Machine Learning in Action – PCA和SVD

降维技术, 
首先举的例子觉得很好,因为不知不觉中天天都在做着降维的工作

对于显示器显示一个图片是通过像素点0,1,比如对于分辨率1024×768的显示器,就需要1024×768个像素点的0,1来表示,这里每个像素点都是一维,即是个1024×768维的数据。而其实眼睛真正看到的只是一副二维的图片,这里眼睛其实在不知不觉中做了降维的工作,把1024×768维的数据降到2维

降维的好处,显而易见,数据更易于显示和使用,去噪音,减少计算量,更容易理解数据 
主流的降维技术,包含: 
主成分分析,principal component analysis(PCA) 
因子分析,factor analysis 
独立成分分析,independent component nalysis (ICA)

这些技术参考NG的课程笔记,这里给出PCA的python实现

PCA的实现很简单,求协方差矩阵的特征值和特征向量,并取特征值top的那些特征向量作为新的坐标轴(原因参考NG讲义)

from numpy import *
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  #Normalization
    covMat = cov(meanRemoved, rowvar=0) #生成协方差矩阵
    eigVals,eigVects = linalg.eig(mat(covMat)) #求解协方差矩阵的特征值,特征向量
    eigValInd = argsort(eigVals)
    eigValInd = eigValInd[:-(topNfeat+1):-1] #选取top特征值
    redEigVects = eigVects[:,eigValInd] #找到对应的特征向量
    lowDDataMat = meanRemoved * redEigVects #用特征向量生成新的数据
    reconMat = (lowDDataMat * redEigVects.T) + meanVals #为了调试恢复原始数据
    return lowDDataMat, reconMat

至于topNfeat取值,即选取多少个top的特征值,其实看到实际数据就可以决定,因为往往从某个特征值开始会和前面的相差几个数量级

比如底下的例子,

 

参考NG的讲义,对于高维的数据,算出协方差矩阵本身就是很耗的,所以其实可以用SVD分解来进行PCA,当然这个只是SVD的一个用法

但是理解singular value decomposition (SVD)还是看看SVD最经典的应用latent semantic indexing (LSI) 
文档是由词组成,所以在比较文章的相似性时,比如分类或聚类时,会以词作为特征 
这样的问题是,无法处理同义词,比如learn和study,或拼错的词

而如果此时对于m篇文章,n个词的矩阵做奇异值分解,就可以自动将词和文章进行分类

并将维数从词数降到分类树,即从n降到r

听上去很神奇,其实原理和PCA是一样的,因为SVD分解后 
U是 的特征向量(eigenvector)矩阵,而 是词之间的协方差矩阵 
并且U是m×r而不是m×n,已经进行了降维,U是取top r的特征向量,和PCA的过程是一样的 
所以看上去是给词做了分类,其实只是将坐标轴旋转到特征向量,并取top进行降维

同理V是DataT*Data的特征向量矩阵,而DataT*Data是文本之间的协方差矩阵

所有SVD分解后,得到

U,每行表示该文本和每个词类的关系 
V,每行表示该词和每个文本类的关系 
奇异矩阵,表示词类和文本类之间的关系

个人理解,SVD其实是在自变量x和因变量y上同时进行了PCA降维 
而普通PCA只是会降低x的维度 
比如上面的例子,同时对于词和文章,进行特征向量的旋转和降维,得到词类和文章类

现在SVD分解更多的用在推荐系统,推荐系统最经典的就是协同过滤(Collaborative filtering),item-base或user-base 
用SVD可以达到更有效的推荐的效果 
比如底下是用户对各个菜评分表,0表示没吃过

如果对这个做SVD分解,会得到两个奇异值 
你会发现可以分别对应到美食BBQ和日式食品两类食品上 
同时得到的结论,一拨人喜欢美食BBQ, 一拨人喜欢日式食品,这样推荐就很简单

python中实现svd很简单,有现成的函数,

输入,

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]]

SVD分解,

>>> import svdRec
>>> Data=svdRec.loadExData()
>>> U,Sigma,VT=linalg.svd(Data)
>>> Sigma
array([ 9.72140007e+00, 5.29397912e+00, 6.84226362e-01,
7.16251492e-16, 4.85169600e-32])

