Skip to content

Commit 94a807e

Browse files
committed
Add some neuralnetwork optimizer
1 parent 7fcdf41 commit 94a807e

20 files changed

+1251
-60
lines changed

js/neuralnetwork_builder.js

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import * as opt from '../../lib/model/nns/optimizer.js'
2+
13
const layerTypes = {
24
abs: {},
35
clip: { min: 0, max: 1 },
@@ -192,22 +194,12 @@ export default class NeuralNetworkBuilder {
192194
this._opt = r.append('select').attr('name', 'optimizer')
193195
this._opt
194196
.selectAll('option')
195-
.data([
196-
'sgd',
197-
'adam',
198-
'momentum',
199-
'adagrad',
200-
'rmsprop',
201-
'adadelta',
202-
'rmspropgraves',
203-
'smorms3',
204-
'adamax',
205-
'nadam',
206-
])
197+
.data(Object.keys(opt))
207198
.enter()
208199
.append('option')
209200
.property('value', d => d)
210201
.text(d => d)
202+
this._opt.property('value', 'adam')
211203
}
212204
}
213205
}

js/view/ladder_network.js

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Controller from '../controller.js'
22
import { BaseWorker } from '../utils.js'
3+
import * as opt from '../../lib/model/nns/optimizer.js'
34

