11라인의 파이선 코드로 설명하는 신경망

By | 2020년 4월 26일
Table of Content

11라인의 파이선 코드로 설명하는 신경망

참조

머신 러닝 공부할 때 가장 많이 도움이 된 코드입니다.

코드

X = np.array([ [0,0,1],[0,1,1],[1,0,1],[1,1,1] ])
y = np.array([[0,1,1,0]]).T
syn0 = 2*np.random.random((3,4)) - 1
syn1 = 2*np.random.random((4,1)) - 1
for j in range(60000):
    l1 = 1/(1+np.exp(-(np.dot(X,syn0))))
    l2 = 1/(1+np.exp(-(np.dot(l1,syn1))))
    l2_delta = (y - l2)*(l2*(1-l2))
    l1_delta = l2_delta.dot(syn1.T) * (l1 * (1-l1))
    syn1 += l1.T.dot(l2_delta)
    syn0 += X.T.dot(l1_delta)

단지 11줄의 코드로 머신러닝을 설명하고 있습니다.

심지어 공식도 없고 뭐도 없습니다.

라인 1-2

머신 러닝은 알고있는 입력값과 출력값을 기반으로 인공지능망(network) 을 학습시키고, 학습된 망(network) 을 이용해 새로운 입력값이 출력값을 생성하는 방식입니다.

import numpy as np

X = np.array([
    [0,0,1],
    [0,1,1],
    [1,0,1],
    [1,1,1]
])
y = np.array([
    [0,1,1,0]
]).T

print(y)

위에서 4개의 입력값(X) 과 4개의 출력값(y) 이 있습니다.

입력값 [0,0,1] 에 대해 출력값 0, 입력값 [0,1,1] 에 대해 출력값 1 등이 대응합니다.

라인 3-4

syn0 = 2*np.random.random((3,4)) - 1
syn1 = 2*np.random.random((4,1)) - 1

랜덤값으로 신경망을 초기화합니다.

Xy 사이에 -1 ~ 1 사이의 랜덤값으로 구성된 행렬을 배치합니다. 학습은 이 랜덤값을 적절한 값으로 교정해 나가는 과정입니다.

라인 5-7

for j in xrange(60000):
    l1 = 1/(1+np.exp(-(np.dot(X,syn0))))
    l2 = 1/(1+np.exp(-(np.dot(l1,syn1))))

위 내용을 함수를 생성해서 정리해 봅니다.

# sigmoid function
def nonlin(x,deriv=False):
    if(deriv==True):
        return x*(1-x)
    return 1/(1+np.exp(-x))

for j in range(60000):
    # forward propagation
    l0 = X
    l1 = nonlin(np.dot(l0,syn0))
    l2 = nonlin(np.dot(l1,syn1))

X 를 첫번째 레이어 l0 에 대입합니다.
l0syn0 과 도트연산 후 sigmoid 함수에 입력합니다.
다시, l1syn1 과 도트연산 후 sigmoid 함수에 입력합니다.

라인 8-9

for j in range(60000):
    # ......
    l2_delta = (y - l2)*(l2*(1-l2))
    l1_delta = l2_delta.dot(syn1.T) * (l1 * (1-l1))

위 내용도 다시 풀어 봅니다.

for j in range(60000):
    # how much did we miss?
    l2_error = y - l2
    l2_delta = l2_error * nonlin(l2,True)
    l1_delta = l2_delta.dot(syn1.T) * nonlin(l1,True)

y - l2 로 출력값과 계산값의 오차를 구합니다.
랜덤값으로 연산을 했으므로 당연히 오차가 발생합니다.

라인 10-11

위에서 구한 델타값을 이용해 신경망을 교정합니다.

for j in range(60000):
    # ......
    syn1 += l1.T.dot(l2_delta)
    syn0 += X.T.dot(l1_delta)

테스트 하기

위의 신경망이 정상적으로 업데이트 되었는지 확인해 봅니다.

이미 알고있는 [1,1,1] 값을 이용해 0 이 출력되는지 확인해 봅니다.

아직 알지 못하는 [1,1,0] 값을 입력해 결과값을 예측해봅니다.

X_test = np.array([
    [1,1,1],
    [1,1,0]
])

l0 = X_test
l1 = nonlin(np.dot(l0,syn0))
l2 = nonlin(np.dot(l1,syn1))

print(l2)

[[0.00284545]
 [0.99835627]]

정확히 0 이 아니라 0.00284545 이 출력됩니다.

답글 남기기