AI 이론/딥러닝 이론

[이미지 분류 모델링] Flatten(), softmax, evaluate(), sparse_categorical_crossentropy

jasonshin 2021. 12. 1. 11:16

1. 이미지와 행렬, Gray scale image, Colored image

그림 => 행렬로 표현

0~ 255까지의 숫자를 저장할 수 있는 데이터프레임 unsigned int => uint8

1개 행렬 => gray scaled 
R,G,B 3개 행렬 => colored image

Start Coding

import tensorflow as tf
print(tf.__version__)
 
Fashion MNIST 데이터는 tf.keras datasets API에 들어있다.
 
mnist = tf.keras.datasets.fashion_mnist
 
트레이닝과 테스트셋 가져온다.
(X_train, y_train),(X_test,y_test) = mnist.load_data()
X_train

array([[[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], ..., [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]]], dtype=uint8)

 

이미지는 숫자로 되어있다. 0부터 255까지의 숫자로 되어있다.

X_train.shape 

(60000, 28, 28) # 28행 28열 짜리 사진이 6만장 있다는 뜻. 

 

# 첫번째 이미지를 가져오는 코드
X_train[0]
X_train[0].shape

(28, 28)

 

X_train[0].dtype
(28, 28)
 
 
X_train[0].ndim
2
 
 
 
import matplotlib.pyplot as plt
plt.imshow(X_train[0], cmap='gray')
plt.show()

y_train.shape
(60000,)
y_train[0]
9

 

2. 이미지를 피져 스케일링하는 방법 :

Image normalization

학습이 잘 되도록 0과 1사이의 값으로 노말라이징(normalizing) 한다.

# 우리가 기본적으로 하는 피처스케일링은  StandardScaler, MinMaxScaler 두가지를 많이 사용한다.
  (Standardization, Normalization)

# 그러나 이미지는 범위가 0~255 사이로 정해져 있기 때문에, 굳이 피처스케일러를 사용할 필요없이
  255로 그냥 나워주기만 하면 자동으로 0과 1사이의 값으로 피처스케일링된다. 
X_train = X_train / 255.0

 

X_test = X_test / 255.0

 

이미지의 가로 세로를 전부 일렬로 만드는 작업이 flatten 이다.

모델을 만들어 보자.

 

28*28

784
 
 
Sequential: SEQUENCE layers 로 모델링

Flatten: 2차원, 3차원을 1차원으로 만드는것

Dense: 뉴런을 레이어에 붙인다.

각 레이어는 activation function 이 필요하다.

Relu effectively means "If X>0 return X, else return 0" -- so what it does it it only passes values 0 or greater to the next layer in the network.

Softmax 여러개의 값 중에서 가장 큰 값을 선택. [0.1, 0.1, 0.05, 0.1, 9.5, 0.1, 0.05, 0.05, 0.05], 여기서 가장 큰 값을 1로 만들고 나머지는 0으로 만들어준다. [0,0,0,0,1,0,0,0,0]

optimizer and loss function 으로 컴파일 한 후에 model.fit 함수로 학습한다..

 

3. 뉴럴넷에 이미지를 학습시킬때 텐서플로우를 활용하는 코드

 

from tensorflow.keras.models import Sequential  

 

from tensorflow.keras.layers import Dense,Flatten
 
model = Sequential()
 
# 지가 알아서 이미지 사이즈 계산해서, 인풋 레이어 만들어 준다. 
model.add(Flatten())
 
# 히든 레이어 1개 
model.add(Dense(units=128, activation='relu'))
 
# 아웃풋 레이어 세팅
 아웃풋 레이어는 10개로 분류하는 문제이므로,
 노드 10개를 세팅하고 액티베이션 함수에는 소프트맥스(softmax)를 설정한다.
model.add(Dense(units=10, activation='softmax'))
 
# loss가 0으로 나오면 아웃풋 레이어의 units이 안맞는 것.
# 에포크를 늘리면 학습데이터의 로스가 0 근처로 가고, 정확도는 1근처로 가게 되면, 학습데이터만 잘 맞추는 상태인 Over Fitting 상태가 된다.
 
 
# 컴파일할때 옵티마이저와 로스를 설정하는데 2개로 분류할때의 loss는 binary_crossendtropy를 사용했다.
 
