Repository: kserve/kserve

Issue:
Add TorchServe Model Archive creating support
/kind feature

**Describe the solution you'd like**
This feature will add support for creating the [TorchServe Model Archiver file](https://github.com/pytorch/serve/tree/master/model-archiver) for serving PyTorch models. It will include detailed steps for generating the MAR file using a mechanisms provided by K8s/KFServing. 



Discussion:
thanks @chauhang ! Can we setup a meeting with you to go over these issues?

Resolving patch:
diff --git a/docs/samples/v1beta1/torchserve/model-archiver/model-store/densenet_161/model.py b/docs/samples/v1beta1/torchserve/model-archiver/model-store/densenet_161/model.py
new file mode 100644
--- /dev/null
+++ b/docs/samples/v1beta1/torchserve/model-archiver/model-store/densenet_161/model.py
@@ -0,0 +1,24 @@
+from torchvision.models.densenet import DenseNet
+
+
+class ImageClassifier(DenseNet):
+    def __init__(self):
+        super(ImageClassifier, self).__init__(48, (6, 12, 36, 24), 96)
+
+    def load_state_dict(self, state_dict, strict=True):
+        # '.'s are no longer allowed in module names, but previous _DenseLayer
+        # has keys 'norm.1', 'relu.1', 'conv.1', 'norm.2', 'relu.2', 'conv.2'.
+        # They are also in the checkpoints in model_urls. This pattern is used
+        # to find such keys.
+        # Credit - https://github.com/pytorch/vision/blob/master/torchvision/models/densenet.py#def _load_state_dict()
+        import re
+        pattern = re.compile(r'^(.*denselayer\d+\.(?:norm|relu|conv))\.((?:[12])\.(?:weight|bias|running_mean|running_var))$')
+
+        for key in list(state_dict.keys()):
+            res = pattern.match(key)
+            if res:
+                new_key = res.group(1) + res.group(2)
+                state_dict[new_key] = state_dict[key]
+                del state_dict[key]
+
+        return super(ImageClassifier, self).load_state_dict(state_dict, strict)
diff --git a/docs/samples/v1beta1/torchserve/model-archiver/model-store/mnist/mnist.py b/docs/samples/v1beta1/torchserve/model-archiver/model-store/mnist/mnist.py
new file mode 100644
--- /dev/null
+++ b/docs/samples/v1beta1/torchserve/model-archiver/model-store/mnist/mnist.py
@@ -0,0 +1,28 @@
+import torch
+from torch import nn
+import torch.nn.functional as F
+
+
+class Net(nn.Module):
+    def __init__(self):
+        super(Net, self).__init__()
+        self.conv1 = nn.Conv2d(1, 32, 3, 1)
+        self.conv2 = nn.Conv2d(32, 64, 3, 1)
+        self.dropout1 = nn.Dropout2d(0.25)
+        self.dropout2 = nn.Dropout2d(0.5)
+        self.fc1 = nn.Linear(9216, 128)
+        self.fc2 = nn.Linear(128, 10)
+
+    def forward(self, x):
+        x = self.conv1(x)
+        x = F.relu(x)
+        x = self.conv2(x)
+        x = F.max_pool2d(x, 2)
+        x = self.dropout1(x)
+        x = torch.flatten(x, 1)
+        x = self.fc1(x)
+        x = F.relu(x)
+        x = self.dropout2(x)
+        x = self.fc2(x)
+        output = F.log_softmax(x, dim=1)
+        return output
diff --git a/docs/samples/v1beta1/torchserve/model-archiver/model-store/mnist/mnist_handler.py b/docs/samples/v1beta1/torchserve/model-archiver/model-store/mnist/mnist_handler.py
new file mode 100644
--- /dev/null
+++ b/docs/samples/v1beta1/torchserve/model-archiver/model-store/mnist/mnist_handler.py
@@ -0,0 +1,23 @@
+import io
+
+from PIL import Image
+from torchvision import transforms
+
+from ts.torch_handler.image_classifier import ImageClassifier
+
+
+class MNISTDigitClassifier(ImageClassifier):
+    """
+    MNISTDigitClassifier handler class. This handler extends class ImageClassifier from image_classifier.py, a
+    default handler. This handler takes an image and returns the number in that image.
+
+    Here method postprocess() has been overridden while others are reused from parent class.
+    """
+
+    image_processing = transforms.Compose([
+        transforms.ToTensor(),
+        transforms.Normalize((0.1307,), (0.3081,))
+    ])
+
+    def postprocess(self, data):
+        return data.argmax(1).tolist()


Test patch: