ai-center
2020.10
false
AI Center
Automation CloudAutomation SuiteStandalone
Last updated 6 de jun. de 2024

Creación de paquetes ML

Los científicos de datos construyen modelos preentrenados utilizando Python o utilizando una plataforma AutoML. Los desarrolladores de RPA son los que consumirán estos modelos dentro de un flujo de trabajo.

Estructurar paquetes ML

Un paquete debe cumplir con un pequeño conjunto de requisitos. Estos requisitos se dividen entre los componentes necesarios para servir un modelo y los componentes necesarios para entrenar un modelo.

Servicio de componentes

Un paquete debe proporcionar al menos lo siguiente:
  • Una carpeta que contenga un archivo main.py en la raíz de esa carpeta.
  • En este archivo, una clase llamada Main que implemente al menos dos funciones:
    • _init_(self): no tiene argumento y carga tu modelo y los datos locales para el modelo (por ejemplo, inserción de palabras).
    • predict(self, input): una función a la que se llamará en el momento del servicio del modelo.
  • Un archivo llamado requirements.txt con dependencias necesarias para ejecutar el modelo.
Piensa en el componente de servicio de un paquete como el modelo en el momento de la inferencia. En el momento del servicio, se crea una imagen de contenedor utilizando el archivo requirements.txt proporcionado, y la función predict se utiliza como punto de conexión del modelo.

Componente de entrenamiento y evaluación

Además de la inferencia, un paquete puede utilizarse de forma opcional para entrenar un modelo de aprendizaje automático. Esta tarea se lleva a cabo proporcionando lo siguiente:

  1. En la misma carpeta raíz, con el archivo main.py, establece un archivo llamado train.py.
  2. En este archivo, establece una clase llamada Main que implemente al menos cuatro funciones. Todas las siguientes funciones excepto _init_, son opcionales, pero limitan el tipo de procesos que pueden ejecutarse con el paquete correspondiente.
    1. _init_(self): no tiene argumento y carga tu modelo y los datos para el modelo (por ejemplo, inserción de palabras).
    2. train(self, training_directory): toma como input un directorio con datos estructurados de forma arbitraria; ejecuta todo el código necesario para entrenar un modelo. Esta función se llama cuando se ejecuta un proceso de entrenamiento.
    3. evaluate(self, evaluation_directory): toma como input un directorio con datos estructurados de forma arbitraria; ejecuta todo el código necesario para evaluar un modo y devuelve una única puntuación para esa evaluación. Esta función se llama cuando se ejecuta un proceso de evaluación.
    4. save(self): no tiene argumento. Esta función se llama después de cada llamada de la función train para mantener tu modelo.
    5. process_data(self, input_directory): toma un input input_directory con datos estructurados de forma arbitraria. Esta función solo se llama cuando se ejecuta un proceso completo. En la ejecución de un proceso completo, esta función puede realizar transformaciones de datos arbitrarias y puede dividir datos. En concreto, cualquier dato guardado en la ruta a la que apunta la variable de entorno training_data_directory es el input a la función train, y cualquier dato guardado en la ruta a la que apunta la variable de entorno evaluation_data_directory es el input a la función evaluation anterior.

Gestión de tipos de datos

Para hacer que AI Fabric sea más fácil de usar en un flujo de trabajo de RPA, el paquete puede disponer de uno de los tres tipos de input: String, File y Files (establecido durante el tiempo de carga del paquete).

Datos de String

Esta es una secuencia de caracteres. Cualquier dato que pueda ser serializado puede utilizarse con un paquete. Si se utilizan dentro de un flujo de trabajo de RPA, los datos pueden ser serializados por el UiPath Robot (por ejemplo, utilizando una actividad personalizada) y enviados como una cadena. El cargador de paquetes debe haber seleccionado json como tipo de input del paquete.
La deserialización de los datos se realiza en la función predict. A continuación se muestran varios ejemplos útiles para deserializar los datos en Python:
<h1>Robot sends raw string to ML Skill Activity
# E.g. skill_input='a customer complaint'`
def predict(self, skill_input):
  example = skill_input  # No extra processing
    
# Robot sends json formatted string to ML Skill Activity
# E.g skill_input='{'email': a customer complaint', 'date': 'mm:dd:yy'}'
def predict(self, skill_input):
  import json
  example = json.loads(skill_input)
  
# Robot sends json formatted string with number array to ML Skill Activity
# E.g. skill_input='[10, 15, 20]'
def predict(self, skill_input):
  import json
  import numpy as np
  example = np.array(json.loads(skill_input))
  
# Robot sends json formmatted pandas dataframe
# E.g. skill_input='{"row 1":{"col 1":"a","col 2":"b"},
#                    "row 2":{"col 1":"c","col 2":"d"}}'
def predict(self, skill_input):
  import pandas as pd
  example = pd.read_json(skill_input)</h1><h1>Robot sends raw string to ML Skill Activity
