TPU'larda Keras ve modern dönüşümler

1. Genel Bakış

Bu laboratuvarda Keras ve Tensorflow 2 ile kendi konvolüsyonlu nöral ağlarınızı sıfırdan oluşturmayı, eğitmeyi ve ayarlamayı öğreneceksiniz. Bu işlem artık TPU'ların gücüyle dakikalar içinde yapılabiliyor. Ayrıca, çok basit transfer öğrenmeden Squeezenet gibi modern konvolüsyon mimarilerine kadar çeşitli yaklaşımları da keşfedeceksiniz. Bu laboratuvar, nöral ağlar hakkında teorik açıklamalar içerir ve derin öğrenme hakkında bilgi edinen geliştiriciler için iyi bir başlangıç noktasıdır.

Derin öğrenme makalelerini okumak zor ve kafa karıştırıcı olabilir. Modern evrişimli nöral ağ mimarilerine uygulamalı bir göz atalım.

ca8cc21f6838eccc.png

Neler öğreneceksiniz?

  • Özel modellerinizi daha hızlı oluşturmak için Keras ve Tensor İşleme Birimleri'ni (TPU'lar) kullanma.
  • Eğitim verilerini verimli bir şekilde yüklemek üzere tf.data.Dataset API'yi ve TFRecord biçimini kullanmak için.
  • Kendi modellerinizi oluşturmak yerine transfer öğrenimi kullanarak hile yapmak 😈
  • Keras sıralı ve işlevsel model stillerini kullanmak için:
  • Softmax katmanı ve çapraz entropi kaybıyla kendi Keras sınıflandırıcınızı oluşturmak için.
  • İyi bir kıvrımlı katman seçimiyle modelinizde ince ayar yapmak için.
  • Modüller, küresel ortalama havuz vb. gibi modern dönüşüm ağı mimarisi fikirlerini keşfetmek için
  • Squeezenet mimarisini kullanarak basit ve modern bir dönüşüm ağı oluşturmak için.

Geri bildirim

Bu kod laboratuvarında bir yanlışlık görürseniz lütfen bize bildirin. Geri bildirim, GitHub sorunları [geri bildirim bağlantısı] üzerinden gönderilebilir.

2. Google Colaboratory hızlı başlangıç kılavuzu

Bu laboratuvarda Google Ortak Çalışması kullanılmaktadır ve sizin herhangi bir kurulum yapmanız gerekmez. Bu programı Chromebook'tan çalıştırabilirsiniz. Lütfen aşağıdaki dosyayı açın ve Colab not defterleri hakkında bilgi edinmek için hücreleri yürütün.

c3df49e90e5a654f.png Welcome to Colab.ipynb

TPU arka ucu seçme

8832c6208c99687d.png

Colab menüsünde, Çalışma zamanı > Çalışma zamanı türünü değiştir'i, ardından TPU'yu seçin. Bu kod laboratuvarında, donanım hızlandırmalı eğitim için desteklenen güçlü bir TPU (Tensor İşleme Birimi) kullanacaksınız. Çalışma zamanına bağlantı, ilk çalıştırma sırasında otomatik olarak kurulur veya sağ üst köşedeki "Bağlan" düğmesini kullanabilirsiniz.

Not defteri yürütme

76d05caa8b4db6da.png

Bir hücreyi tıklayıp Üst Karakter+Enter tuşlarını kullanarak hücreleri tek tek yürütün. Not defterinin tamamını Çalışma zamanı > Tümünü çalıştır'ı kullanarak da çalıştırabilirsiniz.

İçindekiler

429f106990037ec4.png

Tüm not defterlerinin bir içindekiler tablosu vardır. Soldaki siyah oku kullanarak açabilirsiniz.

Gizli hücreler

edc3dba45d26f12a.png

Bazı hücrelerde yalnızca başlık gösterilir. Bu, Colab'e özel bir not defteri özelliğidir. İçlerindeki kodu görmek için dosyaları çift tıklayabilirsiniz ancak bu kodlar genellikle çok ilgi çekici değildir. Genellikle destek veya görselleştirme işlevleridir. İçerideki işlevlerin tanımlanması için bu hücreleri çalıştırmanız gerekir.

Kimlik Doğrulama

cdd4b41413100543.png

Yetkili bir hesapla kimlik doğrulama yaptığınızda Colab'ın gizli Google Cloud Storage paketlerinize erişmesi mümkündür. Yukarıdaki kod snippet'i bir kimlik doğrulama işlemini tetikler.

