Salvați clasificatorul pe disc în scikit-learn (Programare, Python, Învățare Automată, Scikit Learn, Clasificare)

garak a intrebat.

Cum se salvează un clasificator instruit clasificator Naive Bayes pe disc și să-l folosesc pentru să prezic date?

Am următorul program de probă de pe site-ul scikit-learn:

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()

6 răspunsuri
mwv

Clasificatorii sunt doar obiecte care pot fi decapate și aruncate ca oricare altele. Pentru a continua exemplul dvs:

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)

Editare: dacă folosiți un Pipeline sklearn în care aveți transformatoare personalizate care nu pot fi serializate de pickle (nici de joblib), atunci folosind Neuraxle’s custom ML Pipeline saving este o soluție prin care puteți defini propria dvs. salvatoare de etape pentru fiecare pas în parte. Economiștii sunt apelați pentru fiecare pas dacă sunt definiți la salvare, iar în caz contrar, joblib este utilizat în mod implicit pentru pașii care nu au un economizor.

Comentarii

  • Funcționează ca prin minune! Am încercat să folosesc np.savez și să îl încarc din nou tot timpul și asta nu a ajutat niciodată. Mulțumesc mult. –  > Por Kartos.
  • în python3, utilizați modulul pickle, care funcționează exact așa. –  > Por MCSH.
ogrisel

De asemenea, puteți utiliza joblib.dump și joblib.load care este mult mai eficient în manipularea matricelor numerice decât picklerul python implicit.

Joblib este inclus în scikit-learn:

>>> 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

Editare: în Python 3.8+ este acum posibil să se utilizeze pickle pentru o decapare eficientă a obiectelor cu matrici numerice mari ca atribute dacă se utilizează protocolul pickle 5 (care nu este cel implicit).

Comentarii

  • Dar, din câte am înțeles, pipelining-ul funcționează dacă face parte dintr-un singur flux de lucru. Dacă vreau să construiesc modelul, îl stochez pe disc și opresc execuția acolo. Apoi mă întorc o săptămână mai târziu și încerc să încarc modelul de pe disc, îmi dă o eroare : –  > Por venuktan.
  • Nu există nicio modalitate de a opri și de a relua execuția modelului fit metoda dacă asta este ceea ce căutați. Acestea fiind spuse, joblib.load nu ar trebui să ridice o excepție după o execuție reușită joblib.dump dacă o apelați dintr-un Python cu aceeași versiune a bibliotecii scikit-learn. –  > Por ogrisel.
  • Dacă folosiți IPython, nu folosiți opțiunea --pylab pentru linia de comandă sau opțiunea %pylab magic, deoarece se știe că supraîncărcarea implicită a spațiului de nume întrerupe procesul de decapare. Utilizați importurile explicite și opțiunea %matplotlib inline magic. –  > Por ogrisel.
  • consultați documentația scikit-learn pentru referință: scikit-learn.org/stable/tutorial/basic/… –  > Por user1448319.
  • Este posibil să reantrenați modelul salvat anterior? În special modelele SVC? –  > Por Uday Sawant.
Salvador Dali

Ceea ce căutați se numește Persistența modelului în cuvintele sklearn și este documentată în introducere și în persistența modelului secțiuni.

Așadar, v-ați inițializat clasificatorul și l-ați antrenat pentru o perioadă lungă de timp cu

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

După aceasta, aveți două opțiuni:

1) Utilizarea 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) Utilizarea 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')

Încă o dată, este util să citiți linkurile menționate mai sus

Comentarii

  • Procesul Joblib de mai sus funcționează pentru mine. [‘clf’= numele modelului de utilizat în fișier]. Folosesc joblib.dump() într-un fișier și încarc modelul într-un alt fișier folosind joblib.load() pentru a economisi timp de predicție. –  > Por Partha Sen.
  • joblib nu mai funcționează pentru mine – ImportError: cannot import name 'joblib' from 'sklearn.externals' –  > Por jtlz2.
Ash

În multe cazuri, în special în cazul clasificării textului, nu este suficient să stocați doar clasificatorul, ci va trebui să stocați și vectorizatorul, astfel încât să puteți vectoriza intrarea în viitor.

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

