李沫《动手学习深度学习》课程学习
需要预备的知识 | 原因 | 重点 |
---|---|---|
线性代数 | 处理表格数据 | 矩阵运算 |
微积分 | 决定以何种方式调整参数 | 损失函数(loss function)—— 衡量“模型有多糟糕”这个问题的分数 梯度(gradient)—— 连结一个多元函数对其所有变量的偏导数,简单理解就是求导 |
概率 | 在不确定的情况下进行严格的推断 |
目录
2.1. 数据操作——张量
2.1.1. 入门
2.1.2. 运算符
2.1.3. 广播机制
2.1.4. 索引和切片
2.1.5. 节省内存
2.1.6. 转换为其他Python对象
2.1.8. 练习
2.2. 数据预处理
2.3. 线性代数
2.3.1. 标量
2.3.2. 向量
2.3.3. 矩阵
2.3.4. 降维
2.3.4.1. 非降维求和——轴数不变
2.3.5. 练习编辑
2.4. 微积分
2.5. 自动微分
2.6. 概率
一个名词——张量(tensor),指n维数组,其中具有一个轴的张量对应数学上的向量(vector); 具有两个轴的张量对应数学上的矩阵(matrix)
多维张量的几何理解 - 简书 (jianshu.com)
张量的几何理解库名:torch
函数名 | 作用 | 例子 | 结果 |
---|---|---|---|
shape | 访问张量(沿每个轴的长度)的形状 | x.shape | torch.Size([12]) |
size() | 访问张量(沿每个轴的长度)的形状 | x.size() | torch.Size([12]) |
numel() | 张量中元素的总数 | x.numel() | 12 |
reshape() | 改变一个张量的形状而不改变元素数量和元素值 | x.reshape(3,4) | |
——按元素(elementwise)运算
对于任意具有相同形状的张量, 常见的标准算术运算符(+
、-
、*
、/
和**
)都可以被升级为按元素运算。 我们可以在同一形状的任意两个张量上调用按元素操作。
torch.cat 张量连结补充
名词解释:把给定张量端对端地叠起来形成一个更大的张量。
torch.cat 张量连结例子上面的例子分别演示了当沿行(轴-0,形状的第一个元素) 和按列(轴-1,形状的第二个元素)连结两个矩阵时,会发生什么情况。 可以看到,第一个输出张量的轴-0长度(6)是两个输入张量轴-0长度的总和(3+3); 第二个输出张量的轴-1长度(8)是两个输入张量轴-1长度的总和(4+4)
——形状不同的张量通过调用 广播机制(broadcasting mechanism)来执行按元素操作。
广播机制工作方式:复制元素拓展数组,使两个张量具有相同的形状。
拓展方法:在大多数情况下,我们将沿着数组中长度为1的轴进行广播。
例子:a
和b
分别是3×1和1×2矩阵,如果让它们相加,它们的形状不匹配。 我们将两个矩阵广播为一个更大的3×2矩阵,如下所示:矩阵a
将复制列, 矩阵b
将复制行,然后再按元素相加。
——第一个元素的索引是0,最后一个元素索引是-1
例子 | 意义 |
---|---|
X[-1] | 选择最后一个元素 |
X[1:3] | 选择第二个和第三个元素 |
X[0:2,:] | 访问第1行和第2行,其中“:”代表沿轴1(列)的所有元素。 |
低层逻辑:运行一些操作可能会导致为新结果分配内存,机器学习运算量巨大,会导致内存不断被更新占用。
现实意义:节省内存,更重要的是防止需要引用最新值时由于一些问题还是指向了旧值地址,导致错误。
方法:切片表示法,例Y[:] =
Z = torch.zeros_like(Y)
print('id(Z):', id(Z))
Z[:] = X + Y
print('id(Z):', id(Z))
output:
id(Z): 140316199714544
id(Z): 140316199714544
numpy转torch
A = X.numpy()
B = torch.tensor(A)
type(A), type(B)
output:
(numpy.ndarray, torch.Tensor)
torch张量转标量——item函数或Python的内置函数
a = torch.tensor([3.5])
a # tensor([3.5000])
a.item() # 3.5
float(a) # 3.5
int(a) # 3
运行本节中的代码。将本节中的条件语句X == Y
更改为X < Y
或X > Y
,然后看看你可以得到什么样的张量。
x
用其他形状(例如三维张量)替换广播机制中按元素操作的两个张量。结果是否与预期相同
是相同的,但要注意两个问题:
(1) 第3个维度必须相同,否则相加报错
——运用pandas库
注:数据预处理是深度学习中很重要的一部分,pandas库是一个很常用且强大的库,本书中该部分并不是重点,内容较少,在此不总结,会再写一篇文章具体总结pandas库的一些详细用法,并跑几个例程。
——包含一个数值的叫标量(scalar)
1、实例
标量实例2、数学知识
标量的一些数学知识—— 一维张量,将标量从零阶推广到一阶
1、实例
向量实例2、数学知识
向量的一些数学知识1 向量的一些数学知识2注:点乘和点积(dot product)是一个东西,给定两个向量相同位置的按元素乘积的和。
—— 二维张量,将向量从一阶推广到二阶
1、实例
矩阵实例2、矩阵基础知识
代码 | 含义 | 数学解释 |
---|---|---|
A.T | 矩阵的转置 | 交换矩阵的行和列 |
A==A.T结果均为True | 对称矩阵 | Aij = Aji |
反对称矩阵 | Aij = -Aji | |
正交矩阵 | AAT=E(E为单位矩阵,AT表示“矩阵A的转置矩阵”)或ATA=E 什么是正交矩阵-百度经验 (baidu.com) |
|
置换矩阵 | A 是方阵,A 的每一行和每一列都有且仅有一个1,其余均为0 【2.7】P矩阵:置换矩阵 - 知乎 (zhihu.com) |
|
方阵 | 矩阵的行数与列数相等 |
补充知识:特征向量与特征值特征值与特征向量 (baidu.com)
3、数学知识
矩阵的一些数学知识1Hadamard积:两个矩阵的按元素乘法
矩阵的一些数学知识2矩阵乘法会对空间进行扭曲,公式不好理解,视频清楚:矩阵乘法的动画演示_哔哩哔哩_bilibili
矩阵的一些数学知识2 矩阵的一些数学知识3范数其实可以理解为一种长度,常见L1、L2范数
在深度学习中,我们经常试图解决优化问题: 最大化分配给观测数据的概率; 最小化预测和真实观测之间的距离。 用向量表示物品(如单词、产品或新闻文章),以便最小化相似项目之间的距离,最大化不同项目之间的距离。 目标,或许是深度学习算法最重要的组成部分(除了数据),通常被表达为范数。
4、代码中的函数
函数 | 意义 |
---|---|
A+B | A、B张量加法 |
A * B | A、B张量的Hadamard积 |
torch.dot(x,y) | x,y向量点积 |
torch.sum(x*y) | 执行按元素乘法,然后进行求和来表示两个向量的点积 |
torch.mv(A,x) | 矩阵A和向量x的矩阵-向量积,注意,A 的列维数(沿轴1的长度)必须与x 的维数(其长度)相同。 |
torch.mm(A,B) | 矩阵A和矩阵B乘法 |
torch.norm(u) | u张量的L2范数(Frobenius范数) |
torch.abs(u).sum() | u张量的L1范数,将绝对值函数和按元素求和组合起来。 |
方法:
1、求和
直接求和——沿所有的轴降低张量的维度,变为一个标量,向量、矩阵均适用
指定张量沿哪一个轴来求和:
2、求平均
直接求平均:
指定轴:
1、cumsum函数不会沿任何轴降低输入张量的维度。
2、由于sum_A在对每行进行求和后仍保持两个轴,我们可以通过广播将A除以sum_A。
微分和积分是微积分的两个分支,前者可以应用于深度学习中的优化问题。
导数可以被解释为函数相对于其变量的瞬时变化率,它也是函数曲线的切线的斜率。
标量关于列向量的导数是一个行向量。
列向量关于标量的导数是一个列向量。
向量关于向量的导数结果是一个矩阵。
梯度是一个向量,指向值最大的方向,其分量是多变量函数相对于其所有变量的偏导数。
链式法则使我们能够微分复合函数。
深度学习框架通过自动计算导数,即自动微分(automatic differentiation)来加快求导。 实际中,根据我们设计的模型,系统会构建一个计算图(computational graph),来跟踪计算是哪些数据通过哪些操作组合起来产生输出。 自动微分使系统能够随后反向传播(方向累积)梯度。 这里,反向传播(backpropagate)意味着跟踪整个计算图,填充关于每个参数的偏导数。
计算图(链式法则过程)1、backward()反向传播函数和grad函数计算梯度
最基础例子:对函数y=2x⊤x(y等于标量2乘列向量x点积列向量x)关于列向量x求导(按照规则求导后结果为y=4x)
import torch
x = torch.arange(4.0)
x
x.requires_grad_(True) # 等价于x=torch.arange(4.0,requires_grad=True),梯度存的位置
x.grad # 默认值为None
y = 2 * torch.dot(x, x) # y为标量
y
y.backward() # 通过调用反向传播函数来自动计算y关于x每个分量的梯度
x.grad # 打印梯度
在默认情况下,pytorch会累积梯度,单运用同一个变量进行运算,需要清除之前的值,运用下面这行代码
x.grad.zero_()
2、非标量变量的反向传播
当y
不是标量时,机器学习中通常单独计算批量中每个样本的偏导数之和,如下代码所示。
# 对非标量调用backward需要传入一个gradient参数,该参数指定微分函数关于self的梯度。
# 在我们的例子中,我们只想求偏导数的和,所以传递一个1的梯度是合适的
x.grad.zero_()
y = x * x
# 等价于y.backward(torch.ones(len(x)))
y.sum().backward()
x.grad
3、运用detach()函数使在系统中函数类型转为常数类型
例子:计算z=u*x
关于x
的偏导数,同时将u
作为常数处理, 而不是z=x*x*x
关于x
的偏导数。
x.grad.zero_()
y = x * x
u = y.detach()
z = u * x
z.sum().backward()
x.grad == u
output:tensor([True, True, True, True])
##由于记录了y的计算结果,可以随后在y上调用反向传播, 得到y=x*x关于的x的导数,即2*x。
x.grad.zero_()
y.sum().backward()
x.grad == 2 * x
output:tensor([True, True, True, True])
4、通过Python控制流(例如,条件、循环或任意函数调用),仍然可以计算得到的变量的梯度。
例子:在下面的代码中,while
循环的迭代次数和if
语句的结果都取决于输入a
的值。
def f(a):
b = a * 2
while b.norm() < 1000:
b = b * 2
if b.sum() > 0:
c = b
else:
c = 100 * b
return c
#计算梯度
a = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()
a.grad == d / a
output:tensor(True)
小结:深度学习框架可以自动计算导数,首先将梯度附加到想要对其计算偏导数的变量上。然后记录目标值的计算,执行它的反向传播函数,并访问得到的梯度。
我们可以从概率分布中采样。
我们可以使用联合分布、条件分布、Bayes定理、边缘化和独立性假设来分析多个随机变量。
期望和方差为概率分布的关键特征的概括提供了实用的度量形式。