p6张量——秩、轴、形状
秩:rank of a tensor
一个张量的秩tell us 一个张量有所少个轴
轴:axis of a tensor
即维数
形状:shape of a tensor
形状由轴的长度决定
p7张量概念的使用——CNN
图像的输入看作是CNN的张量,张量的形状编码了所有关于张量、轴、秩和索引的相关信息
cnn的输入形状通常为4,len([ , , , ]) = 4 àmeans 有一个秩为4的张量,他有四个轴
[A0, A1, A2, A3] à 每一个索引都表示了其对应轴的长度
à图像的高度和宽度,用最后两个轴的值来表示 Height/Width
à第二个索引表示颜色通道RGB,用C表示,其值是3,如果使用灰度值的话,值为1;这个轴的解释是在张量穿过一个卷积层之后改变的
Now:使用最后三个索引,我们已经用张量表示了一个完整的图像 [ , C, H, W],即彩色通道、高度、宽度,用三个轴来表示
第一个索引:B à[B, C, H, W],B这个轴的长度告诉我们在这一批中有多少个样本
eg. [3, 1, 28, 28]
可得知:我们有三个图像,每个图像都有一个单独的彩色通道,图像的高度宽度分别为28*28,我们由此可以使用四个索引,在一个特定图像的特定颜色通道中导航到特定的像素。
Q: 张量被卷积层转化后,颜色通道轴的解释是如何变化的?
A: 假设有一个张量,包含来自一个28*28的灰度图像的数据:[1,1,28,28];
现在我们将这个图像传递到我们的cnn并通过第一个卷积层 à张量和基础数据的行传将由卷积运算来改变,通道的数量根据使用的滤波器数量而定。我们把一个输入颜色通道和一个卷积滤波器结合起来,再对其做一个卷积运算,我们得到一个输出通道结果,我们称之为特征映射。
feature:输出代表了图像的特定特征,比如边缘
p8 torch tensor
Tensor
t是一个torch.tensor,pytorch类的实例
dtype、device、layout
dtype指的是在张量中包含的数据类型
device,决定了给定张量的张量计算的位置
strided告诉我们张量数据是如何在内存中布局的
0的索引告诉我们他是我们拥有的第一个gpu
张量之间的张量操作必须与存在于同一设备上的张量发生
创建pytorch张量
torch.Tensor(data)
torch.tensor(data)
torch.as_tensor(data)
torch.from_numpy(data)
0、创建一个numpy数组,然后创建张量
1、torch.Tensor(data):
后面的这个点,代表这些值是浮点数
与其他几个不同在于他是类构造函数
2、torch.tensor(data):
这里得到的数据类型与numpy数组中的输入数据相匹配
3、torch.as_tensor(data):
4、torch.from_numpy(data):
eye、zeros、ones、rand
没有任何数据的情况下创建一个张量
p9 数据转换为pytorch张量(best options)
数据转换为张量的方法有哪些,之间的区别,应该选用哪些选项,哪些是最优的
一个张量的抽象概念和一个pytorch张量的区别在于:pytorch张量给了我们一个具体的实现,可以使用和编码
构造函数(constructor)、工厂函数(facotries)
工厂函数或对象用于创建对象的变成概念,而不是使用构造函数来创建类实例
由此可见,构造函数在构造一个张量时使用全局缺省值,而工厂函数则根据输入推断数据类型
可见float是默认的dtype
工厂函数的输入即输出的类型:
也可以自己设置张量的dtype:
这里虽然输入时int,但是我设置了float,所以是float,构造函数没有这个功能
共享数据share、复制数据copy
可以看到t1,t2在之后改变了数组,但是却并没有影响张量的数据,然而t3,t4中的张量包含了更改后的数据中的相同数据;这种差异是由每个创建方法中分配内存的方式造成的;
t1,t2的创建方法是在内存中创建一个额外的输入数据副本;copy data
t3,t4的创建方法是用数字数组在内存中共享数据;share data
可以实现在一个numpy数组和pytorch张量之间切换,当我们说一个pytorch张量和一个numpy数组共享内存时,我们只是说内存中的实际数据存在于一个地方(比如改变了pytorch张量,然后numpy也自动改变了,反之亦然),共享数据比复制数据更有效,使用更少的内存。
best option
so:torch.as_tensor(data)、torch.from_numpy(data)可以共享数据,那么选择哪一种呢?
best option is:torch.tensor(data) & torch.as_tensor(data)
reason:torch.as_tensor()函数可以接受任何像python数据结构这样的数组
p10 张量操作——重塑操作reshape
主要使用的张量操作通常分为四类:
重塑操作reshape、元素操作element-wise、还原reduction、访问操作access
张量的形状是3*4,第一个轴长度3,第二个轴长度4,第一个轴的元素时数组,第二个轴的元素是数字。
我们有两种方式来访问这个形状
size、shape
size、shape都可以看出是几乘几的数组
len:
这个形状shape的维数:
prod:
把这个形状的状态转换成一个张量,tensor(t.shape)
用prod找出这个张量一共包含了多少个分量(3*4维的数组,所以是3*4 = 12个分量)
prod就看成求乘积的即可(这里是对t.shape的形状求乘积)
numel:
元素数量的缩写 = prod()
reshape:
重塑并没有改变基本数据,只是改变了基本数据的形状
接下来看下该数组重塑的所有可能:
这是一个三维的,有两个部分,每个部分又分别是个2*3的形状
squeeze()压缩、unsqueeze()解压缩
压缩张量可以移除所有长度为1的轴,而解压缩一个张量则会增加一个长度为1的维度
flatten:
压扁一个张量意味着除去所有的轴,只保留一个,他创造了一个单轴的张量,它包含了张量的元素,本质上即:创建了一个一维数组,它包含了张量的所有分量
我们从卷积层获取输出,它以输出通道的形式给我们,如[28,28] à 我们把这些通道变平成一个单一的一维数组[784] 即flattened output
-1,根据一个张量中包含的其他值和元素的个数来求出值应该是多少
本题中这个被重塑的函数将能够计算出第二个轴的长度需要12个,以确保一个张量中的元素空间足够大
cat:
cat函数可以组合两个张量
就张量而言,我们计算他们的方式会影响他们的输出形状
p11 CNN Flatten操作——对灰度图像张量的张量flatten操作
如一个图片 18*18 à 压平成一个长度为324的轴
在全连接层中的每个节点接受这个被flatten的输出作为输入
我们处理一个张量,他是一个包含多个图像的批
我们用一个张量来表示一个完整的批次,所以我们需要把三个张量合并成一个更大的张量,合并之后他有三个轴而不是两个
stack
用stack堆栈函数将三个张量的序列连接到一个新的轴上
这个新轴上有三个张量,新轴的长度是3,[3,4,4]分别是数量、高度、宽度,即有一个秩为3的张量,其中包含了3个4*4的图像
Now:把这个张量变成一个CNN期望的形式,为彩色通道增加一个轴
长度为1的额外轴不会改变张量中元素的数量
含义是:每个Batch中有3个东西,每个东西各自有1个彩色通道Channel,每个东西的彩色通道里分别有4个向量(height)的矩阵,每个向量里又有4个数字(width)
我们分别输出:
Next:如何使这批图像变平?
整批是一个单独的张量,将被传递给CNN,所以不需要整批都变平,只需要将这批张量的图像张量变平
第一种:有四个方法
t.reshape(1,-1)[0]
t.reshape(-1)
t.view(t.numel())
t.flatten()
但是这样压缩不太好,因为将所有的图像都被压缩成一个了,而我们需要对每一个图像进行单独的预测。
于是我们用高度和宽度周来亚平颜色通道轴:flatten
flatten:
start_dim参数,告诉了flatten方法当他开始flatten操作时应该从哪个轴开始
这里start_dim = 1是一个索引,表示第二个轴,就是彩色通道轴,我们跳过了批轴
shape是[3,16]:表示有三个单独的彩色通道图像,他们被压平成一个包含16个像素值的单轴
用reshape可以得到同样的结果:
p12 张量操作——元素的操作element-wise
元素操作是对张量元素的运算,这些张量元素在张量中对应或有相同的索引位置,张量的位置是由用来定位每个元素的索引决定的
如果连个元素在一个张量中占据相同的位置,则由用于定位每个元素的索引决定
一个元素操作——算术运算
两个张量必须具有相同数量的元素才能执行一个元素的操作,更严格的讲,两个张量必须具有相同的形状才能执行一个元素操作
即t1[0][0] + t2[0][0] = 10. t1[0][1] + t2[0][1] = 10. 就是对应相同的位置相加
加减乘除,都是相同的运算
张量广播
广播定义了一个在元素操作过程中如何处理不同形状的张量
通过对numpy函数的广播,我们可以看到在标量值上的广播是什么样子
广播,也就是复制张量的一个或多个轴,使它与另一个张量的形状相同
another example:
显然t1,t2的形状不同
t1 + t2 的运算结果是什么?
较低的秩张量t2将通过广播进行转换,以匹配更高阶张量t1的形状,而元素的操作将像往常一样
可以用numpy函数来检查广播的形状:
可以看到广播后,这两个张量之间的加法运算是具有相同形状的张量之间的正则元素运算
一个元素操作——比较运算
大小于等于
t.le(7):元素<=7
t.eq(0): = 0
t.gt(0): >0
t.le(0): <0
绝对值、根号、负号
t.abs(): 绝对值
t.sqrt(): 开根号
t.neg(): 取负号
p13 张量操作——缩减操作reduction
张量的缩减操作:减少张量中包含的元素数量的操作,允许我们队单个张量中的元素执行操作
t.sum():
求张量中元素的和,1+2+2+3 = 8
t.numel():
求张量中元素的个数
t.sum().numel()
t.prod() / t.mean() / t.std()
torch.mean(input) : 返回平均值
torch.std(input) : 返回标准偏差
torch.prod(input) : 返回所有元素的乘积
dim
其中dim是维数,可以看到dim = 0的时候是数组中所有的位置在0的数字相加的和
也就是说当我们对第一个轴(dim = 0)求和的时候,实际上是取第一个轴的所有元素,即1+2+3 = 6
我们对第二个轴(dim = 1)求和的时候,是取第二个轴的所有元素,比如t[0]的所有元素求和1+1+1+1 = 4
ArgMax简化操作
ArgMax是一个数学函数,当输入的函数作为输入结果时,求出函数的最大值的输出值,即告诉我们一个张量内的最大值的索引位置
但11这个并不是我们想要的,我们想要从[0][0]开始向下走à [1][0]à[2][0]à[2][1]à[2][2]
à[2][3]
于是:分别输出两个轴的最大值
注意,values包含了最大的值,indices包含了这些最大值的索引位置
argmax函数中,第一个轴上的每一个元素都一起索引的形式存在
code中,我们通常在神经网络输出预测张量上使用ArgMax函数,可以确定哪个类别的预测值最高,因为输出张量的每个指标都对应一个特定的预测类
item():
当我们由张量得到某个值,但是想仅仅输出得到的值而不输出tensor这些内容,我们可以用item张量来做
tolist():
在一个张量中访问多个值
竖着看,dim = 0的时候,1,4,7的mean是4,所以输出4.0
或者用numpy