python - skimage - Guarde el clasificador en el disco en scikit-learn
scikit learn español (5)
En muchos casos, particularmente con la clasificación de texto, no es suficiente almacenar el clasificador, pero también necesitará almacenar el vectorizador para poder vectorizar su entrada en el futuro.
import pickle
with open(''model.pkl'', ''wb'') as fout:
pickle.dump((vectorizer, clf), fout)
caso de uso futuro:
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)
Antes de eliminar el vectorizador, uno puede eliminar la propiedad stop_words_ del vectorizador de la siguiente manera:
vectorizer.stop_words_ = None
para hacer el dumping más eficiente. Además, si los parámetros de su clasificador son escasos (como en la mayoría de los ejemplos de clasificación de texto), puede convertir los parámetros de denso a disperso, lo que supondrá una gran diferencia en términos de consumo de memoria, carga y descarga. Sparsify el modelo por:
clf.sparsify()
Lo cual funcionará automáticamente para SGDClassifier pero en caso de que sepa que su modelo es escaso (muchos ceros en clf.coef_), entonces puede convertir clf.coef_ manualmente en una matriz dispersa scipy csr de la siguiente manera :
clf.coef_ = scipy.sparse.csr_matrix(clf.coef_)
y luego puedes almacenarlo de manera más eficiente.
¿Cómo guardo un clasificador Naive Bayes entrenado en el disco y lo uso para predecir datos?
Tengo el siguiente programa de ejemplo del sitio web 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()
Lo que está buscando se llama persistencia de modelo en palabras de sklearn y está documentado en la scikit-learn.org/stable/tutorial/basic/… y en las secciones de persistencia del modelo .
Así que has inicializado tu clasificador y lo has entrenado durante mucho tiempo con
clf = some.classifier()
clf.fit(X, y)
Después de esto tienes dos opciones:
1) Usando 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) Usando 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'')
Una vez más, es útil leer los enlaces mencionados anteriormente
Los clasificadores son solo objetos que se pueden escabechar y arrojar como cualquier otro. Para continuar tu ejemplo:
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)
También puede usar joblib.dump y joblib.load que es mucho más eficiente en el manejo de matrices numéricas que el pickler predeterminado de python.
Joblib está incluido en scikit-learn:
>>> from sklearn.externals 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
sklearn
estimadores sklearn
implementan métodos para facilitarle el sklearn
las propiedades relevantes entrenadas de un estimador. Algunos estimadores implementan los métodos __getstate__
sí mismos, pero otros, como el GMM
simplemente usan la implementación base que simplemente guarda el diccionario interno de los objetos:
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
El método recomendado para guardar su modelo en un disco es usar el módulo 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)
Sin embargo, debe guardar datos adicionales para poder volver a capacitar a su modelo en el futuro, o sufrir consecuencias nefastas (como estar bloqueado en una versión anterior de sklearn) .
De la documentación :
Para reconstruir un modelo similar con versiones futuras de scikit-learn, se deben guardar metadatos adicionales a lo largo del modelo en escabeche:
Los datos de entrenamiento, por ejemplo, una referencia a una instantánea inmutable
El código fuente python utilizado para generar el modelo
Las versiones de scikit-learn y sus dependencias
El puntaje de validación cruzada obtenido en los datos de entrenamiento
Esto es especialmente cierto para los estimadores de Ensemble que se basan en el módulo tree.pyx
escrito en Cython (como IsolationForest
), ya que crea un acoplamiento a la implementación, que no se garantiza que sea estable entre las versiones de sklearn. Ha visto cambios hacia atrás incompatibles en el pasado.
Si tus modelos se vuelven muy grandes y la carga se convierte en una molestia, también puedes usar el joblib
más eficiente. De la documentación:
En el caso específico del scikit, puede ser más interesante usar el reemplazo de
pickle
joblib.dump
(joblib.dump
yjoblib.load
), que es más eficiente en objetos que llevan matrices numpy grandes internamente, como suele ser el caso para scikit- aprende estimadores, pero solo puede escalar al disco y no a una cadena: