Kapsayan Felaket olaylar NaN ler bazen modeli eğitim süreçlerini sakatlayıcı bir TensorFlow programı sırasında oluşabilir. Bu tür olayların temel nedeni, özellikle önemsiz olmayan boyut ve karmaşıklık modelleri için genellikle belirsizdir. Bu tür model hatalarının hatalarını ayıklamayı kolaylaştırmak için, TensorBoard 2.3+ (TensorFlow 2.3+ ile birlikte), Debugger V2 adlı özel bir gösterge paneli sağlar. Burada, TensorFlow'da yazılmış bir sinir ağındaki NaN'leri içeren gerçek bir hata üzerinde çalışarak bu aracın nasıl kullanılacağını gösteriyoruz.
Bu öğreticide gösterilen teknikler, karmaşık programlardaki çalışma zamanı tensör şekillerinin incelenmesi gibi diğer hata ayıklama etkinlikleri için geçerlidir. Bu eğitici, nispeten yüksek oluşum sıklıkları nedeniyle NaN'lere odaklanmaktadır.
Hatayı gözlemleme
Hata ayıklayacağımız TF2 programının kaynak kodu GitHub'da bulunmaktadır . Örnek program ayrıca tensorflow pip paketine (versiyon 2.3+) paketlenmiştir ve şu şekilde çağrılabilir:
python -m tensorflow.python.debug.examples.v2.debug_mnist_v2
Bu TF2 programı çok katmanlı bir algı (MLP) oluşturur ve MNIST görüntülerini tanıyacak şekilde eğitir . Bu örnek, özel katman yapılarını, kayıp işlevini ve eğitim döngüsünü tanımlamak için TF2'nin düşük düzeyli API'sını kasıtlı olarak kullanır, çünkü NaN hatalarının olasılığı, daha esnek ama hataya eğilimli API'yi daha kolay kullandığımızdan daha yüksek olduğunda daha yüksektir. tf.keras gibi kullanımı kolay ancak biraz daha az esnek yüksek düzey API'ler.
Program her egzersiz adımından sonra bir test doğruluğu yazdırır. Konsolda, test doğruluğunun ilk adımdan sonra şansa yakın bir seviyede (~ 0.1) sıkıştığını görebiliriz. Model eğitiminin bu şekilde davranması kesinlikle beklenmiyor: adım arttıkça doğruluğun kademeli olarak 1.0'a (% 100) yaklaşmasını bekliyoruz.
Accuracy at step 0: 0.216 Accuracy at step 1: 0.098 Accuracy at step 2: 0.098 Accuracy at step 3: 0.098 ...
Eğitimli bir tahmin, bu sorunun NaN veya sonsuzluk gibi sayısal bir istikrarsızlıktan kaynaklandığıdır. Ancak, bunun gerçekten doğru olduğunu nasıl doğrularız ve TensorFlow işlemini (op) sayısal kararsızlığı oluşturmaktan nasıl sorumlu buluruz? Bu soruları cevaplamak için, hata ayıklayıcı programını Debugger V2 ile birlikte ele alalım.
Debugger V2 ile TensorFlow kodu gösterme
tf.debugging.experimental.enable_dump_debug_info() , Debugger V2'nin API giriş noktasıdır. Tek bir kod satırı içeren bir TF2 programı uygular. Örneğin, programın başlangıcına aşağıdaki satırı eklemek hata ayıklama bilgilerinin / tmp / tfdbg2_logdir adresindeki günlük dizinine (logdir) yazılmasına neden olur. Hata ayıklama bilgileri, TensorFlow çalışma zamanının çeşitli yönlerini kapsar. TF2'de , istekli yürütmenin tam geçmişini, @ tf.function tarafından gerçekleştirilen grafik oluşturma, grafiklerin yürütülmesi, yürütme olayları tarafından oluşturulan tensör değerlerini ve bu olayların kod konumunu (Python yığın izleri) içerir. . Hata ayıklama bilgilerinin zenginliği, kullanıcıların belirsiz hataları daraltmasını sağlar.
tf.debugging.experimental.enable_dump_debug_info( logdir="/tmp/tfdbg2_logdir", tensor_debug_mode="FULL_HEALTH", circular_buffer_size=-1)
tensor_debug_mode bağımsız değişkeni, Debugger V2'nin her istekli veya grafik içi
tensor_debug_mode hangi bilgileri
tensor_debug_mode kontrol eder. “FULL_HEALTH”, her bir kayan tip tensör hakkında aşağıdaki bilgileri yakalayan bir moddur (örneğin, yaygın olarak görülen float32 ve daha az yaygın bfloat16 dtype):
- d_type
- rütbe
- Toplam eleman sayısı
- Kayan tip elemanların aşağıdaki kategorilere ayrılması: negatif sonlu (
-), sıfır (
0), pozitif sonlu (
+), negatif sonsuz (
-∞), pozitif sonsuzluk (
+∞) ve
NaN.
“FULL_HEALTH” modu, NaN ve sonsuzluk içeren hataların ayıklanması için uygundur. Desteklenen diğer
tensor_debug_mode s için aşağıya bakın.
circular_buffer_size birçok tensör olaylar LogDir kaydedilir nasıl argümanı kontrol eder. Varsayılan olarak 1000'dir, bu da enstrümanlı TF2 programının sonundan önce sadece son 1000 tensörün diske kaydedilmesine neden olur. Bu varsayılan davranış, hata ayıklama verilerinin eksiksizliğinden ödün vererek hata ayıklayıcı yükünü azaltır. Tamlık tercih edilirse, bu durumda olduğu gibi, bağımsız değişkeni negatif bir değere ayarlayarak dairesel tamponu devre dışı bırakabiliriz (örn. Burada -1).
Debug_mnist_v2 örneği, komut satırı bayraklarını ileterek
enable_dump_debug_info() öğesini çağırır. Sorunlu TF2 programımızı bu hata ayıklama aracı etkinken tekrar çalıştırmak için şunları yapın:
python -m tensorflow.python.debug.examples.v2.debug_mnist_v2 \ --dump_dir /tmp/tfdbg2_logdir --dump_tensor_debug_mode FULL_HEALTH
TensorBoard'da Hata Ayıklayıcı V2 GUI'sini başlatma
Programı hata ayıklayıcı enstrümanları ile çalıştırmak / tmp / tfdbg2_logdir konumunda bir logdir oluşturur. TensorBoard'u başlatabilir ve logdir'e şu şekilde gösterebiliriz:
tensorboard --logdir /tmp/tfdbg2_logdir
Web tarayıcısında, TensorBoard'un http: // localhost: 6006 adresindeki sayfasına gidin. “Hata Ayıklayıcı V2” eklentisi, aşağıdakine benzer bir sayfa görüntüleyerek varsayılan olarak etkinleştirilmelidir:
NaN'lerin temel nedenini bulmak için Debugger V2 GUI'yi kullanma
TensorBoard'daki Debugger V2 GUI altı bölüm halinde düzenlenmiştir:
- Uyarılar : Bu sol üst kısım, enstrümanlı TensorFlow programındaki hata ayıklama verilerinde hata ayıklayıcı tarafından algılanan “uyarı” olaylarının bir listesini içerir. Her uyarı, dikkat gerektiren belirli bir anomaliyi gösterir. Bizim durumumuzda, bu bölüm belirgin bir pembe-kırmızı renk ile 499 NaN / ∞ olayını vurgulamaktadır. Bu, modelin iç tensör değerlerinde NaN'ler ve / veya sonsuzlukların varlığı nedeniyle öğrenemediği şüphesini doğrulamaktadır. Bu uyarıları birazdan inceleyeceğiz.
- Python Yürütme Zaman Çizelgesi : Bu, üst orta bölümün üst yarısıdır. Ops ve grafiklerin istekli yürütülmesinin tam tarihini sunar. Zaman çizelgesinin her kutusu op veya grafiğin adının ilk harfiyle işaretlenir (örneğin, “TensorSliceDataset” op için “T”, “model”
tf.functioniçin “m”). Bu zaman çizelgesinde gezinme düğmelerini ve zaman çizelgesinin üzerindeki kaydırma çubuğunu kullanarak gezinebiliriz.
- Grafik Yürütme : GUI'nin sağ üst köşesinde bulunan bu bölüm, hata ayıklama görevimizin merkezinde olacaktır. Grafiklerin içinde hesaplanan tüm kayan dtype tensörlerin geçmişini içerir (yani
@tf-functions ile derlenir).
- Grafik Yapısı (üst orta bölümün alt yarısı), Kaynak Kodu (sol alt bölüm) ve Yığın İzi (sağ alt bölüm) başlangıçta boştur. GUI ile etkileşime girdiğimizde içerikleri doldurulur. Bu üç bölüm de hata ayıklama görevimizde önemli roller oynayacaktır.
Kendimizi UI'nin organizasyonuna yönlendirdikten sonra, NaN'lerin neden ortaya çıktığını öğrenmek için aşağıdaki adımları atalım. İlk olarak, Uyarılar bölümünde NaN / ∞ uyarısını tıklatın. Bu, Grafik Yürütme bölümündeki 600 grafik tensörünün listesini otomatik olarak kaydırır ve bir
Log (doğal logaritma) op tarafından oluşturulan “Log: 0” adlı bir tensör olan # 88'e odaklanır. Göze çarpan pembe-kırmızı renk, 2D float32 tensörünün 1000 elementi arasında bir -∞ elemanını vurgular. Bu, TF2 programının çalışma zamanı geçmişinde herhangi bir NaN veya sonsuz içeren ilk tensördür: NaN veya ∞ içermeden önce hesaplanan tensörler; daha sonra hesaplanan pek çok (aslında çoğu) tensör NaN içerir. Bunu Grafik Yürütme listesinde yukarı ve aşağı kaydırarak onaylayabiliriz. Bu gözlem,
Log op'un bu TF2 programındaki sayısal kararsızlığın kaynağı olduğuna dair güçlü bir ipucu vermektedir.
Bu
Log op neden a -∞ verdi? Bu soruyu cevaplamak için op girişini incelemek gerekir. Tensörün adını (“Log: 0”) tıklamak, Grafik Yapısı bölümündeki TensorFlow grafiğinde
Log op çevresinin basit ama bilgilendirici bir görselleştirmesini getirir. Bilgi akışının yukarıdan aşağıya yönüne dikkat edin. Operasyonun kendisi ortadaki kalın harflerle gösterilmiştir. Hemen üstünde, bir Placeholder op'un
Log op için tek ve tek girişi sağladığını görebiliriz. Bu yürütme tarafından yer alan tensör, Grafik Yürütme listesinde yer tutucunun nerede üretildi? Sarı arka plan rengini görsel bir yardım olarak kullanarak,
logits:0 tensörünün
Log:0 tensörünün iki satır üstünde, yani satır 85'te olduğunu görebilirsiniz.
85. satırdaki “logits: 0” tensörünün sayısal dökümüne daha dikkatli bir bakış, tüketici
Log:0 neden bir -∞ ürettiğini gösterir: “logits: 0” 1000 elementi arasında bir elemanın değeri 0'dır. -∞, 0'ın doğal logaritmasının hesaplanmasının bir sonucudur! Bir şekilde Log op'nun sadece pozitif girdilere maruz kalmasını sağlayabilirsek, NaN / ∞'ın olmasını engelleyebiliriz. Bu, Yer Tutucu günlükleri tensörüne kırpma (örneğin, tf.clip_by_value () kullanılarak ) uygulanarak gerçekleştirilebilir.
Hatayı çözmeye yaklaşıyoruz, ancak henüz tamamlanmadı. Düzeltmeyi uygulamak için Python kaynak kodunda Log op ve onun Placeholder girdisinin nereden geldiğini bilmemiz gerekir. Hata ayıklayıcı V2, grafik işlemlerini ve yürütme olaylarını kaynaklarına izlemek için birinci sınıf destek sağlar. Grafik Yürütmelerinde
Log:0 tensörünü tıklattığımızda, Stack Trace (Yığın İzleme) bölümü, Log op'nun oluşturulmasının orijinal yığın iziyle dolduruldu. Yığın izlemesi biraz büyüktür, çünkü TensorFlow'un dahili kodundaki (örneğin gen_math_ops.py ve dumping_callback.py) birçok kareyi içerdiğinden, çoğu hata ayıklama görevi için güvenle yok sayabiliriz. İlgilendiğiniz çerçeve debug_mnist_v2.py'nin 216. satırıdır (yani, gerçekten hata ayıklamaya çalıştığımız Python dosyası). “Satır 204” tıklandığında, Kaynak Kodu bölümünde ilgili kod satırının bir görünümü görüntülenir.
Bu nihayet bizi logit girdisinden problemli Log op'u yaratan kaynak koduna getiriyor. Bu,
@tf.function ile dekore edilmiş ve dolayısıyla bir TensorFlow grafiğine dönüştürülen özel kategorik çapraz entropi kaybı fonksiyonumuzdur. Placeholder op “logits”, kayıp işlevinin ilk girdi bağımsız değişkenine karşılık gelir.
Log op, tf.math.log () API çağrısı ile oluşturulur.
Bu hataya ilişkin değer kırpma düzeltmesi şuna benzer:
diff = -(labels * tf.clip_by_value(tf.math.log(logits), 1e-6, 1.))
Bu TF2 programındaki sayısal kararsızlığı giderecek ve MLP'nin başarılı bir şekilde çalışmasına neden olacaktır. Sayısal dengesizliği düzeltmek için bir başka olası yaklaşım
tf.keras.losses.CategoricalCrossentropy kullanmaktır.
Bu, bir TF2 model hatasını gözlemlemekten, sayısal özetler de dahil olmak üzere enstrümanlı TF2 programının hevesli ve grafik yürütme geçmişine tam görünürlük sağlayan Debugger V2 aracı tarafından desteklenen, hatayı düzelten bir kod değişikliği bulmaya kadar olan yolculuğumuzu sonuçlandırıyor. tensör değerleri ve ops, tensörler ve orijinal kaynak kodları arasındaki ilişki.
Debugger V2'nin donanım uyumluluğu
Hata ayıklayıcı V2, CPU ve GPU dahil olmak üzere genel eğitim donanımını destekler. Tf.distributed.MirroredStrategy ile çoklu GPU eğitimi de desteklenmektedir. TPU desteği hala erken bir aşamada ve arama gerektiriyor
tf.config.set_soft_device_placement(True)
Debugger V2'nin API uyumluluğu
Hata ayıklayıcı V2, nispeten düşük bir TensorFlow yazılım yığını düzeyinde uygulanır ve bu nedenle tf.keras , tf.data ve TensorFlow'un düşük seviyelerinin üzerine inşa edilmiş diğer API'lerle uyumludur. Hata Ayıklayıcı V2, TF1 ile geriye dönük olarak uyumludur, ancak Eager Yürütme Zaman Çizelgesi, TF1 programları tarafından oluşturulan hata ayıklama günlük dizinleri için boş olacaktır.
API kullanım ipuçları
Bu hata ayıklama API'sı hakkında sık sorulan bir soru, TensorFlow kodunda birinin
enable_dump_debug_info() çağrısını eklemesi gerektiğidir. Tipik olarak API, TF2 programınızda, tercihen Python içe aktarma satırlarından sonra ve grafik oluşturma ve yürütme başlamadan önce mümkün olduğunca erken çağrılmalıdır. Bu, modelinizi ve eğitimini güçlendiren tüm operasyon ve grafiklerin tam kapsamını sağlayacaktır.
Şu anda desteklenen tensor_debug_modes şunlardır:
NO_TENSOR ,
CURT_HEALTH ,
CONCISE_HEALTH ,
FULL_HEALTH ve
SHAPE . Her bir tensörden çıkarılan bilgi miktarına ve hata ayıklanan programa yüklenen performansa göre değişir. Lütfen
enable_dump_debug_info() 'nun belgeleri]' nin args bölümüne bakın.
Performans yükü
Hata ayıklama API'si, enstrümanlı TensorFlow programına performans ek yükü sunar. Tepegöz
tensor_debug_mode , donanım tipi ve enstrümanlı TensorFlow programının doğasına göre değişir. Referans noktası olarak, GPU'da
NO_TENSOR modu, 64 numaralı parti altında bir Transformatör modelinin eğitimi sırasında% 15 ek yük ekler. Diğer tensor_debug_modes için ek yük yüzdesi daha yüksektir:
CURT_HEALTH ,
CONCISE_HEALTH ,
FULL_HEALTH ve
SHAPE için yaklaşık% 50 modları. CPU'larda, ek yük biraz daha düşüktür. TPU'larda ek yük şu anda daha yüksektir.
Diğer TensorFlow hata ayıklama API'leriyle ilişkisi
TensorFlow uygulamasının hata ayıklama için başka araçlar ve API'lar sunduğunu unutmayın. Bu tür API'lara, API dokümanları sayfasındaki
tf.debugging.* alanı altında göz atabilirsiniz. Bu API'lar arasında en sık kullanılan
tf.print() . Ne zaman Debugger V2 kullanılmalı ve bunun yerine
tf.print() ne zaman kullanılmalıdır?
tf.print() aşağıdaki durumlarda kullanışlıdır
- tam olarak hangi tansörleri basacağımızı biliyoruz,
- bu
tf.print()ifadelerini tam olarak nereye ekleyeceğimizi
tf.print(),
- bu tür tansörlerin sayısı çok fazla değildir.
Diğer durumlar için (örneğin, birçok tensör değerinin incelenmesi, TensorFlow'un dahili kodu tarafından oluşturulan tensör değerlerinin incelenmesi ve yukarıda gösterdiğimiz gibi sayısal kararsızlığın kaynağının araştırılması), Debugger V2 daha hızlı bir hata ayıklama yöntemi sağlar. Buna ek olarak, Debugger V2, istekli ve grafik tensörlerini denetlemek için birleşik bir yaklaşım sağlar. Ayrıca,
tf.print() özelliğinin ötesinde grafik yapısı ve kod konumları hakkında bilgi sağlar.
∞ ve NaN ile ilgili sorunları ayıklamak için kullanılabilecek başka bir API
tf.debugging.enable_check_numerics() .
enable_dump_debug_info() farklı olarak,
enable_check_numerics() hata ayıklama bilgilerini diske kaydetmez. Bunun yerine, sadece TensorFlow çalışma zamanı sırasında ∞ ve NaN'yi izler ve herhangi bir op bu tür sayısal sayısal değerler ürettiği anda kaynak kodu konumu ile hata yapar.
enable_dump_debug_info() karşılaştırıldığında daha düşük performans yükü vardır, ancak programın yürütme geçmişinin tam bir izini almaz ve Debugger V2 gibi bir grafik kullanıcı arabirimi ile birlikte gelmez.