Gauss NB Arduino ile Kullanmak

Ayarlamak için minimum miktarda parametreye sahip en iyi performans gösteren sınıflandırıcılar mı arıyorsunuz? Başka yere bakmayın: Aradığınız şey Gauss Naive Bayes, ayrıca microML sayesinde artık onu mikrodenetleyicinize kolaylıkla taşıyabilirsiniz.

Gaussian Naive Bayes

Gaussian Naive Bayes

Naive Bayes sınıflandırıcıları, sınıflandırma için kullanılabilecek olasılık teorisine dayalı basit modellerdir.

Girdi değişkenleri arasındaki bağımsızlık varsayımından kaynaklanırlar. Bu varsayım, vakaların büyük çoğunluğunda doğru olmasa da, çoğu sınıflandırma görevinde genellikle çok iyi performans gösterirler, bu nedenle oldukça popülerdirler.

Gauss Naive Bayes başka bir (çoğunlukla yanlış) varsayımı birleştirir: değişkenlerin bir Gauss olasılık dağılımı gösterir.

Bu kadar çok yanlış varsayımın bu kadar iyi performanslara yol açmasının kabul etmek zor olsada, oldukça iyi çalışan bir sınıflandırıcı olması onu tercin nedenlerin biri yapmakta.

Bununla birlikte, bizim için önemli olan sklear’ın GaussianNB‘yi uygulamasıdır, bu yüzden böyle bir sınıflandırıcıyı kolayca eğitiriz.
En ilginç kısım, gaussianNB’nin tek bir parametre ile ayarlanabilmesidir: var_smoothing.

import sklearn.datasets as d
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import normalize
from sklearn.naive_bayes import GaussianNB

def pick_best(X_train, X_test, y_train, y_test):
    best = (None, 0)
    for var_smoothing in range(-7, 1):
        clf = GaussianNB(var_smoothing=pow(10, var_smoothing))
        clf.fit(X_train, y_train)
        y_pred = clf.predict(X_test)
        accuracy = (y_pred == y_test).sum()
        if accuracy > best[1]:
            best = (clf, accuracy)
    print('en iyi doğruluk', best[1] / len(y_test))
    return best[0]

iris = d.load_iris()
X = normalize(iris.data)
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
clf = pick_best(X_train, X_test, y_train, y_test)

Bu basit kod, farklı bir var_smoothingfaktöre sahip bir grup sınıflandırıcıyı eğitecek ve en iyi performans göstereni seçecektir.

EloquentML Uygulaması

Eğitilmiş sınıflandırıcınızı edindikten sonra, onu C’ye taşımak her zamanki gibi kolaydır:

from micromlgen import port

clf = pick_best()
print(port(clf))

port birçok sınıflandırıcıyı taşıyabilen kullanışlı bir yöntemdir: sizin için uygun dönüştürücüyü otomatik olarak algılayacaktır.

Dışa aktarılan kod neye benziyor?

#pragma once
namespace Eloquent {
    namespace ML {
        namespace Port {
            class GaussianNB {
                public:
                    /**
                    * Predict class for features vector
                    */
                    int predict(float *x) {
                        float votes[3] = { 0.0f };
                        float theta[4] = { 0 };
                        float sigma[4] = { 0 };
                        theta[0] = 0.801139789889; theta[1] = 0.54726920354; theta[2] = 0.234408773313; theta[3] = 0.039178084094;
                        sigma[0] = 0.000366881742; sigma[1] = 0.000907992556; sigma[2] = 0.000740960787; sigma[3] = 0.000274925514;
                        votes[0] = 0.333333333333 - gauss(x, theta, sigma);
                        theta[0] = 0.748563871324; theta[1] = 0.349390892644; theta[2] = 0.536186138345; theta[3] = 0.166747384117;
                        sigma[0] = 0.000529727082; sigma[1] = 0.000847956504; sigma[2] = 0.000690057342; sigma[3] = 0.000311828658;
                        votes[1] = 0.333333333333 - gauss(x, theta, sigma);
                        theta[0] = 0.704497203305; theta[1] = 0.318862439835; theta[2] = 0.593755956917; theta[3] = 0.217288784452;
                        sigma[0] = 0.000363782089; sigma[1] = 0.000813846722; sigma[2] = 0.000415475678; sigma[3] = 0.000758478249;
                        votes[2] = 0.333333333333 - gauss(x, theta, sigma);
                        // return argmax of votes
                        uint8_t classIdx = 0;
                        float maxVotes = votes[0];

                        for (uint8_t i = 1; i < 3; i++) {
                            if (votes[i] > maxVotes) {
                                classIdx = i;
                                maxVotes = votes[i];
                            }
                        }

                        return classIdx;
                    }

                protected:
                    /**
                    * Compute gaussian value
                    */
                    float gauss(float *x, float *theta, float *sigma) {
                        float gauss = 0.0f;

                        for (uint16_t i = 0; i < 4; i++) {
                            gauss += log(sigma[i]);
                            gauss += pow(x[i] - theta[i], 2) / sigma[i];
                        }

                        return gauss;
                    }
                };
            }
        }
    }

Kıyaslamalar

Arduino Nano 33 Ble Sense ile yapılan testlerin raporu:

SınıflandırıcıVeri kümesiFlaşVeri deposuUygulama vaktiKesinlik
GaussNBİris (150×4)82 kb42 Kb65 ms%97
LinearSVCİris (150×4)83 Kb42 Kb76 ms%99
GaussNBMeme kanseri (80×40)90 Kb42 Kb160 ms%77
LinearSVCMeme kanseri (80×40)112 Kb42 Kb378 ms%73
GaussNBWinw (100×13)85 Kb42 Kb130 ms%97
LinearSVCWine (100×13)89 Kb42 Kb125 ms%99

Doğruluğun doğrusal bir SVM ile eşit olduğunu ve bazı veri kümelerinde% 97’ye ulaştığını görebiliriz. Sadeliği, yürütme süresinin çizgilerin yarısı olduğu yüksek boyutlu veri kümeleriyle (meme kanseri) göz önüne çıkıyor: Bu kalıbın diğer gerçek dünya, orta ölçekli veri kümeleriyle tekrarlandığını görebiliriz.

Sorun Giderme

micromlgen kullanırken TemplateNotFound hatası alabilirsiniz, böyle bir durumda kütüphaneyi kaldırıp tekrar kurarak sorunu gidebilirsiniz:

pip uninstall micromlgen

Ardından Github’a gidin, paketi zip olarak indirin ve micromlgenklasörünü projenize çıkarın.