首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >softmax python计算

softmax python计算
EN

Stack Overflow用户
提问于 2017-10-25 01:20:39
回答 3查看 2.2K关注 0票数 2

我刚接触机器学习和学习如何在python中实现softmax,我遵循了下面的主题。

Softmax function - python

我在做一些分析,如果我们有一个数组

代码语言:javascript
复制
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分享:

代码语言:javascript
复制
np.exp(z) / np.sum(np.exp(z), axis=1, keepdims=True)

2)在初始问题中提出:

代码语言:javascript
复制
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum() 

在这两种情况下,我都得到了错误(值超出界限),所以我使用了规范化并尝试运行它

代码语言:javascript
复制
x= np.mean(batch1)
y = np.std(batch1)
e_x = np.exp((batch1 - x)/y)
j = e_x / e_x.sum(axis = 0)

所以我的问题是,这是我可以实现的方式吗?如果不是,我如何处理上述情况?

提前感谢

EN

回答 3

Stack Overflow用户

发布于 2017-10-25 01:42:12

2)中的方法在数值上是相当稳定的。最有可能的情况是,错误是从其他行产生的。请参阅以下示例(所有示例都可以正常工作):

代码语言:javascript
复制
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,这会压缩概率。例如:

代码语言:javascript
复制
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)

输出为:

代码语言:javascript
复制
[ 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。

票数 2
EN

Stack Overflow用户

发布于 2017-10-25 01:43:53

np.exp(1000)这个数字实在太大了。请尝试使用Decimal库。

票数 0
EN

Stack Overflow用户

发布于 2017-10-25 01:59:55

这里有一个简单的例子:两个小整数,10和20。

代码语言:javascript
复制
>>> 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

结果是完全不同的,令人无法接受。应用批处理规范不起作用。再看看你的方程式:

代码语言:javascript
复制
j = e_x / e_x.sum(axis = 0)

..。并将其应用于这些简单的值:

代码语言:javascript
复制
j = math.exp(10) / (math.exp(10) + math.exp(20))

分析和建议的解决方案

您可以应用什么转换来保留j#的值?

您的实际数据集遇到的问题是,您试图表示e^5000的值范围,而不管您在指数值中进行了什么移位。您愿意将所有非常非常小的值都设置为0吗?如果是这样的话,你可以通过从每个指数中减去一个常量来构建一个有效的算法,直到所有指数都是300或更少。这将给你留下数学上类似于原始结果的结果。

你能自己处理这些代码吗?找出数组的最大值;如果大于300,就找出差值,diff。从每个数组元素中减去diff。然后执行您惯常的softmax。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46916446

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档