2017-06-07 23:56:45 heyc861221 阅读数 1642
  • 深度学习框架Tensorflow案例实战视频课程

    深度学习框架Tensorflow案例实战视频培训课程概况: Tensorflow是谷歌开源的深度学习(包括机器学习)框架,伴随着人工智能业的兴盛其大名早已响彻云霄。本课程从Tensorflow安装开始讲起,从基本计算结构到深度学习各大神经网络,全程案例代码实战,一步步带大家入门如何使用深度学习框架Tensorflow,玩转Tensorflow模型训练、等所有知识点。

    30268 人正在学习 去看看 唐宇迪

作者:陈迪豪,小米深度学习工程师,负责小米云深度学习平台的架构和实现,目前专注于TensorFlow和Kubernetes社区。
责编:何永灿,欢迎人工智能领域技术投稿、约稿、给文章纠错,请发送邮件至heyc#csdn.net(#改为@)
本文为《程序员》原创文章,未经允许不得转载,更多精彩文章请订阅《程序员》

深度学习服务介绍

机器学习与人工智能,相信大家已经耳熟能详,随着大规模标记数据的积累、神经网络算法的成熟以及高性能通用GPU的推广,深度学习逐渐成为计算机专家以及大数据科学家的研究重点。近年来,无论是图像的分类、识别和检测,还是语音生成、自然语言处理,甚至是AI下围棋或者打游戏都基于深度学习有了很大的突破。而随着TensorFlow、Caffe等开源框架的发展,深度学习的门槛变得越来越低,甚至初中生都可以轻易实现一个图像分类或者自动驾驶的神经网络模型,但目前最前沿的成果主要还是出自Google、微软等巨头企业。

Google不仅拥有优秀的人才储备和大数据资源,其得天独厚的基础架构也极大推动了AI业务的发展,得益于内部的大规模集群调度系统Borg,开发者可以快速申请大量GPU资源进行模型训练和上线模型服务,并且通过资源共享和自动调度保证整体资源利用率也很高。Google开源了TensorFlow深度学习框架,让开发者可以在本地轻易地组合MLP、CNN和RNN等模块实现复杂的神经网络模型,但TensorFlow只是一个数值计算库,并不能解决资源隔离、任务调度等问题,将深度学习框架集成到基于云计算的基础架构上将是下一个关键任务。

除了Google、微软,国内的百度也开源了PaddlePaddle分布式计算框架,并且官方集成了Kubernetes等容器调度系统,用户可以基于PaddlePaddle框架实现神经网络模型,同时利用容器的隔离性和Kubernetes的资源共享、自动调度、故障恢复等特性,但平台不能支持更多深度学习框架接口。而亚马逊和腾讯云相继推出了面向开发者的公有云服务,可以同时支持多种主流的开源深度学习框架,阿里、金山和小米也即将推出基于GPU的云深度学习服务,还有无数企业在默默地研发内部的机器学习平台和大数据服务。

面对如此眼花缭乱的云服务和开源技术,架构师该如何考虑其中的技术细节,从用户的角度又该如何选择这些平台或者服务呢。我将介绍小米云深度学习平台的架构设计与实现细节,希望能给AI领域的研发人员提供一些思考和启示。

云深度学习平台设计

云深度学习平台,我定义为Cloud Machine Learning,就是基于云计算的机器学习和深度学习平台。首先TensorFlow、MXNet是深度学习框架或者深度学习平台,但并不是云深度学习平台,它们虽然可以组成一个分布式计算集群进行模型训练,但需要用户在计算服务器上手动启动和管理进程,并没有云计算中任务隔离、资源共享、自动调度、故障恢复以及按需计费等功能。因此我们需要区分深度学习类库以及深度学习平台之间的关系,而这些类库实现的随机梯度下降和反向传播等算法却是深度学习应用所必须的,这是一种全新的编程范式,需要我们已有的基础架构去支持。

云计算和大数据发展超过了整整十年,在业界催生非常多优秀的开源工具,如实现了类似AWS IaaS功能的OpenStack项目,还有Hadoop、Spark、Hive等大数据存储和处理框架,以及近年很火的Docker、Kubernetes等容器项目,这些都是构建现代云计算服务的基石。这些云服务有共同的特点,例如我们使用HDFS进行数据存储,用户不需要手动申请物理资源就可以做到开箱即用,用户数据保存在几乎无限制的公共资源池中,并且通过租户隔离保证数据安全,集群在节点故障或者水平扩容时自动触发Failover且不会影响用户业务。虽然Spark通过MLib接口提供部分机器学习算法功能,但绝不能替代TensorFlow、Caffe等深度学习框架的作用,因此我们仍需要实现Cloud Machine Learning服务,并且确保实现云服务的基本特性——我将其总结为下面几条:

  • 屏蔽硬件资源保证开箱即用
  • 缩短业务环境部署和启动时间
  • 提供“无限”的存储和计算能力
  • 实现多租户隔离保证数据安全
  • 实现错误容忍和自动故障迁移
  • 提高集群利用率和降低性能损耗

相比于MapReduce或者Spark任务,深度学习的模型训练时间周期长,而且需要调优的超参数更多,平台设计还需要考虑以下几点

  • 支持通用GPU等异构化硬件
  • 支持主流的深度学习框架接口
  • 支持无人值守的超参数自动调优
  • 支持从模型训练到上线的工作流

这是我个人对云深度学习平台的需求理解,也是小米在实现cloud-ml服务时的基本设计原则。虽然涉及到高可用、分布式等颇具实现难度的问题,但借助目前比较成熟的云计算框架和开源技术,我们的架构和实现基本满足了前面所有的需求,当然如果有更多需求和想法欢迎随时交流。

云深度学习平台架构

遵循前面的平台设计原则,我们的系统架构也愈加清晰明了,为了满足小米内部的所有深度学习和机器学习需求,需要有一个多租户、任务隔离、资源共享、支持多框架和GPU的通用服务平台。通过实现经典的MLP、CNN或RNN算法并不能满足业务快速发展的需求,因此我们需要支持TensorFlow等用户自定义的模型结构,并且支持高性能GPU和分布式训练是这个云深度学习平台的必须功能,不仅仅是模型训练,我们还希望集成模型服务等功能来最大化用户的使用效益。

计算机领域有句名言“任何计算机问题都可以通过增加一个中间层来解决”。无论是AWS、OpenStack、Hadoop、Spark还是TCP/IP都是这样做的,通过增加一个抽象层来屏蔽底层资源,对上层提供更易用或者更可靠的访问接口。小米的cloud-ml平台也需要实现对底层物理资源的屏蔽,尤其是对GPU资源的抽象和调度,但我们不需要重新实现,因为社区已经有了很多成熟的分布式解决方案,如OpenStack、Yarn和Kubernetes。目前OpenStack和Yarn对GPU调度支持有所欠缺,虚拟机也存在启动速度慢、性能overhead较大等问题,而容器方案中的Kubernetes和Mesos发展迅速,支持GPU调度等功能,是目前最值得推荐的架构选型之一。

目前小米cloud-ml平台的任务调度和物理机管理基于多节点的分布式Kubernetes集群,对于OpenStack、Yarn和Mesos我们也保留了实现接口,可以通过实现Mesos后端让用户的任务调度到Mesos集群进行训练,最终返回给用户一致的使用接口。目前Kubernetes最新稳定版是1.6,已经支持Nvidia GPU的调度和访问,对于其他厂商GPU暂不支持但基本能满足企业内部的需求,而且Pod、Deployment、Job、StatefulSet等功能日趋稳定,加上Docker、Prometheus、Harbor等生态项目的成熟,已经在大量生产环境验证过,可以满足通用PaaS或者Cloud Machine learning等定制服务平台的需求。

使用Kubernetes管理用户的Docker容器,还解决了资源隔离的问题,保证不同深度学习训练任务间的环境不会冲突,并且可以针对训练任务和模型服务使用Job和Deployment等不同的接口,充分利用分布式容器编排系统的重调度和负载均衡功能。但是,Kubernetes并没有完善的多租户和Quota管理功能,难以与企业内部的权限管理系统对接,这要求我们对Kubernetes API进行再一次“抽象”。我们通过API Server实现了内部的AKSK签名和认证授权机制,在处理用户请求时加入多租户和Quota配额功能,并且对外提供简单易用的RESTful API,进一步简化了整个云深度学习平台的使用流程,整体架构设计如图1。

