Skip to content

Commit 3155592

Browse files
authored
Refactor and add tests (#984)
* Refactor and add tests * Update accuracy threshold in label propagation test from 0.7 to 0.6
1 parent 22bff58 commit 3155592

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+975
-175
lines changed

js/view/gan.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,14 @@ export default function (platform) {
123123
{ name: 'dis_rate', title: 'D', value: 0.5 },
124124
]) {
125125
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 })
126+
rateElms[v.name] = grd.input.number({
127+
label: v.title,
128+
name: v.name,
129+
min: 0,
130+
max: 100,
131+
step: 0.01,
132+
value: v.value,
133+
})
127134
}
128135
const batch = controller.input.number({ label: ' Batch size ', min: 1, max: 100, value: 10 })
129136
let threshold = null

tests/lib/model/categorical_naive_bayes.test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,32 @@ test('predict', () => {
3232
const acc = accuracy(y, t)
3333
expect(acc).toBeGreaterThan(0.95)
3434
})
35+
36+
test('predict fit twice', () => {
37+
const model = new CategoricalNaiveBayes()
38+
const x = [['a']]
39+
const t = []
40+
for (let i = 0; i < x.length; i++) {
41+
t[i] = 'x'
42+
}
43+
44+
model.fit(x, t)
45+
model.fit(x, t)
46+
47+
const y = model.predict([['a']])
48+
expect(y).toEqual(['x'])
49+
})
50+
51+
test('predict unknown data label', () => {
52+
const model = new CategoricalNaiveBayes()
53+
const x = [['a']]
54+
const t = []
55+
for (let i = 0; i < x.length; i++) {
56+
t[i] = 'x'
57+
}
58+
59+
model.fit(x, t)
60+
61+
const y = model.predict([['b']])
62+
expect(y).toEqual([null])
63+
})

tests/lib/model/catmull_rom.test.js

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,35 @@ test('CatmullRomSplines', () => {
2727
expect(err).toBeLessThan(0.1)
2828
})
2929

