程序员的AI书:从代码开始(txt+pdf+epub+mobi电子书下载)


发布时间:2020-10-10 14:38:31

点击下载

作者:张力柯

出版社:电子工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

程序员的AI书:从代码开始

程序员的AI书:从代码开始试读:

程序员的AI书从代码开始张力柯 潘 晖 编著内容简介

随着AI技术的普及,如何快速理解、掌握并应用AI技术,成为绝大多数程序员亟需解决的问题。本书基于Keras框架并以代码实现为核心,详细解答程序员学习AI算法时的常见问题,对机器学习、深度神经网络等概念在实际项目中的应用建立清晰的逻辑体系。

本书分为上下两篇,上篇(第1~4章)可帮助读者理解并独立开发较简单的机器学习应用,下篇(第5~9章)则聚焦于AI技术的三大热点领域:推荐系统、自然语言处理(NLP)及图像处理。其中,第1章通过具体实例对Keras的机器学习实现进行快速介绍并给出整体概念;第2章从简单的神经元开始,以实际问题和代码实现为引导,逐步过渡到多层神经网络的具体实现上,从代码层面讲解神经网络的工作模式;第3章讲解Keras的核心概念和使用方法,帮助读者快速入门Keras;第4章讲解机器学习中的常见概念、定义及算法;第5章介绍推荐系统的常见方案,包括协同过滤的不同实现及Wide&Deep模型等;第6章讲解循环神经网络(RNN)的原理及Seq2Seq、Attention等技术在自然语言处理中的应用;第7~8章针对图像处理的分类及目标识别进行深度讨论,从代码层面分析Faster RCNN及YOLO v3这两种典型识别算法;第9章针对AI模型的工程部署问题,引入TensorFlow Serving并进行介绍。

本书主要面向希望学习AI开发或者转型算法的程序员,也可以作为Keras教材,帮助读者学习Keras在不同领域的具体应用。

未经许可,不得以任何方式复制或抄袭本书之部分或全部内容。

版权所有,侵权必究。

图书在版编目(CIP)数据

程序员的AI书:从代码开始 / 张力柯,潘晖编著.—北京:电子工业出版社,2020.2

ISBN 978-7-121-38270-3

Ⅰ.①程… Ⅱ.①张…②潘… Ⅲ.①人工智能-程序设计 Ⅳ.①TP18

中国版本图书馆CIP数据核字(2020)第014136号

责任编辑:张国霞 特约编辑:顾慧芳

印  刷:三河市君旺印务有限公司

装  订:三河市君旺印务有限公司

出版发行:电子工业出版社

     北京市海淀区万寿路173信箱 邮编100036

开  本:787×980 1/16 印张:20 字数:430千字

版  次:2020年2月第1版

印  次:2020年2月第1次印刷

印  数:5000册 定价:109.00元

凡所购买电子工业出版社图书有缺损问题,请向购买书店调换。若书店售缺,请与本社发行部联系,联系及邮购电话:(010)88254888,88258888。

质量投诉请发邮件至zlts@phei.com.cn,盗版侵权举报请发邮件至dbqq@phei.com.cn。

本书咨询联系方式:010-51260888-819,faq@phei.com.cn。推荐序一

认识力柯兄多年,一直认为他是一员虎将——能用代码说话,便绝不打无谓的嘴仗;能用技术与产品直接证明,便绝不空谈“形式”和“主义”。这次,通过力柯兄写的这本书,一如既往地看到他“心有猛虎”的一面:直截了当、大开大合。

在机器学习或者说工业界AI火起来的这几年,程序员这一受众群体一直缺少优秀的教程。有些教程过于浅显,很难称其为“入门教程”,只能称其为科普书;有些教程则过于贴近理论推导,对夯实读者的数理基础大有裨益,也能给研究生提供参考,但对程序员来说,则理论有余而实践不足,常常令注重工程实践的他们一头雾水:毕竟不是每个程序员都有耐心、有必要一门一门地捡回微积分、概率统计、偏微分方程、线性代数和数值计算等基础学科的知识,再真正实现一个属于自己的模型。如何在数学理论和工程实践之间找到一个平衡点,让具有工程背景的广大读者从中获得实际的价值,而非进行简单的脑力或数学训练,这一直是我评价机器学习教程时最为看重的要素。现在,我有幸从力柯兄的成书中找到了这些要素,实乃幸事!

这是一本写给程序员看的机器学习指南。它有针对性地从程序员的视角切入(而非像市面上的大多数机器学习教程一样,从数学的角度切入),介绍了工业界流行的若干模型及应用场景,同时涵盖了神经网络的原理和基础实现、Keras库的使用方法和TensorFlow的部署方案,可谓有的放矢。另外,本书章节不多,却简短有力。这不是一本科普读物,不存在浅尝辄止;也不是一本百科全书,不存在天书符号。这是一本有代码的书,是一本谈工程实现的书。我认为,这正是机器学习领域所缺少的那一类教程。

本书的上篇,让我不由得想起多年前力柯兄刚从硅谷回国高就时,与我围绕“怎样的面试题对于机器学习程序员是合适的”这一话题展开的讨论。那时AI正在升温,无数有着各种背景、能力和水平的人都在尝试接触AI方面的内容,但对于人才的选拔和录用,却似乎没有一个行业内的公认标准和规范。力柯兄的面试题十分简单粗暴,要求面试者仅使用一些基础的Python库去实现一个深度神经网络。这听起来有点让人匪夷所思,但事后细想,却是大道至简。这可以让人抛去繁杂的模型,回归神经网络最本质的前向传播和反向传播,将一切都落实在代码层面。虽然需要运用的数学知识不过是一点高等数学的皮毛,却可以同时从工程和数学两个角度考察候选人的基本功。这几年间,机器学习和深度学习教程及相关公开课越来越多,我阅课无数,竟发现很少有一门课能够沉下心来,仔仔细细地告诉读者和学员,搭建和实现这些神经网络的基础元素从何而来,又为何如此。而本书的上篇,尤其是在第2章中,一丝不苟地介绍了神经元、激活函数和损失函数,从偏微分方程层面严谨地推导反向传播,又从代码层面给出了那道面试题的答案。这都让我不由得敬佩力柯兄在工程上的执着。本书的下篇,则是标准的深度学习入门。

至此,我不再“剧透”,因为当你从实战角度阅读这些章节时,会有一种不断发现珍宝的惊喜感,而我更愿意把这些“珍宝”留给本书的读者。周竟舸,Pinterest机器学习平台技术负责人2019年12月推荐序二

近十余年,计算机领域中令人瞩目的亮点就是以深度学习为代表的一系列突破。无论是人脸检测还是图像识别,抑或文本翻译或无人驾驶,这些在过去几十年里让计算机科学家苦苦思索却不能解的种种难题,在深度学习的帮助下,竟被一一攻克,这不能不说是人类科技史上一颗耀眼的明星。

AI技术的突飞猛进,却使传统程序员产生不少困惑:过去常用的数据结构、排序搜索、链表数组等,现在变成了模型、卷积、权重和激活函数……无论是要开发AI应用,还是和算法研究人员共同工作,他们都存在同一个问题:如何学习AI技术?如何理解AI算法人员常用的名词和概念?更重要的是,如何把AI相关的代码和自己的软件开发经验联系起来?

现在市面上已经有很多深度学习和机器学习教程了,其中也不乏从实例入手、以代码实现为重点的书籍,但并没有一本书真正地从程序员的视角来看待深度学习技术。或者,我们也可以这么说,大部分相关书籍的重点是讲解深度学习理论,所用的实例是解释深度学习理论的实际应用。尽管有不少书籍在讲解理论和代码时详尽而深入,却没有涉及核心问题:要解决这个问题,为什么非用深度学习或机器学习不可?没有这些方法就不能做吗?用深度学习处理该问题的优势是什么?是十全十美,还是存在问题?

