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


247

로부터 Udacity의의 깊은 학습 클래스 , y_i의 softmax를 전체 Y 벡터의 지수의 합으로 나눈 지수는 간단하다 :

여기에 이미지 설명을 입력하십시오

어디 S(y_i)의 softmax를 함수 y_ie지수 함수이며, j노입니다. 입력 벡터 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)

첫 번째 구현은 명시 적으로 각 열과 최대의 차이를 취한 다음 합계로 나눠도 첫 번째 구현과 동일한 출력 을 생성합니다 .

누군가 수학적으로 이유를 보여줄 수 있습니까? 하나는 정확하고 다른 하나는 잘못입니까?

코드 및 시간 복잡성 측면에서 구현이 유사합니까? 어느 것이 더 효율적입니까?


6
왜 max 함수로 이런 식으로 구현하려고했는지 궁금합니다. 그렇게 생각한 게 뭐야?
BBischof

1
모르겠다. 최대 값을 0으로 취급하고 그래프를 왼쪽으로 옮기고 0을 클립하는 것과 같은 종류의 도움이된다고 생각했습니다. 그런 다음 내 범위는에서 -inf to +inf까지 단축 됩니다 -inf to 0. 나는 너무 생각하고 있었다고 생각한다. hahahaaa
alvas

1
나는 여전히 아래에 답변되지 않은 하위 질문이 하나 있습니다. axis = 0Udacity가 제안한 답변 의 의미는 무엇입니까 ?
Parva Thakkar

3
numpy 문서를 살펴보면 sum (x, axis = 0)과 비슷하게 axis = 1이 수행하는 작업에 대해 설명합니다. 즉, 배열 배열을 합하는 방향을 제공합니다. 이 경우 벡터를 따라 합치도록 지시합니다. 이 경우에는 softmax 함수의 분모에 해당합니다.
BBischof

3
격주로, 내 수학이 누가 옳은지를 결정하기에 충분하지 않을 때까지 더 정확한 답이 있습니다.
alvas

답변:


137

둘 다 맞지만 수치 안정성의 관점에서 당신이 선호됩니다.

당신은 시작

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)를 임의의 변수로 바꾸면 취소됩니다.


