我是机器学习的新手,学习如何在python中实现softmax,我是按照下面的线程
我正在做一些分析并说我们是否有一个数组
batch = np.asarray([[1000,2000,3000,6000],[2000,4000,5000,6000],[1000,2000,3000,6000]])
batch1 = np.asarray([[1,2,2,6000],[2,5,5,3],[3,5,2,1]])
并尝试通过以下方式实现softmax(如上面链接中所述)
1)由Pab Torre共享:
np.exp(z) / np.sum(np.exp(z), axis=1, keepdims=True)
2)在最初的问题中提问:
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum()
对于这两个我得到错误(值超出范围),所以我使用规范化并尝试运行它
x= np.mean(batch1)
y = np.std(batch1)
e_x = np.exp((batch1 - x)/y)
j = e_x / e_x.sum(axis = 0)
所以我向所有人提出的问题是,这是我实施的方式吗?如果没有,我该如何处理上述情况?
提前致谢
答案 0 :(得分:2)
2)中的方法在数值上非常稳定。最有可能的是,错误是由其他一些行产生的。请参阅这些示例(所有工作都没有错误):
def softmax(x):
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum()
print softmax(np.array([0, 0, 0, 0]))
print softmax(np.array([1000, 2000, 3000, 6000]))
print softmax(np.array([2000, 4000, 5000, 6000]))
print softmax(np.array([1000, 2000, 3000, 6000]))
print softmax(np.array([2000, 2000, 2001, 2000]))
print softmax(np.array([1, 2, 2, 600000]))
print softmax(np.array([1, 2, 2, 60000000]))
print softmax(np.array([1, 2, 2, -60000000]))
您的替代实现使所有值更接近于0,这会压缩概率。例如:
def alternative_softmax(x):
mean = np.mean(x)
std = np.std(x)
norm = (x - mean) / std
e_x = np.exp(norm)
return e_x / e_x.sum(axis=0)
print softmax(np.array([1, 2, 2, 6000]))
print softmax(np.array([2, 5, 5, 3]))
print softmax(np.array([3, 5, 2, 1]))
print
batch = np.asarray([[1, 2, 2, 6000],
[2, 5, 5, 3],
[3, 5, 2, 1]])
print alternative_softmax(batch)
输出结果为:
[ 0. 0. 0. 1.]
[ 0.02278457 0.45764028 0.45764028 0.06193488]
[ 0.11245721 0.83095266 0.0413707 0.01521943]
[[ 0.33313225 0.33293125 0.33313217 0.94909178]
[ 0.33333329 0.33353437 0.33373566 0.02546947]
[ 0.33353446 0.33353437 0.33313217 0.02543875]]
正如您所看到的,输出非常不同,行甚至不等于一。
答案 1 :(得分:0)
np.exp(1000)
太大了。请尝试使用Decimal库。
答案 2 :(得分:0)
这是一个简单的例子:两个小整数,10和20。
>>> a = 10
>>> b = 20
>>> denom = math.exp(a) + math.exp(b)
>>> math.exp(a) / denom
4.5397868702434395e-05
>>> math.exp(b) / denom
0.9999546021312976
>>> # Now, let's perform batch-norm on this ...
>>> a = -1
>>> b = 1
>>> denom = math.exp(a) + math.exp(b)
>>> math.exp(a) / denom
0.11920292202211756
>>> math.exp(b) / denom
0.8807970779778824
结果相当不同,令人无法接受。应用批量规范不起作用。 再看看你的等式:
j = e_x / e_x.sum(axis = 0)
...并将其应用于这些简单的值:
j = math.exp(10) / (math.exp(10) + math.exp(20))
分析和建议的解决方案
您可以应用哪种转换来保留 j 的价值?
您的实际数据集遇到的问题是您尝试表示e ^ 5000的值范围,无论您在指数值中做出什么样的转换。你愿意把所有非常小的值推到0吗?如果是这样,你可以通过从每个指数中减去一个常数来构建一个有效的算法,直到所有的都是300或更少。这将使您的结果在数学上与原始结果类似。
您可以自己处理该代码吗?找到数组的最大值;如果它超过300,找到差异,diff
。从每个数组元素中减去diff
。 然后按惯例做softmax。