이번 글부터 텐서플로우, 케라스를 이용해서 몇 가지 예제를 시도해 보겠습니다. 그러면 먼저 Tensorflow ,keras가 뭔지 알아야겠죠??
먼저 tensorflow 는 구글에서 개발한 머신러닝, 딥러닝용 프레임워크입니다. 특히 딥러닝에 많이 사용되는데 파이토치와 함께 가장 많이 사용되는 프레임 워크중 하나입니다.
케라스는 tensorflow를 공부하다보면 자연스레 듣게되는 단어인데, tensorflow가 처음 나왔을때는 다소 사용하기 어렵게 (매우...) 되어 있었기 때문에 사람들이 쉽게 딥러닝을 하기 힘들었습니다. 그래서 tensorflow의 기능들을 묶어주면서 좀더 편하게 사용할수있는 API를 만들어준것이 KERAS입니다. 즉 본질은 같으나, KERAS쪽이 좀더 사용하기 쉬운편이고 직관적입니다.
저는 텐서플로우를 직접 사용하는것보단 주로 KERAS코드를 많이 사용하는 편이여서 KERAS먼저 메인으로 진행을 하도록 하겠습니다!
MNIST는 인공지능 연구의 권위자 LeCun교수가 만든 데이터 셋이고 현재 딥러닝을 공부할 때 반드시 거쳐야할 Hello, World같은 존재입니다. MNIST는 60,000개의 트레이닝 셋과 10,000개의 테스트 셋으로 이루어져 있고 이중 트레이닝 셋을 학습데이터로 사용하고 테스트 셋을 신경망을 검증하는 데에 사용합니다.
모델링에 사용할 데이터를 가져오겠습니다.
from tensorflow.keras.datasets import mnist
import numpy as np
(x_train,y_train),(x_test,y_test) = mnist.load_data()
print(x_train.shape,x_test.shape)
print(y_train.shape,y_test.shape)
(60000, 28, 28) (10000, 28, 28) (60000,) (10000,)
위처럼 데이터를 불러올수 있습니다. 위의 코드에서 input data들은 (28,28) 이미지이고 라벨은 정수 타입입니다. 이미지들이 어떻게 생겼는지 간단하게 시각화 해보겠습니다.
import matplotlib.pyplot as plt
import random
for i in range(1,4,1):
for j in range(1,4,1):
plt.subplot(i,4,j)
plt.imshow(x_train[random.randint(0,60000)],cmap="gray")
plt.show()
시각화를 위해 matplotlib을 import 해주고 실행을 시켜주면 60000개의 이미지중에 랜덤하게 나옵니다. 이미지들을 살펴보면 흑백 이미지에 28,28 size네요 이제 모델에 넣기위해 간단한 처리를 몇가지 해줄겁니다.
from tensorflow.keras.utils import to_categorical
x_train = x_train.reshape(-1,28,28,1)/255.
x_test = x_test.reshape(-1,28,28,1)/255.
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
x_train,x_test에는 (28,28) -> (28,28,1) 로 모양을 변경해줬습니다. 이 작업을 해야 후에 Conv2D레이어에 인풋으로 넣을수 있기 때문입니다. 또한 0~255 값의 범위를 0~1로 바꿔줬습니다.
반면에 y_train,y_test 에는 to_categorical 이라는 함수를 사용해 줫는데 이는 onehot 벡터로 만들기 위함입니다.
예를들어, 5 -> [0,0,0,0,0,1,0,0,0,0] 0 -> [1,0,0,0,0,0,0,0,0,0] 이런식으로 값을 바꾸는 것입니다.
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,Flatten,BatchNormalization,Conv2D
tensorflow.keras에서 Sequential모델을 가져오는데 레이어들을 순차적으로 쌓을수 잇게해주는 모델입니다. 이번에는 Dense,Flatten,BatchNormalization,Conv2D 레이어를 이용해서 간단한 신경망을 구성해 보겠습니다.
model = Sequential()
model.add(Conv2D(32,(2,2),activation="relu",input_shape=(28,28,1)))
model.add(BatchNormalization())
model.add(Conv2D(64,(2,2),activation="relu"))
model.add(BatchNormalization())
model.add(Conv2D(128,(2,2),2,activation="relu"))
model.add(BatchNormalization())
model.add(Conv2D(32,(2,2),activation="relu"))
model.add(BatchNormalization())
model.add(Conv2D(64,(2,2),activation="relu"))
model.add(BatchNormalization())
model.add(Conv2D(128,(2,2),2,activation="relu"))
model.add(BatchNormalization())
model.add(Flatten())
model.add(Dense(128,activation="relu"))
model.add(Dense(10,activation="softmax"))
모델을 구성하고 나서 loss함수, optimizer 를 지정해 줘야합니다. 우리는 분류 작업을 하고있기 때문에 categorical_crossentropy로 해야하며 옵티마이저는 가장 무난한 adam을 사용하겠습니다. metrics=["acc"] 이부분은 accuracy 파라미터를 모니터링하기위해 넣어줍니다. 이후 model.fit 을 사용하여 모델을 훈련시킵니다.
model.compile(loss = "categorical_crossentropy",optimizer = "adam",metrics=["acc"])
history = model.fit(x_train,y_train,validation_data=(x_test,y_test),epochs=30,batch_size=256)
Epoch 1/30 235/235 [==============================] - 5s 10ms/step - loss: 0.1290 - acc: 0.9607 - val_loss: 1.5187 - val_acc: 0.5319 Epoch 2/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0333 - acc: 0.9898 - val_loss: 0.1008 - val_acc: 0.9690 Epoch 3/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0201 - acc: 0.9931 - val_loss: 0.0385 - val_acc: 0.9885 Epoch 4/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0121 - acc: 0.9960 - val_loss: 0.0349 - val_acc: 0.9910 Epoch 5/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0098 - acc: 0.9966 - val_loss: 0.0481 - val_acc: 0.9874 Epoch 6/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0087 - acc: 0.9970 - val_loss: 0.0447 - val_acc: 0.9887 Epoch 7/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0131 - acc: 0.9956 - val_loss: 0.0425 - val_acc: 0.9895 Epoch 8/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0069 - acc: 0.9976 - val_loss: 0.0372 - val_acc: 0.9906 Epoch 9/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0050 - acc: 0.9984 - val_loss: 0.0728 - val_acc: 0.9847 Epoch 10/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0046 - acc: 0.9985 - val_loss: 0.0567 - val_acc: 0.9886 Epoch 11/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0085 - acc: 0.9972 - val_loss: 0.0479 - val_acc: 0.9897 Epoch 12/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0108 - acc: 0.9966 - val_loss: 0.0727 - val_acc: 0.9835 Epoch 13/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0106 - acc: 0.9971 - val_loss: 0.0554 - val_acc: 0.9886 Epoch 14/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0046 - acc: 0.9985 - val_loss: 0.0463 - val_acc: 0.9895 Epoch 15/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0066 - acc: 0.9977 - val_loss: 0.0601 - val_acc: 0.9872 Epoch 16/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0043 - acc: 0.9986 - val_loss: 0.0515 - val_acc: 0.9902 Epoch 17/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0036 - acc: 0.9991 - val_loss: 0.0502 - val_acc: 0.9899 Epoch 18/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0022 - acc: 0.9993 - val_loss: 0.0625 - val_acc: 0.9900 Epoch 19/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0037 - acc: 0.9988 - val_loss: 0.0506 - val_acc: 0.9910 Epoch 20/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0066 - acc: 0.9980 - val_loss: 0.0665 - val_acc: 0.9877 Epoch 21/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0066 - acc: 0.9979 - val_loss: 0.0520 - val_acc: 0.9897 Epoch 22/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0030 - acc: 0.9989 - val_loss: 0.0642 - val_acc: 0.9884 Epoch 23/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0048 - acc: 0.9986 - val_loss: 0.0741 - val_acc: 0.9871 Epoch 24/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0049 - acc: 0.9983 - val_loss: 0.0676 - val_acc: 0.9883 Epoch 25/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0058 - acc: 0.9984 - val_loss: 0.0765 - val_acc: 0.9862 Epoch 26/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0047 - acc: 0.9984 - val_loss: 0.0489 - val_acc: 0.9899 Epoch 27/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0022 - acc: 0.9993 - val_loss: 0.0484 - val_acc: 0.9917 Epoch 28/30 235/235 [==============================] - 2s 9ms/step - loss: 0.0021 - acc: 0.9993 - val_loss: 0.0498 - val_acc: 0.9918 Epoch 29/30 235/235 [==============================] - 2s 9ms/step - loss: 5.7418e-04 - acc: 0.9998 - val_loss: 0.0502 - val_acc: 0.9925 Epoch 30/30 235/235 [==============================] - 2s 9ms/step - loss: 7.4288e-04 - acc: 0.9997 - val_loss: 0.0465 - val_acc: 0.9927
loss = history.history["loss"]
acc = history.history["acc"]
val_loss = history.history["val_loss"]
val_acc = history.history["val_acc"]
plt.subplot(1,2,1)
plt.plot(range(len(loss)),loss,label = "Train Loss")
plt.plot(range(len(val_loss)),val_loss,label = "Validation Loss")
plt.grid()
plt.legend()
plt.subplot(1,2,2)
plt.plot(range(len(acc)),acc,label = "Train Accuracy")
plt.plot(range(len(val_acc)),val_acc,label = "Validation Accuracy")
plt.grid()
plt.legend()
plt.show()
훈련후 Train_loss,Train_accuracy, validation_loss, validation accuracy 를 시각화 하였습니다.
위의 결과로 볼때 안정적으로 수렴 하였으며 accuracy 기준으로는 마지막 epoch에서 가장 높은 0.9925 가 나왔네요. 더 훈련진행이 가능하지만 이정도에서 마무리하고 실제로 결과를 예측해보겠습니다.
이제 훈련한 모델로 간단한 예측을 진행해 보겠습니다.
index =random.randint(0,9999)
plt.imshow(x_test[index],cmap="gray")
predict = model.predict(x_test[index].reshape(1,28,28,1))
print("Actual : {}\tPredict : {}".format(np.argmax(y_test[index]),np.argmax(predict)),)
Actual : 6 Predict : 6
위의 코드는 실행할떄마다 임의의 예측값을 반환합니다. validation_accuracy 값이 99% 나왔기때문에 잘 훈련된 것으로 볼 수 있습니다.
wrong_index_list=[]
predict = model.predict(x_test)
for index in range(10000):
if np.argmax(y_test[index]) != np.argmax(predict[index]):
wrong_index_list.append(index)
print(wrong_index_list)
print("총 틀린 갯수 : ",len(wrong_index_list))
[193, 321, 340, 445, 582, 619, 646, 947, 1014, 1039, 1112, 1156, 1226, 1232, 1242, 1247, 1414, 1522, 1549, 1678, 1681, 1709, 1737, 1901, 2035, 2118, 2130, 2185, 2189, 2293, 2597, 2654, 2896, 2927, 2939, 2953, 3030, 3225, 3422, 3475, 3520, 3727, 3780, 3808, 3941, 3968, 4027, 4078, 4176, 4284, 4289, 4443, 4504, 4639, 4740, 4761, 4807, 4860, 5937, 5955, 6166, 6574, 6576, 6597, 7216, 8527, 9009, 9015, 9024, 9638, 9664, 9729, 9905] 총 틀린 갯수 : 73
틀린것들을 랜덤하게 보여주는 코드가 아래 있습니다. 여러번 실행해보면서 느낀건데 틀릴만 한 거같은 숫자들도 간혹 있는것 같아요.
new_index = random.choice(wrong_index_list)
plt.imshow(x_test[new_index],cmap="gray")
print("Actual : {}\tPredict : {}".format(np.argmax(y_test[new_index]),np.argmax(new_index)),)
Actual : 7 Predict : 0
Keras Callbacks (Model_CheckPoint,Early_Stopping,ReduceLROnPlateau) (0) | 2022.01.01 |
---|---|
CIFAR_10 (0) | 2021.12.19 |
Convolution Neural Network(CNN) (0) | 2021.12.03 |
Keras FCN Network (0) | 2021.11.28 |
댓글 영역