Pytorch:快速搭建模型

原文地址

分类目录——Pytorch

之前写过一篇 Pytorch:一个简单的神经网络——分类 ,通过定义一个网络类的方式来构建神经网络模型

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.predict = torch.nn.Linear(n_hidden, n_output)  # 输出层线性输出
        
    def forward(self, x): 
        x = F.relu(self.hidden(x))  # 激励函数(隐藏层的线性值)
        y = F.softmax(self.predict(x), dim=-1)  # 输出值

        return y

# 声明一个网络
net1 = Net(n_feature=2, n_hidden=10, n_output=2)

这样写很不简洁,在Pytorch中封装了一个torch.nn.Sequential()方法来快速构造一个神经网络

net2 = torch.nn.Sequential(
    torch.nn.Linear(2, 10),
    torch.nn.ReLU(),
    torch.nn.Linear(10, 2),
    torch.nn.Softmax(dim=-1)
)

通过print()观察一下这两个网络

	print(net1)
    """
    Net(
      (hidden): Linear(in_features=2, out_features=10, bias=True)
      (predict): Linear(in_features=10, out_features=2, bias=True)
    )
    """
    print(net2)
    """
    (Sequential(
      (0): Linear(in_features=2, out_features=10, bias=True)
      (1): ReLU()
      (2): Linear(in_features=10, out_features=2, bias=True)
      (3): Softmax(dim=None)
    )
    """

发现两个网络的结构都是相同的,很明显后者这种方式写起来简单一些。

结构倒是一样的,不过在设置相同的训练参数的情况下,两者的训练结果略微有些出入,其中原因我还没有搞清楚。

打印两者对相同数据的分类结果

print(net1(torch.tensor([2., 2.])))
# tensor([0.9182, 0.0818], grad_fn=<SoftmaxBackward>)
print(net2(torch.tensor([2., 2.])))
# tensor([0.9459, 0.0541], grad_fn=<SoftmaxBackward>)  

就类别划分而言,两者的分类结果是相同的,但是在数值上存在着差别。

通过作图来观察

1581743700731

发现在整体上分类结果是相似的,但是在两个类别的边缘部分的数据,存在着类别归属上的些许差异。画图可参见 Matplotlib

最后附上全部代码

import torch
import torch.nn.functional as F     # 激励函数都在这
import matplotlib.pyplot as plt

torch.manual_seed(0)    # 为了使每次随机生成的数据都是一样的

# 生成测试数据
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)

# 拼接
x = torch.cat((x0, x1), 0)
y = torch.cat((y0, y1), 0).type(torch.long)

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

    def forward(self, x):
        x = F.relu(self.hidden(x))
        y = F.softmax(self.predict(x), dim=-1)
        return y

if __name__ == '__main__':

    net1 = Net(n_feature=2, n_hidden=10, n_output=2)  # 这是我们用这种方式搭建的 net1

    net2 = torch.nn.Sequential(
        torch.nn.Linear(2, 10),
        torch.nn.ReLU(),
        torch.nn.Linear(10, 2),
        torch.nn.Softmax(dim=-1)
    )

    print(net1)
    """
    Net(
      (hidden): Linear(in_features=2, out_features=10, bias=True)
      (predict): Linear(in_features=10, out_features=2, bias=True)
    )
    """
    print(net2)
    """
    (Sequential(
      (0): Linear(in_features=2, out_features=10, bias=True)
      (1): ReLU()
      (2): Linear(in_features=10, out_features=2, bias=True)
      (3): Softmax(dim=None)
    )
    """

    # optimizer 是训练的工具
    optimizer1 = torch.optim.SGD(net1.parameters(), lr=0.02)
    optimizer2 = torch.optim.SGD(net2.parameters(), lr=0.02)
    # 传入 net 的所有参数, 学习率
    loss_func = torch.nn.CrossEntropyLoss()
    # 误差的计算方式,这里选用的交叉熵损失
    # 交叉熵损失是分类中常用的一种损失函数,表示数据的不确定程度,大概可以这么理解,越合理的分类结果(视觉上就是成堆聚在一块的分成一类),其交叉熵值越小,反之,则越大

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

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

        optimizer1.zero_grad()  # 清空上一步的残余更新参数值
        loss.backward()  # 误差反向传播, 计算参数更新值
        optimizer1.step()  # 将参数更新值施加到 net 的 parameters 上

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

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

        optimizer2.zero_grad()  # 清空上一步的残余更新参数值
        loss.backward()  # 误差反向传播, 计算参数更新值
        optimizer2.step()  # 将参数更新值施加到 net 的 parameters 上

    prediction1 = torch.max(net1(x), 1)[1]
    prediction2 = torch.max(net2(x), 1)[1]

    plt.figure(figsize=(8,4))
    plt.subplot(121)
    plt.scatter(x[:, 0], x[:, 1], c=prediction1, lw=0, cmap='RdYlGn')

    plt.subplot(122)
    plt.scatter(x[:, 0], x[:, 1], c=prediction2, lw=0, cmap='RdYlGn')

    print(net1(torch.tensor([2., 2.])))
    print(net2(torch.tensor([2., 2.])))

    plt.show()

参考文献

快速搭建法

发布了102 篇原创文章 · 获赞 68 · 访问量 5096

猜你喜欢

转载自blog.csdn.net/BBJG_001/article/details/104354829
今日推荐