Apache Mahout: Aprendizaje escalable con máquina para todos

Actualícese sobre mejoras Mahout y encuentre cómo escalar Mahout en la nube

Grant Ingersoll, quien confirma Apache Mahout, le lleva a alta velocidad por la versión actual de la biblioteca de aprendizaje mediante máquina Mahout y le lleva paso a paso por un ejemplo sobre cómo implementar y escalar algunos de los algoritmos Mahout más populares.

Grant Ingersoll, Chief Scientist, Lucid Imagination

Grant IngersollGrant Ingersoll es co-fundador y Científico Jefe en Lucid Imagination, así como el co-fundador de Apache Mahout. Grant es co-autor de Taming Text (próximamente, de Manning Publications).



13-02-2012

Dos años parecería ser una eternidad en el mundo del software. En los últimos dos años hemos visto el aumento meteórico de los medios sociales, la comercialización de computación en clústeres a gran escala (gracias a actores como Amazon y RackSpace) y el crecimiento masivo de los datos y de nuestra capacidad para ser conscientes de ello. Y han pasado dos años desde que "Introducing Apache Mahout" se publicó por primera vez en developerWorks. Desde entonces, la comunidad Mahout — y el código base y capacidades del proyecto — han crecido significativamente. Mahout también ha visto una acogida significativa por compañías grandes y pequeñas en todo el mundo.

En mi artículo previo sobre Mahout, introduje algunos de los conceptos de aprendizaje por máquina y los fundamentos de usar la suite de algoritmos Mahout. Los conceptos que he presentado todavía son válidos, pero la suite de algoritmos ha cambiado significativamente. En lugar de regresar a lo básico, este artículo se enfoca en el estado actual de Mahout y en cómo escalar Mahout en todo un clúster de computación usando el servicio EC2 de Amazon y un conjunto de datos que comprende 7 millones de documentos de e-mail. Para un repaso de los fundamentos, consulte Recursos, en particular, el libro Mahout in Action . También voy a suponer sus conocimientos básicos sobre Apache Hadoop y sobre el paradigma Map-Reduce. (Vea Recursos para más información sobre Hadoop).

Podcast: Grant Ingersoll sobre aprendizaje por máquina Apache Mahout

En este podcast, el confirmador y co-fundador de Apache Mahout, Grant Ingersoll, presenta el aprendizaje por máquina, los conceptos involucrados, y explica cómo se aplica para aplicaciones del mundo real.

Estado de Mahout

Mahout ha avanzado un largo trayecto en poco tiempo. Aunque el proyecto todavía se enfoca en lo que me gusta llamar las "tres Cs" — el filtrado colaborativo (recomendadores), almacenamiento en clúster y clasificación — , también tiene otras capacidades adicionadas. Voy a destacar algunas expansiones y mejoras en dos áreas: algoritmos principales (implementaciones) para aprendizaje por máquina y soporte de la infraestructura, incluyendo herramientas de entrada/salida, puntos de integración con otras bibliotecas, y más ejemplos para referencia. Sin embargo, observe que este estado no está completo. Además, el espacio limitado de este artículo significa que solo puedo ofrecer algunas frases sobre cada una de las mejoras. Yo animo a los lectores para que encuentren más información leyendo la sección News del sitio web de Mahout y la notas de release para cada uno de los releases Mahout.

Algoritmos, algoritmos, algoritmos

Después de intentar resolver problemas de aprendizaje con máquina durante un rato, uno rápidamente se da cuenta de que ningún algoritmo es adecuado para cada situación. Para ese fin, Mahout ha añadido algunas implementaciones nuevas. La Tabla 1 contiene mi posición sobre las nuevas y más significativas implementaciones algorítmicas en Mahout, así como algunos casos de uso de ejemplo. Pondré algunos de estos algoritmos a trabajar más adelante en este artículo.

Tabla 1. Nuevos algoritmos en Mahout
AlgoritmoDescripción breveCaso de uso
Regresión logística, resuelta por gradiente estocástico descendiente (SGD)Clasificador brillante, rápido, simple y secuencial, capaz de aprendizaje on-line en entornos exigentes Recomiende publicidad a los usuarios, clasifique texto en categorías
Modelos ocultos de Markov (HMM)Implementaciones secuenciales y paralelas del algoritmo clásico de clasificación diseñado para modelar procesos del mundo real cuando el proceso de generación subyacente es desconocido Etiquetado de texto parte-del-discurso; reconocimiento del discurso
Descomposición de valor singular (SVD)Diseñado para reducir el ruido en matrices grandes, haciendo con esto que sean más pequeñas y que sea más fácil trabajar con ellas Como precursor del almacenamiento en clúster, los recomendadores y la clasificación para realizar selección de recursos automáticamente
Almacenamiento en clúster DirichletEnfoque de almacenamiento en clúster basado en modelo, que determina la propiedad con base en si los datos se ajustan al modelo subyacente Útil cuando los datos tienen sobreposición o jerarquía
Almacenamiento en clúster espectralEs una familia de enfoques similares que usa un enfoque basado en gráficas para determinar la membresía a clúster Como todos los algoritmos de almacenamiento en clúster, es útil para explorar conjuntos de datos grandes y no vistos
Almacenamiento en clúster MinhashUtiliza una estrategia de hash para agrupar elementos similares, produciendo así clústeresIgual a otros enfoques de clúster
Numerosas mejoras de recomendadorCo-ocurrencia distribuida, SVD, mínimos cuadrados alternantesSitios de citas, e-commerce, recomendaciones de películas o de libros
ColocacionesImplementación de colocación reducida por correlacionamientoEncontrando frases estadísticamente interesantes en texto

Mahout también ha añadido un número de algoritmos matemáticos de bajo nivel (vea el paquete matemático) que los usuarios pueden encontrar útil. Muchos de estos son usados por los algoritmos descritos en la Tabla 1, pero están diseñados para ser de propósito general y por lo tanto pueden adaptarse a sus necesidades.

Mejorando y expandiendo la infraestructura de Mahout

Mahout's command line

Hace un tiempo, Mahout publicó un script shell que facilita la ejecución de programas Mahout (aquellos que tienen un main()), al encargarse de rutas de clase, variables de entorno y otros elementos de configuración. El script — llamado mahout — está en el directorio $MAHOUT_HOME/bin.

Mientras más personas usen un proyecto de fuente abierta y trabajen para hacer que l código del proyecto funcione con su código, más infraestructura se va incorporando. Para Mahout, esta evolución ha llevado a numerosas mejoras. La más notable es una interfaz de línea de comando bastante mejorada y consistente, la cual hace que sea más fácil ingresar y ejecutar tareas localmente y en Apache Hadoop. Este nuevo script está ubicado en el directorio dentro del directorio Mahout de nivel superior (al cual nos referiremos como $MAHOUT_HOME en adelante). (Vea la barra lateral Mahout's command line ).

Dos componentes clave de cualquier biblioteca de aprendizaje por máquina son una biblioteca matemática confiable y un paquete de colecciones eficiente. La biblioteca matemática (ubicada en el módulo matemático bajo $MAHOUT_HOME) proporciona una variedad de funcionalidades — que van desde estructuras de datos que representan vectores, matrices y operadores relacionados para manipularlos para generar números aleatorios y estadísticas útiles como la probabilidad de registro (vea Recursos). La biblioteca de recursos de Mahout consiste en estructuras de datos similares a las proporcionadas por colecciones Java (Map, List y demás) excepto que estas soportan primitivas Java de forma nativa como int, float y double en lugar de sus contrapartes Object de Integer, Float y Double. Esto es importante porque cada bit (con intención de juego de palabras) cuenta cuando usted está tratando con conjuntos de datos que pueden tener millones de recursos. Además, el costo de boxear entre los primitivos y sus contrapartes Object es prohibitivo a gran escala.

Mahout también ha introducido un nuevo módulo de integración que contiene código que está diseñado para complementar o extender las capacidades núcleo de Mahout, pero no es requerido por todas ni en todas las situaciones. Por ejemplo, el código recomendador (filtrado colaborativo) ahora tiene soporte para almacenar su modelo e una base de datos (vía JDBC), MongoDB, o Apache Cassandra (vea Recursos). El módulo de integración también contiene numerosos mecanismos para obtener datos en formatos Mahout, así como la evaluación de los resultados que se producen. Por ejemplo, incluye herramientas que pueden convertir directorios llenos de archivos de texto en el formato de vector Mahout (vea el paquete org.apache.mahout.text en el módulo de integración).

Finalmente, Mahout tiene algunos nuevos ejemplos, que van desde calcular recomendaciones con el conjunto de datos Netflix hasta almacenamiento de clúster de música Last.fm y muchas otras. Adicionalmente, el ejemplo que desarrollé para este artículo también ha sido añadido a la base de código de Mahout. Le animo a que pase algo de tiempo explorando más detalladamente el módulo de ejemplos (ubicado en $MAHOUT_HOME/examples).

Ahora que usted está al día sobre el estado de Mahout, es hora de profundizar en el evento principal: cómo escalar Mahout.


Escalando Mahout en la nube

Hacer que Mahout se escale efectivamente no es tan fácil como simplemente añadir más nodos a un clúster Hadoop. Factores como la elección de algoritmo, el número de nodos, la selección de recursos y la escasez de datos — así como los sospechosos usuales de memoria, ancho de banda y velocidad de procesador — todos juegan un papel al momento de determinar cuan efectivamente se puede escalar Mahout. Para motivar la discusión, trabajaré mediante un ejemplo de ejecutar algunos algoritmos Mahout sobre un conjunto de datos de archivos de correo, públicamente disponibles, de la Apache Software Foundation (ASF) usando la infraestructura de computación EC2 de Amazon y Hadoop, donde sea apropiado (vea Recursos).

Cada una de las subsecciones después de la configuración observa algunos de los problemas clave del escalamiento de Mahout y explora la sintaxis de ejemplo en EC2.

Configuración

La configuración para los ejemplos involucra dos partes: una configuración local y una configuración EC2 (nube). Para ejecutar los ejemplos usted necesita:

  1. Apache Maven 3.0.2 o superior.
  2. Git sistema de control de versiones (es posible que usted también desee tener una cuenta Github ).
  3. Un sistema operativo basado en *NIX como Linux o Apple OS X. Cygwin puede funcionar para Windows®, pero yo no lo he comprobado.

Para la configuración local ejecute la siguiente línea de comando:

  1. mkdir -p scaling_mahout/data/sample
  2. git clone git://github.com/lucidimagination/mahout.git mahout-trunk
  3. cd mahout-trunk
  4. mvn install (añada -DskipTests si desea saltarse las pruebas Mahout, las cueles pueden tardar un rato en ejecutarse)
  5. cd bin
  6. /mahout (usted debe estar viendo un listado de elementos que usted puede ejecutar, como kmeans)

Esto debe hacer que todo el código que usted necesita se compile e instale correctamente. De forma separada, descargue los datos de muestra, guárdelos en el directorio scaling_mahout/data/sample, y desempáquelos (tar -xf scaling_mahout.tar.gz). Para propósitos de prueba, este es un pequeño subconjunto de los datos que usted utilizará en EC2.

Para configurarse en Amazon, usted necesita una cuenta Amazon Web Services (AWS) (anotando, su clave secreta, clave de acceso e ID de cuenta) y conocimientos básicos sobre cómo funcionan los servicios EC2 de Amazon y Elastic Block Store (EBS). Siga la documentación que hay en el sitio web de Amazon para obtener el acceso necesario.

Dejando de lado los requisitos previos, es hora de iniciar un clúster. Probablemente sea mejor comenzar con un nodo individual y luego añadir nodos según sea necesario. Y note, desde luego, que la ejecución en EC2 cuesta dinero. Por lo tanto, asegúrese de apagar todos sus nodos cuando haya terminado la ejecución.

Para iniciar un clúster para usarlo con los ejemplos en el artículo, siga estos pasos:

  1. Descargue Hadoop 0.20.203.0 desde un espejo ASF y desempáquelo localmente.
  2. cd hadoop-0.20.203.0/src/contrib/ec2/bin
  3. Abra hadoop-ec2-env.sh en un editor y:
    1. Complete su AWS_ACCOUNT_ID,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,EC2_KEYDIR, KEY_NAME y PRIVATE_KEY_PATH. Consulte la página "Use an Existing Hadoop AMI" el wiki de Mahout para más información (vea Recursos).
    2. Defina HADOOP_VERSION como 0.20.203.0.
    3. Defina S3_BUCKET como 490429964467.
    4. Defina ENABLE_WEB_PORTS=true.
    5. Defina INSTANCE_TYPE como m1.xlarge como mínimo.
  4. Abra hadoop-ec2-init-remote.sh en un editor y:
    1. En la sección que crea hadoop-site.xml, añada la siguiente propiedad:
      <property>
      <name>mapred.child.java.opts></name>
      <value>-Xmx8096m></value>
      </property>
      Nota: Si usted desea ejecutar clasificación, necesitará usar una instancia más grande y más memoria. Yo usé instancias doble X-Large y 12GB de memoria dinámica.
    2. Cambie mapred.output.compress por false.
  5. Inicie su clúster:
    ./hadoop-ec2 launch-cluster mahout-clustering X
    X es el número de nodos que usted desea lanzar (por ejemplo, 2 o 10). Sugiero comenzar con un valor pequeño y luego añadir nodos a medida que su nivel de confort aumente. Esto también le ayudará a controlar sus costos.
  6. Cree un volumen EBS para el ASF Public Data Set (Snapshot: snap--17f7f476) y anéxelo a su instancia de nodo principal (esta es la instancia en el grupo de seguridad mahout-clustering-master) en /dev/sdh. (Vea Recursos para enlaces hacia instrucciones detalladas en la documentación EC2 on-line.)
    1. Si está usando API de línea de comandos EC2 (vea Recursos), usted puede hacer:
      1. ec2-create-volume --snapshot snap-17f7f476 --z ZONE
      2. ec2-attach-volume $VOLUME_NUMBER -i $INSTANCE_ID -d /dev/sdh, donde $VOLUME_NUMBER es resultado del paso de creación de volumen y $INSTANCE_ID es el ID del nodo principal que fue lanzado por el comando de inicio de clúster
    2. En cualquier otro caso, usted puede hacer esto mediante la consola web AWS.
  7. Cargue el script setup-asf-ec2.sh (vea Descargas) en la instancia principal:
    ./hadoop-ec2 push mahout-clustering $PATH/setup-asf-ec2.sh
  8. Inicie sesión en su clúster:
    ./hadoop-ec2 login mahout-clustering
  9. Ejecute el script shell para actualizar su sistema, instale Git y Mahout, y limpie algunos de los archivos para facilitar su ejecución:
    ./setup-asf-ec2.sh

Con los detalles de configuración de lado, el siguiente paso es ver qué sucede al poner algunos de los algoritmos más populares de Mahout en producción y escalarlos. Me enfocaré principalmente en las tareas efectivas de escalamiento, pero a lo largo del camino cubriré algunas preguntas sobre la selección de recursos y por qué realicé ciertas elecciones.

Recomendaciones

El filtrado colaborativo es una de las capacidades más populares y fáciles de usar de Mahout, por lo que es un punto de partida lógico para una discusión sobre cómo escalar Mahout. Recuerde que estamos trabajando con archivos de correo desde el ASF. En el caso de una tarea de recomendación, una posibilidad interesante es construir un sistema que recomiende a un usuario secuencias de correo potencialmente interesantes, con base en las secuencias que otros usuarios hayan leído. Para configurar esto como un escenario colaborativo de filtrado, definiré el elemento que el sistema está recomendando como la secuencia de e-mail, según lo determinado por Message-ID y References en el encabezado del e-mail. El usuario será definido por la dirección From en el mensaje de e-mail. En otras palabras, me interesa quién ha instanciado o respondido a su mensaje de e-mail. En cuanto al valor de preferencia en sí, simplemente voy a tratar la interacción con la secuencia de e-mail como una preferencia booleana: activada si el usuario X interactúa con la secuencia Y, y desactivada si no. El efecto causado por esta selección es que debemos usar una métrica de similitud que funcione con preferencias booleanas, como las similitudes Tanimoto o de probabilidad de registro. Esto normalmente permite cálculos más rápidos, y probablemente reduce la cantidad de ruido en el sistema, pero su kilometraje puede variar y tal vez usted desee experimentar con diferentes pesos.

Secuencias, Message-ID y el enemigo de los buenos

Observe que mi aproximación al manejo de secuencias de mensaje no es perfecto, debido a la práctica algo común de secuestro de secuencias en las listas de correo. El secuestro de secuencias sucede cuando alguien comienza un mensaje (esto es, uno con un nuevo asunto/tema) sobre la lista, respondiendo a un mensaje existente, pasando así la referencia del mensaje original. En lugar de intentar trabajar con este problema aquí, simplemente he optado por ignorarlo, pero una solución real necesitaría afrontar el problema y resolverlo. Así, estoy optando por "lo suficientemente bueno" en lugar de perfección.

Como el recurso de selección es sencillo cuando se trata de filtrado colaborativo (usuario, elemento, preferencia opcional), podemos avanzar para observar los pasos para llevar nuestro contenido desde archivos de correo en bruto a que se ejecuten localmente y luego a que se ejecuten en la nube. Observe que en muchas circunstancias el último paso a menudo no es necesario, porque es posible obtener resultados lo suficientemente rápido en una máquina individual, sin añadir la complejidad de Hadoop a la ecuación. Como un estimado general, los puntos de comparación de la comunidad Mahout sugieren que uno puede proporcionar recomendaciones razonablemente de hasta 100 millones de usuarios e un solo nodo. En el caso de los datos de e-mail, en realidad estos no son tantos elementos (apenas 7 millones de mensajes), pero voy a seguir adelante y a ejecutar en Hadoop de todas formas.

Para ver el código en acción, he empaquetado los pasos necesarios en un script shell ubicado en el archivo $MAHOUT_HOME/examples/bin/build-asf-email.sh. Ejecute el script shell, ingresando la ubicación de sus datos de entrada y a dónde le gustaría recibir el resultado, como en:

./build-asf-email.sh ./scaling_mahout/data/sample/content ./scaling_mahout/output/

Cuando se le consulte, seleccione recommender (opción 1) y siéntese y disfrute de la minuciosidad del resultado de registro de Mahout y Hadoop. Cuando termine, usted verá algo similar al Listado 1:

Listado 1. Resultado de muestra del código recommender
11/09/08 09:57:37 INFO mapred.JobClient: Reduce output records=2072
11/09/08 09:57:37 INFO mapred.JobClient: Spilled Records=48604
11/09/08 09:57:37 INFO mapred.JobClient: Map output bytes=10210854
11/09/08 09:57:37 INFO mapred.JobClient: Combine input records=0
11/09/08 09:57:37 INFO mapred.JobClient: Map output records=24302
11/09/08 09:57:37 INFO mapred.JobClient: SPLIT_RAW_BYTES=165
11/09/08 09:57:37 INFO mapred.JobClient: Reduce input records=24302
11/09/08 09:57:37 INFO driver.MahoutDriver: Program took 74847 ms

Los resultados de este trabajo serán todas las recomendaciones para todos los usuarios en os datos de entrada. Los resultados son almacenados en un subdirectorio del directorio de resultado llamado prefs/recommendations y contienen uno o más archivos de texto cuyos nombres comienzan con part-r-. (Así es como Hadoop entrega los archivos). Examinar uno de estos archivos revela, con una salvedad, las recomendaciones formateadas como:

user_id [item_id:score, item_id:score, ...]

Por ejemplo, user ID 25 tiene recomendaciones para IDs de e-mail 26295 y 35548. La salvedad es simplemente que user_id e item_id no son los ID originales, sino correlacionamientos de los originales hacia enteros. Para ayudarle a entender por qué se hace esto, es hora de explicar lo que sucede realmente cuando se ejecuta el script shell.

Hay tres pasos involucrados en la producción de resultados de recomendación:

  1. Convertir los archivos mbox brutos al formato SequenceFile de Hadoop usando SequenceFilesFromMailArchives de Mahout.
  2. Extraer el ID de mensaje y la firma From de los mensajes y dar los resultados en un formato que Mahout pueda entender.
  3. Ejecutar la clase RecommenderJob de Mahout.

No cubriré el Paso 1 más allá de simplemente sugerir que los lectores interesados se refieran al código.

Para el Paso 2, se realizó un poco más de trabajo para extraer de los archivos las piezas de información pertinentes, IDs, referencias de respuesta y las direcciones From) y para luego almacenarlos como triples (From ID, Message-ID, preferencia) para que el RecommenderJob los consuma. El proceso para esto está orientado por MailToPrefsDriver, el cual consiste en tres trabajos Map-Reduce:

  1. Crear un diccionario que correlacione la Message-ID basada en secuencia con una única long.
  2. Crear un diccionario que correlacione la dirección de e-mail From con una única long.
  3. Extraer Message-ID, References y From; correlacionarlas con longs usando los diccionarios de los Pasos 1 y 2; y dar como resultado los triple en un archivo de texto.

