Escola Tècnica Superior d’Enginyeria Electrònica i Informàtica La Salle
Trabajo Final de Máster
Máster en Big Data
Etiquetado de Keywords Automático en Google Adwords
Alumno Profesor Ponente Mentor Externo
Pablo Joan Navarro Albert Morcillo
Monleón Capitán Xavier Solé Pablo Callejón
Reunido el Tribunal calificador en la fecha indicada, el alumno
D. Pablo Monleón Capitán
expuso su Trabajo Final de Máster, titulado:
Etiquetado de Keywords Automático en Google Adwords
Acabada la exposición y contestadas por parte del alumno las objeciones formuladas por los Sres. miembros del tribunal, éste valoró dicho Trabajo con la calificación de
Barcelona,
VOCAL DEL TRIBUNAL VOCAL DEL TRIBUNAL
PRESIDENTE DEL TRIBUNAL
ACTA DEL EXAMEN
DEL TRABAJO FINAL DE MÁSTER
Resumen
En esta memoria se desarrolla un algoritmo de etiquetado automático de keywords para la empresa RocketROI. Tras un análisis de los datos facilitados por la empresa con el software estadístico R se desarrolla un algoritmo de etiquetado automático y después se procede a la implementación de dicho algoritmo en tecnologías Big Data (Hadoop, Mahout,...). Una vez conseguido el objetivo se automati- za todo con Hudson y se presentan las conclusiones del trabajo.
Palabras clave: keyword, Big Data, Google Adwords, etiquetado automático, AdGroup.
Summary
In this essay we develop an automatic keyword tag algorithm for the company RocketROI. After a deep analysis of the data provided by the company with the statistic software R we develop the algorithm and then we proceed to transform it into Big Data technologies such as Hadoop or Mahout.
Once we achieve the goal, we automatize all with Hudson and we present the conclusions of the essay.
Keywords: keyword, Big Data, Google Adwords, etiquetado automático, AdGroup.
Introducción
El Trabajo Fin de Máster que presentamos en la siguiente memoria se ha llevado a cabo bajo la tutela de la empresa RocketROI.
El trabajo se centra en el desarrollo de un algoritmo de etiquetado de keywords. Para ello, se ha trabajado con ficheros de datos reales proporcionados por RocketROI, los cuáles no se divulgarán en esta memoria por el compromiso de protección de datos de la empresa para con sus clientes. Es por eso que durante la lectura se ocultan los nombres de los posibles clientes mediante las letras XXX o mediante un nombre ficticio.
Para la implementación del algoritmo se ha utilizado el software estadístico R, así como para la pre- paración de los datos. Una vez pulido el algoritmo se ha procedido a su aplicación en Pig y Mahout con el objetivo de aplicar técnicas y conocimientos adquiridos durante el Máster en Big Data cuyo punto final será la exposición de este trabajo.
La memoria consta de cinco capítulos. En el primer capítulo se explica la naturaleza y funciona- miento de RocketROI así como el planteamiento del reto que ha motivado este trabajo. Además se incluye un pequeño apartado con una overview de AdWords que consideramos muy recomendable para la comprensión del trabajo en general.
En el segundo capítulo se desarrolla todo lo relativo a la infraestructura necesaria para la realización del reto. El capítulo incluye una pequeña overview de Hadoop así como su posterior configuración.
El tercer capítulo detalla el algoritmo que se ha llevado a cabo. En este caso se trata de una clus- terización con su posterior etiquetado de keywords. Se incluyen los comandos de R así como su im- plementación en Pig lo cuál creemos que resultará muy útil para cualquier persona que quiera replicar lo mismo o hacer alguna implementación parecida.
El cuarto capítulo está dedicado a la automatización con Hudson, y el quinto y último capítulo se centra en las conclusiones, comentarios de los resultados, líneas de futuro y un comentario final de los autores.
Al final de la memoria se pone a disposición del lector una bibliografía con los enlaces, libros y artículos que han sido más relevantes a la hora de hacer este trabajo.
Índice general
Resumen V
Summary VII
Introducción IX
1. RocketROI 1
1.1. ¿Qué es RocketROI? . . . 1
1.2. Google Adwords . . . 1
1.2.1. Diferencia entre resultados por búsqueda orgánica y resultados de anuncios . 2 1.2.2. ¿Cómo funciona AdWords? . . . 2
1.3. Concordancia de keywords . . . 3
1.3.1. Concordancia amplia . . . 4
1.3.2. Concordancia amplia modificada. . . 4
1.3.3. Concordancia frase . . . 4
1.3.4. Concordancia exacta . . . 4
1.4. Reto propuesto por RocketROI . . . 5
1.4.1. Etiquetar keywords automáticamente según las estadísticas de uso . . . 5
1.4.2. Herramientas disponibles. . . 5
1.4.3. Objetivo. . . 5
2. Infraestructura 7 2.1. Descripción general . . . 7
2.1.1. Análisis del problema . . . 7
2.1.2. Propuesta de solución . . . 8
2.2. Configuración de las máquinas virtuales . . . 10
2.3. Configuración de Hadoop . . . 11
2.3.1. HDFS . . . 12
2.3.2. YARN. . . 19
2.3.3. PIG . . . 22
2.3.4. MAHOUT . . . 23
2.3.5. Eclipse . . . 24
2.3.6. JDK (Java Development Kit) . . . 24
2.3.7. Apache-Maven . . . 24
2.3.8. HUDSON CI . . . 25
3. Análisis 27
3.1. Inspección de datos con R . . . 27
3.2. Definición del algoritmo . . . 28
3.2.1. Tipos de etiquetas. . . 29
3.2.2. Preparación de los datos . . . 29
3.2.3. Estudio de etiquetas de una métrica . . . 32
3.2.4. Otros tipos de etiquetas . . . 33
3.2.5. Algoritmo k-means . . . 34
3.3. Implementación de la ETL con Pig . . . 40
3.4. Adaptación del algoritmo a Mahout . . . 45
3.4.1. Preprocesado del input . . . 45
3.4.2. K-means en Mahout . . . 47
3.4.3. Procesado del output . . . 49
3.4.4. Comparativa con el resultado de R . . . 54
3.5. Procesado para presentación de resultados . . . 60
4. Automatización con Hudson 65 4.1. Automatización del levantamiento de máquinas . . . 66
4.2. Automatización de la ejecución del algoritmo . . . 68
5. Conclusiones 71 5.1. Resultados . . . 71
5.2. Líneas de futuro . . . 72
5.2.1. Infraestructura . . . 72
5.2.2. Algoritmo . . . 72
5.3. Comentarios de los autores . . . 73
A. Apéndice 75
Bibliografía 105
RocketROI
1.1. ¿Qué es RocketROI?
RocketROI es una empresa de especialistas en gestión y optimización de campañas en Google Ad- words. Gracias a una exclusiva tecnología se han convertido en líderes del sector en muy poco tiempo.
Su principal objetivo es ayudar a las compañías y agencias a ahorrar costes en materia de publicidad.
Leyendo el mercado publicitario en tiempo real y optimizando la inversión consiguen ahorrar tiempo y dinero a los anunciantes.
Debido a la eficaz optimización de campañas en Google Adwords que ofrece a sus clientes, Roc- ketROI consigue acelerar su ROI, reducir sus pérdidas y aumentar sus conversiones. Todo esto es posible gracias a un equipo formado por consultores de negocio digital, ingenieros y expertos en mi- nería de datos, todos ellos certificados por Google como Google Adwords Proffessionals.
RocketROI consiguió algo impensable en su inicio, conseguir como socio principal a Google. Este gigante tecnológico supo ver el potencial de la firma y es evidente que acertaron. Tan solo un año después de su presentación oficial en junio de 2014, RocketROI se posicionó como el primer socio tecnológico de Google en España, posición que a día de hoy aún mantiene. Google es consciente de las limitaciones que puede tener la gestión manual de sus campañas y es por ello que fomenta y apoya iniciativas dirigidas hacia la gestión inteligente de las mismas.
A día de hoy la empresa tiene sede en Barcelona. Sin embargo, optimiza campañas publicitarias en diversos mercados tales como pueden ser el estadounidense, el alemán, el francés o el brasileño entre otros.
1.2. Google Adwords
Google Adwords es un servicio de márketing online que permite a los anunciantes competir para mostrar sus anuncios a los usuarios. Basándose en cookies o keywords predefinidas por los anuncian- tes, estos pueden mostrar su publicidad a los usuarios. Todas las páginas web que desean usar este servicio están diseñadas para dar permiso a Google para seleccionar y mostrar su anuncio.
Para entender como funciona la plataforma debemos familiarizarnos primero con algunos concep-
tos básicos.
1.2.1. Diferencia entre resultados por búsqueda orgánica y resultados de anuncios Pongamos por ejemplo que queremos anunciar un producto o servicio usando AdWords, la plata- forma online de márketing de Google. Cuando alguien realiza una búsqueda en Google relacionada con nuestro negocio, nuestro anuncio puede aparecer al principio o al final de la página de resultados de Google con una etiqueta de anuncio. La posición de nuestro anuncio dependerá de lo relevante y útil que pueda resultar para la persona que está realizando la búsqueda, lo que paguemos, y algunos otros factores. La sección de anuncios ocupa una buena parte de la página de resultados de Google, situándolos al principio y al final de la misma.
La otra sección de la página muestra los resultados de búsqueda orgánica. Estos resultados son links por los que Google no ha cobrado a páginas con contenido relacionado directamente a lo que el usua- rio ha buscado. Cuánto más relevante es el sitio web en relación a los términos de búsqueda, más alto aparecerá el link en la lista. Nuestra página web podría aparecer también si está relacionada, pero nuestro anuncio no.
1.2.2. ¿Cómo funciona AdWords?
Nuestro anuncio puede aparecer cuando alguien busca términos relacionados con nuestro pro- ducto o servicio, o cuando esa persona está navegando por alguna página web cuyo contenido esta relacionado con nuestro negocio. ¿Cómo funciona?
Las keywords como conexión con los clientes
Las keywords son palabras o frases que el anunciante tiene que elegir cuando lanza su campa- ña AdWord. Estos términos los elegiremos en relación a lo que pensemos que nuestros potenciales clientes buscarán en Google cuando quieran encontrar productos o servicios como los que nosotros ofrecemos.
Relacionando nuestras keywords con el anuncio que hemos creado, hacemos posible que nuestro anuncio se muestre en búsquedas de términos similares, o en páginas de contenido relacionado con el nuestro.
Por ejemplo, si nuestro negocio se basa en el reparto de pizzas a domicilio, usaremos por ejemplo pizza a domiciliocomo keyword de nuestro anuncio. Cuando alguien busque en Google la frase ’pizza a domicilio’ o un término similar, puede que nuestro anuncio aparezca en la página de resultados de Google o en otras páginas relacionadas con la pizza a domicilio.
La subasta de anuncios
¿Cómo decide Google en qué orden aparecen los anuncios? Mediante un sistema de subasta. La persona que más paga no tiene que ser necesariamente la persona cuyo anuncio salga en primera posición. La posición de los anuncios la determina AdWords calculando un coeficiente que ellos de- nominan Ad Rank. El anuncio con un Ad Rank más alto será el que aparecerá en primera posición.
El cálculo del Ad Rank tiene en cuenta tres factores:
- La puja: Cuando establecemos nuestra puja, le estamos diciendo a AdWords la cantidad máxi- ma de dinero que estamos dispuestos a pagar por un click en nuestro anuncio. La cantidad que acabaremos pagando suele ser menos, y hay que tener en cuenta que podemos cambiar nuestra puja en cualquier momento.
- La calidad de nuestro anuncio: Google se caracteriza por ofrecer siempre una experiencia satisfactoria al usuario, por lo tanto AdWords tiene en cuenta lo relevante y útil que puede resultarle al usuario ver nuestro anuncio. Esta puntuación de calidad tiene en cuenta detalles como la estructura del anuncio o el nivel de concordancia del anuncio con la Landing Page, es decir, con la página a la que es dirigido el cliente trás hacer click sobre el anuncio.
- El impacto derivado de las extensiones de tu anuncio y otros formatos: Cuando creamos un anuncio, tenemos la opción de añadirle información adicional como puede ser nuestro número de teléfono, dirección, etc... A ese tipo de datos AdWords les llama extensiones de anuncio.
AdWords hace una estimación de como las extensiones y otro tipo de formatos del anuncio que usemos pueden impactar en la experiencia del usuario.
El coste al final del día
Cuando el CPC (cost-per-click), AdWords solo nos cobrará cuando alguien esté lo suficientemen- te interesado en nuestro anuncio como para visitar nuestra web. Seremos nosotros los que le diremos a AdWords la máxima cantidad que queremos pagar por cada click en nuestro anuncio aunque puede que al final nos cobren menos.
El anunciante tiene control total sobre su presupuesto. Es él el que decide la cantidad media de dinero que queremos gastar por día. De esta forma, en los días en los que nuestro anuncio despierte más inte- rés, AdWords podrá subir nuestro presupuesto hasta un 20 % más para asegurarse de que no perdamos clicks y quedará compensado a lo largo del mes reduciendo el presupuesto en intervalos de tiempo en los que nuestro anuncio pierda interés.
Para una versión más detallada de Google AdWords ver [G].
1.3. Concordancia de keywords
Una vez visto el funcionamiento de AdWords vamos a pasar a explicar los diferentes tipos de concordancia de las keywords. Éstos pueden dividirse en cuatro:
- amplia.
- +amplia +modificada.
- ”frase”.
- [exacta].
1.3.1. Concordancia amplia
El tipo de concordancia amplia tiene las siguientes características:
- Se usa cuando las palabras clave no contienen los carácteres ” ”,[ ], ( ) o +.
- Busca sinónimos, plurales, cambios de género, búsquedas relacionadas y otras palabras clave relevantes en cualquier orden.
- Genera valiosa información a corto y medio plazo acerca de posibles segmentaciones, ideas para campañas y grupos de anuncios y palabras clave negativas.
1.3.2. Concordancia amplia modificada
El tipo de concordancia amplia modificada tiene las siguientes características:
- Se usa poniendo un símbolo + delante de la palabra clave.
- Busca plurales, cambios de género, búsquedas relacionadas y otras palabras clave relevantes en cualquier orden.
- Útiles para tener un buen enfoque de palabras clave a medio plazo sin desviarse mucho de las palabras clave objetivo.
- A largo plazo, mantener en campañas con CPC’s menores.
1.3.3. Concordancia frase
El tipo de concordancia frase tiene las siguientes características:
- Se usa encerrando las palabras clave con comillas dobles.
- Muestra los anuncios cuando un usuario realice una búsqueda que contenga esa frase o ligeras variaciones, pudiendo contener texto delante y/o detrás.
- Lo que va entre comillas siempre mostrará el anuncio si va junto y en el mismo orden.
1.3.4. Concordancia exacta
El tipo de concordancia exacta tiene las siguientes características:
- Se usa encerrando las palabras clave entre corchetes.
- Únicamente se mostrarán los anuncios cuando la búsqueda del usuario coincida exactamente con la palabra clave exacta.
- Opcionalmente, a nivel campaña existe una configuración que permite pequeños errores.
1.4. Reto propuesto por RocketROI
1.4.1. Etiquetar keywords automáticamente según las estadísticas de uso
Según el tipo de búsquedas que se hagan sobre una keyword, podemos encontrar relaciones entre keywordsque nos pueden permitir catalogarlas para después hacer mejores optimizaciones.
Este etiquetado creen que les puede servir para mejorar diferentes aspectos de sus algoritmos. Por ejemplo:
- Las keywords de long tail suelen necesitar periodos más grandes para considerar cualquier ac- ción, ya que acostumbran a recibir menos búsquedas y por lo tanto menos clicks. Si pudiéramos saber que la keyword es de ese tipo, podríamos considerar periodos más grandes antes de decidir que una keyword no funciona.
- Poder clasificar las keywords de forma automática permitiria gestionar las campañas con mayor agilidad pudiendo ,por ejemplo, aplicar un acción sobre todo un grupo de keywords del mismo tipo en un momento determinado.
Es decir, este etiquetado podría aplicarse en diferentes fases de sus algoritmos para mejorar el rendi- miento a la hora de tomar decisiones.
1.4.2. Herramientas disponibles
Google Adwords nos facilita una serie de API’s que nos permiten descargar reports para dife- rentes periodos y métricas agregadas de diferentes maneras. En RocketROI han creado una serie de herramientas que permiten descargar dichos reports de forma sencilla usando consultas SQL.
RocketROI para la elaboración del trabajo nos ha facilitado acceso a dicha plataforma para que pudié- ramos hacer tantas consultas como quisiéramos.
Además a lo largo del trabajo usaremos el software estadístico R para un primer análisis de los datos y desarrollo del algoritmo, así como otras tecnologías como Hadoop o Mahout que explicaremos más adelante.
1.4.3. Objetivo
El objetivo del proyecto propuesto por la empresa y la universidad es: Definir una solución que permita adquirir conocimientos de la aplicación del Big Data en el márketing digital en un caso real de uso.
Más concretamente, el objetivo es poner en marcha una prueba piloto de la solución que sea ca- paz de procesar los datos y obtener un etiquetado de keywords válido para la empresa, utilizando para ello tecnologias Big Data de almacenamiento y procesamiento de datos.
Infraestructura
2.1. Descripción general
2.1.1. Análisis del problema
El problema que se nos plantea a nivel funcional es resumidamente diseñar una solución que guar- de los ficheros procedentes de la descarga de la API de AdWords, procesar estos datos aplicando el algoritmo que desarrollaremos más adelante y guardar los ficheros de salida.
Debemos reflexionar sobre cómo enfocar la solución, qué tipos de tecnologías utilizar y justificar su uso. Esta reflexión la hacemos siempre partiendo de la idea de que las características de los datos condicionan totalmente la infraestructura que se debe utilizar. Esta decisión depende principalmente de 3 factores:
- Volumen de datos que procesaremos.
- Variabilidad de los datos.
- La velocidad que requiere el proceso.
En lo referente al volumen de datos, la cantidad de información que maneja la empresa es grande, podemos estimar que incluyendo todo el registro histórico de todos los clientes hablaríamos de Teras de datos. Hay que tener en cuenta que este volumen aumenta a medida que crece la empresa, y el crecimiento de ésta es rápido.
Sin embargo, nuestro sistema únicamente tiene que almacenar reports de keywords y AdGroups y estaríamos hablando de pocos Gigas. Por tanto no tenemos un problema en cuanto al volumen que tenemos que almacenar.
El volumen de datos podría ser un problema a la hora de procesarlos. No obstante, nuestro algoritmo no necesita una gran cantidad de datos históricos. Es más, nos perjudica tomar una gran cantidad de datos históricos dado que las campañas han ido variando, y los datos podrían desvirtuarse si cogemos un histórico de demasiado tiempo atrás. Por tanto no tenemos un problema con el volumen de datos que procesaremos.
En cuanto a la variabilidad de los datos, como apuntábamos anteriormente, nos centraremos en dos tipos de reports, el de keywords y el de AdGroups. La fuente de procedencia será siempre la misma y con el mismo formato csv.
En lo referente a la velocidad de procesado, no es un proceso de importancia crítica en la empresa que necesite de una ejecución en un tiempo lo más reducido posible.
Tras un breve análisis del problema, podemos concluir que para el desarrollo de nuestra solución no tenemos, a día de hoy, un problema puramente de Big Data. Sin embargo, sí vemos un gran poten- cial en el uso de tecnologías Big Data teniendo en cuenta el rápido crecimiento que está teniendo la empresa.
El uso de estas tecnologías será beneficioso cuando se alcance un número de clientes suficientemente grande y una cierta estabilidad en las campañas que nos permitirá utilizar más datos históricos para el análisis. En este escenario la capacidad de procesamiento de un sistema Big Data jugará un papel diferencial.
2.1.2. Propuesta de solución
Proponemos por tanto una solución basada en Hadoop que nos brinda todas las ventajas del alma- cenamiento distribuido con el sistema HDFS y las ventajas del procesamiento distribuido de MapRe- duce.
Utilizaremos el software estadístico R para realizar una primera inspección y análisis de los datos.
Posteriormente traduciremos el proceso de ETL y parte del proceso analítico a PIG. Haremos uso de la librería de algoritmos de Machine learning de Mahout en la parte púramente analítica de la solución.
Vamos a justificar, sin entrar en mucho detalle, por qué hemos escogido estas tecnologías para lle- var a cabo el proyecto.
¿Por qué Hadoop?
Su sistema de ficheros distribuido (HDFS o Hadoop Distributed File System) nos proporciona un abanico de ventajas tales como tolerancia a fallos de disco, de máquina, de red y corrupción. Permite hacer cargas rápidas de datos tanto estructurados como no estructurados. Permite escalar linealmente con commodity hardware y mejora la utilización del ancho de banda ya que no moveremos los datos por la red para procesarlos, sino que moveremos el software donde estén los datos.
Procesamiento gestionado por Yarn (Yet Another Resource Negotiator). Yarn se encarga de dos cosas principalmente:
- Gestión de recursos: ResourceManager and NodeManager.
- Gestión de trabajos: ApplicationMaster.
Yarn gestiona la coordinación de recursos, el acceso a los recursos, la comunicación entre los procesos, permite escalar linealmente y dispone de gestión de fallos de máquina, de red y de procesos.
La mayor virtud de YARN y su razón de existir es que se trata de un framework multipropósito, es decir, podemos ejecutar no sólo trabajos de MapReduce sino también Tez, HBase y Spark entre otros.
¿Por qué R?
R es un software ideal para realizar un análisis previo de los datos, representarlos y nos ayudará en el proceso a hacernos una idea muy clara de cómo abordar el problema analítico. Es principalmente útil a la hora de representar los datos y dispone de librerías con todos los algoritmos que nos harán falta. También a considerar, es uno de los softwares más populares para realizar analítica de datos y tiene una gran comunidad de usuarios que proporcionan soporte en internet.
¿Por qué PIG?
Pig permite escribir en lenguaje de alto nivel, Pig Latin, y ejecutar en trabajos de MapReduce. Lo que nos ahorra tener que aprender MapReduce de alto nivel. Es muy fácil de depurar y esto permite ahorrar tiempo de desarrollo y optimización. Los datos pueden ser estructurados o sin estructura. Es extensible con UDFs (User Defined Functions) de Java, Ruby, Python... Su instalación, como veremos después es muy sencilla.
¿Por qué Mahout?
Mahout es un producto de Apache. Contiene implementaciones de una gran variedad de algorit- mos de Machine learning escalables. Sus implementaciones están pensadas para adaptarse perfecta- mente al paradigma MapReduce de Hadoop.
El diagrama del flujo de los datos sobre la solución es el siguiente:
Figura 2.1. Diagrama del flujo de los datos sobre la solución
2.2. Configuración de las máquinas virtuales
La arquitectura que proponemos tiene el objetivo de dar soporte a la escalabilidad mediante el ma- nejo y control de las dimensiones tales como volumen, velocidad y variedad. El cumplimiento eficaz y eficiente de estas dimensiones nos dará veracidad y valor logrando de esta manera cumplir con las 5V del Big Data.
Los componentes de nuestra arquitectura son:
Figura 2.2. Componentes de la arquitectura
Dado que el objetivo de este trabajo se limita a realizar una prueba piloto y no crear una infraes- tructura real, utilizaremos la virtualización utilizando el hipervisor de tipo 2, en donde las máquinas virtuales entran en un tercer nivel soportadas por un hipervisor que reposa sobre un Sistema Opera- tivo. Configuraremos las máquinas virtuales para destinarlas a hacer la función de los componentes del HDFS (DataNodes y NameNode) y del Yarn (Resource Manager, Node Manager y Application Master).
Vamos a implementar la solución Big Data con un Cluster de Hadoop que estará soportado con má- quinas virtuales usando la herramienta de Virtual Box de Oracle.
El sistema operativo a utilizar es Centos 6.6, que es una distribución mantenida por la comunidad de Red Hat Enterprise Linux (RHEL).
El detalle de la instalación y la configuración de los maquinas se encuentra en el Anexo A.
2.3. Configuración de Hadoop
Descargamos el paquete de Hadoop desde el siguiente link (http://hadoop.apache.org/releases.html) escogiendo la versión 2.7.2.
Este paquete de Hadoop se descomprime dentro del home del usuario. Para nuestro entorno será
’nn1’.
Figura 2.3. Versión 2.7.2
El esquema que mostramos a continuación es escalable horizontalmente. El diagrama básico del clus- ter es el siguiente:
Figura 2.4. Diagrama del cluster
2.3.1. HDFS
Tras haber realizado toda la configuración previa de las máquinas que hemos detallado anterior- mente, nos disponemos a configurar el Hadoop Distributed File System (HDFS). El primer paso con- siste en configurar una comunicación ágil entre las máquinas. Para la siguiente sección se utilizarán comandos en terminal y por tanto asumimos a lo largo de esta parte que los comandos se ejecutarán en un terminal de cada máquina.
Durante el resto del apartado utilizaremos la notación DN para referirnos a los DataNodes y NN para referirnos al NameNode.
Comunicación entre máquinas
El primer paso a realizar es instalar el agente que nos permitirá realizar acceso entre las máquinas mediante SSH. Abrimos un terminal en todas las máquinas y ejecutamos el comando:
sudo yum install openssh-server
Probamos que se ha instalado correctamente haciendo accesos SSH entre las máquinas con el co- mando:
ssh (IP de la máquina destino)
El comando para ver la IP de la máquina es ifconfig. Para facilitar la comunicación entre máqui- nas y evitar tener que introducir las claves de acceso cada vez debemos crear claves autorizadas en cada una de las máquinas y compartirlas con el resto de máquinas mediante ssh-copy-id. El comando para generar la clave autorizada de una máquina es:
ssh-keygen -t dsa -P ” -f /.ssh/id_dsa
A continuación convertimos esta clave en clave autorizada para acceso a la máquina con el siguiente comando:
cat /.ssh/id_dsa.pub » /.ssh/authorized_keys
Para comunicar la clave de esta máquina al resto ejecutamos el siguiente comando para cada una de las IPs de los demás equipos:
ssh-copy-id -i /.ssh/id_dsa.pub nn1@IPdestino
Este proceso lo hacemos en todas las máquinas y comprobamos que podemos acceder a todas ellas desde cualquiera de ellas sin necesidad de introducir clave.
Variables de entorno
Seguidamente nos descargamos Hadoop con el comando:
wget http://apache.rediris.es/hadoop/common/hadoop-2.7.2/hadoop-2.7.2.tar.gz
A continuación vamos a introducir las variables de entorno en el fichero bashrc. Lo editamos con el comando gedit ./bashrc. Movemos la carpeta comprimida de Hadoop a /home/nn1/ la descompri- mimos e introducimos las siguientes variables de sistema:
export JAVA_HOME=/usr/java/jdk1.7.0_79 export HADOOP_PREFIX=/home/nn1/hadoop-2.7.2
export HADOOP_CONF_DIR=/home/nn1/hadoop-2.7.2/etc/hadoop
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_PREFIX/bin
Para comprobar que se han definido correctamente las variables de entorno podemos ejecutar el co- mando echo $JAVA_HOME y debería aparecer una línea con el directorio donde se encuentra java-7- oracle, es decir: /usr/java/jdk1.7.0_79.
En el fichero de configuración de hadoop /home/nn1//hadoop-2.7.2/etc/hadoop/hadoop-env.sh de- bemos incluir igualmente la variable de entorno del java. Para ello sustituimos la línea export JA- VA_HOME=$JAVA_HOME por export JAVA_HOME=/usr/lib/jvm/java-7-oracle. De esta forma le especificamos a hadoop donde encontrar el java-7-oracle.
Configuración DataNodes
La siguiente configuración será idéntica para todos los DNs. Cuando hacemos referencia a los ficheros de configuración de hadoop son los que se encuentran en el directorio /home/nn1/hadoop- 2.7.2/etc/hadoop/.
En el fichero core-site.xml especificamos la IP del NN y el puerto de comunicación. Introducimos la siguiente configuración en el fichero:
<property>
<name>fs.defaultFS</name>
<value>hdfs://192.168.1.30:9000/</value>
</property>
Donde 192.168.1.30 es la IP del NN y 9000 el puerto.
Creamos un directorio en la raíz con el nombre de HDFS utilizando el comando mkdir -p /hdfs, y dentro creamos otro con el nombre DN con el comando mkdir -p /hdfs/DN. En este directorio se almacenarán todos los punteros y ficheros de conexión entre el NN y el DN. En caso de tener que reiniciar el cluster, es recomendable eliminar los ficheros que se generan dentro de la carpeta DN.
En el fichero hdfs-site.xml introducimos la siguiente configuración:
<property>
<name>dfs.data.dir</name>
<value>file:///hdfs/DN</value>
</property>
En este bloque especificamos el directorio de la raíz que hemos creado.
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
En el bloque anterior le especificamos el factor de replicación que queremos de los bloques. Cada bloque se replicará 3 veces. Este es el factor de replicación del HDFS por defecto y por tanto no sería necesario incluirlo. Lo incluimos para tener comodidad a la hora de cambiarlo.
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
Con este bloque desactivamos la comprobación de permisos para evitar problemas.
<property>
<name>dfs.safemode.extension</name>
<value>0</value>
</property>
Determina el tiempo del safe mode en milisegundos en el que se llega el nivel umbral. Es decir, el safe modeno se extenderá tras alcanzar el nivel umbral.
<property>
<name>dfs.block.size</name>
<value>16777216</value>
</property>
Con este bloque configuramos el tamaño de los bloques del HDFS. Los bloques tendrán un tamaño de 16Mb.
<property>
<name>heartbeat.recheck.interval</name>
<value>15</value>
</property>
Añadiendo la configuración anterior, estamos modificando el tiempo que tarda el NN en confirmar la caída de un DN. Estamos reduciendo el tiempo para hacer más ágil la visualización del funcionamiento y no tener que esperar demasiado tiempo para comprobar que ha caído uno o varios de los DNs.
Configuración NameNode
La configuración del HDFS en la máquina del NN es prácticamente idéntica a la que acabamos de describir en el apartado anterior para las máquinas de DNs.
Debemos crear una carpeta para el NN en el directorio HDFS que creamos anteriormente con el comando mkdir -p /hdfs/NN. Introducimos la dirección de esta carpeta en el fichero de configuración hdfs-site.xml:
<property>
<name>dfs.data.dir</name>
<value>file:///hdfs/NN</value>
</property>
Hasta aquí la configuración de las máquinas NN y los DNs. Ahora nos queda comprobar que el funcionamiento es el esperado.
Comprobación funcionamiento e interfaz web
Para iniciar el HDFS formateamos el NN con el comando:
hdfs NameNode -format
Seguidamente levantamos el NN con el comando:
$HADOOP_PREFIX/sbin/hadoop-daemon.sh –config $HADOOP_CONF_DIR –script hdfs start NN A través del puerto 50070 podemos acceder a la interfaz web de Hadoop. Introducimos por tanto 192.168.1.30:50070 en el navegador y abrimos la siguiente interfaz:
Figura 2.5. Interfaz de Hadoop
Hasta este punto el NN no sabe la dirección de los DNs. Los DNs tienen la dirección del NN en sus ficheros de configuración y por tanto son ellos los que contactan con el NN.
Ahora arrancamos los DNs ejecutando el siguiente comando en todas las máquinas destinadas a DN:
$HADOOP_PREFIX/sbin/hadoop-daemon.sh –config $HADOOP_CONF_DIR –script hdfs start da- tanode
En la interfaz web podemos ver como se han levantado los DNs.
Figura 2.6. Levantamiento de DNs
A continuación creamos un directorio en el HDFS con el comando siguiente:
hdfs dfs -mkdir /mbd/ (por ejemplo) En la interfaz web veremos:
Figura 2.7. Vista de la interfaz web Para cargar un fichero en el HDFS ejecutamos el siguiente comando:
hdfs dfs -put Escritorio/libro.txt /mbd (por ejemplo)
El fichero libro.txt es simplemente un ejemplo. Hay que especificar la dirección del fichero en lo- cal (Escritorio/libro.txt) y el directorio del HDFS donde queremos cargarlo (/mbd).
Figura 2.8. Carga del fichero al HDFS
Podemos comprobar que se ha creado correctamente el directorio y que se ha cargado el fichero a través de la interfaz web. Si hacemos click sobre el fichero nos indica el número de veces que está replicado y en que DNs están las replicaciones.
Figura 2.9. Replicaciones de bloques del fichero
En la imagen vemos únicamente replicaciones en dos DNs, aunque el factor de replicación es 3. Esto es porque solamente hay dos DNs levantados. Por tanto, en uno de esos dos DNs estará replicado dos veces.
Para comprobar que la tolerancia a fallos funciona correctamente escogemos un DN cualquiera y tras observar que bloques contiene lo bajamos ejecutando el comando siguiente en su máquina:
$HADOOP_PREFIX/sbin/hadoop-daemon.sh –config $HADOOP_CONF_DIR –script hdfs stop da- tanode
Vemos como trascurrido el tiempo de muerte que hemos configurado anteriormente, el NN marca el DN como muerto y los bloques que contenía están temporalmente under-replicated.
Figura 2.10. Caída del nodo
El NN replica esos bloques que hemos perdido en otros DNs de forma que conservamos un número de replicaciones igual a 3, como hemos especificado en el fichero de configuración. El HDFS está listo para funcionar.
Dado que se trata de una prueba piloto de la instalación, no destinaremos ninguna máquina a Se- condary NameNodeo Standby NameNode. Somos conscientes que en un entorno de producción real estos dos elementos serían muy recomendables.
2.3.2. YARN
En este apartado vamos a configurar YARN. La configuración que vamos a describir ahora será idéntica tanto para la máquina destinada al ResourceManager como para las máquinas destinadas a los NodeManagers a menos que especifiquemos lo contrario.
Configuración ResourceManager y NodeManagers
El primer fichero de configuración que editaremos es el mapred-site.xml. Para ello hacemos una copia del fichero mapred-site.xml.template y la guardamos como mapred-site.xml. Añadimos la pro- piedad:
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
Con esta propiedad especificamos el framework que vamos a utilizar, que es yarn. En el fichero de yarn-site.xmlintroducimos lo siguiente:
Tal como hemos comentado anteriormente, yarn es multipropósito. Con la siguiente propiedad es- pecificamos que lo queremos para utilizar trabajos de mapReduce.
<property>
<name>yarn.\textit{NodeManager}.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
En la siguiente linea indicamos la IP de la máquina que realizará la función de ResourceManager.
<property>
<name>yarn.\textit{ResourceManager}.hostname</name>
<value>192.168.1.30</value>
</property>
En la siguiente linea activamos la agregación del log. Por defecto viene deshabilitada. La agregación del log permite recoger los logs de cada contenedor y moverlos al file-system, en nuestro caso al HDFS.
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
En la máquina de los NodeManagers vamos a especificar el número de cores virtuales que le ofrece- mos al cluster para desplegar contenedores en la ejecución. Esta información es necesaria para que el Scheduler del ResourceManager pueda saber de que dispone. Por defecto cada máquina dispone de 8 cores. Debemos pensar que necesitaremos 1 para el NodeManager y 1 para el DataNode, cam- biando este parámetro a 4 ofrecemos 2 cores libres al Scheduler para lanzar contenedores. Esto lo conseguimos con la siguiente propiedad:
<property>
<name>yarn.\textit{NodeManager}.resource.cpu-vcores</name>
<value>4</value>
</property>
Vamos a personalizar también la memoria que le ofrecemos al cluster. En las máquinas de NodeMa- nagerla propiedad la cambiamos de la siguiente forma:
<property>
<name>yarn.\textit{NodeManager}.resource.memory-mb</name>
<value>6144</value>
</property>
En la máquina de ResourceManager con la siguiente:
<property>
<name>yarn.\textit{ResourceManager}.resource.memory-mb</name>
<value>6144</value>
</property>
Ofrecemos por tanto 6 GB por máquina.
Con estos pasos ya tenemos el Yarn configurado y listo para funcionar. Existe una gran variedad de propiedades que se pueden modificar para personalizar todavía más el cluster.
Con los siguientes comandos arrancamos el ResourceManager y los NodeManagers y ya podemos ejecutar trabajos en MapReduce sobre nuestro cluster:
$HADOOP_PREFIX/sbin/yarn-daemon.sh start ResourceManager $HADOOP_PREFIX/sbin/yarn- daemon.sh start NodeManager
Comprobación funcionamiento e interfaz web
Vamos a realizar una pequeña prueba para comprobar que el sistema funciona correctamente y mostrar la interfaz web del ResourceManager.
Una vez levantado el ResourceManager podemos acceder a la interfaz web a través del puerto 8088 introduciendo en el navegador: 192.168.1.30:8088
Si hacemos click en el menú de la izquierda sobre Nodes, podemos ver los DataNodes disponibles en el cluster y sus detalles:
Figura 2.11. Nodos del cluster
Para comprobar el funcionamiento, vamos a ejecutar un trabajo MapReduce. Utilizaremos un Word- Count(cuenta el número de ocurrencias de cada palabra) sobre el fichero de texto libro.txt que hemos cargado en el HDFS en el apartado anterior. Los comandos para realizar la ejecución cuando dispone- mos del código java son:
javac -cp ".:*:Escritorio/hadoop-2.7.2/share/hadoop/mapreduce/*:Escritorio/
hadoop-2.7.2/share/hadoop/common/*" WordCount.java jar cf wc.jar WordCount*.class
hadoop jar wc.jar WordCount /libro.txt /output
Una vez finalizado el trabajo podemos ver las características del mismo y si la ejecución ha tenido algún problema en el apartado del menú de la izquierda FINISHED en la interfaz web:
Figura 2.12. Finalización trabajo MapReduce
Podemos ver más detalles si hacemos click sobre el ID del trabajo:
Figura 2.13. Parámetros del Job terminado
El cluster ahora está preparado para ejecutar trabajos de MapReduce con total interacción con el HDFS.
2.3.3. PIG
En el siguiente apartado vamos a describir el proceso de instalación de PIG. Apache PIG es una plataforma para el análisis de grandes conjuntos de datos que consta de un lenguaje de alto nivel pa- ra expresar programas de análisis, junto con la infraestructura para la evaluación de los mismos. La característica sobresaliente de los programas de PIG es que su estructura es susceptible a la paraleli- zación, lo que a su vez le permite manejar enormes cantidades de información.
La capa de infraestructura de PIG se compone de un compilador que produce secuencias MapRe- duce, lo que permite a que los usuarios de Hadoop se enfoquen más en analizar los datos y dediquen menos tiempo en desarrollar aplicaciones MapReduce.
El lenguaje de programación que utiliza PIG es Pig Latin, el cuál crea estructuras tipo SQL (SQL- like), de manera que, en lugar de escribir aplicaciones separadas de MapReduce, se pueda crear un script de Pig Latin el cuál es automáticamente paralelizado y distribuido en el cluster.
Filosofía PIG:
- PIG come todo: Al igual que cualquier cerdo come cualquier cosa, PIG puede operar con cual- quier tipo de dato, sea éste estructurado, semi-estructurado o no estructurado.
- PIG vive en todos lados: A pesar de que PIG fue inicialmente implementado en Hadoop, no está orientado solamente a esta plataforma. Su propósito es ser un lenguaje de procesamiento paralelo.
- PIG es un animal domesticado: PIG está diseñado para ser controlado y modificado fácilmente por sus usuarios. PIG puede enriquecerse a través de funciones definidas por el usuario (UDF).
Con el uso de UDFs se puede extender PIG para un procesamiento personalizado.
- PIG vuela: PIG procesa datos rápidamente. La intención es mejorar el rendimiento y no las características, lo que evita que demasiada funcionalidad le impida ’volar’.
Instalación y configuración
La instalación de PIG se realiza tras descargar el paquete desde la siguiente url: http://apache.rediris .es/pig/pig-0.15.0/y descomprimirlo dentro de la carpeta home del usuario ’nn1’.
La configuración se basa en la definición de la variable de entorno PIG_HOME, dentro del profile del usuario ’nn1’. Esto se realiza editando el fichero .bashrc del usuario ’nn1’ añadiendo la siguiente línea:
PIG_HOME=/home/nn1/pig-0.15.0 PATH=$PATH:$PIG_HOME
Para más información ver [I].
2.3.4. MAHOUT
Es una librería de Machine Learning escrita en Java y preparada para trabajar con Hadoop. Tiene un gran número de algoritmos implementados para trabajar sobre las C’s del Machine Learning.
- Collaborative Filtering (Recomendadores) : Técnica para recomendaciones. Ejemplo: En base a personas a las que les gustan ciertos temas, recomendar otros temas que pudieran gustarles.
- Clustering: Este tipo de algoritmo es para descubrir estructuras en colecciones de datos. Éste es el utilizado para nuestro caso de estudio.
- Classification: Algoritmos de clasificación supervisados.
Mahout está soportada por una gran comunidad que trabaja de manera libre y compartida.
Instalación y configuración
La instalación de Mahout se realiza tras descargar el paquete desde la siguiente url: http://apache.
rediris.es/mahout/0.12.1/ y descomprimirlo dentro de la carpeta home del usuario ’nn1’.
La configuración se basa en la definición de la variable de entorno MAHOUT_HOME, dentro del profile del usuario ’nn1’. Esto se realiza editando el fichero .bashrc del usuario ’nn1’ añadiendo la siguiente línea:
MAHOUT_HOME=/home/nn1/nn1/apache-mahout-distribution-0.12.1PATH=$PATH:$PIG_HOME PATH=$PATH:$MAHOUT_HOME
2.3.5. Eclipse
Es un IDE-Integrated Development Environment (Entorno de Desarrollo Integrado) de código abierto el cuál usaremos para crear componentes a medida que nos ayuden a robustecer nuestra solu- ción BigData. El lenguaje que usaremos será java, el cuál es el lenguaje base en todo el ecosistema Hadoop.
Instalación
La instalación de Eclipse se realiza tras descargar el paquete desde la siguiente url: https://www.ecli pse.org/downloads/eclipse-packages/ y descomprimirlo dentro de la carpeta home del usuario ’nn1’.
2.3.6. JDK (Java Development Kit)
Es un conjunto de librerías que permiten desarrollar, compilar, ejecutar, generar documentación, etc en el lenguaje JAVA. Existen versiones del JDK para prácticamente todos los S.O. Nosotros hemos preferido el JDK en lugar del JRE por ser este una versión más completa que el JRE.
Instalación
La instalación de JKD se detalla en el Anexo A.
2.3.7. Apache-Maven
Es una herramienta de software para la gestión y construcción de proyectos JAVA. Dentro de nuestra solución ayudará a poder descargar las librerías del ecosistema de Hadoop como Mahout.
Instalación
La instalación de Apache-Maven se realiza tras descargar el paquete desde la siguiente url: https://
maven.apache.org/download.cgiy descomprimirlo dentro de la carpeta home del usuario ’nn1’.
Configuración
La configuración se basa en la definición de la variable de entorno M2_HOME, dentro del profile del usuario ’nn1’.
Esto se realiza editando el fichero .bashrc del usuario ’nn1’ añadiendo la siguiente línea:
M2_HOME=/home/nn1/apache-maven-3.3.9 PATH=$PATH:$M2_HOME/bin
2.3.8. HUDSON CI
Es una herramienta de Integración Continua escrita en JAVA. Trabaja con herramientas de control de versión, puede ejecutar proyectos basados en Apache Ant, Apache Maven así como también Shell script.
Esta herramienta nos ayudará en la automatización de tareas dentro del ecosistema de Apache-Hadoop.
Esta herramienta solo se instalará en la máquina donde estará el NameNode.
Instalación y Configuración
La instalación de Hudson se detalla en el Anexo A.
Análisis
En este capítulo vamos a explicar el algoritmo que hemos desarrollado para alcanzar el objetivo propuesto por RocketROI. Para ello hemos empezado trabajando con el software estadístico R [C].
Una vez hecho el algoritmo en lenguaje R, lo hemos traducido a Pig y Mahout con el fin de aplicar tecnologías Big Data al problema y comprobar si merece la pena o no en este tipo de problema.
Por proteger la privacidad de los datos de la empresa RocketROI no citaremos ninguno de sus clientes y usaremos ejemplos inventados en su lugar para explicar ciertas partes. No mostraremos tampoco ningun dato o resultado que pudiera comprometer su integridad.
3.1. Inspección de datos con R
Antes de empezar, procederemos a explicar un poco los datos. Cuanto más sepamos de ellos más fácil nos resultará la clasificación de los mismos. RocketROI pone a nuestra disposición una platafor- ma para hacer descargas de la API de Google mediante sentencias SQL. En la API dispone de una gran cantidad de reports diferentes, para nuestro análisis serán necesarios dos tipos de (reports), el de métricas a nivel de keyword [G1] y el de métricas a nivel de AdGroup [G2]. Los AdGroups son grupos de keywords agrupadas según el criterio de la empresa. En nuestro caso RocketROI las agrupa teniendo en cuenta el tipo de comportamiento que se espera de ellas así como su significado.
La cantidad de variables disponibles es muy numerosa, por lo que se van a omitir del informe aquellas que no necesitemos. Las variables que vamos a utilizar las describiremos a continuación.
A nivel de keyword:
- FirstPositionCPC: Estimación de la cantidad que puedes necesitar pagar para que tu anuncio se muestre en primera posición de la primera página de resultados de Google.
- AdGroupID: La ID del AdGroup.
A nivel de AdGroup:
- CustomerDescriptiveName: El nombre del cliente.
- AdGroupName:El nombre del AdGroup.
- AdGroupID: La ID del AdGroup.
- AdNetworkType1: Primer nivel del tipo de red.
- AdNetworkType2: Segundo nivel del tipo de red.
- AdGroupStatus: Estado del AdGroup.
- Impressions: Representa el número de veces que el anuncio ha aparecido en la página de resul- tados de Google.
- Clicks: Número de clicks.
- ConversionValue: Valor total de todas las conversiones.
- Cost: La suma del coste durante este periodo del cost-per-click (CPC) y el cost-per-thousand- impressions (CPM).
- AveragePosition: La posición de tu anuncio respecto al de otros anunciantes.
- Ctr: El número de clicks que el anuncio recibe (Clicks) dividido por el número de veces que ha aparecido (Impressions).
- SearchImpressionShare: El número de impresiones que el anuncio ha recibido dividido por el número de impresiones que se estimaba que iba a recibir.
- BounceRate: Porcentaje de clicks en los que el usuario solo visitó una página.
- AverageCpc: El total del coste de todos los clicks dividido por el número total de clicks recibido.
- Conversions: El número de conversiones para todas las acciones de conversión que has optimi- zado.
- ConversionRate: El número de conversiones dividido por el total de clicks.
Para más información consultar [G1] y [G2].
3.2. Definición del algoritmo
En esta sección vamos a explicar paso a paso el algoritmo que hemos desarrollado para satisfacer las necesidades de RocketROI. Esta parte ha sido programada en R para más tarde traducirla y usarla en Pig y Mahout.
Recordamos que el objetivo del trabajo es poder clasificar diferentes tipos de keywords en función de las métricas que hemos presentado en el apartado3.1. Para hacerlo vamos a elevarnos un nivel jerárquico y etiquetar AdGroups en vez de keywords. Esto es posible únicamente gracias a la forma de trabajar de RocketROI. La empresa crea los AdGroups de forma que todas las keywords que contengan sean del mismo tipo. Esto mantendrá el porcentaje de aciertos intacto y mejorará el rendimiento del algoritmo porque se reduce considerablemente el tamaño de los datos a procesar.
3.2.1. Tipos de etiquetas
RocketROI nos proporcionó una lista con los tipos de keywords que les gustaría poder clasificar de forma automática. A continuación mostramos los tipos de etiqueta con los que vamos a trabajar separados en dos grupos:
Por una parte tenemos las etiquetas que solamente dependen de una variable.
- Rebote: Clasificamos en ALTO, MEDIO y BAJO el porcentaje de veces que el usuario hace click en el anuncio y abandona rápidamente trás solo ver la primera página, lo cual nos ayuda a intuir que el anuncio no estaba relacionado con la busqueda del usuario.
- CPC: Clasificamos en ALTO, MEDIO y BAJO el coste-por-click medio del Adgroup.
- Conversiones: Clasificamos en ALTO, MEDIO y BAJO el número de conversiones del Ad- Group.
- Impresiones: Clasificamos en ALTO, MEDIO y BAJO el número de impresiones del AdGroup.
- Visibilidad: Clasificamos en ALTO, MEDIO y BAJO el porcentaje de Impression Share del AdGroup.
- ROI: Clasificamos en ALTO, MEDIO y BAJO el retorno por inversión. Para ello crearemos una nueva métrica llamada ROI a partir de la siguiente fórmula:
ROI=ConversionValue− Cost Cost
Por otra parte tenemos tres tipos más que requerirán de un algoritmo de clusterización para poder identificarlas.
- Marca: Son aquellas keywords que contienen el nombre del anunciante.
- Genérica: Son aquellas keywords que contienen el se refieren a términos generales del producto que ejerce el cliente. Por lo tanto podemos esperar de ellas que atraigan mucho tráfico pero pocas conversiones por el hecho de que el término buscado es poco concreto.
- Longtail: Son aquellas keywords más específicas en relación al producto final.
3.2.2. Preparación de los datos
Primero, gracias a la herramienta proporcionada por RocketROI podemos descargarnos un archivo csv con una consulta SQL con las métricas de keyword que nos interesan:
select FirstPositionCpc, AdGroupId
FROM KEYWORDS_PERFORMANCE_REPORT DURING 20160101,20160501
En este caso hemos descargado un archivo que contiene las variables FirstPositionCpc y AdGroupId.
El periodo de tiempo escogido es de 4 meses, concretamente los 4 primeros meses del año 2016.
Ahora lo que vamos a hacer es agrupar todas las keywords que pertenecen al mismo AdGroup y poner
en la columna de FirstPositionCpc de cada AdGroup la media de los FirstPositionCpc de las keywords que formen el grupo. Para ello primero leeremos el archivo csv que hemos descargado antes. Hemos de tener en cuenta que el fichero que proviene de la descarga contiene una cabecera por encima del nombre de las columnas, en la primera fila, que no nos interesa y hemos de especificar que salte la primera fila en la lectura. Además la última línea de todos los reports contiene una fila con los totales que también deberemos omitir. Por tanto leemos el fichero de la forma siguiente:
datakey <- read.csv(’XXX_Keyword.csv’,skip = 1,header=TRUE,sep=’,’) datakey = datakey[-nrow(datakey),]
Y después hacemos la agrupación de la manera anteriormente comentada y eliminamos los datos cuyo FirstPositionCpc= 0.
datos1<-aggregate(First.position.CPC ~ Ad.group.ID, datakey, mean) datos1<-datos1[datos1$First.position.CPC!=0,]
Una vez hecho esto, procedemos a leer el csv de AdGroup que hemos descargado con la consulta SQL siguiente:
SELECT CustomerDescriptiveName,AdGroupName, AdGroupId, AdNetworkType1, AdGroupStatus,Impressions, Clicks,ConversionValue, Cost,AveragePosition,
Ctr,SearchImpressionShare ,BounceRate, AverageCpc, Conversions, ConversionRate FROM ADGROUP_PERFORMANCE_REPORT WHERE Impressions > 0 DURING 20160101,20160501 Además para eliminar datos introducidos de forma automática, filtraremos la variable Network. El report de AdGroups presenta los mismos problemas en la lectura y lo leemos igual.
dataadg <- read.csv(’XXX_Adgroup_Complet.csv’,skip = 1,header=TRUE,sep=’,’) dataadg = dataadg[-nrow(dataadg),]
dataadg<-dataadg[dataadg$Network==’Search Network’,]
A continuación, con la instrucción merge de R, haremos el cruce de los dos datasets y seleccionaremos las columnas que nos interesen.
data<-merge(dataadg, datos1, by = "Ad.group.ID") #hacemos el join data<-subset(data,select=c(Ad.group.ID,CTR,Clicks,Bounce.rate, Impressions,Conv..rate,Cost,Total.conv..value,Conversions,Avg..CPC, Avg..position, First.position.CPC))
Antes de seguir avanzando, hay que tener en cuenta que R lee los datos de manera predeterminada, por lo que deberemos realizar transformaciones de los porcentajes a numéricos eliminando el símbolo del %. Además en varios campos los millares están marcados con una coma, la cuál deberemos quitar también para poder operar con ellos posteriormente:
data$CTR<-as.numeric(sub("%","",data$CTR))
data$Conv..rate<-as.numeric(sub("%","",data$Conv..rate)) data[is.na(data)] <- 0
data$Ad.group.ID<-as.factor(data$Ad.group.ID)
data$Conversions<-as.character(data$Conversions)
data$Conversions2 <- as.numeric(gsub(",", "",as.character(data$Conversions))) data$Conversions<-data$Conversions2
data$Total.conv..value<-as.character(data$Total.conv..value) data$Total.conv..value2 <- as.numeric(gsub(",", "",
as.character(data$Total.conv..value)))
data$Total.conv..value<-data$Total.conv..value2
data$Impressions<-as.numeric(data$Impressions)
data$First.position.CPC<- data$First.position.CPC/10000 data$Avg..CPC<- data$Avg..CPC/10000
Para sacar conclusiones que no se vean demasiado afectadas por el tiempo, hemos decidido filtrar los datos para quedarnos con aquellos que tengan más de cien clicks. Tras conversar con RocketROI y realizar varias pruebas, concluímos que a partir de cien clicks tenemos una masa estadística suficiente para hacer una buena clasificación.
data<-data[data$Clicks>100,]
Si el número fuera menor, clasificaríamos un mayor número de AdGroups pero introduciríamos más error. En el caso contrario, con un filtro de clicks mayor, el porcentaje de acierto sería mayor pero estaríamos clasificando un número demasiado pequeño de AdGroups.
A partir de las variables que tenemos, vamos a crear una nueva que puede ser interesante analizar.
La llamaremos positionratio y la calcularemos de la siguiente forma:
positionratio= First positionCPC AverageCPC Que en lenguaje R sería:
data$positionratio<-round((data$First.position.CPC/data$Avg..CPC),digits=3) Esta nueva variable es interesante porque usamos una métrica (FirstpositionCPC) que no depende de la keyword en la cuenta sino que es un parámetro que depende de la puja que se hace por ella por parte de todos los anunciantes. Calcularemos la media del FirstpositionCPC de todas las keywords que componen un Adgroup y dividiremos por el CPC medio del Adgroup. Este ratio que generamos nos dará información sobre el precio que estamos pagando de media por las keywords de un Adgroup entero en comparación con el resto. Podemos esperar por tanto que si se trata de un Adgroup de key- wordsgenéricas, podemos intuir que el ratio será más elevado que si se trata de una keyword LongTail porque el producto es más específico y la competencia será menor.
Recordamos que la variable First.position.CPC es la media de todas las keywords de cada AdGroup que hemos calculado al principio del script.
3.2.3. Estudio de etiquetas de una métrica
RocketROI nos ha pedido varias etiquetas que implican el estudio de una sola métrica. A conti- nuación mostramos el criterio que hemos seguido para etiquetarlas:
#REBOTE
data$Bounce.rate<-as.numeric(sub("%","",data$Bounce.rate)) dataBOUNCE<-data[data$Bounce.rate!=0,]
data$Etiqueta_BounceRate<-ifelse(data$Bounce.rate>
quantile(dataBOUNCE$Bounce.rate,0.75),’ALTO’,ifelse(data$Bounce.rate<
quantile(dataBOUNCE$Bounce.rate,0.25),’BAJO’,’MEDIO’))
#CPC
dataCPC<-data[data$Avg..CPC!=0,]
dataCPC$Avg..CPC<-dataCPC$Avg..CPC
data$Etiqueta_CPC<-ifelse(data$Avg..CPC>
quantile(dataCPC$Avg..CPC,0.75),’ALTO’,ifelse(data$Avg..CPC<
quantile(dataCPC$Avg..CPC,0.25),’BAJO’,’MEDIO’))
#CONVERSIONES
dataCONVE<-data[data$Conv..rate!=0,]
data$Etiqueta_Conver<-ifelse(data$Conv..rate>
quantile(dataCONVE$Conv..rate,0.75),’ALTO’,ifelse(data$Conv..rate<
quantile(dataCONVE$Conv..rate,0.25),’BAJO’,’MEDIO’))
#IMPRESIONES
dataIMP<-data[data$Impressions!=0,]
data$Etiqueta_Imp<-ifelse(data$Impressions>quantile(dataIMP$Impressions,0.75),
’ALTO’,ifelse(data$Impressions<quantile(dataIMP$Impressions,0.25),’BAJO’,’MED IO’))
#VISIBILIDAD
data$Search.Impr..Share<-as.numeric(sub("%","",data$Search.Impr..Share)) data$Search.Impr..Share<-as.numeric(sub("<","",data$Search.Impr..Share)) dataIMPSHARE<-data[data$Search.Impr..Share!=0,]
data$Etiqueta_Visibilidad<-ifelse(data$Search.Impr..Share>quantile(dataIMPSHARE
$Search.Impr..Share,0.75),’ALTO’,ifelse(data$Search.Impr..Share<quantile(data IMPSHARE$Search.Impr..Share,0.25),’BAJO’,’MEDIO’))
#ROI
dataROI<-data[data$Conversions!=0,]
data$Cost<- data$Cost/1000000
data$ROI<-(data$Total.conv..value-data$Cost)/data$Cost dataROI<-data[data$Conversions!=0,]
summary(dataROI$ROI)
data$Etiqueta_ROI<-ifelse(data$ROI>quantile(dataROI$ROI,0.75),’ALTO’, ifelse(data$ROI<quantile(dataROI$ROI,0.25),’BAJO’,’MEDIO’))
Para hacer una primera estimación de como clasificar las etiquetas unidimensionales, que dependen de una sola variable, hemos utilizado el elemento estadístico del cuartil. Primero excluimos del cálculo de los cuartiles aquellas observaciones con un valor de 0 en esa dimensión. El criterio de la clasificación es el siguiente:
- ALTO: cuartil 4.
- MEDIO: cuartiles 2 y 3.
- BAJO: cuartil 1.
3.2.4. Otros tipos de etiquetas
Ahora procederemos a crear las etiquetas longtail, genérica y marca. Hemos optado por un al- goritmo de clusterización, dado que no tenemos datos de keywords o Adgroups ya etiquetados que hubieran hecho que el problema se tratara con un algoritmo de clasificación. Para explicar de forma intuitiva los diferentes tipos de etiqueta que pretendemos encontrar con el algoritmo de clusterización pongamos el siguiente ejemplo:
En un e-commerce1 que vende zapatos que se llama zapatos BigData, una keyword de marca se- ría ’zapatos BigData’, una keyword genérica podría ser ’zapatos baratos’ y una keyword longtail sería
’zapatos Spark’, siendo Spark uno de los modelos de zapato.
Idealmente lo que podemos esperar de estos tipos de keywords es:
De una keyword de marca esperamos que tenga valores disparados de CTR, ya que cuando el usuario busca una marca en concreto, hay una probabilidad alta de que acabe haciendo click en el anuncio porque éste empareja perfectamente con su búsqueda. Esperamos valores muy altos de Conversion Rateporque el usuario que busca zapatos BigData conoce la marca y la probabilidad de que acabe en conversión es alta. Podemos esperar también que el CPC no sea muy alto porque la competencia en la puja por una keyword de marca debería ser pequeña.
De una keyword longtail esperamos un CTR relativamente alto también, ya que el usuario busca un producto en concreto. El Conversion Rate debería ser relativamente alto por la misma razón. Si el usuario busca ’zapatos Spark’, es porque conoce el modelo y la probabilidad de coversión es alta.
El CPC debería ser bajo en nuestro ejemplo si el modelo de zapato ’Spark’ es exclusivo de nuestra marca, ya que la competencia será menor.
Una keyword genérica es aquella que genera mucho trafico, es decir, muchas impresiones, pero con un Conversion Ratesignificativamente más pequeño que las dos anteriores. Esperamos también que ten- ga un CTR más bajo por tratarse de un término más general que no es exclusivo de nuestra marca ni de
1El término e-commerce hace referencia a las transacciones conducidas electrónicamente a través de internet.
nuestros productos. El CPC debería ser más elevado ya que habrá mucha más competencia en la pu- ja por tratarse de un término tan general como puede ser, siguiendo nuestro ejemplo, ’zapatos baratos’.
El comportamiento que esperamos de cada tipo de keyword va a variar significativamente depen- diendo del sector de mercado del cliente. La estimación que acabamos de hacer no se cumplirá de forma general para todas las campañas porque cada sector tiene sus particularidades que hacen que este comportamiento, que funciona para el caso de un e-commerce con unas características concretas, pueda no funcionar para un cliente del sector viajes (por ejemplo) o incluso para otro e-commerce con otro tipo de productos.
El etiquetado de estos tres tipos de keywords lo haremos de forma satisfactoria para un tipo de e- commerce concreto, que es el caso que mostramos aquí. Para el resto de campañas el algoritmo nece- sitaría una adaptación específica para cada caso.
3.2.5. Algoritmo k-means
Vamos a aplicar sobre nuestro conjunto de datos el algoritmo k-means. K-means es un método de agrupamiento, que tiene como objetivo la partición de un conjunto de n observaciones en k de forma que intentamos reducir la suma de las varianzas intra-cluster, esto es, la suma de las varianzas de to- das las observaciones dentro de un único cluster, grupo por grupo. Por supuesto, el mínimo se daría en la situación en la que cada observación constituyese su propio cluster, lo que arrojaría una suma total de 0. Nuestra labor como analistas consistirá en encontrar cierta parsimonia entre la suma de las varianzas intra-cluster y el número de cluster.
El problema principal del K-means es elegir el valor adecuado para k. Para seleccionar k no exis- ten técnicas analíticas ampliamente aceptadas. Como primera idea, podríamos usar el Elbow Method, que no es un criterio matemático en el sentido riguroso de la expresión, pero cuya comprensión es muy sencilla y cuyo uso sí que está muy extendido. Cabe destacar que este fue uno de los prime- ros métodos propuestos para escoger k y fue introducido por Thorndike [T], uno de los padres del clustering. Consiste en seleccionar el número de grupos en función de la variabilidad explicada, más precisamente, escogeremos k de forma que escogiendo un grupo adicional la variabilidad explicada no crezca tan sustancialmente como lo hacía para valores anteriores, así pues, se trata de un método visual y aproximado. En nuestro caso, y como veremos más adelante, lo hemos tenido que descartar.
Otra dificultad a la que se tiene que hacer frente en este problema es el propio algoritmo en sí. Co- nocemos el objetivo, la minimización de la función objetivo que en este caso es la suma de varianzas intra-cluster dado k. Pero al haber alrededor kncombinaciones, en situaciones reales, es muy difícil tener la capacidad de computación para realizar un algoritmo exacto, así pues, basados en una iden- tidad matemática, se puede desarrollar un algoritmo muy eficiente que es capaz de llegar a óptimos locales. Esta es la razón por la que cuando ejecutamos la orden kmeans en R podemos tener diferentes resultados en la misma situación.
El algoritmo k-means empieza con un conjunto inicial de k centroides. El algoritmo realiza varias iteraciones y ajusta la posición de los centroides hasta que alcanza las iteraciones máximas o hasta
que los centroides converjan a puntos fijos que varíen poco. En la siguiente figura se muestra una iteración del k-means:
Figura 3.1. Una iteración del k-means
Por último, añadir que el nombre K-means proviene, además de la k para el número de clusters, de como funciona este algoritmo citado, en el cual las observaciones se van agrupando a un cluster en cada iteración en función de la distancia al centroide del cluster, que consiste en su vector de medias en ese momento del algoritmo. Para más información ver [OADF].
Hemos elegido el algoritmo k-means entre todos los algoritmos posibles para este trabajo debido a la libertad que proporciona a la hora de elegir el número de cluster. En el marco de nuestro trabajo, éstos están bien definidos, por lo que hemos descartado algoritmos como el Canopy que te impone el número de clusters o el Fuzzy k-means en el que los puntos pueden pertenecer a más de un cluster a la vez. [SLG]
Para nuestro algoritmo vamos a seleccionar solo las tres métricas que a nuestro juicio nos aporta- rán más valor al estudio, que son: CTR, ConversionRate y positionratio. Para ello cogemos un subset solo con lo que necesitamos para evitarnos arrastrar información innecesaria.
dataclust<-subset(data,select=c(CTR,Conv..rate,positionratio))
Ahora vamos a escoger el número de grupos que crearemos. Para ello haremos un bucle y calculare- mos las variabilidades explicadas, que quedarán almacenadas en un vector.
[1] NA 68.13563 82.35304 87.31155 89.74937 91.70105 93.05593 94.18670 [9] 94.66498 95.41381 95.72514 95.76357 96.08150 96.77338 96.79320 96.62878 [17] 97.18307 96.75732 97.00178 97.14957
Vamos ahora a hacer el gráfico de las variabilidades explicadas en función del número de grupos.
5 10 15 20
707580859095
Número de grupos
Variabilidad explicada
Figura 3.2. Variabilidades explicadas en función del número de grupos
En la gráfica podemos observar que un número adecuado de clusters podría ser 9, ya que en el pun- to 9 apreciamos que la variabilidad explicada empieza a crecer mucho menos tal y como describíamos cuando introdujimos el criterio del Elbow Method. Dado que idealmente estamos buscando 3 grupos diferentes, escogemos 3 inicialmente pero después de realizar varios análisis nos damos cuenta de que alguno de los clusters que obtenemos tiene demasiada mezcla de dos tipos de Adgroup, concretamente de longtail y genérica. No obstante, una vez analizado el problema hemos llegado a la conclusión que 5 clusters nos darán mejor resultado porque nos permitirá dividir mejor esos clusters heterogéneos.
Vamos entonces a usar el algoritmo k-means para hacer 5 grupos con 20 puntos de inicio y calcu- lamos el porcentaje de variabilidad explicada, en nuestro caso un 89 %,la cual a primera vista, a falta de probar con otros valores para el número de cluster, parece ser alta.
km2 <- kmeans(dataclust,centers=5,nstart=20)
> (I <-100*km2[[6]]/(km2[[3]])) [1] 89.79324
Utilizando la instrucción princomp de R, realizamos un análisis de componentes principales para in- tentar reducir las dimensiones del conjunto de datos original. Después representamos en una gráfica las dos primeras dimensiones (sus scores, es decir, sus coordenadas en este nuevo sistema de referen- cia).
pc <- princomp(dataclust) par(mfrow=c(1,1))
x <- pc$scores[,1]
y <- pc$scores[,2]
colores <- km.def[[2]]
plot(x,y,pch=19,col=km.def$cluster,cex=0.7)
0 10 20 30 40
−8−6−4−20246
x
y
Figura 3.3. Clusterización primer plano factorial
Las individuos en este primer plano factorial parecen tener una estructura clara, es decir, somos ca- paces de discernir perfectamente patrones. Por ejemplo, los grupos azul y verde tienden a tener coor- denadas muy próximas a las del individuo medio (el punto (0,0)), mientras que el grupo negro como el grupo cyan en más medida tienden a tener valores muy positivos en la primera componente. Sin embargo, estas conclusiones son válidas para este plano factorial. Así pues, para la cantidad de infor- mación que tenemos en el primer plano factorial, hemos encontrado ciertos patrones de forma bastante satisfactoria.
Los patrones en la distribución de los grupos son visibles, a pesar de haber 5 grupos, situación bastante más complicada que en un caso simple de una clasificación binaria.
Representamos a continuación todos los planos resultado de combinar los tres factores.