可以看到奇异值中,最后两个的量级很小,可以忽略,所以取前3个值

所以r=3,做下面的近似

重新构造一个3×3的奇异矩阵,

>>> Sig3=mat([[Sigma[0], 0, 0],[0, Sigma[1], 0], [0, 0, Sigma[2]]])

截取特征值,产生新的数据,这步只是为了验证确实是能得到近似结果

>>> U[:,:3]*Sig3*VT[:3,:]
    array([[ 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.]])

 

下面实际看个推荐的例子,

经典的item-based的协同过滤,

#计算user和item之间的相似度
#simMeas,给出相似度计算方法,比如欧几里德距离,pearson相关系数,余弦法
def standEst(dataMat, user, simMeas, item):
    n = shape(dataMat)[1]
    simTotal = 0.0; ratSimTotal = 0.0
    for j in range(n): #遍历所有的item
        userRating = dataMat[user,j]
        if userRating == 0: continue #如果这个item,user没有评过,没有相关性
        #找出item和j都有评论的user的index
        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]) #算出item和j的相似度
        #print 'the %d and %d similarity is: %f' % (item, j, similarity)
        simTotal += similarity
        ratSimTotal += similarity * userRating #加权,因为每个item用户的rating是不一样的
    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: #找出每个item和user的关系
        estimatedScore = estMethod(dataMat, user, simMeas, item)
        itemScores.append((item, estimatedScore))
    return sorted(itemScores,key=lambda jj: jj[1], reverse=True)[:N] #取出topN,最相关的

其中求overLap的逻辑比较晦涩,

其中dataMat[:,item].A,找出item列,因为是matrix,用.A转成array

logical_and,其实就是找出最item列和j列都>0,只有都大于0才会是true

nonzero会给出其中不为0的index,对于二维的

>>> b2 = np.array([[True, False, True], [True, False, False]])
>>> np.nonzero(b2)
    (array([0, 0, 1]), array([0, 2, 0]))

所以知道b2[0,0]、b[0,2]和b2[1,0]的值不为0

最终取[0],即取出user的index,哪些user同时评了item和j

因为是item-based,所以比较item的时候,维度就取决于user的个数,如果user很多,计算起来就比较麻烦

所以这里可以用SVD来降维,

比如对如下的数据,

进行SVD分解,

>>>from numpy import linalg as la
>>> U,Sigma,VT=la.svd(mat(svdRec.loadExData2()))
>>> Sigma
array([ 1.38487021e+01, 1.15944583e+01, 1.10219767e+01,
        5.31737732e+00, 4.55477815e+00, 2.69935136e+00,
        1.53799905e+00, 6.46087828e-01, 4.45444850e-01,
        9.86019201e-02, 9.96558169e-17])

如何决定r?有个定量的方法是看多少个奇异值可以达到90%的能量

其实和PCA一样,由于奇异值其实是等于data×dataT特征值的平方根,所以总能量就是特征值的和

>>> Sig2=Sigma**2
>>> sum(Sig2)
541.99999999999932

而取到前4个时,发现超过90%,所以r=4

>>> sum(Sig2[:3])
500.50028912757909

所以SVD分解的版本的关键不同在于,降低了user的纬度,从n变为4

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]) #重构奇异矩阵
    xformedItems = dataMat.T * U[:,:4] * Sig4.I #构造item和user类的关系
    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

其中关键一步,

dataMat.T * U[:,:4] * Sig4.I

将dataMat基于特征向量旋转,再用特征值缩放,所以dataMat,m×n,转换为n×4的item和user类的矩阵

 

最后一个SVD的应用是图像压缩,

对于32×32,1024个像素的图片,进行SVD分解,如果取top 2的特征值,最终只需要保存32×2×2 +2 一共130个byte,比1024小了10倍

本文章摘自博客园,原文发布日期: 2014-10-09

时间: 2024-08-29 22:25:06

Machine Learning in Action – PCA和SVD的相关文章

Machine Learning in Action -- 回归

机器学习问题分为分类和回归问题  回归问题,就是预测连续型数值,而不像分类问题,是预测离散的类别 至于这类问题为何称为回归regression,应该就是约定俗成,你也解释不通  比如为何logistic regression叫逻辑回归,明明解决的是分类问题,而且和逻辑没有半点关系 谈到回归,最简单的就是线性回归 用直线去拟合数据点, 我们通常用平方误差来作为目标函数,称为最小二乘(ordinary least squares),参考AndrewNG的讲义 如何解这个问题,可以用梯度下降,但其实更

