From 61a35a70300e0b1974c3aa8284b5c38acbd58685 Mon Sep 17 00:00:00 2001 From: Animesh Singh Date: Thu, 27 Jun 2019 16:57:21 -0700 Subject: [PATCH] PyTorch Support (#153) * initial pytorch support * modifying go crd files * modifying go crd files * test placeholder * cleaning up test placeholder file * updating with cifar10 sample * updating cifar10 instructions * correcting docker steps * adding pytorch doeckerfile * removing generated data files * correcting the sample pytorch yaml file * adding the class file and class name parameters * adding cifar10 input file and dockerfile * adding gcs location for model file * addressing review comments * simplifying PyTorch interface * making model class name optional * fix the comment ordering * removing model file * adding default behaviour --- .../crds/serving_v1alpha1_kfservice.yaml | 30 + docs/samples/pytorch/README.md | 112 + docs/samples/pytorch/cifar10.py | 79 + docs/samples/pytorch/input.json | 3276 +++++++++++++++++ docs/samples/pytorch/pytorch.yaml | 9 + pkg/apis/serving/v1alpha1/framework.go | 5 + .../v1alpha1/kfservice_framework_pytorch.go | 68 + pkg/apis/serving/v1alpha1/kfservice_types.go | 12 + python/pytorch.Dockerfile | 28 + python/pytorchserver/Makefile | 9 + python/pytorchserver/README.md | 145 + .../pytorchserver/pytorchserver/__init__.py | 15 + .../pytorchserver/pytorchserver/__main__.py | 36 + python/pytorchserver/pytorchserver/model.py | 73 + .../pytorchserver/pytorchserver/test_model.py | 39 + python/pytorchserver/setup.py | 41 + 16 files changed, 3977 insertions(+) create mode 100644 docs/samples/pytorch/README.md create mode 100644 docs/samples/pytorch/cifar10.py create mode 100644 docs/samples/pytorch/input.json create mode 100644 docs/samples/pytorch/pytorch.yaml create mode 100644 pkg/apis/serving/v1alpha1/kfservice_framework_pytorch.go create mode 100644 python/pytorch.Dockerfile create mode 100644 python/pytorchserver/Makefile create mode 100644 python/pytorchserver/README.md create mode 100644 python/pytorchserver/pytorchserver/__init__.py create mode 100644 python/pytorchserver/pytorchserver/__main__.py create mode 100644 python/pytorchserver/pytorchserver/model.py create mode 100644 python/pytorchserver/pytorchserver/test_model.py create mode 100644 python/pytorchserver/setup.py diff --git a/config/default/crds/serving_v1alpha1_kfservice.yaml b/config/default/crds/serving_v1alpha1_kfservice.yaml index 519186b19c7..5b5bea3ab51 100644 --- a/config/default/crds/serving_v1alpha1_kfservice.yaml +++ b/config/default/crds/serving_v1alpha1_kfservice.yaml @@ -65,6 +65,21 @@ spec: 0 in case of no traffic format: int64 type: integer + pytorch: + properties: + modelClassName: + description: Name of the model class for PyTorch model + type: string + modelUri: + type: string + resources: + description: Defaults to requests and limits of 1CPU, 2Gb MEM. + type: object + runtimeVersion: + type: string + required: + - modelUri + type: object serviceAccountName: description: Service Account Name type: string @@ -144,6 +159,21 @@ spec: 0 in case of no traffic format: int64 type: integer + pytorch: + properties: + modelClassName: + description: Defaults to latest PyTorch Version. + type: string + modelUri: + type: string + resources: + description: Defaults to requests and limits of 1CPU, 2Gb MEM. + type: object + runtimeVersion: + type: string + required: + - modelUri + type: object serviceAccountName: description: Service Account Name type: string diff --git a/docs/samples/pytorch/README.md b/docs/samples/pytorch/README.md new file mode 100644 index 00000000000..07bcc4f7768 --- /dev/null +++ b/docs/samples/pytorch/README.md @@ -0,0 +1,112 @@ +## Creating your own model and testing the PyTorch server. + +To test the [PyTorch](https://pytorch.org/) server, first we need to generate a simple cifar10 model using PyTorch. + +```shell +python cifar10.py +``` +You should see an output similar to this + +```shell +Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz +Failed download. Trying https -> http instead. Downloading http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz +100.0%Files already downloaded and verified +[1, 2000] loss: 2.232 +[1, 4000] loss: 1.913 +[1, 6000] loss: 1.675 +[1, 8000] loss: 1.555 +[1, 10000] loss: 1.492 +[1, 12000] loss: 1.488 +[2, 2000] loss: 1.412 +[2, 4000] loss: 1.358 +[2, 6000] loss: 1.362 +[2, 8000] loss: 1.338 +[2, 10000] loss: 1.315 +[2, 12000] loss: 1.278 +Finished Training +``` + +Then, we can run the PyTorch server using the trained model and test for predictions. Models can be on local filesystem, S3 compatible object storage or Google Cloud Storage. + +Note: Currently KFServing supports PyTorch models saved using [state_dict method]((https://pytorch.org/tutorials/beginner/saving_loading_models.html#saving-loading-model-for-inference), PyTorch's recommended way of saving models for inference. The KFServing interface for PyTorch expects users to upload the model_class_file in same location as the PyTorch model, and accepts an optional model_class_name to be passed in as a runtime input. If model class name is not specified, we use 'PyTorchModel' as the default class name. The current interface may undergo changes as we evolve this to support PyTorch models saved using other methods as well. + +```shell +python -m pytorchserver --model_dir ./ --model_name pytorchmodel --model_class_name Net +``` + +We can also use the inbuilt PyTorch support for sample datasets and do some simple predictions + +```python +import torch +import torchvision +import torchvision.transforms as transforms +transform = transforms.Compose([transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) +testset = torchvision.datasets.CIFAR10(root='./data', train=False, + download=True, transform=transform) +testloader = torch.utils.data.DataLoader(testset, batch_size=4, + shuffle=False, num_workers=2) +dataiter = iter(testloader) +images, labels = dataiter.next() +formData = { + 'instances': images[0:1].tolist() +} +res = requests.post('http://localhost:8080/models/pytorchmodel:predict', json=formData) +print(res) +print(res.text) +``` + +# Predict on a KFService using PyTorch + +## Setup +1. Your ~/.kube/config should point to a cluster with [KFServing installed](https://github.com/kubeflow/kfserving/blob/master/docs/DEVELOPER_GUIDE.md#deploy-kfserving). +2. Your cluster's Istio Ingress gateway must be network accessible. +3. Your cluster's Istio Egresss gateway must [allow Google Cloud Storage](https://knative.dev/docs/serving/outbound-network-access/) + +## Create the KFService + +Apply the CRD +``` +kubectl apply -f pytorch.yaml +``` + +Expected Output +``` +$ kfservice.serving.kubeflow.org/pytorch-cifar10 created +``` + +## Run a prediction + +``` +MODEL_NAME=pytorch-cifar10 +INPUT_PATH=@./input.json +CLUSTER_IP=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + +SERVICE_HOSTNAME=$(kubectl get kfservice pytorch-cifar10 -o jsonpath='{.status.url}') + +curl -v -H "Host: ${SERVICE_HOSTNAME}" -d $INPUT_PATH http://$CLUSTER_IP/models/$MODEL_NAME:predict +``` + +You should see an output similar to the one below: + +``` +> POST /models/pytorch-cifar10:predict HTTP/1.1 +> Host: pytorch-cifar10.default.svc.cluster.local +> User-Agent: curl/7.54.0 +> Accept: */* +> Content-Length: 110681 +> Content-Type: application/x-www-form-urlencoded +> Expect: 100-continue +> +< HTTP/1.1 100 Continue +* We are completely uploaded and fine +< HTTP/1.1 200 OK +< content-length: 221 +< content-type: application/json; charset=UTF-8 +< date: Fri, 21 Jun 2019 04:05:39 GMT +< server: istio-envoy +< x-envoy-upstream-service-time: 35292 +< + +{"predictions": [[-0.8955065011978149, -1.4453213214874268, 0.1515328735113144, 2.638284683227539, -1.00240159034729, 2.270702600479126, 0.22645258903503418, -0.880557119846344, 0.08783778548240662, -1.5551214218139648]] +``` \ No newline at end of file diff --git a/docs/samples/pytorch/cifar10.py b/docs/samples/pytorch/cifar10.py new file mode 100644 index 00000000000..5509e3d13fe --- /dev/null +++ b/docs/samples/pytorch/cifar10.py @@ -0,0 +1,79 @@ +import torch +import torchvision +import torchvision.transforms as transforms +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim + + +class Net(nn.Module): + def __init__(self): + super(Net, self).__init__() + self.conv1 = nn.Conv2d(3, 6, 5) + self.pool = nn.MaxPool2d(2, 2) + self.conv2 = nn.Conv2d(6, 16, 5) + self.fc1 = nn.Linear(16 * 5 * 5, 120) + self.fc2 = nn.Linear(120, 84) + self.fc3 = nn.Linear(84, 10) + + def forward(self, x): + x = self.pool(F.relu(self.conv1(x))) + x = self.pool(F.relu(self.conv2(x))) + x = x.view(-1, 16 * 5 * 5) + x = F.relu(self.fc1(x)) + x = F.relu(self.fc2(x)) + x = self.fc3(x) + return x + + +if __name__ == "__main__": + + transform = transforms.Compose( + [transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) + + trainset = torchvision.datasets.CIFAR10(root='./data', train=True, + download=True, transform=transform) + trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, + shuffle=True, num_workers=2) + + testset = torchvision.datasets.CIFAR10(root='./data', train=False, + download=True, transform=transform) + testloader = torch.utils.data.DataLoader(testset, batch_size=4, + shuffle=False, num_workers=2) + + classes = ('plane', 'car', 'bird', 'cat', + 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') + + net = Net() + + criterion = nn.CrossEntropyLoss() + optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) + + for epoch in range(2): # loop over the dataset multiple times + + running_loss = 0.0 + for i, data in enumerate(trainloader, 0): + # get the inputs; data is a list of [inputs, labels] + inputs, labels = data + + # zero the parameter gradients + optimizer.zero_grad() + + # forward + backward + optimize + outputs = net(inputs) + loss = criterion(outputs, labels) + loss.backward() + optimizer.step() + + # print statistics + running_loss += loss.item() + if i % 2000 == 1999: # print every 2000 mini-batches + print('[%d, %5d] loss: %.3f' % + (epoch + 1, i + 1, running_loss / 2000)) + running_loss = 0.0 + + print('Finished Training') + + # Save model + torch.save(net.state_dict(), "model.pt") diff --git a/docs/samples/pytorch/input.json b/docs/samples/pytorch/input.json new file mode 100644 index 00000000000..0ff14716c9b --- /dev/null +++ b/docs/samples/pytorch/input.json @@ -0,0 +1,3276 @@ +{ + "instances":[ + [ + [ + [ + 0.23921573162078857, + 0.24705886840820312, + 0.29411768913269043, + 0.301960825920105, + 0.2549020051956177, + 0.22352945804595947, + 0.2705882787704468, + 0.24705886840820312, + 0.23921573162078857, + 0.24705886840820312, + 0.2627451419830322, + 0.2549020051956177, + 0.2627451419830322, + 0.301960825920105, + 0.32549023628234863, + 0.3333333730697632, + 0.30980396270751953, + 0.2705882787704468, + 0.2549020051956177, + 0.2549020051956177, + 0.22352945804595947, + 0.16862750053405762, + 0.17647063732147217, + 0.16078436374664307, + 0.16862750053405762, + 0.12156867980957031, + 0.09803926944732666, + 0.10588240623474121, + 0.12156867980957031, + 0.07450985908508301, + -0.011764705181121826, + -0.09019607305526733 + ], + [ + 0.19215691089630127, + 0.18431377410888672, + 0.24705886840820312, + 0.301960825920105, + 0.2705882787704468, + 0.2549020051956177, + 0.2862745523452759, + 0.2705882787704468, + 0.27843141555786133, + 0.22352945804595947, + 0.21568632125854492, + 0.24705886840820312, + 0.27843141555786133, + 0.3333333730697632, + 0.34117650985717773, + 0.34117650985717773, + 0.32549023628234863, + 0.2549020051956177, + 0.20784318447113037, + 0.18431377410888672, + 0.13725495338439941, + 0.09019613265991211, + 0.09803926944732666, + 0.10588240623474121, + 0.16862750053405762, + 0.15294122695922852, + 0.13725495338439941, + 0.11372554302215576, + 0.12156867980957031, + 0.06666672229766846, + -0.019607841968536377, + -0.06666666269302368 + ], + [ + 0.18431377410888672, + 0.18431377410888672, + 0.23921573162078857, + 0.30980396270751953, + 0.2549020051956177, + 0.27843141555786133, + 0.29411768913269043, + 0.29411768913269043, + 0.27843141555786133, + 0.2705882787704468, + 0.23921573162078857, + 0.23137259483337402, + 0.2627451419830322, + 0.301960825920105, + 0.30980396270751953, + 0.32549023628234863, + 0.3333333730697632, + 0.24705886840820312, + 0.13725495338439941, + -0.05098038911819458, + -0.13725489377975464, + -0.23137253522872925, + -0.2078431248664856, + -0.10588234663009644, + -0.05882352590560913, + 0.050980448722839355, + 0.12156867980957031, + 0.09803926944732666, + 0.11372554302215576, + 0.09019613265991211, + 0.019607901573181152, + -0.05882352590560913 + ], + [ + 0.21568632125854492, + 0.21568632125854492, + 0.2549020051956177, + 0.3647059202194214, + 0.30980396270751953, + 0.30980396270751953, + 0.32549023628234863, + 0.32549023628234863, + 0.29411768913269043, + 0.29411768913269043, + 0.30980396270751953, + 0.49803924560546875, + 0.38823533058166504, + 0.23137259483337402, + 0.2705882787704468, + 0.2862745523452759, + 0.23921573162078857, + 0.16862750053405762, + -0.18431371450424194, + -0.1921568512916565, + -0.23137253522872925, + -0.27843135595321655, + -0.37254899740219116, + -0.41960781812667847, + -0.32549017667770386, + -0.3490195870399475, + -0.11372548341751099, + 0.035294175148010254, + 0.09803926944732666, + 0.09803926944732666, + 0.06666672229766846, + -0.003921568393707275 + ], + [ + 0.21568632125854492, + 0.22352945804595947, + 0.2627451419830322, + 0.3333333730697632, + 0.32549023628234863, + 0.27843141555786133, + 0.32549023628234863, + 0.301960825920105, + 0.2862745523452759, + 0.2862745523452759, + 0.35686278343200684, + 0.929411768913269, + 0.529411792755127, + 0.18431377410888672, + 0.14509809017181396, + 0.11372554302215576, + -0.1294117569923401, + -0.38823527097702026, + -0.3333333134651184, + -0.11372548341751099, + -0.12156862020492554, + -0.16862744092941284, + -0.2392156720161438, + -0.270588219165802, + -0.41960781812667847, + -0.34117645025253296, + -0.3333333134651184, + -0.1764705777168274, + 0.003921627998352051, + 0.08235299587249756, + 0.043137311935424805, + 0.011764764785766602 + ], + [ + 0.16078436374664307, + 0.043137311935424805, + 0.019607901573181152, + 0.15294122695922852, + 0.2627451419830322, + 0.29411768913269043, + 0.30980396270751953, + 0.30980396270751953, + 0.27843141555786133, + 0.29411768913269043, + 0.27843141555786133, + 0.4117647409439087, + 0.23137259483337402, + 0.003921627998352051, + -0.2392156720161438, + -0.4823529124259949, + -0.4588235020637512, + -0.4823529124259949, + -0.3019607663154602, + -0.07450979948043823, + -0.04313725233078003, + -0.06666666269302368, + -0.10588234663009644, + -0.26274508237838745, + -0.2235293984413147, + -0.2862744927406311, + -0.545098066329956, + -0.4745097756385803, + -0.15294116735458374, + 0.09803926944732666, + 0.08235299587249756, + 0.050980448722839355 + ], + [ + -0.003921568393707275, + -0.1450980305671692, + -0.6313725709915161, + -0.30980390310287476, + 0.20000004768371582, + 0.3333333730697632, + 0.3176470994949341, + 0.3333333730697632, + 0.32549023628234863, + 0.301960825920105, + 0.2862745523452759, + 0.15294122695922852, + 0.011764764785766602, + -0.003921568393707275, + -0.21568626165390015, + -0.46666663885116577, + -0.38823527097702026, + -0.43529409170150757, + -0.3490195870399475, + 0.035294175148010254, + 0.14509809017181396, + -0.027450978755950928, + -0.1764705777168274, + -0.1607843041419983, + -0.09803920984268188, + -0.3333333134651184, + -0.5058823823928833, + -0.6392157077789307, + -0.3803921341896057, + 0.035294175148010254, + 0.10588240623474121, + 0.050980448722839355 + ], + [ + 0.027451038360595703, + -0.2235293984413147, + -0.6705882549285889, + -0.45098036527633667, + 0.12156867980957031, + 0.30980396270751953, + 0.29411768913269043, + 0.3176470994949341, + 0.34117650985717773, + 0.2627451419830322, + 0.09803926944732666, + -0.05882352590560913, + 0.019607901573181152, + 0.12941181659698486, + -0.09019607305526733, + -0.30980390310287476, + -0.2862744927406311, + -0.3333333134651184, + -0.3960784077644348, + -0.027450978755950928, + 0.27843141555786133, + 0.06666672229766846, + -0.19999998807907104, + -0.16862744092941284, + -0.21568626165390015, + -0.3333333134651184, + -0.5764706134796143, + -0.615686297416687, + -0.5529412031173706, + -0.1607843041419983, + 0.08235299587249756, + 0.06666672229766846 + ], + [ + 0.3333333730697632, + -0.1921568512916565, + -0.5764706134796143, + -0.027450978755950928, + 0.20000004768371582, + 0.2627451419830322, + 0.27843141555786133, + 0.301960825920105, + 0.29411768913269043, + 0.3647059202194214, + -0.11372548341751099, + -0.019607841968536377, + 0.23137259483337402, + 0.22352945804595947, + -0.05098038911819458, + -0.32549017667770386, + -0.35686272382736206, + -0.34117645025253296, + -0.37254899740219116, + -0.3647058606147766, + 0.08235299587249756, + 0.14509809017181396, + -0.11372548341751099, + -0.3176470398902893, + -0.3490195870399475, + -0.32549017667770386, + -0.4431372284889221, + -0.5607843399047852, + -0.686274528503418, + -0.41960781812667847, + 0.043137311935424805, + 0.07450985908508301 + ], + [ + 0.4117647409439087, + 0.050980448722839355, + -0.26274508237838745, + 0.20784318447113037, + 0.3647059202194214, + 0.23921573162078857, + 0.22352945804595947, + 0.20000004768371582, + 0.6235294342041016, + 0.8588235378265381, + 0.6235294342041016, + 0.22352945804595947, + 0.3647059202194214, + 0.16078436374664307, + -0.019607841968536377, + -0.270588219165802, + -0.32549017667770386, + -0.41960781812667847, + -0.5372549295425415, + -0.40392154455184937, + 0.07450985908508301, + 0.12156867980957031, + 0.043137311935424805, + -0.16862744092941284, + -0.32549017667770386, + -0.3176470398902893, + -0.34117645025253296, + -0.4117646813392639, + -0.6078431606292725, + -0.686274528503418, + -0.2549019455909729, + 0.035294175148010254 + ], + [ + 0.43529415130615234, + -0.15294116735458374, + 0.11372554302215576, + 0.29411768913269043, + 0.38823533058166504, + 0.21568632125854492, + 0.24705886840820312, + -0.04313725233078003, + 0.6705882549285889, + 0.8588235378265381, + 0.7254902124404907, + 0.2862745523452759, + 0.43529415130615234, + 0.22352945804595947, + -0.019607841968536377, + -0.05882352590560913, + -0.38823527097702026, + -0.37254899740219116, + -0.6470588445663452, + -0.2862744927406311, + 0.37254905700683594, + 0.23137259483337402, + 0.21568632125854492, + -0.1607843041419983, + -0.3176470398902893, + -0.1921568512916565, + -0.30980390310287476, + -0.38823527097702026, + -0.5372549295425415, + -0.6784313917160034, + -0.5372549295425415, + -0.18431371450424194 + ], + [ + 0.4745098352432251, + -0.21568626165390015, + 0.058823585510253906, + 0.3333333730697632, + 0.46666669845581055, + 0.301960825920105, + 0.35686278343200684, + 0.050980448722839355, + -0.08235293626785278, + 0.5215686559677124, + 0.5607843399047852, + 0.3333333730697632, + 0.45098042488098145, + 0.48235297203063965, + 0.050980448722839355, + -0.08235293626785278, + -0.19999998807907104, + -0.34117645025253296, + -0.7019608020782471, + -0.019607841968536377, + 0.6470588445663452, + 0.2549020051956177, + 0.14509809017181396, + -0.270588219165802, + -0.3490195870399475, + -0.26274508237838745, + -0.18431371450424194, + -0.3333333134651184, + -0.427450954914093, + -0.5686274766921997, + -0.5137255191802979, + -0.40392154455184937 + ], + [ + 0.48235297203063965, + -0.29411762952804565, + -0.003921568393707275, + 0.37254905700683594, + 0.3647059202194214, + 0.301960825920105, + 0.3960784673690796, + 0.24705886840820312, + -0.2392156720161438, + 0.3176470994949341, + 0.3176470994949341, + 0.07450985908508301, + 0.458823561668396, + 0.6941176652908325, + 0.2549020051956177, + -0.03529411554336548, + -0.05882352590560913, + -0.09803920984268188, + -0.6078431606292725, + 0.17647063732147217, + 0.5215686559677124, + 0.21568632125854492, + -0.03529411554336548, + -0.2862744927406311, + -0.34117645025253296, + -0.34117645025253296, + -0.2549019455909729, + -0.32549017667770386, + -0.34117645025253296, + -0.427450954914093, + -0.3803921341896057, + -0.427450954914093 + ], + [ + 0.48235297203063965, + -0.270588219165802, + 0.19215691089630127, + 0.45098042488098145, + -0.06666666269302368, + 0.06666672229766846, + 0.35686278343200684, + 0.30980396270751953, + -0.1921568512916565, + 0.15294122695922852, + 0.13725495338439941, + 0.30980396270751953, + 0.48235297203063965, + 0.772549033164978, + 0.4117647409439087, + 0.10588240623474121, + -0.011764705181121826, + -0.08235293626785278, + -0.4431372284889221, + 0.20784318447113037, + 0.458823561668396, + 0.16862750053405762, + -0.10588234663009644, + -0.3176470398902893, + -0.37254899740219116, + -0.43529409170150757, + -0.37254899740219116, + -0.2235293984413147, + -0.21568626165390015, + -0.29411762952804565, + -0.2392156720161438, + -0.26274508237838745 + ], + [ + 0.5215686559677124, + -0.15294116735458374, + 0.3176470994949341, + 0.458823561668396, + -0.1764705777168274, + -0.2235293984413147, + 0.22352945804595947, + 0.30980396270751953, + -0.21568626165390015, + -0.09803920984268188, + 0.08235299587249756, + 0.5529412031173706, + 0.4901961088180542, + 0.3490196466445923, + 0.13725495338439941, + 0.20784318447113037, + 0.14509809017181396, + -0.1921568512916565, + -0.4431372284889221, + 0.19215691089630127, + 0.40392160415649414, + 0.07450985908508301, + 0.019607901573181152, + -0.13725489377975464, + -0.3333333134651184, + -0.2862744927406311, + -0.2549019455909729, + -0.1450980305671692, + -0.09803920984268188, + -0.21568626165390015, + -0.2392156720161438, + -0.08235293626785278 + ], + [ + 0.545098066329956, + 0.035294175148010254, + 0.3490196466445923, + 0.4431372880935669, + 0.019607901573181152, + -0.38823527097702026, + 0.09803926944732666, + 0.21568632125854492, + -0.09803920984268188, + 0.019607901573181152, + 0.12156867980957031, + 0.8039215803146362, + 0.8980392217636108, + 0.13725495338439941, + 0.058823585510253906, + 0.027451038360595703, + -0.05098038911819458, + -0.15294116735458374, + -0.2549019455909729, + 0.12941181659698486, + 0.3176470994949341, + 0.19215691089630127, + -0.12156862020492554, + -0.3176470398902893, + -0.4431372284889221, + -0.3176470398902893, + -0.1764705777168274, + -0.12156862020492554, + -0.05882352590560913, + -0.1921568512916565, + -0.05098038911819458, + 0.06666672229766846 + ], + [ + 0.5921568870544434, + 0.14509809017181396, + 0.3176470994949341, + 0.49803924560546875, + 0.3176470994949341, + -0.38823527097702026, + -0.011764705181121826, + 0.08235299587249756, + 0.08235299587249756, + -0.24705880880355835, + 0.20784318447113037, + 0.35686278343200684, + 0.2705882787704468, + 0.09803926944732666, + -0.11372548341751099, + -0.11372548341751099, + -0.2078431248664856, + -0.1764705777168274, + -0.12156862020492554, + 0.34117650985717773, + 0.22352945804595947, + 0.16078436374664307, + 0.058823585510253906, + -0.1450980305671692, + -0.38823527097702026, + -0.3803921341896057, + -0.26274508237838745, + -0.2078431248664856, + -0.1607843041419983, + -0.019607841968536377, + 0.18431377410888672, + 0.12941181659698486 + ], + [ + 0.6784313917160034, + 0.27843141555786133, + 0.2862745523452759, + 0.43529415130615234, + 0.3803921937942505, + -0.26274508237838745, + -0.24705880880355835, + 0.22352945804595947, + 0.16078436374664307, + -0.16862744092941284, + 0.011764764785766602, + -0.07450979948043823, + -0.10588234663009644, + -0.09019607305526733, + -0.19999998807907104, + -0.09803920984268188, + -0.32549017667770386, + -0.2078431248664856, + 0.12941181659698486, + -0.07450979948043823, + -0.46666663885116577, + 0.003921627998352051, + 0.043137311935424805, + -0.4117646813392639, + -0.529411792755127, + -0.545098066329956, + -0.4431372284889221, + -0.19999998807907104, + -0.09019607305526733, + 0.12156867980957031, + 0.17647063732147217, + 0.09803926944732666 + ], + [ + 0.6627451181411743, + 0.3960784673690796, + 0.30980396270751953, + 0.35686278343200684, + 0.3803921937942505, + -0.027450978755950928, + -0.32549017667770386, + 0.10588240623474121, + 0.20000004768371582, + 0.058823585510253906, + -0.18431371450424194, + -0.3960784077644348, + 0.050980448722839355, + -0.027450978755950928, + 0.011764764785766602, + 0.15294122695922852, + -0.3333333134651184, + -0.27843135595321655, + 0.17647063732147217, + 0.035294175148010254, + -0.08235293626785278, + -0.1607843041419983, + -0.4117646813392639, + -0.498039186000824, + -0.6549019813537598, + -0.4901960492134094, + -0.32549017667770386, + 0.043137311935424805, + 0.21568632125854492, + 0.2549020051956177, + 0.20784318447113037, + 0.18431377410888672 + ], + [ + 0.5607843399047852, + 0.46666669845581055, + 0.34117650985717773, + 0.3647059202194214, + 0.38823533058166504, + 0.12941181659698486, + -0.32549017667770386, + -0.06666666269302368, + -0.04313725233078003, + 0.07450985908508301, + 0.12941181659698486, + -0.45098036527633667, + 0.011764764785766602, + -0.15294116735458374, + 0.13725495338439941, + 0.4431372880935669, + -0.09019607305526733, + -0.427450954914093, + 0.027451038360595703, + 0.07450985908508301, + 0.050980448722839355, + -0.3019607663154602, + -0.6000000238418579, + -0.5921568870544434, + -0.6313725709915161, + -0.29411762952804565, + -0.05098038911819458, + 0.27843141555786133, + 0.34117650985717773, + 0.2862745523452759, + 0.23921573162078857, + 0.16862750053405762 + ], + [ + 0.29411768913269043, + 0.529411792755127, + 0.40392160415649414, + 0.38823533058166504, + 0.41960787773132324, + 0.19215691089630127, + -0.2235293984413147, + 0.027451038360595703, + 0.34117650985717773, + -0.1921568512916565, + -0.270588219165802, + -0.37254899740219116, + -0.270588219165802, + -0.04313725233078003, + 0.3960784673690796, + 0.49803924560546875, + 0.17647063732147217, + -0.21568626165390015, + -0.3019607663154602, + -0.3176470398902893, + -0.529411792755127, + -0.6392157077789307, + -0.7019608020782471, + -0.8117647171020508, + -0.6392157077789307, + -0.529411792755127, + -0.15294116735458374, + 0.12941181659698486, + 0.12941181659698486, + 0.003921627998352051, + -0.003921568393707275, + -0.05882352590560913 + ], + [ + -0.08235293626785278, + 0.529411792755127, + 0.38823533058166504, + 0.3960784673690796, + 0.41960787773132324, + 0.08235299587249756, + -0.3490195870399475, + 0.17647063732147217, + 0.9215686321258545, + 0.7176470756530762, + 0.043137311935424805, + 0.050980448722839355, + 0.16862750053405762, + 0.3803921937942505, + 0.4901961088180542, + 0.5215686559677124, + 0.3176470994949341, + -0.019607841968536377, + -0.13725489377975464, + -0.5215686559677124, + -0.7254902124404907, + -0.7333333492279053, + -0.615686297416687, + -0.545098066329956, + -0.5215686559677124, + -0.545098066329956, + -0.4588235020637512, + -0.43529409170150757, + -0.38823527097702026, + -0.4588235020637512, + -0.5372549295425415, + -0.5686274766921997 + ], + [ + -0.3803921341896057, + 0.37254905700683594, + 0.3647059202194214, + 0.3803921937942505, + 0.38823533058166504, + 0.09803926944732666, + -0.1450980305671692, + 0.6549019813537598, + 0.9843137264251709, + 0.9764705896377563, + 0.6313725709915161, + -0.027450978755950928, + -0.10588234663009644, + -0.027450978755950928, + -0.09019607305526733, + -0.04313725233078003, + -0.18431371450424194, + -0.46666663885116577, + -0.46666663885116577, + -0.529411792755127, + -0.5921568870544434, + -0.6078431606292725, + -0.6000000238418579, + -0.5607843399047852, + -0.5607843399047852, + -0.6000000238418579, + -0.6627451181411743, + -0.6000000238418579, + -0.5372549295425415, + -0.6235294342041016, + -0.6627451181411743, + -0.6705882549285889 + ], + [ + -0.6784313917160034, + -0.24705880880355835, + 0.12941181659698486, + 0.3176470994949341, + 0.3960784673690796, + 0.29411768913269043, + 0.29411768913269043, + 0.929411768913269, + 0.9843137264251709, + 0.7803921699523926, + -0.13725489377975464, + -0.529411792755127, + -0.5843137502670288, + -0.615686297416687, + -0.615686297416687, + -0.6235294342041016, + -0.6470588445663452, + -0.6705882549285889, + -0.6392157077789307, + -0.6705882549285889, + -0.7019608020782471, + -0.6392157077789307, + -0.6392157077789307, + -0.6627451181411743, + -0.6705882549285889, + -0.6392157077789307, + -0.6392157077789307, + -0.6078431606292725, + -0.5686274766921997, + -0.5843137502670288, + -0.6000000238418579, + -0.6470588445663452 + ], + [ + -0.772549033164978, + -0.772549033164978, + -0.5372549295425415, + 0.027451038360595703, + 0.301960825920105, + 0.035294175148010254, + 0.5215686559677124, + 0.9921568632125854, + 0.8901960849761963, + 0.10588240623474121, + -0.5215686559677124, + -0.6078431606292725, + -0.6078431606292725, + -0.6000000238418579, + -0.615686297416687, + -0.6078431606292725, + -0.6313725709915161, + -0.6705882549285889, + -0.6941176652908325, + -0.7333333492279053, + -0.7254902124404907, + -0.6941176652908325, + -0.7019608020782471, + -0.6705882549285889, + -0.6470588445663452, + -0.5607843399047852, + -0.5137255191802979, + -0.5372549295425415, + -0.5607843399047852, + -0.6078431606292725, + -0.6392157077789307, + -0.6000000238418579 + ], + [ + -0.6235294342041016, + -0.7647058963775635, + -0.7333333492279053, + -0.427450954914093, + 0.003921627998352051, + 0.003921627998352051, + 0.686274528503418, + 1.0, + 0.46666669845581055, + -0.4823529124259949, + -0.5764706134796143, + -0.6078431606292725, + -0.5921568870544434, + -0.5921568870544434, + -0.6392157077789307, + -0.6470588445663452, + -0.6627451181411743, + -0.6784313917160034, + -0.7176470756530762, + -0.6941176652908325, + -0.686274528503418, + -0.686274528503418, + -0.6627451181411743, + -0.6392157077789307, + -0.5372549295425415, + -0.5137255191802979, + -0.498039186000824, + -0.5372549295425415, + -0.5764706134796143, + -0.6078431606292725, + -0.45098036527633667, + -0.3490195870399475 + ], + [ + -0.5921568870544434, + -0.7254902124404907, + -0.7568627595901489, + -0.6784313917160034, + -0.4823529124259949, + 0.003921627998352051, + 0.7568627595901489, + 0.8823529481887817, + -0.027450978755950928, + -0.545098066329956, + -0.615686297416687, + -0.5607843399047852, + -0.5764706134796143, + -0.6549019813537598, + -0.6549019813537598, + -0.6313725709915161, + -0.6392157077789307, + -0.6627451181411743, + -0.6627451181411743, + -0.6549019813537598, + -0.6549019813537598, + -0.6470588445663452, + -0.5764706134796143, + -0.545098066329956, + -0.5764706134796143, + -0.6392157077789307, + -0.6627451181411743, + -0.7176470756530762, + -0.6000000238418579, + -0.427450954914093, + -0.3333333134651184, + -0.40392154455184937 + ], + [ + -0.6078431606292725, + -0.7254902124404907, + -0.772549033164978, + -0.7254902124404907, + -0.6549019813537598, + -0.38823527097702026, + 0.5843137502670288, + 0.6549019813537598, + -0.2392156720161438, + -0.4901960492134094, + -0.5764706134796143, + -0.6235294342041016, + -0.545098066329956, + -0.6235294342041016, + -0.686274528503418, + -0.6470588445663452, + -0.6313725709915161, + -0.6235294342041016, + -0.6313725709915161, + -0.6392157077789307, + -0.6000000238418579, + -0.6941176652908325, + -0.6941176652908325, + -0.6235294342041016, + -0.6313725709915161, + -0.6941176652908325, + -0.7803921699523926, + -0.686274528503418, + -0.4745097756385803, + -0.4745097756385803, + -0.6392157077789307, + -0.6000000238418579 + ], + [ + -0.6078431606292725, + -0.7254902124404907, + -0.7490196228027344, + -0.7411764860153198, + -0.6784313917160034, + -0.6392157077789307, + -0.18431371450424194, + 0.3333333730697632, + -0.498039186000824, + -0.5764706134796143, + -0.5921568870544434, + -0.5843137502670288, + -0.5215686559677124, + -0.545098066329956, + -0.5764706134796143, + -0.6470588445663452, + -0.6705882549285889, + -0.6784313917160034, + -0.6392157077789307, + -0.615686297416687, + -0.6392157077789307, + -0.6705882549285889, + -0.686274528503418, + -0.6941176652908325, + -0.7098039388656616, + -0.686274528503418, + -0.6549019813537598, + -0.5058823823928833, + -0.6313725709915161, + -0.7568627595901489, + -0.8823529481887817, + -0.6000000238418579 + ], + [ + -0.46666663885116577, + -0.6705882549285889, + -0.7568627595901489, + -0.7019608020782471, + -0.7098039388656616, + -0.6627451181411743, + -0.6705882549285889, + -0.4431372284889221, + -0.615686297416687, + -0.7568627595901489, + -0.7882353067398071, + -0.7019608020782471, + -0.615686297416687, + -0.5607843399047852, + -0.545098066329956, + -0.5843137502670288, + -0.5607843399047852, + -0.529411792755127, + -0.5529412031173706, + -0.5843137502670288, + -0.6078431606292725, + -0.6470588445663452, + -0.6941176652908325, + -0.7411764860153198, + -0.6705882549285889, + -0.5137255191802979, + -0.3803921341896057, + -0.427450954914093, + -0.5607843399047852, + -0.7019608020782471, + -0.8980392217636108, + -0.686274528503418 + ], + [ + -0.5215686559677124, + -0.615686297416687, + -0.7254902124404907, + -0.6627451181411743, + -0.6941176652908325, + -0.6705882549285889, + -0.6549019813537598, + -0.686274528503418, + -0.6705882549285889, + -0.7882353067398071, + -0.8196078538894653, + -0.7647058963775635, + -0.7882353067398071, + -0.772549033164978, + -0.7176470756530762, + -0.6313725709915161, + -0.5607843399047852, + -0.5137255191802979, + -0.4823529124259949, + -0.4117646813392639, + -0.4588235020637512, + -0.615686297416687, + -0.6627451181411743, + -0.6627451181411743, + -0.529411792755127, + -0.3333333134651184, + -0.1450980305671692, + -0.270588219165802, + -0.529411792755127, + -0.7960784435272217, + -0.772549033164978, + -0.843137264251709 + ], + [ + -0.5764706134796143, + -0.5607843399047852, + -0.6470588445663452, + -0.6627451181411743, + -0.686274528503418, + -0.686274528503418, + -0.686274528503418, + -0.7019608020782471, + -0.7176470756530762, + -0.7960784435272217, + -0.8274509906768799, + -0.772549033164978, + -0.8039215803146362, + -0.772549033164978, + -0.8509804010391235, + -0.8588235378265381, + -0.7490196228027344, + -0.6313725709915161, + -0.5215686559677124, + -0.41960781812667847, + -0.4823529124259949, + -0.5843137502670288, + -0.5921568870544434, + -0.6470588445663452, + -0.4745097756385803, + -0.3019607663154602, + -0.1764705777168274, + -0.3019607663154602, + -0.6235294342041016, + -0.8117647171020508, + -0.7333333492279053, + -0.8352941274642944 + ] + ], + [ + [ + -0.12156862020492554, + -0.1294117569923401, + -0.09019607305526733, + -0.07450979948043823, + -0.12156862020492554, + -0.1450980305671692, + -0.09803920984268188, + -0.11372548341751099, + -0.1294117569923401, + -0.11372548341751099, + -0.09019607305526733, + -0.1294117569923401, + -0.1294117569923401, + -0.08235293626785278, + -0.08235293626785278, + -0.06666666269302368, + -0.08235293626785278, + -0.11372548341751099, + -0.1294117569923401, + -0.12156862020492554, + -0.1450980305671692, + -0.1607843041419983, + -0.1607843041419983, + -0.16862744092941284, + -0.1607843041419983, + -0.2078431248664856, + -0.23137253522872925, + -0.2392156720161438, + -0.2392156720161438, + -0.2549019455909729, + -0.2862744927406311, + -0.3333333134651184 + ], + [ + -0.12156862020492554, + -0.13725489377975464, + -0.10588234663009644, + -0.09019607305526733, + -0.12156862020492554, + -0.11372548341751099, + -0.08235293626785278, + -0.10588234663009644, + -0.09019607305526733, + -0.13725489377975464, + -0.1294117569923401, + -0.13725489377975464, + -0.11372548341751099, + -0.06666666269302368, + -0.08235293626785278, + -0.09803920984268188, + -0.09803920984268188, + -0.1294117569923401, + -0.12156862020492554, + -0.09803920984268188, + -0.13725489377975464, + -0.18431371450424194, + -0.19999998807907104, + -0.21568626165390015, + -0.1764705777168274, + -0.19999998807907104, + -0.19999998807907104, + -0.2392156720161438, + -0.23137253522872925, + -0.2549019455909729, + -0.2862744927406311, + -0.30980390310287476 + ], + [ + -0.13725489377975464, + -0.1450980305671692, + -0.1294117569923401, + -0.1294117569923401, + -0.16862744092941284, + -0.09803920984268188, + -0.08235293626785278, + -0.08235293626785278, + -0.09803920984268188, + -0.09803920984268188, + -0.10588234663009644, + -0.1450980305671692, + -0.1294117569923401, + -0.09803920984268188, + -0.10588234663009644, + -0.11372548341751099, + -0.09019607305526733, + -0.10588234663009644, + -0.1294117569923401, + -0.24705880880355835, + -0.29411762952804565, + -0.38823527097702026, + -0.3960784077644348, + -0.3333333134651184, + -0.32549017667770386, + -0.24705880880355835, + -0.1921568512916565, + -0.2235293984413147, + -0.2235293984413147, + -0.23137253522872925, + -0.2549019455909729, + -0.3019607663154602 + ], + [ + -0.1607843041419983, + -0.13725489377975464, + -0.1450980305671692, + -0.12156862020492554, + -0.13725489377975464, + -0.08235293626785278, + -0.05882352590560913, + -0.06666666269302368, + -0.09803920984268188, + -0.08235293626785278, + -0.03529411554336548, + 0.14509809017181396, + 0.019607901573181152, + -0.1294117569923401, + -0.09803920984268188, + -0.10588234663009644, + -0.12156862020492554, + -0.1294117569923401, + -0.37254899740219116, + -0.3176470398902893, + -0.29411762952804565, + -0.29411762952804565, + -0.4117646813392639, + -0.5058823823928833, + -0.45098036527633667, + -0.5137255191802979, + -0.3333333134651184, + -0.23137253522872925, + -0.19999998807907104, + -0.2078431248664856, + -0.2235293984413147, + -0.26274508237838745 + ], + [ + -0.1607843041419983, + -0.10588234663009644, + -0.09803920984268188, + -0.10588234663009644, + -0.10588234663009644, + -0.11372548341751099, + -0.05882352590560913, + -0.09019607305526733, + -0.11372548341751099, + -0.09019607305526733, + 0.003921627998352051, + 0.6784313917160034, + 0.22352945804595947, + -0.10588234663009644, + -0.1294117569923401, + -0.15294116735458374, + -0.37254899740219116, + -0.5843137502670288, + -0.4588235020637512, + -0.1921568512916565, + -0.13725489377975464, + -0.10588234663009644, + -0.19999998807907104, + -0.26274508237838745, + -0.43529409170150757, + -0.38823527097702026, + -0.427450954914093, + -0.3490195870399475, + -0.24705880880355835, + -0.2078431248664856, + -0.26274508237838745, + -0.270588219165802 + ], + [ + -0.1450980305671692, + -0.18431371450424194, + -0.21568626165390015, + -0.12156862020492554, + -0.09803920984268188, + -0.11372548341751099, + -0.09019607305526733, + -0.09803920984268188, + -0.1294117569923401, + -0.09019607305526733, + -0.07450979948043823, + 0.08235299587249756, + -0.04313725233078003, + -0.19999998807907104, + -0.4117646813392639, + -0.6078431606292725, + -0.545098066329956, + -0.5607843399047852, + -0.3490195870399475, + -0.11372548341751099, + -0.05098038911819458, + -0.04313725233078003, + -0.09019607305526733, + -0.24705880880355835, + -0.21568626165390015, + -0.2862744927406311, + -0.545098066329956, + -0.545098066329956, + -0.34117645025253296, + -0.1764705777168274, + -0.23137253522872925, + -0.2549019455909729 + ], + [ + -0.21568626165390015, + -0.2549019455909729, + -0.7098039388656616, + -0.41960781812667847, + -0.08235293626785278, + -0.07450979948043823, + -0.09803920984268188, + -0.07450979948043823, + -0.08235293626785278, + -0.09019607305526733, + -0.05882352590560913, + -0.1607843041419983, + -0.23137253522872925, + -0.15294116735458374, + -0.3176470398902893, + -0.4745097756385803, + -0.3490195870399475, + -0.4117646813392639, + -0.34117645025253296, + 0.019607901573181152, + 0.11372554302215576, + -0.07450979948043823, + -0.2235293984413147, + -0.19999998807907104, + -0.1294117569923401, + -0.3490195870399475, + -0.4431372284889221, + -0.6313725709915161, + -0.5215686559677124, + -0.23137253522872925, + -0.2235293984413147, + -0.270588219165802 + ], + [ + -0.09803920984268188, + -0.24705880880355835, + -0.6627451181411743, + -0.498039186000824, + -0.1294117569923401, + -0.08235293626785278, + -0.10588234663009644, + -0.09019607305526733, + -0.06666666269302368, + -0.11372548341751099, + -0.1450980305671692, + -0.26274508237838745, + -0.13725489377975464, + 0.027451038360595703, + -0.16862744092941284, + -0.3176470398902893, + -0.2549019455909729, + -0.30980390310287476, + -0.3960784077644348, + -0.07450979948043823, + 0.20000004768371582, + -0.027450978755950928, + -0.270588219165802, + -0.23137253522872925, + -0.270588219165802, + -0.3647058606147766, + -0.529411792755127, + -0.5843137502670288, + -0.6313725709915161, + -0.3490195870399475, + -0.1921568512916565, + -0.2392156720161438 + ], + [ + 0.2627451419830322, + -0.1764705777168274, + -0.545098066329956, + -0.05098038911819458, + -0.027450978755950928, + -0.11372548341751099, + -0.08235293626785278, + -0.04313725233078003, + -0.05098038911819458, + 0.058823585510253906, + -0.3019607663154602, + -0.1764705777168274, + 0.10588240623474121, + 0.12156867980957031, + -0.1294117569923401, + -0.37254899740219116, + -0.3647058606147766, + -0.3333333134651184, + -0.38823527097702026, + -0.4431372284889221, + -0.019607841968536377, + 0.058823585510253906, + -0.1921568512916565, + -0.3803921341896057, + -0.3960784077644348, + -0.35686272382736206, + -0.427450954914093, + -0.5529412031173706, + -0.7254902124404907, + -0.5372549295425415, + -0.16862744092941284, + -0.1921568512916565 + ], + [ + 0.3803921937942505, + 0.09019613265991211, + -0.21568626165390015, + 0.20784318447113037, + 0.16862750053405762, + -0.09019607305526733, + -0.09019607305526733, + -0.07450979948043823, + 0.4117647409439087, + 0.6784313917160034, + 0.4117647409439087, + 0.027451038360595703, + 0.20000004768371582, + 0.027451038360595703, + -0.13725489377975464, + -0.3333333134651184, + -0.34117645025253296, + -0.41960781812667847, + -0.5529412031173706, + -0.46666663885116577, + -0.019607841968536377, + 0.043137311935424805, + -0.027450978755950928, + -0.23137253522872925, + -0.3647058606147766, + -0.3333333134651184, + -0.3333333134651184, + -0.40392154455184937, + -0.615686297416687, + -0.7647058963775635, + -0.4117646813392639, + -0.1921568512916565 + ], + [ + 0.43529415130615234, + -0.09019607305526733, + 0.18431377410888672, + 0.32549023628234863, + 0.22352945804595947, + -0.12156862020492554, + -0.07450979948043823, + -0.3019607663154602, + 0.545098066329956, + 0.7568627595901489, + 0.49803924560546875, + 0.058823585510253906, + 0.24705886840820312, + 0.07450985908508301, + -0.15294116735458374, + -0.1294117569923401, + -0.40392154455184937, + -0.37254899740219116, + -0.6549019813537598, + -0.3333333134651184, + 0.29411768913269043, + 0.15294122695922852, + 0.15294122695922852, + -0.21568626165390015, + -0.3490195870399475, + -0.19999998807907104, + -0.30980390310287476, + -0.3803921341896057, + -0.5372549295425415, + -0.7176470756530762, + -0.6392157077789307, + -0.3647058606147766 + ], + [ + 0.49803924560546875, + -0.15294116735458374, + 0.12941181659698486, + 0.37254905700683594, + 0.30980396270751953, + -0.05882352590560913, + -0.03529411554336548, + -0.270588219165802, + -0.2549019455909729, + 0.4274510145187378, + 0.34117650985717773, + 0.11372554302215576, + 0.2627451419830322, + 0.34117650985717773, + -0.06666666269302368, + -0.1607843041419983, + -0.23137253522872925, + -0.34117645025253296, + -0.7019608020782471, + -0.05098038911819458, + 0.5764706134796143, + 0.19215691089630127, + 0.09019613265991211, + -0.3019607663154602, + -0.37254899740219116, + -0.270588219165802, + -0.18431371450424194, + -0.3176470398902893, + -0.4117646813392639, + -0.5843137502670288, + -0.5686274766921997, + -0.5607843399047852 + ], + [ + 0.5215686559677124, + -0.24705880880355835, + 0.050980448722839355, + 0.4117647409439087, + 0.22352945804595947, + -0.03529411554336548, + -0.03529411554336548, + -0.1450980305671692, + -0.46666663885116577, + 0.20784318447113037, + 0.12941181659698486, + -0.10588234663009644, + 0.301960825920105, + 0.5843137502670288, + 0.16862750053405762, + -0.11372548341751099, + -0.10588234663009644, + -0.10588234663009644, + -0.6078431606292725, + 0.15294122695922852, + 0.46666669845581055, + 0.16862750053405762, + -0.07450979948043823, + -0.30980390310287476, + -0.3490195870399475, + -0.34117645025253296, + -0.2549019455909729, + -0.3176470398902893, + -0.3176470398902893, + -0.427450954914093, + -0.41960781812667847, + -0.5686274766921997 + ], + [ + 0.5058823823928833, + -0.2549019455909729, + 0.20784318447113037, + 0.4745098352432251, + -0.13725489377975464, + -0.16862744092941284, + -0.027450978755950928, + -0.09019607305526733, + -0.43529409170150757, + 0.035294175148010254, + -0.019607841968536377, + 0.16862750053405762, + 0.3647059202194214, + 0.6941176652908325, + 0.3490196466445923, + 0.027451038360595703, + -0.08235293626785278, + -0.10588234663009644, + -0.4431372284889221, + 0.19215691089630127, + 0.41960787773132324, + 0.12941181659698486, + -0.13725489377975464, + -0.3333333134651184, + -0.37254899740219116, + -0.427450954914093, + -0.37254899740219116, + -0.21568626165390015, + -0.2078431248664856, + -0.30980390310287476, + -0.3019607663154602, + -0.427450954914093 + ], + [ + 0.5372549295425415, + -0.1607843041419983, + 0.30980396270751953, + 0.458823561668396, + -0.1450980305671692, + -0.3019607663154602, + -0.06666666269302368, + -0.04313725233078003, + -0.41960781812667847, + -0.16862744092941284, + -0.03529411554336548, + 0.45098042488098145, + 0.4117647409439087, + 0.29411768913269043, + 0.09803926944732666, + 0.12156867980957031, + 0.06666672229766846, + -0.21568626165390015, + -0.4431372284889221, + 0.19215691089630127, + 0.37254905700683594, + 0.043137311935424805, + 0.003921627998352051, + -0.1450980305671692, + -0.32549017667770386, + -0.270588219165802, + -0.24705880880355835, + -0.13725489377975464, + -0.09019607305526733, + -0.24705880880355835, + -0.3333333134651184, + -0.2549019455909729 + ], + [ + 0.545098066329956, + 0.011764764785766602, + 0.30980396270751953, + 0.3960784673690796, + 0.07450985908508301, + -0.3490195870399475, + -0.05882352590560913, + -0.019607841968536377, + -0.26274508237838745, + -0.05882352590560913, + 0.027451038360595703, + 0.7333333492279053, + 0.8509804010391235, + 0.08235299587249756, + 0.019607901573181152, + -0.05098038911819458, + -0.12156862020492554, + -0.18431371450424194, + -0.30980390310287476, + 0.050980448722839355, + 0.24705886840820312, + 0.15294122695922852, + -0.15294116735458374, + -0.3333333134651184, + -0.43529409170150757, + -0.30980390310287476, + -0.18431371450424194, + -0.1450980305671692, + -0.13725489377975464, + -0.32549017667770386, + -0.24705880880355835, + -0.18431371450424194 + ], + [ + 0.5921568870544434, + 0.14509809017181396, + 0.2862745523452759, + 0.4274510145187378, + 0.3333333730697632, + -0.32549017667770386, + -0.019607841968536377, + -0.011764705181121826, + -0.05098038911819458, + -0.37254899740219116, + 0.12156867980957031, + 0.27843141555786133, + 0.19215691089630127, + 0.035294175148010254, + -0.16862744092941284, + -0.16862744092941284, + -0.2078431248664856, + -0.2078431248664856, + -0.29411762952804565, + 0.12156867980957031, + 0.08235299587249756, + 0.10588240623474121, + 0.019607901573181152, + -0.1764705777168274, + -0.40392154455184937, + -0.3803921341896057, + -0.270588219165802, + -0.2862744927406311, + -0.3490195870399475, + -0.30980390310287476, + -0.15294116735458374, + -0.18431371450424194 + ], + [ + 0.686274528503418, + 0.301960825920105, + 0.30980396270751953, + 0.4431372880935669, + 0.4274510145187378, + -0.19999998807907104, + -0.24705880880355835, + 0.16862750053405762, + 0.07450985908508301, + -0.270588219165802, + -0.09019607305526733, + -0.1764705777168274, + -0.19999998807907104, + -0.1764705777168274, + -0.2862744927406311, + -0.13725489377975464, + -0.2862744927406311, + -0.1921568512916565, + 0.003921627998352051, + -0.24705880880355835, + -0.5607843399047852, + -0.05882352590560913, + -0.011764705181121826, + -0.4588235020637512, + -0.5607843399047852, + -0.5607843399047852, + -0.45098036527633667, + -0.270588219165802, + -0.26274508237838745, + -0.12156862020492554, + -0.09019607305526733, + -0.13725489377975464 + ], + [ + 0.6549019813537598, + 0.4431372880935669, + 0.37254905700683594, + 0.41960787773132324, + 0.4431372880935669, + 0.027451038360595703, + -0.30980390310287476, + 0.09019613265991211, + 0.16078436374664307, + 0.003921627998352051, + -0.29411762952804565, + -0.498039186000824, + -0.05098038911819458, + -0.1294117569923401, + -0.08235293626785278, + 0.12156867980957031, + -0.27843135595321655, + -0.24705880880355835, + 0.09019613265991211, + -0.08235293626785278, + -0.1450980305671692, + -0.2235293984413147, + -0.46666663885116577, + -0.5372549295425415, + -0.6784313917160034, + -0.5137255191802979, + -0.4588235020637512, + -0.1764705777168274, + -0.06666666269302368, + -0.05882352590560913, + -0.09803920984268188, + -0.1294117569923401 + ], + [ + 0.5058823823928833, + 0.48235297203063965, + 0.3803921937942505, + 0.40392160415649414, + 0.4274510145187378, + 0.16862750053405762, + -0.29411762952804565, + -0.05098038911819458, + -0.027450978755950928, + 0.06666672229766846, + 0.050980448722839355, + -0.5372549295425415, + -0.07450979948043823, + -0.2392156720161438, + 0.050980448722839355, + 0.3803921937942505, + -0.07450979948043823, + -0.4117646813392639, + -0.06666666269302368, + -0.027450978755950928, + 0.011764764785766602, + -0.32549017667770386, + -0.615686297416687, + -0.6000000238418579, + -0.615686297416687, + -0.29411762952804565, + -0.2862744927406311, + -0.07450979948043823, + -0.05098038911819458, + -0.11372548341751099, + -0.1294117569923401, + -0.1607843041419983 + ], + [ + 0.22352945804595947, + 0.5137255191802979, + 0.3960784673690796, + 0.35686278343200684, + 0.41960787773132324, + 0.23137259483337402, + -0.1921568512916565, + 0.058823585510253906, + 0.37254905700683594, + -0.1764705777168274, + -0.29411762952804565, + -0.3960784077644348, + -0.29411762952804565, + -0.07450979948043823, + 0.35686278343200684, + 0.4274510145187378, + 0.16078436374664307, + -0.21568626165390015, + -0.38823527097702026, + -0.3960784077644348, + -0.5215686559677124, + -0.5921568870544434, + -0.6392157077789307, + -0.7411764860153198, + -0.5529412031173706, + -0.4431372284889221, + -0.21568626165390015, + -0.019607841968536377, + -0.03529411554336548, + -0.1450980305671692, + -0.11372548341751099, + -0.1764705777168274 + ], + [ + -0.05882352590560913, + 0.5686274766921997, + 0.3960784673690796, + 0.32549023628234863, + 0.40392160415649414, + 0.12941181659698486, + -0.3176470398902893, + 0.20000004768371582, + 0.9372549057006836, + 0.7411764860153198, + 0.09803926944732666, + 0.10588240623474121, + 0.22352945804595947, + 0.4274510145187378, + 0.5372549295425415, + 0.5058823823928833, + 0.3490196466445923, + 0.043137311935424805, + -0.1450980305671692, + -0.5137255191802979, + -0.615686297416687, + -0.5764706134796143, + -0.45098036527633667, + -0.3647058606147766, + -0.3333333134651184, + -0.34117645025253296, + -0.2235293984413147, + -0.2078431248664856, + -0.18431371450424194, + -0.24705880880355835, + -0.27843135595321655, + -0.29411762952804565 + ], + [ + -0.1764705777168274, + 0.545098066329956, + 0.43529415130615234, + 0.3490196466445923, + 0.38823533058166504, + 0.14509809017181396, + -0.12156862020492554, + 0.6549019813537598, + 0.9764705896377563, + 0.9843137264251709, + 0.7568627595901489, + 0.12156867980957031, + 0.035294175148010254, + 0.10588240623474121, + 0.043137311935424805, + 0.043137311935424805, + -0.027450978755950928, + -0.270588219165802, + -0.3176470398902893, + -0.35686272382736206, + -0.34117645025253296, + -0.34117645025253296, + -0.3333333134651184, + -0.270588219165802, + -0.26274508237838745, + -0.2862744927406311, + -0.24705880880355835, + -0.18431371450424194, + -0.15294116735458374, + -0.2392156720161438, + -0.2392156720161438, + -0.2549019455909729 + ], + [ + -0.3019607663154602, + 0.07450985908508301, + 0.3176470994949341, + 0.3647059202194214, + 0.4274510145187378, + 0.3333333730697632, + 0.301960825920105, + 0.9215686321258545, + 0.9686274528503418, + 0.8117647171020508, + 0.06666672229766846, + -0.30980390310287476, + -0.37254899740219116, + -0.40392154455184937, + -0.4117646813392639, + -0.43529409170150757, + -0.3803921341896057, + -0.3647058606147766, + -0.3647058606147766, + -0.35686272382736206, + -0.32549017667770386, + -0.29411762952804565, + -0.3019607663154602, + -0.3176470398902893, + -0.3019607663154602, + -0.270588219165802, + -0.26274508237838745, + -0.24705880880355835, + -0.24705880880355835, + -0.26274508237838745, + -0.2549019455909729, + -0.29411762952804565 + ], + [ + -0.2862744927406311, + -0.3176470398902893, + -0.19999998807907104, + 0.20000004768371582, + 0.40392160415649414, + 0.06666672229766846, + 0.48235297203063965, + 0.9607843160629272, + 0.9215686321258545, + 0.24705886840820312, + -0.26274508237838745, + -0.34117645025253296, + -0.34117645025253296, + -0.3333333134651184, + -0.3490195870399475, + -0.34117645025253296, + -0.32549017667770386, + -0.34117645025253296, + -0.35686272382736206, + -0.3803921341896057, + -0.3490195870399475, + -0.32549017667770386, + -0.3333333134651184, + -0.3019607663154602, + -0.27843135595321655, + -0.1921568512916565, + -0.1921568512916565, + -0.2078431248664856, + -0.19999998807907104, + -0.2235293984413147, + -0.26274508237838745, + -0.1921568512916565 + ], + [ + -0.1294117569923401, + -0.26274508237838745, + -0.3333333134651184, + -0.16862744092941284, + 0.16078436374664307, + 0.06666672229766846, + 0.6705882549285889, + 0.9843137264251709, + 0.5529412031173706, + -0.270588219165802, + -0.2862744927406311, + -0.30980390310287476, + -0.29411762952804565, + -0.29411762952804565, + -0.3490195870399475, + -0.35686272382736206, + -0.35686272382736206, + -0.3647058606147766, + -0.37254899740219116, + -0.3490195870399475, + -0.32549017667770386, + -0.3019607663154602, + -0.27843135595321655, + -0.2549019455909729, + -0.15294116735458374, + -0.13725489377975464, + -0.1450980305671692, + -0.15294116735458374, + -0.15294116735458374, + -0.1764705777168274, + -0.03529411554336548, + 0.07450985908508301 + ], + [ + -0.10588234663009644, + -0.2235293984413147, + -0.32549017667770386, + -0.3490195870399475, + -0.2549019455909729, + 0.13725495338439941, + 0.7960784435272217, + 0.9215686321258545, + 0.12156867980957031, + -0.27843135595321655, + -0.3176470398902893, + -0.26274508237838745, + -0.27843135595321655, + -0.35686272382736206, + -0.35686272382736206, + -0.3490195870399475, + -0.34117645025253296, + -0.3490195870399475, + -0.32549017667770386, + -0.30980390310287476, + -0.29411762952804565, + -0.2392156720161438, + -0.16862744092941284, + -0.13725489377975464, + -0.1764705777168274, + -0.2392156720161438, + -0.2549019455909729, + -0.2862744927406311, + -0.15294116735458374, + 0.019607901573181152, + 0.08235299587249756, + -0.019607841968536377 + ], + [ + -0.13725489377975464, + -0.23137253522872925, + -0.3019607663154602, + -0.32549017667770386, + -0.3490195870399475, + -0.16862744092941284, + 0.7176470756530762, + 0.7882353067398071, + -0.011764705181121826, + -0.18431371450424194, + -0.26274508237838745, + -0.3176470398902893, + -0.2392156720161438, + -0.3176470398902893, + -0.37254899740219116, + -0.35686272382736206, + -0.34117645025253296, + -0.3176470398902893, + -0.3019607663154602, + -0.3019607663154602, + -0.2392156720161438, + -0.27843135595321655, + -0.270588219165802, + -0.19999998807907104, + -0.2078431248664856, + -0.270588219165802, + -0.3333333134651184, + -0.2078431248664856, + 0.011764764785766602, + -0.011764705181121826, + -0.23137253522872925, + -0.24705880880355835 + ], + [ + -0.15294116735458374, + -0.2392156720161438, + -0.27843135595321655, + -0.30980390310287476, + -0.30980390310287476, + -0.34117645025253296, + 0.043137311935424805, + 0.545098066329956, + -0.21568626165390015, + -0.2392156720161438, + -0.26274508237838745, + -0.2549019455909729, + -0.1921568512916565, + -0.21568626165390015, + -0.24705880880355835, + -0.3490195870399475, + -0.3803921341896057, + -0.37254899740219116, + -0.30980390310287476, + -0.27843135595321655, + -0.27843135595321655, + -0.2549019455909729, + -0.270588219165802, + -0.27843135595321655, + -0.29411762952804565, + -0.270588219165802, + -0.19999998807907104, + -0.019607841968536377, + -0.13725489377975464, + -0.29411762952804565, + -0.529411792755127, + -0.270588219165802 + ], + [ + -0.027450978755950928, + -0.21568626165390015, + -0.30980390310287476, + -0.2862744927406311, + -0.3176470398902893, + -0.3019607663154602, + -0.3803921341896057, + -0.1607843041419983, + -0.3019607663154602, + -0.3960784077644348, + -0.4431372284889221, + -0.35686272382736206, + -0.270588219165802, + -0.21568626165390015, + -0.19999998807907104, + -0.27843135595321655, + -0.26274508237838745, + -0.2235293984413147, + -0.2235293984413147, + -0.2392156720161438, + -0.2549019455909729, + -0.26274508237838745, + -0.30980390310287476, + -0.3490195870399475, + -0.2862744927406311, + -0.12156862020492554, + 0.035294175148010254, + 0.027451038360595703, + -0.09019607305526733, + -0.2392156720161438, + -0.498039186000824, + -0.3333333134651184 + ], + [ + -0.09019607305526733, + -0.19999998807907104, + -0.3333333134651184, + -0.2862744927406311, + -0.29411762952804565, + -0.27843135595321655, + -0.30980390310287476, + -0.3647058606147766, + -0.3333333134651184, + -0.43529409170150757, + -0.4745097756385803, + -0.41960781812667847, + -0.4431372284889221, + -0.427450954914093, + -0.37254899740219116, + -0.32549017667770386, + -0.2549019455909729, + -0.2078431248664856, + -0.1450980305671692, + -0.06666666269302368, + -0.11372548341751099, + -0.2549019455909729, + -0.30980390310287476, + -0.30980390310287476, + -0.1764705777168274, + 0.019607901573181152, + 0.22352945804595947, + 0.13725495338439941, + -0.09803920984268188, + -0.35686272382736206, + -0.35686272382736206, + -0.498039186000824 + ], + [ + -0.1607843041419983, + -0.1764705777168274, + -0.3019607663154602, + -0.32549017667770386, + -0.3019607663154602, + -0.27843135595321655, + -0.3176470398902893, + -0.3647058606147766, + -0.3803921341896057, + -0.4588235020637512, + -0.4823529124259949, + -0.427450954914093, + -0.4588235020637512, + -0.427450954914093, + -0.5058823823928833, + -0.545098066329956, + -0.45098036527633667, + -0.3176470398902893, + -0.18431371450424194, + -0.06666666269302368, + -0.1294117569923401, + -0.24705880880355835, + -0.2549019455909729, + -0.3176470398902893, + -0.1450980305671692, + 0.027451038360595703, + 0.14509809017181396, + 0.058823585510253906, + -0.2235293984413147, + -0.3960784077644348, + -0.34117645025253296, + -0.4745097756385803 + ] + ], + [ + [ + -0.615686297416687, + -0.6313725709915161, + -0.6000000238418579, + -0.5843137502670288, + -0.6392157077789307, + -0.6784313917160034, + -0.6313725709915161, + -0.6470588445663452, + -0.6549019813537598, + -0.6784313917160034, + -0.6784313917160034, + -0.5921568870544434, + -0.615686297416687, + -0.6784313917160034, + -0.6470588445663452, + -0.6549019813537598, + -0.686274528503418, + -0.7019608020782471, + -0.6941176652908325, + -0.6627451181411743, + -0.6549019813537598, + -0.6470588445663452, + -0.6470588445663452, + -0.6627451181411743, + -0.6549019813537598, + -0.6941176652908325, + -0.6627451181411743, + -0.6784313917160034, + -0.7019608020782471, + -0.7176470756530762, + -0.7176470756530762, + -0.7411764860153198 + ], + [ + -0.6000000238418579, + -0.686274528503418, + -0.6470588445663452, + -0.5607843399047852, + -0.615686297416687, + -0.6627451181411743, + -0.6313725709915161, + -0.6470588445663452, + -0.6392157077789307, + -0.7019608020782471, + -0.6784313917160034, + -0.5764706134796143, + -0.5921568870544434, + -0.6784313917160034, + -0.686274528503418, + -0.7411764860153198, + -0.7647058963775635, + -0.7411764860153198, + -0.6784313917160034, + -0.6078431606292725, + -0.5843137502670288, + -0.5686274766921997, + -0.5921568870544434, + -0.6235294342041016, + -0.6078431606292725, + -0.6392157077789307, + -0.6470588445663452, + -0.7019608020782471, + -0.7333333492279053, + -0.7568627595901489, + -0.7490196228027344, + -0.7333333492279053 + ], + [ + -0.6313725709915161, + -0.7411764860153198, + -0.7176470756530762, + -0.6235294342041016, + -0.6705882549285889, + -0.6549019813537598, + -0.6470588445663452, + -0.6470588445663452, + -0.6627451181411743, + -0.6627451181411743, + -0.6235294342041016, + -0.5529412031173706, + -0.6000000238418579, + -0.7019608020782471, + -0.7098039388656616, + -0.7254902124404907, + -0.6941176652908325, + -0.6313725709915161, + -0.5764706134796143, + -0.615686297416687, + -0.5921568870544434, + -0.6078431606292725, + -0.6313725709915161, + -0.6078431606292725, + -0.6235294342041016, + -0.5686274766921997, + -0.6000000238418579, + -0.6941176652908325, + -0.7254902124404907, + -0.7333333492279053, + -0.7333333492279053, + -0.7411764860153198 + ], + [ + -0.686274528503418, + -0.7490196228027344, + -0.7568627595901489, + -0.6549019813537598, + -0.6627451181411743, + -0.6392157077789307, + -0.6235294342041016, + -0.6235294342041016, + -0.6549019813537598, + -0.6470588445663452, + -0.5529412031173706, + -0.2549019455909729, + -0.4117646813392639, + -0.6784313917160034, + -0.6313725709915161, + -0.5764706134796143, + -0.545098066329956, + -0.4745097756385803, + -0.6313725709915161, + -0.4901960492134094, + -0.40392154455184937, + -0.34117645025253296, + -0.4823529124259949, + -0.6078431606292725, + -0.5921568870544434, + -0.6941176652908325, + -0.6470588445663452, + -0.6392157077789307, + -0.6627451181411743, + -0.6941176652908325, + -0.6941176652908325, + -0.7176470756530762 + ], + [ + -0.6784313917160034, + -0.6235294342041016, + -0.615686297416687, + -0.6313725709915161, + -0.6627451181411743, + -0.686274528503418, + -0.6313725709915161, + -0.6549019813537598, + -0.6784313917160034, + -0.6705882549285889, + -0.5372549295425415, + 0.2862745523452759, + -0.1607843041419983, + -0.5607843399047852, + -0.529411792755127, + -0.4431372284889221, + -0.6078431606292725, + -0.7568627595901489, + -0.5607843399047852, + -0.23137253522872925, + -0.1294117569923401, + -0.07450979948043823, + -0.1764705777168274, + -0.270588219165802, + -0.4745097756385803, + -0.45098036527633667, + -0.6313725709915161, + -0.6470588445663452, + -0.6235294342041016, + -0.6392157077789307, + -0.7176470756530762, + -0.7176470756530762 + ], + [ + -0.5764706134796143, + -0.498039186000824, + -0.5529412031173706, + -0.5843137502670288, + -0.6549019813537598, + -0.6941176652908325, + -0.6784313917160034, + -0.6784313917160034, + -0.7098039388656616, + -0.6941176652908325, + -0.6705882549285889, + -0.3333333134651184, + -0.38823527097702026, + -0.545098066329956, + -0.6627451181411743, + -0.7568627595901489, + -0.6627451181411743, + -0.6470588445663452, + -0.40392154455184937, + -0.13725489377975464, + -0.05882352590560913, + -0.04313725233078003, + -0.09019607305526733, + -0.24705880880355835, + -0.2392156720161438, + -0.32549017667770386, + -0.6313725709915161, + -0.7098039388656616, + -0.615686297416687, + -0.545098066329956, + -0.6549019813537598, + -0.686274528503418 + ], + [ + -0.5529412031173706, + -0.37254899740219116, + -0.8666666746139526, + -0.7803921699523926, + -0.6235294342041016, + -0.6627451181411743, + -0.686274528503418, + -0.6627451181411743, + -0.6705882549285889, + -0.7098039388656616, + -0.6941176652908325, + -0.5921568870544434, + -0.5372549295425415, + -0.4117646813392639, + -0.45098036527633667, + -0.5529412031173706, + -0.43529409170150757, + -0.498039186000824, + -0.41960781812667847, + -0.05098038911819458, + 0.035294175148010254, + -0.15294116735458374, + -0.29411762952804565, + -0.26274508237838745, + -0.1921568512916565, + -0.3960784077644348, + -0.4588235020637512, + -0.6941176652908325, + -0.7176470756530762, + -0.545098066329956, + -0.6235294342041016, + -0.6941176652908325 + ], + [ + -0.29411762952804565, + -0.27843135595321655, + -0.7019608020782471, + -0.6784313917160034, + -0.5607843399047852, + -0.6705882549285889, + -0.7176470756530762, + -0.6941176652908325, + -0.615686297416687, + -0.6000000238418579, + -0.6000000238418579, + -0.615686297416687, + -0.3960784077644348, + -0.1607843041419983, + -0.270588219165802, + -0.3803921341896057, + -0.30980390310287476, + -0.35686272382736206, + -0.4588235020637512, + -0.1607843041419983, + 0.09803926944732666, + -0.12156862020492554, + -0.3647058606147766, + -0.30980390310287476, + -0.34117645025253296, + -0.41960781812667847, + -0.545098066329956, + -0.615686297416687, + -0.7490196228027344, + -0.6078431606292725, + -0.6000000238418579, + -0.6941176652908325 + ], + [ + 0.12941181659698486, + -0.1764705777168274, + -0.5372549295425415, + -0.11372548341751099, + -0.35686272382736206, + -0.6627451181411743, + -0.6784313917160034, + -0.6078431606292725, + -0.4823529124259949, + -0.2549019455909729, + -0.5372549295425415, + -0.38823527097702026, + -0.05098038911819458, + 0.003921627998352051, + -0.2078431248664856, + -0.41960781812667847, + -0.3960784077644348, + -0.35686272382736206, + -0.427450954914093, + -0.5215686559677124, + -0.12156862020492554, + -0.03529411554336548, + -0.270588219165802, + -0.45098036527633667, + -0.4588235020637512, + -0.40392154455184937, + -0.4745097756385803, + -0.5843137502670288, + -0.7882353067398071, + -0.7254902124404907, + -0.5372549295425415, + -0.6470588445663452 + ], + [ + 0.27843141555786133, + 0.12156867980957031, + -0.1764705777168274, + 0.16862750053405762, + -0.12156862020492554, + -0.6000000238418579, + -0.6313725709915161, + -0.529411792755127, + 0.14509809017181396, + 0.5529412031173706, + 0.301960825920105, + -0.06666666269302368, + 0.13725495338439941, + -0.019607841968536377, + -0.1607843041419983, + -0.3803921341896057, + -0.3803921341896057, + -0.4431372284889221, + -0.5843137502670288, + -0.545098066329956, + -0.12156862020492554, + -0.04313725233078003, + -0.10588234663009644, + -0.3019607663154602, + -0.41960781812667847, + -0.38823527097702026, + -0.38823527097702026, + -0.4431372284889221, + -0.6627451181411743, + -0.8823529481887817, + -0.6549019813537598, + -0.5529412031173706 + ], + [ + 0.37254905700683594, + -0.04313725233078003, + 0.23921573162078857, + 0.3176470994949341, + -0.04313725233078003, + -0.6078431606292725, + -0.6000000238418579, + -0.6313725709915161, + 0.40392160415649414, + 0.772549033164978, + 0.4745098352432251, + 0.027451038360595703, + 0.21568632125854492, + 0.035294175148010254, + -0.18431371450424194, + -0.18431371450424194, + -0.4588235020637512, + -0.3960784077644348, + -0.686274528503418, + -0.3960784077644348, + 0.20784318447113037, + 0.07450985908508301, + 0.08235299587249756, + -0.27843135595321655, + -0.3960784077644348, + -0.24705880880355835, + -0.3803921341896057, + -0.427450954914093, + -0.5372549295425415, + -0.7411764860153198, + -0.7568627595901489, + -0.6392157077789307 + ], + [ + 0.48235297203063965, + -0.09019607305526733, + 0.20000004768371582, + 0.3960784673690796, + 0.06666672229766846, + -0.5372549295425415, + -0.5686274766921997, + -0.6549019813537598, + -0.37254899740219116, + 0.4745098352432251, + 0.2862745523452759, + 0.043137311935424805, + 0.18431377410888672, + 0.24705886840820312, + -0.16862744092941284, + -0.2549019455909729, + -0.3019607663154602, + -0.3803921341896057, + -0.7333333492279053, + -0.11372548341751099, + 0.5058823823928833, + 0.11372554302215576, + 0.019607901573181152, + -0.35686272382736206, + -0.4117646813392639, + -0.30980390310287476, + -0.26274508237838745, + -0.3647058606147766, + -0.38823527097702026, + -0.5686274766921997, + -0.6235294342041016, + -0.7960784435272217 + ], + [ + 0.5215686559677124, + -0.1764705777168274, + 0.12941181659698486, + 0.45098042488098145, + 0.043137311935424805, + -0.46666663885116577, + -0.5843137502670288, + -0.6313725709915161, + -0.6549019813537598, + 0.19215691089630127, + -0.011764705181121826, + -0.26274508237838745, + 0.16078436374664307, + 0.43529415130615234, + 0.011764764785766602, + -0.23137253522872925, + -0.1764705777168274, + -0.1450980305671692, + -0.6313725709915161, + 0.09803926944732666, + 0.3960784673690796, + 0.09803926944732666, + -0.1294117569923401, + -0.3490195870399475, + -0.3803921341896057, + -0.37254899740219116, + -0.3333333134651184, + -0.3647058606147766, + -0.3019607663154602, + -0.427450954914093, + -0.498039186000824, + -0.8117647171020508 + ], + [ + 0.5137255191802979, + -0.1921568512916565, + 0.27843141555786133, + 0.5058823823928833, + -0.23137253522872925, + -0.4823529124259949, + -0.545098066329956, + -0.6078431606292725, + -0.6941176652908325, + -0.05882352590560913, + -0.1921568512916565, + -0.003921568393707275, + 0.21568632125854492, + 0.5686274766921997, + 0.23137259483337402, + -0.08235293626785278, + -0.1607843041419983, + -0.1450980305671692, + -0.46666663885116577, + 0.15294122695922852, + 0.3647059202194214, + 0.06666672229766846, + -0.18431371450424194, + -0.37254899740219116, + -0.40392154455184937, + -0.45098036527633667, + -0.43529409170150757, + -0.26274508237838745, + -0.2235293984413147, + -0.3647058606147766, + -0.4588235020637512, + -0.7333333492279053 + ], + [ + 0.5372549295425415, + -0.12156862020492554, + 0.3490196466445923, + 0.4745098352432251, + -0.1450980305671692, + -0.4745097756385803, + -0.5137255191802979, + -0.5686274766921997, + -0.7333333492279053, + -0.30980390310287476, + -0.1921568512916565, + 0.32549023628234863, + 0.32549023628234863, + 0.24705886840820312, + 0.09803926944732666, + 0.050980448722839355, + -0.019607841968536377, + -0.2549019455909729, + -0.45098036527633667, + 0.16862750053405762, + 0.3333333730697632, + -0.003921568393707275, + -0.04313725233078003, + -0.1764705777168274, + -0.3490195870399475, + -0.2862744927406311, + -0.29411762952804565, + -0.18431371450424194, + -0.1294117569923401, + -0.37254899740219116, + -0.5843137502670288, + -0.6313725709915161 + ], + [ + 0.545098066329956, + 0.06666672229766846, + 0.3647059202194214, + 0.41960787773132324, + 0.11372554302215576, + -0.3960784077644348, + -0.30980390310287476, + -0.3960784077644348, + -0.5921568870544434, + -0.270588219165802, + -0.09019607305526733, + 0.6549019813537598, + 0.8039215803146362, + 0.07450985908508301, + 0.019607901573181152, + -0.12156862020492554, + -0.2078431248664856, + -0.2549019455909729, + -0.4117646813392639, + -0.07450979948043823, + 0.14509809017181396, + 0.08235299587249756, + -0.2078431248664856, + -0.37254899740219116, + -0.46666663885116577, + -0.3176470398902893, + -0.2235293984413147, + -0.2235293984413147, + -0.270588219165802, + -0.5764706134796143, + -0.6235294342041016, + -0.6235294342041016 + ], + [ + 0.6000000238418579, + 0.2549020051956177, + 0.3960784673690796, + 0.4745098352432251, + 0.3490196466445923, + -0.29411762952804565, + -0.011764705181121826, + -0.11372548341751099, + -0.35686272382736206, + -0.7098039388656616, + 0.043137311935424805, + 0.21568632125854492, + 0.10588240623474121, + -0.08235293626785278, + -0.30980390310287476, + -0.29411762952804565, + -0.27843135595321655, + -0.3176470398902893, + -0.545098066329956, + -0.18431371450424194, + -0.1450980305671692, + -0.011764705181121826, + -0.07450979948043823, + -0.2392156720161438, + -0.43529409170150757, + -0.3960784077644348, + -0.26274508237838745, + -0.35686272382736206, + -0.5686274766921997, + -0.6470588445663452, + -0.5686274766921997, + -0.6392157077789307 + ], + [ + 0.686274528503418, + 0.4117647409439087, + 0.4431372880935669, + 0.5215686559677124, + 0.458823561668396, + -0.1764705777168274, + -0.19999998807907104, + 0.13725495338439941, + -0.1294117569923401, + -0.5215686559677124, + -0.1764705777168274, + -0.2549019455909729, + -0.3019607663154602, + -0.3019607663154602, + -0.427450954914093, + -0.23137253522872925, + -0.30980390310287476, + -0.2549019455909729, + -0.19999998807907104, + -0.498039186000824, + -0.7490196228027344, + -0.1764705777168274, + -0.09803920984268188, + -0.5215686559677124, + -0.6000000238418579, + -0.5843137502670288, + -0.4901960492134094, + -0.38823527097702026, + -0.498039186000824, + -0.46666663885116577, + -0.498039186000824, + -0.5764706134796143 + ], + [ + 0.6078431606292725, + 0.5058823823928833, + 0.48235297203063965, + 0.5137255191802979, + 0.4745098352432251, + 0.043137311935424805, + -0.24705880880355835, + 0.12156867980957031, + 0.10588240623474121, + -0.1294117569923401, + -0.37254899740219116, + -0.5686274766921997, + -0.15294116735458374, + -0.24705880880355835, + -0.21568626165390015, + 0.043137311935424805, + -0.270588219165802, + -0.270588219165802, + -0.05882352590560913, + -0.270588219165802, + -0.27843135595321655, + -0.32549017667770386, + -0.545098066329956, + -0.5921568870544434, + -0.6941176652908325, + -0.529411792755127, + -0.686274528503418, + -0.5372549295425415, + -0.5137255191802979, + -0.5764706134796143, + -0.6470588445663452, + -0.6392157077789307 + ], + [ + 0.4117647409439087, + 0.46666669845581055, + 0.41960787773132324, + 0.45098042488098145, + 0.4431372880935669, + 0.19215691089630127, + -0.2235293984413147, + 0.035294175148010254, + 0.019607901573181152, + 0.058823585510253906, + -0.011764705181121826, + -0.6000000238418579, + -0.15294116735458374, + -0.32549017667770386, + -0.03529411554336548, + 0.3176470994949341, + -0.07450979948043823, + -0.427450954914093, + -0.1921568512916565, + -0.1764705777168274, + -0.07450979948043823, + -0.38823527097702026, + -0.6549019813537598, + -0.6078431606292725, + -0.5921568870544434, + -0.270588219165802, + -0.529411792755127, + -0.46666663885116577, + -0.498039186000824, + -0.5921568870544434, + -0.6078431606292725, + -0.6392157077789307 + ], + [ + 0.14509809017181396, + 0.46666669845581055, + 0.37254905700683594, + 0.3490196466445923, + 0.4117647409439087, + 0.2549020051956177, + -0.1294117569923401, + 0.14509809017181396, + 0.45098042488098145, + -0.1294117569923401, + -0.3176470398902893, + -0.427450954914093, + -0.32549017667770386, + -0.09019607305526733, + 0.35686278343200684, + 0.38823533058166504, + 0.16078436374664307, + -0.2078431248664856, + -0.4823529124259949, + -0.5058823823928833, + -0.5529412031173706, + -0.5764706134796143, + -0.6000000238418579, + -0.6784313917160034, + -0.4588235020637512, + -0.3490195870399475, + -0.4117646813392639, + -0.35686272382736206, + -0.40392154455184937, + -0.5215686559677124, + -0.4588235020637512, + -0.5058823823928833 + ], + [ + -0.027450978755950928, + 0.5686274766921997, + 0.3803921937942505, + 0.3176470994949341, + 0.40392160415649414, + 0.15294122695922852, + -0.2862744927406311, + 0.24705886840820312, + 0.9607843160629272, + 0.7647058963775635, + 0.12941181659698486, + 0.15294122695922852, + 0.2862745523452759, + 0.5058823823928833, + 0.6313725709915161, + 0.545098066329956, + 0.41960787773132324, + 0.12156867980957031, + -0.1450980305671692, + -0.5137255191802979, + -0.545098066329956, + -0.46666663885116577, + -0.3176470398902893, + -0.19999998807907104, + -0.13725489377975464, + -0.1294117569923401, + -0.04313725233078003, + -0.06666666269302368, + -0.05882352590560913, + -0.12156862020492554, + -0.12156862020492554, + -0.09803920984268188 + ], + [ + 0.043137311935424805, + 0.6705882549285889, + 0.5058823823928833, + 0.38823533058166504, + 0.4274510145187378, + 0.17647063732147217, + -0.11372548341751099, + 0.6392157077789307, + 0.9372549057006836, + 0.9764705896377563, + 0.8196078538894653, + 0.23137259483337402, + 0.16862750053405762, + 0.2705882787704468, + 0.22352945804595947, + 0.19215691089630127, + 0.16078436374664307, + -0.06666666269302368, + -0.18431371450424194, + -0.2078431248664856, + -0.1294117569923401, + -0.13725489377975464, + -0.09803920984268188, + -0.019607841968536377, + 0.027451038360595703, + 0.019607901573181152, + 0.058823585510253906, + 0.10588240623474121, + 0.11372554302215576, + 0.035294175148010254, + 0.07450985908508301, + 0.035294175148010254 + ], + [ + 0.058823585510253906, + 0.3176470994949341, + 0.4745098352432251, + 0.4745098352432251, + 0.5058823823928833, + 0.3647059202194214, + 0.2862745523452759, + 0.8588235378265381, + 0.8901960849761963, + 0.7882353067398071, + 0.20000004768371582, + -0.1294117569923401, + -0.1764705777168274, + -0.1764705777168274, + -0.1607843041419983, + -0.2078431248664856, + -0.09803920984268188, + -0.05882352590560913, + -0.11372548341751099, + -0.09019607305526733, + -0.019607841968536377, + -0.019607841968536377, + -0.011764705181121826, + 0.003921627998352051, + 0.035294175148010254, + 0.09019613265991211, + 0.07450985908508301, + 0.07450985908508301, + 0.058823585510253906, + 0.050980448722839355, + 0.09019613265991211, + 0.043137311935424805 + ], + [ + 0.10588240623474121, + 0.019607901573181152, + 0.050980448722839355, + 0.3803921937942505, + 0.49803924560546875, + 0.07450985908508301, + 0.41960787773132324, + 0.8980392217636108, + 0.9215686321258545, + 0.37254905700683594, + -0.003921568393707275, + -0.07450979948043823, + -0.06666666269302368, + -0.05098038911819458, + -0.05882352590560913, + -0.09019607305526733, + -0.08235293626785278, + -0.08235293626785278, + -0.09803920984268188, + -0.11372548341751099, + -0.05882352590560913, + -0.019607841968536377, + -0.019607841968536377, + 0.019607901573181152, + 0.050980448722839355, + 0.13725495338439941, + 0.11372554302215576, + 0.11372554302215576, + 0.14509809017181396, + 0.12941181659698486, + 0.09803926944732666, + 0.16862750053405762 + ], + [ + 0.2705882787704468, + 0.09803926944732666, + -0.027450978755950928, + 0.06666672229766846, + 0.30980396270751953, + 0.12156867980957031, + 0.6392157077789307, + 0.9529411792755127, + 0.6078431606292725, + -0.07450979948043823, + 0.003921627998352051, + -0.019607841968536377, + -0.003921568393707275, + -0.003921568393707275, + -0.05098038911819458, + -0.09803920984268188, + -0.11372548341751099, + -0.12156862020492554, + -0.11372548341751099, + -0.08235293626785278, + -0.03529411554336548, + 0.027451038360595703, + 0.050980448722839355, + 0.08235299587249756, + 0.17647063732147217, + 0.19215691089630127, + 0.15294122695922852, + 0.16862750053405762, + 0.20784318447113037, + 0.19215691089630127, + 0.30980396270751953, + 0.4274510145187378 + ], + [ + 0.29411768913269043, + 0.15294122695922852, + 0.019607901573181152, + -0.04313725233078003, + -0.011764705181121826, + 0.2862745523452759, + 0.8352941274642944, + 0.9372549057006836, + 0.20000004768371582, + -0.10588234663009644, + -0.03529411554336548, + 0.027451038360595703, + 0.011764764785766602, + -0.06666666269302368, + -0.06666666269302368, + -0.06666666269302368, + -0.06666666269302368, + -0.06666666269302368, + -0.03529411554336548, + -0.003921568393707275, + 0.027451038360595703, + 0.10588240623474121, + 0.17647063732147217, + 0.20784318447113037, + 0.17647063732147217, + 0.10588240623474121, + 0.09803926944732666, + 0.08235299587249756, + 0.23921573162078857, + 0.3960784673690796, + 0.4274510145187378, + 0.32549023628234863 + ], + [ + 0.2705882787704468, + 0.16862750053405762, + 0.08235299587249756, + 0.043137311935424805, + -0.011764705181121826, + 0.08235299587249756, + 0.8274509906768799, + 0.8352941274642944, + 0.09803926944732666, + -0.011764705181121826, + 0.011764764785766602, + -0.027450978755950928, + 0.043137311935424805, + -0.03529411554336548, + -0.09019607305526733, + -0.06666666269302368, + -0.04313725233078003, + -0.011764705181121826, + 0.019607901573181152, + 0.035294175148010254, + 0.09803926944732666, + 0.08235299587249756, + 0.09019613265991211, + 0.16078436374664307, + 0.15294122695922852, + 0.09019613265991211, + 0.043137311935424805, + 0.20000004768371582, + 0.4274510145187378, + 0.3803921937942505, + 0.11372554302215576, + 0.09019613265991211 + ], + [ + 0.2627451419830322, + 0.15294122695922852, + 0.12156867980957031, + 0.10588240623474121, + 0.08235299587249756, + -0.019607841968536377, + 0.24705886840820312, + 0.6549019813537598, + -0.06666666269302368, + -0.05098038911819458, + 0.003921627998352051, + 0.019607901573181152, + 0.09019613265991211, + 0.058823585510253906, + 0.027451038360595703, + -0.05882352590560913, + -0.07450979948043823, + -0.05882352590560913, + 0.019607901573181152, + 0.058823585510253906, + 0.06666672229766846, + 0.09019613265991211, + 0.08235299587249756, + 0.06666672229766846, + 0.058823585510253906, + 0.08235299587249756, + 0.18431377410888672, + 0.3960784673690796, + 0.2862745523452759, + 0.09803926944732666, + -0.1921568512916565, + 0.06666672229766846 + ], + [ + 0.38823533058166504, + 0.16078436374664307, + 0.07450985908508301, + 0.14509809017181396, + 0.09019613265991211, + 0.035294175148010254, + -0.11372548341751099, + 0.043137311935424805, + -0.10588234663009644, + -0.1764705777168274, + -0.1764705777168274, + -0.08235293626785278, + 0.003921627998352051, + 0.058823585510253906, + 0.07450985908508301, + 0.003921627998352051, + 0.027451038360595703, + 0.07450985908508301, + 0.09019613265991211, + 0.08235299587249756, + 0.07450985908508301, + 0.06666672229766846, + 0.027451038360595703, + -0.019607841968536377, + 0.043137311935424805, + 0.20784318447113037, + 0.40392160415649414, + 0.41960787773132324, + 0.3176470994949341, + 0.14509809017181396, + -0.15294116735458374, + -0.003921568393707275 + ], + [ + 0.3176470994949341, + 0.16078436374664307, + 0.035294175148010254, + 0.12156867980957031, + 0.09019613265991211, + 0.050980448722839355, + -0.019607841968536377, + -0.12156862020492554, + -0.09803920984268188, + -0.18431371450424194, + -0.19999998807907104, + -0.1450980305671692, + -0.16862744092941284, + -0.15294116735458374, + -0.09803920984268188, + -0.05882352590560913, + 0.003921627998352051, + 0.058823585510253906, + 0.12941181659698486, + 0.22352945804595947, + 0.19215691089630127, + 0.050980448722839355, + -0.003921568393707275, + -0.003921568393707275, + 0.12941181659698486, + 0.3333333730697632, + 0.545098066329956, + 0.4901961088180542, + 0.2862745523452759, + 0.019607901573181152, + -0.011764705181121826, + -0.1607843041419983 + ], + [ + 0.2549020051956177, + 0.16862750053405762, + 0.035294175148010254, + 0.050980448722839355, + 0.050980448722839355, + 0.035294175148010254, + -0.03529411554336548, + -0.09803920984268188, + -0.10588234663009644, + -0.1764705777168274, + -0.2078431248664856, + -0.15294116735458374, + -0.18431371450424194, + -0.15294116735458374, + -0.23137253522872925, + -0.3019607663154602, + -0.21568626165390015, + -0.07450979948043823, + 0.07450985908508301, + 0.19215691089630127, + 0.13725495338439941, + 0.027451038360595703, + 0.019607901573181152, + -0.03529411554336548, + 0.13725495338439941, + 0.30980396270751953, + 0.4274510145187378, + 0.37254905700683594, + 0.13725495338439941, + -0.027450978755950928, + 0.011764764785766602, + -0.13725489377975464 + ] + ] + ] + ] +} diff --git a/docs/samples/pytorch/pytorch.yaml b/docs/samples/pytorch/pytorch.yaml new file mode 100644 index 00000000000..0792f949684 --- /dev/null +++ b/docs/samples/pytorch/pytorch.yaml @@ -0,0 +1,9 @@ +apiVersion: "serving.kubeflow.org/v1alpha1" +kind: "KFService" +metadata: + name: "pytorch-cifar10" +spec: + default: + pytorch: + modelUri: "gs://kfserving-samples/models/pytorch/cifar10/" + modelClassName: "Net" diff --git a/pkg/apis/serving/v1alpha1/framework.go b/pkg/apis/serving/v1alpha1/framework.go index 12e6e3a1eb4..b4202b6ef63 100644 --- a/pkg/apis/serving/v1alpha1/framework.go +++ b/pkg/apis/serving/v1alpha1/framework.go @@ -15,6 +15,7 @@ package v1alpha1 import ( "fmt" + "github.com/kubeflow/kfserving/pkg/constants" v1 "k8s.io/api/core/v1" resource "k8s.io/apimachinery/pkg/api/resource" @@ -65,6 +66,7 @@ type FrameworksConfig struct { TensorRT FrameworkConfig `json:"tensorrt,omitempty"` Xgboost FrameworkConfig `json:"xgboost,omitempty"` SKlearn FrameworkConfig `json:"sklearn,omitempty"` + PyTorch FrameworkConfig `json:"pytorch,omitempty"` } func setResourceRequirementDefaults(requirements *v1.ResourceRequirements) { @@ -108,6 +110,9 @@ func makeHandler(modelSpec *ModelSpec) (FrameworkHandler, error) { if modelSpec.Tensorflow != nil { handlers = append(handlers, modelSpec.Tensorflow) } + if modelSpec.PyTorch != nil { + handlers = append(handlers, modelSpec.PyTorch) + } if modelSpec.TensorRT != nil { handlers = append(handlers, modelSpec.TensorRT) } diff --git a/pkg/apis/serving/v1alpha1/kfservice_framework_pytorch.go b/pkg/apis/serving/v1alpha1/kfservice_framework_pytorch.go new file mode 100644 index 00000000000..8b1bf1da90d --- /dev/null +++ b/pkg/apis/serving/v1alpha1/kfservice_framework_pytorch.go @@ -0,0 +1,68 @@ +/* +Copyright 2019 kubeflow.org. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License 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 v1alpha1 + +import ( + "fmt" + "strings" + + "github.com/kubeflow/kfserving/pkg/utils" + v1 "k8s.io/api/core/v1" +) + +// TODO add image name to to configmap +var ( + AllowedPyTorchRuntimeVersions = []string{ + "latest", + } + InvalidPyTorchRuntimeVersionError = "RuntimeVersion must be one of " + strings.Join(AllowedPyTorchRuntimeVersions, ", ") + PyTorchServerImageName = "gcr.io/kfserving/pytorchserver" + DefaultPyTorchRuntimeVersion = "latest" + DefaultPyTorchModelClassName = "PyTorchModel" +) + +var _ FrameworkHandler = (*PyTorchSpec)(nil) + +func (s *PyTorchSpec) CreateModelServingContainer(modelName string, config *FrameworksConfig) *v1.Container { + imageName := PyTorchServerImageName + if config.PyTorch.ContainerImage != "" { + imageName = config.PyTorch.ContainerImage + } + return &v1.Container{ + Image: imageName + ":" + s.RuntimeVersion, + Resources: s.Resources, + Args: []string{ + "--model_name=" + modelName, + "--model_class_name=" + s.ModelClassName, + "--model_dir=" + s.ModelURI, + }, + } +} + +func (s *PyTorchSpec) ApplyDefaults() { + if s.RuntimeVersion == "" { + s.RuntimeVersion = DefaultPyTorchRuntimeVersion + } + if s.ModelClassName == "" { + s.ModelClassName = DefaultPyTorchModelClassName + } + setResourceRequirementDefaults(&s.Resources) +} + +func (s *PyTorchSpec) Validate() error { + if utils.Includes(AllowedPyTorchRuntimeVersions, s.RuntimeVersion) { + return nil + } + return fmt.Errorf(InvalidPyTorchRuntimeVersionError) +} diff --git a/pkg/apis/serving/v1alpha1/kfservice_types.go b/pkg/apis/serving/v1alpha1/kfservice_types.go index c67ae189f5f..23bad8a7d3b 100644 --- a/pkg/apis/serving/v1alpha1/kfservice_types.go +++ b/pkg/apis/serving/v1alpha1/kfservice_types.go @@ -41,6 +41,7 @@ type ModelSpec struct { TensorRT *TensorRTSpec `json:"tensorrt,omitempty"` XGBoost *XGBoostSpec `json:"xgboost,omitempty"` SKLearn *SKLearnSpec `json:"sklearn,omitempty"` + PyTorch *PyTorchSpec `json:"pytorch,omitempty"` } // TensorflowSpec defines arguments for configuring Tensorflow model serving. @@ -79,6 +80,17 @@ type SKLearnSpec struct { Resources v1.ResourceRequirements `json:"resources,omitempty"` } +// PyTorchSpec defines arguments for configuring PyTorch model serving. +type PyTorchSpec struct { + ModelURI string `json:"modelUri"` + ModelClassName string `json:"modelClassName,omitempty"` + // Defaults to PyTorchModel + RuntimeVersion string `json:"runtimeVersion,omitempty"` + // Defaults to latest Runtime Version. + Resources v1.ResourceRequirements `json:"resources,omitempty"` + // Defaults to requests and limits of 1CPU, 2Gb MEM. +} + // CustomSpec provides a hook for arbitrary container configuration. type CustomSpec struct { Container v1.Container `json:"container"` diff --git a/python/pytorch.Dockerfile b/python/pytorch.Dockerfile new file mode 100644 index 00000000000..2db7c2e95c0 --- /dev/null +++ b/python/pytorch.Dockerfile @@ -0,0 +1,28 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + git \ + curl \ + ca-certificates \ + libjpeg-dev \ + libpng-dev && \ + rm -rf /var/lib/apt/lists/* + +RUN curl -o ~/miniconda.sh -O https://repo.continuum.io/miniconda/Miniconda3-4.2.12-Linux-x86_64.sh && \ + chmod +x ~/miniconda.sh && \ + ~/miniconda.sh -b -p /opt/conda && \ + rm ~/miniconda.sh && \ + /opt/conda/bin/conda install conda-build && \ + /opt/conda/bin/conda create -y --name pytorch-py37 python=3.7.3 numpy pyyaml scipy ipython mkl&& \ + /opt/conda/bin/conda clean -ya +ENV PATH /opt/conda/envs/pytorch-py37/bin:$PATH +RUN conda install --name pytorch-py37 pytorch torchvision -c soumith && /opt/conda/bin/conda clean -ya + +WORKDIR /workspace +RUN chmod -R a+w /workspace + +COPY . . +RUN pip install --upgrade pip && pip install -e ./kfserving +RUN pip install -e ./pytorchserver +ENTRYPOINT ["python", "-m", "pytorchserver"] \ No newline at end of file diff --git a/python/pytorchserver/Makefile b/python/pytorchserver/Makefile new file mode 100644 index 00000000000..875ccc5f367 --- /dev/null +++ b/python/pytorchserver/Makefile @@ -0,0 +1,9 @@ + +dev_install: + pip install -e .[test] + +test: type_check + pytest -W ignore + +type_check: + mypy --ignore-missing-imports pytorchserver diff --git a/python/pytorchserver/README.md b/python/pytorchserver/README.md new file mode 100644 index 00000000000..be6e8f7d1da --- /dev/null +++ b/python/pytorchserver/README.md @@ -0,0 +1,145 @@ +# PyTorch Server + +[PyTorch](https://PyTorch.org) server is an implementation of KFServing for serving PyTorch models, and provides a PyTorch model implementation for prediction, pre and post processing. + +To start the server locally for development needs, run the following command under this folder in your github repository. + +``` +pip install -e . +``` + +The following output indicates a successful install. + +``` +Obtaining file:///Users/animeshsingh/go/src/github.com/kubeflow/kfserving/python/pytorchserver +Requirement already satisfied: kfserver==0.1.0 in /Users/animeshsingh/DevAdv/kfserving/python/kfserving (from pytorchserver==0.1.0) (0.1.0) +Requirement already satisfied: torch>=1.0.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytorchserver==0.1.0) (1.1.0) +Requirement already satisfied: argparse>=1.4.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytorchserver==0.1.0) (1.4.0) +Requirement already satisfied: numpy>=1.8.2 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytorchserver==0.1.0) (1.16.3) +Collecting torchvision>=0.2.2 (from pytorchserver==0.1.0) + Downloading https://files.pythonhosted.org/packages/af/7c/247d46a1f76dee688636d4d5394e440bb32c4e251ea8afe4442c91296830/torchvision-0.3.0-cp37-cp37m-macosx_10_7_x86_64.whl (231kB) +Requirement already satisfied: tornado>=1.4.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from kfserver==0.1.0->pytorchserver==0.1.0) (6.0.2) +Requirement already satisfied: six in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from torchvision>=0.2.2->pytorchserver==0.1.0) (1.12.0) +Requirement already satisfied: pillow>=4.1.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from torchvision>=0.2.2->pytorchserver==0.1.0) (6.0.0) +Installing collected packages: torchvision, pytorchserver + Found existing installation: pytorchserver 0.1.0 + Uninstalling pytorchserver-0.1.0: + Successfully uninstalled pytorchserver-0.1.0 + Running setup.py develop for pytorchserver +Successfully installed pytorchserver torchvision-0.3.0 +``` + +Once PyTorch server is up and running, you can check for successful installation by running the following command + +``` +python3 -m pytorchserver +usage: __main__.py [-h] [--http_port HTTP_PORT] [--grpc_port GRPC_PORT] + [--protocol {tensorflow.http,seldon.http}] --model_dir + MODEL_DIR [--model_name MODEL_NAME] + [--model_class_name MODEL_CLASS_NAME] +__main__.py: error: the following arguments are required: --model_dir +``` + +You can now point to your `pytorch` model directory and use the server to load the model and test for prediction. Model and associaed model class file can be on local filesystem, S3 compatible object storage or Google Cloud Storage. Please follow [this sample](https://github.com/kubeflow/kfserving/tree/master/docs/samples/pytorch) to test your server by generating your own model. + +## Development + +Install the development dependencies with: + +```bash +pip install -e .[test] +``` + +The following indicates a successful install. + +``` +Obtaining file:///Users/animeshsingh/go/src/github.com/kubeflow/kfserving/python/pytorchserver +Requirement already satisfied: kfserver==0.1.0 in /Users/animeshsingh/DevAdv/kfserving/python/kfserving (from pytorchserver==0.1.0) (0.1.0) +Requirement already satisfied: torch>=1.0.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytorchserver==0.1.0) (1.1.0) +Requirement already satisfied: argparse>=1.4.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytorchserver==0.1.0) (1.4.0) +Requirement already satisfied: numpy>=1.8.2 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytorchserver==0.1.0) (1.16.3) +Requirement already satisfied: torchvision>=0.2.2 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytorchserver==0.1.0) (0.3.0) +Requirement already satisfied: pytest in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytorchserver==0.1.0) (4.5.0) +Requirement already satisfied: pytest-tornasync in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytorchserver==0.1.0) (0.6.0.post1) +Requirement already satisfied: mypy in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytorchserver==0.1.0) (0.701) +Requirement already satisfied: tornado>=1.4.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from kfserver==0.1.0->pytorchserver==0.1.0) (6.0.2) +Requirement already satisfied: pillow>=4.1.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from torchvision>=0.2.2->pytorchserver==0.1.0) (6.0.0) +Requirement already satisfied: six in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from torchvision>=0.2.2->pytorchserver==0.1.0) (1.12.0) +Requirement already satisfied: py>=1.5.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytest->pytorchserver==0.1.0) (1.8.0) +Requirement already satisfied: pluggy!=0.10,<1.0,>=0.9 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytest->pytorchserver==0.1.0) (0.11.0) +Requirement already satisfied: more-itertools>=4.0.0; python_version > "2.7" in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytest->pytorchserver==0.1.0) (7.0.0) +Requirement already satisfied: wcwidth in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytest->pytorchserver==0.1.0) (0.1.7) +Requirement already satisfied: atomicwrites>=1.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytest->pytorchserver==0.1.0) (1.3.0) +Requirement already satisfied: attrs>=17.4.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytest->pytorchserver==0.1.0) (19.1.0) +Requirement already satisfied: setuptools in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from pytest->pytorchserver==0.1.0) (40.8.0) +Requirement already satisfied: mypy-extensions<0.5.0,>=0.4.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from mypy->pytorchserver==0.1.0) (0.4.1) +Requirement already satisfied: typed-ast<1.4.0,>=1.3.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from mypy->pytorchserver==0.1.0) (1.3.5) +Installing collected packages: pytorchserver + Found existing installation: pytorchserver 0.1.0 + Uninstalling pytorchserver-0.1.0: + Successfully uninstalled pytorchserver-0.1.0 + Running setup.py develop for pytorchserver +Successfully installed pytorchserver +``` + +To run tests, please change the test file to point to your model.pt file. Then run the following command: + +```bash +make test +``` + +The following shows the type of output you should see: + +``` +pytest -W ignore +=========================================================== test session starts ============================================================ +platform darwin -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0 +rootdir: /Users/animeshsingh/go/src/github.com/kubeflow/kfserving/python/pytorchserver +plugins: tornasync-0.6.0.post1 +collected 1 item + +pytorchserver/test_model.py . +``` + +To run static type checks: + +```bash +mypy --ignore-missing-imports pytorchserver +``` + +An empty result will indicate success. + +## Building your own PyTorch server Docker Image + +You can build and publish your own image for development needs. Please ensure that you modify the kfservice files for PyTorch in the api directory to point to your own image. + +To build your own image, run + +```bash +docker build -t docker_user_name/pytorchserver -f pytorch.Dockerfile . +``` + +You should see an output with an ending similar to this + +```bash +Installing collected packages: torch, pytorchserver + Found existing installation: torch 1.0.0 + Uninstalling torch-1.0.0: + Successfully uninstalled torch-1.0.0 + Running setup.py develop for pytorchserver +Successfully installed pytorchserver torch-1.1.0 +Removing intermediate container 9f6cb904ec57 + ---> 1272c4674955 +Step 11/11 : ENTRYPOINT ["python", "-m", "pytorchserver"] + ---> Running in 6bbbdda829ec +Removing intermediate container 6bbbdda829ec + ---> c5ac6833fdfe +Successfully built c5ac6833fdfe +Successfully tagged animeshsingh/pytorchserver:latest +``` + +To push your image to your dockerhub repo, + +```bash +docker push docker_user_name/pytorchserver:latest +``` diff --git a/python/pytorchserver/pytorchserver/__init__.py b/python/pytorchserver/pytorchserver/__init__.py new file mode 100644 index 00000000000..3532af29ffe --- /dev/null +++ b/python/pytorchserver/pytorchserver/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2019 kubeflow.org. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License 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. + +from .model import PyTorchModel diff --git a/python/pytorchserver/pytorchserver/__main__.py b/python/pytorchserver/pytorchserver/__main__.py new file mode 100644 index 00000000000..7f6da36148e --- /dev/null +++ b/python/pytorchserver/pytorchserver/__main__.py @@ -0,0 +1,36 @@ +# Copyright 2019 kubeflow.org. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License 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. + +import kfserving +import argparse + +from pytorchserver import PyTorchModel + +DEFAULT_MODEL_NAME = "model" +DEFAULT_LOCAL_MODEL_DIR = "/tmp/model" +DEFAULT_MODEL_CLASS_NAME = "PyTorchModel" + +parser = argparse.ArgumentParser(parents=[kfserving.server.parser]) +parser.add_argument('--model_dir', required=True, + help='A URI pointer to the model directory') +parser.add_argument('--model_name', default=DEFAULT_MODEL_NAME, + help='The name that the model is served under.') +parser.add_argument('--model_class_name', default=DEFAULT_MODEL_CLASS_NAME, + help='The class name for the model.') +args, _ = parser.parse_known_args() + +if __name__ == "__main__": + model = PyTorchModel(args.model_name, args.model_class_name, args.model_dir) + model.load() + kfserving.KFServer().start([model]) diff --git a/python/pytorchserver/pytorchserver/model.py b/python/pytorchserver/pytorchserver/model.py new file mode 100644 index 00000000000..da9ae1a6c5b --- /dev/null +++ b/python/pytorchserver/pytorchserver/model.py @@ -0,0 +1,73 @@ +# Copyright 2019 kubeflow.org. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License 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. + +import kfserving +import numpy as np +import os +from typing import List, Any +import torch +from torch.autograd import Variable +import importlib +import shutil +import sys + +PYTORCH_FILE = "model.pt" + +class PyTorchModel(kfserving.KFModel): + def __init__(self, name: str, model_class_name: str, model_dir: str): + super().__init__(name) + self.name = name + self.model_class_name = model_class_name + self.model_dir = model_dir + self.ready = False + + def load(self): + model_file_dir = kfserving.Storage.download(self.model_dir) + model_file = os.path.join(model_file_dir, PYTORCH_FILE) + py_files = [] + for filename in os.listdir(model_file_dir): + if filename.endswith('.py'): + py_files.append(filename) + if len(py_files) == 1: + model_class_file = os.path.join(model_file_dir, py_files[0]) + elif len(py_files) == 0: + raise Exception('Missing PyTorch Model Class File.') + else: + raise Exception('More than one Python file is detected', + 'Only one Python file is allowed within model_dir.') + model_class_name = self.model_class_name + + # Load the python class into memory + sys.path.append(os.path.dirname(model_class_file)) + modulename = os.path.basename(model_class_file).split('.')[0].replace('-', '_') + model_class = getattr(importlib.import_module(modulename), model_class_name) + + # Make sure the model weight is transform with the right device in this machine + device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') + self._pytorch = model_class().to(device) + self._pytorch.load_state_dict(torch.load(model_file, map_location=device)) + self._pytorch.eval() + self.ready = True + + def predict(self, body: List) -> List: + try: + inputs = torch.tensor(body) + except Exception as e: + raise Exception( + "Failed to initialize Torch Tensor from inputs: %s, %s" % (e, inputs)) + try: + result = self._pytorch(inputs).tolist() + return result + except Exception as e: + raise Exception("Failed to predict %s" % e) diff --git a/python/pytorchserver/pytorchserver/test_model.py b/python/pytorchserver/pytorchserver/test_model.py new file mode 100644 index 00000000000..8df5f899030 --- /dev/null +++ b/python/pytorchserver/pytorchserver/test_model.py @@ -0,0 +1,39 @@ +# Copyright 2019 kubeflow.org. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License 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. + +from pytorchserver import PyTorchModel +import os +import torch +import torchvision +import torchvision.transforms as transforms + +model_dir = "../../docs/samples/pytorch" +MODEL_FILE = "model.pt" + +def test_model(): + server = PyTorchModel("pytorchmodel", "Net", model_dir) + server.load() + + transform = transforms.Compose([transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) + testset = torchvision.datasets.CIFAR10(root='./data', train=False, + download=True, transform=transform) + testloader = torch.utils.data.DataLoader(testset, batch_size=4, + shuffle=False, num_workers=2) + dataiter = iter(testloader) + images, labels = dataiter.next() + + request = images[0:1].tolist() + response = server.predict(request) + assert isinstance(response[0], list) diff --git a/python/pytorchserver/setup.py b/python/pytorchserver/setup.py new file mode 100644 index 00000000000..6dc526aaa93 --- /dev/null +++ b/python/pytorchserver/setup.py @@ -0,0 +1,41 @@ +# Copyright 2019 kubeflow.org. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License 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. + +from setuptools import setup, find_packages + +tests_require = [ + 'pytest', + 'pytest-tornasync', + 'mypy' +] +setup( + name='pytorchserver', + version='0.1.0', + author_email='singhan@us.ibm.com', + license='https://github.com/kubeflow/kfserving/LICENSE', + url='https://github.com/kubeflow/kfserving/python/pytorchserver', + description='Model Server implementation for PyTorch. Not intended for use outside KFServing Frameworks Images', + long_description=open('README.md').read(), + python_requires='>3.4', + packages=find_packages("pytorchserver"), + install_requires=[ + "kfserver==0.1.0", + "torch >= 1.0.0", + "argparse >= 1.4.0", + "numpy >= 1.8.2", + "torchvision >= 0.2.0" + ], + tests_require=tests_require, + extras_require={'test': tests_require} +)