45
class LadderNetworkWorker extends BaseWorker {
56
constructor() {
@@ -85,18 +86,8 @@ export default function (platform) {
8586

8687
const optimizer = controller.select({
8788
label: ' Optimizer ',
88-
values: [
89-
'sgd',
90-
'adam',
91-
'momentum',
92-
'adagrad',
93-
'rmsprop',
94-
'adadelta',
95-
'rmspropgraves',
96-
'smorms3',
97-
'adamax',
98-
'nadam',
99-
],
89+
values: Object.keys(opt),
90+
value: 'adam',
10091
})
10192
const slbConf = controller.stepLoopButtons().init(done => {
10293
if (platform.datas.length === 0) {

lib/model/mlp.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Matrix from '../util/matrix.js'
2-
import { AdamOptimizer } from './nns/optimizer.js'
2+
import { adam } from './nns/optimizer.js'
33

44
/**
55
* @ignore
@@ -31,7 +31,7 @@ class MLP {
3131
this._w[i] = Matrix.randn(layer_sizes[i], layer_sizes[i + 1], 0, 0.1)
3232
this._b[i] = Matrix.zeros(1, layer_sizes[i + 1])
3333
}
34-
this._optimizer = new AdamOptimizer()
34+
this._optimizer = new adam()
3535
this._optimizer_mng = this._optimizer.manager()
3636
}
3737

lib/model/neuralnetwork.js

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,31 +84,15 @@ export default class NeuralNetwork {
8484

8585
/**
8686
* @param {ComputationalGraph} graph Graph of a network
87-
* @param {'sgd' | 'adam' | 'momentum' | 'adagrad' | 'rmsprop' | 'adadelta' | 'rmspropgraves' | 'smorms3' | 'adamax' | 'nadam'} [optimizer] Optimizer of the network
87+
* @param {'sgd' | 'adam' | 'momentum' | 'adagrad' | 'rmsprop' | 'adadelta' | 'rmspropgraves' | 'smorms3' | 'adamax' | 'nadam' | 'santae' | 'santasss' | 'amsgrad' | 'adabound' | 'amsbound' | 'adabelief'} [optimizer] Optimizer of the network
8888
*/
8989
constructor(graph, optimizer = 'sgd') {
9090
this._graph = graph
9191
this._optimizer = optimizer
92-
if (optimizer === 'adam') {
93-
this._opt = new opt.AdamOptimizer()
94-
} else if (optimizer === 'momentum') {
95-
this._opt = new opt.MomentumOptimizer()
96-
} else if (optimizer === 'adagrad') {
97-
this._opt = new opt.AdaGradOptimizer()
98-
} else if (optimizer === 'rmsprop') {
99-
this._opt = new opt.RMSPropOptimizer()
100-
} else if (optimizer === 'adadelta') {
101-
this._opt = new opt.AdaDeltaOptimizer()
102-
} else if (optimizer === 'rmspropgraves') {
103-
this._opt = new opt.RMSPropGravesOptimizer()
104-
} else if (optimizer === 'smorms3') {
105-
this._opt = new opt.SMORMS3Optimizer()
106-
} else if (optimizer === 'adamax') {
107-
this._opt = new opt.AdaMaxOptimizer()
108-
} else if (optimizer === 'nadam') {
109-
this._opt = new opt.NadamOptimizer()
92+
if (Object.keys(opt).includes(optimizer)) {
93+
this._opt = new opt[optimizer]()
11094
} else {
111-
this._opt = new opt.SGDOptimizer()
95+
this._opt = new opt.sgd()
11296
}
11397
this._opt_managers = []
11498
for (let i = 0; i < this._graph.size; i++) {

lib/model/nns/optimizer.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
export { SGDOptimizer } from './optimizer/sgd.js'
2-
export { MomentumOptimizer } from './optimizer/momentum.js'
3-
export { AdaGradOptimizer } from './optimizer/adagrad.js'
4-
export { RMSPropOptimizer } from './optimizer/rmsprop.js'
5-
export { AdaDeltaOptimizer } from './optimizer/adadelta.js'
6-
export { AdamOptimizer } from './optimizer/adam.js'
7-
export { RMSPropGravesOptimizer } from './optimizer/rmspropgraves.js'
8-
export { SMORMS3Optimizer } from './optimizer/smorms3.js'
9-
export { AdaMaxOptimizer } from './optimizer/adamax.js'
10-
export { NadamOptimizer } from './optimizer/nadam.js'
1+
export { SGDOptimizer as sgd } from './optimizer/sgd.js'
2+
export { MomentumOptimizer as momentum } from './optimizer/momentum.js'
3+
export { AdaGradOptimizer as adagrad } from './optimizer/adagrad.js'
4+
export { RMSPropOptimizer as rmsprop } from './optimizer/rmsprop.js'
5+
export { AdaDeltaOptimizer as adadelta } from './optimizer/adadelta.js'
6+
export { AdamOptimizer as adam } from './optimizer/adam.js'
7+
export { RMSPropGravesOptimizer as rmspropgraves } from './optimizer/rmspropgraves.js'
8+
export { SMORMS3Optimizer as smorms3 } from './optimizer/smorms3.js'
9+
export { AdaMaxOptimizer as adamax } from './optimizer/adamax.js'
10+
export { NadamOptimizer as nadam } from './optimizer/nadam.js'
11+
export { SantaEOptimizer as santae } from './optimizer/santae.js'
12+
export { SantaSSSOptimizer as santasss } from './optimizer/santasss.js'
13+
export { AMSGradOptimizer as amsgrad } from './optimizer/amsgrad.js'
14+
export { AdaBoundOptimizer as adabound } from './optimizer/adabound.js'
15+
export { AMSBoundOptimizer as amsbound } from './optimizer/amsbound.js'
16+
export { AdaBeliefOptimizer as adabelief } from './optimizer/adabelief.js'
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import Matrix from '../../../util/matrix.js'
2+
3+
export class AdaBeliefOptimizer {
4+
constructor(lr = 0.001, beta1 = 0.9, beta2 = 0.999) {
5+
this._learningrate = lr
6+
this._beta1 = beta1
7+
this._beta2 = beta2
8+
}
9+
10+
set learningRate(value) {
11+
this._learningrate = value
12+
}
13+
14+
manager() {
15+
const this_ = this
16+
return {
17+
get lr() {
18+
return this_._learningrate
19+
},
20+
params: {},
21+
delta(key, value) {
22+
const valueIsNumber = typeof value === 'number'
23+
if (valueIsNumber) {
24+
value = new Matrix(1, 1, value)
25+
}
26+
if (!this.params[key]) {
27+
const z = value.copy()
28+
z.fill(0)
29+
this.params[key] = { m: z.copy(), v: z, t: 1 }
30+
}
31+
this.params[key].m.broadcastOperate(value, (a, b) => a * this_._beta1 + b * (1 - this_._beta1))
32+
const mo = this.params[key].m.copy()
33+
mo.broadcastOperate(value, (a, b) => b - a)
34+
this.params[key].v.broadcastOperate(mo, (a, b) => a * this_._beta2 + (1 - this_._beta2) * b * b)
35+
const nv = 1 - this_._beta1 ** this.params[key].t
36+
const ns = 1 - this_._beta2 ** this.params[key].t
37+
const ret = this.params[key].m.copy()
38+
ret.broadcastOperate(this.params[key].v, (a, b) => (a / nv) * (this.lr / Math.sqrt(b / ns + 1.0e-12)))
39+
this.params[key].t++
40+
return valueIsNumber ? ret.toScaler() : ret
41+
},
42+
}
43+
}
44+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import Matrix from '../../../util/matrix.js'
2+
3+
export class AdaBoundOptimizer {
4+
constructor(lr = 0.001, alpha = 0.003, beta1 = 0.9, beta2 = 0.999) {
5+
this._learningrate = lr
6+
this._alpha = alpha
7+
this._beta1 = beta1
8+
this._beta2 = beta2
9+
10+
this._eta_lbound = t => this._learningrate * (1 - 1 / ((1 - beta2) * t + 1))
11+
this._eta_ubound = t => this._learningrate * (1 + 1 / ((1 - beta2) * t + 1))
12+
}
13+
14+
set learningRate(value) {
15+
this._learningrate = value
16+
}
17+
18+
manager() {
19+
const this_ = this
20+
return {
21+
get lr() {
22+
return this_._learningrate
23+
},
24+
params: {},
25+
delta(key, value) {
26+
const valueIsNumber = typeof value === 'number'
27+
if (valueIsNumber) {
28+
value = new Matrix(1, 1, value)
29+
}
30+
if (!this.params[key]) {
31+
const z = value.copy()
32+
z.fill(0)
33+
this.params[key] = { m: z.copy(), v: z, t: 1 }
34+
}
35+
this.params[key].m.broadcastOperate(value, (a, b) => a * this_._beta1 + b * (1 - this_._beta1))
36+
this.params[key].v.broadcastOperate(value, (a, b) => a * this_._beta2 + (1 - this_._beta2) * b * b)
37+
const eta_lb = this_._eta_lbound(this.params[key].t)
38+
const eta_ub = this_._eta_ubound(this.params[key].t)
39+
const eta = this.params[key].v.copy()
40+
eta.map(v => Math.min(eta_ub, Math.max(eta_lb, this_._alpha / Math.sqrt(v))))
41+
const ret = this.params[key].m.copy()
42+
ret.broadcastOperate(eta, (a, b) => (a * b) / Math.sqrt(this.params[key].t))
43+
this.params[key].t++
44+
return valueIsNumber ? ret.toScaler() : ret
45+
},
46+
}
47+
}
48+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import Matrix from '../../../util/matrix.js'
2+
3+
export class AMSBoundOptimizer {
4+
constructor(lr = 0.001, alpha = 0.003, beta1 = 0.9, beta2 = 0.999) {
5+
this._learningrate = lr
6+
this._alpha = alpha
7+
this._beta1 = beta1
8+
this._beta2 = beta2
9+
10+
this._eta_lbound = t => this._learningrate * (1 - 1 / ((1 - beta2) * t + 1))
11+
this._eta_ubound = t => this._learningrate * (1 + 1 / ((1 - beta2) * t + 1))
12+
}
13+
14+
set learningRate(value) {
15+
this._learningrate = value
16+
}
17+
18+
manager() {
19+
const this_ = this
20+
return {
21+
get lr() {
22+
return this_._learningrate
23+
},
24+
params: {},
25+
delta(key, value) {
26+
const valueIsNumber = typeof value === 'number'
27+
if (valueIsNumber) {
28+
value = new Matrix(1, 1, value)
29+
}
30+
if (!this.params[key]) {
31+
const z = value.copy()
32+
z.fill(0)
33+
this.params[key] = { m: z.copy(), v: z.copy(), vh: z, t: 1 }
34+
}
35+
this.params[key].m.broadcastOperate(value, (a, b) => a * this_._beta1 + b * (1 - this_._beta1))
36+
this.params[key].v.broadcastOperate(value, (a, b) => a * this_._beta2 + (1 - this_._beta2) * b * b)
37+
this.params[key].vh.broadcastOperate(this.params[key].v, (a, b) => Math.max(a, b))
38+
const eta_lb = this_._eta_lbound(this.params[key].t)
39+
const eta_ub = this_._eta_ubound(this.params[key].t)
40+
const eta = this.params[key].vh.copy()
41+
eta.map(v => Math.min(eta_ub, Math.max(eta_lb, this_._alpha / Math.sqrt(v))))
42+
const ret = this.params[key].m.copy()
43+
ret.broadcastOperate(eta, (a, b) => (a * b) / Math.sqrt(this.params[key].t))
44+
this.params[key].t++
45+
return valueIsNumber ? ret.toScaler() : ret
46+
},
47+
}
48+
}
49+
}

lib/model/nns/optimizer/amsgrad.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import Matrix from '../../../util/matrix.js'
2+
3+
export class AMSGradOptimizer {
4+
constructor(lr = 0.001, beta1 = 0.9, beta2 = 0.999) {
5+
this._learningrate = lr
6+
this._beta1 = beta1
7+
this._beta2 = beta2
8+
this._a = t => this._learningrate / Math.sqrt(t)
9+
}
10+
11+
set learningRate(value) {
12+
this._learningrate = value
13+
}
14+
15+
manager() {
16+
const this_ = this
17+
return {
18+
get lr() {
19+
return this_._learningrate
20+
},
21+
params: {},
22+
delta(key, value) {
23+
const valueIsNumber = typeof value === 'number'
24+
if (valueIsNumber) {
25+
value = new Matrix(1, 1, value)
26+
}
27+
if (!this.params[key]) {
28+
const z = value.copy()
29+
z.fill(0)
30+
this.params[key] = { m: z.copy(), v: z.copy(), vh: z, t: 1 }
31+
}
32+
this.params[key].m.broadcastOperate(value, (a, b) => a * this_._beta1 + b * (1 - this_._beta1))
33+
this.params[key].v.broadcastOperate(value, (a, b) => a * this_._beta2 + b ** 2 * (1 - this_._beta2))
34+
this.params[key].vh.broadcastOperate(this.params[key].v, (a, b) => Math.max(a, b))
35+
const ret = this.params[key].m.copy()
36+
const lr = this_._a(this.params[key].t)
37+
ret.broadcastOperate(this.params[key].vh, (a, b) => (lr * a) / Math.sqrt(b + 1.0e-12))
38+
this.params[key].t++
39+
return valueIsNumber ? ret.toScaler() : ret
40+
},
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)