[ML][Train] Fixes for error types of compile() and run() 31/274731/2
authorPiotr Kosko/Tizen API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Fri, 6 May 2022 11:58:22 +0000 (13:58 +0200)
committerPiotr Kosko/Tizen API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Fri, 6 May 2022 14:10:03 +0000 (16:10 +0200)
Fixed error handling for compile() and run() - all errors were casted to
AbortError. After fix, errors reported by native API are casted to
proper Web type if possible.

Added proper handling for null/undefined values passed as options.

[Verification]
modelFile = "/home/owner/media/Documents/test_model.ini"
var Model = tizen.ml.trainer.createModel(modelFile);

Model.compile({loss:"test"})  // InvalidValuesError
// Model.compile({loss:true}) // InvalidValuesError
// Model.compile(null)        // success
// Model.compile()            // success

sCb = (s) => console.log(s)
eCb = (e) => console.log(e)
Model.run({save_path:"not_a_virutal_path"}, sCb, eCb);
//InvalidValuesError via eCb

// Model.run({save_path:"/not_a_real_path"}, sCb, eCb);
// InvalidValuesError via eCb

// Model.run({epochs: "aaaa"}, sCb, eCb)
// InvalidValuesError via eCb

// Model.run({epochs: true}, sCb, eCb)
// InvalidValuesError via eCb

// Model.run(null, sCb, eCb)   // success
// Model.run("abcd", sCb, eCb) // TypeMismatchError

Change-Id: Ibb59f7720048b499ce0d576666fad2d5764637e5

src/ml/js/ml_trainer.js
src/ml/ml_trainer_manager.cc

