从Udacity的深度学习类来看,y_i的软最大值只是指数除以整个Y向量的指数之和:
其中< code>S(y_i)是< code>y_i的softmax函数,而< code>e是指数,而< code>j是输入向量y中的列数
我尝试了以下方法:
import numpy as np
def softmax(x):
"""Compute softmax values for each sets of scores in x."""
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum()
scores = [3.0, 1.0, 0.2]
print(softmax(scores))
返回:
[ 0.8360188 0.11314284 0.05083836]
但建议的解决方案是:
def softmax(x):
"""Compute softmax values for each sets of scores in x."""
return np.exp(x) / np.sum(np.exp(x), axis=0)
它产生与第一个实现相同的输出,即使第一个实现显式地取每列和max的差值,然后除以总和。
有人能用数学说明为什么吗?一个正确,另一个错误吗?
在代码和时间复杂性方面,实现是否相似?哪个更有效?
所以,这确实是对逃兵答案的评论,但由于我的声誉,我还不能对此发表评论。正如他所指出的,只有输入包含单个样本时,您的版本才是正确的。如果您的输入包含多个样本,则是错误的。然而,逃兵的解决方案也是错误的。问题是,一旦他接受了一维输入,然后又接受了二维输入。让我给你看看这个。
import numpy as np
# your solution:
def your_softmax(x):
"""Compute softmax values for each sets of scores in x."""
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum()
# desertnaut solution (copied from his answer):
def desertnaut_softmax(x):
"""Compute softmax values for each sets of scores in x."""
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum(axis=0) # only difference
# my (correct) solution:
def softmax(z):
assert len(z.shape) == 2
s = np.max(z, axis=1)
s = s[:, np.newaxis] # necessary step to do broadcasting
e_x = np.exp(z - s)
div = np.sum(e_x, axis=1)
div = div[:, np.newaxis] # dito
return e_x / div
让我们以沙漠为例:
x1 = np.array([[1, 2, 3, 6]]) # notice that we put the data into 2 dimensions(!)
这是输出:
your_softmax(x1)
array([[ 0.00626879, 0.01704033, 0.04632042, 0.93037047]])
desertnaut_softmax(x1)
array([[ 1., 1., 1., 1.]])
softmax(x1)
array([[ 0.00626879, 0.01704033, 0.04632042, 0.93037047]])
您可以看到,在这种情况下,说明版本将失败。(如果输入只是像np.array([1, 2, 3, 6])那样的一维,则不会)。
现在让我们使用 3 个样本,因为这是我们使用 2 维输入的原因。以下 x2 与来自德纳特示例的 x2 不同。
x2 = np.array([[1, 2, 3, 6], # sample 1
[2, 4, 5, 6], # sample 2
[1, 2, 3, 6]]) # sample 1 again(!)
此输入由一个包含 3 个样本的批次组成。但样本一和样本三本质上是相同的。我们现在期望有 3 行 softmax 激活,其中第一行应该与第三行相同,也与 x1 的激活相同!
your_softmax(x2)
array([[ 0.00183535, 0.00498899, 0.01356148, 0.27238963],
[ 0.00498899, 0.03686393, 0.10020655, 0.27238963],
[ 0.00183535, 0.00498899, 0.01356148, 0.27238963]])
desertnaut_softmax(x2)
array([[ 0.21194156, 0.10650698, 0.10650698, 0.33333333],
[ 0.57611688, 0.78698604, 0.78698604, 0.33333333],
[ 0.21194156, 0.10650698, 0.10650698, 0.33333333]])
softmax(x2)
array([[ 0.00626879, 0.01704033, 0.04632042, 0.93037047],
[ 0.01203764, 0.08894682, 0.24178252, 0.65723302],
[ 0.00626879, 0.01704033, 0.04632042, 0.93037047]])
我希望你能看到我的解决方案只是这样。
softmax(x1) == softmax(x2)[0]
array([[ True, True, True, True]], dtype=bool)
softmax(x1) == softmax(x2)[2]
array([[ True, True, True, True]], dtype=bool)
此外,以下是TensorFlows softmax实施的结果:
import tensorflow as tf
import numpy as np
batch = np.asarray([[1,2,3,6],[2,4,5,6],[1,2,3,6]])
x = tf.placeholder(tf.float32, shape=[None, 4])
y = tf.nn.softmax(x)
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(y, feed_dict={x: batch})
结果是:
array([[ 0.00626879, 0.01704033, 0.04632042, 0.93037045],
[ 0.01203764, 0.08894681, 0.24178252, 0.657233 ],
[ 0.00626879, 0.01704033, 0.04632042, 0.93037045]], dtype=float32)
(嗯……这里有很多困惑,无论是问题还是答案……)
首先,这两种解决方案(即你的和建议的解决方案)是不等价的;它们碰巧只在一维分数数组的特殊情况下是等价的。如果你也尝试过Udacity测验中提供的二维分数数组,你会发现这一点。
就结果而言,这两个解决方案之间唯一的实际区别是axis=0
参数。要了解情况,让我们尝试您的解决方案(your_softmax
),其中唯一的区别是axis
参数:
import numpy as np
# your solution:
def your_softmax(x):
"""Compute softmax values for each sets of scores in x."""
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum()
# correct solution:
def softmax(x):
"""Compute softmax values for each sets of scores in x."""
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum(axis=0) # only difference
正如我所说,对于一维分数数组,结果确实是相同的:
scores = [3.0, 1.0, 0.2]
print(your_softmax(scores))
# [ 0.8360188 0.11314284 0.05083836]
print(softmax(scores))
# [ 0.8360188 0.11314284 0.05083836]
your_softmax(scores) == softmax(scores)
# array([ True, True, True], dtype=bool)
尽管如此,以下是Udacity测验中给出的二维分数数组的结果作为测试示例:
scores2D = np.array([[1, 2, 3, 6],
[2, 4, 5, 6],
[3, 8, 7, 6]])
print(your_softmax(scores2D))
# [[ 4.89907947e-04 1.33170787e-03 3.61995731e-03 7.27087861e-02]
# [ 1.33170787e-03 9.84006416e-03 2.67480676e-02 7.27087861e-02]
# [ 3.61995731e-03 5.37249300e-01 1.97642972e-01 7.27087861e-02]]
print(softmax(scores2D))
# [[ 0.09003057 0.00242826 0.01587624 0.33333333]
# [ 0.24472847 0.01794253 0.11731043 0.33333333]
# [ 0.66524096 0.97962921 0.86681333 0.33333333]]
结果是不同的 - 第二个确实与Udacity测验中预期的相同,其中所有列确实总和为1,而第一个(错误)结果并非如此。
因此,所有的麻烦实际上都是为了实现细节——轴
参数。根据numpy的说法。总和文档:
默认值 axis = None 将对输入数组的所有元素求和
而这里我们想按行求和,因此< code>axis=0。对于一维数组,(唯一的)行的总和与所有元素的总和恰好相同,因此在这种情况下会得到相同的结果...
撇开轴
问题不谈,您的实现(即您选择先减去max)实际上比建议的解决方案要好!事实上,这是实现softmax函数的推荐方法——请看这里的理由(数字稳定性,这里的一些其他答案也指出了这一点)。
它们都是正确的,但是从数值稳定性的角度来看,你的更受欢迎。
你从开始
e ^ (x - max(x)) / sum(e^(x - max(x))
通过使用a^(b-c)=(a^b)/(a^c)的事实,我们得到了
= e ^ x / (e ^ max(x) * sum(e ^ x / e ^ max(x)))
= e ^ x / sum(e ^ x)
这就是另一个答案所说的。你可以用任何变量替换max(x),它会抵消掉。
问题内容: 当实现具有多个属性的类时(例如下面的玩具示例),处理哈希的最佳方法是什么? 我认为和应该是一致的,但是如何实现能够处理所有属性的适当的哈希函数呢? 问题答案: 对于相等的对象应返回相同的值。它也不应在对象的整个生命周期内发生变化。通常,您只为不可变的对象实现它。 一个简单的实现就是公正。这始终是正确的,但效果很差。 您的解决方案,返回一个属性元组的哈希,是很好的。但是请注意,您无需列出
我正在学习神经网络,并在python中实现它。我首先定义了一个 softmax 函数,我遵循这个问题给出的解决方案 Softmax 函数 - python。以下是我的代码: 我得到了一个测试代码,看看函数是否正确。是测试数据,
问题内容: 我以前的编程中,代码段仅用于调试目的(记录命令等)。通过使用预处理程序指令,可以完全禁用这些语句以进行生产,如下所示: 做类似的事情的最好方法是什么? 问题答案: 如果只想禁用日志记录方法,请使用该模块。如果日志级别设置为排除调试语句,那么它将非常接近无操作(它仅检查日志级别并返回而不插入日志字符串)。 如果要在特定条件下以字节码编译时实际删除代码块,则唯一的选择是相当神秘的全局变量。
问题内容: 如何实现与C#代码等效的Python? 这是一个好主意吗??请在您的答案中举例说明。 问题答案: 正如其他人在这里提到的: 在Python中不需要接口。这是因为Python具有适当的多重继承,还具有鸭式输入法,这意味着 必须 在Java中具有接口的地方,而不必在Python中具有接口。 也就是说,接口还有多种用途。其中一些被Python 2.6中引入的Pythons抽象基类覆盖。如果您
问题内容: 我想知道Python 3中的新super是如何实现的。 我做了一个小例子之后,这个问题就浮现在脑海中,我得到了一个奇怪的错误。我正在使用Pyutilib组件体系结构(PCA),并且已经制作了自定义元类来驱动另一个类的创建: 我收到以下错误: 我wonderign究竟超(一样),它引发的错误,而所有的,并存在。另外的“老方法”-正在工作。 问题答案: 如何执行?这是python3.3的代
问题内容: 我已经实现了 算法 对于GMM使用这个 后[GMMs]与最大似然优化 努比](https://towardsdatascience.com/how-to-code-gaussian-mixture-models- from-scratch-in-python-9e7975df5252)未成功,如下所示: when I run the algorithm on a 1-D time-se