Matconvnet 的安裝以及使用

matconvnet是matlab上進行CNN的框架。本文介紹windows下如何安裝以及使用它對pre-trained的網絡進行finetuning. 這裏以win10爲例,cuda版本爲7.5,cudnn的版本爲v3.fine tune的網絡VGG-19.
一.matconvnet 安裝
1.Precondition: 如果是編譯cpu版本的,只需要matlab安裝了mex就可以(c與matlab的混編 ,在matlab的commander裏輸入mex -setup C++搞定)。
如果是編譯GPU的話,首先是需要GPU(其實所有獨立顯卡都可以),然後安裝好cuda用於cu文件的編譯;如果想使用nvidia正對CNN的加速需要下載cudnn。
2.安裝
下載完自己需要的matconvnet版本之後就可以在matlab編譯安裝了。這裏只介紹GPU的安裝。
2.1編譯:
以matconvnet的目錄作爲當前目錄,添加matlab路徑到查找目錄,然後將cudnn文件夾複製到當前目錄,整個目錄結構如下:
這裏寫圖片描述
其中finetune目錄是我後面finetune用到的,這裏主要注意把cudnn(圖中是cuda)複製到當前目錄。
然後既可以按照官網的命令進行編譯:
gpuDevice()可以查看你的顯卡信息,同時可以看cuda toolkit的版本。

vl_compilenn('enableGpu',true,'cudaMethod','nvcc','cudaRoot','C:\ProgramFiles\NVIDIA GPU Computing Toolkit\CUDA\v7.5','enableCudnn',true,'cudnnRoot','cuda')

這裏需要把cudaRoot後面的路徑換做你自己安裝的cuda 路徑,cudnnRoot後的路徑換爲你cudnn的路徑。同時不用cudnn的話將後面兩項去掉即可。如果在編譯cudnn版本的時候提示找不到cudnn.h文件,那多數是路徑不對,此時一個有效的辦法是將cudnn裏面的子目錄的文件copy到cuda安裝路徑(上條命令中的cudaRoot參數)下的對應目錄下。
下面就可以進行測試了:
vl_testnn(‘gpu’,true)
這裏有個問題就是編譯的時候可能會出其他錯誤,如果是說某個函數的參數不對(too few arguments)這種錯誤,很有可能是版本問題引起的,建議更換了cudnn版本後重新編譯。或者先不用cudnn看是否編譯成功。
還遇到一個問題,類似與error using mex cc: unsupported gpu architecture ‘compute_52’,這是因爲這個值只能取10倍數,在vl_compilenn裏面的cudaArch函數裏面將arch_code固定爲你自己的GPU的計算能力即可(取最接近的10的倍數,要用字符格式),如下:

function cudaArch = get_cuda_arch(opts)
% --------------------------------------------------------------------
opts.verbose && fprintf('%s:\tCUDA: determining GPU compute capability (use the ''CudaArch'' option to override)\n', mfilename);
try
  gpu_device = gpuDevice();
  arch_code = strrep(gpu_device.ComputeCapability, '.', '');
  arch_code = '50'%自己添加的
  cudaArch = ...
      sprintf('-gencode=arch=compute_%s,code=\\\"sm_%s,compute_%s\\\" ', ...
              arch_code, arch_code, arch_code) ;
catch
  opts.verbose && fprintf(['%s:\tCUDA: cannot determine the capabilities of the installed GPU;' ...
                      'falling back to default\n'], mfilename);
  cudaArch = opts.defCudaArch;
end

二 fine tune CNN
如果上面的步驟訓練,下面就可以用matconvnet工具包了。examples目錄下面有許多很好的例子,牆裂推薦。這裏以對VGG-19網絡fine tune爲例,也就是使用pre-trianed網絡,然後用自己的數據進行fine tune,得到針對自己數據集的網絡。主要步驟分爲:參數設定;準備數據;準備網絡;訓練網絡;部署網絡;

