Commit 116efe62 authored by Fabrizio Detassis's avatar Fabrizio Detassis
Browse files
parents 4fe9e31e 715f2406
FROM python:3.8-slim-buster
FROM python:3.7-slim-buster
WORKDIR /moving-target
COPY requirements.txt requirements.txt
EXPOSE 8888
# RUN pip3 install --upgrade pip
RUN pip3 install -r requirements.txt
RUN pip3 install jupyter
COPY . /moving-target
RUN apt-get -y update
RUN apt-get -y install git curl
RUN apt-get -y update \
&& apt-get -y install git curl \
&& rm -rf /var/lib/apt/lists/*
RUN curl https://download.java.net/openjdk/jdk12/ri/openjdk-12+32_linux-x64_bin.tar.gz --output java.tar.gz
RUN tar xvf java.tar.gz
RUN curl https://download.java.net/openjdk/jdk12/ri/openjdk-12+32_linux-x64_bin.tar.gz --output java.tar.gz && tar xvf java.tar.gz && rm -f ./java.tar.gz
ENV PYTHONPATH="/moving-target/AIDDL/core/python/src:/moving-target/AIDDL/network/python"
ENV AIDDL_PATH="/moving-target/AIDDL/core/aiddl:/moving-target/AIDDL/common/aiddl"
ENV JAVA_HOME="/moving-target/jdk-12"
RUN git clone https://github.com/uwe-koeckemann/AIDDL.git && cd AIDDL && git checkout develop
RUN cd AIDDL/core/java/ && ./gradlew publishToMavenLocal
RUN cd AIDDL/common/java/ && ./gradlew publishToMavenLoca
RUN cd AIDDL/network/java/ && ./gradlew publishToMavenLocal
ENV PATH="/moving-target/jdk-12/bin:${PATH}"
RUN git clone https://github.com/uwe-koeckemann/AIDDL.git \
&& cd AIDDL && git checkout develop \
&& cd core/java/ && ./gradlew publishToMavenLocal \
&& cd ../../common/java/ && ./gradlew publishToMavenLocal \
&& cd ../../network/java/ && ./gradlew publishToMavenLocal
WORKDIR /moving-target/deps
RUN sh cplex_studio1210.linux-x86-64.bin -f response.properties \
&& python3 /opt/ibm/ILOG/CPLEX_Studio1210/python/setup.py install \
&& rm -rf /deps
WORKDIR /moving-target
RUN jupyter trust ./jupyter/Regression_Example.ipynb
......
(#mod self org.aiddl.example.moving-target.enc-test)
(#nms EVAL org.aiddl.eval-ht)
(#req SL org.aiddl.common.learning.supervised)
(^RegressionProblem@SL enc-test-01
(
attributes:[(y ^#real) (x ^#real)]
label:y
data:[
[1.0 a]
[2.0 b]
[3.0 c]
]
))
......@@ -65,11 +65,13 @@
(#tuple moving-targets-problem
(
examples:$examples ;; Regular supervised ML problem
loss-function:MeanSquareError ;; Select available loss function
loss-function:MeanSquaredError ;; Select available loss function
constraints:{
(> y -30) ;; Each element in set needs to be translated to PySMT
;;(fairness-1 y 1.0)
(>= y -30) ;; Each element in set needs to be translated to PySMT
(didi-real y [x] 0.5)
(didi-bin y [x] 0.5)
(balance y 0.1)
}
alpha:1 ;; Parameter alpha
beta:1 ;; Parameter beta
))
\ No newline at end of file
))
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
......@@ -7,12 +7,16 @@ from aiddl_core.representation.tuple import Tuple
from aiddl_core.container.container import Container
import aiddl_core.function.default as dfun
from aiddl_core.tools.logger import Logger
import aiddl_core.parser.parser as parser
from aiddl_network.grpc_function import GrpcFunction
from aiddl_network.aiddl_grpc_server import AiddlServicer
from aiddl_network.aiddl_grpc_server import LOADER_URI
from moving_target_cplex import MovingTargetRegCplex
# Loaded modules (aka AIDDL files) go to container:
C = Container()
......@@ -21,7 +25,7 @@ C = Container()
F = dfun.get_default_function_registry(C)
# Load example (returns URI of module)
example_module_uri = parser.parse("../..//aiddl/example-01.aiddl", C, F, ".")
example_module_uri = parser.parse("../../aiddl/example-01.aiddl", C, F)
# Fetch "examples" entry from module:
example_entry = C.get_entry(Symbolic("examples"), module=example_module_uri)
# Take value of entry:
......@@ -47,12 +51,33 @@ dt_learner_conf = parser.parse_term('''
config:{}
)
''')
ls_expansion = parser.parse_term('''
(
name:Expansion
module:my
class:org.aiddl.common.learning.linear_regression.ExpansionFunction
config:{}
)
''')
f_create.apply(ls_expansion)
ls_learner_conf = parser.parse_term('''
(
name:LeastSquares
module:my
class:org.aiddl.common.learning.linear_regression.LinearRegression
config:{}
config:{ expansion:^my.Expansion }
)
''')
lap_cfg = parser.parse_term('''
(
name:LearnAndApplyFunction
module:my
class:org.aiddl.common.learning.supervised.LearnAndApplyFunction
config:{ learner:^my.LeastSquares }
)
''')
......@@ -66,10 +91,20 @@ mse_learner_uri = f_create.apply(ls_learner_conf)
# Create local proxy to newly created function
f_MSE = GrpcFunction(host, port, mse_learner_uri)
# Create function on server
lap_uri = f_create.apply(lap_cfg)
# Create local proxy to newly created function
f_LAP = GrpcFunction(host, port, lap_uri)
# Finally, we can apply mean square error to data:
weights = f_MSE.apply(example_data)
print("Weights:", weights)
# print("Weights:", weights)
# y_k = f_LAP.apply(example_data)
# print("Result:", y_k)
# Create local function to expand data and
# hook it into least squares function running on server
......@@ -79,3 +114,13 @@ print("Weights:", weights)
# F.add_function(ExpandData(), Symbolic("my.expander"))
mtc = MovingTargetRegCplex(f_LAP, n=30)
mt_data = C.get_entry(Symbolic("moving-targets-problem"), module=example_module_uri).get_value()
mt_data = mt_data.resolve(C)
# print(Logger.pretty_print(mt_data, 0))
mtc.apply(mt_data)
# from _typeshed import NoneType
from abc import ABC, abstractmethod
from re import A
import numpy as np
from aiddl_core.representation.list import List
from aiddl_core.representation.symbolic import Symbolic
from aiddl_core.representation.real import Real
from aiddl_core.representation.tuple import Tuple
class MovingTarget(ABC):
def __init__(self, n=10):
def __init__(self, ML, n=10):
self.n = n
self.ML = ML
self.y_k_history = []
def apply(self, args):
d = args[Symbolic("examples")][Symbolic("data")] # d = (x_s, y_s)
ml_problem = args[Symbolic("examples")]
d = self.convert_data(args[Symbolic("examples")]) # d = (x_s, y_s)
L = args[Symbolic("loss-function")]
C = args[Symbolic("constraints")]
alpha = args[Symbolic("alpha")]
......@@ -25,19 +31,22 @@ class MovingTarget(ABC):
# self.set_loss_function(M, L, d)
# d_data = self.get_pysmt_data(y_k)
y_k = self.ML.get_function().apply(d)
y_k = self.ML.apply(ml_problem)
for i in range(0, self.n):
sat_C = self.check_constraints_ext(M, C, d)
self.y_k_history.append(np.array(y_k.unpack()))
sat_C = self.check_constraints_ext(M, C, (d[0], np.array(y_k.unpack())))
if not sat_C:
self.m_alpha(M, L, y_k, alpha)
else:
self.m_beta(M, L, y_k, beta)
print("-------------------------")
z_k = self.solve_ext(M)
ml_problem = self.assemble_ml_problem(args, z_k)
ml_problem = self.assemble_ml_problem(ml_problem, z_k)
y_k = self.ML.apply(ml_problem)
print(y_k)
return y_k
@abstractmethod
def add_constraints(self, M, C, y_s):
......@@ -63,14 +72,36 @@ class MovingTarget(ABC):
def initialize_ext(self, d):
"""Initialize external solver and return blank model."""
def convert_data(self, current):
label = current[Symbolic('label')]
attributes = current[Symbolic('attributes')]
data = current[Symbolic('data')]
label_idx = None
for i in range(len(attributes)):
if attributes[i][0] == label:
label_idx = i
break
y = []
x = []
for i in range(len(data)):
y.append(data[i][label_idx].real_value())
x_row = []
for j in range(len(data[i])):
if j != label_idx:
x_row.append(data[i][j].real_value())
x.append(x_row)
x = np.array(x)
y = np.array(y)
return x, y
def assemble_ml_problem(self, current, y_k):
"""Insert current label vector into machine learning problem."""
label = current[Symbolic('label')]
attributes = current[Symbolic['attributes']]
data = current[Symbolic['data']]
attributes = current[Symbolic('attributes')]
data = current[Symbolic('data')]
label_idx = None
for i in range(len(attributes)):
if A[i][0] == label:
if attributes[i][0] == label:
label_idx = i
break
new_data = []
......@@ -78,7 +109,7 @@ class MovingTarget(ABC):
row = []
for j in range(len(data[i])):
if j == label_idx:
row.append(y_k[i])
row.append(Real(y_k[i]))
else:
row.append(data[i][j])
new_data.append(Tuple(row))
......
import numpy as np
from aiddl_core.representation.symbolic import Symbolic
from moving_target_abc import MovingTarget
from docplex.mp.model import Model as CPModel
from docplex.mp.model import DOcplexException
......@@ -34,8 +36,13 @@ class MovingTargetRegCplex(MovingTarget):
]
"""
for c in C:
ctype, cvar, cval = c
print(c)
ctype = c[0].string_value()
cvar = c[1].string_value()
cval = c[2].real_value()
# ctype, cvar, cval = c
# Store the constraint in the class.
cstr = InequalityGlobalConstraint('ct', ctype, cval)
self.constraints.append(cstr)
......@@ -61,20 +68,20 @@ class MovingTargetRegCplex(MovingTarget):
n_points = len(y_k)
idx_var = [i for i in range(n_points)]
x = [M.get_var_by_name(s) for s in self.variables]
y_k = y_k.flatten()
y_k = np.array(y_k.unpack())
if L == 'MSE' or L == 'MeanSquaredError':
if L == Symbolic('MSE') or L == Symbolic('MeanSquaredError'):
y_loss = (1.0 / n_points) * M.sum([(self.y[i] - x[i]) * (self.y[i] - x[i]) for i in idx_var])
p_loss = (1.0 / n_points) * M.sum([(y_k[i] - x[i]) * (y_k[i] - x[i]) for i in idx_var])
elif L == 'MAE' or L == 'MeanAbsoluteError':
elif L == Symbolic('MAE') or L == Symbolic('MeanAbsoluteError'):
y_loss = (1.0 / n_points) * M.sum([M.abs(self.y[i] - x[i]) for i in idx_var])
p_loss = (1.0 / n_points) * M.sum([M.abs(y_k[i] - x[i]) for i in idx_var])
else:
raise NotImplementedError("Loss function not recognized!")
obj_func = y_loss + (1.0 / alpha) * p_loss
obj_func = y_loss + (1.0 / alpha.real_value()) * p_loss
M.minimize(obj_func)
def m_beta(self, M, L, y_k, beta):
......@@ -82,13 +89,13 @@ class MovingTargetRegCplex(MovingTarget):
n_points = len(y_k)
idx_var = [i for i in range(n_points)]
x = [M.get_var_by_name(s) for s in self.variables]
y_k = y_k.flatten()
y_k = np.array(y_k.unpack())
if L == 'MSE' or L == 'MeanSquaredError':
if L == Symbolic('MSE') or L == Symbolic('MeanSquaredError'):
y_loss = (1.0 / n_points) * M.sum([(self.y[i] - x[i]) * (self.y[i] - x[i]) for i in idx_var])
p_loss = (1.0 / n_points) * M.sum([(y_k[i] - x[i]) * (y_k[i] - x[i]) for i in idx_var])
elif L == 'MAE' or L == 'MeanAbsoluteError':
elif L == Symbolic('MAE') or L == Symbolic('MeanAbsoluteError'):
y_loss = (1.0 / n_points) * M.sum([M.abs(self.y[i] - x[i]) for i in idx_var])
p_loss = (1.0 / n_points) * M.sum([M.abs(y_k[i] - x[i]) for i in idx_var])
......@@ -96,7 +103,7 @@ class MovingTargetRegCplex(MovingTarget):
raise NotImplementedError("Loss function not recognized!")
obj_func = y_loss
M.add(p_loss <= beta)
M.add(p_loss <= beta.real_value())
M.minimize(obj_func)
def check_constraints_ext(self, M, C, d):
......@@ -119,6 +126,8 @@ class MovingTargetRegCplex(MovingTarget):
x = [M.get_var_by_name(s) for s in self.variables]
y_opt = np.array([_x.solution_value for _x in x])
print("y_opt:", y_opt)
return y_opt
def initialize_ext(self, d, name='cplex_model'):
......@@ -135,7 +144,7 @@ class MovingTargetRegCplex(MovingTarget):
# Variable declaration.
n_points = len(y)
idx_var = [i for i in range(n_points)]
mod.continuous_var_list(keys=idx_var, lb=-10.0, ub=10.0, name='y')
mod.continuous_var_list(keys=idx_var, lb=min(y)-10.0, name='y')
# Store variable names.
self.variables = ['y_%d' %i for i in idx_var]
......
from aiddl_core.representation.numerical import Numerical
from aiddl_core.representation.symbolic import Symbolic
from aiddl_core.representation.integer import Integer
from aiddl_core.representation.real import Real
from aiddl_core.representation.infinity import Infinity
from aiddl_core.representation.list import List
from aiddl_core.representation.tuple import Tuple
from aiddl_core.function.function import Function
class OneHotEncoder(Function):
def createNormalizer(o, d):
return lambda x: [(o+x)/(d+o)]
def apply(self, mlProblem):
atts = mlProblem[Symbolic("attributes")]
label = mlProblem[Symbolic("label")]
data = mlProblem[Symbolic("data")]
encoding = {}
decoding = []
max_array = []
for i in range(len(atts)):
is_numerical = True
min = Infinity.pos()
max = Infinity.neg()
domain = set()
for j in range(len(data)):
x = data[j][i]
is_numerical &= isinstance(x, Numerical)
if is_numerical:
if min > x:
min = x
if max < x:
max = x
domain.add(x)
if not is_numerical:
encoding_i = {}
decoding_i = []
j = 0
for e in domain:
encoding_i[e] = [0]*j + [1] + [0]*(len(domain)-j-1)
j += 1
decoding_i.append(e)
encoding[i] = encoding_i.get
decoding.append(List(decoding_i))
max_array.append(None)
else:
max_array.append(max)
encoding[i] = OneHotEncoder.createNormalizer(Integer(-1) * min, max)
decoding.append(Tuple([Integer(-1) * min, max]))
enc_data = []
for row in data:
enc_row = []
for i in range(len(row)):
enc_row += encoding[i](row[i])
enc_data.append(List(enc_row))
mlProblem = mlProblem.put(Symbolic("data"), List(enc_data))
mlProblem = mlProblem.put(Symbolic("decoding"), List(decoding))
return mlProblem
import numpy as np
import sklearn
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingRegressor, RandomForestRegressor
from sklearn.exceptions import NotFittedError
from sklearn.naive_bayes import GaussianNB
from aiddl_core.parser.parser import parse_term
from aiddl_core.representation.symbolic import Symbolic
from aiddl_core.representation.integer import Integer
from aiddl_core.representation.list import List
from aiddl_core.function.function import Function
class RandomForestLearner(Function):
def __init__(self):
self.n_estimators = 50
self.max_depth = 5
self.model = RandomForestClassifier(n_estimators=self.n_estimators, max_depth=self.max_depth)
def configure(self, cfg, freg):
self.n_estimators = cfg.get_or_default(Symbolic("n_estimators"), Integer(self.n_estimators)).int_value()
self.n_estimators = cfg.get_or_default(Symbolic("max_depth"), Integer(self.max_depth)).int_value()
self.model = RandomForestClassifier(n_estimators=self.n_estimators, max_depth=self.max_depth)
def apply(self, mlProblem):
x, y = splitAiddlMlProblem(mlProblem)
self.model.fit(x, y)
y_p = self.model.predict(x)
r = []
for e in y_p:
r.append(parse_term(str(e)))
return List(r)
# def fit(self, x, y):
# self.model.fit(x, y)
# def predict(self, x):
# return self.model.predict(x)
# def predict_proba(self, x):
# return self.model.predict_proba(x)
class GBTree(Function):
def __init__(self):
self.n_estimators = 50
self.min_samples_leaf = 5
self.model = GradientBoostingRegressor(n_estimators=self.n_estimators,
min_samples_leaf=self.min_samples_leaf)
def configure(self, cfg, freg):
self.n_estimators = cfg.get_or_default(Symbolic("n_estimators"), Integer(self.n_estimators)).int_value()
self.n_estimators = cfg.get_or_default(Symbolic("min_samples_leaf"), Integer(self.min_samples_leaf)).int_value()
self.model = GradientBoostingRegressor(n_estimators=self.n_estimators,
min_samples_leaf=self.min_samples_leaf)
def apply(self, mlProblem):
x, y = splitAiddlMlProblem(mlProblem)
self.model.fit(x, y)
y_p = self.model.predict(x)
print(y_p)
r = []
for e in y_p:
r.append(parse_term(str(e)))
return List(r)
def splitAiddlMlProblem(mlProblem):
atts = mlProblem[Symbolic("attributes")]
label = mlProblem[Symbolic("label")]
data = mlProblem[Symbolic("data")]
y = []
x = []
labelIdx = -1
for i in range(len(atts)):
if atts[i][0] == label:
labelIdx = i
break
c = 0
for row in data:
x_row = []
for i in range(len(row)):
if i == labelIdx:
y.append(row[i].unpack())
else:
x_row.append(row[i].unpack())
print(c, row[i], type(row[i]), type(row[i].unpack()))
c += 1
x.append(x_row)
return x, y
from abc import ABC, abstractmethod
from aiddl_core.representation.symbolic import Symbolic
from aiddl_core.representation.integer import Integer
from aiddl_core.representation.infinity import Infinity
from aiddl_core.representation.tuple import Tuple
from aiddl_core.container.container import Container
import aiddl_core.function.default as dfun
from aiddl_core.tools.logger import Logger
import aiddl_core.parser.parser as parser
from aiddl_network.grpc_function import GrpcFunction
from aiddl_network.aiddl_grpc_server import AiddlServicer
from aiddl_network.aiddl_grpc_server import LOADER_URI
from preprocessing import OneHotEncoder
# Loaded modules (aka AIDDL files) go to container:
C = Container()
# Loaded functions (#def in modules, or MovingTargetCplex instance)
# go to function registry:
F = dfun.get_default_function_registry(C)
# Load example (returns URI of module)
example_module_uri = parser.parse("../../aiddl/encoding-test.aiddl", C, F)
# Fetch "examples" entry from module:
example_entry = C.get_entry(Symbolic("enc-test-01"), module=example_module_uri)
# Take value of entry:
example_data = example_entry.get_value()
encoder = OneHotEncoder()
print(Logger.pretty_print(example_data, 0))
encoded_prob = encoder.apply(example_data)
print(Logger.pretty_print(encoded_prob, 0))
......@@ -2,4 +2,5 @@ grpcio==1.37.0
grpcio-tools==1.37.0
matplotlib==3.4.1
numpy==1.20.2
pysmt==0.9.0
\ No newline at end of file
pysmt==0.9.0
jupyter==1.0.0