텐서플로우의 예제를 통해서 매우 간단한 뉴럴 네트워크를 알아 봅시다.
앞서 접해본 [TensorFlow] 001. 맛보기와 내용이랑 유사합니다.
둘 다 y = ax + b 일 때, a와 b를 구하는 방법입니다.
하지만 이 예제의 경우, 구해야 하는 a, b를 weights라는 matrix(2x1) 변수로 선언하고, 임의의 표준정규분포 값을 받아서 그 값에서 a와 b를 유추하는 방식으로 진행됩니다.
아! 그리고 도표를 그리기 시작했습니다. 데이터를 인포그래픽으로 보는 일은 즐거운 일입니다.
학습 데이터로 x와 y가 주어졌을때, 가중치(weights)로 할당되어 있는 a와 b의 최적의 값을 구해 봅시다. |
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt %matplotlib inline num_examples = 50 # -2에서 4까지, -6에서 6까지 50(num_examples)단계로 꾸준히 증가하는 값을 받아서 2개의 배열로 저장 (직선 상태) X = np.array([np.linspace(-2, 4, num_examples), np.linspace(-6, 6, num_examples)]) # 꾸준히 증가하는 X 배열에 표준정규분포 값을 각각 넣어줌 (데이터 분산 발생) X += np.random.randn(2, num_examples) x, y = X # x 배열 값에 1을 붙여서 x_with_bias 생성 (1을 붙인 이유는 가중치(weights에서 b, a를 사용할 때, b를 그대로 보존하기 위함) y = b*1 + ax = ax + b x_with_bias = np.array([(1., a) for a in x]).astype(np.float32) losses = [] training_steps = 50 learning_rate = 0.002 with tf.Session() as sess: # 입력은 x_with_bias(50x2) 사용 input = tf.constant(x_with_bias) # 타겟은 y를 전치행렬(1x50 → 50x1) 설정 target = tf.constant(np.transpose([y]).astype(np.float32)) # 가중치 출력 텐서의 모양은 (2x1)으로 정규분포의 분산 0, 표준편차 0.1을 가지는 임의의 값을 초기값으로 설정 weights = tf.Variable(tf.random_normal([2, 1], 0, 0.1)) # 모든 텐서 변수 초기화 tf.initialize_all_variables().run() # input(50x2)과 가중치 값(2x1)을 matrix multiple = yhat은 (50x1) 값이 됨, yhat = 학습 진행중인 데이터 yhat = tf.matmul(input, weights) # yhat(50x1)에서 target(50x1) 값을 뺀 값을 yerror로 설정 yerror = tf.sub(yhat, target) # 학습중인 weights와 실제 target의 차이의 손실값의 평균 (평균 - reduce_mean) loss = tf.reduce_mean(tf.nn.l2_loss(yerror)) # 경사하강법으로 loss가 최소값이 되도록 학습 설정 update_weights = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss) # 50회 학습 for _ in range(training_steps): # 반복적으로 경사하강법을 통해 텐서플로우 변수들을 업데이트 함 update_weights.run() losses.append(loss.eval()) # 학습이 종료되면 결과 값을 출력 betas = weights.eval() yhat = yhat.eval() # 그래프로 표현 # fig는 도표를 그릴 영역을 의미함. 도표가 1x2 형태로 가로로 2개 들어감 fig, (ax1, ax2) = plt.subplots(1, 2) # 도표간 거리는 0.3 plt.subplots_adjust(wspace=.3) # 그릴 영역의 사이즈는 가로 10, 세로 4 fig.set_size_inches(10, 4) # 첫번째 도표(ax1)에 입력에 따른 출력 값을 2차원 평면에 점으로 찍음 ax1.scatter(x, y, alpha=.7) # 첫번째 도표(ax1)에 최종 가중치(weights)를 적용했을 때, 예상되는 target 값을 기준으로 2차원 평면에 점으로 찍음 ax1.scatter(x, np.transpose(yhat)[0], c="g", alpha=.6) line_x_range = (-4, 6) # 첫번째 도표(ax1)에 x 값 -4에서 6사이에서 최종 가중치(weights)에 따른 직선 그래프를 그림 betas[0]은 b를 의미 betas[1]은 a를 의미 (yhat = b + a*input) ax1.plot(line_x_range, [betas[0] + a * betas[1] for a in line_x_range], "g", alpha=0.6) # 두 번째 도표(ax2)에 학습 진행에 따른 losses를 도식화) ax2.plot(range(0, training_steps), losses) ax2.set_ylabel("Loss") ax2.set_xlabel("Training steps") plt.show() |
y = ax + b 인 상황에서, 입력값 x(input)와 출력값 y(target)을 알고 있다. 이때 최적의 a와 b를 구해보자.
예를 들어 위와 같이 input(coefficient), target(constant) 값이 주어졌을때, x, y를 찾을 수 있다.
하지만, 표준정규분포에 의한 input과 target에 대하여 가장 근접 수렴하는 x, y 값을 찾고자 할 때, 학습(training)을 통해서 최적의 값을 찾을 수 있다.
이때 위 도표의 x와 y를 가중치(weights)로 가져가기 위해서는 y=ax+b에 준하는 행렬(matrix)을 설정해주면 됨. 따라서, b 값을 온전히 보전하기 위해 1을 이용함.