【问题标题】:weighting a flat list to the normal distribution将平面列表加权到正态分布
【发布时间】:2016-11-04 19:50:59
【问题描述】:

我有任意长度的字符串项目列表,我需要“规范化”这个列表,以便每个项目都是正态分布的一部分,将权重附加到字符串。

除了我下面的方法之外,还有什么更有效和数学/统计方法来解决这个问题?

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]

或者我可能需要将我的方法更改为更基于统计的方法。底线是我想以多种方式控制从项目列表中的选择,其中之一是确保以接近正态曲线的方式返回项目。

【问题讨论】:

  • 我不明白你的要求。你能澄清一下吗?一个元素成为正态分布的一部分意味着什么?通过附加权重,您的意思是简单的字符串连接吗?也许你可以发布一个例子。
  • 代码不如问题和概念重要,这只是我正在研究的其他东西中对概念的一次废话。
  • 只是计算权重(然后使用具有适当均值和方差的正态分布公式)还是从该分布中采样(然后使用随机生成器进行正态分布)?
  • 主要是计算权重。

标签: algorithm go statistics normal-distribution


【解决方案1】:

如果您只想计算给定列表的权重,那么您需要以下内容:

  • 正态分布的平均值
  • 正态分布的方差
  • 值的离散化器

第一个很简单。您希望均值位于列表的中心。因此(假设从零开始的索引):

mean = (list.size - 1) / 2

第二个是任意的,取决于你希望你的重量下降多陡。从mean3 * standard_deviation 的距离之外,正态分布的权重实际上为零。因此,在大多数情况下,一个好的标准差可能在第四到第六个列表长度之间:

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

假设您需要整数权重,您需要从正态分布中离散化权重。最简单的方法是指定(平均位置的元素的)最大权重。

就是这样。位置i 的元素的权重为:

weight[i] = round(max_weight * exp(-(i - mean)^2 / (2 * variance)))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-06
    • 2018-08-20
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 2021-01-28
    • 1970-01-01
    • 2014-01-30
    相关资源
    最近更新 更多