Pytorch学习日志(2)——线性模型

问题介绍

很多个数据点,希望能找到一个函数来你和这些数据点,使其误差最小。
我们从一位线性回归入手。

一维线性回归

我们从一元函数入手。
目标函数为
f ( x i ) = ω x i + b f(x_i) = \omega x_i +b f(xi)=ωxi+b
那么我们如何确定参数w和b呢?
只需要衡量f(x)和y的差别。
我们可以用它们之间的距离差异:
L o s s = ∑ i = 1 m ( f ( x i ) − y i ) 2 Loss = \sum_{i=1}^m(f(x_i)-y_i)^2 Loss=i=1m(f(xi)yi)2
取平方是因为它们之间的距离差异有正有负。
这也是著名的均方误差。
MSE:估计量与被估计量差异之间的度量。
( w ∗ , b ∗ ) = arg min ⁡ w , b ∑ i = 1 m ( y i − w x i − b ) (w^*,b^*) = \argmin_{w,b} \sum_{i=1}^m(y_i - wx_i - b) (w,b)=w,bargmini=1m(yiwxib)
我们采用最小二乘法来求解均方差最小化。

一维线性回归的代码实现

import torch
from torch.autograd import Variable
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt

x_train = torch.Tensor([[3.3],[4.4],[5.5],[6.71],[6.93],[4.168],[9.779],[6.182],[7.59],[2.167],[7.042],[10.791],[5.313],[7.997],[3.1]])
print(x_train.size())
y_train = torch.Tensor([[1.7],[2.76],[2.09],[3.19],[1.694],[1.573],[3.366],[2.596],[2.53],[1.221],[2.827],[3.465],[1.65],[2.904],[1.3]])
print(y_train.size())

#定义一个简单的模型
class LinearRegression(nn.Module):
    def __init__(self):
        super(LinearRegression,self).__init__()
        self.linear = nn.Linear(1,1)
    '''
    torch.nn —— Linear layers
    class torch.nn.Linear(in_feature,out_features,bias=True)
    对输入数据做线性变换:y=Ax+b
    参数:
    in_features - 每个输入样本的大小/张量形状
    out_features - 每个输出样本的大小/张量形状
    bias - 若设置为False,这层不会学习偏置。默认值:True
    变量:
    weight -形状为(out_features x in_features)的模块中可学习的权值
    bias -形状为(out_features)的模块中可学习的偏置
    根据in_features随机生成
    '''
    def forward(self,x):
        out = self.linear(x)
        return out

model = LinearRegression()

#定义损失函数和优化函数
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(),lr = 1e-3) #model.parameters() model中可以优化的参数

#训练
num_epochs = 1000
for epoch in range(num_epochs):
    #导入Variable是因为其可以自动求导
    inputs = Variable(x_train)
    target = Variable(y_train)
    #forward
    out = model(inputs)
    '''
    model(inputs)等价于model.forwrd(inputs)
    这是因为:
    forward方法的具体流程:
    以一个Module为例:
    1. 调用module的call方法
    2. module的call里面调用module的forward方法
    3. forward里面如果碰到Module的子类,回到第1步,如果碰到的是Function的子类,继续往下
    4. 调用Function的call方法
    5. Function的call方法调用了Function的forward方法。
    6. Function的forward返回值
    7. module的forward返回值
    8. 在module的call进行forward_hook操作,然后返回值。

    上述中“调用module的call方法”是指nn.Module 的__call__方法。定义__call__方法的类可以当作函数调用,具体参考Python的面向对象编程。

    也就是说,当把定义的网络模型model当作函数调用的时候就自动调用定义的网络模型的forward方法。nn.Module 的__call__方法部分源码如下所示:

        def __call__(self, *input, **kwargs):
        result = self.forward(*input, **kwargs)
        for hook in self._forward_hooks.values():
            #将注册的hook拿出来用
            hook_result = hook(self, input, result)
        ...
        return result 
    '''
    loss = criterion(out,target) #nn中的其他模块同理 将out和target中的逐个元素求差,再求均值
    #backward
    optimizer.zero_grad() #优化器梯度清零 不然梯度会累加在一起,造成结果不收敛
    loss.backward() #计算梯度 对这些操作求其梯度
    optimizer.step() #更新参数 参考网络参数更新公式
    if (epoch+1) % 20 == 0:
        print('Epoch[{}/{}],loss:{:.6f}'.format(epoch+1,num_epochs,loss.item()))

