Космический корабль Титаник — это конкурс Kaggle ML. Цель этого состоит в том, чтобы предсказать, какие пассажиры смогли перейти в другое измерение.
В этом посте я объясню свой подход к решению этой проблемы. Так что, если вы готовы, пристегните ремни безопасности, чтобы начать это приключение.
Но сначала давайте познакомимся с нашими пассажирами или набором данных:
- 8693 образца – пассажиры
- Функции:HomePlanet, CryoSleep, Cabin, Destination, Age, VIP,
RoomService, FoodCourt, ShoppingMall, Spa, VRDeck, Name - Ярлык:перемещено
Пояснения к ярлыкам см. по ссылке на веб-сайт Kaggle.
Загрузка данных
Загрузите 3 файла csv (обучение, тест и отправка) с конкурса страница данных. (Submission.csv — это пример файла отправки, показывающий правильный формат.)
Загрузите наборы данных, прочитав файлы train.csv и test.csv с помощью pandas.
import pandas as pd train_dataFull = pd.read_csv('train.csv', index_col='PassengerId') test_dataFull = pd.read_csv('test.csv', index_col='PassengerId')
Предварительная обработка данных
Второй шаг — предварительная обработка данных для избавления от нулевых значений и кодирования нечисловых значений.
В этом наборе данных есть два ненужных столбца.
- Первым является столбец Name, потому что имена не являются числовыми данными и содержат слишком много уникальных значений.
- Второй столбец Cabin. В этом столбце 6560 уникальных значений. Вы можете проверить количество уникальных значений с помощью следующего кода.
print(len(train_dataFull['Cabin'].value_counts()))
Давайте удалим эти столбцы из набора данных.
train_data = train_dataFull.drop(['Cabin', 'Name'], axis=1) test_data = test_dataFull.drop(['Cabin', 'Name'], axis=1)
Определение X и y
y — это цель — то, что мы пытаемся предсказать.
y = train_data.Transported
Значения X — это входные данные — функции, которые позволяют нам прогнозировать. Другими словами, функции, кроме y.
X_train = train_data.drop(['Transported'], axis=1)
Разделение числовых и нечисловых данных
В этом наборе данных есть числовые и нечисловые данные. Чтобы создать модель и делать прогнозы, мы собираемся превратить нечисловые значения в категориальные переменные — таким образом, мы сможем представить их числами.
#columns with non-numeric data objectCols = list(X_train.select_dtypes(['object']).columns)
Столбцы объектов: HomePlanet, CryoSleep, Destination и VIP.
Работа с нулевыми значениями
Важно удалить нулевые значения из фрейма данных, поскольку они снижают точность модели.
Давайте проверим количество значений NA в столбце:
#check number of na values in the cols for col in features: print(col + ': ' + str(X_train[col].isna().sum()))
Как видно из вывода, среди 8693 значений есть от 179 до 217 нулевых значений. Другими словами, в этих столбцах отсутствует около 2,45% данных.
Мы собираемся вменить эти нулевые значения, используя разные стратегии.
Вот числовые столбцы с пропущенными значениями:
#imputation for Age, RoomService, FoodCourt, Shopping Mall, Spa, VRDeck - numeric cols colsMissingNumeric = ['Age', 'RoomService', 'FoodCourt', 'ShoppingMall', 'Spa', 'VRDeck']
Для числовых столбцов я решил заполнить их средними значениями.
Вы можете попробовать различные стратегии вменения, такие как среднее значение, медиана, наиболее частая и постоянная. Вот scikit-learn документация.
from sklearn.impute import SimpleImputer myImputerNumeric = SimpleImputer(strategy='mean') imputed_X_train_numeric = pd.DataFrame(myImputerNumeric.fit_transform(X_train[colsMissingNumeric])) imputed_test_numeric = pd.DataFrame(myImputerNumeric.transform(test_data[colsMissingNumeric]))
После этого преобразования мы теряем имена столбцов и индексы:
RangeIndex(начало=0, стоп=6, шаг=1)
#name imputed cols imputed_X_train_numeric.columns = X_train[colsMissingNumeric].columns imputed_test_numeric.columns = test_data[colsMissingNumeric].columns #add indexes imputed_X_train_numeric.index = X_train.index imputed_test_numeric.index = test_data.index
Теперь у нас нет пропущенных значений в числовых столбцах. Пришло время применить аналогичную стратегию к нечисловым столбцам.
Наиболее частые и постоянные стратегии можно использовать как для строковых, так и для числовых данных.
В этом примере я получил лучшие результаты со стратегией most_frequent.
#impute object cols before encoding myImputerObject = SimpleImputer(strategy='most_frequent') imputed_X_train_object = pd.DataFrame(myImputerObject.fit_transform(X_train[objectCols])) imputed_test_object = pd.DataFrame(myImputerObject.transform(test_data[objectCols])) #name imputed cols imputed_X_train_object.columns = X_train[objectCols].columns imputed_test_object.columns = test_data[objectCols].columns
Кодирование категориальных столбцов
Поскольку мы избавились от нулевых значений, теперь мы можем кодировать категориальные переменные. Давайте проверим, какие столбцы могут быть закодированы.
Идея здесь в том, что если в столбце слишком много уникальных значений, он будет постепенно увеличивать фрейм данных при кодировании. Поэтому мы кодируем только столбцы с максимум 15 уникальными значениями.
# check cols that can be encoded-less than 15 unique values for col in objectCols: print(train_dataFull[col].value_counts())
Как видно сверху:
Родная планета имеет 3 уникальных значения: Земля, Европа и Марс
CryoSleep имеет 2 уникальных значения (boolean)
Пункт назначения имеет 3 уникальных значения: TRAPPIST-1e, 55 Cancri e, PSO J318.5–22.
VIP имеет 2 уникальных значения (boolean)
Горячее кодирование
Так как между категориальными переменными нет порядковой связи (одна категориальная переменная не меньше или больше другой), может применяться однократное кодирование.
Для получения дополнительной информации о горячем кодировании перейдите по этой ссылке.
#encode imputed object cols with one hot encoding #these cols are not suitable for ordering and have low cardinality OH_encoder = OneHotEncoder(handle_unknown='ignore', sparse=False) OH_cols_train = pd.DataFrame(OH_encoder.fit_transform(imputed_X_train_object)) OH_cols_test = pd.DataFrame(OH_encoder.transform(imputed_test_object)) #add index column OH_cols_train.index = X_train.index OH_cols_test.index = test_data.index
Теперь у нас есть,
- фрейм данных вмененных числовых значений
- кадр данных вмененных и закодированных категориальных значений отдельно.
Мы можем объединить их с помощью следующего кода:
OH_X_train = pd.concat([imputed_X_train_numeric,OH_cols_train], axis=1) OH_X_valid = pd.concat([imputed_test_numeric,OH_cols_test], axis=1)
Создание модели
Я использовал два разных алгоритма для наблюдения за точностью прогнозов.
Алгоритм случайного леса
Регрессия случайного леса использует несколько деревьев решений, поэтому точность выше, чем у регрессора дерева решений. Он просто усредняет предсказания многих деревьев решений.
Для получения дополнительной информации об алгоритме случайного леса перейдите по ссылке эта ссылка.
titanic_model = RandomForestRegressor(n_estimators = 100, random_state = 0) titanic_model.fit(OH_X_train, y) predictions = titanic_model.predict(OH_X_valid)
с алгоритмом случайного леса точность: 0,78816
Алгоритм XGBoost
Gradient Boosting просто получает наивную модель, вычисляет потери, обучает модель в соответствии с ней и итеративно повторяет этот процесс.
Для получения дополнительной информации о XGBoost перейдите по этой ссылке.
#XGB titanic_model = XGBRegressor(n_estimators=1000, learning_rate=0.05) titanic_model.fit(OH_X_train, y) predictions = titanic_model.predict(OH_X_valid)
с XGBoost точность: 0,79120
Для получения дополнительной информации о XGBoost и алгоритме Random Forest вы также можете ознакомиться с этой статьей на Medium.
Полный исходный код доступен по моей ссылке на github. ✨
На этом наше приключение подошло к концу, спасибо за прочтение. Давайте встретимся в комментариях. 🚀