30-
test('CentripetalCatmullRomSplines', () => {
31-
const model = new CentripetalCatmullRomSplines()
32-
const x = Matrix.random(20, 1, -2, 2).value
33-
const t = []
34-
for (let i = 0; i < x.length; i++) {
35-
t[i] = Math.sin(x[i])
36-
}
37-
model.fit(x, t)
38-
39-
const y = model.predict(x)
40-
expect(y).toHaveLength(x.length)
41-
for (let i = 0; i < y.length; i++) {
42-
expect(y[i]).toBeCloseTo(t[i])
43-
}
44-
45-
const x0 = Matrix.random(100, 1, -2, 2).value
46-
const y0 = model.predict(x0)
47-
const err = rmse(y0, x0.map(Math.sin))
48-
expect(err).toBeLessThan(0.1)
30+
describe('CentripetalCatmullRomSplines', () => {
31+
test('default', () => {
32+
const model = new CentripetalCatmullRomSplines()
33+
const x = Matrix.random(20, 1, -2, 2).value
34+
const t = []
35+
for (let i = 0; i < x.length; i++) {
36+
t[i] = Math.sin(x[i])
37+
}
38+
model.fit(x, t)
39+
40+
const y = model.predict(x)
41+
expect(y).toHaveLength(x.length)
42+
for (let i = 0; i < y.length; i++) {
43+
expect(y[i]).toBeCloseTo(t[i])
44+
}
45+
46+
const x0 = Matrix.random(100, 1, -2, 2).value
47+
const y0 = model.predict(x0)
48+
const err = rmse(y0, x0.map(Math.sin))
49+
expect(err).toBeLessThan(0.1)
50+
})
51+
52+
test('predict second largest value', () => {
53+
const model = new CentripetalCatmullRomSplines()
54+
const x = [0, 2]
55+
const t = [0, 1]
56+
model.fit(x, t)
57+
58+
const y = model.predict([1])
59+
expect(y[0]).toBeCloseTo(0.5)
60+
})
4961
})
Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
import Matrix from '../../../lib/util/matrix.js'
22
import ChangeFinder from '../../../lib/model/change_finder.js'
33

4-
test('anomaly detection', () => {
5-
const model = new ChangeFinder(5)
6-
const n = 50
7-
const x = Matrix.concat(Matrix.random(n, 1, 0, 1), Matrix.random(n, 1, 10, 11)).value
8-
model.fit(x)
9-
const p = model.predict()
10-
expect(p).toHaveLength(100)
4+
describe('anomaly detection', () => {
5+
test('default', () => {
6+
const model = new ChangeFinder()
7+
const n = 50
8+
const x = Matrix.concat(Matrix.random(n, 1, 0, 1), Matrix.random(n, 1, 10, 11)).value
9+
model.fit(x)
10+
const p = model.predict()
11+
expect(p).toHaveLength(100)
12+
})
13+
14+
test('with params', () => {
15+
const model = new ChangeFinder(5)
16+
const n = 50
17+
const x = Matrix.concat(Matrix.random(n, 1, 0, 1), Matrix.random(n, 1, 10, 11)).value
18+
model.fit(x)
19+
const p = model.predict()
20+
expect(p).toHaveLength(100)
21+
})
1122
})

tests/lib/model/co_training.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,33 @@ test('semi-classifier', () => {
7777
const acc = accuracy(y, t_org)
7878
expect(acc).toBeGreaterThan(0.95)
7979
})
80+
81+
test('semi-classifier not categorized', () => {
82+
const model = new CoTraining(
83+
{
84+
fit(x, y) {},
85+
predict(x) {
86+
return x.map(v => ({ category: 0, score: 0 }))
87+
},
88+
threshold: 0.5,
89+
},
90+
{
91+
fit(x, y) {},
92+
predict(x) {
93+
return x.map(() => ({ category: 0, score: 0 }))
94+
},
95+
threshold: 0.5,
96+
}
97+
)
98+
const x = [
99+
[0, 0],
100+
[1, 1],
101+
]
102+
const t = [0, null]
103+
model.init(x, t)
104+
for (let i = 0; i < 1; i++) {
105+
model.fit()
106+
}
107+
const y = model.predict(x)
108+
expect(y).toEqual([0, null])
109+
})

tests/lib/model/confidence_weighted.test.js

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,34 @@ import { ConfidenceWeighted, SoftConfidenceWeighted } from '../../../lib/model/c
66

77
import { accuracy } from '../../../lib/evaluate/classification.js'
88

9-
test('ConfidenceWeighted', () => {
10-
const model = new ConfidenceWeighted(0.9)
11-
const x = Matrix.concat(Matrix.randn(50, 2, 0, 0.2), Matrix.randn(50, 2, 5, 0.2)).toArray()
12-
const t = []
13-
for (let i = 0; i < x.length; i++) {
14-
t[i] = Math.floor(i / 50) * 2 - 1
15-
}
16-
model.init(x, t)
17-
model.fit()
18-
const y = model.predict(x)
19-
const acc = accuracy(y, t)
20-
expect(acc).toBeGreaterThan(0.95)
9+
describe('ConfidenceWeighted', () => {
10+
test('normal eta', () => {
11+
const model = new ConfidenceWeighted(0.9)
12+
const x = Matrix.concat(Matrix.randn(50, 2, 0, 0.2), Matrix.randn(50, 2, 5, 0.2)).toArray()
13+
const t = []
14+
for (let i = 0; i < x.length; i++) {
15+
t[i] = Math.floor(i / 50) * 2 - 1
16+
}
17+
model.init(x, t)
18+
model.fit()
19+
const y = model.predict(x)
20+
const acc = accuracy(y, t)
21+
expect(acc).toBeGreaterThan(0.95)
22+
})
23+
24+
test.each([1, 0.5, 0])('eta %p', eta => {
25+
const model = new ConfidenceWeighted(eta)
26+
const x = Matrix.concat(Matrix.randn(50, 2, 0, 0.2), Matrix.randn(50, 2, 5, 0.2)).toArray()
27+
const t = []
28+
for (let i = 0; i < x.length; i++) {
29+
t[i] = Math.floor(i / 50) * 2 - 1
30+
}
31+
model.init(x, t)
32+
model.fit()
33+
const y = model.predict(x)
34+
const acc = accuracy(y, t)
35+
expect(acc).toBeCloseTo(0.5)
36+
})
2137
})
2238

2339
test.each([1, 2])('SoftConfidenceWeighted %d', version => {

tests/lib/model/crf.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,21 @@ test('fit', () => {
2020
expect(prob).toBeGreaterThan(0.4)
2121
expect(prob).toBeLessThanOrEqual(1)
2222
})
23+
24+
test('fit unknown predict label', () => {
25+
const model = new CRF()
26+
const x = [['a', 'b', 'c']]
27+
const y = [[2, 0, 1]]
28+
29+
for (let i = 0; i < 100; i++) {
30+
model.fit(x, y)
31+
}
32+
33+
const tx = [['a', 'd', 'c']]
34+
const ty = [[2, 0, 1]]
35+
const p = model.predict(tx)
36+
expect(p).toEqual(ty)
37+
const prob = model.probability(tx[0], ty[0])
38+
expect(prob).toBeGreaterThan(0.4)
39+
expect(prob).toBeLessThanOrEqual(1)
40+
})

tests/lib/model/cubic_hermite_spline.test.js

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,35 @@ import CubicHermiteSpline from '../../../lib/model/cubic_hermite_spline.js'
33

44
import { rmse } from '../../../lib/evaluate/regression.js'
55

6-
test('interpolation', () => {
7-
const model = new CubicHermiteSpline(0, 0)
8-
const x = Matrix.random(50, 1, -2, 2).value
9-
const t = []
10-
for (let i = 0; i < x.length; i++) {
11-
t[i] = Math.sin(x[i])
12-
}
13-
model.fit(x, t)
6+
describe('interpolation', () => {
7+
test('default', () => {
8+
const model = new CubicHermiteSpline(0, 0)
9+
const x = Matrix.random(50, 1, -2, 2).value
10+
const t = []
11+
for (let i = 0; i < x.length; i++) {
12+
t[i] = Math.sin(x[i])
13+
}
14+
model.fit(x, t)
1415

15-
const y = model.predict(x)
16-
expect(y).toHaveLength(x.length)
17-
for (let i = 0; i < y.length; i++) {
18-
expect(y[i]).toBeCloseTo(t[i])
19-
}
16+
const y = model.predict(x)
17+
expect(y).toHaveLength(x.length)
18+
for (let i = 0; i < y.length; i++) {
19+
expect(y[i]).toBeCloseTo(t[i])
20+
}
2021

21-
const x0 = Matrix.random(100, 1, -2, 2).value
22-
const y0 = model.predict(x0)
23-
const err = rmse(y0, x0.map(Math.sin))
24-
expect(err).toBeLessThan(0.1)
22+
const x0 = Matrix.random(100, 1, -2, 2).value
23+
const y0 = model.predict(x0)
24+
const err = rmse(y0, x0.map(Math.sin))
25+
expect(err).toBeLessThan(0.1)
26+
})
27+
28+
test('predict second largest value', () => {
29+
const model = new CubicHermiteSpline(0, 0)
30+
const x = [0, 2]
31+
const t = [0, 1]
32+
model.fit(x, t)
33+
34+
const y = model.predict([1])
35+
expect(y[0]).toBeCloseTo(0.5)
36+
})
2537
})

tests/lib/model/cubic_interpolation.test.js

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,35 @@ import CubicInterpolation from '../../../lib/model/cubic_interpolation.js'
33

44
import { rmse } from '../../../lib/evaluate/regression.js'
55

6-
test('interpolation', () => {
7-
const model = new CubicInterpolation()
8-
const x = Matrix.random(50, 1, -2, 2).value
9-
const t = []
10-
for (let i = 0; i < x.length; i++) {
11-
t[i] = Math.sin(x[i])
12-
}
13-
model.fit(x, t)
6+
describe('interpolation', () => {
7+
test('default', () => {
8+
const model = new CubicInterpolation()
9+
const x = Matrix.random(50, 1, -2, 2).value
10+
const t = []
11+
for (let i = 0; i < x.length; i++) {
12+
t[i] = Math.sin(x[i])
13+
}
14+
model.fit(x, t)
1415

15-
const y = model.predict(x)
16-
expect(y).toHaveLength(x.length)
17-
for (let i = 0; i < y.length; i++) {
18-
expect(y[i]).toBeCloseTo(t[i])
19-
}
16+
const y = model.predict(x)
17+
expect(y).toHaveLength(x.length)
18+
for (let i = 0; i < y.length; i++) {
19+
expect(y[i]).toBeCloseTo(t[i])
20+
}
2021

21-
const x0 = Matrix.random(100, 1, -2, 2).value
22-
const y0 = model.predict(x0)
23-
const err = rmse(y0, x0.map(Math.sin))
24-
expect(err).toBeLessThan(0.1)
22+
const x0 = Matrix.random(100, 1, -2, 2).value
23+
const y0 = model.predict(x0)
24+
const err = rmse(y0, x0.map(Math.sin))
25+
expect(err).toBeLessThan(0.1)
26+
})
27+
28+
test('predict second largest value', () => {
29+
const model = new CubicInterpolation()
30+
const x = [0, 2]
31+
const t = [0, 1]
32+
model.fit(x, t)
33+
34+
const y = model.predict([1])
35+
expect(y[0]).toBeCloseTo(0.5)
36+
})
2537
})

tests/lib/model/dann.test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,17 @@ describe('classification', () => {
3333
const acc = accuracy(y, t)
3434
expect(acc).toBeGreaterThan(0.95)
3535
})
36+
37+
test('same number of class choice', () => {
38+
const model = new DiscriminantAdaptiveNearestNeighbor(2)
39+
const x = [
40+
[-1, -1],
41+
[1, 1],
42+
]
43+
const t = ['a', 'b']
44+
45+
model.fit(x, t)
46+
const y = model.predict([[-1, -1]])
47+
expect(y).toEqual(['a'])
48+
})
3649
})

0 commit comments

Comments
 (0)