198 lines
9.5 KiB
Python
198 lines
9.5 KiB
Python
|
# -*- coding: utf-8 -*-
|
|||
|
"""
|
|||
|
Spyder Editor
|
|||
|
|
|||
|
This is a temporary script file.
|
|||
|
|
|||
|
|
|||
|
python 3.6
|
|||
|
pip install tensorflow-gpu==2.6.0
|
|||
|
pip install keras==2.6.0
|
|||
|
pip install opencv-python==3.4.2.16
|
|||
|
pip install matplotlib==3.3.4
|
|||
|
|
|||
|
"""
|
|||
|
import numpy as np
|
|||
|
import os
|
|||
|
# import cv2
|
|||
|
from sklearn.model_selection import train_test_split # pip install scikit-learn
|
|||
|
from tensorflow import keras
|
|||
|
from tensorflow.keras import layers
|
|||
|
from tensorflow.keras import models
|
|||
|
from tensorflow.keras.preprocessing.image import img_to_array
|
|||
|
from tensorflow.keras.preprocessing.image import load_img
|
|||
|
import tensorflow as tf
|
|||
|
import os
|
|||
|
|
|||
|
|
|||
|
class LearningRateTracker(keras.callbacks.Callback):
|
|||
|
def __init__(self):
|
|||
|
self._lr = list()
|
|||
|
|
|||
|
def on_epoch_end(self, epoch, logs=None):
|
|||
|
optimizer = self.model.optimizer
|
|||
|
self._lr.append(tf.keras.backend.get_value(optimizer.lr))
|
|||
|
print(f'Epoch {epoch + 1}: Learning rate is {tf.keras.backend.get_value(optimizer.lr)}.\n')
|
|||
|
|
|||
|
def show_train_learningRate(self):
|
|||
|
plt.plot(self._lr)
|
|||
|
plt.title('learningRate')
|
|||
|
plt.ylabel('learningRate')
|
|||
|
plt.xlabel('Epoch')
|
|||
|
plt.legend(['train', 'validation'], loc='upper left')
|
|||
|
plt.savefig('LearningRate.png')
|
|||
|
plt.show()
|
|||
|
|
|||
|
|
|||
|
# os.environ['']
|
|||
|
# =============================================================================
|
|||
|
from keras.utils import np_utils
|
|||
|
|
|||
|
# =============================================================================
|
|||
|
config = tf.compat.v1.ConfigProto()
|
|||
|
gpus = tf.config.experimental.list_physical_devices('GPU')
|
|||
|
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
|
|||
|
session = tf.compat.v1.Session(config=config)
|
|||
|
|
|||
|
epochs = 150 # 訓練的次數
|
|||
|
batch_size = 18
|
|||
|
img_rows = None # 驗證碼影像檔的高
|
|||
|
img_cols = None # 驗證碼影像檔的寬
|
|||
|
# digits_in_img = 6 #驗證碼影像檔中有幾位數
|
|||
|
x_list = list() # 存所有驗證碼數字影像檔的array
|
|||
|
y_list = list() # 存所有的驗證碼數字影像檔array代表的正確數字
|
|||
|
x_train = list() # 存訓練用驗證碼數字影像檔的array
|
|||
|
y_train = list() # 存訓練用驗證碼數字影像檔array代表的正確數字
|
|||
|
x_test = list() # 存測試用驗證碼數字影像檔的array
|
|||
|
y_test = list() # 存測試用驗證碼數字影像檔array代表的正確數字
|
|||
|
|
|||
|
|
|||
|
def split_digits_in_img(img_array, x_list, y_list=None): # 副函式:分割及儲存驗證碼
|
|||
|
# for i in range(digits_in_img):
|
|||
|
# step = img_cols // digits_in_img #step=圖片總寬度除六
|
|||
|
# y_list.append(img_filename[:2]) #將圖片正確數字(檔名)存進 y_list
|
|||
|
x_list.append(img_array) # 將圖片存進x_list
|
|||
|
|
|||
|
|
|||
|
input_filepath = './trainingset/1205_Trainning'
|
|||
|
file_list = sorted(os.listdir(input_filepath)) # 获取文件名列表.
|
|||
|
print(f'file_list = {file_list}')
|
|||
|
for classnumber in file_list:
|
|||
|
img_filenames = os.listdir(f'{input_filepath}/{classnumber}')
|
|||
|
count = 0 # os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表
|
|||
|
for img_filename in img_filenames:
|
|||
|
count += 1
|
|||
|
if '.png' not in img_filename: # 只讀取PNG檔
|
|||
|
continue
|
|||
|
# img = load_img('./output_file(00)/{0}/{1}'.format(classnumber, img_filename), color_mode='rgb', target_size=(224, 224, 3)) #將圖片依序以灰階讀取
|
|||
|
img = load_img('{0}/{1}/{2}'.format(input_filepath, classnumber, img_filename), color_mode='grayscale',
|
|||
|
target_size=(112, 112, 1)) # 將圖片依序以灰階讀取
|
|||
|
img_array = img_to_array(img) # 將圖片轉換成數值
|
|||
|
img_rows, img_cols, _ = img_array.shape # 將圖片長寬分別儲存在img_rows, img_cols,
|
|||
|
# print(img_array.shape)
|
|||
|
y_list.append(classnumber[:2]) # 將圖片正確數字(檔名)存進 y_list
|
|||
|
split_digits_in_img(img_array, x_list, y_list) # 呼叫 副函式:分割及儲存驗證碼
|
|||
|
print(f'{classnumber} is ok --> 有{count}張')
|
|||
|
x_train, x_test, y_train, y_test = train_test_split(x_list, y_list, test_size=0.1,
|
|||
|
stratify=y_list) # , stratify=y_list随机划分训练集和测试集
|
|||
|
# print(x_train)
|
|||
|
# print(y_train)
|
|||
|
|
|||
|
y_train = keras.utils.to_categorical(y_train) # 將y_list 轉換成categorical形式
|
|||
|
y_test = keras.utils.to_categorical(y_test)
|
|||
|
|
|||
|
# =============================================================================
|
|||
|
# y_train_onehot = np_utils.to_categorical(y_train)
|
|||
|
# y_test_onehot = np_utils.to_categorical(y_test)
|
|||
|
# =============================================================================
|
|||
|
|
|||
|
# =============================================================================
|
|||
|
# if os.path.isfile('cnn_model.h5'): #檢測是否已有模型
|
|||
|
# model = models.load_model('cnn_model.h5') #將該模型導入
|
|||
|
# print('Model loaded from file.')
|
|||
|
# else: #否則:建立新模型
|
|||
|
# =============================================================================
|
|||
|
|
|||
|
|
|||
|
model = models.Sequential()
|
|||
|
# 創建模型
|
|||
|
model.add(layers.Conv2D(input_shape=(112, 112, 1), filters=64, kernel_size=(4, 4), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=64, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.MaxPool2D(pool_size=(3, 3), strides=(2, 2)))
|
|||
|
model.add(layers.Dropout(rate=0.3)) # 0
|
|||
|
model.add(layers.Conv2D(filters=128, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=128, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.MaxPool2D(pool_size=(3, 3), strides=(2, 2)))
|
|||
|
model.add(layers.Dropout(rate=0.2)) # 0
|
|||
|
model.add(layers.Conv2D(filters=256, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=256, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=256, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=256, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.MaxPool2D(pool_size=(3, 3), strides=(2, 2)))
|
|||
|
model.add(layers.Dropout(rate=0.2)) # 0
|
|||
|
model.add(layers.Conv2D(filters=512, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=512, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=512, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=512, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.MaxPool2D(pool_size=(3, 3), strides=(2, 2)))
|
|||
|
model.add(layers.Dropout(rate=0.2)) # 5
|
|||
|
model.add(layers.Conv2D(filters=512, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=512, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=512, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.Conv2D(filters=512, kernel_size=(3, 3), padding="same", activation="relu"))
|
|||
|
model.add(layers.MaxPool2D(pool_size=(3, 3), strides=(2, 2)))
|
|||
|
|
|||
|
model.add(layers.Flatten())
|
|||
|
model.add(layers.Dense(units=4096, activation="relu"))
|
|||
|
model.add(layers.Dropout(rate=0.5)) # 6
|
|||
|
model.add(layers.Dense(units=4096, activation="relu"))
|
|||
|
model.add(layers.Dense(units=17, activation="softmax")) # 這是類別數
|
|||
|
# 全連接層 (輸出空間的維數,activation)
|
|||
|
print('New model created.') # 全連接層 (輸出空間的維數,activation)
|
|||
|
|
|||
|
model.compile(loss=keras.losses.categorical_crossentropy,
|
|||
|
optimizer=keras.optimizers.Adam(learning_rate=0.000001, beta_1=0.9, beta_2=0.999), metrics=['accuracy'])
|
|||
|
# model.compile 編譯模型(optimizer =優化器,loss =損失函數, metrics= [“準確率”])
|
|||
|
# model.fit(np.array(x_train), np.array(y_train), batch_size=digits_in_img, epochs=epochs, verbose=1, validation_data=(np.array(x_test), np.array(y_test)))
|
|||
|
# =============================================================================
|
|||
|
checkpoint_filepath = os.path.sep.join(['checkpoint',
|
|||
|
"weights-{epoch:03d}-{loss:.9f}-{val_accuracy:.4f}.h5"])
|
|||
|
model_checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(
|
|||
|
filepath=checkpoint_filepath,
|
|||
|
save_weights_only=False,
|
|||
|
monitor='loss',
|
|||
|
mode='min',
|
|||
|
save_best_only=True)
|
|||
|
|
|||
|
lr_tracker = LearningRateTracker()
|
|||
|
with tf.device('/cpu:0'):
|
|||
|
x_train = tf.convert_to_tensor(x_train, np.float32)
|
|||
|
y_train = tf.convert_to_tensor(y_train, np.float32)
|
|||
|
train_history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1,
|
|||
|
callbacks=[model_checkpoint_callback, lr_tracker],
|
|||
|
validation_data=(np.array(x_test), np.array(y_test)), shuffle=True)
|
|||
|
import matplotlib.pyplot as plt
|
|||
|
|
|||
|
|
|||
|
def show_train_history(train_history, title, train_metric, val_metric):
|
|||
|
plt.plot(train_history.history[train_metric])
|
|||
|
plt.plot(train_history.history[val_metric])
|
|||
|
plt.title(title)
|
|||
|
plt.ylabel(train_metric)
|
|||
|
plt.xlabel('Epoch')
|
|||
|
plt.legend(['train', 'validation'], loc='upper left')
|
|||
|
plt.savefig(f'{title}.png')
|
|||
|
plt.show()
|
|||
|
|
|||
|
|
|||
|
show_train_history(train_history, 'Accuracy', 'accuracy', 'val_accuracy')
|
|||
|
show_train_history(train_history, 'Loss', 'loss', 'val_loss')
|
|||
|
lr_tracker.show_train_learningRate()
|
|||
|
# =============================================================================
|
|||
|
|
|||
|
loss, accuracy = model.evaluate(np.array(x_test), np.array(y_test), verbose=1) # 評估模型(verbose:0或1。詳細模式。 0 =靜音,1 =進度欄。)
|
|||
|
# print('Test loss:', loss)
|
|||
|
# print('Test accuracy:', accuracy)
|
|||
|
|
|||
|
model.save('model1124.h5')
|
|||
|
print(model.summary())
|