最近看了论文CDBN 的论文和代码,现将对代码的理解稍作整理。
有关论文的一些网址:
[1] CRBM http://qipeng.me/software/convolutional-rbm.html
[2] CRBM 论文笔记 http://www.cnblogs.com/lijingcong/p/4113143.html
[3] CDBN paper http://ai.stanford.edu/~ang/papers/icml09-ConvolutionalDeepBeliefNetworks.pdf
[4] CDBN matlab 代码 http://www.adv-ci.com/blog/source/cdbn/
本代码支持both binary and Gaussian visible types
在介绍网站上,只在Ubuntu 10.04(64-bit)上测试过,所用的编译器是GNU C/C++ ,Matlab,CUDA 5.0 or above。
本实验机33 CentOS6.5、CUDA 6.5
(1)打开terminal 将路径定位到 CDBN/toolbox/CDBNLIB/mex
(2)打开 Makefile 文件,修改 MATLAB_DIR= &CUDA_DIR
MATLAB_DIR = /usr/local/MATLAB/R2011a
CUDA_DIR = /usr/local/cuda-6.5
(3)Make
经查该错误,发现是由于make里面的target已经存在,所以make什么都没做,只需将mex文件夹中的.mexa64 和.o文件都删除,然后再make就OK了。
(1)运行 ‘setup_toolbox.m’
(2)运行‘DemoCDBN_Binary_2D.m’
如果前面make不成功,提示nothing to be done for ‘target’,后面用mex,cuda计算,都会提示错误
(1)数据
在CDBN代码里面有两种数据mnistSmall.mat 和9幅 MITcoast图像
(2)作者如何使用
作者在做实验的时候对binary data和Gaussian data做了不同的处理,认为mnistSmall data是binary data,MITcoast data是Gaussian data。Gaussian data会经过一步whiten。
观察发现,mnist里面的数据90%以上的点的value是接近0或者是1的(计算出0.1到0.9的数据占8.65%),符合binary data的分布特点
对于MITcoast image,取像素值后/255后各区间所占比例如下表(%)
MITcoast whiten前和whiten后的分布
左侧是原始数据/255后的分布图,右侧是whiten之后的。256*256的image横轴是x 256,纵轴是value。由图可以看出,MITcoast image的数据本身分布在各个区间,而经过whiten后数据符合Gaussian分布,集中在0的左右两侧。可以理解为whiten是为了使得数据符合Gaussian Distribution。
(3)用Binary data 和 Gaussian data做了什么实验
对于Binary data,包括训练model+softmax分类,测试集进行预测
对于Gaussian data,由于原始的是coast图,且只有9幅,所以仅仅是对其进行训练,并没有进行分类。
从代码来看作者将卷积层和池化层关联在一起,共同作为一个layer。在训练某一layer的时候,首先需要对input data 做一下预处理。第一项就是对于pooling层不能整除的问题,代码上来看会是去除掉多余的行数,具体的做法如下code
function [layer] = preprocess_train_data2D(layer) %% % Here you should preprocess your code for pooling layer mod_1 = mod((size(layer.inputdata,1)-layer.s_filter(1))/layer.stride(1)+1,layer.s_pool(1)); if mod_1~=0 layer.inputdata(1:floor(mod_1/2),:,:,:) =[]; layer.inputdata(end-ceil(mod_1/2)+1:end,:,:,:) =[]; end mod_2 = mod((size(layer.inputdata,2)-layer.s_filter(2))/layer.stride(2)+1,layer.s_pool(2)); if mod_2~=0 layer.inputdata(:,1:floor(mod_2/2),:,:) =[]; layer.inputdata(:,end-ceil(mod_2/2)+1:end,:,:) =[]; end if layer.whiten if strcmp(layer.type_input, 'Gaussian') m = size(layer.inputdata,4); n = size(layer.inputdata,3); for i = 1 : m for j =1 : n layer.inputdata(:,:,j,i) = crbm_whiten(layer.inputdata(:,:,j,i)); end end end end
可以选择不同的计算方法 matlab matrix computation、MEX、CUDA,可以在'CDBN/toolbox/CDBNLIB/default_layer2D.m'中修改计算方法
layer.matlab_use = 0; layer.mex_use = 1; layer.cuda_use = 0;
也可以在层次的定义的时候修改计算方法:如在'DemoCDBN_Binary_2D.m' 第一层的定义的之前加入一行
layer{1}.matlab_use = 0; layer{1}.mex_use = 0; layer{1}.cuda_use = 1;
(1)matlab matrix 计算
卷积计算是用一个卷积核对前一层的所有的map进行卷积,然后将结果相加,得到新的feature map。再用第二个卷积核进行卷积求和。
① 前向
卷积求和后的结果为h_input,(block的大小与h_input一样。S_pool = 【2 2】,即block的 s_pool区域内的值为该区域h_input值的的和)
Binary:h_sample = exp(model.h_input)./(1+block);
Gaussian:h_sample = exp(1.0/(model.start_gau^2).*model.h_input)./(1+block);
② 反向
H_state = 二值化(h_sample)
V_input = 卷积 h_state 求和
Binary:V_sample = sigmoid(v_input)
Gaussian:v_sample = v_input
(2)Mex 计算
几个MEX调用C的函数库
mxCreateCellArray 创建n维元胞mxArray mxCreateCellMatrix 创建二维元胞mxArray mxCreateCharArray 创建n维字符串mxArray mxCreateCharMatrixFromStrings 创建二维字符串mxArray mxCreateDoubleMatrix 创建二维双精度浮点mxArray mxCreateDoubleScalar 创建指定值的二维精度浮点mxArray mxCreateLogicalArray 创建n维逻辑mxArray,初值为false mxCreateLogicalMatrix 创建二维逻辑mxArray,初值为false mxCreateLogicalScalar 创建指定值的二维逻辑mxArray mxCreateNumericArray 创建n维数值mxArray mxCreateNumericMatrix 创建二维数值mxArray,初值为0 mxCreateScalarDouble 创建指定值的双精度mxArray MxCreateSparse 创建二维稀疏mxArray mxCreateSparseLogicalMatrix 创建二维稀疏逻辑mxArray MxCreateString 创建指定字符串的1 n的串mxArray mxCreateStructArray 创建n维架构mxArray mxCreateStructMatrix 创建二维架构mxArray
(3)CUDA计算
mex计算和cuda计算,具体的计算方法是和matlab matrix的计算方法是一样的,只是用的不同的语言实现。
对于Binary data,用mex计算的结果会比cuda计算的结果好。
Mex:accuracy 94.45% 且sparsity value不为0,finetune迭代 100
Cuda:accuracy 10.45% 且 sparsity 为0,finetune迭代5