用matlab做深度學習,有什麼工具箱可以直接調用嗎?

好像caffe也支持matlab語言,不過好像不太好接入matlab。新手一枚,望多多指教


Matlab那個DeepLearnToolBox,其實入門很不錯的,而且特比好用,代碼寫的非常簡單明了。

DeepLearnToolbox是一個簡單理解CNN過程的工具箱,可以在github下載。

net中一些參數進行說明:

net.fv: 最後一層隱藏層的特徵矩陣,採用的是全連接方式

net.o: 最後輸出的結果,每一列為一個樣本結果

net.od: 最後一層輸出層所對應的殘差

net.fvd: 最後一層隱藏層所對應的誤差(全連接的方式)

test_example_CNN.m

[plain] view plain copy print?

  1. %function test_example_CNN
  2. addpath D:DeepLearningDeepLearnToolbox-masterdata
  3. addpath D:DeepLearningDeepLearnToolbox-masterCNN
  4. addpath D:DeepLearningDeepLearnToolbox-masterutil
  5. load mnist_uint8;
  6. train_x = double(reshape(train_x",28,28,60000))/255; % 訓練集變成60000張28*28的圖片大小 28*28*60000,像素點歸一化到[0,1]
  7. test_x = double(reshape(test_x",28,28,10000))/255; % 測試集 28*28*10000
  8. train_y = double(train_y"); %10*6000 每列代表一個標籤 softmax回歸模型
  9. test_y = double(test_y");
  10. %% ex1 Train a 6c-2s-12c-2s Convolutional neural network
  11. %will run 1 epoch in about 200 second and get around 11% error.
  12. %With 100 epochs you"ll get around 1.2% error
  13. rand("state",0)
  14. cnn.layers = { %%% 設置各層feature maps個數及卷積模板大小等屬性
  15. struct("type", "i") %input layer
  16. struct("type", "c", "outputmaps", 6, "kernelsize", 5) %convolution layer
  17. struct("type", "s", "scale", 2) %sub sampling layer
  18. struct("type", "c", "outputmaps", 12, "kernelsize", 5) %convolution layer
  19. struct("type", "s", "scale", 2) %subsampling layer
  20. };
  21. opts.alpha = 0.01; %迭代下降的速率
  22. opts.batchsize = 50; %每次選擇50個樣本進行更新 隨機梯度下降,每次只選用50個樣本進行更新
  23. opts.numepochs = 50; %迭代次數
  24. cnn = cnnsetup(cnn, train_x, train_y); %對各層參數進行初始化 包括權重和偏置
  25. cnn = cnntrain(cnn, train_x, train_y, opts); %訓練的過程,包括bp演算法及迭代過程
  26. [er, bad] = cnntest(cnn, test_x, test_y);
  27. %plot mean squared error
  28. figure; plot(cnn.rL);
  29. % assert(er&<0.12, "Too big error");

cnnsetup.m

[plain] view plain copy print?

  1. function net = cnnsetup(net, x, y)
  2. % 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]);
  3. inputmaps = 1; %輸入圖片數量 輸入feature maps數量
  4. mapsize = size(squeeze(x(:, :, 1))); % 圖片的大小 squeeze 要不要都行28 28
  5. for l = 1 : numel(net.layers) % layer
  6. if strcmp(net.layers{l}.type, "s")
  7. mapsize = mapsize / net.layers{l}.scale; %% sumsampling的featuremap長寬都是上一層卷積層featuremap的一半
  8. assert(all(floor(mapsize)==mapsize), ["Layer " num2str(l) " size must be integer. Actual: " num2str(mapsize)]);
  9. for j = 1 : inputmaps
  10. net.layers{l}.b{j} = 0; % 將偏置初始化0, 權重weight,,這段代碼subsampling層將weight設為1/4 而偏置參數設為0,故subsampling階段無需參數
  11. end
  12. end
  13. if strcmp(net.layers{l}.type, "c")
  14. mapsize = mapsize - net.layers{l}.kernelsize + 1; % 得到當前層feature map的大小
  15. fan_out = net.layers{l}.outputmaps * net.layers{l}.kernelsize ^ 2; % fan_out與fan_in都是用來初始化kernel的,不知道why
  16. for j = 1 : net.layers{l}.outputmaps % output map 當前層feature maps的個數
  17. fan_in = inputmaps * net.layers{l}.kernelsize ^ 2;
  18. for i = 1 : inputmaps % input map 共享權值,故kernel參數個數為inputmaps*outputmaps個數,每一個都是5*5
  19. net.layers{l}.k{i}{j} = (rand(net.layers{l}.kernelsize) - 0.5) * 2 * sqrt(6 / (fan_in + fan_out)); %% 初始化每個feature map對應的kernel參數 -0.5 再乘2歸一化到[-1,1],最終歸一化到[-sqrt(6 / (fan_in + fan_out)),+sqrt(6 / (fan_in + fan_out))] why??
  20. end
  21. net.layers{l}.b{j} = 0; % 初始話feture map對應的偏置參數 初始化為0
  22. end
  23. inputmaps = net.layers{l}.outputmaps; % 修改輸入feature maps的個數以便下次使用
  24. end
  25. end
  26. % "onum" is the number of labels, that"s why it is calculated using size(y, 1). If you have 20 labels so the output of the network will be 20 neurons.
  27. % "fvnum" is the number of output neurons at the last layer, the layer just before the output layer.
  28. % "ffb" is the biases of the output neurons.
  29. % "ffW" is the weights between the last layer and the output neurons. Note that the last layer is fully connected to the output layer, that"s why the size of the weights is (onum * fvnum)
  30. fvnum = prod(mapsize) * inputmaps; % S4最後結點個數即為特徵的個數 用作全連接 12*4*4=192維特徵
  31. onum = size(y, 1); %最終分類的個數 10類
  32. net.ffb = zeros(onum, 1); %softmat回歸的偏置參數個數
  33. net.ffW = (rand(onum, fvnum) - 0.5) * 2 * sqrt(6 / (onum + fvnum)); %% softmaxt回歸的權值參數 為10*192個 全連接
  34. end

cnntrain.m

[plain] view plain copy print?

  1. function net = cnntrain(net, x, y, opts)
  2. m = size(x, 3); %% 圖片一共的數量 60000
  3. numbatches = m / opts.batchsize; % 循環的次數 共1200次,每次使用50個樣本進行
  4. if rem(numbatches, 1) ~= 0
  5. error("numbatches not integer");
  6. end
  7. net.rL = [];
  8. for i = 1 : opts.numepochs
  9. disp(["epoch " num2str(i) "/" num2str(opts.numepochs)]);
  10. tic;
  11. kk = randperm(m); %% 隨機產生m以內的不重複的m個數
  12. for l = 1 : numbatches %% 循環1200次,每次選取50個樣本進行更新
  13. batch_x = x(:, :, kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize)); %50個樣本的訓練數據
  14. batch_y = y(:, kk((l - 1) * opts.batchsize + 1 : l * opts.batchsize)); %50個樣本所對應的標籤
  15. net = cnnff(net, batch_x); %計算前向傳播
  16. net = cnnbp(net, batch_y); %bp演算法更新參數
  17. opts.i = i;
  18. opts.l = l;
  19. net = cnnapplygrads(net, opts); %% 運用梯度迭代更新參數
  20. if isempty(net.rL)
  21. net.rL(1) = net.L;
  22. end
  23. net.rL(end + 1) = 0.99 * net.rL(end) + 0.01 * net.L; %為什麼要這樣計算不太明白 net.L為每次迭代時候的cost function
  24. end
  25. toc;
  26. end
  27. end

cnnff.m

[plain] view plain copy print?

  1. function net = cnnff(net, x)
  2. n = numel(net.layers); %% 所具有的層數
  3. net.layers{1}.a{1} = x; %第一層的激勵值初始化
  4. inputmaps = 1;
  5. for l = 2 : n % for each layer %針對每一個卷積層
  6. if strcmp(net.layers{l}.type, "c")
  7. % !!below can probably be handled by insane matrix operations
  8. for j = 1 : net.layers{l}.outputmaps % for each output map %針對該層的每一個feture map
  9. % create temp output map
  10. z = zeros(size(net.layers{l - 1}.a{1}) - [net.layers{l}.kernelsize - 1 net.layers{l}.kernelsize - 1 0]); % 該層feture map的大小,最後一位是樣本圖片個數 初始化為0
  11. for i = 1 : inputmaps % for each input map %針對每一個輸入feature map
  12. % convolve with corresponding kernel and add to temp output map
  13. z = z + convn(net.layers{l - 1}.a{i}, net.layers{l}.k{i}{j}, "valid"); %做卷積操作 k{i}{j} 是5*5的double類型,其中a{i}是輸入圖片的feature map 大小為28*28*50 50為圖像數量
  14. end %% 卷積操作這裡的k是不是應該旋轉180度
  15. % add bias, pass through nonlinearity
  16. net.layers{l}.a{j} = sigm(z + net.layers{l}.b{j}); %%獲取sigmoid function的值
  17. end
  18. % set number of input maps to this layers number of outputmaps
  19. inputmaps = net.layers{l}.outputmaps; %% 設置新的輸入feature maps的個數
  20. elseif strcmp(net.layers{l}.type, "s") %%% 下採樣採用的方法是,2*2相加乘以權值1/4, 沒有取偏置和取sigmoid
  21. % downsample
  22. for j = 1 : inputmaps
  23. z = convn(net.layers{l - 1}.a{j}, ones(net.layers{l}.scale) / (net.layers{l}.scale ^ 2), "valid"); % !! replace with variable %%先卷積後各行各列取結果
  24. net.layers{l}.a{j} = z(1 : net.layers{l}.scale : end, 1 : net.layers{l}.scale : end, :); %得到的結果是上一層卷積層行列的一半 a=z
  25. end
  26. end
  27. end
  28. % concatenate all end layer feature maps into vector
  29. net.fv = []; %%用來保存最後一個隱藏層所對應的特徵 將feature maps變成全連接的形式
  30. for j = 1 : numel(net.layers{n}.a) % 最後一層隱層具有的feture map數量
  31. sa = size(net.layers{n}.a{j});
  32. net.fv = [net.fv; reshape(net.layers{n}.a{j}, sa(1) * sa(2), sa(3))]; %% 最後得到192*50的矩陣,每一列對應一個樣本圖像的特徵,192=4*4*12 12個feturemap
  33. end
  34. % feedforward into output perceptrons
  35. net.o = sigm(net.ffW * net.fv + repmat(net.ffb, 1, size(net.fv, 2))); %% 結果為10*50的矩陣,每一列表示一個樣本圖像的標籤結果 取了sigmoid function表明是k個二分類器,各類之間不互斥,當然也可以換成softmax回歸
  36. % net.o = softmax(net.ffW * net.fv + repmat(net.ffb, 1, size(net.fv, 2)));
  37. end

cnnbp.m

[plain] view plain copy print?

  1. function net = cnnbp(net, y)
  2. n = numel(net.layers); %layers個數
  3. % error
  4. net.e = net.o - y; % 10*50 每一列表示一個樣本圖像
  5. % loss function
  6. net.L = 1/2* sum(net.e(:) .^ 2) / size(net.e, 2); %% cost function 沒有加入參數構成貝葉斯學派的觀點
  7. %% backprop deltas
  8. net.od = net.e .* (net.o .* (1 - net.o)); % output delta 輸出層的誤差 用來求解 10*50
  9. net.fvd = (net.ffW" * net.od); % feature vector delta 最後一層隱藏層誤差 如果是下採樣層,由於a=z,所以誤差就是這個結果(導數為1,就是對z求導),如果是卷積層,那麼需要乘以f(z)的導數 192*50
  10. if strcmp(net.layers{n}.type, "c") % only conv layers has sigm function
  11. net.fvd = net.fvd .* (net.fv .* (1 - net.fv)); %% 如果最後一個隱藏層是卷積層,直接用該公式就能得到誤差
  12. end
  13. % reshape feature vector deltas into output map style
  14. sa = size(net.layers{n}.a{1}); %%layers{n}共有12個a 每個a都是4*4*50 50 為樣本圖片的個數 n表示最後一層隱藏層
  15. fvnum = sa(1) * sa(2);
  16. for j = 1 : numel(net.layers{n}.a) %%最後一個隱藏層一共有多少個feature maps,每個feature map即表示為d{j}變成4*4*50的形式,50為樣本圖片數量,這樣好用於計算前面層次的誤差**** 轉變
  17. net.layers{n}.d{j} = reshape(net.fvd(((j - 1) * fvnum + 1) : j * fvnum, :), sa(1), sa(2), sa(3)); %將最後一層隱藏層變成feature maps的形式,這樣易求解前一層卷積的結果
  18. end
  19. for l = (n - 1) : -1 : 1 %實際是到2終止了,1是輸入層,沒有誤差要求
  20. if strcmp(net.layers{l}.type, "c") %卷積層的計算方式
  21. for j = 1 : numel(net.layers{l}.a) %第n-1層具有的feature maps的個數,進行遍歷 每個d{j}是8*8*50的形式, 由於下一層為下採樣層,故後一層d{j}擴展為8*8的(每個點複製成2*2的),按照bp求誤差公式就可以得出,這裡權重就為1/4,
  22. 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);
  23. end
  24. elseif strcmp(net.layers{l}.type, "s") %下採樣層的計算方式
  25. for i = 1 : numel(net.layers{l}.a) %該層feature maps的個數 每個a都是12*12*50 的大小,其中50為樣本圖片的個數
  26. z = zeros(size(net.layers{l}.a{1})); %大小等於 當前層feature map的大小
  27. for j = 1 : numel(net.layers{l + 1}.a) %計算公式來自 Notes on Convolutional Neural Networks的pdf,,將當前層下採樣層與後面的採樣層每個feature map相連接, 故按照bp的公式要進行求和
  28. z = z + convn(net.layers{l + 1}.d{j}, rot180(net.layers{l + 1}.k{i}{j}), "full"); %%% 可以舉一個簡單的例子進行講解 所有節點相乘都是相加的(因為該結點是與後一層所有的feature maps都是有連接的),
  29. end %% 卷積 full valid是什麼意思 要弄清楚????
  30. net.layers{l}.d{i} = z; %% 因為是下採樣層,所以a=z,就f(z)=z,導數就等於1,所以誤差就是所連接結點權值與後一層誤差和
  31. end
  32. end
  33. end
  34. %% calc gradients %% 對kij求偏導沒有看懂 為什麼要進行求和
  35. for l = 2 : n
  36. if strcmp(net.layers{l}.type, "c")
  37. for j = 1 : numel(net.layers{l}.a)
  38. for i = 1 : numel(net.layers{l - 1}.a)
  39. 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); % 可以看論文中的推導!與論文中先將k rot180,然後再rot整體效果是一樣的。
  40. end
  41. net.layers{l}.db{j} = sum(net.layers{l}.d{j}(:)) / size(net.layers{l}.d{j}, 3); %% 對偏置參數b的導數
  42. end
  43. end
  44. end
  45. net.dffW = net.od * (net.fv)" / size(net.od, 2); %softmax回歸中參數所對應的導數
  46. net.dffb = mean(net.od, 2); %% softmax回歸中最後參數b所對應的導數
  47. function X = rot180(X)
  48. X = flipdim(flipdim(X, 1), 2); % flipdim(X, 1) 行互換 flipdim(X, 2) 列互換
  49. end
  50. end

cnnapplygrads.m

[plain] view plain copy print?

  1. function net = cnnapplygrads(net, opts)
  2. for l = 2 : numel(net.layers)
  3. if strcmp(net.layers{l}.type, "c")
  4. for j = 1 : numel(net.layers{l}.a)
  5. for ii = 1 : numel(net.layers{l - 1}.a)
  6. net.layers{l}.k{ii}{j} = net.layers{l}.k{ii}{j} - 1/(opts.i+opts.alpha + opts.l) * net.layers{l}.dk{ii}{j}; %% 梯度下降求更新後的參數
  7. end
  8. net.layers{l}.b{j} = net.layers{l}.b{j} - 1/(opts.i+opts.alpha + opts.l) * net.layers{l}.db{j};
  9. end
  10. end
  11. end
  12. net.ffW = net.ffW - 1/(opts.i+opts.alpha + opts.l) * net.dffW;
  13. net.ffb = net.ffb - 1/(opts.i+opts.alpha + opts.l) * net.dffb;
  14. end

cnntest.m

[plain] view plain copy print?

  1. function [er, bad] = cnntest(net, x, y)
  2. % feedforward
  3. net = cnnff(net, x);
  4. [~, h] = max(net.o);
  5. [~, a] = max(y);
  6. bad = find(h ~= a);
  7. er = numel(bad) / size(y, 2);
  8. end


用MATLAB做深度學習推薦以下幾種途徑:

1、官方neutral network toolbox自帶的用於深度學習新功能函數,最近每個新版本都會大量更新深度學習方面的內容。支持普通卷積神經網路(ConvNets, CNNs),DAGNN (Directed acyclic graph neural network) 有向圖非循環神經網路、長短記憶網路long short-term memory (LSTM)等。支持預訓練好的網路模型,如GoogLeNet, AlexNet, VGG16, and VGG19,resnet50,另外支持從caffe model zoo直接導入網路的函數importCaffeNetwork、importCaffeLayers,importKerasLayers還有些訓練,提取,可視化特徵的函數trainNetwork、activations、classify、imageDatastore、deepDreamImage等等,遷移學習,特徵提取,訓練自己的網路,基本上你想要的都有。最主要最重要的是其有豐富完善的幫助文檔,很多不錯的實例demo,demo2。具體可以點擊這裡查看Neural Network Toolbox

2、編譯caffe的MATLAB介面matCaffe,用法參見caffe的Matlab介面的使用方法 - CSDN博客。這個用起來也非常方便的,caffe裡面調試網路推薦用這個。

3、樓主提到的matconvnet,是幾年前比較火的第三方工具箱,官網鏈接參看這裡Home - MatConvNet

4、推薦一本最新比較權威的書籍《MATLAB Deep Learning》 2017-Phil Kim博士著作,with machine learning,neural networks and Artificial intelligence,值得一看~http://download.csdn.net/download/cuixing001/10112280


一個是caffe有Matlab的介面,和caffe的c以及python介面調用方式基本一樣,但是如果要用到cuda的話,好像parallel computing toolbox要Matlab2015b以上的版本才有。

另一個是Matconvnet有提供常用的CNN模型和pretrianed參數,簡單的一些應用都可以用這個啦。


Deep Learning - MATLAB amp; Simulink - MathWorks 中國

這是官網對於NN TOOLBOX中DL的介紹


可以看下我們公司同事寫的lightnet


libsvm:LIBSVM -- A Library for Support Vector Machines


MatConvNet: CNNs for MATLAB MatConvNet


新手的話,不建議從matlab開始。

人生苦短,還是Python好一些。


推薦閱讀:

caffe finetune問題:按照網上的教程微調alexnet為什麼loss一直是87.3365?
caffe SolverParameter中的iter_size參數什麼作用?
GTX1080/1070配置深度學習環境。求指導,剛入手~?
如何評價Facebook Training ImageNet in 1 Hour這篇論文?
如何看待賈揚清Caffe2go開源,手機就能訓練神經網路?

TAG:MATLAB | 深度學習DeepLearning | Caffe深度學習框架 |