Después de todo esto, es hora de generar algunas recomendaciones. Para crear recomendaciones, el RecommenderJob realiza los pasos registrados en la Figura 1:

Flujo de trabajo de Recommender

El paso principal durante el trabajo pesado del flujo de trabajo es el paso "calculate co-occurrences". Este paso es responsable de hacer comparaciones por pares a lo largo de toda la matriz, en busca de similitudes. Como un adicional, este paso (realizado por elRowSimilarityJob de Mahout) generalmente es útil para realizar cómputos por pares entre cualquier fila de una matriz (no solo clasificaciones/revisiones).

RecommenderJob es invocado en el script shell con el comando:

bin/mahout recommenditembased --input $PREFS_REC_INPUT --output $RECS_OUT --tempDir
    $PREFS_TMP --similarityClassname SIMILARITY_LOGLIKELIHOOD

El primer argumento de le dice a Mahout cuál comando ejecutar (RecommenderJob); muchos de los otros (input/output/tempDir) se explican por sí mismos. El similarityClassname le dice a Mahout cómo calcular la similitud entre elementos cuando se calculan co-ocurrencias. Y he decidido utilizar probabilidad de registro por su simplicidad, velocidad y calidad.

En cuanto se obtienen los resultados, es hora de evaluarlos. Mahout incluye un paquete de evaluación (org.apache.mahout.cf.taste.eval) con herramientas útiles que le permiten examinar la calidad de los resultados. Desafortunadamente, estos no funcionan con los algoritmos basados en Hadoop, pero pueden ser útiles en otros casos. Estas herramientas contienen un porcentaje de los datos como datos de prueba y luego los comparan contra lo que produjo el sistema, para juzgar la calidad.

Eso que realmente esta todo allí es para generar recomendaciones — y la parte hermosa de esto está en que luego puede ejecutarse directamente en el clúster. Para hacer eso, inicie sesión en el clúster EC2 que configuró antes y ejecute el mismo script shell (esto está en /mnt/asf-email/mahout-trunk/examples/bin) como antes. A medida que usted añada nodos a su clúster, usted debe ver una reducción en el tiempo en general que se tarde en ejecutar los pasos. Como ejemplo, ejecutar el conjunto completo de datos en una máquina local tarda más de tres días en completarse. Ejecutar en un clúster de 10 nodos en EC2 tardó apenas 60 minutos para la tarea de recomendación principal, más el trabajo preparatorio de convertir el e-mail en un formato utilizable.

La última pieza, la cual he dejado como un ejercicio para el lector, es consumir las recomendaciones como parte de una aplicación. Normalmente, en cuanto hay un número significativo de elementos y de usuarios en el sistema, las recomendaciones se generan periódicamente — normalmente puede ser entre cada hora y a diario, dependiendo de las necesidades de negocios. Después de todo, en cuanto un sistema alcanza cierta cantidad de usuarios y recomendaciones, los cambios a las recomendaciones producidas serán mucho más sutiles.

Ahora observemos la clasificación de mensajes de e-mail, que en algunos casos puede pensarse como un sistema de recomendación contextual.

Clasificación

Mahout cuenta con varios algoritmos de clasificación, la mayoría de los cuales (con una excepción notable, el gradiente estocástico descendiente) están escritos para ejecutarse en Hadoop. Para los propósitos de este artículo, utilizaré el clasificador simplista de bahías, con el cual comenzarán muchas personas y el cual a menudo produce resultados razonables mientras se escala efectivamente. Para más detalles sobre otros clasificadores, consulte los capítulos apropiados en Mahout in Action o la sección Algorithms en el wiki de Mahout (vea Recursos).

Los documentos de e-mail están descompuestos por proyectos Apache (Lucene, Mahout, Tomcat, y demás) y normalmente cada proyecto tiene dos o más listas de correo (usuario, desarrollo, etc). Dado que el conjunto ASF de datos de correo está particionado por proyecto, un problema de clasificación lógica es intentar predecir el proyecto al cual se deberá enviar un nuevo mensaje entrante. Por ejemplo, ¿un nuevo mensaje pertenece a la lista de correos electrónicos Lucene o a la lista de correos electrónicos Tomcat?

Para que los algoritmos de clasificación de Mahout funcionen, se debe entrenar un modelo para que represente los patrones que serán identificados, y luego probados de nuevo contra un subconjunto de los datos. En la mayoría de los problemas de clasificación, una o más personas deben pasar y anotar manualmente un subconjunto de los datos que serán usados en el entrenamiento. No obstante y afortunadamente, en este caso el conjunto de datos ya está separado por proyecto, por lo que no hay necesidad de anotación manual — aunque estoy contando con el hecho de que las personas generalmente seleccionan la lista correcta cuando están enviando e-mail, que todos sabemos que no siempre es el caso.

Tal como en el caso del recomendador, los pasos necesarios son pre-empaquetados en el script build-asf-email.sh y son ejecutados cuando se selecciona la opción 3 (y luego la opción 1 en el segundo prompt para bahías simplistas estándar) desde el menú. De forma similar a las recomendaciones, parte del trabajo de escalar el código está en la preparación de los datos que serán consumidos. Para clasificación de texto, esto principalmente significa codificar los recursos y luego crear vectores a partir de los recursos, pero también incluye configurar conjuntos de entrenamiento y prueba. El conjunto completo de pasos realizados es:

  1. Convertir los archivos mbox brutos al formato SequenceFile de Hadoop usando SequenceFilesFromMailArchives de Mahout. (Observe que las opciones de tiempo de ejecución son ligeramente diferentes aquí).
    bin/mahout org.apache.mahout.text.SequenceFilesFromMailArchives --charset "UTF-8" 
        --body --subject --input $ASF_ARCHIVES --output $MAIL_OUT
  2. Convertir las entradas SequenceFile en vectores escasos y modificar las etiquetas:
    1. bin/mahout seq2sparse --input $MAIL_OUT --output $SEQ2SP --norm 2 --weight TFIDF --namedVector --maxDFPercent 90 --minSupport 2 --analyzerName org.apache.mahout.text.MailArchivesClusteringAnalyzer
    2. bin/mahout org.apache.mahout.classifier.email.PrepEmailDriver --input $SEQ2SP --output $SEQ2SPLABEL --maxItemsPerLabel 1000
  3. Dividir la entrada en conjuntos de entrenamiento y de prueba:
    bin/mahout split --input $SEQ2SPLABEL --trainingOutput $TRAIN --testOutput $TEST
        --randomSelectionPct 20 --overwrite --sequenceFiles
  4. Ejecutar los clasificadores simplistas de bahía para entrenamiento y prueba:
    1. bin/mahout trainnb -i $TRAIN -o $MODEL -extractLabels --labelIndex $LABEL
    2. bin/mahout testnb -i $TEST -m $MODEL --labelIndex $LABEL

Los dos pasos principales que vale la pena destacar son el Paso 2 y el Paso 4. El Paso 2a es la selección primaria de recurso y paso de codificación, y un número de los parámetros de entrada controlan cómo será representado el texto de entrada como pesos en los vectores. La Tabla 2 desglosa las opciones relacionadas con selección de recursos del Paso 2:

Tabla 2. Opciones de selección de recursos para creación de vector
OpciónDescripciónEjemplos y notas
--normEl norm modifica todos los vectores mediante una función que calcula su longitud (norm)1 norm = Manhattan distance, 2 norm = Euclidean distance
--weightCalcula el peso de cualquier recurso dado bien sea como TF-IDF (frecuencia term, frecuencia inversa de documento), o simplemente como Term Frequency TF-IDF es un esquema de peso común en búsqueda y aprendizaje por máquina para representar texto como vectores.
--maxDFPercent, --minSupportEstas dos opciones descargan términos que son o muy frecuentes (max) o que no son lo suficientemente frecuentes a lo largo de la colección de documentos Es útil en la descarga automática de términos comunes o muy poco frecuentes que añaden poco valor al cálculo
--analyzerNameEs una clase de analizador Apache Lucene que puede utilizarse para aplicar token, contener remover o cambiar de cualquier otra forma las palabras en el documento Consulte Recursos para aprender más sobre Lucene

El proceso de análisis del Paso 2a justifica profundizar un poco más, dado que está haciendo gran parte del trabajo pesado necesario para la selección de recursos. Un Analyzer Lucene está compuesto por una clase Tokenizer y cero o más clases TokenFilter . El Tokenizer es responsable por descomponer la entrada original en cero o más tokens (como palabras). Las instancias TokenFilter están encadenadas juntas para modificar luego los tokens producidos por el Tokenizer. Por ejemplo, el Analyzer usado en el ejemplo:

  1. 'Tokeniza' en espacio en blanco, más algunos casos extremos para puntuación.
  2. Pone todos los token en minúscula.
  3. Convierte caracteres no-ASCII en ASCII, donde sea posible convirtiendo acentos diacríticos y demás.
  4. Desecha tokens con más de 40 caracteres.
  5. Remueve palabras de detención (vea la lista en el código, lo cual es demasiado extenso para verlo aquí).
  6. Detiene los tokens usando el Porter stemmer (vea Recursos.)

El resultado final de este análisis es un vector significativamente más pequeño para cada documento, así como uno que ha removido palabras "ruido" comunes (the, a , an y similares) que pueden confundir al clasificador. Este Analyzer fue desarrollado de forma iterativa observando ejemplos en el e-mail y luego procesando mediante el Analyzer y examinando el resultado, haciendo llamados de juicio sobre el mejor procedimiento. El proceso es tanto intuición (experiencia) como ciencia, desafortunadamente. El proceso y el resultado están lejos de ser perfectos, pero tienden a ser lo suficientemente buenos.

El Paso 2b realiza algunas conversiones menores de los datos para procesamiento, mientras también descarta algo de contenido para que las diferentes etiquetas sean representadas de forma pareja en los datos de entrenamiento. Este es un punto importante, porque mis primeros experimentos con los datos condujeron al problema que también es común para todos, en el aprendizaje por máquina, de sobre-adaptación para aquellas etiquetas significativamente con más ejemplos. De hecho, cuando se ejecuta en el clúster en el conjunto completo de datos, establecer el --maxItemsPerLabel en 1000 todavía no es lo suficientemente bajo como para crear buenos resultados, porque algunas de las listas de correo tienen menos de 1000 publicaciones. Esto es probablemente debido a un error en Mahout que la comunidad todavía está investigando.

El Paso 4 es donde se lleva a cabo el trabajo real, tanto para construir un modelo como para luego probar si es válido o no. En el Paso 4a, la opción --extractLabels simplemente le dice a Mahout que deduzca las etiquetas de entrenamiento a partir de la entrada. (La alternativa es pasarlas). El resultado de este paso es un archivo que puede ser leído mediante la claseorg.apache.mahout.classifier.naivebayes.NaiveBayesModel . El Paso 4b toma el modelo así como los datos de pruebe y verifica para ver qué tan buen trabajo hizo el entrenamiento. El resultado es una matriz confusa como se describe en"Introducing Apache Mahout." Para los datos de muestra, el resultado está en el Listado 2:

Listado 2. Resultado de muestra para ejecutar el código clasificador
Correctly Classified Instances : 41523 61.9219%
Incorrectly Classified Instances : 25534 38.0781%
Total Classified Instances : 67057
=======================================================
Confusion Matrix
-------------------------------------------------------
a b c d e f ><--Classified as
190440 12 1069 0 0 | 20125 a= cocoon_apache_org_dev
2066 0 1 477 0 0 | 2544 b= cocoon_apache_org_docs
165480 2370 704 0 0 | 19622 c= cocoon_apache_org_users
58 0 0 201090 0 | 20167 d= commons_apache_org_dev
147 0 1 4451 0 0 | 4599 e= commons_apache_org_user

Debe notar que esto es en realidad una muestra bastante pobre para un clasificador (aunque es mejor que adivinar). La razón probable para esta muestra pobre es que las listas de usuario y de desarrollo para un proyecto Apache dado están relacionadas más estrechamente en su vocabulario, lo cual es simplemente muy difícil de distinguir. Esto es soportado por el hecho de que 16,548 mensajes cocoon_user fueron clasificados incorrectamente como cocoon_dev. De hecho, volver a ejecutar la tarea usando solo el nombre del proyecto sin distinguir entre listas de usuario y de v en los datos de muestra, producen los resultados en el Listado 3:

Listado 3. Resultado de muestra de volver a ejecutar el código clasificador con el nombre del proyecto únicamente
Correctly Classified Instances : 38944 96.8949%
Incorrectly Classified Instances : 1248 3.1051%
Total Classified Instances : 40192

=======================================================
Confusion Matrix
-------------------------------------------------------
a b c ><--Classified as
18733 1241 0 | 19974 a = cocoon_apache_org
7 20211 0 | 20218 b = commons_apache_org

¡Pienso que usted estará de acuerdo en que 96% de precisión es muchísimo mejor que 61%! De hecho, probablemente sea demasiado bueno para ser verdad. El porcentaje se debe probablemente a la naturaleza de este pequeño conjunto de datos en particular, o tal vez a un problema más profundo que necesita ser investigado. De hecho, un puntaje como este debe garantizar que uno investigará más al añadir datos y revisar el código para generarlo. Por ahora, me alegra tenerlo como ejemplo de cómo se pueden ver los resultados. No obstante, podríamos intentar otras técnicas o una mejor selección de recursos, o tal vez más ejemplos de entrenamiento con el fin de aumentar la precisión. También es común efectuar validación cross-fold de los resultados. La validación cross-fold incluye tomar repetidamente partes de los datos de la muestra de entrenamiento, y ponerlos dentro de la muestra de prueba o ponerlos a un lado. Luego el sistema es juzgado por la calidad de todas las ejecuciones, no solo de una.

Llevar esto a la nube es tan simple como lo es con los recomendadores. El script completo debe ejecutarse en su clúster simplemente pasando las rutas apropiadas. Ejecutar esto en EC2 en un clúster de 10 nodos toma apenas unos minutos para el entrenamiento y prueba, junto con el trabajo preparatorio paralelo. Desafortunadamente, cuando usted ejecuta esto, la calidad de ejecutar contra el conjunto de datos completo en la nube se ve afectado debido a que algunas listas de correo tienen muy pocos puntos de datos. Estos muy probablemente no deben ser considerados.

Los siguientes pasos hacia la producción incluyen poner el modelo a disposición como parte de su sistema de tiempo de ejecución, así como configurar un flujo de trabajo para asegurar que el modelo es actualizado y que se obtiene retroalimentación del sistema. Desde aquí veremos un poco el almacenamiento en clúster.

Almacenamiento en clúster

Así como con la clasificación, Mahout tiene numerosos algoritmos de almacenamiento en clúster, cada uno con diferentes características. Por ejemplo, K-Means se escala bien, pero requiere que usted especifique el número de clústeres que usted desea por anticipado, mientras que el almacenamiento en clúster Dirchlet requiere que usted seleccione una distribución modelo así como el número de clústeres que usted desea. La agrupación en clúster también tiene una cantidad aceptable en común con la clasificación, y esto es posible, algunas veces, para que trabajen conjuntamente usando clústeres como parte de una clasificación. Además, gran parte del trabajo de preparación de datos es el mismo para almacenamiento en clúster — como la conversión de contenido bruto en secuencias de archivos y luego en pocos vectores — de manera que usted puede referirse a la secciónClasificación para esa información.

Para almacenamiento en clúster, la principal pregunta a ser respondida es: ¿podemos agrupar de forma lógica todos los mensajes con base en la similitud de contenido, independientemente del proyecto? Por ejemplo, tal vez los mensajes en la lista de correos electrónicos Apache Solr sobre el uso de Apache Tomcat como contenedor web estarán más cercanos a los mensajes para el proyecto Tomcat que al proyecto originador.

Para este ejemplo, los primeros pasos son bastante como la clasificación, divergiendo después de que se completa la conversión a pocos vectores. Los pasos específicos son:

  1. Los mismos pasos que los Pasos 1 y 2 de la clasificación.
  2. $ bin/mahout kmeans --input "$SEQ2SP/tfidf-vectors" --output $CLUST_OUT -k 50 --maxIter 20 --distanceMeasure org.apache.mahout.common.distance.CosineDistanceMeasure --clustering --method mapreduce --clusters "$CLUST_OUT/clusters"

En este caso, K-Means se ejecuta para que haga el almacenamiento en clúster, pero el script shell también soporta la ejecución de almacenamiento en clúster Dirichlet. (Cuando usted ejecuta el script, se le solicita que seleccione el algoritmo que desee ejecutar). En el ejemplo previo, los parámetros en los que valía la pena profundizar fueron:

  1. -k: el número de clústeres a crear. Yo seleccioné 50 al azar, pero podrían ser otros valores.
  2. --maxIter: K-Means es un algoritmo iterativo en el que el centro del clúster es adaptado como parte de cada iteración. En algunos casos, no se garantiza que se complete por sí mismo, por lo que este parámetro puede asegurar que el algoritmo se complete.
  3. --distanceMeasure: La medida de distancia determina la similitud entre el centroide actual y el punto que se está examinando. En este caso, yo seleccioné Cosine Distance Measure, la cual es con frecuencia una buena elección para datos de texto. Mahout tiene muchas otras implementaciones, y usted puede encontrar que vale la pena intentarlas con sus datos.
  4. --clustering: Le dice a Mahout que arroje como resultado cuáles puntos pertenecen a cuál centroide. Por defecto, Mahout simplemente computa los centroides, porque a menudo esto es todo lo que se necesita.

En cuanto se realiza la ejecución, usted puede descargar los centroides de clúster (y los puntos asociados) utilizando el programa ClusterDump de Mahout. Los resultados finales estarán en el subdirectorio bajo el directorio kmeans, comenzando con el nombre clusters- y terminando con -final. El valor exacto dependerá de cuántas iteraciones se necesiten para ejecutar la tarea; por ejemplo, clusters-2-final es el resultado de la tercera iteración. Como ejemplo, este comando descarga los clústeres de ejecutar la pequeña muestra de datos:

bin/mahout clusterdump --seqFileDir ../output/ibm/clustering/kmeans/clusters-2-final
    --pointsDir ../output/ibm/clustering/kmeans/clusteredPoints/

El --seqFileDir apunta a los centroides creados, y -pointsDir es el directorio de los puntos almacenados en clúster. En el Listado 4 hay una pequeña muestra de los resultados:

