Python线性分类
努力奋斗的K崽 人气:0通过约束类的协方差相等,将贝叶斯分类器简化为线性分类器。
比较生成模型和判别模型在挑战性分类任务中的性能。
在本实验课中:我们将比较线性分类的“生成建模”和“判别建模”方法。对于“生成”方法,我们将重新讨论我们在前面练习中使用的贝叶斯分类代码,但我们将限制系统具有相等的协方差矩阵,即一个协方差矩阵来表示所有类别,而不是每个类别都有其自己的协方差矩阵。在这种情况下,系统成为线性分类器。我们将把它与“判别式”方法进行比较,在这种方法中,我们使用感知器学习算法直接学习线性分类器参数。
在本笔记本中,我们将使用UCI机器学习库中的另一个数据集:鲍鱼数据。鲍鱼是一种海螺。一个样本的年龄可以通过在圆锥体上切割外壳和用显微镜(更像是树木)计数环来确定,但这是一个耗时且昂贵的过程。这里的任务是通过简单的外部测量动物的重量和尺寸,尝试并预测环的数量。对于我们正在使用的数据集,环数的真实值是已知的(即,在测量蜗牛后对环进行计数)。结果从1到29个环不等,因此这通常被视为29类分类问题。为了简化一些,我将数据重新组合成两个大小大致相同的类:年轻(少于10个环)和老年(10个或更多个环)。我也只采集了女性样本。有7个测量值(都是高度相关的)用于预测类别标签。
生成性建模:具有等协变多元正态分布的贝叶斯分类。
与上一个介绍相比,有更多的样本(1306个,178个),因此我们不必担心遗漏一个测试,相反,我们只需像上一个一样,将数据切割成大小相同的测试和训练集。
通过修改上次编写的代码,使用具有完全协方差矩阵的多元正态分布来评估贝叶斯分类器的性能。在考虑对代码进行更改时,请注意,主要区别在于本笔记本中只有两个类,而不是三个。(如果您愿意,您可以尝试将代码包装到函数中,看看是否可以将其设计为适用于任意数量的类。)
您的分类器的性能如何?此任务的分数可能在60%-70%之间,因此,如果性能似乎比前一个任务差很多,请不要担心。如果性能低于60%,那么您应该检查代码是否存在可能的bug。
import numpy as np X = np.loadtxt(open("data/abalone.txt", "r")) X.shape from scipy.stats import multivariate_normal import matplotlib.pyplot as plt %matplotlib inline abalone1 = X[X[:, 0] == 1, :] abalone2 = X[X[:, 0] == 2, :] abalone1_test = abalone1[0::2, :] abalone1_train = abalone1[1::2, :] abalone2_test = abalone2[0::2, :] abalone2_train = abalone2[1::2, :] abalone_test = np.vstack((abalone1_test, abalone2_test)) abalone_test.shape mean1 = np.mean(abalone1_train[:, 1:], axis=0) mean2 = np.mean(abalone2_train[:, 1:], axis=0) cov1 = np.cov(abalone1_train[:, 1:], rowvar=0) cov2 = np.cov(abalone2_train[:, 1:], rowvar=0) dist1 = multivariate_normal(mean=mean1, cov=cov1) dist2 = multivariate_normal(mean=mean2, cov=cov2) p1 = dist1.pdf(abalone_test[:, 1:]) p2 = dist2.pdf(abalone_test[:, 1:]) p = np.vstack((p1, p2)) index = np.argmax(p, axis=0) + 1 plt.plot(index, "k.", ms=10) correct = abalone_test[:, 0] == index percent_correct = np.sum(correct) * 100.0 / index.shape print(percent_correct)
rowvarbool,可选
如果rowvar为True(默认),则每行表示一个变量,列中包含观察值。否则,关系将被转换:每列表示一个变量,而行包含观察值。
使用等协方差矩阵:
如果您正确地遵循了与上一本笔记相同的步骤,您将为每个类估计出一个单独的协方差矩阵。这些矩阵将不相等,因此您的系统将不是线性分类器(即,它将具有非平面决策边界)。为了将其简化为线性系统,我们需要确保只有一个协方差矩阵。您可以想象这样做的不
同方式:
首先,您可以想象简单地从完整的训练集中估计单个协方差矩阵,然后再将其划分为类。这将生成一个矩阵,但这不是正确的做法。我们希望矩阵表示类内的分布,如果您仅使用完整的训练数据集训练模型,它还将捕获类间的分布。
其次,可以想象平均两个类相关协方差矩阵。这更接近于正确的情况,但它没有考虑到类的示例数可能不相等这一事实。
最好的方法是首先将两个类的中心移动到同一点上,然后将它们视为单个类。要将类中心移动到同一点上,只需从每个数据样本中减去类平均向量。
def centre_data(data): nsamples = data.shape[0] data_mean = np.mean(data, axis=0) data_centred = data - data_mean return data_centred abalone1_centred = centre_data(abalone1_train) abalone2_centred = centre_data(abalone2_train) abalone_centred = np.vstack((abalone1_centred, abalone2_centred)) cov_global = np.cov(abalone_centred[:, 1:], rowvar=0) dist1 = multivariate_normal(mean=mean1, cov=cov_global) dist2 = multivariate_normal(mean=mean2, cov=cov_global) p1 = dist1.pdf(abalone_test[:, 1:]) p2 = dist2.pdf(abalone_test[:, 1:]) p = np.vstack((p1, p2)) index = np.argmax(p, axis=0) + 1 plt.plot(index, "k.", ms=10) correct = abalone_test[:, 0] == index percent_correct = np.sum(correct) * 100.0 / index.shape print(percent_correct)
加载全部内容