2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 var MachineLearningTrainer = function () { };
20 OPTIMIZER_ADAM: 'OPTIMIZER_ADAM',
21 OPTIMIZER_SGD: 'OPTIMIZER_SGD',
22 OPTIMIZER_UNKNOWN: 'OPTIMIZER_UNKNOWN'
26 DATASET_GENERATOR: 'DATASET_GENERATOR',
27 DATASET_FILE: 'DATASET_FILE',
28 DATASET_UNKNOWN: 'DATASET_UNKNOWN'
35 LAYER_CONV2D: 'LAYER_CONV2D',
36 LAYER_POOLING2D: 'LAYER_POOLING2D',
37 LAYER_FLATTEN: 'LAYER_FLATTEN',
38 LAYER_ACTIVATION: 'LAYER_ACTIVATION',
39 LAYER_ADDITION: 'LAYER_ADDITION',
40 LAYER_CONCAT: 'LAYER_CONCAT',
41 LAYER_MULTIOUT: 'LAYER_MULTIOUT',
42 LAYER_LOSS_MSE: 'LAYER_LOSS_MSE',
43 LAYER_LOSS_CROSS_ENTROPY_SIGMOID: 'LAYER_LOSS_CROSS_ENTROPY_SIGMOID',
44 LAYER_LOSS_CROSS_ENTROPY_SOFTMAX: 'LAYER_LOSS_CROSS_ENTROPY_SOFTMAX',
45 LAYER_BACKBONE_NNSTREAMER: 'LAYER_BACKBONE_NNSTREAMER',
46 LAYER_EMBEDDING: 'LAYER_EMBEDDING',
47 LAYER_RNN: 'LAYER_RNN',
48 LAYER_UNKNOWN: 'LAYER_UNKNOWN'
51 var VerbosityLevel = {
52 SUMMARY_MODEL: 'SUMMARY_MODEL',
53 SUMMARY_LAYER: 'SUMMARY_LAYER',
54 SUMMARY_TENSOR: 'SUMMARY_TENSOR'
58 FORMAT_BIN: 'FORMAT_BIN',
59 FORMAT_INI: 'FORMAT_INI',
60 FORMAT_INI_WITH_BIN: 'FORMAT_INI_WITH_BIN'
64 MODE_TRAIN: 'MODE_TRAIN',
65 MODE_VALID: 'MODE_VALID',
66 MODE_TEST: 'MODE_TEST'
69 var ValidGetNameExceptions = [
74 var Layer = function(id, type) {
75 Object.defineProperties(this, {
79 var result = native_.callSync('MLTrainerLayerGetName', { id: this._id });
81 if (native_.isFailure(result)) {
82 throw native_.getErrorObjectAndValidate(
84 ValidGetNameExceptions,
97 _id: { value: id, writable: false, enumerable: false }
101 var ValidSetPropertyExceptions = [
102 'InvalidValuesError',
108 Layer.prototype.setProperty = function() {
109 var args = validator_.validateArgs(arguments, [
120 if (!args.has.name || !args.has.value) {
121 throw new WebAPIException(
122 WebAPIException.TYPE_MISMATCH_ERR,
123 'Invalid parameter: ' + (args.has.name ? 'value' : 'name') + ' is undefined'
133 var result = native_.callSync('MLTrainerLayerSetProperty', callArgs);
135 if (native_.isFailure(result)) {
136 throw native_.getErrorObjectAndValidate(
138 ValidSetPropertyExceptions,
144 var ValidDisposeExceptions = [
146 'NoModificationAllowedError',
150 Layer.prototype.dispose = function () {
151 var result = native_.callSync('MLTrainerLayerDispose', { id: this._id });
153 if (native_.isFailure(result)) {
154 throw native_.getErrorObjectAndValidate(
156 ValidDisposeExceptions,
162 var Optimizer = function(id, type) {
163 Object.defineProperties(this, {
169 _id: { value: id, writable: false, enumerable: false }
173 Optimizer.prototype.setProperty = function() {
174 var args = validator_.validateArgs(arguments, [
185 if (!args.has.name || !args.has.value) {
186 throw new WebAPIException(
187 WebAPIException.TYPE_MISMATCH_ERR,
188 'Invalid parameter: ' + (args.has.name ? 'value' : 'name') + ' is undefined'
198 var result = native_.callSync('MLTrainerOptimizerSetProperty', callArgs);
200 if (native_.isFailure(result)) {
201 throw native_.getErrorObjectAndValidate(
203 ValidSetPropertyExceptions,
209 Optimizer.prototype.dispose = function () {
210 var result = native_.callSync('MLTrainerOptimizerDispose', { id: this._id });
212 if (native_.isFailure(result)) {
213 throw native_.getErrorObjectAndValidate(
215 ValidDisposeExceptions,
221 var Dataset = function(id, type) {
222 Object.defineProperties(this, {
228 _id: { value: id, writable: false, enumerable: false }
232 Dataset.prototype.setProperty = function() {
233 var args = validator_.validateArgs(arguments, [
245 values: Object.values(DatasetMode)
249 if (!args.has.name || !args.has.value || !args.has.mode) {
250 throw new WebAPIException(
251 WebAPIException.TYPE_MISMATCH_ERR,
252 'Invalid parameter: name, value and mode have to be defined'
263 var result = native_.callSync('MLTrainerDatasetSetProperty', callArgs);
265 if (native_.isFailure(result)) {
266 throw native_.getErrorObjectAndValidate(
268 ValidSetPropertyExceptions,
275 Dataset.prototype.dispose = function () {
276 var result = native_.callSync('MLTrainerDatasetDispose', { id: this._id });
278 if (native_.isFailure(result)) {
279 throw native_.getErrorObjectAndValidate(
281 ValidDisposeExceptions,
287 var Model = function(id) {
288 Object.defineProperties(this, {
289 _id: { value: id, writable: false, enumerable: false }
293 function ValidateCompileOptions(options) {
295 if (options.hasOwnProperty('loss_val')) {
296 args.loss = options.loss_val;
298 if (options.hasOwnProperty('loss')) {
299 args.loss = options.loss;
301 if (options.hasOwnProperty('batch_size')) {
302 args.batch_size = options.batch_size;
307 var ValidModelCompileExceptions = [
308 'InvalidValuesError',
310 'NoModificationAllowedError',
314 Model.prototype.compile = function() {
315 var args = validator_.validateArgs(arguments, [
318 type: validator_.Types.DICTIONARY,
324 if (args.has.options) {
325 options = ValidateCompileOptions(args.options);
333 var result = native_.callSync('MLTrainerModelCompile', callArgs);
335 if (native_.isFailure(result)) {
336 throw native_.getErrorObjectAndValidate(
338 ValidModelCompileExceptions,
344 function ValidateRunOptions(options) {
346 if (options.hasOwnProperty('batch_size')) {
347 args.batch_size = options.batch_size;
349 if (options.hasOwnProperty('epochs')) {
350 args.epochs = options.epochs;
352 if (options.hasOwnProperty('save_path')) {
353 // produce a global path without "file://" prefix
354 args.save_path = tizen.filesystem.toURI(options.save_path).substring("file://".length);
359 var ValidModelRunExceptions = [
360 'InvalidValuesError',
366 Model.prototype.run = function() {
367 var args = validator_.validateArgs(arguments, [
370 type: validator_.Types.DICTIONARY,
375 name: 'successCallback',
376 type: types_.FUNCTION
379 name: 'errorCallback',
380 type: types_.FUNCTION,
386 if (args.has.options) {
387 runOptions = ValidateRunOptions(args.options);
395 var callback = function (result) {
396 if (native_.isFailure(result)) {
397 native_.callIfPossible(
399 native_.getErrorObjectAndValidate(
401 ValidModelRunExceptions,
406 args.successCallback();
410 var result = native_.call('MLTrainerModelRun', callArgs, callback);
411 if (native_.isFailure(result)) {
412 throw native_.getErrorObjectAndValidate(
414 ValidModelRunExceptions,
420 var ValidBasicExceptions = [
425 Model.prototype.summarize = function() {
426 var args = validator_.validateArgs(arguments, [
430 values: Object.values(VerbosityLevel),
438 level: args.level ? args.level : "SUMMARY_MODEL"
441 var result = native_.callSync('MLTrainerModelSummarize', callArgs);
443 if (native_.isFailure(result)) {
444 throw native_.getErrorObjectAndValidate(
446 ValidBasicExceptions,
451 return result.summary
455 Private method used for verification of training results.
456 It returns true if the results match given values (with tolerance 1.0e-5), false otherwise.
458 Model.prototype._checkMetrics = function (trainLoss, validLoss, validAccuracy) {
460 trainLoss: trainLoss, validLoss: validLoss, validAccuracy: validAccuracy,
464 var result = native_.callSync('MLTrainerModelCheckMetrics', callArgs);
466 if (native_.isFailure(result)) {
467 throw native_.getErrorObjectAndValidate(
469 ValidBasicExceptions,
478 var ValidModelSaveExceptions = [
479 'InvalidValuesError',
481 "NoModificationAllowedError",
485 Model.prototype.saveToFile = function () {
486 var args = validator_.validateArgs(arguments, [
494 values: Object.values(SaveFormat)
501 saveFormat: args.format
505 callArgs.savePath = tizen.filesystem.toURI(args.path);
507 throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Invalid file path given');
510 if (tizen.filesystem.pathExists(callArgs.savePath)) {
511 throw new WebAPIException(WebAPIException.NO_MODIFICATION_ALLOWED_ERR, 'Path already exists - overwriting is not allowed');
514 var result = native_.callSync('MLTrainerModelSave', callArgs);
516 if (native_.isFailure(result)) {
517 throw native_.getErrorObjectAndValidate(
519 ValidModelSaveExceptions,
525 Model.prototype.load = function () {
526 var args = validator_.validateArgs(arguments, [
534 values: Object.values(SaveFormat)
541 saveFormat: args.format
545 callArgs.savePath = tizen.filesystem.toURI(args.path);
547 throw new WebAPIException(WebAPIException.InvalidValuesError, 'Invalid file path given');
550 if (!tizen.filesystem.pathExists(callArgs.savePath)) {
551 throw new WebAPIException(WebAPIException.NotFoundError, 'Path not found');
554 var result = native_.callSync('MLTrainerModelLoad', callArgs);
556 if (native_.isFailure(result)) {
557 throw native_.getErrorObjectAndValidate(
559 ValidModelSaveExceptions,
565 Model.prototype.addLayer = function() {
566 var args = validator_.validateArgs(arguments, [
569 type: types_.PLATFORM_OBJECT,
574 if (!args.has.layer) {
575 throw new WebAPIException(
576 WebAPIException.TYPE_MISMATCH_ERR, 'Invalid parameter: layer is undefined'
582 layerId: args.layer._id
585 var result = native_.callSync('MLTrainerModelAddLayer', callArgs);
587 if (native_.isFailure(result)) {
588 throw native_.getErrorObjectAndValidate(
590 ValidSetObjectExceptions,
596 var ValidSetObjectExceptions = [
597 'InvalidValuesError',
599 'NoModificationAllowedError',
605 Model.prototype.setDataset = function() {
606 var args = validator_.validateArgs(arguments, [
609 type: types_.PLATFORM_OBJECT,
614 if (!args.has.dataset) {
615 throw new WebAPIException(
616 WebAPIException.TYPE_MISMATCH_ERR, 'Invalid parameter: dataset is undefined'
622 datasetId: args.dataset._id
625 var result = native_.callSync('MLTrainerModelSetDataset', callArgs);
627 if (native_.isFailure(result)) {
628 throw native_.getErrorObjectAndValidate(
630 ValidSetObjectExceptions,
636 Model.prototype.setOptimizer = function() {
637 var args = validator_.validateArgs(arguments, [
640 type: types_.PLATFORM_OBJECT,
645 if (!args.has.optimizer) {
646 throw new WebAPIException(
647 WebAPIException.TYPE_MISMATCH_ERR, 'Invalid parameter: optimizer is undefined'
653 optimizerId: args.optimizer._id
656 var result = native_.callSync('MLTrainerModelSetOptimizer', callArgs);
658 if (native_.isFailure(result)) {
659 throw native_.getErrorObjectAndValidate(
661 ValidSetObjectExceptions,
667 Model.prototype.dispose = function () {
668 var result = native_.callSync('MLTrainerModelDispose', { id: this._id });
670 if (native_.isFailure(result)) {
671 throw native_.getErrorObjectAndValidate(
673 ValidDisposeExceptions,
679 var ValidCreateLayerExceptions = ['NotSupportedError', 'TypeMismatchError', 'AbortError'];
682 MachineLearningTrainer.prototype.createLayer = function() {
683 var args = validator_.validateArgs(arguments, [
687 values: Object.values(LayerType),
696 var result = native_.callSync('MLTrainerLayerCreate', nativeArgs);
697 if (native_.isFailure(result)) {
698 throw native_.getErrorObjectAndValidate(
700 ValidCreateLayerExceptions,
705 var nLay = new Layer(result.id, args.type);
707 nLay.setProperty("name", args.type.toString() + result.id.toString());
712 function ValidateAndReturnDatasetPaths(train, valid, test) {
715 train: tizen.filesystem.toURI(train),
716 valid: valid ? tizen.filesystem.toURI(valid) : '',
717 test: test ? tizen.filesystem.toURI(test) : ''
721 throw new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Path is invalid');
725 MachineLearningTrainer.prototype.createFileDataset = function() {
726 var args = validator_.validateArgs(arguments, [
744 if (!args.has.train) {
745 throw new WebAPIException(
746 WebAPIException.TYPE_MISMATCH_ERR,
747 'Invalid parameter: training set path is undefined'
751 var nativeArgs = ValidateAndReturnDatasetPaths(
753 args.has.valid ? args.valid : undefined,
754 args.has.test ? args.test : undefined
757 var result = native_.callSync('MLTrainerDatasetCreateFromFile', nativeArgs);
758 if (native_.isFailure(result)) {
759 throw native_.getErrorObjectAndValidate(
761 ValidCreateLayerExceptions,
766 return new Dataset(result.id, 'DATASET_FILE');
769 var ValidCreateOptimizerExceptions = [
775 MachineLearningTrainer.prototype.createOptimizer = function() {
776 var args = validator_.validateArgs(arguments, [
780 values: Object.values(OptimizerType),
789 var result = native_.callSync('MLTrainerOptimizerCreate', nativeArgs);
790 if (native_.isFailure(result)) {
791 throw native_.getErrorObjectAndValidate(
793 ValidCreateOptimizerExceptions,
798 return new Optimizer(result.id, args.type);
801 var ValidCreateModelWithConfigurationExceptions = [
802 'InvalidValuesError',
808 MachineLearningTrainer.prototype.createModelWithConfiguration = function() {
809 var args = validator_.validateArgs(arguments, [
816 if (args.has.configPath) {
818 args.configPath = tizen.filesystem.toURI(args.configPath);
820 throw new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Path is invalid');
824 configPath: args.configPath
827 var result = native_.callSync('MLTrainerModelCreate', nativeArgs);
828 if (native_.isFailure(result)) {
829 throw native_.getErrorObjectAndValidate(
831 ValidCreateModelWithConfigurationExceptions,
836 return new Model(result.id);
839 MachineLearningTrainer.prototype.createModel = function() {
840 var result = native_.callSync('MLTrainerModelCreate', {});
841 if (native_.isFailure(result)) {
842 throw new WebAPIException(WebAPIException.AbortError, 'Could not create model');
845 return new Model(result.id);