Listado 4. Resultado de muestra de ejecutar el ClusterDumper
:VL-337881{n=4420 c=[
  Top Terms:
    user                                    =>0.060885823267350335
    mailscann                               => 0.05059369006868677
    cocoon                                  =>0.048781178576134204
    virus                                   => 0.04285897589148712
    derek                                   => 0.04084340722527813
    legal                                   =>0.040052624979813184
    scan                                    => 0.03861016730680097
    danger                                  => 0.03848600584647758
    csir                                    => 0.03712359352614157
    transtec                                => 0.03388019099942435
  Weight : [props - optional]:  Point:
  1.0 : [distance=0.888270593967813]: 
  /cocoon.apache.org/dev/200004.gz/NBBBIDJGFOCOKIOHGDPBKEPPEEAA.XXXXX = 
  [ag:0.165, briefli:0.250, chang:0.075, close:0.137, cocoon:0.060, 
  cocoon1:0.226, cocoon2:0.218, concept:0.277, develop:0.101, differ:0.144, 
  explain:0.154, greet:0.197, klingenderstrass:0.223, langham:0.223, look:0.105, 
  mailserv:0.293, matthew:0.277, mlangham:0.240, paderborn:0.215, processor:0.231, 
  produc:0.202, put:0.170, scan:0.180, tel:0.163, understand:0.127, virus:0.194]

En el Listado 4, observe que el resultado incluye una lista de términos que el algoritmo ha determinado que son los más representativos del clúster. Esto puede ser útil para la generación de etiquetas para uso en producción, así como para optimizar la selección de recursos en los pasos preparatorios — porque con frecuencia se da el caso donde aparecen palabras (en este caso, por ejemplo, user probablemente es una) en la lista en los primeros pocos experimentos con ejecución de datos.

Como usted probablemente ha estado esperando, la ejecución de esto en su clúster es tan simple como la ejecución local — y tan simple como los otros dos ejemplo. Además el tiempo invertido en convertir el contenido, (aproximadamente 150 minutos), el trabajo efectivo de almacenamiento en clúster, tardó aproximadamente 40 minutos en 10 nodos en mis pruebas.

Desafortunadamente, con el almacenamiento en clúster, la evaluación de los resultados a menudo se reduce a la "prueba de olor", aunque Mahout tiene algunas herramientas para la evaluación (vea las opciones CDbwEvaluator yClusterDumper para producir los términos principales). Para la prueba de olor, lo mejor es visualizar los clústeres, pero desafortunadamente muchos kits de herramientas de visualización de gráficas se atragantan con conjuntos de datos extensos, por lo que usted puede quedar dependiendo de sus propios medios para la visualización.

Así como con las recomendaciones y la clasificación, los pasos hacia producción incluyen decidir sobre el flujo de trabajo para obtener datos, así como con qué frecuencia efectuar el procesamiento y, desde luego, hacer uso de este en su entorno de negocios. Usted probablemente también necesitará trabajar con los diversos algoritmos para ver cuales funcionan mejor para sus datos.


¿Qué viene para Mahout en el futuro?

Apache Mahout continúa progresando de diferentes formas. La comunidad está enfocada principalmente y por el momento, en llegar a un release 1.0 tras la realización de pruebas de desempeño, documentación, mejora de API y la adición de nuevos algoritmos. El próximo release, 0.6, probablemente se de hacia finales del 2011, o poco tiempo después. A un nivel más profundo, la comunidad también está comenzando a observar enfoques distribuidos y en memoria, para la solución de problemas de aprendizaje por máquina. En muchos casos, los problemas de aprendizaje por máquina son demasiado grandes para una sola máquina, pero Hadoop induce demasiada carga adicional debido a las E/S de disco. Independientemente del enfoque, Mahout está bien posicionado para ayudar a resolver los problemas actuales más apremiantes de datos de gran tamaño, al concentrarse en la escalabilidad y en facilitar el consumo de algoritmos complicados de aprendizaje de máquina.

Reconocimientos

Agradezco especialmente a Timothy Potter por su asistencia en el empaquetamiento de AMI y a los confirmadores colegas Mahout Sebastian Schelter, Jake Mannix y Sean Owen por su revisión técnica. Parte de este trabajo fue soportado por el Amazon Apache Testing Program.


Descargar

DescripciónNombretamaño
Shell scriptj-mahout-scaling.zip2KB

Recursos

Aprender

  • "Introducing Apache Mahout" (Grant Ingersoll, developerWorks, septiembre del 2009): Ingersoll, el co-fundador de Mahout introduce los conceptos básicos del aprendizaje por máquina y demuestra cómo usar Mahout para almacenamiento en clúster de documentos, para hacer recomendaciones y para organizar contenido.
  • Apache Mahout: Esté atento a la página de Apache Mahout para conocer las noticias más recientes, así como documentación y nuevas descargas.
  • Powered By Mahout: la página operada por Mahout lista compañías dispuestas a declarar su uso de los algoritmos Mahout.
  • Taming Text (Grant S. Ingersoll, Thomas S. Morton y Andrew L. Farris, Manning Publications, 2011): Este libro cubre Mahout y tecnologías relacionadas de fuente abierta para la construcción de aplicaciones basadas en texto.
  • Mahout in Action (Sean Owen, Robin Anil, Ted Dunning y Ellen Friedman, Manning Publications, 2011): Este libro es la guía definitiva para entender Mahout.
  • Apache Hadoop: Aprenda sobre Hadoop.
  • Algoritmos: Lea más sobre los algoritmos que implementa Mahout, así como sobre las áreas de interés para la comunidad en el Wiki Mahout.
  • Surprise and Coincidence: Lea más sobre la utilidad de la medida de probabilidad de registro en el blog del confirmador de Mahout Ted Dunning.
  • MongoDB: Descubra más sobre MongoDB en su sitio web.
  • Apache Cassandra: Obtenga más información sobre Apache Cassandra navegando hacia su sitio web. Lea más sobre su uso con Mahout en la publicación en blog de Sean Owen, "Recommending (from) Cassandra."
  • Amazon Web Services including EC2: Aprenda más sobre la infraestructura EC2 de Amazon.
  • Use an Existing Hadoop AMI: Esta página del wiki Mahout detalla el proceso de inicio de clústeres Hadoop en EC2.
  • Amazon EC2 User Guide: Consulte la Guía del Usuario EC2 para los pasos de Configuración de este artículo:
  • Message-ID: Aprenda más sobre los encabezados de e-mail y sobre el Message-ID.
  • Apache Lucene: Conozca más sobre Apache Lucene a través de su sitio web.
  • Dr. Martin Porter's Snowball stemmers: Estos son útiles con frecuencia para trabajo con texto en proyectos de búsqueda y de aprendizaje por máquina.
  • Consulte la librería tecnológica para libros sobre estos y otros temas técnicos.
  • zona de tecnología Java developerWorks: Encuentre cientos de artículos sobre cada aspecto de la programación Java.

Obtener los productos y tecnologías

Comentar

  • Mahout user mailing list: Suscríbase para hacer preguntas, compartir conocimiento y discutir sobre temas.
  • Participe en la comunidad developerWorks. Conéctese con otros usuarios developerWorks mientras explora los blogs, foros, grupos y wikis dirigidos a desarrolladores.

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=tecnologia Java
ArticleID=792243
ArticleTitle=Apache Mahout: Aprendizaje escalable con máquina para todos
publish-date=02132012