Recomendaciones para TensorFlow: crear el modelo

Este artículo es la primera parte de una serie de instructivos donde se detalla cómo implementar un sistema de recomendaciones de aprendizaje automático (AA) con TensorFlow y Cloud Machine Learning Engine en Google Cloud Platform (GCP). En esta parte, se muestra cómo instalar el código del modelo TensorFlow en un sistema de desarrollo y ejecutarlo en el conjunto de datos MovieLens.

El sistema de recomendaciones en el instructivo utiliza el algoritmo ponderado de mínimos cuadrados alternos (WALS). WALS se incluye en el paquete de contrib.factorization de la base de código de TensorFlow y se usa para factorizar una matriz grande de calificaciones de usuarios y elementos. Para obtener más información sobre WALS, consulta la descripción general.

Este artículo describe el código del modelo en detalle, incluido el procesamiento previo de datos y la ejecución del algoritmo WALS en TensorFlow.

La serie consta de las siguientes partes:

Objetivos

  • Comprender la estructura del código de TensorFlow utilizado para aplicar WALS a la factorización de matriz.
  • Ejecutar el código de muestra de TensorFlow de manera local para realizar recomendaciones en el conjunto de datos MovieLens.

Costos

Este instructivo usa Cloud Storage y Cloud ML Engine, y ambos son servicios facturables. Puedes usar la calculadora de precios para calcular el costo de tu uso previsto. El costo previsto para este instructivo es de $0.15. Si eres un usuario nuevo de GCP, puedes optar por una prueba gratuita.

Antes de comenzar

  1. Select or create a Google Cloud Platform project.

    Go to the Manage resources page

  2. Comprueba que la facturación esté habilitada en tu proyecto.

    Descubre cómo puedes habilitar la facturación

  3. Habilita las Compute Engine y Cloud ML Engine API necesarias.

    Habilita las API

  4. (Opcional) Si deseas ejecutar el instructivo en tu propia computadora (sin usar Cloud Shell), asegúrate de tener Python 2.7 instalado.

Cómo ejecutar el modelo de TensorFlow

Puedes ejecutar los pasos en esta sección en una instancia de Compute Engine con al menos 7 G de memoria, como se muestra en el siguiente procedimiento. Como alternativa, puedes ejecutar los pasos en esta sección en un sistema macOS o Linux local; en ese caso, no es necesario crear una instancia de Compute Engine.

Cómo crear la instancia de Compute Engine

  1. En Google Cloud Platform Console, ve a la página Instancias de VM.

    IR A LA PÁGINA INSTANCIAS DE VM

  2. Haz clic en Crear instancia.

  3. Nombra tu instancia como quieras y elige una zona. Si aún no tienes una zona de preferencia, elige una que esté geográficamente cerca.

  4. En la lista desplegable del tipo de máquina, selecciona 2 CPU virtuales con n1-standard-2.

  5. En la sección Alcances del acceso, selecciona Permitir el acceso total a todas las API.

  6. Haz clic en Crear.

Cómo instalar el código

  1. Conéctate a la instancia nueva. Para obtener más información, consulta Cómo conectarse a las instancias.

  2. En la instancia nueva, clona el repositorio de código de muestra:

    git clone https://github.com/GoogleCloudPlatform/tensorflow-recommendation-wals
  3. Instala miniconda. El código de muestra requiere Python 2.7.

    wget https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh
    bash Miniconda2-latest-Linux-x86_64.sh
  4. Instala los paquetes de Python y TensorFlow. Para este instructivo, usamos la versión 1.4.1 de TensorFlow.

    cd tensorflow-recommendation-wals
    conda create -n tfrec
    conda install -n tfrec --file conda.txt
    source activate tfrec
    pip install -r requirements.txt
    pip install tensorflow==1.4.1
  5. En Cloud Shell, descarga el conjunto de datos MovieLens. Hay varias versiones del conjunto de datos.

    1. Para propósitos de desarrollo, recomendamos usar la versión 100k que contiene 100,000 calificaciones de 943 usuarios en 1,682 artículos. Descárgala con los siguientes comandos:

      curl -O 'http://files.grouplens.org/datasets/movielens/ml-100k.zip'
      unzip ml-100k.zip
      mkdir -p data
      cp ml-100k/u.data data/
    2. Para fines de entrenamiento, recomendamos el conjunto de datos de 1m, que contiene un millón de calificaciones. El formato del conjunto de 1m es un poco diferente al conjunto de 100k. Por ejemplo, el archivo de calificaciones está delimitado con caracteres ::. El código de muestra te permite usar el argumento --delimiter para especificar que el conjunto de datos usa este delimitador.

      curl -O 'http://files.grouplens.org/datasets/movielens/ml-1m.zip'
      unzip ml-1m.zip
      mkdir -p data
      cp ml-1m/ratings.dat data/
    3. Puedes también utilizar el conjunto de datos de 20m con este proyecto. El conjunto de datos se proporciona en un archivo CSV. Si usas este conjunto de datos, debes pasar el marcador --headers, porque el archivo contiene una línea de encabezado.

      curl -O 'http://files.grouplens.org/datasets/movielens/ml-20m.zip'
      unzip ml-20m.zip
      mkdir -p data
      cp ml-20m/ratings.csv data/

Cómo entender el código del modelo

El código del modelo se incluye en el directorio wals_ml_engine. La funcionalidad de nivel alto del código se implementa mediante los siguientes archivos:

mltrain.sh
+ Lanza diversos tipos de trabajos de Cloud ML Engine. Esta secuencia de comandos de shell acepta argumentos para la ubicación del archivo de conjunto de datos, el delimitador utilizado con el propósito de separar los valores en el archivo y si el archivo de datos tiene una línea de encabezado. Se recomienda crear una secuencia de comandos que configure y ejecute automáticamente los trabajos de Cloud ML Engine.
task.py
+ Analiza los argumentos para el trabajo de Cloud ML Engine y ejecuta el entrenamiento.
model.py
+ Carga el conjunto de datos.
  • Crea dos matrices dispersas a partir de los datos, una dirigida a entrenamiento y otra a pruebas. Ejecuta WALS en la matriz de entrenamiento disperso de calificaciones.
wals.py
+ Crea el modelo de WALS.
  • Ejecuta el algoritmo de WALS.
  • Calcula el error de la raíz cuadrada de la media (RMSE) para un conjunto de factores de fila/columna y una matriz de calificaciones.

Cómo el modelo procesa los datos

