数据操作
张量(tensor):𝑛维数组
张量表示由一个数值组成的数组,这个数组可能有多个维度。 具有一个轴的张量对应数学上的向量(vector); 具有两个轴的张量对应数学上的矩阵(matrix); 具有两个轴以上的张量没有特殊的数学名称。
import torchx = torch.arange(12)X = x.reshape(3, 4)torch.randn(3, 4)
张量连结(concatenate)在一起], 把它们端对端地叠起来形成一个更大的张量。 我们只需要提供张量列表,并给出沿哪个轴连结。 下面的例子分别演示了当我们沿行(轴-0,形状的第一个元素) 和按列(轴-1,形状的第二个元素)连结两个矩阵时,会发生什么情况。 我们可以看到,第一个输出张量的轴-0长度(6)是两个输入张量轴-0长度的总和(3+3); 第二个输出张量的轴-1长度(8)是两个输入张量轴-1长度的总和(4+4)。
X = torch.arange(12, dtype=torch.float32).reshape((3,4))tensor([[ 0., 1., 2., 3.],[ 4., 5., 6., 7.],[ 8., 9., 10., 11.]])Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])tensor([[2., 1., 4., 3.],[1., 2., 3., 4.],[4., 3., 2., 1.]])torch.cat((X, Y), dim=0)tensor([[ 0., 1., 2., 3.],[ 4., 5., 6., 7.],[ 8., 9., 10., 11.],[ 2., 1., 4., 3.],[ 1., 2., 3., 4.],[ 4., 3., 2., 1.]])torch.cat((X, Y), dim=1)tensor([[ 0., 1., 2., 3., 2., 1., 4., 3.],[ 4., 5., 6., 7., 1., 2., 3., 4.],[ 8., 9., 10., 11., 4., 3., 2., 1.]])
数据预处理
写入数据集
import os
os.makedirs(os.path.join('..', 'data'), exist_ok=True)
data_file = os.path.join('..', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:
f.write('NumRooms,Alley,Price\n') # 列名
f.write('NA,Pave,127500\n') # 每行表示一个数据样本
f.write('2,NA,106000\n')
f.write('4,NA,178100\n')
f.write('NA,NA,140000\n')
读取数据集
import pandas as pd
data = pd.read_csv(data_file)
print(data)
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
# 处理缺失值
inputs = inputs.fillna(inputs.mean())
print(inputs)
inputs = pd.get_dummies(inputs, dummy_na=True)
print(inputs)
转为张量格式
import torch
X, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
X, y
线性代数
标量
仅包含一个数值的叫标量(scalar)
import torch
x = torch.tensor(3.0)
y = torch.tensor(2.0)
x + y, x * y, x / y, x**y
向量
将向量视为标量值组成的列表。 我们将这些标量值称为向量的元素(element)或分量(component)
x = torch.arange(4)
x
长度、维度和形状
向量只是一个数字数组,就像每个数组都有一个长度一样,每个向量也是如此。 在数学表示法中,如果我们想说一个向量𝐱由𝑛个实值标量组成, 我们可以将其表示为。 向量的长度通常称为向量的维度(dimension)。
len(x)
当用张量表示一个向量(只有一个轴)时,我们也可以通过.shape属性访问向量的长度。 形状(shape)是一个元素组,列出了张量沿每个轴的长度(维数)。 对于只有一个轴的张量,形状只有一个元素。
x.shape
矩阵
矩阵,我们通常用粗体、大写字母来表示 (例如,𝐗、𝐘和𝐙), 在代码中表示为具有两个轴的张量。
在数学表示法中,我们使用 来表示矩阵𝐀,其由𝑚行和𝑛列的实值标量组成。
A = torch.arange(20).reshape(5, 4)
A
转置
当我们交换矩阵的行和列时,结果称为矩阵的转置(transpose)
A.T
张量
张量为我们提供了描述具有任意数量轴的𝑛n维数组的通用方法。 例如,向量是一阶张量,矩阵是二阶张量。 张量用特殊字体的大写字母表示(例如,𝖷、𝖸和𝖹)
X = torch.arange(24).reshape(2, 3, 4)
X
tensor([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
降维
x = torch.arange(4, dtype=torch.float32)
x, x.sum()
为了通过求和所有行的元素来降维(轴0),我们可以在调用函数时指定axis=0。 由于输入矩阵沿0轴降维以生成输出向量,因此输入轴0的维数在输出形状中消失。
A_sum_axis0 = A.sum(axis=0)
A_sum_axis0, A_sum_axis0.shape
(tensor([40., 45., 50., 55.]), torch.Size([4]))
指定axis=1将通过汇总所有列的元素降维(轴1)。因此,输入轴1的维数在输出形状中消失。
A_sum_axis1 = A.sum(axis=1)
A_sum_axis1, A_sum_axis1.shape
(tensor([ 6., 22., 38., 54., 70.]), torch.Size([5]))
非降维求和
sum_A = A.sum(axis=1, keepdims=True)
sum_A
tensor([[ 6.],
[22.],
[38.],
[54.],
[70.]])
点积
y = torch.ones(4, dtype = torch.float32)
x, y, torch.dot(x, y)
范数
一个向量的范数(norm)告诉我们一个向量有多大。 这里考虑的大小(size)概念不涉及维度,而是分量的大小。
L2
欧几里得距离是一个𝐿2范数: 假设𝑛维向量𝐱中的元素是𝑥1,…,𝑥𝑛,其𝐿2范数是向量元素平方和的平方根:
其中,在𝐿2范数中常常省略下标2,也就是说‖𝐱‖等同于‖𝐱‖2。 在代码中,我们可以按如下方式计算向量的𝐿2范数。
u = torch.tensor([3.0, -4.0])
torch.norm(u)
tensor(5.)
L1
𝐿1范数表示为向量元素的绝对值之和:
与𝐿2范数相比,𝐿1范数受异常值的影响较小。 为了计算𝐿1范数,我们将绝对值函数和按元素求和组合起来。
torch.abs(u).sum()
tensor(7.)
微积分
梯度
设函数的输入是 一个𝑛维向量
,并且输出是一个标量。 函数𝑓(𝐱)相对于𝐱的梯度(gradient)是一个包含𝑛个偏导数的向量:
自动微分
深度学习框架通过自动计算导数,即自动微分(automatic differentiation)来加快求导。 实际中,根据我们设计的模型,系统会构建一个计算图(computational graph), 来跟踪计算是哪些数据通过哪些操作组合起来产生输出。 自动微分使系统能够随后反向传播梯度。 这里,反向传播(backpropagate)意味着跟踪整个计算图,填充关于每个参数的偏导数。
概率
贝叶斯定理
Bayes定理(Bayes’ theorem)。 根据乘法法则(multiplication rule )可得到𝑃(𝐴,𝐵)=𝑃(𝐵∣𝐴)𝑃(𝐴)。 根据对称性,可得𝑃(𝐴,𝐵)=𝑃(𝐴∣𝐵)𝑃(𝐵)。 假设𝑃(𝐵)>0,求解其中一个条件变量,我们得到
