實作一個手寫辨識!可以辨識自己寫的數字
- Demo
- 註冊&登入 Google Colab (共編、不用設定環境、免費!) Google Colab
- 註冊&登入 Kaggle (很多資料集跟比賽可以練功、免費!) Kaggle
- 1.1 import libraries
from keras.layers import Conv2D, MaxPooling2D, Dense, Flatten #一些模型內會用到的layer
from keras.callbacks import EarlyStopping, ReduceLROnPlateau #回調函數
from keras.models import Sequential #順序模型
import matplotlib.pyplot as plt # 畫圖用的
import tensorflow as tf # tensorflow!
import pandas as pd # 資料處理&分析的好工具
import numpy as np # 陣列運算、很多的數學函數
-
1.2 串接Kaggle API 拿資料集
-
登入Kaggle => 點右上角個人頭像 => Your Profile => Account => API => Create New Token
-
下載到桌面
-
執行cell並上傳kaggle.json
print(data.info()) # 簡單的訊息
print(data.head()) # 前五筆資料
# print(data.tail()) # 後五筆資料
# print(data.describe()) # 關於資料集的統計數據
class_counts = data['label'].value_counts()
print(class_counts) # 各類別的資料筆數
# 比例依據不同大小的數據適合的不一樣,通常會讓train的比例在0.7~0.8
train_data = data.head(int(len(reduced_data)*比例))
val_data = data.tail(int(len(reduced_data)*比例))
train_labels = train_data.pop('label')
val_labels = val_data.pop('label')
- 將dataframe轉為tensorflow 的dataset, 後續用tensorflow做處理和訓練
tf_train_data = tf.data.Dataset.from_tensor_slices((train_data.values, train_labels.values))
tf_val_data = tf.data.Dataset.from_tensor_slices((val_data.values, val_labels.values))
- 5.1 調整圖片大小並縮小pixel值到0,1區間
def preprocess_image(image, label):
image = tf.reshape(image, [長, 寬, 頻帶數]) #調整大小為28*28*1
image = tf.cast(image, tf.float32) / 縮小倍數. #把pixel值縮小到[0,1]區間,pixel值是0-255,所以要縮小255倍!
return image, label
tf_train_data = tf_train_data.map(preprocess_image)
tf_val_data = tf_val_data.map(preprocess_image)
- 5.2 打亂數據順序並預先讀取資料
def pipeline(tf_data):
tf_data = tf_data.shuffle(一次打亂的數據量) #洗牌打亂數據,一次放100個進buffer
tf_data = tf_data.batch(一個batch的數據量) #一個batch包32個數據
tf_data = tf_data.prefetch(tf.data.experimental.AUTOTUNE) #在訓練前先讀取資料
return tf_data
tf_train_data = pipeline(tf_train_data)
tf_val_data = pipeline(tf_val_data)
model = Sequential()
model.add(Conv2D(個數, (長, 寬), activation='relu', padding='same', input_shape=(長, 寬, 頻帶數))) #卷積層,用6個大小為5*5的filter,在模型的第一層需要指定輸入的大小
model.add(MaxPooling2D((2, 2))) # 池化層,用2*2的窗格
model.add(Conv2D(16, (5, 5), activation='relu', padding='valid'))
model.add(MaxPooling2D((2, 2))) #池化層,用2*2的窗格
model.add(Flatten()) #將數據展平成一維才能輸入全連接層
model.add(Dense(神經元個數, activation='relu')) #全連接層,120個神經元
model.add(Dense(神經元個數, activation='relu')) #全連接層,84個神經元
model.add(Dense(神經元個數, activation='softmax')) #輸出層,10個神經元,softmax會將每個類別轉為機率
- 配置模型訓練要用到的參數 model.compile([優化器], loss=[損失函數], metrics=[指標])
- Step 8.1 定義回調函數
callbacks = [
ReduceLROnPlateau(monitor='loss', patience=2, verbose=1), # 如果連續2 epoch 的loss 沒有減少,就降低learning rate
EarlyStopping(monitor='loss', patience=5, verbose=1), # 如果連續5 epoch 的loss 沒有減少,就提前終止訓練
]
- Step 8.2 訓練模型
hist = model.fit(
tf_train_data, #訓練資料
validation_data=tf_val_data, #驗證資料
epochs=10, #訓練次數
callbacks=callbacks #回調函數
)
-
觀察準確率和loss的曲線
-
val_loss和val_accuracy代表驗證集的訓練結果,若val_loss持續下降且val_accuracy持續上升趨於平穩代表訓練表現非常好!
-
如果accuracy上升但loss沒有下降,可能有overfitting的問題
-
如果accuracy上不去的話可能數據本身有問題,或模型的結構需要大幅度的修改
-
Q: loss跟val_loss差在哪裡?
result = model.predict(tf_test_data)
result = np.argmax(result, axis=1)