沐神-动手学深度学习-线性回归

引言写在2022年暑假,结果只写了个环境配置就因为杂七杂八的原因没有学完。现在是研一下学期了,趁着不需要开题的空挡,在学一些专业技能吧。

线性回归的概念

线性回归其实很容易理解,他的目的就是通过直线拟合输入输出数据,得到输入与输出的变化关系,从而可以实现数据的分析、预测。

详细点解释就是,我们首先通过实验得到输入输出数据;

其次我们将模型已经确定为线性模型,因此可以得到Y=wX+b(其中X为输入数据,Y为输出数据),其中X和X不再是我们之前连接到的标量,比如说0,2这种一个数的形式,而是向量和矩阵,类似于[0, 2, 5],其中Y一般为向量,X一般为矩阵,因为影响输出值的变量可能有很多。比如说我们已知三个房子的价值以及其房间大小、地理位置的信息,那Y就是由三个元素组成的向量,例如[120, 150, 139],那X就是2X3的一个矩阵。

接下来我们先假设w和b为某一向量,通过线性模型Y=wX+b,带入输入数据我们便可以得到预测输出。当然我们刚开始设置的一组w、b不可能良好的拟合,因此我们需要对其进行调整,调整的参考就是误差,将预测值与输出值差的平方作为误差,该值越小说明拟合越好。

那怎么让误差变小呢,简单来说也就是在自变量为w、b,因变量为误差时,找到误差最小时的w、b值。我们只需要让自变量沿其导数的负方向前进便可以使误差减小,也就是梯度下降。插几句,由于损失函数的结构可能很复杂,一般深度学习都求的是数值解,而不是解析解。

在我们设计一个线性回归模型时,大致可以分为以下几个部分:

  1. 输入数据与输出数据的创建

  1. 每次从数据中提取一部分数据进行小批量随机梯度下降(防止数据量过大,计算不过来)

  1. 线性模型计算预测值

  1. 预测值与真值做差、平方,得到损失

  1. 梯度下降,优化参数,梯度在torch是自动计算的,我们不需要实现

代码实现

    • 输入输出数据的创建

##构造人工数据集
#用的不是torch.random,而是torch.normal
#torch.range()需要设定start和end,并且可以取到end,torch.arrange默认start=0,不会取到end
#torch.matmul可求向量内积与矩阵乘积
def creat_data(real_w, real_b, data_num):
    X = torch.normal(0, 1, (len(real_w), data_num))
    Y = torch.matmul(real_w, X) + real_b
    Y +=  torch.normal(0, 0.1, torch.matmul(real_w, X).shape)
    return X, Y.reshape(-1, 1)

real_w = torch.tensor([0.1, 0.2])
real_b = torch.tensor(0.3)
data_num = 10

features, labels = creat_data(real_w, real_b, data_num)
features = features.T
features.shape, labels.shape
    • 小批量数据提取

##批量数据提取:配合for循环多次读取,每次都用全部数据的一部分进行训练,但每个epoch都能用到全部数据
def data_iter(batch_size, features, labels):
    num_examples = len(features)
    indices = list(range(num_examples))
    # 这些样本是随机读取的,没有特定的顺序
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(
            indices[i: min(i + batch_size, num_examples)])
        yield features[batch_indices], labels[batch_indices]#返回数据流
    • 初始化参数模型

##初始化模型参数
w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)#打开导数计算
b = torch.zeros(1, requires_grad=True)
    • 定义线性模型

##定义模型
def linreg(X, w, b): 
    return torch.matmul(X, w) + b
    • 计算损失函数

##计算损失函数
def squared_loss(y_hat, y): 
    return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
    • 随机梯度下降

##随机梯度下降
def sgd(params, lr, batch_size): 
    """小批量随机梯度下降"""
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad / batch_size
            param.grad.zero_()#将梯度填充为0,防止影响后面计算
    • 训练

##训练
lr = 0.03
num_epochs = 3
net = linreg#网络模型
loss = squared_loss#损失函数计算
batch_size = 2

for epoch in range(num_epochs):
    i = 0
    for X, y in data_iter(batch_size, features, labels):
        #print(X, y)
        #i = i+1
        #print(i)
        l = loss(net(X, w, b), y)  # X和y的小批量损失
        # 因为l形状是(batch_size,1),而不是一个标量。l中的所有元素被加到一起,
        # 并以此计算关于[w,b]的梯度
        l.sum().backward()#自动求导只能求解标量
        sgd([w, b], lr, batch_size)  # 使用参数的梯度更新参数
    with torch.no_grad():
        train_l = loss(net(features, w, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值