programing

Python에서 Softmax 함수를 구현하는 방법

copysource 2022. 9. 22. 22:41
반응형

Python에서 Softmax 함수를 구현하는 방법

Udacity의 딥 러닝 클래스에서 y_i의 softmax는 단순히 전체 Y 벡터의 지수 합계로 나눈 값입니다.

여기에 이미지 설명 입력

서 ★★★★★S(y_i)입니다.y_i ★★★★★★★★★★★★★★★★★」e는 지수 및 「」입니다.j의 열.

다음을 시도했습니다.

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)

첫 번째 구현이 각 열과 최대값의 차이를 명시적으로 취하여 합계로 나누더라도 첫 번째 구현과 동일한 출력을 생성합니다.

누가 수학적으로 이유를 보여줄 수 있나요?하나는 맞고 다른 하나는 틀렸나요?

구현은 코드와 시간의 복잡성 측면에서 유사합니까?어느 쪽이 더 효율적이죠?

둘 다 맞지만 숫자 안정성의 관점에서 당신의 것을 선호합니다.

먼저

e ^ (x - max(x)) / sum(e^(x - max(x))

a^(b - c) = (a^b)/(a^c)라는 사실을 이용하여 우리는 다음을 갖는다.

= e ^ x / (e ^ max(x) * sum(e ^ x / e ^ max(x)))

= e ^ x / sum(e ^ x)

다른 대답도 그렇게 돼 있어요max(x)를 임의의 변수로 대체할 수 있습니다.그러면 소거됩니다.

(글쎄요...질문이나 답변에서 많은 혼란을 겪고 있습니다...)

우선, 이 2개의 솔루션(고객의 솔루션과 제안된 솔루션)은 동일하지 않습니다.이러한 솔루션은 1-D 스코어 어레이의 특수한 경우에만 동등합니다.제공된 Udacity 퀴즈의 예에서 2-D 점수 배열을 사용해 봤다면 이 정보를 찾을 수 있었을 것입니다.

두 는 '''가 합니다.axis=0자그러니까여러분도한번해볼까요?your_softmax 점이 , 그 중 입니다.axis★★★★

import numpy as np

# your solution:
def your_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()

# correct solution:
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(axis=0) # only difference

말씀드렸듯이, 1-D 점수 배열의 경우 결과는 실제로 동일합니다.

scores = [3.0, 1.0, 0.2]
print(your_softmax(scores))
# [ 0.8360188   0.11314284  0.05083836]
print(softmax(scores))
# [ 0.8360188   0.11314284  0.05083836]
your_softmax(scores) == softmax(scores)
# array([ True,  True,  True], dtype=bool)

단, 테스트 예시로 Udacity 퀴즈에서 제시된 2-D 점수 배열 결과는 다음과 같습니다.

scores2D = np.array([[1, 2, 3, 6],
                     [2, 4, 5, 6],
                     [3, 8, 7, 6]])

print(your_softmax(scores2D))
# [[  4.89907947e-04   1.33170787e-03   3.61995731e-03   7.27087861e-02]
#  [  1.33170787e-03   9.84006416e-03   2.67480676e-02   7.27087861e-02]
#  [  3.61995731e-03   5.37249300e-01   1.97642972e-01   7.27087861e-02]]

print(softmax(scores2D))
# [[ 0.09003057  0.00242826  0.01587624  0.33333333]
#  [ 0.24472847  0.01794253  0.11731043  0.33333333]
#  [ 0.66524096  0.97962921  0.86681333  0.33333333]]

결과는 다릅니다. 두 번째 결과는 Udacity 퀴즈에서 예상한 것과 동일합니다.여기서 모든 열의 합계는 1이 됩니다.첫 번째(잘못된) 결과는 그렇지 않습니다.

이 세부 사항,즉 구현 사항 때문이었습니다.axis논쟁.숫자에 따르면.합계 문서:

기본 축=없음 입력 배열의 모든 요소를 합합니다.

행 에, 「」를 참조해 주세요.axis=0배열의 ( 그 . 1-D는 같은 것입니다. ( )는 같은 것입니다.

axis문제는 차치하고 구현(즉, 우선 최대값을 뺀 선택)이 실제로 권장 솔루션보다 우수하다는 것입니다.사실, 이는 소프트맥스 기능을 구현하는 권장 방법입니다. 정당성에 대해서는 여기를 참조하십시오(숫자 안정성, 여기서도 일부 다른 답변에서 지적됨).

그래서 이건 정말 데스투르노의 대답에 대한 멘트인데 제 평판 때문에 아직 멘트를 못 드리겠어요.그가 지적한 바와 같이, 당신의 버전은 당신의 입력이 하나의 샘플로 구성되어 있는 경우에만 정확합니다.입력이 여러 샘플로 구성되어 있다면 잘못된 것입니다.하지만, 데저트노트의 해결책 또한 틀렸다.문제는 일단 1차원의 입력을 받고 2차원의 입력을 받는다는 겁니다.이거 보여드릴게요.

import numpy as np

# your solution:
def your_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()

# desertnaut solution (copied from his answer): 
def desertnaut_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(axis=0) # only difference

# my (correct) solution:
def softmax(z):
    assert len(z.shape) == 2
    s = np.max(z, axis=1)
    s = s[:, np.newaxis] # necessary step to do broadcasting
    e_x = np.exp(z - s)
    div = np.sum(e_x, axis=1)
    div = div[:, np.newaxis] # dito
    return e_x / div

desertnauts의 예를 들어보겠습니다.

x1 = np.array([[1, 2, 3, 6]]) # notice that we put the data into 2 dimensions(!)

출력은 다음과 같습니다.

your_softmax(x1)
array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037047]])

desertnaut_softmax(x1)
array([[ 1.,  1.,  1.,  1.]])

softmax(x1)
array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037047]])

이 상황에서는 desernauts 버전이 실패하는 것을 알 수 있습니다.(입력값이 np.array([1, 2, 3, 6])와 같은 1차원일 경우에는 그렇지 않습니다).

2차원 입력을 사용하는 이유는 3개의 샘플을 사용하는 것입니다.다음 x2는 desernauts의 예와 다릅니다.

x2 = np.array([[1, 2, 3, 6],  # sample 1
               [2, 4, 5, 6],  # sample 2
               [1, 2, 3, 6]]) # sample 1 again(!)

이 입력은 3개의 샘플이 포함된 배치로 구성됩니다.하지만 샘플 1과 3은 기본적으로 동일합니다.첫 번째가 세 번째와 같고 x1의 활성화와 같은 소프트맥스 활성화가 세 번째 행으로 예상됩니다!

your_softmax(x2)
array([[ 0.00183535,  0.00498899,  0.01356148,  0.27238963],
       [ 0.00498899,  0.03686393,  0.10020655,  0.27238963],
       [ 0.00183535,  0.00498899,  0.01356148,  0.27238963]])


desertnaut_softmax(x2)
array([[ 0.21194156,  0.10650698,  0.10650698,  0.33333333],
       [ 0.57611688,  0.78698604,  0.78698604,  0.33333333],
       [ 0.21194156,  0.10650698,  0.10650698,  0.33333333]])

softmax(x2)
array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037047],
       [ 0.01203764,  0.08894682,  0.24178252,  0.65723302],
       [ 0.00626879,  0.01704033,  0.04632042,  0.93037047]])

제 솔루션만 해당된다는 것을 알아주셨으면 합니다.

softmax(x1) == softmax(x2)[0]
array([[ True,  True,  True,  True]], dtype=bool)

softmax(x1) == softmax(x2)[2]
array([[ True,  True,  True,  True]], dtype=bool)

또한 TensorFlows softmax 구현의 결과는 다음과 같습니다.

import tensorflow as tf
import numpy as np
batch = np.asarray([[1,2,3,6],[2,4,5,6],[1,2,3,6]])
x = tf.placeholder(tf.float32, shape=[None, 4])
y = tf.nn.softmax(x)
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(y, feed_dict={x: batch})

그 결과:

array([[ 0.00626879,  0.01704033,  0.04632042,  0.93037045],
       [ 0.01203764,  0.08894681,  0.24178252,  0.657233  ],
       [ 0.00626879,  0.01704033,  0.04632042,  0.93037045]], dtype=float32)

둘 다 수학적으로는 맞지만 구현 면에서는 첫 번째 것이 더 낫다고 생각합니다.softmax를 계산할 때 중간값이 매우 커질 수 있습니다.두 개의 큰 숫자를 나누는 것은 수치적으로 불안정할 수 있습니다.(Stanford의) 이 노트에는 기본적으로 여러분이 하고 있는 정규화의 트릭이 기재되어 있습니다.

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]]) 

수학적 관점에서 보면 양쪽이 같다.

그리고 당신은 이것을 쉽게 증명할 수 있다.자.m=max(x).기능이 향상되었습니다.softmaxi번째 좌표가 다음과 같은 벡터를 반환합니다.

여기에 이미지 설명 입력

이것은 모든 사람에게 유효하다는 것을 알 수 있다m모든 (복잡한) 숫자에 대해서e^m != 0

  • 계산 복잡성의 관점에서 보면, 그것들은 동등하고 둘 다 실행된다.O(n)시간, 장소n벡터의 크기입니다.

  • 수치 안정성의 관점에서, 첫 번째 솔루션이 선호된다. 왜냐하면e^x매우 빠르게 성장하며 심지어 꽤 작은 가치에도 불구하고x넘칠 거예요.최대값을 빼면 이 오버플로를 제거할 수 있습니다.제가 말씀드린 것을 실제로 경험해 보기 위해서 밥을 먹여보려고 노력하세요.x = np.array([1000, 5])두 가지 기능을 모두 사용할 수 있습니다.하나는 정확한 확률을 반환하고, 두 번째는 로 넘쳐납니다.nan

  • 이 솔루션은 벡터에 대해서만 작동합니다(Udacity 퀴즈에서는 행렬에 대해서도 계산해야 합니다).수정하려면 를 사용해야 합니다.sum(axis=0)

편집 버전 1.2.0 이후 skipy에는 softmax가 특수 기능으로 포함되어 있습니다.

https://scipy.github.io/devdocs/generated/scipy.special.softmax.html

모든 축에 softmax를 적용하는 함수를 작성했습니다.

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

다른 사용자가 설명한 것처럼 최대값을 빼는 것이 좋습니다.여기에 자세한 글을 올렸습니다.

여기서 그들이 왜 사용했는지 알 수 있다.- max.

여기서부터:

「실제로 Softmax 함수를 계산하기 위한 코드를 작성하는 경우, 지수 때문에 중간 용어가 매우 클 수 있습니다.큰 숫자를 나누면 수치적으로 불안정할 수 있으므로 정규화 방법을 사용하는 것이 중요합니다."

이 둘의 퍼포먼스 차이가 궁금했어요.

import numpy as np

def softmax(x):
    """Compute softmax values for each sets of scores in x."""
    return np.exp(x) / np.sum(np.exp(x), axis=0)

def softmaxv2(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()

def softmaxv3(x):
    """Compute softmax values for each sets of scores in x."""
    e_x = np.exp(x - np.max(x))
    return e_x / np.sum(e_x, axis=0)

def softmaxv4(x):
    """Compute softmax values for each sets of scores in x."""
    return np.exp(x - np.max(x)) / np.sum(np.exp(x - np.max(x)), axis=0)



x=[10,10,18,9,15,3,1,2,1,10,10,10,8,15]

사용.

print("----- softmax")
%timeit  a=softmax(x)
print("----- softmaxv2")
%timeit  a=softmaxv2(x)
print("----- softmaxv3")
%timeit  a=softmaxv2(x)
print("----- softmaxv4")
%timeit  a=softmaxv2(x)

x(+100 + 200 + 500...) 내의 값을 늘리면 원래 numpy 버전에서 일관되게 더 나은 결과를 얻을 수 있습니다(여기서는 1개의 테스트만 실시합니다).

----- softmax
The slowest run took 8.07 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 17.8 µs per loop
----- softmaxv2
The slowest run took 4.30 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 23 µs per loop
----- softmaxv3
The slowest run took 4.06 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 23 µs per loop
----- softmaxv4
10000 loops, best of 3: 23 µs per loop

그때까지...x 안에 있는 값이 800까지 도달하면

----- softmax
/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:4: RuntimeWarning: overflow encountered in exp
  after removing the cwd from sys.path.
/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:4: RuntimeWarning: invalid value encountered in true_divide
  after removing the cwd from sys.path.
The slowest run took 18.41 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 23.6 µs per loop
----- softmaxv2
The slowest run took 4.18 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 22.8 µs per loop
----- softmaxv3
The slowest run took 19.44 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 23.6 µs per loop
----- softmaxv4
The slowest run took 16.82 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 22.7 µs per loop

일부에서 말했듯이, 당신의 버전은 '대수의 경우' 수치적으로 더 안정적입니다.적은 숫자의 경우 그 반대일 수 있습니다.

보다 간결한 버전은 다음과 같습니다.

def softmax(x):
    return np.exp(x) / np.exp(x).sum(axis=0)

대체 해결책을 제시하기 위해 다음과 같이 주장의 크기가 매우 큰 경우를 고려하십시오.exp(x)언더플로우(음의 경우) 또는 오버플로우(양의 경우)가 됩니다.여기서 로그 공간에 가능한 한 오래 남아 있어야 합니다. 결과를 신뢰할 수 있는 마지막 부분만 지수화합니다.

import scipy.special as sc
import numpy as np

def softmax(x: np.ndarray) -> np.ndarray:
    return np.exp(x - sc.logsumexp(x))

텐서플로우에서 나오는 조밀한 층의 출력과 호환되는 것이 필요했습니다.

이 경우 데이터 배치가 있기 때문에 @desertnaut의 솔루션은 작동하지 않습니다.따라서 두 가지 경우 모두 효과가 있는 다른 솔루션을 준비했습니다.

def softmax(x, axis=-1):
    e_x = np.exp(x - np.max(x)) # same code
    return e_x / e_x.sum(axis=axis, keepdims=True)

결과:

logits = np.asarray([
    [-0.0052024,  -0.00770216,  0.01360943, -0.008921], # 1
    [-0.0052024,  -0.00770216,  0.01360943, -0.008921]  # 2
])

print(softmax(logits))

#[[0.2492037  0.24858153 0.25393605 0.24827873]
# [0.2492037  0.24858153 0.25393605 0.24827873]]

참조: Tensorflow softmax

나는 이것을 제안하고 싶다.

def softmax(z):
    z_norm=np.exp(z-np.max(z,axis=0,keepdims=True))
    return(np.divide(z_norm,np.sum(z_norm,axis=0,keepdims=True)))

그것은 배치뿐만 아니라 확률적으로도 효과가 있을 것이다.
상세한 것에 대하여는, https://medium.com/@ravish1729/analysis-of-softmax-function-ad058d6a564d 를 참조해 주세요.

수치 안정성을 유지하기 위해 max(x)를 빼야 합니다.다음은 소프트맥스 기능의 코드입니다.

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

위의 답변에서 이미 상세하게 답변했습니다. max이치노python3는 python3를 말합니다.

import numpy as np
def softmax(x):
    mx = np.amax(x,axis=1,keepdims = True)
    x_exp = np.exp(x - mx)
    x_sum = np.sum(x_exp, axis = 1, keepdims = True)
    res = x_exp / x_sum
    return res

x = np.array([[3,2,4],[4,5,6]])
print(softmax(x))

모두가 자신의 솔루션을 투고하고 있는 것 같기 때문에, 제 솔루션을 투고합니다.

def softmax(x):
    e_x = np.exp(x.T - np.max(x, axis = -1))
    return (e_x / e_x.sum(axis=0)).T

sklearn에서 Import한 것과 동일한 결과를 얻을 수 있습니다.

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

def softmax(x):
    return (np.exp(x).T / np.exp(x).sum(axis=-1)).T

logits = np.array([[1, 2, 3], [3, 10, 1], [1, 2, 5], [4, 6.5, 1.2], [3, 6, 1]])

sess = tf.Session()
print(softmax(logits))
print(sess.run(tf.nn.softmax(logits)))
sess.close()

모든 응답과 CS231n 메모를 바탕으로 다음 사항을 요약합니다.

def softmax(x, axis):
    x -= np.max(x, axis=axis, keepdims=True)
    return np.exp(x) / np.exp(x).sum(axis=axis, keepdims=True)

사용방법:

x = np.array([[1, 0, 2,-1],
              [2, 4, 6, 8], 
              [3, 2, 1, 0]])
softmax(x, axis=1).round(2)

출력:

array([[0.24, 0.09, 0.64, 0.03],
       [0.  , 0.02, 0.12, 0.86],
       [0.64, 0.24, 0.09, 0.03]])

저는 그 문제에 대한 이해를 조금 더 보충하고 싶습니다.여기에서는 어레이의 최대값을 뺀 것이 맞습니다.그러나 다른 게시물에서 코드를 실행하면 어레이가 2D 이상일 때 정답을 알 수 없습니다.

몇 가지 제안을 드리겠습니다.

  1. 최대값을 얻으려면 x축을 따라 하면 1D 어레이가 됩니다.
  2. 최대 배열의 모양을 원래 모양으로 변경합니다.
  3. np.exp를 실행하여 지수값을 가져옵니다.
  4. 축을 따라 np.sum을 수행합니다.
  5. 최종 결과를 얻습니다.

벡터화를 하면 정답을 얻을 수 있습니다.대학 숙제와 관련된 것이기 때문에 여기에 정확한 코드를 올릴 수는 없지만, 이해가 안 된다면 더 많은 제안을 드리고 싶습니다.

Numpy Tensorflow 。은 '오직'입니다.axis''의 np.sumapiapi..

초기 접근법:axis=0단, 가 N 、 N.- 、 N. 단 、 N. - 、 N. - 、 N. - 、 N. - 、 N. - 、 N. - 、 N. - 、 N. - - - - - - - - - - - - - - - -

변경된 접근법:axis=len(e_x.shape)-1어느정도면좋아요.소프트맥스

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)

다음은 numpy를 사용한 일반화 솔루션과 텐서플로우 및 scipy와의 정확성 비교입니다.

데이터 준비:

import numpy as np

np.random.seed(2019)

batch_size = 1
n_items = 3
n_classes = 2
logits_np = np.random.rand(batch_size,n_items,n_classes).astype(np.float32)
print('logits_np.shape', logits_np.shape)
print('logits_np:')
print(logits_np)

출력:

logits_np.shape (1, 3, 2)
logits_np:
[[[0.9034822  0.3930805 ]
  [0.62397    0.6378774 ]
  [0.88049906 0.299172  ]]]

텐서플로우를 사용하는 소프트맥스:

import tensorflow as tf

logits_tf = tf.convert_to_tensor(logits_np, np.float32)
scores_tf = tf.nn.softmax(logits_np, axis=-1)

print('logits_tf.shape', logits_tf.shape)
print('scores_tf.shape', scores_tf.shape)

with tf.Session() as sess:
    scores_np = sess.run(scores_tf)

print('scores_np.shape', scores_np.shape)
print('scores_np:')
print(scores_np)

print('np.sum(scores_np, axis=-1).shape', np.sum(scores_np,axis=-1).shape)
print('np.sum(scores_np, axis=-1):')
print(np.sum(scores_np, axis=-1))

출력:

logits_tf.shape (1, 3, 2)
scores_tf.shape (1, 3, 2)
scores_np.shape (1, 3, 2)
scores_np:
[[[0.62490064 0.37509936]
  [0.4965232  0.5034768 ]
  [0.64137274 0.3586273 ]]]
np.sum(scores_np, axis=-1).shape (1, 3)
np.sum(scores_np, axis=-1):
[[1. 1. 1.]]

Softmax(Scipy 사용):

from scipy.special import softmax

scores_np = softmax(logits_np, axis=-1)

print('scores_np.shape', scores_np.shape)
print('scores_np:')
print(scores_np)

print('np.sum(scores_np, axis=-1).shape', np.sum(scores_np, axis=-1).shape)
print('np.sum(scores_np, axis=-1):')
print(np.sum(scores_np, axis=-1))

출력:

scores_np.shape (1, 3, 2)
scores_np:
[[[0.62490064 0.37509936]
  [0.4965232  0.5034768 ]
  [0.6413727  0.35862732]]]
np.sum(scores_np, axis=-1).shape (1, 3)
np.sum(scores_np, axis=-1):
[[1. 1. 1.]]

numpy를 사용한 Softmax(https://nolanbconaway.github.io/blog/2017/softmax-numpy) :

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


scores_np = softmax(logits_np, axis=-1)

print('scores_np.shape', scores_np.shape)
print('scores_np:')
print(scores_np)

print('np.sum(scores_np, axis=-1).shape', np.sum(scores_np, axis=-1).shape)
print('np.sum(scores_np, axis=-1):')
print(np.sum(scores_np, axis=-1))

출력:

scores_np.shape (1, 3, 2)
scores_np:
[[[0.62490064 0.37509936]
  [0.49652317 0.5034768 ]
  [0.64137274 0.3586273 ]]]
np.sum(scores_np, axis=-1).shape (1, 3)
np.sum(scores_np, axis=-1):
[[1. 1. 1.]]

소프트맥스 함수는 숫자를 확률로 변환하여 합계를 1로 하는 활성화 함수입니다.softmax 함수는 결과 목록의 확률 분포를 나타내는 벡터를 출력합니다.또한 딥 러닝 분류 작업에 사용되는 핵심 요소입니다.

Softmax 함수는 여러 클래스가 있을 때 사용됩니다.

최대값을 가진 클래스를 찾는 데 유용합니다.가능성.

Softmax 함수는 출력 레이어에서 이상적으로 사용되며, 실제로 각 입력의 클래스를 정의할 확률을 얻으려고 합니다.

범위는 0 ~ 1 입니다.

소프트맥스 함수는 로짓 [2.0, 1.0, 0.1]을 확률[0.7, 0.2, 0.1]로 변환하고 확률을 합하면 1이 됩니다.로짓은 뉴럴네트워크의 마지막 레이어에서 출력되는 미가공 점수입니다.활성화하기 전.softmax 함수를 이해하기 위해서는 (n-1)번째 레이어의 출력을 조사할 필요가 있습니다.

softmax 함수는 실제로는 arg max 함수입니다.즉, 입력에서 가장 큰 값을 반환하는 것이 아니라 가장 큰 값의 위치를 반환하는 것입니다.

예를 들어 다음과 같습니다.

softmax 이전

X = [13, 31, 5]

softmax 이후

array([1.52299795e-08, 9.99999985e-01, 5.10908895e-12]

코드:

import numpy as np

# your solution:

def your_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() 

# correct solution: 

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(axis=0) 

# only difference

이것은 np.reshape에서도 동작합니다.

   def softmax( scores):
        """
        Compute softmax scores given the raw output from the model

        :param scores: raw scores from the model (N, num_classes)
        :return:
            prob: softmax probabilities (N, num_classes)
        """
        prob = None

        exponential = np.exp(
            scores - np.max(scores, axis=1).reshape(-1, 1)
        )  # subract the largest number https://jamesmccaffrey.wordpress.com/2016/03/04/the-max-trick-when-computing-softmax/
        prob = exponential / exponential.sum(axis=1).reshape(-1, 1)

        

        return prob

softmax 함수의 목적은 값이 포화되면 끝점을 Sigmoid로 스퀴즈하는 것과 반대로 벡터의 비율을 유지하는 것이다(즉 +/- 1(tanh) 또는 0 ~ 1(logical)의 경향이 있다).이는 엔드포인트에서의 변화율에 대한 더 많은 정보를 보존하기 때문에 1/N 출력 인코딩을 사용하는 신경망에 더 잘 적용되기 때문이다(즉, 엔드포인트를 스퀴즈하면 어느 것이 "가장 큰"지 "가장 작은"지 구분할 수 없기 때문에 N 중 1 출력 클래스를 구별하기가 더 어려워진다).l 따라서 총 출력 합계가 1이 되고, 명확한 승자는 1에 가까워지며, 서로 가까운 다른 숫자는 1/p가 됩니다.여기서 p는 유사한 값을 가진 출력 뉴런의 수입니다.

벡터에서 최대값을 빼는 목적은 e^y 지수를 사용하면 동점으로 이어지는 최대값에서 플로트를 자르는 매우 높은 값을 얻을 수 있다는 것입니다. 이 예에서는 그렇지 않습니다.이것은 최대값을 빼서 음수를 만들면 큰 문제가 됩니다.그러면 비율을 변경하는 값이 급격히 축소되는 음의 지수가 나타나게 됩니다.이것은 포스터의 질문에서 발생했고 오답이 나왔습니다.

Udacity가 제공한 답변은 끔찍하게 비효율적이다.먼저 모든 벡터 성분에 대해 e^y_j를 계산하고 KEEP THES VALUES를 유지한 후 합산하여 나눕니다.Udacity가 망친 것은 e^y_j TWICE를 계산하는 것입니다!!!정답은 다음과 같습니다.

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)

이렇게 하면 후행 치수를 정규화하고 있다고 가정합니다.

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

다음 세 가지 간단한 행을 사용했습니다.

x_exp=np.exp(x)
x_sum=np.sum(x_exp, axis = 1, keepdims = True)
s=x_exp / x_sum

언급URL : https://stackoverflow.com/questions/34968722/how-to-implement-the-softmax-function-in-python

반응형