Skip to content

Commit c75b8fe

Browse files
eedorenkodtzar
authored andcommitted
Enable and fix linting (microsoft#44)
1 parent f2c72e1 commit c75b8fe

File tree

9 files changed

+75
-69
lines changed

9 files changed

+75
-69
lines changed

aml_pipelines/model_train_pipeline.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
1-
from azureml.core.authentication import AzureCliAuthentication
2-
from azureml.core.compute import ComputeTarget
31
from azureml.pipeline.core.graph import PipelineParameter
4-
from azureml.pipeline.core import PublishedPipeline
52
from azureml.pipeline.steps import PythonScriptStep
6-
from azureml.pipeline.core import Pipeline, PipelineData, StepSequence
7-
from azureml.data.data_reference import DataReference
3+
from azureml.pipeline.core import Pipeline, PipelineData
84
from azureml.core.runconfig import RunConfiguration, CondaDependencies
9-
from azureml.core import Workspace, Experiment, Datastore
10-
import argparse
5+
from azureml.core import Datastore
116
import datetime
12-
import requests
13-
import json
147
import os
158
import sys
169
from dotenv import load_dotenv
1710
sys.path.append(os.path.abspath("./aml_service")) # NOQA: E402
1811
from workspace import get_workspace
1912
from attach_compute import get_compute
2013

21-
def main():
14+
15+
def main():
2216
load_dotenv()
2317
workspace_name = os.environ.get("AML_WORKSPACE_NAME")
2418
resource_group = os.environ.get("RESOURCE_GROUP")
@@ -29,7 +23,7 @@ def main():
2923
sources_directory_train = os.environ.get("SOURCES_DIR_TRAIN")
3024
train_script_path = os.environ.get("TRAIN_SCRIPT_PATH")
3125
evaluate_script_path = os.environ.get("EVALUATE_SCRIPT_PATH")
32-
register_script_path = os.environ.get("REGISTER_SCRIPT_PATH")
26+
register_script_path = os.environ.get("REGISTER_SCRIPT_PATH")
3327
vm_size_cpu = os.environ.get("AML_COMPUTE_CLUSTER_CPU_SKU")
3428
compute_name_cpu = os.environ.get("AML_COMPUTE_CLUSTER_NAME")
3529
experiment_name = os.environ.get("EXPERIMENT_NAME")
@@ -42,7 +36,7 @@ def main():
4236
tenant_id,
4337
app_id,
4438
app_secret)
45-
print(aml_workspace)
39+
print(aml_workspace)
4640

4741
# Get Azure machine learning cluster
4842
aml_compute_cpu = get_compute(
@@ -61,7 +55,8 @@ def main():
6155
)
6256
run_config.environment.docker.enabled = True
6357

64-
model_name = PipelineParameter(name="model_name", default_value="sklearn_regression_model.pkl")
58+
model_name = PipelineParameter(
59+
name="model_name", default_value="sklearn_regression_model.pkl")
6560
def_blob_store = Datastore(aml_workspace, "workspaceblobstore")
6661
jsonconfigs = PipelineData("jsonconfigs", datastore=def_blob_store)
6762
config_suffix = datetime.datetime.now().strftime("%Y%m%d%H")
@@ -89,15 +84,15 @@ def main():
8984
compute_target=aml_compute_cpu,
9085
source_directory=sources_directory_train,
9186
arguments=[
92-
"--config_suffix", config_suffix,
93-
"--json_config", jsonconfigs,
87+
"--config_suffix", config_suffix,
88+
"--json_config", jsonconfigs,
9489
],
9590
runconfig=run_config,
9691
inputs=[jsonconfigs],
9792
# outputs=[jsonconfigs],
9893
allow_reuse=False,
9994
)
100-
print("Step Evaluate created")
95+
print("Step Evaluate created")
10196

