Постановка задачи:
В этом проекте мы собираемся классифицировать класс клиента, будь то 0 или 1.
Это проблема бинарной классификации (обучение с учителем).
Ссылка на набор данных: https://raw.githubusercontent.com/subashgandyer/datasets/main/great_customers.csv
Давайте прыгать прямо в!
Импорт необходимых библиотек
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt from matplotlib import rcParams from matplotlib.cm import rainbow %matplotlib inline import warnings warnings.filterwarnings('ignore')
Чтение данных
data=pd.read_csv("https://raw.githubusercontent.com/subashgandyer/datasets/main/great_customers.csv") data
13599 строк × 15 столбцов
Проверка дисбаланса данных
data.great_customer_class.value_counts().plot.pie(autopct='%.2f')
Данные сильно несбалансированы
При работе с несбалансированными данными мы не рекомендуем использовать категориальную точность в качестве основного критерия оценки. Нет ничего необычного в том, чтобы наблюдать высокую точность оценки при тестировании модели классификации, обученной на очень несбалансированных данных.
Метрика производительности
Precision/Specificity: сколько выбранных экземпляров релевантно.
Отзыв/Чувствительность: сколько релевантных экземпляров выбрано.
Оценка F1: среднее гармоническое точности и полноты.
AUC: соотношение между истинно положительными показателями и ложноположительными показателями
Матрица путаницы
data.head(5)
Форма
data.shape (13599, 15)
Функции
data.columns Index(['user_id', 'age', 'workclass', 'salary', 'education_rank', 'marital-status', 'occupation', 'race', 'sex', 'mins_beerdrinking_year', 'mins_exercising_year', 'works_hours', 'tea_per_year', 'coffee_per_year', 'great_customer_class'], dtype='object')
проверить недостающие значения
data.isna().sum() user_id 0 age 421 workclass 543 salary 422 education_rank 0 marital-status 0 occupation 543 race 0 sex 0 mins_beerdrinking_year 424 mins_exercising_year 421 works_hours 0 tea_per_year 2429 coffee_per_year 2411 great_customer_class 0 dtype: int64 data.info() <class 'pandas.core.frame.DataFrame'> RangeIndex: 13599 entries, 0 to 13598 Data columns (total 15 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 user_id 13599 non-null int64 1 age 13178 non-null float64 2 workclass 13056 non-null object 3 salary 13177 non-null float64 4 education_rank 13599 non-null int64 5 marital-status 13599 non-null object 6 occupation 13056 non-null object 7 race 13599 non-null object 8 sex 13599 non-null object 9 mins_beerdrinking_year 13175 non-null float64 10 mins_exercising_year 13178 non-null float64 11 works_hours 13599 non-null int64 12 tea_per_year 11170 non-null float64 13 coffee_per_year 11188 non-null float64 14 great_customer_class 13599 non-null int64 dtypes: float64(6), int64(4), object(5) memory usage: 1.6+ MB
Проверка процента отсутствующего значения
for i in range(len(data.columns)): missing_data = data[data.columns[i]].isna().sum() perc = missing_data / len(data) * 100 print(f'Feature {i+1} >> Missing entries: {missing_data} | Percentage: {round(perc, 2)}') Feature 1 >> Missing entries: 0 | Percentage: 0.0 Feature 2 >> Missing entries: 421 | Percentage: 3.1 Feature 3 >> Missing entries: 543 | Percentage: 3.99 Feature 4 >> Missing entries: 422 | Percentage: 3.1 Feature 5 >> Missing entries: 0 | Percentage: 0.0 Feature 6 >> Missing entries: 0 | Percentage: 0.0 Feature 7 >> Missing entries: 543 | Percentage: 3.99 Feature 8 >> Missing entries: 0 | Percentage: 0.0 Feature 9 >> Missing entries: 0 | Percentage: 0.0 Feature 10 >> Missing entries: 424 | Percentage: 3.12 Feature 11 >> Missing entries: 421 | Percentage: 3.1 Feature 12 >> Missing entries: 0 | Percentage: 0.0 Feature 13 >> Missing entries: 2429 | Percentage: 17.86 Feature 14 >> Missing entries: 2411 | Percentage: 17.73 Feature 15 >> Missing entries: 0 | Percentage: 0.0
Визуализация пропущенных значений
plt.figure(figsize=(10,6)) sns.heatmap(data.isna(), cbar=False, cmap='viridis', yticklabels=False) <AxesSubplot:>
Обработка категориальных пропущенных значений
data['workclass']= data['workclass'].fillna('U') data['occupation']= data['occupation'].fillna('U') data.isnull().sum() user_id 0 age 421 workclass 0 salary 422 education_rank 0 marital-status 0 occupation 0 race 0 sex 0 mins_beerdrinking_year 424 mins_exercising_year 421 works_hours 0 tea_per_year 2429 coffee_per_year 2411 great_customer_class 0 dtype: int64
Обработка числовых пропущенных значений
from numpy import NaN data[['age','salary','mins_beerdrinking_year','mins_exercising_year','tea_per_year','coffee_per_year']] = data[['age','salary','mins_beerdrinking_year','mins_exercising_year','tea_per_year','coffee_per_year']].replace(0, NaN) data.fillna(data.mean(), inplace=True) data
Выходные характеристики:
data_output_features=data.great_customer_class.drop_duplicates() data_output_features 0 0 12431 1 Name: great_customer_class, dtype: int64
Нулевые пропущенные значения
data.isnull().sum() user_id 0 age 0 workclass 0 salary 0 education_rank 0 marital-status 0 occupation 0 race 0 sex 0 mins_beerdrinking_year 0 mins_exercising_year 0 works_hours 0 tea_per_year 0 coffee_per_year 0 great_customer_class 0 dtype: int64
Обработка категориальных данных
from sklearn.preprocessing import LabelEncoder labelencoder_X=LabelEncoder() xm=data.apply(LabelEncoder().fit_transform) xm
Входные функции
X=xm.iloc[:,:-1] X
Выходные характеристики
y=xm.iloc[:,7] y 0 1 1 0 2 0 3 0 4 1 .. 13594 0 13595 0 13596 0 13597 0 13598 0 Name: race, Length: 13599, dtype: int32
Важность функции
#importing the ExtraTreesRegressor from sklearn.ensemble import ExtraTreesClassifier import matplotlib.pyplot as plt model = ExtraTreesClassifier() model.fit(X,y) print(model.feature_importances_) [5.15922695e-03 6.52201813e-03 9.97480198e-03 6.75190966e-03 5.17079298e-03 4.79258824e-03 5.13421973e-03 9.32278250e-01 9.24679975e-03 8.57937431e-04 6.37238179e-04 3.12327395e-03 3.37443667e-03 6.97650620e-03] #Top 5 important features feat_importances = pd.Series(model.feature_importances_, index=X.columns) feat_importances.nlargest(5).plot(kind='barh') plt.show() #X.columns X_new = X[['occupation','user_id','salary','workclass','race']] X_new
Разделить данные
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X_new, y, test_size = 0.30, random_state=5) print(X_train.shape) print(X_test.shape) print(y_train.shape) print(y_test.shape) (9519, 5) (4080, 5) (9519,) (4080,)
Построение модели
КНН
from sklearn.neighbors import KNeighborsClassifier knn_classifier = KNeighborsClassifier() knn_classifier.fit(X_train, y_train) knn_predictions = knn_classifier.predict(X_test) print(knn_classifier.score(X_test, y_test)) print(knn_classifier.score(X_train, y_train)) 0.8960784313725491 0.9083937388381133 from sklearn.metrics import confusion_matrix confusion_matrix(y_test,knn_predictions) array([[3643, 49], [ 375, 13]], dtype=int64)
Случайный лес
from sklearn.ensemble import RandomForestClassifier rf_classifier = RandomForestClassifier() rf_classifier.fit(X_train, y_train) rf_predictions = rf_classifier.predict(X_test) print(rf_classifier.score(X_test, y_test)) print(rf_classifier.score(X_train, y_train)) 1.0 1.0 #overfitting from sklearn.metrics import confusion_matrix confusion_matrix(y_test,rf_predictions) array([[3692, 0], [ 0, 388]], dtype=int64)
Логистическая регрессия
from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression model = LogisticRegression() model.fit(X_train, y_train) print(model.score(X_test, y_test)) print(model.score(X_train, y_train)) lr_predictions=model.predict(X_test) 0.903921568627451 0.9038764576110936
Матрица путаницы
from sklearn.metrics import confusion_matrix confusion_matrix(y_test,lr_predictions) array([[3685, 7], [ 385, 3]], dtype=int64)
SVM
from sklearn import svm Sv_Classifier= svm.SVC() Sv_Classifier.fit(X_train, y_train) SVC() Sv_predictions = Sv_Classifier.predict(X_test) print(Sv_Classifier.score(X_test, y_test)) print(Sv_Classifier.score(X_train, y_train)) 0.9049019607843137 0.9056623594915433 from sklearn.metrics import confusion_matrix confusion_matrix(y_test,Sv_predictions) array([[3692, 0], [ 388, 0]], dtype=int64)
Наивный Байес
from sklearn.model_selection import train_test_split from sklearn.naive_bayes import GaussianNB gnb = GaussianNB() nb=gnb.fit(X_train, y_train) nb GaussianNB() y_pred = gnb.predict(X_test) y_pred array([0, 0, 0, ..., 0, 0, 0]) print(gnb.score(X_test, y_test)) print(gnb.score(X_train, y_train)) 1.0 1.0 #overfitting from sklearn.metrics import confusion_matrix confusion_matrix(y_test,y_pred) array([[3692, 0], [ 0, 388]], dtype=int64)
Заключение
Модели случайного леса и наивные байесовские модели переобучаются из-за несбалансированных данных. Его можно уменьшить с помощью методов выборки. Кроме того, мы можем рандомизировать поиск резюме, чтобы найти лучший параметр
from sklearn.ensemble import VotingClassifier model_ensemble = VotingClassifier(estimators=[('lr', model), ('RF', rf_classifier), ('knn', knn_classifier ),("nb",gnb),("svc",Sv_Classifier)], voting='hard') model_ensemble.fit(X_train, y_train) VotingClassifier(estimators=[('lr', VotingClassifier(estimators=[('lr', LogisticRegression()), ('RF', RandomForestClassifier()), ('knn', KNeighborsClassifier()), ('nb', GaussianNB()), ('svc', SVC())])), ('RF', RandomForestClassifier()), ('knn', KNeighborsClassifier()), ('nb', GaussianNB()), ('svc', SVC())]) print(model_ensemble.score(X_test, y_test)) print(model_ensemble.score(X_train, y_train)) 0.9088235294117647 0.9171131421367791 y_pred_en = model_ensemble.predict(X_test) y_pred_en array([0, 0, 0, ..., 0, 0, 0]) from sklearn.metrics import confusion_matrix confusion_matrix(y_test,y_pred_en) array([[3692, 0], [ 372, 16]], dtype=int64)
Сборка дает ту же точность по сравнению с другими моделями. Однако, когда мы смотрим в матрицу путаницы. Он имеет небольшое улучшение в классификации функций
print('\n Accuracy Error') print(' ---------- --------') print('Logistic Regression : {:.04}% {:.04}%'.format(model.score(X_test, y_test)* 100,\ 100-(model.score(X_test, y_test) * 100))) print('KNN : {:.04}% {:.04}% '.format(knn_classifier.score(X_test, y_test) * 100,\ 100-(knn_classifier.score(X_test, y_test) * 100))) print('Random Forest : {:.04}% {:.04}% '.format(rf_classifier.score(X_test, y_test)* 100,\ 100-(rf_classifier.score(X_test, y_test)* 100))) print('Naivebayes : {:.04}% {:.04}% '.format(gnb.score(X_test, y_test)* 100,\ 100-(gnb.score(X_test, y_test)* 100))) print('Support Vector Machine : {:.04}% {:.04}% '.format(Sv_Classifier.score(X_test, y_test)* 100,\ 100-(Sv_Classifier.score(X_test, y_test)* 100))) print(' ---------- --------') print('Ensembling : {:.04}% {:.04}% '.format(model_ensemble.score(X_test, y_test)* 100,\ 100-(model_ensemble.score(X_test, y_test)* 100))) Accuracy Error ---------- -------- Logistic Regression : 90.88% 9.118% KNN : 89.61% 10.39% Random Forest : 100.0% 0.0% Naivebayes : 100.0% 0.0% Support Vector Machine : 90.49% 9.51% ---------- -------- Ensembling : 90.88% 9.118%