莫烦pytorch学习笔记(三)

搭建一个分类网络

对下图这种平面上的点根据颜色进行分类
在这里插入图片描述

导入所需库

分别导入torch库,宏定义神经元类型(自动梯度)Variable,定义激励函数库F,由于希望过程可视化所以导入matplotlib库

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

生成所需数据

生成被拟合数据x0和x1

n_data = torch.ones(100,2)          #生成一个全为1的100行2列的张量,一列横坐标,一列纵坐标
x0 = torch.normal(2*n_data,1)       #x~N(2,1)的正态分布
y0 = torch.zeros(100)               #x0的标签y0全部设为0,一维数组100个0
x1 = torch.normal(-2*n_data,1)      #同样,x1内包含了的横坐标和纵坐标,X1~N(-2,1)的正态分布
y1 = torch.ones(100)                #x1的标签y1全部设为1,一维数组100个1
  • 因为是对一个平面内的点进行分类,所以
    n_data = torch.ones(100,2)
    生成一个全为1的100行2列的张量,一列横坐标,一列纵坐标,n_data类型含有两个同时变量
  • torch.normal(A,B)意为从正态分布X~N(A,B)中生成张量,由于n_data都是1,所以X0~N(2,1)的正态分布
  • y0和y1分别是x0和x1的标签,我们最终目标是分辨哪些点的标签是1,哪些是0

拼接坐标以及标签

x=torch.cat((x0,x1),0).type(torch.FloatTensor)          # 将x0和x1上下拼接变成待处理数据(200行2列),坐标要定义为浮点数,用.type()将结果转换为浮点数
y=torch.cat((y0,y1),).type(torch.LongTensor)            # 将标签定义为整形类型(一维200个数字,前100个是0,后100个是1)
  • cat函数:cat((A,B),0)把A张量和B张量上下拼接,若为1则左右拼接。若 后没有设置,则默认是0,进行上下拼接。

cat()函数例子:

A=torch.ones(2,3)   #2x3的张量(矩阵)
print("A:\n",A,"\nA.shape:\n",A.shape,"\n")

B=2*torch.ones(3,3)                         #4x3的张量(矩阵)
print("B:\n",B,"\nB.shape:\n",B.shape,"\n")

C=torch.cat((A,B),0)  #按维数0(行,即上下)拼接
print("C:\n",C,"\nC.shape:\n",C.shape,"\n")

输出:

A:
 tensor([[1., 1., 1.],
        [1., 1., 1.]]) 
A.shape:
 torch.Size([2, 3]) 

B:
 tensor([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]]) 
B.shape:
 torch.Size([3, 3]) 

C:
 tensor([[1., 1., 1.],
        [1., 1., 1.],
        [2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]]) 
C.shape:
 torch.Size([5, 3]) 

搭建网络

与前一篇定义基本相同,解读可参照上一篇文章

class Net(torch.nn.Module):             #从torch继承了Module类
    def __init__(self,n_feature,n_hidden,n_output):                 #初始化时定义的,输入个数,隐藏层神经元个数,输出个数
        super().__init__()      #继承父类功能(官方步骤)
        self.hidden = torch.nn.Linear(n_feature,n_hidden)      #隐藏层:输入数据个数,隐藏层神经元个数,
        self.predict = torch.nn.Linear(n_hidden,n_output)               #预测层:输入是前面的hidden,输出个数

    #神经元之间传递是线性,非线性是由激励函数实现的

    def forward(self,x):                    # 前向传递,输入信息是x
        x=F.relu(self.hidden(x))            #使用一个hidden层加工x,输出n个神经元,进入relu函数激活
        x=self.predict(x)                   #将x放入预测层,并不希望结果被截断,所以不用外面套一层F.relu()
        return x

net = Net(2,10,2)
由于输入某个点有横纵坐标,所以输入是2个特征,设置10个神经元,又因为这是二分类问题,输出向量 [0,1]代表输出1,[1,0]代表输出0。

优化网络

optimizer = torch.optim.SGD(net.parameters(),lr=0.01)
调用torch的优化方法,选择常用的SGD优化器。 parameters是net的所有参数 lr是梯度下降速度(也就是学习速度,过快过慢都不行)