图片描述

图1 云深度学习平台整体架构

通过实现API Server,我们对外提供了API、SDK、命令行以及Web控制台多种访问方式,最大程度上满足了用户复杂多变的使用环境。集群内置了Docker镜像仓库服务,托管了我们支持的17个深度学习框架的容器镜像,让用户不需要任何初始化命令就可以一键创建各框架的开发环境、训练任务以及模型服务。多副本的API Server和Etcd集群,保证了整个集群所有组件的高可用,和Hadoop或者Spark一样,我们的cloud-ml服务在任意一台服务器经历断网、宕机、磁盘故障等暴力测试下都能自动Failover保证业务不受任何影响。

前面提到,我们通过抽象层定义了云深度学习平台的接口,无论后端使用Kubernetes、Mesos、Yarn甚至是OpenStack、AWS都可以支持。通过容器的抽象可以定义任务的运行环境,目前已经支持17个主流的深度学习框架,用户甚至可以在不改任何一行代码的情况下定义自己的运行环境或者使用自己实现的深度学习框架。在灵活的架构下,我们还实现了分布式训练、超参数自动调优、前置命令、NodeSelector、Bring Your Own Image和FUSE集成等功能,将在下面逐一介绍。

云深度学习平台实现

前面提到我们后端使用Kubernetes编排系统,通过API Server实现授权认证和Quota配额功能。由于云深度学习服务是一个计算服务,和我以前做过的分布式存储服务有着本质的区别,计算服务离线运算时间较长,客户端请求延时要求较低而且吞吐很小,因此我们的API服务在易用性和高性能上可以选择前者,目前主流的Web服务器都可以满足需求。基于Web服务器我们可以实现集成内部权限管理系统的业务逻辑,小米生态云提供了类似AWS的AKSK签名认证机制,用户注册登录后可以自行创建Access key和Secret key,请求时在客户端进行AKSK的签名后发送,这样用户不需要把账号密码或密钥加到请求中,即使密钥泄露也可以由用户来禁用,请求时即使签名被嗅探也只能重放当前的请求内容,是非常可靠的安全机制。除此之外,我们参考OpenStack项目的体系架构,实现了多租户和Quota功能,通过认证和授权的请求需要经过Quota配额检查,在高可用数据库中持久化相应的数据,这样平台管理员就可以动态修改每个租户的Quota,而且用户可以随时查看自身的审计信息。

小米cloud-ml服务实现了深度学习模型的开发、训练、调优、测试、部署和预测等完整功能,都是通过提交到后端的Kubernetes集群来实现,完整的功能介绍可以查看官方文档http://docs.api.xiaomi.com/cloud-ml/ 。Kubernetes对外提供了RESTful API访问接口,通过YAML或者JSON来描述不同的任务类型,不同编程语言实现的系统也可以使用社区开发的SDK来访问。对于我们支持的多个深度学习框架,还有开发环境、训练任务、模型服务等功能,都需要定制Docker镜像,提交到Kubernetes时指定使用的容器镜像、启动命令等参数。通过对Kubernetes API的封装,我们可以简化Kubernetes的使用细节,保证了对Mesos、Yarn等后端支持的兼容性,同时避免了直接暴露Kubernetes API带来的授权问题以及安全隐患。

除了可以启动单个容器执行用户的训练代码,小米cloud-ml平台也支持TensorFlow的分布式训练,使用时只需要传入ps和worker个数即可。考虑到对TensorFlow原生API的兼容性,我们并没有定制修改TensorFlow代码,用户甚至可以在本地安装开源的TensorFlow测试后再提交,同样可以运行在云平台上。但本地运行分布式TensorFlow需要在多台服务器上手动起进程,同时要避免进程使用的端口与其他服务冲突,而且要考虑系统环境、内存不足、磁盘空间等问题,代码更新和运维压力成倍增加,Cloud Machine Learning下的分布式TensorFlow只需要在提交任务时多加两个参数即可。有人觉得手动启动分布式TensorFlow非常繁琐,在云端实现逻辑是否更加复杂?其实并不是,通过云服务的控制节点,我们在启动任务前就可以分配不会冲突的端口资源,启动时通过容器隔离环境资源,而用户不需要传入Cluster spec等繁琐的参数,我们遵循Google CloudML标准,会自动生成Cluster spec等信息通过环境变量加入到容器的启动任务中。这样无论是单机版训练任务,还是几个节点的分布式任务,甚至是上百节点的分布式训练任务,cloud-ml平台都可以通过相同的镜像和代码来运行,只是启动时传入的环境变量不同,在不改变任何外部依赖的情况下优雅地实现了看似复杂的分布式训练功能。

图片描述

图2 云深度学习平台分布式训练

看到这里大家可能认为,小米的cloud-ml平台和Google的CloudML服务,都有点类似之前很火的PaaS(Platform as a Service)或者CaaS(Container as a Service)服务。确实如此,基于Kubernetes或者Mesos我们可以很容易实现一个通用的CaaS,用户上传应用代码和Docker镜像,由平台调度和运行,但不同的是Cloud Machine Learning简化了与机器学习无关的功能。我们不需要用户了解PaaS的所有功能,也不需要支持所有编程语言的运行环境,暴露提交任务、查看任务、删除任务等更简单的使用接口即可,而要支持不同规模的TensorFlow应用代码,用户需要以标准的Python打包方式上传代码。Python的标准打包方式独立于TensorFlow或者小米cloud-ml平台,幸运的是目前Google CloudML也支持Python的标准打包方式,通过这种标准接口,我们甚至发现Google CloudML打包好的samples代码甚至可以直接提交到小米cloud-ml平台上训练。这是非常有意思的尝试,意味着用户可以使用原生的TensorFlow接口来实现自己的模型,在本地计算资源不充足的情况下可以提交到Google CloudML服务上训练,同时可以一行代码不用改直接提交到小米或者其他云服务厂商中的云平台上训练。如果大家在实现内部的云深度学习平台,不妨也参考下标准的Python打包方式,这样用户同一份代码就可以兼容所有云平台,避免厂商绑定。

除了训练任务,Cloud Machine Learning平台最好也能集成模型服务、开发环境等功能。对于模型服务,TensorFlow社区开源了TensorFlow Serving项目,可以加载任意TensorFlow模型并且提供统一的访问接口,而Caffe社区也提供了Web demo项目方便用户使用。目前Kubernetes和Mesos都实现了类似Deployment的功能,通过制作TensorFlow Serving等服务的容器镜像,我们可以很方便地为用户快速启动对应的模型服务。通过对Kubernetes API的封装,我们在暴露给用户API时也提供了replicas等参数,这样用户就可以直接通过Kubernetes API来创建多副本的Deployment实例,并且由Kubernetes来实现负载均衡等功能。除此之外,TensorFlow Serving本身还支持在线模型升级和同时加载多个模型版本等功能,我们在保证TensorFlow Serving容器正常运行的情况下,允许用户更新分布式对象存储中的模型文件就可以轻易地支持在线模型升级的功能。

对于比较小众但有特定使用场景的深度学习框架,Cloud Macine Learning的开发环境、训练任务和模型服务都支持Bring Your Own Image功能,也就是说用户可以定制自己的Docker镜像并在提交任务时指定使用。这种灵活的设置极大地降低了平台管理者的维护成本,我们不需要根据每个用户的需求定制通用的Golden image,事实上也不可能有完美的镜像可以满足所有需求,用户不同的模型可能有任意的Python或者非Python依赖,甚至是自己实现的私有深度学习框架也可以直接提交到Cloud Machine Learning平台上训练。内测BYOI功能时,我们还惊喜地发现这个功能对于我们开发新的深度学习框架支持,以及提前测试镜像升级有非常大的帮助,同时用户自己实现的Caffe模型服务和XGBoost模型服务也可以完美支持。

