Fizemos uma análise de sentimento de "tweets˜, para responder a uma pergunta: O que as pessoas sentem com relação aos 450 anos do Rio de Janeiro?
Tivemos que dar uma grande volta para podermos responder a essa simples pergunta. Usamos:
- Hadoop;
- API do Twitter;
- Google Translate API;
- SentiWordNet;
- Amazon Elastic MapReduce.
Todo o código-fonte está disponível AQUI!
Atenção
A execução deste tutorial implicará em despesas em Dólar. O uso da Google Translate API é pago e o uso do Amazon Elastic MapReduce também.
Eu já gastei cerca de US$ 15,00 para testar e rodar tudo.
O Google Cloud Platform, onde a Google Translate API fica, é pago, porém, a título de promoção, lhe dá um crédito de US$ 300,00.
A Amazon AWS também é gratuito por 1 ano. Porém, como você vai usar instâncias pagas, vai ter custos. O EMR só usa instâncias "large" e "medium", que não são cobertas pela promoção de 1 ano.
Fique ciente que os erros de configuração do Amazon EMR implicam em custos!
Se quiser, você pode baixar uma versão do Hadoop e rodar localmente em sua máquina. Também pode usar o arquivo de tweets traduzidos que eu coloquei no repositório. Assim, economizará uma grana e poderá rodar os exemplos. Eu não vou explicar como instalar o Hadoop localmente e rodar o exemplo nesse post. Mais tarde, eu postarei alguma coisa.
Como fazer
Para responder à pergunta: "O que as pessoas sentem com relação aos 450 anos do Rio de Janeiro?", temos alguns problemas. Vamos ver como fazer essa análise:
- Temos que coletar os tweets. Existe uma API do Twitter, que faz exatamente isso. Basta nos cadastrarmos para obter uma chave de acesso;
- Precisamos de alguma maneira para analisar os sentimentos dos textos. Há um arquivo que já tem essa classificação: o SentiWordNet;
- Mas há um problema: O SentiWordNet só tem versão em inglês... Precisamos dar um jeito de traduzir nossos tweets para inglês, e podemos usar a Google Translate API;
- Temos que coletar os tweets, traduzi-los e rodar o MapReduce. Fazer isso com uma rede doméstica e usando um computador pessoal, pode ser muito demorado. Por isso, vamos usar os serviços da Amazon AWS: EC2, S3, CloudFormation e Elastic MapReduce;
Temos dois projetos Java Maven que executam essas tarefas. Acesse o código-fonte no GitHub e baixe o zip ou clone o repositório. Importe os projetos para o Eclipse.
O projeto "twitterparser" gera um Jar que coleta os "tweets", traduzindo-os para inglês. Nesse projeto, eu uso a biblioteca: "Hosebird Client", que já coleta os tweets selecionando palavras-chave.
A saída é um arquivo "tweets-translated.txt", que eu uso como "input" para o MapReduce.
O projeto "sentimentanalysis" contém as 3 classes necessárias para invocar o Hadoop: Mapper, Reducer e Instanciador. Nele, eu carrego o SentiWordNet (dentro do Mapper) e vou analisando os tweets nas seguintes categorias:
- VERY_POSITIVE;
- VERY_NEGATIVE;
- NEUTRAL;
- POSITIVE;
- NEGATIVE;
Para classificar os tweets, eu usei a classe de exemplo do SentiWordNet, e a orientação deste POST do StackOverflow, (usuário: Maroun Maroun) que funcionou muito bem.
Também aproveitamos o modelo criado por Frank Willian Cardoso de Oliveira, da universidade de Maringá - PR, que realizou trabalho usando técnica de tradução e SentiWordNet.
Também aproveitamos o modelo criado por Frank Willian Cardoso de Oliveira, da universidade de Maringá - PR, que realizou trabalho usando técnica de tradução e SentiWordNet.
Primeiro passo: Registrar-se nas APIs e no AWS
Aprenda a usar o AWS EMR lendo esse livro da Amazon (gratuito na kindle store). Tente rodar o exemplo que ele dá, que usa programas prontos em Python.
Cadastre-se para usar a API do Twitter, e salve os dados:
- consumerKey;
- consumerSecret;
- secret;
- token;
Cadastre-se para usar a Google Translate API e pegue sua API Key.
Atenção: O uso da Google Translate API é pago! Você vai pagar pelo uso! Embora eles lhe dêem US$ 300,00 de promoção, fique ciente que o uso será cobrado.
Se você optou por usar o arquivo de exemplo, e rodar em sua máquina, então não haverá custos e nem será necessário se inscrever no AWS e no Google Cloud Platform.
Segundo Passo: Criar um Bucket S3
Agora é o momento de criar um "Bucket S3", para armazenar os dados. Para isto, abra a S3 Console e crie um novo Bucket.
Eu dei o nome de "obomprogramadors3". O nome do Bucket tem que ser único. Guarde bem o nome que você deu e, onde estiver escrito "obomprogramadors3" (neste tutorial) substitua pelo nome do seu Bucket.
Atenção: Não use espaços, caracteres especiais e underscore! Só letras e números!
Crie três folders: "collector", "input" e "mapper". Selecione os três e torne-os públicos. Basta selecionar a "Action": "Make Public".
No folder "collector", vamos colocar o jar e os arquivos necessários para rodar o nosso "twitterparser". No folder "input", vamos colocar o arquivo "tweets-translated.txt", e, no folder "mapper", vamos colocar o nosso Jar de MapReduce e o nosso arquivo SentiWordNet.
Usar um Bucket S3 é a única maneira de mover dados de e para as instâncias EC2 e o cluster EMR.
Terceiro passo: Criar uma instância EC2 para rodar o coletor de tweets
Se você usar uma instância micro, e estiver dentro do prazo de 1 ano gratuito no AWS, não pagará nada por isso. Porém, caso não atenda a essas condições, você será cobrado pelo uso. Uma alternativa é usar o arquivo "tweets-translated.txt" que eu forneci. Outra, seria rodar o "twitterparser" em sua própria máquina. Basta ter uma boa internet para isso.Usando o Eclipse, gere um Jar executável do projeto "twitterparser", escolhendo: “Extract required libraries into generated JAR”.
Suba esse Jar para o seu Bucket S3, jogando-o no folder "collector".
Na etapa 2: "Choose an Instance Type", selecione "t2-micro". Clique em "review and launch". Clique em "launch" e selecione seu par de chaves (arquivo Pem que você criou quando se cadastrou no AWS).
Clique no link da frase: "The following instance launches have been initiated: i-507a02aa", para ver a sua instância na console de gerenciamento. Quando ela estiver rodando, você verá uma imagem assim:
Anote as seguintes informações:
Anote as seguintes informações:
- instance id;
- public DNS.
Agora, podemos iniciar uma sessão SSH com a instância e rodar o coletor. Se você usa MS Windows, tem que baixar o programa Putty. Se você usar Mac ou Linux, pode usar o comando SSH normal:
ssh -i <path do arquivo pem> ec2-user@<public dns>
Você deve informar o caminho para o seu arquivo Pem, que você criou quando se cadastrou no AWS. E deve informar o usuário "ec2-user" e o dns público da sua instância.
Bem, agora, você precisa rodar o coletor.
Para começar, temos que instalar as ferramentas de gerenciamento do S3, para podermos ler e gravar arquivos no nosso Bucket:
- cd /etc/yum.repos.d
- sudo wget http://s3tools.org/repo/RHEL_6/s3tools.repo
- sudo yum install s3cmd
- cd ~
Agora, é só copiar o Jar para a pasta do usuário:
s3cmd —configure get s3://obomprogramadors3/collector/twitterparserexec.jar
Lembre-se de mudar o nome do Bucket ( o meu é "obomprogramadors3"). A primeira vez, tem que rodar o “—configure”, que vai te pedir: Access key, Token e senha de encriptação, que você obteve quando criou sua conta no AWS.
Crie um arquivo chamado "config.json", na pasta home, com o seguinte conteúdo:
{
"consumerKey" : "<twitter consumer key>",
"consumerSecret" : "<twitter consummer secret>",
"limit" : 50,
"secret" : "<twitter secret>",
"token" : "<twitter token>",
"googleApiKey": "<google translate API key>",
"terms" : ["rio 450"],
"output" : "<output folder>"
}
Preencha com os dados da API do Twitter e do Google Translate. Na propriedade "terms", indique um vetor JSON com os strings que você quer selecionar. Somente os tweets contendo esses termos serão selecionados.
A propriedade "limit" é o número máximo de tweets a serem processados. Se você deixar um número muito grande, o processo vai demorar mais. Para essa demonstração, 50 tweets é o suficiente, embora seja estatisticamente insignificante.
A propriedade "output" é o folder de saída, por exemplo: "./", para o diretório corrente.
Agora, é só rodar o coletor:
java -jar twitterparserexec.jar ./config.json
Após a execução, devemos copiar o resultado para a pasta "input", em nosso Bucket. Lembre-se que você está acessando sua instância EC2 via SSH.
s3cmd put s3://obomprogramadors3/input/ ./tweetes-translated.txt
Finalmente, termine a instância EC2, caso contrário, ficará pagando por ela. Acesse a console, marque a instância e selecione a "Action" "Instance state" / "Terminate".
Atenção: Certifique-se que sua instância esteja como "Terminated" para evitar cobranças desnecessárias!
Quarto passo: Criar um Cluster EMR para realizar a operação de MapReduce
Bom, antes de continuar, lembre-se que esta é a etapa mais custosa desse processo. Eu estimo que você vá gastar algo entre 5 e 15 dólares, dependendo da quantidade de tweets e dos erros que tenha cometido.
Para não perder tempo, crie um JAR do MapReduce, do tipo "runnable". Usando o eclipse, selecione o projeto "sentimentanalysis" e exporte como "runnable jar", mas selecione: “Extract required libraries into generated JAR”.
Suba o Jar para o s3, no folder mapper, e marque-o como público.
Abra a console do EMR e crie um Cluster.
Ao criar o Cluster EMR:
- Marque "logging enabled" e selecione o log folder location para a raiz do seu bucket:
s3://obomprogramadors3.
- Em “Software configuration”, desinstale as três aplicações: Hive, Pig e Hue, pois não vamos utilizá-las nesse tutorial.
- Em “security and access”, selecione o seu arquivo pem no campo: “EC2 key pair”.
- Crie dois “steps”:
- Copiar o arquivo SentiWordNet para o HDFS. Antes de copiar, renomeie o arquivo e retire todos os caracteres Underscore “_”. Isso dá problema!
- Rodar o Jar do MapReduce que você criou
STEP 1:
Crie um step “Custom Jar:
- Step Type: Custom JAR
- Name: My Custom JAR
- Jar Location: /home/hadoop/lib/emr-s3distcp-1.0.jar
- Arguments: --src s3://obomprogramadors3/mapper/ --dest hdfs:///local/
- Action on failure: Terminate cluster
Atenção: Substitua "obomprogramadors3" pelo nome do seu Bucket.
STEP 2:
Crie um step “Custom Jar”:
- Name: “SentiExec:
- Jar: s3://obomprogramadors3/mapper/sentiexec.jar
- Arguments:
- /local/SentiWordNet.txt s3n://obomprogramadors3/input/tweets-translated.txt s3n://obomprogramadors3/output/
- Action on failure: Terminate cluster
Atenção: Substitua "obomprogramadors3" pelo nome do seu Bucket.
- No final, marque “Auto-terminate” para Yes.
Ao criar o Cluster, ele será provisionado e vai executar os steps
Selecione “Create cluster” e observe a página. Quando o estado aparecer “Terminated”, você pode pegar os arquivos dentro de /output, em seu bucket.
Os arquivos estão dentro da pasta "output", em seu Bucket:
Ele gera vários arquivos, e você tem que consolidá-los. Se quiser, pode criar uma etapa "streaming program", para agregar os arquivos:
--input hdfs:///temp/intermediate/ \
--output s3n://<path-to-bucket>/output-reports-dir/ \
--mapper /bin/cat \
--reducer org.apache.hadoop.mapred.lib.IdentityReducer \
--args -jobconf,mapred.reduce.tasks=1
O resultado
Após consolidar os resultados, obtive:
- VERY_POSITIVE 3
- VERY_NEGATIVE 1
- NEUTRAL 39
- POSITIVE 7
- NEGATIVE 8
O sentimento geral é mais neutro para positivo do que negativo.
Limitações e conclusões
Usar o SentiWordNet não é a melhor das alternativas, e, certamente, existem processos melhores, mas dá um resultado razoavelmente correto.
A coleta de um número maior de tweets, juntamente com outras fontes, como feeds, pode dar maior valor estatístico à análise.
Nenhum comentário:
Postar um comentário