3. [BİLGİ] Tensor İşleme Birimleri (TPU'lar) nedir?

Özet

f88cf6facfc70166.png

Keras'ta TPU'da model eğitme (ve TPU yoksa GPU veya CPU kullanma) kodu:

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

Bugün etkileşimli hızlarda (eğitim çalıştırması başına dakika) çiçek sınıflandırıcı oluşturmak ve optimize etmek için TPU'ları kullanacağız.

688858c21e3beff2.png

Neden TPU'ları kullanmalısınız?

Modern GPU'lar, programlanabilir "çekirdekler" etrafında düzenlenmiştir. Bu, 3D oluşturma, derin öğrenme, fiziksel simülasyonlar gibi çeşitli görevleri gerçekleştirmelerine olanak tanıyan çok esnek bir mimaridir. Öte yandan TPU'lar, bir klasik vektör işlemciyi özel bir matris çarpım birimiyle eşleştirir ve nöral ağlar gibi büyük matris çarpımlarının baskın olduğu tüm görevlerde üstün başarı elde eder.

8eb3e718b8e2ed08.png

Çizim: Bir matris çarpımı olarak yoğun bir nöral ağ katmanı ve aynı anda nöral ağ üzerinden işlenen sekiz görüntüden oluşan bir katman. Bir resmin tüm piksel değerlerinin ağırlıklı toplamını yaptığını doğrulamak için lütfen bir satır x sütun çarpım işlemini gerçekleştirin. Kıvrımlı katmanlar, biraz daha karmaşık olsa da matris çarpımları olarak da temsil edilebilir ( açıklama, 1. bölümdeki).

Donanım

MXU ve VPU

TPU v2 çekirdeği, matris çarpımları çalıştıran bir Matris Çarpma Biriminden (MXU) ve etkinleştirmeler, softmax vb. diğer tüm görevler için bir Vektör İşleme Birimi (VPU)ndan oluşur. VPU, float32 ve int32 hesaplamalarını yürütür. Öte yandan MXU, karma hassasiyetli 16-32 bit kayan nokta biçiminde çalışır.

7d68944718f76b18.png

Karma hassasiyetli kayan nokta ve bfloat16

MXU, bfloat16 girişleri ve float32 çıkışları kullanarak matris çarpmalarını hesaplar. Ara birikimler, float32 hassasiyetinde gerçekleştirilir.

19c5fc432840c714.png

Sinir ağı eğitimi genellikle daha düşük kayan nokta hassasiyetinden kaynaklanan gürültüye karşı dirençlidir. Gürültünün optimize edicinin yakınlaşmasına bile yardımcı olduğu durumlar vardır. 16 bit kayan nokta hassasiyeti, hesaplamaları hızlandırmak için geleneksel olarak kullanılmıştır ancak float16 ve float32 biçimlerinin aralıkları çok farklıdır. Hassasiyetin float32'den float16'ya düşürülmesi, genellikle fazla ve az akışlara yol açar. Çözümler mevcut olsa da float16'ın çalışması için genellikle ek çalışma gerekir.

Bu nedenle Google, TPU'larda bfloat16 biçimini kullanıma sundu. bfloat16, tam olarak float32 ile aynı üssün bitleri ve aralığına sahip, kesilmiş bir float32'dir. Buna ek olarak TPU'lar, matris çarpımlarını bfloat16 girişleriyle ancak float32 çıkışlarıyla karışık hassasiyetle hesaplıyordur, böylece daha düşük hassasiyetten faydalanmak için genellikle hiçbir kod değişikliği gerekmez.

Sistolik dizi

MXU, veri öğelerinin bir dizi donanım hesaplama birimi üzerinden aktığı "sistolik dizi" mimarisi kullanarak donanımda matris çarpma işlemlerini uygular. (Tıpta "sistolik", kalp kasılmalarını ve kan akışını ifade eder. Burada ise veri akışını ifade eder.)

Matris çarpımlarının temel öğesi, bir matristeki çizgi ile diğer matristeki bir sütun arasındaki nokta çarpımıdır (bu bölümün üst kısmındaki resme bakın). Y=X*W matris çarpımı için sonucun bir öğesi şu şekilde olur:

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

GPU'da bu nokta ürünü bir GPU "çekirdek" olarak programlanır ve ardından elde edilen matrisin her değerini aynı anda hesaplamaya çalışmak için paralel olarak mümkün olduğunca çok "çekirdek"te yürütülür. Elde edilen matris 128x128 büyükse, 128x128=16K "çekirdek" değerinin kullanılabilir olması genellikle mümkün değildir. En büyük GPU'lar yaklaşık 4.000 çekirdeğe sahiptir. Öte yandan TPU, MXU'daki işlem birimleri için minimum düzeyde donanım kullanır: Yalnızca bfloat16 x bfloat16 => float32 çarpım toplayıcılar, başka bir şey yoktur. Bu üniteler o kadar küçüktür ki bir TPU, 128x128 MXU'da 16.000 tane uygulayabilir ve bu matris çarpımını tek seferde işleyebilir.

f1b283fc45966717.gif

Çizim: MXU sistolik dizisi. Compute elemanları çarpma toplayıcılarıdır. Bir matrisin değerleri diziye (kırmızı noktalar) yüklenir. Diğer matrisin değerleri, diziden (gri noktalar) geçer. Dikey çizgiler, değerleri yukarı doğru yayar. Yatay çizgiler kısmi toplamları yayar. Veriler, diziden geçerken sağ taraftan çıkan matris çarpımının sonucunu elde ettiğinizi doğrulamak için kullanıcıya bir alıştırma olarak bırakılır.

Buna ek olarak nokta çarpımları, MXU cinsinden hesaplanırken ara toplamlar, bitişik hesap birimleri arasında geçiş yapar. Depolanmaları ve belleğe, hatta bir kayıt dosyasına/belgeden alınmalarına gerek yoktur. Sonuçta TPU sistolik dizi mimarisi önemli bir yoğunluk ve güç avantajına sahip olmanın yanı sıra matris çarpımlarını hesaplarken GPU'ya göre göz ardı edilemez bir hız avantajına sahiptir.

Cloud TPU

Google Cloud Platform'da bir "Cloud TPU v2" istediğinizde PCI'ye bağlı bir TPU kartı bulunan bir sanal makine (VM) alırsınız. TPU kartında dört adet çift çekirdekli TPU çipi bulunur. Her TPU çekirdeğinde bir VPU (Vektör İşleme Birimi) ve 128x128 MXU (MatriX çarpma Birimi) bulunur. Daha sonra bu "Cloud TPU" genellikle ağ üzerinden bunu isteyen sanal makineye bağlanır. Bu nedenle, resmin tamamı şu şekilde görünür:

dfce5522ed644ece.png

Çizim: Ağa bağlı "Cloud TPU" hızlandırıcıya sahip sanal makineniz. "Cloud TPU" da üzerinde dört çift çekirdekli TPU çipi bulunan PCI'ye bağlı TPU kartı bulunan bir sanal makineden oluşur.

TPU kapsülleri

Google'ın veri merkezlerinde TPU'lar, yüksek performanslı bir bilgi işlem (HPC) ara bağlantısına bağlıdır. Bu bağlantı, TPU'ların çok büyük bir hızlandırıcı gibi görünmesini sağlayabilir. Google bunlara kapsül adını verir ve en fazla 512 TPU v2 çekirdek veya 2048 TPU v3 çekirdeklerini kapsayabilir.

2ec1e0d341e7fc34.jpeg

Çizim: TPU v3 kapsülü. HPC ara bağlantısı üzerinden bağlanan TPU kartları ve rafları.

Eğitim sırasında, tümünü azaltma algoritması kullanılarak TPU çekirdekleri arasında gradyanlar değiştirilir (tümünü azaltma hakkında iyi bir açıklamayı burada bulabilirsiniz). Eğitilen model, büyük toplu boyutlarda eğitim alarak donanımdan yararlanabilir.

d97b9cc5d40fdb1d.gif

Çizim: Google TPU'nun 2D toroidal örgü HPC ağında tamamen azaltma algoritması kullanılarak eğitim sırasında gradyanların senkronizasyonu.

Yazılım

Büyük gruplar için eğitim

TPU'lar için ideal toplu boyut, TPU çekirdeği başına 128 veri öğesidir ancak donanım, TPU çekirdeği başına 8 veri öğesi ile bile iyi bir kullanım gösterebilir. Cloud TPU'da 8 çekirdek olduğunu unutmayın.

Bu kod laboratuvarında Keras API'yi kullanacağız. Keras'ta belirttiğiniz grup, TPU'nun tamamı için genel grup boyutudur. Gruplarınız otomatik olarak 8'e bölünecek ve TPU'nun 8 çekirdeği üzerinde çalıştırılacaktır.

da534407825f01e3.png

Ek performans ipuçları için TPU Performans Kılavuzu'na bakın. Çok büyük toplu reklam boyutları için bazı modellerde özel dikkat gösterilmesi gerekebilir. Daha fazla ayrıntı için LARSOptimizer bölümüne bakın.

Gelişmiş seçenekler: XLA

Tensorflow programları hesaplama grafiklerini tanımlar. TPU, Python kodunu doğrudan çalıştırmaz, Tensorflow programınız tarafından tanımlanan hesaplama grafiğini çalıştırır. Tüm bunların altında XLA (hızlandırılmış doğrusal cebir derleyici) adlı bir derleyici, hesaplama düğümlerinin Tensorflow grafiğini TPU makine koduna dönüştürür. Bu derleyici, kodunuzda ve bellek düzeninizde birçok gelişmiş optimizasyon da gerçekleştirir. Çalışma TPU'ya gönderilirken derleme otomatik olarak gerçekleşir. XLA'yı derleme zincirinize açıkça eklemeniz gerekmez.

edce61112cd57972.png

Çizim: TPU'da çalıştırmak için Tensorflow programınız tarafından tanımlanan hesaplama grafiği önce XLA (hızlandırılmış doğrusal Cebir derleyici) temsiline dönüştürülür, ardından XLA tarafından TPU makine koduna derlenir.

Keras'ta TPU'ları kullanma

TPU'lar, Tensorflow 2.1 itibarıyla Keras API aracılığıyla desteklenmektedir. Keras desteği, TPU'lar ve TPU kapsülleri üzerinde çalışır. TPU, GPU ve CPU'da çalışan bir örneği aşağıda bulabilirsiniz:

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

Bu kod snippet'inde:

  • TPUClusterResolver().connect(), ağdaki TPU'yu bulur. Çoğu Google Cloud sisteminde (AI Platform işleri, Colaboratory, Kubeflow, "ctpu up" yardımcı programıyla oluşturulan derin öğrenme sanal makineleri) parametre olmadan çalışır. Bu sistemler, TPU_NAME ortam değişkeni sayesinde TPU'larının nerede olduğunu bilir. TPU'yu manuel olarak oluşturursanız TPU_NAME ortam değişkenini, kullandığınız sanal makinede ayarlayın veya TPUClusterResolver'yi açık parametrelerle çağırın: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy, dağıtım ve "tüm azalt" gradyan senkronizasyon algoritmasını uygulayan kısımdır.
  • Strateji, bir kapsam aracılığıyla uygulanır. Model, strategy scope() içinde tanımlanmalıdır.
  • tpu_model.fit işlevi, TPU eğitimi girişi için bir tf.data.Dataset nesnesi bekler.

Genel TPU bağlantı noktası görevleri

  • Tensorflow modelinde veri yüklemenin birçok yolu olsa da TPU'lar için tf.data.Dataset API'nin kullanılması gerekir.
  • TPU'lar çok hızlıdır ve verileri beslemek, bunlarda çalışırken genellikle darboğaz haline gelir. TPU Performans Kılavuzu'nda, veri sorunlarını tespit etmek için kullanabileceğiniz araçlar ve diğer performans ipuçlarını bulabilirsiniz.
  • int8 veya int16 sayılar int32 olarak değerlendirilir. TPU'da 32 bitten az çalışan tam sayı donanımı yoktur.
  • Bazı Tensorflow işlemleri desteklenmez. Listeyi buradan inceleyebilirsiniz. Neyse ki bu sınırlama, yalnızca eğitim kodu (modelinizde ileri ve geri geçiş) için geçerlidir. CPU'da yürütüleceğinden, veri giriş ardışık düzeninizdeki tüm Tensorflow işlemlerini kullanmaya devam edebilirsiniz.
  • tf.py_func, TPU'da desteklenmez.

4. Verileri Yükleme

c0ecb860e4cad0a9.jpeg cc4781a7739c49ae.jpeg 81236b00f8bbf39e.jpeg 961e2228974076bb.jpeg 7517dc163bdffcd5.jpeg 96392df4767f566d.png

Çiçek resimlerinden oluşan bir veri kümesiyle çalışacağız. Amaç, bu bitkileri 5 çiçek türüne ayırmayı öğrenmek. Veri yükleme işlemi tf.data.Dataset API kullanılarak gerçekleştirilir. Öncelikle API'yi tanıyalım.

Uygulamalı

Lütfen aşağıdaki not defterini açın, hücreleri çalıştırın (Üst Karakter-ENTER) ve "İŞLEM GEREKİR" etiketini gördüğünüz her yerde talimatları uygulayın.

c3df49e90e5a654f.png Fun with tf.data.Dataset (playground).ipynb

Ek bilgiler

"flowers" veri kümesi hakkında

Veri kümesi 5 klasörde düzenlenmiştir. Her klasörde bir türden çiçekler bulunur. Klasörler ayçiçeği, papatya, karahindiba, lale ve gül olarak adlandırılmıştır. Veriler, Google Cloud Storage'da herkese açık bir pakette barındırılır. Alıntı:

gs://flowers-public/sunflowers/5139971615_434ff8ed8b_n.jpg
gs://flowers-public/daisy/8094774544_35465c1c64.jpg
gs://flowers-public/sunflowers/9309473873_9d62b9082e.jpg
gs://flowers-public/dandelion/19551343954_83bb52f310_m.jpg
gs://flowers-public/dandelion/14199664556_188b37e51e.jpg
gs://flowers-public/tulips/4290566894_c7f061583d_m.jpg
gs://flowers-public/roses/3065719996_c16ecd5551.jpg
gs://flowers-public/dandelion/8168031302_6e36f39d87.jpg
gs://flowers-public/sunflowers/9564240106_0577e919da_n.jpg
gs://flowers-public/daisy/14167543177_cd36b54ac6_n.jpg

Neden tf.data.Dataset?

Keras ve Tensorflow, tüm eğitim ve değerlendirme işlevlerinde veri kümelerini kabul eder. Bir veri kümesine veri yüklediğinizde API, nöral ağ eğitimi verileri için yararlı olabilecek tüm yaygın işlevleri sunar:

dataset = ... # load something (see below)
dataset = dataset.shuffle(1000) # shuffle the dataset with a buffer of 1000
dataset = dataset.cache() # cache the dataset in RAM or on disk
dataset = dataset.repeat() # repeat the dataset indefinitely
dataset = dataset.batch(128) # batch data elements together in batches of 128
AUTOTUNE = tf.data.AUTOTUNE
dataset = dataset.prefetch(AUTOTUNE) # prefetch next batch(es) while training

Performansla ilgili ipuçları ve veri kümesi en iyi uygulamalarını bu makalede bulabilirsiniz. Referans belgeleri burada bulabilirsiniz.

tf.data.Dataset ile ilgili temel bilgiler

Veriler genellikle birden fazla dosyada (burada resimler) gelir. Aşağıdakileri çağırarak dosya adlarından oluşan bir veri kümesi oluşturabilirsiniz:

filenames_dataset = tf.data.Dataset.list_files('gs://flowers-public/*/*.jpg')
# The parameter is a "glob" pattern that supports the * and ? wildcards.

Daha sonra her bir dosya adına bir işlev "eşlersiniz". Bu işlev genellikle dosyayı yükleyip kodu çözerek bellekteki gerçek verilere dönüştürür:

def decode_jpeg(filename):
  bits = tf.io.read_file(filename)
  image = tf.io.decode_jpeg(bits)
  return image

image_dataset = filenames_dataset.map(decode_jpeg)
# this is now a dataset of decoded images (uint8 RGB format)

Bir veri kümesini yinelemek için:

for data in my_dataset:
  print(data)

Tuple'ların veri kümeleri

Gözetimli öğrenmede eğitim veri kümesi genellikle eğitim verileri ve doğru yanıtlardan oluşur. Bu işleme izin vermek için kod çözme işlevi tup döndürebilir. Daha sonra, üzerinde iterasyon yaptığınızda tuple ve tuplelardan oluşan bir veri kümeniz olur. Döndürülen değerler, modeliniz tarafından kullanılmaya hazır Tensorflow tensörleridir. Ham değerleri görmek için bu işlevleri .numpy() ile çağırabilirsiniz:

def decode_jpeg_and_label(filename):
  bits = tf.read_file(filename)
  image = tf.io.decode_jpeg(bits)
  label = ... # extract flower name from folder name
  return image, label

image_dataset = filenames_dataset.map(decode_jpeg_and_label)
# this is now a dataset of (image, label) pairs 

for image, label in dataset:
  print(image.numpy().shape, label.numpy())

Sonuç: Resimleri tek tek yüklemek yavaştır.

Bu veri kümesini tekrarlarken saniyede 1-2 görüntü gibi bir şey yükleyebileceğinizi göreceksiniz. Bu çok yavaş! Eğitim için kullanacağımız donanım hızlandırıcılar bu hızı birkaç kat sürdürebilir. Bunu nasıl başaracağımızı görmek için sonraki bölüme geçin.

Çözüm

Çözüm not defterini burada bulabilirsiniz. Sorun yaşadığınızda bu özelliği kullanabilirsiniz.

c3df49e90e5a654f.png Fun with tf.data.Dataset (solution).ipynb

İşlediklerimiz

  • 🤔 tf.data.Dataset.list_files
  • 🤔 tf.data.Dataset.map
  • 🤔 Tuple'ların veri kümeleri
  • 😀 Veri kümelerinde iterasyon

Lütfen bu kontrol listesini gözden geçirin.

5. Verileri hızlıca yükleme

Bu laboratuvarda kullanacağımız Tensor İşleme Birimi (TPU) donanım hızlandırıcıları çok hızlıdır. İşin zor kısmı, genellikle onları meşgul edecek kadar hızlı şekilde verileri beslemektir. Google Cloud Storage (GCS), çok yüksek işleme hızını sürdürebilir ancak tüm bulut depolama sistemlerinde olduğu gibi, bağlantı başlatmak için bazı ağlar arasında bağlantı kurmanız gerekir. Bu nedenle, verilerimizin binlerce ayrı dosya halinde depolanması ideal değildir. Bunları daha az sayıda dosya halinde gruplandıracağız ve paralel olarak birden çok dosyadan okuma yapmak için tf.data.Dataset'in gücünü kullanacağız.

Okuma

Resim dosyalarını yükleyen, ortak bir boyuta yeniden boyutlandıran ve ardından 16 TFRecord dosyasında depolayan kod aşağıdaki not defterindedir. Lütfen hızlıca okuyun. Codelab'in geri kalanı için TFRecord biçimindeki veriler doğru şekilde sağlanacağından bu işlemin yürütülmesi gerekmez.

c3df49e90e5a654f.png Flower pictures to TFRecords.ipynb

Optimum GCS işleme hızı için ideal veri düzeni

TFRecord dosya biçimi

Tensorflow'un veri depolamak için tercih ettiği dosya biçimi, protobuf tabanlı TFRecord biçimidir. Diğer serileştirme biçimleri de çalışır ancak aşağıdakileri yazarak TFRecord dosyalarından doğrudan veri kümesi yükleyebilirsiniz:

filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames)
dataset = dataset.map(...) # do the TFRecord decoding here - see below