当然Cloud Machine Learning平台还可以实现很多有意思的功能,例如通过对线上不同GPU机型打label,通过NodeSelector功能可以允许用户选择具体的GPU型号进行更细粒度的调度,这需要我们暴露更底层Kubernetes API实现,这在集群测试中也是非常有用的功能。而无论是基于GPU的训练任务还是模型服务,我们都制作了对应的CUDA容器镜像,通过Kubernetes调度到对应的GPU计算节点就可以访问本地图像处理硬件进行高性能运算了。小米cloud-ml还开放了前置命令和后置命令功能,允许用户在启动训练任务前和训练任务结束后执行自定义命令,对于不支持分布式存储的深度学习框架,可以在前置命令中挂载S3 fuse和FDS fuse到本地目录,或者初始化HDFS的Kerberos账号,灵活的接口可以实现更多用户自定义的功能。还有超参数自动调优功能,与Google CloudML类似,用户可以提交时指定多组超参数配置,云平台可以自动分配资源起多实例并行计算,为了支持读取用户自定义的指标数据,我们实现了类似TensorBoard的Python接口直接访问TensorFlow event file数据,并通过命令行返回给用户最优的超参数组合。最后还有TensorFlow Application Template功能,在Cloud Machine Learning平台上用户可以将自己的模型代码公开或者使用官方维护的开源TensorFlow应用,用户提交任务时可以直接指定这些开源模板进行训练,模板已经实现了MLP、CNN、RNN和LR等经典神经网络结构,还可以通过超参数来配置神经网络每一层的节点数和层数,而且可以支持任意稠密和稀疏的数据集,这样不需要编写代码就可以在云平台上训练自己的数据快速生成AI模型了。

在前面的平台设计和平台架构后,要实现完整的云深度学习服务并不困难,尤其是集成了Docker、Etcd、Kubernetes、TensorFlow等优秀开源项目,组件间通过API松耦合地交互,需要的重复工作主要是打通企业内部权限系统和将用户请求转化成Kubernetes等后端请求而已,而支持标准的打包方式还可以让业务代码在任意云平台上无缝迁移。

云深度学习平台实践

目前小米云深度学习平台已经在内部各业务部门推广使用,相比于直接使用物理机,云服务拥有超高的资源利用率、快速的启动时间、近乎“无限”的计算资源、自动的故障迁移、支持分布式训练和超参数自动调优等优点,相信可以得到更好的推广和应用。

除了完成上述的功能,我们在实践时也听取了用户反馈进行改进。例如有内部用户反馈,在云端训练的TensorFlow应用把event file也导出到分布式存储中,使用TensorBoard需要先下载文件再从本地起服务相对麻烦,因此我们在原有基础架构实现了TensorboardService功能,可以一键启动TensorBoard服务,用户只需要用浏览器就可以打开使用。

管理GPU资源和排查GPU调度问题也是相当繁琐的,尤其是需要管理不同GPU设备和不同CUDA版本的异构集群,我们统一规范了CUDA的安装方式,保证Kubernetes调度的容器可以正常访问宿主机的GPU设备。当然对于GPU资源的调度和释放,我们有完善的测试文档可以保证每一个GPU都可以正常使用,根据测试需求实现的NodeSelector功能也帮忙我们更快地定位问题。

由于已经支持几十个功能和十几个深度学习框架,每次升级都可能影响已有服务的功能,因此我们会在多节点的分布式staging集群进行上线演习和测试,并且实现smoke test脚本进行完整的功能性测试。服务升级需要更新代码,但是为了保证不影响线上业务,无论是Kubernetes还是我们实现的API Server都有多副本提供服务,通过高可用技术先迁移服务进行滚动升级,对于一些单机运行的脚本也通过Etcd实现了高可用的抢主机制,保证所有组件没有单点故障。

大家可以通过前面提到的文档地址和cloud-ml-sdk项目了解到更多细节,或者关注我微博(@tobe-陈迪豪)与我交流。

总结

本文介绍了实现企业级云深度学习平台需要的概念和知识,基于小米cloud-ml服务探讨了云平台的设计、架构、实现以及实践这四方面的内容,希望大家看完有所收获。


订阅《程序员》(含iOS、Android及印刷版)请访问 http://dingyue.programmer.com.cn
图片描述


2017中国人工智能大会(CCAI 2017)| 7月22日-23日 杭州
本届CCAI由中国人工智能学会、蚂蚁金服主办,由CSDN承办,最专业的年度技术盛宴:
- 40位以上实力讲师
- 8场权威专家主题报告
- 4场开放式专题研讨会
- 超过100家媒体报道
- 超过2000位技术精英和专业人士参会
与大牛面对面,到官网报名:http://ccai.caai.cn/
图片描述

2018-09-14 10:58:20 oliongs 阅读数 8056
  • 深度学习框架Tensorflow案例实战视频课程

    深度学习框架Tensorflow案例实战视频培训课程概况: Tensorflow是谷歌开源的深度学习(包括机器学习)框架,伴随着人工智能业的兴盛其大名早已响彻云霄。本课程从Tensorflow安装开始讲起,从基本计算结构到深度学习各大神经网络,全程案例代码实战,一步步带大家入门如何使用深度学习框架Tensorflow,玩转Tensorflow模型训练、等所有知识点。

    30268 人正在学习 去看看 唐宇迪

前言:SLAM的系列实验基本就更新那么多,之后开始进入点云深度学习的方向,不出意外,这个系列会持续很久

点云深度学习最近一两年逐渐火热,这个系列从CVPR2017的PointNet开始,主要总结顶会的相关文章,不会全文翻译,只总结自己觉得重要的点。感兴趣的同学,可以去阅读原文。毕竟经要去西天取,文章要去源头品。


PointNet

(PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation)

(作为第一个直接处理点云的深度学习框架,相关介绍太多了,不再赘述)

输入是包含n个点的三维点云(nx3) , 原始数据通过一个3D 空间变换矩阵预测网络 T-Net(3),估计出3x3的变换矩阵T(3) 并作用在原始数据上,实现数据的对齐。对齐后的数据会以点为单位,通过一个共享参数的双层感知机模型进行特征提取 。每个点提取出64维的特征,再通过特征空间变换矩阵预测网络 T-Net(64) 预测64x64的变换矩阵,作用到特征上,实现对特征的对齐。然后继续利用三层感知机(64,128,1024)进行以特征点为单位的特征提取,直到把特征的维度变为1024,继而在特征空间的维度上进行Max Pooling,提取出点云的全局特征向量。

 

 

PointNet++

(PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space)

1.文章主要解决两个问题

  • 怎么划分这个点云集合

采用Farthest Point Sampling(FPS)算法,原理: 先随机选一个点,然后呢选择离这个点距离最远的点加入起点,然后继续迭代,直到选出需要的个数为止。(Sampling layer)

采用Ball query分组算法,原理: 给定中心点,把给定半径内的点都包括进来,同时给定邻居点个数。相比KNN,Ball query保证了一个固定的区域尺寸,所以比KNN更加geralizable across space,更适合于需要局部特征的任务。(Grouping layer)

  • 怎么组合点云集的局部特征

local region中的坐标首先被转换到相对于中点的坐标系中,使用相对坐标系,我们可以捕获到局部区域中点到点的关系。

使用PointNet作为局部特征学习器作为一个基础的结构部件,PointNet要在局部点集中抽取特征,或者把特征组合成更高层表示,所以PointNet++递归地使用PointNet在一个嵌套划分的输入点云集合上。(PointNet layer)

但是存在采样不均匀密度的问题。在低密度的地方可能会丢失局部信息,所以还需要增大尺度,所以提出了 density adaptive PointNet layers。主要采用以下两种方式解决:

Multi-scale grouping (MSG):每个尺度使用PointNet,然后将多尺度特征融合到一起。但是计算量比较大。

Multi-resolution grouping (MRG):MRG特征由两个向量组成,左边的使用区域抽象层汇总每个子区域的特征,右边的使用PointNet直接处理所有原始点数据。当局部区域密度低时,左边的特征不如右边的可靠,因为它包含更加稀疏的点,并且更多收到了采样的影响。

另一方面,当时局部区域密度高时,左边的向量提供了更精细的细节信息,因为它具有在较低层次递归地检查更高分辨率的能力。

2.整体框架如下:

set abstraction: 主要分为上面提到的Sampling layer、Grouping layer 和PointNet layer

通过多个set abstraction,最后进行分类和分割:

分类:将提取出的特征使用PointNet进行全局特征提取

分割:NL-1是集合抽象层的输入,NL是集合抽象层的输出。NL是采样得到的,NL-1肯定大于等于NL。在特征传播层,将点特征从NL传递到NL-1。根据NL的点插值得到NL-1,采用邻近的3点反距离加权插值。将插值得到的特征和之前跳跃连接的特征融合,在使用PointNet提取特征

