From ce8dbcf5ced81efd91d99b34c5d3cad31d6d12e1 Mon Sep 17 00:00:00 2001 From: "cezary.maszczyk" Date: Thu, 28 Nov 2024 14:10:12 +0100 Subject: [PATCH 1/9] doc: Add release note for v2.1.24.0 --- .../whats_new/Changes in this version.ipynb | 303 +----------------- 1 file changed, 14 insertions(+), 289 deletions(-) diff --git a/docs/source/rst/whats_new/Changes in this version.ipynb b/docs/source/rst/whats_new/Changes in this version.ipynb index 73a2c2a..401e665 100644 --- a/docs/source/rst/whats_new/Changes in this version.ipynb +++ b/docs/source/rst/whats_new/Changes in this version.ipynb @@ -4,255 +4,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# What's new in RuleKit version 2.1.21.0?\n", + "# What's new in RuleKit version 2.1.24.0?\n", "\n", "\n", - "### 1. Ability to use user-defined quality measures during rule induction, pruning, and voting phases.\n", - "\n", - "Users can now define custom quality measures function and use them for: growing, pruning and voting. Defining quality measure function is easy and straightforward, see example below.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from rulekit.classification import RuleClassifier\n", - "\n", - "def my_induction_measure(p: float, n: float, P: float, N: float) -> float:\n", - " # do anything you want here and return a single float...\n", - " return (p + n) / (P + N)\n", - "\n", - "def my_pruning_measure(p: float, n: float, P: float, N: float) -> float:\n", - " return p - n\n", - "\n", - "def my_voting_measure(p: float, n: float, P: float, N: float) -> float:\n", - " return (p + 1) / (p + n + 2)\n", - "\n", - "python_clf = RuleClassifier(\n", - " induction_measure=my_induction_measure,\n", - " pruning_measure=my_pruning_measure,\n", - " voting_measure=my_voting_measure,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This function was available long ago in the original Java library, but there were some technical problems that prevented its implementation in that package. Now, with the release of RuleKit v2, it is finally available.\n", - "\n", - "> ⚠️ Using this feature comes at a price. Using the original set of quality measures from `rulekit.params.Measures` provides an optimized and much faster implementation of these quality functions in Java. Using a custom Python function **will certainly slow down the model learning process**. For example, learning rules on the Iris dataset using the FullCoverage measure went from 1.8 seconds to 10.9 seconds after switching to using the Python implementation of the same measure.\n", - "\n", - "\n", - "### 2. Reading arff files from url via HTTP/HTTPS.\n", - "\n", - "In the last version of the package, a new function for reading arff files was added. It made it possible to read an arff file by accepting the file path or a file-like object as an argument. As of this version, the function also accepts URLs, giving it the ability to read an arff dataset directly from some servers via HTTP/HTTPS. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "from rulekit.arff import read_arff\n", - "\n", - "df: pd.DataFrame = read_arff(\n", - " 'https://raw.githubusercontent.com/'\n", - " 'adaa-polsl/RuleKit/refs/heads/master/data/seismic-bumps/'\n", - " 'seismic-bumps.arff'\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 3. Improves rules API\n", - "\n", - "Access to some basic rule information was often quite cumbersome in earlier versions of this package. For example, there was no easy way to access information about the decision class of a classification rule. \n", - "\n", - "In this version, rule classes and rule sets have been refactored and improved. Below is a list of some operations that are now much easier. \n", - "\n", - "#### 3.1 For classification rules\n", - "\n", - "You can now access rules decision class via `rulekit.rules.ClassificationRule.decision_class` field. Example below:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Decision class of the first rule: 0\n" - ] - } - ], - "source": [ - "import pandas as pd\n", - "from rulekit.arff import read_arff\n", - "from rulekit.classification import RuleClassifier\n", - "from rulekit.rules import RuleSet, ClassificationRule\n", - "\n", - "DATASET_URL: str = (\n", - " 'https://raw.githubusercontent.com/'\n", - " 'adaa-polsl/RuleKit/refs/heads/master/data/seismic-bumps/'\n", - " 'seismic-bumps.arff'\n", - ")\n", - "df: pd.DataFrame = read_arff(DATASET_URL)\n", - "X, y = df.drop('class', axis=1), df['class']\n", - "\n", - "clf: RuleClassifier = RuleClassifier()\n", - "clf.fit(X, y)\n", - "\n", - "# RuleSet class became generic now\n", - "ruleset: RuleSet[ClassificationRule] = clf.model\n", - "rule: ClassificationRule = ruleset.rules[0]\n", - "print('Decision class of the first rule: ', rule.decision_class)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### 3.2 For regression rules\n", - "\n", - "You can now access rules decision attribute value via `rulekit.rules.RegressionRule.conclusion_value` field. Example below:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Decision value of the first rule: 0.40274932614553977\n" - ] - } - ], - "source": [ - "import pandas as pd\n", - "from rulekit.arff import read_arff\n", - "from rulekit.regression import RuleRegressor\n", - "from rulekit.rules import RuleSet, RegressionRule\n", - "\n", - "DATASET_URL: str = (\n", - " 'https://raw.githubusercontent.com/'\n", - " 'adaa-polsl/RuleKit/master/data/methane/'\n", - " 'methane-train.arff'\n", - ")\n", - "df: pd.DataFrame = read_arff(DATASET_URL)\n", - "X, y = df.drop('MM116_pred', axis=1), df['MM116_pred']\n", - "\n", - "reg = RuleRegressor()\n", - "reg.fit(X, y)\n", - "\n", - "ruleset: RuleSet[RegressionRule] = reg.model\n", - "rule: RegressionRule = ruleset.rules[0]\n", - "print('Decision value of the first rule: ', rule.conclusion_value)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### 3.3 For survival rules\n", - "\n", - "More changes have been made for survival rules. \n", - "\n", - "First, there is a new class `rulekit.kaplan_meier.KaplanMeierEstimator`, which represents Kaplan-Meier estimator rules. In the future, prediction arrays for survival problems will probably be moved from dictionary arrays to arrays of such objects, but this would be a breaking change unfortunately \n", - "\n", - "In addition, one can now easily access the Kaplan-Meier curve of the entire training dataset using the `rulekit.survival.SurvivalRules.get_train_set_kaplan_meier` method.\n", - "\n", - "Such curves can be easily plotted using the charting package of your choice." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjAAAAGdCAYAAAAMm0nCAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABAU0lEQVR4nO3deXxU1f3/8fdNyGQhJAEJSYAYkE1QCAKCERWs0QQsFWwVESXgwhcVN6QCioRFTWuRolbBrwv0a7EgFNSfLCpRVBDZBAFZFGSrkgACCRAgITm/P2KGDGSbMJOZybyej8c8nLlz7p1zTyedD+d8zjmWMcYIAADAhwR4ugIAAADOIoABAAA+hwAGAAD4HAIYAADgcwhgAACAzyGAAQAAPocABgAA+BwCGAAA4HPqeLoCVVFUVKRffvlF9erVk2VZnq4OAACoAmOMjh07psaNGysgwLV9Jj4RwPzyyy+Kj4/3dDUAAEA17Nu3T02bNnXpNX0igKlXr56k4gaIiIjwcG0AAEBV5ObmKj4+3v477ko+EcCUDBtFREQQwAAA4GPckf5BEi8AAPA5BDAAAMDnEMAAAACf4xM5MACA8hUWFqqgoMDT1YAfCgwMVJ06dTyyxAkBDAD4sOPHj+u///2vjDGergr8VFhYmOLi4mSz2Wr0c50OYL788kv97W9/07p167R//34tWLBAffv2rfCcZcuWacSIEfr+++8VHx+vsWPHavDgwdWsMgBAKu55+e9//6uwsDBFR0ez0CdqlDFG+fn5OnjwoHbt2qVWrVq5fLG6ijgdwJw4cUKJiYm65557dOutt1ZafteuXbr55ps1bNgwzZo1S5mZmbrvvvsUFxenlJSUalUaACAVFBTIGKPo6GiFhoZ6ujrwQ6GhoQoKCtKePXuUn5+vkJCQGvtspwOYXr16qVevXlUuP336dDVv3lwvvviiJKlt27Zavny5/v73vxPAAIAL0PMCT6rJXheHz3X3B6xcuVLJyckOx1JSUrRy5Up3fzQAAKil3B7AZGVlKSYmxuFYTEyMcnNzdfLkyTLPOX36tHJzcx0eAADvNn78eHXs2NHT1aiWZs2aaerUqZ6uBpzglevAZGRkKDIy0v5gI0cAqL7BgwefN9li3rx5CgkJsQ/v+5Jly5bJsizVr19fp06dcnhvzZo1sizL6WG1NWvWaOjQoa6sJtzM7QFMbGyssrOzHY5lZ2crIiKi3KSzMWPGKCcnx/7Yt2+f6ytmjJR/ovjB9EMAfuTNN9/UwIEDNW3aND3xxBOerk611atXTwsWLHA49tZbb+niiy92+lrR0dEKCwurdl3y8/Orfa6zWPOnmNsDmKSkJGVmZjoc+/TTT5WUlFTuOcHBwfaNG922gWNBnvR84+JHQZ7rrw8AXuiFF17Qww8/rNmzZ2vIkCH241OmTFH79u1Vt25dxcfH68EHH9Tx48ft78+cOVNRUVF6//331apVK4WEhCglJaXCf2CuWbNGN954oxo2bKjIyEj16NFD3377rUMZy7L05ptvql+/fgoLC1OrVq304YcfVule0tLS9Pbbb9tfnzx5UrNnz1ZaWtp5ZZcvX65rr71WoaGhio+P1yOPPKITJ07Y3z93COno0aO67777FB0drYiICP3ud7/Td999Z3+/ZLjszTffVPPmzSucfbNixQr17NlTYWFhql+/vlJSUnTkyJEyP1eSOnbsqPHjxzu00bRp0/SHP/xBdevW1aRJk9S0aVNNmzbN4bz169crICBAe/bsqdI9fPfdd7r++utVr149RUREqHPnzlq7dm259+FtnA5gjh8/rg0bNmjDhg2SiqdJb9iwQXv37pVU3HsyaNAge/lhw4bpp59+0pNPPqlt27bptdde03vvvafHH3/cNXdQTaUXfWIBKAD+YNSoUZo0aZI++ugj9evXz+G9gIAAvfzyy/r+++/1z3/+U5999pmefPJJhzJ5eXl67rnn9H//939asWKFjh49qjvuuKPczzt27JjS0tK0fPlyffPNN2rVqpV69+6tY8eOOZSbMGGCbr/9dm3cuFG9e/fWwIEDdfjw4Urv5+6779ZXX31l//35z3/+o2bNmqlTp04O5Xbu3KnU1FT98Y9/1MaNGzVnzhwtX75cw4cPL/fat912mw4cOKDFixdr3bp16tSpk2644QaHeu3YsUP/+c9/NH/+fPtv4rk2bNigG264Qe3atdPKlSu1fPly9enTR4WFhZXeX2njx49Xv379tGnTJt13330aMGCA3n33XYcys2bNUvfu3ZWQkFClexg4cKCaNm2qNWvWaN26dRo9erSCgoLs17MsSzNnznSqnjXKOOnzzz83ks57pKWlGWOMSUtLMz169DjvnI4dOxqbzWYuueQSM2PGDKc+Mycnx0gyOTk5zla3XCeOHTUmPcKY9Iji5wDgY06ePGm2bNliTp48WWG5tLQ0Y7PZjCSTmZlZpWvPnTvXXHTRRfbXM2bMMJLMN998Yz+2detWI8msWrXKGGNMenq6SUxMLPeahYWFpl69eub//b//Zz8myYwdO9b++vjx40aSWbx4cbnXKfkdOnLkiOnbt6+ZMGGCMcaY66+/3rz00ktmwYIFpvTP27333muGDh3qcI2vvvrKBAQE2NsuISHB/P3vf7e/FxERYU6dOuVwTosWLczrr79uv9egoCBz4MCBcutpjDEDBgww3bt3L/f90p9bIjEx0aSnp9tfSzKPPfaYQ5n169cby7LMnj17jDHFbdukSRMzbdq0Kt9DvXr1zMyZM8utW5s2bcz8+fMrvD9jKv4euuP3u4TT68D07Nmzwh6LsqK1nj17av369c5+VA2iBwZA7dahQwcdOnRI6enp6tq1q8LDwx3eX7p0qTIyMrRt2zbl5ubqzJkzOnXqlPLy8uy5IXXq1NGVV15pP+fSSy9VVFSUtm7dqq5du573mdnZ2Ro7dqyWLVumAwcOqLCwUHl5efYek9J1K1G3bl1FRETowIEDkqTLLrvMPiRy7bXXavHixQ7n3nPPPXr00Ud11113aeXKlZo7d66++uorhzLfffedNm7cqFmzZtmPGWNUVFSkXbt2qW3btueVP378uC666CKH4ydPntTOnTvtrxMSEhQdHX3efZe2YcMG3XbbbRWWqYouXbo4vO7YsaPatm2rd999V6NHj9YXX3yhAwcO2D+rKvcwYsQI3XfffXrnnXeUnJys2267TS1atLCX3bZt2wXX253YC0lSyDu/l4Z9JbEYFIBaqkmTJpo3b56uv/56paamavHixapXr54kaffu3fr973+vBx54QM8995waNGig5cuX695771V+fn61k1vT0tL066+/6qWXXlJCQoKCg4OVlJR0XsJr6WELqXjooqioSJK0aNEie9JqWRM/evXqpaFDh+ree+9Vnz59zvvBlopTH/7nf/5HjzzyyHnvlZXwe/z4ccXFxWnZsmXnvRcVFWV/Xrdu3fNv+hyVrZAcEBBwXqdAWUm6ZX3WwIED7QHMu+++q9TUVPv9V+Uexo8frzvvvFMLFy7U4sWLlZ6ertmzZ583vOit/DeACQrT90UJuixgjwKyNxUn8toq/zICgK9KSEjQF198YQ9ilixZonr16mndunUqKirSiy++aF9V9b333jvv/DNnzmjt2rX23pbt27fr6NGj5/VglFixYoVee+019e7dW5K0b98+HTp0yOk6V6ROnToaNGiQXnjhhfN6Z0p06tRJW7ZsUcuWLav0mZ06dVJWVpbq1KmjZs2aOVXfc3Xo0EGZmZmaMGFCme9HR0dr//799te5ubnatWtXla595513auzYsVq3bp3mzZun6dOnO30PrVu3VuvWrfX4449rwIABmjFjhs8EMF65DkyNsCzdlp/u6VoAQI2Kj4+3D+mkpKQoNzdXLVu2VEFBgV555RX99NNPeueddxx+DEsEBQXp4Ycf1qpVq7Ru3ToNHjxYV111VZnDR5LUqlUrvfPOO9q6datWrVqlgQMHumXPpkmTJungwYPlbk8zatQoff311xo+fLg2bNigH3/8UR988EG5SbzJyclKSkpS37599cknn2j37t36+uuv9fTTTzs9S2fMmDFas2aNHnzwQW3cuFHbtm3TtGnT7IHc7373O73zzjv66quvtGnTJqWlpSkwMLBK127WrJmuvvpq3XvvvSosLNQf/vCHKt/DyZMnNXz4cC1btkx79uzRihUrtGbNGodg9NJLLz1vmro38d8ARo6ZLxXl9QBAbdK0aVMtW7ZMhw4dUkpKipo3b64pU6bor3/9qy6//HLNmjVLGRkZ550XFhamUaNG6c4771T37t0VHh6uOXPmlPs5b731lo4cOaJOnTrp7rvv1iOPPKJGjRq5/H5sNpsaNmxY7uJ1HTp00BdffKEffvhB1157ra644gqNGzdOjRs3LrO8ZVlatGiRrrvuOg0ZMkStW7fWHXfcoT179py3snxlWrdurU8++UTfffedunbtqqSkJH3wwQeqU6d4AGTMmDHq0aOHfv/73+vmm29W3759HfJQKjNw4EB999136tevn0NwWNk9BAYG6tdff9WgQYPUunVr3X777erVq5dDT9H27duVk5Pj1P3WJMv4wC93bm6uIiMjlZOT47I1YYwxuvWlpVpw9E+SpLyRexUWHumSawNATTh16pR27dpV6TokrjBz5kw99thjOnr0qFs/B76nou+hO36/S/htD4xlWfrXvWV3ewIAAO/mtwGMxKQjAAB8lV8HMACAqhk8eDDDR/AqBDC/ycsvJJEXAAAfQQDzm2tf+Fy3TV9JEAMAgA/w6wAmNMhxrv3aPUd0ssC5DbYAAEDN8+sApvSaAeTzAgDgO/w6gCltrm2C2NQRAADf4N8BTFCYFNteknRZwB6F6rSHKwQAAKrCvwMYy5KGLPF0LQAAv+nZs6cee+wxT1ejQoMHD1bfvn09XQ2/598BjOSwmh15MADgfoMHD5ZlWec9duzYofnz52vSpEkXdH3LsvT++++7prLwWnU8XQFvMtc2QTJ/qLwgAOCCpKamasaMGQ7HoqOjK92JOT8/XzabzS11KigoUFBQkFuuDdejByYoTEUxZ/NgVJDn4QoBQO0XHBys2NhYh0dgYOB5Q0jNmjXTpEmTNGjQIEVERGjo0KHKz8/X8OHDFRcXp5CQECUkJNh3z27WrJkkqV+/frIsy/76XLt375ZlWZozZ4569OihkJAQzZo1S+PHj1fHjh0dyk6dOrXc60hSUVGRMjIy1Lx5c4WGhioxMVHz5s27gNZBVdADY1k6dfdHCpuc4OmaAMAFMcZ4bC2r0KBAh6UpXGny5MkaN26c0tPTJUkvv/yyPvzwQ7333nu6+OKLtW/fPu3bt0+StGbNGjVq1EgzZsxQampqpT06o0eP1osvvqgrrrhCISEhev31152uX0ZGhv71r39p+vTpatWqlb788kvdddddio6OVo8ePZy/YVQJAYwksl8A1AYnCwrVbtzHHvnsLRNTFGar+k/KRx99pPDwcPvrXr16ae7cuWWW/d3vfqcnnnjC/nrv3r1q1aqVrrnmGlmWpYSEs/8AjY6OliRFRUUpNja20no89thjuvXWW6tc73OdPn1azz//vJYuXaqkpCRJ0iWXXKLly5fr9ddfJ4BxIwIYAECNu/766zVt2jT767p165ZbtkuXLg6vBw8erBtvvFFt2rRRamqqfv/73+umm26qVj3OvbazduzYoby8PN14440Ox/Pz83XFFVdc0LVRMQIYAKglQoMCtWViisc+2xl169ZVy5Ytq1y2tE6dOmnXrl1avHixli5dqttvv13JycnVyjs599oBAQHn7YlXUFBQ7vnHjx+XJC1cuFBNmjRxeC84ONjp+qDqCGAAoJawLMupYRxfFhERof79+6t///7605/+pNTUVB0+fFgNGjRQUFCQCgurlwsUHR2trKwsGWPsOT0bNmwot3y7du0UHBysvXv3MlxUw/zjmw4AqDWmTJmiuLg4XXHFFQoICNDcuXMVGxurqKgoScUzkTIzM9W9e3cFBwerfv36Vb52z549dfDgQb3wwgv605/+pCVLlmjx4sWKiIgos3y9evU0cuRIPf744yoqKtI111yjnJwcrVixQhEREUpLS3PFLaMMTKM+h2E7JADwavXq1dMLL7ygLl266Morr9Tu3bu1aNEiBQQU/6S9+OKL+vTTTxUfH+90Hkrbtm312muv6dVXX1ViYqJWr16tkSNHVnjOpEmT9MwzzygjI0Nt27ZVamqqFi5cqObNm1f7HlE5y5w72OeFcnNzFRkZqZycnHKj4AuRdzxHYZMvliT1i5qn+Y8mu206IAC4yqlTp7Rr1y41b95cISEhnq4O/FRF30N3/n7TAyPH5LNtWbkeW0cBAABUDQGM5NDbQr8LAADejwDmHMX7IXn9qBoAAH6NAEZiPyQAAHwMAYxk3w8JAAD4BgIYO7JfAADwFQQwAADA5xDAAAAAn0MAAwAAfA4BDADA5zVr1kxTp06tcvlly5bJsiwdPXrUbXUqz8yZM+37NqH6CGAAADXGsqwKH+PHj6/WddesWaOhQ4dWufzVV1+t/fv3KzIyslqfV9OcDdBcYffu3bIsq8LduD2J3agBADVm//799udz5szRuHHjtH37dvux8PBw+3NjjAoLC1WnTuU/VdHR0U7Vw2azKTY21qlz4F3ogQEA1JjY2Fj7IzIyUpZl2V9v27ZN9erV0+LFi9W5c2cFBwdr+fLl2rlzp2655RbFxMQoPDxcV155pZYuXepw3XN7KCzL0ptvvql+/fopLCxMrVq10ocffmh//9whpJJhnY8//lht27ZVeHi4UlNTHQKuM2fO6JFHHlFUVJQuuugijRo1Smlpaerbt2+F9zxz5kxdfPHFCgsLU79+/fTrr786vF/Z/fXs2VN79uzR448/bu+pkqRff/1VAwYMUJMmTRQWFqb27dvr3//+t8O1582bp/bt2ys0NFQXXXSRkpOTdeLECfv7b775ptq2bauQkBBdeumleu211+zvleymfcUVV8iyLPXs2bPC+6xpBDAAUFsYI+Wf8MzDhVuwjB49Wn/5y1+0detWdejQQcePH1fv3r2VmZmp9evXKzU1VX369NHevXsrvM6ECRN0++23a+PGjerdu7cGDhyow4cPl1s+Ly9PkydP1jvvvKMvv/xSe/fu1ciRI+3v//Wvf9WsWbM0Y8YMrVixQrm5uXr//fcrrMOqVat07733avjw4dqwYYOuv/56Pfvssw5lKru/+fPnq2nTppo4caL2799vD6pOnTqlzp07a+HChdq8ebOGDh2qu+++W6tXr5ZU3Ns1YMAA3XPPPdq6dauWLVumW2+9Vea3/61mzZqlcePG6bnnntPWrVv1/PPP65lnntE///lPSbJfZ+nSpdq/f7/mz59f4b3WNIaQAKC2KMiTnm/smc9+6hfJVtcll5o4caJuvPFG++sGDRooMTHR/nrSpElasGCBPvzwQw0fPrzc6wwePFgDBgyQJD3//PN6+eWXtXr1aqWmppZZvqCgQNOnT1eLFi0kScOHD9fEiRPt77/yyisaM2aM+vXrJ0n6xz/+oUWLFlV4Ly+99JJSU1P15JNPSpJat26tr7/+WkuWLLGXSUxMrPD+GjRooMDAQNWrV89h2KtJkyYOAdbDDz+sjz/+WO+99566du2q/fv368yZM7r11luVkJAgSWrfvr29fHp6ul588UXdeuutkop7XLZs2aLXX39daWlp9mG5iy66yCuH2+iBKQN7OQKA53Tp0sXh9fHjxzVy5Ei1bdtWUVFRCg8P19atWyvtgenQoYP9ed26dRUREaEDBw6UWz4sLMwevEhSXFycvXxOTo6ys7PVtWtX+/uBgYHq3LlzhXXYunWrunXr5nAsKSnJJfdXWFioSZMmqX379mrQoIHCw8P18ccf289LTEzUDTfcoPbt2+u2227TG2+8oSNHjkiSTpw4oZ07d+ree+9VeHi4/fHss89q586dFX6ut6AHpgx3v7VK/3n0Rvs4IwD4hKCw4p4QT322i9St69iTM3LkSH366aeaPHmyWrZsqdDQUP3pT39Sfn5+xVUKCnJ4bVmWioqKnCpvauBftNW9v7/97W966aWXNHXqVLVv315169bVY489Zj8vMDBQn376qb7++mt98skneuWVV/T0009r1apVCgsr/t/rjTfeOC/ACgwMdM+NuhgBzG9Cg87+Dzbp8EidzF+nsOCgCs4AAC9jWS4bxvEmK1as0ODBg+1DN8ePH9fu3btrtA6RkZGKiYnRmjVrdN1110kq7gH59ttv1bFjx3LPa9u2rVatWuVw7JtvvnF4XZX7s9lsKiwsPO+8W265RXfddZckqaioSD/88IPatWtnL2NZlrp3767u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K/4ufvrpJxMWFmZGjBhhtmzZYl555RUTGBholixZUqP3W5GqtEWPHj3M/fff7/DdyMnJsb9fW9riww8/NAsXLjQ//PCD2b59u3nqqadMUFCQ2bx5szHGf74TxlTeFt70nfDLAKZr167moYcesr8uLCw0jRs3NhkZGR6sleulp6ebxMTEMt87evSoCQoKMnPnzrUf27p1q5FkVq5caYwp/uELCAgwWVlZ9jLTpk0zERER5vTp026tuyud+6NdVFRkYmNjzd/+9jf7saNHj5rg4GDz73//2xhjzJYtW4wks2bNGnuZxYsXG8uyzM8//2yMMea1114z9evXd2iLUaNGmTZt2rj5jqqvvADmlltuKfec2toWxhhz4MABI8l88cUXxhjX/V08+eST5rLLLnP4rP79+5uUlBR331K1ndsWxhT/WD366KPlnlNb28IYY+rXr2/efPNNv/5OlChpC2O86zvhd0NI+fn5WrdunZKTk+3HAgIClJycrJUrV3qwZu7x448/qnHjxrrkkks0cOBA7d27V5K0bt06FRQUOLTDpZdeqosvvtjeDitXrlT79u0VExNjL5OSkqLc3Fx9//33NXsjLrRr1y5lZWU53HtkZKS6devmcO9RUVHq0qWLvUxycrICAgK0atUqe5nrrrtONpvNXiYlJUXbt2/XkSNHauhuXGPZsmVq1KiR2rRpowceeEC//vqr/b3a3BY5OTmSpAYNGkhy3d/FypUrHa5RUsab/z/m3LYoMWvWLDVs2FCXX365xowZo7y8PPt7tbEtCgsLNXv2bJ04cUJJSUl+/Z04ty1KeMt3wic2c3SlQ4cOqbCw0KFxJSkmJkbbtm3zUK3co1u3bpo5c6batGmj/fv3a8KECbr22mu1efNmZWVlyWazKSoqyuGcmJgYZWVlSZKysrLKbKeS93xVSd3LurfS996oUSOH9+vUqaMGDRo4lGnevPl51yh5r379+m6pv6ulpqbq1ltvVfPmzbVz50499dRT6tWrl1auXKnAwMBa2xZFRUV67LHH1L17d11++eWS5LK/i/LK5Obm6uTJkwoNDXXHLVVbWW0hSXfeeacSEhLUuHFjbdy4UaNGjdL27ds1f/58SbWrLTZt2qSkpCSdOnVK4eHhWrBggdq1a6cNGzb43XeivLaQvOs74XcBjD/p1auX/XmHDh3UrVs3JSQk6L333vOqPxZ41h133GF/3r59e3Xo0EEtWrTQsmXLdMMNN3iwZu710EMPafPmzVq+fLmnq+Jx5bXF0KFD7c/bt2+vuLg43XDDDdq5c6datGhR09V0qzZt2mjDhg3KycnRvHnzlJaWpi+++MLT1fKI8tqiXbt2XvWd8LshpIYNGyowMPC8DPLs7GzFxsZ6qFY1IyoqSq1bt9aOHTsUGxur/Px8HT161KFM6XaIjY0ts51K3vNVJXWv6DsQGxurAwcOOLx/5swZHT58uNa3zyWXXKKGDRtqx44dkmpnWwwfPlwfffSRPv/8czVt2tR+3FV/F+WViYiI8Lp/PJTXFmXp1q2bJDl8N2pLW9hsNrVs2VKdO3dWRkaGEhMT9dJLL/nld6K8tiiLJ78TfhfA2Gw2de7cWZmZmfZjRUVFyszMdBjjq42OHz+unTt3Ki4uTp07d1ZQUJBDO2zfvl179+61t0NSUpI2bdrk8OP16aefKiIiwt6d6IuaN2+u2NhYh3vPzc3VqlWrHO796NGjWrdunb3MZ599pqKiIvsfbFJSkr788ksVFBTYy3z66adq06aNVw6ZVNV///tf/frrr4qLi5NUu9rCGKPhw4drwYIF+uyzz84b9nLV30VSUpLDNUrKeNP/x1TWFmXZsGGDJDl8N2pDW5SlqKhIp0+f9qvvRHlK2qIsHv1OOJXyW0vMnj3bBAcHm5kzZ5otW7aYoUOHmqioKIes6drgiSeeMMuWLTO7du0yK1asMMnJyaZhw4bmwIEDxpjiqYEXX3yx+eyzz8zatWtNUlKSSUpKsp9fMh3upptuMhs2bDBLliwx0dHRPjGN+tixY2b9+vVm/fr1RpKZMmWKWb9+vdmzZ48xpngadVRUlPnggw/Mxo0bzS233FLmNOorrrjCrFq1yixfvty0atXKYerw0aNHTUxMjLn77rvN5s2bzezZs01YWJjXTR2uqC2OHTtmRo4caVauXGl27dplli5dajp16mRatWplTp06Zb9GbWmLBx54wERGRpply5Y5TAPNy8uzl3HF30XJNNE///nPZuvWrebVV1/1uimzlbXFjh07zMSJE83atWvNrl27zAcffGAuueQSc91119mvUVvaYvTo0eaLL74wu3btMhs3bjSjR482lmWZTz75xBjjP98JYypuC2/7TvhlAGOMMa+88oq5+OKLjc1mM127djXffPONp6vkcv379zdxcXHGZrOZJk2amP79+5sdO3bY3z958qR58MEHTf369U1YWJjp16+f2b9/v8M1du/ebXr16mVCQ0NNw4YNzRNPPGEKCgpq+lac9vnnnxtJ5z3S0tKMMcVTqZ955hkTExNjgoODzQ033GC2b9/ucI1ff/3VDBgwwISHh5uIiAgzZMgQc+zYMYcy3333nbnmmmtMcHCwadKkifnLX/5SU7dYZRW1RV5enrnppptMdHS0CQoKMgkJCeb+++8/L5ivLW1RVjtIMjNmzLCXcdXfxeeff246duxobDabueSSSxw+wxtU1hZ79+411113nWnQoIEJDg42LVu2NH/+858d1vwwpna0xT333GMSEhKMzWYz0dHR5oYbbrAHL8b4z3fCmIrbwtu+E5YxxjjXZwMAAOBZfpcDAwAAfB8BDAAA8DkEMAAAwOcQwAAAAJ9DAAMAAHwOAQwAAPA5BDAAAMDnEMAAAACfQwADAAB8DgEMAADwOQQwAADA5xDAAAAAn/P/ARyUqwJzYsJCAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import pandas as pd\n", - "import matplotlib.pyplot as plt\n", - "from rulekit.arff import read_arff\n", - "from rulekit.survival import SurvivalRules\n", - "from rulekit.rules import RuleSet, SurvivalRule\n", - "from rulekit.kaplan_meier import KaplanMeierEstimator # this is a new class\n", - "\n", - "DATASET_URL: str = (\n", - " 'https://raw.githubusercontent.com/'\n", - " 'adaa-polsl/RuleKit/master/data/bmt/'\n", - " 'bmt.arff'\n", - ")\n", - "df: pd.DataFrame = read_arff(DATASET_URL)\n", - "X, y = df.drop('survival_status', axis=1), df['survival_status']\n", - "\n", - "surv = SurvivalRules(survival_time_attr='survival_time')\n", - "surv.fit(X, y)\n", - "\n", - "ruleset: RuleSet[SurvivalRule] = reg.model\n", - "rule: SurvivalRule = ruleset.rules[0]\n", - "\n", - "# you can now easily access Kaplan-Meier estimator of the rules\n", - "rule_estimator: KaplanMeierEstimator = rule.kaplan_meier_estimator\n", - "plt.step(\n", - " rule_estimator.times, \n", - " rule_estimator.probabilities,\n", - " label='First rule'\n", - ")\n", - "# you can also access training dataset Kaplan-Meier estimator easily\n", - "train_dataset_estimator: KaplanMeierEstimator = surv.get_train_set_kaplan_meier()\n", - "plt.step(\n", - " train_dataset_estimator.times, \n", - " train_dataset_estimator.probabilities,\n", - " label='Training dataset'\n", - ")\n", - "plt.legend(title='Kaplan-Meier curves:')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 4. Changes in expert rules induction for regression and survival `❗BREAKING CHANGES`\n", - "\n", - "> Note that those changes will likely be reverted on the next version and are caused by a known bug in the original RuleKit library. Fixing it is beyond the scope of this package, which is merely a wrapper for it. \n", - "\n", - "Since this version, there has been a change in the way expert rules and conditions for regression and survival problems are communicated. All you have to do is remove conclusion part of those rules (everything after **THEN**).\n", - "\n", - "Expert rules before:" + "### 1. Revert breaking changes in expert rules induction for regression and survival \n", + "The latest version 2.1.21.0 introduced some groundbreaking changes, which you can read more\n", + "about them in the latest [release note](https://github.com/adaa-polsl/RuleKit-python/releases/tag/v2.1.21.0).\n", + "Now rules and expert conditions can be defined in both the old and new formats, see example below." ] }, { @@ -261,23 +19,16 @@ "metadata": {}, "outputs": [], "source": [ + "# both variants will work the same\n", "expert_rules = [\n", " (\n", " 'rule-0',\n", " 'IF [[CD34kgx10d6 = (-inf, 10.0)]] AND [[extcGvHD = {0}]] THEN survival_status = {NaN}'\n", - " )\n", - "]\n", - "\n", - "expert_preferred_conditions = [\n", + " ),\n", " (\n", - " 'attr-preferred-0',\n", - " 'inf: IF [CD34kgx10d6 = Any] THEN survival_status = {NaN}'\n", - " )\n", - "]\n", - "\n", - "\n", - "expert_forbidden_conditions = [\n", - " ('attr-forbidden-0', 'IF [ANCrecovery = Any] THEN survival_status = {NaN}')\n", + " 'rule-0',\n", + " 'IF [[CD34kgx10d6 = (-inf, 10.0)]] AND [[extcGvHD = {0}]] THEN'\n", + " ),\n", "]" ] }, @@ -285,33 +36,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "And now:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "expert_rules = [\n", - " (\n", - " 'rule-0',\n", - " 'IF [[CD34kgx10d6 = (-inf, 10.0)]] AND [[extcGvHD = {0}]] THEN'\n", - " )\n", - "]\n", + "### 2. Upgrade to new version of RuleKit\n", "\n", - "expert_preferred_conditions = [\n", - " (\n", - " 'attr-preferred-0',\n", - " 'inf: IF [CD34kgx10d6 = Any] THEN'\n", - " )\n", - "]\n", - "\n", - "\n", - "expert_forbidden_conditions = [\n", - " ('attr-forbidden-0', 'IF [ANCrecovery = Any] THEN')\n", - "]" + "In the new version of the Java RuleKit library, many bugs regarding expert induction have been corrected." ] }, { @@ -320,10 +47,8 @@ "source": [ "### Other changes\n", "\n", - "* Fix expert rules parsing.\n", - "* Conditions printed in the order they had been added to the rule.\n", - "* Fixed bug when using `sklearn.base.clone` function with RuleKit model classes.\n", - "* Update tutorials in the documentation." + "* Improve flake8 score\n", + "* Add more unit tests." ] } ], From fa082a5c3a8fcca18115e9dfc2751915e9d013d3 Mon Sep 17 00:00:00 2001 From: cezary986 Date: Thu, 28 Nov 2024 13:15:12 +0000 Subject: [PATCH 2/9] Documentation for version v2.1.24.0 --- docs/badges/coverage-badge.svg | 2 +- docs/badges/flake8-badge.svg | 2 +- docs/badges/test-badge.svg | 2 +- docs/reports/coverage/class_index.html | 304 +-- .../coverage/coverage_html_cb_6fb7b396.js | 733 +++++++ docs/reports/coverage/function_index.html | 1076 +++++------ docs/reports/coverage/index.html | 82 +- docs/reports/coverage/status.json | 2 +- docs/reports/coverage/style_cb_8e611ae1.css | 337 ++++ .../z_a44f0ac069e85531___init___py.html | 16 +- ...z_a44f0ac069e85531_test_classifier_py.html | 774 ++++---- ...z_a44f0ac069e85531_test_regression_py.html | 16 +- .../z_a44f0ac069e85531_test_rulekit_py.html | 16 +- ...44f0ac069e85531_test_serialization_py.html | 22 +- ...f0ac069e85531_test_sklearn_metrics_py.html | 16 +- ...z_a44f0ac069e85531_test_statistics_py.html | 16 +- .../z_a44f0ac069e85531_test_survival_py.html | 516 ++--- .../coverage/z_a44f0ac069e85531_utils_py.html | 125 +- .../z_a87f2a4bb6695d91___init___py.html | 16 +- .../z_a87f2a4bb6695d91__helpers_py.html | 1061 ++++++----- .../z_a87f2a4bb6695d91__logging_py.html | 18 +- .../z_a87f2a4bb6695d91__operator_py.html | 432 +++-- .../z_a87f2a4bb6695d91__problem_types_py.html | 16 +- .../coverage/z_a87f2a4bb6695d91_arff_py.html | 16 +- .../z_a87f2a4bb6695d91_classification_py.html | 1567 +++++++-------- .../z_a87f2a4bb6695d91_events_py.html | 16 +- .../z_a87f2a4bb6695d91_exceptions_py.html | 20 +- .../z_a87f2a4bb6695d91_kaplan_meier_py.html | 199 ++ .../coverage/z_a87f2a4bb6695d91_main_py.html | 360 ++-- .../z_a87f2a4bb6695d91_params_py.html | 290 +-- .../z_a87f2a4bb6695d91_regression_py.html | 993 +++++----- .../coverage/z_a87f2a4bb6695d91_rules_py.html | 550 +++--- .../coverage/z_a87f2a4bb6695d91_stats_py.html | 56 +- .../z_a87f2a4bb6695d91_survival_py.html | 1208 ++++++------ docs/reports/flake8/flake8stats.txt | 1 + docs/reports/flake8/index.html | 10 +- .../flake8/rulekit.classification.report.html | 8 +- .../flake8/rulekit.classification.source.html | 1684 +++++++++-------- .../reports/flake8/rulekit.events.report.html | 4 +- .../reports/flake8/rulekit.events.source.html | 4 +- .../flake8/rulekit.regression.report.html | 8 +- .../flake8/rulekit.regression.source.html | 1082 +++++------ .../flake8/rulekit.survival.report.html | 16 +- .../flake8/rulekit.survival.source.html | 1274 +++++++------ docs/reports/junit/report.html | 290 +-- docs/serve/index.html | 9 +- .../_sphinx_javascript_frameworks_compat.js | 123 ++ docs/serve/v2.1.24.0/_static/jquery.js | 2 + 48 files changed, 8502 insertions(+), 6888 deletions(-) create mode 100644 docs/reports/coverage/coverage_html_cb_6fb7b396.js create mode 100644 docs/reports/coverage/style_cb_8e611ae1.css create mode 100644 docs/reports/coverage/z_a87f2a4bb6695d91_kaplan_meier_py.html create mode 100644 docs/serve/v2.1.24.0/_static/_sphinx_javascript_frameworks_compat.js create mode 100644 docs/serve/v2.1.24.0/_static/jquery.js diff --git a/docs/badges/coverage-badge.svg b/docs/badges/coverage-badge.svg index eb0ef9c..458d1a4 100644 --- a/docs/badges/coverage-badge.svg +++ b/docs/badges/coverage-badge.svg @@ -1 +1 @@ -coverage: 88.97%coverage88.97% \ No newline at end of file +coverage: 89.10%coverage89.10% \ No newline at end of file diff --git a/docs/badges/flake8-badge.svg b/docs/badges/flake8-badge.svg index cb00fa6..3be8050 100644 --- a/docs/badges/flake8-badge.svg +++ b/docs/badges/flake8-badge.svg @@ -1 +1 @@ -flake8: 0 C, 3390 W, 0 Iflake80 C, 3390 W, 0 I \ No newline at end of file +flake8: 0 C, 3397 W, 0 Iflake80 C, 3397 W, 0 I \ No newline at end of file diff --git a/docs/badges/test-badge.svg b/docs/badges/test-badge.svg index 51143d6..37c07b2 100644 --- a/docs/badges/test-badge.svg +++ b/docs/badges/test-badge.svg @@ -1 +1 @@ -tests: 45tests45 \ No newline at end of file +tests: 46tests46 \ No newline at end of file diff --git a/docs/reports/coverage/class_index.html b/docs/reports/coverage/class_index.html index 2a5b9d8..bb58e4a 100644 --- a/docs/reports/coverage/class_index.html +++ b/docs/reports/coverage/class_index.html @@ -4,8 +4,8 @@ Coverage report - - + +
@@ -54,8 +54,8 @@

