2017-04-05 61 views
0
import numpy as np 

def softmax(x): 
    row_num = x.shape[0] 
    col_num = x.shape[1] 
    for m in row_num: 
     for n in col_num: 
      new_x[m,n] = np.exp(x[m,n])/sum(x[:,n]) 

    return new_x 

logits = [1.0, 2.0, 3.0] 
logits2 = np.array([ 
    [1, 2, 3, 6], 
    [2, 4, 5, 6], 
    [3, 8, 7, 6]]) 

print(softmax(logits1)) 
print(softmax(logits2)) 

以上为SOFTMAX函数(它是用来开启logits到概率)的Python:定义SOFTMAX功能

欲获得如下所示的解决方案:

[ 0.09003057 0.24472847 0.66524096] 

[ 
    [ 0.09003057 0.00242826 0.01587624 0.33333333] 
    [ 0.24472847 0.01794253 0.11731043 0.33333333] 
    [ 0.66524096 0.97962921 0.86681333 0.33333333] 
] 

然而,错误显示“'int'对象不可迭代”。另外,我希望看到一个更加高效的代码,这个函数的复杂度较低。

回答

2

这将做的工作:

logits = np.array([1.0, 2.0, 3.0]) 
logits2 = np.array([ 
    [1, 2, 3, 6], 
    [2, 4, 5, 6], 
    [3, 8, 7, 6]]) 
def softmax(x): 
    r=np.exp(x - np.max(x)) 
    return r/r.sum(axis=0) 

你得到错误

“ '廉政' 对象不是可迭代”

因为row_num(以及类似col_num)是一个数字,所以你不能迭代它。您需要添加range(即,for m in range(row_num))。

还有其他问题。例如,x.shape[1]未必定义(它没有为logits定义),所以它也会引发错误。 new_x也没有定义。

+0

感谢您的解决方案。但是当我运行你的代码时,它显示“'list'对象没有属性'形状'” – FortranFun

+1

@FortranFun在我的解决方案中,我没有使用形状,所以我猜你在添加范围后运行你的解决方案。这种情况下的问题是logits是一维向量,因此logits.shape是一个带有一个数字的元组,因此您无法访问logits.shape [1]。 \t 此外,写logits = np.array([1.0,2.0,3.0])(你的logits不是numpy数组,而logits2是,你需要使它成为一个numpy数组,以便它具有shape属性)。 –

1

最有效的代码应该是:

import numpy as np 
def softmax(x): 
    return np.exp(x)/np.sum(np.exp(x), axis=0) 
+1

如果x的数目很大,例如x = [100,100,1000],则可能有问题。即使正确的答案实际上是数组([0.,0.,1]),你的代码将返回数组([0.,0.,nan])。 –

1

在一般情况下,最好是用一个量化的实现,而不是依靠循环。你可以利用numpy的broadcasting来做到这一点。还有一些其他问题具有这种功能的正确实施(例如:here,here)。

为了将答案与问题联系起来,我将粘贴我的通用softmax函数,该函数在任意轴上运行,包括一个棘手的最大减法位。我还写了一个关于它的更详细的blog post

def softmax(X, theta = 1.0, axis = None): 
    """ 
    Compute the softmax of each element along an axis of X. 

    Parameters 
    ---------- 
    X: ND-Array. Probably should be floats. 
    theta (optional): float parameter, used as a multiplier 
     prior to exponentiation. Default = 1.0 
    axis (optional): axis to compute values along. Default is the 
     first non-singleton axis. 

    Returns an array the same size as X. The result will sum to 1 
    along the specified axis. 
    """ 

    # make X at least 2d 
    y = np.atleast_2d(X) 

    # find axis 
    if axis is None: 
     axis = next(j[0] for j in enumerate(y.shape) if j[1] > 1) 

    # multiply y against the theta parameter, 
    y = y * float(theta) 

    # subtract the max for numerical stability 
    y = y - np.expand_dims(np.max(y, axis = axis), axis) 

    # exponentiate y 
    y = np.exp(y) 

    # take the sum along the specified axis 
    ax_sum = np.expand_dims(np.sum(y, axis = axis), axis) 

    # finally: divide elementwise 
    p = y/ax_sum 

    # flatten if X was 1D 
    if len(X.shape) == 1: p = p.flatten() 

    return p