Skip to content

Commit 99294a8

Browse files
authored
Merge pull request #119 from sassoftware/mlflow
New Feature: Simple Mlflow Integration
2 parents e3dcd1a + 6f03d0a commit 99294a8

27 files changed

+1616
-70
lines changed
627 Bytes
Binary file not shown.
3.36 KB
Binary file not shown.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
3+
import math
4+
import pickle
5+
import pandas as pd
6+
import numpy as np
7+
8+
with open('/models/resources/viya/d02aadfe-618e-44e0-af6d-1bf00c6396e3/MLFlowTest.pickle', 'rb') as _pFile:
9+
_thisModelFit = pickle.load(_pFile)
10+
11+
def scoreMLFlowTest(fixedacidity, volatileacidity, citricacid, residualsugar, chlorides, freesulfurdioxide, totalsulfurdioxide, density, pH, sulphates, alcohol):
12+
"Output: tensor"
13+
14+
try:
15+
global _thisModelFit
16+
except NameError:
17+
18+
with open('/models/resources/viya/d02aadfe-618e-44e0-af6d-1bf00c6396e3/MLFlowTest.pickle', 'rb') as _pFile:
19+
_thisModelFit = pickle.load(_pFile)
20+
21+
try:
22+
inputArray = pd.DataFrame([[fixedacidity, volatileacidity, citricacid, residualsugar, chlorides, freesulfurdioxide, totalsulfurdioxide, density, pH, sulphates, alcohol]],
23+
columns=['fixedacidity', 'volatileacidity', 'citricacid', 'residualsugar', 'chlorides', 'freesulfurdioxide', 'totalsulfurdioxide', 'density', 'pH', 'sulphates', 'alcohol'],
24+
dtype=float)
25+
prediction = _thisModelFit.predict(inputArray)
26+
except ValueError:
27+
# For models requiring or including an intercept value, a 'const' column is required
28+
# For example, many statsmodels models include an intercept value that must be included for the model prediction
29+
inputArray = pd.DataFrame([[1.0, fixedacidity, volatileacidity, citricacid, residualsugar, chlorides, freesulfurdioxide, totalsulfurdioxide, density, pH, sulphates, alcohol]],
30+
columns=['const', 'fixedacidity', 'volatileacidity', 'citricacid', 'residualsugar', 'chlorides', 'freesulfurdioxide', 'totalsulfurdioxide', 'density', 'pH', 'sulphates', 'alcohol'],
31+
dtype=float)
32+
prediction = _thisModelFit.predict(inputArray)
33+
34+
tensor = prediction
35+
36+
return(tensor)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "MLFlowTest",
3+
"description": "MLFlow Model ",
4+
"function": "classification",
5+
"scoreCodeType": "python",
6+
"trainTable": " ",
7+
"trainCodeType": "Python",
8+
"algorithm": "",
9+
"targetVariable": "",
10+
"targetEvent": 1,
11+
"targetLevel": "BINARY",
12+
"eventProbVar": "tensor",
13+
"modeler": "sasdemo",
14+
"tool": "Python 3",
15+
"toolVersion": "3.8.3"
16+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
data sasep.out;
2+
dcl package pymas pm;
3+
dcl package logger logr('App.tk.MAS');
4+
dcl varchar(32767) character set utf8 pypgm;
5+
dcl double resultCode revision;
6+
dcl double tensor;
7+
8+
9+
method score(double fixedacidity, double volatileacidity, double citricacid, double residualsugar, double chlorides, double freesulfurdioxide, double totalsulfurdioxide, double density, double pH, double sulphates, double alcohol, in_out double resultCode, in_out double tensor);
10+
resultCode = revision = 0;
11+
if null(pm) then do;
12+
pm = _new_ pymas();
13+
resultCode = pm.useModule('model_exec_3106686d-a021-449a-9c2d-f2a6f47a4948', 1);
14+
if resultCode then do;
15+
resultCode = pm.appendSrcLine('');
16+
resultCode = pm.appendSrcLine('');
17+
resultCode = pm.appendSrcLine('import math');
18+
resultCode = pm.appendSrcLine('import pickle');
19+
resultCode = pm.appendSrcLine('import pandas as pd');
20+
resultCode = pm.appendSrcLine('import numpy as np');
21+
resultCode = pm.appendSrcLine('');
22+
resultCode = pm.appendSrcLine('with open("/models/resources/viya/d02aadfe-618e-44e0-af6d-1bf00c6396e3/MLFlowTest.pickle", "rb") as _pFile:');
23+
resultCode = pm.appendSrcLine(' _thisModelFit = pickle.load(_pFile)');
24+
resultCode = pm.appendSrcLine('');
25+
resultCode = pm.appendSrcLine('def scoreMLFlowTest(fixedacidity, volatileacidity, citricacid, residualsugar, chlorides, freesulfurdioxide, totalsulfurdioxide, density, pH, sulphates, alcohol):');
26+
resultCode = pm.appendSrcLine(' "Output: tensor"');
27+
resultCode = pm.appendSrcLine('');
28+
resultCode = pm.appendSrcLine(' try:');
29+
resultCode = pm.appendSrcLine(' global _thisModelFit');
30+
resultCode = pm.appendSrcLine(' except NameError:');
31+
resultCode = pm.appendSrcLine('');
32+
resultCode = pm.appendSrcLine(' with open("/models/resources/viya/d02aadfe-618e-44e0-af6d-1bf00c6396e3/MLFlowTest.pickle", "rb") as _pFile:');
33+
resultCode = pm.appendSrcLine(' _thisModelFit = pickle.load(_pFile)');
34+
resultCode = pm.appendSrcLine('');
35+
resultCode = pm.appendSrcLine(' try:');
36+
resultCode = pm.appendSrcLine(' inputArray = pd.DataFrame([[fixedacidity, volatileacidity, citricacid, residualsugar, chlorides, freesulfurdioxide, totalsulfurdioxide, density, pH, sulphates, alcohol]],');
37+
resultCode = pm.appendSrcLine(' columns=["fixedacidity", "volatileacidity", "citricacid", "residualsugar", "chlorides", "freesulfurdioxide", "totalsulfurdioxide", "density", "pH", "sulphates", "alcohol"],');
38+
resultCode = pm.appendSrcLine(' dtype=float)');
39+
resultCode = pm.appendSrcLine(' prediction = _thisModelFit.predict(inputArray)');
40+
resultCode = pm.appendSrcLine(' except ValueError:');
41+
resultCode = pm.appendSrcLine(' # For models requiring or including an intercept value, a "const" column is required');
42+
resultCode = pm.appendSrcLine(' # For example, many statsmodels models include an intercept value that must be included for the model prediction');
43+
resultCode = pm.appendSrcLine(' inputArray = pd.DataFrame([[1.0, fixedacidity, volatileacidity, citricacid, residualsugar, chlorides, freesulfurdioxide, totalsulfurdioxide, density, pH, sulphates, alcohol]],');
44+
resultCode = pm.appendSrcLine(' columns=["const", "fixedacidity", "volatileacidity", "citricacid", "residualsugar", "chlorides", "freesulfurdioxide", "totalsulfurdioxide", "density", "pH", "sulphates", "alcohol"],');
45+
resultCode = pm.appendSrcLine(' dtype=float)');
46+
resultCode = pm.appendSrcLine(' prediction = _thisModelFit.predict(inputArray)');
47+
resultCode = pm.appendSrcLine('');
48+
resultCode = pm.appendSrcLine(' tensor = prediction');
49+
resultCode = pm.appendSrcLine('');
50+
resultCode = pm.appendSrcLine(' return(tensor)');
51+
revision = pm.publish(pm.getSource(), 'model_exec_3106686d-a021-449a-9c2d-f2a6f47a4948');
52+
53+
if ( revision < 1 ) then do;
54+
logr.log( 'e', 'py.publish() failed.');
55+
resultCode = -1;
56+
return;
57+
end;
58+
end;
59+
end;
60+
resultCode = pm.useMethod('scoreMLFlowTest');
61+
if resultCode then do;
62+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
63+
return;
64+
end;
65+
resultCode = pm.setDouble('fixedacidity', fixedacidity);
66+
if resultCode then
67+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
68+
resultCode = pm.setDouble('volatileacidity', volatileacidity);
69+
if resultCode then
70+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
71+
resultCode = pm.setDouble('citricacid', citricacid);
72+
if resultCode then
73+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
74+
resultCode = pm.setDouble('residualsugar', residualsugar);
75+
if resultCode then
76+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
77+
resultCode = pm.setDouble('chlorides', chlorides);
78+
if resultCode then
79+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
80+
resultCode = pm.setDouble('freesulfurdioxide', freesulfurdioxide);
81+
if resultCode then
82+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
83+
resultCode = pm.setDouble('totalsulfurdioxide', totalsulfurdioxide);
84+
if resultCode then
85+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
86+
resultCode = pm.setDouble('density', density);
87+
if resultCode then
88+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
89+
resultCode = pm.setDouble('pH', pH);
90+
if resultCode then
91+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
92+
resultCode = pm.setDouble('sulphates', sulphates);
93+
if resultCode then
94+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
95+
resultCode = pm.setDouble('alcohol', alcohol);
96+
if resultCode then
97+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
98+
resultCode = pm.execute();
99+
if (resultCode) then put 'Error: pm.execute failed. resultCode=' resultCode;
100+
else do;
101+
tensor = pm.getDouble('tensor');
102+
end;
103+
end;
104+
105+
method run();
106+
set SASEP.IN;
107+
score(fixedacidity, volatileacidity, citricacid, residualsugar, chlorides, freesulfurdioxide, totalsulfurdioxide, density, pH, sulphates, alcohol, resultCode, tensor);
108+
end;
109+
enddata;
110+
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package pythonScore / overwrite=yes;
2+
dcl package pymas pm;
3+
dcl package logger logr('App.tk.MAS');
4+
dcl varchar(32767) character set utf8 pypgm;
5+
dcl int resultCode revision;
6+
7+
method score(double fixedacidity, double volatileacidity, double citricacid, double residualsugar, double chlorides, double freesulfurdioxide, double totalsulfurdioxide, double density, double pH, double sulphates, double alcohol, in_out double resultCode, in_out double tensor);
8+
resultCode = revision = 0;
9+
if null(pm) then do;
10+
pm = _new_ pymas();
11+
resultCode = pm.useModule('model_exec_3106686d-a021-449a-9c2d-f2a6f47a4948', 1);
12+
if resultCode then do;
13+
resultCode = pm.appendSrcLine('');
14+
resultCode = pm.appendSrcLine('');
15+
resultCode = pm.appendSrcLine('import math');
16+
resultCode = pm.appendSrcLine('import pickle');
17+
resultCode = pm.appendSrcLine('import pandas as pd');
18+
resultCode = pm.appendSrcLine('import numpy as np');
19+
resultCode = pm.appendSrcLine('');
20+
resultCode = pm.appendSrcLine('with open("/models/resources/viya/d02aadfe-618e-44e0-af6d-1bf00c6396e3/MLFlowTest.pickle", "rb") as _pFile:');
21+
resultCode = pm.appendSrcLine(' _thisModelFit = pickle.load(_pFile)');
22+
resultCode = pm.appendSrcLine('');
23+
resultCode = pm.appendSrcLine('def scoreMLFlowTest(fixedacidity, volatileacidity, citricacid, residualsugar, chlorides, freesulfurdioxide, totalsulfurdioxide, density, pH, sulphates, alcohol):');
24+
resultCode = pm.appendSrcLine(' "Output: tensor"');
25+
resultCode = pm.appendSrcLine('');
26+
resultCode = pm.appendSrcLine(' try:');
27+
resultCode = pm.appendSrcLine(' global _thisModelFit');
28+
resultCode = pm.appendSrcLine(' except NameError:');
29+
resultCode = pm.appendSrcLine('');
30+
resultCode = pm.appendSrcLine(' with open("/models/resources/viya/d02aadfe-618e-44e0-af6d-1bf00c6396e3/MLFlowTest.pickle", "rb") as _pFile:');
31+
resultCode = pm.appendSrcLine(' _thisModelFit = pickle.load(_pFile)');
32+
resultCode = pm.appendSrcLine('');
33+
resultCode = pm.appendSrcLine(' try:');
34+
resultCode = pm.appendSrcLine(' inputArray = pd.DataFrame([[fixedacidity, volatileacidity, citricacid, residualsugar, chlorides, freesulfurdioxide, totalsulfurdioxide, density, pH, sulphates, alcohol]],');
35+
resultCode = pm.appendSrcLine(' columns=["fixedacidity", "volatileacidity", "citricacid", "residualsugar", "chlorides", "freesulfurdioxide", "totalsulfurdioxide", "density", "pH", "sulphates", "alcohol"],');
36+
resultCode = pm.appendSrcLine(' dtype=float)');
37+
resultCode = pm.appendSrcLine(' prediction = _thisModelFit.predict(inputArray)');
38+
resultCode = pm.appendSrcLine(' except ValueError:');
39+
resultCode = pm.appendSrcLine(' # For models requiring or including an intercept value, a "const" column is required');
40+
resultCode = pm.appendSrcLine(' # For example, many statsmodels models include an intercept value that must be included for the model prediction');
41+
resultCode = pm.appendSrcLine(' inputArray = pd.DataFrame([[1.0, fixedacidity, volatileacidity, citricacid, residualsugar, chlorides, freesulfurdioxide, totalsulfurdioxide, density, pH, sulphates, alcohol]],');
42+
resultCode = pm.appendSrcLine(' columns=["const", "fixedacidity", "volatileacidity", "citricacid", "residualsugar", "chlorides", "freesulfurdioxide", "totalsulfurdioxide", "density", "pH", "sulphates", "alcohol"],');
43+
resultCode = pm.appendSrcLine(' dtype=float)');
44+
resultCode = pm.appendSrcLine(' prediction = _thisModelFit.predict(inputArray)');
45+
resultCode = pm.appendSrcLine('');
46+
resultCode = pm.appendSrcLine(' tensor = prediction');
47+
resultCode = pm.appendSrcLine('');
48+
resultCode = pm.appendSrcLine(' return(tensor)');
49+
revision = pm.publish(pm.getSource(), 'model_exec_3106686d-a021-449a-9c2d-f2a6f47a4948');
50+
51+
if ( revision < 1 ) then do;
52+
logr.log( 'e', 'py.publish() failed.');
53+
resultCode = -1;
54+
return;
55+
end;
56+
end;
57+
end;
58+
resultCode = pm.useMethod('scoreMLFlowTest');
59+
if resultCode then do;
60+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
61+
return;
62+
end;
63+
resultCode = pm.setDouble('fixedacidity', fixedacidity);
64+
if resultCode then
65+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
66+
resultCode = pm.setDouble('volatileacidity', volatileacidity);
67+
if resultCode then
68+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
69+
resultCode = pm.setDouble('citricacid', citricacid);
70+
if resultCode then
71+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
72+
resultCode = pm.setDouble('residualsugar', residualsugar);
73+
if resultCode then
74+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
75+
resultCode = pm.setDouble('chlorides', chlorides);
76+
if resultCode then
77+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
78+
resultCode = pm.setDouble('freesulfurdioxide', freesulfurdioxide);
79+
if resultCode then
80+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
81+
resultCode = pm.setDouble('totalsulfurdioxide', totalsulfurdioxide);
82+
if resultCode then
83+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
84+
resultCode = pm.setDouble('density', density);
85+
if resultCode then
86+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
87+
resultCode = pm.setDouble('pH', pH);
88+
if resultCode then
89+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
90+
resultCode = pm.setDouble('sulphates', sulphates);
91+
if resultCode then
92+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
93+
resultCode = pm.setDouble('alcohol', alcohol);
94+
if resultCode then
95+
logr.log('E', 'useMethod() failed. resultCode=$s', resultCode);
96+
resultCode = pm.execute();
97+
if (resultCode) then put 'Error: pm.execute failed. resultCode=' resultCode;
98+
else do;
99+
tensor = pm.getDouble('tensor');
100+
end;
101+
end;
102+
103+
endpackage;
104+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[
2+
{
3+
"role": "inputVariables",
4+
"name": "inputVar.json"
5+
},
6+
{
7+
"role": "outputVariables",
8+
"name": "outputVar.json"
9+
},
10+
{
11+
"role": "score",
12+
"name": "MLFlowTestScore.py"
13+
},
14+
{
15+
"role": "scoreResource",
16+
"name": "MLFlowTest.pickle"
17+
}
18+
]
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
[
2+
{
3+
"name": "fixedacidity",
4+
"length": 8,
5+
"type": "decimal",
6+
"level": "interval"
7+
},
8+
{
9+
"name": "volatileacidity",
10+
"length": 8,
11+
"type": "decimal",
12+
"level": "interval"
13+
},
14+
{
15+
"name": "citricacid",
16+
"length": 8,
17+
"type": "decimal",
18+
"level": "interval"
19+
},
20+
{
21+
"name": "residualsugar",
22+
"length": 8,
23+
"type": "decimal",
24+
"level": "interval"
25+
},
26+
{
27+
"name": "chlorides",
28+
"length": 8,
29+
"type": "decimal",
30+
"level": "interval"
31+
},
32+
{
33+
"name": "freesulfurdioxide",
34+
"length": 8,
35+
"type": "decimal",
36+
"level": "interval"
37+
},
38+
{
39+
"name": "totalsulfurdioxide",
40+
"length": 8,
41+
"type": "decimal",
42+
"level": "interval"
43+
},
44+
{
45+
"name": "density",
46+
"length": 8,
47+
"type": "decimal",
48+
"level": "interval"
49+
},
50+
{
51+
"name": "pH",
52+
"length": 8,
53+
"type": "decimal",
54+
"level": "interval"
55+
},
56+
{
57+
"name": "sulphates",
58+
"length": 8,
59+
"type": "decimal",
60+
"level": "interval"
61+
},
62+
{
63+
"name": "alcohol",
64+
"length": 8,
65+
"type": "decimal",
66+
"level": "interval"
67+
}
68+
]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[
2+
{
3+
"name": "tensor",
4+
"length": 8,
5+
"type": "decimal",
6+
"level": "interval"
7+
}
8+
]
627 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)