import tensorflow as tf
from tensorflow import keras
keras.__version__
'2.7.0'
#데이터 불러오기
fm = keras.datasets.fashion_mnist
(X_train_full , y_train_full),(X_test, y_test) = fm.load_data()
X_train_full.shape
#확인해본 결과 다음과 같은 결과로 나옴
(60000, 28, 28)
#Validation set 만들기 , 5000개와 55000개
X_valid , X_train = X_train_full[:5000] / 255.0 , X_train_full[5000:] / 255.0
y_valid , y_train = y_train_full[:5000] , y_train_full[5000:]
X_test = X_test / 255.0
#의류 종류에 대해 분류하기 위해 class를 만듬
class_names = ["T-shirt","Trouser","Pullover","Dress","Coat","Sandal","Shirt",
"Sneaker","Bag","Ankle boot"]
class_names[y_train[0]]
#예를 들어 train set의 0번 레이블의 경우 coat다.
'Coat'
#MultiLayer Perceptron, MLP - 2 hidden layer
model = keras.models.Sequential()
model.add(keras.layers.Flatten(input_shape=[28,28]))
model.add(keras.layers.Dense(300, activation="relu"))
model.add(keras.layers.Dense(100, activation="relu"))
model.add(keras.layers.Dense(10, activation="softmax"))
#위와 같은 코드
#Sequntial 모델의 경우 다음과 인자에 리스트를 전달 해서도 만들 수 있다.
model = keras.models.Sequential([
keras.layers.Flatten(input_shape=[28,28]),
keras.layers.Dense(300, activation="relu"),
keras.layers.Dense(100, activation="relu"),
keras.layers.Dense(10, activation="softmax")
])
model.summary()
Model: "sequential_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= flatten_1 (Flatten) (None, 784) 0 dense_3 (Dense) (None, 300) 235500 dense_4 (Dense) (None, 100) 30100 dense_5 (Dense) (None, 10) 1010 ================================================================= Total params: 266,610 Trainable params: 266,610 Non-trainable params: 0 _________________________________________________________________
#모델의 layer를 인덱스로도 선택 가능하고 확인 가능하다.
model.layers
[<keras.layers.core.flatten.Flatten at 0x7fdf1fb02e90>, <keras.layers.core.dense.Dense at 0x7fdf1fa4db10>, <keras.layers.core.dense.Dense at 0x7fdf1fb02590>, <keras.layers.core.dense.Dense at 0x7fdf1fb02b90>]
model.layers[2].name
'dense_4'
#각 층에 대한 파라미터들은 get_weights() 와 set_weight() 메소드로 접근이 가능하다.
#아래의 코드 예시와 같이 get_weights()를 통해 weight와 bias 모두 접근 가능하다.
weight, bias = model.layers[1].get_weights()
weight
array([[-0.06637845, 0.00869625, -0.03596747, ..., -0.00371069, 0.04780079, 0.01165803], [ 0.04360663, -0.03799567, 0.04808863, ..., 0.03029907, -0.05783149, 0.00799306], [-0.04221347, 0.02728531, 0.04899614, ..., 0.02455316, -0.03212978, -0.06892749], ..., [-0.00745593, 0.04390582, 0.0183312 , ..., 0.02503217, -0.07115501, -0.04792337], [-0.06052386, -0.0654074 , 0.01508966, ..., 0.02591585, -0.02830314, -0.0536991 ], [ 0.01827636, -0.07332236, -0.05261526, ..., -0.01299351, -0.01725402, -0.06342798]], dtype=float32)
bias.shape
#weight.shape / bias.shape 모두 확인 가능
(300,)
model.compile(loss="sparse_categorical_crossentropy",
optimizer="sgd",
metrics=["accuracy"])
만약 lable이 샘플마다 어떠한 class로 분류될 확률을 가지고 있는 형태라면 categorical_crossentropy를 사용해야 할 것이다.
또한 , 이진 분류나 다중 레이블 이진 분류의 경우 softmax 대신 sigmoid를 , 또 binary_crossentropy를 사용해야 할 것이다.
#모델을 훈련하고 평가할 단계이다.
#모델의 훈련은 fit() 메소드를 통해 이루어진다.
history = model.fit(X_train, y_train, epochs=30,
validation_data=(X_valid, y_valid))
#위 코드에서 볼 수 있듯이 , fit() 메소드 안에는
#Train x, y 와 epochs , 또 validation set까지 인자로 들어간다. (vali는 선택인자)
#epochs는 모델에서 학습의 횟수를 의미한다.
#epoch를 지정하지 않는다면 디폴트인 1로 지정되어 좋은 결과가 나오지 않을 것이다.
#validation set을 직접 만들어 넣지 않고 비율로 validation_split=0.1 (10%) 이런식으로 비율로 둘 수도 있다.
Epoch 1/30 1719/1719 [==============================] - 7s 4ms/step - loss: 0.7377 - accuracy: 0.7553 - val_loss: 0.5339 - val_accuracy: 0.8188 Epoch 2/30 1719/1719 [==============================] - 7s 4ms/step - loss: 0.4901 - accuracy: 0.8290 - val_loss: 0.4726 - val_accuracy: 0.8308 Epoch 3/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.4434 - accuracy: 0.8443 - val_loss: 0.4447 - val_accuracy: 0.8488 Epoch 4/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.4173 - accuracy: 0.8532 - val_loss: 0.4389 - val_accuracy: 0.8488 Epoch 5/30 1719/1719 [==============================] - 6s 3ms/step - loss: 0.3967 - accuracy: 0.8598 - val_loss: 0.3832 - val_accuracy: 0.8708 Epoch 6/30 1719/1719 [==============================] - 6s 3ms/step - loss: 0.3821 - accuracy: 0.8664 - val_loss: 0.3975 - val_accuracy: 0.8644 Epoch 7/30 1719/1719 [==============================] - 6s 3ms/step - loss: 0.3672 - accuracy: 0.8704 - val_loss: 0.3645 - val_accuracy: 0.8720 Epoch 8/30 1719/1719 [==============================] - 6s 3ms/step - loss: 0.3557 - accuracy: 0.8732 - val_loss: 0.3684 - val_accuracy: 0.8704 Epoch 9/30 1719/1719 [==============================] - 6s 3ms/step - loss: 0.3445 - accuracy: 0.8776 - val_loss: 0.3755 - val_accuracy: 0.8632 Epoch 10/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.3360 - accuracy: 0.8802 - val_loss: 0.3464 - val_accuracy: 0.8764 Epoch 11/30 1719/1719 [==============================] - 7s 4ms/step - loss: 0.3273 - accuracy: 0.8835 - val_loss: 0.3983 - val_accuracy: 0.8514 Epoch 12/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.3204 - accuracy: 0.8860 - val_loss: 0.3434 - val_accuracy: 0.8760 Epoch 13/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.3123 - accuracy: 0.8881 - val_loss: 0.3492 - val_accuracy: 0.8748 Epoch 14/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.3057 - accuracy: 0.8889 - val_loss: 0.3394 - val_accuracy: 0.8784 Epoch 15/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2990 - accuracy: 0.8910 - val_loss: 0.3412 - val_accuracy: 0.8786 Epoch 16/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2931 - accuracy: 0.8938 - val_loss: 0.3178 - val_accuracy: 0.8884 Epoch 17/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2872 - accuracy: 0.8959 - val_loss: 0.3287 - val_accuracy: 0.8834 Epoch 18/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2812 - accuracy: 0.8981 - val_loss: 0.3303 - val_accuracy: 0.8822 Epoch 19/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2765 - accuracy: 0.9000 - val_loss: 0.3078 - val_accuracy: 0.8902 Epoch 20/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2703 - accuracy: 0.9024 - val_loss: 0.3191 - val_accuracy: 0.8882 Epoch 21/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2665 - accuracy: 0.9032 - val_loss: 0.3305 - val_accuracy: 0.8840 Epoch 22/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2614 - accuracy: 0.9050 - val_loss: 0.3120 - val_accuracy: 0.8910 Epoch 23/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2565 - accuracy: 0.9072 - val_loss: 0.3029 - val_accuracy: 0.8900 Epoch 24/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2513 - accuracy: 0.9096 - val_loss: 0.3146 - val_accuracy: 0.8906 Epoch 25/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2469 - accuracy: 0.9117 - val_loss: 0.3078 - val_accuracy: 0.8924 Epoch 26/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2430 - accuracy: 0.9126 - val_loss: 0.3091 - val_accuracy: 0.8890 Epoch 27/30 1719/1719 [==============================] - 7s 4ms/step - loss: 0.2383 - accuracy: 0.9141 - val_loss: 0.3009 - val_accuracy: 0.8928 Epoch 28/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2340 - accuracy: 0.9159 - val_loss: 0.3062 - val_accuracy: 0.8900 Epoch 29/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2311 - accuracy: 0.9180 - val_loss: 0.2929 - val_accuracy: 0.8950 Epoch 30/30 1719/1719 [==============================] - 6s 4ms/step - loss: 0.2272 - accuracy: 0.9181 - val_loss: 0.3035 - val_accuracy: 0.8922
import pandas as pd
import matplotlib.pyplot as plt
pd.DataFrame(history.history).plot(figsize=(8,5))
plt.grid(True)
plt.gca().set_ylim(0, 1)
plt.show()
model.evaluate(X_test,y_test)
#evaluate() 메소드를 통해 test 한다.
313/313 [==============================] - 1s 2ms/step - loss: 0.3338 - accuracy: 0.8823
[0.3337719440460205, 0.8823000192642212]
X_new = X_test[:3]
y_proba = model.predict(X_new)
y_proba.round(2)
#위의 결과는 data에 대해 0 ~ 9번 class일 확률을 보여준다.
#확률값에 대해서 가장 높은 확률을 가진 class를 보고 싶다면 predict_classes() 메소드를 통해
#하나만 딱 분류하도록 할 수도 있다.
array([[0. , 0. , 0. , 0. , 0. , 0.01, 0. , 0.02, 0. , 0.97], [0. , 0. , 0.99, 0. , 0.01, 0. , 0. , 0. , 0. , 0. ], [0. , 1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]], dtype=float32)
import numpy as np
#y_pred = model.predict_classes(X_new)
#위의 코드와 같은 결과
y_prob = model.predict(X_new, verbose=0)
y_pred = y_prob.argmax(axis=-1)
np.array(class_names)[y_pred]
#tensorflow 2.6 이상 부터는 y_pred = model.predict_classes(X_new) 에서 처럼
#classes()가 없어 오류가 난다.
#y_prob = model.predict(X_new, verbose=0)
#y_pred = y_prob.argmax(axis=-1)
#가 같은 역할을 수행한다.
#ref : https://leunco.tistory.com/16
#실제로 그림을 보고 맞는지 확인하자.
array(['Ankle boot', 'Pullover', 'Trouser'], dtype='<U10')
y_test[:3]
#9 2 1 로 맞는 것을 볼 수 있다.
array([9, 2, 1], dtype=uint8)