线性代数
标量:只有一个元素的张量表示
import torch
x=torch.tensor([3.0])
y=torch.tensor([2.0])
x+y, x-y, x*y, x/y, x**y
(tensor([5.]), tensor([1.]), tensor([6.]), tensor([1.5000]), tensor([9.]))
向量:标量组成的列表
x=torch.arange(4)
x
tensor([0, 1, 2, 3])
通过张量的索引来访问任一元素
x[3]
tensor(3)
张量的长度
len(x)
4
只有一个轴的张量,形状只有一个元素
x.shape # tensor([0, 1, 2, 3])
torch.Size([4])
指定两个分量m和n,创建一个形状为m*n的矩阵
A=torch.arange(20).reshape(5,4) # 20个元素,5行4列的矩阵,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]])
对称矩阵:A=A的转置
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]])
向量是标量的推广,矩阵是向量的推广,可以构建更多轴的数据结构
x=torch.arange(24).reshape(2,3,4) # 三维张量中,有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]]])
给定具有相同形状的任何两个张量,任何按元素二元运算的结果都是相同形状的张量
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)
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]]])
a+X,(a*X).shape # X的所有元素都+a
(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]))
计算元素的和
x=torch.arange(4,dtype=torch.float32)
x, x.sum() # sum=0+1+2+3
(tensor([0., 1., 2., 3.]), tensor(6.))
表示任意形状张量的元素和
A.shape,A.sum()
(torch.Size([5, 4]), tensor(190.))
A=torch.arange(20*2,dtype=torch.float32).reshape(2,5,4)
A,A.shape,A.sum()
(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.],
[24., 25., 26., 27.],
[28., 29., 30., 31.],
[32., 33., 34., 35.],
[36., 37., 38., 39.]]]),
torch.Size([2, 5, 4]),
tensor(780.))
张量中的维度究竟是什么?
张量的阶数有时也称维度,或者轴axis。
# 0维
tensor0=torch.tensor(1)
print(tensor0),tensor0.size()
tensor(1)
(None, torch.Size([]))
# 1维: 1行数组
tensor1=torch.tensor([1,2,3])
print(tensor1),tensor1.size()
tensor([1, 2, 3])
(None, torch.Size([3]))
# 2维:1个平面矩阵 = 2个1维数组堆叠
tensor2=torch.tensor([[1,2,3],[4,5,6]])
print(tensor2),tensor2.size()
tensor([[1, 2, 3],
[4, 5, 6]])
(None, torch.Size([2, 3]))
# 3维:一个立体矩阵 = 2个平面矩阵堆叠
import torch
tensor3=torch.tensor([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
print(tensor3),tensor3.size()
tensor([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
(None, torch.Size([2, 2, 3]))
# 4维:多个三维立体矩阵的堆叠
tensor4=torch.tensor([[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]],
[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]])
print(tensor4),tensor4.size()
tensor([[[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]],
[[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]]])
(None, torch.Size([2, 2, 2, 3]))
# 5维:多个四维立体矩阵的堆叠
tensor5=torch.tensor([[[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]],[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]],
[[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]],[[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]]])
print(tensor5),tensor5.size()
tensor([[[[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]],
[[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]]],
[[[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]],
[[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]]]])
(None, torch.Size([2, 2, 2, 2, 3]))
总结:判断张量tensor的维度,可以直接看最外层[]的数量。
tensor的轴Axis、阶数Rank、形状Shape
Rank:给定张量存在的维数。
轴Axis:n阶=n维=n轴
t1=torch.tensor([[1,2,3],[4,5,6],[7,8,9]])
t1,t1.size()
(tensor([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]),
torch.Size([3, 3]))
# axis=0,第一轴:沿第一个轴的每个元素都是一个数组:
t1[0],t1[1],t1[2]
(tensor([1, 2, 3]), tensor([4, 5, 6]), tensor([7, 8, 9]))
# axis=1,第二轴:沿第二个轴的每个元素都是一个数字:
t1[0][0],t1[1][0],t1[2][0]
(tensor(1), tensor(4), tensor(7))
t1[0][1],t1[1][1],t1[2][1]
(tensor(2), tensor(5), tensor(8))
t1[0][2],t1[1][2],t1[2][2]
(tensor(3), tensor(6), tensor(9))
张量的形状由轴长决定。
t1.size() # 张量的形状告诉我们,这个2阶张量的每个轴的长度都是3,这意味着我们有三个沿着每个轴可用的索引
torch.Size([3, 3])
指定求和汇总张量的轴
A=torch.arange(20,dtype=torch.float32).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_sum_axis0=A.sum(axis=0)
A_sum_axis0,A_sum_axis0.shape
# axis=0是行
# 将每一行进行叠加,即:
#[1,2,3,4]+[4,5,6,7]+[8,9,10,11]+[12,13,14,15]+[16,17,18,19]=[40,45,50,55]
(tensor([40., 45., 50., 55.]), torch.Size([4]))
A_sum_axis1=A.sum(axis=1)
A_sum_axis1,A_sum_axis1.shape
# axis=1是列
# 将每一列进行叠加,即:
#[ [ [ [ [
# 0, + 1, + 2, + 3 = 6
# 4, + 5, + 6, + 7 = 22
# 8, + 9, + 10, + 11 = 38
# 12, + 13, + 14, + 15 = 54
# 16, + 17, + 18, + 19 = 70
# ] ] ] ] ]
(tensor([ 6., 22., 38., 54., 70.]), torch.Size([5]))
Shape[5,4]:
axis0:[ ,4]
axis1:[5, ]
Shape[2,5,4]
axis1:[2, ,4]
axis2:[2,5, ]
axis[1,2]:[2, ,] #轴1和2求和,则去掉5和4
import torch
a=torch.ones(2,5,4)
a,a.shape
(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.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]]),
torch.Size([2, 5, 4]))
a.sum(axis=0),a.sum(axis=0).shape
(tensor([[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.]]),
torch.Size([5, 4]))
a.sum(axis=1),a.sum(axis=1).shape
(tensor([[5., 5., 5., 5.],
[5., 5., 5., 5.]]),
torch.Size([2, 4]))
a.sum(axis=2),a.sum(axis=2).shape
(tensor([[4., 4., 4., 4., 4.],
[4., 4., 4., 4., 4.]]),
torch.Size([2, 5]))
当keepdims=True, Shape[2,5,4]: Shape[x,y,z]:
axis0:[1,5,4] axis0: [1,y,z]
axis1:[2,1,4] axis1: [x,1,z]
axis2:[2,5,1] axis2: [x,y,1]
axis[0,1]:[1,1,4] #轴1和2求和,则5和4都变成1 axis[0,1]: [1,1,z]
axis[0,2]:[1,5,1] axis[0,2]: [1,y,1]
axis[1,2]:[2,1,1] axis[1,2]: [x,1,1]
a.sum(axis=0,keepdims=True),a.sum(axis=0,keepdims=True).shape
(tensor([[[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.],
[2., 2., 2., 2.]]]),
torch.Size([1, 5, 4]))
a.sum(axis=1,keepdims=True),a.sum(axis=1,keepdims=True).shape
(tensor([[[5., 5., 5., 5.]],
[[5., 5., 5., 5.]]]),
torch.Size([2, 1, 4]))
a.sum(axis=2,keepdims=True),a.sum(axis=2,keepdims=True).shape
(tensor([[[4.],
[4.],
[4.],
[4.],
[4.]],
[[4.],
[4.],
[4.],
[4.],
[4.]]]),
torch.Size([2, 5, 1]))
a.sum(axis=[0,1],keepdims=True),a.sum(axis=[0,1],keepdims=True).shape
(tensor([[[10., 10., 10., 10.]]]), torch.Size([1, 1, 4]))
a.sum(axis=[0,2],keepdims=True),a.sum(axis=[0,2],keepdims=True).shape
(tensor([[[8.],
[8.],
[8.],
[8.],
[8.]]]),
torch.Size([1, 5, 1]))
a.sum(axis=[1,2],keepdims=True),a.sum(axis=[1,2],keepdims=True).shape
(tensor([[[20.]],
[[20.]]]),
torch.Size([2, 1, 1]))
平均值(mean或者average)
A.mean(),A.sum()/A.numel() # 此处是numL,不是num1,不是数字1
# numl是元素的个数,必须得是浮点数才可以求均值
(tensor(9.5000), tensor(9.5000))
A.mean(axis=0),A.sum(axis=0)/A.shape[0] # 求轴0的均值
(tensor([ 8., 9., 10., 11.]), tensor([ 8., 9., 10., 11.]))
计算总和或均值的时候,保持轴数不变
A=torch.arange(20,dtype=torch.float32).reshape(5,4)
sum_A=A.sum(axis=1,keepdims=True) # 按维度求和时,该维度会被去掉,即三维的矩阵,按一个维度求和,会变成二维矩阵
sum_A # 不降低维度就是令“所要求和的维度”个数变为1
tensor([[ 6.],
[22.],
[38.],
[54.],
[70.]])
通过广播,将A/sum_A
A/sum_A # 如果没有keepdims,sum_A那将少1个维度
tensor([[0.0000, 0.1667, 0.3333, 0.5000],
[0.1818, 0.2273, 0.2727, 0.3182],
[0.2105, 0.2368, 0.2632, 0.2895],
[0.2222, 0.2407, 0.2593, 0.2778],
[0.2286, 0.2429, 0.2571, 0.2714]])
计算A元素在某个轴的和
A=torch.arange(20,dtype=torch.float32).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.cumsum(axis=0)
tensor([[ 0., 1., 2., 3.],
[ 4., 6., 8., 10.],
[12., 15., 18., 21.],
[24., 28., 32., 36.],
[40., 45., 50., 55.]])
第0行:0+0, 1+0, 2+0, 3+0
第1行:4+0, 5+1, 6+2, 7+3
第2行:8+4+0, 9+5+1, 10+6+2, 11+7+3
第3行:12+8+4+0, 13+9+5+1, 14+10+6+2, 15+11+7+3
第4行:16+12+8+4+0,17+13+9+5+1,18+14+10+6+2,19+15+11+7+3
点积:相同位置的按元素乘积的和
x=torch.arange(4,dtype=torch.float32)
y=torch.ones(4,dtype=torch.float32)
x,y
(tensor([0., 1., 2., 3.]), tensor([1., 1., 1., 1.]))
torch.dot(x,y) # 0*1+1*1+2*1+3*1=6
tensor(6.)
点积:也可以通过执行按元素乘法,再求和
torch.sum(x*y) # same
tensor(6.)
A是一个m * n的矩阵,x是一个m * 1的矩阵,
矩阵向量积Ax是一个长度为m的列向量,其第i个元素是a的第i行和x点积的乘法
A.shape,x.shape,torch.mv(A,x) # mv():表示A矩阵 * x向量
# A是一个5*4的矩阵,x是长度为4的向量,结果是长为5的向量
(torch.Size([5, 4]), torch.Size([4]), tensor([ 14., 38., 62., 86., 110.]))
矩阵和矩阵的乘法看作是简单执行m次矩阵-向量积,结果拼在一起,形成n * m矩阵
B=torch.ones(4,3)
torch.mm(A, B) # mm(): A矩阵 * B矩阵
tensor([[ 6., 6., 6.],
[22., 22., 22.],
[38., 38., 38.],
[54., 54., 54.],
[70., 70., 70.]])
L2范数:向量或者矩阵的长度,是向量元素平方和的平方根(欧式距离度量)
u=torch.tensor([3.0,-4.0]) # (3^2+(-4)^2)^0.5=5
torch.norm(u)
tensor(5.)
L1范数:向量元素的绝对值之和
torch.abs(u).sum() # \3\+\-4\=7
tensor(7.)
弗罗贝尼乌斯范数:矩阵元素的平方和的平方根(把矩阵拉成向量再计算,L2是只用于向量)
torch.norm(torch.ones((4,9)))
tensor(6.)