赞
踩
动手深度学习(第二版)
回归(regression)是能为一个或多个自变量与因变量之间关系建模的一类方法。而线性回归是一种利用线性模型对连续变量进行预测的方法,其中自变量和因变量之间存在线性关系。常见的例子包括:预测价格(房屋、股票等)、预测住院时间(针对住院病人等)、 预测需求(零售销量等)。
易于理解和实现:线性回归是最基础、最简单的回归方法之一,易于理解和实现。
适用范围广:线性回归可用于连续型数据预测和分析。它在统计学和机器学习中都有很广泛的应用,例如金融、医疗、物流和销售预测等领域。
可解释性强:由于其线性关系,线性回归得到的模型很容易进行解释。
鲁棒性强:线性回归模型对噪声有一定的鲁棒性,噪声不会导致太大的影响。
对非线性关系敏感:线性回归对自变量与因变量之间存在明显的线性关系时表现很好,但当数据集呈现出复杂的非线性关系时就会遇到困难。
容易受离群点影响:离群点可以对线性回归结果产生较大的影响,对离群点的处理需要特别注意。离群点可能尤其需要在预处理阶段被去除。
受自相关、异方差和多重共线性等问题的影响:在某些情况下,线性回归分析可能会受到数据集中存在自相关、异方差和多重共线性等问题的影响而产生误差。
限制较大:线性回归适用于一些灵活程度较低的问题,如简单的拟合,然而对于一些需要更高灵活度的问题,线性模型就不再合适。
我们把试图预测的目标(比如预测房屋价格)称为标签(label)或目标(target)。 预测所依据的自变量(面积和房龄)称为特征(feature)或协变量(covariate)。通常,我们使用n来表示数据集中的样本数。
wi 称为权重(weight),权重决定了每个特征对我们预测值的影响。 b称为偏置(bias)、偏移量(offset)或截距(intercept)。 偏置是指当所有特征都取值为0时,预测值应该为多少。 即使现实中不会有任何房子的面积是0或房龄正好是0年,我们仍然需要偏置项。 如果没有偏置项,我们模型的表达能力将受到限制。线性回归模型是一个仿射函数,仿射变换的特点是通过加权和对特征进行线性变换(linear transformation), 并通过偏置项来进行平移(translation)。
将上式中的wi向量放在一起形成矩阵X,X∈R(n×d),每一行是一个样本,每一列是一种特征。这时便可以得到矩阵-向量乘法表示的预测值推导式。在代码实现中,一般将偏置b合并到参数w中,合并方法是在包含所有参数的矩阵中附加一列。
损失函数的作用是去确定一个拟合程度的度量,量化目标的实际值与预测值之间的差距。通常我们会选择非负数作为损失,且数值越小表示损失越小,完美预测时的损失为0。 回归问题中最常用的损失函数是平方误差函数。 当样本i的预测值为y^(i),其相应的真实标签为y(i)时, 平方误差可以定义为以下公式:
这里的1/2用于之后求导使得常系数为1,为了计算方便。为了度量模型在整个数据集上的质量,我们需计算在训练集n个样本上的损失均值(也等价于求和)。白话来讲,就是求和后除以样本数,使得损失更加精确与科学。
在训练模型时,我们希望寻找一组参数(w∗,b∗), 这组参数能最小化在所有训练样本上的总损失。
我们的目的是最小化‖y−Xw‖2。 这在损失平面上只有一个临界点,这个临界点对应于整个区域的损失极小点。 将损失关于w的导数设为0,得到解析解:
虽然解析解得到的式子十分简洁明了,但不是所有的模型都可以得到解析解。这时候我们就需要更加普遍性的方法——随机梯度下降法。这种方法几乎可以优化所有深度学习模型。 它通过不断地在损失函数递减的方向上更新参数来降低误差。
在计算损失函数(数据集中所有样本的损失均值) 关于模型参数的导数(在这里也可以称为梯度)时,我们往往要遍历整个数据集,这会极大的增加我们的训练代价。所以我们在每次计算时只使用一小部分样本,这种方法称为小批量随机梯度下降。
算法的主体步骤为下:
(1)初始化模型参数的值,如随机初始化;
(2)从数据集中随机抽取小批量样本且在负梯度的方向上更新参数,并不断迭代这一步骤。
|B|表示每个小批量中的样本数,这也称为批量大小(batch size)。 η表示学习率(learning rate)。 批量大小和学习率的值通常是手动预先指定,而不是通过模型训练得到的。 这些可以调整但不在训练过程中更新的参数称为超参数(hyperparameter)。调参(hyperparameter tuning)是选择超参数的过程。 超参数通常是我们根据训练迭代结果来调整的, 而训练迭代结果是在独立的验证数据集(validation dataset)上评估得到的。
调参的过程至关重要:
1、batchsize越大,在同样的训练数目的前提下,会减少训练的时间,提高计算的稳定性 ,训练出来的曲线更加平滑
2、batchsize越小,泛化的能力就会得到提升,因为适当的噪音能提高模型的鲁棒能力,减少出现过拟合的可能性。
3、学习率lr过大时 ,损失函数会出现震荡的现象,没法收束在一个定值,而取的过小的时候,训练代价又太大了
4、lr和batchsize大小正相关,对于一个固定的lr,存在一个最优的batchsize能够最大化测试精度。lr应该尽量稍大一些,更有利于提高泛化能力。
梯度下降法的具体推导可以看这篇博客:
随机梯度下降法(stochastic gradient descent,SGD)_柠檬上神的博客-CSDN博客
PR曲线,ROC曲线
原理复杂版版
- import random
- import torch
- from d2l import torch as d2l
- def synthetic_data(w, b, num_examples): #@save
- """生成y=Xw+b+噪声"""
- X = torch.normal(0, 1, (num_examples, len(w)))
- y = torch.matmul(X, w) + b
- y += torch.normal(0, 0.01, y.shape)
- return X, y.reshape((-1, 1))
-
- true_w = torch.tensor([2, -3.4])
- true_b = 4.2
- features, labels = synthetic_data(true_w, true_b, 1000)
- print('features:', features[0],'\nlabel:', labels[0])
- d2l.set_figsize()
- d2l.plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1);
- 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]
- batch_size = 10
-
- for X, y in data_iter(batch_size, features, labels):
- print(X, '\n', y)
- break
- w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
- b = torch.zeros(1, requires_grad=True)
- def linreg(X, w, b): #@save
- """线性回归模型"""
- return torch.matmul(X, w) + b
- def squared_loss(y_hat, y): #@save
- """均方损失"""
- return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
- def sgd(params, lr, batch_size): #@save
- """小批量随机梯度下降"""
- with torch.no_grad():
- for param in params:
- param -= lr * param.grad / batch_size
- param.grad.zero_()
- lr = 0.03
- num_epochs = 3
- net = linreg
- loss = squared_loss
-
- for epoch in range(num_epochs):
- for X, y in data_iter(batch_size, features, labels):
- 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}')
- print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
- print(f'b的估计误差: {true_b - b}')
调库简单版
- import numpy as np
- import torch
- from torch.utils import data
- from d2l import torch as d2l
-
- true_w = torch.tensor([2, -3.4])
- true_b = 4.2
- features, labels = d2l.synthetic_data(true_w, true_b, 1000)
- def load_array(data_arrays, batch_size, is_train=True): #@save
- """构造一个PyTorch数据迭代器"""
- dataset = data.TensorDataset(*data_arrays)
- #每次从dataset随机挑选batch个样本
- return data.DataLoader(dataset, batch_size, shuffle=is_train)
-
- batch_size = 10
- #做成一个list
- data_iter = load_array((features, labels), batch_size)
- # nn是神经网络的缩写
- from torch import nn
- #输入维度2和输出维度1
- net = nn.Sequential(nn.Linear(2, 1))
- #使用正态分布来替换掉data的值
- net[0].weight.data.normal_(0, 0.01)
- #偏差设为0
- net[0].bias.data.fill_(0)
- #定义损失函数
- loss = nn.MSELoss()
- #net.parameters为所有参数w和b,随机梯度下降法
- trainer = torch.optim.SGD(net.parameters(), lr=0.03)
- num_epochs = 3
- for epoch in range(num_epochs):
- for X, y in data_iter:
- l = loss(net(X) ,y)
- #梯度清零
- trainer.zero_grad()
- l.backward()
- #模型更新
- trainer.step()
- l = loss(net(features), labels)
- print(f'epoch {epoch + 1}, loss {l:f}')
- w = net[0].weight.data
- print('w的估计误差:', true_w - w.reshape(true_w.shape))
- b = net[0].bias.data
- print('b的估计误差:', true_b - b)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。