使用GPU在caffe上进行CNN训练

来源:互联网 发布:旅贸通软件 编辑:程序博客网 时间:2024/06/05 02:05

转自:http://blog.csdn.net/ws_20100/article/details/48860749

1.配置caffe环境

[请参考此篇博客:http://blog.csdn.net/ws_20100/article/details/48850449]

本篇介绍如何在caffe环境下,实现"图像对图像"的卷积神经网络的训练。



2.文件结构

在配置好的caffe文件夹中,进入examples目录,创建CNN文件夹,并进入文件夹

$ cd caffe-master/examples/

$ mkdir CNN

$ cd CNN/

CNN文件夹下面创建子文件夹

$ mkdir model snapshot TestPhotos TestLabels TrainPhotos TrainLabels

其中,

model用于以后存储卷积核矩阵和偏置向量;

snapshot用于存储训练中备份的caffe模型,每一段时间存储一次,防止断电等一些情况;

TrainPhotosTrainLabels分别存储训练集输入和监督样本;

TestPhotosTestLabels分别存储测试集输入和监督样本,不直接参与到训练中。

然后,将训练所用的输入样本和监督样本分别放入到TrainPhotos和TrainLabels中去。注意,样本文件名无所谓,但是排列次序必须一一对应。同样,将测试所用的输入样本和监督样本分别放入到TestPhotos和TestLabels中去。


3.产生训练和测试数据

1.)产生路径文件

CNN文件夹下面(以下均是在此文件夹下)创建两个路径文件。

$ vim train.txt

输入内容:

examples/CNN/train.h5

:wq保存文档。

$ vim test.txt

输入内容:

examples/CNN/test.h5

:wq保存文档。

2.)产生训练数据

$ vim generate_train.m

输入内容:(把输入图像切成11*11的像素块,监督图像为3*3的像素块(由网络结构和卷积核大小决定),步长为1个像素)

[plain] view plain copy
  1. clear;close all;  
  2.   
  3. %% settings  
  4. folder_input = 'TrainPhotos';  
  5. folder_label = 'TrainLabels';  
  6. savepath = 'train.h5';  
  7. size_input = 11;  
  8. size_label = 3; % size_input - 12  
  9. stride = 1;  
  10.   
  11. %% initialization  
  12. data = zeros(size_input, size_input, 1, 1);  
  13. label = zeros(size_label, size_label, 1, 1);  
  14. padding = abs(size_input - size_label) / 2;  
  15. count = 0;  
  16.   
  17. %% read data  
  18. filepaths_input = dir(fullfile(folder_input,'*.jpg'));  
  19. filepaths_label = dir(fullfile(folder_label,'*.jpg'));  
  20.   
  21. if (length(filepaths_input)==length(filepaths_label))  
  22.     length = length(filepaths_input);  
  23. else  
  24.     error('The Number of Input is NOT equal to the Number of Label.');  
  25. end  
  26.   
  27. %% generate data  
  28. for i = 1 : length  
  29.       
  30.     im_input = imread(fullfile(folder_input,filepaths_input(i).name));  
  31.     im_input = rgb2ycbcr(im_input);  
  32.     im_input = im2double(im_input(:, :, 1));  
  33.       
  34.     im_label = imread(fullfile(folder_label,filepaths_label(i).name));  
  35.     im_label = im2double(im_label(:, :, 1));  
  36.   
  37.     if size(im_input) == size(im_label)  
  38.         [hei,wid] = size(im_input);  
  39.     else  
  40.         error('The size of input and label are not equal.');  
  41.     end  
  42.       
  43.     for x = 1 : stride : hei-size_input+1  
  44.         for y = 1 :stride : wid-size_input+1  
  45.               
  46.             subim_input = im_input(x : x+size_input-1, y : y+size_input-1);  
  47.             subim_label = im_label(x+padding : x+padding+size_label-1, y+padding : y+padding+size_label-1);  
  48.   
  49.             count = count + 1;  
  50.             data(:, :, 1, count) = subim_input;  
  51.             label(:, :, 1, count) = subim_label;  
  52.         end  
  53.     end  
  54.       
  55. end  
  56.   
  57. %% randomized the data and label   
  58. order = randperm(count);  
  59. data = data(:, :, 1, order);  
  60. label = label(:, :, 1, order);   
  61.   
  62. %% writing to HDF5  
  63. chunksz = 128;  
  64. created_flag = false;  
  65. totalct = 0;  
  66.   
  67. for batchno = 1:floor(count/chunksz)  
  68.     last_read=(batchno-1)*chunksz;  
  69.     batchdata = data(:,:,1,last_read+1:last_read+chunksz);   
  70.     batchlabs = label(:,:,1,last_read+1:last_read+chunksz);  
  71.   
  72.     startloc = struct('dat',[1,1,1,totalct+1], 'lab', [1,1,1,totalct+1]);  
  73.     curr_dat_sz = store2hdf5(savepath, batchdata, batchlabs, ~created_flag, startloc, chunksz);   
  74.     created_flag = true;  
  75.     totalct = curr_dat_sz(end);  
  76. end  
  77. h5disp(savepath);  

