Haberler

Raspberry Pi SBC’de Hızlı(laşan) Makine Öğrenimi Çıkarımı – Dört optimizasyon tekniği

Bir süre önce yeni Raspberry Pi HD kamera modülü ile anlamsal segmentasyon üzerine bir video yaptım – segmentasyon görevi için MobileNet v1 backend SegNet-basic kullandım ve Raspberry Pi’de oldukça yavaş çalışıyordu, bu da yorumlarda insanlar tarafından fark edildi.

Raspberry Pi 4’ün Makine Öğrenimi görevleri için en iyi SBC olmadığını kabul etmem gerekiyordu, çünkü çıkarımı hızlandırmak için kullanılabilecek bir donanım hızlandırıcısı yok ve CPU’ya güvenmek zorunda. O zamandan beri reTerminal içindeki Raspberry Pi 4 Compute Module için uygulamalar üzerinde çalışıyorum – bunların bazıları yaş/cinsiyet tanıma, nesne tespiti, yüz sahteciliğine karşı koruma gibi Makine Öğrenimi demolarını içeriyordu.

Raspberry Pi 4 üzerinde gerçek zamanlı model çıkarımı gerçekleştirmeye çalışırken yardımcı olabilecek dört tekniğin listesi burada. Hazır mısınız? Hadi gidelim!

Daha küçük ağlar tasarlamak

Hedef yeterince basitse (100’den az sınıf için görüntü sınıflandırması veya 10’dan az sınıf için nesne tespiti veya benzeri), daha küçük bir ağ kabul edilebilir bir doğruluk elde edebilir ve çok hızlı çalışabilir. Örneğin, yalnızca bir nesne sınıfını (insan yüzleri) tespit etmek için eğitilmiş MobileNet v1 alpha 0.25 YOLOv2 ağı, herhangi bir ek optimizasyon olmadan 62.5 FPS elde ediyor.

Vanilla TensorFlow Lite FP32 çıkarımı:

Kuantizasyon

Kuantizasyon, NN ağ ağırlıklarının hassasiyetini azaltma sürecidir, genellikle FP32’den INT8’e.

Bu, boyutu 4 kat azaltır ve varsayılan TensorFlow Lite çekirdeklerini kullanarak gecikmeyi ~%60-80 oranında azaltır. TensorFlow’da iki tür kuantizasyon süreci vardır: eğitim sonrası kuantizasyon ve kuantizasyon farkındalığı eğitimi veya QAT. Eğitim sonrası kuantizasyon genellikle küçük bir doğruluk kaybı getirir, bu kaybı QAT – kuantizasyon farkındalığı eğitimi ile minimize edilebilir; bu, kuantizasyon düğümleri eklenmiş bir ağın ince ayar sürecidir.

Daha fazla okumak için TensorFlow Lite belgelerine ve aXeleRate’ın convert.py scriptine göz atın, bu benim gömülü cihazlar için çıkarımda yaygın görsel ağların eğitimini basitleştiren kişisel projemdir.

Vanilla TensorFlow Lite INT8 çıkarımı:

Optimize edilmiş çekirdekler kullanmak

Çıkarım hızını, belirli CPU talimat seti için optimize edilmiş işlem çekirdeklerine sahip çerçeveleri kullanarak artırabilirsiniz, örneğin ARM için NEON SIMD (Tek Talimat Çoklu Veri) talimatları. Bu tür ağlara örnekler arasında ARM NN ve XNNPACK bulunmaktadır.

Arm NN SDK, enerji verimli cihazlarda makine öğrenimi iş yüklerini etkinleştiren açık kaynak yazılım ve araçlar setidir.

Açıklama ve sağlanan benchmark’lar umut verici görünüyor, ancak en son Raspberry Pi OS üzerindeki kurulum prosedürü şu anda zorlayıcı – ARM NN’nin en son sürümünü kurmanın tek doğru yolu şu anda kaynaktan çapraz derleme yapmaktır. Debian Bullseye için mevcut ikili dosyalar var, ancak Raspberry Pi OS hala Debian Buster’da. Benchmark scriptlerimle yapılan çıkarım test sonuçları karışıktı, tek bir model için vanilla TensorFlow Lite’den daha kötü bir performans gösterdi, ancak çoklu model çıkarımında daha hızlı olduğu ortaya çıktı, muhtemelen daha verimli çoklu işlem kullanımından dolayı.

