141 lines
5.1 KiB
JavaScript
141 lines
5.1 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2019 Google LLC. All Rights Reserved.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
* =============================================================================
|
|
*/
|
|
|
|
import * as tf from '@tensorflow/tfjs-node';
|
|
import {buildModel} from "./train";
|
|
|
|
describe('buildModel', () => {
|
|
it('multihot inference', () => {
|
|
const maxLen = 10;
|
|
const vocabSize = 3;
|
|
const embeddingSize = 8;
|
|
const model = buildModel('multihot', maxLen, vocabSize, embeddingSize);
|
|
expect(model.inputs.length).toEqual(1);
|
|
expect(model.inputs[0].shape).toEqual([null, vocabSize]);
|
|
expect(model.outputs.length).toEqual(1);
|
|
expect(model.outputs[0].shape).toEqual([null, 1]);
|
|
|
|
const xs = tf.tensor2d([[0, 1, 0], [0, 0, 1]]);
|
|
const ys = model.predict(xs);
|
|
expect(ys.shape).toEqual([2, 1]);
|
|
const ysValues = ys.arraySync();
|
|
expect(ysValues[0][0]).toBeGreaterThanOrEqual(0);
|
|
expect(ysValues[0][0]).toBeLessThanOrEqual(1);
|
|
expect(ysValues[1][0]).toBeGreaterThanOrEqual(0);
|
|
expect(ysValues[1][0]).toBeLessThanOrEqual(1);
|
|
});
|
|
|
|
it('flatten training and inference', async () => {
|
|
const maxLen = 5;
|
|
const vocabSize = 3;
|
|
const embeddingSize = 8;
|
|
const model = buildModel('flatten', maxLen, vocabSize, embeddingSize);
|
|
expect(model.inputs.length).toEqual(1);
|
|
expect(model.inputs[0].shape).toEqual([null, maxLen]);
|
|
expect(model.outputs.length).toEqual(1);
|
|
expect(model.outputs[0].shape).toEqual([null, 1]);
|
|
|
|
model.compile({
|
|
loss: 'binaryCrossentropy',
|
|
optimizer: 'rmsprop',
|
|
metrics: ['acc']
|
|
});
|
|
const xs = tf.ones([2, maxLen])
|
|
const ys = tf.ones([2, 1]);
|
|
const history = await model.fit(xs, ys, {epochs: 2, batchSize: 2});
|
|
expect(history.history.loss.length).toEqual(2);
|
|
expect(history.history.acc.length).toEqual(2);
|
|
|
|
const predictOuts = model.predict(xs);
|
|
expect(predictOuts.shape).toEqual([2, 1]);
|
|
const values = predictOuts.arraySync();
|
|
expect(values[0][0]).toBeGreaterThanOrEqual(0);
|
|
expect(values[0][0]).toBeLessThanOrEqual(1);
|
|
expect(values[1][0]).toBeGreaterThanOrEqual(0);
|
|
expect(values[1][0]).toBeLessThanOrEqual(1);
|
|
});
|
|
|
|
it('cnn training and inference', async () => {
|
|
const maxLen = 5;
|
|
const vocabSize = 3;
|
|
const embeddingSize = 8;
|
|
const model = buildModel('cnn', maxLen, vocabSize, embeddingSize);
|
|
expect(model.inputs.length).toEqual(1);
|
|
expect(model.inputs[0].shape).toEqual([null, maxLen]);
|
|
expect(model.outputs.length).toEqual(1);
|
|
expect(model.outputs[0].shape).toEqual([null, 1]);
|
|
|
|
model.compile({
|
|
loss: 'binaryCrossentropy',
|
|
optimizer: 'rmsprop',
|
|
metrics: ['acc']
|
|
});
|
|
const xs = tf.ones([2, maxLen])
|
|
const ys = tf.ones([2, 1]);
|
|
const history = await model.fit(xs, ys, {epochs: 2, batchSize: 2});
|
|
expect(history.history.loss.length).toEqual(2);
|
|
expect(history.history.acc.length).toEqual(2);
|
|
|
|
const predictOuts = model.predict(xs);
|
|
expect(predictOuts.shape).toEqual([2, 1]);
|
|
const values = predictOuts.arraySync();
|
|
expect(values[0][0]).toBeGreaterThanOrEqual(0);
|
|
expect(values[0][0]).toBeLessThanOrEqual(1);
|
|
expect(values[1][0]).toBeGreaterThanOrEqual(0);
|
|
expect(values[1][0]).toBeLessThanOrEqual(1);
|
|
});
|
|
|
|
it('lstm training and inference', async () => {
|
|
const maxLen = 5;
|
|
const vocabSize = 20;
|
|
const embeddingSize = 8;
|
|
const model = buildModel('cnn', maxLen, vocabSize, embeddingSize);
|
|
expect(model.inputs.length).toEqual(1);
|
|
expect(model.inputs[0].shape).toEqual([null, maxLen]);
|
|
expect(model.outputs.length).toEqual(1);
|
|
expect(model.outputs[0].shape).toEqual([null, 1]);
|
|
|
|
model.compile({
|
|
loss: 'binaryCrossentropy',
|
|
optimizer: 'rmsprop',
|
|
metrics: ['acc']
|
|
});
|
|
const xs = tf.ones([2, maxLen])
|
|
const ys = tf.ones([2, 1]);
|
|
const history = await model.fit(xs, ys, {epochs: 2, batchSize: 2});
|
|
expect(history.history.loss.length).toEqual(2);
|
|
expect(history.history.acc.length).toEqual(2);
|
|
|
|
const predictOuts = model.predict(xs);
|
|
expect(predictOuts.shape).toEqual([2, 1]);
|
|
const values = predictOuts.arraySync();
|
|
expect(values[0][0]).toBeGreaterThanOrEqual(0);
|
|
expect(values[0][0]).toBeLessThanOrEqual(1);
|
|
expect(values[1][0]).toBeGreaterThanOrEqual(0);
|
|
expect(values[1][0]).toBeLessThanOrEqual(1);
|
|
});
|
|
|
|
it('Invalid model name leads to Error', () => {
|
|
const maxLen = 4;
|
|
const vocabSize = 3;
|
|
const embeddingSize = 8;
|
|
expect(() => buildModel('nonsensical', maxLen, vocabSize, embeddingSize))
|
|
.toThrowError('Unsupported model type: nonsensical');
|
|
});
|
|
});
|
|
|