Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions tests/lib/model/abod.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,27 @@ describe('anomaly detection', () => {
expect(y[i]).toBe(true)
}
})

test('LB-ABOD many outliers', () => {
const model = new LBABOD(10, 2)
const x = [
[-0.5, 0],
[-1.0, 0.5],
[0.5, -0.1],
[0.4, -0.2],
[-0.6, -0.8],
[10, 10],
[-10, 10],
[10, -10],
]
const y = model.predict(x)
for (let i = 0; i < y.length - 3; i++) {
expect(y[i]).toBe(false)
}
let c = 0
for (let i = y.length - 3; i < y.length; i++) {
if (y[i]) c++
}
expect(c).toBe(2)
})
})
15 changes: 15 additions & 0 deletions tests/lib/model/adamenn.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,18 @@ test('predict', () => {
const acc = accuracy(y, t)
expect(acc).toBeGreaterThan(0.9)
})

test('specify params', () => {
const model = new ADAMENN(7, 3, 10, 3, 2, 0.5)
const x = Matrix.concat(Matrix.randn(50, 2, 0, 0.2), Matrix.randn(50, 2, 5, 0.2)).toArray()
const t = []
for (let i = 0; i < x.length; i++) {
t[i] = String.fromCharCode('a'.charCodeAt(0) + Math.floor(i / 50))
}

model.fit(x, t)
const y = model.predict(x)
expect(y).toHaveLength(x.length)
const acc = accuracy(y, t)
expect(acc).toBeGreaterThan(0.9)
})
4 changes: 4 additions & 0 deletions tests/lib/model/association_analysis.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ test('items', () => {
const items = [...model.items()].flat()
items.sort()
expect(items).toEqual(['c', 'data', 'image', 'java', 'net', 'web'])
expect(model.items(6)).toHaveLength(0)
})