Classes

- coverage.py v7.6.4, - created at 2024-11-28 12:33 +0100 + coverage.py v7.6.8, + created at 2024-11-28 13:14 +0000

@@ -73,7 +73,7 @@

- rulekit\__init__.py + rulekit/__init__.py (no class) 4 0 @@ -81,47 +81,47 @@

100% - rulekit\_helpers.py - RuleGeneratorConfigurator + rulekit/_helpers.py + RuleGeneratorConfigurator 83 22 0 73% - rulekit\_helpers.py - ExampleSetFactory + rulekit/_helpers.py + ExampleSetFactory 65 11 0 83% - rulekit\_helpers.py - PredictionResultMapper + rulekit/_helpers.py + PredictionResultMapper 33 4 0 88% - rulekit\_helpers.py - ModelSerializer + rulekit/_helpers.py + ModelSerializer 11 1 0 91% - rulekit\_helpers.py + rulekit/_helpers.py (no class) - 61 + 68 0 0 - 100% + 100% - rulekit\_logging.py + rulekit/_logging.py _RuleKitJavaLoggerConfig 5 5 @@ -129,7 +129,7 @@

0% - rulekit\_logging.py + rulekit/_logging.py (no class) 5 0 @@ -137,7 +137,7 @@

100% - rulekit\_operator.py + rulekit/_operator.py BaseOperator 52 10 @@ -145,15 +145,15 @@