10297
register_model_step = PythonScriptStep(
10398
name="Register New Trained Model",
@@ -122,8 +117,8 @@ def main():
122117

123118
train_pipeline = Pipeline(workspace=aml_workspace, steps=steps)
124119
train_pipeline.validate()
125-
pipeline_run = train_pipeline.submit(experiment_name=experiment_name)
120+
train_pipeline.submit(experiment_name=experiment_name)
126121

127122

128123
if __name__ == '__main__':
129-
main()
124+
main()

azdo_pipelines/base-pipeline.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ parameters:
55
steps:
66
- script: |
77
flake8 --output-file=$(Build.BinariesDirectory)/flake8_amlservice_testresults.xml aml_service
8-
flake8 --output-file=$(Build.BinariesDirectory)/flake8_tests_testresults.xml tests
98
workingDirectory: '$(Build.SourcesDirectory)'
109
displayName: 'Run code quality tests'
1110
enabled: 'true'
1211

13-
- script: |
14-
pytest --junitxml=$(Build.BinariesDirectory)/unittest-results.xml $(Build.SourcesDirectory)/Code/tests/unit/${{parameters.pipelineType}}
15-
displayName: 'Run unit tests'
16-
enabled: 'true'
12+
# - script: |
13+
# pytest --junitxml=$(Build.BinariesDirectory)/unittest-results.xml $(Build.SourcesDirectory)/Code/tests/unit/${{parameters.pipelineType}}
14+
# displayName: 'Run unit tests'
15+
# enabled: 'true'
1716

1817
- task: PublishTestResults@2
1918
condition: succeededOrFailed()

azdo_pipelines/build-train.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,24 @@ variables:
1616
- group: devopsforai-aml-vg
1717

1818

19-
steps:
19+
steps:
20+
- script: |
21+
flake8 --output-file=$(Build.BinariesDirectory)/flake8_testresults.xml --format junit-xml
22+
workingDirectory: '$(Build.SourcesDirectory)'
23+
displayName: 'Run code quality tests'
24+
enabled: 'true'
25+
26+
- task: PublishTestResults@2
27+
condition: succeededOrFailed()
28+
inputs:
29+
testResultsFiles: '$(Build.BinariesDirectory)/*_testresults.xml'
30+
testRunTitle: 'Linitnig'
31+
failTaskOnFailedTests: true
32+
displayName: 'Publish linting results'
33+
enabled: 'true'
34+
35+
36+
2037
- bash: |
2138
# Invoke the Python training pipeline
2239
python3 $(Build.SourcesDirectory)/aml_pipelines/model_train_pipeline.py

code/evaluate/evaluate_model.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@
2323
ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
2424
POSSIBILITY OF SUCH DAMAGE.
2525
"""
26-
import os, json
27-
from azureml.core import Workspace
28-
from azureml.core import Experiment
26+
import os
27+
import json
2928
from azureml.core.model import Model
30-
import azureml.core
3129
from azureml.core import Run
3230
import argparse
3331

@@ -68,30 +66,30 @@
6866
with open(train_output_path) as f:
6967
config = json.load(f)
7068

71-
# parser = argparse.ArgumentParser()
72-
# parser.add_argument('--train_run_id',type=str,default='',help='Run id of the newly trained model')
73-
# #parser.add_argument('--model_assets_path',type=str,default='outputs',help='Location of trained model.')
74-
7569

7670
new_model_run_id = config["run_id"] # args.train_run_id
7771
experiment_name = config["experiment_name"]
7872
# exp = Experiment(workspace=ws, name=experiment_name)
7973

8074

8175
try:
82-
# Get most recently registered model, we assume that is the model in production. Download this model and compare it with the recently trained model by running test with same data set.
76+
# Get most recently registered model, we assume that
77+
# is the model in production.
78+
# Download this model and compare it with the recently
79+
# trained model by running test with same data set.
8380
model_list = Model.list(ws)
8481
production_model = next(
8582
filter(
86-
lambda x: x.created_time == max(model.created_time for model in model_list),
83+
lambda x: x.created_time == max(
84+
model.created_time for model in model_list),
8785
model_list,
8886
)
8987
)
9088
production_model_run_id = production_model.tags.get("run_id")
9189
run_list = exp.get_runs()
92-
# production_model_run = next(filter(lambda x: x.id == production_model_run_id, run_list))
9390

94-
# Get the run history for both production model and newly trained model and compare mse
91+
# Get the run history for both production model and
92+
# newly trained model and compare mse
9593
production_model_run = Run(exp, run_id=production_model_run_id)
9694
new_model_run = Run(exp, run_id=new_model_run_id)
9795

@@ -107,9 +105,10 @@
107105
if new_model_mse < production_model_mse:
108106
promote_new_model = True
109107
print("New trained model performs better, thus it will be registered")
110-
except:
108+
except Exception:
111109
promote_new_model = True
112-
print("This is the first model to be trained, thus nothing to evaluate for now")
110+
print("This is the first model to be trained, \
111+
thus nothing to evaluate for now")
113112

114113
run_id = {}
115114
run_id["run_id"] = ""

code/register/register_model.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,13 @@
2323
ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
2424
POSSIBILITY OF SUCH DAMAGE.
2525
"""
26-
import os, json, sys
27-
from azureml.core import Workspace
26+
import os
27+
import json
28+
import sys
2829
from azureml.core import Run
29-
from azureml.core import Experiment
3030
from azureml.core.model import Model
3131
import argparse
3232

33-
from azureml.core.runconfig import RunConfiguration
3433
from azureml.core.authentication import AzureCliAuthentication
3534

3635
cli_auth = AzureCliAuthentication()
@@ -78,10 +77,10 @@
7877
with open(evaluate_output_path) as f:
7978
config = json.load(f)
8079
if not config["run_id"]:
81-
raise Exception("No new model to register as production model perform better")
82-
except:
80+
raise Exception(
81+
"No new model to register as production model perform better")
82+
except Exception:
8383
print("No new model to register as production model perform better")
84-
# raise Exception('No new model to register as production model perform better')
8584
sys.exit(0)
8685

8786
run_id = config["run_id"]

code/scoring/create_scoring_image.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
2424
POSSIBILITY OF SUCH DAMAGE.
2525
"""
26-
import os, json, sys
26+
import os
27+
import json
28+
import sys
2729
import argparse
2830
from azureml.core import Workspace
2931
from azureml.core.image import ContainerImage, Image
@@ -65,16 +67,16 @@
6567
try:
6668
with open(register_output_path) as f:
6769
config = json.load(f)
68-
except:
70+
except Exception:
6971
print("No new model to register thus no need to create new scoring image")
70-
# raise Exception('No new model to register as production model perform better')
7172
sys.exit(0)
7273

7374
model_name = config["model_name"]
7475
model_version = config["model_version"]
7576

7677
model_list = Model.list(workspace=ws)
77-
model, = (m for m in model_list if m.version == model_version and m.name == model_name)
78+
model, = (m for m in model_list if m.version ==
79+
model_version and m.name == model_name)
7880
print(
7981
"Model picked: {} \nModel Description: {} \nModel Version: {}".format(
8082
model.name, model.description, model.version
@@ -123,5 +125,3 @@
123125
output_path = os.path.join(args.json_config, filename)
124126
with open(output_path, "w") as outfile:
125127
json.dump(image_json, outfile)
126-
127-
# How to fix the schema for a model, like if we have multiple models expecting different schema,

code/scoring/score.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,8 @@
2323
ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
2424
POSSIBILITY OF SUCH DAMAGE.
2525
"""
26-
import pickle
2726
import json
2827
import numpy
29-
from sklearn.ensemble import RandomForestClassifier
3028
from azureml.core.model import Model
3129

3230

@@ -35,7 +33,8 @@ def init():
3533
from sklearn.externals import joblib
3634

3735
# load the model from file into a global object
38-
model_path = Model.get_model_path(model_name="sklearn_regression_model.pkl")
36+
model_path = Model.get_model_path(
37+
model_name="sklearn_regression_model.pkl")
3938
model = joblib.load(model_path)
4039

4140

code/training/train.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE CODE, EVEN IF ADVISED OF THE
2424
POSSIBILITY OF SUCH DAMAGE.
2525
"""
26-
import pickle
27-
from azureml.core import Workspace
2826
from azureml.core.run import Run
2927
import os
3028
import argparse
@@ -35,8 +33,6 @@
3533
from sklearn.externals import joblib
3634
import numpy as np
3735
import json
38-
import subprocess
39-
from typing import Tuple, List
4036

4137

4238
parser = argparse.ArgumentParser("train")
@@ -72,8 +68,10 @@
7268

7369
X, y = load_diabetes(return_X_y=True)
7470
columns = ["age", "gender", "bmi", "bp", "s1", "s2", "s3", "s4", "s5", "s6"]
75-
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
76-
data = {"train": {"X": X_train, "y": y_train}, "test": {"X": X_test, "y": y_test}}
71+
X_train, X_test, y_train, y_test = train_test_split(
72+
X, y, test_size=0.2, random_state=0)
73+
data = {"train": {"X": X_train, "y": y_train},
74+
"test": {"X": X_test, "y": y_test}}
7775

7876
print("Running train.py")
7977

@@ -97,16 +95,13 @@
9795

9896
# upload the model file explicitly into artifacts
9997
run.upload_file(name="./outputs/" + model_name, path_or_stream=model_name)
100-
print("Uploaded the model {} to experiment {}".format(model_name, run.experiment.name))
98+
print("Uploaded the model {} to experiment {}".format(
99+
model_name, run.experiment.name))
101100
dirpath = os.getcwd()
102101
print(dirpath)
103102
print("Following files are uploaded ")
104103
print(run.get_file_names())
105104

106-
# register the model
107-
# run.log_model(file_name = model_name)
108-
# print('Registered the model {} to run history {}'.format(model_name, run.history.name))
109-
110105
run_id = {}
111106
run_id["run_id"] = run.id
112107
run_id["experiment_name"] = run.experiment.name
@@ -115,4 +110,4 @@
115110
with open(output_path, "w") as outfile:
116111
json.dump(run_id, outfile)
117112

118-
run.complete()
113+
run.complete()

tests/unit/data_test.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ def get_absPath(filename):
3434
"""Returns the path of the notebooks folder"""
3535
path = os.path.abspath(
3636
os.path.join(
37-
os.path.dirname(__file__), os.path.pardir, os.path.pardir, "data", filename
37+
os.path.dirname(
38+
__file__), os.path.pardir, os.path.pardir, "data", filename
3839
)
3940
)
4041
return path
@@ -119,6 +120,8 @@ def test_check_distribution():
119120
mean = np.mean(dataset.values, axis=0)
120121
std = np.mean(dataset.values, axis=0)
121122
assert (
122-
np.sum(abs(mean - historical_mean) > shift_tolerance * abs(historical_mean))
123-
or np.sum(abs(std - historical_std) > shift_tolerance * abs(historical_std)) > 0
123+
np.sum(abs(mean - historical_mean) >
124+
shift_tolerance * abs(historical_mean))
125+
or np.sum(abs(std - historical_std) >
126+
shift_tolerance * abs(historical_std)) > 0
124127
)

0 commit comments

Comments
 (0)