En iyi performans için aşağıdaki daha karmaşık kodu kullanarak birden çok TFRecord dosyasını aynı anda okumanız önerilir. Bu kod paralel olarak N dosyadan okur ve veri sırasını dikkate alarak okuma hızını dikkate alır.

AUTOTUNE = tf.data.AUTOTUNE
ignore_order = tf.data.Options()
ignore_order.experimental_deterministic = False

filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTOTUNE)
dataset = dataset.with_options(ignore_order)
dataset = dataset.map(...) # do the TFRecord decoding here - see below

TFRecord hakkında yardımcı kısa bilgiler

TFRecord'larda üç tür veri depolanabilir: bayt dizeleri (bayt listesi), 64 bit tamsayılar ve 32 bit kayan değerler. Her zaman liste olarak depolanırlar. Tek bir veri öğesi, 1 boyutunda bir liste olur. Verileri TFRecord'larda depolamak için aşağıdaki yardımcı işlevleri kullanabilirsiniz.

bayt dizeleri yazma

# warning, the input is a list of byte strings, which are themselves lists of bytes
def _bytestring_feature(list_of_bytestrings):
  return tf.train.Feature(bytes_list=tf.train.BytesList(value=list_of_bytestrings))

tam sayılar yazma

def _int_feature(list_of_ints): # int64
  return tf.train.Feature(int64_list=tf.train.Int64List(value=list_of_ints))

yazılar yüzüyor

def _float_feature(list_of_floats): # float32
  return tf.train.Feature(float_list=tf.train.FloatList(value=list_of_floats))