3.总结:

给一片点云,PointNet++会先对点云进行采样(sampling)和划分区域(grouping),在各个小区域内用基础的PointNet网络进行特征提取(MSG、MRG),不断迭代。对于分类问题,直接用PointNet提取全局特征,采用全连接得到每个类别评分。对于分割问题,将高维的点反距离插值得到与低维相同的点数,再特征融合,再使用PointNet提取特征

 

参考链接:

https://blog.csdn.net/sunfei05/article/details/80451808

https://blog.csdn.net/qq_15332903/article/details/80261951

https://www.cnblogs.com/lainey/p/8625141.html

2018-10-10 16:28:17 qq_28863845 阅读数 3041
  • 深度学习框架Tensorflow案例实战视频课程

    深度学习框架Tensorflow案例实战视频培训课程概况: Tensorflow是谷歌开源的深度学习(包括机器学习)框架,伴随着人工智能业的兴盛其大名早已响彻云霄。本课程从Tensorflow安装开始讲起,从基本计算结构到深度学习各大神经网络,全程案例代码实战,一步步带大家入门如何使用深度学习框架Tensorflow,玩转Tensorflow模型训练、等所有知识点。

    30268 人正在学习 去看看 唐宇迪

使用华为云深度学习服务完成kaggle猫狗识别竞赛

参考:

  1. kaggle猫狗竞赛kernel第一名的代码
  2. Tensorflow官网代码
  3. 华为云DLS服务github代码

1. 环境配置与数据集处理

  • 首先我们需要从kaggle上面找到猫狗竞赛的页面,下载数据集压缩文件all.zip,大概853MB,解压两次后可以得到两个文件夹test和train,以及一个sample_submission.csv文件,test里面有12500张没有标签的测试图片,train中有带标签的25000张图片,猫狗各12500张,且按照顺序排好了。
  • 在桶的目录下创建code、log、model、train、test五个文件夹。
  • 使用华为云OBS客户端上传之前解压的图片,我是将解压后的图片上传的,所以需要一定的时间,文件位置为桶的目录下创建的train和test文件夹。
  • 创建开发环境,添加jupyter notebook

2. 代码-库的导入

from __future__ import division, absolute_import, print_function
import os, cv2, random
import pandas as pd
import tensorflow as tf
import numpy as np
import moxing as mox
from tensorflow import keras
from tensorflow.python.keras import layers

我使用tensorflow作为框架实现的,以及最后使用pandas保存结果,moxing用于读取文件,cv2用于图片resize。

3. 代码-定义常量以及运行时参数

# 使用tf.app.flags定义参数,运行时可以指定
tf.app.flags.DEFINE_string('data_url', 's3://dls-dogcat/input/', 'Dataset')
tf.app.flags.DEFINE_string('train_url', 's3://dls-dogcat/model/', 'Model_dir')
tf.app.flags.DEFINE_string('log_url', 's3://dls-dogcat/log/', 'Log_dir')

flags = tf.app.flags.FLAGS
TRAIN_DIR = os.path.join(flags.data_url, 'train/')
TEST_DIR = os.path.join(flags.data_url, 'test/')
MODEL_DIR = flags.train_url
LOG_DIR = flags.log_url

# 注释掉的部分用于测试
# TRAIN_DIR = 's3://dls-dogcat/input/train/'
# TEST_DIR = 's3://dls-dogcat/input/test/'
# MODEL_DIR = 's3://dls-dogcat/model/'
# LOG_DIR = 's3://dls-dogcat/log/'

# 这里获取文件夹下所有文件名称使用mox的函数,或者使用tf.gfile,不能使用os,测试数据需要按照名称顺序排列,
# 我在ubuntu下测试时发现文件名的排列规则是按照字符顺序,所以这里使用循环可以避免这个问题
train_image_url = [TRAIN_DIR + i for i in mox.file.list_directory(TRAIN_DIR)]
test_image_url = []
for i in range(1, 12501):
    path = TEST_DIR + str(i) + '.jpg'
    test_image_url.append(path)
print('Train images : {}, Test images : {}'.format(len(train_image_url), len(test_image_url)))



# 图片压缩为64*64大小,彩色图片3或灰度图片1
IMAGE_SIZE = 64
CHANNELS = 3

# batch大小16,epoch为30,但是一般不会跑完30轮,因为后面我设置了earlystop
BATCH_SIZE = 16
EPOCH = 30

# STEPS_PER_EPOCH后面实际没有使用,打乱训练集顺序
STEPS_PER_EPOCH = len(train_image_url) // BATCH_SIZE
random.shuffle(train_image_url)

# 使用mox获取文件夹下所有文件名
train_images = [TRAIN_DIR + i for i in mox.file.list_directory(TRAIN_DIR)]
test_images = [TEST_DIR + i for i in mox.file.list_directory(TEST_DIR)]

STEPS_PER_EPOCH = len(train_images) // BATCH_SIZE

# 数据集打乱
random.shuffle(train_images)

# 定义读取图片的函数,并且resize大小,设置为灰度图片或彩色,与上面CHANNELS对应即可
def read_image(file_path):
    img = cv2.imdecode(np.fromstring(mox.file.read(file_path, binary=True), np.uint8), cv2.IMREAD_COLOR)
    return cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_CUBIC)

# 将图片数据存入array中,同时除以255进行归一化
def prep_data(images):
    count = len(images)
    data = np.ndarray((count, IMAGE_SIZE, IMAGE_SIZE, CHANNELS), dtype=np.float32)
    for i, image_file in enumerate(images):
        image = read_image(image_file)
        data[i] = image / 255.0
        if i%1000 == 0: print('Processed {} of {}'.format(i, count))
    return data

train_set = prep_data(train_image_url)
test_set = prep_data(test_image_url)
print('Train_set shape: {}, Test_set shape: {}'.format(train_set.shape, test_set.shape))

# 获取训练集对应的label,就是将文件路径切分,找出是否包含dog或者cat,若是dog则写入1,否则0
train_labels = np.ndarray((len(train_image_url), 1), np.int32)
for i, url in enumerate(train_image_url):
    tag = url.split('.')[-3].split('/')[-1]
    if tag == 'dog':
        train_labels[i] = 1
    elif tag == 'cat':
        train_labels[i] = 0
        
print('Train_labels shape: {}'.format(train_labels.shape))

4. 代码-CNN构建

# 添加一些参数,便于调整神经网络,包括units,ksize,strides
f1, f2, f3, f4 = 32, 64, 128, 256
k1, k2, k3, k4 = 5, 5, 5, 5
s1, s2, s3, s4 = 2, 2, 2, 2
c1, c2, c3, c4 = 2, 2, 2, 2
fc1, fc2, fc3, fc4 = 512, 256, 128, 128

# 有三层(卷积层+最大池化+Dropout),然后Flatten层,再是全连接层,再是输出层
# 前面三层使用relu激活,drop概率0.5,全连接层drop概率0.5,最后输出层使用sigmoid激活
# 损失函数binary_crossentropy,优化器rmsprop
# 可优化部分:
# 1.增大内存,受限于内存,总参数在大概600000以上时,32GB内存会不够用,增加内存可以提升CNN的复杂度,也可以使用128大小的图片;
# 2.使用model_to_estimator将model转为estimator,然后使用GPU训练,可以提升训练速度;
# 3.使用vgg16取代前三层卷积层,可以实现更好的效果。

def cnn_model():
    model = keras.Sequential([
        layers.Conv2D(f1, k1, c1, padding='SAME', activation=tf.nn.relu, input_shape=(IMAGE_SIZE, IMAGE_SIZE, CHANNELS)),
        layers.MaxPool2D(strides=s1, padding='SAME'),
        layers.Dropout(0.5),
        
        layers.Conv2D(f2, k2, c2, padding='SAME', activation=tf.nn.relu),
        layers.MaxPool2D(strides=s2, padding='SAME'),
        layers.Dropout(0.5),
        
        layers.Conv2D(f3, k3, c3, padding='SAME', activation=tf.nn.relu),
        layers.MaxPool2D(strides=s3, padding='SAME'),
        layers.Dropout(0.5),
        
#         layers.Conv2D(f4, k4, c4, padding='SAME', activation=tf.nn.relu),
#         layers.MaxPool2D(strides=s4, padding='SAME'),
#         layers.Dropout(0.5),
        
        layers.Flatten(),
        layers.Dense(fc1, activation=tf.nn.relu),
        layers.Dropout(0.5),
        layers.Dense(fc2, activation=tf.nn.relu),
        layers.Dropout(0.5),
#         layers.Dense(fc3, activation=tf.nn.relu),
#         layers.Dropout(0.5),
#         layers.Dense(fc4, activation=tf.nn.relu),
#         layers.Dropout(0.5),
        
        layers.Dense(1, activation=tf.nn.sigmoid)
    ])
    model.compile(loss='binary_crossentropy',
              optimizer=tf.keras.optimizers.RMSprop(lr=1e-4),
              metrics=['accuracy'])
    return model

