파이썬

Keras를 사용한 이미지 분류 #1 (TensorFlow 텐서플로우 이미지 분류 신경망 모델)

sheepone 2021. 7. 29. 11:14
반응형

1차 진행

패션 MNIST 데이터셋 70000중

트레인 이미지 60000개 테스트 이미지 10000개로 이미지 분류 수행

 

트레인 0번 이미지 0~255의 값을 255로 나누어 0~1의 값으로 변경

 

 

트레임 이미지 25개 확인 작업

 

 

모델 생성 장면 Epoch 100회

 

 

트레인 데이터 정확도와 로스율 표기

 

 

스니커즈를 샌달이라고 인식

 

 

# tensorflow와 tf.keras를 임포트합니다
from PIL.Image import NONE
from numpy.lib.function_base import append
import tensorflow as tf
from tensorflow import keras

# 헬퍼(helper) 라이브러리를 임포트합니다
import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__) #2.5.0

fashion_mnist = keras.datasets.fashion_mnist #패션 MNIST 데이터셋 임포트하기 이미지 해상도 28x28

#train_images와 train_labels 배열은 모델 학습에 사용되는 훈련 세트입니다.
#test_images와 test_labels 배열은 모델 테스트에 사용되는 테스트 세트입니다.
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

#Label 레이블 0~9 
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

#데이터 전처리
plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()               

#신경망 모델에 주입하기 전에 이 값의 범위를 0~1 사이로 조정
train_images = train_images / 255.0 #(0 ~ 255) / 255 = (0 ~ 1)
test_images = test_images / 255.0

#훈련 세트에서 처음 25개 이미지와 그 아래 클래스 이름을 출력해 보죠. 
#데이터 포맷이 올바른지 확인하고 네트워크 구성과 훈련할 준비를 마칩니다.
plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
    
plt.show()

'''
이 네트워크의 첫 번째 층인 tf.keras.layers.Flatten은 2차원 배열(28 x 28 픽셀)의 
이미지 포맷을 28 * 28 = 784 픽셀의 1차원 배열로 변환합니다. 
이 층은 이미지에 있는 픽셀의 행을 펼쳐서 일렬로 늘립니다. 
이 층에는 학습되는 가중치가 없고 데이터를 변환하기만 합니다.

픽셀을 펼친 후에는 두 개의 tf.keras.layers.Dense 층이 연속되어 연결됩니다. 
이 층을 밀집 연결(densely-connected) 또는 완전 연결(fully-connected) 층이라고 부릅니다. 
첫 번째 Dense 층은 128개의 노드(또는 뉴런)를 가집니다. 
두 번째 (마지막) 층은 10개의 노드의 소프트맥스(softmax) 층입니다. 
이 층은 10개의 확률을 반환하고 반환된 값의 전체 합은 1입니다. 
각 노드는 현재 이미지가 10개 클래스 중 하나에 속할 확률을 출력합니다.
'''

model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)),
    keras.layers.Dense(128, activation='relu'),
    keras.layers.Dense(10, activation='softmax')
])

'''
모델 컴파일
모델을 훈련하기 전에 필요한 몇 가지 설정이 모델 컴파일 단계에서 추가됩니다:

손실 함수(Loss function)-훈련 하는 동안 모델의 오차를 측정합니다. 
모델의 학습이 올바른 방향으로 향하도록 이 함수를 최소화해야 합니다.
옵티마이저(Optimizer)-데이터와 손실 함수를 바탕으로 모델의 업데이트 방법을 결정합니다.
지표(Metrics)-훈련 단계와 테스트 단계를 모니터링하기 위해 사용합니다. 
다음 예에서는 올바르게 분류된 이미지의 비율인 정확도를 사용합니다.
'''
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

'''
모델 훈련
신경망 모델을 훈련하는 단계는 다음과 같습니다:

훈련 데이터를 모델에 주입합니다-이 예에서는 train_images와 train_labels 배열입니다.
모델이 이미지와 레이블을 매핑하는 방법을 배웁니다.
테스트 세트에 대한 모델의 예측을 만듭니다-이 예에서는 test_images 배열입니다. 
이 예측이 test_labels 배열의 레이블과 맞는지 확인합니다.
훈련을 시작하기 위해 model.fit 메서드를 호출하면 모델이 훈련 데이터를 학습합니다:
'''
#hist = model.fit(train_images, train_labels, epochs=5)   

