Recomendaciones para TensorFlow: crea el modelo

Este artículo es el primero de una serie de instructivos de varias partes que te muestra cómo implementar un sistema de recomendación de aprendizaje automático (AA) con TensorFlow y AI Platform 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

En este instructivo, se usa Cloud Storage y AI Platform, 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. Selecciona o crea un proyecto de GCP.

    Ir a la página Administrar recursos

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

    Descubre cómo puedes habilitar la facturación

  3. Habilita las Compute Engine and AI Platform API necesarias.

    Habilita las API

Ejecuta 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.

Instala el código

  1. Dirígete a la página Instancias de VM.

    Ir a la página Instancias de VM

  2. En la fila de tu instancia, haz clic en SSH para abrir una terminal basada en el navegador que esté conectada de manera segura a la instancia.

  3. En la ventana de la terminal nueva, actualiza los repositorios de software de tu instancia.

    sudo apt-get update
    
  4. Instala git, bzip2 y unzip.

    sudo apt-get install -y git bzip2 unzip
    
  5. Clona el repositorio de código de muestra:

    git clone https://github.com/GoogleCloudPlatform/tensorflow-recommendation-wals
  6. 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
  7. Instala los paquetes de Python y TensorFlow. Este instructivo se ejecutará en cualquier versión 1.x 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
  8. Descarga el conjunto de datos de MovieLens. Hay varias versiones del conjunto de datos.

    • 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/
    • 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/
    • 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 alto nivel del código se implementa con los siguientes archivos:

mltrain.sh
+ Inicia varios tipos de trabajos de AI Platform. 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 los trabajos de la AI Platform de forma automática.
task.py
+ Analiza los argumentos para el trabajo de AI Platform 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 las calificaciones y los índices de usuarios y artículos. 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 preprocesan, el código pasa la matriz de entrenamiento dispersa al modelo WALS de TensorFlow para que se factorice en el factor de fila X y en el factor de columna Y.

El código de TensorFlow que ejecuta el modelo es muy 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.

Entrena el modelo

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

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

En la Parte 4 de este instructivo, se proporcionan más detalles sobre un sistema que usa el modelo entrenado para realizar predicciones y se 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 con rapidez 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 wals_ml_engine con la opción local.

cd wals_ml_engine
  • Para el conjunto de datos MovieLens 100k, especifica la ruta al archivo de datos 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 --headers:

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

El resultado 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.29
INFO:tensorflow:test RMSE = 1.34

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

El RMSE corresponde al error promedio en las calificaciones previstas en comparación con el conjunto de prueba. En promedio, cada calificación producida por el algoritmo está dentro de ± 1,29 de la calificación real del usuario en el conjunto de pruebas en el conjunto de datos 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.

Borra 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. En la GCP Console, dirígete a la página Proyectos.

    Ir a la página Proyectos

  2. En la lista de proyectos, selecciona el proyecto que deseas borrar y haz clic en Borrar.
  3. En el cuadro de diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

Pasos siguientes

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

Enviar comentarios sobre...