Збережіть класифікатор на диску в scikit-learn


192

Як я зберегти навчений наївний байесовский класифікатор на диск і використовувати його для передбачати дані?

У мене є такий зразок програми з веб-сайту 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()

Відповіді:


201

Класифікатори - це просто предмети, які можна маринувати та скидати, як і будь-який інший. Щоб продовжити ваш приклад:

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)

1
Працює як шарм! Я намагався використовувати np.savez і завантажувати його назад весь час, і це ніколи не допомагало. Дуже дякую.
Картос

7
у python3 використовуйте модуль соління, який працює саме так.
MCSH

213

Ви також можете використовувати joblib.dump та joblib.load, що набагато ефективніше в обробці числових масивів, ніж піктолер python за замовчуванням.

Joblib включений у 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

Редагувати: у Python 3.8+ тепер можна використовувати соління для ефективного засолювання об'єкта з великими числовими масивами як атрибути, якщо ви використовуєте протокол 5 маринування (що не є типовим).


1
Але з мого розуміння трубопровід працює, якщо його частина є єдиною роботою. Якщо я хочу побудувати модель, збережіть її на диску і зупиніть її виконання там. Потім я повернувся через тиждень і спробую завантажити модель з диска, вона видає мені помилку:
venuktan

2
Неможливо зупинити та відновити виконання fitметоду, якщо це саме те, що ви шукаєте. Якщо говорити, joblib.loadне слід створювати виняток після успішного, joblib.dumpякщо ви називаєте його з Python з тією ж версією бібліотеки scikit-learn.
ogrisel

10
Якщо ви використовуєте IPython, не використовуйте --pylabпрапор командного рядка або %pylabмагію, оскільки неявна перевантаження простору імен, як відомо, порушує процес маринування. Використовуйте %matplotlib inlineнатомість явний імпорт та магію.
ogrisel

2
дивіться документацію на scikit-learn для довідки: scikit-learn.org/stable/tutorial/basic/…
користувач1448319

1
Чи можливо перекваліфікувати раніше збережену модель? Зокрема моделі SVC?
Uday Sawant

108

Те, що ви шукаєте, називається модель стійкості у чітких словах, і це задокументоване у вступу та в розділах збереження моделі .

Таким чином, ви ініціалізували свій класифікатор і довго його навчали

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

Після цього у вас є два варіанти:

1) Використання соління

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) Використання 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')

Ще раз корисно прочитати вищезазначені посилання


30

У багатьох випадках, особливо з класифікацією тексту, недостатньо лише зберігати класифікатор, але вам потрібно буде також зберігати векторизатор, щоб ви могли векторизувати свій внесок у майбутньому.

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

випадок майбутнього використання:

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)

Перед тим, як скинути векторизатор, можна видалити властивість stop_words_ векторизатора:

vectorizer.stop_words_ = None

зробити демпінг більш ефективним. Крім того, якщо параметри класифікатора є рідкісними (як у більшості прикладів класифікації тексту), ви можете перетворити параметри з щільних у розріджені, що призведе до величезної різниці щодо споживання пам'яті, завантаження та демпінгу. Розподіліть модель за:

clf.sparsify()

Який автоматично працює для SGDClassifier, але якщо ви знаєте, що ваша модель є рідкою (багато нулів у clf.coef_), ви можете вручну перетворити clf.coef_ в рідку матрицю csr scipy :

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

і тоді ви можете зберігати її більш ефективно.


Прониклива відповідь! Просто хотів додати у випадку SVC, він повертає параметр розрідженої моделі.
Шаян Амані

5

sklearnОцінювачі реалізують методи, щоб полегшити вам збереження відповідних навчених властивостей оцінювача. Деякі оцінювачі реалізують __getstate__методи самостійно, але інші, як-от GMMпросто використання базової реалізації, що просто зберігає внутрішній словник об'єктів:

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

Рекомендованим способом збереження вашої моделі на диску є використання pickleмодуля:

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)

Однак вам слід зберегти додаткові дані, щоб ви могли в подальшому перевчити свою модель або зазнати тяжких наслідків (наприклад, заблокувати стару версію sklearn) .

З документації :

Для відновлення подібної моделі з майбутніми версіями scikit-learn слід зберегти додаткові метадані уздовж маринованої моделі:

Дані про тренінг, наприклад, посилання на незмінний знімок

Вихідний код python, який використовується для створення моделі

Версії scikit-learn та його залежності

Оцінка крос-валідації, отримана на даних тренінгу

Особливо це стосується оцінок Ensemble, які покладаються на tree.pyxмодуль, написаний на Cython (такий як IsolationForest), оскільки він створює зв'язок із реалізацією, яка не гарантує стабільності між версіями sklearn. У минулому спостерігалися несумісні зміни.

Якщо ваші моделі стають дуже великими і завантаження стає неприємністю, ви також можете використовувати більш ефективні joblib. З документації:

У конкретному випадку scikit може бути цікавіше використовувати заміну joblib на pickle( joblib.dump& joblib.load), яка є більш ефективною для об'єктів, що містять великі нумерові масиви всередині, як це часто буває для пристосованих оцінювачів, які навчаються наукам, але можуть лише маринувати на диск, а не на рядок:


1
but can only pickle to the disk and not to a stringАле ви можете пересолити це в StringIO від joblib. Цим я весь час займаюся.
Метью

Мій поточний проект робить щось подібне, ти знаєш, що The training data, e.g. a reference to a immutable snapshotтут? ТІА!
Дейзі Цінь

1

sklearn.externals.joblibзастаріли , так 0.21і треба увійти на сайт v0.23:

/usr/local/lib/python3.7/site-packages/sklearn/externals/joblib/ init .py: 15: FutureWarning: sklearn.externals.joblib застаріло в 0,21 і буде видалено в 0,23. Будь ласка, імпортуйте цю функціональність безпосередньо з joblib, яку можна встановити за допомогою: pip install joblib. Якщо це попередження піднімається під час завантаження маринованих моделей, можливо, вам доведеться повторно серіалізувати ці моделі за допомогою scikit-learn 0,21+.
warnings.warn (msg, category = FutureWarning)


Тому вам потрібно встановити joblib:

pip install joblib

і нарешті запишіть модель на диск:

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)

Тепер для того, щоб прочитати викинутий файл, все що вам потрібно запустити:

with open('myClassifier.joblib.pkl', 'rb') as f:
    my_clf = joblib.load(f)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.