一、選題背景
臉部辨識技術是圖形識別和計算機視覺領域最富挑戰性的研究課題之一,也是近年來的研究熱點,人臉性別識別作為臉部辨識技術的重要組成部分也受到了廣泛地關注。人臉性別識別就是向計算機輸入人臉影象,經過某種方法或運算,得出其性別。這種識別對人眼來說很簡單,但對計算機卻並不是一件容易的事情。
二、機器學習案例設計方案
從網站中下載相關的資料集,對資料集進行整理,在python的環境中,給資料集中的檔案進行劃分,對資料進行預處理,利用keras,構建神經網路,訓練模型,匯入圖片測試模型。
資料來源:kaggle,網址:https://www.kaggle.com/maciejgronczynski/biggest-genderface-recognition-dataset
資料集包含27167個jpg檔案,其中17678個是男性面部照片,9489個是女性照片。
三、機器學習的實驗步驟
1.下載資料集
2.匯入需要用到的庫
1 import os 2 import random 3 from shutil import copy 4 from matplotlib import pyplot as plt 5 from keras import optimizers 6 from keras import models 7 from keras import layers 8 from keras.preprocessing.image import ImageDataGenerator 9 from keras.models import load_model 10 from PIL import Image
3.資料集劃分,由總的資料集生成分別生成訓練集,測試集和驗證集
1 # 女性圖片訓練集想儲存到的根路徑 2 woman_train_dir = r'sex\faces\train\woman' 3 # 女性圖片驗證集想儲存到的根路徑 4 woman_validation_dir = r'sex\faces\validation\woman' 5 # 女性圖片測試集想儲存到的根路徑 6 woman_test_dir = r'sex\faces\test\woman' 7 8 # 男性圖片訓練集想儲存到的根路徑 9 man_train_dir = r'sex\faces\train\man' 10 # 男性圖片驗證集想儲存到的根路徑 11 man_validation_dir = r'sex\faces\validation\man' 12 # 男性圖片測試集想儲存到的根路徑 13 man_test_dir = r'sex\faces\test\man' 14 15 # 建立列表,儲存上方6個路徑 16 dir_list = [woman_train_dir, woman_validation_dir, woman_test_dir, 17 man_train_dir, man_validation_dir, man_test_dir] 18 # 如果目錄不存在,則建立 19 for dir_child in dir_list: 20 if not os.path.isdir(dir_child): 21 os.makedirs(dir_child) 22 23 # 女性圖片根路徑 24 woman_path = r'sex\faces\woman' 25 # 獲取 woman_path 下的資料夾列表 26 woman_path_list = os.listdir(woman_path) 27 # 遍歷列表,取6000張圖片加入訓練集,3000張圖片加入驗證集,其餘加入測試集 28 for i in range(len(woman_path_list)): 29 child_path = os.path.join(woman_path, woman_path_list[i]) 30 if i < 6000: 31 to_path = woman_train_dir 32 elif i < 9000: 33 to_path = woman_validation_dir 34 else: 35 to_path = woman_test_dir 36 copy(child_path, to_path) 37 38 # 男性圖片根路徑 39 man_path = r'sex\faces\man' 40 # 獲取 man_path 下的資料夾列表 41 man_path_list = os.listdir(man_path) 42 # 遍歷列表,取6000張圖片加入訓練集,3000張圖片加入驗證集,其餘加入測試集 43 for i in range(len(man_path_list)): 44 child_path = os.path.join(man_path, man_path_list[i]) 45 if i < 6000: 46 to_path = man_train_dir 47 elif i < 9000: 48 to_path = man_validation_dir 49 else: 50 to_path = man_test_dir 51 copy(child_path, to_path) 52 53 # 輸出各目錄中的檔案數目 54 train_path = "sex/faces/train/" 55 print('total training woman images:', len(os.listdir(train_path+"woman"))) 56 print('total training man images:', len(os.listdir(train_path+"man"))) 57 58 valid_path = "sex/faces/validation/" 59 print('total validation woman images:', len(os.listdir(valid_path+"woman"))) 60 print('total validation man images:', len(os.listdir(valid_path+"man"))) 61 62 test_path = "sex/faces/test/" 63 print('total test woman images:', len(os.listdir(test_path+"woman"))) 64 print('total test man images:', len(os.listdir(test_path+"man")))
4.檢視影象以及對應標籤
1 # 檢視影象以及對應的標籤 2 fit, ax = plt.subplots(nrows=3, ncols=3, figsize=(10, 7)) 3 # 檢視影象的根路徑 4 test_view_path = r'sex\faces\test\man' 5 # 獲取 test_view_path 下的資料夾列表 6 test_view_list = os.listdir(test_view_path) 7 for i, a in enumerate(ax.flat): 8 view_path = os.path.join(test_view_path, test_view_list[i]) 9 # 讀取源圖 10 a.imshow(plt.imread(view_path)) 11 # 新增影象名稱 12 a.set_title(man_path_list[i]) 13 plt.tight_layout() # 自動調整子圖引數,使之填充整個影象區域 14 plt.show()
5.圖片預處理
1 # 圖片預處理 2 # 批次大小 3 BATCH_SIZE = 20 4 # 輸入圖片的大小 5 IMG_SIZE = (150, 150) 6 7 # 歸一化處理 8 train_datagen = ImageDataGenerator(rescale=1./255) 9 validation_datagen = ImageDataGenerator(rescale=1./255) 10 test_datagen = ImageDataGenerator(rescale=1./255) 11 12 train_dir = 'sex/faces/train' # 指向訓練集圖片目錄路徑 13 14 train_generator = train_datagen.flow_from_directory( 15 train_dir, 16 target_size=IMG_SIZE, # 輸入訓練影象尺寸 17 batch_size=BATCH_SIZE, 18 color_mode='rgb', 19 class_mode='binary') 20 21 validation_dir = 'sex/faces/validation' # 指向驗證集圖片目錄路徑 22 23 validation_generator = validation_datagen.flow_from_directory( 24 validation_dir, 25 target_size=IMG_SIZE, 26 batch_size=BATCH_SIZE, 27 color_mode='rgb', 28 class_mode='binary') 29 30 test_dir = 'sex/faces/test' # 指向測試集圖片目錄路徑 31 32 test_generator = test_datagen.flow_from_directory( 33 test_dir, 34 target_size=IMG_SIZE, 35 batch_size=BATCH_SIZE, 36 color_mode='rgb', 37 class_mode='binary')
6.檢視經過處理的圖片以及它的binary標籤
1 # 檢視經過處理的圖片以及它的binary標籤 2 fit, ax = plt.subplots(nrows=3, ncols=3, figsize=(10, 7)) 3 4 for i, a in enumerate(ax.flat): 5 img, label = test_generator.next() 6 a.imshow(img[0],) 7 a.set_title(label[0]) 8 9 plt.tight_layout() 10 plt.show()
7.構建神經網路並對模型進行訓練
1 # 構建神經網路 2 model = models.Sequential() 3 4 # 1.Conv2D層,32個過濾器。輸出圖片尺寸:150-3+1=148*148,引數數量:32*3*3*3+32=896 5 model.add(layers.Conv2D(32, (3, 3), 6 activation='relu', 7 input_shape=(150, 150, 3))) # 折積層1 8 model.add(layers.MaxPooling2D((2, 2))) # 最大值池化層1。輸出圖片尺寸:148/2=74*74 9 10 # 2.Conv2D層,64個過濾器。輸出圖片尺寸:74-3+1=72*72,引數數量:64*3*3*32+64=18496 11 model.add(layers.Conv2D(64, (3, 3), 12 activation='relu')) # 折積層2 13 model.add(layers.MaxPooling2D((2, 2))) # 最大值池化層2。輸出圖片尺寸:72/2=36*36 14 15 # 3.Conv2D層,128個過濾器。輸出圖片尺寸:36-3+1=34*34,引數數量:128*3*3*64+128=73856 16 model.add(layers.Conv2D(128, (3, 3), 17 activation='relu')) # 折積層3 18 model.add(layers.MaxPooling2D((2, 2))) # 最大值池化層3。輸出圖片尺寸:34/2=17*17 19 20 # 4.Conv2D層,128個過濾器。輸出圖片尺寸:17-3+1=15*15,引數數量:128*3*3*128+128=147584 21 model.add(layers.Conv2D(128, (3, 3), 22 activation='relu')) # 折積層4 23 model.add(layers.MaxPooling2D((2, 2))) # 最大值池化層4。輸出圖片尺寸:15/2=7*7 24 25 # 將輸入層的資料壓縮成1維資料,全連線層只能處理一維資料 26 model.add(layers.Flatten()) 27 28 # 全連線層 29 model.add(layers.Dense(512, 30 activation='relu')) # 全連線層1 31 model.add(layers.Dense(1, 32 activation='sigmoid')) # 全連線層2,作為輸出層。sigmoid分類,輸出是兩類別 33 34 # 編譯模型 35 # RMSprop 優化器。因為網路最後一層是單一sigmoid單元, 36 # 所以使用二元交叉熵作為損失函數 37 model.compile(loss='binary_crossentropy', 38 optimizer=optimizers.RMSprop(lr=1e-4), 39 metrics=['acc']) 40 41 # 看一下特徵圖的維度如何隨著每層變化 42 model.summary()
1 # 訓練模型50輪次 2 history_save = model.fit( 3 train_generator, 4 steps_per_epoch=100, 5 epochs=50, 6 validation_data=validation_generator, 7 validation_steps=50) 8 # 將訓練過程產生的資料儲存為h5檔案 9 model.save('sex/faces/sex_model.h5')
8.繪製損失曲線和精度曲線圖
1 # 繪製損失曲線和精度曲線圖 2 accuracy = history_save.history['acc'] # 訓練集精度 3 loss = history_save.history['loss'] # 訓練集損失 4 val_loss = history_save.history['val_loss'] # 驗證集精度 5 val_accuracy = history_save.history['val_acc'] # 驗證集損失 6 plt.figure(figsize=(17, 7)) 7 8 # 訓練集精度和驗證集精度曲線圖圖 9 plt.subplot(2, 2, 1) 10 plt.plot(range(50), accuracy, 'bo', label='Training Accuracy') 11 plt.plot(range(50), val_accuracy, label='Validation Accuracy') 12 plt.title('Training and Validation Accuracy') 13 plt.legend(loc='center right') 14 15 # 訓練集損失和驗證集損失圖 16 plt.subplot(2, 2, 2) 17 plt.plot(range(50), loss, 'bo', label='Training Loss') 18 plt.plot(range(50), val_loss, label='Validation Loss') 19 plt.title('Training and Validation Loss') 20 plt.legend(loc='center right') 21 22 # 訓練集精度和損失散點圖 23 plt.subplot(2, 2, 3) 24 plt.scatter(range(50), accuracy, label="Training Accuracy", color='b', s=25, marker="o") 25 plt.scatter(range(50), loss, label="Training Loss", color='r', s=25, marker="o") 26 plt.title('Training : Accuracy and Loss') 27 plt.legend(loc='center right') 28 29 # 驗證集精度和損失散點圖 30 plt.subplot(2, 2, 4) 31 plt.scatter(range(50), val_accuracy, label="Validation Accuracy", color='b', s=25, marker="o") 32 plt.scatter(range(50), val_loss, label="Validation Loss", color='r', s=25, marker="o") 33 plt.title('Validation : Accuracy and Loss') 34 plt.legend(loc='center right') 35 36 plt.show()
9.用ImageDataGenerator資料增強
1 train_datagen = ImageDataGenerator(rescale=1./255, 2 rotation_range=40, # 將影象隨機旋轉40度 3 width_shift_range=0.2, # 在水平方向上平移比例為0.2 4 height_shift_range=0.2, # 在垂直方向上平移比例為0.2 5 shear_range=0.2, # 隨機錯切變換的角度為0.2 6 zoom_range=0.2, # 圖片隨機縮放的範圍為0.2 7 horizontal_flip=True, # 隨機將一半影象水平翻轉 8 fill_mode='nearest') # 填充建立畫素 9 validation_datagen = ImageDataGenerator(rescale=1./255) 10 11 train_generator = train_datagen.flow_from_directory( 12 train_dir, 13 target_size=IMG_SIZE, # 輸入訓練影象尺寸 14 batch_size=BATCH_SIZE, 15 class_mode='binary') 16 17 validation_generator = validation_datagen.flow_from_directory( 18 validation_dir, 19 target_size=IMG_SIZE, 20 batch_size=BATCH_SIZE, 21 class_mode='binary')
再次訓練模型,並繪製繪製損失曲線和精度曲線圖,得到結果圖
10.隨機選取測試集的圖片進行預測
1 # 將圖片縮小到(150,150)的大小 2 def convertjpg(jpgfile, outdir, width=150, height=150): 3 img = Image.open(jpgfile) 4 try: 5 new_img = img.resize((width, height), Image.BILINEAR) 6 new_img.save(os.path.join(outdir, os.path.basename(jpgfile))) 7 except Exception as e: 8 print(e) 9 10 # 從測試集隨機獲取一張男性圖片 11 man_test = r'sex\faces\test\man' 12 man_test_list = os.listdir(man_test) 13 key = random.randint(0, len(man_test_list)) 14 img_key = man_test_list[key] 15 jpg_file = os.path.join(man_test, img_key) 16 convertjpg(jpg_file, "sex/faces/test") # 影象大小改變到(150,150) 17 img_scale = plt.imread('sex/faces/test/' + img_key) 18 plt.imshow(img_scale) # 顯示改變影象大小後的圖片確實變到了(150,150)大小 19 20 # 呼叫訓練模型結果進行預測 21 model = load_model('sex/faces/sex_model.h5') 22 img_scale = img_scale.reshape(1, 150, 150, 3).astype('float32') 23 img_scale = img_scale/255 # 歸一化到0-1之間 24 result = model.predict(img_scale) # 取圖片資訊 25 if result > 0.5: 26 print('該圖片是女性的概率為:', result) 27 else: 28 print('該圖片是男性的概率為:', 1-result) 29 plt.show() # 列印尺寸改變後的影象
1 # 從測試集隨機獲取一張女性圖片 2 woman_test = r'sex\faces\test\woman' 3 woman_test_list = os.listdir(woman_test) 4 key = random.randint(0, len(woman_test_list)) 5 img_key = woman_test_list[key] 6 jpg_file = os.path.join(woman_test, img_key) 7 convertjpg(jpg_file, "sex/faces/test") # 影象大小改變到(150,150) 8 img_scale = plt.imread('sex/faces/test/' + img_key) 9 plt.imshow(img_scale) # 顯示改變影象大小後的圖片確實變到了(150,150)大小 10 11 # 呼叫訓練模型結果進行預測 12 model = load_model('sex/faces/sex_model.h5') 13 img_scale = img_scale.reshape(1, 150, 150, 3).astype('float32') 14 img_scale = img_scale/255 # 歸一化到0-1之間 15 result = model.predict(img_scale) # 取圖片資訊 16 if result > 0.5: 17 print('該圖片是女性的概率為:', result) 18 else: 19 print('該圖片是男性的概率為:', 1-result) 20 plt.show() # 列印尺寸改變後的影象
11.自定義一張圖片進行預測
# 自定義一張男性圖片進行預測 diy_img = 'sex/faces/man.jpg' convertjpg(diy_img, "sex") # 影象大小改變到(150,150) img_scale = plt.imread('sex/man.jpg') plt.imshow(img_scale) # 顯示改變影象大小後的圖片確實變到了(150,150)大小 # 呼叫資料增強後的訓練模型結果進行預測 model = load_model('sex/faces/sex_model_idg.h5') img_scale = img_scale.reshape(1, 150, 150, 3).astype('float32') img_scale = img_scale/255 # 歸一化到0-1之間 result = model.predict(img_scale) # 取圖片資訊 if result > 0.5: print('該圖片是女性的概率為:', result) else: print('該圖片是男性的概率為:', 1-result) plt.show() # 列印尺寸改變後的影象
1 # 自定義一張女性圖片進行預測 2 diy_img = 'sex/faces/woman_2.jpg' 3 convertjpg(diy_img, "sex") # 影象大小改變到(150,150) 4 img_scale = plt.imread('sex/woman_2.jpg') 5 plt.imshow(img_scale) # 顯示改變影象大小後的圖片確實變到了(150,150)大小 6 7 # 呼叫資料增強後的訓練模型結果進行預測 8 model = load_model('sex/faces/sex_model.h5') 9 img_scale = img_scale.reshape(1, 150, 150, 3).astype('float32') 10 img_scale = img_scale/255 # 歸一化到0-1之間 11 result = model.predict(img_scale) # 取圖片資訊 12 if result > 0.5: 13 print('該圖片是女性的概率為:', result) 14 else: 15 print('該圖片是男性的概率為:', 1-result) 16 plt.show() # 列印尺寸改變後的影象
全部程式碼:
1 import os 2 import random 3 from shutil import copy 4 from matplotlib import pyplot as plt 5 from keras import optimizers 6 from keras import models 7 from keras import layers 8 from keras.preprocessing.image import ImageDataGenerator 9 from keras.models import load_model 10 from PIL import Image 11 12 # 女性圖片訓練集想儲存到的根路徑 13 woman_train_dir = r'sex\faces\train\woman' 14 # 女性圖片驗證集想儲存到的根路徑 15 woman_validation_dir = r'sex\faces\validation\woman' 16 # 女性圖片測試集想儲存到的根路徑 17 woman_test_dir = r'sex\faces\test\woman' 18 19 # 男性圖片訓練集想儲存到的根路徑 20 man_train_dir = r'sex\faces\train\man' 21 # 男性圖片驗證集想儲存到的根路徑 22 man_validation_dir = r'sex\faces\validation\man' 23 # 男性圖片測試集想儲存到的根路徑 24 man_test_dir = r'sex\faces\test\man' 25 26 # 建立列表,儲存上方6個路徑 27 dir_list = [woman_train_dir, woman_validation_dir, woman_test_dir, 28 man_train_dir, man_validation_dir, man_test_dir] 29 # 如果目錄不存在,則建立 30 for dir_child in dir_list: 31 if not os.path.isdir(dir_child): 32 os.makedirs(dir_child) 33 34 # 女性圖片根路徑 35 woman_path = r'sex\faces\woman' 36 # 獲取 woman_path 下的資料夾列表 37 woman_path_list = os.listdir(woman_path) 38 # 遍歷列表,取6000張圖片加入訓練集,3000張圖片加入驗證集,其餘加入測試集 39 for i in range(len(woman_path_list)): 40 child_path = os.path.join(woman_path, woman_path_list[i]) 41 if i < 6000: 42 to_path = woman_train_dir 43 elif i < 9000: 44 to_path = woman_validation_dir 45 else: 46 to_path = woman_test_dir 47 copy(child_path, to_path) 48 49 # 男性圖片根路徑 50 man_path = r'sex\faces\man' 51 # 獲取 man_path 下的資料夾列表 52 man_path_list = os.listdir(man_path) 53 # 遍歷列表,取6000張圖片加入訓練集,3000張圖片加入驗證集,其餘加入測試集 54 for i in range(len(man_path_list)): 55 child_path = os.path.join(man_path, man_path_list[i]) 56 if i < 6000: 57 to_path = man_train_dir 58 elif i < 9000: 59 to_path = man_validation_dir 60 else: 61 to_path = man_test_dir 62 copy(child_path, to_path) 63 64 # 輸出各目錄中的檔案數目 65 train_path = "sex/faces/train/" 66 print('total training woman images:', len(os.listdir(train_path+"woman"))) 67 print('total training man images:', len(os.listdir(train_path+"man"))) 68 69 valid_path = "sex/faces/validation/" 70 print('total validation woman images:', len(os.listdir(valid_path+"woman"))) 71 print('total validation man images:', len(os.listdir(valid_path+"man"))) 72 73 test_path = "sex/faces/test/" 74 print('total test woman images:', len(os.listdir(test_path+"woman"))) 75 print('total test man images:', len(os.listdir(test_path+"man"))) 76 77 # 檢視影象以及對應的標籤 78 fit, ax = plt.subplots(nrows=3, ncols=3, figsize=(10, 7)) 79 # 檢視影象的根路徑 80 test_view_path = r'sex\faces\test\man' 81 # 獲取 test_view_path 下的資料夾列表 82 test_view_list = os.listdir(test_view_path) 83 for i, a in enumerate(ax.flat): 84 view_path = os.path.join(test_view_path, test_view_list[i]) 85 # 讀取源圖 86 a.imshow(plt.imread(view_path)) 87 # 新增影象名稱 88 a.set_title(man_path_list[i]) 89 plt.tight_layout() # 自動調整子圖引數,使之填充整個影象區域 90 plt.show() 91 92 # 圖片預處理 93 # 批次大小 94 BATCH_SIZE = 20 95 # 輸入圖片的大小 96 IMG_SIZE = (150, 150) 97 98 # 歸一化處理 99 train_datagen = ImageDataGenerator(rescale=1./255) 100 validation_datagen = ImageDataGenerator(rescale=1./255) 101 test_datagen = ImageDataGenerator(rescale=1./255) 102 103 train_dir = 'sex/faces/train' # 指向訓練集圖片目錄路徑 104 105 train_generator = train_datagen.flow_from_directory( 106 train_dir, 107 target_size=IMG_SIZE, # 輸入訓練影象尺寸 108 batch_size=BATCH_SIZE, 109 color_mode='rgb', 110 class_mode='binary') 111 112 validation_dir = 'sex/faces/validation' # 指向驗證集圖片目錄路徑 113 114 validation_generator = validation_datagen.flow_from_directory( 115 validation_dir, 116 target_size=IMG_SIZE, 117 batch_size=BATCH_SIZE, 118 color_mode='rgb', 119 class_mode='binary') 120 121 test_dir = 'sex/faces/test' # 指向測試集圖片目錄路徑 122 123 test_generator = test_datagen.flow_from_directory( 124 test_dir, 125 target_size=IMG_SIZE, 126 batch_size=BATCH_SIZE, 127 color_mode='rgb', 128 class_mode='binary') 129 130 # 檢視經過處理的圖片以及它的binary標籤 131 fit, ax = plt.subplots(nrows=3, ncols=3, figsize=(10, 7)) 132 133 for i, a in enumerate(ax.flat): 134 img, label = test_generator.next() 135 a.imshow(img[0],) 136 a.set_title(label[0]) 137 138 plt.tight_layout() 139 plt.show() 140 141 # 構建神經網路 142 model = models.Sequential() 143 144 # 1.Conv2D層,32個過濾器。輸出圖片尺寸:150-3+1=148*148,引數數量:32*3*3*3+32=896 145 model.add(layers.Conv2D(32, (3, 3), 146 activation='relu', 147 input_shape=(150, 150, 3))) # 折積層1 148 model.add(layers.MaxPooling2D((2, 2))) # 最大值池化層1。輸出圖片尺寸:148/2=74*74 149 150 # 2.Conv2D層,64個過濾器。輸出圖片尺寸:74-3+1=72*72,引數數量:64*3*3*32+64=18496 151 model.add(layers.Conv2D(64, (3, 3), 152 activation='relu')) # 折積層2 153 model.add(layers.MaxPooling2D((2, 2))) # 最大值池化層2。輸出圖片尺寸:72/2=36*36 154 155 # 3.Conv2D層,128個過濾器。輸出圖片尺寸:36-3+1=34*34,引數數量:128*3*3*64+128=73856 156 model.add(layers.Conv2D(128, (3, 3), 157 activation='relu')) # 折積層3 158 model.add(layers.MaxPooling2D((2, 2))) # 最大值池化層3。輸出圖片尺寸:34/2=17*17 159 160 # 4.Conv2D層,128個過濾器。輸出圖片尺寸:17-3+1=15*15,引數數量:128*3*3*128+128=147584 161 model.add(layers.Conv2D(128, (3, 3), 162 activation='relu')) # 折積層4 163 model.add(layers.MaxPooling2D((2, 2))) # 最大值池化層4。輸出圖片尺寸:15/2=7*7 164 165 # 將輸入層的資料壓縮成1維資料,全連線層只能處理一維資料 166 model.add(layers.Flatten()) 167 168 # 全連線層 169 model.add(layers.Dense(512, 170 activation='relu')) # 全連線層1 171 model.add(layers.Dense(1, 172 activation='sigmoid')) # 全連線層2,作為輸出層。sigmoid分類,輸出是兩類別 173 174 # 編譯模型 175 # RMSprop 優化器。因為網路最後一層是單一sigmoid單元, 176 # 所以使用二元交叉熵作為損失函數 177 model.compile(loss='binary_crossentropy', 178 optimizer=optimizers.RMSprop(lr=1e-4), 179 metrics=['acc']) 180 181 # 看一下特徵圖的維度如何隨著每層變化 182 model.summary() 183 # 184 185 train_datagen = ImageDataGenerator(rescale=1./255, 186 rotation_range=40, # 將影象隨機旋轉40度 187 width_shift_range=0.2, # 在水平方向上平移比例為0.2 188 height_shift_range=0.2, # 在垂直方向上平移比例為0.2 189 shear_range=0.2, # 隨機錯切變換的角度為0.2 190 zoom_range=0.2, # 圖片隨機縮放的範圍為0.2 191 horizontal_flip=True, # 隨機將一半影象水平翻轉 192 fill_mode='nearest') # 填充建立畫素 193 validation_datagen = ImageDataGenerator(rescale=1./255) 194 195 train_generator = train_datagen.flow_from_directory( 196 train_dir, 197 target_size=IMG_SIZE, # 輸入訓練影象尺寸 198 batch_size=BATCH_SIZE, 199 class_mode='binary') 200 201 validation_generator = validation_datagen.flow_from_directory( 202 validation_dir, 203 target_size=IMG_SIZE, 204 batch_size=BATCH_SIZE, 205 class_mode='binary') 206 # 207 # 訓練模型50輪次 208 history_save = model.fit( 209 train_generator, 210 steps_per_epoch=100, 211 epochs=50, 212 validation_data=validation_generator, 213 validation_steps=50) 214 215 # 將訓練過程產生的資料儲存為h5檔案 216 model.save('sex/faces/sex_model.h5') 217 # 儲存資料增強後的訓練模型 218 model.save('sex/faces/sex_model_idg.h5') 219 220 # 繪製損失曲線和精度曲線圖 221 accuracy = history_save.history['acc'] # 訓練集精度 222 loss = history_save.history['loss'] # 訓練集損失 223 val_loss = history_save.history['val_loss'] # 驗證集精度 224 val_accuracy = history_save.history['val_acc'] # 驗證集損失 225 plt.figure(figsize=(17, 7)) 226 227 # 訓練集精度和驗證集精度曲線圖圖 228 plt.subplot(2, 2, 1) 229 plt.plot(range(50), accuracy, 'bo', label='Training Accuracy') 230 plt.plot(range(50), val_accuracy, label='Validation Accuracy') 231 plt.title('Training and Validation Accuracy') 232 plt.legend(loc='center right') 233 234 # 訓練集損失和驗證集損失圖 235 plt.subplot(2, 2, 2) 236 plt.plot(range(50), loss, 'bo', label='Training Loss') 237 plt.plot(range(50), val_loss, label='Validation Loss') 238 plt.title('Training and Validation Loss') 239 plt.legend(loc='center right') 240 241 # 訓練集精度和損失散點圖 242 plt.subplot(2, 2, 3) 243 plt.scatter(range(50), accuracy, label="Training Accuracy", color='b', s=25, marker="o") 244 plt.scatter(range(50), loss, label="Training Loss", color='r', s=25, marker="o") 245 plt.title('Training : Accuracy and Loss') 246 plt.legend(loc='center right') 247 248 # 驗證集精度和損失散點圖 249 plt.subplot(2, 2, 4) 250 plt.scatter(range(50), val_accuracy, label="Validation Accuracy", color='b', s=25, marker="o") 251 plt.scatter(range(50), val_loss, label="Validation Loss", color='r', s=25, marker="o") 252 plt.title('Validation : Accuracy and Loss') 253 plt.legend(loc='center right') 254 255 plt.show() 256 257 # 將圖片縮小到(150,150)的大小 258 def convertjpg(jpgfile, outdir, width=150, height=150): 259 img = Image.open(jpgfile) 260 try: 261 new_img = img.resize((width, height), Image.BILINEAR) 262 new_img.save(os.path.join(outdir, os.path.basename(jpgfile))) 263 except Exception as e: 264 print(e) 265 266 # 從測試集隨機獲取一張男性圖片 267 man_test = r'sex\faces\test\man' 268 man_test_list = os.listdir(man_test) 269 key = random.randint(0, len(man_test_list)) 270 img_key = man_test_list[key] 271 jpg_file = os.path.join(man_test, img_key) 272 convertjpg(jpg_file, "sex/faces/test") # 影象大小改變到(150,150) 273 img_scale = plt.imread('sex/faces/test/' + img_key) 274 plt.imshow(img_scale) # 顯示改變影象大小後的圖片確實變到了(150,150)大小 275 276 # 呼叫訓練模型結果進行預測 277 model = load_model('sex/faces/sex_model.h5') 278 img_scale = img_scale.reshape(1, 150, 150, 3).astype('float32') 279 img_scale = img_scale/255 # 歸一化到0-1之間 280 result = model.predict(img_scale) # 取圖片資訊 281 if result > 0.5: 282 print('該圖片是女性的概率為:', result) 283 else: 284 print('該圖片是男性的概率為:', 1-result) 285 plt.show() # 列印尺寸改變後的影象 286 287 # 從測試集隨機獲取一張女性圖片 288 woman_test = r'sex\faces\test\woman' 289 woman_test_list = os.listdir(woman_test) 290 key = random.randint(0, len(woman_test_list)) 291 img_key = woman_test_list[key] 292 jpg_file = os.path.join(woman_test, img_key) 293 convertjpg(jpg_file, "sex/faces/test") # 影象大小改變到(150,150) 294 img_scale = plt.imread('sex/faces/test/' + img_key) 295 plt.imshow(img_scale) # 顯示改變影象大小後的圖片確實變到了(150,150)大小 296 297 # 呼叫訓練模型結果進行預測 298 model = load_model('sex/faces/sex_model.h5') 299 img_scale = img_scale.reshape(1, 150, 150, 3).astype('float32') 300 img_scale = img_scale/255 # 歸一化到0-1之間 301 result = model.predict(img_scale) # 取圖片資訊 302 if result > 0.5: 303 print('該圖片是女性的概率為:', result) 304 else: 305 print('該圖片是男性的概率為:', 1-result) 306 plt.show() # 列印尺寸改變後的影象 307 308 # 自定義一張男性圖片進行預測 309 diy_img = 'sex/faces/man.jpg' 310 convertjpg(diy_img, "sex") # 影象大小改變到(150,150) 311 img_scale = plt.imread('sex/man.jpg') 312 plt.imshow(img_scale) # 顯示改變影象大小後的圖片確實變到了(150,150)大小 313 314 # 呼叫資料增強後的訓練模型結果進行預測 315 model = load_model('sex/faces/sex_model_idg.h5') 316 img_scale = img_scale.reshape(1, 150, 150, 3).astype('float32') 317 img_scale = img_scale/255 # 歸一化到0-1之間 318 result = model.predict(img_scale) # 取圖片資訊 319 if result > 0.5: 320 print('該圖片是女性的概率為:', result) 321 else: 322 print('該圖片是男性的概率為:', 1-result) 323 plt.show() # 列印尺寸改變後的影象 324 325 # 自定義一張女性圖片進行預測 326 diy_img = 'sex/faces/woman_2.jpg' 327 convertjpg(diy_img, "sex") # 影象大小改變到(150,150) 328 img_scale = plt.imread('sex/woman_2.jpg') 329 plt.imshow(img_scale) # 顯示改變影象大小後的圖片確實變到了(150,150)大小 330 331 # 呼叫資料增強後的訓練模型結果進行預測 332 model = load_model('sex/faces/sex_model.h5') 333 img_scale = img_scale.reshape(1, 150, 150, 3).astype('float32') 334 img_scale = img_scale/255 # 歸一化到0-1之間 335 result = model.predict(img_scale) # 取圖片資訊 336 if result > 0.5: 337 print('該圖片是女性的概率為:', result) 338 else: 339 print('該圖片是男性的概率為:', 1-result) 340 plt.show() # 列印尺寸改變後的影象