矩阵
- 矩阵初始化
- 矩阵元素运算
- 矩阵的乘法
- 矩阵的转置
- 矩阵对应列行的最大值,最小值,和
- 矩阵的其他操作:行列数、切片、复制、非0元素的下标
- 矩阵的行列式
- 矩阵的逆和伪逆
- 矩阵的对称
- 矩阵的秩、迹
- 矩阵求解
- 矩阵的特征值与特征向量(EVD)
矩阵
1. 矩阵初始化
Tensor的初始化
# 全零矩阵
In [1]: import torch
In [2]: myZero = torch.zeros(3,3)
In [3]: myZero
Out[3]:
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
In [4]: type(myZero)
Out[4]: torch.Tensor
In [5]: myZero.dtype
Out[5]: torch.float32
# 全一矩阵
In [6]: myOnes = torch.ones(3,3)
In [8]: myOnes
Out[8]:
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
# 单位矩阵
In [9]: myEye = torch.eye(5)
In [10]: myEye
Out[10]:
tensor([[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]])
# 对称矩阵
In [11]: a1 = [1,2,3,4,5]
In [13]: a1 = torch.tensor(a1)
In [14]: a1
Out[14]: tensor([1, 2, 3, 4, 5])
In [15]: myDiag = torch.diag(a1)
In [16]: myDiag
Out[16]:
tensor([[1, 0, 0, 0, 0],
[0, 2, 0, 0, 0],
[0, 0, 3, 0, 0],
[0, 0, 0, 4, 0],
[0, 0, 0, 0, 5]])
# 随机矩阵
In [17]: myRand = torch.rand(3,3)
In [18]: myRand
Out[18]:
tensor([[0.9588, 0.0139, 0.2303],
[0.4332, 0.1916, 0.4152],
[0.4848, 0.3361, 0.9799]])
- 直接创建tensor
In [19]: a = torch.tensor([[1,2,3],[4,5,6]])
In [20]: a
Out[20]:
tensor([[1, 2, 3],
[4, 5, 6]])
- 通过from_numpy() 函数将ndarray数据类型转化成矩阵(tensor)
In [21]: import numpy as np
In [22]: a = np.arange(12).reshape(3,4)
In [23]: b = torch.from_numpy(a)
In [24]: b
Out[24]:
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]], dtype=torch.int32)
2. 矩阵元素运算
矩阵的元素运算是指矩阵在元素级别的加、减、乘、除运算。
(1)元素相加和相减。
条件:矩阵的行数和列数必须相同。
数学公式:
In [27]: myOnes = torch.ones(4,4)
In [28]: myOnes
Out[28]:
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
In [29]: myEye = torch.eye(4)
In [30]: myEye
Out[30]:
tensor([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
In [31]: myOnes + myEye
Out[31]:
tensor([[2., 1., 1., 1.],
[1., 2., 1., 1.],
[1., 1., 2., 1.],
[1., 1., 1., 2.]])
In [32]: myOnes - myEye
Out[32]:
tensor([[0., 1., 1., 1.],
[1., 0., 1., 1.],
[1., 1., 0., 1.],
[1., 1., 1., 0.]])
(2)矩阵数乘:一个数乘以一个矩阵。
数学公式:
In [37]: b
Out[37]:
tensor([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]], dtype=torch.int32)
In [39]: b*10
Out[39]:
tensor([[ 0, 10, 20, 30],
[ 40, 50, 60, 70],
[ 80, 90, 100, 110]], dtype=torch.int32)
(3)矩阵所有元素求和。
数学公式:
In [40]: torch.sum(b)
Out[40]: tensor(66)
(4)矩阵所有元素之积
数学公式:
In [47]: a = torch.arange(4).reshape(2,2)+1
In [48]: a
Out[48]:
tensor([[1, 2],
[3, 4]])
In [49]: torch.prod(a)
Out[49]: tensor(24)
(5)矩阵各元素的n次幂:n=3。
数学公式:
In [50]: a
Out[50]:
tensor([[1, 2],
[3, 4]])
In [52]: torch.pow(a,3)
Out[52]:
tensor([[ 1, 8],
[27, 64]])
3. 矩阵的乘法
(1)矩阵各元素的积:矩阵的点乘同维对应元素的相乘。当矩阵的维度不同时,会根据一定的广播规则将维数扩充到一致的形式。
数学公式:
In [64]: a
Out[64]:
tensor([[1, 2],
[3, 4]])
In [65]: b
Out[65]:
tensor([[0, 1],
[2, 3]])
In [66]: a*b
Out[66]:
tensor([[ 0, 2],
[ 6, 12]])
(2)矩阵内积
数学公式:
In [68]: a
Out[68]:
tensor([[1, 2],
[3, 4]])
In [69]: b
Out[69]:
tensor([[0, 1, 2],
[3, 4, 5]])
In [70]: torch.dot(a,b)
Traceback (most recent call last):
File "<ipython-input-70-5682e150e844>", line 1, in <module>
torch.dot(a,b)
# 报错,只允许一维的tensor,只适合向量内积
RuntimeError: 1D tensors expected, got 2D, 2D tensors at C:\w\1\s\tmp_conda_3.6_045031\conda\conda-bld\pytorch_1565412750030\work\aten\src\TH/generic/THTensorEvenMoreMath.cpp:723
#官方提示此功能不广播。有关广播的矩阵乘法,请参见torch.matmul()
In [71]: torch.mm(a,b)
Out[71]:
tensor([[ 6, 9, 12],
[12, 19, 26]])
In [72]: torch.matmul(a,b)
Out[72]:
tensor([[ 6, 9, 12],
[12, 19, 26]])
(3)向量内积、外积
向量内积:
向量外积:
In [73]: a1 = torch.tensor([2,1,0])
In [74]: a2 = torch.tensor([-1,2,1])
In [75]: a1
Out[75]: tensor([2, 1, 0])
In [76]: a2
Out[76]: tensor([-1, 2, 1])
In [77]: torch.dot(a1,a2)
Out[77]: tensor(0)
In [78]: torch.outer(a1,a2)
Traceback (most recent call last):
# 在pytorch中没有outer函数
File "<ipython-input-78-cc115fea0111>", line 1, in <module>
torch.outer(a1,a2)
AttributeError: module 'torch' has no attribute 'outer'
# 解决办法,先将一维的向量转换为二维,再利用矩阵内积方法计算
In [86]: a1 = a1.reshape(1,3)
In [87]: a2 = a2.reshape(1,3)
# 转置
In [88]: a1.T
Out[88]:
tensor([[2],
[1],
[0]])
In [89]: torch.mm(a1.T,a2)
Out[89]:
tensor([[-2, 4, 2],
[-1, 2, 1],
[ 0, 0, 0]])
(4)向量叉乘(叉积):运算结果是一个向量而不是一个标量。并且两个向量的叉积与这两个向量组成的坐标平面垂直。
数学公式:
其中
根据i、j、k间关系,有:
例1、已知,a =(2,1,0),b =(-1,2,1),试求(1)(2)
解:(1) =(1,-2,5):(2) =(-1,2,5)
In [79]: torch.cross(a1,a2)
Out[79]: tensor([ 1, -2, 5])
In [80]: torch.cross(a2,a1)
Out[80]: tensor([-1, 2, -5])
4. 矩阵的转置
数学公式:
In [90]: a
Out[90]:
tensor([[1, 2],
[3, 4]])
In [91]: a.T
Out[91]:
tensor([[1, 3],
[2, 4]])
In [92]: a.transpose(1,0)
Out[92]:
tensor([[1, 3],
[2, 4]])
5. 矩阵对应列行的最大值,最小值,和
In [99]: b
Out[99]:
tensor([[0, 1, 2],
[3, 4, 5]])
# 计算矩阵中最大值的对应索引
In [100]: b.argmax()
Out[100]: tensor(5)
# 计算矩阵列中最大值对应的行索引
In [101]: b.argmax(axis=0)
Out[101]: tensor([1, 1, 1])
# 计算矩阵行中最大值对应的列索引
In [102]: b.argmax(axis=1)
Out[102]: tensor([2, 2])
# 矩阵中的最大值
In [103]: b.max()
Out[103]: tensor(5)
# 矩阵列中的最小值
In [104]: b.min()
Out[104]: tensor(0)
# 矩阵列求和
In [105]: b.sum(axis=0)
Out[105]: tensor([3, 5, 7])
6. 矩阵的其他操作:行列数、切片、复制、非0元素的下标
In [106]: a
Out[106]:
tensor([[1, 2],
[3, 4]])
# 行列数
In [107]: m,n = a.shape
In [108]: m,n
Out[108]: (2, 2)
In [109]: b
Out[109]:
tensor([[0, 1, 2],
[3, 4, 5]])
# 切片
In [111]: b[1:]
Out[111]: tensor([[3, 4, 5]])
In [112]: b[:,1:]
Out[112]:
tensor([[1, 2],
[4, 5]])
# 复制
In [114]: c = torch.clone(b)
In [115]: c
Out[115]:
tensor([[0, 1, 2],
[3, 4, 5]])
# 随机生成0-8,大小4*4
In [116]: d = torch.randint(0,9,(4,4))
In [117]: d
Out[117]:
tensor([[3, 1, 2, 2],
[4, 8, 3, 6],
[5, 4, 4, 6],
[0, 3, 0, 5]])
# 帅选出大于3的数
In [118]: d[d>3]
Out[118]: tensor([4, 8, 6, 5, 4, 4, 6, 5])
In [119]: d
Out[119]:
tensor([[3, 1, 2, 2],
[4, 8, 3, 6],
[5, 4, 4, 6],
[0, 3, 0, 5]])
# 非0元素的下标
In [120]: torch.nonzero(d)
Out[120]:
tensor([[0, 0],
[0, 1],
[0, 2],
[0, 3],
[1, 0],
[1, 1],
[1, 2],
[1, 3],
[2, 0],
[2, 1],
[2, 2],
[2, 3],
[3, 1],
[3, 3]])
7. 矩阵的行列式
In [127]: a
Out[127]:
tensor([[1, 2],
[3, 4]])
In [128]: a = a.float()
In [129]: a
Out[129]:
tensor([[1., 2.],
[3., 4.]])
# a必须为浮点型,否则会报错
In [130]: torch.det(a)
Out[130]: tensor(-2.0000)
In [132]: d
Out[132]:
tensor([[3, 1, 2, 2],
[4, 8, 3, 6],
[5, 4, 4, 6],
[0, 3, 0, 5]])
In [133]: torch.det(d.float())
Out[133]: tensor(43.0000)
8. 矩阵的逆和伪逆
矩阵的逆
In [134]: a
Out[134]:
tensor([[1., 2.],
[3., 4.]])
# 矩阵的逆
In [135]: torch.inverse(a)
Out[135]:
tensor([[-2.0000, 1.0000],
[ 1.5000, -0.5000]])
注意:矩阵不满秩,则会报错
矩阵的伪逆
In [143]: e = e.double()
# 最好使用float64,
In [144]: e
Out[144]:
tensor([[3., 3., 3.],
[3., 3., 3.],
[3., 3., 3.]], dtype=torch.float64)
# 伪逆
In [145]: torch.pinverse(e)
Out[145]:
tensor([[0.0370, 0.0370, 0.0370],
[0.0370, 0.0370, 0.0370],
[0.0370, 0.0370, 0.0370]], dtype=torch.float64)
In [146]: f = torch.ones((4,4),dtype=torch.float64)+3
In [147]: f
Out[147]:
tensor([[4., 4., 4., 4.],
[4., 4., 4., 4.],
[4., 4., 4., 4.],
[4., 4., 4., 4.]], dtype=torch.float64)
In [148]: torch.pinverse(f)
Out[148]:
tensor([[0.0156, 0.0156, 0.0156, 0.0156],
[0.0156, 0.0156, 0.0156, 0.0156],
[0.0156, 0.0156, 0.0156, 0.0156],
[0.0156, 0.0156, 0.0156, 0.0156]], dtype=torch.float64)
9. 矩阵的对称
In [149]: a
Out[149]:
tensor([[1., 2.],
[3., 4.]])
In [150]: a*a.T
Out[150]:
tensor([[ 1., 6.],
[ 6., 16.]])
10. 矩阵的秩、迹
矩阵的秩
In [151]: a
Out[151]:
tensor([[1., 2.],
[3., 4.]])
# 秩
In [152]: torch.matrix_rank(a)
Out[152]: tensor(2)
In [153]: e
Out[153]:
tensor([[3., 3., 3.],
[3., 3., 3.],
[3., 3., 3.]], dtype=torch.float64)
In [154]: torch.matrix_rank(e)
Out[154]: tensor(1)
矩阵的迹
In [156]: a
Out[156]:
tensor([[1., 2.],
[3., 4.]])
# 迹
In [157]: torch.trace(a)
Out[157]: tensor(5.)
In [158]: b
Out[158]:
tensor([[0, 1, 2],
[3, 4, 5]])
In [159]: torch.trace(b)
Out[159]: tensor(4)
11. 矩阵求解
可逆矩阵的求解
In [174]: A = torch.randint(0,10,(4,4),dtype=torch.float64)
In [175]: A
Out[175]:
tensor([[1., 0., 9., 1.],
[8., 5., 5., 6.],
[9., 1., 0., 4.],
[2., 0., 4., 0.]], dtype=torch.float64)
In [177]: B = torch.tensor([[1,10,0,1]],dtype=torch.float64)
In [178]: B
Out[178]: tensor([[ 1., 10., 0., 1.]], dtype=torch.float64)
# 求解
In [180]: (X,LU) = torch.solve(B.T,A)
In [181]: X
Out[181]:
tensor([[ 0.0989],
[ 2.7260],
[ 0.2006],
[-0.9040]], dtype=torch.float64)
# 验证
In [182]: torch.mm(A,X)
Out[182]:
tensor([[ 1.0000],
[10.0000],
[ 0.0000],
[ 1.0000]], dtype=torch.float64)
12. 矩阵的特征值与特征向量(EVD)
矩阵的特征向量和特征值:
这里是实对称矩阵,是特征向量,是特征值。下面我们使用Pytorch求取矩阵的特征值和特征向量。
In [200]: A = torch.tensor([[-1,1,0],[-4,3,0],[1,0,2]],dtype=torch.float64)
# 求解特征值与特征向量
In [205]: (evals,evecs) = torch.eig(A,eigenvectors=True)
# 特征值
In [206]: evals
Out[206]:
tensor([[2., 0.],
[1., 0.],
[1., 0.]], dtype=torch.float64)
# 特征向量
In [207]: evecs
Out[207]:
tensor([[ 0.0000, 0.4082, 0.4082],
[ 0.0000, 0.8165, 0.8165],
[ 1.0000, -0.4082, -0.4082]], dtype=torch.float64)