CNN-ების ტრენინგს შეიძლება ბევრი დრო დასჭირდეს და ამ ამოცანისთვის ბევრი მონაცემია საჭირო. თუმცა, დროის დიდი ნაწილი იხარჯება საუკეთესო დაბალი დონის ფილტრების შესასწავლად, რომლებსაც ქსელი იყენებს სურათებიდან შაბლონების ამოსაღებად. ჩნდება ბუნებრივი კითხვა - შეგვიძლია გამოვიყენოთ ერთ მონაცემთა ბაზაზე მომზადებული ნერვული ქსელი და მოვარგოთ სხვადასხვა სურათების კლასიფიკაციას სრული სასწავლო პროცესის გარეშე?
ამ მიდგომას ეწოდება ტრანსფერული სწავლა, რადგან ჩვენ გადავცემთ გარკვეულ ცოდნას ერთი ნერვული ქსელის მოდელიდან მეორეზე. გადაცემის სწავლისას, ჩვენ ჩვეულებრივ ვიწყებთ წინასწარ გაწვრთნილი მოდელით, რომელიც გავლილი იყო გარკვეული დიდი სურათების მონაცემთა ბაზაზე, როგორიცაა ImageNet. ამ მოდელებს უკვე შეუძლიათ კარგი სამუშაოს შესრულება ზოგადი სურათებისგან განსხვავებული ფუნქციების ამოღებით და ხშირ შემთხვევაში მხოლოდ კლასიფიკატორის აგება ამ ამოღებულ მახასიათებლებზე შეიძლება კარგი შედეგის მომტანი იყოს.
იტვირთება…კატები ძაღლების წინააღმდეგ მონაცემთა ნაკრები
ამ განყოფილებაში ჩვენ მოვაგვარებთ კატებისა და ძაღლების სურათების კლასიფიკაციის რეალურ პრობლემას. ამ მიზეზით, ჩვენ გამოვიყენებთ Kaggle Cats vs. Dogs მონაცემთა ნაკრები, რომლის ჩამოტვირთვაც შესაძლებელია Microsoft-ისგან.
გადმოვწეროთ ეს მონაცემთა ნაკრები და ამოვიტანოთ data დირექტორიაში (ამ პროცესს შეიძლება გარკვეული დრო დასჭირდეს!):
იტვირთება…იტვირთება…სამწუხაროდ, მონაცემთა ნაკრებში არის რამდენიმე კორუმპირებული გამოსახულების ფაილი. ჩვენ გვჭირდება სწრაფი გაწმენდა დაზიანებული ფაილების შესამოწმებლად. იმისათვის, რომ ეს ტუტორიალი არ დავკარგოთ, ჩვენ გადავიტანეთ კოდი მონაცემთა ნაკრების დასადასტურებლად მოდულში.
იტვირთება…გამოტანა
Corrupt image or wrong format: data/PetImages/Cat/12235.jpg
Corrupt image or wrong format: data/PetImages/Cat/2663.jpg
Corrupt image or wrong format: data/PetImages/Cat/4929.jpg
Corrupt image or wrong format: data/PetImages/Cat/8183.jpg
Corrupt image or wrong format: data/PetImages/Cat/11083.jpg
Corrupt image or wrong format: data/PetImages/Cat/6435.jpg
Corrupt image or wrong format: data/PetImages/Cat/6491.jpg
Corrupt image or wrong format: data/PetImages/Cat/7968.jpg
Corrupt image or wrong format: data/PetImages/Cat/6768.jpg
Corrupt image or wrong format: data/PetImages/Cat/11397.jpg
Corrupt image or wrong format: data/PetImages/Cat/8295.jpg
Corrupt image or wrong format: data/PetImages/Cat/4874.jpg
Corrupt image or wrong format: data/PetImages/Cat/23.jpg
Corrupt image or wrong format: data/PetImages/Cat/11864.jpg
Corrupt image or wrong format: data/PetImages/Cat/3491.jpg
Corrupt image or wrong format: data/PetImages/Cat/11729.jpg
Corrupt image or wrong format: data/PetImages/Cat/3197.jpg
Corrupt image or wrong format: data/PetImages/Cat/10874.jpg
Corrupt image or wrong format: data/PetImages/Cat/6376.jpg
Corrupt image or wrong format: data/PetImages/Cat/9361.jpg
Corrupt image or wrong format: data/PetImages/Cat/9328.jpg
Corrupt image or wrong format: data/PetImages/Cat/910.jpg
Corrupt image or wrong format: data/PetImages/Cat/2021.jpg
Corrupt image or wrong format: data/PetImages/Cat/666.jpg
Corrupt image or wrong format: data/PetImages/Cat/3710.jpg
Corrupt image or wrong format: data/PetImages/Cat/9171.jpg
Corrupt image or wrong format: data/PetImages/Cat/6906.jpg
Corrupt image or wrong format: data/PetImages/Cat/11095.jpg
Corrupt image or wrong format: data/PetImages/Cat/660.jpg
Corrupt image or wrong format: data/PetImages/Cat/8415.jpg
Corrupt image or wrong format: data/PetImages/Cat/3161.jpg
Corrupt image or wrong format: data/PetImages/Cat/850.jpg
Corrupt image or wrong format: data/PetImages/Cat/7003.jpg
Corrupt image or wrong format: data/PetImages/Cat/1267.jpg
Corrupt image or wrong format: data/PetImages/Cat/7642.jpg
Corrupt image or wrong format: data/PetImages/Cat/8553.jpg
Corrupt image or wrong format: data/PetImages/Cat/6900.jpg
Corrupt image or wrong format: data/PetImages/Cat/4334.jpg
Corrupt image or wrong format: data/PetImages/Cat/10404.jpg
Corrupt image or wrong format: data/PetImages/Cat/6980.jpg
Corrupt image or wrong format: data/PetImages/Cat/936.jpg
Corrupt image or wrong format: data/PetImages/Cat/9619.jpg
Corrupt image or wrong format: data/PetImages/Cat/3300.jpg
Corrupt image or wrong format: data/PetImages/Cat/7647.jpg
Corrupt image or wrong format: data/PetImages/Cat/2742.jpg
Corrupt image or wrong format: data/PetImages/Cat/9565.jpg
Corrupt image or wrong format: data/PetImages/Cat/1757.jpg
Corrupt image or wrong format: data/PetImages/Cat/11874.jpg
Corrupt image or wrong format: data/PetImages/Cat/1936.jpg
Corrupt image or wrong format: data/PetImages/Cat/5077.jpg
Corrupt image or wrong format: data/PetImages/Cat/7845.jpg
Corrupt image or wrong format: data/PetImages/Cat/8832.jpg
Corrupt image or wrong format: data/PetImages/Cat/11935.jpg
Corrupt image or wrong format: data/PetImages/Cat/9208.jpg
Corrupt image or wrong format: data/PetImages/Cat/4322.jpg
Corrupt image or wrong format: data/PetImages/Cat/7978.jpg
Corrupt image or wrong format: data/PetImages/Cat/10820.jpg
Corrupt image or wrong format: data/PetImages/Cat/391.jpg
Corrupt image or wrong format: data/PetImages/Cat/10073.jpg
Corrupt image or wrong format: data/PetImages/Cat/8958.jpg
Corrupt image or wrong format: data/PetImages/Cat/8470.jpg
Corrupt image or wrong format: data/PetImages/Cat/445.jpg
Corrupt image or wrong format: data/PetImages/Cat/4821.jpg
Corrupt image or wrong format: data/PetImages/Cat/11565.jpg
Corrupt image or wrong format: data/PetImages/Cat/4351.jpg
Corrupt image or wrong format: data/PetImages/Cat/4833.jpg
Corrupt image or wrong format: data/PetImages/Cat/140.jpg
Corrupt image or wrong format: data/PetImage
… (გამოტანა შემოკლებულია)/anaconda/envs/py38_tensorflow/lib/python3.8/site-packages/PIL/TiffImagePlugin.py:793: UserWarning: Truncated File Read
warnings.warn(str(msg))
Corrupt image or wrong format: data/PetImages/Dog/543.jpg
Corrupt image or wrong format: data/PetImages/Dog/8730.jpg
Corrupt image or wrong format: data/PetImages/Dog/12114.jpg
Corrupt image or wrong format: data/PetImages/Dog/522.jpg
Corrupt image or wrong format: data/PetImages/Dog/10863.jpg
Corrupt image or wrong format: data/PetImages/Dog/10401.jpg
Corrupt image or wrong format: data/PetImages/Dog/7739.jpg
Corrupt image or wrong format: data/PetImages/Dog/561.jpg
Corrupt image or wrong format: data/PetImages/Dog/1308.jpg
Corrupt image or wrong format: data/PetImages/Dog/9643.jpg
Corrupt image or wrong format: data/PetImages/Dog/3155.jpg
Corrupt image or wrong format: data/PetImages/Dog/5736.jpg
Corrupt image or wrong format: data/PetImages/Dog/4257.jpg
Corrupt image or wrong format: data/PetImages/Dog/11853.jpg
Corrupt image or wrong format: data/PetImages/Dog/6855.jpg
Corrupt image or wrong format: data/PetImages/Dog/1259.jpg
Corrupt image or wrong format: data/PetImages/Dog/7652.jpg
Corrupt image or wrong format: data/PetImages/Dog/573.jpg
Corrupt image or wrong format: data/PetImages/Dog/11702.jpg
Corrupt image or wrong format: data/PetImages/Dog/414.jpg
Corrupt image or wrong format: data/PetImages/Dog/4301.jpg
Corrupt image or wrong format: data/PetImages/Dog/9500.jpg
Corrupt image or wrong format: data/PetImages/Dog/10726.jpg
Corrupt image or wrong format: data/PetImages/Dog/9367.jpg
Corrupt image or wrong format: data/PetImages/Dog/2877.jpg
Corrupt image or wrong format: data/PetImages/Dog/10907.jpg
Corrupt image or wrong format: data/PetImages/Dog/10972.jpg
Corrupt image or wrong format: data/PetImages/Dog/7311.jpg
Corrupt image or wrong format: data/PetImages/Dog/10797.jpg
Corrupt image or wrong format: data/PetImages/Dog/2317.jpg
Corrupt image or wrong format: data/PetImages/Dog/7128.jpg
Corrupt image or wrong format: data/PetImages/Dog/6500.jpg
Corrupt image or wrong format: data/PetImages/Dog/11285.jpg
Corrupt image or wrong format: data/PetImages/Dog/6430.jpg
Corrupt image or wrong format: data/PetImages/Dog/6032.jpg
Corrupt image or wrong format: data/PetImages/Dog/10969.jpg
Corrupt image or wrong format: data/PetImages/Dog/8364.jpg
Corrupt image or wrong format: data/PetImages/Dog/11692.jpg
Corrupt image or wrong format: data/PetImages/Dog/3038.jpg
Corrupt image or wrong format: data/PetImages/Dog/5604.jpg
Corrupt image or wrong format: data/PetImages/Dog/565.jpg
Corrupt image or wrong format: data/PetImages/Dog/9640.jpg
Corrupt image or wrong format: data/PetImages/Dog/7459.jpg
Corrupt image or wrong format: data/PetImages/Dog/6305.jpg
Corrupt image or wrong format: data/PetImages/Dog/6555.jpg
Corrupt image or wrong format: data/PetImages/Dog/11590.jpg
Corrupt image or wrong format: data/PetImages/Dog/6059.jpg
Corrupt image or wrong format: data/PetImages/Dog/3927.jpg
Corrupt image or wrong format: data/PetImages/Dog/10705.jpg
Corrupt image or wrong format: data/PetImages/Dog/2384.jpg
Corrupt image or wrong format: data/PetImages/Dog/3885.jpg
Corrupt image or wrong format: data/PetImages/Dog/663.jpg
Corrupt image or wrong format: data/PetImages/Dog/9043.jpg
Corrupt image or wrong format: data/PetImages/Dog/8563.jpg
Corrupt image or wrong format: data/PetImages/Dog/9556.jpg
Corrupt image or wrong format: data/PetImages/Dog/9967.jpg
Corrupt image or wrong format: data/PetImages/Dog/10158.jpg
Corrupt image or wrong format: data/PetImages/Dog/5263.jpg
Corrupt image or wrong format: data/PetImages/Dog/8641.jpg
Corrupt image or wrong format: data/PetImages/Dog/7369.jpg
Corrupt image or wrong format: data/PetImages/Dog/4924.jpg
Corrupt image or wrong format: data/PetImages/Dog/10351.jpg
Corrupt image or wrong format: data/PetImages/Dog/6213.jpg
Corrupt image or wrong format: data/PetImages/Dog/5104.jpg
Corrupt image or wrong format: data/PetImages/Dog/1356.jpg
Corrupt image or wrong format: data/PetImages/Dog/7133.jpg
Corrupt image or wrong format: data/PetImages/Dog/7112.jpg
Corrupt image or wrong format: data/Pe
… (გამოტანა შემოკლებულია)იტვირთება მონაცემთა ნაკრები
წინა მაგალითებში ჩვენ ვტვირთავდით Keras-ში ჩაშენებულ მონაცემთა ნაკრებებს. ახლა ჩვენ ვაპირებთ გაუმკლავდეთ ჩვენს მონაცემთა ბაზას, რომელიც უნდა ჩატვირთოთ სურათების დირექტორიადან.
რეალურ ცხოვრებაში, სურათების მონაცემთა ნაკრების ზომა შეიძლება იყოს საკმაოდ დიდი და არ შეიძლება დაეყრდნოთ ყველა მონაცემს, რომელიც შეძლებს მეხსიერებაში მოთავსებას. ამრიგად, მონაცემთა ნაკრები ხშირად წარმოდგენილია როგორც გენერატორები, რომლებსაც შეუძლიათ მონაცემების დაბრუნება ტრენინგისთვის შესაფერისი მინი პაკეტებში.
გამოსახულების კლასიფიკაციისთვის Keras მოიცავს სპეციალურ ფუნქციას image_dataset_from_directory, რომელსაც შეუძლია სურათების ჩატვირთვა სხვადასხვა კლასების შესაბამისი ქვედირექტორიებიდან. ეს ფუნქცია ასევე ზრუნავს სურათების სკალირებაზე და მას ასევე შეუძლია მონაცემთა დაყოფა მატარებელ და სატესტო ქვეჯგუფებად:
იტვირთება…გამოტანა
Found 24769 files belonging to 2 classes.
Using 19816 files for training.
Found 24769 files belonging to 2 classes.
Using 4953 files for validation.
მნიშვნელოვანია ორივე ზარისთვის იგივე seed მნიშვნელობის დაყენება, რადგან ეს გავლენას ახდენს სურათების გაყოფაზე მატარებლისა და ტესტის მონაცემთა ბაზას შორის.
მონაცემთა ნაკრები ავტომატურად იღებს კლასების სახელებს დირექტორიებიდან და საჭიროების შემთხვევაში შეგიძლიათ მათზე წვდომა დარეკვით:
იტვირთება…გამოტანა
['Cat', 'Dog']მონაცემთა ნაკრები, რომელიც ჩვენ მივიღეთ, შეიძლება პირდაპირ გადავიდეს fit ფუნქციაზე მოდელის მოსამზადებლად. ისინი შეიცავს როგორც შესაბამის სურათებს, ასევე ეტიკეტებს, რომელთა გადატანა შესაძლებელია შემდეგი კონსტრუქციის გამოყენებით:
იტვირთება…გამოტანა
Training batch shape: features=(64, 224, 224, 3), labels=(64,)

შენიშვნა: მონაცემთა ნაკრების ყველა სურათი წარმოდგენილია როგორც მცურავი წერტილის ტენსორები დიაპაზონით 0-255. სანამ მათ ნერვულ ქსელში გადავიტანთ, ჩვენ უნდა გავაფართოვოთ ეს მნიშვნელობები 0-1 დიაპაზონში. სურათების შედგენისას ჩვენ ან უნდა გავაკეთოთ იგივე, ან გადავიტანოთ მნიშვნელობები
intტიპად (რასაც ვაკეთებთ ზემოთ მოცემულ კოდში), რათა ვაჩვენოთmatplotlib, რომ გვინდა გამოვსახოთ ორიგინალური გაუსწორებელი სურათი.
წინასწარ მომზადებული მოდელები
For many image classification tasks one can find pre-trained neural network models. Many of those models are available inside keras.applications namespace, and even more models can be found on the Internet. ვნახოთ, რამდენად მარტივია VGG-16 მოდელის ჩატვირთვა და გამოყენება:
იტვირთება…გამოტანა
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels.h5
553467904/553467096 [==============================] - 6s 0us/step
Most probable class = [208]
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/imagenet_class_index.json
40960/35363 [==================================] - 0s 0us/step
[[('n02099712', 'Labrador_retriever', 0.5340957),
('n02100236', 'German_short-haired_pointer', 0.0939442),
('n02092339', 'Weimaraner', 0.08160535),
('n02099849', 'Chesapeake_Bay_retriever', 0.057179328),
('n02109047', 'Great_Dane', 0.03733857)]]აქ არის რამდენიმე მნიშვნელოვანი რამ:
- სანამ რაიმე წინასწარ გაწვრთნილ ქსელში შეყვანის გაცემამდე ის წინასწარ უნდა დამუშავდეს გარკვეული გზით. ეს კეთდება შესაბამისი
preprocess_inputფუნქციის გამოძახებით, რომელიც იღებს სურათების ჯგუფს და აბრუნებს მათ დამუშავებულ ფორმას. VGG-16-ის შემთხვევაში, გამოსახულებები ნორმალიზდება და თითოეული არხისთვის წინასწარ განსაზღვრული საშუალო მნიშვნელობა გამოკლებულია. ეს იმიტომ ხდება, რომ VGG-16 თავდაპირველად გაწვრთნილი იყო ამ წინასწარი დამუშავებით. - ნერვული ქსელი გამოიყენება შეყვანის ჯგუფზე და შედეგად ვიღებთ 1000-ელემენტიანი ტენზორების პარტიას, რომელიც აჩვენებს თითოეული კლასის ალბათობას. ჩვენ შეგვიძლია ვიპოვოთ ყველაზე სავარაუდო კლასის ნომერი ამ ტენზორზე
argmax-ზე დარეკვით. - მიღებული შედეგია
ImageNetკლასის ნომერი. ამ შედეგის გასაგებად, ჩვენ ასევე შეგვიძლია გამოვიყენოთdecode_predictionsფუნქცია, რომელიც აბრუნებს ტოპ n კლასს მათ სახელებთან ერთად.
მოდით ასევე ვნახოთ VGG-16 ქსელის არქიტექტურა:
იტვირთება…გამოტანა
Model: "vgg16"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 224, 224, 3)] 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
_________________________________________________________________
flatten (Flatten) (None, 25088) 0
_________________________________________________________________
fc1 (Dense) (None, 4096) 102764544
_________________________________________________________________
fc2 (Dense) (None, 4096) 16781312
_________________________________________________________________
predictions (Dense) (None, 1000) 4097000
=================================================================
Total params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
_________________________________________________________________
GPU გამოთვლები
ღრმა ნეირონული ქსელები, როგორიცაა VGG-16 და სხვა უფრო თანამედროვე არქიტექტურა, საკმაოდ დიდ გამოთვლით ძალას მოითხოვს. აზრი აქვს GPU აჩქარების გამოყენებას, თუ ის ხელმისაწვდომია. საბედნიეროდ, Keras ავტომატურად აჩქარებს გამოთვლებს GPU-ზე, თუ ის ხელმისაწვდომია. ჩვენ შეგვიძლია შევამოწმოთ თუ არა Tensorflow-ს შეუძლია გამოიყენოს GPU შემდეგი კოდის გამოყენებით:
იტვირთება…გამოტანა
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]VGG მახასიათებლების ამოღება
თუ გვინდა გამოვიყენოთ VGG-16 ჩვენი სურათებიდან ფუნქციების ამოსაღებად, გვჭირდება მოდელი საბოლოო კლასიფიკაციის ფენების გარეშე. ჩვენ შეგვიძლია გამოვიყენოთ VGG-16 მოდელი ზედა ფენების გარეშე ამ კოდის გამოყენებით:
იტვირთება…გამოტანა
Shape after applying VGG-16: (7, 7, 512)
<matplotlib.image.AxesImage at 0x7fafcc685ac0>
მახასიათებლის ტენზორის განზომილებაა 7x7x512, მაგრამ მისი ვიზუალიზაციისთვის ჩვენ უნდა გადაგვეკეთებინა 2D ფორმაში.
ახლა ვცადოთ ვნახოთ, შეიძლება თუ არა ამ ფუნქციების გამოყენება სურათების კლასიფიკაციისთვის. მოდით ხელით ავიღოთ სურათების გარკვეული ნაწილი (ჩვენს შემთხვევაში 50 მინი პარტია) და წინასწარ გამოვთვალოთ მათი მახასიათებლების ვექტორები. ჩვენ შეგვიძლია გამოვიყენოთ Tensorflow dataset API ამისათვის. map ფუნქცია იღებს მონაცემთა ნაკრებს და იყენებს მოცემულ ლამბდა ფუნქციას მის გარდაქმნისთვის. ჩვენ ვიყენებთ ამ მექანიზმს მონაცემთა ახალი ნაკრების შესაქმნელად, ds_features_train და ds_features_test, რომლებიც შეიცავს VGG-ით ამოღებულ ფუნქციებს ორიგინალური სურათების ნაცვლად.
იტვირთება…გამოტანა
(64, 7, 7, 512) (64,)
ჩვენ გამოვიყენეთ კონსტრუქცია .take(50) მონაცემთა ნაკრების ზომის შესაზღუდად, ჩვენი დემონსტრირების დასაჩქარებლად. თქვენ, რა თქმა უნდა, შეგიძლიათ განახორციელოთ ეს ექსპერიმენტი სრულ მონაცემთა ბაზაზე.
ახლა, როდესაც ჩვენ გვაქვს მონაცემთა ნაკრები მოპოვებული მახასიათებლებით, ჩვენ შეგვიძლია მოვამზადოთ მარტივი მკვრივი კლასიფიკატორი კატებისა და ძაღლების გასარჩევად. ეს ქსელი მიიღებს ფორმის ვექტორს (7,7,512) და გამოიმუშავებს ერთ გამოსავალს, რომელიც შეესაბამება ძაღლს ან კატას. იმის გამო, რომ ეს არის ორობითი კლასიფიკაცია, ჩვენ ვიყენებთ sigmoid აქტივაციის ფუნქციას და binary_crossentropy დაკარგვას.
იტვირთება…გამოტანა
50/50 [==============================] - 1896s 38s/step - loss: 1.4845 - acc: 0.9144 - val_loss: 0.7220 - val_acc: 0.9516
შედეგი შესანიშნავია, თითქმის 95%-იანი ალბათობით შეგვიძლია გამოვყოთ კატა და ძაღლი! თუმცა, ჩვენ გამოვცადეთ ეს მიდგომა მხოლოდ ყველა სურათის ქვეჯგუფზე, რადგან, როგორც ჩანს, ფუნქციების ხელით ამოღებას დიდი დრო სჭირდება.
სწავლის გადაცემა ერთი VGG ქსელის გამოყენებით
ჩვენ ასევე შეგვიძლია თავიდან ავიცილოთ ფუნქციების ხელით წინასწარი გამოთვლა ტრენინგის დროს ორიგინალური VGG-16 ქსელის მთლიანობაში გამოყენებით, ჩვენს ქსელში ფუნქციების ამომყვანის დამატებით, როგორც პირველ ფენას.
Keras-ის არქიტექტურის სილამაზე იმაში მდგომარეობს, რომ VGG-16 მოდელი, რომელიც ზემოთ განვსაზღვრეთ, ასევე შეიძლება გამოყენებულ იქნას როგორც ფენა სხვა ნერვულ ქსელში! ჩვენ უბრალოდ უნდა ავაშენოთ ქსელი მკვრივი კლასიფიკატორით მის თავზე და შემდეგ მოვამზადოთ მთელი ქსელი უკანა გამრავლების გამოყენებით.
იტვირთება…გამოტანა
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
vgg16 (Functional) (None, 7, 7, 512) 14714688
_________________________________________________________________
flatten (Flatten) (None, 25088) 0
_________________________________________________________________
dense (Dense) (None, 1) 25089
=================================================================
Total params: 14,739,777
Trainable params: 25,089
Non-trainable params: 14,714,688
_________________________________________________________________
ეს მოდელი ჰგავს და ბოლოდან ბოლომდე კლასიფიკაციის ქსელს, რომელიც იღებს სურათს და აბრუნებს კლასს. თუმცა, სახიფათო ის არის, რომ ჩვენ გვინდა, რომ VGG16 იმოქმედოს როგორც ფუნქციების ამომყვანი და არა ხელახლა გადამზადება. ამრიგად, ჩვენ გვჭირდება კონვოლუციური მახასიათებლების ამომყვანის წონების გაყინვა. ჩვენ შეგვიძლია ქსელის პირველ შრეზე წვდომა model.layers[0]-ის გამოძახებით და ჩვენ უბრალოდ უნდა დავაყენოთ trainable თვისება False.
შენიშვნა: საჭიროა მახასიათებლის ექსტრაქტორის წონების გაყინვა, რადგან სხვაგვარად დაუვარჯიშებელი კლასიფიკატორის ფენას შეუძლია გაანადგუროს კონვოლუციური ექსტრაქტორის ორიგინალური წინასწარ მომზადებული წონა.
თქვენ შეგიძლიათ შეამჩნიოთ, რომ მიუხედავად იმისა, რომ ჩვენს ქსელში პარამეტრების საერთო რაოდენობა დაახლოებით 15 მილიონია, ჩვენ ვვარჯიშობთ მხოლოდ 25 ათასი პარამეტრს. უმაღლესი დონის კონვოლუციური ფილტრების ყველა სხვა პარამეტრი წინასწარ არის მომზადებული. ეს კარგია, რადგან ჩვენ შეგვიძლია უფრო მცირე რაოდენობის პარამეტრების დაზუსტება მაგალითების მცირე რაოდენობით.
ჩვენ ახლა მოვამზადებთ ჩვენს ქსელს და ვნახავთ, რამდენად კარგის მიღწევა შეგვიძლია. მოსალოდნელია საკმაოდ ხანგრძლივი მუშაობის დრო და არ ინერვიულოთ, თუ შესრულება გარკვეული დროით გაყინულია.
იტვირთება…გამოტანა
310/310 [==============================] - 265s 716ms/step - loss: 0.9917 - acc: 0.9512 - val_loss: 0.8156 - val_acc: 0.9671
როგორც ჩანს, ჩვენ მივიღეთ საკმაოდ ზუსტი კლასიფიკატორი კატები ძაღლების წინააღმდეგ!
მოდელის შენახვა და ჩატვირთვა
მას შემდეგ რაც ჩვენ მოვამზადებთ მოდელს, ჩვენ შეგვიძლია შევინახოთ მოდელის არქიტექტურა და გაწვრთნილი წონა ფაილში მომავალი გამოყენებისთვის:
იტვირთება…გამოტანა
INFO:tensorflow:Assets written to: data/cats_dogs.tf/assets
შემდეგ ჩვენ შეგვიძლია ჩატვირთოთ მოდელი ფაილიდან ნებისმიერ დროს. შეიძლება გამოგადგეთ იმ შემთხვევაში, თუ მომდევნო ექსპერიმენტმა გაანადგურა მოდელი - თქვენ არ მოგიწევთ თავიდან დაწყება ნულიდან.
იტვირთება…დახვეწილი გადაცემის სწავლა
წინა განყოფილებაში, ჩვენ ვავარჯიშეთ საბოლოო კლასიფიკატორის ფენა სურათების კლასიფიკაციისთვის ჩვენს მონაცემთა ბაზაში. თუმცა, ჩვენ არ გადავარჯიშეთ ფუნქციების ამომყვანი და ჩვენი მოდელი ეყრდნობოდა იმ ფუნქციებს, რომლებიც მოდელმა ისწავლა ImageNet-ის მონაცემებზე. თუ თქვენი ობიექტები ვიზუალურად განსხვავდებიან ჩვეულებრივი ImageNet სურათებისგან, ფუნქციების ეს კომბინაცია შესაძლოა საუკეთესოდ არ იმუშაოს. ამრიგად, აზრი აქვს კონვოლუციური ფენების ვარჯიშის დაწყებასაც.
ამისათვის ჩვენ შეგვიძლია გავაყინოთ კონვოლუციური ფილტრის პარამეტრები, რომლებიც ადრე გავყინეთ.
შენიშვნა: მნიშვნელოვანია, რომ ჯერ გაყინოთ პარამეტრები და განახორციელოთ ვარჯიშის რამდენიმე ეპოქა, რათა დასტაბილურდეს წონა კლასიფიკაციის ფენაში. თუ დაუყონებლივ დაიწყებთ ქსელის ბოლომდე ვარჯიშს გაყინული პარამეტრებით, დიდი შეცდომები სავარაუდოდ გაანადგურებს წინასწარ მომზადებულ წონებს კონვოლუციურ ფენებში.
ჩვენი კონვოლუციური VGG-16 მოდელი მდებარეობს პირველი ფენის შიგნით და ის თავად შედგება მრავალი ფენისგან. ჩვენ შეგვიძლია შევხედოთ მის სტრუქტურას:
იტვირთება…გამოტანა
Model: "vgg16"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 224, 224, 3)] 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
=================================================================
Total params: 14,714,688
Trainable params: 0
Non-trainable params: 14,714,688
_________________________________________________________________
ჩვენ შეგვიძლია გავყინოთ კონვოლუციური ბაზის ყველა ფენა:
იტვირთება…თუმცა, ყველა მათგანის ერთდროულად გაუქმება საუკეთესო იდეა არ არის. ჩვენ შეგვიძლია თავიდან გავაყინოთ კონვოლუციის მხოლოდ რამდენიმე ბოლო ფენა, რადგან ისინი შეიცავს უფრო მაღალი დონის ნიმუშებს, რომლებიც აქტუალურია ჩვენი სურათებისთვის. მაგალითად, დასაწყისისთვის, ჩვენ შეგვიძლია გავყინოთ ყველა ფენა, გარდა ბოლო 4-ისა:
იტვირთება…გამოტანა
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
vgg16 (Functional) (None, 7, 7, 512) 14714688
_________________________________________________________________
flatten (Flatten) (None, 25088) 0
_________________________________________________________________
dense (Dense) (None, 1) 25089
=================================================================
Total params: 14,739,777
Trainable params: 7,104,513
Non-trainable params: 7,635,264
_________________________________________________________________
დააკვირდით, რომ სავარჯიშო პარამეტრების რაოდენობა მნიშვნელოვნად გაიზარდა, მაგრამ მაინც არის ყველა პარამეტრის დაახლოებით 50%.
გაყინვის შემდეგ შეგვიძლია გავაკეთოთ ვარჯიშის კიდევ რამდენიმე ეპოქა (ჩვენს მაგალითში მხოლოდ ერთს გავაკეთებთ). თქვენ ასევე შეგიძლიათ აირჩიოთ უფრო დაბალი სწავლის სიჩქარე, რათა მინიმუმამდე დაიყვანოთ გავლენა წინასწარ მომზადებულ წონებზე. თუმცა, სწავლის დაბალი სიჩქარითაც კი, თქვენ შეგიძლიათ მოელოდეთ, რომ სიზუსტე დაეცემა ვარჯიშის დასაწყისში, სანამ საბოლოოდ არ მიაღწევთ ოდნავ უფრო მაღალ დონეს, ვიდრე ფიქსირებული წონის შემთხვევაში.
შენიშვნა: ეს ტრენინგი გაცილებით ნელა მიმდინარეობს, რადგან ჩვენ გვჭირდება გრადიენტების გავრცელება ქსელის მრავალ ფენაში!
იტვირთება…გამოტანა
310/310 [==============================] - 201s 645ms/step - loss: 0.5270 - acc: 0.9776 - val_loss: 1.4132 - val_acc: 0.9653
ჩვენ სავარაუდოდ მივაღწევთ ტრენინგის უფრო მაღალ სიზუსტეს, რადგან ვიყენებთ უფრო მძლავრ ქსელს მეტი პარამეტრით, მაგრამ ვალიდაციის სიზუსტე არც ისე გაიზრდება.
თავისუფლად გახსენით ქსელის კიდევ რამდენიმე ფენა და ივარჯიშეთ მეტი, რათა ნახოთ, შეძლებთ თუ არა უფრო მაღალი სიზუსტის მიღწევას!
სხვა კომპიუტერული ხედვის მოდელები
VGG-16 არის ერთ-ერთი უმარტივესი კომპიუტერული ხედვის არქიტექტურა. Keras გთავაზობთ კიდევ ბევრ წინასწარ მომზადებულ ქსელს. მათ შორის ყველაზე ხშირად გამოყენებულია ResNet არქიტექტურები, შემუშავებული Microsoft-ის მიერ და Inception Google-ის მიერ. მაგალითად, მოდით გამოვიკვლიოთ უმარტივესი ResNet-50 მოდელის არქიტექტურა (ResNet არის სხვადასხვა სიღრმის მოდელების ოჯახი, შეგიძლიათ სცადოთ ResNet-152-ის ექსპერიმენტები, თუ გსურთ ნახოთ, როგორ გამოიყურება მართლაც ღრმა მოდელი):
იტვირთება…გამოტანა
Model: "resnet50"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_3 (InputLayer) [(None, 224, 224, 3) 0
__________________________________________________________________________________________________
conv1_pad (ZeroPadding2D) (None, 230, 230, 3) 0 input_3[0][0]
__________________________________________________________________________________________________
conv1_conv (Conv2D) (None, 112, 112, 64) 9472 conv1_pad[0][0]
__________________________________________________________________________________________________
conv1_bn (BatchNormalization) (None, 112, 112, 64) 256 conv1_conv[0][0]
__________________________________________________________________________________________________
conv1_relu (Activation) (None, 112, 112, 64) 0 conv1_bn[0][0]
__________________________________________________________________________________________________
pool1_pad (ZeroPadding2D) (None, 114, 114, 64) 0 conv1_relu[0][0]
__________________________________________________________________________________________________
pool1_pool (MaxPooling2D) (None, 56, 56, 64) 0 pool1_pad[0][0]
__________________________________________________________________________________________________
conv2_block1_1_conv (Conv2D) (None, 56, 56, 64) 4160 pool1_pool[0][0]
__________________________________________________________________________________________________
conv2_block1_1_bn (BatchNormali (None, 56, 56, 64) 256 conv2_block1_1_conv[0][0]
__________________________________________________________________________________________________
conv2_block1_1_relu (Activation (None, 56, 56, 64) 0 conv2_block1_1_bn[0][0]
__________________________________________________________________________________________________
conv2_block1_2_conv (Conv2D) (None, 56, 56, 64) 36928 conv2_block1_1_relu[0][0]
__________________________________________________________________________________________________
conv2_block1_2_bn (BatchNormali (None, 56, 56, 64) 256 conv2_block1_2_conv[0][0]
__________________________________________________________________________________________________
conv2_block1_2_relu (Activation (None, 56, 56, 64) 0 conv2_block1_2_bn[0][0]
__________________________________________________________________________________________________
conv2_block1_0_conv (Conv2D) (None, 56, 56, 256) 16640 pool1_pool[0][0]
__________________________________________________________________________________________________
conv2_block1_3_conv (Conv2D) (None, 56, 56, 256) 16640 conv2_block1_2_relu[0][0]
__________________________________________________________________________________________________
conv2_block1_0_bn (BatchNormali (None, 56, 56, 256) 1024 conv2_block1_0_conv[0][0]
__________________________________________________________________________________________________
conv2_block1_3_bn (BatchNormali (None, 56, 56, 256) 1024 conv2_block1_3_conv[0][0]
__________________________________________________________________________________________________
conv2_block1_add (Add) (None, 56, 56, 256) 0 conv2_block1_0_bn[0][0]
conv2_block1_3_bn[0][0]
__________________________________________________________________________________________________
conv2_block1_out (Acti
… (გამოტანა შემოკლებულია)როგორც ხედავთ, მოდელი შეიცავს იგივე ნაცნობ სამშენებლო ბლოკებს: კონვოლუციურ ფენებს, გაერთიანების ფენებს და საბოლოო მკვრივ კლასიფიკატორს. ჩვენ შეგვიძლია გამოვიყენოთ ეს მოდელი ზუსტად ისევე, როგორც ვიყენებდით VGG-16 გადაცემის სწავლისთვის. შეგიძლიათ სცადოთ ექსპერიმენტი ზემოთ მოცემულ კოდზე, გამოიყენოთ სხვადასხვა ResNet მოდელები, როგორც საბაზისო მოდელი და ნახოთ, როგორ იცვლება სიზუსტე.
სერიის ნორმალიზაცია
ეს ქსელი შეიცავს კიდევ ერთი ტიპის ფენას: Batch Normalization. სურათების ნორმალიზაციის იდეა არის მნიშვნელობების მიყვანა, რომლებიც მიედინება ნერვულ ქსელში სწორ ინტერვალამდე. როგორც წესი, ნერვული ქსელები საუკეთესოდ მუშაობს, როდესაც ყველა მნიშვნელობა არის [-1,1] ან [0,1] დიაპაზონში, და ეს არის მიზეზი იმისა, რომ ჩვენ შესაბამისად ვადიდებთ/ნორმალიზებთ შეყვანის მონაცემებს. თუმცა, ღრმა ქსელის ვარჯიშის დროს, შეიძლება მოხდეს, რომ მნიშვნელობები მნიშვნელოვნად გასცდეს ამ დიაპაზონს, რაც ვარჯიშს პრობლემურია. სერიის ნორმალიზაციის ფენა ითვლის საშუალო და სტანდარტულ გადახრას მიმდინარე მინი-სამეფოში ყველა მნიშვნელობისთვის და იყენებს მათ სიგნალის ნორმალიზებისთვის, სანამ ის გაივლის ნერვული ქსელის შრეში. ეს მნიშვნელოვნად აუმჯობესებს ღრმა ქსელების სტაბილურობას.
Takeaway
ტრანსფერის სწავლის გამოყენებით, ჩვენ შევძელით სწრაფად შეგვექმნა კლასიფიკატორი ჩვენი მორგებული ობიექტების კლასიფიკაციის ამოცანისთვის და მივაღწიეთ მაღალ სიზუსტეს. თუმცა, ეს მაგალითი არ იყო სრულიად სამართლიანი, რადგან ორიგინალური VGG-16 ქსელი წინასწარ იყო გაწვრთნილი კატებისა და ძაღლების ამოცნობისთვის და, ამრიგად, ჩვენ უბრალოდ ხელახლა ვიყენებდით ქსელში უკვე არსებული შაბლონების უმეტესობას. თქვენ შეგიძლიათ ველოდოთ უფრო დაბალ სიზუსტეს უფრო ეგზოტიკურ დომენის სპეციფიკურ ობიექტებზე, როგორიცაა მცენარის წარმოების ხაზის დეტალები ან ხის სხვადასხვა ფოთლებზე.
თქვენ ხედავთ, რომ უფრო რთული ამოცანები, რომლებსაც ჩვენ ახლა ვწყვეტთ, მოითხოვს უფრო მაღალ გამოთვლით სიმძლავრეს და ადვილად ვერ გადაიჭრება CPU-ზე. მომდევნო განყოფილებაში ჩვენ შევეცდებით გამოვიყენოთ უფრო მსუბუქი დანერგვა იმავე მოდელის მოსამზადებლად დაბალი გამოთვლითი რესურსების გამოყენებით, რაც იწვევს ოდნავ დაბალ სიზუსტეს.