信息检索中的特征空间变化

本文介绍了信息检索中高维向量空间模型的问题及特征空间变化的重要性。讲解了奇异值分解(SVD)的基本原理,它能用于矩阵降维和特征提取。还提到了LDA等其他降维方法,通过将文档映射到低维潜在语义空间来改善相似度计算。
摘要由CSDN通过智能技术生成

一、背景及概述

    对于一篇文章或者是一段文字信息,我们想要获取其中的关键信息,如果是中文,我们首先要对其进行分词的预处理,中文分词有很多开源的技术,如python就有结巴模块用来做中文分词,网上有很多博客详细讲解,这边不是我们这部分工作的重点内容,在这里就不详细讲解了。(关于python中结巴分词)通过对连续的语义的分词我们会得到由多个独立词语构成的信息,这里就需要合适的信息检索模型,来判断两个不同的文章或语句信息之间的相似程度了,常用的信息检索模型分为三类,集合论模型,代数模型以及概率模型。以代数模型为例,向量空间模型是代数模型的一种,这种模型是将文档表示成空间向量,通过计算向量之间的余弦相似度来比较两篇文档之间的相关程度,然而这种模型建立出来的空间向量维度十分高,最简单的向量空间模型中,加入词典的大小为N维,那么一篇文档的向量也是N维,M篇文章就会构成一个M*N维度的矩阵,但是在在这个矩阵中又有很多值为0的特征,非常冗余;因此可想而知,用如此高纬度的向量计算是多么麻烦。在这类问题的基础上,在信息检索的领域内,我们需要做一些特征空间的变化,来简化运算以及提高效率,并且实验也证明,通过一定的特征空间变化之后得到的效果要优于直接运算。

二、特征空间变化主要方法简介

    常用的特征空间变化有,奇异值分解SVD,隐语义分析LSA,PLSA主题模型,LDA主题模型。

    简单介绍一下,奇异值分解是线性代数中一种重要的矩阵分解

    矩阵A可以理解为我们的M个信息段构成的M*N的矩阵,对于矩阵U是一个M*M的矩阵,这个矩阵中所有的向量是正交的,Σ是一个N*M的矩阵,而且还是个对角阵,即除了对角线上的元素都为0;V'是一个N*N的矩阵,里面的向量也都是正交的。我们可以将Σ理解成奇异值矩阵,其对角线上的每一个元素是奇异值,并且在这个矩阵中对角线上的元素是按照奇异值的大小排列的,同时,前百分之十以内的奇异值在整个运算中占的比重几乎是全部,因此我们可以用前r个奇异值和两个正交矩阵的相乘结果来近似原本的矩阵


    易理解,r越接近N,则相乘的结果越接近于A。由此可见,SVD可以用来作为特征提取的方法,机器学习中的PCA主成分分析法就是用的这种方法。但是这种方法得到的特征是各个特征之间隐含的联系构成的新特征,这样的新特征不具备可解释性。

   隐语义分析LDA是一种潜在语义索引方法,一种新的信息检索代数模型,使用统计计算的方法对大量的文本集进行分析,从而提取出词与词之间潜在的语义结构,并用这种潜在的语义结构,来表示词和文本,达到消除词之间的相关性和简化文本向量实现降维的目的。

    基本观点是,把高维的向量空间模型(VSM)表示中的文档映射到低维的潜在语义空间中,映射是通过对文档矩阵进行奇异值分解来实现的,SVD得到Σ,只保留最大的k个奇异值得到Σ',进行奇异值分解的反运算,得到A的近似矩阵。基本步骤如下:

1、建立词频矩阵frequency matrix

2、计算frequency matrix的奇异值分解

3、对于每一个文档d,用排除了SVD中消除后的词的新向量替换原有的向量

4、用转换后的文档索引和相似度计算


    每个文档可以用三维的向量表示出来。LSA本质上识别了以文档为单位的多个单词并归入同一个子空间,在这个例子中,即为三维空间中相近的点(stock和market)在这一系列数据中存在着隐含的关系。

    后两种方法是对以上方法的改进,我做的项目中没有用到,这里就不做详细的解释,感兴趣的读者可以自行查询。

三、奇异值分解的实现

    参考链接:奇异值分解

# encoding=utf8  
import numpy as np  
from numpy import *  
from numpy import linalg as la  
from operator import itemgetter  
  
def loadExData():  
    return [[4,4,0,2,2],  
            [4,0,0,3,3],  
            [4,0,0,1,1],  
            [1,1,1,2,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]]  
   
def ReconstructSigma(Sigma):  
    return np.mat([[Sigma[0],0,0],[0,Sigma[1],0],[0,0,Sigma[2]]])  
  
def ReconstructData(U,Sigma,VT):  
    return U[:,:3]*Sigma*VT[:3,:]  
  
# 计算相似性函数  
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*np.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)  
''''' 
standEst 需要做的就是估计user 的item 评分, 
采用方法是  根据物品相似性,及每一列相似性 
要估计item那一列与其他列进行相似性估计,获得两列都不为0的元素计算相似性 
然后用相似性乘以 评分来估计未评分的数值 。 
'''  
def standEst(dataMat,user,simMeas,item):  
    n = np.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]# 返回元素不为0的下标  
        ''''' 
        nonzero 返回参考下面例子,返回二维数组,第一维是列方向,第二位是行方向 
        '''  
        if(len(overLap)) == 0 :similarity = 0  
        else:  
            similarity = simMeas(dataMat[overLap,item],dataMat[overLap,j])  
        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 recommend(dataMat,user ,N = 3,simMeas= cosSim,estMethod = standEst):  
    unratedItems = nonzero(dataMat[user,:].A == 0)[1]# .A 使得矩阵类型转为array  
    ''''' 
    >>> a = np.array([[1,2,3],[4,5,6],[7,8,9]]) 
    >>> a > 3 
    array([[False, False, False], 
       [ True,  True,  True], 
       [ True,  True,  True]], dtype=bool) 
    >>> np.nonzero(a > 3) 
    (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2])) 
    '''  
    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=itemgetter(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  
    print xformedItems  
    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  
      
if __name__=="__main__":  
    ''''' 
    # 测试中间数据 
    Data = loadExData() 
    MatData = np.mat(Data) 
    U,Sigma,VT = np.linalg.svd(Data) 
    print Sigma 
    Sigma = ReconstructSigma(Sigma) 
    print Sigma 
    print ReconstructData(U, Sigma, VT) 
    print eulidSim(MatData[:,0], MatData[:,4]) 
    print cosSim(MatData[:,0], MatData[:,4]) 
    print pearsSim(MatData[:,0], MatData[:,0]) 
    '''  
    Data = loadExData()  
    dataMat = np.mat(Data)  
    dataMat2 = mat(loadExData2())  
    print dataMat2  
    print recommend(dataMat2, 1,estMethod=svdEst)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值