├── .github
└── workflows
│ └── azureml-ci-cd.yml
├── .gitignore
├── LICENSE
├── Readme.md
├── aml_service
├── ci_cd
│ ├── 00-WorkSpace.py
│ ├── 01-AttachAmlCluster.py
│ ├── 02-AttachDSVM.py
│ ├── 03-AttachRemoteCompute.py
│ ├── 10-Train.py
│ ├── 20-RegisterModel.py
│ ├── 30-ProfileModel.py
│ ├── 40-DevDeployment.py
│ ├── 50-TestDeployment.py
│ ├── 60-ProdDeployment.py
│ ├── helper
│ │ ├── __init__.py
│ │ └── utils.py
│ └── requirements.txt
└── settings.json
├── code
├── scoring
│ └── score.py
├── testing
│ ├── __init__.py
│ └── test_functions.py
└── training
│ └── train.py
├── data
├── diabetes.csv
├── diabetes_bad_dist.csv
├── diabetes_bad_schema.csv
└── diabetes_missing_values.csv
└── pictures
├── github-actions-azure-machine-learning.png
└── ml-lifecycle.png
/.github/workflows/azureml-ci-cd.yml:
--------------------------------------------------------------------------------
1 | name: DevOps for ML (CI/CD)
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | paths:
8 | - 'code/**'
9 |
10 | jobs:
11 | train-and-deploy:
12 | name: Model Training and Deployment
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - name: Check Out Repository
17 | uses: actions/checkout@master
18 |
19 | - name: Azure Login
20 | uses: azure/login@v1
21 | with:
22 | creds: ${{ secrets.AZURE_CREDENTIALS }}
23 |
24 | - name: Set up Python 3.7
25 | uses: actions/setup-python@v1
26 | with:
27 | python-version: 3.7
28 |
29 | - name: Install Dependencies
30 | run: |
31 | python -m pip install --upgrade pip
32 | pip install -r 'aml_service/ci_cd/requirements.txt'
33 |
34 | - name: Create or Connect to Workspace
35 | run: |
36 | python 'aml_service/ci_cd/00-WorkSpace.py' --subscription-id ${{ secrets.SUBSCRIPTION_ID }} --workspace-name ${{ secrets.WORKSPACE_NAME }} --resource-group ${{ secrets.RESOURCE_GROUP }} --location ${{ secrets.LOCATION }} --friendly-name ${{ secrets.FRIENDLY_NAME }}
37 |
38 | - name: Create or Load Azure Machine Learning Compute
39 | run: |
40 | python 'aml_service/ci_cd/01-AttachAmlCluster.py'
41 |
42 | - name: Train Model
43 | run: |
44 | python 'aml_service/ci_cd/10-Train.py'
45 |
46 | - name: Evaluate and Register Model
47 | run: |
48 | python 'aml_service/ci_cd/20-RegisterModel.py'
49 |
50 | - name: Profile Model
51 | run: |
52 | python 'aml_service/ci_cd/30-ProfileModel.py'
53 |
54 | - name: Dev Deployment
55 | run: |
56 | python 'aml_service/ci_cd/40-DevDeployment.py'
57 |
58 | - name: Test Deployment
59 | run: |
60 | python 'aml_service/ci_cd/50-TestDeployment.py'
61 |
62 | - name: Production Deployment
63 | run: |
64 | python 'aml_service/ci_cd/60-ProdDeployment.py'
65 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 | *.vscode
93 |
94 | # Spyder project settings
95 | .spyderproject
96 | .spyproject
97 |
98 | # Rope project settings
99 | .ropeproject
100 |
101 | # mkdocs documentation
102 | /site
103 |
104 | # mypy
105 | .mypy_cache/
106 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | ### **INFO: We have built a new and even simpler method to do MLOps with GitHub Actions. Please visit this repository to get started: https://github.com/machine-learning-apps/ml-template-azure**
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | # ML DevOps with GitHub Actions and Azure ML
13 |
14 | This repository demonstrates how to automate the machine learning lifecycle using the CI/CD pipeline tools of [GitHub Actions](https://github.com/features/actions) and [Azure Machine Learning](https://docs.microsoft.com/en-us/azure/machine-learning/) for training and deployment. The repository does not make use of Azure DevOps, but uses [GitHub Actions](https://github.com/features/actions) as a future proof backend system for workflow automation.
15 |
16 | The repository includes the following features:
17 | - [GitHub Actions](https://github.com/features/actions) for the continuous integration (CI) and continuous delivery (CD) pipeline
18 | - [Azure Machine Learning](https://docs.microsoft.com/en-us/azure/machine-learning/) as a backend for training and deployment of machine learning models
19 | - CI/CD pipeline as code: the repository uses the [Azure Machine Learning Python SDK](https://docs.microsoft.com/en-us/python/api/overview/azure/ml/intro?view=azure-ml-py) to define the CI/CD steps and implements almost all features of this framework
20 | - Central settings file in json format to enable quick customization of of each step of the pipline
21 |
22 | ## Implemented Azure ML features in the CI/CD pipeline
23 |
24 | The repository and the CI/CD pipeline makes use of the following key features of [Azure Machine Learning](https://docs.microsoft.com/en-us/azure/machine-learning/):
25 | - Loading or deployment of Workspace
26 | - Training on different compute engines: Azure Machine Learning Compute, Data Science VM, Remote VM
27 | - Automatically creates or attaches the compute engine, if it is not available yet
28 | - Allows extensive customizations of the compute engine depending on your requirements
29 | - Granular adjustment of training process
30 | - Custom docker images and container registries
31 | - Distributed training backends: MPI, Parameter Server, Gloo, NCCL
32 | - Supports all frameworks: TensorFlow, PyTorch, SKLearn, Chainer, etc.
33 | - Registration of environment
34 | - Hyperparameter Tuning
35 | - Comparison of models before registration in workspace
36 | - Comparison of production model and newly trained model based on metrics defined in central settings file
37 | - Model profiling after training has completed successfully
38 | - Recommends number of CPUs and RAM size for deployment
39 | - Deployment with testing in three phases:
40 | - Dev deployment: deployment on Azure Container Instance
41 | - Test deployment: deployment on Azure Kubernetes Service with purpose DEV_TEST
42 | - Production deployment: deployment on Azure Kubernetes Service with purpose FAST_PROD
43 | - And many others ...
44 |
45 | ## What is ML DevOps?
46 |
47 |
48 |
49 |
50 |
51 | MLOps empowers data scientists and app developers to bring together their knowledge and skills to simplify the model development as well as the release and deployment of them. ML DevOps enables you to track, version, test, certify and reuse assets in every part of the machine learning lifecycle and provides orchestration services to streamline managing this lifecycle. This allows to automate the end to end machine Learning lifecycle to frequently update models, test new models, and continuously roll out new ML models alongside your other applications and services.
52 |
53 | This repository enables Data Scientists to focus on the training and deployment code of their machine learning project (`code` folder of this repository). Once new code is checked into the `code` folder of the master branch of this repository, the CI/CD pipeline is triggered and the training process starts automatically in the linked Azure Machine Learning workspace. Once the training process is completed successfully, the deployment of the model takes place in three stages: dev, test and production stage.
54 |
55 | ## Key challenges solved by ML DevOps
56 |
57 | **Model reproducibility & versioning**
58 | - Track, snapshot & manage assets used to create the model
59 | - Enable collaboration and sharing of ML pipelines
60 |
61 | **Model auditability & explainability**
62 | - Maintain asset integrity & persist access control logs
63 | - Certify model behavior meets regulatory & adversarial standards
64 |
65 | **Model packaging & validation**
66 | - Support model portability across a variety of platforms
67 | - Certify model performance meets functional and latency requirements
68 |
69 | **Model deployment & monitoring**
70 | - Release models with confidence
71 | - Monitor & know when to retrain by analyzing signals such as data drift
72 |
73 | ## Prerequisites
74 |
75 | The following prerequisites are required to make this repository work:
76 | - Azure subscription
77 | - Contributor access to the Azure subscription
78 | - Access to the [GitHub Actions Beta](https://github.com/features/actions)
79 |
80 | If you don’t have an Azure subscription, create a free account before you begin. Try the [free or paid version of Azure Machine Learning](https://aka.ms/AMLFree) today.
81 |
82 | ## Settings file
83 |
84 | The repository uses a central settings file in [`/aml_service/settings.json`](/aml_service/settings.json) to enable quick customizations of the end to end pipeline. The file can be found [here](/aml_service/settings.json) and can be used to adjust the parameters of:
85 | - The compute engines for training and deployment,
86 | - The training process (experiment and run) and
87 | - The deployment process.
88 |
89 | ## GitHub Workflow
90 |
91 | The GitHub Workflow requires the follwing secrets:
92 | - `AZURE_CREDENTIALS`: Used for the az login action in the [GitHub Actions Workflow](https://github.com/features/actions). Please visit [this website](https://github.com/Azure/login#github-actions-for-deploying-to-azure) for a tutorial of this GitHub Action.
93 | - `FRIENDLY_NAME`: Friendly name of the Azure ML workspace.
94 | - `LOCATION`: Location of the workspace (e.g. `westeurope`, etc.)
95 | - `RESOURCE_GROUP`: Resource group where Azure Machine Learning was or will be deployed.
96 | - `SUBSCRIPTION_ID`: ID of the Azure subscription that should be used.
97 | - `WORKSPACE_NAME`: Name of your workspace or the workspace that should be created by the pipeline.
98 |
99 | ## Further Links
100 |
101 | - [GitHub Actions Documentation](https://help.github.com/en/github/automating-your-workflow-with-github-actions)
102 | - [Azure Machine Learning Documentation](https://docs.microsoft.com/en-us/azure/machine-learning/)
103 | - [Azure Machine Learning Python SDK Reference](https://docs.microsoft.com/en-us/python/api/overview/azure/ml/intro?view=azure-ml-py)
104 |
105 | ## TODO
106 |
107 | - Implement automatic Swagger generation
108 | - Handover of model name to training script
109 | - Bugfix in model evaluation
110 | - stop pileine failing if model performs worse: use features in GitHub Actions for improvement
111 |
--------------------------------------------------------------------------------
/aml_service/ci_cd/00-WorkSpace.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 |
27 | import os, json, sys, argparse
28 | import azureml.core
29 | from azureml.core import Workspace
30 | from azureml.exceptions import WorkspaceException
31 | from azureml.core.authentication import AzureCliAuthentication
32 |
33 | print("SDK Version of azureml: ", azureml.core.VERSION)
34 | print("Current directory: " + os.getcwd())
35 |
36 | # Parse Arguments
37 | print("Parsing arguments")
38 | parser = argparse.ArgumentParser(description="Azure Machine Learning Service - CI/CD")
39 | parser.add_argument("--subscription-id", type=str, dest="subscription_id", help="ID of the Subscription that should be used")
40 | parser.add_argument("--workspace-name", type=str, dest="workspace_name", help="Name of the Azure Machine Learning Workscpace")
41 | parser.add_argument("--resource-group", type=str, dest="resource_group", help="Name of the Resource Group")
42 | parser.add_argument("--location", type=str, dest="location", help="Region in Azure")
43 | parser.add_argument("--friendly-name", type=str, dest="friendly_name", help="Friendly name of the Azure Machine Learning Workspace")
44 | args = parser.parse_args()
45 |
46 | # Mask values
47 | print("Masking values")
48 | print(f"::add-mask::{args.subscription_id}")
49 |
50 | # Use Azure CLI authentication
51 | cli_auth = AzureCliAuthentication()
52 |
53 | try:
54 | print("Loading existing Workspace")
55 | ws = Workspace.get(
56 | name=args.workspace_name,
57 | subscription_id=args.subscription_id,
58 | resource_group=args.resource_group,
59 | auth=cli_auth
60 | )
61 | print("Found existing Workspace")
62 | except WorkspaceException:
63 | print("Loading failed")
64 | print("Creating new Workspace")
65 | ws = Workspace.create(
66 | name=args.workspace_name,
67 | auth=cli_auth,
68 | subscription_id=args.subscription_id,
69 | resource_group=args.resource_group,
70 | location=args.location,
71 | create_resource_group=True,
72 | friendly_name=args.friendly_name,
73 | show_output=True
74 | )
75 |
76 | # Write out the Workspace ARM properties to a config file
77 | config_file_path = os.environ.get("GITHUB_WORKSPACE", default="aml_service")
78 | config_file_name = "aml_arm_config.json"
79 | ws.write_config(
80 | path=config_file_path,
81 | file_name=config_file_name
82 | )
83 |
84 | # Print Workspace details --> only print, if repository is private
85 | print("Workspace name: " + ws.name,
86 | "Azure region: " + ws.location,
87 | "Subscription id: " + ws.subscription_id,
88 | "Resource group: " + ws.resource_group, sep = '\n')
89 | print("Successfully loaded Workspace")
--------------------------------------------------------------------------------
/aml_service/ci_cd/01-AttachAmlCluster.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 |
27 | import os, json
28 | from azureml.core import Workspace
29 | from azureml.core.compute import ComputeTarget, AmlCompute
30 | from azureml.exceptions import ComputeTargetException
31 | from azureml.core.authentication import AzureCliAuthentication
32 |
33 | # Load the JSON settings file
34 | print("Loading settings")
35 | with open(os.path.join("aml_service", "settings.json")) as f:
36 | settings = json.load(f)
37 | aml_settings = settings["compute_target"]["training"]["amlcompute"]
38 |
39 | # Get workspace
40 | print("Loading Workspace")
41 | cli_auth = AzureCliAuthentication()
42 | config_file_path = os.environ.get("GITHUB_WORKSPACE", default="aml_service")
43 | config_file_name = "aml_arm_config.json"
44 | ws = Workspace.from_config(
45 | path=config_file_path,
46 | auth=cli_auth,
47 | _file_name=config_file_name)
48 | print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\n')
49 |
50 | try:
51 | # Loading AMLCompute
52 | print("Loading existing AML Compute")
53 | cluster = AmlCompute(workspace=ws, name=aml_settings["name"])
54 |
55 | # Check settings and redeploy if required settings have changed
56 | print("Found existing cluster")
57 | if cluster.vm_size.lower() != aml_settings["vm_size"].lower() or cluster.vm_priority.lower() != aml_settings["vm_priority"].lower():
58 | cluster.delete()
59 | cluster.wait_for_completion(show_output=True)
60 | raise ComputeTargetException("Cluster is of incorrect size or has incorrect priority. Deleting cluster and provisioning a new one.")
61 |
62 | # Update AMLCompute
63 | #if cluster.provisioning_configuration.min_nodes != aml_settings["min_nodes"] or cluster.provisioning_configuration.max_nodes != aml_settings["max_nodes"] or cluster.provisioning_configuration.idle_seconds_before_scaledown != aml_settings["idle_seconds_before_scaledown"]:
64 | print("Updating settings of Cluster")
65 | cluster.update(min_nodes=aml_settings["min_nodes"],
66 | max_nodes=aml_settings["max_nodes"],
67 | idle_seconds_before_scaledown=aml_settings["idle_seconds_before_scaledown"])
68 |
69 | # Wait until the operation has completed
70 | cluster.wait_for_completion(show_output=True)
71 |
72 | print("Successfully updated Cluster definition")
73 | except ComputeTargetException:
74 | print("Loading failed")
75 | print("Creating new AML Compute resource")
76 | compute_config = AmlCompute.provisioning_configuration(vm_size=aml_settings["vm_size"],
77 | vm_priority=aml_settings["vm_priority"],
78 | min_nodes=aml_settings["min_nodes"],
79 | max_nodes=aml_settings["max_nodes"],
80 | idle_seconds_before_scaledown=aml_settings["idle_seconds_before_scaledown"],
81 | tags=aml_settings["tags"],
82 | description=aml_settings["description"])
83 |
84 | # Deploy to VNET if provided
85 | if aml_settings["vnet_resource_group_name"] and aml_settings["vnet_name"] and aml_settings["subnet_name"]:
86 | compute_config.vnet_resourcegroup_name = aml_settings["vnet_resource_group_name"]
87 | compute_config.vnet_name = aml_settings["vnet_name"]
88 | compute_config.subnet_name = aml_settings["subnet_name"]
89 |
90 | # Set Credentials if provided
91 | if aml_settings["admin_username"] and aml_settings["admin_user_password"]:
92 | compute_config.admin_username = aml_settings["admin_username"]
93 | compute_config.admin_user_password = aml_settings["admin_user_password"]
94 | elif aml_settings["admin_username"] and aml_settings["admin_user_ssh_key"]:
95 | compute_config.admin_username = aml_settings["admin_username"]
96 | compute_config.admin_user_ssh_key = aml_settings["admin_user_ssh_key"]
97 |
98 | # Create Compute Target
99 | cluster = ComputeTarget.create(workspace=ws, name=aml_settings["name"], provisioning_configuration=compute_config)
100 |
101 | # Wait until the cluster is attached
102 | cluster.wait_for_completion(show_output=True)
103 |
104 | # Checking status of AMLCompute Cluster
105 | print("Checking status of AMLCompute Cluster")
106 | if cluster.provisioning_state == "Failed":
107 | cluster.delete()
108 | raise Exception(
109 | "Deployment of AMLCompute Cluster failed with the following status: {} and logs: \n{}".format(
110 | cluster.provisioning_state, cluster.provisioning_errors
111 | )
112 | )
--------------------------------------------------------------------------------
/aml_service/ci_cd/02-AttachDSVM.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 |
27 | import os, json
28 | from azureml.core import Workspace
29 | from azureml.core.compute import DsvmCompute
30 | from azureml.exceptions import ComputeTargetException
31 | from azureml.core.authentication import AzureCliAuthentication
32 |
33 | # Load the JSON settings file
34 | print("Loading settings")
35 | with open(os.path.join("aml_service", "settings.json")) as f:
36 | settings = json.load(f)
37 | dsvm_settings = settings["compute_target"]["training"]["dsvm"]
38 |
39 | # Get workspace
40 | print("Loading Workspace")
41 | cli_auth = AzureCliAuthentication()
42 | config_file_path = os.environ.get("GITHUB_WORKSPACE", default="aml_service")
43 | config_file_name = "aml_arm_config.json"
44 | ws = Workspace.from_config(
45 | path=config_file_path,
46 | auth=cli_auth,
47 | _file_name=config_file_name)
48 | print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\n')
49 |
50 | try:
51 | print("Loading existing and attached DSVM")
52 | dsvm_compute = DsvmCompute(workspace=ws, name=dsvm_settings["name"])
53 | print("Found existing VM")
54 | if dsvm_compute.vm_size != dsvm_settings["vm_size"] or dsvm_compute.location != dsvm_settings["location"]:
55 | dsvm_compute.delete()
56 | dsvm_compute.wait_for_completion(show_output=True)
57 | raise ComputeTargetException("VM is of incorrect size or was deployed in a different location. Deleting VM and provisioning a new one.")
58 | except ComputeTargetException:
59 | print("Loading failed")
60 | print("Creating and attaching new DSVM")
61 | dsvm_config = DsvmCompute.provisioning_configuration(vm_size=dsvm_settings["vm_size"])
62 | if dsvm_settings["location"]:
63 | dsvm_config.location = dsvm_settings["location"]
64 | if dsvm_settings["ssh_port"]:
65 | dsvm_config.ssh_port = dsvm_settings["ssh_port"]
66 |
67 | # Create Compute Target
68 | dsvm_compute = DsvmCompute.create(workspace=ws, name=dsvm_settings["name"], provisioning_configuration=dsvm_config)
69 |
70 | # Wait until the VM is attached
71 | dsvm_compute.wait_for_completion(show_output=True)
72 |
73 | # Checking status of DSVM
74 | print("Checking status of DSVM")
75 | if dsvm_compute.provisioning_state == "Failed":
76 | dsvm_compute.delete()
77 | raise Exception(
78 | "Deployment of DSVM failed with the following status: {} and logs: \n{}".format(
79 | dsvm_compute.provisioning_state, dsvm_compute.provisioning_errors
80 | )
81 | )
--------------------------------------------------------------------------------
/aml_service/ci_cd/03-AttachRemoteCompute.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 |
27 | import os, json
28 | from azureml.core import Workspace
29 | from azureml.core.compute import ComputeTarget, RemoteCompute
30 | from azureml.exceptions import ComputeTargetException
31 | from azureml.core.authentication import AzureCliAuthentication
32 |
33 | # Load the JSON settings file
34 | print("Loading settings")
35 | with open(os.path.join("aml_service", "settings.json")) as f:
36 | settings = json.load(f)
37 | remotecompute_settings = settings["compute_target"]["training"]["remotecompute"]
38 |
39 | # Get workspace
40 | print("Loading Workspace")
41 | cli_auth = AzureCliAuthentication()
42 | config_file_path = os.environ.get("GITHUB_WORKSPACE", default="aml_service")
43 | config_file_name = "aml_arm_config.json"
44 | ws = Workspace.from_config(
45 | path=config_file_path,
46 | auth=cli_auth,
47 | _file_name=config_file_name)
48 | print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\n')
49 |
50 | try:
51 | # Loading remote compute
52 | print("Loading existing and attached compute resource")
53 | remote_compute = RemoteCompute(workspace=ws, name=remotecompute_settings["name"])
54 | print("Found existing VM")
55 | except ComputeTargetException:
56 | print("Loading failed")
57 | print("Trying to attach existing compute")
58 |
59 | # Create the compute config
60 | attach_config = RemoteCompute.attach_configuration(
61 | address=remotecompute_settings["address"],
62 | ssh_port=remotecompute_settings["ssh_port"],
63 | username=remotecompute_settings["address"]
64 | )
65 | if remotecompute_settings["use_ssh_auth"]:
66 | # use ssh authentication
67 | attach_config.password = None
68 | attach_config.private_key_file = remotecompute_settings["private_key_file"]
69 | attach_config.private_key_passphrase = remotecompute_settings["private_key_passphrase"]
70 | else:
71 | # use username and password authentication
72 | attach_config.password = remotecompute_settings["password"]
73 |
74 | # Attach the compute
75 | remote_compute = ComputeTarget.attach(workspace=ws, name=remotecompute_settings["name"], attach_configuration=attach_config)
76 |
77 | # Wait until the VM is attached
78 | remote_compute.wait_for_completion(show_output=True)
79 |
80 | # Checking status of Remote Compute
81 | print("Checking status of Remote Compute")
82 | if remote_compute.provisioning_state == "Failed":
83 | remote_compute.detach()
84 | raise Exception(
85 | "Deployment of Remote Compute failed with the following status: {} and logs: \n{}".format(
86 | remote_compute.provisioning_state, remote_compute.provisioning_errors
87 | )
88 | )
--------------------------------------------------------------------------------
/aml_service/ci_cd/10-Train.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 |
27 | import os, json, azureml.core
28 | from azureml.core import Workspace, Experiment, ContainerRegistry, Environment
29 | from azureml.core.compute import ComputeTarget
30 | from azureml.core.runconfig import MpiConfiguration, TensorflowConfiguration
31 | from azureml.core.authentication import AzureCliAuthentication
32 | from azureml.train.dnn import Chainer, PyTorch, TensorFlow, Gloo, Nccl
33 | from azureml.train.sklearn import SKLearn
34 | from azureml.train.estimator import Estimator
35 | from azureml.train.hyperdrive import HyperDriveConfig, PrimaryMetricGoal
36 | from helper import utils
37 |
38 | # Load the JSON settings file and relevant section
39 | print("Loading settings")
40 | with open(os.path.join("aml_service", "settings.json")) as f:
41 | settings = json.load(f)
42 | experiment_settings = settings["experiment"]
43 | compute_target_to_use = settings["compute_target"]["compute_target_to_use_for_training"].strip().lower()
44 | compute_target_name = settings["compute_target"]["training"][compute_target_to_use]["name"]
45 |
46 | # Get workspace
47 | print("Loading Workspace")
48 | cli_auth = AzureCliAuthentication()
49 | config_file_path = os.environ.get("GITHUB_WORKSPACE", default="aml_service")
50 | config_file_name = "aml_arm_config.json"
51 | ws = Workspace.from_config(
52 | path=config_file_path,
53 | auth=cli_auth,
54 | _file_name=config_file_name)
55 | print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\n')
56 |
57 | # Attach Experiment
58 | print("Loading Experiment")
59 | exp = Experiment(workspace=ws, name=experiment_settings["name"])
60 | print(exp.name, exp.workspace.name, sep="\n")
61 |
62 | # Load compute target
63 | print("Loading Compute Target")
64 | compute_target = ComputeTarget(workspace=ws, name=compute_target_name)
65 |
66 | # Create image registry configuration
67 | if experiment_settings["docker"]["custom_image"]:
68 | container_registry = ContainerRegistry()
69 | container_registry.address = experiment_settings["docker"]["custom_image_registry_details"]["address"]
70 | container_registry.username = experiment_settings["docker"]["custom_image_registry_details"]["username"]
71 | container_registry.password = experiment_settings["docker"]["custom_image_registry_details"]["password"]
72 | else:
73 | container_registry = None
74 |
75 | # Create disributed training configuration
76 | if experiment_settings["distributed_training"]["backend_config"] == "mpi":
77 | distrib_training_backend = MpiConfiguration()
78 | distrib_training_backend.process_count_per_node = experiment_settings["distributed_training"]["mpi"]["process_count_per_node"]
79 | elif experiment_settings["distributed_training"]["backend_config"] == "parameter_server":
80 | distrib_training_backend = TensorflowConfiguration()
81 | distrib_training_backend.worker_count = experiment_settings["distributed_training"]["parameter_server"]["worker_count"]
82 | distrib_training_backend.parameter_server_count = experiment_settings["distributed_training"]["parameter_server"]["parameter_server_count"]
83 | elif experiment_settings["distributed_training"]["backend_config"] == "gloo":
84 | distrib_training_backend = Gloo()
85 | elif experiment_settings["distributed_training"]["backend_config"] == "nccl":
86 | distrib_training_backend = Nccl()
87 | else:
88 | distrib_training_backend = None
89 |
90 | # Create Estimator for Experiment
91 | print("Creating Estimator object according to settings")
92 | if experiment_settings["framework"]["name"] == "chainer":
93 | framework_version = experiment_settings["framework"]["chainer"]["framework_version"]
94 | enable_optimized_mode = experiment_settings["framework"]["chainer"]["_enable_optimized_mode"]
95 |
96 | estimator = Chainer(
97 | source_directory=experiment_settings["source_directory"],
98 | compute_target=compute_target,
99 | entry_script=experiment_settings["entry_script"],
100 | script_params=experiment_settings["script_parameters"],
101 | node_count=experiment_settings["distributed_training"]["node_count"],
102 | distributed_training=distrib_training_backend,
103 | use_docker=experiment_settings["docker"]["use_docker"],
104 | custom_docker_image=experiment_settings["docker"]["custom_image"],
105 | image_registry_details=container_registry,
106 | user_managed=experiment_settings["user_managed"],
107 | conda_packages=experiment_settings["dependencies"]["conda_packages"],
108 | pip_packages=experiment_settings["dependencies"]["pip_packages"],
109 | conda_dependencies_file=experiment_settings["dependencies"]["conda_dependencies_file"],
110 | pip_requirements_file=experiment_settings["dependencies"]["pip_requirements_file"],
111 | environment_variables=experiment_settings["environment_variables"],
112 | inputs=experiment_settings["data_references"],
113 | source_directory_data_store=experiment_settings["source_directory_datastore"],
114 | shm_size=experiment_settings["docker"]["shm_size"],
115 | max_run_duration_seconds=experiment_settings["max_run_duration_seconds"],
116 | framework_version=framework_version,
117 | _enable_optimized_mode=enable_optimized_mode)
118 |
119 | elif experiment_settings["framework"]["name"] == "pytorch":
120 | framework_version = experiment_settings["framework"]["pytorch"]["framework_version"]
121 | enable_optimized_mode = experiment_settings["framework"]["pytorch"]["_enable_optimized_mode"]
122 |
123 | estimator = PyTorch(
124 | source_directory=experiment_settings["source_directory"],
125 | compute_target=compute_target,
126 | entry_script=experiment_settings["entry_script"],
127 | script_params=experiment_settings["script_parameters"],
128 | node_count=experiment_settings["distributed_training"]["node_count"],
129 | distributed_training=distrib_training_backend,
130 | use_docker=experiment_settings["docker"]["use_docker"],
131 | custom_docker_image=experiment_settings["docker"]["custom_image"],
132 | image_registry_details=container_registry,
133 | user_managed=experiment_settings["user_managed"],
134 | conda_packages=experiment_settings["dependencies"]["conda_packages"],
135 | pip_packages=experiment_settings["dependencies"]["pip_packages"],
136 | conda_dependencies_file=experiment_settings["dependencies"]["conda_dependencies_file"],
137 | pip_requirements_file=experiment_settings["dependencies"]["pip_requirements_file"],
138 | environment_variables=experiment_settings["environment_variables"],
139 | inputs=experiment_settings["data_references"],
140 | source_directory_data_store=experiment_settings["source_directory_datastore"],
141 | shm_size=experiment_settings["docker"]["shm_size"],
142 | max_run_duration_seconds=experiment_settings["max_run_duration_seconds"],
143 | framework_version=framework_version,
144 | _enable_optimized_mode=enable_optimized_mode)
145 |
146 | elif experiment_settings["framework"]["name"] == "tensorflow":
147 | framework_version = experiment_settings["framework"]["tensorflow"]["framework_version"]
148 | enable_optimized_mode = experiment_settings["framework"]["tensorflow"]["_enable_optimized_mode"]
149 |
150 | estimator = TensorFlow(
151 | source_directory=experiment_settings["source_directory"],
152 | compute_target=compute_target,
153 | entry_script=experiment_settings["entry_script"],
154 | script_params=experiment_settings["script_parameters"],
155 | node_count=experiment_settings["distributed_training"]["node_count"],
156 | distributed_training=distrib_training_backend,
157 | use_docker=experiment_settings["docker"]["use_docker"],
158 | custom_docker_image=experiment_settings["docker"]["custom_image"],
159 | image_registry_details=container_registry,
160 | user_managed=experiment_settings["user_managed"],
161 | conda_packages=experiment_settings["dependencies"]["conda_packages"],
162 | pip_packages=experiment_settings["dependencies"]["pip_packages"],
163 | conda_dependencies_file=experiment_settings["dependencies"]["conda_dependencies_file"],
164 | pip_requirements_file=experiment_settings["dependencies"]["pip_requirements_file"],
165 | environment_variables=experiment_settings["environment_variables"],
166 | inputs=experiment_settings["data_references"],
167 | source_directory_data_store=experiment_settings["source_directory_datastore"],
168 | shm_size=experiment_settings["docker"]["shm_size"],
169 | max_run_duration_seconds=experiment_settings["max_run_duration_seconds"],
170 | framework_version=framework_version,
171 | _enable_optimized_mode=enable_optimized_mode)
172 |
173 | elif experiment_settings["framework"]["name"] == "sklearn":
174 | framework_version = experiment_settings["framework"]["sklearn"]["framework_version"]
175 | enable_optimized_mode = experiment_settings["framework"]["sklearn"]["_enable_optimized_mode"]
176 |
177 | estimator = SKLearn(
178 | source_directory=experiment_settings["source_directory"],
179 | compute_target=compute_target,
180 | entry_script=experiment_settings["entry_script"],
181 | script_params=experiment_settings["script_parameters"],
182 | use_docker=experiment_settings["docker"]["use_docker"],
183 | custom_docker_image=experiment_settings["docker"]["custom_image"],
184 | image_registry_details=container_registry,
185 | user_managed=experiment_settings["user_managed"],
186 | conda_packages=experiment_settings["dependencies"]["conda_packages"],
187 | pip_packages=experiment_settings["dependencies"]["pip_packages"],
188 | conda_dependencies_file=experiment_settings["dependencies"]["conda_dependencies_file"],
189 | pip_requirements_file=experiment_settings["dependencies"]["pip_requirements_file"],
190 | environment_variables=experiment_settings["environment_variables"],
191 | inputs=experiment_settings["data_references"],
192 | shm_size=experiment_settings["docker"]["shm_size"],
193 | max_run_duration_seconds=experiment_settings["max_run_duration_seconds"],
194 | framework_version=framework_version,
195 | _enable_optimized_mode=enable_optimized_mode)
196 |
197 | else:
198 | estimator = Estimator(
199 | source_directory=experiment_settings["source_directory"],
200 | compute_target=compute_target,
201 | entry_script=experiment_settings["entry_script"],
202 | script_params=experiment_settings["script_parameters"],
203 | node_count=experiment_settings["distributed_training"]["node_count"],
204 | process_count_per_node=experiment_settings["distributed_training"]["mpi"]["process_count_per_node"],
205 | distributed_training=distrib_training_backend,
206 | use_docker=experiment_settings["docker"]["use_docker"],
207 | custom_docker_image=experiment_settings["docker"]["custom_image"],
208 | image_registry_details=container_registry,
209 | user_managed=experiment_settings["user_managed"],
210 | conda_packages=experiment_settings["dependencies"]["conda_packages"],
211 | pip_packages=experiment_settings["dependencies"]["pip_packages"],
212 | conda_dependencies_file=experiment_settings["dependencies"]["conda_dependencies_file"],
213 | pip_requirements_file=experiment_settings["dependencies"]["pip_requirements_file"],
214 | environment_variables=experiment_settings["environment_variables"],
215 | inputs=experiment_settings["data_references"],
216 | source_directory_data_store=experiment_settings["source_directory_datastore"],
217 | shm_size=experiment_settings["docker"]["shm_size"],
218 | max_run_duration_seconds=experiment_settings["max_run_duration_seconds"])
219 |
220 | # Use custom Environment and keep old environment variables
221 | if experiment_settings["use_custom_environment"]:
222 | print("Setting Custom Environment Definition")
223 | env = utils.get_environment()
224 | old_env_variables = estimator._estimator_config.environment.environment_variables
225 | env.environment_variables.update(old_env_variables)
226 | estimator.run_config.environment = env
227 | print(estimator.run_config)
228 |
229 | # Registering Environment
230 | print("Registering Environment")
231 | env = estimator.run_config.environment
232 | env.name = experiment_settings["name"] + "_training"
233 | registered_env = env.register(workspace=ws)
234 | print("Registered Environment")
235 | print(registered_env.name, "Version: " + registered_env.version, sep="\n")
236 |
237 | # Creating HyperDriveConfig for Hyperparameter Tuning
238 | if experiment_settings["hyperparameter_sampling"]["use_hyperparameter_sampling"]:
239 | print("Creating HyperDriveConfig for Hyperparameter Tuning")
240 |
241 | parameter_sampling = utils.get_parameter_sampling(experiment_settings["hyperparameter_sampling"]["method"], experiment_settings["hyperparameter_sampling"]["parameters"])
242 | policy = utils.get_policy(experiment_settings["hyperparameter_sampling"]["policy"])
243 | primary_metric_goal = PrimaryMetricGoal.MAXIMIZE if "max" in experiment_settings["hyperparameter_sampling"]["primary_metric_goal"] else PrimaryMetricGoal.MINIMIZE
244 |
245 | run_config = HyperDriveConfig(estimator=estimator,
246 | hyperparameter_sampling=parameter_sampling,
247 | policy=policy,
248 | primary_metric_name=experiment_settings["hyperparameter_sampling"]["primary_metric_name"],
249 | primary_metric_goal=primary_metric_goal,
250 | max_total_runs=experiment_settings["hyperparameter_sampling"]["max_total_runs"],
251 | max_concurrent_runs=experiment_settings["hyperparameter_sampling"]["max_concurrent_runs"],
252 | max_duration_minutes=experiment_settings["hyperparameter_sampling"]["max_duration_minutes"])
253 | else:
254 | run_config = estimator
255 |
256 | # Submitting an Experiment and creating a Run
257 | print("Submitting an experiment and creating a run")
258 | run = exp.submit(run_config, tags=experiment_settings["run_tags"])
259 |
260 | # Shows output of the run on stdout
261 | run.wait_for_completion(show_output=True, wait_post_processing=True)
262 |
263 | # Checking status of Run
264 | print("Checking status Run")
265 | if run.get_status() != "Completed":
266 | raise Exception(
267 | "Training on local failed with following run status: {} and logs: \n {}".format(
268 | run.get_status(), run.get_details_with_logs()
269 | )
270 | )
271 |
272 | # Writing the run id to /aml_service/run_id.json
273 | run_details = {}
274 | run_details["run_id"] = run.id
275 | run_details["experiment_name"] = run.experiment.name
276 | with open(os.path.join("aml_service", "run_details.json"), "w") as outfile:
277 | json.dump(run_details, outfile)
--------------------------------------------------------------------------------
/aml_service/ci_cd/20-RegisterModel.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 | import os, json, sys, azureml.core
27 | from azureml.core import Workspace, Experiment, Run
28 | from azureml.core.model import Model
29 | from azureml.core.authentication import AzureCliAuthentication
30 |
31 | # Load the JSON settings file and relevant section
32 | print("Loading settings")
33 | with open(os.path.join("aml_service", "settings.json")) as f:
34 | settings = json.load(f)
35 | deployment_settings = settings["deployment"]
36 |
37 | # Get details from Run
38 | print("Loading Run Details")
39 | with open(os.path.join("aml_service", "run_details.json")) as f:
40 | run_details = json.load(f)
41 |
42 | # Get workspace
43 | print("Loading Workspace")
44 | cli_auth = AzureCliAuthentication()
45 | config_file_path = os.environ.get("GITHUB_WORKSPACE", default="aml_service")
46 | config_file_name = "aml_arm_config.json"
47 | ws = Workspace.from_config(
48 | path=config_file_path,
49 | auth=cli_auth,
50 | _file_name=config_file_name)
51 | print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\n')
52 |
53 | # Loading Run
54 | print("Loading Run")
55 | experiment = Experiment(workspace=ws, name=run_details["experiment_name"])
56 | run = Run(experiment=experiment, run_id=run_details["run_id"])
57 |
58 | # Only register model, if it performs better than the production model
59 | print("Register model only if it performs better.")
60 | try:
61 | # Loading run of production model
62 | print("Loading Run of Production Model to evaluate new model")
63 | production_model = Model(workspace=ws, name=deployment_settings["model"]["name"])
64 | production_model_run_id = production_model.tags.get(["run_id"])
65 | production_model_run = Run(experiment=experiment, run_id=production_model_run_id)
66 |
67 | # Comparing models
68 | print("Comparing Metrics of production and newly trained model")
69 | promote_new_model = True
70 | for metric in deployment_settings["model"]["evaluation_parameters"]["larger_is_better"]:
71 | if not promote_new_model:
72 | break
73 | new_model_parameter = run.get_metrics().get(metric)
74 | production_model_parameter = production_model_run.get_metrics().get(metric)
75 | if new_model_parameter < production_model_parameter:
76 | promote_new_model = False
77 | for metric in deployment_settings["model"]["evaluation_parameters"]["smaller_is_better"]:
78 | if not promote_new_model:
79 | break
80 | new_model_parameter = run.get_metrics().get(metric)
81 | production_model_parameter = production_model_run.get_metrics().get(metric)
82 | if new_model_parameter > production_model_parameter:
83 | promote_new_model = False
84 | except Exception:
85 | promote_new_model = True
86 | print("This is the first model to be trained, thus nothing to evaluate for now")
87 |
88 | # TODO: Remove
89 | if promote_new_model:
90 | print("New model performs better, thus it will be registered")
91 | else:
92 | print("New model does not perform better.")
93 | print("Promote all models for now")
94 | promote_new_model = True
95 |
96 | # Registering new Model
97 | if promote_new_model:
98 | print("Registering new Model, because it performs better")
99 | tags = deployment_settings["model"]["tags"]
100 | tags["run_id"] = run.id
101 | model = run.register_model(model_name=deployment_settings["model"]["name"],
102 | model_path=deployment_settings["model"]["path"],
103 | tags=tags,
104 | properties=deployment_settings["model"]["properties"],
105 | model_framework=deployment_settings["model"]["model_framework"],
106 | model_framework_version=deployment_settings["model"]["model_framework_version"],
107 | description=deployment_settings["model"]["description"],
108 | datasets=deployment_settings["model"]["datasets"])
109 | else:
110 | raise Exception("No new model to register as production model perform better")
--------------------------------------------------------------------------------
/aml_service/ci_cd/30-ProfileModel.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 | import os, sys, json, azureml.core
27 | from azureml.core import Workspace, ContainerRegistry, Environment
28 | from azureml.core.model import Model, InferenceConfig
29 | from azureml.core.image import Image, ContainerImage
30 | from azureml.core.conda_dependencies import CondaDependencies
31 | from azureml.core.authentication import AzureCliAuthentication
32 | from helper import utils
33 |
34 | sys.path.insert(0, os.path.join("code", "testing"))
35 | import test_functions
36 |
37 | # Load the JSON settings file and relevant sections
38 | print("Loading settings")
39 | with open(os.path.join("aml_service", "settings.json")) as f:
40 | settings = json.load(f)
41 | deployment_settings = settings["deployment"]
42 | env_name = settings["experiment"]["name"] + "_deployment"
43 |
44 | # Get workspace
45 | print("Loading Workspace")
46 | cli_auth = AzureCliAuthentication()
47 | config_file_path = os.environ.get("GITHUB_WORKSPACE", default="aml_service")
48 | config_file_name = "aml_arm_config.json"
49 | ws = Workspace.from_config(
50 | path=config_file_path,
51 | auth=cli_auth,
52 | _file_name=config_file_name)
53 | print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\n')
54 |
55 | # Loading Model
56 | print("Loading Model")
57 | model = Model(workspace=ws, name=deployment_settings["model"]["name"])
58 |
59 | # Create image registry configuration
60 | if deployment_settings["image"]["docker"]["custom_image"]:
61 | container_registry = ContainerRegistry()
62 | container_registry.address = deployment_settings["image"]["docker"]["custom_image_registry_details"]["address"]
63 | container_registry.username = deployment_settings["image"]["docker"]["custom_image_registry_details"]["username"]
64 | container_registry.password = deployment_settings["image"]["docker"]["custom_image_registry_details"]["password"]
65 | else:
66 | container_registry = None
67 |
68 | # Creating dependencies
69 | print("Creating dependencies and registering environment")
70 | conda_dep = CondaDependencies.create(conda_packages=deployment_settings["image"]["dependencies"]["conda_packages"],
71 | pip_packages=deployment_settings["image"]["dependencies"]["pip_packages"],
72 | python_version=deployment_settings["image"]["dependencies"]["python_version"],
73 | pin_sdk_version=deployment_settings["image"]["dependencies"]["pin_sdk_version"])
74 | dep_path = os.path.join("code", "scoring", "myenv.yml")
75 | conda_dep.save(path=dep_path)
76 |
77 | # Creating InferenceConfig
78 | print("Creating InferenceConfig")
79 | if deployment_settings["image"]["use_custom_environment"]:
80 | env = utils.get_environment(name_suffix="_deployment")
81 | inferenceConfig = InferenceConfig(entry_script=deployment_settings["image"]["entry_script"],
82 | source_directory=deployment_settings["image"]["source_directory"],
83 | runtime=deployment_settings["image"]["runtime"],
84 | environment=env)
85 | else:
86 | inference_config = InferenceConfig(entry_script=deployment_settings["image"]["entry_script"],
87 | source_directory=deployment_settings["image"]["source_directory"],
88 | runtime=deployment_settings["image"]["runtime"],
89 | conda_file=os.path.basename(dep_path),
90 | extra_docker_file_steps=deployment_settings["image"]["docker"]["extra_docker_file_steps"],
91 | enable_gpu=deployment_settings["image"]["docker"]["use_gpu"],
92 | description=deployment_settings["image"]["description"],
93 | base_image=deployment_settings["image"]["docker"]["custom_image"],
94 | base_image_registry=container_registry,
95 | cuda_version=deployment_settings["image"]["docker"]["cuda_version"])
96 |
97 | # Registering Environment
98 | print("Registering Environment")
99 | if "env" not in locals():
100 | env = Environment.from_conda_specification(name=env_name, file_path=dep_path)
101 | registered_env = env.register(workspace=ws)
102 | print("Registered Environment")
103 | print(registered_env.name, "Version: " + registered_env.version, sep="\n")
104 |
105 | # Profile model
106 | print("Profiling Model")
107 | test_sample = test_functions.get_test_data_sample()
108 | profile = Model.profile(workspace=ws,
109 | profile_name=deployment_settings["image"]["name"],
110 | models=[model],
111 | inference_config=inference_config,
112 | input_data=test_sample)
113 | profile.wait_for_profiling(show_output=True)
114 | print(profile.get_results(), profile.recommended_cpu, profile.recommended_cpu_latency, profile.recommended_memory, profile.recommended_memory_latency, sep="\n")
115 |
116 | # Writing the profiling results to /aml_service/profiling_result.json
117 | profiling_result = {}
118 | profiling_result["cpu"] = profile.recommended_cpu
119 | profiling_result["memory"] = profile.recommended_memory
120 | profiling_result["image_id"] = profile.image_id
121 | with open(os.path.join("aml_service", "profiling_result.json"), "w") as outfile:
122 | json.dump(profiling_result, outfile)
--------------------------------------------------------------------------------
/aml_service/ci_cd/40-DevDeployment.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 | import os, sys, json
27 | from azureml.core import Workspace, Image
28 | from azureml.core.webservice import Webservice, AciWebservice
29 | from azureml.exceptions import WebserviceException
30 | from azureml.core.authentication import AzureCliAuthentication
31 |
32 | sys.path.insert(0, os.path.join("code", "testing"))
33 | import test_functions
34 |
35 | # Load the JSON settings file and relevant sections
36 | print("Loading settings")
37 | with open(os.path.join("aml_service", "settings.json")) as f:
38 | settings = json.load(f)
39 | deployment_settings = settings["deployment"]
40 | aci_settings = deployment_settings["dev_deployment"]
41 |
42 | # Loading Model Profile
43 | print("Loading Model Profile")
44 | with open(os.path.join("aml_service", "profiling_result.json")) as f:
45 | profiling_result = json.load(f)
46 |
47 | # Get workspace
48 | print("Loading Workspace")
49 | cli_auth = AzureCliAuthentication()
50 | config_file_path = os.environ.get("GITHUB_WORKSPACE", default="aml_service")
51 | config_file_name = "aml_arm_config.json"
52 | ws = Workspace.from_config(
53 | path=config_file_path,
54 | auth=cli_auth,
55 | _file_name=config_file_name)
56 | print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\n')
57 |
58 | # Loading Image
59 | image_details = profiling_result["image_id"].split(":")
60 | image = Image(workspace=ws,
61 | name=image_details[0],
62 | version=image_details[1])
63 |
64 | # Deploying model on ACI
65 | print("Deploying model on ACI")
66 | try:
67 | print("Trying to update existing ACI service")
68 | dev_service = AciWebservice(workspace=ws, name=aci_settings["name"])
69 | dev_service.update(image=image,
70 | tags=deployment_settings["image"]["tags"],
71 | properties=deployment_settings["image"]["properties"],
72 | description=deployment_settings["image"]["description"],
73 | auth_enabled=aci_settings["auth_enabled"],
74 | ssl_enabled=aci_settings["ssl_enabled"],
75 | ssl_cert_pem_file=aci_settings["ssl_cert_pem_file"],
76 | ssl_key_pem_file=aci_settings["ssl_key_pem_file"],
77 | ssl_cname=aci_settings["ssl_cname"],
78 | enable_app_insights=aci_settings["enable_app_insights"])
79 | print("Successfully updated existing ACI service")
80 | except WebserviceException:
81 | print("Failed to update ACI service... Creating new ACI instance")
82 | aci_config = AciWebservice.deploy_configuration(cpu_cores=profiling_result["cpu"],
83 | memory_gb=profiling_result["memory"],
84 | tags=deployment_settings["image"]["tags"],
85 | properties=deployment_settings["image"]["properties"],
86 | description=deployment_settings["image"]["description"],
87 | location=aci_settings["location"],
88 | auth_enabled=aci_settings["auth_enabled"],
89 | ssl_enabled=aci_settings["ssl_enabled"],
90 | ssl_cert_pem_file=aci_settings["ssl_cert_pem_file"],
91 | ssl_key_pem_file=aci_settings["ssl_key_pem_file"],
92 | ssl_cname=aci_settings["ssl_cname"],
93 | enable_app_insights=aci_settings["enable_app_insights"],
94 | dns_name_label=aci_settings["dns_name_label"])
95 |
96 | # Deploying dev web service from image
97 | dev_service = Webservice.deploy_from_image(workspace=ws,
98 | name=aci_settings["name"],
99 | image=image,
100 | deployment_config=aci_config)
101 |
102 | # Show output of the deployment on stdout
103 | dev_service.wait_for_deployment(show_output=True)
104 | print("State of Service: {}".format(dev_service.state))
105 |
106 | # Checking status of web service
107 | print("Checking status of ACI Dev Deployment")
108 | if dev_service.state != "Healthy":
109 | raise Exception(
110 | "Dev Deployment on ACI failed with the following status: {} and logs: \n{}".format(
111 | dev_service.state, dev_service.get_logs()
112 | )
113 | )
114 |
115 | # Testing ACI web service
116 | print("Testing ACI web service")
117 | test_sample = test_functions.get_test_data_sample()
118 | print("Test Sample: ", test_sample)
119 | test_sample_encoded = bytes(test_sample, encoding='utf8')
120 | try:
121 | prediction = dev_service.run(input_data=test_sample)
122 | print(prediction)
123 | except Exception as e:
124 | result = str(e)
125 | logs = dev_service.get_logs()
126 | dev_service.delete()
127 | raise Exception("ACI Dev web service is not working as expected: \n{} \nLogs: \n{}".format(result, logs))
128 |
129 | # Delete aci after test
130 | print("Deleting ACI Dev web service after successful test")
131 | dev_service.delete()
--------------------------------------------------------------------------------
/aml_service/ci_cd/50-TestDeployment.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 | import os, sys, json
27 | from azureml.core import Workspace, Image
28 | from azureml.core.webservice import Webservice, AksWebservice
29 | from azureml.exceptions import WebserviceException
30 | from azureml.core.authentication import AzureCliAuthentication
31 | from azureml.core.compute import AksCompute, ComputeTarget
32 | from azureml.exceptions import ComputeTargetException
33 |
34 | sys.path.insert(0, os.path.join("code", "testing"))
35 | import test_functions
36 |
37 | # Load the JSON settings file and relevant sections
38 | print("Loading settings")
39 | with open(os.path.join("aml_service", "settings.json")) as f:
40 | settings = json.load(f)
41 | deployment_settings = settings["deployment"]
42 | aks_service_settings = deployment_settings["test_deployment"]
43 | aks_compute_settings = settings["compute_target"]["deployment"]["aks_test"]
44 |
45 | # Loading Model Profile
46 | print("Loading Model Profile")
47 | with open(os.path.join("aml_service", "profiling_result.json")) as f:
48 | profiling_result = json.load(f)
49 |
50 | # Get workspace
51 | print("Loading Workspace")
52 | cli_auth = AzureCliAuthentication()
53 | config_file_path = os.environ.get("GITHUB_WORKSPACE", default="aml_service")
54 | config_file_name = "aml_arm_config.json"
55 | ws = Workspace.from_config(
56 | path=config_file_path,
57 | auth=cli_auth,
58 | _file_name=config_file_name)
59 | print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\n')
60 |
61 | # Loading Image
62 | image_details = profiling_result["image_id"].split(":")
63 | image = Image(workspace=ws,
64 | name=image_details[0],
65 | version=image_details[1])
66 |
67 | try:
68 | # Loading existing Test AKS Cluster
69 | print("Loading existing Test AKS Cluster")
70 | aks_test_cluster = AksCompute(workspace=ws, name=aks_compute_settings["name"])
71 |
72 | # Check settings and redeploy if required settings have changed
73 | print("Found existing cluster")
74 | #aks_test_cluster.update()
75 | #print("Successfully updated Cluster definition")
76 | except ComputeTargetException:
77 | print("Loading failed ... Creating new Dev AKS Cluster")
78 | compute_config = AksCompute.provisioning_configuration(agent_count=aks_compute_settings["agent_count"],
79 | vm_size=aks_compute_settings["vm_size"],
80 | ssl_cname=aks_compute_settings["ssl_cname"],
81 | ssl_cert_pem_file=aks_compute_settings["ssl_cert_pem_file"],
82 | ssl_key_pem_file=aks_compute_settings["ssl_key_pem_file"],
83 | location=aks_compute_settings["location"],
84 | service_cidr=aks_compute_settings["service_cidr"],
85 | dns_service_ip=aks_compute_settings["dns_service_ip"],
86 | docker_bridge_cidr=aks_compute_settings["docker_bridge_cidr"],
87 | cluster_purpose=AksCompute.ClusterPurpose.DEV_TEST)
88 | # Deploy to VNET if provided
89 | if aks_compute_settings["vnet_resourcegroup_name"] and aks_compute_settings["vnet_name"] and aks_compute_settings["subnet_name"]:
90 | compute_config.vnet_resourcegroup_name = aks_compute_settings["vnet_resourcegroup_name"]
91 | compute_config.vnet_name = aks_compute_settings["vnet_name"]
92 | compute_config.subnet_name = aks_compute_settings["subnet_name"]
93 |
94 | # Create Compute Target
95 | aks_test_cluster = ComputeTarget.create(workspace=ws, name=aks_compute_settings["name"], provisioning_configuration=compute_config)
96 |
97 | # Wait until the cluster is attached
98 | aks_test_cluster.wait_for_completion(show_output=True)
99 |
100 | # Checking status of Test AKS Cluster
101 | print("Checking status of Test AKS Cluster")
102 | if aks_test_cluster.provisioning_state == "Failed":
103 | aks_test_cluster.delete()
104 | raise Exception(
105 | "Deployment of Test AKS Cluster failed with the following status: {} and logs: \n {}".format(
106 | aks_test_cluster.provisioning_state, aks_test_cluster.provisioning_errors
107 | )
108 | )
109 |
110 | # Deploying model on test AKS
111 | print("Deploying model on Test AKS")
112 | try:
113 | print("Trying to update existing AKS test service")
114 | test_service = AksWebservice(workspace=ws, name=aks_service_settings["name"])
115 | test_service.update(image=image,
116 | autoscale_enabled=aks_service_settings["autoscale_enabled"],
117 | autoscale_min_replicas=aks_service_settings["autoscale_min_replicas"],
118 | autoscale_max_replicas=aks_service_settings["autoscale_max_replicas"],
119 | autoscale_refresh_seconds=aks_service_settings["autoscale_refresh_seconds"],
120 | autoscale_target_utilization=aks_service_settings["autoscale_target_utilization"],
121 | collect_model_data=aks_service_settings["collect_model_data"],
122 | auth_enabled=aks_service_settings["auth_enabled"],
123 | cpu_cores=profiling_result["cpu"],
124 | memory_gb=profiling_result["memory"],
125 | enable_app_insights=aks_service_settings["enable_app_insights"],
126 | scoring_timeout_ms=aks_service_settings["scoring_timeout_ms"],
127 | replica_max_concurrent_requests=aks_service_settings["replica_max_concurrent_requests"],
128 | max_request_wait_time=aks_service_settings["max_request_wait_time"],
129 | num_replicas=aks_service_settings["num_replicas"],
130 | tags=deployment_settings["image"]["tags"],
131 | properties=deployment_settings["image"]["properties"],
132 | description=deployment_settings["image"]["description"],
133 | gpu_cores=aks_service_settings["gpu_cores"],
134 | period_seconds=aks_service_settings["period_seconds"],
135 | initial_delay_seconds=aks_service_settings["initial_delay_seconds"],
136 | timeout_seconds=aks_service_settings["timeout_seconds"],
137 | success_threshold=aks_service_settings["success_threshold"],
138 | failure_threshold=aks_service_settings["failure_threshold"],
139 | namespace=aks_service_settings["namespace"],
140 | token_auth_enabled=aks_service_settings["token_auth_enabled"])
141 | print("Successfully updated existing AKS test service")
142 | except WebserviceException:
143 | print("Failed to update AKS test service... Creating new AKS test service")
144 | aks_config = AksWebservice.deploy_configuration(autoscale_enabled=aks_service_settings["autoscale_enabled"],
145 | autoscale_min_replicas=aks_service_settings["autoscale_min_replicas"],
146 | autoscale_max_replicas=aks_service_settings["autoscale_max_replicas"],
147 | autoscale_refresh_seconds=aks_service_settings["autoscale_refresh_seconds"],
148 | autoscale_target_utilization=aks_service_settings["autoscale_target_utilization"],
149 | collect_model_data=aks_service_settings["collect_model_data"],
150 | auth_enabled=aks_service_settings["auth_enabled"],
151 | cpu_cores=profiling_result["cpu"],
152 | memory_gb=profiling_result["memory"],
153 | enable_app_insights=aks_service_settings["enable_app_insights"],
154 | scoring_timeout_ms=aks_service_settings["scoring_timeout_ms"],
155 | replica_max_concurrent_requests=aks_service_settings["replica_max_concurrent_requests"],
156 | max_request_wait_time=aks_service_settings["max_request_wait_time"],
157 | num_replicas=aks_service_settings["num_replicas"],
158 | primary_key=aks_service_settings["primary_key"],
159 | secondary_key=aks_service_settings["secondary_key"],
160 | tags=deployment_settings["image"]["tags"],
161 | properties=deployment_settings["image"]["properties"],
162 | description=deployment_settings["image"]["description"],
163 | gpu_cores=aks_service_settings["gpu_cores"],
164 | period_seconds=aks_service_settings["period_seconds"],
165 | initial_delay_seconds=aks_service_settings["initial_delay_seconds"],
166 | timeout_seconds=aks_service_settings["timeout_seconds"],
167 | success_threshold=aks_service_settings["success_threshold"],
168 | failure_threshold=aks_service_settings["failure_threshold"],
169 | namespace=aks_service_settings["namespace"],
170 | token_auth_enabled=aks_service_settings["token_auth_enabled"])
171 |
172 | # Deploying test web service from image
173 | test_service = Webservice.deploy_from_image(workspace=ws,
174 | name=aks_service_settings["name"],
175 | image=image,
176 | deployment_config=aks_config,
177 | deployment_target=aks_test_cluster)
178 | # Show output of the deployment on stdout
179 | test_service.wait_for_deployment(show_output=True)
180 | print(test_service.state)
181 |
182 | # Checking status of test web service
183 | print("Checking status of AKS Test Deployment")
184 | if test_service.state != "Healthy":
185 | raise Exception(
186 | "Test Deployment on AKS failed with the following status: {} and logs: \n{}".format(
187 | test_service.state, test_service.get_logs()
188 | )
189 | )
190 |
191 | # Testing AKS web service
192 | print("Testing AKS test web service")
193 | test_sample = test_functions.get_test_data_sample()
194 | print("Test Sample: ", test_sample)
195 | test_sample_encoded = bytes(test_sample, encoding='utf8')
196 | try:
197 | prediction = test_service.run(input_data=test_sample)
198 | print(prediction)
199 | except Exception as e:
200 | result = str(e)
201 | logs = test_service.get_logs()
202 | test_service.delete()
203 | raise Exception("AKS Test web service is not working as expected: \n{} \nLogs: \n{}".format(result, logs))
204 |
205 | # Delete test AKS service after test
206 | print("Deleting AKS Test web service after successful test")
207 | test_service.delete()
--------------------------------------------------------------------------------
/aml_service/ci_cd/60-ProdDeployment.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 | import os, sys, json
27 | from azureml.core import Workspace, Image
28 | from azureml.core.webservice import Webservice, AksWebservice
29 | from azureml.exceptions import WebserviceException
30 | from azureml.core.authentication import AzureCliAuthentication
31 | from azureml.core.compute import AksCompute, ComputeTarget
32 | from azureml.exceptions import ComputeTargetException
33 |
34 | sys.path.insert(0, os.path.join("code", "testing"))
35 | import test_functions
36 |
37 | # Load the JSON settings file and relevant sections
38 | print("Loading settings")
39 | with open(os.path.join("aml_service", "settings.json")) as f:
40 | settings = json.load(f)
41 | deployment_settings = settings["deployment"]
42 | aks_service_settings = deployment_settings["prod_deployment"]
43 | aks_compute_settings = settings["compute_target"]["deployment"]["aks_prod"]
44 |
45 | # Loading Model Profile
46 | print("Loading Model Profile")
47 | with open(os.path.join("aml_service", "profiling_result.json")) as f:
48 | profiling_result = json.load(f)
49 |
50 | # Get workspace
51 | print("Loading Workspace")
52 | cli_auth = AzureCliAuthentication()
53 | config_file_path = os.environ.get("GITHUB_WORKSPACE", default="aml_service")
54 | config_file_name = "aml_arm_config.json"
55 | ws = Workspace.from_config(
56 | path=config_file_path,
57 | auth=cli_auth,
58 | _file_name=config_file_name)
59 | print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\n')
60 |
61 | # Loading Image
62 | image_details = profiling_result["image_id"].split(":")
63 | image = Image(workspace=ws,
64 | name=image_details[0],
65 | version=image_details[1])
66 |
67 | try:
68 | # Loading existing Prod AKS Cluster
69 | print("Loading existing Prod AKS Cluster")
70 | aks_prod_cluster = AksCompute(workspace=ws, name=aks_compute_settings["name"])
71 |
72 | # Check settings and redeploy if required settings have changed
73 | print("Found existing cluster")
74 | #aks_prod_cluster.update()
75 | #print("Successfully updated Cluster definition")
76 | except ComputeTargetException:
77 | print("Loading failed ... Creating new Prod AKS Cluster")
78 | compute_config = AksCompute.provisioning_configuration(agent_count=aks_compute_settings["agent_count"],
79 | vm_size=aks_compute_settings["vm_size"],
80 | ssl_cname=aks_compute_settings["ssl_cname"],
81 | ssl_cert_pem_file=aks_compute_settings["ssl_cert_pem_file"],
82 | ssl_key_pem_file=aks_compute_settings["ssl_key_pem_file"],
83 | location=aks_compute_settings["location"],
84 | service_cidr=aks_compute_settings["service_cidr"],
85 | dns_service_ip=aks_compute_settings["dns_service_ip"],
86 | docker_bridge_cidr=aks_compute_settings["docker_bridge_cidr"],
87 | cluster_purpose=AksCompute.ClusterPurpose.FAST_PROD)
88 | # Deploy to VNET if provided
89 | if aks_compute_settings["vnet_resourcegroup_name"] and aks_compute_settings["vnet_name"] and aks_compute_settings["subnet_name"]:
90 | compute_config.vnet_resourcegroup_name = aks_compute_settings["vnet_resourcegroup_name"]
91 | compute_config.vnet_name = aks_compute_settings["vnet_name"]
92 | compute_config.subnet_name = aks_compute_settings["subnet_name"]
93 |
94 | # Create Compute Target
95 | aks_prod_cluster = ComputeTarget.create(workspace=ws, name=aks_compute_settings["name"], provisioning_configuration=compute_config)
96 |
97 | # Wait until the cluster is attached
98 | aks_prod_cluster.wait_for_completion(show_output=True)
99 |
100 | # Checking status of Test AKS Cluster
101 | print("Checking status of Test AKS Cluster")
102 | if aks_prod_cluster.provisioning_state == "Failed":
103 | aks_prod_cluster.delete()
104 | raise Exception(
105 | "Deployment of Test AKS Cluster failed with the following status: {} and logs: \n {}".format(
106 | aks_prod_cluster.provisioning_state, aks_prod_cluster.provisioning_errors
107 | )
108 | )
109 |
110 | # Deploying model on prod AKS
111 | print("Deploying model on Prod AKS")
112 | try:
113 | print("Trying to update existing Prod web service")
114 | prod_service = AksWebservice(workspace=ws, name=aks_service_settings["name"])
115 | prod_service.update(image=image,
116 | autoscale_enabled=aks_service_settings["autoscale_enabled"],
117 | autoscale_min_replicas=aks_service_settings["autoscale_min_replicas"],
118 | autoscale_max_replicas=aks_service_settings["autoscale_max_replicas"],
119 | autoscale_refresh_seconds=aks_service_settings["autoscale_refresh_seconds"],
120 | autoscale_target_utilization=aks_service_settings["autoscale_target_utilization"],
121 | collect_model_data=aks_service_settings["collect_model_data"],
122 | auth_enabled=aks_service_settings["auth_enabled"],
123 | cpu_cores=profiling_result["cpu"],
124 | memory_gb=profiling_result["memory"],
125 | enable_app_insights=aks_service_settings["enable_app_insights"],
126 | scoring_timeout_ms=aks_service_settings["scoring_timeout_ms"],
127 | replica_max_concurrent_requests=aks_service_settings["replica_max_concurrent_requests"],
128 | max_request_wait_time=aks_service_settings["max_request_wait_time"],
129 | num_replicas=aks_service_settings["num_replicas"],
130 | tags=deployment_settings["image"]["tags"],
131 | properties=deployment_settings["image"]["properties"],
132 | description=deployment_settings["image"]["description"],
133 | gpu_cores=aks_service_settings["gpu_cores"],
134 | period_seconds=aks_service_settings["period_seconds"],
135 | initial_delay_seconds=aks_service_settings["initial_delay_seconds"],
136 | timeout_seconds=aks_service_settings["timeout_seconds"],
137 | success_threshold=aks_service_settings["success_threshold"],
138 | failure_threshold=aks_service_settings["failure_threshold"],
139 | namespace=aks_service_settings["namespace"],
140 | token_auth_enabled=aks_service_settings["token_auth_enabled"])
141 | print("Successfully updated existing AKS Prod service")
142 | except WebserviceException:
143 | print("Failed to update AKS test service... Creating new AKS Prod service")
144 | aks_config = AksWebservice.deploy_configuration(autoscale_enabled=aks_service_settings["autoscale_enabled"],
145 | autoscale_min_replicas=aks_service_settings["autoscale_min_replicas"],
146 | autoscale_max_replicas=aks_service_settings["autoscale_max_replicas"],
147 | autoscale_refresh_seconds=aks_service_settings["autoscale_refresh_seconds"],
148 | autoscale_target_utilization=aks_service_settings["autoscale_target_utilization"],
149 | collect_model_data=aks_service_settings["collect_model_data"],
150 | auth_enabled=aks_service_settings["auth_enabled"],
151 | cpu_cores=profiling_result["cpu"],
152 | memory_gb=profiling_result["memory"],
153 | enable_app_insights=aks_service_settings["enable_app_insights"],
154 | scoring_timeout_ms=aks_service_settings["scoring_timeout_ms"],
155 | replica_max_concurrent_requests=aks_service_settings["replica_max_concurrent_requests"],
156 | max_request_wait_time=aks_service_settings["max_request_wait_time"],
157 | num_replicas=aks_service_settings["num_replicas"],
158 | primary_key=aks_service_settings["primary_key"],
159 | secondary_key=aks_service_settings["secondary_key"],
160 | tags=deployment_settings["image"]["tags"],
161 | properties=deployment_settings["image"]["properties"],
162 | description=deployment_settings["image"]["description"],
163 | gpu_cores=aks_service_settings["gpu_cores"],
164 | period_seconds=aks_service_settings["period_seconds"],
165 | initial_delay_seconds=aks_service_settings["initial_delay_seconds"],
166 | timeout_seconds=aks_service_settings["timeout_seconds"],
167 | success_threshold=aks_service_settings["success_threshold"],
168 | failure_threshold=aks_service_settings["failure_threshold"],
169 | namespace=aks_service_settings["namespace"],
170 | token_auth_enabled=aks_service_settings["token_auth_enabled"])
171 |
172 | # Deploying prod web service from image
173 | prod_service = Webservice.deploy_from_image(workspace=ws,
174 | name=aks_service_settings["name"],
175 | image=image,
176 | deployment_config=aks_config,
177 | deployment_target=aks_prod_cluster)
178 | # Show output of the deployment on stdout
179 | prod_service.wait_for_deployment(show_output=True)
180 | print(prod_service.state)
181 |
182 | # Checking status of prod web service
183 | print("Checking status of AKS Prod Deployment")
184 | if prod_service.state != "Healthy":
185 | raise Exception(
186 | "Prod Deployment on AKS failed with the following status: {} and logs: \n{}".format(
187 | prod_service.state, prod_service.get_logs()
188 | )
189 | )
190 |
191 | # Testing AKS web service
192 | print("Testing AKS prod web service")
193 | test_sample = test_functions.get_test_data_sample()
194 | print("Test Sample: ", test_sample)
195 | test_sample_encoded = bytes(test_sample, encoding='utf8')
196 | try:
197 | prediction = prod_service.run(input_data=test_sample)
198 | print(prediction)
199 | except Exception as e:
200 | result = str(e)
201 | logs = prod_service.get_logs()
202 | raise Exception("AKS Prod web service is not working as expected: \n{} \nLogs: \n{}".format(result, logs))
--------------------------------------------------------------------------------
/aml_service/ci_cd/helper/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marvinbuss/MLDevOps/43a4f9b7ab86b0540c206158d35f7bbf910aa6ed/aml_service/ci_cd/helper/__init__.py
--------------------------------------------------------------------------------
/aml_service/ci_cd/helper/utils.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 | import os, json, azureml.core
27 | from azureml.core import Environment
28 | from azureml.core.environment import CondaDependencies
29 | from azureml.train.hyperdrive import BanditPolicy, MedianStoppingPolicy, NoTerminationPolicy, TruncationSelectionPolicy
30 | from azureml.train.hyperdrive import RandomParameterSampling, GridParameterSampling, BayesianParameterSampling
31 | from azureml.train.hyperdrive import choice, randint, uniform, quniform, loguniform, qloguniform, normal, qnormal, lognormal, qlognormal
32 | from azureml.exceptions import RunConfigurationException
33 |
34 |
35 | def get_environment(name_suffix="_training"):
36 | # Load the JSON settings file
37 | print("Loading settings")
38 | with open(os.path.join("aml_config", "settings.json")) as f:
39 | settings = json.load(f)
40 | env_settings = settings["environment"]
41 | env_name = settings["experiment"]["name"] + name_suffix
42 |
43 | # Create Dependencies
44 | print("Defining Conda Dependencies")
45 | conda_dep = CondaDependencies().create(
46 | pip_indexurl=None,
47 | pip_packages=env_settings["pip_packages"],
48 | conda_packages=env_settings["conda_packages"],
49 | python_version=env_settings["python_version"],
50 | pin_sdk_version=env_settings["pin_sdk_version"]
51 | )
52 | conda_dep.save(path=env_settings["dependencies_config"]["path"])
53 |
54 | # Create Environment and setting parameters
55 | print("Creating Environment")
56 | env = Environment(name=env_name)
57 | env.python.conda_dependencies = conda_dep
58 | env.environment_variables = env_settings["env_variables"]
59 |
60 | if env_settings["user_managed_dependencies"]:
61 | print("Using existing user-managed Python environment for run")
62 | env.user_managed_dependencies = env_settings["user_managed_dependencies"]
63 | elif env_settings["docker"]["enabled"]:
64 | print("Using Docker run with system-built conda environment based on dependency specification")
65 | env.docker.enabled = env_settings["docker"]["enabled"]
66 | env.docker.gpu_support = env_settings["docker"]["gpu_support"]
67 | env.docker.arguments = env_settings["docker"]["arguments"]
68 | env.docker.shared_volumes = env_settings["docker"]["shared_volumes"]
69 | env.docker.shm_size = env_settings["docker"]["shm_size"]
70 |
71 | if env_settings["docker"]["gpu_support"] and env_settings["docker"]["mpi_image"]:
72 | env.docker.base_image = azureml.core.runconfig.MPI_GPU_IMAGE
73 | elif env_settings["docker"]["gpu_support"]:
74 | env.docker.base_image = azureml.core.runconfig.DEFAULT_GPU_IMAGE
75 | elif env_settings["docker"]["mpi_image"]:
76 | env.docker.base_image = azureml.core.runconfig.MPI_CPU_IMAGE
77 |
78 | env.docker.base_image = env_settings["docker"]["base_image"]
79 | env.docker.base_image_registry.address = env_settings["docker"]["base_image_registry"]["address"]
80 | env.docker.base_image_registry.username = env_settings["docker"]["base_image_registry"]["username"]
81 | env.docker.base_image_registry.password = env_settings["docker"]["base_image_registry"]["password"]
82 | else:
83 | print("Using system-build conda environment based on dependency specification")
84 | env.docker.enabled = False
85 | return env
86 |
87 |
88 | def get_parameter_sampling(sampling_method, parameter_settings):
89 | parameter_dict = {}
90 | for parameter_name, parameter_setting in parameter_settings.items():
91 | parameter_distr = get_parameter_distribution(parameter_name, parameter_setting)
92 | parameter_dict["--{}".format(parameter_name)] = parameter_distr
93 |
94 | if "random" in sampling_method:
95 | ps = RandomParameterSampling(parameter_dict)
96 | elif "grid" in sampling_method:
97 | ps = GridParameterSampling(parameter_dict)
98 | elif "bayesian" in sampling_method:
99 | ps = BayesianParameterSampling(parameter_dict)
100 | else:
101 | ps = None
102 | raise RunConfigurationException("Parameter Sampling Method not defined in settings. Please choose between \'random\', \'grid\' and \'bayesian\'")
103 | return ps
104 |
105 |
106 | def get_parameter_distribution(parameter_name, parameter_setting):
107 | if "choice" in parameter_setting["distribution"]:
108 | parameter_distr = choice(parameter_setting["parameters"]["options"])
109 | elif "randint" in parameter_setting["distribution"]:
110 | parameter_distr = randint(upper=parameter_setting["parameters"]["upper"])
111 | elif "uniform" in parameter_setting["distribution"]:
112 | parameter_distr = uniform(min_value=parameter_setting["parameters"]["min_value"], max_value=parameter_setting["parameters"]["max_value"])
113 | elif "quniform" in parameter_setting["distribution"]:
114 | parameter_distr = quniform(min_value=parameter_setting["parameters"]["min_value"], max_value=parameter_setting["parameters"]["max_value"], q=parameter_setting["parameters"]["q"])
115 | elif "loguniform" in parameter_setting["distribution"]:
116 | parameter_distr = loguniform(min_value=parameter_setting["parameters"]["min_value"], max_value=parameter_setting["parameters"]["max_value"])
117 | elif "qloguniform" in parameter_setting["distribution"]:
118 | parameter_distr = qloguniform(min_value=parameter_setting["parameters"]["min_value"], max_value=parameter_setting["parameters"]["max_value"], q=parameter_setting["parameters"]["q"])
119 | elif "normal" in parameter_setting["distribution"]:
120 | parameter_distr = normal(mu=parameter_setting["parameters"]["mu"], sigma=parameter_setting["parameters"]["sigma"])
121 | elif "qnormal" in parameter_setting["distribution"]:
122 | parameter_distr = qnormal(mu=parameter_setting["parameters"]["mu"], sigma=parameter_setting["parameters"]["sigma"], q=parameter_setting["parameters"]["q"])
123 | elif "lognormal" in parameter_setting["distribution"]:
124 | parameter_distr = lognormal(mu=parameter_setting["parameters"]["mu"], sigma=parameter_setting["parameters"]["sigma"])
125 | elif "qlognormal" in parameter_setting["distribution"]:
126 | parameter_distr = qlognormal(mu=parameter_setting["parameters"]["mu"], sigma=parameter_setting["parameters"]["sigma"], q=parameter_setting["parameters"]["q"])
127 | else:
128 | parameter_distr = None
129 | raise RunConfigurationException("Parameter distribution for parameter {} not defined in settings. Please choose between \'choice\', \'randint\', \'uniform\', \'quniform\', \'loguniform\', \'qloguniform\', \'normal\', \'qnormal\', \'lognormal\' and \'qlognormal\'".format(parameter_name))
130 | return parameter_distr
131 |
132 | def get_policy(policy_settings):
133 | if "bandit" in policy_settings["name"]:
134 | policy = BanditPolicy(evaluation_interval=policy_settings["evaluation_interval"],
135 | delay_evaluation=policy_settings["delay_evaluation"],
136 | slack_factor=policy_settings["bandit"]["slack_factor"],
137 | slack_amount=policy_settings["bandit"]["slack_amount"])
138 | elif "medianstopping" in policy_settings["name"]:
139 | policy = MedianStoppingPolicy(evaluation_interval=policy_settings["evaluation_interval"],
140 | delay_evaluation=policy_settings["delay_evaluation"])
141 | elif "noterminal" in policy_settings["name"]:
142 | policy = NoTerminationPolicy()
143 | elif "truncationselection" in policy_settings["name"]:
144 | policy = TruncationSelectionPolicy(evaluation_interval=policy_settings["evaluation_interval"],
145 | delay_evaluation=policy_settings["delay_evaluation"],
146 | truncation_percentage=policy_settings["truncationselection"]["truncation_percentage"])
147 | else:
148 | policy = None
149 | return policy
--------------------------------------------------------------------------------
/aml_service/ci_cd/requirements.txt:
--------------------------------------------------------------------------------
1 | azure-cli==2.1.0
2 | azureml-sdk==1.0.69
3 |
--------------------------------------------------------------------------------
/aml_service/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "experiment":{
3 | "name": "github-actions-ai-demo",
4 | "source_directory": "./code/training",
5 | "entry_script": "train.py",
6 | "script_parameters": {},
7 | "user_managed": false,
8 | "environment_variables": {},
9 | "source_directory_datastore": null,
10 | "dependencies": {
11 | "conda_packages": [],
12 | "pip_packages": [],
13 | "conda_dependencies_file": null,
14 | "pip_requirements_file": null
15 | },
16 | "framework": {
17 | "name": "sklearn",
18 | "chainer": {
19 | "framework_version": "5.1.0",
20 | "_enable_optimized_mode": false
21 | },
22 | "pytorch": {
23 | "framework_version": "1.1",
24 | "_enable_optimized_mode": false
25 | },
26 | "sklearn": {
27 | "framework_version": "0.20.3",
28 | "_enable_optimized_mode": false
29 | },
30 | "tensorflow": {
31 | "framework_version": "1.13",
32 | "_enable_optimized_mode": false
33 | }
34 | },
35 | "distributed_training":{
36 | "backend_config": null,
37 | "node_count": 1,
38 | "mpi": {
39 | "process_count_per_node": 1
40 | },
41 | "parameter_server": {
42 | "worker_count": 1,
43 | "parameter_server_count": "1"
44 | }
45 | },
46 | "docker": {
47 | "use_docker": true,
48 | "shm_size": "1g",
49 | "custom_image": null,
50 | "custom_image_registry_details": {
51 | "address": null,
52 | "username": null,
53 | "password": null
54 | }
55 | },
56 | "hyperparameter_sampling": {
57 | "use_hyperparameter_sampling": false,
58 | "method": null,
59 | "parameters": {
60 | "value_name": {
61 | "distribution": "quniform",
62 | "parameters": {
63 | "min_value": 1.0,
64 | "max_value": 2.0,
65 | "q": 2
66 | }
67 | },
68 | "value_name2": {
69 | "distribution": "uniform",
70 | "parameters": {
71 | "min_value": 1.0,
72 | "max_value": 2.0
73 | }
74 | }
75 | },
76 | "policy": {
77 | "name": "bandit",
78 | "evaluation_interval": 1,
79 | "delay_evaluation": 0,
80 | "bandit": {
81 | "slack_factor": 0.15,
82 | "slack_amount": null
83 | },
84 | "truncationselection": {
85 | "truncation_percentage": 5
86 | }
87 | },
88 | "primary_metric_name": "",
89 | "primary_metric_goal": "max",
90 | "max_total_runs": 8,
91 | "max_concurrent_runs": 1,
92 | "max_duration_minutes": 10080
93 | },
94 | "resume_state": {
95 | "resume_from_state": false,
96 | "data_reference_name": null,
97 | "datapath_compute_binding": null
98 | },
99 | "history": {
100 | "output_collection": true,
101 | "snapshotProject": true,
102 | "directoriesToWatch": ["logs"]
103 | },
104 | "run_tags": {
105 | "submitted": "GitHub Actions"
106 | },
107 | "data_references": {},
108 | "max_run_duration_seconds": null,
109 | "use_custom_environment": false
110 | },
111 | "compute_target": {
112 | "compute_target_to_use_for_training": "amlcompute",
113 | "training": {
114 | "amlcompute":{
115 | "name": "my-aml-cluster",
116 | "vm_size": "STANDARD_D2_V2",
117 | "vm_priority": "dedicated",
118 | "min_nodes": 0,
119 | "max_nodes": 4,
120 | "idle_seconds_before_scaledown": "300",
121 | "vnet_resource_group_name": null,
122 | "vnet_name": null,
123 | "subnet_name": null,
124 | "admin_username": null,
125 | "admin_user_password": null,
126 | "admin_user_ssh_key": null,
127 | "tags": {
128 | "Creator": "GitHub Actions"
129 | },
130 | "description": "AMLCompute for GitHub Actions"
131 | },
132 | "dsvm":{
133 | "name": "my-vm",
134 | "vm_size": "Standard_D2_v2",
135 | "location": null,
136 | "ssh_port": null
137 | },
138 | "remotecompute":{
139 | "name": "my-remote-vm",
140 | "use_ssh_auth": false,
141 | "address": "",
142 | "username": "",
143 | "password": null,
144 | "ssh_port": 22,
145 | "private_key_file": null,
146 | "private_key_passphrase": null
147 | }
148 | },
149 | "deployment": {
150 | "aci_dev": {},
151 | "aks_test": {
152 | "name": "testAKS",
153 | "agent_count": 1,
154 | "vm_size": "Standard_D3_v2",
155 | "ssl_cname": null,
156 | "ssl_cert_pem_file": null,
157 | "ssl_key_pem_file": null,
158 | "location": null,
159 | "vnet_resourcegroup_name": null,
160 | "vnet_name": null,
161 | "subnet_name": null,
162 | "service_cidr": null,
163 | "dns_service_ip": null,
164 | "docker_bridge_cidr": null
165 | },
166 | "aks_prod": {
167 | "name": "prodAKS",
168 | "agent_count": 3,
169 | "vm_size": "Standard_D3_v2",
170 | "ssl_cname": null,
171 | "ssl_cert_pem_file": null,
172 | "ssl_key_pem_file": null,
173 | "location": null,
174 | "vnet_resourcegroup_name": null,
175 | "vnet_name": null,
176 | "subnet_name": null,
177 | "service_cidr": null,
178 | "dns_service_ip": null,
179 | "docker_bridge_cidr": null
180 | }
181 | }
182 | },
183 | "deployment": {
184 | "model": {
185 | "name": "mymodel",
186 | "path": "outputs/mymodel.pkl",
187 | "evaluation_parameters": {
188 | "larger_is_better": [],
189 | "smaller_is_better": ["mse"]
190 | },
191 | "tags":{
192 | "Creator": "GitHub Actions"
193 | },
194 | "properties": {
195 | "Creator": "GitHub Actions"
196 | },
197 | "description": "Model registered by GitHub Actions",
198 | "model_framework": null,
199 | "model_framework_version": null,
200 | "datasets": null
201 | },
202 | "image": {
203 | "name": "myimage",
204 | "entry_script": "score.py",
205 | "source_directory": "code/scoring/",
206 | "runtime": "python",
207 | "dependencies": {
208 | "conda_packages": ["numpy","scikit-learn"],
209 | "pip_packages": ["azureml-defaults", "azureml-monitoring"],
210 | "python_version": "3.6.2",
211 | "pin_sdk_version": true
212 | },
213 | "docker": {
214 | "use_gpu": false,
215 | "cuda_version": null,
216 | "custom_image": null,
217 | "custom_image_registry_details": {
218 | "address": null,
219 | "username": null,
220 | "password": null
221 | },
222 | "extra_docker_file_steps": null
223 | },
224 | "tags":{
225 | "Creator":"GitHub Actions"
226 | },
227 | "properties":{
228 | "Creator":"GitHub Actions"
229 | },
230 | "description": "Image registered by GitHub Actions",
231 | "use_custom_environment": false
232 | },
233 | "dev_deployment": {
234 | "name": "dev-aci",
235 | "auth_enabled": false,
236 | "ssl_enabled": false,
237 | "ssl_cert_pem_file": null,
238 | "ssl_key_pem_file": null,
239 | "ssl_cname": null,
240 | "enable_app_insights": true,
241 | "location": null,
242 | "dns_name_label": null
243 | },
244 | "test_deployment": {
245 | "name": "test-aks",
246 | "autoscale_enabled": true,
247 | "autoscale_min_replicas": 1,
248 | "autoscale_max_replicas": 10,
249 | "autoscale_refresh_seconds": 1,
250 | "autoscale_target_utilization": 70,
251 | "collect_model_data": true,
252 | "auth_enabled": true,
253 | "enable_app_insights": true,
254 | "scoring_timeout_ms": null,
255 | "replica_max_concurrent_requests": null,
256 | "max_request_wait_time": null,
257 | "num_replicas": null,
258 | "gpu_cores": null,
259 | "period_seconds": 10,
260 | "initial_delay_seconds": null,
261 | "timeout_seconds": 1,
262 | "success_threshold": 1,
263 | "failure_threshold": 3,
264 | "namespace": null,
265 | "token_auth_enabled": false,
266 | "primary_key": null,
267 | "secondary_key": null
268 | },
269 | "prod_deployment": {
270 | "name": "prod-aks",
271 | "autoscale_enabled": true,
272 | "autoscale_min_replicas": 1,
273 | "autoscale_max_replicas": 10,
274 | "autoscale_refresh_seconds": 1,
275 | "autoscale_target_utilization": 70,
276 | "collect_model_data": true,
277 | "auth_enabled": true,
278 | "enable_app_insights": true,
279 | "scoring_timeout_ms": null,
280 | "replica_max_concurrent_requests": null,
281 | "max_request_wait_time": null,
282 | "num_replicas": null,
283 | "gpu_cores": null,
284 | "period_seconds": 10,
285 | "initial_delay_seconds": null,
286 | "timeout_seconds": 1,
287 | "success_threshold": 1,
288 | "failure_threshold": 3,
289 | "namespace": null,
290 | "token_auth_enabled": false,
291 | "primary_key": null,
292 | "secondary_key": null
293 | }
294 | }
295 | }
--------------------------------------------------------------------------------
/code/scoring/score.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 | import pickle, json, time
27 | import numpy as np
28 | from sklearn.externals import joblib
29 | from sklearn.linear_model import Ridge
30 | from azureml.core.model import Model
31 | from azureml.monitoring import ModelDataCollector
32 | #from inference_schema.schema_decorators import input_schema, output_schema
33 | #from inference_schema.parameter_types.numpy_parameter_type import NumpyParameterType
34 |
35 | def init():
36 | global model
37 | print("Model Initialized: " + time.strftime("%H:%M:%S"))
38 | # load the model from file into a global object
39 | model_path = Model.get_model_path(model_name="mymodel")
40 | model = joblib.load(model_path)
41 | print("Initialize Data Collectors")
42 | global inputs_dc, prediction_dc
43 | inputs_dc = ModelDataCollector(model_name="sklearn_regression_model", feature_names=["AGE", "SEX", "BMI", "BP", "S1", "S2", "S3", "S4", "S5", "S6"])
44 | prediction_dc = ModelDataCollector(model_name="sklearn_regression_model", feature_names=["Y"])
45 |
46 | #input_sample = np.array([[10.0,9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0]])
47 | #output_sample = np.array([3726.995])
48 |
49 | #@input_schema('data', NumpyParameterType(input_sample))
50 | #@output_schema(NumpyParameterType(output_sample))
51 | def run(raw_data):
52 | global inputs_dc, prediction_dc
53 | try:
54 | data = json.loads(raw_data)["data"]
55 | data = np.array(data)
56 | result = model.predict(data)
57 |
58 | print("Saving Data " + time.strftime("%H:%M:%S"))
59 | inputs_dc.collect(data)
60 | prediction_dc.collect(result)
61 |
62 | return json.dumps({"result": result.tolist()})
63 | except Exception as e:
64 | error = str(e)
65 | print(error + time.strftime("%H:%M:%S"))
66 | return json.dumps({"error": error})
--------------------------------------------------------------------------------
/code/testing/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marvinbuss/MLDevOps/43a4f9b7ab86b0540c206158d35f7bbf910aa6ed/code/testing/__init__.py
--------------------------------------------------------------------------------
/code/testing/test_functions.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 | import json
27 |
28 | def get_test_data_sample():
29 | """
30 | This function returns a single data sample in json format that can be sent
31 | to the deployed web service for testing purposes. Adjust this function to
32 | return the correct data sample.
33 | """
34 | test_sample = {'data': [[1,2,3,4,5,6,7,8,9,10]]}
35 | return json.dumps(test_sample)
--------------------------------------------------------------------------------
/code/training/train.py:
--------------------------------------------------------------------------------
1 | """
2 | Copyright (C) Microsoft Corporation. All rights reserved.
3 |
4 | Microsoft Corporation (“Microsoft”) grants you a nonexclusive, perpetual,
5 | royalty-free right to use, copy, and modify the software code provided by us
6 | ("Software Code"). You may not sublicense the Software Code or any use of it
7 | (except to your affiliates and to vendors to perform work on your behalf)
8 | through distribution, network access, service agreement, lease, rental, or
9 | otherwise. This license does not purport to express any claim of ownership over
10 | data you may have shared with Microsoft in the creation of the Software Code.
11 | Unless applicable law gives you more rights, Microsoft reserves all other
12 | rights not expressly granted herein, whether by implication, estoppel or
13 | otherwise.
14 |
15 | THE SOFTWARE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 | MICROSOFT OR ITS LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 | """
26 | import pickle, os
27 | import numpy as np
28 | from azureml.core import Workspace
29 | from azureml.core.run import Run
30 | from sklearn.datasets import load_diabetes
31 | from sklearn.linear_model import Ridge
32 | from sklearn.metrics import mean_squared_error
33 | from sklearn.model_selection import train_test_split
34 | from sklearn.externals import joblib
35 |
36 | RANDOM_STATE = 42
37 | MODEL_NAME = "mymodel.pkl"
38 |
39 | print("Creating output folder")
40 | os.makedirs('./outputs', exist_ok=True)
41 |
42 | print("Getting Run context")
43 | run = Run.get_context()
44 |
45 | print("Loading data")
46 | X, y = load_diabetes(return_X_y=True)
47 |
48 | print("Creating train test split")
49 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=RANDOM_STATE)
50 | data = {"train": {"X": X_train, "y": y_train}, "test": {"X": X_test, "y": y_test}}
51 |
52 | print("Training a ridge regression model with sklearn and random alpha value")
53 | alphas = np.arange(0.0, 1.0, 0.05)
54 | alpha = alphas[np.random.choice(alphas.shape[0], 1, replace=False)][0]
55 |
56 | reg = Ridge(alpha=alpha)
57 | reg.fit(data["train"]["X"], data["train"]["y"])
58 | preds = reg.predict(data["test"]["X"])
59 | mse = mean_squared_error(preds, data["test"]["y"])
60 | print("Alpha is {0:.2f}, and MSE is {1:0.2f}".format(alpha, mse))
61 |
62 | print("Logging values")
63 | run.log("alpha", alpha)
64 | run.log("mse", mse)
65 |
66 | print("Saving model to output folder")
67 | with open(MODEL_NAME, "wb") as file:
68 | joblib.dump(value=reg, filename=os.path.join("./outputs/", MODEL_NAME))
69 |
70 | print("Training successfully completed!")
71 |
--------------------------------------------------------------------------------
/data/diabetes.csv:
--------------------------------------------------------------------------------
1 | AGE,SEX,BMI,BP,S1,S2,S3,S4,S5,S6,Y
2 | 0.0380759064334241,0.0506801187398187,0.0616962065186885,0.0218723549949558,-0.0442234984244464,-0.0348207628376986,-0.0434008456520269,-0.00259226199818282,0.0199084208763183,-0.0176461251598052,151.0
3 | -0.001882016527791,-0.044641636506989,-0.0514740612388061,-0.0263278347173518,-0.00844872411121698,-0.019163339748222,0.0744115640787594,-0.0394933828740919,-0.0683297436244215,-0.09220404962683,75.0
4 | 0.0852989062966783,0.0506801187398187,0.0444512133365941,-0.00567061055493425,-0.0455994512826475,-0.0341944659141195,-0.0323559322397657,-0.00259226199818282,0.00286377051894013,-0.0259303389894746,141.0
5 | -0.0890629393522603,-0.044641636506989,-0.0115950145052127,-0.0366564467985606,0.0121905687618,0.0249905933641021,-0.0360375700438527,0.0343088588777263,0.0226920225667445,-0.0093619113301358,206.0
6 | 0.00538306037424807,-0.044641636506989,-0.0363846922044735,0.0218723549949558,0.00393485161259318,0.0155961395104161,0.0081420836051921,-0.00259226199818282,-0.0319914449413559,-0.0466408735636482,135.0
7 | -0.0926954778032799,-0.044641636506989,-0.0406959404999971,-0.0194420933298793,-0.0689906498720667,-0.0792878444118122,0.0412768238419757,-0.076394503750001,-0.0411803851880079,-0.0963461565416647,97.0
8 | -0.0454724779400257,0.0506801187398187,-0.0471628129432825,-0.015999222636143,-0.040095639849843,-0.0248000120604336,0.000778807997017968,-0.0394933828740919,-0.0629129499162512,-0.0383566597339788,138.0
9 | 0.063503675590561,0.0506801187398187,-0.00189470584028465,0.0666296740135272,0.0906198816792644,0.108914381123697,0.0228686348215404,0.0177033544835672,-0.0358167281015492,0.00306440941436832,63.0
10 | 0.0417084448844436,0.0506801187398187,0.0616962065186885,-0.0400993174922969,-0.0139525355440215,0.00620168565673016,-0.0286742944356786,-0.00259226199818282,-0.0149564750249113,0.0113486232440377,110.0
11 | -0.0709002470971626,-0.044641636506989,0.0390621529671896,-0.0332135761048244,-0.0125765826858204,-0.034507614375909,-0.0249926566315915,-0.00259226199818282,0.0677363261102861,-0.0135040182449705,310.0
12 | -0.0963280162542995,-0.044641636506989,-0.0838084234552331,0.0081008722200108,-0.103389471327095,-0.0905611890362353,-0.0139477432193303,-0.076394503750001,-0.0629129499162512,-0.0342145528191441,101.0
13 | 0.0271782910803654,0.0506801187398187,0.0175059114895716,-0.0332135761048244,-0.00707277125301585,0.0459715403040008,-0.0654906724765493,0.0712099797536354,-0.096433222891784,-0.0590671943081523,69.0
14 | 0.0162806757273067,-0.044641636506989,-0.0288400076873072,-0.00911348124867051,-0.00432086553661359,-0.00976888589453599,0.0449584616460628,-0.0394933828740919,-0.0307512098645563,-0.0424987666488135,179.0
15 | 0.00538306037424807,0.0506801187398187,-0.00189470584028465,0.0081008722200108,-0.00432086553661359,-0.0157187066685371,-0.0029028298070691,-0.00259226199818282,0.0383932482116977,-0.0135040182449705,185.0
16 | 0.0453409833354632,-0.044641636506989,-0.0256065714656645,-0.0125563519424068,0.0176943801946045,-6.12835790604833e-05,0.0817748396869335,-0.0394933828740919,-0.0319914449413559,-0.0756356219674911,118.0
17 | -0.0527375548420648,0.0506801187398187,-0.0180618869484982,0.0804011567884723,0.0892439288210632,0.107661787276539,-0.0397192078479398,0.108111100629544,0.0360557900898319,-0.0424987666488135,171.0
18 | -0.00551455497881059,-0.044641636506989,0.0422955891888323,0.0494153205448459,0.0245741444856101,-0.0238605666750649,0.0744115640787594,-0.0394933828740919,0.0522799997967812,0.0279170509033766,166.0
19 | 0.0707687524926,0.0506801187398187,0.0121168511201671,0.0563010619323185,0.034205814493018,0.0494161733836856,-0.0397192078479398,0.0343088588777263,0.027367707542609,-0.00107769750046639,144.0
20 | -0.0382074010379866,-0.044641636506989,-0.0105172024313319,-0.0366564467985606,-0.0373437341334407,-0.0194764882100115,-0.0286742944356786,-0.00259226199818282,-0.0181182673078967,-0.0176461251598052,97.0
21 | -0.0273097856849279,-0.044641636506989,-0.0180618869484982,-0.0400993174922969,-0.00294491267841247,-0.0113346282034837,0.0375951860378887,-0.0394933828740919,-0.0089440189577978,-0.0549250873933176,168.0
22 | -0.0491050163910452,-0.044641636506989,-0.0568631216082106,-0.0435421881860331,-0.0455994512826475,-0.043275771306016,0.000778807997017968,-0.0394933828740919,-0.0119006848015081,0.0154907301588724,68.0
23 | -0.0854304009012408,0.0506801187398187,-0.0223731352440218,0.00121513083253827,-0.0373437341334407,-0.0263657543693812,0.0155053592133662,-0.0394933828740919,-0.072128454601956,-0.0176461251598052,49.0
24 | -0.0854304009012408,-0.044641636506989,-0.00405032998804645,-0.00911348124867051,-0.00294491267841247,0.00776742796567782,0.0228686348215404,-0.0394933828740919,-0.0611765950943345,-0.0135040182449705,68.0
25 | 0.0453409833354632,0.0506801187398187,0.0606183944448076,0.0310533436263482,0.0287020030602135,-0.0473467013092799,-0.0544457590642881,0.0712099797536354,0.133598980013008,0.135611830689079,245.0
26 | -0.0636351701951234,-0.044641636506989,0.0358287167455469,-0.0228849640236156,-0.0304639698424351,-0.0188501912864324,-0.00658446761115617,-0.00259226199818282,-0.0259524244351894,-0.0549250873933176,184.0
27 | -0.067267708646143,0.0506801187398187,-0.0126728265790937,-0.0400993174922969,-0.0153284884022226,0.0046359433477825,-0.0581273968683752,0.0343088588777263,0.0191990330785671,-0.0342145528191441,202.0
28 | -0.107225631607358,-0.044641636506989,-0.0773415510119477,-0.0263278347173518,-0.0896299427450836,-0.0961978613484469,0.0265502726256275,-0.076394503750001,-0.0425721049227942,-0.0052198044153011,137.0
29 | -0.0236772472339084,-0.044641636506989,0.0595405823709267,-0.0400993174922969,-0.0428475455662452,-0.0435889197678055,0.0118237214092792,-0.0394933828740919,-0.0159982677581387,0.0403433716478807,85.0
30 | 0.0526060602375023,-0.044641636506989,-0.0212953231701409,-0.0745280244296595,-0.040095639849843,-0.0376390989938044,-0.00658446761115617,-0.0394933828740919,-0.000609254186102297,-0.0549250873933176,131.0
31 | 0.0671362140415805,0.0506801187398187,-0.00620595413580824,0.063186803319791,-0.0428475455662452,-0.0958847128866574,0.052321737254237,-0.076394503750001,0.0594238004447941,0.0527696923923848,283.0
32 | -0.0600026317441039,-0.044641636506989,0.0444512133365941,-0.0194420933298793,-0.00982467696941811,-0.00757684666200928,0.0228686348215404,-0.0394933828740919,-0.0271286455543265,-0.0093619113301358,129.0
33 | -0.0236772472339084,-0.044641636506989,-0.0654856181992578,-0.081413765817132,-0.0387196869916418,-0.0536096705450705,0.0596850128624111,-0.076394503750001,-0.0371283460104736,-0.0424987666488135,59.0
34 | 0.0344433679824045,0.0506801187398187,0.125287118877662,0.0287580963824284,-0.0538551684318543,-0.0129003705124313,-0.10230705051742,0.108111100629544,0.000271485727907132,0.0279170509033766,341.0
35 | 0.030810829531385,-0.044641636506989,-0.0503962491649252,-0.00222773986119799,-0.0442234984244464,-0.0899348921126563,0.118591217727804,-0.076394503750001,-0.0181182673078967,0.00306440941436832,87.0
36 | 0.0162806757273067,-0.044641636506989,-0.063329994051496,-0.0573136709609782,-0.0579830270064577,-0.0489124436182275,0.0081420836051921,-0.0394933828740919,-0.0594726974107223,-0.0673514081378217,65.0
37 | 0.0489735217864827,0.0506801187398187,-0.030995631835069,-0.0492803060204031,0.0493412959332305,-0.00413221358232442,0.133317768944152,-0.0535158088069373,0.0213108465682448,0.0196328370737072,102.0
38 | 0.0126481372762872,-0.044641636506989,0.0228949718589761,0.0528581912385822,0.00806271018719657,-0.0285577936019079,0.0375951860378887,-0.0394933828740919,0.0547240033481791,-0.0259303389894746,265.0
39 | -0.00914709342983014,-0.044641636506989,0.0110390390462862,-0.0573136709609782,-0.0249601584096305,-0.0429626228442264,0.0302319104297145,-0.0394933828740919,0.01703713241478,-0.0052198044153011,276.0
40 | -0.00188201652779104,0.0506801187398187,0.0713965151836166,0.0976155102571536,0.0878679759628621,0.0754074957122168,-0.0213110188275045,0.0712099797536354,0.0714240327805764,0.0237749439885419,252.0
41 | -0.00188201652779104,0.0506801187398187,0.0142724752679289,-0.0745280244296595,0.00255889875439205,0.00620168565673016,-0.0139477432193303,-0.00259226199818282,0.0191990330785671,0.00306440941436832,90.0
42 | 0.00538306037424807,0.0506801187398187,-0.00836157828357004,0.0218723549949558,0.054845107366035,0.07321545647969,-0.0249926566315915,0.0343088588777263,0.0125531528133893,0.094190761540732,100.0
43 | -0.099960554705319,-0.044641636506989,-0.0676412423470196,-0.108956731367022,-0.0744944613048712,-0.072711726714232,0.0155053592133662,-0.0394933828740919,-0.0498684677352306,-0.0093619113301358,55.0
44 | -0.0600026317441039,0.0506801187398187,-0.0105172024313319,-0.0148515990830405,-0.0497273098572509,-0.0235474182132754,-0.0581273968683752,0.0158582984397717,-0.00991895736315477,-0.0342145528191441,61.0
45 | 0.0199132141783263,-0.044641636506989,-0.0234509473179027,-0.0710851537359232,0.0204462859110067,-0.0100820343563255,0.118591217727804,-0.076394503750001,-0.0425721049227942,0.0734802269665584,92.0
46 | 0.0453409833354632,0.0506801187398187,0.068163078961974,0.0081008722200108,-0.0167044412604238,0.0046359433477825,-0.0765355858888105,0.0712099797536354,0.0324332257796019,-0.0176461251598052,259.0
47 | 0.0271782910803654,0.0506801187398187,-0.0353068801305926,0.0322009670761646,-0.0112006298276192,0.00150445872988718,-0.0102661054152432,-0.00259226199818282,-0.0149564750249113,-0.0507829804784829,53.0
48 | -0.0563700932930843,-0.044641636506989,-0.0115950145052127,-0.0332135761048244,-0.0469754041408486,-0.0476598497710694,0.00446044580110504,-0.0394933828740919,-0.00797939755454164,-0.0880619427119953,190.0
49 | -0.0781653239992017,-0.044641636506989,-0.0730303027164241,-0.0573136709609782,-0.0841261313122791,-0.0742774690231797,-0.0249926566315915,-0.0394933828740919,-0.0181182673078967,-0.0839198357971606,142.0
50 | 0.0671362140415805,0.0506801187398187,-0.041773752573878,0.0115437429137471,0.00255889875439205,0.00588853719494063,0.0412768238419757,-0.0394933828740919,-0.0594726974107223,-0.0217882320746399,75.0
51 | -0.0418399394890061,0.0506801187398187,0.0142724752679289,-0.00567061055493425,-0.0125765826858204,0.00620168565673016,-0.0728539480847234,0.0712099797536354,0.0354619386607697,-0.0135040182449705,142.0
52 | 0.0344433679824045,-0.044641636506989,-0.00728376620968916,0.0149866136074833,-0.0442234984244464,-0.0373259505320149,-0.0029028298070691,-0.0394933828740919,-0.02139368094036,0.00720651632920303,155.0
53 | 0.0598711371395414,0.0506801187398187,0.0164280994156907,0.0287580963824284,-0.0414715927080441,-0.029184090525487,-0.0286742944356786,-0.00259226199818282,-0.00239668149341427,-0.0217882320746399,225.0
54 | -0.0527375548420648,-0.044641636506989,-0.00943939035745095,-0.00567061055493425,0.0397096259258226,0.0447189464568426,0.0265502726256275,-0.00259226199818282,-0.0181182673078967,-0.0135040182449705,59.0
55 | -0.00914709342983014,-0.044641636506989,-0.0159062628007364,0.0700725447072635,0.0121905687618,0.0221722572079963,0.0155053592133662,-0.00259226199818282,-0.0332487872476258,0.0486275854775501,104.0
56 | -0.0491050163910452,-0.044641636506989,0.0250505960067379,0.0081008722200108,0.0204462859110067,0.0177881787429428,0.052321737254237,-0.0394933828740919,-0.0411803851880079,0.00720651632920303,182.0
57 | -0.0418399394890061,-0.044641636506989,-0.0493184370910443,-0.0366564467985606,-0.00707277125301585,-0.0226079728279068,0.0854564774910206,-0.0394933828740919,-0.0664881482228354,0.00720651632920303,128.0
58 | -0.0418399394890061,-0.044641636506989,0.0412177771149514,-0.0263278347173518,-0.0318399227006362,-0.0304366843726451,-0.0360375700438527,0.00294290613320356,0.0336568129023847,-0.0176461251598052,52.0
59 | -0.0273097856849279,-0.044641636506989,-0.063329994051496,-0.0504279295735057,-0.0896299427450836,-0.104339721354975,0.052321737254237,-0.076394503750001,-0.0561575730950062,-0.0673514081378217,37.0
60 | 0.0417084448844436,-0.044641636506989,-0.064407806125377,0.0356438377699009,0.0121905687618,-0.057993749010124,0.181179060397284,-0.076394503750001,-0.000609254186102297,-0.0507829804784829,170.0
61 | 0.063503675590561,0.0506801187398187,-0.0256065714656645,0.0115437429137471,0.0644767773734429,0.048476727998317,0.0302319104297145,-0.00259226199818282,0.0383932482116977,0.0196328370737072,170.0
62 | -0.0709002470971626,-0.044641636506989,-0.00405032998804645,-0.0400993174922969,-0.0662387441556644,-0.0786615474882331,0.052321737254237,-0.076394503750001,-0.0514005352605825,-0.0342145528191441,61.0
63 | -0.0418399394890061,0.0506801187398187,0.00457216660300077,-0.0538708002672419,-0.0442234984244464,-0.0273051997547498,-0.0802172236928976,0.0712099797536354,0.0366457977933988,0.0196328370737072,144.0
64 | -0.0273097856849279,0.0506801187398187,-0.00728376620968916,-0.0400993174922969,-0.0112006298276192,-0.0138398158977999,0.0596850128624111,-0.0394933828740919,-0.0823814832581028,-0.0259303389894746,52.0
65 | -0.034574862586967,-0.044641636506989,-0.0374625042783544,-0.0607565416547144,0.0204462859110067,0.0434663526096845,-0.0139477432193303,-0.00259226199818282,-0.0307512098645563,-0.0714935150526564,128.0
66 | 0.0671362140415805,0.0506801187398187,-0.0256065714656645,-0.0400993174922969,-0.0634868384392622,-0.0598726397808612,-0.0029028298070691,-0.0394933828740919,-0.0191970476139445,0.0113486232440377,71.0
67 | -0.0454724779400257,0.0506801187398187,-0.0245287593917836,0.0597439326260547,0.00531080447079431,0.0149698425868371,-0.0544457590642881,0.0712099797536354,0.0423448954496075,0.0154907301588724,163.0
68 | -0.00914709342983014,0.0506801187398187,-0.0180618869484982,-0.0332135761048244,-0.0208322998350272,0.0121515064307313,-0.0728539480847234,0.0712099797536354,0.000271485727907132,0.0196328370737072,150.0
69 | 0.0417084448844436,0.0506801187398187,-0.0148284507268555,-0.0171468461892456,-0.00569681839481472,0.00839372488925688,-0.0139477432193303,-0.00185423958066465,-0.0119006848015081,0.00306440941436832,97.0
70 | 0.0380759064334241,0.0506801187398187,-0.0299178197611881,-0.0400993174922969,-0.0332158755588373,-0.0241737151368545,-0.0102661054152432,-0.00259226199818282,-0.0129079422541688,0.00306440941436832,160.0
71 | 0.0162806757273067,-0.044641636506989,-0.0460850008694016,-0.00567061055493425,-0.0758704141630723,-0.0614383820898088,-0.0139477432193303,-0.0394933828740919,-0.0514005352605825,0.0196328370737072,178.0
72 | -0.00188201652779104,-0.044641636506989,-0.0697968664947814,-0.0125563519424068,-0.000193006962010205,-0.00914258897095694,0.0707299262746723,-0.0394933828740919,-0.0629129499162512,0.0403433716478807,48.0
73 | -0.00188201652779104,-0.044641636506989,0.0336730925977851,0.125158475807044,0.0245741444856101,0.0262431872112602,-0.0102661054152432,-0.00259226199818282,0.0267142576335128,0.0610539062220542,270.0
74 | 0.063503675590561,0.0506801187398187,-0.00405032998804645,-0.0125563519424068,0.103003457403075,0.0487898764601065,0.056003375058324,-0.00259226199818282,0.0844952822124031,-0.0176461251598052,202.0
75 | 0.0126481372762872,0.0506801187398187,-0.02021751109626,-0.00222773986119799,0.0383336730676214,0.05317395492516,-0.00658446761115617,0.0343088588777263,-0.00514530798026311,-0.0093619113301358,111.0
76 | 0.0126481372762872,0.0506801187398187,0.00241654245523897,0.0563010619323185,0.0273260502020124,0.0171618818193638,0.0412768238419757,-0.0394933828740919,0.00371173823343597,0.0734802269665584,85.0
77 | -0.00914709342983014,0.0506801187398187,-0.030995631835069,-0.0263278347173518,-0.0112006298276192,-0.00100072896442909,-0.0213110188275045,-0.00259226199818282,0.0062093156165054,0.0279170509033766,42.0
78 | -0.0309423241359475,0.0506801187398187,0.0282840322283806,0.0700725447072635,-0.126780669916514,-0.106844909049291,-0.0544457590642881,-0.047980640675551,-0.0307512098645563,0.0154907301588724,170.0
79 | -0.0963280162542995,-0.044641636506989,-0.0363846922044735,-0.0745280244296595,-0.0387196869916418,-0.0276183482165393,0.0155053592133662,-0.0394933828740919,-0.0740888714915354,-0.00107769750046639,200.0
80 | 0.00538306037424807,-0.044641636506989,-0.0579409336820915,-0.0228849640236156,-0.0676146970138656,-0.0683276482491785,-0.0544457590642881,-0.00259226199818282,0.0428956878925287,-0.0839198357971606,252.0
81 | -0.103593093156339,-0.044641636506989,-0.0374625042783544,-0.0263278347173518,0.00255889875439205,0.0199802179754696,0.0118237214092792,-0.00259226199818282,-0.0683297436244215,-0.0259303389894746,113.0
82 | 0.0707687524926,-0.044641636506989,0.0121168511201671,0.0425295791573734,0.0713565416644485,0.0534871033869495,0.052321737254237,-0.00259226199818282,0.0253931349154494,-0.0052198044153011,143.0
83 | 0.0126481372762872,0.0506801187398187,-0.0223731352440218,-0.0297707054110881,0.0108146159035988,0.0284352264437869,-0.0213110188275045,0.0343088588777263,-0.00608024819631442,-0.00107769750046639,51.0
84 | -0.0164121703318693,-0.044641636506989,-0.0353068801305926,-0.0263278347173518,0.0328298616348169,0.0171618818193638,0.100183028707369,-0.0394933828740919,-0.0702093127286876,-0.0797777288823259,52.0
85 | -0.0382074010379866,-0.044641636506989,0.00996122697240527,-0.0469850588797694,-0.0593589798646588,-0.0529833736214915,-0.0102661054152432,-0.0394933828740919,-0.0159982677581387,-0.0424987666488135,210.0
86 | 0.00175052192322852,-0.044641636506989,-0.0396181284261162,-0.100923366426447,-0.0290880169842339,-0.0301235359108556,0.0449584616460628,-0.0501947079281055,-0.0683297436244215,-0.129483011860342,65.0
87 | 0.0453409833354632,-0.044641636506989,0.0713965151836166,0.00121513083253827,-0.00982467696941811,-0.00100072896442909,0.0155053592133662,-0.0394933828740919,-0.0411803851880079,-0.0714935150526564,141.0
88 | -0.0709002470971626,0.0506801187398187,-0.0751859268641859,-0.0400993174922969,-0.051103262715452,-0.015092409744958,-0.0397192078479398,-0.00259226199818282,-0.096433222891784,-0.0342145528191441,55.0
89 | 0.0453409833354632,-0.044641636506989,-0.00620595413580824,0.0115437429137471,0.0631008245152418,0.0162224364339952,0.0965013909032818,-0.0394933828740919,0.0428956878925287,-0.0383566597339788,134.0
90 | -0.0527375548420648,0.0506801187398187,-0.0406959404999971,-0.067642283042187,-0.0318399227006362,-0.0370128020702253,0.0375951860378887,-0.0394933828740919,-0.0345237153303495,0.0693381200517237,42.0
91 | -0.0454724779400257,-0.044641636506989,-0.0482406250171634,-0.0194420933298793,-0.000193006962010205,-0.0160318551303266,0.0670482884705852,-0.0394933828740919,-0.0247911874324607,0.0196328370737072,111.0
92 | 0.0126481372762872,-0.044641636506989,-0.0256065714656645,-0.0400993174922969,-0.0304639698424351,-0.0451546620767532,0.0780932018828464,-0.076394503750001,-0.072128454601956,0.0113486232440377,98.0
93 | 0.0453409833354632,-0.044641636506989,0.0519958978537604,-0.0538708002672419,0.0631008245152418,0.0647604480113727,-0.0102661054152432,0.0343088588777263,0.0372320112089689,0.0196328370737072,164.0
94 | -0.0200447087828888,-0.044641636506989,0.00457216660300077,0.0976155102571536,0.00531080447079431,-0.0207290820571696,0.0633666506664982,-0.0394933828740919,0.0125531528133893,0.0113486232440377,48.0
95 | -0.0491050163910452,-0.044641636506989,-0.064407806125377,-0.10207098997955,-0.00294491267841247,-0.0154055582067476,0.0633666506664982,-0.0472426182580328,-0.0332487872476258,-0.0549250873933176,96.0
96 | -0.0781653239992017,-0.044641636506989,-0.0169840748746173,-0.0125563519424068,-0.000193006962010205,-0.0135266674360104,0.0707299262746723,-0.0394933828740919,-0.0411803851880079,-0.09220404962683,90.0
97 | -0.0709002470971626,-0.044641636506989,-0.0579409336820915,-0.081413765817132,-0.0455994512826475,-0.0288709420636975,-0.0434008456520269,-0.00259226199818282,0.00114379737951254,-0.0052198044153011,162.0
98 | 0.0562385986885218,0.0506801187398187,0.00996122697240527,0.0494153205448459,-0.00432086553661359,-0.0122740735888523,-0.0434008456520269,0.0343088588777263,0.060787754150744,0.0320591578182113,150.0
99 | -0.0273097856849279,-0.044641636506989,0.088641508365711,-0.0251802111642493,0.0218222387692079,0.0425269072243159,-0.0323559322397657,0.0343088588777263,0.00286377051894013,0.0776223338813931,279.0
100 | 0.00175052192322852,0.0506801187398187,-0.00512814206192736,-0.0125563519424068,-0.0153284884022226,-0.0138398158977999,0.0081420836051921,-0.0394933828740919,-0.00608024819631442,-0.0673514081378217,92.0
101 | -0.00188201652779104,-0.044641636506989,-0.064407806125377,0.0115437429137471,0.0273260502020124,0.0375165318356834,-0.0139477432193303,0.0343088588777263,0.0117839003835759,-0.0549250873933176,83.0
102 | 0.0162806757273067,-0.044641636506989,0.0175059114895716,-0.0228849640236156,0.0603489187988395,0.0444057979950531,0.0302319104297145,-0.00259226199818282,0.0372320112089689,-0.00107769750046639,128.0
103 | 0.0162806757273067,0.0506801187398187,-0.0450071887955207,0.063186803319791,0.0108146159035988,-0.00037443204085002,0.0633666506664982,-0.0394933828740919,-0.0307512098645563,0.036201264733046,102.0
104 | -0.0926954778032799,-0.044641636506989,0.0282840322283806,-0.015999222636143,0.0369577202094203,0.0249905933641021,0.056003375058324,-0.0394933828740919,-0.00514530798026311,-0.00107769750046639,302.0
105 | 0.0598711371395414,0.0506801187398187,0.0412177771149514,0.0115437429137471,0.0410855787840237,0.0707102687853738,-0.0360375700438527,0.0343088588777263,-0.0109044358473771,-0.0300724459043093,198.0
106 | -0.0273097856849279,-0.044641636506989,0.0649296427403312,-0.00222773986119799,-0.0249601584096305,-0.0172844489774848,0.0228686348215404,-0.0394933828740919,-0.0611765950943345,-0.063209301222987,95.0
107 | 0.0235457526293458,0.0506801187398187,-0.0320734439089499,-0.0400993174922969,-0.0318399227006362,-0.0216685274425382,-0.0139477432193303,-0.00259226199818282,-0.0109044358473771,0.0196328370737072,53.0
108 | -0.0963280162542995,-0.044641636506989,-0.0762637389380668,-0.0435421881860331,-0.0455994512826475,-0.0348207628376986,0.0081420836051921,-0.0394933828740919,-0.0594726974107223,-0.0839198357971606,134.0
109 | 0.0271782910803654,-0.044641636506989,0.0498402737059986,-0.0550184238203444,-0.00294491267841247,0.0406480164535787,-0.0581273968683752,0.0527594193156808,-0.0529587932392004,-0.0052198044153011,144.0
110 | 0.0199132141783263,0.0506801187398187,0.045529025410475,0.0299057198322448,-0.062110885581061,-0.0558017097775973,-0.0728539480847234,0.0269286347025444,0.0456008084141249,0.0403433716478807,232.0
111 | 0.0380759064334241,0.0506801187398187,-0.00943939035745095,0.0023627543856408,0.00118294589619092,0.0375165318356834,-0.0544457590642881,0.0501763408543672,-0.0259524244351894,0.106617082285236,81.0
112 | 0.0417084448844436,0.0506801187398187,-0.0320734439089499,-0.0228849640236156,-0.0497273098572509,-0.0401442866881206,0.0302319104297145,-0.0394933828740919,-0.126097385560409,0.0154907301588724,104.0
113 | 0.0199132141783263,-0.044641636506989,0.00457216660300077,-0.0263278347173518,0.023198191627409,0.0102726156599941,0.0670482884705852,-0.0394933828740919,-0.0236445575721341,-0.0466408735636482,59.0
114 | -0.0854304009012408,-0.044641636506989,0.0207393477112143,-0.0263278347173518,0.00531080447079431,0.01966706951368,-0.0029028298070691,-0.00259226199818282,-0.0236445575721341,0.00306440941436832,246.0
115 | 0.0199132141783263,0.0506801187398187,0.0142724752679289,0.063186803319791,0.0149424744782022,0.0202933664372591,-0.0470824834561139,0.0343088588777263,0.0466607723568145,0.0900486546258972,297.0
116 | 0.0235457526293458,-0.044641636506989,0.110197749843329,0.063186803319791,0.0135665216200011,-0.0329418720669614,-0.0249926566315915,0.0206554441536399,0.09924022573399,0.0237749439885419,258.0
117 | -0.0309423241359475,0.0506801187398187,0.00133873038135806,-0.00567061055493425,0.0644767773734429,0.0494161733836856,-0.0470824834561139,0.108111100629544,0.0837967663655224,0.00306440941436832,229.0
118 | 0.0489735217864827,0.0506801187398187,0.0584627702970458,0.0700725447072635,0.0135665216200011,0.0206065148990486,-0.0213110188275045,0.0343088588777263,0.0220040504561505,0.0279170509033766,275.0
119 | 0.0598711371395414,-0.044641636506989,-0.0212953231701409,0.0872868981759448,0.0452134373586271,0.0315667110616823,-0.0470824834561139,0.0712099797536354,0.0791210813896579,0.135611830689079,281.0
120 | -0.0563700932930843,0.0506801187398187,-0.0105172024313319,0.0253152256886921,0.023198191627409,0.0400217195299996,-0.0397192078479398,0.0343088588777263,0.0206123307213641,0.0569117993072195,179.0
121 | 0.0162806757273067,-0.044641636506989,-0.0471628129432825,-0.00222773986119799,-0.019456346976826,-0.0429626228442264,0.0339135482338016,-0.0394933828740919,0.027367707542609,0.0279170509033766,200.0
122 | -0.0491050163910452,-0.044641636506989,0.00457216660300077,0.0115437429137471,-0.0373437341334407,-0.0185370428246429,-0.0176293810234174,-0.00259226199818282,-0.0398095943643375,-0.0217882320746399,200.0
123 | 0.063503675590561,-0.044641636506989,0.0175059114895716,0.0218723549949558,0.00806271018719657,0.0215459602844172,-0.0360375700438527,0.0343088588777263,0.0199084208763183,0.0113486232440377,173.0
124 | 0.0489735217864827,0.0506801187398187,0.0810968238485447,0.0218723549949558,0.0438374845004259,0.0641341510877936,-0.0544457590642881,0.0712099797536354,0.0324332257796019,0.0486275854775501,180.0
125 | 0.00538306037424807,0.0506801187398187,0.034750904671666,-0.00108011630809546,0.152537760298315,0.198787989657293,-0.0618090346724622,0.185234443260194,0.0155668445407018,0.0734802269665584,84.0
126 | -0.00551455497881059,-0.044641636506989,0.023972783932857,0.0081008722200108,-0.0345918284170385,-0.0388916928409625,0.0228686348215404,-0.0394933828740919,-0.0159982677581387,-0.0135040182449705,121.0
127 | -0.00551455497881059,0.0506801187398187,-0.00836157828357004,-0.00222773986119799,-0.0332158755588373,-0.0636304213223356,-0.0360375700438527,-0.00259226199818282,0.0805854642386665,0.00720651632920303,161.0
128 | -0.0890629393522603,-0.044641636506989,-0.0611743699037342,-0.0263278347173518,-0.0552311212900554,-0.0545491159304391,0.0412768238419757,-0.076394503750001,-0.0939356455087147,-0.0549250873933176,99.0
129 | 0.0344433679824045,0.0506801187398187,-0.00189470584028465,-0.0125563519424068,0.0383336730676214,0.0137172487396789,0.0780932018828464,-0.0394933828740919,0.00455189046612778,-0.0963461565416647,109.0
130 | -0.0527375548420648,-0.044641636506989,-0.0622521819776151,-0.0263278347173518,-0.00569681839481472,-0.005071658967693,0.0302319104297145,-0.0394933828740919,-0.0307512098645563,-0.0714935150526564,115.0
131 | 0.00901559882526763,-0.044641636506989,0.0164280994156907,0.00465800152627453,0.0094386630453977,0.0105857641217836,-0.0286742944356786,0.0343088588777263,0.0389683660308856,0.11904340302974,268.0
132 | -0.0636351701951234,0.0506801187398187,0.0961861928828773,0.104501251644626,-0.00294491267841247,-0.00475851050590347,-0.00658446761115617,-0.00259226199818282,0.0226920225667445,0.0734802269665584,274.0
133 | -0.0963280162542995,-0.044641636506989,-0.0697968664947814,-0.067642283042187,-0.019456346976826,-0.0107083312799046,0.0155053592133662,-0.0394933828740919,-0.0468794828442166,-0.0797777288823259,158.0
134 | 0.0162806757273067,0.0506801187398187,-0.0212953231701409,-0.00911348124867051,0.034205814493018,0.047850431074738,0.000778807997017968,-0.00259226199818282,-0.0129079422541688,0.0237749439885419,107.0
135 | -0.0418399394890061,0.0506801187398187,-0.0536296853865679,-0.0400993174922969,-0.0841261313122791,-0.0717722813288634,-0.0029028298070691,-0.0394933828740919,-0.072128454601956,-0.0300724459043093,83.0
136 | -0.0745327855481821,-0.044641636506989,0.0433734012627132,-0.0332135761048244,0.0121905687618,0.000251864882729031,0.0633666506664982,-0.0394933828740919,-0.0271286455543265,-0.0466408735636482,103.0
137 | -0.00551455497881059,-0.044641636506989,0.056307146149284,-0.0366564467985606,-0.0483513569990498,-0.0429626228442264,-0.0728539480847234,0.0379989709653172,0.0507815133629732,0.0569117993072195,272.0
138 | -0.0926954778032799,-0.044641636506989,-0.0816527993074713,-0.0573136709609782,-0.0607349327228599,-0.068014499787389,0.0486400994501499,-0.076394503750001,-0.0664881482228354,-0.0217882320746399,85.0
139 | 0.00538306037424807,-0.044641636506989,0.0498402737059986,0.0976155102571536,-0.0153284884022226,-0.0163450035921162,-0.00658446761115617,-0.00259226199818282,0.01703713241478,-0.0135040182449705,280.0
140 | 0.0344433679824045,0.0506801187398187,0.11127556191721,0.076958286094736,-0.0318399227006362,-0.03388131745233,-0.0213110188275045,-0.00259226199818282,0.028016506523264,0.0734802269665584,336.0
141 | 0.0235457526293458,-0.044641636506989,0.0616962065186885,0.0528581912385822,-0.0345918284170385,-0.0489124436182275,-0.0286742944356786,-0.00259226199818282,0.0547240033481791,-0.0052198044153011,281.0
142 | 0.0417084448844436,0.0506801187398187,0.0142724752679289,0.0425295791573734,-0.0304639698424351,-0.00131387742621863,-0.0434008456520269,-0.00259226199818282,-0.0332487872476258,0.0154907301588724,118.0
143 | -0.0273097856849279,-0.044641636506989,0.0476846495582368,-0.0469850588797694,0.034205814493018,0.0572448849284239,-0.0802172236928976,0.13025177315509,0.0450661683362615,0.131469723774244,317.0
144 | 0.0417084448844436,0.0506801187398187,0.0121168511201671,0.0390867084636372,0.054845107366035,0.0444057979950531,0.00446044580110504,-0.00259226199818282,0.0456008084141249,-0.00107769750046639,235.0
145 | -0.0309423241359475,-0.044641636506989,0.00564997867688165,-0.00911348124867051,0.0190703330528056,0.00682798258030921,0.0744115640787594,-0.0394933828740919,-0.0411803851880079,-0.0424987666488135,60.0
146 | 0.030810829531385,0.0506801187398187,0.0466068374843559,-0.015999222636143,0.0204462859110067,0.0506687672308438,-0.0581273968683752,0.0712099797536354,0.0062093156165054,0.00720651632920303,174.0
147 | -0.0418399394890061,-0.044641636506989,0.128520555099304,0.063186803319791,-0.0332158755588373,-0.0326287236051719,0.0118237214092792,-0.0394933828740919,-0.0159982677581387,-0.0507829804784829,259.0
148 | -0.0309423241359475,0.0506801187398187,0.0595405823709267,0.00121513083253827,0.0121905687618,0.0315667110616823,-0.0434008456520269,0.0343088588777263,0.0148227108412663,0.00720651632920303,178.0
149 | -0.0563700932930843,-0.044641636506989,0.0929527566612346,-0.0194420933298793,0.0149424744782022,0.0234248510551544,-0.0286742944356786,0.0254525898675081,0.0260560896336847,0.0403433716478807,128.0
150 | -0.0600026317441039,0.0506801187398187,0.0153502873418098,-0.0194420933298793,0.0369577202094203,0.0481635795365275,0.0191869970174533,-0.00259226199818282,-0.0307512098645563,-0.00107769750046639,96.0
151 | -0.0491050163910452,0.0506801187398187,-0.00512814206192736,-0.0469850588797694,-0.0208322998350272,-0.0204159335953801,-0.0691723102806364,0.0712099797536354,0.061237907519701,-0.0383566597339788,126.0
152 | 0.0235457526293458,-0.044641636506989,0.0703187031097357,0.0253152256886921,-0.0345918284170385,-0.014466112821379,-0.0323559322397657,-0.00259226199818282,-0.0191970476139445,-0.0093619113301358,288.0
153 | 0.00175052192322852,-0.044641636506989,-0.00405032998804645,-0.00567061055493425,-0.00844872411121698,-0.0238605666750649,0.052321737254237,-0.0394933828740919,-0.0089440189577978,-0.0135040182449705,88.0
154 | -0.034574862586967,0.0506801187398187,-0.000816893766403737,0.0700725447072635,0.0397096259258226,0.0669524872438994,-0.0654906724765493,0.108111100629544,0.0267142576335128,0.0734802269665584,292.0
155 | 0.0417084448844436,0.0506801187398187,-0.0439293767216398,0.063186803319791,-0.00432086553661359,0.0162224364339952,-0.0139477432193303,-0.00259226199818282,-0.0345237153303495,0.0113486232440377,71.0
156 | 0.0671362140415805,0.0506801187398187,0.0207393477112143,-0.00567061055493425,0.0204462859110067,0.0262431872112602,-0.0029028298070691,-0.00259226199818282,0.00864028293306308,0.00306440941436832,197.0
157 | -0.0273097856849279,0.0506801187398187,0.0606183944448076,0.0494153205448459,0.0851160702464598,0.0863676918748504,-0.0029028298070691,0.0343088588777263,0.0378144788263439,0.0486275854775501,186.0
158 | -0.0164121703318693,-0.044641636506989,-0.0105172024313319,0.00121513083253827,-0.0373437341334407,-0.0357602082230672,0.0118237214092792,-0.0394933828740919,-0.02139368094036,-0.0342145528191441,25.0
159 | -0.00188201652779104,0.0506801187398187,-0.0331512559828308,-0.0182944697767768,0.0314539087766158,0.0428400556861055,-0.0139477432193303,0.0199174217361217,0.0102256424049578,0.0279170509033766,84.0
160 | -0.0127796318808497,-0.044641636506989,-0.0654856181992578,-0.0699375301828207,0.00118294589619092,0.0168487333575743,-0.0029028298070691,-0.00702039650329191,-0.0307512098645563,-0.0507829804784829,96.0
161 | -0.00551455497881059,-0.044641636506989,0.0433734012627132,0.0872868981759448,0.0135665216200011,0.00714113104209875,-0.0139477432193303,-0.00259226199818282,0.0423448954496075,-0.0176461251598052,195.0
162 | -0.00914709342983014,-0.044641636506989,-0.0622521819776151,-0.0745280244296595,-0.0235842055514294,-0.0132135189742209,0.00446044580110504,-0.0394933828740919,-0.0358167281015492,-0.0466408735636482,53.0
163 | -0.0454724779400257,0.0506801187398187,0.0638518306664503,0.0700725447072635,0.133274420283499,0.131461070372543,-0.0397192078479398,0.108111100629544,0.0757375884575476,0.0859065477110625,217.0
164 | -0.0527375548420648,-0.044641636506989,0.0304396563761424,-0.0745280244296595,-0.0235842055514294,-0.0113346282034837,-0.0029028298070691,-0.00259226199818282,-0.0307512098645563,-0.00107769750046639,172.0
165 | 0.0162806757273067,0.0506801187398187,0.0724743272574975,0.076958286094736,-0.00844872411121698,0.00557538873315109,-0.00658446761115617,-0.00259226199818282,-0.0236445575721341,0.0610539062220542,131.0
166 | 0.0453409833354632,-0.044641636506989,-0.019139699022379,0.0218723549949558,0.0273260502020124,-0.0135266674360104,0.100183028707369,-0.0394933828740919,0.0177634778671173,-0.0135040182449705,214.0
167 | -0.0418399394890061,-0.044641636506989,-0.0665634302731387,-0.0469850588797694,-0.0373437341334407,-0.043275771306016,0.0486400994501499,-0.0394933828740919,-0.0561575730950062,-0.0135040182449705,59.0
168 | -0.0563700932930843,0.0506801187398187,-0.0600965578298533,-0.0366564467985606,-0.0882539898868825,-0.0708328359434948,-0.0139477432193303,-0.0394933828740919,-0.0781409106690696,-0.104630370371334,70.0
169 | 0.0707687524926,-0.044641636506989,0.0692408910358548,0.0379390850138207,0.0218222387692079,0.00150445872988718,-0.0360375700438527,0.0391060045915944,0.0776327891955595,0.106617082285236,220.0
170 | 0.00175052192322852,0.0506801187398187,0.0595405823709267,-0.00222773986119799,0.0617248716570406,0.063194705702425,-0.0581273968683752,0.108111100629544,0.0689822116363026,0.12732761685941,268.0
171 | -0.00188201652779104,-0.044641636506989,-0.0266843835395454,0.0494153205448459,0.0589729659406384,-0.0160318551303266,-0.0470824834561139,0.0712099797536354,0.133598980013008,0.0196328370737072,152.0
172 | 0.0235457526293458,0.0506801187398187,-0.02021751109626,-0.0366564467985606,-0.0139525355440215,-0.015092409744958,0.0596850128624111,-0.0394933828740919,-0.096433222891784,-0.0176461251598052,47.0
173 | -0.0200447087828888,-0.044641636506989,-0.0460850008694016,-0.0986281192858133,-0.0758704141630723,-0.0598726397808612,-0.0176293810234174,-0.0394933828740919,-0.0514005352605825,-0.0466408735636482,74.0
174 | 0.0417084448844436,0.0506801187398187,0.0713965151836166,0.0081008722200108,0.0383336730676214,0.0159092879722056,-0.0176293810234174,0.0343088588777263,0.0734100780491161,0.0859065477110625,295.0
175 | -0.0636351701951234,0.0506801187398187,-0.0794971751597095,-0.00567061055493425,-0.071742555588469,-0.0664487574784414,-0.0102661054152432,-0.0394933828740919,-0.0181182673078967,-0.0549250873933176,101.0
176 | 0.0162806757273067,0.0506801187398187,0.00996122697240527,-0.0435421881860331,-0.0965097070360893,-0.0946321190394993,-0.0397192078479398,-0.0394933828740919,0.01703713241478,0.00720651632920303,151.0
177 | 0.0671362140415805,-0.044641636506989,-0.0385403163522353,-0.0263278347173518,-0.0318399227006362,-0.0263657543693812,0.0081420836051921,-0.0394933828740919,-0.0271286455543265,0.00306440941436832,127.0
178 | 0.0453409833354632,0.0506801187398187,0.0196615356373334,0.0390867084636372,0.0204462859110067,0.0259300387494707,0.0081420836051921,-0.00259226199818282,-0.003303712578677,0.0196328370737072,237.0
179 | 0.0489735217864827,-0.044641636506989,0.0272062201544997,-0.0251802111642493,0.023198191627409,0.0184144756665219,-0.0618090346724622,0.0800662487638535,0.0722236508199124,0.0320591578182113,225.0
180 | 0.0417084448844436,-0.044641636506989,-0.00836157828357004,-0.0263278347173518,0.0245741444856101,0.0162224364339952,0.0707299262746723,-0.0394933828740919,-0.0483617248028919,-0.0300724459043093,81.0
181 | -0.0236772472339084,-0.044641636506989,-0.0159062628007364,-0.0125563519424068,0.0204462859110067,0.0412743133771578,-0.0434008456520269,0.0343088588777263,0.0140724525157685,-0.0093619113301358,151.0
182 | -0.0382074010379866,0.0506801187398187,0.00457216660300077,0.0356438377699009,-0.0112006298276192,0.00588853719494063,-0.0470824834561139,0.0343088588777263,0.0163049527999418,-0.00107769750046639,107.0
183 | 0.0489735217864827,-0.044641636506989,-0.0428515646477589,-0.0538708002672419,0.0452134373586271,0.0500424703072647,0.0339135482338016,-0.00259226199818282,-0.0259524244351894,-0.063209301222987,64.0
184 | 0.0453409833354632,0.0506801187398187,0.00564997867688165,0.0563010619323185,0.0644767773734429,0.0891860280309562,-0.0397192078479398,0.0712099797536354,0.0155668445407018,-0.0093619113301358,138.0
185 | 0.0453409833354632,0.0506801187398187,-0.0353068801305926,0.063186803319791,-0.00432086553661359,-0.00162702588800815,-0.0102661054152432,-0.00259226199818282,0.0155668445407018,0.0569117993072195,185.0
186 | 0.0162806757273067,-0.044641636506989,0.023972783932857,-0.0228849640236156,-0.0249601584096305,-0.0260526059075917,-0.0323559322397657,-0.00259226199818282,0.0372320112089689,0.0320591578182113,265.0
187 | -0.0745327855481821,0.0506801187398187,-0.0180618869484982,0.0081008722200108,-0.019456346976826,-0.0248000120604336,-0.0654906724765493,0.0343088588777263,0.0673172179146849,-0.0176461251598052,101.0
188 | -0.0817978624502212,0.0506801187398187,0.0422955891888323,-0.0194420933298793,0.0397096259258226,0.0575580333902134,-0.0691723102806364,0.108111100629544,0.0471861678860197,-0.0383566597339788,137.0
189 | -0.067267708646143,-0.044641636506989,-0.0547074974604488,-0.0263278347173518,-0.0758704141630723,-0.082106180567918,0.0486400994501499,-0.076394503750001,-0.0868289932162924,-0.104630370371334,143.0
190 | 0.00538306037424807,-0.044641636506989,-0.00297251791416553,0.0494153205448459,0.0741084473808508,0.0707102687853738,0.0449584616460628,-0.00259226199818282,-0.00149858682029207,-0.0093619113301358,141.0
191 | -0.00188201652779104,-0.044641636506989,-0.0665634302731387,0.00121513083253827,-0.00294491267841247,0.00307020103883484,0.0118237214092792,-0.00259226199818282,-0.0202887477516296,-0.0259303389894746,79.0
192 | 0.00901559882526763,-0.044641636506989,-0.0126728265790937,0.0287580963824284,-0.0180803941186249,-0.005071658967693,-0.0470824834561139,0.0343088588777263,0.0233748412798208,-0.0052198044153011,292.0
193 | -0.00551455497881059,0.0506801187398187,-0.041773752573878,-0.0435421881860331,-0.0799982727376757,-0.0761563597939169,-0.0323559322397657,-0.0394933828740919,0.0102256424049578,-0.0093619113301358,178.0
194 | 0.0562385986885218,0.0506801187398187,-0.030995631835069,0.0081008722200108,0.0190703330528056,0.0212328118226277,0.0339135482338016,-0.0394933828740919,-0.0295276227417736,-0.0590671943081523,91.0
195 | 0.00901559882526763,0.0506801187398187,-0.00512814206192736,-0.0641994123484507,0.0699805888062474,0.0838625041805342,-0.0397192078479398,0.0712099797536354,0.0395398780720242,0.0196328370737072,116.0
196 | -0.067267708646143,-0.044641636506989,-0.0590187457559724,0.0322009670761646,-0.051103262715452,-0.0495387405418066,-0.0102661054152432,-0.0394933828740919,0.00200784054982379,0.0237749439885419,86.0
197 | 0.0271782910803654,0.0506801187398187,0.0250505960067379,0.0149866136074833,0.0259500973438113,0.048476727998317,-0.0397192078479398,0.0343088588777263,0.00783714230182385,0.0237749439885419,122.0
198 | -0.0236772472339084,-0.044641636506989,-0.0460850008694016,-0.0332135761048244,0.0328298616348169,0.0362639379885253,0.0375951860378887,-0.00259226199818282,-0.0332487872476258,0.0113486232440377,72.0
199 | 0.0489735217864827,0.0506801187398187,0.00349435452911985,0.0700725447072635,-0.00844872411121698,0.0134041002778894,-0.0544457590642881,0.0343088588777263,0.0133159679089277,0.036201264733046,129.0
200 | -0.0527375548420648,-0.044641636506989,0.0541515220015222,-0.0263278347173518,-0.0552311212900554,-0.03388131745233,-0.0139477432193303,-0.0394933828740919,-0.0740888714915354,-0.0590671943081523,142.0
201 | 0.0417084448844436,-0.044641636506989,-0.0450071887955207,0.0344962143200845,0.0438374845004259,-0.0157187066685371,0.0375951860378887,-0.0144006206784737,0.089898693277671,0.00720651632920303,90.0
202 | 0.0562385986885218,-0.044641636506989,-0.0579409336820915,-0.00796585769556799,0.0520932016496327,0.0491030249218961,0.056003375058324,-0.0214118336448964,-0.0283202425479987,0.0444854785627154,158.0
203 | -0.034574862586967,0.0506801187398187,-0.0557853095343297,-0.015999222636143,-0.00982467696941811,-0.00788999512379879,0.0375951860378887,-0.0394933828740919,-0.0529587932392004,0.0279170509033766,39.0
204 | 0.0816663678456587,0.0506801187398187,0.00133873038135806,0.0356438377699009,0.126394655992494,0.0910649188016934,0.0191869970174533,0.0343088588777263,0.0844952822124031,-0.0300724459043093,196.0
205 | -0.00188201652779104,0.0506801187398187,0.0304396563761424,0.0528581912385822,0.0397096259258226,0.0566185880048449,-0.0397192078479398,0.0712099797536354,0.0253931349154494,0.0279170509033766,222.0
206 | 0.110726675453815,0.0506801187398187,0.00672779075076256,0.0287580963824284,-0.0277120641260328,-0.00726369820021974,-0.0470824834561139,0.0343088588777263,0.00200784054982379,0.0776223338813931,277.0
207 | -0.0309423241359475,-0.044641636506989,0.0466068374843559,0.0149866136074833,-0.0167044412604238,-0.0470335528474903,0.000778807997017968,-0.00259226199818282,0.0634559213720654,-0.0259303389894746,99.0
208 | 0.00175052192322852,0.0506801187398187,0.0261284080806188,-0.00911348124867051,0.0245741444856101,0.038455977221052,-0.0213110188275045,0.0343088588777263,0.00943640914607987,0.00306440941436832,196.0
209 | 0.00901559882526763,-0.044641636506989,0.045529025410475,0.0287580963824284,0.0121905687618,-0.0138398158977999,0.0265502726256275,-0.0394933828740919,0.0461323310394148,0.036201264733046,202.0
210 | 0.030810829531385,-0.044641636506989,0.0401399650410705,0.076958286094736,0.0176943801946045,0.0378296802974729,-0.0286742944356786,0.0343088588777263,-0.00149858682029207,0.11904340302974,155.0
211 | 0.0380759064334241,0.0506801187398187,-0.0180618869484982,0.0666296740135272,-0.051103262715452,-0.0166581520539057,-0.0765355858888105,0.0343088588777263,-0.0119006848015081,-0.0135040182449705,77.0
212 | 0.00901559882526763,-0.044641636506989,0.0142724752679289,0.0149866136074833,0.054845107366035,0.0472241341511589,0.0707299262746723,-0.0394933828740919,-0.0332487872476258,-0.0590671943081523,191.0
213 | 0.0925639831987174,-0.044641636506989,0.0369065288194278,0.0218723549949558,-0.0249601584096305,-0.0166581520539057,0.000778807997017968,-0.0394933828740919,-0.0225121719296605,-0.0217882320746399,70.0
214 | 0.0671362140415805,-0.044641636506989,0.00349435452911985,0.0356438377699009,0.0493412959332305,0.0312535625998928,0.0707299262746723,-0.0394933828740919,-0.000609254186102297,0.0196328370737072,73.0
215 | 0.00175052192322852,-0.044641636506989,-0.0708746785686623,-0.0228849640236156,-0.00156895982021134,-0.00100072896442909,0.0265502726256275,-0.0394933828740919,-0.0225121719296605,0.00720651632920303,49.0
216 | 0.030810829531385,-0.044641636506989,-0.0331512559828308,-0.0228849640236156,-0.0469754041408486,-0.0811667351825494,0.103864666511456,-0.076394503750001,-0.0398095943643375,-0.0549250873933176,65.0
217 | 0.0271782910803654,0.0506801187398187,0.0940305687351156,0.0976155102571536,-0.0345918284170385,-0.0320024266815928,-0.0434008456520269,-0.00259226199818282,0.0366457977933988,0.106617082285236,263.0
218 | 0.0126481372762872,0.0506801187398187,0.0358287167455469,0.0494153205448459,0.0534691545078339,0.0741549018650587,-0.0691723102806364,0.145012221505454,0.0456008084141249,0.0486275854775501,248.0
219 | 0.0744012909436196,-0.044641636506989,0.0315174684500233,0.10105838095089,0.0465893902168282,0.0368902349121043,0.0155053592133662,-0.00259226199818282,0.0336568129023847,0.0444854785627154,296.0
220 | -0.0418399394890061,-0.044641636506989,-0.0654856181992578,-0.0400993174922969,-0.00569681839481472,0.014343545663258,-0.0434008456520269,0.0343088588777263,0.00702686254915195,-0.0135040182449705,214.0
221 | -0.0890629393522603,-0.044641636506989,-0.041773752573878,-0.0194420933298793,-0.0662387441556644,-0.0742774690231797,0.0081420836051921,-0.0394933828740919,0.00114379737951254,-0.0300724459043093,185.0
222 | 0.0235457526293458,0.0506801187398187,-0.0396181284261162,-0.00567061055493425,-0.0483513569990498,-0.0332550205287509,0.0118237214092792,-0.0394933828740919,-0.101643547945512,-0.0673514081378217,78.0
223 | -0.0454724779400257,-0.044641636506989,-0.0385403163522353,-0.0263278347173518,-0.0153284884022226,0.000878161806308105,-0.0323559322397657,-0.00259226199818282,0.00114379737951254,-0.0383566597339788,93.0
224 | -0.0236772472339084,0.0506801187398187,-0.0256065714656645,0.0425295791573734,-0.0538551684318543,-0.0476598497710694,-0.0213110188275045,-0.0394933828740919,0.00114379737951254,0.0196328370737072,252.0
225 | -0.099960554705319,-0.044641636506989,-0.0234509473179027,-0.0641994123484507,-0.0579830270064577,-0.0601857882426507,0.0118237214092792,-0.0394933828740919,-0.0181182673078967,-0.0507829804784829,150.0
226 | -0.0273097856849279,-0.044641636506989,-0.0665634302731387,-0.112399602060758,-0.0497273098572509,-0.0413968805352788,0.000778807997017968,-0.0394933828740919,-0.0358167281015492,-0.0093619113301358,77.0
227 | 0.030810829531385,0.0506801187398187,0.0325952805239042,0.0494153205448459,-0.040095639849843,-0.0435889197678055,-0.0691723102806364,0.0343088588777263,0.0630166151147464,0.00306440941436832,208.0
228 | -0.103593093156339,0.0506801187398187,-0.0460850008694016,-0.0263278347173518,-0.0249601584096305,-0.0248000120604336,0.0302319104297145,-0.0394933828740919,-0.0398095943643375,-0.0549250873933176,77.0
229 | 0.0671362140415805,0.0506801187398187,-0.0299178197611881,0.0574486853821349,-0.000193006962010205,-0.0157187066685371,0.0744115640787594,-0.0505637191368646,-0.0384591123013538,0.00720651632920303,108.0
230 | -0.0527375548420648,-0.044641636506989,-0.0126728265790937,-0.0607565416547144,-0.000193006962010205,0.00808057642746734,0.0118237214092792,-0.00259226199818282,-0.0271286455543265,-0.0507829804784829,160.0
231 | -0.0273097856849279,0.0506801187398187,-0.0159062628007364,-0.0297707054110881,0.00393485161259318,-0.000687580502639557,0.0412768238419757,-0.0394933828740919,-0.0236445575721341,0.0113486232440377,53.0
232 | -0.0382074010379866,0.0506801187398187,0.0713965151836166,-0.0573136709609782,0.153913713156516,0.155886650392127,0.000778807997017968,0.0719480021711535,0.0502764933899896,0.0693381200517237,220.0
233 | 0.00901559882526763,-0.044641636506989,-0.030995631835069,0.0218723549949558,0.00806271018719657,0.00870687335104641,0.00446044580110504,-0.00259226199818282,0.00943640914607987,0.0113486232440377,154.0
234 | 0.0126481372762872,0.0506801187398187,0.000260918307477141,-0.0114087283893043,0.0397096259258226,0.0572448849284239,-0.0397192078479398,0.0560805201945126,0.024052583226893,0.0320591578182113,259.0
235 | 0.0671362140415805,-0.044641636506989,0.0369065288194278,-0.0504279295735057,-0.0235842055514294,-0.034507614375909,0.0486400994501499,-0.0394933828740919,-0.0259524244351894,-0.0383566597339788,90.0
236 | 0.0453409833354632,-0.044641636506989,0.0390621529671896,0.0459724498511097,0.00668675732899544,-0.0241737151368545,0.0081420836051921,-0.0125555646346783,0.0643282330236709,0.0569117993072195,246.0
237 | 0.0671362140415805,0.0506801187398187,-0.0148284507268555,0.0585963091762383,-0.0593589798646588,-0.034507614375909,-0.0618090346724622,0.012906208769699,-0.00514530798026311,0.0486275854775501,124.0
238 | 0.0271782910803654,-0.044641636506989,0.00672779075076256,0.0356438377699009,0.0796122588136553,0.0707102687853738,0.0155053592133662,0.0343088588777263,0.0406722637144977,0.0113486232440377,67.0
239 | 0.0562385986885218,-0.044641636506989,-0.0687190544209005,-0.0687899065952895,-0.000193006962010205,-0.00100072896442909,0.0449584616460628,-0.0376483268302965,-0.0483617248028919,-0.00107769750046639,72.0
240 | 0.0344433679824045,0.0506801187398187,-0.00943939035745095,0.0597439326260547,-0.0359677812752396,-0.00757684666200928,-0.0765355858888105,0.0712099797536354,0.0110081010458725,-0.0217882320746399,257.0
241 | 0.0235457526293458,-0.044641636506989,0.0196615356373334,-0.0125563519424068,0.0837401173882587,0.0387691256828415,0.0633666506664982,-0.00259226199818282,0.0660482061630984,0.0486275854775501,262.0
242 | 0.0489735217864827,0.0506801187398187,0.0746299514052593,0.0666296740135272,-0.00982467696941811,-0.00225332281158722,-0.0434008456520269,0.0343088588777263,0.0336568129023847,0.0196328370737072,275.0
243 | 0.030810829531385,0.0506801187398187,-0.00836157828357004,0.00465800152627453,0.0149424744782022,0.0274957810584184,0.0081420836051921,-0.00812743012956918,-0.0295276227417736,0.0569117993072195,177.0
244 | -0.103593093156339,0.0506801187398187,-0.0234509473179027,-0.0228849640236156,-0.0868780370286814,-0.0677013513255995,-0.0176293810234174,-0.0394933828740919,-0.0781409106690696,-0.0714935150526564,71.0
245 | 0.0162806757273067,0.0506801187398187,-0.0460850008694016,0.0115437429137471,-0.0332158755588373,-0.0160318551303266,-0.0102661054152432,-0.00259226199818282,-0.0439854025655911,-0.0424987666488135,47.0
246 | -0.0600026317441039,0.0506801187398187,0.0541515220015222,-0.0194420933298793,-0.0497273098572509,-0.0489124436182275,0.0228686348215404,-0.0394933828740919,-0.0439854025655911,-0.0052198044153011,187.0
247 | -0.0273097856849279,-0.044641636506989,-0.0353068801305926,-0.0297707054110881,-0.0566070741482565,-0.058620045933703,0.0302319104297145,-0.0394933828740919,-0.0498684677352306,-0.129483011860342,125.0
248 | 0.0417084448844436,-0.044641636506989,-0.0320734439089499,-0.061904165207817,0.0796122588136553,0.0509819156926333,0.056003375058324,-0.00997248617336464,0.0450661683362615,-0.0590671943081523,78.0
249 | -0.0817978624502212,-0.044641636506989,-0.0816527993074713,-0.0400993174922969,0.00255889875439205,-0.0185370428246429,0.0707299262746723,-0.0394933828740919,-0.0109044358473771,-0.09220404962683,51.0
250 | -0.0418399394890061,-0.044641636506989,0.0476846495582368,0.0597439326260547,0.127770608850695,0.128016437292858,-0.0249926566315915,0.108111100629544,0.0638931206368394,0.0403433716478807,258.0
251 | -0.0127796318808497,-0.044641636506989,0.0606183944448076,0.0528581912385822,0.0479653430750293,0.0293746718291555,-0.0176293810234174,0.0343088588777263,0.0702112981933102,0.00720651632920303,215.0
252 | 0.0671362140415805,-0.044641636506989,0.056307146149284,0.0735154154009998,-0.0139525355440215,-0.039204841302752,-0.0323559322397657,-0.00259226199818282,0.0757375884575476,0.036201264733046,303.0
253 | -0.0527375548420648,0.0506801187398187,0.098341817030639,0.0872868981759448,0.0603489187988395,0.0487898764601065,-0.0581273968683752,0.108111100629544,0.0844952822124031,0.0403433716478807,243.0
254 | 0.00538306037424807,-0.044641636506989,0.0595405823709267,-0.0561660474078757,0.0245741444856101,0.0528608064633705,-0.0434008456520269,0.0509143632718854,-0.00421985970694603,-0.0300724459043093,91.0
255 | 0.0816663678456587,-0.044641636506989,0.0336730925977851,0.0081008722200108,0.0520932016496327,0.0566185880048449,-0.0176293810234174,0.0343088588777263,0.0348641930961596,0.0693381200517237,150.0
256 | 0.030810829531385,0.0506801187398187,0.056307146149284,0.076958286094736,0.0493412959332305,-0.0122740735888523,-0.0360375700438527,0.0712099797536354,0.120053382001538,0.0900486546258972,310.0
257 | 0.00175052192322852,-0.044641636506989,-0.0654856181992578,-0.00567061055493425,-0.00707277125301585,-0.0194764882100115,0.0412768238419757,-0.0394933828740919,-0.003303712578677,0.00720651632920303,153.0
258 | -0.0491050163910452,-0.044641636506989,0.160854917315731,-0.0469850588797694,-0.0290880169842339,-0.019789636671801,-0.0470824834561139,0.0343088588777263,0.028016506523264,0.0113486232440377,346.0
259 | -0.0273097856849279,0.0506801187398187,-0.0557853095343297,0.0253152256886921,-0.00707277125301585,-0.0235474182132754,0.052321737254237,-0.0394933828740919,-0.00514530798026311,-0.0507829804784829,63.0
260 | 0.0780338293946392,0.0506801187398187,-0.0245287593917836,-0.0423945646329306,0.00668675732899544,0.0528608064633705,-0.0691723102806364,0.0808042711813717,-0.0371283460104736,0.0569117993072195,89.0
261 | 0.0126481372762872,-0.044641636506989,-0.0363846922044735,0.0425295791573734,-0.0139525355440215,0.0129343775852051,-0.0268334755336351,0.00515697338575809,-0.0439854025655911,0.00720651632920303,50.0
262 | 0.0417084448844436,-0.044641636506989,-0.00836157828357004,-0.0573136709609782,0.00806271018719657,-0.0313761297580137,0.151725957964588,-0.076394503750001,-0.0802365402489018,-0.0176461251598052,39.0
263 | 0.0489735217864827,-0.044641636506989,-0.041773752573878,0.104501251644626,0.0355817673512192,-0.0257394574458021,0.177497422593197,-0.076394503750001,-0.0129079422541688,0.0154907301588724,103.0
264 | -0.0164121703318693,0.0506801187398187,0.127442743025423,0.0976155102571536,0.0163184273364034,0.0174750302811533,-0.0213110188275045,0.0343088588777263,0.0348641930961596,0.00306440941436832,308.0
265 | -0.0745327855481821,0.0506801187398187,-0.0773415510119477,-0.0469850588797694,-0.0469754041408486,-0.0326287236051719,0.00446044580110504,-0.0394933828740919,-0.072128454601956,-0.0176461251598052,116.0
266 | 0.0344433679824045,0.0506801187398187,0.0282840322283806,-0.0332135761048244,-0.0455994512826475,-0.00976888589453599,-0.050764121260201,-0.00259226199818282,-0.0594726974107223,-0.0217882320746399,145.0
267 | -0.034574862586967,0.0506801187398187,-0.0256065714656645,-0.0171468461892456,0.00118294589619092,-0.00287961973516629,0.0081420836051921,-0.015507654304751,0.0148227108412663,0.0403433716478807,74.0
268 | -0.0527375548420648,0.0506801187398187,-0.0622521819776151,0.0115437429137471,-0.00844872411121698,-0.0366996536084358,0.122272855531891,-0.076394503750001,-0.0868289932162924,0.00306440941436832,45.0
269 | 0.0598711371395414,-0.044641636506989,-0.000816893766403737,-0.0848566365108683,0.075484400239052,0.0794784257154807,0.00446044580110504,0.0343088588777263,0.0233748412798208,0.0279170509033766,115.0
270 | 0.063503675590561,0.0506801187398187,0.088641508365711,0.0700725447072635,0.0204462859110067,0.0375165318356834,-0.050764121260201,0.0712099797536354,0.0293004132685869,0.0734802269665584,264.0
271 | 0.00901559882526763,-0.044641636506989,-0.0320734439089499,-0.0263278347173518,0.0424615316422248,-0.0103951828181151,0.159089233572762,-0.076394503750001,-0.0119006848015081,-0.0383566597339788,87.0
272 | 0.00538306037424807,0.0506801187398187,0.0304396563761424,0.0838440274822086,-0.0373437341334407,-0.0473467013092799,0.0155053592133662,-0.0394933828740919,0.00864028293306308,0.0154907301588724,202.0
273 | 0.0380759064334241,0.0506801187398187,0.00888341489852436,0.0425295791573734,-0.0428475455662452,-0.0210422305189592,-0.0397192078479398,-0.00259226199818282,-0.0181182673078967,0.00720651632920303,127.0
274 | 0.0126481372762872,-0.044641636506989,0.00672779075076256,-0.0561660474078757,-0.0758704141630723,-0.0664487574784414,-0.0213110188275045,-0.0376483268302965,-0.0181182673078967,-0.09220404962683,182.0
275 | 0.0744012909436196,0.0506801187398187,-0.02021751109626,0.0459724498511097,0.0741084473808508,0.0328193049088404,-0.0360375700438527,0.0712099797536354,0.106354276741726,0.036201264733046,241.0
276 | 0.0162806757273067,-0.044641636506989,-0.0245287593917836,0.0356438377699009,-0.00707277125301585,-0.00319276819695581,-0.0139477432193303,-0.00259226199818282,0.0155668445407018,0.0154907301588724,66.0
277 | -0.00551455497881059,0.0506801187398187,-0.0115950145052127,0.0115437429137471,-0.0222082526932283,-0.0154055582067476,-0.0213110188275045,-0.00259226199818282,0.0110081010458725,0.0693381200517237,94.0
278 | 0.0126481372762872,-0.044641636506989,0.0261284080806188,0.063186803319791,0.125018703134293,0.0916912157252725,0.0633666506664982,-0.00259226199818282,0.057572856202426,-0.0217882320746399,283.0
279 | -0.034574862586967,-0.044641636506989,-0.0590187457559724,0.00121513083253827,-0.0538551684318543,-0.078035250564654,0.0670482884705852,-0.076394503750001,-0.02139368094036,0.0154907301588724,64.0
280 | 0.0671362140415805,0.0506801187398187,-0.0363846922044735,-0.0848566365108683,-0.00707277125301585,0.01966706951368,-0.0544457590642881,0.0343088588777263,0.00114379737951254,0.0320591578182113,102.0
281 | 0.0380759064334241,0.0506801187398187,-0.0245287593917836,0.00465800152627453,-0.0263361112678317,-0.0263657543693812,0.0155053592133662,-0.0394933828740919,-0.0159982677581387,-0.0259303389894746,200.0
282 | 0.00901559882526763,0.0506801187398187,0.0185837235634525,0.0390867084636372,0.0176943801946045,0.0105857641217836,0.0191869970174533,-0.00259226199818282,0.0163049527999418,-0.0176461251598052,265.0
283 | -0.0926954778032799,0.0506801187398187,-0.0902752958985185,-0.0573136709609782,-0.0249601584096305,-0.0304366843726451,-0.00658446761115617,-0.00259226199818282,0.024052583226893,0.00306440941436832,94.0
284 | 0.0707687524926,-0.044641636506989,-0.00512814206192736,-0.00567061055493425,0.0878679759628621,0.102964560349696,0.0118237214092792,0.0343088588777263,-0.0089440189577978,0.0279170509033766,230.0
285 | -0.0164121703318693,-0.044641636506989,-0.052551873312687,-0.0332135761048244,-0.0442234984244464,-0.0363865051466462,0.0191869970174533,-0.0394933828740919,-0.0683297436244215,-0.0300724459043093,181.0
286 | 0.0417084448844436,0.0506801187398187,-0.0223731352440218,0.0287580963824284,-0.0662387441556644,-0.0451546620767532,-0.0618090346724622,-0.00259226199818282,0.00286377051894013,-0.0549250873933176,156.0
287 | 0.0126481372762872,-0.044641636506989,-0.02021751109626,-0.015999222636143,0.0121905687618,0.0212328118226277,-0.0765355858888105,0.108111100629544,0.0598807230654812,-0.0217882320746399,233.0
288 | -0.0382074010379866,-0.044641636506989,-0.0547074974604488,-0.0779708951233958,-0.0332158755588373,-0.0864902590329714,0.140681044552327,-0.076394503750001,-0.0191970476139445,-0.0052198044153011,60.0
289 | 0.0453409833354632,-0.044641636506989,-0.00620595413580824,-0.015999222636143,0.125018703134293,0.125198101136752,0.0191869970174533,0.0343088588777263,0.0324332257796019,-0.0052198044153011,219.0
290 | 0.0707687524926,0.0506801187398187,-0.0169840748746173,0.0218723549949558,0.0438374845004259,0.0563054395430553,0.0375951860378887,-0.00259226199818282,-0.0702093127286876,-0.0176461251598052,80.0
291 | -0.0745327855481821,0.0506801187398187,0.0552293340754031,-0.0400993174922969,0.0534691545078339,0.05317395492516,-0.0434008456520269,0.0712099797536354,0.061237907519701,-0.0342145528191441,68.0
292 | 0.0598711371395414,0.0506801187398187,0.0767855755530211,0.0253152256886921,0.00118294589619092,0.0168487333575743,-0.0544457590642881,0.0343088588777263,0.0299356483965325,0.0444854785627154,332.0
293 | 0.0744012909436196,-0.044641636506989,0.0185837235634525,0.063186803319791,0.0617248716570406,0.0428400556861055,0.0081420836051921,-0.00259226199818282,0.0580391276638951,-0.0590671943081523,248.0
294 | 0.00901559882526763,-0.044641636506989,-0.0223731352440218,-0.0320659525517218,-0.0497273098572509,-0.0686407967109681,0.0780932018828464,-0.0708593356186146,-0.0629129499162512,-0.0383566597339788,84.0
295 | -0.0709002470971626,-0.044641636506989,0.0929527566612346,0.0126913664668496,0.0204462859110067,0.0425269072243159,0.000778807997017968,0.000359827671889909,-0.0545441527110952,-0.00107769750046639,200.0
296 | 0.0235457526293458,0.0506801187398187,-0.030995631835069,-0.00567061055493425,-0.0167044412604238,0.0177881787429428,-0.0323559322397657,-0.00259226199818282,-0.0740888714915354,-0.0342145528191441,55.0
297 | -0.0527375548420648,0.0506801187398187,0.0390621529671896,-0.0400993174922969,-0.00569681839481472,-0.0129003705124313,0.0118237214092792,-0.0394933828740919,0.0163049527999418,0.00306440941436832,85.0
298 | 0.0671362140415805,-0.044641636506989,-0.0611743699037342,-0.0400993174922969,-0.0263361112678317,-0.024486863598644,0.0339135482338016,-0.0394933828740919,-0.0561575730950062,-0.0590671943081523,89.0
299 | 0.00175052192322852,-0.044641636506989,-0.00836157828357004,-0.0641994123484507,-0.0387196869916418,-0.024486863598644,0.00446044580110504,-0.0394933828740919,-0.0646830224644503,-0.0549250873933176,31.0
300 | 0.0235457526293458,0.0506801187398187,-0.0374625042783544,-0.0469850588797694,-0.0910058956032848,-0.0755300628703378,-0.0323559322397657,-0.0394933828740919,-0.0307512098645563,-0.0135040182449705,129.0
301 | 0.0380759064334241,0.0506801187398187,-0.0137506386529745,-0.015999222636143,-0.0359677812752396,-0.0219816759043277,-0.0139477432193303,-0.00259226199818282,-0.0259524244351894,-0.00107769750046639,83.0
302 | 0.0162806757273067,-0.044641636506989,0.0735521393313785,-0.0412469410453994,-0.00432086553661359,-0.0135266674360104,-0.0139477432193303,-0.00111621716314646,0.0428956878925287,0.0444854785627154,275.0
303 | -0.00188201652779104,0.0506801187398187,-0.0245287593917836,0.0528581912385822,0.0273260502020124,0.0300009687527346,0.0302319104297145,-0.00259226199818282,-0.02139368094036,0.036201264733046,65.0
304 | 0.0126481372762872,-0.044641636506989,0.0336730925977851,0.0333485905259811,0.0300779559184146,0.0271826325966288,-0.0029028298070691,0.00884708547334898,0.0311929907028023,0.0279170509033766,198.0
305 | 0.0744012909436196,-0.044641636506989,0.034750904671666,0.0941726395634173,0.0575970130824372,0.0202933664372591,0.0228686348215404,-0.00259226199818282,0.0738021469200488,-0.0217882320746399,236.0
306 | 0.0417084448844436,0.0506801187398187,-0.0385403163522353,0.0528581912385822,0.0768603530972531,0.116429944206646,-0.0397192078479398,0.0712099797536354,-0.0225121719296605,-0.0135040182449705,253.0
307 | -0.00914709342983014,0.0506801187398187,-0.0396181284261162,-0.0400993174922969,-0.00844872411121698,0.0162224364339952,-0.0654906724765493,0.0712099797536354,0.0177634778671173,-0.0673514081378217,124.0
308 | 0.00901559882526763,0.0506801187398187,-0.00189470584028465,0.0218723549949558,-0.0387196869916418,-0.0248000120604336,-0.00658446761115617,-0.0394933828740919,-0.0398095943643375,-0.0135040182449705,44.0
309 | 0.0671362140415805,0.0506801187398187,-0.030995631835069,0.00465800152627453,0.0245741444856101,0.0356376410649462,-0.0286742944356786,0.0343088588777263,0.0233748412798208,0.0817644407962278,172.0
310 | 0.00175052192322852,-0.044641636506989,-0.0460850008694016,-0.0332135761048244,-0.07311850844667,-0.0814798836443389,0.0449584616460628,-0.0693832907835783,-0.0611765950943345,-0.0797777288823259,114.0
311 | -0.00914709342983014,0.0506801187398187,0.00133873038135806,-0.00222773986119799,0.0796122588136553,0.0700839718617947,0.0339135482338016,-0.00259226199818282,0.0267142576335128,0.0817644407962278,142.0
312 | -0.00551455497881059,-0.044641636506989,0.0649296427403312,0.0356438377699009,-0.00156895982021134,0.0149698425868371,-0.0139477432193303,0.000728838880648992,-0.0181182673078967,0.0320591578182113,109.0
313 | 0.096196521649737,-0.044641636506989,0.0401399650410705,-0.0573136709609782,0.0452134373586271,0.0606895180081088,-0.0213110188275045,0.0361539149215217,0.0125531528133893,0.0237749439885419,180.0
314 | -0.0745327855481821,-0.044641636506989,-0.0234509473179027,-0.00567061055493425,-0.0208322998350272,-0.0141529643595894,0.0155053592133662,-0.0394933828740919,-0.0384591123013538,-0.0300724459043093,144.0
315 | 0.0598711371395414,0.0506801187398187,0.0530737099276413,0.0528581912385822,0.0328298616348169,0.01966706951368,-0.0102661054152432,0.0343088588777263,0.0552050380896167,-0.00107769750046639,163.0
316 | -0.0236772472339084,-0.044641636506989,0.0401399650410705,-0.0125563519424068,-0.00982467696941811,-0.00100072896442909,-0.0029028298070691,-0.00259226199818282,-0.0119006848015081,-0.0383566597339788,147.0
317 | 0.00901559882526763,-0.044641636506989,-0.02021751109626,-0.0538708002672419,0.0314539087766158,0.0206065148990486,0.056003375058324,-0.0394933828740919,-0.0109044358473771,-0.00107769750046639,97.0
318 | 0.0162806757273067,0.0506801187398187,0.0142724752679289,0.00121513083253827,0.00118294589619092,-0.0213553789807487,-0.0323559322397657,0.0343088588777263,0.0749683360277342,0.0403433716478807,220.0
319 | 0.0199132141783263,-0.044641636506989,-0.0342290680567117,0.055153438482502,0.0672286830898452,0.0741549018650587,-0.00658446761115617,0.0328328140426899,0.0247253233428045,0.0693381200517237,190.0
320 | 0.0889314447476978,-0.044641636506989,0.00672779075076256,0.0253152256886921,0.0300779559184146,0.00870687335104641,0.0633666506664982,-0.0394933828740919,0.00943640914607987,0.0320591578182113,109.0
321 | 0.0199132141783263,-0.044641636506989,0.00457216660300077,0.0459724498511097,-0.0180803941186249,-0.0545491159304391,0.0633666506664982,-0.0394933828740919,0.0286607203138089,0.0610539062220542,191.0
322 | -0.0236772472339084,-0.044641636506989,0.0304396563761424,-0.00567061055493425,0.0823641645300576,0.092004364187062,-0.0176293810234174,0.0712099797536354,0.0330470723549341,0.00306440941436832,122.0
323 | 0.096196521649737,-0.044641636506989,0.0519958978537604,0.0792535333386559,0.054845107366035,0.0365770864503148,-0.0765355858888105,0.141322109417863,0.098646374304928,0.0610539062220542,230.0
324 | 0.0235457526293458,0.0506801187398187,0.0616962065186885,0.0620391798699746,0.0245741444856101,-0.0360733566848567,-0.0912621371051588,0.155344535350708,0.133395733837469,0.0817644407962278,242.0
325 | 0.0707687524926,0.0506801187398187,-0.00728376620968916,0.0494153205448459,0.0603489187988395,-0.00444536204411395,-0.0544457590642881,0.108111100629544,0.129019411600168,0.0569117993072195,248.0
326 | 0.030810829531385,-0.044641636506989,0.00564997867688165,0.0115437429137471,0.0782363059554542,0.077912683406533,-0.0434008456520269,0.108111100629544,0.0660482061630984,0.0196328370737072,249.0
327 | -0.00188201652779104,-0.044641636506989,0.0541515220015222,-0.0664946594890845,0.0727324945226497,0.0566185880048449,-0.0434008456520269,0.0848633944777217,0.0844952822124031,0.0486275854775501,192.0
328 | 0.0453409833354632,0.0506801187398187,-0.00836157828357004,-0.0332135761048244,-0.00707277125301585,0.00119131026809764,-0.0397192078479398,0.0343088588777263,0.0299356483965325,0.0279170509033766,131.0
329 | 0.0744012909436196,-0.044641636506989,0.114508998138853,0.0287580963824284,0.0245741444856101,0.0249905933641021,0.0191869970174533,-0.00259226199818282,-0.000609254186102297,-0.0052198044153011,237.0
330 | -0.0382074010379866,-0.044641636506989,0.067085266888093,-0.0607565416547144,-0.0290880169842339,-0.0232342697514859,-0.0102661054152432,-0.00259226199818282,-0.00149858682029207,0.0196328370737072,78.0
331 | -0.0127796318808497,0.0506801187398187,-0.0557853095343297,-0.00222773986119799,-0.0277120641260328,-0.029184090525487,0.0191869970174533,-0.0394933828740919,-0.0170521046047435,0.0444854785627154,135.0
332 | 0.00901559882526763,0.0506801187398187,0.0304396563761424,0.0425295791573734,-0.00294491267841247,0.0368902349121043,-0.0654906724765493,0.0712099797536354,-0.0236445575721341,0.0154907301588724,244.0
333 | 0.0816663678456587,0.0506801187398187,-0.0256065714656645,-0.0366564467985606,-0.0703666027302678,-0.0464072559239113,-0.0397192078479398,-0.00259226199818282,-0.0411803851880079,-0.0052198044153011,199.0
334 | 0.030810829531385,-0.044641636506989,0.104808689473925,0.076958286094736,-0.0112006298276192,-0.0113346282034837,-0.0581273968683752,0.0343088588777263,0.0571041874478439,0.036201264733046,270.0
335 | 0.0271782910803654,0.0506801187398187,-0.00620595413580824,0.0287580963824284,-0.0167044412604238,-0.00162702588800815,-0.0581273968683752,0.0343088588777263,0.0293004132685869,0.0320591578182113,164.0
336 | -0.0600026317441039,0.0506801187398187,-0.0471628129432825,-0.0228849640236156,-0.071742555588469,-0.0576806005483345,-0.00658446761115617,-0.0394933828740919,-0.0629129499162512,-0.0549250873933176,72.0
337 | 0.00538306037424807,-0.044641636506989,-0.0482406250171634,-0.0125563519424068,0.00118294589619092,-0.00663740127664067,0.0633666506664982,-0.0394933828740919,-0.0514005352605825,-0.0590671943081523,96.0
338 | -0.0200447087828888,-0.044641636506989,0.0854080721440683,-0.0366564467985606,0.0919958345374655,0.0894991764927457,-0.0618090346724622,0.145012221505454,0.0809479135112756,0.0527696923923848,306.0
339 | 0.0199132141783263,0.0506801187398187,-0.0126728265790937,0.0700725447072635,-0.0112006298276192,0.00714113104209875,-0.0397192078479398,0.0343088588777263,0.00538436996854573,0.00306440941436832,91.0
340 | -0.0636351701951234,-0.044641636506989,-0.0331512559828308,-0.0332135761048244,0.00118294589619092,0.0240511479787335,-0.0249926566315915,-0.00259226199818282,-0.0225121719296605,-0.0590671943081523,214.0
341 | 0.0271782910803654,-0.044641636506989,-0.00728376620968916,-0.0504279295735057,0.075484400239052,0.0566185880048449,0.0339135482338016,-0.00259226199818282,0.0434431722527813,0.0154907301588724,95.0
342 | -0.0164121703318693,-0.044641636506989,-0.0137506386529745,0.132044217194516,-0.00982467696941811,-0.00381906512053488,0.0191869970174533,-0.0394933828740919,-0.0358167281015492,-0.0300724459043093,216.0
343 | 0.030810829531385,0.0506801187398187,0.0595405823709267,0.0563010619323185,-0.0222082526932283,0.00119131026809764,-0.0323559322397657,-0.00259226199818282,-0.0247911874324607,-0.0176461251598052,263.0
344 | 0.0562385986885218,0.0506801187398187,0.0218171597850952,0.0563010619323185,-0.00707277125301585,0.0181013272047324,-0.0323559322397657,-0.00259226199818282,-0.0236445575721341,0.0237749439885419,178.0
345 | -0.0200447087828888,-0.044641636506989,0.0185837235634525,0.090729768869681,0.00393485161259318,0.00870687335104641,0.0375951860378887,-0.0394933828740919,-0.0578000656756125,0.00720651632920303,113.0
346 | -0.107225631607358,-0.044641636506989,-0.0115950145052127,-0.0400993174922969,0.0493412959332305,0.0644472995495832,-0.0139477432193303,0.0343088588777263,0.00702686254915195,-0.0300724459043093,200.0
347 | 0.0816663678456587,0.0506801187398187,-0.00297251791416553,-0.0332135761048244,0.0424615316422248,0.057871181852003,-0.0102661054152432,0.0343088588777263,-0.000609254186102297,-0.00107769750046639,139.0
348 | 0.00538306037424807,0.0506801187398187,0.0175059114895716,0.0322009670761646,0.127770608850695,0.127390140369279,-0.0213110188275045,0.0712099797536354,0.062575181458056,0.0154907301588724,139.0
349 | 0.0380759064334241,0.0506801187398187,-0.0299178197611881,-0.0745280244296595,-0.0125765826858204,-0.0125872220506418,0.00446044580110504,-0.00259226199818282,0.00371173823343597,-0.0300724459043093,88.0
350 | 0.030810829531385,-0.044641636506989,-0.02021751109626,-0.00567061055493425,-0.00432086553661359,-0.0294972389872765,0.0780932018828464,-0.0394933828740919,-0.0109044358473771,-0.00107769750046639,148.0
351 | 0.00175052192322852,0.0506801187398187,-0.0579409336820915,-0.0435421881860331,-0.0965097070360893,-0.0470335528474903,-0.098625412713333,0.0343088588777263,-0.0611765950943345,-0.0714935150526564,88.0
352 | -0.0273097856849279,0.0506801187398187,0.0606183944448076,0.107944122338362,0.0121905687618,-0.0175975974392743,-0.0029028298070691,-0.00259226199818282,0.0702112981933102,0.135611830689079,243.0
353 | -0.0854304009012408,0.0506801187398187,-0.0406959404999971,-0.0332135761048244,-0.0813742255958769,-0.0695802420963367,-0.00658446761115617,-0.0394933828740919,-0.0578000656756125,-0.0424987666488135,71.0
354 | 0.0126481372762872,0.0506801187398187,-0.0719524906425432,-0.0469850588797694,-0.051103262715452,-0.0971373067338155,0.118591217727804,-0.076394503750001,-0.0202887477516296,-0.0383566597339788,77.0
355 | -0.0527375548420648,-0.044641636506989,-0.0557853095343297,-0.0366564467985606,0.0892439288210632,-0.00319276819695581,0.0081420836051921,0.0343088588777263,0.132372649338676,0.00306440941436832,109.0
356 | -0.0236772472339084,0.0506801187398187,0.045529025410475,0.0218723549949558,0.10988322169408,0.0888728795691667,0.000778807997017968,0.0343088588777263,0.0741925366900307,0.0610539062220542,272.0
357 | -0.0745327855481821,0.0506801187398187,-0.00943939035745095,0.0149866136074833,-0.0373437341334407,-0.0216685274425382,-0.0139477432193303,-0.00259226199818282,-0.0332487872476258,0.0113486232440377,60.0
358 | -0.00551455497881059,0.0506801187398187,-0.0331512559828308,-0.015999222636143,0.00806271018719657,0.0162224364339952,0.0155053592133662,-0.00259226199818282,-0.0283202425479987,-0.0756356219674911,54.0
359 | -0.0600026317441039,0.0506801187398187,0.0498402737059986,0.0184294843012196,-0.0167044412604238,-0.0301235359108556,-0.0176293810234174,-0.00259226199818282,0.049768659920749,-0.0590671943081523,221.0
360 | -0.0200447087828888,-0.044641636506989,-0.084886235529114,-0.0263278347173518,-0.0359677812752396,-0.0341944659141195,0.0412768238419757,-0.0516707527631419,-0.0823814832581028,-0.0466408735636482,90.0
361 | 0.0380759064334241,0.0506801187398187,0.00564997867688165,0.0322009670761646,0.00668675732899544,0.0174750302811533,-0.0249926566315915,0.0343088588777263,0.0148227108412663,0.0610539062220542,311.0
362 | 0.0162806757273067,-0.044641636506989,0.0207393477112143,0.0218723549949558,-0.0139525355440215,-0.0132135189742209,-0.00658446761115617,-0.00259226199818282,0.0133159679089277,0.0403433716478807,281.0
363 | 0.0417084448844436,-0.044641636506989,-0.00728376620968916,0.0287580963824284,-0.0428475455662452,-0.0482861466946485,0.052321737254237,-0.076394503750001,-0.072128454601956,0.0237749439885419,182.0
364 | 0.0199132141783263,0.0506801187398187,0.104808689473925,0.0700725447072635,-0.0359677812752396,-0.0266789028311707,-0.0249926566315915,-0.00259226199818282,0.00371173823343597,0.0403433716478807,321.0
365 | -0.0491050163910452,0.0506801187398187,-0.0245287593917836,6.75072794357462e-05,-0.0469754041408486,-0.0282446451401184,-0.0654906724765493,0.0284046795375808,0.0191990330785671,0.0113486232440377,58.0
366 | 0.00175052192322852,0.0506801187398187,-0.00620595413580824,-0.0194420933298793,-0.00982467696941811,0.00494909180957202,-0.0397192078479398,0.0343088588777263,0.0148227108412663,0.0983328684555666,262.0
367 | 0.0344433679824045,-0.044641636506989,-0.0385403163522353,-0.0125563519424068,0.0094386630453977,0.00526224027136155,-0.00658446761115617,-0.00259226199818282,0.0311929907028023,0.0983328684555666,206.0
368 | -0.0454724779400257,0.0506801187398187,0.137143051690352,-0.015999222636143,0.0410855787840237,0.0318798595234718,-0.0434008456520269,0.0712099797536354,0.0710215779459822,0.0486275854775501,233.0
369 | -0.00914709342983014,0.0506801187398187,0.17055522598066,0.0149866136074833,0.0300779559184146,0.033758750294209,-0.0213110188275045,0.0343088588777263,0.0336568129023847,0.0320591578182113,242.0
370 | -0.0164121703318693,0.0506801187398187,0.00241654245523897,0.0149866136074833,0.0218222387692079,-0.0100820343563255,-0.0249926566315915,0.0343088588777263,0.085533121187439,0.0817644407962278,123.0
371 | -0.00914709342983014,-0.044641636506989,0.0379843408933087,-0.0400993174922969,-0.0249601584096305,-0.00381906512053488,-0.0434008456520269,0.0158582984397717,-0.00514530798026311,0.0279170509033766,167.0
372 | 0.0199132141783263,-0.044641636506989,-0.0579409336820915,-0.0573136709609782,-0.00156895982021134,-0.0125872220506418,0.0744115640787594,-0.0394933828740919,-0.0611765950943345,-0.0756356219674911,63.0
373 | 0.0526060602375023,0.0506801187398187,-0.00943939035745095,0.0494153205448459,0.0507172487914316,-0.019163339748222,-0.0139477432193303,0.0343088588777263,0.119343994203787,-0.0176461251598052,197.0
374 | -0.0273097856849279,0.0506801187398187,-0.0234509473179027,-0.015999222636143,0.0135665216200011,0.0127778033543103,0.0265502726256275,-0.00259226199818282,-0.0109044358473771,-0.0217882320746399,71.0
375 | -0.0745327855481821,-0.044641636506989,-0.0105172024313319,-0.00567061055493425,-0.0662387441556644,-0.0570543036247554,-0.0029028298070691,-0.0394933828740919,-0.0425721049227942,-0.00107769750046639,168.0
376 | -0.107225631607358,-0.044641636506989,-0.0342290680567117,-0.067642283042187,-0.0634868384392622,-0.0705196874817053,0.0081420836051921,-0.0394933828740919,-0.000609254186102297,-0.0797777288823259,140.0
377 | 0.0453409833354632,0.0506801187398187,-0.00297251791416553,0.107944122338362,0.0355817673512192,0.0224854056697859,0.0265502726256275,-0.00259226199818282,0.028016506523264,0.0196328370737072,217.0
378 | -0.00188201652779104,-0.044641636506989,0.068163078961974,-0.00567061055493425,0.119514891701488,0.130208476525385,-0.0249926566315915,0.0867084505215172,0.0461323310394148,-0.00107769750046639,121.0
379 | 0.0199132141783263,0.0506801187398187,0.00996122697240527,0.0184294843012196,0.0149424744782022,0.0447189464568426,-0.0618090346724622,0.0712099797536354,0.00943640914607987,-0.063209301222987,235.0
380 | 0.0162806757273067,0.0506801187398187,0.00241654245523897,-0.00567061055493425,-0.00569681839481472,0.0108989125835731,-0.050764121260201,0.0343088588777263,0.0226920225667445,-0.0383566597339788,245.0
381 | -0.00188201652779104,-0.044641636506989,-0.0385403163522353,0.0218723549949558,-0.108893282759899,-0.115613065979398,0.0228686348215404,-0.076394503750001,-0.0468794828442166,0.0237749439885419,40.0
382 | 0.0162806757273067,-0.044641636506989,0.0261284080806188,0.0585963091762383,-0.0607349327228599,-0.0442152166913845,-0.0139477432193303,-0.0339582147427055,-0.0514005352605825,-0.0259303389894746,52.0
383 | -0.0709002470971626,0.0506801187398187,-0.0891974838246376,-0.0745280244296595,-0.0428475455662452,-0.0257394574458021,-0.0323559322397657,-0.00259226199818282,-0.0129079422541688,-0.0549250873933176,104.0
384 | 0.0489735217864827,-0.044641636506989,0.0606183944448076,-0.0228849640236156,-0.0235842055514294,-0.072711726714232,-0.0434008456520269,-0.00259226199818282,0.104137611358979,0.036201264733046,132.0
385 | 0.00538306037424807,0.0506801187398187,-0.0288400076873072,-0.00911348124867051,-0.0318399227006362,-0.0288709420636975,0.0081420836051921,-0.0394933828740919,-0.0181182673078967,0.00720651632920303,88.0
386 | 0.0344433679824045,0.0506801187398187,-0.0299178197611881,0.00465800152627453,0.0933717873956666,0.0869939887984295,0.0339135482338016,-0.00259226199818282,0.024052583226893,-0.0383566597339788,69.0
387 | 0.0235457526293458,0.0506801187398187,-0.019139699022379,0.0494153205448459,-0.0634868384392622,-0.0611252336280193,0.00446044580110504,-0.0394933828740919,-0.0259524244351894,-0.0135040182449705,219.0
388 | 0.0199132141783263,-0.044641636506989,-0.0406959404999971,-0.015999222636143,-0.00844872411121698,-0.0175975974392743,0.052321737254237,-0.0394933828740919,-0.0307512098645563,0.00306440941436832,72.0
389 | -0.0454724779400257,-0.044641636506989,0.0153502873418098,-0.0745280244296595,-0.0497273098572509,-0.0172844489774848,-0.0286742944356786,-0.00259226199818282,-0.104364820832166,-0.0756356219674911,201.0
390 | 0.0526060602375023,0.0506801187398187,-0.0245287593917836,0.0563010619323185,-0.00707277125301585,-0.005071658967693,-0.0213110188275045,-0.00259226199818282,0.0267142576335128,-0.0383566597339788,110.0
391 | -0.00551455497881059,0.0506801187398187,0.00133873038135806,-0.0848566365108683,-0.0112006298276192,-0.0166581520539057,0.0486400994501499,-0.0394933828740919,-0.0411803851880079,-0.0880619427119953,51.0
392 | 0.00901559882526763,0.0506801187398187,0.0692408910358548,0.0597439326260547,0.0176943801946045,-0.0232342697514859,-0.0470824834561139,0.0343088588777263,0.103292264911524,0.0734802269665584,277.0
393 | -0.0236772472339084,-0.044641636506989,-0.0697968664947814,-0.0641994123484507,-0.0593589798646588,-0.0504781859271752,0.0191869970174533,-0.0394933828740919,-0.0891368600793477,-0.0507829804784829,63.0
394 | -0.0418399394890061,0.0506801187398187,-0.0299178197611881,-0.00222773986119799,0.0218222387692079,0.0365770864503148,0.0118237214092792,-0.00259226199818282,-0.0411803851880079,0.065196013136889,118.0
395 | -0.0745327855481821,-0.044641636506989,-0.0460850008694016,-0.0435421881860331,-0.0290880169842339,-0.0232342697514859,0.0155053592133662,-0.0394933828740919,-0.0398095943643375,-0.0217882320746399,69.0
396 | 0.0344433679824045,-0.044641636506989,0.0185837235634525,0.0563010619323185,0.0121905687618,-0.0545491159304391,-0.0691723102806364,0.0712099797536354,0.130080609521753,0.00720651632920303,273.0
397 | -0.0600026317441039,-0.044641636506989,0.00133873038135806,-0.0297707054110881,-0.00707277125301585,-0.0216685274425382,0.0118237214092792,-0.00259226199818282,0.0318152175007986,-0.0549250873933176,258.0
398 | -0.0854304009012408,0.0506801187398187,-0.030995631835069,-0.0228849640236156,-0.0634868384392622,-0.0542359674686496,0.0191869970174533,-0.0394933828740919,-0.096433222891784,-0.0342145528191441,43.0
399 | 0.0526060602375023,-0.044641636506989,-0.00405032998804645,-0.0309183289641906,-0.0469754041408486,-0.0583068974719135,-0.0139477432193303,-0.0258399681500055,0.0360557900898319,0.0237749439885419,198.0
400 | 0.0126481372762872,-0.044641636506989,0.0153502873418098,-0.0332135761048244,0.0410855787840237,0.0321930079852613,-0.0029028298070691,-0.00259226199818282,0.0450661683362615,-0.0673514081378217,242.0
401 | 0.0598711371395414,0.0506801187398187,0.0228949718589761,0.0494153205448459,0.0163184273364034,0.0118383579689417,-0.0139477432193303,-0.00259226199818282,0.0395398780720242,0.0196328370737072,232.0
402 | -0.0236772472339084,-0.044641636506989,0.045529025410475,0.090729768869681,-0.0180803941186249,-0.0354470597612776,0.0707299262746723,-0.0394933828740919,-0.0345237153303495,-0.0093619113301358,175.0
403 | 0.0162806757273067,-0.044641636506989,-0.0450071887955207,-0.0573136709609782,-0.0345918284170385,-0.05392281900686,0.0744115640787594,-0.076394503750001,-0.0425721049227942,0.0403433716478807,93.0
404 | 0.110726675453815,0.0506801187398187,-0.0331512559828308,-0.0228849640236156,-0.00432086553661359,0.0202933664372591,-0.0618090346724622,0.0712099797536354,0.0155668445407018,0.0444854785627154,168.0
405 | -0.0200447087828888,-0.044641636506989,0.0972640049567582,-0.00567061055493425,-0.00569681839481472,-0.0238605666750649,-0.0213110188275045,-0.00259226199818282,0.0616858488238662,0.0403433716478807,275.0
406 | -0.0164121703318693,-0.044641636506989,0.0541515220015222,0.0700725447072635,-0.0332158755588373,-0.0279314966783289,0.0081420836051921,-0.0394933828740919,-0.0271286455543265,-0.0093619113301358,293.0
407 | 0.0489735217864827,0.0506801187398187,0.1231314947299,0.0838440274822086,-0.104765424185296,-0.10089508827529,-0.0691723102806364,-0.00259226199818282,0.0366457977933988,-0.0300724459043093,281.0
408 | -0.0563700932930843,-0.044641636506989,-0.0805749872335904,-0.0848566365108683,-0.0373437341334407,-0.0370128020702253,0.0339135482338016,-0.0394933828740919,-0.0561575730950062,-0.137767225690012,72.0
409 | 0.0271782910803654,-0.044641636506989,0.0929527566612346,-0.0527231767141394,0.00806271018719657,0.0397085710682101,-0.0286742944356786,0.021024455362399,-0.0483617248028919,0.0196328370737072,140.0
410 | 0.063503675590561,-0.044641636506989,-0.0503962491649252,0.107944122338362,0.0314539087766158,0.0193539210518905,-0.0176293810234174,0.0236075338237126,0.0580391276638951,0.0403433716478807,189.0
411 | -0.0527375548420648,0.0506801187398187,-0.0115950145052127,0.0563010619323185,0.0562210602242361,0.0729023080179005,-0.0397192078479398,0.0712099797536354,0.0305664873984148,-0.0052198044153011,181.0
412 | -0.00914709342983014,0.0506801187398187,-0.0277621956134263,0.0081008722200108,0.0479653430750293,0.0372033833738938,-0.0286742944356786,0.0343088588777263,0.0660482061630984,-0.0424987666488135,209.0
413 | 0.00538306037424807,-0.044641636506989,0.0584627702970458,-0.0435421881860331,-0.07311850844667,-0.0723985782524425,0.0191869970174533,-0.076394503750001,-0.0514005352605825,-0.0259303389894746,136.0
414 | 0.0744012909436196,-0.044641636506989,0.0854080721440683,0.063186803319791,0.0149424744782022,0.0130909518160999,0.0155053592133662,-0.00259226199818282,0.0062093156165054,0.0859065477110625,261.0
415 | -0.0527375548420648,-0.044641636506989,-0.000816893766403737,-0.0263278347173518,0.0108146159035988,0.00714113104209875,0.0486400994501499,-0.0394933828740919,-0.0358167281015492,0.0196328370737072,113.0
416 | 0.0816663678456587,0.0506801187398187,0.00672779075076256,-0.00452298700183173,0.10988322169408,0.117056241130225,-0.0323559322397657,0.0918746074441444,0.0547240033481791,0.00720651632920303,131.0
417 | -0.00551455497881059,-0.044641636506989,0.00888341489852436,-0.0504279295735057,0.0259500973438113,0.0472241341511589,-0.0434008456520269,0.0712099797536354,0.0148227108412663,0.00306440941436832,174.0
418 | -0.0273097856849279,-0.044641636506989,0.0800190117746638,0.09876313370697,-0.00294491267841247,0.0181013272047324,-0.0176293810234174,0.00331191734196264,-0.0295276227417736,0.036201264733046,257.0
419 | -0.0527375548420648,-0.044641636506989,0.0713965151836166,-0.0745280244296595,-0.0153284884022226,-0.00131387742621863,0.00446044580110504,-0.0214118336448964,-0.0468794828442166,0.00306440941436832,55.0
420 | 0.00901559882526763,-0.044641636506989,-0.0245287593917836,-0.0263278347173518,0.0988755988284711,0.0941964034195887,0.0707299262746723,-0.00259226199818282,-0.02139368094036,0.00720651632920303,84.0
421 | -0.0200447087828888,-0.044641636506989,-0.0547074974604488,-0.0538708002672419,-0.0662387441556644,-0.0573674520865449,0.0118237214092792,-0.0394933828740919,-0.0740888714915354,-0.0052198044153011,42.0
422 | 0.0235457526293458,-0.044641636506989,-0.0363846922044735,6.75072794357462e-05,0.00118294589619092,0.0346981956795776,-0.0434008456520269,0.0343088588777263,-0.0332487872476258,0.0610539062220542,146.0
423 | 0.0380759064334241,0.0506801187398187,0.0164280994156907,0.0218723549949558,0.0397096259258226,0.0450320949186321,-0.0434008456520269,0.0712099797536354,0.049768659920749,0.0154907301588724,212.0
424 | -0.0781653239992017,0.0506801187398187,0.077863387626902,0.0528581912385822,0.0782363059554542,0.0644472995495832,0.0265502726256275,-0.00259226199818282,0.0406722637144977,-0.0093619113301358,233.0
425 | 0.00901559882526763,0.0506801187398187,-0.0396181284261162,0.0287580963824284,0.0383336730676214,0.0735286049414796,-0.0728539480847234,0.108111100629544,0.0155668445407018,-0.0466408735636482,91.0
426 | 0.00175052192322852,0.0506801187398187,0.0110390390462862,-0.0194420933298793,-0.0167044412604238,-0.00381906512053488,-0.0470824834561139,0.0343088588777263,0.024052583226893,0.0237749439885419,111.0
427 | -0.0781653239992017,-0.044641636506989,-0.0406959404999971,-0.081413765817132,-0.100637565610693,-0.112794729823292,0.0228686348215404,-0.076394503750001,-0.0202887477516296,-0.0507829804784829,152.0
428 | 0.030810829531385,0.0506801187398187,-0.0342290680567117,0.0436772026071898,0.0575970130824372,0.0688313780146366,-0.0323559322397657,0.057556565029549,0.0354619386607697,0.0859065477110625,120.0
429 | -0.034574862586967,0.0506801187398187,0.00564997867688165,-0.00567061055493425,-0.07311850844667,-0.062690975936967,-0.00658446761115617,-0.0394933828740919,-0.045420957777041,0.0320591578182113,67.0
430 | 0.0489735217864827,0.0506801187398187,0.088641508365711,0.0872868981759448,0.0355817673512192,0.0215459602844172,-0.0249926566315915,0.0343088588777263,0.0660482061630984,0.131469723774244,310.0
431 | -0.0418399394890061,-0.044641636506989,-0.0331512559828308,-0.0228849640236156,0.0465893902168282,0.0415874618389473,0.056003375058324,-0.0247329345237283,-0.0259524244351894,-0.0383566597339788,94.0
432 | -0.00914709342983014,-0.044641636506989,-0.0568631216082106,-0.0504279295735057,0.0218222387692079,0.0453452433804217,-0.0286742944356786,0.0343088588777263,-0.00991895736315477,-0.0176461251598052,183.0
433 | 0.0707687524926,0.0506801187398187,-0.030995631835069,0.0218723549949558,-0.0373437341334407,-0.0470335528474903,0.0339135482338016,-0.0394933828740919,-0.0149564750249113,-0.00107769750046639,66.0
434 | 0.00901559882526763,-0.044641636506989,0.0552293340754031,-0.00567061055493425,0.0575970130824372,0.0447189464568426,-0.0029028298070691,0.0232385226149535,0.0556835477026737,0.106617082285236,173.0
435 | -0.0273097856849279,-0.044641636506989,-0.0600965578298533,-0.0297707054110881,0.0465893902168282,0.0199802179754696,0.122272855531891,-0.0394933828740919,-0.0514005352605825,-0.0093619113301358,72.0
436 | 0.0162806757273067,-0.044641636506989,0.00133873038135806,0.0081008722200108,0.00531080447079431,0.0108989125835731,0.0302319104297145,-0.0394933828740919,-0.045420957777041,0.0320591578182113,49.0
437 | -0.0127796318808497,-0.044641636506989,-0.0234509473179027,-0.0400993174922969,-0.0167044412604238,0.0046359433477825,-0.0176293810234174,-0.00259226199818282,-0.0384591123013538,-0.0383566597339788,64.0
438 | -0.0563700932930843,-0.044641636506989,-0.074108114790305,-0.0504279295735057,-0.0249601584096305,-0.0470335528474903,0.0928197530991947,-0.076394503750001,-0.0611765950943345,-0.0466408735636482,48.0
439 | 0.0417084448844436,0.0506801187398187,0.0196615356373334,0.0597439326260547,-0.00569681839481472,-0.00256647127337676,-0.0286742944356786,-0.00259226199818282,0.0311929907028023,0.00720651632920303,178.0
440 | -0.00551455497881059,0.0506801187398187,-0.0159062628007364,-0.067642283042187,0.0493412959332305,0.0791652772536912,-0.0286742944356786,0.0343088588777263,-0.0181182673078967,0.0444854785627154,104.0
441 | 0.0417084448844436,0.0506801187398187,-0.0159062628007364,0.0172818607481171,-0.0373437341334407,-0.0138398158977999,-0.0249926566315915,-0.0110795197996419,-0.0468794828442166,0.0154907301588724,132.0
442 | -0.0454724779400257,-0.044641636506989,0.0390621529671896,0.00121513083253827,0.0163184273364034,0.0152829910486266,-0.0286742944356786,0.0265596234937854,0.0445283740214053,-0.0259303389894746,220.0
443 | -0.0454724779400257,-0.044641636506989,-0.0730303027164241,-0.081413765817132,0.0837401173882587,0.0278089295202079,0.17381578478911,-0.0394933828740919,-0.00421985970694603,0.00306440941436832,57.0
444 |
--------------------------------------------------------------------------------
/data/diabetes_bad_dist.csv:
--------------------------------------------------------------------------------
1 | AGE,SEX,BMI,BP,S1,S2,S3,S4,S5,S6,Y
2 | 100,0.0506801187398187,0.0616962065186885,0.0218723549949558,-0.0442234984244464,-0.0348207628376986,-0.0434008456520269,-0.00259226199818282,0.0199084208763183,-0.0176461251598052,151.0
3 | -0.0018820165277910,-0.044641636506989,-0.0514740612388061,-0.0263278347173518,-0.00844872411121698,-0.019163339748222,0.0744115640787594,-0.0394933828740919,-0.0683297436244215,-0.09220404962683,75.0
4 |
--------------------------------------------------------------------------------
/data/diabetes_bad_schema.csv:
--------------------------------------------------------------------------------
1 | SEX,BMI,BP,S1,S2,S3,S4,S5,S6,Y
2 | 0.0506801187398187,0.0616962065186885,0.0218723549949558,-0.0442234984244464,-0.0348207628376986,-0.0434008456520269,-0.00259226199818282,0.0199084208763183,-0.0176461251598052,151.0
3 | -0.04464163650698,-0.0514740612388061,-0.0263278347173518,-0.00844872411121698,-0.019163339748222,0.0744115640787594,-0.0394933828740919,-0.0683297436244215,-0.09220404962683,75.0
4 |
--------------------------------------------------------------------------------
/data/diabetes_missing_values.csv:
--------------------------------------------------------------------------------
1 | AGE,SEX,BMI,BP,S1,S2,S3,S4,S5,S6,Y
2 | ,,,0.0218723549949558,-0.0442234984244464,-0.0348207628376986,-0.0434008456520269,-0.00259226199818282,0.0199084208763183,-0.0176461251598052,151.0
3 | -0.001882016527791,-0.044641636506989,-0.0514740612388061,-0.0263278347173518,-0.00844872411121698,-0.019163339748222,0.0744115640787594,-0.0394933828740919,-0.0683297436244215,-0.09220404962683,75.0
4 |
--------------------------------------------------------------------------------
/pictures/github-actions-azure-machine-learning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marvinbuss/MLDevOps/43a4f9b7ab86b0540c206158d35f7bbf910aa6ed/pictures/github-actions-azure-machine-learning.png
--------------------------------------------------------------------------------
/pictures/ml-lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marvinbuss/MLDevOps/43a4f9b7ab86b0540c206158d35f7bbf910aa6ed/pictures/ml-lifecycle.png
--------------------------------------------------------------------------------