运行pytorch版SSD目标检测网络:https://github.com/amdegroot/ssd.pytorch,使用训练好的模型执行目标检测时(执行demo.py)。出现错误:
:RuntimeError: Legacy autograd function with non-static forward method is deprecated. Please use new-style autograd function with static forward method.
(1)demo.py中出错语句为y = net(xx)
(2)demo.py中出现y = net(xx)
错误的原因是ssd.py中下列语句——(使用Detect类创建对象self.detect执行检测)
(3)查看Detect类,既detection.py文件。因为Detect类继承自Function类,在pytorch1.3及以后的版本需要规定forward方法为静态方法,所以在pytorch1.3以上的版本执行出错。
(1)网上的方法:说要将pytorch的版本降低为1.2及以下的版本。但是我的cuda是10.2,目前不支持1.2及其以下的GPU版的pytorch,为了运行这个代码还要重装cuda、pytorch太麻烦了!!!!!!
(2)自己的方法:修改代码
'''检测模式下的网络输出'''
if self.phase == "test":
# output = self.detect(loc.view(loc.size(0), -1, 4), # 将网络的位置预测表示为(-1,4)形式torch.Size([1, 8732, 4])
# self.softmax(conf.view(conf.size(0), -1,self.num_classes)), # 将网络的置信度预测表示为(-1,5)形式torch.Size([1, 8732, 5])
# self.priors.type(type(x.data)) # 先验anchor box,格式(x,y,w,h)
# )
###########################################################修改代码################################################################
#Detect类不支持静态方法的前向传播,因此使用类直接调用方法
output=self.detect.forward(loc.view(loc.size(0), -1, 4),
self.softmax(conf.view(conf.size(0), -1,self.num_classes)),
self.priors.type(type(x.data)) )
###########################################################修改代码################################################################
box_utils.py文件中的nms函数还需要作相应的修改,否则出错RuntimeError: index_select(): functions with out=… arguments don’t support automatic differentiation, but one of the arguments requires grad.错误
'''nms()函数:非极大值抑制函数。对每一类别分别执行该函数'''
def nms(boxes, scores, overlap=0.5, top_k=200):##参数:边界框精确位置,边界框类别的分数、nms阈值、前200个边界框
'''(1)构建keep张量:初始值为0,形状与预测框的数量相同(预测框的数量为该类,类别置信度大于阈值的预测边界框的数量)'''
keep = scores.new(scores.size(0)).zero_().long()
if boxes.numel() == 0:
return keep
'''(2)计算预测边界框的面积'''
x1 = boxes[:, 0]
y1 = boxes[:, 1]
x2 = boxes[:, 2]
y2 = boxes[:, 3]
area = torch.mul(x2 - x1, y2 - y1)
'''(3)获取 类别置信度分数最高的top_k个 预测边界框的索引'''
v, idx = scores.sort(0) #对类别置信度分数升序排序,返回 按照类别置信度分数排序后的 预测边界框的索引
# I = I[v >= 0.01]
'''类别置信度分数最高的前top_k个预测框的索引:idx '''
idx = idx[-top_k:] # indices of the top-k largest vals
xx1 = boxes.new()
yy1 = boxes.new()
xx2 = boxes.new()
yy2 = boxes.new()
w = boxes.new()
h = boxes.new()
'''(4)将nms后的预测边界框的索引,存入keep'''
count = 0
while idx.numel() > 0:
''''#1.类别置信度分数最高的预测边界框————————索引逐一写入keep'''
i = idx[-1] # index of current largest val
# keep.append(i)
keep[count] = i
count += 1
if idx.size(0) == 1:
break
'''#2.剩余预测边界框的索引'''
idx = idx[:-1] # remove kept element from view
'''#3.计算剩余预测边界框与,分数最高的边界框之间的iou值'''
#####################################添加代码##########################################
#否者出错RuntimeError: index_select(): functions with out=... arguments don't support automatic differentiation, but one of the arguments requires grad.
idx= torch.autograd.Variable(idx, requires_grad=False)
idx = idx.data
x1 = torch.autograd.Variable(x1, requires_grad=False)
x1 = x1.data
y1 = torch.autograd.Variable(y1, requires_grad=False)
y1 = y1.data
x2 = torch.autograd.Variable(x2, requires_grad=False)
x2 = x2.data
y2 = torch.autograd.Variable(y2, requires_grad=False)
y2 = y2.data
######################################添加代码#################################################
torch.index_select(x1, 0, idx, out=xx1)
torch.index_select(y1, 0, idx, out=yy1)
torch.index_select(x2, 0, idx, out=xx2)
torch.index_select(y2, 0, idx, out=yy2)
# store element-wise max with next highest score
xx1 = torch.clamp(xx1, min=x1[i])
yy1 = torch.clamp(yy1, min=y1[i])
xx2 = torch.clamp(xx2, max=x2[i])
yy2 = torch.clamp(yy2, max=y2[i])
w.resize_as_(xx2)
h.resize_as_(yy2)
w = xx2 - xx1
h = yy2 - yy1
# check sizes of xx1 and xx2.. after each iteration
w = torch.clamp(w, min=0.0)
h = torch.clamp(h, min=0.0)
inter = w*h
# IoU = i / (area(a) + area(b) - i)
#####################################添加代码##########################################
#否者出错RuntimeError: index_select(): functions with out=... arguments don't support automatic differentiation, but one of the arguments requires grad.
area = torch.autograd.Variable(area, requires_grad=False)
area = area.data
idx= torch.autograd.Variable(idx, requires_grad=False)
idx = idx.data
######################################添加代码#################################################
rem_areas = torch.index_select(area, 0, idx) # load remaining areas)
union = (rem_areas - inter) + area[i]
IoU = inter/union # store result in iou
# keep only elements with an IoU <= overlap
'''4.保留iou值小于nms阈值的预测边界框的索引'''
idx = idx[IoU.le(overlap)]#保留交并比小于阈值的预测边界框的id
return keep, count