0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在一个集成中使用多种模型的使用向导

人工智能和机器人研究院 来源:未知 作者:伍文辉 2017-12-21 15:15 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

在统计学和机器学习领域,集成方法(ensemble method)使用多种学习算法以获得更好的预测性能(相比单独使用其中任何一种算法)。和统计力学中的统计集成(通常是无穷集合)不同,一个机器学习集成仅由一个离散的可选模型的离散集合组成,但通常拥有更加灵活的结构 [1]。

使用集成的主要动机是在发现新的假设,该假设不一定存在于构成模型的假设空间中。从经验的角度看,当模型具有显著的多样性时,集成方法倾向于得到更好的结果 [2]。

动机

在一个大型机器学习竞赛的比赛结果中,最好的结果通常是由模型的集成而不是由单个模型得到的。例如,ILSVRC2015 的得分最高的单个模型架构得到了第 13 名的成绩。而第 1 到 12 名都使用了不同类型的模型集成。

我目前并没有发现有任何的教程或文档教人们如何在一个集成中使用多种模型,因此我决定自己做一个这方面的使用向导。

我将使用 Keras,具体来说是它的功能性 API,以从相对知名的论文中重建三种小型 CNN(相较于 ResNet50、Inception 等而言)。我将在 CIFAR-10 数据集上独立地训练每个模型 [3]。然后使用测试集评估每个模型。之后,我会将所有三个模型组成一个集合,并进行评估。通常按照预期,这个集成相比单独使用其中任何一个模型,在测试集上能获得更好的性能。

有很多种不同类型的集成:其中一种是堆叠(stacking)。这种类型更加通用并且在理论上可以表征任何其它的集成技术。堆叠涉及训练一个学习算法结合多种其它学习算法的预测 [1]。对于这个示例,我将使用堆叠的最简单的一种形式,其中涉及对集成的模型输出取平均值。由于取平均过程不包含任何参数,这种集成不需要训练(只需要训练模型)。

如何在一个集成中使用多种模型的使用向导

本文介绍的集成的简要结构

准备数据

首先,导入类和函数:

  1. fromkeras.modelsimportModel,Input

  2. fromkeras.layersimportConv2D,MaxPooling2D,GlobalAveragePooling2D,Activation,Average,Dropout

  3. fromkeras.utilsimportto_categorical

  4. fromkeras.lossesimportcategorical_crossentropy

  5. fromkeras.callbacksimportModelCheckpoint,TensorBoard

  6. fromkeras.optimizersimportAdam

  7. fromkeras.datasetsimportcifar10

  8. importnumpyasnp

我使用的数据集是 CIFAR-10,因为很容易找到在这个数据集上工作得很好的架构的相关论文。使用一个流行的数据集还可以令这个案例容易复现。

以下是数据集的导入代码。训练数据和测试数据都已经归一化。训练标签向量被转换成一个 one-hot 矩阵。不需要转换测试标签向量,因为它不会在训练中使用。

  1. (x_train, y_train), (x_test, y_test) = cifar10.load_data()

  2. x_train = x_train /255.

  3. x_test = x_test /255.

  4. y_train = to_categorical(y_train, num_classes=10)

