SVD算法

为什么这么难……这么难……

#encoding:utf-8
import numpy as np
from numpy import *
from numpy import linalg as la

def loadExData():
    return[[0, 0, 0, 2, 2],
           [0, 0, 0, 3, 3],
           [0, 0, 0, 1, 1],
           [1, 1, 1, 0, 0],
           [2, 2, 2, 0, 0],
           [1, 1, 1, 0, 0],
           [5, 5, 5, 0, 0]]

def loadExData2():
    return[[0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5],
           [0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 3],
           [0, 0, 0, 0, 4, 0, 0, 1, 0, 4, 0],
           [3, 3, 4, 0, 0, 0, 0, 2, 2, 0, 0],
           [5, 4, 5, 0, 0, 0, 0, 5, 5, 0, 0],
           [0, 0, 0, 0, 5, 0, 1, 0, 0, 5, 0],
           [4, 3, 4, 0, 0, 0, 0, 5, 5, 0, 1],
           [0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 4],
           [0, 0, 0, 2, 0, 2, 5, 0, 0, 1, 2],
           [0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0],
           [1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0]]
'''相似度计算'''
'''1.欧式距离计算法'''
def euclidSim(inA, inB):
    return 1.0/(1.0 + la.norm(inA-inB))#归一化处理到0-1之间
'''2.皮尔逊相关系数计算法'''
def pearSim(inA, inB):
    if len(inA) < 3: return 1.0
    return 0.5+0.5*corrcoef(inA, inB,rowvar = 0)[0][1]#原本皮尔逊相关系数取值范围(-1, 1),归一化处理到0-1之间
'''3.余弦相似度计算法'''
def cosSim(inA, inB):
    num = float(inA.T*inB)
    denom = la.norm(inA)*la.norm(inB)
    return 0.5+0.5*(num/denom)#原本余弦范围(-1, 1),归一化处理到0-1之间
'''基于物品相似度的推荐引擎'''
def standEst(dataMat,user, simMeas, item):
    n = shape(dataMat)[1]
    simTolal = 0.0#累计相似度
    ratSimTotal = 0.0#累计评分
    for j in range(n):
        uesrRating = dataMat[user,j]
        if uesrRating==0: continue
        '''就是根据所有用户对商品j和item相似度来估计打分'''
        overLap = nonzero(logical_and(dataMat[:, j]>0, dataMat[:,item] > 0))[0]
        if len(overLap) == 0: similarity = 0
        else:
            similarity = simMeas(dataMat[overLap, item],dataMat[overLap, j])
        simTolal+=similarity
        ratSimTotal += similarity * uesrRating
    if simTolal == 0: return 0.0
    else :return ratSimTotal/simTolal#通过除以所有评分总和,对上述相似度评分进行乘积的归一化、
'---基于SVD评分估计---'
def svdEst(dataMat,user, simMeas, item): 
    n = shape(dataMat)[1]
    simTotal=0.0;rateSimTotal = 0.0
    U,Sigma,VT = la.svd(dataMat)
    sig4 = mat(eye(4)*Sigma[:4])#建立对角矩阵
    xformedItems = dataMat.T*U[:,:4]*sig4.I#说实话这一步我不明白机器学习实战作者是如何将高维转化到低维的空间
    for j in range(n):
        userating=dataMat[user,j]
        if userating ==0.0 or j == item: continue
        similarity = simMeas(xformedItems[j,:].T, xformedItems[item, :].T)
        simTotal += similarity
        rateSimTotal += similarity*userating  
    if simTotal == 0: return 0
    else: return rateSimTotal/simTotal       
'''推荐系统    推荐用户没用过的商品  通过对商品得分的估计来推荐前N个'''
#datMat数据集 user用户 N 推荐个数 simMeas 相似比较方法  estMethod 评价的方法(传统相似度和SVD降维再比较)
def recommend(dataMat, user, N = 3, simMeas=cosSim, estMethod = standEst):
    unratedItems = nonzero(dataMat[user,:].A == 0)[1]
    if len(unratedItems) == 0: #如果没有 没评价的
        return 'you rated everything'
    itemSocre=[]

    for item in unratedItems:#对每个没评价的进行打分
        estimateSocre = estMethod(dataMat,user, simMeas, item)
        itemSocre.append((item,estimateSocre))
    return sorted(itemSocre, key=lambda jj:jj[1], reverse=True)[:N]
'''对图形进行压缩'''
#打印图形函数    32*32的图像
def printMat(inMat, thresh = 0.8):
    for i in range(32):
        for j in range(32):
            if float(inMat[i,j] > thresh):
                print 1,
            else:
                print 0,
        print ''
#压缩图形函数

def imgCompress(numSV = 3,thresh = 0.8 ):
    myl=[]
    for line in open('0_5.txt'):
        newRow = []
        for i in range(32):
            newRow.append(int(line[i]))

        myl.append(newRow)
    mydat = mat(myl)
    print "-------original matrix------"
    printMat(mydat,thresh)
    U,Sigma, VT = la.svd(mydat)
    SigRecon = mat(eye(numSV)*Sigma[:numSV])

    reconMat =U[:,:numSV]*SigRecon*VT[:numSV, :]
    print '-------reconstructed matrix using %d singular values----------' % numSV
    '''U vT 都是32*2的矩阵,有两个奇异值。因此总数子数目就是64+64+2=130 原本是需要存32*32=1024  我们压缩了近10倍
    虽然压缩后图形与有差别,但是很接近了。终于体会到SVD的好处了,这就是数学的力量。哇 我好垃圾
    '''

    printMat(reconMat,thresh)
    return
