機器學習入門-線性判別分析(LDA)1.LabelEncoder(進行標簽的數字映射) 2.LinearDiscriminantAnalysis (sklearn的LDA模塊)


1.from sklearn.processing import LabelEncoder 進行標簽的代碼編譯

 

首先需要通過model.fit 進行預編譯,然后使用transform進行實際編譯

2.from sklearn.discriminant_analysis import LinearDiscriminantAnalysis  as LDA  從sklearn的線性分析庫中導入線性判別分析即LDA

用途:分類預處理中的降維,做分類任務

目的:LDA關心的是能夠最大化類間區分度的坐標軸

將特征空間(數據中的多維樣本,將投影到一個維度更小的K維空間,保持區別類型的信息)

 

監督性:LDA是“有監督”的,它計算的是另一個類特定的方向

投影:找到更適用的分類空間

與PCA不同: 更關心分類而不是方差(PCA更關心的是方差)

如圖所示,找到合適的方向投影后的數據更加的分散

 

LDA的數據原理:

目標找到投影:y = w^T * x  ,我們需要求解出w

LDA的第一個目標是使得投影后兩個類別之間的距離越大越好,使用的判別依據,是投影后兩個類別的中心點的距離越大越好,即均值u1^ - u2^

 

第一步:求出當前均值和投影后的均值

J(W) = |w^T(u1 - u2)|   # 計算投影以后的兩個類別中心位置之差

LDA的第二個目標是使得投影后的類別之間的距離越來越小,從圖一中我們可以看出,只討論類別之間的距離是不夠的, 同類之間的距離使用單個類別的數據到類別中心之差來表示,值越大,同類數據越分散,值越小,同類數據越集中,我們需要使得這個值的大小越小越好

根據上面兩個目標函數,我們做一個組合, 分子使用類間距離, 分母使用類內距離,求得組合后的最大值

 

該圖表示的是最終的目標函數(類間距離/類內距離),這里的類內散布矩陣:通過同種類別數據-該類別的均值之差進行加和后求得

求得類間距離的散步矩陣

 

上述的目標矩陣就是我們求解的方程,我們需要求得其最大值

構造拉格朗日方程, 我們對分母進行縮放,使得w^TSw*w = 1, 作為限制條件

cw = w^T*SB*w - a(w^T*Sw*w-1) --構造的拉格朗日方程

cw/dw = w^T*SB*w - a(w^T*Sw*w-1) / dw   對上述方程使用dw進行求導,求偏導等於零求最大值

2SB*w - 2*a*Sw * w = 0 

 

a * w = Sw^-1*SB*w  ---- a*w = A*w 

w是Sw^-1*SB的特征向量

 代碼:自己自行的編寫

第一步:讀取數據

第二步:提取樣本變量和標簽

第三步:對標簽進行數字映射,使用LableEncoder

第四步:計算類內散列矩陣Sw sum((x-ui).dot((x-ui).T))

第五步:計算類間散列矩陣SB sum(n*(ui-u).dot(ui-u))  ui表示每一類樣本的均值, u表示所有樣本的均值

第六步:計算Sw^-1*SB的特征向量,即w,如果我們投影的維度是2,使用np.vstack, 將求得的特征向量的第一列和第二列數據進行拼接

第七步:將二維的w和X特征進行點乘操作, 獲得變化后的二維特征

第八步:進行畫圖操作

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 第一步數據載入
data = pd.io.parsers.read_csv(filepath_or_buffer='https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data',
                              header=None, names=['sepal length in cm', 'sepal width in cm','petal length in cm', 'petal width in cm', 'names'],
                             sep=',',)
data.dropna(how='all', inplace=True)

# 第二步提取數據的X軸和y軸信息
feature_names = ['sepal length in cm', 'sepal width in cm','petal length in cm', 'petal width in cm']
X = data[feature_names].values
y = data['names'].values

# 第三步 使用Label_encoding進行標簽的數字轉換
from sklearn.preprocessing import LabelEncoder

model = LabelEncoder().fit(y)
y = model.transform(y) + 1

labels_type = np.unique(y)

