动手学深度学习(pytorch)学习记录6-矢量化加速与正态分布与平方损失[学习记录]

注:本代码在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/
恳请大佬批评指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

walfar

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值