【问题标题】:RuntimeError: Expected object of device type cuda but got device type cpu for argument #1 'self' in call to _thnn_conv2d_forwardRuntimeError:设备类型为 cuda 的预期对象,但在调用 _thnn_conv2d_forward 时获得了参数 #1 'self' 的设备类型 cpu
【发布时间】:2021-04-27 18:42:24
【问题描述】:

我有这个来自 repo 的神经网络:https://github.com/ayooshkathuria/YOLO_v3_tutorial_from_scratch/blob/master/darknet.py

class Darknet(nn.Module):
    def __init__(self, cfgfile):
        super(Darknet, self).__init__()
        self.blocks = parse_cfg(cfgfile)
        self.net_info, self.module_list = create_modules(self.blocks)
        
    def forward(self, x, CUDA):
        modules = self.blocks[1:]
        outputs = {}   #We cache the outputs for the route layer
        
        write = 0
        for i, module in enumerate(modules):        
            module_type = (module["type"])
            
            if module_type == "convolutional" or module_type == "upsample":
                x = self.module_list[i](x)
    
            elif module_type == "route":
                layers = module["layers"]
                layers = [int(a) for a in layers]
    
                if (layers[0]) > 0:
                    layers[0] = layers[0] - i
    
                if len(layers) == 1:
                    x = outputs[i + (layers[0])]
    
                else:
                    if (layers[1]) > 0:
                        layers[1] = layers[1] - i
    
                    map1 = outputs[i + layers[0]]
                    map2 = outputs[i + layers[1]]
                    x = torch.cat((map1, map2), 1)
                
    
            elif  module_type == "shortcut":
                from_ = int(module["from"])
                x = outputs[i-1] + outputs[i+from_]
    
            elif module_type == 'yolo':        
                anchors = self.module_list[i][0].anchors
                #Get the input dimensions
                inp_dim = int (self.net_info["height"])
        
                #Get the number of classes
                num_classes = int (module["classes"])
        
                #Transform 
                x = x.data
                x = predict_transform(x, inp_dim, anchors, num_classes, CUDA)
                if not write:              #if no collector has been intialised. 
                    detections = x
                    write = 1
        
                else:       
                    detections = torch.cat((detections, x), 1)
        
            outputs[i] = x
        
        return detections


    def load_weights(self, weightfile):
        #Open the weights file
        fp = open(weightfile, "rb")
    
        #The first 5 values are header information 
        # 1. Major version number
        # 2. Minor Version Number
        # 3. Subversion number 
        # 4,5. Images seen by the network (during training)
        header = np.fromfile(fp, dtype = np.int32, count = 5)
        self.header = torch.from_numpy(header)
        self.seen = self.header[3]   
        
        weights = np.fromfile(fp, dtype = np.float32)
        
        ptr = 0
        for i in range(len(self.module_list)):
            module_type = self.blocks[i + 1]["type"]
    
            #If module_type is convolutional load weights
            #Otherwise ignore.
            
            if module_type == "convolutional":
                model = self.module_list[i]
                try:
                    batch_normalize = int(self.blocks[i+1]["batch_normalize"])
                except:
                    batch_normalize = 0
            
                conv = model[0]
                
                
                if (batch_normalize):
                    bn = model[1]
        
                    #Get the number of weights of Batch Norm Layer
                    num_bn_biases = bn.bias.numel()
        
                    #Load the weights
                    bn_biases = torch.from_numpy(weights[ptr:ptr + num_bn_biases])
                    ptr += num_bn_biases
        
                    bn_weights = torch.from_numpy(weights[ptr: ptr + num_bn_biases])
                    ptr  += num_bn_biases
        
                    bn_running_mean = torch.from_numpy(weights[ptr: ptr + num_bn_biases])
                    ptr  += num_bn_biases
        
                    bn_running_var = torch.from_numpy(weights[ptr: ptr + num_bn_biases])
                    ptr  += num_bn_biases
        
                    #Cast the loaded weights into dims of model weights. 
                    bn_biases = bn_biases.view_as(bn.bias.data)
                    bn_weights = bn_weights.view_as(bn.weight.data)
                    bn_running_mean = bn_running_mean.view_as(bn.running_mean)
                    bn_running_var = bn_running_var.view_as(bn.running_var)
        
                    #Copy the data to model
                    bn.bias.data.copy_(bn_biases)
                    bn.weight.data.copy_(bn_weights)
                    bn.running_mean.copy_(bn_running_mean)
                    bn.running_var.copy_(bn_running_var)
                
                else:
                    #Number of biases
                    num_biases = conv.bias.numel()
                
                    #Load the weights
                    conv_biases = torch.from_numpy(weights[ptr: ptr + num_biases])
                    ptr = ptr + num_biases
                
                    #reshape the loaded weights according to the dims of the model weights
                    conv_biases = conv_biases.view_as(conv.bias.data)
                
                    #Finally copy the data
                    conv.bias.data.copy_(conv_biases)
                    
                #Let us load the weights for the Convolutional layers
                num_weights = conv.weight.numel()
                
                #Do the same as above for weights
                conv_weights = torch.from_numpy(weights[ptr:ptr+num_weights])
                ptr = ptr + num_weights
                
                conv_weights = conv_weights.view_as(conv.weight.data)
                conv.weight.data.copy_(conv_weights)

