不同的Sigmoid方程及其实现

时间:2016-04-27 22:32:57

标签: 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 

[OUT]:

(0.2689414213699951, 0.5, 0.7310585786300049)

可能它与第一个等式包含某种softmax归一化的事实有关,但如果它是通用的softmax那么元素需要总和为1:

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

[OUT]:

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

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

  • 我是否错误地实现了等式1的功能?
  • 维基百科页面上的等式1是错误的吗?或者它指的是其他东西而不是sigmoid / logistic函数?
  • 为什么第一个和第二个等式存在差异?

2 个答案:

答案 0 :(得分:5)

您已正确实施方程式。你的问题是你混淆了softmax和sigmoid函数的定义。

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

对于你的例子:

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

它只是一个逻辑函数的推广,附加“约束”来获取区间(0,1)中向量的每个元素,并将其总和为1.0。

sigmoid函数是逻辑函数的另一个特例。它只是一个具有钟形的实值,可微分的功能。它对于神经网络来说很有意思,因为它很容易计算,非线性并具有负边界和正边界,所以你的激活不会发散,但如果它“太高”就会陷入饱和状态。

但是,sigmoid函数不能确保输入向量总和达到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(规范化的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,并且能够区分哪个类是您输入的正确猜测。

答案 1 :(得分:2)

在这种情况下,你必须区分三件事:一个sigmoid函数,一个带softmax归一化的sigmoid函数和softmax函数。

  1. Sigmoid函数是一个实值函数,由等式f(x) = 1 / (1 + exp(-x))给出。多年来,它被用于机器学习领域,因为它将实际输入压缩到(0,1)间隔,这可能被解释为例如概率值。现在 - 许多专家建议不要使用它,因为它的饱和度和非零均值问题。你可以阅读它(只要如何处理问题,例如http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf)。
  2. 使用具有softmax归一化的S形模型来处理在使用S形函数期间可能发生的两个重要问题。首先是处理异常值(它将你的x压扁到0并使其sd = 1规范化你的数据)和第二个(我认为更重要的是)使不同的变量在进一步分析中同等重要。要理解这种现象,请假设您有两个变量ageincome,其中age从20到70不等,收入从2000到60000不等。如果没有规范化数据,两个变量都会被压扁通过sigmoid转换几乎一个。此外 - 由于更大的平均绝对值 - income变量对于没有任何合理解释的分析将更为重要。
  3. 我认为标准化在理解softmax标准化方面比处理异常值更为重要。要理解为什么想象一个变量在99%的情况下等于0而在其他情况下等于1。在这种情况下,您的sd ~ 0.01mean ~ 0和softmax规范化将会更加突出1
  4. 完全不同的是softmax功能。 softmax函数是从R^kR^k的数学变换,它将实值向量压缩到相同大小的正值向量,总和达1。它由等式softmax(v) = exp(v)/sum(exp(v))给出。它与softmax标准化完全不同,它通常用于多类分类。