一、课后作业
构造分类器对Titanic数据集进行预测
1.数据集预处理
(1)数据集下载与分析
下载地址:https://www.kaggle.com/c/titanic/data
导入必要的包,并查看训练集、测试集前五行数据
import torch
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns #依赖库numpy、pandas、matlibplot、scipy都要安装
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
train_data = pd.read_csv('D:\\test\\pytorch\\datasets\\titanic\\train.csv')
test_data = pd.read_csv('D:\\test\\pytorch\\datasets\\titanic\\test.csv')
print(train_data.head(5))
print(test_data.head(5))
在jupyter中运行结果如下:(此图展示的数据为训练集数据,测试集大家可以自行查看)
可以看到数据共有12列,具体包括:
:乘客编号(不重要)
Survived:生还情况,1为生还0则相反,也是需要预测的值;测试集数据不包含此列
Pclass:票务等级,分1、2、3级
Name:乘客姓名(不重要)
Sex:乘客性别,male、female,可考虑转换成0,1让模型进行学习
Age:年龄
SibSp:兄弟姐妹及配偶的数量
Parch:父母及子女的数量
Ticket:船票号码(不重要)
Fare:票价
Cabin:船舱
Embarked:登船港 C = Cherbourg, Q = Queenstown, S = Southampton
初步筛选出上述加粗字体特征数据进行后续的模型训练,舍弃passengerID、Name、Ticket
(2)数据清洗和整理
查看数据信息:
train_data.info()
test_data.info()
可以看到训练集数据量为891,其中Age、Cabin、Embarked特征有缺失。Age缺失较少,可以考虑采取中位数填充;Cabin缺失较多,舍弃此数据;Embarked缺失只有2个,可以考虑众数填充;
测试集数据量为418,其中Age、Cabin、Fare特征有缺失。处理方式与训练集相同,Age、Fare考虑采用中位数填充,Cabin舍弃。
#特征选择
y = train_data['Survived'] #真值
train_data.drop('Survived', axis=1, inplace=True) #.drop()用于删除指定行/列;
train_data.drop('PassengerId', axis=1, inplace=True) #axis=1表示列操作,不指定则默认为行操作
train_data.drop('Name', axis=1, inplace=True) #inplace=True表示就地修改,不设置则返回一个新的DataFrame
train_data.drop('Ticket', axis=1, inplace=True)
train_data.drop('Cabin', axis=1, inplace=True)
ID = test_data['PassengerId'] #记录测试集ID用于后续生成结果csv文件
test_data.drop('PassengerId', axis=1, inplace=True)
test_data.drop('Name', axis=1, inplace=True)
test_data.drop('Ticket', axis=1, inplace=True)
test_data.drop('Cabin', axis=1, inplace=True)
#缺失值填充
train_data['Age'].fillna(train_data.Age.median(), inplace=True)
mode_Embarked = train_data['Embarked'].mode()[0]#计算Embark列的众数,因为可能包含多个众数,因此用[0]索引获取第一个
train_data['Embarked'].fillna(mode_Embarked, inplace=True)
test_data['Age'].fillna(test_data.Age.median(), inplace=True)
test_data['Fare'].fillna(test_data.Fare.median(), inplace=True)
#分类型数据转化
d1={'male':0,'female':1}
d2={'S':1,'C':2,'Q':3}
train_data['Sex']=train_data['Sex'].map(d1)
train_data['Embarked']=train_data['Embarked'].map(d2)
test_data['Sex']=test_data['Sex'].map(d1)
test_data['Embarked']=test_data['Embarked'].map(d2)
(3)Dataset&Dataloader
#Dataset and DataLoader
class train_TitanicDataset(Dataset):
def __init__(self):
self.x_data = torch.from_numpy(x_train)
self.y_data = torch.from_numpy(y_train).unsqueeze(1) #得到的是一维张量,记得转成矩阵(列向量)
self.len = x_train.shape[0]
def __getitem__(self, index):
return self.x_data[index], self.y_data[index]
def __len__(self):
return self.len
train_dataset = train_TitanicDataset()
train_loader = DataLoader(dataset=train_dataset,
batch_size=32,
shuffle=True,
num_workers=0)
2.模型搭建及训练
搭了个五层的神经网络,代码和课上的差不多
更新:画损失的时候取了个平均值,现在的损失曲线不会那么曲折了嘿嘿,整体趋势也更明显一点
#Model
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.linear1 = torch.nn.Linear(7, 16)
self.linear2 = torch.nn.Linear(16, 8)
self.linear3 = torch.nn.Linear(8, 6)
self.linear4 = torch.nn.Linear(6, 4)
self.linear5 = torch.nn.Linear(4, 1)
self.sigmoid = torch.nn.Sigmoid()
def forward(self, x):
x = self.sigmoid(self.linear1(x))
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
x = self.sigmoid(self.linear4(x))
x = self.sigmoid(self.linear5(x))
return x
model = Model()
criterion = torch.nn.BCELoss(size_average=True)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.7) #学习率衰减,每过20epoch变为原来的0.7倍
epoch_list = []
loss_list = []
#Training
for epoch in range(100):
running_loss = 0.0
count = 0
for i, data in enumerate(train_loader, 0): #0表示index从0开始读入,train_loader拿出的(x,y)元组放在data里,自动转tensor
#1.prepare data
inputs, labels = data
inputs = inputs.to(torch.float32)
#2.forward
y_pred = model(inputs)
loss = criterion(y_pred.float(), labels.float())
#3.backward
optimizer.zero_grad()
loss.backward()
#4.update
optimizer.step()
running_loss += loss.item()
count += 1
running_loss = running_loss/count
scheduler.step()
epoch_list.append(epoch)
loss_list.append(running_loss)
# print(epoch, loss.item())
plt.plot(epoch_list, loss_list)
plt.grid(True)
plt.xlabel('Epoch')
plt.ylabel('loss')
plt.savefig('train_loss')
plt.show()
3.预测及储存结果
#Predict
x_test = torch.from_numpy(x_test)
y_test_pred = model(x_test.to(torch.float32))
pred = y_test_pred.detach().numpy()
pred = pred.astype(int) #官方csv文件是int格式,转化一下,否则提交得分是0
for i in range(len(pred)):
if pred[i] > 0.5:
pred[i] = 1
else:
pred[i] = 0
#print(pred)
#存储预测结果
df = pd.DataFrame(columns=['PassengerId','Survived'])
df['PassengerId']=ID
df['Survived']=pred
df.to_csv('pred_result.csv', index=False)
loss曲线:
官网得分:
我这个作业效果还不是很好,分数也不高,但是我只想完整地把作业完成一遍,不想继续做了hhhhhh大家可以自行搭建模型调整超参数,刷刷分~
数据预处理部分参考:Python数据分析案例08——预测泰坦尼克号乘员的生存(机器学习全流程)_泰坦尼克号生存预测python-CSDN博客
标签:True,self,torch,Titanic,pytorch,train,课后,test,data From: https://blog.csdn.net/weixin_51944652/article/details/141023865