c语言编程笔录

首页 >   > 笔记大全

笔记大全

Python中的LDA线性判别分析技巧

更新时间:2023-11-16

LDA线性判别分析技巧

LDA(线性判别分析)是一种常用的分类算法,它可以将数据投射到低维空间,然后再进行分类。在这个过程中,LDA会尽量让不同类别之间的距离最大化,同时让同一类别内部的方差最小化。这种算法在很多领域都有应用,包括模式识别、人脸识别、自然语言处理等。

LDA的原理

LDA的核心思想是将高维数据投射到低维空间,使得不同类别之间的距离最大化,同时保持同一类别内部的方差最小化。具体来讲,我们可以先计算每个类别的均值向量:

import numpy as np

def compute_mean_vectors(X, y):
    unique_classes=np.unique(y)
    mean_vectors=[]
    for c in unique_classes:
        mean_vectors.append(np.mean(X[y==c], axis=0))
    return np.array(mean_vectors)
    

然后计算类内散度矩阵$S_w$和类间散度矩阵$S_b$:

def compute_scatter_matrices(X, y):
    unique_classes=np.unique(y)
    mean_vectors=compute_mean_vectors(X, y)
    S_w=np.zeros((X.shape[1], X.shape[1]))
    S_b=np.zeros((X.shape[1], X.shape[1]))
    for c, mv in zip(unique_classes, mean_vectors):
        X_c=X[y==c]
        n_c=X_c.shape[0]
        mean_vec_c=mv.reshape((-1, 1))
        S_w +=np.dot((X_c-mean_vec_c), (X_c-mean_vec_c).T)
        mean_vec=mean_vectors.mean(axis=0).reshape((-1, 1))
        S_b +=n_c * np.dot((mean_vec_c - mean_vec), (mean_vec_c - mean_vec).T)
    return S_w, S_b
    

接着我们可以计算投影矩阵$W$,通过对原始数据进行投影,即可得到低维空间下的表示:

def lda(X, y, n_components):
    S_w, S_b=compute_scatter_matrices(X, y)
    eigenvalues, eigenvectors=np.linalg.eig(np.dot(np.linalg.inv(S_w), S_b))
    sorted_indices=np.argsort(eigenvalues)[::-1][:n_components]
    W=eigenvectors[:,sorted_indices]
    return np.dot(X, W)
    

LDA的应用

LDA在很多领域都有应用,下面我们介绍两个实际的案例。

人脸识别

人脸识别是LDA的一个重要应用,我们可以使用LDA将人脸数据投射到低维空间,然后再进行识别。下面是一个使用LDA进行人脸识别的例子:

from sklearn.datasets import fetch_lfw_people
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.neighbors import KNeighborsClassifier
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

data=fetch_lfw_people(min_faces_per_person=70, resize=0.4)
X_train, X_test, y_train, y_test=train_test_split(
    data.data, data.target, stratify=data.target, test_size=0.25, random_state=42)

# 使用PCA降维
pca=PCA(n_components=100)
X_train_pca=pca.fit_transform(X_train)
X_test_pca=pca.transform(X_test)

# 使用LDA降维
lda=LinearDiscriminantAnalysis(n_components=100)
X_train_lda=lda.fit_transform(X_train, y_train)
X_test_lda=lda.transform(X_test)

# 训练KNN分类器,并计算准确率
knn_pca=KNeighborsClassifier(n_neighbors=5)
knn_pca.fit(X_train_pca, y_train)
accuracy_pca=accuracy_score(y_test, knn_pca.predict(X_test_pca))

knn_lda=KNeighborsClassifier(n_neighbors=5)
knn_lda.fit(X_train_lda, y_train)
accuracy_lda=accuracy_score(y_test, knn_lda.predict(X_test_lda))

print("PCA accuracy:", accuracy_pca)
print("LDA accuracy:", accuracy_lda)
    

从结果可以看出,使用LDA降维可以比PCA取得更好的分类结果。

文本分类

LDA也可以用于文本分类,我们可以将每个文档映射到一个低维空间,然后再进行分类。下面是一个使用LDA进行文本分类的例子:

from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import cross_val_score
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

data=fetch_20newsgroups(subset='all')
vectorizer=CountVectorizer(stop_words='english')
X=vectorizer.fit_transform(data.data)
y=data.target

lda=LinearDiscriminantAnalysis(n_components=20)
X_lda=lda.fit_transform(X.toarray(), y)

scores=cross_val_score(LogisticRegression(), X_lda, y, cv=5)
print("LDA accuracy:", np.mean(scores))
    

同样可以看到,使用LDA降维可以比直接使用词频向量取得更好的分类结果。

总结

LDA(线性判别分析)是一种常用的分类算法,它可以将数据投射到低维空间,然后再进行分类。在这个过程中,LDA会尽量让不同类别之间的距离最大化,同时让同一类别内部的方差最小化。在人脸识别、文本分类等领域都有应用。