В рамках моего проекта по машинному обучению я имел удовольствие работать над созданием модели для выплаты финансовой помощи. С этим бизнес-кейсом было очень весело работать, и я приятно провел время, разбираясь в проблеме, думая о том, как очистить данные, чтобы в конечном итоге дать отличный прогноз, и в целом действительно улучшает мой процесс обучения.
Полный код можно найти на моем гитхабе здесь.
Вот формулировка проблемы:
Цель:
Определить уровень дохода, необходимый для выплаты финансовой помощи семьям в Латинской Америке.
Прежде чем приступить к проекту, я сделал некоторые предварительные выводы:
- Понимать данные через df.head()
- Поймите словарь данных — есть 143 столбца, которые относятся к арендному статусу человека, статусу и уровню образования, состоянию, состоянию их дома и его содержимому, например. владеет телевизором и т. д.
- Понимать типы данных; в основном категоричный
- Определяем модель: случайный лес
Примечание: я не буду вставлять все выходные данные (обратитесь к моей ссылке на github для полного вывода), а только пройдусь по обработке нулевых значений и моим мыслям о точности модели.
Мой подход:
- Понимание данных
Проверка типов данных (число с плавающей запятой, объекты, целое число), количество значений, пустые значения
2. Проверьте распределение целевой переменной y
Здесь я обнаружил, что данные для переменной y искажены влево. Это может указывать на то, что у меня может быть более высокая оценка точности из-за количества точек данных, которые имеет Target 4 по сравнению с остальными.
import matplotlib.pyplot as plt import seaborn as sns sns.set_style('darkgrid') # Create a countplot to visulaise the balance of the data set based on 'Target' variable. sns.countplot(x = 'Target', data = train, alpha=0.5).set_title('Target variable count plot') # Show the plot. plt.show()
2. Обработка нулевых значений
Как мы поняли из нулевых значений, есть 5 столбцов, в которых у нас есть нулевые значения, требующие обработки.
#Find columns with null values for float columns null_counts = train.select_dtypes('float64').isnull().sum() null_counts[null_counts > 0]
#Percentage of total counts total_counts = len(train) percentage = null_counts / total_counts *100 percentage #Null Value Treatments #(2) v2a1 (6,860) = Monthly rent payment - 71.8% #(9) v18q1 (7,342) = Number of all tablets household owns - 76.8% #(22) rez_esc (7,928) = Years behind in school - 82.9% #(104) meaneduc (5) = Average years of education for adults (18+) - 0.05% #(141) SQBmeaned (5) = Mean^2 years of education of adults (>=18) in the household - 0.05%
Понятно, что нам нужно быть осторожными при обработке первых 3 столбцов, поскольку их нулевое значение составляет огромную часть данных.
Обработка нулевого ежемесячного арендного платежа
Первый столбец, который нужно обработать, ежемесячная арендная плата, мой подход состоял бы в том, чтобы заменить его средними значениями его целевой группы (1–4) из-за огромного расхождения в медианных значениях между каждой целевой группой. Я также рассматривал возможность замены его нулевыми значениями, потому что те, у кого нулевые значения, в основном владели и заплатили за свой дом, являются нулевыми (я не включил код в свой github, так как я не использовал этот метод в конце), но решил против этого, поскольку вместо этого рекомендуется заменить его медианным значением — также в том случае, если нам может понадобиться выполнить некоторую регрессию.
Семья, использующая планшеты, не имеет лечения
Далее будет лечение таблеток, которыми владеет домохозяйство. Сначала я хотел удалить этот столбец, потому что есть еще один столбец, в котором указано, есть ли у домохозяйства планшет или нет, но я отказался от него, так как в этом столбце есть значения в диапазоне от 0 до 6, что может повлиять на результаты.
heads = train.loc[train['parentesco1'] == 1].copy() #only locating the household head heads.groupby('v18q')['v18q1'].apply(lambda x: x.isnull().sum()) #while on the household head dataframe, #group by owns a tablet - the one with null values #and get only the sum of the null values with tablet
Поскольку это нужно для проверки того, есть ли у домохозяйства планшеты, мы проверим только наличие планшета у главы домохозяйства, и с помощью этого кода мы обнаружим, что если у вас нет планшета, это составляет 2813 значений, поэтому мы Предположим, что если домохозяйство не «владеет планшетом», количество планшетов, которыми владеют другие члены домохозяйства, также должно быть «0».
Отношение к нулю в школе на несколько лет
Это сложный вопрос, потому что значение этого столбца кажется мне двусмысленным. В моем первоначальном коде, не на github, я обнаружил, что люди, которые в основном нулевые, — это люди в возрасте 17 лет и старше, которых можно считать «не посещающими школу». Но это дискредитирует студентов университета, и, возможно, было бы неправильно заменить его на 0. Вместо этого я решил полностью исключить этот столбец, поскольку есть другие столбцы, которые указывают на уровень образования человека, например. начальная/средняя/колледж и т. д.
Для оставшейся нулевой обработки они составляют 0,05% данных, поэтому я мог бы либо удалить их, либо заменить на нуль, поскольку это совершенно незначительно. Я решил не бросать, так как удаление человека может повлиять на остальную часть домохозяйства.
Запуск модели случайного леса
# Import the train_test_split function. from sklearn.model_selection import train_test_split # Split the predictor matrix X and the target vector y into training and testing sets with a 80-20 split ratio. # Set the random seed to '0' to ensure consistent result. X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0) #fitting the training data from sklearn.ensemble import RandomForestClassifier clf = RandomForestClassifier(criterion = 'gini', max_depth = 8, min_samples_split = 10, random_state = 5) # 'fit' method trains the model using the provided training data. clf.fit(X_train, y_train) #prediction y_pred = clf.predict(X_test) y_pred from sklearn.metrics import classification_report print(classification_report(y_pred, y_test))
# Import cross_val_predict function to review predicted values on the test dataset. from sklearn.model_selection import cross_val_predict # Print and review th predicted values. pred = cross_val_predict(clf, X_test, y_test) # Review the test data using CV = 10. # Perform Random Forest Classifier model (i.e., clf) on test data using cross-validation approach with 10 folds. scores_test = cross_val_score(clf, X_test, y_test, cv = 10) # Print average score of test data. print(np.mean(scores_test)) # Comment: # - 77.5% is the mean performance on test data using all folds (CV=10) cross-validation.
Как видите, наша оценка точности составляет 82%, а наша оценка перекрестной проверки — 77,5%, что может указывать на небольшое переоснащение данных. Сначала я запустил GridSearchCV, и максимальная глубина вывода составила 14. Однако это привело к оценке точности 95%, но с оценкой перекрестной проверки 85%, что составляет разительную разницу в 10%, что указывает на то, что модель была переоснащена. Поэтому я уменьшил максимальную глубину до 8 или 10 и обнаружил, что максимальная глубина 8 является самым низким показателем переобучения.
Моя интерпретация результатов:
- Есть больше возможностей для улучшения Задачи 1 и Задачи 3, и усилия должны быть сосредоточены на этом (вероятно, данных недостаточно для того, чтобы делать точные прогнозы, поскольку данные смещены прямо в сторону Задачи 4)
- Показатели отзыва для каждой цели высоки, что указывает на то, что люди точно классифицируются в соответствии с их целью (истинно отрицательные результаты, как правило, точны).
- Однако показатели точности ниже, особенно для целей 1 и 3, что указывает на то, что модель недостаточно конкретна в своих прогнозах для целей 1 и 3 и вместо этого предсказывает слишком много нецелевых случаев 1 и 3 в качестве целей 1 и 3.
- В целом показатель точности относительно высок и составляет 82%, однако эта модель не подходит для прогнозирования людей с Целями 1 и 3, и, следовательно, этим целям может быть предоставлена неточная финансовая помощь.
- Случайный лес является подходящей моделью для использования в этом бизнес-кейсе, но из-за точности результатов он может неточно выдавать соответствующие вспомогательные средства для 1 и 3.
Последние мысли
В целом, это действительно забавный проект для работы, поскольку мне пришлось много думать о том, как обрабатывать нулевые значения и столбцы типа объекта. В настоящее время я не уверен, как улучшить модель, возможно, может помочь удаление определенных столбцов и т. д. K-средние могут быть другим способом классификации данных, но из-за количества столбцов и сложности я считаю, что случайный лес будет лучшей моделью для этого бизнес-кейса.