终端下输入:

$ matlab -nodesktop -nosplash -logfile generate_train.log -r generate_train

产生训练数据train.h5

3.)产生测试数据

$ vim generate_test.m

generate_test.m只需要将generate_test.m文件开头改为:

[plain] view plain copy
  1. clear;close all;  
  2.   
  3. %% settings  
  4. folder_input = 'TestPhotos';  
  5. folder_label = 'TestLabels';  
  6. savepath = 'test.h5';  
  7. size_input = 11;  
  8. size_label = 3;  
  9. stride = 30;  

将最后一段改成:

[plain] view plain copy
  1. %% writing to HDF5  
  2. chunksz = 2;  
  3. created_flag = false;  
  4. totalct = 0;  
  5.   
  6. for batchno = 1:floor(count/chunksz)  
  7.     last_read=(batchno-1)*chunksz;  
  8.     batchdata = data(:,:,1,last_read+1:last_read+chunksz);   
  9.     batchlabs = label(:,:,1,last_read+1:last_read+chunksz);  
  10.   
  11.     startloc = struct('dat',[1,1,1,totalct+1], 'lab', [1,1,1,totalct+1]);  
  12.     curr_dat_sz = store2hdf5(savepath, batchdata, batchlabs, ~created_flag, startloc, chunksz);   
  13.     created_flag = true;  
  14.     totalct = curr_dat_sz(end);  
  15. end  
  16. h5disp(savepath);  

终端下输入:

$ matlab -nodesktop -nosplash -logfile generate_test.log -r generate_test

产生测试数据test.h5。仅仅用于判断训练到达什么地步。


4.建立训练文件

1.)建立solver文件

$ vim CNN_solver.prototxt

此为运行的配置文件,输入以下内容:

[plain] view plain copy
  1. # The train/test net protocol buffer definition  
  2. net: "examples/CNN/CNN_net.prototxt"  
  3. test_iter: 556  
  4. # Carry out testing every 500 training iterations.  
  5. test_interval: 500  
  6. # The base learning rate, momentum and the weight decay of the network.  
  7. base_lr: 0.0001  
  8. momentum: 0.9  
  9. weight_decay: 0  
  10. # The learning rate policy  
  11. lr_policy: "fixed"  
  12. # Display every 100 iterations  
  13. display: 100  
  14. # The maximum number of iterations  
  15. max_iter: 15000000  
  16. # snapshot intermediate results  
  17. snapshot: 500  
  18. snapshot_prefix: "examples/CNN/snapshot/CNN"  
  19. # solver mode: CPU or GPU  
  20. solver_mode: GPU  

:wq保存退出。

2.)建立net文件

$ vim CNN_net.prototxt

此为网络结构配置文件,可以配置网络层数,节点数,卷积核等参数。输入以下内容:

[plain] view plain copy
  1. name: "CNN"  
  2. layer {  
  3.   name: "data"  
  4.   type: "HDF5Data"  
  5.   top: "data"  
  6.   top: "label"  
  7.   hdf5_data_param {  
  8.     source: "examples/CNN/train.txt"  
  9.     batch_size: 128  
  10.   }  
  11.   include: { phase: TRAIN }  
  12. }  
  13. layer {  
  14.   name: "data"  
  15.   type: "HDF5Data"  
  16.   top: "data"  
  17.   top: "label"  
  18.   hdf5_data_param {  
  19.     source: "examples/CNN/test.txt"  
  20.     batch_size: 2  
  21.   }  
  22.   include: { phase: TEST }  
  23. }  
  24.   
  25. layer {  
  26.   name: "conv1"  
  27.   type: "Convolution"  
  28.   bottom: "data"  
  29.   top: "conv1"  
  30.   param {  
  31.     lr_mult: 1  
  32.   }  
  33.   param {  
  34.     lr_mult: 0.1  
  35.   }  
  36.   convolution_param {  
  37.     num_output: 128  
  38.     kernel_size: 5  
  39.     stride: 1  
  40.     pad: 0  
  41.     weight_filler {  
  42.       type: "gaussian"  
  43.       std: 0.001  
  44.     }  
  45.     bias_filler {  
  46.       type: "constant"  
  47.       value: 0  
  48.     }  
  49.   }  
  50. }  
  51.   
  52. layer {  
  53.   name: "relu1"  
  54.   type: "ReLU"  
  55.   bottom: "conv1"  
  56.   top: "conv1"  
  57. }  
  58.   
  59. layer {  
  60.   name: "conv2"  
  61.   type: "Convolution"  
  62.   bottom: "conv1"  
  63.   top: "conv2"  
  64.   param {  
  65.     lr_mult: 1  
  66.   }  
  67.   param {  
  68.     lr_mult: 0.1  
  69.   }  
  70.   convolution_param {  
  71.     num_output: 64  
  72.     kernel_size: 3  
  73.     stride: 1  
  74.     pad: 0  
  75.     weight_filler {  
  76.       type: "gaussian"  
  77.       std: 0.001  
  78.     }  
  79.     bias_filler {  
  80.       type: "constant"  
  81.       value: 0  
  82.     }  
  83.   }  
  84. }  
  85.   
  86. layer {  
  87.   name: "relu2"  
  88.   type: "ReLU"  
  89.   bottom: "conv2"  
  90.   top: "conv2"  
  91. }  
  92.   
  93. layer {  
  94.   name: "conv3"  
  95.   type: "Convolution"  
  96.   bottom: "conv2"  
  97.   top: "conv3"  
  98.   param {  
  99.     lr_mult: 0.1  
  100.   }  
  101.   param {  
  102.     lr_mult: 0.1  
  103.   }  
  104.   convolution_param {  
  105.     num_output: 1  
  106.     kernel_size: 3  
  107.     stride: 1  
  108.     pad: 0  
  109.     weight_filler {  
  110.       type: "gaussian"  
  111.       std: 0.001  
  112.     }  
  113.     bias_filler {  
  114.       type: "constant"  
  115.       value: 0  
  116.     }  
  117.   }  
  118. }  
  119.   
  120. layer {  
  121.   name: "loss"  
  122.   type: "EuclideanLoss"  
  123.   bottom: "conv3"  
  124.   bottom: "label"  
  125.   top: "loss"  
  126. }  

