流行算法LE_机器学习

前言

    拉普拉斯特征映射是基于图论的方法。

   它从样本点构造带权值的图W,  然后计算拉普拉斯矩阵

   最后对该矩阵进行特征值分解得到投影变换

 

目录:

  1.     拉普拉斯矩阵定义
  2.     目标函数
  3.      推导过程
  4.      算法流程
  5.      算法实现

一  拉普拉斯矩阵定义:

        

         L=D-W

     其中D 为对角矩阵,对角线元素为每个顶点带权值的度     d_i=\sum _{j=1}^{m}w_{ij}     

    \begin{bmatrix} d_1 & ... & 0\\ ... & ... & ... \\ 0 & ... & d_n \end{bmatrix}

    W为低维度权值稀疏矩阵,是一个对称矩阵。每一行代表一个样本点w_i

  \begin{bmatrix} 0 & w_{12} & 0 & ... &w_{1m} \\ w_{21} & 0 & ..& ... & w_{2m}\\ 0 & & ...& &.0 \\ 0& &.... & &0 \\ w_{m1 }& w_{m2} & 0& ... & 0 \end{bmatrix}

 

  1.1  邻接关系,可以采用LLE算法里面的k近邻,注意的是LE算法是有向边,这里采用的是无向边

  1.2  边的权重,如果节点i和节点j是联通的它们的权重为:

     w_{ij}=exp(\frac{-||x_i-x_j|^2}{t})


    二  目标函数

          低维度变量Y为列矩阵

          Y= \begin{bmatrix} y_1 & y_2 & ... & y_m \end{bmatrix} 

         其中 y_i 为降维后的样本。

        J(Y)=\frac{1}{2}\sum_{i=1}^{m}\sum_{j=1}^{m}w_{ij}||y_i-y_j||^2


    三  推导过程

        依然是求最小值

      J(Y)=\frac{1}{2}\sum_{i=1}^{m}\sum_{j=1}^{m}(y_i-y_j)^T(y_i-y_j)w_{ij}

               =\frac{1}{2}(\sum_{i}\sum_j(y_i^Tyi- y_i^Ty_j-y_j^Ty_i+y_j^Ty_j)w_{ij})

             因为W是对称矩阵 w_{ij}=w_{ji}

             =\frac{1}{2}(\sum_{i}(\sum_j w_{ij})y_i^Ty_i+\sum_j(\sum_iw_{ji})y_j^Ty_j-2\sum_j\sum_i w_{ij}y_i^Ty_j)

           =\sum_i D_{ii}y_i^Ty_i-\sum_{i}y_i^T\sum_j w_{ij}y_j

            =tr(Y^TDY-Y^TWY)

           =tr(Y^TLY)

         注意: 后半部转换依然要用到W是对称矩阵

         约束条件

         Y^TDY=I

 

     拉格朗日对偶求值:

      f=tr(Y^TLY+\lambda(Y^TDY-I))

      对Y求偏导数

      LY= -\lambda DY

 

   依然求解m个最小的非零特征值

 

四 : 算法流程:

     1: 构建无向图
       使用某一种方法来将所有的点构建成一个图,例如使用KNN算法,将每个点最近的K个点连上边。

        K是一个预先设定的值。

     2:  权重W
             确定点与点之间的权重大小,例如选用热核函数来确定。
     

    3:特征映射
          计算拉普拉斯矩阵L的特征向量与特征值:

          Ly=λDy

          D^{-1}LY=\lambda Y

     4: 用最小的n个非零特征值对应的特征向量作为降维后的结果输出。

 


 

五  算法实现

 

       

# -*- coding: utf-8 -*-
"""
Created on Mon Oct 14 15:35:00 2019
拉普拉斯降维
@author: chengxf2
"""
from time import time

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.ticker import NullFormatter

from sklearn import manifold, datasets
import pickle
import numpy as np

"""
保存的数据集格式
Args
   data: 训练样本
   color: 样本点对应的color
"""
class Data:
    def __init__(self, data, color):
        
        self.trainData = data
        self.dataColor = color



