深度學習Matlab工具箱DeepLearnToolbox代碼注釋(轉)
2017-01-16 by:CAE仿真在線 來源:互聯(lián)網
深度學習Matlab工具箱DeepLearnToolbox代碼注釋
----轉自csdn“陳俊嶺的程序員之路”
%%=========================================================================
% 主要功能:在mnist數(shù)據庫上做實驗,驗證工具箱的有效性
% 算法流程:1)載入訓練樣本和測試樣本
% 2)設置CNN參數(shù),并進行訓練
% 3)進行檢測cnntest()
% 注意事項:1)由于直接將所有測試樣本輸入會導致內存溢出,故采用一次只測試一個訓練樣本的測試方法
%%=========================================================================
%%
%%%%%%%%%%%%%%%%%%%%加載數(shù)據集%%%%%%%%%%%%%%%%%%%%
load mnist_uint8;
train_x = double(reshape(train_x',28,28,60000))/255;
test_x = double(reshape(test_x',28,28,10000))/255;
train_y = double(train_y');
test_y = double(test_y');
%%
%%=========================================================================
%%%%%%%%%%%%%%%%%%%%設置卷積神經網絡參數(shù)%%%%%%%%%%%%%%%%%%%%
% 主要功能:訓練一個6c-2s-12c-2s形式的卷積神經網絡,預期性能如下:
% 1)迭代一次需要200秒左右,錯誤率大約為11%
% 2)迭代一百次后錯誤率大約為1.2%
% 算法流程:1)構建神經網絡并進行訓練,以CNN結構體的形式保存
% 2)用已知的訓練樣本進行測試
% 注意事項:1)之前在測試的時候提示內存溢出,后來莫名其妙的又不溢出了,估計到了系統(tǒng)的內存臨界值
%%=========================================================================
rand('state',0)
cnn.layers = {
struct('type', 'i') %輸入層
struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %卷積層
struct('type', 's', 'scale', 2) %下采樣層
struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %卷積層
struct('type', 's', 'scale', 2) %下采樣層
};
cnn = cnnsetup(cnn, train_x, train_y);
opts.alpha = 1;
opts.batchsize = 50;
opts.numepochs = 5;
cnn = cnntrain(cnn, train_x, train_y, opts);
save CNN_5 cnn;
load CNN_5;
[er, bad] = cnntest(cnn, test_x, test_y);
figure; plot(cnn.rL);
assert(er<0.12, 'Too big error');
深度學習Matlab工具箱代碼注釋——cnnsetup.m
%%=========================================================================
% 函數(shù)名稱:cnnsetup
% 輸入參數(shù):net,待設置的卷積神經網絡;x,訓練樣本;y,訓練樣本對應標簽;
% 輸出參數(shù):net,初始化完成的卷積神經網絡
% 主要功能:對CNN的結構進行初始化
% 算法流程:1)
% 注意事項:1)isOctave這個語句是為了拋出一個程序在Octave平臺上運行時的一個BUG,在matlab平臺上可以直接注釋掉
% 2)net.layers中有五個struct類型的元素,實際上就表示CNN共有五層,這里范圍的是5
%%=========================================================================
function net = cnnsetup(net, x, y)
assert(~isOctave() || compare_versions(OCTAVE_VERSION, '3.8.0', '>='), ['Octave 3.8.0 or greater is required for CNNs as there is a bug in convolution in previous versions. See http://savannah.gnu.org/bugs/?39314. Your version is ' myOctaveVersion]);
inputmaps = 1; %初始化網絡輸入層數(shù)為1層
%%=========================================================================
% 主要功能:得到輸入圖像的行數(shù)和列數(shù)
% 注意事項:1)B=squeeze(A) 返回和矩陣A相同元素但所有單一維都移除的矩陣B,單一維是滿足size(A,dim)=1的維。
% train_x中圖像的存放方式是三維的reshape(train_x',28,28,60000),前面兩維表示圖像的行與列,
% 第三維就表示有多少個圖像。這樣squeeze(x(:, :, 1))就相當于取第一個圖像樣本后,再把第三維
% 移除,就變成了28x28的矩陣,也就是得到一幅圖像,再size一下就得到了訓練樣本圖像的行數(shù)與列數(shù)了
%%=========================================================================
mapsize = size(squeeze(x(:, :, 1)));
%%%%%%%%%%%%%%%%%%%%下面通過傳入net這個結構體來逐層構建CNN網絡%%%%%%%%%%%%%%%%%%%%
for l = 1 : numel(net.layers) %對于每一層
if strcmp(net.layers{l}.type, 's') %如果當前層是下采樣層
%%=========================================================================
% 主要功能:獲取下采樣之后特征map的尺寸
% 注意事項:1)subsampling層的mapsize,最開始mapsize是每張圖的大小28*28
% 這里除以scale=2,就是pooling之后圖的大小,pooling域之間沒有重疊,所以pooling后的圖像為14*14
% 注意這里的右邊的mapsize保存的都是上一層每張?zhí)卣鱩ap的大小,它會隨著循環(huán)進行不斷更新
%%=========================================================================
mapsize = mapsize / net.layers{l}.scale;
assert(all(floor(mapsize)==mapsize), ['Layer ' num2str(l) ' size must be integer. Actual: ' num2str(mapsize)]);
for j = 1 : inputmaps %對于上一層的每個特征圖
net.layers{l}.b{j} = 0; %將偏置初始化為零
end
end
if strcmp(net.layers{l}.type, 'c') %如果當前層是卷基層
%%=========================================================================
% 主要功能:獲取卷積后的特征map尺寸以及當前層待學習的卷積核的參數(shù)數(shù)量
% 注意事項:1)舊的mapsize保存的是上一層的特征map的大小,那么如果卷積核的移動步長是1,那用
% kernelsize*kernelsize大小的卷積核卷積上一層的特征map后,得到的新的map的大小就是下面這樣
% 2)fan_out代表該層需要學習的參數(shù)個數(shù)。每張?zhí)卣鱩ap是一個(后層特征圖數(shù)量)*(用來卷積的patch圖的大小)
% 因為是通過用一個核窗口在上一個特征map層中移動(核窗口每次移動1個像素),遍歷上一個特征map
% 層的每個神經元。核窗口由kernelsize*kernelsize個元素組成,每個元素是一個獨立的權值,所以
% 就有kernelsize*kernelsize個需要學習的權值,再加一個偏置值。另外,由于是權值共享,也就是
% 說同一個特征map層是用同一個具有相同權值元素的kernelsize*kernelsize的核窗口去感受輸入上一
% 個特征map層的每個神經元得到的,所以同一個特征map,它的權值是一樣的,共享的,權值只取決于
% 核窗口。然后,不同的特征map提取輸入上一個特征map層不同的特征,所以采用的核窗口不一樣,也
% 就是權值不一樣,所以outputmaps個特征map就有(kernelsize*kernelsize+1)* outputmaps那么多的權值了
% 但這里fan_out只保存卷積核的權值W,偏置b在下面獨立保存
%%=========================================================================
mapsize = mapsize - net.layers{l}.kernelsize + 1;
fan_out = net.layers{l}.outputmaps * net.layers{l}.kernelsize ^ 2;
for j = 1 : net.layers{l}.outputmaps %對于卷積層的每一個輸出map
%%=========================================================================
% 主要功能:獲取卷積層與前一層輸出map之間需要鏈接的參數(shù)鏈個數(shù)
% 注意事項:1)fan_out保存的是對于上一層的一張?zhí)卣鱩ap,我在這一層需要對這一張?zhí)卣鱩ap提取outputmaps種特征,
% 提取每種特征用到的卷積核不同,所以fan_out保存的是這一層輸出新的特征需要學習的參數(shù)個數(shù)
% 而,fan_in保存的是,我在這一層,要連接到上一層中所有的特征map,然后用fan_out保存的提取特征
% 的權值來提取他們的特征。也即是對于每一個當前層特征圖,有多少個參數(shù)鏈到前層
%%=========================================================================
fan_in = inputmaps * net.layers{l}.kernelsize ^ 2;
for i = 1 : inputmaps %對于上一層的每一個輸出特征map(本層的輸入map)
%%=========================================================================
% 主要功能:隨機初始化卷積核的權值,再將偏置均初始化為零
% 注意事項:1)隨機初始化權值,也就是共有outputmaps個卷積核,對上層的每個特征map,都需要用這么多個卷積核去卷積提取特征。
% rand(n)是產生n×n的 0-1之間均勻取值的數(shù)值的矩陣,再減去0.5就相當于產生-0.5到0.5之間的隨機數(shù)
% 再 *2 就放大到 [-1, 1]。然后再乘以后面那一數(shù),why?
% 反正就是將卷積核每個元素初始化為[-sqrt(6 / (fan_in + fan_out)), sqrt(6 / (fan_in + fan_out))]
% 之間的隨機數(shù)。因為這里是權值共享的,也就是對于一張?zhí)卣鱩ap,所有感受野位置的卷積核都是一樣的
% 所以只需要保存的是 inputmaps * outputmaps 個卷積核。
% 2)為什么這里是inputmaps * outputmaps個卷積核?
%%=========================================================================
net.layers{l}.k{i}{j} = (rand(net.layers{l}.kernelsize) - 0.5) * 2 * sqrt(6 / (fan_in + fan_out));
end
net.layers{l}.b{j} = 0;
end
inputmaps = net.layers{l}.outputmaps; %在卷積層會更新每層網絡的輸出map數(shù)量
end
end
%%=========================================================================
% 主要功能:初始化最后一層,也就是輸出層的參數(shù)值
% 算法流程:1)fvnum 是輸出層的前面一層的神經元個數(shù)。這一層的上一層是經過pooling后的層,包含有inputmaps個
% 特征map。每個特征map的大小是mapsize,所以,該層的神經元個數(shù)是 inputmaps * (每個特征map的大小)
% 2)onum 是標簽的個數(shù),也就是輸出層神經元的個數(shù)。你要分多少個類,自然就有多少個輸出神經元
% 3)net.ffb和net.ffW為最后一層(全連接層)的偏置和權重
%%=========================================================================
fvnum = prod(mapsize) * inputmaps;
onum = size(y, 1);
net.ffb = zeros(onum, 1);
net.ffW = (rand(onum, fvnum) - 0.5) * 2 * sqrt(6 / (onum + fvnum));
end
深度學習Matlab工具箱代碼注釋——cnntrain.m
%%=========================================================================
%函數(shù)名稱:cnntrain()
%輸入參數(shù):net,神經網絡;x,訓練數(shù)據矩陣;y,訓練數(shù)據的標簽矩陣;opts,神經網絡的相關訓練參數(shù)
%輸出參數(shù):net,訓練完成的卷積神經網絡
%算法流程:1)將樣本打亂,隨機選擇進行訓練;
% 2)取出樣本,通過cnnff2()函數(shù)計算當前網絡權值和網絡輸入下網絡的輸出
% 3)通過BP算法計算誤差對網絡權值的導數(shù)
% 4)得到誤差對權值的導數(shù)后,就通過權值更新方法去更新權值
%注意事項:1)使用BP算法計算梯度
%%=========================================================================
function net = cnntrain(net, x, y, opts)
m = size(x, 3); %m保存的是訓練樣本個數(shù)
disp(['樣本總個數(shù)=' num2str(m)]);
numbatches = m / opts.batchsize; %numbatches表示每次迭代中所選取的訓練樣本數(shù)
if rem(numbatches, 1) ~= 0 %如果numbatches不是整數(shù),則程序發(fā)生錯誤
error('numbatches not integer');
end
%%=====================================================================
%主要功能:CNN網絡的迭代訓練
%實現(xiàn)步驟:1)通過randperm()函數(shù)將原來的樣本順序打亂,再挑出一些樣本來進行訓練
% 2)取出樣本,通過cnnff2()函數(shù)計算當前網絡權值和網絡輸入下網絡的輸出
% 3)通過BP算法計算誤差對網絡權值的導數(shù)
% 4)得到誤差對權值的導數(shù)后,就通過權值更新方法去更新權值
%注意事項:1)P = randperm(N),返回[1, N]之間所有整數(shù)的一個隨機的序列,相當于把原來的樣本排列打亂,
% 再挑出一些樣本來訓練
% 2)采用累積誤差的計算方式來評估當前網絡性能,即當前誤差 = 以前誤差 * 0.99 + 本次誤差 * 0.01
% 使得網絡盡可能收斂到全局最優(yōu)
%%=====================================================================
net.rL = []; %代價函數(shù)值,也就是誤差值
for i = 1 : opts.numepochs %對于每次迭代
disp(['epoch ' num2str(i) '/' num2str(opts.numepochs)]);
tic; %使用tic和toc來統(tǒng)計程序運行時間
%%%%%%%%%%%%%%%%%%%%取出打亂順序后的batchsize個樣本和對應的標簽 %%%%%%%%%%%%%%%%%%%%
kk = randperm(m);
for l = 1 : numbatches
batch_x = x(:, :, kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize));
batch_y = y(:, kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize));
%%%%%%%%%%%%%%%%%%%%在當前的網絡權值和網絡輸入下計算網絡的輸出(特征向量)%%%%%%%%%%%%%%%%%%%%
net = cnnff(net, batch_x); %卷積神經網絡的前饋運算
%%%%%%%%%%%%%%%%%%%%通過對應的樣本標簽用bp算法來得到誤差對網絡權值的導數(shù)%%%%%%%%%%%%%%%%%%%%
net = cnnbp(net, batch_y); %卷積神經網絡的BP算法
%%%%%%%%%%%%%%%%%%%%通過權值更新方法去更新權值%%%%%%%%%%%%%%%%%%%%
net = cnnapplygrads(net, opts);
if isempty(net.rL)
net.rL(1) = net.L; %代價函數(shù)值,也就是均方誤差值 ,在cnnbp.m中計算初始值 net.L = 1/2* sum(net.e(:) .^ 2) / size(net.e, 2);
end
net.rL(end + 1) = 0.99 * net.rL(end) + 0.01 * net.L; %采用累積的方式計算累積誤差
end
toc;
end
end
深度學習Matlab工具箱代碼注釋——cnnff.m
%%=========================================================================
%函數(shù)名稱:cnnff()
%輸入參數(shù):net,神經網絡;x,訓練數(shù)據矩陣;
%輸出參數(shù):net,訓練完成的卷積神經網絡
%主要功能:使用當前的神經網絡對輸入的向量進行預測
%算法流程:1)將樣本打亂,隨機選擇進行訓練;
% 2)講樣本輸入網絡,層層映射得到預測值
%注意事項:1)使用BP算法計算梯度
%%=========================================================================
function net = cnnff(net, x)
n = numel(net.layers); %層數(shù)
net.layers{1}.a{1} = x; %網絡的第一層就是輸入,但這里的輸入包含了多個訓練圖像
inputmaps = 1; %輸入層只有一個特征map,也就是原始的輸入圖像
for l = 2 : n %對于每層(第一層是輸入層,循環(huán)時先忽略掉)
if strcmp(net.layers{l}.type, 'c') %如果當前是卷積層
for j = 1 : net.layers{l}.outputmaps %對每一個輸入map,需要用outputmaps個不同的卷積核去卷積圖像
%%=========================================================================
%主要功能:創(chuàng)建outmap的中間變量,即特征矩陣
%實現(xiàn)步驟:用這個公式生成一個零矩陣,作為特征map
%注意事項:1)對于上一層的每一張?zhí)卣鱩ap,卷積后的特征map的大小是:(輸入map寬 - 卷積核的寬 + 1)* (輸入map高 - 卷積核高 + 1)
% 2)由于每層都包含多張?zhí)卣鱩ap,則對應的索引則保存在每層map的第三維,及變量Z中
%%=========================================================================
z = zeros(size(net.layers{l - 1}.a{1}) - [net.layers{l}.kernelsize - 1 net.layers{l}.kernelsize - 1 0]);
for i = 1 : inputmaps %對于輸入的每個特征map
%%=========================================================================
%主要功能:將上一層的每一個特征map(也就是這層的輸入map)與該層的卷積核進行卷積
%實現(xiàn)步驟:1)進行卷積
% 2)加上對應位置的基b,然后再用sigmoid函數(shù)算出特征map中每個位置的激活值,作為該層輸出特征map
%注意事項:1)當前層的一張?zhí)卣鱩ap,是用一種卷積核去卷積上一層中所有的特征map,然后所有特征map對應位置的卷積值的和
% 2)有些論文或者實際應用中,并不是與全部的特征map鏈接的,有可能只與其中的某幾個連接
%%=========================================================================
z = z + convn(net.layers{l - 1}.a{i}, net.layers{l}.k{i}{j}, 'valid');
end
net.layers{l}.a{j} = sigm(z + net.layers{l}.b{j}); %加基(加上加性偏置b)
end
inputmaps = net.layers{l}.outputmaps; %更新當前層的map數(shù)量;
elseif strcmp(net.layers{l}.type, 's') %如果當前層是下采樣層
for j = 1 : inputmaps
%%=========================================================================
%主要功能:對特征map進行下采樣
%實現(xiàn)步驟:1)進行卷積
% 2)最終pooling的結果需要從上面得到的卷積結果中以scale=2為步長,跳著把mean pooling的值讀出來
%注意事項:1)例如我們要在scale=2的域上面執(zhí)行mean pooling,那么可以卷積大小為2*2,每個元素都是1/4的卷積核
% 2)因為convn函數(shù)的默認卷積步長為1,而pooling操作的域是沒有重疊的,所以對于上面的卷積結果
% 3)是利用卷積的方法實現(xiàn)下采樣
%%=========================================================================
z = convn(net.layers{l - 1}.a{j}, ones(net.layers{l}.scale) / (net.layers{l}.scale ^ 2), 'valid');
net.layers{l}.a{j} = z(1 : net.layers{l}.scale : end, 1 : net.layers{l}.scale : end, :); %跳讀mean pooling的值
end
end
end
%%=========================================================================
%主要功能:輸出層,將最后一層得到的特征變成一條向量,作為最終提取得到的特征向量
%實現(xiàn)步驟:1)獲取倒數(shù)第二層中每個特征map的尺寸
% 2)用reshape函數(shù)將map轉換為向量的形式
% 3)使用sigmoid(W*X + b)函數(shù)計算樣本輸出值,放到net成員o中
%注意事項:1)在使用sigmoid()函數(shù)是,是同時計算了batchsize個樣本的輸出值
%%=========================================================================
net.fv = []; %net.fv為神經網絡倒數(shù)第二層的輸出map
for j = 1 : numel(net.layers{n}.a) %最后一層的特征map的個數(shù)
sa = size(net.layers{n}.a{j}); %第j個特征map的大小
net.fv = [net.fv; reshape(net.layers{n}.a{j}, sa(1) * sa(2), sa(3))];
end
net.o = sigm(net.ffW * net.fv + repmat(net.ffb, 1, size(net.fv, 2))); %通過全連接層的映射得到網絡的最終預測結果輸出
end
深度學習Matlab工具箱代碼注釋——cnnbp.m
%%=========================================================================
%函數(shù)名稱:cnnbp()
%輸入參數(shù):net,呆訓練的神經網絡;y,訓練樣本的標簽,即期望輸出
%輸出參數(shù):net,經過BP算法訓練得到的神經網絡
%主要功能:通過BP算法訓練神經網絡參數(shù)
%實現(xiàn)步驟:1)將輸出的殘差擴展成與最后一層的特征map相同的尺寸形式
% 2)如果是卷積層,則進行上采樣
% 3)如果是下采樣層,則進行下采樣
% 4)采用誤差傳遞公式對靈敏度進行反向傳遞
%注意事項:1)從最后一層的error倒推回來deltas,和神經網絡的BP十分相似,可以參考“UFLDL的反向傳導算法”的說明
% 2)在fvd里面保存的是所有樣本的特征向量(在cnnff.m函數(shù)中用特征map拉成的),所以這里需要重新?lián)Q回來特征map的形式,
% d保存的是delta,也就是靈敏度或者殘差
% 3)net.o .* (1 - net.o))代表輸出層附加的非線性函數(shù)的導數(shù),即sigm函數(shù)的導數(shù)
%%=========================================================================
function net = cnnbp(net, y)
n = numel(net.layers); %網絡層數(shù)
net.e = net.o - y; %實際輸出與期望輸出之間的誤差
net.L = 1/2* sum(net.e(:) .^ 2) / size(net.e, 2); %代價函數(shù),采用均方誤差函數(shù)作為代價函數(shù)
net.od = net.e .* (net.o .* (1 - net.o)); %輸出層的靈敏度或者殘差,(net.o .* (1 - net.o))代表輸出層的激活函數(shù)的導數(shù)
net.fvd = (net.ffW' * net.od); %殘差反向傳播回前一層,net.fvd保存的是殘差
if strcmp(net.layers{n}.type, 'c') %只有卷積層采用sigm函數(shù)
net.fvd = net.fvd .* (net.fv .* (1 - net.fv)); %net.fv是前一層的輸出(未經過simg函數(shù)),作為輸出層的輸入
end
%%%%%%%%%%%%%%%%%%%%將輸出的殘差擴展成與最后一層的特征map相同的尺寸形式%%%%%%%%%%%%%%%%%%%%
sa = size(net.layers{n}.a{1}); %最后一層特征map的大小。這里的最后一層都是指輸出層的前一層
fvnum = sa(1) * sa(2); %因為是將最后一層特征map拉成一條向量,所以對于一個樣本來說,特征維數(shù)是這樣
for j = 1 : numel(net.layers{n}.a) %最后一層的特征map的個數(shù)
net.layers{n}.d{j} = reshape(net.fvd(((j - 1) * fvnum + 1) : j * fvnum, :), sa(1), sa(2), sa(3));
end
for l = (n - 1) : -1 : 1 %對于輸出層前面的層(與輸出層計算殘差的方式不同)
if strcmp(net.layers{l}.type, 'c') %如果是卷積層,則進行上采樣
for j = 1 : numel(net.layers{l}.a) %該層特征map的個數(shù)
%%=========================================================================
%主要功能:卷積層的靈敏度誤差傳遞
%注意事項:1)net.layers{l}.d{j} 保存的是 第l層 的 第j個 map 的 靈敏度map。 也就是每個神經元節(jié)點的delta的值
% expand的操作相當于對l+1層的靈敏度map進行上采樣。然后前面的操作相當于對該層的輸入a進行sigmoid求導
% 這條公式請參考 Notes on Convolutional Neural Networks
%%=========================================================================
net.layers{l}.d{j} = net.layers{l}.a{j} .* (1 - net.layers{l}.a{j}) .* (expand(net.layers{l + 1}.d{j}, [net.layers{l + 1}.scale net.layers{l + 1}.scale 1]) / net.layers{l + 1}.scale ^ 2);
end
elseif strcmp(net.layers{l}.type, 's') %如果是下采樣層,則進行下采樣
%%=========================================================================
%主要功能:下采樣層的靈敏度誤差傳遞
%注意事項:1)這條公式請參考 Notes on Convolutional Neural Networks
%%=========================================================================
for i = 1 : numel(net.layers{l}.a) %第i層特征map的個數(shù)
z = zeros(size(net.layers{l}.a{1}));
for j = 1 : numel(net.layers{l + 1}.a) %第l+1層特征map的個數(shù)
z = z + convn(net.layers{l + 1}.d{j}, rot180(net.layers{l + 1}.k{i}{j}), 'full');
end
net.layers{l}.d{i} = z;
end
end
end
%%=========================================================================
%主要功能:計算梯度
%實現(xiàn)步驟:
%注意事項:1)這里與Notes on Convolutional Neural Networks中不同,這里的子采樣層沒有參數(shù),也沒有
% 激活函數(shù),所以在子采樣層是沒有需要求解的參數(shù)的
%%=========================================================================
for l = 2 : n
if strcmp(net.layers{l}.type, 'c')
for j = 1 : numel(net.layers{l}.a)
for i = 1 : numel(net.layers{l - 1}.a)
%%%%%%%%%%%%%%%%%%%%dk保存的是誤差對卷積核的導數(shù)%%%%%%%%%%%%%%%%%%%%
net.layers{l}.dk{i}{j} = convn(flipall(net.layers{l - 1}.a{i}), net.layers{l}.d{j}, 'valid') / size(net.layers{l}.d{j}, 3);
end
%%%%%%%%%%%%%%%%%%%?保存的是誤差對于bias基的導數(shù)%%%%%%%%%%%%%%%%%%%%
net.layers{l}.db{j} = sum(net.layers{l}.d{j}(:)) / size(net.layers{l}.d{j}, 3);
end
end
end
%%%%%%%%%%%%%%%%%%%%最后一層perceptron的gradient的計算%%%%%%%%%%%%%%%%%%%%
net.dffW = net.od * (net.fv)' / size(net.od, 2);
net.dffb = mean(net.od, 2);
function X = rot180(X)
X = flipdim(flipdim(X, 1), 2);
end
end
深度學習Matlab工具箱代碼注釋——cnnapplygrads.m
%%=========================================================================
%函數(shù)名稱:cnnapplygrads(),權值更新函數(shù)
%輸入參數(shù):net,權值待更新的卷積神經網絡;opts,神經網絡訓練的相關參數(shù)
%輸出參數(shù):
%算法流程:先更新卷積層的參數(shù),再更新全連接層參數(shù)
%注意事項:
%%=========================================================================
function net = cnnapplygrads(net, opts)
for l = 2 : numel(net.layers)
if strcmp(net.layers{l}.type, 'c')
for j = 1 : numel(net.layers{l}.a)
for ii = 1 : numel(net.layers{l - 1}.a)
%這里沒什么好說的,就是普通的權值更新的公式:W_new = W_old - alpha * de/dW(誤差對權值導數(shù))
net.layers{l}.k{ii}{j} = net.layers{l}.k{ii}{j} - opts.alpha * net.layers{l}.dk{ii}{j};
end
net.layers{l}.b{j} = net.layers{l}.b{j} - opts.alpha * net.layers{l}.db{j};
end
end
end
net.ffW = net.ffW - opts.alpha * net.dffW;
net.ffb = net.ffb - opts.alpha * net.dffb;
end
%%=========================================================================
% 主要功能:在mnist數(shù)據庫上做實驗,驗證工具箱的有效性
% 算法流程:1)載入訓練樣本和測試樣本
% 2)設置CNN參數(shù),并進行訓練
% 3)進行檢測cnntest()
% 注意事項:1)由于直接將所有測試樣本輸入會導致內存溢出,故采用一次只測試一個訓練樣本的測試方法
%%=========================================================================
%%
%%%%%%%%%%%%%%%%%%%%加載數(shù)據集%%%%%%%%%%%%%%%%%%%%
load mnist_uint8;
train_x = double(reshape(train_x',28,28,60000))/255;
test_x = double(reshape(test_x',28,28,10000))/255;
train_y = double(train_y');
test_y = double(test_y');
%%
%%=========================================================================
%%%%%%%%%%%%%%%%%%%%設置卷積神經網絡參數(shù)%%%%%%%%%%%%%%%%%%%%
% 主要功能:訓練一個6c-2s-12c-2s形式的卷積神經網絡,預期性能如下:
% 1)迭代一次需要200秒左右,錯誤率大約為11%
% 2)迭代一百次后錯誤率大約為1.2%
% 算法流程:1)構建神經網絡并進行訓練,以CNN結構體的形式保存
% 2)用已知的訓練樣本進行測試
% 注意事項:1)之前在測試的時候提示內存溢出,后來莫名其妙的又不溢出了,估計到了系統(tǒng)的內存臨界值
%%=========================================================================
rand('state',0)
cnn.layers = {
struct('type', 'i') %輸入層
struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %卷積層
struct('type', 's', 'scale', 2) %下采樣層
struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %卷積層
struct('type', 's', 'scale', 2) %下采樣層
};
cnn = cnnsetup(cnn, train_x, train_y);
opts.alpha = 1;
opts.batchsize = 50;
opts.numepochs = 5;
cnn = cnntrain(cnn, train_x, train_y, opts);
save CNN_5 cnn;
load CNN_5;
[er, bad] = cnntest(cnn, test_x, test_y);
figure; plot(cnn.rL);
assert(er<0.12, 'Too big error');
相關標簽搜索:深度學習Matlab工具箱DeepLearnToolbox代碼注釋(轉) MatLab培訓 MatLab培訓課程 MatLab在線視頻教程 MatLab技術學習教程 MatLab軟件教程 MatLab資料下載 MatLab代做 MatLab基礎知識 Fluent、CFX流體分析 HFSS電磁分析 Ansys培訓 Abaqus培訓