Титаническая задача - одно из самых популярных соревнований на Kaggle и отличный проект, которым стоит заняться как начинающий специалист по данным. Эта разбивка проекта включает несколько советов и приемов, которые помогут получить точность более 70%. Усовершенствовать это оставлено на ваше усмотрение.
Цель - точное предсказание выживших среди пассажиров Титаника. В этом блокноте 82,26% - это лучший результат по обучающей выборке с использованием логистической регрессии, а 0,77 - это общедоступный результат.

Ниже представлен обзор предпринятых шагов

  1. Исследование данных
  2. Очистка данных
  3. Функциональная инженерия
  4. Предварительная обработка данных
  5. Разработка и сравнение моделей
  6. Результаты
  7. Подчинение
  8. Исследование данных

Давайте прочитаем наши обучающие данные и посмотрим на первые десять строк. Здесь цель состоит в том, чтобы иметь правильное представление о типе данных, содержащихся в каждом столбце.

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
df=pd.read_csv('/kaggle/input/titanic/train.csv')
df

Теперь давайте проверим, нет ли пустых / пропущенных значений.

l=df.isnull().sum()
print(l , df.shape)

Теперь мы можем видеть количество пропущенных значений в столбцах «Возраст», «Кабина» и «Прибыл»; позже мы сделаем несколько вменений, чтобы справиться с ними.

В ячейке ниже содержится код для проверки степени корреляции между столбцами; обратите внимание, что ожидается, что каждый столбец будет идеально коррелирован сам с собой. Столбцы с наибольшей корреляцией - это столбец «SipSp» (соотношение между родственными и родительскими объектами) и столбцы «Parch» (соотношение родительских и дочерних элементов).

Нам нужно хорошо разбираться в наших данных. Таким образом, мы будем исследовать коэффициенты выживаемости (зависимая переменная) для каждого столбца (независимые переменные).
Давайте сначала посмотрим на общую выживаемость.

sns.countplot(data=df, x='Survived')

Из приведенного выше сюжета ясно, что погибло больше людей, чем выжило; более 500 пассажиров погибли, менее 400 выжили. Давайте посмотрим, как независимые переменные (пол, возраст, посадка, стоимость проезда, P-класс и т. Д.) Связаны с выживаемостью. Мы бы начали с секса.

На графиках ниже показана выживаемость по половому признаку. График слева показывает общее количество мужчин и женщин, которые поднялись на борт корабля, а график справа показывает количество выживших или нет мужчин и женщин. Менее 110 (20 процентов) самцов на корабле выжили, в то время как более 200 (70 процентов) самок выжили. Следовательно, у самки больше шансов на выживание (в 4 раза больше), чем у самца.

from matplotlib import pyplot as plt
fig, axes = plt.subplots(1,2, figsize=(20,5))
sns.countplot(ax=axes[0], data=df,x='Sex')
sns.countplot(ax=axes[1],data=df,x='Sex',hue='Survived')

мы можем продолжить, чтобы проверить выживаемость по отношению к точке посадки

sns.set_palette('Paired')
fig, axes = plt.subplots(1,2, figsize=(20,5))
sns.countplot(ax=axes[0], data=df,x='Embarked')
sns.barplot(ax=axes[1],data=df, x= 'Embarked', y='Survived')

График слева показывает общее количество пассажиров, высадившихся из разных точек, при этом «nan» обозначает пассажиров, место посадки которых не зарегистрировано. График справа представляет процент выживших пассажиров с каждой точки посадки. Из графика видно, что пассажиры, которые садились в 'C', имели более высокие шансы на выживание, 55% из них выжили, в то время как менее 40% пассажиров, которые садились в 'S' и 'C', выжили с 'S 'имеют самую низкую выживаемость (обратите внимание, что очень немногие пассажиры не записали свою точку посадки, и все они выжили).

Ниже приведены данные о выживаемости мужчин и женщин в зависимости от того, откуда они отправились.

