002_wz_kaggle泰坦尼克号深度学习实现

一、目的

使用深度学习对kaggle上的titanic项目,使用乘客数据(如姓名、年龄、性别、社会经济阶层等),建立一个模型预测泰坦尼克号沉船上哪些乘客能够幸存。

二、编程

该项目的训练集与测试集在官网下载即可:https://www.kaggle.com/c/titanic,在完成后还可以上传你的预测文件参与全世界排名。

我们本次编程使用pytorch进行。本次将搭建一个三层神经网络,relu->relu->sigmoid,使用batch优化。
下面是本次编程使用的模块:

import numpy as np
import matplotlib.pyplot as plt
import torch
import pandas as pd
import csv

2.1 数据处理

2.1.1 导入数据集

我们第一步先进行数据处理,先导入数据集

# 导入数据集
train_filepath = r"train.csv"
train_data = pd.read_csv(train_filepath)
test_filepath = r"test.csv"
test_data = pd.read_csv(test_filepath)

2.1.2 数据分析

在训练集train.csv中我们有很多特征,并且数据不全我们需要对其进行处理:

(1)PassengerID:乘客的ID,是无关信息。
(2)Survived:乘客是否幸存,取值为0或1,是我们预测/分类的目标。
(3)Pclass:客舱等级,可能蕴含着乘客的阶层、乘客客舱的位置等信息,比较重要。
(4)Name: 姓名,是无关信息。
(5)Sex:性别,灾难来临时常让妇女儿童先走,而同等条件女性体力普遍弱于男性,这些因素都会影响到一名乘客幸存的可能性,因此比较重要。
(6)Age:年龄,较为重要,理由同上。
(7)Parch:直系亲友数目,比较重要。
(8)SibSp:旁系亲友数目,比较重要。
(9)Ticket:票编号,是无关信息。
(10)Fare:票价,可能会反映乘客的社会阶层等。
(11)Cabin:客舱编号,可能会反映客舱位置等,但由于缺省太多,数据量很小不具有代表性,可以视为噪音剔除。
(12)Embarked:上船的港口编号。

在剔除了一些数据后,是否会因信息损失而降低模型的准确度?例如乘客的姓名可能暗含船上乘客之间家庭的关系。实际上我们的模型本来就是建立在不完全观测上(比如我们不知道船上的一对男女乘客有没有发生像Jack和Rose那样的故事),不确定性是必然存在的,把握主要矛盾,舍弃噪音信息是建立模型的一个好思路。

2.1.3 数据预处理

不了解one-hot的同学看这里:机器学习:数据预处理之独热编码(One-Hot)

# 训练数据预处理
def PreprocessTrainData(all_pf):
    # 预处理1:去掉无关特征
    cols = ["Survived", "Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]
    all_pf = all_pf[cols]
    # 预处理2:填充确实特征并标准化
    age_mean = all_pf["Age"].mean()
    all_pf["Age"] = all_pf["Age"].fillna(age_mean)

    fare_mean = all_pf["Fare"].mean()
    all_pf["Fare"] = all_pf["Fare"].fillna(fare_mean)

    # 预处理3:性别编码
    all_pf["Sex"] = all_pf["Sex"].map({"female": 0, "male": 1}).astype(int)

    # 预处理4:登港地点转换为one-hot编码
    x_OneHot_df = pd.get_dummies(data=all_pf, columns=["Embarked"])
    ndarray = x_OneHot_df.values

    # 预处理5:全体特征标准化,标签向量化
    label = ndarray[:, 0]
    label = label.reshape(label.shape[0], 1)
    features = ndarray[:, 1:]
    mean = features.mean(axis=0)
    features -= mean
    std = features.std(axis=0)
    features /= std

    return label, features


# 测试数据预处理
def PreprocessTestData(all_df):
    # 预处理1:筛除无关特征
    cols = ["Pclass", "Sex", "Age", "SibSp", "Parch", "Fare", "Embarked"]
    all_df = all_df[cols]

    # 预处理2:填充缺失特征并标准化特征
    age_mean = all_df["Age"].mean()
    all_df["Age"] = all_df["Age"].fillna(age_mean)

    fare_mean = all_df["Fare"].mean()
    all_df["Fare"] = all_df["Fare"].fillna(fare_mean)

    # 预处理3:性别编码0-1
    all_df["Sex"] = all_df["Sex"].map({"female": 0, "male": 1}).astype(int)

    # 预处理4:登港地点转换为one-hot编码
    x_OneHot_df = pd.get_dummies(data=all_df, columns=["Embarked"])
    ndarray = x_OneHot_df.values

    # 预处理5:全体特征标准化,标签向量化
    features = ndarray
    mean = features.mean(axis=0)
    features -= mean
    std = features.std(axis=0)
    features /= std
    return features

# 转换为张量
y_train, x_train = PreprocessTrainData(train_data)
x_train_tenser = torch.from_numpy(x_train)
y_train_tenser = torch.from_numpy(y_train)
x_test = PreprocessTestData(test_data)
x_test_tenser = torch.from_numpy(x_test)

2.2 构建网络

# 构造网络模型
class model(torch.nn.Module):
    def __init__(self):
        super(model, self).__init__()
        self.linear1 = torch.nn.Linear(9, 6)
        self.linear2 = torch.nn.Linear(6, 3)
        self.linear3 = torch.nn.Linear(3, 1)
        self.sigmoid = torch.nn.Sigmoid()
        self.relu = torch.nn.ReLU()

    def forward(self, x):
        x = self.relu(self.linear1(x))
        x = self.relu(self.linear2(x))
        x = self.sigmoid(self.linear3(x))
        return x

model = model()

2.3 构建优化器和损失函数

# 构造优化器和损失函数
criterion = torch.nn.BCELoss(reduction="mean")
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)

2.4 开始训练

cost_list = []
# 开始训练
for epoch in range(1000):
    # 正向传播
    y_pred = model(x_train_tenser.float())
    loss = criterion(y_pred, y_train_tenser.float())
    cost_list.append(loss.item())
    print("epoch:", epoch, "cost:", loss.item())
    # 反向传播
    optimizer.zero_grad()
    loss.backward()
    # 更新参数
    optimizer.step()

2.5 预测

y_pred = model(x_test_tenser.float())
y_pred = np.array(y_pred.data)
for i in range(y_pred.shape[0]):
    if y_pred[i, 0] > 0.5:
        y_pred[i, 0] = 1
    else:
        y_pred[i, 0] = 0
with open(r"gender_submission.csv", 'w+', newline='') as f:
    csv_file = csv.writer(f)
    csv_file.writerows(y_pred)

plt.plot(cost_list)
plt.xlabel("epoch")
plt.ylabel("cost")
plt.show()

2.6 损失下降图

epoch: 1 cost: 0.672267496585846
epoch: 2 cost: 0.6718555688858032
epoch: 3 cost: 0.6714616417884827
...
epoch: 997 cost: 0.39888277649879456
epoch: 998 cost: 0.39885351061820984
epoch: 999 cost: 0.39881929755210876

002_wz_kaggle泰坦尼克号深度学习实现_第1张图片
本次结果在kaggle上取得前23%的结果,总体来说还不错,毕竟使用的是未经任何优化的梯度下降法。
002_wz_kaggle泰坦尼克号深度学习实现_第2张图片
此外可以留一部分验证集,测试模型的泛化能力。

2.7 源码

源码在此

三、参考

kaggle泰坦尼克号深度学习实战

你可能感兴趣的:(杂,kaggle,pytorch,深度学习)