yukarıdaki yardımcıları kullanarak bir TFRecord yazarak

# input data in my_img_bytes, my_class, my_height, my_width, my_floats
with tf.python_io.TFRecordWriter(filename) as out_file:
  feature = {
    "image": _bytestring_feature([my_img_bytes]), # one image in the list
    "class": _int_feature([my_class]),            # one class in the list
    "size": _int_feature([my_height, my_width]),  # fixed length (2) list of ints
    "float_data": _float_feature(my_floats)       # variable length  list of floats
  }
  tf_record = tf.train.Example(features=tf.train.Features(feature=feature))
  out_file.write(tf_record.SerializeToString())

TFRecord'lardaki verileri okumak için öncelikle depoladığınız kayıtların düzenini beyan etmeniz gerekir. Bildirimde, adlandırılmış herhangi bir alana sabit uzunlukta liste veya değişken uzunlukta liste olarak erişebilirsiniz:

TFRecords'tan okuma

def read_tfrecord(data):
  features = {
    # tf.string = byte string (not text string)
    "image": tf.io.FixedLenFeature([], tf.string), # shape [] means scalar, here, a single byte string
    "class": tf.io.FixedLenFeature([], tf.int64),  # shape [] means scalar, i.e. a single item
    "size": tf.io.FixedLenFeature([2], tf.int64),  # two integers
    "float_data": tf.io.VarLenFeature(tf.float32)  # a variable number of floats
  }

  # decode the TFRecord
  tf_record = tf.io.parse_single_example(data, features)

  # FixedLenFeature fields are now ready to use
  sz = tf_record['size']

  # Typical code for decoding compressed images
  image = tf.io.decode_jpeg(tf_record['image'], channels=3)

  # VarLenFeature fields require additional sparse.to_dense decoding
  float_data = tf.sparse.to_dense(tf_record['float_data'])

  return image, sz, float_data

# decoding a tf.data.TFRecordDataset
dataset = dataset.map(read_tfrecord)
# now a dataset of triplets (image, sz, float_data)

Yararlı kod snippet'leri:

Tek veri öğelerini okuma

tf.io.FixedLenFeature([], tf.string)   # for one byte string
tf.io.FixedLenFeature([], tf.int64)    # for one int
tf.io.FixedLenFeature([], tf.float32)  # for one float

sabit boyutlu öğe listelerini okuma

tf.io.FixedLenFeature([N], tf.string)   # list of N byte strings
tf.io.FixedLenFeature([N], tf.int64)    # list of N ints
tf.io.FixedLenFeature([N], tf.float32)  # list of N floats

değişken sayıda veri öğesini okuma

tf.io.VarLenFeature(tf.string)   # list of byte strings
tf.io.VarLenFeature(tf.int64)    # list of ints
tf.io.VarLenFeature(tf.float32)  # list of floats

VarLenFeature bir seyrek vektör döndürür ve TFRecord kodunun çözülmesinden sonra ek bir adım gerekir:

dense_data = tf.sparse.to_dense(tf_record['my_var_len_feature'])

TFRecords'ta isteğe bağlı alanlar da olabilir. Bir alanı okurken varsayılan bir değer belirtirseniz alan eksikse hata yerine varsayılan değer döndürülür.

tf.io.FixedLenFeature([], tf.int64, default_value=0) # this field is optional

Ele aldığımız konular

  • 🤔 GCS'den hızlı erişim için veri dosyalarını bölme
  • 🔗 TFRecord'lar nasıl yazılır? (Söz dizimini unuttunuz mu? Sorun değil, bu sayfayı yardımcı kısa bilgiler olarak yer işaretlerine ekleyin)
  • 🤔 TFRecordDataset kullanarak TFRecords'tan veri kümesi yükleme

Lütfen bir dakikanızı ayırarak bu yapılacaklar listesini zihninizde inceleyin.

6. [INFO] Nöral ağ sınıflandırıcı 101

Özet

Bir sonraki paragrafta yer alan kalın yazı tipindeki tüm terimleri zaten biliyorsanız bir sonraki alıştırmaya geçebilirsiniz. Derin öğrenmeye yeni başlıyorsanız hoş geldiniz. Lütfen okumaya devam edin.

Keras, bir dizi katman olarak oluşturulan modeller için Sequential API'yi sunmaktadır. Örneğin, üç yoğun katman kullanan bir resim sınıflandırıcı Keras'ta şu şekilde yazılabilir:

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

Yoğun nöral ağ

Bu, resimleri sınıflandırmak için kullanılan en basit nöral ağdır. Katmanlar halinde düzenlenmiş "nöronlardan" oluşur. İlk katman, giriş verilerini işler ve çıkışlarını diğer katmanlara besler. Her nöron önceki katmandaki tüm nöronlara bağlı olduğu için "yoğun" olarak adlandırılır.

c21bae6dade487bc.png

Bir resmi, tüm piksellerinin RGB değerlerini uzun bir vektörde birleştirerek ve bunu giriş olarak kullanarak böyle bir ağa besleyebilirsiniz. Bu, görüntü tanıma için en iyi teknik değildir, ancak daha sonra bunu iyileştireceğiz.

Nöronlar, aktivasyonlar, RELU

Bir "nöron", tüm girişlerinin ağırlıklı bir toplamını hesaplar, "önyargı" adı verilen bir değer ekler ve sonucu, "etkinleştirme işlevi" olarak adlandırılan bir yöntemle iletir. Ağırlıklar ve yanlılık başlangıçta bilinmiyor. Bunlar rastgele başlatılır ve nöral ağının bilinen çok sayıda veriyle eğitilmesiyle "öğrenilir".

644f4213a4ee70e5.png

En popüler etkinleştirme işlevi, Doğrulanmış Doğrusal Birim için RELU olarak adlandırılır. Yukarıdaki grafikte de görebileceğiniz gibi çok basit bir fonksiyondur.

Softmax etkinleştirme

Çiçekleri 5 kategoriye (gül, lale, karahindiba, papatya, ayçiçeği) ayırdığımız için yukarıdaki ağ 5 nöron katmanıyla sona eriyor. Ara katmanlardaki nöronlar, klasik RELU aktivasyon işlevi kullanılarak etkinleştirilir. Ancak son katmanda, bu çiçeğin gül, lale vb. olma olasılığını temsil eden 0 ile 1 arasında sayılar hesaplamak istiyoruz. Bunun için "softmax" adlı bir etkinleştirme işlevi kullanacağız.

Bir vektöre softmax (softmax) uygulanması, her bir elementin üssü alınıp ardından genellikle L1 normunun (mutlak değerlerin toplamı) kullanılmasıyla vektör normalleştirilir. Böylece, değerlerin toplamı 1'e eşit olur ve olasılık olarak yorumlanabilir.

ef0d98c0952c262d.png d51252f75894479e.gif

Çapraz entropi kaybı

Nöral ağımız giriş resimlerinden tahminler ürettiğine göre, bu tahminlerin ne kadar iyi olduğunu (yani ağın bize söylediği ile doğru cevaplar arasındaki mesafeyi, genellikle "etiketler" olarak adlandırılır) ölçmemiz gerekir. Veri kümesindeki tüm resimler için doğru etiketlere sahip olduğumuzu unutmayın.

Herhangi bir mesafe işe yarar, ancak sınıflandırma sorunları için "entropiler arası mesafe" en etkilidir. Bunu hata veya "kayıp" işlevi olarak adlandıracağız:

7bdf8753d20617fb.png

Gradyan inişi

Sinir ağını "eğitmek", çapraz entropi kayıp işlevini en aza indirmek için ağırlıkları ve önyargıları ayarlamak amacıyla eğitim resimlerini ve etiketlerini kullanmak anlamına gelir. İşleyiş şekline bakalım.

Çapraz entropi, eğitim resminin ağırlıkları, önyargıları, pikselleri ve bilinen sınıfının bir işlevidir.

Tüm ağırlıklara ve tüm sapmalara göre çapraz entropinin kısmi türevlerini hesaplarsak, belirli bir görüntü, etiket ve ağırlıkların ve yanlılığın mevcut değeri için hesaplanan bir "gradyan" elde ederiz. Milyonlarca ağırlığa ve sapmaya sahip olabileceğimizi, bu nedenle gradyanı hesaplamanın çok fazla iş yükü olacağını unutmayın. Neyse ki Tensorflow bunu bizim için yapıyor. Gradyanların matematiksel özelliği "yukarı" işaret etmeleridir. Çapraz entropinin düşük olduğu yere gitmek istediğimizden ters yönde ilerliyoruz. Ağırlıkları ve önyargıları gradyanın bir kesri kadar güncelleriz. Daha sonra, bir eğitim döngüsünde sonraki eğitim görüntüsü ve etiketi gruplarını kullanarak aynı şeyi tekrar tekrar yaparız. Bunun, çapraz entropinin minimum düzeyde olduğu bir yere yaklaşacağını umuyoruz, ancak bu minimum değerin benzersiz olduğunu hiçbir şey garanti etmemektedir.

gradyan descent2.png

Mini toplanma ve ivme

Renk geçişinizi tek bir örnek resim üzerinde hesaplayıp ağırlıkları ve sapmaları hemen güncelleyebilirsiniz. Ancak, örneğin 128 resimden oluşan bir grup üzerinde bunu yaptığınızda, farklı örnek görüntülerin uyguladığı kısıtlamaları daha iyi temsil eden ve dolayısıyla çözüme daha hızlı yaklaşma olasılığı yüksek bir gradyan elde edilir. Mini grubun boyutu ayarlanabilir bir parametredir.

Bazen "olasılık gradyanı inişi" olarak adlandırılan bu tekniğin daha pratik bir faydası daha vardır: Gruplarla çalışmak daha büyük matrislerle çalışmak anlamına gelir ve bunların GPU'lar ile TPU'larda optimize edilmesi genellikle daha kolaydır.

Ancak yakınsaklık yine de biraz kaotik olabilir ve gradyan vektörü sıfır olsa bile durabilir. Bu, minimum değeri bulduğumuz anlamına mı geliyor? Her zaman değil Gradyan bileşeni minimum veya maksimum sıfır olabilir. Milyonlarca öğe içeren bir gradyan vektöründe, bunların tümü sıfır ise her sıfırın minimuma ve hiçbirinin maksimum noktaya karşılık gelme olasılığı oldukça düşüktür. Çok boyutlu bir alanda eyer noktaları oldukça yaygındır ve bunlarda durmak istemeyiz.

52e824fe4716c4a0.png

Görsel: eyer noktası. Gradyan 0'dır, ancak tüm yönlerde minimum değer değildir. (Resim ilişkilendirmesi Wikimedia: By Nicoguaro - Own work, CC BY 3.0)

Çözüm, optimizasyon algoritmasına bir hız eklemektir. Böylece, algoritma durmadan bağlı noktaların ötesine geçebilir.

Sözlük

toplu veya mini toplu: Eğitim, her zaman eğitim verisi ve etiket grupları üzerinde gerçekleştirilir. Bu, algoritmanın yakınlaşmasına yardımcı olur. "Toplu" boyutu, genellikle veri tenörlerinin ilk boyutudur. Örneğin, [100, 192, 192, 3] şeklindeki bir tensör, piksel başına üç değer (RGB) içeren 192x192 piksellik 100 resim içerir.

çapraz entropi kaybı: Sınıflandırıcılarda genellikle kullanılan özel bir kayıp işlevi.

Yoğun katman: Her nöronun önceki katmandaki tüm nöronlara bağlı olduğu bir nöron katmanı.

özellikler: Bir nöral ağın girişlerine bazen "özellikler" denir. İyi tahminler elde etmek için veri kümesinin hangi bölümlerinin (veya parça kombinasyonlarının) nöral ağa besleneceğini bulma sanatına "özellik mühendisliği" denir.

labels: Gözetimli sınıflandırma problemindeki "sınıflar" veya doğru yanıtlar için kullanılan başka bir ad

Öğrenme hızı: Ağırlıkların ve önyargıların eğitim döngüsünün her iterasyonunda güncellendiği gradyanın kesri.

logits: Aktivasyon işlevi uygulanmadan önce bir nöron katmanının çıktılarına "logit" adı verilir. Bu terim, daha önce en popüler aktivasyon fonksiyonu olan "sigmoid işlevi" olarak da bilinen "mantıksal fonksiyon"dan gelir. "Mantıksal işlevden önceki nöron çıkışları" ifadesi "mantıksallar" olarak kısaltıldı.

loss: nöral ağ çıkışlarını doğru yanıtlarla karşılaştıran hata işlevi

nöron: Girişlerinin ağırlıklı toplamını hesaplar, bir ağırlık ekler ve sonucu bir aktivasyon işlevi aracılığıyla iletir.

tek sıcak kodlama: 5 üzerinden 3. sınıf, 5 öğeden oluşan bir vektör olarak kodlanır. 3'üncü olan (1) hariç tüm sıfırlar kullanılır.

relu: Düzeltilmiş doğrusal birim. Nöronlar için popüler bir aktivasyon fonksiyonu.

sigmoid: Eskiden popüler olan ve özel durumlarda hâlâ yararlı olan başka bir etkinleştirme işlevidir.

softmax: Bir vektör üzerinde etki eden, en büyük bileşen ile diğer bileşenler arasındaki farkı artıran ve vektörü, olasılıkların vektörü olarak yorumlanabilmesi için toplam 1 olacak şekilde normalleştiren özel bir aktivasyon fonksiyonu. Sınıflandırıcılarda son adım olarak kullanılır.

tensör: "Tensör", matrise benzer ancak rastgele sayıda boyuta sahiptir. 1 boyutlu bir tensör bir vektördür. 2 boyutlu tensör, bir matristir. 3, 4, 5 veya daha fazla boyutlu tensörleriniz de olabilir.

7. Öğrenimi Aktar

Görüntü sınıflandırma sorunu için yoğun katmanlar muhtemelen yeterli olmaz. Evrimsel katmanlar ve bunları çeşitli şekillerde düzenlemenin yolları hakkında bilgi edinmemiz gerekiyor.

Ama bir kısayol da kullanabiliriz. İndirilebilen, tamamen eğitilmiş evrişimli nöral ağlar vardır. Son katmanını (softmax sınıflandırma başı) kesip kendi katmanınızla değiştirebilirsiniz. Eğitilmiş tüm ağırlıklar ve önyargılar olduğu gibi kalır, yalnızca eklediğiniz softmax katmanını yeniden eğitirsiniz. Bu tekniğe transfer öğrenimi denir ve sinir ağının önceden eğitildiği veri kümesi sizinkine "yeterince yakın" olduğu sürece şaşırtıcı bir şekilde işe yarar.

Uygulamalı

Lütfen aşağıdaki not defterini açın, hücreleri yürütün (Üst Karakter-ENTER) ve "İŞ GEREKLİ" etiketini gördüğünüz her yerde talimatları uygulayın.

c3df49e90e5a654f.png Keras Flowers transfer learning (playground).ipynb

Ek bilgiler

Aktarımla öğrenme sayesinde, hem üst düzey araştırmacılar tarafından geliştirilen gelişmiş konvolüsyonlu nöral ağ mimarilerinden hem de görüntülerden oluşan devasa veri kümesi üzerinde ön eğitimden yararlanabilirsiniz. Bu örnekte, çok sayıda bitki ve dış mekan sahneleri içeren, çiçeklere yeterince yakın olan bir görüntü veritabanı olan ImageNet'te eğitimli bir ağdan bilgi aktaracağız.

b8fc1efd2001f072.png

Çizim: Daha önce eğitilmiş, kara kutu olarak eğitilmiş karmaşık bir konvolüsyonel nöral ağ kullanılarak yalnızca sınıflandırma başının yeniden eğitilmesi. Bu, aktarım öğrenmedir. Konvolüsyonel katmanlardan oluşan bu karmaşık düzenlemelerin nasıl işlediğini daha sonra göreceğiz. Şu an için bu başka birisiyle ilgili.

Keras'ta öğrenimi aktarın

Keras'ta tf.keras.applications.* koleksiyonundan önceden eğitilmiş bir model oluşturabilirsiniz. Örneğin, MobileNet V2, boyutu makul düzeyde kalan çok iyi bir konvolüsyon mimarisi. include_top=False'ü seçerek, son softmax katmanı olmadan önceden eğitilmiş modeli alırsınız. Böylece kendi katmanınızı ekleyebilirsiniz:

pretrained_model = tf.keras.applications.MobileNetV2(input_shape=[*IMAGE_SIZE, 3], include_top=False)
pretrained_model.trainable = False

model = tf.keras.Sequential([
    pretrained_model,
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(5, activation='softmax')
])

pretrained_model.trainable = False ayarına da dikkat edin. Yalnızca softmax katmanınızı eğitmeniz için önceden eğitilmiş modelin ağırlıklarını ve sapmalarını dondurur. Bu işlem genellikle nispeten az ağırlık içerir ve çok büyük bir veri kümesi gerektirmeden hızlı bir şekilde yapılabilir. Ancak çok fazla veriniz varsa transfer öğrenme, pretrained_model.trainable = True ile daha da iyi sonuç verebilir. Önceden eğitilmiş ağırlıklar, mükemmel başlangıç değerleri sağlar ve sorununuza daha iyi uyacak şekilde eğitimle ayarlanabilir.

