diff --git a/.gitignore b/.gitignore index fc613289..ca16d0a6 100644 --- a/.gitignore +++ b/.gitignore @@ -159,4 +159,5 @@ dmypy.json # Local stuff dummy/ tmp_model/ -plots/ \ No newline at end of file +plots/ +demo/ diff --git a/demo/DemoClassification.ipynb b/demo/DemoClassification.ipynb deleted file mode 100644 index dfb35697..00000000 --- a/demo/DemoClassification.ipynb +++ /dev/null @@ -1,714 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "# PSyKE's demo\n", - "\n", - "Some imports." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "6b710e7c", - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.model_selection import train_test_split\n", - "from sklearn.datasets import load_iris\n", - "import pandas as pd\n", - "\n", - "from sklearn.neighbors import KNeighborsClassifier\n", - "from sklearn.metrics import accuracy_score, f1_score\n", - "\n", - "from psyke import Extractor, Clustering, EvaluableModel\n", - "from psyke.extraction.hypercubic.strategy import AdaptiveStrategy\n", - "from psyke.extraction.hypercubic import Grid, FeatureRanker\n", - "from psyke.tuning.orchid import OrCHiD\n", - "from psyke.utils.logic import pretty_theory\n", - "from psyke.utils import Target" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "Import iris dataset separating features and class." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "f8e46c49", - "metadata": {}, - "outputs": [], - "source": [ - "x, y = load_iris(return_X_y=True, as_frame=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "Rename of the features." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "38d5afb0", - "metadata": {}, - "outputs": [], - "source": [ - "x.columns = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth']" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "Replace integer indices with the corresponding string class." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "4f807185", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": " target\n0 setosa\n1 setosa\n2 setosa\n3 setosa\n4 setosa\n.. ...\n145 virginica\n146 virginica\n147 virginica\n148 virginica\n149 virginica\n\n[150 rows x 1 columns]", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
target
0setosa
1setosa
2setosa
3setosa
4setosa
......
145virginica
146virginica
147virginica
148virginica
149virginica
\n

150 rows × 1 columns

