python +keras实现图像分类(入门级例子讲解)
一.項目描述
數(shù)據(jù)集來源于kaggle貓狗大戰(zhàn)數(shù)據(jù)集。訓(xùn)練集有25000張,貓狗各占一半。測試集12500張。希望計算機(jī)可以從這些訓(xùn)練集圖片中學(xué)習(xí)到貓狗的特征,從而使得計算機(jī)可以正確的對未曾見過的貓狗圖片進(jìn)行分類。這就是圖像分類問題,計算機(jī)視覺研究領(lǐng)域之一,計算機(jī)通過學(xué)習(xí)圖像本身的特征將不同類別的圖像區(qū)分開來。
二.評價指標(biāo)
二分類評價指標(biāo)
binary_crossentropy:交叉熵
y? i是樣本標(biāo)簽,yi樣本輸出。只有yi和y? i是相等時,loss才為0,否則loss就是為一個正數(shù)。而且,概率相差越大,loss就越大。這個度量概率距離的方式稱為交叉熵。
二分類模型的最后一層的激活函數(shù) 是:sigmoid
二分類模型最后輸出的是0到1的數(shù)。
應(yīng)該使用numpy的四舍五入求取類別,并轉(zhuǎn)換為整數(shù)
pred_y=int(np.round(predict_y))
多分類評價指標(biāo)
categorical_crossentropy:分類交叉熵函數(shù)
y? i是樣本標(biāo)簽,yi樣本輸出
多分類模型的最后一層的激活函數(shù) 是:softmax
softmax先把輸出指數(shù)化,再歸一化,得到各類概率。
假設(shè)一個問題是3分類,一個訓(xùn)練樣本進(jìn)來得到的softmax是[0.5,0.2,0.3]
假設(shè)這個正確樣本類別為第一個類別。
則該樣本分類交叉熵為:
多分類模型輸出的是各個類別的概率,如2個樣本的預(yù)測輸出為:ypred=[[0.5,0.2,0.3],[0.4,0.1,0.5]]
應(yīng)該使用numpy求取最大值索引
pred=np.argmax(ypred,axis=1)
得到[0,2]
三.算例實現(xiàn)
數(shù)據(jù)集
電腦垃圾啦,無法將全部圖片都用上,跑不動。
于是貓和狗都選取原始數(shù)據(jù)集的一半左右。
貓的圖片如下:
狗的圖片如下:
各種各樣的貓和狗,不容易找到統(tǒng)一的圖片預(yù)處理方式,如處理成二值圖像(但貓狗顏色不一樣,二值處理有的把背景提取出來啦,畢竟二值處理需要把前景色處理成白色,為了達(dá)到此要求,有的圖片得做反二值化處理)
就對圖片不做任何處理吧,防止圖片失真。
1數(shù)據(jù)集讀取函數(shù)
注意:cv2.imread(name) 圖片路徑不能含有中文。
#個人喜好用OpenCV
需要對圖片統(tǒng)一大小: cv2.resize(img, (100, 100))
import os import numpy as np import cv2def ReFileName(dirPath):""":param dirPath: 文件夾路徑:return:"""# 對目錄下的文件進(jìn)行遍歷x=[]for file in os.listdir(dirPath):# 判斷是否是文件if os.path.isfile(os.path.join(dirPath, file)) == True:c= os.path.basename(file)name = dirPath + '\\' + cimg = cv2.imread(name)img = cv2.resize(img, (100, 100)) # 使尺寸大小一樣x.append(img)return x2數(shù)據(jù)集讀取并處理
分別讀取貓狗數(shù)據(jù)集,之前我將貓和狗放在兩個文件夾啦。
對數(shù)據(jù)除以255,cnn模型對數(shù)值小的數(shù)處理得比較好。
轉(zhuǎn)換數(shù)據(jù)格式,圖像格式為np.uint8, 轉(zhuǎn)換成float型,計算機(jī)可以計算。
標(biāo)簽處理,貓?zhí)幚沓?,狗處理成0
3.數(shù)據(jù)打亂
首先拼接數(shù)據(jù)集,然后打亂數(shù)據(jù)集特征和標(biāo)簽。
如果是多分類問題得在打亂數(shù)據(jù)前對y進(jìn)行one-hot化,如:
y=keras.utils.to_categorical(y,4)#四分類
4.定義模型
電腦不行,就用個普通模型跑吧。
如果是多分類問題
最后兩行為
本文模型
from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D import keras import timedef define_model():model = Sequential()model.add(Conv2D(filters=16,kernel_size=(5, 5),padding='same',input_shape=(100, 100, 3),activation='relu')) # 卷積層1model.add(MaxPooling2D(pool_size=(2, 2))) # 池化層2model.add(Dropout(0.25))model.add(Flatten()) # 平坦層model.add(Dense(10,activation='relu')) # 隱藏層model.add(Dense(1, activation='sigmoid')) # 輸出層model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])model.summary()return model5.模型訓(xùn)練并保持
準(zhǔn)確率0.7072,之前使用的是貓狗各3000多張,準(zhǔn)確率為0.5。
現(xiàn)在使用的是各6000多張,準(zhǔn)確率0.7。
原始數(shù)據(jù)集有各12000多張,原諒我,使用全部數(shù)據(jù)集電腦太卡,沒服務(wù)器,學(xué)生黨。
四.pyqt可視化結(jié)果
建立個簡單版的qt貓狗預(yù)測系統(tǒng)吧。
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # @Author: yudengwu # @Date : 2020/7/18 import sys from PyQt5 import QtWidgets, QtCore, QtGui from PyQt5.QtGui import * from PyQt5.QtWidgets import * from PyQt5.QtCore import *import cv2 import keras from keras .models import load_model import numpy as np import re class picture(QWidget):def __init__(self):super(picture, self).__init__()self.resize(600, 400)self.setWindowTitle("貓狗分類")self.btn = QPushButton()self.btn.setText("打開圖片")self.btn.clicked.connect(self.openimage)self.label = QLabel()self.label.setText('圖片路徑')self.labelimage = QLabel()self.labelimage.setText("顯示圖片")#self.labelimage.setFixedSize(500, 400)#設(shè)置尺寸self.labelimage.setStyleSheet("QLabel{background:white;}""QLabel{color:rgb(300,300,300,120);font-size:10px;font-weight:bold;font-family:宋體;}")#預(yù)測按鈕self.btnclass=QPushButton()self.btnclass.setText('點擊預(yù)測分類')self.btnclass.clicked.connect(self.fenlei)self.labelclass=QLabel()self.labelclass.setText('預(yù)測類別')self.labelclass.setStyleSheet("font:16pt '楷體';border-width:2px;border-style: inset;border-color:gray")layout1=QVBoxLayout()layout1.addWidget(self.btn)layout1.addWidget(self.label)layout1.addWidget(self.labelimage)layout2 = QVBoxLayout()layout2.addWidget(self.btnclass)layout2.addWidget(self.labelclass)layout=QVBoxLayout()layout.addLayout(layout1)layout.addLayout(layout2)self.setLayout(layout)def openimage(self):imgName, imgType = QFileDialog.getOpenFileName(self, "打開圖片", "", "*.jpg;;*.png;;All Files(*)")#jpg = QtGui.QPixmap(imgName).scaled(self.labelimage.width(), self.label.height())#適應(yīng)labelimage尺寸,前提是label設(shè)置了尺寸jpg = QtGui.QPixmap(imgName)self.labelimage.setPixmap(jpg)self.label.setText(str(imgName))def fenlei(self):biaoqian = {'1': '貓', '0': '狗'}path=self.label.text()newName = re.sub('(D:/機(jī)器學(xué)習(xí)/學(xué)習(xí)草稿/)','', path)print(newName)img = cv2.imread(str(newName))img = cv2.resize(img, (100, 100)) # 使尺寸大小一樣img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img = np.array(img) / 255img = img.astype(np.float64)img = img.reshape(-1, 100, 100, 1)model = load_model('貓狗分類.h5')predict_y = model.predict(img)pred_y = int(np.round(predict_y))print(pred_y)self.labelclass.setText(biaoqian[str(pred_y)])if __name__ == "__main__":app = QtWidgets.QApplication(sys.argv)my = picture()my.show()sys.exit(app.exec_())說明:
newName = re.sub(’(D:/機(jī)器學(xué)習(xí)/學(xué)習(xí)草稿/)’,’’, path)
這是因為我圖片放在了當(dāng)前項目文件夾里,導(dǎo)致圖片絕對路徑含有中文,cv.imread()會出錯,我去除掉中文部分,使模型讀取相對路徑
如果你要讀取任意文件夾里的圖片,要使圖片絕對路徑無中文。
可以固定圖片顯示尺寸;
#self.labelimage.setFixedSize(500, 400)#設(shè)置尺寸
#jpg = QtGui.QPixmap(imgName).scaled(self.labelimage.width(), self.label.height())#適應(yīng)labelimage尺寸,前提是label設(shè)置了尺寸
結(jié)果
預(yù)測界面:
識別cat
識別dog
這個結(jié)果還不能讓我滿意,等我多學(xué)習(xí)下知識再來吧。
當(dāng)然也可以調(diào)用攝像頭,實現(xiàn)對攝像頭下的貓狗進(jìn)行實時識別。
可以參考博文然后自己修改程序。就是一個定時器作用,每隔多少時間識別下攝像頭下的物體。
opencv進(jìn)階學(xué)習(xí)筆記1: 調(diào)用攝像頭用法大全(打開攝像頭,打開攝像頭并實時不斷截屏,讀取視頻并截圖)
送上其他資源:
計算機(jī)視覺:圖像特征與描述大全 (一篇博文帶你簡單了解完圖像特征提取技術(shù))
電氣專業(yè)的計算機(jī)萌新,寫博文不容易。如果你覺得本文對你有用,請點個贊再走,謝謝。
總結(jié)
以上是生活随笔為你收集整理的python +keras实现图像分类(入门级例子讲解)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pyqt5讲解2:QPushButton
- 下一篇: 银行卡丢失怎么补办 挂失银行卡是第一步