【Pytorch神经网络实战案例】07 预测泰坦尼克号上生存的乘客

简介: 数据之间没有任何连续性的数据称为离散数据,例如数据中的男、女。

4c6d39d5b5ec4374a41163f4b5f84177.png


1 样本处理


1.1 载入样本代码---Titanic forecast.py(第1部分)


import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from scipy import stats
import pandas as pd
import matplotlib.pyplot as plt
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
def moving_average(a, w=10):#定义函数计算移动平均损失值
    if len(a) < w:
        return a[:]
    return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)]
def plot_losses(losses):
    avgloss= moving_average(losses) #获得损失值的移动平均值
    plt.figure(1)
    plt.subplot(211)
    plt.plot(range(len(avgloss)), avgloss, 'b--')
    plt.xlabel('step number')
    plt.ylabel('Training loss')
    plt.title('step number vs. Training loss')
    plt.show()
###1.1 载入样本
titanic_data = pd.read_csv('csv_list/titanic3.csv')
print(titanic_data.columns)
# 输出:Index(['pclass', 'survived', 'name', 'sex', 'age', 'sibsp', 'parch', 'ticket','fare', 'cabin', 'embarked', 'boat', 'body', 'home.dest'],dtype='object')


1.2 离散数据


1.2.1 离散数据的特征


数据之间没有任何连续性的数据称为离散数据,例如数据中的男、女。

离散数据通常可以处理为one-hot编码或者词向量,可以分为两类:


①具有固定类别的样本(性别):易于处理,按照总得类别进行变换


②没有固定类别的样本(姓名):通过hash算法或其他散列算法处理,再通过词向量技术进行转化


1.2.2 连续数据的特征


数据之间具有连续性的数据,称为连续数据,例如票价与年龄


对于连续数据做特征变化时,通过对数运算or归一化处理,使其具有统一的值域


1.2.3 连续数据与离散数据的转化


对于一个跨度很大的特征属性进行数据预处理时,可以有三种方法:


①按照最大值、最小值进行归一化处理


②使用对数运算


③按照分布情况将其分为几类,再做离散化处理


1.3 处理样本中的离散数据与NAn值


1.3.1 将离散数据转化为one-hot编码 代码---Titanic forecast.py(第2部分)


###1.2 处理样本中的离散数据与Nan值
# 将离散数据的字段转化为one-hot
# get_dummies()会根据指定列中的离散值转化为one-hot编码,并将转化后所生成的新列放到原有数据的后面,在新的列中的数据用0,1来表示是否具有该列的属性。
titanic_data = pd.concat(
    [titanic_data,
     pd.get_dummies(titanic_data['sex']),
     pd.get_dummies(titanic_data['embarked'],prefix="embark"),
     pd.get_dummies(titanic_data['pclass'],prefix="class")],axis=1
)
print(titanic_data.columns)
# 输出:Index(['pclass', 'survived', 'name', 'sex', 'age', 'sibsp', 'parch', 'ticket', 'fare', 'cabin', 'embarked', 'boat', 'body', 'home.dest', 'female', 'male', 'embark_C', 'embark_Q', 'embark_S', 'class_1', 'class_2','class_3'],dtype='object')
print(titanic_data['sex'])
print(titanic_data['female']) # 在sex列中,值为female的行,在female列中值为1


1.3.2 对数据中的Nan值进行过滤填充代码---Titanic forecast.py(第3部分)


对于两个具有连续属性的数据列进行Nan值处理,age与fare。


# 对Nan值进行过滤填充
# 调用fillna()对特定列的NAn值进行过滤,并用该列的平均值进行填充
titanic_data["age"] = titanic_data["age"].fillna(titanic_data["age"].mean()) # 乘客年龄
titanic_data["fare"] = titanic_data["fare"].fillna(titanic_data["fare"].mean()) # 乘客票价


1.3.3 剔除无用的数据列代码---Titanic forecast.py(第4部分)


本部分剔除与遇难无关的数据列。


## 去除与是否获取无关的数据列
titanic_data = titanic_data.drop(['name','ticket','cabin','boat','body','home.dest','sex','embarked','pclass'], axis=1)
print(titanic_data.columns ) # 输出真正需要处理的数据列


1.4 分离样本与标签并制作数据集代码---Titanic forecast.py(第5部分)