sns.set_palette('Paired')
fig, axes = plt.subplots(1,2, figsize=(20,5))
sns.countplot(ax=axes[0], data=df,x='Embarked', hue='Survived')
sns.barplot(ax=axes[1],data=df, x= 'Embarked', y='Survived', hue='Sex')

График выше показывает, что выжило больше самок, вышедших из каждой категории.

Давайте продолжим и проверим выживаемость по отношению к классу пассажиров (Pclass).

fig, axes = plt.subplots(1,2, figsize=(20,5))
sns.countplot(ax=axes[0], data=df,x='Pclass')
sns.barplot(ax=axes[1], data=df,x='Sex',y='Survived', hue="Pclass")

Из графиков видно, что больше пассажиров было в пассажирском классе «3», тогда как наименьшее количество пассажиров было в классе «2». И наоборот, пассажиры мужского и женского пола в пассажирском классе «3» имели самый низкий шанс на выживание, в то время как пассажиры класса «1» имели самый высокий шанс на выживание.

Далее мы будем проверять выживаемость по возрасту.

sns.histplot(data=df,x='Age')

Учитывая, что у нас более 800 пассажиров, ниже представлена ​​возрастная структура наших пассажиров. Большинство пассажиров находятся в возрасте от 15 до 40 лет. Если мы построим график зависимости между возрастом и выживаемостью, мы получим загроможденный график из-за широкого диапазона различных значений тарифов. Следовательно, мы разделим тарифы на тарифные группы в новом столбце. Теперь мы создаем столбец, в котором мы группируем возрасты в группы по 10 и сортируем их для удобства построения графиков, а также четкий график, показывающий выживаемость в зависимости от возраста и пола.

Age_group=[]
for c in df.Age:
    if c<11:
        Age_group.append("0-10")
    elif 10<c<21:
        Age_group.append("11-20")
    elif 20<c<31:
        Age_group.append("21-30")
    elif 30<c<41:
        Age_group.append("31-40")
    elif 40<c<51:
        Age_group.append("41-50")
    elif 50<c<61:
        Age_group.append("51-60")
    elif 60<c<71:
        Age_group.append("61-70")
    else:
        Age_group.append("71-80")      
 
df['age_group']=Age_group
fig, axes = plt.subplots(1,2, figsize=(20,5))
sns.set_palette('Paired')
df1=df.sort_values('Age', ascending=True)
sns.countplot(ax=axes[0], data=df1,x='age_group', hue="Survived")
sns.barplot(ax=axes[1], x='age_group', hue='Sex', data=df1, y='Survived')

На графике слева мы видим, что большинство выживших относились к возрастной группе 21–30 лет, а те, кто выжил в возрасте 61–70 лет, выжили меньше всего. На графике справа мужчины в возрастной группе 0–10 лет имели почти такие же шансы на выживание, как и женщины в той же возрастной группе, и это возрастная группа для мужчин с самой высокой вероятностью выживания. График ниже дает нам более четкое представление о возрастной группе с наибольшими шансами на выживание среди мужчин и женщин.

sns.barplot(data=df, x='Sex',hue='age_group',  y='Survived')

График ниже показывает выживаемость для SibSp (количество братьев и сестер / родителей), пассажиры с 0 и 1 «SibSP» имеют самый высокий шанс на выживание; тогда как у тех, у кого есть 6 и 8, самый низкий шанс на выживание (0 возможностей выживания).

fig, axes = plt.subplots(1,2, figsize=(20,5))
sns.countplot(ax=axes[0], data=df,x='SibSp')
sns.countplot(data=df, x='SibSp', hue='Survived')

глядя на выживаемость для «Parch» (количество детей / родителей), мы видим, что у большинства пассажиров «Parch» было 0, а 6 - наименьшее. Однако пассажиры с «Parch» равным 2 имели 50% шанс на выживание, что является наивысшим шансом на выживание в отношении «Parch».

