CNN图像识别_算法篇
CNN圖像識別_算法篇
- 前言
- Keras
- 1外層循環(huán)
- 2中部循環(huán)
- 3內(nèi)部循環(huán)
- Matlab CNN ToolBox
- 總結(jié)
前言
CNN算法方面主要參考的的zh_JNU同學(xué)的工作和Deep-Learning-ToolBox-CNN-master的Matlab源碼,然后也做了些修改和解讀。
Keras
數(shù)據(jù)庫是5鐘分類的400張訓(xùn)練數(shù)據(jù)和100張測試數(shù)據(jù),數(shù)據(jù)庫網(wǎng)盤(提取碼:f5ze)可能跟環(huán)境版本有關(guān),我這邊的預(yù)處理不能使用cv的方法,所以統(tǒng)一使用cv2里的方法,值得強調(diào)的是,Keras版本亦有差異,我這邊的版本大致如圖
首先是預(yù)處理,利用opencv對圖片進(jìn)行縮放和灰化,將RGB3通道降維到單通道,python果然是“玩弄”字符串的語言
這里的預(yù)處理后的維度調(diào)整為126*126,主要考慮的是每層池化層的輸入都為偶數(shù),卷積核kernel size 為3,那么,輸入層126*126 --> 1卷積層124*124–>1池化層62*62–>2卷積層60*60–>2池化層30*30–>3卷積層28*28–>3池化層14*14,接下來就是全連接,預(yù)處理后
然后是測試,包括網(wǎng)絡(luò)的訓(xùn)練和測試,我這里除了版本兼容上的調(diào)整,也做了些改動,
首先是修改后的源碼,這里有一些術(shù)語,我將它們梳理一下
1外層循環(huán)
epoch:完整樣本訓(xùn)練的次數(shù);
batch:1個樣本空間中樣本的個數(shù);
有時1個完整的樣本空間可能包含大量的樣本,這時需要對樣本進(jìn)行分割,分成minibatch,那么完成 一次樣本訓(xùn)練就需要迭代iteration = batch/minibatch;minibatch的一種極限情形就是等于1,理論上不是不可以,但是容易過擬合。
2中部循環(huán)
filters:某一個卷積層中卷積核的個數(shù),之后再經(jīng)過池化層后,每一個filter都會對應(yīng)一個feature map(特征圖)
3內(nèi)部循環(huán)
kernel_size:卷積核的維數(shù),在滑動過程中也會有stride、padding等參數(shù)的選取
label:標(biāo)簽的維數(shù),其實我覺得標(biāo)簽的選取還是挺自由的,可以認(rèn)為每個分類就是一個實數(shù),也可以是種類維度的獨熱碼向量,如果是1*1的實數(shù)R,在BP過程可能會簡單點,因為均方誤差也是一個實數(shù),獨熱碼向量的形式,其實已經(jīng)被賦予了一定的意義,即每一位代表了樣本為該類的可能性(probability)
代碼是3層卷積+池化再進(jìn)行全連接,因為kernel_size是33,并且沒有對輸入樣本擴展,所以卷積層后的維數(shù)就是Nin-kernel_size+1,池化層是22,所以池化后寬高減半。
查看中間變量的方法,插入觀察層,首先要給每一層都取個名字,目前,它的這個打印結(jié)果有點令人撓頭
#coding:utf8 import re import cv2 import os import numpy as npfrom keras.models import Sequential from keras.layers.advanced_activations import LeakyReLU from keras.layers.core import Dense,Dropout,Activation,Flatten from keras.layers.convolutional import Conv2D,MaxPooling2D from keras.optimizers import Adam from keras.utils import np_utils from keras.layers import Densefrom keras.models import Model #得到一共多少個樣本 def getnum(file_path):pathDir = os.listdir(file_path)i = 0for allDir in pathDir:i +=1return i #制作數(shù)據(jù)集 def data_label(path,count):data = np.empty((count,1,126,126),dtype = 'float32')#建立空的四維張量類型32位浮點label = np.empty((count,),dtype = 'uint8')i = 0pathDir = os.listdir(path)for each_image in pathDir:all_path = os.path.join('%s%s' % (path,each_image))#路徑進(jìn)行連接image = cv2.imread(all_path,0)mul_num = re.findall(r"\d",all_path)#尋找字符串中的數(shù)字,由于圖像命名為300.jpg 標(biāo)簽設(shè)置為0num = int(mul_num[0])-3 # print num,each_image # cv2.imshow("fad",image) # print childarray = np.asarray(image,dtype='float32')array -= np.min(array)array /= np.max(array)data[i,:,:,:] = arraylabel[i] = int(num)i += 1return data,label #構(gòu)建卷積神經(jīng)網(wǎng)絡(luò) def cnn_model(train_data,train_label,test_data,test_label):model = Sequential() #卷積層 12 × 120 × 120 大小model.add(Conv2D(filters = 12,kernel_size = (3,3),padding = "valid",data_format = "channels_first",input_shape = (1,126,126),name="cnn1"))model.add(Activation('relu'))#激活函數(shù)使用修正線性單元 #池化層12 × 60 × 60model.add(MaxPooling2D(pool_size = (2,2),strides = (2,2),padding = "valid",name="mxp1")) #卷積層 24 * 58 * 58model.add(Conv2D(24,(3,3),padding = "valid",data_format = "channels_first",name="cnn2"))model.add(Activation('relu')) #池化層 24×29×29model.add(MaxPooling2D(pool_size = (2,2),strides = (2,2),padding = "valid",name="mxp2")) #卷積層 model.add(Conv2D(48,(3,3),padding = "valid",data_format = "channels_first",name="cnn3"))model.add(Activation('relu')) #池化層 model.add(MaxPooling2D(pool_size = (2,2),strides =(2,2),padding = "valid",name="mxp3"))model.add(Flatten())model.add(Dense(20))model.add(Activation(LeakyReLU(0.3)))model.add(Dropout(0.5))model.add(Dense(20))model.add(Activation(LeakyReLU(0.3)))model.add(Dropout(0.4))model.add(Dense(5,kernel_initializer="normal"))model.add(Activation('softmax'))adam = Adam(lr = 0.001)model.compile(optimizer = adam,loss = 'categorical_crossentropy',metrics = ['accuracy'])print ('----------------training-----------------------')model.fit(train_data,train_label,batch_size = 20,epochs = 1,shuffle = "True",validation_split = 0.1)print ('----------------testing------------------------')loss,accuracy = model.evaluate(test_data,test_label)print ('\n test loss:',loss)print ('\n test accuracy',accuracy)##注意縮進(jìn) 觀察層應(yīng)為模型之中dense1_layer_model = Model(inputs=model.input,outputs=model.get_layer("cnn2").output)dense1_output = dense1_layer_model.predict(train_data)print (dense1_output.shape)weight_Dense_1,bias_Dense_1 = model.get_layer("cnn2").get_weights() print(weight_Dense_1.shape)print(bias_Dense_1.shape)print(weight_Dense_1)print(bias_Dense_1)train_path = "/data_base/all_data/train_scale/" test_path = "/data_base/all_data/test_scale/" train_count = getnum(train_path) test_count = getnum(test_path) train_data,train_label = data_label(train_path,train_count) test_data,test_label = data_label(test_path,test_count) train_label = np_utils.to_categorical(train_label,num_classes = 5) test_label = np_utils.to_categorical(test_label,num_classes = 5) cnn_model(train_data,train_label,test_data,test_label)##錯誤 #取某一層的輸出為輸出新建為model,采用函數(shù)模型 #dense1_layer_model = Model(inputs=model.input, # outputs=model.get_layer('cnn1').output) #以這個model的預(yù)測值作為輸出 #dense1_output = dense1_layer_model.predict(data)#print getnum('/home/zhanghao/data/classification/test_scale/') #data_label('/home/zhanghao/data/classification/test_scale/',1) #cv.WaitKey(0)train_path = "/data_base/all_data/train_scale/" test_path = "/data_base/all_data/test_scale/" train_count = getnum(train_path) test_count = getnum(test_path) train_data,train_label = data_label(train_path,train_count) test_data,test_label = data_label(test_path,test_count) train_label = np_utils.to_categorical(train_label,num_classes = 5) test_label = np_utils.to_categorical(test_label,num_classes = 5) cnn_model(train_data,train_label,test_data,test_label)Matlab CNN ToolBox
這個工具箱最早是在Github上開源的,論壇上也有很多同學(xué)對源碼進(jìn)行解讀,我覺得都挺好的,不過,我覺得最好的輔助理解是Sunshine同學(xué)寫的兩層CNN的Matlab實現(xiàn),他把前一個卷積+池化和后一個卷積+池化之間的前饋和反饋連接關(guān)系講得很清楚,并且,和這個CNN ToolBox的處理方式一致,讀者能夠很直觀地看到各個子層的維數(shù)變化
總結(jié)
看了挺多資料的,覺得把這兩個例子讀通,會很有幫助,尤其是Matlab的這個,你可以看到很多細(xì)節(jié)的處理方式
總結(jié)
以上是生活随笔為你收集整理的CNN图像识别_算法篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 流媒体传输协议系列之--RTSP协议详解
- 下一篇: boost::split()的使用方式