Copyright © Microsoft Corporation. All rights reserved. 适用于License版权许可
当数据集有问题,或者网络学习能力不足,或准确度不够时,我们可以采取集成学习的方法,来提升性能。说得通俗一些,就是发挥团队的智慧,根据团队中不同背景、不同能力的成员的独立意见,通过某种决策方法来解决一个问题。所以集成学习也称为多分类器系统(multi-classifier system)、基于委员会的学习(committee-based learning)等。
一个简单的集成学习的示意图如下:
图中有两个组件:
如果所有的个体学习器都是同一类型的学习器,即同质模式,比如都用神经网路,称为“基学习器”(base learner),相应的学习算法称为“基学习算法”(base learning algorithm)。
在传统的机器学习中,个体学习器可以是不同的,比如用决策树、支持向量机等,此时称为异质模式。
个体学习器的输出,通过一定的结合策略,在结合模块中有机结合在一起,可以形成一个能力较强的学习器,所以有时称为强学习器,而相应地称个体学习器为弱学习器。
个体学习器之间是否存在依赖关系呢?这取决于产生个体学习器的方法:
我们只讨论使用神经网络的同质个体学习方法,和Bagging集成算法。由于神经网络的复杂性,即使使用相同的网络参数,由于初始化的不同或者训练数据的不同,也可以得到差别很大的模型。
这是Bagging集成学习的示意图:
def GenerateDataSet(count=9):
mdr = MnistImageDataReader(train_image_file, train_label_file, test_image_file, test_label_file, "vector")
mdr.ReadLessData(1000)
for i in range(count):
X = np.zeros_like(mdr.XTrainRaw)
Y = np.zeros_like(mdr.YTrainRaw)
list = np.random.choice(1000,1000)
k=0
for j in list:
X[k] = mdr.XTrainRaw[j]
Y[k] = mdr.YTrainRaw[j]
k = k+1
# end for
np.savez("level6_" + str(i)+".npz", data=X, label=Y)
# end for
在上面的代码中,我们假设只有1000个手写数据样本,用np.random.choice(1000,1000)函数来可重复地选取1000个数字,分别取出对应的图像数据X和标签数据Y,命名为level6_N.npz,N=[1,9],保存到9个npz文件中。
假设数据集中有m个样本,这样的采样方法,某个样本在第一次被选择的概率是1/m,那么不被选择的概率就是1-1/m,则选择m次后,不被采样到的概率是$(1-\frac{1}{m})^m$,取极限值:
$$\lim_{m \rightarrow \infty} (1-\frac{1}{m})^m \simeq \frac{1}{e} = 0.368$$
即,对于一个新生成的训练数据集来说,原始数据集中的样本没有被使用的概率为36.8%。
这一步很简单,依然用我们在Level0中的过拟合网络,来训练9个神经网络。为了体现“弱学习器”的概念,我们可以在训练每个神经网络时,只迭代10个epoch。
nets = []
net_count = 9
for i in range(net_count):
dataReader = LoadData(i)
net = train(dataReader)
nets.append(net)
上述代码在一个9次的循环中,依次加载我们在前面生成的9个数据集,把训练好的9个net保存到一个列表中,后面测试时使用。
在回归任务中,输出为一个数值,可以使用平均法来处理多个神经网络的输出值。下面公式中的$h_i(x)$表示第i个神经网络的输出,$H(x)$表示集成后的输出。
简单平均法:所有值加起来除以N。 $$H(x)=\frac{1}{N} \sum_{i=1}^N h_i(x)$$
加权平均法:给每个输出值一个人为定义的权重。 $$H(x)=\sum_{i=1}^N w_i \cdot h_i(x)$$
权重值如何给出呢?假设第一个神经网络的准确率为80%,第二个为85%,我们可以令:
$$w1=0.8$$
$$w2=0.85$$
这样准确率高的网络会得到较大的权重值。
对于分类任务,将会从类别标签集合${c_1, c_2, ...,c_n}$中预测出一个值,多个神经网络可能会预测出不一样的值,此时可以采样投票法。
绝对多数投票法(majority voting)
当有半数以上的神经网路预测出同一个类别标签时,我们可以认为此预测有效。如果少于半数,则可以认为预测无效。
比如9个神经网络,5个预测图片上的数字为7,则最终结果就是7。如果有4个神经网络预测为7,3个预测为4,2个预测为1,则认为预测失败。
加权投票法(weighted voting)
与加权平均法类似。
相对多数投票法(plurality voting)
即得票最多的标签获胜。如果有多个标签获得相同的票数,随机选一个。
我们在代码中使用了相对多数投票法,具体过程如下。
假设9个神经网络对于同一张图片的预测结果为:
神经网络ID | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
预测输出 | 7 | 4 | 7 | 4 | 7 | 7 | 9 | 7 | 7 |
可以看到,在9个结果中,有6个结果预测为7,2个预测为4,1个预测为9,我们选择多数投票法,最终的预测结果为7。
为了验证真实的准确率,我们可以用MNIST的测试集中的10000个样本,来测试这9个模型,得到10000行上面表格中的数据,最后再统计最终的准确率。
此处代码比较复杂,最关键的一行语句是:
ra[i] = np.argmax(np.bincount(predict_array[:,i]))
先使用np.bincount得到9个神经网络的预测结果中,每个结果出现的次数,得到:
$$[0,1,0,0,2,0,0,6,0,1]$$
其含义是:数字0出现了0次,数字1出现了1次,......数字4出现了2次,......,数字7出现了6次,等等。然后再用np.argmax([0,1,0,0,2,0,0,6,0,1])得到最大的数字6的下标,结果为7。这样就可以得到9个神经网络的投票结果为该图片上的数字是7,因为有6个神经网络认为是7,占相对多数。
学习法,就是用另外一个神经网络,通过训练的方式,把9个神经网路的输出结果作为输入,把图片的真实数字作为标签,得到一个强学习器。
假设9个神经网络对于原始数据集中的1000个样本的预测结果如下:
神经网络ID | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 标签值 |
---|---|---|---|---|---|---|---|---|---|---|
预测输出1 | 7 | 4 | 7 | 4 | 7 | 7 | 9 | 7 | 7 | 7 |
预测输出2 | 4 | 4 | 7 | 4 | 7 | 4 | 9 | 4 | 7 | 4 |
预测输出N | 0 | 9 | 0 | 0 | 5 | 0 | 0 | 6 | 0 | 0 |
预测输出1000 | 7 | 2 | 2 | 6 | 2 | 2 | 2 | 5 | 2 | 2 |
接下来我们可以建立一个两层的神经网络,输入层为9,用于接收9个神经网络的预测输出,隐层神经元数量不要大于16,输出层为10分类,标签值为上述表格中的最后一列。
我们使用了相对多数投票法,其测试结果为:
神经网络ID | 准确率 |
---|---|
1 | 0.8029 |
2 | 0.701 |
3 | 0.8335 |
4 | 0.7994 |
5 | 0.8254 |
6 | 0.8173 |
7 | 0.8152 |
8 | 0.8321 |
9 | 0.8546 |
9个神经网络的准确率如上表所示,最大的为0.8546,最小的为0.7010。用投票法得到的最后的准确率为0.8726,得到了提升,达到了集成学习的目的。
从偏差-方差的角度看,Bagging主要起到降低方差的作用。在前面我们分析过,单个学习器的过拟合是高方差造成的,我们训练多个这样的学习器,随机选择的样本数据如果分布均匀的话,每个学习器在针对单个测试样本时都会有高方差风险,从而产生泛化误差。但是由于我们拥有9个神经网络,采用集成法后,一定程度上缓解了高方差的现象。
ch16, Level7
首先运行Level6_BootstrappingGenerator.py以获得子数据集,然后运行Level6_BaggingLearner.py来实现集成学习。