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'
32 LAYER_IN: 'LAYER_INPUT',
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_EMBEDDING: 'LAYER_EMBEDDING',
43 LAYER_RNN: 'LAYER_RNN',
44 LAYER_LSTM: 'LAYER_LSTM',
45 LAYER_SPLIT: 'LAYER_SPLIT',
46 LAYER_GRU: 'LAYER_GRU',
47 LAYER_PERMUTE: 'LAYER_PERMUTE',
48 LAYER_DROPOUT: 'LAYER_DROPOUT',
49 LAYER_BACKBONE_NNSTREAMER: 'LAYER_BACKBONE_NNSTREAMER',
50 LAYER_CENTROID_KNN: 'LAYER_CENTROID_KNN',
51 LAYER_PREPROCESS_FLIP: 'LAYER_PREPROCESS_FLIP',
52 LAYER_PREPROCESS_TRANSLATE: 'LAYER_PREPROCESS_TRANSLATE',
53 LAYER_PREPROCESS_L2NORM: 'LAYER_PREPROCESS_L2NORM',
54 LAYER_LOSS_MSE: 'LAYER_LOSS_MSE',
55 LAYER_LOSS_CROSS_ENTROPY_SIGMOID: 'LAYER_LOSS_CROSS_ENTROPY_SIGMOID',
56 LAYER_LOSS_CROSS_ENTROPY_SOFTMAX: 'LAYER_LOSS_CROSS_ENTROPY_SOFTMAX',
57 LAYER_UNKNOWN: 'LAYER_UNKNOWN'
60 var VerbosityLevel = {
61 SUMMARY_MODEL: 'SUMMARY_MODEL',
62 SUMMARY_LAYER: 'SUMMARY_LAYER',
63 SUMMARY_TENSOR: 'SUMMARY_TENSOR'
67 FORMAT_BIN: 'FORMAT_BIN',
68 FORMAT_INI: 'FORMAT_INI',
69 FORMAT_INI_WITH_BIN: 'FORMAT_INI_WITH_BIN'
73 MODE_TRAIN: 'MODE_TRAIN',
74 MODE_VALID: 'MODE_VALID',
75 MODE_TEST: 'MODE_TEST'
78 var ValidGetNameExceptions = [
83 var Layer = function(id, type) {
84 Object.defineProperties(this, {
88 var result = native_.callSync('MLTrainerLayerGetName', { id: this._id });
90 if (native_.isFailure(result)) {
91 throw native_.getErrorObjectAndValidate(
93 ValidGetNameExceptions,
106 _id: { value: id, writable: false, enumerable: false }
110 var ValidSetPropertyExceptions = [
111 'InvalidValuesError',
118 Layer.prototype.setProperty = function() {
119 var args = validator_.validateArgs(arguments, [
130 if (!args.has.name || !args.has.value) {
131 throw new WebAPIException(
132 WebAPIException.TYPE_MISMATCH_ERR,
133 'Invalid parameter: ' + (args.has.name ? 'value' : 'name') + ' is undefined'
143 var result = native_.callSync('MLTrainerLayerSetProperty', callArgs);
145 if (native_.isFailure(result)) {
146 throw native_.getErrorObjectAndValidate(
148 ValidSetPropertyExceptions,
154 var ValidDisposeExceptions = [
156 'NoModificationAllowedError',
160 Layer.prototype.dispose = function () {
161 var result = native_.callSync('MLTrainerLayerDispose', { id: this._id });
163 if (native_.isFailure(result)) {
164 throw native_.getErrorObjectAndValidate(
166 ValidDisposeExceptions,
172 var Optimizer = function(id, type) {
173 Object.defineProperties(this, {
179 _id: { value: id, writable: false, enumerable: false }
183 Optimizer.prototype.setProperty = function() {
184 var args = validator_.validateArgs(arguments, [
195 if (!args.has.name || !args.has.value) {
196 throw new WebAPIException(
197 WebAPIException.TYPE_MISMATCH_ERR,
198 'Invalid parameter: ' + (args.has.name ? 'value' : 'name') + ' is undefined'
208 var result = native_.callSync('MLTrainerOptimizerSetProperty', callArgs);
210 if (native_.isFailure(result)) {
211 throw native_.getErrorObjectAndValidate(
213 ValidSetPropertyExceptions,
219 Optimizer.prototype.dispose = function () {
220 var result = native_.callSync('MLTrainerOptimizerDispose', { id: this._id });
222 if (native_.isFailure(result)) {
223 throw native_.getErrorObjectAndValidate(
225 ValidDisposeExceptions,
231 var Dataset = function(id, type) {
232 Object.defineProperties(this, {
238 _id: { value: id, writable: false, enumerable: false }
242 Dataset.prototype.setProperty = function() {
243 var args = validator_.validateArgs(arguments, [
255 values: Object.values(DatasetMode)
259 if (!args.has.name || !args.has.value || !args.has.mode) {
260 throw new WebAPIException(
261 WebAPIException.TYPE_MISMATCH_ERR,
262 'Invalid parameter: name, value and mode have to be defined'
273 var result = native_.callSync('MLTrainerDatasetSetProperty', callArgs);
275 if (native_.isFailure(result)) {
276 throw native_.getErrorObjectAndValidate(
278 ValidSetPropertyExceptions,
285 Dataset.prototype.dispose = function () {
286 var result = native_.callSync('MLTrainerDatasetDispose', { id: this._id });
288 if (native_.isFailure(result)) {
289 throw native_.getErrorObjectAndValidate(
291 ValidDisposeExceptions,
297 var Model = function(id) {
298 Object.defineProperties(this, {
299 _id: { value: id, writable: false, enumerable: false }
303 function ValidateCompileOptions(options) {
305 if (options.hasOwnProperty('loss_val')) {
306 args.loss = options.loss_val;
308 if (options.hasOwnProperty('loss')) {
309 args.loss = options.loss;
311 if (options.hasOwnProperty('batch_size')) {
312 args.batch_size = options.batch_size;
317 var ValidModelCompileExceptions = [
318 'InvalidValuesError',
321 'NoModificationAllowedError',
325 Model.prototype.compile = function() {
326 var args = validator_.validateArgs(arguments, [
329 type: validator_.Types.DICTIONARY,
335 if (args.has.options) {
336 options = ValidateCompileOptions(args.options);
344 var result = native_.callSync('MLTrainerModelCompile', callArgs);
346 if (native_.isFailure(result)) {
347 throw native_.getErrorObjectAndValidate(
349 ValidModelCompileExceptions,
355 function ValidateRunOptions(options) {
357 if (options.hasOwnProperty('batch_size')) {
358 args.batch_size = options.batch_size;
360 if (options.hasOwnProperty('epochs')) {
361 args.epochs = options.epochs;
363 if (options.hasOwnProperty('save_path')) {
364 // produce a global path without "file://" prefix
365 args.save_path = tizen.filesystem.toURI(options.save_path).substring("file://".length);
370 var ValidModelRunExceptions = [
371 'InvalidValuesError',
378 Model.prototype.run = function() {
379 var args = validator_.validateArgs(arguments, [
382 type: validator_.Types.DICTIONARY,
387 name: 'successCallback',
388 type: types_.FUNCTION
391 name: 'errorCallback',
392 type: types_.FUNCTION,
398 if (args.has.options) {
399 runOptions = ValidateRunOptions(args.options);
407 var callback = function (result) {
408 if (native_.isFailure(result)) {
409 native_.callIfPossible(
411 native_.getErrorObjectAndValidate(
413 ValidModelRunExceptions,
418 args.successCallback();
422 var result = native_.call('MLTrainerModelRun', callArgs, callback);
423 if (native_.isFailure(result)) {
424 throw native_.getErrorObjectAndValidate(
426 ValidModelRunExceptions,
432 var ValidBasicExceptions = [
438 Model.prototype.summarize = function() {
439 var args = validator_.validateArgs(arguments, [
443 values: Object.values(VerbosityLevel),
451 level: args.level ? args.level : "SUMMARY_MODEL"
454 var result = native_.callSync('MLTrainerModelSummarize', callArgs);
456 if (native_.isFailure(result)) {
457 throw native_.getErrorObjectAndValidate(
459 ValidBasicExceptions,
464 return result.summary
468 Private method used for verification of training results.
469 It returns true if the results match given values (with tolerance 1.0e-5), false otherwise.
471 Model.prototype._checkMetrics = function (trainLoss, validLoss, validAccuracy) {
473 trainLoss: trainLoss, validLoss: validLoss, validAccuracy: validAccuracy,
477 var result = native_.callSync('MLTrainerModelCheckMetrics', callArgs);
479 if (native_.isFailure(result)) {
480 throw native_.getErrorObjectAndValidate(
482 ValidBasicExceptions,
491 var ValidModelSaveExceptions = [
492 'InvalidValuesError',
495 'NoModificationAllowedError',
499 Model.prototype.saveToFile = function () {
500 var args = validator_.validateArgs(arguments, [
508 values: Object.values(SaveFormat)
515 saveFormat: args.format
519 callArgs.savePath = tizen.filesystem.toURI(args.path);
521 throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Invalid file path given');
524 if (tizen.filesystem.pathExists(callArgs.savePath)) {
525 throw new WebAPIException(WebAPIException.NO_MODIFICATION_ALLOWED_ERR, 'Path already exists - overwriting is not allowed');
528 var result = native_.callSync('MLTrainerModelSave', callArgs);
530 if (native_.isFailure(result)) {
531 throw native_.getErrorObjectAndValidate(
533 ValidModelSaveExceptions,
539 Model.prototype.load = function () {
540 var args = validator_.validateArgs(arguments, [
548 values: Object.values(SaveFormat)
555 saveFormat: args.format
559 callArgs.savePath = tizen.filesystem.toURI(args.path);
561 throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Invalid file path given');
564 if (!tizen.filesystem.pathExists(callArgs.savePath)) {
565 throw new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Path not found');
568 var result = native_.callSync('MLTrainerModelLoad', callArgs);
570 if (native_.isFailure(result)) {
571 throw native_.getErrorObjectAndValidate(
573 ValidModelSaveExceptions,
579 Model.prototype.addLayer = function() {
580 var args = validator_.validateArgs(arguments, [
583 type: types_.PLATFORM_OBJECT,
588 if (!args.has.layer) {
589 throw new WebAPIException(
590 WebAPIException.TYPE_MISMATCH_ERR, 'Invalid parameter: layer is undefined'
596 layerId: args.layer._id
599 var result = native_.callSync('MLTrainerModelAddLayer', callArgs);
601 if (native_.isFailure(result)) {
602 throw native_.getErrorObjectAndValidate(
604 ValidSetObjectExceptions,
610 var ValidSetObjectExceptions = [
611 'InvalidValuesError',
613 'NoModificationAllowedError',
619 Model.prototype.setDataset = function() {
620 var args = validator_.validateArgs(arguments, [
623 type: types_.PLATFORM_OBJECT,
628 if (!args.has.dataset) {
629 throw new WebAPIException(
630 WebAPIException.TYPE_MISMATCH_ERR, 'Invalid parameter: dataset is undefined'
636 datasetId: args.dataset._id
639 var result = native_.callSync('MLTrainerModelSetDataset', callArgs);
641 if (native_.isFailure(result)) {
642 throw native_.getErrorObjectAndValidate(
644 ValidSetObjectExceptions,
650 Model.prototype.setOptimizer = function() {
651 var args = validator_.validateArgs(arguments, [
654 type: types_.PLATFORM_OBJECT,
659 if (!args.has.optimizer) {
660 throw new WebAPIException(
661 WebAPIException.TYPE_MISMATCH_ERR, 'Invalid parameter: optimizer is undefined'
667 optimizerId: args.optimizer._id
670 var result = native_.callSync('MLTrainerModelSetOptimizer', callArgs);
672 if (native_.isFailure(result)) {
673 throw native_.getErrorObjectAndValidate(
675 ValidSetObjectExceptions,
681 Model.prototype.dispose = function () {
682 var result = native_.callSync('MLTrainerModelDispose', { id: this._id });
684 if (native_.isFailure(result)) {
685 throw native_.getErrorObjectAndValidate(
687 ValidDisposeExceptions,
693 var ValidCreateLayerExceptions = ['NotSupportedError', 'TypeMismatchError', 'AbortError'];
696 MachineLearningTrainer.prototype.createLayer = function() {
697 var args = validator_.validateArgs(arguments, [
701 values: Object.values(LayerType),
710 var result = native_.callSync('MLTrainerLayerCreate', nativeArgs);
711 if (native_.isFailure(result)) {
712 throw native_.getErrorObjectAndValidate(
714 ValidCreateLayerExceptions,
719 var nLay = new Layer(result.id, args.type);
721 nLay.setProperty("name", args.type.toString() + result.id.toString());
726 function ValidateAndReturnDatasetPaths(train, valid, test) {
729 train: tizen.filesystem.toURI(train),
730 valid: valid ? tizen.filesystem.toURI(valid) : '',
731 test: test ? tizen.filesystem.toURI(test) : ''
735 throw new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Path is invalid');
739 MachineLearningTrainer.prototype.createFileDataset = function() {
740 var args = validator_.validateArgs(arguments, [
758 if (!args.has.train) {
759 throw new WebAPIException(
760 WebAPIException.TYPE_MISMATCH_ERR,
761 'Invalid parameter: training set path is undefined'
765 var nativeArgs = ValidateAndReturnDatasetPaths(
767 args.has.valid ? args.valid : undefined,
768 args.has.test ? args.test : undefined
771 var result = native_.callSync('MLTrainerDatasetCreateFromFile', nativeArgs);
772 if (native_.isFailure(result)) {
773 throw native_.getErrorObjectAndValidate(
775 ValidCreateLayerExceptions,
780 return new Dataset(result.id, 'DATASET_FILE');
783 var ValidCreateOptimizerExceptions = [
789 MachineLearningTrainer.prototype.createOptimizer = function() {
790 var args = validator_.validateArgs(arguments, [
794 values: Object.values(OptimizerType),
803 var result = native_.callSync('MLTrainerOptimizerCreate', nativeArgs);
804 if (native_.isFailure(result)) {
805 throw native_.getErrorObjectAndValidate(
807 ValidCreateOptimizerExceptions,
812 return new Optimizer(result.id, args.type);
815 var ValidCreateModelWithConfigurationExceptions = [
821 MachineLearningTrainer.prototype.createModel = function () {
822 var args = validator_.validateArgs(arguments, [
832 if (args.has.configPath) {
834 // if path seems valid pass it to native layer
835 nativeArgs.configPath = tizen.filesystem.toURI(args.configPath);
837 throw new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Path is invalid');
841 var result = native_.callSync('MLTrainerModelCreate', nativeArgs);
842 if (native_.isFailure(result)) {
843 throw native_.getErrorObjectAndValidate(
845 ValidCreateModelWithConfigurationExceptions,
850 return new Model(result.id);