fig, axes = plt.subplots(1,2, figsize=(20,5))
sns.countplot(ax=axes[0], data=df,x='Parch')
sns.countplot(data=df, x='Parch', hue='Survived')

Если мы построим график зависимости между тарифами на проезд и выживаемостью, мы получим загроможденный график из-за широкого диапазона различных значений тарифов. Следовательно, мы разделим тарифы на тарифные группы в новом столбце.

fare_group=[]
for c in df.Fare:
    if c<11:
        fare_group.append("0-10")
    elif 10<c<21:
        fare_group.append("11-20")
    elif 20<c<31:
        fare_group.append("21-30")
    elif 30<c<41:
        fare_group.append("31-40")
    elif 40<c<51:
        fare_group.append("41-50")
    elif 50<c<101:
        fare_group.append("50-100")
    elif 100<c<201:
        fare_group.append("101-200")
    elif 200<c<301:
        fare_group.append("201-300")
    elif 300<c<401:
        fare_group.append("301-400")
    elif 400<c<501:
        fare_group.append("401-500")
    else:
        fare_group.append("501-550")      
 
df['Fare_group']=fare_group
df['Fare_group'].value_counts()
#output below
0-10       364
11-20      160
21-30      142
50-100     106
31-40       50
101-200     33
201-300     17
41-50       16
501-550      3

Выходная ячейка выше показывает количество для каждой тарифной группы; мы можем продолжить и отсортировать столбец fare_group, а затем построить графики, используя столбцы fare_group

df2=df.sort_values('Fare', ascending=True)
fig, axes = plt.subplots(1,2, figsize=(20,5))
sns.barplot(ax=axes[1], x='Fare_group', hue='Sex', data=df2, y='Survived')
sns.countplot(ax=axes[0],data=df2, x='Fare_group', hue='Survived')

Из приведенных выше графиков видно, что большее количество пассажиров заплатило в диапазоне от 0 до 10, а женщины имели более высокий коэффициент выживаемости в каждой тарифной группе, за исключением тех, которые заплатили в диапазоне 501-550, где выжили все.

ОЧИСТКА ДАННЫХ

Давайте посмотрим, где у нас есть нулевые значения.

df.drop(['age_group','Fare_group'], axis=1,inplace =True)
d=df.isnull().sum()
d
#output
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2

У нас есть большое количество нулевых значений, поэтому их удаление не было бы разумным шагом, поскольку это означало бы потерю более половины наших данных. Следовательно, мы будем делать некоторые вменения. Однако давайте сначала внимательно посмотрим на наш тестовый набор.

test_data=pd.read_csv('/kaggle/input/titanic/test.csv')
test_data.head

Чтобы упростить нашу работу при очистке, предварительной обработке и выполнении импутации, мы объединим наши наборы тестов и обучения вместе, чтобы выполнить ранее упомянутые шаги один раз без необходимости повторять какие-либо операции как для обучающего, так и для тестового набора.

all_data=pd.concat([df,test_data], ignore_index=True)  # we are setting the ignore_index to true so our combined data set would be indexed continously (indexed from 0_1309)
all_data.head

Теперь, когда мы объединили наш набор данных, давайте посмотрим на сводку по каждому столбцу, чтобы определить столбцы с пропущенными значениями.

all_data.info()
#output
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1309 entries, 0 to 1308
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  1309 non-null   int64  
 1   Survived     891 non-null    float64
 2   Pclass       1309 non-null   int64  
 3   Name         1309 non-null   object 
 4   Sex          1309 non-null   object 
 5   Age          1046 non-null   float64
 6   SibSp        1309 non-null   int64  
 7   Parch        1309 non-null   int64  
 8   Ticket       1309 non-null   object 
 9   Fare         1308 non-null   float64
 10  Cabin        295 non-null    object 
 11  Embarked     1307 non-null   object 
dtypes: float64(3), int64(4), object(5)
memory usage: 122.8+ KB