loss_function=torch.nn.CrossEntropyLoss() 定义处理误差的方法 分类一般用交叉熵损失处理方法。

交叉熵知识稍后补充。

使用网络进行回归

for t in range(100):                # 训练100次
    prediction = net(x)             # 预测结果=100个数字经过net正向传播的100个值
    loss = loss_function(prediction,y)
    optimizer.zero_grad()           #因为梯度累加,先要梯度降为0
    loss.backward()                 #反向传递
    optimizer.step()                #优化梯度,其实就是找正确结果

整体代码及注释

建议复制到编辑器,配合高亮看。

其中matplotlib相关绘图代码我也看不懂,也不是重点

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

n_data = torch.ones(100,2)          #生成一个全为1的100行2列的张量,一列横坐标,一列纵坐标

x0 = torch.normal(2*n_data,1)       #因为n_data是二维张量,所以x0内包含了某点的横坐标和纵坐标,x~N(2,1)的正态分布
#torch.normal(A,B)意为从正态分布N~(A,B)中生成张量
y0 = torch.zeros(100)               #x0的标签y0全部设为0,一维数组100个0
x1 = torch.normal(-2*n_data,1)      #同样,x1内包含了的横坐标和纵坐标,x~N(-2,1)的正态分布
y1 = torch.ones(100)                #x1的标签y1全部设为1,一维数组100个1
#分辨哪一类是0,哪一类是1

x=torch.cat((x0,x1),).type(torch.FloatTensor)          # 将x0和x1上下拼接变成待处理数据(200行2列),坐标要定义为浮点数,用.type()将结果转换为浮点数
y=torch.cat((y0,y1),).type(torch.LongTensor)            # 将标签定义为整形类型(一维200个数字,前100个是0,后100个是1)
#cat函数,cat((A,B),0)把A张量和B张量上下拼接,若为1则左右拼接

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

'''
# 绘图查看数据(一半红一半绿)
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().__init__()      #继承父类功能(官方步骤)
        self.hidden = torch.nn.Linear(n_feature,n_hidden)      #隐藏层:输入数据个数,隐藏层神经元个数,
        self.predict = torch.nn.Linear(n_hidden,n_output)               #预测层:输入是前面的hidden,输出个数

    #神经元之间传递是线性,非线性是由激励函数实现的

    def forward(self,x):                    # 前向传递,输入信息是x
        x=F.relu(self.hidden(x))            #使用一个hidden层加工x,输出n个神经元,进入relu函数激活
        x=self.predict(x)                   #将x放入预测层,并不希望结果被截断,所以不用外面套一层F.relu()
        return x

net = Net(2,10,2)       #输入某个点的横纵坐标2个特征,10个神经元,这是二分类问题输出向量[0,1]代表输出1,[1,0]代表输出0。
# 有点像线代求特征向量,三分类问题就要[0,0,1],四分类就是[0,1,0,0]。ont-hot

'''
print(net)                  #查看网络
Net(
  (hidden): Linear(in_features=2, out_features=10, bias=True)
  (predict): Linear(in_features=10, out_features=2, bias=True)
)
输入某点的横纵坐标,得到对应的向量[0,1] or [1,0]
隐藏层输入2个变量,输出10个神经元
预测层输入10个神经元,输出向量
'''

plt.ion()             #实时打印过程
plt.show()

# 优化神经网络
optimizer = torch.optim.SGD(net.parameters(),lr=0.01)
# 调用torch的优化方法中,选择常用的SGD优化器。  parameters是net的所有参数   lr是梯度下降速度
loss_function=torch.nn.CrossEntropyLoss()        #定义处理误差的方法 分类一般用交叉熵损失处理方法


for t in range(100):                # 训练100次
    prediction = net(x)             # 预测结果=100个数字经过net正向传播的100个值
    loss = loss_function(prediction,y)
    optimizer.zero_grad()           #因为梯度累加,先要梯度清空为0
    loss.backward()                 #反向传递
    optimizer.step()                #优化梯度,其实就是找正确结果

    if t%2==0:              #每2步打印一次
        plt.cla()
        # 过了一道 softmax 的激励函数后的最大概率才是预测值
        prediction = torch.max(F.softmax(prediction), 1)[1]             #用softmax将向量转换为概率,输出索引为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)
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值