我试图通过ONNX (opset 11)将torch.nn.functional.grid_sample的模型从Pytorch (1.9)转换为使用INT8量化的INT8 (7)。Opset 11不支持将grid_sample转换为ONNX。因此,我将ONNX图形外科医生与外部GridSamplePlugin一起使用,因为它是建议在此。有了它,转换到TensorRT (有和没有INT8量化)是成功的。没有INT8量化的Pytorch和TRT模型提供的结果接近相同的结果(MSE为e-10阶)。但对于具有TensorRT量化的INT8,均方误差要高得多(185)。
grid_sample算子得到两个输入:输入信号和采样网格。两者都应该是同一类型的。在GridSamplePlugin中,只实现了kFLOAT和kHALF的处理。在我的示例中,绝对采样网格中的X坐标(在转换为grid_sample所需的相对坐标之前)在范围内( -d;W+d和-d;H+d用于Y坐标)正在发生变化。W的最大值为640,H的最大值为360,在此范围内坐标可能具有非整数值。出于测试目的,我创建了只包含grid_sample层的测试模型。在这种情况下,TensorRT结果与不带INT8量化的结果是相同的。
下面是测试模型的代码:
import torch
import numpy as np
import cv2
BATCH_SIZE = 1
WIDTH = 640
HEIGHT = 360
def calculate_grid(B, H, W, dtype, device='cuda'):
xx = torch.arange(0, W, device=device).view(1, -1).repeat(H, 1).type(dtype)
yy = torch.arange(0, H, device=device).view(-1, 1).repeat(1, W).type(dtype)
xx = xx + yy * 0.25
if B > 1:
xx = xx.view(1, 1, H, W).repeat(B, 1, 1, 1)
yy = yy.view(1, 1, H, W).repeat(B, 1, 1, 1)
else:
xx = xx.view(1, 1, H, W)
yy = yy.view(1, 1, H, W)
vgrid = torch.cat((xx, yy), 1).type(dtype)
return vgrid.type(dtype)
def modify_grid(vgrid, H, W):
vgrid = torch.cat([
torch.sub(2.0 * vgrid[:, :1, :, :].clone() / max(W - 1, 1), 1.0),
torch.sub(2.0 * vgrid[:, 1:2, :, :].clone() / max(H - 1, 1), 1.0),
vgrid[:, 2:, :, :]], dim=1)
vgrid = vgrid.permute(0, 2, 3, 1)
return vgrid
class GridSamplingBlock(torch.nn.Module):
def __init__(self):
super(GridSamplingBlock, self).__init__()
def forward(self, input, vgrid):
output = torch.nn.functional.grid_sample(input, vgrid)
return output
if __name__ == '__main__':
model = torch.nn.DataParallel(GridSamplingBlock())
model.cuda()
print("Reading inputs")
img = cv2.imread("result/left_frame_rect_0373.png")
img = cv2.resize(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), (WIDTH, HEIGHT))
img_in = torch.from_numpy(img.astype(float)).view(1, 1, HEIGHT, WIDTH).cuda()
vgrid = calculate_grid(BATCH_SIZE, HEIGHT, WIDTH, img_in.dtype)
vgrid = modify_grid(vgrid, HEIGHT, WIDTH)
np.save("result/grid", vgrid.cpu().detach().numpy())
print("Getting output")
with torch.no_grad():
model.module.eval()
img_out = model.module(img_in, vgrid)
img = img_out.cpu().detach().numpy().squeeze()
cv2.imwrite("result/grid_sample_test_output.png", img.astype(np.uint8))TensorRT模型的标定和推理都采用了保存的网格。
所以问题是:
我的环境:
复制步骤:
发布于 2022-03-05 16:12:00
您可以将模型分解为两个部分,一个在网格样本之前,另一个在它之后,并分别进行int8量化。在grid_sample中使用INT8将极大地损害您的模型性能。这将导致您的网络结构发生变化,因此它可能会更改图形的优化。
https://stackoverflow.com/questions/69162186
复制相似问题