python - 不同的Sigmoid方程及其实现

标签 python math neural-network logistic-regression softmax

在回顾神经网络中使用的 Sigmoid 函数时,我们从 https://en.wikipedia.org/wiki/Softmax_function#Softmax_Normalization 中找到了这个等式。 :

enter image description here

与标准sigmoid方程的区别:

enter image description here

上面的第一个方程以某种方式涉及均值和标准差(我希望我没有读错符号),而第二个方程概括了负均值并除以标准差作为常数,因为它在所有项中都是相同的在向量/矩阵/张量中。

因此,在执行方程式时,我得到了不同的结果。

使用第二个方程(标准 sigmoid 函数):

def sigmoid(x):
    return 1. / (1 + np.exp(-x))

我得到这些输出:

>>> x = np.array([1,2,3])
>>> print sigmoid(x)
[ 0.73105858  0.88079708  0.95257413]

我原以为第一个函数是相似的,但第一个和第二个元素之间的差距扩大了很多(尽管元素的排名保持不变:

def get_statistics(x):
    n = float(len(x))
    m = x.sum() / n
    s2 = sum((x - m)**2) / (n-1.) 
    s = s2**0.5
    return m, s2, s

m, s, s2 = get_statistics(x)

sigmoid_x1 = 1 / (1 + np.exp(-(x[0] - m) / s2))
sigmoid_x2 = 1 / (1 + np.exp(-(x[1] - m) / s2))
sigmoid_x3 = 1 / (1 + np.exp(-(x[2] - m) / s2))
sigmoid_x1, sigmoid_x2, sigmoid_x3 

[输出]:

(0.2689414213699951, 0.5, 0.7310585786300049)

可能这与第一个方程包含某种 softmax 归一化这一事实有关,但如果它是通用 softmax,则元素需要总和为 1:

def softmax(x):
    exp_x = np.exp(x)
    return exp_x / exp_x.sum()

[输出]:

>>> x = np.array([1,2,3])
>>> print softmax(x)
[ 0.09003057  0.24472847  0.66524096]

但是第一个方程的输出总和不等于 1,它与标准 S 型方程不相似/相同。所以问题是:

  • 我是否错误地实现了等式 1 的函数?
  • 维基百科页面上的等式 1 是否错误?或者它指的是其他东西而不是真正的 sigmoid/logistic 函数?
  • 为什么第一个和第二个方程式不同?

最佳答案

您已经正确地实现了等式。你的问题是你混淆了 softmax 和 sigmoid 函数的定义。

softmax 函数是一种通过使离群值“不那么有趣”来规范化数据的方法。此外,它以确保向量之和为 1 的方式“压缩”您的输入向量。

以你的例子为例:

> np.sum([ 0.09003057,  0.24472847,  0.66524096])
> 1.0

它只是逻辑函数的推广,带有额外的“约束”以获得区间 (0, 1) 中向量的每个元素及其总和为 1.0。

sigmoid 函数是逻辑函数的另一个特例。它只是一个钟形的实值可微函数。这对神经网络来说很有趣,因为它很容易计算,是非线性的,并且有正负边界,所以你的激活不会发散,但如果它变得“太高”就会达到饱和。

但是,S 形函数并不能确保输入向量的总和为 1.0。

在神经网络中,sigmoid 函数经常用作单个神经元的激活函数,而 sigmoid/softmax 归一化函数更适合用于输出层,以确保整个层加起来为 1。你只是混淆了sigmoid 函数(对于单个神经元)与 sigmoid/softmax 归一化函数(对于整个层)。

编辑:为了向您阐明这一点,我将给您一个带有离群值的简单示例,这为您演示了两个不同函数的行为。

让我们实现一个 sigmoid 函数:

import numpy as np

def s(x):
    return 1.0 / (1.0 + np.exp(-x))

以及规范化版本(以小步骤进行,使其更易于阅读):

def sn(x):
    numerator = x - np.mean(x)
    denominator = np.std(x)
    fraction = numerator / denominator

    return 1.0 / (1.0 + np.exp(-fraction))

现在我们定义一些具有巨大异常值的测量值:

measure = np.array([0.01, 0.2, 0.5, 0.6, 0.7, 1.0, 2.5, 5.0, 50.0, 5000.0])

现在我们来看看s(sigmoid)和sn(normalized sigmoid)给出的结果:

> s(measure)
> array([ 0.50249998,  0.549834  ,  0.62245933,  0.64565631,  0.66818777,
    0.73105858,  0.92414182,  0.99330715,  1.        ,  1.        ])

> sn(measure)
> array([ 0.41634425,  0.41637507,  0.41642373,  0.41643996,  0.41645618,
    0.41650485,  0.41674821,  0.41715391,  0.42447515,  0.9525677 ])

如您所见,s 仅通过逻辑函数“逐一”转换值,因此离群值完全饱和为 0.999、1.0、1.0。其他值之间的距离各不相同。

当我们查看 sn 时,我们发现该函数实际上规范了我们的值。现在一切都非常相同,除了 0.95 是 5000.0。

这有什么用或如何解释?

想想神经网络中的输出层:输出层上一个类的激活值为 5000.0(与我们的其他小值相比)意味着网络确实确定这是给定的“正确”类输入。如果您在那里使用 s,您最终会得到 0.99、1.0 和 1.0,并且无法能够区分哪个类是您输入的正确猜测。

关于python - 不同的Sigmoid方程及其实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36902115/

相关文章:

neural-network - 具有正则化数据的 tanh 错误饱和度的神经网络

java - Encog - 如何为神经网络加载训练数据

python - 根据可能的最低行进距离将一组分成两部分

c# - Math.Round 错误 81.725 MidpointRounding.AwayFromZero = 81.72

python - 无法将分形方程转换为 Python 算法

python - Numpy:随机数生成 - 将循环分成 block

machine-learning - 如何识别神经网络中神经元和层的数量

python - 将不同列的不同格式的 pandas DataFrame 写入 Excel

python - 使用 BeautifulSoup 保存网页内容

python - 使用 CfnParameter 时,ID 组件可能不包含未解析的 token : ${Token[TOKEN. 199]}-ec2