# E.g. skill_input='a customer complaint'`
def predict(self, skill_input):
  example = skill_input  # No extra processing
    
# Robot sends json formatted string to ML Skill Activity
# E.g skill_input='{'email': a customer complaint', 'date': 'mm:dd:yy'}'
def predict(self, skill_input):
  import json
  example = json.loads(skill_input)
  
# Robot sends json formatted string with number array to ML Skill Activity
# E.g. skill_input='[10, 15, 20]'
def predict(self, skill_input):
  import json
  import numpy as np
  example = np.array(json.loads(skill_input))
  
# Robot sends json formmatted pandas dataframe
# E.g. skill_input='{"row 1":{"col 1":"a","col 2":"b"},
#                    "row 2":{"col 1":"c","col 2":"d"}}'
def predict(self, skill_input):
  import pandas as pd
  example = pd.read_json(skill_input)</h1>

Datos de File

Esto informa a la actividad de la habilidad ML que realiza llamadas a este modelo que espere una ruta a un archivo. En concreto, la actividad lee el archivo desde el sistema de archivos y lo envía a la función predict como una cadena de bytes serializada. Así, el desarrollador de RPA puede pasar una ruta a un archivo, en lugar de tener que leer y serializar el archivo en el propio flujo de trabajo.
Dentro del flujo de trabajo, el input a la actividad es solo la ruta al archivo. La actividad lee el archivo, lo serializa y envía los bytes del archivo a la función predict. La deserialización de los datos también se realiza en la función predict: el caso general es simplemente leer los bytes directamente en un objeto similar a un archivo de la siguiente manera:
<h1>ML Package has been uploaded with <em>file</em> as input type. The ML Skill Activity
# expects a file path. Any file type can be passed as input and it will be serialized.
def predict(self, skill_input):
  import io
  file_like = io.BytesIO(skill_input)</h1><h1>ML Package has been uploaded with <em>file</em> as input type. The ML Skill Activity
# expects a file path. Any file type can be passed as input and it will be serialized.
def predict(self, skill_input):
  import io
  file_like = io.BytesIO(skill_input)</h1>

La lectura de los bytes serializados como se ve anteriormente es equivalente a abrir un archivo con la marca binaria de lectura activada. Para probar el modelo localmente, lee un archivo como archivo binario. A continuación, se muestra un ejemplo de lectura de un archivo de imagen y su prueba de forma local:

<h1>main.py where model input is an image
class Main(object):
   ...
    
   def predict(self, skill_input): 
      import io
      from PIL import Image
      image = Image.open(io.BytesIO(skill_input))
   ...
  
if__name__ == '<strong>main</strong>':
   # Test the ML Package locally
   with open('./image-to-test-locally.png', 'rb') as input_file:
      file_bytes = input_file.read()
     m = Main()
     print(m.predict(file bytes))</h1><h1>main.py where model input is an image
class Main(object):
   ...
    
   def predict(self, skill_input): 
      import io
      from PIL import Image
      image = Image.open(io.BytesIO(skill_input))
   ...
  
if__name__ == '<strong>main</strong>':
   # Test the ML Package locally
   with open('./image-to-test-locally.png', 'rb') as input_file:
      file_bytes = input_file.read()
     m = Main()
     print(m.predict(file bytes))</h1>
A continuación, se muestra un ejemplo de lectura de un archivo csv y la utilización de una trama de datos Pandas en la función predict:
<h1>main.py where model input is a csv file
class Main(object):
   ...
   def predict(self, skill_input): 
      import pandas as pd
      data frame = pd.read_csv(io.BytesIO(skill_input))
      ...
      
if name == '<strong>main</strong>':
   # Test the ML Package locally
   with open('./csv—to—test—locally.csv', 'rb') as input_file:
      bytes = input_file.read()
   m = Main()
   print(m.predict(bytes))</h1><h1>main.py where model input is a csv file
class Main(object):
   ...
   def predict(self, skill_input): 
      import pandas as pd
      data frame = pd.read_csv(io.BytesIO(skill_input))
      ...
      
if name == '<strong>main</strong>':
   # Test the ML Package locally
   with open('./csv—to—test—locally.csv', 'rb') as input_file:
      bytes = input_file.read()
   m = Main()
   print(m.predict(bytes))</h1>

Datos de Files

Esto informa a AI Fabric de que la actividad de la habilidad ML que hace llamadas a este modelo espera una lista de rutas de archivos. Como en el caso anterior, la actividad lee y serializa cada archivo, además de enviar una lista de cadenas de bytes a la función predict.

