深度学习PyTorch入门之Tensor(一)
上一篇文章,我们简单地介绍了什么是PyTorch和PyTorch应该怎么学,比较重要的一点就是千万不要被环境所困扰,要注意解决实际的问题,一步一步地慢慢来,坚持手敲代码才可以。
今天我们开始学习PyTorch框架里面的基石Tensor,tensor即为张量,它是机器学习和深度学习的一块基石,它们核心的作用就是“万物数字化”,用数字来表示物体。例如我们可以用“1”表示人,“2”表示车,“3”表示花,当然这种表示还是比较入门,不能体现万物的联系,举例来说,用“1”表示豪放的人,但是苏轼和李白都是比较豪放的人,仅仅用“1”表示很难表示这个豪放的人的真实表征。所以可能需要一串数字才能比较清晰地表示某一类事物的特征。
learnpytorch.io中举例是用一张图片来进行举例,正常一张图片是由3通道(红,绿,蓝)的长宽像素点所组成的,即[channel,height,width]这样的类型来表示这张图片,后面很多的课程都会以图片作为示例进行介绍,大家可以自行补一下计算机视觉方便的基础知识。接下来我们就动手实践使用PyTorch来创建张量。
多维的tensor
首先我们先使用PyTorch来创建一个标量(scalar)初中学过标量可以简单理解为没有方向的数字表示。如下图所示,我们使用torch.tensor方法创建了一个标量未数字101,然后我们打印了引用scalar,可以看见它的输出为tensor(101),接着我们可以查看我们创建的这个张量的属性ndim和方法item() 注意带括号为方法不带括号为属性。
接下来和大家介绍一下这2个比较重要的API,ndim就是表示这个向量嵌套了几层,大家不要紧张,其实很简单,举一个简单的例子,例如在java中,语句int i = 101 这样就是没有嵌套,ndim=0,语句List
标量的ndim其实就是0,接下来就看我们初高中阶段学习的向量(vector),向量是一个单维度的包含多个数字组成的,如下图所示,我们可以仍旧可以使用torch.tensor来创建一个向量,只不过我们这边新增了一个中括号,然后我们现在调用ndim的属性,可以看到这个时候返回的ndim=1,有一个记忆ndim值得小技巧就是可以看下输出tensor中“左中括号”的个数,可以看到这边tensor([6,6])中左中括号的个数是1,ndim的值就是1。在后续实际编程的环节使用shape的这个属性可能更多。
看完了向量,最后我们也可以看下我们在深度学习编程环节中,最多使用的矩阵。可以看到如下jupyter notebook所示,基本上和我们之前说的逻辑是一致的,不过这边就需要注意的属性shape就可以解释成“有2行元素,每一行有2个数值”的初步解释了。这块初步入门就需要掌握这么多,后面还要继续深入其中相关的细节。
接下来就是我们日常初始化项目一些比较常用的API,例如初始化一些随机的tensor,其实深度学习的本质就是先找一些shape与原始数据比较匹配的随机tensor通过不停底训练来调整这些随机的值,直到这些随机的值通过之前设定好的模式进行tensor运算后,最佳的匹配实际值,这样我们就可以获取到两样东西,一个是模型,一个是模型的参数。这样后续我们拿未知的值用同样好的模型和训练好的参数进行运算,就可以得到预测值,其实绝大部分的深度学习和机器学习的逻辑都是如此,所以作为新手的我们,必须夯实基础,学习初始化tensor。
方式一:初始化随机tensor,一般而言有2种方式,一个是torch.rand函数另一个是torch.randn的函数,rand 生成均匀分布的伪随机数。分布在(0~1)之间。randn 生成标准正态分布的伪随机数(均值为0,方差为1),这边需要注意的就是randn是可以生成负数的,这块可以注意一下。
torch.rand和randn的基本使用
方式二:我们都知道神经网络训练的就是我们指定的tensor,把这些tensor通过训练然后在指定的模型中,可以更好地表达我们的输出值,例如一张图片,一段文字,一个图表。所以刚刚开始,这些tensor的值并不是非常重要(当然有一个比较好的分布也是能够帮助我们训练的),但是形状却是非常重要,在后续我们学习矩阵乘法的时候,就会知道形状不对,神经网络前向传播的时候就会报错,所以我们就需要很好地指定tensor的形状和数值类型。如下图所示,我们使用torch.zeros的API,创建3行4列数值全部为0,数值类型全部为torch.float32,值全部在cpu上的张量。大家这边需要加深印象,torch.randn和torch.zeros后续在实战中用的也是比较多的,大家应该勤加练习。
torch.zeros的API使用
方式三:日常PyTorch的开发,创建一个范围张量和与一个张量形状一致的张量的API的场景也是比较多的,这块大家可以死记硬背一下,暂时加深印象,后续实际使用的时候,也可以多练习,第一个就是torch.arange API 这个API大家可以这么记忆,一共有三个参数:
- 第一个是start,表示这个tensor的第一个值从多少开始。
- 第二个参数是end,表示到什么元素结束。
- 第三个参数就是每次前进多少步距。
这边我们如下进行记忆,和我们的for循环比较像,左闭右开,例如从0开始,到10结束,每次步距是1。注意是左闭右开,所以这个tensor最终是不包含10的,如下所示
torch.arange的API演示
还有另一个日常也比较常用的torch.linspace的API,和torch.arange也比较像,不过不是左闭右开,而是左闭右闭的,最后一个参数的含义也变了,不是步距,而是这个创建的tensor需要包含多少个元素。如下演示:
torch.linspace的API演示
最后一个用的比较多的就是torch.zeros_like这样的API,顾名思义就是创建一个和某某某tensor形状一样,但是所有元素都是0的tensor,这样的话可以方便进行tensor的操作。
torch.zeros_like的API使用
最后我们再提一下tensor的核心三个要素,我作为一个初学者,确实还是很容易犯错的,犯错最多的其实是tensor的shape比较难懂,特别是计算机视觉那一块,需要花费很多的功夫和时间去体会,否则真的不会清楚其中tensor形状经过一个操作后的变化。当然这边也是有一定的技巧的,其次就是tensor的类型,这块犯错也还好,主要PyTorch错误提示也比较明显,改起来也比较快速,最后一个就是CPU还是GPU,这块初学者反而并不是很容易犯错,主要是我自己一开始也没有GPU的机器,都是跑在CPU上,所以出错的概率会小很多。
- tensor的形状(shape)
- tensor里数值的类型(dtype)
- tensor元素所在的介质,CPU还是GPU
其实本小节的内容还是非常简单,但是也是非常实用的,后续在构建网络模型的时候,上述的一些创建tensor的API都是一些非常常见的操作。但是我们并没有完全列举,还有一些常用的,大家在遇到的时候,可以去翻阅PyTorch的文档,然后在jupyter lab里面手写一遍,后面基本上就认识了。后续我们也会加快阅读和一起学习的节奏(主要国庆后公司的工作太忙了)。
如果大家喜欢一起学习的方式,希望大家点赞关注,一起迈入深度学习的大门,大家Q4加油,还有最后一点如文章的开头一样提示大家,就是希望大家多练习,动手敲代码,找感觉,否则不会有好的效果。
重要的事情说3遍,敲代码,敲代码,敲代码