Tensorflow 2.0 Tutorial ch3.3.3 - 첫번째 신경망 네트워크, AND

Page content

공지

  • 본 Tutorial은 교재 시작하세요 텐서플로 2.0 프로그래밍의 강사에게 국비교육 강의를 듣는 사람들에게 자료 제공을 목적으로 제작하였습니다.
  • 강사의 주관적인 판단으로 압축해서 자료를 정리하였기 때문에, 자세하게 공부를 하고 싶은 반드시 교재를 구매하실 것을 권해드립니다.

  • 본 교재 외에 강사가 추가한 내용에 대한 Reference를 확인하셔서, 추가적으로 학습하시는 것을 권유드립니다.

Tutorial

이전 강의가 궁금하신 분들은 아래에서 선택하여 추가 학습 하시기를 바랍니다.

I. AND 연산의 기본 개념

AND 연산의 기본개념은 아래와 같습니다. 다른 프로그래밍과 다르지 않습니다.

입력1 입력2 AND 연산
거짓 거짓
거짓 거짓
거짓 거짓 거짓

파이썬에서는 참, 거짓을 나타내는 값은 True, False입니다. 그런데, 딥러닝의 주요 입력값은 정수(Integer)나 실수(float)입니다. 참과 거짓의 값을 출력하여 확인해봅니다.

print(int(True))
print(int(False))
1
0

참은 1로 출력하고 거짓은 0으로 출력한 것을 확인하였습니다. 다시 AND 연산 기본개념에 적용하면 아래와 같습니다.

입력1 입력2 AND 연산
1 1 1
1 0 0
0 1 0
0 0 0

이제 숫자로 된 네개의 입력과 출력(AND 연산)의 쌍이 생겼습니다. 이제 AND 연산을 할 수 있는 신경망 네트워크를 만들어봅니다.

# 본 예제
import tensorflow as tf
import numpy as np

import math
# 시그모이드 함수 정의
def sigmoid(x): 
  return 1 / (1 + math.exp(-x))

x = np.array([[1, 1], [1, 0], [0, 1], [0, 0]])
y = np.array([[1], [0], [0], [0]])
w = tf.random.normal([2], 0, 1)
b = tf.random.normal([1], 0, 1)
b_x = 1

for i in range(2000): 
  error_sum = 0

  for j in range(4): 
    output = sigmoid(np.sum(x[j] * w) + b_x * b)
    error = y[j][0] - output
    w = w + x[j] * 0.1 * error
    b = b + b_x * 0.1 * error
    error_sum += error

  if i % 200 == 199:
    print(i, error_sum)
199 -0.10664604227192419
399 -0.0643946715061894
599 -0.04600188172236917
799 -0.03567996639075575
999 -0.029089461092594807
1199 -0.024526551513673306
1399 -0.0211850336803021
1599 -0.018634950907257527
1799 -0.016626949381179347
1999 -0.01500491979044496

NumPy에 관한 내용은 여기에서는 생략합니다.

위에 가중치(w)에 적용된 수식은 다음과 같습니다. $$w = w + x[j] \times 0.1 \times error$$

여기서는 $x[j]\times0.1$ 부분의 계산을 빨리 하기 위해 NumPy Array를 활용했습니다.

II. NumPy VS List

여기에서 NumPy와 List를 혼동할 때가 많습니다. 메모리 연산 등에 비교하는 문서가 필요하면 Python Lists VS Numpy Arrays에서 확인 후 직접 코드 실행을 해서 익히기를 바랍니다.

딥러닝에서 확인하고 싶은 것은 왜 List 대신에 NumPy가 사용되는 것인지에 대한 내용입니다.

수식을 보면, 오차(error)가 먼저 계산되고 난 뒤, 가중치를 업데이트 하게 됩니다. 이 때 만약 리스트로 값이 이루어진다면, 오차가 0이거나 또는 음수 일 때는 Empty(빈)리스트가 반환될 것입니다.

print([1, 2, 3] * 2)
print([1, 2, 3] * 0)
print([1, 2, 3] * -1)
[1, 2, 3, 1, 2, 3]
[]
[]

또한 0.01과 같은 실수를 곱하면 다음과 같은 에러가 발생합니다.

print([1,2,3] * 0.01)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-4-31e359ec4ae9> in <module>()
----> 1 print([1,2,3] * 0.01)


TypeError: can't multiply sequence by non-int of type 'float'

반대로, NumPy array에 실수를 곱하면 어떨까요?

import numpy as np
print(np.array([1,2,3]) * 2)
print(np.array([1,2,3]) * 0)
print(np.array([1,2,3]) * -1)
print(np.array([1,2,3]) * 0.01)
[2 4 6]
[0 0 0]
[-1 -2 -3]
[0.01 0.02 0.03]

위에서 확인하는 것처럼 모두 출력되는 것을 확인할 수 있습니다. AND 연산의 수가 4배로 많아졌기 때문에 네트워크가 경사하강법으로 수렴하는데에는 더 많은 연산이 필요합니다. error_sum을 통해서 점점 줄어드는 것을 확인할 수 있습니다.

III. AND 네트워크의 평가

이렇게 학습시킨 네트워크가 정상적으로 작동하는지 평가해본다. 네트워크에 x의 각 값을 넣었을 때, 실제 출력이 기대출력인 y값에 얼마나 가까운지 다음 코드를 통해 확인한다.

for i in range(4): 
  print('X:', x[i], 'Y:', y[i], 'Output:', sigmoid(np.sum(x[i]*w)+b))
X: [1 1] Y: [1] Output: 0.9649695824038163
X: [1 0] Y: [0] Output: 0.024824442411186316
X: [0 1] Y: [0] Output: 0.024900221652718595
X: [0 0] Y: [0] Output: 2.359785345402601e-05

마지막 Output2.359785345402601e-05나오는 것은 일종의 과학적 표기법으로 실수를 가수와 지수로 표현하는 방법이다.

다음을 통해서 확인해본다.

print("{:.16f}".format(float("2.359785345402601e-05")))
0.0000235978534540

IV. 연습 파일

V. Reference

김환희. (2020). 시작하세요! 텐서플로 2.0 프로그래밍: 기초 이론부터 실전 예제까지 한번에 끝내는 머신러닝, 딥러닝 핵심 가이드. 서울: 위키북스.