1 前置环境
1.1 硬件
不要使用CPU训练,太耗时耗力
笔者使用的1080Ti,从二手市场淘的,1000大洋,训练模型大多数10分钟以内
1.2 依赖的主要的环境,其他不在赘述
- tensorflow==2.0
- keras
- MTCNN 用来探测人脸
- DeepFace 用来迁移学习
2. 从网站抓取数据
以下提到的网站,都需要科学上网
2.1 需要抓取哪些演员老师?
https://xslist.org/zh/ranking
从这个网站的龙虎榜,获取最热门的老师列表,然后抓取老师们的名字,比如三上悠亜,河北彩花,然后这个网站的提供老师们的图片比较少,需要抓取更多的老师图片
2.2 抓取更多的详情图片
http://www.eropuru.com/search?q=老师的名字
在这个网站查询老师的名字,获取图片列表,然后一一保存
2.3 最终文件夹效果
├── actor_head 人脸图片
│ └── 三上悠亜
│ ├── 1.jpg
│ └── 2.jpg
├── actor 原图片
│ ├── 三上悠亜
│ │ └── 1.jpg
│ └── 河北彩花
│ ├── 1.jpg
│ └── 2.jpg
├── unknown 待定文件夹,需要人工处理,并训练异常检测模型
├── actor_test 验证数据集
3. 使用MTCNN从原图片提取人脸,并保存
import os
import numpy as np from PIL import Image
from deepface import DeepFace from mtcnn import MTCNN import re
原始文件夹
base_dir = 'actor'
裁剪人脸文件夹
actor_head_dir = 'actor_head'
待定人脸文件夹
unknown_dir = 'unknown'
获取文件的夹的所有图片
def image_files_in_folder(folder): return os.path.join(folder, f) for f in os.listdir(folder) if re.match(r'.*.(jpg|jpeg|png)', f, flags=re.I)
定义提取人脸模型,最小人脸图片为100
mtcnn_model = MTCNN(min_face_size=100)
for class_dir in os.listdir(base_dir): path_class = os.path.join(base_dir, class_dir) if not os.path.isdir(path_class): continue print(path_class) # Loop through each training image for the current person for img_path in image_files_in_folder(path_class): ## 防止重复裁剪,提高效率 if os.path.exists(os.path.join(os.path.join(actor_head_dir, class_dir),"0_" + os.path.basename(img_path))): continue try: img = Image.open(img_path) print(img_path)
faces = mtcnn_model.detect_faces(np.array(img)) ## 没有发现人脸,删除原有图片 if len(faces) == 0: os.remove(img_path) continue ## 人脸文件夹不存在,就新建 if not os.path.exists(os.path.join(actor_head_dir, class_dir)): os.mkdir(os.path.join(actor_head_dir, class_dir)) for i, face in enumerate(faces): x, y, width, height = face['box'] ## 从原图裁剪出人脸图片 crop_img = img.crop((x, y, x + width, y + height)) ## 信心大于0.9,就存储图片 if face['confidence'] > 0.9: ## 裁剪的人脸图片的存储路径 file_name = os.path.join(os.path.join(actor_head_dir, class_dir), str(i) + "_" + os.path.basename(img_path)) crop_img.save(file_name) ## 信心大于0.7,设置待定文件夹 elif face['confidence'] > 0.8: file_name = os.path.join(unknown_dir, str(i) + "_" + os.path.basename(img_path)) crop_img.save(file_name) except: print(img_path)
4. 建立异常数据集,并训练异常检测模型
4.1 数据集中有许多男老师,还有很多侧脸角度比较大的照片,还有些不是人脸的图片,需要手工汇集到一个文件夹,并准备训练异常检查模型,如果不把他们驱逐,就会大大影响loss下降
├── unknown
│ └── anomal 异常图片
│ ├── 男老师图片1.jpg
│ └── 侧脸图片.jpg
│ └── nomal 正常图片
│ ├── 三上悠亜.jpg
│ └── 河北彩花.jpg
4.2 训练异常检测模型,使用Facenet512模型,迁移学习,不冻结layer
import keras import tensorflow as tf from keras import applications, Sequential, Model from keras.layers import Input, Lambda, Dense, Flatten, Dropout, GlobalAveragePooling2D, Flatten from keras.preprocessing.image import ImageDataGenerator from deepface import DeepFace from keras.callbacks import EarlyStopping
train_datagen = ImageDataGenerator(rescale=1. / 255,rotation_range=30,fill_mode='nearest')
training_set = train_datagen.flow_from_directory('unknown', target_size=(160, 160), batch_size=16, class_mode='categorical') print(training_set.class_indices)
Facenet512 = DeepFace.build_model("Facenet512")
因为分类类别比较小,不再冻结layer参数
x = Flatten()(Facenet512.layers-4.output) x = Dropout(rate=0.5)(x) x = Dense(training_set.num_classes, activation='softmax')(x) model = Model(inputs=Facenet512.input, outputs=x)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics='accuracy')
8回合loss不再下降,就停止训练
history = model.fit_generator(training_set, callbacks=EarlyStopping(patience=8, monitor='loss'), epochs=100)
保存模型
model.save("anomal.keras")
Found 1287 images belonging to 2 classes.
{'anomal': 0, 'nomal': 1}
Epoch 1/100
81/81 [==============================] - 20s 110ms/step - loss: 0.1508 - accuracy: 0.9456
Epoch 2/100
81/81 [==============================] - 8s 97ms/step - loss: 0.1264 - accuracy: 0.9542
Epoch 3/100
81/81 [==============================] - 8s 98ms/step - loss: 0.0962 - accuracy: 0.9689
Epoch 4/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0732 - accuracy: 0.9681
Epoch 5/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0639 - accuracy: 0.9751
Epoch 6/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0563 - accuracy: 0.9744
Epoch 7/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0506 - accuracy: 0.9837
Epoch 8/100
81/81 [==============================] - 8s 98ms/step - loss: 0.0302 - accuracy: 0.9891
Epoch 9/100
81/81 [==============================] - 8s 99ms/step - loss: 0.0271 - accuracy: 0.9930
Epoch 10/100
81/81 [==============================] - 8s 98ms/step - loss: 0.0319 - accuracy: 0.9907
Epoch 11/100
81/81 [==============================] - 8s 98ms/step - loss: 0.0372 - accuracy: 0.9876
Epoch 12/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0482 - accuracy: 0.9868 1s
Epoch 13/100
81/81 [==============================] - 8s 96ms/step - loss: 0.1346 - accuracy: 0.9744
Epoch 14/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0651 - accuracy: 0.9751
Epoch 15/100
81/81 [==============================] - 8s 98ms/step - loss: 0.0822 - accuracy: 0.9713
Epoch 16/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0249 - accuracy: 0.9915
Epoch 17/100
81/81 [==============================] - 8s 99ms/step - loss: 0.0435 - accuracy: 0.9837
Epoch 18/100
81/81 [==============================] - 8s 98ms/step - loss: 0.0495 - accuracy: 0.9876
Epoch 19/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0142 - accuracy: 0.9930
Epoch 20/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0202 - accuracy: 0.9922
Epoch 21/100
81/81 [==============================] - 8s 99ms/step - loss: 0.0372 - accuracy: 0.9821
Epoch 22/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0170 - accuracy: 0.9922
Epoch 23/100
81/81 [==============================] - 8s 99ms/step - loss: 0.0065 - accuracy: 0.9977
Epoch 24/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0076 - accuracy: 0.9969
Epoch 25/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0044 - accuracy: 0.9992
Epoch 26/100
81/81 [==============================] - 8s 96ms/step - loss: 0.0228 - accuracy: 0.9915
Epoch 27/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0489 - accuracy: 0.9829
Epoch 28/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0292 - accuracy: 0.9915
Epoch 29/100
81/81 [==============================] - 8s 99ms/step - loss: 0.0329 - accuracy: 0.9876
Epoch 30/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0073 - accuracy: 0.9977
Epoch 31/100
81/81 [==============================] - 8s 98ms/step - loss: 0.0022 - accuracy: 0.9992
Epoch 32/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0061 - accuracy: 0.9977
Epoch 33/100
81/81 [==============================] - 8s 98ms/step - loss: 0.0082 - accuracy: 0.9969
Epoch 34/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0154 - accuracy: 0.9961
Epoch 35/100
81/81 [==============================] - 8s 98ms/step - loss: 0.0194 - accuracy: 0.9915
Epoch 36/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0142 - accuracy: 0.9938
Epoch 37/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0587 - accuracy: 0.9837
Epoch 38/100
81/81 [==============================] - 8s 97ms/step - loss: 0.0219 - accuracy: 0.9899
Epoch 39/100
81/81 [==============================] - 8s 98ms/step - loss: 0.0257 - accuracy: 0.9907
4.3 验证异常检测模型,并剔除actor文件夹的异常数据,通过不断在unknown 文件夹下挑选正常和非正常的数据,并重复训练数据,最终提高到一个理想的数据集质量
import os
import keras
import tensorflow as tf import numpy as np import re
from PIL import Image def image_files_in_folder(folder): return os.path.join(folder, f) for f in os.listdir(folder) if re.match(r'.*.(jpg|jpeg|png)', f, flags=re.I) gender_model = keras.models.load_model("anomal.keras") test_path = 'actor_head/' input_shape = gender_model.layers0.input.shape1:3
for i,class_dir in enumerate(os.listdir(test_path)): print(i,class_dir) if not os.path.isdir(os.path.join(test_path, class_dir)): continue path = os.path.join(test_path, class_dir) for img_path in image_files_in_folder(path):
filename=os.path.basename(img_path) img = keras.preprocessing.image.load_img(img_path, target_size=input_shape) ## 数据预处理 img_array = np.array(img)/255.0 img_array = tf.expand_dims(img_array, 0) # Create batch axis ## 预测的值 predict_array = gender_model.predict(img_array)[0] ## 数组最大值的下标 pred_index = np.argmax(predict_array) ## 如果90%概率为异常数据,就删除数据,老鼠屎坏了一锅粥 if pred_index==0 and predict_array[pred_index]>0.85: os.remove(img_path) elif pred_index==0 and predict_array[pred_index]>0.75: ## 其他就存储到unknown 下,然后人工筛选到anomal和nomal,之后重新训练模型,以此往复 Image.open(img_path).save("unknown/"+filename)
C:\Users\cc\miniconda3\envs\tf-gpu\lib\site-packages\keras\layers\core.py:1043: UserWarning: deepface.basemodels.Facenet is not loaded, but a Lambda layer uses it. It may cause errors. warnings.warn('{} is not loaded, but a Lambda layer uses it. '
0 .DS_Store 1 Julia 2 Minamo 3 さつき芽衣 4 七ツ森りり 5 三上悠亜 6 上羽絢 7 中山ふみか 8 乙アリス 9 二階堂夢 10 伊藤舞雪 11 倉本すみれ 12 八掛うみ 13 八木奈々 14 初川みなみ 15 加美杏奈 16 南乃そら 17 古川いおり 18 吉根ゆりあ 19 吉沢明歩 20 四宮ありす 21 夏希まろん 22 夢乃あいか 23 天使もえ 24 天川そら 25 天音まひな 26 奥田咲 27 姫咲はな 28 安齋らら 29 宮下玲奈 30 小倉由菜 31 小湊よつ葉 32 小花のん 33 小野六花 34 山岸逢花 35 山手梨愛 36 川上奈々美 37 工藤ララ 38 希島あいり 39 庵ひめか 40 弥生みづき 41 愛弓りょう 42 戸田真琴 43 推川ゆうり 44 新井リマ 45 新村あかり 46 明日見未来 47 明里つむぎ 48 月乃ルナ 49 有岡みう 50 有栖花あか 51 望月あやか 52 木下ひまり 53 本郷愛 54 東條なつ 55 松下紗栄子 56 松本いちか 57 架乃ゆら 58 柏木こなつ 59 桃乃木かな 60 桃園怜奈 61 桜空もも 62 梓ヒカリ 63 森日向子 64 森沢かな 65 椿りか 66 楓ふうあ 67 楓カレン 68 楪カレン 69 横宮七海 70 橋本ありな 71 水卜さくら 72 沙月恵奈 73 河北彩花 74 河合あすな 75 波多野結衣 76 涼森れむ 77 瀬名ひかり 78 田中ねね 79 白桃はな 80 白石茉莉奈 81 相沢みなみ 82 石原希望 83 石川澪 84 神宮寺ナオ 85 稲場るか 86 篠田ゆう 87 紗倉まな 88 結城りの 89 美乃すずめ 90 美波もも 91 美谷朱里 92 羽咲みはる 93 花狩まい 94 葵つかさ 95 藤森里穂 96 辻井ほのか 97 鈴木真夕 98 高瀬りな 99 鷲尾めい 100 黒川すみれ
5. 正菜,训练老师分类模型
5.1 训练模型
import tensorflow as tf import keras from keras import applications, Sequential, Model from keras.layers import Input, Lambda, Dense, Flatten, Dropout, GlobalAveragePooling2D, Flatten from keras.preprocessing.image import ImageDataGenerator from deepface import DeepFace from keras.callbacks import EarlyStopping
train_datagen = ImageDataGenerator(rescale=1. / 255)
training_set = train_datagen.flow_from_directory('actor_head', target_size=(160, 160), batch_size=128, class_mode='categorical') import pickle
保存字典,以便以后验证模型
with open('teacher.pickle', 'wb') as f: pickle.dump(training_set.class_indices, f)
Facenet512 = DeepFace.build_model("Facenet512")
后8层,可以训练
for layer in Facenet512.layers:-8: layer.trainable = False
去掉后面4层,加上自己的layers
x = Flatten()(Facenet512.layers-4.output) x = Dropout(rate=0.5)(x) x = Dense(training_set.num_classes, activation='softmax')(x) model = Model(inputs=Facenet512.input, outputs=x) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics='accuracy')
history = model.fit_generator(training_set, workers=2, callbacks=EarlyStopping(patience=5, monitor='loss'), epochs=100) model.save("teacher.keras")
Found 9551 images belonging to 100 classes.
Epoch 1/100
75/75 [==============================] - 18s 121ms/step - loss: 2.5396 - accuracy: 0.4803
Epoch 2/100
75/75 [==============================] - 8s 107ms/step - loss: 1.0726 - accuracy: 0.7572
Epoch 3/100
75/75 [==============================] - 8s 106ms/step - loss: 0.8041 - accuracy: 0.8111
Epoch 4/100
75/75 [==============================] - 8s 106ms/step - loss: 0.6838 - accuracy: 0.8336
Epoch 5/100
75/75 [==============================] - 8s 106ms/step - loss: 0.6055 - accuracy: 0.8523
Epoch 6/100
75/75 [==============================] - 8s 106ms/step - loss: 0.5483 - accuracy: 0.8622
Epoch 7/100
75/75 [==============================] - 8s 107ms/step - loss: 0.5228 - accuracy: 0.8674
Epoch 8/100
75/75 [==============================] - 8s 107ms/step - loss: 0.4691 - accuracy: 0.8790
Epoch 9/100
75/75 [==============================] - 8s 107ms/step - loss: 0.4465 - accuracy: 0.8877
Epoch 10/100
75/75 [==============================] - 8s 107ms/step - loss: 0.4162 - accuracy: 0.8913
Epoch 11/100
75/75 [==============================] - 8s 106ms/step - loss: 0.3973 - accuracy: 0.8982
Epoch 12/100
75/75 [==============================] - 8s 106ms/step - loss: 0.3821 - accuracy: 0.8988
Epoch 13/100
75/75 [==============================] - 8s 107ms/step - loss: 0.3546 - accuracy: 0.9055
Epoch 14/100
75/75 [==============================] - 8s 106ms/step - loss: 0.3389 - accuracy: 0.9112
Epoch 15/100
75/75 [==============================] - 8s 106ms/step - loss: 0.3133 - accuracy: 0.9150
Epoch 16/100
75/75 [==============================] - 8s 107ms/step - loss: 0.2989 - accuracy: 0.9180
Epoch 17/100
75/75 [==============================] - 8s 106ms/step - loss: 0.2954 - accuracy: 0.9199
Epoch 18/100
75/75 [==============================] - 8s 106ms/step - loss: 0.2809 - accuracy: 0.9215
Epoch 19/100
75/75 [==============================] - 8s 106ms/step - loss: 0.2806 - accuracy: 0.9230
Epoch 20/100
75/75 [==============================] - 8s 107ms/step - loss: 0.2534 - accuracy: 0.9324
Epoch 21/100
75/75 [==============================] - 8s 107ms/step - loss: 0.2402 - accuracy: 0.9345
Epoch 22/100
75/75 [==============================] - 8s 106ms/step - loss: 0.2428 - accuracy: 0.9320
Epoch 23/100
75/75 [==============================] - 8s 106ms/step - loss: 0.2287 - accuracy: 0.9352
Epoch 24/100
75/75 [==============================] - 8s 107ms/step - loss: 0.2176 - accuracy: 0.9430
Epoch 25/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1991 - accuracy: 0.9451
Epoch 26/100
75/75 [==============================] - 8s 106ms/step - loss: 0.2094 - accuracy: 0.9404
Epoch 27/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1914 - accuracy: 0.9458
Epoch 28/100
75/75 [==============================] - 8s 107ms/step - loss: 0.1851 - accuracy: 0.9492
Epoch 29/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1792 - accuracy: 0.9488
Epoch 30/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1713 - accuracy: 0.9512
Epoch 31/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1724 - accuracy: 0.9523
Epoch 32/100
75/75 [==============================] - 8s 107ms/step - loss: 0.1761 - accuracy: 0.9471
Epoch 33/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1685 - accuracy: 0.9531
Epoch 34/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1652 - accuracy: 0.9490
Epoch 35/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1552 - accuracy: 0.9541
Epoch 36/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1555 - accuracy: 0.9546
Epoch 37/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1472 - accuracy: 0.9561
Epoch 38/100
75/75 [==============================] - 8s 107ms/step - loss: 0.1456 - accuracy: 0.9567
Epoch 39/100
75/75 [==============================] - 8s 107ms/step - loss: 0.1360 - accuracy: 0.9586
Epoch 40/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1315 - accuracy: 0.9604
Epoch 41/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1345 - accuracy: 0.9602
Epoch 42/100
75/75 [==============================] - 8s 107ms/step - loss: 0.1260 - accuracy: 0.9629
Epoch 43/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1208 - accuracy: 0.9639
Epoch 44/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1273 - accuracy: 0.9607
Epoch 45/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1236 - accuracy: 0.9639
Epoch 46/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1224 - accuracy: 0.9615
Epoch 47/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1127 - accuracy: 0.9652
Epoch 48/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1209 - accuracy: 0.9632
Epoch 49/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1117 - accuracy: 0.9665
Epoch 50/100
75/75 [==============================] - 8s 107ms/step - loss: 0.1057 - accuracy: 0.9697
Epoch 51/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1156 - accuracy: 0.9639
Epoch 52/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1098 - accuracy: 0.9637
Epoch 53/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0988 - accuracy: 0.9671
Epoch 54/100
75/75 [==============================] - 8s 107ms/step - loss: 0.1099 - accuracy: 0.9646
Epoch 55/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1141 - accuracy: 0.9620
Epoch 56/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1167 - accuracy: 0.9631
Epoch 57/100
75/75 [==============================] - 8s 107ms/step - loss: 0.0974 - accuracy: 0.9702
Epoch 58/100
75/75 [==============================] - 8s 107ms/step - loss: 0.1016 - accuracy: 0.9681
Epoch 59/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0926 - accuracy: 0.9713
Epoch 60/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1017 - accuracy: 0.9678
Epoch 61/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0885 - accuracy: 0.9708
Epoch 62/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0982 - accuracy: 0.9681
Epoch 63/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0973 - accuracy: 0.9669
Epoch 64/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0883 - accuracy: 0.9719
Epoch 65/100
75/75 [==============================] - 8s 107ms/step - loss: 0.1001 - accuracy: 0.9687
Epoch 66/100
75/75 [==============================] - 8s 106ms/step - loss: 0.1059 - accuracy: 0.9642
Epoch 67/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0980 - accuracy: 0.9669
Epoch 68/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0882 - accuracy: 0.9705
Epoch 69/100
75/75 [==============================] - 8s 107ms/step - loss: 0.0856 - accuracy: 0.9711
Epoch 70/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0815 - accuracy: 0.9718
Epoch 71/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0901 - accuracy: 0.9700
Epoch 72/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0746 - accuracy: 0.9749
Epoch 73/100
75/75 [==============================] - 8s 107ms/step - loss: 0.0839 - accuracy: 0.9726
Epoch 74/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0855 - accuracy: 0.9713
Epoch 75/100
75/75 [==============================] - 8s 107ms/step - loss: 0.0964 - accuracy: 0.9691
Epoch 76/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0908 - accuracy: 0.9719
Epoch 77/100
75/75 [==============================] - 8s 106ms/step - loss: 0.0847 - accuracy: 0.9729
5.2 验证模型 从百度搜索老师的图片,并存储到actor_test文件夹下
测试集的正确率有8成,数据集多的老师,可能正确率高些
import tensorflow as tf import keras import pickle import numpy as np actor_model = keras.models.load_model('teacher.keras') ## label 字典 dict_act={} ## 反向 label 字典 act_dict={} with open("teacher.pickle", "rb") as tf: dict_act=pickle.load(tf) for key, value in dict_act.items(): act_dict[value]=key
import os import re
from deepface import DeepFace from PIL import Image def image_files_in_folder(folder): return os.path.join(folder, f) for f in os.listdir(folder) if re.match(r'.*.(jpg|jpeg|png|webp)', f, flags=re.I) test_dir = 'actor_test' from mtcnn import MTCNN
mtcnn_model = MTCNN(min_face_size=100) input_shape = actor_model.layers0.input.shape1:3 for class_dir in os.listdir(test_dir): class_path = os.path.join(test_dir, class_dir) if not os.path.isdir(class_path): continue # Loop through each training image for the current person for img_path in image_files_in_folder(class_path): img_file = Image.open(img_path) faces = mtcnn_model.detect_faces(np.array(img_file)) for face in faces: if face'confidence' > 0 : x, y, width, height = face'box' ## 从原图裁剪出人脸图片 crop_img = img_file.crop((x, y, x + width, y + height)).resize(input_shape) img_array = np.array(crop_img)/255.0 ## 预测的值 predict_array = actor_model.predict(np.expand_dims(img_array, axis=0))0 pred_index = np.argmax(predict_array) pred_class=act_dictpred_index pred_rate=predict_arraypred_index print("文件路径:{},预测值:{},实际值:{},概率:{}".format(img_path,pred_class,class_dir,pred_rate))
C:\Users\cc\miniconda3\envs\tf-gpu\lib\site-packages\keras\layers\core.py:1043: UserWarning: deepface.basemodels.Facenet is not loaded, but a Lambda layer uses it. It may cause errors. warnings.warn('{} is not loaded, but a Lambda layer uses it. '
文件路径:actor_test\三上悠亜\67f49f3e783e497a80170bcda0c58c79.jpeg,预测值:三上悠亜,实际值:三上悠亜,概率:0.9999772310256958 文件路径:actor_test\三上悠亜\9889e341844b46bc975daf06132e97da.jpeg,预测值:三上悠亜,实际值:三上悠亜,概率:0.9999998807907104 文件路径:actor_test\三上悠亜\cc92b596810043fe9a4eb890f2811849.jpeg,预测值:三上悠亜,实际值:三上悠亜,概率:1.0 文件路径:actor_test\三上悠亜\d57b0d150b7c40bc9a98b8e70a71dee3.jpeg,预测值:三上悠亜,实际值:三上悠亜,概率:0.9999251365661621 文件路径:actor_test\三上悠亜\ff01981fa86c41d89bdc91f13ffeeb4f.jpeg,预测值:三上悠亜,实际值:三上悠亜,概率:0.9999998807907104 文件路径:actor_test\三上悠亜\u=679109634,3255864154&fm=253&fmt=auto&app=138&f=JPEG.webp,预测值:桜空もも,实际值:三上悠亜,概率:0.7386064529418945 文件路径:actor_test\三上悠亜\下载.jpeg,预测值:三上悠亜,实际值:三上悠亜,概率:0.9992682337760925 文件路径:actor_test\吉沢明歩\00e93901213fb80e056eaa6834d12f2eb83894d6.jpeg,预测值:吉沢明歩,实际值:吉沢明歩,概率:0.8445957899093628 文件路径:actor_test\吉沢明歩\a686c9177f3e670975088f4039c79f3df8dc5501.jpeg,预测值:吉沢明歩,实际值:吉沢明歩,概率:0.9998031258583069 文件路径:actor_test\吉沢明歩\aa64034f78f0f736c324f3c40b55b319eac41318.jpeg,预测值:吉沢明歩,实际值:吉沢明歩,概率:0.9969291090965271 文件路径:actor_test\吉沢明歩\b7003af33a87e9506bad38d312385343faf2b4d3.jpeg,预测值:吉沢明歩,实际值:吉沢明歩,概率:0.9996601343154907 文件路径:actor_test\吉沢明歩\ce2e204a56ed44fd9a15887b5ba01015.png,预测值:吉沢明歩,实际值:吉沢明歩,概率:0.9516931772232056 文件路径:actor_test\吉沢明歩\ec55f9c0c40f126ce0b61b.jpg,预测值:吉沢明歩,实际值:吉沢明歩,概率:0.9992449283599854 文件路径:actor_test\吉沢明歩\ooYBAGEfK4OAdtMgAAF3o5oBZgc30.jpeg,预测值:吉沢明歩,实际值:吉沢明歩,概率:0.9940263032913208 文件路径:actor_test\河北彩花\u=1229114700,887308783&fm=253&fmt=auto&app=120&f=JPEG.webp,预测值:希島あいり,实际值:河北彩花,概率:0.8358818292617798 文件路径:actor_test\河北彩花\u=1407682406,2760660712&fm=253&fmt=auto&app=138&f=JPEG.webp,预测值:河北彩花,实际值:河北彩花,概率:0.7551858425140381 文件路径:actor_test\河北彩花\u=2045218031,4076180478&fm=253&fmt=auto.webp,预测值:河北彩花,实际值:河北彩花,概率:0.6508835554122925 文件路径:actor_test\河北彩花\u=381236696,2995450490&fm=253&fmt=auto&app=120&f=JPEG.webp,预测值:河北彩花,实际值:河北彩花,概率:0.9999761581420898 文件路径:actor_test\河北彩花\u=4196010652,1707160962&fm=253&fmt=auto&app=120&f=JPEG.webp,预测值:河北彩花,实际值:河北彩花,概率:1.0 文件路径:actor_test\河北彩花\下载 (1).jpeg,预测值:河北彩花,实际值:河北彩花,概率:1.0 文件路径:actor_test\河北彩花\下载.jpeg,预测值:河北彩花,实际值:河北彩花,概率:0.9999974966049194 文件路径:actor_test\波多野結衣\08f790529822720ec3dab3e377cb0a46f21fab97.jpg,预测值:波多野結衣,实际值:波多野結衣,概率:0.6821474432945251 文件路径:actor_test\波多野結衣\38f9a399bbb84c9fb047a46241926bf7.jpeg,预测值:南乃そら,实际值:波多野結衣,概率:0.6094668507575989 文件路径:actor_test\波多野結衣\44244f281cd244dc90c0ba27bd913371.jpeg,预测值:四宮ありす,实际值:波多野結衣,概率:0.74156653881073 文件路径:actor_test\波多野結衣\6f061d950a7b0208c9966ef86ed9f2d3572cc848.jpg,预测值:小花のん,实际值:波多野結衣,概率:0.997886598110199 文件路径:actor_test\波多野結衣\nQAp-fyeiwny3957990.jpg,预测值:安齋らら,实际值:波多野結衣,概率:0.8031250834465027 文件路径:actor_test\波多野結衣\下载 (1).jpeg,预测值:美谷朱里,实际值:波多野結衣,概率:0.9814733862876892 文件路径:actor_test\波多野結衣\下载.jpeg,预测值:波多野結衣,实际值:波多野結衣,概率:0.9999511241912842
总结
- 刚刚开始时候,迁移模型使用的vgg-face,这个模型真是又大又慢,效果也非常不好
- Deepface 也有探测人脸的功能,也有mtcnn模型
- 使用CPU训练模型,就是一个笑话
- 抓出将近9G的数据,提取人脸数据不到100MB; 分析,选型,再到抓取,再到清洗数据,花了将近一个星期,然而训练模型只需10分钟
- 买1080Ti显卡,必须换电源600W,加上window+cuda+cudnn+tf2+keras+jupyter,硬件+软件 环境搭建,花了一个星期
- 抓取数据时候,还是在服务器上吧,别问我为什么,清洗数据的时候,还是使用多线程处理吧,不然又丑又长,只有干等
- 不管你怎么调优模型都收效甚微,提高数据集的质量才是王道