<jupyter_start><jupyter_text>Multiclass Classification of White Wine Quality Wine DataData from http://archive.ics.uci.edu/ml/datasets/Wine+Quality Citations<NAME>. and <NAME>. (2017). UCI Machine Learning Repository [http://archive.ics.uci.edu/ml/index.php]. Irvine, CA: University of California, School of Information and Computer Science.<NAME>, <NAME>, <NAME>, <NAME> and <NAME>. Modeling wine preferences by data mining from physicochemical properties.In Decision Support Systems, Elsevier, 47(4):547-553. ISSN: 0167-9236.Available at:- [@Elsevier](http://dx.doi.org/10.1016/j.dss.2009.05.016)- [Pre-press (pdf)](http://www3.dsi.uminho.pt/pcortez/winequality09.pdf)- [bib](http://www3.dsi.uminho.pt/pcortez/dss09.bib) Setup<jupyter_code>%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

white_wine = pd.read_csv('../../ch_09/data/winequality-white.csv', sep=';')<jupyter_output><empty_output><jupyter_text>EDA<jupyter_code>white_wine.head()
white_wine.describe()
white_wine.info()
def plot_quality_scores(df, kind):
    ax = df.quality.value_counts().sort_index().plot.barh(
        title=f'{kind.title()} Wine Quality Scores', figsize=(12, 3)
    )
    ax.axes.invert_yaxis()
    for bar in ax.patches:
        ax.text(
            bar.get_width(), 
            bar.get_y() + bar.get_height()/2, 
            f'{bar.get_width()/df.shape[0]:.1%}',
            verticalalignment='center'
        )
    plt.xlabel('count of wines')
    plt.ylabel('quality score')

    for spine in ['top', 'right']:
        ax.spines[spine].set_visible(False)

    return ax

plot_quality_scores(white_wine, 'white')<jupyter_output><empty_output><jupyter_text>White wine quality multiclass classification<jupyter_code>from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

y = white_wine.quality
X = white_wine.drop(columns=['quality'])

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=0, stratify=y
)

lm_pipeline = Pipeline([
    ('scale', StandardScaler()), 
    ('lm', LogisticRegression(multi_class='multinomial', random_state=0, max_iter=1000))
]).fit(X_train, y_train)<jupyter_output><empty_output><jupyter_text>EvaluationGet the predictions:<jupyter_code>preds = lm_pipeline.predict(X_test)<jupyter_output><empty_output><jupyter_text>Check out the classification report:<jupyter_code>%%capture --no-stdout
from sklearn.metrics import classification_report
print(classification_report(y_test, preds))<jupyter_output>precision    recall  f1-score   support

           3       1.00      0.20      0.33         5
           4       0.88      0.17      0.29        41
           5       0.59      0.54      0.56       364
           6       0.53      0.76      0.62       550
           7       0.54      0.21      0.31       220
           8       0.00      0.00      0.00        44
           9       0.00      0.00      0.00         1

    accuracy                           0.55      1225
   macro avg       0.50      0.27      0.30      1225
weighted avg       0.54      0.55      0.51      1225<jupyter_text>Multiclass confusion matrix:<jupyter_code>from ml_utils.classification import confusion_matrix_visual

confusion_matrix_visual(y_test, preds, np.sort(y_test.unique()))<jupyter_output><empty_output><jupyter_text>Extend the `plot_roc()` function to multiclass classification problems<jupyter_code>from ml_utils.classification import plot_multiclass_roc
plot_multiclass_roc??
plot_multiclass_roc(y_test, lm_pipeline.predict_proba(X_test))<jupyter_output><empty_output><jupyter_text>Extend the `plot_pr_curve()` function to multiclass classification problems<jupyter_code>from ml_utils.classification import plot_multiclass_pr_curve
plot_multiclass_pr_curve??<jupyter_output><empty_output><jupyter_text>Note how these tell a much different story than the ROC curves, since we have a class imbalance:<jupyter_code>plot_multiclass_pr_curve(y_test, lm_pipeline.predict_proba(X_test))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11076178960096736, 'fraction_numerical': 0.043047158403869405, 'mean_word_length': 3.6576576576576576, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 9, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '469717', 'license': 'MIT', 'n_tokens_mistral': 1517, 'n_tokens_neox': 1389, 'n_words': 272, 'path': 'solutions/ch_09/exercise_4.ipynb', 'repo_name': 'piotrv/DA-Pandas-Stefanie-Molin', 'size': '4163'}