test('items large support', () => {
Expand Down Expand Up @@ -51,6 +52,7 @@ test('support', () => {
model.fit(data)
expect(model.support('data')).toBeCloseTo(4 / 7)
expect(model.support('data', 'image')).toBeCloseTo(2 / 7)
expect(model.support('hoge')).toBe(0)
})

test('confidence', () => {
Expand All @@ -67,6 +69,8 @@ test('confidence', () => {
]
model.fit(data)
expect(model.confidence('java', 'c')).toBeCloseTo(0.4)
expect(model.confidence('net', 'web')).toBe(0)
expect(model.confidence('hoge', 'data')).toBe(0)
})

test('lift', () => {
Expand Down
4 changes: 3 additions & 1 deletion tests/lib/model/automatic_thresholding.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ test('clustering', () => {
const n = 50
const x = Matrix.concat(Matrix.randn(n, 1, 0, 0.1), Matrix.randn(n, 1, 5, 0.1)).value

model.fit(x)
for (let i = 0; i < 2; i++) {
model.fit(x)
}
const y = model.predict(x)
expect(y).toHaveLength(x.length)

Expand Down
66 changes: 43 additions & 23 deletions tests/lib/model/average_shifted_histogram.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,49 @@ import AverageShiftedHistogram from '../../../lib/model/average_shifted_histogra

import { correlation } from '../../../lib/evaluate/regression.js'

test('density estimation', () => {
const model = new AverageShiftedHistogram({ size: 0.1 }, 10)
const n = 500
const x = Matrix.concat(Matrix.randn(n, 2, 0, 0.1), Matrix.randn(n, 2, 5, 0.1)).toArray()
model.fit(x)
const y = model.predict(x)
expect(y).toHaveLength(x.length)
describe('density estimation', () => {
test('size', () => {
const model = new AverageShiftedHistogram({ size: 0.1 }, 10)
const n = 500
const x = Matrix.concat(Matrix.randn(n, 2, 0, 0.1), Matrix.randn(n, 2, 5, 0.1)).toArray()
model.fit(x)
const y = model.predict(x)
expect(y).toHaveLength(x.length)

const p = []
for (let i = 0; i < x.length; i++) {
const p1 = Math.exp(-x[i].reduce((s, v) => s + v ** 2, 0) / (2 * 0.1)) / (2 * Math.PI * 0.1)
const p2 = Math.exp(-x[i].reduce((s, v) => s + (v - 5) ** 2, 0) / (2 * 0.1)) / (2 * Math.PI * 0.1)
p[i] = (p1 + p2) / 2
}
const corr = correlation(y, p)
expect(corr).toBeGreaterThan(0.9)
})
const p = []
for (let i = 0; i < x.length; i++) {
const p1 = Math.exp(-x[i].reduce((s, v) => s + v ** 2, 0) / (2 * 0.1)) / (2 * Math.PI * 0.1)
const p2 = Math.exp(-x[i].reduce((s, v) => s + (v - 5) ** 2, 0) / (2 * 0.1)) / (2 * Math.PI * 0.1)
p[i] = (p1 + p2) / 2
}
const corr = correlation(y, p)
expect(corr).toBeGreaterThan(0.9)
})

test('domain', () => {
const model = new AverageShiftedHistogram(
{
domain: [
[-1, 1],
[-1, 1],
],
size: 0.1,
},
10
)
const n = 5000
const x = Matrix.random(n, 2, -1, 1).toArray()
model.fit(x)
const y = model.predict(x)
expect(y).toHaveLength(x.length)
})

test('density estimation outsize', () => {
const model = new AverageShiftedHistogram({ size: 0.1 }, 10)
const n = 500
const x = Matrix.randn(n, 2, 0, 0.1).toArray()
model.fit(x)
const y = model.predict([[-10, -10]])
expect(y[0]).toBe(0)
test('outsize', () => {
const model = new AverageShiftedHistogram({ size: 0.1 }, 10)
const n = 500
const x = Matrix.randn(n, 2, 0, 0.1).toArray()
model.fit(x)
const y = model.predict([[-10, -10]])
expect(y[0]).toBe(0)
})
})
21 changes: 21 additions & 0 deletions tests/lib/model/cast.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,24 @@ test('cast', () => {
const ri = randIndex(y, t)
expect(ri).toBeGreaterThan(0.9)
})

test('large t', () => {
const model = new CAST(0.9)
const n = 50
const x = Matrix.concat(
Matrix.concat(Matrix.randn(n, 2, 0, 0.1), Matrix.randn(n, 2, 5, 0.1)),
Matrix.randn(n, 2, [0, 5], 0.1)
).toArray()

model.fit(x)
expect(model.size).toBeGreaterThanOrEqual(3)
const y = model.predict(x)
expect(y).toHaveLength(x.length)

const t = []
for (let i = 0; i < x.length; i++) {
t[i] = Math.floor(i / n)
}
const ri = randIndex(y, t)
expect(ri).toBeGreaterThan(0.7)
})
64 changes: 64 additions & 0 deletions tests/lib/model/ensemble_binary.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,38 @@ describe('oneone', () => {
expect(acc).toBeGreaterThan(0.95)
})

test('predict returns 1d array', () => {
const model = new EnsembleBinaryModel(function () {
this.init = (x, y) => {
this.x = Matrix.fromArray(x)
this.y = Matrix.fromArray(y)
}
this.fit = () => {
this.w = this.x.tDot(this.x).solve(this.x.tDot(this.y))
this.b = Matrix.sub(this.x.dot(this.w), this.y).mean(0)
}
this.predict = x => {
const p = Matrix.fromArray(x).dot(this.w)
p.sub(this.b)
return p.value
}
}, 'oneone')
const n = 100
const x = Matrix.concat(
Matrix.concat(Matrix.randn(n, 2, 0, 0.2), Matrix.randn(n, 2, 5, 0.2)),
Matrix.randn(n, 2, [-1, 4], 0.2)
).toArray()
const t = []
for (let i = 0; i < x.length; i++) {
t[i] = String.fromCharCode('a'.charCodeAt(0) + Math.floor(i / n))
}
model.init(x, t)
model.fit()
const y = model.predict(x)
const acc = accuracy(y, t)
expect(acc).toBeGreaterThan(0.95)
})

test('construct with classes', () => {
const model = new EnsembleBinaryModel(
function () {
Expand Down Expand Up @@ -202,6 +234,38 @@ describe('onerest', () => {
expect(acc).toBeGreaterThan(0.95)
})

test('predict returns 1d array', () => {
const model = new EnsembleBinaryModel(function () {
this.init = (x, y) => {
this.x = Matrix.fromArray(x)
this.y = Matrix.fromArray(y)
}
this.fit = () => {
this.w = this.x.tDot(this.x).solve(this.x.tDot(this.y))
this.b = Matrix.sub(this.x.dot(this.w), this.y).mean(0)
}
this.predict = x => {
const p = Matrix.fromArray(x).dot(this.w)
p.sub(this.b)
return p.value
}
}, 'onerest')
const n = 100
const x = Matrix.concat(
Matrix.concat(Matrix.randn(n, 2, 0, 0.2), Matrix.randn(n, 2, 5, 0.2)),
Matrix.randn(n, 2, [-1, 4], 0.2)
).toArray()
const t = []
for (let i = 0; i < x.length; i++) {
t[i] = String.fromCharCode('a'.charCodeAt(0) + Math.floor(i / n))
}
model.init(x, t)
model.fit()
const y = model.predict(x)
const acc = accuracy(y, t)
expect(acc).toBeGreaterThan(0.95)
})

test('constructo with classes', () => {
const model = new EnsembleBinaryModel(
function () {
Expand Down
2 changes: 1 addition & 1 deletion tests/lib/model/huber_regression.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import HuberRegression from '../../../lib/model/huber_regression.js'
import { rmse } from '../../../lib/evaluate/regression.js'

describe.each([undefined, 'rls', 'gd'])('fit %s', method => {
test.each([undefined, 1])('e: %p', e => {
test.each([undefined, 1.0e-5])('e: %p', e => {
const model = new HuberRegression(e, method)
const x = Matrix.randn(50, 2, 0, 5).toArray()
const t = []
Expand Down
48 changes: 48 additions & 0 deletions tests/lib/model/isodata.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,54 @@ test('clustering', () => {
expect(ri).toBeGreaterThan(0.9)
})

test('large init k', () => {
const model = new ISODATA(100, 1, 20, 10, 1, 0.8)
const n = 50
const x = Matrix.concat(
Matrix.concat(Matrix.randn(n, 2, 0, 0.1), Matrix.randn(n, 2, 5, 0.1)),
Matrix.randn(n, 2, [-2, 5], 0.1)
).toArray()

model.init(x)
for (let i = 0; i < 100; i++) {
model.fit(x)
}
expect(model.size).toBeGreaterThanOrEqual(3)
const y = model.predict(x)
expect(y).toHaveLength(x.length)

const t = []
for (let i = 0; i < x.length; i++) {
t[i] = Math.floor(i / n)
}
const ri = randIndex(y, t)
expect(ri).toBeGreaterThan(0.75)
})

test('small init k', () => {
const model = new ISODATA(1, 3, 20, 10, 0.1, 0.8)
const n = 50
const x = Matrix.concat(
Matrix.concat(Matrix.randn(n, 2, 0, 0.1), Matrix.randn(n, 2, 5, 0.1)),
Matrix.randn(n, 2, [-2, 5], 0.1)
).toArray()

model.init(x)
for (let i = 0; i < 10; i++) {
model.fit(x)
}
expect(model.size).toBeGreaterThanOrEqual(3)
const y = model.predict(x)
expect(y).toHaveLength(x.length)

const t = []
for (let i = 0; i < x.length; i++) {
t[i] = Math.floor(i / n)
}
const ri = randIndex(y, t)
expect(ri).toBeGreaterThan(0.75)
})

test('predict before fit', () => {
const model = new ISODATA(5, 1, 20, 10, 1, 0.8)
const x = Matrix.randn(50, 2, 0, 0.1).toArray()
Expand Down
14 changes: 14 additions & 0 deletions tests/lib/model/kmeans.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ describe.each([KMeans, KMeanspp, KMedoids, KMedians])('%p', methodCls => {
expect(ri).toBeGreaterThan(0.9)
})

test('fit before init', () => {
const model = new methodCls()
const x = Matrix.randn(50, 2, 0, 0.1).toArray()
const d = model.fit(x)
expect(d).toBe(0)
})

test('predict before fit', () => {
const model = new methodCls()
const x = Matrix.randn(50, 2, 0, 0.1).toArray()
Expand Down Expand Up @@ -61,6 +68,13 @@ describe('semi-classifier', () => {
expect(acc).toBeGreaterThan(0.95)
})

test('fit before init', () => {
const model = new SemiSupervisedKMeansModel()
const x = Matrix.randn(50, 2, 0, 0.1).toArray()
const d = model.fit(x, Array(50).fill(0))
expect(d).toBe(0)
})

test('predict before fit', () => {
const model = new SemiSupervisedKMeansModel()
const x = Matrix.randn(50, 2, 0, 0.1).toArray()
Expand Down
15 changes: 15 additions & 0 deletions tests/lib/model/kmodes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,21 @@ describe('predict', () => {
expect(model.size).toBe(0)
})

test('fit before init', () => {
const model = new KModes()
const x = []
for (let i = 0; i < 50n; i++) {
const xi = []
for (let k = 0; k < 5; k++) {
const r = Math.floor(Math.random() * 10)
xi[k] = String.fromCharCode('a'.charCodeAt(0) + r)
}
x.push(xi)
}
const d = model.fit(x)
expect(d).toBe(0)
})

test('before fit', () => {
const model = new KModes()
const x = []
Expand Down
Loading