2 线性代数实验

2.1 线性代数内容介绍

2.1.1 线性代数介绍

线性代数是一门被广泛运用于各工程技术领域的学科。用线性代数的相关概念和结论,可以极大地简化数据挖掘中相关公式的推导和表述。线性代数将复杂的问题简单化,让我们能够对问题进行高效地数学运算。

线性代数是一个数学工具,它不仅提供了有助于操作数组的技术,还提供了像向量和矩阵这样的数据结构用来保存数字和规则,以便进行加,减,乘,除的运算。

2.1.2 代码实现介绍

numpy 是一款基于 Python 的数值处理模块,在处理矩阵数据方面有很强大的功能与优势。因为线性代数的主要内容就是对矩阵的处理,所以本章节主要的内容都是基于 numpy 进行展开。另外也会涉及到方程组求解,所以也会用到数学科学库 scipy。

2.2线性代数实现

导入相应库:

import numpy as np
import scipy as sp

2.2.1 reshape 运算

在数学中并没有 reshape 运算,但是在 numpy 运算库中是一个非常常用的运算,用来改变一个张量的维度数和每个维度的大小例如一个 10×10 的图片在保存时直接保存为一个包含100个元素的序列,在读取后就可以使用 reshape 将其从1100变换为 10×10 。示例如下:

生成一个包含整数0~11的向量

代码输入:

x = np.arange(12)
print(x)

结果输出:

[ 0  1  2  3  4  5  6  7  8  9 10 11]

查看数组大小

x.shape

结果输出:

(12,)

将 x 转换成二维矩阵,其中矩阵的第一个维度为1

x = x.reshape(1,12)
print(x)

结果输出:

[[ 0  1  2  3  4  5  6  7  8  9 10 11]]

查看数组大小

x.shape

结果输出:

(1,12)

将 x 转换 3x4 的矩阵

x = x.reshape(3,4)
print(x)

结果输出:

[[ 0  1  2  3]
[ 4 5 6 7]
[ 8 9 10 11]]

2.2.2 转置实现

向量和矩阵的转置是交换行列顺序,而三维及以上张量的转置就需要指定转置的维度。

生成 3x4 的矩阵

代码输入:

A = np.arange(12).reshape(3,4)
print(A)

结果输出:

[[ 0  1  2  3]
[ 4 5 6 7]
[ 8 9 10 11]]

转置

A.T

结果输出:

