mirror of
https://github.com/Azure/MachineLearningNotebooks.git
synced 2025-12-19 17:17:04 -05:00
593 lines
23 KiB
Plaintext
593 lines
23 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Copyright (c) Microsoft Corporation. All rights reserved.\n",
|
|
"\n",
|
|
"Licensed under the MIT License."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Automated Machine Learning\n",
|
|
"_**Regression on remote compute using Computer Hardware dataset with model explanations**_\n",
|
|
"\n",
|
|
"## Contents\n",
|
|
"1. [Introduction](#Introduction)\n",
|
|
"1. [Setup](#Setup)\n",
|
|
"1. [Train](#Train)\n",
|
|
"1. [Results](#Results)\n",
|
|
"1. [Explanations](#Explanations)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Introduction\n",
|
|
"\n",
|
|
"In this example we use the Hardware Performance Dataset to showcase how you can use AutoML for a simple regression problem. After training AutoML models for this regression data set, we show how you can compute model explanations on your remote compute using a sample explainer script.\n",
|
|
"\n",
|
|
"If you are using an Azure Machine Learning Notebook VM, you are all set. Otherwise, go through the [configuration](../../../configuration.ipynb) notebook first if you haven't already to establish your connection to the AzureML Workspace. \n",
|
|
"\n",
|
|
"In this notebook you will learn how to:\n",
|
|
"1. Create an `Experiment` in an existing `Workspace`.\n",
|
|
"2. Configure AutoML using `AutoMLConfig`.\n",
|
|
"3. Train the model using remote compute.\n",
|
|
"4. Explore the results.\n",
|
|
"5. Setup remote compute for computing the model explanations for a given AutoML model.\n",
|
|
"6. Start an AzureML experiment on your remote compute to compute explanations for an AutoML model.\n",
|
|
"7. Download the feature importance for engineered features and visualize the explanations for engineered features. \n",
|
|
"8. Download the feature importance for raw features and visualize the explanations for raw features. \n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Setup\n",
|
|
"\n",
|
|
"As part of the setup you have already created an Azure ML `Workspace` object. For AutoML you will need to create an `Experiment` object, which is a named object in a `Workspace` used to run experiments."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import logging\n",
|
|
"\n",
|
|
"from matplotlib import pyplot as plt\n",
|
|
"import pandas as pd\n",
|
|
"import os\n",
|
|
"\n",
|
|
"import azureml.core\n",
|
|
"from azureml.core.experiment import Experiment\n",
|
|
"from azureml.core.workspace import Workspace\n",
|
|
"from azureml.core.dataset import Dataset\n",
|
|
"from azureml.train.automl import AutoMLConfig"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"ws = Workspace.from_config()\n",
|
|
"\n",
|
|
"# choose a name for experiment\n",
|
|
"experiment_name = 'automl-regression-computer-hardware'\n",
|
|
"\n",
|
|
"experiment=Experiment(ws, experiment_name)\n",
|
|
"\n",
|
|
"output = {}\n",
|
|
"output['SDK version'] = azureml.core.VERSION\n",
|
|
"output['Subscription ID'] = ws.subscription_id\n",
|
|
"output['Workspace'] = ws.name\n",
|
|
"output['Resource Group'] = ws.resource_group\n",
|
|
"output['Location'] = ws.location\n",
|
|
"output['Experiment Name'] = experiment.name\n",
|
|
"pd.set_option('display.max_colwidth', -1)\n",
|
|
"outputDf = pd.DataFrame(data = output, index = [''])\n",
|
|
"outputDf.T"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Create or Attach existing AmlCompute\n",
|
|
"You will need to create a compute target for your AutoML run. In this tutorial, you create AmlCompute as your training compute resource.\n",
|
|
"#### Creation of AmlCompute takes approximately 5 minutes. \n",
|
|
"If the AmlCompute with that name is already in your workspace this code will skip the creation process.\n",
|
|
"As with other Azure services, there are limits on certain resources (e.g. AmlCompute) associated with the Azure Machine Learning service. Please read this article on the default limits and how to request more quota."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from azureml.core.compute import AmlCompute\n",
|
|
"from azureml.core.compute import ComputeTarget\n",
|
|
"\n",
|
|
"# Choose a name for your cluster.\n",
|
|
"amlcompute_cluster_name = \"automlcl\"\n",
|
|
"\n",
|
|
"found = False\n",
|
|
"# Check if this compute target already exists in the workspace.\n",
|
|
"cts = ws.compute_targets\n",
|
|
"if amlcompute_cluster_name in cts and cts[amlcompute_cluster_name].type == 'AmlCompute':\n",
|
|
" found = True\n",
|
|
" print('Found existing compute target.')\n",
|
|
" compute_target = cts[amlcompute_cluster_name]\n",
|
|
" \n",
|
|
"if not found:\n",
|
|
" print('Creating a new compute target...')\n",
|
|
" provisioning_config = AmlCompute.provisioning_configuration(vm_size = \"STANDARD_D2_V2\", # for GPU, use \"STANDARD_NC6\"\n",
|
|
" #vm_priority = 'lowpriority', # optional\n",
|
|
" max_nodes = 6)\n",
|
|
"\n",
|
|
" # Create the cluster.\n",
|
|
" compute_target = ComputeTarget.create(ws, amlcompute_cluster_name, provisioning_config)\n",
|
|
" \n",
|
|
"print('Checking cluster status...')\n",
|
|
"# Can poll for a minimum number of nodes and for a specific timeout.\n",
|
|
"# If no min_node_count is provided, it will use the scale settings for the cluster.\n",
|
|
"compute_target.wait_for_completion(show_output = True, min_node_count = None, timeout_in_minutes = 20)\n",
|
|
" \n",
|
|
"# For a more detailed view of current AmlCompute status, use get_status()."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Conda Dependecies for AutoML training experiment\n",
|
|
"\n",
|
|
"Create the conda dependencies for running AutoML experiment on remote compute."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from azureml.core.runconfig import RunConfiguration\n",
|
|
"from azureml.core.conda_dependencies import CondaDependencies\n",
|
|
"import pkg_resources\n",
|
|
"\n",
|
|
"# create a new RunConfig object\n",
|
|
"conda_run_config = RunConfiguration(framework=\"python\")\n",
|
|
"\n",
|
|
"# Set compute target to AmlCompute\n",
|
|
"conda_run_config.target = compute_target\n",
|
|
"conda_run_config.environment.docker.enabled = True\n",
|
|
"\n",
|
|
"cd = CondaDependencies.create(conda_packages=['numpy','py-xgboost<=0.80'])\n",
|
|
"conda_run_config.environment.python.conda_dependencies = cd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Setup Training and Test Data for AutoML experiment\n",
|
|
"\n",
|
|
"Here we create the train and test datasets for hardware performance dataset. We also register the datasets in your workspace using a name so that these datasets may be accessed from the remote compute."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Data source\n",
|
|
"data = \"https://automlsamplenotebookdata.blob.core.windows.net/automl-sample-notebook-data/machineData.csv\"\n",
|
|
"\n",
|
|
"# Create dataset from the url\n",
|
|
"dataset = Dataset.Tabular.from_delimited_files(data)\n",
|
|
"\n",
|
|
"# Split the dataset into train and test datasets\n",
|
|
"train_dataset, test_dataset = dataset.random_split(percentage=0.8, seed=223)\n",
|
|
"\n",
|
|
"# Register the train dataset with your workspace\n",
|
|
"train_dataset.register(workspace = ws, name = 'hardware_performance_train_dataset',\n",
|
|
" description = 'hardware performance training data',\n",
|
|
" create_new_version=True)\n",
|
|
"\n",
|
|
"# Register the test dataset with your workspace\n",
|
|
"test_dataset.register(workspace = ws, name = 'hardware_performance_test_dataset',\n",
|
|
" description = 'hardware performance test data',\n",
|
|
" create_new_version=True)\n",
|
|
"\n",
|
|
"# Drop the labeled column from the train dataset\n",
|
|
"X_train = train_dataset.drop_columns(columns=['ERP'])\n",
|
|
"y_train = train_dataset.keep_columns(columns=['ERP'], validate=True)\n",
|
|
"\n",
|
|
"# Drop the labeled column from the test dataset\n",
|
|
"X_test = test_dataset.drop_columns(columns=['ERP']) \n",
|
|
"\n",
|
|
"# Display the top rows in the train dataset\n",
|
|
"X_train.take(5).to_pandas_dataframe()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Train\n",
|
|
"\n",
|
|
"Instantiate an `AutoMLConfig` object to specify the settings and data used to run the experiment.\n",
|
|
"\n",
|
|
"|Property|Description|\n",
|
|
"|-|-|\n",
|
|
"|**task**|classification or regression|\n",
|
|
"|**primary_metric**|This is the metric that you want to optimize. Regression supports the following primary metrics: <br><i>spearman_correlation</i><br><i>normalized_root_mean_squared_error</i><br><i>r2_score</i><br><i>normalized_mean_absolute_error</i>|\n",
|
|
"|**iteration_timeout_minutes**|Time limit in minutes for each iteration.|\n",
|
|
"|**iterations**|Number of iterations. In each iteration AutoML trains a specific pipeline with the data.|\n",
|
|
"|**n_cross_validations**|Number of cross validation splits.|\n",
|
|
"|**X**|(sparse) array-like, shape = [n_samples, n_features]|\n",
|
|
"|**y**|(sparse) array-like, shape = [n_samples, ], targets values.|\n",
|
|
"\n",
|
|
"**_You can find more information about primary metrics_** [here](https://docs.microsoft.com/en-us/azure/machine-learning/service/how-to-configure-auto-train#primary-metric)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"automl_settings = {\n",
|
|
" \"iteration_timeout_minutes\": 5,\n",
|
|
" \"iterations\": 10,\n",
|
|
" \"n_cross_validations\": 2,\n",
|
|
" \"primary_metric\": 'spearman_correlation',\n",
|
|
" \"preprocess\": True,\n",
|
|
" \"max_concurrent_iterations\": 1,\n",
|
|
" \"verbosity\": logging.INFO,\n",
|
|
"}\n",
|
|
"\n",
|
|
"automl_config = AutoMLConfig(task = 'regression',\n",
|
|
" debug_log = 'automl_errors_model_exp.log',\n",
|
|
" run_configuration=conda_run_config,\n",
|
|
" X = X_train,\n",
|
|
" y = y_train,\n",
|
|
" **automl_settings\n",
|
|
" )"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Call the `submit` method on the experiment object and pass the run configuration. Execution of local runs is synchronous. Depending on the data and the number of iterations this can run for a while.\n",
|
|
"In this example, we specify `show_output = True` to print currently running iterations to the console."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"remote_run = experiment.submit(automl_config, show_output = True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"remote_run"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Results"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Widget for Monitoring Runs\n",
|
|
"\n",
|
|
"The widget will first report a \"loading\" status while running the first iteration. After completing the first iteration, an auto-updating graph and table will be shown. The widget will refresh once per minute, so you should see the graph update as child runs complete.\n",
|
|
"\n",
|
|
"**Note:** The widget displays a link at the bottom. Use this link to open a web interface to explore the individual run details"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from azureml.widgets import RunDetails\n",
|
|
"RunDetails(remote_run).show() "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Explanations\n",
|
|
"This section will walk you through the workflow to compute model explanations for an AutoML model on your remote compute.\n",
|
|
"\n",
|
|
"### Retrieve any AutoML Model for explanations\n",
|
|
"\n",
|
|
"Below we select the some AutoML pipeline from our iterations. The `get_output` method returns the a AutoML run and the fitted model for the last invocation. Overloads on `get_output` allow you to retrieve the best run and fitted model for *any* logged metric or for a particular *iteration*."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"automl_run, fitted_model = remote_run.get_output(iteration=5)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Setup model explanation run on the remote compute\n",
|
|
"The following section provides details on how to setup an AzureML experiment to run model explanations for an AutoML model on your remote compute."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Sample script used for computing explanations\n",
|
|
"View the sample script for computing the model explanations for your AutoML model on remote compute."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"with open('train_explainer.py', 'r') as cefr:\n",
|
|
" print(cefr.read())"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Substitute values in your sample script\n",
|
|
"The following cell shows how you change the values in the sample script so that you can change the sample script according to your experiment and dataset."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import shutil\n",
|
|
"\n",
|
|
"# create script folder\n",
|
|
"script_folder = './sample_projects/automl-regression-computer-hardware'\n",
|
|
"if not os.path.exists(script_folder):\n",
|
|
" os.makedirs(script_folder)\n",
|
|
"\n",
|
|
"# Copy the sample script to script folder.\n",
|
|
"shutil.copy('train_explainer.py', script_folder)\n",
|
|
"\n",
|
|
"# Create the explainer script that will run on the remote compute.\n",
|
|
"script_file_name = script_folder + '/train_explainer.py'\n",
|
|
"\n",
|
|
"# Open the sample script for modification\n",
|
|
"with open(script_file_name, 'r') as cefr:\n",
|
|
" content = cefr.read()\n",
|
|
"\n",
|
|
"# Replace the values in train_explainer.py file with the appropriate values\n",
|
|
"content = content.replace('<<experimnet_name>>', automl_run.experiment.name) # your experiment name.\n",
|
|
"content = content.replace('<<run_id>>', automl_run.id) # Run-id of the AutoML run for which you want to explain the model.\n",
|
|
"content = content.replace('<<target_column_name>>', 'ERP') # Your target column name\n",
|
|
"content = content.replace('<<task>>', 'regression') # Training task type\n",
|
|
"# Name of your training dataset register with your workspace\n",
|
|
"content = content.replace('<<train_dataset_name>>', 'hardware_performance_train_dataset') \n",
|
|
"# Name of your test dataset register with your workspace\n",
|
|
"content = content.replace('<<test_dataset_name>>', 'hardware_performance_test_dataset')\n",
|
|
"\n",
|
|
"# Write sample file into your script folder.\n",
|
|
"with open(script_file_name, 'w') as cefw:\n",
|
|
" cefw.write(content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Create conda configuration for model explanations experiment\n",
|
|
"We need `azureml-explain-model`, `azureml-train-automl` and `azureml-core` packages for computing model explanations for your AutoML model on remote compute."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from azureml.core.runconfig import RunConfiguration\n",
|
|
"from azureml.core.conda_dependencies import CondaDependencies\n",
|
|
"import pkg_resources\n",
|
|
"\n",
|
|
"# create a new RunConfig object\n",
|
|
"conda_run_config = RunConfiguration(framework=\"python\")\n",
|
|
"\n",
|
|
"# Set compute target to AmlCompute\n",
|
|
"conda_run_config.target = compute_target\n",
|
|
"conda_run_config.environment.docker.enabled = True\n",
|
|
"azureml_pip_packages = [\n",
|
|
" 'azureml-train-automl', 'azureml-core', 'azureml-explain-model'\n",
|
|
"]\n",
|
|
"\n",
|
|
"# specify CondaDependencies obj\n",
|
|
"conda_run_config.environment.python.conda_dependencies = CondaDependencies.create(\n",
|
|
" conda_packages=['scikit-learn', 'numpy','py-xgboost<=0.80'],\n",
|
|
" pip_packages=azureml_pip_packages)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Submit the experiment for model explanations\n",
|
|
"Submit the experiment with the above `run_config` and the sample script for computing explanations."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Now submit a run on AmlCompute for model explanations\n",
|
|
"from azureml.core.script_run_config import ScriptRunConfig\n",
|
|
"\n",
|
|
"script_run_config = ScriptRunConfig(source_directory=script_folder,\n",
|
|
" script='train_explainer.py',\n",
|
|
" run_config=conda_run_config)\n",
|
|
"\n",
|
|
"run = experiment.submit(script_run_config)\n",
|
|
"\n",
|
|
"# Show run details\n",
|
|
"run"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%time\n",
|
|
"# Shows output of the run on stdout.\n",
|
|
"run.wait_for_completion(show_output=True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Feature importance and explanation dashboard\n",
|
|
"In this section we describe how you can download the explanation results from the explanations experiment and visualize the feature importance for your AutoML model. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Setup for visualizing the model explanation results\n",
|
|
"For visualizing the explanation results for the *fitted_model* we need to perform the following steps:-\n",
|
|
"1. Featurize test data samples.\n",
|
|
"\n",
|
|
"The *automl_explainer_setup_obj* contains all the structures from above list. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from azureml.train.automl.automl_explain_utilities import AutoMLExplainerSetupClass, automl_setup_model_explanations\n",
|
|
"explainer_setup_class = automl_setup_model_explanations(fitted_model, 'regression', X_test=X_test)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Download engineered feature importance from artifact store\n",
|
|
"You can use *ExplanationClient* to download the engineered feature explanations from the artifact store of the *automl_run*. You can also use ExplanationDashboard to view the dash board visualization of the feature importance values of the engineered features."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from azureml.explain.model._internal.explanation_client import ExplanationClient\n",
|
|
"from azureml.contrib.explain.model.visualize import ExplanationDashboard\n",
|
|
"client = ExplanationClient.from_run(automl_run)\n",
|
|
"engineered_explanations = client.download_model_explanation(raw=False)\n",
|
|
"print(engineered_explanations.get_feature_importance_dict())\n",
|
|
"ExplanationDashboard(engineered_explanations, explainer_setup_class.automl_estimator, explainer_setup_class.X_test_transform)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Download raw feature importance from artifact store\n",
|
|
"You can use *ExplanationClient* to download the raw feature explanations from the artifact store of the *automl_run*. You can also use ExplanationDashboard to view the dash board visualization of the feature importance values of the raw features."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"raw_explanations = client.download_model_explanation(raw=True)\n",
|
|
"print(raw_explanations.get_feature_importance_dict())\n",
|
|
"ExplanationDashboard(raw_explanations, explainer_setup_class.automl_pipeline, explainer_setup_class.X_test_raw)"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"authors": [
|
|
{
|
|
"name": "v-rasav"
|
|
}
|
|
],
|
|
"kernelspec": {
|
|
"display_name": "Python 3.6",
|
|
"language": "python",
|
|
"name": "python36"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.6.7"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
} |