Samoriadiace autá si chyby nemôžu dovoliť. Chýbajúci semafor alebo chodec môže znamenať katastrofu. Ale detekcia objektov v dynamickom mestskom prostredí? To je ťažké.
Pracoval som na optimalizácii detekcie objektov pre autonómne vozidlá pomocou Atrous Spatial Pyramid Pooling (ASPP) a Transfer Learning. Výsledok? Model, ktorý rozpoznáva objekty vo viacerých mierkach, dokonca aj pri zlom osvetlení, a efektívne beží v reálnom čase.
Tu je návod, ako som to urobil.
Autá s vlastným pohonom sa pri detekcii objektov spoliehajú na konvolučné neurónové siete (CNN) , no podmienky v reálnom svete prinášajú výzvy:
Tradičné CNN bojujú s detekciou objektov vo viacerých mierkach a školenie od začiatku trvá večnosť. Tu prichádza na rad ASPP a Transfer Learning .
CNN fungujú dobre pre objekty s pevnou veľkosťou, ale objekty v reálnom svete sa líšia veľkosťou a vzdialenosťou. Atrous Spatial Pyramid Pooling (ASPP) to rieši pomocou rozšírených konvolúcií na zachytenie prvkov vo viacerých mierkach.
ASPP používa viacero konvolučných filtrov s rôznymi rýchlosťami dilatácie na extrahovanie prvkov v rôznych rozlíšeniach, malé objekty, veľké objekty a všetko medzi tým.
Tu je návod, ako som implementoval ASPP v PyTorch, ktorý zahŕňa normalizáciu skupiny a pozornosť na robustný výkon v zložitých prostrediach:
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
Trénovanie modelu detekcie objektov od začiatku neposkytuje veľa výhod, ak existujú vopred pripravené modely. Prenosové učenie nám umožňuje doladiť model, ktorý už rozumie objektom.
Použil som DETR (Detection Transformer), model detekcie objektov založený na transformátore od Facebooku AI. Učí sa kontext – takže nielen nájde stopku, ale pochopí, že je súčasťou cestnej scény.
Tu je návod, ako som doladil DETR na množinách údajov s vlastným pohonom:
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)
Autonómne vozidlá potrebujú obrovské súbory údajov, no reálne označených údajov je málo. Oprava? Generujte syntetické dáta pomocou GAN (Generative Adversarial Networks).
Použil som GAN na vytvorenie falošného, ale realistického značenia jazdných pruhov a dopravných scén na rozšírenie súboru údajov .
Tu je jednoduchý GAN na generovanie značenia jazdných pruhov:
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)
Kombináciou ASPP, prenosu učenia a syntetických údajov som vytvoril presnejší, škálovateľný systém detekcie objektov pre autonómne autá. Niektoré z kľúčových výsledkov sú:
Zlúčili sme ASPP, Transformers a Synthetic Data do trojitej hrozby pre autonómnu detekciu objektov – premenili sme kedysi pomalé modely náchylné na slepé uhly na rýchle a vnímavé systémy, ktoré zbadajú semafor z bloku ďalej. Zahrnutím rozšírených konvolúcií pre viacrozmerné detaily, prenosu učenia pre rýchle jemné ladenie a údajov generovaných GAN na vyplnenie každej medzery sme skrátili časy odvodenia takmer na polovicu a ušetrili hodiny školenia. Je to veľký skok smerom k autám, ktoré vidia svet skôr tak, ako my, len rýchlejšie, presnejšie a sú na ceste k sebavedomému pohybu po našich najchaotickejších uliciach.