Puede enviarse una lista de archivos a una habilidad. Dentro del flujo de trabajo, el input a la actividad es una cadena con rutas a los archivos, separadas por una coma.

Al cargar un paquete, el científico de datos selecciona lista de archivos como tipo de input. A continuación, el científico de datos debe deserializar cada uno de los archivos enviados (como se explica anteriormente). El input de la función predict es una lista de bytes en los que cada elemento de la lista es la cadena de bytes del archivo.

Datos arbitrarios persistentes

En train.py, cualquier proceso ejecutado puede generar datos arbitrarios, llamados output del proceso. Cualquier dato que se escriba en la ruta del directorio desde los artefactos de la variable de entorno persiste y puede emerger en cualquier momento yendo a la página Detalles del proceso. Normalmente, cualquier tipo de gráfico, estadísticas de los trabajos de entrenamiento/evaluación, puede guardarse en el directorio artifacts y se puede acceder a ello desde la IU al final de la ejecución del proceso.
<h1>train.py where some historical plot are saved in ./artifacts directory during Full Pipeline execution
# Full pipeline (using process_data) will automatically split data.csv in 2/3 train.csv (which will be in the directory passed to the train function) and 1/3 test.csv
import pandas as pd
from sklearn.model_selection import train_test_split
class Main(object):
   ...
   def process_data(self, data_directory):
     d = pd.read_csv(os.path.join(data_directory, 'data.csv')) 
     d = self.clean_data(d)
     d_train, d_test = train_test_split(d, test_size=0.33, random_state=42)
     d_train.to_csv(os.path.join(data_directory , 'training', 'train.csv'), index=False)
     d_test.to_csv (os.path.join(data__directory , 'test' , 'test.csv'), index=False)
     self.save_artifacts(d_train, 'train_hist.png', os.environ["artifacts"])
     self.save_artifacts(d_test, 'test_hist.png', os.environ["artifacts"])
  ...
  
   def save_artifacts(self, data, file_name, artifact_directory):
      plot = data.hist() 
      fig = plot[0][0].get_figure()
      fig.savefig(os.path.join(artifact_directory, file_name))
...</h1><h1>train.py where some historical plot are saved in ./artifacts directory during Full Pipeline execution
# Full pipeline (using process_data) will automatically split data.csv in 2/3 train.csv (which will be in the directory passed to the train function) and 1/3 test.csv
import pandas as pd
from sklearn.model_selection import train_test_split
class Main(object):
   ...
   def process_data(self, data_directory):
     d = pd.read_csv(os.path.join(data_directory, 'data.csv')) 
     d = self.clean_data(d)
     d_train, d_test = train_test_split(d, test_size=0.33, random_state=42)
     d_train.to_csv(os.path.join(data_directory , 'training', 'train.csv'), index=False)
     d_test.to_csv (os.path.join(data__directory , 'test' , 'test.csv'), index=False)
     self.save_artifacts(d_train, 'train_hist.png', os.environ["artifacts"])
     self.save_artifacts(d_test, 'test_hist.png', os.environ["artifacts"])
  ...
  
   def save_artifacts(self, data, file_name, artifact_directory):
      plot = data.hist() 
      fig = plot[0][0].get_figure()
      fig.savefig(os.path.join(artifact_directory, file_name))
...</h1>

Utilizando TensorFlow

Durante el desarrollo del modelo, el gráfico de TensorFlow debe cargarse en el mismo hilo que se utilizó para el servicio. Para ello, debe utilizarse el gráfico predeterminado.

A continuación se muestra un ejemplo con las modificaciones necesarias:

import tensorflow as tf
class Main(object):
  def <strong>init</strong>(self):
    self.graph = tf.get_default_graph() # Add this line
    ...
    
  def predict(self, skill_input):
    with self.graph.as_default():
      ...import tensorflow as tf
class Main(object):
  def <strong>init</strong>(self):
    self.graph = tf.get_default_graph() # Add this line
    ...
    
  def predict(self, skill_input):
    with self.graph.as_default():
      ...

Información sobre el uso de la GPU

Cuando la GPU se habilita en el momento de la creación de la habilidad, se implementa en una imagen con el controlador de GPU NVIDIA 418, CUDA Toolkit 10.0 y la biblioteca de runtime CUDA Deep Neural Network Library (cuDNN) 7.6.5.

Ejemplos

Modelo ML simple listo para servir sin entrenamiento