打开本书,我惊喜地发现它并非像市面上的其他书籍那样,直接把各种新鲜概念放到读者面前并强迫他们接受。它一开始就没有在机器学习概念上过多纠缠,而是先快速展示了简短的AI实现代码的结构和流程,然后带出一些常常让初学者疑惑的问题,针对这些问题再带出新的内容。我们可以看到,本书每一章都用到了类似的形式:阐述一个领域中的实际问题,提出不同的解决方法,简要探讨不同的方法,找到人们难以解决的问题,然后解释机器学习或深度学习处理这些问题的原理。读者了解到的并非单纯的机器学习理论,而是不同领域的具体技术挑战和相关算法的解决方案,从而理解机器学习的真正意义。

必须要说的是,作者在美国工作多年,养成了求真务实和独立思考的习惯,我们从书中能感受到他独特的风格,并有愉悦的阅读体验。本书在理论讲解方面也没有概念堆砌的枯燥无味,作者常常加入一些对技术的调侃和个人见解,以供读者思考。在代码解析阶段,作者着眼于整体框架与流程,把重点放在理论中的网络结构如何在实际代码中实现,而不会浪费篇幅在代码的语言细节上。

阅读本书,不但是对不同领域AI开发的学习,也是一次以资深程序员的视角去审视相关代码实现的体验。本书无论是对于应用开发程序员,还是对于算法研究人员,都相当有价值,非常值得阅读。喻杰博士,华为智能车云首席技术官2019年12月推荐序三

随着AlphaGo在人机大战中一举成名,关于机器学习的研究开始备受人们关注。机器学习和神经网络已经被广泛应用于互联网的各个方面,例如搜索、广告、无人驾驶、智能家居,等等。AI井喷式发展的主要动力如下。

其一,数据的积累。各大IT公司都拥有了自己的数据平台,数据积累的速度越来越快。各大高校针对不同的机器学习任务,积累了多样化的数据集。

其二,计算机性能指数级的增长。从当初的CPU到GPU,再从GPU到专门为AI设计的芯片,都提供了强大而高效的并行计算能力,大大推动了AI算法的进步。

其三,AI理论及模型的突破,例如卷积网络、长短期记忆等。

其四,深度学习开源框架日趋完善。TensorFlow是当前领先的深度学习开源框架,越来越多的人在使用它从事计算机视觉、自然语言处理、语音识别和一般性的预测分析工作。TensorFlow集成的Keras是为人类而非机器设计的API,易于学习和使用。

这是一本非常适合程序员入门和实践深度学习的书,理论和实践并重,使用Keras作为机器学习框架,侧重于AI 算法实现。

本书以从代码出发,再回归AI相关原理为宗旨,深入浅出、循序渐进地讲解了Keras及常见的深度学习网络,还讲解了深度学习在不同领域的应用及模型的部署与服务。读者在一步步探索AI算法奥秘的同时,也在享受解决问题的喜悦和成就感,并开启深度学习之旅。

衷心地希望有志于AI学习的读者抓住机会,早做准备,成为AI时代的弄潮儿。王昀绩,Google AI高级研究员2019年12月上篇第1章 机器学习的Hello World

机器学习作为近年来的热点技术,不但是汇集传统统计学、数据挖掘、并行计算、大数据等多个领域的交叉学科,也对传统的编程开发方式形成了一定冲击,整个开发的模式、过程及思考角度与传统的代码实现有相当大的差别。从某个角度来说,很多软件工程师在接触机器学习时,所面临的最大困难并不是对其概念和原理无法理解,而是难以转换自己的编程思维方式,从传统的面向具体逻辑流程的实现,变为面向数据和结果拟合的实现。因此,我们在这里改变传统的机器学习入门方式,先从机器学习代码的开发和使用入手,让读者对如何用机器学习的方式解决问题有直观的了解。本章作为入门级的内容,内容精简。读者应备好电脑,尝试运行自己的第1个机器学习程序。1.1 机器学习简介

