Arduino Düşük Kaynaklı Makine Öğrenimi Modeli
Şimdiye kadar, bir Makine öğrenimi modelini bir mikro denetleyiciye taşımak için ana sınıflandırıcımız olarak SVM’yi (Destek Vektör Makinesi) kullandık: ancak son zamanlarda, benzer bir doğruluğu sağlayan, çok daha küçük olabilecek ilginç bir alternatifini sizlerle tanıştırmak istedik!
MicroML çerçevesi için ilgi odağımızı olarak svm’yi seçtik çünkü destek vektör kodlamasının düz C’ye taşındıktan sonra bellek kullanımı verimli olabileceğini biliyorduk.
Eski Arduino Nano (32 kb flaş, 2 kb RAM) gibi küçük mikrodenetleyicilere birçok gerçek dünya modelini (hareket tanımlama, uyandırma kelimesi algılama) uygulayabildik.
Uygulamamın uzlaşması, genellikle en sınırlayıcı faktör olan mümkün olduğunca fazla RAM tasarrufu sağlamak için flaş alanını (genellikle oldukça büyük olan) feda etmekti.
Bu uygulama nedeniyle, modeliniz boyut olarak büyürse (yüksek boyutlu veriler veya iyi ayrılamayan veriler), oluşturulan kod yine de RAM’e sığar, ancak kullanılabilir flaşı “taşar”.
Önceki yazımızın bir çiftinde, bir modeli bir MCU’ya yüklemeden önce model seçiminin gerekli bir adım olabileceği konusunda uyardık, çünkü önce uygun olup olmadığını kontrol etmelisiniz. Değilse, her biri kod boyutu artışına katkıda bulunduğundan, daha az destek vektörü almayı umarak başka bir modeli eğitmeniz gerekir.
Yeni bir algoritma: Uygunluk Vektörü Makineleri
Alaka Düzeyi Vektör Makinesi(Relevance Vector Machine) adı verilen yeni bir algoritma ile karşılaşmamız şans eseri oldu. Geçen yıla kadar Microsoft tarafından patentliydi, ancak şimdi kullanımı ücretsizdir.
Bayesan modeli uygulayarak aynı SVM formülasyonunu (ağırlaştırılmış bir çekirdek toplamı) kullanıyor.
Bu, ilk etapta SVM’de tamamen eksik olan sınıflandırma sonuçlarının olasılıklarını elde edebilmek için hizmet eder.
İkinci sırada, algoritma, aşağıdaki resimde görebileceğiniz gibi, destek vektörlerinin çok daha seyrek bir temsilini öğrenmeye çalışır.
Yüksek doğruluk elde edebilen oldukça hafif bir model
Sınıflandırıcıyı Eğitmek
Öyle görünüyor ki, patentli olduğu için bir uygulaması yoktu. Neyse ki, sklearn paradigmasını izleyen bir uygulama var. Bunu yüklemeniz gerekir:
pip install Cython pip install https://github.com/AmazaspShumik/sklearn_bayes/archive/master.zip
Arayüz her zamanki uyum tahmini olduğundan, bir sınıflandırıcıyı eğitmek çok kolaydır.
from sklearn.datasets import load_iris from skbayes.rvm_ard_models import RVC import warnings # I get tons of boring warnings during training, so turn it off warnings.filterwarnings("ignore") iris = load_iris() X = iris.data y = iris.target clf = RVC(kernel='rbf', gamma=0.001) clf.fit(X, y) y_predict = clf.predict(X)
SVC
Yapıcının parametreleri , sklearn’deki sınıflandırıcınınkilere benzer:
kernel
: lineer, poly, rbf’den biridegree
: eğerkernel=poly
gamma
: eğerkernel=poly
veyakernel=rbf
Daha fazla bilgi edinmek için sklearn’deki belgeleri okuyabilirsiniz.
C’ye Taşıma
Artık eğitilmiş bir sınıflandırıcımız olduğuna göre, onu seçtiğimiz mikrodenetleyicide derlenen düz C’ye taşımamız gerekiyor.
from micromlgen import port_rvm clf = get_rvm_classifier() c_code = port_rvm(clf) print(c_code)
Artık herhangi bir mikrodenetleyiciye yerleştirebileceğiniz düz C kodunuz var.
Performans Karşılaştırması
Bu yeni algoritmanın etkinliğini test etmek için, hem SVM’nin hem de RVM’nin boyutunu ve doğruluğunu yan yana karşılaştırarak önceki gönderilerimde oluşturduğumuz veri kümelerine uyguladık.
veri kümesi | DVM | RVM | Delta | |||
---|---|---|---|---|---|---|
Flaş(bayt) | Doğruluk(%) | Flaş(bayt) | Doğruluk(%) | Flaş | Doğruluk | |
RGB renkleri | 4584 | 100 | 3580 | 100 | -%22 | -0% |
İvmeölçer hareketleri(doğrusal çekirdek) | 36888 | 92 | 7056 | 85 | -%80 | -7% |
İvmeölçer hareketleri(gauss çekirdeği) | 45348 | 95 | 7766 | 95 | -82% | -0% |
Wifi konumlandırma | 4641 | 100 | 3534 | 100 | -24% | -0% |
Kelime ile uyandırma(doğrusal çekirdek) | 18098 | 86 | 3602 | 53 | -%80 | -%33 |
Kelim ile uyandırma(gauss çekirdeği) | 21788 | 90 | 4826 | 62 | -78 | -%28 |
Gördüğünüz gibi, sonuçlar oldukça şaşırtıcı:
- Doğrulukta herhangi bir kayıp olmadan (gauss çekirdeği ile ivmeölçer hareketleri) yüksek boyutlu veri setinde %82’ye kadar alan azaltma elde edebilirsiniz.
- Bazen iyi bir doğruluk elde edemeyebilirsiniz (uyandırma kelimesi veri setinde en fazla %62).
Her durumda olduğu gibi, kullanım durumunuz için iki algoritmadan hangisinin en iyi sonucu verdiğini test etmelisiniz, ancak izleyebileceğiniz birkaç yönerge var:
- En yüksek doğruluğa ihtiyacınız varsa, yeterli alanınız varsa muhtemelen SVM daha az daha iyi performans elde edebilir.
- Küçük alana veya en yüksek hıza ihtiyacınız varsa, RVM’nin tatmin edici bir doğruluk elde edip etmediğini test edin.
- Hem SVM hem de RVM karşılaştırılabilir performans elde ederse, RVM ile devam edin: çoğu durumda SVM’den çok daha hafiftir ve daha hızlı çalışır.
Boyut Karşılaştırması
Referans olarak, IRIS veri setini sınıflandırmak için bir SVM sınıflandırıcısı ve bir RVM sınıflandırıcısı için oluşturulan kodlar buradadır.
uint8_t predict_rvm(double *x) { double decision[3] = { 0 }; decision[0] = -0.6190847299428206; decision[1] = (compute_kernel(x, 6.3, 3.3, 6.0, 2.5) - 72.33233 ) * 0.228214 + -2.3609625; decision[2] = (compute_kernel(x, 7.7, 2.8, 6.7, 2.0) - 81.0089166 ) * -0.29006 + -3.360963; uint8_t idx = 0; double val = decision[0]; for (uint8_t i = 1; i < 3; i++) { if (decision[i] > val) { idx = i; val = decision[i]; } } return idx; } int predict_svm(double *x) { double kernels[10] = { 0 }; double decisions[3] = { 0 }; int votes[3] = { 0 }; kernels[0] = compute_kernel(x, 6.7 , 3.0 , 5.0 , 1.7 ); kernels[1] = compute_kernel(x, 6.0 , 2.7 , 5.1 , 1.6 ); kernels[2] = compute_kernel(x, 5.1 , 2.5 , 3.0 , 1.1 ); kernels[3] = compute_kernel(x, 6.0 , 3.0 , 4.8 , 1.8 ); kernels[4] = compute_kernel(x, 7.2 , 3.0 , 5.8 , 1.6 ); kernels[5] = compute_kernel(x, 4.9 , 2.5 , 4.5 , 1.7 ); kernels[6] = compute_kernel(x, 6.2 , 2.8 , 4.8 , 1.8 ); kernels[7] = compute_kernel(x, 6.0 , 2.2 , 5.0 , 1.5 ); kernels[8] = compute_kernel(x, 4.8 , 3.4 , 1.9 , 0.2 ); kernels[9] = compute_kernel(x, 5.1 , 3.3 , 1.7 , 0.5 ); decisions[0] = 20.276395502 + kernels[0] * 100.0 + kernels[1] * 100.0 + kernels[3] * -79.351629954 + kernels[4] * -49.298850195 + kernels[6] * -40.585178082 + kernels[7] * -30.764341769 ; decisions[1] = -0.903345464 + kernels[2] * 0.743494115 + kernels[9] * -0.743494115 ; decisions[2] = -1.507856504 + kernels[5] * 0.203695177 + kernels[8] * -0.160020702 + kernels[9] * -0.043674475 ; votes[decisions[0] > 0 ? 0 : 1] += 1; votes[decisions[1] > 0 ? 0 : 2] += 1; votes[decisions[2] > 0 ? 1 : 2] += 1; int classVal = -1; int classIdx = -1; for (int i = 0; i < 3; i++) { if (votes[i] > classVal) { classVal = votes[i]; classIdx = i; } } return classIdx; }
Gördüğünüz gibi, RVM aslında sadece 2 çekirdeği hesaplar ve 2 çarpma yapar. SVM ise 10 çekirdek hesaplar ve 13 çarpma işlemi yapar.
Bu yinelenen bir modeldir, dolayısıyla RVM çıkarım sürecinde çok daha hızlıdır.
Yorum yapma özelliği, forum tarafından gelen istek sebebiyle kapatılmıştır. Lütfen tartışmalar ve sorularınız için topluluk forumumuza katılın.