[신경망] MNIST 데이터를 이용한 CNN모델 코드

2020. 4. 23. 17:32노트/Python : 프로그래밍

 

텐서플로우 기반 

 

데이터 불러오기 

 

import random 
from tensorflow.examples.tutorials.mnist import input_data

mnist=input_data.read_data_sets("MNIST_data/", one_hot=True)

# 하이퍼 퍼러미터 
lr = 0.001 
epochs = 15
batch_size = 100

 

계층 생성 

 

# 하이퍼 퍼러미터 
lr = 0.001 
epochs = 15
batch_size = 100

#그래프초기화 ( 변수선언 위에다 입력해야함) 
tf.reset_default_graph()

# 입력층 
keep_prob = tf.placeholder(tf.float32) # drop-out 추가 
x = tf.placeholder(tf.float32, [None,28*28])
xlmg=tf.reshape(x,[-1,28,28,1]) 
y = tf.placeholder(tf.float32, [None,10])

# 히든 1 ( w1=filter )
w1 = tf.Variable(tf.random_normal([3,3,1,32])) 
# 필터의 높이:3와 넓이:3, 채널의 갯수:1, 필터의 갯수:32 
# conv -> (?,28,28,32)
# relu -> (?,28,28,32)
# pool -> (?,14,14,32)
L1= tf.nn.conv2d(xlmg, w1, strides=[1,1,1,1], padding="SAME")
# 활성화 함수 통과 
L1 = tf.nn.relu(L1)
# Pooling 
L1=tf.nn.max_pool(L1, ksize=[1,2,2,1], strides= [1,2,2,1], padding="SAME") 
#(2,2) :윈도우 크기 
L1=tf.nn.dropout(L1,keep_prob=keep_prob)

#히든 2
w2 = tf.Variable(tf.random_normal([3,3,32,64])) 
# conv -> (?,14,14,64)
# relu -> (?,14,14,64)
# pool -> (?,7,7,64)
# flat -> (?, 3136)
L2 = tf.nn.conv2d(L1, w2, strides=[1,1,1,1], padding="SAME")
L2 = tf.nn.relu(L2)
L2 = tf.nn.max_pool(L2, ksize=[1,2,2,1], strides= [1,2,2,1], padding="SAME") 
L2=tf.nn.dropout(L2,keep_prob=keep_prob)


L2_flat= tf.reshape(L2,[-1,7*7*64])

# 마지막계층  FC 7*7*64 -> 10 output 
W3 = tf.get_variable("w3",shape=[7*7*64, 10], initializer=tf.contrib.layers.xavier_initializer())

b = tf.Variable(tf.random_normal([10]))

함수 정의  및 모델 생성 

hf = tf.matmul(L2_flat, W3) + b 

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits = hf , labels= y))
opt = tf.train.AdamOptimizer(lr).minimize(cost)

 

모델 실행 

sess=tf.Session()
sess.run(tf.global_variables_initializer())

for epoch in range(epochs):
    avgCost = 0 
    totalBatch= int(mnist.train.num_examples/batch_size)
    for i in range(totalBatch):
        batchX, batchY = mnist.train.next_batch(batch_size)
        fd = {x:batchX, y:batchY, keep_prob:0.7}
        cv,_=sess.run([cost, opt], feed_dict=fd)
        avgCost+=cv/totalBatch
    print("epoch:","%04d" %(epoch + 1 ), "cost=",avgCost)
pred= tf.equal(tf.argmax(hf,1), tf.argmax(y,1))    
acc = tf.reduce_mean(tf.cast(pred, tf.float32))
print("accuracy:", sess.run(acc, feed_dict={x:mnist.test.images, y:mnist.test.labels , keep_prob:1}))
# accuracy: 0.9853 (keep_prob 추가 안 했을 때, )
# accuracy: 0.9839 (keep_prob 추가 했을 때,)

epoch: 0001 cost= 4.443909129879689
epoch: 0002 cost= 0.9400658628683196
epoch: 0003 cost= 0.5079063882348551
epoch: 0004 cost= 0.35302575529214353
epoch: 0005 cost= 0.26660195535641473
epoch: 0006 cost= 0.21027934439945956
epoch: 0007 cost= 0.18708037155976703
epoch: 0008 cost= 0.16399812486319043
epoch: 0009 cost= 0.14049976978070006
epoch: 0010 cost= 0.13282363239210107
epoch: 0011 cost= 0.122104285933416
epoch: 0012 cost= 0.11527511923658573
epoch: 0013 cost= 0.11351769800710662
epoch: 0014 cost= 0.10328966909638512
epoch: 0015 cost= 0.09901341474869041
accuracy: 0.9841

 

케라스 기반  CNN모델

 

데이터 불러오기

from keras.datasets import mnist 
from keras.utils import np_utils
import numpy as np 
import sys 
import tensorflow as tf 


(xTrain, yTrain ), (xTest, yTest)= mnist.load_data()