В столбце «Embarked» отсутствуют два столбца (1307 из 1309 значений), в столбце «Cabin» отсутствует более 1000 значений, а в столбце «Age» - немногим более 200 значений. Давайте начнем наши вменения со столбца «Выполнено».

all_data.Embarked.unique()
#output
array(['S', 'C', 'Q', nan], dtype=object)

В ячейке выше показаны все уникальные значения из столбца Embarked, мы видим, что столбец содержит значения «nan». Давайте напишем код для замены значений nan на те, которые имеют максимальное вхождение. В ячейке ниже проверяется количество всех значений в столбце.

all_data.value_counts()

«S» встречается чаще, чем любое другое значение, поэтому мы бы заменили значения «nan» на «S». Сначала нам нужно получить расположение значений «nan», что и сделано в ячейке ниже.

for i,j in enumerate(all_data.Embarked):  # gettin a value pair of each value (i) and its index location (j)
    if type(j)!=str:
        print(i,j)
#ouput
61 nan
829 nan

Теперь, когда у нас есть индекс значений «nan», мы можем ввести значение с самой высокой частотой, то есть «S», и проверить, было ли наше вменение успешным.

all_data.Embarked[61]='S'
all_data.Embarked[829]='S'
all_data.Embarked.value_counts()
#output
S    916
C    270
Q    123
Name: Embarked, dtype: int64

В столбце «Стоимость» отсутствует только одно значение. В приведенной ниже ячейке проверяются все строки столбца «Стоимость» на отсутствие пропущенного значения и заменяется средним значением всех значений в столбце.

for i,j in enumerate(all_data.Fare):  # gettin a value pair of each value (i) and its index location (j)
    if np.isnan(j):
         all_data.Fare[i]=test_data.Fare.mean()
print(all_data.Fare[i])
#output
22.3583

Чтобы заполнить значения в столбце «Возраст», мы бы применили другой подход, сгруппировав пассажиров по полу, Pclass и Embarked до получения их среднего возраста для каждой группы. Это должно дать нам лучший результат, чем просто обобщение среднего возраста всех пассажиров. Мы бы использовали метод group_by, чтобы реализовать это.

df1=all_data.groupby(['Sex','Pclass','Embarked']).mean()
df1

Следующим шагом будет замена значений null (nan) на средний возраст для соответствующих групп. В ячейке ниже содержится цикл, который просматривает все строки в столбце «Возраст», проверяет группу, к которой они принадлежат, и вычисляет средний возраст для этой группы. (Если пассажир мужчина, каков его класс и, наконец, откуда он взошел, прежде чем вычислить средний возраст пассажиров из этой группы).

for j,i in enumerate(all_data.Age): # gettin a value pair of each value (i) and its index location (j)
    if np.isnan(i):   # checking if the value is a null (nan) value
        if all_data.Sex[j]=='female':   #check the sex using the index (j) locaion
            if all_data.Pclass[j] == 1:  # check the Pclass using the index (j) locaion
                if all_data.Embarked[j]=='C':  # check where the passenger embarked from using the index (j) locaion
                    all_data.Age[j]=38  # impute mean age for that group using the index (j) locaion
                if all_data.Embarked[j]=='Q':
                    all_data.Age[j]=35
                if all_data.Embarked[j]=='S':
                    all_data.Age[j]=35
            if all_data.Pclass[j] == 2:
                if all_data.Embarked[j]=='C':
                    all_data.Age[j]=23
                if all_data.Embarked[j]=='Q':
                    all_data.Age[j]=30
                if all_data.Embarked[j]=='S':
                    all_data.Age[j]=28
            if all_data.Pclass[j] == 3:
                if all_data.Embarked[j]=='C':
                    all_data.Age[j]=15
                if all_data.Embarked[j]=='Q':
                    all_data.Age[j]=22
                if all_data.Embarked[j]=='S':
                    all_data.Age[j]=22
        if all_data.Sex[j]=='male':
            if all_data.Pclass[j] == 1:
                if all_data.Embarked[j]=='C':
                    all_data.Age[j]=39
                if all_data.Embarked[j]=='Q':
                    all_data.Age[j]=44
                if all_data.Embarked[j]=='S':
                    all_data.Age[j]=42
            if all_data.Pclass[j] == 2:
                if all_data.Embarked[j]=='C':
                    all_data.Age[j]=29
                if all_data.Embarked[j]=='Q':
                    all_data.Age[j]=59
                if all_data.Embarked[j]=='S':
                    all_data.Age[j]=29
            if all_data.Pclass[j] == 3:
                if all_data.Embarked[j]=='C':
                    all_data.Age[j]=24.25
                if all_data.Embarked[j]=='Q':
                    all_data.Age[j]=25
                if all_data.Embarked[j]=='S':
                    all_data.Age[j]=25

