python实现LDA降维,不使用sklearn
时间: 2023-07-28 11:35:20 浏览: 115
实现LDA降维的过程可以分为以下几个步骤:
1. 计算每个类别的均值向量
假设有k个类别,每个类别有n个样本,第i个类别的均值向量为:
![lda_1](https://cdn.jsdelivr.net/gh/lixinxislx/CDN/2021-12-29/1640762986464965.png)
其中,xi为第i个类别中第j个样本的第k个特征值,m为总体均值向量。
2. 计算类内散度矩阵Sw
类内散度矩阵Sw表示每个类别内部的差异性,可以通过计算每个类别内部的协方差矩阵,并将它们加权求和得到。第i个类别的协方差矩阵为:
![lda_2](https://cdn.jsdelivr.net/gh/lixinxislx/CDN/2021-12-29/1640763221830521.png)
其中,Si为第i个类别的协方差矩阵,ni为第i个类别的样本数。
类内散度矩阵Sw为各个类别协方差矩阵的加权和,即:
![lda_3](https://cdn.jsdelivr.net/gh/lixinxislx/CDN/2021-12-29/1640763343077808.png)
3. 计算类间散度矩阵Sb
类间散度矩阵Sb表示不同类别之间的差异性,可以通过计算所有类别的均值向量的协方差矩阵得到。总体协方差矩阵为:
![lda_4](https://cdn.jsdelivr.net/gh/lixinxislx/CDN/2021-12-29/1640763500276458.png)
其中,ni为第i个类别的样本数。
类间散度矩阵Sb为总体协方差矩阵减去类内散度矩阵Sw,即:
![lda_5](https://cdn.jsdelivr.net/gh/lixinxislx/CDN/2021-12-29/1640763618844408.png)
4. 计算投影方向
将类间散度矩阵Sb和类内散度矩阵Sw做特征值分解,得到它们的特征值和特征向量。特征向量组成的矩阵就是投影矩阵W。
5. 降维
将数据矩阵X与投影矩阵W相乘,得到降维后的数据矩阵X_lda。
下面是Python实现LDA降维的代码:
```python
import numpy as np
def LDA(X, y, n_components):
'''
X: 数据矩阵,每行表示一个样本,每列表示一个特征
y: 标签向量,表示每个样本的类别
n_components: 要降到的维度数
'''
# 计算均值向量和总体均值向量
class_list = np.unique(y)
m = np.mean(X, axis=0)
m_list = []
for i in range(len(class_list)):
m_i = np.mean(X[y==class_list[i]], axis=0)
m_list.append(m_i)
m_list = np.array(m_list)
# 计算类内散度矩阵
Sw = np.zeros((X.shape[1], X.shape[1]))
for i in range(len(class_list)):
Xi = X[y==class_list[i]]
Si = np.cov(Xi.T)
Sw += (Xi.shape[0] - 1) * Si
# 计算类间散度矩阵
Sb = np.cov(X.T) - Sw
# 计算投影方向
eig_vals, eig_vecs = np.linalg.eig(np.linalg.inv(Sw).dot(Sb))
idx = np.argsort(-eig_vals)
W = eig_vecs[:, idx[:n_components]]
# 降维
X_lda = X.dot(W)
return X_lda
```
其中,X为数据矩阵,每行表示一个样本,每列表示一个特征;y为标签向量,表示每个样本的类别;n_components为要降到的维度数。函数返回降维后的数据矩阵X_lda。
使用方法如下:
```python
X = np.array(...) # 数据矩阵
y = np.array(...) # 标签
X_lda = LDA(X, y, n_components)
```
需要注意的是,当样本数小于特征数时,类内散度矩阵不可逆,无法使用LDA降维。此时可以考虑使用PCA等无监督方法进行降维。
阅读全文