天天看點

keras-圖像分類(内有詳細代碼注釋)

目錄

    • 資料集
    • 環境
    • 1.圖檔預處理
      • 統一圖檔類型
      • 統一圖檔大小标簽
    • 2.模型訓練
    • 3.預測

資料集

資料集:Animals10

十種動物:狗,貓,馬,大象,蝴蝶,雞,牛,羊,蜘蛛,松鼠

train:val:test=3:1:1

環境

Anaconda4.2.0(python3.5.2)

Keras 2.1.3

Tensorflow-gpu 1.4.0

Pillow 5

H5py 2.7.0(h5py快速入門指南https://www.jianshu.com/p/a6328c4f4986)

Numpy 1.16.3

Pycharm

1.圖檔預處理

寫完之後先執行讓它操作一波

統一圖檔類型

import os

def ranamesJPG(filepath, kind):
    images = os.listdir(filepath)
    for name in images:
        os.rename(filepath+name, filepath+kind+'_'+name.split('.')[0]+'.jpg')
        print(name)
        print(name.split('.')[0])
ranamesJPG('./224/貓/','7')
           

統一圖檔大小标簽

import os
from PIL import Image

def convertjpg(jpgfile,outdir,width=112,height=112):
    img = Image.open('./test/'+jpgfile)
    try:
        new_img = img.resize((width, height), Image.BILINEAR)
        new_img.save(os.path.join(outdir, os.path.basename(jpgfile)))
        #print(type(new_img))
        #new_img的類型'PIL.Image.Image'
    except Exception as e:
        print(e)
for jpgfile in os.listdir('./test/'):#jpgfile讀取檔案夾中圖檔的名字,類型是str
    convertjpg(jpgfile, "./test1/")
           

2.模型訓練

import os
from PIL import Image
import numpy as np
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.optimizers import SGD, RMSprop, Adam
from keras.layers import Conv2D, MaxPooling2D
 
#-----------------------将訓練集圖檔轉換成數組----------------------
ima1 = os.listdir('./train')#将train檔案夾中的檔案讀取出來
def read_image1(filename):#def xxx( ): 是定義函數
    img = Image.open('./train/'+filename).convert('RGB')
    #圖檔賦給img這個對象
return np.array(img)#圖檔轉化為np類型數組
 
x_train = []
 
for i in ima1:#循環所有train下面的圖檔
	x_train.append(read_image1(i))#将上面轉換成np類型的數組放在x_train中
x_train = np.array(x_train)#将x_train轉換成np類型的數組
#----------------------根據訓練集檔案名提取标簽----------------------
y_train = []
for filename in ima1:
y_train.append(int(filename.split('_')[0]))
#讀取下劃線之前的數字,再将它轉換成int類型的,加入到y_train中
#filename.split('_')[0]得到第一個_之前的内容
#filename.split('_')[1]得到第一個_和第二個o之間的内容
y_train = np.array(y_train)#y_train轉化轉化成np類型的數組
#-----------------------将測試集圖檔轉化成數組-----------------------
ima2 = os.listdir('./test')
def read_image2(filename):
    img = Image.open('./test/'+filename).convert('RGB')
    return np.array(img)
 
x_test = []
 
for i in ima2:
    x_test.append(read_image2(i))
 
x_test = np.array(x_test)

#-----------------------根據測試集檔案名提取标簽--------------------
y_test = []
for filename in ima2:
    y_test.append(int(filename.split('_')[0]))
 
y_test = np.array(y_test)
#--------------------------将标簽轉換格式----------------------------
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
 
#-------------------将特征點從0~255轉換成0~1提高特征提取精度---------------
'''
https://blog.csdn.net/m0_37678226/article/details/89635703
最常見的對圖像預處理方法有以下幾種:
(1)去均值
(2)歸一化處理
(3)正常白化處理又叫圖像标準化處理
(4)PCA
 '''
# 歸一化處理
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
 
#----------------------------搭建卷積神經網絡----------------------------
model = Sequential()
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))
 
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4, activation='softmax'))# 你一共分多少類,這裡貓四類
 
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) #随機梯度下降
#sgd = SGD(lr=learning_rate, decay=learning_rate/nb_epoch, momentum=0.9, nesterov=True)
#lr:大于0的浮點數,學習率;momentum:大于0的浮點數,動量參數;decay:大于0的浮點數,每次更新後的學習率衰減值;nesterov:布爾值,确定是否使用Nesterov動量
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])#編譯
#絕對叉熵限制
'''
可以使用 compile(self, optimizer, loss, metrics=None, sample_weight_mode=None, weighted_metrics=None, target_tensors=None) 來完成配置
compile() 主要接收前三個參數:
loss:字元串類型,用來指定損失函數,如:categorical_crossentropy,binary_crossentropy
optimizer:字元串類型,用來指定優化方式,如:rmsprop,adam,sgd
metrics:清單類型,用來指定衡量模型的名額,如:accuracy
'''
hist = model.fit(x_train, y_train, batch_size = 32, epochs = 200,verbose = 1,validation_data = (x_test, y_test))
#開始訓練,傳回train的loss和acc
#一次處理多少張圖檔,計算機性能好的話可以調高
#一共訓練多少次
#傳回test的loss acc
#fit()用于使用給定輸入訓練模型.(傳回訓練集loss、acc)
#predict()用于實際預測.它為輸入樣本生成輸出預測.
#evaluate()用于評估已經訓練過的模型.傳回損失值&模型的路徑成本.
 
