Bir sinir ağı, bir örnek fotoğrafa dayalı olarak bir videodaki yüzleri tanıyacak şekilde eğitildi. Bir sinir ağına, bir fotoğraftaki videodaki yüzleri tanıması öğretildi

Bu günlükte ilk kez karşılaştığım her şeyi yazıyorum. Bu sefer genel histeriye yenik düştüm ve evrişimli sinir ağlarından bahsedeceğiz. Bu sefer sadece sonuçları ve bunlara ulaşmanın yollarını listelemek yerine, düşüncelerimin sürecini ayrıntılı olarak anlatmaya çalışacağım. Dolayısıyla “çok bukaf” olacak.
Çok uzun bir süre bu tür "kirli, yapay" sinir ağlarına direndim ve "saf, doğal" SVM'yi tercih ettim. Ciddi adamlar uzun zamandır evrişimli sinir ağlarını kullanarak problemleri çözüyorlar. Benim için yeni olan bir teknolojiyi test etmek için, tercihen farklı bir paradigmada çözdüğüm basit bir probleme ihtiyacım var. Karar verildi: yüzleri tanıyın. Son ürün videosunu ısıtmak için:
https://www.youtube.com/watch?v=mwDbGpAZdxU

Aletler

Bildiğiniz gibi sinir ağları GPU'lar üzerinde CPU'lardan çok daha verimli eğitim alıyor. Video kartlı bir masaüstü bilgisayarım yok. Neyse ki, birkaç yıl önce bir dizüstü bilgisayar aldığımda, GPU hesaplama konusunda uzmanlaşmam gerekeceği beklentisiyle bir oyun dizüstü bilgisayarı satın aldım ve onu bir ekran kartıyla birlikte satın aldım. nvidia geforce gt 650m 2Gb. Yani, çalışmaya başladığımda sahip olduğum şey: makine öğrenimi üzerine eğlenceli ve yeni başlayanlar için harika bir dizi makale, bilgisayarla görme konusunda biraz deneyim, face-rec.org sitesinden materyaller. Araçlara karar vermeniz gerekiyor. Elbette bu C++ dili, opencv bilgisayarlı görme kütüphanesi olacak, ancak yüz tanıma çerçevesiyle her şeyin daha karmaşık olduğu ortaya çıktı. Adam'ın kullandığı OpenFace'in Python'da yazıldığı ve meşale kullandığı ve bunun da lua ile yazıldığı ortaya çıktı. Temel olarak C++'da monolitik bir çözüme ihtiyacım var. O zamanlar yüksek kaliteli bir yüz algılayıcıya sahip olan, GPU'ları kullanmak da dahil olmak üzere evrişimli ağlarla çalışmak için araçlara sahip olan ancak yüz tanıma işlevine sahip olmayan hafif bir dlib hızla bulundu. Tam da ihtiyacın olan şey!
Hadi onu açmaya başlayalım. Kaynakları indirip cmake kullanarak derlemeniz gerekiyor. Biraz eziyetten sonra, video kartını kullanmak için Nvidia web sitesinden CUDA Toolkit ve cuDNN'yi yüklemeniz gerektiğini anladım. Kurulum yolu boşluk içermemelidir. Projemi dlib kullanmaya başlatmak için test senaryolarındaki parametrelere baktım. Kütüphane listesine ek olarak, burada DLIB_USE_CUDA ön işlemcisinin tanımını belirtmeniz ve optimizasyon parametrelerini ayarlamanız gerekir. Ayrıca eğitim sırasında video kartının kullanımını izlemek için kullanışlı GPUZ yardımcı programını da yükledim.

Tanınmış MNIST veri kümesi için sinir ağlarının çeşitli test yapılandırmalarını çalıştırdım:


  • İki katmanlı algılayıcı, bir işlemci çekirdeği üzerinde yarım saat boyunca eğitim setinde ve test setinde doğrulukla eğitildi: (0,9908, 0,9792).

  • LeNet ağı (Lekun), bir işlemci çekirdeği üzerinde neredeyse 6 saat ve bir video kartı üzerinde 15 dakika eğitim aldı! Doğruluk elde edildi (0,99975, 0,9915).

  • ResNet ağı - video kartında 1 saat 15 dakika, doğruluk (0,9938).

  • Başlangıç ​​ağı - video kartında yaklaşık 4 saat, doğruluk (0,999217, 0,9904).

Şimdi eğitim setine bir göz atalım. Açık veritabanları listesini inceledim, indirilebilecek her şeyi indirdim, hızlıca erişebileceğim bir yere erişim sağladım, indirdim, kısmen dönüştürdüm, kısmen ellerimle çalıştım, sonunda yeni başlayanlar için 65.000 resimden oluşan bir veritabanı elde ettim Tembelliğin üstesinden gelirseniz, veritabanı sürelerini ikiye katlama becerisine sahip 6.700 farklı kişiden oluşan.

Sorunun açıklaması ve ilk çözüm
Şimdi asıl göreve geçelim. Küçük bir grup yüz için (100 kişiye kadar) her birinin 3-5 fotoğrafına dayalı oldukça güvenilir bir sınıflandırıcı oluşturmak istiyorum. Sınıflandırıcının normalde çok değişken görüntüleri "sindirmesi" gerekir. Nitekim bakış açısına, ışık koşullarına, başlığın varlığına, gözlüklere ve yüz ifadesine bağlı olarak çok farklı görüntüler elde edilecektir. Bu kadar küçük bir eğitim örneğiyle (bir peronanın 3-5 fotoğrafı) yalnızca doğrusal bir sınıflandırıcı kullanmanın anlamlı olduğu açıktır. Ve amacı farklı kişilerin fotoğrafları arasındaki farkları ve aynı kişinin farklı fotoğrafları arasındaki benzerlikleri vurgulamak olan, önceden uygulayacağımız çok kaliteli bir tanımlayıcıya ihtiyacımız var.

Sinir ağının bir katmanının doğrusal bölme işlemini gerçekleştirdiği bilinmektedir. Sinir ağımızın son katmanı doğrusal olarak sınıflandırıyorsa, o zamangeri kalan sinir ağı yüz görüntü vektörlerinin “sıkıştırma-düzeltme dönüşümü” olarak düşünülebilir.bu kişilerin doğrusal olarak ayrılabileceği bir alan. Bundan yararlanalım.


