书名:PyTorch深度学习
ISBN:978-7-115-50898-0
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 [印度] 毗湿奴•布拉马尼亚(Vishnu Subramanian)
译 王海玲 刘江峰
审 校 李 昉
责任编辑 傅道坤
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
Copyright © Packt Publishing 2018. First published in the English language under the title Deep Learning with PyTorch.
All Rights Reserved.
本书由英国Packt Publishing公司授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式或任何手段复制和传播。
版权所有,侵权必究。
PyTorch是Facebook于2017年初在机器学习和科学计算工具Torch的基础上,针对Python语言发布的一个全新的机器学习工具包,一经推出便受到了业界的广泛关注和讨论,目前已经成为机器学习从业人员首选的一款研发工具。
本书是使用PyTorch构建神经网络模型的实用指南,内容分为9章,包括PyTorch与深度学习的基础知识、神经网络的构成、神经网络的高级知识、机器学习基础知识、深度学习在计算机视觉中的应用、深度学习在序列数据和文本中的应用、生成网络、现代网络架构,以及PyTorch与深度学习的未来走向。
本书适合对深度学习领域感兴趣且希望一探PyTorch究竟的业内人员阅读;具备其他深度学习框架使用经验的读者,也可以通过本书掌握PyTorch的用法。
在过去的几年里,我一直与Vishnu Subramanian共事。Vishnu给人的印象是一位热情的技术分析专家,他具备达到卓越所需的严谨性。他对大数据、机器学习、人工智能的观点很有见地,并对问题和解决办法的前景进行了分析和评价。由于与他关系密切,我很高兴能以Affine首席执行官的身份为本书作序。
要想更成功地为财富500强客户提供深度学习解决方案,显然需要快速的原型设计。PyTorch允许对分析中的项目进行快速原型化,而不必过于担心框架的复杂性。借助于能更快交付解决方案的框架,开发人员的能力将发挥到极致。作为一名提供高级分析解决方案的企业家,在团队中建立这种能力是我的首要目标。本书中,Vishnu将带领读者了解使用PyTorch构建深度学习解决方案的基本知识,同时帮助读者建立一种面向现代深度学习技术的思维模式。
本书前半部分介绍了深层学习和PyTorch的几个基本构造块,还介绍了关键的概念,如过拟合、欠拟合以及有助于处理这些问题的技术。
在本书后半部分,Vishnu介绍了最新的概念,如CNN、RNN、使用预卷积特征的LSTM迁移学习、一维卷积,以及如何应用这些技术的真实案例。最后两章介绍了现代深度学习体系结构,如Inception、ResNet、DenseNet模型和它们的集成,以及生成网络如风格迁移、GAN和语言建模等。
因为有了所有这些实用案例和详细的解释,对想要精通深度学习的读者,本书无疑是最佳的图书之一。今天,技术发展的速度是无与伦比的。对于期待开发成熟的深度学习解决方案的读者,我想指出的是,合适的框架也会推动合适的思维方式。
祝本书所有读者可以快乐地探索新世界!
祝Vishnu和本书取得巨大的成功,此乃实至名归。
Manas Agarwal
Affine Analytics公司联合创始人兼CEO
印度班加罗尔
Vishnu Subramanian在领导、设计和实施大数据分析项目(人工智能、机器学习和深度学习)方面富有经验。擅长机器学习、深度学习、分布式机器学习和可视化等。在零售、金融和旅行等行业颇具经验,还善于理解和协调企业、人工智能和工程团队之间的关系。
献给Jeremy Howard和Rachel Thomas,感谢他们对我写作本书的鼓励,感谢家人对我的爱和关心!
如果没有Jeremy Howard和Rachel Thomas的 fast.ai的启发和网络公开课,本书就不可能面世。感谢他们为普及人工智能/深度学习所做的工作。
Poonam Ligade是一名自由职业者,专注于大数据工具,如Spark、Flink和Cassandra,以及可扩展的机器学习和深度学习方面的工作。她也是一位顶级的Kaggle核心作者。
王海玲,毕业于吉林大学计算机系,从小喜爱数学,曾获得华罗庚数学竞赛全国二等奖。拥有世界500强企业多年研发经验。作为项目骨干成员,参与过美国惠普实验室机器学习项目。
刘江峰,重庆大学软件工程硕士,专注于物流、旅游、航空票务、电商等垂直技术领域。曾在上市公司内带领团队与去哪儿、途牛、飞猪平台在机票、旅游方向有项目合作。目前在任职公司主要负责带领攻坚团队为公司平台深度整合人工智能、数据决策的多项平台应用。
李昉,毕业于东北大学自动化系,大学期间曾获得“挑战杯”全国一等奖。拥有惠普、文思海辉等世界500强企业多年研发经验,随后加入互联网创业公司。现在中体彩彩票运营公司负责大数据和机器学习方面的研发。同时是集智俱乐部成员,并参与翻译了人工智能图书Deep Thinking。
PyTorch以其灵活性和易用性吸引了数据科学专业人士和深度学习业者的注意。本书介绍了深度学习和PyTorch的基本组成部分,并展示了如何使用可行方法解决真实问题,以及一些用于解决当代前沿研究问题的现代体系结构和技术。
本书在不深入数学细节的条件下,给出了多个先进深度学习架构的直观解释,如ResNet、DenseNet、Inception和Seq2Seq等,也讲解了如何进行迁移学习,如何使用预计算特征加速迁移学习,以及如何使用词向量、预训练的词向量、LSTM和一维卷积进行文本分类。
阅读完本书后,读者将会成为一个熟练的深度学习人才,能够利用学习到的不同技术解决业务问题。
本书面向的读者包括工程师、数据分析员、数据科学家、深度学习爱好者,以及试图使用PyTorch研究和实现高级算法的各类人员。如果读者具备机器学习的知识,则有助于本书的阅读,但这并不是必需的。读者最好了解Python编程的知识。
第1章,PyTorch与深度学习,回顾了人工智能和机器学习的发展史,并介绍了深度学习的最新成果,以及硬件和算法等诸多领域的发展如何引发了深度学习在不同应用上的巨大成功。最后介绍了PyTorch的Python库,它由Facebook基于Torch构建。
第2章,神经网络的构成,讨论了PyTorch的不同组成部分,如变量、张量和nn.module
,以及如何将其用于开发神经网络。
第3章,深入了解神经网络,涵盖了训练神经网络的不同过程,如数据的准备、用于批次化张量的数据加载器、创建神经架构的torch.nn
包以及PyTorch损失函数和优化器的使用。
第4章,机器学习基础,介绍了不同类型的机器学习问题和相关的挑战,如过拟合和欠拟合等,以及避免过拟合的不同技术,如数据增强、加入dropout和使用批归一化。
第5章,深度学习之计算机视觉,介绍了卷积神经网络的基本组成,如一维和二维卷积、最大池化、平均池化、基础CNN架构、迁移学习以及使用预卷积特征加快训练等。
第6章,序列数据和文本的深度学习,介绍了词向量、如何使用预训练的词向量、RNN、LSTM和对IMDB
数据集进行文本分类的一维卷积。
第7章,生成网络,介绍了如何使用深度学习生成艺术图片、使用DCGAN生成新图片,以及使用语言模型生成文本。
第8章,现代网络架构,介绍了可用于计算机视觉的现代架构,如ResNet、Inception和DenseNet。还快速地介绍了可用于现代语言翻译和图像标注系统的encoder-decoder架构。
第9章,未来走向,总结了本书所学内容,并介绍了如何紧跟深度学习领域的最新潮流。
本书除第1章与第9章之外,其他章节在GitHub库中都有对应的Jupyter Notebook,为了节省空间,可能未包含运行所需的导入语句。读者应该可以从该Notebook中运行所有代码。
本书注重实际演示,请在阅读本书时运行Jupeter Notebook。
使用带有GPU的计算机有助于代码运行得更快。有些公司如paperspace和crestle抽象出了运行深度学习算法所需的大量复杂度。
本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。
本书提供如下资源:
本书源代码;
本书彩图文件。
要获得以上配套资源,请在异步社区本书页面中点击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,点击“提交勘误”,输入勘误信息,点击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。
如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。
“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。
异步社区
微信服务号
理解神经网络的基本组成部分,如张量、张量运算和梯度递减等,对构造复杂的神经网络至关重要。本章将构建首个神经网络的Hello world程序,并涵盖以下主题:
PyTorch可以作为Python包使用,用户可以使用pip
或conda
来构建,或者从源代码构建。本书推荐使用Anaconda Python 3发行版。要安装Anaconda,请参考Anaconda官方文档。所有示例将在本书的GitHub存储库中以Jupyter Notebook的形式提供。强烈建议使用Jupyter Notebook,因为它允许进行交互。如果已经安装了Anaconda Python,那么可以继续PyTorch安装的后续步骤。
基于GPU的Cuda 8版安装:
conda install pytorch torchvision cuda80 -c soumith
基于GPU的Cuda 7.5版安装:
conda install pytorch torchvision -c soumith
非GPU版的安装:
conda install pytorch torchvision -c soumith
在本书写作时,PyTorch还不支持Windows,所以可以尝试使用虚拟机或Docker镜像。
下面给出本书介绍的第一个神经网络,它将学习如何将训练示例(即输入数组)映射成目标(即输出数组)。假设我们为最大的在线公司之一Wondermovies工作(该公司按需提供视频服务),训练数据集包含了表示用户在平台上观看电影的平均时间的特征,网络将据此预测每个用户下周使用平台的时间。这是个假想出来的用例,不需要深入考虑。构建解决方案的主要分解活动如下。
get_data
函数准备输入和输出张量(数组)。get_weights
函数提供以随机值初始化的张量,网络通过优化这些参数来解决问题。simple_network
函数应用线性规则为输入数据生成输出,计算时先用权重乘以输入数据,再加上偏差(y=wx+b)。loss_fn
函数提供了评估模型优劣的信息。optimize
函数用于调整初始的随机权重,并帮助模型更准确地计算目标值。如果大家刚接触机器学习,不用着急,到本章结束时将会真正理解每个函数的作用。下面这些从PyTorch代码抽取出来的函数,有助于更容易理解神经网络。我们将逐个详细讨论这些函数。前面提到的分解活动对大多数机器学习和深度学习问题而言都是相同的。接下来的章节会探讨为改进各项功能从而构建实际应用的各类技术。
神经网络的线性回归模型如下:
y= wx+b
用PyTorch编码如下:
x,y = get_data() #x – 表示训练数据,y – 表示目标变量
w,b = get_weights() #w,b – 学习参数
for i in range(500):
y_pred = simple_network(x) # 计算wx + b的函数
loss = loss_fn(y,y_pred) # 计算y和y_pred平方差的和
if i % 50 == 0:
print(loss)
optimize(learning_rate) # 调整 w,b,将损失最小化
到本章结束时,你会了解到每个函数的作用。
PyTorch提供了两种类型的数据抽象,称为张量和变量。张量类似于numpy
中的数组,它们也可以在GPU上使用,并能够改善性能。数据抽象提供了GPU和CPU的简易切换。对某些运算,我们会注意到性能的提高,以及只有当数据被表示成数字的张量时,机器学习算法才能理解不同格式的数据。张量类似Python数组,并可以改变大小。例如,图像可以表示成三维数组(高,宽,通道(RGB)),深度学习中使用最多5个维度的张量表示也很常见。一些常见的张量如下:
包含一个元素的张量称为标量。标量的类型通常是FloatTensor
或LongTensor
。在本书写作时,PyTorch还没有特别的0维张量。因此,我们使用包含一个元素的一维张量表示:
x = torch.rand(10)
x.size()
Output - torch.Size([10])
向量只不过是一个元素序列的数组。例如,可以使用向量存储上周的平均温度:
temp = torch.FloatTensor([23,24,24.5,26,27.2,23.0])
temp.size()
Output - torch.Size([6])
大多数结构化数据都可以表示成表或矩阵。我们使用波士顿房价(Boston House Prices)的数据集,它包含在Python的机器学习包scikit-learn中。数据集是一个包含了506
个样本或行的numpy
数组,其中每个样本用13
个特征表示。Torch
提供了一个工具函数from_numpy()
,它将numpy
数组转换成torch
张量,其结果张量的形状为506
行×13
列:
boston_tensor = torch.from_numpy(boston.data)
boston_tensor.size()
Output: torch.Size([506, 13])
boston_tensor[:2]
Output:
Columns 0 to 7
0.0063 18.0000 2.3100 0.0000 0.5380 6.5750 65.2000 4.0900
0.0273 0.0000 7.0700 0.0000 0.4690 6.4210 78.9000 4.9671
Columns 8 to 12
1.0000 296.0000 15.3000 396.9000 4.9800
2.0000 242.0000 17.8000 396.9000 9.1400
[torch.DoubleTensor of size 2x13]
当把多个矩阵累加到一起时,就得到了一个3维张量。3维张量可以用来表示类似图像这样的数据。图像可以表示成堆叠到一起的矩阵中的数字。一个图像形状的例子是(224,224,3
),其中第一个数字表示高度,第二个数字表示宽度,第三个表示通道数(RGB)。我们来看看计算机是如何识别大熊猫的,代码如下:
from PIL import Image
# 使用PIL包从磁盘读入熊猫图像并转成numpy数组
panda = np.array(Image.open('panda.jpg').resize((224,224)))
panda_tensor = torch.from_numpy(panda)
panda_tensor.size()
Output - torch.Size([224, 224, 3])
# 显示熊猫
plt.imshow(panda)
由于显示大小为(224,224,3
)的张量会占用本书的很多篇幅,因此将把图2.1所示的图像切片成较小的张量来显示。
图2.1 显示的图像
张量的一个常见操作是切片。举个简单的例子,我们可能选择一个张量的前5个元素,其中张量名称为sales
。我们使用一种简单的记号sales[:slice_index]
,其中slice_index
表示要进行切片的张量位置:
sales =
torch.FloatTensor([1000.0,323.2,333.4,444.5,1000.0,323.2,333.4,444.5])
sales[:5]
1000.0000
323.2000
333.4000
444.5000
1000.0000
[torch.FloatTensor of size 5]
sales[:-5]
1000.0000
323.2000
333.4000
[torch.FloatTensor of size 3]
对熊猫图像做些更有趣的处理,比如只选择一个通道时熊猫图像的样子,以及如何选择熊猫的面部。
下面,只选择熊猫图像的一个通道:
plt.imshow(panda_tensor[:,:,0].numpy()) #0表示RGB中的第一个通道
输出如图2.2所示。
图2.2
现在裁剪图像,假设要构造一个熊猫的面部检测器,我们只需要熊猫图像的面部部分。我们来裁剪张量图像,让它只包含熊猫面部。
plt.imshow(panda_tensor[25:175,60:130,0].numpy())
输出如图2.3所示。
另一个常见的例子是需要获取张量的某个特定元素:
# torch.eye(shape)生成一个对角线元素为1的对角矩阵
sales = torch.eye(3,3)
sales[0,1]
Output- 0.00.0
第5章在讨论使用卷积神经网络构建图像分类器时,将再次用到图像数据。
图2.3
![]()
PyTorch的大多数张量运算都和
NumPy
运算非常类似。
4维张量类型的一个常见例子是批图像。为了可以更快地在多样例上执行相同的操作,现代的CPU和GPU都进行了专门优化,因此,处理一张或多张图像的时间相差并不大。因而,同时使用一批样例比使用单样例更加常见。对批大小的选择并不一目了然,它取决于多个因素。不使用更大批尺寸或完整数据集的主要因素是GPU的内存限制,16、32和64是通常使用的批尺寸。
举例来说,加载一批64×224×224×3
的猫咪图片,其中64表示批尺寸或图片数量,两个224分别表示高和宽,3表示通道数:
#从磁盘读取猫咪图片
cats = glob(data_path+'*.jpg')
#将图片转换成numpy数组
cat_imgs = np.array([np.array(Image.open(cat).resize((224,224))) for cat in
cats[:64]])
cat_imgs = cat_imgs.reshape(-1,224,224,3)
cat_tensors = torch.from_numpy(cat_imgs)
cat_tensors.size()
Output - torch.Size([64, 224, 224, 3])
可能必须使用5维张量的一个例子是视频数据。视频可以划分为帧,例如,熊猫玩球的长度为30秒的视频,可能包含30帧,这可以表示成形状为(1×30×224×224×3)的张量。一批这样的视频可以表示成形状为(32×30×224×224×3)的张量——例中的30表示每个视频剪辑中包含的帧数,32表示视频剪辑的个数。
我们已学习了如何用张量表示法表示不同形式的数据。有了张量格式的数据后,要进行一些常见运算,比如加、减、乘、点积和矩阵乘法等。所有这些操作都可以在CPU或GPU上执行。PyTorch提供了一个名为cuda()
的简单函数,将张量从CPU复制到GPU。我们来看一下其中的一些操作,并比较矩阵乘法运算在CPU和GPU上的性能差异。
张量的加法运算用如下代码实现:
#执行张量加法运算的不同方式
a = torch.rand(2,2)
b = torch.rand(2,2)
c = a + b
d = torch.add(a,b)
#和自身相加
a.add_(5)
#不同张量之间的乘法
a*b
a.mul(b)
#和自身相乘
a.mul_(b)
对于张量矩阵乘法,我们比较一下代码在CPU和GPU上的性能。所有张量都可以通过调用cuda()
函数转移到GPU上。
GPU上的乘法运算运行如下:
a = torch.rand(10000,10000)
b = torch.rand(10000,10000)
a.matmul(b)
Time taken: 3.23 s
#将张量转移到GPU
a = a.cuda()
b = b.cuda()
a.matmul(b)
Time taken: 11.2 µs
加、减和矩阵乘法这些基础运算可以用于构建复杂运算,如卷积神经网络(CNN)和递归神经网络(RNN),本书稍后的章节将进行相关讲解。
深度学习算法经常可以表示成计算图。图2.4所示为一个在示例中构建的变量计算图的简单例子。
图2.4 变量计算图
在图2.4所示的计算图中,每个小圆圈表示一个变量,变量形成了一个轻量封装,将张量对象、梯度,以及创建张量对象的函数引用封装起来。图2.5所示为Variable
类的组件。
图2.5 Variable类
梯度是指loss
函数相对于各个参数(W, b)的变化率。例如,如果a的梯度是2,那么a值的任何变化都会导致Y值变为原来的两倍。如果还不清楚,不要着急——大多数数深度学习框架都会为我们代为计算梯度值。本章中,我们将学习如何使用梯度来改善模型的性能。
除了梯度,变量还引用了创建它的函数,相应地也就指明了每个变量是如何创建的。例如,变量a
带有的信息表明它是由X
和W
的积生成的。
让我们看个例子,创建变量并检查梯度和函数引用:
x = Variable(torch.ones(2,2),requires_grad=True)
y = x.mean()
y.backward()
x.grad
Variable containing:
0.2500 0.2500
0.2500 0.2500
[torch.FloatTensor of size 2x2]
x.grad_fn
Output – None
x.data
1 1
1 1
[torch.FloatTensor of size 2x2]
y.grad_fn
<torch.autograd.function.MeanBackward at 0x7f6ee5cfc4f8>
在上面的例子中,我们在变量上调用了backward
操作来计算梯度。默认情况下,变量的梯度是none。
变量中的grad_fn
指向了创建它的函数。变量被用户创建后,就像例子中的x
一样,其函数引用为None
。对于变量y
,它指向的函数引用是MeanBackward
。
属性Data用于获取变量相关的张量。
第一个神经网络中的get_data
函数创建了两个变量:x
和y
,尺寸为(17, 1)
和(17)
。我们看函数内部的构造:
def get_data():
train_X =
np.asarray([3.3,4.4,5.5,6.71,6.93,4.168,9.779,6.182,7.59,2.167,
7.042,10.791,5.313,7.997,5.654,9.27,3.1])
train_Y =
np.asarray([1.7,2.76,2.09,3.19,1.694,1.573,3.366,2.596,2.53,1.221,
2.827,3.465,1.65,2.904,2.42,2.94,1.3])
dtype = torch.FloatTensor
X =
Variable(torch.from_numpy(train_X).type(dtype),requires_grad=False).view(17,1)
y = Variable(torch.from_numpy(train_Y).type(dtype),requires_grad=False)
return X,y
在前面神经网络的例子中,共有两个学习参数:w
和b
,还有两个不变的参数:x
和y
。我们已在get_data
函数中创建了变量x
和y
。学习参数使用随机值初始化并创建,其中参数require_grad
的值设为True
,这与变量x
和y
不同,变量x
和y
创建时require_grad
的值是False
。初始化学习参数有不同的方法,我们将在后续章节探索。下面列出的是get_weights
函数代码:
def get_weights():
w = Variable(torch.randn(1),requires_grad = True)
b = Variable(torch.randn(1),requires_grad=True)
return w,b
前面的代码大部分是一目了然的,其中torch.randn
函数为任意给定形状创建随机值。
使用PyTorch变量定义了输入和输出后,就要构建模型来学习如何将输入映射到输出。在传统的编程中,我们手动编写具有不同逻辑的函数代码,将输入映射到输出。然而,在深度学习和机器学习中,是通过把输入和相关的输出展示给模型,让模型完成函数的学习。我们的例子中,在线性关系的假定下,实现了尝试把输入映射为输出的简单神经网络。线性关系可以表示为y= wx+ b,其中w和b是学习参数。网络要学习w和b的值,这样wx+ b才能更加接近真实的y。图2.6是训练集和神经网络要学习的模型的示意图。
图2.6 输入数据点
图2.7表示和输入数据点拟合的线性模型。
图2.7 拟合数据点的线性模型
图中的深灰(蓝)色线表示网络学习到的模型。
现在已经有了实现网络所需的所有参数(x
、w
、b
和y
),我们对w
和x
做矩阵乘法,然后,再把结果与b
求和,这样就得到了预测值y
。函数实现如下:
def simple_network(x):
y_pred = torch.matmul(x,w)+b
return y_pred
PyTorch在torch.nn
中提供了称为层(layer)的高级抽象,层将负责多数常见的技术都需要用到的后台初始化和运算工作。这里使用低级些的操作是为了理解函数内部的构造。在第5章和第6章中,将用PyTorch抽象出来的层来构建复杂的神经网络或函数。前面的模型可以表示为torch.nn
层,如下:
f = nn.Linear(17,1) #简单很多
我们已经计算出了y
值,接下来要了解模型的性能,必须通过loss
函数评估。
由于我们的学习参数w
和b
以随机值开始,产生的结果y_pred
,必和真实值y
相去甚远。因此,需要定义一个函数,来告知模型预测值和真实值的差距。由于这是一个回归问题,我们使用称为误差平方和(也称为和方差,SSE)的损失函数。我们对y
的预测值和真实值之差求平方。SSE有助于模型评估预测值和真实值的拟合程度。torch.nn
库中有不同的损失函数,如均方差(又称方差,MSE)损失和交叉熵损失。但是在本章,我们自己来实现loss
函数:
def loss_fn(y,y_pred):
loss = (y_pred-y).pow(2).sum()
for param in [w,b]:
if not param.grad is None: param.grad.data.zero_()
loss.backward()
return loss.data[0]
除了计算损失值,我们还进行了backward
操作,计算出了学习参数w和b的梯度。由于我们会不止一次使用loss
函数,因此通过调用grad.data.zero_()
方法来清除前面计算出的梯度值。在第一次调用backward
函数的时候,梯度是空的,因此只有当梯度不为None
时才将梯度值设为0。
前面例子中的算法使用随机的初始权重来预测目标,并计算损失,最后调用loss
变量上的backward
函数计算梯度值。每次迭代都在整个样例集合上重复整个过程。在多数的实际应用中,每次迭代都要对整个数据集的一个小子集进行优化操作。损失值计算出来后,用计算出的梯度值进行优化,以让损失值降低。优化器通过下面的函数实现:
def optimize(learning_rate):
w.data -= learning_rate * w.grad.data
b.data -= learning_rate * b.grad.data
学习率是一个超参数,可以让用户通过较小的梯度值变化来调整变量的值,其中梯度指明了每个变量(w
和b
)需要调整的方向。
不同的优化器,如Adam、RmsProp和SGD,已在torch.optim
包中实现好。后面的章节中,我们将使用这些优化器来降低损失或提高准确率。
为深度学习算法准备数据本身就可能是件很复杂的事情。PyTorch提供了很多工具类,工具类通过多线程、数据增强和批处理抽象出了如数据并行化等复杂性。本章将介绍两个重要的工具类:Dataset
类和DataLoader
类。为了理解如何使用这些类,我们从Kaggle网站(https://www.kaggle.com/c/dogs-vs-cats/data
)上拿到Dogs vs. Cats
数据集,并创建可以生成PyTorch张量形式的批图片的数据管道。
任何自定义的数据集类,例如Dogs
数据集类,都要继承自PyTorch的数据集类。自定义的类必须实现两个函数:__len__(self)
和__getitem__(self,idx)
。任何和Dataset
类表现类似的自定义类都应和下面的代码类似:
from torch.utils.data import Dataset
class DogsAndCatsDataset(Dataset):
def __init__(self,):
pass
def __len__(self):
pass
def __getitem__(self,idx):
pass
在init
方法中,将进行任何需要的初始化。例如在本例中,读取表索引和图片的文件名。__len__(self)
运算负责返回数据集中的最大元素个数。__getitem__ (self, idx)
运算根据每次调用时的idx
返回对应元素。下面的代码实现了DogsAndCatsDataset
类。
class DogsAndCatsDataset(Dataset):
def __init__(self,root_dir,size=(224,224)):
self.files = glob(root_dir)
self.size = size
def __len__(self):
return len(self.files)
def __getitem__(self,idx):
img = np.asarray(Image.open(self.files[idx]).resize(self.size))
label = self.files[idx].split('/')[-2]
return img,label
在定义了DogsAndCatsDataset
类后,可以创建一个对象并在其上进行迭代,如下面的代码所示。
for image,label in dogsdset:
#在数据集上应用深度学习算法
在单个的数据实例上应用深度学习算法并不理想。我们需要一批数据,现代的GPU都对批数据的执行进行了性能优化。DataLoader
类通过提取出大部分复杂度来帮助创建批数据。
DataLoader
类位于PyTorch
的utils
类中,它将数据集对象和不同的取样器联合,如SequentialSampler
和RandomSampler
,并使用单进程或者多进程的的迭代器,为我们提供批量图片。取样器是为算法提供数据的不同策略。下面是使用DataLoader
处理Dogs vs. Cats
数据集的例子。
dataloader = DataLoader(dogsdset,batch_size=32,num_workers=2)
for imgs , labels in dataloader:
#在数据集上应用深度学习算法
pass
imgs
包含一个形状为(32, 224, 224, 3)的张量,其中32表示批尺寸。
PyTorch团队也维护了两个有用的库,即torchvision
和torchtext
,这两个库基于Dataset
和DataLoader
类构建。我们将在相关章节使用它们。
本章中,我们学习了PyTorch提供的多个数据结构和操作,并使用PyTorch的基础组成模块实现了几个组件。在数据准备上,我们创建了供算法使用的张量。我们的网络架构是一个可预测用户使用Wondermovies平台的平均小时数的模型。我们使用loss
函数检查模型的性能,并使用optimize
函数调整模型的学习参数,从而改善平台性能。
我们也了解了PyTorch如何通过抽象出数据并行化和数据增强的复杂度,让创建数据管道变得更简单。
下一章将深入探讨神经网络和深度学习算法的原理。我们将学习PyTorch内置的用于构建网络架构、损失函数和优化器的几个模块,也将演示如何在真实数据集上使用它们。