用node实现一个简单的深度神经网络

初识神经网络

简介

  • 硬编码的智能:人工智能早期,用以实现专家系统。特点,实现难度高,并且难以适应变化。
  • 机器学习:程序本身不编码实现任何解决具体问题的方法,而是模仿生物的进化、认知,能够不断地从周围环境中获取数据进行学习。特点:实现难度相较于上一个简单,但是需要大量数据,训练的方法也很重要,能够适应变化解决各种新的问题。

算法原理

  • 外界信号通过你的眼睛、鼻子、舌头等等一系列感知器官(输入)捕获后传入大脑皮层(这个我也不清除,先假装是的),大脑皮层是第一层神经元,经过第一层处理后,然后传入第二层、第三层,最终经过n层处理后得到结果,所以我们能够对纷繁复杂的世界产生正确的认知。

  • 深度神经网络算法,就是基于人脑认知事务进行学习的这一特性的算法。初始数据经由多层神经元的计算后得到输出,刚开始时可能会有较大的误差,这时就需要我们的训练。

  • 训练分为监督式训练、无监督训练。这里我们讲的是监督式训练。

监督式训练:

给出一组样本数据,以及对应的正确期望结果。让神经网络不断学习,神经网络会在学习的过程中不断地矫正神经元连接的突触的权值、动量系数等等。理论上经过若干次的训练后,这个神经网络就会调整为一个最佳的情况,这时,对给定的输入,能够在比较大的概率下给出正确的结果。

算法实现

以下是神经网络算法的node实现。

asgc-ai是傲世孤尘开源的一款基于node的人工智能算法库,本算法集成于其中,本算法调用了一些asgc-ai中的公共方法,下面只给出算法的核心实现,因此要获取完整的代码请点击这里

BpDeep.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
var math = require('../../common/math');
var log = require('../../common/log');

var random = math.random.random;

function createArray(len){
if(!len)return [];

var res = [];

for(var i = 0; i < len; i++){
res[i] = 0;
}

return res;
}

function create2dArray(m,n){
if(!m) return [];
var res = [];

for(var i = 0; i < m; i++){
res[i] = createArray(n);
}

return res;
}

function create3dArray(m,n,l){
if(!m) return [];
var res = [];

for(var i = 0; i < m; i++){
res[i] = create2dArray(n,l);
}

return res;
}

function BpDeep(layernum,rate,mobp){

var mobp = mobp;//动量系数
var rate = rate;//学习系数
var layer = C= create2dArray(layernum.lengt);//神经网络各层节点
var layerErr = create2dArray(layernum.lengt);//神经网络各节点误差
var layer_weight = create3dArray(layernum.lengt);;//各层节点权重
var layer_weight_delta = create3dArray(layernum.lengt);;//各层节点权重动量

function init(){
for(var l = 0; l < layernum.length; l++){

layer[l] = createArray(layernum[l]);
layerErr[l] = createArray(layernum[l]);

if(l + 1 < layernum.length){

layer_weight[l] = create2dArray(layernum[l]+1,layernum[l+1]);
layer_weight_delta[l] = create2dArray(layernum[l]+1,layernum[l+1]);

for(var j = 0; j < layernum[l]+1; j++){
layer_weight[l][j] = [];
for(var i = 0; i < layernum[l+1]; i++){
layer_weight[l][j][i] = random();//随机初始化权重
}
}
}
}
}

//逐层向前计算输出
function computeOut(input){
for(var l = 1; l < layer.length; l++){
for(var j = 0; j < layer[l].length; j++){
var z = layer_weight[l-1][layer[l-1].length][j];
for(var i = 0; i < layer[l-1].length; i++){
layer[l-1][i] = l==1? input[i] : layer[l-1][i];
z += layer_weight[l-1][i][j] * layer[l-1][i];
}
layer[l][j] = 1/(1+Math.exp(-z));
}
}
return layer[layer.length-1];
}

//逐层反向计算误差并修改权重
function updateWeight(tar){
var l = layer.length - 1;
for(var j = 0; j < layerErr[l].length; j++)
layerErr[l][j] = layer[l][j] * (1-layer[l][j]) * (tar[j]-layer[l][j]);

while(l-- > 0){
for(var j = 0; j < layerErr[l].length; j++){
var z = 0.0;
for(var i = 0; i < layerErr[l+1].length; i++){
z = z+l > 0? layerErr[l+1][i] * layer_weight[l][j][i] : 0;
layer_weight_delta[l][j][i] = mobp * layer_weight_delta[l][j][i] + rate * layerErr[l+1][i] * layer[l][j];//隐含层动量调整
layer_weight[l][j][i]+=layer_weight_delta[l][j][i];//隐含层权重调整
if(j == layerErr[l].length-1){
layer_weight_delta[l][j+1][i]= mobp*layer_weight_delta[l][j+1][i]+rate*layerErr[l+1][i];//截距动量调整
layer_weight[l][j+1][i]+=layer_weight_delta[l][j+1][i];//截距权重调整
}
}
layerErr[l][j] = z*layer[l][j]*(1-layer[l][j]);//记录误差
}
}
}

//单次训练
function train(input,tar){
var out = computeOut(input);
updateWeight(tar);
}

//迭代训练
function iterTrain(data,tar,count){
for(var i = 0; i < count; i++){
for(var j = 0; j < data.length; j++){
train(data[j],tar[j]);
}
}
}

init();

return {
train: train,
computeOut: computeOut,
iterTrain: iterTrain
};
}

module.exports = BpDeep;

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var deep = require('../../../').deep;

//开启日志
deep.setLog(true);

//初始化神经网络的基本配置
var bp = deep.BpDeep([2,10,2],0.15,0.8);

//初始化样本数据
var data = [[1,2],[2,2],[1,1],[2,1]];

//初始化目标数据
var tar = [[1,0],[0,1],[0,1],[1,0]];

//迭代训练
bp.iterTrain(data,tar,1000);

console.log('训练结果:');
for(var j = 0; j < data.length; j++){
var result = bp.computeOut(data[j]);
console.log(data[j] + ":" + result);
}

console.log('计算:');
var x = [3,1]
var result = bp.computeOut(x);
console.log(x + ":" + result);
你的鼓励,是我前进的动力!