沐神《动手学深度学习》之2.3线性代数
一、标量、向量、矩阵和张量
1.1、标量
仅包含一个数值被称为标量,标量可以理解为日常生活中的数值,比如成绩,温度,价格等。
用代码实现如下:
import torch
x = torch.tensor(3.0)
y = torch.tensor(2.0)
#x,y都是标量
print(x + y, x - y, x * y, x / y, x / y, x % y)
#运行结果tensor(5.) tensor(1.) tensor(6.) tensor(1.5000) tensor(1.5000) tensor(1.)
1.2、向量
向量是由标量组成的列表,如你的身高、体重、血压等数字组成的身体数据向量。实现如下:
x = torch.arange(4)
#arange()方法可以理解为,生成一个长度为4的torch数组
1.3、矩阵
把全班人的身高体重等身体数据,汇聚成一张表,就成了矩阵。实现如下:
A = torch.arange(20).reshape(5, 4)
#reshape()函数是把长20的向量,重新塑造成为行数为5,列数为4的矩阵
print(A)
运行结果为:
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])
注意,这里多了个中括号,说明它是二维张量,上面的向量是一维张量
1.4、张量
仅身高是标量,身高加上体重成了向量,一个班级的身高体重成了矩阵,多个班级就是张量。
注意!不需要再往上扩展维度了,三维已经够用了。
X = torch.arange(24).reshape(2, 3, 4)
#这里的reshape是把向量重塑成为,通道数为2,三行四列的张量,也是两个矩阵。
print(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.1矩阵相加
import torch
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
A = torch.ones_like(A)
B = A + A
print(A)
print(B)
此处和书上 不同,为了方便观察,我用ones_like()函数,把A的所有元素变成了“1”。两个A矩阵相加,对应元素相加。
输出结果:
A:tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
B:tensor([[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.]])
2.2Hadamard积
C = A * A
print(C)
Hadamard积是矩阵对应元素相乘,因为A矩阵每个元素都是1,所以运行结果:
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
2.3张量+标量
D = A + 2
print(D)
张量加标量,把每个元素都加上标量,运行结果:
tensor([[3., 3., 3., 3.],
[3., 3., 3., 3.],
[3., 3., 3., 3.],
[3., 3., 3., 3.],
[3., 3., 3., 3.]])
2.4运算函数(降维)
2.4.1 降维运算
sum()函数可以把张量的所有值都加成一个值,输出成为一个标量。
sum()的衍生函数,sum_axis0()和sum_axis1(),分别是对矩阵的“行”和“列”求和,输出成为一个向量。
mean()函数是对张量求平均值。
numel()函数是求张量里标量的个数。
所以有 A.mean() == A.sum()/A.numel,既 张量的平均值 = 张量总值 / 张量中标量的个数。
2.4.2 非降维求和
sum_A = A.sum(axis=1, keepdims=True)
#这段代码在是每一行相加,最后得到一个保存维度的列张量 ,如果没有后面的keepdims=True,将会输出一个向量,也就是降维。
cum_A = A.cumsum(axis=0)表示沿某个轴计算A元素的累积总和。
print输出结果为:
tensor([[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.],
[4., 4., 4., 4.],
[5., 5., 5., 5.]])
2.5向量点积
torch.dot()
向量点积,就是对应标量相乘,然后将相乘的结果相加。
2.6矩阵-向量积
import torch
A = torch.arange(24).reshape(4,-1)
#创建一个矩阵,4行,列数填写-1让其自己计算
A += 1
print(A)
# 运算结果
# tensor([[ 1, 2, 3, 4, 5, 6],
# [ 7, 8, 9, 10, 11, 12],
# [13, 14, 15, 16, 17, 18],
# [19, 20, 21, 22, 23, 24]])
X = torch.arange(6)
X = torch.ones_like(X)
X += 1
#创建了一个长度为6,每个元素都是2的向量
print(X)
B = torch.mv(A, X)
print(B)
#tensor([ 42, 114, 186, 258])
观察上方代码,A和X的向量积的结果,42是A第一行每一个标量乘2然后相加的结果。这里注意,X的长度,要和A的每行的元素个数,也就是列数相等,才能进行乘法。
2.7矩阵-矩阵乘法
torch.mm()
在明白向量矩阵乘法之后,矩阵和矩阵乘法就简单了。
把第二个矩阵的列向量,看作为向量-矩阵乘法的向量,然后把所得的结果作为第一行。
所以,要求第一个矩阵的列数=第二个矩阵的行数。
import torch
A = torch.arange(6).reshape(2,-1)
A += 1
print(A)
#tensor([[1, 2, 3],
# [4, 5, 6]])
B = torch.arange(6).reshape(-1,2)
B = torch.ones_like(B)
print(B)
#tensor([[1, 1],
# [1, 1],
# [1, 1]])
print(torch.mm(A,B))
#tensor([[ 6, 6],
# [15, 15]])
现在我们验算一下,矩阵A的第一行与矩阵B第一列相乘,相加等于6,作为结果的第一行第一个元素。第二行与第一列相乘,结果作为第二行第一个元素。
一个2行3列的矩阵,乘一个3行2列的矩阵,所得的结果是一个2行2列的矩阵。
我们把数字进行一般化,一个a行b列的矩阵,乘一个b行c列的矩阵的结果,是一个a行c列的矩阵。
三、范数
向量的L1范数指的是,向量的各个标量元素的绝对值相加。
代码:torch.abs(A).sum()
向量的L2范数指的是,向量各元素平方和,然后开根号。
代码:torch.norm(A)
Frobenius范数满足向量范数的所有性质,它就像是矩阵形向量的L2范数。
3.1 范数的作用
范数(Norm)是衡量向量或矩阵 “大小” 的一种度量方式(例如向量的长度、矩阵的整体幅值)。
通过控制参数规模防止过拟合、定义损失函数衡量误差、稳定优化过程、量化特征相似性等。理解不同范数的特性(如 L1 的稀疏性、L2 的平滑性),是设计高效模型和训练策略的基础。
更多推荐



所有评论(0)