# 3개 이상으로 분류하는 경우에서 y값이 어떻게 들어있는지 확인한 후,
 1. y값이 0,1,2,3,.... 이런식으로 레이블 인코딩으로 되어있는 경우는 sparse_categorical_crossentropy를 사용하고
 2. y값이 원핫인코딩으로 들어있는 경우 categorical_crossentropy를 사용한다. 
 
y_train
array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)
 
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
 
# flatten일때는 model.summary()가 안된다. fit이 다 끝나고 summary 가능. 
model.fit(X_train, y_train, epochs=5)
Epoch 1/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.4932 - accuracy: 0.8261
Epoch 2/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3737 - accuracy: 0.8662
Epoch 3/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3337 - accuracy: 0.8788
Epoch 4/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.3102 - accuracy: 0.8865
Epoch 5/5
1875/1875 [==============================] - 4s 2ms/step - loss: 0.2920 - accuracy: 0.8915
<keras.callbacks.History at 0x7f5cad9c8610>

accuracy 가 약 90% 라는 뜻. 5 epochs 라 금방 끝났다.

학습에 사용하지 않는, 테스트 데이터를 통해서, 얼마나 정확도되 나오는지 확인해 본다.

 

(평가)
model.evaluate(X_test, y_test)
[0.35349422693252563, 0.8759999871253967]
313/313 [==============================] - 1s 1ms/step - loss: 0.3535 - accuracy: 0.8760
4. y 실제값은 레이블 인코딩이고, y 예측값은 소프트맥스로 나왔을때, 컨퓨전 매트릭스 만드는 방법
 
# 어떤 것을 많이 틀리는 지 확인한다. 이런 것은 컨퓨전 매트릭스 확인하는 것! 

 

from sklearn.metrics import confusion_matrix
 
y_pred = model.predict(X_test)
X_test.shape
(10000, 28, 28)
 
 
y_pred.shape
(10000, 10)
 
y_test[0]
 
9
 
 

y_pred[0]

array([6.9568177e-06, 1.7505666e-06, 1.9499380e-07, 1.2268709e-06, 4.2575034e-06, 1.9690637e-02, 6.4530359e-06, 1.3645212e-01, 4.7943188e-04, 8.4335691e-01], dtype=float32)

 

y_pred[0].argmax()
9
 
 
plt.imshow(X_test[0])
plt.show()

y_pred_label = y_pred.argmax(axis=1)
 
y_pred_label
array([9, 2, 1, ..., 8, 1, 5])
 
y_test
array([9, 2, 1, ..., 8, 1, 5])
 
y_test
array([9, 2, 1, ..., 8, 1, 5], dtype=uint8)
 
cm = confusion_matrix(y_test, y_pred_label)

 

cm
array([[866, 1, 36, 17, 5, 0, 68, 1, 6, 0], [ 5, 963, 1, 24, 4, 0, 2, 0, 1, 0], [ 16, 0, 844, 5, 103, 0, 31, 0, 1, 0], [ 34, 2, 22, 857, 64, 0, 18, 0, 3, 0], [ 1, 0, 108, 12, 843, 0, 33, 0, 3, 0], [ 0, 0, 0, 1, 0, 937, 0, 47, 2, 13], [161, 0, 149, 24, 82, 0, 573, 0, 11, 0], [ 0, 0, 0, 0, 0, 5, 0, 982, 0, 13], [ 6, 0, 6, 2, 5, 1, 1, 5, 974, 0], [ 0, 0, 0, 0, 0, 4, 1, 74, 0, 921]])

 

import seaborn as sb
sb.heatmap(data=cm, annot=True, fmt= '.0f', cmap='RdPu')
plt.show()

 
이미지tf에서의 callback
class myCallback(tf.keras.callbacks.Callback) :
  def on_epoch_end(selfepochlogs={}):
    if logs['accuracy'] > 0.87 :
      print('\n정확도가 87%거 넘으로므로 학습을 멈춥니다.')
      self.model.stop_training = True
my_callback = myCallback()
 
model= build_model()
 
model.fit(X_train, y_train, epochs=25, callbacks=[my_callback])
반응형