使用sklearn在Python中绘制两类线性判别分析(LDA)结果失败的技术问询
嘿,这个问题我碰到过!核心原因是LDA在二分类和多分类时输出的维度逻辑不一样,我来给你拆解清楚并解决~
首先得明确LDA的核心逻辑:对于K类分类问题,LDA最多会生成K-1个线性判别式(LD)。所以当你做二分类(T类/非T类)时,只会得到1个LD维度,也就是X_lda_sklearn是一维数组(形状为(n_samples,)),而不是三分类时的二维数组((n_samples,2))。这就是你访问X[:,1]时会触发“索引越界”错误的根本原因。
下面给你两种解决方案,按需选择:
方案1:适配一维LDA结果的可视化(推荐,更贴合实际意义)
既然二分类只有1个LD维度,我们可以直接用这个维度作为x轴,把类别作为y轴区分数据,这样能直观展示LDA在唯一判别维度上的分类效果。修改后的代码如下:
import matplotlib.pyplot as plt from sklearn.discriminant_analysis import LinearDiscriminantAnalysis # 替换成你的实际数据处理逻辑 X = PODall.drop('标签列名', axis=1) # 把'标签列名'改成你存储0/1标签的列名 y = PODall['标签列名'] # 训练LDA并转换数据 sklearn_lda = LinearDiscriminantAnalysis() X_lda_sklearn = sklearn_lda.fit_transform(X, y) def plot_scikit_lda_binary(X, y, title): ax = plt.subplot(111) # 针对二分类的标签(0=非T类,1=T类)设置样式 for label, marker, color, label_name in zip( [0, 1], ('o', 's'), ('blue', 'red'), ['非T类', 'T类']): plt.scatter( x=X[y == label], y=[label]*len(X[y == label]), # 用标签值作为y轴,将两类数据垂直分开 marker=marker, color=color, alpha=0.5, label=label_name ) plt.xlabel('LD1') plt.ylabel('类别') leg = plt.legend(loc='upper right', fancybox=True) leg.get_frame().set_alpha(0.5) plt.title(title) # 美化图表细节 plt.tick_params(axis="both", which="both", bottom="on", top="off", left="on", right="off") ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) plt.grid(axis='x') plt.tight_layout() plt.show() # 调用绘图函数 plot_scikit_lda_binary(X_lda_sklearn, y, title='二分类LDA结果可视化 (scikit-learn)')
方案2:手动添加维度,模拟二维绘图(适合和三分类可视化风格统一)
如果你希望保持和三分类时完全一致的二维图布局,可以手动给一维的LDA结果添加一列全0的“伪LD2”,这样就能直接复用你原有代码的结构:
import numpy as np import matplotlib.pyplot as plt from sklearn.discriminant_analysis import LinearDiscriminantAnalysis # 同样替换成你的实际数据处理逻辑 X = PODall.drop('标签列名', axis=1) y = PODall['标签列名'] sklearn_lda = LinearDiscriminantAnalysis() X_lda_sklearn = sklearn_lda.fit_transform(X, y) # 把一维数组转换成二维,添加全0的第二列作为伪LD2 X_lda_2d = np.column_stack((X_lda_sklearn, np.zeros_like(X_lda_sklearn))) def plot_scikit_lda(X, y, title): ax = plt.subplot(111) for label, marker, color, label_name in zip( [0, 1], ('o', 's'), ('blue', 'red'), ['非T类', 'T类']): plt.scatter( x=X[:,0][y == label], y=X[:,1][y == label] * -1, # 乘-1不影响,因为第二列全是0 marker=marker, color=color, alpha=0.5, label=label_name ) plt.xlabel('LD1') plt.ylabel('LD2') leg = plt.legend(loc='upper right', fancybox=True) leg.get_frame().set_alpha(0.5) plt.title(title) # 保留你原来的图表美化逻辑 plt.tick_params(axis="both", which="both", bottom="on", top="off", labelbottom="on", left="off", right="off", labelleft="on") ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) ax.spines["bottom"].set_visible(False) ax.spines["left"].set_visible(False) plt.grid() plt.tight_layout() plt.show() # 调用绘图函数 plot_scikit_lda(X_lda_2d, y, title='二分类LDA结果可视化(模拟二维)')
注意:方案2中的LD2没有实际意义,只是为了适配原有代码结构,如果是做分析推荐用方案1哦~
内容的提问来源于stack exchange,提问作者CJohnson
相关产品推荐
相关产品推荐

