도서 : 신경망 첫걸음(한빛미디어)
지음 : 타리크라시드(송교석 옮김)
- 기본적인 숫자들을 그래프의 그림형태로 나타내 보겠습니다. MNIST 손글씨 데이터는 책 안의 내용에서 찾을 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14 |
import numpy
import matplotlib.pyplot
%matplotlib inline
#데이터를 불러오고 그 파일을 읽는다.
data_file = open("mnist_train_100.txt",'r')
data_list = data_file.readlines()
data_file.close()
all_values = data_list[0].split(',') #split는 구분자로 사용할 기호를 그 매개변수로 가진다. 리스트를 불러와서 쉼표로 구분하여 분리
#asfarray는 문자열을 실수로 변환한 다음에 그 숫자로 구성된 배열을 생성한다.
#reshape((28,28))함수는 784개의 어레이 숫자들을 28 x 28 형태의 정방 행렬로 만들어 준다
image_array = numpy.asfarray(all_values[1:]).reshape((28,28)) #리스트의 원소중 가장 첫 번째 원소는 이 원소들이 무엇을 표현하는 것인지를 알려주는 것이기 때문에 빼준다.
matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None') #imshow를 이용해 어레이를 시각화 |
cs |
-
결과
-
MNIST 학습 데이터 준비하기
-
현재 학습 데이터들의 값은 0~255의 값이므로 이를 255로 나눈 후 0.99를 곱하고 0.01을 더해 0.01 ~ 1.0의 범위로 만들겠습니다.
1
2 |
scaled_input = (numpy.asfarray(all_values[1:])/255.0*0.99)+0.01
print(scaled_input) |
cs |
-
우리가 신경망에 바라는 바는 이미지를 분류해 정확한 레이블을 할당하는 것입니다. 레이블은 0~9까지 10개 숫자 중 하나입니다. 다시 말해 10개의 노드로 구성된 출력 계층이 필요하고, 각 노드는 가능한 결과 값, 즉 각 레이블에 해당할 것입니다.
-
우리는 0.01~ 0.99사이의 값을 결과로 가지고자 합니다. 각 원소들의 첫 번째 값을 targets의 인덱스로 두고 그 값을 0.99로 정해주면 그 원소에 해당하는 노드의 값을 0.99로 설정해 준 것이 됩니다.
-
이를 바탕으로 우리는 0~9까지의 숫자를 구분지어 줄 수 있으며 이전에 만든 인공신경망을 사용해 이를 학습시킬 수 있게 됩니다.
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 |
import numpy
import scipy.special
import matplotlib.pyplot
%matplotlib inline
#신경망 클래스의 정의
class neutalNetwork:
#신경망 초기화하기
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
#입력, 은닉, 출력 계층의 노드 개수 설정
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
#가중치 행렬 wih와 who -> 정규분포의 중심은 0.0으로 설정, 표준편차는 노드로 들어오는 연결 노드의 개수에 루트를 씌우고 역수를 취함(pow함수)
#배열 내 가중치는 w_i_j로 표기. 노드 i에서 다음 계층의 j로 연결됨을 의미
#w11 w21
#w12 w22 등
self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
#학습률
self.lr = learningrate
#활성화 함수는 시그모이드 함수를 이용
self.activation_function = lambda x: scipy.special.expit(x)
pass
#신경망 학습시키기
def train(self, inputs_list, targets_list) :
#입력 리스트를 2차원의 행렬로 변환
inputs = numpy.array(inputs_list, ndmin=2).T
targets = numpy.array(targets_list, ndmin=2).T
#은닉 계층으로 들어오는 신호를 계산
hidden_inputs = numpy.dot(self.wih, inputs)
#은닉 계층에서 나가는 신호를 계산
hidden_outputs = self.activation_function(hidden_inputs)
#최종 출력 계층으로 들어오는 신호를 계산
final_inputs = numpy.dot(self.who, hidden_outputs)
#최종 출력 계층에서 나가는 신호를 계산
final_outputs = self.activation_function(final_inputs)
#오차는 (실제 값 - 계산 값)
output_errors = targets - final_outputs
#은닉 계층의 오차는 가중치에 의해 나뉜 출력 계층의 오차들을 재조합해 계산
hidden_errors = numpy.dot(self.who.T, output_errors)
#은닉 계층과 출력 계층 간의 가중치 업데이트
self.who += self.lr*numpy.dot((output_errors*final_outputs*(1.0 - final_outputs)), numpy.transpose(hidden_outputs))
#입력 계층과 은닉 계층 간의 가중치 업데이트
self.wih += self.lr*numpy.dot((hidden_errors*hidden_outputs*(1.0 - hidden_outputs)), numpy.transpose(inputs))
pass
#신경망에 질의하기
def query(self, inputs_list):
#입력 리스트를 2차원 행렬로 변환
inputs = numpy.array(inputs_list, ndmin=2).T
#은닉 계층으로 들어오는 신호를 계산
hidden_inputs = numpy.dot(self.wih, inputs)
#은닉 계층에서 나가는 신호를 계산
hidden_outputs = self.activation_function(hidden_inputs)
#최종 출력 계층으로 들어오는 신호를 계산
final_inputs = numpy.dot(self.who, hidden_outputs)
#최종 출력 계층에서 나가는 신호를 계산
final_outputs = self.activation_function(final_inputs)
return final_outputs
#입력, 은닉, 출력 노드의 수
input_nodes = 784 #손글씨 숫자 이미지를 구성하는 픽셀이 28x28의 크기를 가지기 때문
hidden_nodes = 100 #입력 값의 수보다 작은 값을 선택함으로써 신경망이 주요 특징을 찾아낸다, 너무 적은 수의 은닉 계층 노드를 선택한다면 제한적이 될 수도 있다
output_nodes = 10 #0~9까지의 레이블을 구분해야 하므로 출력은 10개면 충분하다.
#학습률은 0.3으로 정의
learning_rate = 0.3
#신경망의 인스턴스를 생성
n = neutalNetwork(input_nodes,hidden_nodes,output_nodes,learning_rate)
#데이터를 불러오고 그 파일을 읽는다.
training_data_file = open("mnist_train_100.txt",'r')
training_data_list = training_data_file.readlines()
training_data_file.close()
#신경망 학습시키기
#학습 데이터 모음 내의 모든 레코드 탐색
for record in training_data_list:
#레코드를 쉼표에 의해 분리
all_values = record.split(',') #split는 구분자로 사용할 기호를 그 매개변수로 가진다. 리스트를 불러와서 쉼표로 구분하여 분리
#입력 값의 범위와 값 조정
inputs = (numpy.asfarray(all_values[1:])/255.0*0.99)+0.01
#결과 값 생성 (실제 값인 0.99 외에는 모두 0.01)
targets = numpy.zeros(output_nodes) + 0.01
#all_values[0]은 이 레코드에 대한 결과 값
targets[int(all_values[0])] = 0.99
n.train(inputs,targets)
pass |
cs |
- 이 소스를 실행시켰다면 신경망이 학습되었을 것입니다.
- 이제 테스트를 해보도록 하겠습니다. 학습시킨 100개의 데이터가 아닌 10개의 데이터에서 값을 찾아 신경망에 넣고 정확한 결과가 나오는지 확인합니다.
- 먼저 데이터를 확인해 보겠습니다.
1
2
3
4
5
6
7
8
9 |
test_data_file = open("mnist_test_10.txt",'r')
test_data_list = test_data_file.readlines()
test_data_file.close()
all_values = test_data_list[0].split(',')
print(all_values[0])
image_array = numpy.asfarray(all_values[1:]).reshape((28,28))
matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None') |
cs |
- 결과는
- 그리고 우리가 학습시킨 인공 신경망에 질의를 하면?
1 |
n.query((numpy.asfarray(all_values[1:])/255.0*0.99)+0.01) |
cs |
- 레이블 7에 해당하는 결과 값이 가장 크다는 것을 알 수 있습니다. 학습데이터와는 전혀다른 손글씨를 구분한 것입니다.
- 이번에는 10개의 테스트 데이터를 인공 신경망이 잘 구분하는지 확인해 보겠습니다.
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 |
#신경망 테스트
#신경망의 성능의 지표가 되는 성적표를 아무 값도 가지지 않도록 초기화
scorecard = []
#테스트 데이터 모음 내의 모든 레코드 탐색
for record in test_data_list:
#레코드를 쉼표에 의해 분리
all_values = record.split(',')
#정답은 첫 번째 값
correct_label = int(all_values[0])
print(correct_label,"correct label")
#입력 값의 범위와 값 조정
inputs = (numpy.asfarray(all_values[1:])/255.0*0.99)+0.01
#신경망에 질의
outputs = n.query(inputs)
#가장 높은 값의 인덱스는 레이블의 인덱스와 일치
label = numpy.argmax(outputs)
print(label, "network's answer")
#정답 또는 오답을 리스트에 추가
if(label == correct_label):
#정답인 경우 성적표에 1을 더함
scorecard.append(1)
else:
#정답이 아닌 경우 성적표에 0을 더함
scorecard.append(0)
pass
pass
print(scorecard) |
cs |
- 일치하는 값은 10개 중 6개 입니다. 즉, 100개의 데이터로 학습시킨 인공 신경망은 60%의 정확도밖에 보이지 않는다는 말 입니다.
- 전체 데이터를 이용해 학습 및 테스트하기
- 이제부터는 좀 더 큰 학습 데이터와 테스트 데이터를 이용해 정확도를 확인해 보도록 하겠습니다.
- 책의 내용에 있는 깃허브에서 각각의 파일을 다운로드 한 후 폴더에 넣어줍니다.
- 그 후 파일명만 바꿔주면 됩니다.
1
2
3 |
#스코어 평균
scorecard_array = numpy.asarray(scorecard)
print("performance = ", scorecard_array.sum()/scorecard_array.size) |
cs |
- 약 95%의 정확도를 가질 수 있게 되었습니다.
'Deep-Learning > Deep-Learning 기초 지식' 카테고리의 다른 글
[신경망 첫걸음]나만의 손글씨 데이터 (0) | 2019.02.22 |
---|---|
[신경망 첫걸음]신경망의 개선 (0) | 2019.02.22 |
[신경망 첫걸음]실습 : 파이썬으로 인공 신경망 만들기 (0) | 2019.02.21 |
[신경망 첫걸음]데이터 준비하기 (0) | 2019.02.20 |
[신경망 첫걸음]가중치의 진짜 업데이트 (0) | 2019.02.20 |