#batch_size(배치사이즈)
#배치사이즈는 몇 개의 관측치에 대한 예측을 하고, 레이블 값과 비교를 하는지를 설정하는 파라미터입니다. 위의 예시에서 배치사이즈가 100이면 전체 데이터에 대해 모두 예측한 뒤 실제 레이블 값과 비교한 후 가중치 갱신을 합니다. 배치사이즈가 10이면 10개 데이터에 대해 예측한 뒤 실제 레이블 값과 비교하며 가중치 갱신도 10번 발생합니다.
#배치사이즈가 100인 경우, 어떤 한 유형에 대한 예측이 틀리면 이후 비슷한 유형에 대한 예측도 틀릴 수 있습니다. 하지만 배치사이즈가 10인 경우에는, 데이터 10개마다 실제 레이블 값과 비교하기 때문에, 처음에 틀리게 예측하더라도 가중치 업데이트를 하면서 뒤에는 맞추게 될 확률이 높습니다.
#배치사이즈가 클수록 많은 데이터를 저장해두어야 하므로 용량이 커야합니다. 반면, 배치사이즈가 작으면 학습은 촘촘하게 되겠지만 계속 레이블과 비교하고, 가중치를 업데이트하는 과정을 거치면서 시간이 오래 걸립니다.
#epochs 전체 데이터셋을 몇번 반복할 것인지 설정     
#너무 많이 반복학습을 하면 학습셋에 대해 성능은 올라가지만 관측되지 못한 테스트셋에 대한 성능이 떨어지는 오버피팅(overfitting)이 발생하게 됩니다. 때문에, 오버피팅이 일어날 것 같으면 학습을 종료합니다.(early stopping)
hist = model.fit(train_images,train_labels,epochs=100,batch_size=NONE, validation_data=(test_images,test_labels))

#%matplotlib inline
import matplotlib.pyplot as plt
fig, loss_ax = plt.subplots()
acc_ax = loss_ax.twinx()
loss_ax.plot(hist.history['loss'],'y',label='train loss')
loss_ax.plot(hist.history['val_loss'],'r',label='val loss')
acc_ax.plot(hist.history['accuracy'],'b',label='train acc') #acc 로 하면 에러남요.
acc_ax.plot(hist.history['val_accuracy'],'g',label='val acc') #val_acc 로 하면 에러남요.
loss_ax.set_xlabel('epoch')
loss_ax.set_ylabel('loss')
acc_ax.set_ylabel('accuracy')
loss_ax.legend(loc='upper left')
acc_ax.legend(loc='lower left')
plt.show()

#정확도 평가
#그다음 테스트 세트에서 모델의 성능을 비교합니다:
test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)

print('\n테스트 정확도:', test_acc)
# 테스트 세트의 정확도가 훈련 세트의 정확도보다 조금 낮습니다. 훈련 세트의 정확도와 테스트 세트의 정확도 사이의 차이는 
# 과대적합(overfitting) 때문입니다. 
# 과대적합은 머신러닝 모델이 훈련 데이터보다 새로운 데이터에서 성능이 낮아지는 현상을 말합니다.

'''
예측 만들기
'''
predictions = model.predict(test_images)
np.argmax(predictions[0])

def one_test(self):
    # 테스트 세트에서 이미지 하나를 선택합니다
    img = self.test_images[0]
    print(img.shape)
    # 이미지 하나만 사용할 때도 배치에 추가합니다
    img = (np.expand_dims(img, 0))
    print(img.shape)
    predictions_single = self.model.predict(img)
    print(predictions_single)
    self.plot_value_array(0, predictions_single, self.test_labels)
    _ = plt.xticks(range(10), self.class_names, rotation=45)
    np.argmax(predictions_single[0])
        
def plot_image(i, predictions_array, true_label, img):
    predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])

    plt.imshow(img, cmap=plt.cm.binary)

    predicted_label = np.argmax(predictions_array)
    if predicted_label == true_label:
        color = 'blue'
    else:
        color = 'red'

    plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                100*np.max(predictions_array),
                                class_names[true_label]),
                                color=color)

def plot_value_array(i, predictions_array, true_label):
  predictions_array, true_label = predictions_array[i], true_label[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1])
  predicted_label = np.argmax(predictions_array)

  thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue')

'''
i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions,  test_labels)
plt.show()
'''
# 처음 X 개의 테스트 이미지와 예측 레이블, 진짜 레이블을 출력합니다
# 올바른 예측은 파랑색으로 잘못된 예측은 빨강색으로 나타냅니다
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions, test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions, test_labels)
plt.show()

# 마지막으로 훈련된 모델을 사용하여 한 이미지에 대한 예측을 만듭니다.
# 테스트 세트에서 이미지 하나를 선택합니다
img = test_images[0]

print(img.shape)

# 이미지 하나만 사용할 때도 배치에 추가합니다
img = (np.expand_dims(img,0))

print(img.shape)

predictions_single = model.predict(img)

print(predictions_single)

plot_value_array(0, predictions_single, test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)

np.argmax(predictions_single[0])

 

반응형