MindSpore这款刚刚开源的深度学习框架我爱了

【摘要】 本文主要通过两个实际应用案例:一是基于本地 Jupyter Notebook 的 MNIST 手写数据识别;二是基于华为云服务器的 CIFAR-10 图像分类,对开源框架 MindSpore 进行介绍。 犹记得今年的华为开发者大会 HDC 2020 上,一直受人瞩目的深度学习框架 MindSpore 终于开源了。 我之前一直关注 MindSpore,还是挺期待的。MindSpore 是一款支持端、边、云独立/协同的统一训练和推理框架。与 TensorFlow、PyTorch  等流行深度学习框架对标,MindSpore 旨在大幅度降低 AI 应用开发门槛,让人工智能无处不在。 MindSpore 最大的特点就是开发门槛大大降低,提高开发效率,这样可以显著减少模型开发时间。 因此,使用MindSpore的优势可以总结为以下四点: ●简单的开发体验 ●灵活的调试模式 ●充分发挥硬件潜能 ●全场景快速部署 既然开源了,那就赶紧上手,试一试这款开源的 MindSpore 怎么样!本文我将介绍 MindSpore 的安装和上手教程,通过一个简单的图像识别案例来跑完整个 AI 训练和测试流程。 一、MindSpore 的安装开源框架 MindSpore 的安装方法有很多,可以在 Windows、Ubuntu 上安装,也可以在华为 Ascend 910 上安装。各种详尽的安装方法请见下面的链接: https://www.mindspore.cn/install 下面介绍两种最简单的安装方法! 1. Docker 安装 Docker 安装最为简单,可参考: https://gitee.com/mindspore/m... 以 0.3.0-alpha 版本为例: CPU:docker pull mindspore/mindspore-cpu:0.3.0-alpha GPU:docker pull mindspore/mindspore-gpu:0.3.0-alpha 安装好后,可以看到安装的镜像,并使用下面的命令创建一个你的容器: docker run -it mindspore/mindspore-cpu:0.3.0-alpha /bin/bash2. Win10+Anaconda+MindSpore ...

July 2, 2020 · 3 min · jiezi

重磅YOLOv4阅读笔记附思维导图和论文译文

今天刷看到了YOLOv4之时,有点激动和兴奋,等了很久的YOLOv4,你终究还是出现了论文地址:https://arxiv.org/pdf/2004.10934.pdf GitHub地址:https://github.com/AlexeyAB/darknet 觉得作者很地道,论文附上开源,没有比这更开心的事情了吧! 首先附上对论文总结的思维导图,帮助大家更好的理解! 下边是对论文的翻译,有些地方可能翻译的不是很准备,欢迎指正补充 (思维导图和论文译文PDF均可在公众号【计算机视觉联盟】回复YOLOv4获取)摘要有很多特征可以提高卷积神经网络(CNN)的准确性。需要在大型数据集上对这些特征的组合进行实际测试,并需要对结果进行理论证明。某些特征仅在某些模型上运行,并且仅在某些问题上运行,或者仅在小型数据集上运行;而某些特征(例如批归一化和残差连接)适用于大多数模型,任务和数据集。我们假设此类通用特征包括加权残差连接(WRC),跨阶段部分连接(CSP),交叉小批量标准化(CmBN),自对抗训练(SAT)和Mish激活。我们使用以下新功能:WRC,CSP,CmBN,SAT,Mish激活,马赛克数据增强,CmBN,DropBlock正则化和CIoU丢失,并结合其中的一些特征来实现最新的结果:在MS COCO数据集上利用Tesla V10以65 FPS的实时速度获得了43.5%的AP(65.7%AP50)。开源代码链接:https://github.com/AlexeyAB/darknet。 1、介绍大多数基于CNN的物体检测器仅适用于推荐系统。例如,通过慢速精确模型执行的城市摄像机搜索免费停车位,而汽车碰撞警告与快速不精确模型有关。提高实时物体检测器的精度不仅可以将它们用于提示生成推荐系统,还可以用于独立的过程管理和减少人工输入。常规图形处理单元(GPU)上的实时对象检测器操作允许以可承受的价格对其进行运行。最精确的现代神经网络无法实时运行,需要使用大量的GPU进行大量的mini-batch-size训练。我们通过创建在常规GPU上实时运行的CNN来解决此类问题,并且该培训仅需要一个传统的GPU。 这项工作的主要目标是在产生式系统中设计一个运行速度快的目标探测器,并对并行计算进行优化,而不是设计一个低计算量的理论指标(BFLOP)。我们希望所设计的对象易于训练和使用。如图1中的YOLOv4结果所示,任何人使用传统的GPU进行训练和测试,都可以获得实时、高质量和令人信服的目标检测结果。我们的贡献概括如下: 我们开发了一个高效且功能强大的目标检测模型。它使每个人都可以使用1080Ti或2080TiGPU来训练超快、精确的物体探测器。我们验证了当前最新的“免费袋”和“特殊袋”检测方法在探测器训练过程中的影响。我们修改了最新的方法,使其更有效,更适合于单个GPU的培训,包括CBN[89]、PAN[49]、SAM[85]等。 2、相关工作(Related work)2.1 目标检测算法(Object detection models)目标检测算法一般有两部分组成:一个是在ImageNet预训练的骨架(backbone),,另一个是用来预测对象类别和边界框的头部。对于在GPU平台上运行的检测器,其骨干可以是VGG [68],ResNet [26],ResNeXt [86]或DenseNet [30]。对于在CPU平台上运行的那些检测器,其主干可以是SqueezeNet [31],MobileNet [28、66、27、74]或ShuffleNet [97、53]。对于头部,通常分为两类,即一级对象检测器和二级对象检测器。最具有代表性的两级对象检测器是R-CNN [19]系列,包括fast R-CNN [18],faster R-CNN [64],R-FCN [9]和Libra R-CNN [ 58]。还可以使两级对象检测器成为无锚对象检测器,例如RepPoints [87]。对于一级目标检测器,最具代表性的模型是YOLO [61、62、63],SSD [50]和RetinaNet [45]。近年来,开发了无锚的(anchor free)一级物体检测器。这类检测器是CenterNet [13],CornerNet [37、38],FCOS [78]等。近年来,无锚点单级目标探测器得到了发展,这类探测器有CenterNet[13]、CornerNet[37,38]、FCOS[78]等。近年来发展起来的目标探测器经常在主干和头部之间插入一些层,这些层通常用来收集不同阶段的特征图。我们可以称它为物体探测器的颈部。通常,颈部由几个自下而上的路径和几个自上而下的路径组成。具有这种机制的网络包括特征金字塔网络(FPN)[44]、路径聚集网络(PAN)[49]、BiFPN[77]和NAS-FPN[17]。除上述模型外,一些研究人员将重点放在直接构建用于检测对象的新主干(DetNet [43],DetNAS [7])或新的整个模型(SpineNet [12],HitDe-tector [20])上。 总而言之,普通的检测器由以下几个部分组成: 输入:图像,斑块,图像金字塔骨架:VGG16 [68],ResNet-50 [26],SpineNet [12],EfficientNet-B0 / B7 [75],CSPResNeXt50 [81],CSPDarknet53 [81]颈部: 其他块:SPP [25],ASPP [5],RFB [47],SAM [85]路径聚合块:FPN [44],PAN [49],NAS-FPN [17] ],Fully-connected FPN,BiFPN [77],ASFF [48],SFAM [98]Heads : ...

June 28, 2020 · 2 min · jiezi

中美高校合作开发深度学习框架或可用于疫情防范控制

技术编辑:芒果果丨发自 思否编辑部SegmentFault 思否报道丨公众号:SegmentFault 网络科学是一个学术领域,旨在揭示网络背后的结构和动态,如电信、计算机、生物和社会网络。近年来,网络科学家一直在试图解决的一个基本问题是确定一组最能影响网络功能的最佳节点,被称为「关键参与者」。 最近,中国国防科技大学、加州大学洛杉矶分校和哈佛医学院的研究人员开发了一个深度强化学习分析框架,称为 FINDER,可以更有效地识别复杂网络中的关键参与者。 相关研究论文已发表在《自然机器智能》杂志上,论文中描述的框架是在经典网络模型生成的合成网络上进行训练的,然后应用到现实世界的场景中。 FINDER 识别网络中的关键参与者确定关键参与者可以大大有益于许多现实世界的应用,例如,加强网络免疫技术,以及协助控制流行病、药物设计和病毒营销。 然而,由于其具有 NP 难性,使用具有多项式时间复杂度的精确算法来解决此问题具有很高的挑战性。 参与这项研究的高级研究人员之一  Yangyu Liu 说:“这项工作的动机是网络科学中的一个基本问题: 我们如何才能找到一组最优的关键参与者,他们的激活(或删除)将最大限度地增强(或降低)网络功能?针对具体的应用场景,已经提出了许多近似和启发式的策略,但是我们仍然缺乏一个统一的框架来有效地解决这个问题。” “FINDER”代表通过深度强化学习寻找网络关键参与者的缩写,它以最近开发的深度学习技术为基础,用于解决组合优化问题。研究人员将 FINDER 训练在一个由经典网络模型生成的大型小型合成网络上,使用特定于它试图解决的任务的奖励函数来引导它。 这个策略引导 FINDER 确定它应该做什么(例如,它应该选择什么节点)来根据当前的状态(例如,当前的网络结构)确定在一段时间内积累最大的回报应采取的措施。 另一位参与此项研究的高级研究员 Yizhou Sun 说:“在传统的强化学习任务中,比如机器人技术中,代表状态和动作可能很简单,但是网络却不是这样。我们在这个项目中面临的另一个挑战是确定如何表示一个网络,因为它有一个离散的数据结构,位于一个极其高维的空间。 为了解决这个问题,我们扩展了当前的图形神经网络来表示节点(动作)和图形(状态),这是与强化学习任务共同学习的。” 为了有效地表示复杂的网络,研究人员共同确定了各个网络状态和动作的最佳表示,以及当网络处于特定状态时确定最佳动作的最佳策略。由此产生的表示方法可以指导 FINDER 识别网络中的关键参与者。 新的深层加固框架已取得良好效果由 Sun,Liu 和他们的同事设计的新框架具有很高的灵活性,因此可以通过简单地改变奖励函数来应用于各种现实世界的网络分析。 它也非常有效,因为它在效率和速度方面超过了许多以前制定的确定网络中关键角色的战略。 值得注意的是,FINDER 可以很容易地扩大规模,以分析包含数千甚至数百万节点的广泛网络。 Yangyu Liu 表示:“与现有技术相比,FINDER 在复杂网络中寻找关键参与者的有效性和效率方面取得了优异的成绩。在解决复杂的现实世界网络上具有挑战性的优化问题方面,它代表了一种范式转变。 FINDER 不需要特定领域的知识,只需要真实网络的程度异质性,只需对小的合成图进行一次离线自我训练,就可以实现这一目标,然后在大得多的现实世界网络的不同领域中得到惊人的普及。” 迄今为止,新的深层加固框架已经取得了很好的效果。 在未来,它可以用于研究社交网络、电网、传染病的传播以及许多其他类型的网络。 新项目进行中,可用于人类健康研究Yangyu Liu 和 Yizhou Sun 与研究团队收集的结果强调了如经典网络模型 Barabási-Albert 模型的前景,并从中汲取了灵感。 虽然简单的模型可能看起来非常基本,但实际上,它们通常捕获了许多现实世界网络的主要特征,即程度异构性。 当试图解决与复杂网络相关的复杂优化问题时,这个特性可能具有巨大的价值。 “我的实验室正在沿着同样的研究方向进行几个不同研究,包括:(1)设计更好的图形表示学习架构; (2)探索如何在不同领域的不同图形甚至图形之间转移知识; (3)研究图形上的其他 NP 难题,并从学习的角度解决这些问题。” Yizhou Sun 和他在加州大学洛杉矶分校的团队计划为网络科学研究开发新技术。而 Yangyu Liu 和他在 HMS 的团队则希望开始在真正的生物网络上测试 FINDER。 ...

June 28, 2020 · 1 min · jiezi

深度学习四大名著发布PythonTensorFlow机器学习深度学习四件套

Python 程序员深度学习的“四大名著”: 这四本书着实很不错!我们都知道现在机器学习、深度学习的资料太多了,面对海量资源,往往陷入到“无从下手”的困惑出境。而且并非所有的书籍都是优质资源,浪费大量的时间是得不偿失的。 给大家推荐这几本好书并做简单介绍: 1、《Deep Learning with Python》 推荐指数:★★★★☆ 本书自出版以来收到众多好评,因为是 Keras 作者写的书,所以全书基本围绕着 Keras 讲深度学习的各种实现,从 CNN,RNN 到 GAN 等,偏入门,但也承载着很多作者对深度学习整体性的思考。这是一本偏实战的书,教你使用 Keras 快速实现深度学习经典项目。看完这本书,基本能对 Keras 和深度学习实战有比较初步的掌握了。 本书源码 GitHub 地址: https://github.com/fchollet/d... 2、《Python Machine Learning》 推荐指数:★★★☆☆ 本书使用了 Scikit-Learn 和 TensorFlow,分别讲解机器学习和深度学习,并每章配备实操代码。还有一点是讲解了如何将机器学习模型发布到 Web 应用。整个知识体系相对更加完善,是一本比较全面的机器学习书籍。 本书源码 GitHub 地址: https://github.com/rasbt/pyth... 3、《Hands-On Machine Learning with Scikit-Learn & TensorFlow》 推荐指数:★★★★★ 本书中文译为《Scikit-Learn 与 TensorFlow 机器学习实用指南》。这本书最大的特色从理论上讲就是言简意赅,全书基本上没有太多复杂的数学公式推导,语言通俗易懂,很容易看得懂、看得下去。正本书兼顾理论与实战,是一本非常适合入门和实战的机器学习书籍。 本书源码 GitHub 地址: https://github.com/ageron/han... 4、《Deep Learning》 推荐指数:★★★★☆ 又名“花书”。该书由三位大佬 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 撰写,是深度学习领域奠基性的经典教材。相信这本书大部分人入坑深度学习的都知道! ...

June 27, 2020 · 1 min · jiezi

Spark如何与深度学习框架协作处理非结构化数据

随着大数据和AI业务的不断融合,大数据分析和处理过程中,通过深度学习技术对非结构化数据(如图片、音频、文本)进行大数据处理的业务场景越来越多。本文会介绍Spark如何与深度学习框架进行协同工作,在大数据的处理过程利用深度学习框架对非结构化数据进行处理。 Spark介绍Spark是大规模数据处理的事实标准,包括机器学习的操作,希望把大数据处理和机器学习管道整合。 Spark使用函数式编程范式扩展了MapReduce模型以支持更多计算类型,可以涵盖广泛的工作流。Spark使用内存缓存来提升性能,因此进行交互式分析也足够快速(如同使用Python解释器,与集群进行交互一样)。缓存同时提升了迭代算法的性能,这使得Spark非常适合机器学习。 由于Spark库提供了Python、Scale、Java编写的API,以及内建的机器学习、流数据、图算法、类SQL查询等模块;Spark迅速成为当今最重要的分布式计算框架之一。与YARN结合,Spark提供了增量,而不是替代已存在的Hadoop集群。在最近的Spark版本中,Spark加入了对于K8s的支持,为Spark与AI能力的融合提供了更好的支持。 深度学习框架介绍TensorFlow TensorFlow最初是由Google机器智能研究部门的Google Brain团队开发,基于Google 2011年开发的深度学习基础架构DistBelief构建起来的。由于Google在深度学习领域的巨大影响力和强大的推广能力,TensorFlow一经推出就获得了极大的关注,并迅速成为如今用户最多的深度学习框架。 TensorFlow是一个非常基础的系统,因此也可以应用于众多领域。但由于过于复杂的系统设计,对读者来说,学习TensorFlow底层运行机制更是一个极其痛苦的过程。TensorFlow的接口一直处于快速迭代之中,并且没有很好地考虑向后兼容性,这导致现在许多开源代码已经无法在新版的TensorFlow上运行,同时也间接导致了许多基于TensorFlow的第三方框架出现BUG。 Keras Keras 于2015年3月首次发布,拥有“为人类而不是机器设计的API”,得到Google的支持。它是一个用于快速构建深度学习原型的高层神经网络库,由纯Python编写而成,以TensorFlow、CNTK、Theano和MXNet为底层引擎,提供简单易用的API接口,能够极大地减少一般应用下用户的工作量。 严格意义上讲,Keras并不能称为一个深度学习框架,它更像一个深度学习接口,它构建于第三方框架之上。Keras的缺点很明显:过度封装导致丧失灵活性。Keras最初作为Theano的高级API而诞生,后来增加了TensorFlow和CNTK作为后端。学习Keras十分容易,但是很快就会遇到瓶颈,因为它缺少灵活性。另外,在使用Keras的大多数时间里,用户主要是在调用接口,很难真正学习到深度学习的内容。 PyTorch PyTorch于2016年10月发布,是一款专注于直接处理数组表达式的低级API。 前身是Torch(一个基于Lua语言的深度学习库)。Facebook人工智能研究院对PyTorch提供了强力支持。PyTorch支持动态计算图,为更具数学倾向的用户提供了更低层次的方法和更多的灵活性,目前许多新发表的论文都采用PyTorch作为论文实现的工具,成为学术研究的首选解决方案。 Caffe/Caffe2.0 Caffe的全称是Convolutional Architecture for Fast Feature Embedding,它是一个清晰、高效的深度学习框架,于2013年底由加州大学伯克利分校开发,核心语言是C++。它支持命令行、Python和MATLAB接口。Caffe的一个重要特色是可以在不编写代码的情况下训练和部署模型。如果您是C++熟练使用者,并对CUDA计算游刃有余,你可以考虑选择Caffe。 在Spark大数据处理中使用深度学习框架在Spark程序中使用一个预训练过的模型,将其并行应用于大型数据集的数据处理。比如,给定一个可以识别图片的分类模型,其通过一个标准数据集(如ImageNet)训练过。可以在一个Spark程序中调用一个框架(如TensorFlow或Keras)进行分布式预测。通过在大数据处理过程中调用预训练模型可以直接对非结构化数据进行直接处理。 我们重点介绍在Spark程序中使用Keras+TensorFlow来进行模型推理。 使用深度学习处理图片的第一步,就是载入图片。Spark 2.3中新增的ImageSchema包含了载入数百万张图像到Spark DataFrame的实用函数,并且以分布式方式自动解码,容许可扩展地操作。 使用Spark's ImageSchema: from pyspark.ml.image import ImageSchemaimage_df = ImageSchema.readImages("/data/myimages")image_df.show()也可以利用Keras的图片处理库: from keras.preprocessing import imageimg = image.load_img("/data/myimages/daisy.jpg", target_size=(299, 299))可以通过图片路径来构造Spark DataFrame: def get_image_paths_df(sqlContext, dirpath, colName): files = [os.path.abspath(os.path.join(dirpath, f)) for f in os.listdir(dirpath) if f.endswith('.jpg')] return sqlContext.createDataFrame(files, StringType()).toDF(colName)使用Keras接口加载预训练模型: from keras.applications import InceptionV3model = InceptionV3(weights="imagenet")model.save('/tmp/model-full.h5')model = load_model('/tmp/model-full.h5')定义图片识别推理方法: ...

June 18, 2020 · 1 min · jiezi

mask-rcnn-部署小技巧

int8进行网络传输目的:我们项目需要用到instance segmentation, 所以 rcnn_mask输出层数据量特别大,同时因为图片尺寸有1024*1024*3这么大.如果不压缩一下直接进行网络传输,数据量会很大,接口延迟很高.为了部署后,请求推理服务时,数据输入层和输出层的传输量减少.从float32 转变成 int8,传输量减少了4倍.处理:输入层:先转换成 int8,然后再转成float32 def build(self, mode, config): input_image = KL.Input( shape=[None, None, config.IMAGE_SHAPE[2]], name="input_image",dtype=tf.int8) input_image = KL.Input(tensor=K.cast(input_image,dtype= tf.float32)) 输出层: mrcnn_mask = build_fpn_mask_graph(detection_boxes, mrcnn_feature_maps, input_image_meta, config.MASK_POOL_SIZE, config.NUM_CLASSES,模型导出时加上去 mrcnn_mask = KL.Lambda(lambda x: x*255)(mrcnn_mask) mrcnn_mask = KL.Lambda(lambda x: tf.cast(x,dtype=tf.int8))(mrcnn_mask)云函数服务 拿到`mrcnn_mask`输出层数据后,再转换成 `float32`- 模型导出:导出时注意 `output` 名称要对应.def save_model(): config = QuesConfig()PRETRAINED_MODEL_PATH = "/xxxxx/weights"MODEL_NAME = 'xxxxx_0601.h5'export_dir = "./saved_model/1/"h5_to_saved_model(config, PRETRAINED_MODEL_PATH, MODEL_NAME, export_dir)def h5_to_saved_model(config, model_dir, model_name, export_dir): if tf.gfile.Exists(export_dir): tf.gfile.DeleteRecursively(export_dir)config.display()model = modellib.MaskRCNN(mode="inference", config=config, model_dir=model_dir)model_path = os.path.join(model_dir, model_name)model.load_weights(model_path, by_name=True)with K.get_session() as session: save_m(export_dir, session)def save_m(export_dir, session): ...

June 4, 2020 · 1 min · jiezi

DeepMind-发布-Acme-框架用于强化学习算法开发的分布式框架

技术编辑:芒果果丨发自 思否编辑部SegmentFault 思否报道丨公众号:SegmentFault DeepMind 发布了 Acme 框架,该框架旨在通过使 AI 驱动的代理可以执行各种规模的运行来简化强化学习算法的开发。 Acme 背后的工程师和研究人员共同撰写了一篇关于这项工作的技术论文,根据他们的说法,Acme 可以用来创建比以前的方法具有更大并行性的代理。 Acme 试图解决复杂性和规模问题Acme 是用于培训强化学习代理的开发套件,该套件试图解决复杂性和规模问题,其组件用于构建从算法和策略到学习者的各种抽象级别代理。 有人认为,这样做可以让想法快速迭代,并在生产过程中对这些想法进行评估,主要是通过培训循环、强迫性日志记录和检查点。 在 Acme 内部,参与者与环境紧密互动,观察环境产生观察结果,并采取相应的行动,将其反馈到环境中。在观察了随之而来的过度之后,行为者有机会更新自己的状态。这通常与其行动选择政策又短,这些政策决定了他们为应对环境而采取的行动。 一种特殊类型的 Acme actor 包括演示和学习两个部分,它们被称为“代理”,其状态更新是由学习器组件中的一些步骤触发的。也就是说,参与主体在很大程度上会将他们的行动选择放到自己的行动组成部分。 Acme 框架加强环境互动强化学习技术让代理人与环境互动,声称他们自己的训练数据,并在电子游戏、机器人技术、自动驾驶机器人出租车等领域取得了突破。 相关技术最近的进展归因于所使用的训练数据量的增加,进行了新的系统设计,使代理人与环境实例相互作用,以迅速积累经验。 DeepMind 断言,将算法的单进程原型扩展到分布式系统通常需要重新实现相关的代理,这就是 Acme 框架的用武之地。 Acme 改善强化学习可再现性,可提供构建新代理的能力Acme 提供了一个数据集模块,位于参与者和学习者组件之间,并由 DeepMind 本周发布的称为 Reverb 的低级存储系统提供支持。 此外,该框架还建立了一个用于插入 Reverb 的通用接口,从而实现了不同风格的预处理以及正在进行的观测数据聚合。 行动、学习和存储组件在 Acme 内的不同线程或过程中划分,这具有两个好处:环境交互与学习过程异步发生,并且数据生成加速。在其他地方,Acme 的速率限制允许从学习到行动执行所需的速率,只要流程保持在一定的定义公差内,就可以不受阻碍地运行。 例如,如果一个进程由于网络问题或资源不足而开始落后于另一个进程,则速率限制器将组织落后者,而另一个则追赶上来。 除了这些工具和资源,Acme 还附带了一组示例代理,作为其各自的强化学习算法以及强大的研究基准的实现。 DeepMind 表示,未来可能会有更多这样的服务。研究人员表示:“通过提供这些,我们希望 Acme 将帮助改善强化学习中的可再现性,并为学术研究社区提供简单的构建新代理的能力。此外,我们的基线应该提供更多的标准来衡量该领域的进展。”

June 4, 2020 · 1 min · jiezi

BN和LN

Batch NormalizationBN的参数计算是以一个mini batch为组的,每一层的输出$Z= R^{batch\_size,hidden\_size}$在进激活函数之前,针对每一个神经元,即每一个输出$Z_i = R^{batch\_size,1}$做统计归一。统计指标为每个batch的输出的一个维度的均值和方差,对应的会有两个hidden_size维的向量: $$\mu_{ Z_i} = \frac{1}{batch\_size} \sum\limits^{batch\_size}_{j=1} Z_{i,j} $$$$\sigma_{Z_i}=\sqrt{\frac{1}{batch\_size}\sum\limits_{j=1}^{batch\_size}(\mu_{Z_i} - Z_i)^2} $$ BN的更新BN得到两个参数向量后会对该层的输出$Z$做变换,即更新该层的输出到一个合理的分布上。更新分两步,1. 变换到一个均值为0方差为1的分布上(针对的是每一维度)。2. 再做一次平移和缩放操作,这一步是通过一个线性变换得到的,平移参数可学习。两步更新后再过激活函数。$$ Z'_i = \frac {Z_i - \mu_{Z_i}}{\sigma_{Z_i}} $$$$ Z''_i = gZ'_i+b $$ BN特点: 所有的操作都是在一个维度上进行的,参数的计算依赖于batch_size倾向于认为同一位置的特征的同一维度的信息应该具有相同的分布,也可以认为同一位置的特征具有相同分布。因为参数和batch_size相关,batch_size太小会带来分布和整体不一致的问题。故train的batch_size不适宜太小,且需尽量打散,以保证分布和整体接近。在infer阶段和train阶段会有不一样的策略。infer阶段往往只有一个样本,再去求参数,明显不可行,所以一般会在train阶段迭代的更新$\mu和\sigma$参数,以估计所有训练样本的参数,且存下来,作为infer阶段使用的参数。Layer NormalizationLN的计算是在单个样本级别上做的normlize。对每一层的输出$Z= R^{batch\_size,hidden\_size}$ 在激活之前,针对每一个样本$Z_j = R^{1,hidden_size}$求参数$\mu 和\sigma$,求取方式和BN类似,只是方向不同。最终batch_size个样本得到batch_size组参数。LN的更新,依据每个样本的参数逐个更新各个样本的每一维度。然后做同样的缩放和平移。平移参数和缩放参数可学习。LN特点: 所有的操作都是在单个样本上计算的,所以不依赖于batch_size,所以不用存储$\mu和\sigma$参数到infer阶段。train和infer一致。倾向于认为一个样本内部的所有feature是相似的,可以直接在样本内各个维度上norm。这一假设在nlp任务中比较得到明显。一个句子的各个特征就是各个字词处理后得到的,基本是相似的。但假如输入特征是类似年龄,性别,身高这种多个不同特征concat起来的,再直接求样本内部的norm,由于各个feature的分布不一样,就会存在很大的问题。对比BN不太适合NLP任务中的不定长类任务。 不定长的样本,在靠后位置的有效样本会变少,相当于变相的batch_size在变小。在RNN类的循环网络中,越往后相当于样本越长,有效样本越少,BN效果会变差。在infer阶段如果一个很长的样本在train阶段没有见过,则会找不到对应的参数。LN比较适合NLP任务 变长样本处理起来无问题。一个样本的各个特征一般是比较相似的,如一个句子的特征是各个字,concat后,各个维度的分布也是一致的。在TF,pytoch等的实现中,LN一般是针对最内层的向量内部做norm参数。如[batch_size,seq_len,hidden_size]这样的一个输出,在LN时,是针对最内层的hidden_size个神经元求参,更是不会和padding的feature起冲突。而BN相当于在一个[batch_size*seq_len,hidden_size]的矩阵上做BN,这时求均值方差时会把padding的样本也算进去。LN和BN都需要两步变换,第一步变换得到一个$\mu=0 且\sigma=1$的分布,这一步目的把神经元的输出变换到一个比较均衡的分布上,达到参数稳定的目的。第二部通过两个可学系参数(tf中的$\gamma和\beta $)做缩放和平移,以期恢复原数据的表达的能力。

May 31, 2020 · 1 min · jiezi

深度学习优质实践案例用-Keras-实现人群中的口罩检测

Keras 是一个由 Python 编写的开源人工神经网络库,可以作为 Tensorflow、Microsoft-CNTK 和 Theano 的高阶应用程序接口,进行深度学习模型的设计、调试评估、应用和可视化。 Gitee 上这位优秀的开发者也是一名深度学习爱好者,为了做一次目标检测学习了 RCNN,FastRCNN,FasterRCNN 的理论,随后便诞生了这个项目,我们一起来看看他是怎么做的吧。 项目名称:keras 口罩检测 项目作者:唐振超 开源许可协议:GPL-3.0 项目地址:https://gitee.com/tang_zhen_chao/keraskouzhaojiance 介绍使用 keras 搭建 fasterRCNN,在 VOC 格式的口罩数据集上训练,达到了检测人群中有无戴口罩的目的。 软件架构*可前往项目主页查看 安装教程 需要numpy,matplotlib,scikit-learn,Pillow,tensorflow1.x,keraspip install package或者conda install package如果要训练,需要使用VOC格式数据集,需要安装labelimg使用说明 ./model_data/logs下必须有模型权重文件,由于权重较大,所以未上传./theory下是做这个东西的流程与方便理解代码的原理说明./net下是fasterRCNN的模型构建run.py用于直接运行看结果,voctrain.py用于训练自己的VOC数据集结果显示 点击链接前往项目主页看看项目的详细信息:https://gitee.com/tang_zhen_chao/keraskouzhaojiance

May 28, 2020 · 1 min · jiezi

高德地图首席科学家任小枫视觉智能在高德地图的应用

2019杭州云栖大会上,高德地图技术团队向与会者分享了包括视觉与机器智能、路线规划、场景化/精细化定位、时空数据应用、亿级流量架构演进等多个出行技术领域的热门话题。现场火爆,听众反响强烈。我们把其中的优秀演讲内容整理成文并陆续发布出来,本文为其中一篇。 高德地图首席科学家任小枫在高德技术专场分享了题为《视觉智能连接真实世界》的演讲,本文根据现场内容整理而成(在不影响原意的情况下对文字略作编辑),更多视觉智能技术的实现细节请关注后续系列文章。 以下为演讲内容的简版实录: 我今天主要给大家介绍视觉及相关技术如何在高德落地,如何帮助连接真实世界。连接真实世界这句话并不只是我个人的想法,而是高德地图的使命,我们的使命是“连接真实世界,让出行更美好”。 首先,简单介绍下高德地图,有超过1亿的日活用户,超过4亿的月活用户,高德地图不光提供导航,也提供出行相关的其他服务,涵盖了信息服务、驾车导航、共享出行、智慧公交、智慧景区、骑行、步行、长途出行等应用场景。 高德地图做的事情是建立人和真实世界的关系,人要跟真实世界建立联系,地图是基础,地图之上还有更多的信息可以获取。 视觉是连接真实世界的桥梁 视觉是连接真实世界的桥梁。为什么?从人的信息获取角度来看,80%的内容是通过视觉获取到的。从人的信息处理来看,人的大脑30%-60%用于视觉感知。从机器的角度,视觉是非常重要的通用感知手段。 人类感知真实世界的方法,还有很多其他方式,例如传感器、LT...但是,作为通用的手段,我一直觉得视觉是第一选择,通用,信息量非常大,可以远距感知,也可以做到实时。 还有一个原因,人类真实世界里(各种元素)80%以上是为了视觉而设计。有的时候,我们对真实世界太过于熟悉,可能不会太在意。但是看一下周围的标志和信息,包括认识的事物,都是根据视觉设计和获取。 因为人类获取信息的主要方式是通过视觉,所以真实世界的设计也是基于视觉。大家可以想象下,如果获取信息的主要方式是通过嗅觉,那这个世界会非常不一样。基于这些,回到我们在做的事情,大家一定不会奇怪,地图信息的获取和建立,绝大部分也是来自于视觉。 视觉技术@高德地图-地图制作 视觉技术在高德地图的应用有很多不同的方式,如下图所示: 左边是地图制作,有常规地图和高精地图,高精地图对应于未来的无人驾驶。右边是跟导航体验相关的,我们在做的一些跟定位相关的工作,也在利用视觉技术希望使导航变得更加便利。因为时间关系,今天只给大家介绍常规地图和导航相关的部分。 地图服务从哪里来,首先要采集资料,目前绝大部分是通过相机和视觉的方式采集信息。真实世界很大,全国有几百万公里道路,再加上其他信息,人工方式目前是处理不过来的,很大程度上需要用自动识别,通过算法识别资料。当然有时候算法没办法做到100%,还需要人工修正,从而制作成地图数据库,来支持地图数据服务。 地图制作任务,常规地图任务通常分为两大类,一类是道路相关,一类是POI挂牌识别。这两类任务都需要较多的视觉技术。例如,在道路标志识别上,算法要做的就是把道路上的标志一个一个全部找出来,同时识别标志的类型和内容。 道路标志有100多种。如果只是处理这些标志,其实并不是那么复杂。现实中,有时候需要用低成本的方式采集数据,这时如何保证图像质量就是需要考虑和解决的问题。 采集信息的时候,有时候图片会有畸变、反光、遮挡等情况,先不说分辨率压缩的问题,成像本身取决于镜头的质量和成本、天气条件、光线等因素,有时候采集回来的图像中差的图很多。这时候就不只是单纯去解决一个理想当中的算法问题,也需要处理很多实际情况。 给大家举几个例子,下面左边的图是实际采集的图像,会有各种各样的问题。大家对相机有些了解的话,知道相机有内参和外参,内参是焦距、中心、畸变。外参是位置、角度,这些都会影响成像效果。 对于识别问题来说,这些相机参数不会造成太大问题,但是如果需要做一些跟几何、位置相关的计算,这时候相机畸变和内外参不准就会造成很大的问题。我们通过把多源数据放在一起做匹配,基本可以解决这个问题。右边是一个实际例子,相机的畸变纠正角度,有一些斜的被纠正过来了,很大的提高了后面的算法处理。 另一个例子,图像质量。有的图质量比较差,但是没办法丢掉,还是有有用的信息。有的原始图像,放大之后非常模糊。如果这时采用图像增强的方法,可以把这张图变得更清楚。改善原始数据的质量,有很多可用的方法。比如提高识别算法精度,提高人工效率,也可以用它做模糊的检测,对比一下增强前后,可以知道哪些是模糊,哪些是不模糊。 刚才举的只是交通标志的例子。还有一个有趣的问题,就是感知电子眼。电子眼很小,而小目标的检测是一个有挑战的问题,在研究领域大家也比较关注。大家可以感受下,拿一张图,如果是太小的东西,放大之后就看不清了,还不如远景。那怎么能比较精确的找到这么小的电子眼呢? 通常方式就是放大区域,因为这个东西太小了,光找这个目标比较难,找到区域放大,引入周边的信息。这些信息可以帮助更好的找到这个小目标,放的再大一点,才能看到其他相关的信息来帮助电子眼的智能检测。 但是放的太大也会有问题,放的太大会引入很多无关的信息。从技术上来说有一些解决方法,现在视觉技术上用的比较多的有一个注意力机制,画一个大框,机器自己会学哪块重要哪块不重要,帮助更好的聚焦到目标本身。当然,尽量会用一些先验信息,比如本身的分布、高度、大小。 光检测还不够,很多时候真实世界在变。很多时候要分辨出哪些变了哪些没变。以前检测出一个电子眼,新的资料又检测出一个电子眼,需要知道这两个是否是同一个。 如何判断?因为这张图表达的不一样,如果仔细看,确实可以看到背景的建筑、架设类型都差不多。需要用算法来判断到底是不是,这就牵涉到目标检测、车道归属、架设类型分析,还要做场景匹配。通过这些,很大程度上可以判断这是一个什么场景,从而判断两张图的元素是不是同一个。 刚才说的是道路,下面是几个跟POI相关的例子。POI的牌子,可以分成好多不同类型,有牌坊式、挂牌式、门脸式等。不仅POI各种各样,非POI其实也各种各样。如果只是检测文字的话,你会发现真实世界里的很多不是POI,有的只是标牌、标语、广告、对联、交通标志等。所以,要区分出POI和非POI。 有很多其他的复杂场景,这里不一一举例了,有些可能平时也不太能想到,比如三维挂牌,它不是一个平的牌子,在街角,可能是一个水果超市,沿着街角弯曲过来。这类牌子很难在一张图里完全检测出来,即使检测出来,一不小心就会分成两块牌子,所以真实世界的复杂性还是会造成更多的问题。 面对这么多复杂性,需要去分析具体场景的情况。很多时候最后的结果往往不是一个算法就能解决所有的问题,需要各种算法的融合。比方说,如果是文字,需要做检测,文字本身也需要做检测和识别。位置的话,需要做一些三维方面的推断。很多时候资料获取到以后也有模糊和遮挡的部分,也要做判断。 每一个判断不是单一办法就可以解决,不是光靠一个模型就能够做到最好的效果,需要的是两个甚至更多的模型,从不同的角度去解决问题,才能够达到更好的效果,这是在数据积累的基础之上。 上面列举的一些问题有一定的复杂性,跟所有的问题一样,越做到后面越难,我们现在还在做,这些算法很大程度上决定了地图制作的效率和触达到用户的地图质量,这些是非常重要的核心问题。 POI也不光是以上介绍的只需要判断是不是POI或者文字识别,很多时候还需要做版面的内容理解。如果一个牌子,需要知道这个牌子上的信息,有时候会有主名称,有时候会有分店,有时候没有,有没有联系方式、营业范围,这些都需要用算法去做。 视觉技术@高德地图-导航 以上介绍的是在地图制作方面有很多的复杂性,需要用视觉算法或者其他算法来处理。接下来分享下在导航方面的。 先说下自己的一个体会。前段时间在西班牙休假,欧洲的环岛特别多,谷歌(地图)导航经常提示我,进了弯道之后从第三个出口出去,我当时特别郁闷,因为要数口子,经常你也不知道那个到底算不算出口,所以走错了好几次。我在国内没开过车,国内的交通更复杂,例如在北京的西直门,有时候可以直接右拐,有时候需要转一个810度的圈。 我们希望对导航的方式做一个比较大的变化,让它变成所见即所得的场景。如果有算法能够直接告诉人们往哪边走,对人来说是更加有用的,能够让开车更加简单,导航变得更加直接。 很多汽车现在都会有摄像头,不管是前端还是后端,很多时候可以获取到视频数据。我们把AI算法计算出的效果叠加在视频上,告诉人们到底该怎么走。 高德在今年4月份发布了AR导航产品,这个产品里有一项是实景增强,它会告诉你应该保持在这条线上继续往前开或者转弯,会有压线的提示,会有箭头告诉你前面右转。 这个产品中,除了引导之外,还有别的功能。例如,也加入了前车的碰撞预警功能,会估计前车的距离和速度,这将帮助大家安全驾驶。其他事物也可以用更加直观的方式展示,例如限速,电子眼,跟斑马线相关的,如果看到前方有人,也会做出提示。 以上的功能看起来可能不那么难,但要实现起来很难。为什么?因为我们希望这是每个人马上就能实用的功能,所以要做到很低的成本。这和自动驾驶系统不一样。从传感器的角度,我们要做的是单个传感器,而且是低成本的相机。从计算的角度来说,自动驾驶系统可能会用一个几百瓦的专用芯片,而对于我们来说,所需要的算力大概只是普通手机的五分之一。 给大家看一个AR导航的例子,这是实际算法的输出,这个例子里面有车辆的检测,车道线的分割,和引导线的计算等。刚才提到了,高性能(低算力)是一个主要挑战,那我们在开发算法的时候就要充分考虑计算效率,包括各种手段,比如模型压缩,小模型训练优化,检测和跟踪的结合,多目标的联合模型,和传统GPS导航的融合,等等,需要几件事情在一个模型里做。 真实世界是非常复杂的,要做到高质量、高效的地图制作,或者做到精准的定位导航,在视觉方面还有很多工作要做。希望通过以上介绍,大家对视觉技术在高德地图中的应用,在出行领域的应用,有了更多的了解,也对高德的使命有了更多了解。 我们在很多时候需要去连接真实世界或者是理解真实世界,才能够让出行更美好。希望能够尽快的把这些做好,让大家实际应用高德APP的时候,能够感受到技术进步带来的体验变化。我今天就讲到这里,谢谢大家。 本文作者:高德技术小哥 阅读原文 本文为云栖社区原创内容,未经允许不得转载。

October 17, 2019 · 1 min · jiezi

干货Flutter-原理与闲鱼深度实践

王康(正物)—— Flutter 官方成员 阿里巴巴技术专家,之前主要负责 Flutter 在闲鱼中的混合开发体系,目前重点关注 Flutter 深入度以及生态相关的工作。本文将分享三方面内容, Flutter 的原理、 Flutter 在闲鱼中的应用,最后介绍我们在深度方面的一些探索。01、Flutter 原理 当我们谈到跨平台框架时,可能会想到很多备选方案。包括早期的 HTML 和 Cordova , 后来的 React Native , Weex ,以及这两年很是流行的 Flutter ,它们都在不同阶段不同程度上解决了我们对跨平台的诉求。如果我们从一些关键指标包括动态性、性能来观察,他们的区别还比较明显。 HTML 和 Cordova 具有最好的动态性,但他们的性能却是最差的,RN / Weex 具有良好的动态性。Flutter 则是一个纯原生的设计,其设计使它天生具有很好的性能与跨端一致性。 Flutter 是如何实现优秀的性能和跨端一致性的呢?从设计上可以看出 Flutter 在操作系统之上包含了三个层次。最下面是平台相关的嵌入层,其向上提供一个 Surface 用以绘制,建立了相关的线程模型和事件循环机制。在此之上则是一个平台无关的引擎,包括用于绘制的 Skia ;Dart 的运行时,开发模式下包括一个解释器;还有一部分是文本绘制相关内容。最上面就是用 Dart 语言编写的 Flutter 框架,也是我们最常接触到的内容。Flutter 框架包含一个完整分层的 UI 框架,从基础的 Foundation 库,到动画手势,再到渲染,之上又提供了各种丰富的 Widget 库。为了方便开发者使用, Flutter 还提供了两套不同风格的组件库,针对安卓的 Material Design 的组件库和针对 iOS 的 Cupertino 风格的组件库。 从这个设计可以看出,Flutter 和平台相关的内容,其实只提供 Surface 和线程/事件循环模型的嵌入层部分。这种类似用游戏引擎的方式来开发应用的设计很好解释了为什么它具有优秀的跨端一致性。 ...

October 16, 2019 · 3 min · jiezi

一文读懂深度学习时序分析

作者 | Prakhar Ganesh编译 | 安然来源 | 图灵TOPIA近日,发表在《DataScience》上的一篇文章,使用深度学习方法,从数据处理、循环网络、RNN上的LSTM、CNN-LSTMs等方面介绍了时间序列分析,同时解释了时间序列的概念以及为什么选择深度学习的方法等问题。 什么是时间序列分析? 时间序列是一系列数据点,使用时间戳进行排序,是对时间序列数据的分析。 从水果的每日价格到电路提供的电压输出的读数,时间序列的范围非常大,时间序列分析的领域也是如此。分析时间序列数据通常侧重于预测,但也可以包括分类,聚类,异常检测等。 例如,通过研究过去的价格变化模式,可以尝试预测曾经想要购买的一款手表的价格,判断它的最佳购买时间! 为什么选择深度学习? 时间序列数据可能非常不稳定且复杂。深度学习方法不假设数据的基本模式,而且对噪声(在时间序列数据中很常见)的鲁棒性更强,是时间序列分析的首选方法。 数据处理 在继续进行预测之前,重要的是首先以数学模型可以理解的形式处理数据。通过使用滑动窗口切出数据点,可以将时间序列数据转换为监督学习问题。然后,每个滑动窗口的预期输出是窗口结束后的时间步长。 循环网络 循环网络一种复杂的深度学习网络。它们可以记住过去,因此是序列处理的首选。RNN单元是循环网络的骨干。 RNN单元具有2个传入连接,即输入和先前状态。同样,它们还具有2个传出连接,即输出和当前状态。这种状态有助于他们结合过去和当前输入的信息。 一个简单的RNN单元太简单了,无法统一用于跨多个域的时间序列分析。因此,多年来提出了各种各样的变体,以使循环网络适应各个领域,但核心思想保持不变!、 RNN上的LSTM LSTM单元格是特殊的RNN单元格,其中带有“门”,其本质上是介于0到1之间的值,对应于状态输入。这些门背后的直觉是忘记或保留过去的信息,这使他们不仅可以记住过去,还可以记住更多。 CNN-LSTMs 由于状态信息要经过每一个步长,所以RNNs只能记住最近的过去。 另一方面,像LSTM和GRU这样的门控网络可以处理相对较长的序列,但是即使这些网络也有其局限性!!为了更好地理解这一问题,还可以研究消失和爆炸的梯度。 那么如何处理很长的序列呢?最明显的解决办法就是缩短它们!!但如何?一种方法是丢弃信号中呈现的细粒度时间信息。 这可以通过将一小组数据点累积在一起并从中创建特征来完成,然后将这些特征像单个数据点一样传递给LSTM。 多尺度分层LSTMs 看看CNN-LSTM架构,有一件事浮现在我的脑海中……为什么要使用CNNs来合并那些组?为什么不使用不同的LSTM呢!多尺度分层LSTMs是基于相同的思想构建的。 输入是在多个尺度上处理的,每个尺度都致力于做一些独特的事情。适用于更细粒度输入的较低标度专注于提供细粒度(但仅是最近的)时间信息。 另一方面,较高的比例集中在提供完整的图片(但没有细粒度的细节)上。多个刻度可以一起更好地理解时间序列。 下一步是什么? 时间序列分析是一个非常古老的领域,包含各种跨学科的问题,每种陈述问题都有其自身的挑战。 然而,尽管每个领域都根据自己的要求调整了模型,但是时间序列分析中仍然有一些一般性的研究方向需要加以改进。 例如,从最基本的RNN单元到多尺度分层LSTM的每项开发都以某种方式专注于处理更长的序列,但是即使最新的LSTM修改也有其自身的序列长度限制,并且目前仍然没有一种架构可以真正处理极长的序列。

October 16, 2019 · 1 min · jiezi

经验拾忆纯手工-DeepLearningMetricsNg

前言看Andrew Ng视频,总结的学习心得。虽然本篇文章可能不是那么细致入微,甚至可能有了解偏差。但是,我喜欢用更直白的方式去理解知识。 数据划分传统机器学习数据的划分传统机器学习一般都是小规模数据(几万条) 那么可以 训练集:验证集:测试集 = 6:2:2若是大规模深度学习一般都是大规模数据(几百万条) 训练集: 验证机:测试集 = 9:0.5:0.5划分 验证集 可以过早的为我们预测 指标和精度 偏差 与 方差高偏差: 训练集和测试集 loss 都比较高 (比人预测的loss高很多) (欠拟合)高方差: 训练集Loss低, 测试集 Loss高。 所以训练集和测试集 loss相差太大, 也成为(过拟合) 防止过拟合的几种方法损失函数 (惩罚项系数) 正则化(regularization)可分两种 (L1正则化惩罚 和 L2正则化惩罚)下面只以 L2为例,L2用的也是比较多的)正则化系数公式: loss = ...new_loss = loss + (/2m) * w^2w = w - learning_rate * 梯度上面公式的单调变换解释: 求梯度的时候 越大, new_loss越大, 求得的梯度越大(正比)w 减去的值就越大。 w变得就越小。w 越小, 一定程度上特征就衰减了许多。 就有效的放置了过拟合哦对应API(有两种方式): L1 = keras.regularizers.l2(0.01) # TF2 当作 keras 的 Layers定义来使用L1 = tf.nn.l2_loss(w_b) # 看到里面传递 w和b了吧, 这种是偏手动方式实现的API如果你想使用手撕实现,下面有个例子(伪代码): ...

October 3, 2019 · 4 min · jiezi

盘点文本内容安全领域-深度学习的六个主流应用方法

本文来自:易盾实验室 在深度学习技术兴起之前相当长的一段时间内,基于机器学习技术的文本分类方法占据着文本分类领域的统治地位。 如下图所示,特征工程+机器学习分类器一直是解决文本分类问题的标准范式。针对不同的业务场景,算法工程师需要精心设计相应的特征工程,以取得最佳的分类效果。][2] 到2010年,深度学习技术逐渐兴起,文本分类领域的技术格局也相应的发生了变化。基于深度学习的文本分类方法打破了上述技术范式,对文本进行简单预处理后,直接喂给深度学习模型,进行端到端的训练和推断。一般性的,用于文本分类的深度学习模型最后一层为softmax层(多标签问题则为sigmoid),这相当于机器学习分类器中的LR模型。由此可见,模型的其余部分本质上就是在自动学习文本的特征表示,因此算法工程师再也不用操心特征工程的事情了。不过先别高兴得太早,文本特征学得好不好,取决于具体的深度学习模型结构设计和超参数设置,工程师们还是得把省下来的时间花在模型结构和超参数的调整上面。 本文根据易盾文本算法团队在内容安全领域的实践经验,介绍在项目中用过的一些深度学习模型以及对部分技术细节进行讨论。深度学习是近几年来的热门方向,学术界和工业界的研究人员提出了很多有价值的方法,本文所分享的方法只是其中少数代表性的工作,仅供读者参考。 CNN 使用CNN来做文本分类最早见于2014年Convolutional Neural Networks for Sentence Classification”这篇文章当中。CNN模型现在已经是做文本分类的经典模型,综合考虑模型效果、计算开销、计算并行化等因素,CNN模型往往具备不错的竞争力。有学者表示,CNN模型之所以能够获得较好的分类效果,与卷积核的使用有关。不同size的卷积核,对文本在不同位置进行卷积计算,相当于提取不同的n-gram特征,这有助于模型的最终分类。 上图是一个典型的单层CNN模型结构。首先将文本转化成词向量矩阵,然后分别使用不同size的的卷积核对矩阵进行卷积,每组卷积输出多个feature map,然后进行max pooling后,把所有feature map拼接在一起,形成单个向量表示,最后加上一层全连接和softmax操作,输出分类分数。 图中只是一个示例,各类超参数都比较小,在实际使用过程中,词向量大小50以上,卷积核的size一般取2~7,每个卷积的feature map数量在几十到几百。另外max pooling也可以换成其它的pooling方法,比如average pooling,不过总体来说还是max pooling比较适合分类场景。正常情况下,通过超参数的调优,单层CNN模型已经能够适用大多数文本分类场景。但也有人使用多层CNN模型的,我们的经验是参数数量差不多的前提下,多层CNN未发现有明显的效果提升。 RNN RNN模型主要用于处理序列数据,而文本天然的就是表示成若干词的序列,因此使用RNN模型来对文本进行建模是十分自然的事情。与全连接或卷积网络不同,RNN内部不同词对应的隐藏层相互之间是有联系的:当前词的隐藏层的输入除了输入层的输出,还包括前一个词的隐藏层的输出。 当序列长度较长时,基础的RNN模型存在梯度爆炸和梯度消失问题。LSTM和GRU是RNN的两种改良版本,它们通过门的机制对RNN中信息的传播进行控制,缓解了RNN的梯度消失问题(RNN梯度爆炸问题可以通过gradient clipping技术进行解决)。从图中可以看出,GRU与LSTM结构比较相似,主要不同之处在于GRU使用更新门来对LSTM的输入门和遗忘门进行简化。 由于RNN最后一个词的输出已经融合了前面词的信息,RNN用于文本分类时一般取最后一个词的输出作为整个文本的特征表示,即用最后的输出加上全连接和softmax计算分类分数。当然,一般我们会使用多层RNN的结构,用最后一个词的末层RNN的输出计算分类分数。 RNN的数据流动是单向的,只能从前往后或从后往前。Bi-RNN对此进行了改进,具体做法是使用前向RNN和后向RNN,把文本中最后一个词的前向RNN输出和第一个词的后向RNN输出拼接在一起,作为文本的特征表示。从我们的实践经验上看,Bi-RNN的这种改进效果提升很明显,我们知道attention对模型有较大的提升作用,但在某些业务场景里面attention对Bi-LSTM的提升比较有限,这说明Bi-LSTM自身的效果已经比较接近问题本身的理论上限。 RCNN RCNN也是早期深度学习技术应用于文本分类上面经常用到的模型之一。RCNN为每个词定义了left context和right context两个变量,具体计算方式如下: 最终每个词由自身的词向量和两个context拼接共同表示,然后先接一层全连接层,再作max pooling形成单个的向量。这个模型为什么叫RCNN(Recurrent Convolutional Neural Networks)呢?首先,从left context和right context的定义可以看出这部分其实就是一个双向的RNN,只不过最后还拼接上原始的词向量。另外,这里并没有只取最后一个词的输出计算分类分数,而是对每个词的输出进行全连接再作max pooling。其实,这里的全连接等价于进行size为[1,emb_size]和strip为1的二维卷积操作,后面再跟着max pooling,这就是典型的CNN结构。 Attention Attention机制被广泛使用在自然语言处理、图像识别及语音识别等各种不同类型的深度学习任务中,是深度学习技术中最值得关注与深入了解的核心技术之一。Attention机制可以理解成给定Q,从一系列K-V键值对中计算出各个V的权重,然后再对V进行加权平均。具体公式如下: 其中f函数对Q和K进行打分,可以有不同的实现方式,常见的有点积、缩放点积、加性、双线性等方法,我们也可以自己实现其它的计算方法。 我们注意到上述attention的计算涉及到Q、K、V三个输入,当Q=K时,这样的attention技术被称为self-attention。实际上,self-attention是目前用得最多的attention技术,它不需要额外的数据,只根据文本自身的上下文,就能计算文本中各个词的重要性。可以看出,attention本质上就是算各个词的权重,然后进行加权平均。而我们知道在word2vec问世以后,在怎么把多个词的词向量变成单个向量来表示句子的问题上,有一种做法就是加权平均,比如根据tf-idf加权平均。那么attention和这种加权平均的区别是什么?最本质的不同就是同一个词,普通的加权平均方法权重是固定不变的(最多乘以词频系数),attention方法的权重是根据上下文动态计算的,在不同的文本和不同的位置,它的权重都是不一样的。这就像人类的视觉注意力,看到不同的图像时重点关注的区域不一样,所以我们把这个技术叫做attention。同一个词在不同的上下文中得到不同的输出,这种特性使得attention方法天然的般配NLP中的一词多义问题。 具体到文本分类模型,attention的使用比较灵活,既可以单独使用attention进行分类,也可以和CNN、RNN等模型结合。目前常见的模型有transformer、HAN、RNN+attention、CNN+attention、Bi-RNN+attention等等,这里不再展开赘述。 FastText FastText是Facebook在2016年开源的一个轻量级文本表示和文本分类工具。它的特点是在具有媲美当时复杂深度神经网络模型文本分类准确率的同时,训练和预测非常高效,CNN训练1天的数据,FastText只要几秒即可。 FastText之所以这么高效,主要有三个原因。第一,模型结构特别简单,对文本所有单词的embedding求平均然后加上softmax分类器。第二,这个softmax分类器是一个层次softmax分类器,这个在分类类别很多的时候比较有用。第三,FastText使用C++实现的,并且作者代码能力也非常强,因此虽然有很多复现版本,但都没有原版高效。 尽管模型结构简单,FastText使用了n-gram和subword两种技术,帮助提升了文本分类效果。n-gram有助于模型捕捉文本局部的单词顺序,而大部分文本分类任务并不需要太长的依赖关系。subword也叫char n-gram,就是把单词分解更小的子串片段,这能更好的对未登录词和稀有词进行建模,同时学习到相同词缀单词语义关系。 总的来说,FastText适用于对精确度要求不高同时需要较高实时性的文本分类场景,也可以作为新算法的一个baseline。 Bert BERT是谷歌在2018年发布的一个预训练语言模型,它刷新了11个NLP任务的记录。BERT的发布使得NLP领域真正进入到了基于通用预训练模型进行下游任务的时代,同时也进入了大力出奇迹的时代——通过更多的数据、更大的模型获得更高的准确率,从此以后各家科技巨头推出的模型越来越大,训练用的数据也越来越多,简直就是在炫富。其实在BERT之前也有很多预训练语言模型的研究,像ELMo、GPT都是当时比较突出的成果,它们的很多思路和方法都被BERT借鉴了。 相比前辈们,BERT之所以引起这么大的关注,主要在于它的效果确实很惊艳,同时在多个NLP任务上面刷新记录,并且提升幅度都还挺大的。更重要的是,BERT用在这些任务上面并不需要精心设计下游网络,基本上都是接一个简单的预测结构,然后简单地fine-tuning一下就OK了。 BERT模型结构本身并不复杂,主要分为3个部分:最底层是embedding组件,包括词、位置和token types三种embedding的组合;中间层是由多个Transformer encoder组成的深度网络(base版本是12层,large版本是24层);上层是与训练任务相关的组件,主要就是softmax网络。BERT模型比较重要的创新有两方面,分别是Masked LM和Next Sentence Prediction(NSP)。Masked LM用[MASK]替换句子中的部分单词,模型的目标是预测[MASK]位置上的真实单词。 ...

September 10, 2019 · 1 min · jiezi

用11个事实为8岁女儿解读深度学习

作者 | Jean-Louis Queguiner来源 | 机器之心「神经网络就像数数一样简单」,「卷积层只是一个蝙蝠信号灯」……在本文中,一位奶爸从手写数字识别入手,用这样简单的语言向自己 8 岁的女儿解释了一下「深度学习」。当然,用这篇文章向女朋友(如果有的话)科普自己的工作也是可以的。 机器学习,尤其是深度学习是一个热门话题,你肯定会在媒体上看到流行语「人工智能」。 然而,这些并非新概念。第一个人工神经网络(ANN)是在 40 年代引入的。那么为什么最近的热点话题都是关于神经网络和深度学习的呢?我们将在 GPU 和机器学习的一系列博客文章中探讨这些概念。 在 80 年代,我记得我父亲构建了用于银行支票的字符识别工具。检查这么多不同类型的笔迹真的是一件痛苦的事,因为他需要一个方程来适应所有的变化。 在过去几年中,很明显,处理这类问题的最佳方法是通过卷积神经网络。人类设计的方程不再适合处理无限的手写模式。 让我们来看看最经典的例子之一:构建一个数字识别系统,一个识别手写数字的神经网络。 事实 1:神经网络就像数数一样简单 我们首先计算最上面一行的红色形状在每个黑色手写数字中出现了几次。 ▲手写数字的简化矩阵 现在让我们尝试通过计算具有相同红色形状的匹配数来识别(推断)新的手写数字。然后我们将其与之前的表格进行比较,以确定这个数字与哪个数字有最强的关联: ▲匹配手写数字的形状 恭喜!你刚刚构建了世界上最简单的神经网络系统,用于识别手写数字。 事实 2:图像只是一个矩阵 计算机将图像视为矩阵。一张黑白图像是个 2D 矩阵。 我们来考虑一张图像。为了简单起见,我们拍摄一张数字 8 的小黑白图像,方形尺寸为 28 像素。 矩阵的每个单元表示从 0(表示黑色)到 255(表示纯白色像素)的像素强度。 因此,图像将表示为以下 28×28 的像素矩阵。 ▲手写数字 8 的图像和相关的强度矩阵 事实 3:卷积层只是一个蝙蝠信号灯 为了确定图片中显示的图案(此处指手写数字 8),我们将使用一种蝙蝠信号灯/手电筒。在机器学习中,手电筒被称为过滤器(filter)。该过滤器用于执行 Gimp 等常见图像处理软件中用到的经典卷积矩阵计算。 过滤器将扫描图片,以便在图像中找到图案,并在匹配成功时触发正反馈。它有点像儿童形状分类盒:三角形过滤器匹配三角形孔,方形过滤器匹配方孔等。 ▲图像过滤器像儿童形状分类盒一样工作。 事实 4:过滤器匹配是一项易并行任务 更科学地来讲,图像过滤过程看起来有点像下面的动画。如你所见,过滤器扫描的每个步骤都是相互独立的,这意味着此任务可以高度并行化。 要注意,数十个过滤器将同时运行,因为它们不相互依赖。 事实 5:尽可能多次重复过滤操作(矩阵卷积) ...

August 20, 2019 · 1 min · jiezi

为什么异或问题是线性不可分割的

为什么异或问题是线性不可分割的看教材的时候多说,感知机(单层神经网络)不能解决异或问题,那为什么呢??? 感知机是处理线性问题的 异或问题是非线性问题 为什么感知机是处理线性问题的?为什么异或问题是非线性问题?给出一个知乎上的解释,我觉得可以跳转链接——go知乎 平面上4个点, (0,0)(1,1)为一类, (0,1)(1,0)为另一类。线性可分就是指通过平面上一条直线 ax+by+c=0 可以将两类分开到直线的两侧。 假设存在这样的直线,则(0,0)(1,1)代入直线方程(不妨假设该类在直线的正侧,则另一类在直线的负侧): c>0 (1) a+b+c>0 (2) 把(0,1)(1,0)代入直线方程 b+c<0 (3) a+c<0 (4) 而(3)+(4)-(1) 与 (2)矛盾,所以不存在这样的直线 为什么是线性可分?

July 14, 2019 · 1 min · jiezi

第2话-TensorFlow-数据流图

1.1 什么是数据流图TensorFlow使用符号计算图,这与Theano相似,不过与Theano相比,TensorFlow 更简洁。TensorFlow 的名字本身描述了它自身的执行原理: Tensor (张量)意味着N维数组,Flow (流)意味着基于数据流图的计算。数据流图中的图就是我们所说的有向图,在图这种数据结构中包含两种基本元素:节点和边。这两种元素在数据流图中有自己各自的作用,其中节点代表对数据所做的运算或某种算子(Operation)。另外,任何一种运算都有输人/输出,因此它也可以表示数据输人的起点或输出的终点。而边表示节点与节点之间的输人1输出关系,一种特殊类型的数据沿着这些边传递。这种特殊类型的数据在TensorFlow中被称为Tensor,即张量,所谓的张量通俗点说就是多维数组。 当我们向这种图中输人张量后,节点代表的操作就会被分配到计算设备完成计算,下面就是一个简单的数据流图。 1.2 TensorFlow实现数据流图1.3 可视化数据流图

July 13, 2019 · 1 min · jiezi

深度学习与神经网络

CDA数据分析研究院出品,转载需授权深度学习是机器学习的一个子领域,研究的算法灵感来自于大脑的结构和功能,称为人工神经网络。 如果你现在刚刚开始进入深度学习领域,或者你曾经有过一些神经网络的经验,你可能会感到困惑。因为我知道我刚开始的时候有很多的困惑,我的许多同事和朋友也是这样。因为他们在20世纪90年代和21世纪初就已经学习和使用神经网络了。 该领域的领导者和专家对深度学习的观点都有自己的见解,这些具体而细微的观点为深度学习的内容提供了很多依据。 在这篇文章中,您将通过听取该领域的一系列专家和领导者的意见,来了解什么是深度学习以及它的内容。 来让我们一探究竟吧。 深度学习是一种大型的神经网络Coursera的Andrew Ng和百度研究的首席科学家正式创立了Google Brain,最终导致了大量Google服务中的深度学习技术的产品化。 他已经说了很多关于深度学习的内容并且也写了很多,这是一个很好的开始。 在深度学习的早期讨论中,Andrew描述了传统人工神经网络背景下的深度学习。在2013年的题为“ 深度学习,自学习和无监督特征学习”的演讲中“他将深度学习的理念描述为: 这是我在大脑中模拟的对深度学习的希望: 使学习算法更好,更容易使用。在机器学习和人工智能方面取得革命性进展。我相信这是我们迈向真正人工智能的最好机会 后来他的评论变得更加细致入微了。 Andrew认为的深度学习的核心是我们现在拥有足够快的计算机和足够多的数据来实际训练大型神经网络。在2015年ExtractConf大会上,当他 的题目“科学家应该了解深度学习的数据”讨论到为什么现在是深度学习起飞的时候,他评论道: 我们现在拥有的非常大的神经网络......以及我们可以访问的大量数据 他还评论了一个重要的观点,那就是一切都与规模有关。当我们构建更大的神经网络并用越来越多的数据训练它们时,它们的性能会不断提高。这通常与其他在性能上达到稳定水平的机器学习技术不同。 对于大多数旧时代的学习算法来说......性能将达到稳定水平。......深度学习......是第一类算法......是可以扩展的。...当你给它们提供更多的数据时,它的性能会不断提高 他在幻灯片中提供了一个漂亮的卡通片: 最后,他清楚地指出,我们在实践中看到的深度学习的好处来自有监督的学习。从2015年的ExtractConf演讲中,他评论道: 如今的深度学习几乎所有价值都是通过有监督的学习或从有标记的数据中学习 在2014年的早些时候,在接受斯坦福大学的题为“深度学习”的演讲时,他也发出了类似的评论。 深度学习疯狂发展的一个原因是它非常擅长监督学习 Andrew经常提到,我们应该并且会看到更多的好处来自DL的无监督的一面,因为该领域已经成熟到可以处理大量未标记的数据。 Jeff Dean是Google的系统和基础架构小组的向导和谷歌高级研究员,他参与并可能负责部分Google内部深度学习的扩展和采用。Jeff参与了Google Brain项目以及负责大型深度学习软件DistBelief和后来的TensorFlow的开发。 在2016年的一次题为“ 构建智能计算机系统的深度学习”的演讲中“他以类似的方式发表评论,深度学习实际上是关于大型神经网络的。 当你听到深度学习这个词的时候,就想想一个巨大的深度神经网络。深度指的是典型的层数,因此这种流行术语在印刷机中被采用。我认为它们通常是深度神经网络。 他已经多次发表过这个演讲,并且在同一个演讲的一组修改过的幻灯片中,他强调了神经网络的可扩展性,表明随着更多的数据和更大的模型,结果会变得更好,然而这反过来需要更多的计算来训练模型。 深度学习是层次特征学习除了可扩展性之外,深度学习模型的另一个经常被引用的好处是它们能够从原始数据中执行自动特征提取,也称为特征学习。 Yoshua Bengio是深度学习的另一个领导者,尽管他开始对大型神经网络能够实现的自动特征学习产生了浓厚的兴趣。 他描述了使用特征学习发现和学习良好表示的算法能力方面的深度学习。在2012年题为“ 深度学习无监督和转移学习的表征 ”的论文中,他评论说: 深度学习算法试图利用输入分布中的未知结构,以便通常在多个级别上发现良好的表示,并使用较低级别的特征定义更高级别的学习特征 他在2009年的技术报告“ 人工智能学习深层架构”中提供了沿着这些方向深入学习的详细视角,其中他强调了特征学习中层次结构的重要性。 深度学习方法旨在学习具有来自较低级别特征的组成所形成的较高级别的层级的特征的特征层级。在多个抽象级别上自动学习特性允许系统学习的复杂函数,这些函数直接从数据映射输入到输出,而不完全依赖于人工创建的特性。 在与Ian Goodfellow和Aaron Courville合着的即将出版的名为“ 深度学习 ”的书中,他们根据模型的架构深度来定义深度学习。 概念的层次结构允许计算机通过用简单的概念构建复杂的概念来学习它们。如果我们绘制一个图表来显示这些概念是如何相互构建的,那么图表很深的,有很多层。出于这个原因,我们将这种方法称为人工智能深度学习。 这是一本重要的书,有可能在一段时间内成为该领域的权威资源。本书继续描述多层感知器作为深度学习领域中使用的算法,给出了深度学习已包含在人工神经网络中的观点。 深度学习模型的典型例子是前馈深度网络或多层感知器(MLP)。 彼得·诺维格(Peter Norvig)是谷歌研究部主任,以其题为“ 人工智能:现代方法”的人工智能教科书而闻名。 在2016年的一次演讲中,他给出了题为“深度学习和可理解性与软件工程和验证的关系”“他以与Yoshua非常相似的方式定义深度学习,重点关注使用更深层网络结构所允许的抽象力量。 这是一种学习,你形成的表示有多个抽象层次,而不是直接输入到输出 为什么称它为“深度学习”? 而不只是称它为“人工神经网络”?Geoffrey Hinton是人工神经网络领域的先驱,共同发表了关于训练多层感知器网络的反向传播算法的第一篇论文。 他可能已经开始引入“ 深度 ” 这个短语来描述大型人工神经网络的发展。 他在2006年共同撰写了一篇题为“ 深度信念网的快速学习算法”的论文,其中描述了一种受训练限制的玻尔兹曼机器的“深度”(就像一个多层网络一样)的方法。 ...

July 11, 2019 · 1 min · jiezi

TensorFlow学习笔记第三章TensorFlow入门

(基于tensorflow 1.14 c'pu版本,读者需要具有良好的python基础和线性代数知识) 第三章分别介绍TensorFlow的计算模型、数据模型和运行模型,以对TensorFlow的工作原理有一个大致的了解。 3.1 计算图————TensorFlow的计算模型计算图的概念TensorFlow这个单词由两部分组成:tensor代表张量,是数据结构;flow代表流,是计算模型。流动的事务具有有向性,计算图就是一个具有‘每一个节点都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系’性质的有向图。 计算图的使用TensorFlow程序一般分为两个阶段。第一阶段:定义计算图中所有的计算,然后定义一个计算来得到他们的和;第二阶段:执行计算。 在TensorFlow程序中,系统会自动维护一个默认的计算图,通过tf.get_default_graph()函数可以获取这个默认的计算图 import tensorflow as tfa = tf.constant([1.0, 2.0], name='a')b = tf.constant([1.0, 2.0], name='b')result = a + b#通过a.graph属性可以查看这个张量所属的计算图。因为没有特意指定,所以这个计算图应该等于当前默认的计算图print(a.graph is tf.get_default_graph())'''输出>>>True'''除了使用默认的计算图,TensorFlow支持通过tf.Graph函数来生成新的计算图。不同计算图上的张量和运算不会共享。以下代码示意了如何通过在不同的计算图上定义和使用变量。 import tensorflow as tfg1 = tf.Graph()with g1.as_default(): v = tf.get_variable('v', shape=[1], initializer=tf.zeros_initializer)g2 = tf.Graph()with g2.as_default(): v = tf.get_variable('v', shape=[1], initializer=tf.ones_initializer)'''tf.Graph()没有实现__enter__()方法,做不到下面那优雅pythonic的写法。with tf.Graph() as g2: v = tf.get_variable('v', shape=[1], initializer=tf.ones_initializer) Traceback (most recent call last): File "D:/bb/TensorFlow/Untitled1.py", line 7, in <module> with tf.Graph() as g2:AttributeError: __enter__'''with tf.Session(graph=g1) as sess: tf.global_variables_initializer().run() with tf.variable_scope("", reuse=True): print(sess.run(tf.get_variable('v')))with tf.Session(graph=g2) as sess: tf.global_variables_initializer().run() with tf.variable_scope("", reuse=True): print(sess.run(tf.get_variable('v')))'''输出>>>[0.][1.]注:先不要管代码是什么含义,继续往下看'''TensorFlow中的计算图不仅可以隔绝张量和计算,它还提供了管理张量和计算的机制 ...

July 10, 2019 · 1 min · jiezi

机器学习在高德搜索建议中的应用优化实践

导读:高德的愿景是:连接真实世界,让出行更美好。为了实现愿景,我们要处理好LBS大数据和用户之间的智能链接。信息检索是其中的关键技术,而搜索建议又是检索服务不可或缺的组成部分。 本文将主要介绍机器学习在高德搜索建议的具体应用,尤其是在模型优化方面进行的一些尝试,这些探索和实践都已历经验证,取得了不错的效果,并且为后来几年个性化、深度学习、向量索引的应用奠定了基础。 对搜索排序模块做重构搜索建议(suggest服务)是指:用户在输入框输入query的过程中,为用户自动补全query或POI(Point of Interest,兴趣点,地理信息系统中可以是商铺、小区、公交站等地理位置标注信息),罗列出补全后的所有候选项,并进行智能排序。 我们希望通过suggest服务:智能提示,降低用户的输入成本。它的特点是:响应快、不承担复杂query的检索,可以把它理解为一个简化版的LBS领域信息检索服务。 和通用IR系统一样,suggest也分为doc(LBS中的doc即为POI)的召回和排序两个阶段。其中,排序阶段主要使用query和doc的文本相关性,以及doc本身的特征(weight、click),进行加权算分排序。 但随着业务的不断发展、特征规模越来越大,人工调参逐渐困难,基于规则的排序方式已经很难得到满意的效果。这种情况下,为了解决业务问题,将不得不打上各种补丁,导致代码难以维护。 因此,我们决定对排序模块进行重构,Learning to Rank无疑是一个好的选择。 面临的挑战:样本构造、模型调优Learning to Rank(LTR)是用机器学习的方法来解决检索系统中的排序问题。业界比较常用的模型是gbrank,loss方案用的最多的是pair wise,这里也保持一致。一般应用LTR解决实际问题,最重要的问题之一就是如何获得样本。 首先,高德地图每天的访问量巨大,这背后隐藏的候选POI更是一个天文数字,想要使用人工标注的方法去获得样本明显不现实。 其次,如果想要使用一些样本自动构造的方法,比如基于用户对POI的点击情况构建样本pair ,也会遇到如下的问题: 容易出现点击过拟合,以前点击什么,以后都给什么结果。有时,用户点击行为也无法衡量真实满意度。suggest前端只展示排序top10结果,更多的结果没有机会展现给用户,自然没有点击。部分用户习惯自己输入完整query进行搜索,而不使用搜索建议的补全结果,统计不到这部分用户的需求。对于这几个问题总结起来就是:无点击数据时,建模很迷茫。但就算有某个POI的点击,却也无法代表用户实际是满意的。 最后,在模型学习中,也面临了特征稀疏性的挑战。统计学习的目标是全局误差的一个最小化。稀疏特征由于影响的样本较少,在全局上影响不大,常常被模型忽略。但是实际中一些中长尾case的解决却往往要依靠这些特征。因此,如何在模型学习过程中进行调优是很重要。 系统建模过程详解上一节,我们描述了建模的两个难题,一个是样本如何构造,另一个是模型学习如何调优。 先看下怎么解决样本构造难题,我们解决方案是: 考量用户在出行场景的行为session,不光看在suggest的某次点击行为,更重要的是,考察用户在出行场景下的行为序列。比如suggest给出搜索建议后,继续搜索的是什么词,出行的地点是去哪里,等等。不是统计某个query下的点击, 而是把session看作一个整体,用户在session最后的点击行为,会泛化到session中的所有query上。详细方案第一步,融合服务端多张日志表,包括搜索建议、搜索、导航等。接着,进行session的切分和清洗。最后,通过把输入session中,末尾query的点击计算到session中所有query上,以此满足实现用户输入session最短的优化目标。 如下图所示: 最终,抽取线上点击日志超过百万条的随机query,每条query召回前N条候选POI。利用上述样本构造方案,最终生成千万级别的有效样本作为gbrank的训练样本。 特征方面,主要考虑了4种建模需求,每种需求都有对应的特征设计方案: 有多个召回链路,包括:不同城市、拼音召回。因此,需要一种特征设计,解决不同召回链路间的可比性。随着用户的不断输入,目标POI不是静态的,而是动态变化的。需要一种特征能够表示不同query下的动态需求。低频长尾query,无点击等后验特征,需要补充先验特征。LBS服务,有很强的区域个性化需求。不同区域用户的需求有很大不同。为实现区域个性化,做到千域千面,首先利用geohash算法对地理空间进行分片,每个分片都得到一串唯一的标识符。从而可以在这个标识符(分片)上分别统计特征。 详细的特征设计,如下表所示: 完成特征设计后,为了更好发挥特征的作用,进行必要的特征工程,包括尺度缩放、特征平滑、去position bias、归一化等。这里不做过多解释。 初版模型,下掉所有规则,在测试集上MRR 有5个点左右的提升,但模型学习也存在一些问题,gbrank特征学习的非常不均匀。树节点分裂时只选择了少数特征,其他特征没有发挥作用。 以上就是前面提到的,建模的第二个难题:模型学习的调优问题。具体来说就是如何解决gbrank特征选择不均匀的问题。接下来,我们详细解释下。 先看下,模型的特征重要度。如下图所示: 经过分析,造成特征学习不均衡的原因主要有: 交叉特征query-click的缺失程度较高,60%的样本该特征值为0。该特征的树节点分裂收益较小,特征无法被选择。然而,事实上,在点击充分的情况下,query-click的点击比city-click更接近用户的真实意图。对于文本相似特征,虽然不会缺失,但是它的正逆序比较低,因此节点分裂收益也比city-click低,同样无法被选择。综上,由于各种原因,导致树模型学习过程中,特征选择时,不停选择同一个特征(city-click)作为树节点,使得其他特征未起到应有的作用。解决这个问题,方案有两种: 方法一:对稀疏特征的样本、低频query的样本进行过采样,从而增大分裂收益。优点是实现简单,但缺点也很明显:改变了样本的真实分布,并且过采样对所有特征生效,无法灵活的实现调整目标。我们选择了方法二来解决。方法二: 调loss function。按两个样本的特征差值,修改负梯度(残差),从而修改该特征的下一轮分裂收益。例如,对于query-click特征非缺失的样本,学习错误时会产生loss,调loss就是给这个loss增加惩罚项loss_diff。随着loss的增加,下一棵树的分裂收益随之增加,这时query-click特征被选作分裂节点的概率就增加了。具体的计算公式如下式: 以上公式是交叉熵损失函数的负梯度,loss_diff 相当于对sigmod函数的一个平移。 差值越大,loss_diff越大,惩罚力度越大,相应的下一轮迭代该特征的分裂收益也就越大。 调loss后,重新训练模型,测试集MRR在初版模型的基础又提升了2个点。同时历史排序case的解决比例从40%提升到70%,效果明显。 写在最后Learning to Rank技术在高德搜索建议应用后,使系统摆脱了策略耦合、依靠补丁的规则排序方式,取得了明显的效果收益。gbrank模型上线后,效果基本覆盖了各频次query的排序需求。 目前,我们已经完成了人群个性化、个体个性化的建模上线,并且正在积极推进深度学习、向量索引、用户行为序列预测在高德搜索建议上的应用。 本文作者:高德技术小哥阅读原文 本文为云栖社区原创内容,未经允许不得转载。

July 10, 2019 · 1 min · jiezi

如何教机器思考他们所看到的

研究人员将统计和符号人工智能技术结合起来,以加快学习速度和提高透明度。Researchers combine statistical and symbolic artificial intelligence techniques to speed learning and improve transparency. Kim Martineau | 麻省理工学院 探索智能本文由CDA数据分析研究院编译出品,转载需授权研究人员训练了一个混合人工智能模型来回答这样的问题:“绿色立方体左边的红色物体与紫色哑光物体形状相同吗?”“通过给它提供包含颜色和形状的样本,然后是涉及多对象比较的更复杂的场景。该模型可以将这些知识转移到新的场景中,也比使用部分训练数据的进行训练的最先进的模型要好。 一个从未见过粉红大象的孩子仍然可以描述一只粉红色的大象---“不像电脑”。麻省理工学院(MIT)博士生吴嘉君(Jiajun Wu)说:“计算机是从数据中学习的。”“对机器来说,能够概括和识别你从未见过的东西,比如粉红色的大象-是非常困难的。” 深度学习系统通过挑选出数据中包含的某种统计信息来解释世界。这种机器学习方式现在随处可见,在Facebook上给朋友自动贴上标签,讲述亚历克莎最新的天气预报,并通过谷歌搜索提供有趣的事情。但是统计学习有其局限性。它需要大量的数据,很难解释为什么会是这样的,并且很难将过去的知识应用到新的环境中;比如它无法理解一只粉红而不是灰色的大象。 为了让计算机有能力像我们一样进行推理,人工智能(AI)的研究人员又回到了抽象的或象征性的编程模式中。20世纪50年代和60年代,符号AI将规则和逻辑连接起来,允许机器进行比较,并解释物体和实体之间的联系。符号AI使用较少的数据,记录它所采取的一系列步骤来达成一个决定,当它与统计神经网络的野蛮处理能力相结合时,它甚至可以在复杂的图像理解测试中击败人类。 麻省理工学院IBM沃森人工智能实验室和DeepMind的一组研究人员进行的一项新研究表明,将统计人工智能和符号人工智能结合在一起是有希望的。在麻省理工学院脑和认知科学系以及计算机科学和人工智能实验室的教授吴宇森和 Joshua Tenenbaum 的带领下,研究表明,其混合模型可以学习与物体相关的概念,如颜色和形状,并利用这些知识来解释场景中复杂的物体关系。他们的模型只需要很少的训练数据,没有明确的编程,就可以将模型迁移到更大的场景中,并能回答越来越棘手的问题,甚至比其最先进的同行更好。该小组在5月举行的国际学习代表大会上介绍了其成果。 “孩子们学习概念的一种方式是把文字和图像联系起来,”该研究的主要作者、清华大学的本科生、麻省理工学院的访问学者毛家源说。“能够以同样的方式学习的机器需要的数据少得多,而且能够更好地将其知识迁移到新的场景中。” 雅各布·安德烈亚斯(Jacob Andreas)说,这项研究是回归抽象程序方法的有力论据,他是加利福尼亚大学伯克利分校(University of California at Berkeley)的一名毕业生,今年秋天开始在麻省理工学院(MIT)担任助理教授,并未参与这项工作。他说:“事实证明,诀窍在于增加更多的符号结构,并向神经网络提供一种世界的表示,这种世界被划分为对象和属性,而不是给它提供原始图像。”“这项工作让我们了解在语言学习成为可能之前,机器需要了解什么。” 研究小组将他们的模型训练在与相关问题和答案配对的图像上,这是斯坦福大学开发的CLEVR图像理解测试的一部分。随着模型的学习,问题越来越难回答,“物体的颜色是什么?”“到”绿色圆柱体右侧有多少个物体,与蓝色小球的材质相同吗?“一旦掌握了对象级的概念,模型就开始学习如何将对象及其属性相互关联。 像其他混合人工智能模型一样,麻省理工的工作就是将任务分解。神经网络的感知模块对每幅图像中的像素进行处理,并绘制出物体的地图。语言模块,也由神经网络组成,从每个句子中的单词中提取意义,并创建符号程序或指令,告诉机器如何回答问题。第三个推理模块在现场运行符号程序并给出答案,当模型出错时更新模型。 团队方法的关键是一个感知模块,它将图像转换为基于对象的表示,使程序更容易执行。同样独特的是他们所说的课程学习,或选择性地训练模式的概念和场景,逐步增长的难度。事实证明,以合乎逻辑的方式而不是随意地输入数据有助于模型更快地学习,同时提高准确性。 一旦模型有了坚实的基础,它就可以解释新的场景和概念,以及越来越难的问题,这几乎是完美的。被要求回答一个不熟悉的问题,比如,“大黄色物体的形状是什么?”它的训练数据比斯坦福大学和附近的麻省理工林肯实验室的同行要少,但是效果上是更好的。 当其他模型接受了70000张图片和700000个问题的完整CLEVR数据集进行训练时,MIT-IBM模型使用了5000张图片和100000个问题。由于模型建立在先前学习的概念之上,它吸收了每个问题的基础程序,所以加快了训练过程。 虽然在统计上,深度学习模型现在已经嵌入日常生活中,但它们的决策过程中的大部分仍然隐藏在视野之外。由于缺乏透明度,很难预测系统易受操纵、错误或偏差的影响。添加一个符号层可以打开黑匣子,解释混合人工智能系统日益增长的兴趣。 林肯实验室研究员大卫·马斯卡卡(David Mascharka)说:“将任务分解,让程序完成一些工作,是将可解释性构建成深度学习模型的关键。”他的混合模型“透明设计网络”(Transparency by Design Network)是麻省理工学院-IBM研究的基准。 MIT-IBM团队现在正致力于改进模型在真实照片上的性能,并将其扩展到视频理解和机器人操作。这项研究的其他作者分别是麻省理工学院-IBM沃森人工智能实验室和DeepMind的研究员庄根(Chuang Gan)和普希梅特·科利(Pushmeet Kohli)。 原标题:Teaching machines to reason about what they see 如果你是以下几种情况之一: 1、想了解更多大数据分析、数据挖掘、数据科学、人工智能领域的内容; 2、职业遭遇瓶颈,想提升自己在数据分析或人工智能领域的硬件技能; 3、寻求新出路、新发展,有意向转行到数据分析行业或人工智能领域。 可前往我们的官网,获取更多有效信息和帮助:https://www.cda.cn/?seo-segme...

July 10, 2019 · 1 min · jiezi

深度学习CNN-用-ReLURNN-用-tanh

作者:LogM 本文原载于 https://segmentfault.com/u/logm/articles ,不允许转载~ 1. CNN 用 ReLU ?sigmoid 的导数在 [0, 0.25] 范围里;tanh 的导数在 [0, 1] 范围里;ReLU 的导数为 {0, 1}。 如果 CNN 的每一层都使用 sigmoid,小于1的导数的多次连乘引发"梯度消失"。 那为什么不使用 tanh? tanh 的导数虽然可以达到1,但在边缘仍有"梯度消失"的问题出现。只能说 tanh 在一定程度上缓解了"梯度消失"。 ReLU 的正半区没有"梯度消失",但负半区存在"梯度消失",(但也有人认为负半区的存在可以使参数矩阵稀疏,有一定正则化的效果)。 最最重要的是,ReLU 的计算量是远小于 sigmoid 和 tanh 的。 A four-layer convolutional neural network with ReLUs (solid line) reaches a 25% training error rate on CIFAR-10 six times faster than an equivalent network with tanh neurons (dashed line).ReLU 最先不是针对深度网络发明出来的,所以我们很难从发明者的角度探寻 ReLU 的诞生解决了深度网络的什么问题。事实情况是,当学者们把 ReLU 用在深度网络上发现效果很好,就陆陆续续提出了一些理论来解释为什么 ReLU 的效果好。所以,这些支持 ReLU 的理论是有一些生硬的。 ...

July 7, 2019 · 1 min · jiezi

深度学习RNNGRULSTM

作者:LogM 本文原载于 https://segmentfault.com/u/logm/articles ,不允许转载~ 文章中的数学公式若无法正确显示,请参见:正确显示数学公式的小技巧 1. RNN$$H_t = \phi(W_{xh}X_t + W_{hh}H_{t-1} + b_h)$$ $$O_t = W_{hq}H_t + b_q$$ 其中,$\phi$ 为激活函数。RNN 容易出现"梯度爆炸"和"梯度衰减",应对梯度衰减的方式是使用 GRU 或 LSTM,应对梯度爆炸的方式是"裁剪梯度":$$min(\frac{\theta}{||g||})g$$其中,$g$ 为求得的梯度,限制梯度的 $L_2$ 范数的值不超过 $\theta$。 2. GRU重置门:$$R_t = \sigma(W_{xr}X_t + W_{hr}H_{t-1} + b_r)$$ 更新门:$$Z_t = \sigma(W_{xz}X_t + W_{hz}H_{t-1} + b_z)$$ 候选隐状态:$$\tilde{H_t} = tanh[W_{xh}X_t + W_{hh}(R_t \odot H_{t-1}) + b_h]$$ 隐状态:$$H_t = Z_t \odot H_{t-1} + (1-Z_t) \odot \tilde{H_t}$$ 其中,$\sigma$ 为 sigmoid 函数,$\odot$ 表示 element-wise 乘法。 ...

July 7, 2019 · 1 min · jiezi

深度学习深度学习常用优化方法

作者:LogM 本文原载于 https://segmentfault.com/u/logm/articles ,不允许转载~ 文章中的数学公式若无法正确显示,请参见:正确显示数学公式的小技巧 1. SGD(随机梯度下降)$$g_t = \bigtriangledown_{\theta_{t-1}} f(\theta_{t-1})$$ $$\Delta\theta_t = -\eta*g_t$$ 需要手动选取合适的learning_rate稀疏特征更新问题(不常出现的特征更新慢,如word2vec的embedding矩阵)易被困局部最优2. momentum$$m_t = \mu*m_{t-1}+g_t$$ $$\Delta\theta_t = -\eta*m_t$$ 引入惯量缓解局部最优问题未解决稀疏特征更新问题3. AdaGrad$$\nu_t = \nu_{t-1} + g_t*g_t$$ $$\Delta\theta_t = \frac{g_t}{\sqrt{\nu_t+\epsilon}} * \eta$$ 解决稀疏特征更新问题,不常出现的特征更新快局部最优问题没有解决随着 $\nu_t$ 的累加,学习率不断衰减4. RMSprop$$\nu_t = \mu * \nu_{t-1} + (1-\mu) * g_t*g_t$$ $$\Delta\theta_t = \frac{g_t}{\sqrt{\nu_t+\epsilon}} * \eta$$ 解决稀疏特征更新问题,不常出现的特征更新快局部最优问题没有解决RMSprop 是 AdaGrad 的升级版,区别是 $\nu_t$ 的计算方式:RMSprop 是移动平均,而 AdaGrad 是累加,越加越大。5. Adadelta$$\nu_t = \mu * \nu_{t-1} + (1-\mu) * g_t*g_t$$ ...

July 6, 2019 · 1 min · jiezi

开源背后-面对端侧推理引擎的挑战阿里工程师如何应对

阿里妹导读:MNN(Mobile Neural Network)已于今年5月7日在 Github 上正式开源。淘宝无线开发专家——陈以鎏(离青)在 GMTC 全球大前端技术大会为大家分享了 MNN 开发、开源中的思考与总结,通过淘宝在移动 AI 上的实践经验,你将会了解移动 AI 的发展状况和应用场景,以及通过端侧推理引擎了解移动/ IoT 深度优化策略。开源与背景 人工智能从 2006 年开始,迎来了第三次浪潮。随着 AlphaGo 在 2016 年、 2017 年先后战胜李世石和柯洁,人工智能彻底进入了公众的视野。人工智能大热的背后,是大数据的积累,是深度学习的发展,也是设备算力的提升。与此同时,深度学习的框架也在不断演进 —— 从 Torch、Caffe 到 TensorFlow、PyTorch ,再到更面向移动端的 CoreML、NNAPI、NCNN、MACE 等。淘宝的深度学习推理引擎 MNN 也于 2019 年 5 月宣布开源。 MNN 是一个轻量级的深度学习端侧推理引擎,核心解决深度神经网络模型在端侧推理运行问题,涵盖深度神经网络模型的优化、转换和推理。目前,MNN已经在手淘、手猫、优酷、聚划算、UC、飞猪、千牛等 20 多个 App 中使用,覆盖直播、短视频、搜索推荐、商品图像搜索、互动营销、权益发放、安全风控等场景,每天稳定运行上亿次。此外,菜鸟自提柜等 IoT 设备中也有应用。在 2018 年双十一购物节中,MNN 在天猫晚会笑脸红包、扫一扫、明星猜拳大战等场景中使用。 开源地址:https://developer.aliyun.com/... MNN 项目从 2017 年开始启动,在经历一年多的开发迭代并通过了淘宝双十一的考验后,于 2018 年底启动开源计划,在历时小半年的开源改造后,今年 5 月份正式在 Github 开源。 开源首先还是因为经历过双十一之后,我们觉得自己做好了准备,开源有助于我们鞭策自己,把 MNN 做的更好;另一方面,业界的开源方案,不论是 TensorFlow Lite 、 NCNN 还是 Mace ,都给了我们很好的输入和借鉴,我们也希望借着开源,将我们的思考和创新回馈社区。 ...

July 3, 2019 · 3 min · jiezi

自然语言处理手撕-FastText-源码02基于字母的-Ngram-实现FastTexts-subwords

作者:LogM 本文原载于 https://segmentfault.com/u/logm/articles ,不允许转载~ 1. 源码来源FastText 源码:https://github.com/facebookresearch/fastText 本文对应的源码版本:Commits on Jun 27 2019, 979d8a9ac99c731d653843890c2364ade0f7d9d3 FastText 论文: [1] P. Bojanowski, E. Grave, A. Joulin, T. Mikolov, Enriching Word Vectors with Subword Information [2] A. Joulin, E. Grave, P. Bojanowski, T. Mikolov, Bag of Tricks for Efficient Text Classification 2. 概述之前的博客介绍了"分类器的预测"的源码,里面有一个重点没有详细展开,就是"基于字母的 Ngram 是怎么实现的"。这块论文里面关于"字母Ngram的生成"讲的比较清楚,但是对于"字母Ngram"如何加入到模型中,讲的不太清楚,所以就求助于源码,源码里面把这块叫做 Subwords。 看懂了源码其实会发现 Subwords 加入到模型很简单,就是把它和"词语"一样对待,一起求和取平均。 另外,我自己再看源码的过程中还有个收获,就是关于"中文词怎么算subwords",之前我一直觉得 Subwords 对中文无效,看了源码才知道是有影响的。 最后是词向量中怎么把 Subwords 加到模型。这部分我估计大家也不怎么关心,所以我就相当于写给我自己看的,解答自己看论文的疑惑。以skipgram为例,输入的 vector 和所要预测的 vector 都是单个词语与subwords相加求和的结果。 3. 怎么计算 Subwords之前的博客有提到,Dictionary::getLine 这个函数的作用是从输入文件中读取一行,并将所有的Id(包括词语的Id,SubWords的Id,WordNgram的Id)存入到数组 words 中。 ...

June 30, 2019 · 5 min · jiezi

自然语言处理手撕-FastText-源码01分类器的预测过程

作者:LogM 本文原载于 https://segmentfault.com/u/logm/articles ,不允许转载~ 1. 源码来源FastText 源码:https://github.com/facebookre... 本文对应的源码版本:Commits on Jun 27 2019, 979d8a9ac99c731d653843890c2364ade0f7d9d3 FastText 论文: [1] P. Bojanowski, E. Grave, A. Joulin, T. Mikolov, Enriching Word Vectors with Subword Information [2] A. Joulin, E. Grave, P. Bojanowski, T. Mikolov, Bag of Tricks for Efficient Text Classification 2. 概述FastText 的论文写的比较简单,有些细节不明白,网上也查不到,所幸直接撕源码。 FastText 的"分类器"功能是用的最多的,所以先从"分类器的predict"开始挖。 3. 开撕先看程序入口的 main 函数,ok,是调用了 predict 函数。 // 文件:src/main.cc// 行数:403int main(int argc, char** argv) { std::vector<std::string> args(argv, argv + argc); if (args.size() < 2) { printUsage(); exit(EXIT_FAILURE); } std::string command(args[1]); if (command == "skipgram" || command == "cbow" || command == "supervised") { train(args); } else if (command == "test" || command == "test-label") { test(args); } else if (command == "quantize") { quantize(args); } else if (command == "print-word-vectors") { printWordVectors(args); } else if (command == "print-sentence-vectors") { printSentenceVectors(args); } else if (command == "print-ngrams") { printNgrams(args); } else if (command == "nn") { nn(args); } else if (command == "analogies") { analogies(args); } else if (command == "predict" || command == "predict-prob") { predict(args); // 这句是我们想要的 } else if (command == "dump") { dump(args); } else { printUsage(); exit(EXIT_FAILURE); } return 0;}再看 predict 函数,预处理的代码不用管,直接看 predict 的那行,调用了 FastText::predictLine。这里注意下,这是个 while 循环,所以FastText::predictLine 这个函数每次只处理一行。 ...

June 30, 2019 · 3 min · jiezi

上海居民快被垃圾分类逼疯这个深度学习技术帮你做到垃圾自动分类

让垃圾自动分类 近期垃圾分类成为了一个热门话题,原来直接一次性扔掉的垃圾,现在都需要分门别类进行投放。从今年7月1日起,新的《上海市生活垃圾管理条例》正式开始施行,号称史上最严的垃圾分类就要来了。我们以后在扔垃圾前都要先将垃圾仔细分成可回收物、有害垃圾、湿垃圾和干垃圾四个类别,如果分错还会被罚款。 垃圾分类可以更好地保护我们的环境卫生,为了让大家能够正确对垃圾进行分类,官方发布了垃圾分类指南,列举了每种类别对应的常见垃圾,大家可以对照着进行分类投放。此外,脑洞大开的网友们也另辟蹊径,提供了各种有意思的分类思路。 在日常生活中,每个类别的垃圾往往包含了各式各样的内容,人们在分类投放的时候难免会出现偏差,这个时候如果有一个分类神器对垃圾拍个照就能告诉我们是什么类别就好了。 当前人工智能飞速发展,我们能否利用AI技术来对垃圾自动分类,实现上面提到的设想呢?为了回答这个问题,在今天的文章中,我们将从人工智能的角度出发,尝试利用深度学习技术来构建一个垃圾自动分类器,同时也会进一步介绍AI垃圾分类遇到的挑战和一些思考。 “垃圾”图像数据准备 为了实现一个理想的垃圾自动分类器,需要有一个已经分好类别的“垃圾”图像数据集作为训练的基础。然而当前并没有这样一个可以直接使用的数据集,所以我们首先自己动手收集海量的“垃圾”图像并为每张图像标注上相应的类别。 数据集的收集一直是一件耗时耗力的工作,为了快速便捷地完成“垃圾”图像数据集的收集,我们依据官方发布的垃圾分类指南上每一类所包含的垃圾名称,通过在百度图片上爬取名称对应的图像来实现。官方发布的垃圾分类指南如下图所示。 在实际的应用场景中,待分类的样本往往是不可控的,所以一般会增加“其他”这个类别用来收留各种异常样本。在垃圾分类中,除可回收物、有害垃圾和湿垃圾外都属于干垃圾,所以干垃圾已经扮演了“其他”的角色。我们的“垃圾”图像数据集最终分为可回收垃圾、有害垃圾、湿垃圾和干垃圾四个类别。数据集的部分图像如下图所示。 垃圾自动分类器 垃圾自动分类本质上是一个图像分类问题,当前基于深度卷积神经网络的图像分类算法发展很快,各种方法层出不穷。下面我们先回顾这些分类网络的演进思路,再进一步将分类算法应用于垃圾分类,介绍构建一个垃圾自动分类器的流程和细节。 卷积神经网络的开山之作LeNet于1998年被提出,并成功应用于手写体识别。LeNet和现在的网络结构相比虽然简单(如上图所示),但是卷积层、池化层和全连接层这些基本模块都已经具备。 随着ReLU和dropout的提出,以及GPU和大规模数据集的出现,卷积神经网络在2012年迎来了历史突破,AlexNet的出现让卷积神经网络开始逐渐成为计算机视觉任务的标配。在AlexNet的基础上,以增加网络深度为思路,出现了VGGNet;以增强卷积模块为思路,出现了基于Inception的一系列网络。 随着后来居上的ResNet的提出,层数极深的网络成为了可能。通过引入残差模块,缓解了深度网络训练过程中的梯度消失问题,让网络的深度不断加大,网络性能也得到了大幅提升。之后的DenseNet更是通过对特征图的稠密连接,加强了特征的传递,继续提升分类效果。当前ResNet及其变种形式已经被广泛地应用于图像分类任务,同时也成为了在解决目标检测和图像分割等其他计算机视觉问题时常用的主干网络结构。 在本文中,我们使用50层的ResNet来构建垃圾自动分类器。具体我们采用在ImageNet数据集上预训练的ResNet50模型参数作为初始化,利用上一节中收集的“垃圾”图像数据集对其进行微调。 其中我们将上述ResNet50的最后一层输出从1000(ImageNet数据集的分类数量)修改为4(垃圾分类数量),同时在训练过程中冻结了部分卷积层参数的更新。此外还进一步利用水平翻转、随机裁剪和色彩抖动等方式对训练的“垃圾”图像进行数据增强。在完成垃圾自动分类器的训练后,我们对一些垃圾进行了自动分类的测试,准确率达到近90%。虽然对复杂的情况还是存在一定的误判,但大部分常见的垃圾都得到了正确的区分,具有较强的实用性。 从单个垃圾分类到一群垃圾分类 上一节中我们介绍了垃圾自动分类器的构建,但是这样的垃圾分类器的输入都是单个垃圾图像。在实际的垃圾分类投放过程中,对单个的垃圾进行一一拍照分类显得过于繁琐和缓慢。那能不能对一群垃圾直接拍照后进行批量分类呢?要实现对一群垃圾的批量分类,其实就是要构建一个垃圾的目标检测器。输入一张含有多个垃圾的图像,让模型输出图像上每种垃圾对应的类别。 在深度学习出现之前,可变形部件模型(DPM)一直是流行的目标检测方法。深度学习出现后,以R-CNN、Fast R-CNN、Faster R-CNN为代表的两阶段算法和以YOLOv1-3、SSD、RetinaNet为代表的单阶段算法成为主流。前者是先由算法生成一系列待检测目标的候选框,再通过卷积神经网络进行候选框的分类;后者则不用产生候选框,直接将目标边框定位的问题转化为回归问题处理。 和垃圾分类器一样,一个理想的垃圾检测器,需要大量的“垃圾”标注数据来支撑。但是与分类数据集相比,检测数据集除了标注类别外还要标注图位置坐标,这样的标注工作更为艰巨。在完成垃圾检测的图像数据集后,就可以利用当前主流的深度学习检测算法来实现批量垃圾的分类。 写在最后 垃圾分类最近成为了大家生活中经常讨论的话题,这篇文章分享了如何利用深度学习技术来构建一个垃圾自动分类器,也进一步介绍了从单个垃圾分类到批量垃圾分类的思路和挑战。 在实际的垃圾分类中,由于垃圾多种多样,同一类别的垃圾可能差异很大,而不同类别的垃圾可能差异很小,在复杂情况下分类器效果可能会不尽如人意,后续可以考虑加入垃圾之间的高层次语义关系信息,进一步提升分类器的性能。最后希望大家都能做到正确的垃圾分类投放,毕竟生活不易,还是不要被罚款。 一些资料 [1] Deep Residual Learning for Image Recognition [2] ImageNet Classification with Deep Convolutional Neural Networks [3] Very Deep Convolutional Networks for Large-Scale Image Recognition

June 28, 2019 · 1 min · jiezi

一文带你看遍深度学习发展的成就历程二

在这篇文章中,作者将描述17年在机器学习领域中发生了什么有趣的重大发展,主要是深度学习领域。在17年中发生了很多事情,在作者停下来进行回顾的时候,他发现了这些发展的成就是非常壮观的,下面让我们来在作者的带领下认识一下17年在深度学习中发展的领域的状况,这篇文章很可能会影响我们在数据科学领域未来的发展。 3.10 CycleGAN为了应用Pix2Pix,你需要一个包含来自不同领域的相应图片的数据集。例如在使用卡片的情况下,组装这样的数据集不是问题。但是,如果你想做一些更复杂的事情,如“变形”对象或样式化,那么原则上是找不到成对的对象。 因此,Pix2Pix的作者决定发展他们的想法并提出了CycleGAN,用于在不同的图像区域之间进行传输 - “不配对的图像到图像翻译”。 这个想法是教两对发生器鉴别器将图像从一个域转移到另一个域并返回,而我们需要一个循环一致性 - 在对生成器进行连续应用之后,我们应该得到一个类似于原始L1损失相似的图像。需要循环损失以确保生成器不仅仅只是一开始将一个域的图片转移到另一个域的图片上,并且还要防止与原始图像完全无关。 这种方法可以让你将马匹的映射成为 - >斑马。 但是这种转换是不稳定的,通常会产生不成功的结果: 您可以在此处找到源代码。 3.11 肿瘤学中分子的发展机器学习现在正在进入医学领域。除了识别超声波,核磁共振(MRI)和诊断疾病外,它还可用来寻找新的抗癌药物。 简而言之,在对抗性自动编码器(AAE)的帮助下,你可以学习分子的潜在表示,然后使用它来搜索新的分子。结果发现了69个分子,其中一半用于对抗癌症,其他的分子则具有很大的潜力。 3.12 对抗性攻击积极探索与对抗性攻击的主题。什么是对抗攻击?例如,在ImageNet上训练的标准网络在向分类图像添加特殊噪声时是完全不稳定。在下面的例子中,我们看到人眼的噪声图像实际上没有变化,但模型会变得非常疯狂并且预测了一个完全不同的类。 例如,通过快速梯度符号方法(FGSM)实现稳定性:可以访问模型的参数,你可以朝着所需要的类进行一个或多个梯度步骤并更改原始图像。 [](https://link.zhihu.com/?targe...:鼓励参与者创建通用的攻击/防御方法,这些攻击/防御方法最终都是相互对抗以确定什么最佳的攻击/防御方法。 我们为什么要调查这些攻击?首先,如果我们想要保护我们的产品,我们可以在验证码中添加噪音,以防止垃圾邮件发送者自动识别它。其次,算法越来越多地涉及我们的生活比如:人脸识别系统和自动驾驶汽车。在这种情况下,攻击者可以使用算法的缺点。 下面是一个例子,说明特殊眼镜何时会让你欺骗面部识别系统,并“将自己当作另一个人。”因此,我们需要在训练模型时考虑到可能会存在的攻击。 这种带符号的标识也不正确的识别它们。 • 比赛组织者的一篇文章。 •已经编写了用于攻击的库:cleverhans 和 foolbox. 4.强化学习强化学习(RL)或强化的学习也是机器学习中最有趣和积极发展的方法之一。 该方法的本质是在一个通过在获得回报的环境中进行学习的成功行为 - 就像人们在整个人生中的学习一样。 RL主要用于游戏,机器人和系统管理(例如流量)中得到了积极的应用。 当然,每个人都听说过AlphaGo在围棋这种人类的游戏中胜过最优秀的专业人士。而研究人员正是使用RL进行训练:机器人通过自我对抗进行改进自我策略。 4.1 加化训练与不受控制的辅助任务在过去几年中,DeepMind已经学会了使用DQN来玩街机游戏并且比人类玩的更好。目前,人们正在教算法来玩像Doom毁灭战士这样的更复杂的游戏。 大部分注意力都集中在学习加速上,因为代理与环境交互的经验需要在现代的GPU上进行数小时的训练。 Deepmind在他的博客中报到,引入了额外的损失(辅助任务),例如预测帧变化(像素控制),以便代理更好地理解动作的后果,大大加快了学习速度。 学习成果: 4.2 学习机器人在OpenAI中,他们一直在积极研究人类在虚拟环境中对代理人的训练,这种实验比在现实生活更安全。 在其中一项研究中,团队表明一次性学习是可能的:一个人在VR中展示如何执行某项任务,这一次演示足以让算法学习它然后在真实条件下重现它。 如果和人相处这么容易就好了。:) 4.3 关于人类偏好的学习以下是OpenAI和DeepMind在同一主题上进行工作。最重要的是,一个代理有一个任务,该算法为人提供两种可能的解决方案,并指出哪一种更好。这个过程是迭代重复的,并且从学习如何解决问题的人那里得到900位反馈(二进制标记)的算法 像往常一样,人类必须小心并仔细思考他正在教机器做什么。例如,评估器决定算法想要获取的对象,但事实上,他只是模拟了这个动作。 4.4 复杂环境中的运动DeepMind 还有另一项研究。要教会机器人复杂的行为(唱、跳、...、打篮球等),甚至是与人类相似的行为,你必须在损失函数的选择上投入大量的精力,这将鼓励所期望的行为。然而,更可取的是,算法通过简单的奖励来学习复杂的行为本身。 研究人员设法实现了这一目标:他们教导代理人(身体模拟者)通过构建具有障碍的复杂环境以及对运动进展的简单奖励来执行复杂的行动。 你可以看一下这个有点搞笑的视频结果,当然打开声音的效果可能有点吓人。 ...

June 25, 2019 · 1 min · jiezi

一文带你看遍深度学习发展的成就历程一

在这篇文章中,作者将描述17年在机器学习领域中发生了什么有趣的重大发展,主要是深度学习领域。在17年中发生了很多事情,在作者停下来进行回顾的时候,他发现了这些发展的成就是非常壮观的,下面让我们来在作者的带领下认识一下17年在深度学习中发展的领域的状况,这篇文章很可能会影响我们在数据科学领域未来的发展。 1.文字1.1 谷歌神经机器翻译 2016年左右,谷歌宣布推出谷歌翻译新模式。谷歌公司详细描述翻译的网络架构 - 回归神经网络(RNN)。 而最后的主要结果是:缩小了机器与人类在翻译准确性方面上的差距,达到了55-85%(人们按照六分制进行评分)。如果Google没有拥有的庞大数据集,那么很难重新呈现这个模型的高效果性。 1.2 人机交流是否会有市场? 你可能在过去听到了一个古怪的新闻,新闻的内容是Facebook关闭了它的聊天机器人,原因是这个聊天机器人已经失去了控制并创造了自己的语言。这个聊天机器人是由FB公司创建的。它的主要目的是与另一个代理人进行文本交流并达成共识:如何将一个物品(书籍,帽子等)分成两部分。每个代理人在交流中都有自己的目标,而对方则不知道对方的目标。在没有达成协议的情况下不可能离开这场交流。 在训练这方面,他们收集了人类交流谈话的数据集,并培训了一个受监督的神经网络。然后,他们使用了一个强化学习训练的代理人并训练它与自己交谈,并设定了一个限制:使用的语言必须跟人类的语言相似。 机器人已经学会了一种真正的交流策略,比如在交易的某些方面表现出虚假的兴趣,但是后来放弃了这部分兴趣,然后从真正 的目标中获益。这是第一次尝试创建出这样一个交互式的机器人,而且是非常成功的。 当然,有关于说机器人从零开始发明了一种语言的消息无疑是有夸大的成分在里面的。当机器人训练时(与同一个代理人进行谈判时),他们取消了了文本必须和人类语言有相似性的限制,算法修改了交互语言。没什么不寻常的。 在过去的一年中,神经网络已经正在被积极的应用并得到了发展,不断的被开发并用于许多任务和应用程序中。但RNN的体系结构变得更加复杂,但在某些领域,通过简单的前馈网络(DSSM)也取得了类似的结果 。例如,Google的邮件功能Smart Reply与之前的LSTM达到了相同的质量。此外,Yandex还推出了基于此类网络的新搜索引擎。 2.声音2.1 WaveNet:原始音频的生成模型DeepMind的员工在他们的文章中报道了如何生成音频。简而言之,研究人员基于以前的图像生成方法(PixelRNN和PixelCNN)制作了一个自回归全卷积波网模型。 网络经过端到端的训练:输入文本,输出音频。研究得到了很好的结果,与人类相比,研究的结果差异减少了50%,取得了较好的效果。 网络的主要缺点是生产率低,因为自动回归是按顺序产生声音的,创建一秒钟的音频需要大约1-2分钟的时间。 看看......抱歉,听听下面这个例子。 如果你删除网络模型对输入文本的依赖性并且只依赖于对先前生成并保留下来的音素,那么网络将生成一段毫无意义的类似于人类语言的音素。 听听下面这段生成声音的音频。 同样的模式不仅仅可以应用于语言,还可以应用于例如创建音乐。想象一下由模型生成的音乐,这是使用钢琴游戏的数据集所进行训练的(同样不依赖于输入数据)。 2.2 读唇术读唇是另一项深度学习的成就和对人类挑战的胜利。 谷歌Deepmind与牛津大学合作,在文章《 Lip Reading Sentences in the Wild 》报告了他们的模型是如何获取数据进行训练并超越BBC频道中的专业的唇语读者的。 数据集中有100,000个带有音频和视频的句子。型号:音频LSTM,视频CNN + LSTM。这两个状态向量被输入到最终的LSTM,并最终有LSTM生成结果(字符)。 在训练期间使用了不同类型的输入数据:音频,视频和音频+视频。换句话说,它是一个“全方位”的模型。 2.3 合成奥巴马的演讲视频:视频、音频、唇语的同步 华盛顿大学在创造美国前总统奥巴马的嘴唇运动方面做了大量工作。因为他的在线演讲视频数量巨大(17小时的高清视频),所以华盛顿大学的人选的选择就落在他身上。 由于他们有太多的工作,所以他们不可能每天都去跟神将网络相处。因此,他们制作了一些拐杖(或者说技巧,如果你喜欢这个词语的话)来改进纹理和时间。 你可以看到结果非常令人惊讶。我相信很快的,你就不会相信在网上看到的有关总统的视频了。 3.计算机视觉3.1 OCR:谷歌地图和街景在他们的帖子和文章中,谷歌Brain团队报告了他们如何在其地图中引入一种新的OCR(光学字符识别)引擎,通过该引擎可以识别街道标志和商店标志。 在技术开发过程中,公司编制了一个新的FSNS(法语街道名称标识),其中包含许多复杂的案例。 为了识别每个标志,该网络使用了每个标志多达四张照片。使用CNN提取特征,在空间注意力的帮助下进行缩放(考虑像素坐标),并将结果馈送到LSTM。 同样的方法适用于在招牌上识别商店名称的任务(可能存在大量“噪音”数据,并且网络本身必须“聚焦”在正确的位置)。该算法应用于800亿张照片。 3.2 视觉推理有一种称为视觉推理的任务,要求神经网络使用一张照片来回答一个问题。例如:“图中是否有与黄色金属圆筒相同尺寸的橡胶?”这个问题真的很重要,直到最近,这个问题才得以解决,但是这个问题的准确率只有68.5%。 但是,Deepmind团队在这个问题上实现了突破:在CLEVR数据集上,他们达到了95.5%的超人精度。 网络架构非常有趣: ...

June 25, 2019 · 1 min · jiezi

用深度学习魔法为你的照片转换风格附源码

——深度学习在艺术方面的进展作者:George Seif翻译:疯狂的技术宅原文:https://towardsdatascience.co...未经允许严禁转载图像背景中的风格转移是指将一个图像的“风格”转移到另一个图像的过程,同时保持第二图像中的“内容”。 例如,最上边的照片是“内容”图像。我们要将中间照片中的“风格”(“风格”图像)应用于内容图像。也就是说我们希望把中间的图像中大都市的夜晚氛围反映在最终图像上,得到的结果是最下边的照片! 这项技术源自的原始研究论文:https://arxiv.org/pdf/1703.07... Adobe 的一项最具开创性的研究就来自于此。他们称之为深度照片风格转移(DPST)。 如何转换照片的风格为了正确执行从一张照片到另一张照片的样式转换,Adobe 团队制定了他们的 DPST 的目标:“将参考的风格转移到输入的图片上,同时保持结果的真实感” 这里的关键部分是保持输出的“真实感”属性。对于上面的内容照片,我们不希望任何建筑物发生任何变化。只是希望它看起来像是在夜间拍摄的同一位置的照片。 在该研究发表之前,也出现了许多风格转移算法,但是这些算法扭曲了原始图像的内容。在当时的 Neural Style Transfer 技术的输出结果中,常见的问题就是直线变成了波浪线并且改变了物体的形状。 这是完全可以接受的。许多算法都是为艺术风格转移而设计的,所以往往会存在一些失真! 失真的风格转移图像 (来源:https://github.com/yusuketomo...) 但是当前的目标是创建依然逼真的图像 —— 就好像它们是由真实世界的相机拍摄的一样。 作者为实现这一点主要做了两件事情:(1)损失函数中的照片写实正则化项(2)内容图像的语义分割,用于指导。 照片写实正则化设想一下应该怎样在图像中直观地保持照片的写实。我们希望原始图像的线条和形状保持不变。颜色和灯光可能会改变,但是一个人应该看起来还像一个人,树还是树,狗仍然像狗等。 基于这种直观的想法,作者实现的正则化约束迫使像素从输入到输出的转换在颜色空间中是局部仿射的。根据定义,仿射变换在将输入映射到输出时必须保持点、直线和平面的形状不变。 有了这个限制,直线永远不会产生波动,我们的输出中不会出现任何奇怪的形状变化! 分段指导除了保证图像不失真外,我们还希望能够确保样式图像中各种“事物”的样式是被正确转移的。 想象一下,如果你的风格图像显示出美丽的橙色日落,就像下面这张照片一样: 来源:https://pixabay.com/illustrat... 图像的大部分是红橙色的,如果将这个风格转移到城市的照片上,那么所有的建筑都会变红!这可不是我们想要的 —— 更真实的转移应该是使大多数建筑物非常暗(接近黑色),只有天空才会有日落和水的颜色。 深度图像风格转换算法使用应用于内容图像的语义分割的结果来引导风格转移。当算法能够准确地知道哪些像素属于前景和背景时,可以更真实地转换风格。天空的像素将始终转移到天空像素,背景像素会转移到背景像素等等。 转换风格的代码你可以从GitHub下载 Photo Realistic Style Transfer 的存储库: git clone https://github.com/GeorgeSeif/DeepPhotoStyle_pytorch.git它运行所需的只是 Pytorch 的最新版本。下载完成后,进入文件夹并使用下载脚本下载语义分段模型: cd DeepPhotoStyle_pytorchsh download_seg_model.sh现在可以运行代码了! 下载样式图像和内容图像 —— 你可以选择任何图像!根据我的经验,城市和风景往往效果最佳。最后像这样运行代码: python main.py --style_image path_style_image --content_image path_content_image该算法将迭代地改进样式传递结果,因此你等待得实践越久效果就越好!默认情况下它被设置为迭代 3000 次,但如果你觉得更多的迭代次数能够改善结果,可以增加该数字。 试着亲自去运行代码,这非常有趣! 欢迎扫码关注公众号:硬核智能

June 18, 2019 · 1 min · jiezi

K近邻算法你掌握了吗来测试一下就知道了

简介如果你要问我两个机器学习中最直观明了且通俗易懂的算法——那必然就是K近邻算法和基于树的算法了。这两个算法都易于理解,也很容易解释,并且能够很好地去向人们展示。最近,我们就针对这两种算法,整理了一些测试题。 如果你是机器学习的新手,也要在理解这两种算法的基础上进行测试。它们虽然简单,但是却十分强大且被广泛运用在工业领域。这些技能测试能够帮助你测试你在K近邻算法方面的技术能力。因为它们是为测试你在K近邻算法上的基础知识与应用能力而量身定制的。 有超过650人注册参加考试。如果你错过了这个测试也没关系,下面就是测试的问题与答案。 技能测试试题与答案解析1)【True or False】KNN算法在测试时花费更多计算,而不是训练时。 A) TRUE B)FALSE 答案:A 解析:算法的训练阶段仅包括存储训练样本的特征向量和类标签。 在测试阶段,通过在最接近该查询点的k个训练样本中分配最频繁的标签来对测试点进行分类——因此这方面计算更多。 2)下图中,若使用K近邻算法,最佳K值应在哪里取得? A) 3 B)10 C) 20 D)50 答案:B 解析:当K为10时,验证的错误率最低,所以K值应取10. 3)下图哪种度量距离不能用于KNN算法? A)Manhattan B)Minkowski C)Tanimoto D) Jaccard E)Mahalanobis F) 所有都可以 答案:F 解析:所有的度量距离都可以用于KNN。 4)关于KNN哪种观点是对的? A)它可以用于分类 B)它可以用于回归 C)它可以用于分类和回归 答案:C 解析:我们也可以使用KNN来解决回归问题。在这种情况下,预测可以基于k个最相似实例的均值或中值。 5)下面关于KNN算法哪种说法是正确的? 1.如果所有的数据是同样的大小,KNN算法表现比较好 2.KNN算法适用于小数据输入,而大量数据输入时会遇到困难。 3.KNN算法并没有对正在处理的问题的功能形式进行假设。 A)1和2 B)1和3 C)只有1 D)以上所有 答案:D 解析:以上所有的说法都是正确的 6)以下哪种机器学习算法可用于输入分类和连续变量的缺失值? A )KNN B)线性回归 C)逻辑回归 答案:A 解析:k-NN算法可用于估算分类和连续变量的缺失值。 7)关于曼哈顿距离哪种观点是对的? A)它可以用于连续变量 B)它可以用于分类变量 C)两者都可以 D)两者都不可以 答案:A 解析:曼哈顿距离用于计算实值特征之间的距离。 8)对于k-NN中的分类变量,我们使用以下哪种距离测量? 1.汉明距离 ...

June 18, 2019 · 2 min · jiezi

在-Google-Colab-中快速实践深度学习

本文很多是对于 Colab 官方 Welcome 系列的总结,更多人工智能与深度学习相关知识参考人工智能与深度学习实战 https://github.com/wx-chevalier/AIDL-Series 系列文章。 ColaboratoryColaboratory 是一个免费的 Jupyter 笔记本环境,不需要进行任何设置就可以使用,并且完全在云端运行。借助 Colaboratory,我们可以在浏览器中编写和执行代码、保存和共享分析结果,以及利用强大的计算资源,包含 GPU 与 TPU 来运行我们的实验代码。 Colab 能够方便地与 Google Driver 与 Github 链接,我们可以使用 Open in Colab 插件快速打开 Github 上的 Notebook,或者使用类似于 https://colab.research.google... 这样的链接打开。如果需要将 Notebook 保存回 Github,直接使用 File→Save a copy to GitHub 即可。譬如笔者所有与 Colab 相关的代码归置在了 AIDL-Workbench/colab。 依赖与运行时依赖安装Colab 提供了便捷的依赖安装功能,允许使用 pip 或者 apt-get 命令进行安装: # Importing a library that is not in Colaboratory!pip install -q matplotlib-venn!apt-get -qq install -y libfluidsynth1# Upgrading TensorFlow# To determine which version you're using:!pip show tensorflow# For the current version:!pip install --upgrade tensorflow# For a specific version:!pip install tensorflow==1.2# For the latest nightly build:!pip install tf-nightly# Install Pytorchfrom os import pathfrom wheel.pep425tags import get_abbr_impl, get_impl_ver, get_abi_tagplatform = '{}{}-{}'.format(get_abbr_impl(), get_impl_ver(), get_abi_tag())accelerator = 'cu80' if path.exists('/opt/bin/nvidia-smi') else 'cpu'!pip install -q http://download.pytorch.org/whl/{accelerator}/torch-0.4.0-{platform}-linux_x86_64.whl torchvision# Install 7zip reader libarchive# https://pypi.python.org/pypi/libarchive!apt-get -qq install -y libarchive-dev && pip install -q -U libarchiveimport libarchive# Install GraphViz & PyDot# https://pypi.python.org/pypi/pydot!apt-get -qq install -y graphviz && pip install -q pydotimport pydot# Install cartopy!apt-get -qq install python-cartopy python3-cartopyimport cartopy在 Colab 中还可以设置环境变量: ...

June 18, 2019 · 4 min · jiezi

深度学习之卷积神经网络经典模型

LeNet-5模型在CNN的应用中,文字识别系统所用的LeNet-5模型是非常经典的模型。LeNet-5模型是1998年,Yann LeCun教授提出的,它是第一个成功大规模应用在手写数字识别问题的卷积神经网络,在MNIST数据集中的正确率可以高达99.2%。 下面详细介绍一下LeNet-5模型工作的原理。 LeNet-5模型一共有7层,每层包含众多参数,也就是卷积神经网络中的参数。虽然层数只有7层,这在如今庞大的神经网络中可是说是非常少的了,但是包含了卷积层,池化层,全连接层,可谓麻雀虽小五脏俱全了。为了方便,我们把卷积层称为C层,下采样层叫做下采样层。 首先,输入层输入原始图像,原始图像被处理成32×32个像素点的值。然后,后面的隐层计在卷积和子抽样之间交替进行。C1层是卷积层,包含了六个特征图。每个映射也就是28x28个神经元。卷积核可以是5x5的十字形,这28×28个神经元共享卷积核权值参数,通过卷积运算,原始信号特征增强,同时也降低了噪声,当卷积核不同时,提取到图像中的特征不同;C2层是一个池化层,池化层的功能在上文已经介绍过了,它将局部像素值平均化来实现子抽样。 池化层包含了六个特征映射,每个映射的像素值为14x14,这样的池化层非常重要,可以在一定程度上保证网络的特征被提取,同时运算量也大大降低,减少了网络结构过拟合的风险。因为卷积层与池化层是交替出现的,所以隐藏层的第三层又是一个卷积层,第二个卷积层由16个特征映射构成,每个特征映射用于加权和计算的卷积核为10x10的。第四个隐藏层,也就是第二个池化层同样包含16个特征映射,每个特征映射中所用的卷积核是5x5的。第五个隐藏层是用5x5的卷积核进行运算,包含了120个神经元,也是这个网络中卷积运算的最后一层。 之后的第六层便是全连接层,包含了84个特征图。全连接层中对输入进行点积之后加入偏置,然后经过一个激活函数传输给输出层的神经元。最后一层,也就是第七层,为了得到输出向量,设置了十个神经元来进行分类,相当于输出一个包含十个元素的一维数组,向量中的十个元素即0到9。 AlexNet模型AlexNet简介2012年Imagenet图像识别大赛中,Alext提出的alexnet网络模型一鸣惊人,引爆了神经网络的应用热潮,并且赢得了2012届图像识别大赛的冠军,这也使得卷积神经网络真正意义上成为图像处理上的核心算法。上文介绍的LeNet-5出现在上个世纪,虽然是经典,但是迫于种种复杂的现实场景限制,只能在一些领域应用。不过,随着SVM等手工设计的特征的飞速发展,LeNet-5并没有形成很大的应用状况。随着ReLU与dropout的提出,以及GPU带来算力突破和互联网时代大数据的爆发,卷积神经网络带来历史的突破,AlexNet的提出让深度学习走上人工智能的最前端。 图像预处理AlexNet的训练数据采用ImageNet的子集中的ILSVRC2010数据集,包含了1000类,共1.2百万的训练图像,50000张验证集,150000张测试集。在进行网络训练之前我们要对数据集图片进行预处理。首先我们要将不同分辨率的图片全部变成256x256规格的图像,变换方法是将图片的短边缩放到 256像素值,然后截取长边的中间位置的256个像素值,得到256x256大小的图像。除了对图片大小进行预处理,还需要对图片减均值,一般图像均是由RGB三原色构成,均值按RGB三分量分别求得,由此可以更加突出图片的特征,更方便后面的计算。 此外,对了保证训练的效果,我们仍需对训练数据进行更为严苛的处理。在256x256大小的图像中,截取227x227大小的图像,在此之后对图片取镜像,这样就使得原始数据增加了(256-224)x(256-224)x2= 2048倍。最后对RGB空间做PCA,然后对主成分做(0,0.1)的高斯扰动,结果使错误率下降1%。对测试数据而言,抽取以图像4个角落的大小为224224的图像,中心的224224大小的图像以及它们的镜像翻转图像,这样便可以获得10张图像,我们便可以利用softmax进行预测,对所有预测取平均作为最终的分类结果。 ReLU激活函数之前我们提到常用的非线性的激活函数是sigmoid,它能够把输入的连续实值全部确定在0和1之间。但是这带来一个问题,当一个负数的绝对值很大时,那么输出就是0;如果是绝对值非常大的正数,输出就是1。这就会出现饱和的现象,饱和现象中神经元的梯度会变得特别小,这样必然会使得网络的学习更加困难。此外,sigmoid的output的值并不是0为均值,因为这会导致上一层输出的非0均值信号会直接输入到后一层的神经元上。所以AlexNet模型提出了ReLU函数,公式:f(x)=max(0,x)f(x)=max(0,x)。 用ReLU代替了Sigmoid,发现使用 ReLU 得到的SGD的收敛速度会比 sigmoid快很多,这成了AlexNet模型的优势之一。 DropoutAlexNet模型提出了一个有效的模型组合方式,相比于单模型,只需要多花费一倍的时间,这种方式就做Dropout。在整个神经网络中,随机选取一半的神经元将它们的输出变成0。这种方式使得网络关闭了部分神经元,减少了过拟合现象。同时训练的迭代次数也得以增加。当时一个GTX580 GPU只有3GB内存,这使得大规模的运算成为不可能。但是,随着硬件水平的发展,当时的GPU已经可以实现并行计算了,并行计算之后两块GPU可以互相通信传输数据,这样的方式充分利用了GPU资源,所以模型设计利用两个GPU并行运算,大大提高了运算效率。 模型分析 AlexNet模型共有8层结构,其中前5层为卷积层,其中前两个卷积层和第五个卷积层有池化层,其他卷积层没有。后面3层为全连接层,神经元约有六十五万个,所需要训练的参数约六千万个。 图片预处理过后,进过第一个卷积层C1之后,原始的图像也就变成了55x55的像素大小,此时一共有96个通道。模型分为上下两块是为了方便GPU运算,48作为通道数目更加适合GPU的并行运算。上图的模型里把48层直接变成了一个面,这使得模型看上去更像一个立方体,大小为55x55x48。在后面的第二个卷积层C2中,卷积核的尺寸为5x5x48,由此再次进行卷积运算。在C1,C2卷积层的卷积运算之后,都会有一个池化层,使得提取特征之后的特征图像素值大大减小,方便了运算,也使得特征更加明显。而第三层的卷积层C3又是更加特殊了。第三层卷积层做了通道的合并,将之前两个通道的数据再次合并起来,这是一种串接操作。第三层后,由于串接,通道数变成256。全卷积的卷积核尺寸也就变成了13×13×25613×13×256。一个有4096个这样尺寸的卷积核分别对输入图像做4096次的全卷积操作,最后的结果就是一个列向量,一共有4096个数。这也就是最后的输出,但是AlexNet最终是要分1000个类,所以通过第八层,也就是全连接的第三层,由此得到1000个类输出。 Alexnet网络中各个层发挥了不同的作用,ReLU,多个CPU是为了提高训练速度,重叠pool池化是为了提高精度,且不容易产生过拟合,局部归一化响应是为了提高精度,而数据增益与dropout是为了减少过拟合。 VGG net在ILSVRC-2014中,牛津大学的视觉几何组提出的VGGNet模型在定位任务第一名和分类任务第一名[[[i]](https://zhuanlan.zhihu.com/wr...]。如今在计算机视觉领域,卷积神经网络的良好效果深得广大开发者的喜欢,并且上文提到的AlexNet模型拥有更好的效果,所以广大从业者学习者试图将其改进以获得更好地效果。而后来很多人经过验证认为,AlexNet模型中所谓的局部归一化响应浪费了计算资源,但是对性能却没有很大的提升。VGG的实质是AlexNet结构的增强版,它侧重强调卷积神经网络设计中的深度。将卷积层的深度提升到了19层,并且在当年的ImageNet大赛中的定位问题中获得了第一名的好成绩。整个网络向人们证明了我们是可以用很小的卷积核取得很好地效果,前提是我们要把网络的层数加深,这也论证了我们要想提高整个神经网络的模型效果,一个较为有效的方法便是将它的深度加深,虽然计算量会大大提高,但是整个复杂度也上升了,更能解决复杂的问题。虽然VGG网络已经诞生好几年了,但是很多其他网络上效果并不是很好地情况下,VGG有时候还能够发挥它的优势,让人有意想不到的收获。 与AlexNet网络非常类似,VGG共有五个卷积层,并且每个卷积层之后都有一个池化层。当时在ImageNet大赛中,作者分别尝试了六种网络结构。这六种结构大致相同,只是层数不同,少则11层,多达19层。网络结构的输入是大小为224*224的RGB图像,最终将分类结果输出。当然,在输入网络时,图片要进行预处理。 VGG网络相比AlexNet网络,在网络的深度以及宽度上做了一定的拓展,具体的卷积运算还是与AlexNet网络类似。我们主要说明一下VGG网络所做的改进。第一点,由于很多研究者发现归一化层的效果并不是很好,而且占用了大量的计算资源,所以在VGG网络中作者取消了归一化层;第二点,VGG网络用了更小的3x3的卷积核,而两个连续的3x3的卷积核相当于5x5的感受野,由此类推,三个3x3的连续的卷积核也就相当于7x7的感受野。这样的变化使得参数量更小,节省了计算资源,将资源留给后面的更深层次的网络。第三点是VGG网络中的池化层特征池化核改为了2x2,而在AlexNet网络中池化核为3x3。这三点改进无疑是使得整个参数运算量下降,这样我们在有限的计算平台上能够获得更多的资源留给更深层的网络。由于层数较多,卷积核比较小,这样使得整个网络的特征提取效果很好。其实由于VGG的层数较多,所以计算量还是相当大的,卷积层比较多成了它最显著的特点。另外,VGG网络的拓展性能比较突出,结构比较简洁,所以它的迁移性能比较好,迁移到其他数据集的时候泛化性能好。到现在为止,VGG网络还经常被用来提出特征。所以当现在很多较新的模型效果不好时,使用VGG可能会解决这些问题。 GoogleNet谷歌于2014年Imagenet挑战赛(ILSVRC14)凭借GoogleNet再次斩获第一名。这个通过增加了神经网络的深度和宽度获得了更好地效果,在此过程中保证了计算资源的不变。这个网络论证了加大深度,宽度以及训练数据的增加是现有深度学习获得更好效果的主要方式。但是增加尺寸可能会带来过拟合的问题,因为深度与宽度的加深必然会带来过量的参数。此外,增加网络尺寸也带来了对计算资源侵占过多的缺点。为了保证计算资源充分利用的前提下去提高整个模型的性能,作者使用了Inception模型,这个模型在下图中有展示,可以看出这个有点像金字塔的模型在宽度上使用并联的不同大小的卷积核,增加了卷积核的输出宽度。因为使用了较大尺度的卷积核增加了参数。使用了1*1的卷积核就是为了使得参数的数量最少。 Inception模块 上图表格为网络分析图,第一行为卷积层,输入为224×224×3 ,卷积核为7x7,步长为2,padding为3,输出的维度为112×112×64,这里面的7x7卷积使用了 7×1 然后 1×7 的方式,这样便有(7+7)×64×3=2,688个参数。第二行为池化层,卷积核为3×33×3,滑动步长为2,padding为 1 ,输出维度:56×56×64,计算方式:1/2×(112+2×1−3+1)=56。第三行,第四行与第一行,第二行类似。第 5 行 Inception module中分为4条支线,输入均为上层产生的 28×28×192 结果:第 1 部分,1×1 卷积层,输出大小为28×28×64;第 2 部分,先1×1卷积层,输出大小为28×28×96,作为输入进行3×3卷积层,输出大小为28×28×128;第 3部分,先1×1卷积层,输出大小为28×28×32,作为输入进行3×3卷积层,输出大小为28×28×32;而第3 部分3×3的池化层,输出大小为输出大小为28×28×32。第5行的Inception module会对上面是个结果的输出结果并联,由此增加网络宽度。 ResNet2015年ImageNet大赛中,MSRA何凯明团队的ResidualNetworks力压群雄,在ImageNet的诸多领域的比赛中上均获得了第一名的好成绩,而且这篇关于ResNet的论文Deep Residual Learning for Image Recognition也获得了CVPR2016的最佳论文,实至而名归。 上文介绍了的VGG以及GoogleNet都是增加了卷积神经网络的深度来获得更好效果,也让人们明白了网络的深度与广度决定了训练的效果。但是,与此同时,宽度与深度加深的同时,效果实际会慢慢变差。也就是说模型的层次加深,错误率提高了。模型的深度加深,以一定的错误率来换取学习能力的增强。但是深层的神经网络模型牺牲了大量的计算资源,学习能力提高的同时不应当产生比浅层神经网络更高的错误率。这个现象的产生主要是因为随着神经网络的层数增加,梯度消失的现象就越来越明显。所以为了解决这个问题,作者提出了一个深度残差网络的结构Residual: 上图就是残差网络的基本结构,可以看出其实是增加了一个恒等映射,将原本的变换函数H(x)转换成了F(x)+x。示意图中可以很明显看出来整个网络的变化,这样网络不再是简单的堆叠结构,这样的话便很好地解决了由于网络层数增加而带来的梯度原来越不明显的问题。所以这时候网络可以做得很深,到目前为止,网络的层数都可以上千层,而能够保证很好地效果。并且,这样的简单叠加并没有给网络增加额外的参数跟计算量,同时也提高了网络训练的效果与效率。 在比赛中,为了证明自己观点是正确的,作者控制变量地设计几个实验。首先作者构建了两个plain网络,这两个网络分别为18层跟34层,随后作者又设计了两个残差网络,层数也是分别为18层和34层。然后对这四个模型进行控制变量的实验观察数据量的变化。下图便是实验结果。实验中,在plain网络上观测到明显的退化现象。实验结果也表明,在残差网络上,34层的效果明显要好于18层的效果,足以证明残差网络随着层数增加性能也是增加的。不仅如此,残差网络的在更深层的结构上收敛性能也有明显的提升,整个实验大为成功。 ...

June 17, 2019 · 1 min · jiezi

如何将深度学习训练速度提升一百倍PAISoar-来了

阿里妹导读:得力于数据规模增长、神经网络结构的演进和计算能力的增强,深度学习的图像处理、语音识别等领域取得了飞速发展。随着训练数据规模和模型复杂度的不断增大,如何充分利用分布式集群的计算资源加快训练速度,提升业务支持能力成为用户非常关注的问题。今天,我们就来分享阿里工程师的实践成果:将深度学习模型的大规模分布式训练框架 PAISoar应用于绿网模型(多层CNN网络)后,绿网模型在128 GPU卡上取得101倍的计算加速比,效果显著。1. 概述近几年来深度学习发展迅速,图像处理、语音识别等领域都取得了飞速发展。例如在图片识别上,神经网络结构快速演进,分类的网络结构从 AlexNet、VGG、Inception V1 发展到了 Inception V4、Inception-ResNet、SENet。随着模型层次越来越深,参数越来越多,模型能力也越来越强,ImageNet 数据集 Top-5 的错误率越来越低,目前降到了2.25%(人眼5.1%)。 随着模型复杂度不断增长、训练样本的指数级增长,分布式进行高效并行的神经网络训练已经变得越发重要。在社区版 Tensorflow 中,分布式训练是基于 Parameter Server 模式进行多机训练的。在这种训练方式下训练任务通常会遇到以下挑战: Variable placement 策略,常用的 replica_device_setter 的策略是 round-robin over all ps tasks,这种策略并没有考虑 Variable 大小,会导致参数分配不均衡,某些 ps 上分配的 Variable size 大就会成为通信瓶颈;多个 Worker 访问同一个 PS 节点时,受 PS 节点带宽限制和 TCP 的拥塞窗口控制,会导致通信效率大幅降低,并且规模越大,效率越差;分布式扩展后,模型需要精细调参才能收敛,需要用户有丰富的调参经验。对此,我们基于 PAI Tensorflow 研发了针对于深度学习模型的高速分布式训练框架 PAISoar,从硬件到软件打造一套分布式训练场景 E2E 的解决方案: 在硬件上,我们和 AIS 网络团队一起搭建了集团内部第一套基于 RoCE 的大规模 RDMA 集群,并针对于深度学习场景进行了相应的参数调优,支持低延迟、高吞吐的无损传输网络;在软件上,我们基于 Ring AllReduce 算法在 RDMA 网络上实现了高度优化的 PAISoar 分布式训练框架,通过软硬件一体的深度优化大大提高了多机的计算加速比;在 API 层面,我们提供了简化用户构建分布式 TF 模型训练的ReplicatedVarsOptimizer,极大地方便了将单机模型扩展成分布式模型,降低了用户构建分布式TF训练代码的难度,同时提供支持 warm up 的 learning rate 动态调节方法,帮助模型训练更容易的收敛。PAISoar 在 Tensorflow 官方 benchmarks 模型上取得了非常不错的加速效果。同时我们还和安全部团队合作,将该研发成果成功的在安全部图像模型业务上落地。安全部的绿网模型训练样本280万张图片,单机两卡训练需要12天才能收敛,因此有着非常强的分布式训练需求,希望能达到一天内完成训练,提升模型迭代能力。借助于 PAISoar,绿网模型分布式训练取得非常明显的加速效果,模型收敛时间从原先的12天降低到目前的一天以内,大大加速了业务的快速迭代。 ...

June 12, 2019 · 3 min · jiezi

无所不能的深度学习

古往今来,人类一直在探求科技的极限。随着信息技术在21世纪的爆发,数据科学与人工智能技术迎来自己的春天,尤其是以深度学习为基础的人工智能技术可谓是大放异彩,在诸多领域远胜人类,并且如人脸识别这样的技术也纷纷落地,甚至悲观者认为,机器智能时代来临,倘若某天机器有了自主思维,人类将会面临灭顶之灾。可是,深度学习就如此无所不能吗?答案是否定的!深度学习是利用深层神经网络的技术,虽然在图像识别等方面已经能够超越人类,但是它仍然有许多方面是不能完成的,本文列举深度学习目前不能实现的一些领域,希望能够帮大家打开思维,更好地认识深度学习。 深度学习的“能”既是学霸,又是游戏王一般来说,多数人每年可以看300篇文献,而IBM的Watson系统在10分钟里就可以阅读2000万的文献,显而易见,深度学习的学习能力是远远大于人类的,是个十足的“学霸”。与此同时,在游戏领域,不管是围棋还是dota2,深度学习有足够的能力碾压人类。所以深度学习既是学霸,又是游戏王。 多才多艺下棋,写诗,作曲,艺术画······2016年,阿尔法狗大胜李世石,2017年微软小冰出版第一部诗集,随后又开始转向音乐创作·····深度学习已经慢慢变成琴棋书画样样精通,多才多艺全能王。 从深度学习所取得的成果来看,它似乎已经无所不能,在诸多方面超过了人类。 深度学习的“不能”算法输出不稳定,容易被攻击在图像识别领域,我们可能在一张图像中只改变一个像素点的值,那么输出结果会发生巨大改变,这就是算法输出不稳定导致的,这种细微的改变在人类看来微不足道,对于算法模型来说确不同。不仅在图像领域,自然语言处理领域也有这样的问题。在问答系统中,在原始文本中随机得加入一些简单的词,模型的理解能力大大降低。这种问题不仅出现在深度学习,传统机器学习更容易被攻击。 模型复杂度高,难以纠错或调试在2016年阿法狗与李世石的大战中,李世石赢了一局。在李世石的78手后,阿法狗的胜率便直线下降。如果可以投降的话,那么在李世石的第78手后,阿法狗应该会选择投降,而并不会针对这一手进行相应的改进。此外,在深度学习进行翻译时,不管是给模型什么数据输入,都会有一个有意义的输出。此前的谷歌翻译曾遇到过这样的问题,在翻译结果有明显错误的时候,翻译部门的工程师也很难去对模型修改,可见深度学习模型的复杂。 层级复合程度高,参数不透明在图像识别领域,我们在模型的中间层中尽力去抓取图像的特征。在第一层的卷积层计算后,我们对结果进行可视化,可以很容易看出结果与原图像有很大相似性。然后,随着层数的加深,对中间其他层的可视化,我们完全不能看出中间层所代表的意义。主要原因在于感受野的复合,而且每层的卷积核也会产生复合,加上一些模型会有自己特有的复合,如inception模块的复合,残差的复合,让我们难以从中间层的可视化中看到模型具体运行的结果。 对数据依赖性强,模型增量性差深度学习是端到端结构,灵活性非常低。我们将单个图像拼接在一起,人类很容易识别的内容,深度学习确无能为力,可见其迁移能力较差。在“语义标注”和“关系检测”这类问题中,人类可以通过完成一个任务中的多个子任务,并将子任务整合的方式解决问题,而对于深度学习来说,多个子任务与一个总任务是完全不同的两个任务,需要不同的模型去解决问题。在数据量较小的情况下,模型拟合能力较差。 专注直观感知类问题,对开放性问题无能为力我们小时候都曾学习过关于乌鸦喝水的故事。乌鸦在面对半瓶水,而自己的嘴够不着水时,会往瓶子里丢入石子,使得水面上升从而喝到水。此外,乌鸦在无法拨开坚果时,它会把坚果丢在马路上,让来往的车辆碾压从而迟到果实,在此过程中,乌鸦能够通过观察人行道的情况学会判断车辆是否会行驶以保障自己的安全。而鹦鹉也有自己的智能,在听过人类重复说过的话后,鹦鹉能够很好地模仿人类说话。深度学习只能做到鹦鹉的智能,而做不到乌鸦的智能,可见其泛化能力之低。此外,深度学习也难以理解图像背后的寓意。当一幅图中出现奥巴马与一群大象时,深度学习仅仅能辨认图中是一个男人与一群大象,显然图作者却是想透过图片暗喻美国的两党之争,一般来说,大象喻指美国民主党。 机器偏见难以避免,人类知识难以有效监督这可能是目前深度学习面临的最大问题。数据是深度学习的基础,而数据的可靠程度决定了模型的可靠程度。微软层开发聊天机器人Tay,模仿年轻网民的语言模式。但是试用24小时后便被引入歧途,成为偏激的种族主义者,甚至发出了“希特勒无罪”的消息。原因在于年轻的网民本身的语料库并不是纯净的,是人就会有偏见,这种偏见在网络中尤其严重,这样便导致了Tay用来训练的数据带有偏见,并使得Tay误入歧途,而人类知识的监督很难有效采用,这就无法避免机器的偏见。另一个例子,美国法院用以评估犯罪风险的算法COMPAS,也被证明对黑人造成了系统性歧视。机器偏见无法消除,日后可能会给人类带来严重的后果。 总结不可否认,深度学习可以在特定领域超过人类,有很好的效果,但它并非万能。某种意义上说,它离智能还差很远。目前,对深度学习的泛化性与可解释性的呼声越来越高。2017年7月,国务院在《新一代人工智能发展规划》中提出“实现具备高可解释性,强泛化能力的人工智能”。或许下一代人工智能技术还是在深度学习基础之上展开,但是希望新的技术能够很好地解决现在深度学习的不能,更好地造福人类!

June 11, 2019 · 1 min · jiezi

一文读懂深度学习从神经元到BERT

阿里妹导读:自然语言处理领域的殿堂标志 BERT 并非横空出世,背后有它的发展原理。今天,蚂蚁金服财富对话算法团队整理对比了深度学习模型在自然语言处理领域的发展历程。从简易的神经元到当前最复杂的BERT模型,深入浅出地介绍了深度学习在 NLP 领域进展,并结合工业界给出了未来的 NLP 的应用方向,相信读完这篇文章,你对深度学习的整体脉络会有更加深刻认识。一个神经网络结构通常包含输入层、隐藏层、输出层。输入层是我们的 features (特征),输出层是我们的预测 (prediction)。神经网络的目的是拟合一个函数 f:features -> prediction。在训练期间,通过减小 prediction 和实际 label 的差异的这种方式,来更改网络参数,使当前的网络能逼近于理想的函数 f。 神经元(Neural Cell)神经网络层的基本组成成员为神经元,神经元包含两部分,一部分是上一层网络输出和当前网络层参数的一个线性乘积,另外一部分是线性乘积的非线性转换。(如果缺少非线性转换,则多层线性乘积可以转化为一层的线性乘积) 浅层神经网络( Neural Network )只有一层隐藏层的,我们称为浅层网络。 深度学习网络(Multilayer Perceptron)相对于浅层网络结构,有两层、三层及以上隐藏层的我们就可以称为深度网络。 在通常的理解中,一个足够宽的网络,是能够拟合任何函数的。而一个深层网络,则能够用更少的参数来拟合该函数,因为深层的神经元可以获取比浅层神经元更复杂的特征表示。 在图二及三所示网络,我们称为全连接网络,也就是隐藏层的神经元会和上一层所有的神经元输出相关。和全连接网络相对应的,是只和上一层部分神经元输出连接的网络,如下文介绍的卷积网络。 卷积网络(CNN)卷积网络神经元只和上一层的部分神经元输出是连接的。(在直觉上,是因为人的视觉神经元触突只对局部信息敏感,而不是全局所有信息都对同一个触突产生等价作用) 同一个卷积核从左到右,从上到下和输入做乘积,得到了不同强度的输出。从直觉上来理解,卷积核对原始数据的不同数据分布的敏感度是不一样的。如果把卷积核理解为是某种 pattern,那么符合这种 pattern 的数据分布会得到比较强的输出,而不符合这种 pattern 的输出则得到弱的,甚至是不输出。 一个卷积核是一个 pattern 提取器, 多个卷积核就是多个 pattern 提取器。通过多个特征提取器对原始数据做特征提取转换,就构成了一层卷积。 Alex Net, 因为 GPU 内存的原因,Alex 使用了两块 GPU 对模型做了切割,本质上的卷积层是用于特征提取, 最大池化层用于提取强特征及减少参数,全连接层则是所有高级特征参与到最后分类决策中去。 循环神经网络(RNN)CNN是对空间上特征的提取, RNN则是对时序上特征的提取。 在RNN中,x1 , x2, x3, xt 是在时序上不一样的输入,而 V, U, W 三个矩阵则是共享。同时 RNN 网络中保存了自己的状态 S。 S 随着输入而改变,不同的输入/不同时刻的输入或多或少影响 RNN 网络的状态 S。而 RNN 网络的状态 S 则决定最后的输出。 ...

May 27, 2019 · 3 min · jiezi

谷歌发布的Translatotron是什么

背景介绍作为中国人,学好英语这件事从小学开始就让人苦恼,近些年随着AI的快速发展,语言差异是否会缩小甚至被消灭成了热门话题。在5月15日,谷歌AI在博客平台发出一篇文章,正式介绍了一款能保留原声的“同声传译”黑科技,消息一出,迅速席卷网络,为科技发烧友带来了更多曙光,下面,让我们来揭开这个叫做“Translatoron”的神秘面纱。 Translatotron的出现目前市面常用的语音翻译产品的翻译过程包含三个步骤,首先将语音转换为文字,再由机器将文字转换为目标语言文字,最后将目标语言的文字转化为语音(文字转语音全称Text-To-Speech,也叫TTS)。 而谷歌的Translatotron有很大不同,它通过某种手段实现了语音到语音的直接转译,避免了上述的三个步骤。除此之外,它还有一些其它的优势,比如更快的推理速度、更容易识别不需要翻译的名称及专业名词等,最牛的是它可以保留原说话人的声音特征,做到原声输出其它语言,幻想一下用自己的声音说出了连本人都听不懂的外语,是不是有点像《流浪地球》中的同声翻译,多刺激啊,在此向大刘致敬! Translatotron的原理其实端到端的语音翻译在2016年就出现了,当时研究者们发现用“序列到序列模型”来做“语音到文字”的翻译可行性很高,到了2017年,研究者们证明出它果然很吊,但是这还不够,Translatotron的出现又向大家证明了“序列到序列模型”不仅可以转文字,还可以不依赖任何中间文本,直接帮你转为语音。 上面部分的名词有些含糊不清,这里来解释一下,首先是端到端学习,英文名为end-to-end,它就像一个黑盒子,人们把数据丢进去后只关心结果是否与期望的结果一致,不关心中间的实现过程。这个黑盒子的实现原理是,当结果和期望的结果出现误差后,它会将误差反传回训练模型的每一环节,让它们根据误差来自我调节,直到结果与预期相符为止。 而序列到序列模型,英文为Sequence to Sequence,它是端到端理念的一种实现框架,最早出现于Bengio在2014年的论文,Bengio是蒙特利尔大学的教授,他与另外两位朋友被AI领域的人戏称为“加拿大黑手党”。 “序列到序列”模型的目的是“将一个领域(比如中文)的序列转化为另一个领域(比如英文)的序列”,它是通过联合两个循环神经网络(RNN)来实现的,而联合的这种结构又被叫做编码-解码(Encoder-Decoder)结构,结构的两端支持多种数据类型,比如文字、语音、图像、视频等,非常适用于机器翻译。 Translatotron正是利用了图像这种数据类型,它通过声谱图作为输入,再生成出目标语言的声谱图,然后通过一个叫做Vocoder的语音编解码器(用于分析和合成用于音频数据压缩,多路复用,语音加密,语音转换等的人类语音信号)将新生成的光谱图转换为时域波形(一种表达信号与时间关系的波浪形状)。另外,它还可以选择使用一个编码器在合成翻译语音中维护原来的语音特征。 这项研究是由谷歌大脑、谷歌翻译和谷歌语音团队共同完成的,由于目前的训练数量较少,Translatotron所展示出的翻译质量以及原声匹配度没有预想中那么好,但随着更多数据的训练相信会有非常光明的前景。感兴趣的同学可以去官方博客了解一下。 如果你愿意,让我来帮你关注那些可能不知道又想知道却想不到的知识。

May 18, 2019 · 1 min · jiezi

GPT2吓坏创造者的深度造假写手

简评: 今年二月份刷屏的 GPT-2 着实厉害,那个生成续写故事的例子更是效果好到吓人一跳,它到底有多厉害,本文略微讲讲。更详细的信息可参考文末 OpenAI 的博客链接。你能从下面这两段文字里品味出什么区别? 「四月间,天气寒冷晴朗,钟敲了十三下。」「我坐在小汽车里,前往西雅图开始一份新工作。给车加油,插入钥匙,让它自己开。我沉入冥思,想象这会是怎样的一天。」第一段文字,是英国著名作家乔治·奥维尔(George Orwell)的传世经典,政治荒诞讽刺小说《1984》开篇第一句话。 第二段文字,则是将第一段文字输入 GPT-2 程序后,这个 AI 系统的自动续写。 仅仅输入这么简单的一句话,GPT-2 显然就精确的抓住了乔治·奥维尔《1984》的荒诞、压抑、恐惧和反乌托邦的笔调,洋洋洒洒的续写起来: 一百年后,2045 年, 我在中国一个贫穷农村地区的一所中学教书。我先开始教的是中国历史和中国科技史...... ▎「深度造假」GPT-2 人工智能文字编写程序可以写小说、新闻、发言稿,还可以发短信推文。 程序开发者给它起了个绰号 —— 深度造假文字(deepfakes for text),精确地概括了它的功能。简而言之,GPT-2 就是一个文字发生器。你可以文字输入这个 AI 系统,只言片语或者大段文字都行,之后程序会根据自己的判断,决定接下来应该如何写作。 它产生的文字,从质量到数量到适应范围,都远远超出了设计者的预期。 它的「造假能力」如此令人信服,以至于其所属公司 Open AI 做出了一个不同寻常的决定:暂不公开 GPT-2 的技术信息,以免该技术被恶意使用。 ▎以假乱真与其它类似功能的程序相比,GPT-2 几乎不露马脚,比如写着写着忘了在写什么,或夹杂一些莫名其妙的词汇等。 英国《卫报》记者把英国脱欧的一些标题词汇输入 GPT-2,它写出了这样的一段「新闻稿」: 当被要求对有关报道做出澄清时,梅首相的发言人说:“首相已经明确表明,她要做的是尽快完成脱欧,这在上周的女王年度施政讲话中有明确授权。”OpenAI 的研究负责人阿莫迪(Dario Amodei)对《卫报》说,GPT-2 从两个方面具有革命性的突破 —— 一是它的数据储藏能力巨大,是现有最前沿的 AI 文字发生器数据储量的 12 倍。这使得它能更好地理解掌握写作文风,笔法和意图。这也导致了它的第二个突破,即它的写作质量和应用的广泛性。 而也正是它生产出的文字达到了真假难辨的程度,也促使 OpenAI 公司决定暂时不公开 GPT-2 的技术。他们下一步将测试使用 GPT-2 可能出现的任何结果,以及如何防止恶意使用。 公司表示,使用 AI 技术的道德原则是一个全新的领域,他们还在探索之中。 博客链接:Better Language Models and Their Implications推荐阅读:数字游戏:艺术家如何用大数据展现艺术欢迎关注:微信公众号「极光开发者」 ...

May 15, 2019 · 1 min · jiezi

阿里搜索推荐系统又双叒叕升级了

阿里妹导读:搜索导购产品作为搜索的流量入口,承载了为用户导购推荐、搜索流量分流的重要功能。主要产品包括:首页底纹、下拉推荐、搜索发现、导航、历史搜索等。经过几年的探索和积累,各个产品越发地成熟,机器学习算法广泛地应用于导购产品中,取得了显著的效果。在支撑好手淘搜索业务的基础上,搜索导购也积极地拓展边界,支持了集团内大量的产品线。因此对搜索导购产品线提出了更高的要求:不仅需要提升本身产品的效率,更好地支持手淘搜索业务,同时也需要有一套灵活的框架,支持更多更广的业务。 一、系统框架导购升级的优化思路从三个方向着手:1.策略升级。利用深度学习及异构网络的思想,对用户个性化进行更深的理解和建模;同时对因马太效应引起的独立query数下降等问题进行优化。 2.导购外投。在包括会场激活页、猜你喜欢等渠道进行搜索导购赋能,为用户打通搜索通路。 3.产品创新。一方面对现有的产品进行创新升级,如激活页、下拉推荐等;另一方面积极尝试新产品形态,如首页热词、搜索动态卡片等。 搜索导购核心解决对消费者关键词推荐的问题,因此虽然产品众多,形态各异,但是在底层架构上有很多共性,因此我们设计了一套通用灵活的框架进行支持。 在召回阶段,我们丰富了召回方式;并根据不同的渠道、场景以及产品形态,选择不同的召回策略得到候选query词candidates。 在排序阶段,我们不仅将深度学习引入导购算法框架中,而且创新的加入了异构网络的思想,将用户不同路径的序列信息结合lstm等模型进行有效融合,对消费者进行更深入的理解。 在业务策略阶段,我们利用 jaccard 系数、编辑距离等进行了对语义重复问题进行了优化,同时结合E&E机制对马太效应较为严重的场景进行了升级,并增加了效率轮播机制使得效率进一步的得到提升。 接下来以几个具体的产品来进行详细的介绍。 二、详细方案2.1 底纹推荐优化 在底纹推荐的算法优化中,我们创新性地提出了基于异构网络(Heterogeneous Information Network,后面简称HIN)的推荐方法,推荐框架如下图所示: user,item 和 query 是手淘中三种基本类型的节点,这三种类型节点之间又有不同的交互关系,比如,user 直接点击 item,user 通过查询 query 进入搜索,并在搜索里发生 item 的点击等。 但是,大多数传统推荐方法只关注特征工程,忽略了这些不同节点之间的关联关系。同时电商领域的大规模数据体量(一亿query,数十亿user和item)也是需要考虑的问题。因此我们设计提出了一种基于元路径embedding 表示的大规模 query 推荐方法,MetaPath-guided Embedding for Large-scale Query Recommendation(MELQR),它采用异构网络对 query推荐进行建模,并利用元路径通过聚合局部邻居信息来指导 user 和 query 的表示学习,此外,我们对异构网络中所有节点用term embedding的某种融合方法来进行表示,从而避免了网络学习中的大规模参数问题。 该模型结合扩召回、动态展示等策略,对线上底纹使用uv提升10%+,引导成交金额提升10%+。值得一提的是,该模型目前也同步使用到了导购的其它产品例如搜索发现、首页热词等,效果的提升同样非常明显。 2.2 首页热词优化 首页热词是今年搜索在手淘首页的一个创新性产品,可以帮助用户通过关键词找到感兴趣的商品,增强用户的搜索心智。 首页热词与底纹推荐共享系统框架与算法框架 2.3 下拉推荐优化 下拉推荐上一个版本的优化目标在于提升下拉引导pv在搜索pv中的占比,即下拉使用率。上个版本试图拟合的是用户对下拉所展示的 query 的偏好程度。但是在其使用的统计类特征中,使用的特征均都是下拉引导的数据。这就带来了一个比较严重的问题,在目前的产品形态下,每次用户输入,只能展示10个候选的 query。因此一开始展示相对较多的 query 会具有相对较高的统计值,而较高的统计值会促进该query 在排序中排到更靠前的位置。因此形成循环,久而久之,在某些特定的 query下,下拉推荐候选词的统计值特征会有非常大的差异。由此形成马太效应。马太效应一个最严重的问题就是会导致下拉展示的 query 会过度收敛到一个较小的集合中,导致引导的独立 query 数下降。 针对这些问题,我们对下拉推荐模型进行了系统的重构,框架如下: ...

May 14, 2019 · 1 min · jiezi

机器学习与传统编程之间的区别是什么

翻译:疯狂的技术宅https://towardsdatascience.co... 有些人认为 AI 和 ML 被过分夸大了,认为它们只不过是写一些 if 语句,或者仅仅是和编程有关的玩意儿,但我建议你对这些观点进行仔细的思考和分辨。在本文中,我将对它们涉及到的术语进行比较,并展示这两个领域的专家之间的区别:他们究竟是做什么的?软件工程师、软件开发人员、机器学习专家、数据科学家......有些人甚至用程序员或码农称呼他们,有些人甚至可以成为大佬、大师或明星!但是他们真的一样吗?如果是这样的话,那机器学习和传统编程之间究竟有什么区别? 首先,什么是机器学习? 尽管说起来很容易,AI 和 ML 只不过是 if 编程,或者更深入一点,它只是简单的统计数据。我们还能知道些什么呢? ML 只是一个描述数学 + 算法的新词吗?尽管有时这种简化似乎很有趣,但很明显,ML更复杂。 但是让我们来看一个更合适的解释。 因此,简单来说,人工智能是一个包含其他领域的大筐,如图像处理、认知科学、神经网络等等。机器学习也是这个大筐中的一个组成部分。它的核心思想是:计算机不只是使用了预先编写的算法,还学习如何解决问题本身。或者,换句话说,Arthur Samuel 给出了一个很好的定义(他实际上创造了ML的术语): 机器学习是一个研究领域,使计算机无需明确编程即可学习。是的,ML 教一台机器来解决难以通过算法解决的各种复杂任务。那些任务是什么?好吧,你可能已经在实践中偶然发现了它们。例如它可以是你的手机上的面部识别或语音识别,驾驶汽车(Google自动驾驶汽车),按症状诊断疾病(Watson),推荐商品(如:书籍(亚马逊),电影(Netflix),音乐(Spotify) ),个人助理(Siri,Cortana)的功能......这个列表可以列的很长很长。 我希望说得已经足够清楚了,接下来继续谈论关于 ML 的另一个重要的问题。 任何有效的 ML 技术都可以有条件地归于三个级别的可访问性。这是什么意思?嗯,第一个层面是 Google 或 IBM 等这种科技巨头的特殊用例。第二个层次是,比方说,具有一定知识的学生可以使用它。而最后一个也就是 ML 可访问性的第三个层次是甚至一个老奶奶能够应对它。 我们目前的发展阶段是机器学习正处在第二级和第三级交界处。因此借助这项技术,世界的变化将会日新月异。 关于 ML 最后还有一点点说明:大多数 ML 任务可以分为跟着老师学(监督学习)和没有老师去教(无监督学习)。如果你想象一个程序员一只手拿鞭子,另一只手拿着糖,那就有点误会了。 “老师”这个名字意味着人为干预数据处理的想法。在有老师参与培训时,这是监督学习,我们有数据,需要在其基础上预测一些事情。另一方面,当没有老师进行教学时,这是无监督学习时,我们仍然有数据,但需要自己去找到它的属性。 好的,那么它与编程有什么不同? 在传统编程中,你需要对程序的行为进行硬编码。在机器学习中,你将大量内容留给机器去学习数据。所以这些工作内容无法互换:数据工程师无法取代传统编程的工作,反之亦然。尽管每个数据工程师都必须使用至少一种编程语言,但传统编程只是他所做的一小部分。另一方面,我们不能说软件开发人员正在用 ML 算法来启动网站。 ML 不是替代品,而是传统编程方法的补充。例如,ML 可用于为在线交易平台构建预测算法,而平台的 UI、数据可视化和其他元素仍然用主流编程语言(如Ruby或Java)编写。 所以最主要的是:ML 被用在传统编程策略无法满足的场景,而且它不足以独立完全完成某项任务。 那么这在实施中意味着什么呢?我们用一个汇率预测的经典 ML 问题的需求来进行解释: 传统的编程方法 对于任何解决方案,第一个任务是创建最合适的算法并编写代码。之后必须设置输入参数,如果实现的算法没问题,将会产生预期的结果。 软件开发人员如何制定解决方案 但是当我们要对某些东西进行预测时,需要用到有各种输入参数的算法。若要预测汇率,必须添加昨天的汇率的详细信息,以及发行货币的国家的外部和内部经济变化等数据。 因此,我们需要设计一个能够接受一组参数的解决方案,并能够根据输入的数据预测新的汇率。 我们需要添加成百上千个参数,用它们的有限集去构建一个非常基本同时不可扩展的模型。是的,任何人都很难处理如此庞大的数据阵列。 对于这个任务,我们可以用机器学习方法,那么它是怎么做的呢? ...

May 8, 2019 · 1 min · jiezi

阿里开源轻量级深度学习端侧推理引擎-MNN

阿里妹导读:近日,阿里正式开源轻量级深度学习端侧推理引擎“MNN”。AI科学家贾扬清如此评价道:“与 Tensorflow、Caffe2 等同时覆盖训练和推理的通用框架相比,MNN 更注重在推理时的加速和优化,解决在模型部署的阶段的效率问题,从而在移动端更高效地实现模型背后的业务。这和服务器端 TensorRT 等推理引擎的想法不谋而合。在大规模机器学习应用中,考虑到大规模的模型部署,机器学习的推理侧计算量往往是训练侧计算量的十倍以上,所以推理侧的优化尤其重要。” MNN背后的技术框架如何设计?未来有哪些规划?今天一起来深入了解。 1、MNN是什么? MNN 是一个轻量级的深度学习端侧推理引擎,核心解决深度神经网络模型在端侧推理运行问题,涵盖深度神经网络模型的优化、转换和推理。目前,MNN已经在手淘、手猫、优酷、聚划算、UC、飞猪、千牛等 20 多个 App 中使用,覆盖直播、短视频、搜索推荐、商品图像搜索、互动营销、权益发放、安全风控等场景,每天稳定运行上亿次。此外,菜鸟自提柜等 IoT 设备中也有应用。在 2018 年双十一购物节中,MNN 在天猫晚会笑脸红包、扫一扫、明星猜拳大战等场景中使用。 该项目已经在 Github 开源,关注“阿里技术”官方公众号,并在对话框内回复“MNN”,即可获得 Github 下载链接、了解更多详情。 2、MNN的优势MNN 负责加载网络模型,推理预测返回相关结果,整个推理过程可以分为模型的加载解析、计算图的调度、在异构后端上高效运行。MNN 具有通用性、轻量性、高性能、易用性的特征: 通用性: 支持 Tensorflow、Caffe、ONNX 等主流模型格式,支持 CNN、RNN、GAN 等常用网络;支持 86 个 TensorflowOp、34 个 CaffeOp ;各计算设备支持的 MNN Op 数:CPU 71 个,Metal 55 个,OpenCL 40 个,Vulkan 35 个;支持 iOS 8.0+、Android 4.3+ 和具有POSIX接口的嵌入式设备;支持异构设备混合计算,目前支持 CPU 和 GPU,可以动态导入 GPU Op 插件,替代 CPU Op 的实现;轻量性: 针对端侧设备特点深度定制和裁剪,无任何依赖,可以方便地部署到移动设备和各种嵌入式设备中;iOS 平台上,armv7+arm64 静态库大小 5MB 左右,链接生成可执行文件增加大小 620KB 左右,metallib 文件 600KB 左右;Android 平台上,so 大小 400KB 左右,OpenCL 库 400KB 左右,Vulkan 库 400KB 左右;高性能: ...

May 7, 2019 · 2 min · jiezi

TensorFlow-20Keras-防坑指南

TensorFlow 2.0是对1.x版本做了一次大的瘦身,Eager Execution默认开启,并且使用Keras作为默认高级API,这些改进大大降低的TensorFlow使用难度。 本文主要记录了一次曲折的使用Keras+TensorFlow2.0的BatchNormalization的踩坑经历,这个坑差点要把TF2.0的新特性都毁灭殆尽,如果你在学习TF2.0的官方教程,不妨一观。 问题的产生从教程[1]https://www.tensorflow.org/alpha/tutorials/images/transfer_learning?hl=zh-cn(讲述如何Transfer Learning)说起: IMG_SHAPE = (IMG_SIZE, IMG_SIZE, 3)# Create the base model from the pre-trained model MobileNet V2base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE, include_top=False,weights='imagenet')model = tf.keras.Sequential([ base_model, tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Dense(NUM_CLASSES)])简单的代码我们就复用了MobileNetV2的结构创建了一个分类器模型,接着我们就可以调用Keras的接口去训练模型: model.compile(optimizer=tf.keras.optimizers.RMSprop(lr=base_learning_rate), loss='sparse_categorical_crossentropy', metrics=['sparse_categorical_accuracy'])model.summary()history = model.fit(train_batches.repeat(), epochs=20, steps_per_epoch = steps_per_epoch, validation_data=validation_batches.repeat(), validation_steps=validation_steps)输出的结果看,一起都很完美: Model: "sequential"_________________________________________________________________Layer (type) Output Shape Param #=================================================================mobilenetv2_1.00_160 (Model) (None, 5, 5, 1280) 2257984_________________________________________________________________global_average_pooling2d (Gl (None, 1280) 0_________________________________________________________________dense (Dense) (None, 2) 1281=================================================================Total params: 2,259,265Trainable params: 1,281Non-trainable params: 2,257,984_________________________________________________________________Epoch 11/20581/581 [==============================] - 134s 231ms/step - loss: 0.4208 - accuracy: 0.9484 - val_loss: 0.1907 - val_accuracy: 0.9812Epoch 12/20581/581 [==============================] - 114s 197ms/step - loss: 0.3359 - accuracy: 0.9570 - val_loss: 0.1835 - val_accuracy: 0.9844Epoch 13/20581/581 [==============================] - 116s 200ms/step - loss: 0.2930 - accuracy: 0.9650 - val_loss: 0.1505 - val_accuracy: 0.9844Epoch 14/20581/581 [==============================] - 114s 196ms/step - loss: 0.2561 - accuracy: 0.9701 - val_loss: 0.1575 - val_accuracy: 0.9859Epoch 15/20581/581 [==============================] - 119s 206ms/step - loss: 0.2302 - accuracy: 0.9715 - val_loss: 0.1600 - val_accuracy: 0.9812Epoch 16/20581/581 [==============================] - 115s 197ms/step - loss: 0.2134 - accuracy: 0.9747 - val_loss: 0.1407 - val_accuracy: 0.9828Epoch 17/20581/581 [==============================] - 115s 197ms/step - loss: 0.1546 - accuracy: 0.9813 - val_loss: 0.0944 - val_accuracy: 0.9828Epoch 18/20581/581 [==============================] - 116s 200ms/step - loss: 0.1636 - accuracy: 0.9794 - val_loss: 0.0947 - val_accuracy: 0.9844Epoch 19/20581/581 [==============================] - 115s 198ms/step - loss: 0.1356 - accuracy: 0.9823 - val_loss: 0.1169 - val_accuracy: 0.9828Epoch 20/20581/581 [==============================] - 116s 199ms/step - loss: 0.1243 - accuracy: 0.9849 - val_loss: 0.1121 - val_accuracy: 0.9875然而这种写法还是不方便Debug,我们希望可以精细的控制迭代的过程,并能够看到中间结果,所以我们训练的过程改成了这样: ...

April 30, 2019 · 5 min · jiezi

浅谈-Spark-的多语言支持

作者:郑锴,花名铁杰,阿里巴巴高级技术专家,Apache Hadoop PMC,Apache Kerby 创立者。深耕分布式系统开发和开源大数据多年,先后专注在安全,存储和计算领域。之前在 Intel,目前转战阿里云上,致力于提供更好用更有弹性的 Hadoop/Spark 大数据平台。 Spark架构和设计上的优秀毋庸置疑,从一出道便抢了 Hadoop 的 C 位。在开源大数据的黄金十年一时风头无两,在当下人工智能时代仍然能够与时俱进,通天之处不遑多言,美中不足之处也有不少。小的方面,比如调度模型跟 MapReduce 这种计算范式过于耦合,Spark 最近引入 Barrier 调度模式就是为了支持深度学习这种新的计算类型,所幸在于对框架的改动不会伤筋动骨;有些缺陷则不然,影响全局,调整起来绝非易事。今天我主要想谈下 Spark 的框架语言实现和多语言支持---------有得,必有失。 Spark 核心和框架构建在 Scala 上,对应用开发者也是言必称 Scala,直接秀起了代码极简的肌肉。在用户接口上,从企业级应用的首选 Java,到数据科学家的 Python 和 R,再到商业智能 BI 的 SQL,官方都一一支持,按说已经很全面很完整了,各方神圣也都伺候到了,还有什么抱怨的,言何缺陷?首先,对 Python 的支持也就是 PySpark ,复杂且效率低下,有点像 hack,十分像早期 Spark 攻城略地的产出。其实对 R 的支持 SparkR 也如出一辙,我们讨论清楚了 PySpark 也就明白了对其他语言的支持其实是类似的。从使用者的角度来看用 PySpark 写程序的体验还是很不错的,跟 Scala 有点类似,简洁而优雅,就跟写个单机程序一样,不需要考虑分布式处理的复杂性。然而在这件漂亮的外衣下,用 PySpark 写的 Spark 程序就是比 Scala 版本慢,还动不动 OOM 掉,为什么?我们来探一下究竟。 一般 Spark 程序首先给定输入也就是要处理的数据集,然后表达好针对这个数据集的每行记录要处理的逻辑和转换规则,再将结果打印出来或是保存到文件。背后 Spark 框架进行翻译转换,产出一个个 RDD 和这些 RDD 之间的关系,每个 RDD 表示对应的数据集和在该数据集上要执行的变换处理逻辑。这些 RDD 根据它们之间的依赖关系组成 DAG,对 DAG 翻译转换成 stages 和 tasks,这个过程在 driver 端由框架 Scala 代码完成,包括对 stages 和 tasks 的调度执行;RDD 的处理逻辑对应用户的 Scala 或 Python 代码,因为要分布式并发处理,主要在 executor 上执行。因此,对于 Python 版本的 Spark 程序,在 driver 上和 executor 上都有要执行的 Python 代码,必然需要对应的 Python 解释器来执行;然而 Spark 计算框架是 Scala/Java 代码实现的,driver 和 executor 整体上得跑在 JVM 进程里面。那么如何在 driver 端和 executor 上同时执行代表用户逻辑的 Python 代码和核心引擎的 JVM 代码,并在两者之间进行交互和协调呢? ...

April 24, 2019 · 2 min · jiezi

用C / C ++实现BP神经网络

缘起最近跟着老师在学习神经网络,为了更加深刻地理解这个黑盒,我打算自己用C/C++将其实现一遍。今天忙活了好一会儿,终于实现了一个BP神经网络,后期还会陆续实现CNN神经网络之类的,也会发上来和大家一起分享的因为最近比较忙,所以这里直接放代码了,关于一些原理以及自己的一点见解会在有空的时候整理出来的代码main.cpp#include <iostream>#include <vector>#include “BPUtils.h"using namespace std;/* run this program using the console pauser or add your own getch, system(“pause”) or input loop /vector<vector<double>>dataTest;vector<double>dataTestY;vector<vector<double>>trainDataX;vector<double>trainDataY;int main() {// double m1[3][1]={{1},{2},{3}};// double m2[1][4]={1,2,3,4};// double m3[3][4];// dott(&m1[0][0],&m2[0][0],&m3[0][0],3,1,4);// for(int i=0;i<3;i++){// for(int j=0;j<4;j++){// cout<<m3[i][j]<<” “;// }// cout<<endl;// } createTrainSet(); createTestSet(); guiYiHua(dataTest); guiYiHua(trainDataX); NeuralNetwork nn(2,44,2); nn.train(trainDataX,trainDataY);// for(int i=0;i<trainDataX.size();i++){// for(int j=0;j<trainDataX[i].size();j++){// cout<<trainDataX[i][j]<<” “;// }// cout<<endl;// }// for(int i=0;i<trainDataX.size();i++){// cout<<trainDataY[i]<<” “;// }//// cout<<endl<<”———————————————————"<<endl;//// for(int i=0;i<dataTest.size();i++){// for(int j=0;j<dataTest[i].size();j++){// cout<<dataTest[i][j]<<" “;// }// cout<<endl;// }// for(int i=0;i<dataTestY.size();i++){// cout<<dataTestY[i]<<” “;// }// NeuralNetwork nn(2,4,3);// vector<vector<double>>dataX;// vector<double>dataY;// for(int i=0;i<4;i++){// vector<double>vec;// for(int j=0;j<2;j++){// vec.push_back(i+j);// }// dataX.push_back(vec);// }// for(int i=0;i<4;i++){// for(int j=0;j<2;j++){// cout<<dataX[i][j]<<” “;// }// cout<<endl;// }// for(int i=0;i<4;i++){// dataY.push_back(i);// }// nn.train(dataX,dataY); return 0;}BPUtils.h#ifndef BP_UTILS#define BP_UTILS#include <cmath>#include <cstdlib>#include <iostream>#include <vector>#include <ctime>#include <string.h>#include <cstdio>#include <fstream>#define random(x) (rand()%x)using namespace std;#define MAXSIZE 99//全局变量//测试集extern vector<vector<double>>dataTest;extern vector<double>dataTestY;extern vector<vector<double>>trainDataX;extern vector<double>trainDataY;vector<string> split(const string& str, const string& delim) { vector<string> res; if(”" == str) return res; //先将要切割的字符串从string类型转换为char类型 char * strs = new char[str.length() + 1] ; //不要忘了 strcpy(strs, str.c_str()); char * d = new char[delim.length() + 1]; strcpy(d, delim.c_str()); char p = strtok(strs, d); while(p) { string s = p; //分割得到的字符串转换为string类型 res.push_back(s); //存入结果数组 p = strtok(NULL, d); } return res;}double getMax(vector<vector<double>>dataSet){ double MYMAX=-999; for(int i=0;i<dataSet.size();i++){ for(int j=0;j<dataSet[i].size();j++){ if(MYMAX<dataSet[i][j]){ MYMAX=dataSet[i][j]; } } } return MYMAX;}double getMin(vector<vector<double>>dataSet){ double MYMIN=999; for(int i=0;i<dataSet.size();i++){ for(int j=0;j<dataSet[i].size();j++){ if(MYMIN>dataSet[i][j]){ MYMIN=dataSet[i][j]; } } } return MYMIN;}//数据归一化//一般是x=(x-x.min)/x.max-x.minvoid guiYiHua(vector<vector<double>>&dataSet){ double MYMAX=getMax(dataSet); double MYMIN=getMin(dataSet); for(int i=0;i<dataSet.size();i++){ for(int j=0;j<dataSet[i].size();j++){ dataSet[i][j]=(dataSet[i][j]-MYMIN)/(MYMAX-MYMIN); } }}//创建测试集的数据void createTrainSet(){ fstream f(“train.txt”); //保存读入的每一行 string line; vector<string>res; int ii=0; while(getline(f,line)){ res=split(line,"\t"); vector<double>vec1; for(int i=0;i<res.size();i++){ //cout<<res[i]<<endl; char ch[MAXSIZE]; strcpy(ch,res[i].c_str()); if(i!=2){ vec1.push_back(atof(ch)); }else{ trainDataY.push_back(atof(ch)); } } trainDataX.push_back(vec1); ii++; }}//创建训练集的数据void createTestSet(){ fstream f(“test.txt”); //保存读入的每一行 string line; vector<string>res; int ii=0; while(getline(f,line)){ res=split(line,"\t"); vector<double>vec1; for(int i=0;i<res.size();i++){ //cout<<res[i]<<endl; char ch[MAXSIZE]; strcpy(ch,res[i].c_str()); if(i!=2){ vec1.push_back(atof(ch)); }else{ dataTestY.push_back(atof(ch)); } } dataTest.push_back(vec1); ii++; }}//sigmoid激活函数double sigmoid(double x){ return 1/(1+exp(-x));}//sigmoid函数的导数double dsigmoid(double x){ return x(1-x);}class NeuralNetwork{public: //输入层单元个数 int inputLayers; //隐藏层单元个数 int hidenLayers; //输出层单元个数 int outputLayers; //输入层到隐藏层的权值 //行数为输入层单元个数+1(因为有偏置) //列数为隐藏层单元个数 vector<vector<double>>VArr; //隐藏层到输出层的权值 //行数为隐藏层单元个数 //列数为输出层单元个数 vector<vector<double>>WArr;private: //矩阵乘积 void dot(const double* m1,const double* m2,double m3,int m,int n,int p){ for(int i=0;i<m;++i) //点乘运算 { for(int j=0;j<p;++j) { ((m3+ip+j))=0; for(int k=0;k<n;++k) { ((m3+ip+j))+=((m1+in+k))((m2+kp+j)); } } } } void vectorToArr1(vector<vector<double>>vec,double arr,int n){ for(int i=0;i<vec.size();i++){ for(int j=0;j<vec[i].size();j++){ //cout<<endl<<vec[i][j]<<""<<i<<""<<j<<""; ((arr+in+j))=vec[i][j]; } //cout<<endl; } } void vectorToArr2(vector<double>vec,double arr){ for(int i=0;i<vec.size();i++){ ((arr+i))=vec[i]; } } void arrToVector1(double arr,vector<double>&vec,int m){ for(int i=0;i<m;i++){ vec.push_back(((arr+i))); } } //矩阵转置 void ZhuanZhi(const doublem1,double m2,int n1,int n2){ for(int i=0;i<n1;i++){ for(int j=0;j<n2;j++){ ((m2+jn1+i))=((m1+in2+j)); } } } //验证准确率时的预测 //输入测试集的一行数据 //ArrL2为输出层的输出 //eg.当我们要分成10类的时候,输出10个数,类似于该样本属于这10个类别的概率 //我们选取其中概率最大的类别作为最终分类得到的类别 void predict(vector<double>test,double ArrL2){// for(int i=0;i<test.size();i++){// cout<<“test[i]:"<<test[i]<<endl;// } //添加转置 test.push_back(1); double testArr[1][inputLayers+1]; //转成矩阵 vectorToArr2(test,&testArr[0][0]);// for(int i=0;i<inputLayers+1;i++){// cout<<“testArr:"<<testArr[0][i]<<endl;// } double dotL1[1][hidenLayers]; double VArr_temp[inputLayers+1][hidenLayers]; vectorToArr1(VArr,&VArr_temp[0][0],hidenLayers);// for(int i=0;i<inputLayers+1;i++){// for(int j=0;j<hidenLayers;j++){// cout<<VArr_temp[i][j]<<” “;// }// cout<<endl;// } //testArr[1][inputLayers+1] dot VArr[inputLayers+1][hidenLayers] dot(&testArr[0][0],&VArr_temp[0][0],&dotL1[0][0],1,inputLayers+1,hidenLayers);// for(int i=0;i<1;i++){// for(int j=0;j<hidenLayers;j++){// cout<<dotL1[i][j]<<” “;// }// cout<<endl;// } //隐藏层输出 double ArrL1[1][hidenLayers]; //double ArrL2[1][outputLayers]; for(int i=0;i<hidenLayers;i++){ ArrL1[0][i]=sigmoid(dotL1[0][i]); //cout<<ArrL1[0][i]<<endl; } double dotL2[1][outputLayers]; double WArr_temp[hidenLayers][outputLayers]; vectorToArr1(WArr,&WArr_temp[0][0],outputLayers); //ArrL1[1][hidenLayers] dot WArr[hidenLayers][outputLayers] dot(&ArrL1[0][0],&WArr_temp[0][0],&dotL2[0][0],1,hidenLayers,outputLayers); //输出层输出 for(int i=0;i<outputLayers;i++){ //ArrL2[0][i]=sigmoid(dotL2[0][1]); ((ArrL2+i))=sigmoid(dotL2[0][i]); //cout<<(ArrL2+i)<<endl; } } int getMaxIndex(vector<double>vec){ int index=-1; double MYMAX=-999; for(int i=0;i<vec.size();i++){ //cout<<vec.size()<<”"<<endl; //cout<<i<<”::::"<<vec[i]<<endl; if(MYMAX<vec[i]){ MYMAX=vec[i]; index=i; } } return index; }public: //构造函数,传入输入层,隐藏层,输出层单元个数 //并且构造权值矩阵 NeuralNetwork(int _inputLayers,int _hidenLayers,int _outputLayers){ this->inputLayers=_inputLayers; hidenLayers=_hidenLayers; outputLayers=_outputLayers; //构造V权值矩阵 for(int i=0;i<inputLayers+1;i++){ vector<double>vec; for(int j=0;j<hidenLayers;j++){ vec.push_back((double)rand()/RAND_MAX2-1); } VArr.push_back(vec); } for(int i=0;i<hidenLayers;i++){ vector<double>vec; for(int j=0;j<outputLayers;j++){ vec.push_back((double)rand()/RAND_MAX2-1); } WArr.push_back(vec); } } //开始训练 //传入训练集,预期的y值,学习效率,以及训练迭代的次数 //这里规定输入的数据为2列的数据 void train(vector<vector<double>>dataX,vector<double>dataY,double lr=0.03,int epochs=1000000){ double arrL1[1][hidenLayers]; //将VArr由vector转成arr double VArr_temp[inputLayers+1][hidenLayers]; double hangx_temp[1][inputLayers+1]; vectorToArr1(VArr,&VArr_temp[0][0],hidenLayers); double hangxT[inputLayers+1][1]; double hangxDotVArr[1][hidenLayers]; double arrL2[1][outputLayers]; double WArr_temp[hidenLayers][outputLayers]; double arrL2_delta[1][outputLayers]; double arrL1_delta[1][hidenLayers]; double E; double dao; double dotTemp[hidenLayers][outputLayers]; double WArr_tempT[outputLayers][hidenLayers]; double arrL1T[hidenLayers][1]; double dotTempp[inputLayers+1][hidenLayers]; srand((int)time(0)); //为数据集添加偏置 //eg.当我们输入的数据集为4X2的时候,需要为其在最后添加一列偏置,让其变成一个4X3的矩阵 for(int i=0;i<dataX.size();i++){ //最后一列为偏置 dataX[i].push_back(1); } //进行权值训练更新 for(int n=0;n<epochs;n++){ //随机选取一行样本进行更新 int iii=random(dataX.size()); //cout<<“iii:"<<iii<<endl; //得到随机选取的一行数据 vector<double>hangx=dataX[iii];// for(int i=0;i<hangx.size();i++){// cout<<hangx[i]<<”"<<endl;// } //隐藏层输出 //这里先计算输入矩阵与权值矩阵的点乘,再将其输入sigmoid函数中,得到最终的输出 //eg.输入4X2的dataX,我们先加上偏置变成4X3 //选取其中的一行数据1X3 //然后计算dataX与arrV(3XhidenLayers)的dot,得到一个1XhidenLayers的矩阵// for(int ii=0;ii<inputLayers+1;ii++){// for(int jj=0;jj<hidenLayers;jj++){// cout<<VArr[ii][jj]<<"—";// cout<<VArr_temp[ii][jj]<<" “;// }// cout<<endl;// } vectorToArr2(hangx,&hangx_temp[0][0]);// for(int i=0;i<inputLayers+1;i++){// cout<<hangx[i]<<”—"<<endl;// cout<<hangx_temp[0][i]<<""<<endl;// } //hangx[1][inputLayers+1] dot VArr[inputLayers+1][hidenLayers] dot(&hangx_temp[0][0],&VArr_temp[0][0],&arrL1[0][0],1,inputLayers+1,hidenLayers); //将点乘后的值输入到sigmoid函数中 for(int k1=0;k1<hidenLayers;k1++){ arrL1[0][k1]=sigmoid(arrL1[0][k1]); //cout<<arrL1[0][k1]<<endl; } vectorToArr1(WArr,&WArr_temp[0][0],outputLayers);// for(int ii=0;ii<hidenLayers;ii++){// for(int jj=0;jj<outputLayers;jj++){// cout<<WArr_temp[ii][jj]<<endl;// }// } //arrL1[1][hidenLayers] dot WArr_temp[hidenLayers][outputLayers] dot(&arrL1[0][0],&WArr_temp[0][0],&arrL2[0][0],1,hidenLayers,outputLayers); //cout<<outputLayers<<endl; //cout<<arrL2[0][1]<<endl;// for(int k1=0;k1<outputLayers;k1++){// arrL2[0][k1]=sigmoid(arrL2[0][k1]);//// // cout<<k1<<endl;//// cout<<arrL2[0][k1]<<endl;// } //求权值的delta //根据公式计算权值更新的delta for(int k1=0;k1<outputLayers;k1++){ arrL2[0][k1]=sigmoid(arrL2[0][k1]); // cout<<k1<<endl; //cout<<“arrL2[0][k1]:"<<arrL2[0][k1]<<endl; E=dataY[iii]-arrL2[0][k1]; //cout<<“E:"<<E<<endl; dao=dsigmoid(arrL2[0][k1]); //cout<<“dao:"<<dao<<endl; arrL2_delta[0][k1]=Edao; //cout<<“arrL2_delta[0][k1]:"<<arrL2_delta[0][k1]<<endl; }// for(int k1=0;k1<outputLayers;k1++){// //计算误差// E=dataY[iii]-arrL2[0][k1];// //对L2输出的结果求导// dao=dsigmoid(arrL2[0][k1]);//// cout<<“arrL2[0][k1]:"<<arrL2[0][k1]<<endl;//// cout<<“dataY[iii]:"<<dataY[iii]<<endl;//// cout<<“E:"<<E<<endl;//// cout<<“dao:"<<dao<<endl;// //计算delta// arrL2_delta[0][k1]=Edao;// }// for(int i=0;i<outputLayers;i++){// cout<<arrL2_delta[0][i]<<endl;// } //W矩阵转置 ZhuanZhi(&WArr_temp[0][0],&WArr_tempT[0][0],hidenLayers,outputLayers);// for(int i=0;i<outputLayers;i++){// for(int j=0;j<hidenLayers;j++){// cout<<WArr_temp[j][i]<<””;// cout<<WArr_tempT[i][j]<<” “;// }// cout<<endl;// } //arrL2_delta[1][outputLayers] dot WArr_tempT[outputLayers][hidenLayers] dot(&arrL2_delta[0][0],&WArr_tempT[0][0],&arrL1_delta[0][0],1,outputLayers,hidenLayers); //乘上L1输出的导数// for(int k1=0;k1<hidenLayers;k1++){// cout<<dsigmoid(arrL1[0][k1])<<endl;// } //乘上L1输出的导数 for(int k1=0;k1<hidenLayers;k1++){ double ii=arrL1_delta[0][k1]; arrL1_delta[0][k1]=ii*dsigmoid(arrL1[0][k1]); //cout<<ii<<”"<<dsigmoid(arrL1[0][k1])<<”"<<arrL1_delta[0][k1]<<endl; } //通过上面的delta更新权值WV ZhuanZhi(&arrL1[0][0],&arrL1T[0][0],1,hidenLayers);// for(int i=0;i<hidenLayers;i++){// cout<<arrL1T[i][0]<<endl;// } //arrL1T[hidenLayers][1] dot arrL2_delta[1][outputLayers] dot(&arrL1T[0][0],&arrL2_delta[0][0],&dotTemp[0][0],hidenLayers,1,outputLayers);// for(int k1=0;k1<outputLayers;k1++){// cout<<arrL2_delta[0][k1]<<endl;// }// for(int k1=0;k1<hidenLayers;k1++){// for(int k2=0;k2<outputLayers;k2++){// cout<<dotTemp[k1][k2]<<” “;// }// cout<<endl;// }// for(int k1=0;k1<outputLayers;k1++){// cout<<arrL2_delta[0][k1]<<endl;// } for(int k1=0;k1<hidenLayers;k1++){ for(int k2=0;k2<outputLayers;k2++){ //根据学习效率进行更新 //cout<<dotTemp[k1][k2]<<endl; WArr[k1][k2]+=(lrdotTemp[k1][k2]); //cout<<“WArr[k1][k2]:"<<WArr[k1][k2]<<endl; } } //转置 ZhuanZhi(&hangx_temp[0][0],&hangxT[0][0],1,inputLayers+1);// for(int i=0;i<inputLayers+1;i++){// cout<<hangxT[i][0]<<”))"<<endl;// } //hangxT[inputLayers+1][1] dot arrL1_delta[1][hidenLayers]// for(int k1=0;k1<hidenLayers;k1++){// //double ii=arrL1_delta[0][k1];// //arrL1_delta[0][k1]=iidsigmoid(arrL1[0][k1]);// cout<<arrL1_delta[0][k1]<<” “;// } //cout<<endl; dot(&hangxT[0][0],&arrL1_delta[0][0],&dotTempp[0][0],inputLayers+1,1,hidenLayers);// for(int i=0;i<inputLayers+1;i++){// for(int j=0;j<hidenLayers;j++){// cout<<dotTempp[i][j]<<” “;// }// cout<<endl;// } for(int k1=0;k1<inputLayers+1;k1++){ for(int k2=0;k2<hidenLayers;k2++){ VArr[k1][k2]+=(lrdotTempp[k1][k2]); //cout<<"(lrdotTempp[k1][k2]):"<<(lr*dotTempp[k1][k2])<<endl; //cout<<VArr[k1][k2]<<”*****"<<endl; } } //每训练100次预测一下准确率 if(n%10000==0){ //使用测试集验证一下准确率 //存放预测返回的结果 double resultArr[1][outputLayers]; int index; //整个样本集中预测结果正确的样本个数 int num=0; //准确率 double accuracy=0; //遍历整个测试样本 for(int k1=0;k1<dataTest.size();k1++){ vector<double>result; //取测试集中的第k1行进行测试,结果保存在resultArr中 predict(dataTest[k1],&resultArr[0][0]); //将arr转成vector arrToVector1(&resultArr[0][0],result,outputLayers);// for(int kk=0;kk<result.size();kk++){// //cout<<resultArr[0][kk]<<”%%%%%%%%"<<endl;// cout<<result[kk]<<"&&&&&&&&&7”<<endl;// } //取得结果中的最大值(概率最大)的index index=getMaxIndex(result);// cout<<”**k1:"<<k1<<endl;// cout<<"**index:"<<index<<endl;// cout<<"**Y:"<<dataTestY[k1]<<endl; if(index==dataTestY[k1]){// cout<<“k1:"<<k1<<endl;// cout<<“index:"<<index<<endl;// cout<<“Y:"<<dataTestY[k1]<<endl; num++; } } accuracy=(double)num/dataTestY.size(); //if(num>5)cout<<“num:!!!!!!!!!!!!!!!!!!!!!!!111”<<num<<endl; cout<<“epoch: “<<n<<”, “<<“accuracy: “<<accuracy<<endl; } } }};#endif训练效果 ...

April 20, 2019 · 4 min · jiezi

对话阿里云Alex Chen:下一代存储应如何面对云转型?

摘要: 如何定义下一代存储标准?在阿里云智能存储产品资深总监Alex Chen看来,其本质必须具备以下四个特性:安全稳定、优化、无缝上云、智能。数字经济"乘云而上"。十年前,阿里云开始自主研发云计算操作系统飞天之路,开启了中国云时代;十年后,阿里云在中国市场份额超过2-8名总和,培育了整个中国云计算市场,数字经济在云上蓬勃发展。十年前,EMC、NetApp、IBM等国际独立存储大厂称霸市场,中国企业存储市场被国际寡头瓜分,一本万利;十年后,中国存储市场国产率超过50%,Dell EMC、NetApp、Commvault、Veritas都紧紧包围阿里云构建合作伙伴生态,云上数字经济成为了企业存储走向新的发展阶段的原动力。如果说云计算是数字经济时代发展的新范式,那么,存储作为数字化基础架构的核心,将成为支撑数字化到智能化转型升级的基石。尤其在混合云大势得道的今天,存储架构应对不同介质、技术、应用的演进升级,存储系统对云和云上应用的支撑能力,以及对海量数据的智能化分析和管理,都成为了下一代存储的核心考量标准。软件定义、分布式、融合、云资源化、两地三中心……这些技术名词几乎占据了存储热搜榜,在面向云的数字化和智能化的转型风口,未来存储之路如何发展?如何定义下一代存储标准?在阿里云智能存储产品资深总监Alex Chen看来,其本质必须具备以下四个特性:安全稳定、优化、无缝上云、智能。更安全更稳定数据是企业最重要的资产,存储是数据的载体,数据安全对存储的要求不言而喻。云环境下,数据存储是由大量数据存储节点构成分布式数据中心,通过虚拟化拓展了存储容量并提高存储和读取数据性能,让用户可以充分享受高效、稳定的存储服务。但同时,数据的加密存储、数据隔离、数据迁移、数据安全审计等环节也都考验着云存储的安全可靠性。在这点上,任何云厂商都也不例外。Alex介绍,打造更高数据安全稳定标准是阿里云始终坚持的首要目标。在安全方面,阿里云存储产品具备全面的静态数据加密能力。以对象存储(OSS)为例,提供包括KMS密钥、BYOK密钥、OSS托管密钥完成服务端数据加密和客户端线下加密等5种加密方式,也是中国首家通过Cohasset Associates审计认证,符合美国证券交易委员会(SEC)和金融业监管局(FINRA)合规要求的云厂商,已成功在海外服务国际金融行业客户,此举也标志着阿里云已实现合规方面的里程碑式建设。在稳定性方面,经过十年的技术积累和沉淀,阿里云自研飞天大规模的分布式存储引擎已经换代升级为盘古2.0;基于盘古2.0,整个阿里巴巴今天有60%-70%的流量跑在公共云上,扎实的底层存储系统支撑了十年“双11”大规模高并发洪峰考验,也为阿里云成为最佳实践的云打下良好基础。更优化不同应用需要不一样的存储架构,对IOPS、延时、吞吐的要求也自然不同,没有一个存储产品可以做到完全覆盖所有的应用场景。在阿里云的产品设计上,针对不同场景下,提供满足用户定制化需求的最优存储类型服务。在数据库和实时业务分析场景下,阿里云推出全球百万级IOPS的企业级ESSD云盘,相比于SSD云盘分别提升40倍性能和降低70%读写延时,在实际的业务场景测试下,以MySQL和PostgreSQL为例,采用ESSD云盘可获得3-4倍的TPS性能提升。此外,ESSD云盘支持不停机扩展容量、不停机提高IO读写性能上限、数据加密等高级数据服务功能,给客户在弹性、安全等方面带来了更多的技术红利。在容器共享存储、动态网站、DevOps开发测试的小文件读写场景下,阿里云推出文件存储NAS极速型规格,提供百微秒级延时,同时提供文件系统级快照,以提升数据安全性。在大数据和离线数据分析、机器学习场景下,阿里云发布全球首个云原生文件存储HDFS,无需关心和维护底层存储,降低TCO,真正解决了传统自建HDFS系统计算存储耦合的问题,使得真正实现了计算存储分离,实现存储计算分离后分别拥有享受可线性扩展的吞吐能力和免运维的快速弹性伸缩能力。在HPC、人工智能、基因生命科学场景下,阿里云发布高性能文件存储CPFS,提供针对亿级文件,提供TB/s级超高吞吐的并行文件存储服务,并与阿里云计算生态无缝对接,满足计算密集型场景应用的高性能要求。无缝上云根据IDC公开报告显示,85%的大型企业表示不会将所有数据存储一地,而是会采用更多方式且适合自己的方法,在混合云环境中实现数据在其整个生命周期中的流转。Alex认为,通过混合云IT架构无缝上云已成为企业应用的新常态,混合云存储将成为架起本地数据中心和公共云的桥梁,开启传统企业用户上云的新路径。在3月的阿里云北京峰会上,阿里云发布全新Apsara SA系列混合云存储阵列,实现了本地数据中心架构和公共云存储的无缝结合,融合了IP SAN、FC SAN、NAS和OSS多种存储协议,提供异构存储虚拟化、双活容灾、混合云协同计算、在线多控横向扩展等企业级存储特性,支持端到端数据加密,满足数据库,虚拟化,文件共享,数据分析等各类场景下企业客户对数据存储和灾备等需求。更智能如果说单纯的卖存储、安全、计算等能力是云计算的1.0时代,那么以智能化为核心的2019年,则是阿里云进入2.0时代的标志。Alex表示,阿里云存储在第一阶段完成了以弹性扩展、灵活高效、降低成本为核心的存储基础服务,在第二阶段,除了支撑集团100%业务上云外,还要帮助更多企业实现数据管理的数字化和智能化,不仅是存储,更是数据智能管理平台。针对不同业务场景,阿里云发布了智能媒体管理视频型实例,提供场景化封装数据智能分析管理,为云上文档、图片、视频提供一站式数据处理、分析、检索等智能管理体验。阿里云日志服务是面向日志类数据的智能化一站式平台,针对AIOps场景,新增面向趋势预测、异常发现、智能聚类、根因分析(推导)等4个高频场景系列函数,提升DevOps分析与诊断的效率,该功能已通过阿里巴巴“双11”实战验证。后记2018年底,阿里云正式升级为阿里云智能。3个月后的阿里云北京峰会上,阿里云首次对外公布了云的下一阶段发展定位和云到云智能的思考。在对Alex Chen的采访中,这位曾在IBM存储领域有着19年丰富经历的专家同时坦言,“安全稳定、优化、无缝上云、智能”不仅是云时代下一代存储的本质性特点,是阿里云未来几年存储创新的主方向,也将是企业存储厂商产品服务能力比拼的主赛道。2018年,阿里云已实现完整的存储基础服务,丰富的数据服务,多元的应用场景的产品布局,成功签约5家渠道代销商,并与合作伙伴在产品层面打造混合云解决方案,开拓企业级存储市场。不难预见,2019年阿里云将持续围绕下一代存储理念持续技术创新,不断拓展存储边界,深耕数据密集型细分行业,并同更多的合作伙伴一起构建企业级存储生态,这同时也意味着以阿里云为代表的云计算厂商也真真正正的进入企业级存储市场竞争格局中。而在这样的2019年,无论对于存储市场还是用户,都是好事。本文作者:株莉阅读原文本文为云栖社区原创内容,未经允许不得转载。

April 16, 2019 · 1 min · jiezi

语义分割浅析

背景对图像而言,常见的任务是:图像分类:提取类别特征,如:VGG19网络目标检测:提取类别,位置特征,如:YOLO网络语义分割(实例分割):提取类别,位置特征,针对每个像素,如:Deeplab网络我们知道,在做图像分类的时候,一般会在模型的最后添加全连接层+softmax用于预测。但是,全连接层会把卷积学习到的类别,位置特征抽象成一维的概率信息,可以识别整个图片的类别,不能标识每个像素的类别。因此,为了保留图像特征我们将全连接层替换为卷积层。这样,模型的输出不再是一维,而是二维的图。由于特征图经过一系列的卷积和池化后(保持特征不变性,增大感受野,节省计算资源等)造成分辨率降低,丢失大量细节和边缘信息,因此我们需要通过一定的手段还原原图分辨率。不同的模型会采取不同的还原方式,图上以FCN为例,采用反卷积还原分辨率并使用加和的方式找回下采样阶段丢失的信息,直接把编码阶段的特征图加到解码阶段中来。基石FCN模型FCN阐释了如何将CNN应用到语义分割问题上,是深度学习应用此问题的基石。文章开始,我们谈到模型最后的全连接层不适用与分割任务,需要替换成卷积层,以此获取二维的特征图然后接softmax,对每个像素点进行分类。先通过卷积,池化下采样,然后上采样还原分辨率。上采样一般有两种方式:双线性插值(Deeplab),反卷积(FCN)。Google DeepLab v1DeepLab是针对语义分割任务提出的模型,主要使用DCNN(深度卷积网络),CRF(条件随机场),空洞卷积做像素级预测。DCNN在语义分割中存在两个主要问题:下采样带来的分辨率下降,细节信息丢失平移不变性,限制了定位精度针对以上问题,Deeplab采用空洞卷积扩大感受野,获取更多的上下文信息。使用全连接条件随机场(DenseCRF)提高模型捕获细节的能力。DCNN以VGG16模型为后端网络,将FC层全部转为卷积层,改成全卷积网络形式。最后的两个池化层不下采样,通过2或4的采样率空洞卷积对特征图扩大感受野,缩小步幅。模型训练的时候讲VGG16的权重做微调,损失函数取输出特征图ground truth下采样8倍做交叉熵和;测试时取输出图双线性上采样得到的结果(DCNN预测物体的位置是粗略的,没有确切的轮廓,针对此问题采用全连接的CRF提升分割精度)。Google DeepLab v2DeepLab v2相比DeepLab v1基础层由VGG16改为ResNet,添加多尺度和ASPP模块得到更好的分割结果。空洞卷积作为密集预测的强大工具,可以扩大感受野,在不增加参数量和计算量的同时获取更多的上下文。提出ASPP(空洞空间卷积池化金字塔),并行的采用多采样率的空洞卷积进行探测,以多个比例捕获对象及图像上下文。组合DCNN和概率模型,改善分割边界结果。模型运行步骤:输入经过改进的DCNN(带空洞卷积和ASPP模块)通过双线性插值恢复原图大小(FCN采用反卷积)通过全连接的CRF细化预测结果,得到最终输出Google DeepLab v3DeepLab v3相比DeepLab v2:重新讨论了空洞卷积的使用,让我们在级联模块和空间金字塔池化的框架下,能够获取更大的感受野从而获取多尺度信息。改进ASPP模块,由不同采样率的空洞卷积和BN层组成。使用大采样率的3x3空洞卷积,因为图像边界响应无法捕获远距离信息,会退化为1x1卷积,因此将图像级特征融合到ASPP模块。没有使用CRF做后期优化处理Google DeepLab v3+DeepLab v3+采用编码器,解码器结构,通过使用解码器模块改善物体边缘的分割结果,还尝试使用Xception作为编码器。如图所示,空间金字塔池化可以池化不同分辨率的特征图来捕获上下文信息。编码器解码器结构可以捕获锋利的边界。先4倍上采样,然后与编码器中的特征图合并,最后4倍上采样恢复到原始图像大小。encoder就是DeepLab V3,通过修改ResNet101最后两(一)个block的stride,使得output stride为8(16)。之后在block4后应用改进后的Atrous Spatial Pyramid Pooling,将所得的特征图concatenate用1×1的卷积得到256个通道的特征图。在decoder中,特征图首先上采样4倍,然后与encoder中对应分辨率低级特征concatenate。在concatenate之前,由于低级特征图的通道数通常太多(256或512),而从encoder中得到的富含语义信息的特征图通道数只有256,这样会淡化语义信息,因此在concatenate之前,需要将低级特征图通过1×1的卷积减少通道数。在concatenate之后用3×3的卷积改善特征,最后上采样4倍恢复到原始图像大小。U-Net网络U-Net网络可以利用较少的数据集进行端到端训练,医学领域应用较多(医学领域的标注数据获取成本很高)。为了更有效的利用标注数据,采用数据增强的方法(训练样本进行随机弹性形变)网络由收缩路径获取上下文信息以及一个对称的扩张路径用以精确定位。如图所示,网络结构由contracting path和expansive path组成。contracting:含有重复结构,每个都有2个3x3卷积层,relu层和2x2最大池化层每一次下采样都将特征通道数加倍expansive path:每一步都使用反卷积,每次反卷积后将通道数量减半,特征图大小加倍。反卷积后,将反卷积的结果与contracting path中对应的步骤的特征图拼接起来对拼接后的map再进行2次3*3卷积最后一层卷积核大小为1x1,将64通道的特征图转为特定类别数量

April 16, 2019 · 1 min · jiezi

Searching with Deep Learning 深度学习的搜索应用

本文首发于 vivo 互联网技术微信公众号 https://mp.weixin.qq.com/s/wLMvJPXXaND9xq-XMwY2Mg作者:Eike Dehling翻译:杨振涛 本文由来自 Textkernel 的软件与数据工程师 Eike Dehling 于2018年10月23日发布与其Linkedin 的 pulse 上,已获得翻译授权。英文原文链接:https://www.linkedin.com/pulse/searching-deep-learning-eike-dehling/ 目录: 一、Fast Nearest Neighbours 二、Elasticsearch 插件 三、集成工作 四、结论最近我在帮一个数据科学家同事工程化一个基于深度学习模型的搜索系统。他们的项目是关于在文档嵌入应用深度学习模型,然后使用嵌入向量到我们的搜索系统中来查找相似文档。一个文档嵌入本质上其实是一个(长的)数值数组,查找相似文档就相当于查找其他与其较相近的(长的)数值数组;可以采用诸如欧氏距离等来衡量相似性。可以借此来查找相似文档,但是因为不是直接基于关键词而是基于“嵌入”,所以可以自动获得与同义词扩展相媲美的效果。它会查找相关文档,即使它们使用不同的关键词,因此能比关键词检索表现更好。已经有解决这种问题的工具了,比如 facebook 的 FAISS 库(https://github.com/facebookresearch/faiss)。这个类库速度非常快,并且支持多种智能方法使用嵌入向量实现快速检索。不过它不能友好地集成到类似 Elasticsearch 这样的搜索引擎中。对于 Elasticsearch 来说,也有一些插件(https://github.com/muhleder/elasticsearch-vector-scoring)提供了相似度计算功能,但是它们的速度并不怎么样,因为它们只计算了向量相似度而没有做过滤。所以我们自己动手实现了更好的解决方案。一、Fast Nearest Neighbours为了更快速检索通常会使用各种“索引”,这种数据结构支持高效地过滤出相关的匹配,而无需单独评估每一个匹配。基于关键词的检索一般使用“倒排索引”;基于地理位置的检索,一般使用一种叫做 KD树 的数据结构。我们也需要诸如此类的机制来快速过滤出最相关的匹配,因此我们只需要在这个较小的集合上计算精确得分。这一点非常重要,因为在一个高维向量的超大集合上计算距离,是代价非常高昂(慢)的操作。上文提到的 FAISS 库提供了多种方式来解决这个问题:PCA 降维K 均值聚类局部敏感哈希可能还有其他我不知道方法这些方法中的每一种都能实现高效的索引方法,因此可以快速地筛选出较近邻的文档,然后通过计算精确的距离来查找最近邻文档。在降维以后就可以使用 KD树,聚类或者局部敏感哈希后也可以使用倒排索引。上图揭示了如何通过过滤数据集来加速计算,需要计算精确距离的文档数与计算时间之间是线性关系;同时也说明了高效地过滤掉不相似文档多么重要。当然所有这些方法都是有可能在 Elasticsearch 里得到实现的,其优点是便于和其他检索系统集成。届时就可以组合使用关键词查询或其他基于深度学习的查询结果了。实验表明在我们的数据集上,结合了 PCA 降维后再使用 KD 树索引,能带给我们速度和精度的最佳y组合。上图揭示了缩小数据集是如何影响结果精确度的。能够看到,过滤得太狠意味着我们会丢失一些最近邻文档;而如果过滤掉 50k 到 75k 的文档,就可以找到所有的最近邻文档,同时计算时间只占暴力计算所有距离的很小一部分。二、Elasticsearch 插件在 Lucene 即 Elasticsearch的底层类库中,KD树的数据结构已经实现了,但还没有通过 Elasticsearch 的 API 暴露出来。已经有插件可以计算精确的向量距离,所以我们只需要开发一个小插件来支持使用这种索引结构即可。参见这里:https://github.com/EikeDehlin…三、集成工作现在集成工作只是相当于把拼图图片按照正确的顺序拼到一起:安装 Elasticsearch 插件PCA降维(Python/sklearn 或者 Java/Smile)索引降维后的完整向量到 Elasticsearch 中(以及其他必要属性)整装待发!安装插件、创建索引以及添加文档请参考这里(https://github.com/EikeDehlin…。完成这些步骤后,现在就可以使用我们的嵌入向量了!请注意 pca_reduced_vector 上的范围查询,这才是我们新插件起到的作用。四、结论我们展示了如何应用深度学习向量来实现高效的搜索。这一方法适用于想要寻找相似文档而普通关键词查询不够好的任何应用场景。其中的嵌入向量,可以使用诸如 doc2vec 等来实现。更多内容敬请关注 vivo 互联网技术 微信公众号注:转载文章请先与微信号:labs2020 联系。 ...

April 16, 2019 · 1 min · jiezi

贾扬清:我对人工智能方向的一点浅见

阿里妹导读:作为 AI 大神,贾扬清让人印象深刻的可能是他写的AI框架Caffe ,那已经是六年前的事了。经过多年的沉淀,成为“阿里新人”的他,对人工智能又有何看法?最近,贾扬清在阿里内部分享了他的思考与洞察,欢迎共同探讨、交流。贾扬清,浙江上虞人,毕业于清华大学自动化系,在加州大学 Berkeley 分校获得计算机博士学位,目前担任阿里计算平台掌门人。最近几年深度学习的流行,大家一般认为是从2012年 AlexNet 在图像识别领域的成功作为一个里程碑。AlexNet 提升了整个业界对机器学习的接受程度:以前很多机器学习算法都处在“差不多能做 demo ”的程度,但是 AlexNet 的效果跨过了很多应用的门槛,造成了应用领域井喷式的兴趣。当然,任何事情都不是一蹴而就的,在2012年以前,很多成功的因素已经开始逐渐显现:2009年的 ImageNet 数据库奠定了大量标注数据的基础;2010年开始,IDSIA 的 Dan Ciresan 首次用 GPGPU 进行物体识别;2011年,北京的 ICDAR 大会上,神经网络在中文离线识别上大放异彩。就算是 AlexNet 中用到的ReLU层,早在2001年神经科学的文献中就有提及过。所以,一定程度上说,神经网络的成功也是一个水到渠成的过程。2012年以后的事情,大家可以读到很多,这里就不再赘述。成功与局限在看待神经网络成功的同时,我们也要进一步深挖其背后的理论背景和工程背景,为什么神经网络和深度学习在几十年前失败,但是现在却成功了?它成功的原因是什么?而它的局限又在什么地方?我们这里只能片面地说几个重点:成功的原因,一点是大数据,一点是高性能计算。局限的原因,一点是结构化的理解,一点是小数据上的有效学习算法。大量的数据,比如说移动互联网的兴起,以及 AWS 这样低成本获得标注数据的平台,使机器学习算法得以打破数据的限制;由于 GPGPU 等高性能运算的兴起,又使得我们可以在可以控制的时间内(以天为单位甚至更短)进行 exaflop 级别的计算,从而使得训练复杂网络变得可能。要注意的是,高性能计算并不仅限于 GPU ,在 CPU 上的大量向量化计算,分布式计算中的 MPI 抽象,这些都和60年代就开始兴起的 HPC 领域的研究成果密不可分。但是,我们也要看到深度学习的局限性。今天,很多深度学习的算法还是在感知这个层面上形成了突破,可以从语音、图像,这些非结构化的数据中进行识别的工作。在面对更加结构化的问题的时候,简单地套用深度学习算法可能并不能达到很好的效果。有的同学可能会问为什么 AlphaGo 和 Starcraft 这样的算法可以成功, 一方面,深度学习解决了感知的问题,另一方面,我们也要看到还有很多传统的非深度学习算法,比如说 Q-learning 和其他增强学习的算法,一起支撑起了整个系统。而且,在数据量非常小的时候,深度学习的复杂网络往往无法取得很好的效果,但是很多领域,特别是类似医疗这样的领域,数据是非常难获得的,这可能是接下去的一个很有意义的科研方向。接下去,深度学习或者更广泛地说,AI 这个方向会怎么走?我个人的感觉,虽然大家前几年一直关注AI框架,但是近年来框架的同质化说明了它不再是一个需要花大精力解决的问题,TensorFlow 这样的框架在工业界的广泛应用,以及各种框架利用 Python 在建模领域的优秀表现,已经可以帮助我们解决很多以前需要自己编程实现的问题,因此,作为 AI 工程师,我们应该跳出框架的桎梏,往更广泛的领域寻找价值。挑战往上走,我们会遇到产品和科研的很多新挑战,比如说:传统的深度学习应用,比如说语音、图像等等,应该如何输出产品和价值?比如说,计算机视觉现在基本还是停留在安防这个层面上,如何深入到医疗、传统工业,甚至社会关爱(如何帮助盲人看见这个世界?)这些领域,是不仅需要技术,还需要产品的思考的。除了语音和图像之外,如何解决更多问题。在阿里和很多互联网企业中有一个“沉默的大多数”的应用,就是推荐系统:它常常占据了超过80%甚至90%的机器学习算力,如何将深度学习和传统推荐系统进一步整合,如何寻找新的模型,如何对搜索和推荐的效果建模,这些可能没有像语音和图像那么为人所知,却是公司不可缺少的技能。即使在科研方向,我们的挑战也刚刚开始:Berkeley 的教授 Jitendra Malik 曾经说,“我们以前是手工调算法,现在是手工调网络架构,如果囿于这种模式,那人工智能无法进步”。如何走出手工调参的老路,用智能提升智能,是个非常有意思的问题。最开始的 AutoML 系统依然停留在用大量算力暴力搜索模型结构的层面上,但是现在各种更高效的 AutoML 技术开始产生,这是值得关注的。机会往下走,我们会发现传统的系统、体系结构等知识,计算机软件工程的实践,会给 AI 带来很多新的机会,比如说:传统的 AI 框架都是手写高性能代码,但是模型如此多变,新的硬件平台层出不穷,我们应该如何进一步提升软件效率?我们已经看到有通过编译器技术和传统的人工智能搜索方法来反过来优化AI框架,比如 Google 的 XLA 和华盛顿大学的 TVM,这些项目虽然处于早期,但是已经展现出它们的潜力。平台如何提升整合能力。在开源领域,大家的做法是一个人,一台机器,几个 GPU ,训练比较学院派的模型。但是在大规模应用中,我们的数据量非常大,模型非常复杂,集群还会出现各种调度的挑战(能不能一下子就要求256个 GPU ?计算资源是否可以弹性调度?),这些对于我们自己的机器学习平台,以及云上向客户提供的服务,都提出了非常多的挑战。如何进行软硬件的协同设计。在深度学习的计算模式开始逐渐固化的时候(比如说 CNN ),新硬件和特殊硬件(比如 ASIC )的优势就开始体现出来了。如何实现软硬件的协同设计,防止“硬件出来了,不知道怎么写程序”或者“模型已经变了,硬件一出来就过时了”这样的问题,会是将来几年中很大的方向。人工智能是一个日新月异的领域,我们有一个笑话说,2012年的科研成果,现在说起来都已经是上古时代的故事了。快速的迭代带来的大量机遇和挑战是非常令人兴奋的,无论是有经验的研究者还是新学 AI 的工程师,在当今云化,智能化的年代,如果能快速学习并刷新算法和工程的各种挑战,就可以通过算法创新引领并且赋能社会各个领域。这方面,人工智能领域开源开放的各种代码,科研文章和平台给大家创造了比以前更容易的入门门槛,机遇都掌握在我们自己手中。本文作者: 贾扬清阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。 ...

April 15, 2019 · 1 min · jiezi

神经网络和深度学习

课程是我自己在学的,所以笔记会不断完善…第一周What you’ll learnCourses in this sequence (Specialization):Neural Networks and Deep LearningImproving Deep Neural Networks: Hyperparameter tuning, Regularization and OptimizationStructuring your Machine Learning projectConvolutional Neural NetworksNatural Language Processing: Building sequence models1.2 什么是神经网络?如果你有6个房子价格的数据,会想到 linear regression 同时价格不会为负,所以得到了蓝色函数,拟合的挺好,这里的蓝色函数可以看成一个非常简单的神经网络。这个神经网路输入房子的大小(size)通过你的神经元(neuron)输出了价格(price)。在深度学习中,会经常看见这个函数,从水平线开始,然后上升,叫做 ReLU函数 (Rectified linear unit,修正线性单元)修正认为是取不小于0的值 大一些的神经网络就是由这些神经元堆积起来。对于同样的问题,我们考虑更多的条件:1.由房屋面积大小和卧室可以推断出家庭大小2.由邮编可以推断出步行程度(walkability),即是否可以步行去超市, 步行去学校3.由邮编和富有程度可以推断出附近学校的质量4.由家庭大小加步行便利程度加附近学校质量可以推断出房屋的价格这就是一个大一些的神经网络,中间的小圆圈就是一个个的 函数,有可能是 ReLU 函数,也有可能是其他的线性或者不那么线性的函数。中间的圆圈(一共四个)叫做 隐藏单元(hidden units) 每个隐藏单元的输入都同时来源于四个输入,我们会将输入层和隐藏单元全连接,并不告诉神经网络个别输入只影响部分隐藏单元,而是让神经网络自己去决定。1.3用神经网络进行无监督学习Supervised Learning在房屋预测和在线广告用的是标准神经网络(standard NN)在图像领域,通常使用的是CNN对于序列问题经常使用RNN (recurrent neural network)语言,也是序列问题,要用到更复杂的RNNs对于自动驾驶,雷达信息,面对更复杂的信息,用到混合神经网络后续讲解图片,并有实现。对于监督学习 数据的分类 ,分为 结构化数据 和 非结构化数据结构化数据(Structured Data) 指的是数据库中的数据,可以存储在数据库中。非结构化数据(Unstructured Data) 指的是类似于语音数据、图像数据、文本数据等,通常处理所针对的是一个像素、文本中的一个单词,相比结构化的数据,更难让计算机理解。这里的应用是可以结合的,可以在神经网络中同时应用结构话数据和非结构化数据。1.4为什么深度学习最近几年才流行起来?深度学习已经进行了20多年来了,为什么是在20年后的今天才得到巨大的发展?横坐标代表数据的大小(指的是带标签的数据,(x,y)x是数据,y是该数据的标签),纵坐标表示算法的表现。在本堂课中都会用m表示数据集的大小、样本的数量红线代表传统学习算法(SVM,logistic regression等等),这些算法会在数据达到一定规模的时候进入平台期,表现并没有提升很多甚至不会再提升了,无法处理大规模数据。如果使用一个小型神经网络,那么得到的是黄线中型神经网络是蓝线绿线表示大型神经网络,表现的非常好。此时的神经网络表现好的原因有两点,也只有在这两点的支持下,才会有如此的表现:1.我们在一个数据爆炸的时代,科技进步带来的数据量可以支撑神经网络2.我们的神经网络足够大,意味着更多的神经元,更多层所以现在,如果想要更好的结果,要么训练一个更大的神经网络,要么投入更多的数据,但这也只能在一定程度上起作用(数据量增多和神经网络变大都需要更多的计算时间)。数据的发展,cpu、Gpu的发展提高了计算力,新算法的出现,推动了深度学习的进程。算法的更新,也是为了让神经网络运行的更快。一个较为突破性的一点就是从sigmoid函数变成了ReLU函数,sigmoid函数的一个缺点就是在这两点(图中两个箭头所指)梯度会接近于0,学习会变得很慢,因为此时参数变化很慢。通过改变activation function(激活函数)为ReLU函数,对于所有大于0的输入,梯度输出都是1 。所以通过更换函数梯度下降会运行的更快。这是简单的算法创新的例子。

April 14, 2019 · 1 min · jiezi

Machine Learning Mastery 博客文章翻译:深度学习与 Keras

目录Keras 中神经网络模型的 5 步生命周期在 Python 迷你课程中应用深度学习Keras 深度学习库的二元分类教程如何用 Keras 构建多层感知器神经网络模型如何在 Keras 中检查深度学习模型10 个用于 Amazon Web Services 深度学习的命令行秘籍机器学习卷积神经网络的速成课程如何在 Python 中使用 Keras 进行深度学习的度量深度学习书籍深度学习课程你所知道的深度学习是一种谎言如何设置 Amazon AWS EC2 GPU 以训练 Keras 深度学习模型(分步)神经网络中批量和迭代之间的区别是什么?在 Keras 展示深度学习模型训练历史基于 Keras 的深度学习模型中的dropout正则化评估 Keras 中深度学习模型的表现如何评价深度学习模型的技巧小批量梯度下降的简要介绍以及如何配置批量大小在 Keras 中获得深度学习帮助的 9 种方法如何使用 Keras 在 Python 中网格搜索深度学习模型的超参数用 Keras 在 Python 中使用卷积神经网络进行手写数字识别如何用 Keras 进行预测用 Keras 进行深度学习的图像增强8 个深度学习的鼓舞人心的应用Python 深度学习库 Keras 简介Python 深度学习库 TensorFlow 简介Python 深度学习库 Theano 简介如何使用 Keras 函数式 API 进行深度学习Keras 深度学习库的多类分类教程多层感知器神经网络速成课程基于卷积神经网络的 Keras 深度学习库中的目标识别流行的深度学习库用深度学习预测电影评论的情感Python 中的 Keras 深度学习库的回归教程如何使用 Keras 获得可重现的结果如何在 Linux 服务器上运行深度学习实验保存并加载您的 Keras 深度学习模型用 Keras 逐步开发 Python 中的第一个神经网络用 Keras 理解 Python 中的有状态 LSTM 循环神经网络在 Python 中使用 Keras 深度学习模型和 Scikit-Learn如何使用预训练的 VGG 模型对照片中的物体进行分类在 Python 和 Keras 中对深度学习模型使用学习率调度如何在 Keras 中可视化深度学习神经网络模型什么是深度学习?何时使用 MLP,CNN 和 RNN 神经网络为什么用随机权重初始化神经网络?贡献指南请您勇敢地去翻译和改进翻译。虽然我们追求卓越,但我们并不要求您做到十全十美,因此请不要担心因为翻译上犯错——在大部分情况下,我们的服务器已经记录所有的翻译,因此您不必担心会因为您的失误遭到无法挽回的破坏。(改编自维基百科)需要校对:术语语法格式欢迎大家提交 PR,贡献者会写在每个文档的开头处。关于我们我们是一个大型开源社区,旗下 QQ 群共 9000 余人,Github Star 数量超过 20k 个,在所有 Github 组织中排名 110,网站日 uip 超过 4k,拥有 CSDN 博客专家和简书程序员优秀作者认证。我们组织公益性的翻译活动、学习活动和比赛组队活动,并和 DataWhale、LinuxStory 等国内著名开源组织保持良好的合作关系。与商业组织不同,我们并不会追逐热点,或者唯利是图。作为公益组织,我们将完成项目放在首要位置,并有足够时间把项目打磨到极致。我们希望做出广大 AI 爱好者真正需要的东西,打造真正有价值的长尾作品。【主页】apachecn.org【归档】home.apachecn.org【社区】bbs.apachecn.org【Github】@ApacheCN自媒体平台微博:@ApacheCN知乎专栏:AILearning公众号:ApacheCNCSDN | OSChina | 博客园简书 | 搜狐号 | bilibili 专栏We are ApacheCN Open Source Organization, not ASF! We are fans of AI, and have no relationship with ASF!合作 or 侵权,请联系 <apachecn@163.com> | 请抄送一份到 <wizard.z@foxmail.com> ...

April 11, 2019 · 1 min · jiezi

机器学习导图系列(5):机器学习模型及神经网络模型

机器学习导图系列教程旨在帮助引导开发者对机器学习知识网络有一个系统的概念,其中有些具体释义并未完善,需要开发者自己探索才能对具体知识有深入的掌握。本项目灵感来自Daniel Formoso的github开源项目。本文作者对其项目进行翻译、整理、批注等二次创作,其中不乏生僻的数学名词,对于没有留过学的作者来说费了很多功夫。我又将导图整理成了知识卡片,方便大家查看。由于机器学习的知识网络很大,导致完整的导图过大,文章中的图片可能经过压缩,如需完整图片可查看github项目machine-learning-mindmap-cn下载高清原图。本系列还在持续创作中终于完成了,你的点赞、留言、star都会成为我持续创作的动力。machine-learning-mindmap-cn: https://github.com/caiyongji/…机器学习导图系列分为五大模块。机器学习数据处理机器学习概念机器学习过程机器学习算法机器学习模型及神经网络模型机器学习模型回归贝叶斯降维实例决策树聚类神经网络神经元与层批量标准化与学习率初始化权重反向传播激活函数最后呼……终于写完了。接下来我有时间的话会连载《深度学习》系列的知识卡片,欢迎大家继续关注。

April 11, 2019 · 1 min · jiezi

机器学习导图系列(4):算法(含61公式)

机器学习导图系列教程旨在帮助引导开发者对机器学习知识网络有一个系统的概念,其中有些具体释义并未完善,需要开发者自己探索才能对具体知识有深入的掌握。本项目灵感来自Daniel Formoso的github开源项目。本文作者对其项目进行翻译、整理、批注等二次创作,其中不乏生僻的数学名词,对于没有留过学的作者来说费了很多功夫。我又将导图整理成了知识卡片,方便大家查看。由于机器学习的知识网络很大,导致完整的导图过大,文章中的图片可能经过压缩,如需完整图片可查看github项目machine-learning-mindmap-cn下载高清原图。本系列还在持续创作中,你的点赞、留言、star都会成为我持续创作的动力。machine-learning-mindmap-cn: https://github.com/caiyongji/…机器学习导图系列分为五大模块。机器学习数据处理机器学习概念机器学习过程机器学习算法机器学习模型及神经网络模型线性代数统计优化正则化函数概率分布信息论密度估计

April 10, 2019 · 1 min · jiezi

机器学习导图系列(3):过程

机器学习导图系列教程旨在帮助引导开发者对机器学习知识网络有一个系统的概念,其中有些具体释义并未完善,需要开发者自己探索才能对具体知识有深入的掌握。本项目灵感来自Daniel Formoso的github开源项目。本文作者对其项目进行翻译、整理、批注等二次创作,其中不乏生僻的数学名词,对于没有留过学的作者来说费了很多功夫。我又将导图整理成了知识卡片,方便大家查看。由于机器学习的知识网络很大,导致完整的导图过大,文章中的图片可能经过压缩,如需完整图片可查看github项目machine-learning-mindmap-cn下载高清原图。本系列还在持续创作中,你的点赞、留言、star都会成为我持续创作的动力。machine-learning-mindmap-cn: https://github.com/caiyongji/…机器学习导图系列分为五大模块。机器学习数据处理机器学习概念机器学习过程机器学习算法机器学习模型及神经网络模型问题方向数据模型-成本函数-优化-调参-结果和基准-扩展部署和运营-基础架构最后你随手就是一个赞。

April 9, 2019 · 1 min · jiezi

机器学习导图系列(2):概念

机器学习导图系列教程旨在帮助引导开发者对机器学习知识网络有一个系统的概念,其中具体释义并未完善,需要开发者自己探索才能对具体知识有深入的掌握。本项目灵感来自Daniel Formoso的github开源项目。本文作者对其项目进行翻译、整理、批注等二次创作,其中不乏生僻的数学名词,对于没有留过学的作者来说费了很多功夫。我又将导图整理成了知识卡片,方便大家查看。由于机器学习的知识网络很大,导致完整的导图过大,文章中的图片可能经过压缩,如需完整图片可查看github项目machine-learning-mindmap-cn下载高清原图。本系列还在持续创作中,你的点赞、留言、star都会成为我持续创作的动力。machine-learning-mindmap-cn: https://github.com/caiyongji/…机器学习导图系列分为五大模块。机器学习数据处理机器学习概念机器学习过程机器学习算法机器学习模型及神经网络模型动机性能分析调参类型种类分类学习方法分类学选择标准库最后你随手就是一个赞。

April 8, 2019 · 1 min · jiezi

自己动手玩转深度学习项目

摘要: 深度学习项目何其多?对于入门而言,合适且有趣的项目能产生积极的影响,本文总结了一份计算机视觉领域的几个有趣项目,感兴趣的可以动手尝试一下。自从2012年AlexNet网络在ImageNet挑战赛上取得巨大成功之后,计算机视觉和深度学习等领域再一次迎来研究热潮。计算机视觉,从字面意义上理解就是让计算机等机器也具备人类视觉,研究让机器进行图像分类、目标检测等。在这近十年里,该领域取得的成就让人大吃一惊,有些研究已经超越了人类的表现水平。对于想入门或者从事深度学习领域的工作者而言,一般是从计算机视觉入手,网上有很多资料去介绍理论方面的知识,进行相应的实践也必不可少。本文总结一些在计算机视觉和深度学习领域的一些实践项目,供读者针对自己的感兴趣点挑选并实践。如果不熟悉上述术语,可以从下面的文章中了解更多的相关信息:一份“新奇”的深度学习介绍两个月探索深度学习和计算机视觉从神经科学到计算机视觉Andrew Ng在Coursera上的计算机视觉课程下面进行正文介绍:1.使用OpenCV进行手部动作跟踪项目地址:akshaybahadur21/HandMovementTracking为了执行视频跟踪,算法分析连续视频帧并输出帧之间的目标移动。针对这类问题,有各种各样的算法,每种算法都有各自的优缺点。在选择使用哪种算法时,针对实际应用场景考虑是很重要的。视觉跟踪系统有两个主要组成部分:目标表示和局部化,以及过滤和数据关联。视频跟踪是使用相机随时间定位移动物体(或多个物体)的过程。它有多种用途,比如:人机交互、安全和监控、视频通信和压缩、增强现实、交通控制、医学成像和视频编辑等。项目代码如下:import numpy as npimport cv2import argparsefrom collections import dequecap=cv2.VideoCapture(0)pts = deque(maxlen=64)Lower_green = np.array([110,50,50])Upper_green = np.array([130,255,255])while True: ret, img=cap.read() hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV) kernel=np.ones((5,5),np.uint8) mask=cv2.inRange(hsv,Lower_green,Upper_green) mask = cv2.erode(mask, kernel, iterations=2) mask=cv2.morphologyEx(mask,cv2.MORPH_OPEN,kernel) #mask=cv2.morphologyEx(mask,cv2.MORPH_CLOSE,kernel) mask = cv2.dilate(mask, kernel, iterations=1) res=cv2.bitwise_and(img,img,mask=mask) cnts,heir=cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2:] center = None if len(cnts) > 0: c = max(cnts, key=cv2.contourArea) ((x, y), radius) = cv2.minEnclosingCircle(c) M = cv2.moments(c) center = (int(M[“m10”] / M[“m00”]), int(M[“m01”] / M[“m00”])) if radius > 5: cv2.circle(img, (int(x), int(y)), int(radius),(0, 255, 255), 2) cv2.circle(img, center, 5, (0, 0, 255), -1) pts.appendleft(center) for i in xrange (1,len(pts)): if pts[i-1]is None or pts[i] is None: continue thick = int(np.sqrt(len(pts) / float(i + 1)) * 2.5) cv2.line(img, pts[i-1],pts[i],(0,0,225),thick) cv2.imshow(“Frame”, img) cv2.imshow(“mask”,mask) cv2.imshow(“res”,res) k=cv2.waitKey(30) & 0xFF if k==32: break# cleanup the camera and close any open windowscap.release()cv2.destroyAllWindows()54行代码即可解决这个问题,很简单吧!该项目依赖Opencv包,需要在计算机中安装OpenCV才能执行这个项目,下面是针对Mac系统、Ubuntu系统以及Windows系统的安装方法:Mac系统:如何在MacOS上安装OpenCV3Ubuntu系统:OpenCV:在Ubuntu中安装OpenCV-PythonWindows系统:在Windows中安装OpenCV-Python2.使用OpenCV进行睡意检测项目地址:akshaybahadur21/Drowsiness_Detection睡意检测对于长时间驾驶、工厂生产等场景很重要,由于长时间开车时,容易产生睡意,进而可能导致事故。当用户昏昏欲睡时,此代码可以通过检测眼睛来发出警报。依赖包CV2immutilsDLIBSciPy实现算法每只眼睛用6个(x,y)坐标表示,从眼睛的左角开始,然后顺时针绕眼睛工作:条件它检查20个连续帧,如果眼睛纵横比低于0.25,则生成警报。关系实现3.使用Softmax回归进行数字手写体识别项目地址:akshaybahadur21/Digit-Recognizer此代码使用softmax回归对不同的数字进行分类,依赖的包有点多,可以安装下Conda,它包含了机器学习所需要的所有依赖包。描述Softmax回归(同义词:多项Logistic、最大熵分类器、多类Logistic回归)是逻辑回归的推广,可以将其用于多类分类(假设类间是互斥的)。相反,在二分类任务中使用(标准)Logistic回归模型。Python实现使用的是MNIST数字手写体数据集,每张图像大小为28×28,这里尝试使用三种方法对0到9的数字进行分类,分别是Logistic回归、浅层神经网络和深度神经网络。Logistic回归:import numpy as npimport matplotlib.pyplot as pltdef softmax(z): z -= np.max(z) sm = (np.exp(z).T / np.sum(np.exp(z), axis=1)) return smdef initialize(dim1, dim2): """ :param dim: size of vector w initilazied with zeros :return: """ w = np.zeros(shape=(dim1, dim2)) b = np.zeros(shape=(10, 1)) return w, bdef propagate(w, b, X, Y): """ :param w: weights for w :param b: bias :param X: size of data(no of features, no of examples) :param Y: true label :return: """ m = X.shape[1] # getting no of rows # Forward Prop A = softmax((np.dot(w.T, X) + b).T) cost = (-1 / m) * np.sum(Y * np.log(A)) # backwar prop dw = (1 / m) * np.dot(X, (A - Y).T) db = (1 / m) * np.sum(A - Y) cost = np.squeeze(cost) grads = {“dw”: dw, “db”: db} return grads, costdef optimize(w, b, X, Y, num_iters, alpha, print_cost=False): """ :param w: weights for w :param b: bias :param X: size of data(no of features, no of examples) :param Y: true label :param num_iters: number of iterations for gradient :param alpha: :return: """ costs = [] for i in range(num_iters): grads, cost = propagate(w, b, X, Y) dw = grads[“dw”] db = grads[“db”] w = w - alpha * dw b = b - alpha * db # Record the costs if i % 50 == 0: costs.append(cost) # Print the cost every 100 training examples if print_cost and i % 50 == 0: print(“Cost after iteration %i: %f” % (i, cost)) params = {“w”: w, “b”: b} grads = {“dw”: dw, “db”: db} return params, grads, costsdef predict(w, b, X): """ :param w: :param b: :param X: :return: """ # m = X.shape[1] # y_pred = np.zeros(shape=(1, m)) # w = w.reshape(X.shape[0], 1) y_pred = np.argmax(softmax((np.dot(w.T, X) + b).T), axis=0) return y_preddef model(X_train, Y_train, Y,X_test,Y_test, num_iters, alpha, print_cost): """ :param X_train: :param Y_train: :param X_test: :param Y_test: :param num_iterations: :param learning_rate: :param print_cost: :return: """ w, b = initialize(X_train.shape[0], Y_train.shape[0]) parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iters, alpha, print_cost) w = parameters[“w”] b = parameters[“b”] y_prediction_train = predict(w, b, X_train) y_prediction_test = predict(w, b, X_test) print(“Train accuracy: {} %”, sum(y_prediction_train == Y) / (float(len(Y))) * 100) print(“Test accuracy: {} %”, sum(y_prediction_test == Y_test) / (float(len(Y_test))) * 100) d = {“costs”: costs, “Y_prediction_test”: y_prediction_test, “Y_prediction_train”: y_prediction_train, “w”: w, “b”: b, “learning_rate”: alpha, “num_iterations”: num_iters} # Plot learning curve (with costs) #costs = np.squeeze(d[‘costs’]) #plt.plot(costs) #plt.ylabel(‘cost’) #plt.xlabel(‘iterations (per hundreds)’) #plt.title(“Learning rate =” + str(d[“learning_rate”])) #plt.plot() #plt.show() #plt.close() #pri(X_test.T, y_prediction_test) return ddef pri(X_test, y_prediction_test): example = X_test[2, :] print(“Prediction for the example is “, y_prediction_test[2]) plt.imshow(np.reshape(example, [28, 28])) plt.plot() plt.show()浅层神经网络:import numpy as npimport matplotlib.pyplot as pltdef softmax(z): z -= np.max(z) sm = (np.exp(z).T / np.sum(np.exp(z),axis=1)) return smdef layers(X, Y): "”” :param X: :param Y: :return: """ n_x = X.shape[0] n_y = Y.shape[0] return n_x, n_ydef initialize_nn(n_x, n_h, n_y): """ :param n_x: :param n_h: :param n_y: :return: """ np.random.seed(2) W1 = np.random.randn(n_h, n_x) * 0.01 b1 = np.random.rand(n_h, 1) W2 = np.random.rand(n_y, n_h) b2 = np.random.rand(n_y, 1) parameters = {“W1”: W1, “b1”: b1, “W2”: W2, “b2”: b2} return parametersdef forward_prop(X, parameters): W1 = parameters[‘W1’] b1 = parameters[‘b1’] W2 = parameters[‘W2’] b2 = parameters[‘b2’] Z1 = np.dot(W1, X) + b1 A1 = np.tanh(Z1) Z2 = np.dot(W2, A1) + b2 A2 = softmax(Z2.T) cache = {“Z1”: Z1, “A1”: A1, “Z2”: Z2, “A2”: A2} return A2, cachedef compute_cost(A2, Y, parameters): m = Y.shape[1] W1 = parameters[‘W1’] W2 = parameters[‘W2’] logprobs = np.multiply(np.log(A2), Y) cost = - np.sum(logprobs) / m cost = np.squeeze(cost) return costdef back_prop(parameters, cache, X, Y): m = Y.shape[1] W1 = parameters[‘W1’] W2 = parameters[‘W2’] A1 = cache[‘A1’] A2 = cache[‘A2’] dZ2 = A2 - Y dW2 = (1 / m) * np.dot(dZ2, A1.T) db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True) dZ1 = np.multiply(np.dot(W2.T, dZ2), 1 - np.square(A1)) dW1 = (1 / m) * np.dot(dZ1, X.T) db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True) grads = {“dW1”: dW1, “db1”: db1, “dW2”: dW2, “db2”: db2} return gradsdef update_params(parameters, grads, alpha): W1 = parameters[‘W1’] b1 = parameters[‘b1’] W2 = parameters[‘W2’] b2 = parameters[‘b2’] dW1 = grads[‘dW1’] db1 = grads[‘db1’] dW2 = grads[‘dW2’] db2 = grads[‘db2’] W1 = W1 - alpha * dW1 b1 = b1 - alpha * db1 W2 = W2 - alpha * dW2 b2 = b2 - alpha * db2 parameters = {“W1”: W1, “b1”: b1, “W2”: W2, “b2”: b2} return parametersdef model_nn(X, Y,Y_real,test_x,test_y, n_h, num_iters, alpha, print_cost): np.random.seed(3) n_x,n_y = layers(X, Y) parameters = initialize_nn(n_x, n_h, n_y) W1 = parameters[‘W1’] b1 = parameters[‘b1’] W2 = parameters[‘W2’] b2 = parameters[‘b2’] costs = [] for i in range(0, num_iters): A2, cache = forward_prop(X, parameters) cost = compute_cost(A2, Y, parameters) grads = back_prop(parameters, cache, X, Y) if (i > 1500): alpha1 = 0.95alpha parameters = update_params(parameters, grads, alpha1) else: parameters = update_params(parameters, grads, alpha) if i % 100 == 0: costs.append(cost) if print_cost and i % 100 == 0: print(“Cost after iteration for %i: %f” % (i, cost)) predictions = predict_nn(parameters, X) print(“Train accuracy: {} %”, sum(predictions == Y_real) / (float(len(Y_real))) * 100) predictions=predict_nn(parameters,test_x) print(“Train accuracy: {} %”, sum(predictions == test_y) / (float(len(test_y))) * 100) #plt.plot(costs) #plt.ylabel(‘cost’) #plt.xlabel(‘iterations (per hundreds)’) #plt.title(“Learning rate =” + str(alpha)) #plt.show() return parametersdef predict_nn(parameters, X): A2, cache = forward_prop(X, parameters) predictions = np.argmax(A2, axis=0) return predictions深度神经网络:import numpy as npimport matplotlib.pyplot as pltdef softmax(z): cache = z z -= np.max(z) sm = (np.exp(z).T / np.sum(np.exp(z), axis=1)) return sm, cachedef relu(z): """ :param z: :return: """ s = np.maximum(0, z) cache = z return s, cachedef softmax_backward(dA, cache): """ :param dA: :param activation_cache: :return: """ z = cache z -= np.max(z) s = (np.exp(z).T / np.sum(np.exp(z), axis=1)) dZ = dA * s * (1 - s) return dZdef relu_backward(dA, cache): """ :param dA: :param activation_cache: :return: """ Z = cache dZ = np.array(dA, copy=True) # just converting dz to a correct object. dZ[Z <= 0] = 0 return dZdef initialize_parameters_deep(dims): """ :param dims: :return: """ np.random.seed(3) params = {} L = len(dims) for l in range(1, L): params[‘W’ + str(l)] = np.random.randn(dims[l], dims[l - 1]) * 0.01 params[‘b’ + str(l)] = np.zeros((dims[l], 1)) return paramsdef linear_forward(A, W, b): """ :param A: :param W: :param b: :return: """ Z = np.dot(W, A) + b cache = (A, W, b) return Z, cachedef linear_activation_forward(A_prev, W, b, activation): """ :param A_prev: :param W: :param b: :param activation: :return: """ if activation == “softmax”: Z, linear_cache = linear_forward(A_prev, W, b) A, activation_cache = softmax(Z.T) elif activation == “relu”: Z, linear_cache = linear_forward(A_prev, W, b) A, activation_cache = relu(Z) cache = (linear_cache, activation_cache) return A, cachedef L_model_forward(X, params): """ :param X: :param params: :return: """ caches = [] A = X L = len(params) // 2 # number of layers in the neural network # Implement [LINEAR -> RELU](L-1). Add “cache” to the “caches” list. for l in range(1, L): A_prev = A A, cache = linear_activation_forward(A_prev, params[“W” + str(l)], params[“b” + str(l)], activation=‘relu’) caches.append(cache) A_last, cache = linear_activation_forward(A, params[“W” + str(L)], params[“b” + str(L)], activation=‘softmax’) caches.append(cache) return A_last, cachesdef compute_cost(A_last, Y): """ :param A_last: :param Y: :return: """ m = Y.shape[1] cost = (-1 / m) * np.sum(Y * np.log(A_last)) cost = np.squeeze(cost) # To make sure your cost’s shape is what we expect (e.g. this turns [[17]] into 17). return costdef linear_backward(dZ, cache): """ :param dZ: :param cache: :return: """ A_prev, W, b = cache m = A_prev.shape[1] dW = (1. / m) * np.dot(dZ, cache[0].T) db = (1. / m) * np.sum(dZ, axis=1, keepdims=True) dA_prev = np.dot(cache[1].T, dZ) return dA_prev, dW, dbdef linear_activation_backward(dA, cache, activation): """ :param dA: :param cache: :param activation: :return: """ linear_cache, activation_cache = cache if activation == “relu”: dZ = relu_backward(dA, activation_cache) dA_prev, dW, db = linear_backward(dZ, linear_cache) elif activation == “softmax”: dZ = softmax_backward(dA, activation_cache) dA_prev, dW, db = linear_backward(dZ, linear_cache) return dA_prev, dW, dbdef L_model_backward(A_last, Y, caches): """ :param A_last: :param Y: :param caches: :return: """ grads = {} L = len(caches) # the number of layers m = A_last.shape[1] Y = Y.reshape(A_last.shape) # after this line, Y is the same shape as A_last dA_last = - (np.divide(Y, A_last) - np.divide(1 - Y, 1 - A_last)) current_cache = caches[-1] grads[“dA” + str(L)], grads[“dW” + str(L)], grads[“db” + str(L)] = linear_activation_backward(dA_last, current_cache, activation=“softmax”) for l in reversed(range(L - 1)): current_cache = caches[l] dA_prev_temp, dW_temp, db_temp = linear_activation_backward(grads[“dA” + str(l + 2)], current_cache, activation=“relu”) grads[“dA” + str(l + 1)] = dA_prev_temp grads[“dW” + str(l + 1)] = dW_temp grads[“db” + str(l + 1)] = db_temp return gradsdef update_params(params, grads, alpha): """ :param params: :param grads: :param alpha: :return: """ L = len(params) // 2 # number of layers in the neural network for l in range(L): params[“W” + str(l + 1)] = params[“W” + str(l + 1)] - alpha * grads[“dW” + str(l + 1)] params[“b” + str(l + 1)] = params[“b” + str(l + 1)] - alpha * grads[“db” + str(l + 1)] return paramsdef model_DL( X, Y, Y_real, test_x, test_y, layers_dims, alpha, num_iterations, print_cost): # lr was 0.009 """ Implements a L-layer neural network: [LINEAR->RELU]*(L-1)->LINEAR->SIGMOID. Arguments: X – data, numpy array of shape (number of examples, num_px * num_px * 3) Y – true “label” vector (containing 0 if cat, 1 if non-cat), of shape (1, number of examples) layers_dims – list containing the input size and each layer size, of length (number of layers + 1). alpha – learning rate of the gradient descent update rule num_iterations – number of iterations of the optimization loop print_cost – if True, it prints the cost every 100 steps Returns: params – params learnt by the model. They can then be used to predict. """ np.random.seed(1) costs = [] # keep track of cost params = initialize_parameters_deep(layers_dims) for i in range(0, num_iterations): A_last, caches = L_model_forward(X, params) cost = compute_cost(A_last, Y) grads = L_model_backward(A_last, Y, caches) if (i > 800 and i<1700): alpha1 = 0.80 * alpha params = update_params(params, grads, alpha1) elif(i>=1700): alpha1 = 0.50 * alpha params = update_params(params, grads, alpha1) else: params = update_params(params, grads, alpha) if print_cost and i % 100 == 0: print(“Cost after iteration %i: %f” % (i, cost)) if print_cost and i % 100 == 0: costs.append(cost) predictions = predict(params, X) print(“Train accuracy: {} %”, sum(predictions == Y_real) / (float(len(Y_real))) * 100) predictions = predict(params, test_x) print(“Test accuracy: {} %”, sum(predictions == test_y) / (float(len(test_y))) * 100) #plt.plot(np.squeeze(costs)) #plt.ylabel(‘cost’) #plt.xlabel(‘iterations (per tens)’) #plt.title(“Learning rate =” + str(alpha)) #plt.show() return paramsdef predict(parameters, X): A_last, cache = L_model_forward(X, parameters) predictions = np.argmax(A_last, axis=0) return predictions通过网络摄像头执行写入运行代码python Dig-Rec.py通过网络摄像头显示图像运行代码python Digit-Recognizer.py梵文字母识别项目地址:akshaybahadur21/Devanagiri-Recognizer此代码可帮助您使用CNN对不同梵文字母进行分类。使用技术使用了卷积神经网络,使用Tensorflow作为框架和Keras API来提供高级抽象。网络结构CONV2D→MAXPOOL→CONV2D→MAXPOOL→FC→Softmax→Classification额外的要点1.可以尝试不同的网络结构;2.添加正则化以防止过拟合;3.可以向训练集添加其他图像以提高准确性;Python实现使用Dataset-DHCD(Devnagari Character Dataset)数据集,每张图大小为32 X 32,详细代码请参考项目地址。运行代码python Dev-Rec.py4.使用FaceNet进行面部识别项目地址:akshaybahadur21/Face-Recoinion此代码使用facenet进行面部识别。facenet的概念最初是在一篇研究论文中提出的,主要思想是谈到三重损失函数来比较不同人的图像。为了提供稳定性和更好的检测,额外添加了自己的几个功能。本项目依赖的包如下:numpy matplotlib cv2 keras dlib h5py scipy描述面部识别系统是能够从数字图像或来自视频源的视频帧识别或验证人的技术。面部识别系统有多种方法,但一般来说,它们都是通过将给定图像中的选定面部特征与数据库中的面部进行比较来工作。功能增加1.仅在眼睛睁开时检测脸部(安全措施);2.使用dlib中的面部对齐功能在实时流式传输时有效预测;Python实现1.网络使用 - Inception Network;2.原始论文 - Google的Facenet;程序1.如果想训练网络,运行Train-inception.py,但是不需要这样做,因为已经训练了模型并将其保存为face-rec_Google.h5,在运行时只需加载这个文件即可;2.现在需要在数据库中放置一些图像。检查/images文件夹,可以将图片粘贴到此,也可以使用网络摄像头拍摄;3.运行rec-feat.py以运行该应用程序;5.表情识别器项目地址akshaybahadur21/Emojinator此项目可识别和分类不同的表情符号。但是目前为止,只支持手势表达的情绪。代码依赖包numpy matplotlib cv2 keras dlib h5py scipy描述表情符号是电子信息和网页中使用的表意文字和表情的符号。表情符号存在于各种类型中,包括面部表情、常见物体、地点和天气以及动物等。功能1.用于检测手的过滤器;2.CNN用于训练模型;Python实现1.网络使用 - 卷积神经网络程序1.首先,创建一个手势数据库。为此,运行CreateGest.py。尝试在框架内稍微移动一下手,以确保模型在训练时不会发生过拟合;2.对所需的所有功能重复此操作;3.运行CreateCSV.py将图像转换为CSV文件;4.训练模型,运行TrainEmojinator.py;5.运行Emojinator.py通过网络摄像头测试模型;总结这些项目都令人印象深刻,所有这些项目都可以在计算机上运行。如果你不想安装任何东西,可以更轻松地在Deep Cognition平台上运行,并且可以在线运行。感谢网络上各种开源项目的贡献。尝试一下各种感兴趣的项目,运行它们并获得灵感。上述这些这只是深度学习和计算机视觉可以做的事情中的一小部分,还有很多事情可以尝试,并且可以将其转变为帮助世界变得更美好的事情,code change world!此外,每个人都应该对许多不同的事情感兴趣。我认为这样可以改善世界、改善生活、改善工作方式,思考和解决问题的方式,如果我们依据现在所掌握的资源,使这些知识领域共同发挥作用,我们就可以在世界和生活中产生巨大的积极影响。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

April 8, 2019 · 9 min · jiezi

机器学习导图系列(1):数据处理

机器学习导图系列教程旨在帮助引导开发者对机器学习知识网络有一个系统的概念,其中具体释义并未完善,需要开发者自己探索才能对具体知识有深入的掌握。本项目灵感来自Daniel Formoso的github开源项目。本文作者对其项目进行翻译、整理、批注等二次创作,其中不乏生僻的数学名词,对于没有留过学的作者来说费了很多功夫。我又将导图整理成了知识卡片,方便大家查看。由于机器学习的知识网络很大,导致完整的导图过大,文章中的图片可能经过压缩,如需完整图片可查看github项目machine-learning-mindmap-cn下载高清原图。本系列还在持续创作中,你的点赞、留言、star都会成为我持续创作的动力。Daniel Formoso: https://github.com/dformoso/m...machine-learning-mindmap-cn: https://github.com/caiyongji/…机器学习导图系列分为五大模块。机器学习数据处理机器学习概念机器学习过程机器学习算法机器学习模型及神经网络模型数据类型数据探索数据清洗特征插补特征工程特征选择特征编码特征归一化(Normalisation)或缩放(Scaling)构造数据集最后你随手就是一个赞。

April 7, 2019 · 1 min · jiezi

机器学习 | K-均值聚类

聚类效果数据集1.658985 4.285136-3.453687 3.4243214.838138 -1.151539-5.379713 -3.3621040.972564 2.924086-3.567919 1.5316110.450614 -3.302219-3.487105 -1.7244322.668759 1.594842-3.156485 3.1911373.165506 -3.999838-2.786837 -3.0993544.208187 2.984927-2.123337 2.9433660.704199 -0.479481-0.392370 -3.9637042.831667 1.574018-0.790153 3.3431442.943496 -3.357075-3.195883 -2.2839262.336445 2.875106-1.786345 2.5542482.190101 -1.906020-3.403367 -2.7782881.778124 3.880832-1.688346 2.2302672.592976 -2.054368-4.007257 -3.2070662.257734 3.387564-2.679011 0.7851190.939512 -4.023563-3.674424 -2.2610842.046259 2.735279-3.189470 1.7802694.372646 -0.822248-2.579316 -3.4975761.889034 5.190400-0.798747 2.1855882.836520 -2.658556-3.837877 -3.2538152.096701 3.886007-2.709034 2.9238873.367037 -3.184789-2.121479 -4.2325862.329546 3.179764-3.284816 3.2730993.091414 -3.815232-3.762093 -2.4321913.542056 2.778832-1.736822 4.2410412.127073 -2.983680-4.323818 -3.9381163.792121 5.135768-4.786473 3.3585472.624081 -3.260715-4.009299 -2.9781152.493525 1.963710-2.513661 2.6421621.864375 -3.176309-3.171184 -3.5724522.894220 2.489128-2.562539 2.8844383.491078 -3.947487-2.565729 -2.0121143.332948 3.983102-1.616805 3.5731882.280615 -2.559444-2.651229 -3.1031982.321395 3.154987-1.685703 2.9396973.031012 -3.620252-4.599622 -2.1858294.196223 1.126677-2.133863 3.0936864.668892 -2.562705-2.793241 -2.1497062.884105 3.043438-2.967647 2.8486964.479332 -1.764772-4.905566 -2.911070代码import numpy as npimport mathimport matplotlib.pyplot as plt#从文件中加载数据def loadDataSet(file_name): data_mat = [] with open(file_name) as fr: #一次性读取文件中的所有数据 lines = fr.readlines() #print(lines) #遍历数据中的每一行 for line in lines: #对每一行以\t进行分割 cur_line = line.strip().split("\t") #[‘1.658985’, ‘4.285136’] #print(cur_line) #将每一行的内容由字符串转换成float flt_line = list(map(lambda x:float(x), cur_line)) #[-4.905566, -2.91107] #print(flt_line) #将转换后的内容append到data_mat中 data_mat.append(flt_line) #返回一个array类型 return np.array(data_mat)#计算两个向量的欧式距离#传入vecA=(x1,y1);vecB=(x2,y2)#计算的是sqrt((x1-x2)^2+(y1-y2)^2)def dist_eclud(vecA,vecB): vec_square = [] for element in vecA - vecB: element = element ** 2 vec_square.append(element) return sum(vec_square) ** 0.5#构建k个随机质心def rand_cent(dataSet,k): #n表示dataSet的列数 n = data_set.shape[1] #print(np.shape(dataSet)) #构造一个kn的0矩阵 centroids = np.zeros((k, n)) #填充矩阵的每一列 for j in range(n): #得到dataSet中第j列的最小值s min_j = float(min(data_set[:,j])) #获得第j列的最小值与最大值的差 range_j = float(max(data_set[:,j])) - min_j #minJ+最小值与最大值的差一个(0-1)之间的随机数 centroids[:,j] = (min_j + range_j * np.random.rand(k, 1))[:,0] return centroids#K-均值聚类算法def Kmeans(data_set, k): #m为dataSet的行数 m = data_set.shape[0] #初始化一个m2的0矩阵 #每一行表示每一个点,[0]存放该点对应的质心的行;[1]为到质心的距离 cluster_assment = np.zeros((m, 2)) #构建k个随机质心 centroids = rand_cent(data_set, k) cluster_changed = True #当任意一点所属的类别发生了变化的时候 while cluster_changed: cluster_changed = False #遍历每个点(每一行) for i in range(m): #初始化 min_dist = np.inf; min_index = -1 #遍历每一个质心 for j in range(k): #计算当前这一点与质心的dis dist_ji = dist_eclud(centroids[j,:], data_set[i,:]) #更新最小的dis与对应的质心所在的行j if dist_ji < min_dist: min_dist = dist_ji; min_index = j #该点的质心所在的行发生了变换——该点所属的类别发生了变化 if cluster_assment[i,0] != min_index: cluster_changed = True #更新类别与该点到质心的距离 cluster_assment[i,:] = min_index, min_dist**2 #更新质心 for cent in range(k): pts_inclust = data_set[np.nonzero(list(map(lambda x:x==cent, cluster_assment[:,0])))] centroids[cent,:] = np.mean(pts_inclust, axis=0) #返回质心,一个m2的矩阵,[0]存放该点对应的质心的行(类别);[1]为到质心的距离 return centroids, cluster_assment #绘制散点图def drawFigure(dataMat): #第一列(特征1)为横坐标 pointX=dataMat[:,0] pointY=dataMat[:,1] fig, ax = plt.subplots(figsize=(10,5)) ax.scatter(pointX, pointY, s=30, c=“r”, marker=“o”, label=“sample point”) ax.legend() ax.set_xlabel(“factor1”) ax.set_ylabel(“factor2”) plt.show()#绘制聚类后的散点图def drawFigure2(data_set,my_centroids): point_x = data_set[:,0] point_y = data_set[:,1] cent_x = my_centroids[:,0] cent_y = my_centroids[:,1] fig, ax = plt.subplots(figsize=(10,5)) ax.scatter(point_x, point_y, s=30, c=“r”, marker=“o”, label=“sample point”) ax.scatter(cent_x, cent_y, s=100, c=“black”, marker=“v”, label=“centroids”) ax.legend() ax.set_xlabel(“factor1”) ax.set_ylabel(“factor2”) plt.show()if name==’main’: #将文本内容转换成矩阵 data_set=loadDataSet(“testSet.txt”) my_centroids, my_cluster_assment = Kmeans(data_set, 4) drawFigure2(data_set,my_centroids) #print(my_centroids) # print(my_cluster_assment) #画图 #drawFigure(dataMat) #计算第一行与第二行的距离 #dist=distEclud(dataMat[0],dataMat[1]) #print(dist) #mm=randCent(dataMat,2) #print(mm) #print(dataMat) #第一列 #print(dataMat[:,0]) #第一行 #print(dataMat[0]) ...

April 6, 2019 · 2 min · jiezi

这款神秘的移动端OCR引擎,如何做到“所见即所得”?

阿里妹导读:随着深度学习,尤其是CNN和RNN等技术的飞速发展,文字识别技术(OCR)近几年得到了迅速的提升。与此同时,在智能化终端的大趋势下,本地化智能识别凭借更高效快捷的体验以及高度的隐私保护和零流量消耗等优势备受瞩目和亲睐,越来越多的应用算法开始倾向终端化完成,OCR也不例外。接下来,蚂蚁金服的算法专家亦弦为我们剖析这个轻量而精准的移动端OCR引擎——xNN-OCR。背景及概述移动端OCR的优势受算法效率和算法模型大小的限制和约束,目前大部分的OCR端上应用都是上传图片到服务端识别再将识别结果回传到客户端。虽然满足了部分业务需求,但一方面,对一些实效性要求较高的业务场景来说用户体验无疑是一个巨大的损失,尤其是弱网环境下。另一方面,在面临大促业务并发请求量过大的情况下,服务端不得不采用降级方案,而如果端上也具备识别能力的话,便可以极大地减少服务端的压力。此外,涉及到身份证、银行卡等重要私人证件采用OCR进行信息提取的时候,端上“识完即焚”这种方式,对这种敏感数据和隐私保护来说是天然的堡垒。因此,具备终端OCR识别能力有着极其重要的业务价值和意义。移动端OCR的难点OCR采用深度学习技术使得识别精度在特定的场景下面有了一定的保障,但模型大小和速度问题在端上依然是一大难题。目前大部分的后台OCR模型通常几十M或者上百M,可能比整个App安装包都要大,是不可能直接放到移动端的,而如果走实时下载的办法,模型过大也会造成下载失败率高、等待时间长、App占用空间大、流量消耗大等问题。另外,现在很多OCR算法在云端GPU上运行尚且需要几十到上百毫秒,要在手机CPU上保持较高的运行效率是一个极大的挑战。我们做了什么?——xNN-OCRxNN-OCR是专门针对移动端本地识别研发的的高精度、高效率、轻体量文字识别引擎,目前支持场景数字、场景英文、场景汉字以及特殊符号的识别。xNN-OCR针对移动端开发和优化了一套基于深度学习的文字检测和文字行识别算法框架,结合xNN的网络压缩和加速能力,检测和识别模型可以压缩到数百K级别,在中端及以上手机CPU上达到实时(最高15FPS),可结合“扫一扫”的模式在视频流中做到所见即所得。移动端OCR识别技术移动端OCR技术主要分为二个方面,一是OCR算法框架的研究和优化,主要目标是探索高精度且轻量级的检测和识别框架,确保在压缩之前模型的大小和速度在一个适当的范围以内,二是利用xNN对模型进行剪枝和量化压缩到实际应用需要的大小。下图是我们以银行卡检测和识别模型为例子展示整个压缩流程精度和模型的变化,其他OCR场景识别均是类似流程。轻量级OCR算法框架的探索目前大部分的移动端OCR技术都是以传统算法为主,在复杂自然场景下识别率相对较低,而基于深度学习的方案可以很好的解决这一类问题,识别率和稳定性远超传统算法。目前主流的深度学习OCR主要分为文字行检测和行识别两大块,下面我们分别介绍下:文字行检测在检测方面,我们将物体检测的Region-CNN框架与FCN的图像分割框架融合在一起,保留了FCN的简单框架以适应端上对模型尺寸和预测时间的要求,同时又在模型中加入了目标检测的位置回归模块,实现了对任意形状文本的检测能力。在基于FCN的整体框架中,为了在精简模型的同时不降低检测效果,我们采用了各种模型精简结构(例如Separable Convolution、Group Convolution + Channel Shuffle等,如下图),模型的尺寸虽然不断减小,精度并未随之下降,在满足端上对模型的苛刻限制的同时取得了较好的检测效果。文字行识别在识别方面,我们在CRNN(CNN+LSTM+CTC)框架基础上进行了优化改进,在Densenet的基础上结合Multiscale Feature、Channel-wise Attention等技术设计出了一套专门用于移动端文字行识别的轻量级CNN网络,同时对LSTM内部参数采用Project技术、全连接层采用SVD、BTD等降维技术进一步减少参数数量(如下图),在ICDAR2013数据集(NOFINETUNE)上,模型大小下降约50%的前提下识别率高出CRNN近4个点,这一改进优化点为上端打下了强有力的基础。xNN模型压缩目前我们的OCR算法模型都是基于tensorflow开发的,xNN已经增加了对TFLite模型的支持,并且在性能上已经远超TFLite。xNN对于我们OCR算法的模型压缩比在10-20倍之间,不同的场景稍微有些区别,与此同时,压缩后模型的精度基本保持不变。由于OCR是一个较复杂的识别任务,算法模型通常都非常大,并且目前大部分的后台OCR算法都是在GPU上运行,要想在端上运行,除了需要在算法层次上做很多优化外,更需要xNN强大的模型压缩和加速能力。移动端OCR应用OCR技术是信息提取和场景理解极其重要的技术手段之一,应用领域非常广泛。目前移动端本地OCR应用从技术角度可以分为2大类,一类是印刷体文字识别,主要是针对字体变化不大、背景单一的场景,例如身份证识别、名片识别、车牌识别等等,另一类是场景类文字识别,主要是针对字体变化大且背景复杂的场景,例如银行卡识别、燃气表/水表识别、门头名识别、场景英文识别(AR翻译)等等,这两类场景中后者识别难度较大,面临的挑战性更多。我们将xNN-OCR用于这些场景并根据场景的特点做了各种优化,取得了一系列的成果,特别是在复杂环境下面识别依然可以保持高效和精准,具体的数据如下表。下面简介了几个比较重要和常见的应用场景。银行卡识别:银行卡识别是金融类行业非常重要的一项技术,是场景数字类识别的一个典型代表。目前大部分银行卡识别均是采用端上识别的方案,因为端上识别不仅能带来更好更快的体验,同时由于不需要数据上传也能一定程度保护用户的隐私数据。基于xNN-OCR开发的银行卡识别在中端手机上耗时<300ms,大部分银行卡都是秒识别。此外,在面对复杂背景以及复杂环境干扰的时候,xNN-OCR在识别速度和精度上均展现了非常明显的优势。燃气表识别:通过OCR识别燃气表读数是目前燃气自助抄表中的一项关键性技术,相比于传统上门抄表,一方面可以节省很大的人力物力,避免上门抄表带来的麻烦,另外一方面也可以减少漏抄、误抄等问题。目前已经有很多燃气公司已经开始应用这一项技术,但实际应用过程中,由于燃气表的位置有时候比较隐蔽,拍摄角度和光照难以控制,通常一般的用户拍照上传到后台识别的图片质量都比较差,识别率偏低。xNN-OCR在端上完成整套识别流程,通过识别反馈引导用户拍摄,可较大程度的提升识别率,在与一家燃气公司的合作中,我们测试识别率可以达到93%+,模型尺寸可保持在500k以内,识别成功耗时<1s。车牌/VIN码识别:车牌/VIN码识别是传统印刷体类文字应用的一个经典场景,在移动警务、车辆维修定损等日常场景中起着非常重要的作用。由于车牌/VIN码识别在实际应用中可能同时需要,为了避免交互流程上的繁琐以及端上2套算法模型过大,xNN-OCR将车牌和VIN码这2个场景识别合二为一,模型尺寸依然<500k,在中端手机上识别成功耗时<1s,并且对光照、模糊、拍摄角度等干扰因素不敏感,同时由于端上可以反复识别寻求置信度最高的结果作为最终结果,所以相对于后台识别“一锤子买卖”而言,在识别精度上会更胜一筹。身份证识别:身份证识别也是金融类行业非常重要的一项技术,在实名认证、安全审核等场景起着非常重要的作用,但由于中文汉字字库较大,导致模型较大,目前大部分的身份证识别均采用的是服务端识别,但由于端侧质量难以控制,往往会导致体验和精度上面难以均衡。xNN-OCR在大字库中文识别方面也作出了一些突破,整体模型小于1M,在端侧用单字识别信度控制识别精度,避免了对图片质量判断的依赖,通过多帧融合提升识别效率,单次识别中端手机上<600ms,识别成功<2s。展望xNN-OCR目前在端上已经能较好的识别场景数字、英文以及部分汉字,无论是模型大小、速度、准确度均已达到工业应用的水平,并且全面超过基于传统算法识别的OCR端上应用,在多个实际应用项目中对比得以验证。另外,我们在端上全量7000多类汉字识别上也做出了一些成果,在不久的将来会分享出来,欢迎有兴趣的同学来一起研究和探讨。我们坚信,随着深度学习的移动端化逐步增强和移动硬件设备的逐步升级,终端智能化的应用与业务将会越来越多,未来xNN-OCR必将会给OCR相关的业务带来更深远的影响和更高的价值。本文作者:亦弦阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。

April 3, 2019 · 1 min · jiezi

机器学习 | CNN卷积神经网络

测试结果最后两行分别为预测类别与真实类别。数据预览这里的数据使用的是mnist数据集,大家可以将代码中的DOWNLOAD_MNIST值修改为True进行自动下载。代码import torchimport torch.nn as nnimport torch.utils.data as Dataimport torchvision # 数据库模块import matplotlib.pyplot as plt#训练整批数据多少次,这里为了节约时间,只训练一次EPOCH=1#每次批处理50个数据BATCH_SIZE=50#学习效率LR=0.001# 如果已经下载好了mnist数据就写上FalseDOWNLOAD_MNIST = False #训练的数据集:Mnist手写数字train_data=torchvision.datasets.MNIST( #保存或提取数据集的位置 root=’./mnist/’, #该数据是训练数据 train=True, #转换PIL.Image or numpy.ndarray成torch.FloatTensor (C x H x W), 训练的时候 normalize 成 [0.0, 1.0] 区间 transform=torchvision.transforms.ToTensor(), #没下载就下载,下载了就不用再下了 download=DOWNLOAD_MNIST,)#绘制一下数据集#黑色的地方的值都是0, 白色的地方值大于0.print(train_data.train_data.size()) # (60000, 28, 28)print(train_data.train_labels.size()) # (60000)plt.imshow(train_data.train_data[2].numpy(), cmap=‘gray’)plt.title(’%i’ % train_data.train_labels[2])plt.show()#测试数据test_data=torchvision.datasets.MNIST(root=’./mnist/’,train=False)#批训练50samples,1 channel,28x28 (50, 1, 28, 28)train_loader=Data.DataLoader(dataset=train_data,batch_size=BATCH_SIZE,shuffle=True)#这里只测试了前2000个#特征test_x=torch.unsqueeze(test_data.test_data,dim=1).type(torch.FloatTensor)[:2000]/255.#标签test_y=test_data.test_labels[:2000]#构建CNN模型class CNN(nn.Module): def init(self): super(CNN,self).init() #input shape(1,28,28) self.conv1=nn.Sequential( #卷积 nn.Conv2d( in_channels=1, out_channels=16, #filter size kernel_size=5, #filter movement/step stride=1, #如果想要con2d出来的图片长宽没有变化, #padding=(kernel_size-1)/2当stride=1 padding=2, ), #output shape(16,28,28) #激励函数 nn.ReLU(), #池化 # 在2x2空间里向下采样,output shape(16,14,14) nn.MaxPool2d(kernel_size=2), ) #input shape(16,14,14) self.conv2=nn.Sequential( nn.Conv2d(16,32,5,1,2), #output shape(32,14,14) #激励函数 nn.ReLU(), #output shape(32,7,7) nn.MaxPool2d(2), ) #全连接层——进行分类。这里将其分成了10类 self.out=nn.Linear(3277,10) def forward(self,x): x=self.conv1(x) x=self.conv2(x) #展平多维的卷积图成(batch_size,3277) x=x.view(x.size(0),-1) output=self.out(x) return outputcnn=CNN()print(cnn)#训练#优化器optimizer=torch.optim.Adam(cnn.parameters(),lr=LR)#损失函数loss_func=nn.CrossEntropyLoss()#开始训练for epoch in range(EPOCH): for step,(b_x,b_y) in enumerate(train_loader): #将数据输入nn并且得到output output=cnn(b_x) #计算output与真实值之间的误差 loss=loss_func(output,b_y) #清空上一步残余更新参数值 optimizer.zero_grad() #误差反向传播,让参数进行更新 loss.backward() #将更新后的参数值施加到nn的parameters上 optimizer.step()#测试:选取10个数据test_output=cnn(test_x[:10])pred_y=torch.max(test_output,1)[1].data.numpy().squeeze()print(pred_y, ‘prediction number’)print(test_y[:10].numpy(), ‘real number’)# if name==’main’:# print(“hello word”) ...

April 3, 2019 · 1 min · jiezi

Tensorflow Lite介绍

简介Tensorflow Lite是针对移动设备和嵌入式设备的轻量化解决方案,占用空间小,低延迟。Tensorflow Lite在android8.1以上的设备上可以通过ANNA启用硬件加速。支持浮点运算和量化模型,并已针对移动平台进行优化,可以用来创建和运行自定义模型。开发者也可以在模型中添加自定义操作。FlatBuffer格式具有在移动设备运行更快的内核解释器支持通过Tensorflow训练好的模型转换为Tensorflow Lite格式(pd,h5等都可以)当支持所有优化操作时,模型小于300k,当仅支持inception v3和mobilenet模型优化时,模型小于200k预训练模型:inception v3:用于目标检测MobileNets:专门针对移动端的模型,具有低延迟,高速度,低内存,可用于图像识别,目标检测,图像分割,但是精度小于inception v3量化版本的MobileNets,通过将float-32转为int-8,在CPU上拥有更快的速度支持java,c++API以上谈到的预训练模型基于ImageNet数据集训练,支持1000种类别。如果此数据集不能满足你的项目需要,你需要准备自己的数据集和标签,使用迁移学习重新训练模型。模型结构Tensorflow Lite模型的数据格式与Tensorflow桌面端不同,需要使用Tensorflow Lite转换为.tflite格式,然后应用到移动端。模型结构:java-API:包装C++API,以便在android上使用java调用C++-API:加载Tensorflow Lite模型和解释器解释器:执行模型一系列核心操作,支持选择内核加载。全部加载300kb,不加载只有100kb在android8.1以上设备,可通过相关api进行硬件加速(硬件支持的情况下),否则在CPU执行转换模型格式Tensorflow Lite转换器支持以下格式:使用python API执行SavedModel保存的模型文件tf.keras保存的.h5模型文件转换后的GraphDef文件转换GraphDef文件Tensorflow模型一般保存为.pd或.pdtxt格式的文件,要转换为Tensorflow Lite支持的文件,首先需要进行frozen操作。此操作处理多个不同格式的文件:tf.GraphDef(pd,pdtxt):图文件,包含操作,张量,变量的定义checkpoint(.ckpt):包含变量,不包含解释器tensorflow lite(.tflite):序列化的FlatBuffer文件,包含所有需要的文件checkpoint文件包含训练权重,tf.graphdef文件包含图结构。冻结操作就是将上述文件进行合并操作使用命令行,执行该操作的示例如下:freeze_graph –input_graph=/demo/mobilenet_v1_224.pd--input_checkpoint=/demo/checkpoints/mobilenet-1001.ckpt--input_binary=True--output_graph=/demo/frozen_mobilenet_v1_224.pd--output_node_names=/demo/MobileNetV1/Predictions/Reshape_1input_binary:读取的文件是否是二进制文件,如:pd和pdtxt文件android端使用Tensorflow Lite可以使用android studio和源码编译两种方式,此处我们介绍第一种(由于你懂的原因,开vpn会比较顺利些)。安装android studioSDK大于26,NDK大于14导入工程项目,路径:tensorflow/lite/examples默认使用mobilenet模型,如要使用inception模型,先下载模型文件并拷贝至asset文件夹,然后修改Camera2BasicFragment文件:classifier = new ImageClassifierQuantizedMobileNet(getActivity())改为:classifier = new ImageClassifierFloatInception(getActivity())Tensorflow Lite转换器上图是Tensorflow Lite转换器的工作流程,清晰明了,就不做过多介绍了。此外,转换的方式有两种,python api的方式和命令行方式。从Session中导出GraphDef使用tf.Session将Tensorflow模型转为Tensorflow Lite模型import tensorflow as tfimg = tf.placeholder(name=“img”, dtype=tf.float32, shape=(1, 64, 64, 3))var = tf.get_variable(“weights”, dtype=tf.float32, shape=(1, 64, 64, 3))val = img + varout = tf.identity(val, name=“out”)with tf.Session() as sess: sess.run(tf.global_variables_initializer()) converter = tf.lite.TFLiteConverter.from_session(sess, [img], [out]) tflite_model = converter.convert() open(“converted_model.tflite”, “wb”).write(tflite_model)从file中导出GraphDef以下代码展示怎样将.pd或.pdtxt文件转为Tensorflow Lite模型支持的FlateBuffer格式文件。import tensorflow as tfgraph_def_file = “/path/to/Downloads/mobilenet_v1_1.0_224/frozen_graph.pb"input_arrays = [“input”]output_arrays = [“MobilenetV1/Predictions/Softmax”]converter = tf.lite.TFLiteConverter.from_frozen_graph( graph_def_file, input_arrays, output_arrays)tflite_model = converter.convert()open(“converted_model.tflite”, “wb”).write(tflite_model)将SaveModle导出import tensorflow as tfconverter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)tflite_model = converter.convert()open(“converted_model.tflite”, “wb”).write(tflite_model)tf.keras文件导出import tensorflow as tfconverter = tf.lite.TFLiteConverter.from_keras_model_file(“keras_model.h5”)tflite_model = converter.convert()open(“converted_model.tflite”, “wb”).write(tflite_model)量化模型import tensorflow as tfimg = tf.placeholder(name=“img”, dtype=tf.float32, shape=(1, 64, 64, 3))const = tf.constant([1., 2., 3.]) + tf.constant([1., 4., 4.])val = img + constout = tf.fake_quant_with_min_max_args(val, min=0., max=1., name=“output”)with tf.Session() as sess: converter = tf.lite.TFLiteConverter.from_session(sess, [img], [out]) converter.inference_type = tf.lite.constants.QUANTIZED_UINT8 input_arrays = converter.get_input_arrays() converter.quantized_input_stats = {input_arrays[0] : (0., 1.)} # mean, std_dev tflite_model = converter.convert() open(“converted_model.tflite”, “wb”).write(tflite_model)TensorFlow Lite Python解释器代码展示如何使用Tensorflow Lite解释器读取.tflite文件。import numpy as npimport tensorflow as tf# 加载模型并分配张量interpreter = tf.lite.Interpreter(model_path=“converted_model.tflite”)interpreter.allocate_tensors()# 获取输入输出张量input_details = interpreter.get_input_details()output_details = interpreter.get_output_details()# 随机生成测试数据,测试模型输出input_shape = input_details[0][‘shape’]input_data = np.array(np.random.random_sample(input_shape), dtype=np.float32)interpreter.set_tensor(input_details[0][‘index’], input_data)interpreter.invoke()output_data = interpreter.get_tensor(output_details[0][‘index’])print(output_data)Tensorflow2.0转换器使用如图所示,Tensorflow2.0与之前相比,少了冻结graph模块,增加了Concrete Fn。生成concrete Fn为了将Tensorflow2.0模型转为Tensorflow Lite,模型需要导出concrete Fn。这是因为Tensorflow2.0中,eager execution是默认设置,虽然调试更加便利,但是它没有保存图,因为不能直接应用到移动设备。不过,可以使用tf.function包装,这样保存的模型就包含图,可以转换为Tensorflow Lite所需要的FlatBuffer格式文件。class BasicModel(tf.Module): def init(self): self.const = None @tf.function def pow(self, x): if self.const is None: self.const = tf.Variable(2.) return x ** self.constconcrete Fn声明的图可以被转换为Tensorflow Lite模型或者使用SaveModel导出。为了导出此方法,需要声明signature,使用方法如下:在tf.function中声明input_signature将tf.TensorSpec传值给get_concrete_funtion将input传值给get_concrete_funtionimport tensorflow as tfroot = tf.Module()# 初始化一次变量值root.var = None@tf.functiondef exported_function(x): if root.var is None: root.var = tf.Variable(tf.random.uniform([2, 2])) root.const = tf.constant([[37.0, -23.0], [1.0, 4.0]]) root.mult = tf.matmul(root.const, root.var) return root.mult * xroot.func = exported_functionconcrete_func = root.func.get_concrete_function( tf.TensorSpec([1, 1], tf.float32))Python api执行the TensorFlow Lite converterTensorflow2.0中转换Tensorflow Lite模型使用tf.lite.TFLiteConverter.from_concrete_function(),示例如下:import tensorflow as tf# 创建模型root = tf.train.Checkpoint()root.v1 = tf.Variable(3.)root.v2 = tf.Variable(2.)root.f = tf.function(lambda x: root.v1 * root.v2 * x)# 保存模型export_dir = “/tmp/test_saved_model"input_data = tf.constant(1., shape=[1, 1])to_save = root.f.get_concrete_function(input_data)tf.saved_model.save(root, export_dir, to_save)# 加载模型并获取concrete fn.model = tf.saved_model.load(export_dir)concrete_func = model.signatures[ tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY]# 设置input shapeconcrete_func.inputs[0].set_shape(input_data.shape)# 转换模型converter = tf.lite.TFLiteConverter.from_concrete_function(concrete_func)tflite_model = converter.convert()TensorFlow Lite 推断TensorFlow Lite推断一般执行以下步骤:加载.tflite模型处理数据以适应模型input调用API,创建解析器,运行模型获取模型输出结果如何选择模型如图所示,大模型高精度,高延迟;小模型低精度,低延迟,模型的选择需要根据你的项目需求进行选择。 ...

April 2, 2019 · 2 min · jiezi

机器学习 | 树回归

由于近期学业繁重QAQ,所以我就不说废话了,直接上代码~运行结果代码from numpy import #使用二元切分法——每次将数据集切成两份#如果数据的某特征值等于切分所要求的值,#那么这些数据就进入树的左子树,反之则# 进入右子树def loadDataSet(fileName): dataMat=[] fr=open(fileName) for line in fr.readlines(): curLine=line.strip().split(’\t’) #将每行映射成浮点数 fltLine=list(map(float,curLine)) dataMat.append(fltLine) #将文件中的所有数据都保存在同一个矩阵中 return dataMat#参数:数据集,待切分的特征,该特征的某个值def binSplitDataSet(dataSet,feature,value): #将数据集合切分得到两个子集并返回 mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:] mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:] return mat0,mat1#建立叶结点的函数#当chooseBestSplit函数决定不再对数据集进行切分时,将调用该regLeaf函数#来得到叶节点的模型。在回归树种,该模型其实就是目标变量的均值def regLeaf(dataSet): return mean(dataSet[:,-1])#计算误差的函数——这里计算的是总方差def regErr(dataSet): #均方差函数var数据集中样本的个数=总方差 return var(dataSet[:,-1]) * shape(dataSet)[0]#给定某个误差计算方法,该函数会找到数据集上最佳的二元切割方式#(他遍历所有的特征及可能的取值来找到使误差最小化的切分阈值)#另外,该函数还要确定什么时候停止切分,一旦停止切分就会生成一个叶节点#errType为平方误差的总值(总方差)def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)): #用户指定的参数,用于控制函数停止时机 #tolS为误差下降值,tolN为切分的最少样本数 tolS = ops[0]; tolN = ops[1] #如果所有值相等则退出 if len(set(dataSet[:,-1].T.tolist()[0])) == 1: #找不到一个“好”的二元切分,返回None并同时调用leafType来生成叶节点 return None, leafType(dataSet) m,n = shape(dataSet) S = errType(dataSet) bestS = inf; bestIndex = 0; bestValue = 0 for featIndex in range(n-1): for splitVal in set((dataSet[:,featIndex].T.A.tolist())[0]): mat0, mat1 = binSplitDataSet(dataSet, featIndex, splitVal) if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): continue newS = errType(mat0) + errType(mat1) if newS < bestS: bestIndex = featIndex bestValue = splitVal bestS = newS #如果误差减少不大则退出 if (S - bestS) < tolS: return None, leafType(dataSet) mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue) #如果切分出的数据集很小则退出 if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): return None, leafType(dataSet) #找到了一个“好”的切分方式,返回特征编号和切分特征值 #找到了最佳的切分方式:切分后能达到最低误差的切分 return bestIndex,bestValue#构建树的函数#dataSet为数据集#leafType为建立叶结点的函数,errType为误差计算函数#ops是一个包含书构建所需其他参数的元组def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)): #chooseBestSplit为切分函数 #若满足停止条件chooseBestSplit将返回None和某类模型的值 #如果构建的是回归树,该模型是一个常数,如果是模型树,其 #模型是一个线性方程(回归树假设叶节点是常数值) #若不满足停止条件,chooseBestSplit将创建一个新的python #字典,并将数据集分成两份,在这两份数据集上分别继续递归调 #用createTree函数 feat,val=chooseBestSplit(dataSet,leafType,errType,ops) #满足停止条件时返回叶节点 if feat==None: return val retTree={} retTree[‘spInd’]=feat retTree[‘spVal’]=val #将数据集按照待分特征和该特征的某个值进行二分操作 lSet,rSet=binSplitDataSet(dataSet,feat,val) #创建左右子树 retTree[’left’]=createTree(lSet,leafType,errType,ops) retTree[‘right’]=createTree(rSet,leafType,errType,ops) return retTreedef drawFigure1(): # import matplotlib.pyplot as plt # myDat=loadDataSet(’ex00.txt’) # myMat=mat(myDat) # createTree(myMat) # plt.plot(myMat[:,0],myMat[:,1],‘ro’) # plt.show() import matplotlib.pyplot as plt myDat=loadDataSet(’ex0.txt’) myMat=mat(myDat) createTree(myMat) plt.plot(myMat[:,1],myMat[:,2],‘ro’) plt.show()def main(): drawFigure1() # myDat=loadDataSet(’ex00.txt’) # myMat=mat(myDat) # myTree=createTree(myMat) # print(myTree) #建立一个主对角线元素全为1的矩阵 #testMat=mat(eye(4)) #print(testMat) #要分割的特征位于第一列 #按照0.5去划分 #mat0,mat1=binSplitDataSet(testMat,0,0.5) # print(mat0) # print(mat1)if name==’main’: main()``` ...

March 30, 2019 · 2 min · jiezi

机器学习 | 预测数值型数据:回归

由于近期学业繁重QAQ,所以我就不说废话了,直接上代码~线性回归局部加权线性回归代码from numpy import import matplotlib.pyplot as plt#标准回归函数和数据导入函数#默认文本的最后一行为目标值#第一列为偏移量,假定为常数1.0#第二列为x1,也就是图中的横坐标def loadDataSet(fileName): numFeat=len(open(fileName).readline().split(’\t’))-1 dataMat=[] labelMat=[] fr=open(fileName) for line in fr.readlines(): lineArr=[] curLine=line.strip().split(’\t’) for i in range(numFeat): lineArr.append(float(curLine[i])) dataMat.append(lineArr) labelMat.append(float(curLine[-1])) return dataMat,labelMat#计算最佳拟合曲线#.T标识矩阵的转置def standRegres(xArr,yArr): xMat=mat(xArr) #矩阵转置,变程行向量 yMat=mat(yArr).T #判断xTx的转置与xTx相乘是否为0 xTx=xMat.TxMat #若为0,那么计算逆矩阵的时候会出错 if linalg.det(xTx)==0.0: print(“this matrix is singular,cannot do inverse”) return #计算ws #.I返回矩阵的逆 ws=xTx.I*(xMat.TyMat) return ws #绘制数据集散点图和最佳拟合直线图def drawFigure(): xArr,yArr=loadDataSet(’ex0.txt’) ws=standRegres(xArr,yArr) xMat=mat(xArr) yMat=mat(yArr) fig=plt.figure() ax=fig.add_subplot(111) ax.scatter(xMat[:,1].flatten().A[0],yMat.T[:,0].flatten().A[0]) xCopy=xMat.copy() xCopy.sort(0) yHat=xCopyws ax.plot(xCopy[:,1],yHat) plt.show() #局部加权线性回归#给待预测的点附近的每个点赋予一定的权重#在这个子集上基于最小均方差来进行普通的回归#使用的核为高斯核#最终构建了一个只含对角元素的权重矩阵w,并且x与x(i)越近,#w(i,i)将会越大#局部加权线性回归函数def lwlr(testPoint,xArr,yArr,k=1.0): xMat=mat(xArr) yMat=mat(yArr).T m=shape(xMat)[0] #创建对角矩阵 #权重矩阵是一个方阵,阶数为样本点的个数 #该矩阵为每个样本点初始化了一个权重 weights=mat(eye((m))) #遍历数据集,计算每个样本点对应的权重值 #随着样本点与待预测点距离的递增,权重将以指数级衰减 #参数k控制衰减的速度 #权重值大小以指数级衰减 for j in range(m): diffMat=testPoint-xMat[j,:] weights[j,j]=exp(diffMatdiffMat.T/(-2.0k**2)) xTx=xMat.T*(weightsxMat) if linalg.det(xTx)==0.0: print(“This matrix is singular,cannot do inverse”) return #得到回归系数 ws=xTx.I(xMat.T*(weightsyMat)) return testPointwsdef lwlrTest(testArr,xArr,yArr,k=1.0): m=shape(testArr)[0] yHat=zeros(m) #为数据集中的每个点调用lwlr() for i in range(m): yHat[i]=lwlr(testArr[i],xArr,yArr,k) return yHatdef drawfigure2(): xArr,yArr=loadDataSet(’ex0.txt’) #print(yArr[0]) yHat0=lwlr(xArr[0],xArr,yArr,1.0) #print(yHat0) yHat=lwlrTest(xArr,xArr,yArr,0.01) xMat=mat(xArr) strInd=xMat[:,1].argsort(0) xSort=xMat[strInd][:,0,:] fig=plt.figure() ax=fig.add_subplot(111) ax.plot(xSort[:,1],yHat[strInd]) ax.scatter(xMat[:,1].flatten().A[0],mat(yArr).T.flatten().A[0],s=2,c=‘red’) plt.show() def main(): drawfigure2() #drawFigure() #xArr,yArr=loadDataSet(’ex0.txt’) #ws=standRegres(xArr,yArr) #xMat=mat(xArr) #yMat=mat(yArr) #计算预测值yHat和真实值y的匹配程度——计算两个序列的相关程度 #yHat=xMat*ws #arr=corrcoef(yHat.T,yMat) #yHat与yMat的相关系数为0.98 #[[1. 0.98647356] #[0.98647356 1. ]] #print(arr) #[[1.0, 0.067732], [1.0, 0.42781],…] #print(xArr) #[3.176513, 3.816464,…] #print(yArr) #[[3.00774324] #[1.69532264]] #Haty=wx[0]*x0+ws[1]*x1 #print(ws)if name==’main’: main() ...

March 28, 2019 · 1 min · jiezi

机器学习 | Logistic回归

由于近期学业繁重QAQ,所以我就不说废话了,直接上代码~Logistic回归进行分类分类效果Logistic回归预测病马的死亡率预测结果全部代码from numpy import import matplotlib.pyplot as plt#使用梯度上升法找到最佳参数#使用梯度上升法找到最佳回归系数,#也就是拟合Logistic回归模型的最佳参数#Logistic归回梯度上升优化算法#加载文件def loadDataSet(): dataMat=[];labelMat=[] #打开文本文件 fr=open(’testSet.txt’) #逐行读取 for line in fr.readlines(): lineArr=line.strip().split() #为了方便计算,将x0设为1,后面的x1,x2是文本中每行的前两个值 dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) #文本中每行的第三个值为数据对应的标签 labelMat.append(int(lineArr[2])) return dataMat,labelMat #sigmiod函数def sigmoid(inX): return 1.0/(1+exp(-inX)) #梯度上升算法#第一个参数是一个2维的Numpy数组#每列表示不同的特征#每行表示每个训练样本#我们采用100个样本,包含两个x1,x2特征#再加上第0维特征x0,所以dataMatIn是一个100X3的矩阵#第二个参数是类别标签,是一个1X100的行向量def gradAscent(dataMatIn,classLabels): dataMatrix=mat(dataMatIn) #将行向量转置为列向量 labelMat=mat(classLabels).transpose() #得到矩阵的大小 m,n=shape(dataMatrix) #向目标移动的步长 alpha=0.001 #迭代次数 maxCycles=500 weights=ones((n,1)) #在for循环结束之后,将返回训练好的回归系数 for k in range(maxCycles): #注:此处是矩阵相乘 #h是一个列向量,元素的个数等于样本的个数 h=sigmoid(dataMatrixweights) #真实类别与预测类别的差别 error=(labelMat-h) #按照该差别的方向调整回归系数 weights=weights+alphadataMatrix.transpose()error #返回回归系数——确定了不同类别数据之间的分割线 return weights #画出决策边界#画出数据集和Logistic回归最佳拟合直线的函数 #X1表示一个特征,X2表示另一个特征def plotBestFit(weights): #得到数据集与标签 dataMat,labelMat=loadDataSet() dataArr = array(dataMat) n = shape(dataArr)[0] xcord1 = []; ycord1 = [] xcord2 = []; ycord2 = [] #对数据集进行分类 for i in range(n): if int(labelMat[i])== 1: xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2]) else: xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2]) fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(xcord1, ycord1, s=30, c=‘red’, marker=’s’) ax.scatter(xcord2, ycord2, s=30, c=‘green’) x = arange(-3.0, 3.0, 0.1) #根据gradAscent得到的回归系数绘制分割线 y = (-weights[0]-weights[1]x)/weights[2] #print(x) #print(y) ax.plot(x, y) plt.xlabel(‘X1’); plt.ylabel(‘X2’); plt.show() #梯度上升方法在每次更新回归系数时都需要遍历整个数据集#改进方法:一次仅使用一个样本点来更新回归系数——随机梯度上升算法#由于可以在新样本到来时对分类器进行增量式更新,因此随机梯度上升#算法是一个在线学习算法#与“在线学习”相对应,一次数里所有数据被称作“批处理”#随机梯度上升算法def stocGradAscent0(dataMatrix,classLabels): #得到矩阵的大小 m,n=shape(dataMatrix) #向目标移动的步长 alpha=0.01 weights=ones(n) for i in range(m): #h为向量 h=sigmoid(sum(dataMatrix[i]weights)) #error为向量 error=classLabels[i]-h weights=weights+alphaerrordataMatrix[i] return weights #由于经过测试,多次迭代后,X0,X1收敛速度较小#且存在一些小的周期性的波动,因此及逆行改进#改进随机梯度上升算法#第三个参数为迭代次数def stocGradAscent1(dataMatrix,classLabels,numIter=150): m,n=shape(dataMatrix) weights=ones(n) for j in range(numIter): dataIndex=list(range(m)) for i in range(m): #改进1:alpha[向目标移动的步长]会随着迭代的次数不断减小 #可以缓解数据波动或高频波动, alpha=4/(1.0+j+i)+0.01 #通过随机选取样本来更新回归系数 #可以减少周期性的波动 randIndex=int(random.uniform(0,len(dataIndex))) h=sigmoid(sum(dataMatrix[randIndex]weights)) error=classLabels[randIndex]-h weights=weights+alphaerrordataMatrix[randIndex] del(dataIndex[randIndex]) return weights #Logistic回归预测病马的死亡率#对于缺失数据,我们选择用0来替换#因为这样不会影响系数weights的值#对于标签已经丢失的,我们将这条数据丢弃#使用Logistic回归进行分类的主要思路:#把测试集上每个特征向量乘最优方法得到的回归系数#再将该乘积结果求和,最后输入Sigmoid函数中即可,#若对应的sigmoid值>0.5预测类别标签为1,否则为0#Logistic回归分类函数def classifyVector(inX,weights): #以回归系数和特征向量作为输入来计算对应的Sigmoid值 prob=sigmoid(sum(inXweights)) if prob>0.5:return 1.0 else:return 0.0#打开测试集和训练集,并对数据进行格式化处理 def colicTest(): frTrain=open(‘horseColicTraining.txt’) frTest=open(‘horseColicTest.txt’) trainingSet=[] trainingLabels=[] #遍历每一行 for line in frTrain.readlines(): currLine=line.strip().split(’\t’) lineArr=[] #遍历每一列 for i in range(21): lineArr.append(float(currLine[i])) trainingSet.append(lineArr) #最后一列为类别标签 trainingLabels.append(float(currLine[21])) #计算回归系数向量 trainWeights=stocGradAscent1(array(trainingSet),trainingLabels,500) errorCount=0 numTestVec=0.0 for line in frTest.readlines(): numTestVec+=1.0 currLine=line.strip().split(’\t’) lineArr=[] for i in range(21): lineArr.append(float(currLine[i])) #对测试集进行分类,并查看结果是否正确 if int(classifyVector(array(lineArr),trainWeights))!=int(currLine[21]): errorCount+=1 #计算错误率 errorRate=(float(errorCount)/numTestVec) print(“the error rate of this test is: %f”%errorRate) return errorRate#调用colicTest函数10次,并且结果的平均值 def multiTest(): numTests=10 errorSum=0.0 for k in range(numTests): errorSum+=colicTest() print(“after %d iterations the average error rate is: %f”%(numTests,errorSum/float(numTests))) def main(): #dataArr,labelMat=loadDataSet() #weights=gradAscent(dataArr,labelMat) #print(weights) #plotBestFit(weights.getA()) #weights=stocGradAscent0(array(dataArr),labelMat) #weights=stocGradAscent1(array(dataArr),labelMat) #plotBestFit(weights) multiTest() if name==’main’: main() ...

March 27, 2019 · 2 min · jiezi

机器学习 | 朴素贝叶斯

由于近期学业繁重QAQ,所以我就不说废话了,直接上代码~用朴素贝叶斯进行词汇分类代码from numpy import #词表到向量的转换#创建实验样本,返回的是进行词条切分后的文档集合,#还有一个类别标签——侮辱性的or非侮辱性的def loadDataSet(): postingList=[[‘my’, ‘dog’, ‘has’, ‘flea’, ‘problems’, ‘help’, ‘please’], [‘maybe’, ’not’, ’take’, ‘him’, ’to’, ‘dog’, ‘park’, ‘stupid’], [‘my’, ‘dalmation’, ‘is’, ‘so’, ‘cute’, ‘I’, ’love’, ‘him’], [‘stop’, ‘posting’, ‘stupid’, ‘worthless’, ‘garbage’], [‘mr’, ’licks’, ‘ate’, ‘my’, ‘steak’, ‘how’, ’to’, ‘stop’, ‘him’], [‘quit’, ‘buying’, ‘worthless’, ‘dog’, ‘food’, ‘stupid’]] #1 代表侮辱性文字 0代表正常言论 classVec = [0,1,0,1,0,1] return postingList,classVec #创建一个包含在所有文档中出现的不重复的词的列表 def createVocabList(dataSet): vocabSet=set([]) #document:[‘my’, ‘dog’, ‘has’, ‘flea’, ‘problems’, ‘help’, ‘please’] for document in dataSet: #求并集 vocabSet=vocabSet|set(document) #print(vocabSet) return list(vocabSet) #参数为词汇表以及某个文档,输出的是文档向量#输出的向量的每一个元素为1或0,表示词汇表中#的单词在输入文档中是否出现def setOfWords2Vec(vocabList,inputSet): #创建一个所含元素都为0的向量 returnVec=[0]len(vocabList) #遍历文档中的所有单词,如果出现了词汇表中的单词, #则将输出文档的对应值设为1 for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)]=1 else: print(“the word: %s is not in my Vocabulary!"%word) return returnVec #输入的参数:文档矩阵trainMatrix#由每篇文档类别标签构成的向量trainCategory#朴素贝叶斯分类器训练函数#trainMatrix:每个词向量中的词,在词汇表中出现的就是1#trainMatrix:[[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0], #[0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0],#[1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], #[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0], #[0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1], #[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0]]#该词向量中带有侮辱性的词的就是1#trainCategory:[0, 1, 0, 1, 0, 1]def trainNBO(trainMatrix,trainCategory): #一共有几个词向量 numTrainDocs=len(trainMatrix) #词汇表的长度 numWords=len(trainMatrix[0]) #3/6 表示6个词向量中,3个带侮辱词 pAbusive=sum(trainCategory)/float(numTrainDocs) #初始化概率 p0Num=ones(numWords) p1Num=ones(numWords) p0Denom=2.0;p1Denom=2.0 #遍历训练集trainMatrix中的所有文档 #一旦某个词在某一文档中出现 #该文档的总词数加1 #两个类别都要进行同样的处理 #i:012345 for i in range(numTrainDocs): #该词向量带侮辱 if trainCategory[i]==1: #向量相加 p1Num+=trainMatrix[i] p1Denom+=sum(trainMatrix[i]) else: p0Num+=trainMatrix[i] p0Denom+=sum(trainMatrix[i]) #每个元素除以该类别的总词数 p1Vect=log(p1Num/p1Denom) p0Vect=log(p0Num/p0Denom) return p0Vect,p1Vect,pAbusive #朴素贝叶斯分类函数def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1): #元素相乘 p1=sum(vec2Classifyp1Vec)+log(pClass1) p0=sum(vec2Classifyp0Vec)+log(1.0-pClass1) if p1>p0: return 1 else: return 0 def testingNB(): listOPosts,listClasses=loadDataSet() myVocabList=createVocabList(listOPosts) trainMat=[] #使用词向量填充trainMat列表 for postinDoc in listOPosts: Vec01=setOfWords2Vec(myVocabList,postinDoc) trainMat.append(Vec01) p0V,p1V,pAb=trainNBO(trainMat,listClasses) #测试集 testEntry=[’love’,‘my’,‘dalmation’] thisDoc=array(setOfWords2Vec(myVocabList,testEntry)) #print(thisDoc) print(testEntry,’ classified as: ‘,classifyNB(thisDoc,p0V,p1V,pAb)) testEntry=[‘stupid’,‘garbage’] thisDoc=array(setOfWords2Vec(myVocabList,testEntry)) #print(thisDoc) print(testEntry,’ classified as: ‘,classifyNB(thisDoc,p0V,p1V,pAb)) def main(): testingNB() #创建数据 #listOPosts,listClasses=loadDataSet() #print(listOPosts) #构建一个包含所有词的列表 #myVocabList=createVocabList(listOPosts) #print(myVocabList) #returnVec=setOfWords2Vec(myVocabList,listOPosts[0]) #print(returnVec) #trainMat=[] #使用词向量填充trainMat列表 #for postinDoc in listOPosts: #传入词汇表 以及每一行词向量 #返回的是一个与词汇表同样size的向量 #1表示这个词在词向量中出现过 #Vec01=setOfWords2Vec(myVocabList,postinDoc) #print(Vec01) #将01list填充trainMat #trainMat.append(Vec01) #print(trainMat) #print(listClasses) #p0V,p1V,pAB=trainNBO(trainMat,listClasses) #print(p0V) #print(p1V) #print(pAB) if name==’main’: main() ...

March 25, 2019 · 2 min · jiezi

深度召回模型在QQ看点推荐中的应用实践

本文由云+社区发表作者:腾讯技术工程导语:最近几年来,深度学习在推荐系统领域中取得了不少成果,相比传统的推荐方法,深度学习有着自己独到的优势。我们团队在QQ看点的图文推荐中也尝试了一些深度学习方法,积累了一些经验。本文主要介绍了一种用于推荐系统召回模块的深度学习方法,其出处是Google在2016年发表于RecSys的一篇用于YouTube视频推荐的论文。我们在该论文的基础上做了一些修改,并做了线上AB测试,与传统的协同召回做对比,点击率等指标提升明显。为了系统的完整性,在介绍主模型前,本文先对传统推荐算法和召回算法做一些简单的介绍和总结,并指出深度学习方法相对于传统方法的优势所在,然后再进入本文的主题——深度召回模型。1. 推荐系统算法概述按照使用的数据类型来分,推荐算法可以分为两大类: 第一类是基于用户行为数据的推荐算法,通常也叫做协同过滤;协同过滤又分为memory-based和model-based这两类。其中,memory-based协同过滤的代表算法有基于用户的UserCF,基于物品的ItemCF,它们的特点是用行为数据直接计算user-user或item-item的相似度[1]。Model-based协同过滤的代表算法主要是一些隐变量模型,例如SVD、矩阵分解MF[2, 3]、主题模型pLSA、LDA[4]等,它们的特点是用行为数据先计算出user和item的隐向量,然后通过这些隐向量计算user-user或item-item间的匹配度去做推荐。在实践中,我们除了能拿到用户的行为数据以外,通常还可以拿到用户和物品的画像数据,比如性别、年龄、地域、标签、分类、标题、正文等,在一些文献中,这些行为以外的数据被称为side information。传统的协同过滤是不考虑side information的,如果把side information和行为数据结合使用,应该会提升推荐的准确率。这种同时使用行为数据和side information的算法都属于第二类算法。在第二类算法中,最常见的模型就是CTR模型。CTR模型本质上是一个二分类的分类器,用得比较多的是LR、xgboost[10]、lightGBM[11]等分类器。其中,行为数据和side information被用于构造训练样本的特征和类标。分类器完成训练后,通过预测user点击item的概率,可以把topK概率最大的item作为推荐结果推送给用户。比起纯行为的协同过滤,使用了side information 的CTR模型通常会取得更好的推荐效果。而整个CTR模型取胜的关键,在于如何结合side information和行为数据构造出具有判别性的用户特征、物品特征以及交叉特征;近五年来,基于深度学习的CTR模型逐渐发展起来,在不少应用场景下取得了比传统CTR模型更好的效果。相比于传统的CTR模型,深度CTR模型有着自己独到的优势,主要体现在如下几个方面:(1)特征的整合能力:深度学习通过使用embedding技术,可以将任何分类变量转化为具有语义结构的低维稠密向量,很容易把分类变量和连续变量结合在一起作为模型的输入,比传统方法使用one-hot或multi-hot表示分类变量的方式更方便有效,特别适合于web推荐这种分类变量比较多的场景;(2)自动交叉特征的能力:深度学习通过神经网络强大的非线性拟合能力,可以从原始输入数据中自动学习用户和物品的交叉特征,能更深层次地匹配用户与物品,从而提高推荐准确率。通过自动学习交叉特征,大大降低了特征工程的工作量;(3)端到端的学习:传统CTR模型会把特征构造和模型训练分开,先做数据预处理、特征构造或特征学习,然后给模型训练。这些事先构造或学习好的特征,并不一定最适合用来拟合当前模型。而在深度学习中,输入数据不需要做过多的预处理或特征学习,特征学习和模型训练是同时进行的,学到的特征也是最适合拟合当前模型的,学出来的模型的泛化能力通常会更好一些。由于不需要专门学习特征,因此也提高了开发模型的效率。(4)完善的计算平台和工具:模型建得再漂亮,最后也得能求解出来才能在实际中发挥真正的作用。对于深度学习来说,一些现有的计算平台(如TensorFlow)使得模型求解变得非常容易。研究者只需要把精力放在模型的设计和调优上,不需要推导复杂的求解公式。模型的求解由TensorFlow等工具的自动微分技术完成,大大降低了模型实现和落地的难度。由于以上原因,基于深度学习的CTR模型受到了广泛关注,在最近几年内发展很快,并在不少业务中取得了显著的成果。2.召回模型推荐系统在架构上一般分为两层:召回层和排序层。 其中,召回层主要负责从全体物品中快速筛选出跟用户兴趣相关的物品池子,大大缩小物品的范围,为排序做准备。在资讯类产品的推荐场景下,召回物品通常还需要满足时新性。所以在资讯类推荐场景中,召回模型要满足如下几点:(1)高效性:要在很短的响应时间内完成物品的召回;(2)相关性:要尽可能召回那些匹配用户兴趣的物品;(3)时新性:新上线的物品,也要能被召回,以确保最新的内容也有曝光的机会;2.1传统召回模型以图文推荐为例,常用的召回方式是通过用户历史点击的文章去关联相似文章作为召回,其中,按照所用数据的不同,又分为按内容召回和协同召回。内容召回:(1)根据用户画像中的标签、分类,召回具有相同或相似标签、分类的文章;(2)使用文章的标题或正文,通过word2vec、glove等方法求出文章的标题向量或正文向量,通过计算向量的余弦相似度召回内容上相似的文章。协同召回: (1)可以使用jaccard公式直接计算两篇文章的用户重合度作为这两篇文章的行为相似度;优缺点:以上这两类召回方法,都有各自的优点和缺点。第一种方法的优点是可以召回最新的文章。缺点是可能会出现召回内容过于集中或兴趣漂移等问题。对于向量化方法,容易出现“点过什么就召回什么”的现象,降低了推荐的多样性。对于直接用标签或分类来召回,可能会召回相关性不高的文章,降低召回的准确性。第二种方法在一定程度上解决召回内容过于集中和兴趣漂移的问题,但是因为依赖于行为数据,所以只能召回训练数据中包含的文章,没办法召回最新的文章。为了召回新文章,就必须每隔一段时间重新计算一遍。所以它召回的文章做不到真正意义的时新。为了解决以上两种方法存在的缺点,我们使用了深度学习的方法去做召回,充分利用用户的画像信息去深度匹配用户兴趣和文章,同时保证可以召回最新的文章。业界中用深度学习做召回比较成功的是Google在YouTube视频推荐中使用的召回方法[9],但它并不考虑召回内容是否时新这一点,所以为了让这个方法也能召回最新的item,我们对YouTube深度召回模型做了一些修改,让它既能召回深度匹配用户兴趣的文章,也能保持召回文章的时新性。“此外,由于YouTube召回模型使用的是用户向量直接匹配文章向量的召回方式,因此通过使用向量索引系统,很容易满足从大量文章中快速召回候选集的性能要求。”2.2深度召回模型为了表述上的简洁,我把Google提出的这个用于YouTube视频推荐的深度召回模型简称为YouTube召回模型。在讲述模型之前,先讲一下深度CTR模型中一般都要使用的两个基本网络结构:embedding层和全连接层。Embedding层深度CTR模型的输入通常会包含各种不同的分类变量,例如用户画像里的标签、一级分类、二级分类等。这些分类变量的取值往往比较多,比如标签,它的取值可能就有几十万个,如果用one-hot或multi-hot方式来表示标签,则会产生几十万维的高维稀疏向量。在深度CTR模型中,对这些取值特别多的分类变量通常都会使用embedding方法,将其表示为一个低维稠密的向量,然后输入到网络中。这个低维稠密向量被称为这个分类变量的embedding,把分类变量转化为embedding的那一层网络称为embedding层。下图给出了一个例子,讲述了如何使用embedding方法将用户画像中的标签表示为一个低维稠密向量。图1 用embedding方法表示分类变量的例子首先,我们初始化一个lookup table,这个lookup table是一个矩阵(可以是事先选了好固定不变的,也可以是从数据中学习,不断迭代更新的),矩阵的行数为分类变量的取值数,在这个例子中就是标签总个数,矩阵的列数是低维稠密向量的维数(事先指定)。假设标签总个数为1万,那么lookup table就有1万行,其中第i行是编号为i的标签对应的embedding。在上图例子中,用户有两个标签,编号分别为308和4080,对应权重为0.7和0.3,求embedding时首先将第308行和第4080行的向量拿出来,分别记为,然后以0.7和0.3为权重加权求和这两个向量,就得到了用户标签的embedding,即 事实上,用以上方法求embedding,跟用输入分类变量one-hot或multi-hot后得到的高维稀疏向量乘以lookup table,得到的结果是一样的,不同的只是用查表求和的方式来做这个矩阵乘法会高效得多。所以从本质上说,求embedding做的是线性降维。 全连接层全连接层是多层感知器(multiple layer perceptron, MLP)中的基本结构,定义了第l层到第l+1层的非线性映射关系,它的主要作用是使模型具备非线性拟合能力,或者说学习特征交叉的能力。图2给出了一个从第l层到第l+1层的全连接示意图。图2 第l层到第l+1层的全连接示意图Youtube召回模型的网络结构YouTube召回模型根据user的点击历史和画像,计算user对item库里每个item的喜欢的概率,返回topK概率最大的item作为召回列表。从本质上说,YouTube召回模型是一个超大规模的多分类模型,每个item是一个类别,通过用户画像计算出用户特征作为模型输入,预测用户最喜欢的topK个类别(topK个item)。在图文主feeds召回这一场景中,用户的输入主要为以下几种类型的数据:(1)用户的点击历史,包括阅读、点赞、评论、收藏、biu过的文章;(2)用户的兴趣画像,包括用户的标签、一级分类、二级分类等;(3)用户的人口统计学特征,包括用户的性别、年龄等;(4)用户的上下文信息,包括用户的地域信息、访问推荐系统时的时间段等;这里有一点需要注意的,就是我们模型里文章的lookup table是由文章正文分词的word2vec向量构成的,在训练过程中不更新。在YouTube召回模型的原始论文里,item是视频,item的lookup table是学习出来的。但是在图文推荐场景下,如果文章的lookup table是学习得到的话,那就没办法召回最新的文章了,只能召回那些训练样本中出现过的文章,满足不了时新文章推荐的需求。为了能召回新文章,我们修改了原模型,直接用文章的word2vec向量构造文章的lookup table,其中文章的word2vec向量由文章的词向量加权求和得到,而词向量则是事先用word2vec学好固定下来的。每入库一篇新文章,我们都可以通过该文章的词向量加权求和得到它的word2vec向量,然后存起来,YouTube模型在线召回时,无论是计算用户兴趣向量还是计算内积,都可以实时获取到每篇文章的向量,包括最新文章,从而可以满足时新文章召回的需求。图3 YouTube深度召回模型的网络结构训练阶段:以用户所有的side information和点击行为数据作为训练样本,最大化以上这个总似然函数,便可以学习出所有lookup table、DNN网络权重和偏置。预测阶段:优化算法:由于这个模型里的softmax需要对库中所有文章进行,文章数量一般都在几十万这个量级,直接优化是不可行的,会非常耗时,所以实际计算中会采用专门针对这种超大规模多分类问题而设计的优化算法,这类算法的名字叫做candidate sampling,其中用得最广泛的是噪声对比估计(NCE,Noise-Contrastive Estimation),它将点击样本的softmax变为多个二分类logistic问题。由于softmax具有sum-to-one的性质,最大化点击样本的概率必然能导致最小化非点击样本的概率,而二分类logistic则没有这个性质,所以需要人为指定负样本,NCE就是一种根据热度随机选取负样本的技术,通过优化NCE损失,可以快速地训练得到模型的所有参数。在实践中,我们采用了TensorFlow提供的函数tf.nn.nce_loss去做候选采样并计算NCE损失。3.实验和分析实验设置为了验证YouTube深度召回模型是否比传统的召回方法更有效,我们做了线上的AB测试实验。其中,深度召回模型离线训练完成以后,将其用于服务端做在线召回,对比的召回方法是基于文章的协同过滤。训练样本(1)用户向量计算:用户最近一段时间的点击历史,包括阅读、点赞、评论、收藏、分享过的文章;用户最近一段时间的兴趣画像,包括用户的标签、一级分类、二级分类以及对应权重;用户的人口统计学特征,主要为用户的性别、年龄;用户的上下文信息,主要为用户的地域信息、当前时间;(2)正样本选取:用户在画像统计时间点后一天点击过的文章;(3)文章向量:计算用户向量和正样本涉及到的所有文章的word2vec向量;(4)样本量:对用户抽样,用于训练的用户数抽样到千万级别,样本总数达到亿级别;实验结果抽样分析在上线实验前,我们做了抽样分析。也就是随机抽取若干用户,获取他们的历史点击文章,然后看看 YouTube召回模型和协同过滤模型分别召回了什么文章,主观上去看一下哪个召回更符合用户的历史点击。以下是某个用户的case分析:从这个用户的历史点击文章可以看出,他的兴趣点有娱乐类、社会类和科技类。协同召回和YouTube召回基本都能召回这些类别相关的文章。相比而言,协同召回的文章在内容上会比较相似,YouTube召回的文章不仅有内容相似的,而且还有主题相关的,在多样性和推广性上会更好一些。比如说,对于协同召回,历史点击了漫威的复联4,召回就有漫威的文章,历史点击了马云,召回也有马云。而对于YouTube召回,“点什么就召回什么”这种现象会少很多,召回的文章既保持了相关性,同时又有一定推广性。比如说,“复联4”召回“疯狂的外星人”,虽然它们不是同一个系列的电影,但是都是新电影。也许该用户并不是特别关心漫威的电影,而只是关心一些新电影,YouTube模型可能识别到了用户的这一兴趣趋向,召回了“疯狂的外星人”。所以主观上会有一种在相关性上做推广的感觉。然而,以上case分析只是主观上的感受,而且抽样分析不能代表总体。最可靠的还是通过线上的AB测试来评估召回算法,看能否提高线上的核心指标。在线评估指标在线AB测试实验的评估指标是算法的点击数、曝光数、点击率以及文章覆盖度。AB测试实验的对照组用的是基于Item的协同过滤算法,即ItemCF,通过jaccard计算item-item相似度,根据用户历史点击过的文章召回相似文章。实验组是YouTube深度召回模型。在ranker档位相同的情况下,实验组和对照组在点击数、曝光数和点击率上的对比如下:点击率对比曝光数对比点击数对比从在线指标上可以看到,YouTube深度召回的曝光数稍低于协同召回的曝光数,但是点击率会明显高于协同召回的点击率。YouTube召回模型的曝光数大约是协同召回曝光数的80%,但平均点击率比协同召回的平均点击率有大约20%的相对提升。说明YouTube深度召回模型召回的文章比协同召回更能匹配用户的兴趣。此外,YouTube召回模型在推荐内容的多样性和文章覆盖度上也比协同召回更好一些,在线实验统计结果显示,在推荐出去的去重文章总数上,实验组比对照组的多2%左右,这个数据间接反映了YouTube召回比协同召回找到了更多匹配用户兴趣的文章。小结(1)本文介绍了一种基于深度学习的召回模型,并将其与传统召回方法进行了实验对比; (2)在线实验表明, YouTube召回模型召回文章的点击率显著高于协同过滤召回文章的点击率,说明YouTube召回模型通过画像数据学到了更准确的用户兴趣向量,匹配到更多符合用户兴趣的文章,体现出深度学习模型在特征整合利用和自动学习交叉特征上的优势;(3)因为YouTube召回模型在计算用户向量时采用的是word2vec预训练的文章向量,而每篇文章入库时都可以计算出其word2vec向量,因此YouTube召回模型能够召回最新入库的文章,做到真正的时新召回。参考文献[1]项亮. 推荐系统实践. 北京: 人民邮电出版社, 2012.[2]KorenY, Bell R, Volinsky C. Matrix factorization techniques for recommender systems.Computer, 2009 (8): 30-37.[3]HuY, Koren Y, Volinsky C. Collaborative filtering for implicit feedback datasets.ICDM, 2008: 263-272.[4]BleiD M, Ng A Y, Jordan M I. Latent dirichlet allocation. Journal of machineLearning research, 2003, 3(Jan): 993-1022.[5]ZhangS, Yao L, Sun A. Deep learning based recommender system: A survey and newperspectives. arXiv preprint arXiv:1707.07435, 2017.[6]Mikolov,Tomas & Chen, Kai & Corrado, G.s & Dean, Jeffrey. EfficientEstimation of Word Representations in Vector Space. Proceedings of Workshop atICLR. 2013.[7]MikolovT, Sutskever I, Chen K, et al. Distributed representations of words and phrasesand their compositionality. NIPS.2013: 3111-3119.[8]PenningtonJ, Socher R, Manning C. Glove: Global vectors for word representation. EMNLP.2014: 1532-1543.[9]CovingtonP, Adams J, Sargin E. Deep neural networks for youtube recommendations. RecSys.2016: 191-198.[10]Chen T, Guestrin C. Xgboost: A scalable tree boosting system. SIGKDD. 2016:785-794.[11]Ke G, Meng Q, Finley T, et al. Lightgbm: A highly efficient gradient boostingdecision tree. NIPS. 2017: 3146-3154.此文已由腾讯云+社区在各渠道发布获取更多新鲜技术干货,可以关注我们腾讯云技术社区-云加社区官方号及知乎机构号 ...

March 20, 2019 · 1 min · jiezi

100行Python代码理解深度学习关键概念:从头构建恶性肿瘤检测网络

摘要: 100行Python代码理解深度学习关键概念!在构建乳腺癌预测神经网络过程中,我们主要分为3大部分:1.用Python从零开始创建一个神经网络,并使用梯度下降算法训练模型。2.在该神经网络中使用威斯康星乳腺癌数据集,根据9种不同的特征,预测肿瘤是良性还是恶性的。3.探索反向传播和梯度下降算法的工作原理。在这个领域中,有很多大牛都通过视频和博文分享了自己掌握的专业知识,如fast.ai的Jeremy Howard、吴恩达、Andrej Karpathy、Yann Lecun等等。他们一致认为,深度学习的关键之一就是,尽快亲自动手编写一个深度学习的模型。当前,深度学习领域中有很多强大的库可供我们使用,如Tensorflow、 PyTorch、 Fast.ai、 Keras、 Mxnett、Nctk、DL4J 等。如果仅仅直接使用这些强大的库,我们可能会错过很多关键的东西,因此,我们需要进一步思考这些进程中最重要的那部分。如果能自己亲自动手编码创建一个神经网络,我们就不得不面对创建过程中出现的一些问题和障碍,挖掘深度学习背后隐藏的那些令人惊叹的知识。当前,深度学习领域中有各种各样的架构和开发:卷积神经网络、循环神经网络和生成对抗网络等等。在这些不同种类的网络背后,都包含了两个相同的算法:反向传播算法和梯度下降算法。探索神秘的函数宇宙中的很多事物都可以用函数表示。本质上来说,函数是一种数学结构,接受一个输入并产生一个输出,表示因果关系、输入输出关系。当我们审视周围的世界时,会接收到很多信息,我们将这些信息转化为数据,就可以从这些数据中学到很多知识。在利用这些数据进行学习的时候,会有很多不同的种类。通常来说,深度学习中有三种最常见的类型:1.监督学习:从一组有标签(已分类)的训练数据中学习函数,输入和输出是成对的数据集。2.非监督学习:从没有任何标签或分类的数据中学习到函数。3.强化学习:代理人会在特定环境中做出相应的动作,通过最大化代理人得到的奖励得到函数。监督学习本文中,我们主要关注监督学习。现在,我们有一个数据集,包含输入及对应的输出。下面,我们想了解这些输入和输出是如何通过一个神秘的函数联系起来的。当数据集达到一定的复杂度时,寻找这个函数的难度就相当大。因此,我们就需要使用神经网络和深度学习,来探索这个神秘的函数。本质上来说,神经网络通过一系列的中间“权重”连接我们的输入和期望输出数据。这些权重实际上就是一些数字。当我们使用正确的架构和参数,通过神经网络的结构和优化算法,我们可将神经网络近似成一个通用函数近似器,将输入和输出数据联系起来。创建一个神经网络一般来说,简单的神经网络包括两层(输入不计入层数):1.输入:神经网络的输入包含了我们的源数据。并且,神经元的数量与源数据的特征数量相匹配。下图中有4个输入,当我们使用威斯康星乳腺癌数据集创建神经网络的时候,就会使用9个输入。2.第一层:隐藏层,包含一些隐藏层神经元,这些神经元将会与周围层中的所有单元相连接。3.第二层:有一个单元,为神经网络的输出。在实际的神经网络构建过程中,我们可以使用更多的层,比如10个或20个层的网络。为了简单起见,在这里,我们使用2个层。千万不要小看这2个层,它能够实现很多功能。神经网络如何进行学习问题来了:在这个神经网络中,学习将在哪个部分进行?我们来回顾一下,我们在神经网络的输入层放置了一些数据,并向网络展示某个输入应该对应什么输出,也就是说,神经网络的输出(第2层)应该是什么结果。在神经网络中,每个神经元都有一个相关的权重以及一个偏差。这些权重只是神经网络在开始学习时候初始化的一些随机数字。神经网络根据输入数据和这些权重值进行计算,通过神经网络传播,直到输出产生最终的结果。这些计算的结果就是一个将输入映射到输出的函数。我们需要的就是,这些神经网络能够计算出一个最佳权重值。因为网络通过计算,不同的权重和不同的层结合起来,会近似出不同类型的函数。现在,我们来进一步探索正在探寻的函数。为了方便阅读,我们需要解释下这些变量的名称:1.X表示输入层,即提供给网络的数据集。2.Y表示与输入x对应的目标输出,由输入经过网络进行一系列的计算得到的输出。3.Yh(y hat)表示预测函数,即我们像网络提供输入数据集x后,经过神经网络一系列的计算产生的输出。因此,Y是理想的输出,Yh是神经网络接收到输入数据后产生的实际输出。4.W表示网络各层的权重。我们首先看第一层——隐藏层,它执行了一个运算WX(即W和X的乘积)。然后进行一个加权和:1.这一层中的每个单元都和前一层中的每个单元相连接。2.权重值存在于每个连接中。3.该层中每个单元的值都是由前一个层中每个单元的值权重的总和,而该权重则是1中所得到的权重。从某种程度上来说,权重表示连接的强度,即:不同层之间单元连接的强度。现在,我们要在这个架构中添加一个额外的量——偏差:WX+b。这个偏差能够给神经网络带来更多的灵活性,偏差允许网络“移动”单位的线性计算,加强网络学习这些函数的能力。b代表单位偏差项。我们看到,WX+b就是一个线性方程,通过乘积与和运算表示输入和输出的线性关系。现在,我们的神经网络只有2层,但是请记住,一个神经网络可以有很多层,比如20个甚至200个。因此,我们用数字表述这些变量属于哪一层。这样一来,定义隐藏层(第1层)的线性方程则为:W1X+b1,并为其输出命名为Z,表示某一层计算的输出。因此,我们得到如下方程:Z1=W1X+b1注意,这个计算应该针对每个层的每个单元进行。当我们为神经网络编写代码的时候,我们将使用向量化编程,也就是说,利用矩阵将某一层的所有计算放在一个单一的数学运算中。上面所讲述的是只有一个层的神经网络。现在,我们考虑一个有很多层的神经网络,每个层执都执行一个类似上面的线性运算,当所有的线性运算连接在一起时,这个神经网络就能够计算复杂的函数了。激活函数然而,现在就有一个问题:线性函数——太简单了吧。这个世界是复杂的,因此,线性函数远远满足不了实际需求。一般来说,复杂的函数往往都是非线性的。而且,如果神经网络的架构仅仅由线性函数计算,那么就很难计算非线性行为。这就是为什么我们要在神经网络的每一层末尾加上一个额外的量:激活函数。现在,我们介绍4个最典型的例子。为了方便我们后续对激活函数进行深入探索,首先需要介绍梯度这一概念。一个函数在某一点上的梯度也称为函数的导数,表示该函数在该点输出值的变化率。我们来思考这样一个问题:当特定输入发生变化时,函数的输出会发生怎样的变化?当梯度(导数)非常小,即函数的输出变化非常平坦时,我们称之为梯度消失。在后边的反向传播算法中,我们可以通过梯度了解网络中每个参数将会如何影响网络的输出,从而就能够决定如何调整网络的权值,也就是说了解这个参数的变化将会使网络的输出增加还是减少?梯度消失是我们所面临的一个问题,因为如果某一点的梯度变化很小或趋于0,我们就很难确定该神经网络在该点的输出方向。当然,我们也会遇到相反的情况——梯度爆炸。当梯度值非常大时,神经网络可能就会变得非常不稳定。不同的激活函数有各自的优点,但是都会面临梯度消失和梯度爆炸这两大问题。左上:Sigmoid激活函数;右上:Tanh激活函数;左下:Relu激活函数;右下:Leaky Relu激活函数(1)Sigmoid激活函数——1/(1+e-x)1.输出范围:[0,1]。2.非线性,输出为两个极端变量0和1。适用于二分类问题。3.曲线变化温和,因此,梯度(导数)比较容易控制。4.该激活函数的主要缺点为:在极端情况下,函数的输出曲线变得非常平坦,也就是说,函数的导数(变化率)将变得非常小,在这种情况下,Sigmoid激活函数的计算效率和速度将会非常低,甚至会完全没效率。5.当Sigmoid激活函数出现在神经网络的最后一层时,将会特别有用,因为Sigmoid激活函数有助于将输出变为0或1(即二分类问题)。如果将Sigmoid激活函数放在神经网络的其他层,就会出现梯度消失问题。(2)Tanh激活函数——(2/(1+e-2x))-11.输出范围:[-1,1]。2.曲线和Sigmoid激活函数的曲线类似,是Sigmoid激活函数曲线的缩小版。3.Tanh激活函数曲线较为陡峭,因此,该激活函数的导数(变化率)比较大。4.Tanh激活函数的缺点与Sigmoid激活函数类似。(3)Relu激活函数——max (0,x)1.如果输入大于0,那么,输出值等于输入值;否则,输出为0。2.Relu激活函数的范围是[0,+∞),这就意味着输出可能是+∞,可能会存在梯度爆炸问题。3.优点:使神经网络轻量化,因为一些神经元可能输出为0,防止所有的神经元被同时激活。4.Relu激活函数存在一个问题,即输入为0的时候,输出全部为0,这将会导致梯度为0,会让我们忽视某些神经元的一些有用的计算。5.Relu激活函数计算简单,成本低廉。6.当前,Relu激活函数是神经网络内层最经常使用的激活函数。(4)Leaky Relu激活函数——ex / Sum(ex)1.输出范围:[0,1]2.Leaky Relu激活函数将输入进行标准化处理为一个概率分布。3.通常用于多分类场景中的输出层。在这里,我们在输出层使用Sigmoid激活函数,在隐藏层使用Relu激活函数。好了,现在我们已经理解了激活函数,那么,就需要对其进行命名!A:表示激活函数的输出。因此,在神经网络的隐藏层中,将会进行如下计算:A1=Relu(Z1)Z1=W1X+b1在第二层的输出层中,将会进行如下计算:A2=Sigmoid(Z2)Z2=W2A1+b2请注意,第二层(输出层)的输入为第一层的输出,即A1。第二层的输出就是网络的最终输出。将上面的计算归纳一下,就得到2层神经网络所执行的全部计算:Yh = A2 = Sigmoid(W2ReLU (W1X+ b1) + b2 )因此,本质上来说,神经网络是一连串的函数,有些是线性函数,有些是非线性函数,它们共同组成了一个复杂的函数,将我们的输入数据和想要的输出数据连接了起来。现在,我们注意到,在这个方程的所有变量中,W和b是两个未知数,这就是神经网络需要学习的地方。也就是说,神经网络必须进行不断的学习,找到W和b的正确值,才能计算出正确的函数。因此,我们训练神经网络的目的也变得明了了,即寻找W1,b1,W2,b2的正确值。但是,在开始训练神经网络之前,我们必须首先对这些值进行初始化,即用随机函数对其进行初始化处理。初始化以后,我们就可以对神经网络进行编码,我们使用Python构建一个类,对这些主要的参数进行初始化处理。我们将如何进行实战编码呢?请继续阅读我们的第二部分:用Python构建一个神经网络。一站式开发者服务,海量学习资源0元起!阿里热门开源项目、机器学习干货、开发者课程/工具、小微项目、移动研发等海量资源;更有开发者福利Kindle、技术图书幸运抽奖,100%中–》https://www.aliyun.com/acts/product-section-2019/developer?utm_content=g_1000047140本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 19, 2019 · 1 min · jiezi

深度神经网络原理与实践

理论基础什么是神经网络我们知道深度学习是机器学习的一个分支,是一种以人工神经网络为架构,对数据进行表征学习的算法。而深度神经网络又是深度学习的一个分支,它在 wikipedia 上的解释如下:深度神经网络(Deep Neural Networks, DNN)是一种判别模型,具备至少一个隐层的神经网络,可以使用反向传播算法进行训练。权重更新可以使用下式进行随机梯度下降法求解。首先我们可以知道,深度神经网络是一种判别模型。意思就是已知变量 x ,通过判别模型可以推算出 y。比如机器学习中常用到的案例,通过手写数字,模型推断出手写的是数字几。深度神经网络中的“深度”指的是一系列连续的表示层,数据模型中包含了多少层,这就被称为模型的“深度”。通过这些层我们可以对数据进行高层的抽象。如下图所示,深度神级网络由一个输入层,多个(至少一个)隐层,以及一个输出层构成,而且输入层与输出层的数量不一定是对等的。每一层都有若干个神经元,神经元之间有连接权重。还是上面的案例,识别手写数字,手写的数字要怎么转成输入呢?既然是手写,那么肯定是一张图片,图片由多个像素点组成,这些像素点可以构成一个输入,经过多层神经网络,输出10个数字,这个10个数字就代表了数字 0 ~ 9 的概率。神经元如何输入输出神经网络中的每个神经元都可以看成是一个简单的线性函数,下面我们构造一个简单的三层的神经网络来看看。如上图所示,n1 可以表示为:$$n_1 = w_{1,1}x_1 + w_{2,1}x_2 + w_{3,1}x_3 + b$$其中 w_{1,1} 表示神经元之间的权重,b 为一个常量,作为函数的偏移量。较小的权重可以弱化某个神经元对下一个神经元造成的影响,而较大的权重将放大信号。假设 w_{1,1} 为 0.1,w_{3,1} 为 0.7,那么 x3 对 n1 的影响要大于 x1。你可能会问,为什么每个神经元要与其他所有层的神经元相互连接?这里主要由两个原因:完全连接的形式相对容易的编写成计算机指令。在神经网络训练的过程中会弱化实际上不需要的连接(也就是某些连接权重会慢慢趋近于 0)。实际上通过计算得到 n1 后,其实不能立马用于后面的计算,还需要经过一个激活函数(一般为 sigmod 函数)。 其作用主要是引入非线性因素。如果神级网络中只有上面那种线性函数,无论有多少层,结果始终是线性的。实际案例为了方便计算,我们构造一个只有两层的神经网络,演示一下具体的计算过程。先通过线性函数求得一个 x 值,再把 x 值带入激活函数,得到 y1 的值。$$x = w_{1,1}x_1 + w_{2,1}x_2 = (1.0 * 0.9) + (0.5 * 0.3) = 1.05$$$$y_1 = 1 / (1 + e ^{-x}) = 1 / (1 + 0.3499) = 0.7408$$矩阵乘法其实上面的计算过程,很容易通过矩阵乘法的方式表示。矩阵这个东西,说简单点就是一个表格,或者一个二维数组。如下图所示,就是一个典型的矩阵。那么矩阵的乘法可以表示为:矩阵的乘法通常被成为点乘或者内积。如果我们将矩阵内的数字换成我们神经网络的输入和权重,你会发现原来前面的计算如此简单。获得点积后,只需要代入到激活函数,就能获得输出了。通过矩阵计算过程可以表示为:$$X_{hidden} = W_{input_hidden} · I_{input}O_{hidden} = sigmoid(X_{hidden})$$实际案例下面通过矩阵来表示一个三层神经网络的计算过程。上图只给出了输入层到隐层的计算过程,感兴趣可以自己手动计算下,隐层到输出层的计算过程。隐层到输出层的权重矩阵如下:反向传播进过一轮神经网络计算得到输出值,通常与我们实际想要的值是不一致的,这个时候我们会得到一个误差值(误差值就是训练数据给出的正确答案与实际输出值之间的差值)。但是这个误差是多个节点共同作用的结果,我们到底该用何种方式来更新各个连接的权重呢?这个时候我们就需要通过反向传播的方式,求出各个节点的误差值。下面我们代入具体值,进行一次计算。上图中可以看到 e_1 的误差值主要由 w_{1,1} 和 w_{2,1} 造成,那么其误差应当分散到两个连接上,可以按照两个连接的权重对误差 e_1 进行分割。$$e_1 * \frac{w_{1,1}}{w_{1,1} + w_{2,1}} = 0.8 * \frac{2}{2 + 3} = 0.32e_1 * \frac{w_{2,1}}{w_{1,1} + w_{2,1}} = 0.8 * \frac{3}{2 + 3} = 0.48$$同理对误差 e_2 进行分割,然后把两个连接处的误差值相加,就能得到输出点的前馈节点的误差值。然后在按照之前的方法将这个误差传播到前面的层,直到所有节点都能得到自己的误差值,这种方式被成为反向传播。使用矩阵乘法进行反向传播误差上面如此繁琐的操作,我们也可以通过矩阵的方式进行简化。这个矩阵中还是有麻烦的分数需要处理,那么我们能不能大胆一点,将分母直接做归一化的处理。这么做我们仅仅只是改变了反馈误差的大小,其误差依旧是按照比例来计算的。仔细观察会发现,与我们之前计算每层的输出值的矩阵点击很像,只是权重矩阵进行翻转,右上方的元素变成了左下方的元素,我们可以称其为转置矩阵,记为 w^T 。反向传播误差的矩阵可以简单表示为:$$error_{hidden} = W^{T}{hidden_output} · error{output}$$梯度下降在每个点都得到误差后,我们该按照何种方式来更新权重呢?这个时候就要使用到机器学习中常用的方式:梯度下级。更多细节可以参考我之前写的博客:梯度下降与线性回归通过不停的训练,我们就能改进神经网络,其本质就是不断地改变权重的大小,减小神经网络输出的误差值。最后就能够得到一个多层神经网络的模型,通过输入进行有效的预测。实战环境准备首先需要安装 python3 ,直接去 python 官网安装,尽量安装最新版,不推荐安装 python2 。安装好 python 环境之后,然后安装 virtualenv 以及相关依赖。# 升级 pip 到最新版本pip3 install –upgrade pip# 安装 virtualenv ,用于配置虚拟环境pip3 install –user –upgrade virtualenv正常情况下,当我们在使用 pip 进行包安装的时候,都是安装的全局包,相当于npm install -g。假如现在有两个项目,项目 A 依赖 simplejson@2 ,项目 B 依赖 simplejson@3,这样我们在一台机器上开发显得有些手足无措。这个时候 virtualenv 就能大展身手了,virtualenv 可以创建一个独立的 python 运行环境,也就是一个沙箱,你甚至可以在 virtualenv 创建的虚拟环境中使用与当前系统不同的 python 版本。# 配置虚拟环境cd /mlvirtualenv env# 启动虚拟环境# linuxsource env/bin/activate# windows./env/Scripts/activate启动后,如下(env) 在虚拟环境下安装所有模块依赖。# 安装模块和依赖(env) pip3 install –upgrade jupyter matplotlib numpy scipyjupyter:基于网页的用于交互计算的应用程序。其可被应用于全过程计算:开发、文档编写、运行代码和展示结果。numpy:数组计算扩展的包,支持高维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。scipy:基于numpy的扩展包,它增加的功能包括数值积分、最优化、统计和一些专用函数。matplotlib:基于numpy的扩展包,提供了丰富的数据绘图工具,主要用于绘制一些统计图形。scikit-learn:开源的Python机器学习库,它基于Numpy和Scipy,提供了大量用于数据挖掘和分析的工具,包括数据预处理、交叉验证、算法与可视化算法等一系列接口。启动 jupyterjupyter notebookjupyter 会在8888端口起一个服务,并自动打开浏览器。通过右上角的new,你就能创建一个项目了。创建项目后,我们很方便的在该页面上进行 python 代码的运行与输出。准备数据MNIST 是由美国的高中生和美国人口调查局的职员手写数字(0 ~ 9)图片。接下来要做的事情就是让我们的程序学习这些图片的信息,能够识别出输入的图片所代表的数字含义,这听上去好像有点难度,不着急,我们一步步来。这里准备了 MNIST 的训练数据,其中 train_100 为训练数据集,test_10 为测试数据集。在机器学习的过程中,我们一般会将数据集切分成两个,分别为训练集合测试集,一般 80% 的数据进行训练,保留 20% 用于测试。这里因为是 hello world 操作,我们只用 100 个数据进行训练,真实情况下,这种数据量是远远不够的。mnist_train_100.csvmnist_test_10.csv如果想用完整的数据进行训练,可以下载这个 csv 文件。https://pjreddie.com/media/files/mnist_train.csv观察数据下载数据后,将 csv (逗号分隔值文件格式)文件放入到 datasets 文件夹,然后使用 python 进行文件的读取。data_file = open(“datasets/mnist_train_100.csv”, ‘r’)data_list = data_file.readlines() # readlines方法用于读取文件的所有行,并返回一个数组data_file.close()len(data_list) # 数组长度为100打印第一行文本,看看数据的格式是怎么样的print(data_list[0])len(data_list[0].split(’,’)) # 使用 , 进行分割,将字符串转换为数组可以看到一行数据一共有 785 个数据,第一列表示这个手写数的真实值(这个值在机器学习中称为标签),后面的 784 个数据表示一个 28 * 28 的尺寸的像素值,流行的图像处理软件通常用8位表示一个像素,这样总共有256个灰度等级(像素值在0255 间),每个等级代表不同的亮度。下面我们导入 numpy 库,对数据进行处理,values[1:] 取出数组的第一位到最后并生成一个新的数组,使用 numpy.asfarray 将数组转为一个浮点类型的 ndarray,然后每一项除以 255 在乘以 9,将每个数字转为 0 ~ 9 的个位数,使用 astype(int) 把每个数再转为 int 类型,最后 reshape((28,28) 可以把数组转为 28 * 28 的二维数组。如果想了解更多 numpy 的资料,可以查看它的文档。import numpy as npvalues = data_list[3].split(’,’)image_array = (np.asfarray(values[1:]) / 255 * 9).astype(int).reshape(28,28)这样看不够直观,接下来使用 matplotlib ,将像素点一个个画出来。import matplotlib.pyplot%matplotlib inlinematplotlib.pyplot.imshow( np.asfarray(values[1:]).reshape(28,28), cmap=‘Greys’, interpolation=‘None’)搭建神经网络我们简单勾勒出神经网络的大概样子,至少需要三个函数:初始化函数——设定输入层、隐藏层、输出层节点的数量,随机生成的权重。训练——学习给定的训练样本,调整权重。查询——给定输入,获取预测结果。框架代码如下:# 引入依赖库import numpy as npimport scipy.specialimport matplotlib.pyplot# 神经网络类定义class neuralNetwork: # 初始化神经网络 def init(): pass # 训练神经网络 def train(): pass # 查询神经网络 def query(): pass初始化神经网络接下来让我们进行第一步操作,初始化一个神经网络。 # 初始化神经网络 def init(self, inputnodes, hiddennodes, outputnodes, learningrate): # 设置输入层、隐藏层、输出层节点的数量 self.inodes = inputnodes self.hnodes = hiddennodes self.onodes = outputnodes # 连接权重,随机生成输入层到隐藏层和隐藏层到输出层的权重 self.wih = np.random.rand(self.hnodes, self.inodes) - 0.5 self.who = np.random.rand(self.onodes, self.hnodes) - 0.5 # 学习率 self.lr = learningrate # 将激活函数设置为 sigmoid 函数 self.activation_function = lambda x: scipy.special.expit(x) pass生成权重生成连接权重使用 numpy 函数库,该库支持大维度数组以及矩阵的运算,通过numpy.random.rand(x, y)可以快速生成一个 x * y 的矩阵,每个数字都是一个 0 ~ 1 的随机数。因为导入库的时候使用了 import numpy as np 命令,所有代码中可以用 np 来代替 numpy。上面就是通过 numpy.random.rand 方法生成一个 3 * 3 矩阵的案例。减去0.5是为了保证生成的权重所有权重都能维持在 -0.5 ~ 0.5 之间的一个随机值。激活函数scipy.special 模块中包含了大量的函数库,利用 scipy.special 库可以很方便快捷的构造出一个激活函数:activation_function = lambda x: scipy.special.expit(x)查询神经网络 # 查询神经网络 def query(self, inputs_list): # 将输入的数组转化为一个二维数组 inputs = np.array(inputs_list, ndmin=2).T # 计算输入数据与权重的点积 hidden_inputs = np.dot(self.wih, inputs) # 经过激活函数的到隐藏层数据 hidden_outputs = self.activation_function(hidden_inputs) # 计算隐藏层数据与权重的点积 final_inputs = np.dot(self.who, hidden_outputs) # 最终到达输出层的数据 final_outputs = self.activation_function(final_inputs) return final_outputs查询神经网络的操作很简单,只需要使用 numpy 的 dot 方法对两个矩阵求点积即可。这里有一个知识点,就是关于 numpy 的数据类型,通过 numpy.array 方法能够将 python 中的数组转为一个 N 维数组对象 Ndarray,该方法第二个参数就是表示转化后的维度。上图是一个普通数组 [1, 2, 3] 使用该方法转变成二维数组,返回 [[1, 2, 3]]。该方法还有个属性 T,本质是调用 numpy 的 transpose 方法,对数组进行轴对换,如下图所示。通过转置我们就能得到一个合适的输入矩阵了。训练神经网络 # 训练神经网络 def train(self, inputs_list, targets_list): # 将输入数据与目标数据转为二维数组 inputs = np.array(inputs_list, ndmin=2).T targets = np.array(targets_list, ndmin=2).T # 通过矩阵点积和激活函数得到隐藏层的输出 hidden_inputs = np.dot(self.wih, inputs) hidden_outputs = self.activation_function(hidden_inputs) # 通过矩阵点积和激活函数得到最终输出 final_inputs = np.dot(self.who, hidden_outputs) final_outputs = self.activation_function(final_inputs) # 获取目标值与实际值的差值 output_errors = targets - final_outputs # 反向传播差值 hidden_errors = np.dot(self.who.T, output_errors) # 通过梯度下降法更新隐藏层到输出层的权重 self.who += self.lr * np.dot( (output_errors * final_outputs * (1.0 - final_outputs)), np.transpose(hidden_outputs) ) # 通过梯度下降法更新输入层到隐藏层的权重 self.wih += self.lr * np.dot( (hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), np.transpose(inputs) ) pass训练神经网络前半部分与查询类似,中间会将得到的差值通过求矩阵点积的方式进行反向传播,最后就是使用梯度下级的方法修正权重。其中 self.lr 为梯度下降的学习率,这个值是限制梯度方向的速率,我们需要经常调整这个值来达到模型的最优解。进行训练# 设置每一层的节点数量input_nodes = 784hidden_nodes = 100output_nodes = 10# 学习率learning_rate = 0.1# 创建神经网络模型n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, learning_rate)# 加载训练数据training_data_file = open(“datasets/mnist_train_100.csv”, ‘r’)training_data_list = training_data_file.readlines()training_data_file.close()# 训练神经网络# epochs 表示训练次数epochs = 10for e in range(epochs): # 遍历所有数据进行训练 for record in training_data_list: # 数据通过 ‘,’ 分割,变成一个数组 all_values = record.split(’,’) # 分离出图片的像素点到一个单独数组 inputs = (np.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01 # 创建目标输出值(数字 0~9 出现的概率,默认全部为 0.01) targets = np.zeros(output_nodes) + 0.01 # all_values[0] 表示手写数字的真实值,将该数字的概率设为 0.99 targets[int(all_values[0])] = 0.99 n.train(inputs, targets) pass pass# 训练完毕print(‘done’)验证训练结果# 加载测试数据test_data_file = open(“datasets/mnist_test_10.csv”, ‘r’)test_data_list = test_data_file.readlines()test_data_file.close()# 测试神经网络# 记录所有的训练值,正确存 1 ,错误存 0 。scorecard = []# 遍历所有数据进行测试for record in test_data_list: # 数据通过 ‘,’ 分割,变成一个数组 all_values = record.split(’,’) # 第一个数字为正确答案 correct_label = int(all_values[0]) # 取出测试的输入数据 inputs = (np.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01 # 查询神经网络 outputs = n.query(inputs) # 取出概率最大的数字,表示输出 label = np.argmax(outputs) # 打印出真实值与查询值 print(‘act: ‘, label, ’ pre: ‘, correct_label) if (label == correct_label): # 神经网络查询结果与真实值匹配,记录数组存入 1 scorecard.append(1) else: # 神经网络查询结果与真实值不匹配,记录数组存入 0 scorecard.append(0) pass pass # 计算训练的成功率scorecard_array = np.asarray(scorecard)print(“performance = “, scorecard_array.sum() / scorecard_array.size)完整代码要查看完整代码可以访问我的 github: deep_neural_network总结到这里整个深度神级网络的模型原理与实践已经全部进行完毕了,虽然有些部分概念讲解并不是那么仔细,但是你还可以通过搜索其他资料了解更多。感谢《Python神经网络编程》这本书,因为它才有了这个博客,如果感兴趣你也可以买来看看,这本书真的用很简单的语言描述了复杂的数学计算。人工智能现在确实是一个非常火热的阶段,希望感兴趣的同学们多多尝试,但是也不要一昧的追新,忘记了自己本来的优势。最后附上原文链接:深度神经网络原理与实践 ...

March 18, 2019 · 4 min · jiezi

开发者必看!探秘阿里云Hi购季开发者分会场:海量学习资源0元起!

摘要: 开发者分会场致力于帮助开发者学习了解阿里云最新技术,为开发者设计全方位的技术成长与进阶之路。2019阿里云云上Hi购季活动已经于2月25日正式开启,从已开放的活动页面来看,活动分为三个阶段: 2月25日-3月04日的活动报名阶段、3月04日-3月16日的新购满返+5折抢购阶段、3月16日-3月31日的续费抽豪礼+5折抢购阶段。活动核心亮点:作为阿里云-Hi购季最神秘的会场,开发者分会场在3月16日全网开放。下面,云栖社区小编就为各位开发者分享该会场的攻略:开发者分会场活动阵地关键词:学习,成长,进阶开发者分会场致力于帮助开发者学习了解阿里云最新技术,为开发者设计全方位的技术成长与进阶之路。开发者分会场包括小微项目,开发者工具,阿里开源,移动开发,企业研发效能,机器学习,学习认证交流,技术影响力&众包平台 八大技术场景。从个人开发者到企业开发者,到技术影响力打造,开发者分会场提供给开发者一站式的开发者服务及海量免费资源下载!开发者会场链接:https://www.aliyun.com/acts/product-section-2019/developer?utm_content=g_1000046885首先,先为大家送上开发者福利!Kindle、技术图书、T恤等好礼等你来抽取!100%中奖!点此进入抽奖:https://www.aliyun.com/acts/product-section-2019/developer下面小编就带着大家去逐个了解每个开发者场景:1. 小微项目小微项目提供域名注册,商标服务,网站部署等服务,帮助用户在阿里云上快速搭建应用。域名注册互联网应用始于域名,高记忆度的域名既是吸引用户访问网站的“门牌”,又是电子商务的“经营场所”。阿里云旗下品牌万网域名注册蝉联国内市场NO.1,目前有超过4000万域名在万网注册。万网为用户提供快速稳定,易用安全及高性价比的域名服务,目前可支持域名注册,域名交易,域名预定,域名转入,域名云解析等等服务。帮助用户智能查询,快速注册,通过强大的域名自助平台轻松管理域名,同时提供独具特色的隐私保护,安全锁,自检服务,以及贴心的到期续费提醒,全方位保护用户的域名。商标注册商标注册流程包括创建订单,材料审核,提交商标局,获取回执,受理通过,初审公告,注册公告,核发证书等8个步骤。阿里云商标注册服务,提供一站式标准服务,最快1分钟极速申报,实时掌握申请进度。用户可以根据自身情况选择自助注册申请,专家辅助申请及担保注册申请。同时阿里云也提供商标续展申请及商标数据监控服务,目前用户可免费体验商标数据监控服务。网站部署阿里云提供定制建站服务,1V1网站策划设计,量身打造企业互联网形象可视化管理后台便捷维护,支持软件上云。阿里云提供千套模版,涵盖物流,化工业,知识产权服务,教育机构,能源设备等等。集成41中控件,用户可随意搭配。零基础学员也可以建站,APP、小程序、电商网站、云计算架构等轻松搭建。同时根据用户需求选择个性化网站定制开发。2. 开发者工具阿里云SDK平台通过调用阿里云SDK,用户不需要复杂编程即可访问云服务器、云数据库RDS、云监控等多个阿里云服务。阿里云SDK平台提供全产品线相关sdk,包括Java SDK、Go SDK、C SDK、Python SDK、Node.js SDK、Ruby SDK、PHP SDK、Android SDK、.Net SDK、IOS SDK等。阿里云API平台阿里云提供了丰富的 API 供用户使用。用户可在线查询云产品API文档,在线接口调试功能,同步生成对应SDK Demo代码,并对API文档进行整合。除此之外,阿里云推荐行业应用API及定制API解决方案,如通用文字识别,图像人脸检测,图片文字识别API等,可支持海量全企业应用,方便用户快速调用。3. 阿里开源阿里技术架构图首次曝光,提供25个开源库。大前端层开源库有Weex,ice,vlayout,ARouler,atals,AndFix。微服务层包括服务发现,配置管理,服务管理平台Nacos,分布式数据流平台,RocketMQ,微服务开发一站式解决方案Spring Cloud Alibaba,分布式事物解决方案Fescar,微服务架构解决方案Dubbo,控制流组件Sentinel。开源的数据库有关系型数据库AliSQL,关系型数据的分布式处理系统cobar,数据传输与同步服务otter、canal、DataX,以及大数据可视化图表库BizCharts。运行时可使用p2p镜像分发工具Dragonfly和企业级富容器引擎PouchContainer。操作系统层开源产品是AliKernel。4. 移动开发阿里云移动研发平台(Enterprise Mobile Application Studio, EMAS),面向企业服务市场,期望将阿里巴巴移动互联网近十年在移动互联网行业沉淀的DevOps研发支撑能力,移动App,基础中间件能力开放给用户。EMAS平台宗旨是提供一站式移动开发解决方案,帮助传统企业快速完成业务移动化的转型升级目标。EMAS提供的服务覆盖移动APP研发全生命周期的组件服务,提供APP内反馈、业务行位分析、用户消息推动等运维服务。另外,还包括APP真机自动化测试、线上APP质量、性能实施分析服务。帮助开发者解决研发阶段碰到的流量劫持、线上问题修复等痛点。目前阿里云移动开发服务用户包括猫途鹰,头条,CCTV,中国平安,汽车之家等等国内知名企业。阿里云为开发者提供了几种不同移动开发套餐,包括免费版,基础版,标准版及高级版。开发者可按需选择。5. 企业研发效能云效,一站式企业协同研发云,源于阿里巴巴多年先进的管理理念和工程实践,提供从“需求->开发->测试->发布->运维->运营”端到端的协同服务和研发工具支撑。云效涵盖项目协作域、研发域、测试域、运维域的一站式企业研发协同云服务。目前,云效主要服务于企业管理层、业务负责人、研发工程师、测试工程师、PM/PMO、ScrumMaster等企业角色。云效致力于让协同更简单,让交付更高效。云效为用户提供项目管理,持续交付,代码托管,自动化测试及智能运维等服务。6. 机器学习阿里云机器学习和深度学习平台PAI(Platform of Artificial Intelligence),为传统机器学习提供100余种算法和大规模分布式计算的服务,覆盖回归、分类、聚类、文本分析等算法。提供企业分布式计算能力,轻松实现大规模数据处理。为深度学习客户提供单机多卡、多机多卡的高性价比资源服务,支持最新的深度学习开源框架,并提供阿里云深度优化的Tensorflow,性能与速度更佳。帮助开发者和企业客户弹性扩缩计算资源,轻松实现在线预测服务,提供可视化操作界面,通过托拉拽的方式拖动算法组件拼接实验。一站式服务包括数据清洗,特征工程,机器学习算法,评估,在线预测以及离线调度等都可以在机器学习平台(PAI)一站式体验。PAI泛推荐解决方案四部曲阿里云机器学习PAI产品为了帮助不同企业的快速实现个性化推荐的应用,推出了难度系数由浅到深的技术方案。方案一:基于Online Learning的流式算法推荐(免费邀测)方案二:基于深度学习模型Wide&Deep的推荐(限时5折)方案三:基于协同过滤算法的推荐方案四:基于对象特征的推荐以上所有方案都已经通过模型Demo的内嵌到PAI的产品中。机器学习应用实践阿里云机器学习平台PAI提供多种行业应用实践案例,帮助企业解决痛点。新浪微博MaxCompute+PAI:面对当前超大规模的数据量时,提供支持百亿特征维度的算法,提升平台算法处理能力。汇合营销DataWorks+PAI+AnalyticDB+MaxCompute:提供高效低成本的海量数据分析,数据查询分析的实时性,精准化广告营销。PING++MaxCompute+PAI:对海量数据进行数据分析与业务创新从而提高用户黏性,搭建安全、可靠、稳定的大数据平台。天弘基金MaxCompute+PAI:面对多用户场景,提升数据清算效率,降低成本。为用户推荐产品,画像分析,识别敏感数据。7. 学习认证交流云大学阿里云大学作为阿里云泛云生态人才培养的平台,旨在充分利用学院制的教学方式,结合互联网的特点与优势,为用户提供严谨的体系化课程与实验环境。资深行业专家辅导+阿里云真实环境实操的方式,认证讲师在线辅导,班级助教在线服务。目前包含专业有云计算,大数据分析,大数据开发,云安全,人工智能等。此外,还精选100余门免费课程,囊括云计算、大数据、编程语言和物联网(IoT)的行业热点技术,帮助学员简单入门,上手学习。云大学开放实验室还提供真实云环境、精品实验项目、详细实验文档,帮助用户快速上手并掌握阿里云产品 。云栖社区云栖社区是面向开发者的开放型技术平台。源自阿里云,服务于云计算技术全生态。包含博客、问答、培训、设计研发、资源下载等产品,以分享专业、优质、高效的技术为己任。提供阿里云最新技术活动,资源分享,直播课程,线下沙龙,专家分享等内容。8. 技术影响力MVP&云众包平台阿里云MVP阿里云最有价值专家,简称 MVP(Most Valuable Professional),是专注于帮助他人充分了解和使用阿里云的技术实践领袖。目前,阿里云已有来自全球26个国家的419位MVP成员。阿里云MVP等级分为初级,黄金,铂金和砖石四大级别。可享受的权益包括MVP定制礼包、专享服务权益、阿里云专家面对面、阿里云官方活动主推、全球年度峰会(定向邀约)、阿里云创客大赛提名、参观阿里巴巴总部、MVP 实验室、云栖大会城市峰会门票、云栖大会讲师邀请及全球技术游学等11种权益。初级MVP可立即享受前6种权益,逐级增加两项权益。同时,阿里云MVP成员也会通过分享自身行业数字化转型实践,技术干货的方式,手把手教用户使用阿里云,将开发者的声音反映到阿里云的技术路线图上。云众包平台阿里云众包平台是阿里云网站下设的一个子频道(zhongbao.aliyun.com),是阿里云提供的产品、技术或服务进行交易的网络平台。由需求方(买家)发布项目需求,阿里云认证服务商(卖家)接单并完成项目开发,需求方在项目验收后完成交易。众包平台目前有八大集市,包括网站建设、软件开发、云服务与咨询、办公软件、企业服务、设计类、营销类、大数据。对于众包平台的用户,仅需1分钟发布需求,从需求梳理到完成售后为您提供全套服务。阿里云有一套完整的从售前、交易到售后的保障体系,使其关注在产品及服务的选择而不是对交易的担忧。最后,欢迎大家参与我们的调研项目,提出您宝贵的意见:https://survey.aliyun.com/apps/zhiliao/UkPNoDNPC阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 18, 2019 · 1 min · jiezi

2019五个最棒的机器学习课程

摘要: 爱学习的朋友们,你们的福利来了!2019五个最棒的机器学习课程!!凭借强大的统计学基础,机器学习正在成为最有趣,节奏最快的计算机科学领域之一,目前已经有无穷无尽的行业和应用正在使用机器学习使它们更高效和智能。聊天机器人、垃圾邮件过滤、广告投放、搜索引擎和欺诈检测是机器学习模型正在实际应用于日常生活的几个例子。机器学习到底是什么呢?我认为机器学习是让我们找到模式并为人类无法做的事情创建数学模型。机器学习课程与包含探索性数据分析,统计,通信和可视化技术等主题的数据科学课程不同,它更侧重于教授机器学习算法,如何以数学方式工作,以及如何在编程语言中使用它们。以下是今年五大机器学习课程的简要回顾。最好的五个机器学习课程:1. 机器学习-Coursera2. 深度学习专项课程-Coursera3. 使用Python进行机器学习-Coursera4. 高级机器学习专项课程-Coursera5. 机器学习-EdX什么是一个非常好的机器学习课程?标准:上面的每门课程都遵循以下标准:严格关注机器学习;使用免费的开源编程语言,即Python,R或Octave;这些开源的语言都有很多免费的开源库;包含练习和实践经验的编程任务;解释算法如何以数学方式工作;有吸引力的讲师和有趣的讲座;有了这个标准,很多课程都会被淘汰,为了让自己沉浸其中并尽可能快速全面地学习ML,我相信除了在线学习之外,你还应该寻找各种书籍。以下是两本对我的学习经历产生重大影响的书籍。两本优秀的书籍伴侣除了参加下面的任何视频课程,如果你对机器学习还不熟悉,你应该考虑阅读以下书籍:统计学习简介,可在线免费获取。本书提供了令人难以置信的清晰直接的解释和示例,以提高你对许多基本机器学习技术的整体数学直觉。而去更多地是关于事物的理论方面,但它确实包含许多使用R编程语言的练习和例子。使用Scikit-Learn和TensorFlow进行动手机器学习,可通过Safari订阅获得。这是对前一本书的一个很好的补充,因为本文主要关注使用Python进行机器学习的应用。本书将强化你的编程技巧,并向你展示如何立即将机器学习应用于项目。现在,让我们来看看课程描述和评论。1:机器学习 - Coursera此课程的创作者是Andrew Ng,一个斯坦福大学教授,谷歌大脑、Coursera的创始人之一。本课程使用开源编程语言Octave而不是Python或R进行教学。对于某些人来说,这可能是不太友好,但如果你是一个完整的初学者,Octave实际上是一种最简单学习ML基础知识的方法。总的来说,课程材料非常全面,并且由Ng直观地表达,该课程完整地解释了理解每个算法所需的所有数学,包括一些微积分解释和线性代数的复习,课程相当独立,但事先对线性代数的一些了解肯定会有所帮助。提供者:Andrew Ng,斯坦福大学费用:免费审核,证书79美元课程结构:单变量的线性回归回顾线性代数多变量的线性回归Octave/Matlab教程Logistic回归正则化神经网络:表示神经网络:学习应用机器学习的建议机器学习系统设计支持向量机降维异常检测推荐系统大规模机器学习应用示例:Photo OCR如果你可以承诺完成整个课程,你将在大约四个月内掌握机器学习的基础知识。之后,你可以轻松地进入更高级或专业的主题,如深度学习,ML工程或任何其他引起你兴趣的话题。毫无疑问,这是新手开始的最佳课程。2:深度学习专项课程-Coursera同样由Andrew Ng教授,这是一个更高级的课程系列,适合任何有兴趣学习神经网络和深度学习的人。每门课程的作业和讲座都使用Python编程语言,并将TensorFlow库用于神经网络。这第一个机器学习课程的很好的后续,因为你现在将接触使用Python进行机器学习。提供者:Andrew Ng,deeplearning.ai费用:免费审核,证书每月49美元课程结构:1. 神经网络与深度学习深度学习简介神经网络基础知识浅层神经网络深度神经网络2. 改进神经网络:超参数调整,正则化和优化深度学习的实践方面优化算法超参数调整,批量标准化和编程框架3. 构建机器学习项目ML策略(1)ML策略(2)4. 卷积神经网络卷积神经网络的基础深度卷积模型:案例研究物体检测特殊应用:人脸识别和神经风格转移5. 序列模型递归神经网络自然语言处理和Word嵌入序列模型和注意机制为了理解本课程中介绍的算法,你应该熟悉线性代数和机器学习。如果你需要一些建议来获取所需的数学,请参阅本文末尾的学习指南。3:使用Python进行机器学习-Coursera这是另一个初学者课程,这个课程仅关注最基本的机器学习算法。本课程使用Python教学,并且对数学的要求不是很高。通过每个模块,你将有机会使用交互式Jupyter笔记本来完成你刚学过的新概念。每个笔记本都增强了你的知识,并为你提供了在实际数据上使用算法的具体说明。提供者:IBM价格:免费审核,证书每月39美元课程结构:机器学习简介回归分类聚类推荐系统项目本课程最好的一点是为每种算法提供实用的建议。当引入新算法时,老师会向你提供它的工作原理,它的优点和缺点,以及你应该使用它的哪种情况。这些点经常被排除在其他课程之外,这些信息对于新学员来说非常重要。4:高级机器学习专项课程-Coursera这是另一个高级系列课程,涉及了非常多的网络类型。如果你有兴趣尽可能多地使用机器学习技术,这个课程很关键。本课程的教学非常棒,由于其先进性,你需要学习更多的数学。本课程涵盖的大部分内容对许多机器学习项目至关重要。提供者:国立研究大学高等经济学院成本:免费审核,每月49美元的证书课程:1. 深度学习简介优化简介神经网络简介深度学习图像无监督表示学习Dee学习序列项目2. 如何赢得数据科学竞赛:向顶级Kagglers学习介绍和回顾关于模型的特征处理和生成最终项目描述探索性数据分析验证数据泄漏度量标准优化高级特征工程-1超参数优化高级特征工程-2Ensembling项目3. 机器学习的贝叶斯方法贝叶斯方法和共轭先验的介绍期望最大化算法变分推断和潜在Dirichlet分配(LDA)马尔可夫链蒙特卡洛变分自动编码器高斯过程和贝叶斯优化项目4. 实践强化学习简介:我为什么要关心?RL的核心:动态编程无模型方法基于近似值的方法基于政策的方法探索5. 计算机视觉中的深度学习图像处理和计算机视觉入门视觉识别的卷积特征物体检测对象跟踪和动作识别图像分割与合成6. 自然语言处理简介和文本分类语言建模和序列标记语义的向量空间模型序列到序列任务对话系统7. 通过机器学习解决大型强子对撞机挑战数据科学家的粒子物理入门粒子识别寻找稀有衰变中的新物理学在新的CERN实验中用机器学习搜索暗物质提示探测器优化完成这一系列课程大约需要8到10个月,所以如果你从今天开始,在不到一年的时间里,你将学到大量的机器学习算法,并能够开始处理更多尖端的应用程序。在这几个月中,你还将创建几个真正的项目,使计算机学习如何阅读,查看和播放。这些项目将成为你投资组合的理想选择,并将使你的GitHub对任何感兴趣的雇主都非常活跃。5:机器学习-EdX这是一个高级课程,具有文中任何其他课程的最高数学先决条件。你需要非常牢固地掌握线性代数、微积分、概率和编程。该课程在Python或Octave中都有编程作业,但该课程不教授任何一种语言。与其他课程的不同之处是对机器学习的概率方法的讲解。如果你有兴趣阅读教科书,例如机器学习:概率视角,这是硕士课程中最流行的数据科学书籍之一。提供者:哥伦比亚大学费用:免费审核,证书300美元课程结构:最大似然估计,线性回归,最小二乘法岭回归,偏差方差,贝叶斯规则,最大后验推断最近邻分类,贝叶斯分类器,线性分类器,感知器Logistic回归,Laplace逼近,核方法,高斯过程最大边距,支持向量机(SVM),树木,随机森林,提升聚类,K均值,EM算法,缺失数据高斯混合,矩阵分解非负矩阵分解,潜在因子模型,PCA和变化马尔可夫模型,隐马尔可夫模型连续状态空间模型,关联分析模型选择,后续步骤课程中的许多主题都包含在针对初学者的其他课程中,但数学并未在这里淡化。如果你已经学习了这些技术,有兴趣深入研究数学,并希望从事实际推导出某些算法的编程作业,那么请学习本课程。学习指南这里是你学习机器学习之旅的快速指南,首先,我们将介绍大多数机器学习课程的先决条件。课程先决条件高级的课程在开始之前需要以下知识:线性代数概率微积分程序设计这些是能够理解机器学习如何在幕后工作的简单组件。许多初级课程通常要求至少一些编程和熟悉线性代数基础知识,例如向量,矩阵。本文的第一个课程,Andrew Ng的机器学习,包含了你需要的大部分数学的复习,但是如果你以前没有学过线性代数,那么同时学习机器学习和线性代数可能会很困难。另外,我建议学习Python,因为大多数优秀的ML课程都使用Python。如果你学习使用Octave的Andrew Ng的机器学习课程,你应该在课程期间或之后学习Python,因为你最终需要它。另外,另一个很棒的Python资源是dataquest.io,它在他们的交互式浏览器环境中有一堆免费的Python课程。在学习了必备必需品之后,你就可以开始真正理解算法的工作原理了。基本算法在机器学习中有一套基本的算法,每个人都应该熟悉并具有使用经验。这些是:线性回归Logistic回归k-Means聚类k-最近邻居支持向量机(SVM)决策树随机森林朴素贝叶斯这些是必需品,上面列出的课程基本上包含所有这些。在开展新项目时,了解这些技术如何工作以及何时使用它们将非常重要。在基础知识之后,一些更先进的学习技巧将是:集成学习Boosting降维强化学习神经网络与深度学习这只是一个开始,但这些算法通常是你在最有趣的机器学习解决方案中看到的,它们是你工具箱的有效补充。就像基本技术一样,你学习的每一个新工具都应该养成一个习惯,立即将它应用到项目中,以巩固你的理解,并在需要复习时有所回头。解决一个项目在线学习机器学习具有挑战性并且非常有益。重要的是要记住,只是观看视频和参加测验并不意味着你真的在学习这些材料。如果你正在进行的项目使用不同的数据并且目标与课程本身不同,你将学到更多。一旦你开始学习基础知识,你应该寻找可以应用这些新技能的有趣数据。上面的课程将为你提供何时应用某些算法的直觉,因此立即将它们应用于你自己的项目中是一种很好的做法。通过反复试验,探索和反馈,你将发现如何尝试不同的技术,如何衡量结果,以及如何分类或预测。有关要采用何种ML项目的一些灵感,请参阅此示例列表。解决项目可以让你更好地理解机器学习环境,当你深入了解深度学习等更高级的概念时,实际上可以使用无限数量的技术和方法来理解和使用。阅读新研究机器学习是一个快速发展的领域,每天都有新的技术和应用出现。一旦你通过基础知识,你应该有能力通过一些关于你感兴趣的主题的研究论文。有几个网站可以获得符合你标准的新论文的通知。Google学术搜索始终是一个好的开始,输入“机器学习”和“深度学习”等关键词,或者你感兴趣的任何其他内容,点击左侧的“创建提醒”链接即可收到电子邮件。让它成为每周习惯,阅读这些警报,扫描文件,看看它们是否值得阅读,然后承诺了解正在发生的事情。如果它与你正在处理的项目有关,请查看你是否可以将这些技术应用于你自己的问题。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

March 15, 2019 · 1 min · jiezi

大众点评信息流基于文本生成的创意优化实践

引言信息流是目前大众点评除搜索之外的第二大用户获取信息的入口,以优质内容来辅助用户消费决策并引导发现品质生活。整个大众点评信息流(下文简称点评信息流)围绕个性化推荐去连接用户和信息,把更好的内容推荐给需要的用户。信息流推荐系统涉及内容挖掘、召回、精排、重排、创意等多层机制和排序。本文主要围绕创意部分的工作展开,并选取其中重要的文本创意优化做介绍,分为三个部分:第一部分阐述几个重点问题,包括创意优化是什么,为什么做,以及挑战在哪里;第二部分讲述领域内的应用及技术进展;第三部分介绍我们创意优化的实践,最后做个总结。什么是创意优化创意是一个宽泛的概念,它作为一种信息载体对受众展现,可以是文本、图像、视频等任何单一或多类间的组合,如新闻的标题就是经典的创意载体。而创意优化,作为一种方法,指在原有基础上进一步挖掘和激活资源组合方式进而提升资源的价值。在互联网领域产品中,往往表现为通过优化创意载体来提升技术指标、业务目标的过程,在信息流中落地重点包括三个方向:文本创意:在文本方面,既包括了面向内容的摘要标题、排版改写等,也包括面向商户的推荐文案及内容化聚合页。它们都广泛地应用了文本表示和文本生成等技术,也是本文的主要方向。图像创意:图像方面涉及到首图或首帧的优选、图像的动态裁剪,以及图像的二次生成等。其他创意:包括多类展示理由(如社交关系等)、元素创意在内的额外补充信息。核心目标与推荐问题相似,提升包括点击率、转化率在内的通用指标,同时需要兼顾考量产品的阅读体验包括内容的导向性等。关于“阅读体验”的部分,这里不作展开。为什么要做文本生成首先文本创意本身为重要的业务发展赋能。在互联网下半场,大众点评平台(下称点评平台)通过内容化去提升用户停留时长,各类分发内容类型在不停地增加,通过优化创意来提升内容的受众价值是必由之路。其次,目前很多内容类型还主要依赖运营维护,运营内容天然存在覆盖少、成本高的问题,无法完全承接需要内容化改造的场景。最后,近几年深度学习在NLP(Natural Language Processing,自然语言处理)的不同子领域均取得了重大突破。更重要的是,点评平台历经多年,积淀了大量可用的内容数据。从技术层面来说,我们也有能力提供系统化的文本创意生成的解决方案。对此,我们从文本创意面向对象的角度定义了两类应用形态,分别是面向内容的摘要标题,以及面向商户的推荐文案与内容化聚合页。前者主要应用信息流各主要内容场景,后者则主要应用在信息流广告等内容化场景。这里提前做下产品的简单介绍,帮助大家建立一个立体化的感知。摘要标题:顾名思义,就是针对某条分发内容生成摘要作标题展示。点评内容源非常多样,但超过95%内容并没有原生标题,同时原生标题质量和多样性等差异也极大。商户文案:生成有关单个商户核心卖点的描述,一般形式为一句话的短文案。内容聚合:生成完整的内容页包括标题及多条文案的短篇推荐理由,不同于单商户文案的是,既需要考虑商户的相关性,又要保证理由的多样性。最后需要明确的是,我们做文本创意优化最大的初心,是希望通过创意这个载体显式地连接用户、商户和内容。我们能够知道用户关注什么,知道哪些内容说什么,如何引导用户看,知道哪些商户好、好在哪里,将信息的推荐更进一步。而非为了生成而生成。面临的挑战文本创意优化,在业务和技术上分别面临着不同的挑战。首先业务侧,启动创意优化需要两个基础前提:第一,衔接好创意优化与业务目标,因为并不是所有的创意都能优化,也不是所有创意优化都能带来预期的业务价值,方向不对则易蹚坑。第二,创意优化转化为最优化问题,有一定的Gap。其不同于很多分类排序问题,本身相对主观,所谓“一千个人眼中有一千个哈姆雷特”,创意优化能不能达到预期的业务目标,这个转化非常关键。其次,在技术层面,业界不同的应用都面临不一样的挑战,并且尝试和实践对应的解决方案。对文本创意生成来说,我们面临的最大的挑战包括以下三点:带受限的生成 生成一段流畅的文本并非难事,关键在于根据不同的场景和目标能控制它说什么、怎么说。这是目前挑战相对较大的一类问题,在我们的应用场景中都面临这个挑战。业务导向 生成能够提升业务指标、贴合业务目标的内容。为此,对内容源、内容表示与建模上提出了更高的要求。高效稳定 这里有两层含义,第一层是高效,即模型训练预测的效果和效率;第二层是稳定,线上系统应用,需要具备很高的准确率和一套完善的质量提升方案。2. 文本生成问题综述我们整体的技术方案演进,可以视作近两年NLP领域在深度学习推动下发展的一个缩影。所以在展开之前,先谈一谈整个领域的应用及技术进展。2.1 相关领域应用在学界相关领域,文本生成被称为NLG,其相关任务目标是根据输入数据生成自然语言的文本。而我们在NLP领域使用更多的一般是NLU(Nature Language Understanding 自然语言理解)类任务,如文本分类、命名实体识别等,NLU的目标则是将自然语言文本转化成结构化数据。NLU和NLG两者表向上是一对相反的过程,但其实是紧密相连的,甚至目前很多NLU的任务都受到了生成式模型中表示方法的启发,它们更多只在最终任务上有所区别。文本生成也是一个较宽泛的概念,如下图所示,广义上只要输出是自然语言文本的各类任务都属于这个范畴。但从不同的输入端可以划分出多种领域应用,从应用相对成熟的连接人和语言的NMT(神经机器翻译),到2019年初,能续写短篇故事的GPT2都属于Text2Text任务。给定结构化数据比如某些信息事件,来生成文本比如赛事新闻的属于Data2Text类任务,我们的商户文案也属此类。另外还有Image2Text等,这块也逐渐在出现一些具有一定可用性又让人眼前一亮的应用,比如各种形式的看图说话。2.2 相关技术与进展文本生成包含文本表示和文本生成两个关键的部分,它们既可以独立建模,也可以通过框架完成端到端的训练。文本生成文本生成要解决的一个关键问题,是根据给定的信息如何生成一段文本句子。这是一个简单输入复杂输出的任务,问题的复杂度太大,至今在准确和泛化上都没有兼顾的非常好的方法。2014年提出的Seq2Seq Model,是解决这类问题一个非常通用的思路,本质是将输入句子或其中的词Token做Embedding后,输入循环神经网络中作为源句的表示,这一部分称为Encoder;另一部分生成端在每一个位置同样通过循环神经网络,循环输出对应的Token,这一部分称为Decoder。通过两个循环神经网络连接Encoder和Decoder,可以将两个平行表示连接起来。另外一个非常重要的,就是Attention机制,其本质思想是获取两端的某种权重关系,即在Decoder端生成的词和Encoder端的某些信息更相关。它也同样可以处理多模态的问题,比如Image2Text任务,通过CNN等将图片做一个关键特征的向量表示,将这个表示输出到类似的Decoder中去解码输出文本,视频语音等也使用同样的方式(如下图所示)。可见Encoder-Decoder是一个非常通用的框架,它同样深入应用到了文本生成的三种主流方法,分别是规划式、抽取式和生成式,下面看下这几类方法各自的优劣势:规划式:根据结构化的信息,通过语法规则、树形规则等方式规划生成进文本中,可以抽象为三个阶段。宏观规划解决“说什么内容”,微观规划解决“怎么说”,包括语法句子粒度的规划,以及最后的表层优化对结果进行微调。其优势是控制力极强、准确率较高,特别适合新闻播报等模版化场景。而劣势是很难做到端到端的优化,损失信息上限也不高。抽取式:顾名思义,在原文信息中抽取一部分作为输出。可以通过编码端的表征在解码端转化为多种不同的分类任务,来实现端到端的优化。其优势在于:能降低复杂度,较好控制与原文的相关性。而劣势在于:容易受原文的束缚,泛化能力不强。生成式:通过编码端的表征,在解码端完成序列生成的任务,可以实现完全的端到端优化,可以完成多模态的任务。其在泛化能力上具有压倒性优势,但劣势是控制难度极大,建模复杂度也很高。目前的主流的评估方法主要基于数据和人工评测。基于数据可以从不同角度衡量和训练目标文本的相近程度,如基于N-Gram匹配的BLUE和ROUGE等,基于字符编辑距离(Edit Distance)等,以及基于内容Coverage率的Jarcard距离等。基于数据的评测,在机器翻译等有明确标注的场景下具有很大的意义,这也是机器翻译领域最先有所突破的重要原因。但对于我们创意优化的场景来说,意义并不大,我们更重要的是优化业务目标,多以线上的实际效果为导向,并辅以人工评测。另外,值得一提的是,近两年也逐渐涌现了很多利用GAN(Generative Adversarial Networks,生成对抗网络)的相关方法,来解决文本生成泛化性多样性的问题。有不少思路非常有趣,也值得尝试,只是GAN对于NLP的文本生成这类离散输出任务在效果评测指标层面,与传统的Seq2Seq模型还存在一定的差距,可视为一类具有潜力的技术方向。文本表示前文提到,在Encoder端包括有些模型在Decoder端都需要对句子进行建模,那如何设计一个比较好的模型做表示,既可以让终端任务完成分类、序列生成,也可以做语义推理、相似度匹配等等,就是非常重要的一个部分。那在表示方面,整个2018年有两方面非常重要的工作进展:Contextual Embedding:该方向包括一系列工作,如最佳论文Elmo(Embeddings from Language Models),OpenAI的GPT(Generative Pre-Training),以及谷歌大力出奇迹的BERT(Bidirectional Encoder Representations from Transformers)。解决的核心问题,是如何利用大量的没标注的文本数据学到一个预训练的模型,并通过通过这个模型辅助在不同的有标注任务上更好地完成目标。传统NLP任务深度模型,往往并不能通过持续增加深度来获取效果的提升,但是在表示层面增加深度,却往往可以对句子做更好的表征,它的核心思想是利用Embedding来表征上下文的的信息。但是这个想法可以通过很多种方式来实现,比如ELMo,通过双向的LSTM拼接后,可以同时得到含上下文信息的Embedding。而Transformer则在Encoder和Decoder两端,都将Attention机制都应用到了极致,通过序列间全位置的直连,可以高效叠加多层(12层),来完成句子的表征。这类方法可以将不同的终端任务做一个统一的表示,大大简化了建模抽象的复杂度。我们的表示也经历了从RNN到拥抱Attention的过程。Tree-Based Embedding:另外一个流派则是通过树形结构进行建模,包括很多方式如传统的语法树,在语法结构上做Tree Base的RNN,用根结点的Embedding即可作为上下文的表征。Tree本身可以通过构造的方式,也可以通过学习的方式(比如强化学习)来进行构建。最终Task效果,既和树的结构(包括深度)有关,也受“表示”学习的能力影响,调优难度比较大。在我们的场景中,人工评测效果并不是很好,仍有很大继续探索的空间。3. 探索与实践该部分介绍从2017年底至今,我们基于文本生成来进行文本创意优化的一些探索和实践。3.1 内容源启动文本生成,首先要了解内容本身,数据的数量和质量对我们的任务重要性无须赘述,这是一切模型的基础。目前我们使用到的数据和大致方法包括:平台渠道:用户评价、用户笔记、Push、攻略、视频内容、榜单、团单等等。第三方渠道:合作获取了很多第三方平台的内容来补缺,同时运营侧辅助创意撰写和标注了大量内容,他们同样贡献了可观的数据量。标注数据:最稀缺的永远是标注数据,尤其是符合业务目标的标注。为此,我们在冷启动阶段设计了E&E(Explore and Exploit,探索与利用)机制,有意识地积累线上标注,同时尽量引入更多第三方的标注源。但这些内容的不同特点,也带来了不同的挑战:内容多样:前面提到的这些内容的结构化程度各不相同,长短差异也极大,对内容表示提出了很高的要求。质量不一:源内容非常丰富,但事实上质量、质感远远没有达到理想的标准。尤其是占绝对大头的UGC的内容,不做好两端的质控将极大影响业务目标的优化,甚至会造成体验问题。聚焦商户:平台99%以上的内容,都以商户作为核心载体,这个对商户的理解和表示同样提出了很高的要求,尤其是在内容化升级的场景下。场景差异:不同的场景、不同的应用,对模型能力的侧重和优化目标不一样。比如内容和商户,前者要求要有很高的准确率,同时保证优化线上效果;后者更多的是要求有较强的泛化性,并对质感进行优化。3.2 基础能力模块所以,文本创意优化要在业务侧落地产生效果,还需应用到NLP领域诸多方向的技术。下图是抽象的整个文本生成应用的基础能力模块,包括用于源和端质量控制的文本质量层,构建Context表示的文本表示层,以及面向业务优化的端到端模型层,其中很多技术应用了公司其他兄弟团队包括内容挖掘组、NLP中心、离线计算组的出色成果。如针对负面内容过滤的情感分析,多项针对性的文本分类,针对商户表示的标签挖掘等,在这里特别向他们表示感谢。3.3 信息流标题实践双平台的内容需要在信息流分发,在创意上最先优化的就是标题,这是用户仅能看到两个要素之一(另一个为首图),而我们超过95%的内容并没有原生标题,同时原生标题也存在诸如多样性差非场景导向等问题,还有二次优化的空间。但是,有两点比较大的挑战,在不同任务上具象可能不一样。它们的本质并没有改变,部分也是业界难点:1. 两个受限条件:第一,需要以线上点击率转化率为优化目标,线上没效果,写的再好意义都不大;第二,需要与原文强相关,并且容错空间极小,一出现就是Case。2. 优化评估困难:第一,模型目标和业务目标间存在天然Gap;第二,标注数据极度稀缺,离线训练和线上实际预测样本数量之间,往往差距百倍。对此,我们通过抽取式和生成式的相结合互补的方式,并在流程和模型结构上着手进行解决。抽取式标题抽取式方法在用户内容上有比较明显的优势:首先控制力极强,对源内容相关性好,改变用户行文较少,也不容易造成体验问题,可以直接在句子级别做端到端优化。对此,我们把整个标题建模转变为一个中短文本分类的问题,但也无法规避上文提到两个大挑战,具体表现在:在优化评估上,首先标题创意衡量的主观性很强,线上Feeds的标注数据也易受到其他因素的影响,比如推荐排序本身;其次,训练预测数据量差异造成OOV问题非常突出,分类任务叠加噪音效果提升非常困难。对此,我们重点在语义+词级的方向上来对点击/转化率做建模,同时辅以线上E&E选优的机制来持续获取标注对,并提升在线自动纠错的能力。在受限上,抽取式虽然能直接在Seq级别对业务目标做优化,但有时候也须兼顾阅读体验,否则会形成一些“标题党”,亦或造成与原文相关性差的问题。对此,我们抽象了预处理和质量模型,来通用化处理文本创意内容的质控,独立了一个召回模块负责体验保障。并在模型结构上来对原文做独立表示,后又引入了Topic Feature Context来做针对性控制。整个抽取式的流程,可以抽象为四个环节+一个在线机制:源数据在内容中台完成可分发分析后,针对具体内容,进行系统化插件式的预处理,包括分句拼句、繁简转换、大小写归一等,并进行依存分析。而后将所有可选内容作质量评估,包括情感过滤、敏感过滤等通用过滤,以及规则判别等涉及表情、冗余字符处理与语法改写的二次基础优化。在召回模块中,通过实体识别+TF-IDF打分等方式来评估候选内容标题基础信息质量,并通过阈值召回来保证基础阅读体验,从而避免一些极端的Bad Case。最后,针对候选标题直接做句子级别的点击/转化率预估,负责质感、相关性及最终的业务目标的优化。为此,我们先后尝试了诸多模型结构来解决不同问题,下面重点在这方面做下介绍。我们第一版Bi-LSTM+Attention整个结构并不复杂。我们的输入层是PreTrain的Word Embedding,经过双向LSTM给到Attention层,Dropout后全连接,套一个交叉熵的Sigmod,输出判别,但它的意义非常明显,既可以对整句序列做双向语义的建模,同时可以通过注意力矩阵来对词级进行加权。这个在线上来看,无论是对体感还是点击转化率都较召回打分的原始版本,有了巨大提升。而后,我们还在这个Base模型基础上,尝试添加过ELMo的Loss,在模型的第一层双向LSTM进行基于ELMo Loss的Pre Train作为初始化结果,在线上指标也有小幅的提升。但是上述这个结构,将中短文本脱离原文独立建模,显然无法更好地兼顾原文受限这个条件。一个表现,就是容易出现“标题党”、原文不相关等对体验造成影响的问题。对此,我们在原文与候选标题结合的表示建模方面,做了不少探索,其中以CNN+Bi-LSTM+Attention的基模型为代表,但其在相关性建模受原文本身长度的影响较大,而且训练效率也不理想。经过一段时间的探索分析,在原文受限问题上,最终既通过深度模型来表征深层的语义,也辅以更多的特征工程,如属性、Topic等挖掘特征我们统称为Context,来表征用户能感知到的浅层信息,“两条腿走路”才能被更好的学习,这个在文案生成和标题生成的探索中反过来为抽取式提供了借鉴。在效率上,我们整体替换了RNN-LSTM的循环结构,采用了谷歌那时新提出的自注意力的机制,来解决原文表征训练效率和长依赖问题。采用这个结构在效果和效率上又有了较大的提升。主要问题是,我们的Context信息如何更好地建模到Self-Attention的结构中。它与生成式模型结构非常类似,在下文生成式部分有所介绍。另外,需要说明的一点是,除非有两个点以上的巨大提升,一般我们并不会以离线评测指标来评价模型好坏。因为前面提到,我们的标注数据存在不同程度的扰动,而且只是线上预测很小的一个子集,无法避免的与线上存在一定的Gap,所以我们更关注的是模型影响的基础体验(人工检测通过率即非Bad Case率),效率表现(训练预测的时效)最重要的还是线上实际的业务效果。在我们这几个版本的迭代中,这三个方面都分别获得了不同程度的优化,尤其是包括点击率、总点击量等在内的业务指标,都累计获得了10%以上的提升。受限生成式标题抽取式标题在包括业务指标和基础体验上都获取了不错的效果,但仍有明显的瓶颈。第一,没有完全脱离原文,尤其在大量质量欠优内容下无法实现创意的二次优化;第二,更好的通过创意这个载体显式的连接用户、商户和内容,这个是生成式标题可以有能力实现的,也是必由之路。生成式标题,可以抽象描述为:在给定上文并在一定受限条件下,预估下个词的概率的问题。在信息流标题场景,抽取式会面临的问题生成式全部会继承,且在受限优化上面临更大的挑战:原文受限,首先只有表示并学习到原文的语义意图才能更好的控制标题生成,这个本身在NLU就是难点,在生成式中就更为突出;其次,标注数据稀缺,原文+标题对的数据极少,而大部分又存在于长文章。为了保证控制和泛化性,我们初期将标题剥离原文独立建模,通过Context衔接,这样能引入更多的非标数据,并在逐步完成积累的情况下,才开始尝试做原文的深度语义表示。优化评估,受限生成式对训练语料的数量和质量要求高很多,首先要保证基础的语义学习也要保证生成端的质量;其次,生成式本质作为语言模型无法在句子层面对业务目标直接做优化,这中间还存在一道Gap。在表示上,前面已经提到,我们经历过目标单独建模和结合原文建模的过程,主要原因还是在于仅针对Target的理解去构建Context衔接,非常容易出现原文相关性问题。所以我们在描述的泛化性方向也做了不少的尝试,比如尽可能地描述广而泛主题。诸如“魔都是轻易俘获人心的聚餐胜地”,因为只面向上海的商户,内容符合聚餐主题,泛化能力很强,但仍然不能作为一个普适的方案解决问题。下图为我们一个有初步成效的RNN-Base的Seq2Seq模型的整体结构。Encoder端使用的是,包括前面提到的主题(包括商户信息)表示以及原文的双向语义表示,两部分的拼接构成的Context,输出给注意力层。Decoder端生成文本时,通过注意力机制学习主题和原文表示的权重关系,这个结构也完整应用到了文案生成,其中控制结构会在文案中展开介绍。在序列建模上,我们经历了一个从RNN到自注意力的过程。简单介绍下,序列建模一个核心要点是如何建模序列间的长依赖关系。影响它的重要因素是,信号在网络正向和反向计算中传递的长度(也就是计算次数),较长的依赖关系消失越严重。而在自注意力结构中,每一层都直接与前一层的所有位置直接连接,因此依赖长度均为O(1),最大程度保留了序列间的依赖关系。可以看到,Encoder包括两部分,一部分是Source原文,一部分是基于原文和商户理解的主题Context,两者共同组成。为此,我们借鉴了NMT的一部分研究思想,调整了Transformer的结构,在原结构上额外引入了Context Encoder,并且在Encoder和Decoder端加入了Context的Attention层,来强化模型捕捉Context信息的能力。我们在生成式方向探索过程中,对低质内容的标题生成,在线上获得了接近10%的效果提升,但仍有很多值得进一步的尝试和深挖的空间。抽取与生成Combine在我们的场景中,有两种Combine的思路,一个是以业务效果为导向的偏工程化方法,另外一个是我们正在探索的一种Copy方法。工程化的思想非常简洁,在推荐问题上扩充候选,是提升效果的一个可行途径,那生成内容即作为新增的候选集之一,参与整体的预估排序。这个方法能保证最终线上效果不会是负向的,实际上也取得了一定的提升。另一种方法也是学业界研究的子方向之一,即Copy机制,我们也在做重点探索,这里仅作思路的介绍,不再进行展开。使用Copy机制的原始目的,是为了解决生成式的OOV(超出词表范围)问题。但对于我们的场景来说,大部分的“内容-标题”对数据是来自于抽取式,即我们很多标题数据,其实参考了原文。那如何继承这个参考机制,针对业务目标学习何时Copy以及Copy什么,来更优雅地发挥生成式的优势,就是我们探索Copy方法的初衷。我们的方向是对Copy和Generate概率做独立建模,其中重点解决在受限情况下的“Where To Point”问题。业务指标与生成式目标的Gap我们知道生成式模型其本质是一个Language Model,它的训练目标是最小化Word级别的交叉熵Loss,而最终我们的需要评价的其实是业务相关的句子级别点击率,这就导致了训练目标和业务指标不一致。解决这个问题,在我们的场景中有三个可行的方向,第一是在Context中显式地标注抽取式模型的Label,让模型学习到两者的差异;第二是在预测Decoder的Beam Search计算概率的同时,添加一个打分控制函数;第三则是在训练的Decoder中,建立一个全局损失函数参与训练,类似于NMT中增加的Coverage Loss。考虑到稳定性和实现成本,我们最终尝试了第一和第二种方式,其中第二种方式还是从商户文案迁移过来的,也会在下文进行介绍。在线上,这个尝试并没有在Combine的基础上取得更好的效果,但同样值得更加深入的探索。在线E&E机制最后,介绍一下前面提到过的标题E&E(Explore and Exploit,探索与利用)机制,用来持续获取标注数据,并提升在线自动纠错的能力。我们采用了一种贪心的Epsilon Greedy策略,并做了一点修改,类似经典的Epsilon算法,区别是引入创意状态,根据状态将Epsilon分成多级。目的是将比较好的创意可以分配给较大概率的流量,而不是均分,差的就淘汰,以此来提升效率。在初期优化阶段,这种方式发挥了很大的作用。具体我们根据标题和图片的历史表现和默认相比,将状态分成7档,从上到下效果表现依次递减,流量分配比例也依次降低,这样可以保证整个系统在样本有噪音的情况下实现线上纠偏。3.4 商户文案实践文案作为一个常见的创意形式,在O2O以商户为主要载体的场景下有三点需要:第一,赋予商户以内容调性,丰富创意;第二,通过内容化扩展投放的场景;最后,赋能平台的内容化升级,主要业务目标包括点击率、页面穿透率等等。文案生成和标题生成能够通用整体的生成模型框架,可以归为Data2Text类任务,最大区别是由文案的载体"商户"所决定。不同于内容,准确性的要求低很多,复杂度也大大降低,但同时为泛化能力提出了更高的要求,也带来了与内容生成不同的问题。首先在表示上,对商户的结构化理解变得尤其关键;其次在控制上,有D2T任务特有且非常重要的控制要求。前文也提到了生成一段文本从来不是难点,重要的是如何按照不同要求控制Seq生成的同时,保证很好的泛化性。下文也会分别介绍卖点控制、风格控制、多样性控制控制等几个控制方法。实现这样的控制,也有很多不同的思路。商户表示商户的表示抽象为Context,如下图中所示,主要分两部分。第一部分来源于商户的自身理解,一部分则来源于目标文本,两部分有一定交集。其中商户理解的数据为卖点或者Topic,在初期,为了挖掘商户卖点和Topic,我们主要使用成本较低、无需标注的LDA。但是它的准确性相对不可控,同时对产出的卖点主题仍需要进行人工的选择,以便作为新的标注,辅助后续扩展有监督的任务。我们通过Key和Value两个Field,来对卖点和主题进行共同表达(也存在很多只有Value的情况),比如下图这个商户“菜品”是个Key,“雪蟹”是Value,“约会”则仅是Value。随着时间的推移,后续我们逐渐利用平台商户标签和图谱信息,来扩展商户卖点的覆盖,以此丰富我们的输入信息。该部分在内容挖掘和NLP知识图谱的相关介绍中都有涉及,这里不再进行展开。第二部分目标文本来源,特意添加这部分进入Context,主要有三方面原因:第一,仅仅依靠商户理解的Context,在训练过程中Loss下降极慢,并且最终预测生成多样性不理想。本质原因是,目标文本内容与商户卖点、主题间的相关性远远不够。通过不同商户的集合来学习到这个表示关系,非常困难。第二,拓宽可用数据范围,不受商户评论这类有天然标注对的数据限制,从商户衔接扩展到卖点衔接,引入更多的泛化描述数据,比如各类运营文案等等。第三,这也是更为重要的一点,能够间接地实现卖点选择的能力,这个会在下文进行介绍。控制端实现控制,在解码端表现为两类,一类我们称之为Hard Constrained(强控制),即在数据端给定(或没有给定)的信息,一定要在解码端进行(或不进行)相应描述,这个适用于地域类目等不能出错的信息。比如这家商户在上海,生成时不能出现除上海以外的地域信息,否则容易造成歧义。另一类称之为Soft Constrained(弱控制),不同于NMT问题,在文案生成上即便是完全相同的输入,不同的输出都是允许的,比如同一商户,最终的文案可以选择不同的卖点去描述不同的内容。这类同属受限优化的问题,前文提到过有两个思路方向:第一,通过构建机制来让模型自己学习到目标;第二,在Decoder的Beam Search阶段动态地加入所需的控制目标。我们使用两者相结合的方法,来完成最终的不同控制的实现。两端机制设计:在具体机制实现上,主要依赖在Input Context和Output Decoder两端同时生效,让Context的Hard Constrained来源于Output,从而使Model能够自动学习到强受限关系;而Soft Constrained则通过贝叶斯采样的方法,动态添加进Context,从而帮助Model提升泛化能力。Decoder控制:简单介绍下Beam Search,前面提到过,文本生成的预测过程是按Word级进行的,每轮预测的候选是整个词汇空间,而往往一般的词表都是十万以上的量级。如果生成序列序列长度为N,最终候选序列就有十万的N次方种可能,这在计算和存储上绝不可行。这时候,就需要使用到Beam Search方法,每一步保留最优的前K(K一般为2)个最大概率序列,其他则被剪枝,本质上可以视作一个压缩版的维特比解码。我们在预测Beam Search阶段,除了计算模型概率外,额外增加下图中绿色部分的Fuction。输入为之前已生成的序列,具体计算逻辑取决于控制目标,可以自由实现。下面简单介绍两个重要的控制实现:卖点控制:这是最重要的一个控制机制,我们整理了涉及到Hard Constrained的卖点和实体,重要的如地域、品类等,在目标理解过程中直接加入Context。对于Soft Constrained,我们通过卖点的共现计算一个简单的条件概率,并将卖点依此条件概率随机添加进Context中,从而让模型通过注意力学习到受限关系。最后在Decoder fuction部分,我们新增了一个Hard&Soft Constrained的匹配打分项,参与最终的概率计算。最终的实际结果,也非常符合我们的预期。风格控制:实现方法和卖点控制非常相似,只是这里的风格,其实是通过不同内容之间的差异来间接进行实现。比如大众点评头条、PGC类的内容与UGC类的的写作风格,就存在极大的差异。那么在文案上,比如聚合页标题上可能更需要PGC的风格,而聚合页内容上则需要UGC的风格。这样的内容属性,即可作为一个Context的控制信号,让模型捕获。3.5 内容聚合多样性控制多样性,在文案生成上是一个比较重要和普遍的问题,尤其对于同一个店铺、同一个卖点或主题同时生成N条内容的聚合页来说,更为突出。本质原因是,在解码预测Beam Search时永远选择概率最大的序列,并不考虑多样性。但是如果预测时采用Decoder概率Random Search的方法,则在通顺度上会存在比较大的问题。对此,我们直接对全局结果进行优化,在预测时把一个聚合页Context放到同一个batch中,batch_size即为文案条数,对已经生成序列上进行实体重复检测和n-gram重复检测,将检测判重的加一个惩罚性打分,这个简单的思想已经能非常好的解决多样性问题。4. 动态创意目前,很多搜索推荐等排序优化场景,都会将创意信息作为特征工程一部分添加进精排或召回模型。那如果把创意优化近似为一个内容级创意排序问题,也可以无缝衔接常用的Wide&Deep、DNN、FNN等CTR预估模型。但是这之前,需要明确一点非常重要的问题,即它与推荐精排模型的差异,它们之间甚至可能会相互影响,对此,提供下我们的思考。与精排模型的差异第一,精排模型能否一并完成创意的排序,答案显然是肯定的。但它的复杂度决定了能Cover候选集的上限,性能上往往接受不了叉乘创意带来的倍数增长。但此非问题的关键。第二,创意层排序在精排层之前还是之后,直接影响了创意模型的复杂度,也间接决定了其效果的上限,以及它对精排模型可能的影响程度,从而可能带来全局的影响。此没有最佳实践,视场景权衡。第三,精排模型与创意排序业务目标一致,但实现方式不同。精排模型通过全局排序的最优化来提升业务指标,而创意优化则是通过动态提升内容受众价值来提升业务指标。最后,我们回到用户视角,当用户在浏览信息流时,其实看到的只有创意本身(标题、图片、作者等信息),但用户却能从中感知到背后的诸多隐含信息,也就是CTR预估中的重要内容/商户类特征,诸如类目、场景、商户属性等。这个现象背后的本质在于,创意可以表征很多高阶的结构化信息。基于这一点,在创意优化的特征工程上,方向就很明确了:强化User/Context,弱化Item/POI,通过创意表征,来间接学习到弱化的信息从而实现创意层面的最优排序。该部分工作不仅仅涉及到文本,在本文中不再展开。用户兴趣与文本生成结合的可能性动态创意为文本生成提供了全新的空间,也提出了更高的要求。动态创意提升受众价值,不仅仅只能通过排序来实现,在正篇介绍的最后部分,我们抛出一个可能性的问题,供各位同行和同学一起思考。也希望能看到更多业界的方案和实践,共同进步。5. 总结与展望整个2018年,大众点评信息流在核心指标上取得了显著的突破。创意优化作为其中的一部分,在一些方面进行了很多探索,也在效果指标上取得了较为显著的收益。不过,未来的突破,更加任重而道远。2018年至2019年初,NLP的各个子领域涌现了非常多令人惊喜的成果,并且这些成果已经落地到业界实践上。这是一个非常好的趋势,也预示着在应用层面会有越来越多的突破。比如2019年初,能够续写短篇小说的GPT2问世,虽然它真实的泛化能力还未可知,但让我们真切看到了在内容受限下高质量内容生成的可能性。最后,回到初心,我们希望通过创意的载体显式地连接用户、商户和内容。我们能了解用户关注什么,知道某些内容表达什么,获知哪些商户好,好在哪里,将信息的推荐更进一步。参考资料[1] Context-aware Natural Language Generation with Recurrent Neural Networks. arXiv preprint arXiv:1611.09900.[2] Attention Is All You Need. arXiv preprint arXiv:1706.03762.[3] Universal Transformers. arXiv preprint arXiv:1807.03819.[4] A Convolutional Encoder Model for Neural Machine Translation. arXiv preprint arXiv:1611.02344.[5] Don’t Give Me the Details, Just the Summary! Topic-Aware Convolutional Neural Networks for Extreme Summarization. arXiv preprint arXiv:1808.08745.[6] Bert: Pre-training of deep bidirectional transformers for language understanding. arXiv preprint arXiv:1810.04805.[7] ELMO:Deep contextualized word representations. arXiv preprint arXiv:1802.05365.[8] openAI GPT:Improving Language Understanding by Generative Pre-Training.[9] Neural machine translation by jointly learning to align and translate. arXiv preprint arXiv:1409.0473.[10] Tensor2Tensor for Neural Machine Translation. arXiv preprint arXiv:1803.07416.[11] A Convolutional Encoder Model for Neural Machine Translation. arXiv preprint arXiv:1611.02344.[12] Sequence-to-Sequence Learning as Beam-Search Optimization. arXiv preprint arXiv:1606.02960.[13] A Deep Reinforced Model For Abstractive Summarization. arXiv preprint arXiv:1705.04304.[14] SeqGAN: Sequence Generative Adversarial Nets with Policy Gradient. arXiv preprint arXiv:1609.05473.[15] Generating sequences with recurrent neural networks. CoRR,abs/1308.0850.作者简介忆纯,2015年加入美团点评,算法专家,目前负责点评信息流内容创意工作。杨肖,博士,2016年加入美团点评,高级算法专家,点评推荐智能中心内容团队负责人。明海,2016年加入美团点评,美团点评研究员,点评推荐智能中心团队负责人。众一,2016年加入美团点评,算法研发工程师,目前主要负责点评信息流创意相关算法研发工作。扬威,2018年初加入美团点评,算法研发工程师,目前主要负责点评信息流动态创意相关算法研发工作。凤阳,2016年加入美团点评,算法研发工程师,目前主要负责点评信息流内容运营算法优化的工作。

March 15, 2019 · 2 min · jiezi

北大旁听 - 深入Loss Function的来源

想法由于有朋友在北大,很高兴能蹭到深度学习的课程,李戈教授的课程十分精彩,比起只会念PPT的老师,他的教学就像在堆积知识的金字塔。2. Loss Function2.1 经典统计 vs 深度学习 vs 贝叶斯统计概率论分为两大学派,贝叶斯学派认为先验知识很重要,而经典统计学派就是纯粹的看统计信息。现在的深度学习最大的优点就是在数据拟合上表现非常好,但最大的缺点就是它的不可解释性。在一篇论文:Deep Learning: A Bayesian Perspective 中提到,目前深度学习算法取得好效果的主要原因归功于ReLU、learning_rate、Dropout。实际上先验知识只是以网络的模型结构的方式呈现的(包括Loss Function的设计等)。2.2 最大似然估计其实目前大部分使用的损失函数都是以最大似然原理为核心而设计的。深度学习的核心问题就是让网络产生的数据分布尽可能贴近样本分布,所以极大似然原理就很自然的用在了深度学习上。而要评判分布的“差别”,首先需要可以评判分布的指标,而这个指标就是香农的信息熵。有了评价指标后,我们还不急着对比,因为要计算信息熵,需要知道样本的真实分布和概率密度。在计算模型分布的信息熵时,此时就不叫信息熵了,而称为交叉熵,这也就是所谓的cross-entropy(而不是大家常见的1-log(x))。Many authors use the term “cross-entropy” to identify specifically the negative log-likelihood of a Bernoulli or softmax distribution, but that is a misnomer.根据Gibbs不等式,有:E(P, Q) >= E(P),其实很好解释,用模拟出来的概率密度去计算真实分布的信息熵,肯定是比较混乱的(相对于真实概率密度计算真实分布的信息熵)。有了交叉熵和原分布的信息熵后,我们做差,就能得到相对熵(又称KL散度)。终于,我们得到了相对熵,可以评判分布的“差别”后,我们就可以用一个视角来看Loss Function:Loss Function 用于计算模型输出数据与样本数据之间的“差别”。Loss Function 体现了人们对这种“差别”进行度量时所依赖的先验知识。几种常见的“差别”度量方法个体模型结果与样本数据之间的“距离”。多个模型结果与样本数据之间存在数据分布上的差别。通过分析"统计距离“(Statistical Distance)来设计Loss。好了,让我们回到最大似然原理上,为了让模型分布尽可能贴近样本分布,那么我们要解决的问题就是最小化KL散度由于真实样本分布是已经确定的值,而我们能改变的就是pmodel(x)中的权值(也就是神经网络的weights),所以我们将问题简化为最小化(6),简写为:2.3 基于上述原则推导MSE的合理性MSE损失大家一定都知道,但是它是怎么来的呢?为什么要以这个形式出现呢?其实它是有一个非常严格的使用条件的:由于模型的输出和真实数据的分布一定会有偏差,那么只有假设当这个偏差符合正态分布时,才可以推导出MSE的形式,具体如下:得出了概率密度分布函数后,将其带入最大似然原理中,再取对数,就可以得到MSE的标准形式了:那么这里又出现了一个问题,为什么要让偏差符合正态分布呢?其实这是由以下两条理论得出的:同分布中心极限定理:n个独立同分布的随机变量之和,服从正态分布。非同分布的李雅普诺夫定理:大量随机因素叠加的结果,近似服从正态分布。有了这已经证明的两条理论,才可以基于正态分布,得出MSE的标准形式。同理,我们可以很容易的得到交叉熵(这里不是真的交叉熵,只是大家都习惯这么叫它了)、softmax的一般形式的证明:2.4 总结终于,我们说完了现代常用的损失函数是怎么得到的了。来一个简单的总结:一切的起源都是最大似然原理,为了衡量模型分布和真实分布的差异,我们从信息熵中得到了KL散度。于是我们将基于正态分布的偏差假设(MSE)、伯努利分布、多项分布代入最大似然原理,得到了我们现在常见的Loss Function(MSE、CrossEntropyLoss、Softmax)。所以这里有很重要的一点,不要盲目地使用交叉熵!你要注意的是你的数据分布,如果它不符合正态分布假设,那么你很可能就需要重新设计Loss Function了,那我们该如何做呢?其实KL散度有它的缺点,比如它不符合距离的定义(不对称)于是乎,你需要自己寻找衡量数据分布的散度(Divergence)Comprehensive Survey on Distance/Similarity Measures Between Probability Density Functions, 2007然后根据散度重新你的设计Loss Function。至此,关于Loss Function的内容就告一段落了,其实讲到最后,以我的数学水平实在达不到这个境界,所以到后面的概念如果讲的不太清楚,请各位读者谅解了。

March 14, 2019 · 1 min · jiezi

AI 安全在阿里业务中的实践,你了解吗?

我们知道,AI 技术将在很长一段时间占据互联网技术时代的风口。但是,有代码的地方就有缺陷,提到技术很难不讲安全,那么AI会不会碰到安全问题呢?AI安全试想一下,未来的某个早晨,当你像往常一样打开无人驾驶的汽车车门,报出目的地,然后坐在后座上舒舒服服地浏览推送给你的各种新闻,汽车突然失控,在本该停止的红灯前飞驰而过撞向了正在过马路的行人,那将是怎样一场灾难。人工智能技术给生活带来便利的同时,其自身的安全问题(AI安全)也不容忽视,AI安全问题可以归纳为内外2方面原因:自身缺陷导致的模型出错:例如,模型结构本身存在缺陷、或者训练数据和真实场景数据之间的偏差,都可能导致模型预测错误。外部攻击导致的模型风险:例如,来自外部的对抗样本攻击可诱使算法识别出现误判漏判,输出错误结果。本文,我们会针对第2点的对抗样本技术结合其在阿里巴巴安全领域中的实际应用给大家做展开介绍。对抗样本技术对抗样本由 ChristianSzegedy[1]等人提出,他们发现通过深度神经网络训练得到的模型,在输入与输出之间的映射往往不是线性的。这样就存在一个问题: 在输入数据中通过故意添加肉眼不易察觉的细微扰动,可以生成对抗样本,导致AI模型以高置信度给出一个错误的输出。如下图所示:目前的对抗样本根据是否需要指定攻击的类目可以分为无目标攻击(non-targeted attack)和目标攻击(targeted attack)。前者不指定具体类目,只要让AI识别错误即可。后者不仅需要使AI识别错误,还需要使AI识别到指定的类别。生成对抗样本,最直接的方法是在给定扰动量的范围内修改样本,使得修改后的样本在AI模型上的损失函数最大化(非定向攻击)或最小化(定向攻击),这样就可以把生成对抗样本的问题归纳为空间搜索的优化问题。基于不同的优化算法,学术界提出了很多对抗样本生成算法,有兴趣的朋友可以自行检索,此处不具体展开。对抗样本应用场景对抗样本技术提出后引发了学术界和工业界对于深度学习模型在安全方面的广泛关注,成为目前深度学习领域最火热的研究课题之一,新的对抗攻击方法不断涌现,应用场景从图像分类扩展到目标检测等。阿里安全一直以来致力于用技术解决社会问题。为了保障整个生态圈中7亿多消费者和千万商家的信息安全,AI技术很早就被应用到了阿里安全体系建设中。安全领域一个重要的特点就是存在很强的对抗性,日常防控中,黑灰产会尝试使用各种对抗样本攻击我们部署的AI防控大坝。对此,一方面,阿里安全图灵实验室的算法专家们提出了若干种提升模型安全性能的方法,强化自身堡垒;另一方面,算法专家们也会以战养战,开展针对对抗样本的攻防研究,利用对抗技术去防御攻击者的模型。下面我们结合实际业务,介绍两种对抗样本的应用场景:1.人脸识别人脸识别技术已经在生活的各个场景普遍应用,手机解锁要靠脸、移动支付要靠脸,机场安检要靠脸……一脸走天下的时代逐渐到来。然而,Bose 和 Aarabi[2]发现通过在原始图像中加入人眼不可区分的微量干扰对人脸识别算法进行攻击后,能够使人脸无法被检测算法定位到。如下图所示,左列为原始图像,检测算法可以准确定位,右列为对抗样本,已经成功绕开了人脸检测算法,而在我们肉眼看来两幅图画基本没有差别。更进一步,采用对抗样本攻击人脸识别系统,还可以使算法把人脸识别成指定的错误类别[3]。下图第一列为目标类别,第2和第4列为原始样本,对其加入干扰生成的对抗样本在第3和第5列,它们均被算法错误识别为第一列目标类别。2.对抗验证码如同网络通信的基础安全设施——防火墙,互联网业务安全也有其基础安全设施——图片验证码和短信验证码。互联网业务广泛使用图形验证码用于区分人类和机器的操作行为,使用短信验证码过滤黑灰产批量账号及提供二次校验功能。现在随着深度学习的门槛越来越低,黑灰产会利用深度学习技术构建模型自动识别验证码,突破算法模型设置的人机识别防线。下图的文本验证码基本都可以被AI模型轻松识别。针对文本验证码面临的挑战,阿里安全图灵实验室的算法专家们将原始验证码替换成增加扰动后的对抗验证码。为了增加对抗验证码的识别难度,又不影响正常用户的体验,算法专家们又在图像区域和生成方式上进行了组合扩展,最终生成的对抗样验证码有效抵御了黑灰产的批量破解,成为阿里业务安全的一道铜墙铁壁。采用该组合扩展生成的对抗验证码如下图所示:针对点击式的图文验证与行为辅助验证码,阿里安全图灵实验室的算法专家们首先在验证码中结合了NLP的问答技术,再将全部问答转换成图片,最后利用对抗技术生成对抗问答图片。使用商业的OCR引擎进行对此类对抗问答图片样本进行识别测试,和原始样本的识别率相比,对抗样本的识别率大幅降低,且并没有对用户的体验带来很大的影响,由此可见AI结合安全能为业务带来巨大的价值。本文作者:安全第一阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。

March 12, 2019 · 1 min · jiezi

4种方法计算句子相似度

Edit Distance计算两个字符串之间,由一个转成另一个所需要的最少编辑次数,次数越多,距离越大,也就越不相关。比如,“xiaoming”和“xiamin”,两者的转换需要两步:去除‘o’去除‘g’所以,次数/距离=2。!pip install distanceimport distancedef edit_distance(s1, s2): return distance.levenshtein(s1, s2)s1 = ‘xiaoming’s2 = ‘xiamin’print(‘距离:’+str(edit_distance(s1, s2)))杰卡德系数用于比较有限样本集之间的相似性与差异性。Jaccard 系数值越大,样本相似度越高,计算方式是:两个样本的交集除以并集。from sklearn.feature_extraction.text import CountVectorizerimport numpy as npdef jaccard_similarity(s1, s2): def add_space(s): return ’ ‘.join(list(s)) # 将字中间加入空格 s1, s2 = add_space(s1), add_space(s2) # 转化为TF矩阵 cv = CountVectorizer(tokenizer=lambda s: s.split()) corpus = [s1, s2] vectors = cv.fit_transform(corpus).toarray() # 求交集 numerator = np.sum(np.min(vectors, axis=0)) # 求并集 denominator = np.sum(np.max(vectors, axis=0)) # 计算杰卡德系数 return 1.0 * numerator / denominators1 = ‘你在干啥呢’s2 = ‘你在干什么呢’print(jaccard_similarity(s1, s2))TF 计算计算矩阵中两个向量的相似度,即:求解两个向量夹角的余弦值。计算公式:cos=a·b/|a|*|b|from sklearn.feature_extraction.text import CountVectorizerimport numpy as npfrom scipy.linalg import normdef tf_similarity(s1, s2): def add_space(s): return ’ ‘.join(list(s)) # 将字中间加入空格 s1, s2 = add_space(s1), add_space(s2) # 转化为TF矩阵 cv = CountVectorizer(tokenizer=lambda s: s.split()) corpus = [s1, s2] vectors = cv.fit_transform(corpus).toarray() # 计算TF系数 return np.dot(vectors[0], vectors[1]) / (norm(vectors[0]) * norm(vectors[1]))s1 = ‘你在干啥呢’s2 = ‘你在干什么呢’print(tf_similarity(s1, s2))高阶模型BertBert的内部结构,请查看从word2vec到bert这篇文章,本篇文章我们只讲代码实现。我们可以下载Bert模型源码,或者使用TF-HUB的方式使用,本次我们使用下载源码的方式。首先,从Github下载源码,然后下载google预训练好的模型,我们选择Bert-base Chinese。预模型下载后解压,文件结构如图:vocab.txt是训练时中文文本采用的字典,bert_config.json是BERT在训练时,可选调整的一些参数。其它文件是模型结构,参数等文件。准备数据集修改 processorclass MoveProcessor(DataProcessor): “““Processor for the move data set .””” def get_train_examples(self, data_dir): “““See base class.””” return self._create_examples( self._read_tsv(os.path.join(data_dir, “train.tsv”)), “train”) def get_dev_examples(self, data_dir): “““See base class.””” return self._create_examples( self._read_tsv(os.path.join(data_dir, “dev.tsv”)), “dev”) def get_test_examples(self, data_dir): “““See base class.””” return self._create_examples( self._read_tsv(os.path.join(data_dir, “test.tsv”)), “test”) def get_labels(self): “““See base class.””” return [“0”, “1”] @classmethod def _read_tsv(cls, input_file, quotechar=None): “““Reads a tab separated value file.””” with tf.gfile.Open(input_file, “r”) as f: reader = csv.reader(f, delimiter="\t", quotechar=quotechar) lines = [] for line in reader: lines.append(line) return lines def create_examples(self, lines, set_type): “““Creates examples for the training and dev sets.””” examples = [] for (i, line) in enumerate(lines): guid = “%s-%s” % (set_type, i) if set_type == “test”: text_a = tokenization.convert_to_unicode(line[0]) label = “0” else: text_a = tokenization.convert_to_unicode(line[1]) label = tokenization.convert_to_unicode(line[0]) examples.append( InputExample(guid=guid, text_a=text_a, text_b=None, label=label)) return examples修改 processor字典def main(): tf.logging.set_verbosity(tf.logging.INFO) processors = { “cola”: ColaProcessor, “mnli”: MnliProcessor, “mrpc”: MrpcProcessor, “xnli”: XnliProcessor, ‘setest’:MoveProcessor }Bert模型训练export BERT_BASE_DIR=/Users/xiaomingtai/Downloads/chinese_L-12_H-768_A-12export MY_DATASET=/Users/xiaomingtai/Downloads/bert_modelpython run_classifier.py \ –data_dir=$MY_DATASET \ –task_name=setest \ –vocab_file=$BERT_BASE_DIR/vocab.txt \ –bert_config_file=$BERT_BASE_DIR/bert_config.json \ –output_dir=/Users/xiaomingtai/Downloads/ber_model_output/ \ –do_train=true \ –do_eval=true \ –do_predict=true\ –init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \ –max_seq_length=128 \ –train_batch_size=16 \ –eval_batch_size=8\ –predict_batch_size=2\ –learning_rate=5e-5\ –num_train_epochs=3.0\Bert模型训练结果 ...

March 12, 2019 · 2 min · jiezi

从Word2Vec到Bert

Word2Vec模型Word2Vec有两种训练方法:CBOW和Skip-gram。CBOW的核心思想是上下文预测某个单词,Skip-gram正好相反,输入单词,要求网络预测它的上下文。如上图所示,一个单词表达成word embedding后,很容易找到词义相近的其它词汇。word embedding使用:句子中的单词以one-hot的形式作为输入,然后乘以学好的word embedding矩阵Q,就直接取出单词对应的word embedding了。word embedding矩阵Q其实就是网络one-hot层到embedding层映射的网络参数矩阵。所以,word embedding等价于把one-hot层到embedding层的网络用预训练好的参数矩阵Q初始化了。不过,word embedding只能初始化第一层网络参数,再高层就无能为力了。下游NLP任务使用word embedding的时候与图像类似,有两种方法,一种是frozen:word embedding层的网络参数固定不动;另一种是fine-tuning,即:word embedding这层参数使用新的训练集合训练。word embedding存在的问题如图所示,多义词bank有两种含义,但是word embedding在对bank这个词进行编码的时候无法区分这两个含义。尽管上下文环境中出现的单词相同,但是在语言模型训练的时候,不论什么上下文的句子经过word2vec,都是预测相同的单词bank,而同一个单词占用的同一行的参数空间,这导致两种不同的上下文信息都会编码到相同的word embedding空间去。所以,word embedding无法区分多义词的不同语义,这是它一个比较严重的问题。BertBert采用transformer作为特征提取器,并采用双向语言模型。此外,Bert预训练的数据规模非常庞大。NLP的四大类任务:序列标注:中文分词,词性标注,命名实体识别,语义角色标注等。特点是,句子中的每个单词要求模型根据上下文给出一个分类类别。分类任务:文本分类,情感计算。特点是,不管文章有多长,总体给出一个分类类别即可。句子关系判断:问答,语义改写,自然语言推理等任务。特点是,给定两个句子,模型判断两个句子是否具有某种语义关系。生成式任务:机器翻译,文本摘要,写诗造句,看图说话等。特点是,输入文本后,需要自主生成另外一种文字。对于句子关系类任务,加上一个其实符号和终结符号,句子之间加上分隔符号即可。对输出来说,把第一个起始符号对应的transformer最后一层位置上串联一个softmax分类层。对于分类问题,增加起始和终结符号,输出部分和句子关系类任务类似。序列标注问题:输入部分和单句分类问题一样,只需要输出部分transformer最后一层每个单词对应位置都进行分类即可。从这里可以看出,NLP四大类任务都可以比较方便的改造bert能够接受的方式,这意味着bert具有很强的普适性。bert构造双向语言模型Masked双向语言模型,随机选择语料中15%的单词,其中80%替换成mask标记,10%随机替换另一个单词,10%不做改动。Next Sentence Prediction,分两种情况选择句子,一种是在语料中选择真正顺序相连的两个句子;另一种方式是,第二个句子随机选择拼接到第一个句子的后面。要求模型做句子关系预测,判断第二个句子是不是真的第一个句子的后续句子。这么做的目的是,在很多NLP任务中是句子关系判断任务,单词预测颗粒度的训练到不了句子关系这个层级,增加这个任务有助于下游句子关系判断任务。由此可以看到,bert的预训练是个多任务过程。bert输入部分处理bert输入是一个线性序列,两个句子通过分隔符分割,前后两端分别增加标识符号。每个单词有三个embedding。位置embedding:NLP中单词顺序是重要特征,需要对位置进行编码。单词embedding句子embedding:前面提到的训练数据都是由两个句子构成,那么每个句子有个句子整体的embedding对应每个单词。三者叠加,就形成了bert的输入。bert输出处理bert评价从模型或者方法的角度来看,bert借鉴了ELMO,GPT以及CBOW,主要提出了masked语言模型和next sentence prediction。训练采用两阶段模型,第一阶段双向语言模型预训练,第二阶段采用具体任务fine-tuning或者做特征集成;第二是特征提取采用transformer作为特征提取器而不是rnn或cnn。bert最大的两点是效果好普适性强,几乎所有的NLP任务都可以套用bert这种两阶段解决思路。案例实现:Predicting Movie Review Sentiment with BERT on TF Hubbert已经添加到TF-Hub模块,可以快速集成到现有项目中。bert层可以替代之前的elmo,glove层,并且通过fine-tuning,bert可以同时提供精度,训练速度的提升。此案例中,我们将在tensorflow中使用bert训练一个模型用于判断电影评论的情绪是消极还是积极。导入模块from sklearn.model_selection import train_test_splitimport pandas as pdimport tensorflow as tfimport tensorflow_hub as hubfrom datetime import datetime!pip install bert-tensorflowimport bertfrom bert import run_classifierfrom bert import optimizationfrom bert import tokenization数据下载# 读取文件,创建dataframedef load_directory_data(directory): data={} data[‘sentence’]=[] data[‘sentiment’]=[] for file_path in os.listdir(directory): with tf.gfile.GFile(os.path.join(directory,file_path),‘r’) as f: data[‘sentence’].append(f.read()) data[‘sentiment’].append(re.match(’\d+_(\d+).txt’,file_path).group(1)) return pd.DataFrame.from_dict(data)# 添加新列,并打乱数据def load_dataset(directory): # 积极情绪文件 pos_df=load_directory_data(os.path.join(directory,‘pos’)) # 消极情绪 neg_df=load_directory_data(os.path.join(directory,’neg’)) pos_df[‘polarity’]=1 neg_df[‘polarity’]=0 # sample 参数frac,返回的比例,如:df中有10行数据,想返回30%,设置值为:0.3 return pd.concat([pos_df,neg_df]).sample(frac=1).reset_index(drop=True)# 下载并加载数据def download_and_load_datasets(force_download=False): dataset=tf.keras.utils.get_file( fname=‘aclImdb.tar.gz’, origin=‘http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz', extract=True ) train_df=load_dataset(os.path.join(os.path.dirname(dataset),‘aclImdb’,’train’)) test_df=load_dataset(os.path.join(os.path.dirname(dataset),‘aclImdb’,’test’)) return train_df,test_dftrain,test=download_and_load_datasets()# 去前5000个样本train=train.sample(5000)test=test.sample(5000)DATA_COLUMN=‘sentence’LABEL_COLUMN=‘polarity’label_list=[0,1]数据处理我们需要将数据转换成bert能够处理的格式。我们首先创建InputExample构造函数:test_a:我们要分类的数据,如:DATA_COLUMNtest_b:用于句子关系判断,如:问答,翻译等label:数据标签train_InputExample=train.apply(lambda x:bert.run_classifier.InputExample( guid=None, text_a=x[DATA_COLUMN], text_b=None, label=x[LABEL_COLUMN]),axis=1)test_InputExample=test.apply(lambda x:bert.run_classifier.InputExample( guid=None, text_a=x[DATA_COLUMN], text_b=None, label=x[LABEL_COLUMN]),axis=1)接下来,我们需要处理数据以适合bert进行训练。步骤依次如下:单词全部小写将文本转换成序列(如:‘sally says hi’ -> [‘sally’,‘says’,‘hi’])将单词分解为wordpieces(如:‘calling’->[‘call’,’##ing’])用bert提供的词汇文件进行单词索引映射添加‘CLS’,‘SEP’标记符每次输入添加‘index’和‘segment’标记# lowercase bert版本BERT_MODEL_HUB=‘https://tfhub.dev/google/bert_uncased_L-12_H-768_A-12/1'# 获取词表文件,小写数据处理def create_tokenizer_from_hub_module(): with tf.Graph().as_default(): bert_module = hub.Module(BERT_MODEL_HUB) tokenization_info = bert_module(signature=‘tokenization_info’, as_dict=True) with tf.Session() as sess: vocab_file,do_lower_case=sess.run([tokenization_info[‘vocab_file’],tokenization_info[‘do_lower_case’]]) return bert.tokenization.FullTokenizer( vocab_file=vocab_file, do_lower_case=do_lower_case )tokenizer=create_tokenizer_from_hub_module()# 序列最长MAX_SEQ_LENGTH=128# 将训练,测试数据特征转换成bert需要的格式train_features=bert.run_classifier.convert_examples_to_features(train_InputExample,label_list,MAX_SEQ_LENGTH,tokenizer)test_features=bert.run_classifier.convert_examples_to_features(test_InputExample,label_list,MAX_SEQ_LENGTH,tokenizer)创建模型def create_model(is_predicting,input_ids,input_mask,segment_ids,labels,num_labels): # 创建分类模型 bert_module=hub.Module( BERT_MODEL_HUB, trainable=True ) bert_inputs=dict( input_ids=input_ids, input_mask=input_mask, segment_ids=segment_ids ) bert_outputs=bert_module( inputs=bert_inputs, signature=‘tonkens’, as_dict=True ) output_layer=bert_outputs[‘pooled_output’] hidden_size=output_layer.shape[-1].value output_weights=tf.get_variable( ‘output_weights’,[num_labels,hidden_size], initializer=tf.truncated_normal_initializer(stddev=0.02) ) output_bias=tf.get_variable( ‘output_bias’,[num_labels],initializer=tf.zeros_initializer() ) with tf.variable_scope(’loss’): # dropout用于防止过拟合,仅训练时使用 output_layer=tf.nn.dropout(output_layer,keep_prob=0.9) logits=tf.matmul(output_layer,output_weights,transpose_b=True) logits=tf.nn.bias_add(logits,output_bias) log_prob=tf.nn.log_softmax(logits,axis=-1) # 将标签转为one-hot格式 one_hot_labels=tf.one_hot(labels,depth=num_labels) predcited_labels=tf.squeeze(tf.argmax(log_prob,axis=-1)) if is_predicting: return (predcited_labels,log_prob) per_example_loss=-tf.reduce_sum(one_hot_labelslog_prob,axis=-1) loss=tf.reduce_mean(per_example_loss) return (loss,predcited_labels,log_prob)创建InputFndef model_fn_builder(num_labels,learning_rate,num_train_steps,num_warmup_steps): def model_fn(features,labels,mode,params): input_idx=features[‘input_idx’] input_mask=features[‘input_mask’] segment_ids=features[‘segment_ids’] lable_ids=features[’labels_ids’] is_predicting=(mode == tf.estimator.ModeKeys.PREDICT) if not is_predicting: (loss,predicted_labels,log_probs)=create_model( is_predicting,input_idx,input_mask,segment_ids,lable_ids,num_labels ) train_op = bert.optimization.create_optimizer( loss, learning_rate, num_train_steps, num_warmup_steps, use_tpu=False) def metric_fn(label_ids,predicted_labels): accuracy=tf.metrics.accuracy(labels=lable_ids,predictions=predicted_labels) f1_score = tf.contrib.metrics.f1_score( label_ids, predicted_labels) auc = tf.metrics.auc( label_ids, predicted_labels) recall = tf.metrics.recall( label_ids, predicted_labels) precision = tf.metrics.precision( label_ids, predicted_labels) true_pos = tf.metrics.true_positives( label_ids, predicted_labels) true_neg = tf.metrics.true_negatives( label_ids, predicted_labels) false_pos = tf.metrics.false_positives( label_ids, predicted_labels) false_neg = tf.metrics.false_negatives( label_ids, predicted_labels) return { “eval_accuracy”: accuracy, “f1_score”: f1_score, “auc”: auc, “precision”: precision, “recall”: recall, “true_positives”: true_pos, “true_negatives”: true_neg, “false_positives”: false_pos, “false_negatives”: false_neg } eval_metrics=metric_fn(lable_ids,predicted_labels) if mode == tf.estimator.ModeKeys.TRAIN: return tf.estimator.EstimatorSpec( mode=mode, loss=loss, train_op=train_op ) else: return tf.estimator.EstimatorSpec( mode=mode, loss=loss, eval_metric_ops=eval_metrics ) else: (predicted_labels, log_probs) = create_model( is_predicting, input_idx, input_mask, segment_ids, lable_ids, num_labels) predictions = { ‘probabilities’: log_probs, ’labels’: predicted_labels } return tf.estimator.EstimatorSpec(mode, predictions=predictions) return model_fn参数配置BATCH_SIZE=32LEARNING_RATE=2e-5NUM_TRAIN_EPOCHS=3WARMUP_PROPORTION=0.1SAVE_CHECKEPOINTS_STEPS=500SAVE_SUMMARY_STEPS=100# 计算train,warmup总训练步数num_train_steps=int(len(train_features)/BATCH_SIZENUM_TRAIN_EPOCHS)num_warmup_steps=int(num_train_steps*WARMUP_PROPORTION)# 设置模型保存路径/次数,图信息保存次数run_config=tf.estimator.RunConfig( model_dir=OUTPUT_DIR, save_checkpoints_steps=SAVE_CHECKEPOINTS_STEPS, save_summary_steps=SAVE_SUMMARY_STEPS)模型训练,验证modle_fn=model_fn_builder( num_labels=len(label_list), learning_rate=LEARNING_RATE, num_train_steps=num_train_steps, num_warmup_steps=num_train_steps)estimator=tf.estimator.Estimator( model_fn=modle_fn, config=run_config, params={‘batch_size’:BATCH_SIZE})train_input_fn=bert.run_classifier.input_fn_builder( features=train_features, seq_length=MAX_SEQ_LENGTH, is_training=True, drop_remainder=False)estimator.train(input_fn=train_input_fn,max_steps=num_train_steps) ...

March 7, 2019 · 2 min · jiezi

使用权重正则化较少模型过拟合

介绍权重正则化可以减轻深度神经网络模型的过拟合问题,可以提升对新数据的泛化能力。有多种正则方法可供选择,如:L1,L2正则化,每种方法在使用前需要超参数配置。在这篇文章中,你将学习在keras如何使用权重正则化的方法来减轻模型过拟合问题。读完本篇文章,你将学习到:如何在keras中使用权重正则化应用到MLP,CNN,或者LSTM神经网络任务中一些常见论文在模型中使用权重正则化的方法和经验通过一个案例学习如何使用权重正则化解决过拟合问题## keras中权重正则化方法 ##keras提供了权重正则化方法,可以在损失函数中通过添加惩罚系数来使用。keras提供了三种正则化方法:L1:绝对值权重之和L2:平方权重之和L1L2:两者累加之和tf.keras.regularizers.l1(l=0.01)tf.keras.regularizers.l2(l=0.01)tf.keras.regularizers.l1_l2(l1=0.01,l2=0.01)keras中,权重正则化可以应用到任意一层,不过,模型默认不使用任何权重正则化。全连接层使用权重正则化全连接层使用L2权重正则化:import tensorflow as tfmodel=tf.keras.models.Sequential( # 权重正则化,bias正则化(应用较少)tf.keras.layers.Dense(512,activation=tf.nn.relu,kernel_regularizer=tf.keras.regularizers.l2(l=0.001),bias_regularizer=tf.keras.regularizers.l2(l=0.001)))卷积层使用权重正则化同全连接层一样,卷积层也使用kernel_regularizer和bias_regularizer参数添加正则化。代码展示在卷积层中使用L2正则化。import tensorflow as tfmodel=tf.keras.models.Sequential( tf.keras.layers.Conv2D(32,3,activation=tf.nn.relu,kernel_regularizer=tf.keras.regularizers.l2(l=0.001),bias_regularizer=tf.keras.regularizers.l2(l=0.001)))RNN网络中使用权重正则化代码展示在LSTM网络中使用L2权重正则化import tensorflow as tfmodel=tf.keras.models.Sequential( tf.keras.layers.LSTM(32,activation=tf.nn.tanh,recurrent_regularizer=tf.keras.regularizers.l2(l=0.001),kernel_regularizer=tf.keras.regularizers.l2(l=0.001),bias_regularizer=tf.keras.regularizers.l2(l=0.001)))权重正则化使用经验最常见的权重正则化是L2正则化,数值通常是0-0.1之间,如:0.1,0.001,0.0001。找到最优的系数并不容易,需要尝试不同的权重系数,找到模型表现最平稳优秀的系数L2正则化在CNN网络中,建议系数设置小一些,如:0.0005少量的权重正则对模型很重要,可以减少模型训练误差LSTM网络中L2权重系数通常更小,如:10^-6权重正则化案例学习我们将使用标准二元分类问题来定义两个半圆观察:每个类一个半圆。每个观测值都有两个输入变量,它们具有相同的比例,类输出值为0或1.该数据集称为“月亮”数据集,因为绘制时每个类中的观测值的形状。# 导入sklearn中的数据集from sklearn.datasets import make_moonsfrom matplotlib import pyplotfrom pandas import DataFrame# 生成2分类数据集X, y = make_moons(n_samples=100, noise=0.2, random_state=1)print(X.shape)print(X[:6])print(y.shape)print(y[:6])df = DataFrame(dict(x=X[:,0], y=X[:,1], label=y))colors = {0:‘red’, 1:‘blue’}fig, ax = pyplot.subplots()grouped = df.groupby(’label’)for key, group in grouped: group.plot(ax=ax, kind=‘scatter’, x=‘x’, y=‘y’, label=key, color=colors[key])pyplot.show()sklearn常用数据集:数据集格式:matplot结果显示:如图所示,该问题是非线性问题,可以使用神经网络来解决。我们只生成了100个样本,对神经网络来说数据量很少,这很容易造成过拟合问题。我们使用正则化,添加噪声数据来处理问题。虽然卷积神经网络(CNN)功能强大,并广泛应用于各种计算机视觉任务中,但由于参数过多而导致过度拟合[22]。神经网络的最初发展受到人脑机制的启发[18],它不像计算机那样精确。受到差异的启发,我们推断在训练过程中添加噪音可能会指示CNN学习更强大的特征表示以抵消噪音的影响,从而降低过度拟合的风险。许多正则化方法通过向训练数据添加噪声来防止过拟合。数据增强的输入图像,如随机裁剪,翻转和阻塞[9,21,30]已广泛用于提高CNNs的泛化能力。 Adversarial Training [1]被提出来通过在图像中添加基于梯度的扰动来调整网络。 DisturbLabel [26]随机地将样本的一小部分子集的标签改变为不正确的值,从而在损失层上规则化CNN。过拟合模型我们创建一个只有一层隐藏层的MLP模型,并让神经元数量大于样本数量,然后过长时间训练模型,以此来人为造成过拟合问题。训练模型之前,我们拆分下数据集,训练数据30%,验证数据70%,来训练模型表现。X, y = make_moons(n_samples=100, noise=0.2, random_state=1)# 拆分数据集n_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]模型隐藏层有500个神经元,激活函数使用relu,输出层使用sigmoid激活函数,输出一项类别。模型使用bind_crossentropy损失函数,adam优化器。model = Sequential()model.add(Dense(500, input_dim=2, activation=‘relu’))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])模型迭代数据集400次,batch_size=32。model.fit(trainX, trainy, epochs=4000, verbose=0)在测试集上评估模型表现:# model.evaluate返回:loss value;metrics value_, train_acc = model.evaluate(trainX, trainy, verbose=0), test_acc = model.evaluate(testX, testy, verbose=0)print(‘Train: %.3f, Test: %.3f’ % (train_acc, test_acc))模型输出结果:我们看到训练表现远大于测试表现,这是过拟合问题的典型标志。我们将train和test训练精度过程图形化展示出来。from sklearn.datasets import make_moonsfrom keras.layers import Densefrom keras.models import Sequentialfrom matplotlib import pyplotX, y = make_moons(n_samples=100, noise=0.2, random_state=1)n_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]# 创建模型model = Sequential()model.add(Dense(500, input_dim=2, activation=‘relu’))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])# 返回训练,验证集的损失和准确率history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0)pyplot.plot(history.history[‘acc’], label=‘train’)pyplot.plot(history.history[‘val_acc’], label=‘test’)pyplot.legend()pyplot.show()如图所示,在某一点,train和test的准确率出现分叉口。使用正则化的模型我们将在隐藏层中使用权重正则化,并设置系数为0.001,以此来减轻过拟合问题。model.add(Dense(500, input_dim=2, activation=‘relu’, kernel_regularizer=l2(0.001)))完整代码如下:from sklearn.datasets import make_moonsfrom keras.layers import Densefrom keras.models import Sequentialfrom keras.regularizers import l2# 创建数据集X, y = make_moons(n_samples=100, noise=0.2, random_state=1)# 拆分数据集n_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]# 创建模型model = Sequential()# 设置权重正则化model.add(Dense(500, input_dim=2, activation=‘relu’, kernel_regularizer=l2(0.001)))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])# 训练模型model.fit(trainX, trainy, epochs=4000, verbose=0)# 评估模型, train_acc = model.evaluate(trainX, trainy, verbose=0)_, test_acc = model.evaluate(testX, testy, verbose=0)print(‘Train: %.3f, Test: %.3f’ % (train_acc, test_acc))乍一看,好像除了test准确率降低些,其它也没什么了。让我们画图看下train和test的训练过程。from sklearn.datasets import make_moonsfrom keras.layers import Densefrom keras.models import Sequentialfrom keras.regularizers import l2from matplotlib import pyplotX, y = make_moons(n_samples=100, noise=0.2, random_state=1)n_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]model = Sequential()model.add(Dense(500, input_dim=2, activation=‘relu’, kernel_regularizer=l2(0.001)))model.add(Dense(1, activation=‘sigmoid’))model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’])history = model.fit(trainX, trainy, validation_data=(testX, testy), epochs=4000, verbose=0pyplot.plot(history.history[‘acc’], label=‘train’)pyplot.plot(history.history[‘val_acc’], label=‘test’)pyplot.legend()pyplot.show()如图所示,现在就很清楚了,test与train一致。网格搜索正则化超参数当确定权重正则化可以改善模型的时候,这时你可以尝试不同的权重系数值。首先对0.0到0.1之间的一些数量级进行网格搜索,然后再找到一个级别后进行网格搜索,这是一个很好的做法。# 待测权重正则化值values = [1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6]all_train, all_test = list(), list()for param in values: … model.add(Dense(500, input_dim=2, activation=‘relu’, kernel_regularizer=l2(param))) … all_train.append(train_acc) all_test.append(test_acc)我们依然可以图形化展示训练过程:pyplot.semilogx(values, all_train, label=‘train’, marker=‘o’)pyplot.semilogx(values, all_test, label=‘test’, marker=‘o’)完整代码如下:from sklearn.datasets import make_moonsfrom keras.layers import Densefrom keras.models import Sequentialfrom keras.regularizers import l2from matplotlib import pyplot# 创建数据集X, y = make_moons(n_samples=100, noise=0.2, random_state=1)# 拆分数据集n_train = 30trainX, testX = X[:n_train, :], X[n_train:, :]trainy, testy = y[:n_train], y[n_train:]# 待测权重系数值values = [1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6]all_train, all_test = list(), list()for param in values: # 创建模型 model = Sequential() model.add(Dense(500, input_dim=2, activation=‘relu’, kernel_regularizer=l2(param))) model.add(Dense(1, activation=‘sigmoid’)) model.compile(loss=‘binary_crossentropy’, optimizer=‘adam’, metrics=[‘accuracy’]) # 训练模型 model.fit(trainX, trainy, epochs=4000, verbose=0) # 评估模型 _, train_acc = model.evaluate(trainX, trainy, verbose=0) _, test_acc = model.evaluate(testX, testy, verbose=0) print(‘Param: %f, Train: %.3f, Test: %.3f’ % (param, train_acc, test_acc)) all_train.append(train_acc) all_test.append(test_acc)# plot train and test meanspyplot.semilogx(values, all_train, label=‘train’, marker=‘o’)pyplot.semilogx(values, all_test, label=‘test’, marker=‘o’)pyplot.legend()pyplot.show()总结降低过拟合问题,我们一般需要从“数据”,“模型结构”,“模型参数”,“模型训练方法”等角度,采用的方法如下:数据增强:图像的平移,旋转,裁剪等;利用GAN生成新数据;利用机器翻译生成新数据。降低模型复杂度:减少网络层数,神经元个数;添加正则化项,如:L1,L2集成学习:神经网络,dropout避免过长时间训练模型,设置提前终止。 ...

March 4, 2019 · 2 min · jiezi

助力深度学习!阿里开源可插拔 GPU 共享调度工具

根据 Gartner 对全球 CIO 的调查结果显示,人工智能将成为 2019 年组织革命的颠覆性力量。对于人工智能来说,算力即正义,成本即能力,利用 Docker 和 Kubernetes 代表云原生技术为 AI 提供了一种新的工作模式,将 GPU 机器放到统一的资源池进行调度和管理,这避免了GPU 资源利用率低下和人工管理的成本。因此,全球主要的容器集群服务厂商 Kubernetes 都提供了 Nvidia GPU 容器集群调度能力,但是通常都是将一个 GPU 卡分配给一个容器。这虽然可以实现比较好的隔离性,确保使用 GPU 的应用不会被其他应用影响;对于深度学习模型训练的场景也非常适合,但是,针对模型开发和模型预测的场景还是会显得比较浪费。基于此,大家有了共享 GPU 的集群调度需求。Kubernetes 共享 GPU 集群调度共享 GPU 的集群调度就是能够让更多的模型开发和预测服务共享同一个 GPU 卡,进而提高集群中 Nvidia GPU 的利用率。而这就需要提供 GPU 资源的划分,而这里 GPU 资源划分的维度指的就是 GPU 显存和 Cuda Kernel 线程的划分。通常在集群级别谈支持共享 GPU 是以下两件事情:1.调度2.隔离,我们这里主要讨论的是调度,隔离的方案目前需要用户通过应用限制(比如使用 Tensorflow 的per_process_gpu_memory_fraction 来控制),未来会提供基于 Nvidia 的 MPS 的可选项, 也会考虑 GPU 的方案。而对于细粒度的 GPU 卡调度,目前 Kubernetes 社区并没有很好的方案,这是由于 Kubernetes 对于 GPU 这类扩展资源的定义仅仅支持整数粒度的加加减减,无法支持复杂资源的分配。比如用户希望使用 Pod A 占用半张 GPU卡,这在目前 Kubernetes 的架构设计中无法实现资源分配的记录和调用。这里挑战是多卡 GPU 共享是实际矢量资源问题,而 Extened Resource 是标量资源的描述。针对此问题,我们设计了一个 Out Of Tree 的共享 GPU 调度方案,该方案依赖于 Kubernetes 的现有的工作机制:Extended Resource 定义Scheduler Extender 机制Device Plugin 机制Kubectl 的扩展机制这个 GPU 共享调度扩展的好处是:利用 Kubernetes 的扩展和插件机制实现,对于 API Server,Scheduler,Controller Manager 以及 Kubelet 等核心组件没有侵入性。这就方便了使用者可以在不同 Kubernetes 版本上应用这个方案,无需 rebase 代码和重新构建 Kubernetes 二进制包。用户场景集群管理员:“我想提高集群的 GPU 使用率;在开发过程中,多个用户共享模型开发环境。”应用开发人员:“我希望能够同时在 Volta GPU 上运行多个推理任务。”目标能够让使用者通过 API 描述对于一个可共享资源的申请, 并能实现该种资源的调度非目标不支持该共享资源的隔离不支持超卖设计原则明确问题简化设计,第一步只负责调度和部署,后续再实现运行时显存管控。有很多的客户明确的诉求是首先可以支持多AI应用可以调度到同一个 GPU 上,他们可以接受从应用级别控制显存的大小,利用类似gpu_options.per_process_gpu_memory_fraction控制应用的显存使用量。那我们要解决的问题就先简化到以显存为调度标尺,并且把显存使用的大小以参数的方式传递给容器内部。不做侵入式修改本设计中不会修改 Kubernetes 核心的 Extended Resource 的设计, Scheduler 的实现,Device Plugin 的机制以及 Kubelet 的相关设计。重用 Extended Resource 描述共享资源的申请 API。这样的好处在于提供一个可以移植的方案,用户可以在原生 Kubernetes 上使用这个方案。按显存和按卡调度的方式可以在集群内并存,但是同一个节点内是互斥的,不支持二者并存;要么是按卡数目,要么是按显存分配。详细设计前提:依旧延用 Kubernetes Extended Resource 定义,但是衡量维度最小单位从 1 个 GPU 卡变为 GPU 显存的 MiB。如果所节点使用的 GPU 为单卡 16GiB 显存,它对应的资源就是 16276MiB;由于用户对于共享GPU的诉求在于模型开发和模型预测场景,在此场景下,用户申请的GPU资源上限不会超过一张卡,也就是申请的资源上限为单卡。而我们的工作首先是定义了两个新的 Extended Resource: 第一个是 gpu-mem, 对应的是 GPU 显存;第二个是 gpu-count,对应的是 GPU 卡数。 通过两个标量资源描述矢量资源, 并且结合这一资源,提供支持共享 GPU 的工作机制。下面是基本的架构图:核心功能模块:GPU Share Scheduler Extender: 利用 Kubernetes 的调度器扩展机制,负责在全局调度器 Filter 和 Bind 的时候判断节点上单个 GPU 卡是否能够提供足够的 GPU Mem,并且在 Bind 的时刻将 GPU 的分配结果通过 annotation 记录到 Pod Spec 以供后续 Filter 检查分配结果。GPU Share Device Plugin: 利用 Device Plugin 机制,在节点上被 Kubelet 调用负责 GPU 卡的分配,依赖 scheduler Extender 分配结果执行。具体流程:1. 资源上报GPU Share Device Plugin 利用 nvml 库查询到 GPU 卡的数量和每张 GPU 卡的显存, 通过ListAndWatch()将节点的 GPU 总显存(数量 显存)作为另外 Extended Resource 汇报给 Kubelet; Kubelet 进一步汇报给 Kubernetes API Server。 举例说明,如果节点含有两块 GPU 卡,并且每块卡包含 16276MiB,从用户的角度来看:该节点的 GPU 资源为 16276 2 = 32552; 同时也会将节点上的 GPU 卡数量 2 作为另外一个 Extended Resource 上报。2. 扩展调度GPU Share Scheduler Extender 可以在分配 gpu-mem 给 Pod 的同时将分配信息以 annotation 的形式保留在 Pod spec 中,并且在过滤时刻根据此信息判断每张卡是否包含足够可用的 gpu-mem 分配。2.1 Kubernetes 默认调度器在进行完所有过滤(filter)行为后会通过 http 方式调用 GPU Share Scheduler Extender的filter 方法, 这是由于默认调度器计算 Extended Resource 时,只能判断资源总量是否有满足需求的空闲资源,无法具体判断单张卡上是否满足需求;所以就需要由 GPU Share Scheduler Extender 检查单张卡上是否含有可用资源。以下图为例, 在由 3 个包含两块 GPU 卡的节点组成的 Kubernetes 集群中,当用户申请gpu-mem=8138时,默认调度器会扫描所有节点,发现 N1 所剩的资源为 (16276 * 2 - 16276 -12207 = 4069 )不满足资源需求,N1 节点被过滤掉。而 N2 和 N3 节点所剩资源都为 8138MiB,从整体调度的角度看,都符合默认调度器的条件;此时默认调度器会委托 GPU Share Scheduler Extender 进行二次过滤,在二次过滤中,GPU Share Scheduler Extender 需要判断单张卡是否满足调度需求,在查看 N2 节点时发现该节点虽然有 8138MiB 可用资源,但是落到每张卡上看,GPU0 和分别 GPU1 只有 4069MiB 的可用资源,无法满足单卡 8138MiB 的诉求。而 N3 节点虽然也是总共有 8138MiB 可用资源,但是这些可用资源都属于 GPU0,满足单卡可调度的需求。由此,通过 GPU Share Scheduler Extender 的筛选就可以实现精准的条件筛选。2.2 当调度器找到满足条件的节点,就会委托 GPU Share Scheduler Extender 的 bind 方法进行节点和 Pod 的绑定,这里 Extender 需要做的是两件事情以 binpack 的规则找到节点中最优选择的 GPU 卡 id,此处的最优含义是对于同一个节点不同的 GPU 卡,以 binpack 的原则作为判断条件,优先选择空闲资源满足条件但同时又是所剩资源最少的 GPU 卡,并且将其作为ALIYUN_COM_GPU_MEM_IDX保存到 Pod 的 annotation 中;同时也保存该 Pod 申请的 GPU Memory 作为ALIYUN_COM_GPU_MEM_POD和ALIYUN_COM_GPU_MEM_ASSUME_TIME保存至 Pod 的 annotation 中,并且在此时进行 Pod 和所选节点的绑定。注意:这时还会保存ALIYUN_COM_GPU_MEM_ASSIGNED的 Pod annotation,它被初始化为“false”。它表示该 Pod 在调度时刻被指定到了某块 GPU 卡,但是并没有真正在节点上创建该 Pod。ALIYUN_COM_GPU_MEM_ASSUME_TIME代表了指定时间。如果此时发现分配节点上没有 GPU 资源符合条件,此时不进行绑定,直接不报错退出,默认调度器会在 assume 超时后重新调度。调用 Kubernetes API 执行节点和 Pod 的绑定以下图为例,当 GPU Share Scheduler Extender 要把 gpu-mem:8138 的 Pod 和经过筛选出来的节点 N1 绑定,首先会比较不同 GPU 的可用资源,分别为 GPU0(12207),GPU1(8138),GPU2(4069),GPU3(16276),其中 GPU2 所剩资源不满足需求,被舍弃掉;而另外三个满足条件的 GPU 中, GPU1 恰恰是符合空闲资源满足条件但同时又是所剩资源最少的 GPU 卡,因此 GPU1 被选出。3. 节点上运行当 Pod 和节点绑定的事件被 Kubelet 接收到后,Kubelet 就会在节点上创建真正的 Pod 实体,在这个过程中, Kubelet 会调用 GPU Share Device Plugin 的Allocate方法, Allocate方法的参数是 Pod 申请的 gpu-mem。而在Allocate方法中,会根据 GPU Share Scheduler Extender 的调度决策运行对应的 Pod会列出该节点中所有状态为 Pending 并且ALIYUN_COM_GPU_MEM_ASSIGNED为false的 GPU Share Pod选择出其中 Pod Annotation 的ALIYUN_COM_GPU_MEM_POD的数量与 Allocate 申请数量一致的 Pod。如果有多个符合这种条件的 Pod,就会选择其中ALIYUN_COM_GPU_MEM_ASSUME_TIME最早的 Pod。将该 Pod 的 annotation ALIYUN_COM_GPU_MEM_ASSIGNED设置为true,并且将 Pod annotation 中的 GPU 信息转化为环境变量返回给 Kubelet 用以真正的创建 Pod。相关项目目前项目已经开源到 github.com 上gpushare-scheduler-extendergpushare-device-plugin部署请参照部署文档测试样例首先创建一个使用aliyun.com/gpu-mem的应用apiVersion: apps/v1kind: Deploymentmetadata: name: binpack-1 labels: app: binpack-1spec: replicas: 1 selector: # define how the deployment finds the pods it manages matchLabels: app: binpack-1 template: # define the pods specifications metadata: labels: app: binpack-1 spec: containers: - name: binpack-1 image: cheyang/gpu-player:v2 resources: limits: # MiB aliyun.com/gpu-mem: 1024使用请参照使用文档构建请参照如何构建视频 Demo1: 部署多个 GPU Share 的 Pod,发现他们以 binpack 的方式被放置到同一个 GPU 卡上视频地址:https://cloud.video.taobao.com//play/u/2987821887/p/2/e/6/t/1/214292079721.mp42: 避免错误调度申请资源超过单个 GPU 可用资源的 Pod视频地址:https://cloud.video.taobao.com//play/u/2987821887/p/2/e/6/t/1/214235285109.mp4Roadmap在 Device Plugin 中提供 Nvidia MPS 的可选支持;支持该方案可以在由 kubeadm 初始化的 Kubernetes 集群自动化部署;提升 Scheduler Extener 的高可用性;为 GPU, RDMA 和弹性网卡提供通用方案。本文作者:jessie筱姜阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 4, 2019 · 3 min · jiezi

斯坦福DAWNBench:华为云ModelArts深度学习训练全球最快

斯坦福DAWNBench:华为云ModelArts深度学习训练全球最快近日,斯坦福大学发布了DAWNBenchmark最新成绩,在图像识别(ResNet50-on-ImageNet,93%以上精度)的总训练时间上,华为云ModelArts排名第一,仅需10分28秒,比第二名提升近44%。成绩证明,华为云ModelArts实现了更低成本、更快速度、更极致的体验。斯坦福大学DAWNBench是用来衡量端到端的深度学习模型训练和推理性能的国际权威基准测试平台,相应的排行榜反映了当前全球业界深度学习平台技术的领先性。计算时间和成本是构建深度模型的关键资源,DAWNBench提供了一套通用的深度学习评价指标,用于评估不同优化策略、模型架构、软件框架、云和硬件上的训练时间、训练成本、推理延迟以及推理成本。作为人工智能最重要的基础技术之一,近年来深度学习也逐步延伸到更多的应用场景。随着深度学习模型越来越大,所需数据量越来越多,深度学习的训练和推理性能将是重中之重。华为云ModelArts将结合华为在AI芯片、硬件、云设施、软件和算法的全栈优势,打造更快的普惠的AI开发平台。下文将深入分析,华为云ModelArts如何做到性能极致——128块GPU,ImageNet训练时间10分钟。深度学习已广泛应用,模型增大、数据增长,深度学习训练加速的需求日益剧增近年来,深度学习已经广泛应用于计算机视觉、语音识别、自然语言处理、视频分析等领域,可服务于视频监控、自动驾驶、搜索推荐、对话机器人等场景,具有广阔的商业价值。为了达到更高的精度,通常深度学习所需数据量和模型都很大,训练非常耗时。例如,在计算机视觉中,如果我们在ImageNet[1]数据集上用1块V100 GPU训练一个ResNet-50模型, 则需要耗时将近1周。这严重阻碍了深度学习应用的开发进度。因此,深度学习训练加速一直是学术界和工业界所关注的重要问题,也是深度学习应主要用的痛点。Jeremy Howard等几位教授领衔的fast.ai当前专注于深度学习加速,在ImageNet数据集上用128块V100 GPU训练 ResNet-50模型的最短时间为18分钟。然而,最近BigGAN、NASNet、BERT等模型的出现,预示着训练更好精度的模型需要更强大的计算资源。可以预见,在未来随着模型的增大、数据量的增加,深度学习训练加速将变得会更加重要。只有拥有端到端全栈的优化能力,才能使得深度学习的训练性能做到极致。[1] 文中所指的ImageNet数据集包含1000类个类别,共128万张图片,是最常用、最经典的图像分类数据集,是原始的ImageNet数据的一个子集。华为云ModelArts创造新纪录,“极致”的训练速度华为云ModelArts是一站式的AI开发平台,已经服务于华为公司内部各大产品线的AI模型开发,几年下来已经积累了跨场景、软硬协同、端云一体等多方位的优化经验。ModelArts提供了自动学习、数据管理、开发管理、训练管理、模型管理、推理服务管理、市场等多个模块化的服务,使得不同层级的用户都能够很快地开发出自己的AI模型。在模型训练部分,ModelArts通过硬件、软件和算法协同优化来实现训练加速。尤其在深度学习模型训练方面,华为将分布式加速层抽象出来,形成一套通用框架——MoXing(“模型”的拼音,意味着一切优化都围绕模型展开)。采用与fast.ai一样的硬件、模型和训练数据,ModelArts可将训练时长可缩短到10分钟,创造了新的纪录,为用户节省44%的时间。3.分布式加速框架MoXingMoXing是华为云ModelArts团队自研的分布式训练加速框架,它构建于开源的深度学习引擎TensorFlow、MXNet、PyTorch、Keras之上,使得这些计算引擎分布式性能更高,同时易用性更好。高性能MoXing内置了多种模型参数切分和聚合策略、分布式SGD优化算法、级联式混合并行技术、超参数自动调优算法,并且在分布式训练数据切分策略、数据读取和预处理、分布式通信等多个方面做了优化,结合华为云Atlas高性能服务器,实现了硬件、软件和算法协同优化的分布式深度学习加速。易用:让开发者聚焦业务模型,无忧其他在易用性方面,上层开发者仅需关注业务模型,无需关注下层分布式相关的API,仅需根据实际业务定义输入数据、模型以及相应的优化器即可,训练脚本与运行环境(单机或者分布式)无关,上层业务代码和分布式训练引擎可以做到完全解耦。4.从两大指标看MoXing分布式加速关键技术在衡量分布式深度学习的加速性能时,主要有如下2个重要指标:1)吞吐量,即单位时间内处理的数据量;2)收敛时间,即达到一定的收敛精度所需的时间。吞吐量一般取决于服务器硬件(如更多、更大FLOPS处理能力的AI加速芯片,更大的通信带宽等)、数据读取和缓存、数据预处理、模型计算(如卷积算法选择等)、通信拓扑等方面的优化,除了低bit计算和梯度(或参数)压缩等,大部分技术在提升吞吐量的同时,不会造成对模型精度的影响。为了达到最短的收敛时间,需要在优化吞吐量的同时,在调参方面也做调优。如果调参调的不好,那么吞吐量有时也很难优化上去,例如batch size这个超参不足够大时,模型训练的并行度就会较差,吞吐量难以通过增加计算节点个数而提升。对用户而言,最终关心的指标是收敛时间,因此MoXing和ModelArts实现了全栈优化,极大缩短了训练收敛时间。在数据读取和预处理方面,MoXing通过利用多级并发输入流水线使得数据IO不会成为瓶颈;在模型计算方面,MoXing对上层模型提供半精度和单精度组成的混合精度计算,通过自适应的尺度缩放减小由于精度计算带来的损失;在超参调优方面,采用动态超参策略(如momentum、batch size等)使得模型收敛所需epoch个数降到最低;在底层优化方面,MoXing与底层华为自研服务器和通信计算库相结合,使得分布式加速进一步提升。5.测试结果对比,用数据说话一般在ImageNet数据集上训练ResNet-50模型,当Top-5精度≥93%或者Top-1 精度≥75%时即可认为模型收敛。我们测试的模型训练收敛曲线如下图所示。此处Top-1和Top-5精度为训练集上的精度,为了达到极致的训练速度,训练过程中采用了额外进程对模型进行验证,最终验证精度如表1所示(包含与fast.ai的对比)。图4(a)所对应的模型在验证集上Top-1 精度≥75%,训练耗时为10分06秒;图4(b)所对应的模型在验证集上Top-5 精度≥93%,训练耗时为10分28秒。未来展望——更快的普惠AI开发平台华为云ModelArts致力于为用户提供更快的普惠AI开发体验,尤其在模型训练这方面,内置的MoXing框架使得深度学习模型训练速度有了很大的提升。正如前所述,深度学习加速属于一个从底层硬件到上层计算引擎、再到更上层的分布式训练框架及其优化算法多方面协同优化的结果,具备全栈优化能力才能将用户训练成本降到最低。后续,华为云ModelArts将进一步整合软硬一体化的优势,提供从芯片(Ascend)、服务器(Atlas Server)、计算通信库(CANN)到深度学习引擎(MindSpore)和分布式优化框架(MoXing)全栈优化的深度学习训练平台。并且,ModelArts会逐步集成更多的数据标注工具,扩大应用范围,将继续服务于智慧城市、智能制造、自动驾驶及其它新兴业务场景,在公有云上为用户提供更普惠的AI服务。目前华为云ModelArts课程已上线免费学习,欢迎到华为云学院 (https://edu.huaweicloud.com/c… )搜索ModelArts 即可获取。

March 4, 2019 · 1 min · jiezi

UI2Code智能生成Flutter代码——版面分析篇

开篇: 在《UI2CODE–整体设计》篇中,我们提到UI2CODE工程的第一步是版面分析,如果是白色的简单背景,我们可以像切西瓜一样,将图片信息切割为GUI元素。但是在实际生产过程中,UI的复杂度会高很多。本篇我们将围绕版面分析这块内容分享我们的探索过程。架构设计: 版面分析主要处理UI图像的前景提取和背景分析:通过前后景分离算法,将UI视觉稿剪裁为GUI元素:背景分析:通过机器视觉算法,分析背景颜色,背景渐变方向,以及背景的连通区域。前景分析:通过深度学习算法,对GUI碎片进行整理,合并,识别。背景分析: 背景分析的关键在于找到背景的连通区域和闭合区间; 我们从一个实际的应用场景来分析整个背景提取的过程:我们期望将上一张图片,通过UI2CODE,来提取GUI元素。第一步:判断背景区块,通过sobel,Lapacian,canny等边缘检测的方法计算出梯度变化方向,从而得到纯色背景和渐变色背景区域。基于拉普拉斯算子的背景区域提取离散拉普拉斯算子的模板:扩展模板:当该区域点与模板点乘,得到的数值越小越是平坦的区域,即接近背景区域。如果是渐变色区域,则统计它的运动趋势。(左->右,右->左,上->下, 下->上)提取效果如下:我们发现上图虽然能大致提取背景轮廓,但是对于有渐变色的背景还是比较粗糙。因此我们通过统计背景运动趋势的方式来判定它是否存在渐变色背景。如果存在,我们将通过第二步进行精细化处理。第二步:基于漫水填充算法,选取漫水的种子节点,滤除渐变色背景区域噪声。 def fill_color_diffuse_water_from_img(task_out_dir, image, x, y, thres_up = (10, 10, 10), thres_down = (10, 10, 10), fill_color = (255,255,255)): """ 漫水填充:会改变图像 """ # 获取图片的高和宽 h, w = image.shape[:2] # 创建一个h+2,w+2的遮罩层, # 这里需要注意,OpenCV的默认规定, # 遮罩层的shape必须是h+2,w+2并且必须是单通道8位,具体原因我也不是很清楚。 mask = np.zeros([h + 2, w + 2], np.uint8) # 这里执行漫水填充,参数代表: # copyImg:要填充的图片 # mask:遮罩层 # (x, y):开始填充的位置(开始的种子点) # (255, 255, 255):填充的值,这里填充成白色 # (100,100,100):开始的种子点与整个图像的像素值的最大的负差值 # (50,50,50):开始的种子点与整个图像的像素值的最大的正差值 # cv.FLOODFILL_FIXED_RANGE:处理图像的方法,一般处理彩色图象用这个方法 cv2.floodFill(image, mask, (x, y), fill_color, thres_down, thres_up, cv2.FLOODFILL_FIXED_RANGE) cv2.imwrite(task_out_dir + “/ui/tmp2.png”, image) # mask是非常重要的一个区域,这块区域内会显示哪些区域被填充了颜色 # 对于UI自动化,mask可以设置成shape,大小以1最大的宽和高为准 return image, mask处理过后的效果如下:第三步:通过版面切割,提取GUI元素,切割方法之前有提到过。这个时候我们已经成功提取了80%的GUI元素,但是叠加图层部分元素还无法解析。第四步:通过霍夫直线、霍夫圆和轮廓查找的方式找到对称的轮廓区域。对提取的轮廓区域做第二步到第四步的递归处理。复杂背景的提取是后续前景分析的基础。当提炼出背景区域后,我们就可以通过连通域分析前景区域,并利用组件识别的方式分析前景类别,再通过语义分析等方式对前景做拆分和合并。背景分析小结:对比较简单的渐变色背景,通过上述四步基本都能够解决。基于霍夫直线和霍夫圆的思想,去查找特定的轮廓区域,并分析这些轮廓区域做细化分析。再通过漫水填充的方式消除渐变色背景。对于复杂背景的处理,可以基于目标检测的方法,找到一些特定含义的内容。再利用马尔科夫随机场(mrf)细化边缘特征。前景分析前景分析的关键在于组件完整性切割与识别;我们通过连通域分析,防止组件碎片化,再通过机器学习识别组件类型,再通过组件类型进行碎片化合并,反复执行上述动作,直到无特征属性碎片。但是有些情况会比较复杂,我们通过瀑布流中提取一个完整item为例:概述闲鱼页面中瀑布流卡片识别是实现布局分析的一个重要步骤,需求是当卡片完整出现在截屏图像中时(允许图标遮挡)需要识别出来,卡片被背景部分遮挡时不应该识别出来。下图所示的瀑布流卡片样式,由于其布局紧凑且样式繁多,导致容易产生漏检或误检。瀑布流卡片样式 a)红框显示卡片部分被图标遮挡 b)红框显示卡片内图片颜色和卡片外背景颜色接近基于边缘梯度或连通域的传统图像处理方法能根据图像本身的灰度或者形状特征提取出瀑布流卡片的轮廓,优点是定位精度高、运算速度快。缺点是容易受到干扰,召回率不高。基于目标检测或者特征点检测的深度学习方法采用有监督的方式学习卡片的样式特征,优点是不易受到干扰,召回率很高。缺点是因为涉及回归过程,定位精度比传统图像处理方法要低,并且需要大量的人工标注,运算速度也比传统图像处理方法要慢。受集成学习的启发,通过融合传统图像处理方法和深度学习方法,结合两者各自的优点,最终能得到具有较高精确率、召回率和定位精度的识别结果。传统图像处理1.算法流程整个算法流程如下图所示: 1》. 输入的瀑布流卡片图像转换成灰度图后使用对比度受限的自适应直方图均衡化(CLAHE)进行增强 2》. 使用Canny算子进行边缘检测得到二值化图像 3》. 对二值化图像进行形态学膨胀处理,连接断开的边缘 4》. 提取连续边缘的外层轮廓,并基于轮廓包含区域的面积大小丢弃面积较小的轮廓,输出候选轮廓 5》. 使用Douglas-Peucker算法进行矩形逼近,保留最像矩形的外轮廓,输出新的候选轮廓 6》. 最后对第4步的候选轮廓进行水平和垂直方向投影得到平滑的轮廓作为输出2.边缘检测算法流程中1》-3》可以归为边缘检测部分。 受各种因素影响,图像会出现降质,需要对其进行增强来提高边缘检测的效果。使用全图单一的直方图进行均衡化显然不是最好的选择,因为截取的瀑布流图像不同区域对比度可能差别很大,增强后的图像可能会产生伪影。在单一直方图均衡化的基础上,学者基于分块处理的思想提出了自适应的直方图均衡化算法(AHE),但是AHE在增强边缘的同时有时候也会将噪声放大。后来学者在AHE的基础上提出了CLAHE,利用一个对比度阈值来去除噪声的干扰,如下图所示直方图,CLAHE不是将直方图中超过阈值的部分丢弃,而是将其均匀分布于其他bin中。Canny算子是一种经典的边缘检测算子,它能得到精确的边缘位置。Canny检测的一般步骤为:1)用高斯滤波进行降噪 2)用一阶偏导的有限差分计算梯度的幅值和方向 3)对梯度幅值进行非极大值抑制 4)用双阈值检测和连接边缘。实验过程中,需要多次尝试选择较好的双阈值参数。 检测出来的边缘在某些局部地方会断开,可以采用特定形状和尺寸的结构元素对二值化图像进行形态学膨胀处理来连接断开的边缘。边缘检测的结果如下图所示,其中c)中CLAHE设定对比度阈值为10.0,区域大小为(10,10),d)中Canny检测设置双阈值为(20,80),e)中形态学膨胀结构元素使用大小为(3,3)的十字线。3.轮廓提取算法流程中4》-6》可以归为轮廓提取部分。 二值图像形态学膨胀处理后,首先提取连续边缘的外层轮廓。如下图所示,对于只有0和1的二值图像,假设S1为像素值为0的一堆背景点,S2为像素值为1的一堆前景点,外层轮廓B1为一堆前景点最外围的点,内层轮廓B2为一堆前景点最内部的点。通过对二值图像进行行扫描给不同轮廓边界赋予不同的整数值,从而确定轮廓的类型以及之间的层次关系。提取出外层轮廓后通过计算轮廓包含的面积大小丢弃面积较小的外层轮廓,输出第一步候选轮廓。闲鱼页面瀑布流卡片轮廓近似于矩形,在四个角由弧形曲线连接。对于提取的候选轮廓使用Douglas-Peucker算法进行矩形逼近,保留形状接近矩形的外轮廓。Douglas-Peucker算法通过将一组点表示的曲线或多边形拟合成另一组更少的点,使得两组点之间的距离满足特定的精度。之后输出第二步候选轮廓。 通过对第二步候选轮廓所处位置对应的第一步候选轮廓进行水平和垂直方向投影,去除毛刺影响,输出矩形轮廓。轮廓提取的结果如下图所示,其中c)中轮廓包含面积设置的阈值为10000,d)中Douglas-Peucker算法设置的精度为0.01轮廓长度。本文所有提取的轮廓均包含输入框。我们再介绍下机器学习如何处理:深度学习算法1.目标检测算法传统算法中提出采用传统图像处理方法提取轮廓特征,这样会带来一个问题:当图像不清晰或者有遮挡的情况下无法提取出轮廓,即召回率不是很高。基于卷积神经网络的目标检测算法能通过输入大量样本数据,学习到更具有代表性和区别性的特征。目前目标检测算法主要分成两个派系:以R-CNN家族为代表的两阶段流和以YOLO、SSD为代表的一阶段流。一阶段流直接对预测的目标进行分类和回归,优点是速度快,缺点是mAP整体上没有两阶段流高。两阶段流在对预测的目标进行分类和回归前需要先生成候选的目标区域,这样训练时更容易收敛,因此优点是mAP高,缺点是速度上不如一阶段流。不管是一阶段流还是两阶段流,通用的目标检测推理过程如图所示。输入一张图像到特征提取网络(可选择VGG、Inception、Resnet等成熟的CNN网络)得到图像特征,然后将特定区域特征分别送入分类器和回归器进行类别分类和位置回归,最后将框的类别和位置进行输出。2.Faster R-CNNFaster R-CNN对R-CNN家族最大的贡献是将生成候选目标区域的过程整合到整个网络中,使得综合性能有了较大提高,尤其是在检测速度上。Faster R-CNN的基本结构如图所示。主要分为4个部分:1)conv layers。作为一种特征提取网络,使用一组基础的conv+relu+pooling层提取图像的特征,该特征被共享用于后续RPN网络和全连接层。2)Region Proposal Network。该网络用于生成候选目标框,通过softmax判断候选框是属于前景还是背景,并且通过候选框回归修正候选框位置。3)RoI pooling。收集输入的特征图和候选区域,将这些候选区域映射到固定大小并送入后续全连接层。4)classifer。计算候选框的具体类别,并且再次回归修正候选框的位置。使用Faster R-CNN进行瀑布流卡片的识别,得到下图的结果。传统算法与机器学习的融合1.融合流程描述的传统图像方法能够获得高定位精度的卡片位置,但受卡片本身模式的影响,召回率不高)中右边卡片没有检测到。上文描述的基于目标检测的深度学习方法具有较高的泛化能力,能获得较高的召回率,但是回归过程无法得到高定位精度的卡片位置)中卡片都能检测出来,但有两个卡片的边缘几乎粘连在了一起。 将两种方法得到的结果融合在一起,能同时获得高精确率、高召回率、高定位精度的检测结果。融合过程如下:输入一张图像,并行运行传统图像处理方法和深度学习方法,分别得到提取的卡片框trbox和dlbox。定位精度以trbox为标杆,精确率和召回率以dlbox为标杆筛选trbox。规则为当trbox与dlbox的IOU大于某个阈值时(比如0.8)保留此trbox,否则丢弃,得到trbox1筛选dlbox。规则为当dlbox与trbox1的IOU大于某个阈值时(比如0.8)丢弃此dlbox,否则保留,得到dlbox1修正dlbox1位置。规则为dlbox1的每条边移动到距离其最近的一条直线上,约束条件为移动的距离不能超过给定的阈值(比如20个像素),并且移动的边不能跨越trbox1的边,得到修正的dlbox2输出trbox1+dlbox2为最终融合的卡片框2.结果先介绍几个基本指标: True Positive(TP):被模型预测为正的正例数 True Negative(TN):被模型预测为负的负例数 False Positive(FP):被模型预测为正的负例数 False Negative(FN):被模型预测为负的正例数 精确率(Precision) = TP/(TP+FP):反映了被模型预测的正例中真正的正样本所占比重 召回率(Recall) = TP/(TP+FN):反映了被模型正确预测的正例占总的正样本比重 定位精度(IOU) = 两个框的交集大小/两个框的并集大小上图分别显示了不同方法识别的卡片,d)相对于b)的优势是提高了召回率,d)相对于c)的优势是提高了定位精度。图一图二图三显示了一些其他实例图像的识别,每行图像是一类实例图,第一列是原始图像,第二列是传统图像处理识别的卡片,第三列是深度学习识别的卡片,第四列是融合的卡片。图一图二能够准确识别卡片轮廓:图三融合卡片的下边缘并没有完全贴合,这是因为融合步骤中修正dlbox1位置时,采用传统图像处理方法寻找临域范围内最近的直线,受到图像样式的影响,找到的直线并不是期望的卡片下边缘。实验过程中随机截取了50张闲鱼瀑布流卡片图像,共有卡片96个(不包含输入框),对每张图像分别采用传统图像处理方法、深度学习方法、融合方法得到卡片的识别结果,其中传统图像处理方法共识别出65个卡片,深度学习方法共识别出97个,融合后共识别出98个。精确率、召回率、定位精度如下表所示。融合后识别结果结合了传统图像处理方法定位精度高、深度学习方法召回率高的优点。不同方法结果前景算法小结通过对闲鱼页面瀑布流卡片识别过程中的描述,我们简单介绍了前景处理的探索,通过机器视觉算法和机器学习算法协同完成前景元素的提取和识别。结束语本篇我们通过对前景提取和背景分析的介绍,提出了一种通过传统图像处理和深度学习相融合的方法,来得到高精确率、高召回率和高定位精度的识别结果。但方法本身还存在一些瑕疵,比如融合过程对组件元素进行修正时也会受到图像样式的干扰,后续这部分可以进一步进行优化。本文作者:闲鱼技术-上叶,仝辉,深宇阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

March 1, 2019 · 1 min · jiezi

UI2Code智能生成Flutter代码--整体设计篇

摘要: UI2CODE项目是闲鱼技术团队研发的一款通过机器视觉理解+AI人工智能将UI视觉图片转化为端侧代码的工具。背景:随着移动互联网时代的到来,人类的科学技术突飞猛进。然而软件工程师们依旧需要花费大量精力在重复的还原UI视觉稿的工作。UI视觉研发拥有明显的特征:组件,位置和布局,符合机器学习处理范畴。能否通过机器视觉和深度学习等手段自动生成UI界面代码,来解放重复劳动力,成为我们关注的方向。UI2CODE简单介绍:UI2CODE项目是闲鱼技术团队研发的一款通过机器视觉理解+AI人工智能将UI视觉图片转化为端侧代码的工具。2018年3月UI2CODE开始启动技术可行性预研工作,到目前为止,经历了3次整体方案的重构(或者重写)。我们参考了大量的利用机器学习生成代码的方案,但都无法达到商用指标,UI2CODE的主要思想是将UI研发特征分而治之,避免鸡蛋放在一个篮子里。我们着重关注以下3个问题的解法:视觉稿还原精度:我们的设计师甚至无法容忍1像素的位置偏差;准确率:机器学习还处于概率学范畴,但我们需要100%的准确率;易维护性:工程师们看的懂,改的动是起点,合理的布局结构才能保障界面流畅运行。UI2CODE运行效果:UI2CODE插件化运行效果,如下视频:进过几轮重构,最终我们定义UI2CODE主要解决feeds流的卡片自动生成,当然它也可以对页面级自动生成。视频地址:https://yunqivedio.alicdn.com…架构设计:简化分析下UI2CODE的流程:大体分为4个步骤:1.通过机器视觉技术,从视觉稿提取GUI元素2.通过深度学习技术,识别GUI元素类型3.通过递归神经网络技术,生成DSL4.通过语法树模板匹配,生成flutter代码版面分析版面分析只做一件事:切图。图片切割效果直接决定UI2CODE输出结果的准确率。我们拿白色背景的简单UI来举例:上图是一个白色背景的UI,我们将图片读入内存,进行二值化处理:def image_to_matrix(filename): im = Image.open(filename) width, height = im.size im = im.convert(“L”) matrix = np.asarray(im) return matrix, width, height得到一个二维矩阵:将白色背景的值转化为0.像切西瓜一样,我们只需要5刀,就可以将GUI元素分离,切隔方法多种多样:(下面是横切的代码片段,实际切割逻辑稍微复杂些,基本是递归过程)def cut_by_col(cut_num, _im_mask): zero_start = None zero_end = None end_range = len(_im_mask) for x in range(0, end_range): im = _im_mask[x] if len(np.where(im==0)[0]) == len(im): if zero_start == None: zero_start = x elif zero_start != None and zero_end == None: zero_end = x if zero_start != None and zero_end != None: start = zero_start if start > 0: cut_num.append(start) zero_start = None zero_end = None if x == end_range-1 and zero_start != None and zero_end == None and zero_start > 0: zero_end = x start = zero_start if start > 0: cut_num.append(start) zero_start = None zero_end = None客户端的UI基本都是纵向流式布局,我们可以先横切在纵切。将切割点的x,y轴坐标记录下来,它将是处理组件位置关系的核心。切割完成后,我们获取到2组数据:6个GUI元素图片和对应的坐标系记录。后续步骤通过分类神经网络进行组件识别。在实际生产过程中,版面分析会复杂些,主要是在处理复杂背景方面。关注我们的技术公众号,我们后续会详细分解。组件识别:进行组件识别前我们需要收集一些组件样本进行训练,使用Tensorflow提供的CNN模型和SSD模型等进行增量训练。UI2CODE对GUI进行了几十种类型分类:IMAGE, TEXT,SHAP/BUTTON,ICON,PRICE等等,分别归类为UI组件,CI组件和BI组件。UI组件,主要针对flutter原生的组件进行分类。CI组件,主要针对闲鱼自定义UIKIT进行分类。BI组件,主要针对具备一定业务意义的feed卡片进行分类。组件的识别需要反复的通过全局特征反馈来纠正,通常会采用SSD+CNN协同工作,比如下图的红色“全新“shape,这该图例中是richtext的部分,同样的shape样式可能属于button或者icon。属性提取:这块的技术点比较杂,归纳起来需要处理3部分内容:shape轮廓, 字体属性和组件的宽高。完成属性提取,基本上我们完成所有GUI信息的提取。生成的GUI DSL如下图:通过这些数据我们就可以进行布局分析了。其中文字属性的提取最为复杂,后续我们会专门介绍。布局分析:前期我们采用4层LSTM网络进行训练学习,由于样本量比较小,我们改为规则实现。规则实现也比较简单,我们在第一步切图时5刀切割的顺序就是row和col。缺点是布局比较死板,需要结合RNN进行前置反馈。视频地址:https://yunqivedio.alicdn.com…视频中展示的是通过4层LSTM预测布局结构的效果,UI的布局结构就像房屋的框架,建造完成后通过GUI的属性进行精装修就完成了一个UI图层的代码还原工作。代码生成及插件化:机器学习本质上来说还属于概率学范畴,自动生成的代码需要非常高的还原度和100%的准确率,概率注定UI2CODE很难达到100%的准确率,所以我们需要提供一个可编辑工具,由开发者通过工具能够快速理解UI的布局结构和修改布局结构。我们将UI2CODE生成的DSL TREE进行代码模板化匹配,代码模板的内容由资深的flutter技术专家来定义,它代表目前我们发现的最优代码实现方案。代码模板中会引入一些标签,由Intellij plugin来检索flutter工程中是否存在对应的自定义UIKIT,并进行替换,提高代码的复用度。整个插件化工程需要提供自定义UIKIT的检索,替换和校验工作,以及DSL Tree的创建,修改,图示等工作,总体来说,更像ERP系统,花费一些时间能够做的更加完美。小结:本篇我们简单介绍了UI2CODE的设计思路,我们将整个工程结构分为5个部分,其中4块内容核心处理机器视觉的问题,通过机器学习将它们链接起来。代码的线上发布是非常严格的事情,而单纯的机器学习方式,很难达到我们要求,所以我们选择以机器视觉理解为主,机器学习为辅的方式,构建整个UI2CODE工程体系。我们将持续关注AI技术,来打造一个完美的UI2CODE工具。本文作者:闲鱼技术-上叶阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 27, 2019 · 1 min · jiezi

模型微调

什么是预训练模型预训练模型就是已经用数据集训练好了的模型现在我们常用的预训练模型,比如:VGG16/19,Resnet等模型,并且已经用大型数据集来做训练,如:Imagenet,得到训练好的模型参数什么情况下使用微调手头的数据集类型和预训练模型的数据集内容相似,因为不同数据集模型提取的特征不同,所以相应的参数训练后也是不同的数据集内容相似,但是数据量太少计算资源不够自己创建的模型正确率较低为什么要微调用大型数据集训练后的模型,具备提取浅层基础特征和深层抽象特征的能力浅层卷积层提取基础特征,比如:边缘,轮廓等基础特征深层卷积层提取抽象特征,比如:整个脸型全连接层根据特征组合进行评分分类不做微调:从头开始训练模型,需要大量的数据,计算时间和计算资源存在模型不收敛,参数不够优化,准确率低,模型泛化能力低,容易过拟合等风险做微调,可以一定程度上缓解上述存在的问题。模型微调注意事项通常是截断预训练好网络的最后一层(softmax层),用我们自己的softmax层进行替换。如:Imagenet上预训练好的网络输出是1000个类别,我们的实际项目输出类别是10项,则可以进行上述替换。然后,我们在网络上运行预先训练的权重,确保执行交叉验证。使用较小学习率来训练网络。由于我们预计预先训练网络的权重相对于随机初始化的权重已经相当不错,我们不想过快的扭曲它们,通常做法是使初始学习率比从头开始训练的初始学习率小10倍如果手头数据集数量过少,我们可以只训练最后一层,如果数据集数量中等,我们可以冻结预训练网络的前几层权重。因为网络的前几层提取的是基础特征,如:边缘,轮廓。我们希望保持这些权重不变,让我们的网络更专注于学习后续深层中特定于数据集的特征不同数据集下使用微调数据集少,但内容相似度高。这种情况下,我们修改最后几层或者softmax层的输出类别数据集少,内容相似度低。这种情况下,我们冻结预训练网络的初始层(比如K层),然后训练剩余的N-K层。因为数据集内容相似度低,因此我们需要对较高层进行重新训练数据集大,但内容相似度低。这种情况下,需要根据自己的数据从头开始训练神经网络数据量大,内容相似度高。这种情况下,十分理想了,预训练模型也是最有效的。使用模型的最好方法是保留模型的结构和初始权重,然后,我们可以使用预先训练的模型中的权重来重新训练该模型。

February 27, 2019 · 1 min · jiezi

google-colab平台训练模型案例

数据集介绍数据集来自Kaggle,质量很高,由知名医院的专业人员严格审核标注,如图所示数据有4种类别:CNV:具有新生血管膜和相关视网膜下液的脉络膜新血管形成DME:糖尿病性黄斑水肿与视网膜增厚相关的视网膜内液DRUSEN:早期AMD中存在多个玻璃疣NORMAL:视网膜正常,没有任何视网膜液或水肿文件大小约为5GB,8万多张图像,分为训练,测试,验证三个文件夹,每个文件夹按照种类不同分成4个子文件夹,其次是具体图像文件。数据集下载挂载文件夹:from google.colab import drivedrive.mount(’/content/gdrive/’)按照提示进行验证,结果如下:kaggle数据下载:创建kaggle账户并下载kaggle.json文件。创建账户这里就不介绍了,创建完账户后在“我的账户”-“API”中选择“CREATE NEW API TOKEN”,然后下载kaggle.json文件。创建kaggle文件夹:!mkdir -p ~/.kaggle将kaggle.json文件夹复制到指定文件夹:!cp /content/gdrive/My\ Drive/kaggle.json ~/.kaggle/测试是否成功:!kaggle competitions list下载数据集:!kaggle datasets download -d paultimothymooney/kermany2018解压文件:!unzip “/content/kermany2018.zip"将文件解压至google云盘:!unzip “/content/OCT2017.zip” -d “/content/gdrive/My Drive"数据读取训练,测试文件夹:import ostrain_folder = os.path.join(’/’,‘content’,‘gdrive’,‘My Drive’,‘OCT’, ’train’, ‘’, ‘*.jpeg’)test_folder = os.path.join(’/’,‘content’,‘gdrive’,‘My Drive’,‘OCT’, ’test’, ‘’, ‘.jpeg’)有人不知道这里的“ ** ”什么意思,我举例说明吧:Example: If we had the following files on our filesystem: - /path/to/dir/a.txt - /path/to/dir/b.py - /path/to/dir/c.py If we pass “/path/to/dir/.py” as the directory, the dataset would produce: - /path/to/dir/b.py - /path/to/dir/c.py数据处理def input_fn(file_pattern, labels, image_size=(224,224), shuffle=False, batch_size=64, num_epochs=None, buffer_size=4096, prefetch_buffer_size=None): table = tf.contrib.lookup.index_table_from_tensor(mapping=tf.constant(labels)) num_classes = len(labels) def _map_func(filename): label = tf.string_split([filename], delimiter=os.sep).values[-2] image = tf.image.decode_jpeg(tf.read_file(filename), channels=3) image = tf.image.convert_image_dtype(image, dtype=tf.float32) # vgg16模型图像输入shape image = tf.image.resize_images(image, size=image_size) return (image, tf.one_hot(table.lookup(label), num_classes)) dataset = tf.data.Dataset.list_files(file_pattern, shuffle=shuffle) # tensorflow2.0以后tf.contrib模块就不再维护了 if num_epochs is not None and shuffle: dataset = dataset.apply(tf.contrib.data.shuffle_and_repeat(buffer_size, num_epochs)) elif shuffle: dataset = dataset.shuffle(buffer_size) elif num_epochs is not None: dataset = dataset.repeat(num_epochs) # map默认是序列的处理数据,取消序列可加快数据处理 dataset = dataset.apply( tf.contrib.data.map_and_batch(map_func=_map_func, batch_size=batch_size, num_parallel_calls=os.cpu_count())) # prefetch数据预读取,合理利用CPU和GPU的空闲时间 dataset = dataset.prefetch(buffer_size=prefetch_buffer_size) return dataset模型训练import tensorflow as tfimport os# 设置log显示等级tf.logging.set_verbosity(tf.logging.INFO)# 数据集标签labels = [‘CNV’, ‘DME’, ‘DRUSEN’, ‘NORMAL’]# include_top:不包含最后3个全连接层keras_vgg16 = tf.keras.applications.VGG16(input_shape=(224,224,3), include_top=False)output = keras_vgg16.outputoutput = tf.keras.layers.Flatten()(output)predictions = tf.keras.layers.Dense(len(labels), activation=tf.nn.softmax)(output)model = tf.keras.Model(inputs=keras_vgg16.input, outputs=predictions)for layer in keras_vgg16.layers[:-4]: layer.trainable = False optimizer = tf.train.AdamOptimizer()model.compile(loss=‘categorical_crossentropy’, optimizer=optimizer, metrics=[‘accuracy’]) est_config=tf.estimator.RunConfig(log_step_count_steps=10)estimator = tf.keras.estimator.model_to_estimator(model,model_dir=’/content/gdrive/My Drive/estlogs’,config=est_config)BATCH_SIZE = 32EPOCHS = 2estimator.train(input_fn=lambda:input_fn(test_folder, labels, shuffle=True, batch_size=BATCH_SIZE, buffer_size=2048, num_epochs=EPOCHS, prefetch_buffer_size=4)) ...

February 25, 2019 · 1 min · jiezi

如何评估深度学习模型效果?阿里工程师这么做

小叽导读:复杂的深度模型中,如果效果不好,是因为网络设计的欠缺?还是数据天然缺陷?是训练代码的bug?还是Tensorflow自身的问题?基于此,阿里工程师推出了DeepInsight深度学习质量平台,致力于解决当前模型调试和问题定位等一系列问题。接下来,阿里巴巴高级技术专家、DeepInsight深度学习质量平台技术负责人:孙凯(花名:路宸),带我们一起探索。1. 背景机器学习训练过程的调试、可视化以及训练效果的评估一直是业界难题。在数据较少,模型较简单,如LR、GBDT、SVM,超参不多的情况下,模型的可调性和可解释性都有一定保障,那么我们用简单的训练,再观察召回/精度/AUC等指标就可以应对。而深度学习时代,模型的复杂性远远超乎想象,层层嵌套的网络结构,优化器和大量超参的选择,特征的连续化,一起构建了复杂的深度模型。如果效果不好,其原因是多样的,为了定位和解决这些问题,算法研发同学需要花费大量精力反复尝试,而且很可能得不到准确的答案。简单来说,网络模型近似于黑盒。2. DeepInsight通过研究,我们发现训练和评估过程中大量中间指标与模型效果能产生关系,通过系统的分析建模张量、梯度、权重和更新量,能够对算法调优、问题定位起到辅助决策作用。而且,通过改进AUC算法,分析ROC、PR、预估分布等更多评估指标,能够更全面地评估模型效果。通过2个多月的努力,我们推出了DeepInsight平台,致力于解决当前模型调试和问题定位等一系列问题。提交模型开始训练之后,用户可以通过DeepInsight平台,能一站式查看并分析训练过程,从训练中间指标到预测指标,再到性能数据,一应俱全。对于训练中明显的问题,平台也会高亮给予提示。未来,我们希望平台能更好地帮助用户发现和定位训练中的问题,并能给予适当提示(如更改某些子网络的最优化算法、更改学习率动量等),就如同GDB之于C++一样。2.1 目标沉淀并持久化训练数据。深度学习的数据非常宝贵,每次训练的网络拓扑、参数、训练中间过程、模型评估指标都会持久存储,方便后续人工分析和二次建模;沉淀对模型训练的认识,提供分析调优手段,辅助决策,同时规避各类已知问题;利用大数据分析建模,寻找中间过程指标的关系,更好地辅助决策,我们称这个目标为Model on Model,即利用新的模型来分析评估深度模型;在大数据分析建模的基础上,尝试对已有模型进行深度强化学习(DRL),提高深度学习调试效率。2.2 架构系统主要分为四层:输入层、解析层、评估层、输出层;同时包括五大组件:Tensorboard+可视化分析;TensorViewer日志展示对比;TensorDealer集成配置;TensorTracer数据透出;TensorDissection分析调优。2.3 进展2.3.1 高性能可视化组件TensorBoard+Google的TensorBoard(简称为TB)是TensorFlow(简称为TF)的可视化组件,可以查看深度学习的网络结构、中间指标等。原生的TB是单机版命令行方式运行,无法多用户使用;易用性差,每次切换日志路径都需要kill掉当前进程;同时性能也很差,加载工业模型数据立即卡死;指标分层混乱,几千个指标全都罗列,无法查看;用法复杂功能较弱,不支持已展示图形的二次数据对比,不支持X轴浮点数据展示等。因此,我们重构了TB的核心代码,支持GB级日志加载和数据分层,将整个服务改造成多用户版本,利用Docker灵活管理资源并自动回收。UI上支持了高亮自定义指标、分层展示、数据对比、日志上传等,具体如下:支持在线更改TF日志路径:支持图形数据在线聚合对比:支持X轴浮点数值类型展示:支持图形数据Hightlight分维度显示:支持手动调整前端定时刷新时间,实时展示数据:2.3.2 集成配置日志管理系统TensorViewerTF的任务缺乏有效管理,用户无法按需查看和分析数据,更无法回顾历史数据。我们打通了TF与DeepInsight的通路,收集了所有任务的信息,用户可以查看每次训练的实时数据和所有历史数据,支持多任务对比分析;同时支持一键跳转到Tensorboard+,直接对当前日志数据进行可视化展示。2.3.3 改进TensorFlow的可视化数据透出我们定义了一套数据透出方式,可以把所有内部数据透出成统一的Summary格式,并被Tensorboard+处理。由于PS架构没有Master集中处理中间数据,再加上张量、梯度等指标的透出是极为消耗资源的,所以,如何透出数据是值得深入研究的。当前我们在Worker0上透出数据,能满足一般模型训练的要求,未来,会研究Snapshot数据透出方案,在大规模网络下也能取得较好效果。当前,我们已经初步解析了Tensorflow透出的过程指标,正在这些海量指标上进行有监督和无监督的建模探索。2.3.4 改进模型评估指标Tensorflow自带的AUC计算方式分桶较少,计算精度有bug,在处理大量数据时性能不够,而且,仅仅能计算AUC,无法绘制ROC、PR等曲线。我们改进了计算方式,引入更多桶,并提升计算效率,同时,绘制了更多新的指标。当前绘制的指标包括AUC、ROC、PR、波动率、正负样本分桶分布。通过观察正负样本的分布,我们发现Tensorflow异步计算的缺陷,导致某些桶的样本数量有误差,会带来AUC上极小波动,这个bug目前尚未解决。所有的预估指标都无缝接入DeepInsight平台。2.3.5 研究模型训练中间指标通过深入观察和建模大规模Embedding子网络的训练指标,我们发现权重(偏置)值的变化可以反应出相关网络结构是否被有效训练。权重(偏置)值变化微弱的区域即为训练的“盲区”—该部分网络没有被训练起来。通过观察权重(偏置)的梯度,可以帮助我们诊断梯度弥散或梯度爆炸等问题,分析了解训练该部分网络的难易程度,有针对性地调整优化器以及学习率等设置。通过全面考察整个网络各部分的激活以及梯度,可以帮助我们深入了解整个网络前后向多路信息相互耦合、协同传导的复杂机制,从而更有效地进行模型结构的设计调优。对中间指标的研究会沉淀回流到DeepInsight,在训练指标产出后,对用户给予提示,做到辅助决策的作用。本文作者:孙凯阅读原文本文来自云栖社区合作伙伴“ 阿里技术”,如需转载请联系原作者。

February 22, 2019 · 1 min · jiezi

深度学习在美团配送ETA预估中的探索与实践

1.背景ETA(Estimated Time of Arrival,“预计送达时间”),即用户下单后,配送人员在多长时间内将外卖送达到用户手中。送达时间预测的结果,将会以"预计送达时间"的形式,展现在用户的客户端页面上,是配送系统中非常重要的参数,直接影响了用户的下单意愿、运力调度、骑手考核,进而影响配送系统整体成本和用户体验。对于整个配送系统而言,ETA既是配送系统的入口和全局约束,又是系统的调节中枢。具体体现在:ETA在用户下单时刻就需要被展现,这个预估时长继而会贯穿整个订单生命周期,首先在用户侧给予准时性的承诺,接着被调度系统用作订单指派的依据及约束,而骑手则会按照这个ETA时间执行订单的配送,配送是否准时还会作为骑手的工作考核结果。ETA作为系统的调节中枢,需要平衡用户-骑手-商家-配送效率。从用户的诉求出发,尽可能快和准时,从骑手的角度出发,太短会给骑手极大压力。从调度角度出发,太长或太短都会影响配送效率。而从商家角度出发,都希望订单被尽可能派发出去,因为这关系到商家的收入。在这样多维度的约束之下,外卖配送的ETA的建模和估计会变得更加复杂。与打车场景中的ETA做对比,外卖场景的ETA面临如下的挑战:外卖场景中ETA是对客户履约承诺的重要组成部分,无论是用户还是骑手,对于ETA准确性的要求非常高。而在打车场景,用户更加关心是否能打到车,ETA仅提供一个参考,司机端对其准确性也不是特别在意。由于外卖ETA承担着承诺履约的责任,因此是否能够按照ETA准时送达,也是外卖骑手考核的指标、配送系统整体的重要指标;承诺一旦给出,系统调度和骑手都要尽力保证准时送达。因此过短的ETA会给骑手带来极大的压力,并降低调度合单能力、增加配送成本;过长的ETA又会很大程度影响用户体验。外卖场景中ETA包含更多环节,骑手全程完成履约过程,其中包括到达商家、商家出餐、等待取餐、路径规划、不同楼宇交付等较多的环节,且较高的合单率使得订单间的流程互相耦合,不确定性很大,做出合理的估计也有更高难度。下图是骑手履约全过程的时间轴,过程中涉及各种时长参数,可以看到有十几个节点,其中关键时长达到七个。这些时长涉及多方,比如骑手(接-到-取-送)、商户(出餐)、用户(交付),要经历室内室外的场景转换,因此挑战性非常高。对于ETA建模,不光是简单一个时间的预估,更需要的是全链路的时间预估,同时更需要兼顾"单量-运力-用户转化率"转化率之间的平衡。配送ETA的演变包括了数据、特征层面的持续改进,也包括了模型层面一路从LR-XGB-FM-DeepFM-自定义结构的演变。具体ETA在整个配送业务中的位置及配送业务的整体机器学习实践,请参看《机器学习在美团配送系统的实践:用技术还原真实世界》。2.业务流程迭代中的模型改进2.1 基础模型迭代及选择与大部分CTR模型的迭代路径相似,配送ETA模型的业务迭代经历了LR->树模型->Embedding->DeepFM->针对性结构修改的路径。特征层面也进行不断迭代和丰富。模型维度从最初考虑特征线性组合,到树模型做稠密特征的融合,到Embedding考虑ID类特征的融合,以及FM机制低秩分解后二阶特征组合,最终通过业务指标需求,对模型进行针对性调整。特征维度逐步丰富到用户画像/骑手画像/商家画像/地址特征/轨迹特征/区域特征/时间特征/时序特征/订单特征等维度。目前版本模型在比较了Wide&Deep、DeepFM、AFM等常用模型后,考虑到计算性能及效果,最终选择了DeepFM作为初步的Base模型。整个DeepFM模型特征Embedding化后,在FM(Factorization Machine)基础上,进一步加入deep部分,分别针对稀疏及稠密特征做针对性融合。FM部分通过隐变量内积方式考虑一阶及二阶的特征融合,DNN部分通过Feed-Forward学习高阶特征融合。模型训练过程中采取了Learning Decay/Clip Gradient/求解器选择/Dropout/激活函数选择等,在此不做赘述。2.2 损失函数在ETA预估场景下,准时率及置信度是比较重要的业务指标。初步尝试将Square的损失函数换成Absolute的损失函数,从直观上更为切合MAE相比ME更为严苛的约束。在适当Learning Decay下,结果收敛且稳定。同时,在迭代中考虑到相同的ETA承诺时间下,在前后N分钟限制下,早到1min优于晚到1min,损失函数的设计希望整体的预估结果能够尽量前倾。对于提前部分,适当降低数值惩罚。对于迟到部分,适当增大数值惩罚。进行多次调试设计后,最终确定以前后N分钟以及原点作为3个分段点。在原先absolute函数优化的基础上,在前段设计1.2倍斜率absolute函数,后段设计1.8倍斜率absolute函数,以便让结果整体往中心收敛,且预估结果更倾向于提前送达,对于ETA各项指标均有较大幅度提升。2.3 业务规则融入模型目前的业务架构是"模型+规则",在模型预估一个ETA值之后,针对特定业务场景,会有特定业务规则时间叠加以满足特定场景需求,各项规则由业务指标多次迭代产生。这里产生了模型和规则整体优化的割裂,在模型时间和规则时间分开优化后,即模型训练时并不能考虑到规则时间的影响,而规则时间在一年之中不同时间段,会产生不同的浮动,在经过一段时间重复迭代后,会加大割裂程度。在尝试了不同方案后,最终将整体规则写入到了TF模型中,在TF模型内部调整整体规则参数。对于简单的(ab+c)d等规则,可以将规则逻辑直接用TF的OP算子来实现,比如当b、d为定值时,则a、c为可学习的参数。对于过于复杂的规则部分,则可以借助一定的模型结构,通过模型的拟合来代替,过多复杂OP算子嵌套并不容易同时优化。通过调节不同的拟合部分及参数,将多个规则完全在TF模型中实现。最终对业务指标具备很大提升效果,且通过对部分定值参数的更改,具备部分人工干涉模型能力。在这里,整体架构就简化为多目标预估的架构,这里采用多任务架构中常用的Shared Parameters的结构,训练时按比例采取不同的交替训练策略。结构上从最下面的模型中间融合层出发,分别在TF内实现常规预测结构及多个规则时间结构,而其对应的Label则仍然从常规的历史值和规则时间值中来,这样考虑了以下几点:模型预估时,已充分考虑到规则对整体结果的影响(例如多个规则的叠加效应),作为整体一起考虑。规则时间作为辅助Label传入模型,对于模型收敛及Regularization,起到进一步作用。针对不同的目标预估,采取不同的Loss,方便进行针对性优化,进一步提升效果。模型结构在进行预估目标调整尝试中:尝试过固定共享网络部分及不固定共享部分参数,不固定共享参数效果明显。通常情况下激活函数差异不大,但在共享层到独立目标层中,不同的激活函数差异很大。2.4 缺失值处理在模型处理中,特征层面不可避免存在一定的缺失值,而对于缺失值的处理,完全借鉴了《美团“猜你喜欢”深度学习排序模型实践》文章中的方法。对于特征x进入TF模型,进行判断,如果是缺失值,则设置w1参数,如果不是缺失值则进入模型数值为w2*x,这里将w1和w2作为可学习参数,同时放入网络进行训练。以此方法来代替均值/零值等作为缺失值的方法。3.长尾问题优化3.1 模型预估结果+长尾规则补时基础模型学习的是整体的统计分布,但对于一些长尾情形的学习并不充分,体现在长尾情形下预估时间偏短(由于ETA拥有考核骑手的功能,预估偏短对骑手而言意味着很大的伤害)。故将长尾拆解成两部分来分析:业务长尾,即整体样本分布造成的长尾。主要体现在距离、价格等维度。距离越远,价格越高,实际送达时间越长,但样本占比越少,模型在这一部分上的表现整体都偏短。模型长尾,即由于模型自身对预估值的不确定性造成的长尾。模型学习的是整体的统计分布,但不是对每个样本的预估都有“信心”。实践中采用RF多棵决策树输出的标准差来衡量不确定性。RF模型生成的决策树是独立的,每棵树都可以看成是一个专家,多个专家共同打分,打分的标准差实际上就衡量了专家们的“分歧”程度(以及对预估的“信心”程度)。从下图也可以看出来,随着RF标准差的增加,模型的置信度和准时率均在下降。在上述拆解下,采用补时规则来解决长尾预估偏短的问题:长尾规则补时为 <业务长尾因子 , 模型长尾因子> 组合。其中业务长尾因子为距离、价格等业务因素,模型长尾因子为RF标准差。最终的ETA策略即为模型预估结果+长尾规则补时。4.工程开发实践4.1 训练部分实践整体训练流程对于线下训练,采取如下训练流程:Spark原始数据整合 -> Spark生成TFRecord -> 数据并行训练 -> TensorFlow Serving线下GPU评估 -> CPU Inference线上预测整个例行训练亿级数据多轮Epoch下流程持续约4小时,其中TF训练中,考虑到TF实际计算效率并不是很高,有很大比例在数据IO部分,通过Spark生成TFRecord部分,在此可将速度加速约3.6倍。而在数据并行训练部分,16卡内的并行度扩展基本接近线性,具备良好的扩展性。由于PS上参数量并未达到单机无法承受,暂时未对参数在PS上进行切分。Serving线下GPU评估部分,是整个流程中的非必需项,虽然在训练过程中Chief Worker设置Valid集合可有一定的指标,但对全量线下,通过Spark数据调用Serving GPU的评估具备短时间内完成全部流程能力,且可以指定大量复杂自定义指标。数据并行训练方式整个模型的训练在美团的AFO平台上进行,先后尝试分布式方案及单机多卡方案。考虑到生产及结果稳定性,目前线上模型生产采用单机多卡方案进行例行训练。分布式方案:采用TF自带的PS-Worker架构,异步数据并行方式,利用tf.train.MonitoredTrainingSession协调整个训练过程。整个模型参数存储于PS,每个Step上每个Worker拉取数据进行数据并行计算,同时将梯度返回,完成一次更新。目前的模型单Worker吞吐1~2W/s,亿级数据几轮Epoch耗时在几小时内完成。同时测试该模型在平台上的加速比,大约在16块内,计算能力随着Worker数目线性增加,16卡后略微出现分离。在目前的业务实践中,基本上4-6块卡可以短时间内完成例行的训练任务。单机多卡方案:采用PS-Worker的方案在平台上具备不错的扩展性,但是也存在一定的弊端,使用RPC的通讯很容易受到其他任务的影响,整个的训练过程受到最慢Worker的影响,同时异步更新方式对结果也存在一定的波动。对此,在线上生产中,最终选取单机多卡的方案,牺牲一定的扩展性,带来整体训练效果和训练速度的稳定性。单机多卡方案采取多GPU手动指定OP的Device,同时在各个Device内完成变量共享,最后综合Loss与梯度,将Grad更新到模型参数中。TF模型集成预处理模型训练过程中,ID类特征低频过滤需要用到Vocab词表,连续型特征都需要进行归一化。这里会产生大量的预处理文件,在线下处理流程中很容易在Spark中处理成Libsvm格式,然后载入到模型中进行训练。但是在线上预测时,需要在工程开发端载入多个词表及连续型特征的归一化预处理文件(avg/std值文件等),同时由于模型是按天更新,存在不同日期版本的对齐问题。为了简化工程开发中的难度,在模型训练时,考虑将所有的预处理文件写入TF计算图之中,每次在线预测只要输入最原始的特征,不经过工程预处理,直接可得到结果:对于ID类特征,需要进行低频过滤,然后制作成词表,TF模型读入词表的list_arr,每次inference通过ph_vals,得到对应词表的ph_idx。tf_look_up = tf.constant(list_arr, dtype=tf.int64)table = tf.contrib.lookup.HashTable(tf.contrib.lookup.KeyValueTensorInitializer(tf_look_up, idx_range), 0)ph_idx = table.lookup(ph_vals) + idx_bias对于连续型特征,在Spark处理完得到avg/std值后,直接写入TF模型计算图中,作为constant节点,每个ph_in经过两个节点,得到相应ph_out。constant_avg = tf.constant(feat_avg, dtype=tf.float32, shape=[feat_dim], name=“avg”)constant_std = tf.constant(feat_std, dtype=tf.float32, shape=[feat_dim], name=“std”)ph_out = (ph_in - constant_avg) / constant_std4.2 TF模型线上预测配送机器学习平台内置了模型管理平台,对算法训练产出的模型进行统一管理和调度,管理线上模型所用的版本,并支持模型版本的切换和回退,同时也支持节点模型版本状态的管理。ETA使用的DeepFM模型用TensorFlow训练,生成SavedModel格式的模型,需要模型管理平台支持Tensorflow SavedModel格式。实现方案S线上服务加载TensorFlow SavedModel模型有多种实现方案:自行搭建TensorFlow Serving CPU服务,通过gRPC API或RESTful API提供服务,该方案实现比较简单,但无法与现有的基于Thrift的模型管理平台兼容。使用美团AFO GPU平台提供的TensorFlow Serving服务。在模型管理平台中通过JNI调用TensorFlow提供的Java API TensorFlow Java API,完成模型管理平台对SavedModel格式的支持。最终采用TensorFlow Java API加载SavedModel在CPU上做预测,测试batch=1时预测时间在1ms以内,选择方案3作为实现方案。远程计算模式TensorFlow Java API的底层C++动态链接库对libstdc++.so的版本有要求,需要GCC版本不低于4.8.3,而目前线上服务的CPU机器大部分系统为CentOS 6, 默认自带GCC版本为4.4.7。如果每台线上业务方服务器都支持TensorFlow SavedModel本地计算的话,需要把几千台服务器统一升级GCC版本,工作量比较大而且可能会产生其他风险。因此,我们重新申请了几十台远程计算服务器,业务方服务器只需要把Input数据序列化后传给TensorFlow Remote集群,Remote集群计算完后再将Output序列化后返回给业务方。这样只需要对几十台计算服务器升级就可以了。线上性能模型上线后,支持了多个业务方的算法需求,远程集群计算时间的TP99基本上在5ms以内,可以满足业务方的计算需求。总结与展望模型落地并上线后,对业务指标带来较大的提升。后续将会进一步根据业务优化模型,进一步提升效果:将会进一步丰富多目标学习框架,将取餐、送餐、交付、调度等整个配送生命周期内的过程在模型层面考虑,对订单生命周期内多个目标进行建模,同时提升模型可解释性。模型融合特征层面的进一步升级,在Embedding以外,通过更多的LSTM/CNN/自设计结构对特征进行更好的融合。特征层面的进一步丰富。作者简介基泽,美团点评技术专家,目前负责配送算法策略部机器学习组策略迭代工作。周越,2017年加入美团配送事业部算法策略组,主要负责ETA策略开发。显杰,美团点评技术专家,2018年加入美团,目前主要负责配送算法数据平台深度学习相关的研发工作。 ...

February 22, 2019 · 1 min · jiezi

Tensorflow源码解析1 -- 内核架构和源码结构

1 主流深度学习框架对比当今的软件开发基本都是分层化和模块化的,应用层开发会基于框架层。比如开发Linux Driver会基于Linux kernel,开发Android app会基于Android Framework。深度学习也不例外,框架层为上层模型开发提供了强大的多语言接口、稳定的运行时、高效的算子,以及完备的通信层和设备层管理层。因此,各大公司早早的就开始了深度学习框架的研发,以便能占领市场。当前的框架有数十种之多,主流的如下(截止到2018年11月)显然TensorFlow是独一无二的王者。第二名Keras,它是对TensorFlow或Theano接口的二次封装,严格意义上并不是一个独立的深度学习框架。TensorFlow目前也已经集成了Keras,使得安装了TensorFlow的用户就可以直接使用Keras了。TensorFlow之所以能够从数十种框架中脱颖而出,主要优点有出身高贵,是谷歌出品的。但其他很多框架出身也不差,例如PyTorch之于Facebook,MXNET之于Amazon2015年就开源了,比较早的俘获了一大批开发者。这个确实是tf的一大先发优势,但PyTorch的前身Caffe,以及MXNET开源时间都不晚,而且Caffe流行时间比tf早,后来才被赶超的。更有Theano这样的绝对老前辈。由此可见,软件开源是多么重要。目前流行的深度学习框架也基本都开源了。支持的开发语言多,支持Python Java Go C++等多种流行语言。相比某些框架,确实是优势很大。相比MXNET则小巫见大巫了。MXNET早期发展的一个主要方向就是前端多语言的支持,连MATLAB R Julia等语言都支持了。运行效率高。早期的时候,其实tf的运行效率比很多框架都要低一些的。安装容易,用户上手快,文档齐全,社区活跃。这个是tf的一个较大优势,特别是社区方面,也就是我们常说的生态优势。互联网头部集中效应十分明显,体现在开源软件上也是一样。这也是我认为最大的一个优势。总结起来,TensorFlow虽然每个方面都不是绝对领先的优势,但贵在每个方面都做的不错,因此最终能够一骑绝尘,独领风骚。学习Tensorflow框架内核,可以理解前端接口语言的支持,session生命周期,graph的构建、分裂和执行,operation的注册和运行,模块间数据通信,本地运行和分布式运行模式,以及CPU GPU TPU等异构设备的封装支持等。学习这些,对于模型的压缩 加速 优化等都是大有裨益的。2 TensorFlow系统架构TensorFlow设计十分精巧,基于分层和模块化的设计思想进行开发的。框架如下图整个框架以C API为界,分为前端和后端两大部分。前端:提供编程模型,多语言的接口支持,比如Python Java C++等。通过C API建立前后端的连接,后面详细讲解。后端:提供运行环境,完成计算图的执行。进一步分为4层运行时:分为分布式运行时和本地运行时,负责计算图的接收,构造,编排等。计算层:提供各op算子的内核实现,例如conv2d, relu等通信层:实现组件间数据通信,基于GRPC和RDMA两种通信方式设备层:提供多种异构设备的支持,如CPU GPU TPU FPGA等模型构造和执行流程TensorFlow的一大特点是,图的构造和执行相分离。用户添加完算子,构建好整图后,才开始进行训练和执行,也就是图的执行。大体流程如下图构建:用户在client中基于TensorFlow的多语言编程接口,添加算子,完成计算图的构造。图传递:client开启session,通过它建立和master之间的连接。执行session.run()时,将构造好的graph序列化为graphDef后,以protobuf的格式传递给master。图剪枝:master根据session.run()传递的fetches和feeds列表,反向遍历全图full graph,实施剪枝,得到最小依赖子图图分裂:master将最小子图分裂为多个Graph Partition,并注册到多个worker上。一个worker对应一个Graph Partition。图二次分裂:worker根据当前可用硬件资源,如CPU GPU,将Graph Partition按照op算子设备约束规范(例如tf.device(’/cpu:0’),二次分裂到不同设备上。每个计算设备对应一个Graph Partition。图运行:对于每一个计算设备,worker依照op在kernel中的实现,完成op的运算。设备间数据通信可以使用send/recv节点,而worker间通信,则使用GRPC或RDMA协议。3 前端多语言实现 - swig包装器TensorFlow提供了很多种语言的前端接口,使得用户可以通过多种语言来完成模型的训练和推断。其中Python支持得最好。这也是TensorFlow之所以受欢迎的一大原因。前端多语言是怎么实现的呢?这要归功于swig包装器。swig是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。在TensorFlow使用bazel编译时,swig会生成两个wrapper文件pywrap_tensorflow_internal.py:对接上层Python调用pywrap_tensorflow_internal.cc:对接底层C API调用。pywrap_tensorflow_internal.py 模块被导入时,会加载_pywrap_tensorflow_internal.so动态链接库,它里面包含了所有运行时接口的符号。而pywrap_tensorflow_internal.cc中,则注册了一个函数符号表,实现Python接口和C接口的映射。运行时,就可以通过映射表,找到Python接口在C层的实现了。4 tensorflow 源码结构TensorFlow源码基本也是按照框架分层来组织文件的。如下其中core为tf的核心,它的源码结构如下5 总结TensorFlow框架设计精巧,代码量也很大,我们可以从以下部分逐步学习TensorFlow内核架构和源码结构。先从全局上对框架进行理解。前后端连接的桥梁–Session,重点理解session的生命周期,并通过相关源码可以加深理解Python前端如何调用底层C实现。TensorFlow核心对象—Graph。图graph是TensorFlow最核心的对象,基本都是围绕着它来进行的。graph的节点为算子operation,边为数据tensor。TensorFlow图的节点 – Operation。operation是图graph的节点,承载了计算算子。TensorFlow图的边 – Tensor。Tensor是图graph的边,承载了计算的数据。TensorFlow本地运行时。TensorFlow分布式运行时。和本地运行时有一些共用的接口,但区别也很大。TensorFlow设备层。主要了解设备层的定义规范,以及实现。TensorFlow队列和并行运算。TensorFlow断点检查checkpoint,模型保存Saver,以及可视化tensorboard。这三个为TensorFlow主要的工具。本文作者:扬易阅读原文本文为云栖社区原创内容,未经允许不得转载。

February 20, 2019 · 1 min · jiezi

指明方向与趋势!2019开发者技能报告出炉!!!

近日国外开发者平台 HankerRank 发布了 2019 年开发者技能调查报告( https://research.hackerrank.com/developer-skills/2019 ),该报告根据对71,281开发者的调查得出。2018 年最受欢迎的开发语言经过调查,2018年的所有开发语言中,JavaScript是最受欢迎的语言,2017年最受欢迎的语言是Java,今年被JavaScript超越,位居第二。2019年开发者最想学的语言报告调查了开发者最想学习的开发语言,结果显示,Go语言、Kotlin语言和Python语言位列前三。 Go语言 Go语言是谷歌2009发布的第二款开源编程语言。Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。Go语言是谷歌推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。Kotlin Kotlin 是一个用于现代多平台应用的静态编程语言 ,由 JetBrains 开发。Kotlin可以编译成Java字节码,也可以编译成JavaScript,方便在没有JVM的设备上运行。Kotlin已正式成为Android官方支持开发语言。Python Python是一种计算机程序设计语言。是一种动态的、面向对象的脚本语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。2018年最闻名的开发框架2018年,最闻名的开发框架是AngularJS、其次是Spring。AngularJS AngularJS 是一个 JavaScript框架。它是一个以 JavaScript 编写的库。它可通过 标签添加到HTML 页面。Spring Spring是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。2019最想学习的框架2019年,开发者最想学洗的框架是React,Java系的Spring排名第七。React React主要用于构建UI。你可以在React里传递多种类型的参数,如声明代码,帮助你渲染出UI、也可以是静态的HTML DOM元素、也可以传递动态变量、甚至是可交互的应用组件。最容易落地的新技术是什么最近几年,新技术层出不穷,如IoT(物联网)、深度学习、机器学习、计算机视觉、区块链、量子计算、AR(增强现实)、VR(虚拟现实)等。这些新技术,到底哪个在开发者心目中是最接近现实,目前看来最容易落地的呢。经过调查,IoT以53%占比获得第一名、量子计算排名最后,区块链倒数第二。找工作最看重什么不同程序员找工作的时候,会看重不同的东西,比如薪资、成长等。那么报告结果是如何的呢?初级开发者和高级开发者找工作最看重的东西排名前三名是一致的:个人成长和学习空间、其次是工作与生活的平衡,也就是加班的多少、排名第三的是有竞争力的薪酬。总结以上就是2018开发者技能报告的所有主要内容。报告中分别围绕开发者、编程语言等展开。涉及到多个方面。希望能对所有读者有所启发。活在当下,既要脚踏实地,也要仰望星空。作为一名程序员,我们也要时不时的抬起头,看一看自己所在的行业。本文作者:阿里高级开发工程师 洪亮阅读原文本文首发自微信公众号“Hollis”,如需转载请联系原作者。

February 19, 2019 · 1 min · jiezi

Perseus-BERT——业内性能极致优化的BERT训练方案【阿里云弹性人工智能】

一,背景——横空出世的BERT全面超越人类2018年在自然语言处理(NLP)领域最具爆炸性的一朵“蘑菇云”莫过于Google Research提出的BERT(Bidirectional Encoder Representations from Transformers)模型。作为一种新型的语言表示模型,BERT以“摧枯拉朽”之势横扫包括语言问答、理解、预测等各项NLP锦标的桂冠,见图1和图2。【图1】SQuAD是基于Wikipedia文章的标准问答数据库的NLP锦标。目前SQuAD2.0排名前十名均为基于BERT的模型(图中列出前五名),前20名有16席均是出自BERT 【图2】GLUE是一项通用语言理解评估的benchmark,包含11项NLP任务。BERT自诞生日起长期压倒性霸占榜首(目前BERT排名第二,第一为Microsoft提交的BIGBIRD模型,由于没有URL链接无从知晓模型细节,网传BIGBIRD的名称上有借鉴BERT BIG模型之嫌) 业内将BERT在自然语言处理的地位比作ResNet之于计算机视觉领域的里程碑地位。在BERT横空出世之后,所有的自然语言处理任务都可以基于BERT模型为基础展开。一言以蔽之,现如今,作为NLP的研究者,如果不了解BERT,那就是落后的科技工作者;作为以自然语言处理为重要依托的科技公司,如果不落地BERT,那就是落后生产力的代表。二,痛点——算力成为BERT落地的拦路虎BERT强大的原因在哪里?让我们拂去云霭,窥探下硝烟下的奥秘。BERT模型分为预训练模型(Pretrain)和精调模型(Finetune)。Pretrain模型为通用的语言模型。Finetune只需要在Pretrain的基础上增加一层适配层就可以服务于从问答到语言推理等各类任务,无需为具体任务修改整体模型架构,如图3所示。这种设计方便BERT预处理模型适配于各类具体NLP模型(类似于CV领域基于ImageNet训练的各种Backbone模型)。【图3】左图基于BERT pretrain的模型用于语句问答任务(SQuAD)的finetune模型,右图为用于句对分类(Sentence Pair Classification Tasks)的finetune模型。他们均是在BERT Pretrain模型的基础上增加了一层具体任务的适配层因此,BERT的强大主要归功于精确度和鲁棒性俱佳的Pretrain语言模型。大部分的计算量也出自Pretrain模型。其主要运用了以下两项技术,都是极其耗费计算资源的模块。1. 双向Transformer架构图4可见,与其他pre-training的模型架构不同,BERT从左到右和从右到左地同时对语料进行transformer处理。这种双向技术能充分提取语料的时域相关性,但同时也大大增加了计算资源的负担。【关于Transformer是Google 17年在NLP上的大作,其用全Attention机制取代NLP常用的RNN及其变体LSTM等的常用架构,大大改善了NLP的预测准确度。本文不展开,该兴趣的同学可以自行搜索一下】。【图4】Pretrain架构对比。其中OpenAI GPT采用从左到右的Transformer架构,ELMo采用部分从左到右和部分从右到左的LSTM的级联方式。BERT采用同时从左到右和从右到左的双向Transformer架构。1. 词/句双任务随机预测BERT预训练模型在迭代计算中会同时进行单词预测和语句预测两项非监督预测任务。其一,单词预测任务对语料进行随机MASK操作(Masked LM)。在所有语料中随机选取15%的单词作为Mask数据。被选中Mask的语料单词在迭代计算过程中80%时间会被掩码覆盖用于预测、10%时间保持不变、10%时间随机替换为其他单词,如图5所示。其二,语句预测任务(Next Sentence Prediction)。对选中的前后句A和B,在整个迭代预测过程中,50%的时间B作为A的真实后续语句(Label=IsNext),另外50%的时间则从语料库里随机选取其他语句作为A的后续语句(Label=NotNext),如图5所示【图5】词/句双任务随机预测输入语料实例。蓝框和红框为同一个语料输入在不同时刻的随机状态。对单词预测任务,蓝框中的“went”为真实数据,到了红框则被[MASK],红框中的“the” 则相反;对于语句预测任务,蓝框中的句组为真实的前后句,而红框中的句组则为随机的组合。这种随机选取的单词/语句预测方式在功能上实现了非监督数据的输入的功能,有效防止模型的过拟合。但是按比例随机选取需要大大增加对语料库的迭代次数才能消化所有的语料数据,这给计算资源带来了极大的压力。综上,BERT预处理模型功能需要建立在极强的计算力基础之上。BERT论文显示,训练BERT BASE 预训练模型(L=12, H=768, A=12, Total Parameters=110M, 1000,000次迭代)需要1台Cloud TPU工作16天;而作为目前深度学习主流的Nvidia GPU加速卡面对如此海量的计算量更是力不从心。即使是目前主流最强劲的Nvidia V100加速卡,训练一个BERT-Base Pretrain模型需要一两个月的时间。而训练Large模型,需要花至少四五个月的时间。花几个月训练一个模型,对于绝大部分在GPU上训练BERT的用户来说真是伤不起。三,救星——擎天云加速框架为BERT披荆斩棘阿里云弹性人工智能团队依托阿里云强大的基础设施资源打磨业内极具竞争力的人工智能创新方案。基于BERT的训练痛点,团队打造了擎天优化版的Perseus-BERT, 极大地提升了BERT pretrain模型的训练速度。在云上一台V100 8卡实例上,只需4天不到即可训练一份BERT模型。Perseus-BERT是如何打造云上最佳的BERT训练实践?以下干货为您揭秘Perseus-BERT的独门绝技。1. Perseus 统一分布式通信框架 —— 赋予BERT分布式训练的轻功Perseus(擎天)统一分布式通信框架是团队针对人工智能云端训练的痛点,针对阿里云基础设施极致优化的分布式训练框架。其可轻便地嵌入主流人工智能框架的单机训练代码,在保证训练精度的同时高效地提升训练的多机扩展性。擎天分布式框架的干货介绍详见团队另一篇文章《Perseus(擎天):统一深度学习分布式通信框架》。针对tensorflow代码的BERT,Perseus提供horovod的python api方便嵌入BERT预训练代码。基本流程如下:让每块GPU对应一个Perseus rank进程;对global step和warmup step做基于rank数的校准;对训练数据根据rank-id做划分;给Optimizer增加DistributeOptimizer的wrapper。值得注意的是,BERT源码用的自定义的Optimizer,在计算梯度时采用了以下apigrads = tf.gradients(loss, tvars)Perseus的DistributeOptimizer继承标准的Optimizer实现,并在compute_gradients api 上实现分布式的梯度更新计算。因此对grads获取做了如下微调grads_and_vars = optimizer.compute_gradients(loss, tvars)grads = list()for grad, var in grads_and_vars: grads.append(grad)2. 混合精度训练和XLA编译优化——提升BERT单机性能的内功混合精度在深度学习中,混合精度训练指的是float32和float16混合的训练方式,一般的混合精度模式如图6所示【图6】混合精度训练示例。在Forward+Backward计算过程中用float16做计算,在梯度更新时转换为float32做梯度更新。混合梯度对Bert训练带来如下好处,增大训练时的batch size和sequence_size以保证模型训练的精度。 目前阿里云上提供的主流的Nvidia显卡的显存最大为16GB,对一个BERT-Base模型在float32模式只能最高设置为sequence_size=256,batch_size=26。BERT的随机预测模型设计对sequence_size和batch_size的大小有一定要求。为保证匹配BERT的原生训练精度,需要保证sequece_size=512的情况下batch_size不小于16。Float16的混合精度可以保证如上需求。混合精度能充分利用硬件的加速资源。 NVidia从Volta架构开始增加了Tensor Core资源,这是专门做4x4矩阵乘法的fp16/fp32混合精度的ASIC加速器,一块V100能提供125T的Tensor Core计算能力,只有在混合精度下计算才能利用上这一块强大的算力。 受限于float16的表示精度,混合精度训练的代码需要额外的编写,NVidia提供了在Tensorflow下做混合精度训练的教程 。其主要思路是通过tf.variable_scope的custom_getter 参数保证存储的参数为float32并用float16做计算。 在BERT预训练模型中,为了保证训练的精度,Perseus-BERT没有简单的利用custom_getter参数,而是显式指定训地参数中哪些可以利用float16不会影响精度,哪些必须用float32已保证精度。我们的经验如下:Embedding部分要保证float32精度;Attetion部分可以利用float16加速;Gradients相关的更新和验证需要保证float32精度;非线性激活等模块需要保证float32精度。XLA编译器优化XLA是Tensorflow新近提出的模型编译器,其可以将Graph编译成IR表示,Fuse冗余Ops,并对Ops做了性能优化、适配硬件资源。然而官方的Tensorflow release并不支持xla的分布式训练,为了保证分布式训练可以正常进行和精度,我们自己编译了带有额外patch的tensorflow来支持分布式训练,Perseus-BERT 通过启用XLA编译优化加速训练过程并增加了Batch size大小。3. 数据集预处理的加速Perseus BERT 同时对文本预处理做的word embedding和语句划分做了并行化的优化。这里就不展开说明。四,性能——计算时间单位从月降低到天图7展示了Perseus BERT在P100实例上的性能,与开源主流的horovod相比,Peseus-BERT双机16卡的分布式性能是前者的5倍之多。目前某大客户已在阿里云P100集群上大规模上线了Perseus BERT,用10台4卡P100只需要2.5天即可训练完成业务模型,如果用开源的horovod(Tensorflow分布式性能优化版)大概需要1个月的时间。【图7】Bert在阿里云上P100实例的对比(实验环境Bert on P100; Batch size: 22 ;Max seq length: 256 ;Data type:float32; Tensorflow 1.12; Perseus: 0.9.1;Horovod: 0.15.2)为了和Google TPU做对比,我们量化了TPU的性能,性能依据如图8。一个Cloud TPU可计算的BERT-Base性能 256 (1000000/4/4/24/60/60) = 185 exmaples/s。 而一台阿里云上的V100 单机八卡实例在相同的sequence_size=512下, 通过Perseus-BERT优化的Base模型训练可以做到 680 examples/s,接近一台Cloud TPU的4倍性能。对一台Cloud TPU花费16天才能训练完的BERT模型,一台阿里云的V100 8卡实例只需要4天不到便可训练完毕。【图8】BERT Pretain在Google Cloud TPU上的性能依据五,总结——基于阿里云基础设施的AI极致性能优化弹性人工智能团队一直致力基于阿里云基础设施的AI极致性能优化的创新方案。Perseus-BERT就是一个非常典型的案例,我们在框架层面上基于阿里云的基础设施做深度优化,充分释放阿里云上基础资源的计算能力,让阿里云的客户充分享受云上的AI计算优势,让天下没有难算的AI。本文作者:笋江阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

February 19, 2019 · 1 min · jiezi

人工智能深度学习Caffe框架介绍,优秀的深度学习架构

在深度学习领域,Caffe框架是人们无法绕过的一座山。这不仅是因为它无论在结构、性能上,还是在代码质量上,都称得上一款十分出色的开源框架。更重要的是,它将深度学习的每一个细节都原原本本地展现出来,大大降低了人们学习研究和开发的难度。一、从Caffe的开发中了解到的用户需求:深度学习的框架总会不断改变,Caffe也会有被新框架代替的一天。但是在开发Caffe的过程中,贾扬清发现大家喜欢的框架其实有着很多相似的地方,这些闪光点拥有很长的生命周期,发现并掌握人们这些共同偏好将为以后开发新的框架积累经验。Caffe之所以广受欢迎可能是因为有以下的四个特点: 1、 稳定的模型架构 Caffe通过Protobuf来定义一个网络的结构,而这个由Google开源的库具有优秀的版本兼容性。随着Caffe的框架源码的不断更新迭代,之前定义的网络结构依然能兼容解析,模型仍然能正确加载运行。 2、较好的设备抽象 合理的设备抽象能够精简代码,提高框架适用性。在这方面Caffe做了比较好的尝试,模型的训练和使用与不同的平台耦合比较低,只要平台能解析网络结构并读取二进制的模型参数,就能运行该模型。这样大大拓展了框架的应用范围,自然更加符合用户的使用需求。 3、清晰的说明教程 如何让首次接触到框架的人通过说明教程就能最快地熟悉运用,这对于一个新面世的框架来说尤为重要。以Caffe为例,用户只需要将官方文档的例子跑一遍,基本就能清楚Caffe的操作过程和细节,这给它的广泛传播提供了最坚实的基础。 4、开放的模型仓库 目前Caffe还维护了一个Model Zoo, 许多论文的作者会将模型发布到这里,其它用户可以利用这些材料轻松地将模型复现,还可以在github上参与开发讨论,从而更深入地学习实践。二、现有深度学习框架的侧重点: 1、人们的需求多种多样,目前,还没有任何一种深度学习的框架能够满足人们所有的需求。对于工业界而言,从业者看重的是框架的稳定性强、数据量大、速度快、容易进行数据整合等。 2、对于学术界来说,学者们更希望框架容易调试、灵活性要强、迭代要快。因此,比照现有深度学习框架的特点,Theano、Torch可能会更加适合学术界,而D4J等可能就要更适合工业界一些,至于Caffe、Tensorflow等为代表的框架则是介于二者之间。 三、对未来机器学习框架设计的一些思考: 1、使用计算图 (computation graph) Caffe框架在实现网络的forward, backward, update时,是通过Solver, Net, Layer之间递进地逐步回调对应的forward, backward, update来实现的,在加入并行化之后,为了用计算来覆盖数据传输的时间,这些回调的运用会变得相对复杂。 因此,目前许多框架都在往computation graph的风格上偏移。这种基于computation graph的深度学习框架不仅在网络的更新方面更加直接,而且在并行方面,无论是数据并行方式还是模型并行方式,都能做到接近线性的提速。大家未来也可以在这个方向做些尝试。 2、高效方便地输入数据 对于Caffe用户而言,首要问题便是如何导入数据。尤其是在算法比较简单时,保证数据输入的高效性将成为制约模型的首要因素。之前进行的某个项目里,在8个GPU(Titan X)上训练AlexNet,需要达到每秒钟处理1600张图片(3.14GB/s)的要求。甚至对于另外一些模型而言,还需要更多的吞吐量。如果数据接口没有做好,是绝对无法达到这样的要求的。 3、更快的速度 网络结构实现需要在灵活性和速度上进行权衡,这种权衡可以体现在框架设计的粗细粒度上。例如一个Inception的结构,是做成像Caffe这样通过各个层的累积来形成,还是直接由Conv2D, BiasAdd, Relu这样的基本计算来直接构造一个Inception结构。这样不同粗细粒度的构建方法体现了整个框架对速度或是灵活性的权衡。 另外,对于底层的实现,最好用硬件供应商提供的数值计算库,比如CuDNN, MKL-DNN,Accelerate,Eigen,NNPack等。 4、 可移植性 要提升框架的实用价值,就必须提升其训练出的模型的可移植性。换句话说,也就是要让框架训练出的模型具有平台无关性,包括了系统层面(windows、linux、android、iOS、OS X等)及硬件层面(CPU、GPU、FPGA、ARM等)。这就必须使得设计出的模型更加轻量。—————————————–人工智能范畴及深度学习主流框架工业机器人,家用机器人这些只是人工智能的一个细分应用而已。图像识别,语音识别,推荐算法,NLP自然语言,广告算法,预测算法,数据挖掘,无人驾驶、医疗咨询机器人、聊天机器人,这些都属于人工智能的范畴。人工智能现在用到的基础算法是深度学习里面的神经网络算法,具体应用场景有不同的专业算法实际上很多细分领域的,差别还是很多的机器人的对运动控制算法,图像识别算法要求比较高像alphaGo,推荐算法,语音识别这些就主要靠深度学习算法和大数据训练了深度学习的开源框架现在主流的有:caffeonspark(微软), tensorflow(google),Theano,dl4j, Torch,Kerascaffeonspark用在视觉图片识别上比较好,dl4j用在NLP上做类似问答搜索的比较多,tensorflow用在学习新的算法上比较好关注主页一起学习交流

February 15, 2019 · 1 min · jiezi

Transformer-XL: Unleashing the Potential of Attention Models

简介现实远程依赖问题,比如要正确理解文章内容,有时需要阅读多处段落,这对人来说轻松自如。但是,对神经网络来说,远程依赖问题依然是一个挑战。虽然基于门控的RNN(LSTM,GRU等)和梯度裁剪等技术提高了对远程依赖建模的能力,但仍不足以解决问题。其中一个解决方法就是使用Transformers,Transformers允许数据单元直接连接,可以更好的捕获远距离的数据关系。但是,在语音模型中,Transformers一般使用固定长度context实现,即:把文本序列截断为几个固定长度的序列,然后分别单独处理。这存在两个问题:无法计算超过固定长度的依赖关系。序列截断后,造成段落边界破碎,从而造成低效优化,即使是短序列这也是严重问题。为了解决这些问题,可以尝试使用Transformers-XL模型。Transformers-XL由两种技术构成:Segment-level Recurrence和Relative Positional Encodings。Segment-level Recurrence在训练期间,当模型处理下一个新段落时,将前一个段落的计算表示固定并且缓存以作为重用扩展上下文。此附加连接将最大可能的将依赖性长度增加N倍,其中N是网络的深度,因为上下文信息现在能够跨越段落边界流动。此外,这种重复机制还解决了上下文碎片问题。Relative Positional Encodings在标准的Transformer中,序列顺序的信息,都是由一组位置编码提供,每一个位置都有绝对的位置信息。但将这个逻辑应用到重用机制中时,会导致性能损失。这个问题的解决思路是,对隐藏状态中的相对位置信息进行编码。从概念上讲,位置编码为模型提供了关于应如何收集信息的时间线索,即应该在哪里介入处理。以相对的方式定义时间线索,将相同的信息注入每层的注意分数,更加直观,也更通用。基于这个思路,可以创建一组相对位置编码,使得重用机制变得可行,也不会丢失任何的时间信息。将相对位置嵌入Transformer之中,并配合重用机制,就得到了Transformer-XL的架构。基于这些改进,Transformer-XL在相关的数据集上都取得了很好的成绩。论文中表示,这是第一个在字符级和单词级建模方面比RNN结果更好的自注意力模型。总结Transformer-XL 在几种不同的数据集(大 / 小,字符级别 / 单词级别等)均实现了最先进的语言建模结果。它结合了深度学习的两个重要概念——循环机制和注意力机制,允许模型学习长期依赖性,且可能可以扩展到需要该能力的其他深度学习领域,例如音频分析(如每秒 16k 样本的语音数据)等。

February 13, 2019 · 1 min · jiezi

NLP教程:教你如何自动生成对联

桃符早易朱红纸,杨柳轻摇翡翠群 ——FlyAI Couplets体验对对联Demo: https://www.flyai.com/couplets循环神经网络最重要的特点就是可以将序列作为输入和输出,而对联的上联和下联都是典型的序列文字,那么,能否使用神经网络进行对对联呢?答案是肯定的。本项目使用网络上收集的对联数据集地址作为训练数据,运用Seq2Seq + 注意力机制网络完成了根据上联对下联的任务。项目流程数据处理Seq2Seq + Attention 模型解读模型代码实现训练神经网络数据处理创建词向量字典和词袋字典在原始数据集中,对联中每个汉字使用空格进行分割,格式如下所示: 室 内 崇 兰 映 日,林 间 修 竹 当 风 翠 岸 青 荷 , 琴 曲 潇 潇 情 辗 转,寒 山 古 月 , 风 声 瑟 瑟 意 彷 徨由于每个汉字表示一个单一的词,因此不需要对原始数据进行分词。在获取原始数据之后,需要创建两个字典,分别是字到词向量的字典和字到词袋的字典,这样做是为了将词向量输入到网络中,而输出处使用词袋进行分类。在词袋模型中,添加三个关键字 ’ “ ‘, ’ ” ’ 和 ’ ~ ’ ,分别代表输入输出的起始,结束和空白处的补零,其关键字分别为1,2,0。class Processor(Base): ## Processor是进行数据处理的类 def init(self): super(Processor, self).init() embedding_path = os.path.join(DATA_PATH, ’embedding.json’) ##加载词向量字典 words_list_path = os.path.join(DATA_PATH, ‘words.json’) ## 加载词袋列表 with open(embedding_path, encoding=‘utf-8’) as f: self.vocab = json.loads(f.read()) with open(words_list_path, encoding=‘utf-8’) as f: word_list = json.loads(f.read()) self.word2ix = {w:i for i,w in enumerate(word_list, start = 3)} self.word2ix[’“’] = 1 ##句子开头为1 self.word2ix[’”’] = 2 ##句子结尾为2 self.word2ix[’~’] = 0 ##padding的内容为0 self.ix2word = {i:w for w,i in self.word2ix.items()} self.max_sts_len = 40 ##最大序列长度对上联进行词向量编码def input_x(self, upper): ##upper为输入的上联 word_list = [] #review = upper.strip().split(’ ‘) review = [’“’] + upper.strip().split(’ ‘) + [’”’] ##开头加符号1,结束加符号2 for word in review: embedding_vector = self.vocab.get(word) if embedding_vector is not None: if len(embedding_vector) == 200: # 给出现在编码词典中的词汇编码 embedding_vector = list(map(lambda x: float(x),embedding_vector)) ## convert element type from str to float in the list word_list.append(embedding_vector) if len(word_list) >= self.max_sts_len: word_list = word_list[:self.max_sts_len] origanal_len = self.max_sts_len else: origanal_len = len(word_list) for i in range(len(word_list), self.max_sts_len): word_list.append([0 for j in range(200)]) ## 词向量维度为200 word_list.append([origanal_len for j in range(200)]) ## 最后一行元素为句子实际长度 word_list = np.stack(word_list) return word_list对真实下联进行词袋编码def input_y(self, lower): word_list = [1] ##开头加起始符号1 for word in lower: word_idx = self.word2ix.get(word) if word_idx is not None: word_list.append(word_idx) word_list.append(2) ##结束加终止符号2 origanal_len = len(word_list) if len(word_list) >= self.max_sts_len: origanal_len = self.max_sts_len word_list = word_list[:self.max_sts_len] else: origanal_len = len(word_list) for i in range(len(word_list), self.max_sts_len): word_list.append(0) ## 不够长度则补0 word_list.append(origanal_len) ##最后一个元素为句子长度 return word_listSeq2Seq + Attention 模型解读Seq2Seq 模型可以被认为是一种由编码器和解码器组成的翻译器,其结构如下图所示:编码器(Encoder)和解码器(Decoder)通常使用RNN构成,为提高效果,RNN通常使用LSTM或RNN,在上图中的RNN即是使用LSTM。Encoder将输入翻译为中间状态C,而Decoder将中间状态翻译为输出。序列中每一个时刻的输出由的隐含层状态,前一个时刻的输出值及中间状态C共同决定。Attention 机制在早先的Seq2Seq模型中,中间状态C仅由最终的隐层决定,也就是说,源输入中的每个单词对C的重要性是一样的。这种方式在一定程度上降低了输出对位置的敏感性。而Attention机制正是为了弥补这一缺陷而设计的。在Attention机制中,中间状态C具有了位置信息,即每个位置的C都不相同,第i个位置的C由下面的公式决定:公式中,Ci代表第i个位置的中间状态C,Lx代表输入序列的全部长度,hj是第j个位置的Encoder隐层输出,而aij为第i个C与第j个h之间的权重。通过这种方式,对于每个位置的源输入就产生了不同的C,也就是实现了对不同位置单词的‘注意力’。权重aij有很多的计算方式,本项目中使用使用小型神经网络进行映射的方式产生aij。模型代码实现EncoderEncoder的结构非常简单,是一个简单的RNN单元,由于本项目中输入数据是已经编码好的词向量,因此不需要使用nn.Embedding() 对input进行编码。class Encoder(nn.Module): def init(self, embedding_dim, hidden_dim, num_layers=2, dropout=0.2): super().init() self.embedding_dim = embedding_dim #词向量维度,本项目中是200维 self.hidden_dim = hidden_dim #RNN隐层维度 self.num_layers = num_layers #RNN层数 self.dropout = dropout #dropout self.rnn = nn.GRU(embedding_dim, hidden_dim, num_layers=num_layers, dropout=dropout) self.dropout = nn.Dropout(dropout) #dropout层 def forward(self, input_seqs, input_lengths, hidden=None): # src = [sent len, batch size] embedded = self.dropout(input_seqs) # embedded = [sent len, batch size, emb dim] packed = torch.nn.utils.rnn.pack_padded_sequence(embedded, input_lengths) #将输入转换成torch中的pack格式,使得RNN输入的是真实长度的句子而非padding后的 #outputs, hidden = self.rnn(packed, hidden) outputs, hidden = self.rnn(packed) outputs, output_lengths = torch.nn.utils.rnn.pad_packed_sequence(outputs) # outputs, hidden = self.rnn(embedded, hidden) # outputs = [sent len, batch size, hid dim * n directions] # hidden = [n layers, batch size, hid dim] # outputs are always from the last layer return outputs, hiddenAttentation机制Attentation权重的计算方式主要有三种,本项目中使用concatenate的方式进行注意力权重的运算。代码实现如下:class Attention(nn.Module): def init(self, hidden_dim): super(Attention, self).init() self.hidden_dim = hidden_dim self.attn = nn.Linear(self.hidden_dim * 2, hidden_dim) self.v = nn.Parameter(torch.rand(hidden_dim)) self.v.data.normal_(mean=0, std=1. / np.sqrt(self.v.size(0))) def forward(self, hidden, encoder_outputs): # encoder_outputs:(seq_len, batch_size, hidden_size) # hidden:(num_layers * num_directions, batch_size, hidden_size) max_len = encoder_outputs.size(0) h = hidden[-1].repeat(max_len, 1, 1) # (seq_len, batch_size, hidden_size) attn_energies = self.score(h, encoder_outputs) # compute attention score return F.softmax(attn_energies, dim=1) # normalize with softmax def score(self, hidden, encoder_outputs): # (seq_len, batch_size, 2*hidden_size)-> (seq_len, batch_size, hidden_size) energy = torch.tanh(self.attn(torch.cat([hidden, encoder_outputs], 2))) energy = energy.permute(1, 2, 0) # (batch_size, hidden_size, seq_len) v = self.v.repeat(encoder_outputs.size(1), 1).unsqueeze(1) # (batch_size, 1, hidden_size) energy = torch.bmm(v, energy) # (batch_size, 1, seq_len) return energy.squeeze(1) # (batch_size, seq_len)DecoderDecoder同样是一个RNN网络,它的输入有三个,分别是句子初始值,hidden tensor 和Encoder的output tensor。在本项目中句子的初始值为‘“’代表的数字1。由于初始值tensor使用的是词袋编码,需要将词袋索引也映射到词向量维度,这样才能与其他tensor合并。完整的Decoder代码如下所示:class Decoder(nn.Module): def init(self, output_dim, embedding_dim, hidden_dim, num_layers=2, dropout=0.2): super().init() self.embedding_dim = embedding_dim ##编码维度 self.hid_dim = hidden_dim ##RNN隐层单元数 self.output_dim = output_dim ##词袋大小 self.num_layers = num_layers ##RNN层数 self.dropout = dropout self.embedding = nn.Embedding(output_dim, embedding_dim) self.attention = Attention(hidden_dim) self.rnn = nn.GRU(embedding_dim + hidden_dim, hidden_dim, num_layers=num_layers, dropout=dropout) self.out = nn.Linear(embedding_dim + hidden_dim * 2, output_dim) self.dropout = nn.Dropout(dropout) def forward(self, input, hidden, encoder_outputs): # input = [bsz] # hidden = [n layers * n directions, batch size, hid dim] # encoder_outputs = [sent len, batch size, hid dim * n directions] input = input.unsqueeze(0) # input = [1, bsz] embedded = self.dropout(self.embedding(input)) # embedded = [1, bsz, emb dim] attn_weight = self.attention(hidden, encoder_outputs) # (batch_size, seq_len) context = attn_weight.unsqueeze(1).bmm(encoder_outputs.transpose(0, 1)).transpose(0, 1) # (batch_size, 1, hidden_dim * n_directions) # (1, batch_size, hidden_dim * n_directions) emb_con = torch.cat((embedded, context), dim=2) # emb_con = [1, bsz, emb dim + hid dim] , hidden = self.rnn(emb_con, hidden) # outputs = [sent len, batch size, hid dim * n directions] # hidden = [n layers * n directions, batch size, hid dim] output = torch.cat((embedded.squeeze(0), hidden[-1], context.squeeze(0)), dim=1) output = F.log_softmax(self.out(output), 1) # outputs = [sent len, batch size, vocab_size] return output, hidden, attn_weight在此之上,定义一个完整的Seq2Seq类,将Encoder和Decoder结合起来。在该类中,有一个叫做teacher_forcing_ratio的参数,作用为在训练过程中强制使得网络模型的输出在一定概率下更改为ground truth,这样在反向传播时有利于模型的收敛。该类中有两个方法,分别在训练和预测时应用。Seq2Seq类名称为Net,代码如下所示:class Net(nn.Module): def init(self, encoder, decoder, device, teacher_forcing_ratio=0.5): super().init() self.encoder = encoder.to(device) self.decoder = decoder.to(device) self.device = device self.teacher_forcing_ratio = teacher_forcing_ratio def forward(self, src_seqs, src_lengths, trg_seqs): # src_seqs = [sent len, batch size] # trg_seqs = [sent len, batch size] batch_size = src_seqs.shape[1] max_len = trg_seqs.shape[0] trg_vocab_size = self.decoder.output_dim # tensor to store decoder outputs outputs = torch.zeros(max_len, batch_size, trg_vocab_size).to(self.device) # hidden used as the initial hidden state of the decoder # encoder_outputs used to compute context encoder_outputs, hidden = self.encoder(src_seqs, src_lengths) # first input to the decoder is the <sos> tokens output = trg_seqs[0, :] for t in range(1, max_len): # skip sos output, hidden, _ = self.decoder(output, hidden, encoder_outputs) outputs[t] = output teacher_force = random.random() < self.teacher_forcing_ratio output = (trg_seqs[t] if teacher_force else output.max(1)[1]) return outputs def predict(self, src_seqs, src_lengths, max_trg_len=30, start_ix=1): max_src_len = src_seqs.shape[0] batch_size = src_seqs.shape[1] trg_vocab_size = self.decoder.output_dim outputs = torch.zeros(max_trg_len, batch_size, trg_vocab_size).to(self.device) encoder_outputs, hidden = self.encoder(src_seqs, src_lengths) output = torch.LongTensor([start_ix] * batch_size).to(self.device) attn_weights = torch.zeros((max_trg_len, batch_size, max_src_len)) for t in range(1, max_trg_len): output, hidden, attn_weight = self.decoder(output, hidden, encoder_outputs) outputs[t] = output output = output.max(1)[1] #attn_weights[t] = attn_weight return outputs, attn_weights训练神经网络训练过程包括定义损失函数,优化器,数据处理,梯队下降等过程。由于网络中tensor型状为(sentence len, batch, embedding), 而加载的数据形状为(batch, sentence len, embedding),因此有些地方需要进行转置。定义网络,辅助类等代码如下所示:# 数据获取辅助类data = Dataset()en=Encoder(200,64) ##词向量维度200,rnn隐单元64de=Decoder(9133,200,64) ##词袋大小9133,词向量维度200,rnn隐单元64network = Net(en,de,device) ##定义Seq2Seq实例loss_fn = nn.CrossEntropyLoss() ##使用交叉熵损失函数optimizer = Adam(network.parameters()) ##使用Adam优化器model = Model(data)训练过程如下所示:lowest_loss = 10# 得到训练和测试的数据for epoch in range(args.EPOCHS): network.train() # 得到训练和测试的数据 x_train, y_train, x_test, y_test = data.next_batch(args.BATCH) # 读取数据; shape:(sen_len,batch,embedding) #x_train shape: (batch,sen_len,embed_dim) #y_train shape: (batch,sen_len) batch_len = y_train.shape[0] #input_lengths = [30 for i in range(batch_len)] ## batch内每个句子的长度 input_lengths = x_train[:,-1,0] input_lengths = input_lengths.tolist() #input_lengths = list(map(lambda x: int(x),input_lengths)) input_lengths = [int(x) for x in input_lengths] y_lengths = y_train[:,-1] y_lengths = y_lengths.tolist() x_train = x_train[:,:-1,:] ## 除去长度信息 x_train = torch.from_numpy(x_train) #shape:(batch,sen_len,embedding) x_train = x_train.float().to(device) y_train = y_train[:,:-1] ## 除去长度信息 y_train = torch.from_numpy(y_train) #shape:(batch,sen_len) y_train = torch.LongTensor(y_train) y_train = y_train.to(device) seq_pairs = sorted(zip(x_train.contiguous(), y_train.contiguous(),input_lengths), key=lambda x: x[2], reverse=True) #input_lengths = sorted(input_lengths, key=lambda x: input_lengths, reverse=True) x_train, y_train,input_lengths = zip(*seq_pairs) x_train = torch.stack(x_train,dim=0).permute(1,0,2).contiguous() y_train = torch.stack(y_train,dim=0).permute(1,0).contiguous() outputs = network(x_train,input_lengths,y_train) #, prediction = torch.max(outputs.data, 2) optimizer.zero_grad() outputs = outputs.float() # calculate the loss according to labels loss = loss_fn(outputs.view(-1, outputs.shape[2]), y_train.view(-1)) # backward transmit loss loss.backward() # adjust parameters using Adam optimizer.step() print(loss) # 若测试准确率高于当前最高准确率,则保存模型 if loss < lowest_loss: lowest_loss = loss model.save_model(network, MODEL_PATH, overwrite=True) print(“step %d, best lowest_loss %g” % (epoch, lowest_loss)) print(str(epoch) + “/” + str(args.EPOCHS))小结通过使用Seq2Seq + Attention模型,我们完成了使用神经网络对对联的任务。经过十余个周期的训练后,神经网络将会对出与上联字数相同的下联,但是,若要对出工整的对联,还需训练更多的周期,读者也可以尝试其他的方法来提高对仗的工整性。体验对对联Demo: https://www.flyai.com/couplets获取更多项目样例开源代码 请PC端访问:www.flyai.com ...

January 31, 2019 · 6 min · jiezi

将视觉深度学习模型应用于非视觉领域

摘要: 本文可以让你了解到,具有创造性的数据处理方法如何才能将深度学习视觉的功能应用于非视觉的领域。介绍近些年来,深度学习技术已经彻底改变了计算机视觉领域。由于迁移学习和各种各样的学习资源的出现,任何人都可以通过使用预训练的模型,将其应用到自己的工作当中,以此获得非常好的结果。随着深度学习越来越商业化,希望它的创造性能应用在不同的领域上。今天,计算机视觉领域中的深度学习在很大程度上解决了视觉对象的分类、目标检测和识别问题。在这些领域,深度神经网络(Deep Neural Network,DNN)的表现要胜过人类。即使数据不是可视化的,但你仍然可以利用这些视觉深度学习模型的力量,主要是卷积神经网络(Convolutional Neural Network,CNN)。要做到这一点,你必须将数据从非视觉领域迁移到视觉领域(图像)里,然后使用一个经过在图像和数据上训练过的模型。你将会感叹这种方法是多么的强大。在本文中,我将介绍3个案例,这是关于公司如何进行创造性地深度学习应用,将视觉深度学习模型应用于非视觉领域。在每一个案例中,都会对一个非计算机视觉的问题进行转换和描述,以便更好地利用适合图像分类的深度学习模型的能力。案例1:石油工业在石油工业中,游梁式抽油机(Beam pumps)常常用于从地下开采石油和天然气。它们由连接在移动梁上的发动机来提供动力。移动梁将发动机的旋转运动传递给抽油杆的垂直往复运动,抽油杆作为一个动力泵,再将油输送到地面上。游梁式抽油机作为一种复杂的机械系统,很容易发生故障。为了方便诊断排查,在抽油机上安装了一个测功机,用于测量杆上的负载。测量后,绘制出一张测功机的动力泵卡片,图上显示了发动机在旋转循环过程中每个部分的负载。当游梁式抽油机出故障的时候,测功机卡片上的形状会改变。这个时候,通常会邀请专业的技术人员过来检查卡片,并根据抽油机出现故障的部分来判断需要采取什么措施和方法来进行维修。这个过程不仅非常耗时,而且还需要非常深入的专业知识才能有效地解决问题。另一方面,这个过程看起来有可能是可以自动化完成的,这就是为什么尝试过典型的机器学习系统而并没有取得很好效果的原因,准确率大约为60%。将深度学习应用到这个领域的一个公司是Baker Hughes。在这种情况下,测功机卡片被转变为图像,然后作为输入到Imagenet的预训练模型中。这个结果非常令人印象深刻,精度从60%上升到93%,只需采用预训练的模型并用新的数据对其进行一下微调。经过模型训练的进一步优化,其精度达到了97%。上图是Baker Hughes部署的系统示例。在左侧,你可以看到输入图像,在右侧是故障模式的实时分类。它不仅击败了以前的基于机器学习的传统方法,而且公司不再需要抽油机的技术人员花费大量的时间来排查故障,他们过来就可以立即进行机械故障修复,从而大大提高了效率。案例2:在线欺诈检测计算机用户在使用计算机的时候有独特的模式和习惯。当你在浏览一个网站或在键盘上键入电子邮件内容的时候,你使用鼠标的习惯是独一无二的。在这种特殊的情况下,Splunk解决了一个问题,即通过使用计算机鼠标的方式来对用户进行分类。如果你的系统能够根据鼠标使用的方式来识别用户,那么这种方法可以用于欺诈检测。假设这样一个情况:某些人在窃取了别人的用户名和登录密码之后在网上消费。他们使用电脑鼠标的方式是独一无二的,系统将很容易检测到这种异常操作,并进一步防止发生欺诈交易,同时也会通知真正的账户所有者。使用特殊的Javascript代码,可以收集所有鼠标的行为活动。软件每5-10毫秒记录一次鼠标的行为。因此,每个用户在每个网页的行为数据可以是5000–10000个数据点。数据代表了两个挑战:第一个挑战是对于每个用户来说都是海量的数据,第二个挑战是每个用户的数据集都将包含不同多个数据点,这不太方便,因为,通常来说,不同长度的序列需要更复杂的深度学习架构。这个方案是将每个用户在每个网页上的鼠标活动转换为一个单个图像。在每幅图像中,鼠标的移动是一条由不同的颜色来表示鼠标移动速度的线来表示的,而点击左键和点击右键则是由绿色和红色的圆圈来表示的。这种处理初始数据的方法解决了上述的两个问题:首先,所有图像的大小都相同;其次,现在基于图像的深度学习模型可以用于此类数据了。Splunk使用TensorFlow和Keras为用户分类创建了一个深度学习的系统。他们做了2个实验:1. 当访问相类似的页面时,金融服务网站的用户组分类:正常客户与非客户用户。一个由2000张图片组成的相对较小的训练数据集。在对基于VGG16网络的一个已修改结构进行了2分钟的训练之后,系统能够以80%以上的准确度识别出这两个类;2. 用户的个人分类。该任务是为一个给定的用户预测出是真实用户还是一个模拟者。提供了一个只有360张图片的非常小的训练数据集。基于VGG16网络,但是由于考虑到小数据集和减少过度拟合(有可能放弃和批量标准化)而进行了修改。经过了3分钟的训练,准确率达到了78%左右,考虑到任务具有的挑战性,那么这一点很令人印象深刻;要了解更多相关内容,请参阅描述了系统和实验过程的完整内容。案例3:鲸鱼的声音检测在这个例子中,谷歌使用卷积神经网络来分析录音并检测出其中的座头鲸。这对于科学研究来说很有帮助,例如跟踪单个鲸鱼的活动、叫声的特性、鲸鱼的数量等等。有趣不是目的,而是如何通过需要利用图像的卷积神经网络来处理数据。将音频数据转换成图像的方法是通过使用光谱图来实现的。光谱图是音频数据基于频率特征的视觉来表示的。在将音频数据转换成光谱图之后,谷歌的研究人员使用了ResNet-50网络结构来训练这个模型。他们能够达到以下的性能表现:90%的准确度:90%的音频剪辑被归类为鲸鱼叫声的分类;90%的敏感度:如果给一个鲸鱼叫声的录音,那么就会有90%的机会被打上敏感度的标签;让我们把焦点从鲸鱼叫声转移到处理音频数据时可以做些什么。当你创建光谱图的时候,可以选择要使用的频率,这取决于你所拥有的音频数据的类型。你将需要给人类的说话声、座头鲸的叫声、或工业设备的录音设置不同的频率,因为在所有的这些情况下,最重要的信息是包含在了不同的频段里。你不得不使用自己的专业领域知识来选择相关的参数。例如,如果你使用的是人类声音数据,那么你的第一选择应该是梅尔频率倒谱图。目前有一些有比较好的软件包可用于音频。Librosa是一个免费的音频分析Python库,可以使用CPU生成光谱图。如果你在TensorFlow中开发并且想在GPU上做光谱计算,那也是支持的。请参考一下这篇文章,了解更多的关于谷歌如何处理座头鲸数据的内容。综上所述,本文所阐述的一般方法都遵循了两个步骤。首先,找到一种将数据转换成图像的方法;其次,使用一个经过预训练的卷积网络或者从头开始进行训练。第一步要比第二步更难,这是需要你必须有创造力的地方,要考虑到如果你的数据可以转换成图像。我希望提供的实例对解决你的问题有所帮助。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 30, 2019 · 1 min · jiezi

人物志 | MIT 科技创新“远见者”:美团 NLP 负责人王仲远

2019 年 1 月 21 日,《麻省理工科技评论》发布了 2018 年“35 岁以下科技创新 35 人”(35 Innovators Under 35)中国榜单,美团点评AI平台部 NLP 中心负责人、点评搜索智能中心负责人王仲远获评为“远见者”。Innovators Under 35 是《麻省理工科技评论》杂志从 1999 年开始的年度评选,针对新兴科技产业的青年从业者,肯定他们的创新工作。历史上的获奖者包括 Google 创始人 Larry Page 和 Sergey Brin,Linux 创始人 Linus Torvalds,Facebook 创始人马克·扎克伯格(Mark Zuckberg),网景浏览器创始人 Marc Andreessen,Apple 设计负责人 Jonathan Ive 等杰出人士。趁此机会,美团技术学院采访了王仲远博士,本文内容根据采访内容整理而成。大学王仲远没有想到,他高考时填报的第一志愿是中国人民大学国际经济与贸易专业,最后却被调剂到了中国人民大学的计算机系。更没想到的是,他从此爱上了这个专业,并且在计算机这个行业越走越深。幸运的是,王仲远就读的人民大学虽然以文科著称,却是中国数据库的学术重镇,萨师煊、王珊、杜小勇和孟小峰等几代人都是数据库领域的知名学者。刚开始的时候,王仲远也很困惑学校为什么总是教数据结构、操作系统、编译原理、计算机组成这种基础性的知识,好像都不是找工作所需要的技能。孟小峰教授却告诉他,在学校里把基本功打扎实最重要,如果有了扎实的基本功,社会上培训班教的那些“短平快”的技术,其实是很容易学习的。大二结束的暑假,王仲远找到孟小峰教授主动请缨,开始进入孟老师的 WAMDM (网络与移动数据管理)实验室学习,做了很多数据相关的项目,包括国内首款 Native XML 数据库 OrientX 的系统测试,以及 Deep Web 数据集成项目的研究。他发现孟老师的教导完全正确,有了基础课的底子,对很多工作都有着完全不一样的理解,做实际项目时上手很快。本科期间,王仲远与人合作的论文《Deep Web 数据集成中的实体识别方法》被中国数据库学术会议 NDBC 2006 录用,并发表在《计算机研究与发展(增刊)》上。这小小的一个进展,却意外开启了王仲远的研究之路。2007 年他获得了国际顶级学术会议 SIGMOD 2007 Undergraduate Scholarship 奖(当年全球只有 7 人获奖)。这更坚定了他踏上学术研究道路的决心。微软亚洲研究院硕士毕业时,王仲远很冒险地拒绝了百度、腾讯和 IBM 等众多知名公司研究机构的邀请,选择坚持等待微软亚洲研究院的offer。“其实当时我也很迷茫,在宿舍里望着窗外的枝头,希望能看到喜鹊经过。” 而王仲远不知道的是,他在当时微软亚洲研究院所有候选人中面试结果排名第一。他未来的老板王海勋和田江森主动找到研究院院长说,“这个小孩真不错,如果我们再不发 offer,就对不起人家了。”当年 12 月份的寒冬,王仲远终于成为研究院那批候选人中第一个拿到 offer 的人。王仲远说自己很幸运,微软亚洲研究院具备很多先天优势,在刚刚工作时就可以接触到很多世界级的学者,了解各领域前沿研究已经做到什么程度,无需摸着石头过河。2010 年 10 月,微软创始人、当时的全球首富比尔·盖茨来研究院访问,正式入职两个多月的王仲远获得做现场演示的机会。“可以想象,我当时是多么的激动。”王仲远所在的团队那时已经开始做一些知识图谱领域的探索和研究,虽然业界还没有这个概念。演示很成功,盖茨的反馈非常正面,给王仲远很大的激励,更坚定了他在知识图谱探索的道路上苦心孤诣地前行。这张与比尔·盖茨合影的照片,至今他还保留着。王仲远在微软亚洲研究院6年多,从校招生一直做到主管研究员,负责了微软研究院知识图谱项目和对话机器人项目。他一直专注于自然语言处理、知识图谱及其在文本理解方面的研究,取得了不少成绩,在国际顶级学术会议如 VLDB、ICDE、IJCAI、CIKM 等发表论文 30 余篇,并获得 ICDE 2015 最佳论文奖。谈到做研究的经验,王仲远总结说,很多时候我们觉得某件事情比较高深,只不过是不了解而已。做学术研究跟创业一样,只有自己真正扎进去才会发现其中的奥秘。同时,做研究需要长期有耐心,这刚好和现在美团所倡导的价值观相符。因为在这个过程中,你会受到非常多的质疑,也会面临多方面的挑战,包括来自你的同事、你的老板、还有学术界中其他流派的挑战。同时,还有短期的压力和长期的压力,也有项目无法落地的压力。但只要对这件事本身真的感兴趣,不管是做技术还是做研究,都可以做的很好。在王仲远看来,做研究需要有一颗强大的内心,按现在美团的话说,是炼心志。一方面他经常虚心地向前辈们请教,另一方面就是当别人质疑的时候,坚持自己的理想和信念。在他看来,做研究,过程往往比结果更重要,做正确的事情,好结果自然会来。“我从来没有给自己定一个目标,比如说要发几十篇顶级会议的学术论文。而是告诉自己,要踏踏实实地把这个研究项目做好,实实在在解决这个技术所面临的一些挑战性问题,当这些突破和研究的成果不断出现的时候,发表论文就是一个自然而然的事情。”现在,王仲远也经常跟美团 NLP 中心的同学讲,做事情要首先关注问题本身,要进行深度的思考,注重解决问题的逻辑和体系,而不是一上来就简单粗暴地冲着结果去。因为往往是人们越想得到结果,就越得不到结果。反而是专注解决问题本身,好结果就自然获得了。Facebook2016 年,王仲远在考虑自己下一步职业规划的时候,更多的是思考如何将自己的一身所学付诸实践,而不仅仅只停留在研究层面。“如何将技术转化为更为实际的生产力,更加直接地影响几十亿人的生活”,这是他再次出发的初心。这一次,王仲远依然拿到了很多顶级机构发出的 offer。他最终选择了 Facebook。因为相比于微软,Facebook 是一家纯粹的互联网企业,能够更加直接地面向消费者和用户。而且,在王仲远的眼中,扎克伯格是一个优秀的创始人。“我选择公司非常看重创始人的素质,他是不是一个有理想、有抱负、有信念的人。因为只有这样的创始人才能有战略性的思考,才能不被短期资本市场所影响,才能顶住财报的压力、舆论的压力,才能帮助企业走的更远。”在 Facebook,王仲远主要负责公司的产品级 NLP Service,要在用户每天发布的几十亿条帖子(Post)中,完成语义分析、查询以及搜索等相关的工作,从非常庞大且复杂的信息流中,找到一个用户想要看到的结果。比如在 Facebook 用户搜索 Trump 时,系统就知道用户想要找美国总统特朗普相关的信息。不过,在特朗普没有当上美国总统时,更多返回的结果其实是纽约的地标建筑特朗普大厦。王仲远说:“这是非常有意思的一件事,用户的各种查询意图,其实会随着时间而变化,我们做的事情就是在有限的关键词中解读出非常丰富的信号,然后用于各种搜索的召回、排序以及展示。今天,美团大脑以及点评搜索的深度查询理解服务也在做类似的事情,只不过我们处理的信息变成了几十亿条餐饮娱乐的评论以及数百万的活跃商户信息。”在 Facebook 工作期间,他所负责的一个项目是做实体链接,就是要把查询(Query)和知识图谱进行打通,这也是 NLP 领域一个非常重要的方向。短短半年的时间,效果就提升了 80% 左右,成为 Facebook 内部最重要同时也是世界上最先进的产品级实体链接服务。Facebook 的搜索、推荐、广告、智能助理等许多系统中,都在使用他负责的这些技术。美团“我们中国的移动互联网现在真的是非常发达,一天到晚不带钱包、信用卡,生活毫无问题,方便快捷。相比之下,美国就是一个发达的大农村。在国内叫个美团外卖,半小时就能送到家门口,在美国这简直是无法想象的。” 2018 年,因为家庭方面的考虑,王仲远选择回国发展。他收到了多家知名公司的橄榄枝,百度、腾讯和阿里巴巴都给出非常丰厚的待遇。但是他的考虑是,此前已经在微软亚洲研究院、Facebook 工作过,再去选择一家非常成熟的大公司,并不会发生太大的改变。他想接受新的挑战,承担更重要的角色,更希望选择一家能够发挥出自己更大优势的公司。滴滴、快手、今日头条等很多互联网新贵,当时也给王仲远发出了邀请,但他最终选择了美团。为什么?王仲远说,他最看好美团,相信美团是一家能够持续几十年乃至更久生命力的公司。阿里巴巴从解决“衣食住行”中的“衣”开始起家,电子商务也成就了阿里巴巴。那么在“食、住、行”等这些生活服务领域呢?王仲远相信,一样会成就新的互联网巨头。而且民以食为天,美团外卖已经占据绝对领先的市场份额,美团酒店单日入住间夜不断在刷新行业的新纪录,美团出行也完成了战略布局。美团最新的战略是“Food + Platform”,王仲远对此非常认可。他相信,十年后,一定会有新的纯线上App出现,大家那时很可能早就不玩“抖音”了。还会有更多新鲜好玩的游戏,也不会再玩“王者荣耀”了。这种纯线上的信息和娱乐服务,变化是非常快的,所谓“江山代有才人出”。“但是无论怎么变,大家总是还要吃饭的。”即使将来有一天,技术真的可以让我们吃饭的方式完全不一样,但是人类也绝对不会放弃对美食的追求,因为这本身也是一种乐趣。这也意味着,美团很有可能成长为一家长期有耐心、不断积累、不断发展的公司,“Food + Platform”也会是一项非常长期的事业。王仲远的另外一个思考就是,AI 技术想真正能够落地,需要算力,需要数据,需要算法模型,更需要丰富的应用场景。美团的应用场景丰富程度,显然远超滴滴、快手、今日头条等互联网同行。“在这样的情况下,美团对我来说,可能就是不二的选择了。”还有一个重要因素是,王仲远非常认可美团创始人王兴,“我还是很崇拜兴哥的,他是非常有理想、有信念、有战略思考的一个人。”王仲远坦言,最终选择加入美团,也是非常认同美团倡导的“以客户为中心”、“追求卓越”、“长期有耐心”这些价值观,他相信可以在美团中发挥自己的才华,而美团也提供了一个广阔的舞台,可以让他尽情地施展。从 0 到 1 组建新团队,最看重成员的价值观刚到美团,王仲远受命组建美团 AI 平台部的 NLP 中心。他对团队成员的要求是:知行合一,希望大家都是带着自己梦想加入这个团队,踏踏实实地把事情做出来。王仲远说:“从 0 到 1 组建一个新的团队,挑战还是非常大的。我们的标准非常高,即使招聘速度再慢,都要保证团队成员的质量。”因为招聘要求很高,所以王仲远需要花很多时间去吸引那些认可美团价值观的候选人。他是怀抱将AI技术在各种场景中落地的梦想加入美团,他相信肯定有很多跟自己一样有梦想、有信念的候选人。他也希望找到这样一群志同道合的人,共同前行。今天,美团 NLP 中心团队已经初步成型,汇集了很多优秀的 AI 专家和工程师。从“美团大脑”到搜索系统的智能化升级很快王仲远又开始负责大众点评搜索智能中心。王仲远说:“我非常感谢公司管理层对我的信任,能让我同时负责两个团队,一个 AI 平台团队,一个业务平台团队。这使得我能够更好地规划和掌控AI技术的落地,让 AI 技术更好更快地发挥价值,帮助业务平台进行智能化升级。”2018 年 5 月,他开始领导团队构建美团大规模餐饮娱乐知识图谱的平台——美团大脑。这个“大脑”充分挖掘、关联各个场景数据,使用 AI 算法让机器“阅读”用户针对商户的公开评论,理解用户在菜品、价格、服务、环境等方面的喜好,构建人、店、商品、场景之间的知识关联,从而形成一个“知识大脑”。在王仲远眼中,美团大脑更像一个AI的基础设施,目前这个 AI 平台已经开始逐步服务于美团的搜索、SaaS 收银、金融、外卖、智能客服等众多应用场景。在这些场景中,既有 ToC 的业务,也有 ToB 的业务。同时管理两个团队,经常往返于北京上海之间,对王仲远而言,虽然辛苦,但效果也很显著。在 NLP 中心以及大众点评搜索智能中心两个团队的紧密合作下,短短半年时间,点评搜索核心 KPI 在高位基础上仍然大幅提升,是过去一年半涨幅的六倍之多,提前半年完成全年目标。王仲远眼中的微软、Facebook 和美团一个在学术圈深耕了六、七年的研究型人才,进入企业做项目落地。拥有两家全球顶尖科技企业的从业背景,但回国后却放弃优厚的待遇,选择一家互联网公司再次出发。王仲远的每一次选择,都显得有些与众不同。但是在他身上,我们没有看到任何”莽撞“的成分。每一次选择,他都经过深思熟虑,而且是慎之又慎。在王仲远的眼中,微软亚洲研究院是中国互联网行业学术研究方向的领头羊,对他的培养和成长,都有很大的帮助。时至今日,微软亚洲研究院对他的影响,仍是不可磨灭的。不过,微软也面临着时代的挑战,虽然这么多年一直在尝试突破,但是它仍然更像一家传统的软件公司。而 Facebook,是一家非常顶尖的互联网公司,它也是很多国内的互联网公司学习的榜样。Facebook 有一个口号是“快速行动,打破传统(Move Fast and Break Things)”,可以看出,他们对“快”的追求。Facebook 还有很多像“Go Big or Go Home”这一类的内部口号,这跟美团的技术团队“要么牛 X,要么滚蛋”的说法异曲同工。王仲远认为,Facebook 的进化速度要比微软快很多。而美团是一家比 Facebook 节奏更快的互联网公司,当然这代表了中国速度,也代表了中国互联网的发展速度。王仲远说:“很多的事情,可能在微软亚洲研究院我们需要要用一年的时间来做,在 Facebook 可能会用半年。但是在美团,我们可能只有两个月到三个月的时间。”美团的高速成长,给王仲远的团队带来很大的挑战。他们每天都要面临各种的持续迭代,要做很多快速的技术演化和突破。美团技术团队是在为生活服务各行业构建信息基础设施,实现需求侧和供给侧的数字化,任重而道远。未来的路还很长,王仲远和他的 AI 团队,还在路上。对话王仲远:关于职业发展、知识图谱以及 AI 的未来秉持信念,不忘初心,不断拥抱变化,才能真正把工作做好Q:你觉得偏研究型的人才,怎么在企业中发挥出自己的价值?王仲远:任何科技的发展,都需要研究型人才的推动。但是研究型的人才分几种,有的是做纯理论研究的人才,可能高校是他们最好的选择。这些人愿意几十年如一日的深耕一个领域。比如深度学习先驱 Geoffrey Hinton 教授,长期从事神经网络领域的研究,不管是神经网络发展的高潮还是低谷,他都能坚持做下去。还有一些人才,他们更希望把自己学到的各种研究模型、研究成果,能够实实在在地应用在真正的科技产品里面,然后去影响几亿人甚至几十亿人的生活。那么这一类研究型人才,他们更看重应用型的研究,公司可能会更需要他们。我们整个 NLP 中心也在做一个平衡,80% 的同学会偏应用型研究,也会有 20% 同学会做偏理论的研究,也会鼓励同学们根据兴趣做一些前沿的技术研究。我们希望能够保持较强的科技创新能力,并具备长期的核心竞争力。Q:外企和海归背景的人,怎么在本土企业中证明自己的价值?王仲远:不建议给自己贴“标签”。文化上肯定会有一些冲突和差异。但是能不能适应,其实很大程度上取决于个人,取决于这些人能不能拥抱变化。我必须承认,国内互联网的变化或者演化速度,远远超出原来我待过的两家外企,我也必须要适应和拥抱这种变化。如果我们能够秉持自己的信念,不忘自己的初心,同时能不断地提炼自己,升级自己,愿意拥抱这些变化,我相信在新团队也可以做的更好。而且我也观察过,真正的最顶尖的人、最聪明的那些人,他们不管做什么行业,不管做什么事情,不管身处什么样的环境,都能够把事情做的非常好,都能够取得非常好的成就。在我看来,“人”本身的因素要比“外企背景”这种因素重要很多。我深信真正聪明的人的适应力也都是非常强的。而且加入美团后,我们发现很多很厉害的人,即使把他们放在一个完全不懂,或者不熟悉的项目中,他们一样可以做的很优秀。比如美团内部某个业务部门的负责人,曾经做了 15 年的互联网音乐。我相信拥抱变化的人,都不会做的很差。至于如何证明自己?其实刚刚我也提到过,不要刻意。越刻意地想去证明自己,往往越证明不了自己。越想刻意拿到结果,往往越拿不到结果。我会给身边的同学提这样的建议。关注事情本身,关注怎么解决用户的痛点,关注怎么解决技术的难点,关注怎么解决业务的需求。如果把这些事情做好了,既能拿到结果,最终也能证明自己的价值。知识图谱技术的春天来临,是因为大数据在推动Q:像知识图谱相关的技术已经存在了很多年,为什么迟迟没有进入大众的视野呢?王仲远:技术的发展,永远都是起起伏伏,处于一个螺旋上升的阶段。知识图谱并不是新技术。早在上个世纪 80 年代,就有很多知识库系统的研究了。包括 1984 年开始的 Cyc 就是一个知识图谱项目。其实比 Cyc 更早之前,还有很多医疗诊断的专家系统。但是受限于当时的计算能力、人们的认知、数据量,很多都是通过人工编写规则,或者去找专家建设行业知识库,这种方式不仅效率低下,而且人的思考也具备局限性。通过领域专家去构建的知识库,通常就是几十万的量级,显然不能够满足需求。2000 年以后,随着互联网的高速发展,数据也越发的丰富,促进了知识图谱技术的蓬勃发展。我们这些做知识库的研究者开始有了新的思路,不再以专家系统为驱动,而是变成依靠数据来驱动产生知识。从观念层面发生的根本性改变后,知识图谱马上展示出自身巨大的价值。特别是 2012 年,谷歌发布了 Google Knowledge Graph,人们又重新认识了知识图谱技术。此外,知识图谱之所以影响力有限,还有一个很重要的原因就是,拥有这种规模数据的只有少数几家大公司。它们暂时也没有办法去开放,因为涉及到用户隐私问题、数据安全问题,同时还涉及到核心竞争力。但我相信,所有从事AI行业相关的人都清楚地知道知识图谱的价值和意义。其实在这些互联网巨头内部,不管是微软、Facebook,包括谷歌和百度,它们对知识图谱技术都非常重视。Q:你觉得像知识图谱这些技术的落地,目前面临的最大挑战是什么?王仲远:可能很多人不太清楚,十年前或则更久之前,在学术研究界就已经存在非常多的且成熟的知识图谱相关的技术,包括知识的提取、知识的发现、实体识别、实体链接等等。但是,学校实验室或者研究所缺少海量的研究数据,科研人员基于的数据量基本处在几十万或者百万的量级,当这些技术遇到亿级甚至百亿量级的数据时,很多技术走不通。我们目前面临的最大挑战就是,即使是一个非常简单的,或者已经被学术界认定非常成熟的技术,在去解决百亿、千亿量级知识图谱应用问题时,基本都会失效。因此,应该如何重新设计算法,应该如何重新设计新的工程架构,是我们需要解决的核心问题。此外,深度学习跟知识图谱进行结合,也是一个非常重要的研究方向。Q:你觉得对企业而言,如何才能做好 NLP?王仲远:NLP 是人工智能所有方向中一个还需要突破的领域。像语音识别和图像识别,通过深度学习已经可以得到非常好的结果。但人类和动物一个非常重要的区别就是,人类拥有非常完备的理解、推理、思考能力,这些能力是 NLP 需要解决的,但是挑战性也很高。目前在 NLP 领域,我们已经做了很多的突破,也有一些很好的落地场景,比如智能客服,语音助手,还有搜索、推荐、广告这些应用场景。但是在特定的领域,比如餐饮、酒店预订、出行等领域,还有很大的提升空间。在我看来,企业想要做好 NLP,首先需要打通基础数据。像美团大脑目前包含了 23 类概念、18 亿实体、600 亿三元组,这个知识关联数量级已经达到了世界级的规模。只有数据被打通,才能发挥出更大的价值。其次,需要构建扎实的技术底层,打造一个平台,使得不同的业务线都能更方便、快捷地去使用 NLP 的这些技术,当新技术出现时,也可以快速进行升级和迭代。总的来说,一个是打通数据,一个构建技术底层。当然还有人才,人才也是实现以上两者的根本因素。当然,既能够安心做研究,又能够落地的核心人才也是最稀缺的,我们美团 NLP 中心对于优秀人才的渴求,也是永无止境的,我们随时都欢迎有理想、有信念的同学加入,一起创造未来。相信 AI 的未来:道路是曲折的,前景是光明的Q:怎么看待 AI 未来的发展?王仲远:我应该属于理性的乐观派。在我看来,不管是深度学习还是知识图谱,技术发展历程永远会有高潮,也会有低谷。这两年因为资本的涌入,因为媒体的宣传,有时甚至过度炒作,使得 AI 进入了大众的视野。这会带来一个好处,就是人们对 AI 有了更加广泛的关注。但是也带来很多的风险,比如很多不是特别成熟的 AI 技术也被“催熟”了,如果这些 AI 产品不能够很好地解决人们实际需求的时候,就会被大家所质疑,比如像前几年很火爆的 VR、AR 等等。还有无人驾驶技术,距离真正落地,还存在很多亟待解决的问题。我预计未来一两年,随着资本的收缩,AI 可能会陷入冷静期甚至是低谷期。但这个时间应该不会持续太久,因为核心技术一直都在研究和突破。随着 5G 时代的到来,随着 AR、VR 技术更加成熟,随着NLP技术更加成熟,随着无人驾驶技术更加成熟,未来 AI 也会带来产业新的热潮。20年 ToC,20 年 ToB。在互联网高速发展的前 20 年,我们主要解决了消费者的需求。但在很多传统产业,供给侧的数字化,AI 对它们的影响还很有限,这也是我们未来的机会。Q:对从事AI相关工作的同学,有什么建议吗?王仲远:我觉得大家还是要多关注核心技术,以及核心技术跟业务场景的结合。一个属于“基本功”,另一个是思考技术对业务的价值。因为技术永远是日新月异,也会不断地更新迭代。特别是做算法研究的同学,相对比较辛苦,要持续的进行学习和提升,如果有一段时间不学习,很可能会被淘汰。在我们的面试过程中也能够感觉出来。如果面试算法工程师的同学,还是用传统模型而不是深度学习的话,就会面临很大的挑战。此外,如果只关注模型本身,而不去思考如何跟业务进行结合,在工作中也很难证明自己。如果是在校的大学生,建议大家不要上来就学习 Java、Python 这些编程语言。应该先对计算机的各种原理、基础知识(概率论、数学分析)等掌握清楚,再去学习很多技术时,就会有完全不一样的理解。我们未来的一切,都应该建立在一个扎实的基本功之上。影响王仲远的书、人、事Q:你觉得对你影响最大的一件事是什么?王仲远:很难说具体的哪件事影响最大。刚刚也提到了,这么多年的职业生涯,我做了很多次、可能看起来比较重大的选择,但是我很难讲,哪一件事会彻底的改变自己的职业生涯。相对来说,影响比较大的事情有很多,像大学时获得“SIGMOD 2007 Undergraduate Award”奖项,让我坚定地选择了研究这条路。后来在这条道路上,也受到很多老板对我的鼓励。还有刚工作两个月,就得到跟比尔盖茨做汇报的机会,得到他的正向反馈。还有在顶级学术会议发表论文,以及现在做的美团大脑项目,包括刚刚获得的《麻省理工科技评论》这个荣誉等等,我想这些事对都产生了非常大的影响。但对于具体的一件事而言,我觉得,更多的是在每一次做人生选择时所做的坚持,以及坚持之后通过努力所带来的一些认可。这也是鼓励我在各种质疑中、在各种压力中,持续前进的一个非常重要的动力,使我能够长期地坚持下去。Q:你觉得,这么多年对你影响最大的一个人是谁?王仲远:对我影响很大的人其实很多。比如我的第一个导师孟小峰教授,他带领我进入了研究的大门。我的第一任老板王海勋博士,他也是我在Facebook的老板,给了我很多次机会。还有后来研究院的常务副院长马维英(现今日头条人工智能实验室主任),从他身上,我学到了很多管理的能力。加入美团后,兴哥和老王(美团联合创始人王慧文)对我的影响也非常大,每一次听他们的分享,都让我受益良多,比如兴哥对战略的思考能力和大局观,老王对市场敏锐的把握、对产品的认知等等,都让我学到非常多新的知识。我再次感觉到自己在快速的成长之中。他们对我的帮助也都非常大。Q:如果让你推荐一本书,你会推荐哪本?王仲远:推荐微软 CEO 萨提亚·纳德拉首部作品《刷新:重新发现商业与未来》。我觉得萨提亚能够带领微软这样的巨型科技公司成功转型,再次成为市值最高的公司,非常令人钦佩。尤其是当年我也曾在微软工作过,感受过微软所面临的那种困境与挣扎,更能体会到萨提亚的管理智慧。在书中,萨提亚反复提到“同理心”,这是我所非常认同的,它也深刻地影响我的思考、沟通和行为方式。相关阅读王仲远博士获评《麻省理工科技评论》“35 岁以下科技创新 35 人”中的“远见者”,麻省理工科技评论给出的获奖理由为:“在知识图谱和自然语言处理领域解决多项挑战性问题,其工作涉及搜索引擎、广告推荐、知识挖掘、关系推理、智能助理等多个领域。获奖人(王仲远)在微软负责包括微软概念知识图谱、企业知识图谱等多个知识图谱和 NLP 相关项目,提出的概念化模型能让计算机像人类一样对文本进行理解;在 Facebook 领导团队构建了世界上最大的产品级社交网络知识图谱实体链接服务。在美团仅用半年就领导团队构建出世界上最大的餐饮娱乐知识图谱“美团大脑”。获奖人的开发应用于餐饮、出行、休闲娱乐、旅游、金融等各个场景,为数亿人提供了更便捷、更智能的服务。”受访者简介王仲远博士,美团点评高级研究员、高级总监,美团 AI 平台部 NLP 中心负责人、大众点评搜索智能中心负责人。加入美团点评前,担任美国 Facebook 公司 Research Scientist,负责 Facebook 产品级 NLP Service。在 Facebook 之前,担任微软亚洲研究院的主管研究员,负责微软研究院知识图谱项目和对话机器人项目。多年来专注于自然语言处理、知识图谱及其在文本理解方面的研究,在国际顶级学术会议如 VLDB、ICDE、IJCAI、CIKM 等发表论文 30 余篇,获得 ICDE 2015 最佳论文奖,并是 ACL 2016 Tutorial “Understanding Short Texts”的主讲人,出版学术专著 3 部,获得美国专利 5 项。在 NLP 和 KG 研究领域及实际产品系统中均有丰富经验,研究领域包括自然语言处理、知识图谱、深度学习、数据挖掘等。参考文献《麻省理工科技评论》年度中国科技青年英雄榜发布!35位中国入选者涵盖全球最前沿科学与技术计算机系本科生王仲远荣获 SIGMOD07 Undergraduate Scholarship ...

January 28, 2019 · 2 min · jiezi

TensorFlow 2.0深度强化学习指南

摘要: 用深度强化学习来展示TensorFlow 2.0的强大特性!在本教程中,我将通过实施Advantage Actor-Critic(演员-评论家,A2C)代理来解决经典的CartPole-v0环境,通过深度强化学习(DRL)展示即将推出的TensorFlow2.0特性。虽然我们的目标是展示TensorFlow2.0,但我将尽最大努力让DRL的讲解更加平易近人,包括对该领域的简要概述。事实上,由于2.0版本的焦点是让开发人员的生活变得更轻松,所以我认为现在是使用TensorFlow进入DRL的好时机,本文用到的例子的源代码不到150行!代码可以在这里或者这里获取。建立由于TensorFlow2.0仍处于试验阶段,我建议将其安装在独立的虚拟环境中。我个人比较喜欢Anaconda,所以我将用它来演示安装过程:> conda create -n tf2 python=3.6> source activate tf2> pip install tf-nightly-2.0-preview # tf-nightly-gpu-2.0-preview for GPU version让我们快速验证一切是否按能够正常工作:>>> import tensorflow as tf>>> print(tf.version)1.13.0-dev20190117>>> print(tf.executing_eagerly())True不要担心1.13.x版本,这只是意味着它是早期预览。这里要注意的是我们默认处于eager模式!>>> print(tf.reduce_sum([1, 2, 3, 4, 5]))tf.Tensor(15, shape=(), dtype=int32)如果你还不熟悉eager模式,那么实质上意味着计算是在运行时被执行的,而不是通过预编译的图(曲线图)来执行。你可以在TensorFlow文档中找到一个很好的概述。深度强化学习一般而言,强化学习是解决连续决策问题的高级框架。RL通过基于某些agent进行导航观察环境,并且获得奖励。大多数RL算法通过最大化代理在一轮游戏期间收集的奖励总和来工作。基于RL的算法的输出通常是policy(策略)-将状态映射到函数有效的策略中,有效的策略可以像硬编码的无操作动作一样简单。在某些状态下,随机策略表示为行动的条件概率分布。演员,评论家方法(Actor-Critic Methods)RL算法通常基于它们优化的目标函数进行分组。Value-based诸如DQN之类的方法通过减少预期的状态-动作值的误差来工作。策略梯度(Policy Gradients)方法通过调整其参数直接优化策略本身,通常通过梯度下降完成的。完全计算梯度通常是难以处理的,因此通常要通过蒙特卡罗方法估算它们。最流行的方法是两者的混合:actor-critic方法,其中代理策略通过策略梯度进行优化,而基于值的方法用作预期值估计的引导。深度演员-批评方法虽然很多基础的RL理论是在表格案例中开发的,但现代RL几乎完全是用函数逼近器完成的,例如人工神经网络。具体而言,如果策略和值函数用深度神经网络近似,则RL算法被认为是“深度”。异步优势演员-评论家(actor-critical)多年来,为了提高学习过程的样本效率和稳定性,技术发明者已经进行了一些改进。首先,梯度加权回报:折现的未来奖励,这在一定程度上缓解了信用分配问题,并以无限的时间步长解决了理论问题。其次,使用优势函数代替原始回报。优势在收益与某些基线之间的差异之间形成,并且可以被视为衡量给定值与某些平均值相比有多好的指标。第三,在目标函数中使用额外的熵最大化项以确保代理充分探索各种策略。本质上,熵以均匀分布最大化来测量概率分布的随机性。最后,并行使用多个工人加速样品采集,同时在训练期间帮助它们去相关。将所有这些变化与深度神经网络相结合,我们得出了两种最流行的现代算法:异步优势演员评论家(actor-critical)算法,简称A3C或者A2C。两者之间的区别在于技术性而非理论性:顾名思义,它归结为并行工人如何估计其梯度并将其传播到模型中。有了这个,我将结束我们的DRL方法之旅,因为博客文章的重点更多是关于TensorFlow2.0的功能。如果你仍然不了解该主题,请不要担心,代码示例应该更清楚。如果你想了解更多,那么一个好的资源就可以开始在Deep RL中进行Spinning Up了。使用TensorFlow 2.0的优势演员-评论家让我们看看实现现代DRL算法的基础是什么:演员评论家代理(actor-critic agent)。如前一节所述,为简单起见,我们不会实现并行工作程序,尽管大多数代码都会支持它,感兴趣的读者可以将其用作锻炼机会。作为测试平台,我们将使用CartPole-v0环境。虽然它有点简单,但它仍然是一个很好的选择开始。在实现RL算法时,我总是依赖它作为一种健全性检查。通过Keras Model API实现的策略和价值首先,让我们在单个模型类下创建策略和价值估计NN:import numpy as npimport tensorflow as tfimport tensorflow.keras.layers as klclass ProbabilityDistribution(tf.keras.Model): def call(self, logits): # sample a random categorical action from given logits return tf.squeeze(tf.random.categorical(logits, 1), axis=-1)class Model(tf.keras.Model): def init(self, num_actions): super().init(‘mlp_policy’) # no tf.get_variable(), just simple Keras API self.hidden1 = kl.Dense(128, activation=‘relu’) self.hidden2 = kl.Dense(128, activation=‘relu’) self.value = kl.Dense(1, name=‘value’) # logits are unnormalized log probabilities self.logits = kl.Dense(num_actions, name=‘policy_logits’) self.dist = ProbabilityDistribution() def call(self, inputs): # inputs is a numpy array, convert to Tensor x = tf.convert_to_tensor(inputs, dtype=tf.float32) # separate hidden layers from the same input tensor hidden_logs = self.hidden1(x) hidden_vals = self.hidden2(x) return self.logits(hidden_logs), self.value(hidden_vals) def action_value(self, obs): # executes call() under the hood logits, value = self.predict(obs) action = self.dist.predict(logits) # a simpler option, will become clear later why we don’t use it # action = tf.random.categorical(logits, 1) return np.squeeze(action, axis=-1), np.squeeze(value, axis=-1)验证我们验证模型是否按预期工作:import gymenv = gym.make(‘CartPole-v0’)model = Model(num_actions=env.action_space.n)obs = env.reset()# no feed_dict or tf.Session() needed at allaction, value = model.action_value(obs[None, :])print(action, value) # [1] [-0.00145713]这里要注意的事项:模型层和执行路径是分开定义的;没有“输入”图层,模型将接受原始numpy数组;可以通过函数API在一个模型中定义两个计算路径;模型可以包含一些辅助方法,例如动作采样;在eager的模式下,一切都可以从原始的numpy数组中运行;随机代理现在我们可以继续学习一些有趣的东西A2CAgent类。首先,让我们添加一个贯穿整集的test方法并返回奖励总和。class A2CAgent: def init(self, model): self.model = model def test(self, env, render=True): obs, done, ep_reward = env.reset(), False, 0 while not done: action, _ = self.model.action_value(obs[None, :]) obs, reward, done, _ = env.step(action) ep_reward += reward if render: env.render() return ep_reward让我们看看我们的模型在随机初始化权重下得分多少:agent = A2CAgent(model)rewards_sum = agent.test(env)print("%d out of 200" % rewards_sum) # 18 out of 200离最佳转台还有很远,接下来是训练部分!损失/目标函数正如我在DRL概述部分所描述的那样,代理通过基于某些损失(目标)函数的梯度下降来改进其策略。在演员评论家中,我们训练了三个目标:用优势加权梯度加上熵最大化来改进策略,并最小化价值估计误差。import tensorflow.keras.losses as klsimport tensorflow.keras.optimizers as koclass A2CAgent: def init(self, model): # hyperparameters for loss terms self.params = {‘value’: 0.5, ’entropy’: 0.0001} self.model = model self.model.compile( optimizer=ko.RMSprop(lr=0.0007), # define separate losses for policy logits and value estimate loss=[self._logits_loss, self._value_loss] ) def test(self, env, render=True): # unchanged from previous section … def _value_loss(self, returns, value): # value loss is typically MSE between value estimates and returns return self.params[‘value’]*kls.mean_squared_error(returns, value) def _logits_loss(self, acts_and_advs, logits): # a trick to input actions and advantages through same API actions, advantages = tf.split(acts_and_advs, 2, axis=-1) # polymorphic CE loss function that supports sparse and weighted options # from_logits argument ensures transformation into normalized probabilities cross_entropy = kls.CategoricalCrossentropy(from_logits=True) # policy loss is defined by policy gradients, weighted by advantages # note: we only calculate the loss on the actions we’ve actually taken # thus under the hood a sparse version of CE loss will be executed actions = tf.cast(actions, tf.int32) policy_loss = cross_entropy(actions, logits, sample_weight=advantages) # entropy loss can be calculated via CE over itself entropy_loss = cross_entropy(logits, logits) # here signs are flipped because optimizer minimizes return policy_loss - self.params[’entropy’]*entropy_loss我们完成了目标函数!请注意代码的紧凑程度:注释行几乎比代码本身多。代理训练循环最后,还有训练回路本身,它相对较长,但相当简单:收集样本,计算回报和优势,并在其上训练模型。class A2CAgent: def init(self, model): # hyperparameters for loss terms self.params = {‘value’: 0.5, ’entropy’: 0.0001, ‘gamma’: 0.99} # unchanged from previous section … def train(self, env, batch_sz=32, updates=1000): # storage helpers for a single batch of data actions = np.empty((batch_sz,), dtype=np.int32) rewards, dones, values = np.empty((3, batch_sz)) observations = np.empty((batch_sz,) + env.observation_space.shape) # training loop: collect samples, send to optimizer, repeat updates times ep_rews = [0.0] next_obs = env.reset() for update in range(updates): for step in range(batch_sz): observations[step] = next_obs.copy() actions[step], values[step] = self.model.action_value(next_obs[None, :]) next_obs, rewards[step], dones[step], _ = env.step(actions[step]) ep_rews[-1] += rewards[step] if dones[step]: ep_rews.append(0.0) next_obs = env.reset() _, next_value = self.model.action_value(next_obs[None, :]) returns, advs = self._returns_advantages(rewards, dones, values, next_value) # a trick to input actions and advantages through same API acts_and_advs = np.concatenate([actions[:, None], advs[:, None]], axis=-1) # performs a full training step on the collected batch # note: no need to mess around with gradients, Keras API handles it losses = self.model.train_on_batch(observations, [acts_and_advs, returns]) return ep_rews def _returns_advantages(self, rewards, dones, values, next_value): # next_value is the bootstrap value estimate of a future state (the critic) returns = np.append(np.zeros_like(rewards), next_value, axis=-1) # returns are calculated as discounted sum of future rewards for t in reversed(range(rewards.shape[0])): returns[t] = rewards[t] + self.params[‘gamma’] * returns[t+1] * (1-dones[t]) returns = returns[:-1] # advantages are returns - baseline, value estimates in our case advantages = returns - values return returns, advantages def test(self, env, render=True): # unchanged from previous section … def value_loss(self, returns, value): # unchanged from previous section … def logits_loss(self, acts_and_advs, logits): # unchanged from previous section …训练和结果我们现在已经准备好在CartPole-v0上训练我们的单工A2C代理了!训练过程不应超过几分钟,训练完成后,你应该看到代理成功达到200分中的目标。rewards_history = agent.train(env)print(“Finished training, testing…")print("%d out of 200” % agent.test(env)) # 200 out of 200在源代码中,我包含了一些额外的帮助程序,可以打印出运行的奖励和损失,以及rewards_history的基本绘图仪。静态计算图有了所有这种渴望模式的成功的喜悦,你可能想知道静态图形执行是否可以。当然!此外,我们还需要多一行代码来启用它!with tf.Graph().as_default(): print(tf.executing_eagerly()) # False model = Model(num_actions=env.action_space.n) agent = A2CAgent(model) rewards_history = agent.train(env) print(“Finished training, testing…”) print("%d out of 200" % agent.test(env)) # 200 out of 200有一点需要注意,在静态图形执行期间,我们不能只有Tensors,这就是为什么我们在模型定义期间需要使用CategoricalDistribution的技巧。事实上,当我在寻找一种在静态模式下执行的方法时,我发现了一个关于通过Keras API构建的模型的一个有趣的低级细节。还有一件事…还记得我说过TensorFlow默认是运行在eager模式下吧,甚至用代码片段证明它吗?好吧,我错了。如果你使用Keras API来构建和管理模型,那么它将尝试将它们编译为静态图形。所以你最终得到的是静态计算图的性能,具有渴望执行的灵活性。你可以通过model.run_eagerly标志检查模型的状态,你也可以通过设置此标志来强制执行eager模式变成True,尽管大多数情况下你可能不需要这样做。但如果Keras检测到没有办法绕过eager模式,它将自动退出。为了说明它确实是作为静态图运行,这里是一个简单的基准测试:# create a 100000 samples batchenv = gym.make(‘CartPole-v0’)obs = np.repeat(env.reset()[None, :], 100000, axis=0)Eager基准%%timemodel = Model(env.action_space.n)model.run_eagerly = Trueprint(“Eager Execution: “, tf.executing_eagerly())print(“Eager Keras Model:”, model.run_eagerly) = model(obs)######## Results #######Eager Execution: TrueEager Keras Model: TrueCPU times: user 639 ms, sys: 736 ms, total: 1.38 s静态基准%%timewith tf.Graph().as_default(): model = Model(env.action_space.n) print(“Eager Execution: “, tf.executing_eagerly()) print(“Eager Keras Model:”, model.run_eagerly) _ = model.predict(obs)######## Results #######Eager Execution: FalseEager Keras Model: FalseCPU times: user 793 ms, sys: 79.7 ms, total: 873 ms默认基准%%timemodel = Model(env.action_space.n)print(“Eager Execution: “, tf.executing_eagerly())print(“Eager Keras Model:”, model.run_eagerly) = model.predict(obs)######## Results #######Eager Execution: TrueEager Keras Model: FalseCPU times: user 994 ms, sys: 23.1 ms, total: 1.02 s正如你所看到的,eager模式是静态模式的背后,默认情况下,我们的模型确实是静态执行的。结论希望本文能够帮助你理解DRL和TensorFlow2.0。请注意,TensorFlow2.0仍然只是预览版本,甚至不是候选版本,一切都可能发生变化。如果TensorFlow有什么东西你特别不喜欢,让它的开发者知道!人们可能会有一个挥之不去的问题:TensorFlow比PyTorch好吗?也许,也许不是。它们两个都是伟大的库,所以很难说这样谁好,谁不好。如果你熟悉PyTorch,你可能已经注意到TensorFlow 2.0不仅赶上了它,而且还避免了一些PyTorch API的缺陷。在任何一种情况下,对于开发者来说,这场竞争都已经为双方带来了积极的结果,我很期待看到未来的框架将会变成什么样。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 28, 2019 · 4 min · jiezi

Auto-Keras与AutoML:入门指南

摘要: 不会机器学习?不会人工智能?没关系!自动化程序来了!在本教程中,你将学习如何使用Auto-Keras(Google的AutoML的开源替代品)来实现自动化机器学习和深度学习。目前来说,深度学习从业者在数据集上训练神经网络时,主要正在尝试优化和平衡两个目标:1.定义适合数据集性质的神经网络体系结构;2.在许多实验中调整一组超参数,这将导致模型具有高精度并能够推广到训练和测试集之外的数据。需要调整的典型超参数包括优化算法(SGD,Adam等),学习速率和学习速率调度以及正则化等。根据数据集和具体问题,深度学习专家可以进行数十到数百次实验,以找到神经网络架构和超参数之间的平衡,这些实验通常需要计算数百到数千小时。刚刚提到的这种模式仅适用于专家,那非深度学习专家呢?这就需要Auto-Keras和AutoML:Auto-Keras和AutoML的最终目标是通过使用自动神经架构搜索(NAS)算法降低进入机器学习和深度学习的门槛。Auto-Keras和AutoML使非深度学习专家能够以最小的深度学习领域知识或实际数据来训练他们自己的模型。具有最小机器学习专业知识的程序员可以使用AutoML和Auto-Keras并应用这些算法,只需很少的努力即可实现最先进的性能。听起来好得令人难以置信?也许你需要好好阅读这篇文章的其余部分以找出原因。Auto-Keras和AutoML:入门指南在本博文的第一部分中,我们将讨论自动机器学习(AutoML)和神经架构搜索(NAS),这种算法使得AutoML在应用于神经网络和深度学习时成为可能。我们还将简要讨论Google的AutoML,这是一套工具和库,允许具有有限机器学习专业知识的程序员在自己的数据上训练高精度模型。当然,谷歌的AutoML是一种专有算法,AutoML的另一种选择是开源Auto-Keras、它是围绕Keras和PyTorch而构建。然后,我将向你展示如何使用Auto-Keras自动训练网络以及评估它。什么是自动机器学习(AutoML)?Auto-Keras是Google AutoML的替代品。它可以帮助你自动训练模型,几乎不需要干预。对于新手深度学习从业者来说,它们是很好的选择。在无监督学习之外,非专家的自动机器学习被认为是机器学习的“圣杯”。想象一下通过以下方式自动创建机器学习模型的能力:1.安装库/使用Web界面;2.将库/接口指向你的数据;3.自动训练数据模型而无需调整参数/需要深入了解为其提供动力的算法;一些公司正试图创建这样的解决方案,其中一个就是谷歌的AutoML。Google AutoML使非常有限的机器学习经验的开发人员和工程师能够自动在他们自己的数据集上训练神经网络。谷歌的底层AutoML算法是迭代的:1.在训练集上训练网络;2.在测试集上评估网络;3.修改神经网络架构;4.调整超参数;5.重复上述过程;使用AutoML的程序员或工程师不需要定义他们自己的神经网络架构或调整超参数,AutoML会自动为他们做这件事。神经架构搜索(NAS)使AutoML成为可能神经架构搜索(NAS)在搜索CIFAR-10的最佳CNN架构时,通过这些图表生成了一个模型。Google的AutoML和Auto-Keras都采用了一种称为神经架构搜索(NAS)的算法。根据你的输入数据集,神经架构搜索算法将自动搜索最佳架构和相应参数。神经架构搜索基本上是用一组自动调整模型的算法取代深度学习工程师/从业者!在计算机视觉和图像识别的背景下,神经架构搜索算法将:1.接受输入训练数据集;2.优化并找到称为“单元”的架构构建块,然后让这些单元自动学习,这可能看起来类似于初始化,残留或激活微架构;3.不断训练和搜索“NAS搜索空间”以获得更优化的单元;如果AutoML系统的用户是经验丰富的深度学习从业者,那么他们可能会决定:1.在训练数据集的一个非常小的子集上运行NAS;2.找到一组最佳的架构构建块/单元;3.获取这些单元并手动定义在体系结构搜索期间找到的更深层次的网络版本;4.使用自己的专业知识和最佳实践,在完整的培训集上训练网络;这种方法是全自动机器学习解决方案与需要专家深度学习实践者的解决方案之间的混合体,通常这种方法比NAS自己训练的模型性能更好。Auto-Keras:谷歌AutoML的开源替代品在Auto-Keras包是由在德克萨斯州A&M大学数据实验室团队开发。Auto-Keras是Google AutoML的开源替代品。Auto-Keras依然是利用神经架构搜索,但应用“网络态射”(在更改架构时保持网络功能)以及贝叶斯优化,以指导网络态射以实现更高效的神经网络搜索。你可以在Jin等人的2018年出版物Auto-Keras:Efficient Neural Architecture Search with Network Morphism中找到Auto-Keras框架的全部细节。安装Auto-Keras:正如Auto-Keras GitHub存储库所述,Auto-Keras处于“预发布”状态-它现在还不是正式版本。其次,Auto-Keras需要Python 3.6并且只与Python 3.6兼容。如果你使用的*是3.6以外的任何其他版本的Python,你将无法使用Auto-Keras软件包。如果你想要检查Python版本,只需使用以下命令:python –version如果你有Python 3.6,你可以使用pip安装Auto-Keras:pip install tensorflow # or tensorflow-gpupip install keraspip install autokeras使用Auto-Keras实现我们的训练脚本:让我们继续使用Auto-Keras实现我们的训练脚本,打开train_auto_keras.py文件并插入以下代码:# import the necessary packagesfrom sklearn.metrics import classification_reportfrom keras.datasets import cifar10import autokeras as akimport osdef main(): # initialize the output directory OUTPUT_PATH = “output"首先,我们在第2-5行导入必要的包:如前所述,我们将使用scikit-learn的classification_report来计算我们将在输出文件中保存的统计信息。我们将使用CIFAR-10数据集,因为它已经被内置到keras.datasets。然后是导入import依赖项-autokeras,我已经将它用AK的简写代替。该os模块是必需的,因为我们会在建立输出文件的路径时,在各种操作系统上容纳路径分隔符。我们在第7行定义脚本的主要功能,由于Auto-Keras和TensorFlow处理线程的方式,我们需要将代码包装在main函数中。有关更多详细信息,请参阅此GitHub问题线程。现在让我们初始化Auto-Keras的训练时间列表:# initialize the list of training times that we’ll allow # Auto-Keras to train for TRAINING_TIMES = [ 60 * 60, # 1 hour 60 * 60 * 2, # 2 hours 60 * 60 * 4, # 4 hours 60 * 60 * 8, # 8 hours 60 * 60 * 12, # 12 hours 60 * 60 * 24, # 24 hours ]上述代码是限定了一组训练-TIMES,包括[1,2,4,8,12,24]小时。我们将使用Auto-Keras来探索更长的训练时间对精确度的影响。让我们加载CIFAR-10数据集并初始化类名:# load the training and testing data, then scale it into the # range [0, 1] print("[INFO] loading CIFAR-10 data…”) ((trainX, trainY), (testX, testY)) = cifar10.load_data() trainX = trainX.astype(“float”) / 255.0 testX = testX.astype(“float”) / 255.0 # initialize the label names for the CIFAR-10 dataset labelNames = [“airplane”, “automobile”, “bird”, “cat”, “deer”, “dog”, “frog”, “horse”, “ship”, “truck”]我们的CIFAR-10数据被加载并存储在第25行的训练/测试分组中。随后,我们将这个数据缩放到[0,1]的范围。接着我们会初始化我们的类labelNames,这10个类包含在CIFAR-10中。请注意,标签在这里很重要。现在让我们开始循环遍历我们的TRAINING_TIMES,每次都使用Auto-Keras:# loop over the number of seconds to allow the current Auto-Keras # model to train for for seconds in TRAINING_TIMES: # train our Auto-Keras model print("[INFO] training model for {} seconds max…".format( seconds)) model = ak.ImageClassifier(verbose=True) model.fit(trainX, trainY, time_limit=seconds) model.final_fit(trainX, trainY, testX, testY, retrain=True) # evaluate the Auto-Keras model score = model.evaluate(testX, testY) predictions = model.predict(testX) report = classification_report(testY, predictions, target_names=labelNames) # write the report to disk p = os.path.sep.join(OUTPUT_PATH, “{}.txt”.format(seconds)) f = open(p, “w”) f.write(report) f.write("\nscore: {}".format(score)) f.close()上面的代码块是今天脚本的核心。在第35行,我们在每个TRAINING_TIMES上定义了一个循环,我们在其中做以下操作:初始化我们的模型(AK.ImageClassifier),并让训练开始。请注意,我们并没有实例化一个特定对象的CNN类,我们也没有调整超参数。因为Auto-Keras会为我们处理所有这些。一旦达到时间限制,请采用Auto-Keras找到的最佳模型和参数+重新训练模型。评估和构建分类报告。将分类报告与准确度分数一起写入磁盘,以便我们评估更长训练时间的影响。我们将为每个TRAINING_TIMES重复此过程。最后,我们将检查并启动执行的主线程:# if this is the main thread of execution then start the process (our# code must be wrapped like this to avoid threading issues with# TensorFlow)if name == “main”: main()这里我们检查确保这是执行的主线程,然后是主函数。仅仅60行代码,我们就完成了使用CIFAR-10示例脚本编写Auto-Keras,但是我们还没有完成……使用Auto-Keras训练神经网络让我们继续使用Auto-Keras训练我们的神经网络。请确保使用本教程的“下载”部分下载源代码。从那里打开终端,导航到下载源代码的位置,然后执行以下命令:$ python train_auto_keras.py[INFO] training model for 3600 seconds max… Preprocessing the images.Preprocessing finished.Initializing search.Initialization finished.+———————————————-+| Training model 0 |+———————————————-+Using TensorFlow backend.No loss decrease after 5 epochs.Saving model.+————————————————————————–+| Model ID | Loss | Metric Value |+————————————————————————–+| 0 | 4.816269397735596 | 0.5852 |+————————————————————————–++———————————————-+| Training model 1 |+———————————————-+Using TensorFlow backend.Epoch-14, Current Metric - 0.83: 28%|██████▊ | 110/387 [01:02<02:46, 1.67 batch/s]Time is out.[INFO] training model for 86400 seconds max… Preprocessing the images.Preprocessing finished.Initializing search.Initialization finished.+———————————————-+| Training model 0 |+———————————————-+Using TensorFlow backend.No loss decrease after 5 epochs….+———————————————-+| Training model 21 |+———————————————-+Using TensorFlow backend.No loss decrease after 5 epochs.+————————————————————————–+| Father Model ID | Added Operation |+————————————————————————–+| | to_deeper_model 16 ReLU || 16 | to_wider_model 16 64 |+————————————————————————–+Saving model.+————————————————————————–+| Model ID | Loss | Metric Value |+————————————————————————–+| 21 | 0.8843476831912994 | 0.9316000000000001 |+————————————————————————–++———————————————-+| Training model 22 |+———————————————-+Using TensorFlow backend.Epoch-3, Current Metric - 0.9: 80%|████████████████████▊ | 310/387 [03:50<00:58, 1.31 batch/s]Time is out.No loss decrease after 30 epochs.在这里你可以看到我们的脚本正在指示Auto-Keras执行六组实验。在NVIDIA K80 GPU上,总训练时间为3天多一点。Auto-Keras的结果:使用Auto-Keras通常是一个非常耗时的过程。使用Auto-Keras进行训练可在8-12小时范围内为CIFAR-10生成最佳型号。在上图中,你可以看到训练时间(x轴)对使用Auto-Keras的总体准确度(y轴)的影响。较短的训练时间,即1小时和2小时,大约可以达到73%的准确性。一旦我们训练4小时,我们就能达到高达93%的准确率。训练8-12小时,我们就能获得95%的精确度了。超过8-12小时的训练不会提高我们的准确度,这意味着我们已达到饱和点并且Auto-Keras无法进一步优化。Auto-Keras和AutoML值得吗?Auto-Keras值得吗?这无疑是行业向前迈出的一大步,对那些没有深入学习领域知识的人尤其有用。在无监督学习之外(从未标记数据自动学习模式),非专家的自动机器学习被认为是机器学习的“圣杯”。Google的AutoML和开源Auto-Keras软件包都试图将机器学习带给大众,即使是没有关键性技术的经验的程序员。虽然Auto-Keras在CIFAR-10上工作得相当好,但是我使用我之前关于深度学习,医学图像和疟疾检测的文章进行了第二组实验。我使用简化的ResNet架构获得了97.1%的准确率,该架构花费了不到一小时的时间进行训练。然后我让Auto-Keras在相同的数据集上运行24小时-结果只有96%的准确度,低于我自己定义的架构。但不管怎样,谷歌的AutoML和Auto-Keras都是向前迈出的一大步。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 28, 2019 · 2 min · jiezi

机器学习数据集哪里找:最佳数据集来源盘点

摘要:很难找到一个特定的数据集来解决对应的机器学习问题,这是非常痛苦的。下面的网址列表不仅包含用于实验的大型数据集,还包含描述、使用示例等,在某些情况下还包含用于解决与该数据集相关的机器学习问题的算法代码。1 -Kaggle数据集网址:http://www.kaggle.com/datasets 这是我最喜欢的数据集网站之一。每个数据集都有对应的一个小型社区,你可以在其中讨论数据、查找公共代码或在内核中创建自己的项目。该网站包含大量形状、大小、格式各异的真实数据集。你还可以看到与每个数据集相关的“内核”,其中许多不同的数据科学家提供了笔记来分析数据集。有时在某些特定的数据集中,你可以从笔记中找到相应的算法,解决预测问题。2 -亚马逊数据集网址:https://registry.opendata.aws 该数据源包含多个不同领域的数据集,如:公共交通、生态资源、卫星图像等。它也有一个搜索框来帮助你找到你正在寻找的数据集,另外它还有数据集描述和使用示例,这是非常简单、实用的!3- UCI机器学习库:网址:https://archive.ics.uci.edu/ml/datasets.html 这是加州大学信息与计算机科学学院的一个数据库,包含了100多个数据集。它根据机器学习问题的类型对数据集进行分类。你可以找到单变量、多变量、分类、回归或者是推荐系统的数据集。UCI的某些数据集已经更新完毕并准备使用。4-谷歌的数据集搜索引擎:网址:https://toolbox.google.com/datasetsearch 在2018年末,谷歌做了他们最擅长的事情,推出了另一项伟大的服务。它是一个可以按名称搜索数据集的工具箱。谷歌的目标是统一成千上万个不同的数据集存储库,使这些数据能够被发现。5 -微软数据集:网址:https://msropendata.com 2018年7月,微软与外部研究社区共同宣布推出“微软研究开放数据”。它在公共云中包含一个数据存储库,用于促进全球研究社区之间的协作。另外它还提供了一组在已发表的研究中使用的、经过整理的数据集。6-Awesome公共数据集:网址:https://github.com/awesomedata/awesome-public-datasets 这是一个按照主题分类的,由社区公开维护的一系列数据集清单,比如生物学、经济学、教育学等。这里列出的大多数数据集都是免费的,但是在使用任何数据集之前,你应该检查相应的许可要求。7 -政府数据集:政府的相关数据集也很容易找到。许多国家为了提高知名度,向公众分享了各种数据集。例如:欧盟开放数据门户:欧洲政府数据集。新西兰政府数据集。印度政府数据集。8-计算机视觉数据集:网址:https://www.visualdata.io 如果你从事图像处理、计算机视觉或者是深度学习,那么这应该是你的实验获取数据的重要来源之一。该数据集包含一些可以用来构建计算机视觉(CV)模型的大型数据集。你可以通过特定的CV主题查找特定的数据集,如语义分割、图像标题、图像生成,甚至可以通过解决方案(自动驾驶汽车数据集)查找特定的数据集。综上所述,从我所观察到的情况来看,越来越多的用于研究机器学习的各种数据集变得更容易获取,维护这些新数据集的社区,也将不断地发展,使计算机科学社区能够继续快速创新,为生活带来更多创造性的解决方案。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 25, 2019 · 1 min · jiezi

大众点评搜索基于知识图谱的深度学习排序实践

引言挑战与思路搜索是大众点评App上用户进行信息查找的最大入口,是连接用户和信息的重要纽带。而用户搜索的方式和场景非常多样,并且由于对接业务种类多,流量差异大,为大众点评搜索(下文简称点评搜索)带来了巨大的挑战,具体体现在如下几个方面:意图多样:用户查找的信息类型和方式多样。信息类型包括POI、榜单、UGC、攻略、达人等。以找店为例,查找方式包括按距离、按热度、按菜品和按地理位置等多种方式。例如用户按照品牌进行搜索时,大概率是需要寻找距离最近或者常去的某家分店;但用户搜索菜品时,会对菜品推荐人数更加敏感,而距离因素会弱化。业务多样:不同业务之间,用户的使用频率、选择难度以及业务诉求均不一样。例如家装场景用户使用频次很低,行为非常稀疏,距离因素弱,并且选择周期可能会很长;而美食多为即时消费场景,用户行为数据多,距离敏感。用户类型多样:不同的用户对价格、距离、口味以及偏好的类目之间差异很大;搜索需要能深度挖掘到用户的各种偏好,实现定制化的“千人千面”的搜索。LBS的搜索:相比电商和通用搜索,LBS的升维效应极大地增加了搜索场景的复杂性。例如对于旅游用户和常驻地用户来说,前者在搜索美食的时候可能会更加关心当地的知名特色商户,而对于距离相对不敏感。上述的各项特性,叠加上时间、空间、场景等维度,使得点评搜索面临比通用搜索引擎更加独特的挑战。而解决这些挑战的方法,就需要升级NLP(Natural Language Processing,自然语言处理)技术,进行深度查询理解以及深度评价分析,并依赖知识图谱技术和深度学习技术对搜索架构进行整体升级。在美团NLP中心以及大众点评搜索智能中心两个团队的紧密合作之下,经过短短半年时间,点评搜索核心KPI在高位基础上仍然大幅提升,是过去一年半涨幅的六倍之多,提前半年完成全年目标。基于知识图谱的搜索架构重塑美团NLP中心正在构建全世界最大的餐饮娱乐知识图谱——美团大脑(相关信息请参见《美团大脑:知识图谱的建模方法及其应用》)。它充分挖掘关联各个场景数据,用NLP技术让机器“阅读”用户公开评论,理解用户在菜品、价格、服务、环境等方面的喜好,构建人、店、商品、场景之间的知识关联,从而形成一个“知识大脑”[1]。通过将知识图谱信息加入到搜索各个流程中,我们对点评搜索的整体架构进行了升级重塑,图1为点评搜索基于知识图谱搭建的5层搜索架构。本篇文章是“美团大脑”系列文章第二篇(系列首篇文章请参见《美团餐饮娱乐知识图谱——美团大脑揭秘》),主要介绍点评搜索5层架构中核心排序层的演变过程,文章主要分为如下3个部分:核心排序从传统机器学习模型到大规模深度学习模型的演进。搜索场景深度学习排序模型的特征工程实践。适用于搜索场景的深度学习Listwise排序算法——LambdaDNN。2. 排序模型探索与实践搜索排序问题在机器学习领域有一个单独的分支,Learning to Rank(L2R)。主要分类如下:根据样本生成方法和Loss Function的不同,L2R可以分为Pointwise、Pairwise、Listwise。按照模型结构划分,可以分为线性排序模型、树模型、深度学习模型,他们之间的组合(GBDT+LR,Deep&Wide等)。在排序模型方面,点评搜索也经历了业界比较普遍的迭代过程:从早期的线性模型LR,到引入自动二阶交叉特征的FM和FFM,到非线性树模型GBDT和GBDT+LR,到最近全面迁移至大规模深度学习排序模型。下面先简单介绍下传统机器学习模型(LR、FM、GBDT)的应用和优缺点,然后详细介绍深度模型的探索实践过程。传统机器学习模型LR可以视作单层单节点的线性网络结构。模型优点是可解释性强。通常而言,良好的解释性是工业界应用实践比较注重的一个指标,它意味着更好的可控性,同时也能指导工程师去分析问题优化模型。但是LR需要依赖大量的人工特征挖掘投入,有限的特征组合自然无法提供较强的表达能力。FM可以看做是在LR的基础上增加了一部分二阶交叉项。引入自动的交叉特征有助于减少人工挖掘的投入,同时增加模型的非线性,捕捉更多信息。FM能够自动学习两两特征间的关系,但更高量级的特征交叉仍然无法满足。GBDT是一个Boosting的模型,通过组合多个弱模型逐步拟合残差得到一个强模型。树模型具有天然的优势,能够很好的挖掘组合高阶统计特征,兼具较优的可解释性。GBDT的主要缺陷是依赖连续型的统计特征,对于高维度稀疏特征、时间序列特征不能很好的处理。深度神经网络模型随着业务的发展,在传统模型上取得指标收益变得愈发困难。同时业务的复杂性要求我们引入海量用户历史数据,超大规模知识图谱特征等多维度信息源,以实现精准个性化的排序。因此我们从2018年下半年开始,全力推进L2核心排序层的主模型迁移至深度学习排序模型。深度模型优势体现在如下几个方面:强大的模型拟合能力:深度学习网络包含多个隐藏层和隐藏结点,配合上非线性的激活函数,理论上可以拟合任何函数,因此十分适用于点评搜索这种复杂的场景。强大的特征表征和泛化能力:深度学习模型可以处理很多传统模型无法处理的特征。例如深度网络可以直接中从海量训练样本中学习到高维稀疏ID的隐含信息,并通过Embedding的方式去表征;另外对于文本、序列特征以及图像特征,深度网络均有对应的结构或者单元去处理。自动组合和发现特征的能力:华为提出的DeepFM,以及Google提出的DeepCrossNetwork可以自动进行特征组合,代替大量人工组合特征的工作。下图是我们基于Google提出的Wide&Deep模型搭建的网络结构[2]。其中Wide部分输入的是LR、GBDT阶段常用的一些细粒度统计特征。通过较长周期统计的高频行为特征,能够提供很好的记忆能力。Deep部分通过深层的神经网络学习Low-Order、高纬度稀疏的Categorical型特征,拟合样本中的长尾部分,发现新的特征组合,提高模型的泛化能力。同时对于文本、头图等传统机器学习模型难以刻画的特征,我们可以通过End-to-End的方式,利用相应的子网络模型进行预处理表示,然后进行融合学习。3. 搜索深度排序模型的特征工程实践深度学习的横空出世,将算法工程师从很多人工挖掘和组合特征的事情中解放出来。甚至有一种论调,专做特征工程的算法工程师可能面临着失业的风险。但是深度学习的自动特征学习目前主要集中体现在CV领域,CV领域的特征数据是图片的像素点——稠密的低阶特征,深度学习通过卷积层这个强力工具,可以自动对低阶特征进行组合和变换,相比之前人工定义的图像特征从效果上来说确实更加显著。在NLP领域因为Transformer的出现,在自动特征挖掘上也有了长足的进步,BERT利用Transformer在多个NLP Task中取得了State-of-The-Art的效果。但是对于CTR预估和排序学习的领域,目前深度学习尚未在自动特征挖掘上对人工特征工程形成碾压之势,因此人工特征工程依然很重要。当然,深度学习在特征工程上与传统模型的特征工程也存在着一些区别,我们的工作主要集中在如下几个方面。3.1 特征预处理特征归一化:深度网络的学习几乎都是基于反向传播,而此类梯度优化的方法对于特征的尺度非常敏感。因此,需要对特征进行归一化或者标准化以促使模型更好的收敛。特征离散化:工业界一般很少直接使用连续值作为特征,而是将特征离散化后再输入到模型中。一方面因为离散化特征对于异常值具有更好的鲁棒性,其次可以为特征引入非线性的能力。并且,离散化可以更好的进行Embedding,我们主要使用如下两种离散化方法:等频分桶:按样本频率进行等频切分,缺失值可以选择给一个默认桶值或者单独设置分桶。树模型分桶:等频离散化的方式在特征分布特别不均匀的时候效果往往不好。此时可以利用单特征结合Label训练树模型,以树的分叉点做为切分值,相应的叶子节点作为桶号。特征组合:基于业务场景对基础特征进行组合,形成更丰富的行为表征,为模型提供先验信息,可加速模型的收敛速度。典型示例如下:用户性别与类目之间的交叉特征,能够刻画出不同性别的用户在类目上的偏好差异,比如男性用户可能会较少关注“丽人”相关的商户。时间与类目之间的交叉特征,能够刻画出不同类目商户在时间上的差异,例如,酒吧在夜间会更容易被点击。3.2 万物皆可Embedding深度学习最大的魅力在于其强大的特征表征能力,在点评搜索场景下,我们有海量的用户行为数据,有丰富的商户UGC信息以及美团大脑提供的多维度细粒度标签数据。我们利用深度学习将这些信息Embedding到多个向量空间中,通过Embedding去表征用户的个性化偏好和商户的精准画像。同时向量化的Embedding也便于深度模型进一步的泛化、组合以及进行相似度的计算。3.2.1 用户行为序列的Embedding用户行为序列(搜索词序列、点击商户序列、筛选行为序列)包含了用户丰富的偏好信息。例如用户筛选了“距离优先”时,我们能够知道当前用户很有可能是一个即时消费的场景,并且对距离较为敏感。行为序列特征一般有如下图所示的三种接入方式:Pooling:序列Embedding后接入Sum/Average Pooling层。此方式接入成本低,但忽略了行为的时序关系。RNN:LSTM/GRU接入,利用循环网络进行聚合。此方式能够考虑行为序列的时序关系;代价是增大了模型复杂度,影响线上预测性能。Attention:序列Embedding后引入Attention机制,表现为加权的Sum Pooling;相比LSTM/GRU计算开销更低[4]。同时,为了突显用户长期偏好和短期偏好对于排序的不同影响,我们按照时间维度对行为序列进行了划分:Session、半小时、一天、一周等粒度,也在线上取得了收益。3.2.2 用户ID的Embedding一种更常见的刻画用户偏好的方式,是直接将用户ID经过Embedding后作为特征接入到模型中,但是最后上线的效果却不尽如人意。通过分析用户的行为数据,我们发现相当一部分用户ID的行为数据较为稀疏,导致用户ID的Embedding没有充分收敛,未能充分刻画用户的偏好信息。Airbnb发表在KDD 2018上的文章为这种问题提供了一种解决思路[9]——利用用户基础画像和行为数据对用户ID进行聚类。Airbnb的主要场景是为旅游用户提供民宿短租服务,一般用户一年旅游的次数在1-2次之间,因此Airbnb的用户行为数据相比点评搜索会更为稀疏一些。如上图所示,将用户画像特征和行为特征进行离散分桶,拼接特征名和所属桶号,得到的聚类ID为:US_lt1_pn3_pg3_r3_5s4_c2_b1_bd2_bt2_nu3。我们也采取了类似Airbnb的方案,稀疏性的问题得到了很好的解决,并且这样做还获得了一些额外的收益。点评搜索作为一个本地化的生活信息服务平台,大部分用户的行为都集中自己的常驻地,导致用户到达一个新地方时,排序个性化明显不足。通过这种聚类的方式,将异地有相同行为的用户聚集在一起,也能解决一部分跨站的个性化问题。3.2.3 商户信息Embedding商户Embedding除了可以直接将商户ID加入模型中之外,美团大脑也利用深度学习技术对UGC进行大量挖掘,对商家的口味、特色等细粒度情感进行充分刻画,例如下图所示的“好停车”、“菜品精致”、“愿意再次光顾”等标签。这些信息与单纯的商户星级、点评数相比,刻画的角度更多,粒度也更细。我们将这些标签也进行Embedding并输入到模型中:直连:将标签特征做Pooling后直接输入模型。这种接入方式适合端到端的学习方式;但受输入层大小限制,只能取Top的标签,容易损失抽象实体信息。分组直连:类似于直连接入的方式,但是先对标签进行分类,如菜品/风格/口味等类别;每个分类取Top N的实体后进行Pooling生成不同维度的语义向量。与不分组的直连相比,能够保留更多抽象信息。子模型接入:可以利用DSSM模型,以标签作为商户输入学习商户的Embedding表达。此种方式能够最大化保留标签的抽象信息,但是线上实现和计算成本较高。3.2.4 加速Embedding特征的收敛在我们的深度学习排序模型中,除了Embedding特征,也存在大量Query、Shop和用户维度的强记忆特征,能够很快收敛。而Embedding特征是更为稀疏的弱特征,收敛速度较慢,为了加速Embedding特征的收敛,我们尝试了如下几种方案:低频过滤:针对出现频率较低的特征进行过滤,可以很大程度上减少参数量,避免过拟合。预训练:利用多类模型对稀疏Embedding特征进行预训练,然后进入模型进行微调:通过无监督模型如Word2vec、Fasttext对用户-商户点击关系建模,生成共现关系下的商户Embedding。利用DSSM等监督模型对Query-商户点击行为建模得到Query和商户的Embedding。Multi-Task:针对稀疏的Embedding特征,单独设置一个子损失函数,如下图所示。此时Embedding特征的更新依赖两个损失函数的梯度,而子损失函数脱离了对强特征的依赖,可以加快Embedding特征的收敛。3.3 图片特征图片在搜索结果页中占据了很大的展示面积,图片质量的好坏会直接影响用户的体验和点击,而点评商户首图来自于商户和用户上传的图片,质量参差不齐。因此,图片特征也是排序模型中较为重要的一类。目前点评搜索主要用了以下几类图片特征:基础特征:提取图片的亮度、色度饱和度等基础信息,进行特征离散化后得到图片基础特征。泛化特征:使用ResNet50进行图片特征提取[3],通过聚类得到图片的泛化特征。质量特征:使用自研的图片质量模型,提取中间层输出,作为图片质量的Embedding特征。标签特征:提取图片是否是食物、环境、价目表、Logo等作为图片分类和标签特征。4. 适用于搜索场景的深度学习Listwise排序算法—LambdaDNN4.1 搜索业务指标与模型优化目标的Gap通常模型的预测目标与业务指标总会存在一些Gap。如果模型的预测目标越贴近业务目标,越能保证模型优化的同时业务指标也能够有相应的提升;反之则会出现模型离线指标提升,但线上关键业务指标提升不明显,甚至出现负向的问题。工业届大部分深度学习排序采用Pointwise的Log Loss作为损失函数,与搜索业务指标有较大的Gap。体现在如下两个方面:搜索业务常用的指标有QV_CTR或者SSR(Session Success Rate),更关心的是用户搜索的成功率(有没有发生点击行为);而Pointwise的Log Loss更多是关注单个Item的点击率。搜索业务更关心排在页面头部结果的好坏,而Pointwise的方法则对于所有位置的样本一视同仁。基于上述理由,我们对于深度学习模型的损失函数进行了优化。4.2 优化目标改进-从Log Loss到NDCG为了让排序模型的优化目标尽量贴近搜索业务指标,需要按照Query计算损失,且不同位置的样本具有不同的权重。搜索系统常用的指标NDCG(Normalized Discounted Cumulative Gain)相较于Log Loss显然更贴近搜索业务的要求,NDCG计算公式如下:累加部分为DCG(Discounted Cumulative Gain)表示按照位置折损的收益,对于Query下的结果列表l,函数G表示对应Doc的相关度分值,通常取指数函数,即G(lj)=2lj-1(lj表示的是相关度水平,如{0,1,2});函数 即位置折损,一般采用 (j)=1/log(j+1),Doc与Query的相关度越高且位置越靠前则DCG值会越大。另外,通常我们仅关注排序列表页前k位的效果,Zk 表示 DCG@k 的可能最大值,以此进行归一化处理后得到的就是NDCG@k。问题在于NDCG是一个处处非平滑的函数,直接以它为目标函数进行优化是不可行的。LambdaRank提供了一种思路:绕过目标函数本身,直接构造一个特殊的梯度,按照梯度的方向修正模型参数,最终能达到拟合NDCG的方法[6]。因此,如果我们能将该梯度通过深度网络进行反向传播,则能训练一个优化NDCG的深度网络,该梯度我们称之为Lambda梯度,通过该梯度构造出的深度学习网络称之为LambdaDNN。要了解Lambda梯度需要引入LambdaRank。LambdaRank模型是通过Pairwise来构造的,通常将同Query下有点击样本和无点击样本构造成一个样本Pair。模型的基本假设如下式所示,令Pij为同一个Query下Doci相比Docj更相关的概率,其中si和sj分别为Doci和Docj的模型得分:使用交叉熵为损失函数,令Sij表示样本Pair的真实标记,当Doci比Docj更相关时(即Doci有被用户点击,而Docj没有被点击),有Sij=1,否则为-1;则损失函数可以表示为:在构造样本Pair时,我们可以始终令i为更相关的文档,此时始终有Sij≡1,代入上式并进行求导,则损失函数的梯度为:到目前为止,损失函数的计算过程中并未考虑样本所在的位置信息。因此进一步对梯度进行改造,考虑Doci和Docj交换位置时的NDCG值变化,下式即为前述的Lambda梯度。可以证明,通过此种方式构造出来的梯度经过迭代更新,最终可以达到优化NDCG的目的。Lambda梯度的物理意义如下图所示。其中蓝色表示更相关(用户点击过)的文档,则Lambda梯度更倾向于位置靠上的Doc得到的提升更大(如红色箭头所示)。有了Lambda梯度的计算方法,训练中我们利用深度网络预测同Query下的Doc得分,根据用户实际点击Doc的情况计算Lambda梯度并反向传播回深度网络,则可以得到一个直接预测NDCG的深度网络。4.3 LambdaDNN的工程实施我们利用TensorFlow分布式框架训练LambdaDNN模型。如前文所述,Lambda梯度需要对同Query下的样本进行计算,但是正常情况下所有的样本是随机Shuffle到各个Worker的。因此我们需要对样本进行预处理:通过QueryId进行Shuffle,将同一个Query的样本聚合在一起,同一个Query的样本打包进一个TFRecord。由于每次请求Query召回的Doc数不一样,对于可变Size的Query样本在拉取数据进行训练时需要注意,TF会自动补齐Mini-Batch内每个样本大小一致,导致输入数据中存在大量无意义的默认值样本。这里我们提供两点处理方式:MR过程中对Key进行处理,使得多个Query的样本聚合在一起,然后在训练的时候进行动态切分。读取到补齐的样本,根据设定的补齐标记获取索引位,去除补齐数据。为了提升训练效率,我们与基础研发平台数据平台中心紧密协同,一起探索并验证了多项优化操作:将ID类特征的映射等操作一并在预处理中完成,减少多轮Training过程中的重复计算。将样本转TfRecord,利用RecordDataSet方式读取数据并计算处理,Worker的计算性能大概提升了10倍。Concat多个Categorical特征,组合成Multi-Hot的Tensor进行一次Embedding_Lookup操作,减少Map操作的同时有助于参数做分片存储计算。稀疏Tensor在计算梯度以及正则化处理时保留索引值,仅对有数值的部分进行更新操作。多个PS服务器间进行分片存储大规模Tensor变量,减少Worker同步更新的通讯压力,减少更新阻塞,达到更平滑的梯度更新效果。整体下来,对于30亿左右的样本量、上亿级别的特征维度,一轮迭代大概在半小时内完成。适当的增加并行计算的资源,可以达到分钟级的训练任务。4.4 进一步改进优化目标NDCG的计算公式中,折损的权重是随着位置呈指数变化的。然而实际曝光点击率随位置变化的曲线与NDCG的理论折损值存在着较大的差异。对于移动端的场景来说,用户在下拉滑动列表进行浏览时,视觉的焦点会随着滑屏、翻页而发生变动。例如用户翻到第二页时,往往会重新聚焦,因此,会发现第二页头部的曝光点击率实际上是高于第一页尾部位置的。我们尝试了两种方案去微调NDCG中的指数位置折损:根据实际曝光点击率拟合折损曲线:根据实际统计到的曝光点击率数据,拟合公式替代NDCG中的指数折损公式,绘制的曲线如图12所示。计算Position Bias作为位置折损:Position Bias在业界有较多的讨论,其中7将用户点击商户的过程分为观察和点击两个步骤:a.用户需要首先看到该商户,而看到商户的概率取决于所在的位置;b.看到商户后点击商户的概率只与商户的相关性有关。步骤a计算的概率即为Position Bias,这块内容可以讨论的东西很多,这里不再详述。经过上述对NDCG计算改造训练出的LambdaDNN模型,相较Base树模型和Pointwise DNN模型,在业务指标上有了非常显著的提升。4.5 Lambda深度排序框架Lambda梯度除了与DNN网络相结合外,事实上可以与绝大部分常见的网络结构相结合。为了进一步学习到更多交叉特征,我们在LambdaDNN的基础上分别尝试了LambdaDeepFM和LambdaDCN网络;其中DCN网络是一种加入Cross的并行网络结构,交叉的网络每一层的输出特征与第一层的原始输入特征进行显性的两两交叉,相当于每一层学习特征交叉的映射去拟合层之间的残差。离线的对比实验表明,Lambda梯度与DCN网络结合之后充分发挥了DCN网络的特点,简洁的多项式交叉设计有效地提升模型的训练效果。NDCG指标对比效果如下图所示:5. 深度学习排序诊断系统深度学习排序模型虽然给业务指标带来了大幅度的提升,但由于深度学习模型的“黑盒属性”导致了巨大的解释性成本,也给搜索业务带来了一些问题:日常搜索Bad Case无法快速响应:搜索业务日常需要应对大量来自于用户、业务和老板们的“灵魂拷问”,“为何这个排序是这样的”,“为什么这家商户质量跟我差不多,但是会排在我的前面”。刚切换到深度学习排序模型的时候,我们对于这样的问题显得手足无措,需要花费大量的时间去定位问题。无法从Bad Case中学习总结规律持续优化:如果不明白为什么排序模型会得出一个很坏的排序结果,自然也无法定位模型到底出了什么问题,也就无法根据Bad Case总结规律,从而确定模型和特征将来的优化方向。模型和特征是否充分学习无从得知:新挖掘一些特征之后,通常我们会根据离线评测指标是否有提升决定特征是否上线。但是,即使一个有提升的特征,我们也无法知道这个特征是否性能足够好。例如,模型拟合的距离特征,会不会在特定的距离段出现距离越远反而打分越高的情况。这些问题都会潜在带来一些用户无法理解的排序结果。我们需要对深度排序模型清晰地诊断并解释。关于机器学习模型的可解释性研究,业界已经有了一些探索。Lime(Local Interpretable Model-Agnostic Explanations)是其中的一种,如下图所示:通过对单个样本的特征生成扰动产生近邻样本,观察模型的预测行为。根据这些扰动的数据点距离原始数据的距离分配权重,基于它们学习得到一个可解释的模型和预测结果[5]。举个例子,如果需要解释一个情感分类模型是如何预测“我讨厌这部电影”为负面情感的,我们通过丢掉部分词或者乱序构造一些样本预测情感,最终会发现,决定“我讨厌这部电影”为负面情感的是因为“讨厌”这个词。基于Lime解释器的思想,我们开发了一套深度模型解释器工具——雅典娜系统。目前雅典娜系统支持两种工作模式,Pairwise和Listwise模式:Pairwise模式用来解释同一个列表中两个结果之间的相对排序。通过对样本的特征进行重新赋值或者替换等操作,观察样本打分和排序位次的变化趋势,诊断出当前样本排序是否符合预期。如下图所示,通过右侧的特征位次面板可以快速诊断出为什么“南京大牌档”的排序比“金时代顺风港湾”要更靠前。第一行的特征位次信息显示,若将“金时代顺风港湾”的1.3km的距离特征用“南京大牌档”的0.2km的距离特征进行替换,排序位次将上升10位;由此得出,“南京大牌档”排在前面的决定性因素是因为距离近。Listwise模式与Lime的工作模式基本类似,通过整个列表的样本生成扰动样本,训练线性分类器模型输出特征重要度,从而达到对模型进行解释的目的。6. 总结与展望2018年下半年,点评搜索完成了从树模型到大规模深度学习排序模型的全面升级。团队在深度学习特征工程、模型结构、优化目标以及工程实践上都进行了一些探索,在核心指标上取得了较为显著的收益。当然,未来依然有不少可以探索的点。在特征层面,大量知识图谱提供的标签信息尚未充分挖掘。从使用方式上看,简单以文本标签的形式接入,损失了知识图谱的结构信息,因此,Graph Embedding也是未来需要尝试的方向。同时团队也会利用BERT在Query和商户文本的深层语义表达上做一些工作。模型结构层面,目前线上依然以全连接的DNN网络结构为主,但DNN网络结构在低秩数据的学习上不如DeepFM和DCN。目前LambdaDeepFM和LambdaDCN在离线上已经取得了收益,未来会在网络结构上做进一步优化。在模型优化目标上,Lambda Loss计算损失的时候,只会考虑Query内部有点击和无点击的样本对,大量无点击的Query被丢弃,同时,同一个用户短时间内在不同Query下的行为也包含着一些信息可以利用。因此,目前团队正在探索综合考虑Log Loss和Lambda Loss的模型,通过Multi-Task和按照不同维度Shuffle样本让模型充分学习,目前我们已经在线下取得了一些收益。最后,近期Google开源的TF Ranking提出的Groupwise模型也对我们有一些启发。目前绝大部分的Listwise方法只是体现在模型训练阶段,在打分预测阶段依然是Pointwise的,即只会考虑当前商户相关的特征,而不会考虑列表上下文的结果,未来我们也会在这个方向上进行一些探索。参考资料美团大脑:知识图谱的建模方法及其应用Wide & Deep Learning for Recommender SystemsDeep Residual Learning for Image RecognitionAttention Is All You NeedLocal Interpretable Model-Agnostic Explanations: LIMEFrom RankNet to LambdaRank to LambdaMART: An OverviewA Novel Algorithm for Unbiased Learning to RankUnbiased Learning-to-Rank with Biased FeedbackReal-time Personalization using Embeddings for Search Ranking at Airbnb作者简介非易,2016年加入美团点评,高级算法工程师,目前主要负责点评搜索核心排序层的研发工作。祝升,2016年加入美团点评,高级算法工程师,目前负责点评搜索核心排序层的研发工作。汤彪,2013年加入美团点评,高级算法专家,点评平台搜索技术负责人,致力于深层次查询理解和大规模深度学习排序的技术落地。张弓,2012年加入美团点评,美团点评研究员。目前主要负责点评搜索业务演进,及集团搜索公共服务平台建设。仲远,博士,美团AI平台部NLP中心负责人,点评搜索智能中心负责人。在国际顶级学术会议发表论文30余篇,获得ICDE 2015最佳论文奖,并是ACL 2016 Tutorial “Understanding Short Texts”主讲人,出版学术专著3部,获得美国专利5项。此前,博士曾担任微软亚洲研究院主管研究员,以及美国Facebook公司Research Scientist。曾负责微软研究院知识图谱、对话机器人项目和Facebook产品级NLP Service。

January 22, 2019 · 1 min · jiezi

人人都可以做深度学习应用:入门篇

本文由云+社区发表作者:徐汉彬一、人工智能和新科技革命2017年围棋界发生了一件比较重要事,Master(Alphago)以60连胜横扫天下,击败各路世界冠军,人工智能以气势如虹的姿态出现在我们人类的面前。围棋曾经一度被称为“人类智慧的堡垒”,如今,这座堡垒也随之成为过去。从2016年三月份AlphaGo击败李世石开始,AI全面进入我们大众的视野,对于它的讨论变得更为火热起来,整个业界普遍认为,它很可能带来下一次科技革命,并且,在未来可预见的10多年里,深刻得改变我们的生活。其实,AI除了可以做我们熟知的人脸、语音等识别之外,它可以做蛮多有趣的事情。例如,让AI学习大量古诗之后写古诗,并且可以写出质量非常不错的古诗。又或者,将两部设计造型不同的汽车进行融合,形成全新一种设计风格的新汽车造型。还有,之前大家在朋友圈里可能看过的,将相片转换成对应的艺术风格的画作。当前,人工智能已经在图像、语音等多个领域的技术上,取得了全面的突破。与此同时,另外一个问题随之而来,如果这一轮的AI浪潮真的将会掀起新的科技革命,那么在可预见的未来,我们整个互联网都将发生翻天覆地的变化,深刻影响我们的生活。那么作为普通业务开发工程师的我,又应该以何种态度和方式应对这场时代洪流的冲击呢?在回答这个问题之前,我们先一起看看上一轮由计算机信息技术引领的科技革命中,过去30多年中国程序员的角色变化:通过上图可以简总结:编程技术在不断地发展并且走向普及,从最开始掌握在科学家和专家学者手中的技能,逐渐发展为一门大众技能。换而言之,我们公司内很多资深的工程师,如果带着今天对编程和计算机的理解和理念回到1980年,那么他无疑就是那个时代的计算机专家。如果这一轮AI浪潮真的会带来新的一轮科技革命,那么我们相信,它也会遵循类似的发展轨迹,逐步发展和走向普及。如果基于这个理解,或许,我们可以通过积极学习,争取成为第一代AI工程师。二、深度学习技术这一轮AI的技术突破,主要源于深度学习技术,而关于AI和深度学习的发展历史我们这里不重复讲述,可自行查阅。我用了一个多月的业务时间,去了解和学习了深度学习技术,在这里,我尝试以一名业务开发工程师的视角,以尽量容易让大家理解的方式一起探讨下深度学习的原理,尽管,受限于我个人的技术水平和掌握程度,未必完全准确。1. 人的智能和神经元人类智能最重要的部分是大脑,大脑虽然复杂,它的组成单元却是相对简单的,大脑皮层以及整个神经系统,是由神经元细胞组成的。而一个神经元细胞,由树突和轴突组成,它们分别代表输入和输出。连在细胞膜上的分叉结构叫树突,是输入,那根长长的“尾巴”叫轴突,是输出。神经元输出的有电信号和化学信号,最主要的是沿着轴突细胞膜表面传播的一个电脉冲。忽略掉各种细节,神经元,就是一个积累了足够的输入,就产生一次输出(兴奋)的相对简单的装置。树突和轴突都有大量的分支,轴突的末端通常连接到其他细胞的树突上,连接点上是一个叫“突触”的结构。一个神经元的输出通过突触传递给成千上万个下游的神经元,神经元可以调整突触的结合强度,并且,有的突触是促进下游细胞的兴奋,有的是则是抑制。一个神经元有成千上万个上游神经元,积累它们的输入,产生输出。人脑有1000亿个神经元,1000万亿个突触,它们组成人脑中庞大的神经网络,最终产生的结果即是人的智能。2. 人工神经元和神经网络一个神经元的结构相对来说是比较简单的,于是,科学家们就思考,我们的AI是否可以从中获得借鉴?神经元接受激励,输出一个响应的方式,同计算机中的输入输出非常类似,看起来简直就是量身定做的,刚好可以用一个函数来模拟。通过借鉴和参考神经元的机制,科学家们模拟出了人工神经元和人工神经网络。当然,通过上述这个抽象的描述和图,比较难让大家理解它的机制和原理。我们以“房屋价格测算”作为例子,一起来看看:一套房子的价格,会受到很多因素的影响,例如地段、朝向、房龄、面积、银行利率等等,这些因素如果细分,可能会有几十个。一般在深度学习模型里,这些影响结果的因素我们称之为特征。我们先假设一种极端的场景,例如影响价格的特征只有一种,就是房子面积。于是我们收集一批相关的数据,例如,50平米50万、93平米95万等一系列样本数据,如果将这些样本数据放到而为坐标里看,则如下图:然后,正如我们前面所说的,我们尝试用一个“函数”去拟合这个输入(面积x)和输出(价格y),简而言之,我们就是要通过一条直线或者曲线将这些点“拟合”起来。假设情况也比较极端,这些点刚好可以用一条“直线”拟合(真实情况通常不会是直线),如下图:那么我们的函数是一个一次元方程f(x) = ax +b,当然,如果是曲线的话,我们得到的将是多次元方程。我们获得这个f(x) = ax +b的函数之后,接下来就可以做房价“预测”,例如,我们可以计算一个我们从未看见的面积案例81.5平方米,它究竟是多少钱?这个新的样本案例,可以通过直线找到对应的点(黄色的点),如图下:粗略的理解,上面就是AI的概括性的运作方式。这一切似乎显得过于简单了?当然不会,因为,我们前面提到,影响房价其实远不止一个特征,而是有几十个,这样问题就比较复杂了,接下来,这里则要继续介绍深度学习模型的训练方式。这部分内容相对复杂一点,我尽量以业务工程师的视角来做一个粗略而简单的阐述。3. 深度学习模型的训练方式当有好几十个特征共同影响价格的时候,自然就会涉及权重分配的问题,例如有一些对房价是主要正权重的,例如地段、面积等,也有一些是负权重的,例如房龄等。(1)初始化权重计算那么,第一个步其实是给这些特征加一个权重值,但是,最开始我们根本不知道这些权重值是多少?怎么办呢?不管那么多了,先给它们随机赋值吧。随机赋值,最终计算出来的估算房价肯定是不准确的,例如,它可能将价值100万的房子,计算成了10万。(2)损失函数因为现在模型的估值和实际估值差距比较大,于是,我们需要引入一个评估“不准确”程度的衡量角色,也就是损失(loss)函数,它是衡量模型估算值和真实值差距的标准,损失函数越小,则模型的估算值和真实值的察觉越小,而我们的根本目的,就是降低这个损失函数。让刚刚的房子特征的模型估算值,逼近100万的估算结果。(3)模型调整通过梯度下降和反向传播,计算出朝着降低损失函数的方向调整权重参数。举一个不恰当的比喻,我们给面积增加一些权重,然后给房子朝向减少一些权重(实际计算方式,并非针对单个个例特征的调整),然后损失函数就变小了。(4)循环迭代调整了模型的权重之后,就可以又重新取一批新的样本数据,重复前面的步骤,经过几十万次甚至更多的训练次数,最终估算模型的估算值逼近了真实值结果,这个模型的则是我们要的“函数”。为了让大家更容易理解和直观,采用的例子比较粗略,并且讲述深度学习模型的训练过程,中间省略了比较多的细节。讲完了原理,那么我们就开始讲讲如何学习和搭建demo。三、深度学习环境搭建在2个月前,人工智能对我来说,只是一个高大上的概念。但是,经过一个多月的业余时间的认真学习,我发现还是能够学到一些东西,并且跑一些demo和应用出来的。1. 学习的提前准备(1)部分数学内容的复习,高中数学、概率、线性代数等部分内容。(累计花费了10个小时,挑了关键的点看了下,其实还是不太够,只能让自己看公式的时候,相对没有那么懵)(2)Python基础语法学习。(花费了3个小时左右,我以前从未写过Python,因为后面Google的TensorFlow框架的使用是基于Python的)(3)Google的TensorFlow深度学习开源框架。(花费了10多个小时去看)数学基础好或者前期先不关注原理的同学,数学部分不看也可以开始做,全凭个人选择。2. Google的TensorFlow开源深度学习框架深度学习框架,我们可以粗略的理解为是一个“数学函数”集合和AI训练学习的执行框架。通过它,我们能够更好的将AI的模型运行和维护起来。深度学习的框架有各种各样的版本(Caffe、Torch、Theano等等),我只接触了Google的TensorFlow,因此,后面的内容都是基于TensorFlow展开的,它的详细介绍这里不展开讲述,建议直接进入官网查看。非常令人庆幸的是TensorFlow比较早就有中文社区了,尽管里面的内容有一点老,搭建环境方面有一些坑,但是已经属于为数不多的中文文档了,大家且看且珍惜。TensorFlow 的中文社区TensorFlow 的英文社区3. TensorFlow环境搭建环境搭建本身并不复杂,主要解决相关的依赖。但是,基础库的依赖可以带来很多问题,因此,建议尽量一步到位,会简单很多。(1)操作系统我搭建环境使用的机器是腾讯云上的机器,软件环境如下:操作系统:CentOS 7.2 64位(GCC 4.8.5)因为这个框架依赖于python2.7和glibc 2.17。比较旧的版本的CentOS一般都是python2.6以及版本比较低的glibc,会产生比较的多基础库依赖问题。而且,glibc作为Linux的底层库,牵一发动全身,直接对它升级是比较复杂,很可能会带来更多的环境异常问题。(2)软件环境我目前安装的Python版本是python-2.7.5,建议可以采用yum install python的方式安装相关的原来软件。然后,再安装 python内的组件包管理器pip,安装好pip之后,接下来的其他软件的安装就相对比较简单了。例如安装TensorFlow,可通过如下一句命令完成(它会自动帮忙解决一些库依赖问题):pip install -U tensorflow这里需要特别注意的是,不要按照TensorFlow的中文社区的指引去安装,因为它会安装一个非常老的版本(0.5.0),用这个版本跑很多demo都会遇到问题的。而实际上,目前通过上述提供的命令安装,是tensorflow (1.0.0)的版本了。Python(2.7.5)下的其他需要安装的关键组件:tensorflow (0.12.1),深度学习的核心框架image (1.5.5),图像处理相关,部分例子会用到PIL (1.1.7),图像处理相关,部分例子会用到除此之后,当然还有另外的一些依赖组件,通过pip list命令可以查看我们安装的python组件:appdirs (1.4.0)backports.ssl-match-hostname (3.4.0.2)chardet (2.2.1)configobj (4.7.2)decorator (3.4.0)Django (1.10.4)funcsigs (1.0.2)image (1.5.5)iniparse (0.4)kitchen (1.1.1)langtable (0.0.31)mock (2.0.0)numpy (1.12.0)packaging (16.8)pbr (1.10.0)perf (0.1)PIL (1.1.7)Pillow (3.4.2)pip (9.0.1)protobuf (3.2.0)pycurl (7.19.0)pygobject (3.14.0)pygpgme (0.3)pyliblzma (0.5.3)pyparsing (2.1.10)python-augeas (0.5.0)python-dmidecode (3.10.13)pyudev (0.15)pyxattr (0.5.1)setuptools (34.2.0)six (1.10.0)slip (0.4.0)slip.dbus (0.4.0)tensorflow (1.0.0)urlgrabber (3.10)wheel (0.29.0)yum-langpacks (0.4.2)yum-metadata-parser (1.1.4)按照上述提供的来搭建系统,可以规避不少的环境问题。搭建环境的过程中,我遇到不少问题。例如:在跑官方的例子时的某个报错,AttributeError: ‘module’ object has no attribute ‘gfile’,就是因为安装的TensorFlow的版本比较老,缺少gfile模块导致的。而且,还有各种各样的。(不要问我是怎么知道的,说多了都是泪啊~)更详细的安装说明:Installing TensorFlow on Ubuntu(3)TensorFlow环境测试运行测试是否安装成功,可以采用官方的提供的一个短小的例子,demo生成了一些三维数据, 然后用一个平面拟合它们(官网的例子采用的初始化变量的函数是initialize_all_variables,该函数在新版本里已经被废弃了):#!/usr/bin/python#coding=utf-8import tensorflow as tfimport numpy as np# 使用 NumPy 生成假数据(phony data), 总共 100 个点.x_data = np.float32(np.random.rand(2, 100)) # 随机输入y_data = np.dot([0.100, 0.200], x_data) + 0.300# 构造一个线性模型# b = tf.Variable(tf.zeros([1]))W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))y = tf.matmul(W, x_data) + b# 最小化方差loss = tf.reduce_mean(tf.square(y - y_data))optimizer = tf.train.GradientDescentOptimizer(0.5)train = optimizer.minimize(loss)# 初始化变量,旧函数(initialize_all_variables)已经被废弃,替换为新函数init = tf.global_variables_initializer()# 启动图 (graph)sess = tf.Session()sess.run(init)# 拟合平面for step in xrange(0, 201): sess.run(train) if step % 20 == 0: print step, sess.run(W), sess.run(b)# 得到最佳拟合结果 W: [[0.100 0.200]], b: [0.300]运行的结果类似如下:经过200次的训练,模型的参数逐渐逼近最佳拟合的结果(W: [[0.100 0.200]], b: [0.300]),另外,我们也可以从代码的“风格”中,了解到框架样本训练的基本运行方式。虽然,官方的教程后续会涉及越来越多更复杂的例子,但从整体上看,也是类似的模式。步骤划分准备数据:获得有标签的样本数据(带标签的训练数据称为有监督学习);设置模型:先构建好需要使用的训练模型,可供选择的机器学习方法其实也挺多的,换而言之就是一堆数学函数的集合; 损失函数和优化方式:衡量模型计算结果和真实标签值的差距;真实训练运算:训练之前构造好的模型,让程序通过循环训练和学习,获得最终我们需要的结果“参数”;验证结果:采用之前模型没有训练过的测试集数据,去验证模型的准确率。其中,TensorFlow为了基于python实现高效的数学计算,通常会使用到一些基础的函数库,例如Numpy(采用外部底层语言实现),但是,从外部计算切回到python也是存在开销的,尤其是在几万几十万次的训练过程。因此,Tensorflow不单独地运行单一的函数计算,而是先用图描述一系列可交互的计算操作流程,然后全部一次性提交到外部运行(在其他机器学习的库里,也是类似的实现)。所以,上述流程图中,蓝色部分都只是设置了“计算操作流程”,而绿色部分开始才是真正的提交数据给到底层库进行实际运算,而且,每次训练一般是批量执行一批数据的。此文已由腾讯云+社区在各渠道发布获取更多新鲜技术干货,可以关注我们腾讯云技术社区-云加社区官方号及知乎机构号 ...

January 21, 2019 · 1 min · jiezi

Euler 今日问世!国内首个工业级的图深度学习开源框架,阿里妈妈造

阿里妹导读:千呼万唤始出来!阿里妈妈正式公布重磅开源项目——图深度学习框架Euler。这是国内首个在核心业务大规模应用后开源的图深度学习框架。此次开源,Euler内置了大量的算法供用户直接使用,相关代码已经可在GitHub上进行下载。图学习和深度学习都是人工智能的一个分支,作为阿里巴巴旗下的大数据营销平台,阿里妈妈创新性地将图学习与深度学习进行结合,推出了Euler,可帮助大幅度提升营销效率。Euler已在阿里妈妈核心业务场景进行了锤炼和验证,同时,在金融、电信、医疗等涉及到复杂网络分析的场景中也具有很高的应用价值。例如,用户可以利用Euler对基于用户交易等金融数据构建的复杂异构图进行学习与推理,进而应用于金融反欺诈等场景。下面让我们一起走进Euler的世界。Euler 开源地址 : https://github.com/alibaba/euler1. 概述过去几年随着数据规模和硬件计算力的迅速增长,深度学习技术在工业界被广泛应用并产生了巨大的技术红利。当前应用已经相对成熟,下一步的技术红利在哪里还在积极探索之中。图神经网络将端到端学习与归纳推理相结合,有望解决深度学习无法处理的关系推理、可解释性等一系列问题。对结构知识的表达、计算和组合泛化是实现具备human-like AI的关键,图神经网络有希望在这些方面形成突破,使得机器能力进一步提升,因此对图神经网络的深入应用有希望形成下一波技术红利。图作为表达能力很强的通用的数据结构,可以用来刻画现实世界中的很多问题,例如社交场景的用户网络、电商场景的用户和商品网络、电信场景的通信网络、金融场景的交易网络和医疗场景的药物分子网络等等。相比文本、语音和图像领域的数据比较容易处理成欧式空间的Grid-like类型,适合现有的深度学习模型处理,图是一种非欧空间下的数据,并不能直接应用现有方法,需要专门设计的图神经网络系统。1.1Euler的核心能力1)大规模图的分布式学习工业界的图往往具有数十亿节点和数百亿边,有些场景甚至可以到数百亿节点和数千亿边,在这样规模的图上单机训练是不可行的。Euler支持图分割和高效稳定的分布式训练,可以轻松支撑数十亿点、数百亿边的计算规模。2)支持复杂异构图的表征工业界的图关系大都错综复杂,体现在节点异构、边关系异构,另外节点和边上可能有非常丰富的属性,这使得一些常见的图神经网络很难学到有效的表达。Euler在图结构存储和图计算的抽象上均良好的支持异构点、异构边类型的操作,并支持丰富的异构属性,可以很容易的在图学习算法中进行异构图的表征学习。3)图学习与深度学习的结合工业界有很多经典场景,例如搜索/推荐/广告场景,传统的深度学习方法有不错效果,如何把图学习和传统方法结合起来,进一步提升模型能力是很值得探索的。Euler支持基于深度学习样本的mini-batch训练,把图表征直接输入到深度学习网络中联合训练。4)分层抽象与灵活扩展Euler系统抽象为图引擎层、图操作算子层、算法实现层三个层次,可以快速地在高层扩展一个图学习算法。实际上,Euler也内置了大量的算法实现供大家直接使用。1.2 Euler内置的算法实现考虑到框架的易用性,我们内置了多种知名算法以及几种我们内部的创新算法。所有实现,我们仔细进行了测试,保证了算法运行效率,且算法效果与原论文对齐。用户无需进行开发,注入数据到平台后,可以直接使用。我们内置的算法列表见下表。有关我们内部算法的详细信息请见2.3节。2. 系统设计Euler系统整体可以分为三层:最底层的分布式图引擎,中间层图语义的算子,高层的图表示学习算法。下边我们分开描述各个层次的核心功能。2.1分布式图引擎为了支持我们的业务,我们不仅面临超大规模图存储与计算的挑战,还需要处理由多种不同类型的点,边及其属性构成异构图的复杂性。我们的分布式图引擎针对海量图存储,分布式并行图计算及异构图进行了优化设计,确保了工业场景下的有效应用。首先为了存储超大规模图(数十亿点,数百亿边),Euler必须突破单机的限制,从而采用了分布式的存储架构。在图加载时,整张图在引擎内部被切分为多个子图,每个计算节点被分配1个或几个子图进行加载。为了充分利用各个计算节点的能力,在进行图的操作时,顶层操作被分解为多个对子图的操作由各个节点并行执行。这样随着更多节点的加入,我们可以得到更好的服务能力。其次,我们引入了多replica的支持。从而用户可以灵活平衡shard与replica的数量,取得更佳的服务能力。最后,我们针对图表示学习优化了底层的图存储数据结构与操作算法,单机的图操作性能获得了数倍的提升。多种不同类型的边,点与属性所组成的异构图,对很多复杂的业务场景必不可少。为了支持异构图计算能力,底层存储按照不同的节点与边的类型分别组织。这样我们可以高效支持异构的图操作。2.2中间图操作算子由于图学习算法的多样性以及业务的复杂性,固定的某几种甚至几十种算法实现无法满足客户的所有需求。所以在Euler设计中,我们围绕底层系统的核心能力着重设计了灵活强大的图操作算子,且所有算子均支持异构图操作语义。用户可以利用它来快速搭建自己的算法变体,满足独特的业务需求。首先,Euler分布式图引擎提供了C++的API来提供所有图操作。基于这个API,我们可以方便的基于某个深度学习框架添加图操作的算子,从而利用Euler C++接口访问底层图引擎的能力。我们支持广泛使用的深度学习框架,比如阿里巴巴的X-DeepLearning与流行的TensorFlow。后继我们也会考虑支持其它的深度学习框架,比如PyTorch。利用灵活的图操作算子,机器学习框架可以在每个mini-batch与Euler交互,动态扩充与组织训练样本。这样,Euler不仅支持传统的以图为中心的学习模式,且可以把图学习的能力注入传统的学习任务,实现端到端训练。按照功能分类,我们的核心系统提供的API可以分类如下:全局带权采样点和边的能力。主要用于mini-batch样本的随机生成以及Negative Sampling。基于给定节点的邻居操作。这个是图计算的核心能力包括邻居带权采样,取Top权重的邻居等。点/边的属性查找。这个能力使得算法可以使用更丰富的特征,而不仅限于点/边的ID特征。2.3高层算法实现如1.2节所述,除了LINE算法以外,我们实现的算法可以分为随机游走与邻居汇聚两大类算法。有关外部算法的详细信息,请参见1.2节提供的论文链接。下面我们详细介绍内部的三个创新算法,相关论文的链接我们会在github上给出。Scalable-GCN它是一种高效的GCN训练算法。GCN以及更一般的Graph Neural Network (GNN)类的方法由于能有效的提取图结构信息,在许多任务上均取得了超过以往方法的效果。但是GCN的模型会引入巨大的计算量,导致模型的训练时间不可接受。Scalable-GCN在保证优秀效果的前提下,把mini-batch GCN的计算复杂度从层数的指数函数压到线性。这使得在阿里妈妈的海量数据下应用三层GCN成为可能,广告匹配的效果获得了显著提升。LsHNELsHNE是我们结合阿里妈妈搜索广告场景创新地提出一种无监督的大规模异构网络embedding学习方法。区别于DeepWalk类算法,LsHNE的特点包括:a) 采用深度神经网络学习表达,可以有效融合Attribute信息;b)考虑embedding表示的距离敏感需求,提出两个负采样原则:分布一致性原则和弱相关性原则;c)支持异构网络。LasGNNLasGNN是一种半监督的大规模异构图卷积神经网络学习方法, 它有效融合了图结构知识信息和海量用户行为信息,大幅提升了模型精度,是工业界广告场景下首次应用半监督图方法。该方法有多处创新,例如将metapath的思想应用于图卷积网络中,并提出了metapathGCN模型,有效解决了异构网络的卷积问题;提出了metapathSAGE模型,在模型中我们设计高效的邻居采样的方法,使得大规模的多层邻居卷积成为可能。3. 应用实例Euler平台已经在阿里妈妈搜索广告的多个场景下广泛实用,并取得了出色的业务效果,例如检索匹配场景、CTR预估场景、营销工具场景和反作弊场景等。我们以匹配场景的为例来看下Euler的应用。广告匹配的任务是给定用户搜索请求,匹配模块通过理解用户意图,快速准确地从海量广告中找到高质量的小规模候选广告集,输送给下游的排序模块进行排序。我们首先使用一些传统的挖掘算法,从用户行为日志、内容属性等维度挖掘出Query(查询词), Item(商品)和Ad(广告)的多种关系,然后利用Euler平台的LsHNE方法学习图中节点的embedding,这里节点embedding后的空间距离刻画了原来图中的关系,对于在线过来的请求通过计算用户查询词向量、前置行为中节点向量和广告节点向量之间的距离进行高效的向量化最近邻检索,可以快速匹配到符合用户意图的广告。图2展示了LsHNE方法的离线和在线流程。具体图3展示了样本构造和网络结构示意。本文作者:让你久等了阅读原文本文来自云栖社区合作伙伴“阿里技术”,如需转载请联系原作者。

January 21, 2019 · 1 min · jiezi

使用DeepLab进行语义分割

介绍DeepLab是谷歌使用tensorflow基于CNN开发的语义分割模型,至今已更新4个版本。最新版本是DeepLabv3+,在此模型中进一步将深度可分离卷积应用到孔空间金字塔池化和解码器模块,从而形成更快,更强大的语义分割编码器-解码器网络。本文从官方案例出发,介绍如何训练以及使用DeepLabv3+模型。模型安装1,下载tensorflow model,然后将解压后的文件重命名为”models“并移动到tensorflow文件夹下。2,添加环境变量cd /anaconda3/lib/python3.6/site-packages/tensorflow/models/researchexport PYTHONPATH=$PYTHONPATH:pwd:pwd/slim3,测试是否安装成功cd /anaconda3/lib/python3.6/site-packages/tensorflow/models/researchpython deeplab/model_test.py结果出现如下错误:解决方法如下:准备数据下载数据:cd /anaconda3/lib/python3.6/site-packages/tensorflow/models/research/deeplab/datasets/sh download_and_convert_voc2012.sh具体执行步骤:下载并解压VOC2012数据集移除colormap在数据集中创建TFRecord文件下载预训练模型官方提供了多种模型,可以根据自己的实际需求下载安装。使用PASCAL VOC2012数据集训练文件结构:tensorflow deeplab文件夹:训练:cd /anaconda3/lib/python3.6/site-packages/tensorflow/models/research填写相关路径,执行训练python deeplab/train.py \ –logtostderr \ –training_number_of_steps=30000 \ –train_split=“train” \ –model_variant=“xception_65” \ –atrous_rates=6 \ –atrous_rates=12 \ –atrous_rates=18 \ –output_stride=16 \ –decoder_output_stride=4 \ –train_crop_size=513 \ –train_crop_size=513 \ –train_batch_size=1 \ –dataset=“pascal_voc_seg” \ –tf_initial_checkpoint=${PATH_TO_INITIAL_CHECKPOINT} \ –train_logdir=${PATH_TO_TRAIN_DIR} \ –dataset_dir=${PATH_TO_DATASET}PATH_TO_INITIAL_CHECKPOINT:初始checkpoint文件路径(迁移学习)PATH_TO_TRAIN_DIR:训练模型保存路径PATH_TO_DATASET:数据集路径需要注意的问题:当GPU显存不够,使用迁移学习方式进行训练并减少学习率大小,设置”fine_tune_batch_norm=False“当设置”output_stride=8“,”atrous_rates“取值区间应由[6,12,18]改为[12,24,36]。当不想使用解码器结构,需要注释掉”decoder_output_stride“。验证cd /anaconda3/lib/python3.6/site-packages/tensorflow/models/researchpython deeplab/eval.py \ –logtostderr \ –eval_split=“val” \ –model_variant=“xception_65” \ –atrous_rates=6 \ –atrous_rates=12 \ –atrous_rates=18 \ –output_stride=16 \ –decoder_output_stride=4 \ –eval_crop_size=513 \ –eval_crop_size=513 \ –dataset=“pascal_voc_seg” \ –checkpoint_dir=${PATH_TO_CHECKPOINT} \ –eval_logdir=${PATH_TO_EVAL_DIR} \ –dataset_dir=${PATH_TO_DATASET}PATH_TO_CHECKPOINT:训练阶段checkpoint文件路径PATH_TO_EVAL_DIR:评估模型保存路径PATH_TO_DATASET:数据集路径可视化模型输出cd /anaconda3/lib/python3.6/site-packages/tensorflow/models/researchpython deeplab/vis.py \ –logtostderr \ –vis_split=“val” \ –model_variant=“xception_65” \ –atrous_rates=6 \ –atrous_rates=12 \ –atrous_rates=18 \ –output_stride=16 \ –decoder_output_stride=4 \ –vis_crop_size=513 \ –vis_crop_size=513 \ –dataset=“pascal_voc_seg” \ –checkpoint_dir=${PATH_TO_CHECKPOINT} \ –vis_logdir=${PATH_TO_VIS_DIR} \ –dataset_dir=${PATH_TO_DATASET}PATH_TO_CHECKPOINT:训练阶段checkpoint文件路径PATH_TO_VIS_DIR:评估模型保存路径PATH_TO_DATASET:数据集路径需要注意的问题:当需要保存分割结果时,需要设置”also_save_raw_predictions = True“Tensorboardtensorboard –logdir=${PATH_TO_LOG_DIRECTORY}将同时显示”train“,”eval“,”vis“结果,如需要单独显示一类,可以指定显示类别,如:tensorboard –logdir train/对于voc2012这样的数据集,Tensorboard显示数据可能需要几分钟的时间。模型导出cd /anaconda3/lib/python3.6/site-packages/tensorflow/models/researchpython deeplab/export_model.py \ –logtostderr \ –checkpoint_path="${PATH_TO_CHECKPOINT}" \ –export_path="${PATH_TO_EXPORT_PD}" \ –model_variant=“xception_65” \ –atrous_rates=6 \ –atrous_rates=12 \ –atrous_rates=18 \ –output_stride=16 \ –decoder_output_stride=4 \ –num_classes=21 \ –crop_size=513 \ –crop_size=513 \ –inference_scales=1.0PATH_TO_CHECKPOINT:checkpoint文件路径PATH_TO_EXPORT_PD:导出PD文件路径(加后缀.pd)案例cd /anaconda3/lib/python3.6/site-packages/tensorflow/models/research/deeplabsh local_test.shGoogle Colab在线测试地址,可选择预训练模型,测试分割照片来查看模型输出结果。总结基于深度学习的语义分割与传统基于随机森林的方法相比有了很大的进步,虽然目前基于深度学习的方法有多种思路,不过基本都是基于全卷积(FCN)衍变而来。FCN将网络全连接层使用卷积替代,因此可以接受任意大小的输入并且针对下采样存在位置信息丢失等问题,采用转置卷积用于恢复图片尺寸,方便后续进行逐像素预测。DeepLab模型为了改善分割效果,使用atrous卷积(空洞卷积),ASPP,全连接条件随机场等技术。 ...

January 21, 2019 · 1 min · jiezi

深度学习入门:10门免费线上课程推荐

Dive into Deep Learning,深度学习一直在音视频业内也是非常受到关注的热点,这里推荐10个免费的优质线上课程。推荐大家开源项目Class Central,里面有31个在线课程(其中10个是完全免费的),涵盖了从深度学习的基础到今天最前沿的研究。在线深度学习课程Creative Applications of Deep Learning with TensorFlow ★★★★★将介绍深度学习的基本组成部分,它的含义,工作原理,以及开发构建各种算法所需的代码,如深度卷积网络,变分自动编码器,生成性对抗网络和循环神经网络。本课程的主要重点是不仅要了解如何构建这些算法的必要组件,还要了解如何将它们应用于探索创造性应用程序。提供免费和付费选项。这门课程的专业性和质量都非常好,被很多人强烈推荐。Neural Networks for Machine Learning多伦多大学★★★★★了解人工神经网络及其如何用于机器学习,应用于语音和对象识别,图像分割,建模语言和人体运动等。强调基本算法和获得所需的实用技巧他们运作良好。提供免费和付费选项。比较厉害的是里面的讲师,Geoffrey Hinton,80年代研究人工智能和神经网络的最重要和最有影响力的研究人员之一。他现在也与Google合作开展人工智能/深度学习工程。就是这个老爷爷,深度学习教父级别Practical Deep Learning For Coders, Part 1fast.ai★★★★☆课程为期7周,专门为一年编程经验以上的人设计,比较初级,帮你从0开始学习如何让GPU适合深度学习。免费的哟6.S191:深度学习简介麻省理工学院(MIT)★★★★课程为期1周,对深度学习方法做了介绍,包含了包括机器翻译,图像识别,游戏,图像生成等应用。MIT的课程,免费again6.S094:自动驾驶汽车的深度学习麻省理工学院(MIT)★★★★☆这门课程通过构建自动驾驶汽车的应用主题介绍深度学习的实践。为初学者开放,专为那些刚接触机器学习的人设计的,但资深人士也可以会从中获益,寻找深度学习方法及其应用的实用概述。免费again自然语言处理的深度学习牛津大学★★★★☆课程重点介绍使用递归神经网络分析和生成语音和文本的最新进展。介绍了相关机器学习模型的数学定义,并推导了相关的优化算法。由Phil Blunsom带领,并与DeepMind自然语言研究小组合作。免费哟CS224n: Natural Language Processing with Deep Learning 斯坦福大学这门课程全面介绍了应用于NLP的深度学习的前沿研究。免费CS231n: Convolutional Neural Networks for Visual Recognition斯坦福大学课程深入探讨深度学习架构的细节,重点是学习这些任务的端到端模型,尤其是图像分类。在为期10周的课程中,学生将学习如何实施,训练和调试他们自己的神经网络,并详细了解计算机视觉的前沿研究。最终任务将涉及训练数百万参数卷积神经网络并将其应用于最大图像分类数据集(ImageNet)。这门课程专注于教授如何设置图像识别问题,学习算法(例如反向传播),培训和微调网络的实用工程技巧,并指导学生完成动手作业和最终课程项目。斯坦福这两门课程都是在业内很受欢迎的。Machine Learning Nando de Freitas /University of British Columbia重点介绍了神经网络,反向传播,玻尔兹曼机器,自动编码器,卷积神经网络和递归神经网络的基本背景。它说明了深度学习如何影响我们对智能的理解并有助于智能机器的实际设计。Deep Learning Summer School 2015and2016受众是已经拥有机器学习基础知识(可能但不一定是深度学习)的研究生,工程师和研究人员,并希望更多地了解这一快速发展的研究领域。它不像传统的在线课程那样组织,但它的组织者(包括Bengio和LeCun等深度学习名人)和他们吸引的讲师使这个系列成为深度学习内容的金矿。免费哟~网易云信,你身边的即时通讯和音视频技术专家,了解我们,请戳网易云信官网想要阅读更多行业洞察和技术干货,请关注网易云信博客更多精彩内容,关注网易云信

January 21, 2019 · 1 min · jiezi