Commit 0b99ff5e authored by Uwe Köckemann's avatar Uwe Köckemann
Browse files

Documentation, cleaned notebooks, fixed bug when using ortools

parent f3c7c086
No related merge requests found
......@@ -29,6 +29,11 @@ RUN git clone https://github.com/uwe-koeckemann/AIDDL.git \
&& cd ../../common/java/ && ./gradlew publishToMavenLocal \
&& cd ../../network/java/ && ./gradlew publishToMavenLocal
################################
# To use cplex:
# 1) Uncomment the instructions below
# 2) Place cplex binary deps directory
################################
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 \
......
#+TITLE: AI Integration Languages: A Case Study in Constraint Machine Learning
This repository contains the results of the [[https:www.humane-ai.eu][Humane AI Net]] Micro Project ~AI
Integration Languages: A Case Study in Constraint Machine Learning~.
The easiest way to try the results is via [[https:docs.docker.com/engine/install/][Docker]]. Docker essentially creates a
virtual machine starting from a base image and then performs the minimal setup
required to run some software (in this case our moving target notebooks). All
information needed for this can be found in the ~Dockerfile~ at the root of this
repository. Alternatively, you can follow the instructions in the ~Dockerfile~ to
create an environment that can run our Jupyter notebooks (Python 3.7 is required
and we recommend setting up a virtual environment, e.g., via [[https:docs.conda.io/en/latest/miniconda.html][Miniconda]]).
To build the container open a terminal in this folder and run:
#+begin_src
......@@ -15,3 +26,9 @@ docker run --rm --publish=8888:8888 moving-target-aiddl:latest
A local link to the jupyter notebook will appear in the console. Open the link
in a browser and select a notebook to try it. For now there is a single notebook
running linear regression through AIDDL.
~Note:~ currently [[https:www.ibm.com/analytics/cplex-optimizer][IBM's CPLEX Optimizter]] is required and the corresponding binary
file ~cplex_studio1210.linux-x86-64.bin~ must be placed in the ~deps~ folder. For
obvious reasons we do not provide the binary ourselves but a free academic
edition of CPLEX is available following the link above. We will update the
notebooks to make CPLEX optional as soon as possible.
......@@ -28,11 +28,6 @@
"if module_path not in sys.path:\n",
" sys.path.append(module_path)\n",
"\n",
"from moving_target_cplex import MovingTargetRegCplex\n",
"from moving_target_cplex import MovingTargetClsCplex\n",
"from moving_target_ortools import MovingTargetRegOT\n",
"from moving_target_ortools import MovingTargetClsOT\n",
"\n",
"from factory import moving_targets_factory\n",
"from tools import CsvLoader\n",
"from utils import didi_r\n",
......@@ -126,8 +121,8 @@
"output_type": "stream",
"text": [
"DIDI (pre-learning): 0.18046885714845506\n",
"DIDI (post-learning): 0.2278699416515176\n",
"MSE (test data): 0.007579562360896998\n"
"DIDI (post-learning): 0.22802470095999794\n",
"MSE (test data): 0.007566857207861887\n"
]
}
],
......@@ -210,7 +205,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
......@@ -234,7 +229,7 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
......@@ -250,7 +245,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 7,
"metadata": {},
"outputs": [
{
......@@ -312,6 +307,20 @@
" i += 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
......
......@@ -29,11 +29,6 @@
"if module_path not in sys.path:\n",
" sys.path.append(module_path)\n",
"\n",
"from moving_target_cplex import MovingTargetRegCplex\n",
"from moving_target_cplex import MovingTargetClsCplex\n",
"from moving_target_ortools import MovingTargetRegOT\n",
"from moving_target_ortools import MovingTargetClsOT\n",
"\n",
"from factory import moving_targets_factory\n",
"from tools import CsvLoader\n",
"from utils import didi_r\n",
......@@ -41,7 +36,10 @@
"from scikit_learn_wrapper import splitAiddlMlProblem\n",
"\n",
"from sklearn.metrics import accuracy_score\n",
"from sklearn.metrics import mean_squared_error"
"from sklearn.metrics import mean_squared_error\n",
"\n",
"from moving_target_ortools import MovingTargetRegOT\n",
"from moving_target_ortools import MovingTargetClsOT"
]
},
{
......@@ -162,7 +160,7 @@
" alpha:?a ;; Parameter alpha\n",
" beta:?b ;; Parameter beta\n",
" problem-type:regression ;; classification/regression?\n",
" constraint-solver:cplex ;; Select constraint solver (cplex/pysmt)\n",
" constraint-solver:ortools ;; Select constraint solver (cplex/ortools/pysmt)\n",
" learner:gradient-boosting-regressor ;; URI of learner (registered above)\n",
")''')"
]
......@@ -183,7 +181,7 @@
"outputs": [],
"source": [
"mt_data_exp = parse('''{\n",
" loss-function:MeanSquaredError ;; Select loss function\n",
" loss-function:MeanAbsoluteError ;; Select loss function\n",
" constraints:{\n",
" (didi \"violentPerPop\" [\"race\"] ?q)\n",
" }\n",
......@@ -213,8 +211,8 @@
" [Real(0.5), Real(1.0)]\n",
"]\n",
"exp_choices = [\n",
" [Real(0.01)],\n",
" [Real(0.01), Real(0.1), Real(1.0)], \n",
" [Real(0.01), Real(0.1), Real(1.0)],\n",
" [Real(0.1)], \n",
" [Real(0.1)]\n",
"]"
]
......@@ -231,21 +229,89 @@
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Experiment 1 --- {?q:0.01 ?a:0.01 ?b:0.1}\n",
"\tMSE: [0.007588565538294634, 0.008131744502836076, 0.008251143707917746, 0.008271531001695245, 0.008299917084728419, 0.008438876263755632, 0.008537551291707692, 0.008654730678913905, 0.008734091334804964, 0.008759243243717194]\n",
"\tDIDI: [0.22793670295719143, 0.026074799129800402, 0.02271436112802383, 0.029382616748211576, 0.026316159345737944, 0.029813426469609022, 0.027741503410432092, 0.027882408279166257, 0.02407727939724455, 0.026403834335311502]\n",
"Experiment 2 --- {?q:0.01 ?a:0.1 ?b:0.1}\n",
"\tMSE: [0.0075826448019711565, 0.008182087611238203, 0.008188589333784605, 0.008252837900160296, 0.008323044365123695, 0.008291525110291525, 0.008265260611368001, 0.008305757523369348, 0.008322008767789223, 0.008392240059471558]\n",
"\tDIDI: [0.22809099757238005, 0.022512617567149673, 0.02901920210460053, 0.027128540474840784, 0.023153865500196005, 0.03005582253330895, 0.024004495388340985, 0.022570724322993924, 0.019212757555981785, 0.016868118959705525]\n",
"Experiment 3 --- {?q:0.01 ?a:1.0 ?b:0.1}\n",
"\tMSE: [0.007607322026272641, 0.00813858058873332, 0.008027421318854578, 0.008035467378250425, 0.007977773135693209, 0.008051132573259906, 0.007908165685712329, 0.008033408305663903, 0.008146265111157003, 0.008115958823143744]\n",
"\tDIDI: [0.22774664014697008, 0.02505018952006889, 0.0351762833305775, 0.020584737130891914, 0.029271441437475787, 0.029012714331511855, 0.032824425586367556, 0.03004223912777998, 0.01886469080727733, 0.018902679851626192]\n"
"Initializing model\n",
"Constraint added: ('didi', 'violentPerPop', [15], 0.01)\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Experiment 1 --- {?q:0.01 ?a:0.1 ?b:0.1}\n",
"\tMSE: [0.0075649999432197785, 0.008530069799771141, 0.008548233691510771, 0.008498669905116565, 0.008427397889178548, 0.008569340042030802, 0.008551833063050502, 0.008455712109618931, 0.027763400410349862, 0.02768183036604746]\n",
"\tDIDI: [0.2280682687346325, 0.05094295119441482, 0.053259187314152995, 0.05559364454608068, 0.05781008494006891, 0.04394251566917626, 0.038524931348284386, 0.05436155866195111, 0.000661859070061047, 9.355019065670928e-05]\n",
"Initializing model\n",
"Constraint added: ('didi', 'violentPerPop', [15], 0.1)\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Experiment 2 --- {?q:0.1 ?a:0.1 ?b:0.1}\n",
"\tMSE: [0.007588003613171019, 0.007906674299587958, 0.007900176954594803, 0.007995230779557692, 0.007946528856603964, 0.007866819668687346, 0.008047197687253146, 0.007617327913203704, 0.027824013460150242, 0.02767700693493508]\n",
"\tDIDI: [0.22794109178949823, 0.13473696305239571, 0.1316695576569858, 0.12707686632408643, 0.12917608258843566, 0.12482873204718598, 0.1300031341470565, 0.10499027144651946, 0.0006531467950797183, 3.5610045082483e-05]\n",
"Initializing model\n",
"Constraint added: ('didi', 'violentPerPop', [15], 1.0)\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Constraint satisfaction: True\n",
"Solving\n",
"Experiment 3 --- {?q:1.0 ?a:0.1 ?b:0.1}\n",
"\tMSE: [0.0075753209453758115, 0.007575360995763902, 0.007562777782553964, 0.007578252200353943, 0.0075788085477299545, 0.007586122957775647, 0.007586557677977061, 0.0075963029735288115, 0.027681729171628547, 0.027675562114745537]\n",
"\tDIDI: [0.22807828809058894, 0.22794580558788946, 0.2281122734614801, 0.22807129080185268, 0.22810444746015368, 0.22793314661911016, 0.22788304311607913, 0.22785403737016305, 2.5798229396370304e-14, 2.745704556514911e-06]\n"
]
}
],
......@@ -254,7 +320,7 @@
"\n",
"exp_id = 1\n",
"cIter = ComboIterator(exp_choices)\n",
"for combo in cIter:\n",
"for combo in cIter: \n",
" s = Substitution()\n",
" for i in range(len(exp_vars)):\n",
" s.add(exp_vars[i], combo[i])\n",
......@@ -348,6 +414,13 @@
"plt.legend()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
......
......@@ -157,8 +157,8 @@
"output_type": "stream",
"text": [
"DIDI (pre-learning): 1.3178840744255598\n",
"DIDI (post-learning): 1.162334319282314\n",
"ACC (test data): 0.8519807724183657\n"
"DIDI (post-learning): 1.1725631788433029\n",
"ACC (test data): 0.8562904027846843\n"
]
}
],
......@@ -281,7 +281,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 7,
"metadata": {
"scrolled": true
},
......@@ -291,7 +291,26 @@
"output_type": "stream",
"text": [
"Constraint added: FairnessConstraint: didi <= 0.01\n",
"Constraint satisfaction: False\n"
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n",
"Constraint satisfaction: False\n",
"Solving\n"
]
}
],
......@@ -318,16 +337,16 @@
"output_type": "stream",
"text": [
"n ACC DIDI\n",
"0 0.8556 1.2272\n",
"1 0.2536 0.0000\n",
"2 0.2536 0.0000\n",
"3 0.2536 0.0000\n",
"4 0.2536 0.0000\n",
"5 0.2536 0.0000\n",
"6 0.2536 0.0000\n",
"7 0.2536 0.0000\n",
"8 0.2536 0.0000\n",
"9 0.2536 0.0000\n"
"0 0.8553 1.2083\n",
"1 0.8533 0.9210\n",
"2 0.8553 0.9807\n",
"3 0.8545 0.9143\n",
"4 0.8568 0.9761\n",
"5 0.8540 0.9939\n",
"6 0.8555 0.9858\n",
"7 0.8523 1.0195\n",
"8 0.8566 0.9139\n",
"9 0.8553 1.0617\n"
]
}
],
......
This diff is collapsed.
......@@ -51,24 +51,7 @@
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Parsing: /home/uwe/Work/Projects/moving-targets/aiddl-project/aiddl/example-01.aiddl\n",
"Parsing: /home/uwe/Work/Projects/aiddl-pub/core/aiddl/eval-ht.aiddl\n",
"Parsing: /home/uwe/Work/Projects/aiddl-pub/common/aiddl/learning/supervised.aiddl\n",
"Parsing: /home/uwe/Work/Projects/aiddl-pub/core/aiddl/eval.aiddl\n",
"Parsing: /home/uwe/Work/Projects/aiddl-pub/common/aiddl/domain.aiddl\n",
"Parsing: /home/uwe/Work/Projects/aiddl-pub/core/aiddl/eval.aiddl\n",
"Parsing: /home/uwe/Work/Projects/aiddl-pub/common/aiddl/reasoning/logic/first-order.aiddl\n",
"Parsing: /home/uwe/Work/Projects/aiddl-pub/core/aiddl/eval.aiddl\n",
"Parsing: /home/uwe/Work/Projects/aiddl-pub/common/aiddl/math/linear-algebra/linear-algebra.aiddl\n",
"Parsing: /home/uwe/Work/Projects/aiddl-pub/core/aiddl/eval.aiddl\n"
]
}
],
"outputs": [],
"source": [
"# Loaded modules (aka AIDDL files) go to container:\n",
"C = Container()\n",
......@@ -195,19 +178,22 @@
"name": "stdout",
"output_type": "stream",
"text": [
"(1.0 10.0 100.0 1.0 42.0 1764.0)\n",
"String 0 is localhost\n"
"(1.0 10.0 100.0 1.0 42.0 1764.0)\n"
]
},
{
"data": {
"text/plain": [
"<aiddl_core.representation.function_reference.FunctionReference at 0x7f8bd6cfe458>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
"ename": "_InactiveRpcError",
"evalue": "<_InactiveRpcError of RPC that terminated with:\n\tstatus = StatusCode.UNAVAILABLE\n\tdetails = \"failed to connect to all addresses\"\n\tdebug_error_string = \"{\"created\":\"@1628517518.881042459\",\"description\":\"Failed to pick subchannel\",\"file\":\"src/core/ext/filters/client_channel/client_channel.cc\",\"file_line\":3008,\"referenced_errors\":[{\"created\":\"@1628517518.881040325\",\"description\":\"failed to connect to all addresses\",\"file\":\"src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc\",\"file_line\":397,\"grpc_status\":14}]}\"\n>",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31m_InactiveRpcError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-7-1695c926d33b>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 12\u001b[0m )\n\u001b[1;32m 13\u001b[0m ''')\n\u001b[0;32m---> 14\u001b[0;31m \u001b[0mf_hook\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmy_expansion\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m~/Work/Projects/aiddl-pub/network/python/aiddl_network/grpc_function.py\u001b[0m in \u001b[0;36mapply\u001b[0;34m(self, args)\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;31m# print(\"-------------- Request --------------\")\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 29\u001b[0m \u001b[0mreq\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0maiddl_pb2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFunctionCallRequest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunction_uri\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfunction_uri\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0marg\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# Create request\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 30\u001b[0;31m \u001b[0manswer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstub\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFunctionCall\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mreq\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# Execute request\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 31\u001b[0m \u001b[0;31m# print(\"-------------- Answer --------------\")\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 32\u001b[0m \u001b[0;31m# print(answer)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/Programs/python-venv/python3.7/lib/python3.7/site-packages/grpc/_channel.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, request, timeout, metadata, credentials, wait_for_ready, compression)\u001b[0m\n\u001b[1;32m 944\u001b[0m state, call, = self._blocking(request, timeout, metadata, credentials,\n\u001b[1;32m 945\u001b[0m wait_for_ready, compression)\n\u001b[0;32m--> 946\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m_end_unary_response_blocking\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstate\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcall\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 947\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 948\u001b[0m def with_call(self,\n",
"\u001b[0;32m~/Programs/python-venv/python3.7/lib/python3.7/site-packages/grpc/_channel.py\u001b[0m in \u001b[0;36m_end_unary_response_blocking\u001b[0;34m(state, call, with_call, deadline)\u001b[0m\n\u001b[1;32m 847\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mstate\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresponse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 848\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 849\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0m_InactiveRpcError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstate\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 850\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 851\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31m_InactiveRpcError\u001b[0m: <_InactiveRpcError of RPC that terminated with:\n\tstatus = StatusCode.UNAVAILABLE\n\tdetails = \"failed to connect to all addresses\"\n\tdebug_error_string = \"{\"created\":\"@1628517518.881042459\",\"description\":\"Failed to pick subchannel\",\"file\":\"src/core/ext/filters/client_channel/client_channel.cc\",\"file_line\":3008,\"referenced_errors\":[{\"created\":\"@1628517518.881040325\",\"description\":\"failed to connect to all addresses\",\"file\":\"src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc\",\"file_line\":397,\"grpc_status\":14}]}\"\n>"
]
}
],
"source": [
......@@ -948,6 +934,19 @@
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": false,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"ename": "ImportError",
"evalue": "cannot import name 'GBTree' from 'scikit_learn_wrapper' (/home/uwe/Work/Projects/moving-targets/aiddl-project/python/moving_target/scikit_learn_wrapper.py)",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-1-f7efb1359eb3>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 34\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mtools\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mCsvLoader\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 35\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mutils\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mdidi_c\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 36\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mscikit_learn_wrapper\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mGBTree\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 37\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mscikit_learn_wrapper\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mSciKitLearnFunction\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mscikit_learn_wrapper\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0msplitAiddlMlProblem\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mImportError\u001b[0m: cannot import name 'GBTree' from 'scikit_learn_wrapper' (/home/uwe/Work/Projects/moving-targets/aiddl-project/python/moving_target/scikit_learn_wrapper.py)"
]
}
],
"source": [
"from abc import ABC, abstractmethod\n",
"\n",
"import random as r\n",
"\n",
"import matplotlib.pyplot as plt\n",
"plt.style.use('seaborn-whitegrid')\n",
"import numpy as np\n",
"\n",
"from aiddl_core.representation.symbolic import Symbolic\n",
"from aiddl_core.representation.integer import Integer\n",
"from aiddl_core.representation.real import Real\n",
"from aiddl_core.representation.infinity import Infinity\n",
"from aiddl_core.representation.tuple import Tuple\n",
"from aiddl_core.representation.list import List\n",
"from aiddl_core.container.container import Container\n",
"import aiddl_core.function.default as dfun\n",
"from aiddl_core.tools.logger import Logger\n",
"from aiddl_core.parser.parser import parse_term\n",
"\n",
"from aiddl_network.grpc_function import GrpcFunction\n",
"from aiddl_network.aiddl_grpc_server import AiddlServicer\n",
"from aiddl_network.aiddl_grpc_server import LOADER_URI\n",
"\n",
"import os\n",
"import sys\n",
"module_path = os.path.abspath(os.path.join('../python/moving_target'))\n",
"if module_path not in sys.path:\n",
" sys.path.append(module_path)\n",
"\n",
"from moving_target_cplex import MovingTargetRegCplex\n",
"from moving_target_cplex import MovingTargetClsCplex\n",
"from factory import get_problem\n",
"from preprocessing import OneHotEncoder\n",
"from tools import CsvLoader\n",
"from utils import didi_c\n",
"from scikit_learn_wrapper import GBTree\n",
"from scikit_learn_wrapper import SciKitLearnFunction\n",
"from scikit_learn_wrapper import splitAiddlMlProblem"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Setup\n",
"\n",
"Create container and function registry and load some example data from a local file."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"C = Container()\n",
"F = dfun.get_default_function_registry(C)\n",
"\n",
"loader = CsvLoader()\n",
"\n",
"test_data = loader.apply(parse_term('(\"../resources/whitewine_test.csv\" \",\" \"quality\")'))\n",
"train_data = loader.apply(parse_term('(\"../resources/whitewine_train.csv\" \",\" \"quality\")'))\n",
"\n",
"print(\"Label:\", test_data[Symbolic(\"label\")])\n",
"print(\"Attributes:\", Logger.pretty_print(test_data[Symbolic(\"attributes\")], 1))\n",
"print(\"Data (first row):\", Logger.pretty_print(test_data[Symbolic(\"data\")][0], 1))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Estimate Weights\n",
"\n",
"Finally, we can estimate the weights based on the resulting data set."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"learner = parse_term('''{\n",
" py_module:sklearn.ensemble\n",
" py_class:RandomForestClassifier\n",
" n_estimators:50\n",
" max_depth:5\n",
"}''')\n",
"\n",
"\n",
"f_ML = SciKitLearnFunction(learner)\n",
"F.add_function(Symbolic(\"mt.learner\"), f_ML)\n",
"\n",
"x, y = splitAiddlMlProblem(train_data)\n",
"x_test, y_test = splitAiddlMlProblem(test_data)\n",
"\n",
"y_0 = f_ML.apply(train_data)\n",
"\n",
"labels, counts = np.unique(y_0.unpack(), return_counts=True)\n",
"plt.title('White Wine Quality Predictions (Trainig Data)')\n",
"plt.bar(labels, counts, align='center')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Moving Targets on Example"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mt_cfg = parse_term('''(\n",
" n:3 ;; Number of iterations\n",
" alpha:1 ;; Parameter alpha\n",
" beta:1 ;; Parameter beta\n",
" problem-type:classification ;; classification/regression?\n",
" constraint-solver:cplex ;; Select constraint solver (cplex/pysmt)\n",
" learner:mt.learner ;; URI of learner (registered above)\n",
")''')\n",
"\n",
"mt_data = parse_term('''{\n",
" loss-function:HammingDistance ;; Select loss function\n",
" constraints:{\n",
" (balance \"quality\" 0.01)\n",
" ;;(didi-bin \"quality\" [\"alcohol\"] 0.01)\n",
" }\n",
"}''')\n",
"\n",
"\n",
"if mt_cfg.get(Symbolic(\"constraint-solver\")) == Symbolic(\"cplex\"):\n",
" if mt_cfg.get(Symbolic(\"problem-type\")) == Symbolic(\"classification\"):\n",
" f_MT = MovingTargetClsCplex(mt_cfg, F, test_data=x_test)\n",
" else:\n",
" f_MT = MovingTargetRegCplex(mt_cfg, F, test_data=x_test)\n",
"\n",
"mt_data = mt_data.put_all(train_data)\n",
"\n",
"y_k = f_MT.apply(mt_data)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"i = 0\n",
"for y_k in f_MT.y_k_history:\n",
" plt.figure()\n",
" labels, counts = np.unique(y_k, return_counts=True)\n",
" plt.title('White Wine Quality Predictions (iteration %d)' % i)\n",
" plt.bar(labels, counts, align='center')\n",
" i += 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"i = 0\n",
"for y_k in f_MT.y_k_test_history:\n",
" plt.figure()\n",
" labels, counts = np.unique(y_k, return_counts=True)\n",
" plt.title('White Wine Quality Predictions (iteration %d)' % i)\n",
" plt.bar(labels, counts, align='center')\n",
" i += 1\n",
"\n",
"i = 0\n",
"for y_k in f_MT.y_k_test_history:\n",
" didi_k = didi_c(x_test, y_k, [11])\n",
" print(\"didi_%d = %f\" % (i, didi_k))\n",
" i += 1\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "myenv",
"language": "python",
"name": "myenv"
},
"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.7.0"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": false,
"sideBar": false,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": false,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 4
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -27,6 +27,15 @@ class MovingTargetRegOT(MovingTarget):
supp_variables = set()
constraints = list()
def __init__(self, cfg, freg, test_data=None):
MovingTargetRegOT.x = None
MovingTargetRegOT.y = None
MovingTargetRegOT.n_points = None
MovingTargetRegOT.variables = set()
MovingTargetRegOT.supp_variables = set()
MovingTargetRegOT.constraints = list()
super().__init__(cfg, freg, test_data=test_data)
def add_constraints(self, M: Solver, C, x_s, y_s):
"""
Constraints are expressed with a list/set? of tuples, i.e.:
......@@ -36,7 +45,6 @@ class MovingTargetRegOT(MovingTarget):
]
"""
for c in C:
print(c)
ctype = c[0]
# Translate the constraint to SMT language.
......@@ -69,12 +77,11 @@ class MovingTargetRegOT(MovingTarget):
if v not in self.supp_variables:
M.NumVar(lb=0, ub=M.infinity(), name=v)
self.supp_variables.add(v)
abs_val = [M.LookupVariable("abs_%d" % i) for i in range(len(np.unique(x_s[:, pfeat])))]
# Add fairness constraint.
for ix_feat in pfeat:
vals = np.unique(x_s[:, ix_feat])
vals = np.unique(x_s[:, ix_feat])
for i, v in enumerate(vals):
mask = 1 * (x_s[:, ix_feat] == v).reshape(-1, 1)
yp = mask * self.y
......@@ -83,11 +90,10 @@ class MovingTargetRegOT(MovingTarget):
# print("Np", Np)
# print("yp", yp)
if Np > 0:
tmp = (1.0 / self.n_points) * M.Sum(x) - (1 / Np) * M.Sum([mask[j][0] * x[j]
for j in range(self.n_points)])
tmp = (1.0 / self.n_points) * M.Sum(x) - (1 / Np) * M.Sum([mask[j][0] * x[j] for j in range(self.n_points)])
# Linearization of the absolute value.
M.Add(abs_val[i] >= tmp)
M.Add(abs_val[i] >= -tmp)
M.Add(abs_val[i] >= tmp)
constraint += M.Sum(abs_val)
M.Add(constraint <= cval)
......@@ -227,6 +233,15 @@ class MovingTargetClsOT(MovingTarget):
supp_variables = set()
constraints = list()
def __init__(self, cfg, freg, test_data=None):
MovingTargetClsOT.x = None
MovingTargetClsOT.y = None
MovingTargetClsOT.n_points = None
MovingTargetClsOT.variables = set()
MovingTargetClsOT.supp_variables = set()
MovingTargetClsOT.constraints = list()
super().__init__(cfg, freg, test_data=test_data)
def add_constraints(self, M: Solver, C, x_s, y_s):
"""
Constraints are expressed with a list/set? of tuples, i.e.:
......@@ -558,7 +573,7 @@ class MovingTargetClsOTCP(MovingTarget):
xpr = LinearExpr.Sum([x[i][c] for i in range(M.n_points)])
M.Add(den * xpr <= num)
elif ctype == 'didi-bin':
elif ctype == 'didi':
cvar = ct[1]
pfeat = ct[2]
cval = ct[3]
......@@ -779,4 +794,4 @@ class MovingTargetClsOTCP(MovingTarget):
f = Fraction(Decimal(x)).limit_denominator(limit_denominator)
num, den = f.numerator, f.denominator
return num, den
\ No newline at end of file
return num, den
import numpy as np
def didi_r(x, y, pfeat):
"""
Compute the disparate impact discrimination index of a given dataset.
......
......@@ -6,4 +6,5 @@ pysmt==0.9.0
jupyter==1.0.0
scikit-learn==0.24.2
ortools==9.0.9048
pebble==4.6.1
\ No newline at end of file
pebble==4.6.1
multiprocess==0.70.12.2
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment