权重的初始化
一般使用nn.init.xavier_uniform_()初始化权重
用nn.init.constant_(i.bias,0)初始化偏置,置为0
具体目前不太懂,先记着
for i in model.modules():
# i和nn.Conv2d类型一致
if isinstance(i,nn.Conv2d):
# xavier_uniform 一种初始化方法
nn.init.xavier_uniform_(i.weight)
if i.bias is not None:
# .constant 用一个数填充
nn.init.constant_(i.bias,0)
elif isinstance(i,nn.Linear):
nn.init.xavier_uniform_(i.weight)
nn.init.constant_(i.bias,0)
加载搭建好的backbone的部分模型并修改步长
都是经过test后的一点猜测
用list(model.children())来将实例化的模型转化成列表访问
列表里每一个元素都是forward里的一个self.xxxx()的实例化操作
Sequential 作为一个嵌套列表
但是遇到了定义的Bottleneck类就不能继续访问了,必须再次使用model.children()打开
from resnet_50 import resnet_50
model = resnet_50(224)
# model得是一个继承自nn.Module的一个类 用model.children()来打开
# list(model.children())转换成list
resnet_50_d = list(model.children())
print(resnet_50_d)
# 该list的每一元素对应于resnet_50类里forward的每一个实例操作self.xxxx(x)
print(resnet_50_d[0])
# nn.Sequential()也可以被作为list中嵌套的一个list访问
print(resnet_50_d[3][0])
# 但是遇到了定义的Bottleneck类就不能继续访问了,必须再次使用model.children()打开
# print(resnet_50_d[3][0][0])
bottleneck = resnet_50_d[3][0]
bottleneck_d = list(bottleneck.children())
print(bottleneck_d)
# 访问到nn.conv等pytorch的基本类,就可以修改stride的值了
bottleneck_d[0].stride = (3,3)
print(bottleneck_d)
卷积计算公式
N = (W − F + 2P )/S+1
卷积向下取整,池化向上取整
Maxpool2d中ceil_mode = True 时 向上取整
boxes格式
[batch, 4, num_anchors]
获取损失计算的正样本
先对所有损失降序再升序,在进行lt判断 得到的bool可以确定前neg_num个损失最大的参数
mask = torch.gt(g_label, 0)
# 选损失值最大的一部分作为负样本
# 对所有损失降序再升序
_, conf_idx = conf_all_loss.sort(dim=1, descending=True)
_, conf_rank = conf_idx.sort(dim=1)
# 前negative_num的掩摸
negative_mask = torch.lt(conf_rank, negative_num)
交换维度
permute:
permute(a,b,c,d)原来的a维度作为新的0维度,以此类推
a=torch.rand(4,3,28,32)
a.permute(0,2,3,1).shape
torch.Size([4,28,32,3])
transpose:
transpose:交换两个维度
a=torch.rand(4,3,28,32)
a.transpose(1,3).shape
torch.Size([4,32,28,3])
拆分Tensor
tensor.split(大小,维度)
x = tensor([[0.3671, 0.3908, 0.0952, 0.7797, 0.8647, 0.4163, 0.2684, 0.0373],
[0.4714, 0.8399, 0.4101, 0.5223, 0.8602, 0.5641, 0.0650, 0.4025]])
x.split(2,1)
tensor([[0.3671, 0.3908],
[0.4714, 0.8399]])
tensor([[0.0952, 0.7797],
[0.4101, 0.5223]])
tensor([[0.8647, 0.4163],
[0.8602, 0.5641]])
tensor([[0.2684, 0.0373],
[0.0650, 0.4025]])
扩充
推荐tenor.repeat(a,b,c)对应维度重复a或b或c次
a.repeat(1,1).size() # 原始值:torch.Size([33, 55])
torch.Size([33, 55])
a.repeat(2,1).size() # 原始值:torch.Size([33, 55])
torch.Size([66, 55])
a.repeat(1,2).size() # 原始值:torch.Size([33, 55])
torch.Size([33, 110])
a.repeat(1,2,1).size() # 原始值:torch.Size([33, 55])
torch.Size([1, 66, 55])
筛选
torch.gt() 和 torch.nonzero()
torch.gt()一般用作掩摸,返回的是和输入一样尺寸的bool矩阵
x = torch.Tensor([[2,1,4,0,2,4,5],[3,2,0,7,0,3,2]])
y = torch.gt(x,1)
tensor([[ True, False, True, False, True, True, True],
[ True, True, False, True, False, True, True]])
torch.nonzero()返回满足条件的坐标,一般用来剔除不需要的
当as_tuple = True是,按每个维度返回,可以用来筛选
x = torch.Tensor([[2,1,4,0,2,4,5],[3,2,0,7,0,3,2]])
y = torch.nonzero(x>3)
tensor([[0, 2],
[0, 5],
[0, 6],
[1, 3]])
y = torch.nonzero(x>3,as_tuple=True)
(tensor([0, 0, 0, 1]), tensor([2, 5, 6, 3]))
print(x[y])
tensor([4., 4., 5., 7.])
将pytorch模型转换成onnx模型
torch.onnx.export(model ,input,verbose)
model :要转换的模型(先加载好权重)
input:模型需要输入
verbose:是否打印出一个导出轨迹的调试描述
首先要将模型转换为推理模式:model.eval()
随机生成一个输入:dummy_input=torch.randn(32, 3, 224, 224)
生成onnx文件:torch.onnx.export(model, dummy_input, “model.onnx”, verbose=False)
onnx模型转换成trt文件
使用以下命令
#USE_FP16表示是否使用fp16精度
# 假设之前保存的文件为resnet50_pytorch.onnx
if USE_FP16:
!trtexec --onnx=resnet50_pytorch.onnx --saveEngine=resnet_engine_pytorch.trt --explicitBatch --inputIOFormats=fp16:chw --outputIOFormats=fp16:chw --fp16
else:
!trtexec --onnx=resnet50_pytorch.onnx --saveEngine=resnet_engine_pytorch.trt --explicitBatch
使用trt文件进行推理
#
import tensorrt as trt
import pycuda.driver as cuda
import pycuda.autoinit
f = open("resnet_engine_pytorch.trt", "rb")
runtime = trt.Runtime(trt.Logger(trt.Logger.WARNING))
engine = runtime.deserialize_cuda_engine(f.read())
context = engine.create_execution_context()
import numpy as np
# 设置好输入和输出精度
output = np.empty([BATCH_SIZE, 1000], dtype = target_dtype)
# 分配内存
d_input = cuda.mem_alloc(1 * input_batch.nbytes)
d_output = cuda.mem_alloc(1 * output.nbytes)
bindings = [int(d_input), int(d_output)]
stream = cuda.Stream()
def predict(batch): # result gets copied into output
# 把输入复制到GPU
cuda.memcpy_htod_async(d_input, batch, stream)
# 运行模型
context.execute_async_v2(bindings, stream.handle, None)
# 输出复制到CPU
cuda.memcpy_dtoh_async(output, d_output, stream)
# 同步线程?
stream.synchronize()
return output
# 调用函数就能得到模型的输出值,输入的是一个batch的图片
pred = predict(preprocessed_images)