将suivived列从数据集中抽取出来,将数据列中剩下的数据作为输入样本。


### 1.3 分离样本和标签并制作数据集
# 分离样本
labels = titanic_data["survived"].to_numpy()
titanic_data = titanic_data.drop(['survived'],axis=1)
data = titanic_data.to_numpy()
# 样本属性名称
feature_names = list(titanic_data.columns)
# 将样本分为训练和测试两部分
np.random.seed(10) # 设置随机种子,保证每次运行所分的样本一致
# set() 函数创建一个无序不重复元素集,x-y返回一个新的集合,包括在集合x中但不在集合y中的元素
# random.choice(a=5, size=3, replace=False, p=None) 参数意思分别 是从a中以概率P随机选择3个, p没有指定的时候相当于是一致的分布
# 按照行号提取
train_indices = np.random.choice(len(labels),int(0.7 * len(labels)),replace = False)
print('train_indices++++',train_indices)
test_indices = list(set(range(len(labels))) - set(train_indices)) #将剩余部分设为测试集
print('train_indices++++',train_indices)
# data[:]相当于重新拷贝一个列表,列表是可变对象如果直接引用传参给函数,则会导致修改其中任意一个变量,其余变量相应改变。但是,通过这种方式可以避免这种情况。
train_features = data[train_indices]
train_labels = labels[train_indices]
test_features = data[test_indices]
test_labels = labels[test_indices]
print('测试样本数量',len(test_labels)) # 测试样本数量 393


2 训练模型


2.1 定义Mish激活函数与多层全连接网络代码---Titanic forecast.py(第6部分)


###定义Mish激活函数与多层全连接网络
# 定一个带有3层全连接网络的类,每个网络层使用Mish作为激活函数,该模型使用交叉熵损失函数
class Mish(nn.Module):
    def __init__(self):
        super().__init__()
    def forward(self,x):
        x = x * (torch.tanh(F.softplus(x)))
        return x
torch.manual_seed(0) # 设置随机种子函数
class ThreeLinearModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear1 = nn.Linear(12,12)
        self.mish1 = Mish()
        self.linear2 = nn.Linear(12,8)
        self.mish2 = Mish()
        self.linear3 = nn.Linear(8,2)
        self.softmax = nn.Softmax(dim = 1)
        self.criterion = nn.CrossEntropyLoss() #定义交叉熵
    def forward(self,x): # 定义一个全连接网络
        lin1_out = self.linear1(x)
        out_1 = self.mish1(lin1_out)
        out_2 = self.mish2(self.linear2(out_1))
        return self.softmax(self.linear3(out_2))
    def getloss(self,x,y): # 实现类的损失值计算接口
        y_pred = self.forward(x)
        loss = self.criterion(y_pred,y)
        return loss


2.2 训练模型并输出结果代码---Titanic forecast.py(第7部分)


### 训练模型并输出结果
if __name__ == '__main__':
    net = ThreeLinearModel()
    num_epochs = 200
    optimizer = torch.optim.Adam(net.parameters(),lr = 0.04)
    # 将输入的样本标签转化为标量
    input_tensor = torch.from_numpy(train_features).type(torch.FloatTensor)
    label_tensor = torch.from_numpy(train_labels)
    losses = [] # 定义损失值列表
    for epoch in range(num_epochs):
        loss = net.getloss(input_tensor, label_tensor)
        losses.append(loss.item())
        optimizer.zero_grad()  # 清空之前的梯度
        loss.backward()  # 反向传播损失值
        optimizer.step()  # 更新参数
        if epoch % 20 == 0:
            print('Epoch {}/{} => Loss: {:.2f}'.format(epoch + 1, num_epochs, loss.item()))
    os.makedirs('models', exist_ok=True)
    torch.save(net.state_dict(), 'models/titanic_model.pt')
    plot_losses(losses)
    # 输出训练结果
    # tensor.detach():从计算图中脱离出来,返回一个新的tensor,新的tensor和原tensor共享数据内存,(这也就意味着修改一个tensor的值,另外一个也会改变),
    #                  但是不涉及梯度计算。在从tensor转换成为numpy的时候,如果转换前面的tensor在计算图里面(requires_grad = True),那么这个时候只能先进行detach操作才能转换成为numpy
    out_probs = net(input_tensor).detach().numpy()
    out_classes = np.argmax(out_probs, axis=1)
    print("Train Accuracy:", sum(out_classes == train_labels) / len(train_labels))
    # 测试模型
    test_input_tensor = torch.from_numpy(test_features).type(torch.FloatTensor)
    out_probs = net(test_input_tensor).detach().numpy()
    out_classes = np.argmax(out_probs, axis=1)
    print("Test Accuracy:", sum(out_classes == test_labels) / len(test_labels))


