Java教程

动手学深度学习(二)——线性神经网络

本文主要是介绍动手学深度学习(二)——线性神经网络,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

在学习深度神经网络之前,需要了解神经网络训练的基础知识。 包括:定义简单的神经网络架构、数据处理、指定损失函数和如何训练模型。 为了更容易学习,从经典算法————线性神经网络开始,了解神经网络的基础知识。

文章目录

  • 1.1 线性回归中的基本元素
    • 1.1.1 线性模型
    • 1.1.2 损失函数
    • 1.1.3 随机梯度下降
  • 1.2 矢量化加速
  • 1.3 正态分布与平方损失
  • 1.4 从线性回归到深度网络
  • 1.5 总结

1.1 线性回归中的基本元素

线性回归基于几个简单的假设:
首先,假设自变量 x 和因变量 y 之间的关系是线性的, 即 y 可以表示为 x 中元素的加权和,这里通常允许包含观测值的一些噪声; 其次,我们假设任何噪声都比较正常,如噪声遵循正态分布。
我们以一个非常经典的根据房屋的面积(平方米)和房龄(年)来估算房屋价格的模型为例。
首先,我们需要准备训练数据集(training data set) 或训练集(training set),包括真实的房屋价格,面积和房龄。
我们把试图预测的目标(比如预测房屋价格)称为标签(label)或目标(target)。 预测所依据的自变量(面积和房龄)称为特征(feature)或协变量(covariate)

1.1.1 线性模型

根据最开始我们的线性假设,我们的预测目标(房屋价格)可以表示为(面积和房龄)的加权和,用一个数学表达式来表示如下:
在这里插入图片描述

这个表达式可以看作输入特征的一个 仿射变换(affine transformation)。 仿射变换的特点是通过加权和对特征进行线性变换(linear transformation), 并通过偏置项来进行平移(translation)

warea 和 wage 称为权重(weight)权重决定了每个特征对我们预测值的影响。
b 称为偏置(bias)、偏移量(offset)或截距(intercept)。(表述成截距可能更熟悉)可以很清楚的看到,b可以表示当所有特征都取0时,预测值为多少。即使现实中不会有任何房子的面积是0或房龄正好是0年,我们仍然需要偏置项。 如果没有偏置项,我们模型的表达能力将受到限制

在机器学习中,我们通常使用的是高维数据集,很多个特征(feature)的输入
在这里插入图片描述
所以用线性代数的方式,用向量来表示会更方便,同时向量的点积可以表示加权和,就会简化成如下形式:
在这里插入图片描述
表示完这种数学模型之后,就可以发现,表达式中有两个模型参数(model parameters)w 和 b ,接下来就是确定这两个参数,我们就引入了另外两个概念:

  • 损失函数:一种模型质量的度量方式
  • 随机梯度下降:一种能够更新模型以提高模型预测质量的方法。

1.1.2 损失函数

损失函数(loss function)能够量化目标的实际值与预测值之间的差距。
通常我们会选择非负数作为损失,且数值越小表示损失越小,完美预测时的损失为0。
回归问题中最常用的损失函数是平方误差函数。 当样本 i 的预测值为 y^(i) ,其相应的真实标签为 y(i) 时, 平方误差可以定义为以下公式
在这里插入图片描述

常数 1/2 不会带来本质的差别,但这样在形式上稍微简单一些 (因为当我们对损失函数求导后常数系数为1)。

用线性模型拟合数据
由于平方误差函数中的二次方项, 估计值 y^(i) 和观测值 y(i) 之间较大的差异将导致更大的损失。 为了度量模型在整个数据集上的质量,我们需计算在训练集 n 个样本上的损失均值(也等价于求和)
在这里插入图片描述
在训练模型时,我们希望寻找一组参数( w∗,b∗ ), 这组参数能最小化在所有训练样本上的总损失。
在这里插入图片描述

1.1.3 随机梯度下降

梯度下降(gradient descent), 这种方法几乎可以优化所有深度学习模型。 它通过不断地在损失函数递减的方向上更新参数来降低误差。
梯度下降最简单的用法是计算损失函数关于模型参数的导数(在这里也可以称为梯度)。
但实际中的执行可能会非常慢:因为在每一次更新参数之前,我们必须遍历整个数据集。 因此,我们通常会在每次需要计算更新的时候随机抽取一小批样本, 这种变体叫做小批量随机梯度下降(minibatch stochastic gradient descent)
算法步骤:
(1)初始化模型参数的值,如随机初始化;
(2)从数据集中随机抽取小批量样本,计算小批量的平均损失关于模型参数的导数(也可以称为梯度)。 最后,我们将梯度乘以一个预先确定的正数 η ,并从当前参数的值中减掉。并不断迭代这一步骤。
在这里插入图片描述

| B| 表示每个小批量中的样本数,这也称为批量大小(batch size)。 η表示学习率(learning rate)。 批量大小和学习率的值通常是手动预先指定,而不是通过模型训练得到的。 这些可以调整但不在训练过程中更新的参数称为超参数(hyperparameter)
调参(hyperparameter tuning)是选择超参数的过程。 超参数通常是我们根据训练迭代结果来调整的, 而训练迭代结果是在独立的验证数据集(validation dataset)上评估得到的。

