基于Python實(shí)現(xiàn)口罩佩戴檢測功能
口罩佩戴檢測
一 題目背景
1.1 實(shí)驗(yàn)介紹
今年一場席卷全球的新型冠狀病毒給人們帶來了沉重的生命財(cái)產(chǎn)的損失。有效防御這種傳染病毒的方法就是積極佩戴口罩。我國對此也采取了嚴(yán)肅的措施,在公共場合要求人們必須佩戴口罩。在本次實(shí)驗(yàn)中,我們要建立一個(gè)目標(biāo)檢測的模型,可以識別圖中的人是否佩戴了口罩。
1.2 實(shí)驗(yàn)要求
- 建立深度學(xué)習(xí)模型,檢測出圖中的人是否佩戴了口罩,并將其盡可能調(diào)整到最佳狀態(tài)。
- 學(xué)習(xí)經(jīng)典的模型 MTCNN 和 MobileNet 的結(jié)構(gòu)。
- 學(xué)習(xí)訓(xùn)練時(shí)的方法。
1.3 實(shí)驗(yàn)環(huán)境
實(shí)驗(yàn)使用重要python包:
import cv2 as cv import numpy as np import matplotlib.pyplot as plt from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping
由于擔(dān)心平臺GPU時(shí)長不夠用,所以在自己電腦上搭建了配套實(shí)驗(yàn)環(huán)境,由于電腦顯卡CUDA版本較老,所以最終本地配置如下:
- Python: 3.8
- Tensorflow-GPU: 2.3.0
- Keras: 2.7.0
1.4 實(shí)驗(yàn)思路
針對目標(biāo)檢測的任務(wù),可以分為兩個(gè)部分:目標(biāo)識別和位置檢測。通常情況下,特征提取需要由特有的特征提取神經(jīng)網(wǎng)絡(luò)來完成,如 VGG、MobileNet、ResNet 等,這些特征提取網(wǎng)絡(luò)往往被稱為 Backbone 。而在 BackBone 后面接全連接層***(FC)***就可以執(zhí)行分類任務(wù)。但 FC 對目標(biāo)的位置識別乏力。經(jīng)過算法的發(fā)展,當(dāng)前主要以特定的功能網(wǎng)絡(luò)來代替 FC 的作用,如 Mask-Rcnn、SSD、YOLO 等。我們選擇充分使用已有的人臉檢測的模型,再訓(xùn)練一個(gè)識別口罩的模型,從而提高訓(xùn)練的開支、增強(qiáng)模型的準(zhǔn)確率。
常規(guī)目標(biāo)檢測:
本次案例:
圖1 實(shí)驗(yàn)口罩佩戴檢測流程
二 實(shí)驗(yàn)內(nèi)容
2.1 已知文件與數(shù)據(jù)集
首先,導(dǎo)入已經(jīng)寫好的python文件并對數(shù)據(jù)集進(jìn)行處理。
- image 文件夾:圖片分成兩類,戴口罩的和沒有戴口罩的
- train.txt: 存放的是 image 文件夾下對應(yīng)圖片的標(biāo)簽
- keras_model_data 文件夾:存放 keras 框架相關(guān)預(yù)訓(xùn)練好的模型
2.2 圖片尺寸調(diào)整
將圖片尺寸調(diào)整到網(wǎng)絡(luò)輸入的圖片尺寸
2.3 制作訓(xùn)練時(shí)需要用到的批量數(shù)據(jù)集
圖片生成器的主要方法:
fit(x, augment=False, rounds=1)
:計(jì)算依賴于數(shù)據(jù)的變換所需要的統(tǒng)計(jì)信息(均值方差等)。flow(self, X, y, batch_size=32, shuffle=True, seed=None, save_to_dir=None, save_prefix='', save_format='png')
:接收 Numpy 數(shù)組和標(biāo)簽為參數(shù),生成經(jīng)過數(shù)據(jù)提升或標(biāo)準(zhǔn)化后的batch
數(shù)據(jù),并在一個(gè)無限循環(huán)中不斷的返回batch
數(shù)據(jù)。flow_from_directory(directory)
: 以文件夾路徑為參數(shù),會(huì)從路徑推測label
,生成經(jīng)過數(shù)據(jù)提升/歸一化后的數(shù)據(jù),在一個(gè)無限循環(huán)中無限產(chǎn)生batch
數(shù)據(jù)。
結(jié)果:
Found 693 images belonging to 2 classes.
Found 76 images belonging to 2 classes.
{'mask': 0, 'nomask': 1}
{0: 'mask', 1: 'nomask'}
2.4 調(diào)用MTCNN
通過搭建 MTCNN 網(wǎng)絡(luò)實(shí)現(xiàn)人臉檢測
keras_py/mtcnn.py
文件是在搭建 MTCNN 網(wǎng)絡(luò)。keras_py/face_rec.py
文件是在繪制人臉檢測的矩形框。
這里直接使用現(xiàn)有的表現(xiàn)較好的 MTCNN 的三個(gè)權(quán)重文件,它們已經(jīng)保存在
datasets/5f680a696ec9b83bb0037081-momodel/data/keras_model_data
文件夾下
2.5 加載預(yù)訓(xùn)練模型MobileNet
# 加載 MobileNet 的預(yù)訓(xùn)練模型權(quán)重 weights_path = basic_path + 'keras_model_data/mobilenet_1_0_224_tf_no_top.h5'
2.6 訓(xùn)練模型
2.6.1 加載和保存
為了避免訓(xùn)練過程中遇到斷電等突發(fā)事件,導(dǎo)致模型訓(xùn)練成果無法保存。我們可以通過 ModelCheckpoint
規(guī)定在固定迭代次數(shù)后保存模型。同時(shí),我們設(shè)置在下一次重啟訓(xùn)練時(shí),會(huì)檢查是否有上次訓(xùn)練好的模型,如果有,就先加載已有的模型權(quán)重。這樣就可以在上次訓(xùn)練的基礎(chǔ)上繼續(xù)模型的訓(xùn)練了。
2.6.2 手動(dòng)調(diào)整學(xué)習(xí)率
學(xué)習(xí)率的手動(dòng)設(shè)置可以使模型訓(xùn)練更加高效。這里我們設(shè)置當(dāng)模型在三輪迭代后,準(zhǔn)確率沒有上升,就調(diào)整學(xué)習(xí)率。
# 學(xué)習(xí)率下降的方式,acc三次不下降就下降學(xué)習(xí)率繼續(xù)訓(xùn)練 reduce_lr = ReduceLROnPlateau( monitor='accuracy', # 檢測的指標(biāo) factor=0.5, # 當(dāng)acc不下降時(shí)將學(xué)習(xí)率下調(diào)的比例 patience=3, # 檢測輪數(shù)是每隔三輪 verbose=2 # 信息展示模式 )
2.6.3 早停法
當(dāng)我們訓(xùn)練深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)的時(shí)候通常希望能獲得最好的泛化性能。但是所有的標(biāo)準(zhǔn)深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)如全連接多層感知機(jī)都很容易過擬合。當(dāng)網(wǎng)絡(luò)在訓(xùn)練集上表現(xiàn)越來越好,錯(cuò)誤率越來越低的時(shí)候,就極有可能出現(xiàn)了過擬合。早停法就是當(dāng)我們在檢測到這一趨勢后,就停止訓(xùn)練,這樣能避免繼續(xù)訓(xùn)練導(dǎo)致過擬合的問題。
early_stopping = EarlyStopping( monitor='val_accuracy', # 檢測的指標(biāo) min_delta=0.0001, # 增大或減小的閾值 patience=3, # 檢測的輪數(shù)頻率 verbose=1 # 信息展示的模式 )
2.6.4 亂序訓(xùn)練數(shù)據(jù)
打亂txt
的行,這個(gè)txt
主要用于幫助讀取數(shù)據(jù)來訓(xùn)練,打亂的數(shù)據(jù)更有利于訓(xùn)練。
np.random.seed(10101) np.random.shuffle(lines) np.random.seed(None)
2.6.5 訓(xùn)練模型
一次訓(xùn)練集大小設(shè)定為64,優(yōu)化器使用Adam
,初始學(xué)習(xí)率設(shè)定為0.001,優(yōu)化目標(biāo)為accuracy
,總的學(xué)習(xí)輪次設(shè)定為20輪。(通過多次實(shí)驗(yàn)測定,在這些參數(shù)條件下,準(zhǔn)確率較高)
# 一次的訓(xùn)練集大小 batch_size = 64 # 編譯模型 model.compile(loss='binary_crossentropy', # 二分類損失函數(shù) optimizer=Adam(lr=0.001), # 優(yōu)化器 metrics=['accuracy']) # 優(yōu)化目標(biāo) # 訓(xùn)練模型 history = model.fit(train_generator, epochs=20, # epochs: 整數(shù),數(shù)據(jù)的迭代總輪數(shù)。 # 一個(gè)epoch包含的步數(shù),通常應(yīng)該等于你的數(shù)據(jù)集的樣本數(shù)量除以批量大小。 steps_per_epoch=637 // batch_size, validation_data=test_generator, validation_steps=70 // batch_size, initial_epoch=0, # 整數(shù)。開始訓(xùn)練的輪次(有助于恢復(fù)之前的訓(xùn)練)。 callbacks=[checkpoint_period, reduce_lr])
三 算法描述
3.1 MTCNN
- 三階段的級聯(lián)(cascaded)架構(gòu)
- coarse-to-fine 的方式
- new online hard sample mining 策略
- 同時(shí)進(jìn)行人臉檢測和人臉對齊
- state-of-the-art 性能
圖2 MTCNN架構(gòu)
3.2 MobileNet
圖3 MobileNet架構(gòu)
MobileNet的網(wǎng)絡(luò)結(jié)構(gòu)如圖3所示。首先是一個(gè)3x3
的標(biāo)準(zhǔn)卷積,然后后面就是堆積depthwise separable convolution
,并且可以看到其中的部分depthwise convolution
會(huì)通過strides=2
進(jìn)行down sampling
。然后采用average pooling
將feature
變成1x1
,根據(jù)預(yù)測類別大小加上全連接層,最后是一個(gè)softmax
層。
四 求解結(jié)果
最終確定最佳取值為batch_size=64
,lr=0.0001
,epochs=20
,其它參數(shù)如下,連續(xù)訓(xùn)練兩次,可以獲得最佳結(jié)果。此處僅展示兩個(gè)參數(shù)條件下的結(jié)果作為對比
# 一次的訓(xùn)練集大小 batch_size = 64 # 編譯模型 model.compile(loss='binary_crossentropy', # 二分類損失函數(shù) optimizer=Adam(lr=0.001), # 優(yōu)化器 metrics=['accuracy']) # 優(yōu)化目標(biāo) # 訓(xùn)練模型 history = model.fit(train_generator, epochs=20, # epochs: 整數(shù),數(shù)據(jù)的迭代總輪數(shù)。 # 一個(gè)epoch包含的步數(shù),通常應(yīng)該等于你的數(shù)據(jù)集的樣本數(shù)量除以批量大小。 steps_per_epoch=637 // batch_size, validation_data=test_generator, validation_steps=70 // batch_size, initial_epoch=0, # 整數(shù)。開始訓(xùn)練的輪次(有助于恢復(fù)之前的訓(xùn)練)。 callbacks=[checkpoint_period, reduce_lr])
條件1: 取batch_size=48
, lr=0.001
,epochs=20
,對訓(xùn)練之后的模型進(jìn)行測試,得到結(jié)果如下:
圖4 條件1 loss曲線
由loss
曲線可以看出,隨著訓(xùn)練迭代次數(shù)的加深,驗(yàn)證集上的損失在逐漸的減小,最終穩(wěn)定在0.2左右;而在訓(xùn)練集上loss
始終在0附近。
圖5 條件1 acc曲線
從驗(yàn)證集和測試集的準(zhǔn)確率變化曲線上可以看出,隨著訓(xùn)練輪次的增加,驗(yàn)證集的準(zhǔn)確率逐漸上升,最終穩(wěn)定在96%左右,效果還是不錯(cuò)的。
圖6 條件1 測試樣例1
使用樣例照片進(jìn)行測試,首先人臉識別部分順利識別到了五張人臉,但是口罩識別部分將一個(gè)沒有帶口罩的人識別成了帶著口罩的人,說明還有進(jìn)步空間,實(shí)際錯(cuò)誤率達(dá)到了20%。
圖7 條件1 測試樣例2
另一張樣例照片的測試結(jié)果同樣是人臉識別部分沒有出現(xiàn)問題,正確識別到了四張人臉,但是同樣將一個(gè)沒有帶口罩的人識別成了帶有口罩的人。
平臺測試:
后續(xù)通過調(diào)整各項(xiàng)參數(shù)并打亂測試集和訓(xùn)練集圖片順序來進(jìn)行了多次實(shí)驗(yàn),最終確定的最佳狀態(tài)如下:
條件2: 取batch_size=64
, lr=0.0001
,epochs=20
,對訓(xùn)練之后的模型進(jìn)行測試,得到結(jié)果如下:
圖8 條件2 loss曲線
觀察準(zhǔn)確率曲線可以看出,在該條件下,驗(yàn)證集上的準(zhǔn)確率最終穩(wěn)定在98%附近,效果非常的好,說明我們做出的一些優(yōu)化還是具有一定效果的。
圖9 條件2 acc曲線
觀察此條件下的loss
曲線可以看到最終驗(yàn)證集的loss
穩(wěn)定在0.2左右,訓(xùn)練集的loss
非常小,基本趨近于0
圖10 條件2 測試樣例1
使用兩張測試樣例對模型進(jìn)行檢測,第一張圖片所有檢測點(diǎn)均正確,正確識別出了五張人臉并且口罩佩戴檢測均正確,識別正確率100%。
圖11 條件2 測試樣例2
第二章測試樣例上,正確識別出了4張人臉并且口罩佩戴檢測結(jié)果均正確。
兩張測試樣例上所有檢測點(diǎn)檢測結(jié)果均正確,說明在此參數(shù)條件下,模型識別效果較好,達(dá)到了口罩佩戴檢測的要求。
平臺測試:
條件3:
使用更多測試樣例發(fā)現(xiàn)MTCNN人臉識別部分存在不能正確識別人臉的問題,故通過多次實(shí)驗(yàn)和測試,修改了mask_rec()
的門限函數(shù)權(quán)重self.threshold
,由原來的self.threshold = [0.5,0.6,0.8]
修改為self.threshold = [0.4,0.15,0.65]
在本地使用更多自選圖片進(jìn)行測試,發(fā)現(xiàn)人臉識別準(zhǔn)確率有所提升。在條件2訓(xùn)練參數(shù)不變的情況下,使用同一模型進(jìn)行平臺測試,結(jié)果如下:
平臺測試成績有所提升。
條件4:
繼續(xù)調(diào)整mask_rec()
的門限函數(shù)權(quán)重self.threshold
,通過系統(tǒng)測試反饋來決定門限函數(shù)的權(quán)重,通過多次測試,由原來的self.threshold = [0.4,0.15,0.65]
修改為self.threshold = [0.4,0.6,0.65]
平臺測試,結(jié)果如下:
平臺測試成績有所提升,達(dá)到95分。
為了達(dá)到條件4所展示的效果,對門限函數(shù)的數(shù)值進(jìn)行了大量的嘗試,根據(jù)提交測試的反饋結(jié)果,最終確定數(shù)值為條件4時(shí),可以達(dá)到最優(yōu)。由于不知道后臺測試圖片是什么且沒有反饋數(shù)據(jù),所以最終再次修改人臉識別的門限函數(shù)或者修改參數(shù)重新訓(xùn)練口罩識別模型依舊沒有提升。
五 比較分析
驗(yàn)證集準(zhǔn)確率 | 測試樣例結(jié)果 | 平臺成績 | |
---|---|---|---|
條件1 | 96% | 7/9 | 77.5 |
條件2 | 98% | 9/9 | 88.33333334 |
條件3 | 98% | 9/9 | 90 |
條件4 | 98% | 9/9 | 95 |
最終通過不斷調(diào)試與優(yōu)化算法,得到了95分的平臺成績。
六 心得與感想
本次實(shí)驗(yàn)過程中主要使用了keras方法進(jìn)行訓(xùn)練,由于初次使用這些方法,所以前期實(shí)現(xiàn)的過程相對困難。最初我想通過調(diào)用GPU資源來進(jìn)行訓(xùn)練,所以給自己的電腦配套安裝了tensorflow-gpu、CUDA等等配套的軟件和包,由于個(gè)人電腦的顯卡版本較老,所以安裝的過程也是非常的曲折。好在最終安裝好了所有的東西,但是由于顯卡顯存比較小,所以bath_size
大小一直上不去,最大只能給到32,不過影響也不大。調(diào)整參數(shù)的過程花費(fèi)了很多的時(shí)間,優(yōu)化算法也花費(fèi)了很多的時(shí)間。之后又對門限函數(shù)進(jìn)行了修改,雖然過程非常的辛苦,但最終的結(jié)果還是很不錯(cuò)的,最終整體達(dá)到95分,在兩張給定的測試樣例上所有檢測點(diǎn)都是正確的,由于不知道平臺的五張檢測照片是什么,所以不知道到底出錯(cuò)在哪里,希望之后平臺可以反饋一些修改意見~??偟膩碚f在過程中收獲還是很大的,受益匪淺。
訓(xùn)練源代碼:
import warnings # 忽視警告 warnings.filterwarnings('ignore') import os import matplotlib import cv2 as cv import numpy as np import matplotlib.pyplot as plt from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping from tensorflow.keras.applications.imagenet_utils import preprocess_input from tensorflow.keras import backend as K from tensorflow.keras.optimizers import Adam K.image_data_format() == 'channels_last' from keras_py.utils import get_random_data from keras_py.face_rec import mask_rec from keras_py.face_rec import face_rec from keras_py.mobileNet import MobileNet from tensorflow.keras.preprocessing.image import ImageDataGenerator # 數(shù)據(jù)集路徑 basic_path = "./datasets/5f680a696ec9b83bb0037081-momodel/data/" def letterbox_image(image, size): # 調(diào)整圖片尺寸,返回經(jīng)過調(diào)整的照片 new_image = cv.resize(image, size, interpolation=cv.INTER_AREA) return new_image read_img = cv.imread("test1.jpg") print("調(diào)整前圖片的尺寸:", read_img.shape) read_img = letterbox_image(image=read_img, size=(50, 50)) print("調(diào)整前圖片的尺寸:", read_img.shape) def processing_data(data_path, height, width, batch_size=32, test_split=0.1): # 數(shù)據(jù)處理,batch_size默認(rèn)大小為32 train_data = ImageDataGenerator( # 對圖片的每個(gè)像素值均乘上這個(gè)放縮因子,把像素值放縮到0和1之間有利于模型的收斂 rescale=1. / 255, # 浮點(diǎn)數(shù),剪切強(qiáng)度(逆時(shí)針方向的剪切變換角度) shear_range=0.1, # 隨機(jī)縮放的幅度,若為浮點(diǎn)數(shù),則相當(dāng)于[lower,upper] = [1 - zoom_range, 1+zoom_range] zoom_range=0.1, # 浮點(diǎn)數(shù),圖片寬度的某個(gè)比例,數(shù)據(jù)提升時(shí)圖片水平偏移的幅度 width_shift_range=0.1, # 浮點(diǎn)數(shù),圖片高度的某個(gè)比例,數(shù)據(jù)提升時(shí)圖片豎直偏移的幅度 height_shift_range=0.1, # 布爾值,進(jìn)行隨機(jī)水平翻轉(zhuǎn) horizontal_flip=True, # 布爾值,進(jìn)行隨機(jī)豎直翻轉(zhuǎn) vertical_flip=True, # 在 0 和 1 之間浮動(dòng)。用作驗(yàn)證集的訓(xùn)練數(shù)據(jù)的比例 validation_split=test_split ) # 接下來生成測試集,可以參考訓(xùn)練集的寫法 test_data = ImageDataGenerator( rescale=1. / 255, validation_split=test_split) train_generator = train_data.flow_from_directory( # 提供的路徑下面需要有子目錄 data_path, # 整數(shù)元組 (height, width),默認(rèn):(256, 256)。 所有的圖像將被調(diào)整到的尺寸。 target_size=(height, width), # 一批數(shù)據(jù)的大小 batch_size=batch_size, # "categorical", "binary", "sparse", "input" 或 None 之一。 # 默認(rèn):"categorical",返回one-hot 編碼標(biāo)簽。 class_mode='categorical', # 數(shù)據(jù)子集 ("training" 或 "validation") subset='training', seed=0) test_generator = test_data.flow_from_directory( data_path, target_size=(height, width), batch_size=batch_size, class_mode='categorical', subset='validation', seed=0) return train_generator, test_generator # 數(shù)據(jù)路徑 data_path = basic_path + 'image' # 圖像數(shù)據(jù)的行數(shù)和列數(shù) height, width = 160, 160 # 獲取訓(xùn)練數(shù)據(jù)和驗(yàn)證數(shù)據(jù)集 train_generator, test_generator = processing_data(data_path, height, width) # 通過屬性class_indices可獲得文件夾名與類的序號的對應(yīng)字典。 labels = train_generator.class_indices print(labels) # 轉(zhuǎn)換為類的序號與文件夾名對應(yīng)的字典 labels = dict((v, k) for k, v in labels.items()) print(labels) pnet_path = "./datasets/5f680a696ec9b83bb0037081-momodel/data/keras_model_data/pnet.h5" rnet_path = "./datasets/5f680a696ec9b83bb0037081-momodel/data/keras_model_data/rnet.h5" onet_path = "./datasets/5f680a696ec9b83bb0037081-momodel/data/keras_model_data/onet.h5" # 加載 MobileNet 的預(yù)訓(xùn)練模型權(quán)重 weights_path = basic_path + 'keras_model_data/mobilenet_1_0_224_tf_no_top.h5' # 圖像數(shù)據(jù)的行數(shù)和列數(shù) height, width = 160, 160 model = MobileNet(input_shape=[height,width,3],classes=2) model.load_weights(weights_path,by_name=True) print('加載完成...') def save_model(model, checkpoint_save_path, model_dir): # 保存模型 if os.path.exists(checkpoint_save_path): print("模型加載中") model.load_weights(checkpoint_save_path) print("模型加載完畢") checkpoint_period = ModelCheckpoint( # 模型存儲路徑 model_dir + 'ep{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5', # 檢測的指標(biāo) monitor='val_acc', # ‘a(chǎn)uto',‘min',‘max'中選擇 mode='max', # 是否只存儲模型權(quán)重 save_weights_only=False, # 是否只保存最優(yōu)的模型 save_best_only=True, # 檢測的輪數(shù)是每隔2輪 period=2 ) return checkpoint_period checkpoint_save_path = "./results/last_one88.h5" model_dir = "./results/" checkpoint_period = save_model(model, checkpoint_save_path, model_dir) # 學(xué)習(xí)率下降的方式,acc三次不下降就下降學(xué)習(xí)率繼續(xù)訓(xùn)練 reduce_lr = ReduceLROnPlateau( monitor='accuracy', # 檢測的指標(biāo) factor=0.5, # 當(dāng)acc不下降時(shí)將學(xué)習(xí)率下調(diào)的比例 patience=3, # 檢測輪數(shù)是每隔三輪 verbose=2 # 信息展示模式 ) early_stopping = EarlyStopping( monitor='val_accuracy', # 檢測的指標(biāo) min_delta=0.0001, # 增大或減小的閾值 patience=3, # 檢測的輪數(shù)頻率 verbose=1 # 信息展示的模式 ) # 一次的訓(xùn)練集大小 batch_size = 64 # 圖片數(shù)據(jù)路徑 data_path = basic_path + 'image' # 圖片處理 train_generator, test_generator = processing_data(data_path, height=160, width=160, batch_size=batch_size, test_split=0.1) # 編譯模型 model.compile(loss='binary_crossentropy', # 二分類損失函數(shù) optimizer=Adam(lr=0.001), # 優(yōu)化器 metrics=['accuracy']) # 優(yōu)化目標(biāo) # 訓(xùn)練模型 history = model.fit(train_generator, epochs=20, # epochs: 整數(shù),數(shù)據(jù)的迭代總輪數(shù)。 # 一個(gè)epoch包含的步數(shù),通常應(yīng)該等于你的數(shù)據(jù)集的樣本數(shù)量除以批量大小。 steps_per_epoch=637 // batch_size, validation_data=test_generator, validation_steps=70 // batch_size, initial_epoch=0, # 整數(shù)。開始訓(xùn)練的輪次(有助于恢復(fù)之前的訓(xùn)練)。 callbacks=[checkpoint_period, reduce_lr]) # 保存模型 model.save_weights(model_dir + 'temp.h5') plt.plot(history.history['loss'],label = 'train_loss') plt.plot(history.history['val_loss'],'r',label = 'val_loss') plt.legend() plt.show() plt.plot(history.history['accuracy'],label = 'acc') plt.plot(history.history['val_accuracy'],'r',label = 'val_acc') plt.legend() plt.show()
到此這篇關(guān)于基于Python實(shí)現(xiàn)的口罩佩戴檢測的文章就介紹到這了,更多相關(guān)python口罩佩戴檢測內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Python實(shí)現(xiàn) 學(xué)生學(xué)籍管理系統(tǒng)
這篇文章主要介紹了使用Python實(shí)現(xiàn) 學(xué)生學(xué)籍管理系統(tǒng),代碼大致分為五個(gè)函數(shù)組成,具體內(nèi)容詳情本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2019-11-11

Python中關(guān)鍵字global和nonlocal的區(qū)別詳解

Python+Opencv實(shí)現(xiàn)表格邊框線檢測