
Вы задавались вопросом, почему Джек должен был умереть? Тогда этот проект может дать вам несколько советов.
Это также пример использования PySpark для машинного обучения.
Но имейте в виду, что PySpark часто используется в контексте больших данных, поэтому используемые данные являются лишь упрощением.
Предварительная информация
Прежде чем мы сможем углубиться: вот краткий обзор используемых моделей классификации, техника настройки гиперпараметров и пример методов оценки.
Логистическая регрессия:
Этот тип статистической модели (также известный как логит-модель) часто используется для классификации и прогнозной аналитики. Логистическая регрессия оценивает вероятность возникновения события, такого как голосование или неголосование, на основе заданного набора данных независимых переменных. Поскольку результат является вероятностью, зависимая переменная ограничена между 0 и 1.
Наивный Байес:
Наивный байесовский классификатор — это контролируемый алгоритм машинного обучения, который используется для задач классификации, таких как классификация текста. Он также является частью семейства алгоритмов генеративного обучения, что означает, что он стремится моделировать распределение входных данных данного класса или категории. Наивный байесовский классификатор также известен как вероятностный классификатор, поскольку он основан на теореме Байеса. Тем не менее, классификатор работает по-другому, поскольку он работает с несколькими ключевыми предположениями, за что получил титул «наивного». Предполагается, что предикторы в наивной байесовской модели условно независимы или не связаны с какими-либо другими функциями модели. Также предполагается, что все функции в равной степени влияют на результат. Хотя эти предположения часто нарушаются в реальных сценариях (например, последующее слово в электронном письме зависит от слова, которое ему предшествует), это упрощает задачу классификации, делая ее более поддающейся вычислительной обработке. То есть теперь для каждой переменной потребуется только одна вероятность, что, в свою очередь, упрощает расчет модели.
Древо решений:
Дерево решений — это непараметрический алгоритм обучения с учителем, который используется как для задач классификации, так и для задач регрессии. Он имеет иерархическую древовидную структуру, состоящую из корневого узла, ветвей, внутренних узлов и конечных узлов. Он начинается с корневого узла, который не имеет входящих ветвей. Исходящие ветви от корневого узла затем направляются во внутренние узлы, также известные как узлы принятия решений. На основе доступных функций оба типа узлов выполняют оценку для формирования однородных подмножеств, которые обозначаются конечными узлами или конечными узлами. Листовые узлы представляют все возможные результаты в наборе данных. Обучение дереву решений использует стратегию «разделяй и властвуй», проводя жадный поиск для определения оптимальных точек разделения в дереве. Затем этот процесс разделения повторяется рекурсивно сверху вниз до тех пор, пока все или большинство записей не будут отнесены к определенным меткам классов.
Случайный лес:
Этот алгоритм машинного обучения объединяет выходные данные нескольких деревьев решений для получения единого результата. Его простота использования и гибкость способствовали его принятию, поскольку он решает как задачи классификации, так и регрессии. Алгоритм случайного леса является расширением метода мешков, поскольку он использует как мешки, так и случайность признаков для создания некоррелированного леса деревьев решений. В методе мешков случайная выборка данных в обучающем наборе выбирается с заменой — это означает, что отдельные точки данных могут быть выбраны более одного раза. После создания нескольких выборок данных эти модели затем обучаются независимо, и в зависимости от типа задачи — например, регрессии или классификации — среднее значение или большинство этих прогнозов дают более точную оценку. Этот подход обычно используется для уменьшения дисперсии в зашумленном наборе данных. Случайность признаков, также известная как пакетирование признаков или «метод случайного подпространства», генерирует случайное подмножество признаков, что обеспечивает низкую корреляцию между деревьями решений. Это ключевое различие между деревьями решений и случайными лесами. В то время как деревья решений учитывают все возможные разделения функций, случайные леса выбирают только подмножество этих функций.
Дерево с градиентным усилением:
Подобно бэггингу и бустингу, бустинг градиента — это методология, применяемая поверх другого алгоритма машинного обучения. Неформально повышение градиента включает два типа моделей: «слабая» модель машинного обучения, которая обычно представляет собой дерево решений, и «сильная» модель машинного обучения, состоящая из нескольких слабых моделей. При повышении градиента на каждом этапе новая слабая модель обучается предсказывать «ошибку» текущей сильной модели. Затем слабая модель добавляется к сильной модели с отрицательным знаком, чтобы уменьшить ошибку сильной модели. Это итеративный процесс.
Настройка гиперпараметров
Можно повысить производительность модели с помощью гиперпараметров. Таким образом, поиск оптимальных гиперпараметров может помочь в создании наиболее эффективной модели. Гиперпараметры для модели можно выбрать с помощью нескольких методов, таких как случайный поиск, поиск по сетке, ручной поиск, байесовская оптимизация и т. д. В этом проекте мы использовали метод поиска по сетке, реализованный в пакете ML для spark.
Гиперпараметры — это переменные, которые можно указать при построении модели машинного обучения. Таким образом, гиперпараметры задаются перед указанием параметров или можно сказать, что гиперпараметры используются для оценки оптимальных параметров модели. Параметры — это переменные, которые используются алгоритмом машинного обучения для прогнозирования результатов на основе входных исторических данных. Они оцениваются с помощью алгоритма оптимизации самого алгоритма машинного обучения.
Но возникает вопрос, как найти эти наилучшие наборы гиперпараметров? Можно попробовать метод ручного поиска, используя процесс проб и ошибок, и найти лучшие гиперпараметры, на создание одной модели которых уйдет огромное время. Поэтому был введен поиск по сетке.
Grid Search использует различные комбинации всех указанных гиперпараметров и их значений, вычисляет производительность для каждой комбинации и выбирает наилучшее значение для гиперпараметров. Это делает обработку трудоемкой и дорогостоящей из-за количества задействованных гиперпараметров. Однако в данном случае этим можно пренебречь из-за небольшого размера набора данных.
Метрики оценки
а) Мера точности - это сумма правильного прогноза по общему количеству наблюдений.
b) Кривая рабочих характеристик приемника (ROC) является еще одним распространенным инструментом, используемым при двоичной классификации. Кривая ROC показывает истинную положительную скорость (т.е. отзыв) по сравнению с ложной положительной скоростью. Частота ложноположительных результатов — это доля отрицательных случаев, которые ошибочно классифицируются как положительные. Он равен единице минус истинная отрицательная ставка. Истинный отрицательный показатель также называется специфичностью. Следовательно, кривая ROC отображает чувствительность (отзыв) по сравнению с 1 — специфичностью. Чтобы вычислить точки на ROC-кривой, мы могли бы много раз оценивать модель логистической регрессии с разными порогами классификации, но это было бы неэффективно. К счастью, существует эффективный алгоритм, основанный на сортировке, который может предоставить нам эту информацию, называемый AUC. AUC означает «Площадь под кривой ROC». AUC измеряет всю двумерную область под всей кривой ROC от (0,0) до (1,1). AUC обеспечивает совокупный показатель производительности по всем возможным пороговым значениям классификации. Это позволяет нам сравнивать различные кривые ROC. Чем ближе ROC AUC модели к 1, тем лучше она разделяет классы и делает более точные прогнозы.
в) Метрики F1 используются в статистическом анализе бинарной классификации, F-оценка или F-мера являются мерой точности теста. Он рассчитывается на основе прецизионности и отзыва теста, где прецизионность — это количество истинно положительных результатов, деленное на количество всех положительных результатов, включая те, которые были идентифицированы неправильно, а полнота — это количество истинно положительных результатов, деленное на количество всех проб, которые должны были быть идентифицированы как положительные. Максимально возможное значение F-оценки равно 1,0, что указывает на идеальную точность и полноту, а наименьшее возможное значение равно 0, если либо точность, либо полнота равны нулю. Должен рассматриваться как критический, когда существует дисбаланс классов.
d) Матрица путаницы — это таблица NxN, в которой суммируется количество правильных и неправильных прогнозов, сделанных моделью классификации. Матрицы путаницы содержат достаточно информации для расчета различных показателей производительности, включая точность и полноту.
Оценка с k-кратной перекрестной проверкой:
В этом методе данные случайным образом разбиваются k-кратно на равные наборы. Один из наборов k-данных используется для проверки, а остальные наборы данных используются для обучения модели. Это делается в k-повторах. Наконец, среднее значение результатов формирует выходные данные модели. Для этой цели k может быть установлен произвольно, но обычно используется значение 5.
Следовательно, набор данных слегка несбалансирован. Было бы лучше использовать стратифицированную k-кратную перекрестную проверку. Он работает как k-кратная перекрестная проверка, но в отличие от нее стратифицированная перекрестная проверка сохраняет классовое распределение исходных данных в свертках. Однако он не включен в пакет python spark ML.
Теперь мы можем начать.
Подготовка данных
Для этого проекта использовался популярный набор данных Titanic, который вы можете найти здесь: https://www.kaggle.com/competitions/titanic.
Использовалась только обучающая выборка, предназначенная для создания моделей машинного обучения. Он служит «наземной истиной», предоставляя информацию о реальных пассажирах и позволяя точно оценивать и корректировать модель перед использованием новых данных. Такой подход предотвращает переоснащение и обеспечивает надежность моделей.
Чтобы сэкономить вычислительные затраты и время, а в некоторых случаях улучшить прогноз, вы можете выбрать специальные функции из всего набора данных. Этот шаг называется Выбор функции.
Раньше выбор признаков — это процесс уменьшения количества входных переменных при разработке прогностической модели. Желательно уменьшить количество входных переменных, чтобы уменьшить вычислительные затраты на моделирование и, в некоторых случаях, улучшить производительность модели. Кроме того, это может уменьшить переоснащение, поскольку меньшее количество избыточных данных означает меньшую способность принимать решения на основе шума.
Для этого проекта я решил использовать автоматизированную форму выбора функций.
Для этого используется случайная модель случайного леса для оценки важности функций. Это своего рода метод ансамблевого обучения, который объединяет результаты множества декоррелированных деревьев решений, собранных в «лес», для получения результата его классификации. Затем для каждого тестового узла дается случайная выборка из k характеристик из набора признаков, из которых каждое дерево решений должно выбрать наилучший признак для разделения данных на основе некоторого математического критерия (обычно индекса Джини). Эта случайная выборка характеристик приводит к формированию множества декоррелированных деревьев решений. Затем для модели используются признаки из модели с самым сильным прогнозом и наивысшей чистотой.
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.classification import NaiveBayes
from pyspark.ml.classification import DecisionTreeClassifier
from pyspark.ml.classification import RandomForestClassifier
from pyspark.ml.classification import GBTClassifier
from pyspark.ml.tuning import ParamGridBuilder, CrossValidator
from pyspark.ml.evaluation import BinaryClassificationEvaluator
from pyspark.mllib.evaluation import BinaryClassificationMetrics
from pyspark.sql.functions import *
from pyspark.ml.feature import StringIndexer, VectorAssembler, VectorSlicer
from pyspark.ml import Pipeline
from pyspark.ml.linalg import Vectors
from pyspark.ml.tuning import TrainValidationSplit
import pandas as pd
# Databricks used as the computation platform.
from pyspark.sql.functions import col
# File location and type
file_location = "/FileStore/tables/train.csv"
file_type = "csv"
# CSV options
infer_schema = "true"
first_row_is_header = "true"
delimiter = ","
# The applied options are for CSV files. Ignored for other file types.
df = spark.read.format(file_type) \
.option("inferSchema", infer_schema) \
.option("header", first_row_is_header) \
.option("sep", delimiter) \
.load(file_location)
# Choosing all of the columns and directly cast them for the Feature Selection
data = df.select(col('Survived').cast('float'),
col('Pclass').cast('float'),
col('Sex'),
col('Age').cast('float'),
col('Fare').cast('float'),
col('Embarked'),
col('Name'),
col('PassengerId').cast('float'),
col('SibSp').cast('float'),
col('Parch').cast('float'),
col('Ticket'),
col('Cabin')
)
data.show()

