|
本帖最后由 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);
复制代码
先就酱。 |
|