კომპიუტერული ხედვა Jupyter ნოუთბუქი · TensorFlow

წინასწარ მომზადებული მოდელები და გადაცემის სწავლა

ეს არის პრაქტიკული ნოუთბუქი. წაიკითხე კოდი და შედეგები აქ, ან გაუშვი ინტერაქტიულად Google Colab-ში ან Jupyter-ში.

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-ზე. მომდევნო განყოფილებაში ჩვენ შევეცდებით გამოვიყენოთ უფრო მსუბუქი დანერგვა იმავე მოდელის მოსამზადებლად დაბალი გამოთვლითი რესურსების გამოყენებით, რაც იწვევს ოდნავ დაბალ სიზუსტეს.

ეს გაკვეთილი არის Microsoft “AI for Beginners” კურსის ქართული თარგმანი, გავრცელებული MIT ლიცენზიით.