Определение:
В машинном обучении и статистике классификация - это проблема определения того, к какому из набора категорий относится новое наблюдение, на основе обучающего набора данных, содержащих наблюдения, принадлежность к категории которых известна.
ДАННЫЕ О КАЧЕСТВЕ ВИНА
Описание набора данных:
Набор данных относится к красному варианту португальского вина «Винью Верде», который можно рассматривать как данные классификации. Из-за конфиденциальности доступны только физико-химические (входные) и сенсорные (выходные) переменные. В наборе данных всего 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()
ПОДБОР МОДЕЛЕЙ К НАБОРУ ДАННЫХ
Применяемые модели:
- Логистическая регрессия
- Линейный SVM
- rbf SVM
- KNN
- Гауссовский NB
- Древо решений
- Случайный лес
- Повышение градиента
РАЗДЕЛЕНИЕ ПЕРЕМЕННЫХ 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