본문 바로가기
기계학습/[밑바닥부터 시작하는 딥러닝]

4장 신경망 학습 코드 모음

by tryotto 2019. 8. 8.

1) 손실함수 - 평균 제곱 오차, 교차 엔트로피 오차

** 결괏값이 0에 가까울수록 (작을수록) 더 정확한 추측값이다

-> 추측값이 정확한지 아닌지를 확인하기 위한게 손실함수의 역할


** 원리 : 활성함수를 구한 값을, 손실 함수에 넣는다 (받는 값=활성함수 값, one-hot값) -> 정확도를 체크 -> 매개변수 수정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
 
def mean_squared_error(y,t):
    return 0.5*np.sum((y-t)**2)
 
def cross_entropy_error(y,t):
    delta = 1e-7
    return -np.sum(t*np.log(y+delta))
 
= np.array([0.10.050.60.00.050.10.00.10.00.0])
= np.array([0,0,1,0,0,0,0,0,0,0])
 
= mean_squared_error(y,t)
print(z)
 
z= cross_entropy_error(y,t)
print(z)
cs



2) 미니 배치학습


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
 
(x_train, t_train), (x_test, t_test)=load_mnist(normalize=True, one_hot_label=True)
 
train_size = x_train.shape[0]
batch_size = 10
batch_mask = np.random.choice(train_size, batch_size)
 
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
 
print(x_batch)
print(t_batch)
cs


3) 배치용 교차 엔트로피 오차 구현

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
import sys, os
sys.path.append(os.pardir)
import numpy as np
from dataset.mnist import load_mnist
 
def cross_entropy_error1(y,t):
    if y.ndim == 1 :
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
        
    batch_size = y.shape[0]
    return -np.sum(t*np.log(y))/batch_size
 
def cross_entropy_error2(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
 
    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arrange(batch_size), t])) / batch_size
 
(x_train, t_train), (x_test, t_test)=load_mnist(normalize=True, one_hot_label=True)
 
train_size = x_train.shape[0]
batch_size = 10
batch_mask = np.random.choice(train_size, batch_size)
 
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
 
print(x_batch)
print(t_batch)
cs


4) 수치 미분

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import numpy as np
import matplotlib.pylab as plt
 
def numerical_diff(f,x):
    h = 1e-4
    return (f(x+h)-f(x-h))/(2*h)
 
def func_1(x):
    return 0.01*x**2 + 0.1*x
 
= np.arange(0.020.00.1)
= func_1(x)
 
plt.xlabel("x")
plt.ylabel("f(x)")
plt.plot(x,y)
plt.show()
 
= numerical_diff(func_1, 5)
print(z)
= numerical_diff(func_1, 10)
print(z)
cs


5) 편미분


1
2
3
def func_2(x):
    return x[0]**2 + x[1]**2
 
cs


6) 기울기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
 
def func_2(x):
    return x[0]**2 + x[1]**2
 
def numerical_gradient(f,x):
    h = 1e-4
    grad = np.zeros_like(x)
 
    for idx in range(x.size):
        tmp_val = x[idx]
        x[idx] = tmp_val + h
        fxh1 = f(x)
 
        x[idx] = tmp_val - h
        fxh2 = f(x)
 
        grad[idx] = (fxh1 - fxh2)/(2*h)
        x[idx] = tmp_val
 
        print(grad)
    return grad
 
numerical_gradient(func_2, np.array([3.04.0]))
cs

7) 경사법 
- 핵심 원리 : 미분법 -> 미분 값을 이용해서, 다음 좌표를 얻어내기

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
import numpy as np
 
def numerical_gradient(f, x):
    h = 1e-4
    grad = np.zeros_like(x)
 
    for idx in range(x.size):
        tmp_val = x[idx]
        x[idx] = tmp_val + h
        fxh1 = f(x)
 
        x[idx] = tmp_val - h
        fxh2 = f(x)
 
        grad[idx] = (fxh1 - fxh2) / (2 * h)
        x[idx] = tmp_val
 
        print(grad)
    return grad
 
def gradient_descent(f, init_x, lr=0.1, step_num=100):
    x = init_x
 
    for i in range(step_num):
        grad = numerical_gradient(f, x)
        x -= lr*grad
 
    return x
 
def func_2(x):
    return x[0]**2 + x[1]**2
 
= gradient_descent(func_2,np.array([-3.04.0]), 0.1100)
print(z)
cs


8) 신경망에서의 기울기


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
import sys, os
sys.path.append(os.pardir)
import numpy as np
 
def cross_entropy_error(y,t):
    delta = 1e-7
    return -np.sum(t*np.log(y+delta))
 
def softmax(a):
    c = np.max(a)
 
    exp_a = np.exp(a - c)
    sum_exp_a = sum(exp_a)
 
    y = exp_a / sum_exp_a
 
    return y
 
 
class simpleNet:
    def __init__(self):
        self.W = np.random.randn(2,3)
 
    def predict(self, x):
        return np.dot(x, self.W)
 
    def loss(self, x, t):
        z = self.predict(x)
        y = softmax(z)
        loss = cross_entropy_error(y,t)
 
        return loss
 
net = simpleNet()
print(net.W)
 
= net.predict(np.array([0.60.9]))
print(p)
print(np.argmax(p))
print(net.loss(np.array([0.60.9]), np.array([001])))
cs


9) 2차 신경망 클래스 구현하기

** 정확도 구현 : 활성함수 확인 -> 그 중에서 가장 가능성 높은 인덱스 찾기 -> 해당 인덱스와 정답 레이블을 비교

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
import sys, os
sys.path.append(os.pardir)
import numpy as np
 
def sigmoid(x):
    return 1/(1+np.exp(-x))
 
def softmax(a):
    c = np.max(a)
 
    exp_a = np.exp(a - c)
    sum_exp_a = sum(exp_a)
 
    y = exp_a / sum_exp_a
 
    return y
 
def cross_entropy_error(y,t):
    delta = 1e-7
    return -np.sum(t*np.log(y+delta))
 
class TwoLayerNet:
    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        self.params = {}
        self.params['W1'= weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'= np.zeros(hidden_size)
        self.params['W2'= weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b2'= np.zeros(output_size)
 
    def predict(self, x):
        w1, w2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
 
        a1 = np.dot(x, w1)+b1
        z1 = sigmoid(a1)
 
        a2 = np.dot(z1, w2)+b2
        y = softmax(a2)
 
        return y
 
    def loss(self, x,t):
        y = self.predict(self, x)
 
        return cross_entropy_error(y,t)
 
    def accuracy(self, x, t):
        y = self.predict(self, x)
        y = np.argmax(y, axis=1)
        t = np.argmax(t, axis=1)
 
        accuracy = np.sum(y==t)/float(x.shape[0])
        return accuracy
 
    def numerical_gradient(self, x, t):
        loss_W = lambda W:self.loss(x,t)
        
        grads={}
        grads['W1'= self.numerical_gradient(loss_W, self.params['W1'])
        grads['b1'= self.numerical_gradient(loss_W, self.params['b1'])
        grads['W2'= self.numerical_gradient(loss_W, self.params['W2'])
        grads['b2'= self.numerical_gradient(loss_W, self.params['b2'])
        
        return grads
cs