日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Matlab实现CNN(一)

發布時間:2025/3/17 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Matlab实现CNN(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

卷積神經網絡CNN是深度學習的一個重要組成部分,由于其優異的學習性能(尤其是對圖片的識別)。近年來研究異常火爆,出現了很多模型LeNet、Alex net、ZF net等等。由于大多高校在校生使用matlab比較多,而網上的教程代碼基本都基于caffe框架或者python,對于新入門的同學來說甚是煎熬,所以本文采用matlab結合MNIst手寫數據庫完成對手寫數字的識別。本人水平有限,如有紕漏,還望各路大神,幫忙指正。?
一、卷積網絡原理

1、動機

卷積神經網絡(CNN)是多層感知機(MLP)的一個變種模型,它是從生物學概念中演化而來的。從Hubel和Wiesel早期對貓的視覺皮層的研究工作,我們知道在視覺皮層存在一種細胞的復雜分布,,這些細胞對于外界的輸入局部是很敏感的,它們被稱為“感受野”(細胞),它們以某種方法來覆蓋整個視覺域。這些細胞就像一些濾波器一樣,它們對輸入的圖像是局部敏感的,因此能夠更好地挖掘出自然圖像中的目標的空間關系信息。

此外,視覺皮層存在兩類相關的細胞,S細胞(Simple Cell)和C(Complex Cell)細胞。S細胞在自身的感受野內最大限度地對圖像中類似邊緣模式的刺激做出響應,而C細胞具有更大的感受野,它可以對圖像中產生刺激的模式的空間位置進行精準地定位。

視覺皮層作為目前已知的最為強大的視覺系統,廣受關注。學術領域出現了很多基于它的神經啟發式模型。比如:NeoCognitron [Fukushima], HMAX [Serre07] 以及本教程要討論的重點 LeNet-5 [LeCun98]。

2、稀疏連接

CNNs通過加強神經網絡中相鄰層之間節點的局部連接模式(Local Connectivity Pattern)來挖掘自然圖像(中的興趣目標)的空間局部關聯信息。第m層隱層的節點與第m-1層的節點的局部子集,并具有空間連續視覺感受野的節點(就是m-1層節點中的一部分,這部分節點在m-1層都是相鄰的)相連。可以用下面的圖來表示這種連接。

假設,m-1層為視網膜輸入層(接受自然圖像)。根據上圖的描述,在m-1層上面的m層的神經元節點都具有寬度為3的感受野,m層每一個節點連接下面的視網膜層的3個相鄰的節點。m+1層的節點與它下面一層的節點有著相似的連接屬性,所以m+1層的節點仍與m層中3個相鄰的節點相連,但是對于輸入層(視網膜層)連接數就變多了,在本圖中是5。這種結構把訓練好的濾波器(corresponding to the input producing the strongest response)構建成了一種空間局部模式(因為每個上層節點都只對感受野中的,連接的局部的下層節點有響應)。根據上面圖,多層堆積形成了濾波器(不再是線性的了),它也變得更具有全局性了(如包含了一大片的像素空間)。比如,在上圖中,第m+1層能夠對寬度為5的非線性特征進行編碼(就像素空間而言)。

3、權值共享

在CNNs中,每一個稀疏濾波器hi在整個感受野中是重復疊加的,這些重復的節點形式了一種特征圖(feature map),這個特種圖可以共享相同的參數,比如相同的權值矩陣和偏置向量。?

在上圖中,屬于同一個特征圖的三個隱層節點,因為需要共享相同顏色的權重, 他們的被限制成相同的。在這里, 梯度下降算法仍然可以用來訓練這些共享的參數,只需要在原算法的基礎上稍作改動即可。共享權重的梯度可以對共享參數的梯度進行簡單的求和得到。

二、網絡的分析?
上面這些內容,基本就是CNN的精髓所在了,下面結合LeNet做具體的分析。?
結構圖:?
?
?
LeNet算上輸入輸出一共為八層,下面逐層分析。?
第一層:數據輸入層?
CNN的強項在于圖片的處理,lenet的輸入為32*32的矩陣圖片。這里需要注意的點:?
1、數據的歸一化,這里的歸一化是廣義的,不一定要歸到0-1,但要是相同的一個區間范圍,一般我們的灰度圖為0-255。?
2、數據的去均值,如果樣本有非零的均值,而且與測試部分的非零均值不一致,可能就會導致識別率的下降。當然這不一定發生,我們這么做是為了增加系統的魯棒性。?
?
第二層:卷積層c1?
卷積層是卷積神經網絡的核心,通過不同的卷積核,來獲取圖片的特征。卷積核相當于一個濾波器,不同的濾波器提取不同特征。打個比方,對于手寫數字識別,某一個卷積核提取‘一’,另一個卷積核提取‘|’,所以這個數字很有可能就判定為‘7’。當然實際要比這復雜度得多,但原理大概就是這個樣子。?
第三層:pooling層?
基本每個卷積層后邊都會接一個pooling層,目的是為了降維。一般都將原來的卷積層的輸出矩陣大小變為原來的一半,方便后邊的運算。另外,pooling層增加了系統的魯棒性,把原來的準確描述變為了概略描述(原來矩陣大小為28*28,現在為14*14,必然有一部分信息丟失,一定程度上防止了過擬合)。?
第四層:卷積層?
與之前類似,在之前的特征中進一步提取特征,對原樣本進行更深層次的表達。注意:這里不是全連接。這里不是全連接。這里不是全連接。X代表連接,空白代表不連。?
?
第五層:pooling層?
與之前類似。?
第六層:卷積層(全連接)?
這里有120個卷積核,這里是全連接的。將矩陣卷積成一個數,方便后邊網絡進行判定。?
第七層:全連接層?
和MLP中的隱層一樣,獲得高維空間數據的表達。?
第八層:輸出層?
這里一般采用RBF網絡,每個RBF的中心為每個類別的標志,網絡輸出越大,代表越不相似,輸出的最小值即為網絡的判別結果。?
三、卷積網絡的BP訓練?
前面的都很好理解,卷積神經網絡的難度在于BP過程。網上zouxy09的博文寫的很好,可以看一下,自己搞明白。傳送門:CNN的BP推導?
四、代碼部分?
關于MNIST數據集,網上有很多現成的代碼對其進行提取,但提取出來的都是亂序的很不利于使用。這里有提取好的分類后的,詳情傳送門?
簡單起見,我們的代碼選用一層卷積層。?
CNN_simple_mian.m

%%% matlab實現LeNet-5 %%% 作者:xd.wp %%% 時間:2016.10.22 14:29 %% 程序說明 % 1、池化(pooling)采用平均2*2 % 2、網絡結點數說明: % 輸入層:28*28 % 第一層:24*24(卷積)*20 % tanh % 第二層:12*12(pooling)*20 % 第三層:100(全連接) % 第四層:10(softmax) % 3、網絡訓練部分采用800個樣本,檢驗部分采用100個樣本 clear all;clc; %% 網絡初始化 layer_c1_num=20; layer_s1_num=20; layer_f1_num=100; layer_output_num=10; %權值調整步進 yita=0.01; %bias初始化 bias_c1=(2*rand(1,20)-ones(1,20))/sqrt(20); bias_f1=(2*rand(1,100)-ones(1,100))/sqrt(20); %卷積核初始化 [kernel_c1,kernel_f1]=init_kernel(layer_c1_num,layer_f1_num); %pooling核初始化 pooling_a=ones(2,2)/4; %全連接層的權值 weight_f1=(2*rand(20,100)-ones(20,100))/sqrt(20); weight_output=(2*rand(100,10)-ones(100,10))/sqrt(100); disp('網絡初始化完成......'); %% 開始網絡訓練 disp('開始網絡訓練......'); for iter=1:20 for n=1:20for m=0:9%讀取樣本train_data=imread(strcat(num2str(m),'_',num2str(n),'.bmp'));train_data=double(train_data);% 去均值 % train_data=wipe_off_average(train_data);%前向傳遞,進入卷積層1for k=1:layer_c1_numstate_c1(:,:,k)=convolution(train_data,kernel_c1(:,:,k));%進入激勵函數state_c1(:,:,k)=tanh(state_c1(:,:,k)+bias_c1(1,k));%進入pooling1state_s1(:,:,k)=pooling(state_c1(:,:,k),pooling_a);end%進入f1層[state_f1_pre,state_f1_temp]=convolution_f1(state_s1,kernel_f1,weight_f1);%進入激勵函數for nn=1:layer_f1_numstate_f1(1,nn)=tanh(state_f1_pre(:,:,nn)+bias_f1(1,nn));end%進入softmax層for nn=1:layer_output_numoutput(1,nn)=exp(state_f1*weight_output(:,nn))/sum(exp(state_f1*weight_output));end%% 誤差計算部分Error_cost=-output(1,m+1); % if (Error_cost<-0.98) % break; % end%% 參數調整部分[kernel_c1,kernel_f1,weight_f1,weight_output,bias_c1,bias_f1]=CNN_upweight(yita,Error_cost,m,train_data,...state_c1,state_s1,...state_f1,state_f1_temp,...output,...kernel_c1,kernel_f1,weight_f1,weight_output,bias_c1,bias_f1);end end end disp('網絡訓練完成,開始檢驗......'); count=0; for n=1:20for m=0:9%讀取樣本train_data=imread(strcat(num2str(m),'_',num2str(n),'.bmp'));train_data=double(train_data);% 去均值 % train_data=wipe_off_average(train_data);%前向傳遞,進入卷積層1for k=1:layer_c1_numstate_c1(:,:,k)=convolution(train_data,kernel_c1(:,:,k));%進入激勵函數state_c1(:,:,k)=tanh(state_c1(:,:,k)+bias_c1(1,k));%進入pooling1state_s1(:,:,k)=pooling(state_c1(:,:,k),pooling_a);end%進入f1層[state_f1_pre,state_f1_temp]=convolution_f1(state_s1,kernel_f1,weight_f1);%進入激勵函數for nn=1:layer_f1_numstate_f1(1,nn)=tanh(state_f1_pre(:,:,nn)+bias_f1(1,nn));end%進入softmax層for nn=1:layer_output_numoutput(1,nn)=exp(state_f1*weight_output(:,nn))/sum(exp(state_f1*weight_output));end[p,classify]=max(output);if (classify==m+1)count=count+1;endfprintf('真實數字為%d 網絡標記為%d 概率值為%d \n',m,classify-1,p);end end

init_kernel.m

function [kernel_c1,kernel_f1]=init_kernel(layer_c1_num,layer_f1_num) %% 卷積核初始化 for n=1:layer_c1_numkernel_c1(:,:,n)=(2*rand(5,5)-ones(5,5))/12; end for n=1:layer_f1_numkernel_f1(:,:,n)=(2*rand(12,12)-ones(12,12)); end end

convolution.m

function [state]=convolution(data,kernel) %實現卷積層操作 [data_row,data_col]=size(data); [kernel_row,kernel_col]=size(kernel); for m=1:data_col-kernel_col+1for n=1:data_row-kernel_row+1state(m,n)=sum(sum(data(m:m+kernel_row-1,n:n+kernel_col-1).*kernel));end end end

pooling.m

function state=pooling(data,pooling_a) %% 實現取樣層pooling操作 [data_row,data_col]=size(data); [pooling_row,pooling_col]=size(pooling_a); for m=1:data_col/pooling_colfor n=1:data_row/pooling_rowstate(m,n)=sum(sum(data(2*m-1:2*m,2*n-1:2*n).*pooling_a));end end end

convolution_f1.m

function [state_f1,state_f1_temp]=convolution_f1(state_s1,kernel_f1,weight_f1) %% 完成卷積層2操作 layer_f1_num=size(weight_f1,2); layer_s1_num=size(weight_f1,1);%% for n=1:layer_f1_numcount=0;for m=1:layer_s1_numtemp=state_s1(:,:,m)*weight_f1(m,n);count=count+temp;endstate_f1_temp(:,:,n)=count;state_f1(:,:,n)=convolution(state_f1_temp(:,:,n),kernel_f1(:,:,n)); end end

CNN_upweight.m

function [kernel_c1,kernel_f1,weight_f1,weight_output,bias_c1,bias_f1]=CNN_upweight(yita,Error_cost,classify,train_data,state_c1,state_s1,state_f1,state_f1_temp,...output,kernel_c1,kernel_f1,weight_f1,weight_output,bias_c1,bias_f1) %%% 完成參數更新,權值和卷積核 %% 結點數目 layer_c1_num=size(state_c1,3); layer_s1_num=size(state_s1,3); layer_f1_num=size(state_f1,2); layer_output_num=size(output,2);[c1_row,c1_col,~]=size(state_c1); [s1_row,s1_col,~]=size(state_s1);[kernel_c1_row,kernel_c1_col]=size(kernel_c1(:,:,1)); [kernel_f1_row,kernel_f1_col]=size(kernel_f1(:,:,1)); %% 保存網絡權值 kernel_c1_temp=kernel_c1; kernel_f1_temp=kernel_f1;weight_f1_temp=weight_f1; weight_output_temp=weight_output; %% Error計算 label=zeros(1,layer_output_num); label(1,classify+1)=1; delta_layer_output=output-label; %% 更新weight_output for n=1:layer_output_numdelta_weight_output_temp(:,n)=delta_layer_output(1,n)*state_f1'; end weight_output_temp=weight_output_temp-yita*delta_weight_output_temp;%% 更新bias_f1以及kernel_f1 for n=1:layer_f1_numcount=0;for m=1:layer_output_numcount=count+delta_layer_output(1,m)*weight_output(n,m);end%bias_f1delta_layer_f1(1,n)=count*(1-tanh(state_f1(1,n)).^2);delta_bias_f1(1,n)=delta_layer_f1(1,n);%kernel_f1delta_kernel_f1_temp(:,:,n)=delta_layer_f1(1,n)*state_f1_temp(:,:,n); end bias_f1=bias_f1-yita*delta_bias_f1; kernel_f1_temp=kernel_f1_temp-yita*delta_kernel_f1_temp; %% 更新weight_f1 for n=1:layer_f1_numdelta_layer_f1_temp(:,:,n)=delta_layer_f1(1,n)*kernel_f1(:,:,n); end for n=1:layer_s1_numfor m=1:layer_f1_numdelta_weight_f1_temp(n,m)=sum(sum(delta_layer_f1_temp(:,:,m).*state_s1(:,:,n)));end end weight_f1_temp=weight_f1_temp-yita*delta_weight_f1_temp;%% 更新 bias_c1 for n=1:layer_s1_numcount=0;for m=1:layer_f1_numcount=count+delta_layer_f1_temp(:,:,m)*weight_f1(n,m); enddelta_layer_s1(:,:,n)=count;delta_layer_c1(:,:,n)=kron(delta_layer_s1(:,:,n),ones(2,2)/4).*(1-tanh(state_c1(:,:,n)).^2);delta_bias_c1(1,n)=sum(sum(delta_layer_c1(:,:,n))); end bias_c1=bias_c1-yita*delta_bias_c1; %% 更新 kernel_c1 for n=1:layer_c1_numdelta_kernel_c1_temp(:,:,n)=rot90(conv2(train_data,rot90(delta_layer_c1(:,:,n),2),'valid'),2); end kernel_c1_temp=kernel_c1_temp-yita*delta_kernel_c1_temp;%% 網絡權值更新 kernel_c1=kernel_c1_temp; kernel_f1=kernel_f1_temp;weight_f1=weight_f1_temp; weight_output=weight_output_temp;end

程序運行結果:?

檢驗200個,196個識別正確,4個識別錯誤。?

總結

以上是生活随笔為你收集整理的Matlab实现CNN(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。