機器學習 LDA線性判別分析python實現

2021-10-01 20:30:42 字數 4227 閱讀 5350

理論部分可以看看這個大佬的文章:

# -*- coding: utf-8 -*-

# @date : 2019/12/18

# @file : lda.py

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

'''類內sw 類間sb矩陣

根據拉格朗日:

s_b*u = lambda * s_w * u ==> s_w^(-1) * s_b * u = lambda*u

'''class lda(object):

def __init__(self, num_class=2, out_dim=2):

self.num_class = num_class

self.out_dim = out_dim

self.w = none # 用來降維的特徵向量

self.eig_pairs = none # 特徵值從大到小的,特徵值和特徵向量的組合

self.reduced_data = none # 降維後的資料(reduced_x, y) x.shape=(n, outdim)

def fit(self, x, y):

''':param x:

:param y: 預設y的值從0開始

:return:

'''m = x.shape[1]

class_mean = self.__calc_class_mean(x, y)

s_b = self.__calc_sb(x, y, class_mean)

s_w = self.__calc_sw(x, y, class_mean)

# 得到特徵值[..., wi], 特徵向量[:, i]

eig_vals, eig_vecs = np.linalg.eig(np.linalg.inv(s_w).dot(s_b))

eig_pairs = [(eig_vals[i], eig_vecs[:,i]) for i in range(len(eig_vals))]

eig_pairs = sorted(eig_pairs, key=lambda x:x[0], reverse=true)

# 預設取前2個特徵值對應的特徵向量

out_vecs =

for dim in range(self.out_dim):

self.w = np.hstack(out_vecs)

self.eig_pairs = eig_pairs

self.reduced_x = x.dot(self.w)

self.reduced_data = (self.reduced_x, y)

return self

def predict(self, x):

pass

def __calc_class_mean(self, x, y):

class_mean =

for label in range(self.num_class):

idx = (y == label)

vec = np.mean(x[idx], axis=0)

return np.array(class_mean)

def __calc_sb(self, x, y, class_mean):

'''可以通過總體散度矩陣進行優化 \sum_k n_k * (mean_k - mean) * (mean_k - mean)^t}'''

m = x.shape[1]

s_b = np.zeros((m, m))

all_mean = np.mean(x, axis=0)

for k in range(self.num_class):

class_k_mean = class_mean[k]

n_k = sum(y == k)

all_mean, class_k_mean = all_mean.reshape(m, 1), class_k_mean.reshape(m, 1)

s_b += n_k * (class_k_mean - all_mean).dot((class_k_mean - all_mean).t)

return s_b

def __calc_sw(self, x, y, class_mean):

'''類內矩陣'''

m = x.shape[1]

s_w = np.zeros((m, m))

for k in range(self.num_class):

class_k_mat = np.zeros((m, m))

class_k_mean = class_mean[k]

for x_i in x[y==k]:

x_i, class_k_mean = x_i.reshape(m, 1), class_k_mean.reshape(m, 1)

# class_k_mat += (x_i.dot(x_i.t) - class_k_mean.dot(class_k_mean.t))

class_k_mat += (x_i - class_k_mean).dot((x_i - class_k_mean).t)

s_w += class_k_mat

return s_w

def plot(self, y):

# 預設降維到二維資料進行視覺化

assert self.num_class == 2

for label, marker, color in zip([0, 1], ('^', 's'), ('blue', 'yellow')):

plt.scatter(x=self.reduced_x[:, 0][y == label],

y=self.reduced_x[:, 1][y == label],

marker=marker,

color=color,

alpha=0.5,

label=str(label)

)plt.xlabel('x1')

plt.ylabel('x2')

plt.title('lda')

plt.legend()

plt.show()

if __name__ == '__main__':

data = pd.read_csv('f:/datastructureprectice/data/breast-cancer-wisconsin.data.csv',

header=none,

names=['id', 'ct', 'size', 'shape', 'ma', 'secs', 'bn', 'bc', 'nn', 'mit', 'y'])

data['y'] = data['y'].replace()

# 將樣例資料進行處理 用 眾數 對問號 進行填充

for f in data.select_dtypes(include=['object']):

mode = data[f].mode().iloc[0]

data[f] = data[f].replace('?', mode).astype(int)

x = data.drop(columns=['id', 'y']).values

y = data['y'].values

lda = lda(num_class=2, out_dim=2)

lda.fit(x, y)

lda.plot(y)

將資料降維到二維的視覺化:

最後:lda vs pca

lda用於降維,和pca有很多相同,也有很多不同的地方,因此值得好好的比較一下兩者的降維異同點。

相同點:

1)兩者均可以對資料進行降維。

2)兩者在降維時均使用了矩陣特徵分解的思想。

3)兩者都假設資料符合高斯分布。

不同點:

1)lda是有監督的降維方法,而pca是無監督的降維方法

2)lda降維最多降到類別數k-1的維數,而pca沒有這個限制。 主要由於rank(ab) <= min(rank(a), rank(b))

3)lda除了可以用於降維,還可以用於分類。

4)lda選擇分類效能最好的投影方向,而pca選擇樣本點投影具有最大方差的方向。

在某些資料分布下lda比pca降維較優。

機器學習之線性判別分析(LDA)

根據公式可以計算出sw為 求其特徵值和特徵向量 value,vector np.linalg.eig sw.i sb value 1.5639568e 17,8.0000000e 00 vector 0.97421693,0.22561331 0.92309826,0.38456417 這裡選擇特徵...

LDA 線性判別分析

1.lda是什麼 線性判別式分析 linear discriminant analysis 簡稱為lda。也稱為fisher線性判別 fisher linear discriminant,fld 是模式識別的經典演算法,在1996年由belhumeur引入模式識別和人工智慧領域。基本思想是將高維的模...

線性判別分析LDA

首先搞清楚什麼叫判別分析?discriminant analysis就是根據研究物件的各種特徵值判別其型別歸屬問題的一種多變數統計分析方法。根據判別標準不同,可以分為距離判別 fisher判別 bayes判別法等。比如在knn中用的就是距離判別,當然這裡的 距離 又有好幾種 歐氏距離 街區距離 甚至...