深度学习100例 - 卷积神经网络(CNN)实现车牌识别 | 第15天
- 🔗 運行環(huán)境:python3
- 🚩 作者:K同學啊
- 🥇 選自專欄:《深度學習100例》
- 🔥 推薦專欄:《新手入門深度學習》
- 📚 精選專欄:《Matplotlib教程》
- 🧿 優(yōu)秀專欄:《Python入門100題》
文章目錄
- 一、前期工作
- 1.設置GPU
- 2.導入數(shù)據(jù)
- 3.數(shù)據(jù)可視化
- 4.標簽數(shù)字化
- 二、構建一個tf.data.Dataset
- 1.預處理函數(shù)
- 2.加載數(shù)據(jù)
- 3.配置數(shù)據(jù)
- 三、搭建網(wǎng)絡模型
- 四、設置動態(tài)學習率
- 五、編譯
- 六、訓練
- 七、模型評估
- 八、保存和加載模型
- 九、預測
一、前期工作
🚩 我的環(huán)境:
- 語言環(huán)境:Python3.6.5
- 編譯器:jupyter notebook
- 深度學習環(huán)境:TensorFlow2.4.1
- 數(shù)據(jù)和代碼:📌【傳送門】
🚩 來自專欄:《深度學習100例》
🚩 往期精彩:
如果你還是一名小白,可以看看我這個專門為你寫的專欄:《小白入門深度學習》,幫助零基礎的你入門深度學習。
1.設置GPU
如果使用的是CPU可以注釋掉這部分的代碼,不影響運行。
import tensorflow as tfgpus = tf.config.list_physical_devices("GPU")if gpus:tf.config.experimental.set_memory_growth(gpus[0], True) #設置GPU顯存用量按需使用tf.config.set_visible_devices([gpus[0]],"GPU")2.導入數(shù)據(jù)
import matplotlib.pyplot as plt # 支持中文 plt.rcParams['font.sans-serif'] = ['SimHei'] # 用來正常顯示中文標簽 plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號import os,PIL,random,pathlib# 設置隨機種子盡可能使結果可以重現(xiàn) import numpy as np np.random.seed(1)# 設置隨機種子盡可能使結果可以重現(xiàn) import tensorflow as tf tf.random.set_seed(1) data_dir = "D:/jupyter notebook/DL-100-days/datasets/015_licence_plate" data_dir = pathlib.Path(data_dir)pictures_paths = list(data_dir.glob('*')) pictures_paths = [str(path) for path in pictures_paths] pictures_paths[:3] ['D:\\jupyter notebook\\DL-100-days\\datasets\\015_licence_plate\\000000000_藏WP66B0.jpg','D:\\jupyter notebook\\DL-100-days\\datasets\\015_licence_plate\\000000001_津D8Z15T.jpg','D:\\jupyter notebook\\DL-100-days\\datasets\\015_licence_plate\\000000002_陜Z813VB.jpg'] image_count = len(list(pictures_paths))print("圖片總數(shù)為:",image_count) 圖片總數(shù)為: 619 # 獲取數(shù)據(jù)標簽 all_label_names = [path.split("_")[-1].split(".")[0] for path in pictures_paths] all_label_names[:3] ['藏WP66B0', '津D8Z15T', '陜Z813VB']3.數(shù)據(jù)可視化
plt.figure(figsize=(10,5)) plt.suptitle("數(shù)據(jù)示例",fontsize=15)for i in range(20):plt.subplot(5,4,i+1)plt.xticks([])plt.yticks([])plt.grid(False)# 顯示圖片images = plt.imread(pictures_paths[i])plt.imshow(images)# 顯示標簽plt.xlabel(all_label_names[i],fontsize=13)plt.show()4.標簽數(shù)字化
char_enum = ["京","滬","津","渝","冀","晉","蒙","遼","吉","黑","蘇","浙","皖","閩","贛","魯",\"豫","鄂","湘","粵","桂","瓊","川","貴","云","藏","陜","甘","青","寧","新","軍","使"]number = [str(i) for i in range(0, 10)] # 0 到 9 的數(shù)字 alphabet = [chr(i) for i in range(65, 91)] # A 到 Z 的字母char_set = char_enum + number + alphabet char_set_len = len(char_set) label_name_len = len(all_label_names[0])# 將字符串數(shù)字化 def text2vec(text):vector = np.zeros([label_name_len, char_set_len])for i, c in enumerate(text):idx = char_set.index(c)vector[i][idx] = 1.0return vectorall_labels = [text2vec(i) for i in all_label_names]二、構建一個tf.data.Dataset
1.預處理函數(shù)
def preprocess_image(image):image = tf.image.decode_jpeg(image, channels=1)image = tf.image.resize(image, [50, 200])return image/255.0def load_and_preprocess_image(path):image = tf.io.read_file(path)return preprocess_image(image)2.加載數(shù)據(jù)
構建 tf.data.Dataset 最簡單的方法就是使用 from_tensor_slices 方法。
AUTOTUNE = tf.data.experimental.AUTOTUNEpath_ds = tf.data.Dataset.from_tensor_slices(pictures_paths) image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=AUTOTUNE) label_ds = tf.data.Dataset.from_tensor_slices(all_labels)image_label_ds = tf.data.Dataset.zip((image_ds, label_ds)) image_label_ds <ShuffleDataset shapes: ((50, 200, 1), (7, 69)), types: (tf.float32, tf.float64)> train_ds = image_label_ds.take(5000).shuffle(5000) # 前5000個batch val_ds = image_label_ds.skip(5000).shuffle(1000) # 跳過前5000,選取后面的3.配置數(shù)據(jù)
先復習一下prefetch()函數(shù)。prefetch()功能詳細介紹:CPU 正在準備數(shù)據(jù)時,加速器處于空閑狀態(tài)。相反,當加速器正在訓練模型時,CPU 處于空閑狀態(tài)。因此,訓練所用的時間是 CPU 預處理時間和加速器訓練時間的總和。prefetch()將訓練步驟的預處理和模型執(zhí)行過程重疊到一起。當加速器正在執(zhí)行第 N 個訓練步時,CPU 正在準備第 N+1 步的數(shù)據(jù)。這樣做不僅可以最大限度地縮短訓練的單步用時(而不是總用時),而且可以縮短提取和轉換數(shù)據(jù)所需的時間。如果不使用prefetch(),CPU 和 GPU/TPU 在大部分時間都處于空閑狀態(tài):
使用prefetch()可顯著減少空閑時間:
BATCH_SIZE = 16train_ds = train_ds.batch(BATCH_SIZE) train_ds = train_ds.prefetch(buffer_size=AUTOTUNE)val_ds = val_ds.batch(BATCH_SIZE) val_ds = val_ds.prefetch(buffer_size=AUTOTUNE) val_ds <PrefetchDataset shapes: ((None, 50, 200, 1), (None, 7, 69)), types: (tf.float32, tf.float64)>三、搭建網(wǎng)絡模型
目前這里主要是帶大家跑通代碼、整理一下思路,大家可以自行優(yōu)化網(wǎng)絡結構、調整模型參數(shù)。后續(xù)我也會針對性的出一些調優(yōu)的案例的。
from tensorflow.keras import datasets, layers, modelsmodel = models.Sequential([layers.Conv2D(32, (3, 3), activation='relu', input_shape=(50, 200, 1)),#卷積層1,卷積核3*3layers.MaxPooling2D((2, 2)), #池化層1,2*2采樣layers.Conv2D(64, (3, 3), activation='relu'), #卷積層2,卷積核3*3layers.MaxPooling2D((2, 2)), #池化層2,2*2采樣layers.Flatten(), #Flatten層,連接卷積層與全連接層 # layers.Dense(1000, activation='relu'), #全連接層,特征進一步提取layers.Dense(1000, activation='relu'), #全連接層,特征進一步提取 # layers.Dropout(0.2), layers.Dense(label_name_len * char_set_len),layers.Reshape([label_name_len, char_set_len]),layers.Softmax() #輸出層,輸出預期結果 ]) # 打印網(wǎng)絡結構 model.summary() Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 48, 198, 32) 320 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 24, 99, 32) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 22, 97, 64) 18496 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 11, 48, 64) 0 _________________________________________________________________ flatten (Flatten) (None, 33792) 0 _________________________________________________________________ dense (Dense) (None, 1000) 33793000 _________________________________________________________________ dense_1 (Dense) (None, 483) 483483 _________________________________________________________________ reshape (Reshape) (None, 7, 69) 0 _________________________________________________________________ softmax (Softmax) (None, 7, 69) 0 ================================================================= Total params: 34,295,299 Trainable params: 34,295,299 Non-trainable params: 0 _________________________________________________________________四、設置動態(tài)學習率
這里先羅列一下學習率大與學習率小的優(yōu)缺點。
-
學習率大
- 優(yōu)點:1、加快學習速率。2、有助于跳出局部最優(yōu)值。
- 缺點:1、導致模型訓練不收斂。2、單單使用大學習率容易導致模型不精確。
-
學習率小
- 優(yōu)點:1、有助于模型收斂、模型細化。2、提高模型精度。
- 缺點:1、很難跳出局部最優(yōu)值。2、收斂緩慢。
注意:這里設置的動態(tài)學習率為:指數(shù)衰減型(ExponentialDecay)。在每一個epoch開始前,學習率(learning_rate)都將會重置為初始學習率(initial_learning_rate),然后再重新開始衰減。計算公式如下:
learning_rate = initial_learning_rate * decay_rate ^ (step / decay_steps)
# 設置初始學習率 initial_learning_rate = 1e-3lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(initial_learning_rate, decay_steps=20, # 敲黑板!!!這里是指 steps,不是指epochsdecay_rate=0.96, # lr經(jīng)過一次衰減就會變成 decay_rate*lrstaircase=True)# 將指數(shù)衰減學習率送入優(yōu)化器 optimizer = tf.keras.optimizers.Adam(learning_rate=lr_schedule)五、編譯
model.compile(optimizer=optimizer,loss='categorical_crossentropy',metrics=['accuracy'])六、訓練
epochs = 50history = model.fit(train_ds,validation_data=val_ds,epochs=epochs )七、模型評估
acc = history.history['accuracy'] val_acc = history.history['val_accuracy']loss = history.history['loss'] val_loss = history.history['val_loss']epochs_range = range(epochs)plt.figure(figsize=(12, 4)) plt.subplot(1, 2, 1)plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy')plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') plt.show()八、保存和加載模型
# 保存模型 model.save('model/15_model.h5') # 加載模型 new_model = tf.keras.models.load_model('model/15_model.h5')九、預測
def vec2text(vec):"""還原標簽(向量->字符串)"""text = []for i, c in enumerate(vec):text.append(char_set[c])return "".join(text)plt.figure(figsize=(10, 8)) # 圖形的寬為10高為8for images, labels in val_ds.take(1):for i in range(6):ax = plt.subplot(5, 2, i + 1) # 顯示圖片plt.imshow(images[i])# 需要給圖片增加一個維度img_array = tf.expand_dims(images[i], 0) # 使用模型預測驗證碼predictions = model.predict(img_array)plt.title(vec2text(np.argmax(predictions, axis=2)[0]),fontsize=15)plt.axis("off")往期精彩:
🚀 來自專欄:《深度學習100例》
關注、點贊、收藏,送我上熱搜,謝謝大家啦!
最后再送大家一本,幫助大家拿到 BAT 等一線大廠 offer 的數(shù)據(jù)結構刷題筆記,是谷歌和阿里的大佬寫的,對于算法薄弱或者需要提高的同學都十分受用(提取碼:9go2 ):
谷歌和阿里大佬的Leetcode刷題筆記
以及我整理的7K+本開源電子書,總有一本可以幫到你 💖(提取碼:4eg0)
7K+本開源電子書
總結
以上是生活随笔為你收集整理的深度学习100例 - 卷积神经网络(CNN)实现车牌识别 | 第15天的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于深度学习的交通标识别算法对比研究-T
- 下一篇: 台式电脑可以连wifi吗_[Window