#预测
model.eval()  #转化为测试模式
predict = model(Variable(x_train))
predict = predict.data.numpy()
plt.plot(x_train.numpy(),y_train.numpy(),'ro',label = 'Original data')
plt.plot(x_train.numpy(),predict,label = 'Fitting Line')
plt.show()

网络构成三步走:
1.搭建model并设置;
2.设置loss和optimizer;
3.设置epoch开始训练;

epoch三步走:
1.转化Variable,将数据导入model
2.计算loss
3.梯度清空,反向传播,更新参数

多维线性回归

在这里插入图片描述

多项式回归的代码实现

y = b + ω 1 x + ω 2 x 2 + ω 3 x 3 y = b + \omega_1 x + \omega_2 x^2 + \omega_3 x^3 y=b+ω1x+ω2x2+ω3x3

import torch
import torch.nn as nn
import torch.optim  as optim
from torch.autograd import Variable
#我们首先要将数据处理为矩阵形式
def make_features(x):
    x = x.unsqueeze(1)
    """
    unsqueeze()用于调整维度 默认增加一维或减少一维(在维度是1时才有效)
    增加一个括号,如果宽为1,可以默认是一维,只含长
    unsqueeze(0):增加第一维
    unsqueeze(1):增加第二维
    unsqueeze(2):增加第三维
    unsqueeze(-1):减少第三维
    unsqueeze(-2):减少第二维
    unsqueeze(-3):减少第三维
    """
    return torch.cat([x ** i for i in range(1,4)],1)
    """
    对输入的张量序列进行链接操作
    >>> x = torch.randn(2, 3)
    >>> x

    0.5983 -0.0341  2.4918
    1.5981 -0.5265 -0.8735
    [torch.FloatTensor of size 2x3]

    >>> torch.cat((x, x, x), 0)

    0.5983 -0.0341  2.4918
    1.5981 -0.5265 -0.8735
    0.5983 -0.0341  2.4918
    1.5981 -0.5265 -0.8735
    0.5983 -0.0341  2.4918
    1.5981 -0.5265 -0.8735
    [torch.FloatTensor of size 6x3]

    >>> torch.cat((x, x, x), 1)

    0.5983 -0.0341  2.4918  0.5983 -0.0341  2.4918  0.5983 -0.0341  2.4918
    1.5981 -0.5265 -0.8735  1.5981 -0.5265 -0.8735  1.5981 -0.5265 -0.8735
    [torch.FloatTensor of size 2x9]
    """
W_target = torch.FloatTensor([0.5,3,2.4]).unsqueeze(1) #将张量由3变为(3,1)
b_target = torch.FloatTensor([0.9])

def f(x):
    return x.mm(W_target) + b_target[0] #x.mm()矩阵乘法 x必须为张量
    
def get_batch(batch_size=32):
    random = torch.randn(batch_size)
    x = make_features(random)
    y = f(x)
    return Variable(x),Variable(y)

#定义多项式模型
class poly_model(nn.Module):
    def __init__(self):
        super(poly_model,self).__init__()
        self.poly = nn.Linear(3,1)

    def forward(self,x):
        out = self.poly(x)
        return out

model = poly_model()
criterion = nn.MSELoss()
print(model.parameters())
optimizer = optim.SGD(model.parameters(),lr=1e-3)
epoch = 0

while True:
    batch_x,batch_y = get_batch()
    output = model(batch_x)
    loss = criterion(output , batch_y)
    print_loss = loss.item() #将零维张量转化为浮点数
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    epoch += 1
    print(f'epoch={epoch},loss={print_loss}')
    if print_loss <1e-3:
        break
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

右边是我女神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值