0%

深度学习-3.day

从张量基础知识开始

学到的

·张量,是pytorch中的最基本的数据结构

·张量的索引与运算

·与NumPy多维数组交互操作

·将计算移动到GPU以提高速度

深度学习实际上需要构建一个能将数据从一种转化为另一种表示的系统,系统可以正确的将具有给定形状和颜色的图像映射到标签上

实际数据转化为浮点数

浮点数是网络处理信息的方式,深度学习的神经网络通常在不同阶段学习将数据从一种形式转化为另一种形式,每一个阶段转换的数据可以被认为是一个中间表征序列,这些中间表征都是浮点数的集合

1
输入表征(像素值)------->中间表征(浮点数集合)------->输出表征(类的概率)

开始将数据转化为浮点数输入之前,必须要对pytorch如何处理和存储数据有深入的理解

为此,pytorch引入了张量这个而基本的数据结构,在深度学习中张量可以将向量和矩阵推广到任意维度

张量:多维数组

从列表到张量

列表的索引的作用是众所周知的,可以用对应的索引来访问相对应位置的数据,这可以用来类比张量中的索引

构造第一个张量

来构造第一个pytorch张量

1
2
3
4
5
6
import torch
a = torch.ones(3)
# 解释:torch.ones(3)创建了一个长度为3的一维张量,其中所有元素都被初始化为1
# 所以当我们打印这个张量时,会看到3个1
print(f"这是一个一维张量,包含 {len(a)} 个元素: {a}")
print(a[1])#访问到第二个位置的数据

虽然看起来和列表差不多,但实际上是完全不一样的

张量的本质

张量通常是连续的内存块的视图,这些内存块包含未装箱的数字类型

假设有一个坐标列表,用它来表示一个几何对象,如一个二维三角形,顶点有三个,我们可以使用一维张量,将x轴坐标储存在偶数索引中,将y轴坐标储存在奇数索引中,而不是在列表中使用数字来 表示坐标,如下所示:

1
2
3
4
5
6
7
points = torch.zeros(6) 
points[0] = 4.0
points[1] = 1.0
points[2] = 5.0
points[3] = 3.0
points[4] = 2.0
points[5] = 1.0

也可以像构造函数传递一个列表达到相同的效果,如下图所示:

1
2
points = torch.tensor([4.0, 1.0, 5.0, 3.0, 2.0, 1.0]) 
points

尽管将第一个索引单独指向二维点而不是点是可行的,我们可以使用一个二维张量

1
2
points = torch.tensor([[4.0, 1.0], [5.0, 3.0], [2.0, 1.0]]) 
points

可以通过shape属性来查看张量的形状

1
2
3
points.shape
输出
torch.Size([3, 2])

我们就可以知道每一个维度上张量的带线啊哦,我们还可以使用zeros方法和ones方法来初始化张量,以元组的形式来指定大小

1
2
3
4
5
6
7
points = torch.zeros(3, 2) 
points

输出
tensor([[0., 0.],
[0., 0.],
[0., 0.]])

我们可以使用两个索引来访问呢张量中单个元素

1
2
3
points[0, 1]
输出
tensor(1.)#返回第0个点的y坐标,可以理解为二维数组访问元素的方法

索引张量

如果我们需要得到张量中除了第一个点之外的所有点,我们九十一使用列表中的切片,如在列表中

1
2
3
4
5
6
7
some_list = list(range(6)) 
some_list[:] #全部切片
some_list[1:4] #第二个到第三个
some_list[1:] #第二个以后
some_list[:4] #第一个到第三个
some_list[::1] #所有元素
some_list[1:4:2]#第二个到第三个,步长为2

在张量中,可以使用相同的表示法,在每一个维度都可以使用范围索引

1
2
3
4
points[1:] #第一行后的所有行,包含所有列
points[1:, :] #第一行后的所有行,所有列
points[1:, 0] #第一行后的所有行,第一列
points[None]#增加大小为1的维度

命名张量

张量的维度或者是坐标轴通常用来表示诸如像素位置或者是颜色通道的信息,当我们需要将一个张量作为索引的时候,我们需要记住维度的顺序并以此顺序些索引

假设有一个img_t的三维向量,为了简单,使用虚拟数据,将其转换为灰度图像,

1
img_t = torch.randn(3, 5, 5) # shape [channels, rows, columns] weights = torch.tensor([0.2126, 0.7152, 0.0722])

如果希望代码具有通用性,从表示为具有高度和宽度的二维张量的灰度图像到添加第三个通道的彩色图像,或者从单幅图像到一批图像,假设增加的维度是2:

1
batch_t = torch.randn(2, 3, 5, 5) # shape [batch, channels, rows, columns]

rgb通道有时候在第0维,有时在第一维,我们可以通过从末端开始计数来归纳,总是在从末端开始的第三维中,因此惰性的未加权平均值可以写成下面的形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
img_gray_naive = img_t.mean(-3) 
batch_gray_naive = batch_t.mean(-3)
img_gray_naive.shape, batch_gray_naive.shape
解释
- 代码功能 :

- img_t.mean(-3) 和 batch_t.mean(-3) 都是沿着通道维度(第-3维)计算平均值
- 这种计算方式被称为"惰性"或"未加权"灰度转换,因为它简单地对RGB通道取均值
- 维度解释 :

- 对于单张图像 img_t (形状为 [C,H,W]):
- -3 表示通道维度(通常是第0维)
- 计算后会得到形状为 [H,W] 的灰度图
- 对于批量图像 batch_t (形状为 [N,C,H,W]):
- -3 仍然是通道维度(第1维)
- 计算后会得到形状为 [N,H,W] 的批量灰度图

灰度图:灰度图(Grayscale Image)是指仅包含亮度信息而不包含颜色信息的图像

pytorch允许我们对相同形状的张量进行乘法运算,也允许与给定维度中其中一个操作数大小为1的张量进行计算,他还会自动附加大小为1 的前导维度,这个特性别称之为广播

当创建和使用张量的位置在很远的时候,就很容易出现错误,可以给维度指定一个名称,

1
2
3
weights_named = torch.tensor([0.2126, 0.7152, 0.0722], names=['channels']) weights_named
输出
tensor([0.2126, 0.7152, 0.0722], names=('channels',))

当我们已经有一个张量并且想要为其添加名称但不改变现有的名称时,我们可以对其调用refine_names()方法。与索引类似,省略号(…)允许你省略任意数量的维度。使用rename()兄弟方法,还可以覆盖或删除(通过传入None)现有名称:

1
2
3
4
5
img_named = img_t.refine_names(..., 'channels', 'rows', 'columns') batch_named = batch_t.refine_names(..., 'channels', 'rows', 'columns') 
print("img named:", img_named.shape, img_named.names)
print("batch named:", batch_named.shape, batch_named.names)

img named: torch.Size([3, 5, 5]) ('channels', 'rows', 'columns') batch named: torch.Size([2, 3, 5, 5]) (None, 'channels', 'rows', 'columns')