index 7938d95..f36d2df 100755 (executable)
@@ -302,14 +302,16 @@ var Model = function(id) {
 
 function ValidateCompileOptions(options) {
     var args = {};
-    if (options.hasOwnProperty('loss_val')) {
-        args.loss = options.loss_val;
-    }
-    if (options.hasOwnProperty('loss')) {
-        args.loss = options.loss;
-    }
-    if (options.hasOwnProperty('batch_size')) {
-        args.batch_size = options.batch_size;
+    if (!type_.isNullOrUndefined(options)) {
+        if (options.hasOwnProperty('loss_val')) {
+            args.loss = options.loss_val;
+        }
+        if (options.hasOwnProperty('loss')) {
+            args.loss = options.loss;
+        }
+        if (options.hasOwnProperty('batch_size')) {
+            args.batch_size = options.batch_size;
+        }
     }
     return args;
 }
@@ -354,24 +356,29 @@ Model.prototype.compile = function() {
 
 function ValidateRunOptions(options) {
     var args = {};
-    if (options.hasOwnProperty('batch_size')) {
-        args.batch_size = options.batch_size;
-    }
-    if (options.hasOwnProperty('epochs')) {
-        args.epochs = options.epochs;
-    }
-    if (options.hasOwnProperty('save_path')) {
-        // produce a global path without "file://" prefix
-        args.save_path = tizen.filesystem.toURI(options.save_path).substring("file://".length);
+    if (!type_.isNullOrUndefined(options)) {
+        if (options.hasOwnProperty('batch_size')) {
+            args.batch_size = options.batch_size;
+        }
+        if (options.hasOwnProperty('epochs')) {
+            args.epochs = options.epochs;
+        }
+        if (options.hasOwnProperty('save_path')) {
+            // produce a global path without "file://" prefix
+            args.save_path = tizen.filesystem.toURI(options.save_path).substring("file://".length);
+        }
     }
     return args;
 }
 
 var ValidModelRunExceptions = [
+    'TypeMismatchError'
+];
+
+var ValidModelRunCallbackErrors = [
     'InvalidValuesError',
     'NotFoundError',
     'InvalidStateError',
-    'TypeMismatchError',
     'AbortError'
 ];
 
@@ -394,15 +401,6 @@ Model.prototype.run = function() {
             nullable: true
         }
     ]);
-    var runOptions = {};
-    if (args.has.options) {
-        runOptions = ValidateRunOptions(args.options);
-    }
-
-    var callArgs = {
-        id: this._id,
-        options: runOptions
-    };
 
     var callback = function (result) {
         if (native_.isFailure(result)) {
@@ -410,7 +408,7 @@ Model.prototype.run = function() {
                 args.errorCallback,
                 native_.getErrorObjectAndValidate(
                     result,
-                    ValidModelRunExceptions,
+                    ValidModelRunCallbackErrors,
                     AbortError
                 )
             );
@@ -419,6 +417,23 @@ Model.prototype.run = function() {
         }
     };
 
+    var runOptions = {};
+    if (args.has.options) {
+        try {
+            runOptions = ValidateRunOptions(args.options);
+        } catch (e) {
+            // pass InvalidValuesError to callback
+            native_.callIfPossible(args.errorCallback, e);
+            return;
+        }
+    }
+
+    var callArgs = {
+        id: this._id,
+        options: runOptions
+    };
+
+
     var result = native_.call('MLTrainerModelRun', callArgs, callback);
     if (native_.isFailure(result)) {
         throw native_.getErrorObjectAndValidate(
index 9b81d66..41c7754 100644 (file)
@@ -45,7 +45,7 @@ PlatformResult TrainerManager::CreateModel(int& id) {
   int ret_val = ml_train_model_construct(&n_model);
   if (ret_val != ML_ERROR_NONE) {
     LoggerE("Could not create model: %d (%s)", ret_val, ml_strerror(ret_val));
-    return PlatformResult(ErrorCode::ABORT_ERR, ml_strerror(ret_val));
+    return util::ToPlatformResult(ret_val, ml_strerror(ret_val));
   }
 
   models_[next_model_id_] = std::make_shared<Model>(n_model);
@@ -62,7 +62,7 @@ PlatformResult TrainerManager::CreateModel(int& id, const std::string config) {
   int ret_val = ml_train_model_construct_with_conf(config.c_str(), &n_model);
   if (ret_val != ML_ERROR_NONE) {
     LoggerE("Could not create model: %d (%s)", ret_val, ml_strerror(ret_val));
-    return PlatformResult(ErrorCode::ABORT_ERR, ml_strerror(ret_val));
+    return util::ToPlatformResult(ret_val, ml_strerror(ret_val));
   }
 
   models_[next_model_id_] = std::make_shared<Model>(n_model);
@@ -100,7 +100,7 @@ PlatformResult TrainerManager::ModelCompile(int id,
       ss << key << "=" << value << OPTION_SEPARATOR;
     } else {
       LoggerE("Unexpected param type for: %s", key.c_str());
-      return PlatformResult(ErrorCode::ABORT_ERR,
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
                             "Unexpected param type for:" + key);
     }
   }
@@ -122,7 +122,7 @@ PlatformResult TrainerManager::ModelCompile(int id,
 
   if (ret_val != ML_ERROR_NONE) {
     LoggerE("Could not compile model: %d (%s)", ret_val, ml_strerror(ret_val));
-    return PlatformResult(ErrorCode::ABORT_ERR, ml_strerror(ret_val));
+    return util::ToPlatformResult(ret_val, ml_strerror(ret_val));
   }
   model->setCompiled(true);
 
@@ -164,7 +164,7 @@ PlatformResult TrainerManager::ModelRun(int id,
       ss << key << "=" << value << OPTION_SEPARATOR;
     } else {
       LoggerE("Unexpected param type for: %s", key.c_str());
-      return PlatformResult(ErrorCode::ABORT_ERR,
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
                             "Unexpected param type for:" + key);
     }
   }
@@ -184,7 +184,7 @@ PlatformResult TrainerManager::ModelRun(int id,
   if (ret_val != ML_ERROR_NONE) {
     LoggerE("Could not run (train) model: %d (%s)", ret_val,
             ml_strerror(ret_val));
-    return PlatformResult(ErrorCode::UNKNOWN_ERR, ml_strerror(ret_val));
+    return util::ToPlatformResult(ret_val, ml_strerror(ret_val));
   }
 
   return PlatformResult();