ARM NN FP32 çıkarımı:

XNNPACK, Android, iOS, Windows, Linux, macOS ortamlarında ARM, x86 ve WebAssembly mimarileri için sinir ağı çıkarımını hızlandırmak için bir kütüphanedir.

Accelerating TensorFlow Lite with XNNPACK Integration — The TensorFlow Blog

TensorFlow Lite’da bir delegate olarak entegre edilmiştir, bu Android derlemesi için varsayılan olarak etkinleştirilmiştir, ancak diğer ortamlar için manuel olarak etkinleştirilmesi gerekir – bu nedenle Raspberry Pi 4’te XNNPACK kullanmak istiyorsanız, TensorFlow Lite Yorumlayıcı paketini kaynaktan derlemeniz veya üçüncü taraf ikili dosyalardan birini indirmeniz gerekecek.

XNNPACK (hem FP32 hem de INT8 optimize edilmiş çekirdekler) ile TensorFlow Lite Yorumlayıcı pip paketini oluşturmak için aşağıdakileri yapın:

git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow 
nano tensorflow/lite/tools/pip_package/build_pip_package_with_bazel.sh

Sonra Bazel derleme seçeneklerini şu şekilde değiştirin:

# Python yorumlayıcı_wrapper'ı oluştur.
cd "${BUILD_DIR}"
case "${TENSORFLOW_TARGET}" in
  armhf)
    BAZEL_FLAGS="--config=elinux_armhf
      --copt=-march=armv7-a --copt=-mfpu=neon-vfpv4
      --copt=-O3 --copt=-fno-tree-pre --copt=-fpermissive
      --define tensorflow_mkldnn_contraction_kernel=0
      --define=raspberry_pi_with_neon=true"
    ;;
  aarch64)
    BAZEL_FLAGS="--config=elinux_aarch64
      --define tensorflow_mkldnn_contraction_kernel=0
      --copt=-O3"
    ;;
  native)
    BAZEL_FLAGS="--copt=-O3 --copt=-march=native"
    ;;
  *)
    BAZEL_FLAGS="--copt=-O3"
    ;;
esac

şu şekilde:

# Python yorumlayıcı_wrapper'ı oluştur.
cd "${BUILD_DIR}"
case "${TENSORFLOW_TARGET}" in
  armhf)
    BAZEL_FLAGS="--config=elinux_armhf
      --copt=-march=armv7-a --copt=-mfpu=neon-vfpv4
      --copt=-O3 --copt=-fno-tree-pre --copt=-fpermissive
      --define tensorflow_mkldnn_contraction_kernel=0
      --define=raspberry_pi_with_neon=true
      --define=tflite_pip_with_flex=true
      --define=tflite_with_xnnpack=true
      --define=xnn_enable_qs8=true"
    ;;
  aarch64)
    BAZEL_FLAGS="--config=elinux_aarch64
      --define tensorflow_mkldnn_contraction_kernel=0
      --define=tflite_pip_with_flex=true
      --define=tflite_with_xnnpack=true
      --define=xnn_enable_qs8=true
      --copt=-O3"
    ;;
  native)
    BAZEL_FLAGS="--copt=-O3 --copt=-march=native
      --define=tflite_pip_with_flex=true
      --define=tflite_with_xnnpack=true
      --define=xnn_enable_qs8=true"
    ;;
  *)
    BAZEL_FLAGS="--copt=-O3
      --define=tflite_pip_with_flex=true
      --define=tflite_with_xnnpack=true
      --define=xnn_enable_qs8=true"      
    ;;
esac

Ve ardından nihayet derleme işlemine başlamak için:

sudo CI_DOCKER_EXTRA_PARAMS="-e CI_BUILD_PYTHON=python3.7 -e CROSSTOOL_PYTHON_INCLUDE_PATH=/usr/include/python3.7" \
  tensorflow/tools/ci_build/ci_build.sh PI-PYTHON37 \
  tensorflow/lite/tools/pip_package/build_pip_package_with_bazel.sh aarch64