# Check balance of the dataset
data.groupby('Survived').agg({'Survived': 'count'}).show()
print("Most people have not survived")

# One-Hot Encoding the columns with datatype string with StringIndexer
from pyspark.ml.feature import StringIndexer
data = StringIndexer(
inputCol='Sex',
outputCol='Gender',
handleInvalid='keep').fit(data).transform(data)
data = StringIndexer(
inputCol='Embarked',
outputCol='Boarded',
handleInvalid='keep').fit(data).transform(data)
data = StringIndexer(
inputCol='Name',
outputCol='Passengername',
handleInvalid='keep').fit(data).transform(data)
data = StringIndexer(
inputCol='Ticket',
outputCol='TicketID',
handleInvalid='keep').fit(data).transform(data)
data = StringIndexer(
inputCol='Cabin',
outputCol='Cabinname',
handleInvalid='keep').fit(data).transform(data)
data.show()

# Drop not-encoded string columns because they are now transformed
data = data.drop('Sex')
data = data.drop('Embarked')
data = data.drop('Name')
data = data.drop('Ticket')
data = data.drop('Cabin')
# clean data from null values
data = data.replace('?', None)\
.dropna(how='any')
На следующем шаге необходимо создать Pipeline. Но что это?
ML Pipelines — это высокоуровневый API для MLlib, который находится в пакете spark.ml. Конвейер состоит из последовательности этапов. Существует два основных типа этапов конвейера: преобразователь и оценщик. Преобразователь принимает набор данных в качестве входных данных и создает расширенный набор данных в качестве выходных данных. Например, токенизатор — это преобразователь, который преобразует набор данных с текстом в набор данных с токенизированными словами. Оценщик должен сначала соответствовать входному набору данных, чтобы создать модель, которая является преобразователем, который преобразует входной набор данных. Последний используется для автоматического выбора признаков.
Метод проб и ошибок привел к пониманию того, что слишком много различных опций в категориальных данных вызывают проблемы. Для простоты я исключил из набора данных имя, идентификатор пассажира, название билета и название салона.
Давайте двигаться дальше.
# Assemble all the features with VectorAssembler
required_features2 = ['Pclass',
'Age',
'Fare',
'SibSp',
'Parch',
'Gender',
'Boarded']
from pyspark.ml.feature import VectorAssembler
assembler2 = VectorAssembler(inputCols=required_features2,
outputCol='features')
# Random random forest model to get the feature importance score
rf = RandomForestClassifier(labelCol="Survived",
featuresCol="features",
seed = 1234,
numTrees=10,
cacheNodeIds = True,
subsamplingRate = 0.7)
# Define Pipeline
stages = []
stages += [assembler2]
pipe = Pipeline(stages = stages + [rf])
# Fit Pipeline to data
mod = pipe.fit(data)
# Make predictions
df2 = mod.transform(data)
# The feature importance score that is in the form of a sparse vector.
mod.stages[-1].featureImportances

