2017-04-05 59 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