통계, IT, AI

딥러닝: 화풍을 모방하기 (4) - 연습: 회귀 문제 본문

머신러닝

딥러닝: 화풍을 모방하기 (4) - 연습: 회귀 문제

Harold_Finch 2017. 1. 30. 22:13

1. 개요

- 다음 파트로 넘어가기 전에 지금까지 배운 것을 구현하여 이해를 확실하게 하자. 

- 가장 간단한 경우부터 연습하기 위하여 변수가 1개인 회귀 문제를 선택한다. 즉, 신경망은 다음과 같다. 


그림 1. 회귀 모형의 신경망

- 출력층의 활성함수는 항등함수로 한다. 그러므로 u1=w11x1+b1이며 z1=f(u1)=u1이다. 

- 연습에 사용할 x1U(4,4)에서 200개를 생성한다. 

- 출력 dx11+ε이며 εN(0,1)를 따른다. 

- 데이터의 형태는 그림 2와 같다. 붉은 선은 연습에서 추정해야 할 파라미터를 나타낸다.

그림 2. 데이터의 형태

- minibatch를 사용하며 1개의 batch size는 20으로 하며 반복횟수(epoch)는 2,000으로 한다.

- 테스트 데이터는 연습데이터에서 임의로 20개를 골라 사용한다.

- 오차 함수는 제곱오차를 사용한다. 

E(w)=12i=1Ny(xi;w)di2


- 따라서 파라미터의 미분은 다음과 같다.


Ew=Ew11=iDt(y(xi;w)di)x1i,Eb=Eb1=iDt(y(xi;w)di)


2. 구현

- 파이썬을 사용하여 구현하며, numpy, matplotlib와 같은 패키지를 사전에 깔아둔다.

- 가능한 매트릭스 연산을 사용하여 코드를 간결하게 하며 계산 속도를 높인다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
 
""" GENERAL SETTING """
np.random.seed(0)
enable_visualization = True
 
 
""" DATA """
N = 200
x_1 = np.random.uniform(-4, 4, N)
W = np.array([-1, 1]).reshape((-1,1)) # uppercase of w is target parameter
d = np.column_stack(([1]*N,x_1)).dot(W) + np.random.normal(0, 1, N).reshape((N,1))
X = np.column_stack((x_1)).reshape((N,1))
 
test_data_index = np.random.randint(N, size=20)
test_x = X[test_data_index,]
test_d = d[test_data_index,]
 
if enable_visualization:
    plt.plot(x_1, d, 'bo')
    plt.plot(np.array([-4,4]), np.array([[1,-4],[1,4]]).dot(W), color='red')
    plt.show()
 
 
""" FUNCTION """
def activate(u, type='i'):
    if type == 'i':
        return u
 
def feedforward(X, w, b):
    X = np.column_stack(([1]*X.shape[0], X))
    w = np.vstack((b,w))
    return activate(X.dot(w))
 
def error(X, w, b, d, feedforward):
    return np.linalg.norm(feedforward(X, w, b) - d)**2/2
 
""" PARAMETER & OPTIMIZATION SETTINGS """
w = np.array([0.0]).reshape((-1,1))
b = np.array([0.0]).reshape((-1,1))
epsilon = 0.001
batch_size = 20  # number of samples in minibatch
epoch_size = 2000
 
error_history = [error(test_x, w, b ,test_d, feedforward)]
index_list = np.arange(0,N)
 
 
""" OPTIMIZATION """
for epoch in range(epoch_size):
    np.random.shuffle(index_list)
 
    for i in range(N//batch_size):
        training_index = index_list[(i*batch_size):((i+1)*batch_size)]
 
        training_x = X[training_index,]
        training_d = d[training_index,]
 
        # Caculate nabla E
        der_error = feedforward(training_x, w, b) - training_d
        der_w, der_b = np.mean(der_error*training_x, axis=0), np.mean(der_error, axis=0)
        der_w, der_b = np.asmatrix(der_w).reshape((-1,1)), np.asmatrix(der_b).reshape((-1,1))
 
        w -= epsilon * der_w
        b -= epsilon * der_b
 
    error_history.append(error(test_x, w, b ,test_d, feedforward))
 
 
""" RESULT """
if enable_visualization:
    # OPTIMIZATION
    plt.plot(x_1, d, 'bo')
    plt.plot(np.array([-4,4]),
             np.array([[1,-4],[1,4]]).dot(W), color='red')
    plt.plot(np.array([-4,4]),
             np.array([[1,-4],[1,4]]).dot(np.vstack((b,w))), color='green')
    plt.show()
 
    # ERROR HISTORY
    plt.plot(error_history)
    plt.show()
 
print( b, w)



3. 결과

- bw11의 추정치는 각각 -1.11, 0.95이며 아래 그림의 초록 선으로 나타낼 수 있다.

그림 3. 학습 결과

- 아래는 반복 횟수에 따른 테스트오차의 경향이다. 500회를 반복하기 전에 학습을 끝내도 됬다는 것을 알 수 있다. 

그림 4. 테스트 오차의 변화