张量和线性代数基础

  • 一、张量基础
    • 1. 张量的定义
    • 2. 张量的基本操作和运算
  • 二、线性代数基础
    • 1. 本征值分解与最大本征值问题
      • 本征值分解
      • 最大本征值问题
      • 最大本征值问题的幂级数求解法
    • 2. 奇异值分解与最优低秩近似问题
      • 奇异值分解(SVD)
      • 矩阵的低秩近似问题
      • 高阶奇异值分解
    • 2. 多线性代数中的张量单秩问题

这是本人在暑期学习中对有关张量网络算法知识的一些梳理,有什么错误请大家批评指正,喜欢的给点个赞。

一、张量基础

1. 张量的定义

0阶张量(点)----标量(scalar):0
1阶张量(线)----向量(vector):[1,2,3,4,5]
2阶张量(面)----矩阵(matrix):[1021]\left[\begin{array}{ll}1 & 0 \\2 & 1\end{array}\right][12​01​]
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阶。注意:腿的形状不影响张量的阶数

2. 张量的基本操作和运算

张量可进行切片操作提取相关的元素,以三阶张量为例,如图。切片操作就是在张量中抽取矩阵的操作,保留两个维度的变化。这个方式可能不太好理解,也或多或少有点绕(要是你不觉得绕,当我没说)。

换一种理解方式,我们可以理解为对一个维度进行切割,就像Frontal slices是对n3n_{3}n3​这个维度进行切割,Horizontal slices是对n1n_{1}n1​这个维度进行切割,Lateral slices是对n2n_{2}n2​这个维度进行切割,就像我们平时切豆腐,可以对三个不同的维度进行切割,这一块主要是理解记忆。

切片之后张量的展开自然是不能少的,张量展开通俗点来讲就是把切片之后的张量一片一片拼凑起来,拼凑方式有下图三种,可以n1n_{1}n1​维度进行拼接,可以n2n_{2}n2​维度进行拼接,也可以n3n_{3}n3​维度进行拼接。


有没有点点的混乱,下面上我们带有数字和颜色的图,配上下图是不是感觉好多了。

张量的基本运算主要有以下几个:
向量的内积:
C=∑axayaC=\sum_{a} x_{a} y_{a}C=a∑​xa​ya​

向量乘矩阵:
vb=∑axaMab=xMv_{b}=\sum_{a} x_{a} M_{a b}=x Mvb​=a∑​xa​Mab​=xM

矩阵乘矩阵:
Mac=∑bAabBbc=ABM_{a c}=\sum_{b} A_{a b} B_{b c}=A BMac​=b∑​Aab​Bbc​=AB

张量的缩并:
Tacde=∑bAabcBbdeT_{a c d e}=\sum_{b} A_{a b c} B_{b d e}Tacde​=b∑​Aabc​Bbde​

由下面的图我们很容易可以看出,只要下标相同,我们就可以把它们缩并,这也是张量运算的核心所在,后面还会遇到很多类似的情况。

二、线性代数基础

1. 本征值分解与最大本征值问题

本征值分解

本征向量与本征值又称特征向量与特征值,相信学过线性代数的小伙伴是不会陌生的。对于给定D × D的方阵M, 设D维归一化向量vvv与标量 λ\lambdaλ ,当其满足 Mv=λv\boldsymbol{M} \boldsymbol{v}=\boldsymbol{\lambda} \boldsymbol{v}Mv=λv 时,称vvv与λ\lambdaλ分别为M的本征向量与本征值。本征值分解,又称特征分解(eigenvalue decomposition ) ,满足:
M=UΓU+M=U \Gamma U^{+}M=UΓU+

其中 U被称为变换矩阵,其每一列为M的本征向量,且满足正交归一性 UU†=I;ΓU U^{\dagger}=I ; \GammaUU†=I;Γ 为对角矩阵,称为本征谱。

最大本征值问题

假设矩阵本征值为实数,求解给定矩阵的最大本征值及其本征态。最大本征值问题对应的优化问题就是对于给定的矩阵MMM,求解归一化向量vvv,使得函数 f=∣vTMv∣\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

最大本征值问题的幂级数求解法

