LDA线性判别分析Python程序

理论讲解

需要导入的包

# -*- coding: utf-8 -*-
import numpy as np 
import csv
from matplotlib import pyplot as plt
import math

导入数据集

def read_iris():
    from sklearn.datasets import load_iris
    from sklearn import preprocessing
    data_set = load_iris()
    data_x = data_set.data 
    label = data_set.target + 1
    #preprocessing.scale(data_x, axis=0, with_mean=True, with_std=True, copy=False) 
    return data_x,label

iris数据集
有三类,4个特征
初始类标签是从0开始的,加一后从1开始。
preprocessing.scale(data_x, axis=0, with_mean=True, with_std=True, copy=False)
是对数据进行标准化


    # 特征均值,计算每类的均值,返回一个向量
def class_mean(data,label,clusters):
    mean_vectors = [] 
    for cl in range(1,clusters+1):
        mean_vectors.append(np.mean(data[label==cl,],axis=0))
    #print mean_vectors
    return mean_vectors

输入特征数据集,类标签,类别个数
计算每类数据的均值
用于计算散度矩阵

    # 计算类内散度
def within_class_SW(data,label,clusters):
    m = data.shape[1]
    S_W = np.zeros((m,m))
    mean_vectors = class_mean(data,label,clusters)
    for cl ,mv in zip(range(1,clusters+1),mean_vectors):
        class_sc_mat = np.zeros((m,m))
        # 对每个样本数据进行矩阵乘法 
        for row  in data[label == cl]:
            row ,mv =row.reshape(4,1),mv.reshape(4,1)
            class_sc_mat += (row-mv).dot((row-mv).T)
        S_W +=class_sc_mat
    #print S_W 
    return S_W

计算类内散度,散度矩阵式 mm 的对称矩阵, m 是特征(属性)的个数
首先计算类内均值
对每一类中的每条数据减去均值进行矩阵乘法(列向量乘以行向量,所得的矩阵秩为1,线代中讲过 )
相加,就是类内散度矩阵


def between_class_SB(data,label,clusters):
    m = data.shape[1]
    all_mean =np.mean(data,axis = 0)
    S_B = np.zeros((m,m))
    mean_vectors = class_mean(data,label,clusters)
    for cl ,mean_vec in enumerate(mean_vectors):
        n = data[label==cl+1,:].shape[0]
        mean_vec = mean_vec.reshape(4,1) # make column vector
        all_mean = all_mean.reshape(4,1)# make column vector
        S_B += n * (mean_vec - all_mean).dot((mean_vec - all_mean).T)
    #print S_B 
    return S_B

计算类间散度矩阵,这里某一类的特征用改类的均值向量体现。
C个秩为1的矩阵的和,数据集中心是整体数据的中心,S_B是秩为C-1

def lda():
    data,label=read_iris();
    clusters = 3
    S_W = within_class_SW(data,label,clusters)
    S_B = between_class_SB(data,label,clusters)
    eig_vals, eig_vecs = np.linalg.eig(np.linalg.inv(S_W).dot(S_B))
    #print S_W 
    #print S_B 
    for i in range(len(eig_vals)):
        eigvec_sc = eig_vecs[:,i].reshape(4,1)
        print('\nEigenvector {}: \n{}'.format(i+1, eigvec_sc.real))
        print('Eigenvalue {:}: {:.2e}'.format(i+1, eig_vals[i].real))
    eig_pairs = [(np.abs(eig_vals[i]), eig_vecs[:,i]) for i in range(len(eig_vals))]
    eig_pairs = sorted(eig_pairs, key=lambda k: k[0], reverse=True)
    W = np.hstack((eig_pairs[0][1].reshape(4,1), eig_pairs[1][1].reshape(4,1)))
    print 'Matrix W:\n', W.real
        print data.dot(W)
    return W 

类内散度矩阵 SW
类间散度矩阵 SB
计算 S1WSB 的特征值,特征向量
SB 的秩为 C1
所数据集中有d个特征
特征值为0的有: dC+1
我们只需要考虑前 C1 个不为0的特征值的特征向量

写了这个程序发现,若投影矩阵式 W ,投影后的数据是 Ynk=XndWdk
n是数据的数量
d是特征数
k是降维后的维数
上篇中说的投影后的数据是: Y=WTX
这个两个不一样啊???
WT kd
X dn
Y kn
这样就说得通了,只是数据的表现形式不一样。

下面是用上面程序投影后的数据的散点图
LDA线性判别分析Python程序_第1张图片

下面的是用 sklearnldasvd 分解,两个图差别还是比较大的(不会改成用特征值的)
LDA线性判别分析Python程序_第2张图片


def plot_lda():
    data,labels = read_iris()
    W = lda()
    Y = data.dot(W)
    #print Y 
    ax= plt.subplot(111)
    for label,marker,color in zip(range(1,4),('^','s','o'),('blue','red','green')):
        plt.scatter(x=Y[:,0][labels == label],
            y=Y[:,1][labels == label],
            marker = marker,
            color = color,
            alpha = 0.5,
            )
    plt.xlabel('LDA1')
    plt.ylabel('LDA2')
    plt.title('LDA: Iris projection onto the first 2 linear discriminants')
    plt.show()

def default_plot_lda():
    Y = sklearnLDA()
    data,labels = read_iris()
    ax= plt.subplot(111)
    for label,marker,color in zip(range(1,4),('^','s','o'),('blue','red','green')):
            plt.scatter(x=Y[:,0][labels == label],
                    y=Y[:,1][labels == label],
                    marker = marker,
                    color = color,
                    alpha = 0.5,
                    )
    plt.xlabel('LDA1')
    plt.ylabel('LDA2')
    plt.title('LDA:default')

    plt.show()  

def sklearnLDA():
    from sklearn import datasets
    from sklearn.lda import LDA

    iris = datasets.load_iris()

    X = iris.data
    y = iris.target
    target_names = iris.target_names

    lda = LDA(n_components=2)
    X_r2 = lda.fit(X, y).transform(X)
    return X_r2

if __name__ =="__main__":
    #lda()
    #sklearnLDA()
    plot_lda()
    default_plot_lda()

参考:http://sebastianraschka.com/Articles/2014_python_lda.html
这个说明的很详细,程序几乎都是看上面的。

你可能感兴趣的:(机器学习)