用js实现一个三层的bp神经网络
程序员文章站
2022-05-22 13:06:44
...
当我实现了一个简单的bp神经网络后内心很是激动,赶忙实现了三层的神经网络是什么样子的。
网络长这个样子的:
实际上三个输入,两个隐层元,一个输出
各种参数的说明是这样子的:
比起二层网络要多更新很多值。
公式的一些推导长这样子的:
依旧使用梯度下降法:
最后代码是这样子的:
<html>
<head>
</head>
<body>
<div class="div"></div>
<button>开始</button>
<script src="http://www.numericjs.com/lib/numeric-1.2.6.js" type="text/javascript"></script>
<script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js" type="text/javascript"></script>
<script>
//Initial input/ouput values
var X = [
[0, 0, 1],
[1, 0, 1],
[0, 1, 0],
[1, 1, 0]
];
var y = [
[0],
[1],
[0],
[1]
];
</script>
<script>
// test 输出函数
function print(x){
if(typeof x === "object"){
$('.div').before("<p>"+numeric.prettyPrint(x)+"</p>");
}else{
$('.div').before("<p>"+x+"</p>");
}
}
// Sigmoid 函数
function sigmoid(x) {
return numeric.div(1, numeric.add(1, numeric.exp(numeric.neg(x))));
}
// 输入层到隐层的权值
var syn0;
// 初始化为 -1~1
syn0 = numeric.sub(numeric.mul(2, numeric.random([2, 3])), 1);//输入层有三个元,隐层有两个元
// 隐层的阈值
var gama;
// 初始化为 -1~1
var gama = numeric.sub(numeric.mul(2,numeric.random([2,1])),1);
// 隐层到输出层的权值
var syn1;
// 初始化为 -1~1
syn1 = numeric.sub(numeric.mul(2,numeric.random([1,2])),1);//输出层有一个元
// 输出层的阈值
var sita;
// 初始化
sita = numeric.random([1,1]);
// 学习率
var engama = 0.1;
// 隐层第h元的输出函数
function output0(x,h){ // x=[[0,0,1]]这种形式
var temp = numeric.transpose([syn0[h]]);
return sigmoid(numeric.sub(numeric.dot(x,temp),gama[h][0]))[0];
}
function putput0_toArr(x){
var q = 2; //隐层元数量为2
var h = 0;
var b = new Array();
for(;h<q;h++){
b.push(output0(x,h));
}
return b; //b = [[1],[1]]这种形式
}
// 输出层的输出函数
function output1(x){ // x=[[0,0,1]]这种形式
b = putput0_toArr(x);
return sigmoid(numeric.sub(numeric.dot(syn1,b),sita));
}
function train_neural(X, y, iteration) {
//第i代训练
var i = 0;
for (; i < iteration; i++) {
// 第k个训练样本
var k;
for( k in X){
// 真实输出
var yt = output1([X[k]]);
// 函数gi的值为
var gk = (yt-y[k])*yt*(1-yt);
var b = putput0_toArr([X[k]]); //b = [[1],[1]]这种形式
// 参数更新
var temp2 = numeric.mul(numeric.transpose(syn1),gk); //gk * wh
var temp3 = numeric.mul(b,numeric.sub(1,b)); //bh * (1 - bh)
var temp4 = numeric.mul(temp2,temp3); // [[0],[0]]这种形式 eh
syn0 = numeric.sub(syn0,numeric.mul(engama,numeric.dot(temp4,[X[k]])));
gama = numeric.add(gama,temp4);
var temp1 = numeric.transpose(numeric.mul(gk,b));
// 标准误差逆传播
syn1 = numeric.sub(syn1,numeric.mul(engama,temp1));
sita = numeric.add(sita,engama * gk);//阈值更新
}
}
}
$('button').on('click',function(){
train_neural(X, y, 10000);
var k;
for( k in X){
print(output1([X[k]]));
}
})
</script>
</body>
</html>
这是一段很头疼的代码,因为js上实现矩阵运算还是比较麻烦的,加上numeric这个js库运用不熟练,让部分代码看起来很奇怪
运行结果是这样子的:
对训练样本做训练然后输出训练样本的值,也是蛮接近(0,1,0,1)
注:渴望您的交流!
上一篇: leetcode在圆内随机生成点
下一篇: 【三层】创建一个简单的C#三层结构