1 簡單的深度學習過程常規流程:
PS: 標*的 構建神經網絡是最重要的。
2 本demo功能:基於TensorFlow Keras來建立模型、訓練(喂給它已經分類好的人臉表情圖片)和預測 人臉表情圖片。
上代碼:
1 import os 2 import sys 3 from PIL import Image # 使用第三方包Pillow來進行圖像處理 4 import numpy as np 5 import tensorflow.contrib.keras as k 6 import scipy.spatial.distance as distance # 使用第三方包scipy來進行向量余弦相似度判斷 7 import pandas as pd 8 9 10 # 這是一個自定義函數,用於把圖片按比例縮放到最大寬度為maxWidth、最大高度為maxHeight 11 def resizeImage(inputImage, maxWidth, maxHeight): 12 originalWidth, originalHeight = inputImage.size 13 14 f1 = 1.0 * maxWidth / originalWidth 15 f2 = 1.0 * maxHeight / originalHeight 16 factor = min([f1, f2]) 17 18 width = int(originalWidth * factor) 19 height = int(originalHeight * factor) 20 return inputImage.resize((width, height), Image.ANTIALIAS) 21 22 23 ifRestartT = False 24 roundCount = 20 25 learnRate = 0.01 26 trainDir = "./imagedata/" # 用於指定訓練數據所在目錄 27 trainResultPath = "./imageClassifySave/" # 用於指定訓練過程保存目錄 28 optimizerT = "RMSProp" # 用於指定優化器 29 lossT = "categorical_crossentropy" # 用於指定誤差函數 30 #predictFile = None # 用於指定需預測的新圖像文件,如果為None則表示不預測 31 predictFile = "./predictFile/xx.jpg" 32 33 # 讀取meta.txt文件內容:分類 34 #metaData = pd.read_csv(trainDir + "meta.txt", header=None).as_matrix() 35 metaData = pd.read_csv(trainDir + "meta.txt", header=None).iloc[:,:].values 36 37 # maxTypes表示種類個數 38 maxTypes = len(metaData) 39 print("maxTypes: %d" % maxTypes) 40 41 argt = sys.argv[1:] 42 print("argt: %s" % argt) 43 44 for v in argt: 45 if v == "-restart": 46 print("我打印了嗎?") 47 ifRestartT = True 48 if v.startswith("-round="): 49 roundCount = int(v[len("-round="):]) 50 if v.startswith("-learnrate="): 51 learnRate = float(v[len("-learnrate="):]) 52 if v.startswith("-dir="): # 用於指定訓練數據所在目錄(不使用默認目錄時才需要設置) 53 trainDir = v[len("-dir="):] 54 if v.startswith("-optimizer="): 55 optimizerT = v[len("-optimizer="):] 56 if v.startswith("-loss="): 57 lossT = v[len("-loss="):] 58 if v.startswith("-predict="): 59 predictFile = v[len("-predict="):] 60 61 print("predict file: %s" % predictFile) 62 63 xData = [] 64 yTrainData = [] 65 fnData = [] 66 predictAry = [] 67 68 listt = os.listdir(trainDir) # 獲取變量trainDir指定的目錄下所有的文件 69 70 lent = len(listt) 71 72 # 循環處理訓練目錄下的圖片文件,統一將分辨率轉換為256*256, 73 # 再把圖片處理成3通道(RGB)的數據放入xData,然后從文件名中提取目標值放入yTrainData 74 # 文件名放入fnData 75 for i in range(lent): 76 v = listt[i] 77 if v.endswith(".jpg"): # 只處理.jpg為擴展名的文件 78 print("processing %s ..." % v) 79 img = Image.open(trainDir + v) 80 w, h = img.size 81 82 img1 = resizeImage(img, 256, 256) 83 84 img2 = Image.new("RGB", (256, 256), color="white") 85 86 w1, h1 = img1.size 87 88 img2 = Image.new("RGB", (256, 256), color="white") 89 90 img2.paste(img1, box=(int((256 - w1) / 2), int((256 - h1) / 2))) 91 92 xData.append(np.matrix(list(img2.getdata()))) 93 94 tmpv = np.full([maxTypes], fill_value=0) 95 tmpv[int(v.split(sep="_")[0]) - 1] = 1 96 yTrainData.append(tmpv) 97 98 fnData.append(trainDir + v) 99 100 rowCount = len(xData) 101 print("rowCount: %d" % rowCount) 102 103 # 轉換xData、yTrainData、fnData為合適的形態 104 xData = np.array(xData) 105 xData = np.reshape(xData, (-1, 256, 256, 3)) 106 107 yTrainData = np.array(yTrainData) 108 109 fnData = np.array(fnData) 110 111 # 使用Keras來建立模型、訓練和預測 112 if (ifRestartT is False) and os.path.exists(trainResultPath + ".h5"): 113 # 載入保存的模型和可變參數 114 print("模型已經存在!!!!!!!!...") 115 print("Loading...") 116 model = k.models.load_model(trainResultPath + ".h5") 117 model.load_weights(trainResultPath + "wb.h5") 118 else: 119 # 新建模型 120 model = k.models.Sequential() 121 122 # 使用4個卷積核、每個卷積核大小為3*3的卷積層 123 model.add(k.layers.Conv2D(filters=4, kernel_size=(3, 3), input_shape=(256, 256, 3), data_format="channels_last", activation="relu")) 124 125 model.add(k.layers.Conv2D(filters=3, kernel_size=(3, 3), data_format="channels_last", activation="relu")) 126 127 # 使用2個卷積核、每個卷積核大小為2*2的卷積層 128 model.add(k.layers.Conv2D(filters=2, kernel_size=(2, 2), data_format="channels_last", activation="selu")) 129 130 model.add(k.layers.Flatten()) 131 # 此處的256沒有改 132 model.add(k.layers.Dense(256, activation='tanh')) 133 134 model.add(k.layers.Dense(64, activation='sigmoid')) 135 136 # 按分類數進行softmax分類 137 model.add(k.layers.Dense(maxTypes, activation='softmax')) 138 139 model.compile(loss=lossT, optimizer=optimizerT, metrics=['accuracy']) 140 141 142 if predictFile is not None: 143 # 先對已有訓練數據執行一遍預測,以便后面做圖片相似度比對 144 print("preparing ...") 145 predictAry = model.predict(xData) 146 147 print("processing %s ..." % predictFile) 148 img = Image.open(predictFile) 149 150 # 下面是對新輸入圖片進行預測 151 img1 = resizeImage(img, 256, 256) 152 153 w1, h1 = img1.size 154 155 img2 = Image.new("RGB", (256, 256), color="white") 156 157 img2.paste(img1, box=(int((256 - w1) / 2), int((256 - h1) / 2))) 158 159 xi = np.matrix(list(img2.getdata())) 160 xi1 = np.array(xi) 161 xin = np.reshape(xi1, (-1, 256, 256, 3)) 162 163 resultAry = model.predict(xin) 164 print("x: %s, y: %s" % (xin, resultAry)) 165 166 # 找出預測結果中最大可能的概率及其對應的編號 167 maxIdx = -1 168 maxPercent = 0 169 170 for i in range(maxTypes): 171 if resultAry[0][i] > maxPercent: 172 maxPercent = resultAry[0][i] 173 maxIdx = i 174 175 # 將新圖片的預測結果與訓練圖片的預測結果逐一比對,找出相似度最高的 176 minDistance = 200 177 minIdx = -1 178 minFile = "" 179 180 for i in range(rowCount): 181 dist = distance.cosine(resultAry[0], predictAry[i]) # 用余弦相似度來判斷兩張圖片預測結果的相近程度 182 if dist < minDistance: 183 minDistance = dist 184 minIdx = i 185 minFile = fnData[i] 186 187 print("推測表情:%s,推斷正確概率:%10.6f%%,最相似文件:%s,相似度:%10.6f%%" % (metaData[maxIdx][1], maxPercent * 100, minFile.split("\\")[-1], (1 - minDistance) * 100)) 188 189 sys.exit(0) 190 191 model.fit(xData, yTrainData, epochs=roundCount, batch_size=lent, verbose=2) 192 193 print("saving...") 194 model.save(trainResultPath + ".h5") 195 model.save_weights(trainResultPath + "wb.h5")
3 用於訓練的圖片:
PS: 這些圖是在網上隨便找噠。這里需要注意圖片的命名規則:eg: 01_06.jpg 01代表圖片的類型,和meta.txt中的類型對應,06代表01類型下的第幾張
meat.txt文件:
1 1,微笑 2 2,大笑 3 3,哭 4 4,憤怒 5 5,平靜
4 預測:
用於預測的圖片:小公舉~~~
預測結果:
PS: 后續有需要會繼續更新。。。