一、标量、向量、矩阵和张量

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 的平滑性),是设计高效模型和训练策略的基础。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