81% - rulekit\_operator.py - ExpertKnowledgeOperator + rulekit/_operator.py + ExpertKnowledgeOperator 25 1 0 96% - rulekit\_operator.py + rulekit/_operator.py (no class) 44 0 @@ -161,7 +161,7 @@

100% - rulekit\_problem_types.py + rulekit/_problem_types.py ProblemType 0 0 @@ -169,7 +169,7 @@

100% - rulekit\_problem_types.py + rulekit/_problem_types.py (no class) 8 0 @@ -177,7 +177,7 @@

100% - rulekit\arff.py + rulekit/arff.py (no class) 23 3 @@ -185,7 +185,7 @@

87% - rulekit\classification.py + rulekit/classification.py ClassificationPredictionMetrics 0 0 @@ -193,63 +193,63 @@

100% - rulekit\classification.py - _ClassificationParams + rulekit/classification.py + _ClassificationParams 0 0 0 100% - rulekit\classification.py - _ClassificationExpertParams + rulekit/classification.py + _ClassificationExpertParams 0 0 0 100% - rulekit\classification.py - BaseClassifier + rulekit/classification.py + BaseClassifier 8 0 0 100% - rulekit\classification.py - BaseClassifier.MetricTypes + rulekit/classification.py + BaseClassifier.MetricTypes 0 0 0 100% - rulekit\classification.py - RuleClassifier + rulekit/classification.py + RuleClassifier 52 3 0 94% - rulekit\classification.py - ExpertRuleClassifier + rulekit/classification.py + ExpertRuleClassifier 19 2 0 89% - rulekit\classification.py - ContrastSetRuleClassifier + rulekit/classification.py + ContrastSetRuleClassifier 31 31 0 0% - rulekit\classification.py + rulekit/classification.py (no class) 75 0 @@ -257,7 +257,7 @@