Aklıma gelen ilk fikir, farklılıkları aramak için bir sinir ağını eğitmekti. Bunu yapmak için girişe bir çift görüntü ve bu görüntülerin aynı kişiye mi yoksa farklı kişilere mi ait olduğunu belirtin.

Öyleyse ızgara başarılı bir şekilde eğitildiyse, birkaç resim göndererek bir tanımlayıcı alabilirsiniz, biri - bir tanımlayıcıİle ki bunu hesaplıyoruz ve ikincisi herhangi bir görüntü, önemli olan tek şey onun her zaman aynı olmasıdır. İnternette ortalama bir yüz resmi buldum.Tanımlayıcı vektör olarak sinir ağının sondan bir önceki katmanını alabilirsiniz, sonuncusu yalnızca iki nörondan oluşacaktır.


İlk konfigürasyon Lenet'e benzer şekilde çok basittir; bir çift evrişimli katman ve üç tamamen bağlantılı katman içerir:
statik sabit size_t MINI_BATCH_SIZE = 128; //128; const unsigned long descriptor_size = 128; statik const cv:: Boyut DATASET_IMAGE_SIZE = ( 128 , 128 ) ; //LeNet gibi ızgara //LeCun, Yann ve diğerleri. "Belge tanımaya uygulanan gradyan tabanlı öğrenme." //IEEE 86.11 (1998) Bildirileri: 2278-2324. net_type = dlib::loss_multiclass_log kullanarak< dlib:: fc < 2 , dlib:: fc < 128 , //!!!BURADA RELU'YU KAÇIRDIK dlib::relu > >>> >>> >> >> > > > ;
Eğitim şuna benziyor:

Std::cout<< "net initialization..." << std:: endl ; net_type net; //Aşağıdaki kod, bunu başarmak için başlangıç ​​öğrenme oranı 0,01 olan mini toplu stokastik gradyan inişini kullanıyor. std::cout<< "trainer initialization..." << std:: endl ; dlib:: dnn_trainer < net_type>eğitmen(net); //dnn_trainer eğitmen(net, adam(0,0005, 0,9, 0,999), (0, 0, 0, 0)); trainer.set_learning_rate(0.01); //1e-3 trainer.set_min_learning_rate (MIN_LEARNING_RATE) ; trainer.set_mini_batch_size (MINI_BATCH_SIZE) ; trainer.be_verbose(); trainer.set_synchronization_file ("lenet_faces_sync", std::chrono::seconds (180) ) ; //std'yi eğit::vektör< dlib:: matrix < unsigned char >> mini_batch_samples; std::vektör< unsigned long >mini_batch_labels; dlib:: rand rnd(zaman (0 ) ) ; std::cout<< "traning..." << std:: endl ; while (trainer.get_learning_rate () >= MIN_LEARNING_RATE) ( dataset.GetInputSamplePairBatch (mini_batch_samples, mini_batch_labels, MINI_BATCH_SIZE) ; win1.set_image (mini_batch_samples[ 0 ]) ; win2.set_image (mini_batch_samples[ 1 ]) ; trainer.train_one_step (mini_batch_samples, mini _toplu_etiketler) ) // train_one_step()'i çağırdığınızda, eğitmen işlemini bir // ayrı iş parçacığı. Ancak bu aynı zamanda mini partileri beklememiz gerektiği anlamına da geliyor. // hala yürütülüyor. get_net() işlevinin çağrılması gerekli senkronizasyonu gerçekleştirir. trainer.get_net(); std<< std:: endl ; net.clean () ; //Ağı yardımcı bilgilerden temizle dlib::serialize("lenet_faces.dat")<< net; //Ve kaydedin. Seri durumdan çıkarmak için("lenet_faces.dat") >> net;

Eğitim tamamlandıktan sonra ağ tanımlayıcı olarak kullanılır. Ayrı bir test örneği kullanılarak, sinir ağının ikinci tamamen bağlı katmanının bir çift görüntüye verdiği yanıtlardan elde edilen vektörler uzayında doğrusal bir sınıflandırıcı eğitilir ve test edilir. Test örneği 15 farklı kişiye ait yaklaşık 1500 görsel içermektedir. Sınıflandırıcı kişi başına 5 görüntüye göre eğitilir. Test - herkes için.
//Sınıflandırıcının eğitimi std::cout<< "Traning classifier..." << std:: endl ; TSVMClassifier classifier({ cv:: ml :: SVM :: POLY ,2 ,2 } ) ; static const long NL = 5 ; long i = 0 ; std:: vector < long >isum(dataset.ClassNumber()); cv:: Mat descr(1 , descriptor_size, CV_32FC1) , train_data(dataset.ClassNumber () * NL, descriptor_size, CV_32FC1) , train_classes(dataset.ClassNumber () * NL, 1 , CV_32SC1) , test_data(dataset.Size () , descriptor_size, CV_32FC1) , test_classes(dataset.Size () , 1 , CV_32SC1) , tahmin edilen_sınıflar(dataset.Size () , 1 , CV_32FC1) , ortalama = cv::imread ("../AveragedMan.jpg" , CV_LOAD_IMAGE_GRAYSCALE) ; dlib::matrix< unsigned char >ortalama_dlib(DATASET_IMAGE_SIZE.height, DATASET_IMAGE_SIZE.width) , sample_dlib; //Ortalama yüzün hazırlanması TFaceDetector FaceDetector( "shape_predictor_68_face_landmarks.dat") ); std::vektör< dlib:: rectangle >face_rects = FaceDetector.Detect(ortalamalı) ; dlib::dizi< dlib:: matrix < unsigned char >>yüzler; FaceDetector.ExtractFaces(ortalama, face_rects, yüzler) ; if (faces.size () == 1 ) resize_image(faces[ 0 ], ortalama_dlib) ; dlib::image_window kazan; //Her sınıftan 5 nesne üzerinde eğitim alıyoruz ve hepsini test ediyoruz for (unsigned long idx = 0 ; idx< dataset.Size () ; idx++ ) { try { sample_dlib = dataset.GetSample (idx) ; win.set_image (sample_dlib) ; std:: cout << dataset.GetLabelIdx (idx) << " " << dataset.GetLabelByIdx (dataset.GetLabelIdx (idx) ) << std:: endl ; } catch (exception & e) { TException * E = dynamic_cast < TException * >(&e) ; if (E) std::cout<< E- >Ne()<< std:: endl ; else std:: cout << e.what () << std:: endl ; continue ; } ; net(dataset.MakeInputSamplePair (& averaged_dlib, & sample_dlib) ) ; for (unsigned long iv = 0 ; iv < dlib:: layer < 2 >(net).get_output().size(); iv++ ) açıklama.at< float >(iv) = dlib::katman< 2 >(net).get_output().host()[iv]; descr.copyTo(test_data.row(idx)); test_classes.at< long >(idx) = (uzun) veri kümesi.GetLabelIdx (idx) ; if (isum[ test_classes.at< long >(idx)]< NL) { //train_data.push_back(descr); //train_classes.push_back(test_classes.at (idx)); descr.copyTo(train_data.row(i)); train_classes.at< long >(i) = test_classes.at< long >(idx); isum[ test_classes.at< long >(idx) ] ++ ; i++ ; )) std::cout<< train_data.cols << " " << train_data.rows << " " << train_classes.cols << " " << train_classes.rows << std:: endl ; classifier.Train (train_data, train_classes) ; classifier.Save ("classifier.txt" ) ; //Doğrusal sınıflandırıcının test edilmesi std::cout<< "Doğrusal sınıflandırıcı test ediliyor..."<< std:: endl ; classifier.Predict (test_data, predicted_classes) ; unsigned long num_right = 0 , num_wrong = 0 ; for (unsigned long idx = 0 ; idx < dataset.Size () ; idx++ ) if (test_classes.at < long >(idx) == (uzun) tahmin edilen_sınıflar.at< float >(idx)) sayı_sağ++; aksi halde num_wrong++ ; std::cout<< "training num_right: " << num_right << std:: endl ; std:: cout << "training num_wrong: " << num_wrong << std:: endl ; std:: cout << "training accuracy: " << num_right/ (double ) (num_right+ num_wrong) << std:: endl ; std:: cin >>c;

