Определение:

В машинном обучении и статистике классификация - это проблема определения того, к какому из набора категорий относится новое наблюдение, на основе обучающего набора данных, содержащих наблюдения, принадлежность к категории которых известна.

ДАННЫЕ О КАЧЕСТВЕ ВИНА

Описание набора данных:

Набор данных относится к красному варианту португальского вина «Винью Верде», который можно рассматривать как данные классификации. Из-за конфиденциальности доступны только физико-химические (входные) и сенсорные (выходные) переменные. В наборе данных всего 11 атрибутов / переменных плюс выходная переменная (класс) с 1599 экземплярами / наблюдениями. Классы упорядочены, но не сбалансированы.

Информация об атрибутах:

Входные переменные (на основе физико-химических тестов):
1. фиксированная кислотность
2. летучая кислотность
3. лимонная кислота
4. остаточный сахар
5. хлориды
6. свободный диоксид серы
7. общий диоксид серы
8. плотность
9. pH
10. сульфаты
11. спирт
Выходная переменная (на основе сенсорных данных):
12. качество (оценка от 0 до 10)

# Importing necessary packages and functions required
import numpy as np # for numerical computations
import pandas as pd # for data processing,I/O file operations
import matplotlib.pyplot as plt # for visualization of different kinds of plots
%matplotlib inline 
# for matplotlib graphs to be included in the notebook, next to the code
import seaborn as sns # for visualization 
import warnings # to silence warnings
warnings.filterwarnings('ignore')
# Importing red wine data into a dataframe
data=pd.read_csv("...\\winequality-red.csv")
# Glimpse of the data
data.sample(5)

#shape of the data i.e., no of rows and columns in the data
data.shape
(1599, 12)
#size of the data
data.size
19188

Анализ и визуализация данных

# data information i.e., datatypes of different columns,their count etc
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1599 entries, 0 to 1598
Data columns (total 12 columns):
fixed acidity           1599 non-null float64
volatile acidity        1599 non-null float64
citric acid             1599 non-null float64
residual sugar          1599 non-null float64
chlorides               1599 non-null float64
free sulfur dioxide     1599 non-null float64
total sulfur dioxide    1599 non-null float64
density                 1599 non-null float64
pH                      1599 non-null float64
sulphates               1599 non-null float64
alcohol                 1599 non-null float64
quality                 1599 non-null int64
dtypes: float64(11), int64(1)
memory usage: 150.0 KB
# Description of the data i.e., Descriptive Statistics
data.describe()

# checking the different classes of the wine quality 
data.quality.unique()
array([5, 6, 7, 4, 8, 3], dtype=int64)

По нашим данным, всего 6 уникальных качеств вин.

# Checking the number of supporting observations for each class of wine quality
data['quality'].value_counts()
5    681
6    638
7    199
4     53
8     18
3     10
Name: quality, dtype: int64

Качество вина 5 имеет максимальные поддерживающие случаи из данных 681 случая, в то время как вина качества 3,8 имеют очень меньшее количество поддерживающих случаев 10,18 соответственно.

sns.countplot(data.quality)
plt.show()

Из приведенного выше графика подсчета мы обнаруживаем, что вина с нормальным качеством (4,5,6,7) не имеют больше экземпляров, в то время как вина отличного или плохого качества (8,3) соответственно имеют меньше экземпляров для поддержки.

Поскольку классы не сбалансированы, мы удаляем классы с меньшим количеством поддерживающих классов, то есть с качествами 3, 8, поскольку они препятствуют процессу обучения моделей при подборе данных, что дает ненормальные результаты.

# Get names of indexes for which column Age has value 30
indexNames1 = data[ (data['quality'] == 3) ].index
indexNames2 = data[ (data['quality'] == 8) ].index
 
# Delete these row indexes from dataFrame
data.drop(indexNames1, inplace=True)
data.drop(indexNames2,inplace=True)
# Checking the number of supporting observations for each class of wine quality
data['quality'].value_counts()
5    681
6    638
7    199
4     53
Name: quality, dtype: int64
# Again visualizing count plot
sns.countplot(data.quality)
plt.show()

Теперь у каждого класса есть приличное количество вспомогательных классов, чтобы модель могла изучить и классифицировать новый.

# Now lets see the shape of the data
data.shape
(1571, 12)
# Checking for missing values in the data
sns.heatmap(data.isnull(),yticklabels=False,cbar=False,cmap="viridis")
plt.show()

Из приведенной выше тепловой карты мы видим, что в данных нет пропущенных значений.

# Checking fixed acidity levels for each wine quality
fig = plt.figure(figsize = (8,6))
sns.barplot(x = 'quality', y = 'fixed acidity', data = data)
plt.show()

