【问题标题】:Modelling a probability distribution as a fuzzy set in Python3在 Python3 中将概率分布建模为模糊集
【发布时间】:2017-07-26 17:45:18
【问题描述】:

我正在尝试使用python3 从一系列示例值构建一个模糊集

例如,给定[6, 7, 8, 9, 27],我想获得一个函数:

  • 从 0 到 5ca 返回 0.0
  • 从 5ca 逐渐上升到 1.0 到 6,
  • 6点到9点入住1.0
  • 从 9 到 10ca 逐渐下降到 0.0
  • 从10ca到26ca住在0.0
  • 从 26ca 到 27 逐渐上升到 1.0
  • 从 27 到 28ca 逐渐下降到 0.0
  • 从 28ca 及之后返回 0.0

请注意,y 的值始终在 [0.0, 1.0] 范围内,如果系列缺少值,则该值的 y 为 0.0。

请考虑,在最一般的情况下,输入值可能类似于 [9, 41, 20, 13 ,11, 12, 14, 40, 4, 4, 4, 3, 34, 22](值始终可以排序,但请注意,在本系列中,值 4 重复了 3 次,因此我希望概率为 1,所有其他值的概率值较低——在这种情况下不一定是 1/3。

这张图片的顶部显示了绘制到x=16(手绘)的所需函数。我很乐意得到这样的东西。 图片的底部显示了一些额外的功能,这些功能很不错,但不是严格强制的:

  • 比我的图 (A) 中显示的平滑效果更好,
  • 累积效应 (B) 前提是...
  • 函数永远不会超过 1 (C) 并且...
  • 函数永远不会低于 0 (D)。

例如,我尝试了一些改编自 polyfitbeziergaussothers 的方法,但结果并不如我所愿。 我也尝试过使用包fuzzpy,但我无法使其工作,因为它依赖于epydoc,这似乎与python3 不兼容。 StatModels 也没有运气。

谁能建议如何实现所需的功能?提前致谢。

如果您想知道,我计划使用结果函数来预测给定值的可能性;对于上述模糊集,例如,4.0 返回 0.0,6.5 返回 1.0,5.8 类似于 0.85。也许还有另一种更简单的方法可以做到这一点?


这就是我通常处理输入值的方式(不确定是否需要添加0s 的部分),我有什么显示而不是??? 来计算所需的f

def prepare(values, normalize=True):
    max = 0
    table = {}
    for value in values:
        table[value] = (table[value] if value in table else 0) + 1
        if normalize and table[value] > max:
            max = table[value]

    if normalize:
        for value in table:
           table[value] /= float(max)

    for value in range(sorted(table)[-1] + 2):
        if value not in table:
            table[value] = 0

    x = sorted(table)
    y = [table[value] for value in x]
    return x, y

if __name__ == '__main__':
    # get x and y vectors
    x, y = prepare([9, 41, 20, 13, 11, 12, 14, 40, 4, 4, 4, 3, 34, 22], normalize=True)

    # calculate fitting function
    f = ???

    # calculate new x's and y's
    x_new = np.linspace(x[0], x[-1], 50)
    y_new = f(x_new)

    # plot the results
    plt.plot(x, y, 'o', x_new, y_new)
    plt.xlim([x[0] - 1, x[-1] + 1])
    plt.show()

    print("Done.")

一个实际的例子,只是为了澄清这样做的动机...... 这一系列值可能是人们放弃在售货亭前排队的分钟数......使用这样的模型,我们可以通过知道等待多长时间来尝试预测某人离开队列的可能性.然后可以对以这种方式读取的值进行模糊化处理,例如,happily waiting [0.00, 0.33]、just waiting (0.33, 0.66] 和 about to leave (0.66, 1.00]。如果是 about to leave,有人可以通过某些东西(和广告?)来说服他留下来。

【问题讨论】:

  • “ca”是什么意思?我不清楚您正在寻找的功能应该为您的 [9, 41, 20, 13 ,11, 12, 14, 40, 4, 4, 4, 3, 34, 22] 示例输出什么。你能澄清一下吗?
  • ca 表示大约(接近给定值)
  • 函数的输出对于 [9, 41, 20, 13 ,11, 12, 14, 40, 4, 4, 4, 3, 34, 22] 应该是什么?
  • 较长示例的函数将是从 0 到 2 或更多的 0.0,然后从 2 或更多到 3 上升到 1.0,在 3 和 4 之间下降到 1/3,然后转到 0.0 并保持在 0.0 直到 9 点之前,等等(如果我可以轻松绘制结果函数,我会包含图片......对此感到抱歉)。
  • 3和4之间是1/3的原因是什么?

标签: python python-3.x numpy fuzzy-logic probability-distribution


【解决方案1】:

这仅对一组整数有效(由于np.bincount)。

def fuzzy_interp(x, vals):
    vmn, vmx = np.amin(vals), np.amax(vals)
    v = vals - vmn + 1
    b = np.bincount(v, minlength = vmx - vmn + 2)
    b = b / np.amax(b)
    return np.interp(x - vmn - 1, np.arange(b.size), b, left = 0, right = 0)

【讨论】:

  • 感谢您的回答!刚刚尝试了您的解决方案...我认为第 3 行中的 vmin 应该替换为 vmn 但无论如何结果似乎右移了 1...
【解决方案2】:
def pulse(x):
    return np.maximum(0, 1 - abs(x))

def fuzzy_in_unscaled(x, xs):
    return pulse(np.subtract.outer(x, xs)).sum(axis=-1)

def fuzzy_in(x, xs):
    largest = fuzzy_in_unscaled(xs, xs).max()
    return fuzzy_in_unscaled(x, xs) / largest
>>> fuzzy_in(1.5, [1, 3, 4, 5])  # single membership
0.5
>>> fuzzy_in([[1.5, 3], [3.5, 10]], [1, 3, 4, 5])  # vectorized in the first argument
array([[0.5, 1], [1, 0]])

这利用了峰值必须位于元素上的事实。这不适用于所有 pulse 函数。

你最好预先计算 largest,因为它是 O(N^2)

【讨论】:

  • 感谢您的回答!只是为了确保我做对了:xs 是我的一系列值,x 是我想要测试的值?什么是最大的?最大的 x 还是最大的 y?可以加一点主线吗? TIA!
  • xs 确实是要查找成员资格的一组值。这是在 x 中向量化的,因此您可以一次测试整个数组的成员资格。最大的是使结果不超过 1 所需的任意比例因子
  • x, y = prepare([9, 41, 20, 13, 11, 12, 14, 40, 4, 4, 4, 3, 34, 22], normalize=True) 返回所有x 和各自的 y 已经归一化为 1。因此不再需要除以最大吗?仍然不知道如何调用你的函数。在我的问题中查看更新的 sn-p...
  • 有没有办法让脉搏的底变大?再次感谢!
  • np.maximum(0, 1 - abs(x / 2)) 会这样做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-04
  • 1970-01-01
  • 2015-03-31
  • 1970-01-01
  • 1970-01-01
  • 2019-06-07
相关资源
最近更新 更多