美文网首页
2020-08-25--PCA降维01

2020-08-25--PCA降维01

作者: program_white | 来源:发表于2020-08-25 22:29 被阅读0次

    主要内容

    • PCA简介
    • 使用梯度上升法解决PCA问题

    1.PCA简介

    PCA(Principal Component Analysis : 主成分分析):也是一个梯度分析的应用,不仅是机器学习的算法,也是统计学的经典算法

    • 一个非监督的机器学习算法
    • 主要用于数据的降维
    • 通过降维,可以发现更便于人类理解的特征
    • 其他应用:可视化,去噪。

    1.1 PCA举例

    例如下面一个两个特征的一个训练集,我们可以选择一个特征,扔掉一个特征:

    下图分别是扔掉了特征一和特征二的两种方案,很明显右边这种的效果会更好一些,因为访问二扔掉特征二以后,点之间的分布情况更接近与原图,但是这不是更好的

    我们希望有一根直线,是斜着的,我们希望将所有的点都映射到这条直线上,那么这个时候我们就成功的将二维降到了一维,与此同时,这些点更加趋近与原来的点的分布情况。
    换句话说,点和点之间的距离比无论是映射到x还是映射到y周,他们之间的区分度都更加的大,也就更加容易区分。

    1.2 分析

    那么如何找到这个让样本间间距最大的轴? 如何定义样本间间距? 事实上有一个指标可以之间定义样本间的距离,就是方差(Variance)(方差:描述样本整体之间的疏密的一个指标,方差越大,代表样本之间越稀疏,方差越小,代表样本之间越紧密)。

    方差公式:

    为了简化方差计算,我们可以将样例的均值归为0 (demean),使得均值为0,这样可以简化方差的公式:

    对于右上角的(w1,w2),我们将其理解为一个二维向量,因为是在二维空间中,这个维度是由样本数据为维度决定的,当样本的维度为多维时,这个w也是多维向量,类似于线性回归中的theta向量,但是theta值是直线x的系数,w向量就只是一个向量。

    向量知识可以参考本节后的数学知识--向量。

    1.3 推导

    我们想要求一个轴的方向w = (w1,w2),是的我们所有的样本映射到w后,有:

    其中X(project)为样本映射到w向量后对应的特征值,也可以理解为一个向量:

    进行方差归一化后:

    X(i)映射到w的距离实际上就是X(i)与w的点乘(棕色的线),根据定义推导,其值实际上就是Xproject,其中w看作单位向量。

    那么:

    此时我们的目标函数就可以化简为:

    其中X(i)为样本,w为我们要找的向量,这个向量要做到上式结果最大。
    我们的样本X的特征维度时几维,我们要找的w就是几维。

    1.4 与线性回归的区别

    线性回归:
    PCA降维

    1.主成分分析法(PCA)的两个轴都是特征,线性回归y轴是目标结果值。

    1. 主成分分析法的点是垂直于方差轴直线的,目标是让这些点投影到这个线上后的间距尽可能的大。
    2. 而线性回归的点是垂直于x轴的,目标是让这些点特征值对应值与该线预测值之间结果尽可能的小。

    2. 使用梯度上升法解决PCA问题

    2.1 公式推导--梯度值

    对于梯度值得计算,与J函数一样,对f函数对每一个w求偏导组成得向量:

    注意上面式子里的每一个(X1(i)·w1+X2(i)·w2+......Xn(i)·wn)都是一个X(i)和w的点乘,所以式子可以进一步化解:

    化简过后可以进行向量化,也就是去掉∑(m),其每一项拆开开都是m个标量相加。每一项的前半部分都一样(向量),后半部分组合起来的值为X矩阵的转置,那么这样的话就变成了X矩阵的转置与向量的点乘:(X (*) w )*X(T)
    其中:

    • X:m行n列
    • w:n行1列

    这样计算出来的结果为n行1列。

    2.2使用梯度上升法代码实现PCA

    1.创建数据--画图
    import numpy as np
    import matplotlib.pyplot as plt
    
    X = np.empty((100, 2))
    # 将X的第0列设置为0-100的随机小数
    X[:,0] = np.random.uniform(0., 100., size=100)
    # 第2列数据 = 0.75 * X[:,0] + 3 + noise
    X[:,1] = 0.75 * X[:,0] + 3. + np.random.normal(0, 10., size=100)
    
    plt.scatter(X[:,0],X[:,1])
    plt.show()
    
    2.demean(归0)

    上述公式使用的前提有两个:

    1. 要对数据进行归0处理。
    2. w必须为单位向量。

    那么这里我们一一处理:

    1.归0

    假设X为m行n列的矩阵:
    np.mean(X, axis=0):对X中数据求均值。

    • axis = 0,对每一列求均值,返回一行n列向量。
    • axis = 1,对每一行求均值,返回m行一列向量。

    归0操作就是每一列数据减去该列的平均值组成的新的向量。
    demean:

    def demean(X):
        return X - np.mean(X, axis=0)
    X_mean = demean(X)
    
    re = np.mean(X_mean[:,0])
    print(re)       # 2.5437429940211587e-14
    
    plt.scatter(X_mean[:,0],X_mean[:,1])
    plt.show()
    

    2.转化单位向量函数:

    • np.linalg.norm(w),w向量的模
    # 单位向量w
    def dirextion(w):
        return w/np.linalg.norm(w)
    
    3.梯度上升法

    1.f函数
    f函数,也就是效用函数。

    f():

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

    2.df函数

    df函数分为df_math()和df_debug():

    • df_math()按照公式计算:
    • df_debug()与之前的梯度下降法调试中的一样:
    def df_math(X,w):
        gradient  = (X.T.dot(X.dot(w))) * 2 / len(X)
        return gradient
    
    def df_debug(X,w,epsilon=0.0001):
        gradient = np.empty(len(w))
        
        for i in range(len(w)):
            w_1 = w.copy()
            w_1[i] += epsilon
            w_2 = w.copy()
            w_2[1] -=epsilon
            
            gradient[i] = (f(X,w_1) - f(X,w_2)) /(2 *epsilon)
            
        return gradient
    

    3.梯度上升函数

    该函数的逻辑与梯度下降相似,只是在每次循环中,都要调用单位向量函数将w转为单位向量进行计算。

    def gradient_ascent(df, X, initial_w, eta, n_iters = 1e4, epsilon=1e-8):
        w = dirextion(initial_w)
        i_iter = 0
    
        while i_iter < n_iters:
            gradient = df(X,w)
            last = w
            w = w + eta * gradient
            w = dirextion(w)
    
            if abs(f(X,w) - f(X,last)) < epsilon:
                break
            i_iter +=1
    
        return w
    
    4. 测试:
    # 设置参数
    init_w = np.random.random(X.shape[1])
    eta = 0.001
    
    # df_debug
    re = gradient_ascent(df_debug,X_mean,init_w,eta)
    print(re)    # [0.74936349 0.66215886]
    
    # df_math
    re = gradient_ascent(df_math,X_mean,init_w,eta)
    print(re)      # [0.78531688 0.61909401]
    
    5.画图

    将所有样本点描在图中,并将w向量放大100倍画在图中:

    plt.scatter(X_mean[:,0],X_mean[:,1])
    plt.plot([0,re[0]*100],[0,re[1]*100],color='r')
    plt.show()
    
    6.使用极端数据集测试

    1.生成数据集:

    数据集的第二列不加噪音,也就是这些样本点全部在一条直线上。

    import numpy as np
    import matplotlib.pyplot as plt
    
    
    X2 = np.empty((100, 2))
    X2[:,0] = np.random.uniform(0., 100., size=100)
    X2[:,1] = 0.75 * X2[:,0] + 3.
    
    plt.scatter(X2[:,0], X2[:,1])
    plt.show()
    

    2.数据处理,测试数据,画图:

    from PCA.pca_01 import demean,df_math,gradient_ascent
    
    # 数据集归0
    X2_mean = demean(X2)
    
    # 设置参数
    init_w = np.random.random(X2.shape[1])
    eta = 0.001
    # 梯度上升
    re = gradient_ascent(df_math,X2_mean,init_w,eta)
    print(re)
    
    # 画图对比
    plt.scatter(X2_mean[:,0],X2_mean[:,1])
    plt.plot([0,re[0]*10],[0,re[1]*10],color='r')
    plt.show()
    

    ##########################################################

    附录:数学知识--向量

    1.向量概述
    • 向量有方向和长度或者叫大小。
    • 向量可以看成是一个有方向的线段,用(w1,w2)表示 。
    • 一个点怎么能表示一个线段呢? 还有一个隐含点 就是坐标原点,如果一个向量的起点不在坐标原点 我们可以将它平移到坐标原点。
    • 向量的模:就是指向量的长度 也即(w1^2 + w2^2)方开根号 也即原点出发的线段的长度.
    • 单位向量:向量的模为1的向量,其数量有无数个。
    • 向量转化为单位向量:该向量/该向量的模。
    2.向量的意义

    1.定义
    概括的说,向量的内积(点乘)对于两个向量执行点乘就是对应位置一一相乘求和的操作。计算出来为一个标量值。

    这里要求a和b的行列数相同。

    2.向量内积的几何意义

    两向量相乘可以表示为如下形式:

    其中,theta为向量a和向量b 之间的夹角。
    上式右边的意思为:一个向量在另一个向量方向上的射影乘以另一个向量的长度。
    即:两向量的点积为向量a在向量b方向上 “贡献” 长度的多少;

    画图:

    推导过程:

    首先我们了解一下a+b和a-b:

    a+b:

    a-b:

    假设a+b/a-b 结果为c向量,用(c1,c2)表示,a向量(a1,a2),b向量(b1,b2),那么c向量中的c1 = a1+b1/a1-b1,c2 = a2+b2/a2-b2

    定义:

    根据三角形余弦定理有:

    根据关系c=a-b(a、b、c均为向量)有:

    即:

    向量a,b的长度都是可以计算的已知量,从而有a和b间的夹角θ:

    据这个公式就可以计算向量a和向量b之间的夹角。从而就可以进一步判断这两个向量是否是同一方向,是否正交(也就是垂直)等方向关系,具体对应关系为:

    • a·b>0 方向基本相同,夹角在0°到90°之间
    • a·b=0 正交,相互垂直
    • a·b<0 方向基本相反,夹角在90°到180°之间

    相关文章

      网友评论

          本文标题:2020-08-25--PCA降维01

          本文链接:https://www.haomeiwen.com/subject/whbajktx.html