机器学习主要有三大类别:监督学习(Supervised Learning)、无监督学习(Unsupervised Learning)、增强学习(Reinforcement Learning),下面对这三大类别进行简要介绍。

1.监督学习

监督学习是机器学习中应用最广泛也最可靠的技术。简单来说,监督学习的目的就是通过标注好的数据进行模型训练,从而期望利用训练好的模型对新的数据进行预测或分类。在这里,“监督”(Supervised)这个词意味着我们已经有标注好的已知数据集。

监督学习的应用场景非常广泛,常见的垃圾邮件过滤、房价预测、图片分类等都是适合它的领域,但其最大弱点就是需要大量标注数据,前期投入成本极高。

2.无监督学习

相对于需要大量标注数据的监督学习,无监督学习无须标注数据就能达到某个目标。注意,并不是所有场景都适合采用无监督学习,无监督学习经常被用于以下两方面。

◎ 聚类(Clustering):在聚类场景下使用无监督学习的频率可能是最高的。例如给出一堆图片,把相似的图片划分在一起。我们既可以预设一个类别总数进行自动划分(即半监督学习,Semi-supervised);也可以预设一个差异阈值,然后对所有图片进行自动聚类。

◎ 降维(Dimensionality Reduction):在数据特征过多、维度过高时,我们通常需要把高维数据降到合理的低维空间处理,并期望保留最重要的特征数据。主成分分析(Principal Component Analysis,PCA)就是其中最为常见的算法应用。

3.增强学习

无论是监督学习还是无监督学习,其训练基础都来源于数据本身。而增强学习最大的特点就是需要与环境有某种互动关系,这也促使人们在增强学习的研究中利用类似电子游戏的环境来模拟互动并进行AI训练。例如,DeepMind在2015年提出的利用DQN学习ATARI游戏的操作,以及OpenAI的Gym等。

增强学习的实现和应用场景比较特殊,尽管某些大型公司已经在推荐系统、动态定价等场景中尝试应用增强学习,但仍只限于实验性质,有兴趣的读者可以自行阅读其他资料进行学习,在本书中不对增强学习进行讲解。1.2 机器学习应用的核心开发流程

我们经常听到机器学习的研究人员开口“特征”,闭口“模型”,也听过他们调侃自己是“调参”师,然而,他们口中的这些术语到底指什么呢?若想了解这些术语,就先要清楚机器学习应用开发的核心流程。

图1-1把机器学习应用的核心开发流程划分为4个阶段,实际上,基本上所有机器学习项目的开发流程都是按照这4个阶段来划分和实施的。图1-1 机器学习的基本流程

下面对图1-1所示的4个阶段进行解释。

1.数据预处理(Preprocessing)

机器学习的第1阶段就是处理原始数据。从图1-1可以看出,我们需要处理带有标签的原始数据,形成用于模型训练的训练数据集和用于验证模型效果的测试数据集,包含如下两项核心工作。(1)特征提取。我们要处理的原始数据往往是以多种形式存在的,可以是来自MySQL 数据库的不同字段,也可以是原始的文本文件或图像、视频、音频等多媒体文件。然而,绝大部分机器学习算法的输入通常是某种浮点数矩阵形式或者向量形式的。把这些多样化的原始数据转化为符合算法数据的数据格式,是工作的第1步,我们通常可以把这一步称为“特征提取”。而从原始数据中挑选出来进行转换,并最终用于机器学习的数值就被称为“特征值”。例如,我们要识别花的种类,从花的图片中将花瓣颜色、花瓣形状、花瓣长度、花瓣宽度、叶片长度、叶片形状等属性数值化,这些数值就被定义为花的“特征”。注意,我们在这里是通过经验去选取我们觉得重要且有用的特征值的,因为在现实场景下可能会有成百上千种数据类型(例如一个业务中所有数据表的字段)备选,我们不太可能将它们全部用于机器学习,必须有所取舍,这就是特征工程的目的。然而,依赖经验选择并不是100%可靠的。在实际工作中,我们需要和业务专家一起不断讨论和尝试验证,直到确认我们选取的特征值的确能达到业务要求。(2)数据清洗。有时,我们哪怕是把数据转化为符合算法输入的形式,也会出现很多问题,例如,需要输入的某些特征可能不存在、不同特征的数值区间差别太大、某些特征可能是文字形式等,这时我们需要根据情况处理这些不规范的特征值。例如,将不存在的特征设为0或取平均值,对文字形式的特征进行编码,或者对数值区间较大的特征进行归一化(Normalization)等。数据清洗的目的是让算法训练所用的数据集尽量理想化,不包含不必要的干扰数值,从而提高模型训练的精度。

