1、深度学习实现步骤

  • 数据集建立
  • 选择模型
  • 训练
  • 推理/预测

2、线性模型基本概念

  • 训练集/数据集
  • 样本/数据点:数据集中的每一行数据称为一个样本
  • 标签/目标:需要预测的目标
  • 特征/协变量:预测所依据的自变量
  • 线性假设:目标可以表述为特征的加权和
  • 偏置:当所有特征为0时,目标预测值的大小
  • 噪声项:无论权重和偏置如何精准,预测值都不可避免地产生误差,此时需要噪声项来考虑观测误差带来的影响

对于特征集合,预测值可以通过矩阵乘法表示。

线性回归的目标是,找到一个权重w和偏置值b使得给出一组特征时,所获得的预测值可以尽可能真实。而在找到最好的模型参数w和b前,我们还需要两个东西:模型质量的度量方式、能够更新模型使预测更精准的方法。

3、损失函数

损失函数可以量化预测值和实际值之间的差距,一般会选使用非负数,数据越小,损失越小。

平方误差函数:预测值和实际值的误差的平方,损失函数求导后参数一般为1,由于平方项会使误差更大,一般我们会计算整个数据集上所有样本的损失均值。

临界点:整个区域损失极小点

解析解:将b也归入w矩阵中,损失关于w的导数设为0,得到解析解,并不是所有问题都能得到解析解,线性回归可以。

梯度下降:不断地在损失函数减小的方向上来更新参数来降低误差,这种方式几乎可以优化所有深度学习模型。

梯度下降最简单的用法:计算损失函数关于模型参数的导数

小批量随机梯度下降:由于每次更新参数之前都要遍历所有的数据集,导致时间太长,所以回不在遍历之前随机抽取一小部分样本。

超参数:可以调整但是不在训练中更新的参数,比如批量大小和学习率,通常通过训练迭代结果来调整,训练迭代结果是在独立的验证数据集上评估得到的。

调参:选择超参数的过程

泛化:损失平面上通常包含多个最小值,寻找到这样一组参数,使得这组参数能够在我们从未见到过的数据上实现最小的损失,这一过程称为泛化。

4、矢量化加速

import torch
import math
import time
import numpy as np
# %matplotlib inline #这是 IPython 的魔法命令,作用是将 Matplotlib 绘制的图形直接嵌入到当前的 Notebook(比如 Jupyter Notebook)中,方便在 Notebook 里查看图形结果,而不是弹出独立的图形窗口。
# import matplotlib_inline
n = 10000
a = torch.ones([n])
b = torch.ones([n])
# 创建的是一个长度为 10000,所有元素都是 1 的一维张量tensor,ones方法是关键。
print(a)
class Timer:  #@save
    """记录多次运行时间"""
    def __init__(self):  # 类的初始化方法,在创建 Timer 类的实例时会被调用。
        self.times = []   # 初始化一个空列表 times,用于存储每次计时的时间间隔。
        self.start()   # 调用 start 方法,在实例创建时就启动计时器。

    def start(self):
        """启动计时器"""
        self.tik = time.time()  # 使用 time.time() 获取当前时间戳,并将其赋值给实例变量 tik,作为计时的起始时间。

    def stop(self):
        """停止计时器并将时间记录在列表中"""
        self.times.append(time.time() - self.tik) # 当前时间减去计时器启动时间。
        # 计算从 tik 记录的起始时间到当前时间的时间间隔,然后将这个时间间隔添加到 times 列表中。
        return self.times[-1] # 返回列表中最后一个元素

    def avg(self):
        """返回平均时间"""
        return sum(self.times) / len(self.times) # 计算 times 列表中所有时间间隔的总和,再除以列表的长度,得到平均时间并返回。

    def sum(self):
        """返回时间总和"""
        return sum(self.times) # 返回 times 列表中所有时间间隔的总和。

    def cumsum(self):
        """返回累计时间"""
        return np.array(self.times).cumsum().tolist() # 首先将 times 列表转换为 NumPy 数组,然后使用 cumsum 方法计算累计和,最后再将结果转换回 Python 列表并返回。

c = torch.zeros(n)
timer = Timer()  # 实例化Timer类
for i in range(n):
    c[i] = a[i] + b[i]
print(f'{timer.stop():.5f} sec')
# 使用循环计算,时间为0.1sec量级

timer.start()
d = a + b
print(f'{timer.stop():.5f} sec')
# 使用重载的加法计算,时间为0.0001sec量级
# 矢量化代码通常会带来数量级的加速

5、正态分布与平方损失

# 定义正态分布概率密度函数
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) #生成从\(-7\)到7,步长为\(0.01\)的数组,作为正态分布的自变量取值

# 均值和标准差对
params = [(0, 1), (0, 2), (3, 1)] # 定义了三组 “均值\(\mu\) - 标准差\(\sigma\)” 参数,分别是(均值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])    # 图例

# 就像我们所看到的,改变均值会产生沿轴的偏移,增加方差将会分散分布、降低其峰值。
# 均方误差损失函数(简称均方损失)可以用于线性回归的一个原因是: 我们假设了观测中包含噪声,其中噪声服从正态分布

涉及到概率论与数理统计的数学知识,需要进一步学习。

6、从线性回归到深度网络

  • 特征维度:输入层的输入个数。
  • 神经网络层数计算:由于模型重点在发生计算的地方,所以通常我们在计算层数时不考虑输入层。
  • 线性回归模型可视为仅由单个人工神经元组成的神经网络,或称为单层神经网络。

7、小结

  • 机器学习模型中的关键要素是训练数据、损失函数、优化算法,还有模型本身。
  • 矢量化使数学表达上更简洁,同时运行的更快。
  • 最小化目标函数和执行极大似然估计等价。
  • 线性回归模型也是一个简单的神经网络。

更多推荐