机器学习和生物信息学实验室联盟
标题:
【新生指南】Matlab StackAutoEncoder和Deep Belief Networks的使用调参和批处理
[打印本页]
作者:
xingpengwei
时间:
2017-6-24 13:56
标题:
【新生指南】Matlab StackAutoEncoder和Deep Belief Networks的使用调参和批处理
本帖最后由 xingpengwei 于 2017-6-24 13:54 编辑
本帖只针对新生尽快熟悉工作做参考,我会写得啰嗦些,大神绕道{:243:} 。
生物信息主要处理一维字符序列,如果想转化成矩阵处理,可使用onehot编码,快速理解就是01编码每个字符类别,如果序列只有AUGC四种字符,那么每个字符用0001,0010,0100,1000编码代替。这样序列就变成了Nx4的矩阵。
StackAutoEncoder,即Stack自动编码机,一种最简单的无监督学习深度网络,首先我们来理解一下无监督学习:
(引自
http://blog.csdn.net/zouxy09/article/details/8775524
)
如图,输入的样本是有标签的,即(input, target),我们根据当前输出和target(label)之间的差去改变前面各层的参数,直到收敛。
那么无标签怎么得到误差呢?
如上图,我们将input输入一个encoder编码器,就会得到一个code,这个code也就是输入的一个表示,那么我们怎么知道这个code表示的就是input呢?我们加一个decoder解码器,这时候decoder就会输出一个信息,那么如果输出的这个信息和一开始的输入信号input是很像的(理想情况下就是一样的),那很明显,我们就有理由相信这个code是靠谱的。所以,我们就通过调整encoder和decoder的参数,使得重构误差最小,这时候我们就得到了输入input信号的第一个表示了,也就是编码code了。因为是无标签数据,所以误差的来源就是直接重构后与原输入相比得到。
Stack自动编码机的话,就是堆叠上述层,上一层的输入作为下一层的输入。
看到这里,我们知道了StackAutoEncoder就是(encoder->decoder)-(encoder->decoder)-(encoder->decoder)...
当然还有一些变形和其他知识,这里主要讲应用,有不看原理心忐忑的伙伴有时间后可以参考以下教程。
斯坦福的
UFLDL教程
算是根正苗红的深度学习基础教程,或者是
Andrew Ng的视频
那么,我们来上代码:
matlab自带有StackAutoEncoder的例子,首先我们来实现onehot编码:
[tits, seqs]=fastaread('p1_n1_H.txt');
num=length(tits);
len=length(char(seqs(1)));
Y=zeros(2,num);
X=cell(1,num);
%onehot
for i=1:num
str=char(tits(i));
temp=strsplit(str,'|');
label=char(temp(2));
if label=='1'
Y(:,i)=[1,0];
else
Y(:,i)=[0,1];
end
img=zeros(len,4);
for j=1:len
seq=char(seqs(1,i));
switch seq(j)
case 'A'
img(j,:)=[0,0,0,1];
case 'C'
img(j,:)=[0,0,1,0];
case 'G'
img(j,:)=[0,1,0,0];
case 'U'
img(j,:)=[1,0,0,0];
case 'T'
img(j,:)=[1,0,0,0];
end
end
X{i}=img;
复制代码
以上代码基本就是01编码代替序列字符。
主体StackAutoEncoder代码参考
https://cn.mathworks.com/help/nn ... classification.html
你只需要替换相关输入,改图片长宽等。
我们主要讲Deep Belief Networks深度信念网络:
深度信念网络也是stack层,只是stack的是RBM,Restricted Boltzmann Machine (RBM)限制波尔兹曼机。
理论参考
http://blog.csdn.net/zouxy09/article/details/8781396
讲得挺好。
这里我们使用matlab第三方的工具包:
DeeBNet (Deep Belief Networks) toolbox in MATLAB and Octave
:
工具包里边有很多例子脚本,我们主要使用test_getFeatureMNIST.m其他也行:
首先我们要做的依然是把我们的数据结构化成这个脚本接受的形式:
[tits, seqs]=fastaread('+SCM6A/p1_n1_H.txt');
num=length(tits);
len=length(char(seqs(1)));
Y=zeros(num,1);
X=zeros(num,len*4);
%onehot
for i=1:num
str=char(tits(i));
temp=strsplit(str,'|');
label=char(temp(2));
if label=='1'
Y(i)=1;
else
Y(i)=2;
end
img=zeros(len,4);
for j=1:len
seq=char(seqs(1,i));
switch seq(j)
case 'A'
img(j,:)=[0,0,0,1];
case 'C'
img(j,:)=[0,0,1,0];
case 'G'
img(j,:)=[0,1,0,0];
case 'U'
img(j,:)=[1,0,0,0];
case 'T'
img(j,:)=[1,0,0,0];
end
end
X(i,:)=img(:);
end
inputs = X;
targets = Y;
%custom your split_point by multiplier
split_point=round(size(inputs,1)*0.7);
ranindex=randperm(size(inputs,1));
data=inputs(ranindex(1:split_point),:);
labels=targets(ranindex(1:split_point),:);
testdata=inputs(ranindex(split_point+1:end),:);
testlabels=targets(ranindex(split_point+1:end),:);
save('SCM6A.mat','data','labels','testdata','testlabels');
复制代码
后边的代码是生成一个随机种子然后分割训练测试集。
下边是主体脚本:
如果不包装网格调参的设定的话,代码是这样的:
dbn=DBN();
dbn.dbnType='autoEncoder';
% RBM1
rbmParams=RbmParameters(1000,ValueType.binary);
rbmParams.maxEpoch=50;
rbmParams.samplingMethodType=SamplingClasses.SamplingMethodType.CD;
rbmParams.performanceMethod='reconstruction';
dbn.addRBM(rbmParams);
% RBM2
rbmParams=RbmParameters(500,ValueType.binary);
rbmParams.maxEpoch=50;
rbmParams.samplingMethodType=SamplingClasses.SamplingMethodType.CD;
rbmParams.performanceMethod='reconstruction';
dbn.addRBM(rbmParams);
% RBM3
rbmParams=RbmParameters(250,ValueType.binary);
rbmParams.maxEpoch=50;
rbmParams.samplingMethodType=SamplingClasses.SamplingMethodType.CD;
rbmParams.performanceMethod='reconstruction';
dbn.addRBM(rbmParams);
RBM4
rbmParams=RbmParameters(200,ValueType.gaussian);
rbmParams.maxEpoch=50;
rbmParams.samplingMethodType=SamplingClasses.SamplingMethodType.CD;
rbmParams.performanceMethod='reconstruction';
dbn.addRBM(rbmParams);
dbn.train(data);
dbn.backpropagation(data,'yes');
复制代码
Stack了四层RBM,每一层设置了一些参数,设置好后addRBM,然后训练,然后fine turn。
为了能网格调参,我们需要把这部分的参数设置成变量的形式,然后包裹在几层for循环中(简单粗暴法),我们先设定一堆参数,如需修改参数范围,修改这部分就可以
RbmNode1=[250,100];
RbmNode2=[500,250,100];
RbmNode3=[1000,500,250,100];
GridSearch_nodes={RbmNode1,RbmNode2,RbmNode3};
GridSearch_maxEpoch=[200];
GridSearch_learningRate=[0.1,0.01,0.001];
GridSearch_BPorNot=[1,0];
复制代码
然后把单层包裹着for循环中:
fid = fopen('out.txt','w');
for k=1:length(GridSearch_maxEpoch);
for l=1:4%GridSearch_SamplingMethodType
for m=1:length(GridSearch_learningRate)
for n=1:length(GridSearch_BPorNot)
for i=1:length(GridSearch_nodes)
for times=1:3
dbn=DBN();
dbn.dbnType='autoEncoder';
for j=1:length( GridSearch_nodes{i})
rbmParams=RbmParameters(GridSearch_nodes{i}(j),ValueType.binary);
rbmParams.maxEpoch=GridSearch_maxEpoch(k);
rbmParams.samplingMethodType=l;
rbmParams.performanceMethod='reconstruction';
rbmParams.learningRate=GridSearch_learningRate(m);
dbn.addRBM(rbmParams);
end
dbn.train(data);
if GridSearch_BPorNot(n)==1
dbn.backpropagation(data,'yes');
end
load('SCM6A_nosh.mat');
feat=dbn.getFeature(inputs);
label=targets-1;
label(label==1)=-1;
label(label==0)=1;
confu=svmtrain(label,feat,'-v 10');
confu=double(confu);
TP=confu(1);
FN=confu(2);
FP=confu(3);
TN=confu(4);
Sn=TP/(TP+FN);
Sp=TN/(TN+FP);
Acc=(TP+TN)/(TP+FN+FP+TN);
MCC=(TP*TN-FN*FP)/sqrt((TP+FP)*(TN+FN)*(TP+FN)*(TN+FP));
fprintf(fid, '%s %s %s %s %s %s %s %s %s %s %s %s %s %s\n','times','GridSearch_nodes','maxEpoch','SamplingMethodType','learningRate','BPorNot','Sn','Sp','Acc','MCC','TP','FN','FP','TN');
fprintf(fid, '%d %s %d %d %d %d %.4f %.4f %.4f %.4f %d %d %d %d\n',times,mat2str(GridSearch_nodes{i}(:)),GridSearch_maxEpoch(k),l,GridSearch_learningRate(m),GridSearch_BPorNot(n),Sn,Sp,Acc,MCC,TP,FN,FP,TN);
feat_label=[feat,targets-1];
csvwrite('feat_temp.csv',feat_label);
S = fileread('feat_temp.csv');
feat_dim=100;
attribute='';
for index=1:feat_dim
attribute=[attribute,'@attribute Fea',int2str(index),' numeric',char(10)];
end
header=['@relation m6a_dbn',char(10),attribute,'@attribute class {0,1}',char(10),'@data',char(10)];
S = [header, S];
name=sprintf('%s-%d-%d-%d-%d-%.4f-%.4f-%.4f-%.4f-%d-%d-%d-%d-%d',mat2str(GridSearch_nodes{i}(:)),GridSearch_maxEpoch(k),l,GridSearch_learningRate(m),GridSearch_BPorNot(n),Sn,Sp,Acc,MCC,TP,FN,FP,TN,times);
FID = fopen([name,'.arff'], 'w');
if FID == -1, error('Cannot open file'); end
fwrite(FID, S, 'char');
fclose(FID);
end
end
end
end
end
end
fclose(fid);
复制代码
当然,我们也利用这个训练批量地
使用修改编译后的libsvm十折交叉验证:
confu=svmtrain(label,feat,'-v 10');
复制代码
这一行直接可以输出混淆矩阵,默认的libsvm包是十折的话只输出一个准确度,这是蛋疼,
具体参考关于libsvm包优化的那一篇
计算了准确率等论文可以直接使用的指标:
confu=double(confu);
TP=confu(1);
FN=confu(2);
FP=confu(3);
TN=confu(4);
Sn=TP/(TP+FN);
Sp=TN/(TN+FP);
Acc=(TP+TN)/(TP+FN+FP+TN);
MCC=(TP*TN-FN*FP)/sqrt((TP+FP)*(TN+FN)*(TP+FN)*(TN+FP));
复制代码
生成保存了arff文件以[/code]便后续使用:
feat_label=[feat,targets-1];
csvwrite('feat_temp.csv',feat_label);
S = fileread('feat_temp.csv');
feat_dim=100;
attribute='';
for index=1:feat_dim
attribute=[attribute,'@attribute Fea',int2str(index),' numeric',char(10)];
end
header=['@relation m6a_dbn',char(10),attribute,'@attribute class {0,1}',char(10),'@data',char(10)];
S = [header, S];
name=sprintf('%s-%d-%d-%d-%d-%.4f-%.4f-%.4f-%.4f-%d-%d-%d-%d-%d',mat2str(GridSearch_nodes{i}(:)),GridSearch_maxEpoch(k),l,GridSearch_learningRate(m),GridSearch_BPorNot(n),Sn,Sp,Acc,MCC,TP,FN,FP,TN,times);
FID = fopen([name,'.arff'], 'w');
if FID == -1, error('Cannot open file'); end
fwrite(FID, S, 'char');
fclose(FID);
复制代码
先就酱。
欢迎光临 机器学习和生物信息学实验室联盟 (http://123.57.240.48/)
Powered by Discuz! X3.2