深度学习学习笔记(1)前置知识

偏导数与梯度

偏导数是对于一个多元函数将其他变量当作常数时,某个变量的导数,记作$ \frac{\partial y}{\partial x_i} $。

偏导数有多种表示方式:$$ \frac{\partial y}{\partial x_i} = \frac{\partial f}{\partial x_i} = f_{x_i} = f_i = D_i f = D_{x_i} f $$

多元函数对其所有变量的偏导数连结成的向量即为其梯度:$$ \nabla_{\mathbf{x}} f(\mathbf{x}) = \bigg[\frac{\partial f(\mathbf{x})}{\partial x_1}, \frac{\partial f(\mathbf{x})}{\partial x_2}, \ldots, \frac{\partial f(\mathbf{x})}{\partial x_n}\bigg]^\top $$

张量

张量是向量、矩阵在任意多维数上的推广,是是描述具有任意数量轴的 nn 维数组的通用方法。

其线性运算与向量、矩阵类似。

其按元素的乘法称为 Hadamard积 ,记作 \odot

数据操作

有如下方法生成张量:

torch.arange(12) # tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
torch.zeros((2, 3, 4))
'''
tensor([[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],

[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])
'''
torch.ones(2, 3, 4)
# ...
torch.randn(3, 4)
'''
tensor([[-0.0135, 0.0665, 0.0912, 0.3212],
[ 1.4653, 0.1843, -1.6995, -0.3036],
[ 1.7646, 1.0450, 0.2457, -0.7732]])
'''
torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])

张量可以方便地进行常见的运算:

x + y, x - y, x * y, x / y, x ** y
torch.exp(x)

若干个张量可以在某一个轴上进行连结,形成一个新的张量:

torch.cat((X, Y), dim=0)

逻辑运算符:

X == Y
'''
tensor([[False, True, False, True],
[False, False, False, False],
[False, False, False, False]])
'''

广播机制让形状不同的张量也可以进行按元素操作。

a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a, b
'''
(tensor([[0],
[1],
[2]]),
tensor([[0, 1]]))
'''

索引和切片:

X[-1], X[1:3] # 最后一个元素/1-2
X[1, 2] = 9 # 赋值
X[0:2, :] = 12 # 第0维上0-1的所有元素

为了节省内存空间,多使用索引操作。

Z[:] = X + Y

自动求导

x = torch.arange(4.0,requires_grad=True) # 注意必须使用浮点数
y = 2 * torch.dot(x,x) # 现在y是一个标量
y.backward() # 反向传播
x.grad # tensor([ 0., 4., 8., 12.])
x.grad == 4 * x # tensor([True, True, True, True])
x.grad.zero_() # 清除梯度
y = x.sum()
y.backward()
x.grad # tensor([1., 1., 1., 1.])

Python 进阶

迭代器

使用 iter() 函数从可迭代对象创建一个迭代器:

lst = [1, 2, 3]
it = iter(lst) # 返回 list_iterator 对象
print(next(it)) # 1
print(next(it)) # 2

iter() 也可以调用 无参可调用对象(如函数),直到返回的是“哨兵值”为止:

# 逐行读取文件直到空行
with open('data.txt') as f:
for line in iter(f.readline, ''):
print(line.strip())

使用 yield 关键字的函数叫做生成器,可以当作迭代器使用。

def count_up_to(n):
i = 1
while i <= n:
yield i
i += 1
for x in count_up_to(3):
print(x) # 1, 2, 3

列表推导式

列表推导式可以用一行代码简洁地创建列表:

[表达式 for 变量 in 可迭代对象]

如:

squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]

也可以嵌套循环:

pairs = [(x, y) for x in [1, 2] for y in [3, 4]] # [(1, 3), (1, 4), (2, 3), (2, 4)]

内置函数

  • enumerate() 在遍历可迭代对象(如列表、元组、字符串等)时,同时获取元素的索引和元素本身。
  • zip() 将多个可迭代对象“打包”成一个元组序列,按位置一一对应组合(如果不等长,将在最短的可迭代对象结束时停止)