# 第四步 計算類內距離Sw
Sw = np.zeros([4, 4])
# 循環每一種類型
print(labels_type)
for i in range(1, 4):
    xi = X[y==i]
    ui = np.mean(xi, axis=0)
    sw = ((xi - ui).T).dot(xi-ui)
    Sw += sw
print(Sw)

# 第五步:計算類間距離SB
SB = np.zeros([4, 4])
u = np.mean(X, axis=0).reshape(4, 1)
for i in range(1, 4):
    n = X[y==i].shape[0]
    u1 = np.mean(X[y==i], axis=0).reshape(4, 1)
    sb = n * (u1 - u).dot((u1 - u).T)
    SB += sb

# 第六步:使用Sw^-1*SB特征向量計算w
vals, eigs = np.linalg.eig(np.linalg.inv(Sw).dot(SB))

# 第七步:取前兩個特征向量作為w,與X進行相乘操作,相當於進行了2維度的降維操作
w = np.vstack([eigs[:, 0], eigs[:, 1]]).T

transform_X = X.dot(w)

# 第八步:定義畫圖函數
labels_dict = data['names'].unique()
def plot_lda():

    ax = plt.subplot(111)
    for label, m, c in zip(labels_type, ['*', '+', 'v'], ['red', 'black', 'green']):
        plt.scatter(transform_X[y==label][:, 0], transform_X[y==label][:, 1], c=c, marker=m, alpha=0.6, s=100, label=labels_dict[label-1])

    plt.xlabel('LD1')
    plt.ylabel('LD2')
    # 定義圖例,loc表示的是圖例的位置
    leg = plt.legend(loc='upper right', fancybox=True)
    # 設置圖例的透明度為0.6
    leg.get_frame().set_alpha(0.6)
    #坐標軸上的一簇簇的豎點
    plt.tick_params(axis='all', which='all', bottom='off', left='off', right='off', top='off',
                    labelbottom='on', labelleft='on')
    # 表示的是坐標方向上的框線
    ax.spines['top'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.spines['left'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.tight_layout()
    plt.grid()
    plt.show()

plot_lda()

我們使用Sklearn自帶的程序進行操作

第一步:讀取數據

第二步:提取特征

第三步:對標簽做數字映射,使用的是LabelEncoder

第四步:使用from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

第五步:結果進行畫圖

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 第一步數據載入
data = pd.io.parsers.read_csv(filepath_or_buffer='https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data',
                              header=None, names=['sepal length in cm', 'sepal width in cm','petal length in cm', 'petal width in cm', 'names'],
                             sep=',',)
data.dropna(how='all', inplace=True)

# 第二步提取數據的X軸和y軸信息
feature_names = ['sepal length in cm', 'sepal width in cm','petal length in cm', 'petal width in cm']
X = data[feature_names].values
y = data['names'].values

# 第三步 使用Label_encoding進行標簽的數字轉換
from sklearn.preprocessing import LabelEncoder

model = LabelEncoder().fit(y)
y = model.transform(y) + 1

labels_type = np.unique(y)

# 第四步 建立LDA模型
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA

model = LDA(n_components=2)
sklearn_x = model.fit_transform(X, y)


# 第五步進行畫圖操作
def plot_lda_sklearn(X, title):

    ax = plt.subplot(111)
    for label, m, c in zip(labels_type, ['*', '+', 'v'], ['red', 'black', 'green']):
        plt.scatter(X[y==label][:, 0], X[y==label][:, 1], c=c, marker=m, alpha=0.6, s=100, label=labels_dict[label-1])

    plt.title(title)
    plt.xlabel('LD1')
    plt.ylabel('LD2')
    leg = plt.legend(loc='upper right', fancybox=True)
    leg.get_frame().set_alpha(0.6)

    plt.tick_params(axis='all', which='all', bottom='off', left='off', right='off', top='off',
                    labelbottom='on', labelleft='on')
    ax.spines['top'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.spines['left'].set_visible(False)
    ax.spines['right'].set_visible(False)

    plt.tight_layout()
    plt.grid()
    plt.show()

plot_lda_sklearn(sklearn_x, 'the Sklearn LDA')


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM