텐서플로우

tensorflow, keras 를 이용한 Fashion Mnist 모델

Coding J 2021. 10. 4. 10:35
#본 모델은 코랩을 이용하여 제작하였습니다. 

## Fashion MNIST 모델

<img src="https://www.tensorflow.org/tutorials/keras/classification_files/output_oZTImqg_CaW1_0.png?hl=ko" width="500">


### 모듈 임포트

import tensorflow as tf
from tensorflow.keras.datasets.fashion_mnist import load_data  #케라스 mnist 데이터의 로드데이터사용
from tensorflow.keras.models import Sequential, Model   #모델데이터에서 시퀀셜이랑 모델 임폴트
from tensorflow.keras import models  #임폴트 모델스
from tensorflow.keras. layers import Dense, Input #레이어는 덴스와 인풋
from tensorflow.keras.optimizers import Adam #옵티마이저는 아담
from tensorflow.keras.utils import plot_model #유틸은 플롯 모델 임폴트

from sklearn.model_selection import train_test_split #모델 셀렉션에 트레인테스트스플릿 사용

import numpy as np  #넘파이 사용
import matplotlib.pyplot as plt #매트플롯 파이플롯 as plt 사용
plt.style.use('seaborn-white') #스타일 지정

### 데이터 로드

tf.random.set_seed(111) #랜덤 셋 시드 111로 정의

(x_train_full, y_train_full), (x_test, y_test) = load_data() # 각 트레인 풀 값과 테스트 값 validation 만들기 위해 full로 이름 저장 fload_data에서 가져옴

x_train, x_val, y_train, y_val = train_test_split(x_train_full, y_train_full,  # val 나눠주고 test_split 함수를 통해 각 full에서
                                                  test_size=0.3,                #test_size, 즉 validation 을 30퍼센트를 확보 랜덤스테이트=111
                                                  random_state=111)

print("학습데이터 : {}\t레이블: {}".format(x_train_full.shape, y_train_full.shape)) #전체 학습데이터수
print("학습데이터 : {}\t레이블: {}".format(x_train.shape, y_train.shape))           #x트레인을 보여주는것
print("검증데이터 : {}\t레이블: {}".format(x_val.shape, y_val.shape))               #x val보여주는 것
print("테스트 데이터 : {}\t레이블: {}".format(x_test.shape, y_test.shape))          #test 보여주는 것



class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
              'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankie boot']

class_names[y_train[0]] #y트레인 0번째를 찾는 법 ( y트레인 0의 값은 2)



plt.figure()            #직접 이미지로 보여주기 컬러바 띄우고
plt.imshow(x_train[0])
plt.colorbar()
plt.grid(False) #grid는 이미지를 보여줘야 하기 때문에 false로
plt.show()

num_sample=4 #4개를 띄우기 위해 샘플정의

random_idxs = np.random.randint(60000, size=num_sample)  # 랜덤인덱스를 60000개를 랜덤으로 잡고 nom_sample크기만큼

