線性判別分析(Linear Discriminant Analysis,簡稱LDA)是一種常用的多元統(tǒng)計分析方法,通常被用于分類和特征提取。它的目的是在給定一組帶有標簽的數(shù)據(jù)的情況下,找到一個線性變換,將數(shù)據(jù)投影到一個低維空間中,使得不同類別的數(shù)據(jù)點在該低維空間中能夠更加容易地區(qū)分開來。簡而言之,LDA 的目的是將高維數(shù)據(jù)投影到低維空間中,同時最大化類別之間的差異性,最小化類別內(nèi)部的差異性。
LDA 的基本思想是,將數(shù)據(jù)在低維空間中找到一個合適的投影方向,使得類別之間的距離最大化,同時類別內(nèi)部的距離最小化。為了實現(xiàn)這個目的,LDA 首先需要計算數(shù)據(jù)的協(xié)方差矩陣,然后對協(xié)方差矩陣進行特征值分解,得到協(xié)方差矩陣的特征向量和特征值。這些特征向量構(gòu)成了投影矩陣,可以將原始數(shù)據(jù)映射到新的低維空間中。投影后的數(shù)據(jù)可以使用簡單的分類器(如線性分類器)來進行分類。
LDA 和 PCA(Principal Component Analysis,主成分分析)有相似之處,但它們的目標不同。PCA 的目標是在不降低數(shù)據(jù)的可區(qū)分性的前提下,將數(shù)據(jù)投影到一個低維空間中,以最大化數(shù)據(jù)的方差。而 LDA 的目標是最大化類別之間的距離,最小化類別內(nèi)部的距離,以提高分類的準確性。
總之,LDA 是一種經(jīng)典的分類算法,具有較好的分類性能和解釋性。在實際應(yīng)用中,LDA 常常被用于面部識別、語音識別、圖像分類等領(lǐng)域。
LDA 的數(shù)學(xué)推導(dǎo)可以分為兩個步驟:第一步是計算數(shù)據(jù)的協(xié)方差矩陣,第二步是找到一個合適的投影方向。
首先,假設(shè)有 N?個樣本,每個樣本有 p?個特征,數(shù)據(jù)矩陣為 X_{N\times p},其中 X_i?表示第 i?個樣本的特征向量。假設(shè)數(shù)據(jù)被分為 K個類別,每個類別包含 N_k?個樣本,其中 sum_{k=1}^{K}N_k=N。每個類別的均值向量為 mu_k,總體均值向量為 mu。類內(nèi)散度矩陣為 S_w,類間散度矩陣為 S_b。則有:
?
其中,C_k?表示第 k個類別。
接下來,我們需要找到一個投影方向 w,將數(shù)據(jù)矩陣 X?映射到一維空間中。投影后的數(shù)據(jù)為 y=Xw。我們希望在投影后的一維空間中,不同類別的數(shù)據(jù)點能夠更加容易地區(qū)分開來。因此,我們希望在一維空間中最大化類間散度矩陣 S_b,同時最小化類內(nèi)散度矩陣 S_w。
類間散度矩陣 S_b?在一維空間中的表達式為:
類內(nèi)散度矩陣 S_w?在一維空間中的表達式為:
?
其中,c_i?表示第 i?個樣本所屬的類別,mu_{c_i}?表示第 i個樣本所屬類別的均值。y_i?表示第 i個樣本在一維空間中的投影。
為了最大化 S_b,我們需要找到一個投影方向 w,使得 w^T(\mu_1-\mu_2)^2w?最大化。這等價于找到一個方向 w,使得 w^TS_bw最大化。
為了最小化 S_w,我們需要找到一個投影方向 w,使得 w^T\sum_{i=1}^{N}(y_i-\mu_{c_i})^2w?最小化。因為 y=Xw,所以有:
?
因此,我們需要最小化 sum_{i=1}^{N}(y_i-\mu_{c_i})^2,即最小化類內(nèi)散度矩陣 S_w。
綜上所述,我們需要找到一個投影方向 w,使得 w^TS_bw?最大化,w^TS_ww?最小化。這是一個標準的廣義瑞利商問題,可以通過求解廣義特征值問題來解決。具體來說,我們需要求解下面的廣義特征值問題:
?求解出特征值和特征向量之后,我們可以選擇最大的 d?個特征向量,將數(shù)據(jù)矩陣X映射到 d?維空間中,從而進行分類。
?當(dāng)我們得到數(shù)據(jù)矩陣 X和類別向量 y?后,可以使用 Python 中的 sklearn.discriminant_analysis.LinearDiscriminantAnalysis
類來進行線性判別分析。下面是一個簡單的例子:
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
# 創(chuàng)建 LDA 模型對象
lda = LinearDiscriminantAnalysis()
# 使用 LDA 擬合數(shù)據(jù)
lda.fit(X, y)
# 對新數(shù)據(jù)進行預(yù)測
y_pred = lda.predict(X_new)
其中,X
是形狀為 (n_samples, n_features)的數(shù)據(jù)矩陣,y
是形狀為 (n_samples,)?的類別向量,X_new
是形狀為 (m, n_features)?的新數(shù)據(jù)矩陣,y_pred
是形狀為 (m,)?的預(yù)測結(jié)果向量。
在實際使用中,我們可以先將數(shù)據(jù)集拆分成訓(xùn)練集和測試集,然后使用訓(xùn)練集來擬合 LDA 模型,最后使用測試集來評估模型的分類性能。下面是一個完整的例子:
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.metrics import accuracy_score
# 生成樣本數(shù)據(jù)
X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_classes=2, random_state=42)
# 將數(shù)據(jù)集拆分成訓(xùn)練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 創(chuàng)建 LDA 模型對象
lda = LinearDiscriminantAnalysis()
# 使用訓(xùn)練集擬合 LDA 模型
lda.fit(X_train, y_train)
# 對測試集進行預(yù)測
y_pred = lda.predict(X_test)
# 計算分類準確率
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy:.2f}")
在這個例子中,我們首先使用 make_classification
函數(shù)生成一個二分類數(shù)據(jù)集,然后將數(shù)據(jù)集拆分成訓(xùn)練集和測試集,使用訓(xùn)練集來擬合 LDA 模型,最后使用測試集來評估模型的分類性能。在這個例子中,我們使用了分類準確率來評估模型的性能。
除了使用 sklearn
庫提供的 LinearDiscriminantAnalysis
類之外,我們還可以手動實現(xiàn)線性判別分析算法。下面是一個基于 NumPy 的簡單實現(xiàn):
import numpy as np
class LinearDiscriminantAnalysis:
def __init__(self, n_components=None):
self.n_components = n_components
self.w = None
def fit(self, X, y):
# 計算類別數(shù)量、總均值和類內(nèi)散度矩陣
self.classes_ = np.unique(y)
self.mean_ = np.mean(X, axis=0)
Sw = np.zeros((X.shape[1], X.shape[1]))
for c in self.classes_:
Xc = X[y == c]
mean_c = np.mean(Xc, axis=0)
Sw += (Xc - mean_c).T.dot(Xc - mean_c)
self.Sw_ = Sw
# 計算類間散度矩陣和投影方向
Sb = np.zeros((X.shape[1], X.shape[1]))
for c in self.classes_:
Xc = X[y == c]
mean_c = np.mean(Xc, axis=0)
Sb += Xc.shape[0] * (mean_c - self.mean_).reshape(-1, 1).dot((mean_c - self.mean_).reshape(1, -1))
eigvals, eigvecs = np.linalg.eig(np.linalg.inv(self.Sw_).dot(Sb))
eigvecs = eigvecs[:, np.argsort(eigvals)[::-1]]
if self.n_components is not None:
self.w = eigvecs[:, :self.n_components]
else:
self.w = eigvecs
def transform(self, X):
return X.dot(self.w)
def fit_transform(self, X, y):
self.fit(X, y)
return self.transform(X)
在這個實現(xiàn)中,我們首先定義了一個 LinearDiscriminantAnalysis
類,其中 n_components
參數(shù)指定了投影的維數(shù),如果不指定,則默認為原始特征的維數(shù)。
在 fit
方法中,我們首先計算了類別數(shù)量、總均值和類內(nèi)散度矩陣 Sw
,然后計算了類間散度矩陣 Sb
和投影方向 w
。我們使用 numpy.linalg.eig
函數(shù)來求解廣義特征值問題,然后將特征向量按照特征值從大到小排序,并選擇前 n_components
個特征向量作為投影方向。最后,我們將投影方向保存在 w
屬性中。
在 transform
方法中,我們將數(shù)據(jù)矩陣 X
乘以投影方向 w
,得到經(jīng)過投影后的數(shù)據(jù)矩陣。在 fit_transform
方法中,我們先調(diào)用 fit
方法來擬合模型,然后調(diào)用 transform
方法來進行投影。
對于分類問題,我們可以使用投影后的數(shù)據(jù)進行訓(xùn)練和預(yù)測。下面是一個完整的示例,演示了如何使用上面的實現(xiàn)來訓(xùn)練和評估模型:
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 生成樣本數(shù)據(jù)
X, y = make_classification(n_samples=1000, n_features=10, n_classes=2, random_state=42)
# 劃分訓(xùn)練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 訓(xùn)練模型
lda = LinearDiscriminantAnalysis(n_components=1)
X_train_lda = lda.fit_transform(X_train, y_train)
# 預(yù)測測試集
X_test_lda = lda.transform(X_test)
y_pred = np.zeros_like(y_test)
for c in lda.classes_:
y_c = y_train == c
mu_c = np.mean(X_train_lda[y_c], axis=0)
sigma_c = np.var(X_train_lda[y_c], axis=0, ddof=1)
p_c = np.sum(y_c) / len(y_train)
y_pred += p_c * stats.norm.pdf(X_test_lda, mu_c, np.sqrt(sigma_c))
# 計算準確率
y_pred = np.argmax(y_pred, axis=1)
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
在這個示例中,我們首先生成了一個樣本數(shù)據(jù)集,并將其劃分為訓(xùn)練集和測試集。然后,我們實例化了一個 LinearDiscriminantAnalysis
類,并使用訓(xùn)練集擬合了模型。接下來,我們將訓(xùn)練集和測試集投影到一維空間,并使用高斯分布來擬合每個類別的投影值分布。最后,我們使用貝葉斯公式來計算每個測試樣本屬于每個類別的概率,并選擇具有最大概率的類別作為預(yù)測結(jié)果。我們使用 accuracy_score
函數(shù)來計算準確率。
可視化代碼實現(xiàn)
?
下面我們以鳶尾花數(shù)據(jù)集為例,來展示如何使用線性判別分析進行分類。
首先,我們從Scikit-learn庫中導(dǎo)入鳶尾花數(shù)據(jù)集,并將其分為訓(xùn)練集和測試集。
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=42)
接下來,我們使用LinearDiscriminantAnalysis
類來訓(xùn)練線性判別分析模型,并使用訓(xùn)練集對其進行擬合。
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
lda = LinearDiscriminantAnalysis()
lda.fit(X_train, y_train)
然后,我們可以使用訓(xùn)練好的模型對測試集進行預(yù)測,并計算分類準確率。
from sklearn.metrics import accuracy_score
y_pred = lda.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
最后,我們可以使用Matplotlib庫將訓(xùn)練集和測試集在二維平面上可視化,以及繪制決策邊界。文章來源:http://www.zghlxwxcb.cn/news/detail-774235.html
import numpy as np
import matplotlib.pyplot as plt
# 將訓(xùn)練集和測試集投影到二維平面
X_train_lda = lda.transform(X_train)
X_test_lda = lda.transform(X_test)
# 繪制訓(xùn)練集和測試集
plt.figure(figsize=(8,6))
for i, target_name in enumerate(iris.target_names):
plt.scatter(X_train_lda[y_train == i, 0], X_train_lda[y_train == i, 1], label=target_name)
plt.scatter(X_test_lda[y_test == i, 0], X_test_lda[y_test == i, 1], marker='x', label=target_name)
# 繪制決策邊界
x_min, x_max = X_train_lda[:, 0].min() - 1, X_train_lda[:, 0].max() + 1
y_min, y_max = X_train_lda[:, 1].min() - 1, X_train_lda[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1), np.arange(y_min, y_max, 0.1))
Z = lda.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contour(xx, yy, Z, colors='black', alpha=0.5)
plt.xlabel('LD1')
plt.ylabel('LD2')
plt.title('Linear Discriminant Analysis')
plt.legend()
plt.show()
?在這個圖中,每個類別用不同的顏色表示。我們可以看到,訓(xùn)練集和測試集在投影后可以明顯地分開。決策邊界是一個非線性的分割線,它將不同的類別分開。文章來源地址http://www.zghlxwxcb.cn/news/detail-774235.html
到了這里,關(guān)于線性判別分析(LDA)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!