Simpan classifier ke disk di scikit-pelajari

192

Bagaimana cara menyimpan classifier Naive Bayes yang terlatih ke disk dan menggunakannya untuk memprediksi data?

Saya memiliki program sampel berikut dari situs 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()
garak
sumber

Jawaban:

201

Pengklasifikasi hanyalah objek yang dapat diacar dan dibuang seperti yang lainnya. Untuk melanjutkan contoh Anda:

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
sumber
1
Bekerja seperti pesona! Saya mencoba menggunakan np.savez dan memuatnya kembali dan itu tidak pernah membantu. Terima kasih banyak.
Kartos
7
di python3, gunakan modul acar, yang berfungsi persis seperti ini.
MCSH
213

Anda juga dapat menggunakan joblib.dump dan joblib.load yang jauh lebih efisien dalam menangani array numerik daripada python pickler default.

Joblib termasuk dalam 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

Sunting: dengan Python 3.8+ sekarang dimungkinkan untuk menggunakan acar untuk pengawetan objek yang efisien dengan array numerik yang besar sebagai atribut jika Anda menggunakan protokol acar 5 (yang bukan default).

ogrisel
sumber
1
Tapi dari pengertian saya pipelining berfungsi jika itu bagian dari alur kerja tunggal. Jika saya ingin membangun model, simpan di disk dan hentikan eksekusi di sana. Kemudian saya kembali seminggu kemudian dan mencoba memuat model dari disk itu membuat saya kesalahan:
venuktan
2
Tidak ada cara untuk menghentikan dan melanjutkan eksekusi fitmetode jika ini yang Anda cari. Yang sedang berkata, joblib.loadseharusnya tidak menimbulkan pengecualian setelah berhasil joblib.dumpjika Anda memanggilnya dari Python dengan versi yang sama dari perpustakaan scikit-learn.
ogrisel
10
Jika Anda menggunakan IPython, jangan gunakan --pylabbendera baris perintah atau %pylabsihir karena overload namespace implisit diketahui dapat memecah proses pengawetan. Gunakan impor eksplisit dan %matplotlib inlinesihir sebagai gantinya.
ogrisel
2
lihat dokumentasi scikit-learn untuk referensi: scikit-learn.org/stable/tutorial/basic/…
user1448319
1
Apakah mungkin untuk melatih ulang model yang disimpan sebelumnya? Khususnya model SVC?
Uday Sawant
108

Apa yang Anda cari disebut Model kegigihan dalam kata-kata sklearn dan didokumentasikan dalam pengantar dan di bagian kegigihan model .

Jadi Anda telah menginisialisasi classifier Anda dan melatihnya untuk waktu yang lama bersama

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

Setelah ini, Anda memiliki dua opsi:

1) Menggunakan Acar

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) Menggunakan 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')

Sekali lagi, sangat membantu untuk membaca tautan yang disebutkan di atas

Salvador Dali
sumber
30

Dalam banyak kasus, terutama dengan klasifikasi teks, tidak cukup hanya menyimpan classifier tetapi Anda juga harus menyimpan vectorizer sehingga Anda dapat membuat vektor input Anda di masa depan.

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

kasus penggunaan di masa depan:

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)

Sebelum membuang vektorizer, seseorang dapat menghapus properti stop_words_ vektorizer dengan:

vectorizer.stop_words_ = None

untuk membuat pembuangan lebih efisien. Juga jika parameter classifier Anda jarang (seperti pada kebanyakan contoh klasifikasi teks) Anda dapat mengkonversi parameter dari padat menjadi jarang yang akan membuat perbedaan besar dalam hal konsumsi memori, memuat dan membuang. Sebar model dengan:

clf.sparsify()

Yang secara otomatis akan bekerja untuk SGDClassifier tetapi jika Anda tahu model Anda jarang (banyak nol di clf.coef_) maka Anda dapat secara manual mengkonversi clf.coef_ menjadi matriks jarang csr scipy sparse dengan:

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

dan kemudian Anda dapat menyimpannya dengan lebih efisien.

Abu
sumber
Jawaban mendalam! Hanya ingin menambahkan dalam kasus SVC, ia mengembalikan parameter model yang jarang.
Shayan Amani
5

sklearnestimator menerapkan metode untuk memudahkan Anda menyimpan properti terlatih yang relevan dari estimator. Beberapa estimator mengimplementasikan __getstate__metode sendiri, tetapi yang lain, seperti GMMhanya menggunakan implementasi basis yang hanya menyimpan objek kamus batin:

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

Metode yang disarankan untuk menyimpan model Anda ke disk adalah dengan menggunakan picklemodul:

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)

Namun, Anda harus menyimpan data tambahan sehingga Anda dapat melatih kembali model Anda di masa depan, atau menderita konsekuensi yang mengerikan (seperti dikunci ke dalam versi lama sklearn) .

Dari dokumentasi :

Untuk membangun kembali model yang sama dengan versi scikit-learn di masa depan, metadata tambahan harus disimpan di sepanjang model acar:

Data pelatihan, misalnya referensi ke foto yang tidak dapat diubah

Kode sumber python digunakan untuk menghasilkan model

Versi scikit-learn dan dependensinya

Skor validasi silang diperoleh pada data pelatihan

Hal ini terutama berlaku untuk penaksir Ensemble yang bergantung pada tree.pyxmodul yang ditulis dalam Cython (seperti IsolationForest), karena ia membuat sambungan ke implementasi, yang tidak dijamin stabil di antara versi sklearn. Telah melihat perubahan yang tidak kompatibel di masa lalu.

Jika model Anda menjadi sangat besar dan memuat menjadi gangguan, Anda juga dapat menggunakan yang lebih efisien joblib. Dari dokumentasi:

Dalam kasus khusus scikit, mungkin lebih menarik untuk menggunakan penggantian joblib pickle( joblib.dump& joblib.load), yang lebih efisien pada objek yang membawa array numpy besar secara internal seperti yang sering terjadi pada penduga scikit-learn yang dipasang, tetapi hanya dapat mengasup ke disk dan bukan ke string:

Sebastian Wozny
sumber
1
but can only pickle to the disk and not to a stringTapi Anda bisa memilih ini ke dalam StringIO dari joblib. Inilah yang saya lakukan sepanjang waktu.
Matius
Proyek saya saat ini melakukan hal yang serupa, tahukah Anda di The training data, e.g. a reference to a immutable snapshotsini? TIA!
Daisy Qin
1

sklearn.externals.joblibtelah ditinggalkan sejak 0.21dan akan dihapus di v0.23:

/usr/local/lib/python3.7/site-packages/sklearn/externals/joblib/ init .py: 15: FutureWarning: sklearn.externals.joblib tidak digunakan lagi di 0.21 dan akan dihapus di 0.23. Silakan impor fungsi ini langsung dari joblib, yang dapat diinstal dengan: pip install joblib. Jika peringatan ini dinaikkan saat memuat model acar, Anda mungkin perlu membuat ulang model-model tersebut dengan scikit-learn 0.21+.
warnings.warn (msg, category = FutureWarning)


Karena itu, Anda perlu menginstal joblib:

pip install joblib

dan akhirnya menulis model ke disk:

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)

Sekarang untuk membaca file yang dibuang, yang perlu Anda jalankan adalah:

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