Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Explorando o Paper "Large-Scale Computerized Text Analysis in Political Science"

+2 votos
14 visitas
perguntada Nov 4 em Ciência da Computação por Matheus Cintrão (26 pontos)  
editado Nov 4 por Matheus Cintrão

Introdução

As palavras são uma parte fundamental da política, pois desde a eleição, passando pelas comunicações e até as leis são expressas em forma de palavra, mas recentemente tivemos uma revolução na área: os governos agora têm a obrigação de publicar na internet os seus registros e até discursos. Além disso, outras empresas tem feito o mesmo como Facebook, Twitter, Amazon. Criando grandes bases de dados em texto. Frente a esta oportunidade os pesquisadores têm se dedicado criação de mecanismos de análise de texto em plataformas abertas como Python e R. Veremos primeiramente uma revisão sobre os métodos de análise de texto.

Os 4 estágios da análise de texto

Obtenção
O primeiro passo é, obviamente, a obtenção destes textos. Mas esta não é uma etapa trivial, pois estes dados raramente estão em um formato que permita uma importação eficiente nos volumes necessários.
A forma mais fácil de obter os dados é no caso da existência de uma API (Application user interface) que permite uma requisição que é facilmente automatizavel, geralmente ocupando 1 uma única linha de código. Mas nem sempre teremos APIs para os dados que queremos.
A segunda forma mais fácil é no caso de os dados estarem em algum formato padronizado nos arquivos de texto como HTML, DPF, .doc, etc. Pois é possível criar um algorítimo automatizado de extração baseado nas linguagens de programação ocultas destes documentos.
Por fim, quando os textos se quer estão em formatação padronizadas, como seria o caso de os dados terem que ser coletados em sites diferentes, nos estaremos lidando algorítimos de "scraping", que são os mais difíceis até aqui pois irão exigir códigos distintos para cada uma destas fontes de dados
Caso não haja necessidade de automação, ou seja, caso os dados possam ser coletados um única vez, ainda existe a possibilidade de "crowdsourcing" onde pessoas se cadastram em sites como "Mechanical Turk"e "Crowdflower" para serem contratadas para trabalhos de "copia e cola" nos sites definidos .

"Converter textos em dados quantitativos"

O objetivo é converter os dados em uma matriz de frequência de termos onde teremos a contagem de vezes que um determinado termo apareceu. Esta matriz pode fazer apenas uma contagem do total dos termos ou pode fazer esta contagem por documento, onde teremos os documentos nas linhas e os termos nas colunas. Esta é a matriz termo-documento. Esta segunda permite análises através de métodos de Machine Learning.

Temos também que tratar os textos de forma a extrair apenas aquilo que é relevante. Para isso temos 4 procedimentos básicos: 1) Padronização: converter para caixa baixa, sem acento e sem pontuação. 2) Stopwords: remover palavras que servem para dar fluidez e coerência ao texto, mas que não tem significado como "a", "o", "em", "sim", "todavia". Note que a palavra "não" pode ser bastante importante para a análise. 3) Stemming ou Lemmatization: aqui as palavras semelhantes serão reduzidas a um termo comum. No primeiro caso elas são reduzidas ao seu radical lingueistico. Na segunda elas são reduzidas a um termo representativo, um "lema". 4) Remoção de termos esparsos. Aqui pode ser utilizada as frequência geral dos termos para remover da matriz termo-documento aqueles que apareceram muito poucas vezes.

Por fim podemos procurar os "n-gramas" (bigramas, trigramas, etc) que são as sequências de palavras. Eles podem ser mais relevantes que as palavras isoladas. Lembrando que a matriz termo-ducumento pode apresentar diversas combinações de n-gramas em suas colunas.

Análise
Em posse dos dados em forma numérica podemos fazer diversas análises.
A mais simples delas é a frequência geral de palavra, como já citado. Aqui serão identificados os termos (palavras e n-gramas) mais utilizados em cada um dos grupos.

Utilizando a matriz de termo-documento podemos correr algorítimos de Machine Learning, tanto supervisionados como não supervisionados. Os métodos supervisionados podem apresentar um trabalho adicional de atribuir "labels" a um conjunto de dados a fim de treinar o algorítimo e estes métodos se destinam à previsões e a rotulação de outros documentos. Os métodos não-supervisionados são utilizados para descobrir novos padrões nos dados ao agrupá-los segundo similaridade.
Temos ainda mais 2 tipos de algorítimos que são o Text Reuse, que leva em consideração a ordem em que as palavras aparecem e o Processamento de Linguagem Natural, que incorpora na sua análise elementos sintáticos e semânticos das palavras.

