Введение
Грибы могут быть вкусным дополнением к вашей еде, но определение съедобных может быть сложной задачей. Набор данных грибов UCI содержит исчерпывающий список признаков, которые могут помочь нам отличить ядовитые и съедобные грибы. В этой статье мы рассмотрим этот набор данных, чтобы классифицировать, является ли данный гриб ядовитым или нет. Наш процесс будет охватывать проверку качества данных, выбор функций, обучение модели, интерпретируемость модели и создание отчетов.
Цель
Наша цель — эффективно классифицировать грибы как съедобные или ядовитые на основе атрибутов набора данных. Для этого мы будем:
- Проверить качество данных
- Выполнить выбор функции
- Обучайте различные модели машинного обучения, выбирайте лучшую модель и точно настраивайте гиперпараметры.
- Интерпретируйте результаты модели
- Создавайте отчеты и визуализации, чтобы понять наши выводы
Установленные библиотеки
Для проведения нашего анализа мы будем использовать следующие библиотеки:
# import all the required libraries import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.preprocessing import LabelEncoder, StandardScaler from sklearn.model_selection import train_test_split, KFold from sklearn.linear_model import LinearRegression from sklearn.svm import SVC from collections import defaultdict from sklearn.feature_selection import chi2, SelectKBest, RFE, SelectFromModel, mutual_info_classif from sklearn.metrics import mean_squared_error, r2_score, confusion_matrix, accuracy_score from xgboost import XGBClassifier from sklearn.ensemble import RandomForestClassifier import shap import h2o import plotly.express as px import plotly.graph_objects as go import plotly.figure_factory as ff from plotly.subplots import make_subplots from sklearn.experimental import enable_iterative_imputer from sklearn.impute import SimpleImputer, IterativeImputer, KNNImputer
Чтение CSV-файла
# Reading the dataset data = pd.read_csv('mushrooms.csv')
Исследовательский анализ данных (EDA)
Мы начали наше исследование с EDA в наборе данных UCI Mushroom. Этот процесс позволил нам лучше понять набор данных и извлечь ценную информацию. Во время EDA мы обнаружили:
- Набор данных не содержал нулевых значений, что указывает на хорошее качество данных.
# check for the null values data.isnull().any()
2. Набор данных был сбалансированным, с примерно равным количеством съедобных и ядовитых грибов.
# Lets check the balance of the dataset counts = data['class'].value_counts() x_axis = counts.index y_axis = counts.values plt.figure(figsize=(8, 5)) sns.barplot(x=x_axis, y=y_axis)
3. После изучения распределения независимой переменной было замечено, что признаки «вуалевидность» и «жаберность» содержат значительное количество уникальных значений. Это указывает на возможность проблем корреляции между этими функциями, которые следует дополнительно изучить, чтобы обеспечить точный анализ и моделирование.
С помощью EDA мы также сделали несколько важных наблюдений:
- Затонувшие грибы обычно съедобны.
- Грибы с зеленым и фиолетовым цветом шляпки обычно съедобны.
- Запахи аниса и миндаля указывают на съедобные грибы, а другие запахи указывают на ядовитые.
- Прикрепленные жабры – признак ядовитых грибов.
- Зеленый и желтовато-коричневый цвета жабр обозначают съедобность, а красный и оранжевый - нет.
- Грибы пустошей обычно съедобны.
- Обильные, сгруппированные или многочисленные популяции грибов, как правило, безопасны для употребления.
Горячее кодирование
Чтобы подготовить наши категориальные данные для машинного обучения, мы использовали однократное кодирование. Этот метод преобразует категориальные признаки в двоичный формат, облегчая нашим моделям интерпретацию и обработку данных.
# One hot encode the categorical variable one_hot_data = pd.get_dummies(data) n = one_hot_data[['class_e', 'class_p']] # The label for the machine learning models M = one_hot_data.drop(['class_e', 'class_p'], axis=1) #Features M
Анализ тепловой карты
Мы использовали тепловую карту, чтобы визуализировать любую высокую коллинеарность между функциями. В результате нашего анализа мы обнаружили, что следующие признаки демонстрируют значительную коллинеарность:
- Жаберное приложение
- Кольцевой
- жаберный цвет
- синяки
Выбор функции
Чтобы еще больше уточнить наш набор данных, мы выполнили выбор признаков с использованием регрессии обычных наименьших квадратов (OLS). На основе нашего анализа мы выявили несколько несущественных особенностей:
# Looking for most relavant features import statsmodels.api as sm independent_variables_for_ols = list(data.columns) model = sm.OLS(data['class'], data[list(independent_variables_for_ols)]).fit() # Print out the statistics model.summary()
Учитывая значение точности 0,05
- Население (значение p: 0,19)
- Форма крышки (значение p: 0,22)
- Форма стебля (значение p: 0,19)
- Цвет стебля под кольцом (значение p: 0,049)
Эти функции были удалены из набора данных, поскольку они не будут существенно влиять на прогностическую силу нашей модели.
Обучение модели
Мы разделили наш набор данных, используя размер теста 0,2.
# X test data and x train data X_train, X_test, y_train, y_test = train_test_split(M, n, test_size=0.2) X_train.head()
МЫ обучили три разные модели: XGBoost, машины опорных векторов (SVM) и деревья решений. Удивительно, но все три модели достигли 100% точности. Мы использовали матрицу путаницы для визуализации результатов.
- XGBКлассификатор
# XG boost using the Classifiers XGB = XGBClassifier(learning_rate=0.005, max_depth=10, n_estimators=30, colsample_bytree=0.3, min_child_weight=0.5, reg_alpha=0.3, ) XGB.fit(X_train, y_train["class_e"]) xgb_prediction = XGB.predict(X_test) xgb_linear = accuracy_score(y_test['class_e'], xgb_prediction) print('Accuracy of SVM Model: %', 100 * xgb_linear) predictions_rf = pd.DataFrame(LR.predict(X_test)) plt.figure(figsize=(12, 8)) conf_mat = confusion_matrix(y_true=y_test['class_e'], y_pred=predictions_rf[0]) sns.heatmap(conf_mat, annot=True, fmt='g') plt.title('Confusion Matrix of the Test Data (Edible Class Based)', fontsize=14) plt.ylabel('Real Class', fontsize=12) plt.xlabel('Predicted Class', fontsize=12) plt.show()
2. Классификатор SVM
# Classification using one hot encoded data clf = SVC(kernel='linear', probability=True) clf.fit(X_train, y_train['class_e']) predictions_svm = clf.predict(X_test) acc_svm = accuracy_score(y_test['class_e'], predictions_svm) print('Accuracy of SVM Model: %', 100 * acc_svm) predictions_rf = pd.DataFrame(clf.predict(X_test)) plt.figure(figsize=(12, 8)) conf_mat = confusion_matrix(y_true=y_test['class_e'], y_pred=predictions_rf[0]) sns.heatmap(conf_mat, annot=True, fmt='g') plt.title('Confusion Matrix of the Test Data (Edible Class Based)', fontsize=14) plt.ylabel('Real Class', fontsize=12) plt.xlabel('Predicted Class', fontsize=12) plt.show()
3. Классификатор на основе дерева
# XG boost using the Classifiers dec = DecisionTreeClassifier() dec.fit(X_train, y_train["class_e"]) tree_prediction = dec.predict(X_test) accuracy_tree = accuracy_score(y_test['class_e'], tree_prediction) print('Accuracy of Decision Tree Model: %', 100 * accuracy_tree) predictions_rf = pd.DataFrame(tree.predict(X_test)) plt.figure(figsize=(12, 8)) conf_mat = confusion_matrix(y_true=y_test['class_e'], y_pred=predictions_rf[0]) sns.heatmap(conf_mat, annot=True, fmt='g') plt.title('Confusion Matrix of the Test Data (Edible Class Based)', fontsize=14) plt.ylabel('Real Class', fontsize=12) plt.xlabel('Predicted Class', fontsize=12) plt.show()
Чтобы найти лучшую модель, мы использовали H2OAutoML с максимум 25 моделями, максимальным временем выполнения 800 секунд и начальным значением 1. Затем мы создали таблицу лидеров, отображающую производительность каждой модели, что позволило нам сравнить и выбрать наиболее подходящий для нашей задачи.
from h2o.automl import H2OAutoML from h2o.estimators import H2OXGBoostEstimator # Convert the current data frame into H2O dataframe hf = h2o.H2OFrame(data) hf['class'] = hf['class'].asfactor() predictor_variables = hf.drop('class').columns # Train test split train, valid = hf.split_frame(ratios=[0.8], seed=1234) train aml_model = H2OAutoML(max_models=25, max_runtime_secs=800, seed=1) aml_model.train(x=predictor_variables, y='class', training_frame=train, validation_frame=valid) leader_board = aml_model.leaderboard leader_board.head(rows=leader_board.nrows)
График AUC
# plot the bar graph of AUC of each model lb = leader_board.as_data_frame() lb['model_type'] = lb['model_id'].apply(lambda x: x.split('_')[0]) fig = px.bar( lb, x='model_id', y='auc', color='model_type' ) fig.update_yaxes(range=[0.999, 1]) fig.show()
Интерпретируемость модели и сводка SHAP
Чтобы интерпретировать результаты нашей модели и понять, как различные функции влияют на съедобность, мы использовали значения SHAP (Shapley Additive ExPlanations). Сводная диаграмма SHAP предоставила следующую информацию:
- Каждая точка (красная и синяя) представляет собой особенность гриба.
- Красный цвет обозначает высокие значения характеристик, а синий цвет — низкие значения.
- Точки справа от оси Y положительно влияли на съедобность, а точки слева — отрицательно.
- Положение точки на оси x указывает на интенсивность ее воздействия на съедобность, при этом большее расстояние от оси соответствует более высокой интенсивности.
На сводном графике SHAP мы заметили, что:
- Более высокие значения запаха, как правило, оказывают положительное влияние на съедобность грибов.
- Меньшие значения размера жабр положительно повлияли на съедобность грибов.
- Пониженные значения поверхности ножки над кольцом улучшили съедобность гриба.
Важность функции
На основании нашего анализа были определены следующие признаки, наиболее важные для определения съедобности грибов:
- Запах
- Цвет печати спор
- Стволовой корень
- синяки
Здесь мы получаем важную переменную из automl_mode
# Automl model variable importance graph with maximum feature 10 aml_model.leader.varimp_plot(num_of_features=10)
Понимание важности этих признаков может помочь нам сосредоточить наши усилия на наиболее важных признаках при различении съедобных и ядовитых грибов.
Заключение
В этой статье мы изучили набор данных UCI Mushroom, чтобы классифицировать грибы как съедобные или ядовитые. Благодаря проверке качества данных, выбору признаков, обучению модели и интерпретируемости мы эффективно проанализировали и поняли набор данных. Наши результаты, в том числе наиболее важные признаки для определения съедобности, могут быть использованы для более точного определения грибов, безопасных для употребления в пищу в будущем.