deeplearn.js API用例(二)softmax的手动实现(解决Softmax backprop is not yet implemented问题)
来源:互联网 发布:node.js能做什么 编辑:程序博客网 时间:2024/05/17 03:01
【写在最前】
玩了一周的python,没忍住又跑回来了。
这次是从tensorflow官网例子中得到的灵感,解决deeplearn.js中的如下问题:
Softmax backprop is not yet implemented
Softmax backprop is not yet implemented
Softmax backprop is not yet implemented
也就是之前写的《源码解析》中的动力源泉。
至于灵感,是tensorflow官方给的demo中用数学计算手动实现了交叉熵。所以既然deeplearn.js暂时没有实现softmax的bp,我可以用数学计算代替它,并且实际测试后证明是可行的。
github工程地址:https://github.com/knimet/deeplearn.js-softmax-can-backprop
【干货】
【明确目标】
在Graph内手动实现softmax。
当前deeplearn.js文档中对Graph的说明如下:
【目标分析】
1.分解softmax公式
对向量X=[x1,x2,...,xn],softmax(X)的结果为与其维度相同的向量。该向量的每个元素分子部分为e^xi,其中xi为对应位置向量X的值;分母部分相同,为sum(e^xi)。
由此,明确计算softmax(X)的基本思路,伪代码如下:
//基本思路powX = pow(Math.E , X); sum_powX = sum(powX);sfX = divide(powX,sum_powX)
2.尝试实现
首先,Graph由Tensor构建,由Node记录/表现网络中的行为,无法操作具体的数值。在查阅Graph提供的方法后,不存在能实现e^xi的类似于power的方法,甚至math中的pow方法也只支持整形次方的计算,如e^2,e^0.1是无法计算的。
综上,基本思路失败。
3.改进
基本思路失败的关键是无法计算e的次方,所以解决问题需要找到能够提供e的次方的方法。查阅文档,铛铛铛铛~
sigmoid登场~
对向量X=[x1,x2,...,xn],sigmoid(X)的结果为与其维度相同的向量。向量的每个元素为1/(1+e^(-x))。
综上,改进思路如下sigmoid提供了e^(-x),是很好的中间件。以此为基础可以尝试计算softmax。
4.改进思路尝试实现
改进思路的伪代码如下:
sigX = sigmoid(X)sig1 = 1/sigXsig2 = sig1-1sum_sig = sum(sig2)sfX = sig2 / sum_sig这是我第一次写出的伪代码,有坑有坑有坑!
查阅文档可以发现,这次的思路可以实现,Graph分别提供了sigmoid、divide、subtract、reduceSum来满足我们的需求。
5.NDArrayMath下的测试
接下来要测试改进思路的实际测试了,代码如下:
var target = dl.Array1D.new([1,2,3,4,5])var sf1 = math.softmax(target)sf1.getValues()var _tsg = math.sigmoid(_t1)_tsg.getValues()var _t1 = math.divide(dl.Array1D.new([1]) , _tsg)_t1.getValues()var _t2 = math.subtract(_t1,dl.Array1D.new([1]))_t2.getValues()var sf2 = math.divide(_t2,math.sum(_t2))sf2.getValues()运行结果如下:
两个结果不一样不一样不一样啊坑啊坑啊坑啊
哎为啥结果是正相反的?
6.填坑
检查改进思路发现,sigmoid在计算的过程中,每个元素为1/(1+e^(-x))。e的次方为-x而不是我们需要的x。因此,正确的填了坑的伪代码如下
mX = X * (-1)sigX = sigmoid(mX)sig1 = 1/sigXsig2 = sig1-1sum_sig = sum(sig2)sfX = sig2 / sum_sig给X的每个元素xi乘上-1,在计算得到sigmoid后就是我们需要的e^x了。
7.填坑后的测试
代码如下:
var target = dl.Array1D.new([1,2,3,4,5])var sf1 = math.softmax(target)sf1.getValues()var _t1 = math.multiply(dl.Scalar.new(-1),target)_t1.getValues()var _tsg = math.sigmoid(_t1)_tsg.getValues()var _t2 = math.divide(dl.Array1D.new([1]) , _tsg)_t2.getValues()var _t3 = math.subtract(_t2,dl.Array1D.new([1]))_t3.getValues()var sf2 = math.divide(_t3,math.sum(_t3))sf2.getValues()测试结果如下:
完美完美完美!
8.Graph样例测试
代码如下:
var dl = require('deeplearn');var math = new dl.NDArrayMathCPU();const session = new dl.Session(g, math);var target = [dl.Array1D.new([1,2,3,4,5])];var g = new dl.Graph();var X = g.placeholder('X',[5]);var sf1 = g.softmax(X);var _t1 = g.multiply(X,g.constant(-1));var _tsg = g.sigmoid(_t1);var _t2 = g.divide(g.constant(1),_tsg);var _t3 = g.subtract(_t2,g.constant(1));var sf2 = g.divide(_t3,g.reduceSum(_t3));const shuffledInputProviderBuilder = new dl.InCPUMemoryShuffledInputProviderBuilder([target]); const inputX = shuffledInputProviderBuilder.getInputProviders()[0]; const feedEntries = [{ tensor: X, data: inputX } ];console.log(session.eval(sf1,feedEntries ).getValues());console.log(session.eval(sf2,feedEntries ).getValues());运行结果如下:
完美完美完美!
9.mnist数据集测试
下次见~
阅读全文
0 0
- deeplearn.js API用例(二)softmax的手动实现(解决Softmax backprop is not yet implemented问题)
- SOFTMAX 的python实现
- Softmax层的实现
- softmax层的实现
- deeplearn.js入门(二)
- Python Numpy联系 手动实现softmax
- softmax
- softmax
- Softmax
- Softmax
- Softmax
- Softmax
- Softmax
- deeplearn.js API用例(一)卷积的前向计算
- softmax函数的硬件实现
- softmax regression的tensorflow实现
- TensorFlow(二)实现Softmax Regression 识别手写数字
- tensorflow实现softmax回归(softmax regression)——简单的MNIST识别(第一课)
- Java--jvm
- JsonUtility解析Json
- CodeForces
- 内排序- 当有两种以上变元的时候的贪心算法
- Gym
- deeplearn.js API用例(二)softmax的手动实现(解决Softmax backprop is not yet implemented问题)
- C++ STL容器之map操作
- JavaScript之Promise实现
- 数据结构--树、森林和二叉树的转换
- 形参和实参是什么?
- Java实现平衡二叉树(AVL树)
- opencv3/C++图像滤波实现
- 区分识别机器学习中的分类与回归
- Android 利用Zxing实现扫描二维码并跳转详情页面