# Takes more run time can avoid this code if considered unnecessary.
fig,ax=plt.subplots(4,2,figsize=(15,15))
plt.subplots_adjust(hspace=.4)
ax[0,0].bar(x='quality',height='fixed acidity',data = data)
ax[0,1].bar(x="quality",height="volatile acidity",data=data)
ax[1,0].bar(x="quality",height="citric acid",data=data)
ax[1,1].bar(x="quality",height="residual sugar",data=data)
ax[2,0].bar(x="quality",height="chlorides",data=data)
ax[2,1].bar(x="quality",height="free sulfur dioxide",data=data)
ax[3,0].bar(x="quality",height="sulphates",data=data)
ax[3,1].bar(x="quality",height="alcohol",data=data)
ax[0,0].set_title("fixed acidity")
ax[0,1].set_title("volatile acidity")
ax[1,0].set_title("citric acid")
ax[1,1].set_title("residual sugar")
ax[2,0].set_title("chlorides")
ax[2,1].set_title("free sulfur dioxide")
ax[3,0].set_title("sulphates")
ax[3,1].set_title("alcohol")
plt.show()

# point plot
fig = plt.figure(figsize = (9,6))
sns.pointplot(x=data['pH'].round(1),y='residual sugar',color='green',data=data)
plt.show()
fig = plt.figure(figsize = (8,6))
sns.pointplot(y=data['pH'].round(1),x='quality',color='MAGENTA',data=data)
plt.show()

# Takes more run time can avoid this code if considered unnecessary. 
sns.pairplot(data)
plt.show()

# Correlation
corr=data.corr()
corr

# Visualizing correlation
plt.figure(figsize=(10,10))
sns.heatmap(corr,annot=True)
plt.show()

ПОДБОР МОДЕЛЕЙ К НАБОРУ ДАННЫХ

Применяемые модели:

  1. Логистическая регрессия
  2. Линейный SVM
  3. rbf SVM
  4. KNN
  5. Гауссовский NB
  6. Древо решений
  7. Случайный лес
  8. Повышение градиента

РАЗДЕЛЕНИЕ ПЕРЕМЕННЫХ X И Y

# SPLITING X AND Y VARIABLES
X=data.iloc[:,:-1]
y=data.iloc[:,11]
# A GLIMPSE OF X AND Y VARAIBLES
X.sample(3)

y.sample(3)
732     5
869     6
1083    6
Name: quality, dtype: int64

НАБОРЫ ДАННЫХ ДЛЯ ОБУЧЕНИЯ И ТЕСТИРОВАНИЯ

# SPLITTING DATASET INTO TRAINING AND TESTING DATA
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=1)
# SHAPE OF TRAINING AND TESTING DATA
print(X_train.shape)
print(X_test.shape)
print(y_train.shape)
print(y_test.shape)
(1099, 11)
(472, 11)
(1099,)
(472,)

УСТАНОВКА ВСЕХ МОДЕЛЕЙ ОДНОВРЕМЕННО

# Importing packages and functions required for fitting different models to the data
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC,SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier,GradientBoostingClassifier

# Importing functions to get the model fitting for the data 
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,confusion_matrix  
from sklearn.model_selection import cross_val_score

Одновременная подгонка всех моделей с использованием цикла for и получение матриц ошибок, точности

# Fitting all the models at the same time using 'for' loop
models=[LogisticRegression(multi_class="multinomial",solver="newton-cg"),
        LinearSVC(),
        SVC(kernel='rbf',gamma="auto"),
        KNeighborsClassifier(n_neighbors=10,metric="euclidean"),
        GaussianNB(),
        DecisionTreeClassifier(criterion="gini",max_depth=10),
        RandomForestClassifier(n_estimators=100),
        GradientBoostingClassifier()
        ]
model_names=['LogisticRegression',
             'LinearSVM',
             'rbfSVM',
             'KNearestNeighbors',
             'GaussianNB',
             'DecisionTree',
             'RandomForestClassifier',
             'GradientBoostingClassifier',
             ]
acc=[]
for model in range(len(models)):
    classification_model=models[model]
    classification_model.fit(X_train,y_train)
    y_pred=classification_model.predict(X_test)
    acc.append(accuracy_score(y_pred,y_test))
    print("confusion matrix of:",model_names[model],"\n",confusion_matrix(y_test,y_pred))  
d={'Modelling Algorithm':model_names,'Accuracy':acc}
acc_table=pd.DataFrame(d)
acc_table
confusion matrix of: LogisticRegression 
 [[  0   9   7   2]
 [  0 156  48   1]
 [  0  69 113   8]
 [  0   3  42  14]]
