딥러닝구조를 이용하여 MNIST, 즉 필기체손글씨를 인식할 수 있습니다.
np.loadtxt()함수를 이용하여 트레이닝데이터행렬을 만들 수 있습니다.
Train Data Set 과 Test Data Set 을 활용해보겠습니다.
학습데이터인 Train Data Set에는 총 6만개의 이미지데이터가 있습니다.
하나의 이미지는 28*28개로 총 784개의 숫자로 이루어져 있습니다.
위 Train Data Set 파일에서 처음 5라는 숫자는 정답 숫자에 대한 정보이고
그 이후로 784개의 숫자가 이미지를 나타내는 정보입니다. 픽셀 하나의 밝기값이라고 볼 수 있습니다.
0에 가까울수록 검은색이고 255에 가까울수록 밝은(흰)색입니다.
학습데이터에서는 하나의 이미지가 784개의 숫자를 가진 1차원 배열로 표현되지만
실제이미지는 28*28의 숫자를 가진 2차원 배열로 표현됩니다.
(입력층-은닉층-출력층)의 딥러닝 아키텍처로 다시 한번 복습해보겠습니다.
MNIST 인식을 위한 딥러닝 아키텍처
입력층 노드는 그림에서 보이듯 총 784개입니다.(이미지를 나타내는 정보의 숫자들)
트레이닝데이터에서 하나의 레코드, 즉 하나의 행은 1열의 정답을 제외하면 2열부터 785열까지 784개입니다.
총 784개의 픽셀값이 정답 이미지 정보를 나타냅니다.( 위 내용과 같은 내용)
은닉층 노드개수는 제한이 없습니다.(임의로 30개로 설정)
출력층 노드의 개수는 원핫인코딩 기법을 사용하기 위해 10개입니다. 정답은 0부터 9까지의 숫자 중 하나이므로 10개의 노드로 구성된 출력층이 필요합니다.
원핫인코딩(One-Hot Encoding)
출력층 노드에서 최댓값을 가지는 노드의 인덱스값을 정답으로 판단하는 기법입니다.
0~9 사이의 숫자 중 어느것인지 분류해내는 방법입니다.
(선형회귀 Classification개념에서 확률값이 가장 높은 것=해당인덱스(숫자)일 확률이 가장 높은 것)
(이는 기존의 Logistic Regression에서 사용하는 0또는 1이라는 이분법적 Classification 방법을 보완했습니다.)
그림에서 보이듯 1차원 배열에서 각각 숫자일 확률을 기록하고 그 확률이 가장 높은 것을 정답으로 취급합니다.
파이썬 코드로 구현해보겠습니다.
import numpy as np
train_data=np.loadtxt("mnist_train.csv",delimiter=',',dtype=np.float32)
test_data=np.loadtxt("mnist_test.csv",delimiter=',',dtype=np.float32)
print("load data")
def sigmoid(x):
return 1/(1+np.exp(-x))
def numerical_derivative(f,input_data):
delta_x=1e-4
ret=np.zeros_like(input_data)
it=np.nditer(input_data, flags=['multi_index'])
while not it.finished:
idx=it.multi_index
tmp_val=input_data[idx]
input_data[idx]=float(tmp_val)+delta_x
fx1=f(input_data)
input_data[idx]=float(tmp_val)-delta_x
fx2=f(input_data)
ret[idx]=(fx1-fx2)/(2*delta_x)
input_data[idx]=tmp_val
it.iternext()
return ret
class NeuralNetwork:
def init(self,input_nodes, hidden_nodes, output_nodes):
self.input_nodes=input_nodes #784개
self.hidden_nodes=hidden_nodes #100개
self.output_nodes=output_nodes #10개
self.learning_rate=1e-3
#은닉층 가중치 W2 Xaiver/He방법으로 self.W2 가중치 초기화
self.W2=np.random.rand(input_nodes, hidden_nodes)/np.sqrt(self.input_nodes/2)
self.b2=np.random.rand(hidden_nodes)
#출력층 가중치 W3
self.W3=np.random.rand(hidden_nodes,output_nodes)/np.sqrt(self.hidden_nodes/2)
self.b2=np.random.rand(output_nodes)
self.data=np.array([])
self.one_hot=np.array([])
print("MNIST_Test object is created !!!")
def feed_forward(self):
delta=1e-7
z2=np.dot(self.data, self.W2)+self.b2
a2=sigmoid(z2)
z3=np.dot(a2, self.W3)+self.b3
a3=sigmoid(z3)
#cross-entropy
return -np.sum(self.one_hot*np.log(y+delta)+(1-self.one_hot)*np.log(1-y+delta))
def loss_val(self):
delta=1e-7
z2=np.dot(self.data, self.W2)+self.b2
a2=sigmoid(z2)
z3=np.dot(a2, self.W3)+self.b3
a3=sigmoid(z3)
return -np.sum(self.one_hot*np.log(y+delta)+(1-self.one_hot)*np.log(1-y+delta))
def predict(self, input_data):
z2=np.dot(input_data, self.W2)+self.b2
a2=sigmoid(z2)
z3=np.dot(a2,self.W3)+self.b3
a3=sigmoid(z3)
#MNIST one-hot encoding따라 0또는1이 아닌 argmax()통해 최대 인덱스 값을 넘겨줘야함
return np.argmax(y)
#정확도 측정 함수
def accuracy(self, test_data):
count=0
for index in range(len(test_data)):
label=int(test_data[index,0])
#정규화
data=test_data[index,1:]
predicted_val=self.predict(data)
if predicted_val==label:
count+=1
print("Accuracy=",100*(count/float(len(test_data))))
#수치미분 통해 loss값 최소될때까지 학습하는 함수
def train(self, train_data):
label=int(train_data[0])
self.data=(train_data[1:]/255.0*0.99)+0.01
self.one_hot=np.zeros(self.output_nodes)+0.01
self.one_hot[label]=0.99
f=lambda x:self.feed_forward()
self.W2=self.learning_rate*numerical_derivative(f,self.W2)
self.b2=self.learning_rate*numerical_derivative(f,self.b2)
self.W3=self.learning_rate*numerical_derivative(f,self.W3)
self.b3=self.learning_rate*numerical_derivative(f,self.b3)
mnist=NeuralNetwork(784,50,10)
for step in range(30001):
mnist.train(train_data[step])
if step%400==0:
print("step=",step,"loss_val=",mnist.loss_val())
mnist.accuracy(test_data)
이미지로 직접 보고싶다면 Matplotlib 모듈을 사용합니다.
아래와 같이 코드를 사용합니다.
import numpy as np
import matplotlib.pyplot as plt
train_data = np.loadtxt('mnist_train.csv', delimiter=',', dtype=np.float32)
test_data = np.loadtxt('mnist_test.csv', delimiter=',', dtype=np.float32)
print('load datas')
img=train_data[0][1:].reshape(28,28)
plt.imshow(img, cmap='gray')
plt.show()
이미지 결과입니다!
여기까지의 결과를 도출해내는 데에만 20시간이 넘는 학습시간이 소요되었습니다...
(중간에 컴퓨터가 배터리가 나가서 다시 학습을 하루종일 시켰어야 했습니다..)
엄청난 비효율성과 낭비죠.. 이를 보완하기 위해서 tensorflow(텐서플로)를 기반으로 한 딥러닝 아키텍처를 사용합니다.
훨씬 빠른 학습속도로 학습을 할 수 있도록 해줍니다.
'인공지능 AI' 카테고리의 다른 글
Tensorflow(텐서플로우) 설치와 기초 (0) | 2020.08.23 |
---|---|
[딥러닝/인공지능] 오차역전파(Back Propagation) (0) | 2020.06.07 |
[딥러닝/인공지능]딥러닝기초_피드포워드/XOR문제해결 (0) | 2020.06.06 |
[머신러닝/인공지능] 선형회귀_분류(Classification) (0) | 2020.06.06 |
[머신러닝/인공지능] 선형회귀 예제 _단일변수/다변수 (0) | 2020.06.06 |