在数据集处理完成后,我们通常需要把数据集划分为训练数据集和测试数据集,这样的划分通常是随机的,随机挑选 80%的数据用于训练,将剩下的 20%用于测试验证。数据集其实在不同的机器学习框架中均有对应的API进行快速划分,这里不做详述。

2.学习(Learning)

这个阶段也是我们常说的训练阶段。我们已经在数据预处理阶段构建了合适的数据集,在这个阶段就需要根据自己的最终目标选择合适的算法模型,并根据我们的数据集进行合理的参数设置,开始模型训练。

什么是模型训练?我们在中学都学过多元函数,例如:

其中,y 就是标签,在数据集中已经标注好;x、x、x就是前123面提到的特征值。我们可以这样描述:花的类别=a×花蕊颜色+ b×花瓣颜色 + c×叶片颜色

这里,y就是花的类别,x、x、x就分别是花蕊颜色、花瓣颜色123和叶片颜色。

假设这个公式正确,我们接下来需要做的就是通过训练集中的数据输入,把a、b、c反推出来。当然,一般来说我们不可能找到100%完美的a、b、c,使以上算法得到的结果和训练集中所有的输入都一致,所以我们只能让结果尽量接近原始数据,并设定损失函数(Loss Function),设法使整体误差最小。在实际场景中,我们通常使用MSE(Mean Squared Error,均方误差)作为损失函数的误差计算。

当然,上面的例子非常简单,所要推导的参数也不多。在实际的深度学习模型中,我们需要推导的参数是以万甚至百万为单位的,这些参数通常被称为“权重”(Weight)并被存为特定格式的文件(不同框架所存的权重文件格式各不相同)。我们将在第2章深入接触深度学习并了解其训练过程。

3.评价(Evaluation)

我们在学习阶段将误差降到足够小之后,就可以停止训练,将训练好的模型用在数据预处理阶段生成的测试数据集上验证效果。因为测试数据集的所有数据都没有在训练阶段出现过,所以我们可以把测试数据视为“新”数据,用来模拟真实环境的输入,从而预估模型被部署到真实环境后的效果。

4.预测(Prediction)

我们在评价阶段确认模型达到了预期的准确率和覆盖率(召回率)之后,就可以将模型部署上线。注意,在小规模研究中,我们可以直接使用训练后的模型;但在真正大流量的产品环境中,我们往往[4]需要使用专门的模型服务框架(如TensorFlow Serving)将模型转换为专有的格式,并在该框架下进行高效服务。我们将在第9章学习如何在TensorFlow Serving上进行模型的部署与验证。1.3 从代码开始“Talk is cheap, show me the code”这句话无论是对于程序开发还是对于机器学习都是适用的。对于一个软件工程师来说,原理、分析和推导都比不上一段真实的代码更容易让人理解,下面就让我们直接尝试用代码来解决问题吧。1.3.1 搭建环境

本节希望让读者尽快接触真实开发环境下的代码,因此将使用TensorFlow中的Keras作为开发框架(现在Keras已是TensorFlow的一部分)。此外,我们需要一些额外的Python包作为支持。我们选用了Python 3.7以上版本,并假设读者已经安装好Python 3.7。下面执行安装本章代码运行所需依赖库的命令:1.3.2 一段简单的代码

