1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
19 | return new (P || (P = Promise))(function (resolve, reject) {
|
20 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
21 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
22 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
23 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
24 | });
|
25 | };
|
26 | var __generator = (this && this.__generator) || function (thisArg, body) {
|
27 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
28 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
29 | function verb(n) { return function (v) { return step([n, v]); }; }
|
30 | function step(op) {
|
31 | if (f) throw new TypeError("Generator is already executing.");
|
32 | while (_) try {
|
33 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
34 | if (y = 0, t) op = [op[0] & 2, t.value];
|
35 | switch (op[0]) {
|
36 | case 0: case 1: t = op; break;
|
37 | case 4: _.label++; return { value: op[1], done: false };
|
38 | case 5: _.label++; y = op[1]; op = [0]; continue;
|
39 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
40 | default:
|
41 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
42 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
43 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
44 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
45 | if (t[2]) _.ops.pop();
|
46 | _.trys.pop(); continue;
|
47 | }
|
48 | op = body.call(thisArg, _);
|
49 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
50 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
51 | }
|
52 | };
|
53 | var _this = this;
|
54 | Object.defineProperty(exports, "__esModule", { value: true });
|
55 | var tf = require("@tensorflow/tfjs");
|
56 | var callbacks_1 = require("./callbacks");
|
57 | describe('progbarLogger', function () {
|
58 |
|
59 | var FakeProgbar = (function () {
|
60 | function FakeProgbar(specs, config) {
|
61 | this.specs = specs;
|
62 | this.config = config;
|
63 | this.tickConfigs = [];
|
64 | }
|
65 | FakeProgbar.prototype.tick = function (tickConfig) {
|
66 | this.tickConfigs.push(tickConfig);
|
67 | };
|
68 | return FakeProgbar;
|
69 | }());
|
70 | var originalStderrColumns;
|
71 | beforeEach(function () {
|
72 |
|
73 | originalStderrColumns = process.stderr.columns;
|
74 | process.stderr.columns = 100;
|
75 | });
|
76 | afterEach(function () {
|
77 | process.stderr.columns = originalStderrColumns;
|
78 | });
|
79 | it('Model.fit with loss, no metric, no validation, verobse = 1', function () { return __awaiter(_this, void 0, void 0, function () {
|
80 | var fakeProgbars, consoleMessages, model, numSamples, epochs, batchSize, xs, ys, _i, fakeProgbars_1, fakeProgbar, tickConfigs, i;
|
81 | return __generator(this, function (_a) {
|
82 | switch (_a.label) {
|
83 | case 0:
|
84 | fakeProgbars = [];
|
85 | spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
86 | .and.callFake(function (specs, config) {
|
87 | var fakeProgbar = new FakeProgbar(specs, config);
|
88 | fakeProgbars.push(fakeProgbar);
|
89 | return fakeProgbar;
|
90 | });
|
91 | consoleMessages = [];
|
92 | spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
93 | consoleMessages.push(message);
|
94 | });
|
95 | model = tf.sequential();
|
96 | model.add(tf.layers.dense({ units: 10, inputShape: [8], activation: 'relu' }));
|
97 | model.add(tf.layers.dense({ units: 1 }));
|
98 | model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' });
|
99 | numSamples = 14;
|
100 | epochs = 3;
|
101 | batchSize = 8;
|
102 | xs = tf.randomNormal([numSamples, 8]);
|
103 | ys = tf.randomNormal([numSamples, 1]);
|
104 | return [4 , model.fit(xs, ys, { epochs: epochs, batchSize: batchSize, verbose: 1 })];
|
105 | case 1:
|
106 | _a.sent();
|
107 |
|
108 | expect(fakeProgbars.length).toEqual(3);
|
109 | for (_i = 0, fakeProgbars_1 = fakeProgbars; _i < fakeProgbars_1.length; _i++) {
|
110 | fakeProgbar = fakeProgbars_1[_i];
|
111 | tickConfigs = fakeProgbar.tickConfigs;
|
112 |
|
113 |
|
114 | expect(tickConfigs.length).toEqual(3);
|
115 | for (i = 0; i < 2; ++i) {
|
116 | expect(Object.keys(tickConfigs[i])).toEqual([
|
117 | 'placeholderForLossesAndMetrics'
|
118 | ]);
|
119 | expect(tickConfigs[i]['placeholderForLossesAndMetrics'])
|
120 | .toMatch(/^loss=.*/);
|
121 | }
|
122 | expect(tickConfigs[2]).toEqual({ placeholderForLossesAndMetrics: '' });
|
123 | }
|
124 | expect(consoleMessages.length).toEqual(6);
|
125 | expect(consoleMessages[0]).toEqual('Epoch 1 / 3');
|
126 | expect(consoleMessages[1]).toMatch(/.*ms .*us\/step - loss=.*/);
|
127 | expect(consoleMessages[2]).toEqual('Epoch 2 / 3');
|
128 | expect(consoleMessages[3]).toMatch(/.*ms .*us\/step - loss=.*/);
|
129 | expect(consoleMessages[4]).toEqual('Epoch 3 / 3');
|
130 | expect(consoleMessages[5]).toMatch(/.*ms .*us\/step - loss=.*/);
|
131 | return [2 ];
|
132 | }
|
133 | });
|
134 | }); });
|
135 | it('Model.fit with loss, metric and validation, verbose = 2', function () { return __awaiter(_this, void 0, void 0, function () {
|
136 | var fakeProgbars, consoleMessages, model, numSamples, epochs, batchSize, validationSplit, xs, ys, _i, fakeProgbars_2, fakeProgbar, tickConfigs, i;
|
137 | return __generator(this, function (_a) {
|
138 | switch (_a.label) {
|
139 | case 0:
|
140 | fakeProgbars = [];
|
141 | spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
142 | .and.callFake(function (specs, config) {
|
143 | var fakeProgbar = new FakeProgbar(specs, config);
|
144 | fakeProgbars.push(fakeProgbar);
|
145 | return fakeProgbar;
|
146 | });
|
147 | consoleMessages = [];
|
148 | spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
149 | consoleMessages.push(message);
|
150 | });
|
151 | model = tf.sequential();
|
152 | model.add(tf.layers.dense({ units: 10, inputShape: [8], activation: 'relu' }));
|
153 | model.add(tf.layers.dense({ units: 1 }));
|
154 | model.compile({ loss: 'meanSquaredError', optimizer: 'sgd', metrics: ['acc'] });
|
155 | numSamples = 40;
|
156 | epochs = 2;
|
157 | batchSize = 8;
|
158 | validationSplit = 0.15;
|
159 | xs = tf.randomNormal([numSamples, 8]);
|
160 | ys = tf.randomNormal([numSamples, 1]);
|
161 | return [4 , model.fit(xs, ys, { epochs: epochs, batchSize: batchSize, validationSplit: validationSplit, verbose: 2 })];
|
162 | case 1:
|
163 | _a.sent();
|
164 |
|
165 | expect(fakeProgbars.length).toEqual(2);
|
166 | for (_i = 0, fakeProgbars_2 = fakeProgbars; _i < fakeProgbars_2.length; _i++) {
|
167 | fakeProgbar = fakeProgbars_2[_i];
|
168 | tickConfigs = fakeProgbar.tickConfigs;
|
169 |
|
170 |
|
171 | expect(tickConfigs.length).toEqual(6);
|
172 | for (i = 0; i < 5; ++i) {
|
173 | expect(Object.keys(tickConfigs[i])).toEqual([
|
174 | 'placeholderForLossesAndMetrics'
|
175 | ]);
|
176 | expect(tickConfigs[i]['placeholderForLossesAndMetrics'])
|
177 | .toMatch(/^acc=.* loss=.*/);
|
178 | }
|
179 | expect(tickConfigs[5]).toEqual({ placeholderForLossesAndMetrics: '' });
|
180 | }
|
181 | expect(consoleMessages.length).toEqual(4);
|
182 | expect(consoleMessages[0]).toEqual('Epoch 1 / 2');
|
183 | expect(consoleMessages[1])
|
184 | .toMatch(/.*ms .*us\/step - acc=.* loss=.* val_acc=.* val_loss=.*/);
|
185 | expect(consoleMessages[2]).toEqual('Epoch 2 / 2');
|
186 | expect(consoleMessages[3])
|
187 | .toMatch(/.*ms .*us\/step - acc=.* loss=.* val_acc=.* val_loss=.*/);
|
188 | return [2 ];
|
189 | }
|
190 | });
|
191 | }); });
|
192 | it('Model.fit does not create ProgbarLogger if verbose is 0', function () { return __awaiter(_this, void 0, void 0, function () {
|
193 | var fakeProgbars, consoleMessages, model, numSamples, epochs, batchSize, validationSplit, xs, ys;
|
194 | return __generator(this, function (_a) {
|
195 | switch (_a.label) {
|
196 | case 0:
|
197 | fakeProgbars = [];
|
198 | spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
199 | .and.callFake(function (specs, config) {
|
200 | var fakeProgbar = new FakeProgbar(specs, config);
|
201 | fakeProgbars.push(fakeProgbar);
|
202 | return fakeProgbar;
|
203 | });
|
204 | consoleMessages = [];
|
205 | spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
206 | consoleMessages.push(message);
|
207 | });
|
208 | model = tf.sequential();
|
209 | model.add(tf.layers.dense({ units: 10, inputShape: [8], activation: 'relu' }));
|
210 | model.add(tf.layers.dense({ units: 1 }));
|
211 | model.compile({ loss: 'meanSquaredError', optimizer: 'sgd', metrics: ['acc'] });
|
212 | numSamples = 40;
|
213 | epochs = 2;
|
214 | batchSize = 8;
|
215 | validationSplit = 0.15;
|
216 | xs = tf.randomNormal([numSamples, 8]);
|
217 | ys = tf.randomNormal([numSamples, 1]);
|
218 | return [4 , model.fit(xs, ys, { epochs: epochs, batchSize: batchSize, validationSplit: validationSplit, verbose: 0 })];
|
219 | case 1:
|
220 | _a.sent();
|
221 | expect(fakeProgbars.length).toEqual(0);
|
222 | return [2 ];
|
223 | }
|
224 | });
|
225 | }); });
|
226 | it('Model.fitDataset: batchesPerEpoch specified, verbose = 1', function () { return __awaiter(_this, void 0, void 0, function () {
|
227 | var fakeProgbars, consoleMessages, epochs, xDataset, yDataset, dataset, model;
|
228 | return __generator(this, function (_a) {
|
229 | switch (_a.label) {
|
230 | case 0:
|
231 | fakeProgbars = [];
|
232 | spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
233 | .and.callFake(function (specs, config) {
|
234 | var fakeProgbar = new FakeProgbar(specs, config);
|
235 | fakeProgbars.push(fakeProgbar);
|
236 | return fakeProgbar;
|
237 | });
|
238 | consoleMessages = [];
|
239 | spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
240 | consoleMessages.push(message);
|
241 | });
|
242 | epochs = 2;
|
243 | xDataset = tf.data.array([[1, 2], [3, 4], [5, 6], [7, 8]])
|
244 | .map(function (x) { return tf.tensor2d(x, [1, 2]); });
|
245 | yDataset = tf.data.array([[1], [2], [3], [4]]).map(function (y) { return tf.tensor2d(y, [1, 1]); });
|
246 | dataset = tf.data.zip({ xs: xDataset, ys: yDataset }).repeat(epochs);
|
247 | model = tf.sequential();
|
248 | model.add(tf.layers.dense({ units: 1, inputShape: [2] }));
|
249 | model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' });
|
250 | return [4 , model.fitDataset(dataset, { batchesPerEpoch: 4, epochs: epochs, verbose: 1 })];
|
251 | case 1:
|
252 | _a.sent();
|
253 | expect(consoleMessages.length).toEqual(4);
|
254 | expect(consoleMessages[0]).toEqual('Epoch 1 / 2');
|
255 | expect(consoleMessages[1]).toMatch(/.*ms .*us\/step - loss=.*/);
|
256 | expect(consoleMessages[2]).toEqual('Epoch 2 / 2');
|
257 | expect(consoleMessages[3]).toMatch(/.*ms .*us\/step - loss=.*/);
|
258 | return [2 ];
|
259 | }
|
260 | });
|
261 | }); });
|
262 | it('Model.fitDataset: batchesPerEpoch unavailable, verbose = 1', function () { return __awaiter(_this, void 0, void 0, function () {
|
263 | var fakeProgbars, consoleMessages, epochs, xDataset, yDataset, dataset, model;
|
264 | return __generator(this, function (_a) {
|
265 | switch (_a.label) {
|
266 | case 0:
|
267 | fakeProgbars = [];
|
268 | spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
269 | .and.callFake(function (specs, config) {
|
270 | var fakeProgbar = new FakeProgbar(specs, config);
|
271 | fakeProgbars.push(fakeProgbar);
|
272 | return fakeProgbar;
|
273 | });
|
274 | consoleMessages = [];
|
275 | spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
276 | consoleMessages.push(message);
|
277 | });
|
278 | epochs = 2;
|
279 | xDataset = tf.data.array([[1, 2], [3, 4], [5, 6], [7, 8]])
|
280 | .map(function (x) { return tf.tensor2d(x, [1, 2]); });
|
281 | yDataset = tf.data.array([[1], [2], [3], [4]]).map(function (y) { return tf.tensor2d(y, [1, 1]); });
|
282 | dataset = tf.data.zip({ xs: xDataset, ys: yDataset }).repeat(epochs);
|
283 | model = tf.sequential();
|
284 | model.add(tf.layers.dense({ units: 1, inputShape: [2] }));
|
285 | model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' });
|
286 |
|
287 |
|
288 | return [4 , model.fitDataset(dataset, { epochs: epochs, verbose: 1 })];
|
289 | case 1:
|
290 |
|
291 |
|
292 | _a.sent();
|
293 | expect(consoleMessages.length).toEqual(4);
|
294 | expect(consoleMessages[0]).toEqual('Epoch 1 / 2');
|
295 | expect(consoleMessages[1]).toMatch(/.*ms .*us\/step - loss=.*/);
|
296 | expect(consoleMessages[2]).toEqual('Epoch 2 / 2');
|
297 | expect(consoleMessages[3]).toMatch(/.*ms .*us\/step - loss=.*/);
|
298 | return [2 ];
|
299 | }
|
300 | });
|
301 | }); });
|
302 | it('Model.fitDataset: verbose = 0 leads to no logging', function () { return __awaiter(_this, void 0, void 0, function () {
|
303 | var fakeProgbars, consoleMessages, xDataset, yDataset, dataset, model, history;
|
304 | return __generator(this, function (_a) {
|
305 | switch (_a.label) {
|
306 | case 0:
|
307 | fakeProgbars = [];
|
308 | spyOn(callbacks_1.progressBarHelper, 'ProgressBar')
|
309 | .and.callFake(function (specs, config) {
|
310 | var fakeProgbar = new FakeProgbar(specs, config);
|
311 | fakeProgbars.push(fakeProgbar);
|
312 | return fakeProgbar;
|
313 | });
|
314 | consoleMessages = [];
|
315 | spyOn(callbacks_1.progressBarHelper, 'log').and.callFake(function (message) {
|
316 | consoleMessages.push(message);
|
317 | });
|
318 | xDataset = tf.data.array([[1, 2], [3, 4], [5, 6], [7, 8]])
|
319 | .map(function (x) { return tf.tensor2d(x, [1, 2]); });
|
320 | yDataset = tf.data.array([[1], [2], [3], [4]]).map(function (y) { return tf.tensor2d(y, [1, 1]); });
|
321 | dataset = tf.data.zip({ xs: xDataset, ys: yDataset });
|
322 | model = tf.sequential();
|
323 | model.add(tf.layers.dense({ units: 1, inputShape: [2] }));
|
324 | model.compile({ loss: 'meanSquaredError', optimizer: 'sgd' });
|
325 | return [4 , model.fitDataset(dataset, { epochs: 1, verbose: 0 })];
|
326 | case 1:
|
327 | history = _a.sent();
|
328 | expect(history.history.loss.length).toEqual(1);
|
329 | expect(consoleMessages.length)
|
330 | .toEqual(0);
|
331 | return [2 ];
|
332 | }
|
333 | });
|
334 | }); });
|
335 | });
|
336 | describe('getSuccinctNumberDisplay', function () {
|
337 | it('Not finite', function () {
|
338 | expect(callbacks_1.getSuccinctNumberDisplay(Infinity)).toEqual('Infinity');
|
339 | expect(callbacks_1.getSuccinctNumberDisplay(-Infinity)).toEqual('-Infinity');
|
340 | expect(callbacks_1.getSuccinctNumberDisplay(NaN)).toEqual('NaN');
|
341 | });
|
342 | it('zero', function () {
|
343 | expect(callbacks_1.getSuccinctNumberDisplay(0)).toEqual('0.00');
|
344 | });
|
345 | it('Finite and positive', function () {
|
346 | expect(callbacks_1.getSuccinctNumberDisplay(300)).toEqual('300.00');
|
347 | expect(callbacks_1.getSuccinctNumberDisplay(30)).toEqual('30.00');
|
348 | expect(callbacks_1.getSuccinctNumberDisplay(1)).toEqual('1.00');
|
349 | expect(callbacks_1.getSuccinctNumberDisplay(1e-2)).toEqual('0.0100');
|
350 | expect(callbacks_1.getSuccinctNumberDisplay(1e-3)).toEqual('1.00e-3');
|
351 | expect(callbacks_1.getSuccinctNumberDisplay(4e-3)).toEqual('4.00e-3');
|
352 | expect(callbacks_1.getSuccinctNumberDisplay(1e-6)).toEqual('1.00e-6');
|
353 | });
|
354 | it('Finite and negative', function () {
|
355 | expect(callbacks_1.getSuccinctNumberDisplay(-300)).toEqual('-300.00');
|
356 | expect(callbacks_1.getSuccinctNumberDisplay(-30)).toEqual('-30.00');
|
357 | expect(callbacks_1.getSuccinctNumberDisplay(-1)).toEqual('-1.00');
|
358 | expect(callbacks_1.getSuccinctNumberDisplay(-1e-2)).toEqual('-0.0100');
|
359 | expect(callbacks_1.getSuccinctNumberDisplay(-1e-3)).toEqual('-1.00e-3');
|
360 | expect(callbacks_1.getSuccinctNumberDisplay(-4e-3)).toEqual('-4.00e-3');
|
361 | expect(callbacks_1.getSuccinctNumberDisplay(-1e-6)).toEqual('-1.00e-6');
|
362 | });
|
363 | });
|
364 | describe('getDisplayDecimalPlaces', function () {
|
365 | it('Not finite', function () {
|
366 | expect(callbacks_1.getDisplayDecimalPlaces(Infinity)).toEqual(2);
|
367 | expect(callbacks_1.getDisplayDecimalPlaces(-Infinity)).toEqual(2);
|
368 | expect(callbacks_1.getDisplayDecimalPlaces(NaN)).toEqual(2);
|
369 | });
|
370 | it('zero', function () {
|
371 | expect(callbacks_1.getDisplayDecimalPlaces(0)).toEqual(2);
|
372 | });
|
373 | it('Finite and positive', function () {
|
374 | expect(callbacks_1.getDisplayDecimalPlaces(300)).toEqual(2);
|
375 | expect(callbacks_1.getDisplayDecimalPlaces(30)).toEqual(2);
|
376 | expect(callbacks_1.getDisplayDecimalPlaces(1)).toEqual(2);
|
377 | expect(callbacks_1.getDisplayDecimalPlaces(1e-2)).toEqual(4);
|
378 | expect(callbacks_1.getDisplayDecimalPlaces(1e-3)).toEqual(5);
|
379 | expect(callbacks_1.getDisplayDecimalPlaces(4e-3)).toEqual(5);
|
380 | expect(callbacks_1.getDisplayDecimalPlaces(1e-6)).toEqual(8);
|
381 | });
|
382 | it('Finite and negative', function () {
|
383 | expect(callbacks_1.getDisplayDecimalPlaces(-300)).toEqual(2);
|
384 | expect(callbacks_1.getDisplayDecimalPlaces(-30)).toEqual(2);
|
385 | expect(callbacks_1.getDisplayDecimalPlaces(-1)).toEqual(2);
|
386 | expect(callbacks_1.getDisplayDecimalPlaces(-1e-2)).toEqual(4);
|
387 | expect(callbacks_1.getDisplayDecimalPlaces(-1e-3)).toEqual(5);
|
388 | expect(callbacks_1.getDisplayDecimalPlaces(-4e-3)).toEqual(5);
|
389 | expect(callbacks_1.getDisplayDecimalPlaces(-1e-6)).toEqual(8);
|
390 | });
|
391 | });
|