- Модель машинного обучения, которая обучается на наборе данных Red Wine из репозитория StatLib.
- Здесь мы проводим контролируемое обучение, и наша цель — проводить прогнозный анализ.
- Во время нашего путешествия мы поймем важные инструменты, необходимые для разработки мощной модели машинного обучения.
- Наша модель поможет нам в прогнозировании качества вина.
- Мы проверим его на нашем тестовом наборе данных.
Чтобы выполнить сквозной проект машинного обучения, нам необходимо выполнить следующие шаги.
- Поймите постановку задачи для бизнеса.
- Получить набор данных.
- Выполнение исследовательского анализа данных для лучшего понимания и разработки модели.
- Предварительно обработайте данные, чтобы подготовить их для нашей модели машинного обучения.
- Идентифицируйте и удаляйте выбросы, применяя методы удаления выбросов, чтобы получить точные результаты.
- Проверка и устранение асимметрии распределения.
- Пробуйте разные модели и тренируйте их. Выберите тот, который мы считаем лучшим.
- Настройте нашу модель, настроив гиперпараметры.
- Проверка важности функции.
- Вывод .
- Сохранение модели.
1. Понять постановку задачи для бизнеса
Мы увлеченные специалисты по данным, и прежде чем начать, нам нужно задать несколько фундаментальных вопросов.
2. Получить набор данных
Получите набор данных в формате CSV здесь и сохраните его в папке. Откройте Jupyter Notebook и начните импорт основных библиотек.
# data processing import pandas as pd #Linear Algebra import numpy as np #Data Visualization import seaborn as sns %matplotlib inline import matplotlib.pyplot as plt from matplotlib import style # Algorithms from sklearn.svm import SVC, LinearSVC from sklearn import model_selection from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.linear_model import SGDClassifier from sklearn.tree import DecisionTreeClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import StandardScaler,LabelEncoder from sklearn.metrics import confusion_matrix,classification_report,accuracy_score,roc_curve,roc_auc_score from sklearn.model_selection import train_test_split,cross_val_score,GridSearchCV import warnings warnings.filterwarnings(‘ignore’)
Получение и чтение набора данных
wine=pd.read_csv("winequality_red.csv") wine.head()
Эти данные имеют такие показатели, как фиксированная кислотность, летучая кислотность, лимонная кислота, остаточный сахар, хлориды, свободный диоксид серы, общий диоксид серы, плотность, pH, сульфаты, спирт, качество.
#to know shape of the dataset wine.shape
(1599,12)
Здесь мы можем заметить, что в этом наборе данных присутствует 1599 строк и 12 признаков.
#Number of unique valuesin this dataset for col in wine.columns.values: print("Number of unique values of {}:{}".format(col,wine[col].nunique()))
вывод:
Количество уникальных значений фиксированной кислотности:96
Количество уникальных значений летучей кислотности:143
Количество уникальных значений лимонной кислоты:80
Количество уникальных значений остаточного сахара:91
Количество уникальных значений хлоридов: 153
Количество уникальных значений свободного диоксида серы: 60
Количество уникальных значений общего диоксида серы: 144
Количество уникальных значений плотности: 436
Количество уникальных значений pH:89
Количество уникальных значений сульфатов:96
Количество уникальных значений спирта:65
Количество уникальных значений качества:6
Признак фиксированной кислотности имеет большее количество уникальных значений, а признак качества имеет меньшее количество уникальных значений.
wine.info()
wine.describe(include='all')
1. Среднее значение больше медианы (50-й процентиль) во всех столбцах.
2. Существует большая разница в процентиле 75% и максимальном уровне остаточного сахара, свободного диоксида серы, общего диоксида серы.
3.Наблюдения 1 и 2 предполагают наличие экстремальных выбросов.
wine.tail()
Исследовательский анализ данных
#check weather null values present or not sns.heatmap(wine.isnull())
Есть еще один способ проверить нулевые значения, см. ниже…
wine.isnull().sum()
sns.countplot(wine['quality'])
Качество наблюдений
имеет большинство значений, сосредоточенных в категориях 5,6,7
несколько наблюдений, сосредоточенных в категориях 4,8,3
Создание бинов для функции качества
bins=(2,6.5,8) group=['Bad','Good'] wine['quality']=pd.cut(wine['quality'],bins=bins,labels=group) #now assign kabels to quality label_quality=LabelEncoder() #Bad becomes 0,and good becomes 1 wine['quality']=label_quality.fit_transform(wine['quality'])
Теперь давайте проверим
Были созданы новые лейблы.
plt.scatter(wine['chlorides'],wine['alcohol'],cmap='orange')
#to check correlation sns.heatmap(wine.corr())
- плотность имеет сильную положительную корреляцию с остаточным сахаром, тогда как она имеет сильную отрицательную корреляцию с алкоголем.
- pH и фиксированная кислотность имеют отрицательную корреляцию.
- плотность и фиксированная кислотность имеют положительную корреляцию.
- лимонная кислота и фиксированная кислотность имеют положительную корреляцию.
- лимонная кислота и летучие кислоты имеют отрицательную корреляцию.
- свободный диоксид серы и общий диоксид серы имеют положительную корреляцию.
- Колонку pH лучше убрать
wine.drop('pH',axis=1,inplace=True)
#distribution plots sns.FacetGrid(wine,hue='quality',size=5).map(sns.distplot,'chlorides').add_legend() sns.FacetGrid(wine,hue='quality',size=6).map(sns.distplot,'alcohol').add_legend()
Отсюда диапазон хлоридов находится между (0,0–0,1) качество вина больше, а при значении хлорида 0,5 качество вина низкое. Наконец, я заметил одну вещь: если диапазон хлоридов увеличивается, качество вина снижается.
Отсюда диапазон содержания алкоголя находится между (9–12) качество вина Больше и количество алкоголя 9 качество вина больше
#boxplot for to check outliers sns.boxplot(x='quality',y='citric acid',data=wine)
sns.pairplot(wine ,hue ='quality', vars =['fixed acidity','volatile acidity', 'citric acid', 'residual sugar', 'chlorides', 'free sulfur dioxide', 'total sulfur dioxide', 'density', 'sulphates', 'alcohol'])
- Светлые оттенки тесно связаны
- качество сильно коррелирует с алкоголем
- спирт сильно отрицательно с плотностью -0,5 (см. в темно-бордовом оттенке)
- плотность сильно положительно коррелирует с остаточным сахаром
- летучая кислотность отрицательно коррелирует с качеством
- свободная серная кислота сильно коррелирует с общим диоксидом серы
- здесь мы можем исключить летучую кислотность из набора данных, если мы делаем линейную регрессию
Идентификация и удаление выбросов
wine['fixed acidity'].plot.box()
collist=wine.columns.values ncol=12 nrows=10 plt.figure(figsize=(ncol,5*ncol)) for i in range(1,len(collist)): plt.subplot(nrows,ncol,i+1) sns.boxplot(wine[collist[i]],color='green',orient='v') plt.tight_layout()
#Removing Outliers from scipy.stats import zscore z=np.abs(zscore(wine)) z threshold=3 np.where(z>3)
wine_new=wine[(z<3).all(axis=1)] wine_new.shape wine.shape
141 строка была удалена как выбросы
Проверка и удаление - Распределение асимметрии
plt.figure(figsize=(20,20)) for i in range(0,len(collist)): plt.subplot(nrows,ncol,i+1) sns.distplot(wine_new[collist[i]])
wine_new.skew()
Отсюда мы можем заметить, что большинство функций имеет асимметрию, поэтому лучше поработать над этим….
x=wine_new.iloc[:,:-1] y=wine_new.iloc[:,-1]
Сверху мы видим, что x и y y являются целевой переменной, а функция качества назначается y, а все остальные функции, кроме качества, назначаются x.
#removal of skew-ness using log function for col in x.columns: if x.skew().loc[col]>0.55: x[col]=np.log1p(x[col])
Снова проверьте асимметрию
x.skew()
только данные плотности имеют нормальное распределение
другие независимые переменные смещены вправо/положительно
Построение модели машинного обучения
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=43)
Отсюда мы можем заметить, что 80% данных идут на обучение и 20% данных идут на тестирование….
#Applying Standard Scaling to get optimized result sc=StandardScaler() x_train=sc.fit_transform(x_train) x_test=sc.fit_transform(x_test)
| Применение алгоритмов машинного обучения
dtc=DecisionTreeClassifier() rfc=RandomForestClassifier() lg=LogisticRegression() knc=KNeighborsClassifier() sgc=SGDClassifier() seed=7 #prepare models models=[] models.append(('DecisionTreeClassifier',dtc)) models.append(('RandomForestClassifier',rfc)) models.append(('KNeighborsClassifier',knc)) models.append(('SGDClassifier',sgc)) models.append(('LogisticRegression',lg)) #evaluate each model in turn Model=[] cvs=[] score=[] rocscore=[] for name,model in models: print('**************',name,'***********') print('\n') Model.append(name) model.fit(train_X,train_Y) print(model) pred=model.predict(test_X) print('\n') acc=accuracy_score(test_Y,pred) print('accuracy score',acc) score.append(acc*100) kfold=model_selection.KFold(n_splits=10,random_state=seed) cv=model_selection.cross_val_score(model,X,Y,cv=10,scoring='accuracy').mean() print('Cross-val-score=',cv) cvs.append(cv*100) print('\n') false_positive_rate,true_positive_rate,thresholds=roc_curve(test_Y,pred) roc_auc=roc_auc_score(test_Y,pred) print('roc_auc_score',roc_auc) rocscore.append(roc_auc*100) print('\n') print(classification_report(test_Y,pred)) print('\n') cm=confusion_matrix(test_Y,pred) print(cm) print('\n') plt.figure(figsize=(10,15)) plt.subplot(911) plt.title(name) print(sns.heatmap(cm,annot=True)) plt.subplot(912) plt.title(name) plt.plot(false_positive_rate,true_positive_rate,label='AUC'%roc_auc) plt.plot([0,1],[0,1],'k--') plt.xlabel('false_positive_rate') plt.ylabel('true_positive_rate') plt.show()
Результат вы можете увидеть ниже
Выбор лучшей модели
- Из таблицы выше мы можем наблюдать одну вещь, то есть точность для RandomForestClassifier составляет 92%, я думаю, что это хороший результат.
- И Cross-val-score 88 это неплохо, а Roc-score 75…..
- Общая производительность этого алгоритма лучше по сравнению со всеми другими алгоритмами.
Сетка Поиск параметра Настройка
param_grid ={'C':[0.1,1,10,100],'gamma':[1,0.1,0.01,0.001],'kernel':['rbf']} from sklearn.model_selection import GridSearchCV, cross_val_score rfc = RandomForestClassifier( random_state=1) grid=GridSearchCV(SVC(),param_grid,refit=True,verbose=4) grid.fit(x_train, y_train) grid.best_params_
Мы можем найти лучший оценщик из поиска по сетке, как это. Подчеркивание в конце предназначено для параметров, которые модель изучила.
grid_predictions=grid.predict(x_test) grid_predictions
Прогнозирование значений
rfc.fit(x_train,y_train) pred=rfc.predict(x_test) print('predicted insurance claim:',pred) print('actual insurance claim',y_test)
Важность функции
importances = pd.DataFrame({'feature':X.columns,'importance':np.round(rfc.feature_importances_,3)}) importances = importances.sort_values('importance',ascending=False).set_index('feature')
Вывод
свободный диоксид серы не играет существенной роли в нашем процессе прогнозирования случайных лесных классификаторов. из-за этого я удаляю их из набора данных и снова обучаю классификатор
Сохранение модели
from sklearn.externals import joblib #save the model as a pickle in a file joblib.dump(rfc,'quality of wine.obj') #load the model from a file lg_from_joblib=joblib.load('quality of wine.obj') #use the loaded model to make prediction lg_from_joblib.predict(test_X)
Я думаю, что пока это хорошо.