:wq保存退出。


5.CNN训练

$ vim train.sh

输入以下shell:

#!/bin/bash
cd ../../
./build/tools/caffe train --solver examples/CNN/CNN_solver.prototxt 2>&1 | tee examples/CNN/CNN.log

增加运行权限:

$ chmod +x train.sh

运行脚本文件:

$ ./train.sh

时间可能会运行几天,也可以提前退出(Ctrl+C),因为在snapshot中有中间备份存储。



6.保存滤波器

1.)创建mat文件

$ cp CNN_net.prototxt CNN_mat.prototxt

CNN_mat.prototxt文件开头两个layer段改为:

[plain] view plain copy
  1. name: "CNN"  
  2. input: "data"  
  3. input_dim: 1  
  4. input_dim: 1  
  5. input_dim: 11  
  6. input_dim: 11  
  7.   
  8. input: "label"  
  9. input_dim: 1  
  10. input_dim: 1  
  11. input_dim: 3  
  12. input_dim: 3  

:wq保存即可。

2.)创建M文件

$ vim saveFilters.m

输入以下内容:(第7行可以更改需要转换的caffemodel文件名)

[plain] view plain copy
  1. caffe.reset_all();  
  2. clear; close all;  
  3. %% settings  
  4. %folder = 'examples/CNN/';  
  5. folder = './';  
  6. model = [folder 'CNN_mat.prototxt'];  
  7. weights = [folder 'snapshot/CNN_iter_550000.caffemodel'];  
  8. savepath = [folder 'model/x.mat'];  
  9. layers = 3;  
  10.   
  11. %% load model using mat_caffe  
  12. net = caffe.Net(model,weights,'test');  
  13.   
  14. %% reshap parameters  
  15. weights_conv = cell(layers,1);  
  16.   
  17. for idx = 1 : layers  
  18.     conv_filters = net.layers(['conv' num2str(idx)]).params(1).get_data();  
  19.     [~,fsize,channel,fnum] = size(conv_filters);  
  20.   
  21.     if channel == 1  
  22.         weights = double(ones(fsize^2, fnum));  
  23.     else  
  24.         weights = double(ones(channel, fsize^2, fnum));  
  25.     end  
  26.       
  27.     for i = 1 : channel  
  28.         for j = 1 : fnum  
  29.              temp = conv_filters(:,:,i,j);  
  30.              if channel == 1  
  31.                 weights(:,j) = temp(:);  
  32.              else  
  33.                 weights(i,:,j) = temp(:);  
  34.              end  
  35.         end  
  36.     end  
  37.   
  38.     weights_conv{idx} = weights;  
  39. end  
  40.   
  41. %% save parameters  
  42. weights_conv1 = weights_conv{1};  
  43. weights_conv2 = weights_conv{2};  
  44. weights_conv3 = weights_conv{3};  
  45. biases_conv1 = double(net.layers('conv1').params(2).get_data());  
  46. biases_conv2 = double(net.layers('conv2').params(2).get_data());  
  47. biases_conv3 = double(net.layers('conv3').params(2).get_data());  
  48.   
  49. save(savepath,'weights_conv1','biases_conv1','weights_conv2','biases_conv2','weights_conv3','biases_conv3');  

:wq保存。

3.)运行M文件

$ matlab -nodesktop -nosplash -logfile saveFilters.log -r saveFilters

此时,在model中会生成x.mat文件。


7.CNN重构

已经知道了x.mat文件中,有三层卷积层的卷积核矩阵weights_conv*和偏置向量biases_conv*。

编写一个demo_net.m文件,使用这些参数构建卷积网络结构,对输入图像(矩阵)进行处理,即可得到结果。

不同应用有不同的源码,这里省略该文件源码。

1 0
原创粉丝点击