From 8009d631672e2b041ce02215bf74eaa1338ac416 Mon Sep 17 00:00:00 2001 From: Leon Chen Date: Sun, 9 Oct 2016 00:55:38 -0400 Subject: [PATCH] create weight row matrices on layer initialization, not call() --- src/layers/convolutional/Convolution2D.js | 34 ++++++++++++++++----- src/layers/convolutional/Convolution3D.js | 9 +++--- src/layers/convolutional/Deconvolution2D.js | 7 ++--- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/layers/convolutional/Convolution2D.js b/src/layers/convolutional/Convolution2D.js index afc15f1..adf1e52 100644 --- a/src/layers/convolutional/Convolution2D.js +++ b/src/layers/convolutional/Convolution2D.js @@ -67,6 +67,8 @@ export default class Convolution2D extends Layer { weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 1, 0) } super.setWeights(weightsArr) + + this._wRowsMat = this._w2row() } /** @@ -161,11 +163,10 @@ export default class Convolution2D extends Layer { /** * Convert filter weights to row matrix - * @param {Tensor} x - * @returns {Tensor} x + * @returns {Tensor} wRowsMat */ - _w2row (x) { - const inputChannels = x.tensor.shape[2] + _w2row () { + const inputChannels = this.weights.W.tensor.shape[2] const [nbFilter, nbRow, nbCol] = this.kernelShape const patchLen = nbRow * nbCol * inputChannels @@ -192,13 +193,24 @@ export default class Convolution2D extends Layer { if (this.dimOrdering === 'th') { x.tensor = x.tensor.transpose(1, 2, 0) } - + let startTime = performance.now() this._calcOutputShape(x) + let endTime = performance.now() + if (this.name === 'conv1') console.log('_calcOutputShape', endTime - startTime) + startTime = performance.now() this._padInput(x) - + endTime = performance.now() + if (this.name === 'conv1') console.log('_padInput', endTime - startTime) + startTime = performance.now() const imColsMat = this._im2col(x) - const wRowsMat = this._w2row(x) + endTime = performance.now() + if (this.name === 'conv1') console.log('imColsMat', endTime - startTime) + startTime = performance.now() + const wRowsMat = this._wRowsMat + endTime = performance.now() + if (this.name === 'conv1') console.log('wRowsMat', endTime - startTime) + startTime = performance.now() const nbFilter = this.kernelShape[0] const outputRows = this.outputShape[0] const outputCols = this.outputShape[1] @@ -222,7 +234,10 @@ export default class Convolution2D extends Layer { } else { gemm(matMul.tensor, imColsMat.tensor, wRowsMat.tensor, 1, 1) } + endTime = performance.now() + if (this.name === 'conv1') console.log('gemm', endTime - startTime) + startTime = performance.now() let output = new Tensor([], this.outputShape) let outputChannelRaveled = new Tensor([], [outputRows * outputCols]) let outputChannel = new Tensor([], [outputRows, outputCols]) @@ -232,8 +247,13 @@ export default class Convolution2D extends Layer { ops.assign(output.tensor.pick(null, null, n), outputChannel.tensor) } x.tensor = output.tensor + endTime = performance.now() + if (this.name === 'conv1') console.log('createOutput', endTime - startTime) + startTime = performance.now() this.activation(x) + endTime = performance.now() + if (this.name === 'conv1') console.log('activation', endTime - startTime) // convert back to th ordering if necessary if (this.dimOrdering === 'th') { diff --git a/src/layers/convolutional/Convolution3D.js b/src/layers/convolutional/Convolution3D.js index b5748af..357aabe 100644 --- a/src/layers/convolutional/Convolution3D.js +++ b/src/layers/convolutional/Convolution3D.js @@ -180,11 +180,10 @@ export default class Convolution3D extends Layer { /** * Convert filter weights to row matrix - * @param {Tensor} x - * @returns {Tensor} x + * @returns {Tensor} wRowsMat */ - _w2row (x) { - const inputChannels = x.tensor.shape[3] + _w2row () { + const inputChannels = this.weights.W.tensor.shape[3] const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = this.kernelShape const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels @@ -216,7 +215,7 @@ export default class Convolution3D extends Layer { this._padInput(x) const volColsMat = this._vol2col(x) - const wRowsMat = this._w2row(x) + const wRowsMat = this._w2row() const nbFilter = this.kernelShape[0] const outputDim1 = this.outputShape[0] diff --git a/src/layers/convolutional/Deconvolution2D.js b/src/layers/convolutional/Deconvolution2D.js index e1b293f..020a62e 100644 --- a/src/layers/convolutional/Deconvolution2D.js +++ b/src/layers/convolutional/Deconvolution2D.js @@ -140,10 +140,9 @@ export default class Deconvolution2D extends Layer { /** * Convert filter weights to row matrix, along channels axis * shape: [nbRow, nbCol, inputChannels, nbFilter] -> [inputChannels, nbRow * nbCol * nbFilter] - * @param {Tensor} x - * @returns {Tensor} x + * @returns {Tensor} wRowsMat */ - _w2row (x) { + _w2row () { const [nbRow, nbCol, inputChannels, nbFilter] = this.weights.W.tensor.shape const wRowsMat = new Tensor([], [inputChannels, nbRow * nbCol * nbFilter]) @@ -169,7 +168,7 @@ export default class Deconvolution2D extends Layer { } const imColsMat = this._im2col(x) - const wRowsMat = this._w2row(x) + const wRowsMat = this._w2row() const inputRows = x.tensor.shape[0] const inputCols = x.tensor.shape[1]