作者 | 李秋鍵
責編 | 伍杏玲
出品 | AI科技大本營(ID:rgznai100)
在人工智能的發展越來越火熱的今天,其中最具有代表性的便是影像識別,其應用比比皆是,如車站的人臉識別系統,交通的智能監控車牌號系統等,卷積神經網路作為影像識別的首選演算法,其對于影像的特征提取具有很好的效果,Keras 框架作為卷積神經網路的典型框架,可創建神經網路層,更容易提取影像特征,從而達到區分動物的目的,在生產實踐中達到輔助的效果,
這里的建筑物主要是借助神經網路搭建幾種常見動物的識別系統,先設定了識別高樓、平房、橋梁和公路四種建筑物,程式分為四個部分:整體網路搭建程式,檔案夾整體預測、網路層繪制程式和單個預測可視化程式,分別為deep learning.py,predict.py、create_graph.py和predict-show.py,實作效果如下圖:
實驗前的準備
Python版本是3.6.5;使用的神經網路是CNN;所用到的搭建網路層的庫是Keras,
Keras是一個高層神經網路API,由純Python撰寫而成并基Tensorflow、Theano以及CNTK后端,Keras 為支持快速實驗而生,能夠把你的idea迅速轉換為結果,Keras的基本優點如下:
1、簡易和快速的原型設計(keras具有高度模塊化,極簡,和可擴充特性)
2、支持CNN和RNN,或二者的結合
3、無縫CPU和GPU切換
卷積神經網路,是一種前饋神經網路,人工神經元可以回應周圍單元,可以進行大型影像處理,卷積神經網路包括卷積層和池化層,
積神經網路CNN的結構一般包含這幾個層:
輸入層:用于資料的輸入
卷積層:使用卷積核進行特征提取和特征映射
激勵層:由于卷積也是一種線性運算,因此需要增加非線性映射
池化層:進行下采樣,對特征圖稀疏處理,減少資料運算量,
全連接層:通常在CNN的尾部進行重新擬合,減少特征資訊的損失
輸出層:用于輸出結果
當然中間還可以使用一些其他的功能層:
歸一化層(Batch Normalization):在CNN中對特征的歸一化
切分層:對某些(圖片)資料的進行磁區域的單獨學習
融合層:對獨立進行特征學習的分支進行融合
資料集準備
我們需要準備訓練的資料集檔案,我找的圖片都是來自于百度,將其保存在./data/train檔案夾下,建立四個檔案夾,分別保存公路、橋梁、高樓和平房的圖片,需要訓練的資料集的標簽就是檔案夾的名稱,train檔案夾資料集如下:
建立./data/test檔案夾,里面放入測驗的圖片,作為測驗集使用,如下圖可見:
網路層的搭建
(1)預處理:
為了提高模型的精準度,需要在圖片中進行旋轉角度,平移等圖形變化形成新的圖形拿來訓練從而提高精準度代碼如下:
train_datagen = ImageDataGenerator(
rotation_range = 40, # 隨機旋轉度數
width_shift_range = 0.2, # 隨機水平平移
height_shift_range = 0.2,# 隨機豎直平移
rescale = 1/255, # 資料歸一化
shear_range = 20, # 隨機錯切變換
zoom_range = 0.2, # 隨機放大
horizontal_flip = True, # 水平翻轉
fill_mode = 'nearest', # 填充方式
)
接著定義一些用到引數變數,其中包括統一圖片的尺寸、分類數量、訓練批次和模型大小等等:
IMG_W = 224 #定義裁剪的圖片寬度
IMG_H = 224 #定義裁剪的圖片高度
CLASS = 4 #圖片的分類數
EPOCHS = 200 #迭代周期
BATCH_SIZE = 64 #批次大小
TRAIN_PATH = 'data/train' #訓練集存放路徑
TEST_PATH = 'data/test' #測驗集存放路徑
SAVE_PATH = 'buildings_selector' #模型保存路徑
LEARNING_RATE = 1e-4 #學習率
DROPOUT_RATE = 0 #抗擬合,不作業的神經網路百分比
(2)網路層搭建:
創建多個卷積層以及池化層,每一層的輸入為上一層的輸出,其中池化層類似卷積層,主要目的在于降采樣,減少訓練的數值,可以防止過擬合,代碼如下:
#再次構建一個卷積層
model.add(Conv2D(filters=32,kernel_size=3,padding='same',activation='relu'))
#構建一個池化層,提取特征,池化層的池化視窗為2*2,步長為2,
model.add(MaxPool2D(pool_size=2,strides=2))
#繼續構建卷積層和池化層,區別是卷積核數量為64,
model.add(Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2,strides=2))
#繼續構建卷積層和池化層,區別是卷積核數量為128,
model.add(Conv2D(filters=128,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=128,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2, strides=2))
model.add(Flatten()) #資料扁平化
model.add(Dense(128,activation='relu')) #構建一個具有128個神經元的全連接層
model.add(Dense(64,activation='relu')) #構建一個具有64個神經元的全連接層
model.add(Dropout(DROPOUT_RATE)) #加入dropout,防止過擬合,
model.add(Dense(CLASS,activation='softmax')) #輸出層,一共4個神經元,對應4個分類
(3)模型訓練:
創建優化器和模型,代碼如下:
train_generator = train_datagen.flow_from_directory( #設定訓練集迭代器
TRAIN_PATH, #訓練集存放路徑
target_size=(IMG_W,IMG_H), #訓練集圖片尺寸
batch_size=BATCH_SIZE #訓練集批次
)
test_generator = test_datagen.flow_from_directory( #設定測驗集迭代器
TEST_PATH, #測驗集存放路徑
target_size=(IMG_W,IMG_H), #測驗集圖片尺寸
batch_size=BATCH_SIZE, #測驗集批次
)
print(train_generator.class_indices) #列印迭代器分類,各分類代號為{'du': 0, 'gui': 1,'kang': 2, 'tao': 3}
try:
model =load_model('{}.h5'.format(SAVE_PATH)) #嘗試讀取訓練好的模型,再次訓練
print('model upload,starttraining!')
except:
print('not find model,starttraining') #如果沒有訓練過的模型,則從頭開始訓練
model.fit_generator( #模型擬合
train_generator, #訓練集迭代器
steps_per_epoch=len(train_generator), #每個周期需要迭代多少步(圖片總量/批次大小=11200/64=175)
epochs=EPOCHS, #迭代周期
validation_data=test_generator,#測驗集迭代器
validation_steps=len(test_generator) #測驗集迭代多少步
)
model.save('{}.h5'.format(SAVE_PATH)) #保存模型
print('finish {} epochs!'.format(EPOCHS))
最終訓練的結果200次模型的精準度89%,
資料預測
利用創建好的模型進行試驗,建立predict.py檔案用來預測圖片,將要試驗的圖片放在./predict檔案夾下,首先需要匯入庫的代碼為:
from keras.models import load_model
from keras.preprocessing.image import img_to_array,load_img
import numpy as np
import os
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
接著載入模型,由訓練部分的代碼可知模型檔案為building_selector.h5
model = load_model('building_selector.h5')
分類分別為高樓、公路、平房、橋梁,建立一個陣列用來保存
label = np.array(['高樓','公路','平房','橋梁'])
定義函式,用來把圖片轉成可以識別的矩陣,由于激活函式值在0~1之間,故需要將其中矩陣值變在0~1之間,故需要除以255以達到目的
def image_change(image):
image = image.resize((224, 224))
image = img_to_array(image)
image = image / 255
image = np.expand_dims(image, 0)
return image
最終識別效果如下:
predict預測結果圖
建立predict-show.py程式,里面的整體結構和predict.py類似,加上圖片標注顯示即可,
image = load_img("2.jpg")
image = image_change(image)
img=cv2.imread("2.jpg")
img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
myfont = ImageFont.truetype(r'C:/Windows/Fonts/simfang.ttf', 40)
draw = ImageDraw.Draw(img_PIL)
draw.text((300, 10), label[model.predict_classes(image)][0], font=myfont,fill=(200, 100, 0))
img_OpenCV = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR)
cv2.imshow('frame', img_OpenCV)
cv2.waitKey(0)
最終效果如下:
原始碼地址:https://pan.baidu.com/s/1e5SnM_rL2sxcO_ceC4l99g
提取碼:1q5k
作者簡介:
李秋鍵,CSDN博客專家,CSDN達人課作者,碩士在讀于中國礦業大學,開發有taptap競賽獲獎等,
更多精彩推薦
?科學“干飯”,AI 營養師教你
?GitHub 標星超 26600,TiDB 社區運營的道與術!
?區區幾行Python代碼,一分鐘搞定一天作業量
?讀懂深度遷移學習,看這文就夠了
點分享點收藏點點贊點在看
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/254498.html
標籤:AI
