scikit-learn: Guardar y restaurar modelos


En muchas ocasiones, mientras trabaja con la biblioteca scikit-learn , deberá guardar sus modelos de predicción en un archivo y luego restaurarlos para reutilizar su trabajo anterior para: probar su modelo con datos nuevos, comparar varios modelos o Algo más. Este procedimiento de guardado también se conoce como serialización de objetos: representa un objeto con un flujo de bytes para almacenarlo en el disco, enviarlo a través de una red o guardarlo en una base de datos, mientras que el procedimiento de restauración se conoce como deserialización. En este artículo, analizamos tres formas posibles de hacer esto en Python y scikit-learn, cada una presentada con sus pros y sus contras.

Herramientas para guardar y restaurar modelos

La primera herramienta que describimos es Pickle , la herramienta estándar de Python para la (des) serialización de objetos. Luego, miramos la biblioteca Joblib que ofrece (des) serialización fácil de objetos que contienen matrices de datos grandes, y finalmente presentamos un enfoque manual para guardar y restaurar objetos hacia / desde JSON (JavaScript Object Notation). Ninguno de estos enfoques representa una solución óptima, pero se debe elegir el ajuste correcto de acuerdo con las necesidades de su proyecto.

Inicialización del modelo

Inicialmente, creemos un modelo de scikit-learn. En nuestro ejemplo usaremos un modelo de regresión logística y el conjunto de datos Iris . 

Vamos a importar las bibliotecas necesarias, cargar los datos y dividirlos en conjuntos de prueba y entrenamiento.

from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

# Load and split data
data = load_iris()
Xtrain, Xtest, Ytrain, Ytest = train_test_split(data.data, data.target, test_size=0.3, random_state=4)

Ahora creemos el modelo con algunos parámetros no predeterminados y ajustémoslo a los datos de entrenamiento. Suponemos que ha encontrado previamente los parámetros óptimos del modelo, es decir, los que producen la mayor precisión estimada.

# Create a model
model = LogisticRegression(C=0.1, 
                           max_iter=20, 
                           fit_intercept=True, 
                           n_jobs=3, 
                           solver='liblinear')
model.fit(Xtrain, Ytrain)

Y nuestro modelo resultante:

LogisticRegression(C=0.1, class_weight=None, dual=False, fit_intercept=True,
    intercept_scaling=1, max_iter=20, multi_class='ovr', n_jobs=3,
    penalty='l2', random_state=None, solver='liblinear', tol=0.0001,
    verbose=0, warm_start=False)

Usando el fitmétodo, el modelo ha aprendido sus coeficientes que están almacenados en model.coef_. El objetivo es guardar los parámetros y los coeficientes del modelo en un archivo, por lo que no es necesario repetir el entrenamiento del modelo y los pasos de optimización de los parámetros nuevamente con datos nuevos.

Módulo pickle

En las siguientes líneas de código, el modelo que creamos en el paso anterior se guarda en un archivo y luego se carga como un nuevo objeto llamado pickled_model. A continuación, el modelo cargado se utiliza para calcular la puntuación de precisión y predecir los resultados sobre nuevos datos no vistos (de prueba).

import pickle

#
# Create your model here (same as above)
#

# Save to file in the current working directory
pkl_filename = "pickle_model.pkl"
with open(pkl_filename, 'wb') as file:
    pickle.dump(model, file)

# Load from file
with open(pkl_filename, 'rb') as file:
    pickle_model = pickle.load(file)
    
# Calculate the accuracy score and predict target values
score = pickle_model.score(Xtest, Ytest)
print("Test score: {0:.2f} %".format(100 * score))
Ypredict = pickle_model.predict(Xtest)

La ejecución de este código debería generar su puntuación y guardar el modelo a través de Pickle:

$ python save_model_pickle.py
Test score: 91.11 %

Lo mejor de usar Pickle para guardar y restaurar nuestros modelos de aprendizaje es que es rápido: puede hacerlo en dos líneas de código. Es útil si ha optimizado los parámetros del modelo en los datos de entrenamiento, por lo que no necesita repetir este paso nuevamente. De todos modos, no guarda los resultados de la prueba ni ningún dato. Aún así, puede hacer esto guardando una tupla, o una lista, de varios objetos (y recuerde qué objeto va a dónde), de la siguiente manera:

tuple_objects = (model, Xtrain, Ytrain, score)

