考虑到大家有可能对深度学习的识别有点模糊,因此决定写一个短博客,简单介绍下如何识别,结合本系列的第一篇博文提到的深度学习之所以叫深度,其中之一的原因是多层RBM模仿了人脑多层神经元对输入数据进行层层预处理(值得一提的是并不是每层都是RBM,DBN就是个例外),即深层次的数据拟合,多个RBM连接起来构成DBM(deep boltzmann machines),每层RBM的节点数自己指定,这需要一些经验,DBN和DBM在训练上没有区别,都是逐层使用CD算法训练,也叫贪心预训练算法,DBN和DBM的区别如(图一)所示。
图一
对于二者都使用同一个算法来训练,看起来毫无区别,但是DBM有一个优势,由于RBM是无向的,这就决定了无论给定可视节点还是隐藏节点,各个节点都是独立的,可由图模型的马尔科夫性看出。作为无向图的DBM天生具有一些优秀的基因,比如当人看到一个外观性质,知道它是什么物体,同样你告诉他物体名字,他可以知道物体的外观应该是什么样子。这种互相推理的关系正好可以用无向图来表示。这种优势也顺理成章的延伸出了autoencoder(大家所谓的自编码神经网络)和栈式神经网络,最终输出的少量节点是可以推理(重建)出原来样本,也起到了降维的作用,无形中也找到了特征(编码),autoencoder的效果如图二所示。但是DBN中有些层是有向的,就不具有这种优势。
图二
二者逐层预训练后,结合样本标签,使用BP算法进行权重微调,说白了就是在预训练后的权重基础上使用BP算法进行训练,这样得出的权重更好些。。。
下面贴出部分DBN代码,大家可以看出总体思路是按照构建DBN网络(刚构建后的每层的权重是随机生成的,从代码也能看出),贪心层层预训练,权重微调,预测(识别)这个步骤来的。另外代码中softmax其实是多变量的逻辑回归函数,注意我发的下面的代码中权重微调使用的是逻辑回归,不是BP:
#include <iostream>
#include <math.h>
#include "HiddenLayer.h"
#include "RBM.h"
#include "LogisticRegression.h"
#include "DBN.h"
using namespace std;
double uniform(double min, double max) {
return rand() / (RAND_MAX + 1.0) * (max - min) + min;
}
int binomial(int n, double p) {
if(p < 0 || p > 1) return 0;
int c = 0;
double r;
for(int i=0; i<n; i++) {
r = rand() / (RAND_MAX + 1.0);
if (r < p) c++;
}
return c;
}
double sigmoid(double x) {
return 1.0 / (1.0 + exp(-x));
}
// DBN
DBN::DBN(int size, int n_i, int *hls, int n_o, int n_l) {
int input_size;
N = size;
n_ins = n_i;
hidden_layer_sizes = hls;
n_outs = n_o;
n_layers = n_l;
sigmoid_layers = new HiddenLayer*[n_layers];
rbm_layers = new RBM*[n_layers];
// construct multi-layer
for(int i=0; i<n_layers; i++) {
if(i == 0) {
input_size = n_ins;
} else {
input_size = hidden_layer_sizes[i-1];
}
// construct sigmoid_layer
sigmoid_layers[i] = new HiddenLayer(N, input_size, hidden_layer_sizes[i], NULL, NULL);
// construct rbm_layer
rbm_layers[i] = new RBM(N, input_size, hidden_layer_sizes[i],\
sigmoid_layers[i]->W, sigmoid_layers[i]->b, NULL);
}
// layer for output using LogisticRegression
log_layer = new LogisticRegression(N, hidden_layer_sizes[n_layers-1], n_outs);
}
DBN::~DBN() {
delete log_layer;
for(int i=0; i<n_layers; i++) {