第2章 预备知识
2.1 数据操作
2.1.1 入门
导入的是torch而不是pytorch
import torch
一个数叫标量
一个轴叫向量
两个轴叫矩阵
arange
# 生成行向量 x = torch.arange(12) x
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
shape
x.shape #访问张量的形状
torch.Size([12])
numel()
#访问张量中元素的个数 x.numel()
12
reshape()
x = x.reshape(3,4) x
tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
torch.zeros()
torch.zeros((2,3,4)) #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()
torch.ones((2,3,4))
tensor([[[1., 1., 1., 1.], [1., 1., 1., 1.], [1., 1., 1., 1.]], [[1., 1., 1., 1.], [1., 1., 1., 1.], [1., 1., 1., 1.]]])
torch.randn()
生成元素服从均值为0,标准差为1的正态分布
torch.randn(3,4)
tensor([[ 0.7507, 0.6205, -1.2569, 0.6519], [-2.0297, 0.7286, -0.0741, -0.7660], [-1.5470, -1.2288, -0.3673, 0.3899]])
torch.tensor()
numpy转换为Tensor
torch.tensor([[2,1,4,3],[1,2,3,4],[4,3,2,1]])
tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
2.1.2 运算符
x = torch.tensor([1,2,4,8]) y = torch.tensor([2,2,2,2]) x+y, x-y, x*y, x/y, x**y
(tensor([ 3, 4, 6, 10]), tensor([-1, 0, 2, 6]), tensor([ 2, 4, 8, 16]), tensor([0.5000, 1.0000, 2.0000, 4.0000]), tensor([ 1, 4, 16, 64]))
x = torch.tensor([1.0,2,4,8]) y = torch.tensor([2,2,2,2]) x+y, x-y, x*y, x/y, x**y
(tensor([ 3., 4., 6., 10.]), tensor([-1., 0., 2., 6.]), tensor([ 2., 4., 8., 16.]), tensor([0.5000, 1.0000, 2.0000, 4.0000]), tensor([ 1., 4., 16., 64.]))
torch.exp()
torch.exp(x)
tensor([2.7183e+00, 7.3891e+00, 5.4598e+01, 2.9810e+03])
torch.cat()
X = torch.arange(12, dtype=torch.float32).reshape((3,4)) Y = torch.tensor([[2.0,1,4,3],[1,2,3,4],[4,3,2,1]]) torch.cat((X,Y), dim=0), torch.cat((X,Y), dim=1) #dim=1按列
(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.]]), 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.]]))
X == Y
tensor([[False, True, False, True], [False, False, False, False], [False, False, False, False]])
X.sum()
X.sum()
tensor(66.)
a = torch.arange(3).reshape((3,1)) b = torch.arange(2).reshape((1,2)) a,b
(tensor([[0], [1], [2]]), tensor([[0, 1]]))
2.1.3 广播机制
#a为列向量,b为行向量 a+b #广播机制
tensor([[0, 1], [1, 2], [2, 3]])
2.1.4 索引和切片
print(X) print(X[-1]) #访问最后一行 print(X[1:3]) #访问索引为1,2的行
tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.]]) tensor([ 8., 9., 10., 11.]) tensor([[ 4., 5., 6., 7.], [ 8., 9., 10., 11.]])
X[1,2] = 9 # 赋值 X
tensor([[ 0., 1., 2., 3.], [ 4., 5., 9., 7.], [ 8., 9., 10., 11.]])
X[0:2, :] = 12 X
tensor([[12., 12., 12., 12.], [12., 12., 12., 12.], [ 8., 9., 10., 11.]])
2.1.5 节省内存
before = id(Y) Y = Y+X id(Y) == before #运行一些操作可能导致为新结果分配内存
False
zeros_like(Y)即形状与Y一致的全零矩阵
Z = torch.zeros_like(Y) print(id(Z)) Z[:] = X+Y #原地操作 print(id(Z))
2435091263384 2435091263384
before = id(X) X += Y #不同于赋值 id(X) == before
True
得出结论:X[:]=X+Y或X+=Y可以减少操作的内存开销
2.1.6 array和Tensor类型相互转换
A = X.numpy() B = torch.tensor(A) type(A), type(B)
(numpy.ndarray, torch.Tensor)
2.2 数据预处理
2.2.1. 读取数据集
先生成一个数据集:其中每行描述了房间数量(“NumRooms”)、巷子类型
(“Alley”)和房屋价格(“Price”)。
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')
再读取数据集
# 如果没有安装pandas,只需取消对以下行的注释来安装pandas # !pip install pandas import pandas as pd data = pd.read_csv(data_file) print(data)
NumRooms Alley Price 0 NaN Pave 127500 1 2.0 NaN 106000 2 4.0 NaN 178100 3 NaN NaN 140000
2.2.2. 处理缺失值
#划分输入输出 inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2] #对输出进行预处理 inputs = inputs.fillna(inputs.mean()) print(inputs)
NumRooms Alley 0 3.0 Pave 1 2.0 NaN 2 4.0 NaN 3 3.0 NaN
对于inputs中的类别值或离散值,我们将“NaN”视为一个类别。
inputs = pd.get_dummies(inputs, dummy_na=True) print(inputs)
NumRooms Alley_Pave Alley_nan 0 3.0 1 0 1 2.0 0 1 2 4.0 0 1 3 3.0 0 1
可见输入为3*4矩阵
上面数据都是array类型,用pandas和numpy处理;下面转换成Tensor
2.2.3. 转换为张量格式
X:34
y:41
import torch X, y = torch.tensor(inputs.values), torch.tensor(outputs.values) X, y
(tensor([[3., 1., 0.], [2., 0., 1.], [4., 0., 1.], [3., 0., 1.]], dtype=torch.float64), tensor([127500, 106000, 178100, 140000]))
2.3 线性代数
2.3.1 标量
标量由只有一个元素的张量表示
import torch x = torch.tensor(3.0) y = torch.tensor(2.0) x + y, x * y, x / y, x**y
(tensor(5.), tensor(6.), tensor(1.5000), tensor(9.))
2.3.2 向量
向量可以视为由标量值组成的列表
x = torch.arange(4) x
tensor([0, 1, 2, 3])
大量文献认为列向量是向量的默认方向,这里也是默认此
x[3]
tensor(3)
2.3.2.1. 长度、维度和形状
向量只是一个数组,数组有长度,没向量也如此
len(x)
4
当用张量表示一个向量(只有一个轴)时,我们也可以通过.shape属性访问向量的长度。
x.shape
torch.Size([4])
2.3.3 矩阵
A = torch.arange(20).reshape(5, 4) A
tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]])
转置
A.T
tensor([[ 0, 4, 8, 12, 16], [ 1, 5, 9, 13, 17], [ 2, 6, 10, 14, 18], [ 3, 7, 11, 15, 19]])
对称矩阵
B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]]) B
tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
B == B.T
tensor([[True, True, True], [True, True, True], [True, True, True]])
2.3.4 张量
向量是标量的推广,矩阵是向量的推广
向量是一阶张量,矩阵是二阶张量
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]]])
2.3.5 张量算法的基本性质
A = torch.arange(20, dtype=torch.float32).reshape(5, 4) B = A.clone() # 通过分配新内存,将A的一个副本分配给B A, A + B
(tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [12., 13., 14., 15.], [16., 17., 18., 19.]]), tensor([[ 0., 2., 4., 6.], [ 8., 10., 12., 14.], [16., 18., 20., 22.], [24., 26., 28., 30.], [32., 34., 36., 38.]]))
A * B #点乘 对应元素相乘
tensor([[ 0., 1., 4., 9.], [ 16., 25., 36., 49.], [ 64., 81., 100., 121.], [144., 169., 196., 225.], [256., 289., 324., 361.]])
a = 2 X = torch.arange(24).reshape(2, 3, 4) a + X, (a * X).shape
(tensor([[[ 2, 3, 4, 5], [ 6, 7, 8, 9], [10, 11, 12, 13]], [[14, 15, 16, 17], [18, 19, 20, 21], [22, 23, 24, 25]]]), torch.Size([2, 3, 4]))
2.3.6. 降维
一阶张量求和
x = torch.arange(4, dtype=torch.float32) x, x.sum()
(tensor([0., 1., 2., 3.]), tensor(6.))
二阶张量求和
A
tensor([[ 0., 1., 2., 3.], [ 4., 5., 6., 7.], [ 8., 9., 10., 11.], [12., 13., 14., 15.], [16., 17., 18., 19.]])
A.shape, A.sum()
(torch.Size([5, 4]), tensor(190.))
对每一列求和
A_sum_axis0 = A.sum(axis=0) A_sum_axis0, A_sum_axis0.shape
(tensor([40., 45., 50., 55.]), torch.Size([4]))
对每一行求和
A_sum_axis1 = A.sum(axis=1) A_sum_axis1, A_sum_axis1.shape
(tensor([ 6., 22., 38., 54., 70.]), torch.Size([5]))
对整个矩阵元素求和
A.sum(axis=[0, 1]) # SameasA.sum()
tensor(190.)
A.mean()
整个矩阵求均值
A.mean(), A.sum() / A.numel()
(tensor(9.5000), tensor(9.5000))
对每一列求均值
A.mean(axis=0), A.sum(axis=0) / A.shape[0]
(tensor([ 8., 9., 10., 11.]), tensor([ 8., 9., 10., 11.]))