ayooshkathuria / YOLO_v3_tutorial_from_scratch

Accompanying code for Paperspace tutorial series "How to Implement YOLO v3 Object Detector from Scratch"
https://blog.paperspace.com/how-to-implement-a-yolo-object-detector-in-pytorch/
2.32k stars 725 forks source link

Help me from tutorial code error. #7

Open omg777 opened 6 years ago

omg777 commented 6 years ago

Thanks for your tutorial from scratch. It helps me a lot. In article part 3, there are some codes you wrote. I copy that codes but some error for me.

model = Darknet("cfg/yolov3.cfg")
inp = get_test_input()
pred = model(inp)
print (pred)

TypeError: forward() missing 1 required positional argument: 'CUDA'

and I want to ask you that training module is the only left work

ayooshkathuria commented 6 years ago

Umm, That's an error on my part. I've fixed it in the tutorial. If you see the definition of forward,

def forward(self, x, CUDA):
    modules = self.blocks[1:]
    outputs = {}   #We cache the outputs for the route layer

We have two args, and CUDA is the one which decides whether you wanna use GPU or not.

Replace the line

pred = model(inp)

by

pred = model(inp, torch.cuda.is_available())

Updated the blog too.

omg777 commented 6 years ago

@ayooshkathuria

TypeError: add_ received an invalid combination of arguments - got (torch.cuda.FloatTensor), but expected one of:
 * (float value)
      didn't match because some of the arguments have invalid types: (!torch.cuda.FloatTensor!)
 * (torch.FloatTensor other)
      didn't match because some of the arguments have invalid types: (!torch.cuda.FloatTensor!)
 * (torch.SparseFloatTensor other)
      didn't match because some of the arguments have invalid types: (!torch.cuda.FloatTensor!)
 * (float value, torch.FloatTensor other)
 * (float value, torch.SparseFloatTensor other)
ayooshkathuria commented 6 years ago

At what line are you getting this error?

This is error is prolly being generated by trying to add two tensors one of which is a cuda tensors and other is a CPU tensor.

Which version of PyTorch you're on as well?

ayooshkathuria commented 6 years ago

Hey? Did you solve your issue?

noirblack commented 6 years ago

@ayooshkathuria I got the same error as @omg777 at this line: prediction[:, :, :2] += x_y_offset my PyTorch version is 0.3.0.post4, CUDA7.5

noirblack commented 6 years ago

@ayooshkathuria I debug predict_transform, and find that, x_y_offset is cuda tensors, prediction is not cuda tensors.

I think that most of the darknet is not running on GPU, I add:

def forward(self, x, CUDA):
    if CUDA:
        x = x.cuda()

to change the input image into cuda variables and add:

    if CUDA:
        module = module.cuda()
    module_list.append(module)

to change the module parameters into cuda variables

Finally, the test forward pass result is: ( 0 ,.,.) = 15.3653 15.1631 82.1072 ... 0.4796 0.5119 0.5580 17.7080 16.1629 130.4487 ... 0.4602 0.4873 0.4512 16.4433 14.4144 265.2342 ... 0.4617 0.5766 0.5741 ... ⋱ ...
411.8746 412.0942 9.9459 ... 0.5417 0.4852 0.5150 412.0383 412.2539 17.8763 ... 0.5541 0.5176 0.5344 411.9370 412.5887 38.4126 ... 0.4333 0.5321 0.4493 [torch.cuda.FloatTensor of size 1x10647x85 (GPU 0)]

RyanCV commented 6 years ago

@noirblack Hi, where did u add the following code to solve the problem? Thx.

if CUDA:
        module = module.cuda()
    module_list.append(module)
RyanCV commented 6 years ago

Hi @ayooshkathuria , I use pytroch with torch Version: 0.4.0 but got the following errors, could you give some help? Thanks.

**python detect.py --images dog-cycle-car.png --det det**
Loading network.....
Network successfully loaded
/python3.5.2/lib/python3.5/site-packages/torch/nn/functional.py:1749: UserWarning: Default upsampling behavior when mode=bilinear is changed to align_corners=False since 0.4.0. Please specify align_corners=True if the old behavior is desired. See the documentation of nn.Upsample for details.
  "See the documentation of nn.Upsample for details.".format(mode))
detect.py:186: UserWarning: volatile was removed and now has no effect. Use `with torch.no_grad():` instead.
  prediction = model(Variable(batch, volatile = True), CUDA)
Traceback (most recent call last):
  File "detect.py", line 199, in <module>
    prediction = write_results(prediction, confidence, num_classes, nms = True, nms_conf = nms_thesh)
  File "/pytorch-yolo-v3-master/util.py", line 181, in write_results
    ious = bbox_iou(image_pred_class[i].unsqueeze(0), image_pred_class[i+1:])
  File "/pytorch-yolo-v3-master/bbox.py", line 73, in bbox_iou
    iou = inter_area / (b1_area + b2_area - inter_area)
RuntimeError: Expected object of type torch.cuda.FloatTensor but found type torch.FloatTensor for argument #3 'other'
noirblack commented 6 years ago

@RyanCV In the function create_modules() add

if CUDA: module = module.cuda()

before

module_list.append(module)

I find that @ayooshkathuria had change the module into cuda model in detect.py, so I add this just in order to pass the forward test.

ayooshkathuria commented 6 years ago

@RyanCV @noirblack Instead of modifying the code inside the create_module function simply do,

CUDA = torch.cuda.is_avaliable()
model = Darknet("cfg/yolov3.cfg")
if CUDA:
    model = model.cuda()
inp = get_test_input()
pred = model(inp, CUDA)
print (pred)

I'll update the blog too.

kakutit commented 6 years ago

I followed noirblack's approach but got error like below.

