miércoles, 7 de noviembre de 2012

Hadoop On Azure Mahout: Algoritmos de recomendación, Clasificaciones y Agrupaciones (Clustering)

Hadoop-Mahout

Una vez que ya conocemos los conceptos y componentes principales de Hadoop según vimos en los posts anteriores:

  • Hadoop
  • HiveQL
  • Hive desde Excel, Power Pivot y Power View
  • Sqoop I
  • Sqoop II

    Continuaremos probando más funcionalidad de y para Hadoop on Azure. En esta ocasíón Mahout.

    La verdad es que cuando la semana pasada me disponía a indagar sobre el tema de mahout, no me imaginaba que la Intenligencia Artifical estuviera tan cerca, durante la carrera pensaba que este tipo de algoritmos sólo eran teoría y estarían lejos de acercarse a una realidad, pero sinceramente, creo que me equivoqué

    ¿Que es Mahout?

    Mahout proviene del Hindi, mahaut, “montador de elefantes”, de ahí el logotipo.  La labor de un Mahout es permanecer desde joven vinculado a un elefante también joven a fin de que tanto jinete como elefante se conozcan mutuamente a lo largo de toda la vida. ¡Se podría sacar de aquí una peli, seguro,jeje…! Técnicamente hablando, Apache Mahout,es una máquina de aprendizaje cuyo objetivo consiste en construir bibliotecas escalables de aprendizaje automático.

    Los sistemas de recomendación son alguna de las aplicaciones de aprendizaje más conocida hoy día. Su objetivo es tratar de presentar al usuario items de información: películas, música, libros, noticias, páginas web, etc, sobre las que el usuario está interesado. Todo ello basado en su comportamiento previo. Estos algoritmos proporcionan una funcionalidad importante para muchos sitios de redes sociales , compras on-line, streaming, y otros sitios de Internet. Mahout ofrece un motor de recomendación out-of-the-box que es fácil de usar, tiene muchas características útiles, y es escalable en Hadoop.  Algunas de las aplicaciones más conocidas que utilizan estos algoritmos, son Pandora RadioNetflix o incluso la propia web de Amazon que ofrece/recomienda a sus clientes productos a partir de los ya comprados por otros.

    A continuación veremos las técnicas que A continuación veremos las técnicas que por ahora nos ofrece Hadoop On Azure, es decir, Clasificación y Agrupación (Clustering).

    1) Clasificación

    Partamos del propio ejemplo que nos presenta Hadoop o directamente desde aquí. Este ejemplo esta basado 100% en el ejemplo del website de Mahout el cual consiste en:

    “The 20 Newsgroups data set is a collection of approximately 20,000 newsgroup documents, partitioned (nearly) evenly across 20 different newsgroups. The 20 newsgroups collection has become a popular data set for experiments in text applications of machine learning techniques, such as text classification and text clustering. We will use Mahout Bayes Classifier to create a model that would classify a new document into one of the 20 newsgroup.”

    Para ello tal y como nos dice el tutorial y desde el Head Node al que accedemos remotamente:

    1) Descargamos del fichero de datos en la ruta ““C:\apps\dist\mahout-0.5\examples\bin\work”

    2) Descomprimimos el fichero “.tar.gz” en la capeta: “C:\apps\dist\mahout-0.5\examples\bin\work\20news-bydate”

    3) Ejecutamos el “.cmd” c:\apps\dist\mahout-0.5\examples\bin\build-20news-bayes.cmd”

    Nota: Aunque esperamos que funcione, resulta que no es así, parece que se trata de algún error de configuración en los scripts de “Mahout” para Azure on Hadoop o, incluso de alguna incompatibilidad de versiones entre los comandos Mahout y Hadoop.

    image

    Para solucionar el problema modificamos el script “build-20news-bayes.cmd” sustituyendo la llamada al comando Mahout por la llamada directa a hadoop (realmente es lo que hace internamente el comando Mahout), es decir,

    Sustituimos esto:

    call mahout.cmd org.apache.mahout.classifier.bayes.preparetwentynewsgroups ^
      -p %work_path%\20news-bydate-train ^
      -o %work_path%\bayes-train-input ^
      -a org.apache.mahout.vectorizer.defaultanalyzer ^
      -c utf-8

    call mahout.cmd org.apache.mahout.classifier.bayes.preparetwentynewsgroups ^
      -p %work_path%\20news-bydate-test ^
      -o %work_path%\bayes-test-input ^
      -a org.apache.mahout.vectorizer.defaultanalyzer ^
      -c utf-8

    por esto otro:

    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar ^
    org.apache.mahout.driver.MahoutDriver ^

    org.apache.mahout.classifier.bayes.PrepareTwentyNewsgroups ^
    -p %WORK_PATH%20news-bydate-train ^
    -o %WORK_PATH%bayes-train-input ^
    -a org.apache.mahout.vectorizer.DefaultAnalyzer ^
    -c UTF-8

    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar ^
    org.apache.mahout.driver.MahoutDriver ^

    org.apache.mahout.classifier.bayes.PrepareTwentyNewsgroups ^
      -p %WORK_PATH%20news-bydate-test ^
      -o %WORK_PATH%bayes-test-input ^
      -a org.apache.mahout.vectorizer.DefaultAnalyzer ^
      -c UTF-8

    De todas formas, os dejo el contenido completo del fichero “build-20news-bayes.cmd” con el problema solucionado.

    @echo off
    @rem
    @rem Licensed to the Apache Software Foundation (ASF) under one or more
    @rem contributor license agreements.  See the NOTICE file distributed with
    @rem this work for additional information regarding copyright ownership.
    @rem The ASF licenses this file to You under the Apache License, Version 2.0
    @rem (the "License"); you may not use this file except in compliance with
    @rem the License.  You may obtain a copy of the License at
    @rem
    @rem     http://www.apache.org/licenses/LICENSE-2.0
    @rem
    @rem Unless required by applicable law or agreed to in writing, software
    @rem distributed under the License is distributed on an "AS IS" BASIS,
    @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    @rem See the License for the specific language governing permissions and
    @rem limitations under the License.
    @rem
     
    @rem
    @rem Downloads the 20newsgroups dataset, trains and tests a bayes classifier. 
    @rem
    @rem To run:  change into the mahout directory and type:
    @rem  examples/bin/build-20news.sh
     
    setlocal enabledelayedexpansion
     
    set SCRIPT_PATH=%~dp0
    set MAHOUT_BIN_PATH=%SCRIPT_PATH%..\..\bin\
    set WORK_PATH=%SCRIPT_PATH%work\20news-bydate\
    set HDFS_WORK_PATH=examples/bin/work/20news-bydate/
     
    if not exist %WORK_PATH% (
        mkdir %WORK_PATH%
    )
     
    if not exist %WORK_PATH%20news-bydate-train (
         goto :ErrorMessage
    )
     
    if not exist %WORK_PATH%20news-bydate-test (
         goto :ErrorMessage
    )
     
    pushd %MAHOUT_BIN_PATH%
     
    REM call mahout.cmd org.apache.mahout.classifier.bayes.PrepareTwentyNewsgroups ^
      REM -p %WORK_PATH%\20news-bydate-train ^
      REM -o %WORK_PATH%\bayes-train-input ^
      REM -a org.apache.mahout.vectorizer.DefaultAnalyzer ^
      REM -c UTF-8
     
    REM call mahout.cmd org.apache.mahout.classifier.bayes.PrepareTwentyNewsgroups ^
      REM -p %WORK_PATH%\20news-bydate-test ^
      REM -o %WORK_PATH%\bayes-test-input ^
      REM -a org.apache.mahout.vectorizer.DefaultAnalyzer ^
      REM -c UTF-8 
     
      
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar ^
    org.apache.mahout.driver.MahoutDriver ^
    org.apache.mahout.classifier.bayes.PrepareTwentyNewsgroups ^
    -p %WORK_PATH%20news-bydate-train ^
    -o %WORK_PATH%bayes-train-input ^
    -a org.apache.mahout.vectorizer.DefaultAnalyzer ^
    -c UTF-8
     
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar ^
    org.apache.mahout.driver.MahoutDriver ^
    org.apache.mahout.classifier.bayes.PrepareTwentyNewsgroups ^
      -p %WORK_PATH%20news-bydate-test ^
      -o %WORK_PATH%bayes-test-input ^
      -a org.apache.mahout.vectorizer.DefaultAnalyzer ^
      -c UTF-8 
      
    @rem mapreduce test method used on hadoop
    set TEST_METHOD="mapreduce"
     
    call hadoop.cmd dfs -rmr ^
          %HDFS_WORK_PATH%bayes-train-input 
     
    call hadoop.cmd dfs -rmr ^
          %HDFS_WORK_PATH%bayes-test-input
     
    call hadoop.cmd dfs -put ^
          %WORK_PATH%\bayes-train-input ^
          %HDFS_WORK_PATH%bayes-train-input 
     
    call hadoop.cmd dfs -put ^
          %WORK_PATH%\bayes-test-input ^
          %HDFS_WORK_PATH%bayes-test-input
     
          
    REM call mahout.cmd trainclassifier ^
      REM -i %HDFS_WORK_PATH%bayes-train-input ^
      REM -o %HDFS_WORK_PATH%bayes-model ^
      REM -type bayes ^
      REM -ng 1 ^
      REM -source hdfs
     
    REM call mahout.cmd testclassifier ^
      REM -m %HDFS_WORK_PATH%bayes-model ^
      REM -d %HDFS_WORK_PATH%bayes-test-input ^
      REM -type bayes ^
      REM -ng 1 ^
      REM -source hdfs ^
      REM -method %TEST_METHOD%
     
      
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar ^
    org.apache.mahout.driver.MahoutDriver ^
    trainclassifier ^
      -i %HDFS_WORK_PATH%bayes-train-input ^
      -o %HDFS_WORK_PATH%bayes-model ^
      -type bayes ^
      -ng 1 ^
      -source hdfs
     
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar ^
    org.apache.mahout.driver.MahoutDriver ^
    testclassifier ^
      -m %HDFS_WORK_PATH%bayes-model ^
      -d %HDFS_WORK_PATH%bayes-test-input ^
      -type bayes ^
      -ng 1 ^
      -source hdfs ^
      -method %TEST_METHOD%
     
      
    popd
     
    goto :eof
     
    :ErrorMessage
    echo Please download 20news-bydate.tar.gz from:
    echo http://people.csail.mit.edu/jrennie/20Newsgroups/20news-bydate.tar.gz
    echo and extract it under:
    echo %WORK_PATH%

    4) Solucionado el problema ahora si, el resultado esperado es la siguiente “Confusion Matrix”.  Esta misma matriz puede verse en el ejemplo de partida de Apache Mohout que indicábamos antes.


    image


    En este ejemplo, puede verse como funciona una “Confusion Matrix” y un poco de teoría.


    Adicionalmente, aquí tenemos otro ejemplo de clasificación (en este caso más concretamente, un ejemplo de algoritmo de recomendación).


    2) Agrupación(Clustering)


    Partimos nuevamente del propio ejemplo que nos presenta Hadoop o directamente desde aquí. Este ejemplo esta basado 100% en el ejemplo del website de Mahout el cual consiste en:


    “The example will demonstrate clustering of control charts which exhibits a time series. Control charts are tools used to determine whether or not a manufacturing or business process is in a state of statistical control. Such control charts are generated / simulated over equal time interval and available for use in UCI machine learning database. The data is described here .”


    Para ello y como nos dice el tutorial:


    1) Descargamos el fichero “http://archive.ics.uci.edu/ml/databases/synthetic_control/synthetic_control.data” y lo situamos en la carpeta “C:\apps\dist\mahout-0.5\examples\bin\work\clustering\”


    2) Ejecutamos “C:\apps\dist\mahout-0.5\examples\bin\build-cluster-syntheticcontrol.cmd” y elegimos el tipo de “clustering”:image


    3) De la misma manera que para el ejemplo anterior, volvemos a tener problemas así que tenemos que hacer algunos ajustes:


  • Creamos un directorio “testdata” en HDFS desde la consola interactiva de Javascript ejecutando el comando ”#mkdir testdata
  • Modificamos el script (.cmd) “build-cluster-syntheticcontrol.cmd” siguiendo las misma pautas que para el ejemplo de clasificación,

    Sustituyendo esto:



    call mahout hadoop fs -rmr %HDFS_WORK_PATH%
    call mahout hadoop fs -mkdir %HDFS_WORK_PATH%
    call mahout hadoop fs -put %WORK_PATH%\synthetic_control.data %HDFS_WORK_PATH%
    call mahout org.apache.mahout.clustering.syntheticcontrol.%_clustertype%.Job


    Por esto otro:



    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar org.apache.mahout.driver.MahoutDriver ^
       hadoop fs -rmr %HDFS_WORK_PATH%
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar org.apache.mahout.driver.MahoutDriver ^
       hadoop fs -mkdir %HDFS_WORK_PATH%
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar org.apache.mahout.driver.MahoutDriver ^
       hadoop fs -put %WORK_PATH%\synthetic_control.data %HDFS_WORK_PATH%
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar org.apache.mahout.driver.MahoutDriver ^
       org.apache.mahout.clustering.syntheticcontrol.%_clustertype%.Job


     


    Nuevamente, aquí dejo el fichero “build-cluster-syntheticcontrol.cmd” con el problema ya solucionado.



    @echo off
     
    @rem
    @rem Licensed to the Apache Software Foundation (ASF) under one or more
    @rem contributor license agreements.  See the NOTICE file distributed with
    @rem this work for additional information regarding copyright ownership.
    @rem The ASF licenses this file to You under the Apache License, Version 2.0
    @rem (the "License"); you may not use this file except in compliance with
    @rem the License.  You may obtain a copy of the License at
    @rem
    @rem     http://www.apache.org/licenses/LICENSE-2.0
    @rem
    @rem Unless required by applicable law or agreed to in writing, software
    @rem distributed under the License is distributed on an "AS IS" BASIS,
    @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    @rem See the License for the specific language governing permissions and
    @rem limitations under the License.
    @rem
     
    @rem
    @rem Downloads the Synthetic control dataset and prepares it for clustering
    @rem
    @rem To run:  change into the mahout directory and type:
    @rem  examples/bin/cluster-syntheticcontrol.sh
     
    setlocal enabledelayedexpansion
     
    set SCRIPT_PATH=%~dp0
    set MAHOUT_BIN_PATH=%SCRIPT_PATH%..\..\bin\
    set WORK_PATH=%SCRIPT_PATH%work\clustering\
    set HDFS_WORK_PATH=testdata
     
    if not exist %WORK_PATH% (
        mkdir %WORK_PATH%
    )
     
    if not exist %WORK_PATH%synthetic_control.data (
        echo Please downloading Synthetic control data from:
        echo http://archive.ics.uci.edu/ml/databases/synthetic_control/synthetic_control.data
        echo and put it under:
        echo %WORK_PATH%synthetic_control.data
        goto :end
    )
     
    :main
    echo "Please select a number to choose the corresponding clustering algorithm"
    echo "1. canopy clustering"
    echo "2. kmeans clustering"
    echo "3. fuzzykmeans clustering"
    echo "4. dirichlet clustering"
    echo "5. meanshift clustering"
    set /p _choice="Enter your choice:"
      
    @rem set _algorithms=canopy kmeans fuzzykmeans dirichlet meanshift
    if [%_choice%] == [1] (
        set _clustertype=canopy
    ) else (
        if [%_choice%] == [2] (
            set _clustertype=kmeans
        ) else (
            if [%_choice%] == [3] (
                set _clustertype=fuzzykmeans
            ) else (
                if [%_choice%] == [4] (
                    set _clustertype=dirichlet
                ) else (
                    if [%_choice%] == [5] (
                        set _clustertype=meanshift
                    ) else (
                        echo "Invalid choice %_choice%. Please try again"
                        goto :end
    )))))
    echo "ok. You chose %_choice% and we'll use %_clustertype% Clustering"
     
    pushd %MAHOUT_BIN_PATH%
     
    echo "DFS is healthy... "
    echo "Uploading Synthetic control data to HDFS"
     
    @REM call mahout hadoop fs -rmr %HDFS_WORK_PATH%
    @REM call mahout hadoop fs -mkdir %HDFS_WORK_PATH%
    @REM call mahout hadoop fs -put %WORK_PATH%\synthetic_control.data %HDFS_WORK_PATH%
     
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar org.apache.mahout.driver.MahoutDriver ^
    hadoop fs -rmr %HDFS_WORK_PATH%
     
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar org.apache.mahout.driver.MahoutDriver ^
    hadoop fs -mkdir %HDFS_WORK_PATH%
     
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar org.apache.mahout.driver.MahoutDriver ^
    hadoop fs -put %WORK_PATH%\synthetic_control.data %HDFS_WORK_PATH%
     
    echo "Successfully Uploaded Synthetic control data to HDFS "
     
    @REM call mahout org.apache.mahout.clustering.syntheticcontrol.%_clustertype%.Job
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar org.apache.mahout.driver.MahoutDriver ^
    org.apache.mahout.clustering.syntheticcontrol.%_clustertype%.Job
     
    :end
    popd

    4) Una vez que hemos lanzado este script, ejecutamos los dos siguientes para la comprobación y obtención de resultados:


    Para verificar que el resultado se encuentra en HDFS, ejecutamos:



    • hadoop fs -lsr output”, o,
    • #ls output”, desde la consola interactiva de Java Script.

    Para descargar el resultado desde HDFS en un directorio local del Head Node del cluster de Hadoop:



    • hadoop fs -get output C:\apps\dist\mahout-0.5\examples\bin\work\clustering
    • Veremos que la ruta “C:\Apps\dist\mahout-0.5\examples\bin\work\clustering” contiene la carpeta “output” como resultado del comando anterior.

    5) A continuación, analizaremos los datos obtenidos utilizando el parámetro de Mahout “clusterdump”.



    • Creamos un nuevo script:


    @echo off
    setlocal enabledelayedexpansion
     
    set SCRIPT_PATH=%~dp0
    set MAHOUT_BIN_PATH=%SCRIPT_PATH%..\..\bin\
     
    set MAHOUT_HOME=%MAHOUT_BIN_PATH%..\
     
    pushd %MAHOUT_BIN_PATH%
     
    call %HADOOP_HOME%\bin\hadoop jar %MAHOUT_BIN_PATH%..\mahout-examples-0.5-job.jar ^
       org.apache.mahout.driver.MahoutDriver ^
       clusterdump ^
       --seqFileDir output/clusters-0 ^
       --pointsDir output/clusteredPoints ^
       --output clusteranalyze.txt
     
    popd

    Nota: En vista de que el resultado esperado para este ejemplo no es satisfactorio, puesto que no obtendremos resultados, en este enlace podemos ver un análisis de los resultados de manera genérica así como el contenido del fichero de salida, “clusteranalyze.txt”.  Este fichero lo encontraremos en la carpeta  “C:\apps\dist\mahout-0.5\bin\” una vez hayamos ejecutado este último script.


    Adicionalmente, de las 5 opciones que presenta este último ejemplo sólo la primera y las dos últimas funcionan, el resto producen errores y como ya hemos comentado, es posible que sea debido a las incompatibilidades para las versiones actuales entre Hadoop y Mahout. Siempre que ocurran estos problemas podemos intentar solucionarlo descargando y actualizando sus nuevas versiones: Hadoop y Mahout


    Importante: Si optamos por actualizar las versiones, tengamos en cuenta lo siguiente:



    • Es posible que las nuevas versiones no contengan los mismo ejemplos.
    • Los script (.cmd) adaptados a Windows, tendremos que generarlos manualmente a partir de los “.sh” de Linux/unix que se distribuyen con la versión original de apache. Por ejemplo, para mahout descargaremos la nueva versión, mahot-distribution-0.7, y la renombraremos por “mahout-0.7” ubicándola en “C:\apps\dist\” al mismo nivel que “mahout-0.5”, así podremos intentar reutilizar los script (.cmd) de la versión anteriores.
    • A partir de aquí, toca probar y cruzar los dedos, por eso, no recomiendo esto a menos que los cambios a realizar fueran mínimos. Esperemos a que Microsft vaya realizando y adaptando las versiones adecuadamente.

    Aunque estos algoritmos y ejemplos están cambiando constantemente y Hadoop aun está en “Preview”, espero haber aclarado incógnitas sobre este nuevo mundo de la Inteligencia Artificial con Mahout… !


    Saludos y feliz “cacharreo” con Mahout…
    Juanlu,ElGuerre


  • Etiquetas: , ,


    This page is powered by Blogger. Isn't yours?