0阶张量(点)----标量(scalar):0
1阶张量(线)----向量(vector):[1,2,3,4,5]
2阶张量(面)----矩阵(matrix): [ 1 0 2 1 ] \left[\begin{array}{ll}1 & 0 \\2 & 1\end{array}\right] [1201]
3阶张量(体)----张量(tensor):[[[1,2,3],[4,5,6],[7,8,9]],[[1,2,3],[4,5,6],[7,8,9]],[[1,2,3],[4,5,6],[7,8,9]]]
这样子看起来不是很直观,张量的图形表示更加直观,如下图。从图中我们可以看出,0阶张量就是一个点,就像一个天安门站岗的士兵;1阶张量就是N多个0阶张量排成一行,就像天安门的升国旗对的士兵们排成的一列队伍;2阶张量就像阅兵时那些军人们排出的一个阵列;3阶张量就像每个军区的不同兵种排成的一个大阵列以此类推,N阶张量就是按照如上规律继续进行排列。
按照上面张量的表示方法,当张量的阶数越高,表示也会越麻烦,于是另外一种用bond来表示阶数的图形表示则会更加简洁,如下图。张量用连着N个腿(bond)的圆圈、方块或者其它图形来表示,每一条腿代表张量的一个阶,N条腿就代表张量有N阶。注意:腿的形状不影响张量的阶数
张量可进行切片操作提取相关的元素,以三阶张量为例,如图。切片操作就是在张量中抽取矩阵的操作,保留两个维度的变化。这个方式可能不太好理解,也或多或少有点绕(要是你不觉得绕,当我没说)。
换一种理解方式,我们可以理解为对一个维度进行切割,就像Frontal slices是对 n 3 n_{3} n3这个维度进行切割,Horizontal slices是对 n 1 n_{1} n1这个维度进行切割,Lateral slices是对 n 2 n_{2} n2这个维度进行切割,就像我们平时切豆腐,可以对三个不同的维度进行切割,这一块主要是理解记忆。
切片之后张量的展开自然是不能少的,张量展开通俗点来讲就是把切片之后的张量一片一片拼凑起来,拼凑方式有下图三种,可以 n 1 n_{1} n1维度进行拼接,可以 n 2 n_{2} n2维度进行拼接,也可以 n 3 n_{3} n3维度进行拼接。
有没有点点的混乱,下面上我们带有数字和颜色的图,配上下图是不是感觉好多了。
张量的基本运算主要有以下几个:
向量的内积:
C = ∑ a x a y a C=\sum_{a} x_{a} y_{a} C=a∑xaya
向量乘矩阵:
v b = ∑ a x a M a b = x M v_{b}=\sum_{a} x_{a} M_{a b}=x M vb=a∑xaMab=xM
矩阵乘矩阵:
M a c = ∑ b A a b B b c = A B M_{a c}=\sum_{b} A_{a b} B_{b c}=A B Mac=b∑AabBbc=AB
张量的缩并:
T a c d e = ∑ b A a b c B b d e T_{a c d e}=\sum_{b} A_{a b c} B_{b d e} Tacde=b∑AabcBbde
由下面的图我们很容易可以看出,只要下标相同,我们就可以把它们缩并,这也是张量运算的核心所在,后面还会遇到很多类似的情况。
本征向量与本征值又称特征向量与特征值,相信学过线性代数的小伙伴是不会陌生的。对于给定D × D的方阵M, 设D维归一化向量 v v v与标量 λ \lambda λ ,当其满足 M v = λ v \boldsymbol{M} \boldsymbol{v}=\boldsymbol{\lambda} \boldsymbol{v} Mv=λv 时,称 v v v与 λ \lambda λ分别为M的本征向量与本征值。本征值分解,又称特征分解(eigenvalue decomposition ) ,满足:
M = U Γ U + M=U \Gamma U^{+} M=UΓU+
其中 U被称为变换矩阵,其每一列为M的本征向量,且满足正交归一性 U U † = I ; Γ U U^{\dagger}=I ; \Gamma UU†=I;Γ 为对角矩阵,称为本征谱。
假设矩阵本征值为实数,求解给定矩阵的最大本征值及其本征态。最大本征值问题对应的优化问题就是对于给定的矩阵 M M M,求解归一化向量 v v v,使得函数 f = ∣ v T M v ∣ \mathrm{f}=\left|\mathrm{v}^{\mathrm{T}} \mathrm{Mv}\right| f=∣∣vTMv∣∣ 的值极大化,f 对应最大的本征值的绝对值。此证明采用数值证明法,要是小伙伴有其它的好方法评论区留言哦!
数值证明的代码实现:
import numpy as np
import copy
import matplotlib.pyplot as plt#画图
dim=4
M=np.random.randn(dim,dim)
M=M+M.T #对称化保证本征分解存在
print(M)
#求本征值和本征向量
lm,u=np.linalg.eig(M)
print("Eigenvalues:\n",lm)
print("Eigenvectors:\n",u)
#求绝对值最大的本征值及其对应的本征向量
n_max=np.argmax(abs(lm))
lm_max=lm[n_max]
v_max=u[:,n_max]
print(v_max)
#f=vMv'
f_max=abs(v_max.dot(M).dot(v_max))
print(f_max)
#随机建立多个归一化向量
num_v=200
vecs=np.random.randn(num_v,dim)
vecs=np.einsum('na,n->na',vecs,1/np.linalg.norm(vecs,axis=1))
#计算每个向量的f
f=abs(np.einsum('na,ab,nb->n',vecs,M,vecs.conj()))
#print(np.ones(num_v,))
#画图展示最大本征值
x=np.arange(num_v)
y=np.ones(num_v,)*f_max
plt.plot(x,y,'-')
plt.plot(x,f,'r')
plt.show()
随机建立200个归一化向量所得到的结果,由图可以看出,当随机生成的归一化向量越多,向量的本征值会越来越靠近最大本征值的绝对值,但永远不会大于最大本征值的绝对值。
num_v=200 | num_v=600 |
考虑实对称矩阵 M M M,设 Γ \Gamma Γ和u ( 0 ) ^{(0)} (0) 为其绝对值最大的唯一本征值及本征向量,则
lim K → ∞ M K = Γ 0 K u ( 0 ) u ( 0 ) T \lim _{K \rightarrow \infty} M^{K}=\Gamma_{0}^{K} u^{(0)} u^{(0) T} K→∞limMK=Γ0Ku(0)u(0)T
证明:
设M的本征值分解为M = U Γ U T , =U \Gamma U^{T}, \quad =UΓUT,
有 M K = U Γ U T U Γ U T … U Γ U T M^{K}=U \Gamma U^{T} U \Gamma U^{T} \ldots U \Gamma U^{T} MK=UΓUTUΓUT…UΓUT
由 U U T = U T U = I \mathrm{由} U U^{T}=U^{T} U=I 由UUT=UTU=I 得, M K = U Γ K U T = Γ i K U ( Γ Γ i ) K U T \quad M^{K}=U \Gamma^{K} U^{T}=\Gamma_{i}^{K} U\left(\frac{\Gamma}{\Gamma_{i}}\right)^{K} U^{T} MK=UΓKUT=ΓiKU(ΓiΓ)KUT
令 Γ i = Γ 0 \Gamma_{\mathrm{i}}=\Gamma_{0} Γi=Γ0
则 lim K → ∞ ( Γ Γ 0 ) K = lim K → ∞ [ Γ 0 / Γ 0 ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ Γ D − 1 / Γ 0 ] ∗ ∗ K = diag ( [ 1 0 \lim _{K \rightarrow \infty}\left(\frac{\Gamma}{\Gamma_{0}}\right)^{K}=\lim _{K \rightarrow \infty}\left[\begin{array}{ccc}\Gamma_{0} / \Gamma_{0} & \cdots & 0 \\ \vdots & \ddots & \vdots \\ 0 & \cdots & \Gamma_{D-1} / \Gamma_{0}\end{array}\right] * * \mathrm{K}=\operatorname{diag}([1 \quad 0 limK→∞(Γ0Γ)K=limK→∞⎣⎢⎡Γ0/Γ0⋮0⋯⋱⋯0⋮ΓD−1/Γ0⎦⎥⎤∗∗K=diag([10
得 lim k → ∞ M x = Γ 0 z U [ 1 ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ 0 ] U T = U [ 1 ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ 0 ] [ 1 ⋯ 0 ⋮ ⋱ ⋮ 0 ⋯ 0 ] U T = Γ 0 K u ( 0 ) u ( 0 ) T \lim _{k \rightarrow \infty} \mathrm{M}^{\mathrm{x}}=\Gamma_{0}^{\mathrm{z}} \mathrm{U}\left[\begin{array}{ccc}1 & \cdots & 0 \\ \vdots & \ddots & \vdots \\ 0 & \cdots & 0\end{array}\right] \mathrm{U}^{\mathrm{T}}=\mathrm{U}\left[\begin{array}{lll}1 & \cdots & 0 \\ \vdots & \ddots & \vdots \\ 0 & \cdots & 0\end{array}\right]\left[\begin{array}{ccc}1 & \cdots & 0 \\ \vdots & \ddots & \vdots \\ 0 & \cdots & 0\end{array}\right] \mathrm{U}^{\mathrm{T}}=\Gamma_{0}^{\mathrm{K}} \mathrm{u}^{(0)} \mathrm{u}^{(0) T} limk→∞Mx=Γ0zU⎣⎢⎡1⋮0⋯⋱⋯0⋮0⎦⎥⎤UT=U⎣⎢⎡1⋮0⋯⋱⋯0⋮0⎦⎥⎤⎣⎢⎡1⋮0⋯⋱⋯0⋮0⎦⎥⎤UT=Γ0Ku(0)u(0)T
证毕
最大本征值问题的幂级数求解法的代码实现:
#使用scipy中的eigs求最大几个本征值和本征向量
import numpy as np
import scipy.sparse.linalg as la
import copy
dim=4
M=np.random.randn(dim,dim)#随机生成4×4的张量
M=M+M.T
lm1,v1=la.eigs(M,k=1,which='LM')#求最大的本征值和本征向量
print(lm1)
print(M)
#最大本征值问题的幂级数求解法:
def eig0(mat,it_time=1000,tol=1e-15):
v1=np.random.randn(mat.shape[0],)
v0=copy.deepcopy(v1)
lm=1
for n in range(it_time):
v1=mat.dot(v0)
lm=np.linalg.norm(v1)#求本征值
v1/=lm #归一化
#判断是否收敛
conv=np.linalg.norm(v1-v0)
if conv<tol:
break
else:
v0=copy.deepcopy(v1)
return lm,v1
lm2,v2=eig0(M)
print(lm2)
print(v2.reshape(-1,))
奇异值分解(singular value decomposition):给定D × D’的矩阵M,有
M = U Λ V † M=U \Lambda V^{\dagger} M=UΛV†
其中 U U U 与V每一列分别被称为 M M M 的左、右奇异向量,且满足正交归一性
U U † = I , V V † = I U U^{\dagger}=I, \quad V V^{\dagger}=I UU†=I,VV†=I
Λ \Lambda Λ 为非负定实对角矩阵,称为奇异谱, 其元素称为奇异值。矩阵的非零奇异值个数定义为矩阵的秩。类似于本征值分解,但是进行奇异值分解的矩阵可以不是方阵。如图所示:
给定 D × D ′ D \times D^{\prime} D×D′ 的矩阵M,设其秩为 R R R 求解秩为 R ′ R^{\prime} R′ 的矩阵 M ′ M^{\prime} M′ 有 R > R ′ > 0 R>R^{\prime}>0 R>R′>0 且极小化二矩阵间的范数
ε = ∣ ∣ M − M ′ ∣ ∣ = ∑ i j ( M i j − M i j ′ ) 2 ∼ ∥ Λ R ′ : R − 1 ∥ ( 裁剪误差 ) \varepsilon=|| M-M^{\prime}||=\sqrt{\sum_{i j}\left(M_{i j}-M_{i j}^{\prime}\right)^{2} \sim\left\|\Lambda_{R^{\prime}: R-1}\right\|}(\text { 裁剪误差 }) ε=∣∣M−M′∣∣=ij∑(Mij−Mij′)2∼∥ΛR′:R−1∥( 裁剪误差 )
低秩近似问题的最优解为:
M ′ = U [ : , 0 : R ′ ] ∧ [ 0 : R ′ , 0 : R ′ ] V [ : , 0 : R ′ ] † M^{\prime}=U\left[:, 0: R^{\prime}\right] \wedge\left[0: R^{\prime}, 0: R^{\prime}\right] \quad V\left[:, 0: R^{\prime}\right]^{\dagger} M′=U[:,0:R′]∧[0:R′,0:R′]V[:,0:R′]†
代码实现:
import numpy as np
import matplotlib.image as pimg
import matplotlib.pyplot as plt
img=pimg.imread('C:/Users/86177/Pictures/Saved Pictures/ice.jpg')#导入图片
img=np.sum(img,axis=2) /3 #设置为灰度图片
print('shape of the image data = '+str(img.shape))
plt.imshow(img)
plt.show()
import scipy.sparse.linalg as la
#进行图片SVD分解
def img_compress(img,k):
u,lm,v=la.svds(img,k=k)
img1=u.dot(np.diag(lm)).dot(v)
num_para=2*k*u.shape[0]
#print(num_para)
return img1,num_para
for k in range(10,100,40):
img1,num_para=img_compress(img,k)
plt.imshow(img1)
plt.show()
#进行奇异值分解后的相对误差
print('error = '+str(np.linalg.norm(img-img1)/np.linalg.norm(img)))
print('k = ',k)
由图可以看出当特征值取10个时图片很模糊,此时裁剪误差约13.9%;当特征值取50个时图片肉眼可见整理构图元素,此时裁剪误差约5.2%;当特征值取90个时图片很清晰,此时裁剪误差约3.2%,此时误差已经很小并且图片清晰度很高。可以采用此算法进行图片压缩从而减少所占存储空间。
高阶奇异值分解(简称HOSVD),又称Tucker分解
T a b c = ∑ i j k G i j k U a i V b j W c k T_{a b c}=\sum_{i j k} G_{i j k} U_{a i} V_{b j} W_{c k} Tabc=ijk∑GijkUaiVbjWck
变换矩阵满足正交性
U U T = V V T = W W T = I U U^{T}=V V^{T}=W W^{T}=I UUT=VVT=WWT=I
张量G被称为核张量。定义G的键约化矩阵,以指标 i i i为例,其键约化矩阵定义为:
J i i ′ = ∑ j k G i j k G i ′ j k J_{i i^{'}}=\sum_{j k} G_{i j k} G_{i^{'}j k} Jii′=jk∑GijkGi′jk
高阶奇异值分解算法
a.计算各指标的键约化矩阵(相同的指标进行缩并处理):
I a a ′ = ∑ j k T a b c T a ′ b c J b b ′ = ∑ i k T a b c T a b ′ c K c c ′ = ∑ i j T a b c T a b c ′ \begin{aligned} I_{a a^{\prime}} &=\sum_{j k} T_{a b c} T_{a^{\prime} b c} \\ J_{b b^{\prime}} &=\sum_{i k} T_{a b c} T_{a b^{\prime} c} \\ K_{c c^{\prime}} &=\sum_{i j} T_{a b c} T_{a b c^{\prime}} \end{aligned} Iaa′Jbb′Kcc′=jk∑TabcTa′bc=ik∑TabcTab′c=ij∑TabcTabc′
b.计算每个键约化矩阵的本征值分解:
I = U Ω U T I=U \Omega U^{T} I=UΩUT
J = V ∏ V T J=V \prod V^{T} J=V∏VT
K = W Υ W T K=W\Upsilon W^{T} K=WΥWT
c.计算核张量:
G i j k = ∑ a b c T a b c U a i V b j W c k G_{i j k}=\sum_{a b c} T_{a b c} U_{a i} V_{b j} W_{c k} Gijk=abc∑TabcUaiVbjWck
最终得到高阶奇异值分解:
T a b c = ∑ i j k G i j k U a i V b j W c k T_{a b c}=\sum_{i j k} G_{i j k} U_{a i} V_{b j} W_{c k} Tabc=ijk∑GijkUaiVbjWck
本人资质愚钝,我刚开始其实也是学了大概1 or 2个月才弄明白,如果没有懂,可以多查查资料或者欢迎评论区见。反正每天多思考,久而久之不懂的地方自然也就明白了。
记第n个左、右 奇异向量分别为u ( n ) ^{(n)} (n) 和 v ( n ) v^{(n)} v(n) 证明如下等式:
∑ a u a ( n ) M a b = Λ ( n ) v b ( n ) ∑ b M a b v b ( n ) = Λ ( n ) u a ( n ) \begin{array}{l} \sum_{a} u_{a}^{(n)} M_{a b}=\Lambda^{(n)} v_{b}^{(n)} \\ \sum_{b} M_{a b} v_{b}^{(n)}=\Lambda^{(n)} u_{a}^{(n)} \end{array} ∑aua(n)Mab=Λ(n)vb(n)∑bMabvb(n)=Λ(n)ua(n)
其中, Λ ( n ) \quad \Lambda^{(n)} Λ(n) 为第n个奇异值, \quad 且有
Λ ( n ) = ∑ a b u a ( n ) M a b v b ( n ) \Lambda^{(n)}=\sum_{a b} u_{a}^{(n)} M_{a b} v_{b}^{(n)} Λ(n)=ab∑ua(n)Mabvb(n)
计算最大奇异值及奇异向量的迭代算法(和矩阵的幂级数算法有点类似,不懂可以往前再看看哦!):
(a)随机初始化归一向量u和v;
(b) 利用第一个式子,计算u和M的收缩并归一化,更新v,归一化因子记为 Λ \Lambda Λ
(c)利用第二个式子,计算v和M的收缩并归一化,更新u, 归一化因子记为 Λ \Lambda Λ
(d)如果u和v(以及 Λ \Lambda Λ ) 收剑,则返回u、v和 Λ \Lambda Λ; 否则,返回执行步骤
(b)最后我们会发现u和v刚好对应于M最大左、右奇异向量, 对应最大的奇异值。
将上述自洽方程组推广到高阶张量,得到如下自洽方程组(以三阶张量为例):
∑ a b T a b c u a v b = Λ w c \sum_{a b} T_{a b c} u_{a} v_{b}=\Lambda w_{c} ab∑Tabcuavb=Λwc
∑ a c T a b c u a w c = Λ v b \sum_{a c} T_{a b c} u_{a} w_{c}=\Lambda v_{b} ac∑Tabcuawc=Λvb
∑ b c T a b c v b w c = Λ u a \sum_{b c} T_{a b c} v_{b} w_{c}=\Lambda u_{a} bc∑Tabcvbwc=Λua
u、v和w为归一化向量,方程组成立时满足:
Λ = ∑ a b c T a b c u a v b w c \Lambda=\sum_{a b c} T_{a b c} u_{a} v_{b} w_{c} Λ=abc∑Tabcuavbwc
其被称为rank-1分解,迭代求解的方法与二阶张量相同。
我学习张量有关的知识也不是很久,有很多东西也不懂。我是一只正在不断学习、希望早日成为小白的小小白,这是我第一次写博客,有什么错误欢迎大家批评指正,喜欢的请点个赞哦!