Öğrenme sürecinin kendisi şöyle görünür:


Video kartındaki ve işlemcideki yükün minimum düzeyde olduğu görülebilir. Mevcut kaynakları daha kapsamlı kullanarak hesaplamaları hızlandırmak mümkün mü? Saniyede yaklaşık 10 çift işlendi.Darboğaz, beklediğim gibi diskten okuma bile değil, yüz algılamaydı.Dedektörü tüm görüntüler üzerinde önceden çalıştırıp sonucu diske kaydetme ve ardından onunla çalışma seçeneği vardı.Ancak bu seçeneği beğenmedim çünkü gelecekte dedektörü değiştirebileceğim ve "ham" işlenmemiş görüntüleri depolamak zorunda kalacağım için diskte iki büyük veritabanı depolamam gerekecekti. Ayrıca bir önbellekleme seçeneği de vardır. Numunenin tamamı RAM'e sığacak bloklara bölünmüştür. Rastgele bir blok seçiyoruz ve her görüntü kullanılıncaya kadar onun rastgele görüntü alt kümeleri üzerinde eğitim alıyoruz N bir kere. Daha sonra bir sonraki bloğa geçiyoruz. Bu şekilde disk okuma sayısını n faktörü kadar azaltabilirsiniz.

Yüz tespitini aynı dlib kütüphanesindeki iş parçacığı havuzunu kullanarak paralel hale getirdim ve 5-6 kat zaman kazancı elde ettim.
struct TR ( TDataset * Veri Kümesi; bool Pozitif; dlib::matrix< unsigned char >Örnek Çift; imzasız uzun Etiket; ) ); ... if (UseMultiThreading) ( std::vector< TR>trv; std::vektör< dlib:: future < TR>> fv(batch_size) ; for (unsigned long i = 0 ; i< batch_size; i++ ) { trv.push_back (TR() = { this , positive} ) ; fv[ i] = trv[ i] ; //Tabii ki lambdalar olmadan da yapabilirsiniz ThreadPool- > add_task_by_value( (TR & val) ( val.Dataset - > GetInputSamplePair(val.Positive, val.SamplePair, val.Label) ; ) , fv[ i] ) ; pozitif = ! pozitif; ) );//Her iş parçacığının kendi dedektör örneğine ihtiyacı vardır, çünkü farklı boyutlarda vb. olabilir.< batch_size; i++ ) { batch_sample_pairs.push_back (fv[ i] .get () .SamplePair ) ; batch_labels.push_back (fv[ i] .get () .Label ) ; ThreadPool-> wait_for_all_tasks() ; for (unsigned long i = 0 ; i //batch_sample_pairs.push_back(tfv[i].SamplePair);//batch_labels.push_back(tfv[i].Label);< batch_size; i++ ) { GetInputSamplePair(positive, sample_pair, label) ; batch_sample_pairs.push_back (sample_pair) ; batch_labels.push_back (label) ; positive = ! positive; ) ); ) else ( for (unsigned long i = 0 ; i } ; }

//Alternatif olumlu ve olumsuz örnekler

Artık öğrenme süreci şöyle görünür:

İşlemci, GPU ve sabit sürücü üzerindeki yüke bakılırsa, artık yalnızca donanım değiştirilerek önemli ölçüde hızlandırılabilir. Not:

Makalelerin boyutunu sınırladığı için Livejournal'dan nefret ediyorum. Bu kısmen, diğer şeylerin yanı sıra blogun tam sürümünü de sürdürmeyi planladığım web sitem delirium.su'yu açmamın nedenidir.

Son zamanlarda ultra hassas sinir ağları, yüzleri tanıma konusunda en iyi işi yapıyor. Böyle bir sistemin daha iyi çalışabilmesi için mümkün olduğu kadar çok sayıda örnek fotoğraf göstermesi gerekmektedir. Öğrenme süreci sırasında sistem, temel özellikleri tanımlar ve bunlar arasında bağlantılar kurar ve ardından edinilen bilgiyi bilinmeyen görüntüleri tanımak için kullanır. Kontrollü veriler için, yani çerçevedeki aynı konum, aynı ışıklandırma vb. ile algoritmaların doğruluğu uzun süredir insanlarınkiyle karşılaştırılabilir sonuçlar elde etmiştir. Ancak kontrolsüz koşullarda, değişen ışık, açı ve boyuta sahip video verilerinin tanınmasında yüksek doğruluk elde etmek hala zordur.

Bu sorunu çözmek için İktisat Yüksek Okulu'ndan araştırmacılar bulanık kümeler teorisini ve olasılık teorisini kullandılar. Daha önce yapılan deneylere kıyasla videodaki yüzleri tanımlamanın doğruluğunu %2-6 oranında artırabilen bir algoritma geliştirdiler.

Araştırmacılar, video yüz tanıma yöntemlerini değerlendirmek için bir test temeli olarak çeşitli geleneksel veri kümelerini kullandılar: IJB-A (IARPA Janus Benchmark A) ve YTF (YouTube Faces). Bu setler, ünlü kişilerin (aktörler, politikacılar, tanınmış kişiler) farklı zamanlarda, kontrolsüz koşullar altında açık kaynaklardan toplanan, kamuya açık görsellerini içerir. Algoritmanın, başka bir veri kümesi olan LFW'den (Vahşi Doğadaki Etiketli Yüzler) aynı kişilerin birkaç fotoğrafını örnek olarak kullanarak YouTube videolarındaki yüzleri tanıması gerekiyordu. LFW daha yüksek çözünürlük kullandı ve fotoğraflar 1970'lerden 2010'lara kadar farklı zamanlarda çekildi.

Yeni yaklaşım, referans fotoğraflarının birbirleriyle nasıl ilişkili olduğu, yani birbirlerine ne kadar yakın veya uzak oldukları hakkındaki bilgileri matematiksel bir modelde kullanıyor. Bu durumda, benzer insanlar arasındaki bağlantı daha az, farklı insanlar arasındaki bağlantı ise daha fazladır. İnsanların birbirinden ne kadar farklı olduğunu bilmek, sistemin video karelerini tanıma sürecindeki hataları düzeltmesine olanak tanır.

"Algoritma, bir karenin bir kişiye ne kadar yakın olduğunu ve diğerinin diğerine ne kadar yakın olduğunu değerlendiriyor. Daha sonra iki kişinin birbirine ne kadar benzediğini karşılaştırır. Daha sonra üçüncü bir kişiyi ekler ve kime daha yakın olduğunu değerlendirir - birinciye mi yoksa ikinciye mi? Bu yakınlığa dayanarak tanıma hatalarını bir kez daha düzeltiyor” diyor Profesör Savchenko.

Telefonunuzdaki bir fotoğrafı kullanarak kıyafet aramak kızlara göredir diyorsunuz. Bunun ciddi BT uzmanlarına göre olmadığını söylüyorsunuz. Ve genel olarak, son derece bilimsel teknoloji nerede ve mmm... vanilya modası ve gösteriş dünyası nerede?

'11'de Skolkovo BT kümesinin bir sakini olduğumuzda ve kısa bir süre sonra Odnoklassniki ile yüzleri tespit etmek için karmaşık bir hesaplamalı program geliştirmek üzere bir sözleşme imzaladığımızda, biz de aynı şekilde düşündük. Mesela hayatımız boyunca harika bilimsel alanlarda çalışacağız, sana tatlı yok.

Ancak bir süre sonra, görsel arama, çevrimiçi ve mobil ticaret, küresel perakende pazarındaki genel eğilimler ile ilgili dünya istatistiklerini inceleyerek, iş dünyasının giyim, ayakkabı ve aksesuarların mobil olarak tanınmasına olan ilgisinin (ekip içinde buna genel moda kelimesi diyoruz) farkına vardık. ) hızla büyüyor.

Örnekleyelim.

Bazı sayılar

Giyim, moda ve lüks mallar endüstrileri oldukça umut verici bir pazardır. McKinsey'deki pazarlamacılar ve finansörler, yaptıkları çalışmada küresel hazır giyim sektörünün 2014 ile 2020 yılları arasında çift haneli büyüme yaşayacağını söylüyor. Üstelik büyüme, gelişen pazarlar (elbette Rusya burada da geçerli) ve büyük ölçüde Asyalı alıcılar (Çin'in kentleşme hızı, 19. yüzyılda Büyük Britanya'daki benzer süreçten 10 kat daha hızlı) nedeniyle gerçekleşecek.

Sadece kadın giyim pazarından bahsedersek, önümüzdeki 12 yıl içinde dünya çapındaki büyüme %50'nin üzerinde olacak (McKinsey'in Şehir bazında Moda Büyümesini Serbest Bırakma araştırmasına göre).