4
자세한 설명을 위해 답변 @TrevorM을 다시 포맷하십시오 .e ^ (x-max (x)) / sum (e ^ (x-max (x)) using a ^ (b-c) = (a ^ b) / (a ​​^ c) 우리가, E = X ^ / {최대 ^ E (X) * 합 (X ^ E / E ^ 맥스 (X))} = E ^ X / 합 (E ^ X)
shanky_thebearer

5
@ Trevor Merrifield, 나는 첫 번째 접근 방식에 "불필요한 용어"가 있다고 생각하지 않습니다. 실제로 두 번째 방법보다 낫습니다. 이 점을 별도의 답변으로 추가했습니다.
Shagun Sodhani

6
@Shagun 당신은 맞습니다. 이 둘은 수학적으로 동일하지만 수치 적 안정성을 고려하지 않았습니다.
Trevor Merrifield

마음에 들지 않기를 바랍니다. 사람들이 주석을 읽지 않거나 주석이 사라지는 경우를 위해 "불필요한 용어"를 편집했습니다. 이 페이지는 검색 엔진에서 많은 트래픽을 얻었으며 현재 사람들이 보는 첫 번째 답변입니다.
Alex Riley

왜 max (abs (x))가 아닌 max (x)를 빼는 지 궁금합니다 (값을 결정한 후 부호 수정). 모든 값이 0보다 작고 절대 값이 매우 크고 값 (최대 값) 만 0에 가까우면 최대 값을 빼더라도 아무런 변화가 없습니다. 여전히 수치 적으로 불안정하지 않습니까?
Cerno

102

(글쎄 ... 질문과 대답 모두에서 많은 혼란이 있습니다 ...)

우선 두 가지 솔루션 (예 : 귀하와 제안 된 솔루션)은 동일 하지 않습니다 . 그들은 일어난다 단지 1-D 점수 배열의 특별한 경우에 해당합니다. 제공된 Udacity 퀴즈 예제에서 2 차원 점수 배열을 시도한 경우이를 발견했을 것입니다.

결과적으로 두 솔루션의 실제 차이점은 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

내가 말했듯이 1D 점수 배열의 경우 결과는 실제로 동일합니다.

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 차원 점수 배열의 결과는 다음과 같습니다.

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인수였습니다. numpy.sum 문서 에 따르면 :

기본값 인 axis = None은 입력 배열의 모든 요소를 ​​합산합니다.

여기서 우리는 행 단위로 합계를 원합니다 axis=0. 1-D 배열의 경우 (전용) 행의 합과 모든 요소의 합이 동일 하므로이 경우 동일한 결과가 발생합니다 ...

axis문제를 제외하고, 구현 (최대 첫째을 뺄 즉, 당신의 선택은) 실제로 더 나은 제안 된 솔루션보다! 실제로, 그것은 softmax 기능을 구현하기 위해 권장되는 방법입니다 . 정당화에 대해서는 여기 를 참조 하십시오 (숫자 안정성, 여기에 다른 답변이 지적함).


다차원 배열에 대해서만 이야기한다면. 첫 번째 솔루션은 및 axis에 모두 인수를 추가하여 쉽게 수정할 수 있습니다 . 그러나 첫 번째 구현은 여전히 ​​낫을 때 오버플로 할 수 있기 때문에 여전히 좋습니다maxsumexp
Louis Yang

@LouisYang 팔로우하지 않습니다; "첫 번째"솔루션은 무엇입니까? 어느 것을 사용 하지 exp않습니까? 여기에 axis인수를 추가하는 것 외에 무엇이 더 수정 되었습니까?
desertnaut

첫 번째 솔루션은 @alvas의 솔루션을 나타냅니다. 차이점은 alvas의 질문에서 제안 된 솔루션에 최대 값을 빼는 부분이 빠져 있다는 것입니다. 예를 들어 exp (1000) / (exp (1000) + exp (1001)) vs exp (-1) / (exp (-1) + exp (0))은 수학에서 동일하지만 첫 번째는 오버플로됩니다.
루이 양

@LouisYang은 여전히 ​​귀하의 의견의 필요성을 이해하지 못합니다.이 모든 것은 이미 답변에서 명시 적으로 해결되었습니다.
Desertnaut

A는 ( "OP 의아해 : @LouisYang 스레드의 (이후)의 인기가 당신을 바보, 그리고 자신의 대답이 제공 한 상황을 상상 해보자하지 마십시오 모두 같은 결과를 제공 ") 및 (아직도!) 허용 대답을 "주장 이 모두 올바른지 "(물론, 그들이는 없습니다 ). 답은 " 일반적으로 소프트 맥스를 계산하는 가장 정확하고 효율적인 방법 "이 아닙니다 . 그것은 단지 정당화하는 의미 에서, 특정 Udacity의 퀴즈 논의, 2 개 솔루션은 없습니다 해당.
desertnaut

56

따라서 이것은 실제로 desertnaut의 답변에 대한 의견이지만 내 평판으로 인해 아직 댓글을 달 수 없습니다. 그가 지적했듯이 입력이 단일 샘플로 구성된 경우에만 버전이 정확합니다. 입력 값이 여러 샘플로 구성되어 있으면 잘못되었습니다. 그러나 desertnaut의 솔루션도 잘못되었습니다. 문제는 일단 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은 본질적으로 동일합니다. 우리는 이제 3 행의 softmax 활성화를 기대합니다. 여기서 첫 번째는 세 번째와 동일해야하며 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)

6
그것은 논평의 한 지옥이었을 것입니다 ;-)
Michael Benjamin

27
np.exp (z) / np.sum (np.exp (z), axis = 1, keepdims = True)는 softmax 함수와 동일한 결과에 도달합니다. s 단계는 불필요합니다.
PabTorre

