Pytorch 딥러닝 프레임워크 YOLOv3 목표 탐지 학습 노트(二) - 네트워크 프레임워크를 만드는 층

개시하다


프로젝트 코드 디렉터리 만들기darknet.py,darknet은 YOLO의 기초 구조 프레임워크입니다. 이 파일은 YOLO 네트워크를 만드는 코드를 포함하고 util을 사용합니다.py 파일에 포함된 여러 가지 유용한 함수 코드는darknet에 대한 것입니다.py 지원, 이 두 파일을 디렉터리에 넣기

프로파일


공식 코드(c 언어)는 프로필을 사용하여 네트워크를 구축하고, cfg 파일은 네트워크 레이아웃, 블록과 블록의 연결을 설명한다.다음 명령으로 네트워크 설정 정보를 다운로드합니다
mkdir cfg
cd cfg
wget https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3.cfg
[convolutional]
batch_normalize=1
filters=64
size=3
stride=2
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=32
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky

[shortcut]
from=-3
activation=linear

우리는 4개의 블록, 3개의 볼륨 및 1개의 짧은 연결층을 보았습니다. 짧은 연결층은 연결을 건너뛰는 데 사용되고 YOLO에는 다섯 가지 층이 사용되었습니다.

볼륨 레이어:

[convolutional]
batch_normalize=1  
filters=64  
size=3  
stride=1  
pad=1  
activation=leaky

짧은 레이어:

[shortcut]
from=-3  
activation=linear

from-3은 단접층의 출력은 앞의 몇 층의feature map과 단접층의 세 번째 층의 역방향 전파에서 얻어진다는 뜻이다

샘플링 레이어:

[upsample]
stride=2

단계 2의 샘플링 레이어

노선층:

[route]
layers = -4

[route]
layers = -1, 61

한 개 혹은 두 개의 값이 있을 수 있다. 한 개의 값이 있을 때 출력은 이 값이 인덱스된 층의 피처맵이 두 개의 값이 있을 때 되돌아온다. 예를 들어 -1,61은 -1과 64 사이의 급수 깊이 차원을 출력한다.

YOLO 레이어:

[yolo]
mask = 0,1,2
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=80
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=1

앙코르스는 9개의 닻을 묘사했다. mask값이 012라는 뜻은 1, 2, 3개의 닻이 사용되었다는 것이다. 각 단원은 3개의 상자를 예측했다. 우리 검측층은 3개의 크기가 있는데 모두 9개의 닻이 있다.

네트워킹

[net]
# Testing
batch=1
subdivisions=1
# Training
# batch=64
# subdivisions=16
width= 320
height = 320
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1

네트워크는 층이 아니라 네트워크 입력 훈련 파라미터의 정보를 묘사했을 뿐 YOLO의 전방향 전파를 하지 않기 때문이다. 그러나 이것은 우리에게 크기 정보를 입력하고 전방향 전파의 닻을 조정할 수 있도록 제공한다.

구성 파일 확인


시작하기 전에darknet에서.py 시작에 필요한 모듈 포함
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

parse 정의cfg 함수, 설정 파일의 경로를 입력으로
def parse_cfg(cfgfile):
    """
    Takes a configuration file
    
    Returns a list of blocks. Each blocks describes a block in the neural
    network to be built. Block is represented as a dictionary in the list
    
    """