100% - rulekit\events.py + rulekit/events.py RuleInductionProgressListener 1 0 @@ -265,7 +265,7 @@

100% - rulekit\events.py + rulekit/events.py _command_listener_factory._CommandListener 4 0 @@ -273,7 +273,7 @@

100% - rulekit\events.py + rulekit/events.py (no class) 22 0 @@ -281,7 +281,7 @@

100% - rulekit\exceptions.py + rulekit/exceptions.py RuleKitJavaException 5 5 @@ -289,7 +289,7 @@

0% - rulekit\exceptions.py + rulekit/exceptions.py RuleKitMisconfigurationException 17 17 @@ -297,7 +297,7 @@

0% - rulekit\exceptions.py + rulekit/exceptions.py (no class) 15 0 @@ -305,7 +305,7 @@

100% - rulekit\kaplan_meier.py + rulekit/kaplan_meier.py KaplanMeierEstimator 19 0 @@ -313,7 +313,7 @@

100% - rulekit\kaplan_meier.py + rulekit/kaplan_meier.py (no class) 16 0 @@ -321,7 +321,7 @@

100% - rulekit\main.py + rulekit/main.py JRE_Type 0 0 @@ -329,15 +329,15 @@

100% - rulekit\main.py - RuleKit + rulekit/main.py + RuleKit 50 17 0 66% - rulekit\main.py + rulekit/main.py (no class) 39 0 @@ -345,7 +345,7 @@