En este ejemplo, el problema de la empresa no requiere reentrenamiento de modelos, por lo que el paquete debe contener el modelo IrisClassifier.sav serializado que se servirá.
  1. Árbol de proyecto inicial (sin main.py y requirements.txt):

    IrisClassifier/
      - IrisClassifier.savIrisClassifier/
      - IrisClassifier.sav
  2. main.py de muestra que se añadirá a la carpeta raíz:

    from sklearn.externals import joblib 
    import json
    class Main(object):
       def <strong>init</strong>(self):
          self.model = joblib.load('IrisClassifier.sav')
       def predict(self, X):
          X = json.loads(X)
          result = self.model.predict_proba(X)
          return json.dumps(result.tolist())from sklearn.externals import joblib 
    import json
    class Main(object):
       def <strong>init</strong>(self):
          self.model = joblib.load('IrisClassifier.sav')
       def predict(self, X):
          X = json.loads(X)
          result = self.model.predict_proba(X)
          return json.dumps(result.tolist())
  3. Añade requirements.txt:

    scikit-learn==0.19.0scikit-learn==0.19.0
Nota: hay algunas restricciones que deben respetarse en las bibliotecas pip. Asegúrese de que puede instalar bibliotecas con los siguientes archivos de restricción:
itsdangerous<2.1.0
Jinja2<3.0.5
Werkzeug<2.1.0
click<8.0.0itsdangerous<2.1.0
Jinja2<3.0.5
Werkzeug<2.1.0
click<8.0.0

Para probar esto, puedes usar el siguiente comando en un entorno nuevo y asegurarte de que todas las bibliotecas se están instalando correctamente:

pip install -r requirements.txt -c constraints.txtpip install -r requirements.txt -c constraints.txt

4. Estructura final de carpetas:

IrisClassifier/
  - IrisClassifier.sav
  - main.py
  - requirements.txtIrisClassifier/
  - IrisClassifier.sav
  - main.py
  - requirements.txt

Modelo simple listo para servir con entrenamiento habilitado

En este ejemplo, el problema de la empresa requiere que el modelo se reentrene. Al desarrollar sobre el paquete descrito anteriormente, es posible que experimentes lo siguiente:

  1. Árbol de proyecto inicial (paquete solo de servicio):

    IrisClassifier/
      - IrisClassifier.sav
      - main.py
      - requirements.txtIrisClassifier/
      - IrisClassifier.sav
      - main.py
      - requirements.txt
  2. train.py de muestra para añadir a la carpeta raíz:

    import pandas as pd 
    import joblib
    class Main(object): 
       def <strong>init</strong>(self):
           self.model_path = './IrisClassifier.sav' 
           self.model = joblib.load(self.model_path)
          
       def train(self, training_directory):
           (X,y) = self.load_data(os.path.join(training_directory, 'train.csv'))
           self.model.fit(X,y)
       def evaluate(self, evaluation_directory):
           (X,y) = self.load_data(os.path.join(evaluation_directory, 'evaluate.csv'))
           return self.model.score(X,y)
       def save(self):
           joblib.dump(self.model, self.model_path)
       def load_data(self, path):
           # The last column in csv file is the target column for prediction.
           df = pd.read_csv(path)
           X = df.iloc[:, :-1].get_values()
           y = df.iloc[:, 'y'].get_values()
           return X,yimport pandas as pd 
    import joblib
    class Main(object): 
       def <strong>init</strong>(self):
           self.model_path = './IrisClassifier.sav' 
           self.model = joblib.load(self.model_path)
          
       def train(self, training_directory):
           (X,y) = self.load_data(os.path.join(training_directory, 'train.csv'))
           self.model.fit(X,y)
       def evaluate(self, evaluation_directory):
           (X,y) = self.load_data(os.path.join(evaluation_directory, 'evaluate.csv'))
           return self.model.score(X,y)
       def save(self):
           joblib.dump(self.model, self.model_path)
       def load_data(self, path):
           # The last column in csv file is the target column for prediction.
           df = pd.read_csv(path)
           X = df.iloc[:, :-1].get_values()
           y = df.iloc[:, 'y'].get_values()
           return X,y
  3. Edita requirements.txt si es necesario:

    pandas==1.0.1
    scikit-learn==0.19.0pandas==1.0.1
    scikit-learn==0.19.0
  4. Estructura de carpeta final (paquete):

    IrisClassifier/
      - IrisClassifier.sav
      - main.py
      - requirements.txt
      - train.pyIrisClassifier/
      - IrisClassifier.sav
      - main.py
      - requirements.txt
      - train.py
    Aviso: Este modelo ahora puede servirse primero y, conforme van entrando al sistema nuevos puntos de datos a través del UiPath Robot o "persona en el ciclo", los procesos de entrenamiento y de evaluación pueden crearse aprovechando train.py.

¿Te ha resultado útil esta página?

Obtén la ayuda que necesitas
RPA para el aprendizaje - Cursos de automatización
Foro de la comunidad UiPath
Uipath Logo White
Confianza y seguridad
© 2005-2024 UiPath. Todos los derechos reservados.