\n
" - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "y = pd.DataFrame(y).replace({\"target\": {0: 'setosa', 1: 'versicolor', 2: 'virginica'}})\n", - "y" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "The final dataset:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "7ac49b4e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": " SepalLength SepalWidth PetalLength PetalWidth iris\n0 5.1 3.5 1.4 0.2 setosa\n1 4.9 3.0 1.4 0.2 setosa\n2 4.7 3.2 1.3 0.2 setosa\n3 4.6 3.1 1.5 0.2 setosa\n4 5.0 3.6 1.4 0.2 setosa\n.. ... ... ... ... ...\n145 6.7 3.0 5.2 2.3 virginica\n146 6.3 2.5 5.0 1.9 virginica\n147 6.5 3.0 5.2 2.0 virginica\n148 6.2 3.4 5.4 2.3 virginica\n149 5.9 3.0 5.1 1.8 virginica\n\n[150 rows x 5 columns]", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
SepalLengthSepalWidthPetalLengthPetalWidthiris
05.13.51.40.2setosa
14.93.01.40.2setosa
24.73.21.30.2setosa
34.63.11.50.2setosa
45.03.61.40.2setosa
..................
1456.73.05.22.3virginica
1466.32.55.01.9virginica
1476.53.05.22.0virginica
1486.23.45.42.3virginica
1495.93.05.11.8virginica
\n

150 rows × 5 columns

\n
" - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "dataset = x.join(y)\n", - "dataset.columns = [*dataset.columns[:-1], 'iris']\n", - "dataset" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "Split between train and test set in a reproducible way." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "03fc5e2c", - "metadata": {}, - "outputs": [], - "source": [ - "train, test = train_test_split(dataset, test_size=0.25, random_state=1)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "We use as predictor a KNN and we train it." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "aa8a3128", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Accuracy: 1.00\n", - "F1: 1.00\n" - ] - } - ], - "source": [ - "#predictor = MLPClassifier(alpha=1, max_iter=1000)\n", - "predictor = KNeighborsClassifier(n_neighbors=5)\n", - "#predictor = DecisionTreeClassifier()\n", - "predictor.fit(train.iloc[:, :-1], train.iloc[:, -1])\n", - "print(f'Accuracy: {accuracy_score(predictor.predict(test.iloc[:, :-1]), test.iloc[:, -1]):.2f}')\n", - "print(f'F1: {f1_score(predictor.predict(test.iloc[:, :-1]), test.iloc[:, -1], average=\"weighted\"):.2f}')" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "outputs": [], - "source": [ - "def print_scores(scores):\n", - " print(f'Classification accuracy = {scores[EvaluableModel.ClassificationScore.ACCURACY][0]:.2f} (data), '\n", - " f'{scores[EvaluableModel.ClassificationScore.ACCURACY][1]:.2f} (BB)\\n'\n", - " f'F1 = {scores[EvaluableModel.ClassificationScore.F1][0]:.2f} (data), '\n", - " f'{scores[EvaluableModel.ClassificationScore.F1][1]:.2f} (BB)')\n", - "\n", - "def get_scores(extractor, test, predictor):\n", - " return extractor.score(test, predictor, True, True, EvaluableModel.Task.CLASSIFICATION,\n", - " [EvaluableModel.ClassificationScore.ACCURACY, EvaluableModel.ClassificationScore.F1])" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ITER performance (5 rules with 97.37% coverage):\n", - "Classification accuracy = 0.97 (data), 0.97 (BB)\n", - "F1 = 0.97 (data), 0.97 (BB)\n", - "\n", - "ITER extracted rules:\n", - "\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n", - " SepalLength in [4.29, 7.70], SepalWidth in [1.99, 4.40], PetalLength in [0.99, 3.17], PetalWidth in [0.09, 2.10].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " SepalLength in [4.29, 7.70], SepalWidth in [1.99, 4.40], PetalLength in [3.17, 5.82], PetalWidth in [0.09, 1.74].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " SepalLength in [4.29, 7.70], SepalWidth in [1.99, 4.40], PetalLength in [0.99, 4.05], PetalWidth in [2.10, 2.50].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n", - " SepalLength in [4.29, 7.70], SepalWidth in [1.99, 4.40], PetalLength in [5.82, 6.90], PetalWidth in [0.09, 2.50].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n", - " SepalLength in [4.29, 7.70], SepalWidth in [1.99, 4.40], PetalLength in [4.05, 5.82], PetalWidth in [1.74, 2.50].\n" - ] - } - ], - "source": [ - "it = Extractor.iter(predictor, min_update=0.15, min_examples=150, threshold=0.1, max_iterations=600, n_points=1)\n", - "theory_from_iter = it.extract(train)\n", - "scores, completeness = get_scores(it, test, predictor)\n", - "print(f'ITER performance ({it.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nITER extracted rules:\\n\\n' + pretty_theory(theory_from_iter))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "We create a GridEx extractor to extract prolog rules from the same KNN." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "GridEx performance (3 rules with 94.74% coverage):\n", - "Classification accuracy = 0.92 (data), 0.92 (BB)\n", - "F1 = 0.92 (data), 0.92 (BB)\n", - "\n", - "GridEx extracted rules:\n", - "\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n", - " PetalLength in [0.99, 2.47].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " PetalLength in [3.21, 4.68].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n", - " PetalLength in [4.68, 6.90].\n" - ] - } - ], - "source": [ - "ranked = FeatureRanker(x.columns).fit(predictor, x).rankings()\n", - "gridEx = Extractor.gridex(predictor, Grid(1, AdaptiveStrategy(ranked, [(0.85, 8)])), threshold=.1, min_examples=1)\n", - "theory_from_gridEx = gridEx.extract(train)\n", - "scores, completeness = get_scores(gridEx, test, predictor)\n", - "print(f'GridEx performance ({gridEx.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nGridEx extracted rules:\\n\\n' + pretty_theory(theory_from_gridEx))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "We create an extractor that uses the CART algorithm and we extract prolog rules from our trained KNN." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CART performance (3 rules with 100.00% coverage):\n", - "Classification accuracy = 0.97 (data), 0.97 (BB)\n", - "F1 = 0.97 (data), 0.97 (BB)\n", - "\n", - "CART extracted rules:\n", - "\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n", - " PetalLength =< 2.6.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " PetalLength =< 4.75.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica).\n" - ] - } - ], - "source": [ - "cart = Extractor.cart(predictor, simplify=True)\n", - "theory_from_cart = cart.extract(train)\n", - "scores, completeness = get_scores(cart, test, predictor)\n", - "print(f'CART performance ({cart.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nCART extracted rules:\\n\\n' + pretty_theory(theory_from_cart))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "We use the CReEPy clustering-based extractor to perform the extraction." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "outputs": [], - "source": [ - "def print_clustering_scores(scores):\n", - " print(f'ARI = {scores[EvaluableModel.ClusteringScore.ARI][0]:.2f}\\n'\n", - " f'AMI = {scores[EvaluableModel.ClusteringScore.AMI][0]:.2f}\\n'\n", - " f'V-measure = {scores[EvaluableModel.ClusteringScore.V][0]:.2f}\\n'\n", - " f'FMI = {scores[EvaluableModel.ClusteringScore.FMI][0]:.2f}')\n", - "\n", - "def get_clustering_scores(clustering, test):\n", - " return clustering.score(test, None, False, True, EvaluableModel.Task.CLASSIFICATION,\n", - " [EvaluableModel.ClusteringScore.ARI, EvaluableModel.ClusteringScore.AMI,\n", - " EvaluableModel.ClusteringScore.V, EvaluableModel.ClusteringScore.FMI])\n", - "\n", - "def print_scores_short(scores):\n", - " print(f'Classification accuracy = {scores[EvaluableModel.ClassificationScore.ACCURACY][0]:.2f}')\n", - "\n", - "def get_scores_short(extractor, test):\n", - " return extractor.score(test, None, False, True, EvaluableModel.Task.CLASSIFICATION,\n", - " [EvaluableModel.ClassificationScore.ACCURACY, EvaluableModel.ClassificationScore.F1])" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 16, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Algorithm.ExACT. Depth: 1. Threshold = 1.00. Predictive loss = 0.30, 2 rules\n", - "Algorithm.ExACT. Depth: 1. Threshold = 0.02. Predictive loss = 0.30, 2 rules\n", - "Algorithm.ExACT. Depth: 1. Threshold = 0.06. Predictive loss = 0.30, 2 rules\n", - "Algorithm.ExACT. Depth: 1. Threshold = 0.11. Predictive loss = 0.30, 2 rules\n", - "Algorithm.ExACT. Depth: 1. Threshold = 0.15. Predictive loss = 0.30, 2 rules\n", - "Algorithm.ExACT. Depth: 1. Threshold = 0.20. Predictive loss = 0.30, 2 rules\n", - "\n", - "Algorithm.ExACT. Depth: 2. Threshold = 1.00. Predictive loss = 0.30, 2 rules\n", - "Algorithm.ExACT. Depth: 2. Threshold = 0.02. Predictive loss = 0.27, 3 rules\n", - "Algorithm.ExACT. Depth: 2. Threshold = 0.06. Predictive loss = 0.27, 3 rules\n", - "Algorithm.ExACT. Depth: 2. Threshold = 0.11. Predictive loss = 0.27, 3 rules\n", - "Algorithm.ExACT. Depth: 2. Threshold = 0.15. Predictive loss = 0.27, 3 rules\n", - "Algorithm.ExACT. Depth: 2. Threshold = 0.20. Predictive loss = 0.27, 3 rules\n", - "\n", - "****************************************\n", - "* Best Algorithm.ExACT\n", - "****************************************\n", - "* Predictive loss = 0.27, 3 rules\n", - "* Threshold = 0.02\n", - "* Depth = 2\n", - "****************************************\n", - "\n", - "****************************************\n", - "* Best Predictive loss\n", - "****************************************\n", - "* Predictive loss = 0.27, 3 rules\n", - "* Threshold = 0.02\n", - "* Depth = 2\n", - "****************************************\n", - "\n", - "****************************************\n", - "* Best N rules\n", - "****************************************\n", - "* Predictive loss = 0.30, 2 rules\n", - "* Threshold = 1.00\n", - "* Depth = 2\n", - "****************************************\n", - "\n" - ] - } - ], - "source": [ - "orchid = OrCHiD(dataframe=train, algorithm=OrCHiD.Algorithm.ExACT, output=Target.CLASSIFICATION,\n", - " max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1, patience=5, max_depth=3)\n", - "orchid.search()\n", - "(_, _, depth, threshold) = orchid.get_best()[0]" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ExACT performance (3 clusters with 97.37% coverage):\n", - "ARI = 0.53\n", - "AMI = 0.62\n", - "V-measure = 0.64\n", - "FMI = 0.69\n", - "Classification accuracy = 0.78\n", - "\n", - "Output is virginica if:\n", - " SepalLength is in [4.90, 7.70]\n", - " SepalWidth is in [2.20, 3.80]\n", - " PetalLength is in [4.50, 6.90]\n", - " PetalWidth is in [1.40, 2.50]\n", - "Output is versicolor if:\n", - " SepalLength is in [4.90, 7.70]\n", - " SepalWidth is in [2.00, 3.80]\n", - " PetalLength is in [3.30, 6.90]\n", - " PetalWidth is in [1.00, 2.50]\n", - "Output is setosa if:\n", - " SepalLength is in [4.30, 7.70]\n", - " SepalWidth is in [2.00, 4.40]\n", - " PetalLength is in [1.00, 6.90]\n", - " PetalWidth is in [0.10, 2.50]\n" - ] - } - ], - "source": [ - "exact = Clustering.exact(depth=depth, error_threshold=threshold, output=Target.CLASSIFICATION)\n", - "exact.fit(train)\n", - "scores, completeness = get_clustering_scores(exact, test)\n", - "print(f'ExACT performance ({exact.n_rules} clusters with {completeness * 100:.2f}% coverage):')\n", - "print_clustering_scores(scores)\n", - "scores, _ = get_scores_short(exact, test)\n", - "print_scores_short(scores)\n", - "print()\n", - "exact.explain()" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CReEPy performance (3 rules with 100.00% coverage):\n", - "Classification accuracy = 0.95 (data), 0.95 (BB)\n", - "F1 = 0.95 (data), 0.95 (BB)\n", - "\n", - "CReEPy extracted rules:\n", - "\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n", - " PetalLength in [4.79, 6.90].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " PetalLength in [3.29, 6.90].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa).\n" - ] - } - ], - "source": [ - "creepy = Extractor.creepy(predictor, depth=2, error_threshold=0.1, output=Target.CLASSIFICATION,\n", - " ranks=ranked, ignore_threshold=.99, clustering=Clustering.exact)\n", - "theory_from_creepy = creepy.extract(train)\n", - "scores, completeness = get_scores(creepy, test, predictor)\n", - "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nCReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Algorithm.CREAM. Depth: 1. Threshold = 1.00. Predictive loss = 0.30, 2 rules\n", - "Algorithm.CREAM. Depth: 1. Threshold = 0.02. Predictive loss = 0.30, 2 rules\n", - "Algorithm.CREAM. Depth: 1. Threshold = 0.06. Predictive loss = 0.30, 2 rules\n", - "Algorithm.CREAM. Depth: 1. Threshold = 0.11. Predictive loss = 0.30, 2 rules\n", - "Algorithm.CREAM. Depth: 1. Threshold = 0.15. Predictive loss = 0.30, 2 rules\n", - "Algorithm.CREAM. Depth: 1. Threshold = 0.20. Predictive loss = 0.30, 2 rules\n", - "\n", - "Algorithm.CREAM. Depth: 2. Threshold = 1.00. Predictive loss = 0.30, 2 rules\n", - "Algorithm.CREAM. Depth: 2. Threshold = 0.02. Predictive loss = 0.07, 3 rules\n", - "Algorithm.CREAM. Depth: 2. Threshold = 0.06. Predictive loss = 0.07, 3 rules\n", - "Algorithm.CREAM. Depth: 2. Threshold = 0.11. Predictive loss = 0.07, 3 rules\n", - "Algorithm.CREAM. Depth: 2. Threshold = 0.15. Predictive loss = 0.07, 3 rules\n", - "Algorithm.CREAM. Depth: 2. Threshold = 0.20. Predictive loss = 0.07, 3 rules\n", - "\n", - "****************************************\n", - "* Best Algorithm.CREAM\n", - "****************************************\n", - "* Predictive loss = 0.07, 3 rules\n", - "* Threshold = 0.02\n", - "* Depth = 2\n", - "****************************************\n", - "\n", - "****************************************\n", - "* Best Predictive loss\n", - "****************************************\n", - "* Predictive loss = 0.07, 3 rules\n", - "* Threshold = 0.02\n", - "* Depth = 2\n", - "****************************************\n", - "\n", - "****************************************\n", - "* Best N rules\n", - "****************************************\n", - "* Predictive loss = 0.30, 2 rules\n", - "* Threshold = 1.00\n", - "* Depth = 2\n", - "****************************************\n", - "\n" - ] - } - ], - "source": [ - "orchid = OrCHiD(dataframe=train, algorithm=OrCHiD.Algorithm.CREAM, output=Target.CLASSIFICATION,\n", - " max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1, patience=5, max_depth=3)\n", - "orchid.search()\n", - "(_, _, depth, threshold) = orchid.get_best()[0]" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CREAM performance (3 clusters with 97.37% coverage):\n", - "ARI = 0.85\n", - "AMI = 0.82\n", - "V-measure = 0.83\n", - "FMI = 0.90\n", - "Classification accuracy = 0.95\n", - "\n", - "Output is setosa if:\n", - " SepalLength is in [4.30, 5.70]\n", - " SepalWidth is in [2.30, 4.40]\n", - " PetalLength is in [1.00, 1.90]\n", - " PetalWidth is in [0.10, 0.60]\n", - "Output is versicolor if:\n", - " SepalLength is in [4.90, 7.00]\n", - " SepalWidth is in [2.00, 3.40]\n", - " PetalLength is in [3.30, 5.10]\n", - " PetalWidth is in [1.00, 1.80]\n", - "Output is virginica if:\n", - " SepalLength is in [4.30, 7.70]\n", - " SepalWidth is in [2.00, 4.40]\n", - " PetalLength is in [1.00, 6.90]\n", - " PetalWidth is in [0.10, 2.50]\n" - ] - } - ], - "source": [ - "cream = Clustering.cream(depth=depth, error_threshold=threshold, output=Target.CLASSIFICATION)\n", - "cream.fit(train)\n", - "scores, completeness = get_clustering_scores(cream, test)\n", - "print(f'CREAM performance ({cream.n_rules} clusters with {completeness * 100:.2f}% coverage):')\n", - "print_clustering_scores(scores)\n", - "scores, _ = get_scores_short(cream, test)\n", - "print_scores_short(scores)\n", - "print()\n", - "cream.explain()" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CReEPy performance (3 rules with 100.00% coverage):\n", - "Classification accuracy = 0.95 (data), 0.95 (BB)\n", - "F1 = 0.95 (data), 0.95 (BB)\n", - "\n", - "CReEPy extracted rules:\n", - "\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n", - " PetalLength in [0.99, 1.90].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " PetalLength in [3.29, 5.00].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica).\n" - ] - } - ], - "source": [ - "creepy = Extractor.creepy(predictor, depth=2, error_threshold=0.1, output=Target.CLASSIFICATION,\n", - " ranks=ranked, ignore_threshold=.99, clustering=Clustering.cream)\n", - "theory_from_creepy = creepy.extract(train)\n", - "scores, completeness = get_scores(creepy, test, predictor)\n", - "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nCReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/demo/DemoClassificationDisc.ipynb b/demo/DemoClassificationDisc.ipynb deleted file mode 100644 index c240351b..00000000 --- a/demo/DemoClassificationDisc.ipynb +++ /dev/null @@ -1,452 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "source": [ - "# PSyKE's demo\n", - "\n", - "Some imports." - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "6b710e7c", - "metadata": {}, - "outputs": [], - "source": [ - "from psyke.utils.dataframe import get_discrete_features_supervised, get_discrete_dataset\n", - "from sklearn.model_selection import train_test_split\n", - "from sklearn.datasets import load_iris\n", - "import pandas as pd\n", - "\n", - "from sklearn.neighbors import KNeighborsClassifier\n", - "from sklearn.tree import DecisionTreeClassifier\n", - "from psyke.extraction.cart.predictor import CartPredictor\n", - "\n", - "from psyke import Extractor, EvaluableModel\n", - "from psyke.utils.logic import pretty_theory" - ] - }, - { - "cell_type": "markdown", - "source": [ - "Import iris dataset separating features and class." - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "f8e46c49", - "metadata": {}, - "outputs": [], - "source": [ - "x, y = load_iris(return_X_y=True, as_frame=True)" - ] - }, - { - "cell_type": "markdown", - "source": [ - "Rename of the features." - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "38d5afb0", - "metadata": {}, - "outputs": [], - "source": [ - "x.columns = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth']" - ] - }, - { - "cell_type": "markdown", - "source": [ - "The original features' dataset is discretized using the equal frequency method. Each feature is mapped in a 3 (can be an arbitrary integer) new one-hot encoded sub-features representing 3 real intervals. So from the original 4 features we have a new 12 features dataset. S, M and L stand for small, medium and large." - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "423ff1b4", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "SepalLength = {'SepalLength_0' if SepalLength ∈ ]-∞, 5.39], 'SepalLength_1' if SepalLength ∈ [5.39, 6.26[, 'SepalLength_2' if SepalLength ∈ ]6.26, ∞[}\n", - "\n", - "SepalWidth = {'SepalWidth_0' if SepalWidth ∈ ]-∞, 2.87], 'SepalWidth_1' if SepalWidth ∈ [2.87, 3.20[, 'SepalWidth_2' if SepalWidth ∈ ]3.20, ∞[}\n", - "\n", - "PetalLength = {'PetalLength_0' if PetalLength ∈ ]-∞, 2.27], 'PetalLength_1' if PetalLength ∈ [2.27, 4.87[, 'PetalLength_2' if PetalLength ∈ ]4.87, ∞[}\n", - "\n", - "PetalWidth = {'PetalWidth_0' if PetalWidth ∈ ]-∞, 0.65], 'PetalWidth_1' if PetalWidth ∈ [0.65, 1.64[, 'PetalWidth_2' if PetalWidth ∈ ]1.64, ∞[}\n", - "\n" - ] - } - ], - "source": [ - "iris_features = get_discrete_features_supervised(x.join(y))\n", - "\n", - "for descrete_feature in iris_features:\n", - " print(str(descrete_feature), end='\\n\\n')" - ] - }, - { - "cell_type": "markdown", - "source": [ - "Reassign features' data to the discretized one." - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "ffc1852e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": " PetalLength_0 PetalLength_1 PetalLength_2 PetalWidth_0 PetalWidth_1 \\\n0 1 0 0 1 0 \n1 1 0 0 1 0 \n2 1 0 0 1 0 \n3 1 0 0 1 0 \n4 1 0 0 1 0 \n.. ... ... ... ... ... \n145 0 0 1 0 0 \n146 0 0 1 0 0 \n147 0 0 1 0 0 \n148 0 0 1 0 0 \n149 0 0 1 0 0 \n\n PetalWidth_2 SepalLength_0 SepalLength_1 SepalLength_2 SepalWidth_0 \\\n0 0 1 0 0 0 \n1 0 1 0 0 0 \n2 0 1 0 0 0 \n3 0 1 0 0 0 \n4 0 1 0 0 0 \n.. ... ... ... ... ... \n145 1 0 0 1 0 \n146 1 0 0 1 1 \n147 1 0 0 1 0 \n148 1 0 1 0 0 \n149 1 0 1 0 0 \n\n SepalWidth_1 SepalWidth_2 \n0 0 1 \n1 1 0 \n2 1 0 \n3 1 0 \n4 0 1 \n.. ... ... \n145 1 0 \n146 0 0 \n147 1 0 \n148 0 1 \n149 1 0 \n\n[150 rows x 12 columns]", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
PetalLength_0PetalLength_1PetalLength_2PetalWidth_0PetalWidth_1PetalWidth_2SepalLength_0SepalLength_1SepalLength_2SepalWidth_0SepalWidth_1SepalWidth_2
0100100100001
1100100100010
2100100100010
3100100100010
4100100100001
.......................................
145001001001010
146001001001100
147001001001010
148001001010001
149001001010010
\n

150 rows × 12 columns

\n
" - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "x = get_discrete_dataset(x, iris_features)\n", - "x" - ] - }, - { - "cell_type": "markdown", - "source": [ - "Replace integer indices with the corresponding string class." - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "4f807185", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": " target\n0 setosa\n1 setosa\n2 setosa\n3 setosa\n4 setosa\n.. ...\n145 virginica\n146 virginica\n147 virginica\n148 virginica\n149 virginica\n\n[150 rows x 1 columns]", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
target
0setosa
1setosa
2setosa
3setosa
4setosa
......
145virginica
146virginica
147virginica
148virginica
149virginica
\n

150 rows × 1 columns

\n
" - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "y = pd.DataFrame(y).replace({\"target\": {0: 'setosa', 1: 'versicolor', 2: 'virginica'}})\n", - "y" - ] - }, - { - "cell_type": "markdown", - "source": [ - "The final dataset:" - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "7ac49b4e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": " PetalLength_0 PetalLength_1 PetalLength_2 PetalWidth_0 PetalWidth_1 \\\n0 1 0 0 1 0 \n1 1 0 0 1 0 \n2 1 0 0 1 0 \n3 1 0 0 1 0 \n4 1 0 0 1 0 \n.. ... ... ... ... ... \n145 0 0 1 0 0 \n146 0 0 1 0 0 \n147 0 0 1 0 0 \n148 0 0 1 0 0 \n149 0 0 1 0 0 \n\n PetalWidth_2 SepalLength_0 SepalLength_1 SepalLength_2 SepalWidth_0 \\\n0 0 1 0 0 0 \n1 0 1 0 0 0 \n2 0 1 0 0 0 \n3 0 1 0 0 0 \n4 0 1 0 0 0 \n.. ... ... ... ... ... \n145 1 0 0 1 0 \n146 1 0 0 1 1 \n147 1 0 0 1 0 \n148 1 0 1 0 0 \n149 1 0 1 0 0 \n\n SepalWidth_1 SepalWidth_2 iris \n0 0 1 setosa \n1 1 0 setosa \n2 1 0 setosa \n3 1 0 setosa \n4 0 1 setosa \n.. ... ... ... \n145 1 0 virginica \n146 0 0 virginica \n147 1 0 virginica \n148 0 1 virginica \n149 1 0 virginica \n\n[150 rows x 13 columns]", - "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
PetalLength_0PetalLength_1PetalLength_2PetalWidth_0PetalWidth_1PetalWidth_2SepalLength_0SepalLength_1SepalLength_2SepalWidth_0SepalWidth_1SepalWidth_2iris
0100100100001setosa
1100100100010setosa
2100100100010setosa
3100100100010setosa
4100100100001setosa
..........................................
145001001001010virginica
146001001001100virginica
147001001001010virginica
148001001010001virginica
149001001010010virginica
\n

150 rows × 13 columns

\n
" - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "dataset = x.join(y)\n", - "dataset.columns = [*dataset.columns[:-1], 'iris']\n", - "dataset" - ] - }, - { - "cell_type": "markdown", - "source": [ - "Split between train and test set in a reproducible way." - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "03fc5e2c", - "metadata": {}, - "outputs": [], - "source": [ - "train, test = train_test_split(dataset, test_size=0.5, random_state=0)" - ] - }, - { - "cell_type": "markdown", - "source": [ - "We use as predictor a KNN with K = 4 and we train it." - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "aa8a3128", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": "0.9333333333333333" - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "predictor = KNeighborsClassifier(n_neighbors=4)\n", - "predictor.fit(train.iloc[:, :-1], train.iloc[:, -1])\n", - "predictor.score(test.iloc[:, :-1], test.iloc[:, -1])" - ] - }, - { - "cell_type": "markdown", - "source": [ - "We create an extractor that uses the REAL algorithm and we extract prolog rules from our trained KNN." - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 19, - "outputs": [], - "source": [ - "def print_scores(scores):\n", - " print(f'Classification accuracy = {scores[EvaluableModel.ClassificationScore.ACCURACY][0]:.2f} (data), '\n", - " f'{scores[EvaluableModel.ClassificationScore.ACCURACY][1]:.2f} (BB)\\n'\n", - " f'F1 = {scores[EvaluableModel.ClassificationScore.F1][0]:.2f} (data), '\n", - " f'{scores[EvaluableModel.ClassificationScore.F1][1]:.2f} (BB)')\n", - "\n", - "def get_scores(extractor, test, predictor):\n", - " return extractor.score(test, predictor, True, True, EvaluableModel.Task.CLASSIFICATION,\n", - " [EvaluableModel.ClassificationScore.ACCURACY, EvaluableModel.ClassificationScore.F1])" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "5e97565d", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "REAL performance (8 rules with 94.67% coverage):\n", - "Classification accuracy = 0.96 (data), 1.00 (BB)\n", - "F1 = 0.96 (data), 1.00 (BB)\n", - "REAL extracted rules:\n", - "\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n", - " PetalWidth =< 0.64, SepalLength =< 5.38.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n", - " PetalWidth =< 0.64, SepalWidth > 3.20, SepalLength =< 6.26.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " PetalWidth in [0.64, 1.63], SepalWidth =< 2.87, PetalLength > 2.26, SepalLength =< 6.26.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " PetalWidth in [0.64, 1.63], SepalLength in [5.38, 6.26], SepalWidth =< 3.20.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " PetalWidth in [0.64, 1.63], PetalLength =< 4.86, SepalLength > 5.38, SepalWidth =< 3.20.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " SepalLength in [5.38, 6.26], SepalWidth in [2.87, 3.20], PetalLength =< 4.86, PetalWidth > 0.64.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n", - " PetalLength > 4.86, SepalLength > 6.26.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n", - " PetalLength > 4.86, PetalWidth > 1.63.\n" - ] - } - ], - "source": [ - "real = Extractor.real(predictor, iris_features)\n", - "theory_from_real = real.extract(train)\n", - "scores, completeness = get_scores(real, test, predictor)\n", - "print(f'REAL performance ({real.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('REAL extracted rules:\\n\\n' + pretty_theory(theory_from_real))" - ] - }, - { - "cell_type": "markdown", - "source": [ - "We create a different extractor that use Trepan algorithm and we extract prolog rules from the same KNN." - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "dc20410e", - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "TREPAN performance (3 rules with 100.00% coverage):\n", - "Classification accuracy = 0.95 (data), 0.96 (BB)\n", - "F1 = 0.95 (data), 0.96 (BB)\n", - "\n", - "Trepan extracted rules:\n", - "\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n", - " PetalLength > 2.26, PetalLength in [2.26, 4.86].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n", - " PetalLength > 2.26.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa).\n" - ] - } - ], - "source": [ - "trepan = Extractor.trepan(predictor, iris_features)\n", - "theory_from_trepan = trepan.extract(train)\n", - "scores, completeness = get_scores(trepan, test, predictor)\n", - "print(f'TREPAN performance ({trepan.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nTrepan extracted rules:\\n\\n' + pretty_theory(theory_from_trepan))" - ] - }, - { - "cell_type": "markdown", - "source": [ - "We create another different extractor that use CART algorithm." - ], - "metadata": { - "collapsed": false - } - }, - { - "cell_type": "code", - "execution_count": 22, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CART performance (3 rules with 100.00% coverage):\n", - "Classification accuracy = 0.95 (data), 0.96 (BB)\n", - "F1 = 0.95 (data), 0.96 (BB)\n", - "\n", - "CART extracted rules:\n", - "\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n", - " PetalWidth =< 0.64.\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n", - " PetalLength not_in [2.26, 4.86].\n", - "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor).\n" - ] - } - ], - "source": [ - "cart = Extractor.cart(predictor, discretization=iris_features, simplify=True)\n", - "theory_from_cart = cart.extract(train)\n", - "scores, completeness = get_scores(cart, test, predictor)\n", - "print(f'CART performance ({cart.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nCART extracted rules:\\n\\n' + pretty_theory(theory_from_cart))" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "code", - "execution_count": null, - "outputs": [], - "source": [], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/demo/DemoRegression.ipynb b/demo/DemoRegression.ipynb deleted file mode 100644 index 68f73ceb..00000000 --- a/demo/DemoRegression.ipynb +++ /dev/null @@ -1,1835 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "f52126f3", - "metadata": {}, - "source": [ - "# PSyKE's demo for regression tasks\n", - "\n", - "Some imports." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "6b710e7c", - "metadata": {}, - "outputs": [], - "source": [ - "from psyke import Extractor, Clustering, EvaluableModel\n", - "from psyke.tuning.pedro import PEDRO\n", - "from psyke.tuning import Objective\n", - "from psyke.tuning.crash import CRASH\n", - "from sklearn.tree import DecisionTreeRegressor\n", - "from psyke.utils.logic import pretty_theory\n", - "from psyke.utils.metrics import mae, mse, r2\n", - "from sklearn.model_selection import train_test_split\n", - "from psyke.utils import Target\n", - "import pandas as pd" - ] - }, - { - "cell_type": "markdown", - "id": "d7c90ed2", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "Import a dataset." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "f8e46c49", - "metadata": {}, - "outputs": [], - "source": [ - "dataset = pd.read_csv(\"../test/resources/datasets/df.csv\")\n", - "dataset = dataset[[\"X\", \"Y\", \"Z4\"]].dropna()\n", - "#dataset = pd.read_csv(\"../test/resources/datasets/CCPP.csv\", sep=\";\", decimal=\",\")\n", - "#dataset" - ] - }, - { - "cell_type": "markdown", - "id": "d673b766", - "metadata": {}, - "source": [ - "Split between train and test set in a reproducible way." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "03fc5e2c", - "metadata": {}, - "outputs": [], - "source": [ - "train, test = train_test_split(dataset, test_size=0.5, random_state=10)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "outputs": [], - "source": [ - "#from psyke.tuning.orchid import OrCHiD\n", - "\n", - "#orchid = OrCHiD(dataframe=train, algorithm=OrCHiD.Algorithm.CREAM, output=Target.REGRESSION,\n", - "# max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1, patience=5, max_depth=3)\n", - "#orchid.search()\n", - "#(_, _, depth, threshold) = orchid.get_best()[0]" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "markdown", - "id": "fa6754a0", - "metadata": {}, - "source": [ - "We use as predictor a KNN and we train it." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "bed764ca", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "MAE = 0.08\n", - "MSE = 0.03\n", - "R2 = 1.00\n" - ] - } - ], - "source": [ - "#predictor = KNeighborsRegressor(n_neighbors=3).fit(train.iloc[:, :-1], train.iloc[:, -1])\n", - "predictor = DecisionTreeRegressor().fit(train.iloc[:, :-1], train.iloc[:, -1])\n", - "#predictor = LinearRegression().fit(train.iloc[:, :-1], train.iloc[:, -1])\n", - "\n", - "predicted = predictor.predict(test.iloc[:, :-1]).flatten()\n", - "true = test.iloc[:, -1]\n", - "\n", - "print(f'MAE = {mae(true, predicted):.2f}')\n", - "print(f'MSE = {mse(true, predicted):.2f}')\n", - "print(f'R2 = {r2(true, predicted):.2f}')" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "We define a function to print the extractors' evaluation" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "def print_scores(scores):\n", - " print(f'MAE = {scores[EvaluableModel.RegressionScore.MAE][0]:.2f} (data), '\n", - " f'{scores[EvaluableModel.RegressionScore.MAE][1]:.2f} (BB)\\n'\n", - " f'MSE = {scores[EvaluableModel.RegressionScore.MSE][0]:.2f} (data), '\n", - " f'{scores[EvaluableModel.RegressionScore.MSE][1]:.2f} (BB)\\n'\n", - " f'R2 = {scores[EvaluableModel.RegressionScore.R2][0]:.2f} (data), '\n", - " f'{scores[EvaluableModel.RegressionScore.R2][1]:.2f} (BB)')\n", - "\n", - "def get_scores(extractor, test, predictor):\n", - " return extractor.score(test, predictor, True, True, EvaluableModel.Task.REGRESSION,\n", - " [EvaluableModel.RegressionScore.MAE, EvaluableModel.RegressionScore.MSE,\n", - " EvaluableModel.RegressionScore.R2])" - ] - }, - { - "cell_type": "markdown", - "id": "96835867", - "metadata": {}, - "source": [ - "We create several extractors that use ITER, GridEx and GridREx algorithms to extract prolog rules from the predictor." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ORBIt performance (2 rules with 100.00% coverage):\n", - "MAE = 4.15 (data), 4.15 (BB)\n", - "MSE = 28.12 (data), 28.10 (BB)\n", - "R2 = -0.13 (data), -0.13 (BB)\n", - "\n", - "ORBIt extracted rules:\n", - "\n", - "'Z4'(X, Y, 15.42) :-\n", - " 0.02 * X - 0.03 * Y =< -0.01, -0.02 * X + 0.03 * Y =< 0.01, 1.0 * X + 0.0 * Y =< 0.46, -1.0 * X + 0.0 * Y =< -0.16.\n", - "'Z4'(X, Y, 5.053691).\n" - ] - } - ], - "source": [ - "orbit = Extractor.orbit(predictor, depth=3, error_threshold=1.0, gauss_components=2, output=Target.REGRESSION)\n", - "theory_from_orbit = orbit.extract(train)\n", - "scores, completeness = get_scores(orbit, test, predictor)\n", - "print(f'ORBIt performance ({orbit.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nORBIt extracted rules:\\n\\n' + pretty_theory(theory_from_orbit))" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 14, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CReEPy performance (3 rules with 100.00% coverage):\n", - "MAE = 0.68 (data), 0.71 (BB)\n", - "MSE = 2.05 (data), 2.06 (BB)\n", - "R2 = 0.92 (data), 0.92 (BB)\n", - "\n", - "CReEPy extracted rules (ExACT):\n", - "\n", - "'Z4'(X, Y, Z4) :-\n", - " X in [0.15, 0.84], Y in [-0.00, 0.59], Z4 is 7.49 - 7.63 * X + 12.05 * Y.\n", - "'Z4'(X, Y, Z4) :-\n", - " X in [0.15, 0.84], Y in [-0.00, 0.84], Z4 is 9.0 - 12.0 * X + 15.0 * Y.\n", - "'Z4'(X, Y, Z4) :-\n", - " Y in [-0.00, 1.00], Z4 is 2.0 + 4.0 * X - 3.0 * Y.\n" - ] - } - ], - "source": [ - "creepy = Extractor.creepy(predictor, depth=3, error_threshold=0.02, output=Target.REGRESSION,\n", - " clustering=Clustering.exact)\n", - "theory_from_creepy = creepy.extract(train)\n", - "scores, completeness = get_scores(creepy, test, predictor)\n", - "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nCReEPy extracted rules (ExACT):\\n\\n' + pretty_theory(theory_from_creepy))" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CReEPy performance (4 rules with 100.00% coverage):\n", - "MAE = 3.37 (data), 3.47 (BB)\n", - "MSE = 18.62 (data), 19.19 (BB)\n", - "R2 = 0.94 (data), 0.93 (BB)\n", - "\n", - "CReEPy extracted rules (CREAM):\n", - "\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [6.21, 32.45], V in [34.02, 50.16], AP in [997.90, 1026.41], RH in [35.63, 100.10], PE is 502.53 - 2.16 * AP - 0.26 * AT + 0.01 * RH - 0.11 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [6.21, 35.77], V in [25.35, 81.56], AP in [997.84, 1026.45], RH in [25.55, 100.12], PE is 234.73 - 1.42 * AP - 0.29 * AT + 0.26 * RH - 0.12 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [3.30, 14.60], V in [34.68, 44.47], AP in [1011.31, 1033.25], RH in [58.98, 98.68], PE is 720.26 - 2.20 * AP - 0.47 * AT - 0.18 * RH - 0.22 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15], PE is 579.01 - 2.05 * AP - 0.60 * AT - 0.05 * RH + 0.00 * V.\n" - ] - } - ], - "source": [ - "creepy = Extractor.creepy(predictor, depth=2, error_threshold=0.02, output=Target.REGRESSION,\n", - " clustering=Clustering.cream)\n", - "theory_from_creepy = creepy.extract(train)\n", - "scores, completeness = get_scores(creepy, test, predictor)\n", - "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nCReEPy extracted rules (CREAM):\\n\\n' + pretty_theory(theory_from_creepy))" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Algorithm.ExACT. Depth: 1. Threshold = 0.00. MAE = 3.52, 2 rules\n", - "Algorithm.ExACT. Depth: 1. Threshold = 0.00. MAE = 3.54, 2 rules\n", - "\n", - "Algorithm.ExACT. Depth: 2. Threshold = 0.00. MAE = 3.52, 3 rules\n", - "Algorithm.ExACT. Depth: 2. Threshold = 0.00. MAE = 3.48, 3 rules\n", - "Algorithm.ExACT. Depth: 2. Threshold = 0.00. MAE = 3.50, 3 rules\n", - "\n", - "Algorithm.ExACT. Depth: 3. Threshold = 0.00. MAE = 3.44, 4 rules\n", - "Algorithm.ExACT. Depth: 3. Threshold = 0.00. MAE = 3.41, 4 rules\n", - "Algorithm.ExACT. Depth: 3. Threshold = 0.00. MAE = 3.52, 4 rules\n", - "\n", - "**********************\n", - "Best Algorithm.ExACT\n", - "**********************\n", - "MAE = 3.41, 4 rules\n", - "Threshold = 0.00\n", - "Depth = 3\n", - "\n", - "**********************\n", - "Best MAE \n", - "**********************\n", - "MAE = 3.41, 4 rules\n", - "Threshold = 0.00\n", - "Depth = 3\n", - "\n", - "**********************\n", - "Best N rules\n", - "**********************\n", - "MAE = 3.54, 2 rules\n", - "Threshold = 0.00\n", - "Depth = 1\n", - "\n", - "CReEPy performance (4 rules with 100.00% coverage):\n", - "MAE = 3.37 (data), 3.46 (BB)\n", - "MSE = 18.48 (data), 19.00 (BB)\n", - "R2 = 0.94 (data), 0.94 (BB)\n", - "\n", - "CReEPy extracted rules:\n", - "\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [6.21, 32.45], V in [35.39, 50.16], AP in [998.07, 1026.40], RH in [35.63, 100.10], PE is 499.89 - 2.16 * AP - 0.27 * AT + 0.01 * RH - 0.11 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [6.21, 32.45], V in [34.02, 50.16], AP in [997.90, 1026.41], RH in [35.63, 100.10], PE is 697.90 - 1.74 * AP - 2.04 * AT - 0.17 * RH + 0.61 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [6.21, 35.77], V in [25.35, 81.56], AP in [997.84, 1026.45], RH in [25.55, 100.12], PE is 234.73 - 1.42 * AP - 0.29 * AT + 0.26 * RH - 0.12 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15], PE is 628.20 - 2.19 * AP - 0.50 * AT - 0.09 * RH - 0.17 * V.\n" - ] - } - ], - "source": [ - "crash = CRASH(predictor, train, max_depth=3, patience=1, readability_tradeoff=.5,\n", - " algorithm=CRASH.Algorithm.ExACT, output=Target.REGRESSION)\n", - "crash.search()\n", - "(_, _, depth, threshold) = crash.get_best()[0]\n", - "\n", - "creepy = Extractor.creepy(predictor, depth=depth, error_threshold=threshold, output=Target.REGRESSION,\n", - " clustering=Clustering.exact)\n", - "theory_from_creepy = creepy.extract(train)\n", - "scores, completeness = get_scores(creepy, test, predictor)\n", - "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nCReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Algorithm.CREAM. Depth: 1. Threshold = 0.00. MAE = 10.29, 2 rules\n", - "Algorithm.CREAM. Depth: 1. Threshold = 0.00. MAE = 8.46, 2 rules\n", - "Algorithm.CREAM. Depth: 1. Threshold = 0.00. MAE = 10.29, 2 rules\n", - "\n", - "Algorithm.CREAM. Depth: 2. Threshold = 0.00. MAE = 6.46, 4 rules\n", - "Algorithm.CREAM. Depth: 2. Threshold = 0.00. MAE = 6.10, 4 rules\n", - "Algorithm.CREAM. Depth: 2. Threshold = 0.00. MAE = 7.75, 4 rules\n", - "\n", - "Algorithm.CREAM. Depth: 3. Threshold = 0.00. " - ] - }, - { - "ename": "KeyboardInterrupt", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m", - "\u001B[1;31mKeyboardInterrupt\u001B[0m Traceback (most recent call last)", - "\u001B[1;32m~\\AppData\\Local\\Temp/ipykernel_14404/1950581394.py\u001B[0m in \u001B[0;36m\u001B[1;34m\u001B[0m\n\u001B[0;32m 1\u001B[0m \u001B[0mcrash\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mCRASH\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mpredictor\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mtrain\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mmax_depth\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;36m3\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mpatience\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mreadability_tradeoff\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;36m.75\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0malgorithm\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mCRASH\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mAlgorithm\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mCREAM\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m----> 2\u001B[1;33m \u001B[0mcrash\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0msearch\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 3\u001B[0m \u001B[1;33m(\u001B[0m\u001B[0m_\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0m_\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mdepth\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mthreshold\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mcrash\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mget_best\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m0\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 4\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 5\u001B[0m creepy = Extractor.creepy(predictor, depth=depth, error_threshold=threshold, output=Target.REGRESSION,\n", - "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\tuning\\crash\\__init__.py\u001B[0m in \u001B[0;36msearch\u001B[1;34m(self)\u001B[0m\n\u001B[0;32m 23\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 24\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0msearch\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 25\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mparams\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m__search_depth\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 26\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 27\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0m__search_depth\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\tuning\\crash\\__init__.py\u001B[0m in \u001B[0;36m__search_depth\u001B[1;34m(self)\u001B[0m\n\u001B[0;32m 30\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 31\u001B[0m \u001B[1;32mfor\u001B[0m \u001B[0mdepth\u001B[0m \u001B[1;32min\u001B[0m \u001B[0mrange\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mmax_depth\u001B[0m \u001B[1;33m+\u001B[0m \u001B[1;36m1\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 32\u001B[1;33m \u001B[0mp\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m__search_threshold\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdepth\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 33\u001B[0m \u001B[0mb\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mOptimizer\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_best\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mp\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 34\u001B[0m \u001B[0mprint\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\tuning\\crash\\__init__.py\u001B[0m in \u001B[0;36m__search_threshold\u001B[1;34m(self, depth)\u001B[0m\n\u001B[0;32m 56\u001B[0m \u001B[0mclustering\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mClustering\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcream\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0malgorithm\u001B[0m \u001B[1;33m==\u001B[0m \u001B[0mCRASH\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mAlgorithm\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mCREAM\u001B[0m \u001B[1;32melse\u001B[0m \u001B[0mClustering\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mexact\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 57\u001B[0m )\n\u001B[1;32m---> 58\u001B[1;33m \u001B[0m_\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mextractor\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mextract\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 59\u001B[0m mae, n = (extractor.mae(self.dataframe, self.predictor) if self.objective == Objective.MODEL else\n\u001B[0;32m 60\u001B[0m extractor.mae(self.dataframe)), extractor.n_rules\n", - "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\__init__.py\u001B[0m in \u001B[0;36mextract\u001B[1;34m(self, dataframe, mapping, sort)\u001B[0m\n", - "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\extraction\\hypercubic\\creepy\\__init__.py\u001B[0m in \u001B[0;36m_extract\u001B[1;34m(self, dataframe, mapping, sort)\u001B[0m\n\u001B[0;32m 32\u001B[0m \u001B[1;32mraise\u001B[0m \u001B[0mTypeError\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;34m\"clustering must be a HyperCubeClustering\"\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 33\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 34\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mclustering\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 35\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_hypercubes\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mclustering\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mget_hypercubes\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 36\u001B[0m \u001B[1;32mfor\u001B[0m \u001B[0mcube\u001B[0m \u001B[1;32min\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_hypercubes\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\clustering\\exact\\__init__.py\u001B[0m in \u001B[0;36mfit\u001B[1;34m(self, dataframe)\u001B[0m\n\u001B[0;32m 58\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_predictor\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0miloc\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m:\u001B[0m\u001B[1;33m-\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mdataframe\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0miloc\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m-\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 59\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_hypercubes\u001B[0m \u001B[1;33m=\u001B[0m\u001B[0;31m \u001B[0m\u001B[0;31m\\\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 60\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_iterate\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mNode\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mHyperCube\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcreate_surrounding_cube\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;32mTrue\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_output\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 61\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 62\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0mget_hypercubes\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m->\u001B[0m \u001B[0mIterable\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mHyperCube\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\clustering\\cream\\__init__.py\u001B[0m in \u001B[0;36m_iterate\u001B[1;34m(self, surrounding)\u001B[0m\n\u001B[0;32m 52\u001B[0m \u001B[0mgauss_params\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mselect_gaussian_mixture\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdata\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mgauss_components\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 53\u001B[0m \u001B[0mgauss_pred\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mgauss_params\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m2\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mpredict\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdata\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 54\u001B[1;33m \u001B[0mcubes\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m__eligible_cubes\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mgauss_pred\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mnode\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mgauss_params\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 55\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mcubes\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m<\u001B[0m \u001B[1;36m1\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 56\u001B[0m \u001B[1;32mcontinue\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\clustering\\cream\\__init__.py\u001B[0m in \u001B[0;36m__eligible_cubes\u001B[1;34m(self, gauss_pred, node, clusters)\u001B[0m\n\u001B[0;32m 27\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdf\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m==\u001B[0m \u001B[1;36m0\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 28\u001B[0m \u001B[1;32mcontinue\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 29\u001B[1;33m \u001B[0minner_cube\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_create_cube\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdf\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mclusters\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 30\u001B[0m \u001B[0mindices\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_indices\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0minner_cube\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mnode\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 31\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mindices\u001B[0m \u001B[1;32mis\u001B[0m \u001B[1;32mNone\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\clustering\\exact\\__init__.py\u001B[0m in \u001B[0;36m_create_cube\u001B[1;34m(self, dataframe, clusters)\u001B[0m\n\u001B[0;32m 49\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0m_create_cube\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mdataframe\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mpd\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mDataFrame\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mclusters\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mint\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m->\u001B[0m \u001B[0mClosedCube\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 50\u001B[0m \u001B[0mdata\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mExACT\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_remove_string_label\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 51\u001B[1;33m \u001B[0mdbscan_pred\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mDBSCAN\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0meps\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mselect_dbscan_epsilon\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdata\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mclusters\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit_predict\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdata\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0miloc\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m:\u001B[0m\u001B[1;33m-\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 52\u001B[0m return HyperCube.create_surrounding_cube(\n\u001B[0;32m 53\u001B[0m \u001B[0mdataframe\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0miloc\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mnp\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mwhere\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdbscan_pred\u001B[0m \u001B[1;33m==\u001B[0m \u001B[0mCounter\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdbscan_pred\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mmost_common\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m0\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m0\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\clustering\\utils.py\u001B[0m in \u001B[0;36mselect_dbscan_epsilon\u001B[1;34m(data, clusters)\u001B[0m\n\u001B[0;32m 30\u001B[0m \u001B[0mepsilon\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mmax\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdistances\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m-\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;36m1e-3\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 31\u001B[0m \u001B[0mk\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;36m1.\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 32\u001B[1;33m \u001B[0mdbscan_pred\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mDBSCAN\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0meps\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mepsilon\u001B[0m \u001B[1;33m*\u001B[0m \u001B[0mk\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit_predict\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdata\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0miloc\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m:\u001B[0m\u001B[1;33m-\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 33\u001B[0m \u001B[1;31m# while Counter(dbscan_pred).most_common(1)[0][0] == -1:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 34\u001B[0m \u001B[1;32mfor\u001B[0m \u001B[0mi\u001B[0m \u001B[1;32min\u001B[0m \u001B[0mrange\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m1000\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\sklearn\\cluster\\_dbscan.py\u001B[0m in \u001B[0;36mfit_predict\u001B[1;34m(self, X, y, sample_weight)\u001B[0m\n\u001B[0;32m 456\u001B[0m \u001B[0mCluster\u001B[0m \u001B[0mlabels\u001B[0m\u001B[1;33m.\u001B[0m \u001B[0mNoisy\u001B[0m \u001B[0msamples\u001B[0m \u001B[0mare\u001B[0m \u001B[0mgiven\u001B[0m \u001B[0mthe\u001B[0m \u001B[0mlabel\u001B[0m \u001B[1;33m-\u001B[0m\u001B[1;36m1.\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 457\u001B[0m \"\"\"\n\u001B[1;32m--> 458\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mX\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0msample_weight\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0msample_weight\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 459\u001B[0m \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mlabels_\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 460\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\sklearn\\cluster\\_dbscan.py\u001B[0m in \u001B[0;36mfit\u001B[1;34m(self, X, y, sample_weight)\u001B[0m\n\u001B[0;32m 404\u001B[0m \u001B[0mneighbors_model\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mX\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 405\u001B[0m \u001B[1;31m# This has worst case O(n^2) memory complexity\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 406\u001B[1;33m \u001B[0mneighborhoods\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mneighbors_model\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mradius_neighbors\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mX\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mreturn_distance\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mFalse\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 407\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 408\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0msample_weight\u001B[0m \u001B[1;32mis\u001B[0m \u001B[1;32mNone\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\sklearn\\neighbors\\_base.py\u001B[0m in \u001B[0;36mradius_neighbors\u001B[1;34m(self, X, radius, return_distance, sort_results)\u001B[0m\n\u001B[0;32m 1167\u001B[0m \u001B[0mn_jobs\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0meffective_n_jobs\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mn_jobs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 1168\u001B[0m \u001B[0mdelayed_query\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mdelayed\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0m_tree_query_radius_parallel_helper\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m-> 1169\u001B[1;33m chunked_results = Parallel(n_jobs, prefer=\"threads\")(\n\u001B[0m\u001B[0;32m 1170\u001B[0m delayed_query(\n\u001B[0;32m 1171\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_tree\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mX\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0ms\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mradius\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mreturn_distance\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0msort_results\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0msort_results\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\parallel.py\u001B[0m in \u001B[0;36m__call__\u001B[1;34m(self, iterable)\u001B[0m\n\u001B[0;32m 1041\u001B[0m \u001B[1;31m# remaining jobs.\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 1042\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_iterating\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;32mFalse\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m-> 1043\u001B[1;33m \u001B[1;32mif\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mdispatch_one_batch\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0miterator\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 1044\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_iterating\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_original_iterator\u001B[0m \u001B[1;32mis\u001B[0m \u001B[1;32mnot\u001B[0m \u001B[1;32mNone\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 1045\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\parallel.py\u001B[0m in \u001B[0;36mdispatch_one_batch\u001B[1;34m(self, iterator)\u001B[0m\n\u001B[0;32m 859\u001B[0m \u001B[1;32mreturn\u001B[0m \u001B[1;32mFalse\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 860\u001B[0m \u001B[1;32melse\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 861\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_dispatch\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtasks\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 862\u001B[0m \u001B[1;32mreturn\u001B[0m \u001B[1;32mTrue\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 863\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\parallel.py\u001B[0m in \u001B[0;36m_dispatch\u001B[1;34m(self, batch)\u001B[0m\n\u001B[0;32m 777\u001B[0m \u001B[1;32mwith\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_lock\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 778\u001B[0m \u001B[0mjob_idx\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_jobs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 779\u001B[1;33m \u001B[0mjob\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_backend\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mapply_async\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mbatch\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcallback\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mcb\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 780\u001B[0m \u001B[1;31m# A job can complete so quickly than its callback is\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 781\u001B[0m \u001B[1;31m# called before we get here, causing self._jobs to\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\_parallel_backends.py\u001B[0m in \u001B[0;36mapply_async\u001B[1;34m(self, func, callback)\u001B[0m\n\u001B[0;32m 206\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0mapply_async\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mfunc\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcallback\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mNone\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 207\u001B[0m \u001B[1;34m\"\"\"Schedule a func to be run\"\"\"\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 208\u001B[1;33m \u001B[0mresult\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mImmediateResult\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mfunc\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 209\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mcallback\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 210\u001B[0m \u001B[0mcallback\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mresult\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\_parallel_backends.py\u001B[0m in \u001B[0;36m__init__\u001B[1;34m(self, batch)\u001B[0m\n\u001B[0;32m 570\u001B[0m \u001B[1;31m# Don't delay the application, to avoid keeping the input\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 571\u001B[0m \u001B[1;31m# arguments in memory\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 572\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mresults\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mbatch\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 573\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 574\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0mget\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\parallel.py\u001B[0m in \u001B[0;36m__call__\u001B[1;34m(self)\u001B[0m\n\u001B[0;32m 260\u001B[0m \u001B[1;31m# change the default number of processes to -1\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 261\u001B[0m \u001B[1;32mwith\u001B[0m \u001B[0mparallel_backend\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_backend\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mn_jobs\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_n_jobs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 262\u001B[1;33m return [func(*args, **kwargs)\n\u001B[0m\u001B[0;32m 263\u001B[0m for func, args, kwargs in self.items]\n\u001B[0;32m 264\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\parallel.py\u001B[0m in \u001B[0;36m\u001B[1;34m(.0)\u001B[0m\n\u001B[0;32m 260\u001B[0m \u001B[1;31m# change the default number of processes to -1\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 261\u001B[0m \u001B[1;32mwith\u001B[0m \u001B[0mparallel_backend\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_backend\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mn_jobs\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_n_jobs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 262\u001B[1;33m return [func(*args, **kwargs)\n\u001B[0m\u001B[0;32m 263\u001B[0m for func, args, kwargs in self.items]\n\u001B[0;32m 264\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\sklearn\\utils\\fixes.py\u001B[0m in \u001B[0;36m__call__\u001B[1;34m(self, *args, **kwargs)\u001B[0m\n\u001B[0;32m 115\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0m__call__\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m*\u001B[0m\u001B[0margs\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 116\u001B[0m \u001B[1;32mwith\u001B[0m \u001B[0mconfig_context\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m**\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mconfig\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 117\u001B[1;33m \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfunction\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m*\u001B[0m\u001B[0margs\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 118\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 119\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\sklearn\\neighbors\\_base.py\u001B[0m in \u001B[0;36m_tree_query_radius_parallel_helper\u001B[1;34m(tree, *args, **kwargs)\u001B[0m\n\u001B[0;32m 949\u001B[0m \u001B[0mcloudpickle\u001B[0m \u001B[0munder\u001B[0m \u001B[0mPyPy\u001B[0m\u001B[1;33m.\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 950\u001B[0m \"\"\"\n\u001B[1;32m--> 951\u001B[1;33m \u001B[1;32mreturn\u001B[0m \u001B[0mtree\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mquery_radius\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m*\u001B[0m\u001B[0margs\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 952\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 953\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n", - "\u001B[1;31mKeyboardInterrupt\u001B[0m: " - ] - } - ], - "source": [ - "crash = CRASH(predictor, train, max_depth=3, patience=1, readability_tradeoff=.75, algorithm=CRASH.Algorithm.CREAM)\n", - "crash.search()\n", - "(_, _, depth, threshold) = crash.get_best()[0]\n", - "\n", - "creepy = Extractor.creepy(predictor, depth=depth, error_threshold=threshold, output=Target.REGRESSION,\n", - " clustering=Clustering.cream)\n", - "theory_from_creepy = creepy.extract(train)\n", - "scores, completeness = get_scores(creepy, test, predictor)\n", - "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nCReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "it = Extractor.iter(predictor, min_update=1.0 / 10, n_points=1, max_iterations=600,\n", - " min_examples=100, threshold=5)\n", - "theory_from_iter = it.extract(train)\n", - "scores, completeness = get_scores(it, test, predictor)\n", - "print(f'ITER performance ({it.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nITER extracted rules:\\n\\n' + pretty_theory(theory_from_iter))" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Algorithm.GRIDEX. Grid (1). Fixed (2). Threshold = 0.00. MAE = 6.45, 15 rules\n", - "Algorithm.GRIDEX. Grid (1). Fixed (2). Threshold = 0.00. MAE = 6.45, 30 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Fixed (3). Threshold = 0.00. MAE = 6.45, 86 rules\n", - "Algorithm.GRIDEX. Grid (1). Fixed (3). Threshold = 0.00. MAE = 6.45, 142 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 2)]). Threshold = 0.00. MAE = 6.45, 144 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 2)]). Threshold = 0.00. MAE = 6.45, 146 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 2)]). Threshold = 0.00. MAE = 6.45, 150 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 2)]). Threshold = 0.00. MAE = 6.45, 154 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 3)]). Threshold = 0.00. MAE = 6.45, 157 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 3)]). Threshold = 0.00. MAE = 6.45, 160 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 3)]). Threshold = 0.00. MAE = 6.45, 169 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 3)]). Threshold = 0.00. MAE = 6.45, 178 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 5)]). Threshold = 0.00. MAE = 6.45, 183 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 5)]). Threshold = 0.00. MAE = 6.45, 188 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 5)]). Threshold = 0.00. MAE = 6.45, 209 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 5)]). Threshold = 0.00. MAE = 6.45, 230 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 10)]). Threshold = 0.00. MAE = 6.45, 240 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 10)]). Threshold = 0.00. MAE = 6.45, 250 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.33, 2), (0.67, 3)]). Threshold = 0.00. MAE = 6.45, 256 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.33, 2), (0.67, 3)]). Threshold = 0.00. MAE = 6.45, 262 rules\n", - "\n", - "**********************\n", - "Best Algorithm.GRIDEX\n", - "**********************\n", - "MAE = 6.45, 15 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Fixed (2)\n", - "\n", - "**********************\n", - "Best MAE \n", - "**********************\n", - "MAE = 6.45, 256 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Adaptive ([(0.33, 2), (0.67, 3)])\n", - "\n", - "**********************\n", - "Best N rules\n", - "**********************\n", - "MAE = 6.45, 15 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Fixed (2)\n", - "\n", - "GridEx performance (277 rules with 99.90% coverage):\n", - "MAE = 6.50 (data), 6.49 (BB)\n", - "MSE = 66.41 (data), 65.91 (BB)\n", - "R2 = 0.77 (data), 0.77 (BB)\n", - "\n", - "GridEx extracted rules:\n", - "\n", - "'PE'(AP, AT, RH, V, 473.96) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 468.97) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 471.39) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 472.61) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 468.07) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.26) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 464.10) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 445.50) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.77) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 449.32) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 447.25) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.54) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 438.05) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.71) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.25) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 473.96) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 468.97) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 471.39) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 472.61) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 468.07) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.26) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 464.10) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 445.50) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.77) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 449.32) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 447.25) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.54) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 438.05) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.71) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.25) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.41) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 481.90) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.04) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.21) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 478.54) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.40) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.33) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 479.69) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.58) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.58) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 475.51) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.59) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.63) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.84) :-\n", - " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.40) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 457.29) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 457.77) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 460.79) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 461.57) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 463.79) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 460.57) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 459.06) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 456.52) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 451.68) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 450.11) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 455.09) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 451.49) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 451.23) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 456.93) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 457.31) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 456.15) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 448.29) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 445.98) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 451.08) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 447.20) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 443.67) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 450.66) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 450.45) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.79) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 443.17) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 445.23) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 437.81) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 439.21) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 443.28) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 442.04) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 443.39) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.45) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 442.41) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 440.86) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.81) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 434.24) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 434.45) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.93) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 436.02) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 434.65) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.39) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 482.41) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 481.90) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.04) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.21) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 478.54) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.40) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.33) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 479.69) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.58) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.58) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 475.51) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.59) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.63) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.84) :-\n", - " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.40) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 457.29) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 457.77) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 460.79) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 461.57) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 463.79) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 460.57) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 459.06) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 456.52) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 451.68) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 450.11) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 455.09) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 451.49) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 451.23) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 456.93) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 457.31) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 456.15) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 448.29) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 445.98) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 451.08) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 447.20) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 443.67) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 450.66) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 450.45) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.79) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 443.17) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 445.23) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 437.81) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 439.21) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 443.28) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 442.04) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 443.39) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.45) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 442.41) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 440.86) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.81) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 434.24) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 434.45) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.93) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 436.02) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 434.65) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.39) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 470.05) :-\n", - " AT in [2.33, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.29) :-\n", - " AT in [19.05, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.05) :-\n", - " AT in [2.33, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.29) :-\n", - " AT in [19.05, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 471.13) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 461.20) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 449.17) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 439.66) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 471.13) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 461.20) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 449.17) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 439.66) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.90) :-\n", - " AT in [2.33, 13.48], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 453.67) :-\n", - " AT in [13.48, 24.62], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.76) :-\n", - " AT in [24.62, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.90) :-\n", - " AT in [2.33, 13.48], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 453.67) :-\n", - " AT in [13.48, 24.62], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.76) :-\n", - " AT in [24.62, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.45) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 475.45) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.45) :-\n", - " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 463.56) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 452.52) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.06) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.94) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.07) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.18) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.45) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 475.45) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.45) :-\n", - " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 463.56) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 452.52) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.06) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.94) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.07) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.18) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 483.28) :-\n", - " AT in [2.33, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.58) :-\n", - " AT in [9.02, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 453.90) :-\n", - " AT in [15.71, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.37) :-\n", - " AT in [22.39, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.51) :-\n", - " AT in [29.08, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 483.28) :-\n", - " AT in [2.33, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.58) :-\n", - " AT in [9.02, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 453.90) :-\n", - " AT in [15.71, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.37) :-\n", - " AT in [22.39, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.51) :-\n", - " AT in [29.08, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 485.17) :-\n", - " AT in [2.33, 9.02], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 483.31) :-\n", - " AT in [2.33, 9.02], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.27) :-\n", - " AT in [2.33, 9.02], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.21) :-\n", - " AT in [2.33, 9.02], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 472.40) :-\n", - " AT in [9.02, 15.71], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.93) :-\n", - " AT in [9.02, 15.71], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 466.36) :-\n", - " AT in [9.02, 15.71], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 467.00) :-\n", - " AT in [9.02, 15.71], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 457.10) :-\n", - " AT in [15.71, 22.39], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.41) :-\n", - " AT in [15.71, 22.39], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 452.81) :-\n", - " AT in [15.71, 22.39], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 448.42) :-\n", - " AT in [15.71, 22.39], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 446.88) :-\n", - " AT in [15.71, 22.39], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 445.49) :-\n", - " AT in [22.39, 29.08], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.57) :-\n", - " AT in [22.39, 29.08], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.40) :-\n", - " AT in [22.39, 29.08], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.49) :-\n", - " AT in [22.39, 29.08], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.89) :-\n", - " AT in [29.08, 35.77], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 443.08) :-\n", - " AT in [29.08, 35.77], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.92) :-\n", - " AT in [29.08, 35.77], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 432.88) :-\n", - " AT in [29.08, 35.77], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 485.17) :-\n", - " AT in [2.33, 9.02], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 483.31) :-\n", - " AT in [2.33, 9.02], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.27) :-\n", - " AT in [2.33, 9.02], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.21) :-\n", - " AT in [2.33, 9.02], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 472.40) :-\n", - " AT in [9.02, 15.71], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.93) :-\n", - " AT in [9.02, 15.71], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 466.36) :-\n", - " AT in [9.02, 15.71], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 467.00) :-\n", - " AT in [9.02, 15.71], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 457.10) :-\n", - " AT in [15.71, 22.39], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.41) :-\n", - " AT in [15.71, 22.39], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 452.81) :-\n", - " AT in [15.71, 22.39], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 448.42) :-\n", - " AT in [15.71, 22.39], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 446.88) :-\n", - " AT in [15.71, 22.39], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 445.49) :-\n", - " AT in [22.39, 29.08], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.57) :-\n", - " AT in [22.39, 29.08], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.40) :-\n", - " AT in [22.39, 29.08], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.49) :-\n", - " AT in [22.39, 29.08], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.89) :-\n", - " AT in [29.08, 35.77], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 443.08) :-\n", - " AT in [29.08, 35.77], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.92) :-\n", - " AT in [29.08, 35.77], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 432.88) :-\n", - " AT in [29.08, 35.77], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 486.49) :-\n", - " AT in [2.33, 5.68], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.56) :-\n", - " AT in [5.68, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 474.79) :-\n", - " AT in [9.02, 12.36], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 466.96) :-\n", - " AT in [12.36, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 458.45) :-\n", - " AT in [15.71, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 450.01) :-\n", - " AT in [19.05, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.66) :-\n", - " AT in [22.39, 25.74], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 437.65) :-\n", - " AT in [25.74, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.90) :-\n", - " AT in [29.08, 32.42], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.90) :-\n", - " AT in [32.42, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 486.49) :-\n", - " AT in [2.33, 5.68], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.56) :-\n", - " AT in [5.68, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 474.79) :-\n", - " AT in [9.02, 12.36], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 466.96) :-\n", - " AT in [12.36, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 458.45) :-\n", - " AT in [15.71, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 450.01) :-\n", - " AT in [19.05, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.66) :-\n", - " AT in [22.39, 25.74], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 437.65) :-\n", - " AT in [25.74, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.90) :-\n", - " AT in [29.08, 32.42], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.90) :-\n", - " AT in [32.42, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.95) :-\n", - " AT in [2.33, 13.48], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.83) :-\n", - " AT in [2.33, 13.48], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.42) :-\n", - " AT in [13.48, 24.62], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 446.57) :-\n", - " AT in [13.48, 24.62], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.25) :-\n", - " AT in [24.62, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.31) :-\n", - " AT in [24.62, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.95) :-\n", - " AT in [2.33, 13.48], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.83) :-\n", - " AT in [2.33, 13.48], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.42) :-\n", - " AT in [13.48, 24.62], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 446.57) :-\n", - " AT in [13.48, 24.62], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.25) :-\n", - " AT in [24.62, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.31) :-\n", - " AT in [24.62, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 473.96) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 468.97) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 471.39) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 472.61) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 468.07) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.26) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 464.10) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 445.50) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.77) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 449.32) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 447.25) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.54) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 438.05) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.71) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.25) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n" - ] - } - ], - "source": [ - "pedro = PEDRO(predictor, train, max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1,\n", - " max_depth=1, patience=1, algorithm=PEDRO.Algorithm.GRIDEX, objective=Objective.MODEL)\n", - "pedro.search()\n", - "(_, _, threshold, grid) = pedro.get_best()[0]\n", - "\n", - "gridEx = Extractor.gridex(predictor, grid, threshold=threshold)\n", - "theory_from_gridEx = gridEx.extract(train)\n", - "scores, completeness = get_scores(gridEx, test, predictor)\n", - "print(f'GridEx performance ({gridEx.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('\\nGridEx extracted rules:\\n\\n' + pretty_theory(theory_from_gridEx))" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "**********************\n", - "Best Algorithm.GRIDEX\n", - "**********************\n", - "MAE = 6.45, 15 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Fixed (2)\n", - "\n", - "**********************\n", - "Best MAE \n", - "**********************\n", - "MAE = 6.45, 256 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Adaptive ([(0.33, 2), (0.67, 3)])\n", - "\n", - "**********************\n", - "Best N rules\n", - "**********************\n", - "MAE = 6.45, 15 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Fixed (2)\n", - "\n", - "GridREx performance (292 rules with 99.90% coverage):\n", - "MAE = 6.50 (data), 6.49 (BB)\n", - "MSE = 66.41 (data), 65.91 (BB)\n", - "R2 = 0.77 (data), 0.77 (BB)\n", - "GridREx extracted rules:\n", - "\n", - "'PE'(AP, AT, RH, V, 473.96) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 468.97) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 471.39) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 472.61) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 468.07) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.26) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 464.10) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 445.50) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.77) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 449.32) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 447.25) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.54) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 438.05) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.71) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.25) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 473.96) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 468.97) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 471.39) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 472.61) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 468.07) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.26) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 464.10) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 445.50) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.77) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 449.32) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 447.25) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.54) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 438.05) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.71) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.25) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.41) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 481.90) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.04) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.21) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 478.54) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.40) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.33) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 479.69) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.58) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.58) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 475.51) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.59) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.63) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.84) :-\n", - " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.40) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 457.29) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 457.77) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 460.79) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 461.57) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 463.79) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 460.57) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 459.06) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 456.52) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 451.68) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 450.11) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 455.09) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 451.49) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 451.23) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 456.93) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 457.31) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 456.15) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 448.29) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 445.98) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 451.08) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 447.20) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 443.67) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 450.66) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 450.45) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.79) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 443.17) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 445.23) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 437.81) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 439.21) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 443.28) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 442.04) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 443.39) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.45) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 442.41) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 440.86) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.81) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 434.24) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 434.45) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.93) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 436.02) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 434.65) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.39) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 482.41) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 481.90) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.04) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.21) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 478.54) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.40) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.33) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 479.69) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.58) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.58) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 475.51) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.59) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 477.63) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.84) :-\n", - " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.40) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 457.29) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 457.77) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 460.79) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 461.57) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 463.79) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 460.57) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 459.06) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 456.52) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 451.68) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 450.11) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 455.09) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 451.49) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 451.23) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 456.93) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 457.31) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 456.15) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 448.29) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 445.98) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 451.08) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 447.20) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 443.67) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 450.66) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 450.45) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.79) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 443.17) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 445.23) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 437.81) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 439.21) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 443.28) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 442.04) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 443.39) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.45) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 442.41) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 440.86) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.81) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 434.24) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 434.45) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.93) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n", - "'PE'(AP, AT, RH, V, 436.02) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 434.65) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.39) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n", - "'PE'(AP, AT, RH, V, 470.05) :-\n", - " AT in [2.33, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.29) :-\n", - " AT in [19.05, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.05) :-\n", - " AT in [2.33, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.29) :-\n", - " AT in [19.05, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 471.13) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 461.20) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 449.17) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 439.66) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 471.13) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 461.20) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 449.17) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 439.66) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.90) :-\n", - " AT in [2.33, 13.48], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 453.67) :-\n", - " AT in [13.48, 24.62], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.76) :-\n", - " AT in [24.62, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.90) :-\n", - " AT in [2.33, 13.48], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 453.67) :-\n", - " AT in [13.48, 24.62], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.76) :-\n", - " AT in [24.62, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.45) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 475.45) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.45) :-\n", - " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 463.56) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 452.52) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.06) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.94) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.07) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.18) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.45) :-\n", - " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 475.45) :-\n", - " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.45) :-\n", - " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 463.56) :-\n", - " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 452.52) :-\n", - " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.06) :-\n", - " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.94) :-\n", - " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.07) :-\n", - " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.18) :-\n", - " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 483.28) :-\n", - " AT in [2.33, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.58) :-\n", - " AT in [9.02, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 453.90) :-\n", - " AT in [15.71, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.37) :-\n", - " AT in [22.39, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.51) :-\n", - " AT in [29.08, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 483.28) :-\n", - " AT in [2.33, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.58) :-\n", - " AT in [9.02, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 453.90) :-\n", - " AT in [15.71, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.37) :-\n", - " AT in [22.39, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.51) :-\n", - " AT in [29.08, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 485.17) :-\n", - " AT in [2.33, 9.02], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 483.31) :-\n", - " AT in [2.33, 9.02], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.27) :-\n", - " AT in [2.33, 9.02], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.21) :-\n", - " AT in [2.33, 9.02], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 472.40) :-\n", - " AT in [9.02, 15.71], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.93) :-\n", - " AT in [9.02, 15.71], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 466.36) :-\n", - " AT in [9.02, 15.71], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 467.00) :-\n", - " AT in [9.02, 15.71], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 457.10) :-\n", - " AT in [15.71, 22.39], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.41) :-\n", - " AT in [15.71, 22.39], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 452.81) :-\n", - " AT in [15.71, 22.39], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 448.42) :-\n", - " AT in [15.71, 22.39], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 446.88) :-\n", - " AT in [15.71, 22.39], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 445.49) :-\n", - " AT in [22.39, 29.08], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.57) :-\n", - " AT in [22.39, 29.08], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.40) :-\n", - " AT in [22.39, 29.08], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.49) :-\n", - " AT in [22.39, 29.08], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.89) :-\n", - " AT in [29.08, 35.77], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 443.08) :-\n", - " AT in [29.08, 35.77], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.92) :-\n", - " AT in [29.08, 35.77], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 432.88) :-\n", - " AT in [29.08, 35.77], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 485.17) :-\n", - " AT in [2.33, 9.02], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 483.31) :-\n", - " AT in [2.33, 9.02], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.27) :-\n", - " AT in [2.33, 9.02], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.21) :-\n", - " AT in [2.33, 9.02], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 472.40) :-\n", - " AT in [9.02, 15.71], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.93) :-\n", - " AT in [9.02, 15.71], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 466.36) :-\n", - " AT in [9.02, 15.71], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 467.00) :-\n", - " AT in [9.02, 15.71], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 457.10) :-\n", - " AT in [15.71, 22.39], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.41) :-\n", - " AT in [15.71, 22.39], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 452.81) :-\n", - " AT in [15.71, 22.39], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 448.42) :-\n", - " AT in [15.71, 22.39], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 446.88) :-\n", - " AT in [15.71, 22.39], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 445.49) :-\n", - " AT in [22.39, 29.08], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 444.57) :-\n", - " AT in [22.39, 29.08], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.40) :-\n", - " AT in [22.39, 29.08], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 435.49) :-\n", - " AT in [22.39, 29.08], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 440.89) :-\n", - " AT in [29.08, 35.77], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 443.08) :-\n", - " AT in [29.08, 35.77], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.92) :-\n", - " AT in [29.08, 35.77], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 432.88) :-\n", - " AT in [29.08, 35.77], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 486.49) :-\n", - " AT in [2.33, 5.68], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.56) :-\n", - " AT in [5.68, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 474.79) :-\n", - " AT in [9.02, 12.36], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 466.96) :-\n", - " AT in [12.36, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 458.45) :-\n", - " AT in [15.71, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 450.01) :-\n", - " AT in [19.05, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.66) :-\n", - " AT in [22.39, 25.74], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 437.65) :-\n", - " AT in [25.74, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.90) :-\n", - " AT in [29.08, 32.42], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.90) :-\n", - " AT in [32.42, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 486.49) :-\n", - " AT in [2.33, 5.68], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 482.56) :-\n", - " AT in [5.68, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 474.79) :-\n", - " AT in [9.02, 12.36], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 466.96) :-\n", - " AT in [12.36, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 458.45) :-\n", - " AT in [15.71, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 450.01) :-\n", - " AT in [19.05, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.66) :-\n", - " AT in [22.39, 25.74], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 437.65) :-\n", - " AT in [25.74, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 433.90) :-\n", - " AT in [29.08, 32.42], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.90) :-\n", - " AT in [32.42, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.95) :-\n", - " AT in [2.33, 13.48], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.83) :-\n", - " AT in [2.33, 13.48], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.42) :-\n", - " AT in [13.48, 24.62], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 446.57) :-\n", - " AT in [13.48, 24.62], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.25) :-\n", - " AT in [24.62, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.31) :-\n", - " AT in [24.62, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 476.95) :-\n", - " AT in [2.33, 13.48], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 477.83) :-\n", - " AT in [2.33, 13.48], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 459.42) :-\n", - " AT in [13.48, 24.62], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 446.57) :-\n", - " AT in [13.48, 24.62], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 442.25) :-\n", - " AT in [24.62, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.31) :-\n", - " AT in [24.62, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n", - "'PE'(AP, AT, RH, V, 473.96) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 468.97) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 471.39) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 472.61) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 468.07) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 470.26) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 464.10) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 445.50) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.77) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 449.32) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 447.25) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 436.54) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 438.05) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, 441.71) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n", - "'PE'(AP, AT, RH, V, 446.25) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85], PE is 462.71 - 2.15 * AP - 0.22 * AT + 0.04 * RH - 0.02 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15], PE is 431.79 - 2.16 * AP - 0.45 * AT + 0.08 * RH - 0.06 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85], PE is 495.74 - 1.80 * AP - 0.07 * AT + 0.00 * RH - 0.01 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15], PE is 703.70 - 2.37 * AP - 0.12 * AT - 0.18 * RH - 0.11 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15], PE is 540.25 - 2.54 * AP - 0.04 * AT - 0.04 * RH + 0.03 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85], PE is 556.66 - 2.35 * AP - 0.04 * AT - 0.05 * RH + 0.05 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15], PE is 453.81 - 2.40 * AP - 0.18 * AT + 0.05 * RH - 0.04 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85], PE is 495.08 - 1.30 * AP - 0.20 * AT - 0.00 * RH - 0.10 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15], PE is 394.31 - 1.06 * AP - 0.32 * AT + 0.09 * RH - 0.01 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85], PE is 625.50 - 1.14 * AP + 0.09 * AT - 0.13 * RH - 0.27 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15], PE is 699.87 - 1.10 * AP + 0.06 * AT - 0.21 * RH - 0.05 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85], PE is 106.52 - 1.12 * AP - 0.21 * AT + 0.37 * RH - 0.04 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15], PE is 180.91 - 1.23 * AP - 0.29 * AT + 0.31 * RH - 0.09 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85], PE is 396.75 - 1.41 * AP - 0.28 * AT + 0.10 * RH - 0.01 * V.\n", - "'PE'(AP, AT, RH, V, PE) :-\n", - " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15], PE is 446.80 - 1.76 * AP - 0.30 * AT + 0.07 * RH - 0.22 * V.\n" - ] - } - ], - "source": [ - "#pedro = PEDRO(predictor, train, max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1,\n", - "# max_depth=2, patience=1, algorithm=PEDRO.Algorithm.GRIDREX, objective=Objective.MODEL)\n", - "#pedro.search()\n", - "(_, _, threshold, grid) = pedro.get_best()[0]\n", - "\n", - "gridREx = Extractor.gridrex(predictor, grid, threshold=threshold)\n", - "theory_from_gridREx = gridREx.extract(train)\n", - "scores, completeness = get_scores(gridREx, test, predictor)\n", - "print(f'GridREx performance ({gridREx.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('GridREx extracted rules:\\n\\n' + pretty_theory(theory_from_gridREx))" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CART performance (6 rules with 100.00% coverage):\n", - "MAE = 4.46 (data), 4.49 (BB)\n", - "MSE = 32.55 (data), 32.53 (BB)\n", - "R2 = 0.89 (data), 0.89 (BB)\n", - "CART extracted rules:\n", - "\n", - "'PE'(AP, AT, RH, V, 479.15) :-\n", - " AT =< 18.25, AT =< 11.90.\n", - "'PE'(AP, AT, RH, V, 435.66) :-\n", - " AT > 18.25, V > 66.20.\n", - "'PE'(AP, AT, RH, V, 451.33) :-\n", - " AT > 18.25, V =< 66.20, AT =< 22.89.\n", - "'PE'(AP, AT, RH, V, 443.00) :-\n", - " AT > 18.25, V =< 66.20, AT > 22.89.\n", - "'PE'(AP, AT, RH, V, 467.45) :-\n", - " AT > 11.90, AT =< 15.64.\n", - "'PE'(AP, AT, RH, V, 459.70) :-\n", - " AT > 15.64.\n" - ] - } - ], - "source": [ - "cart = Extractor.cart(predictor, max_depth=5, max_leaves=6, simplify=True)\n", - "theory_from_cart = cart.extract(train)\n", - "scores, completeness = get_scores(cart, test, predictor)\n", - "print(f'CART performance ({cart.n_rules} rules with {completeness * 100:.2f}% coverage):')\n", - "print_scores(scores)\n", - "print('CART extracted rules:\\n\\n' + pretty_theory(theory_from_cart))" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "outputs": [], - "source": [], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - } - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "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.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} \ No newline at end of file diff --git a/demo/DemoRegressionScaled.ipynb b/demo/DemoRegressionScaled.ipynb index b57fab34..133d3e91 100644 --- a/demo/DemoRegressionScaled.ipynb +++ b/demo/DemoRegressionScaled.ipynb @@ -1,15 +1,5 @@ { "cells": [ - { - "cell_type": "markdown", - "id": "f52126f3", - "metadata": {}, - "source": [ - "# PSyKE's demo for regression tasks\n", - "\n", - "Some imports." - ] - }, { "cell_type": "code", "execution_count": 1, @@ -17,976 +7,399 @@ "metadata": {}, "outputs": [], "source": [ - "from psyke import Extractor, Clustering\n", - "from psyke.tuning.pedro import PEDRO\n", - "from psyke.tuning import Objective\n", - "from psyke.tuning.crash import CRASH\n", - "from sklearn.tree import DecisionTreeRegressor\n", - "from psyke.utils.logic import pretty_theory\n", - "from psyke.utils.metrics import mae, mse, r2\n", - "from sklearn.model_selection import train_test_split\n", + "from sklearn.neighbors import KNeighborsRegressor as KNN\n", "from sklearn.preprocessing import StandardScaler\n", - "from psyke.utils import Target\n", - "import pandas as pd" - ] - }, - { - "cell_type": "markdown", - "id": "d7c90ed2", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "Import an artificial dataset." + "\n", + "from joblib import dump, load\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "from psyke import Extractor, Clustering, Target\n", + "from psyke.extraction.hypercubic.strategy import AdaptiveStrategy\n", + "from psyke.extraction.hypercubic import Grid, FeatureRanker\n", + "from psyke.utils.logic import pretty_theory\n", + "\n", + "from plot import *" ] }, { "cell_type": "code", "execution_count": 2, - "id": "f8e46c49", - "metadata": {}, "outputs": [], "source": [ - "#dataset = pd.read_csv(\"../test/resources/datasets/df.csv\")\n", - "#dataset = dataset[[\"X\", \"Y\", \"Z4\"]].dropna()\n", - "#dataset = pd.read_csv(\"../test/resources/datasets/CCPP.csv\", sep=\";\", decimal=\",\")\n", - "dataset = pd.read_csv(\"../test/resources/datasets/arti.csv\")" - ] - }, - { - "cell_type": "markdown", - "id": "d673b766", - "metadata": {}, - "source": [ - "Split between train and test set in a reproducible way." - ] + "def plot(testB, x, pred, extracted):\n", + " missing = pd.read_csv(\"data/missing.csv\", parse_dates = [0], index_col = 0)\n", + " df = pd.read_csv(\"data/averaged1.csv\", parse_dates = [0], index_col = 0)\n", + " df.LPFnorm[missing.index] = np.nan\n", + "\n", + " for i, b in bartels.iterrows():\n", + " if b.n != testB:\n", + " continue\n", + " xminmax = [b.t0, b.t1]\n", + "\n", + " f, axes = plt.subplots(3, figsize=(10, 8)) # l x h\n", + "\n", + " myplot(axes[0], [3, 1], \"LPF\", df.index, df.LPFnorm, xminmax)\n", + " myplot(axes[0], [3, 1], \"\", missing.index, missing.LPF0, xminmax, color='r', marker='*', lw=0, size=10)\n", + " myplot(axes[1], [3, 2], \"V\", df.index, df.V, xminmax)\n", + " myplot(axes[1], [3, 2], \"\", x, pred, xminmax, color='b', marker='.', lw=0)\n", + " myplot(axes[1], [3, 2], \"\", x, extracted, xminmax, color='r', marker='.', lw=0)\n", + " myplot(axes[2], [3, 3], \"B\", df.index, df.B, xminmax)\n", + " plt.subplots_adjust(hspace=0.6)\n", + " plt.savefig(f\"plot/{b.n}.jpg\", dpi=96 * 2)\n", + " plt.show()" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } }, { "cell_type": "code", - "execution_count": 3, - "id": "03fc5e2c", - "metadata": {}, + "execution_count": 5, "outputs": [], "source": [ - "train, test = train_test_split(dataset, test_size=0.5, random_state=10)\n", + "def splitTest(data):\n", + " b = bartels[(bartels.n == 2490)]\n", + " data = data[(data.index >= b.t1.values[0])]\n", "\n", - "scaler = StandardScaler().fit(train)\n", - "train = pd.DataFrame(scaler.transform(train), columns=train.columns, index=train.index)\n", - "test = pd.DataFrame(scaler.transform(test), columns=test.columns, index=test.index)\n", + " b = bartels[(bartels.n == 2494) | (bartels.n == 2495)]\n", + " idx = np.zeros_like(data.index, dtype='bool')\n", + " for _, row in b.iterrows():\n", + " t0, t1 = row.t0, row.t1\n", + " idx = idx | (data.index >= t0) & (data.index < t1)\n", + " return data[~idx], data[idx]\n", "\n", - "normalization = {key: (m, s) for key, m, s in zip(train.columns, scaler.mean_, scaler.scale_)}" - ] - }, - { - "cell_type": "markdown", - "id": "fa6754a0", - "metadata": {}, - "source": [ - "We select and train a predictor." - ] + "bartels = pd.read_csv(\"data/bartels.csv\", parse_dates = [1, 2])\n", + "data = pd.read_csv(f'data/halffuzzycoefs4B3.csv', parse_dates=[0], index_col=0)\n", + "train, test = splitTest(data)\n", + "train.to_csv('data/alltrain.csv')\n", + "test.to_csv('data/alltest.csv')\n", + "\n", + "data = pd.read_csv(f'data/pruned.csv', parse_dates=[0], index_col=0)\n", + "train, test = splitTest(data)\n", + "train.to_csv('data/prunedtrain.csv')\n", + "test.to_csv('data/prunedtest.csv')" + ], + "metadata": { + "collapsed": false, + "pycharm": { + "name": "#%%\n" + } + } }, { "cell_type": "code", - "execution_count": 4, - "id": "bed764ca", - "metadata": {}, + "execution_count": 73, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "MAE = 0.00\n", - "MSE = 0.00\n", - "R2 = 1.00\n" - ] + "data": { + "text/plain": " Bmin Bmedian Bmax Btrend Bhalf1 Bhalf2 \\\n2016-03-04 00:00:00 4.0 7.5 12.3 -0.080751 0.009474 -0.106862 \n2016-03-04 01:00:00 4.0 7.5 12.3 -0.086067 -0.012065 -0.101174 \n2016-03-04 02:00:00 4.0 7.5 12.3 -0.090328 -0.029534 -0.094717 \n2016-03-04 03:00:00 4.0 7.5 12.3 -0.094527 -0.046781 -0.089474 \n2016-03-04 04:00:00 4.0 7.5 12.3 -0.098312 -0.062166 -0.087105 \n... ... ... ... ... ... ... \n2017-07-02 19:00:00 1.6 8.0 18.2 0.168533 0.139028 0.004049 \n2017-07-02 20:00:00 1.6 8.3 18.2 0.165550 0.157085 -0.019089 \n2017-07-02 21:00:00 1.6 8.3 18.2 0.161067 0.174393 -0.041862 \n2017-07-02 22:00:00 1.6 8.5 18.2 0.156652 0.188077 -0.061781 \n2017-07-02 23:00:00 1.6 8.5 18.2 0.151061 0.198158 -0.086761 \n\n Bthird1 Bthird2 Bthird3 GCRmin ... GCRhalf1 \\\n2016-03-04 00:00:00 -0.001462 -0.016066 -0.068720 -3.883201 ... -0.034045 \n2016-03-04 01:00:00 -0.004731 -0.012913 -0.074356 -3.883201 ... -0.035872 \n2016-03-04 02:00:00 -0.007107 -0.008399 -0.080310 -3.883201 ... -0.038517 \n2016-03-04 03:00:00 -0.010202 -0.001853 -0.085397 -3.883201 ... -0.040322 \n2016-03-04 04:00:00 -0.012979 0.006375 -0.089585 -3.883201 ... -0.042501 \n... ... ... ... ... ... ... \n2017-07-02 19:00:00 -0.032341 0.005700 0.162350 -4.670171 ... -0.059403 \n2017-07-02 20:00:00 -0.032566 0.005048 0.159932 -4.670171 ... -0.058878 \n2017-07-02 21:00:00 -0.033405 0.002897 0.157075 -4.670171 ... -0.058062 \n2017-07-02 22:00:00 -0.033445 0.001775 0.153994 -4.670171 ... -0.057460 \n2017-07-02 23:00:00 -0.033619 0.001199 0.149502 -4.670171 ... -0.056252 \n\n GCRhalf2 GCRthird1 GCRthird2 GCRthird3 GCRfourth1 \\\n2016-03-04 00:00:00 0.060357 0.002682 -0.072897 0.065471 0.007162 \n2016-03-04 01:00:00 0.061504 0.000701 -0.070397 0.064501 0.006544 \n2016-03-04 02:00:00 0.062143 -0.002516 -0.066904 0.064396 0.004833 \n2016-03-04 03:00:00 0.063626 -0.002422 -0.062109 0.066305 0.004309 \n2016-03-04 04:00:00 0.064246 -0.005347 -0.056971 0.065904 0.002981 \n... ... ... ... ... ... \n2017-07-02 19:00:00 0.016938 -0.075540 0.018295 -0.025042 -0.074034 \n2017-07-02 20:00:00 0.015490 -0.076592 0.020250 -0.027076 -0.076765 \n2017-07-02 21:00:00 0.014373 -0.076522 0.022473 -0.028479 -0.079294 \n2017-07-02 22:00:00 0.013574 -0.077431 0.025158 -0.029432 -0.080745 \n2017-07-02 23:00:00 0.012860 -0.077216 0.027493 -0.031331 -0.082300 \n\n GCRfourth2 GCRfourth3 GCRfourth4 V \n2016-03-04 00:00:00 -0.092158 0.046471 0.069499 410.0 \n2016-03-04 01:00:00 -0.095190 0.049612 0.069178 400.0 \n2016-03-04 02:00:00 -0.098934 0.049670 0.071374 395.0 \n2016-03-04 03:00:00 -0.102389 0.052382 0.072217 408.0 \n2016-03-04 04:00:00 -0.105296 0.052220 0.070273 406.0 \n... ... ... ... ... \n2017-07-02 19:00:00 -0.027912 0.071203 -0.054068 477.0 \n2017-07-02 20:00:00 -0.026023 0.071905 -0.053493 442.0 \n2017-07-02 21:00:00 -0.022508 0.073575 -0.054818 437.0 \n2017-07-02 22:00:00 -0.020645 0.074790 -0.054839 436.0 \n2017-07-02 23:00:00 -0.017545 0.074579 -0.054656 430.0 \n\n[9720 rows x 23 columns]", + "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
BminBmedianBmaxBtrendBhalf1Bhalf2Bthird1Bthird2Bthird3GCRmin...GCRhalf1GCRhalf2GCRthird1GCRthird2GCRthird3GCRfourth1GCRfourth2GCRfourth3GCRfourth4V
2016-03-04 00:00:004.07.512.3-0.0807510.009474-0.106862-0.001462-0.016066-0.068720-3.883201...-0.0340450.0603570.002682-0.0728970.0654710.007162-0.0921580.0464710.069499410.0
2016-03-04 01:00:004.07.512.3-0.086067-0.012065-0.101174-0.004731-0.012913-0.074356-3.883201...-0.0358720.0615040.000701-0.0703970.0645010.006544-0.0951900.0496120.069178400.0
2016-03-04 02:00:004.07.512.3-0.090328-0.029534-0.094717-0.007107-0.008399-0.080310-3.883201...-0.0385170.062143-0.002516-0.0669040.0643960.004833-0.0989340.0496700.071374395.0
2016-03-04 03:00:004.07.512.3-0.094527-0.046781-0.089474-0.010202-0.001853-0.085397-3.883201...-0.0403220.063626-0.002422-0.0621090.0663050.004309-0.1023890.0523820.072217408.0
2016-03-04 04:00:004.07.512.3-0.098312-0.062166-0.087105-0.0129790.006375-0.089585-3.883201...-0.0425010.064246-0.005347-0.0569710.0659040.002981-0.1052960.0522200.070273406.0
..................................................................
2017-07-02 19:00:001.68.018.20.1685330.1390280.004049-0.0323410.0057000.162350-4.670171...-0.0594030.016938-0.0755400.018295-0.025042-0.074034-0.0279120.071203-0.054068477.0
2017-07-02 20:00:001.68.318.20.1655500.157085-0.019089-0.0325660.0050480.159932-4.670171...-0.0588780.015490-0.0765920.020250-0.027076-0.076765-0.0260230.071905-0.053493442.0
2017-07-02 21:00:001.68.318.20.1610670.174393-0.041862-0.0334050.0028970.157075-4.670171...-0.0580620.014373-0.0765220.022473-0.028479-0.079294-0.0225080.073575-0.054818437.0
2017-07-02 22:00:001.68.518.20.1566520.188077-0.061781-0.0334450.0017750.153994-4.670171...-0.0574600.013574-0.0774310.025158-0.029432-0.080745-0.0206450.074790-0.054839436.0
2017-07-02 23:00:001.68.518.20.1510610.198158-0.086761-0.0336190.0011990.149502-4.670171...-0.0562520.012860-0.0772160.027493-0.031331-0.082300-0.0175450.074579-0.054656430.0
\n

