mirror of
https://github.com/wassname/keras-js.git
synced 2026-10-04 12:40:46 +08:00
implement MaxPooling1D/AveragePooling1D, with tests
This commit is contained in:
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)
|
||||
|
||||
@@ -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)
|
||||
))
|
||||
|
||||
@@ -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,3 +1,4 @@
|
||||
export * from './advanced_activations'
|
||||
export * from './core'
|
||||
export * from './convolutional'
|
||||
export * from './pooling'
|
||||
@@ -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'
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import MaxPooling1D from './MaxPooling1D'
|
||||
import AveragePooling1D from './AveragePooling1D'
|
||||
|
||||
export {
|
||||
MaxPooling1D,
|
||||
AveragePooling1D
|
||||
}
|
||||
Reference in new issue
Block a user