在LSI中,一个矩阵是由文档和词语组成的。当我们在该矩阵上应用SVD时,就会构建出多个奇异值。这些奇异值代表了文档中的概念或主题,这一特点可以用于更高效的文档搜索。在词语拼写错误时,只基于词语存在与否的简单搜索方法会遇到问题。简单搜索的另一个问题就是同义词的使用。这就是说,当我们查找一个词时,其同义词所在的文档可能并不会匹配上。如果我们从上千篇相似的文档中抽取出概念,那么同义词就会映射为同一概念。
SVD的另一个应用就是推荐系统。简单版本的推荐系统能够计算项或者人之间的相似度。更先进的方法则先利用SVD从数据中构建一个主题空间,然后再在该空间下计算其相似度。
矩阵Σ,该矩阵只有对角元素,其他元素均为0(近似于0)。另一个惯例
就是,Σ的对角元素是从大到小排列的。这些对角元素称为奇异值
奇异值与特征值(PCA 数据中重要特征)是有关系的。这里的奇异值就是矩阵 D a t a ∗ D a t a T Data * Data^T Data∗DataT特征值的平方根
普遍的事实:在某个奇异值的数目(r个 = > => =>奇异值的平方和累加到总值的90%以上)之后,其他的奇异值都置为0(近似于0)。这意味着数据集中仅有r个重要特征,而其余特征则都是噪声或冗余特征
NumPy有一个称为linalg的线性代数工具箱,可以直接对矩阵进行奇异值分解:
import numpy as np
U,Sigma,VT = np.linalg.svd([[1,1],[7,7]])
def euclidsim(inA, inB):
return 1.0 / (1.0 + np.linalg.norm(inA - inB))
def pearsSim(inA, inB):
if len(inA) < 3:
return 1.0
return 0.5 + 0.5 * np.corrcoef(inA, inB, rowvar=False)[0][1]
def cosSim(inA, inB):
num = float(inA.T * inB)
denom = np.linalg.norm(inA) * np.linalg.norm(inB)
return 0.5 + 0.5 * (num / denom)
python代码
def standEst(dataMat, user, simMeans, item):
col = np.shape(dataMat)[1]
simTotal = 0.0
ratSimTotal = 0.0
for j in range(col):
userRating = dataMat[user, j]
if userRating == 0:
continue
overLap = np.nonzero(np.logical_and(dataMat[:, item].A > 0, dataMat[:, j].A > 0))[0]
if len(overLap) == 0:
similarity = 0
else:
similarity = simMeans(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, simMeans=cosSim, estMethod=standEst):
unratedItems = np.nonzero(dataMat[user, :].A == 0)[1]
if len(unratedItems) == 0:
return 'you rated everything'
itemScores = []
for item in unratedItems:
estimateScore = estMethod(dataMat, user, simMeans, item)
itemScores.append((item, estimateScore))
return sorted(itemScores, key=lambda jj: jj[1], reverse=True)[:N]
def svdEst(dataMat, user, simMeas, item):
col = np.shape(dataMat)[1]
simTotal = 0.0
ratSimTotal = 0.0
U, Sigma, VT = np.linalg.svd(dataMat)
Sig5 = np.mat(np.eye(5) * Sigma[:5])
xformedItems = dataMat.T * U[:, :5] * Sig5.I
for j in range(col):
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