PCA(Principal Component Analysis)主成分分析
PCA 可以从数据中识别其主要特征,它是通过沿着数据最大方差方向旋转坐标轴来实现的。选择方差最大的方向座位第一条坐标轴,后续坐标轴则与前面的坐标轴正交。协方差矩阵上的特征值分析可以用一系列的正交坐标轴来获取。
优点:降低数据的复杂性,识别最重要的几个特征
缺点:不一定需要,且可能损失有用信息
适用数据类型:数值型数据
步骤:
- 去除平均值
- 计算协方差矩阵
- 计算协方差矩阵的特征值和特征向量
- 将特征值从大到小排序
- 保留最上面的N个特征向量
- 将数据转换到上述N个特征向量构件的的新空间中
from numpy import *
import matplotlib
def loadDataSet(fileName, delim='\t'):
fr = open(fileName)
stringArr = [line.strip().split(delim) for line in fr.readlines()]
datArr = [map(float,line) for line in stringArr]
return mat(datArr)
def pca(dataMat, topNfeat=9999999):
meanVals = mean(dataMat, axis=0) #计算平均只
meanRemoved = dataMat - meanVals #去除平均值
covMat = cov(meanRemoved, rowvar=0) #计算协方差矩阵 rowvar=0代表样本为行向量
eigVals,eigVects = linalg.eig(mat(covMat)) #计算特征值,特征向量
eigValInd = argsort(eigVals) #特征值从小到大排序
eigValInd = eigValInd[:-(topNfeat+1):-1] #提取最大的几个特征值
redEigVects = eigVects[:,eigValInd] #提取最大特征值所对应的特征向量
lowDDataMat = meanRemoved * redEigVects #将原数据转换到低维空间上
reconMat = (lowDDataMat * redEigVects.T) + meanVals #重构原数据
return lowDDataMat, reconMat
SVD
优点: 简化数据,去除噪声,提高算法的结果
缺点: 数据的转换可能难以理解
适用数据类型: 数值型数据
SVD与推荐系统:
利用SVD实现item-based CF:
步骤:
- 构建物品用户数据矩阵
- 对数据矩阵进行SVD分解
- 提取最大的几个特征值
- 利用最大的几个特征值和特征向量构建低维空间上的物品矩阵
- 寻找目标用户未评分的物品
- 在低维空间上计算未评分物品与其它物品的相似度,再把相似度与评分值加权预测未评分物品的评分
- 按计算到的评分值从大到小排序,推荐前N个评分值高的给目标用户
from numpy import *
from numpy import linalg as la
def ecludSim(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 svdEst(dataMat, user, simMeas, item):
n = shape(dataMat)[1] #计算物品数
simTotal = 0.0; ratSimTotal = 0.0
U,Sigma,VT = la.svd(dataMat) #进行SVD分解
Sig4 = mat(eye(4)*Sigma[:4]) #提取前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 recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=svdEst):
unratedItems = nonzero(dataMat[user,:].A==0)[1] #寻找目标用户未被评分的物品
if len(unratedItems) == 0: return 'you rated everything'
itemScores = []
for item in unratedItems: #对每一个未被评分的物品利用svd计算评分值
estimatedScore = estMethod(dataMat, user, simMeas, item)
itemScores.append((item, estimatedScore))
return sorted(itemScores, key=lambda jj: jj[1], reverse=True)[:N] #按评分值排序,并且提取前N个。
SVD 是一种强大的降维工具,利用SVD来逼近矩阵,从中提取重要特征。通过保留矩阵80%-90% 的能量,就可以得到重要的特征并去除噪声。利用SVD实现,我们能够用小得多的数据集来表示原始数据集,可以节省空间。