bee6242f7a98472e840a2e1fa180900c.png


3.0 代码汇总


import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from scipy import stats
import pandas as pd
import matplotlib.pyplot as plt
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
def moving_average(a, w=10):#定义函数计算移动平均损失值
    if len(a) < w:
        return a[:]
    return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)]
def plot_losses(losses):
    avgloss= moving_average(losses) #获得损失值的移动平均值
    plt.figure(1)
    plt.subplot(211)
    plt.plot(range(len(avgloss)), avgloss, 'b--')
    plt.xlabel('step number')
    plt.ylabel('Training loss')
    plt.title('step number vs. Training loss')
    plt.show()
###1.1 载入样本
titanic_data = pd.read_csv('csv_list/titanic3.csv')
print(titanic_data.columns)
# 输出:Index(['pclass', 'survived', 'name', 'sex', 'age', 'sibsp', 'parch', 'ticket','fare', 'cabin', 'embarked', 'boat', 'body', 'home.dest'],dtype='object')
###1.2 处理样本中的离散数据与Nan值
# 将离散数据的字段转化为one-hot
# get_dummies()会根据指定列中的离散值转化为one-hot编码,并将转化后所生成的新列放到原有数据的后面,在新的列中的数据用0,1来表示是否具有该列的属性。
titanic_data = pd.concat(
    [titanic_data,
     pd.get_dummies(titanic_data['sex']),
     pd.get_dummies(titanic_data['embarked'],prefix="embark"),
     pd.get_dummies(titanic_data['pclass'],prefix="class")],axis=1
)
print(titanic_data.columns)
# 输出:Index(['pclass', 'survived', 'name', 'sex', 'age', 'sibsp', 'parch', 'ticket', 'fare', 'cabin', 'embarked', 'boat', 'body', 'home.dest', 'female', 'male', 'embark_C', 'embark_Q', 'embark_S', 'class_1', 'class_2','class_3'],dtype='object')
print(titanic_data['sex'])
print(titanic_data['female']) # 在sex列中,值为female的行,在female列中值为1
# 对Nan值进行过滤填充
# 调用fillna()对特定列的NAn值进行过滤,并用该列的平均值进行填充
titanic_data["age"] = titanic_data["age"].fillna(titanic_data["age"].mean()) # 乘客年龄
titanic_data["fare"] = titanic_data["fare"].fillna(titanic_data["fare"].mean()) # 乘客票价
## 去除与是否获取无关的数据列
titanic_data = titanic_data.drop(['name','ticket','cabin','boat','body','home.dest','sex','embarked','pclass'], axis=1)
print(titanic_data.columns )
### 1.3 分离样本和标签并制作数据集
# 分离样本
labels = titanic_data["survived"].to_numpy()
titanic_data = titanic_data.drop(['survived'],axis=1)
data = titanic_data.to_numpy()
# 样本属性名称
feature_names = list(titanic_data.columns)
# 将样本分为训练和测试两部分
np.random.seed(10) # 设置随机种子,保证每次运行所分的样本一致
# set() 函数创建一个无序不重复元素集,x-y返回一个新的集合,包括在集合x中但不在集合y中的元素
# random.choice(a=5, size=3, replace=False, p=None) 参数意思分别 是从a中以概率P随机选择3个, p没有指定的时候相当于是一致的分布
# 按照行号提取
train_indices = np.random.choice(len(labels),int(0.7 * len(labels)),replace = False)
print('train_indices++++',train_indices)
test_indices = list(set(range(len(labels))) - set(train_indices)) #将剩余部分设为测试集
print('train_indices++++',train_indices)
# data[:]相当于重新拷贝一个列表,列表是可变对象如果直接引用传参给函数,则会导致修改其中任意一个变量,其余变量相应改变。但是,通过这种方式可以避免这种情况。
train_features = data[train_indices]
train_labels = labels[train_indices]
test_features = data[test_indices]
test_labels = labels[test_indices]
print('测试样本数量',len(test_labels)) # 测试样本数量 393
###定义Mish激活函数与多层全连接网络
# 定一个带有3层全连接网络的类,每个网络层使用Mish作为激活函数,该模型使用交叉熵损失函数
class Mish(nn.Module):
    def __init__(self):
        super().__init__()
    def forward(self,x):
        x = x * (torch.tanh(F.softplus(x)))
        return x
