deeplearn.js科研之路(一)

【写在最前】

转发请注明原地址~

要读博了,得做研究了,不能成天想着JavaScript接私活了,就让我用另一种方式来爱你吧~

deeplearn.js本身并没有什么特别的东西,基本就是Numpy和Tensorflow两套API。

从基础开始接触深度学习,这几天一直在手写推导公式,暂时喘口气,把最早接触deeplearn.js的这个全连接拟合异或的实验记录下来。

以前没有接触过tensorflow,好在官方文档给的很清晰,好在有个玩得转tensorflow的女朋友。这次的实验应该是非常非常简单,甚至简陋,甚至甚至丑陋了,只用了一些矩阵运算。后面会慢慢地按tensorflow的架构来搭网络做实验搞研究,一些不重要的内容也会记录在blog里。

本篇文章不包含任何全连接网络的基础知识,只有deeplearn.js实现全连接网络拟合异或的实现,基础知识网上大把大把。也不包含任何对API的说明,官网上有API文档的。如果有疑问可以发消息给我~

本次实验少一点点东西...就是隐藏层到输出层的bias。

还处于学习阶段,还差得远呢

github展示页(可以进去直接体验直接控制台写代码玩哦):https://knimet.github.io/my-research-with-deeplearn.js/xor.html

github工程地址:https://github.com/knimet/my-research-with-deeplearn.js

【任务】全连接网络拟合XOR。

【思路】

实验设计的全连接网络,输入层3节点,1个包含3节点的隐藏层,输出层1节点。

【实现】

首先按官网指导引入文件

开启严格模式,搭建基础环境。

var dl = deeplearn;
var math = new dl.NDArrayMathCPU();

定义实验数据。输入的第三个数据恒为1,为bias准备的。

const data = [dl.Array2D.new([3,1],[0,0,1]),dl.Array2D.new([3,1],[0,1,1]),dl.Array2D.new([3,1],[1,0,1]),dl.Array2D.new([3,1],[1,1,1])];
const label = dl.Array1D.new([0,1,1,0]);

激活函数使用sigmoid函数,基础环境中math.sigmoid()已定义。

定义学习速率

const n = dl.Scalar.new(0.1);
定义权重矩阵,也就是要训练的部分。wih是输入层到隐藏层的3*3权重矩阵,who是隐藏层到输出层的1*3权重矩阵。

var wih = dl.Array2D.rand([3,3],Math.random); 
var who = dl.Array2D.rand([1,3],Math.random); 
定义初始的输出,用于启动训练。我定义的初始输出为[0,0,0,0],这样可以让循环继续下去。

var output = dl.Array1D.new([0,0,0,0]);
定义loss函数,误差平方和。

function loss(output){ //计算loss,认为误差平方和小于0.01为合格
    let result = math.subtract(label,output);
    return math.dotProduct(result,result).getValues();
}

定义c记录迭代次数。

var c = 0;
开始训练。

while( loss(output) > 0.01 ){//误差平方和小于0.01为合格
        c++;
        if(c % 100 ==0){ //每100轮打印一次loss
            document.write("第"+c+"轮的loss值为"+loss(output)+"
"); } data.forEach(function(value,index,array){ //对每个样本进行训练 //前向计算 var outih = math.sigmoid(math.matMul(wih,value));//3*1,3*3的权重矩阵和3*1的输入矩阵相乘,得到隐藏层值 //console.log("隐藏层计算结果为"+outih.getValues()); var out = math.sigmoid(math.matMul(who,outih));//1*1,1*3的权重矩阵和3*1的隐藏层值相乘,得到输出结果 //console.log("输出为"+out.getValues()); //反向传播调整权重 var y = out.getValues(); //得到输出层的值 var t = label.getValues()[index]; //得到label值,也就是目标值 if(y != t){ //console.log("输出结果和label不同,开始BP"); //计算误差 var deltay = y * (1-y) * (t-y); //输出层误差 let deltaihp1 = math.subtract(dl.Scalar.new(1),outih); let deltaihp2 = math.multiply(outih , deltaihp1); let deltaihp3 = math.multiply(dl.Scalar.new(deltay),deltaihp2); let deltaihp4 = math.multiply(deltaihp3 , math.transpose(who)); //隐藏层误差 //console.log("开始调整权重"); var wihp1 = math.matMul(deltaihp4,math.transpose(value)); //这一步写了草稿才确定写法是正确的 var wihp2 = math.multiply(n,wihp1); wih = math.add(wih,wihp2);//更新输入到隐藏层的权重矩阵 who = math.add(who,math.multiply(dl.Scalar.new(deltay),math.transpose(outih)));//更新隐藏层到输出层的权重矩阵 //前向计算,更新本轮输出 var outih = math.sigmoid(math.matMul(wih,value));//3*1 var out = math.sigmoid(math.matMul(who,outih));//1*1 output.set(out.getValues(),index); } }) }

训练结束后,打印训练后的结果到屏幕上。

document.write("计算结果为
"); data.forEach(function(value,index,array){ //对每个样本 var outih = math.sigmoid(math.matMul(wih,value));//3*1 var out = math.sigmoid(math.matMul(who,outih));//1*1 var v = value.getValues(); document.write(v[0]+"异或"+v[1]+"="+out.getValues()+"
"); })

【体验】

权重初值,隐藏层节点数对训练次数影响非常非常大~文章开始留下的github展示页,多刷新几次就能体验到权重初值对训练次数的影响。

【THE END】

你可能感兴趣的:(deeplearn.js)