前言
今日給大家帶來的是圖像識別技術——小狗分類器
工具使用
開發環境:win10、python3.6
開發工具:pycharm
工具包 :keras,numpy, PIL
效果展示
訓練集的准確率為0.925,但測試集只有0.7
說明過擬合了,可以再增加一些圖片,或者使用數據增強,來減少過擬合。
測試了兩張圖片,全都識別對了!
思路分析
- 1 准備數據集
- 2 數據集的預處理
- 3 搭建卷積神經網絡
- 4 訓練
- 5 預測
1、准備數據集
我們可以通過爬蟲技術,把4類圖像(京巴、拉布拉多、柯基、泰迪)保存到本地。總共有840張圖片做訓練集,188張圖片做測試集。
2 數據集的預處理
1 統一尺寸為1001003(RGB彩色圖像)
# 統一尺寸的核心代碼
img = Image.open(img_path)
new_img = img.resize((100, 100), Image.BILINEAR)
new_img.save(os.path.join('./dog_kinds_after/' + dog_name, jpgfile))
2 由於數據是自己下載的,需要制作標簽(label),可提取圖像名稱的第一個數字作為類別。(重命名圖片)
kind = 0
# 遍歷京巴的文件夾
images = os.listdir(images_path)
for name in images:
image_path = images_path + '/'
os.rename(image_path + name, image_path + str(kind) +'_' + name.split('.')[0]+'.jpg')
3 划分數據集
840張圖片做訓練集,188張圖片做測試集。
4 把圖片轉換為網絡需要的類型
# 只放了訓練集的代碼,測試集一樣操作。
ima_train = os.listdir('./train')
# 圖片其實就是一個矩陣(每一個像素都是0-255之間的數)(100*100*3)
# 1.把圖片轉換為矩陣
def read_train_image(filename):
img = Image.open('./train/' + filename).convert('RGB')
return np.array(img)
x_train = []
# 2.把所有的圖片矩陣放在一個列表里 (840, 100, 100, 3)
for i in ima_train:
x_train.append(read_train_image(i))
x_train = np.array(x_train)
# 3.提取kind類別作為標簽
y_train = []
for filename in ima_train:
y_train.append(int(filename.split('_')[0]))
# 標簽(0/1/2/3)(840,)
y_train = np.array(y_train)
# 我是因為重命名圖片為(1/2/3/4),所以都減了1
# 為了能夠轉化為獨熱矩陣
y_train = y_train - 1
# 4.把標簽轉換為獨熱矩陣
# 將類別信息轉換為獨熱碼的形式(獨熱碼有利於神經網絡的訓練)
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
print(y_test)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print(x_train.shape) # (840, 100, 100, 3)
print(y_train.shape) # (840,)
3 搭建卷積神經網絡
Keras是基於TensorFlow的深度學習庫,是由純Python編寫而成的高層神經網絡API,也僅支持Python開發。
它是為了支持快速實踐而對Tensorflow的再次封裝,讓我們可以不用關注過多的底層細節,能夠把想法快速轉換為結果。
# 1.搭建模型(類似於VGG,直接拿來用就行)
model = Sequential()
# 這里搭建的卷積層共有32個卷積核,卷積核大小為3*3,采用relu的激活方式。
# input_shape,字面意思就是輸入數據的維度。
#這里使用序貫模型,比較容易理解
#序貫模型就像搭積木一樣,將神經網絡一層一層往上搭上去
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
#dropout層可以防止過擬合,每次有25%的數據將被拋棄
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4, activation='softmax'))
4 訓練
訓練的過程,就是最優解的過程。
對上圖來說,就是根據數據集,不斷的迭代,找到一條最近似的直線(y = kx + b),把參數k,b保存下來,預測的時候直接加載。
# 編譯模型
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
# 一共進行32輪
# 也就是說840張圖片,每次訓練10張,相當於一共訓練84次
model.fit(x_train, y_train, batch_size=10, epochs=32)
# 保存權重文件(也就是相當於“房價問題的k和b兩個參數”)
model.save_weights('./dog_weights.h5', overwrite=True)
# 評估模型
score = model.evaluate(x_test, y_test, batch_size=10)
print(score)
5 預測
此時k、b(參數)和x(小狗的圖像)都是已知的了,求k(類別)就完了。
# 1.上傳圖片
name = input('上傳圖片的名稱(例如:XX.jpg)為:')
# 2.預處理圖片(代碼省略)
# 3.加載權重文件
model.load_weights('dog_weights.h5')
# 4.預測類別
classes = model.predict_classes(x_test)[0]
target = ['京巴', '拉布拉多', '柯基', '泰迪']
# 3-泰迪 2-柯基 1-拉布拉多 0-京巴
# 5.打印結果
print("識別結果為:" + target[classes])
文章到這里就結束了,感謝你的觀看,Python數據分析系列,下個系列分享Python小技巧
為了感謝讀者們,我想把我最近收藏的一些編程干貨分享給大家,回饋每一個讀者,希望能幫到你們。
干貨主要有:
① 2000多本Python電子書(主流和經典的書籍應該都有了)
② Python標准庫資料(最全中文版)
③ 項目源碼(四五十個有趣且經典的練手項目及源碼)
④ Python基礎入門、爬蟲、web開發、大數據分析方面的視頻(適合小白學習)
⑤ Python學習路線圖(告別不入流的學習)
⑥ 兩天的Python爬蟲訓練營直播權限
All done~詳見個人簡介或者私信獲取完整源代碼。。