Validação

Para concluir a análise precisamos criar formas de testar a validade dos resultados encontrados. No caso dos métodos supervisionados podemos simplesmente separar uma parte dos documentos que foram pré classificados para servirem como teste.
Em outros casos a validação é menos objetiva. Podemos utilizar testes de robustes verificando quanto nossos resultados variam com mududanças nos algoritimos utilizados anteriormente, como alterções no número de clusters, nos algorítimos de tratamento ou nos n-gramas escolhidos.

Exercício empírico
No artigo o autor utiliza os "one-minute floor speeches" dos deputados do congresso americano através da API "Sunlight Foundation’s Capitol Words ", aplicando um algorítimo de clustering que agrupou os discursos em temas, para então avaliar quais temas são mais discutidos por cada partido.

Eu não obtive sucesso com esta API pois ela se encontra fora de serviço. Para a realização do exercício empírico eu utilizei os dados que a Amazon disponibiliza em relação às avaliações de produtos.

O meu exercício consistiu nos seguintes procedimentos.
- Baixar os dados da Amazon atravéz de uma base de teste no site https://data.world/datafiniti/consumer-reviews-of-amazon-products
O produto selecionado foi " AmazonBasics AAA Performance Alkaline Batterie"

  • A base foi separada em 2 grupos: Avaliações positivas (5 estrelas), com aproximadamente 6000 avaliações, e avaliações negativas (3 estrelas ou menos) com aproximadamente 1100 avaliações.

-Foi feito um tratamento padronizando em caixa baixa e retirando caracteres que não fossem letras (números e pontuações). Foram então removidas as stopwords e e feita a Stemmatização.

-A forma de análise utilizada foi simplesmente uma contagem de palavras em cada grupo. Este resultado foi apresentado de 2 maneiras: Wordcloud e Gráfico de barras. Um ponto importante é que as palavras baterri e review apareceram com frequência demasiada e como não tem significado para a análise do produto foram retiradas.

-Foi também feita a mesma análise bigramas e trigramas, que apresentarem resultados melhores do que a análise de palavras isoladas.

-Seguem os resultados:
Wordcloud
Avaliações positivas
A imagem será apresentada aqui.

Avaliações Negativas
A imagem será apresentada aqui.

1-gram: Palavras isoladas
Avaliações positivas
A imagem será apresentada aqui.

Avaliações negativas
A imagem será apresentada aqui.

**2-gram: **
Avaliações positivas
A imagem será apresentada aqui.

Avaliações negativas
A imagem será apresentada aqui.

**3-gram: **
Avaliações positivas
A imagem será apresentada aqui.

Avaliações negativas
A imagem será apresentada aqui.

Códigos:

import pandas as pd
import re
from nltk.stem import WordNetLemmatizer, PorterStemmer, SnowballStemmer
import matplotlib.pyplot as plt
from wordcloud import WordCloud
from nltk.tokenize import word_tokenize
from nltk.util import ngrams, bigrams, trigrams
from collections import Counter

#função que realiza todos os tratamentos
def preprocess(raw_text):

    #Removendo números
    letters_only_text = re.sub("[^a-zA-Z]", " ", raw_text)

    # Convertendo em caixa baixa
    words = letters_only_text.lower().split()

    cleaned_words = []
    lemmatizer = PorterStemmer() #caso queira fazer a lemmatização deve-se trocar aqui para "WordNetLemmatizer"

    #R emoveendo stopwords
    for word in words:
        if word not in stop_words:
            cleaned_words.append(word)

    # stemmatização (poderia ser feita a lemmatização com pouca alteração)
    stemmed_words = []
    for word in cleaned_words:
        word = lemmatizer.stem(word) #aqui poderia ser trocado "steam" por "lemmatize"
        stemmed_words.append(word)

    # Convertendo lista em string
    return " ".join(stemmed_words)

if __name__ == '__main__':

#importando dados
    df = pd.read_csv('dados2.csv')

#Filrando colunas de interesse   
    a = df[['id', 'name', 'reviews.rating', 'reviews.text']]

