Speichern Sie den Klassifikator in scikit-learn auf der Festplatte

191

Wie speichere ich einen trainierten Naive Bayes-Klassifikator auf der Festplatte und verwende ihn zur Vorhersage von Daten?

Ich habe das folgende Beispielprogramm von der scikit-learn-Website:

from sklearn import datasets
iris = datasets.load_iris()
from sklearn.naive_bayes import GaussianNB
gnb = GaussianNB()
y_pred = gnb.fit(iris.data, iris.target).predict(iris.data)
print "Number of mislabeled points : %d" % (iris.target != y_pred).sum()
Garak
quelle

Antworten:

201

Klassifikatoren sind nur Objekte, die wie alle anderen eingelegt und entsorgt werden können. So setzen Sie Ihr Beispiel fort:

import cPickle
# save the classifier
with open('my_dumped_classifier.pkl', 'wb') as fid:
    cPickle.dump(gnb, fid)    

# load it again
with open('my_dumped_classifier.pkl', 'rb') as fid:
    gnb_loaded = cPickle.load(fid)
mwv
quelle
1
Klappt wunderbar! Ich habe versucht, np.savez zu verwenden und es die ganze Zeit zurück zu laden, und das hat nie geholfen. Vielen Dank.
Kartos
7
Verwenden Sie in Python3 das Pickle-Modul, das genau so funktioniert.
MCSH
212

Sie können auch joblib.dump und joblib.load verwenden, die bei der Verarbeitung numerischer Arrays wesentlich effizienter sind als der Standard-Python-Pickler.

Joblib ist in scikit-learn enthalten:

>>> import joblib
>>> from sklearn.datasets import load_digits
>>> from sklearn.linear_model import SGDClassifier

>>> digits = load_digits()
>>> clf = SGDClassifier().fit(digits.data, digits.target)
>>> clf.score(digits.data, digits.target)  # evaluate training error
0.9526989426822482

>>> filename = '/tmp/digits_classifier.joblib.pkl'
>>> _ = joblib.dump(clf, filename, compress=9)

>>> clf2 = joblib.load(filename)
>>> clf2
SGDClassifier(alpha=0.0001, class_weight=None, epsilon=0.1, eta0=0.0,
       fit_intercept=True, learning_rate='optimal', loss='hinge', n_iter=5,
       n_jobs=1, penalty='l2', power_t=0.5, rho=0.85, seed=0,
       shuffle=False, verbose=0, warm_start=False)
>>> clf2.score(digits.data, digits.target)
0.9526989426822482

Bearbeiten: In Python 3.8+ ist es jetzt möglich, Pickle zum effizienten Beizen von Objekten mit großen numerischen Arrays als Attribute zu verwenden, wenn Sie das Pickle-Protokoll 5 verwenden (dies ist nicht die Standardeinstellung).

Ogrisel
quelle
1
Nach meinem Verständnis funktioniert Pipelining jedoch, wenn es Teil eines einzelnen Arbeitsablaufs ist. Wenn ich das Modell erstellen möchte, speichern Sie es auf der Festplatte und stoppen Sie die Ausführung dort. Dann komme ich eine Woche später zurück und versuche, das Modell von der Festplatte zu laden. Es gibt mir einen Fehler:
venuktan
2
Es gibt keine Möglichkeit, die Ausführung der fitMethode anzuhalten und fortzusetzen , wenn Sie danach suchen. That being said, joblib.loadsollte nicht eine Ausnahme nach einer erfolgreichen erhöhen , joblib.dumpwenn Sie es von einem Python mit der gleichen Version des Scikit-Learn - Bibliothek aufrufen.
Ogrisel
10
Wenn Sie IPython verwenden, verwenden Sie weder das --pylabBefehlszeilenflag noch die %pylabMagie, da die implizite Überladung des Namespace bekanntermaßen den Beizprozess unterbricht. Verwenden Sie %matplotlib inlinestattdessen explizite Importe und die Magie.
Ogrisel
2
Weitere Informationen finden Sie in der Dokumentation zu scikit-learn: scikit-learn.org/stable/tutorial/basic/…
user1448319
1
Ist es möglich, zuvor gespeichertes Modell neu zu trainieren? Speziell SVC-Modelle?
Uday Sawant
108

Was Sie suchen genannt Modell Persistenz in sklearn Worten , und es wird in dokumentiert Einführung und in Modell Persistenz Abschnitten.

Sie haben also Ihren Klassifikator initialisiert und lange mit trainiert

clf = some.classifier()
clf.fit(X, y)

Danach haben Sie zwei Möglichkeiten:

1) Mit Pickle

import pickle
# now you can save it to a file
with open('filename.pkl', 'wb') as f:
    pickle.dump(clf, f)

# and later you can load it
with open('filename.pkl', 'rb') as f:
    clf = pickle.load(f)

2) Verwenden von Joblib

from sklearn.externals import joblib
# now you can save it to a file
joblib.dump(clf, 'filename.pkl') 
# and later you can load it
clf = joblib.load('filename.pkl')

Noch einmal ist es hilfreich, die oben genannten Links zu lesen

Salvador Dali
quelle
30

In vielen Fällen, insbesondere bei der Textklassifizierung, reicht es nicht aus, nur den Klassifizierer zu speichern, sondern Sie müssen auch den Vektorisierer speichern, damit Sie Ihre Eingabe in Zukunft vektorisieren können.

import pickle
with open('model.pkl', 'wb') as fout:
  pickle.dump((vectorizer, clf), fout)

zukünftiger Anwendungsfall:

with open('model.pkl', 'rb') as fin:
  vectorizer, clf = pickle.load(fin)

X_new = vectorizer.transform(new_samples)
X_new_preds = clf.predict(X_new)

Vor dem Dumping des Vektorisierers kann die Eigenschaft stop_words_ des Vektorisierers gelöscht werden durch:

vectorizer.stop_words_ = None

um das Dumping effizienter zu gestalten. Auch wenn Ihre Klassifizierungsparameter spärlich sind (wie in den meisten Textklassifizierungsbeispielen), können Sie die Parameter von dicht in dünn konvertieren, was einen großen Unterschied in Bezug auf Speicherverbrauch, Laden und Dumping darstellt. Sparsifizieren Sie das Modell durch:

clf.sparsify()

Dies funktioniert automatisch für SGDClassifier. Wenn Sie jedoch wissen, dass Ihr Modell spärlich ist (viele Nullen in clf.coef_), können Sie clf.coef_ manuell in eine csr scipy sparse-Matrix konvertieren, indem Sie:

clf.coef_ = scipy.sparse.csr_matrix(clf.coef_)

und dann können Sie es effizienter speichern.

Asche
quelle
Aufschlussreiche Antwort! Ich wollte nur im Fall von SVC hinzufügen, es gibt einen spärlichen Modellparameter zurück.
Shayan Amani
4

sklearnSchätzer implementieren Methoden, die es Ihnen erleichtern, relevante trainierte Eigenschaften eines Schätzers zu speichern. Einige Schätzer implementieren __getstate__Methoden selbst, sondern andere, wie die GMMgerade die Verwendung Basisimplementierung , die einfach speichert die inneren Wörterbuch - Objekte:

def __getstate__(self):
    try:
        state = super(BaseEstimator, self).__getstate__()
    except AttributeError:
        state = self.__dict__.copy()

    if type(self).__module__.startswith('sklearn.'):
        return dict(state.items(), _sklearn_version=__version__)
    else:
        return state

Die empfohlene Methode zum Speichern Ihres Modells auf einer Disc ist die Verwendung des pickleModuls:

from sklearn import datasets
from sklearn.svm import SVC
iris = datasets.load_iris()
X = iris.data[:100, :2]
y = iris.target[:100]
model = SVC()
model.fit(X,y)
import pickle
with open('mymodel','wb') as f:
    pickle.dump(model,f)

Sie sollten jedoch zusätzliche Daten speichern, damit Sie Ihr Modell in Zukunft neu trainieren können oder schwerwiegende Folgen haben (z. B. die Bindung an eine alte Version von sklearn) .

Aus der Dokumentation :

Um ein ähnliches Modell mit zukünftigen Versionen von scikit-learn neu zu erstellen, sollten zusätzliche Metadaten entlang des ausgewählten Modells gespeichert werden:

Die Trainingsdaten, zB ein Verweis auf einen unveränderlichen Schnappschuss

Der Python-Quellcode, der zum Generieren des Modells verwendet wird

Die Versionen von scikit-learn und seine Abhängigkeiten

Die Kreuzvalidierungsbewertung, die anhand der Trainingsdaten erhalten wurde

Dies gilt insbesondere für Ensemble-Schätzer , die sich auf das tree.pyxin Cython geschriebene Modul stützen (z. B. IsolationForest), da dadurch eine Kopplung an die Implementierung hergestellt wird, die zwischen den Versionen von sklearn nicht garantiert stabil ist. In der Vergangenheit gab es rückwärts inkompatible Änderungen.

Wenn Ihre Modelle sehr groß werden und das Laden zu einem Ärgernis wird, können Sie auch das effizientere verwenden joblib. Aus der Dokumentation:

Im speziellen Fall des Scikits kann es interessanter sein, Joblibs Ersatz von pickle( joblib.dump& joblib.load) zu verwenden, der bei Objekten effizienter ist, die intern große Anzahl von Arrays tragen, wie dies häufig bei angepassten Scikit-Lernschätzern der Fall ist, aber nur beizen kann auf die Festplatte und nicht auf eine Zeichenfolge:

Sebastian Wozny
quelle
1
but can only pickle to the disk and not to a stringSie können dies jedoch von joblib in StringIO einfügen. Das mache ich die ganze Zeit.
Matthew
1

sklearn.externals.joblibist veraltet , da 0.21und wird in entfernt werden v0.23:

/usr/local/lib/python3.7/site-packages/sklearn/externals/joblib/ init .py: 15: FutureWarning: sklearn.externals.joblib ist in 0.21 veraltet und wird in 0.23 entfernt. Bitte importieren Sie diese Funktionalität direkt aus der Joblib, die installiert werden kann mit: pip install joblib. Wenn diese Warnung beim Laden eingelegter Modelle ausgegeben wird, müssen Sie diese Modelle möglicherweise mit scikit-learn 0.21+ neu serialisieren.
warnings.warn (msg, category = FutureWarning)


Daher müssen Sie installieren joblib:

pip install joblib

und schließlich schreiben Sie das Modell auf die Festplatte:

import joblib
from sklearn.datasets import load_digits
from sklearn.linear_model import SGDClassifier


digits = load_digits()
clf = SGDClassifier().fit(digits.data, digits.target)

with open('myClassifier.joblib.pkl', 'wb') as f:
    joblib.dump(clf, f, compress=9)

Um die abgelegte Datei zu lesen, müssen Sie lediglich Folgendes ausführen:

with open('myClassifier.joblib.pkl', 'rb') as f:
    my_clf = joblib.load(f)
Giorgos Myrianthous
quelle