研究背景
线性判别分析(Linear Discriminant Analysis,简称LDA)是一种经典的分类算法,其研究历史可以追溯到20世纪早期。以下是一些关于LDA算法的经典论文:
Fisher, R. A. (1936). The use of multiple measurements in taxonomic problems. Annals of Eugenics, 7(2), 179-188.
这篇论文是LDA算法的奠基之作,提出了Fisher线性判别准则,为后来的LDA算法提供了理论基础。
Switzer, P. (1984). The use of linear discriminant analysis in the development of classification equations for computer-assisted diagnostic systems. IEEE Transactions on Biomedical Engineering, (5), 464-467.
这篇论文介绍了LDA算法在计算机辅助诊断系统中的应用,为LDA算法在实际应用中的发展提供了重要的参考。
Duda, R. O., & Hart, P. E. (1973). Pattern classification and scene analysis (Vol. 3). John Wiley & Sons.
这本书介绍了LDA算法在模式分类和场景分析中的应用,为LDA算法在实际应用中的发展提供了重要的参考。
McLachlan, G. (1992). Discriminant analysis and statistical pattern recognition (Vol. 544). John Wiley & Sons.
这本书是LDA算法和其它判别分析方法的经典著作,详细介绍了LDA算法的理论和应用,为LDA算法的学习和应用提供了重要的参考。
Ding, C., & Peng, H. (2005). Minimum redundancy feature selection from microarray gene expression data. Journal of bioinformatics and computational biology, 3(02), 185-205.
这篇论文介绍了LDA算法在生物信息学中的应用,为LDA算法在实际应用中的拓展提供了重要的参考。
这些论文为LDA算法的研究和应用提供了重要的参考和指导,对于学习和掌握LDA算法具有重要意义。
原理说明
线性判别分析(Linear Discriminant Analysis, LDA)是一种经典的模式识别方法,它通过将数据投影到一个低维空间来实现分类。该算法假设每个类别的数据都服从多元正态分布,并且各个类别的协方差矩阵相同。LDA算法的主要目标是将不同类别之间的距离最大化,同时将同一类别内部的距离最小化。
基本思想
LDA算法的基本思想是将多维数据投影到一个低维空间,使得不同类别之间的距离尽可能大,同一类别内部的距离尽可能小。假设有n个样本,每个样本有m个特征。LDA算法的主要步骤如下:
对每个类别,计算其均值向量。将所有类别的均值向量合并为一个矩阵M,其中每行对应一个均值向量。
对每个类别,计算其协方差矩阵Si。
计算总的类别内散度矩阵Sw,表示所有类别内部数据的离散程度。
计算总的类别间散度矩阵Sb,表示不同类别之间的距离。
对矩阵Sw求逆,然后计算矩阵Sw^-1Sb的特征向量和特征值。
对特征值从大到小排序,选择前k个特征向量作为投影方向。
将数据投影到选定的投影方向上,得到新的低维特征表示。
利用投影后的特征表示进行分类。
数学表述
假设有k个类别,每个类别有nk个样本。每个样本有m个特征,表示为x=(x1, x2, …, xm)。类别标签用y表示,y∈{1,2,…,k}。LDA算法的主要目标是最大化以下函数:
J(w) = (wTSbTw)/(w^T Sw^w)
其中w是一个m维列向量,表示投影方向。Sb和Sw分别表示类别间散度矩阵和类别内散度矩阵,定义如下:
Sb = Σk(nk*(mk-m)(mk-m)^T)
Sw = ΣkΣi(xi-mk)(xi-mk)^T
其中mk是第k个类别的均值向量,xi是第k个类别中的第i个样本。J(w)的值越大,说明投影后的类别间距离越大,同一类别内部距离越小。因此,LDA算法的目标是求解J(w)的最大值对应的投影方向w。利用拉格朗日乘数法,将J(w)的约束条件w^T Sw^w = 1加入到目标函数中,得到如下优化问题:
max(w) J(w) = (w^T SbTw)/(wT Sw^w)
subject to: w^T Sw^w = 1
对上述优化问题求解,可以得到特征值问题:
Sw^-1 Sb w = λw
其中λ是特征值,w是特征向量。解出特征向量后,将其按照特征值大小从大到小排序,选择前k个特征向量作为投影方向,将原始数据投影到这些方向上,得到新的低维特征表示。
LDA和PCA的比较
LDA和主成分分析(Principal Component Analysis, PCA)都是常用的降维方法,它们的区别在于降维的目标不同。PCA旨在最大化数据的方差,而LDA旨在最大化类别间距离,同时最小化类别内距离。因此,LDA更适合于分类问题,而PCA更适合于数据可视化等非监督学习任务。
此外,LDA的投影方向是根据类别信息得到的,因此它需要有类别标签的数据才能训练。而PCA只需要原始数据,不需要类别标签。在没有类别标签的情况下,PCA是更为常用的降维方法。
公式推导
设样本集合D={(x1, y1), (x2, y2), …, (xn, yn)},其中xi∈R^d为第i个样本的特征向量,yi∈{0, 1}为第i个样本的类别标签,0表示负样本,1表示正样本。假设正样本数为m1,负样本数为m0,总样本数为m=m0+m1。
计算均值向量
分别计算正样本集合D1和负样本集合D0的均值向量:
μ1 = (1/m1) ∑xi,yi=1
μ0 = (1/m0) ∑xi,yi=0
计算类内散度矩阵
计算正样本集合D1和负样本集合D0的类内散度矩阵Si:
Si = ∑(xi - μi)(xi - μi)^T,yi = i
计算总类内散度矩阵
计算总类内散度矩阵Sw:
Sw = S0 + S1
其中,S0和S1分别为负样本集合D0和正样本集合D1的类内散度矩阵。
计算类间散度矩阵
计算类间散度矩阵Sb:
Sb = (μ1 - μ0)(μ1 - μ0)^T
求解投影方向
目标是求解J(w)的最大值对应的投影方向w。利用拉格朗日乘数法,将J(w)的约束条件w^T Sw^w = 1加入到目标函数中,得到如下优化问题:
max(w) J(w) = (w^T SbTw)/(wT Sw^w)
subject to: w^T Sw^w = 1
对上述优化问题求解,可以得到特征值问题:
Sw^-1 Sb w = λw
其中λ是特征值,w是特征向量。
选择投影方向
将特征向量按照对应的特征值大小从大到小排序,选择前k个特征向量作为投影方向,将原始数据投影到这些方向上,得到新的低维特征表示。
这样,我们就完成了线性判别分析算法的公式推导。
代码示意
import numpy as np
class LinearDiscriminantAnalysis:
def __init__(self):
self.w = None
self.b = None
def fit(self, X, y):
classes = np.unique(y)
n_classes = len(classes)
n_features = X.shape[1]
# Compute the mean vectors of each class
mean_vectors = []
for c in classes:
mean_vectors.append(np.mean(X[y==c], axis=0))
# Compute the within-class scatter matrix
S_w = np.zeros((n_features, n_features))
for c, mv in zip(classes, mean_vectors):
class_sc_mat = np.zeros((n_features, n_features))
for row in X[y == c]:
row, mv = row.reshape(n_features, 1), mv.reshape(n_features, 1)
class_sc_mat += (row - mv).dot((row - mv).T)
S_w += class_sc_mat
# Compute the between-class scatter matrix
overall_mean = np.mean(X, axis=0)
S_b = np.zeros((n_features, n_features))
for c, mean_vec in zip(classes, mean_vectors):
n = X[y==c,:].shape[0]
mean_vec = mean_vec.reshape(n_features,1)
overall_mean = overall_mean.reshape(n_features,1)
S_b += n * (mean_vec - overall_mean).dot((mean_vec - overall_mean).T)
# Compute the eigenvalues and eigenvectors of (S_w^-1)*(S_b)
eig_vals, eig_vecs = np.linalg.eig(np.linalg.inv(S_w).dot(S_b))
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)
# Choose the first k eigenvectors
k = n_classes - 1
self.w = np.hstack([eig_pairs[i][1].reshape(n_features,1) for i in range(k)])
# Compute the bias term
self.b = np.dot(np.mean(X, axis=0), self.w)
def predict(self, X):
return np.sign(X.dot(self.w) - self.b)