{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Create and evaluate handcrafted classification rules in decision-rules\n", "\n", "In this tutorial we will create manually decision rules for and evaluate them." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We begin by loading the iris dataset into a DataFrame." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "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", "
sepallengthsepalwidthpetallengthpetalwidthclass
05.13.51.40.2Iris-setosa
14.93.01.40.2Iris-setosa
24.73.21.30.2Iris-setosa
34.63.11.50.2Iris-setosa
45.03.61.40.2Iris-setosa
..................
1456.73.05.22.3Iris-virginica
1466.32.55.01.9Iris-virginica
1476.53.05.22.0Iris-virginica
1486.23.45.42.3Iris-virginica
1495.93.05.11.8Iris-virginica
\n", "

150 rows × 5 columns

\n", "
" ], "text/plain": [ " sepallength sepalwidth petallength petalwidth class\n", "0 5.1 3.5 1.4 0.2 Iris-setosa\n", "1 4.9 3.0 1.4 0.2 Iris-setosa\n", "2 4.7 3.2 1.3 0.2 Iris-setosa\n", "3 4.6 3.1 1.5 0.2 Iris-setosa\n", "4 5.0 3.6 1.4 0.2 Iris-setosa\n", ".. ... ... ... ... ...\n", "145 6.7 3.0 5.2 2.3 Iris-virginica\n", "146 6.3 2.5 5.0 1.9 Iris-virginica\n", "147 6.5 3.0 5.2 2.0 Iris-virginica\n", "148 6.2 3.4 5.4 2.3 Iris-virginica\n", "149 5.9 3.0 5.1 1.8 Iris-virginica\n", "\n", "[150 rows x 5 columns]" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Columns: ['sepallength' 'sepalwidth' 'petallength' 'petalwidth' 'class']\n", "Class names: ['Iris-setosa' 'Iris-versicolor' 'Iris-virginica']\n" ] } ], "source": [ "import pandas as pd\n", "IRIS_PATH = 'resources/iris.csv'\n", "iris_df = pd.read_csv(IRIS_PATH)\n", "display(iris_df)\n", "print('Columns: ', iris_df.columns.values)\n", "print('Class names:', iris_df['class'].unique())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The task is to predict the class of an example (Iris-setosa, Iris-versicolor or Iris-virginica) using the values in the other columns ('sepallength', 'sepalwidth', 'petallength', 'petalwidth'). We will store the predictors in the X variable and the target in y." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "X = iris_df.drop(columns=['class'])\n", "y = iris_df['class']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "Someone suggested the following simple rules:\n", "\n", "1. If $petallength < 2.5$, then it's Iris-setosa.\n", "2. If $petallength \\geq 2.5$ and $petalwidth < 1.65$, then it's Iris-versicolor.\n", "3. Otherwise, it's Iris-virginica\n", "\n", "Let's implement them. We will start from the first one." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from decision_rules.classification.rule import ClassificationConclusion\n", "from decision_rules.classification.rule import ClassificationRule\n", "from decision_rules.conditions import ElementaryCondition, CompoundCondition\n", "\n", "rule_1 = ClassificationRule(\n", " premise=CompoundCondition(\n", " subconditions=[\n", " ElementaryCondition(\n", " column_index=X.columns.get_loc('petallength'),\n", " right = 2.5\n", " )\n", " ]\n", " ),\n", " conclusion=ClassificationConclusion(\n", " value='Iris-setosa',\n", " column_name='class',\n", " ),\n", " column_names=X.columns,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We use `ClassificationRule` class to create the rule. Every rule has two parts: premise (e.g. $petallength < 2.5$) and conclusion (e.g. Iris-setosa).\n", "\n", "You can create a premise using the conditions from `decision_rules.conditions`:\n", "\n", "- `NominalCondition`: checks if a value of the attribute is equal to a value, e.g. $x = 1$. Useful for nominal attributes.\n", "- `ElementaryCondition`: checks if a value is inside an interval, e.g. $x \\in [2.3, 3.1)$.\n", "- `CompoundCondition`: a conjunction or alternative of `ElementaryCondition`s, e.g. $x \\in [2.3, 3.1)$ and $y \\in (8, +\\infty)$.\n", "- `AttributesCondition`: checks if a relationship between two attributes is met, e.g. $x < y$.\n", "\n", "In case of this rule, the premise $petallength < 2.5$ can be written as $petallength \\in [-\\infty, 2.5)$, so we can use the `ElementaryCondition`. The `column_index` argument is the index of the column with the relevant attribute (petallength). The arguments `left` and `right` are the boundaries of the interval, their default values are minus and plus infinity respectively. The interval is open by default, we can change that by setting the `left_closed` or `right_colsed` attribute to `True`.\n", "\n", "Currently, the premise needs to be a `CompoundCondition`, so we put that `ElementaryCondition` as a subcondition inside a `CompoundCondition`. `CompoundCondition` has one required argument named `subconditions` which must be a list of `ElementaryCondition` objects.\n", "\n", "The conclusion is a `ClassificationConclusion` object. It accepts two arguments: the predicted value (Iris-setosa) and the column name (class).\n", "\n", "Now, let's create the rule 2. The premise is a conjunction (has two parts joined by \"and\"), so we will use again `CompoundCondition`. This time the `subconditions` list will have two elementary conditions." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "rule_2 = ClassificationRule(\n", " premise=CompoundCondition(\n", " subconditions=[\n", " ElementaryCondition(\n", " column_index=X.columns.get_loc('petallength'),\n", " left = 2.5,\n", " left_closed=True,\n", " ),\n", " ElementaryCondition(\n", " column_index=X.columns.get_loc('petalwidth'),\n", " right = 1.65,\n", " ),\n", " ]\n", " ),\n", " conclusion=ClassificationConclusion(\n", " value='Iris-versicolor',\n", " column_name='class',\n", " ),\n", " column_names=X.columns,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we have all the rules, we can create the rule set. To to this, we use the `ClassificationRuleSet` class. It has one mandatory argument `rules` which is a list of `ClassificationRule` objects" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "from decision_rules.classification.ruleset import ClassificationRuleSet\n", "\n", "ruleset = ClassificationRuleSet(rules=[rule_1, rule_2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We still need to add the 3rd rule (otherwise, it's Iris-virginica). We implement such a rule using the `default_conclusion` property of a ruleset." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "ruleset.default_conclusion = ClassificationConclusion(\n", " value='Iris-virginica',\n", " column_name='class',\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now the rule set is almost ready. After defining the rules, you should call the `update` function. It accepts 3 arguments:\n", "\n", "- a `DataFrame` of predictors (X)\n", "- a `Series` of target values (y)\n", "- a measure of rule quality\n", "\n", "This function calculates also the coverage matrix, which shows which rules cover each row." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [ True, False],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, False],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, False],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, True],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, True],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, True],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, True],\n", " [False, True],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False],\n", " [False, False]])" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from decision_rules.measures import accuracy\n", "coverage_matrix = ruleset.update(X, y, accuracy)\n", "display(coverage_matrix)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ruleset is ready now. Let's see what it will predict for our data stored in X variable." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepallengthsepalwidthpetallengthpetalwidthclasspredictions
05.13.51.40.2Iris-setosaIris-setosa
14.93.01.40.2Iris-setosaIris-setosa
24.73.21.30.2Iris-setosaIris-setosa
34.63.11.50.2Iris-setosaIris-setosa
45.03.61.40.2Iris-setosaIris-setosa
55.43.91.70.4Iris-setosaIris-setosa
64.63.41.40.3Iris-setosaIris-setosa
75.03.41.50.2Iris-setosaIris-setosa
84.42.91.40.2Iris-setosaIris-setosa
94.93.11.50.1Iris-setosaIris-setosa
105.43.71.50.2Iris-setosaIris-setosa
114.83.41.60.2Iris-setosaIris-setosa
124.83.01.40.1Iris-setosaIris-setosa
134.33.01.10.1Iris-setosaIris-setosa
145.84.01.20.2Iris-setosaIris-setosa
155.74.41.50.4Iris-setosaIris-setosa
165.43.91.30.4Iris-setosaIris-setosa
175.13.51.40.3Iris-setosaIris-setosa
185.73.81.70.3Iris-setosaIris-setosa
195.13.81.50.3Iris-setosaIris-setosa
205.43.41.70.2Iris-setosaIris-setosa
215.13.71.50.4Iris-setosaIris-setosa
224.63.61.00.2Iris-setosaIris-setosa
235.13.31.70.5Iris-setosaIris-setosa
244.83.41.90.2Iris-setosaIris-setosa
255.03.01.60.2Iris-setosaIris-setosa
265.03.41.60.4Iris-setosaIris-setosa
275.23.51.50.2Iris-setosaIris-setosa
285.23.41.40.2Iris-setosaIris-setosa
294.73.21.60.2Iris-setosaIris-setosa
304.83.11.60.2Iris-setosaIris-setosa
315.43.41.50.4Iris-setosaIris-setosa
325.24.11.50.1Iris-setosaIris-setosa
335.54.21.40.2Iris-setosaIris-setosa
344.93.11.50.1Iris-setosaIris-setosa
355.03.21.20.2Iris-setosaIris-setosa
365.53.51.30.2Iris-setosaIris-setosa
374.93.11.50.1Iris-setosaIris-setosa
384.43.01.30.2Iris-setosaIris-setosa
395.13.41.50.2Iris-setosaIris-setosa
405.03.51.30.3Iris-setosaIris-setosa
414.52.31.30.3Iris-setosaIris-setosa
424.43.21.30.2Iris-setosaIris-setosa
435.03.51.60.6Iris-setosaIris-setosa
445.13.81.90.4Iris-setosaIris-setosa
454.83.01.40.3Iris-setosaIris-setosa
465.13.81.60.2Iris-setosaIris-setosa
474.63.21.40.2Iris-setosaIris-setosa
485.33.71.50.2Iris-setosaIris-setosa
495.03.31.40.2Iris-setosaIris-setosa
507.03.24.71.4Iris-versicolorIris-versicolor
516.43.24.51.5Iris-versicolorIris-versicolor
526.93.14.91.5Iris-versicolorIris-versicolor
535.52.34.01.3Iris-versicolorIris-versicolor
546.52.84.61.5Iris-versicolorIris-versicolor
555.72.84.51.3Iris-versicolorIris-versicolor
566.33.34.71.6Iris-versicolorIris-versicolor
574.92.43.31.0Iris-versicolorIris-versicolor
586.62.94.61.3Iris-versicolorIris-versicolor
595.22.73.91.4Iris-versicolorIris-versicolor
605.02.03.51.0Iris-versicolorIris-versicolor
615.93.04.21.5Iris-versicolorIris-versicolor
626.02.24.01.0Iris-versicolorIris-versicolor
636.12.94.71.4Iris-versicolorIris-versicolor
645.62.93.61.3Iris-versicolorIris-versicolor
656.73.14.41.4Iris-versicolorIris-versicolor
665.63.04.51.5Iris-versicolorIris-versicolor
675.82.74.11.0Iris-versicolorIris-versicolor
686.22.24.51.5Iris-versicolorIris-versicolor
695.62.53.91.1Iris-versicolorIris-versicolor
705.93.24.81.8Iris-versicolorIris-virginica
716.12.84.01.3Iris-versicolorIris-versicolor
726.32.54.91.5Iris-versicolorIris-versicolor
736.12.84.71.2Iris-versicolorIris-versicolor
746.42.94.31.3Iris-versicolorIris-versicolor
756.63.04.41.4Iris-versicolorIris-versicolor
766.82.84.81.4Iris-versicolorIris-versicolor
776.73.05.01.7Iris-versicolorIris-virginica
786.02.94.51.5Iris-versicolorIris-versicolor
795.72.63.51.0Iris-versicolorIris-versicolor
805.52.43.81.1Iris-versicolorIris-versicolor
815.52.43.71.0Iris-versicolorIris-versicolor
825.82.73.91.2Iris-versicolorIris-versicolor
836.02.75.11.6Iris-versicolorIris-versicolor
845.43.04.51.5Iris-versicolorIris-versicolor
856.03.44.51.6Iris-versicolorIris-versicolor
866.73.14.71.5Iris-versicolorIris-versicolor
876.32.34.41.3Iris-versicolorIris-versicolor
885.63.04.11.3Iris-versicolorIris-versicolor
895.52.54.01.3Iris-versicolorIris-versicolor
905.52.64.41.2Iris-versicolorIris-versicolor
916.13.04.61.4Iris-versicolorIris-versicolor
925.82.64.01.2Iris-versicolorIris-versicolor
935.02.33.31.0Iris-versicolorIris-versicolor
945.62.74.21.3Iris-versicolorIris-versicolor
955.73.04.21.2Iris-versicolorIris-versicolor
965.72.94.21.3Iris-versicolorIris-versicolor
976.22.94.31.3Iris-versicolorIris-versicolor
985.12.53.01.1Iris-versicolorIris-versicolor
995.72.84.11.3Iris-versicolorIris-versicolor
1006.33.36.02.5Iris-virginicaIris-virginica
1015.82.75.11.9Iris-virginicaIris-virginica
1027.13.05.92.1Iris-virginicaIris-virginica
1036.32.95.61.8Iris-virginicaIris-virginica
1046.53.05.82.2Iris-virginicaIris-virginica
1057.63.06.62.1Iris-virginicaIris-virginica
1064.92.54.51.7Iris-virginicaIris-virginica
1077.32.96.31.8Iris-virginicaIris-virginica
1086.72.55.81.8Iris-virginicaIris-virginica
1097.23.66.12.5Iris-virginicaIris-virginica
1106.53.25.12.0Iris-virginicaIris-virginica
1116.42.75.31.9Iris-virginicaIris-virginica
1126.83.05.52.1Iris-virginicaIris-virginica
1135.72.55.02.0Iris-virginicaIris-virginica
1145.82.85.12.4Iris-virginicaIris-virginica
1156.43.25.32.3Iris-virginicaIris-virginica
1166.53.05.51.8Iris-virginicaIris-virginica
1177.73.86.72.2Iris-virginicaIris-virginica
1187.72.66.92.3Iris-virginicaIris-virginica
1196.02.25.01.5Iris-virginicaIris-versicolor
1206.93.25.72.3Iris-virginicaIris-virginica
1215.62.84.92.0Iris-virginicaIris-virginica
1227.72.86.72.0Iris-virginicaIris-virginica
1236.32.74.91.8Iris-virginicaIris-virginica
1246.73.35.72.1Iris-virginicaIris-virginica
1257.23.26.01.8Iris-virginicaIris-virginica
1266.22.84.81.8Iris-virginicaIris-virginica
1276.13.04.91.8Iris-virginicaIris-virginica
1286.42.85.62.1Iris-virginicaIris-virginica
1297.23.05.81.6Iris-virginicaIris-versicolor
1307.42.86.11.9Iris-virginicaIris-virginica
1317.93.86.42.0Iris-virginicaIris-virginica
1326.42.85.62.2Iris-virginicaIris-virginica
1336.32.85.11.5Iris-virginicaIris-versicolor
1346.12.65.61.4Iris-virginicaIris-versicolor
1357.73.06.12.3Iris-virginicaIris-virginica
1366.33.45.62.4Iris-virginicaIris-virginica
1376.43.15.51.8Iris-virginicaIris-virginica
1386.03.04.81.8Iris-virginicaIris-virginica
1396.93.15.42.1Iris-virginicaIris-virginica
1406.73.15.62.4Iris-virginicaIris-virginica
1416.93.15.12.3Iris-virginicaIris-virginica
1425.82.75.11.9Iris-virginicaIris-virginica
1436.83.25.92.3Iris-virginicaIris-virginica
1446.73.35.72.5Iris-virginicaIris-virginica
1456.73.05.22.3Iris-virginicaIris-virginica
1466.32.55.01.9Iris-virginicaIris-virginica
1476.53.05.22.0Iris-virginicaIris-virginica
1486.23.45.42.3Iris-virginicaIris-virginica
1495.93.05.11.8Iris-virginicaIris-virginica
\n", "
" ], "text/plain": [ " sepallength sepalwidth petallength petalwidth class \\\n", "0 5.1 3.5 1.4 0.2 Iris-setosa \n", "1 4.9 3.0 1.4 0.2 Iris-setosa \n", "2 4.7 3.2 1.3 0.2 Iris-setosa \n", "3 4.6 3.1 1.5 0.2 Iris-setosa \n", "4 5.0 3.6 1.4 0.2 Iris-setosa \n", "5 5.4 3.9 1.7 0.4 Iris-setosa \n", "6 4.6 3.4 1.4 0.3 Iris-setosa \n", "7 5.0 3.4 1.5 0.2 Iris-setosa \n", "8 4.4 2.9 1.4 0.2 Iris-setosa \n", "9 4.9 3.1 1.5 0.1 Iris-setosa \n", "10 5.4 3.7 1.5 0.2 Iris-setosa \n", "11 4.8 3.4 1.6 0.2 Iris-setosa \n", "12 4.8 3.0 1.4 0.1 Iris-setosa \n", "13 4.3 3.0 1.1 0.1 Iris-setosa \n", "14 5.8 4.0 1.2 0.2 Iris-setosa \n", "15 5.7 4.4 1.5 0.4 Iris-setosa \n", "16 5.4 3.9 1.3 0.4 Iris-setosa \n", "17 5.1 3.5 1.4 0.3 Iris-setosa \n", "18 5.7 3.8 1.7 0.3 Iris-setosa \n", "19 5.1 3.8 1.5 0.3 Iris-setosa \n", "20 5.4 3.4 1.7 0.2 Iris-setosa \n", "21 5.1 3.7 1.5 0.4 Iris-setosa \n", "22 4.6 3.6 1.0 0.2 Iris-setosa \n", "23 5.1 3.3 1.7 0.5 Iris-setosa \n", "24 4.8 3.4 1.9 0.2 Iris-setosa \n", "25 5.0 3.0 1.6 0.2 Iris-setosa \n", "26 5.0 3.4 1.6 0.4 Iris-setosa \n", "27 5.2 3.5 1.5 0.2 Iris-setosa \n", "28 5.2 3.4 1.4 0.2 Iris-setosa \n", "29 4.7 3.2 1.6 0.2 Iris-setosa \n", "30 4.8 3.1 1.6 0.2 Iris-setosa \n", "31 5.4 3.4 1.5 0.4 Iris-setosa \n", "32 5.2 4.1 1.5 0.1 Iris-setosa \n", "33 5.5 4.2 1.4 0.2 Iris-setosa \n", "34 4.9 3.1 1.5 0.1 Iris-setosa \n", "35 5.0 3.2 1.2 0.2 Iris-setosa \n", "36 5.5 3.5 1.3 0.2 Iris-setosa \n", "37 4.9 3.1 1.5 0.1 Iris-setosa \n", "38 4.4 3.0 1.3 0.2 Iris-setosa \n", "39 5.1 3.4 1.5 0.2 Iris-setosa \n", "40 5.0 3.5 1.3 0.3 Iris-setosa \n", "41 4.5 2.3 1.3 0.3 Iris-setosa \n", "42 4.4 3.2 1.3 0.2 Iris-setosa \n", "43 5.0 3.5 1.6 0.6 Iris-setosa \n", "44 5.1 3.8 1.9 0.4 Iris-setosa \n", "45 4.8 3.0 1.4 0.3 Iris-setosa \n", "46 5.1 3.8 1.6 0.2 Iris-setosa \n", "47 4.6 3.2 1.4 0.2 Iris-setosa \n", "48 5.3 3.7 1.5 0.2 Iris-setosa \n", "49 5.0 3.3 1.4 0.2 Iris-setosa \n", "50 7.0 3.2 4.7 1.4 Iris-versicolor \n", "51 6.4 3.2 4.5 1.5 Iris-versicolor \n", "52 6.9 3.1 4.9 1.5 Iris-versicolor \n", "53 5.5 2.3 4.0 1.3 Iris-versicolor \n", "54 6.5 2.8 4.6 1.5 Iris-versicolor \n", "55 5.7 2.8 4.5 1.3 Iris-versicolor \n", "56 6.3 3.3 4.7 1.6 Iris-versicolor \n", "57 4.9 2.4 3.3 1.0 Iris-versicolor \n", "58 6.6 2.9 4.6 1.3 Iris-versicolor \n", "59 5.2 2.7 3.9 1.4 Iris-versicolor \n", "60 5.0 2.0 3.5 1.0 Iris-versicolor \n", "61 5.9 3.0 4.2 1.5 Iris-versicolor \n", "62 6.0 2.2 4.0 1.0 Iris-versicolor \n", "63 6.1 2.9 4.7 1.4 Iris-versicolor \n", "64 5.6 2.9 3.6 1.3 Iris-versicolor \n", "65 6.7 3.1 4.4 1.4 Iris-versicolor \n", "66 5.6 3.0 4.5 1.5 Iris-versicolor \n", "67 5.8 2.7 4.1 1.0 Iris-versicolor \n", "68 6.2 2.2 4.5 1.5 Iris-versicolor \n", "69 5.6 2.5 3.9 1.1 Iris-versicolor \n", "70 5.9 3.2 4.8 1.8 Iris-versicolor \n", "71 6.1 2.8 4.0 1.3 Iris-versicolor \n", "72 6.3 2.5 4.9 1.5 Iris-versicolor \n", "73 6.1 2.8 4.7 1.2 Iris-versicolor \n", "74 6.4 2.9 4.3 1.3 Iris-versicolor \n", "75 6.6 3.0 4.4 1.4 Iris-versicolor \n", "76 6.8 2.8 4.8 1.4 Iris-versicolor \n", "77 6.7 3.0 5.0 1.7 Iris-versicolor \n", "78 6.0 2.9 4.5 1.5 Iris-versicolor \n", "79 5.7 2.6 3.5 1.0 Iris-versicolor \n", "80 5.5 2.4 3.8 1.1 Iris-versicolor \n", "81 5.5 2.4 3.7 1.0 Iris-versicolor \n", "82 5.8 2.7 3.9 1.2 Iris-versicolor \n", "83 6.0 2.7 5.1 1.6 Iris-versicolor \n", "84 5.4 3.0 4.5 1.5 Iris-versicolor \n", "85 6.0 3.4 4.5 1.6 Iris-versicolor \n", "86 6.7 3.1 4.7 1.5 Iris-versicolor \n", "87 6.3 2.3 4.4 1.3 Iris-versicolor \n", "88 5.6 3.0 4.1 1.3 Iris-versicolor \n", "89 5.5 2.5 4.0 1.3 Iris-versicolor \n", "90 5.5 2.6 4.4 1.2 Iris-versicolor \n", "91 6.1 3.0 4.6 1.4 Iris-versicolor \n", "92 5.8 2.6 4.0 1.2 Iris-versicolor \n", "93 5.0 2.3 3.3 1.0 Iris-versicolor \n", "94 5.6 2.7 4.2 1.3 Iris-versicolor \n", "95 5.7 3.0 4.2 1.2 Iris-versicolor \n", "96 5.7 2.9 4.2 1.3 Iris-versicolor \n", "97 6.2 2.9 4.3 1.3 Iris-versicolor \n", "98 5.1 2.5 3.0 1.1 Iris-versicolor \n", "99 5.7 2.8 4.1 1.3 Iris-versicolor \n", "100 6.3 3.3 6.0 2.5 Iris-virginica \n", "101 5.8 2.7 5.1 1.9 Iris-virginica \n", "102 7.1 3.0 5.9 2.1 Iris-virginica \n", "103 6.3 2.9 5.6 1.8 Iris-virginica \n", "104 6.5 3.0 5.8 2.2 Iris-virginica \n", "105 7.6 3.0 6.6 2.1 Iris-virginica \n", "106 4.9 2.5 4.5 1.7 Iris-virginica \n", "107 7.3 2.9 6.3 1.8 Iris-virginica \n", "108 6.7 2.5 5.8 1.8 Iris-virginica \n", "109 7.2 3.6 6.1 2.5 Iris-virginica \n", "110 6.5 3.2 5.1 2.0 Iris-virginica \n", "111 6.4 2.7 5.3 1.9 Iris-virginica \n", "112 6.8 3.0 5.5 2.1 Iris-virginica \n", "113 5.7 2.5 5.0 2.0 Iris-virginica \n", "114 5.8 2.8 5.1 2.4 Iris-virginica \n", "115 6.4 3.2 5.3 2.3 Iris-virginica \n", "116 6.5 3.0 5.5 1.8 Iris-virginica \n", "117 7.7 3.8 6.7 2.2 Iris-virginica \n", "118 7.7 2.6 6.9 2.3 Iris-virginica \n", "119 6.0 2.2 5.0 1.5 Iris-virginica \n", "120 6.9 3.2 5.7 2.3 Iris-virginica \n", "121 5.6 2.8 4.9 2.0 Iris-virginica \n", "122 7.7 2.8 6.7 2.0 Iris-virginica \n", "123 6.3 2.7 4.9 1.8 Iris-virginica \n", "124 6.7 3.3 5.7 2.1 Iris-virginica \n", "125 7.2 3.2 6.0 1.8 Iris-virginica \n", "126 6.2 2.8 4.8 1.8 Iris-virginica \n", "127 6.1 3.0 4.9 1.8 Iris-virginica \n", "128 6.4 2.8 5.6 2.1 Iris-virginica \n", "129 7.2 3.0 5.8 1.6 Iris-virginica \n", "130 7.4 2.8 6.1 1.9 Iris-virginica \n", "131 7.9 3.8 6.4 2.0 Iris-virginica \n", "132 6.4 2.8 5.6 2.2 Iris-virginica \n", "133 6.3 2.8 5.1 1.5 Iris-virginica \n", "134 6.1 2.6 5.6 1.4 Iris-virginica \n", "135 7.7 3.0 6.1 2.3 Iris-virginica \n", "136 6.3 3.4 5.6 2.4 Iris-virginica \n", "137 6.4 3.1 5.5 1.8 Iris-virginica \n", "138 6.0 3.0 4.8 1.8 Iris-virginica \n", "139 6.9 3.1 5.4 2.1 Iris-virginica \n", "140 6.7 3.1 5.6 2.4 Iris-virginica \n", "141 6.9 3.1 5.1 2.3 Iris-virginica \n", "142 5.8 2.7 5.1 1.9 Iris-virginica \n", "143 6.8 3.2 5.9 2.3 Iris-virginica \n", "144 6.7 3.3 5.7 2.5 Iris-virginica \n", "145 6.7 3.0 5.2 2.3 Iris-virginica \n", "146 6.3 2.5 5.0 1.9 Iris-virginica \n", "147 6.5 3.0 5.2 2.0 Iris-virginica \n", "148 6.2 3.4 5.4 2.3 Iris-virginica \n", "149 5.9 3.0 5.1 1.8 Iris-virginica \n", "\n", " predictions \n", "0 Iris-setosa \n", "1 Iris-setosa \n", "2 Iris-setosa \n", "3 Iris-setosa \n", "4 Iris-setosa \n", "5 Iris-setosa \n", "6 Iris-setosa \n", "7 Iris-setosa \n", "8 Iris-setosa \n", "9 Iris-setosa \n", "10 Iris-setosa \n", "11 Iris-setosa \n", "12 Iris-setosa \n", "13 Iris-setosa \n", "14 Iris-setosa \n", "15 Iris-setosa \n", "16 Iris-setosa \n", "17 Iris-setosa \n", "18 Iris-setosa \n", "19 Iris-setosa \n", "20 Iris-setosa \n", "21 Iris-setosa \n", "22 Iris-setosa \n", "23 Iris-setosa \n", "24 Iris-setosa \n", "25 Iris-setosa \n", "26 Iris-setosa \n", "27 Iris-setosa \n", "28 Iris-setosa \n", "29 Iris-setosa \n", "30 Iris-setosa \n", "31 Iris-setosa \n", "32 Iris-setosa \n", "33 Iris-setosa \n", "34 Iris-setosa \n", "35 Iris-setosa \n", "36 Iris-setosa \n", "37 Iris-setosa \n", "38 Iris-setosa \n", "39 Iris-setosa \n", "40 Iris-setosa \n", "41 Iris-setosa \n", "42 Iris-setosa \n", "43 Iris-setosa \n", "44 Iris-setosa \n", "45 Iris-setosa \n", "46 Iris-setosa \n", "47 Iris-setosa \n", "48 Iris-setosa \n", "49 Iris-setosa \n", "50 Iris-versicolor \n", "51 Iris-versicolor \n", "52 Iris-versicolor \n", "53 Iris-versicolor \n", "54 Iris-versicolor \n", "55 Iris-versicolor \n", "56 Iris-versicolor \n", "57 Iris-versicolor \n", "58 Iris-versicolor \n", "59 Iris-versicolor \n", "60 Iris-versicolor \n", "61 Iris-versicolor \n", "62 Iris-versicolor \n", "63 Iris-versicolor \n", "64 Iris-versicolor \n", "65 Iris-versicolor \n", "66 Iris-versicolor \n", "67 Iris-versicolor \n", "68 Iris-versicolor \n", "69 Iris-versicolor \n", "70 Iris-virginica \n", "71 Iris-versicolor \n", "72 Iris-versicolor \n", "73 Iris-versicolor \n", "74 Iris-versicolor \n", "75 Iris-versicolor \n", "76 Iris-versicolor \n", "77 Iris-virginica \n", "78 Iris-versicolor \n", "79 Iris-versicolor \n", "80 Iris-versicolor \n", "81 Iris-versicolor \n", "82 Iris-versicolor \n", "83 Iris-versicolor \n", "84 Iris-versicolor \n", "85 Iris-versicolor \n", "86 Iris-versicolor \n", "87 Iris-versicolor \n", "88 Iris-versicolor \n", "89 Iris-versicolor \n", "90 Iris-versicolor \n", "91 Iris-versicolor \n", "92 Iris-versicolor \n", "93 Iris-versicolor \n", "94 Iris-versicolor \n", "95 Iris-versicolor \n", "96 Iris-versicolor \n", "97 Iris-versicolor \n", "98 Iris-versicolor \n", "99 Iris-versicolor \n", "100 Iris-virginica \n", "101 Iris-virginica \n", "102 Iris-virginica \n", "103 Iris-virginica \n", "104 Iris-virginica \n", "105 Iris-virginica \n", "106 Iris-virginica \n", "107 Iris-virginica \n", "108 Iris-virginica \n", "109 Iris-virginica \n", "110 Iris-virginica \n", "111 Iris-virginica \n", "112 Iris-virginica \n", "113 Iris-virginica \n", "114 Iris-virginica \n", "115 Iris-virginica \n", "116 Iris-virginica \n", "117 Iris-virginica \n", "118 Iris-virginica \n", "119 Iris-versicolor \n", "120 Iris-virginica \n", "121 Iris-virginica \n", "122 Iris-virginica \n", "123 Iris-virginica \n", "124 Iris-virginica \n", "125 Iris-virginica \n", "126 Iris-virginica \n", "127 Iris-virginica \n", "128 Iris-virginica \n", "129 Iris-versicolor \n", "130 Iris-virginica \n", "131 Iris-virginica \n", "132 Iris-virginica \n", "133 Iris-versicolor \n", "134 Iris-versicolor \n", "135 Iris-virginica \n", "136 Iris-virginica \n", "137 Iris-virginica \n", "138 Iris-virginica \n", "139 Iris-virginica \n", "140 Iris-virginica \n", "141 Iris-virginica \n", "142 Iris-virginica \n", "143 Iris-virginica \n", "144 Iris-virginica \n", "145 Iris-virginica \n", "146 Iris-virginica \n", "147 Iris-virginica \n", "148 Iris-virginica \n", "149 Iris-virginica " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# The predictions for each row in X will be stored in the y_pred array.\n", "y_pred = ruleset.predict(X)\n", "# The compare_df will show us the true class and the prediction for each example.\n", "compare_df = iris_df.copy()\n", "compare_df['predictions'] = y_pred\n", "with pd.option_context('display.max_rows', 150):\n", " display(compare_df)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will check now how well our rules perform on the data using various metrics. The `calculate_for_classification` function computes the typical classification metrics, such as accuracy, f1 or Cohen kappa." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'type_of_problem': 'classification',\n", " 'general': {'Balanced_accuracy': 0.96,\n", " 'Accuracy': 0.96,\n", " 'Cohen_kappa': 0.94,\n", " 'F1_micro': 0.96,\n", " 'F1_macro': 0.9599839935974389,\n", " 'F1_weighted': 0.9599839935974391,\n", " 'G_mean_micro': 0.9699484522385713,\n", " 'G_mean_macro': 0.9699484522385713,\n", " 'G_mean_weighted': 0.9699484522385713,\n", " 'Recall_micro': 0.96,\n", " 'Recall_macro': 0.96,\n", " 'Recall_weighted': 0.96,\n", " 'Specificity': 1.0,\n", " 'Confusion_matrix': {'classes': ['Iris-setosa',\n", " 'Iris-versicolor',\n", " 'Iris-virginica'],\n", " 'Iris-setosa': [50, 0, 0],\n", " 'Iris-versicolor': [0, 48, 2],\n", " 'Iris-virginica': [0, 4, 46]}},\n", " 'for_classes': {'Iris-setosa': {'TP': 50,\n", " 'FP': 0,\n", " 'TN': 100,\n", " 'FN': 0,\n", " 'Recall': 1.0,\n", " 'Specificity': 1.0,\n", " 'F1_score': 1.0,\n", " 'G_mean': 1.0,\n", " 'MCC': 1.0,\n", " 'PPV': 1.0,\n", " 'NPV': 1.0,\n", " 'LR_plus': 0,\n", " 'LR_minus': 0.0,\n", " 'Odd_ratio': 0,\n", " 'Relative_risk': 0,\n", " 'Confusion_matrix': {'classes': ['Iris-setosa', 'other'],\n", " 'Iris-setosa': [50, 0],\n", " 'other': [0, 100]}},\n", " 'Iris-versicolor': {'TP': 48,\n", " 'FP': 4,\n", " 'TN': 96,\n", " 'FN': 2,\n", " 'Recall': 0.96,\n", " 'Specificity': 0.96,\n", " 'F1_score': 0.9411764705882353,\n", " 'G_mean': 0.96,\n", " 'MCC': 0.9112931795128765,\n", " 'PPV': 0.9230769230769231,\n", " 'NPV': 0.9795918367346939,\n", " 'LR_plus': 23.99999999999998,\n", " 'LR_minus': 0.041666666666666706,\n", " 'Odd_ratio': 576.0,\n", " 'Relative_risk': 45.23076923076923,\n", " 'Confusion_matrix': {'classes': ['Iris-versicolor', 'other'],\n", " 'Iris-versicolor': [48, 2],\n", " 'other': [4, 96]}},\n", " 'Iris-virginica': {'TP': 46,\n", " 'FP': 2,\n", " 'TN': 98,\n", " 'FN': 4,\n", " 'Recall': 0.92,\n", " 'Specificity': 0.98,\n", " 'F1_score': 0.9387755102040817,\n", " 'G_mean': 0.9495261976375375,\n", " 'MCC': 0.9095085938862487,\n", " 'PPV': 0.9583333333333334,\n", " 'NPV': 0.9607843137254902,\n", " 'LR_plus': 45.999999999999964,\n", " 'LR_minus': 0.08163265306122446,\n", " 'Odd_ratio': 563.5,\n", " 'Relative_risk': 24.4375,\n", " 'Confusion_matrix': {'classes': ['Iris-virginica', 'other'],\n", " 'Iris-virginica': [46, 4],\n", " 'other': [2, 98]}}}}" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from decision_rules.classification.prediction_indicators import calculate_for_classification\n", "metrics = calculate_for_classification(y, y_pred)\n", "display(metrics)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `calculate_rules_metrics` function of a ruleset object computes metrics describing each of the rules in the rule set. The full description of the metrics can be found in the [documentation of ruleminer](https://github.com/ruleminer/ruleminer/wiki/10-Description-of-the-results-obtained)." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Rule fd0d78eb-aea8-4ab0-9704-6999d87573c2\n", "{'p': 50, 'n': 0, 'P': 50, 'N': 100, 'p_unique': 50, 'n_unique': 50, 'support': 50, 'conditions_count': 1, 'precision': 1.0, 'coverage': 1.0, 'C2': 1.0, 'RSS': 1.0, 'correlation': 1.0, 'lift': 3.0, 'p_value': 4.968040370318492e-41, 'TP': 50, 'FP': 0, 'TN': 100, 'FN': 0, 'sensitivity': 1.0, 'specificity': 1.0, 'negative_predictive_value': 1.0, 'odds_ratio': inf, 'relative_risk': inf, 'lr+': inf, 'lr-': 0.0}\n", "Rule 1cd50058-f754-4d69-ab42-5690bdccfa1b\n", "{'p': 48, 'n': 4, 'P': 50, 'N': 100, 'p_unique': 48, 'n_unique': 48, 'support': 52, 'conditions_count': 2, 'precision': 0.9230769230769231, 'coverage': 0.96, 'C2': 0.8669230769230769, 'RSS': 0.9199999999999999, 'correlation': 0.9112931795128765, 'lift': 2.769230769230769, 'p_value': 6.403421751602081e-32, 'TP': 48, 'FP': 4, 'TN': 96, 'FN': 2, 'sensitivity': 0.96, 'specificity': 0.96, 'negative_predictive_value': 0.9795918367346939, 'odds_ratio': 576.0, 'relative_risk': 45.23076923076923, 'lr+': 23.99999999999998, 'lr-': 0.041666666666666706}\n" ] } ], "source": [ "metrics = ruleset.calculate_rules_metrics(X, y)\n", "for rule_id, metrics in metrics.items():\n", " print('Rule', rule_id)\n", " print(metrics)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `calculate_ruleset_stats` function returns some general statistics regarding the rules present in the rule set." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'rules_count': 2, 'avg_conditions_count': 1.5, 'avg_precision': 0.96, 'avg_coverage': 0.98, 'total_conditions_count': 3}\n" ] } ], "source": [ "general_stats = ruleset.calculate_ruleset_stats()\n", "print(general_stats)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can serialize the ruleset into a dict using `JSONSerializer.serialize`. The dict can be later stored in a string or in a text file." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'meta': {'attributes': ['sepallength',\n", " 'sepalwidth',\n", " 'petallength',\n", " 'petalwidth'],\n", " 'decision_attribute': 'class',\n", " 'decision_attribute_distribution': {'Iris-setosa': 50,\n", " 'Iris-versicolor': 50,\n", " 'Iris-virginica': 50}},\n", " 'rules': [{'uuid': 'fd0d78eb-aea8-4ab0-9704-6999d87573c2',\n", " 'string': 'IF petallength < 2.50 THEN class = Iris-setosa',\n", " 'premise': {'type': 'compound',\n", " 'operator': 'CONJUNCTION',\n", " 'subconditions': [{'type': 'elementary_numerical',\n", " 'attributes': [2],\n", " 'negated': False,\n", " 'left': None,\n", " 'right': 2.5,\n", " 'left_closed': False,\n", " 'right_closed': False}]},\n", " 'conclusion': {'value': 'Iris-setosa'},\n", " 'coverage': {'p': 50, 'n': 0, 'P': 50, 'N': 100}},\n", " {'uuid': '1cd50058-f754-4d69-ab42-5690bdccfa1b',\n", " 'string': 'IF petallength >= 2.50 AND petalwidth < 1.65 THEN class = Iris-versicolor',\n", " 'premise': {'type': 'compound',\n", " 'operator': 'CONJUNCTION',\n", " 'subconditions': [{'type': 'elementary_numerical',\n", " 'attributes': [2],\n", " 'negated': False,\n", " 'left': 2.5,\n", " 'right': None,\n", " 'left_closed': True,\n", " 'right_closed': False},\n", " {'type': 'elementary_numerical',\n", " 'attributes': [3],\n", " 'negated': False,\n", " 'left': None,\n", " 'right': 1.65,\n", " 'left_closed': False,\n", " 'right_closed': False}]},\n", " 'conclusion': {'value': 'Iris-versicolor'},\n", " 'coverage': {'p': 48, 'n': 4, 'P': 50, 'N': 100}}]}" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import os\n", "import json\n", "from decision_rules.serialization import JSONSerializer\n", "\n", "OUTPUT_DIR = 'output'\n", "RULESET_FILENAME = 'manual_iris.json'\n", "os.makedirs(OUTPUT_DIR, exist_ok=True)\n", "ruleset_path = os.path.join(OUTPUT_DIR, RULESET_FILENAME)\n", "# Serialize the ruleset\n", "ruleset_dict = JSONSerializer.serialize(ruleset)\n", "display(ruleset_dict)\n", "# Save to JSON\n", "with open(ruleset_path, 'w') as fp:\n", " json.dump(ruleset_dict, fp)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The ruleset can be loaded using `JSONSerializer.deserialize`" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "with open(ruleset_path) as fp:\n", " reloaded_json = json.load(fp)\n", "reloaded_ruleset = JSONSerializer.deserialize(reloaded_json, ClassificationRuleSet)\n", "assert reloaded_ruleset == ruleset" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before using some of the functions of the deserialized ruleset, it may be necessary to call the `update` function. After that the object will be ready for prediction." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array(['Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n", " 'Iris-setosa', 'Iris-setosa', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-virginica', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-virginica', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-versicolor',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-versicolor', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-versicolor',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-versicolor', 'Iris-versicolor', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica', 'Iris-virginica',\n", " 'Iris-virginica', 'Iris-virginica'], dtype='