7

在回顾神经网络中使用的 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,那么元素需要求和为一个:

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]

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

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

2 回答 2

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(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,并且无法区分哪个类是您输入的正确猜测。

于 2016-04-27T22:54:46.377 回答
2

在这种情况下,您必须区分三件事:sigmoid 函数、具有 softmax 归一化的 sigmoid 函数和 softmax 函数。

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