一个简单的第三方CNN自编码matlab工具箱
使用到的是手寫體數據庫,該數據庫已經集成到工具箱了,直接用就好,顯示看一看該數據庫的一部分,其目標就是通過訓練該數據庫達到識別的目的:?
緊接著是對該數據庫數據進行歸一化等等預處理。nnsetup建立一個網絡,里面會有許多參數初始化,同時在設置下opts.numepochs = 1; 該參數個人感覺就是將所有數據重復試驗次數,設置1就是實驗一次。opts.batchsize = 100;該參數是將大量樣本每隨機100個作為一波送進去實驗。再就是訓練測試了。
nnsetup:
function nn = nnsetup(architecture) %NNSETUP創建前向神經網絡 % nn = nnsetup(architecture) 返回一個神經網絡結構,architecture為結構參數 % architecture 是一個n x 1 向量,表示每一層神經元的個數 %比如architecture=[784 100 10],表示輸入層為784維輸入,100個隱含層,10個輸出層 %為什么是輸入為784:因為每一個手寫體大小為28*28的,也就是784維度 %隱含層為什么是100:隨便設置的,可以隨意修改,需要設計 %輸出為什么是10:手寫體有0-9這10種結果,所以為10nn.size = architecture;nn.n = numel(nn.size);nn.activation_function = 'tanh_opt'; % 隱含層激活函數: 'sigm' (sigmoid) or 'tanh_opt' (默認 tanh).nn.learningRate = 2; % 學習率: typically needs to be lower when using 'sigm' activation function and non-normalized inputs.nn.momentum = 0.5; % Momentum 權值動量因子nn.scaling_learningRate = 1; % 學習率變化因子 (each epoch)nn.weightPenaltyL2 = 0; % L2 regularization正則化nn.nonSparsityPenalty = 0; % 非稀疏懲罰nn.sparsityTarget = 0.05; % 稀疏目標值nn.inputZeroMaskedFraction = 0; % 自動編碼的去噪作用nn.dropoutFraction = 0; % Dropout level (http://www.cs.toronto.edu/~hinton/absps/dropout.pdf)nn.testing = 0; % Internal variable. nntest sets this to one.nn.output = 'sigm'; % 輸出激活output unit 'sigm' (=logistic), 'softmax' and 'linear'for i = 2 : nn.n % weights and weight momentumnn.W{i - 1} = (rand(nn.size(i), nn.size(i - 1)+1) - 0.5) * 2 * 4 * sqrt(6 / (nn.size(i) + nn.size(i - 1)));nn.vW{i - 1} = zeros(size(nn.W{i - 1}));% average activations (for use with sparsity)nn.p{i} = zeros(1, nn.size(i)); end end?
這個函數理解起來很簡單,初始化網絡,網絡需要什么初始化什么,一大堆初始化是適應所有的網絡的(cnn,dbn等等),有些用到了再說吧,現在你只需要知道網絡的結構,以及與稀疏編碼表示有關的參數: nn.nonSparsityPenalty ,nn.sparsityTarget,這也就是上節說到的,為什么稀疏表示,具體怎么樣不用管,實際使用的時候只是這么幾個參數設置,其他的交給程序吧。再有就是注意下激活函數 nn.activation_function。,然后網絡權值隨機初始化。
?
這里再說下這個函數整體:[nn, L] = nntrain(nn, train_x, train_y, opts);
可以看到nntrain需要的是設計的網絡nn,訓練數據train_x,訓練對應的目標值train_y,以及附加參數opts。附加參數包括:重復訓練次數opts.numepochs,訓練數據每一塊大小opts.batchsize等等。函數出來的就是訓練好的網絡nn,這個很重要,訓練好的nn為結構體,里面包括你所需要的所有信息,比如說每一層網絡的權值系數,訓練誤差,等等都可以找到,并且在nntest也是用這個訓練好的nn。nntrain的具體實現細節見上面那個博客的介紹吧。
nntrain
setup大概就這樣一個過程,下面就到了train了,打開\NN\nntrain.m
我們跳過那些檢驗傳入數據是否正確的代碼,直接到關鍵的部分
denoising 的部分請參考論文:Extracting and Composing Robust Features with Denoising Autoencoders
m = size(train_x, 1); //m是訓練樣本的數量 //注意在調用的時候我們設置了opt,batchsize是做batch gradient時候的大小 batchsize = opts.batchsize; numepochs = opts.numepochs; numbatches = m / batchsize; //計算batch的數量,訓練樣本的總個數除以一個batch的 size,得到batch的總數目 assert(rem(numbatches, 1) == 0, 'numbatches must be a integer');//即上一步 對總數據進行分組,組數應是一個整數 L = zeros(numepochs*numbatches,1); n = 1; //numepochs是循環的次數 for i = 1 : numepochs tic; // tic用來保存當前時間,而后使用toc來記錄程序完成時間。kk = randperm(m); //把batches打亂順序進行訓練,randperm(m)功能是隨機打亂一個數字序列,生成一個 亂序的1到m的數組。例如 randperm(5),ans = 2 3 4 1 5for l = 1 : numbatches batch_x = train_x(kk((l - 1) * batchsize + 1 : l * batchsize), :); //Add noise to input (for use in denoising autoencoder) //加入noise,這是denoising autoencoder需要使用到的部分 //這部分請參見《Extracting and Composing Robust Features with Denoising Autoencoders》這篇論文 //具體加入的方法就是把訓練樣例中的一些數據調整變為0,inputZeroMaskedFraction表示了調整的比例 if(nn.inputZeroMaskedFraction ~= 0) batch_x = batch_x* (rand(size(batch_x))>nn.inputZeroMaskedFraction); end batch_y = train_y(kk((l - 1) * batchsize + 1 : l * batchsize), :); //這三個函數 //nnff是進行前向傳播,nnbp是后向傳播,nnapplygrads是進行梯度下降 //我們在下面分析這些函數的代碼 nn = nnff(nn, batch_x, batch_y); nn = nnbp(nn); nn = nnapplygrads(nn); L(n) = nn.L; n = n + 1; end t = toc; if ishandle(fhandle) if opts.validation == 1 loss = nneval(nn, loss, train_x, train_y, val_x, val_y); else loss = nneval(nn, loss, train_x, train_y); end nnupdatefigures(nn, fhandle, loss, opts, i); end disp(['epoch ' num2str(i) '/' num2str(opts.numepochs) '. Took ' num2str(t) ' seconds' '. Mean squared error on training set is ' num2str(mean(L((n-numbatches):(n-1))))]); nn.learningRate = nn.learningRate * nn.scaling_learningRate; end下面分析三個函數nnff,nnbp和nnapplygrads
nnff
nnff就是進行feedforward pass,其實非常簡單,就是整個網絡正向跑一次就可以了
當然其中有dropout和sparsity的計算
具體的參見論文“Improving Neural Networks with Dropout“和Autoencoders and Sparsity
?
function nn = nnff(nn, x, y) //NNFF performs a feedforward pass // nn = nnff(nn, x, y) returns an neural network structure with updated // layer activations, error and loss (nn.a, nn.e and nn.L) n = nn.n; m = size(x, 1); x = [ones(m,1) x]; nn.a{1} = x; //feedforward pass for i = 2 : n-1 //根據選擇的激活函數不同進行正向傳播計算 //你可以回過頭去看nnsetup里面的第一個參數activation_function //sigm就是sigmoid函數,tanh_opt就是tanh的函數,這個toolbox好像有一點改變 //tanh_opt是1.7159*tanh(2/3.*A) switch nn.activation_function case 'sigm' // Calculate the unit's outputs (including the bias term) nn.a{i} = sigm(nn.a{i - 1} * nn.W{i - 1}'); case 'tanh_opt' nn.a{i} = tanh_opt(nn.a{i - 1} * nn.W{i - 1}'); end //dropout的計算部分部分 dropoutFraction 是nnsetup中可以設置的一個參數 if(nn.dropoutFraction > 0) if(nn.testing) nn.a{i} = nn.a{i}.*(1 - nn.dropoutFraction); else nn.dropOutMask{i} = (rand(size(nn.a{i}))>nn.dropoutFraction); nn.a{i} = nn.a{i}.*nn.dropOutMask{i}; end end //計算sparsity,nonSparsityPenalty 是對沒達到sparsitytarget的參數的懲罰系數 //calculate running exponential activations for use with sparsity if(nn.nonSparsityPenalty>0) nn.p{i} = 0.99 * nn.p{i} + 0.01 * mean(nn.a{i}, 1); end //Add the bias term nn.a{i} = [ones(m,1) nn.a{i}]; end switch nn.output case 'sigm' nn.a{n} = sigm(nn.a{n - 1} * nn.W{n - 1}'); case 'linear' nn.a{n} = nn.a{n - 1} * nn.W{n - 1}'; case 'softmax' nn.a{n} = nn.a{n - 1} * nn.W{n - 1}';//這里的n就是循環n-1里時那個具體的數,代表最后一層輸出層(不參與循環) nn.a{n} = exp(bsxfun(@minus, nn.a{n}, max(nn.a{n},[],2))); //max這種表達的意思比較并取每一行的最大值,結果為列向量。nn.a{n} = bsxfun(@rdivide, nn.a{n}, sum(nn.a{n}, 2)); // bsxfun代表高效運算,指兩個數組間元素逐個計算的二值操作,@rdivide 這里指左除;@minus是減法end //error and loss //計算error nn.e = y - nn.a{n}; //計算計算loss 函數 switch nn.output case {'sigm', 'linear'} nn.L = 1/2 * sum(sum(nn.e .^ 2)) / m; case 'softmax' nn.L = -sum(sum(y .* log(nn.a{n}))) / m; end endnnbp
代碼:\NN\nnbp.m
nnbp呢是進行back propagation的過程,過程還是比較中規中矩,和ufldl中的Neural Network講的基本一致
值得注意的還是dropout和sparsity的部分
if(nn.nonSparsityPenalty>0) pi = repmat(nn.p{i}, size(nn.a{i}, 1), 1); sparsityError = [zeros(size(nn.a{i},1),1) nn.nonSparsityPenalty * (-nn.sparsityTarget ./ pi + (1 - nn.sparsityTarget) ./ (1 - pi))]; end // Backpropagate first derivatives if i+1==n % in this case in d{n} there is not the bias term to be removed d{i} = (d{i + 1} * nn.W{i} + sparsityError) .* d_act; // Bishop (5.56) else // in this case in d{i} the bias term has to be removed d{i} = (d{i + 1}(:,2:end) * nn.W{i} + sparsityError) .* d_act; end if(nn.dropoutFraction>0) d{i} = d{i} .* [ones(size(d{i},1),1) nn.dropOutMask{i}]; end這只是實現的內容,代碼中的d{i}就是這一層的delta值,在ufldl中有講的
dW{i}基本就是計算的gradient了,只是后面還要加入一些東西,進行一些修改
具體原理參見論文“Improving Neural Networks with Dropout“ 以及?Autoencoders and Sparsity的內容
nnapplygrads
代碼文件:\NN\nnapplygrads.m
for i = 1 : (nn.n - 1) if(nn.weightPenaltyL2>0) dW = nn.dW{i} + nn.weightPenaltyL2 * nn.W{i}; else dW = nn.dW{i}; end dW = nn.learningRate * dW; if(nn.momentum>0) nn.vW{i} = nn.momentum*nn.vW{i} + dW; dW = nn.vW{i}; end nn.W{i} = nn.W{i} - dW; end
這個內容就簡單了,nn.weightPenaltyL2 是weight decay的部分,也是nnsetup時可以設置的一個參數
有的話就加入weight Penalty,防止過擬合,然后再根據momentum的大小調整一下,最后改變nn.W{i}即可
nntest
Ok再來看看nntest,如下:
function [ri, right] = nntest(nn, x, y)labels = nnpredict(nn, x);[~, expected] = max(y,[],2);right = find(labels == expected); ri = numel(right) / size(x, 1); end?調用一下nnpredict。函數需要的就是測試數據x和標簽y,如果有y的話那么可以計算準確率,如果沒有y的話那么你可以自己直接調用 labels = nnpredict(nn, x)可以得到預測的標簽。
nnpredict
代碼文件:\NN\nnpredict.m
[cpp]??view plain??copy
繼續非常簡單,predict不過是nnff一次,得到最后的output~~
max(nn.a{end},[],2); 是返回每一行的最大值以及所在的列數,所以labels返回的就是標號啦
(這個test好像是專門用來test 分類問題的,我們知道nnff得到最后的值即可)
總結
以上是生活随笔為你收集整理的一个简单的第三方CNN自编码matlab工具箱的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于FPGA的BP神经网络的verilo
- 下一篇: 基于FPGA的DES加解密系统开发(50