თვითმართვადი მანქანებს არ შეუძლიათ შეცდომების დაშვება. შუქნიშნის ან ფეხით მოსიარულეთა გამოტოვება შეიძლება კატასტროფას ნიშნავდეს. მაგრამ ობიექტების აღმოჩენა დინამიურ ურბანულ გარემოში? ეს ძნელია.
მე ვმუშაობდი ავტონომიური მანქანებისთვის ობიექტების ამოცნობის ოპტიმიზაციაზე Atrous Spatial Pyramid Pooling (ASPP) და Transfer Learning-ის გამოყენებით. შედეგი? მოდელი, რომელიც ამოიცნობს ობიექტებს რამდენიმე მასშტაბით, თუნდაც ცუდი განათების პირობებში და ეფექტურად მუშაობს რეალურ დროში.
აი, როგორ გავაკეთე ეს.
პრობლემა: ობიექტების აღმოჩენა ველურ ბუნებაში
თვითმართვადი მანქანები ეყრდნობიან კონვოლუციურ ნერვულ ქსელებს (CNN) ობიექტების აღმოსაჩენად, მაგრამ რეალურ სამყაროში არსებული პირობები იწვევს გამოწვევებს:
- შუქნიშანი ჩნდება სხვადასხვა მასშტაბით - პატარა, როდესაც შორს, დიდი, როდესაც ახლოს.
- ზოლის ნიშნები დამახინჯებულია სხვადასხვა კუთხით.
- ოკლუზიები ხდება - გაჩერებული მანქანის უკან ფეხით მოსიარულე შეიძლება გამოტოვოს.
- განათების პირობები განსხვავებულია - ჩრდილები, სიკაშკაშე ან ღამის მართვა.
ტრადიციული CNN-ები ებრძვიან მრავალმასშტაბიანი ობიექტების აღმოჩენას და სწავლება ნულიდან სამუდამოდ გრძელდება. სწორედ აქ მოდის ASPP და Transfer Learning .
ASPP: ობიექტების დაჭერა სხვადასხვა მასშტაბით
CNN-ები კარგად მუშაობს ფიქსირებული ზომის ობიექტებისთვის, მაგრამ რეალურ სამყაროში არსებული ობიექტები განსხვავდება ზომითა და მანძილით. Atrous Spatial Pyramid Pooling (ASPP) აგვარებს ამას გაფართოებული კონვოლუციების გამოყენებით მრავალი მასშტაბის მახასიათებლების აღსაბეჭდად.
როგორ მუშაობს 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
რატომ მუშაობს
- მრავალფეროვანი მიმღები ველები საშუალებას აძლევს მოდელს აიღოს პატარა ობიექტები (როგორიცაა შორეული შუქნიშანი) და დიდი ობიექტები (როგორც ავტობუსი) ერთ უღელტეხილზე.
- გლობალური საშუალო გაერთიანების ფილიალიდან გლობალური კონტექსტი ხელს უწყობს ობიექტების გარკვევას.
- მსუბუქი ყურადღება ხაზს უსვამს ყველაზე ინფორმაციულ არხებს, აძლიერებს ამოცნობის სიზუსტეს არეულ სცენებში.
შედეგები:
- აღმოჩენილი ობიექტები სხვადასხვა მასშტაბით (აღარ აკლია პატარა შუქნიშანი).
- გაუმჯობესებული საშუალო საშუალო სიზუსტე (mAP) 14%-ით.
- ამუშავებს ოკლუზიებს უკეთესად , ნაწილობრივ ფარული ობიექტების აღმოჩენით.
ტრანსფერული სწავლება: გიგანტების მხრებზე დგომა
ობიექტების აღმოჩენის მოდელის ნულიდან სწავლება დიდ სარგებელს არ იძლევა, როდესაც არსებობს წინასწარ მომზადებული მოდელები. ტრანსფერული სწავლება საშუალებას გვაძლევს დავაზუსტოთ მოდელი, რომელსაც უკვე ესმის ობიექტები.
მე გამოვიყენე 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)
შედეგები:
- ვარჯიშის დრო 80%-ით შემცირდა.
- გაუმჯობესებული რეალური შესრულება ღამის და ნისლიან პირობებში.
- ტრენინგისთვის საჭიროა ნაკლები მარკირებული მონაცემები.
მონაცემთა გაძლიერება სინთეზური სურათებით
ავტონომიურ მანქანებს მონაცემთა მასიური ნაკრები სჭირდება, მაგრამ რეალურ სამყაროში ეტიკეტირებული მონაცემები მწირია. გამოსწორება? შექმენით სინთეზური მონაცემები GAN-ების (Generative Adversarial Networks) გამოყენებით.
მე გამოვიყენე 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)
შედეგები:
- მონაცემთა ნაკრების ზომა 5-ჯერ გაიზარდა ხელით მარკირების გარეშე.
- გაწვრთნილი მოდელები უფრო მდგრადი გახდა კიდეებისთვის.
- შემცირებული მიკერძოება მონაცემთა ნაკრებებში (უფრო მრავალფეროვანი ტრენინგის ნიმუშები).
საბოლოო შედეგები: უფრო ჭკვიანი, უფრო სწრაფი ობიექტების ამოცნობა
ASPP, Transfer Learning და Synthetic Data-ის კომბინაციით, მე შევქმენი უფრო ზუსტი, მასშტაბირებადი ობიექტების აღმოჩენის სისტემა თვითმართვადი მანქანებისთვის. ზოგიერთი ძირითადი შედეგია:
- ობიექტის ამოცნობის სიჩქარე : 110 ms/ჩარჩო
- მცირე ობიექტების ამოცნობა (შუქნიშანი) : +14% mAP
- ოკლუზიის მართვა : უფრო ძლიერი გამოვლენა
- ტრენინგის დრო : შემცირდა 6 საათამდე
- საჭირო ტრენინგის მონაცემები : 50% სინთეტიკური (GANs)
შემდეგი ნაბიჯები: კიდევ უფრო უკეთესი
- რეალურ დროში მიკვლევის დამატება დროთა განმავლობაში აღმოჩენილ ობიექტებს თვალყურის დევნებისთვის.
- უფრო მოწინავე ტრანსფორმატორების გამოყენება (როგორიცაა OWL-ViT) ნულოვანი გასროლის გამოვლენისთვის.
- დასკვნის სიჩქარის შემდგომი ოპტიმიზაცია ჩაშენებულ აპარატურაზე განლაგებისთვის.
დასკვნა
ჩვენ გავაერთიანეთ ASPP, ტრანსფორმატორები და სინთეტიკური მონაცემები სამმაგ საფრთხედ ავტონომიური ობიექტების აღმოჩენისთვის - ოდესღაც დუნე, ბრმა წერტილებისკენ მიდრეკილი მოდელები გადავაქციეთ სწრაფ, აღქმის სისტემებად, რომლებიც ამჩნევენ შუქნიშანს ერთი ბლოკიდან. გაფართოვებული კონვოლუციების გამოყენებით მრავალმასშტაბიანი დეტალებისთვის, სწავლის გადაცემით სწრაფი დახვეწისთვის და GAN-ით გენერირებული მონაცემები ყოველი სიცარიელის შესავსებად, ჩვენ თითქმის გავანახევრეთ დასკვნის დრო და დავზოგეთ ტრენინგის საათები. ეს არის დიდი ნახტომი მანქანებისკენ, რომლებიც სამყაროს ისე ხედავენ, როგორც ჩვენ, მხოლოდ უფრო სწრაფად, უფრო ზუსტად და გზაზე, რომ ჩვენს ყველაზე ქაოტურ ქუჩებში თავდაჯერებულად იარონ.
შემდგომი წაკითხვა ზოგიერთი ტექნიკის შესახებ
- DETR: ობიექტების ბოლოდან ბოლომდე ამოცნობა
- Atrous Convolutions სემანტიკური სეგმენტაციისთვის
- GAN სინთეზური მონაცემებისთვის