机器学习--主成分分析(PCA)算法的原理及优缺点

1、PCA算法的原理算法

  PCA(principle component analysis),即主成分分析法,是一个非监督的机器学习算法,是一种用于探索高维数据结构的技术,主要用于对数据的降维,经过降维能够发现更便于人理解的特征,加快对样本有价值信息的处理速度,此外还能够应用于可视化(降到二维)和去噪。
数据结构

  PCA本质上是将方差最大的方向做为主要特征,而且在各个正交方向上将数据“离相关”,也就是让它们在不一样正交方向上没有相关性。dom

                                      

  求解思路:用方差来定义样本的间距,方差越大表示样本分布越稀疏,方差越小表示样本分布越密集。机器学习

  方差的公式以下:函数

      

 

    在求解最大方差前,为了方便计算,能够先对样本进行demean(去均值)处理,即减去每一个特征的均值,这种处理方式不会改变样本的相对分布(效果就像坐标轴进行了移动)。去均值后,样本x每一个特征维度上的均值都是0,方差的公式转换下图的公式:学习

                                                                                                     在这里,表明已经通过映射后的某样本。spa

    对于只有2个维度的样本,如今的目标就是:求一个轴的方向w=(w1,w2),使得映射到w方向后,方差最大。3d

    目标函数表示以下:code

          

    为求解此问题,须要使用梯度上升算法,梯度的求解公式以下:component

                                        

    PCA算法流程:   

    (1)去平均值,即每一位特征减去各自的平均值;

    (2)计算协方差矩阵;

    (3)计算协方差矩阵的特征值与特征向量;

    (4)对特征值从大到小排序;

    (5)保留最大的个特征向量;

    (6)将数据转换到个特征向量构建的新空间中。

  PCA降维准则:

    (1) 最近重构性:样本集中全部点,重构后的点距离原来的点的偏差之和最小。

    (2) 最大可分性:样本在低维空间的投影尽量分开。

  PCA算法优势:

    (1)使得数据集更易使用;

    (2)下降算法的计算开销;

    (3)去除噪声;

    (4)使得结果容易理解;

    (5)彻底无参数限制。

  PCA算法缺点:

    (1)若是用户对观测对象有必定的先验知识,掌握了数据的一些特征,却没法经过参数化等方法对处理过程进行干预,可能会得不到预期的效果,效率也不高;

    (2) 特征值分解有一些局限性,好比变换的矩阵必须是方阵;

    (3) 在非高斯分布状况下,PCA方法得出的主元可能并非最优的。

  PCA算法应用:

    (1)高维数据集的探索与可视化。

    (2)数据压缩。

    (3)数据预处理。

    (4)图象、语音、通讯的分析处理。

    (5)降维(最主要),去除数据冗余与噪声。

2、代码实现

  1.本身实现的PCA算法

import numpy as np
import matplotlib.pyplot as plt

X=np.empty((100,2))
X[:,0]=np.random.uniform(0,100,size=100)
X[:,1]=0.75*X[:,0]+3+np.random.normal(0,10,size=100)
plt.scatter(X[:,0],X[:,1])

def demean(X):
    return X-np.mean(X,axis=0)
X_demean=demean(X)
plt.figure(2)
plt.scatter(X_demean[:,0],X_demean[:,1])
#print(np.mean(X[:,0]))
#print(np.mean(X_deman[:,0]))
#print(np.mean(X_deman[:,1]))

def f(w,X):
    return np.sum((X.dot(w)**2))/len(X)

def df_math(w,X):
    return X.T.dot(X.dot(w))*2/len(X)
 
def direction(w):
    return w / np.linalg.norm(w)
    
def gradient_ascent(df, X, initial_w, eta, n_iters = 1e4, epsilon=1e-8):
    
    w = direction(initial_w) 
    cur_iter = 0

    while cur_iter < n_iters:
        gradient = df(w, X)
        last_w = w
        w = w + eta * gradient
        w = direction(w) # 注意1:每次求一个单位方向
        if(abs(f(w, X) - f(last_w, X)) < epsilon):
            break
            
        cur_iter += 1

    return w

initial_w = np.random.random(X.shape[1]) # 注意2:不能用0向量开始
eta = 0.001
w = gradient_ascent(df_math, X_demean, initial_w, eta)
plt.figure(3)
plt.scatter(X_demean[:,0], X_demean[:,1])
#plt.plot([0, w[0]*30], [0, w[1]*30], color='r')
plt.plot([0, w[0]*50], [0 , w[1]*50], color='r')

 

 输出结果:

相关文章
相关标签/搜索