model = cnn_model()
model.summary()

图像处理使用卷积,为了避免过拟合使用了dropout,最后输出层为一个unit,因为是二分类,激活函数使用sigmoid,
所以使用binary_crossentropy为损失函数。

5. 代码-训练模型

# 设置PrintLoss callback在训练过程中打印损失和准确率
# 设置early_stop避免过拟合
# 设置tensorboard callback记录训练过程中loss、acc、val_loss、val_acc
# 设置checkpoint_callback保存训练过程中的模型
# 由于cp_callback、tb_callback不能直接写入,所以在华为云上实际运行时没有使用,如果跑在自己的机器上可以使用
early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_loss', 
                                              patience=3, 
                                              mode='auto')

checkpoint_path = MODEL_DIR + "cp-{epoch:04d}.ckpt"
cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path, 
                                                 verbose=1, 
                                                 save_weights_only=True, 
                                                 period=5)

tb_callback = tf.keras.callbacks.TensorBoard(log_dir=LOG_DIR, batch_size=BATCH_SIZE)

class PrintLoss(keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs):
        print('Epoch: {:03d} - loss: {:.5f} - acc: {:.5f} - val_loss: {:.5f} - val_acc: {:.5f}'.format(epoch + 1, 
                                                                                                       logs['loss'], 
                                                                                                       logs['acc'], 
                                                                                                       logs['val_loss'], 
                                                                                                       logs['val_acc']))

# 设置validation_split获取验证集损失
history = model.fit(train_set, 
                    train_labels, 
                    epochs=EPOCH, 
                    batch_size=BATCH_SIZE, 
                    validation_split=0.2, 
                    verbose=0, 
                    callbacks=[early_stop, cp_callback, tb_callback, PrintLoss()])

# 随便测试一下模型对训练集前3000图片的准确率
model.evaluate(train_set[:3000], train_labels[:3000])

6. 代码-预测与写入

# 调用predict进行预测
predictions = model.predict(test_set)

import pandas as pd
# path = os.path.join(flags.log_dir, 'submission.csv')
path = 's3://dls-dogcat/log/submission.csv'
counter = range(1, len(predictions) + 1)
df = pd.DataFrame({'id': counter, 'label': predictions})
# df['label'] = df['label'].map(lambda x: x.lstrip('[').rstrip(']')).astype('float32')
# df.reindex(index=list(range(1, df.shape[0])))
result = df.to_csv(path_or_buf=None, index=None)
with tf.gfile.Open(path, 'w') as f:
    f.write(result)
print('write success')

submission格式有要求,columns为id和label,label列下的数据格式要对,以及向桶中写数据的方式,参考华为云项目在github中的代码

7. kaggle分数

在这里插入图片描述

使用华为云深度学习服务完成kaggle猫狗识别竞赛-进阶版

进阶版主要使用了moxing和tensorflow框架,好处在于可以直接使用华为云GPU,非常迅速即可调试,坏处在于需要对自己的代码进行修改以适配框架

1. 数据处理

将图片数据存储为tfrecord,我对图片进行了resize处理,可以产生image size 128和64两种tfrecord,同时划分了train、eval数据集

代码参考华为云dls-example的使用moxing玩冰山

# 前面的部分代码和keras模式基本相同,将图片数据处理为numpy数组,不同的地方在于这个numpy数组我reshape为二维的了
# coding=utf-8
from __future__ import division, absolute_import, print_function
import os, cv2, random
import pandas as pd
import tensorflow as tf
import numpy as np
import moxing as mox
import matplotlib.pyplot as plt
import moxing.tensorflow as mtf
from sklearn.model_selection import train_test_split
from tensorflow import keras
from tensorflow.python.keras import layers
slim = tf.contrib.slim

print('load lib success', tf.VERSION)

TRAIN_DIR = 's3://dls-dogcat/input/train/'
TEST_DIR = 's3://dls-dogcat/input/test/'
OUTPUT_DIR = 's3://dls-dogcat/input/128'
TRAIN64 = 'train64.tfrecord'
EVAL64 = 'eval64.tfrecord'
TEST64 = 'test64.tfrecord'

TRAIN128 = 'train128.tfrecord'
EVAL128 = 'eval128.tfrecord'
TEST128 = 'test128.tfrecord'

train_image_url = [TRAIN_DIR + i for i in mox.file.list_directory(TRAIN_DIR)]

IMAGE_SIZE = 64
CHANNELS = 3

random.shuffle(train_image_url)

TRAIN_SIZE = len(train_image_url)
TEST_SIZE = len(tf.gfile.ListDirectory(TEST_DIR))
test_image_url = []
for i in range(1, TEST_SIZE + 1):
    path = TEST_DIR + str(i) + '.jpg'
    test_image_url.append(path)
print('Train images : {}, Test images : {}'.format(TRAIN_SIZE, TEST_SIZE))


def read_image(file_path):
    img = cv2.imdecode(np.fromstring(mox.file.read(file_path, binary=True), np.uint8), cv2.IMREAD_COLOR)
    return cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_CUBIC)

def prep_data(images):
    count = len(images)
    data = np.ndarray((count, IMAGE_SIZE * IMAGE_SIZE * CHANNELS), dtype=np.float32) # data也要改变对应下面
    for i, image_file in enumerate(images):
        image = read_image(image_file)
        image = image.reshape(-1) # 为了使用tfrecord的floatlist,我reshape了一下,其实可以使用byteslist,就不用reshape
        data[i] = image / 255.0
        if i%1000 == 0: print('Processed {} of {}'.format(i, count))
    return data

train_set = prep_data(train_image_url)
test_set = prep_data(test_image_url)
print('Train_set shape: {}, Test_set shape: {}'.format(train_set.shape, test_set.shape))


train_labels = np.ndarray((len(train_image_url), 1), np.int64)
for i, url in enumerate(train_image_url):
    tag = url.split('.')[-3].split('/')[-1]
    if tag == 'dog':
        train_labels[i] = 1
    elif tag == 'cat':
        train_labels[i] = 0
# 在这里划分数据集,80%train, 20%eval
print('Train_labels shape: {}'.format(train_labels.shape))
train_imgs, eval_imgs, train_labels, eval_labels = train_test_split(train_set, train_labels, test_size=0.2)
print(train_imgs.shape, eval_imgs.shape, train_labels.shape, eval_labels.shape)

# 将train和eval的numpy数组写入tfrecord的函数,这里需要定义Features,一个是image保存图片数组,一个是label保存标签(1、0)
# FloatList要求数组为一维的,所以上面我reshape了,如果使用byteslist就不用
def convert_and_encode_to_tfrecord(num_samples, images, labels, output_file):
    output_file = os.path.join(OUTPUT_DIR, output_file)
    with tf.python_io.TFRecordWriter(output_file) as tfrecord_writer:
        for i in range(num_samples):
            example = tf.train.Example(features=tf.train.Features(feature={
                'image': tf.train.Feature(float_list=tf.train.FloatList(value=images[i])),
                'label': tf.train.Feature(int64_list=tf.train.Int64List(value=labels[i]))
            }))
            tfrecord_writer.write(example.SerializeToString())
# 此处执行完毕会产生train64.tfrecord和eval64.tfrecord两个文件,train0.916GB,eval234MB,tfrecord比源文件大是很正常的
convert_and_encode_to_tfrecord(train_imgs.shape[0], train_imgs, train_labels, TRAIN64)
convert_and_encode_to_tfrecord(eval_imgs.shape[0], eval_imgs, eval_labels, EVAL64)


