【Python机器学习】利用SVD简化数据——示例:基于SVD的图像压缩
通过可视化的方式,我们可以很容易的看到SVD对数据近似的效果。在代码库中,有一张手写的数字图像。原始的图形大小是32*32=1024像素,我们可以尝试对图像进行压缩,那么就可以节省空间或带宽开销了。
我们可以使用SVD来对数据降维,从而实现图像的压缩。下面我们可以看到利用SVD的手写数字图像的压缩过程:
def printMat(inMat,thresh=0.8):for i in range(32):for k in range(32):if float(inMat[i,k])>thresh:print(1, end=' ')else:print(0, end=' ')print('')
def imgCompress(numSV=3,thresh=0.8):myl=[]for line in open('test/0_5.txt').readlines():newRow=[]for i in range(32):newRow.append(int(line[i]))myl.append(newRow)myMat=mat(myl)print('*****original matrix*****')printMat(myMat,thresh)U,Sigma,VT=la.svd(myMat)SigRecon=mat(zeros((numSV,numSV)))for k in range(numSV):SigRecon[k,k]=Sigma[k]reconMat=U[:,:numSV]*SigRecon*VT[:numSV,:]print('*****reconstruced matrix using %d singular values*****' % numSV)printMat(reconMat,thresh)
上述代码中第一个函数printMat()的作用是打印矩阵。由于矩阵包含了浮点数,因此必须定义浅色和深色。这里通过一个阈值来界定,后面也可以调节该值。该函数遍历所有的矩阵元素,当元素大于阈值时打印1,否则打印0。
第二个函数实现了图像的压缩。它允许基于任意给定的奇异值数目来重构图像。该函数构建了一个列表,然后打开文本文件,并从文件中以数值方式读入字符。在矩阵调入之后,我们就可以在屏幕上输出该矩阵了。接下来就开始对原始图像进行SVD分解并重构图像。在代码中,通过将Sigma重新构成SigRecon来实现这一点。Sigma是一个对角矩阵,因此需要建立一个全0矩阵,然后将前面的那些奇异值填充到对角线上,最后通过截断的U和矩阵,用SigRecon得到重构后的矩阵,该矩阵通过printMat()函数输出。
下面看实际运行效果:
可以看到,只需要两个奇异值就能相当准确地对图像实现重构。U和都是32*2的矩阵,有两个奇异值,因此总数字数目是64+64+2=130,和原数目1024相比,压缩比是接近10倍。