最近着手学习深度学习,学习之余整理此学习笔记,以便后续复习,也希望能帮助到以后学习深度学习的同好。我观看的网课是李沐老师的动手学深度学习v2,文章也是主要在李沐老师的课程学习中所记。读者可以通过前文超链接直接进入李沐老师的B站主页观看原视频。
本文章主要用于个人学习,非商用,如有侵权还请海涵,并联系博主删除。
首先,我们要导入torch
import torch
张量表示一个数值组成的数组,这个数组可能有多个维度。
我们通过如下代码创建了一个长度为12的一维数组。其中,我们可以通过arange(n)
方法创建一个长度为n的一维数组,其各元素的值分别为0至n-1。
x = torch.arange(12)
有了数据,我们就可以对数据进行操作了。一些基础操作如下表所示:
操作 | 属性/方法 |
---|---|
形状尺寸 | shape |
元素个数 | numel() |
改变形状 | reshape() |
对于我们的张量x,我们可以通过如下代码进行操作。其中,x.reshape(3, 4)
将x改变为一个3行4列的二维张量,并且不改变各元素的值和顺序。
x.shape
x.numel()
x.reshape(3, 4)
我们可以使用全0、全1、其他常量或者从特定分布中随机采样的数字。
类型 | 方法 |
---|---|
全0 | zeros() |
全1 | ones() |
赋确定值 | tensor() |
举个例子:
torch.zeros(2, 3, 4) # 创建一个三维全0张量,各维度分布为2、3和4
torch.ones(2, 3, 4) # 创建一个三维全1张量
我们可以通过提供包含数值的Python列表(或嵌套列表)来为所需张量中的每个元素赋确定值。
下例中,我们创建了一个确定值的三维张量:
[ 1 2 3 4 2 3 4 1 4 3 2 1 ] \begin{bmatrix} 1 & 2 & 3 & 4 \\ 2 & 3 & 4 & 1 \\ 4 & 3 & 2 & 1 \end{bmatrix} ⎣ ⎡124233342411⎦ ⎤
torch.tensor([[1, 2, 3, 4], [2, 3, 4, 1], [4, 3, 2, 1]])
创建了张量之后,我们就可以进行一些常见的操作了。
类型 | 运算符 |
---|---|
加 | + |
减 | - |
乘 | * |
除 | / |
求幂 | ** |
指数运算 | exp() |
求和 | sum() |
如下例所示:
x = torch.tensor([1.0, 2, 3, 4])
y = torch.tensor([2, 2, 2, 2])
# 加减乘除和求幂
x + y, x - y, x * y, x / y, x ** y
# 指数运算
torch.exp(x)
# 求和
x.sum()
此外,我们还可以通过cat()
方法将多个张量连接在一起。当dim = 0
时,按列连接;当dim = 1
时,按行连接。
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)
我们还可以通过逻辑运算符来构建二元张量。例如,我们可以通过X == Y
来构建二元张量:
[ F a l s e T r u e F a l s e T r u e F a l s e F a l s e F a l s e F a l s e F a l s e F a l s e F a l s e F a l s e ] \begin{bmatrix} False & True & False & True \\ False & False & False & False \\ False & False & False & False \end{bmatrix} ⎣ ⎡FalseFalseFalseTrueFalseFalseFalseFalseFalseTrueFalseFalse⎦ ⎤
对于两个形状不同的张量,pytorch和numpy会将这个运算的参数自动扩张成相同的大小,来执行按元素操作。在不复制数据的情况下就能进行运算,以达到更高的效率。
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a + b
上例可看成如下运算:
[ 0 1 2 ] + [ 0 1 ] = [ 0 0 1 1 2 2 ] + [ 0 1 0 1 0 1 ] = [ 0 1 1 2 2 3 ] \begin{bmatrix} 0 \\ 1 \\ 2 \end{bmatrix} + \begin{bmatrix} 0 & 1 \\ \end{bmatrix} = \begin{bmatrix} 0 & 0\\ 1 & 1\\ 2 & 2 \end{bmatrix} + \begin{bmatrix} 0 & 1 \\ 0 & 1 \\ 0 & 1 \end{bmatrix} = \begin{bmatrix} 0 & 1 \\ 1 & 2 \\ 2 & 3 \end{bmatrix} ⎣ ⎡012⎦ ⎤+[01]=⎣ ⎡012012⎦ ⎤+⎣ ⎡000111⎦ ⎤=⎣ ⎡012123⎦ ⎤
我们可以用[-1]
选择最后一个元素,可以用[n1:n2]
选择第n1+1至第n2个元素。
X[-1] # 选择X的最后一个元素
X[1:3] # 选择X的第二个和第三个元素
此外,我们可以通过指定索引来将元素写入矩阵。
X[1, 2] = 9 # 将X的第二行第三列元素赋值为9
为多个元素赋相同的值,我们只需要索引所有元素,然后为他们赋值。
X[0:2, :] = 12 # 将X的第一二行元素赋值为12
如果矩阵过大,运行一些操作可能会导致为新结果分配内存。我们可通过一些办法执行原地操作。
# 运算前后Z的地址不变
Z = torch.zeros_like(Y)
Z[:] = X + Y
# 若后续运算中没有重复使用X,可以使用如下两种操作
X[:] = X + Y
X += Y
tensor类型的数据可以与numpy类型的数据相互转换。并且,大小为1的张量可以转换为Python标量。
A = X.numpy() # tensor -> numpy
B = torch.tensor(A) # numpy -> tensor
a = torch.tensor([1.2])
b = a.item() # tensor -> float
c = float(a) # tensor -> float
d = int(a) # tensor -> int
首先,创建一个人工数据集,并存储在csv文件中。
import os
os.makedirs(os.path.join('..', 'data'), exist_ok=True) # 创建目录
data_file = os.path.join('..', 'data', 'house_tiny.csv')# 文件路径
def write():
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')
然后,从csv文件中加载原始数据集,我们会得到如下所示的数据:
N u m R o o m s A l l e y P r i c e 0 N a N P a v e 127500 1 2.0 N a N 106000 2 4.0 N a N 178100 3 N a N N a N 140000 \begin{matrix} & NumRooms & Alley & Price \\ 0 & NaN & Pave & 127500 \\ 1 & 2.0 & NaN & 106000 \\ 2 & 4.0 & NaN & 178100 \\ 3 & NaN & NaN & 140000 \end{matrix} 0123NumRoomsNaN2.04.0NaNAlleyPaveNaNNaNNaNPrice127500106000178100140000
import pandas as pd
def read():
data = pd.read_csv(data_file)
其次,我们进行缺失数据处理:插值和删除。
我们先将加载的数据分为输入数据和输出数据。通过mean()
方法获得输入数据的平均值,再通过fillna()
方法将缺失的数据修改为之前获得的平均值。
# 前两列为输入数据 后一列为输出数据
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
inputs = inputs.fillna(inputs.mean())
如上操作可视为对输入数据进行了如下处理:
N u m R o o m s A l l e y 0 N a N P a v e 1 2.0 N a N 2 4.0 N a N 3 N a N N a N ⟶ N u m R o o m s A l l e y 0 3.0 P a v e 1 2.0 N a N 2 4.0 N a N 3 3.0 N a N \begin{matrix} & NumRooms & Alley\\ 0 & NaN & Pave \\ 1 & 2.0 & NaN \\ 2 & 4.0 & NaN \\ 3 & NaN & NaN \end{matrix} \longrightarrow \begin{matrix} & NumRooms & Alley\\ 0 & 3.0 & Pave \\ 1 & 2.0 & NaN \\ 2 & 4.0 & NaN \\ 3 & 3.0 & NaN \end{matrix} 0123NumRoomsNaN2.04.0NaNAlleyPaveNaNNaNNaN⟶0123NumRooms3.02.04.03.0AlleyPaveNaNNaNNaN
可以看到,第一列的缺失值已经被赋予了平均值。但第二列为字符类型,无法通过此方法为缺失值赋值。因此,对于输入数据中的类别值或离散值,我们将“NaN”视为一个类别。
inputs = pd.get_dummies(inputs, dummy_na=True)
如上操作可视为对输入数据进行了如下处理:
N u m R o o m s A l l e y 0 3.0 P a v e 1 2.0 N a N 2 4.0 N a N 3 3.0 N a N ⟶ N u m R o o m s A l l e y _ P a v e A l l e y _ n a n 0 3.0 1 0 1 2.0 0 1 2 4.0 0 1 3 3.0 0 1 \begin{matrix} & NumRooms & Alley\\ 0 & 3.0 & Pave \\ 1 & 2.0 & NaN \\ 2 & 4.0 & NaN \\ 3 & 3.0 & NaN \end{matrix} \longrightarrow \begin{matrix} & 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 \end{matrix} 0123NumRooms3.02.04.03.0AlleyPaveNaNNaNNaN⟶0123NumRooms3.02.04.03.0Alley_Pave1000Alley_nan0111
此时,inputs
和outputs
中的所有数据元素都是数值类型,它们可以转换为张量格式。
import torch
x, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
其中,输入数据最终为:
[ 3. 1. 0. 2. 0. 1. 4. 0. 1. 3. 0. 1. ] \begin{bmatrix} 3. & 1. & 0. \\ 2. & 0. & 1. \\ 4. & 0. & 1. \\ 3. & 0. & 1. \end{bmatrix} ⎣ ⎡3.2.4.3.1.0.0.0.0.1.1.1.⎦ ⎤
下一篇:【动手学深度学习v2】学习笔记02:线性代数、矩阵计算、自动求导