torch.manual_seed(0) # 设置随机种子函数
class ThreeLinearModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear1 = nn.Linear(12,12)
        self.mish1 = Mish()
        self.linear2 = nn.Linear(12,8)
        self.mish2 = Mish()
        self.linear3 = nn.Linear(8,2)
        self.softmax = nn.Softmax(dim = 1)
        self.criterion = nn.CrossEntropyLoss() #定义交叉熵
    def forward(self,x): # 定义一个全连接网络
        lin1_out = self.linear1(x)
        out_1 = self.mish1(lin1_out)
        out_2 = self.mish2(self.linear2(out_1))
        return self.softmax(self.linear3(out_2))
    def getloss(self,x,y): # 实现类的损失值计算接口
        y_pred = self.forward(x)
        loss = self.criterion(y_pred,y)
        return loss
### 训练模型并输出结果
if __name__ == '__main__':
    net = ThreeLinearModel()
    num_epochs = 200
    optimizer = torch.optim.Adam(net.parameters(),lr = 0.04)
    # 将输入的样本标签转化为标量
    input_tensor = torch.from_numpy(train_features).type(torch.FloatTensor)
    label_tensor = torch.from_numpy(train_labels)
    losses = [] # 定义损失值列表
    for epoch in range(num_epochs):
        loss = net.getloss(input_tensor, label_tensor)
        losses.append(loss.item())
        optimizer.zero_grad()  # 清空之前的梯度
        loss.backward()  # 反向传播损失值
        optimizer.step()  # 更新参数
        if epoch % 20 == 0:
            print('Epoch {}/{} => Loss: {:.2f}'.format(epoch + 1, num_epochs, loss.item()))
    os.makedirs('models', exist_ok=True)
    torch.save(net.state_dict(), 'models/titanic_model.pt')
    plot_losses(losses)
    # 输出训练结果
    # tensor.detach():从计算图中脱离出来,返回一个新的tensor,新的tensor和原tensor共享数据内存,(这也就意味着修改一个tensor的值,另外一个也会改变),
    #                  但是不涉及梯度计算。在从tensor转换成为numpy的时候,如果转换前面的tensor在计算图里面(requires_grad = True),那么这个时候只能先进行detach操作才能转换成为numpy
    out_probs = net(input_tensor).detach().numpy()
    out_classes = np.argmax(out_probs, axis=1)
    print("Train Accuracy:", sum(out_classes == train_labels) / len(train_labels))
    # 测试模型
    test_input_tensor = torch.from_numpy(test_features).type(torch.FloatTensor)
    out_probs = net(test_input_tensor).detach().numpy()
    out_classes = np.argmax(out_probs, axis=1)
    print("Test Accuracy:", sum(out_classes == test_labels) / len(test_labels))