# Function for extracting important features: Mapping score and feature
# Based on: https://www.timlrx.com/blog/feature-selection-using-feature-importance-score-creating-a-pyspark-estimator
def ExtractFeatureImp(featureImp, dataset, featuresCol):
list_extract = []
for i in dataset.schema[featuresCol].metadata["ml_attr"]["attrs"]:
list_extract = list_extract + dataset.schema[featuresCol].metadata["ml_attr"]["attrs"][i]
varlist = pd.DataFrame(list_extract)
varlist['score'] = varlist['idx'].apply(lambda x: featureImp[x])
return(varlist.sort_values('score', ascending = False))
# Show most important features
gini_features = ExtractFeatureImp(mod.stages[-1].featureImportances,
df2,
"features")
print(gini_features)

Результат выбора функции:
Выбор признаков со случайным лесом и поддержка индекса Джини показали, что признаки «Пол», «Pclass», «Возраст» и «Проезд» являются лучшими для модели. Таким образом, модели будут обучаться вместе с ними.
Запуск моделей:
# Assemble all the features with VectorAssembler
required_features = ['Pclass',
'Age',
'Fare',
'Gender'
]
from pyspark.ml.feature import VectorAssembler
assembler = VectorAssembler(inputCols=required_features, outputCol='features')
transformed_data_fs = assembler.transform(data)
# 80 20 split is common and delivered the best results
(training_data_fs, test_data_fs) = transformed_data_fs.randomSplit([0.8,0.2],
seed=1333)
# Models
# 1) Logistic Regression
lr_fs = LogisticRegression(labelCol="Survived", featuresCol="features")
# Create a parameter grid for tuning the model with random assessed numbers
lrparamGrid_fs = (ParamGridBuilder()
.addGrid(lr_fs.regParam, [0.01, 0.1, 0.5, 1.0, 2.0])
.addGrid(lr_fs.elasticNetParam, [0.0, 0.25, 0.5, 0.75, 1.0])
.addGrid(lr_fs.maxIter, [1, 5, 10, 20, 50])
.build())
# Define the evaluator
lrevaluator_fs = BinaryClassificationEvaluator(labelCol="Survived",
rawPredictionCol="rawPrediction",
metricName = "areaUnderROC")
# Create 5-fold CrossValidator
lrcv_fs = CrossValidator(estimator = lr_fs,
estimatorParamMaps = lrparamGrid_fs,
evaluator = lrevaluator_fs,
numFolds = 5)
# Train model
lrcvModel_fs = lrcv_fs.fit(training_data_fs)
# Prediction on test data
lrpredictions_fs = lrcvModel_fs.transform(test_data_fs)
# 2) Naive Bayes
nb_fs = NaiveBayes(labelCol="Survived", featuresCol="features")
# Create a parameter grid for tuning the model with random assessed numbers
nbparamGrid_fs = (ParamGridBuilder()
.addGrid(nb_fs.smoothing, [0.0, 0.2, 0.4, 0.6, 0.8, 1.0])
.build())
# Define the evaluator
nbevaluator_fs = BinaryClassificationEvaluator(labelCol="Survived",
rawPredictionCol="rawPrediction",
metricName = "areaUnderROC")
# Create 5-fold CrossValidator
nbcv_fs = CrossValidator(estimator = nb_fs,
estimatorParamMaps = nbparamGrid_fs,
evaluator = nbevaluator_fs,
numFolds = 5)
# Train model
nbcvModel_fs = nbcv_fs.fit(training_data_fs)
# Prediction on test data
nbpredictions_fs = nbcvModel_fs.transform(test_data_fs)
# 3) Decision Tree
dt_fs = DecisionTreeClassifier(labelCol="Survived", featuresCol="features")
# Create a parameter grid for tuning the model with random assessed numbers
dtparamGrid_fs = (ParamGridBuilder()
.addGrid(dt_fs.maxDepth, [2, 5, 10])
.addGrid(dt_fs.maxBins, [10, 20])
.build())
# Define the evaluator
dtevaluator_fs = BinaryClassificationEvaluator(labelCol="Survived",
rawPredictionCol="rawPrediction",
metricName = "areaUnderROC")
# Create 5-fold CrossValidator
dtcv_fs = CrossValidator(estimator = dt_fs,
estimatorParamMaps = dtparamGrid_fs,
evaluator = dtevaluator_fs,
numFolds = 5)
# Train model
dtcvModel_fs = dtcv_fs.fit(training_data_fs)
# Prediction on test data
dtpredictions_fs = dtcvModel_fs.transform(test_data_fs)
# 4) Random Forest
rf_fs = RandomForestClassifier(labelCol="Survived", featuresCol="features")
# Create a parameter grid for tuning the model with random assessed numbers
rfparamGrid_fs = (ParamGridBuilder()
.addGrid(rf_fs.maxDepth, [2, 5, 10])
.addGrid(rf_fs.maxBins, [5, 10, 20])
.addGrid(rf_fs.numTrees, [5, 20, 50])
.build())
# Define the evaluator
rfevaluator_fs = BinaryClassificationEvaluator(labelCol="Survived",
rawPredictionCol="rawPrediction",
metricName = "areaUnderROC")
# Create 5-fold CrossValidator
rfcv_fs = CrossValidator(estimator = rf_fs,
estimatorParamMaps = rfparamGrid_fs,
evaluator = rfevaluator_fs,
numFolds = 5)
# Train model
rfcvModel_fs = rfcv_fs.fit(training_data_fs)
# Prediction on test data
rfpredictions_fs = rfcvModel_fs.transform(test_data_fs)
# 5) Gradient Boosted Tree
gb_fs = GBTClassifier(labelCol="Survived", featuresCol="features")
# Create a parameter grid for tuning the model with random assessed numbers
gbparamGrid_fs = (ParamGridBuilder()
.addGrid(gb_fs.maxDepth, [2, 5, 10])
.addGrid(gb_fs.maxBins, [10, 20, 40])
.addGrid(gb_fs.maxIter, [5, 10, 20])
.build())
# Define the evaluator
gbevaluator_fs = BinaryClassificationEvaluator(labelCol="Survived",
rawPredictionCol="rawPrediction",
metricName = "areaUnderROC")
# Create 5-fold CrossValidator
gbcv_fs = CrossValidator(estimator = gb_fs,
estimatorParamMaps = gbparamGrid_fs,
evaluator = gbevaluator_fs,
numFolds = 5)
# Train model
gbcvModel_fs = gbcv_fs.fit(training_data_fs)
# Prediction on test data
gbpredictions_fs = gbcvModel_fs.transform(test_data_fs)
# model evaluation
for model in ["lrpredictions_fs", "dtpredictions_fs",
"rfpredictions_fs", "nbpredictions_fs", "gbpredictions_fs"]:
df = globals()[model]
tp_fs = df[(df.Survived == 1) & (df.prediction == 1)].count()
tn_fs = df[(df.Survived == 0) & (df.prediction == 0)].count()
fp_fs = df[(df.Survived == 0) & (df.prediction == 1)].count()
fn_fs = df[(df.Survived == 1) & (df.prediction == 0)].count()
a_fs = ((tp_fs + tn_fs)/df.count())
if(tp_fs + fn_fs == 0.0):
r_fs = 0.0
p_fs = float(tp_fs) / (tp_fs + fp_fs)
elif(tp_fs + fp_fs == 0.0):
r_fs = float(tp_fs) / (tp_fs + fn_fs)
p_fs = 0.0
else:
r_fs = float(tp_fs) / (tp_fs + fn_fs)
p_fs = float(tp_fs) / (tp_fs + fp_fs)
if(p_fs + r_fs == 0):
f1_fs = 0
else:
f1_fs = 2 * ((p_fs * r_fs)/(p_fs + r_fs))
print("Model:", model)
print("True Positives with Feature Selection:", tp_fs)
print("True Negatives with Feature Selection:", tn_fs)
print("False Positives with Feature Selection:", fp_fs)
print("False Negatives with Feature Selection:", fn_fs)
print("Total with Feature Selection:", data.count())
print("Accuracy with Feature Selection:", a_fs)
print("Recall with Feature Selection:", r_fs)
print("Precision with Feature Selection: ", p_fs)
print("F1 score with Feature Selection:", f1_fs)
print('AUC:', BinaryClassificationMetrics(df['Survived','prediction'].rdd).areaUnderROC)
print("\n")
# metrics evaluation after feature selection
data_after_fs = [{"ID": 1, "Model": 'Logistic Regression', "Accuracy": 0.7969, "F1": 0.7379, "ROC-AUC": 0.7851},
{"ID": 2, "Model": 'Naive Bayes', "Accuracy": 0.7218, "F1": 0.6022, "ROC-AUC": 0.7069},
{"ID": 3, "Model": 'Decision Tree', "Accuracy": 0.8270, "F1": 0.7425, "ROC-AUC": 0.8336},
{"ID": 4, "Model": 'Random Forest', "Accuracy": 0.8346, "F1": 0.7885, "ROC-AUC": 0.8243},
{"ID": 5, "Model": 'Gradient Boosted Tree', "Accuracy": 0.8571, "F1": 0.7816, "ROC-AUC": 0.8846}
]
from pyspark.sql import SparkSession
spark_after_fs = SparkSession.builder.getOrCreate()
df_evaluation_temp_after_fs = spark_after_fs.createDataFrame(data_after_fs)
df_evaluation_after_fs = df_evaluation_temp_after_fs.select(["ID","Model","Accuracy","F1", "ROC-AUC"])
display(df_evaluation_after_fs)

