注:本代码在jupyter notebook上运行
封面图片来源
1 、矢量化加速
在训练模型时, 为了实现同时处理整个小批量的样本,需要对计算进行矢量化, 从而利用线性代数库,而不是在Python中编写开销高昂的for循环。
%matplotlib inline
# %matplotlib inline 是一个IPython魔术命令(magic command),主要用于Jupyter Notebook或IPython环境中,用于控制matplotlib绘图的显示方式。当你在Jupyter Notebook中运行这个命令时,它会使得matplotlib生成的图表直接嵌入到Notebook的输出中,而不是在新的窗口中打开。
import math
import time
import numpy as np
import torch
# from d2l import torch as d2l
# 两个全为1的10000维向量
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'
使用重载的+运算符来计算按元素的和。
timer.start()
d = a + b
f'{timer.stop():.5f} sec'
可见用矢量计算速度相当快
2、正态分布与平方损失
定义函数计算平方损失
def normal(x, mu, sigma):
p = 1 / np.sqrt(2 * np.pi * sigma**2)
return p * np.exp(-0.5 / sigma**2 * (x - mu)**2)
from matplotlib import pyplot as plt
可视化正态分布
# 再次使用numpy进行可视化
x = np.arange(-7, 7, 0.01)
# 均值和标准差对
params = [(0, 1), (0, 2), (3, 1)]
plt.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])
报错:ValueError: x and y must have same first dimension, but have shapes (1400,) and (3, 1400)
列表推导式中,normal(x, mu, sigma) 对于每个 (mu, sigma) 对都被独立地计算了,但是由于 x 是一个一维数组,而 params 是一个包含三个元素的列表,所以列表推导式 [normal(x, mu, sigma) for mu, sigma in params] 实际上生成了一个形状为 (3, 1400) 的二维数组,其中每一行都对应于一个 (mu, sigma) 对计算出的正态分布的概率密度函数。
然而,plt.plot() 函数期望的 y 参数应该是一个一维数组或者是一个一维数组的列表(在这种情况下,它会绘制多条线,每条线对应一个数组)。为了解决这个问题,应该使用循环来分别绘制每条线。
# 创建一个空列表来存储每条线的句柄(可选,用于图例)
lines = []
# 使用循环来绘制每条线
for mu, sigma in params:
line, = plt.plot(x, normal(x, mu, sigma), label=f'mean {mu}, std {sigma}')
lines.append(line) # 将线的句柄添加到列表中
# 设置图表的其他属性
plt.xlabel('x')
plt.ylabel('p(x)')
plt.figsize=(4.5, 2.5) # 注意:应该在调用plt.plot()之前设置,但在这里也可以
plt.legend(handles=lines) # 使用之前收集的句柄来创建图例
plt.show()
本人学习地址https://zh-v2.d2l.ai/
恳请大佬批评指正。