考虑一个简单的问题:对正负数分类,对正数返回1,对负数返回0。

这用传统的代码实现起来非常简单,如下所示:

但用机器学习该如何实现呢?

下面用TensorFlow自带的Keras实现对正负数分类:

我们看看这18行代码都做了什么。

第1~3行:引入依赖库TensorFlow和其自带的Keras相关库。

第5~8行:这4行建立了一个简单的两层神经网络模型。在第5行定义了一个Sequential类型的网络,顾名思义是按顺序层叠的网络。在第6行加入第1层网络,输入input_dim为1,意味着只有1个输入(因为我们只判断一个数字是否为正数);但是定义了8个输出(units=8),这个数字其实是随意定的,可以视为其中神经元的个数(我们将在第2章解释什么是神经元),一般神经元的个数越多,效果越好(训练时间也越长)。算法科研人员会耗费大量的时间来确定这些数字,以找到最佳的个数。第7行再叠加一层,接收前面的输出(8个),但作为最后一层,这次只定义一个输出(units=1),这个输出决定了最后的分类结果。第8行对整个模型进行最后的配置,选择mean_squared_error(平均方差)作为损失函数计算,选择随机梯度下降(Stochastic Gradient Descent,SGD)作为梯度优化方式。这里将不从理论角度解释随机梯度下降的原理,但在第2章中将通过代码来手工实现随机梯度下降。

第10~12行:设定了两组数据x和y作为训练集,其中,x包括10个正数,y包括对应的10个分类结果。可以看到,对于x中的每个正数,y中对应的值都是1.0,负数x[i]所对应的y[i]则是0。然后我们调用model.fit函数进行训练,设置epochs为10(训练10次),batch_size为4(每次都随机挑选4组数据)。

第14~18行:这里构建了4个输入数据进行测试并打印结果。我们构建了数组test_x,该数组包含4个整数,然后调用model.predict方法对test_x进行预测。在第17~18行将打印每个输入所对应的预测结果。

以上18行代码的运行结果如下:

可以看到,在最后的预测结果中,所有正数的预测值都非常接近1,所有负数的预测值都小于0.01。前面解释过,机器学习是一种概率预测,不可能完全精确,以上结果对正负数做了较为明确的划分,是可以接受的。

经过上面的代码实现,读者可能仍然对其中涉及的一些内容有些茫然,比如什么是梯度下降,神经元又是什么,什么叫加一层、减一层,具体的参数又是怎样训练的,等等,在第2~4章会详细解释这些内容。

上述代码是基于Keras实现的,Keras是机器学习研究主流的开发框架,封装了很多常见的算法和模型。第2章将抛开这些框架,用最基本的Python代码从最简单的神经网络开始,尝试实现上面的功能。1.4 本章小结

本章简明扼要地解释了机器学习的大致概念和主要实施流程,然后迅速进入实际代码阶段,说明了开发环境所需的工具,并通过一个简单的数字分类实例引入了简明的Keras代码实现,对其进行详细解释,让读者对机器学习的开发有一个初步的感性认识。

但是本章并没有解释任何原理如神经元、梯度下降、损失函数、激活函数等概念。第2章将手工进行代码实现,让读者对这些概念从软件工程师的角度去学习和思考。1.5 本章参考文献

[1] HBO “Silicon Valley”, https://en.wikipedia.org/wiki/Silicon_Valley_(TV_series)

[2] Google Deepmind, “Human Level control through deep reinforcement learning”, Nature, 2015

[3] OpenAI Gym, https://gym.openai.com/

[4] https://github.com /tensorflow/serving第2章 手工实现神经网络

第1章快速介绍了机器学习的基本概念和开发流程,并通过一段代码展示了如何用Keras机器学习框架实现简单的数字分类。

