Identificação de dificuldades e questões de
interesse de desenvolvedores de aplicações para
Big Data com o framework Apache Spark
Denis José Sousa de Albuquerque
Natal-RN Setembro de 2019
Identificação de dificuldades e questões de interesse de
desenvolvedores de aplicações para Big Data com o
framework Apache Spark
Dissertação de Mestrado apresentada ao Pro-grama de Pós-Graduação em Sistemas e Computação do Departamento de Informá-tica e MatemáInformá-tica Aplicada da Universidade Federal do Rio Grande do Norte como re-quisito parcial para a obtenção do grau de Mestre em Sistemas e Computação.
Linha de pesquisa:
Linguagens de Programação e Métodos For-mais
Orientador
Prof. Dr. Umberto Souza da Costa
PPgSC – Programa de Pós-Graduação em Sistemas e Computação DIMAp – Departamento de Informática e Matemática Aplicada
CCET – Centro de Ciências Exatas e da Terra UFRN – Universidade Federal do Rio Grande do Norte
Natal-RN Setembro de 2019
Apache Spark - Dissertação. 4. Modelagem de tópicos
probabilística - Dissertação. 5. Latent Dirichlet Allocation (LDA) - Dissertação. 6. Stack Overflow - Dissertação. 7.
Taxonomia - Dissertação. I. Costa, Umberto Souza da. II. Título. RN/UF/CCET CDU 004
Agradeço à minha esposa, Mirella Albuquerque, pelo apoio em todos os momentos. Aos amigos Roberta Freitas e João Batista pelas inúmeras contribuições.
Ao professor Dr. Martin Musicante pelas valiosas e sempre bem-humoradas colabora-ções.
Ao meu orientador, Prof. Dr. Umberto Costa, pela oportunidade, confiança, ensina-mentos e paciência.
Este trabalho não seria possível sem a participação de vocês. Obrigado.
Resumo
Este trabalho de pesquisa busca identificar e classificar as principais dificuldades e questões de interesse dos desenvolvedores de aplicações para o processamento de Big Data utili-zando o framework Apache Spark. Nesse sentido, utilizamos o algoritmo Latent Dirichlet Allocation para realizar a modelagem probabilística de tópicos em informações extraí-das do Stack Overflow, uma vez que não é viável a inspeção manual de todo o conjunto de dados. A partir do conhecimento obtido pelo estudo abrangente de trabalhos rela-cionados, estabelecemos e aplicamos uma metodologia baseada nas práticas usualmente empregadas. Construímos aplicações Spark para execução automatizada das tarefas, tais como a seleção e preparação dos dados, o agrupamento de tópicos – aplicação do algo-ritmo de modelagem probabilista para várias configurações – e a computação de métricas. Análises sobre os resultados obtidos foram conduzidas por um grupo composto por 5 pes-quisadores: dois professores doutores, um aluno doutorando e dois alunos mestrandos. A partir da análise semântica dos rótulos atribuídos para cada um dos tópicos identificados, uma taxonomia de interesses e dificuldades foi construída. Por fim, estabelecemos um ranqueamento dos temas mais importantes de acordo com as várias métricas calculadas e comparamos os métodos e resultados de nosso estudo com os apresentados em outro trabalho.
Palavras-chave: Big Data, Apache Spark, modelagem de tópicos probabilística, Latent Dirichlet Allocation (LDA), Stack Overflow, taxonomia.
Data application developers using the Apache Spark
Author: Denis José Sousa de Albuquerque Supervisor: Prof. Dr. Umberto Souza da Costa
Abstract
This research aims to identify and classify the main difficulties and issues of interest of Apache Spark application developers regarding the framewok usage. For this purpose, we use the Latent Dirichlet Allocation algorithm to perform a probabilistic modeling of topics on information extracted from Stack Overflow, since the manual inspection of the entire dataset is not feasible. From the knowledge obtained by the comprehensive study of related works, we established and applied a methodology based on the practices usually employed. We developed Spark applications for the automated execution os tasks, such as the data selection and preparation, the discovery of topics - applying the probabilistic modeling algorithm with various configurations - and metrics computation. Analyzes of the results were carried by a group of 5 researchers: two doctor professors, one doctoral student and two master students. Based on the semantic analysis of the labels assigned to each of the identified topics, a taxonomy of interests and difficulties was constructed. Finally, we ranked the most important themes according to the various calculated metrics and compared the methods and results of our study with those presented in another work. Keywords: Big Data, Apache Spark, Probabilistic Topic Models, Latent Dirichlet Alloca-tion (LDA), Stack Overflow, Taxonomy.
5 APIs de Spark e Spark SQL. Adaptado de (ARMBRUST et al., 2015b). . p. 27
6 Transformação de um Dataframe utilizando Spark SQL . . . p. 29 7 Parametrização do Algoritmo LDA. . . p. 35 8 Exemplo de página do Stack Overflow com pergunta e uma resposta aceita3. p. 37
9 Valores utilizados nos trabalhos relacionados para o hiperparâmetro α. p. 52 10 Valores utilizados nos trabalhos relacionados para o hiperparâmetro β. p. 52 11 Atividades comumente realizadas. . . p. 64 12 Visão geral da metodologia. . . p. 65 13 Inter-relacionamento entre tópicos dos experimentos para Coeficiente de
Jaccard maior que 0,3. . . p. 77 14 Dados do processo de rotulação de tópicos nos experimentos . . . p. 84 15 Árvore de conceitos relacionados à abstração de dados. . . p. 87 16 Árvore de conceitos relacionados à abstração de processos. . . p. 87 17 Árvore de conceitos relacionados ao uso de bibliotecas. . . p. 88 18 Árvore de conceitos relacionados ao gerenciamento de arquivos. . . p. 89 19 Árvore de conceitos relacionados à integração e execução de aplicações
de aplicações Spark. . . p. 91 21 Árvore de conceitos relacionados a falhas em geral. . . p. 91 22 Árvore de conceitos relacionados à linguagens. . . p. 92 23 Taxonomia de interesses e dificuldades acerca do processamento de Big
Data utilizando o framework Apache Spark. . . p. 93 24 Distribuição de temas de acordo com a métrica T S. . . p. 96 25 Distribuição de temas de acordo com a métrica V S. . . p. 97 26 Distribuição de temas de acordo com a métrica AS. . . p. 98 27 Distribuição de temas de acordo com a métrica CS. . . p. 98 28 Distribuição de temas de acordo com a métrica F S. . . p. 99 29 Distribuição de temas de acordo com a métrica SS. . . p. 100 30 Distribuição de temas de acordo com a métrica T E. . . p. 101 31 Distribuição de temas de acordo com a métrica DT . . . p. 102 32 Distribuição dos grupos de temas. . . p. 102 33 Importância dos temas de acordo com as diversas métricas aferidas. . . p. 103 34 Métricas para o grupo Abstração de Dados. . . p. 104 35 Métricas para o grupo Abstração de Processos. . . p. 104 36 Métricas para o grupo Bibliotecas. . . p. 104 37 Métricas para o grupo Falhas. . . p. 104 38 Métricas para o grupo Gerenciamento de Arquivos. . . p. 105 39 Métricas para o grupo Linguagens . . . p. 105 40 Métricas para o grupo Integração e Execução. . . p. 105
5 Exemplo de matriz de proporções tópicos para os documentos em um
corpus de N documentos . . . p. 58 6 Quantidades de documentos e tópicos por trabalho relacionado. . . p. 69 7 Resultado do LDA para 20 Tópicos. . . p. 70 8 Exemplos de documentos para o tópico T1. . . p. 72 9 Distribuição de termos para dois tópicos semelhantes entre experimentos. p. 74 10 Estatística descritiva sobre valores do Coeficiente de Jaccard. . . p. 75 11 Distribuição de frequências em intervalos de classe para os Coeficientes
de Jaccard calculados. . . p. 75 12 Rótulos padronizados para as diversas Modelagens de Tópicos . . . p. 81 13 Valores das métricas para a modelagem de 50 tópicos . . . p. 94 14 Coeficientes de Pearson calculados para identificar o grau de correlação
linear entre as métricas. . . p. 96 15 Correspondência de tópicos entre os utilizados em nosso trabalho e os
SQL – Structured Query Language
RDBMS – Relational Database Management Systems API – Application Programming Interface
RDD – Resilient Distributed Dataset DAG – Directed Acyclic Graph JVM – Java Virtual Machine
IDE – Integrated Development Environment LDA – Latent Dirichlet Allocation
1.4 Organização do Documento . . . p. 17
2 Revisão Bibliográfica p. 18
2.1 Big Data . . . p. 18 2.2 Apache Spark . . . p. 20 2.2.1 Resilient Distributed Dataset (RDD) . . . p. 23 2.2.2 Dataframes . . . p. 25 2.2.3 Datasets . . . p. 29 2.3 Modelagem de Tópicos . . . p. 30 2.3.1 Latent Dirichlet Allocation . . . p. 32 2.4 Stack Overflow . . . p. 36
3 Trabalhos Relacionados p. 40
3.1 Preparação do Corpus . . . p. 42 3.2 Parametrização do LDA . . . p. 49 3.3 Computação de Métricas e Análise de Resultados . . . p. 55
4 Experimentos p. 63
4.3 Pré-processamento de Textos . . . p. 67 4.4 Aplicação do LDA . . . p. 68 4.5 Computação de métricas e análises . . . p. 71
5 Resultados p. 80
5.1 Tópicos Identificados . . . p. 80 5.2 Taxonomia de Dificuldades e Interesses . . . p. 86 5.3 Importância Relativa dos Tópicos . . . p. 94 5.4 Comparação com Trabalho Relacionado . . . p. 106 5.4.1 Preparação do Corpus . . . p. 106 5.4.2 Parametrização do LDA . . . p. 107 5.4.3 Computação de Métricas e Análise de Resultados . . . p. 107
6 Considerações Finais p. 110
6.1 Principais Contribuições . . . p. 111 6.2 Limitações . . . p. 112 6.3 Trabalhos Futuros . . . p. 112
O grande volume de dados disponível nos dias atuais tem criado novos desafios e oportunidades. O termo Big Data é frequentemente utilizado para referir-se a grandes conjuntos de dados (datasets) que crescem rapidamente e possivelmente contém dados em diversos formatos. Um ambiente de computação distribuída é normalmente necessário para processar o Big Data, uma vez que o grande volume de dados pode exceder as capacidades de armazenamento e processamento de uma única máquina. Neste cenário, é necessário que os desenvolvedores de software tratem questões difíceis como o particionamento dos dados, a distribuição da computação e o tratamento das falhas que ocorrem de forma muito mais complexa.
Vários esforços de pesquisa foram realizados com objetivo de ajudar os desenvolve-dores no enfrentamento da complexidade de sistemas distribuídos. Conforme declarado por Ranganathan e Campbell (2007), os desenvolvedores geralmente enfrentam grandes curvas de aprendizagem antes que possam iniciar a programação de um grande sistema distribuído. Nesse sentido, o uso de tecnologias bem estabelecidas – como, por exemplo, a linguagem de consulta SQL (Structured Query Language) – pode ajudar nesse processo, uma vez que os desenvolvedores serão capazes de utilizar seu conhecimento prévio, bem como já existe uma grande quantidade de material educacional disponível.
Frameworks de programação têm sido propostos para ajudar os desenvolvedores de sistemas distribuídos (RANGANATHAN; CAMPBELL, 2007). Um exemplo de framework é
o Apache Spark1 que foi lançado em 2010 e tem sido adotado por muitas organizações,
tornando-se o mais ativo projeto de código aberto para processamento de Big Data, com mais de 1.200 pessoas que contribuíram para o projeto (XIN, 2018).
Spark é um framework de computação em cluster – um conjunto de computadores que compartilham seus recursos e trabalham como um único sistema – para o desenvol-vimento de aplicações de processamento de dados com grande escalabilidade e tolerância
1
a falhas (ZAHARIA et al., 2010). Utilizando Spark, os desenvolvedores escrevem programas
que implementam operações em alto-nível, utilizando alguma das linguagens de progra-mação suportadas (Java, Scala, Python ou R), enquanto que o framework trata boa parte das complexidades relacionadas a distribuição dos dados e da computação. Usuários do Spark também podem fazer uso de um conjunto de bibliotecas que proveem uma grande variedade de funcionalidades, incluindo a biblioteca Spark SQL para o processamento de dados relacionais, MLlib para algoritmos de aprendizagem de máquina, GraphX para o manipulação de grafos e Spark Streaming para o processamento de fluxos contínuos de dados.
No contexto do processamento de dados, a linguagem SQL e os RDBMS (Sistemas Gerenciadores de Bancos de Dados Relacionais, do inglês Relational Database Manage-ment Systems) têm sido bastante utilizados. A popularidade de SQL é uma evidência que desenvolvedores preferem utilizar consultas declarativas para o processamento de dados. Entretanto, de acordo com Armbrust et al. (2015b), a abordagem estritamente relacional utilizando SQL é insuficiente para muitas aplicações de Big Data, tais como aquelas que empregam algoritmos de aprendizagem de máquina e processamento de grafos. Spark, mediante uso da biblioteca Spark SQL, busca permitir o uso combinado tanto de con-sultas declarativas relacionais quanto de algoritmos procedimentais imperativos. Spark SQL estende Spark com APIs (Interface de Programação de Aplicativos, do inglês Ap-plication Programming Interface) construídas para prover um ambiente integrado e de fácil uso. Segundo Armbrust et al. (2015b), benchmarks e feedbacks de usuários mostram que Spark SQL torna significativamente mais simples e eficiente a escrita de pipelines de processamento de dados que misturam o processamento relacional e o procedural.
Apesar do suporte oferecido pelas bibliotecas, a implementação de uma aplicação para processamento de Big Data utilizado Spark não é uma tarefa trivial. Considerando que os desenvolvedores geralmente recorrem à sistemas de perguntas e respostas disponíveis na Internet para sanar dúvidas, este trabalho propõe a identificação e classificação das questões comumente enfrentadas por programadores Spark no desenvolvimento dessas aplicações.
Dentre as plataformas de perguntas e respostas, o maior exemplo é o Stack Overflow2
que, com mais de 18 milhões de perguntas e mais de 28 milhões de respostas registradas3,
tornou-se um grande e popular repositório de conhecimento relacionado ao desenvolvi-mento de softwares. Isso faz com que ele seja uma importante fonte de dados para
apren-2https://stackoverflow.com 3
seja possível organizá-los, sumarizá-los, visualizá-los, etc (BLEI, 2012a). O Latent Dirichlet
Allocation é a técnica mais frequentemente utilizada para modelagem de tópicos (TREUDE; WAGNER, 2018). Trata-se de algoritmo para modelagem probabilística de tópicos que
emprega métodos estatísticos pelos quais busca-se inferir os assuntos (tópicos) abordados em um conjunto de documentos a partir das palavras que o compõem. Discutiremos essa técnica com mais detalhes na Seção 2.3.
Dessa forma, este trabalho propõe identificar as dificuldades e interesses de desenvol-vedores relacionadas ao desenvolvimento de aplicações para o processamento de grandes volumes de dados utilizando o Apache Spark. Esperamos alcançar esse resultado através da extração de conhecimento – a partir de perguntas e respostas feitas por desenvolvedores Spark – da plataforma Stack Overflow. Acreditamos que esse trabalho revele observações interessantes acerca dos desafios encontrados pelos desenvolvedores Spark, sendo estas informações úteis não somente para os desenvolvedores de aplicações, mas também para pesquisadores, educadores e os próprios criadores do framework. Considerando a enorme quantidade de documentos a serem estudados, o que inviabiliza sua inspeção, análise e síntese manual, recorreremos ao auxílio de técnica de modelagem probabilística de tópicos.
1.1
Objetivos
O objetivo principal desta pesquisa é o de identificar e classificar as principais difi-culdades e interesses de desenvolvedores de aplicações para o processamento de Big Data utilizando o framework Apache Spark.
Propomos uma taxonomia construída a partir da modelagem probabilística de tópicos aplicada sobre dados extraídos da plataforma Stack Overflow. Avaliar como a modelagem probabilística de tópicos pode ser utilizada na construção de uma hierarquia de assuntos é um objetivo secundário deste trabalho.
O estudo detalhado dos trabalhos de pesquisa que aplicaram o algoritmo Latent Diri-chlet Allocation para modelagem probabilística de tópicos em datasets extraídos do Stack Overflow é outro objetivo secundário deste trabalho. Esse estudo é importante para iden-tificar como o algoritmo foi aplicado e parametrizado, além de indicar como os dados de entrada foram preparados e como os resultados obtidos foram analisados.
Para identificação das questões mais importantes, objetivamos também ranquear os tópicos a partir de diversas métricas relacionadas a frequência de ocorrência das questões e de sua popularidade na plataforma de perguntas e respostas.
1.2
Motivação
Embora exista uma boa quantidade de documentação sobre o Apache Spark, os pro-gramadores frequentemente recorrem a plataformas de perguntas e respostas para sanar dúvidas e encontrar ajuda no desenvolvimento de aplicações para processamento de Big Data. É necessário identificar sistematicamente as dificuldades frequentemente encontra-das por esses desenvolvedores para melhor ajudá-los.
Taxonomias são ferramentas úteis para organização do conhecimento na medida em que proveem uma estrutura hierárquica que facilita a classificação e o acesso ao conhe-cimento. Uma taxonomia de interesses e dificuldades frequentemente enfrentadas pelos desenvolvedores pode ser um passo chave para endereçar os problemas de forma sistemá-tica. Em nosso cenário, a taxonomia de interesses e dificuldades pode ser utilizada para categorizar os tipos de problemas e apontar estratégias de intervenção apropriadas. Por exemplo, ela poderia ser utilizada para produzir guias de práticas de desenvolvimento, com recomendações para a melhoria da qualidade de aplicações Spark e diminuição da quantidade de problemas enfrentados durante o desenvolvimento das aplicações.
Ainda, esse entendimento é útil não somente para os desenvolvedores, mas também para as comunidades de educadores e de pesquisadores que podem utilizar esse conheci-mento para decidir onde concentrar seus esforços.
1.3
Contribuições
Este trabalho apresenta as seguintes contribuições:
Stack Overflow;
5. Implementação e disponibilização de uma Aplicação Spark de código aberto para aplicação de modelagem probabilística de tópicos sobre dados do Stack Overflow.
1.4
Organização do Documento
O restante deste documento segue a seguinte organização:
• No Capítulo 2 apresentamos uma revisão bibliográfica com os conceitos necessários ao entendimento e desenvolvimento deste trabalho;
• No Capítulo 3 discutimos em detalhes os trabalhos relacionados a este, apresentando os métodos, técnicas e métricas utilizadas neles. O conhecimento obtido a partir do estudo dos trabalhos relacionados serão aplicados na condução de experimentos para obtenção de dados necessários para alcançar nossos objetivos;
• O Capítulo 4 discorre sobre a metodologia concebida para esse estudo, bem como sobre os experimentos realizados.
• No Capítulo 5 apresentamos os resultados obtidos a partir da modelagem de tópicos, a taxonomia de dificuldades e interesses de desenvolvedores, a identificação dos principais assuntos relacionados ao uso do Apache Spark;
• O Capítulo 6 encerra o documento com as considerações finais, contribuições do estudo e propostas de trabalhos futuros.
2
Revisão Bibliográfica
Neste Capítulo apresentamos uma revisão bibliográfica acerca dos conceitos necessá-rios ao entendimento e desenvolvimento deste trabalho. Na Seção 2.1 conceituaremos o Big Data e as razões que levaram à construção de frameworks como o Apache Spark. O funcionamento e arquitetura do framework Apache Spark será abordado em detalhes na Seção 2.2. A modelagem de tópicos e o algoritmo Latent Dirichlet Allocation serão trata-dos na Seção 2.3. Por fim, apresentamos informações sobre a plataforma Stack Overflow na Seção 2.4.
2.1
Big Data
O termo Big Data popularizou-se nos últimos anos devido a natureza pervasiva das tecnologias digitais e da grande variedade de aplicações baseadas em dados (MAURO; GRECO; GRIMALDI, 2016). Segundo Hilbert e López (2011), a quantidade de dados
ar-mazenados têm crescido exponencialmente. Talvez por ser algo novo, a conceituação do Big Data muitas vezes é imprecisa, com várias definições encontradas na literatura. O termo pode dar a impressão de estar relacionado apenas a grandes volumes de dados, entretanto seu uso também se refere à outras características dos dados, tais como sua va-riedade e a velocidade em que são gerados. Buscando estabelecer um consenso a cerca de uma definição precisa, Mauro, Greco e Grimaldi (2016) estudaram a literatura científica e propuseram a seguinte definição:
Big Data representa os ativos de informação caracterizados por tão grande volume, velocidade e variedade que requerem tecnologias e métodos ana-líticos específicos para sua transformação em valor (MAURO; GRECO; GRIMALDI, 2016). .
Extrair valor do Big Data não é uma tarefa simples, pois envolve a análise de dados heterogêneos e desestruturados que crescem em um ritmo tão acelerado que os Sistemas Gerenciadores de Bancos de Dados e as ferramentas de análise tipicamente utilizadas não
mover o uso de clusters (grupos de computadores que compartilham recursos de hardware) na realização de computações de forma paralela e distribuída. Apache Hadoop1 é um
im-portante exemplo de solução para Big Data. Ele é um framework para o processamento distribuído de grandes conjuntos de dados em clusters usando um modelo de programação simples denominado MapReduce (DEAN; GHEMAWAT, 2008).
MapReduce é um modelo de programação idealizado pelo Google que foi projetado para processar paralelamente, com alta escalabilidade e tolerância a falhas, grandes quan-tidades de dados em clusters de computadores comuns (DEAN; GHEMAWAT, 2008). Esse
modelo é baseado na aplicação de duas funções: map e reduce. A função map transforma os dados de entrada para gerar um conjunto intermediário de dados em formato específico e a função reduce combina esses resultados intermediários para obter valores agregados. Um programa MapReduce executa essas funções em sequência, sendo bastante útil para o processamento de dados em lote, onde os dados são manipulados de forma sequencial. A ideia geral não é nova, ela é desde muito tempo utilizada em linguagens de programação funcional como LISP. A novidade do MapReduce é a abordagem da implementação da infraestrutura que abstrai grande parte da complexidade da paralelização e da distribui-ção da computadistribui-ção, permitindo que o usuário programador se concentre na construdistribui-ção das funcionalidades de alto nível do programa.
Embora o modelo MapReduce tenha se provado bastante útil e popular, ele não é adequado para certos casos de uso, havendo críticas ao modelo na literatura. De acordo com Bonner et al. (2017), os críticos ao MapReduce argumentam que o modelo possui funcionalidade limitada, que sua API ainda é de baixo nível e que ele necessita de clusters dedicados. Segundo Zaharia et al. (2012), o MapReduce não é eficiente para casos de uso onde haja a necessidade de realizar trabalhos não sequenciais em que sejam realizadas várias passagens sobre os mesmos dados, como é comum em algoritmos de aprendizagem
de máquina, por exemplo. Quando comparado com outras abordagens, tais como o uso de RDBMS e da linguagem SQL, MapReduce oferece funcionalidades restritas e usabi-lidade bastante dificultada. Operações comuns e simples na abordagem relacional como, por exemplo, joins são complicadas de se expressar em programas MapReduce, sendo geralmente necessário o uso de soluções mais sofisticadas e complexas. Para Chambers e Zaharia (2018), construir grandes aplicações com MapReduce é desafiador e ineficiente.
Um grupo de pesquisadores da Universidade de Berkeley2idealizou o framework Spark
com o objetivo de ser um modelo de computação para Big Data, com grande desempenho, alta escalabilidade, tolerância a falhas e alternativo ao MapReduce, não apresentando as desvantagens relativas ao processamento paralelo de múltiplas operações sobre um mesmo conjunto de dados. Spark foi projetado para fornecer um modelo de computação de propósito mais geral que o MapReduce e que pudesse ser executado de forma muito eficiente em clusters. De acordo com Zaharia et al. (2010), em comparação com o Hadoop, Spark pode melhorar em dez vezes o desempenho de aplicações iterativas.
2.2
Apache Spark
Spark é um framework que fornece um motor de computação e um conjunto de bibli-otecas para o processamento paralelo de dados em clusters de computadores (CHAMBERS; ZAHARIA, 2018). Spark foi lançado em 2010 como um software de código aberto3 e se
tornou o projeto para Big Data mais ativo da atualidade, com mais de 1300 contribui-dores ao seu repositório de código-fonte4. De acordo com dados do Google (Figura 1), o
interesse por Spark tem crescido de forma considerável nos últimos anos.
Figura 1: Interesse pelos frameworks Spark e Hadoop de acordo com Google Trends5.
Empregando um modelo de computação com menos restrições que o MapReduce,
2 https://amplab.cs.berkeley.edu 3 https://github.com/apache/spark 4 https://github.com/apache/spark/graphs/contributors 5 https://trends.google.com.br
Segundo Zaharia et al. (2010), Spark foi inicialmente criado para tratar a ineficiência do modelo MapReduce em dois tipos de aplicações:
• Trabalhos iterativos: muitos algoritmos de aprendizagem de máquina aplicam fun-ções repetidamente sobre um mesmo conjunto de dados. Apesar de ser possível expressar essa computação como um trabalho MapReduce, cada trabalho neces-sita carregar os dados do disco rígido, resultando em uma perda de desempenho significante.
• Análise exploratória de dados: consultas em grandes conjuntos de dados em ambien-tes Hadoop são frequentemente realizadas por meio de interfaces SQL tais como Pig6
e Hive7. Essas queries em Hadoop resultam em latências significantes porque são
executadas como trabalhos MapReduce separados, necessitando de muitas leituras no disco rígido.
As funcionalidade de Spark são utilizadas por meio de APIs disponíveis para as lin-guagens de programação Java, Scala, Python e R. Em constante evolução, Spark permite a integração com diversas soluções de armazenamento distribuído de dados (Hadoop Dis-tributed File System – HDFS, Cassandra8, HBASE9, Amazon S310, etc) e gerenciadores de
clusters(Hadoop YARN, Apache MESOS11, Spark Standalone). Usuários também podem utilizar e combinar diversas bibliotecas que proveem um amplo conjunto de funcionalida-des, incluindo as bibliotecas Spark SQL para o processamento de dados relacionais, MLlib para algoritmos de aprendizagem de máquina, GraphX para o processamento de grafos, Spark Streaming para o processamento de fluxos de dados contínuos, além de centenas
6https://pig.apache.org 7 https://hive.apache.org 8 https://cassandra.apache.org 9 https://hbase.apache.org 10 https://aws.amazon.com/pt/s3 11 https://mesos.apache.org
de outras bibliotecas desenvolvidas por sua comunidade de usuários12. A Figura 2 ilustra,
em camadas, as tecnologias citadas que podem compor uma aplicação Spark.
Figura 2: Pilha de tecnologias envolvidas em uma aplicação Spark.
O modelo de computação de Spark se baseia no processamento de dados em memó-ria principal que é realizado mediante funcionalidades expostas pela API da abstração denominada RDD (Conjunto de Dados Distribuídos e Resilientes, do inglês Resilient Dis-tributed Dataset). RDD é uma representação dos dados carregados pela aplicação Spark na memória principal da máquina. Ele forma uma coleção de objetos Java que podem ser distribuídos e manipulados em paralelo. Uma grande parte de Spark é construído sobre a abstração de RDDs e mais detalhes sobre eles são apresentados na Seção 2.2.1.
Uma típica aplicação Spark é formada pelo programa do usuário (Driver), um geren-ciador de recursos do cluster e nós trabalhadores (Workers). A Figura 3 ilustra esses com-ponentes. A aplicação Spark executa um conjunto independente de processos coordenados por um objeto (SparkContext) contido no Driver. Mais especificamente, o SparkContext se comunica com o gerenciador do cluster de forma a obter os recursos computacionais necessários para a execução das aplicações. O Driver é o ponto de entrada da aplicação. Ele é responsável por mapear todas as operações sobre RDDs em um conjunto de tarefas (Tasks) que formam um DAG (Grafo Acíclico Dirigido, do inglês Directed Acyclic Graph) de dependências entre as operações. Essas tarefas são executadas por processos denomi-nados executores (Executors) que rodam em nós trabalhadores (Workers) do cluster.
Executores recebem as tarefas do Driver, executam as operações requeridas sobre os
12
https://spark-packages.org
13Adaptado da documentação de Spark em
https://spark.apache.org/docs/latest/ cluster-overview.html
Figura 3: Componentes de uma aplicação Spark13.
dados e eventualmente retornam o resultado da computação para o Driver. Os processos executores são JVMs (Máquina Virtual Java, do inglês Java Virtual Machine) que perma-necem ativas durante todo o tempo de vida da aplicação e executam as tarefas por meio de diferentes threads.
O Driver e os Executores se comunicam regularmente durante a execução da aplicação para a execução das operações definidas no DAG, bem como para o reagendamento de tarefas para outros nós do cluster em caso de falhas. Segundo estudo realizado por Shi et al. (2015), com essa arquitetura e abstrações, Spark alcançou vantagens consideráveis, especialmente em tarefas iterativas, em comparação com o projeto original do Hadoop MapReduce.
2.2.1
Resilient Distributed Dataset (RDD)
RDD é uma abstração para uma memória distribuída que permite aos usuários a sua manipulação de forma paralela por meio de um rico conjunto de operadores (ZAHARIA et al., 2012). Essa abstração torna o particionamento das estruturas de dados, seu
armaze-namento e a sua manipulação paralela transparentes ao usuário Spark, permitindo que a programação da aplicação seja tratada em mais alto nível. O nome RDD advém de três características:
1. Resiliente (Resilient): RDDs são tolerantes a falhas, eles podem ser recriados em caso de problemas nos nós do cluster;
2. Distribuído (Distributed): os RDDs são particionados e distribuídos, podendo residir em diferentes nós do cluster;
3. Conjunto de dados (Dataset): RDDs armazenam uma coleção de dados que podem ser representados em memória por tipos primitivos ou quaisquer outros objetos Java. RDDs são implementados como uma coleção de objetos imutáveis que podem ser recriados em caso de problemas, tornando a aplicação Spark tolerante a falhas. As opera-ções disponíveis na API dos RDDs podem ser classificadas em duas categorias distintas: transformações e ações.
As transformações são operações voltadas para a manipulação dos dados. Como os RDDs são imutáveis, as transformações, ao invés de modificarem o RDD, criam novos RDDs transformados. As operações rdd.map(function) e rdd.reduceByKey(function) são exemplos de transformações para, respectivamente, aplicar uma função em todos os elementos de um RDD e agregar elementos usando uma função de redução de elementos no formato de pares (chave, valor). Essas transformações são preguiçosas (lazy), no sentido de que o resultado da operação será computado sob demanda. Na verdade, o programa Driver armazena a linhagem da sequência de transformações (um plano de execução em forma de um DAG) que serão aplicadas sobre o conjunto de dados. Dessa forma, a aplicação mantém o controle sobre todas as dependências entre os RDDs e esse plano de transformações é executado apenas quando uma operação do tipo ação é chamada. Além disso, é o histórico de transformações desses planos que será utilizado para reconstruir RDDs em casos de falhas.
As ações são operações executadas sobre RDDs com objetivo de computar valores e retorná-los para o Driver. Elas são gatilhos para iniciar a execução do plano das transfor-mações que irão processar os dados. Adotando a estratégia de adiar as transfortransfor-mações para somente quando seu resultado for necessário – para somente quando uma ação for cha-mada – Spark pode realizar otimizações no plano de transformações, como, por exemplo, combinar operações para evitar a necessidade de materialização de resultados intermediá-rios e, dessa forma, executar o programa mais eficientemente. As operações rdd.count() e rdd.collect() são exemplos de ações para, respectivamente, a contagem da quanti-dade de elementos de um RDD e o retorno ao Driver de um array que contém todos os elementos do RDD.
A Figura 4 ilustra um programa Spark simples que, por meio de transformações e ações, realiza a contagem de cada uma das palavras de um texto. O programa realiza:
Figura 4: Transformações e ações para contagem das palavras de um arquivo texto. As transformações e ações disponíveis para os RDDs constituem a chamada Spark Core API. De forma a possibilitar maior usabilidade e expressividade em vários contextos, Spark provê adicionalmente outra API de mais alto nível que foi construída com base na API Core. De fato, a partir de sua versão 2.0, lançada em 26 de julho de 2016, o projeto Spark passou a encorajar que seus usuários não mais adotassem primariamente a API RDD na programação de suas aplicações. A recomendação atual é que os usuários utilizem principalmente a API conhecida como Dataframe.
2.2.2
Dataframes
Grande parte dos Sistemas de Informações desenvolvidos para manipulação de bases de dados utiliza a linguagem SQL. SQL é uma linguagem declarativa – declara o que deve ser feito, não como fazê-lo – originalmente desenvolvida pela IBM em 1970 para servir
de interface para bancos de dados relacionais. Atualmente, a linguagem é empregada em muitos outros casos de uso, sendo também muito utilizada por cientistas de dados e usuários de sistemas de Business Intelligence para examinar dados interativamente.
Em razão da popularidade de SQL, existe uma forte demanda pela incorporação de interfaces relacionais em frameworks para processamento de Big Data. Nesse sentido, novas tecnologias como Hive, Pig, Drill14, Impala15e outras foram criadas como forma de
fornecer uma experiência de uso mais amigável e produtiva na medida em que possibilita a execução de consultas relacionais. No que diz respeito a Spark, aplicações podem fazer uso de SQL por meio de funcionalidades da biblioteca Spark SQL, um componente de Spark que teve origem no projeto Shark16 (XIN et al., 2013). De acordo com Xin (2018),
Spark SQL foi projetado para atender os seguintes requisitos:
1. API amigável para o programador com suporte ao processamento relacional; 2. Alto desempenho utilizando técnicas já empregadas e bem estabelecidas em sistemas
gerenciadores de bancos de dados relacionais;
3. Suporte fácil a novas fontes de dados, incluindo dados semi-estruturados e bancos de dados externos;
4. Extensão com algoritmos analíticos avançados tais como processamento de grafos e aprendizagem de máquina.
Spark SQL é executado como uma camada sobre a API (RDDs) do Spark Core, provendo aos seus usuários uma interface (Dataframe) para operação relacional de dados estruturados, conforme ilustrado de forma simplificada na Figura 5, cujos elementos serão explicados nesta Seção.
Spark SQL introduziu a nova abstração chamada Dataframe que permite a seus usuá-rios utilizarem tanto consultas relacionais declarativas quanto algoritmos procedimentais em uma mesma aplicação. De acordo com Armbrust et al. (2015b), a utilização apenas da abordagem relacional é insuficiente para várias das aplicações de Big Data, como, por exemplo, as aplicações que envolvem processamento de grafos e aprendizagem de má-quina. Xin (2018) afirma que as duas classes de sistemas – relacionais e procedurais – permaneciam até então bastante disjuntas, forçando o usuário a escolher um paradigma
14https://drill.apache.org 15https://impala.apache.org 16https://shark.cs.berkeley.edu
Figura 5: APIs de Spark e Spark SQL. Adaptado de (ARMBRUST et al., 2015b).
em detrimento do outro. A API DataFrame foi então projetada para permitir a fácil in-tegração relacional/procedimental em programas Spark. Além disso, o módulo Catalyst foi concebido para otimização de consultas e geração de código, realizando otimizações baseadas em regras e em custos, semelhantemente as otimizações realizadas por RDBMS. Dataframes são conjuntos distribuídos de dados organizados estruturalmente em co-lunas. Eles são conceitualmente semelhantes à tabelas em bancos de dados relacionais, onde cada objeto do Dataframe representa uma linha da tabela. Além de facilitar o de-senvolvimento de aplicações, o uso da API Dataframe resulta em melhor desempenho em razão das possibilidades de otimizações automáticas (ARMBRUST et al., 2015b).
Ao contrário dos RDDs, Dataframes mantêm o registro do esquema dos dados, per-mitindo que Spark realize otimizações automáticas ao explorar essa estrutura. Segundo Armbrust et al. (2015a), ainda que as otimizações aplicadas em nível de RDDs sejam extremamente úteis, elas são limitadas porque as estruturas de dados contidos nos RDDs e as funções dos usuários são opacas, ou seja, o otimizador não possui as informações semânticas necessárias para otimizações mais avançadas. Segundo Xin (2018), Datafra-mes são mais convenientes e eficientes que RDDs em situações como, por exemplo, a computação de múltiplos valores agregados utilizando declarações SQL, algo que é difícil de se expressar com a API dos RDDs. Além disso, Dataframes armazenam os dados na memória em um formato colunar que é significativamente mais compacto que na forma de atributos de objetos Java. Xin et al. (2013) declaram que Spark SQL é até 100 vezes
mais rápido que Hive para consultas SQL e até 100 vezes mais rápido que Hadoop para algoritmos de Machine Learning.
Importante observar que o ganho de desempenho utilizando a API Dataframe é obtido independentemente da linguagem de programação empregada na construção da aplicação Spark SQL. Armbrust et al. (2015b) afirmam que isto é especialmente importante para aplicações escritas em Python, considerando que Python é tipicamente mais lento que Java. O otimizador de Spark SQL transforma o plano lógico construído em Python em um plano físico compilado para código nativo Spark na forma de bytecode JVM, resultando em uma execução mais eficiente.
Para além do ganho em desempenho, a API dos Dataframes apresenta funcionalidades não oferecidas pela API RDD, incluindo o suporte a vários operadores relacionais como junções (joins) e agregações que são familiares para muitos desenvolvedores e cientistas de dados. Além disso, o usuário pode definir suas próprias funções (user defined functions) para manipulações avançadas dos dados contidos nos Dataframes. Armbrust et al. (2015b) declaram que dessa forma é possível combinar SQL com outras linguagens para fins de realizar análises de dados complexas.
A Figura 6 ilustra um exemplo simples de transformação de dataframes. Nesse exem-plo, supondo a existência do dataframe ViagensDF com informações sobre a quantidade de voos entre países, buscamos relacionar os países de origem e destino cuja frequên-cia de voos é menor que 20. A transformação (1) pode ser obtida utilizando a API Dataframe de várias formas, como, por exemplo, val NovoDF = ViagensDF.select( "Origem","Destino").where(col("Qtd_Voos").lt(20)). É possível também realizar a mesma transformação utilizando diretamente um comando SQL, por exemplo val NovoDF = sql("select Origem, Destino from Viagens where Qtd_Voos < 20") desde que o dataframe tenha sido previamente registrado como uma tabela no catálogo do Spark SQL.
Spark SQL executa consultas SQL sobre Dataframes utilizando um processo seme-lhante ao empregado pelos RDBMS tradicionais: (i) parsing da consulta; (ii) geração do plano lógico da consulta; (iii) transformação do plano lógico em um plano de execução físico, realizando automaticamente as possíveis otimizações; (iv) execução do plano físico no cluster na forma de operações sobre RDDs.
Além da API Dataframe, outro importante marco na evolução de Spark foi a introdu-ção da API denominada Dataset. Trata-se de uma extensão para a API Dataframe com objetivo de prover segurança de tipos (type-safe), conforme abordaremos na Seção 2.2.3.
Figura 6: Transformação de um Dataframe utilizando Spark SQL
2.2.3
Datasets
Assim como Dataframes, Datasets são coleções distribuídas de objetos que represen-tam tabelas relacionais, com linhas e colunas bem definidas. A diferença é que a API Dataset permite que usuários associem classes Java (no padrão JavaBean) ou Scala (case classes) com Dataframes, de forma a permitir a escrita de código estaticamente tipado.
Dessa forma, Dataset busca ser uma API type-safe, mais atrativa para codificação de grandes aplicações. A verificação de conformidade entre os tipos do Dataset e a especifi-cação da classe é realizada em tempo de compilação, enquanto que para Dataframes essa verificação só é realizada em tempo de execução. Assim, Datasets permitem que alguns erros de codificação das aplicações sejam detectados antes que a aplicação seja executada. O compilador e a IDE (Ambiente Integral de Desenvolvimento, do inglês Integrated De-velopment Environment) entendem os tipos usados e podem, portanto, fornecer ajuda e mensagens de erros enquanto se constrói a aplicação.
O uso de Datasets só está disponível para as linguagens Scala e Java. É preciso utilizar codificadores (encoders) para converter os objetos Java em sua representação tabular e vice-versa. Spark SQL provê suporte para automaticamente gerar codificadores para uma grande quantidade de tipos, incluindo os tipos primitivos (String, Integer, Long, etc), as case classesde Scala e as classes Java Beans. Entretanto, essa conversão implica em perda de desempenho da aplicação. De acordo com Chambers e Zaharia (2018), o mais comum é utilizar Datasets e Dataframes em conjunto, avaliando caso-a-caso o equilíbrio entre desempenho, flexibilidade e type safety.
A partir da versão 2.017, lançada em julho de 2016, Spark unificou as APIs Dataframe
e Dataset de forma que Dataframe passou a ser simplesmente um Dataset do tipo Row (type DataFrame = Dataset[Row]), onde objetos da classe Row representam linhas de uma tabela relacional.
De maneira geral, Spark SQL e suas APIs Dataframe e Dataset representaram im-portantes evoluções para Spark. A API RDD é bastante geral, mas oferece oportunidades limitadas para otimizações automáticas. Além disso, o uso dos Dataframes/Datasets faci-lita consideravelmente a construção de aplicações Spark. Em razão disso, o projeto Spark tem buscado incorporar essas novas APIs como a base para as demais bibliotecas do fra-mework. Dataframes estão se tornando a representação de dados padrão para os algoritmos das bibliotecas de grafos, de streaming e de aprendizagem de máquina.
No que diz respeito a algoritmos de aprendizagem de máquina, Spark fornece a bi-blioteca MLlib com diversas funções que podem ser utilizadas com relativa facilidade. A partir da versão 2.0 do framework, os algoritmos de aprendizagem de máquina passaram a ser implementados exclusivamente com base na API Dataframes, enquanto que os algo-ritmos previamente existentes – baseados na API RDD – estão sendo reimplementados. As funções implementadas anteriormente sobre a API RDD foram mantidas na biblioteca MLlib, mas não serão mais evoluídas e serão removidas na futura versão Spark 3.0. A biblioteca fornece, por exemplo, funcionalidades para agrupamentos de elementos com base em alguma noção de similaridade (Clustering). Neste trabalho, utilizamos algumas dessas funções para realizar a técnica de modelagem de tópicos.
2.3
Modelagem de Tópicos
A obtenção de informação útil a partir de grandes quantidades de dados é um desafio que requer bastante esforço, pois pode demandar perícia tanto para a escolha das técnicas e métodos utilizados quanto para o domínio estudado. Segundo Proto (2018) a análise sintática ou semântica de documentos textuais é complexa e envolve o uso de técnicas específicas para o processamento de linguagem natural em razão da riqueza da linguagem humana e da diversidade encontrada nos textos produzidos. Técnicas de mineração de dados (Data Mining) auxiliam na extração de conhecimento implícito contido em um conjunto de dados a partir da identificação de padrões e correlações (PROTO, 2018). De
acordo com Proto (2018), a mineração de textos – ramo da mineração de dados que busca extrair informações anteriormente desconhecidas a partir da análise de dados textuais – é uma área de grande interesse e pesquisa com diversas aplicações no cotidiano, tais como:
palavras ou frases; vetores ou matrizes; ou probabilidades de ocorrência das palavras. Algoritmos para modelagem probabilística de tópicos empregam métodos estatísticos pelos quais busca-se inferir os assuntos (tópicos) abordados em um conjunto de documen-tos a partir das palavras o compõem. São algoritmos não-determinísticos, uma vez que seu resultado depende de um processo de amostragens estocásticas (AGRAWAL; FU; MENZIES,
2018). De acordo com (CHEN; THOMAS; HASSAN, 2016), os trabalhos científicos acerca da
modelagem de tópicos probabilística compartilham uma terminologia comum. Definimos abaixo alguns dos termos utilizados:
• Termo (palavra ou token) w: uma string de um ou mais caracteres alfanuméricos; • Documento d: um conjunto ordenado de n termos, w1, ..., wn;
• Corpus D: um conjunto não-ordenado de n documentos, d1, ..., dn;
• Vocabulário V : o conjunto não-ordenado dos m termos de um corpus;
• Tópico k: um conjunto de termos que frequentemente coocorrem em documentos de um corpus.
Considerando a grande quantidade de dados textuais disponíveis nos dias atuais e a sua natureza muitas vezes não-estruturada, busca-se ao máximo tornar o processo de mi-neração de textos uma atividade automática, pois a necessidade de constante supervisão humana resulta em um processo ineficiente. De acordo com Blei (2012a), os algoritmos para modelagem de tópicos nos permite organizar e sumarizar documentos em uma escala impossível de ser tratada por humanos. Algoritmos como, por exemplo, o LDA (Latent Dirichlet Allocation) procuram descrever o corpus ainda que não se tenha conhecimento acerca dos documentos nele contidos (aprendizagem não-supervisionada), ou seja, não requerem anotações ou marcações prévias de documentos como é comum em outros algo-ritmos de aprendizagem de máquina.
2.3.1
Latent Dirichlet Allocation
O algoritmo LDA foi apresentado em 2003 no trabalho de Blei, Ng e Jordan (2003) e, desde então, deu origem a diversos estudos e aplicações em vários domínios, incluindo Engenharia de Software, Geografia, Ciência Política, Ciências Médicas, etc (BLEI, 2012b).
Na Engenharia de Software, conforme levantamento realizado por Jelodar et al. (2018), o LDA tem sido utilizado para análises de código-fonte, detecção de eventos, classificação de imagens, sistemas de recomendação, classificação de emoções, categorização automática de software, mineração de logs e muitas outras aplicações.
Segundo Treude e Wagner (2018), o LDA é a técnica mais frequentemente utilizada para modelagem de tópicos. O termo Latent (latente), parte do nome LDA, foi utilizado porque na Estatística uma variável que é inferida ao invés de ser diretamente observada recebe este nome. No LDA, as variáveis observadas são os termos dos documentos, en-quanto que os tópicos, a distribuição de termos por tópico e a distribuição de tópicos por documento são variáveis escondidas (não-observadas, latentes). Já o termo “Dirich-let” refere-se ao nome – atribuído em homenagem ao matemático Johann Peter Gustav Lejeune Dirichlet – da distribuição de probabilidades utilizada no algoritmo para obter aleatoriamente a distribuição de tópicos por documento. E o termo Allocation (aloca-ção) significa que o algoritmo irá atribuir tópicos para os documentos e palavras para os tópicos.
A intuição por trás do LDA é que os documentos são uma mistura de múltiplos tópicos e os tópicos são grupos de palavras associadas a um assunto. Segundo Blei, Ng e Jordan (2003) os termos que constituem um tópico são frequentemente relacionados semantica-mente em razão da natureza da linguagem humana. No LDA, um documento é modelado como uma distribuição de probabilidades sobre um conjunto de diferentes tópicos, ou seja, documentos discutem múltiplos tópicos em diferentes proporções, enquanto que um tópico é uma distribuição de probabilidades sobre um vocabulário fixo.
De acordo com Blei (2012a), LDA pode ser formalmente descrito com a seguinte notação:
• Os tópicos são β1:K, onde βk é a distribuição de probabilidades para os termos do
vocabulário do corpus para o tópico k, com 1 6 k 6 K;
• As proporções de tópicos para os documentos são θ1:D, onde θd,k é a proporção do
onal das variáveis escondidas dadas as variáveis observadas. Dessa forma, de acordo com Blei (2012a), o problema computacional de inferência da estrutura de tópicos latente é o problema de computar:
p(β1:K, θ1:D, Z1:D | W1:D) =
p(β1:K, θ1:D, Z1:D, W1:D)
p(W1:D)
Contudo, segundo Blei, Ng e Jordan (2003), esse problema é intratável computacional-mente, pois seria necessário computar as distribuições conjuntas para todas as possíveis instanciações da estrutura de tópicos. Portanto, na modelagem probabilística de tópi-cos utilizam-se métodos para obtenção de resultados aproximados. De acordo com Blei (2012a), o desenvolvimento de métodos eficientes para aproximação do resultado dessas distribuições é um importante objetivo de pesquisa na modelagem probabilística moderna. Jelodar et al. (2018) discutem vários desses métodos, dentre os quais destacamos o Collapsed Gibbs Sampling (PORTEOUS et al., 2008) – por ser o método empregado pela
ferramenta MALLET18, muito utilizada em diversos trabalhos científicos, conforme
ve-remos no Capítulo 3 – além do Expectation Maximization (DEMPSTER; LAIRD; RUBIN,
1977) e do Online Variational Bayes (HOFFMAN; BACH; BLEI, 2010) – que são os métodos
implementados nas bibliotecas de aprendizagem de máquina do Spark19. Para os
propó-sitos deste trabalho, omitimos os detalhes dos métodos de computação das distribuições probabilísticas de modelos como o LDA. Um rica literatura existe sobre o assunto, sendo suficiente saber que tais métodos existem e o tema continua sendo ativamente pesquisado. No que diz respeito a Spark, algoritmos para LDA estão disponíveis tanto para a API RDD (org.apache.spark.mllib.clustering.LDA) quanto para a API Dataframe (org.apache.spark.ml.clustering.LDA). Em ambos os casos, a versão atual de Spark implementa tanto o Expectation Maximization quanto o Online Variational Bayes. Outras
18
https://mallet.cs.umass.edu
19
ferramentas populares que implementam o LDA e que foram utilizadas em trabalhos relacionados a este, conforme veremos no Capítulo 3, são: Gensim20, SciKit Learn21 e
LDA R package22.
A escolha do algoritmo de computação das distribuições do LDA depende do caso de uso: o Online Variational Bayes é um algoritmo que processa os dados em lotes pe-quenos de maneira a otimizar o uso da memória na medida em que descarta os dados já processados. Dessa forma, o modelo resultante contém apenas o conjunto de tópicos inferidos, sendo bastante escalável para conjuntos de dados muito grandes; o Expectation Maximization obtém resultados mais completos na medida em que armazena não somente o conjunto de tópicos inferidos, mas também todo o conjunto de dados usado no treina-mento do modelo e a distribuição de tópicos por docutreina-mento. Neste trabalho, utilizamos o Expectation Maximization, pois as informações adicionalmente guardadas são úteis para análises que desejamos realizar sobre o corpus.
Em geral, LDA tem sido bastante utilizado e produzido bons resultados para diferentes domínios de aplicações. Entretanto, a parametrização do modelo para obtenção de bons resultados não é uma tarefa trivial. De acordo com Martinez (2018), um dos desafios do uso do LDA é a escolha de uma configuração – os valores dos parâmetros de entrada – que produza tópicos significantes. De maneira geral, os algoritmos para LDA trabalham com três parâmetros:
1. K: a quantidade de tópicos a serem inferidos.
2. α: hiperparâmetro da distribuição Dirichlet para a proporção de tópicos do docu-mento. O parâmetro α representa a densidade documento-tópico (TREUDE; WAG-NER, 2018). Valores altos para α indicam que cada documento contém uma mistura
da maior parte dos tópicos, enquanto que valores baixos indicam que cada docu-mento tende a tratar de poucos tópicos de forma mais específica.
3. β : hiperparâmetro da distribuição Dirichlet para a proporção de palavras por tópico. O parâmetro β representa a densidade tópico-palavra (TREUDE; WAGNER, 2018).
Valores altos para β indicam que cada tópico contém uma mistura da maior parte das palavras do vocabulário, ou seja, compartilham muitas palavras, enquanto que valores baixos indicam que os tópicos possuem palavras mais específicas.
20
https://radimrehurek.com/gensim
21
https://scikit-learn.org
Figura 7: Parametrização do Algoritmo LDA.
O usuário deve conhecer de alguma forma a quantidade adequada de tópicos K para a análise do corpus. A modelagem probabilística de tópicos será útil na medida em que essa estrutura latente inferida se assemelhe a estrutura temática da coleção de documentos. O número de tópicos possui grande influência sobre os resultados do LDA, mas geralmente a avaliação do resultado é subjetiva, de difícil interpretação e consome bastante tempo (PROTO, 2018). Encontrar o valor ótimo para o número de tópicos a serem descobertos
pelo LDA não é uma tarefa trivial. Este parâmetro deve ser pensado com cuidado, dado que ele define o número de agrupamentos e, portanto, o resultado final poderá mudar con-sideravelmente. Um valor baixo poderá conduzir a um resultado de granularidade grossa que dificulte a identificação dos agrupamentos, enquanto um valor alto pode levar a mode-los muitos complexos, de difícil interpretação e validação (WALLACH; MIMNO; MCCALLUM,
2009).
É importante observar que para cada um dos tópicos podemos escolher rótulos que representem o assunto abordado. Essa escolha é manual – não identificamos nenhum trabalho que tenha conseguido automatizar satisfatoriamente esse processo – com base na semântica dos termos associados a cada tópico. Em geral, a escolha dos rótulos se dá pela análise das palavras do vocabulário mais frequentemente atribuídas ao tópico pelo algoritmo. Esse não é necessariamente o objetivo do LDA, mas diversos trabalhos publicados utilizaram especificamente essa técnica para classificar grandes conjuntos de documentos. Para Zou et al. (2017) é necessário conceber rótulos apropriados aos tópicos para facilitar a análise e a discussão, uma vez que os tópicos extraídos são abstratos e de difícil entendimento.
Conforme evidenciamos no Capítulo 3, diversas pesquisas já foram desenvolvidas na área da Engenharia de Software aplicando LDA, dentre as quais destacamos as que uti-lizaram o conjunto de dados disponível na plataforma Stack Overflow como fonte de conhecimento para obtenção de compreensão das técnicas e problemas relacionados ao desenvolvimento de software. Portanto, apresentamos a seguir mais informações sobre a plataforma Stack Overflow.
2.4
Stack Overflow
Stack Overflow23 é provavelmente o mais popular website de perguntas e respostas
técnicas sobre Computação. Ele conta com uma comunidade rica de participantes especi-alistas em vários domínios. Desenvolvedores do mundo todo costumam recorrer ao Stack Overflow para fazer perguntas, responder a questões existentes ou encontrar respostas à perguntas já respondidas anteriormente. Grande parte dos participantes da comunidade do Stack Overflow são especialistas em áreas da Computação. Nesse sentido, o website é hoje um enorme repositório de conhecimento sobre as várias necessidades dos desenvol-vedores de software. Analisar e entender esse repositório pode nos ajudar a obter uma melhor compreensão dos tópicos de interesse desses profissionais e das mais variadas ques-tões relacionadas aos desenvolvimento de software. O conjunto de dados do Stack Overflow compreende mais de 17 milhões de perguntas e mais de 26 milhões de respostas atual-mente24.
A plataforma Stack Overflow conta com um sistema de avaliação no qual os usuários votam para classificar as perguntas e respostas mais relevantes. De acordo com a quali-dade de suas contribuições, os usuários recebem pontos de reputação que lhe dão acessos privilegiados e servem como prêmio de reconhecimento, objetivando incentivar a partici-pação dos usuários da comunidade. O participante que realizou a pergunta pode também identificar a resposta que lhe foi mais útil, de forma que a resposta ficará em destaque na página referente a questão. Os usuários também podem associar rótulos (tags) para suas questões. As tags são escolhidas de listas predefinidas ou criadas quando não houve-rem tags relevantes para classificação. Essa classificação por tags é subjetiva e pode não contextualizar as questões corretamente.
A Figura 8 apresenta um exemplo de página do Stack Overflow destacando: o título da pergunta (A); o corpo da pergunta (B); as tags associadas a pergunta (C); a classificação
23
https://stackoverflow.com
Figura 8: Exemplo de página do Stack Overflow com pergunta e uma resposta aceita25.
O Stack Overflow é a plataforma recomendada26 pelo projeto Apache Spark para
que os utilizadores do framework busquem por ajuda. Recomenda-se que seja utilizada a tag apache-spark ao postar uma pergunta sobre Spark na plataforma. Atualmente essa tag está associada a mais de 45 mil perguntas. Além dessa, existem diversas outras tags que podem ajudar a filtrar perguntas sobre temas específicos, tais como pyspark, spark-dataframe, spark-streaming, spark-r, spark-mllib, spark-ml,
spark-graphx, spark-graphframes, etc. Portanto, a análise dos dados do Stack Overflow pode nos ajudar ricamente na compreensão de questões relacionadas ao processamento de Big Data com Apache Spark.
25https://stackoverflow.com/questions/31508083 26https://spark.apache.org/community.html
O conjunto de dados do Stack Overflow está publicamente disponível27 no formato
XML sob uma licença Creative Commons28 que permite seu livre uso para qualquer
pro-pósito. Os dados estão organizados em 8 arquivos XML, cada um representando uma entidade: Posts, Users, Comments, Tags, Votes, PostLinks, PostHistory e Badges. Para as análises propostas neste estudo, trabalharemos os dados contidos no arquivo posts.xml. No Capítulo 4 apresentamos como selecionamos do posts.xml apenas as questões rela-cionadas ao Apache Spark, bem como quais atributos foram utilizados para obtermos as informações para análise. Nesse arquivo, cada linha representa uma postagem (post), que pode ser uma pergunta ou uma resposta e poder conter diversos atributos, dentre os quais relacionamos:
• Id: número de identificação única do post;
• PostTypeId: número que indica se o post é uma pergunta (1), ou uma resposta (2); • AcceptedAnswerId: número do identificador da resposta marcada como aceita pelo
questionador. Atributo presente apenas em posts do tipo pergunta;
• ParentId: número identificador da pergunta a qual uma resposta se refere. Atributo presente apenas em posts do tipo resposta;
• CreationDate: data de criação do post;
• Score: número que representa a reputação de um post com base nas interações positivas (upvote) e negativas (downvote) dos usuários da plataforma.
• ViewCount: número de visualizações do post;
• Body: texto do corpo da pergunta ou da resposta em formato HTML.
• Title: texto do título da pergunta. Atributo presente apenas em posts do tipo pergunta;
• Tags: rótulos para classificação das perguntas na plataforma. Atributo presente apenas em posts do tipo pergunta;
• AnswerCount: quantidade de respostas para uma pergunta. Atributo presente ape-nas em posts do tipo pergunta;
• CommentCount: quantidade de comentários feitos sobre um post;
27
https://archive.org/details/stackexchange
28
3
Trabalhos Relacionados
Neste Capítulo apresentaremos o estudo detalhado das publicações científicas rela-cionadas ao nosso trabalho. Estudamos esses trabalhos no sentido de entender como – mediante aplicação do LDA – identificar adequadamente as dificuldades e questões de in-teresse relacionadas ao Spark. Nas seções deste Capítulo, apresentamos o resultado desse estudo sob três perspectivas: (i) preparação do corpus – na Seção 3.1 tratamos como os artigos relacionados abordaram a preparação dos documentos para a análise, uma etapa essencial para alcançar bons resultados com o LDA; (ii) parametrização do LDA – na Seção 3.2 discutimos como foi realizada a parametrização do modelo LDA em cada um dos trabalhos que utilizou este método para a modelagem de tópicos; (iii) computação de métricas e análise dos resultados. – na Seção 3.3 apresentamos questões relacionadas às métricas e aos tipos de análise realizadas em cada um dos trabalhos estudados.
Na literatura científica, já foram publicados diversos artigos acerca do uso de técnicas de modelagem de tópicos para suporte às atividades da Engenharia de Software. Segundo (SUN et al., 2016), existe um interesse crescente na exploração da modelagem de tópicos
para várias atividades da Engenharia de Software, como por exemplo: compreensão de códigos-fonte; localização de conceitos ou características; previsibilidade de defeitos; re-cuperação de links de rastreabilidade entre artefatos (rastreabilidade entre código-fonte e documentos de requisitos, por exemplo); compreensão da história e da evolução de softwares; etc.
Diversos trabalhos estudaram repositórios de conhecimento, tais como o Stack Over-flow, para obter entendimento sobre os tópicos de interesse de desenvolvedores de software. Dentre os estudos já realizados, uma relevante quantidade aplicou LDA em conjuntos de dados obtidos do Stack Overflow, demonstrando que a modelagem de tópicos é útil para encontrar padrões nesses dados. A modelagem de tópicos com LDA sobre dados do Stack Overflow permitiu a realização de diversas análises, conforme sumarizado na tabela 1.
relati-na modelagem de tópicos KOCHHAR, 2016; ZOU et al., 2017; JOHRI; BANSAL, 2018;
RODRIGUEZ; WANG; KUANG, 2018) Entendimento sobre as questões que
não foram respondidas
(VÁSQUEZ; DIT; POSHYVANYK, 2013;ZOU et al., 2015;YANG et al., 2016;ROSEN; SHIHAB, 2016;ZOU et al., 2017;AHMED; BAGHERZADEH, 2018)
Identificação das questões mais relevan-tes para os tópicos identificados na mo-delagem
(ROSEN; SHIHAB, 2016;KOCHHAR, 2016;MARTINEZ, 2018)
Entendimento sobre os conceitos discu-tidos e os tipos de perguntas realizadas
(ALLAMANIS; SUTTON, 2013) Identificação de usuários especialistas
na comunidade
(TIAN et al., 2013) Elaboração de hierarquia dos tópicos
identificados
(AHMED; BAGHERZADEH, 2018)
vas ao desenvolvimento de aplicações para dispositivos móveis (WANG; GODFREY, 2013; VÁSQUEZ; DIT; POSHYVANYK, 2013;ROSEN; SHIHAB, 2016;MARTINEZ, 2018), tecnologias
da Web (BAJAJ; PATTABIRAMAN; MESBAH, 2014; VENKATESH et al., 2016), linguagens
de programação (REBOUÇAS et al., 2016; JOHRI; BANSAL, 2018), segurança da
informa-ção (YANG et al., 2016), teste de softwares (KOCHHAR, 2016), análise de requisitos
não-funcionais (ZOU et al., 2015, 2017), programação concorrente (AHMED; BAGHERZADEH,
2018), utilização de logs (GUJRAL et al., 2018), uso de frameworks (RODRIGUEZ; WANG; KUANG, 2018), bem como análises para compreensão abrangente do conjunto de dados do
Stack Overflow como um todo (BARUA; THOMAS; HASSAN, 2012; WANG; LO; JIANG, 2013; ALLAMANIS; SUTTON, 2013).
De forma semelhante, nosso trabalho propõe a modelagem de tópicos– mediante apli-cação do LDA sobre corpus de documentos do Stack Overflow – para identifiapli-cação das dificuldades e questões de interesses de desenvolvedores de aplicações para Big Data com Apache Spark.
3.1
Preparação do Corpus
Os resultados da modelagem probabilística de tópicos é substancialmente afetada pela qualidade dos termos extraídos dos documentos. Diversos trabalhos (BARUA; THOMAS; HASSAN, 2012; CHEN; THOMAS; HASSAN, 2016; YANG et al., 2016; JOHRI; BANSAL, 2018; AHMED; BAGHERZADEH, 2018; PROTO et al., 2018) indicam que, na etapa de preparação
do dataset, é importante remover os ruídos – termos que não são relevantes para identificar os tópicos dos documentos – que afetariam negativamente o resultado do LDA. Em geral, na maior parte dos trabalhos (ver tabela 2 ao fim desta Seção), foi empregado algum tipo de pre-processamento dos documentos, com a realização de tarefas como:
• Remoção de trechos de código-fonte. Segundo Barua, Thomas e Hassan (2012), as palavras reservadas das linguagens de programação e os elementos de sintaxe de códigos introduzem ruídos na fase de análise, atrapalhando a modelagem de tópicos. Para o autor, grande parte do código-fonte presente no Stack Overflow é feito de pequenos fragmentos, não havendo contexto suficiente para permitir a extração de conteúdo significante;
• Remoção de Stop Words. Stop Words são termos comuns em todos os textos, tais como artigos, conjunções, preposições, pronomes, etc. Para Barua, Thomas e Hassan (2012), as Stop Words não ajudam na criação de tópicos significantes;
• Remoção de elementos de formatação. É comum realizar a remoção de tags HTML (<b>, <p> e <a href="..."> por exemplo), uma vez que esse conteúdo adiciona ruído no vocabulário;
• Remoção de caracteres de pontuação, símbolos especiais ou números, uma vez que eles adicionam pouco valor na identificação de tópicos (YANG et al., 2016);
• Remoção de termos muito frequentes ou raros. Termos do vocabulário do corpus muito frequentes (aparecem na maioria dos documentos) ou raros (aparecem em poucos documentos) afetam negativamente o modelo de tópicos. Por exemplo, em nosso trabalho não faz sentido considerarmos o termo “Spark” na modelagem LDA, uma vez que a palavra está presente praticamente em todos os documentos, não servindo para identificar tópicos. Segundo Proto et al. (2018), uma vez que o LDA sorteia palavras do vocabulário considerando as probabilidades dos termos para cada tópico, a exclusão de palavras que aparecem apenas uma vez no corpus reduz o ruído no vocabulário e melhora a modelagem probabilística em geral;
tantes no pré-processamento dos textos que compõem os documentos do corpus.
Ainda quanto à preparação do corpus, não há consenso acerca de quais dados extraídos do Stack Overflow devem compor os documentos a serem processados pelo LDA. Em geral, podemos identificar três estratégias:
1. Gerar documentos a partir do títulos das perguntas e dos corpos das per-guntas e respostas. Essa estratégia foi utilizada em (BARUA; THOMAS; HASSAN,
2012; ALLAMANIS; SUTTON, 2013; VÁSQUEZ; DIT; POSHYVANYK, 2013; WANG; LO; JIANG, 2013; BAJAJ; PATTABIRAMAN; MESBAH, 2014; ZOU et al., 2015, 2017; KO-CHHAR, 2016; VENKATESH et al., 2016; YANG et al., 2016; AHMED; BAGHERZADEH,
2018; JOHRI; BANSAL, 2018);
2. Gerar documentos a partir dos títulos e corpos das perguntas, não utilizando os dados contidos nas resposta. Essa estratégia foi utilizada em (WANG; GOD-FREY, 2013; REBOUÇAS et al., 2016; ZOU et al., 2015, 2017; GUJRAL et al., 2018; RODRIGUEZ; WANG; KUANG, 2018);
3. Utilizar apenas os títulos das perguntas. Essa estratégia foi utilizada em (ROSEN; SHIHAB, 2016) e (MARTINEZ, 2018). Rosen e Shihab (2016) justificam essa escolha
com três motivos: (i) os títulos sumarizam e identificam os principais conceitos tratados na questão; (ii) o corpo das perguntas adiciona informações sem relevância – por exemplo, como o usuário abordou o problema originalmente, o que o usuário já tentou, trechos de código-fonte, etc – para a ideia principal da questão; (iii) considerando que o interesse é nas questões perguntadas pelos desenvolvedores, a adição das respostas não faz sentido. Para Rosen e Shihab (2016), ainda que o corpo do post contenha observações interessantes sobre o que o desenvolvedor já tentou, essa informação adicional se torna um ruído na análise pretendida, pois as questões de pesquisa do trabalho estão interessadas em saber o que o desenvolvedor pergunta.