在回顾神经网络中使用的 Sigmoid 函数时,我们从 https://en.wikipedia.org/wiki/Softmax_function#Softmax_Normalization 中找到了这个等式。 :
与标准sigmoid方程的区别:
上面的第一个方程以某种方式涉及均值和标准差(我希望我没有读错符号),而第二个方程概括了负均值并除以标准差作为常数,因为它在所有项中都是相同的在向量/矩阵/张量中。
因此,在执行方程式时,我得到了不同的结果。
使用第二个方程(标准 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/