Давайте проверим, было ли наше условное исчисление для столбца возраста успешным.

all_data.info()
#output
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1309 entries, 0 to 1308
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  1309 non-null   int64  
 1   Survived     891 non-null    float64
 2   Pclass       1309 non-null   int64  
 3   Name         1309 non-null   object 
 4   Sex          1309 non-null   object 
 5   Age          1309 non-null   float64
 6   SibSp        1309 non-null   int64  
 7   Parch        1309 non-null   int64  
 8   Ticket       1309 non-null   object 
 9   Fare         1309 non-null   float64
 10  Cabin        295 non-null    object 
 11  Embarked     1309 non-null   object 
dtypes: float64(3), int64(4), object(5)

Из приведенного выше у нас есть 1309 ненулевых значений, которые представляют собой общее количество значений в столбце.

ОСОБЕННОСТИ ИНЖИНИРИНГА

В этом разделе мы будем генерировать новые функции (столбцы) из существующих функций. ЦЕЛЬ ЭТОГО - РАЗРАБОТАТЬ ПОЛЕЗНЫЕ ФУНКЦИИ, КОТОРЫЕ МОГУТ УЛУЧШИТЬ НАШИ ПРОГНОЗЫ.
Начиная со столбца «Кабина», где у нас много пропущенных значений, номера кабин расположены в паре string_integr, поэтому мы можем взять первая буква каждого номера каюты и используйте ее как класс / группу кают, в то время как значения «nan» берутся как отдельная группа, тем самым создавая новую функцию / столбец без пропущенных значений.

