从Udacity的深度学习课程中,y_i的softmax仅仅是指数除以整个Y向量的指数之和:

其中S(y_i)是y_i的软最大函数e是指数函数j是no。输入向量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的差值,然后除以和。

有人能用数学方法解释一下吗?一个是对的,另一个是错的?

实现在代码和时间复杂度方面是否相似?哪个更有效率?


当前回答

这将泛化并假设您正在规范化尾随维度。

def softmax(x: np.ndarray) -> np.ndarray:
    e_x = np.exp(x - np.max(x, axis=-1)[..., None])
    e_y = e_x.sum(axis=-1)[..., None]
    return e_x / e_y

其他回答

为了保持数值的稳定性,应减去max(x)。下面是softmax函数的代码;

def softmax (x):

if len(x.shape) > 1:
    tmp = np.max(x, axis = 1)
    x -= tmp.reshape((x.shape[0], 1))
    x = np.exp(x)
    tmp = np.sum(x, axis = 1)
    x /= tmp.reshape((x.shape[0], 1))
else:
    tmp = np.max(x)
    x -= tmp
    x = np.exp(x)
    tmp = np.sum(x)
    x /= tmp


return x

目标是使用Numpy和Tensorflow实现类似的结果。与原始答案的唯一变化是np的轴参数。和api。

初始方法:axis=0 -然而,当维度为N时,这并不能提供预期的结果。

修改方法:axis=len(e_x.shape)-1 -总是在最后一个维度上求和。这提供了与tensorflow的softmax函数类似的结果。

def softmax_fn(input_array):
    """
    | **@author**: Prathyush SP
    |
    | Calculate Softmax for a given array
    :param input_array: Input Array
    :return: Softmax Score
    """
    e_x = np.exp(input_array - np.max(input_array))
    return e_x / e_x.sum(axis=len(e_x.shape)-1)

我想补充一点对这个问题的理解。这里减去数组的最大值是正确的。但如果你运行另一篇文章中的代码,你会发现当数组是2D或更高维度时,它不会给你正确的答案。

在这里我给你一些建议:

为了得到max,试着沿着x轴做,你会得到一个1D数组。 重塑你的最大数组原始形状。 np。Exp得到指数值。 np。沿轴求和。 得到最终结果。

根据结果,你将通过做矢量化得到正确的答案。因为和大学作业有关,所以我不能把具体的代码贴在这里,如果你不明白我可以多给你一些建议。

Sklearn还提供了softmax的实现

from sklearn.utils.extmath import softmax
import numpy as np

x = np.array([[ 0.50839931,  0.49767588,  0.51260159]])
softmax(x)

# output
array([[ 0.3340521 ,  0.33048906,  0.33545884]]) 

The purpose of the softmax function is to preserve the ratio of the vectors as opposed to squashing the end-points with a sigmoid as the values saturate (i.e. tend to +/- 1 (tanh) or from 0 to 1 (logistical)). This is because it preserves more information about the rate of change at the end-points and thus is more applicable to neural nets with 1-of-N Output Encoding (i.e. if we squashed the end-points it would be harder to differentiate the 1-of-N output class because we can't tell which one is the "biggest" or "smallest" because they got squished.); also it makes the total output sum to 1, and the clear winner will be closer to 1 while other numbers that are close to each other will sum to 1/p, where p is the number of output neurons with similar values.

从向量中减去最大值的目的是,当你计算e^y指数时,你可能会得到非常高的值,将浮点数夹在最大值处,导致平局,但在这个例子中不是这样。如果你减去最大值得到一个负数,那么就会出现一个大问题,然后你就会得到一个负指数,它会迅速缩小数值,改变比率,这就是在海报上的问题中发生的情况,并得到错误的答案。

Udacity提供的答案效率低得可怕。我们需要做的第一件事是计算所有向量分量的e^y_j, KEEP这些值,然后求和,然后除。Udacity搞砸的地方是他们计算了两次e^y_j !!正确答案如下:

def softmax(y):
    e_to_the_y_j = np.exp(y)
    return e_to_the_y_j / np.sum(e_to_the_y_j, axis=0)