implement MaxPooling1D/AveragePooling1D, with tests

This commit is contained in:
Leon Chen committed 2016-08-31 17:00:51 -04:00
1 parent 18170ac11a
commit 30d045339a
15 files changed
+1445 -7

No files matched your search

@@ -87,8 +87,8 @@ export default class AtrousConvolution2D extends Convolution2D {
let patch = new Tensor([], [patchLen])
let n = 0
for (let i = 0; i <= inputRows - nbRowDilated; i += this.subsample[0]) {
for (let j = 0; j <= inputCols - nbColDilated; j += this.subsample[1]) {
for (let i = 0, limit = inputRows - nbRowDilated; i <= limit; i += this.subsample[0]) {
for (let j = 0, limit = inputCols - nbColDilated; j <= limit; j += this.subsample[1]) {
const patchData = flattenDeep(unpack(
x.tensor
.hi(i + nbRowDilated, j + nbColDilated, inputChannels)
+2 -2
View File
@@ -143,8 +143,8 @@ export default class Convolution2D extends Layer {
let patch = new Tensor([], [patchLen])
let n = 0
for (let i = 0; i <= inputRows - nbRow; i += this.subsample[0]) {
for (let j = 0; j <= inputCols - nbCol; j += this.subsample[1]) {
for (let i = 0, limit = inputRows - nbRow; i <= limit; i += this.subsample[0]) {
for (let j = 0, limit = inputCols - nbCol; j <= limit; j += this.subsample[1]) {
const patchData = flattenDeep(unpack(
x.tensor.hi(i + nbRow, j + nbCol, inputChannels).lo(i, j, 0)
))
+3 -3
View File
@@ -159,9 +159,9 @@ export default class Convolution3D extends Layer {
let patch = new Tensor([], [patchLen])
let n = 0
for (let i = 0; i <= inputDim1 - kernelDim1; i += this.subsample[0]) {
for (let j = 0; j <= inputDim2 - kernelDim2; j += this.subsample[1]) {
for (let k = 0; k <= inputDim3 - kernelDim3; k += this.subsample[2]) {
for (let i = 0, limit = inputDim1 - kernelDim1; i <= limit; i += this.subsample[0]) {
for (let j = 0, limit = inputDim2 - kernelDim2; j <= limit; j += this.subsample[1]) {
for (let k = 0, limit = inputDim3 - kernelDim3; k <= limit; k += this.subsample[2]) {
const patchData = flattenDeep(unpack(
x.tensor.hi(i + kernelDim1, j + kernelDim2, k + kernelDim3, inputChannels).lo(i, j, k, 0)
))
+1
View File
@@ -1,3 +1,4 @@
export * from './advanced_activations'
export * from './core'
export * from './convolutional'
export * from './pooling'
+14
View File
@@ -0,0 +1,14 @@
import _Pooling1D from './_Pooling1D'
/**
* AveragePooling1D layer class, extends abstract _Pooling1D class
*/
export default class AveragePooling1D extends _Pooling1D {
/**
* Creates a AveragePooling1D activation layer
*/
constructor (attrs = {}) {
super(attrs)
this.poolingFunc = 'average'
}
}
+14
View File
@@ -0,0 +1,14 @@
import _Pooling1D from './_Pooling1D'
/**
* MaxPooling1D layer class, extends abstract _Pooling1D class
*/
export default class MaxPooling1D extends _Pooling1D {
/**
* Creates a MaxPooling1D activation layer
*/
constructor (attrs = {}) {
super(attrs)
this.poolingFunc = 'max'
}
}
+80
View File
@@ -0,0 +1,80 @@
import Layer from '../../engine/Layer'
import Tensor from '../../Tensor'
import ops from 'ndarray-ops'
/**
* _Pooling1D layer class
*/
export default class _Pooling1D extends Layer {
/**
* Creates a _Pooling1D activation layer
*/
constructor (attrs = {}) {
super(attrs)
const {
poolLength = 2,
stride = null,
borderMode = 'valid'
} = attrs
this.poolLength = poolLength
this.stride = stride === null ? poolLength : stride
this.borderMode = borderMode
// default pooling function
// can be `max` or `average`
this.poolingFunc = 'max'
}
/**
* Method for layer computational logic
* @param {Tensor} x
* @returns {Tensor} x
*/
call (x) {
if (this.poolingFunc !== 'max' && this.poolingFunc !== 'average') {
throw new Error(`[pooling._Pooling1D] pooling function must be max or average.`)
}
const stepsNew = this.borderMode === 'valid'
? Math.floor((x.tensor.shape[0] - this.poolLength + this.stride) / this.stride)
: Math.floor((x.tensor.shape[0] + this.stride - 1) / this.stride)
let y = new Tensor([], [stepsNew, x.tensor.shape[1]])
let yStep = new Tensor([], [x.tensor.shape[1]])
// in borderMode same, start negative from beyond step 0
let step = this.borderMode === 'valid'
? 0
: Math.min(0, Math.ceil((x.tensor.shape[0] - (stepsNew - 1) * this.stride - this.poolLength) / 2))
for (let i = 0; i < stepsNew; i++) {
let _step = Math.max(0, step)
let limit = this.poolLength + Math.min(0, step)
ops.assign(yStep.tensor, x.tensor.pick(_step, null))
let count = 1
for (let j = 1; j < limit; j++) {
if ((_step + j) > (x.tensor.shape[0] - 1)) {
break
}
if (this.poolingFunc === 'max') {
ops.maxeq(yStep.tensor, x.tensor.pick(_step + j, null))
} else if (this.poolingFunc === 'average') {
ops.addeq(yStep.tensor, x.tensor.pick(_step + j, null))
}
count += 1
}
if (this.poolingFunc === 'average') {
ops.divseq(yStep.tensor, count)
}
ops.assign(y.tensor.pick(i, null), yStep.tensor)
step += this.stride
}
x.tensor = y.tensor
return x
}
}
+7
View File
@@ -0,0 +1,7 @@
import MaxPooling1D from './MaxPooling1D'
import AveragePooling1D from './AveragePooling1D'
export {
MaxPooling1D,
AveragePooling1D
}