首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用于神经网络的softmax激活函数的实现

用于神经网络的softmax激活函数的实现
EN

Stack Overflow用户
提问于 2012-03-28 19:01:28
回答 2查看 14.8K关注 0票数 20

我在神经网络的最后一层使用Softmax激活函数。但是我对这个函数的安全实现有问题。

一个简单的实现是这样的:

代码语言:javascript
复制
Vector y = mlp(x); // output of the neural network without softmax activation function
for(int f = 0; f < y.rows(); f++)
  y(f) = exp(y(f));
y /= y.sum();

这对于> 100个隐藏节点不能很好地工作,因为在许多情况下y将为NaN (如果y(f) > 709,则exp(y(f))将返回inf)。我想出了这个版本:

代码语言:javascript
复制
Vector y = mlp(x); // output of the neural network without softmax activation function
for(int f = 0; f < y.rows(); f++)
  y(f) = safeExp(y(f), y.rows());
y /= y.sum();

其中safeExp定义为

代码语言:javascript
复制
double safeExp(double x, int div)
{
  static const double maxX = std::log(std::numeric_limits<double>::max());
  const double max = maxX / (double) div;
  if(x > max)
    x = max;
  return std::exp(x);
}

此函数限制exp的输入。在大多数情况下,这是有效的,但不是在所有情况下,我没有真正设法找出它在哪些情况下不起作用。当我在前一层中有800个隐藏的神经元时,它根本不起作用。

然而,即使这起作用了,我还是以某种方式“扭曲”了ANN的结果。你还能想出其他方法来计算正确的解吗?有没有什么C++库或技巧可以用来计算这个ANN的确切输出?

edit:由Itamar Katz提供的解决方案是:

代码语言:javascript
复制
Vector y = mlp(x); // output of the neural network without softmax activation function
double ymax = maximal component of y
for(int f = 0; f < y.rows(); f++)
  y(f) = exp(y(f) - ymax);
y /= y.sum();

它在数学上确实是一样的。然而,在实践中,由于浮点精度的原因,一些较小的值会变为0。我想知道为什么从来没有人在教科书中写下这些实现细节。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-28 19:49:32

首先使用对数刻度,即计算log(y)而不是y。分子的对数是微不足道的。为了计算分母的对数,您可以使用以下“技巧”:http://lingpipe-blog.com/2009/06/25/log-sum-of-exponentials/

票数 14
EN

Stack Overflow用户

发布于 2015-03-23 10:54:35

我知道已经有人回答了,但我还是会在这里一步一步地写出来。

记入日志:

代码语言:javascript
复制
zj = wj . x + bj
oj = exp(zj)/sum_i{ exp(zi) }
log oj = zj - log sum_i{ exp(zi) }

设m是对数和{ zi },使用max_i -sum-exp技巧:

代码语言:javascript
复制
log oj = zj - log {sum_i { exp(zi + m - m)}}
   = zj - log {sum_i { exp(m) exp(zi - m) }},
   = zj - log {exp(m) sum_i {exp(zi - m)}}
   = zj - m - log {sum_i { exp(zi - m)}}

如果m比其他z_i大得多,术语exp(zi-m)可能会出现下溢,但这是可以的,因为这意味着z_i在归一化后与softmax输出无关。最终结果为:

代码语言:javascript
复制
oj = exp (zj - m - log{sum_i{exp(zi-m)}})
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9906136

复制
相关文章

相似问题

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