2016-11-04 2 views
0

У меня есть список строковых элементов любой длины, мне нужно «нормализовать» этот список, чтобы каждый элемент был частью обычного распределения, добавляя вес к строке.взвешивание плоского списка до нормального распределения

Что является более эффективным и математическим/статистическим способом для этого, кроме того, что у меня ниже?

func normalizeAppend(in []string, shuffle bool) []string { 
    var ret []string 

    if shuffle { 
     shuffleStrings(in) 
    } 

    l := len(in) 
    switch { 
    case remain(l, 3) == 0: 
     l3 := (l/3) 
     var low, mid, high []string 
     for i, v := range in { 
      o := i + 1 
      switch { 
      case o <= l3: 
       low = append(low, v) 
      case o > l3 && o <= l3*2: 
       mid = append(mid, v) 
      case o >= l3*2: 
       high = append(high, v) 
      } 
     } 

     q1 := 1600/len(low) 
     q2 := 6800/len(mid) 
     q3 := 1600/len(high) 

     for _, v := range low { 
      ret = append(ret, fmt.Sprintf("%s_%d", v, q1)) 
     } 

     for _, v := range mid { 
      ret = append(ret, fmt.Sprintf("%s_%d", v, q2)) 
     } 

     for _, v := range high { 
      ret = append(ret, fmt.Sprintf("%s_%d", v, q3)) 
     } 
    case remain(l, 2) == 0 && l >= 4: 
     l4 := (l/4) 
     var first, second, third, fourth []string 
     for i, v := range in { 
      o := i + 1 
      switch { 
      case o <= l4: 
       first = append(first, v) 
      case o > l4 && o <= l4*2: 
       second = append(second, v) 
      case o > l4*2 && o <= l4*3: 
       third = append(third, v) 
      case o > l4*3: 
       fourth = append(fourth, v) 
      } 
     } 
     q1 := 1600/len(first) 
     q2 := 3400/len(second) 
     q3 := 3400/len(third) 
     q4 := 1600/len(fourth) 

     for _, v := range first { 
      ret = append(ret, fmt.Sprintf("%s_%d", v, q1)) 
     } 

     for _, v := range second { 
      ret = append(ret, fmt.Sprintf("%s_%d", v, q2)) 
     } 

     for _, v := range third { 
      ret = append(ret, fmt.Sprintf("%s_%d", v, q3)) 
     } 

     for _, v := range fourth { 
      ret = append(ret, fmt.Sprintf("%s_%d", v, q4)) 
     } 
    default: 
     var first, second, third []string 
     q1 := (1 + math.Floor(float64(l)*.16)) 
     q3 := (float64(l) - math.Floor(float64(l)*.16)) 
     var o float64 
     for i, v := range in { 
      o = float64(i + 1) 
      switch { 
      case o <= q1: 
       first = append(first, v) 
      case o > q1 && o < q3: 
       second = append(second, v) 
      case o >= q3: 
       third = append(third, v) 
      } 
     } 
     lq1 := 1600/len(first) 
     lq2 := 3400/len(second) 
     lq3 := 1600/len(third) 
     for _, v := range first { 
      ret = append(ret, fmt.Sprintf("%s_%d", v, lq1)) 
     } 

     for _, v := range second { 
      ret = append(ret, fmt.Sprintf("%s_%d", v, lq2)) 
     } 

     for _, v := range third { 
      ret = append(ret, fmt.Sprintf("%s_%d", v, lq3)) 
     } 

    } 

    return ret 
} 

Некоторые просили уточнение:

У меня есть список элементов, которые будут выбраны из списка во много раз по одному с помощью взвешенного выбора, чтобы начать с У меня есть список с (подразумеваемые) весов 1:

[a_1, b_1, c_1, d_1, e_1, f_1, g_1, h_1, i_1, j_1, k_1]

Я ищу лучший способ, чтобы сделать этот список в нечто производящего более «нормальное» распределение взвешивания для выбора:

[a_1, b_2, C_3, d_5, e_14, F_30, g_14, h_5, i_3, j_2, k_1]

или, возможно, это, скорее всего, мне нужно изменить свои методы к чему-то более заземленной статистически. Итог: я хочу контролировать выбор из списка элементов разными способами, один из которых здесь гарантирует, что элементы возвращаются способом, приближающимся к нормальной кривой.

+0

Я не понимаю ваших требований. Не могли бы вы уточнить? Что означает, что элемент является частью нормального распределения? Добавляя вес, вы имеете в виду простую конкатенацию строк? Возможно, вы можете опубликовать пример. –

+0

Код не так важен, как вопрос и понятия, это всего лишь дерьмо, которое первым ударит по концепции во что-то еще, над чем я работаю. – blueblank

+0

Речь идет только о вычислении весов (затем используйте стандартную формулу распределения с соответствующим средним значением и дисперсией) или о выборке из этого распределения (затем используйте случайный генератор для нормальных распределений)? –

ответ

0

Если вы просто хотите, чтобы вычислить веса для данного списка, то вам понадобятся следующие вещи:

  • среднего значения нормального распределения
  • Дисперсии нормального распределения
  • discretizer для значений

Первый из них довольно прост. Вы хотите, чтобы среднее значение находилось в центре списка. Поэтому (предполагая, что индексация с нуля):

mean = (list.size - 1)/2 

Второй вид произвольно и зависит от того, насколько крут вы хотите, чтобы ваши веса, чтобы упасть. Масса нормального распределения практически равна нулю за пределами 3 * standard_deviation от mean. Таким образом, хорошее стандартное отклонение в большинстве случаев, вероятно, что-то между четвертым и шестой длиной списка:

standard_deviation = (1/4 .. 1/6) * list.size 
variance = standard_deviation^2 

Предполагая, что вы хотите, целые веса, вам нужно Дискретизируют веса от нормального распределения. Самый простой способ сделать это - указать максимальный вес (элемента в среднем положении).

Все. Вес для элемента в позиции i:

weight[i] = round(max_weight * exp(-(i - mean)^2/(2 * variance))) 
Смежные вопросы