100% - rulekit\params.py + rulekit/params.py _user_defined_measure_factory._UserMeasure 1 1 @@ -353,39 +353,39 @@

0% - rulekit\params.py - Measures + rulekit/params.py + Measures 0 0 0 100% - rulekit\params.py - ModelsParams + rulekit/params.py + ModelsParams 0 0 0 100% - rulekit\params.py - ExpertModelParams + rulekit/params.py + ExpertModelParams 0 0 0 100% - rulekit\params.py - ContrastSetModelParams + rulekit/params.py + ContrastSetModelParams 0 0 0 100% - rulekit\params.py + rulekit/params.py (no class) 87 6 @@ -393,7 +393,7 @@

93% - rulekit\regression.py + rulekit/regression.py _RegressionModelParams 0 0 @@ -401,7 +401,7 @@

100% - rulekit\regression.py + rulekit/regression.py _RegressionExpertModelParams 0 0 @@ -409,7 +409,7 @@

100% - rulekit\regression.py + rulekit/regression.py RuleRegressor 15 3 @@ -417,23 +417,23 @@

80% - rulekit\regression.py - ExpertRuleRegressor + rulekit/regression.py + ExpertRuleRegressor 7 0 0 100% - rulekit\regression.py - ContrastSetRuleRegressor + rulekit/regression.py + ContrastSetRuleRegressor 13 13 0 0% - rulekit\regression.py + rulekit/regression.py (no class) 47 0 @@ -441,7 +441,7 @@