数据集由 6 万张 10 个类别的 32x32 的 RGB 图像组成。其中 5 万张用于训练/验证,其它 1 万张用于测试。

  1. print('x_train shape: {} |

  2. y_train shape: {}\nx_test shape : {} |

  3. y_test shape : {}'.format(x_train.shape, y_train.shape, x_test.shape, y_test.shape))

>>> x_train shape: (50000, 32, 32, 3) | y_train shape: (50000, 10)

>>> x_test shape : (10000, 32, 32, 3) | y_test shape : (10000, 1)

由于三个模型使用的是相同类型的数据,定义单个用于所有模型的输入层是合理的。

  1. input_shape = x_train[0,:,:,:].shape

  2. model_input =Input(shape=input_shape)

第一个模型:ConvPool-CNN-C

第一个将要训练的模型是 ConvPool-CNN-C[4]。它使用了常见的模式,即每个卷积层连接一个池化层。唯一一个对一些人来说可能不熟悉的细节是其最后的层。它使用的并不是多个全连接层,而是一个全局平均池化层(global average pooling layer)。

以下是关于全局池化层的工作方式的简介。最后的卷积层 Conv2D(10,(1,1)) 输出和 10 个输出类别相关的 10 个特征图。然后 GlobalAveragePooling2D() 层计算这 10 个特征图的空间平均(spatial average),意味着其输出是一个维度为 10 的向量。之后,对这个向量应用一个 softmax 激活函数。如你所见,这个方法在某种程度上类似于在模型的顶部使用全连接层。可以在这篇论文 [5] 中查看更多关于全局池化层的内容。

重要事项:不要对最后的 Conv2D(10,(1,1)) 层的输出直接应用激活函数,因为这个层的输出需要先输入 GlobalAveragePooling2D()。

  1. defconv_pool_cnn(model_input):

  2. x =Conv2D(96, kernel_size=(3,3), activation='relu', padding = 'same')(model_input)

  3. x =Conv2D(96, (3,3), activation='relu', padding ='same')(x)

  4. x =Conv2D(96, (3,3), activation='relu', padding ='same')(x)

  5. x =MaxPooling2D(pool_size=(3,3), strides =2)(x)

  6. x =Conv2D(192, (3,3), activation='relu', padding ='same')(x)

  7. x =Conv2D(192, (3,3), activation='relu', padding ='same')(x)

  8. x =Conv2D(192, (3,3), activation='relu', padding ='same')(x)

  9. x =MaxPooling2D(pool_size=(3,3), strides =2)(x)

  10. x =Conv2D(192, (3,3), activation='relu', padding ='same')(x)

  11. x =Conv2D(192, (1,1), activation='relu')(x)

  12. x =Conv2D(10, (1,1))(x)

  13. x =GlobalAveragePooling2D()(x)

  14. x =Activation(activation='softmax')(x)

  15. model =Model(model_input, x, name='conv_pool_cnn')

  16. returnmodel

用具体例子解释该模型

  1. conv_pool_cnn_model = conv_pool_cnn(model_input)

为了简单起见,每个模型都使用相同的参数进行编译和训练。其中,epoch 数等于 20、批尺寸等于 32(每个 epoch 进行 1250 次迭代)的参数设置能使三个模型都找到局部极小值。随机选择训练集的 20% 作为验证集。

  1. defcompile_and_train(model, num_epochs):

  2. model.compile(loss=categorical_crossentropy, optimizer=Adam(), metrics=['acc'])

  3. filepath ='weights/'+ model.name +'.{epoch:02d}-{loss:.2f}.hdf5'

  4. checkpoint =ModelCheckpoint(filepath, monitor='loss', verbose=0, save_weights_only=True, save_best_only=True, mode='auto', period=1)

  5. tensor_board =TensorBoard(log_dir='logs/', histogram_freq=0, batch_size=32)

  6. history = model.fit(x=x_train, y=y_train, batch_size=32, epochs=num_epochs, verbose=1, callbacks=[checkpoint, tensor_board], validation_split=0.2)

  7. returnhistory

大约需要每 epoch1 分钟的时间训练这个(以及下一个)模型,我们使用了单个 Tesla K80 GPU。如果你使用的是 CPU,可能需要花较多的时间。

  1. _ = compile_and_train(conv_pool_cnn_model, num_epochs=20)

该模型达到了大约 79% 的验证准确率。

如何在一个集成中使用多种模型的使用向导

ConvPool-CNN-C 验证准确率和损失

通过计算测试集的误差率对模型进行评估。

  1. defevaluate_error(model):

  2. pred=model.predict(x_test,batch_size=32)

  3. pred=np.argmax(pred,axis=1)

  4. pred=np.expand_dims(pred,axis=1)# make same shape as y_test

  5. error=np.sum(np.not_equal(pred,y_test))/y_test.shape[0]

  6. returnerror

  7. evaluate_error(conv_pool_cnn_model)

>>> 0.2414

第二个模型:ALL-CNN-C

下一个模型,ALL-CNN-C,来自同一篇论文 [4]。这个模型和上一个很类似。唯一的区别是用步幅为 2 的卷积层取代了最大池化层。再次,需要注意,在 Conv2D(10,(1,1)) 层之后不要立刻应用激活函数,如果在该层之后应用了 ReLU 激活函数,会导致训练失败。

  1. defall_cnn(model_input):

  2. x=Conv2D(96,kernel_size=(3,3),activation='relu',padding='same')(model_input)

  3. x=Conv2D(96,(3,3),activation='relu',padding='same')(x)

  4. x=Conv2D(96,(3,3),activation='relu',padding='same',strides=2)(x)

  5. x=Conv2D(192,(3,3),activation='relu',padding='same')(x)

  6. x=Conv2D(192,(3,3),activation='relu',padding='same')(x)

  7. x=Conv2D(192,(3,3),activation='relu',padding='same',strides=2)(x)

  8. x=Conv2D(192,(3,3),activation='relu',padding='same')(x)

  9. x=Conv2D(192,(1,1),activation='relu')(x)

  10. x=Conv2D(10,(1,1))(x)

  11. x=GlobalAveragePooling2D()(x)

  12. x=Activation(activation='softmax')(x)

  13. model=Model(model_input,x,name='all_cnn')

  14. returnmodel

  15. all_cnn_model=all_cnn(model_input)

  16. _=compile_and_train(all_cnn_model,num_epochs=20)

该模型收敛到了大约 75% 的验证准确率。

如何在一个集成中使用多种模型的使用向导

ConvPool-CNN-C 验证准确率和损失

由于这两个模型很相似,误差率差别不大。

  1. evaluate_error(all_cnn_model)

>>> 0.26090000000000002

第三个模型:Network In Network CNN

第三个 CNN 是 Network In Network CNN[5]。这个模型来自引入了全局池化层的论文。它比之前的两个模型更小,因此其训练速度更快。(再提醒一次,不要在最后的卷积层之后使用 ReLU 函数!)

相较于在 MLP 卷积层中使用多层感知机,我使用的是 1x1 卷积核的卷积层。从而需要优化的参数变得更少,训练速度进一步加快,并且还获得了更好的结果(当使用全连接层的时候无法获得高于 50% 的验证准确率)。该论文中称,MLP 卷积层中应用的函数等价于在普通卷积层上的级联跨通道参数化池化(cascaded cross channel parametric pooling),其中依次等价于一个 1x1 卷积核的卷积层。如果这个结论有错误,欢迎指正。

  1. defnin_cnn(model_input):

  2. #mlpconv block 1

  3. x=Conv2D(32,(5,5),activation='relu',padding='valid')(model_input)

  4. x=Conv2D(32,(1,1),activation='relu')(x)

  5. x=Conv2D(32,(1,1),activation='relu')(x)

  6. x=MaxPooling2D((2,2))(x)

  7. x=Dropout(0.5)(x)

  8. #mlpconv block2

  9. x=Conv2D(64,(3,3),activation='relu',padding='valid')(x)

  10. x=Conv2D(64,(1,1),activation='relu')(x)

  11. x=Conv2D(64,(1,1),activation='relu')(x)

  12. x=MaxPooling2D((2,2))(x)

  13. x=Dropout(0.5)(x)

  14. #mlpconv block3

  15. x=Conv2D(128,(3,3),activation='relu',padding='valid')(x)

  16. x=Conv2D(32,(1,1),activation='relu')(x)

  17. x=Conv2D(10,(1,1))(x)

  18. x=GlobalAveragePooling2D()(x)

  19. x=Activation(activation='softmax')(x)

  20. model=Model(model_input,x,name='nin_cnn')

  21. returnmodel

  22. nin_cnn_model=nin_cnn(model_input)

这个模型的训练速度快得多,在我的机器上每个 epoch 只要 15 秒就能完成。

  1. _=compile_and_train(nin_cnn_model,num_epochs=20)

该模型达到了大约 65% 的验证准确率。

如何在一个集成中使用多种模型的使用向导

NIN-CNN 验证准确率和损失

这个模型比之前的两个模型简单得多,因此其误差率要高一点。

  1. evaluate_error(nin_cnn_model)

>>> 0. 0.31640000000000001

三个模型的集成

现在将这三个模型组合成一个集成。

所有三个模型都被重新实例化并加载了最佳的已保存权重。

  1. conv_pool_cnn_model=conv_pool_cnn(model_input)

  2. all_cnn_model=all_cnn(model_input)

  3. nin_cnn_model=nin_cnn(model_input)

  4. conv_pool_cnn_model.load_weights('weights/conv_pool_cnn.29-0.10.hdf5')

  5. all_cnn_model.load_weights('weights/all_cnn.30-0.08.hdf5')

  6. nin_cnn_model.load_weights('weights/nin_cnn.30-0.93.hdf5')

  7. models=[conv_pool_cnn_model,all_cnn_model,nin_cnn_model]

集成模型的定义是很直接的。它使用了所有模型共享的输入层。在顶部的层中,该集成通过使用 Average() 合并层计算三个模型输出的平均值。

  1. defensemble(models,model_input):

  2. outputs=[model.outputs[0]formodelinmodels]

  3. y=Average()(outputs)

  4. model=Model(model_input,y,name='ensemble')

  5. returnmodel

  6. ensemble_model=ensemble(models,model_input)

不出所料,相比于任何单一模型,集成有着更低的误差率。

  1. evaluate_error(ensemble_model)

>>> 0.2049

其他可能的集成

为了完整性,我们可以查看由两个模型组合组成的集成的性能。相比于单一模型,前者有更低的误差率。

  1. pair_A=[conv_pool_cnn_model,all_cnn_model]

  2. pair_B=[conv_pool_cnn_model,nin_cnn_model]

  3. pair_C=[all_cnn_model,nin_cnn_model]

  4. pair_A_ensemble_model=ensemble(pair_A,model_input)

  5. evaluate_error(pair_A_ensemble_model)

>>> 0.21199999999999999

  1. pair_B_ensemble_model=ensemble(pair_B,model_input)

  2. evaluate_error(pair_B_ensemble_model)

>>> 0.22819999999999999

  1. pair_C_ensemble_model=ensemble(pair_C,model_input)

  2. evaluate_error(pair_C_ensemble_model)

>>>0.2447

结论

重申一下介绍中的内容:每个模型有其自身的缺陷。使用集成背后的原因是通过堆叠表征了关于数据的不同假设的不同模型,我们可以找到一个更好的假设,它不在一个从其构建集成的模型的假设空间之中。

与在大多数情况下使用单个模型相比,使用一个非常基础的集成实现了更低的误差率。这证明了集成的有效性。

当然,在使用集成处理你的机器学习任务时,需要牢记一些实际的考虑。由于集成意味着同时堆栈多个模型,这也意味着输入数据需要前向传播到每个模型。这增加了需要被执行的计算量,以及最终的评估(预测)时间。如果你在研究或 Kaggle 竞赛中使用集成,增加的评估时间并不重要,但是在设计一个商业化产品时却非常关键。另一个考虑是最后的模型增加的大小,它会再次成为商业化产品中集成使用的限制性因素。

参考文献

1. Ensemble Learning. (n.d.). In Wikipedia. Retrieved December 12, 2017, from https://en.wikipedia.org/wiki/Ensemble_learning

2. D. Opitz and R. Maclin (1999)「Popular Ensemble Methods: An Empirical Study」, Volume 11, pages 169–198 (http://jair.org/papers/paper614.html)

3. Learning Multiple Layers of Features from Tiny Images, Alex Krizhevsky, 2009.

4. Striving for Simplicity: The All Convolutional Net:arXiv:1412.6806v3 [cs.LG]

5. Network In Network:arXiv:1312.4400v3 [cs.NE]


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 集成
    +关注

    关注

    1

    文章

    178

    浏览量

    30816
  • keras
    +关注

    关注

    2

    文章

    20

    浏览量

    6283

原文标题:如何使用Keras集成多个卷积网络并实现共同预测

文章出处:【微信号:gh_ecbcc3b6eabf,微信公众号:人工智能和机器人研究院】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    何在AMD Vitis Unified IDE中使用系统设备树

    您将在这篇博客中了解系统设备树 (SDT) 以及如何在 AMD Vitis Unified IDE 中使用 SDT 维护来自 XSA 的硬件元数据。本文还讲述了如何对 SDT 进行操作,以便在 Vitis Unified IDE 中实现更灵活的使用场景。
    的头像 发表于 11-18 11:13 2809次阅读
    如<b class='flag-5'>何在</b>AMD Vitis Unified IDE<b class='flag-5'>中使</b>用系统设备树

    何在VS code中配置Zephyr集成开发环境

    篇文章介绍了如何在VS code中使用瑞萨官方插件为RA芯片创建项目与项目调试,相信大家对RA在VS code中的开发有了基础的了解。
    的头像 发表于 11-05 14:46 1063次阅读
    如<b class='flag-5'>何在</b>VS code中配置Zephyr<b class='flag-5'>集成</b>开发环境

    何在vivadoHLS中使用.TLite模型

    本帖欲分享如何在vivadoHLS中使用.TLite模型。在Vivado HLS中导入模型后,需要设置其输入和输出接口以与您的设计进行适配。 1. 在Vivado HLS项目中导入
    发表于 10-22 06:29

    高效反向导通IGBT的原理详解

    在先进的反向导通绝缘栅双极晶体管(RCIGBT)中,低导通电压降(Vce(sat))和集成二极管正向电压(VF)对于有效减少导通损耗至关重要。
    的头像 发表于 10-10 09:25 2025次阅读
    高效反<b class='flag-5'>向导</b>通IGBT的原理详解

    请问如何在 Keil μVision 或 IAR EWARM 中使用观察点进行调试?

    何在 Keil μVision 或 IAR EWARM 中使用观察点进行调试?
    发表于 08-20 06:29

    请问如何在RK3588上使用npu,用onnx模型来推理

    请问如何在瑞芯微 RK3588上使用npu,用onnx模型来推理。官网上介绍说要把ONNX模型转换成RKNN模型。但是我并不想这么干,请问有什么办法吗?
    发表于 08-09 00:51

    请问如何在C++中使用NPU上的模型缓存?

    无法确定如何在 C++ 中的 NPU 上使用模型缓存
    发表于 06-24 07:25

    如何将FA模型开发的声明式范式应用切换到Stage模型

    模型切换概述 本文介绍如何将FA模型开发的声明式范式应用切换到Stage模型,您需要完成如下动作: 工程切换:新建
    发表于 06-04 06:22

    射频前端模块中使用的集成无源元件技术

    本文介绍了在射频前端模块(RF-FEM)中使用的集成无源元件(IPD)技术。
    的头像 发表于 06-03 18:26 1084次阅读
    射频前端模块<b class='flag-5'>中使</b>用的<b class='flag-5'>集成</b>无源元件技术

    何在Ollama中使用OpenVINO后端

    Ollama 和 OpenVINO 的结合为大型语言模型(LLM)的管理和推理提供了强大的双引擎驱动。Ollama 提供了极简的模型管理工具链,而 OpenVINO 则通过 Intel 硬件(CPU
    的头像 发表于 04-14 10:22 1118次阅读

    如何实现MC33774IC在Simulink环境中使用基于模型的设计?

    我想熟悉如何实现MC33774IC 在 Simulink 环境中使用基于模型的设计。 尽管 MATLAB 提供了些示例文件,但它们似乎是最终版本。要更深入地了解如何配置MC33774,我正在寻找
    发表于 04-10 08:05

    何在MATLAB中使用DeepSeek模型

    在 DeepSeek-R1(https://github.com/deepseek-ai/DeepSeek-R1) AI 模型横空出世后,人们几乎就立马开始询问如何在 MATLAB 中使用这些
    的头像 发表于 02-13 09:20 4057次阅读
    如<b class='flag-5'>何在</b>MATLAB<b class='flag-5'>中使</b>用DeepSeek<b class='flag-5'>模型</b>

    C#中使用OpenVINO™:轻松集成AI模型

    与分析三大领域中,如何快速将AI模型集成到应用程序中,实现AI赋能和应用增值?最容易的方式是:在C#中,使用OpenVINO™工具套件集成AI模型
    的头像 发表于 02-07 14:05 1642次阅读
    C#<b class='flag-5'>中使</b>用OpenVINO™:轻松<b class='flag-5'>集成</b>AI<b class='flag-5'>模型</b>!

    何在Windows中使用MTP协议

    在Windows操作系统中使用MTP(Media Transfer Protocol)协议主要涉及到与移动设备(如智能手机、平板电脑等)的连接和数据传输。MTP是种用于交换媒体文件(如音乐、视频
    的头像 发表于 01-03 10:26 4407次阅读

    【「大模型启示录」阅读体验】如何在客服领域应用大模型

    模型可以提高客户满意度和服务质量。新引入的模型需要能够无缝集成到现有系统中,以确保服务的连续性和稳定性。因此,在选择模型时需要考虑其与现有系统的兼容性。同时,随着企业业务的发展,可能
    发表于 12-17 16:53