# 同理,这里将test写入tfrecord,但是test没有label,所以只需要一个feature
def convert_test_and_encode_to_tfrecord(num_samples, images, output_file):
    output_file = os.path.join(OUTPUT_DIR, output_file)
    with tf.python_io.TFRecordWriter(output_file) as tfrecord_writer:
        for i in range(num_samples):
            example = tf.train.Example(features=tf.train.Features(feature={
                'image': tf.train.Feature(float_list=tf.train.FloatList(value=images[i]))
            }))
            tfrecord_writer.write(example.SerializeToString())
# 大概586MB
convert_test_and_encode_to_tfrecord(test_set.shape[0], test_set, TEST64)

# 读取tfrecord的数据并显示出来,就可以验证是否正确的存入了数据,使用mox的get_tfrecord,参数照着改就完事了
# 这个方法不能与下面读取test一起使用,因为使用了session
def read_and_decode_tfrecord(dataset_dir, file_pattern, num_samples):
  keys_to_features = {
    'image': tf.FixedLenFeature((IMAGE_SIZE * IMAGE_SIZE * CHANNELS,), tf.float32, default_value=None),
    'label': tf.FixedLenFeature([1], tf.int64, default_value=None),
  }
  # 这里可以实现对一维数组的reshape,我们将数据恢复为彩色图片的三维形式
  items_to_handlers = {
    'image': slim.tfexample_decoder.Tensor('image', shape=[IMAGE_SIZE, IMAGE_SIZE, CHANNELS]),
    'label': slim.tfexample_decoder.Tensor('label', shape=[]),
  }
  dataset = mtf.get_tfrecord(dataset_dir=dataset_dir,
                             file_pattern=file_pattern,
                             num_samples=num_samples,
                             keys_to_features=keys_to_features,
                             items_to_handlers=items_to_handlers,
                             shuffle=False,
                             num_epochs=1)
  image, label = dataset.get(['image', 'label'])
  sv = tf.train.Supervisor()
  # 这里可以显示图片,20张彩色图片
  with sv.managed_session() as sess:
    plt.figure()
    for i in range(20):
      subp = plt.subplot(4, 5, i + 1)
      plt.subplots_adjust(hspace=1)
      subp.imshow(sess.run(image))
      label_eval = sess.run(label)
      subp.set_title('label=%s' % (label_eval))
    plt.show()

read_and_decode_tfrecord(dataset_dir=OUTPUT_DIR,
                         file_pattern='eval*.tfrecord',
                         num_samples=5000)



def read_test_and_decode_tfrecord(dataset_dir, file_pattern, num_samples):
  keys_to_features = {
    'image': tf.FixedLenFeature((IMAGE_SIZE * IMAGE_SIZE * CHANNELS,), tf.float32, default_value=None)
  }
  items_to_handlers = {
    'image': slim.tfexample_decoder.Tensor('image', shape=[IMAGE_SIZE, IMAGE_SIZE, CHANNELS])
  }
  dataset = mtf.get_tfrecord(dataset_dir=dataset_dir,
                             file_pattern=file_pattern,
                             num_samples=num_samples,
                             keys_to_features=keys_to_features,
                             items_to_handlers=items_to_handlers,
                             shuffle=False,
                             num_epochs=1)
  image = dataset.get(['image'])
  sv = tf.train.Supervisor()
  with sv.managed_session() as sess:
    plt.figure()
    for i in range(20):
      subp = plt.subplot(4, 5, i + 1)
      plt.subplots_adjust(hspace=1)
      subp.imshow(sess.run(image[0])) # 注意这个位置,test读出来的形式不一样,需要取image[0]才是正确的图片信息,此处有伏笔
    plt.show()

read_test_and_decode_tfrecord(dataset_dir=OUTPUT_DIR,
                         file_pattern='test*.tfrecord',
                         num_samples=12500)

2. 代码

经过上面的数据处理会得到三个tfrecord,分别是train、eval、test,可以修改参数得到128大小的tfrecord,文件大小为train3.66GB,eval0.915GB,test2.28GB

# 前面部分不必多说,是一些固定的库以及参数
from __future__ import absolute_import, division, print_function 
import os 
os.environ.pop('http_proxy', None) 
import math 
import numpy as np 
import pandas as pd 
import tensorflow as tf 
import moxing.tensorflow as mox 
from tensorflow.python.keras import layers

slim = tf.contrib.slim 

NUM_SAMPLES_TRAIN = 20000 
NUM_SAMPLES_EVAL = 5000 
NUM_SAMPLES_TEST = 12500 
# image_size对应之前存入tfrecord的图片大小
IMAGE_SIZE = 128
CHANNELS = 3

# 定义flags参数,这些参数将在创建作业时指定,有batch_size,data_url数据集路径,log_url日志以及checkpoint的路径、csv文件存储路径,is_training决定训练还是预测
tf.flags.DEFINE_integer('batch_size', 16, 'Mini-batch size') 
tf.flags.DEFINE_string('data_url', 's3://zxy/model/zzy', 'Dir of dataset') 
tf.flags.DEFINE_string('log_dir', 's3://zxy/model/zzy/log', 'Dir of log') 
tf.flags.DEFINE_boolean('is_training', True, 'True for train. False for eval and predict.') 
flags = tf.flags.FLAGS 

# 这个地方加上去可以避免因为obs传数据不稳定造成的失败,本质上是将桶内的数据拷贝到cache中
import atexit
import logging
_data_url = flags.data_url
_log_dir = flags.log_dir
if not mox.file.is_directory(_log_dir):
  mox.file.make_dirs(_log_dir)
mox.file.make_dirs('/cache/data_url')
mox.file.make_dirs('/cache/log_dir')
mox.file.copy_parallel(_data_url, '/cache/data_url')
mox.file.copy_parallel(_log_dir, '/cache/log_dir')
flags.data_url = '/cache/data_url'
flags.log_dir = '/cache/log_dir'
atexit.register(lambda: mox.file.copy_parallel('/cache/log_dir', _log_dir))
logger = logging.getLogger()
while logger.handlers:
  logger.handlers.pop()

# 这个部分实现了查询当前环境下的GPU数量,并据此定义steps,后面要用
num_gpus = mox.get_flag('num_gpus') 
# if using distributed, the number of workers is related to the number of machines.
num_workers = len(mox.get_flag('worker_hosts').split(',')) 
steps_per_epoch = int(math.ceil(float(NUM_SAMPLES_TRAIN) / (flags.batch_size * num_gpus * num_workers))) 
submission = pd.DataFrame(columns=['label']) 

# 定义输入函数,返回image、label,使用方式类似上面显示tfrecord的图片
def input_fn(run_mode, **kwargs): 
  # Train
  if run_mode == mox.ModeKeys.TRAIN: 
    num_samples = NUM_SAMPLES_TRAIN 
    num_epochs = None 
    shuffle = True 
    file_pattern = 'train*.tfrecord' 
  # Eval or Test
  else: 
    num_epochs = 1 
    shuffle = False 
    if run_mode == mox.ModeKeys.EVAL: 
      num_samples = NUM_SAMPLES_EVAL 
      file_pattern = 'eval*.tfrecord' 
    else: 
      num_samples = NUM_SAMPLES_TEST 
      file_pattern = 'test*.tfrecord' 
  keys_to_features = { 
    'image': tf.FixedLenFeature((IMAGE_SIZE * IMAGE_SIZE * CHANNELS,), tf.float32, default_value=None)
  } 
  items_to_handlers = { 
    'image': slim.tfexample_decoder.Tensor('image', shape=[IMAGE_SIZE, IMAGE_SIZE, CHANNELS])
  } 
  if run_mode != mox.ModeKeys.PREDICT: 
    keys_to_features['label'] = tf.FixedLenFeature([1], tf.int64, default_value=None) 
    items_to_handlers['label'] = slim.tfexample_decoder.Tensor('label', shape=[]) 
    
  # returns an instance of 'DatasetDataProvider' 
  # defined in 'tensorflow/contrib/slim/python/data/dataset_data_provider.py'
  dataset = mox.get_tfrecord(dataset_dir=flags.data_url, 
                             file_pattern=file_pattern, 
                             num_samples=num_samples, 
                             keys_to_features=keys_to_features, 
                             items_to_handlers=items_to_handlers, 
                             num_epochs=num_epochs, 
                             shuffle=shuffle) 
  # 如果运行的是predict,返回image,如果是train或eval,返回image和label
  if run_mode == mox.ModeKeys.PREDICT: 
    image = dataset.get(['image']) 
    # Non-DMA safe string cannot tensor may not be copied to a GPU. 
    # So we encode string to a list of integer. 
    return image
  else: 
    image, label = dataset.get(['image', 'label']) 
    return image, label
  # Data augementation(Only using in training data) 