run(fullfile(fileparts(mfilename('fullpath')), ...
  '..', 'matlab', 'vl_setupnn.m')) ;
%------------------------------
%parameter setting
%------------------------------
%數據
opts.dataDir = 'YourDataPath' ;
opts.expDir  = 'YourOutputPath';
% 導入預訓練的model
opts.modelPath = fullfile('YourModelPath','imagenet-vgg-verydeep-19.mat');
opts.train = struct() ;
opts.train.gpus = [1];%使用GPU
opts.train.batchSize = 40;%每個batch的樣本數
opts.train.numSubBatches = 4 ;%每個batch分成多少個subbatch
opts.contrastNormalization = true;
opts.lite = false ;
if ~isfield(opts.train, 'gpus'), opts.train.gpus = []; end;
opts = vl_argparse(opts, varargin) ;
acc_list = [];
%opts.numFetchThreads = 12 ;
modelPath = ['PATHTOSAVEMODEL'.mat'];%保存model的路徑
imdbname = ['imdb.mat'];
opts.imdbPath = fullfile(opts.expDir, imdbname);%讀取imdb數據的路徑
%-------------------------
%prepare data
%-------------------------
if exist(opts.imdbPath,'file')
    imdb = load(opts.imdbPath) ;
else
    imdb = getEggImdb(opts) ;
end
%------------------------------
%prepare model
%------------------------------
%load net
net = load(opts.modelPath);
%adjust net
net.layers  = net.layers(1:end-2);%去掉原來的softmax層以及fc8層
%set learning rate
lr = [0.005 0.002];%每層的網絡學習率
for i = 1:size(net.layers,2)
    if(strcmp(net.layers{i}.type,'conv'))
        net.layers{i}.learningRate = lr;
    end
end
net.layers{end+1} = struct('name','fc8_egg','type', 'conv', ...
'weights', {{0.05*randn(1,1,4096,YOURCLASSNUM, 'single'), zeros(1,YOURCLASSNUM,'single')}}, ...
    'learningRate',[0.005 0.002], ...
    'stride', [1 1], ...
    'pad', [0 0 0 0], ...
    'opts',{cell(0,0)}) ;%添加新的fc8層,'weights'後面的YOURCLASSNUM爲你分類的類別數
    net.layers{end+1} = struct('type','softmaxloss','opts',{cell(0,0)});%重新添加softmaxloss層用於訓練
%-----------------------------------------------------------   
%                                    Learn
% ---------------------------------------------------------- 
opts.train.train = find(imdb.images.set==1) ;%訓練集
opts.train.val = find(imdb.images.set==3) ;%測試集
[net, info] = cnn_train(net, imdb,opts.iband, @getBatch, ...
                          'expDir', opts.expDir, ...
                          opts.train);
%------------------------------------------
%                               deploy
%------------------------------------------
net = cnn_deploy(net);
save(modelPath, '-struct', 'net') ; 
acc_list(end+1) = test_val_data(modelPath,iband);

% --------------------------------------------------------------------
function [im, labels] = getBatch(imdb, batch)
% --------------------------------------------------------------------
im = imdb.images.data(:,:,:,batch) ;
labels = imdb.images.labels(1,batch) ;
if rand > 0.5, im=fliplr(im) ; end         

需要注意的是每層的learning rate也是我們可以根據效果調的地方,裏面的有幾個函數需要自己修改:getEggImdb是根據自己的數據集建立imdb的函數;cnn_deploy是對網絡進行部署的函數,也很重要,因爲fine tune後的網絡不能直接用於測試。這幾個文件應該在matconvnet裏面都給出來了,可以照着更改,我也把自己的放到github上了。
很多細節沒來得及深究,多多指點。

Reference:
[1]http://www.vlfeat.org/matconvnet/
[2]http://blog.csdn.net/on2way/article/details/52959344
[3]http://blog.csdn.net/anysky___/article/details/51356158

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章