目录
直接对矩阵进行奇异值分解
已知矩阵,对其进行奇异值分解。
import numpy as np
#创建矩阵A
A = np.array([[1,5,7,6,1],[2,1,10,4,4],[3,6,7,5,2]])
#利用np.linalg.svd()函数直接进行奇异值分解
#该函数有三个返回值:左奇异矩阵,所有奇异值,右奇异矩阵。
U,Sigma,VT = np.linalg.svd(A)
#展示
print(U)
print(Sigma)
print(VT)
运行结果:
利用SVD分解、压缩图像
原图:
代码:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
img_eg = mpimg.imread("car.jpg")
print(img_eg.shape) #运行结果:(400,640,3)
#将图片数据转化为二维矩阵并对其进行奇异值分解
img_temp = img_eg.reshape(400, 640 * 3)
U,Sigma,VT = np.linalg.svd(img_temp)
# 取前10个奇异值
sval_nums = 10
img_restruct1 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
img_restruct1 = img_restruct1.reshape(400,640,3)
img_restruct1.tolist()
# 取前50个奇异值
sval_nums = 50
img_restruct2 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
img_restruct2 = img_restruct2.reshape(400,640,3)
# 取前100个奇异值
sval_nums = 100
img_restruct3 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
img_restruct3 = img_restruct3.reshape(400,640,3)
#展示
fig, ax = plt.subplots(nrows=1, ncols=3)
ax[0].imshow(img_restruct1.astype(np.uint8))
ax[0].set(title = "10")
ax[1].imshow(img_restruct2.astype(np.uint8))
ax[1].set(title = "50")
ax[2].imshow(img_restruct3.astype(np.uint8))
ax[2].set(title = "100")
plt.show()
运行结果:
可以看到,取前50或100个特征值即可较好的重构图片,相对于原来的图片(400个特征值)节约了大量空间。
利用SVD分解求超定方程的解
于是对于齐次线性方程,如果列满秩且,则该方程组为超定方程组(有效方程个数大于未知参数的个数的方程)。此时的方程组没有精确解,需要求解最小二乘解。在的约束条件下下,其最小二乘解为矩阵的最小特征值所对应的特征向量,根据。
下面我们来以这个思路求解一个非常简单的超定方程组:
首先,我们将这个方程组化简为的格式:
下面是代码:
import numpy as np
#输入系数矩阵A
A = np.array([[2,4,-11],[3,-5,-3],[1,2,-6],[2,1,-7]])
#对A进行svd分解
U,Sigma,VT = np.linalg.svd(A)
#print(U)
#print(Sigma)
#print(VT)
#求解,V的列向量即是ATA的特征向量
#VT最后一行的行向量即为最小特征值对应的特征向量
#由于x[3,0]=1,所以需要对结果进行处理
k=1/ VT[2,2]
x_1=VT[2,0]*k
x_2=VT[2,1]*k
print(x_1,x_2)
#误差
X=np.array([[x_1],[x_2],[1]])
R=np.dot(np.transpose(np.dot(A,X)),(np.dot(A,X)))
print (R)
运行结果:
解得最小二乘解为,误差平方和 。