print(xTrain.shape)
print(yTrain.shape)
print(xTest.shape)
print(yTest.shape)
>>>
(60000, 28, 28)
(60000,)
(10000, 28, 28)
(10000,)

import matplotlib.pyplot as plt

plt.imshow(xTrain[0], cmap="Greys")
plt.show()

for x in xTrain[0]: 
    for i in x:
        sys.stdout.write("%d\t" % i)
    sys.stdout.write("\n") #표준출력장치 (모니터)로 출력하여라 

 

 

(xTrain, yTrain ), (xTest, yTest)= mnist.load_data()

xTrain=xTrain.reshape(xTrain.shape[0],28,28,1)
xTrain=xTrain.astype("float64")
xTrain=xTrain/255

xTest=xTest.reshape(xTest.shape[0],28,28,1).astype("float64")/255

yTrain=np_utils.to_categorical(yTrain,10)
yTest=np_utils.to_categorical(yTest,10)

 

모델 구성 

from keras.models import Sequential
from keras.layers import Dense 
from keras.callbacks import ModelCheckpoint, EarlyStopping
import numpy as np 
import tensorflow as tf 
import os
from keras.layers import *

model = Sequential()
model.add(Conv2D(32, kernel_size=(3,3) , input_shape = (28,28,1), activation = 'relu')) 
#Conv2D(필터갯수, 필터크기 ,(행,열,흑백),활성화함수)
model.add(Conv2D(64, (3,3), activation = 'relu')) 
model.add(MaxPooling2D(pool_size=2))
model.add(Dropout(0.25)) # 드롭아웃 비율 (25%)

"""
드롭아웃 (dropout)
- 오버피팅 감소 
- 히든계층의 노드 중 일부를 선택하여 학습하는 기법 
- 학습데이터에 지나치게 치우쳐서 학습되는 과적합을 방지 

"""
# Flatten(): 1치원으로 변경하는 함수 
model.add(Flatten())

model.add(Dense(128,activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))



# 모델 환경설정 
model.compile(loss="categorical_crossentropy", 
             optimizer = "adam",
             metrics=['accuracy'])
          
          
#모델 최적화 기록
modelDir = './myCnnModel/'
if not os.path.exists(modelDir):  # 만약 myModel directory가 존재하지 않는다면 
    modelPath = "./myCnnModel/{epoch:02d}-{val_loss:.4f}.hdf5"
    os.mkdir(modelDir)

checkpointer = ModelCheckpoint(filepath=modelPath, monitor = 'val_loss', verbose=1 , save_best_only=True )
# ModelCheckpoint: 콜백함수 : 어떤 상황이 되면 시스템에 의해서 호출되는 함수 , 
#                 keras에서 모델을 학습할 때마다 중간중간에 콜백형태로 알려줌 
# save_best_only: 모델의 정확도가 최고값을 갱신할때만 저장 
es = EarlyStopping(monitor='val_loss', patience=10)

 

모델 실행 

history= model.fit(xTrain, yTrain,validation_data=(xTest,yTest),
                   epochs=30, batch_size=200, callbacks=[es,checkpointer])

 

모델 평가 

print("테스트 정확도: %.4f" %(model.evaluate(xTest,yTest)[1]))

10000/10000 [==============================] - 3s 311us/step
테스트 정확도: 0.9938

 

# 테스트 셋의 오차 
yVloss = history.history['val_loss']
# 학습 셋의 오차 
yLoss=history.history['loss']

%matplotlib notebook
xLen = np.arange(len(yLoss))
plt.plot(xLen, yVloss, marker=".", c="red", label="testset_loss")
plt.plot(xLen, yLoss, marker=".", c="blue", label="trainset_loss")
plt.legend()
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

 

모델 사용 

# 모델 예측하기
import pandas as pd

index=[]
ori=[]
pred=[]

for i in range(0, xTest.shape[0]):
    if np.argmax(yHat[i]) != np.argmax(yTest[i]):
        index.append(i)
        ori.append(np.argmax(yTest[i]))
        pred.append(np.argmax(yHat[i]))
res=pd.DataFrame({"label":ori, 
                  "predict":pred},
                 index=index)
print(res)

      label  predict
321       2        7
340       5        3
359       9        4
445       6        0
659       2        1
...     ...      ...
9664      2        7
9692      9        7
9729      5        6
9770      5        0
9839      2        7

[62 rows x 2 columns
# 예측이 틀린 이미지를 8개 정도 출력 
# label : 9, prediction : 4 

ver=res.sample(n=16).index

%matplotlib notebook
cnt=0
for n in ver:
    cnt+=1
    plt.subplot(4,4,cnt)
    plt.imshow(xTest[n].reshape(28,28), cmap='Greys')
    t="label:"+str(res['label'][n])+"pred:"+str(res['predict'][n])
    plt.title(t)
plt.tight_layout()
plt.show()

 

 

 

 

케라스 기반 분류 (CNN모델 아님) 

2020/04/21 - [노트/Python : 프로그래밍] - [텐서플로우/케라스] MNIST 숫자 분류하기 (softmax)