# Save tuple
pickle.dump(tuple_objects, open("tuple_model.pkl", 'wb'))

# Restore tuple
pickled_model, pickled_Xtrain, pickled_Ytrain, pickled_score = pickle.load(open("tuple_model.pkl", 'rb'))

Módulo Joblib

La biblioteca Joblib está destinada a ser un reemplazo de Pickle, para objetos que contienen datos grandes. Repetiremos el procedimiento de guardar y restaurar como con Pickle.

from sklearn.externals import joblib

# Save to file in the current working directory
joblib_file = "joblib_model.pkl"
joblib.dump(model, joblib_file)

# Load from file
joblib_model = joblib.load(joblib_file)

# Calculate the accuracy and predictions
score = joblib_model.score(Xtest, Ytest)
print("Test score: {0:.2f} %".format(100 * score))
Ypredict = pickle_model.predict(Xtest)
$ python save_model_joblib.py
Test score: 91.11 %

Como se ve en el ejemplo, la biblioteca Joblib ofrece un flujo de trabajo un poco más simple en comparación con Pickle. Si bien Pickle requiere que se pase un objeto de archivo como argumento, Joblib funciona tanto con objetos de archivo como con nombres de archivo de cadena. En caso de que su modelo contenga grandes conjuntos de datos, cada conjunto se almacenará en un archivo separado, pero el procedimiento de guardar y restaurar seguirá siendo el mismo. Joblib también permite diferentes métodos de compresión, como ‘zlib’, ‘gzip’, ‘bz2’ y diferentes niveles de compresión.

Guardar y restaurar manualmente a JSON

Dependiendo de su proyecto, muchas veces encontrará Pickle y Joblib como soluciones inadecuadas. De todos modos, siempre que desee tener un control total sobre el proceso de guardar y restaurar, la mejor manera es crear sus propias funciones manualmente.

A continuación, se muestra un ejemplo de cómo guardar y restaurar objetos manualmente mediante JSON. Este enfoque nos permite seleccionar los datos que deben guardarse, como los parámetros del modelo, los coeficientes, los datos de entrenamiento y cualquier otra cosa que necesitemos.

Dado que queremos guardar todos estos datos en un solo objeto, una forma posible de hacerlo es crear una nueva clase que herede de la clase modelo, que en nuestro ejemplo es LogisticRegression. La nueva clase, llamada MyLogReg, implementa los métodos save_jsonload_json para guardar y restaurar a / desde un archivo JSON, respectivamente.

Para simplificar, guardaremos solo tres parámetros del modelo y los datos de entrenamiento. Algunos datos adicionales que podríamos almacenar con este enfoque son, por ejemplo, una puntuación de validación cruzada en el conjunto de entrenamiento, datos de prueba, puntuación de precisión en los datos de prueba, etc.

import json
import numpy as np

class MyLogReg(LogisticRegression):
    
    # Override the class constructor
    def __init__(self, C=1.0, solver='liblinear', max_iter=100, X_train=None, Y_train=None):
        LogisticRegression.__init__(self, C=C, solver=solver, max_iter=max_iter)
        self.X_train = X_train
        self.Y_train = Y_train
        
    # A method for saving object data to JSON file
    def save_json(self, filepath):
        dict_ = {}
        dict_['C'] = self.C
        dict_['max_iter'] = self.max_iter
        dict_['solver'] = self.solver
        dict_['X_train'] = self.X_train.tolist() if self.X_train is not None else 'None'
        dict_['Y_train'] = self.Y_train.tolist() if self.Y_train is not None else 'None'
        
        # Creat json and save to file
        json_txt = json.dumps(dict_, indent=4)
        with open(filepath, 'w') as file:
            file.write(json_txt)
    
    # A method for loading data from JSON file
    def load_json(self, filepath):
        with open(filepath, 'r') as file:
            dict_ = json.load(file)
            
        self.C = dict_['C']
        self.max_iter = dict_['max_iter']
        self.solver = dict_['solver']
        self.X_train = np.asarray(dict_['X_train']) if dict_['X_train'] != 'None' else None
        self.Y_train = np.asarray(dict_['Y_train']) if dict_['Y_train'] != 'None' else None
        

Ahora probemos la MyLogRegclase. Primero creamos un objeto mylogreg, le pasamos los datos de entrenamiento y lo guardamos en un archivo. Luego creamos un nuevo objeto json_mylogregy llamamos al métod load_json para cargar los datos del archivo.

