文章目录
- 使用thop计算参数时的疑问
- x = x.view(-1, 32 * 8 * 8)和x = x.view(x.size(0), -1)区别是什么
- input_shape = (3, 224, 224)这个张量是什么意思
- 为什么summary计算时没有批次大小
- input_tensor = torch.randn(1, *input_shape).to(device)这句代码什么意思
- flops, params = profile(net, inputs=(input_tensor,))这句话什么意思
- 为什么用inputs=(input_tensor,),而不是inputs=(input_tensor)呢
- flops, params = clever_format([flops, params], "%.3f")这个代码什么意思
使用thop计算参数时的疑问
x = x.view(-1, 32 * 8 * 8)和x = x.view(x.size(0), -1)区别是什么
x.view(-1, 32 * 8 * 8)
和 x.view(x.size(0), -1)
都是将一个多维张量 x
转换为一个二维张量,但是它们的实现方式略有不同。
x.view(-1, 32 * 8 * 8)
的 -1
参数表示该维度的大小由其他维度的大小和张量的总元素个数自动推导而来。在这个例子中,32 * 8 * 8
是张量 x
在第二个维度上的元素个数,而 -1
表示第一个维度的大小应该自动计算以保证张量的总元素个数不变,因此,x.view(-1, 32 * 8 * 8)
的作用是将张量 x
展开为一个二维张量,其中每一行表示一个样本的所有特征向量。
x.view(x.size(0), -1)
的实现方式略有不同,其中 x.size(0)
表示张量 x
在第 0 维的大小,也就是张量的批次大小(batch size)。因此,x.view(x.size(0), -1)
的作用是将张量 x
的第一个维度(批次大小)保持不变,将其余的所有维度展开为一个二维张量,其中每一行表示一个样本的所有特征向量。
总的来说,这两种方法都可以将卷积层的输出展开为一个二维张量以便于传递给全连接层进行分类或回归任务。两种方法的区别在于 -1
参数的使用方式,其中 x.view(-1, 32 * 8 * 8)
更加简洁,但是需要确保张量的总元素个数不变,而 x.view(x.size(0), -1)
则需要显式地指定批次大小以及展开后的维度大小,但是更加灵活。
input_shape = (3, 224, 224)这个张量是什么意思
input_shape = (3, 224, 224)
是一个元组(tuple),其中包含了一个三维张量的形状(shape)。在这个例子中,这个三维张量的形状是 (3, 224, 224)
,它表示一个 RGB 图像,其中包含 3 个颜色通道(红、绿、蓝),每个通道的高度和宽度都是 224 像素。
在深度学习中,通常需要指定输入数据的形状,以便于为模型构建输入层。在这个例子中,input_shape
就是这样一个形状。在定义模型时,可以使用这个形状来定义输入层的大小和形状,以确保模型能够处理输入数据。
需要注意的是,这个元组仅仅是描述了一个形状,它并不是一个实际的张量。要创建一个具有这个形状的张量,可以使用 PyTorch 中的 torch.zeros()
或 torch.ones()
等函数创建一个全零或全一张量,并指定这个张量的形状为 input_shape
。
为什么summary计算时没有批次大小
summary()
函数在计算模型参数数量和 MACs(multiply-accumulate operations)时,并不需要知道批次大小。因此,在调用 summary()
函数时,可以将 input_shape
设置为不包含批次大小的形状。
在这个例子中,input_shape = (3, 224, 224)
表示一个 RGB 图像,其中包含 3 个颜色通道,每个通道的高度和宽度都是 224 像素。在模型的输入层中,通常会将批次大小作为额外的维度添加到输入数据中,因此,对于单张图片来说,其形状应该是 (1, 3, 224, 224)
。
但是,summary()
函数并不需要知道批次大小,因为它只关心模型的结构和参数数量以及 MACs。因此,在调用 summary()
函数时,可以将 input_shape
设置为不包含批次大小的形状,例如 (3, 224, 224)
,而不会影响 summary()
函数的计算结果。
input_tensor = torch.randn(1, *input_shape).to(device)这句代码什么意思
这句代码的作用是创建一个形状为 (1, 3, 224, 224)
的张量 input_tensor
,并将其移动到指定的设备上。
具体来说,这句代码分为两个部分。首先,torch.randn(1, *input_shape)
创建了一个形状为 (1, 3, 224, 224)
的张量 input_tensor
,其中 1 表示批次大小,3 表示颜色通道数,224 表示图像的高度,224 表示图像的宽度。torch.randn()
函数会返回一个张量,其中的元素是从均值为 0,方差为 1 的正态分布中随机采样的。
然后,.to(device)
将张量 input_tensor
移动到指定的设备上,其中 device
是一个 PyTorch 设备对象,表示要将张量移动到哪个设备上。例如,如果 device = 'cpu'
,则将张量移动到 CPU 上;如果 device = 'cuda'
,则将张量移动到 GPU 上。
总的来说,这句代码的作用是创建一个形状为 (1, 3, 224, 224)
的张量 input_tensor
,并将其移动到指定的设备上,以便于将其传递给模型进行计算。这个张量可以表示一个 RGB 图像,其中包含 1 张图片,每张图片包含 3 个颜色通道,每个通道的高度和宽度都是 224 像素。在模型的计算过程中,可以将这个张量传递给模型作为输入数据。
flops, params = profile(net, inputs=(input_tensor,))这句话什么意思
这句代码的作用是使用 PyTorch 的 torch.profiler.profile()
函数,对给定的模型 net
在输入数据 input_tensor
上进行性能分析,并输出模型的计算量和参数数量。
具体来说,profile()
函数接受一个 PyTorch 模型和输入数据,自动计算模型在输入数据上的计算量和参数数量,并返回这两个值。其中,计算量通常使用 FLOPs(floating-point operations)作为衡量标准,表示模型在执行前向传播时需要进行的浮点运算次数;而参数数量则表示模型中需要学习的参数的数量,包括权重和偏置等。
在这个例子中,net
是一个 PyTorch 模型,input_tensor
是一个形状为 (1, 3, 224, 224)
的输入张量,表示一张 RGB 图像。inputs=(input_tensor,)
是一个元组,其中包含了输入数据,用于传递给 profile()
函数。
执行这句代码后,flops
和 params
分别表示模型在输入数据上的 FLOPs 和参数数量。这个结果可以用于评估模型的计算复杂度和内存使用情况,以便于优化模型的性能。
为什么用inputs=(input_tensor,),而不是inputs=(input_tensor)呢
在这个例子中,使用 inputs=(input_tensor,)
的方式传递输入数据是为了满足 profile()
函数的输入要求。
profile()
函数的输入参数 inputs
是一个元组(tuple),其中包含了输入数据。即使只有一个输入张量,也必须将其放在一个元组中传递给 inputs
参数。这是因为 inputs
参数需要接受一个可迭代对象(iterable),而元组是一种可迭代对象,可以用于传递单个或多个输入数据。
在这个例子中,input_tensor
是一个形状为 (1, 3, 224, 224)
的 PyTorch 张量,表示一张 RGB 图像。要将这个张量作为输入数据传递给 profile()
函数,必须将其放在一个元组中,即 (input_tensor,)
。如果直接使用 inputs=(input_tensor)
,则会将整个张量作为输入参数传递给 profile()
函数,而不是放在一个元组中,这会导致参数类型不匹配的错误。
flops, params = clever_format([flops, params], “%.3f”)这个代码什么意思
这句代码的作用是使用 clever_format()
函数,将给定的 FLOPs 和参数数量进行格式化,以便于显示在屏幕上。
具体来说,clever_format()
函数接受一个数字或一个元组,表示要进行格式化的数据。在这个例子中,输入的是一个包含两个数字的元组 [flops, params]
,其中 flops
表示模型的计算量(FLOPs),params
表示模型的参数数量。第二个参数 %.3f
指定了浮点数的格式,其中 %
表示格式化字符串的起始标志,.3
表示保留 3 位小数,f
表示格式化为浮点数。
执行这句代码后,flops
和 params
分别表示格式化后的模型计算量和参数数量,可以直接显示在屏幕上。例如,如果 flops=1234567890
,params=123456
,则执行 clever_format([flops, params], "%.3f")
后的结果可能是 1.235G FLOPs, 123.456K params
,表示模型的计算量约为 1.235 亿次浮点运算,参数数量约为 123,456 个。这个结果可以更加直观地表示模型的复杂度和规模,便于进行模型选择和优化。
这里是这个模型的FLOPs计算步骤:
-
第一个卷积层: 64输出通道,输入大小为224224,卷积核大小33
FLOPs = 64 * 33 * 224224 = 1.579G -
第二个卷积层: 同样64输出通道,输入大小不变
FLOPs = 64 * 33 * 224224 = 1.579G -
池化层后,大小变为112*112
-
第三个卷积层: 128输出通道,输入大小112112,卷积核33
FLOPs = 128 * 33 * 112112 = 0.633G -
第四个卷积层:同样128输出通道,输入大小不变
FLOPs = 128 * 33 * 112112 = 0.633G -
全连接层前,flatten为12888
FLOPs = 12888 * 1024 = 8.388M -
第一个全连接层: 1024个神经元
FLOPs = 88128 * 1024 = 8.388M -
第二个全连接层:10个神经元
FLOPs = 1024 * 10 = 10.24K
总的FLOPs为:
1.579G + 1.579G + 0.633G + 0.633G + 8.388M + 8.388M + 10.24K = 6.357G