线性回归的简洁实现(二)

此处使用Pytorch可以更方便的实现线性回归的训练。

import torch
import numpy as np
import torch.utils.data as Data
import torch.nn as nn #nn是neural networks 缩写,该模块定义了大量神经网络的层
import torch.optim as optim

#1.生成数据集
num_inputs=2
num_examples=1000
true_w=[2,-3,4]
true_b=4.2
features=torch.tensor(np.random.normal(0,1,(num_examples,num_inputs)),dtype=torch.float32)
labels=true_w[0]*features[:,0]+true_w[1]*features[:,1]+true_b
labels+=torch.tensor(np.random.normal(0,0.01,size=labels.size()),dtype=torch.float32)

#2.读取数据集:Pytorch提供了data包来读取数据,我们将导入的data模块用Data代替
batch_size=10
#将训练数据的特征和标签组合
dataset=Data.TensorDataset(features,labels)
#从数据集中随机读取小批量
data_iter=Data.DataLoader(dataset,batch_size,shuffle=True)

#读取并打印第一个小批量样本数据
for x,y in data_iter:
    print(x,y)
    break

#3.定义模型
'''
在线性回归从零开始实现中我们需要定义模型参数并使用它们描述模型是怎样计算的
Pytorch中提供了大量预定义的层,这使我们只需关注使用哪些层来构造模型,nn的核心数据是Module
'''
class LinearNet(nn.Module):#定义成模型类,继承Module类然后撰写自己的网络层
    def __init__(self,n_feature):
        #调用LinearNet类的父类nn.Module的init方法
        super(LinearNet, self).__init__()
        #Linear是Pytorch的一个类也继承自Module类,因此可以自动进行反向传播,Linear()表示构造了一个对象:该对象包含w和b
        self.linear=nn.Linear(n_feature,1)


    #前馈计算:不需要定义反向传播因为继承自nn.Module自动根据计算图完成backward
    def forward(self,x):
        #只要类中实现了_call_方法则类实例化的对象就变成了一个可调用的对象,此处相当于完成y=w*x+b计算
        y=self.linear(x)
        return y

#打印出网络的结构
#net=LinearNet(num_inputs)
#print(net)


#method1:事实上还可以通过nn.Sequential更加方便的搭建网络,Sequential是一个有序的容器 网络层将按照在传入容器的顺序依次被添加到计算图中

net=nn.Sequential(nn.Linear(num_inputs,1),)
                  #此处还可以传入其它层

'''method2:
net=nn.Sequential()
net.add_module('linear',nn.Linear(num_inputs,1))
'''
#method3
print(net)


#通过net.parameters()来查看模型所有可学习参数,此函数将返回一个生成器
for param in net.parameters():
    print(param)


#4.初始化模型参数:在使用net前需要初始化模型参数,如线性回归模型中的权重和偏差
#Pytorch在init模块中提供了多种参数初始化方法,我们通过init.normal_将权重参数每个元素初始化为随机采样于均值为0、标准差为0.01的正态分布,偏差会初始化为0
from torch.nn import init

init.normal_(net[0].weight,mean=0,std=0.01)
init.constant_(net[0].bias,val=0)

#5.定义损失函数:Pytorch在nn模块中提供了各类损失函数并将这些损失函数实现为nn.Module的子类
loss=nn.MSELoss()

#6.定义优化算法:torch.optim模块中提供了很多常用的优化算法
optimizer=optim.SGD(net.parameters(),lr=0.03)
print(optimizer)

'''
还可以为不同子网络设置不同的学习率
optimizer=optim.SGD([# 如果对某个参数不指定学习率,就使⽤最外层的默认学习率
 {'params': net.subnet1.parameters()}, # lr=0.03
 {'params': net.subnet2.parameters(), 'lr': 0.01}
 ], lr=0.03
                    ])
'''

#7.训练模型:通过调用optim实例的step函数来迭代模型参数,按照小批量随机梯度下降我们在step函数中指明批量大小从而对批量中样本梯度求平均
num_epochs=3
for epoch in range(1,num_epochs+1):
    for X,y in data_iter:
        output=net(X)#y_hat
        l=loss(output,y.view(-1,1))#前馈中计算损失
        optimizer.zero_grad()#梯度清零等价于net.zero_grad()
        l.backward()#反向传播
        optimizer.step()#梯度更新
    print('epoch %d,loss:%f'%(epoch,l.item()))
        
#比较学到的模型参数和真实的模型参数,从net获得需要的层,并访问其权重weight和偏差bias.
dense=net[0]
print(true_w,dense.weight)
print(true_b,dense.bias)

 迭代3次的loss和学习到的参数:

版本二

import torch
import torch.utils.data as Data #Pytorch中提供了data包来读取数据
import torch.nn as nn #该模块定义了大量神经网络的层
import torch.optim as optim
import numpy as np



#1.生成数据集
num_examples=1000
num_inputs=2
true_w=[2,-3.4]
true_b=4.2
features=torch.randn(num_examples,num_inputs,dtype=torch.float32)
labels=true_w[0]*features[:,0]+true_w[1]*features[:,1]+true_b
labels+=torch.tensor(np.random.normal(0,0.01,size=labels.size()),dtype=torch.float32)


#2.读取数据集:在每次迭代中随机读取10个随机小批量样本数据
batch_size=10
#将生成数据的特征和标签组合
dataset=Data.TensorDataset(features,labels)
#随机读取小批量,此处的data_iter仍然是个迭代器
data_iter=Data.DataLoader(dataset,batch_size,shuffle=True)#

for x,y in data_iter:
    print(x,y)
    break

'''


'''
#3.定义模型(定义成模型类)(模型类构造方法)
class LinearNet(nn.Module):#继承Module类然后撰写自己的网络/层
    def __init__(self,n_feature):#self代表的是类的实例,不必非写为self,但约定俗成写成self
        #此处是调用LinearNet类的父类(nn.Module)的init方法
        super(LinearNet,self).__init__()
        #Linear是Pytorch中的一个类,也继承自Module类,因此可以自动进行反向传播.Linear()表示构造一个对象,该对象包含了w和b
        self.linear=nn.Linear(n_feature,1)#输入样本的维度n_feature,输出样本的维度1

    #前馈计算:不需定义反向因为继承nn.Module中自动根据计算图完成backward()
    #nn.Module类中实现了_call_方法且call方法中调用了forward()方法,此处要重写
    def forward(self,x):
        y=self.linear(x)#只要类中实现了_call_方法那么类实例化的对象就变成了一个可调用得到对象.此处相当于计算y=w*x+b
        return y

model=LinearNet(num_inputs)

#选择loss function和优化器sgd
loss=torch.nn.MSELoss(size_average=True)
optimizer=optim.SGD(model.parameters(),lr=0.03)

#训练模型
num_epochs=3
for epoch in range(1,num_epochs+1):
    for X,y in data_iter:
        output=model(X)#在前馈中算出y_hat
        l=loss(output,y.view(-1,1))#计算损失
        print(l)
        optimizer.zero_grad()#梯度清零,等价于net.zero_grad()
        l.backward()#反向传播
        optimizer.step()#梯度更新
    print('epoch %d,loss %f'%(epoch,l.item()))

print('w=',model.linear.weight)
print('b=',model.linear.bias.item())


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值