100% - rulekit\rules.py + rulekit/rules.py InductionParameters 14 14 @@ -449,39 +449,39 @@

0% - rulekit\rules.py - BaseRule + rulekit/rules.py + BaseRule 14 2 0 86% - rulekit\rules.py - ClassificationRule + rulekit/rules.py + ClassificationRule 3 1 0 67% - rulekit\rules.py - RegressionRule + rulekit/rules.py + RegressionRule 3 1 0 67% - rulekit\rules.py - SurvivalRule + rulekit/rules.py + SurvivalRule 3 0 0 100% - rulekit\rules.py + rulekit/rules.py RuleSet 30 3 @@ -489,7 +489,7 @@

90% - rulekit\rules.py + rulekit/rules.py (no class) 85 0 @@ -497,7 +497,7 @@

100% - rulekit\stats.py + rulekit/stats.py RuleStatistics 7 1 @@ -505,7 +505,7 @@

86% - rulekit\stats.py + rulekit/stats.py RuleSetStatistics 16 1 @@ -513,7 +513,7 @@

94% - rulekit\stats.py + rulekit/stats.py (no class) 7 0 @@ -521,71 +521,71 @@

100% - rulekit\survival.py - _SurvivalModelsParams + rulekit/survival.py + _SurvivalModelsParams 0 0 0 100% - rulekit\survival.py - _SurvivalExpertModelParams + rulekit/survival.py + _SurvivalExpertModelParams 0 0 0 100% - rulekit\survival.py - _BaseSurvivalRulesModel + rulekit/survival.py + _BaseSurvivalRulesModel 1 0 0 100% - rulekit\survival.py - SurvivalRules + rulekit/survival.py + SurvivalRules 38 8 0 79% - rulekit\survival.py - ExpertSurvivalRules + rulekit/survival.py + ExpertSurvivalRules 12 0 0 100% - rulekit\survival.py - _SurvivalContrastSetModelParams + rulekit/survival.py + _SurvivalContrastSetModelParams 0 0 0 100% - rulekit\survival.py - ContrastSetSurvivalRules + rulekit/survival.py + ContrastSetSurvivalRules 16 16 0 0% - rulekit\survival.py + rulekit/survival.py (no class) - 55 + 63 0 0 - 100% + 100% - tests\__init__.py + tests/__init__.py (no class) 1 0 @@ -593,39 +593,39 @@