plt.figure(figsize=(15,10))  #fig사이즈를 지정하고 enumerate를 랜덤인덱스로 지정 
for i, idx in enumerate(random_idxs):
    image=x_train_full[idx, :]  #첫 인덱스(값)에서 이미지를 가져오기
    label=y_train_full[idx]     #레이블도 y인덱스에서 가져오기

    plt.subplot(1, len(random_idxs), #i+1) 총 4개를 표현하기위해 len정하기
    plt.imshow(image)       #이미지쇼도 표현
    plt.title('index: {}, label: {}' .format(idx, class_names[label]))  #인덱스값과 레이블 값 표시

### 데이터 전처리

- Normalization
- Flatten
- loss='sparse_categorical_crossentropy'

x_train = (x_train.reshape(-1, 28*28))/255. #nomallzation을 하기위해 reshape(255로 나눔) 28*28이 flatten
x_val = (x_val.reshape(-1, 28*28))/255.
x_test = (x_test.reshape(-1, 28*28))/255.


### 모델 구성 (함수형 API)

input = Input(shape=(784,), name= 'input') #28*28사용 인풋만들기
hidden1 = Dense(512, activation='relu', name='hidden1')(input) #hidden dense크게만들고 점차 줄여가듯이 하나씩 내려갈떄마다 반씩줄이기
hidden2 = Dense(256, activation='relu', name='hidden2')(hidden1) 
hidden3 = Dense(128, activation='relu', name='hidden3')(hidden2)
hidden4 = Dense(64, activation='relu', name='hidden4')(hidden3)
hidden5 = Dense(32, activation='relu', name='hidden5')(hidden4)
output = Dense(10, activation='softmax', name='output')(hidden5) #최종결과는 10개 , 소프트맥스로 엑티베이션 각각 위의 것들을 참조
model = Model(inputs=[input], outputs=output)  #모델 만들기 input은 input넣고 out에 outpup
model.summary() #보여주기

plot_model(model)  #plot모델로 보여주기(시퀀셜)

### 모델 컴파일 및 학습

model.compile(loss='sparse_categorical_crossentropy', # 로스는 스펄스 카테고리컬 크로스엔트로피 사용
              optimizer=Adam(learning_rate=0.01), #옵티마이저는 아담, 러닝레이트는 디폴트 0.01로설정
              metrics=['acc']) #매트릭스에 acc

history = model.fit(x_train, y_train,    #히스토리로 model.fit 각 트레인과 에폭스 배치사이즈, validation_data 설정
                    epochs=40,
                    batch_size=512,
                    validation_data=(x_val,y_val))

history.history.keys()  #히스토리 키 
history_dict = history.history #모델 시각화하는 코드

loss = history_dict['loss']
val_loss = history_dict['val_loss']

epochs=range(1, len(loss) + 1)
fig= plt.figure(figsize=(12,5))

ax1 = fig.add_subplot(1,2,1)
ax1.plot(epochs, loss, color = 'blue', label='train_loss')
ax1.plot(epochs, val_loss, color = 'red', label='val_loss')
ax1.set_title('Train and Validation Loss')
ax1.set_xlabel('Epochs')
ax1.set_ylabel('Loss')
ax1.grid()
ax1.legend()

accuracy= history_dict['acc']
val_accuracy=history_dict['val_acc']

ax2 = fig.add_subplot(1,2,2)
ax2.plot(epochs, accuracy, color = 'blue', label='train_accuracy')
ax2.plot(epochs, val_accuracy, color = 'red', label='val_accuracy')
ax2.set_title('Train and Validation Loss')
ax2.set_xlabel('Epochs')
ax2.set_ylabel('Loss')
ax2.grid()
ax2.legend()

plt.show()

### 모델 평가 및 예측

model.evaluate(x_test, y_test) #실제로 평가 

pred_ys= model.predict(x_test) #프리딕트

print(pred_ys.shape)  
np.set_printoptions(precision=7)
print(pred_ys[0])

arg_pred_y = np.argmax(pred_ys, axis=1) #프레딕트 클래스에 이름이 맞는지 확인

plt.imshow(x_test[0].reshape(-1,28))
plt.title('Predicted class: {}'.format(class_names[arg_pred_y[0]]))
plt.show()

def plot_image(i,pred_ys,y_test, img):
    pred_ys, y_test, img=pred_ys[i], y_test[i], img[i]
    plt.grid(False) #이미지기 떄문에 false
    plt.xticks([])  #xticks와 ytick스 없애기
    plt.yticks([])

    plt.imshow(img, cmap= plt.cm.binary) #이미지 쇼 컬러맵= 바이너리형태

    predicted_label = np.argmax(pred_ys) #argmax(최대값)으로 레이블가져옴
    if predicted_label == y_test:  #예측값과 테스트값이 같을 경우 블루 다를경우 레드
        color = 'blue'
    else:
        color = 'red'

        plt.xlabel("{} {:2.0f}% ({}".format(class_names[predicted_label],               #앞두자리 소숫점 첫재까지, 실제 예측숫자를 클래스이름으로,퍼센테이지 값으로환산
                                                100*np.max(pred_ys),                    #실제 ytest 값을 클래스네임으로, color은color으로
                                                class_names[y_test]),color=color)
def plot_value_array(i,pred_ys, true_label):
    pred_ys, true_label = pred_ys[i], true_label[i] #i번쨰 값을 가져오기
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    thisplot = plt.bar(range(10), pred_ys, color='#777777') #range 10, 색깔지정
    plt.ylim([0,1]) #ylim을 0~1까지
    predicted_label = np.argmax(pred_ys) #프리딕티드 레이블 값을 argmax 값으로 (pred_ys)

    thisplot[predicted_label].set_color('red') #예측값은 레드 진짜값은 블루
    thisplot[true_label].set_color('blue')

i=0   
plt.figure(figsize=(8,4)) #피규어 8,4
plt.subplot(1,2,1)
plot_image(i,pred_ys, y_test, x_test.reshape(-1, 28, 28)) #reshape해주기(이미지모양으로 만들기)
plt.subplot(1,2,2)
plot_value_array(i,pred_ys, y_test) # 얼만큼 확률로 맞췄는지 바로
plt.show()

i=40  #똑같이 40번째 값
plt.figure(figsize=(8,4))
plt.subplot(1,2,1)
plot_image(i,pred_ys, y_test, x_test.reshape(-1, 28, 28))
plt.subplot(1,2,2)
plot_value_array(i,pred_ys, y_test)
plt.show()

num_rows = 10 #10*3 행렬 갯수만들기
num_cols = 3
num_images = num_rows * num_cols

random_num = np.random.randint(10000, size=num_images)
plt.figure(figsize=(2*2*num_cols,2*num_rows)) 
for idx, num in enumerate(random_num): #enumerate의 랜덤갯수만큼 반복
    plt.subplot(num_rows, 2*num_cols, 2* idx+1)
    plot_image(num, pred_ys, y_test, x_test.reshape(-1,28,28)) #plot이미지 넣음 (reshape까지)
    plt.subplot(num_rows,2*num_cols,2*idx+2) 
    plot_value_array(num, pred_ys, y_test)  #바형태로 보여주게

plt.show()    

- 혼동 행렬 (Confusion Matrix)

from tensorflow.keras.utils import to_categorical #케라스의 유틸에서 카테고리컬 임폴트

y_test_che = to_categorical(y_test) #y_Test값을 카테고리로 바꿈
y_test_che.shape 

from sklearn.metrics import classification_report, confusion_matrix  #혼동행렬 만들어주기
import seaborn as sns
sns.set(style='white')

plt.figure(figsize=(8,8))
cm = confusion_matrix(np.argmax(y_test_che, axis=-1), np.argmax(pred_ys, axis=-1))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted Label')
plt.ylabel('True Label')
plt.show()

- 분류 보고서

print(classification_report(np.argmax(y_test_che, axis=-1),np.argmax(pred_ys,axis=-1)))  #마지막 분류보고서까지.