Skip to content

Commit 22bff58

Browse files
authored
Prevent NeuralNetworkBuilder from using D3.js node (#982)
* Prevent NeuralNetworkBuilder from using D3.js node * Refactor GANWorker to streamline learning rate input handling and improve UI element creation
1 parent d237846 commit 22bff58

File tree

14 files changed

+165
-168
lines changed

14 files changed

+165
-168
lines changed

js/controller.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ export default class Controller {
3838
return new Controller(this._platform, span)
3939
}
4040

41+
div() {
42+
const div = document.createElement('div')
43+
this._e.appendChild(div)
44+
return new Controller(this._platform, div)
45+
}
46+
4147
text(conf = {}) {
4248
if (typeof conf === 'string') {
4349
conf = { value: conf }

js/neuralnetwork_builder.js

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export default class NeuralNetworkBuilder {
154154
constructor() {
155155
this._app = Vue.createApp({})
156156
this._app.component('array_attr', arrayAttrDefinition)
157-
this._app.component('mlp_model', nnModelDefinition)
157+
this._app.component('nn_model', nnModelDefinition)
158158
this._vue = null
159159
this._name = Math.random().toString(32).substring(2)
160160
}
@@ -186,20 +186,16 @@ export default class NeuralNetworkBuilder {
186186
return this._opt && this._opt.property('value')
187187
}
188188

189-
makeHtml(r, { optimizer = false } = {}) {
190-
r.append('span').attr('id', `mlp_model_${this._name}`).append('mlp_model').attr('ref', 'layerselm')
191-
this._vue = this._app.mount(`#mlp_model_${this._name}`)
189+
makeHtml(controller, { optimizer = false } = {}) {
190+
const mdlElm = controller.span()
191+
mdlElm.element.id = `nn_model_${this._name}`
192+
const nnModelElm = document.createElement('nn_model')
193+
nnModelElm.setAttribute('ref', 'layerselm')
194+
mdlElm.element.append(nnModelElm)
195+
this._vue = this._app.mount(`#nn_model_${this._name}`)
192196
if (optimizer) {
193-
r.append('span').text(' Optimizer ')
194-
this._opt = r.append('select').attr('name', 'optimizer')
195-
this._opt
196-
.selectAll('option')
197-
.data(Object.keys(opt))
198-
.enter()
199-
.append('option')
200-
.property('value', d => d)
201-
.text(d => d)
202-
this._opt.property('value', 'adam')
197+
const optElm = controller.span()
198+
optElm.select({ label: ' Optimizer ', values: Object.keys(opt), value: 'adam' })
203199
}
204200
}
205201
}

js/view/a2c.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export default function (platform) {
7272
}
7373

7474
controller.text(' Hidden Layers ')
75-
builder.makeHtml(platform.setting.ml.configElement, { optimizer: true })
75+
builder.makeHtml(controller, { optimizer: true })
7676
agent = new A2CCBAgent(platform, resolution, builder.layers, builder.optimizer, use_worker, () => {
7777
readyNet = true
7878
setTimeout(() => {

js/view/autoencoder.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export default function (platform) {
103103
rdim = controller.input.number({ label: ' Size ', min: 1, max: 100, value: 10 })
104104
}
105105
const builder = new NeuralNetworkBuilder()
106-
builder.makeHtml(platform.setting.ml.configElement, { optimizer: true })
106+
builder.makeHtml(controller, { optimizer: true })
107107
const slbConf = controller.stepLoopButtons().init(done => {
108108
platform.init()
109109
if (platform.datas.length === 0) {

js/view/dqn.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export default function (platform) {
8585
}
8686

8787
controller.text(' Hidden Layers ')
88-
builder.makeHtml(platform.setting.ml.configElement, { optimizer: true })
88+
builder.makeHtml(controller, { optimizer: true })
8989
agent = new DQNCBAgent(platform, resolution, builder.layers, builder.optimizer, use_worker, () => {
9090
readyNet = true
9191
setTimeout(() => {

js/view/gan.js

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ class GANWorker extends BaseWorker {
3838
}
3939

4040
export default function (platform) {
41-
const elm = platform.setting.ml.configElement
4241
platform.setting.ml.usage =
4342
'Click and add data point. Next, click "Initialize". Finally, click "Fit" button repeatedly.'
4443
const controller = new Controller(platform)
@@ -51,8 +50,8 @@ export default function (platform) {
5150
if (platform.datas.length === 0) {
5251
return
5352
}
54-
const gen_rate = +elm.select('[name=gen_rate]').property('value')
55-
const dis_rate = +elm.select('[name=dis_rate]').property('value')
53+
const gen_rate = rateElms.gen_rate.value
54+
const dis_rate = rateElms.dis_rate.value
5655

5756
const tx = platform.trainInput
5857
const ty = platform.trainOutput
@@ -96,12 +95,13 @@ export default function (platform) {
9695
}
9796
const noiseDim = controller.input.number({ label: 'Noise dim', min: 1, max: 100, value: 5 })
9897
controller.text('Hidden size ')
99-
const ganHiddensDiv = elm.append('div').style('display', 'inline-block')
100-
const gHiddensDiv = ganHiddensDiv.append('div')
101-
gHiddensDiv.append('span').text('G')
98+
const ganHiddensDiv = controller.div()
99+
ganHiddensDiv.element.style.display = 'inline-block'
100+
const gHiddensDiv = ganHiddensDiv.div()
101+
gHiddensDiv.text('G')
102102
gbuilder.makeHtml(gHiddensDiv, { optimizer: true })
103-
const dHiddensDiv = ganHiddensDiv.append('div')
104-
dHiddensDiv.append('span').text('D')
103+
const dHiddensDiv = ganHiddensDiv.div()
104+
dHiddensDiv.text('D')
105105
dbuilder.makeHtml(dHiddensDiv, { optimizer: true })
106106
const slbConf = controller.stepLoopButtons().init(done => {
107107
const g_hidden = gbuilder.layers
@@ -115,20 +115,15 @@ export default function (platform) {
115115
})
116116
const iteration = controller.select({ label: ' Iteration ', values: [1, 10, 100, 1000, 10000] })
117117
controller.text('Learning rate ')
118-
const ganRatesDiv = elm.append('div').style('display', 'inline-block')
118+
const ganRatesDiv = controller.div()
119+
ganRatesDiv.element.style.display = 'inline-block'
120+
const rateElms = {}
119121
for (const v of [
120122
{ name: 'gen_rate', title: 'G', value: 0.01 },
121123
{ name: 'dis_rate', title: 'D', value: 0.5 },
122124
]) {
123-
const grd = ganRatesDiv.append('div')
124-
grd.append('span').text(v.title)
125-
grd.append('input')
126-
.attr('type', 'number')
127-
.attr('name', v.name)
128-
.attr('min', 0)
129-
.attr('max', 100)
130-
.attr('step', 0.01)
131-
.attr('value', v.value)
125+
const grd = ganRatesDiv.div()
126+
rateElms[v.name] = grd.input.number({ label: v.title, name: v.name, min: 0, max: 100, step: 0.01, value: v.value })
132127
}
133128
const batch = controller.input.number({ label: ' Batch size ', min: 1, max: 100, value: 10 })
134129
let threshold = null

js/view/neuralnetwork.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export default function (platform) {
9292
width = controller.input.number({ label: 'window width', min: 1, max: 1000, value: 20 })
9393
}
9494
controller.text(' Hidden Layers ')
95-
builder.makeHtml(platform.setting.ml.configElement, { optimizer: true })
95+
builder.makeHtml(controller, { optimizer: true })
9696
const slbConf = controller.stepLoopButtons().init(done => {
9797
if (platform.datas.length === 0) {
9898
done()

js/view/vae.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export default function (platform) {
8585
noiseDim = controller.input.number({ label: 'Noise dim', min: 1, max: 100, value: 5 })
8686
}
8787
const builder = new NeuralNetworkBuilder()
88-
builder.makeHtml(platform.setting.ml.configElement, { optimizer: true })
88+
builder.makeHtml(controller, { optimizer: true })
8989
const slbConf = controller.stepLoopButtons().init(done => {
9090
if (platform.datas.length === 0) {
9191
done()

tests/gui/view/a2c.test.js

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ describe('reinforcement learning', () => {
55
let page
66
beforeEach(async () => {
77
page = await getPage()
8-
const dataSelectBox = await page.waitForSelector('#ml_selector dl:first-child dd:nth-child(2) select')
8+
const dataSelectBox = page.locator('#ml_selector dl:first-child dd:nth-child(2) select')
99
await dataSelectBox.selectOption('')
10-
const taskSelectBox = await page.waitForSelector('#ml_selector dl:first-child dd:nth-child(5) select')
10+
const taskSelectBox = page.locator('#ml_selector dl:first-child dd:nth-child(5) select')
1111
await taskSelectBox.selectOption('MD')
12-
const envSelectBox = await page.waitForSelector('#ml_selector #task_menu select')
12+
const envSelectBox = page.locator('#ml_selector #task_menu select')
1313
await envSelectBox.selectOption('grid')
14-
const modelSelectBox = await page.waitForSelector('#ml_selector .model_selection #mlDisp')
14+
const modelSelectBox = page.locator('#ml_selector .model_selection #mlDisp')
1515
await modelSelectBox.selectOption('a2c')
1616
})
1717

@@ -20,26 +20,26 @@ describe('reinforcement learning', () => {
2020
})
2121

2222
test('initialize', async () => {
23-
const methodMenu = await page.waitForSelector('#ml_selector #method_menu')
24-
const buttons = await methodMenu.waitForSelector('.buttons')
25-
26-
const method = await buttons.waitForSelector('select:nth-of-type(1)')
27-
await expect((await method.getProperty('value')).jsonValue()).resolves.toBe('full')
28-
const rate = await buttons.waitForSelector('input:nth-of-type(3)')
29-
await expect(rate.getAttribute('value')).resolves.toBe('0.001')
30-
const size = await buttons.waitForSelector('input:nth-of-type(4)')
31-
await expect(size.getAttribute('value')).resolves.toBe('10')
23+
const methodMenu = page.locator('#ml_selector #method_menu')
24+
const buttons = methodMenu.locator('.buttons')
25+
26+
const method = buttons.locator('select:nth-of-type(1)').nth(0)
27+
await expect(method.inputValue()).resolves.toBe('full')
28+
const rate = buttons.locator('input:nth-of-type(3)')
29+
await expect(rate.inputValue()).resolves.toBe('0.001')
30+
const size = buttons.locator('input:nth-of-type(4)')
31+
await expect(size.inputValue()).resolves.toBe('10')
3232
})
3333

3434
test('learn', async () => {
35-
const methodMenu = await page.waitForSelector('#ml_selector #method_menu')
36-
const buttons = await methodMenu.waitForSelector('.buttons')
35+
const methodMenu = page.locator('#ml_selector #method_menu')
36+
const buttons = methodMenu.locator('.buttons')
3737

38-
const step = await page.waitForSelector('[name=step]')
38+
const step = page.locator('[name=step]')
3939
await expect(step.textContent()).resolves.toBe(' Step: 0')
4040

41-
const calcButton = await buttons.waitForSelector('input[value=Step]')
42-
await calcButton.evaluate(el => el.click())
41+
const calcButton = buttons.locator('input[value=Step]')
42+
await calcButton.dispatchEvent('click')
4343

4444
await expect(step.textContent()).resolves.toBe(' Step: 1')
4545
})

tests/gui/view/autoencoder.test.js

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ describe('clustering', () => {
55
let page
66
beforeEach(async () => {
77
page = await getPage()
8-
const taskSelectBox = await page.waitForSelector('#ml_selector dl:first-child dd:nth-child(5) select')
8+
const taskSelectBox = page.locator('#ml_selector dl:first-child dd:nth-child(5) select')
99
await taskSelectBox.selectOption('CT')
10-
const modelSelectBox = await page.waitForSelector('#ml_selector .model_selection #mlDisp')
10+
const modelSelectBox = page.locator('#ml_selector .model_selection #mlDisp')
1111
await modelSelectBox.selectOption('autoencoder')
1212
})
1313

@@ -16,35 +16,35 @@ describe('clustering', () => {
1616
})
1717

1818
test('initialize', async () => {
19-
const methodMenu = await page.waitForSelector('#ml_selector #method_menu')
20-
const buttons = await methodMenu.waitForSelector('.buttons')
21-
22-
const size = await buttons.waitForSelector('input:nth-of-type(1)')
23-
await expect(size.getAttribute('value')).resolves.toBe('10')
24-
const iteration = await buttons.waitForSelector(':scope > select:nth-of-type(2)')
25-
await expect((await iteration.getProperty('value')).jsonValue()).resolves.toBe('1')
26-
const rate = await buttons.waitForSelector(':scope > input:nth-of-type(3)')
27-
await expect(rate.getAttribute('value')).resolves.toBe('0.001')
28-
const batch = await buttons.waitForSelector(':scope > input:nth-of-type(4)')
29-
await expect(batch.getAttribute('value')).resolves.toBe('10')
30-
const rho = await buttons.waitForSelector(':scope > input:nth-of-type(5)')
31-
await expect(rho.getAttribute('value')).resolves.toBe('0.02')
19+
const methodMenu = page.locator('#ml_selector #method_menu')
20+
const buttons = methodMenu.locator('.buttons')
21+
22+
const size = buttons.locator('input:nth-of-type(1)').first()
23+
await expect(size.inputValue()).resolves.toBe('10')
24+
const iteration = buttons.locator('select').nth(3)
25+
await expect(iteration.inputValue()).resolves.toBe('1')
26+
const rate = buttons.locator(':scope > input:nth-of-type(3)')
27+
await expect(rate.inputValue()).resolves.toBe('0.001')
28+
const batch = buttons.locator(':scope > input:nth-of-type(4)')
29+
await expect(batch.inputValue()).resolves.toBe('10')
30+
const rho = buttons.locator(':scope > input:nth-of-type(5)')
31+
await expect(rho.inputValue()).resolves.toBe('0.02')
3232
})
3333

3434
test('learn', async () => {
35-
const methodMenu = await page.waitForSelector('#ml_selector #method_menu')
36-
const buttons = await methodMenu.waitForSelector('.buttons')
35+
const methodMenu = page.locator('#ml_selector #method_menu')
36+
const buttons = methodMenu.locator('.buttons')
3737

38-
const epoch = await buttons.waitForSelector('[name=epoch]')
38+
const epoch = buttons.locator('[name=epoch]')
3939
await expect(epoch.textContent()).resolves.toBe('0')
40-
const methodFooter = await page.waitForSelector('#method_footer', { state: 'attached' })
40+
const methodFooter = page.locator('#method_footer', { state: 'attached' })
4141
await expect(methodFooter.textContent()).resolves.toBe('')
4242

43-
const initButton = await buttons.waitForSelector('input[value=Initialize]')
44-
await initButton.evaluate(el => el.click())
45-
const stepButton = await buttons.waitForSelector('input[value=Step]:enabled')
46-
await stepButton.evaluate(el => el.click())
47-
await buttons.waitForSelector('input[value=Step]:enabled')
43+
const initButton = buttons.locator('input[value=Initialize]')
44+
await initButton.dispatchEvent('click')
45+
const stepButton = buttons.locator('input[value=Step]:enabled')
46+
await stepButton.dispatchEvent('click')
47+
await buttons.locator('input[value=Step]:enabled').waitFor()
4848

4949
await expect(epoch.textContent()).resolves.toBe('1')
5050
await expect(methodFooter.textContent()).resolves.toMatch(/^loss/)

0 commit comments

Comments
 (0)