本章将抛开机器学习框架,用纯粹的Python代码实现简单的神经网络,并复现第1章中Keras代码的结果。本章以代码为主,理论为辅。读者一定要自行运行书中的代码,如果对部分内容不理解,则也不用担心,本章最后一个代码示例会解答所有问题。2.1 感知器2.1.1 从神经元到感知器

我们首先要了解神经网络的历史。

1943年,W.McCullock和W.Pitts发表了一篇讨论简单的人类大脑细胞的论文A Logical Calculus of the Ideas Immanent in Nervous [1]Activity ,在该论文中将Neuron定义为大脑中相互连接的神经细胞,用于处理和传递各种化学信号和生物电信号。在该论文中,这样的神经元被定义为一个简单的逻辑门,该逻辑门接收多个信号输入并将其整合到一起,如果信号叠加值超过某个阈值,该神经元就会输出信号到下一个神经元。

1957年,F.Rosenblatt在The Perceptron, a Perceiving and [2]Recognizing Automaton 一文中提出了感知器(Perceptron)的概念及对应的算法,该算法能够自动学习权重,使得其与输入的乘积能够决定一个神经元是否产生输出。更严谨地说,我们可以把这个问题描述为一个二分类问题,把类别定义为1(输出)和0(不输出)。然后,我们可以把输入和权重的乘积进行叠加,最终产生输出,在输出值上可以定义某种转换函数(Transfer Function)来将结果转换到我们需要的分类上,这个转换函数通常又被称为激活函数(Activation Function)。整个流程如下所示:

其中,我们把w称为权重,把x称为输入特征,把z称为网络输入(NetworkInput),是决定输出的激活函数。

由此,我们应该能够理解为什么要把称为激活函数。这是因为对于早期的脑神经研究来说,要么输出(1),要么不输出(0),如果输出的话,我们就认为该神经元被激活了,所以就有了激活函数的概念。

同时,在w、x、z、这几组数据中可以看到:

◎ 在监督训练阶段,w不可知,是需要训练和学习的目标。我们通过训练集中已知的x和输出值来反推w的值,这个反推的过程被称为反向传播,通常使用梯度下降(Gradient Descent)算法,这在后面会进行详细讲解。这个过程需要反复循环多次,计算量通常较大,需要大量的计算资源和时间。

◎ 在实际运行和预测阶段,我们用训练好的w权重和实时输入来计算最后的输出值,因为基本上只进行少数几次矩阵运算,所以复杂度比反向传播要低很多。

我们在图2-1中可以看到基本的感知器工作流程:神经元(Neuron)收到输入x,输入x和权重w相乘后叠加合并形成网络输入;网络输入被传送到激活函数,生成输出(Output,1或0)。如果在训练阶段,则输出将被用于和真实输出进行误差计算,并依此更新权重w。图2-1 感知器

这里还没谈到神经网络。到目前为止,我们只需知道神经网络由神经元构成,而感知器指的是神经元的工作方式。要了解神经网络,则首先要了解单个神经元是如何工作的。2.1.2 实现简单的感知器

我们现在按照图2-1的思路来实现一个简单的感知器。为了展示基本的感知器思路,这段代码不涉及任何第三方库,甚至不使用Numpy。这里只设一个权重w,并设置一个bias参数。因此network_input为wx+bias(注意,bias也可被视为权重w,对应一个0输入为1的常数。把bias视为权重参数之一有利于统一计算),同时,我们使用上面定义的作为激活函数,根据网络输入的值来输出1或0,这就是最简单的感知器模型实现。

我们的训练集和测试数据与第1章的示例相同,用10组数据作为训练集,用4组数组作为测试集,整体的代码(Simple_perceptron.py)实现如下:

我们来看看这些代码都做了什么。

第1~6行:设置初始化参数lr(用于调整训练时的步长,即learning rate学习率)、iterations(迭代次数)、权重w与bias。

