PyTorch搭建神经网络求解二分类问题

PyTorch搭建全连接神经网络求解二分类问题

求解线性回归问题的时候,我们已经学习了如何使用梯度下降算法来不断更新权重矩阵,使误差函数不断减小,这一节我们将使用PyTorch搭建一个简单的神经网络来求解二分类问题。

本文的Jupyter Notebook代码可以在这里找到。文末也附上了可以运行的.py文件的代码

import numpy as np
import matplotlib.pyplot as plt
import torch
from sklearn.datasets import make_circles

生成训练集

X,Y=make_circles(n_samples=1000,factor=0.2,noise=0.1) #生成二维平面上的一些点,和这些点的标签
print("X shape:",X.shape)
plt.scatter(X[:,0],X[:,1],c=Y) #查看生成的数据
X shape: (1000, 2)
<matplotlib.collections.PathCollection at 0x18fd706e5e0>

在这里插入图片描述

构建神经网络

我们要搭建的神经网络如下图:
其中中间的一层(即隐藏层)的激活函数为Relu函数。
在这里插入图片描述

class neural_net(torch.nn.Module): #继承torch.nn.Module构建自己的网络
    def __init__(self):
        super(neural_net, self).__init__()
        self.layer1 = torch.nn.Linear(2, 4) #隐藏层
#         self.layer2 = torch.nn.Linear(4, 4) #这里还可以再加一个隐藏层,调试的时候可以试试把这行注释取消了,看看训练效果怎样
        self.layer_out = torch.nn.Linear(4, 2) #输出层

    def forward(self, input):
        #第一个隐藏层
        out = self.layer1(input)
        out = torch.relu(out) #隐藏层的激活函数设置成Relu函数
#        #第二个隐藏层
#         out = self.layer2(out)
#         out = torch.relu(out)
        #输出层
        out = self.layer_out(out) #输出层直接输出
        return out

net = neural_net() #从自己的网络实例化一个对象
print(net) #查看网络信息
neural_net(
  (layer1): Linear(in_features=2, out_features=4, bias=True)
  (layer_out): Linear(in_features=4, out_features=2, bias=True)
)

格式化数据

把numpy格式的数组转换成torch格式的张量

X = torch.from_numpy(X).type(torch.FloatTensor)
Y = torch.from_numpy(Y).type(torch.LongTensor)

取消下面的注释可以把神经网络和数据搬到GPU上训练,如何配置GPU可以参考这篇文章

#net.cuda()
#X = X.cuda()
#Y = Y.cuda()
print("X.device:", X.device) #查看数据在CPU上还是GPU上
print("Y.device:", Y.device)
X.device: cpu
Y.device: cpu

开始训练

import time

optimizer = torch.optim.SGD(net.parameters(), lr = 0.03) #设置梯度下降的算法为SGD算法,学习率为0.03。SGD使随机梯度下降
loss_func = torch.nn.CrossEntropyLoss() #设置损失函数为交叉熵函数

t0 = time.time_ns()

#跑5000步梯度下降
loss = 0
for i in range(5000):
    Y_hat = net(X) #前馈过程
    loss = loss_func(Y_hat, Y) #计算损失函数
    #反向传播计算梯度并更新权重
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    #每隔1000步打印一下loss的值
    if i%1000 == 0:
        print("step=",i, "loss=", loss.data.item())

t1 = time.time_ns()
print("in the end loss=", loss.data.item())
print("running time=%dms" %((t1-t0)/1000000))
step= 0 loss= 0.7381522059440613
step= 1000 loss= 0.27246278524398804
step= 2000 loss= 0.06931144744157791
step= 3000 loss= 0.031707875430583954
step= 4000 loss= 0.020208552479743958
in the end loss= 0.01475528534501791
running time=3519ms

查看训练结果

生成一些均匀分布在测试集范围内的点,直观的看到哪些区域的点会被分成哪一类

X = 2*np.random.rand(1000, 2) - 1
X = torch.from_numpy(X).type(torch.FloatTensor)
Y = net.forward(X).detach().numpy() #前馈计算输出
Y_color = []
for y in Y:
    Y_color.append(0 if y[0] > y[1] else 1)
plt.scatter(X.T[0], X.T[1], c=Y_color)
<matplotlib.collections.PathCollection at 0x18fd713fcd0>

在这里插入图片描述

生成测试集,看看训练好的模型在测试集上的表现怎样(loss值)

X,Y=make_circles(n_samples=1000,factor=0.2,noise=0.16) #生成测试集,相比训练集,这里噪声调的稍大了一些
X = torch.from_numpy(X).type(torch.FloatTensor)
Y = torch.from_numpy(Y).type(torch.LongTensor)

