심층 학습/확률 적 기울기 강하 (SGD) 시뮬레이션

1. 소개



심층 학습을 시작했습니다. 이번에는 확률적 그라디언트 강하법(SGD)을 Jupyter Notebook에서 시뮬레이션해 보겠습니다.

간단한 경사 강하법은 모든 데이터에서 기울기를 계산하여 가중치를 갱신하기 때문에 한 번 국소해에 빠지면 거기에서 빠져나가기 어려워지고 계산하는 시간도 걸립니다. 
 
확률적 그라디언트 강하법(SGD)은 데이터의 일부를 무작위로 추출하여 기울기를 계산하여 가중치를 업데이트하기 때문에 기울기 계산이 좋은 가감으로 흔들리고 국소해를 극복하여 보다 최적의 해에 도달 쉬워지고, 게다가 계산하는 시간은 짧아서 끝납니다.

이, 좋은 가감한 흔들림이, 보다 최적의 해에 도달하기 위한 수단이 되는 것이 매우 흥미롭게 느꼈기 때문에, 이번은, 확률적 구배 강하법(SGD)을 Jupyter Notebook 로 시뮬레이션해 보고 싶습니다.

2. 데이터 생성



이번은, 단순화하기 위해서 가중은 1개로 합니다. 적당히 x, y 좌표를 11점으로 하여 6차원 다항식으로 근사합니다.
import numpy as np
import matplotlib.pyplot as plt

# データ(多項式作成用)
x = np.array([-5.0,  -4.0,  -3.0,  -2.0,  -1.0,   0.0,   1.0,   2.0,   3.0,   4.0,    5.0])
y = np.array([ 5.0,   1.5,   2.0,   1.5,   0.0,  -3.0,  -1.0,   2.0,   3.0,   2.5,    5.0])

# 多項式作成(6次元)
p = np.poly1d(np.polyfit(x, y, 6))
print(p)

# データと多項式を表示
xp = np.linspace(-10, 10, 100)
plt.plot(x, y, '.', xp, p(xp), '')
plt.xlim(-7, 7)
plt.ylim(-5, 10)
plt.show()


◈ 얻어진 다항식을 바탕으로 x를 -10~10까지 100분할하여 변화시켰을 때의 y를 구합니다. 현실적으로는, 관측치에 노이즈가 타고 있을 것이므로, y 에는 0~0.2의 난수를 더하고 있습니다.
# 多項式から100点のデータを作成 (0〜0.2の乱数を足す)
x_add, y_add =[], []
for i in np.linspace(-10, 10, 100):
    x_add.append(i)
    y_add.append( p(i) + np.random.normal(0, 0.2)) 

# 作成したデータを表示
plt.scatter(x_add, y_add, alpha=0.5)
plt.xlim(-7, 7)
plt.ylim(-5, 10)
plt.show()


x = -4, 4 근처에 국소해, x = 0 주변에 최적해가 있는 데이터(100점)를 작성할 수 있었습니다.

3. 확률적 구배 강하법



코드의 메인 부분입니다. train_test_split 를 사용하여 100점 데이터에서 10점을 무작위로 샘플링합니다.

그 10점의 데이터만을 바탕으로, 6차원의 다항식으로 근사해, d_y = p.deriv() 로 미분을 구해, 기울기를 계산해 가중치를 갱신합니다.

이것을 1 화면씩 실시해, matplotlib 의 애니메이션으로 동영상화합니다.
from sklearn.model_selection import train_test_split
from matplotlib import pylab
from matplotlib import animation, rc

# 設定
rc('animation', html='jshtml')
w = np.array([-2.])

# ランダムサンプリング関数(100点から10点をサンプリング)
def random_sampling():
    X_train, X_test, y_train, y_test = train_test_split(x_add, y_add, test_size=0.90)
    _x = X_train
    _y = y_train 
    return _x, _y

# 1画面作成関数
def animate(frame, w, alpha):    
    _x, _y = random_sampling()
    p = np.poly1d(np.polyfit(_x, _y, 6))
    plt.plot(_x, _y, '.',
             xp, p(xp), '')
    d_y = p.deriv()

    plt.clf()
    plt.plot(xp, p(xp), '-', color='green')
    plt.plot(w, p(w), '.', color='red', markersize=20)
    plt.xlim(-7, 7)
    plt.ylim(-5, 10)  

    grad = d_y(w)
    w -= alpha * grad

# アニメーション作成関数
def gradient_descent(alpha, w):
    fig, ax = plt.subplots(111)
    if type(w) is list:
        w = np.array(w, detype=np.float32)
    anim = animation.FuncAnimation(fig, animate, fargs=(w, alpha), frames=100, interval=300) 

    return anim

4. 시뮬레이션



그러면 학습률 alpha = 0.3, 가중치의 초기값 x = 3.5 로 시뮬레이션을 실행해 보겠습니다.
# 学習率0.3、重みの初期値3.5で実行
gradient_descent(alpha=0.3, w=np.array([3.5]))  


코드를 실행하면 이런 표시가 나타나므로 ▶︎ 버튼으로 재생해 보세요. 확률적이므로 잘 가지 않는 경우도 있습니다만, 몇번이나 시도하면 좋은 가감한 것이 나타납니다. 다양한 파라미터를 만나 보면 재미 있습니다.

 
능숙하게 실시한 예를 아래에 올려 둡니다 (학습률 alpha = 0.3, 가중치의 초기값 X = 3.5, 루프 재생). 좋은 가감한 기울기 계산은 로컬 솔루션 X = 4에 머물지 않고 최적 솔루션 X = 0에 도달합니다.

좋은 웹페이지 즐겨찾기