#   if run_mode == mox.ModeKeys.TRAIN: 
#     image = tf.image.random_flip_left_right(image) 
#     image = tf.image.random_flip_up_down(image) 
#     image = tf.image.rot90(image, k=tf.random_uniform(shape=(), maxval=3, minval=0, dtype=tf.int32)) 
  

# 定义CNN模型,不多说,和keras模式差不多
f1, f2, f3, f4 = 32, 64, 128, 256
k1, k2, k3, k4 = 5, 5, 5, 5
s1, s2, s3, s4 = 2, 2, 2, 2
c1, c2, c3, c4 = 2, 2, 2, 2
fc1, fc2, fc3, fc4 = 256, 128, 64, 128

# Classification Model
def model_v1(images, run_mode): 
  is_training = (run_mode == mox.ModeKeys.TRAIN) 
  # Conv Layer 1 
  x = layers.Conv2D(f1, k1, c1, padding='SAME', activation=tf.nn.relu, input_shape=(IMAGE_SIZE, IMAGE_SIZE, CHANNELS))(images) 
  x = layers.MaxPool2D(strides=s1, padding='SAME')(x) 
  x = layers.Dropout(0.5)(x, training=is_training) 
  # Conv Layer 2 
  x = layers.Conv2D(f2, k2, c2, padding='SAME', activation=tf.nn.relu)(x) 
  x = layers.MaxPool2D(strides=s2, padding='SAME')(x) 
  x = layers.Dropout(0.5)(x, training=is_training)
  # Conv Layer 3 
  x = layers.Conv2D(f3, k3, c3, padding='SAME', activation=tf.nn.relu)(x) 
  x = layers.MaxPool2D(strides=s3, padding='SAME')(x) 
  x = layers.Dropout(0.5)(x, training=is_training)
  # Conv Layer 4 
  x = layers.Conv2D(f4, k4, c4, padding='SAME', activation=tf.nn.relu)(x) 
  x = layers.MaxPool2D(strides=s4, padding='SAME')(x) 
  x = layers.Dropout(0.5)(x, training=is_training)
  # Flatten the data for upcoming dense layers 
  x = layers.Flatten()(x) 
  # Dense Layers 
  x = layers.Dense(fc1, activation=tf.nn.relu)(x) 
  x = layers.Dropout(0.2)(x, training=is_training) 
  # Dense Layer 2 
  x = layers.Dense(fc2, activation=tf.nn.relu)(x) 
  x = layers.Dropout(0.2)(x, training=is_training) 
  # Sigmoid Layer 
  logits =layers.Dense(2)(x) 
  return logits 

# 定义model函数,这里是核心部分,从input_fn得到的数据在这里与model_fn发生反应,
# 通过mox.ModelSpec打印信息或者输出信息,与keras不同的是,这里使用softmax以及one-hot编码,sigmoid应该也是可以的
def model_fn(inputs, run_mode, **kwargs): 
  # In train or eval, id_or_labels represents labels. In predict, id_or_labels represents id. 
  if run_mode == mox.ModeKeys.PREDICT:
    images = inputs[0]
  else:
    images, labels = inputs
  # Reshape angles from [batch_size] to [batch_size, 1] 
  # Apply your version of model 
  logits = model_v1(images, run_mode) 
  if run_mode == mox.ModeKeys.PREDICT: 
    logits = tf.nn.softmax(logits) 
    model_spec = mox.ModelSpec(output_info={'logits': logits}) 
  else: 
    labels_one_hot = slim.one_hot_encoding(labels, 2) 
    loss = tf.losses.softmax_cross_entropy( 
      logits=logits, onehot_labels=labels_one_hot) 
    model_spec = mox.ModelSpec(loss=loss, log_info={'loss': loss}) 
  return model_spec 

# 这里对应model_fn的output_info,将logits[1]即dog的概率保存到DataFrame中,之后写入
def output_fn(outputs): 
  global submission 
  for output in outputs: 
    for logits in output['logits']: 
      # Get the probability of label==1 
      label = logits[1] 
      df = pd.DataFrame([label], columns=['label']) 
      submission = submission.append(df) 
      
# 主函数,根据创建作业时指定的is_training决定运行哪个方法,True对应训练,False对应eval和test      
if __name__ == '__main__': 
  # In training mode, using max_number_of_steps to control the epochs
  # Else, only run one epoch in eval and test mode.
  if flags.is_training: 
    mox.run(input_fn=input_fn, 
            model_fn=model_fn, 
            optimizer_fn=mox.get_optimizer_fn(name='adam', learning_rate=0.0001), 
            run_mode=mox.ModeKeys.TRAIN, 
            batch_size=flags.batch_size, 
            log_dir=flags.log_dir, 
            max_number_of_steps=steps_per_epoch * 150, # 这里与训练次数相关,自行修改
            log_every_n_steps=20, 
            save_summary_steps=50, 
            save_model_secs=120) 
  else: 
    mox.run(input_fn=input_fn, 
            model_fn=model_fn, 
            run_mode=mox.ModeKeys.EVAL, 
            batch_size=5, 
            log_every_n_steps=1, 
            max_number_of_steps=int(NUM_SAMPLES_EVAL / 5), 
            checkpoint_path=flags.log_dir) 
    mox.run(input_fn=input_fn, 
            output_fn=output_fn, 
            model_fn=model_fn, 
            run_mode=mox.ModeKeys.PREDICT, 
            batch_size=20,      # 这个地方很关键,必须为test size能整除的数,12500/20,ok,否则会丢失一部分测试数据
            max_number_of_steps=int(NUM_SAMPLES_TEST / 20),  # 对应上面
            log_every_n_steps=50, 
            output_every_n_steps=1,   # 这个地方必须为1,否则数据无法存入DataFrame中
            checkpoint_path=flags.log_dir) 
    # Write results to file. tf.gfile allow writing file to EBS/s3 
    submission_file = os.path.join(flags.log_dir, 'submission.csv') 
    print('start to write!!!!!')
    print('info: ', submission.label.values[:10])
    result = submission.to_csv(path_or_buf=None, index=False) 
    with tf.gfile.Open(submission_file, 'w') as f: 
      f.write(result)
    print('Success!!!')

经过上面的处理,并不能得到直接可以上传到kaggle的数据,因为我偷懒了,这个csv文件没有id列,所以最后你还需要再加工一下,很简单

结果及分析

使用image size为64的情况

Loss:

在这里插入图片描述

在这里插入图片描述
Score:

在这里插入图片描述

使用image size为128的情况

Loss:

在这里插入图片描述

在这里插入图片描述

Score:

在这里插入图片描述

  1. 在CNN不变的情况下,128大小的训练可以达到更低的损失,但是似乎结果并不比64好,而且与keras对比,似乎这个训练过程中有过拟合的问题,减少max_number_of_steps应该能得到更好的效果;
  2. 使用GPU的速度可快多了,最初的keras使用CPU跑了10小时以上,使用4个GPU可以在几十分钟内跑完更多轮的数据,效果相当的好。

总结

  1. 进行图片识别时基本的方式是使用卷积神经网络,所以使用基于tensorflow的keras可以迅速搭建一个卷积神经网络。
  2. 使用CNN的过程中可能会遇到内存不够的情况,一方面可以考虑优化CNN结构,另一方面可以考虑使用vgg16等已经训练好的模型加上自己的模型进行调试。
  3. 使用华为云进行开发的过程中会遇到一些问题,比如读取图片的方式被限定,tensorflow1.8版本model使用dataset会报错,文件写入的方式被限定,notebook意外断开连接等等。
  4. 使用华为云很方便,基于一个云平台基本可以完成所有的机器学习开发,而且提供了不少的学习工具,还是很实用的。
  5. 希望华为云可以提供更加直接的云计算平台使用方式,就我所想的应该是提供一个可以ssh的服务器,这样代码迁移更加方便。
