MLP-垃圾邮件分类

文章介绍了全连接神经网络的基础知识,包括其在卷积神经网络和循环神经网络中的应用。通过一个使用PyTorch的实例,展示了如何构建一个多层感知机(MLP)模型,对spambase.csv数据集进行预处理并进行垃圾邮件分类。训练过程中使用了Adam优化器和交叉熵损失函数,并通过History和Canvas库可视化了训练过程和性能指标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        全连接神经网络是最基础的深度学习网络,通常由多层多个神经元组成。在卷积神经网络和循环神经网络中,都能看到全连接层的身影。全连接网络在分类和回归问题中都非常有效。

        全连接神经网络(Multi-Layer Perception,MLP)或者叫多层感知机,是一种连接方式较为简单的人工神经网络结构,属于前馈神经网络的一种,主要由输入层、隐藏层和输出层构成,并且在每个隐藏层中可以有多个神经元。

        全连接层和线性层是同一个概念,都表示输入节点到输出节点之间的每个节点都相互连接的一种神经网络层,在PyTorch中,全连接层被实现为nn.Linear()

 全连接神经网络示意图

 可以看到,上述全连接神经网络由输入层、隐藏层、输出层三层组成,其中输入层不参与计算,而后隐藏层和输出层,均把前一层的输出作为输入,进行加权计算和激活函数:

z=wx+b

f(z)=\frac{1}{e^{-z}}

层层计算输出预测结果,利用损失函数反向传播计算参数梯度,利用梯度下降等优化算法更新模型参数,来减小损失,即选取最优参数来拟合样本和目标之间的关系,从而使得预测效果最好,可以通过模型预测新样本的目标。(神经网络的本质就是通过参数与激活函数来拟合特征与目标之间的真实函数关系。)

这里通过MLP模型对spambase.csv数据集进行一个垃圾邮件分类实例:

import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler,MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score,confusion_matrix,classification_report
from sklearn.manifold import TSNE
import torch
import torch.nn as nn
from torch.optim import SGD,Adam
import torch.utils.data as Data
import matplotlib.pyplot as plt
import seaborn as sns
import hiddenlayer as hl
from torchviz import make_dot
import warnings
warnings.filterwarnings("ignore")#忽略警告

##读取数据显示数据的前几行
spam=pd.read_csv('data/chap1/spambase.csv')
print(spam.head())

##计算垃圾邮件和非垃圾邮件的数量
print(pd.value_counts(spam.label))

##将数据随机切分为训练集和测试集
X=spam.iloc[:,0:57].values
y=spam.label.values
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.25,random_state=123)
##对数据的前57列特征进行数据标准化处理(采用MinMaxScaler方法)
scales=MinMaxScaler(feature_range=(0,1))
X_train_s=scales.fit_transform(X_train)
X_test_s=scales.transform(X_test)
'''得到标准化数据后,将训练数据集的每个特征变量使用箱线图进行显示,对比不同类别
的邮件(垃圾邮件和非垃圾邮件)在每个特征变量上的数据分布情况'''
colname=spam.columns.values[:-1]
plt.figure(figsize=(20,14))
for ii in range(len(colname)):
    plt.subplot(7,9,ii+1)
    sns.boxplot(x=y_train,y=X_train_s[:,ii])
    plt.title(colname[ii])
plt.subplots_adjust(hspace=0.4)
plt.show()

##使用预处理后的数据训练模型
##将数据转化为张量
X_train_t=torch.from_numpy(X_train_s.astype(np.float32))
y_train_t=torch.from_numpy(y_train.astype(np.int64))
X_test_t=torch.from_numpy(X_test_s.astype(np.float32))
y_test_t=torch.from_numpy(y_test.astype(np.int64))
##将训练集转化为张量后,使用TensorDataset将X和Y整理到一起
train_data=Data.TensorDataset(X_train_t,y_train_t)
##定义一个数据加载器,将训练数据集进行批量处理
train_loader=Data.DataLoader(
    dataset=train_data,
    batch_size=64,
    shuffle=True,
    num_workers=0,
)



#全连接网络
class MLPclassifica(nn.Module):
    def __init__(self):
        super(MLPclassifica,self).__init__()
        ##定义第一个隐藏层
        self.hidden1=nn.Sequential(
            nn.Linear(
            in_features=57,##第一个隐藏层的输入,数据的特征数
            out_features=30,##第一个隐藏层的输出,神经元的数量
            bias=True,##默认会有偏置
            ),
            nn.ReLU()
        )
        ##定义第二个隐藏层
        self.hidden2=nn.Sequential(
            nn.Linear(30,10),
            nn.ReLU()
        )
        ##分类层
        self.classifica=nn.Sequential(
            nn.Linear(10,2),
            nn.Sigmoid()
        )
    ##定义网络的前向传播路径
    def forward(self,x):
        fc1=self.hidden1(x)
        fc2=self.hidden2(fc1)
        output=self.classifica(fc2)
        ##输出为两个隐藏层和输出层
        return fc1,fc2,output
    
##输出网络结构
mlpc=MLPclassifica()
##使用make_dot可视化网络
x=torch.randn(1,57).requires_grad_(True)
y=mlpc(x)
Mymlpcvis=make_dot(y,params=dict(list(mlpc.named_parameters())+[('x',x)]))
##将Mymlpcvis保存为图片
Mymlpcvis.format='png'##形式转化为png
##指定文件保存位置
Mymlpcvis.directory='data/chap4/Mymlpc_vis'
Mymlpcvis.view()



##定义优化器、损失函数
optimizer=torch.optim.Adam(mlpc.parameters(),lr=0.01)
loss_func=nn.CrossEntropyLoss()


##记录训练过程的指标
history1=hl.History()
##使用Canvas进行可视化
canvas1=hl.Canvas()
print_step=25

##对模型进行迭代训练,对所有的数据训练epoch轮
for epoch in range(15):
    ##对训练数据的加载器进行迭代计算
    for step,(b_x,b_y) in enumerate(train_loader):
        ##计算每个batch的损失    
        _,_,output=mlpc(b_x)      ##MLP在训练batch上的输出
        train_loss=loss_func(output,b_y) ##二分类交叉熵损失函数
        optimizer.zero_grad()           ##每个迭代步的梯度初始化为0
        train_loss.backward()           ##损失的后向传播,计算梯度
        optimizer.step()                ##使用梯度进行优化
        niter=epoch*len(train_loader)+step+1
        ##计算每经过print_step次迭代后的输出
        if niter%print_step==0:
            _,_,output=mlpc(X_test_t)
            _,pre_lab=torch.max(output,1)
            test_accuracy=accuracy_score(y_test_t,pre_lab)
            ##为history添加epoch,损失和精度
            history1.log(niter,train_loss=train_loss,
                         test_accuracy=test_accuracy)
            ##使用两个图像可视化损失函数和精度
            with canvas1:
                canvas1.draw_plot(history1['train_loss'])
                canvas1.draw_plot(history1['test_accuracy'])

#测试
_,_,output=mlpc(X_test_t)
_,pre_lab=torch.max(output,1)
test_accuracy=accuracy_score(y_test_t,pre_lab)
print('test_accuracy:',test_accuracy)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值