LDA线性判别分析原理及python应⽤(葡萄酒案例分析)
⽬录
线性判别分析(LDA)数据降维及案例实战
⼀、LDA是什么
LDA概念及与PCA区别
LDA线性判别分析(Linear Discriminant Analysis)也是⼀种特征提取、数据压缩技术。在模型训练时候进⾏LDA数据处理可以提⾼计算效率以及避免过拟合。它是⼀种有监督学习算法。
与PCA主成分分析(Principal Component Analysis)相⽐,LDA是有监督数据压缩⽅法,⽽PCA是有监督数据压缩及特征提取⽅法。PCA ⽬标是寻数据集最⼤⽅差⽅向作为主成分,LDA⽬标是寻和优化具有可分性特征⼦空间。其实两者各有优势,更深⼊详细的区分和应⽤等待之后的学习,这⾥我仍然以葡萄酒数据集分类为案例记录原理知识的学习和具体实现步骤。
对⽐我之前记录的PCA请看:
LDA内部逻辑实现步骤
1. 标准化d维数据集。
2. 计算每个类别的d维均值向量。
3. 计算跨类散布矩阵和类内散布矩阵.
4. 线性判别式及特征计算。
5. 按特征值降序排列,与对应的特征向量成对排序。
6. 选择最具线性判别性的前k个特征,构建变换矩阵.
7. 通过变换矩阵将原数据投影⾄k维⼦空间。
pycharm下载第三方库⼆、计算散布矩阵
1、数据集下载
下载葡萄酒数据集到本地,或者到时在加载数据代码是从远程服务器获取,为了避免加载超时推荐下载本地数据集。
下载之后⽤记事本打开wine.data可见得,第⼀列为葡萄酒数据类别标签,共有3类,往后的13列为特征值。
数据加载以及标准化数据处理与PCA技术⼀样,具体可以翻看,或者本⽂第五部分完整代码有具体实现代码。
2、计算散布矩阵第⼀步,先计算每个类别每个样本的均值向量。
公式:, i =1,2,3 表⽰类别,每个特征取平均值。
得到三个均值向量为:
代码实现:
# 计算均值向量
np.set_printoptions(precision=4)
mean_vecs = []
for label in range(1, 4):
mean_vecs.an(x_train_std[y_train == label], axis=0))
打印查看结果:
3、计算类内散布矩阵。
每个样本 i 的散布矩阵:
类内散布矩阵即每个样本的累加:
代码实现:
# 计算类内散布矩阵
k = 13
Sw = np.zeros((k, k))
for label, mv in zip(range(1, 4), mean_vecs):
Si = np.zeros((k, k))
Si = np.cov(x_train_std[y_train == label].T)
Sw += Si
print("类内散布矩阵:",Sw.shape[0],"*",Sw.shape[1])
矩阵规模:
4、计算跨类散布矩阵。
公式:
公式中,m是所有样本总均值向量,也就是不分类的情况下计算特征平均值。
代码实现:
# 计算跨类散布矩阵
mean_all = np.mean(x_train_std, axis=0)
Sb = np.zeros((k, k))
for i, col_mv in enumerate(mean_vecs):
n = x_train[y_train == i + 1, :].shape[0]
col_mv = shape(k, 1) # 列均值向量
mean_all = shape(k, 1)
Sb += n * (col_mv - mean_all).dot((col_mv - mean_all).T)
三、线性判别式及特征选择
LDA其他步骤与PCA相似,但是,PCA是分解协⽅差矩阵提取特征值,LDA则是求解矩阵得到⼴义特征值,实现:# 计算⼴义特征值
eigen_vals, eigen_vecs = np.linalg.eig(np.linalg.inv(Sw).dot(Sb))
eigen_pairs = [(np.abs(eigen_vals[i]), eigen_vecs[:, i]) for i in range(len(eigen_vals))]
eigen_pairs = sorted(eigen_pairs, key=lambda k: k[0], reverse=True)
对特征值降序排列之后,打印看看:
print("特征值降序排列:")
for eigen_val in eigen_pairs:
print(eigen_val[0])
从捕捉到的特征值发现,前两个可以占据⼤部分数据集特征了,接下来可视化表⽰更加直观地观察:
# 线性判别捕捉,计算辨识⼒
tot = sum(al)
discr = []
# discr=[(i/tot) for i in sorted(al,reverse=True)]
for i in sorted(al, reverse=True):
discr.append(i / tot)
# print(discr)
cum_discr = np.cumsum(discr) # 计算累加⽅差
plt.bar(range(1,14),discr,alpha=0.5,align='center',label='独⽴辨识⼒')
plt.step(range(1,14),cum_discr,where='mid',label='累加辨识⼒')
plt.ylabel('"辨识⼒"⽐')
plt.xlabel('线性判别')
plt.ylim([-0.1,1.1])
plt.legend(loc='best')
plt.show()
很明显,最具线性判别的前两个特征捕捉了100%的信息,下⾯以此构建变换矩阵 W.
四、样本数据降维投影
构建变换矩阵:
# 变换矩阵
w = np.hstack((eigen_pairs[0][1][:, np.newaxis].real, eigen_pairs[1][1][:, np.newaxis].real))
print(w)
来瞅瞅,这就是前两个特征向量的矩阵表⽰。
现在有了变换矩阵,就可以将样本训练数据投影到降维特征空间了:. 并展⽰分类结果:# 样本数据投影到低维空间
x_train_lda = x_train_std.dot(w)
colors = ['r', 'g', 'b']
marks = ['s', 'x', 'o']
for l, c, m in zip(np.unique(y_train), colors, marks):
plt.scatter(x_train_lda[y_train == l, 0],
c=c, label=l, marker=m)
plt.xlabel('LD 1')
plt.ylabel('LD 2')
plt.legend(loc='lower right')
plt.show()
很明显,三个类别线性可分,效果也不错,相⽐较,我感觉LDA分类结果更好,我们知道,LDA是有监督的⽅法,有利⽤到数据集的标签。
五、完整代码
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
del_selection import train_test_split
import matplotlib.pyplot as plt
# load data
df_wine = pd.read_csv('D:\\PyCharm_Project\\maching_learning\\wine_data\\wine.data', header=None) # 本地加载
# df_ad_csv('archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data',header=None)#服务器加载
# split the data,train:test=7:3
x, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].values
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, stratify=y, random_state=0)
# standardize the feature 标准化单位⽅差
sc = StandardScaler()
x_train_std = sc.fit_transform(x_train)
x_test_std = sc.fit_transform(x_test)
# 计算均值向量
np.set_printoptions(precision=4)
mean_vecs = []
for label in range(1, 4):
mean_vecs.an(x_train_std[y_train == label], axis=0))
# print("Mean Vectors %s:" % label,mean_vecs[label-1])
# 计算类内散布矩阵
k = 13
Sw = np.zeros((k, k))
for label, mv in zip(range(1, 4), mean_vecs):
Si = np.zeros((k, k))
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论