Самастойныя аўтамабілі не могуць дазволіць сабе памылак. Прапусціць святлафор або пешахода можа азначаць катастрофу. Але выяўленне аб'ектаў у дынамічным гарадскім асяроддзі? Гэта цяжка.
Я працаваў над аптымізацыяй выяўлення аб'ектаў для аўтаномных транспартных сродкаў з дапамогай Atrous Spatial Pyramid Pooling (ASPP) і Transfer Learning. Вынік? Мадэль, якая выяўляе аб'екты ў розных маштабах, нават пры дрэнным асвятленні, і эфектыўна працуе ў рэжыме рэальнага часу.
Вось як я гэта зрабіў.
Для выяўлення аб'ектаў беспілотныя аўтамабілі выкарыстоўваюць згорткавыя нейронавыя сеткі (CNN) , але ў рэальных умовах узнікаюць праблемы:
Традыцыйныя CNN змагаюцца з шматмаштабным выяўленнем аб'ектаў , і навучанне з нуля займае вечнасць. Вось дзе ASPP і Transfer Learning прыходзяць.
CNN добра працуюць для аб'ектаў фіксаванага памеру, але аб'екты рэальнага свету адрозніваюцца па памеры і адлегласці. Atrous Spatial Pyramid Pooling (ASPP) вырашае гэтую праблему, выкарыстоўваючы пашыраныя звіліны для фіксацыі функцый у розных маштабах.
ASPP прымяняе некалькі фільтраў згорткі з рознымі хуткасцямі пашырэння, каб вылучыць аб'екты з рознымі раздзяленнямі, малыя аб'екты, вялікія аб'екты і ўсё паміж імі.
Вось як я рэалізаваў ASPP у PyTorch, уключыўшы групавую нармалізацыю і ўвагу для надзейнай прадукцыйнасці ў складаных асяроддзях:
import torch import torch.nn as nn import torch.nn.functional as F class ASPP(nn.Module): """ A more advanced ASPP with optional attention and group normalization. """ def __init__(self, in_channels, out_channels, dilation_rates=(6,12,18), groups=8): super(ASPP, self).__init__() self.aspp_branches = nn.ModuleList() #1x1 Conv branch self.aspp_branches.append( nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1, padding=0, bias=False), nn.GroupNorm(groups, out_channels), nn.ReLU(inplace=True) ) ) for rate in dilation_rates: self.aspp_branches.append( nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=rate, dilation=rate, bias=False), nn.GroupNorm(groups, out_channels), nn.ReLU(inplace=True) ) ) #Global average pooling branch self.global_pool = nn.AdaptiveAvgPool2d((1, 1)) self.global_conv = nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1, bias=False), nn.GroupNorm(groups, out_channels), nn.ReLU(inplace=True) ) #Attention mechanism to refine the concatenated features self.attention = nn.Sequential( nn.Conv2d(out_channels*(len(dilation_rates)+2), out_channels, kernel_size =1, bias=False), nn.Sigmoid() ) self.project = nn.Sequential( nn.Conv2d(out_channels*(len(dilation_rates)+2), out_channels, kernel_size=1, bias=False), nn.GroupNorm(groups, out_channels), nn.ReLU(inplace=True) ) def forward(self, x): cat_feats = [] for branch in self.aspp_branches: cat_feats.append(branch(x)) g_feat = self.global_pool(x) g_feat = self.global_conv(g_feat) g_feat = F.interpolate(g_feat, size=x.shape[2:], mode='bilinear', align_corners=False) cat_feats.append(g_feat) #Concatenate along channels x_cat = torch.cat(cat_feats, dim=1) #channel-wise attention att_map = self.attention(x_cat) x_cat = x_cat * att_map out = self.project(x_cat) return out
Навучанне мадэлі выяўлення аб'ектаў з нуля не дае вялікай карысці, калі існуюць папярэдне падрыхтаваныя мадэлі. Трансфернае навучанне дазваляе нам дакладна наладзіць мадэль, якая ўжо разумее аб'екты.
Я выкарыстаў DETR (Detection Transformer), мадэль выяўлення аб'ектаў на аснове трансфарматараў ад Facebook AI. Ён вывучае кантэкст, таму ён не проста знаходзіць знак прыпынку, ён разумее, што гэта частка дарожнай сцэны.
Вось як я наладзіў DETR на наборах даных для самастойнага кіравання:
import torch import torch.nn as nn from transformers import DetrConfig, DetrForObjectDetection class CustomBackbone(nn.Module): def __init__(self, in_channels=3, hidden_dim=256): super(CustomBackbone, self).__init__() # Example: basic conv layers + ASPP self.initial_conv = nn.Sequential( nn.Conv2d(in_channels, 64, kernel_size=7, stride=2, padding=3, bias=False), nn.BatchNorm2d(64), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=3, stride=2, padding=1) ) self.aspp = ASPP(in_channels=64, out_channels=hidden_dim) def forward(self, x): x = self.initial_conv(x) x = self.aspp(x) return x class DETRWithASPP(nn.Module): def __init__(self, num_classes=91): super(DETRWithASPP, self).__init__() self.backbone = CustomBackbone() config = DetrConfig.from_pretrained("facebook/detr-resnet-50") config.num_labels = num_classes self.detr = DetrForObjectDetection.from_pretrained("facebook/detr-resnet-50", config=config) self.detr.model.backbone.body = nn.Identity() def forward(self, images, pixel_masks=None): features = self.backbone(images) feature_dict = { "0": features } outputs = self.detr.model(inputs_embeds=None, pixel_values=None, pixel_mask=pixel_masks, features=feature_dict, output_attentions=False) return outputs model = DETRWithASPP(num_classes=10) images = torch.randn(2, 3, 512, 512) outputs = model(images)
Аўтаномным транспартным сродкам патрэбны вялізныя наборы даных, але пазначаных дадзеных у рэальным свеце мала. Выпраўленне? Стварайце сінтэтычныя даныя з дапамогай GAN (генератыўных канкурэнтных сетак).
Я выкарыстаў GAN для стварэння фальшывай, але рэалістычнай разметкі палос і сцэн дарожнага руху, каб пашырыць набор даных .
Вось просты GAN для стварэння разметкі паласы:
import torch import torch.nn as nn import torch.nn.functional as F class LaneMarkingGenerator(nn.Module): """ A DCGAN-style generator designed for producing synthetic lane or road-like images. Input is a latent vector (noise), and the output is a (1 x 64 x 64) grayscale image. You can adjust channels, resolution, and layers to match your target data. """ def __init__(self, z_dim=100, feature_maps=64): super(LaneMarkingGenerator, self).__init__() self.net = nn.Sequential( #Z latent vector of shape (z_dim, 1, 1) nn.utils.spectral_norm(nn.ConvTranspose2d(z_dim, feature_maps * 8, 4, 1, 0, bias=False)), nn.BatchNorm2d(feature_maps * 8), nn.ReLU(True), #(feature_maps * 8) x 4 x 4 nn.utils.spectral_norm(nn.ConvTranspose2d(feature_maps * 8, feature_maps * 4, 4, 2, 1, bias=False)), nn.BatchNorm2d(feature_maps * 4), nn.ReLU(True), #(feature_maps * 4) x 8 x 8 nn.utils.spectral_norm(nn.ConvTranspose2d(feature_maps * 4, feature_maps * 2, 4, 2, 1, bias=False)), nn.BatchNorm2d(feature_maps * 2), nn.ReLU(True), #(feature_maps * 2) x 16 x 16 nn.utils.spectral_norm(nn.ConvTranspose2d(feature_maps * 2, feature_maps, 4, 2, 1, bias=False)), nn.BatchNorm2d(feature_maps), nn.ReLU(True), #(feature_maps) x 32 x 32 nn.utils.spectral_norm(nn.ConvTranspose2d(feature_maps, 1, 4, 2, 1, bias=False)), nn.Tanh() ) def forward(self, z): return self.net(z) class LaneMarkingDiscriminator(nn.Module): """ A DCGAN-style discriminator. It takes a (1 x 64 x 64) image and attempts to classify whether it's real or generated (fake). """ def __init__(self, feature_maps=64): super(LaneMarkingDiscriminator, self).__init__() self.net = nn.Sequential( #1x 64 x 64 nn.utils.spectral_norm(nn.Conv2d(1, feature_maps, 4, 2, 1, bias=False)), nn.LeakyReLU(0.2, inplace=True), #(feature_maps) x 32 x 32 nn.utils.spectral_norm(nn.Conv2d(feature_maps, feature_maps * 2, 4, 2, 1, bias=False)), nn.BatchNorm2d(feature_maps * 2), nn.LeakyReLU(0.2, inplace=True), #(feature_maps * 2) x 16 x 16 nn.utils.spectral_norm(nn.Conv2d(feature_maps * 2, feature_maps * 4, 4, 2, 1, bias=False)), nn.BatchNorm2d(feature_maps * 4), nn.LeakyReLU(0.2, inplace=True), #(feature_maps * 4) x 8 x 8 nn.utils.spectral_norm(nn.Conv2d(feature_maps * 4, feature_maps * 8, 4, 2, 1, bias=False)), nn.BatchNorm2d(feature_maps * 8), nn.LeakyReLU(0.2, inplace=True), #(feature_maps * 8) x 4 x 4 nn.utils.spectral_norm(nn.Conv2d(feature_maps * 8, 1, 4, 1, 0, bias=False)), ) def forward(self, x): return self.net(x).view(-1)
Аб'яднаўшы ASPP, навучанне перадачы і сінтэтычныя даныя , я стварыў больш дакладную маштабаваную сістэму выяўлення аб'ектаў для беспілотных аўтамабіляў. Некаторыя з ключавых вынікаў:
Мы аб'ядналі ASPP, Transformers і Synthetic Data у патройную пагрозу для аўтаномнага выяўлення аб'ектаў - ператварыўшы некалі млявыя мадэлі, схільныя да сляпых зон, у хуткія, праніклівыя сістэмы, якія заўважаюць святлафор з квартала. Прымяняючы пашыраныя згорткі для шматмаштабнай дэталізацыі, пераноснае навучанне для хуткай тонкай налады і дадзеныя, згенераваныя GAN, каб запоўніць кожны прабел, мы скарацілі час вываду амаль удвая і зэканомілі гадзіны навучання. Гэта вялікі крок у напрамку аўтамабіляў, якія бачаць свет больш, як мы, толькі хутчэй, больш дакладна і ўпэўнена перамяшчаюцца па самых хаатычных вуліцах.