GELU (Gaussian Error Linear Unit) 는 방정식을 $$ GELU (x) = xP (X ≤ x) = xΦ (x). $$로 나타냅니다. 이는 대략 $$ 0.5x (1 + tanh [\ sqrt {2 / π} (x + 0.044715x ^ 3)]) $$
등식을 단순화하고 근사치에 대해 설명해 주시겠습니까?
답변
GELU 함수
$ \ mathcal {N} (0, 1) $ 의 누적 분포를 확장 할 수 있습니다. span> , 즉 $ \ Phi (x) $ , 다음과 같습니다. $$ \ text {GELU} (x) : = x {\ Bbb P} (X \ le x) = x \ Phi (x) = 0.5x \ left (1+ \ text {erf} \ left (\ frac {x} {\ sqrt {2 }} \ right) \ right) $$
이것은 방정식 (또는 관계)이 아니라 정의 입니다. 저자는이 제안에 대한 몇 가지 정당성을 제공했습니다. 확률 론적 유사 학 이지만 수학적으로는 정의 일뿐입니다.
다음은 GELU의 플롯입니다.
Tanh 근사
이러한 유형의 수치 근사에서 핵심 아이디어는 유사한 함수 (주로 경험을 기반으로 함)를 찾고 매개 변수화 한 다음 원래 함수의 포인트 세트.
$ \ text {erf} (x) $ 가 $ \ text에 매우 가깝다는 것을 알고 있습니다. {tanh} (x) $
및 $ \ text {erf} (\ frac {x} {\ sqrt {2}}) $ 는 $ \ text {tanh} (\ sqrt { $ x = 0 $ 의 \ frac {2} {\ pi}} x) $ () $ \ sqrt {\ frac {2} {\ pi}} $ , $$ \ text {tanh} \ left (\ sqrt {\ frac { 2} {\ pi}} (x + ax ^ 2 + bx ^ 3 + cx ^ 4 + dx ^ 5) \ right) $$ (또는 더 많은 용어 포함)를 점 집합 $ \ left (x_i, \ text {erf} \ left (\ frac {x_i} {\ sqrt {2}} \ right) \ right) $ .
이 함수를 $ (-1.5, 1.5) $ (이 사이트 사용 ), 계수는 다음과 같습니다.
$ a = c = d = 0 $ , $ b $ 은 (는) $ 0.04495641로 추정되었습니다. $ . 더 넓은 범위 (사이트에서 20 개만 허용됨)에서 더 많은 샘플을 사용하면 계수 $ b $ 가 논문의 에 더 가깝습니다. $ 0.044715 $ . 마지막으로
$ \ text {GELU} (x) = x \ Phi (x) = 0.5x \ left (1 + \ text {erf} \ left (\ frac {x} {\ sqrt {2}} \ right) \ right) \ simeq 0.5x \ left (1+ \ text {tanh} \ left (\ sqrt {\ frac { 2} {\ pi}} (x + 0.044715x ^ 3) \ right) \ right) $
평균 제곱 오차 $ \ sim $ x \ in [-10, 10] $ 에 대해 10 ^ {-8} $ .
그렇다면 1 차 파생 상품 간의 관계를 활용하지 않으면 $ \ sqrt {\ frac {2} {\ pi}} $ 라는 용어가 다음과 같이 매개 변수에 포함되었을 것입니다. $$ 0.5x \ left (1+ \ text {tanh} \ left (0.797885x + 0.035677x ^ 3 \ right) \ right) $$ 덜 아름답습니다 (덜 분석적 , 더 많은 숫자)!
패리티 활용
@BookYourLuck , 함수 패리티를 활용하여 검색하는 다항식 공간을 제한 할 수 있습니다. 즉, $ \ text {erf} $ 는 이상한 함수이므로 $ f (-x) =-f (x) $ 및 $ \ text {tanh} $ 도 홀수 함수, 다항식 함수 $ $ \ text {tanh} $ 내부의 \ text {pol} (x) $ 도 홀수 여야합니다 ( $ x $ )를 $$ \ text {erf} (-x) \ simeq \ text {tanh} (\ text {pol} (-x)) = \ text {tanh} (-\ text {pol} (x)) =-\ text {tanh} (\ text {pol} (x)) \ simeq- \ text {erf} (x) $$
이전에는 운이 좋게도 $ x ^ 2 $ 및 짝수 제곱에 대해 (거의) 계수가 0이되었습니다. $ x ^ 4 $ 그러나 일반적으로 이로 인해 예를 들어 와 같은 용어가있는 낮은 품질의 근사값이 나올 수 있습니다. $ 0.23x ^ 2 $ 추가 조건 (짝수 또는 홀수)으로 취소됨 단순히 $ 0x ^ 2 $ 를 선택하는 대신.
시그 모이 드 근사
$ \ text {erf} (x) $ 와 $ 2 \ left (\ sigma (x)-\ frac {1} {2} \ right) $ (시그 모이 드), 평균 제곱 오차와 함께 또 다른 근사치로 논문에서 제 안됨 $ x \ in [-10, 10] $ 의 경우 $ \ sim 10 ^ {-4} $ .
다음은 데이터 포인트 생성, 함수 피팅, 평균 제곱 오차 계산을위한 Python 코드입니다.
p>
import math import numpy as np import scipy.optimize as optimize def tahn(xs, a): return [math.tanh(math.sqrt(2 / math.pi) * (x + a * x**3)) for x in xs] def sigmoid(xs, a): return [2 * (1 / (1 + math.exp(-a * x)) - 0.5) for x in xs] print_points = 0 np.random.seed(123) # xs = [-2, -1, -.9, -.7, 0.6, -.5, -.4, -.3, -0.2, -.1, 0, # .1, 0.2, .3, .4, .5, 0.6, .7, .9, 2] # xs = np.concatenate((np.arange(-1, 1, 0.2), np.arange(-4, 4, 0.8))) # xs = np.concatenate((np.arange(-2, 2, 0.5), np.arange(-8, 8, 1.6))) xs = np.arange(-10, 10, 0.001) erfs = np.array([math.erf(x/math.sqrt(2)) for x in xs]) ys = np.array([0.5 * x * (1 + math.erf(x/math.sqrt(2))) for x in xs]) # Fit tanh and sigmoid curves to erf points tanh_popt, _ = optimize.curve_fit(tahn, xs, erfs) print("Tanh fit: a=%5.5f" % tuple(tanh_popt)) sig_popt, _ = optimize.curve_fit(sigmoid, xs, erfs) print("Sigmoid fit: a=%5.5f" % tuple(sig_popt)) # curves used in https://mycurvefit.com: # 1. sinh(sqrt(2/3.141593)*(x+a*x^2+b*x^3+c*x^4+d*x^5))/cosh(sqrt(2/3.141593)*(x+a*x^2+b*x^3+c*x^4+d*x^5)) # 2. sinh(sqrt(2/3.141593)*(x+b*x^3))/cosh(sqrt(2/3.141593)*(x+b*x^3)) y_paper_tanh = np.array([0.5 * x * (1 + math.tanh(math.sqrt(2/math.pi)*(x + 0.044715 * x**3))) for x in xs]) tanh_error_paper = (np.square(ys - y_paper_tanh)).mean() y_alt_tanh = np.array([0.5 * x * (1 + math.tanh(math.sqrt(2/math.pi)*(x + tanh_popt[0] * x**3))) for x in xs]) tanh_error_alt = (np.square(ys - y_alt_tanh)).mean() # curve used in https://mycurvefit.com: # 1. 2*(1/(1+2.718281828459^(-(a*x))) - 0.5) y_paper_sigmoid = np.array([x * (1 / (1 + math.exp(-1.702 * x))) for x in xs]) sigmoid_error_paper = (np.square(ys - y_paper_sigmoid)).mean() y_alt_sigmoid = np.array([x * (1 / (1 + math.exp(-sig_popt[0] * x))) for x in xs]) sigmoid_error_alt = (np.square(ys - y_alt_sigmoid)).mean() print("Paper tanh error:", tanh_error_paper) print("Alternative tanh error:", tanh_error_alt) print("Paper sigmoid error:", sigmoid_error_paper) print("Alternative sigmoid error:", sigmoid_error_alt) if print_points == 1: print(len(xs)) for x, erf in zip(xs, erfs): print(x, erf)
출력 :
Tanh fit: a=0.04485 Sigmoid fit: a=1.70099 Paper tanh error: 2.4329173471294176e-08 Alternative tanh error: 2.698034519269613e-08 Paper sigmoid error: 5.6479106346814546e-05 Alternative sigmoid error: 5.704246564663601e-05
댓글
- 근사치가 필요한 이유는 무엇입니까? ' 그냥 erf 함수를 사용할 수 없었나요?
답변
먼저 $$ \ Phi (x) = \ frac12 \ mathrm {erfc} \ left (-\ frac {x} {\ sqrt {2}} \ right) = \ frac12 \ left (1 + \ mathrm {erf} \ left (\ frac {x} {\ sqrt2} \ right) \ right) $$ $ \ mathrm {erf} $ . $$ \ mathrm {erf} \ left (\ frac x {\ sqrt2} \ right) \ approx \ tanh \ left (\ sqrt {\ frac2 \ pi} $ a \ approx 0.044715 $ 의 경우 \ left (x + ax ^ 3 \ right) \ right) $$ .
$ x $ 의 큰 값의 경우 두 함수 모두 $ [-1, 1 ] $ . 작은 $ x $ 의 경우 각 Taylor 시리즈는 $$ \ tanh (x) = x-\ frac {x ^ 3} {3} + o (x ^ 3) $$ 및 $$ \ mathrm {erf} (x) = \ frac {2} {\ sqrt {\ pi}} \ left (x-\ frac {x ^ 3} {3} \ right) + o (x ^ 3). $$ 대체하면 $$ \ tanh \ left (\ sqrt {\ frac2 \ pi} \ left (x + ax ^ 3 \ right) \ right) = \ sqrt \ frac {2} {\ pi} \ left (x + \ left (a -\ frac {2} {3 \ pi} \ right) x ^ 3 \ right) + o (x ^ 3) $$ 및 $$ \ mathrm {erf } \ left (\ frac x {\ sqrt2} \ right) = \ sqrt \ frac2 \ pi \ left (x-\ frac {x ^ 3} {6} \ right) + o (x ^ 3). $$ $ x ^ 3 $ 에 대한 등가 계수는 $$ a \ approx 0.04553992412 $$ 논문의 $ 0.044715 $ 에 가깝습니다.