plesna/notebooks/auto_tagging.ipynb

2555 lines
149 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "96263cc4-e4f1-4f42-94cb-14b2d2d35302",
"metadata": {},
"source": [
"# Automatic tagging"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "a6d0b19f-9d89-4260-8662-a0f5683d0ec2",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"from pathlib import Path\n",
"from sklearn.pipeline import Pipeline\n",
"from matplotlib import pyplot as plt "
]
},
{
"cell_type": "markdown",
"id": "1585b7a5-d0b9-4781-accd-ee36dddd7bae",
"metadata": {},
"source": [
"## Import des données"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "0751d414-f28e-4e9a-9151-3a1dc1b05f3c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[PosixPath('../PLESNA Compta SYSTEM/staging/CRG/2020.csv'),\n",
" PosixPath('../PLESNA Compta SYSTEM/staging/CRG/2018.csv'),\n",
" PosixPath('../PLESNA Compta SYSTEM/staging/CRG/2022.csv'),\n",
" PosixPath('../PLESNA Compta SYSTEM/staging/CRG/2021.csv'),\n",
" PosixPath('../PLESNA Compta SYSTEM/staging/CRG/2023.csv'),\n",
" PosixPath('../PLESNA Compta SYSTEM/staging/CRG/2019.csv'),\n",
" PosixPath('../PLESNA Compta SYSTEM/staging/CRG/2017.csv')]"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"staging_path = Path(\"../PLESNA Compta SYSTEM/staging/CRG/\")\n",
"assert staging_path.exists()\n",
"files = list(staging_path.glob(\"*.csv\"))\n",
"files"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "f88989ca-968b-4c97-849b-ef12ab24f0ee",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Régie</th>\n",
" <th>Immeuble</th>\n",
" <th>Porte</th>\n",
" <th>Lot</th>\n",
" <th>Année</th>\n",
" <th>Mois</th>\n",
" <th>Catégorie</th>\n",
" <th>Fournisseur</th>\n",
" <th>Libellé</th>\n",
" <th>Débit</th>\n",
" <th>Crédit</th>\n",
" <th>Impact</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Imi Gérance</td>\n",
" <td>B</td>\n",
" <td>9</td>\n",
" <td>B09</td>\n",
" <td>2020</td>\n",
" <td>1</td>\n",
" <td>Loyer Charge</td>\n",
" <td>NaN</td>\n",
" <td>Règl. Loyer 01/2020</td>\n",
" <td>0.0</td>\n",
" <td>100.48</td>\n",
" <td>100.48</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Imi Gérance</td>\n",
" <td>S</td>\n",
" <td>5</td>\n",
" <td>S05</td>\n",
" <td>2020</td>\n",
" <td>1</td>\n",
" <td>Loyer Charge</td>\n",
" <td>NaN</td>\n",
" <td>Règl. Prov. Char 01/2020</td>\n",
" <td>0.0</td>\n",
" <td>191.00</td>\n",
" <td>191.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Imi Gérance</td>\n",
" <td>S</td>\n",
" <td>5</td>\n",
" <td>S05</td>\n",
" <td>2020</td>\n",
" <td>1</td>\n",
" <td>Loyer Charge</td>\n",
" <td>NaN</td>\n",
" <td>Règl. Loyer 01/2020</td>\n",
" <td>0.0</td>\n",
" <td>745.39</td>\n",
" <td>745.39</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Imi Gérance</td>\n",
" <td>S</td>\n",
" <td>2</td>\n",
" <td>S02</td>\n",
" <td>2020</td>\n",
" <td>1</td>\n",
" <td>Loyer Charge</td>\n",
" <td>NaN</td>\n",
" <td>Règl. Prov. Char 01/2020</td>\n",
" <td>0.0</td>\n",
" <td>519.00</td>\n",
" <td>519.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Imi Gérance</td>\n",
" <td>S</td>\n",
" <td>2</td>\n",
" <td>S02</td>\n",
" <td>2020</td>\n",
" <td>1</td>\n",
" <td>Loyer Charge</td>\n",
" <td>NaN</td>\n",
" <td>Règl. Loyer 01 à 03/2020</td>\n",
" <td>0.0</td>\n",
" <td>3473.79</td>\n",
" <td>3473.79</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Régie Immeuble Porte Lot Année Mois Catégorie Fournisseur \\\n",
"0 Imi Gérance B 9 B09 2020 1 Loyer Charge NaN \n",
"1 Imi Gérance S 5 S05 2020 1 Loyer Charge NaN \n",
"2 Imi Gérance S 5 S05 2020 1 Loyer Charge NaN \n",
"3 Imi Gérance S 2 S02 2020 1 Loyer Charge NaN \n",
"4 Imi Gérance S 2 S02 2020 1 Loyer Charge NaN \n",
"\n",
" Libellé Débit Crédit Impact \n",
"0 Règl. Loyer 01/2020 0.0 100.48 100.48 \n",
"1 Règl. Prov. Char 01/2020 0.0 191.00 191.00 \n",
"2 Règl. Loyer 01/2020 0.0 745.39 745.39 \n",
"3 Règl. Prov. Char 01/2020 0.0 519.00 519.00 \n",
"4 Règl. Loyer 01 à 03/2020 0.0 3473.79 3473.79 "
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dfs = []\n",
"for file in files:\n",
" dfs.append(pd.read_csv(file))\n",
"df = pd.concat(dfs)\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "012dcdaf-83de-44e3-b480-c5498421dc8f",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Régie</th>\n",
" <th>Immeuble</th>\n",
" <th>Porte</th>\n",
" <th>Lot</th>\n",
" <th>Année</th>\n",
" <th>Mois</th>\n",
" <th>Catégorie</th>\n",
" <th>Fournisseur</th>\n",
" <th>Libellé</th>\n",
" <th>Débit</th>\n",
" <th>Crédit</th>\n",
" <th>Impact</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Imi Gérance</td>\n",
" <td>B</td>\n",
" <td>9</td>\n",
" <td>B09</td>\n",
" <td>2020</td>\n",
" <td>1</td>\n",
" <td>Loyer Charge</td>\n",
" <td></td>\n",
" <td>Règl. Loyer 01/2020</td>\n",
" <td>0.0</td>\n",
" <td>100.48</td>\n",
" <td>100.48</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Imi Gérance</td>\n",
" <td>S</td>\n",
" <td>5</td>\n",
" <td>S05</td>\n",
" <td>2020</td>\n",
" <td>1</td>\n",
" <td>Loyer Charge</td>\n",
" <td></td>\n",
" <td>Règl. Prov. Char 01/2020</td>\n",
" <td>0.0</td>\n",
" <td>191.00</td>\n",
" <td>191.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Imi Gérance</td>\n",
" <td>S</td>\n",
" <td>5</td>\n",
" <td>S05</td>\n",
" <td>2020</td>\n",
" <td>1</td>\n",
" <td>Loyer Charge</td>\n",
" <td></td>\n",
" <td>Règl. Loyer 01/2020</td>\n",
" <td>0.0</td>\n",
" <td>745.39</td>\n",
" <td>745.39</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Imi Gérance</td>\n",
" <td>S</td>\n",
" <td>2</td>\n",
" <td>S02</td>\n",
" <td>2020</td>\n",
" <td>1</td>\n",
" <td>Loyer Charge</td>\n",
" <td></td>\n",
" <td>Règl. Prov. Char 01/2020</td>\n",
" <td>0.0</td>\n",
" <td>519.00</td>\n",
" <td>519.00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Imi Gérance</td>\n",
" <td>S</td>\n",
" <td>2</td>\n",
" <td>S02</td>\n",
" <td>2020</td>\n",
" <td>1</td>\n",
" <td>Loyer Charge</td>\n",
" <td></td>\n",
" <td>Règl. Loyer 01 à 03/2020</td>\n",
" <td>0.0</td>\n",
" <td>3473.79</td>\n",
" <td>3473.79</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Régie Immeuble Porte Lot Année Mois Catégorie Fournisseur \\\n",
"0 Imi Gérance B 9 B09 2020 1 Loyer Charge \n",
"1 Imi Gérance S 5 S05 2020 1 Loyer Charge \n",
"2 Imi Gérance S 5 S05 2020 1 Loyer Charge \n",
"3 Imi Gérance S 2 S02 2020 1 Loyer Charge \n",
"4 Imi Gérance S 2 S02 2020 1 Loyer Charge \n",
"\n",
" Libellé Débit Crédit Impact \n",
"0 Règl. Loyer 01/2020 0.0 100.48 100.48 \n",
"1 Règl. Prov. Char 01/2020 0.0 191.00 191.00 \n",
"2 Règl. Loyer 01/2020 0.0 745.39 745.39 \n",
"3 Règl. Prov. Char 01/2020 0.0 519.00 519.00 \n",
"4 Règl. Loyer 01 à 03/2020 0.0 3473.79 3473.79 "
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = df[~df[\"Libellé\"].isna()]\n",
"df = df.assign(\n",
" Fournisseur = df[\"Fournisseur\"].fillna(\"\")\n",
")\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "396257d6-77bc-4fc7-9347-29698e1d2399",
"metadata": {},
"outputs": [],
"source": [
"X = df[\"Libellé\"]# + df[\"Fournisseur\"]\n",
"y = df[\"Catégorie\"]"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "5c63ad34-5fe9-41ab-8a34-c9a6003f77e3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"31929\n",
"5857 Honoraires Bien COP33M- 15\n",
"5858 Honoraires Bien COP33M- 16\n",
"5859 Honoraires Bien COP33M- 17\n",
"5860 Honoraires Bien COP33M- 18\n",
"5861 Honoraires Bien COP33M- 19\n",
"Name: Libellé, dtype: object\n"
]
}
],
"source": [
"print(len(X))\n",
"print(X.tail())"
]
},
{
"cell_type": "markdown",
"id": "273daee3-b0e2-4adf-8c0a-b1152e139abb",
"metadata": {},
"source": [
"## Exploration de l'actuel"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "76fa04a7-7087-4af3-a05d-e5de591f1cd2",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<Axes: xlabel='Catégorie'>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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md4x/fz8EBkZ+dq2ZGRkIC0tTW8hIiIibXrvMznv49mzZxg/fjy6du0KW1tbaf3w4cNRvXp1FC5cGMeOHcPEiRORlJSEBQsWAACSk5Ph7u6udyxHR0dpm4ODA5KTk6V1ufdJTk5+bXtmz56NqVOnyvX0iIiI6F9MsZDz4sULdOrUCUIIrFy5Um9bYGCg9G8fHx+Ympris88+w+zZs2FmZqZUkzBx4kS92mlpaXBxcVGsHhEREalHkZCTE3Bu3ryJ/fv3653FyU/t2rWRmZmJGzduoHz58ihRogTu3r2rt0/O45x+PK/b53X9fADAzMxM0RBFRERE/x6y98nJCTjx8fHYt28fihQp8tafiY6OhpGREYoXLw4A8PX1RUREBF68eCHtExYWhvLly8PBwUHaJzw8XO84YWFh8PX1lfHZEBERUUH13mdy0tPTkZCQID2+fv06oqOjUbhwYTg5OeF///sfzpw5gx07diArK0vqI1O4cGGYmpoiMjISJ06cQOPGjWFjY4PIyEiMGjUK3bt3lwJMt27dMHXqVAQEBGD8+PGIjY3F4sWLsXDhQqnuiBEj0LBhQ8yfPx+tW7fGpk2bcPr0ab3bzImIiOi/SyeEEO/zAwcPHkTjxo3zrO/VqxemTJmSp8NwjgMHDqBRo0Y4c+YMBg8ejLi4OGRkZMDd3R09evRAYGCg3qWkc+fOYciQITh16hSKFi2KYcOGYfz48XrH/PHHHzFp0iTcuHEDZcuWxdy5c9GqVat3fi5paWmws7PDw4cP872k5jZh5zsfK7cbc1r/rZ8jIiKit3vb53eO9w45WsKQQ0REVPC8a8jh3FVERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEnvHXIiIiLQpk0bODs7Q6fTYdu2bXrbhRAICgqCk5MT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mD9/PgCgYsWKOHLkCBYuXAg/Pz8lnhIREREVMIqcyYmPj4ezszM8PDzg7++PxMREAEBUVBRevHiBZs2aSftWqFABpUuXRmRkJAAgMjIS3t7ecHR0lPbx8/NDWloaLly4IO2T+xg5++Qc43UyMjKQlpamtxAREZE2yR5yateujZCQEOzevRsrV67E9evXUb9+fTx69AjJyckwNTWFvb293s84OjoiOTkZAJCcnKwXcHK252x70z5paWl4+vTpa9s2e/Zs2NnZSYuLi8s/fbpERET0LyX75aqWLVtK//bx8UHt2rXh6uqKLVu2wMLCQu5y72XixIkIDAyUHqelpTHoEBERaZTit5Db29ujXLlySEhIQIkSJfD8+XOkpqbq7XP37l2pD0+JEiXy3G2V8/ht+9ja2r4xSJmZmcHW1lZvISIiIm1SPOSkp6fj6tWrcHJyQo0aNVCoUCGEh4dL2y9fvozExET4+voCAHx9fXH+/Hncu3dP2icsLAy2trbw8vKS9sl9jJx9co5BREREJHvIGTNmDA4dOoQbN27g2LFj6NChA4yNjdG1a1fY2dkhICAAgYGBOHDgAKKiotCnTx/4+vqiTp06AIDmzZvDy8sLPXr0QExMDPbs2YNJkyZhyJAhMDMzAwAMHDgQ165dw7hx4xAXF4cVK1Zgy5YtGDVqlNxPh4iIiAoo2fvk3L59G127dsX9+/dRrFgxfPjhhzh+/DiKFSsGAFi4cCGMjIzQsWNHZGRkwM/PDytWrJB+3tjYGDt27MCgQYPg6+sLKysr9OrVC9OmTZP2cXd3x86dOzFq1CgsXrwYpUqVwurVq3n7OBEREUl0QgihdiPUkpaWBjs7Ozx8+DDf/jluE3b+rePemNP6b7fp79b8p3WJiIgKird9fufg3FVERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5REREpEkMOURERKRJDDlERESkSQw5RERE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S5bA19cXnp6eePHiBZYuXYpr167hu+++Q3BwsN4x3NzckJ6ejvDwcPz111948uQJypUrB39/f/Ts2RNbt27F9evXcfLkScyePRs7d+4EAAwbNgy7du3CggULEB8fj2+++Qa///673lg6Y8eORUhICFauXIn4+HgsWLAAW7duxZgxY97reY4fPx7Hjh3D0KFDER0djfj4ePz6668YOnToP/8lEtE/o3anICLSrj/++EMMGTJEuLq6ClNTU1GyZEnRtm1bceDAASGEEAsWLBBOTk7CwsJC+Pn5idDQUL1OvUIIMXDgQFGkSBEBQHz55ZdCCCGeP38ugoKChJubmyhUqJBwcnISHTp0EOfOnZN+btWqVaJkyZLCwsJCtG/fXsyYMUOUKFFCr30rVqwQHh4eolChQqJcuXIiNDRUbzsA8csvv+ite7XjsRBCnDx5Unz00UfC2tpaWFlZCR8fHzFz5sx//Psjon9GJ8Q79hAkIirA+vfvj7i4OBw+fFjtphCRgbBPDhFp0tdff42PPvoIVlZW+P3337F+/XqsWLFC7WYRkQHxTA4RaVKnTp1w8OBBPHr0CB4eHhg2bBgGDhyodrOIyIAYcoiIiEiTeHcVERERaRJDDhEREWkSQw4RERFpEkMOERERaRJDDhEREWkSQw4RERFpEkMOERERaRJDDhEREWkSQw4RERFp0v8DBoSzfl58FMQAAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"df.Catégorie.value_counts().plot.bar()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a8120d1-5c88-4e31-a4e0-0857309e0c9b",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "3db38e8c-4f5d-4823-954a-18300de9074d",
"metadata": {},
"source": [
"## Découpage des datas"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "8295411a-1f7e-43c7-ba19-a5a835a09223",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "d7b1dbf9-e068-4a75-b714-d9bf88f7d028",
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)"
]
},
{
"cell_type": "markdown",
"id": "5e65fd83-a6ad-4f7c-b00c-9b9cda448074",
"metadata": {},
"source": [
"## Tokenisation des Libellé"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "962a08a1-2dd1-4da3-bcf1-1e5f3f741a24",
"metadata": {},
"outputs": [],
"source": [
"from nltk.stem import SnowballStemmer\n",
"from sklearn.feature_extraction.text import CountVectorizer"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "7f39c305-25a6-4ac1-9e1c-e0337f2783b8",
"metadata": {},
"outputs": [],
"source": [
"stemmer = SnowballStemmer('french')\n",
"analyzer = CountVectorizer().build_analyzer()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "98b52881-6d37-4802-9a70-3963b6f03eae",
"metadata": {},
"outputs": [],
"source": [
"def stemmed_words(doc):\n",
" return (stemmer.stem(w) for w in analyzer(doc))"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "5ff329eb-b7b8-48e1-95f8-dfde26285be1",
"metadata": {},
"outputs": [],
"source": [
"vectorizer = CountVectorizer(analyzer=stemmed_words)"
]
},
{
"cell_type": "markdown",
"id": "ccc1eba6-439a-4bf9-87df-a2b225079ae7",
"metadata": {},
"source": [
"## Créations de modèles"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "71da2f84-b75a-4adc-8533-956312c3fd94",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style>#sk-container-id-1 {\n",
" /* Definition of color scheme common for light and dark mode */\n",
" --sklearn-color-text: black;\n",
" --sklearn-color-line: gray;\n",
" /* Definition of color scheme for unfitted estimators */\n",
" --sklearn-color-unfitted-level-0: #fff5e6;\n",
" --sklearn-color-unfitted-level-1: #f6e4d2;\n",
" --sklearn-color-unfitted-level-2: #ffe0b3;\n",
" --sklearn-color-unfitted-level-3: chocolate;\n",
" /* Definition of color scheme for fitted estimators */\n",
" --sklearn-color-fitted-level-0: #f0f8ff;\n",
" --sklearn-color-fitted-level-1: #d4ebff;\n",
" --sklearn-color-fitted-level-2: #b3dbfd;\n",
" --sklearn-color-fitted-level-3: cornflowerblue;\n",
"\n",
" /* Specific color for light theme */\n",
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
" --sklearn-color-icon: #696969;\n",
"\n",
" @media (prefers-color-scheme: dark) {\n",
" /* Redefinition of color scheme for dark theme */\n",
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
" --sklearn-color-icon: #878787;\n",
" }\n",
"}\n",
"\n",
"#sk-container-id-1 {\n",
" color: var(--sklearn-color-text);\n",
"}\n",
"\n",
"#sk-container-id-1 pre {\n",
" padding: 0;\n",
"}\n",
"\n",
"#sk-container-id-1 input.sk-hidden--visually {\n",
" border: 0;\n",
" clip: rect(1px 1px 1px 1px);\n",
" clip: rect(1px, 1px, 1px, 1px);\n",
" height: 1px;\n",
" margin: -1px;\n",
" overflow: hidden;\n",
" padding: 0;\n",
" position: absolute;\n",
" width: 1px;\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-dashed-wrapped {\n",
" border: 1px dashed var(--sklearn-color-line);\n",
" margin: 0 0.4em 0.5em 0.4em;\n",
" box-sizing: border-box;\n",
" padding-bottom: 0.4em;\n",
" background-color: var(--sklearn-color-background);\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-container {\n",
" /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
" but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
" so we also need the `!important` here to be able to override the\n",
" default hidden behavior on the sphinx rendered scikit-learn.org.\n",
" See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
" display: inline-block !important;\n",
" position: relative;\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-text-repr-fallback {\n",
" display: none;\n",
"}\n",
"\n",
"div.sk-parallel-item,\n",
"div.sk-serial,\n",
"div.sk-item {\n",
" /* draw centered vertical line to link estimators */\n",
" background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
" background-size: 2px 100%;\n",
" background-repeat: no-repeat;\n",
" background-position: center center;\n",
"}\n",
"\n",
"/* Parallel-specific style estimator block */\n",
"\n",
"#sk-container-id-1 div.sk-parallel-item::after {\n",
" content: \"\";\n",
" width: 100%;\n",
" border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
" flex-grow: 1;\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-parallel {\n",
" display: flex;\n",
" align-items: stretch;\n",
" justify-content: center;\n",
" background-color: var(--sklearn-color-background);\n",
" position: relative;\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-parallel-item {\n",
" display: flex;\n",
" flex-direction: column;\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
" align-self: flex-end;\n",
" width: 50%;\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
" align-self: flex-start;\n",
" width: 50%;\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
" width: 0;\n",
"}\n",
"\n",
"/* Serial-specific style estimator block */\n",
"\n",
"#sk-container-id-1 div.sk-serial {\n",
" display: flex;\n",
" flex-direction: column;\n",
" align-items: center;\n",
" background-color: var(--sklearn-color-background);\n",
" padding-right: 1em;\n",
" padding-left: 1em;\n",
"}\n",
"\n",
"\n",
"/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
"clickable and can be expanded/collapsed.\n",
"- Pipeline and ColumnTransformer use this feature and define the default style\n",
"- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
"*/\n",
"\n",
"/* Pipeline and ColumnTransformer style (default) */\n",
"\n",
"#sk-container-id-1 div.sk-toggleable {\n",
" /* Default theme specific background. It is overwritten whether we have a\n",
" specific estimator or a Pipeline/ColumnTransformer */\n",
" background-color: var(--sklearn-color-background);\n",
"}\n",
"\n",
"/* Toggleable label */\n",
"#sk-container-id-1 label.sk-toggleable__label {\n",
" cursor: pointer;\n",
" display: block;\n",
" width: 100%;\n",
" margin-bottom: 0;\n",
" padding: 0.5em;\n",
" box-sizing: border-box;\n",
" text-align: center;\n",
"}\n",
"\n",
"#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
" /* Arrow on the left of the label */\n",
" content: \"▸\";\n",
" float: left;\n",
" margin-right: 0.25em;\n",
" color: var(--sklearn-color-icon);\n",
"}\n",
"\n",
"#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
" color: var(--sklearn-color-text);\n",
"}\n",
"\n",
"/* Toggleable content - dropdown */\n",
"\n",
"#sk-container-id-1 div.sk-toggleable__content {\n",
" max-height: 0;\n",
" max-width: 0;\n",
" overflow: hidden;\n",
" text-align: left;\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-toggleable__content pre {\n",
" margin: 0.2em;\n",
" border-radius: 0.25em;\n",
" color: var(--sklearn-color-text);\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-fitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
" /* Expand drop-down */\n",
" max-height: 200px;\n",
" max-width: 100%;\n",
" overflow: auto;\n",
"}\n",
"\n",
"#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
" content: \"▾\";\n",
"}\n",
"\n",
"/* Pipeline/ColumnTransformer-specific style */\n",
"\n",
"#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" color: var(--sklearn-color-text);\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"/* Estimator-specific style */\n",
"\n",
"/* Colorize estimator box */\n",
"#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
"#sk-container-id-1 div.sk-label label {\n",
" /* The background is the default theme color */\n",
" color: var(--sklearn-color-text-on-default-background);\n",
"}\n",
"\n",
"/* On hover, darken the color of the background */\n",
"#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
" color: var(--sklearn-color-text);\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"/* Label box, darken color on hover, fitted */\n",
"#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
" color: var(--sklearn-color-text);\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"/* Estimator label */\n",
"\n",
"#sk-container-id-1 div.sk-label label {\n",
" font-family: monospace;\n",
" font-weight: bold;\n",
" display: inline-block;\n",
" line-height: 1.2em;\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-label-container {\n",
" text-align: center;\n",
"}\n",
"\n",
"/* Estimator-specific */\n",
"#sk-container-id-1 div.sk-estimator {\n",
" font-family: monospace;\n",
" border: 1px dotted var(--sklearn-color-border-box);\n",
" border-radius: 0.25em;\n",
" box-sizing: border-box;\n",
" margin-bottom: 0.5em;\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-estimator.fitted {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-0);\n",
"}\n",
"\n",
"/* on hover */\n",
"#sk-container-id-1 div.sk-estimator:hover {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
"\n",
"/* Common style for \"i\" and \"?\" */\n",
"\n",
".sk-estimator-doc-link,\n",
"a:link.sk-estimator-doc-link,\n",
"a:visited.sk-estimator-doc-link {\n",
" float: right;\n",
" font-size: smaller;\n",
" line-height: 1em;\n",
" font-family: monospace;\n",
" background-color: var(--sklearn-color-background);\n",
" border-radius: 1em;\n",
" height: 1em;\n",
" width: 1em;\n",
" text-decoration: none !important;\n",
" margin-left: 1ex;\n",
" /* unfitted */\n",
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
" color: var(--sklearn-color-unfitted-level-1);\n",
"}\n",
"\n",
".sk-estimator-doc-link.fitted,\n",
"a:link.sk-estimator-doc-link.fitted,\n",
"a:visited.sk-estimator-doc-link.fitted {\n",
" /* fitted */\n",
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
" color: var(--sklearn-color-fitted-level-1);\n",
"}\n",
"\n",
"/* On hover */\n",
"div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
".sk-estimator-doc-link:hover,\n",
"div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
".sk-estimator-doc-link:hover {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-3);\n",
" color: var(--sklearn-color-background);\n",
" text-decoration: none;\n",
"}\n",
"\n",
"div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
".sk-estimator-doc-link.fitted:hover,\n",
"div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
".sk-estimator-doc-link.fitted:hover {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-3);\n",
" color: var(--sklearn-color-background);\n",
" text-decoration: none;\n",
"}\n",
"\n",
"/* Span, style for the box shown on hovering the info icon */\n",
".sk-estimator-doc-link span {\n",
" display: none;\n",
" z-index: 9999;\n",
" position: relative;\n",
" font-weight: normal;\n",
" right: .2ex;\n",
" padding: .5ex;\n",
" margin: .5ex;\n",
" width: min-content;\n",
" min-width: 20ex;\n",
" max-width: 50ex;\n",
" color: var(--sklearn-color-text);\n",
" box-shadow: 2pt 2pt 4pt #999;\n",
" /* unfitted */\n",
" background: var(--sklearn-color-unfitted-level-0);\n",
" border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
"}\n",
"\n",
".sk-estimator-doc-link.fitted span {\n",
" /* fitted */\n",
" background: var(--sklearn-color-fitted-level-0);\n",
" border: var(--sklearn-color-fitted-level-3);\n",
"}\n",
"\n",
".sk-estimator-doc-link:hover span {\n",
" display: block;\n",
"}\n",
"\n",
"/* \"?\"-specific style due to the `<a>` HTML tag */\n",
"\n",
"#sk-container-id-1 a.estimator_doc_link {\n",
" float: right;\n",
" font-size: 1rem;\n",
" line-height: 1em;\n",
" font-family: monospace;\n",
" background-color: var(--sklearn-color-background);\n",
" border-radius: 1rem;\n",
" height: 1rem;\n",
" width: 1rem;\n",
" text-decoration: none;\n",
" /* unfitted */\n",
" color: var(--sklearn-color-unfitted-level-1);\n",
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
"}\n",
"\n",
"#sk-container-id-1 a.estimator_doc_link.fitted {\n",
" /* fitted */\n",
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
" color: var(--sklearn-color-fitted-level-1);\n",
"}\n",
"\n",
"/* On hover */\n",
"#sk-container-id-1 a.estimator_doc_link:hover {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-3);\n",
" color: var(--sklearn-color-background);\n",
" text-decoration: none;\n",
"}\n",
"\n",
"#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-3);\n",
"}\n",
"</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>Pipeline(steps=[(&#x27;vect&#x27;,\n",
" CountVectorizer(analyzer=&lt;function stemmed_words at 0x7017e451cfe0&gt;)),\n",
" (&#x27;clf&#x27;, MultinomialNB())])</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" ><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;Pipeline<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.pipeline.Pipeline.html\">?<span>Documentation for Pipeline</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>Pipeline(steps=[(&#x27;vect&#x27;,\n",
" CountVectorizer(analyzer=&lt;function stemmed_words at 0x7017e451cfe0&gt;)),\n",
" (&#x27;clf&#x27;, MultinomialNB())])</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" ><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;CountVectorizer<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html\">?<span>Documentation for CountVectorizer</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>CountVectorizer(analyzer=&lt;function stemmed_words at 0x7017e451cfe0&gt;)</pre></div> </div></div><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-3\" type=\"checkbox\" ><label for=\"sk-estimator-id-3\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;MultinomialNB<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.naive_bayes.MultinomialNB.html\">?<span>Documentation for MultinomialNB</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>MultinomialNB()</pre></div> </div></div></div></div></div></div>"
],
"text/plain": [
"Pipeline(steps=[('vect',\n",
" CountVectorizer(analyzer=<function stemmed_words at 0x7017e451cfe0>)),\n",
" ('clf', MultinomialNB())])"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.naive_bayes import MultinomialNB\n",
"\n",
"mnb_pipeline = Pipeline([\n",
" ('vect', vectorizer),\n",
" ('clf', MultinomialNB())\n",
"])\n",
"mnb_pipeline.fit(X_train, y_train)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "c5cc500a-5e49-4e07-9a9f-e410dd35b69e",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/svm/_classes.py:31: FutureWarning: The default value of `dual` will change from `True` to `'auto'` in 1.5. Set the value of `dual` explicitly to suppress the warning.\n",
" warnings.warn(\n"
]
},
{
"data": {
"text/html": [
"<style>#sk-container-id-2 {\n",
" /* Definition of color scheme common for light and dark mode */\n",
" --sklearn-color-text: black;\n",
" --sklearn-color-line: gray;\n",
" /* Definition of color scheme for unfitted estimators */\n",
" --sklearn-color-unfitted-level-0: #fff5e6;\n",
" --sklearn-color-unfitted-level-1: #f6e4d2;\n",
" --sklearn-color-unfitted-level-2: #ffe0b3;\n",
" --sklearn-color-unfitted-level-3: chocolate;\n",
" /* Definition of color scheme for fitted estimators */\n",
" --sklearn-color-fitted-level-0: #f0f8ff;\n",
" --sklearn-color-fitted-level-1: #d4ebff;\n",
" --sklearn-color-fitted-level-2: #b3dbfd;\n",
" --sklearn-color-fitted-level-3: cornflowerblue;\n",
"\n",
" /* Specific color for light theme */\n",
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
" --sklearn-color-icon: #696969;\n",
"\n",
" @media (prefers-color-scheme: dark) {\n",
" /* Redefinition of color scheme for dark theme */\n",
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
" --sklearn-color-icon: #878787;\n",
" }\n",
"}\n",
"\n",
"#sk-container-id-2 {\n",
" color: var(--sklearn-color-text);\n",
"}\n",
"\n",
"#sk-container-id-2 pre {\n",
" padding: 0;\n",
"}\n",
"\n",
"#sk-container-id-2 input.sk-hidden--visually {\n",
" border: 0;\n",
" clip: rect(1px 1px 1px 1px);\n",
" clip: rect(1px, 1px, 1px, 1px);\n",
" height: 1px;\n",
" margin: -1px;\n",
" overflow: hidden;\n",
" padding: 0;\n",
" position: absolute;\n",
" width: 1px;\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-dashed-wrapped {\n",
" border: 1px dashed var(--sklearn-color-line);\n",
" margin: 0 0.4em 0.5em 0.4em;\n",
" box-sizing: border-box;\n",
" padding-bottom: 0.4em;\n",
" background-color: var(--sklearn-color-background);\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-container {\n",
" /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
" but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
" so we also need the `!important` here to be able to override the\n",
" default hidden behavior on the sphinx rendered scikit-learn.org.\n",
" See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
" display: inline-block !important;\n",
" position: relative;\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-text-repr-fallback {\n",
" display: none;\n",
"}\n",
"\n",
"div.sk-parallel-item,\n",
"div.sk-serial,\n",
"div.sk-item {\n",
" /* draw centered vertical line to link estimators */\n",
" background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
" background-size: 2px 100%;\n",
" background-repeat: no-repeat;\n",
" background-position: center center;\n",
"}\n",
"\n",
"/* Parallel-specific style estimator block */\n",
"\n",
"#sk-container-id-2 div.sk-parallel-item::after {\n",
" content: \"\";\n",
" width: 100%;\n",
" border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
" flex-grow: 1;\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-parallel {\n",
" display: flex;\n",
" align-items: stretch;\n",
" justify-content: center;\n",
" background-color: var(--sklearn-color-background);\n",
" position: relative;\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-parallel-item {\n",
" display: flex;\n",
" flex-direction: column;\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-parallel-item:first-child::after {\n",
" align-self: flex-end;\n",
" width: 50%;\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-parallel-item:last-child::after {\n",
" align-self: flex-start;\n",
" width: 50%;\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-parallel-item:only-child::after {\n",
" width: 0;\n",
"}\n",
"\n",
"/* Serial-specific style estimator block */\n",
"\n",
"#sk-container-id-2 div.sk-serial {\n",
" display: flex;\n",
" flex-direction: column;\n",
" align-items: center;\n",
" background-color: var(--sklearn-color-background);\n",
" padding-right: 1em;\n",
" padding-left: 1em;\n",
"}\n",
"\n",
"\n",
"/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
"clickable and can be expanded/collapsed.\n",
"- Pipeline and ColumnTransformer use this feature and define the default style\n",
"- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
"*/\n",
"\n",
"/* Pipeline and ColumnTransformer style (default) */\n",
"\n",
"#sk-container-id-2 div.sk-toggleable {\n",
" /* Default theme specific background. It is overwritten whether we have a\n",
" specific estimator or a Pipeline/ColumnTransformer */\n",
" background-color: var(--sklearn-color-background);\n",
"}\n",
"\n",
"/* Toggleable label */\n",
"#sk-container-id-2 label.sk-toggleable__label {\n",
" cursor: pointer;\n",
" display: block;\n",
" width: 100%;\n",
" margin-bottom: 0;\n",
" padding: 0.5em;\n",
" box-sizing: border-box;\n",
" text-align: center;\n",
"}\n",
"\n",
"#sk-container-id-2 label.sk-toggleable__label-arrow:before {\n",
" /* Arrow on the left of the label */\n",
" content: \"▸\";\n",
" float: left;\n",
" margin-right: 0.25em;\n",
" color: var(--sklearn-color-icon);\n",
"}\n",
"\n",
"#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {\n",
" color: var(--sklearn-color-text);\n",
"}\n",
"\n",
"/* Toggleable content - dropdown */\n",
"\n",
"#sk-container-id-2 div.sk-toggleable__content {\n",
" max-height: 0;\n",
" max-width: 0;\n",
" overflow: hidden;\n",
" text-align: left;\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-toggleable__content.fitted {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-toggleable__content pre {\n",
" margin: 0.2em;\n",
" border-radius: 0.25em;\n",
" color: var(--sklearn-color-text);\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-toggleable__content.fitted pre {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-fitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
" /* Expand drop-down */\n",
" max-height: 200px;\n",
" max-width: 100%;\n",
" overflow: auto;\n",
"}\n",
"\n",
"#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
" content: \"▾\";\n",
"}\n",
"\n",
"/* Pipeline/ColumnTransformer-specific style */\n",
"\n",
"#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" color: var(--sklearn-color-text);\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"/* Estimator-specific style */\n",
"\n",
"/* Colorize estimator box */\n",
"#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-label label.sk-toggleable__label,\n",
"#sk-container-id-2 div.sk-label label {\n",
" /* The background is the default theme color */\n",
" color: var(--sklearn-color-text-on-default-background);\n",
"}\n",
"\n",
"/* On hover, darken the color of the background */\n",
"#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {\n",
" color: var(--sklearn-color-text);\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"/* Label box, darken color on hover, fitted */\n",
"#sk-container-id-2 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
" color: var(--sklearn-color-text);\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"/* Estimator label */\n",
"\n",
"#sk-container-id-2 div.sk-label label {\n",
" font-family: monospace;\n",
" font-weight: bold;\n",
" display: inline-block;\n",
" line-height: 1.2em;\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-label-container {\n",
" text-align: center;\n",
"}\n",
"\n",
"/* Estimator-specific */\n",
"#sk-container-id-2 div.sk-estimator {\n",
" font-family: monospace;\n",
" border: 1px dotted var(--sklearn-color-border-box);\n",
" border-radius: 0.25em;\n",
" box-sizing: border-box;\n",
" margin-bottom: 0.5em;\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-estimator.fitted {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-0);\n",
"}\n",
"\n",
"/* on hover */\n",
"#sk-container-id-2 div.sk-estimator:hover {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-2 div.sk-estimator.fitted:hover {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
"\n",
"/* Common style for \"i\" and \"?\" */\n",
"\n",
".sk-estimator-doc-link,\n",
"a:link.sk-estimator-doc-link,\n",
"a:visited.sk-estimator-doc-link {\n",
" float: right;\n",
" font-size: smaller;\n",
" line-height: 1em;\n",
" font-family: monospace;\n",
" background-color: var(--sklearn-color-background);\n",
" border-radius: 1em;\n",
" height: 1em;\n",
" width: 1em;\n",
" text-decoration: none !important;\n",
" margin-left: 1ex;\n",
" /* unfitted */\n",
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
" color: var(--sklearn-color-unfitted-level-1);\n",
"}\n",
"\n",
".sk-estimator-doc-link.fitted,\n",
"a:link.sk-estimator-doc-link.fitted,\n",
"a:visited.sk-estimator-doc-link.fitted {\n",
" /* fitted */\n",
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
" color: var(--sklearn-color-fitted-level-1);\n",
"}\n",
"\n",
"/* On hover */\n",
"div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
".sk-estimator-doc-link:hover,\n",
"div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
".sk-estimator-doc-link:hover {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-3);\n",
" color: var(--sklearn-color-background);\n",
" text-decoration: none;\n",
"}\n",
"\n",
"div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
".sk-estimator-doc-link.fitted:hover,\n",
"div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
".sk-estimator-doc-link.fitted:hover {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-3);\n",
" color: var(--sklearn-color-background);\n",
" text-decoration: none;\n",
"}\n",
"\n",
"/* Span, style for the box shown on hovering the info icon */\n",
".sk-estimator-doc-link span {\n",
" display: none;\n",
" z-index: 9999;\n",
" position: relative;\n",
" font-weight: normal;\n",
" right: .2ex;\n",
" padding: .5ex;\n",
" margin: .5ex;\n",
" width: min-content;\n",
" min-width: 20ex;\n",
" max-width: 50ex;\n",
" color: var(--sklearn-color-text);\n",
" box-shadow: 2pt 2pt 4pt #999;\n",
" /* unfitted */\n",
" background: var(--sklearn-color-unfitted-level-0);\n",
" border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
"}\n",
"\n",
".sk-estimator-doc-link.fitted span {\n",
" /* fitted */\n",
" background: var(--sklearn-color-fitted-level-0);\n",
" border: var(--sklearn-color-fitted-level-3);\n",
"}\n",
"\n",
".sk-estimator-doc-link:hover span {\n",
" display: block;\n",
"}\n",
"\n",
"/* \"?\"-specific style due to the `<a>` HTML tag */\n",
"\n",
"#sk-container-id-2 a.estimator_doc_link {\n",
" float: right;\n",
" font-size: 1rem;\n",
" line-height: 1em;\n",
" font-family: monospace;\n",
" background-color: var(--sklearn-color-background);\n",
" border-radius: 1rem;\n",
" height: 1rem;\n",
" width: 1rem;\n",
" text-decoration: none;\n",
" /* unfitted */\n",
" color: var(--sklearn-color-unfitted-level-1);\n",
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
"}\n",
"\n",
"#sk-container-id-2 a.estimator_doc_link.fitted {\n",
" /* fitted */\n",
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
" color: var(--sklearn-color-fitted-level-1);\n",
"}\n",
"\n",
"/* On hover */\n",
"#sk-container-id-2 a.estimator_doc_link:hover {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-3);\n",
" color: var(--sklearn-color-background);\n",
" text-decoration: none;\n",
"}\n",
"\n",
"#sk-container-id-2 a.estimator_doc_link.fitted:hover {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-3);\n",
"}\n",
"</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>Pipeline(steps=[(&#x27;vect&#x27;,\n",
" CountVectorizer(analyzer=&lt;function stemmed_words at 0x7017e451cfe0&gt;)),\n",
" (&#x27;clf&#x27;, LinearSVC())])</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-4\" type=\"checkbox\" ><label for=\"sk-estimator-id-4\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;Pipeline<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.pipeline.Pipeline.html\">?<span>Documentation for Pipeline</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>Pipeline(steps=[(&#x27;vect&#x27;,\n",
" CountVectorizer(analyzer=&lt;function stemmed_words at 0x7017e451cfe0&gt;)),\n",
" (&#x27;clf&#x27;, LinearSVC())])</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-5\" type=\"checkbox\" ><label for=\"sk-estimator-id-5\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;CountVectorizer<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html\">?<span>Documentation for CountVectorizer</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>CountVectorizer(analyzer=&lt;function stemmed_words at 0x7017e451cfe0&gt;)</pre></div> </div></div><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-6\" type=\"checkbox\" ><label for=\"sk-estimator-id-6\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;LinearSVC<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.svm.LinearSVC.html\">?<span>Documentation for LinearSVC</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>LinearSVC()</pre></div> </div></div></div></div></div></div>"
],
"text/plain": [
"Pipeline(steps=[('vect',\n",
" CountVectorizer(analyzer=<function stemmed_words at 0x7017e451cfe0>)),\n",
" ('clf', LinearSVC())])"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.svm import LinearSVC\n",
"\n",
"svc_pipeline = Pipeline([\n",
" ('vect', vectorizer),\n",
" ('clf', LinearSVC())\n",
"])\n",
"svc_pipeline.fit(X_train, y_train)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "72387f32-b462-4113-8292-c5e88ffd5712",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style>#sk-container-id-3 {\n",
" /* Definition of color scheme common for light and dark mode */\n",
" --sklearn-color-text: black;\n",
" --sklearn-color-line: gray;\n",
" /* Definition of color scheme for unfitted estimators */\n",
" --sklearn-color-unfitted-level-0: #fff5e6;\n",
" --sklearn-color-unfitted-level-1: #f6e4d2;\n",
" --sklearn-color-unfitted-level-2: #ffe0b3;\n",
" --sklearn-color-unfitted-level-3: chocolate;\n",
" /* Definition of color scheme for fitted estimators */\n",
" --sklearn-color-fitted-level-0: #f0f8ff;\n",
" --sklearn-color-fitted-level-1: #d4ebff;\n",
" --sklearn-color-fitted-level-2: #b3dbfd;\n",
" --sklearn-color-fitted-level-3: cornflowerblue;\n",
"\n",
" /* Specific color for light theme */\n",
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
" --sklearn-color-icon: #696969;\n",
"\n",
" @media (prefers-color-scheme: dark) {\n",
" /* Redefinition of color scheme for dark theme */\n",
" --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
" --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
" --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
" --sklearn-color-icon: #878787;\n",
" }\n",
"}\n",
"\n",
"#sk-container-id-3 {\n",
" color: var(--sklearn-color-text);\n",
"}\n",
"\n",
"#sk-container-id-3 pre {\n",
" padding: 0;\n",
"}\n",
"\n",
"#sk-container-id-3 input.sk-hidden--visually {\n",
" border: 0;\n",
" clip: rect(1px 1px 1px 1px);\n",
" clip: rect(1px, 1px, 1px, 1px);\n",
" height: 1px;\n",
" margin: -1px;\n",
" overflow: hidden;\n",
" padding: 0;\n",
" position: absolute;\n",
" width: 1px;\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-dashed-wrapped {\n",
" border: 1px dashed var(--sklearn-color-line);\n",
" margin: 0 0.4em 0.5em 0.4em;\n",
" box-sizing: border-box;\n",
" padding-bottom: 0.4em;\n",
" background-color: var(--sklearn-color-background);\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-container {\n",
" /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
" but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
" so we also need the `!important` here to be able to override the\n",
" default hidden behavior on the sphinx rendered scikit-learn.org.\n",
" See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
" display: inline-block !important;\n",
" position: relative;\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-text-repr-fallback {\n",
" display: none;\n",
"}\n",
"\n",
"div.sk-parallel-item,\n",
"div.sk-serial,\n",
"div.sk-item {\n",
" /* draw centered vertical line to link estimators */\n",
" background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
" background-size: 2px 100%;\n",
" background-repeat: no-repeat;\n",
" background-position: center center;\n",
"}\n",
"\n",
"/* Parallel-specific style estimator block */\n",
"\n",
"#sk-container-id-3 div.sk-parallel-item::after {\n",
" content: \"\";\n",
" width: 100%;\n",
" border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
" flex-grow: 1;\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-parallel {\n",
" display: flex;\n",
" align-items: stretch;\n",
" justify-content: center;\n",
" background-color: var(--sklearn-color-background);\n",
" position: relative;\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-parallel-item {\n",
" display: flex;\n",
" flex-direction: column;\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-parallel-item:first-child::after {\n",
" align-self: flex-end;\n",
" width: 50%;\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-parallel-item:last-child::after {\n",
" align-self: flex-start;\n",
" width: 50%;\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-parallel-item:only-child::after {\n",
" width: 0;\n",
"}\n",
"\n",
"/* Serial-specific style estimator block */\n",
"\n",
"#sk-container-id-3 div.sk-serial {\n",
" display: flex;\n",
" flex-direction: column;\n",
" align-items: center;\n",
" background-color: var(--sklearn-color-background);\n",
" padding-right: 1em;\n",
" padding-left: 1em;\n",
"}\n",
"\n",
"\n",
"/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
"clickable and can be expanded/collapsed.\n",
"- Pipeline and ColumnTransformer use this feature and define the default style\n",
"- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
"*/\n",
"\n",
"/* Pipeline and ColumnTransformer style (default) */\n",
"\n",
"#sk-container-id-3 div.sk-toggleable {\n",
" /* Default theme specific background. It is overwritten whether we have a\n",
" specific estimator or a Pipeline/ColumnTransformer */\n",
" background-color: var(--sklearn-color-background);\n",
"}\n",
"\n",
"/* Toggleable label */\n",
"#sk-container-id-3 label.sk-toggleable__label {\n",
" cursor: pointer;\n",
" display: block;\n",
" width: 100%;\n",
" margin-bottom: 0;\n",
" padding: 0.5em;\n",
" box-sizing: border-box;\n",
" text-align: center;\n",
"}\n",
"\n",
"#sk-container-id-3 label.sk-toggleable__label-arrow:before {\n",
" /* Arrow on the left of the label */\n",
" content: \"▸\";\n",
" float: left;\n",
" margin-right: 0.25em;\n",
" color: var(--sklearn-color-icon);\n",
"}\n",
"\n",
"#sk-container-id-3 label.sk-toggleable__label-arrow:hover:before {\n",
" color: var(--sklearn-color-text);\n",
"}\n",
"\n",
"/* Toggleable content - dropdown */\n",
"\n",
"#sk-container-id-3 div.sk-toggleable__content {\n",
" max-height: 0;\n",
" max-width: 0;\n",
" overflow: hidden;\n",
" text-align: left;\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-toggleable__content.fitted {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-toggleable__content pre {\n",
" margin: 0.2em;\n",
" border-radius: 0.25em;\n",
" color: var(--sklearn-color-text);\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-toggleable__content.fitted pre {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-fitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-3 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
" /* Expand drop-down */\n",
" max-height: 200px;\n",
" max-width: 100%;\n",
" overflow: auto;\n",
"}\n",
"\n",
"#sk-container-id-3 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
" content: \"▾\";\n",
"}\n",
"\n",
"/* Pipeline/ColumnTransformer-specific style */\n",
"\n",
"#sk-container-id-3 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" color: var(--sklearn-color-text);\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"/* Estimator-specific style */\n",
"\n",
"/* Colorize estimator box */\n",
"#sk-container-id-3 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-label label.sk-toggleable__label,\n",
"#sk-container-id-3 div.sk-label label {\n",
" /* The background is the default theme color */\n",
" color: var(--sklearn-color-text-on-default-background);\n",
"}\n",
"\n",
"/* On hover, darken the color of the background */\n",
"#sk-container-id-3 div.sk-label:hover label.sk-toggleable__label {\n",
" color: var(--sklearn-color-text);\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"/* Label box, darken color on hover, fitted */\n",
"#sk-container-id-3 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
" color: var(--sklearn-color-text);\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"/* Estimator label */\n",
"\n",
"#sk-container-id-3 div.sk-label label {\n",
" font-family: monospace;\n",
" font-weight: bold;\n",
" display: inline-block;\n",
" line-height: 1.2em;\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-label-container {\n",
" text-align: center;\n",
"}\n",
"\n",
"/* Estimator-specific */\n",
"#sk-container-id-3 div.sk-estimator {\n",
" font-family: monospace;\n",
" border: 1px dotted var(--sklearn-color-border-box);\n",
" border-radius: 0.25em;\n",
" box-sizing: border-box;\n",
" margin-bottom: 0.5em;\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-0);\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-estimator.fitted {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-0);\n",
"}\n",
"\n",
"/* on hover */\n",
"#sk-container-id-3 div.sk-estimator:hover {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-2);\n",
"}\n",
"\n",
"#sk-container-id-3 div.sk-estimator.fitted:hover {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-2);\n",
"}\n",
"\n",
"/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
"\n",
"/* Common style for \"i\" and \"?\" */\n",
"\n",
".sk-estimator-doc-link,\n",
"a:link.sk-estimator-doc-link,\n",
"a:visited.sk-estimator-doc-link {\n",
" float: right;\n",
" font-size: smaller;\n",
" line-height: 1em;\n",
" font-family: monospace;\n",
" background-color: var(--sklearn-color-background);\n",
" border-radius: 1em;\n",
" height: 1em;\n",
" width: 1em;\n",
" text-decoration: none !important;\n",
" margin-left: 1ex;\n",
" /* unfitted */\n",
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
" color: var(--sklearn-color-unfitted-level-1);\n",
"}\n",
"\n",
".sk-estimator-doc-link.fitted,\n",
"a:link.sk-estimator-doc-link.fitted,\n",
"a:visited.sk-estimator-doc-link.fitted {\n",
" /* fitted */\n",
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
" color: var(--sklearn-color-fitted-level-1);\n",
"}\n",
"\n",
"/* On hover */\n",
"div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
".sk-estimator-doc-link:hover,\n",
"div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
".sk-estimator-doc-link:hover {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-3);\n",
" color: var(--sklearn-color-background);\n",
" text-decoration: none;\n",
"}\n",
"\n",
"div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
".sk-estimator-doc-link.fitted:hover,\n",
"div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
".sk-estimator-doc-link.fitted:hover {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-3);\n",
" color: var(--sklearn-color-background);\n",
" text-decoration: none;\n",
"}\n",
"\n",
"/* Span, style for the box shown on hovering the info icon */\n",
".sk-estimator-doc-link span {\n",
" display: none;\n",
" z-index: 9999;\n",
" position: relative;\n",
" font-weight: normal;\n",
" right: .2ex;\n",
" padding: .5ex;\n",
" margin: .5ex;\n",
" width: min-content;\n",
" min-width: 20ex;\n",
" max-width: 50ex;\n",
" color: var(--sklearn-color-text);\n",
" box-shadow: 2pt 2pt 4pt #999;\n",
" /* unfitted */\n",
" background: var(--sklearn-color-unfitted-level-0);\n",
" border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
"}\n",
"\n",
".sk-estimator-doc-link.fitted span {\n",
" /* fitted */\n",
" background: var(--sklearn-color-fitted-level-0);\n",
" border: var(--sklearn-color-fitted-level-3);\n",
"}\n",
"\n",
".sk-estimator-doc-link:hover span {\n",
" display: block;\n",
"}\n",
"\n",
"/* \"?\"-specific style due to the `<a>` HTML tag */\n",
"\n",
"#sk-container-id-3 a.estimator_doc_link {\n",
" float: right;\n",
" font-size: 1rem;\n",
" line-height: 1em;\n",
" font-family: monospace;\n",
" background-color: var(--sklearn-color-background);\n",
" border-radius: 1rem;\n",
" height: 1rem;\n",
" width: 1rem;\n",
" text-decoration: none;\n",
" /* unfitted */\n",
" color: var(--sklearn-color-unfitted-level-1);\n",
" border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
"}\n",
"\n",
"#sk-container-id-3 a.estimator_doc_link.fitted {\n",
" /* fitted */\n",
" border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
" color: var(--sklearn-color-fitted-level-1);\n",
"}\n",
"\n",
"/* On hover */\n",
"#sk-container-id-3 a.estimator_doc_link:hover {\n",
" /* unfitted */\n",
" background-color: var(--sklearn-color-unfitted-level-3);\n",
" color: var(--sklearn-color-background);\n",
" text-decoration: none;\n",
"}\n",
"\n",
"#sk-container-id-3 a.estimator_doc_link.fitted:hover {\n",
" /* fitted */\n",
" background-color: var(--sklearn-color-fitted-level-3);\n",
"}\n",
"</style><div id=\"sk-container-id-3\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>Pipeline(steps=[(&#x27;vect&#x27;,\n",
" CountVectorizer(analyzer=&lt;function stemmed_words at 0x7017e451cfe0&gt;)),\n",
" (&#x27;clf&#x27;, SGDClassifier())])</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-7\" type=\"checkbox\" ><label for=\"sk-estimator-id-7\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;Pipeline<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.pipeline.Pipeline.html\">?<span>Documentation for Pipeline</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>Pipeline(steps=[(&#x27;vect&#x27;,\n",
" CountVectorizer(analyzer=&lt;function stemmed_words at 0x7017e451cfe0&gt;)),\n",
" (&#x27;clf&#x27;, SGDClassifier())])</pre></div> </div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-8\" type=\"checkbox\" ><label for=\"sk-estimator-id-8\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;CountVectorizer<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html\">?<span>Documentation for CountVectorizer</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>CountVectorizer(analyzer=&lt;function stemmed_words at 0x7017e451cfe0&gt;)</pre></div> </div></div><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-9\" type=\"checkbox\" ><label for=\"sk-estimator-id-9\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;SGDClassifier<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.4/modules/generated/sklearn.linear_model.SGDClassifier.html\">?<span>Documentation for SGDClassifier</span></a></label><div class=\"sk-toggleable__content fitted\"><pre>SGDClassifier()</pre></div> </div></div></div></div></div></div>"
],
"text/plain": [
"Pipeline(steps=[('vect',\n",
" CountVectorizer(analyzer=<function stemmed_words at 0x7017e451cfe0>)),\n",
" ('clf', SGDClassifier())])"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn.linear_model import SGDClassifier\n",
"\n",
"\n",
"svm_pipeline = Pipeline([\n",
" ('vect', vectorizer),\n",
" ('clf', SGDClassifier())\n",
"])\n",
"svm_pipeline.fit(X_train, y_train)"
]
},
{
"cell_type": "markdown",
"id": "93cde7ff-1ecd-4c2e-a2c8-3fabb914c78f",
"metadata": {},
"source": [
"## Évaluation"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "cbbc44ed-74ab-407e-8acf-e668513498aa",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.metrics import accuracy_score"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "f5450692-99d9-4080-b0a6-75b73cb9146e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"MNB ccuracy: 94.15%\n"
]
}
],
"source": [
"y_pred = mnb_pipeline.predict(X_test)\n",
"accuracy = accuracy_score(y_test, y_pred)\n",
"print(\"MNB ccuracy: {:.2f}%\".format(accuracy * 100))"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "0fd79ffb-752b-4886-994d-ed489b1950d1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"742 33BLO- DIAG LOT 4\n",
"928 33BLO- PLAQUES LOC\n",
"3466 4SER-lot 1 FRAIS COMM DIAG\n",
"65 FORFAIT REGLAGE HORLOGE\n",
"219 PC - ENTRETIEN ELECTRICITE\n",
" ... \n",
"51 Solde Départ - Remboursement Solde D.G. Du 120...\n",
"669 Gestion impaye locataire ALUR Du 28/09/2\n",
"2188 4SER - Mise en demeure KALAI\n",
"3251 33BLO-LOT REMISE GESTION\n",
"1665 1MAR - MAINTENANCE ELECTRIQUE\n",
"Length: 186, dtype: object"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X_test[y_test!=y_pred]"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "17191e07-3a77-415b-947e-2475c0e42e08",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"SVC Accuracy: 95.85%\n"
]
}
],
"source": [
"y_pred = svc_pipeline.predict(X_test)\n",
"accuracy = accuracy_score(y_test, y_pred)\n",
"print(\"SVC Accuracy: {:.2f}%\".format(accuracy * 100))"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "cbcaf96f-56ce-4618-b578-d1498fe78d20",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3062 33BLO- LOT 15 PLAQUES\n",
"928 33BLO- PLAQUES LOC\n",
"268 1MAR-CONSOMMATION EAU\n",
"440 PC - CONTRAT ASCENSEUR\n",
"2085 vac hor INST COMPTEUR ELEC\n",
" ... \n",
"1057 Accès Extranet 2020\n",
"51 Solde Départ - Remboursement Solde D.G. Du 120...\n",
"2188 4SER - Mise en demeure KALAI\n",
"3162 1MAR- SUIVI TRAVAUX DEBARRASS\n",
"1665 1MAR - MAINTENANCE ELECTRIQUE\n",
"Length: 132, dtype: object"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X_test[y_test!=y_pred]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "8367c994-de9e-4977-b703-cd26ee4f9eb9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"SVC Accuracy: 95.97%\n"
]
}
],
"source": [
"y_pred = svm_pipeline.predict(X_test)\n",
"accuracy = accuracy_score(y_test, y_pred)\n",
"print(\"SVC Accuracy: {:.2f}%\".format(accuracy * 100))"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "d5c458d1-4b2b-410a-8d77-fffea9f6a46e",
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"3062 33BLO- LOT 15 PLAQUES\n",
"928 33BLO- PLAQUES LOC\n",
"268 1MAR-CONSOMMATION EAU\n",
"65 FORFAIT REGLAGE HORLOGE\n",
"123 1MAR- dossier Grosjean\n",
" ... \n",
"1057 Accès Extranet 2020\n",
"51 Solde Départ - Remboursement Solde D.G. Du 120...\n",
"2188 4SER - Mise en demeure KALAI\n",
"3162 1MAR- SUIVI TRAVAUX DEBARRASS\n",
"1665 1MAR - MAINTENANCE ELECTRIQUE\n",
"Length: 128, dtype: object"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display(X_test[y_test!=y_pred])"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "6e71a627-8bb6-470e-aba8-cb82c42b4fda",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3062 33BLO- LOT 15 PLAQUES\n",
"928 33BLO- PLAQUES LOC\n",
"268 1MAR-CONSOMMATION EAU\n",
"65 FORFAIT REGLAGE HORLOGE\n",
"123 1MAR- dossier Grosjean\n",
"440 PC - CONTRAT ASCENSEUR\n",
"3078 33BLO- VAC HOR PB CANALISA OFF\n",
"1662 4SER - MAINTENANCE ELECTRIQUE\n",
"85 DESINSECTISATION PUNAISES\n",
"1550 4 SER - EDF ASCENSEUR\n",
"1710 Extranet gestion locative 2017\n",
"1061 Accès Extranet 2020\n",
"2530 1MAR- RAMONAGE\n",
"3800 1MAR- lot 6 plaques\n",
"3766 1MAR- lot 6 SUIVI TRAVAUX\n",
"1998 4SER- PLAQUES LOT 7\n",
"1865 Frais suivi d'impaye Du 01052020 Au 3105\n",
"4246 33blo- LOGE SUIVI TRAVAUX\n",
"3160 Suivi travaux debarrassage\n",
"144 S3 - Reception travaux\n",
"1285 1 MAR - Eau gd Lyon\n",
"1708 Extranet gestion locative 2017\n",
"1716 4SER - Contrat ascenseur\n",
"2855 33BLO- TT COMM DIAG LOT 4\n",
"167 4SER- SUIVI REPAR ASCENSEUR\n",
"3532 4SER- NETTOYAGE VITRAGES\n",
"1107 1MAR- lOT 13 GROSJEAN HUISSIER\n",
"518 4SER-TEL ASCENSEUR 1TRIM2019\n",
"1345 33BLO- LOT 18 COMM DIAGNOSTICS\n",
"2555 Accès Extranet 2018\n",
"598 20 - PLAQUES BAL\n",
"1011 Accès Extranet 2020\n",
"747 33BLO- LOT 17 RED NVEAU BAIL\n",
"1730 4 SER - Tél ascenseur\n",
"1183 4SER - EDF ASCENSEUR\n",
"1632 4S-CONTRAT ASCENSEUR-3TRIM\n",
"2007 1MAR- PLAQUES LOT 9\n",
"1704 Extranet gestion locative 2017\n",
"1056 Accès Extranet 2020\n",
"1644 4SER - Contrat ascenseur\n",
"2839 4SER- LOT 9PLAQUES\n",
"516 4SER - Travaux tél ascenseur\n",
"2488 1MAR- ENTRETIEN ASCENSEUR\n",
"749 4 SER - TELEPHONE ASCENSEUR\n",
"1991 33blo- lot 17 PLAQUES\n",
"298 7 - REMISE AUX NORMES ELECTRCITE\n",
"800 Avis de valeur\n",
"79 1MAR - Huissier doss. Grosjean\n",
"38 1MAR - LARMIERS CAVES\n",
"4473 33MB-Lot11 -Sommation huissier\n",
"4455 4SER - Mise en demeure KALAI\n",
"211 Honoraires suivi recouvrement GROSJEAN S\n",
"1236 33MB- Plaque signalétique\n",
"508 1MAR- suivi trx ascen 1h offer\n",
"364 1MAR-Travaux fuite ascenseur\n",
"2016 Commde diagnostic Lot 19-33MBL\n",
"343 Etat des risques 33M - LOT 6\n",
"750 4SER - MAINTENANCE ELECTRIQUE\n",
"3636 Rembt Annul frais impayé\n",
"364 PC CONTRAT REGLAGE HORLOGE\n",
"3174 33BLO- SUIVI TRAVAUX\n",
"4594 33MB - Plaques lot 4\n",
"92 RAMONAGE 1ER SEMESTRE 2017\n",
"1700 Extranet gestion locative 2017\n",
"2520 Accès Extranet 2018\n",
"2850 1MAR- LOT 8 VAC HOR TRAVAUX\n",
"2289 1MAR - LARMIERS CAVES\n",
"1053 Accès Extranet 2020\n",
"121 1MAR-Contrat ascenseur 1T 2020\n",
"2554 Accès Extranet 2018\n",
"3632 4SER-LOT 9 PLAQUES\n",
"2533 Accès Extranet 2018\n",
"1406 4SER- lot 8 COURR AVOCAT NUISA\n",
"4366 4SER- LOT 12 PLAQUES\n",
"4357 vac hor install compteur elec\n",
"4450 4 SER - CT Ascenseur 1T2020\n",
"3163 33BLO- SUIVI TRAVAUX DEBARRASS\n",
"2318 Accès Extranet 2019\n",
"1992 ESTIMATION VALEUR VENALE\n",
"2775 1MAR - MAINTENANCE ELECTRICITE\n",
"292 DESOURISATION PARTIES PRIVATIVES\n",
"2556 Accès Extranet 2018\n",
"1706 Extranet gestion locative 2017\n",
"1475 33M-Lot11- Affaire PICARD\n",
"4082 4SER - Sommation Versini\n",
"1647 1MAR - Contrat ascenseur\n",
"177 1 MAR - Eau Gd LYON\n",
"685 PC - CONTRAT ASCESENEUR\n",
"2540 Accès Extranet 2018\n",
"2179 4SER - Réparation ascenseur\n",
"2296 Accès Extranet 2019\n",
"1408 33BLO- lot 16 FRAIS COMM DIAG\n",
"4247 33blo- LOGE SUIVI TRAVAUX\n",
"1975 33blo- LOGE SUIVI TRX offert\n",
"510 1MAR- LOT 2 SUIVI TRX\n",
"1714 1MAR-Lot 13-Frais huissier\n",
"4300 TT COMMANDE DIAGNOSTICS\n",
"917 4SER- LOT 8 FRAIS AVOCAT\n",
"228 4 SER - TELEPHONE ASCENSEUR\n",
"78 1MAR - Huissier doss. Grosjean\n",
"2006 33MB- PLAQUES LOT 6\n",
"1854 PC - 3ème trimestre 2020\n",
"1002 33MB-Lot 17 - Plaques BAL\n",
"2221 Forfait nego loyers suite COV1 Loc ASSOCIES A2...\n",
"1167 33BLO- LOT 12 REDACTION BAIL\n",
"1043 Accès Extranet 2020\n",
"1073 1 MAR - Entretien ascenseur\n",
"3169 Rbst soc ADICTUM-4SER\n",
"385 Honoraires suivi de procedure GROSJEAN S\n",
"1169 1MAR - Lot 6 -Frais diagnostic\n",
"1937 Remboursement Solde D.G. Du 06082020\n",
"143 Distribution cle/badge aux loc suite nouvelles...\n",
"753 1MAR - MAINTENANCE ELECTRIQUE\n",
"2532 Accès Extranet 2018\n",
"534 Commde diagnostic Lot 7-4SERV\n",
"3 4 SER - CT ASCENSEUR 1T2018\n",
"1387 1MAR- LOT 10 PLAQUES\n",
"2205 1MAR - Plaques lot 13\n",
"1703 Extranet gestion locative 2017\n",
"3644 1MAR- LOT 6 SUIVI TRAVAUX\n",
"360 vacation horaire travaux\n",
"98 PC - TELEPHONIE ASCENSEUR\n",
"842 3 - RACORDEMENT ELECTRIQUE SRUDIO RDC\n",
"1057 Accès Extranet 2020\n",
"51 Solde Départ - Remboursement Solde D.G. Du 120...\n",
"2188 4SER - Mise en demeure KALAI\n",
"3162 1MAR- SUIVI TRAVAUX DEBARRASS\n",
"1665 1MAR - MAINTENANCE ELECTRIQUE\n",
"dtype: object\n"
]
}
],
"source": [
"with pd.option_context('display.max_rows', None, 'display.max_columns', None): # more options can be specified also\n",
" print(X_test[y_test!=y_pred])"
]
},
{
"cell_type": "markdown",
"id": "61a935da-40fd-4043-9109-ec97635dfc00",
"metadata": {},
"source": [
"## Optimisations\n"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "5321423f-55d4-4241-815c-22a516460bf6",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import GridSearchCV"
]
},
{
"cell_type": "markdown",
"id": "fac29ae8-a68b-434f-82d4-865856222222",
"metadata": {},
"source": [
"### Modèle Naive Bayes"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "366e66d6-5bcf-4000-85d5-6d488220070f",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.naive_bayes import MultinomialNB\n",
"from sklearn.feature_extraction.text import TfidfTransformer\n",
"\n",
"\n",
"mnb_pipeline = Pipeline([\n",
" ('vect', CountVectorizer()),\n",
" #('tfid', TfidfTransformer()),\n",
" ('clf', MultinomialNB())\n",
"])"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "008f18a2-5538-412e-8863-c287aef8af0d",
"metadata": {},
"outputs": [],
"source": [
"parameters = {\n",
" 'vect__ngram_range': [(1, 1), (1, 2), (2,2)],\n",
" #'tfidf__use_idf': (True, False),\n",
" 'clf__alpha': (1, 1e-1,1e-2, 1e-3,),\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "70fe6252-a653-4cfe-89d4-809518e7968b",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/model_selection/_split.py:737: UserWarning: The least populated class in y has only 1 members, which is less than n_splits=5.\n",
" warnings.warn(\n"
]
}
],
"source": [
"gs_clf = GridSearchCV(mnb_pipeline, parameters, n_jobs=-1)\n",
"gs_clf = gs_clf.fit(X, y)"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "f5a9281a-a37d-4373-8710-9ea089d39ddb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.9446366782006921"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gs_clf.best_score_"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "2d84af17-194e-4718-9b96-94cb1b5330e1",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'clf__alpha': 0.001, 'vect__ngram_range': (1, 2)}"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gs_clf.best_params_"
]
},
{
"cell_type": "markdown",
"id": "ac0800c5-58f3-4ee7-876c-9d3e4e9eed57",
"metadata": {},
"source": [
"### Linear SVC"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "f4e02729-9559-4579-b4a7-f875a3becb72",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.feature_extraction.text import TfidfTransformer\n",
"from sklearn.svm import LinearSVC\n",
"\n",
"svc_pipeline = Pipeline([\n",
" ('vect', CountVectorizer()),\n",
" #('tfid', TfidfTransformer()),\n",
" ('clf', LinearSVC())\n",
"])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "578baa50-8d47-4a1a-a5f3-f2f992245693",
"metadata": {},
"outputs": [],
"source": [
"parameters = {\n",
" 'vect__ngram_range': [(1, 1), (1, 2), (2,2)],\n",
" #'tfidf__use_idf': (True, False),\n",
" 'clf__alpha': (1, 1e-1,1e-2, 1e-3,),\n",
"}"
]
},
{
"cell_type": "markdown",
"id": "e894aebd-b0d8-4ce9-900b-0a6afb7e10bd",
"metadata": {},
"source": [
"### SGD"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "6a793449-8540-43e2-9683-f81cfe47488b",
"metadata": {},
"outputs": [],
"source": [
"from sklearn.linear_model import SGDClassifier\n",
"\n",
"\n",
"sgd_pipeline = Pipeline([\n",
" ('vect', vectorizer),\n",
" ('clf', SGDClassifier())\n",
"])"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "a871784a-05f6-471b-a972-d154db3ed181",
"metadata": {},
"outputs": [],
"source": [
"parameters = {\n",
" 'vect__ngram_range': [(1, 1), (1, 2), (2,2)],\n",
" #'tfidf__use_idf': (True, False),\n",
" 'clf__tol': (1, 1e-1,1e-2, 1e-3,),\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 37,
"id": "9efff414-1052-4e42-b60d-a6955ccacfa4",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/model_selection/_split.py:737: UserWarning: The least populated class in y has only 1 members, which is less than n_splits=5.\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n",
"/home/commun/scripts/Plesna/.venv/lib/python3.11/site-packages/sklearn/feature_extraction/text.py:541: UserWarning: The parameter 'ngram_range' will not be used since 'analyzer' is callable'\n",
" warnings.warn(\n"
]
}
],
"source": [
"gs_clf = GridSearchCV(sgd_pipeline, parameters, n_jobs=-1)\n",
"gs_clf = gs_clf.fit(X, y)"
]
},
{
"cell_type": "code",
"execution_count": 38,
"id": "eb47b8c4-5eca-4e54-93e2-7a932261aedb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.9485372758729159"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gs_clf.best_score_"
]
},
{
"cell_type": "code",
"execution_count": 39,
"id": "e9920e95-7720-48cd-83f8-a650a12d9639",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'clf__tol': 0.001, 'vect__ngram_range': (1, 1)}"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gs_clf.best_params_"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2d5b30f5-3114-4559-8a77-e30d716134a3",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.11.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}