caz de utilizare viitoare:

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)

Înainte de a arunca vectorizatorul, se poate șterge proprietatea stop_words_ a vectorizatorului prin:

vectorizer.stop_words_ = None

pentru a face ca descărcarea să fie mai eficientă.De asemenea, dacă parametrii clasificatorului dvs. sunt puțini (ca în majoritatea exemplelor de clasificare a textelor), puteți converti parametrii din densi în puțini, ceea ce va face o diferență uriașă în ceea ce privește consumul de memorie, încărcarea și descărcarea. Sparsify modelul prin:

clf.sparsify()

Care va funcționa automat pentru SGDClassifier dar, în cazul în care știți că modelul dvs. este rar (multe zerouri în clf.coef_), atunci puteți converti manual clf.coef_ într-un fișier csr scipy sparse matrix de către:

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

și apoi o puteți stoca mai eficient.

Comentarii

  • Răspuns perspicace! Am vrut doar să adaug în cazul SVC, acesta returnează un parametru de model sparse. –  > Por Shayan Amani.
Sebastian Wozny

sklearn estimatorii implementează metode care să vă faciliteze salvarea proprietăților instruite relevante ale unui estimator. Unii estimatori implementează __getstate__ metode în sine, dar altele, cum ar fi GMM folosesc doar metoda implementarea de bază care salvează pur și simplu dicționarul interior al obiectelor:

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

Metoda recomandată pentru a salva modelul pe disc este utilizarea pickle modul:

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)

Cu toate acestea, ar trebui să salvați date suplimentare pentru a vă putea reeduca modelul în viitor, în caz contrar veți suferi consecințe grave. (cum ar fi blocarea într-o versiune veche de sklearn)..

Din modulul documentația:

Pentru a reconstrui un model similar cu versiunile viitoare ale scikit-learn, ar trebui să se salveze metadate suplimentare de-a lungul modelului decapat:

Datele de instruire, de exemplu, o referință la un instantaneu imuabil.

Codul sursă python utilizat pentru a genera modelul

versiunile scikit-learn și dependențele sale

Scorul validării încrucișate obținut pe datele de instruire

Acest lucru este valabil în special pentru estimatorii de ansamblu care se bazează pe tree.pyx scris în Cython (cum ar fi IsolationForest), deoarece se creează un cuplaj cu implementarea, a cărui stabilitate nu este garantată între versiunile sklearn. Acesta a cunoscut în trecut modificări incompatibile în sens invers.

Dacă modelele dvs. devin foarte mari și încărcarea devine o pacoste, puteți utiliza, de asemenea, modul mai eficient joblib. Din documentație:

În cazul specific al scikit-ului, poate fi mai interesant să folosiți înlocuirea joblib-ului de la pickle (joblib.dump & joblib.load), care este mai eficient pentru obiectele care transportă în interior matrici numpy mari, așa cum este adesea cazul estimatorilor scikit-learn, dar care nu poate decupla decât pe disc și nu pe un șir de caractere:

Comentarii

  • but can only pickle to the disk and not to a string Dar ați putea să o transferați în StringIO din joblib. Este ceea ce fac eu tot timpul. –  > Por Matthew.
  • Proiectul meu actual face ceva asemănător, știți cumva ce The training data, e.g. a reference to a immutable snapshot aici? TIA! –  > Por Daisy QL.
Giorgos Myrianthous

sklearn.externals.joblib a fost eliminat de la 0.21 și va fi eliminat în v0.23:

/usr/local/lib/python3.7/site-packages/sklearn/externals/joblib/init.py:15: FutureWarning: sklearn.externals.joblib este depreciat în 0.21 și va fi eliminat în 0.23. Vă rugăm să importați această funcționalitate direct din joblib, care poate fi instalat cu: pip install joblib. Dacă acest avertisment este afișat la încărcarea modelelor decapate, este posibil să trebuiască să serializați din nou aceste modele cu scikit-learn 0.21+.
warnings.warn(msg, category=FutureWarning)


Prin urmare, trebuie să instalați joblib:

pip install joblib

și, în final, să scrieți modelul pe disc:

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)

Acum, pentru a citi fișierul descărcat, tot ce trebuie să executați este:

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