2019-05-19 00:05:15 jiaxianhua 阅读数 101
  • 深度学习框架Tensorflow案例实战视频课程

    深度学习框架Tensorflow案例实战视频培训课程概况: Tensorflow是谷歌开源的深度学习(包括机器学习)框架,伴随着人工智能业的兴盛其大名早已响彻云霄。本课程从Tensorflow安装开始讲起,从基本计算结构到深度学习各大神经网络,全程案例代码实战,一步步带大家入门如何使用深度学习框架Tensorflow,玩转Tensorflow模型训练、等所有知识点。

    30268 人正在学习 去看看 唐宇迪

有没有觉得一台笔记本电脑不够强大,无法运行你的模型?忘记它吧,来使用 云 GPU 来更快更、更便宜地训练你的模型!

  • 你还可以了解在哪里可以 部署 你为数百万人服务的模型

  • 查看 免费积分优惠 部分获得一些免费的 gpu 小时

最后更新时间:2019 年 4 月 20 日

# 云供应商 网站 价格 免费试用 / 免费积分
1 Google Colaboratory❤️ https://colab.research.google.com 免费 永久免费*
2 Kaggle Kernels https://www.kaggle.com 免费 永久免费*
3 Tensorpad https://www.tensorpad.com 1080ti at $0.49/hour 5 free GPU hours
4 FloydHub https://www.floydhub.com https://www.floydhub.com/pricing free 2 GPU powerups in 14 days trial plan
5 Onepanel https://www.onepanel.io https://www.onepanel.io/pricing -
6 Nimblebox https://nimblebox.ai https://nimblebox.ai/plans free $5 worth of cloud credits
7 paperspace https://www.paperspace.com https://www.paperspace.com/pricing $10 credits
8 Overture https://www.overture.ai - free credits on signup
9 Dataiku https://www.dataiku.com - Free Plans
10 Cloudalize https://www.cloudalize.com https://www.cloudalize.com/pricing/ -
11 Deepcognition https://deepcognition.ai https://deepcognition.ai/products Desktop version free to use
12 GPUeater https://gpueater.com https://gpueater.com/#pricing -
13 Vast.ai https://vast.ai https://vast.ai/console/create/ -
14 Clusterone https://clusterone.com https://clusterone.com/pricing $25 Sign up credit
15 Snark https://snark.ai https://scale.snark.ai/pricing -
16 Crestle https://crestle.ai https://crestle.ai/#pricing 1 hour of free GPU usage on sign up fast.ai
17 Vector Dash(gaming) https://vectordash.com - free 7 day plan
18 Spell https://spell.run/developers https://spell.run/pricing $10 GPU credit on signup
19 Rapid Switch https://www.rapidswitch.com pricing -
20 Salamander https://salamander.ai https://salamander.ai -
21 Leadergpu https://www.leadergpu.com https://www.leadergpu.com -
22 vscaler https://www.vscaler.com on request -
23 AWS Sagemaker https://aws.amazon.com/sagemaker/ pricing Free plans
24 Exoscale https://www.exoscale.com/gpu/ pricing -
25 Cirrascale http://www.cirrascale.com Work station -
26 Alibaba cloud https://alibabacloud.com pay as you go $300 credits
27 IBM Cloud https://www.ibm.com/cloud/gpu pay as you go $200 credits
28 Google Cloud Platform https://cloud.google.com/gpu/ https://cloud.google.com/pricing/ $300 credits
29 Valohai https://valohai.com https://valohai.com/pricing/ free trial avaliable
30 Nvidia cloud https://www.nvidia.com/en-us/data-center/gpu-cloud-computing/ - -
31 One stop System https://www.onestopsystems.com - -
32 Azure https://azure.microsoft.com/en-in/services/machine-learning-studio/ pricing $200 credits
33 Omnisci https://www.omnisci.com https://www.omnisci.com/cloud 14 day free trial
34 Rendsolve https://rendsolve.com https://rendsolve.com/pricing -
35 Golem https://golem.network - -

将模型部署为 Web 应用

有一个想法, 并希望服务于世界 ?, 创建一个 Webapp, 并将其部署为 flask , Django 等

# 供应商 网站 价格 免费试用 / 免费积分
1 Render https://render.com https://render.com/pricing -
2 Heroku https://www.heroku.com https://www.heroku.com/pricing Free plan (model<500MB)
3 Digtal Ocean https://www.digitalocean.com pay as you go free $100 credits with github student pack
4 Glitch https://glitch.com - -
5 Zeit https://zeit.co https://zeit.co/pricing Free plan available

优惠

如果你是学生或研究人员, 你可以获得额外的积分, 请联系提供商

  • Paperspace 提供 10 美元的免费 Gradient° 积分 fast.ai 链接

  • 你是否有一个 GPU 躺在你的机器使用 Vast.ai 租来赚钱?

  • 试驾 Nvidia GPU 链接

  • Google Cloud Research 计划 - 提供 $5000+ 积分 链接

  • 用于研究的 AWS 云积分 - 链接

  • Nvidia GPU Grant 计划 - 链接

  • 如果您是初创公司,那么谷歌已经为您提供了启动计划,为您提供 1000-100000 美元的积分 - 链接

  • Google 向研究人员提供 1000 TPU 的集群 总的来说,这个集群总共提供超过 180 petaflops 的初始计算能力 techcrunch 链接 - 应用程序链接

  • Google 云教育资助 - 链接

  • Github 教育包 - 以及许多优惠,最高可获得 110 美元的 AWS 积分 - 链接

  • 注意 fast.ai 论坛 获取免费积分的优惠券代码

  • Valohai 为学生和研究人员提供 研究员许可证

  • 想要使用 超级计算机 但还没有,去 Golem - Golem 是一个 分散的计算能力市场。它能够在 P2P 使用 CPU 和 GPU ,使应用程序所有者和个人用户能够从其他用户机器中租用资源,因此 turbo 会为您的下一次模型培训收费。

备注

  • Google colab 和 Kaggle 内核的会话时间有限
  • 大多数 gpu 提供程序运行在 AWS,GCP 等之上,因此可能与后者具有或多或少相同的定价
  • 上面给出的信息最适合我的搜索能力,您可以与提供商重新检查定价和其他信息
  • 许可证

作者:zszazi
原文:https://github.com/virgili0/Virgilio/blob/master/zh-CN/Topics/Deep%20learning%20in%20cloud/README.md

2018-09-19 00:23:07 oliongs 阅读数 1235
  • 深度学习框架Tensorflow案例实战视频课程

    深度学习框架Tensorflow案例实战视频培训课程概况: Tensorflow是谷歌开源的深度学习(包括机器学习)框架,伴随着人工智能业的兴盛其大名早已响彻云霄。本课程从Tensorflow安装开始讲起,从基本计算结构到深度学习各大神经网络,全程案例代码实战,一步步带大家入门如何使用深度学习框架Tensorflow,玩转Tensorflow模型训练、等所有知识点。

    30268 人正在学习 去看看 唐宇迪

1. 整体框架

初始n*d的点云,首先经过输入特征提取块(3卷积层,每层64个1*1滤波器),输出n*din大小的特征Fin;通过x、y、z三个方向的切片池化层将无序点云转换为有序序列;采用双向RNN处理序列,更新特征;采用切片上池化层映射回每个点;最后经过输出特征提取块(3个1*1卷积层,输出维度为512,256,K),处理Fsu(切片上池化层的输出),输出每个点的预测

2.局部依赖模块

Slice Pooling Layer

输入是无序的点云特征,输出是有序的特征向量序列。从x、y、z三个方向进行切片,通过超参数r控制切片的分辨率,N为切片数。Si代表每个切片集合。通过最大池化操作得到全局特征。

 

RNN Layer

利用RNN处理局部依赖建模的序列中,因为它们是一组为结构化序列而设计的端到端学习算法。它的输入是Fs,为了保证某一个切片可以影响到其它切片,采用双向RNN,输出是周边点影响的特征Fr。

Slice Unpooling Layer

利用之前保存的S集合的信息,将Fr反投影到每个点

3.总结

相比其他为了得到局部信息需要复杂计算的模型,RSNet简化了计算。整体思路比较简单,但效果很好。尤其灵活地将RNN运用到模型中。

 

原作者公开课:http://www.mooc.ai/open/course/501

原作者公开课稿件:https://baijiahao.baidu.com/sid=1605235762733551923&wfr=spider&for=pc

点云深度学习

阅读数 1421

没有更多推荐了,返回首页