Son olarak, yoğun softmax katmanınızın önüne Flatten() katmanının eklendiğine dikkat edin. Yoğun katmanlar, düz veri vektörlerinde çalışır ancak önceden eğitilmiş modelin bunu döndürüp döndürmediğini bilmiyoruz. Bu nedenle düzleştirmemiz gerekiyor. Bir sonraki bölümde kıvrımlı mimarileri ele alırken kıvrımlı katmanların döndürdüğü veri biçimini açıklayacağız.

Bu yaklaşımda doğruluk oranı% 75'e yaklaşır.

Çözüm

Çözüm not defterini burada bulabilirsiniz. Sorun yaşadığınızda bu özelliği kullanabilirsiniz.

c3df49e90e5a654f.png Keras Flowers transfer learning (solution).ipynb

İşlediklerimiz

  • 🤔 Keras'ta sınıflandırıcı yazma
  • 🤓 Son katman olarak yumuşak maksimum ve çapraz entropi kaybıyla yapılandırılmış
  • 😈 Transfer öğrenme
  • 🤔 İlk modelinizi eğitme
  • 🧐 Eğitim sırasındaki kaybını ve doğruluğunu takip etme

Lütfen bir dakikanızı ayırarak bu yapılacaklar listesini zihninizde inceleyin.

8. [INFO] Konvolüsyonlu nöral ağlar

Özet

Bir sonraki paragrafta yer alan kalın yazı tipindeki tüm terimleri zaten biliyorsanız bir sonraki alıştırmaya geçebilirsiniz. Devrimsel sinir ağlarını kullanmaya yeni başladıysanız lütfen okumaya devam edin.

convolutional.gif

Görsel: Her biri 4x4x3=48 öğrenilebilir ağırlıktan oluşan iki art arda filtreyle bir resmi filtreleme.

Basit bir konvolüsyonel nöral ağ Keras'ta şöyle görünür:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

688858c21e3beff2.png

Konvolüsyonel nöral ağlar 101

Bir "nöron", bir konvolüsyon ağının katmanında, yalnızca resmin küçük bir bölgesinde, hemen üzerindeki piksellerin ağırlıklı toplamını yapar. Normal yoğun katmandaki bir nöron gibi, bir önyargı ekler ve toplamı bir etkinleştirme işlevi aracılığıyla besler. Daha sonra bu işlem, aynı ağırlıklar kullanılarak resmin tamamında tekrarlanır. Yoğun katmanlarda her nöronun kendi ağırlıkları olduğunu unutmayın. Burada, ağırlıklardan oluşan tek bir "yama" görüntünün üzerinde her iki yönde de kayar ("dönüşüm"). Çıkış, resimde piksel sayısı kadar değere sahiptir (yine de kenarlarda bazı dolgu yapılması gerekir). 4x4x3=48 ağırlıktan oluşan bir filtre kullanan bir filtreleme işlemidir.

Ancak 48 ağırlık yeterli olmayacaktır. Daha fazla serbestlik derecesi eklemek için aynı işlemi yeni bir ağırlık grubuyla tekrarlarız. Bu işlem yeni bir filtre çıktıları kümesi oluşturur. Giriş resmindeki R, G, B kanallarına benzer şekilde buna bir çıkış "kanalı" diyelim.

Screen Shot 2016-07-29 at 16.02.37.png

İki (veya daha fazla) ağırlık kümesi, yeni bir boyut eklenerek tek bir tensör olarak toplanabilir. Bu şekilde, konvolüsyonlu bir katman için ağırlık tensörünün genel şeklini elde ederiz. Giriş ve çıkış kanallarının sayısı parametre olduğundan, konvolüsyonel katmanları yığmaya ve zincirlemeye başlayabiliriz.

d1b557707bcd1cb9.png

Görsel: Evrişimli nöral ağ, veri "küplerini" başka veri "küplerine" dönüştürür.

Sıralı konvolüsyon, maksimum havuz hızı

Evrimleri 2 veya 3 adımla yaparak elde edilen veri küpünü yatay boyutlarında da küçültebiliriz. Bunu iki şekilde yapabilirsiniz:

  • Aşamalı konvolüsyon: Yukarıdaki gibi ancak adımı 1'den büyük olan kayan bir filtre
  • Maks. havuz: MAX işlemini uygulayan bir kayan pencere (genellikle 2x2 yamalarda, her 2 pikselde bir tekrarlanır)

2b2d4263bb8470b.gif

Çizim: Hesaplama penceresinin 3 piksel kaydırılması daha az çıkış değeriyle sonuçlanır. Adımlamalı konvolüsyonlar veya maksimum havuzlama (2 adım kaydırarak 2x2 pencerede maksimum), veri kübünün yatay boyutlarda küçültülmesinin bir yoludur.

Konvolüsyonsal sınıflandırıcı

Son olarak, son veri kübünü düzleştirip yoğun, softmax etkinleştirilmiş bir katmandan besleyerek bir sınıflandırma başlığı ekleriz. Tipik bir konvolüsyonel sınıflandırıcı aşağıdaki gibi görünebilir:

4a61aaffb6cba3d1.png

Görsel: Devrimsel ve yumuşak maksimum katmanları kullanan bir resim sınıflandırıcı. 3x3 ve 1x1 filtreler kullanır. Maxpool katmanları, 2x2 veri noktası gruplarının maksimum değerini alır. Sınıflandırma başlığı, softmax etkinleştirmesine sahip yoğun bir katmanla uygulanmıştır.

Keras'ta

Yukarıda gösterilen konvolüsyon grubu, Keras'ta şu şekilde yazılabilir:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

9. Özel dönüşümünüz

Uygulamalı

Sıfırdan bir konvolüsyonel sinir ağı oluşturup eğitelim. TPU kullanmak, çok hızlı yineleme yapmamızı sağlar. Lütfen aşağıdaki not defterini açın, hücreleri yürütün (Üst Karakter-ENTER) ve "İŞ GEREKLİ" etiketini gördüğünüz her yerde talimatları uygulayın.

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

Amaç, aktarım öğrenme modelinin% 75'lik doğruluk oranını geçmektir. Elimizde yalnızca 3.670 görüntü varken milyonlarca görüntüden oluşan bir veri kümesiyle önceden eğitilmiş olması sayesinde bu model bir avantaja sahipti. En azından eşleştirebilir misiniz?

Ek bilgiler

Kaç katman, ne kadar büyük?

Katman boyutlarını seçmek, bilimden çok sanata benzer. Çok az ve çok fazla parametre (ağırlıklar ve önyargılar) arasında doğru dengeyi bulmanız gerekir. Çok az sayıda ağırlığa sahip olan sinir ağı, çiçek şekillerinin karmaşıklığını temsil edemez. Çok fazla resim kullanıldığında "aşırı uyum" oluşabilir. Bu durumda, model eğitim resimlerine odaklanır ve genelleme yapamaz. Çok fazla parametre olduğunda modelin eğitilmesi de yavaş olur. Keras'ta model.summary() işlevi, modelinizin yapısını ve parametre sayısını gösterir:

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 192, 192, 16)      448       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 192, 192, 30)      4350      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 96, 96, 30)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 96, 96, 60)        16260     
_________________________________________________________________
 ... 
_________________________________________________________________
global_average_pooling2d (Gl (None, 130)               0         
_________________________________________________________________
dense (Dense)                (None, 90)                11790     
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 455       
=================================================================
Total params: 300,033
Trainable params: 300,033
Non-trainable params: 0
_________________________________________________________________

Birkaç ipucu:

  • "Derin" nöral ağları etkili kılan birden çok katmana sahip olmaktır. Bu basit çiçek tanıma problemi için 5 ila 10 katman anlamlıdır.
  • Küçük filtreler kullanın. Genellikle 3x3 filtreler her yerde iyidir.
  • 1x1 filtreler de kullanılabilir ve ucuzdur. Gerçekte hiçbir şeyi "filtrelemezler". Ancak kanalların doğrusal kombinasyonlarını hesaplarlar. Bunları gerçek filtrelerle değiştirin. ("1x1 toplamaları" hakkında daha fazla bilgiyi sonraki bölümde bulabilirsiniz.)
  • Bu tür bir sınıflandırma problemlerinde, maksimum havuz katmanlarıyla (veya adım >1 olan kıvrımlarla) sıkça alt örnekleme yapın. Çiçeğin nerede olduğu önemli değildir, yalnızca gül veya karahindiba çiçeği olduğu için x ve y bilgilerini kaybetmek önemli değildir, daha küçük alanları filtrelemek ise daha ucuzdur.
  • Filtrelerin sayısı genellikle ağın sonundaki sınıf sayısına benzer olur (neden? aşağıdaki "küresel ortalama havuz" hilesine bakın). Yüzlerce sınıfa göre sınıflandırma yapıyorsanız filtre sayısını art arda katmanlarda kademeli olarak artırın. 5 sınıflı çiçek veri kümesi için yalnızca 5 filtreyle filtreleme yeterli olmaz. Çoğu katmanda aynı filtre sayısını (ör. 32) kullanabilir ve sonlara doğru azaltabilirsiniz.
  • Son yoğun katmanlar pahalıdır. Bu katmanlar, tüm konvolüsyon katmanlarının toplamından daha fazla ağırlığa sahip olabilir. Örneğin, 24x24x10 boyutunda son veri küpünden elde edilen çok makul bir çıkış olsa bile, 100 nöronlu bir katmanın maliyeti 24x24x10x100=576.000 ağırlık olacaktır. Dikkatli olun veya genel ortalama havuza bakın (aşağıya bakın).

Dünya genelinde ortalama havuz

Bir konvolüsyonel sinir ağının sonunda pahalı bir yoğun katman kullanmak yerine, gelen veri "küpünü" sınıflarınız kadar parçaya bölebilir, değerlerini ortalamasını alabilir ve bunları bir softmax aktivasyon işlevi üzerinden besleyebilirsiniz. Sınıflandırma başlığını oluşturmanın bu şekilde maliyeti 0 ağırlıktır. Keras'ta söz dizimi tf.keras.layers.GlobalAveragePooling2D(). şeklindedir

93240029f59df7c2.png

Çözüm

Çözüm not defterini burada bulabilirsiniz. Sorun yaşadığınızda bu özelliği kullanabilirsiniz.

c3df49e90e5a654f.png Keras_Flowers_TPU (solution).ipynb

İşlediklerimiz

  • 🤔 Evrimsel katmanlarla oynandı
  • 🤓 Maksimum havuz, adım sayısı, global ortalama havuz ve ...
  • 😀

Lütfen bir dakikanızı ayırarak bu yapılacaklar listesini zihninizde inceleyin.

10. [INFO] Modern evrimsel mimariler

Özet

7968830b57b708c0.png

Çizim: konvolüsyonlu "modül". Şu anda en iyi seçenek nedir? Maksimum havuz katmanının ardından 1x1 konvolüsyon katmanı mı yoksa farklı bir katman kombinasyonu mu? Tümünü deneyin, sonuçları birleştirin ve ağa karar vermesine izin verin. Sağda: Bu tür modülleri kullanan " inception" konvolüsyon mimarisi.

Keras'ta, veri akışının farklı alanlara yayılabileceği modeller oluşturmak için "işlevsel" model stilini kullanmanız gerekir. Örnek:

l = tf.keras.layers # syntax shortcut

y = l.Conv2D(filters=32, kernel_size=3, padding='same',
             activation='relu', input_shape=[192, 192, 3])(x) # x=input image

# module start: branch out
y1 = l.Conv2D(filters=32, kernel_size=1, padding='same', activation='relu')(y)
y3 = l.Conv2D(filters=32, kernel_size=3, padding='same', activation='relu')(y)
y = l.concatenate([y1, y3]) # output now has 64 channels
# module end: concatenation

# many more layers ...

# Create the model by specifying the input and output tensors.
# Keras layers track their connections automatically so that's all that's needed.
z = l.Dense(5, activation='softmax')(y)
model = tf.keras.Model(x, z)

688858c21e3beff2.png

Diğer ucuz numaralar

Küçük 3x3 filtreleri

40a7b15fb7dbe75c.png

Bu görselde, art arda uygulanan iki 3x3 filtrenin sonucu gösterilmektedir. Sonuca hangi veri noktalarının katkıda bulunduğunu geriye dönük olarak izlemeyi deneyin: Bu art arda gelen iki 3x3 filtre, 5x5 bölgenin bir kombinasyonunu hesaplar. Bu, bir 5x5 filtresinin hesapladığı kombinasyon değildir, ancak art arda gelen iki 3x3 filtresi tek bir 5x5 filtresinden daha ucuz olduğu için denemekte fayda vardır.

1x1 evrişimler ?

fd7cac16f8ecb423.png

Matematiksel terimlerle "1x1" bir toplama, sabit bir değerle çarpma işlemidir ve çok kullanışlı bir kavram değildir. Ancak, filtrenin, konvolüsyonel sinir ağlarında yalnızca 2D bir resme değil, bir veri kümesine uygulandığını unutmayın. Bu nedenle, "1x1" filtre, 1x1 veri sütununun ağırlıklı toplamını hesaplar (resme bakın) ve filtreyi veriler üzerinde kaydırdıkça giriş kanallarının doğrusal bir kombinasyonunu elde edersiniz. Bu aslında faydalı. Kanalları, ayrı ayrı filtreleme işlemlerinin (ör. "sivri kulaklar" için bir filtre, başka bir "bıyıklar" filtresi, üçüncüsü ise "yarık gözler" için) bir diğeri olarak düşünürseniz, "1x1" kıvrımlı bir katman, bu özelliklerin birden çok olası doğrusal kombinasyonunu hesaplar. Bu, bir "kedi" ararken yararlı olabilir. Üstelik 1x1 katmanlar daha az ağırlık kullanır.

11. Sıkıştırmalı

Bu fikirleri bir araya getirmenin basit bir yolu "Squeezenet" makalesinde gösterilmiştir. Yazarlar yalnızca 1x1 ve 3x3 konvolüsyonel katmanlar kullanan çok basit bir kıvrımlı modül tasarımını öne çıkarmıştır.

1730ac375379269b.png

Görsel: "Ateş modüllerine" dayalı squeezenet mimarisi. Gelen verileri dikey boyutta "sıkıştıran" bir 1x1 katmanını, ardından verilerin derinliğini tekrar "genişleten" iki paralel 1x1 ve 3x3 konvolusyon katmanını dönüşümlü olarak kullanırlar.

Uygulamalı

Önceki not defterinizde devam ederek squeezenet'ten ilham alan konvolüsyonel nöral ağ oluşturun. Model kodunu Keras "işlevsel stili" olarak değiştirmeniz gerekir.

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

Ek bilgi

Bu alıştırmada, squeezenet modülü için bir yardımcı işlev tanımlamak faydalı olacaktır:

def fire(x, squeeze, expand):
  y = l.Conv2D(filters=squeeze, kernel_size=1, padding='same', activation='relu')(x)
  y1 = l.Conv2D(filters=expand//2, kernel_size=1, padding='same', activation='relu')(y)
  y3 = l.Conv2D(filters=expand//2, kernel_size=3, padding='same', activation='relu')(y)
  return tf.keras.layers.concatenate([y1, y3])

# this is to make it behave similarly to other Keras layers
def fire_module(squeeze, expand):
  return lambda x: fire(x, squeeze, expand)

# usage:
x = l.Input(shape=[192, 192, 3])
y = fire_module(squeeze=24, expand=48)(x) # typically, squeeze is less than expand
y = fire_module(squeeze=32, expand=64)(y)
...
model = tf.keras.Model(x, y)

Bu seferki hedefimiz %80 doğruluk oranı elde etmektir.

Denenebilecekler

Tek bir kıvrımlı katmanla başlayın, ardından MaxPooling2D(pool_size=2) katmanla dönüşümlü olarak "fire_modules" ile devam edin. Ağda 2 ila 4 maksimum havuzlama katmanı ve maksimum havuzlama katmanları arasında 1, 2 veya 3 art arda ateşleme modülü deneyebilirsiniz.

Ateşleme modüllerinde "squeeze" parametresi genellikle "expand" parametresinden küçük olmalıdır. Bu parametreler aslında filtrelerin sayısıdır. Bu sayılar genellikle 8 ila 196 arasında değişebilir. Filtre sayısının ağda kademeli olarak arttığı mimarileri veya tüm ateşleme modüllerinin aynı sayıda filtreye sahip olduğu basit mimarileri deneyebilirsiniz.

Örnek:

x = tf.keras.layers.Input(shape=[*IMAGE_SIZE, 3]) # input is 192x192 pixels RGB

y = tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu')(x)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.GlobalAveragePooling2D()(y)
y = tf.keras.layers.Dense(5, activation='softmax')(y)

model = tf.keras.Model(x, y)

Bu noktada, denemelerinizin çok iyi gitmediğini ve %80 doğruluk hedefini yakalamanın zor olduğunu fark edebilirsiniz. Birkaç tane daha ucuz numaraya geçelim.

Toplu Normalleştirme

Toplu norm, yaşadığınız yakınlaşma sorunlarına yardımcı olur. Bir sonraki atölyede bu teknikle ilgili ayrıntılı açıklamalar yapılacak. Şimdilik lütfen fire_module işlevinizin içindeki katmanlar da dahil olmak üzere ağınızdaki her bir konvolüsyon katmanından sonra bu satırı ekleyerek kara kutu "sihirli" bir yardımcı olarak kullanın:

y = tf.keras.layers.BatchNormalization(momentum=0.9)(y)
# please adapt the input and output "y"s to whatever is appropriate in your context

Veri kümeniz küçük olduğundan momentum parametresinin varsayılan değeri olan 0,99'dan 0,9'a düşürülmesi gerekir. Şimdilik bu ayrıntıyı boşver.

Veri genişletme

Verileri, doygunluk değişikliklerinin sağa ve sola çevrilmesi gibi kolay dönüşümlerle zenginleştirerek birkaç yüzde puan daha elde edebilirsiniz:

4ed2958e09b487ca.png

ad795b70334e0d6b.png

Bu işlemi TensorFlow'da tf.data.Dataset API ile çok kolay bir şekilde yapabilirsiniz. Verileriniz için yeni bir dönüşüm işlevi tanımlayın:

def data_augment(image, label):
    image = tf.image.random_flip_left_right(image)
    image = tf.image.random_saturation(image, lower=0, upper=2)
    return image, label

Ardından, son veri dönüşümünüzde kullanın ("eğitim ve doğrulama veri kümeleri" hücresi, "get_batched_dataset" işlevi):

dataset = dataset.repeat() # existing line
# insert this
if augment_data:
  dataset = dataset.map(data_augment, num_parallel_calls=AUTO)
dataset = dataset.shuffle(2048) # existing line

Veri artırmayı isteğe bağlı hale getirmeyi ve yalnızca eğitim veri kümesinin artırıldığından emin olmak için gerekli kodu eklemeyi unutmayın. Doğrulama veri kümesini genişletmek anlamlı değildir.

35 dönemde %80 doğruluk artık ulaşılabilir durumdadır.

Çözüm

Çözüm not defterini burada bulabilirsiniz. Sorun yaşadığınızda bu özelliği kullanabilirsiniz.

c3df49e90e5a654f.png Keras_Flowers_TPU_squeezenet.ipynb

İşlediklerimiz

  • 🤔 Keras "işlevsel stil" modelleri
  • 🤓 Squeezenet mimarisi
  • 🤓 tf.data.datset ile veri genişletme

Lütfen bu kontrol listesini gözden geçirin.

12. Xception ince ayarlandı

Ayrılabilir kıvrımlar

Konvolüsyonel katmanları uygulamanın farklı bir yolu da son zamanlarda popülerlik kazanıyordu: derinlikten ayrılabilen kıvrımlar. Çok ağızlı bir konu olduğunu biliyorum ancak konsept son derece basit. Tensorflow ve Keras'ta tf.keras.layers.SeparableConv2D olarak uygulanır.

Ayrılabilir bir topoloji de resim üzerinde bir filtre çalıştırır ancak giriş resminin her kanalı için farklı bir ağırlık grubu kullanır. Ardından, filtrelenen kanalların ağırlıklı toplamıyla sonuçlanan bir dizi nokta çarpımı olan "1x1 konvolüsyon" işlemi uygulanır. Her seferinde yeni ağırlıklarla, kanalların gerektiği kadar ağırlıklı yeniden birleşimi hesaplanır.

615720b803bf8dda.gif

Çizim: ayrılabilir kıvrımlar. 1. Aşama: Her bir kanal için ayrı bir filtreyle evrişimler. 2. Aşama: Kanalların doğrusal rekombinasyonları. İstenilen çıkış kanalı sayısına ulaşılana kadar yeni bir ağırlık kümesiyle tekrarlanır. 1. aşama da her seferinde yeni ağırlıklarla tekrarlanabilir ancak pratikte bu nadiren görülür.

Ayrılabilir konvolüsyonlar en yeni konvolüsyonlu ağ mimarilerinde kullanılır: MobileNetV2, Xception, EfficientNet. Bu arada, daha önce transfer öğrenme için kullandığınız model MobileNetV2'dir.

Normal kıvrımlardan daha ucuzdur ve pratikte aynı derecede etkili oldukları tespit edilmiştir. Yukarıda gösterilen örnek için ağırlık sayısı:

Toplama katmanı: 4 x 4 x 3 x 5 = 240

Ayrılabilir konvolusyon katmanı: 4 x 4 x 3 + 3 x 5 = 48 + 15 = 63

Bu, okuyucunun her kıvrımlı katman ölçeği stilini benzer şekilde uygulamak için gereken çarpma sayısından daha fazla hesaplama yapması için bir alıştırma olarak bırakılır. Ayrılabilir kıvrımlar daha küçüktür ve hesaplama açısından çok daha etkilidir.

Uygulamalı

"Öğrenmeyi aktarma" oyun alanı not defterinden yeniden başlatın. Ancak bu kez önceden eğitilmiş model olarak Xception'ı seçin. Xception yalnızca ayrılabilir konvolusyonlar kullanır. Tüm ağırlıkları eğitilebilir durumda bırakın. Önceden eğitilmiş katmanları bu şekilde kullanmak yerine, verilerimiz üzerindeki önceden eğitilmiş ağırlıklara ince ayar yapacağız.

c3df49e90e5a654f.png Keras Flowers transfer learning (playground).ipynb

Hedef: Doğruluk > %95 (Hayır, cidden, mümkün!)

Bu son alıştırma olduğundan biraz daha fazla kod ve veri bilimi çalışması gerektiriyor.

İnce ayarlama hakkında ek bilgiler

Xception, tf.keras.application konumundaki önceden eğitilmiş standart modellerde kullanılabilir.* Bu sefer tüm ağırlıkları eğitilebilir durumda bırakmayı unutmayın.

pretrained_model = tf.keras.applications.Xception(input_shape=[*IMAGE_SIZE, 3],
                                                  include_top=False)
pretrained_model.trainable = True

Bir modelde ince ayarlar yaparken iyi sonuçlar almak için öğrenme hızına dikkat etmeniz ve kampanya gelişim dönemi olan bir öğrenme hızı programı kullanmanız gerekir. Aşağıdaki gibi:

9b1af213b2b36d47.png

Standart bir öğrenme hızıyla başlamak, modelin önceden eğitilmiş ağırlıklarını bozar. Başlatma işlemi, verileriniz model tarafından mantıklı bir şekilde değiştirilinceye kadar kademeli olarak korunur. Rampadan sonra, sabit veya katlanarak artan bir öğrenme hızıyla devam edebilirsiniz.

Keras'ta öğrenme hızı, her dönem için uygun öğrenme hızını hesaplayabileceğiniz bir geri çağırma işlevi aracılığıyla belirtilir. Keras, her dönem için doğru öğrenme hızını optimizatöre iletir.

def lr_fn(epoch):
  lr = ...
  return lr

lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_fn, verbose=True)

model.fit(..., callbacks=[lr_callback])

Çözüm

Çözüm not defterini burada bulabilirsiniz. Sorun yaşadığınızda bu özelliği kullanabilirsiniz.

c3df49e90e5a654f.png 07_Keras_Flowers_TPU_xception_fine_tuned_best.ipynb

İşlediklerimiz

  • 🤔 Derinlikten ayrılabilen konvolüsyon
  • 🤓 Öğrenme hızı programları
  • 😈 Önceden eğitilmiş bir modelde ince ayar yapma.

Lütfen bir dakikanızı ayırarak bu yapılacaklar listesini zihninizde inceleyin.

13. Tebrikler!

İlk modern konvolüsyonlu nöral ağınızı oluşturup% 90'ın üzerinde doğruluk oranıyla eğittiniz. TPU'lar sayesinde sadece dakikalar içinde ardışık eğitim çalışmalarını tekrarlarsınız.

Uygulamada TPU'lar

TPU'lar ve GPU'lar, Google Cloud'un Vertex AI'ında bulunur:

Son olarak, geri bildirimlere değer veriyoruz. Bu laboratuvarda bir eksiklik görürseniz veya bir şeylerin iyileştirilmesi gerektiğini düşünüyorsanız lütfen bize bildirin. Geri bildirimlerinizi, GitHub sorunları [feedback link] sayfasında bulabilirsiniz.

HR.png

Martin Görner ID small.jpg
Yazar: Martin Görner
Twitter: @martin_gorner