Os coches autónomos non poden permitirse erros. Faltar un semáforo ou un peón pode significar un desastre. Pero a detección de obxectos en ambientes urbanos dinámicos? Iso é difícil.
Traballei na optimización da detección de obxectos para vehículos autónomos mediante Atrous Spatial Pyramid Pooling (ASPP) e Transfer Learning. O resultado? Un modelo que detecta obxectos a múltiples escalas, mesmo con mala iluminación, e funciona de forma eficiente en tempo real.
Velaquí como o fixen.
Os coches autónomos confían nas redes neuronais convolucionais (CNN) para detectar obxectos, pero as condicións do mundo real presentan desafíos:
As CNN tradicionais loitan coa detección de obxectos multiescala e o adestramento desde cero leva unha eternidade. Aí é onde entran ASPP e Transfer Learning .
As CNN funcionan ben para obxectos de tamaño fixo, pero os obxectos do mundo real varían en tamaño e distancia. A Atrous Spatial Pyramid Pooling (ASPP) resolve isto usando circunvolucións dilatadas para capturar características a múltiples escalas.
ASPP aplica varios filtros de convolución con diferentes taxas de dilatación para extraer funcións en diferentes resolucións, obxectos pequenos, obxectos grandes e todo o que está por diante.
Así é como implementei ASPP en PyTorch incorporando a normalización do grupo e a atención para un rendemento robusto en ambientes complexos:
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
Adestrar un modelo de detección de obxectos desde cero non proporciona moito beneficio cando existen modelos adestrados previamente. A aprendizaxe por transferencia permítenos afinar un modelo que xa entende os obxectos.
Usei DETR (Detection Transformer), un modelo de detección de obxectos baseado en transformadores de Facebook AI. Aprende contexto, polo que non só atopa un sinal de alto, senón que entende que forma parte dunha escena da estrada.
Así é como axustei DETR en conxuntos de datos de condución autónoma:
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)
Os vehículos autónomos necesitan conxuntos de datos masivos, pero os datos etiquetados no mundo real son escasos. A corrección? Xera datos sintéticos mediante GANs (Generative Adversarial Networks).
Usei un GAN para crear marcas de carril falsas pero realistas e escenas de tráfico para ampliar o conxunto de datos .
Aquí tes un GAN sinxelo para a xeración de marcas de carril:
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)
Ao combinar ASPP, Transfer Learning e Synthetic Data , construí un sistema de detección de obxectos máis preciso e escalable para coches autónomos. Algúns dos resultados clave son:
Combinamos ASPP, Transformers e Synthetic Data nunha triple ameaza para a detección de obxectos autónomos, convertendo modelos que antes eran lentos e propensos a puntos cegos en sistemas rápidos e perceptivos que detectan un semáforo a unha cuadra de distancia. Ao adoptar circunvolucións dilatadas para obter detalles a varias escalas, transferir a aprendizaxe para axustar rapidamente e os datos xerados por GAN para cubrir cada oco, reducimos os tempos de inferencia case á metade e aforramos horas de adestramento. É un gran salto cara aos coches que ven o mundo máis como nós, só máis rápido, con máis precisión, e camiño de navegar polas nosas rúas máis caóticas con confianza.