【写在最前】
之所以想到读代码,是因为deeplearn.js报的这个错
Softmax backprop is not yet implemented
Softmax backprop is not yet implemented
Softmax backprop is not yet implemented
怎么办怎么办怎么办
没有枪没有炮,我们 (自己造||喝西北风)
只能依靠dl.math手写了自己需要的网络的bp,然后重新搭建了网络。
本以为自己数学基础可以,但是草稿纸还是写了很多张。
希望读了代码之后可以试着补上softmax的bp吧
语言表达能力有限,搜【实例】有惊喜
【解析】
【关键词】
【Tensor】
这个是架构中最重要的一环。Tensor只有两条属性:shape和id。构造函数接收Tensor的shape,id由Tensor实例化的顺序决定。
根据文档说明和我的理解,Tensor记录shape,保证网络结构正确,维护/保持网络结构。
【Node】
【Graph】
【Graph.prototype.addNodeAndReturnOutput】
【Graph.prototype.variable】
【节点说明:VariableNode】
【实例】
var graph= new dl.Graph();
var W = graph.variable('W',dl.Array2D.randNormal([2,3]));
以上代码创建了图graph,并创建了权重矩阵W到图中。var U = graph.variable('W',dl.Array2D.randNormal([6,7]));
结果显而易见。【Graph.prototype.matmul】
【实例】
var graph = new dl.Graph()
var St = graph.placeholder('St',[5,1]);
var W = graph.variable('W',dl.Array2D.randNormal([5,5]))
var mm = graph.matmul(W,St)
mm的node指向由参数构建的MatMulNode。该节点构造函数如下(还是决定贴一下,要不太抽象了)
var MatMulNode = (function (_super) {
__extends(MatMulNode, _super);
function MatMulNode(graph, x1, x2) {
var _this = _super.call(this, graph, 'MatMul', {
x1: x1,
x2: x2
}, new Tensor(getMatMulOutputShape(x1.shape, x2.shape))) || this;
_this.x1 = x1;
_this.x2 = x2;
return _this;
}
MatMulNode.prototype.validate = function () {
if (this.x1.shape.length === 2 && this.x2.shape.length === 2) {
util.assert(this.x1.shape[1] === this.x2.shape[0], 'Error adding matmul op: inner shapes of matrices with shapes ' +
(this.x1.shape + " and " + this.x2.shape + " must match."));
} else if (this.x1.shape.length === 2 && this.x2.shape.length === 1) {
util.assert(this.x1.shape[1] === this.x2.shape[0], 'Error adding matmul op: second dimension of matrix with shape ' +
this.x1.shape.toString() +
(" must match size of vector with shape " + this.x2.shape + "."));
} else if (this.x1.shape.length === 1 && this.x2.shape.length === 2) {
util.assert(this.x1.shape[0] === this.x2.shape[0], "Error adding matmul op: size of vector with shape " + this.x1.shape +
" must match first dimension of matrix with " +
("shape " + this.x2.shape + "."));
} else {
throw new Error('Error adding matmul op: inputs must be vectors or matrices.');
}
};
MatMulNode.X1 = 'x1';
MatMulNode.X2 = 'x2';
return MatMulNode;
}(Node));
和前面VariableNode不同,MatMulNode将其输入定义为传入的形参x1和x2,在本实例中即为Tensor W和Tensor St。而构建输出Tensor的shape为输入的x1和x2做矩阵乘法结果的shape,getMatMulOutputShape(x1Shape, x2Shape)源码如下,很清晰的数学表达: function getMatMulOutputShape(x1Shape, x2Shape) {
if (x1Shape.length === 1 && x2Shape.length === 1) {
return [1];
} else if (x1Shape.length === 1 && x2Shape.length === 2) {
return [x2Shape[1]];
} else if (x1Shape.length === 2 && x2Shape.length === 1) {
return [x1Shape[0]];
}
return [x1Shape[0], x2Shape[1]];
}
合法性校验方面,检验的是输入合法性(是否是矩阵向量)以及两个输入是否能做矩阵乘法运算。【写在最后】