Kıyafetler ayıklanıyor. Pazarın büyüdüğünü, bunun da teknoloji geliştirme fırsatları olduğu anlamına geldiğini fark ettik. İyi.

Daha sonra çevrimiçi alışveriş trendlerini incelemeye başladık. Amerika'ya baktık. 2015 yılında 205 milyon Amerikalı (325 milyonluk nüfusun %60'ından fazlası) en az bir kez internette ürün aradı, fiyatları karşılaştırdı veya internetten bir şey satın aldı. 2019 yılında bu rakamın 224 milyona ulaşması bekleniyor.

Benzer bir eğilim dünya çapında da gözlemleniyor: Birleşmiş Milletler Ticaret ve Kalkınma Konferansı için yapılan bir araştırma, 2018 yılına kadar dünya çapında yaklaşık 1,623 milyar insanın çevrimiçi olarak mal ve hizmet satın alacağını belirtiyor (2013'teki 1,039 milyara kıyasla).

Aynı zamanda, mobil ticaret segmentinin (yani mobil cihazlardan yapılan satın alımların) da büyüdüğünü belirtmek ilginçtir. eMarketer tahminlerine göre, yalnızca Amerika'da mobil perakende gelirleri 2018'de 130,12 milyar dolara (2014'teki 56,67 milyar dolardı) ulaşacak; bu da iki katından fazla artacak.

Çevrimiçi alışverişin “seferberleştirilmesine” yönelik küresel eğilim de ortadadır. Goldman Sachs, m-ticaret segmentinin kullanıcı sayısı açısından 5 yıl içinde 5 kat büyüyeceğini belirten bir rapor yayınladı: 2013'te 379 milyon kullanıcıdan 2018'de 1 milyardan fazla alıcıya (raporun şuna dikkat edilmelidir: "Seyahat" segmentindeki çevrimiçi satın alımları hesaba katmaz.

Nielsen araştırmasına göre giyimin çevrimiçi olarak en sık satın alınan kategori olduğunu söylemek gerekir. Onunla yalnızca kitaplar, kırtasiye malzemeleri ve müzik yarışıyor.

Aslında olan şu: İnternet erişim pazarı şu anda doyum noktasına ulaştı, kullanıcı artışı önemli ölçüde yavaşladı (sonraki yıllarda %5-10 olarak tahmin ediliyor). Akıllı telefon pazarının büyümesi de sıfıra doğru gidiyor.

Örneğin Mark Zuckerberg'in Facebook F8 konferansındaki konuşmasının sunumunu izleyin.

Bu, İnternet ve akıllı telefon pazarının bir meta, tüketim malı, günlük yaşamın bir parçası haline geldiği anlamına geliyor. Ancak mobil cihazlar aracılığıyla yapılan satın almalar, yeni teknolojilerin geliştirilmesine alan sağlayan yeni davranış kalıplarıdır.

Tüm bu gerçekler, sinir ağı teknolojimizi nasıl uygulayabileceğimizi ve bu alanda ilginç ve gerekli bir şeyi nasıl yapabileceğimizi düşünmemize temel oluşturdu. Böylece 2014 yılında mobil kıyafet tanıma sistemi geliştirmeye başladık.

Sisteme elbiseleri tanımayı nasıl ve neden öğretmeliyiz?

Mobil tanıma fikri basittir: Kullanıcı beğendiği bir moda ürününü görür (sokaktaki bir kişinin üzerinde, bir mağazanın vitrininde veya bir derginin kapağında), bunun bir mobil cihazda fotoğrafını çeker, fotoğrafı, görseldeki ürünü tanıyan ve mağazanın ürün yelpazesinden benzer ürünleri seçen yüklü mobil uygulamaya yükler. Mallar elbette hemen satın alınabilir. Tüm.

Yani kullanıcının hizmetten beklentisi üç aşamaya indirgenebilir: testere - fotoğraflandı - satın alındı.

Böyle bir sistemi geliştirmek ve inşa etmek için 30.000.000'den fazla görüntüyü işlememiz, kazak ile kazak arasındaki farkı anlamamız (kazak ve hırka da var ve bunların hepsi farklı şeyler), derbi çizmeler ve keşişler, spor çanta ve çantayı anlamamız gerekiyordu. çantalarımızı açın ve “kunstkameramızı” açın, mankenler kiralayın, genç (aslında pek de genç değil, tamam) moda tasarımcıları gibi hissedin - ve çok daha fazlası. Ama önce ilk şeyler.

Mobil tanıma sistemini kurmaya karar verdik. nöral ağlar derin öğrenme teknolojisinin özüdür. Ağlar, öğrenme ve hata düzeltme açısından insan beynindeki nöronların çalışmasını taklit eder: Ağ bağımsız olarak öğrenir (yeterli eğitim verileriyle) ve önceki deneyimlere dayanarak hareket eder, her yeni öğrenmede giderek daha az hata yapar.

Bir nöron, bir ağın ayrı bir hesaplama öğesidir; her nöron, ağın önceki ve sonraki katmanlarındaki nöronlara bağlanır. Giriş olarak bir görüntü, video veya ses dosyası geldiğinde ağın tüm katmanları tarafından sırayla işlenir. Sonuçlara bağlı olarak ağ, konfigürasyonunu (her bir nöronun parametreleri) değiştirebilir.

Görevimiz için sinir ağları iyidir çünkü gerekli miktarda eğitim verisi verildiğinde neredeyse her türlü nesneyi tanımayı öğrenebilirler.

1. Adım: Moda hakkında her şeyi öğrenin

Yani teknolojik açıdan bakıldığında sistemin şu sırayla çalışması gerekiyor: Sistem tarafından yüklenen fotoğrafın analizi - Potansiyel olarak ürün içeren alanların vurgulanması - Ürün kategorisinin belirlenmesi - Bir nesnenin arka plandan ayrılması - Dijital parmak izi oluşturulması ürün görselinin - belirli bir kategorideki benzer ürünleri arama.

Ar-Ge planında ilk nokta modanın doğru, eksiksiz ve isabetli bir sınıflandırmasının oluşturulmasıydı.

Ayakkabıların sınıflandırılmasıyla başlamaya karar verdik. Ve kadınlar için bize daha kolay göründü (hemen haç çıkarmalıydık, sizi saf aptallar). Anlıyoruz: Sistemin kategorileri doğru bir şekilde tanıyabilmesi için kadın ayakkabı türlerinin ayrıntılı bir sınıflandırmasına ihtiyacımız var. Wikipedia'yı, açıklayıcı sözlükleri, çevrimiçi ayakkabı mağazası sitelerini ve Google'dan alınan görselleri şu şekilde kullandılar:

Kategoriye göre görsel aramaya ve işaretlemeye paralel olarak, bazılarını hemen "görmek" istediğimiz alışılmadık (hatta tamamen tuhaf) ayakkabı örnekleriyle doldurulmaya başlayan dahili bir "Kunstkamera" klasörü oluşturduk. Örneğin aşağıdaki sergilerimiz var:

Biz elbette bu tür görüntüleri ağı eğitmek için çekmedik. Bu benim için - “sadece gülmek için” (c).

Ve unisex ayakkabıların olduğunu fark ettik. Örneğin, espadril, mokasen veya Timberlands gibi ayakkabı kategorileri hem erkekler hem de kadınlar için görünüş olarak çok benzer olabilir.

Toplamda 10 kategoriyi unisex olarak sınıflandırdık.

Yani toplamda 100'den biraz daha az ayakkabı kategorisi belirledik ve ardından bu adımda karşılaştığımız zorlukları özetledik.

Birinci- Bu başlı başına bir sınıflandırmadır. Hangi kategorileri vurgulamalıyız? Çok küçük olacaklar mı? Veya tam tersine aşırı derecede büyümüş mü?

Burada son müşterilerimizin - çevrimiçi mağazaların - kataloglarının yapısı bize yardımcı oldu. Onların kategorilendirmesini esas alarak ihtiyaçlarımızı karşılayabilecek bir forma getirdik (Rus ve Amerika mağazaları için evrensel, çok genel ve çok detaylı değil).

Saniye– bazı malların belirli bir kategoriye sınıflandırılmasındaki anlaşmazlık. Mesela bu nedir? Ayak bileği botları mı yoksa spor ayakkabıları mı?

Dışarıdan elbette ayak bileği botlarına benziyorlar, ancak bazı çevrimiçi mağazaların web sitelerinde bu tür ayakkabılar spor ayakkabı olarak sınıflandırılıyor. Müşterinin benzer botları hangi kategoride aramak isteyeceğini nasıl anlarsınız?

Üçüncü– sınıflandırıcı detayı. Bazen daha iyi tanınma sonuçları elde etmek amacıyla "sıkıcı" olmak ve daha doğru bir arama için mağaza kategorileriyle her zaman ilişkili olmayan ek kategoriler seçmek (arama filtreleriyle karıştırılmamalıdır!) gerekliydi.

Bu şekilde dolgu topuklu botlar, stiletto topuklu bilekte botlar, geniş topuklu bilekte botlar, kürklü bilekte botlar vb. elde ettik.

Dördüncü– bazı kategorilere göre resim seçmede zorluk. Örneğin tekne ayakkabılarının görsellerinin yalnızca yabancı kaynaklarda bulunabildiği bir dönem vardı - bu ayakkabılar henüz mağazalarımızda geniş çapta temsil edilmiyordu.

VE son şey. Ayakkabı malzemesinin belirlenmesinde nöronun nasıl davranacağını anlamadık. Yani, yüksek deri botlara yönelik ağ, özellikle deri botları mı arayacak yoksa arama sonuçları, benzer şekle sahip ancak farklı malzemelerden yapılmış tüm botları mı içerecek?

Sonuç olarak, kategorileri malzemeye göre ayırıp ayırmamamız gerektiğini bilemedik: deri ayakkabılar, süet ayakkabılar, kumaş ayakkabılar vb.

Test için 2 kategori oluşturduk: “Süet botlar” ve “Deri botlar” (elbette diğer kategorilerle örtüşüyorlar - yüksek botlar, dolgu topuklu botlar ve diğerleri). Ağ bunları doğru bir şekilde tanır. Ancak sonuçta, tüm ayakkabı türlerini malzemeye göre örtüşmeyen kategorilere ayırmadık - bu gereksiz olurdu. Ancak bu iki "tarihsel olarak kurulmuş" kategori kaldı. Düzgün çalışmaya müdahale etmezler.

Genel olarak ayakkabı sınıflandırıcısını hazırladıktan sonra kendimizi Alexander Vasiliev, Vyacheslav Zaitsev ve Valentin Yudashkin'in bir karışımı olarak görmeye başladık.

İç yazışmalarımız

Daha sonra aynı prensibi kullanarak kadın ve erkek çantalarını, ardından kadın ve erkek kıyafetlerini ayırmaya başladık.

Adım 2: Rahipleri mokasenlerden ve kazak ile kazak arasında ayrım yapmak için sinir ağlarını eğitin

Böylece sistemimizin çalışacağı moda kategorilerini belirledik. Şimdi sinir ağlarını bir fotoğraftaki kategorileri tanıyacak şekilde eğitmemiz gerekiyor: yani istenen nesnenin resimde nerede bulunduğunu belirleyip onu doğru şekilde sınıflandırmalıyız.

Bir sinir ağını bir kategoriyi tanıyacak şekilde eğitmek için ilk adım, önemli sayıda resmi seçip ağa yüklemektir (bu sürece "ağları beslemek" diyoruz) binden birkaç yüz bine kadar.

Yani sisteme "Yüksek topuklu ayakkabılar" kategorisini tanımayı öğretmek için internetten iki veya daha fazla bin farklı yüksek topuklu ayakkabı resmi indirmeniz gerekiyor. Prensip basittir: Daha fazla eğitim verisi daha iyi ağ performansı (daha kesin olarak tanıma) anlamına gelir.

Eğitim için resimlerin indirilmesi, yarı otomatik olarak dahili algoritmalarımız tarafından, yarı manuel olarak yapılır. Daha sonra, kopya veya rastgele uygunsuz resimlerin olmadığından emin olmak için fotoğraf dizisi kontrol edilir. Ayrıca, tüm dosyalara tek tip adlar ve aynı format (uzantı) verilir.

Ve sonra en zor kısım başlıyor: Resimdeki ürünleri manuel olarak işaretlemek. Çalışanlarımız fotoğraftaki ürünün çevresine çerçeve çizerek kategorisini belirliyor.

Örneğin:

Sistemin anlaması için bu gereklidir: Dikdörtgenin içinde olan tam olarak belirli bir kategorinin ürünüdür. İşaretleme işi en çok zaman alır: Görev zahmetlidir ve çok hızlı ilerlemez. Kahve fincanlarını işaretlemek için harcanan adam-saati ölçerseniz, çıktı bir tondan fazla canlandırıcı içecek olacaktır.

Neyle kavga ediyordun?

Markalama aşamasında deneyim ve öngörü eksikliği ters tepti: Yeni çanta ve giysi kategorilerini belirledikten sonra, önceden işaretlenmiş ayakkabı fotoğraflarını yeni ürünlere yeniden etiketlemek zorunda kaldık. Yeni kategoriler için işaretleme yapılmaması nedeniyle sistem kıyafet buldu ancak bunun hatalı olduğunu düşündü ve bulunan ürünleri “arka plana” ekledi.

Yani, ilk önce olası tüm ayakkabı, giysi ve aksesuar kategorilerini belirleseydik (sınıflandırıcıyı şu anki formuna getirseydik) ve ancak daha sonra resimleri işaretleseydik Tüm kategorileri aynı anda kullanırsak, çok fazla kaynaktan tasarruf etmiş oluruz.

Diğer bir darboğaz ise işaretlemeye birden fazla çalışanın dahil olmasıydı. Ve öyle oldu ki, herkesin hangi giysinin hangi kategoriye ait olduğu konusunda kendi anlayışı vardı (tartışmalı vakalar hakkında yukarıda yazdık). Bu nedenle, meslektaşlarından işaretli fotoğrafları kabul eden ve tüm klasörleri ve resimleri işaretlerin doğruluğu açısından iki kez kontrol eden sorumlu bir çalışan atandı.

Örnek olarak kadın ayakkabılarını kullandığımız moda sınıflandırıcımız şu şekilde görünüyor (sayfalardan biri):

Sinir ağları artık görüntü işleme ve tanıma, konuşma tanıma sistemlerinde, video analizinde ve entelektüel güvenlikte yaygın olarak kullanılıyor. Ağlar müzik yaratır ( Müzik güvertesi). Bir dizi faaliyette (örneğin bir çağrı merkezinde müşteriye temel konularda tavsiyelerde bulunmak) insan zekasının yerini alacak sinir ağı botlarının ortaya çıkacağı zaman çok uzak değil.

Genel olarak pek çok insanın ağlara dahil olduğunu söylemek gerekir. Bunlar İnternet pazarının köpekbalıkları: "Yandex"(örneğin, Auto.ru için son özellikleri - bir arabanın markasını ve modelini bir görüntüden tanıma), Microsoft(hizmet What-Dog.net, fotoğraflardan köpek ırklarının belirlenmesi), Mail.ru Ve Facebook(Facebook AI Research'ün bir bölümü) ve elbette Google. Ancak bunlar aynı zamanda genç girişimlerdir (yalnızca bilgi işlem gücü için yeterli fona sahip olanlar).

Ağlar dünya genelindeki teknik üniversitelerde, özellikle de MIPT Belki artık siz de ağlara dahil olmak istiyorsunuz. Serin!

Daha sonra hazırlıklı olmanız gereken iki noktayı hemen dile getireceğiz.

Teknolojinin önemli bir kısmının eğitim verileri olduğunu bir kez daha söyleyelim. Bu ilk "ama". Ağın bir nesne türünü başarılı bir şekilde ayırt edebilmesi için, üzerinde eğitim yapılacak olan bu nesnenin birkaç bin örneğinin toplanması gerekir. Genellikle nesnelerin sayısı yüzlercedir. Nihai eğitim veritabanları yüzbinlerce veya milyonlarca nesneyi numaralandırabilir.

Bu nedenle tabanın hazırlanması oldukça emek yoğun bir süreçtir. Bazen startuplar bize geliyor ve Pinterest gibi Amazon ürünlerine bağlantı vererek tanınma yapmak istediğimizi söylüyorlar. “Harika” diyoruz, “ayarlayabiliriz. Ancak ağın çalışması için her ürün için çok sayıda resme ihtiyacınız var. Toplayabilir miyiz? Bundan sonra müşteriler bir sebepten dolayı uzaya kayboluyor.

Bununla birlikte, çeşitli hızlandırılmış öğrenme teknolojilerinin artık ortaya çıktığı da unutulmamalıdır. Örneğin, önceden eğitilmiş görüntülerin halka açık bir dizisi ImageNet; Görüntüleri tanıyabilen ve ağın operasyon için uzun süre hazırlanmasını gerektirmeyen, önceden eğitilmiş sinir ağları.

İlerleme, donanım tarafında da görülebilir; ağları yüzlerce kat daha hızlı eğitmenize ve kullanmanıza olanak tanıyan yüksek performanslı video kartları vardır.

İkincisi, büyük miktarlarda verinin depolanması ve işlenmesi, önemli miktarda bilgi işlem gücü ve altyapı fonu gerektirir. Eğitim ve ağ işletimi için en az 3-4 GB belleğe sahip kartlara ihtiyaç vardır ve bazı mimariler için 11 konserin tamamı gerekir. Kartlar ucuz değil: Küçük bir proje, yaklaşık 100.000 rubleye mal olan bir kart gerektiriyor. Ayrıca verilerin kendisi için de çok fazla disk alanı gerekir.

Bu nedenle, sinir ağı teknolojisi yaygın olarak geliştirilmektedir ve buna olan talep büyüktür. İnternette konuyla ilgili pek çok literatür ve araştırma bulabilirsiniz; hatta ağların program kodları bile mevcuttur. Yani, bir yandan teknoloji genel olarak mevcut gibi görünüyor, ancak diğer yandan şu anda karmaşık ve yeterince anlaşılmamış durumda. Büyük şirketler düzenli olarak en iyi algoritmalar için her türlü yarışmayı düzenler ve çoğu zaman bu mücadele algoritmaların doğruluğunun yalnızca onda biri ve yüzde biri için yapılır.

Böylece moda alanında mobil tanınma konulu makalemizle finale çıktık KDD Bilgi Keşfi ve Veri Madenciliği alanında dünyanın en büyük konferansı. Raporun metnine linkten ulaşabilirsiniz.

Gelişen teknoloji konusunda çalışmalarımızı sürdürüyoruz.

Temas halinde

Yüz tanıma  bilgisayarlı görme alanında temel bir sorundur ve insanları yüzlerinden tanıyabilen ve ayırt edebilen uygulamalar yaratmaya yönelik önemli bir adımdır. Yüz tanıma yöntemleri son 20 yıldır aktif olarak araştırılıyor ve bu süre zarfında belirli koşullarda çalışan doğru ve etkili yöntemler öneriliyor.

Modern yüz tanıma teknikleri, orta ve büyük yüz görüntüleriyle çalışırken etkileyici sonuçlar elde etmiştir. küçük resimlerle çalışmanın verimliliği tatmin edici değil. Küçük yüzleri (örneğin 10x10 piksel boyutunda) tanımadaki temel zorluk, onu arka plandan ayırt edecek yüz ayrıntılarının olmayışıdır. Diğer bir sorun ise mevcut yüz tanıma yöntemlerinin evrişimli sinir ağlarına dayanması ve bir yüzü temsil etmek için düşük örnekleme oranına ve büyük bir adıma (8, 16, 32) sahip evrişimli özellik haritaları kullanmasıdır; bu haritalar bilgi kaybeder ve küçük verileri tanımlamak için fazla hatalıdır. boyutlu resimler.

Daha iyi yüz tanıma yolunda bu zorlukların üstesinden gelmek için, klasik üretken sinir ağına dayanan evrensel bir evrişimli sinir ağı önerildi. İki alt ağdan oluşur: jeneratör Ve ayrımcı.

Jeneratör bir sinir ağı kullanıyor SRN (süper çözünürlüklü ağ)Çözünürlüğü artırmak için. Çift doğrusal yükseltmeden farklı olarak SRN, oluşturulan görüntülere yapaylık eklemez ve büyük ölçeklendirme faktörleri nedeniyle görüntülerin kalitesini artırır. Buna rağmen araştırmacılar, SRN ve diğer gelişmiş sinir ağlarını kullanırken, ince ayrıntılara sahip olmayan, oldukça bulanık görüntüler elde etti. Bu, giriş görüntülerinin çok düşük çözünürlüğünün bir sonucudur.

Ortaya çıkan görüntülerdeki eksik ayrıntıları düzeltmek ve sınıflandırma görevleri için doğru, yüksek çözünürlüklü görüntüler oluşturmak için "gelişen" bir sinir ağı kullanıldı. RN (arıtma ağı). Nihai ve gerçek görüntüler, her iki görüntünün gerçek mi yoksa yaratılmış mı olduğunu ve yüz gösterip göstermediğini belirleyen bir ayırıcıdan geçirilir. Geri bildirim, jeneratörün daha doğru yüz özelliklerine sahip görüntüler oluşturmasına neden olur.

Sinir ağı mimarisi

Öncelikle jeneratörün yapısına bakalım. İki bölümden oluşur — SRN sinir ağı ve iyileştirme sinir ağı. Birinci sinir ağı, giriş görüntüsünün çözünürlüğünü artırır. Küçük yüz görüntüleri detay eksikliğinden ve ayrıca rms kaybının etkisinden dolayı, ilk sinir ağı tarafından oluşturulan görüntüler genellikle bulanıktır. Bu nedenle bu görüntüleri iyileştiren ikinci bir sinir ağı kullanılır. Sonunda Ayırıcıya yüz tanıma için bir sınıflandırma dalı eklendi Bu, ayırıcının yüzleri ve diğer nesneleri sınıflandırmasının yanı sıra oluşturulan ve gerçek görüntüler arasında ayrım yapmasına olanak tanır.

Jeneratör ve Ayırıcı Mimarisi

Jeneratör

Jeneratörün gelişen sinir ağı, evrişimli bir sinir ağı mimarisine sahiptir. Sonuncusu hariç her evrişimli katmandan sonra normalizasyon (toplu normalleştirme) ve ReLU'nun aktivasyonu gerçekleştirildi.

Jeneratördeki SRN sinir ağı, seçilen görüntü parçalarının çözünürlüğünü 4 kat artırır. Yüz kameradan uzaktaysa veya hareket ediyorsa ortaya çıkan parçalar bulanıklaşıyordu. Sinir ağının iyileştirilmesi bu parçaları işler ve daha ayrıntılı görüntüler üretir Ayırıcının yüzleri kolayca tanıyabildiği.

ayrımcı

Ayırıcı, sinir ağını ana sinir ağı olarak kullanır VGG19Çeşitli çözünürlük azaltma işlemlerini ortadan kaldırmak için alt örnekleme katmanının kaldırıldığı. Ayrıca, tamamen bağlı tüm katmanlar (yani f c6, f c7, f c8), tamamen bağlı iki paralel katmanla değiştirilir fcGAN ve fcclc. Girişe artırılmış çözünürlüklü bir görüntü sağlanır. fcGAN dalı, giriş görüntüsünün gerçek olma olasılığını verir ve fcclc dalı, giriş görüntüsünün bir yüz içerme olasılığını verir.

Kayıp fonksiyonu

Piksel başına kayıp: Jeneratör girişi rastgele gürültü değil, küçük bulanık görüntülerdir. Jeneratörün çıktı görüntüsünü gerçeğe yakın hale getirmenin doğal bir yolu, piksel başına ortalama kare hatasının kökünü kullanmaktır; bu şu şekilde hesaplanır:

burada ILR ve IHR sırasıyla küçük bulanık parçaları (düşük çözünürlük) ve yüksek çözünürlüklü görüntüleri (yüksek çözünürlük) belirtir, G1 — SNR sinir ağı, G2 — gelişen sinir ağı, w  - Jeneratör parametreleri.

Rekabetçi kayıplar: Daha gerçekçi sonuçlara ulaşmak için, şu şekilde tanımlanan düşmanca kayıplar uygulanır:

Düşmanın kaybı, Ayırıcıyı "kandırmak" için sinir ağını daha keskin yüksek frekanslı ayrıntılar üretmeye zorlar.

Sınıflandırma kayıpları: Jeneratör tarafından geri yüklenen görüntülerin tanınmasını kolaylaştırmak için sınıflandırma kayıpları eklenir. Sınıflandırma kayıplarını hesaplama formülü aşağıdaki gibidir:

Sınıflandırma kayıpları iki nedenden dolayı kullanılır. İlk olarak Ayırıcının gerçek ve oluşturulan görüntülerin yüz içerip içermediğini belirlemesine olanak tanır. İkincisi, Jeneratörü daha ayrıntılı görüntüler oluşturmaya teşvik ederler.

Amaç fonksiyonu: Rakip ve sınıflandırma kayıpları piksel başına rms kaybına dahildir. Üretken bir rakip sinir ağı, bir amaç fonksiyonu kullanılarak eğitilebilir. Daha iyi gradyan davranışı için Jeneratör G ve Ayırıcı D'nin kayıp fonksiyonları aşağıdaki şekilde değiştirildi:


İlk denklem, yeniden oluşturulan görüntüleri sırasıyla yüksek frekanslı ayrıntı, piksel ve anlamsal düzeylerde gerçek yüksek çözünürlüklü görüntülere benzer hale getiren rakip, ortalama karekök ve sınıflandırma kayıplarından oluşur. İkinci denklemdeki ayırıcı kayıp fonksiyonu D, yüksek çözünürlüklü görüntülerde yüzlerin mevcut olup olmadığını belirlemek için bir sınıflandırma kaybı ekler. Sınıflandırma kayıpları eklendiğinde, Jeneratörün yeniden oluşturulan görüntüleri, çekişmeli ve ortalama kare kayıpları kullanılarak optimize edilen sonuçlardan daha gerçekçi olur.