例如对对于平方损失中的wB
在这里插入图片描述
线性回归恰好是一个在整个域中只有一个最小值的学习问题。 但是对于像深度神经网络这样复杂的模型来说,损失平面上通常包含多个最小值。 需要花费大力气寻找这样一组参数,使得在训练集上的损失达到最小。 事实上,更难做到的是找到一组参数,这组参数能够在我们从未见过的数据上实现较低的损失, 这一挑战被称为泛化(generalization)。

1.2 矢量化加速

其实简单来说就是利用线性代数库,而不是在for循环,来简化运算过程。对两个向量用两种方式相加的过程进行计时,来表示他们之间的效率差异

n = 100000
a = torch.ones(n)
b = torch.ones(n)

一个常用的计时器:

class Timer:  #@save
    """记录多次运行时间"""
    def __init__(self):
        self.times = []
        self.start()

    def start(self):
        """启动计时器"""
        self.tik = time.time()

    def stop(self):
        """停止计时器并将时间记录在列表中"""
        self.times.append(time.time() - self.tik)
        return self.times[-1]

    def avg(self):
        """返回平均时间"""
        return sum(self.times) / len(self.times)

    def sum(self):
        """返回时间总和"""
        return sum(self.times)

    def cumsum(self):
        """返回累计时间"""
        return np.array(self.times).cumsum().tolist()

第一种:使用for循环,每次执行一位的加法:

c = torch.zeros(n)
timer = Timer()
for i in range(n):
    c[i] = a[i] + b[i]
f'{timer.stop():.5f} sec'

输出时长:

'0.76498 sec'

第二种:使用重载的+运算符来计算按元素的和。

timer.start()
d = a + b
f'{timer.stop():.5f} sec'

输出时长:

'0.00100 sec'

结果很明显,第二种方法比第一种方法快得多。 矢量化代码通常会带来数量级的加速。 另外,我们将更多的数学运算放到库中,而无须自己编写那么多的计算,从而减少了出错的可能性。

1.3 正态分布与平方损失

正态分布和线性回归之间的关系很密切。 正态分布(normal distribution),也称为高斯分布(Gaussian distribution)其正态分布概率密度函数如下:
在这里插入图片描述
下面我们定义一个Python函数来计算正态分布。

def normal(x, mu, sigma):
    p = 1 / math.sqrt(2 * math.pi * sigma**2)
    return p * np.exp(-0.5 / sigma**2 * (x - mu)**2)

进行可视化:

# 再次使用numpy进行可视化
x = np.arange(-7, 7, 0.01)

# 均值和标准差对
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'mu {mu}, sigma {sigma}' for mu, sigma in params])

在这里插入图片描述
如图,就是对正态分布的理解:改变均值(mu)会产生沿 x 轴的偏移,增加方差(sigma)将会分散分布、降低其峰值。
均方损失可以用于线性回归的一个原因是: 我们假设了观测中包含噪声,其中噪声服从正态分布。 噪声正态分布如下式:
在这里插入图片描述
可以写出通过给定的 x 观测到特定 y 的似然(likelihood):
在这里插入图片描述
根据极大似然估计法,参数 w 和 b 的最优值是使整个数据集的似然最大的值
在这里插入图片描述
根据极大似然估计法选择的估计量称为极大似然估计量。 虽然使许多指数函数的乘积最大化看起来很困难,我们可以通过概率论中计算最大化似然对数来简化。 由于历史原因,优化通常是说最小化而不是最大化。 我们可以改为最小化负对数似然 −logP(y∣X) 。
在这里插入图片描述
现在我们只需要假设 σ 是某个固定常数就可以忽略第一项, 因为第一项不依赖于 w 和 b 。 现在第二项除了常数 1/σ2 外,其余部分和前面介绍的均方误差是一样的。
因此,在高斯噪声的假设下,最小化均方误差等价于对线性模型的极大似然估计

1.4 从线性回归到深度网络

尽管神经网络涵盖了更多更为丰富的模型,我们依然可以用描述神经网络的方式来描述线性模型, 从而把线性模型看作一个神经网络, 该图只显示连接模式,即只显示每个输入如何连接到输出,隐去了权重和偏置的值。

在这里插入图片描述
图中,输入为 x1,…,xd , 因此输入层中的输入数(或称为特征维度,feature dimensionality)为 d 。 网络的输出为 o1 ,因此输出层中的输出数是1。 需要注意的是,输入值都是已经给定的,并且只有一个计算神经元。
由于模型重点在发生计算的地方,所以通常我们在计算层数时不考虑输入层。 所以图中神经网络的层数为1。 我们可以将线性回归模型视为仅由单个人工神经元组成的神经网络,或称为单层神经网络。
对于线性回归,每个输入都与每个输出(在本例中只有一个输出)相连, 我们将这种变换( 图3中的输出层) 称为全连接层(fully-connected layer)或称为稠密层(dense layer)

1.5 总结

  • 机器学习模型中的关键要素是训练数据、损失函数、优化算法,还有模型本身。
  • 矢量化使数学表达上更简洁,同时运行的更快。
  • 最小化目标函数和执行极大似然估计等价。
  • 线性回归模型也是一个简单的神经网络。
这篇关于动手学深度学习(二)——线性神经网络的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!