利用PyTorch实现一个简单的两层全连接神经网络,从而实现三分类

下面的代码使用 PyTorch 库实现了一个简单的两层全连接神经网络,用于解决一个多分类问题。代码首先生成了一个模拟数据集,包含三个类别的数据点。然后定义了一个神经网络 Net 类,该类包含一个隐藏层和一个输出层。ReLU激活函数被用于隐藏层。

在训练过程中,使用随机梯度下降(SGD)作为优化器,并使用交叉熵损失函数来计算网络输出与真实标签之间的误差。在每次迭代过程中,误差通过网络反向传播,优化器根据计算出的梯度更新网络参数。

代码还包含了一个实时绘图部分,以可视化每隔几轮的分类结果和准确率。最后,训练完成后,通过绘制散点图展示了分类器对于这个三分类问题的分类效果。

下面是完整代码:

import os
import torch
import torch.nn.functional as F
from torch.autograd import Variable
import matplotlib.pyplot as plt

os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'

# Fake data
n_data = torch.ones(100, 2)
x0 = torch.normal(2 * n_data, 1)
y0 = torch.zeros(100)
x1 = torch.normal(-2 * n_data, 1)
y1 = torch.ones(100)
x2 = torch.normal(torch.Tensor([[0, -3]] * 100), 1)
y2 = torch.ones(100) * 2   # 这行代码创建了一个长度为100的一维Tensor,其中所有元素的值都是2。它表示第三类数据点(x2)对应的标签。

x = torch.cat((x0, x1, x2), 0).type(torch.FloatTensor)
y = torch.cat((y0, y1, y2)).type(torch.LongTensor)

x, y = Variable(x), Variable(y)
class Net(torch.nn.Module):
    def __init__(self, n_features, n_hidden, n_output):
        super(Net, self).__init__()
        self.hidden = torch.nn.Linear(n_features, n_hidden)
        self.predict = torch.nn.Linear(n_hidden, n_output)

    def forward(self, x):
        x = F.relu(self.hidden(x))
        x = self.predict(x)
        return x

net = Net(2, 10, 3)
print(net)

optimizer = torch.optim.SGD(net.parameters(), lr=0.02)
loss_func = torch.nn.CrossEntropyLoss()

plt.ion()
plt.show()

for t in range(100):
    out = net(x)
    loss = loss_func(out, y)

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

    if t % 2 == 0:
        plt.cla()
        prediction = torch.max(F.softmax(out, dim=1), 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) / 300.
        plt.text(1.5, -4, 'Accuracy=%.2f' % accuracy, fontdict={'size': 20, 'color': 'red'})
        plt.pause(0.1)

plt.ioff()
plt.show()

定义的神经网络:

class Net(torch.nn.Module):
    def __init__(self, n_features, n_hidden, n_output):
        super(Net, self).__init__()
        self.hidden = torch.nn.Linear(n_features, n_hidden)
        self.predict = torch.nn.Linear(n_hidden, n_output)

    def forward(self, x):
        x = F.relu(self.hidden(x))
        x = self.predict(x)
        return x

Net 是一个继承自 torch.nn.Module 的自定义神经网络类。这是一个简单的两层全连接神经网络,用于解决多分类问题。

以下是关于 Net 类的详细解释:

init 方法:构造函数定义了网络的结构。这里,我们有两个线性层(全连接层):self.hidden 和 self.predict。

self.hidden 是一个隐藏层,输入特征数为 n_features,隐藏层神经元数为 n_hidden。
self.predict 是输出层,输入特征数为 n_hidden(即隐藏层的神经元数量),输出神经元数为 n_output(即类别数量)。
forward 方法:这是网络的前向传播函数,它接收输入 x,并通过神经网络的各层计算输出。在这个例子中,我们首先将输入 x 传递给隐藏层 self.hidden,然后对输出应用 ReLU 激活函数。接下来,将激活后的输出传递给输出层 self.predict。forward 方法返回输出层的结果。

这个自定义神经网络类可以用于训练和预测多分类问题。在上面的示例中,我们使用了一个具有10个隐藏层神经元的网络,用于解决三分类问题。可以根据具体问题调整隐藏层神经元的数量以及其他参数。

x, y = Variable(x), Variable(y)

在这个代码中,x, y = Variable(x), Variable(y) 这行代码的作用是将原始的 x 和 y 张量封装到 PyTorch 的 Variable 对象中。然而,这种用法现在已经过时。

从 PyTorch 0.4.0 版本开始,Tensor 对象已经合并了 Variable 对象的功能。因此,在现代 PyTorch 代码中,不再需要显式地使用 Variable 对象。可以直接使用 Tensor 对象进行自动求导和优化。

所以,这行代码实际上可以被省略,而 x 和 y 张量可以直接在训练过程中使用。

运行结果:

crossentropy pytorch 二分类 pytorch 三分类_全连接