filepath = "mylogreg.json"

# Create a model and train it
mylogreg = MyLogReg(X_train=Xtrain, Y_train=Ytrain)
mylogreg.save_json(filepath)

# Create a new object and load its data from JSON file
json_mylogreg = MyLogReg()
json_mylogreg.load_json(filepath)
json_mylogreg

Al imprimir el nuevo objeto, podemos ver nuestros parámetros y datos de entrenamiento según sea necesario.

MyLogReg(C=1.0,
     X_train=array([[ 4.3,  3. ,  1.1,  0.1],
       [ 5.7,  4.4,  1.5,  0.4],
       ...,
       [ 7.2,  3. ,  5.8,  1.6],
       [ 7.7,  2.8,  6.7,  2. ]]),
     Y_train=array([0, 0, ..., 2, 2]), class_weight=None, dual=False,
     fit_intercept=True, intercept_scaling=1, max_iter=100,
     multi_class='ovr', n_jobs=1, penalty='l2', random_state=None,
     solver='liblinear', tol=0.0001, verbose=0, warm_start=False)

Dado que la serialización de datos usando JSON realmente guarda el objeto en un formato de cadena, en lugar de un flujo de bytes, el archivo ‘mylogreg.json’ podría abrirse y modificarse con un editor de texto. Aunque este enfoque sería conveniente para el desarrollador, es menos seguro ya que un intruso puede ver y modificar el contenido del archivo JSON. Además, este enfoque es más adecuado para objetos con una pequeña cantidad de variables de instancia, como los modelos scikit-learn, porque cualquier adición de nuevas variables requiere cambios en los métodos de guardar y restaurar.

Problemas de compatibilidad

Si bien algunos de los pros y los contras de cada herramienta se cubrieron en el texto hasta ahora, probablemente el mayor inconveniente de las herramientas Pickle y Joblib es su compatibilidad con diferentes modelos y versiones de Python.

Compatibilidad con la versión de Python : la documentación de ambas herramientas indica que no se recomienda (des) serializar objetos en diferentes versiones de Python, aunque podría funcionar con cambios menores de versión.

Compatibilidad del modelo : uno de los errores más frecuentes es guardar su modelo con Pickle o Joblib y luego cambiar el modelo antes de intentar restaurar desde un archivo. La estructura interna del modelo debe permanecer sin cambios entre guardar y recargar.

Un último problema con Pickle y Joblib está relacionado con la seguridad. Ambas herramientas pueden contener código malicioso, por lo que no se recomienda restaurar datos de fuentes no confiables o no autenticadas.

Conclusiones

En esta publicación describimos tres herramientas para guardar y restaurar modelos de scikit-learn. Las bibliotecas Pickle y Joblib son rápidas y fáciles de usar, pero tienen problemas de compatibilidad en diferentes versiones de Python y cambios en el modelo de aprendizaje. Por otro lado, el enfoque manual es más difícil de implementar y debe modificarse con cualquier cambio en la estructura del modelo, pero en el lado positivo podría adaptarse fácilmente a varias necesidades y no tiene problemas de compatibilidad.

Cómo convertir su impresora 3D en un plotter en dos pasos


Un plotter o trazador es un dispositivo que puede dibujar texto e imágenes en papel con un utensilio ( por ejemplo un bolígrafo). 

Si pensamos en en el hardware necesario , podemos pensar que un buen atajo puede ser una vieja ( o no) impresora 3D pues estas ya incluyen todo el hardware y la electrónica que necesitamos: sólo hay que encontrar la manera de adjuntar un utensilio de dibujo y cómo decirle que dibuje.

En realidad como vamos a ver es mucho más fácil de lo que nos podemos imaginar, asi que en esta publicación de blog, aprenderá cómo puede hacer su propio dibujo de impresora.

Convertir una impresora 3D en una impresora 2D

Quizás se pregunte cuál es la utilidad de convertir una impresora 3D en algo que pueda dibujar imágenes 2D en un papel. Después de todo, las impresoras convencionales hacen eso desde hace varias décadas, ¿no es eso un paso atrás?