Bu çapraz derleme, bu nedenle derleme işlemi Linux x86 uyumlu bilgisayarınızda yapılmalıdır ve Raspbery Pi’de DEĞİL! Derleme biraz zaman alacaktır – bir hata ile karşılaşırsanız, daha önceki bir commit’e geçmeyi deneyin, çünkü TensorFlow’un ana dalındaki derlemelerin başarısız olması yaygındır.

Önceden oluşturulmuş pakete Seeed studio Wiki sayfası üzerinden erişebilirsiniz. Bu sayfa, reTerminal üzerinde TensorFlow Lite kullanımı hakkında bilgi vermektedir.

XNNPACK delegesi Tensorflow Lite FP32 çıkarımı:

Optimize edilmiş çekirdeklerin ana sorunu, farklı çerçevelerde farklı mimarilerin/NN operatörlerinin/precision türlerinin düzensiz desteklenmesidir. Örneğin, INT8 optimize edilmiş çekirdekler hem ARM NN hem de XNNPACK’ta geliştirilme aşamasındadır. XNNPACK’ta INT8 optimize edilmiş çekirdekler için destek çok yakın bir zamanda eklendi ve kullanılan operatörlere bağlı olarak yaklaşık %30’luk mütevazı bir performans artışı sağladığı görülmektedir.

Model çıkarım optimizasyon tekniklerini araştırırken, Tensorflow Github Pull Request‘inde dinamik olarak kuantize edilmiş modeller için optimize edilmiş çekirdekler eklenmesiyle ilgili başka bir umut verici bilgiye rastladım; videonun açıklamasında PR bağlantısını bulabilirsiniz.

Geliştirici, 3-4 kat gecikme iyileştirmesi iddia ediyor, ancak şu anda bu yalnızca çok belirli bir model seti ile sınırlıdır. Daha uygun kullanım sağlamak için bir PR geliştirilme aşamasındadır.

Pruning ve seyrek çıkarım

Pruning, doğru tahminlere katkıda bulunmayan ağırlıkları bulmak ve bunları kaldırmak için eğitilmiş sinir ağını ince ayar yapma sürecidir. Pruning, “ölü” ağırlıkları sıfıra ayarlayarak modelin boyutunu sıkıştırmak için çok yardımcıdır, ancak gecikmeyi azaltmak için kullanmak daha karmaşıktır, çünkü bu, bağlantıların kendilerini kaldırmayı gerektirir ve bu da önemli bir doğruluk kaybına yol açabilir.

Neural Network Pruning Research Review 2020 | by Prabhu Prakash Kagitha |  Heartbeat

Tensorflow Model Optimization araç setini kullanarak deneysel olarak, doğruluk üzerinde önemsiz bir etki ile %80’e kadar seyrekliğe ulaşmak mümkün olmuştur. Google AI blog makalesini buradan kontrol edin ve Tensorflow model optimizasyon araç seti ile pruning hakkında bir kılavuz burada bulunmaktadır.

Özetlemek gerekirse, bir kartın NN çıkarımını hızlandırmak için özel bir donanıma sahip olmaması, ML için işe yaramaz olduğu anlamına gelmez – kabul edilebilir çıkarım hızlarına ulaşmayı sağlayan bazı optimizasyon seçenekleri vardır. Ancak, optimize edilmiş çekirdekler gibi bu tekniklerin bazılarını uygulamak biraz karmaşık olabilir ve model mimarisinde bazı ayarlamalar ve (muhtemelen) çıkarım paketlerini kaynak kodundan derlemeyi gerektirebilir, çünkü birçok optimizasyon şu anda geliştirme aşamasının en önünde yer almaktadır.

Oh, ve bunu yaparken, Raspberry Pi 4 üzerinde optimize edilmiş çıkarım çalıştırırken termal kısıtlamalardan kaçındığınızdan emin olun – kendinize bu güzel soğutma kulelerinden birini edinin ve Pi’nizi ateşe vermeyin.

Leave a Reply

Your email address will not be published. Required fields are marked *