ქვემოთ მოყვანილი მაგალითი არის შთაგონებული ორიგინალური გაკვეთილით TensorFlow-ზე, ისევე როგორც ამ ბლოგის პოსტით. სტილის გადაცემის კიდევ ერთი კარგი მაგალითი CNTK ჩარჩოს გამოყენებით არის აქ. აქ არის ორიგინალური ნაშრომი მხატვრული სტილის ტრანსფერი-ზე.
სტილის გადაცემის ძირითადი იდეები შემდეგია:
- თეთრი ხმაურიდან დაწყებული, ჩვენ ვცდილობთ მიმდინარე სურათის $x$-ის ოპტიმიზაციას, რათა მინიმუმამდე დავიყვანოთ დაკარგვის ფუნქცია
- დაკარგვის ფუნქცია შედგება სამი კომპონენტისგან $\mathcal{L(x)} = \alpha\mathcal{L}_c(x,i) + \beta\mathcal{L}_s(x,s)+\gamma\mathcal{L}_t(x)$
- $\mathcal{L}_c$ - შინაარსის დაკარგვა - აჩვენებს, რამდენად ახლოსაა მიმდინარე სურათი $x$ ორიგინალ სურათთან $i$
- $\mathcal{L}_s$ - სტილის დაკარგვა - გვიჩვენებს, რამდენად ახლოსაა მიმდინარე სურათი $x$ სურათის სტილისთვის $s$
- $\mathcal{L}_t$ - ვარიაციის სრული დანაკარგი (ჩვენ არ განვიხილავთ მას ჩვენს მაგალითში) - დარწმუნდება, რომ მიღებული სურათი არის გლუვი, ანუ ის აჩვენებს სურათის მეზობელი პიქსელების საშუალო კვადრატულ შეცდომას $x$
დაკარგვის ეს ფუნქციები უნდა იყოს შემუშავებული ჭკვიანურად, ისე, რომ მაგალითად სტილის დაკარგვა შეესაბამებოდეს სურათების მსგავს სტილებს და არა რეალურ შინაარსს. ამისათვის ჩვენ შევადარებთ CNN-ის რამდენიმე ღრმა მახასიათებლის ფენას, რომელიც ათვალიერებს სურათს.
დავიწყოთ რამდენიმე სურათის ჩატვირთვით:
იტვირთება…გამოტანა
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 210k 100 210k 0 0 2670k 0 --:--:-- --:--:-- --:--:-- 2670k
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 131k 100 131k 0 0 459k 0 --:--:-- --:--:-- --:--:-- 459k
იტვირთება…მოდით, ავტვირთოთ ეს სურათები და შევცვალოთ მათი ზომა $512\times512$-მდე. ასევე, ჩვენ გამოვქმნით შედეგად გამოსახულებას img_result შემთხვევითი მასივის სახით.
იტვირთება…გამოტანა
<Figure size 864x864 with 3 Axes>სტილის დაკარგვისა და შინაარსის დაკარგვის გამოსათვლელად, ჩვენ უნდა ვიმუშაოთ CNN-ის მიერ ამოღებულ ფუნქციების სივრცეში. ჩვენ შეგვიძლია გამოვიყენოთ CNN-ის სხვადასხვა არქიტექტურა, მაგრამ ჩვენს შემთხვევაში სიმარტივისთვის ავირჩევთ VGG-19-ს, წინასწარ მომზადებულ ImageNet-ზე.
იტვირთება…მოდით შევხედოთ მოდელის არქიტექტურას:
იტვირთება…გამოტანა
Model: "vgg16"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_3 (InputLayer) [(None, None, None, 3)] 0
block1_conv1 (Conv2D) (None, None, None, 64) 1792
block1_conv2 (Conv2D) (None, None, None, 64) 36928
block1_pool (MaxPooling2D) (None, None, None, 64) 0
block2_conv1 (Conv2D) (None, None, None, 128) 73856
block2_conv2 (Conv2D) (None, None, None, 128) 147584
block2_pool (MaxPooling2D) (None, None, None, 128) 0
block3_conv1 (Conv2D) (None, None, None, 256) 295168
block3_conv2 (Conv2D) (None, None, None, 256) 590080
block3_conv3 (Conv2D) (None, None, None, 256) 590080
block3_pool (MaxPooling2D) (None, None, None, 256) 0
block4_conv1 (Conv2D) (None, None, None, 512) 1180160
block4_conv2 (Conv2D) (None, None, None, 512) 2359808
block4_conv3 (Conv2D) (None, None, None, 512) 2359808
block4_pool (MaxPooling2D) (None, None, None, 512) 0
block5_conv1 (Conv2D) (None, None, None, 512) 2359808
block5_conv2 (Conv2D) (None, None, None, 512) 2359808
block5_conv3 (Conv2D) (None, None, None, 512) 2359808
block5_pool (MaxPooling2D) (None, None, None, 512) 0
=================================================================
Total params: 14,714,688
Trainable params: 0
Non-trainable params: 14,714,688
_________________________________________________________________
მოდით განვსაზღვროთ ფუნქცია, რომელიც საშუალებას მოგვცემს გამოვიტანოთ შუალედური ფუნქციები VGG ქსელიდან:
იტვირთება…შინაარსის დაკარგვა
შინაარსის დაკარგვა აჩვენებს, რამდენად ახლოსაა ჩვენი ამჟამინდელი სურათი $x$ თავდაპირველ სურათთან. ის უყურებს შუალედურ ფუნქციების ფენებს CNN-ში და ითვლის კვადრატულ შეცდომას. შიგთავსის დაკარგვა $l$ ფენაზე განისაზღვრება როგორც $$ \mathcal{L}c = {1\over2}\sum{i,j} (F_{ij}^{(l)}-P_{ij}^{(l)})^2 $$ სადაც $F^{(l)}$ და $P^{(l)}$ -- მახასიათებლები $l$-ზე.
იტვირთება…ახლა განვახორციელებთ სტილის გადაცემის მთავარ ხრიკს - ოპტიმიზაცია. ჩვენ დავიწყებთ შემთხვევითი გამოსახულებით და შემდეგ გამოვიყენებთ TensorFlow ოპტიმიზატორს ამ სურათის დასარეგულირებლად, შინაარსის დაკარგვის შესამცირებლად.
მნიშვნელოვანი: ჩვენს შემთხვევაში, ყველა გამოთვლა ხორციელდება GPU-aware TensorFlow ჩარჩოს გამოყენებით, რაც საშუალებას აძლევს ამ კოდს ბევრად უფრო ეფექტურად იმუშაოს GPU-ზე.
იტვირთება…გამოტანა
<Figure size 864x864 with 1 Axes>სავარჯიშო: სცადეთ ექსპერიმენტი ჩაატაროთ ქსელში სხვადასხვა შრეებით და ნახეთ რა მოხდება. თქვენ ასევე შეგიძლიათ სცადოთ ოპტიმიზაცია რამდენიმე ფენისთვის ერთად, მაგრამ თქვენ მოგიწევთ ცოტათი შეცვალოთ კოდი
content_loss-ისთვის.
სტილის დაკარგვა
სტილის დაკარგვა არის Style Transfer-ის მთავარი იდეა. ჩვენ ვადარებთ არა რეალურ მახასიათებლებს, არამედ მათ გრამის მატრიცებს, რომლებიც განისაზღვრება როგორც $$G=A\ჯერ A^T$$
გრამ მატრიცა კორელაციური მატრიცის მსგავსია და ის გვიჩვენებს, თუ როგორ არის დამოკიდებული ზოგიერთი ფილტრი სხვებზე. Style Loss გამოითვლება, როგორც დანაკარგების ჯამი სხვადასხვა ფენებიდან, რომლებიც ხშირად განიხილება შეწონილი კოეფიციენტებით.
მთლიანი დაკარგვის ფუნქცია სტილის გადაცემისთვის არის შინაარსის დაკარგვის და სტილის დაკარგვის ჯამი.
იტვირთება…ეს ყველაფერი ერთად
ჩვენ განვსაზღვრავთ total_loss ფუნქციას, რომელიც გამოთვლის კომბინირებულ დანაკარგს და აწარმოებს ოპტიმიზაციას:
იტვირთება…გამოტანა
<Figure size 864x864 with 1 Axes>ქვემოთ მოცემული კოდი ასრულებს დანაკარგის რეალურ ოპტიმიზაციას. გაითვალისწინეთ, რომ GPU-სთან ერთად ოპტიმიზაციას მნიშვნელოვანი დრო სჭირდება. შეგიძლიათ რამდენჯერმე გაუშვათ ქვემოთ მოცემული უჯრედი შედეგის გასაუმჯობესებლად.
დაამატეთ ვარიაციის დაკარგვა
ვარიაციის დაკარგვა საშუალებას გვაძლევს გავხადოთ სურათი ნაკლებად ხმაურიანი მეზობელ პიქსელებს შორის სხვაობის მინიმიზაციის გზით.
ჩვენ ასევე დავიწყებთ ოპტიმიზაციას ორიგინალური შინაარსის სურათიდან, რაც საშუალებას გვაძლევს შევინარჩუნოთ მეტი შინაარსის დეტალები სურათში, კონტენტის დაკარგვის ფუნქციის გართულების გარეშე. თუმცა, ჩვენ დავამატებთ ხმაურს.
იტვირთება…გამოტანა
<Figure size 864x864 with 1 Axes>იტვირთება…გამოტანა
(256, 256, 3)
True