机器学习实战(Machine Learning in Action)笔记--Chapter1:机器学习基础

Part1 分类 监督学习一般使用两种类型的目标变量:标称型(主要用于分类).数值型(主要用于回归). 非均衡分类问题 第1章 机器学习基础 专家系统 训练样本.特征.目标变量(分类问题中为类别) 训练数据和测试数据 知识表示 监督学习:分类.回归 无监督学习 将数据集合分成由类似的对象组成的多个类的过程被称为聚类 将寻找描述数据统计值的过程称之为密度估计 监督学习的用途:k-近邻算法.朴素贝叶斯算法.支持向量机.决策树.线性回归.局部加权线性回归.Ridge回归.Lasso最小回归系数估计 无

Machine Learning in Action -- Support Vector Machines

虽然SVM本身算法理论,水比较深,很难懂 但是基本原理却非常直观易懂,就是找到与训练集中支持向量有最大间隔的超平面 形式化的描述: 其中需要满足m个约束条件,m为数据集大小,即数据集中的每个数据点function margin都是>=1,因为之前假设所有支持向量,即离超平面最近的点,的function margin为1 对于这种有约束条件的最优化问题,用拉格朗日定理,于是得到如下的形式, 现在我们的目的就是求出最优化的m个拉格朗日算子,因为通过他们我们可以间接的算出w和b,从而得到最优超平面 考

Machine Learning in Action -- AdaBoost

初始的想法就是,结合不同的分类算法来给出综合的结果,会比较准确一些  称为ensemble methods or meta-algorithms,集成方法或元算法 集成方法有很多种,可以是不同算法之间的,也可以是同一个算法但不同参数设置之间的,也可以是将数据集分成多分给不同的分类器之间的  总的来说,有3个维度可以进行集成,算法,算法参数和数据集 下面简单介绍两种比较流行的元算法思路, 1. Building classifiers from randomly resampled data: b

Machine Learning in Action -- Logistic regression

这个系列,重点关注如何实现,至于算法基础,参考Andrew的公开课 相较于线性回归,logistic回归更适合用于分类 因为他使用Sigmoid函数,因为分类的取值是0,1 对于分类,最完美和自然的函数,当然是Heaviside step function,即0-1阶跃函数,但是这个函数中数学上有时候比较难处理 所以用Sigmoid函数来近似模拟阶跃函数, 可以看到Sigmoid在增大坐标尺度后,已经比较接近于阶跃函数 其中, 而logistic回归就是要根据训练集找到,最优的w向量 下面就通过

Machine Learning in Action -- FP-growth

要解决的问题,频繁项集 最暴力的方法,就是遍历所有的项集组合,当然计算量过大  最典型的算法apriori, 算法核心思想,当一个集合不是频繁项集,那么它的超集也一定不是频繁项集  这个结论是很明显的,基于这样的思路,可以大大减少频繁项集的候选项  因为你只要发现一个集合非频繁项集,那么他所有的超集都可以忽略 但apriori算法的问题是,计算每个候选项的出现频率的时候都需要遍历整个数据集,这个明显是低效的  很自然的想法,就是否有办法可以尽量少的遍历数据集?比如遍历一遍就可以得到所有的项集的出

Mapreduce for Machine Learning

MapReduce for Machine Learning Baofeng Zhang 369447122@qq.com  转载请注明出处:http://blog.csdn.net/zbf8441372   Abstract We are at the beginning of the multicoreera. Computers will have increasingly many cores (processors), but there isstill no good program

Learning Machine Learning, Part 2: Algorithms and Techniques

The previous blog post, Introduction to Machine Learning, presented the Machine Learning concept. Now, let's discuss representative methods used in the technology. Regression Algorithms In most Machine Learning courses, regression algorithms are the

Learning Machine Learning, Part 3: Application

This post features a basic introduction to machine learning (ML). You don't need any prior knowledge about ML to get the best out of this article. Before getting started, let's address this question: "Is ML so important that I really need to read thi