forked from RealData/PredictiveMaintenance
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtrain.py
More file actions
200 lines (157 loc) · 8.7 KB
/
Copy pathtrain.py
File metadata and controls
200 lines (157 loc) · 8.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
from azureml.core import Run
import os
import glob
import time
from pyspark.ml.feature import StringIndexer, OneHotEncoder, VectorAssembler, VectorIndexer
from pyspark.ml import Pipeline, PipelineModel
from pyspark.ml.classification import RandomForestClassifier
from pyspark.ml.classification import DecisionTreeClassifier
from pyspark.ml.classification import GBTClassifier
from pyspark.ml.evaluation import MulticlassClassificationEvaluator
from pyspark.sql.functions import col
from pyspark.sql import SparkSession
import pandas as pd
import numpy as np
from azure.storage.blob import BlockBlobService
from azure.storage.blob import PublicAccess
ACCOUNT_NAME = "realdataws2381254700"
ACCOUNT_KEY = "5V1gUjiCjoOBozvQf6wTHHnQDFqylAwnDPyAdwkMhEb0vke//ckkj+B06Z8YaoO2InjlAVduJ/IhZwACw1bapg=="
run = Run.get_context(allow_offline = True) # Get Run object from context
run.log('Starting Model Training', time.asctime(time.localtime(time.time())))
run.tag('Description', 'Model Building')
tic = time.time()
spark = SparkSession.builder.getOrCreate()
CONTAINER_NAME = CONTAINER_NAME = "featureengineering"
az_blob_service = BlockBlobService(account_name=ACCOUNT_NAME, account_key=ACCOUNT_KEY)
# This is the final feature data file.
FEATURES_LOCAL_DIRECT = 'featureengineering_files.parquet'
# This is where we store the final model data file.
LOCAL_DIRECT = 'model_result.parquet'
# load the previous created final dataset into the workspace
# create a local path where we store results
if not os.path.exists(FEATURES_LOCAL_DIRECT):
os.makedirs(FEATURES_LOCAL_DIRECT)
print('DONE creating a local directory!')
# download the entire parquet result folder to local path for a new run
for blob in az_blob_service.list_blobs(CONTAINER_NAME):
if FEATURES_LOCAL_DIRECT in blob.name:
local_file = os.path.join(FEATURES_LOCAL_DIRECT, os.path.basename(blob.name))
az_blob_service.get_blob_to_path(CONTAINER_NAME, blob.name, local_file)
feat_data = spark.read.parquet(FEATURES_LOCAL_DIRECT)
# define list of input columns for downstream modeling
# We'll use the known label, and key variables.
label_var = ['label_e']
key_cols =['machineID','dt_truncated']
# Then get the remaing feature names from the data
input_features = feat_data.columns
# We'll use the known label, key variables and
# a few extra columns we won't need.
remove_names = label_var + key_cols + ['failure','model_encoded','model' ]
# Remove the extra names if that are in the input_features list
input_features = [x for x in input_features if x not in set(remove_names)]
# assemble features
va = VectorAssembler(inputCols=(input_features), outputCol='features')
feat_data = va.transform(feat_data).select('machineID','dt_truncated','label_e','features')
# set maxCategories so features with > 10 distinct values are treated as continuous.
featureIndexer = VectorIndexer(inputCol="features",
outputCol="indexedFeatures",
maxCategories=10).fit(feat_data)
# fit on whole dataset to include all labels in index
labelIndexer = StringIndexer(inputCol="label_e", outputCol="indexedLabel").fit(feat_data)
# split the data into train/test based on date
split_date = "2015-10-30"
training = feat_data.filter(feat_data.dt_truncated < split_date)
testing = feat_data.filter(feat_data.dt_truncated >= split_date)
run.log('Training Count', training.count())
run.log('Testing Count', testing.count())
print(training.count())
print(testing.count())
# # Classification models
model_type = 'RandomForest' # Use 'DecisionTree', or 'RandomForest'
# train a model
if model_type == 'DecisionTree':
model = DecisionTreeClassifier(labelCol="indexedLabel", featuresCol="indexedFeatures",
# Maximum depth of the tree. (>= 0)
# E.g., depth 0 means 1 leaf node; depth 1 means 1 internal node + 2 leaf nodes.'
maxDepth=15,
# Max number of bins for discretizing continuous features.
# Must be >=2 and >= number of categories for any categorical feature.
maxBins=32,
# Minimum number of instances each child must have after split.
# If a split causes the left or right child to have fewer than
# minInstancesPerNode, the split will be discarded as invalid. Should be >= 1.
minInstancesPerNode=1,
# Minimum information gain for a split to be considered at a tree node.
minInfoGain=0.0,
# Criterion used for information gain calculation (case-insensitive).
# Supported options: entropy, gini')
impurity="gini")
##=======================================================================================================================
#elif model_type == 'GBTClassifier':
# cls_mthd = GBTClassifier(labelCol="indexedLabel", featuresCol="indexedFeatures")
##=======================================================================================================================
else:
model = RandomForestClassifier(labelCol="indexedLabel", featuresCol="indexedFeatures",
# Passed to DecisionTreeClassifier
maxDepth=15,
maxBins=32,
minInstancesPerNode=1,
minInfoGain=0.0,
impurity="gini",
# Number of trees to train (>= 1)
numTrees=50,
# The number of features to consider for splits at each tree node.
# Supported options: auto, all, onethird, sqrt, log2, (0.0-1.0], [1-n].
featureSubsetStrategy="sqrt",
# Fraction of the training data used for learning each
# decision tree, in range (0, 1].'
subsamplingRate = 0.632)
# chain indexers and model in a Pipeline
pipeline_cls_mthd = Pipeline(stages=[labelIndexer, featureIndexer, model])
# train model. This also runs the indexers.
model_pipeline = pipeline_cls_mthd.fit(training)
# To evaluate this model, we predict the component failures over the test data set. Since the test set has been created from data the model has not been seen before, it simulates future data. The evaluation then can be generalize to how the model could perform when operationalized and used to score the data in real time.
# make predictions. The Pipeline does all the same operations on the test data
predictions = model_pipeline.transform(testing)
# Create the confusion matrix for the multiclass prediction results
# This result assumes a decision boundary of p = 0.5
conf_table = predictions.stat.crosstab('indexedLabel', 'prediction')
confuse = conf_table.toPandas()
# select (prediction, true label) and compute test error
# select (prediction, true label) and compute test error
# True positives - diagonal failure terms
tp = confuse['1.0'][1]+confuse['2.0'][2]+confuse['3.0'][3]+confuse['4.0'][4]
# False positves - All failure terms - True positives
fp = np.sum(np.sum(confuse[['1.0', '2.0','3.0','4.0']])) - tp
# True negatives
tn = confuse['0.0'][0]
# False negatives total of non-failure column - TN
fn = np.sum(np.sum(confuse[['0.0']])) - tn
# Accuracy is diagonal/total
acc_n = tn + tp
acc_d = np.sum(np.sum(confuse[['0.0','1.0', '2.0','3.0','4.0']]))
acc = acc_n/acc_d
# Calculate precision and recall.
prec = tp/(tp+fp)
rec = tp/(tp+fn)
# Print the evaluation metrics to the notebook
print("Accuracy = %g" % acc)
print("Precision = %g" % prec)
print("Recall = %g" % rec )
print("F1 = %g" % (2.0 * prec * rec/(prec + rec)))
print("")
run.log('Model Accuracy', (acc))
run.log('Model Precision', (prec))
run.log('Model Recall', (rec))
run.log('Model F1', (2.0 * prec * rec/(prec + rec)))
#%%
importances = model_pipeline.stages[2].featureImportances
# save model
model_pipeline.write().overwrite().save(os.environ['AZUREML_NATIVE_SHARE_DIRECTORY']+'pdmrfull.model')
print("Model saved")
# Time the notebook execution.
# This will only make sense if you "Run All" cells
toc = time.time()
print("Full run took %.2f minutes" % ((toc - tic)/60))
#logger.log("Model Building Run time", ((toc - tic)/60))
run.log('Model Building Run time', ((toc - tic)/60))