考虑实对称矩阵MMM,设Γ\GammaΓ和u (0)^{(0)}(0) 为其绝对值最大的唯一本征值及本征向量,则
lim⁡K→∞MK=Γ0Ku(0)u(0)T\lim _{K \rightarrow \infty} M^{K}=\Gamma_{0}^{K} u^{(0)} u^{(0) T}K→∞lim​MK=Γ0K​u(0)u(0)T

证明:
设M的本征值分解为M =UΓUT,=U \Gamma U^{T}, \quad=UΓUT,
有 MK=UΓUTUΓUT…UΓUTM^{K}=U \Gamma U^{T} U \Gamma U^{T} \ldots U \Gamma U^{T}MK=UΓUTUΓUT…UΓUT
由UUT=UTU=I\mathrm{由} U U^{T}=U^{T} U=I由UUT=UTU=I 得, MK=UΓKUT=ΓiKU(ΓΓi)KUT\quad M^{K}=U \Gamma^{K} U^{T}=\Gamma_{i}^{K} U\left(\frac{\Gamma}{\Gamma_{i}}\right)^{K} U^{T}MK=UΓKUT=ΓiK​U(Γ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⁡([10\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 0limK→∞​(Γ0​Γ​)K=limK→∞​⎣⎢⎡​Γ0​/Γ0​⋮0​⋯⋱⋯​0⋮ΓD−1​/Γ0​​⎦⎥⎤​∗∗K=diag([10
得 lim⁡k→∞Mx=Γ0zU[1⋯0⋮⋱⋮0⋯0]UT=U[1⋯0⋮⋱⋮0⋯0][1⋯0⋮⋱⋮0⋯0]UT=Γ0Ku(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=Γ0z​U⎣⎢⎡​1⋮0​⋯⋱⋯​0⋮0​⎦⎥⎤​UT=U⎣⎢⎡​1⋮0​⋯⋱⋯​0⋮0​⎦⎥⎤​⎣⎢⎡​1⋮0​⋯⋱⋯​0⋮0​⎦⎥⎤​UT=Γ0K​u(0)u(0)T
证毕
最大本征值问题的幂级数求解法的代码实现:

#使用scipy中的eigs求最大几个本征值和本征向量
import numpy as np
import scipy.sparse.linalg as la
import copydim=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=1for 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:breakelse:v0=copy.deepcopy(v1)return lm,v1lm2,v2=eig0(M)
print(lm2)
print(v2.reshape(-1,))

2. 奇异值分解与最优低秩近似问题

注意这个很重要,后面会有很多很多和这个有关的知识点。

奇异值分解(SVD)

奇异值分解(singular value decomposition):给定D × D’的矩阵M,有
M=UΛV†M=U \Lambda V^{\dagger}M=UΛV†

其中 UUU 与V每一列分别被称为 MMM 的左、右奇异向量,且满足正交归一性
UU†=I,VV†=IU U^{\dagger}=I, \quad V V^{\dagger}=IUU†=I,VV†=I

Λ\LambdaΛ 为非负定实对角矩阵,称为奇异谱, 其元素称为奇异值。矩阵的非零奇异值个数定义为矩阵的秩。类似于本征值分解,但是进行奇异值分解的矩阵可以不是方阵。如图所示:

矩阵的低秩近似问题

给定 D×D′D \times D^{\prime}D×D′ 的矩阵M,设其秩为 RRR 求解秩为 R′R^{\prime}R′ 的矩阵 M′M^{\prime}M′ 有 R>R′>0R>R^{\prime}>0R>R′>0 且极小化二矩阵间的范数
ε=∣∣M−M′∣∣=∑ij(Mij−Mij′)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 pltimg=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分解
Tabc=∑ijkGijkUaiVbjWckT_{a b c}=\sum_{i j k} G_{i j k} U_{a i} V_{b j} W_{c k}Tabc​=ijk∑​Gijk​Uai​Vbj​Wck​

变换矩阵满足正交性
UUT=VVT=WWT=IU U^{T}=V V^{T}=W W^{T}=IUUT=VVT=WWT=I

张量G被称为核张量。定义G的键约化矩阵,以指标iii为例,其键约化矩阵定义为:
Jii′=∑jkGijkGi′jkJ_{i i^{'}}=\sum_{j k} G_{i j k} G_{i^{'}j k}Jii′​=jk∑​Gijk​Gi′jk​


高阶奇异值分解算法
a.计算各指标的键约化矩阵(相同的指标进行缩并处理):
Iaa′=∑jkTabcTa′bcJbb′=∑ikTabcTab′cKcc′=∑ijTabcTabc′\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∑​Tabc​Ta′bc​=ik∑​Tabc​Tab′c​=ij∑​Tabc​Tabc′​​

b.计算每个键约化矩阵的本征值分解:
I=UΩUTI=U \Omega U^{T}I=UΩUT

J=V∏VTJ=V \prod V^{T}J=V∏VT

K=WΥWTK=W\Upsilon W^{T}K=WΥWT

c.计算核张量:
Gijk=∑abcTabcUaiVbjWckG_{i j k}=\sum_{a b c} T_{a b c} U_{a i} V_{b j} W_{c k}Gijk​=abc∑​Tabc​Uai​Vbj​Wck​

最终得到高阶奇异值分解:
Tabc=∑ijkGijkUaiVbjWckT_{a b c}=\sum_{i j k} G_{i j k} U_{a i} V_{b j} W_{c k}Tabc​=ijk∑​Gijk​Uai​Vbj​Wck​

有没有感觉奇异值分解也不是很难呢?

本人资质愚钝,我刚开始其实也是学了大概1 or 2个月才弄明白,如果没有懂,可以多查查资料或者欢迎评论区见。反正每天多思考,久而久之不懂的地方自然也就明白了。

2. 多线性代数中的张量单秩问题

记第n个左、右 奇异向量分别为u (n)^{(n)}(n) 和 v(n)v^{(n)}v(n) 证明如下等式:
∑aua(n)Mab=Λ(n)vb(n)∑bMabvb(n)=Λ(n)ua(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}∑a​ua(n)​Mab​=Λ(n)vb(n)​∑b​Mab​vb(n)​=Λ(n)ua(n)​​

其中, Λ(n)\quad \Lambda^{(n)}Λ(n) 为第n个奇异值, \quad 且有
Λ(n)=∑abua(n)Mabvb(n)\Lambda^{(n)}=\sum_{a b} u_{a}^{(n)} M_{a b} v_{b}^{(n)}Λ(n)=ab∑​ua(n)​Mab​vb(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最大左、右奇异向量, 对应最大的奇异值。
将上述自洽方程组推广到高阶张量,得到如下自洽方程组(以三阶张量为例):
∑abTabcuavb=Λwc\sum_{a b} T_{a b c} u_{a} v_{b}=\Lambda w_{c}ab∑​Tabc​ua​vb​=Λwc​

∑acTabcuawc=Λvb\sum_{a c} T_{a b c} u_{a} w_{c}=\Lambda v_{b}ac∑​Tabc​ua​wc​=Λvb​

∑bcTabcvbwc=Λua\sum_{b c} T_{a b c} v_{b} w_{c}=\Lambda u_{a}bc∑​Tabc​vb​wc​=Λua​

u、v和w为归一化向量,方程组成立时满足:
Λ=∑abcTabcuavbwc\Lambda=\sum_{a b c} T_{a b c} u_{a} v_{b} w_{c}Λ=abc∑​Tabc​ua​vb​wc​

其被称为rank-1分解,迭代求解的方法与二阶张量相同。

我学习张量有关的知识也不是很久,有很多东西也不懂。我是一只正在不断学习、希望早日成为小白的小小白,这是我第一次写博客,有什么错误欢迎大家批评指正,喜欢的请点个赞哦!

张量网络算法基础(一、张量和线性代数基础)相关推荐

  1. 张量网络算法基础(七、张量网络中的有效哈密顿思想)

    张量网络中的有效哈密顿思想 一.无穷大张量网络的本征自洽方法 二.张量网络的梯度更新 三.任意尺寸张量网络收缩算法 四.张量网络中的有效哈密顿量思想 我是一只正在不断学习.希望早日成为小白的小小白,有 ...

  2. 张量网络算法基础(二、量子态、量子算符)

    量子态.量子算符 量子态与量子算符 1. 定义 2. 态矢与算符的向量或矩阵表示 态矢和在给定基矢下的展开系数的向量表示 算符在给定基矢下的展开系数的矩阵表示 3. 量子态和算符的运算 单体算符及其运 ...

  3. 张量网络算法基础(三、格点模型)

    格点模型 格点模型 1. 热力学基础 经典热力学基础 量子格点模型的热力学基础 2. 海森堡模型的基态计算 量子格点模型的基态问题 基态计算的退火算法 基态计算的严格对角化算法 基于自动微分的基态变分 ...

  4. 十、张量网络收缩算法

    十.张量网络收缩算法 1. 张量网络的基本定义 通过前面的学习,我们对张量网络有了简单的了解,这里我们给出张量网络的一般定义:由多个张量按照一定的收缩规则构成的模型,被称为张量网络. 其中,收缩规则由 ...

  5. 谷歌开源张量网络库TensorNetwork,GPU处理提升100倍!

    编译 |  琥珀 出品 | AI科技大本营(ID:rgznai100) 世界上许多最严峻的科学挑战,如开发高温超导体和理解时空的本质,都涉及处理量子系统的复杂性.然而,这些系统中量子态的数量程指数级增 ...

  6. uBLAS——Boost 线性代数基础程序库 (三)

    uBLAS--Boost 线性代数基础程序库 uBLAS--Boost 线性代数基础程序库 (二) namespace ublas = boost::numeric::ublas; row() vs ...

  7. 《基于张量网络的机器学习入门》学习笔记8(Shor算法)

    <基于张量网络的机器学习入门>学习笔记8 Shor算法 来源 Shor算法的大致流程 因数分解 周期求取与量子傅里叶变换(QFT) Shor算法 来源 1994 1994 1994年,应用 ...

  8. 《基于张量网络的学习入门》学习笔记3

    <基于张量网络的机器学习入门>学习笔记3 量子寄存器.量子状态叠加与并行处理的关系 不确定性原理 量子寄存器.量子状态叠加与并行处理的关系 叠加态的数学定义: ∣x⟩=α1∣x1⟩+α2∣ ...

  9. 张量网络系列(一 从张量到张量网络)

    历时半个多月,我们终于从刚开始的张量学习 ,到现在的张量网络,本人真的是一路艰辛,哎 ,打油诗一首表心意: 本是计科专业狗,年少无知四顾首. 无奈量子吸引我,前路茫茫无处走. 早知人生本就难,科研门前 ...

最新文章

  1. opencv自定义角点检测
  2. CentripetalNet 48
  3. vba字典合并单元格为空_VBA合并单元格求和处理套路
  4. 【错误记录】IntelliJ IDEA 编译 Groovy 报错 ( GroovyRuntimeException: This script or class could not be run. )
  5. 天锐绿盾解密_天锐绿盾携手衡阳规划设计院 实现信息系统安全管理
  6. CoreData 增删改查
  7. phonegap文件上传(java_php),Android应用开发之使用PhoneGap实现位置上报功能
  8. 新版仿山楂岛留言PHP源码+短视频/公众号吸粉引流
  9. Unity摄像机平滑处理跟随
  10. 初中计算机教学进度表,信息技术教学计划范文
  11. 梆梆加固的Android P版本预兼容之路
  12. 【报告分享】2021懂车帝经销商直播价值白皮书-懂车帝x巨量算数(附下载)
  13. 2021-2027全球及中国红外探测器芯片行业研究及十四五规划分析报告
  14. 物尽其用,数码相机兼职摄像头!
  15. eversync safari_推荐好用的firefox和chrome的书签同步工具
  16. Python的数据科学函数包(二)——pandas(series dataframe)(loc iloc ix)(csv文件)
  17. 听心 文/一个会写诗的程序员
  18. Postman参数化
  19. 那些在开源世界顶半边天的女同胞们
  20. python做大数据可视化软件_一般用哪些工具做大数据可视化分析?

热门文章

  1. 国产CAD想说爱你,并不容易。
  2. 二进制方式搭建Kubernetes高可用集群(超丰富的组件概念理论总结)
  3. UGUI源码解析(LayoutSystem布局系统)
  4. Linux(Ubuntu)操作系统,vi编辑器与gcc编译器的下载与使用(命令参数很详细)
  5. 辉光翼战记 天空のユミナ 繁体免DVD破解补丁
  6. Mac安装配置Maven及镜像
  7. floquet端口x极化入射波_AnsoftHFSS在周期性异向介质研究中的仿真方法.pdf
  8. CSS实现bootstrap的Collapse动态折叠和展开时箭头图标
  9. 动画般Git History查看工具
  10. cad批量打印_CAD如何批量打印