每当我们想要预测一个数值时,就会出现回归问题。常见的例子包括预测价格(房屋、股票等)、预测住院时间(对于住院患者)、预测需求(对于零售销售)等等。并非每个预测问题都是经典的回归问题。稍后,我们将介绍分类问题,其目标是预测一组类别中的成员资格。
作为一个运行示例,假设我们希望根据房屋的面积(以平方英尺为单位)和年龄(以年为单位)来估算房屋的价格(以美元为单位)。要开发预测房价的模型,我们需要掌握由销售额组成的数据,包括每个房屋的销售价格、面积和年龄。在机器学习的术语中,数据集称为训练数据集或训练集,每一行(包含与一次销售对应的数据)称为示例( 或数据点、实例、样本)。我们试图预测的东西(价格)称为标签(或目标). 预测所依据的变量(年龄和面积)称为特征(或 协变量)。
%matplotlib inline import math import time import numpy as np import torch from d2l import torch as d2l
%matplotlib inline import math import time from mxnet import np from d2l import mxnet as d2l
%matplotlib inline import math import time from jax import numpy as jnp from d2l import jax as d2l
No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)
%matplotlib inline import math import time import numpy as np import tensorflow as tf from d2l import tensorflow as d2l
3.1.1. 基本
线性回归可能是解决回归问题的标准工具中最简单和最受欢迎的。追溯到 19 世纪初(高斯,1809 年,勒让德,1805 年),线性回归源于一些简单的假设。首先,我们假设特征之间的关系x和目标 y近似线性,即条件均值 E[Y∣X=x]可以表示为特征的加权和x. 由于观察噪声,此设置允许目标值仍可能偏离其预期值。接下来,我们可以假设任何此类噪声都表现良好,服从高斯分布。通常,我们会使用n来表示我们数据集中的示例数量。我们使用上标来枚举样本和目标,并使用下标来索引坐标。更具体地说,x(i)表示i-th 样品和 xj(i)表示其j-th 坐标。
3.1.1.1. 模型
每个解决方案的核心都是一个模型,该模型描述了如何将特征转换为对目标的估计。线性假设意味着目标(价格)的期望值可以表示为特征(面积和年龄)的加权和:
(3.1.1)price=warea⋅area+wage⋅age+b.
这里warea和wage称为 权重,并且b称为偏差(或偏移量或 截距)。权重决定了每个特征对我们预测的影响。当所有特征都为零时,偏差决定了估计值。即使我们永远不会看到任何面积恰好为零的新建房屋,我们仍然需要偏差,因为它允许我们表达特征的所有线性函数(而不是将我们限制在通过原点的直线上)。严格来说, (3.1.1)是输入特征的仿射变换,其特点是通过加权求和对特征进行线性变换,结合平移通过增加偏差。给定一个数据集,我们的目标是选择权重 w和偏见b平均而言,使我们的模型预测尽可能接近数据中观察到的真实价格。
在通常关注仅具有少量特征的数据集的学科中,明确表达模型的长格式,如 (3.1.1)中,是常见的。在机器学习中,我们通常使用高维数据集,在这种情况下使用紧凑的线性代数符号会更方便。当我们的输入包括 d特征,我们可以为每个特征分配一个索引(介于1和 d) 并表达我们的预测y^(通常,“帽子”符号表示估计值)作为
(3.1.2)y^=w1x1+...+wdxd+b.
将所有特征收集到一个向量中 x∈Rd并将所有权重放入向量中 w∈Rd,我们可以通过点积来简洁地表达我们的模型w和x:
(3.1.3)y^=w⊤x+b.
在(3.1.3)中,向量x对应于单个示例的特征。我们经常会发现引用整个数据集的特征很方便n通过 设计矩阵的例子 X∈Rn×d. 这里, X每个示例包含一行,每个特征包含一列。对于功能集合X, 预测y^∈Rn可以通过矩阵向量积表示:
(3.1.4)y^=Xw+b,
在求和期间应用广播(第 2.1.4 节)。给定训练数据集的特征X 和相应的(已知)标签y,线性回归的目标是找到权重向量w和偏置项b给定从相同分布采样的新数据示例的特征X,新示例的标签将(在预期中)以最低的错误率进行预测。
即使我们相信最好的预测模型y给予 x是线性的,我们不希望找到一个真实世界的数据集n例子在哪里y(i)正好等于 w⊤x(i)+b对全部 1≤i≤n. 例如,无论我们使用什么仪器来观察特征X和标签y 可能会出现少量测量误差。因此,即使我们确信潜在关系是线性的,我们也会加入噪声项来解释此类错误。
在我们开始寻找最佳参数(或模型参数)之前w和b,我们还需要两件事:(i)一些给定模型的质量度量;(ii) 更新模型以提高其质量的程序。
3.1.1.2。损失函数
自然地,将我们的模型拟合到数据需要我们就某种适合度(或等价的不适合度)的度量达成一致。损失函数量化 目标的真实值和预测值之间的距离。损失通常是一个非负数,其中值越小越好,完美的预测会导致损失为 0。对于回归问题,最常见的损失函数是平方误差。当我们预测一个例子i是 y^(i)对应的真实标签是 y(i),平方误差由下式给出:
(3.1.5)l(i)(w,b)=12(y^(i)−y(i))2.
常量12没有真正的区别,但证明在符号上很方便,因为当我们对损失求导时它会抵消。因为训练数据集是给我们的,因此不受我们的控制,经验误差只是模型参数的函数。下面,我们可视化线性回归模型在一维输入问题中的拟合(图 3.1.1)。
图 3.1.1将线性回归模型拟合到一维数据。
请注意,估计之间的巨大差异y^(i)和目标y(i)由于损失的二次形式,导致对损失的贡献更大(这可能是一把双刃剑。虽然它鼓励模型避免大的错误,但它也可能导致对异常数据过度敏感)。衡量模型在整个数据集上的质量n例如,我们简单地平均(或等价地,求和)训练集上的损失:
(3.1.6)L(w,b)=1n∑i=1nl(i)(w,b)=1n∑i=1n12(w⊤x(i)+b−y(i))2.
在训练模型时,我们想找到参数(w∗,b∗) 最小化所有训练示例的总损失:
(3.1.7)w∗,b∗=argminw,bL(w,b).
3.1.1.3. 解析解
与我们将介绍的大多数模型不同,线性回归向我们展示了一个非常简单的优化问题。特别是,我们可以通过应用如下简单公式分析地找到最佳参数(根据训练数据评估)。首先,我们可以归入偏差b进入参数w通过将一列附加到由所有元素组成的设计矩阵。那么我们的预测问题就是最小化 ‖y−Xw‖2. 只要设计矩阵X具有满秩(没有特征与其他特征线性相关),那么损失面上将只有一个临界点,它对应于整个域的损失的最小值。对损失求导数 w并将其设置为零会产生:
(3.1.8)∂w‖y−Xw‖2=2X⊤(Xw−y)=0and henceX⊤y=X⊤Xw.
求解w为我们提供了优化问题的最优解。请注意,此解决方案
(3.1.9)w∗=(X⊤X)−1X⊤y
只有当矩阵X⊤X是可逆的,即当设计矩阵的列线性独立时(Golub 和 Van Loan,1996 年)。
虽然像线性回归这样的简单问题可能有解析解,但您不应该习惯这样的好运。尽管解析解可以进行很好的数学分析,但解析解的要求非常严格,以至于几乎排除了深度学习的所有令人兴奋的方面。
3.1.1.4。小批量随机梯度下降
幸运的是,即使在我们无法解析地解决模型的情况下,我们仍然可以在实践中经常有效地训练模型。此外,对于许多任务,那些难以优化的模型结果证明要好得多,以至于弄清楚如何训练它们最终是值得的。
优化几乎所有深度学习模型的关键威廉希尔官方网站 ,以及我们将在整本书中提到的威廉希尔官方网站 ,包括通过在逐渐降低损失函数的方向上更新参数来迭代减少误差。该算法称为 梯度下降。
梯度下降最简单的应用包括对损失函数求导,它是对数据集中每个样本计算的损失的平均值。实际上,这可能非常慢:我们必须在进行单个更新之前传递整个数据集,即使更新步骤可能非常强大 (Liu 和 Nocedal,1989)。更糟糕的是,如果训练数据中存在大量冗余,则完全更新的好处会更低。
另一个极端是一次只考虑一个例子,并一次根据一个观察采取更新步骤。由此产生的算法,随机梯度下降(SGD) 可能是一种有效的策略(Bottou,2010 年),即使对于大型数据集。不幸的是,SGD 在计算和统计方面都有缺点。一个问题是处理器对数字进行乘法和加法运算的速度比将数据从主内存移动到处理器缓存的速度快得多。执行矩阵-向量乘法的效率比相应数量的向量-向量运算高一个数量级。这意味着与整批样品相比,一次处理一个样品可能需要更长的时间。第二个问题是某些层,例如批量归一化(将在第 8.5 节中描述),只有在我们一次访问多个观察值时才能正常工作。
这两个问题的解决方案是选择一个中间策略:我们不是一次获取完整的批次或只获取一个样本,而是获取一个小批量的观察结果(Li等人,2014 年)。所述minibatch大小的具体选择取决于许多因素,例如内存量、加速器数量、层的选择和总数据集大小。尽管如此,一个介于 32 和 256 之间的数字,最好是 2, 是一个好的开始。这将我们引向小批量随机梯度下降。
在其最基本的形式中,在每次迭代中t,我们首先随机抽取一个小批量Bt由固定数组成 |B|的训练例子。然后我们计算小批量平均损失相对于模型参数的导数(梯度)。最后,我们将梯度乘以一个预定的小正值η,称为学习率,并从当前参数值中减去结果项。我们可以这样表达更新:
(3.1.10)(w,b)←(w,b)−η|B|∑i∈Bt∂(w,b)l(i)(w,b).
总之,minibatch SGD 进行如下:(i)初始化模型参数的值,通常是随机的;(ii) 迭代地从数据中抽样随机小批量,在负梯度方向上更新参数。对于二次损失和仿射变换,这有一个封闭形式的展开:
(3.1.11)w←w−η|B|∑i∈Bt∂wl(i)(w,b)=w−η|B|∑i∈Btx(i)(w⊤x(i)+b−y(i))b←b−η|B|∑i∈Bt∂bl(i)(w,b)=b−η|B|∑i∈Bt(w⊤x(i)+b−y(i)).
因为我们选择了一个小批量B我们需要按它的大小归一化|B|. 小批量大小和学习率通常是用户定义的。这种在训练循环中不更新的可调参数称为超参数。它们可以通过多种威廉希尔官方网站 自动调整,例如贝叶斯优化 ( Frazier, 2018 )。最后,解决方案的质量通常在单独的验证数据集(或验证集)上进行评估。
在训练了一些预定的迭代次数后(或直到满足其他一些停止标准),我们记录估计的模型参数,表示为w^,b^. 请注意,即使我们的函数是真正线性且无噪声的,这些参数也不会是损失的精确最小值,甚至不是确定性的。尽管该算法向最小化器收敛的速度很慢,但它通常无法在有限的步数内准确地实现收敛。此外,小批量B用于更新的参数是随机选择的。这打破了决定论。
线性回归恰好是一个具有全局最小值的学习问题(每当X是满秩的,或者等效地,每当 X⊤X是可逆的)。然而,深度网络的损失面包含许多鞍点和最小值。幸运的是,我们通常不关心找到一组精确的参数,而只关心任何导致准确预测(从而降低损失)的参数集。在实践中,深度学习从业者很少努力寻找能够最大限度地减少 训练集损失的参数 (Frankle 和 Carbin,2018 年,Izmailov等人,2018 年)。更艰巨的任务是找到能够对以前看不见的数据进行准确预测的参数,这一挑战称为 泛化。我们将在整本书中回到这些主题。
3.1.1.5。预测
给定模型w^⊤x+b^,我们现在可以对新示例进行预测,例如,根据面积预测以前未见过的房屋的销售价格x1和年龄 x2. 深度学习从业者已开始将预测阶段称为推理,但这有点用词不当——推理泛指根据证据得出的任何结论,包括参数值和未见实例的可能标签。如果有的话,在统计学文献中,推断更多地表示参数推断,当深度学习从业者与统计学家交谈时,这种术语的超载会造成不必要的混淆。在下文中,我们将尽可能坚持预测。
3.1.2. 速度矢量化
在训练我们的模型时,我们通常希望同时处理整个小批量示例。有效地做到这一点需要我们矢量化计算并利用快速线性代数库,而不是在 Python 中编写昂贵的 for 循环。
为了说明为什么这如此重要,我们可以考虑两种添加向量的方法。首先,我们实例化两个包含全 1 的 10,000 维向量。在一种方法中,我们使用 Python for 循环遍历向量。在另一种方法中,我们依赖于对+.
n = 10000 a = torch.ones(n) b = torch.ones(n)
n = 10000 a = np.ones(n) b = np.ones(n)
n = 10000 a = jnp.ones(n) b = jnp.ones(n)
n = 10000 a = tf.ones(n) b = tf.ones(n)
现在我们可以对工作负载进行基准测试。首先,我们使用 for 循环添加它们,一次添加一个坐标。
c = torch.zeros(n) t = time.time() for i in range(n): c[i] = a[i] + b[i] f'{time.time() - t:.5f} sec'
'0.18086 sec'
c = np.zeros(n) t = time.time() for i in range(n): c[i] = a[i] + b[i] f'{time.time() - t:.5f} sec'
'5.17106 sec'
# JAX arrays are immutable, meaning that once created their contents # cannot be changed. For updating individual elements, JAX provides # an indexed update syntax that returns an updated copy c = jnp.zeros(n) t = time.time() for i in range(n): c = c.at[i].set(a[i] + b[i]) f'{time.time() - t:.5f} sec'
'19.67977 sec'
c = tf.Variable(tf.zeros(n)) t = time.time() for i in range(n): c[i].assign(a[i] + b[i]) f'{time.time() - t:.5f} sec'
'12.77678 sec'
或者,我们依靠重新加载的+运算符来计算元素总和。
t = time.time() d = a + b f'{time.time() - t:.5f} sec'
'0.00015 sec'
t = time.time() d = a + b f'{time.time() - t:.5f} sec'
'0.00053 sec'
t = time.time() d = a + b f'{time.time() - t:.5f} sec'
'0.02348 sec'
t = time.time() d = a + b f'{time.time() - t:.5f} sec'
'0.00055 sec'
第二种方法比第一种方法快得多。矢量化代码通常会产生数量级的加速。此外,我们将更多的数学推向库,而无需自己编写那么多的计算,从而减少了出错的可能性并提高了代码的可移植性。
3.1.3. 正态分布和平方损失
到目前为止,我们已经给出了平方损失目标的一个相当实用的动机:最优参数返回条件期望 E[Y∣X]只要基础模式真正是线性的,损失就会对异常值分配过大的惩罚。我们还可以通过对噪声分布进行概率假设,为平方损失目标提供更正式的动机。
线性回归是在 19 世纪初发明的。虽然长期以来一直争论高斯或勒让德首先想到这个想法,但高斯也发现了正态分布(也称为高斯分布)。事实证明,正态分布和具有平方损失的线性回归比共同的亲子关系更深。
首先,回想一下具有均值的正态分布μ和方差σ2(标准偏差σ) 给出为
(3.1.12)p(x)=12πσ2exp(−12σ2(x−μ)2).
下面我们定义一个函数来计算正态分布。
def normal(x, mu, sigma): p = 1 / math.sqrt(2 * math.pi * sigma**2) return p * np.exp(-0.5 * (x - mu)**2 / sigma**2)
def normal(x, mu, sigma): p = 1 / math.sqrt(2 * math.pi * sigma**2) return p * np.exp(-0.5 * (x - mu)**2 / sigma**2)
def normal(x, mu, sigma): p = 1 / math.sqrt(2 * math.pi * sigma**2) return p * jnp.exp(-0.5 * (x - mu)**2 / sigma**2)
def normal(x, mu, sigma): p = 1 / math.sqrt(2 * math.pi * sigma**2) return p * np.exp(-0.5 * (x - mu)**2 / sigma**2)
我们现在可以可视化正态分布。
# Use NumPy again for visualization x = np.arange(-7, 7, 0.01) # Mean and standard deviation pairs params = [(0, 1), (0, 2), (3, 1)] d2l.plot(x, [normal(x, mu, sigma) for mu, sigma in params], xlabel='x', ylabel='p(x)', figsize=(4.5, 2.5), legend=[f'mean {mu}, std {sigma}' for mu, sigma in params])
# Use NumPy again for visualization x = np.arange(-7, 7, 0.01) # Mean and standard deviation pairs params = [(0, 1), (0, 2), (3, 1)] d2l.plot(x.asnumpy(), [normal(x, mu, sigma).asnumpy() for mu, sigma in params], xlabel='x', ylabel='p(x)', figsize=(4.5, 2.5), legend=[f'mean {mu}, std {sigma}' for mu, sigma in params])
# Use JAX NumPy for visualization x = jnp.arange(-7, 7, 0.01) # Mean and standard deviation pairs params = [(0, 1), (0, 2), (3, 1)] d2l.plot(x, [normal(x, mu, sigma) for mu, sigma in params], xlabel='x', ylabel='p(x)', figsize=(4.5, 2.5), legend=[f'mean {mu}, std {sigma}' for mu, sigma in params])
# Use NumPy again for visualization x = np.arange(-7, 7, 0.01) # Mean and standard deviation pairs params = [(0, 1), (0, 2), (3, 1)] d2l.plot(x, [normal(x, mu, sigma) for mu, sigma in params], xlabel='x', ylabel='p(x)', figsize=(4.5, 2.5), legend=[f'mean {mu}, std {sigma}' for mu, sigma in params])
请注意,改变均值对应于沿 x-轴,增加方差会分散分布,降低其峰值。
使用平方损失激励线性回归的一种方法是假设观测值来自噪声测量,其中噪声正态分布如下:
(3.1.13)y=w⊤x+b+ϵwhereϵ∼N(0,σ2).
因此,我们现在可以写出看到特定的 可能性y对于给定的x通过
(3.1.14)P(y∣x)=12πσ2exp(−12σ2(y−w⊤x−b)2).
因此,可能性因式分解。根据最大似然原理,参数的最佳取值w 和b是那些最大化整个数据集的可能性的那些:
(3.1.15)P(y∣X)=∏i=1np(y(i)∣x(i)).
等式如下,因为所有对(x(i),y(i)) 彼此独立绘制。根据最大似然原理选择的估计量称为最大似然估计量。虽然最大化许多指数函数的乘积可能看起来很困难,但我们可以在不改变目标的情况下通过最大化似然的对数来显着简化事情。由于历史原因,优化通常表示为最小化而不是最大化。所以,在不改变任何东西的情况下,我们可以最小化负对数似然,我们可以表示如下:
(3.1.16)−logP(y∣X)=∑i=1n12log(2πσ2)+12σ2(y(i)−w⊤x(i)−b)2.
如果我们假设σ是固定的,我们可以忽略第一项,因为它不依赖于w或者b. 第二项与前面介绍的平方误差损失相同,除了乘法常数1σ2. 幸运的是,该解决方案不依赖于σ任何一个。由此可见,最小化均方误差等同于在加性高斯噪声假设下线性模型的最大似然估计。
3.1.4. 作为神经网络的线性回归
虽然线性模型不足以表达我们将在本书中介绍的许多复杂的神经网络,但神经网络足够丰富,可以将线性模型包含为神经网络,其中每个特征都由一个输入神经元表示,所有这些神经元都连接在一起直接输出。
图 3.1.2将线性回归描述为神经网络。该图突出显示了连接模式,例如每个输入如何连接到输出,但没有突出显示权重或偏差所采用的特定值。
图 3.1.2线性回归是单层神经网络。
输入是x1,…,xd. 我们指的是d作为 输入层中输入的数量或特征维度。网络的输出是o1. 因为我们只是试图预测单个数值,所以我们只有一个输出神经元。请注意,输入值都是给定的。只有一个计算 神经元。综上所述,我们可以将线性回归视为单层全连接神经网络。在以后的章节中,我们将遇到层数更多的网络。
3.1.4.1. 生物学
因为线性回归早于计算神经科学,所以用神经网络来描述线性回归似乎不合时宜。尽管如此,当控制论学家和神经生理学家 Warren McCulloch 和 Walter Pitts 开始开发人工神经元模型时,它们自然而然地成为了起点。考虑图 3.1.3中生物神经元的卡通图片,它由 树突(输入终端)、细胞核(CPU)、轴突(输出线)和轴突终端(输出终端)组成,能够连接到其他神经元通过突触。
图 3.1.3真实的神经元。
信息xi来自其他神经元(或环境传感器)的信号被树突接收。特别是,该信息由突触权重加权 wi,确定输入的影响,例如,通过产品激活或抑制 xiwi. 来自多个来源的加权输入在核中聚合为加权和 y=∑ixiwi+b,可能通过一些非线性后处理σ(y). 然后该信息通过轴突发送到轴突末端,在那里它到达目的地(例如,诸如肌肉的致动器)或通过其树突被馈送到另一个神经元。
当然,许多这样的单元可以与正确的连接和正确的学习算法相结合,产生比任何一个神经元单独表达的更有趣和复杂的行为的高级想法归功于我们对真实生物神经系统的研究。与此同时,当今深度学习的大多数研究都从更广泛的来源中汲取灵感。我们援引Russell 和 Norvig ( 2016 )的观点,他们指出虽然飞机可能受到鸟类的启发,但几个世纪以来鸟类学并不是航空创新的主要驱动力。同样,如今深度学习的灵感同样或更多地来自数学、语言学、心理学、统计学、计算机科学和许多其他领域。
3.1.5. 概括
在本节中,我们介绍了传统的线性回归,其中选择线性函数的参数以最小化训练集上的平方损失。我们还通过一些实际考虑以及通过将线性回归解释为线性和高斯噪声假设下的最大似然估计来激发这种目标选择。在讨论了计算注意事项和与统计的联系之后,我们展示了如何将此类线性模型表示为简单的神经网络,其中输入直接连接到输出。虽然我们很快将完全超越线性模型,但它们足以介绍我们所有模型所需的大部分组件:参数形式、可微分目标、通过小批量随机梯度下降进行优化,以及最终,
3.1.6. 练习
假设我们有一些数据 x1,…,xn∈R. 我们的目标是找到一个常数b这样∑i(xi−b)2被最小化。
找到最优值的解析解b.
这个问题及其解决方案与正态分布有何关系?
如果我们将损失从∑i(xi−b)2到 ∑i|xi−b|?你能找到最优解吗 b?
证明仿射函数可以表示为 x⊤w+b相当于线性函数(x,1).
假设你想找到的二次函数 x, IE, f(x)=b+∑iwixi+∑j≤iwijxixj. 你会如何在一个深度网络中表达这个?
回想一下,线性回归问题可解的条件之一是设计矩阵 X⊤X有满级。
如果不是这种情况会怎样?
你怎么能修好它?如果向所有条目添加少量坐标独立的高斯噪声会发生什么 X?
设计矩阵的期望值是多少 X⊤X在这种情况下?
当随机梯度下降时会发生什么 X⊤X没有满级?
假设控制加性噪声的噪声模型 ϵ是指数分布。那是, p(ϵ)=12exp(−|ϵ|).
写出模型下数据的负对数似然 −logP(y∣X).
你能找到一个封闭形式的解决方案吗?
建议一个小批量随机梯度下降算法来解决这个问题。可能会出现什么问题(提示:当我们不断更新参数时,驻点附近会发生什么)?你能修这个吗?
假设我们要通过组合两个线性层来设计一个具有两层的神经网络。也就是说,第一层的输出成为第二层的输入。为什么这样天真的构图不起作用?
如果您想使用回归来估算房屋或股票价格的实际价格会怎样?
表明加性高斯噪声假设是不合适的。提示:我们可以有负价格吗?波动呢?
为什么回归到价格的对数会好得多,即y=logprice?
在处理 pennystock(即价格非常低的股票)时,您需要担心什么?提示:你能以所有可能的价格进行交易吗?为什么这对廉价股票来说是一个更大的问题?
有关更多信息,请查看著名的期权定价 Black-Scholes 模型(Black 和 Scholes,1973 年)。
假设我们想使用回归来估计杂货店出售的苹果数量。
高斯加性噪声模型有什么问题?提示:你卖的是苹果,不是油。
泊松分布 捕获计数分布。它由 p(k∣λ)=λke−λ/k!. 这里 λ是率函数和k是您看到的事件数。证明λ是计数的期望值k.
设计与泊松分布相关的损失函数。
设计用于估计的损失函数logλ 反而。
-
线性回归
+关注
关注
0文章
41浏览量
4306 -
pytorch
+关注
关注
2文章
808浏览量
13202
发布评论请先 登录
相关推荐
评论