推荐序
在 IT 技术飞速发展的今天,云计算、人工智能、大数据和云原生应用等新兴技术的发展为我们的生活带来了翻天覆地的变化,也对软件开发者提出了更高的要求,特别是在人工智能开发领域,应运而生的新概念让人目不暇接。
作为一个.NET 开发者,在开发机器学习项目的过程中会遇到很多困难。主要原因之一是我们认为 C#不是适合该工作的编程语言,Python 和 R 语言才是,而 C#语言更适合用于机器学习的前期数据分析阶段。
不知道各位有没有思考一下为什么微软公司要在.NET 平台上引入机器学习,以及我们为什么要探索机器学习。
一个原因是,机器学习技术正在跨越鸿沟。事实上,这个鸿沟是非常难以跨越的,之所以那么多的高科技产品只在小众范围内流传,而没有被主流市场接受,是因为相关技术没有跨越这个鸿沟。最早的机器学习算法可以追溯到 20 世纪初,到今天为止,已经过去了 100 多年。从 1980 年机器学习技术成为一个独立的方向开始算起,到现在已经过去了 40 多年。在这 100 多年中,经过一代又一代人的努力,近几年机器学习技术终于跨越了鸿沟。跨越鸿沟意味着机器学习技术正在从仅有少数人掌握的时代过渡到大多数人掌握的时代。微软公司的CEO 萨提亚·纳德拉在他写的《刷新:重新发现商业与未来》一书中提出“民主化”的人工智能,ML.NET 正是要完成这项使命的载体之一。如何实现人工智能“民主化”,让它惠及每个人?如何让每个人打造自己的人工智能?在医疗、教育和零售机构中,打造一个相适应的人工智能是至关重要的。当我们谈人工智能的时候,不能空谈任何一个人工智能公司,而要“民主化”人工智能,让人工智能真正落地应用到个人。
我们应该探索机器学习的另一个原因是,作为人类,我们会产生大量数据,却无法处理全部数据;从技术上讲,我们面临无法从数据中提取信息的问题。此时,机器学习模型可以帮助我们处理海量的数据。
在.NET 生态上,人工智能领域有一个开源团队 SciSharp Stack,他们为 TensorFlow 提供了.NET Standard Binding,旨在用 C#实现完整的 TensorFlow API,允许.NET 开发人员使用跨平台的.NET Standard 框架开发、训练和部署机器学习模型。他们打造了一个完全属于.NET 开发人员自己的机器学习平台——TensorFlow.NET,对于 C#开发人员来说,这是一个零学习成本的机器学习平台,该平台集成了大量的 API 和底层封装,力图使 TensorFlow 的 Python 代码风格和编程习惯无缝移植到.NET 平台上。
虽然有大量的 TensorFlow 文档可以参考,但是对于初学者来说,其中涉及的知识难免晦涩,特别是对于.NET 的开发人员来说,缺少便于上手的指南及来自生产实践的案例总结。因此,一本系统地介绍 TensorFlow.NET 的图书是很有必要的,这样可以让更多的.NET 开发人员把人工智能应用于生产实践之中。
这是本书的目的和价值。本书采用.NET 5.0 进行实践,可能在本书发布的时候.NET 6.0已经发布,代码从.NET 5.0 升级到.NET 6.0 是很平滑的,请务必一边实际运行代码,一边阅读本书。
微软 MVP、腾讯云 TVP、华为云 MVP 张善友
序一
几年前一次偶然的机会接触到机器学习领域,对于我这样习惯了十几年强规则型机器编码的“老码农”来说,就像发现了一块新大陆。我充满了好奇,于是迫不及待地开启了机器学习探索之旅。在经历了满世界找文档、看论文和研究算法后,我渐渐地发现了自己力所能及并可能有所贡献的机会。在互联网上能找到的有关机器学习方面的示例中,几乎 99%的示例都是用Python 写的,剩下的是用 C/C++写的,可以说是 Python“独霸天下”的局面,让人误以为做机器学习项目就必须用Python。这个情况让我萌生了移植一些常用的机器学习库到.NET 生态的想法,最初的想法是通过迁移这些库来加深对机器学习的掌握程度,揭开“时髦”词汇人工智能(AI)和机器学习(ML)背后的秘密。
目前机器学习流行的基础库 NumPy 是首先要进行移植的,于是产生了 NumSharp 这个张量计算库,移植过程并不是很顺利,因为张量计算对于我来说是一个全新的概念。要实现一个和现有 NumPy 库可以相互替换的.NET 库比想象中更难,最具有挑战性的是它对函数性能的要求很高。最后的效果是只移植了表面上的接口和一小部分 API,满足了少部分模型的计算要求,但性能较差,.NET 天生在这方面不能和 C/C++ 相提并论,虽然有 SIMD 的加持,但是实现起来仍然非常不方便。
随着对机器学习的不断深入了解,我逐步接触了神经网络和深度学习知识。神经网络带我进入了一个魔幻的世界,里面充满未知。当时谷歌的 TensorFlow 开源深度学习框架正火遍全球,同时期的 PyTorch 崭露头角,所以第一个进入目标移植深度学习库的就是 TensorFlow 了,我称之为 TensorFlow.NET。
移植工作从“Hello World!”开始,API 逐步增多,复杂性随之增加,从静态图到动态图,再到上层的 Keras,基本上都实现了。在代码编写的过程中,因为项目从一开始就是在 GitHub上开源的,所以我不断收到各种各样的使用反馈。正因为有这样的反馈互动,我才有了不断完善这个项目的动力。在此过程中,我结识了仇华——在图像识别领域深耕多年的朋友,并产生了应该编写一本关于如何使用 TensorFlow.NET 的书籍的想法,把现有的示例代码通过图文讲解的方式呈现给读者,于是有了这本《TensorFlow.NET 实战》。书中详细介绍了从张量计算到神经网络模型的搭建,从理论编码到工业场景重现的剖析,示例涵盖线性回归、逻辑回归、全连接神经网络、文本分类、图像分类和迁移学习等,是帮助.NET 开发者进入机器学习世界的宝贵资料。
最后要感谢在项目编码和宣传上给予过我帮助的人,特别是家人对我在开源项目方面的支持,因为做开源项目几乎占用了我所有的业余时间和精力,照顾 3 个孩子的重任都由我太太承担了。
SciSharp Stack 开源社区创办者 陈海平
序二
我写这本书的初衷原本是为 SciSharp Stack 开源社区贡献一点自己的力量,为国内使用 C#开发 TensorFlow 深度学习模型的小伙伴们提供一个快速入门的指南。写着写着,我发现很多语法和代码需要搭配理论知识才能更好地读懂,因而逐渐添加了很多机器学习和深度学习的理论知识,包括在 TensorFlow 2.x 之后出现的一些新特性的专题说明,如 Eager Mode、AutoGraph和 Keras 等。同时考虑到本书的定位,尽量避开了复杂数学公式的推导,而以 API 文档说明和实践应用为主。作为市面上第一本,也是目前唯一的一本 TensorFlow.NET 开源库官方出品的专门面向.NET 开发者的 TensorFlow 中文开发书籍,很多社区的小伙伴和.NET 开发者在本书的编写过程中提供了宝贵的建议,在大家的热切推荐下,书中增加了大量的案例实践,包括图像分类、目标检测、自然语言、生成对抗等不同领域的应用。
2021 年年底,这本入门手册终于接近完成。记得我是在 2019 年 11 月认识的陈海平先生,对于我个人来说,他是我进入开源社区这个新世界的领路人。当时我在实际项目开发过程中遇到了一个比较困难的抉择(后来发现几乎所有.NET 开发者在实际项目中应用深度学习框架都会遇到这个痛点),就是现有深度学习框架以 Python 语言开发为主和实际工业项目以 C#语言开发为主之间的矛盾。网络上有很多的解决方案。大约花了 1 个月的时间,我对常见的各种解决方案进行了现场项目测试和多维度的比较,综合考虑深度学习模型 GPU 训练的必要性和在实际项目中部署的便利性后,选择了 TensorFlow.NET 作为自己的项目开发框架。找准方向后,我深入学习和了解了这个框架,惊喜地发现这个框架的创立者陈海平先生是一名华人,并且几乎凭一己之力创建了 TensorFlow.NET 这个超级庞大而复杂的项目,陈海平先生的开发能力和开源精神令我敬佩不已,他在我心中成为大神级的存在,本书中的案例代码几乎都是他开发的。
从 2019 年加入 SciSharp Stack 开源社区起,在大约 1 年的时间里,我陆续发表了一些TensorFlow.NET 相关的技术博客文章,并在一些大学校园和研究生院里给学校的老师和同学们宣导 TensorFlow.NET 在实际工业项目中的应用,也在微软年度的.NET 大会上给大家做了TensorFlow.NET 的专题报告。作为谷歌苏州 TensorFlow User Group 的创立者,我在每一次社区的技术公益活动中都会对 TensorFlow.NET 进行推广和入门应用讲解。期间,我也经常和海平聊起要给 TensorFlow.NET 出一个官方教程,并在 GitHub 上创建了库进行教程的更新,断断续续地出了一些入门视频教程和技术文章,但迟迟没有系统地开展出书的工作。转折点大约在2020 年的 12 月,F#语言之父 Don Syme 大神加入了我们的 SciSharp Stack 开源社区,带来了 F#语言爱好者的开发团体。至此,C#和 F#这两大.NET 核心开发语言的开发者们都加入了我们的社区。随着社区成员的壮大和热度的提升,出书的任务迫在眉睫,官方教程的需求愈加热烈,因此我们打算静下心来快速地把这个教程制作完成。
出书比想象中要难,在差不多 1 年半的时间里,这件事几乎占用了我所有的个人业余时间,
写书过程中的点滴故事我至今记忆犹新。在每个夜深人静的晚上,查询资料、斟酌语词、编写测试代码,为了确保这类技术书籍的准确性,书中的每个案例和代码都需要仔细地编写完,并在机器上实际跑一遍,不断调试优化,确保读者在实践过程中没有错误。可以说,这是我目前做过的单个工程量最大的事情,但是回首看,也收获了很多,对于 TensorFlow 的整体框架有了更系统的认识,对机器学习和深度学习的发展历史和理论结构也有了更深入的了解。为了讲清楚 F#的应用,我学习了一门新的语言,深深感受到了函数式编程的魅力所在。
IT 技术更新飞快,深度学习领域的各种创新是层出不穷的,在本书的编写过程中,TensorFlow 从 1.x 升级到了 2.x,新增了很多功能和特性,.NET 也推出了.NET 5.0,.NET 6.0 的预览版也发布了,正式版不久也要面世。本书尽量做到与时俱进,书中的代码主要基于TensorFlow 2.x 和.NET 5.0,读者可以根据时下最新的语言和框架版本进行升级应用。本书适用于有一些机器学习或深度学习基础,希望在实际生产项目中应用 TensorFlow 的.NET 开发者和工程师。在编写此书的过程中,由于个人能力有限,书中肯定有很多的不足和缺陷,也有很多案例没有来得及开发完成,包括时序分析和时下比较热门的 Transform 模型等,希望广大读者能提供宝贵的意见和想法,我们期望有机会在下一版本或英文版中得到完善。
本书的出版得到了 SciSharp Stack 社区、微软技术俱乐部、TensorFlow User Group 的多位小伙伴的帮助和支持,他们不但为本书的示例代码提供了建议和测试结果,而且提供了本书的方向和需求点,为本书的完成做出了重要贡献。
本书中的案例代码主要来自 SciSharp Stack Examples,其中 C#部分主要由陈海平提供,F#部分主要由 Vianney P.提供。生成对抗网络的案例代码由社区成员彭波提供,卷积神经网络可视化的案例代码和张量查看器由社区成员久永提供,煤矿矿区的时间序列预测应用案例代码由社区成员孙翔宇提供。在此特别表示感谢。
本书的出版过程得到了微软技术俱乐部的潘淳校长、盛派网络科技的苏震巍主席、.NET圈子知名的微软 MVP 张善友队长和数据工程畅销书作者齐伟老师的共同指导和大力帮助。在此一并表示由衷的谢意。衷心感谢电子工业出版社的符隆美编辑对本书的细致编校及出版流程跟进。
感谢我的太太在我写书过程中给予的关注和大力支持,因为写书占据了我太多的业余时间和精力,家里两个孩子全交给太太照顾了。依稀记得,2019 年的大年夜晚上,在老家父母的家中,我刚刚完成了第 2 篇关于 TensorFlow.NET 的案例文章,并在笔记本电脑上使用 GPU 成功测试了代码,而窗外,我的太太正带着两个孩子在放烟花。也记得,不知多少个伏案疾书的夜晚,每当完成一个章节并提交到了 GitHub,我都会在写书计划表上划去一项,并在心里暗自庆祝进度又推进一格,在此真诚地感谢太太给我创造的专注的写作环境。
最后,感谢所有支持并帮助我们社区的朋友。
SciSharp Stack 开源社区核心组成员 仇华(Henry)