array([[ 0,  4,  8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])

2.2.3 矩阵乘法实现

矩阵乘法:记两个矩阵分别为 A 和 B,两个矩阵能够相乘的条件为第一个矩阵的列数等于第二个

矩阵的行数。

代码输入:

A = np.arange(6).reshape(3,2)
B = np.arange(6).reshape(2,3)
print(A)
print("\n")
print(B)

结果输出:

[[0 1]
[2 3]
[4 5]]

[[0 1 2]
[3 4 5]]

矩阵相乘

np.matmul(A,B)

结果输出:

array([[ 3,  4,  5],
[ 9, 14, 19],
[15, 24, 33]])

2.2.4 矩阵对应运算

元素对应运算:针对形状相同矩阵的运算统称,包括元素对应相乘、相加等,即对两个矩阵相同位置的元素进行加减乘除等运算。

代码输入:

创建矩阵

A = np.arange(6).reshape(3,2)

矩阵相乘

print(A*A)

结果输出:

[[ 0  1]
[ 4 9]
[16 25]]

矩阵相加

print(A+A)

结果输出:

[[ 0  2]
[ 4 6]
[ 8 10]]

2.2.5 逆矩阵实现

只有方阵才有逆矩阵,逆矩阵实现。

代码输入:

A = np.arange(4).reshape(2,2)
print(A)

结果输出:

[[0 1]
[2 3]]

求逆矩阵

np.linalg.inv(A)

结果输出:

array([[-1.5,  0.5],
[ 1. , 0. ]])

2.2.6 特征值与特征向量

求矩阵的特征值与特征向量并实现可视化。

导入相应库:

import numpy as np
from scipy.linalg import eig
import matplotlib.pyplot as pit

求特征值与特征向量:

A = [[1,2],
[2,1]] #生成一个2*2的矩阵
evals,evecs = eig(A) #求A的特征值(evals)和特征向量(evecs)
evecs = evecs[:,0],evecs[:,1]

plt.subplots() 返回一个 Figure 实例 fig 和一个 AxesSubplot 实例ax。fig 代表整个图像,ax代表坐标轴和画的图。作图:

fig,ax = plt.subplots()

让坐标轴经过原点:

for spine in ['left','bottom']:
ax.spines[spine].set_position('zero') #让在左下角的坐标轴经过原点

画出网格:

ax.grid(alpha=0.4)

设置坐标轴的范围:

xmin,xmax = -3,3
ymin,ymax = -3,3
ax.set(xlim=(xmin,xmax),ylim=(ymin,ymax))

画出特征向量。用一个箭头指向要注释的地方,再写上一段话的行为,叫做 annotat。s 是输入内容;xy 是箭头指向; xytext 是文字所处的位置; arrowprops 通过 arrowstyle 表明箭头的风格或种类。

for v in evecs:
ax.annotate(s='',xy=v,xytext=(0,0),arrowprops=dict(facecolor='blue',shrink=0,alpha=0.6,width=0.5))

画出特征空间:

x = np.linspace(xmin,xmax,3)    #在指定的间隔内返回均匀间隔的数字
for v in evecs:
a = v[1]/v[0] #沿特征向量方向的单位向量
ax.plot(x,a*x,'r-',lw=0.4) #参数lw表示图线的粗细
plt.show()

可视化图像:

暂时不贴

2.2.7 求行列式

求一个矩阵的行列式:

代码输入:

E = [[1,2,3],
[4,5,6],
[7,8,9]]
print(np.linalg.det(E))

结果输出:

-9.51619735392994e-16

2.2.8 奇异值分解实现

利用奇异值分解,通过文章标题出现的关键词,对文章进行聚类

导入相应模块:

import numpy as np
import matplotlib.pyplot as plt

输入关键字:

words = ["books","dad","stock","value","singular","estate","decomposition"]

设已知8个标题,7个关键字。记录每个标题中每个关键字出现的次数,得矩阵 X。X 中每一行表示一个标题,每一列表示一个关键字,矩阵中的每个元素表示一个关键字中一个标题中出现的次数。

X = np.array([[0,2,1,0,0,0,0],[2,0,0,1,0,1,0],[1,0,0,0,0,0,1],[0,0,1,0,0,0,0],[0,1,0,0,0,0,0],[0,0,0,1,1,0,1],[0,1,0,0,1,0,0],[0,0,0,0,1,1,1]])

进行奇异值分解:

U,s,Vh = np.linalg.svd(X)

输出左奇异矩阵U:

print("U=",U)

结果输出:

U= [[-1.87135757e-01 -7.93624528e-01  2.45011855e-01 -2.05404352e-01
-3.88578059e-16 5.75779114e-16 -2.57394431e-01 -4.08248290e-01]
[-6.92896814e-01 2.88368077e-01 5.67788037e-01 2.22142537e-01
2.54000254e-01 -6.37019839e-16 -2.21623012e-02 2.05865892e-17]
[-3.53233681e-01 1.22606651e-01 3.49203461e-02 -4.51735990e-01
-7.62000762e-01 1.27403968e-15 2.72513448e-01 3.80488702e-17]
[-2.61369658e-02 -1.33189110e-01 7.51079037e-02 -6.44727454e-01
5.08000508e-01 1.77635684e-15 3.68146235e-01 4.08248290e-01]
[-8.04993957e-02 -3.30217709e-01 8.49519758e-02 2.19661551e-01
-2.54000254e-01 -4.81127681e-16 -3.12770333e-01 8.16496581e-01]
[-3.95029694e-01 1.56123876e-02 -5.28290830e-01 -6.82340484e-02
1.27000127e-01 -7.07106781e-01 -2.09360158e-01 1.55512464e-17]
[-2.02089013e-01 -3.80395849e-01 -2.12899198e-01 4.80790894e-01
8.04483689e-16 -1.60632798e-15 7.33466480e-01 1.76241226e-16]
[-3.95029694e-01 1.56123876e-02 -5.28290830e-01 -6.82340484e-02
1.27000127e-01 7.07106781e-01 -2.09360158e-01 -1.23226632e-16]]

输出奇异值矩阵:

print("s=",s)

按每个奇异值一对应一个左奇异向量和一个右奇异向量奇异值从大到小排列输出结果:

s= [2.85653844 2.63792139 2.06449303 1.14829917 1.         1.
0.54848559] #似乎有问题,仅作参考

输出右奇异矩阵Vh:

print("Vh=",Vh)

输出结果:

Vh= [[-6.08788345e-01 -2.29949618e-01 -7.46612474e-02 -3.80854846e-01
-3.47325416e-01 -3.80854846e-01 -4.00237243e-01]
[ 2.65111314e-01 -8.71088358e-01 -3.51342402e-01 1.15234846e-01
-1.32365989e-01 1.15234846e-01 5.83153945e-02]
[ 5.66965547e-01 1.75382762e-01 1.55059743e-01 1.91316736e-02
-6.14911671e-01 1.91316736e-02 -4.94872736e-01]
[-6.48865369e-03 2.52237176e-01 -7.40339999e-01 1.34031699e-01
2.99854608e-01 1.34031699e-01 -5.12239408e-01]
[-2.54000254e-01 -2.54000254e-01 5.08000508e-01 3.81000381e-01
2.54000254e-01 3.81000381e-01 -5.08000508e-01]
[ 0.00000000e+00 -7.68640544e-16 2.33583082e-15 -7.07106781e-01
-1.21802199e-15 7.07106781e-01 1.91457709e-15]
[ 4.16034348e-01 -1.71550021e-01 2.01922906e-01 -4.22112199e-01
5.73845817e-01 -4.22112199e-01 -2.66564648e-01]]

规定坐标轴的范围

plt.axis([-0.8,0.2,-0.8,0.8])

原每个关键字由 1*8 的向量表示,现降维成 1*2 的向量以便进行可视化

for i in range(len(words)):
plt.text(U[i,0],U[i,1],words[i])
plt.show()

可视化结果:
暂无

图解:将2维可视化后,我们可以将关键词聚类,如 singular, value 和 decomposition 三个词距离比较近可以被划分为一组,而 stock 和 estate 经常同时出现。

2.2.9 线性方程组求解

求解线性方程组比较简单,只需要用到一个函数( scipy linalg. solve)就可以了。
比如我们对胶片中矩阵章节中的部门月度跑步案例进行线性方程组求解,线性方程组如下:
待更新!!!!!!

代码输入:

from scipy.linalg import solve
a = np.array([[10,8,12],[4,4,2],[2,-4,-2]])
b = np.array([10,8,-5])
x = solve(a,b)
print(x)

结果输出:

[ 0.5     1.9375 -0.875 ]