El código del modelo realiza el procesamiento previo de los datos con el propósito de crear una matriz de calificaciones dispersas y prepararla para la factorización de la matriz. Esto implica los siguientes pasos:

  1. El código del modelo carga los datos de un archivo de texto delimitado. Cada fila contiene una sola calificación.

    ratings_df = pd.read_csv(input_file,
                             sep=args['delimiter'],
                             names=headers,
                             header=header_row,
                             dtype={
                               'user_id': np.int32,
                               'item_id': np.int32,
                               'rating': np.float32,
                               'timestamp': np.int32,
                             })
  2. El código establece un conjunto 0-indexado de ID únicos para usuarios y artículos. Esto garantiza que un ID único corresponda a índices de filas y columnas específicos de la matriz de calificaciones dispersas.

    • Los datos de MovieLens 100k usan ID basadas en 1, en las cuales el índice más bajo del conjunto único es 1. Para normalizar, el código resta uno de cada índice. Desde model.py:

      ratings = ratings_df.as_matrix(['user_id', 'item_id', 'rating'])
      # deal with 1-based user indices
      ratings[:,0] -= 1
      ratings[:,1] -= 1
    • Los conjuntos de datos de 1m y 20m MovieLens omiten algunos ID de usuarios y elementos. Esto crea un problema: tienes que asignar el conjunto de ID de usuarios únicos a un conjunto de índices igual a [ 0 ... num_users-1] y hacer lo mismo con los ID de elementos. La asignación de elementos se realiza mediante el siguiente código [numpy](http://www.numpy.org/). El código crea un arreglo de tamaño [ 0..max_item_id] para realizar la asignación, por lo que si el ID máximo del elemento es muy grande, este método puede usar demasiada memoria.

      np_items = ratings_df.item_id.as_matrix()
      unique_items = np.unique(np_items)
      n_items = unique_items.shape[0]
      max_item = unique_items[-1]
      
      # map unique items down to an array 0..n_items-1
      z = np.zeros(max_item+1, dtype=int)
      z[unique_items] = np.arange(n_items)
      i_r = z[np_items]
    • El código para asignar usuarios es esencialmente el mismo que el código correspondiente a los artículos.

  3. El código del modelo selecciona aleatoriamente un conjunto de pruebas de calificaciones. De forma predeterminada, el 10% de las calificaciones se eligen para el conjunto de pruebas. Estas calificaciones se quitan del conjunto de entrenamiento y se utilizarán para evaluar la precisión predictiva del usuario y los factores del elemento.

    test_set_size = len(ratings) / TEST_SET_RATIO
    test_set_idx = np.random.choice(xrange(len(ratings)),
                                    size=test_set_size, replace=False)
    test_set_idx = sorted(test_set_idx)
    
    ts_ratings = ratings[test_set_idx]
    tr_ratings = np.delete(ratings, test_set_idx, axis=0)
  4. Por último, el código crea una matriz dispersa scipy de manera conjunta (coo_matrix) que incluye los índices de usuarios y artículos y las calificaciones. El objeto coo_matrix actúa como un wrapper para una matriz dispersa. También realiza la validación de los índices de usuarios y calificaciones, verificando errores en el procesamiento previo.

    u_tr, i_tr, r_tr = zip(*tr_ratings)
    tr_sparse = coo_matrix((r_tr, (u_tr, i_tr)), shape=(n_users, n_items))

Cómo se implementa el algoritmo de WALS en TensorFlow

Una vez que los datos se procesan previamente, el código pasa la matriz de entrenamiento dispersa al modelo de WALS de TensorFlow para que se factorice en el factor de fila X y el factor de columna Y.

El código de TensorFlow que ejecuta el modelo es realmente simple, ya que está basado en la clase WALSModel incluida en el módulo contrib.factorization_ops de TensorFlow.

  1. Un objeto SparseTensor se inicializa con ID de usuarios y de elementos como índices y con las calificaciones como valores. Desde wals.py:

    input_tensor = tf.SparseTensor(indices=zip(data.row, data.col),
                                    values=(data.data).astype(np.float32),
                                    dense_shape=data.shape)

    La variable de datos es el objeto coo_matrix de las calificaciones de entrenamiento creadas en el paso de procesamiento previo.

  2. En el modelo se crea una instancia:

    model = factorization_ops.WALSModel(num_rows, num_cols, dim,
                                        unobserved_weight=unobs,
                                        regularization=reg,
                                        row_weights=row_wts,
                                        col_weights=col_wts)
  3. Los factores de fila y los tensores de factores de columna se crean automáticamente por la clase WALSModel y se recuperan para que puedan evaluarse después de factorizar la matriz:

    # retrieve the row and column factors
    row_factor = model.row_factors[0]
    col_factor = model.col_factors[0]
  4. El proceso de formación ejecuta el siguiente bucle dentro de una sesión de TensorFlow con el método simple_train en wals.py:

    row_update_op = model.update_row_factors(sp_input=input_tensor)[1]
    col_update_op = model.update_col_factors(sp_input=input_tensor)[1]
    
    sess.run(model.initialize_op)
    sess.run(model.worker_init)
    for _ in xrange(num_iterations):
        sess.run(model.row_update_prep_gramian_op)
        sess.run(model.initialize_row_update_op)
        sess.run(row_update_op)
        sess.run(model.col_update_prep_gramian_op)
        sess.run(model.initialize_col_update_op)
        sess.run(col_update_op)
  5. Después de que se hayan ejecutado las iteraciones de num_iterations, los tensores de factor de filas y columnas se evalúan en la sesión con el propósito de producir arreglos numpy para cada factor:

    # evaluate output factor matrices
    output_row = row_factor.eval(session=session)
    output_col = col_factor.eval(session=session)

Estos arreglos de factores se utilizan para calcular el RMSE en el conjunto de evaluaciones de prueba. Los dos arreglos también se guardan en el directorio de salida en formato numpy.

Cómo entrenar el modelo

En este contexto, el entrenamiento del modelo implica factorizar una matriz dispersa de calificaciones en una matriz de factores de usuario X y una matriz de factores de elementos Y. Los factores de elementos y usuarios guardados se pueden utilizar como modelo base para un sistema de recomendaciones.

Este sistema toma un usuario como entrada, recupera el vector de factores de usuarios para ese usuario de X, multiplica ese vector por todos los factores de elementos Y, y muestra los elementos N principales de acuerdo con la calificación predicha.

La Parte 4 de este instructivo proporciona más detalles sobre un sistema que usa el modelo entrenado para realizar predicciones y muestra cómo implementar este sistema en GCP.

Cómo entrenar el modelo de manera local

Entrenar el modelo de manera local es útil para propósitos de desarrollo. Te permite probar rápidamente los cambios de código, incluidos los puntos de interrupción para una depuración fácil. Para ejecutar el modelo en Cloud Shell o desde tu sistema local, ejecuta la secuencia de comandos mltrain.sh desde el directorio del código con la opción local.

  • Para el conjunto de datos de MovieLens 100k, especifica la ruta al archivo de datos de 100k:

    ./mltrain.sh local ./../data/u.data
  • Para el conjunto de datos MovieLens 1m, incluye la opción --delimiter y especifica la ruta al archivo de datos 1m:

    ./mltrain.sh local data/ratings.dat --delimiter ::
  • Para el conjunto de datos MovieLens 20m, usa las opciones --delimiter y --header:

    ./mltrain.sh local data/ratings.csv --header --delimiter ,

La salida del trabajo de entrenamiento muestra el RMSE calculado en el conjunto de pruebas. Para el conjunto de datos de 1m, y cuando se utilizan los hiperparámetros predeterminados especificados en el código fuente, la salida debería ser del siguiente modo:

INFO:tensorflow:Train Start: <timestamp>
...
INFO:tensorflow:Train Finish: <timestamp>
INFO:tensorflow:train RMSE = 1.06
INFO:tensorflow:test RMSE = 1.11

Para obtener más detalles, consulta la Parte 2.

El RMSE corresponde al error promedio en las calificaciones predichas en comparación con el conjunto de pruebas. En promedio, cada calificación producida por el algoritmo está dentro de ± 1.11 de la calificación real del usuario en el conjunto de pruebas en el conjunto de datos de 1m. El algoritmo WALS tiene un rendimiento mucho mejor con los ajustes de los hiperparámetros, como se muestra en la Parte 2 de esta serie.

Limpieza

Si creaste una instancia de Compute Engine para ejecutar TensorFlow, debes detenerla con el propósito de evitar incurrir en cargos en tu cuenta de GCP. Esta instancia no se usa en la Parte 2 de esta serie. Sin embargo, la instancia de Compute Engine se requiere para la Parte 3 y la Parte 4.

Cómo detener la instancia de Compute Engine

  1. En GCP Console, abre la página de lista de instancias de VM de Compute Engine.
  2. Selecciona el nombre de la instancia.
  3. Haz clic en Detener y confirma la operación.

Cómo borrar el proyecto

La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.

Para borrar el proyecto, haz lo siguiente:

  1. In the GCP Console, go to the Projects page.

    Go to the Projects page

  2. In the project list, select the project you want to delete and click Delete .
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Pasos siguientes

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...