################################################## File "darknet.py", line 233, in model = Darknet("cfg/yolov3.cfg") File "darknet.py", line 168, in init self.net_info, self.module_list = create_modules(self.blocks) File "darknet.py", line 152, in create_modules if CUDA: NameError: name 'CUDA' is not defined ##################################################

maybe it's my missunderstanding, i put the whole darknet.py code above. ################################################## from future import division

import torch import torch.nn as nn import torch.nn.functional as F from torch.autograd import Variable import numpy as np

from util import *

def get_testinput(): img = cv2.imread("dog-cycle-car.png") img = cv2.resize(img, (416,416)) #resize to the input dimension img = img[:,:,::-1].transpose((2,0,1)) #BGR -> RGB | HXWC -> CXHXW img = img[np.newaxis,:,:,:]/255.0 #add a channel at 0 (for batch) | Normalise img_ = torch.fromnumpy(img).float() #convert to float img = Variable(img) #convert to variable return img_

def parse_cfg(cfgfile): file = open(cfgfile, "r") lines = file.read().split("\n") lines = [x for x in lines if len(x) > 0] #store the lines in a list lines = [x for x in lines if x[0] != "#"] #get read of the empty lines lines = [x.rstrip() for x in lines] #get rid of comments

block = {}
blocks = []

for line in lines:
    if line[0] == "[":
        if len(block) != 0:
            blocks.append(block)
            block = {}
        block["type"] = line[1:-1].rstrip()
    else:
        key, value = line.split("=")
        block[key.rstrip()] = value.lstrip()
blocks.append(block)

return blocks

class EmptyLayer(nn.Module): def init(self): super(EmptyLayer, self).init()

class DetectionLayer(nn.Module): def init(self, anchors): super(DetectionLayer, self).init() self.anchors = anchors

def create_modules(blocks): net_info = blocks[0] module_list = nn.ModuleList() prev_filters = 3 output_filters = []

for index, x in enumerate(blocks[1:]):
    module = nn.Sequential()

    #check the type of block
    #create a new module for the block
    #append to module_list

    #if it is a convolutional layer
    if (x["type"] == "convolutional"):
        #get the info about the layer
        activation = x["activation"]

        try:
            batch_normalize = int(x["batch_normalize"])
            bias = False
        except:
            batch_normalize = 0
            bias = True

        filters = int(x["filters"])
        padding = int(x["pad"])
        kernel_size = int(x["size"])
        stride = int(x["stride"])

        if padding:
            pad = (kernel_size - 1)/2
        else:
            pad = 0

        #add the convolutional layer
        conv = nn.Conv2d(prev_filters, filters, kernel_size, stride, pad, bias = bias)
        module.add_module("conv_{0}".format(index), conv)

        #add the batch norm layer
        if batch_normalize:
            bn = nn.BatchNorm2d(filters)
            module.add_module("batch_norm_{0}".format(index), bn)

        #check the activation
        #it si either linear or a leaky relu for YOLO
        if activation == "leaky":
            activn = nn.LeakyReLU(0.1, inplace = "True")
            module.add_module("leaky_{0}".format(index), activn)

        #if it's an upsampling layer
        #we use bilinear2dupsampling
    elif (x["type"] == "upsample"):
        stride = int(x["stride"])
        upsample = nn.Upsample(scale_factor = 2, mode = "nearest")
        module.add_module("upsample_{}".format(index), upsample)

    #if its a route layer
    elif (x["type"] == "route"):
        x["layers"] = x["layers"].split(",")
        #start of a route
        start = int(x["layers"][0])
        #end, if there exists one
        try:
            end = int(x["layers"][1])
        except:
            end = 0
        #positive anotation
        if start > 0:
            start = start - index
        if end > 0:
            end = end - index
        route = EmptyLayer()

        module.add_module("route_{0}".format(index), route)
        if end < 0:
            filters = output_filters[index + start] + output_filters[index + end]
        else:
            filters = output_filters[index + start]

    #shortcut corresponds to skip connection
    elif x["type"] == "shortcut":
        shortcut = EmptyLayer()
        module.add_module("shortcut_{}".format(index), shortcut)

    #yolo is the detection layer
    elif x["type"] == "yolo":
        mask = x["mask"].split(",")
        mask = [int(x) for x in mask]

        anchors = x["anchors"].split(",")
        anchors = [int(a) for a in anchors]
        anchors = [(anchors[i], anchors[i+1]) for i in range(0, len(anchors), 2)]
        anchors = [anchors[i] for i in mask]

        detection = DetectionLayer(anchors)
        module.add_module("Detection_{}".format(index), detection)

    if CUDA:
        module = module.cuda()
    module_list.append(module)
    prev_filters = filters
    output_filters.append(filters)

return (net_info, module_list)

blocks = parse_cfg("cfg/yolov3.cfg")

print(create_modules(blocks))

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):

    if CUDA:
        x = x.cuda()
    modules = self.blocks[1:]
    outputs = {}# 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 == "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:
                detections = x
                write = 1

            else:
                detections = torch.cat((detections, x), 1)

        outputs[i] = x

    return detections

#####################################

CUDA = torch.cuda.is_available()

#####################################

model = Darknet("cfg/yolov3.cfg")

#####################################

if CUDA:

model = model.cuda()

##################################### inp = get_test_input() pred = model(inp, torch.cuda.is_available()) #####################################

pred = model(inp, CUDA)

##################################### print(pred)

peterhhchan commented 4 years ago

Might also be necessary to move the input tensor to the correct device as well:

CUDA = torch.cuda.is_avaliable()
model = Darknet("cfg/yolov3.cfg")
inp = get_test_input()

if CUDA:
    model = model.cuda()
    inp = inp.cuda()
pred = model(inp, CUDA)
print (pred)