当我尝试使用我写的这个检测器对模块进行推理时,出现上述错误?

import cv2
from darknet import Darknet
from util import *
from torch.autograd import Variable
import torch

class ObjectDetector:
    def __init__(self, confidence=0.5, nms_thresh=0.4, reso=416):
        
        #Load Darknet model for object detection
        print("Loading network...")
        self.model = Darknet("cfg/yolov3.cfg")
        self.model.load_weights("yolov3.weights")
        print("Network successfully loaded")

        self.model.net_info["height"] = reso
        self.inp_dim = int(self.model.net_info["height"])
        if torch.cuda.is_available():
            self.model.cuda()

        self.model.eval()

        #Set detector parameters
        self.confidence = confidence
        self.nms_thresh = nms_thresh
        self.reso = reso

        #Load class file
        self.num_classes = 80
        self.classes = load_classes("data/coco.names")

    def detect(self, img):
        img_ = prep_image(img, self.inp_dim)
    
        if torch.cuda.is_available():
            img_.cuda()

        pred = self.model(img_, torch.cuda.is_available())
        res = write_results(pred, self.confidence, self.num_classes)[:,[1,2,3,4,7]] # only take the 4 corner coordinate points and class index
    
        # Create a python list for all the objects with the format [x1,y1,x2,y2,class_name]
        objs = []
        for obj in res:
            _ = obj[:4].tolist()
            _.append(self.classes[int(obj[4])])
            objs.append(_)

        return objs

if __name__=="__main__":
    detector = ObjectDetector()
    img = cv2.imread(input("Input image path: "))
    detector.detect(img)

谁能帮我找出问题,因为我看不到。我在 repo 上设置了一个问题,但没有回复,所以如果这里有人可以提供帮助,那就太好了。

这是完整的错误跟踪:

Traceback (most recent call last):
  File "engine.py", line 133, in <module>
    system.run()
  File "engine.py", line 107, in run
    res = self.detector.detect(img)
  File "/home/greatman/code/vics/describe/detector.py", line 39, in detect
    pred = self.model(img_, torch.cuda.is_available())
  File "/home/greatman/.local/lib/python3.6/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/greatman/code/vics/describe/darknet.py", line 171, in forward
    x = self.module_list[i](x)
  File "/home/greatman/.local/lib/python3.6/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/greatman/.local/lib/python3.6/site-packages/torch/nn/modules/container.py", line 117, in forward
    input = module(input)
  File "/home/greatman/.local/lib/python3.6/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/home/greatman/.local/lib/python3.6/site-packages/torch/nn/modules/conv.py", line 423, in forward
    return self._conv_forward(input, self.weight)
  File "/home/greatman/.local/lib/python3.6/site-packages/torch/nn/modules/conv.py", line 420, in _conv_forward
    self.padding, self.dilation, self.groups)
RuntimeError: Expected object of device type cuda but got device type cpu for argument #1 'self' in call to _thnn_conv2d_forward

【问题讨论】:

  • 您能提供完整的错误跟踪吗?
  • 当然,我编辑了它

标签: python deep-learning pytorch gpu yolo


【解决方案1】:

在张量上调用 .cuda() 将在 CUDA 内存中返回该对象的副本(如果它还没有存在的话)。但是它不会改变它被调用的张量的内存位置。与nn.Modules 不同,model.cuda() 就足够了,您需要将其分配回img = img.cuda()

>>> x = torch.rand(1)
>>> x.cuda()

>>> x.is_cuda
False

对比

>>> x = torch.rand(1)
>>> x = x.cuda()

>>> x.is_cuda
True

因此,在您的代码中,您应该进行以下更改:

    if torch.cuda.is_available():
        img_ = img_.cuda()

【讨论】:

    猜你喜欢
    • 2020-10-08
    • 2020-04-08
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 2020-10-28
    • 2020-03-07
    • 1970-01-01
    相关资源
    最近更新 更多