if __name__ == '__main__':
#     dataMat = mat(loadExData())   
#     print euclidSim(dataMat[:,0],dataMat[:,4])
#     print pearSim(dataMat[:,0],dataMat[:,4])
#     print cosSim(dataMat[:,0],dataMat[:,4])
#     print '---基于物品相似度的推荐引擎---'
#     dataMat[0,1] = dataMat[0,0] = dataMat[1,0] = dataMat[2,0] = 4
#     dataMat[3,3] = 2
#     print dataMat
#     print recommend(dataMat, 2)
#     print 'SVD评分估计'
#     datMat = mat(loadExData2())
#     print datMat
#     print recommend(datMat, 1,estMethod=svdEst)
    print"----------压缩图像-----------"
    imgCompress(numSV = 3,thresh = 0.8 )




<think>好的,我现在需要回答用户关于奇异值分解(SVD算法实现与应用的问题。首先,我得先回忆SVD的基本概念,确保自己理解正确。根据用户提供的引用,SVD是将矩阵分解为三个矩阵的乘积:U、Σ和V^T。其中U和V是正交矩阵,Σ是对角矩阵,对角线上的元素是奇异值。引用[4]提到,任何m×n的矩阵都可以这样分解,而引用[5]则区分了完全、紧和截断三种SVD形式。 接下来,用户想知道实现方法。我需要考虑不同的编程语言,比如Python,因为用户示例中的快速排序用了Python。Python中NumPy和SciPy库有现成的SVD实现,比如numpy.linalg.svd。需要说明如何使用这些函数,并指出不同模式的区别,比如全矩阵、经济模式等。同时,用户提供的引用[2]提到截断SVD可以提升计算效率,所以可能还需要提到像scikit-learn的TruncatedSVD。 然后是应用部分。根据引用[3],SVD用于协同过滤,比如推荐系统。另外,引用[2]和[1]提到了降维和数学建模中的应用。常见的应用还有图像压缩、去噪、自然语言处理中的潜在语义分析(LSA)等。需要分点列举这些应用,并结合引用中的例子。 用户可能还希望了解理论基础,比如奇异值的意义,或者分解后的矩阵如何解释。但问题主要关注实现和应用,所以需要保持重点。要注意使用正确的LaTeX格式,比如矩阵分解公式用$$...$$,行内变量用$...$。 还要生成相关问题。根据用户示例,可能需要关于优化、不同分解的区别、实际应用案例等问题。例如,截断SVD如何选择k值,或者SVD与PCA的关系等。 需要检查引用是否正确对应。例如,引用[3]提到协同过滤和分解算法,引用[2]讨论降维时的截断处理,引用[5]说明分解类型。确保每个引用的位置合适,比如在讲应用时引用[3],在讲实现效率时引用[2]。 最后,确保回答结构清晰,分步骤或分点,代码示例正确,并且中文表达流畅。避免技术错误,比如混淆特征值分解和SVD,或者错误解释矩阵的维度。可能还需要提到SVD的数学性质,比如奇异值与矩阵的秩、低秩近似的关系。</think>### 奇异值分解(SVD算法实现与应用 #### 1. **算法原理** 奇异值分解(SVD)是线性代数中一种重要的矩阵分解方法,可将任意$m \times n$的矩阵$A$分解为三个矩阵的乘积: $$A = U \Sigma V^T$$ - **$U$**: $m \times m$的正交矩阵,列向量为左奇异向量 - **$\Sigma$**: $m \times n$的对角矩阵,对角元素为非负奇异值(按降序排列) - **$V^T$**: $n \times n$的正交矩阵的转置,列向量为右奇异向量 根据需求,SVD可分为三种形式[^5]: - **完全SVD**:保留所有奇异值(计算成本高) - **紧SVD**:仅保留非零奇异值(保持原矩阵秩) - **截断SVD**:仅保留前$k$个最大奇异值(用于降维,提升效率)[^2] --- #### 2. **算法实现** ##### Python示例(使用NumPy): ```python import numpy as np # 生成随机矩阵 A = np.random.rand(5, 3) # 完全SVD分解 U, S, VT = np.linalg.svd(A, full_matrices=True) # 截断SVD(保留前2个奇异值) k = 2 U_trunc = U[:, :k] S_trunc = S[:k] VT_trunc = VT[:k, :] # 重构近似矩阵 A_approx = U_trunc @ np.diag(S_trunc) @ VT_trunc ``` - **关键参数**:`full_matrices`控制是否生成完全正交矩阵 - **优化库**:对于大规模数据,推荐使用`scipy.sparse.linalg.svds`或`sklearn.decomposition.TruncatedSVD` --- #### 3. **核心应用场景** 1. **数据降维** 通过截断SVD保留主要特征,减少计算复杂度[^2],例如图像压缩(保留95%能量对应的奇异值)。 2. **推荐系统** 协同过滤中分解用户-物品评分矩阵,预测缺失值(如Netflix推荐算法)[^3]。 3. **自然语言处理** 潜在语义分析(LSA)中,用SVD分解词-文档矩阵,捕捉语义关联。 4. **噪声过滤** 通过去除小奇异值对应的成分,消除数据中的噪声(如MRI图像去噪)。 --- #### 4. **实际案例解析** **案例:图像压缩** 将$512 \times 512$的灰度图像矩阵$A$进行截断SVD: - 原始数据量:$512 \times 512 = 262,144$像素 - 取$k=50$时:存储$U_{512 \times 50} + \Sigma_{50} + V^T_{50 \times 512} = 50 \times (512+512+1) = 51,250$,压缩率约80% ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值