all_data['cabin_adv'] = all_data.Cabin.apply(lambda x: str(x)[0]) # we use the 'str' method to strip the cabin number and take only the first character (the same applies for 'nan' values).
all_data.info()
#output
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1309 entries, 0 to 1308
Data columns (total 13 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  1309 non-null   int64  
 1   Survived     891 non-null    float64
 2   Pclass       1309 non-null   int64  
 3   Name         1309 non-null   object 
 4   Sex          1309 non-null   object 
 5   Age          1309 non-null   float64
 6   SibSp        1309 non-null   int64  
 7   Parch        1309 non-null   int64  
 8   Ticket       1309 non-null   object 
 9   Fare         1309 non-null   float64
 10  Cabin        295 non-null    object 
 11  Embarked     1309 non-null   object 
 12  cabin_adv    1309 non-null   object 
dtypes: float64(3), int64(4), object(6)
memory usage: 133.1+ KB

Мы также можем извлечь заголовок каждого пассажира из его имен и создать для этого отдельный столбец. Давайте сначала посмотрим, как расположены имена.

all_data.Name.head
#output
<bound method NDFrame.head of 0                                 Braund, Mr. Owen Harris
1       Cumings, Mrs. John Bradley (Florence Briggs Th...
2                                  Heikkinen, Miss. Laina
3            Futrelle, Mrs. Jacques Heath (Lily May Peel)
4                                Allen, Mr. William Henry
                              ...                        
1304                                   Spector, Mr. Woolf
1305                         Oliva y Ocana, Dona. Fermina
1306                         Saether, Mr. Simon Sivertsen
1307                                  Ware, Mr. Frederick
1308                             Peter, Master. Michael J
Name: Name, Length: 1309, dtype: object>

Имена представлены в формате Имя / Титул / Другие имена. Следовательно, мы разделяем имена по первой «запятой» и выбираем заголовок, затем мы разделяем заголовок «точки» в конце и берем только заголовок, как в первой строке ячейки ниже.

ll_data['tittle'] = all_data.Name.apply(lambda x: x.split(',')[1].split('.')[0].strip())
all_data.info()
#output
RangeIndex: 1309 entries, 0 to 1308
Data columns (total 14 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  1309 non-null   int64  
 1   Survived     891 non-null    float64
 2   Pclass       1309 non-null   int64  
 3   Name         1309 non-null   object 
 4   Sex          1309 non-null   object 
 5   Age          1309 non-null   float64
 6   SibSp        1309 non-null   int64  
 7   Parch        1309 non-null   int64  
 8   Ticket       1309 non-null   object 
 9   Fare         1309 non-null   float64
 10  Cabin        295 non-null    object 
 11  Embarked     1309 non-null   object 
 12  cabin_adv    1309 non-null   object 
 13  tittle       1309 non-null   object 
dtypes: float64(3), int64(4), object(7)

Проверяя нулевые значения в нашем наборе данных, мы видим, что нет нулевых значений, кроме столбца «Кабина», и это не проблема, поскольку вместо этого мы использовали бы столбец «cabin_adv». Мы также можем видеть созданные нами новые столбцы (title, cabin_adv).

Мы бы сделали что-то похожее на нашу колонку билетов, как и на колонку кабины. Мы бы взяли первую букву нашей пары string_integer и использовали ее для создания новой функции / столбца в качестве нашего класса заявки. Давайте сначала посмотрим, как устроены билеты.

all_data.Ticket.head(20)
#output
0            A/5 21171
1             PC 17599
2     STON/O2. 3101282
3               113803
4               373450
5               330877
6                17463
7               349909
8               347742
9               237736
10             PP 9549
11              113783
12           A/5. 2151
13              347082
14              350406
15              248706
16              382652
17              244373
18              345763
19                2649
Name: Ticket, dtype: object

Теперь давайте создадим нашу новую колонку / функцию

all_data['ticket_typ']= all_data.Ticket.apply(lambda x: x.split('/')[0]) #split the ticket at '/' and take the first value
all_data['ticket_typ']= all_data.Ticket.apply(lambda x: x.split(' ')[0]) #split the ticket(the output above) at ' ' (space) and take the first value
                
for i,t in enumerate(all_data.ticket_typ):  # this loop checks the length of the tickets and picks only the first character if the length  id more than 1. if the first character is a number it replaces it with 'x' otherwise it keeps it if is an alphabet
    if len(t)>1:
        all_data.ticket_typ[i]= t[0]
        if t[0].isdigit():
            all_data.ticket_typ[i]='x'
all_data.ticket_typ.value_counts()
#output
x    957
S     98
P     98
C     77
A     42
W     19
F     13
L      5
Name: ticket_typ, dtype: int64

Теперь давайте разделим наш набор данных (all_data) на обучающий и тестовый набор, чтобы мы могли посмотреть на распределения наших столбцов с вменениями, выполненными в наших новых столбцах.

train=all_data.iloc[0:891,:] # our training set had 891 rows, it occupies the forst 891 rows of our combined data set
train

test=all_data.iloc[891:,:] # our test set had 418 rows, it occupies the last 418 rows of our combined data set
test

Проверив cabin_adv (группа / класс салона), очевидно, что в классе / группе 'n' было больше пассажиров. Тем не менее, классы / группы «E», «D» и «F» имели лучшие показатели выживаемости, даже несмотря на то, что у них было гораздо меньше пассажиров.

fig, axes = plt.subplots(1,2, figsize=(20,5))
sns.barplot(ax=axes[1], x='cabin_adv', data=train, y='Survived')
sns.countplot(ax=axes[0],data=train, x='cabin_adv', hue='Survived')

Ниже приведена таблица с указанием показателей выживаемости с разбивкой по цифрам, nan означает 0.

pd.pivot_table(train,index='Survived',columns='tittle', values = 'Ticket', aggfunc='count')

Ниже приведена таблица, показывающая выживаемость по типу билета. Пассажиры с билетами «P» имели самые высокие показатели выживаемости.

pd.pivot_table(train, index='Survived', columns='ticket_typ', values='Ticket', aggfunc='count')

ПОДГОТОВКА МОДЕЛИ

Мы бы вернулись к использованию нашего объединенного набора данных (all_data) для предварительной обработки, «features» - это список столбцов, которые мы будем использовать для обучения нашей модели. Обратите внимание, что мы опустили столбцы name, пассажира_id, tittle, ticket и cabin, но вместо этого используем tittle, ticket_typ, cabin_adv. Это связано с тем, что отброшенные столбцы бесполезны для нашей модели, поскольку они специфичны для каждого пассажира, и мы извлекли из них полезную информацию.

features=[ 'Pclass','Sex','Age', 'SibSp',
       'Parch', 'Embarked','Fare', 'cabin_adv', 'tittle','ticket_typ',] # notice this does not contain our Survived column because we are going to save them seperatly
all_data_features=all_data[features]

Теперь давайте получим фиктивные переменные для наших категориальных столбцов (столбцы с объектами / строками, а не числовыми значениями).

all_data_dummies=pd.get_dummies(all_data_features)

В ячейке ниже мы будем извлекать наш обучающий набор из нашего объединенного набора данных, как это было сделано ранее, но сохраняя их как X (независимые переменные) и y (зависимые переменные).

X=all_data_dummies.iloc[0:891, : ] # this is being extracted from our combined dataset with dummie variables
y=all_data.Survived.iloc[0:891]# this is being extracted from our combined dataset beefore dropping some columns. it's basically our survived column

давайте посмотрим на y, который является сохранившимся столбцом.

y
#OUTPUT
0      0.0
1      1.0
2      1.0
3      1.0
4      0.0
      ... 
886    0.0
887    1.0
888    0.0
889    1.0
890    0.0
Name: Survived, Length: 891, dtype: float64

РАЗРАБОТКА МОДЕЛИ

Пора импортировать необходимые библиотеки

from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression

Использование логистической регрессии

lr = LogisticRegression(max_iter = 2000)
cv = cross_val_score(lr,X,y,cv=5)
print(cv)
print(cv.mean())
#output
[0.82681564 0.8258427  0.79775281 0.80898876 0.85393258]
0.822666499278137

По результатам нашей модели логистической регрессии мы получили точность 0,8229, что довольно хорошо. Давайте подстроимся под нашу модель, сделаем и представим прогнозы.

model = LogisticRegression(max_iter = 2000)
model.fit(X,y)
predictions=model.predict(test).astype(int)
output = pd.DataFrame({'PassengerId': test_data.PassengerId, 'Survived': predictions})
output.to_csv('my_submission.csv', index=False)
print("Your submission was successfully saved!")
#output
Your submission was successfully saved

Выполнив описанные выше действия, вы должны получить общедоступную оценку 0,77 при отправке своих прогнозов. Теперь вам нужно улучшить модель, чтобы получить лучшие результаты. Вы можете настроить модель, попробовать другую модель и даже заняться инженерией данных.

Вот ссылка на мое репозиторий на github для этого проекта:

Https://github.com/usmanbiu/kaggle-titanic.git

Я надеюсь, что вы нашли этот пост полезным, не забывайте делиться, аплодировать и проверять, есть ли другие посты. спасибо и удачи.