모든 블록을 폴더로 저장합니다. cfg 파일을 저장하는 디렉터리부터 다음 코드는 목록의 프로세스를 보여 줍니다.
file = open(cfgfile, 'r')
lines = file.read().split('
') # store the lines in a list lines = [x for x in lines if len(x) > 0] # get read of the empty lines lines = [x for x in lines if x[0] != '#'] # get rid of comments lines = [x.rstrip().lstrip() for x in lines] # get rid of fringe whitespaces

블록을 얻기 위해 Resultant list를 순환합니다
block = {}
blocks = []

for line in lines:
    if line[0] == "[":               # This marks the start of a new block
        if len(block) != 0:          # If block is not empty, implies it is storing values of previous block.
            blocks.append(block)     # add it the blocks list
            block = {}               # re-init the block
        block["type"] = line[1:-1].rstrip()     
    else:
        key,value = line.split("=") 
        block[key.rstrip()] = value.lstrip()
blocks.append(block)

return blocks

블록 작성


저희는 Parse 를 사용합니다.cfg 목록pytorch 모듈은 설정 파일의 블록을 구성합니다. 위에서 언급한 물종층은pytorch가 우리에게 이미 만들어진 권적층과 샘플링층을 제공합니다. 확장nn을 통해 확장해야 합니다.Module 클래스는 우리만의 모듈createmodules 함수 Parsecfg 함수 Blocks 반환
def create_modules(blocks):
    net_info = blocks[0]     #Captures the information about the input and pre-processing    
    module_list = nn.ModuleList()
    prev_filters = 3
    output_filters = []

Blocks를 다시 쓰기 전에 넷을 정의했습니다.info 변수로 네트워크 정보 저장

nn.ModulList


함수가 nn을 반환합니다.ModuleList.이 종류는nn을 포함한다.Module의 대상 목록입니다. 단, nn.ModuleList가 nn으로 추가되었습니다.Module의 구성원일 때,nn.Module의 모든 매개변수는 nn에 있습니다.ModuleList의 객체는 nn.Module의 대상에 인자가 추가되었습니다. 예를 들어 우리가 nn.Module가 구성원으로 추가된 것처럼 우리가 새로운 볼륨층을 정의할 때 볼륨핵의 크기를 정의해야 한다. 볼륨핵의 높이와 너비는 cfg 파일에 의해 제공되고 핵의 깊이는 필터의 수량이다. 이것은 필터의 수량이 볼륨층이 응용된 후에 변수prev 를 기록해야 한다는 것을 의미한다.Filter에서 이것을 완성합니다. 우리는 3으로 초기화합니다. 이미지에 RGB 세 개의 채널이 있기 때문에 매개 변수화 블록의 목록입니다. 각 블록에pytorch 모듈을 생성합니다.
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

nn.Sequential 클래스는 nn을 순서대로 실행하는 데 사용됩니다.모듈 대상, cfg 파일을 보면 블록이 한 층 이상 포함될 수 있음을 알 수 있습니다. 예를 들어 볼륨 형식의 블록은 ReLU 활성화층이 있는 대량 규범층을 제외하고 볼륨층이 있습니다.우리는 nn을 쓴다.Sequential은 이 층과 그의add 를module 기능의 선형 연결은 다음과 같습니다. 저희가 만든 볼륨 샘플링 층입니다.
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 is 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 = "bilinear")
            module.add_module("upsample_{}".format(index), upsample)

단접층


다음은 저희 단접층 코드입니다.
#If it is 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)

노선층을 만드는 코드는 먼저, 우리가 공헌한 값을 풀고, 그것을 활성기에 넣어 목록에 저장합니다.그리고 저희가 EmptyLayer라는 층을 얻었어요.
route = EmptyLayer()
class EmptyLayer(nn.Module):
    def __init__(self):
        super(EmptyLayer, self).__init__()

YOLO 레이어


마지막으로 YOLO 층 코드를 드릴게요.
        #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)

YOLO 체크 레이어, 앵커 체크 레이어를 감지하기 위한 새 레이어 체크 레이어 정의
class DetectionLayer(nn.Module):
    def __init__(self, anchors):
        super(DetectionLayer, self).__init__()
        self.anchors = anchors

순환 마지막에 우리는 약간의 기록을 했다
        module_list.append(module)
        prev_filters = filters
        output_filters.append(filters)

이것은 순환하는 테마를 포함합니다.createmodules 함수의 끝,net 포함info 및 modulelist의 배열
return (net_info, module_list)

검사 코드


darknet에서py 마지막으로 이 말 검사 코드를 추가하고 파일을 실행합니다
blocks = parse_cfg("cfg/yolov3.cfg")
print(create_modules(blocks))

106개의 항목을 포함하는 긴 목록을 볼 수 있다.다음과 같은 코드와 유사하다
  (9): Sequential(
     (conv_9): Conv2d (128, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)
     (batch_norm_9): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True)
     (leaky_9): LeakyReLU(0.1, inplace)
   )
   (10): Sequential(
     (conv_10): Conv2d (64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
     (batch_norm_10): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True)
     (leaky_10): LeakyReLU(0.1, inplace)
   )
   (11): Sequential(
     (shortcut_11): EmptyLayer(
     )

좋은 웹페이지 즐겨찾기