장소 of`에서 s = s[:, np.newaxis], s = s.reshape(z.shape[0],1)작업도해야한다.
Debashish

2
이 페이지에 많은 잘못된 / 비효율적 인 솔루션이 있습니다. 호의를 베풀고 PabTorre를 사용하십시오
Miss Palmer

@PabTorre 축 = 1을 의미 했습니까? 1 축 입력이 1 차원 입력에서 작동하지 않음
DiehardTheTryhard

36

둘 다 수학적으로, 구현 측면에서는 정확하지만 첫 번째 방법이 더 낫습니다. softmax를 계산할 때 중간 값이 매우 커질 수 있습니다. 두 개의 큰 숫자를 나누면 수치 적으로 불안정 할 수 있습니다.(스탠포드의) 이 노트 는 본질적으로하고있는 정규화 트릭을 언급합니다.


3
치명적인 취소의 영향을 과소 평가할 수 없습니다.
Cesar

24

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

3
어떻게 이것이 제 3 자 라이브러리의 가용성이 아니라 구현 자체 에 관한 특정 질문에 정확히 대답 합니까?
desertnaut

8
두 가지 접근 방식의 결과를 확인하기 위해 타사 구현을 찾고있었습니다. 이것이이 의견이 도움이되는 방식입니다.
Eugenio F. Martinez Pacheco

13

수학적 관점에서 양측은 동일합니다.

그리고 당신은 이것을 쉽게 증명할 수 있습니다. 하자 m=max(x). 이제 함수 softmax는 i 번째 좌표가 같은 벡터를 반환합니다.

여기에 이미지 설명을 입력하십시오

이 모든 작동 것을 통보 m하기 때문에 모든 (복잡한) 숫자,e^m != 0

  • 계산 복잡성의 관점에서 볼 때 그것들은 또한 동등하며 O(n)시간 에 따라 실행됩니다 n. 벡터의 크기는 어디 입니까?

  • 에서 수치 적 안정성 때문에 관점, 제 용액, 바람직 e^x매우 빠르게 성장하고 짝수의 아주 작은 값 x것이 오버플. 최대 값을 빼면이 오버플로를 제거 할 수 있습니다. 내가 말한 것을 실제로 경험하려면 x = np.array([1000, 5])두 기능 모두에 공급 하십시오. 하나는 올바른 확률을 반환하고 두 번째는nan

  • 솔루션은 벡터에 대해서만 작동합니다 (Udacity 퀴즈에서는 행렬에 대해서도 계산하려고 함). 그것을 고치려면 사용해야합니다.sum(axis=0)


1
벡터가 아닌 행렬에 대해 softmax를 계산할 수 있다면 언제 유용한가요? 즉 어떤 모델이 매트릭스를 출력합니까? 더 차원적일 수 있습니까?
mrgloom

2
"숫자 안정성 관점에서 두 번째 솔루션이 선호됩니다 ..." 의 첫 번째 솔루션 을 의미 합니까?
Dataman

10

편집하다 . 버전 1.2.0부터 scipy는 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

다른 사용자가 설명한 것처럼 최대 값을 빼는 것이 좋습니다. 나는 여기 에 대한 자세한 게시물을 썼습니다 .


9

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

거기에서:

"실제로 Softmax 함수를 계산하기위한 코드를 작성할 때 지수로 인해 중간 항이 매우 클 수 있습니다. 큰 수를 나누는 것은 수치 적으로 불안정 할 수 있으므로 정규화 트릭을 사용하는 것이 중요합니다."



4

대체 솔루션을 제공하려면 인수의 크기가 극도로 큰 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))

포스터 코드와 동일하게하려면 axis=0에 인수로 추가해야 합니다 logsumexp.
Björn Lindqvist

또는 logsumexp에 전달할 추가 인수를 압축 해제 할 수 있습니다.
PikalaxALT

3

Tensorflow 의 고밀도 레이어 출력과 호환되는 것이 필요했습니다 .

이 경우 배치 데이터가 있기 때문에 @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


대답은 질문에 설명 된 매우 구체적인 설정을 나타냅니다 . 결코 '어떤 상황이나 일반적으로 원하는 데이터 형식으로
소프트 맥스

질문은 "Udacity의 딥 러닝 클래스"를 참조하기 때문에 여기에 넣었습니다 .Tensorflow를 사용하여 모델을 빌드하면 작동하지 않습니다. 귀하의 솔루션은 시원하고 깨끗하지만 매우 구체적인 시나리오에서만 작동합니다. 어쨌든 고마워
Lucas Casagrande


1

수치 안정성을 유지하려면 max (x)를 빼야합니다. 다음은 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

1

위의 답변에서 이미 매우 자세히 답변했습니다. max오버플로를 피하기 위해 뺍니다. 여기에 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))

1

모두 자신의 솔루션을 게시하는 것 같습니다.

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

sklearn에서 가져온 것과 정확히 동일한 결과를 얻습니다.

from sklearn.utils.extmath import softmax

1
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()

SO에 오신 것을 환영합니다. 코드가 질문에 어떻게 대답하는지에 대한 설명은 항상 도움이됩니다.
Nick

1

모든 응답과 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]])

0

문제에 대한 이해를 조금 더 보충하고 싶습니다. 여기에서 배열의 최대 값을 빼는 것이 맞습니다. 그러나 다른 게시물에서 코드를 실행하면 배열이 2D 이상일 때 올바른 답변을 제공하지 않습니다.

여기에 몇 가지 제안이 있습니다.

  1. 최대를 얻으려면 x 축을 따라 시도하면 1D 배열이 생깁니다.
  2. 최대 배열을 원래 모양으로 바꿉니다.
  3. np.exp는 지수 값을 얻습니다.
  4. 축을 따라 np.sum을 수행하십시오.
  5. 최종 결과를 얻으십시오.

벡터화를 수행하면 정답을 얻을 수있는 결과를 따릅니다. 그것은 대학 숙제와 관련이 있기 때문에 정확한 코드를 여기에 게시 할 수는 없지만 이해하지 못하면 더 많은 제안을하고 싶습니다.


1
그것은 대학 숙제와 관련이 없으며 다음 단계에서 정답이 제공되는 공인되지 않은 과정의 비정기 연습 퀴즈에만 해당됩니다.
desertnaut

0

softmax 함수의 목적은 값이 포화 될 때 (즉, +/- 1 (tanh) 경향이 있거나 0에서 1 (logistical) 경향이있는 S 자형으로 끝점을 찌그러 뜨리는 것과 반대로 벡터의 비율을 유지하는 것입니다. 이는 종점의 변화율에 대한 더 많은 정보를 유지하므로 1-N 출력 인코딩을 사용하는 신경망에 더 적합하기 때문입니다 (즉, 종점을 찌그러 뜨리면 1을 구별하기가 더 어려워집니다) 어떤 것이 "가장 큰지"또는 "가장 작은 지"를 알아낼 수 없기 때문에 -of-N 출력 클래스. 또한 총 출력 합계를 1로 만들고 명확한 승자는 1에 가까워지고 서로 가까운 다른 숫자는 1 / p에 합산됩니다. 여기서 p는 비슷한 값을 가진 출력 뉴런의 수입니다.

벡터에서 최대 값을 빼는 목적은 e = y 지수를 사용할 때 부동 소수점을 최대 값으로 클립하여 넥타이로 연결하는 매우 높은 값을 얻을 수 있다는 것입니다.이 예에서는 그렇지 않습니다. 음수를 만들기 위해 최대 값을 빼면 큰 문제가됩니다. 포스터의 질문에서 발생한 비율을 변경하는 값을 빠르게 축소하는 음의 지수가 있습니다.

Udacity가 제공하는 답변은 비효율적입니다. 가장 먼저해야 할 일은 모든 벡터 구성 요소에 대해 e ^ y_j를 계산하고, 값을 유지 한 다음 합산하여 나누는 것입니다. 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)

0

Numpy와 Tensorflow를 사용하여 비슷한 결과를 얻는 것이 목표였습니다. 원래의 대답에서 단 하나의 변화는 axis를위한 매개 변수np.sum 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)

0

다음은 tensorflow ans scipy의 정확성을 위해 numpy와 비교를 사용하는 일반 솔루션입니다.

데이터 준비 :

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

tensorflow를 사용한 Softmax :

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

scipy를 사용한 Softmax :

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

0

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

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

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

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

0에서 1까지의 범위입니다.

Softmax 함수는 로지트 [2.0, 1.0, 0.1]를 확률 [0.7, 0.2, 0.1]로 변환하고 확률의 합을 1로 설정합니다.로 짓은 신경망의 마지막 계층에서 출력 된 원시 점수입니다. 활성화하기 전에. softmax 함수를 이해하려면 n-1 번째 레이어의 출력을 살펴 봐야합니다.

실제로 softmax 함수는 arg max 함수입니다. 즉, 입력에서 가장 큰 값을 반환하지 않고 가장 큰 값의 위치를 ​​반환합니다.

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

softmax 이전

X = [13, 31, 5]

소프트 맥스 후

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.