线性回归
模型、损失函数及其解析解
将所有特征放到向量x∈R^d中去并将所有权重放到向量w∈R^d中可以用以下式子表示模型:
对于n个样本集用矩阵X∈R^n*d表示则预测值 ∈ R^n,则可以用矩阵-向量的乘法表示为:
平方误差:
损失函数:
可以将偏置b合并到参数w中即w = ( w1 , ... , wn , b ) 此时 x = ( x1 , ... , xn , 1 )
由于线性回归较为简单,因此其存在解析解:
随机梯度下降
| B | 表示每个校批量中的样本数,这也成为批量大小。η 表示学习率,批量大小和学习率的值永昌是手动预先指定。
矢量化加速
在训练我们的模型时,我们经常希望能够同时处理整个小批量的样本。 为了实现这一点,需要(我们对计算进行矢量化, 从而利用线性代数库,而不是在Python中编写开销高昂的for循环)。
%matplotlib inline
import math
import time
import numpy as np
import torch
from d2l import torch as d2l
为了说明矢量化为什么如此重要,我们考虑(对向量相加的两种方法)。 我们实例化两个全为1的10000维向量。 在一种方法中,我们将使用Python的for循环遍历向量; 在另一种方法中,我们将依赖对+
的调用。
n = 10000
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.16749 sec'
timer.start()
d = a + b
f'{timer.stop():.5f} sec'
'0.00042 sec'
结果很明显,第二种方法比第一种方法快得多。 矢量化代码通常会带来数量级的加速。 另外,我们将更多的数学运算放到库中,而无须自己编写那么多的计算,从而减少了出错的可能性。
正态分布与平方损失
import numpy as np
import matplotlib.pyplot as plt
def normal(x, mu, sigma):
p = 1 / (np.sqrt(2 * np.pi) * sigma)
return p * np.exp(-0.5 * ((x - mu) / sigma)**2)
x = np.arange(-7, 7, 0.01)
params = [(0, 1), (0, 2), (3, 1)]
plt.figure(figsize=(8, 5))
for mu, sigma in params:
plt.plot(x, normal(x, mu, sigma), label=f'mean {mu}, std {sigma}')
plt.xlabel('x')
plt.ylabel('p(x)')
plt.legend()
plt.grid(True)
plt.show()