目录
相关文章
|
13天前
|
机器学习/深度学习 PyTorch 算法框架/工具
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
这篇文章介绍了如何使用PyTorch框架,结合CIFAR-10数据集,通过定义神经网络、损失函数和优化器,进行模型的训练和测试。
44 2
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
|
2月前
|
安全 算法 网络安全
网络安全与信息安全:构建数字世界的坚固防线在数字化浪潮席卷全球的今天,网络安全与信息安全已成为维系社会秩序、保障个人隐私和企业机密的关键防线。本文旨在深入探讨网络安全漏洞的本质、加密技术的前沿进展以及提升公众安全意识的重要性,通过一系列生动的案例和实用的建议,为读者揭示如何在日益复杂的网络环境中保护自己的数字资产。
本文聚焦于网络安全与信息安全领域的核心议题,包括网络安全漏洞的识别与防御、加密技术的应用与发展,以及公众安全意识的培养策略。通过分析近年来典型的网络安全事件,文章揭示了漏洞产生的深层原因,阐述了加密技术如何作为守护数据安全的利器,并强调了提高全社会网络安全素养的紧迫性。旨在为读者提供一套全面而实用的网络安全知识体系,助力构建更加安全的数字生活环境。
|
15天前
|
机器学习/深度学习 数据可视化 测试技术
YOLO11实战:新颖的多尺度卷积注意力(MSCA)加在网络不同位置的涨点情况 | 创新点如何在自己数据集上高效涨点,解决不涨点掉点等问题
本文探讨了创新点在自定义数据集上表现不稳定的问题,分析了不同数据集和网络位置对创新效果的影响。通过在YOLO11的不同位置引入MSCAAttention模块,展示了三种不同的改进方案及其效果。实验结果显示,改进方案在mAP50指标上分别提升了至0.788、0.792和0.775。建议多尝试不同配置,找到最适合特定数据集的解决方案。
154 0
|
21天前
|
机器学习/深度学习 PyTorch 算法框架/工具
深度学习入门案例:运用神经网络实现价格分类
深度学习入门案例:运用神经网络实现价格分类
|
30天前
|
SQL 安全 算法
网络安全的盾牌与剑:漏洞防御与加密技术的实战应用
【9月更文挑战第30天】在数字时代的浪潮中,网络安全成为守护信息资产的关键防线。本文深入浅出地探讨了网络安全中的两大核心议题——安全漏洞与加密技术,并辅以实例和代码演示,旨在提升公众的安全意识和技术防护能力。
|
2月前
|
网络协议 Python
告别网络编程迷雾!Python Socket编程基础与实战,让你秒变网络达人!
在网络编程的世界里,Socket编程是连接数据与服务的关键桥梁。对于初学者,这往往是最棘手的部分。本文将用Python带你轻松入门Socket编程,从创建TCP服务器与客户端的基础搭建,到处理并发连接的实战技巧,逐步揭开网络编程的神秘面纱。通过具体的代码示例,我们将掌握Socket的基本概念与操作,让你成为网络编程的高手。无论是简单的数据传输还是复杂的并发处理,Python都能助你一臂之力。希望这篇文章成为你网络编程旅程的良好开端。
50 3
|
2月前
|
机器学习/深度学习 JSON API
HTTP协议实战演练场:Python requests库助你成为网络数据抓取大师
在数据驱动的时代,网络数据抓取对于数据分析、机器学习等至关重要。HTTP协议作为互联网通信的基石,其重要性不言而喻。Python的`requests`库凭借简洁的API和强大的功能,成为网络数据抓取的利器。本文将通过实战演练展示如何使用`requests`库进行数据抓取,包括发送GET/POST请求、处理JSON响应及添加自定义请求头等。首先,请确保已安装`requests`库,可通过`pip install requests`进行安装。接下来,我们将逐一介绍如何利用`requests`库探索网络世界,助你成为数据抓取大师。在实践过程中,务必遵守相关法律法规和网站使用条款,做到技术与道德并重。
44 2
|
20天前
|
机器学习/深度学习 数据采集 自然语言处理
【NLP自然语言处理】基于PyTorch深度学习框架构建RNN经典案例:构建人名分类器
【NLP自然语言处理】基于PyTorch深度学习框架构建RNN经典案例:构建人名分类器
|
20天前
|
机器学习/深度学习 存储 自然语言处理
深度学习入门:循环神经网络------RNN概述,词嵌入层,循环网络层及案例实践!(万字详解!)
深度学习入门:循环神经网络------RNN概述,词嵌入层,循环网络层及案例实践!(万字详解!)
|
2月前
|
数据采集 API 开发者
🚀告别网络爬虫小白!urllib与requests联手,Python网络请求实战全攻略
在网络的广阔世界里,Python凭借其简洁的语法和强大的库支持,成为开发网络爬虫的首选语言。本文将通过实战案例,带你探索urllib和requests两大神器的魅力。urllib作为Python内置库,虽API稍显繁琐,但有助于理解HTTP请求本质;requests则简化了请求流程,使开发者更专注于业务逻辑。从基本的网页内容抓取到处理Cookies与Session,我们将逐一剖析,助你从爬虫新手成长为高手。
61 1