-
Notifications
You must be signed in to change notification settings - Fork 4
/
neural_network_for_mnist.py
212 lines (169 loc) · 7.66 KB
/
neural_network_for_mnist.py
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# numpy provides arrays and useful functions for working with them
import numpy as np
# scipy.special for the sigmoid function expit()
import scipy.special
# scipy.ndimage for rotating image arrays
import scipy.ndimage
import matplotlib.pyplot as plt
import gzip
# neural network class definition
class NeuralNetwork:
#initial the neural network
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
# set number of nodes in each input, hidden, output layer
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
#self.wih = (np.random.rand(self.hnodes, self.inodes) - 0.5)
#self.who = (np.random.rand(self.onodes, self.hnodes) - 0.5)
self.wih = np.random.normal(0.0, pow(self.inodes, -0.5), (self.hnodes, self.inodes))
self.who = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes))
# learning rate
self.lr = learningrate
# 활성화 함수로 시그모이드 함수를 이용
self.activation_function = lambda x: scipy.special.expit(x)
self.inverse_activation_function = lambda x: scipy.special.logit(x)
pass
# train the neural network
def train(self, inputs_list, targets_list):
# 입력 리스트를 2차원 행렬로 변환
inputs = np.array(inputs_list, ndmin=2).T
targets = np.array(targets_list, ndmin=2).T
#은닉 계층으로 들어오는 신호를 계산
hidden_inputs = np.dot(self.wih, inputs)
#은닉 계층에서 나가는 신호를 계산
hidden_outputs = self.activation_function(hidden_inputs)
# 최종 출력 계층으로 들어오는 신호를 계산
final_inputs = np.dot(self.who, hidden_outputs)
# 최종 출력 계층에서 나가는 신호를 계산
final_outputs = self.activation_function(final_inputs)
# 오차는 (실제 값 - 계산 값)
output_errors = targets - final_outputs
# 은닉 계층의 오차는 가중치에 의해 나뉜 출력 계층의 오차들을 재조합해 계산
hidden_errors = np.dot(self.who.T, output_errors)
# 은닉 계층과 출력 계층 간의 가중치 업데이트
self.who += self.lr * np.dot((output_errors * final_outputs * (1.0 - final_outputs)), np.transpose(hidden_outputs))
# 입력 계층과 은닉 계층 간의 가충치 업데이트
self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0- hidden_outputs)), np.transpose(inputs))
pass
# query the neural network
def query(self, inputs_list):
# 입력 리스트를 2차원 행렬로 변환
inputs = np.array(inputs_list, ndmin=2).T
#은닉 계층으로 들어오는 신호를 계산
hidden_inputs = np.dot(self.wih, inputs)
#은닉 계층에서 나가는 신호를 계산
hidden_outputs = self.activation_function(hidden_inputs)
# 최종 출력 계층으로 들어오는 신호를 계산
final_inputs = np.dot(self.who, hidden_outputs)
# 최종 출력 계층에서 나가는 신호를 계산
final_outputs = self.activation_function(final_inputs)
return final_outputs
def backquery(self, targets_list):
# transpose the targets list to a vertical array
final_outputs = np.array(targets_list, ndmin=2).T
# calculate the signal into the final output layer
final_inputs = self.inverse_activation_function(final_outputs)
# calculate the signal out of the hidden layer
hidden_outputs = np.dot(self.who.T, final_inputs)
# scale them back to 0.01 to .99
hidden_outputs -= np.min(hidden_outputs)
hidden_outputs /= np.max(hidden_outputs)
hidden_outputs *= 0.98
hidden_outputs += 0.01
# calculate the signal into the hideen layer
hidden_inputs = self.inverse_activation_function(hidden_outputs)
# calculate the signal out of the input layer
inputs = np.dot(self.wih.T, hidden_inputs)
# scale them back to 0.01 to .99
inputs -= np.min(inputs)
inputs /= np.max(inputs)
inputs *= 0.98
inputs += 0.01
return inputs
# number of input, hidden and output nodes
input_nodes = 784
hidden_nodes = 200
output_nodes = 10
# learning rate is 0.01
learning_rate = 0.01
# create instance of neural network
n = NeuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 신경망 학습 시키기
# Train용 mnist 파일 open
with gzip.open("mnist_train.gz", 'r') as f:
training_data_list = [x.decode('utf8').strip() for x in f.readlines()]
f.close()
# 주기(epoch)란 학습 데이터가 학습을 위해 사용되는 횟수를 의미
epochs = 10
train_cnt = 0
for e in range(epochs) :
# 학습 데이터 모음 내의 모든 레코드 탐색
for record in training_data_list:
# 케로드를 쉽표에 의해 분리
all_values = record.split(',')
# 입력 값의 법위와 값 조정
inputs = (np.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
# 결과 값 생성 (실제 값인 0.99 외에는 모두 0.01)
targets = np.zeros(output_nodes) + 0.01
# all_values[0]은 이 레코드에 대한 결과 값
targets[int(all_values[0])] = 0.99
n.train(inputs, targets)
## create rotated variations
# rotated anticlockwise by 10 degrees
inputs_plusx_img = scipy.ndimage.interpolation.rotate(inputs.reshape(28,28), 10, cval=0.01, order=1, reshape=False)
n.train(inputs_plusx_img.reshape(784), targets)
# rotated clockwise by 10 degrees
inputs_minusx_img = scipy.ndimage.interpolation.rotate(inputs.reshape(28,28), -10, cval=0.01, order=1, reshape=False)
n.train(inputs_minusx_img.reshape(784), targets)
train_cnt += 1
if(train_cnt % 100 == 0):
print("epochs", e+1, "train count :", train_cnt)
pass
train_cnt = 0
pass
# 신경망 테스트
# Test 용 mnist 파일 open
with gzip.open("mnist_test.gz", 'r') as f:
test_data_list = [x.decode('utf8').strip() for x in f.readlines()]
f.close()
# 신경망의 성능의 지표가 되는 성적표를 아무 값도 가지지 않도록 초기화
scorecard = []
for record in test_data_list:
# 레코드를 쉼표에 의해 분리
all_values = record.split(',')
# 정답은 첫번째 값
correct_label = int(all_values[0])
#print(correct_label,"correct label")
# 입력 값의 범위와 값 조정
inputs = (np.asfarray(all_values[1:])/255.0*0.99) + 0.01
# 신경망에 질의
outputs = n.query(inputs)
# 가장 높은 값의 인덱스는 레이블의 인덱스와 일치
label = np.argmax(outputs)
#print(label,"network's answer")
# 정답 또는 오답을 리스트에 추가
if(label == correct_label):
# 정답인 경우 성적표에 1을 더함
scorecard.append(1)
else:
# 정답이 아닌경우 성적표에 0을 더함
scorecard.append(0)
pass
# 정답의 비율인 성적을 계산해 출력
scorecard_array = np.asarray(scorecard)
print("performance = ", scorecard_array.sum()/scorecard_array.size, "total", scorecard_array.size)
# run the network backwards, given a label, see what image it produces
# label to test
label = 0
# create the output signals for this label
targets = np.zeros(output_nodes) + 0.01
# all_values[0] is the target label for this record
targets[label] = 0.99
print(targets)
# get image data
image_data = n.backquery(targets)
# plot image data
image_array = image_data.reshape((28,28))
plt.imshow(image_array, cmap='Greys', interpolation=None)
plt.show()