Y_hat = net.forward(X) #前馈计算测试集的输出
loss = loss_func(Y_hat, Y) #查看测试集上的loss值
print("loss on test:",loss.data.item())

#图形化
Y_color = []
for y in Y_hat.detach().numpy():
    Y_color.append(0 if y[0] > y[1] else 1)
plt.scatter(X[:,0],X[:,1],c=Y_color)
loss on test: 0.0439218208193779
<matplotlib.collections.PathCollection at 0x18fd72ed880>

在这里插入图片描述

全部代码

上面的代码可以依次复制到Jupyter Notebook上运行,下面的代码可以在py文件里运行

import numpy as np
import matplotlib.pyplot as plt
import torch
from sklearn.datasets import make_circles
import time

class neural_net(torch.nn.Module): #继承torch.nn.Module构建自己的网络
    def __init__(self):
        super(neural_net, self).__init__()
        self.layer1 = torch.nn.Linear(2, 4) #隐藏层
#         self.layer2 = torch.nn.Linear(4, 4) #这里还可以再加一个隐藏层,调试的时候可以试试把这行注释取消了,看看训练效果怎样
        self.layer_out = torch.nn.Linear(4, 2) #输出层

    def forward(self, input):
        #第一个隐藏层
        out = self.layer1(input)
        out = torch.relu(out) #隐藏层的激活函数设置成Relu函数
#        #第二个隐藏层
#         out = self.layer2(out)
#         out = torch.relu(out)
        #输出层
        out = self.layer_out(out) #输出层直接输出
        return out

def make_train_data():
    X,Y=make_circles(n_samples=1000,factor=0.2,noise=0.1) #生成二维平面上的一些点,和这些点的标签
    plt.scatter(X[:,0],X[:,1],c=Y) #查看生成的数据
    X = torch.from_numpy(X).type(torch.FloatTensor)
    Y = torch.from_numpy(Y).type(torch.LongTensor)
    return X, Y

def train(X, Y, net):
    optimizer = torch.optim.SGD(net.parameters(), lr = 0.03) #设置梯度下降的算法为SGD算法,学习率为0.03。SGD使随机梯度下降
    global loss_func
    loss_func = torch.nn.CrossEntropyLoss() #设置损失函数为交叉熵函数
    t0 = time.time_ns()
    loss = 0
    for i in range(5000):
        Y_hat = net(X) #前馈过程
        loss = loss_func(Y_hat, Y) #计算损失函数
        #反向传播计算梯度并更新权重
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        #每隔1000步打印一下loss的值
        if i%1000 == 0:
            print("step=",i, "loss=", loss.data.item())
    t1 = time.time_ns()
    return loss.data.item(), t1-t0

def show_result1():
    X,Y=make_circles(n_samples=1000,factor=0.2,noise=0.16) #生成测试集,相比训练集,这里噪声调的稍大了一些
    X = torch.from_numpy(X).type(torch.FloatTensor)
    Y = torch.from_numpy(Y).type(torch.LongTensor)

    Y_hat = net.forward(X) #前馈计算测试集的输出
    loss = loss_func(Y_hat, Y) #查看测试集上的loss值
    print("loss on test:",loss.data.item())

    #图形化
    Y_color = []
    for y in Y_hat.detach().numpy():
        Y_color.append(0 if y[0] > y[1] else 1)
    plt.scatter(X[:,0],X[:,1],c=Y_color)

def show_result2():
    X = 2*np.random.rand(1000, 2) - 1
    X = torch.from_numpy(X).type(torch.FloatTensor)
    Y = net.forward(X).detach().numpy() #前馈计算输出
    Y_color = []
    for y in Y:
        Y_color.append(0 if y[0] > y[1] else 1)
    plt.scatter(X.T[0], X.T[1], c=Y_color)



global train_X, train_Y #训练集
global net #神经网络
global loss_func #损失函数

if __name__ == "__main__":

    #生成测试集
    plt.subplot(1,3,1)
    plt.title("train data")
    train_X, train_Y = make_train_data()

    #创建神经网络
    net = neural_net()
    print(net) #查看网络信息

    #开始训练
    loss, t = train(train_X, train_Y, net)
    print("in the end loss=", loss)
    print("running time=%dms" %(t/1000000))

    #显示训练结果1
    plt.subplot(1,3,2)
    plt.title("test data")
    show_result1()

    #显示训练结果2
    plt.subplot(1,3,3)
    plt.title("for all point")
    show_result2()

    plt.show()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值