100% - tests\test_classifier.py - TestClassifier + tests/test_classifier.py + TestClassifier 106 0 0 100% - tests\test_classifier.py - TestClassifier.test_induction_progress_listener.EventListener + tests/test_classifier.py + TestClassifier.test_induction_progress_listener.EventListener 6 0 0 100% - tests\test_classifier.py - TestExperClassifier + tests/test_classifier.py + TestExperClassifier 34 0 0 100% - tests\test_classifier.py + tests/test_classifier.py (no class) - 35 + 38 1 0 - 97% + 97% - tests\test_regression.py + tests/test_regression.py TestRegressor 47 0 @@ -633,7 +633,7 @@

100% - tests\test_regression.py + tests/test_regression.py TestRegressor.test_induction_progress_listener.EventListener 10 0 @@ -641,7 +641,7 @@

100% - tests\test_regression.py + tests/test_regression.py TestExpertRegressor 28 0 @@ -649,7 +649,7 @@

100% - tests\test_regression.py + tests/test_regression.py (no class) 31 1 @@ -657,7 +657,7 @@

97% - tests\test_rulekit.py + tests/test_rulekit.py TestRuleKitMainClass 5 0 @@ -665,7 +665,7 @@

100% - tests\test_rulekit.py + tests/test_rulekit.py (no class) 10 1 @@ -673,7 +673,7 @@