class LE:
    
    """
    ·保存文件
    Args
      file: 文件名
      data: 样本
      color: 颜色
    return
       None
    """
    def SaveData(self, data ,color):
        
     DataInfo = Data(data,color)
     f = open(self.filePath,'wb')
     pickle.dump(DataInfo, f,0)
     f.close()
    
    """
    初始化
    """
    def __init__(self):
        
        self.newDim = 2 ##降维后样本新维度
        self.m = 0  ##样本的个数
        self.n = 0  ##样本的维度
        self.zero = 1e-5  ##当特征值大于该值时,就采用对应的特征向量
        self.k = 15 ##k 金陵
        self.r = 5.0 ## 半径
        self.filePath = "d:\\swissdata.dat" ##数据集路径
        




 
    """
    从文件中读取数据
    Args
       file: 文件路劲
    return
       trainData: 训练样本
       color: 样本点对应的color
    """
    def LoadFile(self, file):
        f = open(file, 'rb')
        data = pickle.load(f)
        f.close()
        
        trainData = data.trainData
        color = data.dataColor
        self.Draw(trainData, color,True)
        return trainData, color
    

    """
    生成保存流行数据
    Args
     None
    return 
     None
    """
    def SWData(self):
        
        n_points = 500
        data, color = datasets.samples_generator.make_swiss_roll(n_points, random_state=0)
        
        self.Draw(data, color)
    
        self.SaveData(self.filePath, data,color)
   
    """
    绘制点
    Args:
        Args
       data: 训练样本
       color: 样本点对应的color
       D3: 画维曲线还是二维曲线
        
    """
    def Draw(self, data, color,D3):
        
        if D3 ==True:
            
      
            fig = plt.figure(figsize=(6, 5))
            ax = fig.add_subplot(111, projection='3d')
            
            ax.scatter(data[:, 0], data[:, 1], data[:, 2], c=color, cmap=plt.cm.hot)
            ax.view_init(10, -70)
            ax.set_xlabel("$x_1$", fontsize=18)
            ax.set_ylabel("$x_2$", fontsize=18)
            ax.set_zlabel("$x_3$", fontsize=18)
        else:
            Tip ="r[Radius]:%d"%self.r + "     k[Neighbor]:%d"%self.k
            print("Tip ",Tip)
            plt.title(Tip, fontsize=14)
            plt.scatter(data[:, 0], data[:, 1], c=color, cmap=plt.cm.hot)
            plt.xlabel("$z_1$", fontsize=18)
            plt.ylabel("$z_2$", fontsize=18)
            plt.grid(True)

        plt.show()
      
        


    """
    获取权重参数
    Args
      xi  当前样本
      xj: 临近样本
      t:  半径
    """
    def Getw(self, xi,xj):
        
        diff = (xi-xj)**2
        dist = diff.sum( axis=0)  ##行
        alpha = np.exp(-dist/self.r)

        return alpha   
     
    """
    拉普拉降维Laplar dimensionality reduction
    Args
        k: k 个近邻
        t: exp 中分母
        dataMat: 数据集
    """
    def Ldr(self, trainData):
        
        wMat = np.zeros((self.m,self.m))
        DMat= np.zeros((self.m,self.m))
        
        
        print("\n step1  计算临近样本的权重  \n")
        for i in range(self.m):
            
            xi = trainData[i]
            sortK = self.GetKNear(xi, trainData,i)  ##返回临近的Index
            
            for j in sortK:
                xj = trainData[j]
                alpha = self.Getw(xi, xj)
                wMat[i,j]=alpha
                wMat[j,i] = wMat[i,j]

            di=sum(wMat[i,])
            DMat[i,i]=di
            
        print("\n step2  拉普拉斯矩阵计算 \n")
        L = DMat-wMat
        invD = np.linalg.inv(DMat)
        LD = np.dot(invD,L)
        
        
        print("\n step3   计算特征值特征向量")
        lamb, Y = np.linalg.eig(LD)
        
        
        print("\n step3   排序特征值")
        sortIndex = lamb.argsort()
        
        #print("lamb ",lamb)
        #print("sortIndex:  ",sortIndex)
        
        num = 0
        indexList =[]
        for index in sortIndex:
            
            lam = lamb[index]
            if lam>self.zero and num<self.newDim:
                indexList.append(index)
                num = num+1
        print("\n step4 降维后对应特征值序列")
        
        RedData = np.zeros((self.m,self.newDim))  ##500*2
        i = 0
        for j in indexList:
            
            yj = Y[:,j]
           
            RedData[:,i] = yj
            i+=1
            
        print("shape RedData",np.shape(RedData))
        
        return RedData
        
        
                
            
    
    
    
    
    """
    获取k近邻
    Args
       xi: 当前样本
       trianData: 所有样本
       k:  k个最近点
    """        
    
    def GetKNear(self, xi, trainData,i):
       
        
        diffData = np.tile(xi,(self.m,1))-trainData  ##m 行,1列
        
        #print("\n m ",m ,"\n diffData ", diffData)  ##array
         
        sqDiff = diffData**2
        sumDiff = sqDiff.sum(axis=1)
        sortK= list(sumDiff.argsort())
        sortK.remove(i)   ##排除自身点

        return sortK
        
    """
    开始训练
    Args
       None
    return 
      降维后的数据集
    """
    def Train(self):
        trainData, color  = self.LoadFile(self.filePath)
        self.m , self.n = np.shape(trainData)
        print("\n  加载数据集完毕 \n ")
        data = self.Ldr(trainData)
        self.Draw(data, color,False)


def Test():
    ##reshape
    ##m
    a = np.array([1,2,3,4])
    print("shape ",np.shape(a))
    print("shapeT ",np.shape(a.T))

  

le = LE()    
le.Train()
    
#tr = Test()



 效果:

     

   

 

   

 

 

说明:

   相对LLE算法

   1: LE权重是对称矩阵

   2: 模型对k,以及r的取值很敏感(r 上文中的t值),总的来说效果不错。     

   

     

    

参考文档:

  《机器学习与应用》  119页

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值