# Extracting the best parameters from the best model bestModel_gb_fs = gbcvModel_fs.bestModel bestModel_gb_fs.extractParamMap()

Полученные результаты
На основании анализа можно сделать вывод, что наиболее важными факторами, влияющими на вероятность выживания, являются забронированный класс, возраст, стоимость проезда и пол пассажиров.
Важно отметить, что при оценке результатов моделей необходимо учитывать несбалансированность набора данных. Хотя метрики точности и f1-оценки широко используются, они придают большее значение истинным положительным результатам, которые могут не давать точного представления о производительности модели.
Поэтому рекомендуется ориентироваться на результаты метрики ROC-AUC, которая обеспечивает более полную оценку моделей.
Результаты ROC-AUC показывают, что для прогнозирования живучести в этом наборе данных следует в первую очередь использовать более сложную модель «Gradient Boosted Tree». Особенно со следующими гиперпараметрами: maxDepth 2, maxBins 40 и maxIter 20.
Ограничения
Важно знать об ограничениях этого проекта. Во-первых, используемый набор данных имеет ограниченный размер и содержит в основном категориальные данные, что приводит к низкой информативности.
Во-вторых, выбор признаков был сделан автоматически с использованием модели случайного леса. Существуют и другие возможности выбора функций, которые могут привести к другим результатам.
В-третьих, набор данных несбалансирован, и использование разных методов балансировки также может привести к разным результатам. Кроме того, в наборе данных Титаника отсутствуют некоторые точки данных, что может повлиять на результаты анализа и моделей.
Наконец, объем проекта ограничен, поскольку он включает только информацию о пассажирах и не включает членов экипажа или другие факторы, которые могли повлиять на результаты. Эти ограничения следует учитывать при интерпретации результатов анализа и моделей проекта.
Подводя итог, остается еще много вариантов для дальнейшего анализа.
Удачного кодирования!