Repository: deepjavalibrary/djl
Pull request #2051 (2022-09-29 22:45:25)

[pytorch] Update deeplabv3 model zoo metadata
## Description ##

Brief description of what this PR is about

- If this change is a backward incompatible change, why must this change be made?
- Interesting edge cases to note here



Patch:
diff --git a/api/src/main/java/ai/djl/nn/Parameter.java b/api/src/main/java/ai/djl/nn/Parameter.java
index 62b62137f..857e4c474 100644
--- a/api/src/main/java/ai/djl/nn/Parameter.java
+++ b/api/src/main/java/ai/djl/nn/Parameter.java
@@ -120,7 +120,8 @@ public class Parameter implements AutoCloseable {
      */
     public NDArray getArray() {
         if (!isInitialized()) {
-            throw new IllegalStateException("The array has not been initialized");
+            throw new UninitializedParameterException(
+                    "The array for parameter \"" + getName() + "\" has not been initialized");
         }
         return array;
     }
diff --git a/api/src/main/java/ai/djl/nn/UninitializedParameterException.java b/api/src/main/java/ai/djl/nn/UninitializedParameterException.java
new file mode 100644
index 000000000..20d3fe2ac
--- /dev/null
+++ b/api/src/main/java/ai/djl/nn/UninitializedParameterException.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. 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. A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0/
+ *
+ * or in the "license" file accompanying this file. This file 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.
+ */
+package ai.djl.nn;
+
+/** Thrown to indicate that a {@link Parameter} was not initialized. */
+public class UninitializedParameterException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructs a new exception with the specified detail message. The cause is not initialized,
+     * and may subsequently be initialized by a call to {@link #initCause}.
+     *
+     * @param message the detail message that is saved for later retrieval by the {@link
+     *     #getMessage()} method
+     */
+    public UninitializedParameterException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message and cause.
+     *
+     * <p>Note that the detail message associated with {@code cause} is <i>not</i> automatically
+     * incorporated in this exception's detail message.
+     *
+     * @param message the detail message that is saved for later retrieval by the {@link
+     *     #getMessage()} method
+     * @param cause the cause that is saved for later retrieval by the {@link #getCause()} method. A
+     *     {@code null} value is permitted, and indicates that the cause is nonexistent or unknown
+     */
+    public UninitializedParameterException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new exception with the specified cause and a detail message of {@code
+     * (cause==null ? null : cause.toString())} which typically contains the class and detail
+     * message of {@code cause}. This constructor is useful for exceptions that are little more than
+     * wrappers for other throwables. For example, {@link java.security.PrivilegedActionException}.
+     *
+     * @param cause the cause that is saved for later retrieval by the {@link #getCause()} method. A
+     *     {@code null} value is permitted, and indicates that the cause is nonexistent or unknown
+     */
+    public UninitializedParameterException(Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/api/src/main/java/ai/djl/training/Trainer.java b/api/src/main/java/ai/djl/training/Trainer.java
index 393bca171..8358c0238 100644
--- a/api/src/main/java/ai/djl/training/Trainer.java
+++ b/api/src/main/java/ai/djl/training/Trainer.java
@@ -21,6 +21,7 @@ import ai.djl.ndarray.NDList;
 import ai.djl.ndarray.NDManager;
 import ai.djl.ndarray.types.Shape;
 import ai.djl.nn.Parameter;
+import ai.djl.nn.UninitializedParameterException;
 import ai.djl.training.dataset.Batch;
 import ai.djl.training.dataset.Dataset;
 import ai.djl.training.evaluator.Evaluator;
@@ -121,7 +122,20 @@ public class Trainer implements AutoCloseable {
                 .forEach(
                         pair -> {
                             for (Device device : devices) {
-                                parameterStore.getValue(pair.getValue(), device, true);
+                                try {
+                                    parameterStore.getValue(pair.getValue(), device, true);
+                                } catch (UninitializedParameterException e) {
+                                    throw new IllegalStateException(
+                                            "Failed to initialize parameter: "
+                                                    + pair.getKey()
+                                                    + ".\n"
+                                                    + "If you are defining a Block extending"
+                                                    + " AbstractBlock, check that you are"
+                                                    + " initializing all child blocks as part of"
+                                                    + " the overload for"
+                                                    + " AbstractBlock.initializeChildBlocks().",
+                                            e);
+                                }
                             }
                         });
     }
diff --git a/extensions/tokenizers/src/main/python/arg_parser.py b/extensions/tokenizers/src/main/python/arg_parser.py
index eb88acb8e..8af923ba2 100644
--- a/extensions/tokenizers/src/main/python/arg_parser.py
+++ b/extensions/tokenizers/src/main/python/arg_parser.py
@@ -27,6 +27,10 @@ def converter_args():
                         "--retry-failed",
                         action='store_true',
                         help="Retry failed model")
+    parser.add_argument("-u",
+                        "--cpu-only",
+                        action='store_true',
+                        help="Only validate jit traced model on CPU")
     group = parser.add_mutually_exclusive_group(required=True)
     group.add_argument(
         "-c",
diff --git a/extensions/tokenizers/src/main/python/huggingface_converter.py b/extensions/tokenizers/src/main/python/huggingface_converter.py
index 1eb521b40..ec1aeebd4 100644
--- a/extensions/tokenizers/src/main/python/huggingface_converter.py
+++ b/extensions/tokenizers/src/main/python/huggingface_converter.py
@@ -14,6 +14,7 @@
 import logging
 import os.path
 import shutil
+from argparse import Namespace
 
 import torch
 from huggingface_hub import hf_hub_download
@@ -35,7 +36,7 @@ class HuggingfaceConverter:
         self.inputs = None
         self.outputs = None
 
-    def save_model(self, model_info, output_dir: str, temp_dir: str):
+    def save_model(self, model_info, args: Namespace, temp_dir: str):
         model_id = model_info.modelId
         if not os.path.exists(temp_dir):
             os.makedirs(temp_dir)
@@ -56,7 +57,7 @@ class HuggingfaceConverter:
             return False, "Failed to trace model", -1
 
         result, reason = self.verify_jit_model(hf_pipeline, model_file,
-                                               include_types)
+                                               include_types, args.cpu_only)
         if not result:
             include_types = True
             model_file = self.jit_trace_model(hf_pipeline, model_id, temp_dir,
@@ -65,11 +66,12 @@ class HuggingfaceConverter:
                 return False, reason, -1
 
             result, reason = self.verify_jit_model(hf_pipeline, model_file,
-                                                   include_types)
+                                                   include_types,
+                                                   args.cpu_only)
             if not result:
                 return False, reason, -1
 
-        size = self.save_to_model_zoo(model_info, output_dir, temp_dir,
+        size = self.save_to_model_zoo(model_info, args.output_dir, temp_dir,
                                       hf_pipeline, include_types)
 
         return True, None, size
@@ -157,7 +159,7 @@ class HuggingfaceConverter:
         return file_size
 
     def verify_jit_model(self, hf_pipeline, model_file: str,
-                         include_types: bool):
+                         include_types: bool, cpu_only: bool):
         logging.info(
             f"Verifying torchscript model(include_token_types={include_types}): {model_file} ..."
         )
@@ -168,7 +170,7 @@ class HuggingfaceConverter:
         input_ids = encoding["input_ids"]
         attention_mask = encoding["attention_mask"]
         token_type_ids = encoding.get("token_type_ids")
-        if torch.cuda.is_available():
+        if torch.cuda.is_available() and not cpu_only:
             traced_model = torch.jit.load(model_file, map_location='cuda:0')
             traced_model.to(self.device)
             input_ids = input_ids.to(self.device)
diff --git a/extensions/tokenizers/src/main/python/huggingface_models.py b/extensions/tokenizers/src/main/python/huggingface_models.py
index 6f974febb..3418815d5 100644
--- a/extensions/tokenizers/src/main/python/huggingface_models.py
+++ b/extensions/tokenizers/src/main/python/huggingface_models.py
@@ -124,7 +124,7 @@ class HuggingfaceModels:
         return ret
 
     def update_progress(self, model_info: ModelInfo, application: str,
-                        result: bool, reason: str, size: int):
+                        result: bool, reason: str, size: int, cpu_only: bool):
         status = {
             "result": "success" if result else "failed",
             "application": application,
@@ -134,6 +134,9 @@ class HuggingfaceModels:
         }
         if reason:
             status["reason"] = reason
+        if cpu_only:
+            status["cpu_only"] = True
+
         self.processed_models[model_info.modelId] = status
 
         dict_file = os.path.join(self.output_dir, "models.json")
diff --git a/extensions/tokenizers/src/main/python/model_zoo_importer.py b/extensions/tokenizers/src/main/python/model_zoo_importer.py
index a4e2c6d86..2841dbde4 100644
--- a/extensions/tokenizers/src/main/python/model_zoo_importer.py
+++ b/extensions/tokenizers/src/main/python/model_zoo_importer.py
@@ -47,13 +47,12 @@ def main():
         model_info = model["model_info"]
         converter = SUPPORTED_TASK[task]
 
-        result, reason, size = converter.save_model(model_info,
-                                                    args.output_dir, temp_dir)
+        result, reason, size = converter.save_model(model_info, args, temp_dir)
         if not result:
             logging.error(f"{model_info.modelId}: {reason}")
 
         huggingface_models.update_progress(model_info, converter.application,
-                                           result, reason, size)
+                                           result, reason, size, args.cpu_only)
         shutil.rmtree(temp_dir)
 
     logging.info("finished.")


Test patch:
diff --git a/engines/pytorch/pytorch-model-zoo/src/test/resources/mlrepo/model/cv/semantic_segmentation/ai/djl/pytorch/deeplabv3/metadata.json b/engines/pytorch/pytorch-model-zoo/src/test/resources/mlrepo/model/cv/semantic_segmentation/ai/djl/pytorch/deeplabv3/metadata.json
index 31ddf1b81..0aa710262 100644
--- a/engines/pytorch/pytorch-model-zoo/src/test/resources/mlrepo/model/cv/semantic_segmentation/ai/djl/pytorch/deeplabv3/metadata.json
+++ b/engines/pytorch/pytorch-model-zoo/src/test/resources/mlrepo/model/cv/semantic_segmentation/ai/djl/pytorch/deeplabv3/metadata.json
@@ -31,9 +31,9 @@
       "files": {
         "model": {
           "uri": "0.0.1/deeplabv3.zip",
-          "sha1Hash": "06b8471f40d41d5f4fce7736cdd24081b9fa2e8e",
+          "sha1Hash": "417241c13140e8ad307fdb5884442183fb94e130",
           "name": "",
-          "size": 155844147
+          "size": 155844400
         }
       }
     }