9720 rows × 23 columns

\n
" + }, + "execution_count": 73, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "#predictor = KNeighborsRegressor(n_neighbors=3).fit(train.iloc[:, :-1], train.iloc[:, -1])\n", - "predictor = DecisionTreeRegressor().fit(train.iloc[:, :-1], train.iloc[:, -1])\n", - "#predictor = LinearRegression().fit(train.iloc[:, :-1], train.iloc[:, -1])\n", - "\n", - "m, s = normalization[test.columns[-1]]\n", - "\n", - "predicted = predictor.predict(test.iloc[:, :-1]).flatten() * s + m\n", - "true = test.iloc[:, -1] * s + m\n", - "\n", - "print(f'MAE = {mae(true, predicted):.2f}')\n", - "print(f'MSE = {mse(true, predicted):.2f}')\n", - "print(f'R2 = {r2(true, predicted):.2f}')" - ] - }, - { - "cell_type": "markdown", + "pd.read_csv('data/alltrain.csv', parse_dates=[0], index_col=[0])" + ], "metadata": { "collapsed": false, "pycharm": { - "name": "#%% md\n" + "name": "#%%\n" } - }, - "source": [ - "We define a function to print the extractors’ evaluation" - ] + } }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 3, + "outputs": [], + "source": [ + "def getTrainTest(data, testB):\n", + " b = bartels[bartels.n==testB]\n", + " t0, t1 = b.t0.values[0], b.t1.values[0]\n", + " idx = (data.index >= t0) & (data.index < t1)\n", + " return data[~idx], data[idx]\n", + "\n", + "def getScaler(train, name):\n", + " scaler = StandardScaler().fit(train)\n", + " dump(scaler, f\"scalers/scalerV{name}.joblib\")\n", + " normalization = {key: (m, s) for key, m, s in zip(train.columns, scaler.mean_, scaler.scale_)}\n", + " return scaler, pd.DataFrame(scaler.transform(train), columns=train.columns), normalization" + ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [], - "source": [ - "def evaluate(name, extractor, true, predicted):\n", - " extracted = extractor.unscale(extractor.predict(test.iloc[:, :-1]), test.columns[-1])\n", - " print(f'{name} performance ({extractor.n_rules} rules):\\n'\n", - " f'MAE = {mae(true, extracted):.2f}\\nMAE fidelity = {mae(predicted, extracted):.2f}\\n'\n", - " f'R2 = {r2(true, extracted):.2f}\\nR2 fidelity = {r2(predicted, extracted):.2f}\\n')" - ] - }, - { - "cell_type": "markdown", - "id": "96835867", - "metadata": {}, - "source": [ - "We create several extractors that use ITER, GridEx and GridREx algorithms to extract prolog rules from the predictor." - ] + } }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 4, + "outputs": [], + "source": [ + "def gridex(model, train, test, normalization):\n", + " ranked = FeatureRanker(train.columns).fit(model, train.iloc[:, :-1]).rankings()\n", + " gridEx = Extractor.gridex(model, Grid(1, AdaptiveStrategy(ranked, [(0.6, 3), (0.75, 4)])),\n", + " threshold=.5, min_examples=1, normalization=normalization)\n", + " gridEx.extract(train)\n", + " return gridEx.brute_predict(test), gridEx.n_rules, sum([p is None for p in gridEx.predict(test)])\n", + " \n", + "def gridrex(model, train, test, normalization):\n", + " ranked = FeatureRanker(train.columns).fit(model, train.iloc[:, :-1]).rankings()\n", + " gridREx = Extractor.gridrex(model, Grid(1, AdaptiveStrategy(ranked, [(0.5, 3)])),\n", + " threshold=.5, min_examples=1, normalization=normalization)\n", + " gridREx.extract(train)\n", + " return gridREx.brute_predict(test, 'default'), gridREx.n_rules, sum([p is None for p in gridREx.predict(test)])\n", + "\n", + "def cart(model, train, test, normalization):\n", + " CART = Extractor.cart(model, max_depth=10, max_leaves=10, normalization=normalization)\n", + " CART.extract(train)\n", + " return CART.predict(test), CART.n_rules, sum([p is None for p in CART.predict(test)])\n", + "\n", + "def cosmik(model, train, test, normalization):\n", + " COSMiK = Extractor.cosmik(model, max_components=4, k=125, patience=12, close_to_center=True,\n", + " output=Target.REGRESSION, normalization=normalization)\n", + " COSMiK.extract(train)\n", + " return COSMiK.brute_predict(test, 'default'), COSMiK.n_rules, sum([p is None for p in COSMiK.predict(test)])\n", + "\n", + "def cream(model, train, test, normalization):\n", + " CReEPy = Extractor.creepy(model, clustering=Clustering.cream, depth=5, error_threshold=.5, gauss_components=10,\n", + " output=Target.REGRESSION, normalization=normalization)\n", + " CReEPy.extract(train)\n", + " return CReEPy.brute_predict(test), CReEPy.n_rules, sum([p is None for p in CReEPy.predict(test)])\n", + "\n", + "def exact(model, train, test, normalization):\n", + " CReEPy = Extractor.creepy(model, clustering=Clustering.exact, depth=5, error_threshold=.5, gauss_components=10,\n", + " output=Target.REGRESSION, normalization=normalization)\n", + " CReEPy.extract(train)\n", + " return CReEPy.brute_predict(test), CReEPy.n_rules, sum([p is None for p in CReEPy.predict(test)])" + ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ITER performance (9 rules):\n", - "MAE = 0.04\n", - "MAE fidelity = 0.04\n", - "R2 = 0.88\n", - "R2 fidelity = 0.88\n", - "\n", - "ITER extracted rules:\n", - "\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.46], Y in [0.00, 0.43].\n", - "z(X, Y, 0.59) :-\n", - " X in [0.00, 0.46], Y in [0.43, 0.53].\n", - "z(X, Y, 0.4) :-\n", - " X in [0.00, 0.46], Y in [0.53, 0.99].\n", - "z(X, Y, 0.47) :-\n", - " X in [0.46, 0.56], Y in [0.00, 0.43].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.56, 0.99], Y in [0.00, 0.43].\n", - "z(X, Y, 0.18) :-\n", - " X in [0.46, 0.56], Y in [0.53, 0.99].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.56, 0.99], Y in [0.53, 0.99].\n", - "z(X, Y, 0.32) :-\n", - " X in [0.46, 0.56], Y in [0.43, 0.53].\n", - "z(X, Y, 0.20) :-\n", - " X in [0.56, 0.99], Y in [0.43, 0.53].\n" - ] - } - ], - "source": [ - "it = Extractor.iter(predictor, min_update=1.0 / 10, n_points=1, max_iterations=600,\n", - " min_examples=100, threshold=.4, normalization=normalization)\n", - "theory_from_iter = it.extract(train)\n", - "evaluate('ITER', it, true, predicted)\n", - "print('ITER extracted rules:\\n\\n' + pretty_theory(theory_from_iter))" - ] + } }, { "cell_type": "code", "execution_count": 7, - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%%\n" - } - }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "CReEPy performance (3 rules):\n", - "MAE = 0.08\n", - "MAE fidelity = 0.08\n", - "R2 = 0.81\n", - "R2 fidelity = 0.81\n", - "\n", - "CReEPy extracted rules:\n", - "\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.49], Y in [0.00, 0.49].\n", - "z(X, Y, 0.4) :-\n", - " X in [0.00, 0.49], Y in [0.00, 0.99].\n", - "z(X, Y, 0.145238).\n" + "2491\n", + "GridEx\n", + "GridREx\n", + "CART\n", + "COSMiK\n", + "ExACT\n", + "CREAM\n", + "2492\n", + "GridEx\n", + "GridREx\n", + "CART\n", + "COSMiK\n", + "ExACT\n", + "CREAM\n", + "2493\n", + "GridEx\n", + "GridREx\n", + "CART\n", + "COSMiK\n", + "ExACT\n", + "CREAM\n" ] } ], "source": [ - "creepy = Extractor.creepy(predictor, depth=3, error_threshold=0.02, output=Target.CONSTANT,\n", - " normalization=normalization, clustering=Clustering.exact)\n", - "theory_from_creepy = creepy.extract(train)\n", - "evaluate('CReEPy', creepy, true, predicted)\n", - "print('CReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))" - ] - }, - { - "cell_type": "code", - "execution_count": 8, + "bartels = pd.read_csv(\"data/bartels.csv\", parse_dates = [1, 2])\n", + "\n", + "extractors = ['GridEx', 'GridREx', 'CART', 'COSMiK', 'ExACT', 'CREAM']\n", + "\n", + "TESTB = [i for i in range(2491, 2509)]\n", + "\n", + "predicted = {name: [] for name in ['index', 'V', 'model'] + extractors}\n", + "\n", + "rules = {name: [] for name in ['BR'] + extractors}\n", + "\n", + "missed = {name: [] for name in ['BR'] + extractors}\n", + "\n", + "for testB in TESTB[:3]:\n", + " rules['BR'].append(testB)\n", + " missed['BR'].append(testB)\n", + " print(testB)\n", + "\n", + " data = pd.read_csv(f'data/pruned.csv', parse_dates=[0], index_col=0)\n", + " train, test = getTrainTest(data, testB)\n", + "\n", + " predicted['index'] += list(test.index.values)\n", + " predicted['V'] += list(test.V.values)\n", + "\n", + " scaler, scaledTrain, normalization = getScaler(train, f\"test{testB}\")\n", + " scaledTest = pd.DataFrame(scaler.transform(test), columns=test.columns).iloc[:, :-1]\n", + " m, s = normalization[test.columns[-1]]\n", + "\n", + " model = KNN(200, weights='distance', p=1).fit(scaledTrain.iloc[:, :-1], scaledTrain.iloc[:, -1])\n", + " #dump(model, f\"models/RF/{k}_{name}_{testB}.joblib\")\n", + " predicted['model'] += list(model.predict(scaledTest) * s + m)\n", + "\n", + " for name, fun in zip(extractors, [cart, cart, cart, cosmik, exact, cream]):\n", + " print(name)\n", + " #if name in ['GridREx', 'CART', 'COSMiK']:\n", + " # continue\n", + " pred, n, miss = fun(model, scaledTrain, scaledTest, normalization)\n", + " predicted[name] += list(pred)\n", + " rules[name].append(n)\n", + " missed[name].append(miss)" + ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } - }, + } + }, + { + "cell_type": "code", + "execution_count": 15, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "CReEPy performance (3 rules):\n", - "MAE = 0.03\n", - "MAE fidelity = 0.03\n", - "R2 = 0.94\n", - "R2 fidelity = 0.94\n", - "\n", - "CReEPy extracted rules:\n", - "\n", - "z(X, Y, Z) :-\n", - " X in [0.00, 0.49], Y in [0.00, 0.49], Z is 0.7.\n", - "z(X, Y, Z) :-\n", - " X in [0.00, 0.49], Y in [0.00, 0.99], Z is 0.4.\n", - "z(X, Y, Z) :-\n", - " Y in [0.00, 0.99], Z is 0.38 - 0.09 * X - 1.73 * Y.\n" + "90.20644923758856 47.26039351140736\n", + "90.20644923758856 47.26039351140736\n", + "90.20644923758856 47.26039351140736\n", + "73.38650661174208 31.857409982273143\n", + "71.27591988138312 36.1748132343631\n", + "70.26005494494277 33.783890819165826\n" ] + }, + { + "data": { + "text/plain": " BR GridEx GridREx CART COSMiK ExACT CREAM\n0 2491 10 10 10 4 6 6\n1 2492 10 10 10 8 6 6\n2 2493 10 10 10 9 6 7", + "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
BRGridExGridRExCARTCOSMiKExACTCREAM
02491101010466
12492101010866
22493101010967
\n
" + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "creepy = Extractor.creepy(predictor, depth=3, error_threshold=0.02, output=Target.REGRESSION,\n", - " normalization=normalization, clustering=Clustering.exact)\n", - "theory_from_creepy = creepy.extract(train)\n", - "evaluate('CReEPy', creepy, true, predicted)\n", - "print('CReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))" - ] - }, - { - "cell_type": "code", - "execution_count": 9, + "p = pd.DataFrame(predicted)\n", + "for e in extractors:\n", + " print(abs(p.V - p[e]).mean(), abs(p.model - p[e]).mean())\n", + "\n", + "b = 2493\n", + "#plot(b, p['index'], p.model, p.COSMiK)\n", + "#plot(b, p['index'], p.model, p.ExACT)\n", + "#plot(b, p['index'], p.model, p.CREAM)\n", + "\n", + "pd.DataFrame(rules)" + ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CReEPy performance (4 rules):\n", - "MAE = 0.01\n", - "MAE fidelity = 0.01\n", - "R2 = 0.94\n", - "R2 fidelity = 0.94\n", - "\n", - "CReEPy extracted rules:\n", - "\n", - "z(X, Y, Z) :-\n", - " X in [0.51, 0.99], Y in [0.00, 0.49], Z is 0.3.\n", - "z(X, Y, Z) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.98], Z is 0.0.\n", - "z(X, Y, Z) :-\n", - " X in [0.00, 0.49], Y in [0.50, 0.99], Z is 0.4.\n", - "z(X, Y, Z) :-\n", - " Y in [0.00, 0.99], Z is 0.7.\n" - ] - } - ], - "source": [ - "creepy = Extractor.creepy(predictor, depth=2, error_threshold=0.02, output=Target.REGRESSION,\n", - " normalization=normalization, clustering=Clustering.cream)\n", - "theory_from_creepy = creepy.extract(train)\n", - "evaluate('CReEPy', creepy, true, predicted)\n", - "print('CReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))" - ] + } }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, + "outputs": [], + "source": [ + "pd.DataFrame(predicted).to_csv(\"results/pred1.csv\")\n", + "pd.DataFrame(rules).to_csv('results/rules1.csv')\n", + "pd.DataFrame(missed).to_csv('results/missed1.csv')" + ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Algorithm.ExACT. Depth: 1. Threshold = 0.00. MAE = 0.06, 2 rules\n", - "Algorithm.ExACT. Depth: 1. Threshold = 0.00. MAE = 0.06, 2 rules\n", - "\n", - "Algorithm.ExACT. Depth: 2. Threshold = 0.00. MAE = 0.06, 2 rules\n", - "Algorithm.ExACT. Depth: 2. Threshold = 0.00. MAE = 0.06, 2 rules\n", - "\n", - "**********************\n", - "Best Algorithm.ExACT\n", - "**********************\n", - "MAE = 0.06, 2 rules\n", - "Threshold = 0.00\n", - "Depth = 2\n", - "\n", - "**********************\n", - "Best MAE \n", - "**********************\n", - "MAE = 0.06, 2 rules\n", - "Threshold = 0.00\n", - "Depth = 2\n", - "\n", - "**********************\n", - "Best N rules\n", - "**********************\n", - "MAE = 0.06, 2 rules\n", - "Threshold = 0.00\n", - "Depth = 2\n", - "\n", - "CReEPy performance (3 rules):\n", - "MAE = 0.69\n", - "MAE fidelity = 0.69\n", - "R2 = -8.82\n", - "R2 fidelity = -8.82\n", - "\n", - "CReEPy extracted rules:\n", - "\n", - "z(X, Y, Z) :-\n", - " X in [-1.70, 0.01], Y in [-1.69, 0.02], Z is 1.37.\n", - "z(X, Y, Z) :-\n", - " X in [-1.70, 0.01], Y in [-1.69, 1.75], Z is 0.19.\n", - "z(X, Y, Z) :-\n", - " Y in [-1.69, 1.75], Z is -0.76 - 0.02 * X - 0.50 * Y.\n" - ] - } - ], - "source": [ - "crash = CRASH(predictor, train, max_depth=3, patience=1, readability_tradeoff=.5,\n", - " algorithm=CRASH.Algorithm.ExACT, output=Target.REGRESSION, normalization=normalization)\n", - "crash.search()\n", - "(_, _, depth, threshold) = crash.get_best()[0]\n", - "\n", - "creepy = Extractor.creepy(predictor, depth=depth, error_threshold=threshold, output=Target.REGRESSION,\n", - " clustering=Clustering.exact)\n", - "theory_from_creepy = creepy.extract(train)\n", - "evaluate('CReEPy', creepy, true, predicted)\n", - "print('CReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))" - ] + } }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, + "outputs": [], + "source": [], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Algorithm.CREAM. Depth: 1. Threshold = 0.00. MAE = 0.12, 2 rules\n", - "Algorithm.CREAM. Depth: 1. Threshold = 0.00. MAE = 0.12, 2 rules\n", - "\n", - "Algorithm.CREAM. Depth: 2. Threshold = 0.00. MAE = 0.02, 3 rules\n", - "Algorithm.CREAM. Depth: 2. Threshold = 0.00. MAE = 0.02, 3 rules\n", - "\n", - "**********************\n", - "Best Algorithm.CREAM\n", - "**********************\n", - "MAE = 0.02, 3 rules\n", - "Threshold = 0.00\n", - "Depth = 2\n", - "\n", - "**********************\n", - "Best MAE \n", - "**********************\n", - "MAE = 0.02, 3 rules\n", - "Threshold = 0.00\n", - "Depth = 2\n", - "\n", - "**********************\n", - "Best N rules\n", - "**********************\n", - "MAE = 0.12, 2 rules\n", - "Threshold = 0.00\n", - "Depth = 1\n", - "\n", - "CReEPy performance (4 rules):\n", - "MAE = 0.69\n", - "MAE fidelity = 0.69\n", - "R2 = -9.40\n", - "R2 fidelity = -9.40\n", - "\n", - "CReEPy extracted rules:\n", - "\n", - "z(X, Y, Z) :-\n", - " X in [0.07, 1.75], Y in [-1.69, 0.00], Z is -0.19.\n", - "z(X, Y, Z) :-\n", - " X in [0.02, 1.75], Y in [-1.69, 1.71], Z is -1.37.\n", - "z(X, Y, Z) :-\n", - " X in [-1.69, 0.01], Y in [0.03, 1.75], Z is 0.19.\n", - "z(X, Y, Z) :-\n", - " Y in [-1.69, 1.75], Z is 1.37.\n" - ] - } - ], - "source": [ - "crash = CRASH(predictor, train, max_depth=3, patience=1, readability_tradeoff=.75, algorithm=CRASH.Algorithm.CREAM,\n", - " normalization=normalization)\n", - "crash.search()\n", - "(_, _, depth, threshold) = crash.get_best()[0]\n", - "\n", - "creepy = Extractor.creepy(predictor, depth=depth, error_threshold=threshold, output=Target.REGRESSION,\n", - " clustering=Clustering.cream)\n", - "theory_from_creepy = creepy.extract(train)\n", - "evaluate('CReEPy', creepy, true, predicted)\n", - "print('CReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))" - ] + } }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, + "outputs": [], + "source": [ + "[\n", + " ('half2', 1.0),\n", + " ('Bmin', 0.9014926374248455),\n", + " ('Bmedian', 0.5931779258652916),\n", + " ('Bmax', 0.5580664110760513),\n", + "\n", + " ('trend', 0.441328536097858),\n", + " ('max', 0.19391808653199277),\n", + " ('median', 0.16157357528452515),\n", + "\n", + " ('halfB2', 0.06672545822303622),\n", + " ('min', 0.042323799412967836),\n", + " ('B', 0.014457395044254808),\n", + " ('halfB1', 0.005159557201584083),\n", + " ('half1', 0.0023286124765232786),\n", + "]" + ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Algorithm.GRIDEX. Grid (1). Fixed (2). Threshold = 0.00. MAE = 0.00, 4 rules\n", - "Algorithm.GRIDEX. Grid (1). Fixed (2). Threshold = 0.00. MAE = 0.00, 8 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Fixed (3). Threshold = 0.00. MAE = 0.00, 17 rules\n", - "Algorithm.GRIDEX. Grid (1). Fixed (3). Threshold = 0.00. MAE = 0.00, 26 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 2)]). Threshold = 0.00. MAE = 0.00, 28 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 2)]). Threshold = 0.00. MAE = 0.00, 30 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 3)]). Threshold = 0.00. MAE = 0.00, 33 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 3)]). Threshold = 0.00. MAE = 0.00, 36 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 5)]). Threshold = 0.00. MAE = 0.00, 41 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 5)]). Threshold = 0.00. MAE = 0.00, 46 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 10)]). Threshold = 0.00. MAE = 0.00, 56 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 10)]). Threshold = 0.00. MAE = 0.00, 66 rules\n", - "\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.33, 2), (0.67, 3)]). Threshold = 0.00. MAE = 0.00, 72 rules\n", - "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.33, 2), (0.67, 3)]). Threshold = 0.00. MAE = 0.00, 78 rules\n", - "\n", - "**********************\n", - "Best Algorithm.GRIDEX\n", - "**********************\n", - "MAE = 0.00, 4 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Fixed (2)\n", - "\n", - "**********************\n", - "Best MAE \n", - "**********************\n", - "MAE = 0.00, 72 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Adaptive ([(0.33, 2), (0.67, 3)])\n", - "\n", - "**********************\n", - "Best N rules\n", - "**********************\n", - "MAE = 0.00, 4 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Fixed (2)\n", - "\n", - "GridEx performance (82 rules):\n", - "MAE = 0.00\n", - "MAE fidelity = 0.00\n", - "R2 = 0.99\n", - "R2 fidelity = 0.99\n", - "\n", - "GridEx extracted rules:\n", - "\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.49].\n", - "z(X, Y, 0.39) :-\n", - " X in [0.00, 0.50], Y in [0.49, 0.99].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.49].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.50, 0.99], Y in [0.49, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.49].\n", - "z(X, Y, 0.39) :-\n", - " X in [0.00, 0.50], Y in [0.49, 0.99].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.49].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.50, 0.99], Y in [0.49, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.33].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.00, 0.33], Y in [0.33, 0.66].\n", - "z(X, Y, 0.4) :-\n", - " X in [0.00, 0.33], Y in [0.66, 0.99].\n", - "z(X, Y, 0.48) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.33].\n", - "z(X, Y, 0.37) :-\n", - " X in [0.33, 0.66], Y in [0.33, 0.66].\n", - "z(X, Y, 0.17) :-\n", - " X in [0.33, 0.66], Y in [0.66, 0.99].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.33].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.66, 0.99], Y in [0.33, 0.66].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.66, 0.99], Y in [0.66, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.33].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.00, 0.33], Y in [0.33, 0.66].\n", - "z(X, Y, 0.4) :-\n", - " X in [0.00, 0.33], Y in [0.66, 0.99].\n", - "z(X, Y, 0.48) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.33].\n", - "z(X, Y, 0.37) :-\n", - " X in [0.33, 0.66], Y in [0.33, 0.66].\n", - "z(X, Y, 0.17) :-\n", - " X in [0.33, 0.66], Y in [0.66, 0.99].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.33].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.66, 0.99], Y in [0.33, 0.66].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.66, 0.99], Y in [0.66, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.99].\n", - "z(X, Y, 0.35) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.99].\n", - "z(X, Y, 0.35) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.56) :-\n", - " X in [0.00, 0.20], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.20, 0.40], Y in [0.00, 0.99].\n", - "z(X, Y, 0.37) :-\n", - " X in [0.40, 0.60], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.60, 0.80], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.80, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.56) :-\n", - " X in [0.00, 0.20], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.20, 0.40], Y in [0.00, 0.99].\n", - "z(X, Y, 0.37) :-\n", - " X in [0.40, 0.60], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.60, 0.80], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.80, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.56) :-\n", - " X in [0.00, 0.10], Y in [0.00, 0.99].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.10, 0.20], Y in [0.00, 0.99].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.20, 0.30], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.30, 0.40], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.40, 0.50], Y in [0.00, 0.99].\n", - "z(X, Y, 0.15) :-\n", - " X in [0.50, 0.60], Y in [0.00, 0.99].\n", - "z(X, Y, 0.15) :-\n", - " X in [0.60, 0.70], Y in [0.00, 0.99].\n", - "z(X, Y, 0.13) :-\n", - " X in [0.70, 0.80], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.80, 0.89], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.89, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.56) :-\n", - " X in [0.00, 0.10], Y in [0.00, 0.99].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.10, 0.20], Y in [0.00, 0.99].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.20, 0.30], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.30, 0.40], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.40, 0.50], Y in [0.00, 0.99].\n", - "z(X, Y, 0.15) :-\n", - " X in [0.50, 0.60], Y in [0.00, 0.99].\n", - "z(X, Y, 0.15) :-\n", - " X in [0.60, 0.70], Y in [0.00, 0.99].\n", - "z(X, Y, 0.13) :-\n", - " X in [0.70, 0.80], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.80, 0.89], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.89, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.49].\n", - "z(X, Y, 0.4) :-\n", - " X in [0.00, 0.33], Y in [0.49, 0.99].\n", - "z(X, Y, 0.52) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.49].\n", - "z(X, Y, 0.17) :-\n", - " X in [0.33, 0.66], Y in [0.49, 0.99].\n", - "z(X, Y, 0.29) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.49].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.66, 0.99], Y in [0.49, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.49].\n", - "z(X, Y, 0.4) :-\n", - " X in [0.00, 0.33], Y in [0.49, 0.99].\n", - "z(X, Y, 0.52) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.49].\n", - "z(X, Y, 0.17) :-\n", - " X in [0.33, 0.66], Y in [0.49, 0.99].\n", - "z(X, Y, 0.29) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.49].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.66, 0.99], Y in [0.49, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.49].\n", - "z(X, Y, 0.39) :-\n", - " X in [0.00, 0.50], Y in [0.49, 0.99].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.49].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.50, 0.99], Y in [0.49, 0.99].\n" - ] - } - ], - "source": [ - "pedro = PEDRO(predictor, train, max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1,\n", - " max_depth=1, patience=1, algorithm=PEDRO.Algorithm.GRIDEX, objective=Objective.MODEL,\n", - " normalization=normalization)\n", - "pedro.search()\n", - "(_, _, threshold, grid) = pedro.get_best()[0]\n", - "\n", - "gridEx = Extractor.gridex(predictor, grid, threshold=threshold, normalization=normalization)\n", - "theory_from_gridEx = gridEx.extract(train)\n", - "evaluate('GridEx', gridEx, true, predicted)\n", - "print('GridEx extracted rules:\\n\\n' + pretty_theory(theory_from_gridEx))" - ] + } }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "p = pd.read_csv('results/cartpredpruned.csv')\n", + "p = p[p.columns[2:]]\n", + "for c in p.columns[2:]:\n", + " p[c] = abs(p[c] - p.model)\n", + "p.describe().loc['mean']" + ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "**********************\n", - "Best Algorithm.GRIDEX\n", - "**********************\n", - "MAE = 0.00, 4 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Fixed (2)\n", - "\n", - "**********************\n", - "Best MAE \n", - "**********************\n", - "MAE = 0.00, 72 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Adaptive ([(0.33, 2), (0.67, 3)])\n", - "\n", - "**********************\n", - "Best N rules\n", - "**********************\n", - "MAE = 0.00, 4 rules\n", - "Threshold = 0.00\n", - "Iterations = 1\n", - "Strategy = Fixed (2)\n", - "\n", - "GridREx performance (86 rules):\n", - "MAE = 0.00\n", - "MAE fidelity = 0.00\n", - "R2 = 0.99\n", - "R2 fidelity = 0.99\n", - "\n", - "GridREx extracted rules:\n", - "\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.49].\n", - "z(X, Y, 0.39) :-\n", - " X in [0.00, 0.50], Y in [0.49, 0.99].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.49].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.50, 0.99], Y in [0.49, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.49].\n", - "z(X, Y, 0.39) :-\n", - " X in [0.00, 0.50], Y in [0.49, 0.99].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.49].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.50, 0.99], Y in [0.49, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.33].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.00, 0.33], Y in [0.33, 0.66].\n", - "z(X, Y, 0.4) :-\n", - " X in [0.00, 0.33], Y in [0.66, 0.99].\n", - "z(X, Y, 0.48) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.33].\n", - "z(X, Y, 0.37) :-\n", - " X in [0.33, 0.66], Y in [0.33, 0.66].\n", - "z(X, Y, 0.17) :-\n", - " X in [0.33, 0.66], Y in [0.66, 0.99].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.33].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.66, 0.99], Y in [0.33, 0.66].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.66, 0.99], Y in [0.66, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.33].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.00, 0.33], Y in [0.33, 0.66].\n", - "z(X, Y, 0.4) :-\n", - " X in [0.00, 0.33], Y in [0.66, 0.99].\n", - "z(X, Y, 0.48) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.33].\n", - "z(X, Y, 0.37) :-\n", - " X in [0.33, 0.66], Y in [0.33, 0.66].\n", - "z(X, Y, 0.17) :-\n", - " X in [0.33, 0.66], Y in [0.66, 0.99].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.33].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.66, 0.99], Y in [0.33, 0.66].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.66, 0.99], Y in [0.66, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.99].\n", - "z(X, Y, 0.35) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.99].\n", - "z(X, Y, 0.35) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.56) :-\n", - " X in [0.00, 0.20], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.20, 0.40], Y in [0.00, 0.99].\n", - "z(X, Y, 0.37) :-\n", - " X in [0.40, 0.60], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.60, 0.80], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.80, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.56) :-\n", - " X in [0.00, 0.20], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.20, 0.40], Y in [0.00, 0.99].\n", - "z(X, Y, 0.37) :-\n", - " X in [0.40, 0.60], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.60, 0.80], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.80, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.56) :-\n", - " X in [0.00, 0.10], Y in [0.00, 0.99].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.10, 0.20], Y in [0.00, 0.99].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.20, 0.30], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.30, 0.40], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.40, 0.50], Y in [0.00, 0.99].\n", - "z(X, Y, 0.15) :-\n", - " X in [0.50, 0.60], Y in [0.00, 0.99].\n", - "z(X, Y, 0.15) :-\n", - " X in [0.60, 0.70], Y in [0.00, 0.99].\n", - "z(X, Y, 0.13) :-\n", - " X in [0.70, 0.80], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.80, 0.89], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.89, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.56) :-\n", - " X in [0.00, 0.10], Y in [0.00, 0.99].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.10, 0.20], Y in [0.00, 0.99].\n", - "z(X, Y, 0.54) :-\n", - " X in [0.20, 0.30], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.30, 0.40], Y in [0.00, 0.99].\n", - "z(X, Y, 0.55) :-\n", - " X in [0.40, 0.50], Y in [0.00, 0.99].\n", - "z(X, Y, 0.15) :-\n", - " X in [0.50, 0.60], Y in [0.00, 0.99].\n", - "z(X, Y, 0.15) :-\n", - " X in [0.60, 0.70], Y in [0.00, 0.99].\n", - "z(X, Y, 0.13) :-\n", - " X in [0.70, 0.80], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.80, 0.89], Y in [0.00, 0.99].\n", - "z(X, Y, 0.14) :-\n", - " X in [0.89, 0.99], Y in [0.00, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.49].\n", - "z(X, Y, 0.4) :-\n", - " X in [0.00, 0.33], Y in [0.49, 0.99].\n", - "z(X, Y, 0.52) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.49].\n", - "z(X, Y, 0.17) :-\n", - " X in [0.33, 0.66], Y in [0.49, 0.99].\n", - "z(X, Y, 0.29) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.49].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.66, 0.99], Y in [0.49, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.33], Y in [0.00, 0.49].\n", - "z(X, Y, 0.4) :-\n", - " X in [0.00, 0.33], Y in [0.49, 0.99].\n", - "z(X, Y, 0.52) :-\n", - " X in [0.33, 0.66], Y in [0.00, 0.49].\n", - "z(X, Y, 0.17) :-\n", - " X in [0.33, 0.66], Y in [0.49, 0.99].\n", - "z(X, Y, 0.29) :-\n", - " X in [0.66, 0.99], Y in [0.00, 0.49].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.66, 0.99], Y in [0.49, 0.99].\n", - "z(X, Y, 0.7) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.49].\n", - "z(X, Y, 0.39) :-\n", - " X in [0.00, 0.50], Y in [0.49, 0.99].\n", - "z(X, Y, 0.3) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.49].\n", - "z(X, Y, 0.0) :-\n", - " X in [0.50, 0.99], Y in [0.49, 0.99].\n", - "z(X, Y, Z) :-\n", - " X in [0.00, 0.50], Y in [0.00, 0.49], Z is 0.7.\n", - "z(X, Y, Z) :-\n", - " X in [0.00, 0.50], Y in [0.49, 0.99], Z is 0.40 - 0.07 * X + 0.00 * Y.\n", - "z(X, Y, Z) :-\n", - " X in [0.50, 0.99], Y in [0.00, 0.49], Z is 0.3.\n", - "z(X, Y, Z) :-\n", - " X in [0.50, 0.99], Y in [0.49, 0.99], Z is 0.0.\n" - ] - } - ], - "source": [ - "#pedro = PEDRO(predictor, train, max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1,\n", - "# max_depth=2, patience=1, algorithm=PEDRO.Algorithm.GRIDREX, objective=Objective.MODEL)\n", - "#pedro.search()\n", - "(_, _, threshold, grid) = pedro.get_best()[0]\n", - "\n", - "gridREx = Extractor.gridrex(predictor, grid, threshold=threshold, normalization=normalization)\n", - "theory_from_gridREx = gridREx.extract(train)\n", - "evaluate('GridREx', gridREx, true, predicted)\n", - "print('GridREx extracted rules:\\n\\n' + pretty_theory(theory_from_gridREx))" - ] + } }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, + "outputs": [], + "source": [], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CART performance (4 rules):\n", - "MAE = 0.00\n", - "MAE fidelity = 0.00\n", - "R2 = 1.00\n", - "R2 fidelity = 1.00\n", - "\n", - "CART extracted rules:\n", - "\n", - "z(X, Y, 0.3) :-\n", - " X > 0.50, Y =< 0.49.\n", - "z(X, Y, 0.0) :-\n", - " X > 0.50, Y > 0.49.\n", - "z(X, Y, 0.7) :-\n", - " Y =< 0.50.\n", - "z(X, Y, 0.4).\n" - ] - } - ], - "source": [ - "cart = Extractor.cart(predictor, max_depth=4, max_leaves=4, simplify=True, normalization=normalization)\n", - "theory_from_cart = cart.extract(train)\n", - "evaluate('CART', cart, true, predicted)\n", - "print('CART extracted rules:\\n\\n' + pretty_theory(theory_from_cart))" - ] + } } ], "metadata": { diff --git a/demo/README.md b/demo/README.md deleted file mode 100644 index a67d14ac..00000000 --- a/demo/README.md +++ /dev/null @@ -1,40 +0,0 @@ -## About Notebooks files in this directory - -Notebook files (`.ipynb`) in this directory contain demos of PSyKE. - -These are NOT meant to be executed directly, but rather via some container started from the [PSyKE Image](https://hub.docker.com/r/pikalab/psyke) on DockerHub. - -To do so, please ensure -- [Docker](https://docs.docker.com/engine/install/) is installed on your system -- the Docker service is up and running - -and then follow these steps: - -1. Choose a target version of PSyKE, say `X.Y.Z` - - cf. [DockerHub image tags](https://hub.docker.com/r/pikalab/psyke/tags) - - cf. [PyPi releases history](https://pypi.org/project/psyke/#history) - - cf. [GitHub releases](https://github.com/psykei/psyke-python/releases) - -2. Pull the corresponding image: - ```bash - docker pull pikalab/psyke:X.Y.Z - ``` - -2. Run the image into a container: - ```bash - docker run --rm -it -p 8888:8888 --name psyke pikalab/psyke:X.Y.Z - ``` - -3. Some logs such as the following ones should eventually be printed - ``` - To access the notebook, open this file in a browser: - file:///root/.local/share/jupyter/runtime/nbserver-7-open.html - Or copy and paste one of these URLs: - http://66fa9b93bbe7:8888/?token= - or http://127.0.0.1:8888/?token= - ``` - -4. Open your browser and browse to `http://localhost:8888/?token=` - - use the token from the logs above, if requested by the Web page - -5. Enjoy PSyKE-powered notebook! diff --git a/demo/demo.py b/demo/demo.py deleted file mode 100644 index c4d2d124..00000000 --- a/demo/demo.py +++ /dev/null @@ -1,27 +0,0 @@ -from sklearn.datasets import load_iris -from sklearn.model_selection import train_test_split -from sklearn.neighbors import KNeighborsClassifier -import pandas as pd -from psyke import Extractor -from psyke.utils.dataframe import get_discrete_features_equal_frequency, get_discrete_dataset -from psyke.utils.logic import pretty_theory - -x, y = load_iris(return_X_y=True, as_frame=True) -x.columns = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth'] -iris_features = get_discrete_features_equal_frequency(x, bins=3, output=False) -x = get_discrete_dataset(x, iris_features) -y = pd.DataFrame(y).replace({"target": {0: 'setosa', 1: 'virginica', 2: 'versicolor'}}) -dataset = x.join(y) -dataset.columns = [*dataset.columns[:-1], 'iris'] -train, test = train_test_split(dataset, test_size=0.5, random_state=0) - -predictor = KNeighborsClassifier(n_neighbors=7) -predictor.fit(train.iloc[:, :-1], train.iloc[:, -1]) - -real = Extractor.real(predictor, iris_features) -theory_from_real = real.extract(train) -print('REAL extracted rules:\n' + pretty_theory(theory_from_real)) - -trepan = Extractor.trepan(predictor, iris_features) -theory_from_trepan = trepan.extract(train) -print('\nTrepan extracted rules:\n' + pretty_theory(theory_from_trepan)) diff --git a/psyke/__init__.py b/psyke/__init__.py index eb71036c..77bb12e8 100644 --- a/psyke/__init__.py +++ b/psyke/__init__.py @@ -56,14 +56,27 @@ def predict(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None) -> It :param mapping: for one-hot encoding. :return: a list of predictions. """ - ys = self._predict(dataframe) + return self.__convert(self._predict(dataframe), mapping) + + def _predict(self, dataframe: pd.DataFrame) -> Iterable: + raise NotImplementedError('predict') + + def __convert(self, ys: Iterable, mapping: dict[str: int] = None) -> Iterable: if mapping is not None: inverse_mapping = {v: k for k, v in mapping.items()} ys = [inverse_mapping[y] for y in ys] + if self.normalization is not None: + m, s = self.normalization[list(self.normalization.keys())[-1]] + ys = [prediction if prediction is None else prediction * s + m for prediction in ys] return ys - def _predict(self, dataframe: pd.DataFrame) -> Iterable: - raise NotImplementedError('predict') + def brute_predict(self, dataframe: pd.DataFrame, criterion: str = 'corner', n: int = 2, + mapping: dict[str: int] = None) -> Iterable: + return self.__convert(self._brute_predict(dataframe, criterion, n, mapping), mapping) + + def _brute_predict(self, dataframe: pd.DataFrame, criterion: str = 'corner', n: int = 2, + mapping: dict[str: int] = None) -> Iterable: + raise NotImplementedError('brute_predict') def unscale(self, values, name): if self.normalization is None or isinstance(values, LinearRegression): @@ -76,9 +89,13 @@ def unscale(self, values, name): return values def score(self, dataframe: pd.DataFrame, predictor=None, fidelity: bool = False, completeness: bool = True, + brute: bool = False, criterion: str = 'corners', n: int = 2, task: EvaluableModel.Task = Task.CLASSIFICATION, scoring_function: Iterable[EvaluableModel.Score] = [ClassificationScore.ACCURACY]): - extracted = np.array(self.predict(dataframe.iloc[:, :-1])) + extracted = np.array( + self.predict(dataframe.iloc[:, :-1]) if not brute else + self.brute_predict(dataframe.iloc[:, :-1], criterion, n) + ) idx = [prediction is not None for prediction in extracted] y_extracted = extracted[idx] true = [dataframe.iloc[idx, -1]] @@ -153,59 +170,81 @@ def extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort: """ raise NotImplementedError('extract') - def mae(self, dataframe: pd.DataFrame, predictor=None) -> float: + def mae(self, dataframe: pd.DataFrame, predictor=None, brute: bool = False, criterion: str = 'center', + n: int = 3) -> float: """ Calculates the predictions' MAE w.r.t. the instances given as input. :param dataframe: is the set of instances to be used to calculate the mean absolute error. :param predictor: if provided, its predictions on the dataframe are taken instead of the dataframe instances. + :param brute: if True, a brute prediction is executed. + :param criterion: creterion for brute prediction. + :param n: number of points for brute prediction with 'perimeter' criterion. :return: the mean absolute error (MAE) of the predictions. """ - return self.score(dataframe, predictor, predictor is not None, False, Extractor.Task.REGRESSION, - [Extractor.RegressionScore.MAE])[Extractor.RegressionScore.MAE][-1] + return self.score(dataframe, predictor, predictor is not None, False, brute, criterion, n, + Extractor.Task.REGRESSION, [Extractor.RegressionScore.MAE])[Extractor.RegressionScore.MAE][-1] - def mse(self, dataframe: pd.DataFrame, predictor=None) -> float: + def mse(self, dataframe: pd.DataFrame, predictor=None, brute: bool = False, criterion: str = 'center', + n: int = 3) -> float: """ Calculates the predictions' MSE w.r.t. the instances given as input. :param dataframe: is the set of instances to be used to calculate the mean squared error. :param predictor: if provided, its predictions on the dataframe are taken instead of the dataframe instances. + :param brute: if True, a brute prediction is executed. + :param criterion: creterion for brute prediction. + :param n: number of points for brute prediction with 'perimeter' criterion. :return: the mean squared error (MSE) of the predictions. """ - return self.score(dataframe, predictor, predictor is not None, False, Extractor.Task.REGRESSION, - [Extractor.RegressionScore.MSE])[Extractor.RegressionScore.MSE][-1] + return self.score(dataframe, predictor, predictor is not None, False, brute, criterion, n, + Extractor.Task.REGRESSION, [Extractor.RegressionScore.MSE])[Extractor.RegressionScore.MSE][-1] - def r2(self, dataframe: pd.DataFrame, predictor=None) -> float: + def r2(self, dataframe: pd.DataFrame, predictor=None, brute: bool = False, criterion: str = 'center', + n: int = 3) -> float: """ Calculates the predictions' R2 score w.r.t. the instances given as input. :param dataframe: is the set of instances to be used to calculate the R2 score. :param predictor: if provided, its predictions on the dataframe are taken instead of the dataframe instances. + :param brute: if True, a brute prediction is executed. + :param criterion: creterion for brute prediction. + :param n: number of points for brute prediction with 'perimeter' criterion. :return: the R2 score of the predictions. """ - return self.score(dataframe, predictor, predictor is not None, False, + return self.score(dataframe, predictor, predictor is not None, False, brute, criterion, n, Extractor.Task.REGRESSION, [Extractor.RegressionScore.R2])[Extractor.RegressionScore.R2][-1] - def accuracy(self, dataframe: pd.DataFrame, predictor=None) -> float: + def accuracy(self, dataframe: pd.DataFrame, predictor=None, brute: bool = False, criterion: str = 'center', + n: int = 3) -> float: """ Calculates the predictions' accuracy classification score w.r.t. the instances given as input. :param dataframe: is the set of instances to be used to calculate the accuracy classification score. :param predictor: if provided, its predictions on the dataframe are taken instead of the dataframe instances. + :param brute: if True, a brute prediction is executed. + :param criterion: creterion for brute prediction. + :param n: number of points for brute prediction with 'perimeter' criterion. :return: the accuracy classification score of the predictions. """ - return self.score(dataframe, predictor, predictor is not None, False, Extractor.Task.CLASSIFICATION, + return self.score(dataframe, predictor, predictor is not None, False, brute, criterion, n, + Extractor.Task.CLASSIFICATION, [Extractor.ClassificationScore.ACCURACY])[Extractor.ClassificationScore.ACCURACY][-1] - def f1(self, dataframe: pd.DataFrame, predictor=None) -> float: + def f1(self, dataframe: pd.DataFrame, predictor=None, brute: bool = False, criterion: str = 'center', + n: int = 3) -> float: """ Calculates the predictions' F1 score w.r.t. the instances given as input. :param dataframe: is the set of instances to be used to calculate the F1 score. :param predictor: if provided, its predictions on the dataframe are taken instead of the dataframe instances. + :param brute: if True, a brute prediction is executed. + :param criterion: creterion for brute prediction. + :param n: number of points for brute prediction with 'perimeter' criterion. :return: the F1 score of the predictions. """ - return self.score(dataframe, predictor, predictor is not None, False, Extractor.Task.CLASSIFICATION, + return self.score(dataframe, predictor, predictor is not None, False, brute, criterion, n, + Extractor.Task.CLASSIFICATION, [Extractor.ClassificationScore.F1])[Extractor.ClassificationScore.F1][-1] @staticmethod @@ -218,6 +257,27 @@ def cart(predictor, max_depth: int = 3, max_leaves: int = 3, return Cart(predictor, max_depth, max_leaves, discretization=discretization, normalization=normalization, simplify=simplify) + @staticmethod + def divine(predictor, k: int = 5, patience: int = 15, close_to_center: bool = True, + discretization: Iterable[DiscreteFeature] = None, normalization=None) -> Extractor: + """ + Creates a new DiViNE extractor. + """ + from psyke.extraction.hypercubic.divine import DiViNE + return DiViNE(predictor, k=k, patience=patience, close_to_center=close_to_center, + discretization=discretization, normalization=normalization) + + @staticmethod + def cosmik(predictor, max_components: int = 4, k: int = 5, patience: int = 15, close_to_center: bool = True, + output: Target = Target.CONSTANT, + discretization: Iterable[DiscreteFeature] = None, normalization=None) -> Extractor: + """ + Creates a new COSMiK extractor. + """ + from psyke.extraction.hypercubic.cosmik import COSMiK + return COSMiK(predictor, max_components=max_components, k=k, patience=patience, close_to_center=close_to_center, + output=output, discretization=discretization, normalization=normalization) + @staticmethod def iter(predictor, min_update: float = 0.1, n_points: int = 1, max_iterations: int = 600, min_examples: int = 250, threshold: float = 0.1, fill_gaps: bool = True, normalization: dict[str, tuple[float, float]] = None, @@ -250,15 +310,15 @@ def gridrex(predictor, grid, min_examples: int = 250, threshold: float = 0.1, return GridREx(predictor, grid, min_examples, threshold, normalization, seed) @staticmethod - def creepy(predictor, clustering, depth: int, error_threshold: float, output, gauss_components: int = 2, - ranks: [(str, float)] = [], ignore_threshold: float = 0.0, - normalization: dict[str, tuple[float, float]] = None) -> Extractor: + def creepy(predictor, clustering, depth: int, error_threshold: float, output: Target = Target.CONSTANT, + gauss_components: int = 2, ranks: [(str, float)] = [], ignore_threshold: float = 0.0, + discretization=None, normalization: dict[str, tuple[float, float]] = None) -> Extractor: """ Creates a new CReEPy extractor. """ from psyke.extraction.hypercubic.creepy import CReEPy return CReEPy(predictor, depth, error_threshold, output, gauss_components, ranks, ignore_threshold, - normalization, clustering) + discretization, normalization, clustering) @staticmethod def real(predictor, discretization=None) -> Extractor: @@ -314,6 +374,7 @@ def __init__(self, predictor, discretization=None, normalization=None): Extractor.__init__(self, predictor=predictor, discretization=discretization, normalization=normalization) def extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort: bool = True) -> Theory: + from psyke.extraction.hypercubic import HyperCubeExtractor, HyperCube new_y = self.predictor.predict(dataframe.iloc[:, :-1]) if mapping is not None: if hasattr(new_y[0], 'shape'): @@ -326,7 +387,11 @@ def extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort: new_y = pd.DataFrame(new_y).set_index(dataframe.index) data = dataframe.iloc[:, :-1].copy().join(new_y) data.columns = dataframe.columns - return self._extract(data, mapping, sort) + theory = self._extract(data, mapping, sort) + if isinstance(self, HyperCubeExtractor): + self._surrounding = HyperCube.create_surrounding_cube(dataframe, output=self._output) + self._surrounding.update(dataframe, self.predictor) + return theory def _extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort: bool = True) -> Theory: raise NotImplementedError('extract') diff --git a/psyke/extraction/cart/__init__.py b/psyke/extraction/cart/__init__.py index c2ceabff..444045ed 100644 --- a/psyke/extraction/cart/__init__.py +++ b/psyke/extraction/cart/__init__.py @@ -77,8 +77,8 @@ def _extract(self, data: pd.DataFrame, mapping: dict[str: int] = None, sort: boo self._cart_predictor.predictor.fit(data.iloc[:, :-1], data.iloc[:, -1]) return self._create_theory(data, mapping, sort) - def _predict(self, data) -> Iterable: - return self._cart_predictor.predict(data) + def _predict(self, dataframe: pd.DataFrame) -> Iterable: + return self._cart_predictor.predict(dataframe) @property def n_rules(self) -> int: diff --git a/psyke/extraction/hypercubic/__init__.py b/psyke/extraction/hypercubic/__init__.py index 7d7783a5..7a5ee046 100644 --- a/psyke/extraction/hypercubic/__init__.py +++ b/psyke/extraction/hypercubic/__init__.py @@ -9,26 +9,78 @@ from sklearn.linear_model import LinearRegression from tuprolog.core import Var, Struct, clause from tuprolog.theory import Theory, mutable_theory -from psyke import logger, PedagogicalExtractor -from psyke.extraction.hypercubic.hypercube import HyperCube, RegressionCube, ClassificationCube, ClosedCube +from psyke import logger, PedagogicalExtractor, EvaluableModel +from psyke.extraction.hypercubic.hypercube import HyperCube, RegressionCube, ClassificationCube, ClosedCube, Point, \ + GenericCube from psyke.utils.logic import create_variable_list, create_head, to_var, Simplifier from psyke.utils import Target, get_int_precision from psyke.extraction.hypercubic.strategy import Strategy, FixedStrategy +from sklearn.neighbors import BallTree -class HyperCubePredictor: - def __init__(self, cubes=[], output=Target.CONSTANT, normalization=None): - self._hypercubes = cubes +class HyperCubePredictor(EvaluableModel): + def __init__(self, output=Target.CONSTANT, normalization=None): + super().__init__(normalization) + self._hypercubes = [] self._output = output - self.normalization = normalization def _predict(self, dataframe: pd.DataFrame) -> Iterable: - return np.array([self._predict_from_cubes(dict(row.to_dict())) for _, row in dataframe.iterrows()]) + return np.array([self._predict_from_cubes(row.to_dict()) for _, row in dataframe.iterrows()]) + + def _brute_predict(self, dataframe: pd.DataFrame, criterion: str = 'corner', n: int = 2, + mapping: dict[str: int] = None) -> Iterable: + predictions = self._predict(dataframe) + idx = [prediction is None for prediction in predictions] + if sum(idx) > 0: + if criterion == 'default': + if not isinstance(self, HyperCubeExtractor): + raise ValueError("'default' criterion only available for instances of HyperCubeExtractor") + predictions[idx] = np.array([HyperCubePredictor._get_cube_output( + self._surrounding, row + ) for _, row in dataframe[idx].iterrows()]) + elif criterion == 'surface': + if not isinstance(self, HyperCubeExtractor): + raise ValueError("'surface' criterion only available for instances of HyperCubeExtractor") + predictions[idx] = np.array([HyperCubePredictor._get_cube_output(self._brute_predict_surface(row), row) + for _, row in dataframe[idx].iterrows()]) + else: + tree, cubes = self._create_brute_tree(criterion, n) + predictions[idx] = np.array([HyperCubePredictor._brute_predict_from_cubes( + row.to_dict(), tree, cubes + ) for _, row in dataframe[idx].iterrows()]) + return np.array(predictions) - def _predict_from_cubes(self, data: dict[str, float]) -> float | None: - data = {k: v for k, v in data.items()} + @staticmethod + def _brute_predict_from_cubes(row: dict[str, float], tree: BallTree, + cubes: list[GenericCube]) -> float | str: + idx = tree.query([list(row.values())], k=1)[1][0][0] + return HyperCubePredictor._get_cube_output(cubes[idx], row) + + def _brute_predict_surface(self, row: dict[str, float]) -> GenericCube: + distances = [( + cube.surface_distance(Point(list(row.keys()), list(row.values))), cube.volume(), cube + ) for cube in self._hypercubes] + return min(distances)[-1] + + def _create_brute_tree(self, criterion: str = 'center', n: int = 2) -> (BallTree, list[GenericCube]): + admissible_criteria = ['surface', 'center', 'corner', 'perimeter', 'density', 'default'] + if criterion not in admissible_criteria: + raise NotImplementedError( + "'criterion' should be chosen in " + str(admissible_criteria) + ) + + points = [(cube.center, cube) for cube in self._hypercubes] if criterion == 'center' else \ + [(cube.barycenter, cube) for cube in self._hypercubes] if criterion == 'density' else \ + [(corner, cube) for cube in self._hypercubes for corner in cube.corners()] if criterion == 'corner' else \ + [(point, cube) for cube in self._hypercubes for point in cube.perimeter_samples(n)] \ + if criterion == 'perimeter' else None + + return BallTree(pd.concat([point[0].to_dataframe() for point in points], ignore_index=True)), \ + [point[1] for point in points] + + def _predict_from_cubes(self, data: dict[str, float]) -> float | str | None: for cube in self._hypercubes: - if cube.__contains__(data): + if data in cube: if self._output == Target.CLASSIFICATION: return HyperCubePredictor._get_cube_output(cube, data) else: @@ -50,9 +102,10 @@ def _get_cube_output(cube, data: dict[str, float]) -> float: class HyperCubeExtractor(HyperCubePredictor, PedagogicalExtractor, ABC): - def __init__(self, predictor, output, normalization): - PedagogicalExtractor.__init__(self, predictor, normalization=normalization) + def __init__(self, predictor, output, discretization=None, normalization=None): HyperCubePredictor.__init__(self, output=output, normalization=normalization) + PedagogicalExtractor.__init__(self, predictor, discretization=discretization, normalization=normalization) + self._surrounding = None def _default_cube(self) -> HyperCube | RegressionCube | ClassificationCube: if self._output == Target.CONSTANT: @@ -61,6 +114,11 @@ def _default_cube(self) -> HyperCube | RegressionCube | ClassificationCube: return RegressionCube() return ClassificationCube() + def _sort_cubes(self): + cubes = [(cube.diversity, i, cube) for i, cube in enumerate(self._hypercubes)] + cubes.sort() + self._hypercubes = [cube[2] for cube in cubes] + @staticmethod def _create_head(dataframe: pd.DataFrame, variables: list[Var], output: float | LinearRegression) -> Struct: return create_head(dataframe.columns[-1], variables[:-1], output) \ @@ -70,7 +128,11 @@ def _create_head(dataframe: pd.DataFrame, variables: list[Var], output: float | def _ignore_dimensions(self) -> Iterable[str]: return [] - def _create_theory(self, dataframe: pd.DataFrame, sort: bool = True) -> Theory: + def __drop(self, dataframe: pd.DataFrame): + self._hypercubes = [cube for cube in self._hypercubes if cube.count(dataframe) > 1] + + def _create_theory(self, dataframe: pd.DataFrame, sort: bool = False) -> Theory: + self.__drop(dataframe) new_theory = mutable_theory() for cube in self._hypercubes: logger.info(cube.output) diff --git a/psyke/extraction/hypercubic/cosmik/__init__.py b/psyke/extraction/hypercubic/cosmik/__init__.py new file mode 100644 index 00000000..c7be3a89 --- /dev/null +++ b/psyke/extraction/hypercubic/cosmik/__init__.py @@ -0,0 +1,43 @@ +import pandas as pd +from sklearn.mixture import GaussianMixture +from tuprolog.theory import Theory + +from psyke import Target, Extractor +from psyke.clustering.utils import select_gaussian_mixture +from psyke.extraction.hypercubic import HyperCube, HyperCubeExtractor, RegressionCube + + +class COSMiK(HyperCubeExtractor): + """ + Explanator implementing COSMiK algorithm. + """ + + def __init__(self, predictor, max_components: int = 4, k: int = 5, patience: int = 15, close_to_center: bool = True, + output: Target = Target.CONSTANT, discretization=None, normalization=None): + super().__init__(predictor, Target.REGRESSION, discretization, normalization) + self.max = max_components + self.k = k + self.patience = patience + self.output = output + self.close_to_center = close_to_center + + def _extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort: bool = True) -> Theory: + X, y = dataframe.iloc[:, :-1], dataframe.iloc[:, -1] + + _, n, _ = select_gaussian_mixture(dataframe, self.max) + gmm = GaussianMixture(n) + gmm.fit(X, y) + + divine = Extractor.divine(gmm, self.k, self.patience, self.close_to_center, + self.discretization, self.normalization) + df = X.join(pd.DataFrame(gmm.predict(X))) + df.columns = dataframe.columns + divine.extract(df) + + self._hypercubes = [HyperCube(cube.dimensions.copy()) if self.output == Target.CONSTANT else + RegressionCube(cube.dimensions.copy()) for cube in divine._hypercubes] + for cube in self._hypercubes: + cube.update(dataframe, self.predictor) + + self._sort_cubes() + return self._create_theory(dataframe, sort) \ No newline at end of file diff --git a/psyke/extraction/hypercubic/creepy/__init__.py b/psyke/extraction/hypercubic/creepy/__init__.py index 8bdba96f..1d72f759 100644 --- a/psyke/extraction/hypercubic/creepy/__init__.py +++ b/psyke/extraction/hypercubic/creepy/__init__.py @@ -11,18 +11,19 @@ from psyke.clustering import HyperCubeClustering from psyke.extraction.hypercubic import HyperCubeExtractor from psyke.utils import Target +from psyke.utils.logic import last_in_body -class CReEPy(HyperCubeExtractor, ABC): +class CReEPy(HyperCubeExtractor): """ Explanator implementing CReEPy algorithm. """ def __init__(self, predictor, depth: int, error_threshold: float, output: Target = Target.CONSTANT, gauss_components: int = 5, ranks: list[(str, float)] = [], ignore_threshold: float = 0.0, - normalization=None, clustering=Clustering.exact): + discretization=None, normalization=None, clustering=Clustering.exact): super().__init__(predictor, Target.CLASSIFICATION if isinstance(predictor, ClassifierMixin) else output, - normalization) + discretization, normalization) self.clustering = clustering(depth, error_threshold, self._output, gauss_components) self.ranks = ranks self.ignore_threshold = ignore_threshold @@ -40,7 +41,7 @@ def _extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort last_clause = list(theory.clauses)[-1] theory.retract(last_clause) theory.assertZ(clause( - last_clause.head, [list(last_clause.body)[-1]] if self._output is Target.REGRESSION else [])) + last_clause.head, [last_in_body(last_clause.body)] if self._output is Target.REGRESSION else [])) last_cube = self._hypercubes[-1] for dimension in last_cube.dimensions.keys(): last_cube[dimension] = [-np.inf, np.inf] diff --git a/psyke/extraction/hypercubic/divine/__init__.py b/psyke/extraction/hypercubic/divine/__init__.py new file mode 100644 index 00000000..08c80e74 --- /dev/null +++ b/psyke/extraction/hypercubic/divine/__init__.py @@ -0,0 +1,83 @@ +import numpy as np +import pandas as pd +from tuprolog.theory import Theory + +from psyke import Target +from psyke.extraction.hypercubic import HyperCubeExtractor +from psyke.extraction.hypercubic.hypercube import Point, GenericCube, HyperCube + +from sklearn.neighbors import BallTree + + +class DiViNE(HyperCubeExtractor): + """ + Explanator implementing DiViNE algorithm. + """ + + def __init__(self, predictor, k: int = 5, patience: int = 15, close_to_center: bool = True, + discretization=None, normalization=None): + super().__init__(predictor, Target.CLASSIFICATION, discretization, normalization) + self.k = k + self.patience = patience + self.vicinity_function = DiViNE.closest_to_center if close_to_center else DiViNE.closest_to_corners + + @staticmethod + def __pop(data: pd.DataFrame, idx: int = None) -> (Point, pd.DataFrame): + if idx is None: + idx = data.sample(1).index.values[0] + t = data.T + return DiViNE.__to_point(t.pop(idx)), t.T.reset_index(drop=True) + + @staticmethod + def __to_point(instance) -> Point: + point = Point(instance.index.values, instance.values) + return point + + def __to_cube(self, point: Point) -> GenericCube: + cube = HyperCube.cube_from_point(point.dimensions, self._output) + cube._output = list(point.dimensions.values())[-1] + return cube + + def __clean(self, data: pd.DataFrame) -> pd.DataFrame: + _, idx = BallTree(data.iloc[:, :-1]).query(data.iloc[:, :-1], k=self.k) + # how many output classes are associated with the k neighbors + count = np.array(list(map(lambda indices: len(data.iloc[indices].iloc[:, -1].unique()), idx))) + # instances with neighbors of different classes are discarded + return data[count == 1] + + def __closest(self, data: pd.DataFrame, cube: GenericCube) -> (Point, pd.DataFrame): + return DiViNE.__pop(data, self.vicinity_function(BallTree(data.iloc[:, :-1]), cube)) + + @staticmethod + def closest_to_center(tree: BallTree, cube: GenericCube): + return tree.query([list(cube.center.dimensions.values())], k=1)[1][0][-1] + + @staticmethod + def closest_to_corners(tree: BallTree, cube: GenericCube): + distance, idx = tree.query([list(point.dimensions.values()) for point in cube.corners()], k=1) + return idx[np.argmin(distance)][-1] + + def _extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort: bool = True) -> Theory: + data = self.__clean(dataframe) + + while len(data) > 0: + discarded = [] + patience = self.patience + point, data = self.__pop(data) + cube = self.__to_cube(point) + + while patience > 0 and len(data) > 0: + other, data = self.__closest(data, cube) + if cube.output == list(other.dimensions.values())[-1]: + cube = cube.merge_with_point(other) + data = data[~(cube.filter_indices(data.iloc[:, :-1]))].reset_index(drop=True) + else: + patience -= 1 + discarded.append(other) + if cube.volume() > 0: + cube.update(dataframe, self.predictor) + self._hypercubes.append(cube) + if len(discarded) > 0: + data = pd.concat([data] + [d.to_dataframe() for d in discarded]).reset_index(drop=True) + self._sort_cubes() + return self._create_theory(dataframe, sort) diff --git a/psyke/extraction/hypercubic/gridex/__init__.py b/psyke/extraction/hypercubic/gridex/__init__.py index 09272ee0..664554b6 100644 --- a/psyke/extraction/hypercubic/gridex/__init__.py +++ b/psyke/extraction/hypercubic/gridex/__init__.py @@ -17,7 +17,7 @@ class GridEx(HyperCubeExtractor): def __init__(self, predictor, grid: Grid, min_examples: int, threshold: float, normalization=None, seed=get_default_random_seed()): - super().__init__(predictor, Target.CONSTANT, normalization) + super().__init__(predictor, Target.CONSTANT, normalization=normalization) self.grid = grid self.min_examples = min_examples self.threshold = threshold diff --git a/psyke/extraction/hypercubic/hypercube.py b/psyke/extraction/hypercubic/hypercube.py index 7c8d2d2b..342d1da7 100644 --- a/psyke/extraction/hypercubic/hypercube.py +++ b/psyke/extraction/hypercubic/hypercube.py @@ -30,25 +30,31 @@ class Point: EPSILON = get_default_precision() - def __init__(self, dimensions: list[str], values: list[float]): + def __init__(self, dimensions: list[str], values: list[float | str]): self._dimensions = {dimension: value for (dimension, value) in zip(dimensions, values)} - def __getitem__(self, feature: str) -> float: + def __getitem__(self, feature: str) -> float | str: if feature in self._dimensions.keys(): return self._dimensions[feature] else: raise FeatureNotFoundException(feature) - def __setitem__(self, key: str, value: float) -> None: + def __setitem__(self, key: str, value: float | str) -> None: self._dimensions[key] = value def __eq__(self, other: Point) -> bool: return all([abs(self[dimension] - other[dimension]) < Point.EPSILON for dimension in self._dimensions]) @property - def dimensions(self) -> dict[str, float]: + def dimensions(self) -> dict[str, float | str]: return self._dimensions + def to_dataframe(self) -> pd.DataFrame: + return pd.DataFrame(data=[self.dimensions.values()], columns=list(self.dimensions.keys())) + + def copy(self) -> Point: + return Point(list(self._dimensions.keys()), list(self._dimensions.values())) + class HyperCube: """ @@ -59,11 +65,12 @@ class HyperCube: INT_PRECISION = get_int_precision() def __init__(self, dimension: dict[str, tuple[float, float]] = None, limits: set[Limit] = None, - output: float | LinearRegression = 0.0): + output: float | LinearRegression | str = 0.0): self._dimensions = self._fit_dimension(dimension) if dimension is not None else {} self._limits = limits if limits is not None else set() self._output = output self._diversity = 0.0 + self._barycenter = Point([], []) def __contains__(self, point: dict[str, float]) -> bool: """ @@ -101,13 +108,17 @@ def limit_count(self) -> int: return len(self._limits) @property - def output(self) -> float | LinearRegression: + def output(self) -> float | str | LinearRegression: return self._output @property def diversity(self) -> float: return self._diversity + @property + def barycenter(self) -> Point: + return self._barycenter + def _fit_dimension(self, dimension: dict[str, tuple[float, float]]) -> dict[str, tuple[float, float]]: new_dimension: dict[str, tuple[float, float]] = {} for key, value in dimension.items(): @@ -125,12 +136,11 @@ def filter_indices(self, dataset: pd.DataFrame) -> ndarray: ds = dataset.to_numpy(copy=True) return np.all((v[:, 0] <= ds) & (ds < v[:, 1]), axis=1) - def _filter_dataframe(self, dataset: pd.DataFrame) -> pd.DataFrame: + def filter_dataframe(self, dataset: pd.DataFrame) -> pd.DataFrame: return dataset[self.filter_indices(dataset)] - def _zip_dimensions(self, hypercube: HyperCube) -> list[ZippedDimension]: - return [ZippedDimension(dimension, self[dimension], hypercube[dimension]) - for dimension in self._dimensions.keys()] + def _zip_dimensions(self, other: HyperCube) -> list[ZippedDimension]: + return [ZippedDimension(dimension, self[dimension], other[dimension]) for dimension in self._dimensions.keys()] def add_limit(self, limit_or_feature: Limit | str, direction: str = None) -> None: if isinstance(limit_or_feature, Limit): @@ -167,7 +177,7 @@ def copy(self) -> HyperCube: return HyperCube(self.dimensions.copy(), self._limits.copy(), self.output) def count(self, dataset: pd.DataFrame) -> int: - return self._filter_dataframe(dataset.iloc[:, :-1]).shape[0] + return self.filter_dataframe(dataset.iloc[:, :-1]).shape[0] def body(self, variables: dict[str, Var], ignore: list[str], unscale=None, normalization=None) -> Iterable[Struct]: dimensions = dict(self.dimensions) @@ -202,7 +212,7 @@ def _create_tuple(self, generator: Random) -> dict: return {k: generator.uniform(self.get_first(k), self.get_second(k)) for k in self._dimensions.keys()} @staticmethod - def cube_from_point(point: dict, output=None) -> GenericCube: + def cube_from_point(point: dict[str, float], output=None) -> GenericCube: if output is Target.CLASSIFICATION: return ClassificationCube({k: (v, v) for k, v in list(point.items())[:-1]}) if output is Target.REGRESSION: @@ -249,6 +259,7 @@ def diagonal(self) -> float: lambda a, b: a + b, [(dimension[1] - dimension[0]) ** 2 for dimension in self._dimensions.values()], 0 ) ** 0.5 + @property def center(self) -> Point: return Point(list(self._dimensions.keys()), [(interval[0] + interval[1]) / 2 for interval in self._dimensions.values()]) @@ -258,6 +269,50 @@ def corners(self) -> Iterable[Point]: Point(list(self._dimensions.keys()), values) for values in itertools.product(*self._dimensions.values()) ] + def surface_distance(self, point: Point) -> float: + s = 0 + for d in self.dimensions.keys(): + lower, upper = self[d] + p = point[d] + if p > upper: + s += (p - upper)**2 + elif p < lower: + s += (lower - p)**2 + return s**0.5 + + def perimeter_samples(self, n: int = 5) -> Iterable[Point]: + def duplicate(point: Point, feature: str) -> Iterable[Point]: + new_point_a = point.copy() + new_point_b = point.copy() + new_point_a[feature] = self.get_first(feature) + new_point_b[feature] = self.get_second(feature) + return [new_point_a, new_point_b] + + def remove_duplicates(points: Iterable[Point]) -> Iterable[Point]: + new_points = [] + for point in points: + if point not in new_points: + new_points.append(point) + return new_points + + def split(point: Point, feature: str, n: int): + points = [] + a, b = self.get_first(feature), self.get_second(feature) + for value in np.linspace(a, b, n) if n > 1 else [(a + b) / 2]: + new_point = point.copy() + new_point[feature] = value + points.append(new_point) + return points + + points = [] + for primary in self._dimensions: + new_points = [Point([], [])] + for secondary in self._dimensions: + new_points = np.array([duplicate(point, secondary) if primary != secondary else + split(point, primary, n) for point in new_points]).flatten() + points = points + list(new_points) + return remove_duplicates(points) + def is_adjacent(self, cube: HyperCube) -> str | None: adjacent = None for (feature, [a1, b1]) in self._dimensions.items(): @@ -276,6 +331,15 @@ def merge_along_dimension(self, cube: HyperCube, feature: str) -> HyperCube: new_cube.update_dimension(feature, (min(a1, a2), max(b1, b2))) return new_cube + def merge(self, other: HyperCube) -> HyperCube: + new_cube = self.copy() + for dimension in self.dimensions.keys(): + new_cube = new_cube.merge_along_dimension(other, dimension) + return new_cube + + def merge_with_point(self, other: Point) -> HyperCube: + return self.merge(HyperCube.cube_from_point(other.dimensions)) + # TODO: maybe two different methods are more readable and easier to debug def overlap(self, hypercubes: Iterable[HyperCube] | HyperCube) -> HyperCube | bool | None: if isinstance(hypercubes, Iterable): @@ -298,10 +362,12 @@ def update_dimension(self, feature: str, lower: float | tuple[float, float], upp self.update_dimension(feature, (lower, upper)) def update(self, dataset: pd.DataFrame, predictor) -> None: - filtered = self._filter_dataframe(dataset.iloc[:, :-1]) + filtered = self.filter_dataframe(dataset.iloc[:, :-1]) predictions = predictor.predict(filtered) self._output = np.mean(predictions) self._diversity = np.std(predictions) + means = filtered.describe().loc['mean'] + self._barycenter = Point(means.index.values, means.values) # TODO: why this is not a property? def init_diversity(self, std: float) -> None: @@ -313,40 +379,45 @@ def __init__(self, dimension: dict[str, tuple] = None): super().__init__(dimension=dimension, output=LinearRegression()) def update(self, dataset: pd.DataFrame, predictor) -> None: - filtered = self._filter_dataframe(dataset.iloc[:, :-1]) + filtered = self.filter_dataframe(dataset.iloc[:, :-1]) if len(filtered > 0): predictions = predictor.predict(filtered) self._output.fit(filtered, predictions) self._diversity = (abs(self._output.predict(filtered) - predictions)).mean() + means = filtered.describe().loc['mean'] + self._barycenter = Point(means.index.values, means.values) def copy(self) -> RegressionCube: return RegressionCube(self.dimensions.copy()) def body(self, variables: dict[str, Var], ignore: list[str], unscale=None, normalization=None) -> Iterable[Struct]: - intercept = self.output.intercept_ if normalization is None else \ - unscale(sum([-self.output.coef_[i] * normalization[name][0] / normalization[name][1] for i, name in - enumerate(self.dimensions.keys())], self.output.intercept_), list(normalization.keys())[-1]) - coefs = self.output.coef_ if normalization is None else \ - [self.output.coef_[i] / normalization[name][1] for i, name in enumerate(self.dimensions.keys())] + intercept = self.output.intercept_ if normalization is None else unscale(sum( + [-self.output.coef_[i] * normalization[name][0] / normalization[name][1] for i, name in + enumerate(self.dimensions.keys())], self.output.intercept_), list(normalization.keys())[-1]) + coefs = self.output.coef_ if normalization is None else [ + self.output.coef_[i] / normalization[name][1] * normalization[list(normalization.keys())[-1]][1] for + i, name in enumerate(self.dimensions.keys()) + ] return list(super().body(variables, ignore, unscale, normalization)) + [linear_function_creator( - list(variables.values()), [to_rounded_real(v) for v in coefs], - to_rounded_real(intercept) + list(variables.values()), [to_rounded_real(v) for v in coefs], to_rounded_real(intercept) )] class ClassificationCube(HyperCube): - def __init__(self, dimension: dict[str, tuple] = None): - super().__init__(dimension=dimension) + def __init__(self, dimension: dict[str, tuple] = None, limits: set[Limit] = None, output: str = ""): + super().__init__(dimension=dimension, limits=limits, output=output) def update(self, dataset: pd.DataFrame, predictor) -> None: - filtered = self._filter_dataframe(dataset.iloc[:, :-1]) + filtered = self.filter_dataframe(dataset.iloc[:, :-1]) if len(filtered > 0): predictions = predictor.predict(filtered) self._output = mode(predictions) self._diversity = 1 - sum(prediction == self.output for prediction in predictions) / len(filtered) + means = filtered.describe().loc['mean'] + self._barycenter = Point(means.index.values, means.values) def copy(self) -> ClassificationCube: - return ClassificationCube(self.dimensions.copy()) + return ClassificationCube(self.dimensions.copy(), self._limits.copy(), self._output) class ClosedCube(HyperCube): diff --git a/psyke/extraction/hypercubic/iter/__init__.py b/psyke/extraction/hypercubic/iter/__init__.py index 7f2ca76d..1e6d8237 100644 --- a/psyke/extraction/hypercubic/iter/__init__.py +++ b/psyke/extraction/hypercubic/iter/__init__.py @@ -5,7 +5,6 @@ import pandas as pd from sklearn.base import ClassifierMixin from tuprolog.theory import Theory -from psyke import PedagogicalExtractor from psyke.extraction.hypercubic import HyperCube, HyperCubeExtractor from psyke.extraction.hypercubic.hypercube import GenericCube from psyke.extraction.hypercubic.utils import MinUpdate, Expansion diff --git a/psyke/tuning/orchid/__init__.py b/psyke/tuning/orchid/__init__.py index d1dfe6c8..cf76eefa 100644 --- a/psyke/tuning/orchid/__init__.py +++ b/psyke/tuning/orchid/__init__.py @@ -57,7 +57,8 @@ def __search_threshold(self, depth): (EvaluableModel.Task.CLASSIFICATION, EvaluableModel.ClassificationScore.INVERSE_ACCURACY) \ if self.output == Target.CLASSIFICATION else \ (EvaluableModel.Task.REGRESSION, EvaluableModel.RegressionScore.MAE) - p, n = clustering.score(self.dataframe, None, False, False, task, [metric])[metric][0], clustering.n_rules + p, n = clustering.score(self.dataframe, None, False, False, task=task, + scoring_function=[metric])[metric][0], clustering.n_rules print(f"Predictive loss = {p:.2f}, {n} rules") diff --git a/psyke/tuning/pedro/__init__.py b/psyke/tuning/pedro/__init__.py index feb57e5e..9e6aae3b 100644 --- a/psyke/tuning/pedro/__init__.py +++ b/psyke/tuning/pedro/__init__.py @@ -4,10 +4,10 @@ from psyke import Extractor from psyke.extraction.hypercubic import Grid, FeatureRanker from psyke.extraction.hypercubic.strategy import AdaptiveStrategy, FixedStrategy -from psyke.tuning import Objective, Optimizer +from psyke.tuning import Objective, GridOptimizer -class PEDRO(Optimizer): +class PEDRO(GridOptimizer): class Algorithm(Enum): GRIDEX = 1, GRIDREX = 2 @@ -71,7 +71,7 @@ def __search_depth(self, strategy, critical, max_partitions): for iterations in range(self.max_depth): grid = Grid(iterations + 1, strategy) p = self.__search_threshold(grid, critical, max_partitions) - b = Optimizer._best(p)[1] + b = GridOptimizer._best(p)[1] print() improvement = self._depth_improvement( [best[0], best[1]], [b[0], b[1]] diff --git a/psyke/utils/logic.py b/psyke/utils/logic.py index d606252d..e56da90a 100644 --- a/psyke/utils/logic.py +++ b/psyke/utils/logic.py @@ -134,6 +134,10 @@ def create_variable_list(features: list[DiscreteFeature], dataset: pd.DataFrame return values +def last_in_body(body: Struct) -> Struct: + return body.args[-1] if body.args[-1].functor == 'is' else last_in_body(body.args[-1]) + + def create_head(functor: str, variables: Iterable[Var], output) -> Struct: if isinstance(output, Var): variables += [output] diff --git a/psyke/utils/plot.py b/psyke/utils/plot.py index 2bcbca82..3d69f60f 100644 --- a/psyke/utils/plot.py +++ b/psyke/utils/plot.py @@ -7,10 +7,81 @@ from matplotlib.lines import Line2D from tuprolog.solve.prolog import prolog_solver from tuprolog.theory import Theory, mutable_theory -from psyke.utils.logic import data_to_struct, pretty_theory, get_in_rule, get_not_in_rule + +from psyke.extraction.hypercubic import HyperCubeExtractor +from psyke.utils.logic import data_to_struct, get_in_rule, get_not_in_rule import matplotlib -matplotlib.use('TkAgg') +#matplotlib.use('TkAgg') + + +def plot_init(xlim, ylim, xlabel, ylabel, size=(4, 3), equal=False): + plt.figure(figsize=size) + if equal: + plt.gca().set_aspect(1) + plt.xlim(xlim) + plt.ylim(ylim) + plt.gca().set_xlabel(xlabel) + plt.gca().set_ylabel(ylabel) + plt.gca().set_rasterized(True) + + +def plot_point(x, y, color, marker): + plt.scatter(x, y, c=color, marker=marker) + + +def plot_classification_samples(dataframe, classes, colors, markers, labels, loc, name, show=True): + marks = [Line2D([0], [0], color=c, marker=m, lw="0") for c, m in zip(colors, markers)] + + for cl, c, m in zip(classes, colors, markers): + df = dataframe[dataframe.target == cl] + plot_point(df["petal length"], df["petal width"], c, m) + + plt.gca().legend(marks, labels, loc=loc) + plt.savefig("plot/{}.pdf".format(name), dpi=500, bbox_inches='tight') + if show: + plt.show() + + +def plot_boundaries(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str], + a: float = .5, h: str = '////////', ls='-', e=.05): + for cube in extractor._hypercubes: + plt.gca().fill_between((cube[x][0] - e, cube[x][1] + e), cube[y][0] - e, cube[y][1] + e, + fc='none', ec=colors[cube.output], alpha=a, hatch=h, linestyle=ls) + + +def plot_surfaces(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str], ec='r', e=.05): + for cube in extractor._hypercubes: + plt.gca().fill_between((cube[x][0] - e, cube[x][1] + e), cube[y][0] - e, cube[y][1] + e, + fc='none', ec=ec) + + +def plot_perimeters(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str], n: int = 5, + ec: str = 'r', m: str = '*', s: int = 60, z: float = 1e10, lw: float = 0.8): + for cube in extractor._hypercubes: + for corner in cube.perimeter_samples(n): + plt.scatter(corner[x], corner[y], c=colors[cube.output], marker=m, edgecolor=ec, s=s, zorder=z, linewidth=lw) + + +def plot_centers(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str], + ec: str = 'r', m: str = '*', s: int = 60, z: float = 1e10, lw: float = 0.8): + for cube in extractor._hypercubes: + center = cube.center + plt.scatter(center[x], center[y], c=colors[cube.output], marker=m, edgecolor=ec, s=s, zorder=z, linewidth=lw) + + +def plot_corners(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str], + ec: str = 'r', m: str = '*', s: int = 60, z: float = 1e10, lw: float = 0.8): + for cube in extractor._hypercubes: + for corner in cube.corners(): + plt.scatter(corner[x], corner[y], c=colors[cube.output], marker=m, edgecolor=ec, s=s, zorder=z, linewidth=lw) + + +def plot_barycenters(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str], + ec: str = 'r', m: str = '*', s: int = 60, z: float = 1e10, lw: float = 0.8): + for cube in extractor._hypercubes: + center = cube.barycenter + plt.scatter(center[x], center[y], c=colors[cube.output], marker=m, edgecolor=ec, s=s, zorder=z, linewidth=lw) def predict_from_theory(theory: Theory, data: pd.DataFrame) -> list[float or str]: @@ -95,6 +166,7 @@ def color_fader(v: float = 0., c1: str = 'green', c2: str = 'red'): pass # ax.text2D(0., 0.88, pretty_theory(theory, new_line=False), transform=ax.transAxes, fontsize=8) if isinstance(ys[0], str): - custom_lines = [Line2D([0], [0], marker='o', markerfacecolor=get_color(c), markersize=20, color='w') for c in classes] + custom_lines = [Line2D([0], [0], marker='o', markerfacecolor=get_color(c), + markersize=20, color='w') for c in classes] ax.legend(custom_lines, classes, loc='upper left', numpoints=1, ncol=3, fontsize=18, bbox_to_anchor=(0, 0)) plt.savefig(output, format='pdf') diff --git a/requirements.txt b/requirements.txt index e85d46d2..bee085c2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,4 +11,4 @@ parameterized==0.9.0 protobuf==4.24.3 setuptools==68.2.2 kneed==0.8.5 -sympy==1.12 \ No newline at end of file +sympy==1.12 diff --git a/test/psyke/extraction/hypercubic/test_hypercube.py b/test/psyke/extraction/hypercubic/test_hypercube.py index d1ee273a..ef4fcec4 100644 --- a/test/psyke/extraction/hypercubic/test_hypercube.py +++ b/test/psyke/extraction/hypercubic/test_hypercube.py @@ -162,7 +162,7 @@ def test_filter_dataframe(self): expected = (self.dataset.X >= self.x[0]) & (self.dataset.X < self.x[1]) & \ (self.dataset.Y >= self.y[0]) & (self.dataset.Y < self.y[1]) expected = self.dataset[expected].iloc[:, :-1] - filtered = self.cube._filter_dataframe(self.dataset.iloc[:, :-1]) + filtered = self.cube.filter_dataframe(self.dataset.iloc[:, :-1]) self.assertTrue(all(expected == filtered)) def test_update(self): @@ -225,8 +225,8 @@ def test_diagonal(self): self.assertEqual(self.cube.diagonal(), ((self.x[1] - self.x[0])**2 + (self.y[1] - self.y[0])**2)**0.5) def test_center(self): - self.assertEqual(self.cube.center(), Point(list(self.dimensions.keys()), - [(val[0] + val[1]) / 2 for val in self.dimensions.values()])) + self.assertEqual(self.cube.center, Point(list(self.dimensions.keys()), + [(val[0] + val[1]) / 2 for val in self.dimensions.values()])) def test_corners(self): self.assertEqual(self.cube.corners(), [