Pues , un plotter le permitirá dibujar con bolígrafo, lápices de colores, crayones, marcadores e incluso una pluma (básicamente todo lo que pueda dejar marcas en un papel). Pero no solo eso, incluso podemos dibujar en diferentes materiales, como cartón o vidrio. También puede ser creativo con tipos de tinta únicos, como dorada, plateada o que brillan en la oscuridad

Una utilidad innegable para los electrónicos es ayudar en la fabricación de circuitos impresos pues normalmente el diseño de la pcb se realiza calcando el diseño en la parte del cobre y luego hay que volver hay que repintar el diseño con un rotulador edding ( Además incluso puede ayudar en el taladrado con un cnc los orificios para los componentes)

Paso 1 – Colocación de un utensilio de dibujo

Desea montar de manera confiable un bolígrafo en el cabezal de la impresora y asegurarse de que la punta del bolígrafo quede un poco por debajo de la boquilla. Empecé diseñando una pequeña parte de este propósito. Se sujeta al cabezal de la impresora utilizando un pequeño tornillo M3 para fijar el bolígrafo en él:

Puede conseguir el modelo en thingiverse aquí . Debe adaptarse a cualquier impresora Creality Ender-3 o CR-20, y posiblemente a otras impresoras Creality. También es personalizable, por lo que puede modificar las dimensiones (si desea colocar un marcador más grande o necesita un ajuste más ajustado con la impresora).

Para otras impresoras, deberá diseñar su propio mecanismo de montaje (cuando lo haga, comparta un enlace en los comentarios). Si bien también es posible usar tornillos para montar el bolígrafo, personalmente prefiero el mecanismo de recorte, ya que me permite cambiar entre los modos de impresora 3D y trazador muy rápido, y también cambiar los bolígrafos muy rápido.

Paso 2 – Calibración

Una vez que haya montado correctamente su lápiz en su impresora, es hora de calibrarlo. Deberá adjuntar una hoja de papel a la cama de la impresora:

A continuación, deberá encontrar la altura correcta para imprimir. Se recomiendo usar Repetier Host pen lugar del clasico Cura, pues Repetier Host hara todo mucho más fácil ).

Antes de comenzar, asegúrese de que la plataforma de la impresora esté nivelada y que tanto la boquilla como la plataforma de la impresora estén frías.

Después de ubicar su impresora, vaya a la pestaña «Control manual» dentro de Repetier y mueva el cabezal de impresión hacia arriba hasta que la punta del bolígrafo esté por encima del papel. Luego, mueva su eje X / Y al borde de donde desea que esté su dibujo. Finalmente, mueva el eje Z hacia abajo en incrementos de 0,1 mm, hasta que vea que la punta del bolígrafo toca el papel. A continuación, puede mover un poco la X / Y y comprobar que el bolígrafo realmente deja un rastro en el papel. Cuando termine, observe los valores X / Y / Z que aparecen en la línea superior:

En mi caso, los valores fueron 47 para X, 40 para Y y 14,6 para Z. Usaremos estos valores en breve cuando generemos el archivo GCode para imprimir.

Paso 3: elegir qué imprimir y generacion del gcode

Esa es una dificil pues existen infinitass opciones. Sin embargo, deberá obtenerlo en formato vectorial, por lo que si usa Google Imágenes, agregue el texto type:svg al final de su consulta de búsqueda. También puede convertir imágenes JPEG y PNG a SVG , pero sugeriría comenzar con algo que ya viene como un vector para simplificar las cosas.

Cuando se comenza un proyecto asi seguro que se piensa en el tiempo para conseguir el hardware correcto, pero se sorprenderalo rápido que se hace funcionar la parte del hardware. Sin embargo, el software es otra historia completamente diferente; como siempre, el software es donde reside la verdadera complejidad .

 Además de Repetier Host mencionado anteriormente, también necesita obtener Inkscape (que, por cierto, ¡también es útil si desea crear arte de PCB !).

Dentro de Inkscape, cree un nuevo archivo y vaya al menú Archivo → Propiedades del documento (Acceso directo: Ctrl + Shift + D). Luego, establezca el tamaño del documento un poco más pequeño que el tamaño de la cama de impresión y asegúrese también de usarlo mm para las unidades.

Una vez que haya establecido el tamaño, puede importar cualquier archivo SVG que desee o simplemente dibujar un texto con la herramienta Texto:

Cuando termine, con el texto aún seleccionado, haga clic en el menú Ruta → Objeto a ruta (Mayús + Ctrl + C). Esto convertirá el texto en una serie de puntos conectados por líneas, lo cual es necesario para alimentar la impresora. Puede agregar más elementos como espirales y formas de estrella, repitiendo la operación «Objeto a ruta» para cada uno:

Al imprimir, los objetos no se rellenarán, por lo que es posible que desee eliminar su color de relleno y establecer su color de trazo en negro (o el color de su lápiz), para obtener una representación más precisa del resultado final. Seleccione todos los objetos (Ctrl + A) y luego elimine el relleno y aplique color negro para el trazo (Ctrl + Shift + F):

Cuando esté satisfecho con el resultado, es hora de generar el GCode para la impresora. Usaremos una extensión llamada «Gcodetools», que viene incluida con Inkscape (si no, tiene una versión anterior y necesita actualizar).

Comenzaremos definiendo los puntos de orientación, que le dicen a la impresora cómo mapear las líneas en la pantalla en el papel. Vaya al Menú de extensiones → Gcodetools → Puntos de orientación  y después de asegurarse de que el modo “2 puntos” esté seleccionado, haga clic en Aplicar y luego en Cerrar . Ahora debería ver dos nuevos elementos de texto agregados en la parte inferior de su dibujo:

Estos son los puntos de orientación. Cada punto es una lista de coordenadas X, Y, Z que especifica la ubicación de destino de ese punto en el sistema de coordenadas de la impresora. Debe editarlos para que coincidan con la X / Y que encontró en el paso de calibración y establecer la Z (la tercera coordenada) en 0.

Edite el texto en el punto izquierdo y actualícelo para que contenga las coordenadas X / Y que encontró. En mi caso lo fue (47; 40; 0). Para el punto correcto, agregue 100 al valor X, copie el Y / Z del primero, por ejemplo (147; 40; 0):

A continuación, necesitamos generar una herramienta y configurar su velocidad. Este paso es opcional, pero si no lo hace, su impresora se dibujará realmente muy lento. Vaya al menú Extensiones → Gcodetools → Biblioteca de herramientas  y seleccione «predeterminado» en «Tipos de herramientas»:

Haga clic en Aplicar y luego en Cerrar, y debería ver un rectángulo verde con muchas configuraciones agregadas a su dibujo:

Puede alejar este rectángulo (junto con todos los valores) para que no se sobreponga en su dibujo. Luego, desea editar el texto y cambiar los valores de «Alimentación», «Alimentación de penetración», «Alimentación de paso» para establecer la velocidad de movimiento de la impresora al dibujar. Yo uso 4500 para todos ellos (la unidad es mm / min, por lo que este valor corresponde a 75 mm / seg).

¡Finalmente estamos listos para generar el GCode! Seleccione todos los elementos en su dibujo (Ctrl + A) y vaya a Extensiones → Gcodetools → Ruta a Gcode…

Allí, vaya a la pestaña Opciones y establezca «Escala a lo largo del eje Z» en 1, y «Desplazamiento a lo largo del eje Z» al valor Z que encontró en el paso de calibración, menos uno (encontré 14.6, así que lo configuré aquí a 13.6):

A continuación, vaya a la pestaña Preferencias y establezca el nombre del archivo de salida y la ruta del directorio cuando desee que se guarde. También puede configurar la altura segura Z en un valor más bajo, para acelerar la impresión (yo uso 5):

Finalmente, cambie a la pestaña Ruta a Gcode , configure la Función de profundidad en 1y haga clic en Aplicar. Tardará unos segundos y es posible que muestre una advertencia acerca de que no se han seleccionado rutas, que puede ignorar con seguridad. Debería ver una nueva capa en la parte superior de su dibujo, mostrando los movimientos del cabezal de impresión en el archivo Gcode generado:

En este punto, sugiero abrir el archivo .gcode en un editor de texto y verificar que se vea legítimo, especialmente que los valores Z coincidan con el valor de calibración que encontró:

También sugiero editar la primera linea G00 y agregar F4500 al final, de lo contrario, su impresora podría hacer que el movimiento inicial del cabezal sea realmente lento:

¡Eso es! Estás listo para imprimir. Cargue su archivo Gcode en el host de Repetier y debería ver su dibujo en la pantalla:

Diga su oración, haga clic en el botón «Iniciar impresión» y … ¡disfrute del espectáculo!

Fuente :https://urish.medium.com/