如何轻松干掉svd(矩阵奇异值分解),用代码说话

    svd我认识我机器学习里面最扯淡的玩意了。尼玛。老实说,好多机器学习的书老是在扯svd有多高端,然后看了netflix电影推荐大赛,哇塞,冠军队就是用svd+做的。然后狠狠的下载了所有他们的论文,硬是没看明白。后来居然对svd有恐惧感。感觉这个玩意好高端似的。你看他啊,它能提高预测精度,它好像是万能的,能降维,什么比赛有事没事都要扯扯svd。后来看Kaggle上的比赛,有个walmat仓储量预测大赛,也是对数据先用svd预处理。

    回去下载了好多svd论文看,搞了好久都没搞明白。他们都是说自己如何使用svd的。但是到底svd是个啥玩意,讲的就玄乎了。

   他把一个大的矩阵分解成了一些小矩阵相乘,如这博客里讲的:http://blog.csdn.net/wangran51/article/details/7408414

::::-------------------------分割线----------我所不喜欢的-------------------------------------------

  奇异值分解

上面讨论了方阵的分解,但是在LSA中,我们是要对Term-Document矩阵进行分解,很显然这个矩阵不是方阵。这时需要奇异值分解对Term-Document进行分解。奇异值分解的推理使用到了上面所讲的方阵的分解。

假设C是M x N矩阵,U是M x M矩阵,其中U的列为CCT的正交特征向量,V为N x N矩阵,其中V的列为CTC的正交特征向量,再假设r为C矩阵的秩,则存在奇异值分解:

clip_image020

其中CCT和CTC的特征值相同,为clip_image022

Σ为M X N,其中clip_image024clip_image026,其余位置数值为0,clip_image028的值按大小降序排列。以下是Σ的完整数学定义:

clip_image030

σi称为矩阵C的奇异值。

用C乘以其转置矩阵CT得:

clip_image032

上式正是在上节中讨论过的对称矩阵的分解。

奇异值分解的图形表示:

clip_image034

从图中可以看到Σ虽然为M x N矩阵,但从第N+1行到M行全为零,因此可以表示成N x N矩阵,又由于右式为矩阵相乘,因此U可以表示为M x N矩阵,VT可以表示为N x N矩阵

-------------------------分割线----------我找了好多资料,都是这样讲的。尼玛---------------------------------------------

我看这些玩意,我总感觉好高端啊,一个矩阵他就是把他分解成了这么多小矩阵,而且还保证这些小矩阵的乘积等于原来的矩阵。真是奇妙。这样要我用代码实现,怎么实现。

然后找了不少博客,都在瞎鸡巴扯svd可以放在推荐系统啦,U矩阵就是用户的特性啦,V矩阵就是电影的特性啦,好牛逼高端的,还可以用在自然语言处理中。

然并卵。一头雾水。

我想告诉大家。svd是一个任何大学本科生都会做的事情,你知道他干了什么吗?

下面 我给你们先轻松讲述,随后奉上python版代码:

当一个矩阵是方阵的时候,他是可以做特征分解的。就是线性代数里面老考的那玩意。拿个方阵你来求特征值特征向量啦,当他有n个线性无关的特征向量的时候,这个方阵就可以相似对角化为一个对角矩阵,如果

他的线性无关的特征向量少于n.他就只能规范化为约当块(jadom 块)。

那么,问题来了,什么是svd?

当一个矩阵A不是方阵的时候,你就不能将它对角化,但是:

A和A的转置特征值特征向量是一样的。这就有的玩了。我先求A*A的转置。假设求出来的矩阵是W,它绝对是一个方阵。那么好了,我求这个方阵的特征向量,然后对它做特征分解,将它化为一个对角矩阵。

那么A的特征值其实就是S特征值开根号。当然嘛。|A|就是等于特征值相乘的,|S|就是|A|的平方。而A和A的转置特征向量相同。那不就求出了svd分解里的对角阵么。

接下来求那写用户属性特征向量和电影属性特征向量。其实就是求S的特征向量,然后做点矩阵乘法就可以了。留点悬念,请看代码:

还是不吊大家胃口了。我这里清楚明白的告诉大家这个两个特征向量矩阵是个啥,首先,A*A的转置和A的转置* A两个所得的矩阵是不一样,由于A是m*n列的矩阵,那么A*A转置就是M*M的方阵,他的特征向量就是所谓的U矩阵,而A的转置 * A的特征向量组成的矩阵则是V矩阵。就这么回事。

 

from numpy import *
from numpy import linalg as la

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

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


def eulidSim(inA,inB):
    return 1.0/(1.0+la.norm(inA-inB))

def pearsSim(inA,inB):
    if len(inA) <3:return 1.0
    return 0.5 + 0.5*corrcoef(inA,inB,rowvar=0)[0][1]

def cosSim(inA,inB):
    num = float(inA.T*inB)
    denom = la.norm(inA)*la.norm(inB)
    return 0.5+0.5*(num/denom)
        
def standEst(dataMat,user,simMeas,item):
    n = shape(dataMat)[1]
    simTotal = 0.0;ratSimTotal = 0.0
    for j in range(n):
        userRating = dataMat[user,j]
        if userRating ==0:continue
        overLap = nonzero(logical_and(dataMat[:,item].A>0,
                                      dataMat[:,j].A >0))[0]
        if len(overLap) == 0:similarity =0
        else:similarity = simMeas(dataMat[overLap,item],dataMat[overLap,j])
        simTotal += similarity
        ratSimTotal += similarity*userRating
    if simTotal ==0:return 0
    else :return ratSimTotal/simTotal

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'
    itemScores = []
    for item in unratedItems:
        estimatedScore = estMethod(dataMat,user,simMeas,item)
        itemScores.append((item,estimatedScore))
    return sorted(itemScores,key=lambda jj:jj[1],reverse= True)[:N]

def svdEst(dataMat,user,simMeas,item):
    n =shape(dataMat)[1]
    simTotal = 0.0;ratSimTotal = 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):
        userRating = dataMat[user,j]
        if userRating ==0 or j==item:continue
        similarity = simMeas(xformedItems[item,:].T,xformedItems[j,:].T)
        print('the %d and %d similarity is :%f' % (item,j,similarity))
        simTotal += similarity
        ratSimTotal += similarity * userRating
        if simTotal == 0:return 0
        else:return ratSimTotal/simTotal
              
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):
    my1=[]
    for line in open('E:数据挖掘MLiA_SourceCodemachinelearninginactionCh14/0_5.txt').readlines():
        newRow = []
        for i in range(32):
            newRow.append(int(line[i]))
        my1.append(newRow)
    myMat = mat(my1)
    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 ('****reconstructed matrix using %d singular values****' % numSV)
    printMat(reconMat,thresh)

 

 

 

 

 

博上文章,均属原创,如需转载,请注明出处
原文地址:https://www.cnblogs.com/whu-zeng/p/4705970.html