Pytorch构建神经网络(一)
2、张量
2.6、函 数解释——张量的重塑
t = torch.tensor([[1,1,1,1],
[2,2,2,2],
[3,3,3,3]], dtype=torch.float32)
t.numel()和torch.tensor(t.shape).prod()
用于获取tensor的元素个数
t.numel()
torch.tensor(t.shape).prod()
out:
12
tensor(12)
t.view()和t.reshape()
用于修改tensor的形状
print(t.reshape(1,12))
t4 = t.view(t.numel())
print(t4)
out:
tensor([1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.])
tensor([1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.])
注意:
相同之处
都可以用来重新调整 tensor 的形状。
不同之处
1.view 函数只能用于 contiguous 后的 tensor 上,也就是只能用于内存中连续存储的 tensor。如果对 tensor 调用过 transpose, permute 等操作的话会使该 tensor 在内存中变得不再连续,此时就不能再调用 view 函数。因此,需要先使用 contiguous 来返回一个 contiguous copy。
2.reshape 则不需要依赖目标 tensor 是否在内存中是连续的。
t.flatten()
flatten张量:除去所有的轴,只保留一个,创造一个单轴张量包含原张量所有元素;
flatten操作是从一个卷积层过度到一个全连接层时在神经网络中必须发生的;
flatten操作是一种特殊的reshaping操作,即所有轴被挤压成一个轴
# 方法1:
def flatten(t):
t1 = t.reshape(1,-1) # -1:根据输入t的总元素数确定该值为多少
t1 = t1.squeeze()
return t1
print(flatten(t))
# 方法2:
t5 = t.flatten()
print(t5)
out:
tensor([1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.])
tensor([1., 1., 1., 1., 2., 2., 2., 2., 3., 3., 3., 3.])
2.7多批次张量的flatten
flatten操作的前提:张量至少有两个轴
全连接层接收被flatten的张量来作为输入
多批次张量的flatten:保持batch的长度不变,只flatten图像通道部分
# t1,t2,t3为三个4x4的图像
t1 = torch.tensor([
[1,1,1,1],
[1,1,1,1],
[1,1,1,1],
[1,1,1,1]
])
t2 = torch.tensor([
[2,2,2,2],
[2,2,2,2],
[2,2,2,2],
[2,2,2,2]
])
t3 = torch.tensor([
[3,3,3,3],
[3,3,3,3],
[3,3,3,3],
[3,3,3,3]
])
# 使用stack将其合并成一个秩为3的张量
t = torch.stack((t1,t2,t3))
print(t.shape)
# 增加一个彩色通道轴,将其变成CNN期望的形式,以上三张图像均为灰度图像
t = t.reshape(3,1,4,4)
print(t[0]) # 第一个图像
print(t[0][0]) # 第一个图像的第一个通道
print(t[0][0][0]) # 第一个图像的第一个通道中的第一行像素
print(t[0][0][0][0]) # 第一个图像的第一个通道中的第一行的第一个像素
# 该张量的flatten:我们期望只将图像张量flatten,而不是全部flatten
print(t.flatten(start_dim=1).shape)
print(t.flatten(start_dim=1)) # 参数start_dim告诉flatten函数应该从哪个轴开始
输出:
torch.Size([3, 4, 4])
tensor([[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]]])
tensor([[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]])
tensor([1, 1, 1, 1])
tensor(1)
torch.Size([3, 16])
tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]])
2.8 张量的操作
2.8.2 张量的广播
张量的广播:定义了在元素操作的过程中如何处理不同形状的张量,即:将标量变成与另一个张量相同的形状
张量广播在数据标准化时会常用到
NumPy 广播(Broadcast)
这个链接中有一些具体的定义和细节
import torch
import numpy as np
t1 = torch.tensor([
[1,1],
[1,1]
])
t2 = torch.tensor([2,4])
print(t1+t2)
np.broadcast_to(t2.numpy,t1.shape) #广播
t1 + t2
输出:
tensor([[3, 5],
[3, 5]])
tensor([[3, 5],
[3, 5]])
2.8.3 张量的比较运算
会返回一个与比较张量形状相同的张量,其值为0或1(0表示False;1表示True)
element-wise,component-wise以及point-wise的操作方式均相同
t.le(7) # 指元素小于或等于7
t.lt(0) #
t.eq(0) # 指元素等于0
t.ge(0) #
t.abs() # 取绝对值
t.sqrt() # 开平方
t.neg() # 加上负号
2.9 张量的缩减操作(reduction)
缩减操作是一个减少张量中包含的元素数量的操作
元素操作允许我们对多个张量进行操作;缩减操作允许我们对单个张量进行操作
求和操作是缩减操作,缩减操作还有:
t.sum()
t.prod()
t.mean()
t.std()
# 缩减操作通常允许跨数据结构计算总值
# 对某个轴进行缩减操作
t = torch.tensor([
[1,1,1,1],
[2,2,2,2],
[3,3,3,3]
], dtype=torch.float32)
out:
t.sum(dim=0)
tensor([6., 6., 6., 6.])
t.sum(dim=1)
tensor([ 4., 8., 12.])
argmax函数:得到张量的最大输出值的对应索引位置
在实际应用中,经常在神经网络输出预测张量上使用argmax,确定哪个类别的预测最高
t = torch.tensor([
[1,0,0,2],
[0,3,3,0],
[4,0,0,5]
], dtype=torch.float32)
t.max()
tensor(5.)
t.argmax() # 输出的是flatten后的索引
tensor(11) # 输出的坐标是从0开始的