pytorch深度学习:神经网络实现数据分类(分类问题)

这一节,用pytorch实现神经网络分类问题,再次熟悉pytorch搭建神经网络的步骤。

1. 问题的提出

分类问题是将数据划分种类的一种问题,常见的有二分类和多分类问题,这节就是做一个简单的二分类问题。

同样,我们先做一组数据。其中第一组数据的标签为0,第二组数据标签为1。

# x0,x1是数据,y0,y1是标签
n_data = torch.ones(100, 2)         # 数据的基本形态
x0 = torch.normal(2*n_data, 1)      # 类型0 x data (tensor), shape=(100, 2)
y0 = torch.zeros(100)               # 类型0 y data (tensor), shape=(100, )
x1 = torch.normal(-2*n_data, 1)     # 类型1 x data (tensor), shape=(100, 1)
y1 = torch.ones(100)                # 类型1 y data (tensor), shape=(100, )

将两组数据进行融合,并用散点图表示出来,明显地看到可以将数据分为2类,即红绿各代表一类。
在这里插入图片描述

2. 神经网络模型的搭建和训练

神经网络模型的搭建和上一节回归问题基本一样,也是先搭建网络框架,再创建模型、优化器、损失函数。

要注意的是,在这个分类问题中我们输入的数据x是2维的,输出的预测值也是2维的(几分类问题输出就是几维),因此各个网络层的神经单元数要改变。

input_dim = 2
hidden_dim = 10
out_dim = 2

还有一点不同之处在于损失函数选用的是交叉熵(CrossEntropy) ,这是在做回归问题时常用的损失函数,而分类问题中最后一层的激活函数常选用的是softmax

有关交叉熵这有一篇博客介绍的很清晰,可以看一下。

pytorch中将两者集成在了torch.nn.CrossEntropyLoss() 这个函数中了,我们直接调用就好。

loss_func = nn.CrossEntropyLoss()

3. 结果展示

同样,我们输出训练过程中的loss值图像,发现损失值是在不断减小的,也就意味着模型拟合的越来越好。
在这里插入图片描述
要注意的是,这时给出的prediction并不是最后的分类值,而是一个Tensor数据格式,如[0.3,0.7],表示神经网络预测的样本属于每类的概率,所以需要取这个概率的最大值来表示最后的分类。

prediction = torch.max(F.softmax(out), 1)[1]

最后的分类结果展示图:
在这里插入图片描述

4. 结语

代码参考了莫烦大神的教程,完整代码放在这里:

# 神经网络的搭建--分类任务 #
import torch
import matplotlib.pyplot as plt
import torch.nn.functional as F   # 激励函数都在这

# x0,x1是数据,y0,y1是标签
n_data = torch.ones(100, 2)         # 数据的基本形态
x0 = torch.normal(2*n_data, 1)      # 类型0 x data (tensor), shape=(100, 2)
y0 = torch.zeros(100)               # 类型0 y data (tensor), shape=(100, )
x1 = torch.normal(-2*n_data, 1)     # 类型1 x data (tensor), shape=(100, 1)
y1 = torch.ones(100)                # 类型1 y data (tensor), shape=(100, )

# 注意 x, y 数据的数据形式是一定要像下面一样 (torch.cat 是在合并数据)
x = torch.cat((x0, x1), 0).type(torch.FloatTensor)  # FloatTensor = 32-bit floating
y = torch.cat((y0, y1), ).type(torch.LongTensor)    # LongTensor = 64-bit integer

plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=y.data.numpy(), s=100, lw=0, cmap='RdYlGn')
plt.show()


# 建立神经网络
class Net(torch.nn.Module):     # 继承 torch 的 Module
    def __init__(self, n_feature, n_hidden, n_output):
        super(Net, self).__init__()     # 继承 __init__ 功能
        self.hidden = torch.nn.Linear(n_feature, n_hidden)   # 隐藏层线性输出
        self.out = torch.nn.Linear(n_hidden, n_output)       # 输出层线性输出

    def forward(self, x):
        # 正向传播输入值, 神经网络分析出输出值
        x = F.relu(self.hidden(x))      # 激励函数(隐藏层的线性值)
        x = self.out(x)                 # 输出值, 但是这个不是预测值, 预测值还需要再另外计算
        return x

net = Net(n_feature=2, n_hidden=10, n_output=2) # 几个类别就几个 output


# 训练网络
optimizer = torch.optim.SGD(net.parameters(), lr=0.02)  
# 算误差的时候, 注意真实值!不是! one-hot 形式的, 而是1D Tensor, (batch,)
# 但是预测值是2D tensor (batch, n_classes)
loss_func = torch.nn.CrossEntropyLoss()

plt.ion()   # 画图
plt.show()

for t in range(100):
    out = net(x)     # 喂给 net 训练数据 x, 输出分析值

    loss = loss_func(out, y)     # 计算两者的误差

    optimizer.zero_grad()   
    loss.backward()         
    optimizer.step()        

    # 可视化展示
    if t % 2 == 0:
        plt.cla()
        # 过了一道 softmax 的激励函数后的最大概率才是预测值
        prediction = torch.max(F.softmax(out), 1)[1]

        pred_y = prediction.data.numpy().squeeze()
        target_y = y.data.numpy()
        plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=pred_y, s=100, lw=0, cmap='RdYlGn')
        accuracy = sum(pred_y == target_y) / 200.  # 计算准确度
        plt.text(1.5, -4, 'Accuracy=%.2f' % accuracy, fontdict={'size': 20, 'color': 'red'})
        plt.pause(0.1)

plt.ioff()  # 停止画图
plt.show()

补充:激励函数和损失函数的选择

在神经网络中针对不同问题会用到不同的激励函数和损失函数,比如上节回归问题用到的就是relu激活函数和mse损失函数,而这节分类问题我们最后一层用到的就是softmax激活函数和crossentropy损失函数。

针对最后一层激活函数的选择和损失函数的选择,有一个图可以参考,来自这篇博客
在这里插入图片描述


版权声明:本文为qq_37333048原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。