alv*_*vas 7 python math neural-network logistic-regression softmax
在通过神经网络中使用的Sigmoid函数进行检查时,我们从https://en.wikipedia.org/wiki/Softmax_function#Softmax_Normalization中找到了这个等式:
与标准sigmoid方程不同:
第一个方程在某种程度上涉及平均值和标准差(我希望我没有错误地读取符号)而第二个方程推广了负均值并除以标准差作为常数,因为它在向量中的所有项中都是相同的/基质/张量.
所以在实现方程时,我会得到不同的结果.
用第2个方程(标准sigmoid函数):
def sigmoid(x):
return 1. / (1 + np.exp(-x))
Run Code Online (Sandbox Code Playgroud)
我得到这些输出:
>>> x = np.array([1,2,3])
>>> print sigmoid(x)
[ 0.73105858 0.88079708 0.95257413]
Run Code Online (Sandbox Code Playgroud)
我希望第一个函数是相似的,但第一个和第二个元素之间的差距相当大(尽管元素的排名依然存在:
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
Run Code Online (Sandbox Code Playgroud)
[OUT]:
(0.2689414213699951, 0.5, 0.7310585786300049)
Run Code Online (Sandbox Code Playgroud)
可能它与第一个等式包含某种softmax归一化这一事实有关,但如果它是通用softmax那么元素需要总和为1:
def softmax(x):
exp_x = np.exp(x)
return exp_x / exp_x.sum()
Run Code Online (Sandbox Code Playgroud)
[OUT]:
>>> x = np.array([1,2,3])
>>> print softmax(x)
[ 0.09003057 0.24472847 0.66524096]
Run Code Online (Sandbox Code Playgroud)
但是第一个方程的输出并不总和为1,它与标准的S形方程不相似/相同.所以问题是:
您已正确实施方程式.你的问题是你正在混合softmax和sigmoid函数的定义.
softmax函数是一种通过使异常值"不那么有趣"来规范化数据的方法.此外,它以一种确保向量之和为1的方式"压缩"输入向量.
对于你的例子:
> np.sum([ 0.09003057, 0.24472847, 0.66524096])
> 1.0
Run Code Online (Sandbox Code Playgroud)
它只是一个逻辑函数的推广,带有附加的"约束",以便在区间(0,1)中获得向量的每个元素,并将其总和为1.0.
该乙状结肠功能是物流功能的另一个特殊情况.它只是一个具有钟形的实值,可微分的功能.它对神经网络很有意思,因为它很容易计算,非线性并具有负边界和正边界,所以你的激活不会发散,但如果它"太高"就会陷入饱和状态.
但是,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))
Run Code Online (Sandbox Code Playgroud)
和标准化版本(只需很少的步骤,使其更容易阅读):
def sn(x):
numerator = x - np.mean(x)
denominator = np.std(x)
fraction = numerator / denominator
return 1.0 / (1.0 + np.exp(-fraction))
Run Code Online (Sandbox Code Playgroud)
现在我们定义一些具有巨大异常值的测量值:
measure = np.array([0.01, 0.2, 0.5, 0.6, 0.7, 1.0, 2.5, 5.0, 50.0, 5000.0])
Run Code Online (Sandbox Code Playgroud)
现在我们来看看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 ])
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,s只能通过逻辑函数"逐个"转换值,因此异常值完全用0.999,1.0,1.0进行平衡.其他值之间的距离会有所不同.
当我们看到时,sn我们看到该函数实际上正常化了我们的值.现在一切都非常相同,除了0.95,这是5000.0.
这有什么好处或如何解释这个?
想想神经网络中的输出层:在输出层上的一个类中激活5000.0(与我们的其他小值相比)意味着网络确实知道这是给定输入的"正确"类.如果您在那里使用过s,最终会得到0.99,1.0和1.0,并且无法区分哪个类是您输入的正确猜测.
| 归档时间: |
|
| 查看次数: |
995 次 |
| 最近记录: |