confusion matrix of: LinearSVM 
 [[  0  12   5   1]
 [  0 132  72   1]
 [  0  61 125   4]
 [  0   4  45  10]]
confusion matrix of: rbfSVM 
 [[  0  11   6   1]
 [  0 135  69   1]
 [  0  75 110   5]
 [  0  14  36   9]]
confusion matrix of: KNearestNeighbors 
 [[  1   8   7   2]
 [  1 138  63   3]
 [  0  97  86   7]
 [  0  16  33  10]]
confusion matrix of: GaussianNB 
 [[  1   9   6   2]
 [ 11 129  57   8]
 [ 12  43 107  28]
 [  1   4  26  28]]
confusion matrix of: DecisionTree 
 [[  2   9   5   2]
 [  2 128  64  11]
 [  3  51 120  16]
 [  0   8  29  22]]
confusion matrix of: RandomForestClassifier 
 [[  0  12   5   1]
 [  0 154  49   2]
 [  0  42 139   9]
 [  0   3  36  20]]
confusion matrix of: GradientBoostingClassifier 
 [[  0  13   4   1]
 [  3 151  50   1]
 [  1  47 130  12]
 [  0   2  34  23]]

ТАБЛИЦА, ПОКАЗЫВАЮЩАЯ КАЖДУЮ МОДЕЛЬ И ЕЕ СООТВЕТСТВУЮЩИЕ ОЦЕНКИ ТОЧНОСТИ.

sns.barplot(y='Modelling Algorithm',x='Accuracy',data=acc_table)
plt.show()
sns.catplot(x='Modelling Algorithm',y='Accuracy',data=acc_table,kind='point',height=4,aspect=3.5)
plt.show()

Получение 10-кратных результатов перекрестной проверки для всех моделей одновременно с использованием цикла for

# Finding 10 fold cross validation scores for all the models at the same time using 'for' loop 
models=[LogisticRegression(multi_class="multinomial",solver="newton-cg"),
        LinearSVC(),
        SVC(kernel='rbf',gamma="auto"),
        KNeighborsClassifier(n_neighbors=10,metric="euclidean"),
        GaussianNB(),
        DecisionTreeClassifier(criterion="gini",max_depth=10),
        RandomForestClassifier(n_estimators=100),
        GradientBoostingClassifier()
        ]
model_names=['LogisticRegression',
             'LinearSVM',
             'rbfSVM',
             'KNearestNeighbors',
             'GaussianNB',
             'DecisionTree',
             'RandomForestClassifier',
             'GradientBoostingClassifier',
             ]
cvs=[]
for model in range(len(models)):
    classification_model=models[model]
    clf=classification_model.fit(X_train,y_train)
    scores = cross_val_score(clf, X_test, y_test, cv=10)
    scores.mean()
    print("10 fold cross validation of:",model_names[model],"\n",scores.mean())
10 fold cross validation of: LogisticRegression 
 0.5704360674272791
10 fold cross validation of: LinearSVM 
 0.5173323311748381
10 fold cross validation of: rbfSVM 
 0.5301701099804708
10 fold cross validation of: KNearestNeighbors 
 0.4837970243601603
10 fold cross validation of: GaussianNB 
 0.4810738513721862
10 fold cross validation of: DecisionTree 
 0.5198442799876657
10 fold cross validation of: RandomForestClassifier 
 0.6067686812622057
10 fold cross validation of: GradientBoostingClassifier 
 0.5855266471374242

ПРОГНОЗ НОВОГО НАБЛЮДЕНИЯ ДЛЯ ВСЕХ РАЗЛИЧНЫХ МОДЕЛЕЙ, ФАКТИЧЕСКАЯ ЦЕННОСТЬ 5.

# prediction 
new_obs=[[9,0.580,0.25,2.8,0.075,9.0,104.0,0.99779,3.23,0.57,9.7]]
pv=[]
for model in range(len(models)):
    classification_model=models[model]
    models[model].predict(new_obs)
    pv.append(models[model].predict(new_obs))
    
d={'Modelling Algorithm':model_names,'Predicted value':pv}
pred_table=pd.DataFrame(d)
pred_table

Заключение:

ПО ВСЕМ ВЫШЕ ЗНАЧЕНИЯМ МЫ ВИДИМ, ЧТО ПОДДЕРЖКА ВЕКТОРНОЙ МАШИНЫ (RBF) НЕПРАВИЛЬНО ПРЕДНАЗНАЧЕНА.

Github суть

Gist.github.com/SAMEERA-DS/2241be2cdaddbfcd133fe48b340b1a78

Мой Github