model.save_weights('./cat/cat_weights.h5', overwrite=True)
#找到的拟合的很好的參數儲存成.h5
score = model.evaluate(x_test, y_test, batch_size = 32,verbose=0)
#測試集輸入到卷積神經網絡中
#verbose = 0 為不在标準輸出流輸出日志資訊,verbose = 1 為輸出進度條記錄,verbose = 2 為每個epoch輸出一行記錄
 
model.evaluate
輸入資料和标簽,輸出損失和精确度.
	# 評估模型,不輸出預測結果
	loss,accuracy = model.evaluate(X_test,Y_test)
	print('test loss',loss)
	print('accuracy',accuracy)
 
print(score)
#後兩句為了列印這個
#---------------------------------畫圖--------------------------------
plt.figure()# 建立一個繪圖視窗
acc = hist.history['acc']
val_acc = hist.history['val_acc']
loss = hist.history['loss']
val_loss = hist.history['val_loss']
epochs = range(len(acc))
plt.plot(epochs, acc, 'y-', label='Training acc')  
#'b-'為畫藍色線 ‘r-’紅色‘y-’黃色 ‘g-’綠色
plt.plot(epochs, val_acc, 'r-', label='Validation acc')
plt.plot(epochs, loss, 'b-', label='Training loss')
plt.plot(epochs, val_loss, 'g-', label='Validation loss')
plt.title('acc & loss')#标題
plt.legend()  # 繪制圖例,預設在右上角
plt.show()
           

3.預測

import os
from PIL import Image
import numpy as np
import copy
import random

from keras.optimizers import SGD
from keras.applications.vgg16 import VGG16
from keras.backend import clear_session

'''
單個圖檔預測
def prepicture(picname):
    img = Image.open('./pic/' + picname)
    new_img = img.resize((224, 224), Image.BILINEAR)
    new_img.save(os.path.join('./pic/', os.path.basename(picname)))

def read_image2(filename):
    img = Image.open('./pic/'+filename).convert('RGB')
    return np.array(img)

prepicture('0_OIP-sjeHzofdssb2vtWhVM8PGQHaFj.jpg')
x_test = []

x_test.append(read_image2('0_OIP-sjeHzofdssb2vtWhVM8PGQHaFj.jpg'))

x_test = np.array(x_test)

x_test = x_test.astype('float32')
x_test /= 255

clear_session() #清理session反複識别注意

predict = model.predict(x_test)
predict=np.argmax(predict,axis=1)
print(predict)
'''
random.seed(0)
clear_session() #清理session反複識别注意
model = VGG16(include_top = True,classes = 4,weights = None)
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
model.load_weights ("animals_weights_qy12_pca.h5")
daxiang=0
songshu=0
niu=0
gou=0
#多個圖檔預測
imgs = os.listdir('./pic/')
for jpg in imgs:
    img = Image.open('./pic/'+jpg)
    img = img.resize((224,224))
    img = np.array(img)
    img = img/255
    img = img.reshape(-1,224,224,3)

    pr = model.predict(img)[0]
    pr = np.argmax(pr, axis=-1)
    if pr==0:
        daixiang=daxiang+1
    elif pr==1:
        songshu = songshu + 1
    elif pr == 2:
        niu = niu+1
    else:
        gou=gou+1
        '''
    target = ['大象', '松鼠', '牛', '狗']
    print(target[pr])
    '''
print(daxiang,songshu,niu,gou)
           

繼續閱讀