90% - tests\test_serialization.py + tests/test_serialization.py TestModelSerialization 68 0 @@ -681,7 +681,7 @@

100% - tests\test_serialization.py + tests/test_serialization.py (no class) 33 0 @@ -689,7 +689,7 @@

100% - tests\test_sklearn_metrics.py + tests/test_sklearn_metrics.py TestMetrics 13 0 @@ -697,7 +697,7 @@

100% - tests\test_sklearn_metrics.py + tests/test_sklearn_metrics.py (no class) 12 1 @@ -705,7 +705,7 @@

92% - tests\test_statistics.py + tests/test_statistics.py TestRuleClassifier 7 0 @@ -713,7 +713,7 @@

100% - tests\test_statistics.py + tests/test_statistics.py (no class) 11 1 @@ -721,47 +721,47 @@

91% - tests\test_survival.py - TestKaplanMeierEstimator + tests/test_survival.py + TestKaplanMeierEstimator 9 0 0 100% - tests\test_survival.py - TestSurvivalRules + tests/test_survival.py + TestSurvivalRules 64 0 0 100% - tests\test_survival.py - TestSurvivalRules.test_induction_progress_listener.EventListener + tests/test_survival.py + TestSurvivalRules.test_induction_progress_listener.EventListener 6 0 0 100% - tests\test_survival.py - TestExpertSurvivalRules - 19 + tests/test_survival.py + TestExpertSurvivalRules + 23 0 0 - 100% + 100% - tests\test_survival.py + tests/test_survival.py (no class) - 32 + 35 1 0 - 97% + 97% - tests\utils.py + tests/utils.py ExampleSetWrapper 4 1 @@ -769,7 +769,7 @@

75% - tests\utils.py + tests/utils.py Knowledge 3 0 @@ -777,7 +777,7 @@

100% - tests\utils.py + tests/utils.py TestReport 2 0 @@ -785,7 +785,7 @@

100% - tests\utils.py + tests/utils.py TestCase 20 0 @@ -793,7 +793,7 @@

100% - tests\utils.py + tests/utils.py DataSetConfig 4 0 @@ -801,7 +801,7 @@

100% - tests\utils.py + tests/utils.py TestConfig 3 0 @@ -809,7 +809,7 @@

100% - tests\utils.py + tests/utils.py TestConfigParser 62 6 @@ -817,7 +817,7 @@

90% - tests\utils.py + tests/utils.py TestCaseFactory 50 2 @@ -825,7 +825,7 @@

96% - tests\utils.py + tests/utils.py TestReportReader 20 2 @@ -833,7 +833,7 @@

90% - tests\utils.py + tests/utils.py TestReportWriter 8 8 @@ -841,7 +841,7 @@

0% - tests\utils.py + tests/utils.py (no class) 147 13 @@ -853,10 +853,10 @@

Total   - 2176 + 2201 240 0 - 89% + 89% @@ -867,8 +867,8 @@

diff --git a/docs/reports/coverage/z_a44f0ac069e85531_test_serialization_py.html b/docs/reports/coverage/z_a44f0ac069e85531_test_serialization_py.html index 4f2e60a..66f231d 100644 --- a/docs/reports/coverage/z_a44f0ac069e85531_test_serialization_py.html +++ b/docs/reports/coverage/z_a44f0ac069e85531_test_serialization_py.html @@ -2,16 +2,16 @@ - Coverage for tests\test_serialization.py: 100% + Coverage for tests/test_serialization.py: 100% - - + +

- Coverage for tests\test_serialization.py: + Coverage for tests/test_serialization.py: 100%

diff --git a/docs/reports/coverage/z_a44f0ac069e85531_test_sklearn_metrics_py.html b/docs/reports/coverage/z_a44f0ac069e85531_test_sklearn_metrics_py.html index b742ffc..6f686a0 100644 --- a/docs/reports/coverage/z_a44f0ac069e85531_test_sklearn_metrics_py.html +++ b/docs/reports/coverage/z_a44f0ac069e85531_test_sklearn_metrics_py.html @@ -2,16 +2,16 @@ - Coverage for tests\test_sklearn_metrics.py: 96% + Coverage for tests/test_sklearn_metrics.py: 96% - - + +

- Coverage for tests\test_sklearn_metrics.py: + Coverage for tests/test_sklearn_metrics.py: 96%

diff --git a/docs/reports/coverage/z_a44f0ac069e85531_test_statistics_py.html b/docs/reports/coverage/z_a44f0ac069e85531_test_statistics_py.html index 55ddeaf..5d69ec4 100644 --- a/docs/reports/coverage/z_a44f0ac069e85531_test_statistics_py.html +++ b/docs/reports/coverage/z_a44f0ac069e85531_test_statistics_py.html @@ -2,16 +2,16 @@ - Coverage for tests\test_statistics.py: 94% + Coverage for tests/test_statistics.py: 94% - - + +

- Coverage for tests\test_statistics.py: + Coverage for tests/test_statistics.py: 94%

diff --git a/docs/reports/coverage/z_a44f0ac069e85531_test_survival_py.html b/docs/reports/coverage/z_a44f0ac069e85531_test_survival_py.html index f980afe..19cc1f8 100644 --- a/docs/reports/coverage/z_a44f0ac069e85531_test_survival_py.html +++ b/docs/reports/coverage/z_a44f0ac069e85531_test_survival_py.html @@ -2,16 +2,16 @@ - Coverage for tests\test_survival.py: 99% + Coverage for tests/test_survival.py: 99% - - + +

- Coverage for tests\test_survival.py: + Coverage for tests/test_survival.py: 99%

- 130 statements   - + 137 statements   +

@@ -64,8 +64,8 @@

^ index     » next       - coverage.py v7.6.4, - created at 2024-11-28 12:23 +0100 + coverage.py v7.6.8, + created at 2024-11-28 13:14 +0000