#filtrando por produto (no caso, pilhas alcalinas) e por avaliação

    hr = a.loc[(a['id']=='AVpgNzjwLJeJML43Kpxn') & (a['reviews.rating'] >4) ]
    lr = a.loc[(a['id']=='AVpgNzjwLJeJML43Kpxn') & (a['reviews.rating'] <4) ]

#isolando os textos
    hrt = hr['reviews.text']
    lrt = lr['reviews.text']


#aqui vou criar a lista de stopwords que serão excluidas pela função preprocess
#A biblioteca nltk possui uma lista predefinida, mas eu encontrei esta lista mais completa 
#em um artigo na internet
    stop_words_file = 'SmartStoplist.txt'

    stop_words = []

    with open(stop_words_file, "r") as f:
        for line in f:
            stop_words.extend(line.split()) 

    stop_words = stop_words

    hrt = hr['reviews.text'].apply(preprocess)
    lrt = lr['reviews.text'].apply(preprocess)

#transformando em texto único

    hrtj = '' 
    for arg in hrt: 

        tokens = arg.split()  

        hrtj += " ".join(tokens)+" "

        lrtj = '' 
    for arg in lrt: 

        tokens = arg.split()  

        lrtj += " ".join(tokens)+" "


# plotando worldcloud    

    wordcloud = WordCloud(width = 700, height = 700, 
                    background_color ='white', 
                    min_font_size = 10).generate(hrtj) 


    plt.figure(figsize = (5, 5), facecolor = None) 
    plt.imshow(wordcloud) 
    plt.axis("off") 
    plt.tight_layout(pad = 0) 

    plt.show()

#notasse que as palavras baterri e reviw aparecem com frequencia demasiada e 
#não informam nada sobre o produto, logo serão removidas.

#retirando as palavras batteri e review

    hrlr = hrtj.split()
    lrlr = lrtj.split()


    hrlr = [h for h in hrlr if h != 'batteri' and h != 'review' ]
    lrlr = [l for l in lrlr if l != 'batteri' and l != 'review' ]

    hrtr = '' 
    for arg in hrlr: 

        hrtr += arg +" "

    lrtr = '' 
    for arg in lrlr: 

        lrtr += arg +" "

#Wordcloud para as avaliações positivas

    hwordcloud = WordCloud(width = 700, height = 700, 
                    background_color ='white', 
                    min_font_size = 10).generate(hrtr) 


    plt.figure(figsize = (5, 5), facecolor = None) 
    plt.imshow(hwordcloud) 
    plt.axis("off") 
    plt.tight_layout(pad = 0) 

    plt.show()

#Wordcloud para as avaliações negativas

    lwordcloud = WordCloud(width = 700, height = 700, 
                    background_color ='white', 
                    min_font_size = 10).generate(lrtr) 


    plt.figure(figsize = (5, 5), facecolor = None) 
    plt.imshow(lwordcloud) 
    plt.axis("off") 
    plt.tight_layout(pad = 0) 

    plt.show()


    #Realizand o a contagem de termos

    #O código abaixo permite realizar a contagem para diverso n-gramas com pequenas alterações
    #ele foi utilizado para gerar todos os gráficos de barras apresentados.


    n_gram = 2


    n_gram_dic_h = dict(Counter(ngrams(hrlr, n_gram)))
    n_gram_df_h  = pd.DataFrame(list(n_gram_dic_h.items()),columns = ['col1','col2']) 
    n_gram_df_h = n_gram_df_h.sort_values(by=['col2'], ascending=False) 



    n_gram_dic_l = dict(Counter(ngrams(lrlr, n_gram)))
    n_gram_df_l  = pd.DataFrame(list(n_gram_dic_l.items()),columns = ['col1','col2']) 
    n_gram_df_l = n_gram_df_l.sort_values(by=['col2'], ascending=False) 



    xhigh = []
    xlow = []
    yhigh = n_gram_df_h['col2']
    ylow = n_gram_df_l['col2']


    for t in n_gram_df_h['col1']:
        xstr = t[0]+" "+ t[1]
        xhigh.append(xstr)

    for j in n_gram_df_l['col1']:
        xstr = j[0]+" "+ j[1]
        xlow.append(xstr)

    n = 20    
    xhigh = xhigh[1:n]
    xlow  = xlow[1:n]

    yhigh = yhigh[1:n]
    ylow  = ylow[1:n]


    print(n_gram_df_h[1:n])
    print(plt.barh(xhigh, yhigh))
Compartilhe

Entre ou cadastre-se para responder esta pergunta.

...