terça-feira, 24 de março de 2015

R + hadoop - Big Data Analytics

      Neste post iremos discutir um tema que está em alta ultimamente, big data analytics. Mais precisamente, discutiremos como combinar o poder computacional do hadoop com a flexibilidade e variedade de algoritmos encontrados no software R.
O surgimento do hadoop no final da década passada revolucionou e continua revolucionando a forma que armazenamos e processamos os dados. Baseado em processamento paralelo, baixo custo de hardware e à prova de falhas, este projeto open source expandiu consideravelmente a capacidade de processamento sem grande elevação do custo final para o manuseio destes dados. Vale lembrar que podemos combinar quantos processadores forem necessários em um cluster hadoop, permitindo uma grande escalabilidade dos seus dados.
Para facilitar o manuseio dos dados dentro do hadoop que é uma plataforma em Java, surgiu nos anos posteriores algumas ferramentas, sendo a mais famoso o Hive, que em linhas gerais, permite o uso de uma linguagem SQL dentro de um cluster hadoop. Embora o Hive seja muito poderoso para trabalharmos com os dados, a linguagem SQL não é a mais adequada para advanced analytics.
Como complemento à linguagem SQL, várias soluções foram surgindo desde então, como o projeto Mahout, que consiste em uma biblioteca de códigos em Java de machine learning. No entanto, este projeto acabou não se consolidando como solução para analytics com hadoop.
Uma possível solução para isto é o casamento do software R com o hadoop. O R é uma linguagem de computação extremamente popular para cálculos estatísticos e, por ser uma ferramenta aberta, conta com diversos algoritmos construídos pela comunidade de programadores R ao redor do mundo.
 Trabalhamos o R com o hadoop de três formas que descreveremos a seguir, cada uma com vantagens e desvantagens. O uso de algumas delas depende exclusivamente da sua necessidade.


  • Base na memória: se os seus dados não são tão “big” assim, ou podem ser sumarizados, e há memória RAM suficiente no seu cluster, uma alternativa é fazer uma conexão JDBC e colocar esses dados na memória do R. Assim, usaremos o R normalmente, podendo aplicar qualquer um dos algoritmos disponíveis nos diversos pacotes. Com este método, também podem ser utilizados vários pacotes existentes no R para processamento em paralelo e assim conseguir utilizar todos os processadores disponíveis. Vale ressaltar que esta forma de trabalho com o R é delicada, podendo impactar o cluster se não for bem utilizada. Recomenda-se o uso de servidores dedicados para processamento R neste caso, o R Studio Web é uma solução muito interessante para isso.
  •   Uso de ferramentas pagas como o Oracle R Advanced Analytics ou o R revolution: estas empresas desenvolveram e continuam desenvolvendo alguns algoritmos para o uso do R combinado com o hadoop. No entanto, ainda há poucas funções implementadas em ambas as soluções, principalmente se compararmos com os números de algoritmos disponíveis do software R.
  • Hadoop streaming: Pela minha experiência, esta alternativa é a que atinge melhores resultados, embora seja a que exige mais trabalho para a sua implementação. O hadoop streaming é uma utilidade presente no hadoop que permite programarmos as funções Map e Reduce (filosofia Map Reduce em que o Hadoop se baseia) em qualquer linguagem que permite stdin e stdout, como R ou Python.
    A grande dificuldade desta abordagem é adaptar o seu problema dentro da filosofia
    Map Reduce, o que nem sempre é trivial e requer horas de trabalho árduo. No entanto, uma vez que as funções Map e Reduce estejam prontas, poderemos trabalhar com bases de dados gigantescas e realmente fazer analytics em Big Data.
O hadoop streaming pode ser utilizado dentro do Hive por meio da função “transform”. Para exemplificar o uso desta abordagem, construí um exemplo de contagem de palavras de um arquivo utilizando o R em Map Reduce. Tanto os dados de exemplo quantos os códigos utilizados estão disponíveis na minha conta do GitHub (https://github.com/carlosrelvas/Word_Count_R).
O arquivo “mapper_word_count.R” contém a função Map em R. A lógica é bem simples, cada mapper irá receber um pedaço do arquivo de entrada e fará a contagem de palavras em cada um destes pedaços. Assim, digamos que o primeiro mapper receba a seguinte parte do arquivo “casa casa casa gato casa gato” e o segundo “gato gato casa pato”. Cada mapper irá emitir uma lista de chave valor, em que chave será o nome da palavra e o valor a contagem parcial. Logo, o primeiro mapper emitirá {casa; 4} e {gato; 2}, enquanto que o segundo terá {gato; 2}, {casa; 1} e {pato; 1}.
Todas as chaves iguais irão para o mesmo reducer (“reducer_word_count.R”), assim, por exemplo, todas as tuplas que contém a chave “casa” irão para o mesmo reducer, que farão a contagem final. Assim os reducers irão devolver {casa; 4+1=5}, {gato; 2+2=4} e {pato;1}.
O arquivo usado para testarmos as funções é o “text.txt” e o quebramos, por conveniência, em dois (“text1.txt” e “text2.txt”) para simularmos as funções sem a necessidade de uma máquina virtual com hadoop. Assim conseguimos testar facilmente a função dentro de um ambiente Unix por meio dos seguintes comandos:

cat text1.txt | Rscript mapper_word_count.R > mapper1.txt
cat text2.txt | Rscript mapper_word_count.R > mapper2.txt
cat mapper1.txt mapper2.txt | sort -k1,1 | Rscript reducer_word_count.R.

          Os dois primeiros comandos simulam um mapper cada, enquanto que o terceiro simula um reducer ao receber as duas saídas do mapper.

O arquivo do GitHub “simulator_mapreduce.txt” contém os códigos desta simulação no Linux bem como os códigos para colocar a base dentro hadoop distributed file system (hdfs) e testar as funções dentro do Hive por meio da função transform.