第9~29行:这是模型训练的核心代码。根据iterations的设定,我们用同样的训练数据反复训练给定的次数,在每一次训练中都根据每一对数据对参数进行调整,即模型训练。在训练集中有真实标签y,注明当前输入x的真实类别,然后就可以根据我们设定的y’(预测值)=(wx+bias)来获得y’的预测值。这个预测是通过第23~24行的predict函数实现的,它实际上是根据第19~20行的network_input输入做出的判断。

在第14行,我们首先获得真实值y与预测值y'的偏差,却并不直接用这个偏差来计算和调整w、bias,而是乘以一个较小的参数lr。我们希望每次都对w和bias进行微调,通过多次迭代和调整后让w和bias接近最优解(Optimized Value),所以我们希望每次调整的幅度都不要太大。这是一个较难两全的事情:lr值过小可能会导致训练时间过长,难以在实际实验中判断是否收敛;lr值过大则容易造成步长过大而无法收敛。在第14行获得需要更新的update值之后,我们可以按照在本章参考文献[2]中给出的感知器的学习率来计算如何调整w和bias(这里暂时不去仔细分析这两个公式是怎么得来的,因为不同算法的实现各不相同,我们会在2.2.2节讲解梯度下降时再去分析):

第15~16行:仅仅是每次都把w和bias根据上面的误差更新进行调整。

那么,这样一个简单模型的运行效果如何呢?我们在第28~39行引入了在第1章中使用的训练数据和测试数据,看看训练效果如何。运行该代码,我们可以看到以下输出:

可以看到,对于输入的4组数据,运行结果完全正确。

最后两行输出的是w和bias的数值。

以上便是神经网络的最初起源及用Python进行的具体实现。当然,这个例子是非常简单的:①我们只处理单个输入;②分类也仅仅是很简单的二分;③我们的激活函数是一个非常直接的二分输出,在实际情况下基本不可能这么设置。但是,这基本解释了神经网络运行的基本原理和模式。

本章后面几节将仔细讲解基于梯度下降的算法实现(即如何基于梯度下降来调整权重)和相关的一些概念。当然,正如本书反复强调的,我们将通过Python代码来实现所有这些概念,而不会停留在名词解析层面。2.2 线性回归、梯度下降及实现2.2.1 分类的原理

在2.1节中,我们用代码实现了简单的感知器,学习了基本的神经网络原理实现。然而,在其中的代码实现里,我们提到感知器在修正权重w和偏移值bias时的修改规则如下:

这是整个训练过程中的核心,又是怎么得来的呢?本节将解释这个问题。

首先,我们要理解为什么要定义网络输入为wx +b。

实际上,我们做了一个假设:预测数据是线性可分的,因此我们希望用一个简单的斜线来判断所输入的数据落在哪个区间(类别)。

什么叫线性可分呢?请看图2-2。图2-2 线性可分

由图2-2可以看到,实心圆和空心圆能够被一条直线分开。如果我们的数据能被一条直线分为两类(或多个类),我们便称其为线性可分。图2-2实际上是二维坐标的数据划分,我们将在2.4节通过实现一个神经网络来处理。对于在2.1节中所举的正负数分类问题,这时解决起来就更简单了,可以将其视为对x轴上的点进行划分,如图2-3所示。图2-3 正负数分类

所以,现在我们知道了为什么要定义y’(预测值)=(wx+b),那么我们来看真正的关键问题:怎么得到w和b?

这实际上是一个线性回归(Linear Regression)问题,线性回归可以处理多于一个输入的形式,例如y'=(w·x+w·x+w·x)。在这个112233例子中,我们实际上预设了x=1、w=bias,即y'=(w·x+w·x)=000011(w+w·x)=(w·x+b)。注意,这是一个常见的技巧,给输入参数增加011一个固定为1的常量,可以让我们不用单独处理bias参数,而能将它作为权重值统一计算,2.4节会讲解如何计算。2.2.2 损失函数与梯度下降

在2.1节中假设:

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载