on
[PT-BR] Introdução à Inferência Estatística
Thanks rawpixel for the pic!
Em Data Science nos normalmente falamos muito sobre Análise de Dados Exploratória (Estatística Descritiva) mas existe um outro “mundo estatístico” muito útil para nós: o ramo da Inferência Estatística.
Inferência estatística é um ramo da Estatística cujo objetivo é fazer afirmações a partir de um conjunto de valores representativo (amostra) sobre um universo (população)[1], assume-se que a população é muito maior do que o conjunto de dados observados, a amostra. Tal tipo de afirmação deve sempre vir acompanhada de uma medida de precisão sobre sua veracidade. — Inferência estatística
Nesse artigo vamos usar os dados das salas de chat do freeCodeCamp para responder a seguinte pergunta: existe alguma diferença no padrão de menção em salas de cidades diferentes?
Vamos aprender um pocuo sobre Inferência Estatística e como extrair informação de textos usando a classe Matcher do spaCy. Primeiro a gente vai ver como extrair os dados e depois usar estatística para fazer inferências.
Extraindo informação usando o spacy.Matcher
A forma de usar o Matcher é similar a forma que usamos expressões regulares (inclusive podemos usar regex para criar padrões). Cada regra pode ter muitos padrões, e um padrão consiste em uma lista de dicionários, onde cada dicionário descreve um token.
// este padrão captura todos os tokens == 'hello' (lowercase)
{'LOWER': 'hello'}
Vamos criar exemplos de informações que podemos extrair das mensagens.
Saudações
Temos 4 padrões para a mesma regra ("SAUDACAO"
):
matcher = Matcher(nlp.vocab)
self.matcher.add("SAUDACAO", None,
[{"LOWER": "good"}, {"LOWER": "morning"}],
[{"LOWER": "good"}, {"LOWER": "evening"}],
[{"LOWER": "good"}, {"LOWER": "afternoon"}],
[{"LOWER": "good"}, {"LOWER": "night"}])
matches = matcher(text)
Padrão: Mensagens com pontuação
Podemos usar todos os token attributes disponíveis como padrões. No exemplos a seguir vamos capturar toda mensagem que possui pontuação:
matcher = Matcher(nlp.vocab)
self.matcher.add("PUNTUACAO", None,
[{"IS_PUNCT": True}])
matches = matcher(text)
Padrão: Como as pessoas estão se sentido?
Neste exemplo os padrões começam a ficar mais interessantes. Vamos capturar todos os
lemmas do verbo ‘ser’ para detectar todas as conjugações do verbo. O matcher também permite que você use quantificadores, especificados com o operador 'OP'
. Vamos capturar todos os advérbios depois do verbo ser (com 'OP': '*'
podemos capturar todos eles).
Depois do advérbio existem várias possibilidades para a próxima palavra, por isso vamos usar o wildcard {}
, que captura qualquer palavra.
matcher = Matcher(nlp.vocab)
self.matcher.add("FEELING", None,
[
{"LOWER": "i"}, {"LEMMA":"be"},
{"POS": "ADV", "OP": "*"},
{"POS": "ADJ"}
])
matches = matcher(text)
Padrão: Menções
Não existe um atributo para uma palavra com @ no primeiro caractere (@nick_da_pessoa), então vamos criar um.
mention_flag = lambda text: bool(
.match(text))
IS_MENTION = nlp.vocab.add_flag(mention_flag)
self.matcher.add("MENTION", None, [{IS_MENTION: True}])
matches = matcher(text)
Eu criei um conjunto de dados com as menções desta forma:
[message, mention, sent_at, city]
Você pode acessar todo o código aqui.
Introdução à Inferência Estatística
Inferência Estatística consiste e usar análise de dados para deduzir propriedades a partir de uma distribuição de probabilidade (Statistical inference, tradução nossa).
Nós temos amostras de mensagens das salas de chat e queremos compará-las. Com Estatística de Teste podemos medir a probabilidade das amostras pertenceram à mesma distribuição. Aplicando isso ao nosso cenário, se a probabilidade das menções pertenceram à mesma distribuição for menor do que um limite (definido por nós) então nós podemos inferir que pessoas de cidades diferentes possuem padrões de menção diferentes.
Vamos definir uns conceitos para clarear um pouco as coisas (todas as definições foram tiradas da Wikipedia):
- Distribuição de Frequência: uma lista, tabela ou gráfico que mostra a frequência dos valores de uma amostra
- Hipótese Nula: a hipótese nula geralmente afirma que não existe relação entre dois fenômenos medidos
- Valor-p: é a probabilidade de se obter uma estatística de teste igual ou mais extrema que aquela observada em uma amostra, sob a hipótese nula. Em termos gerais, um valor-p pequeno significa que a probabilidade de obter um valor da estatística de teste como o observado é muito improvável, levando assim à rejeição da hipótese nula
- Significância estatística: a significância estatística é considerada um procedimento para verificar a discrepância de uma hipótese estatística em relação aos dados observados, utilizando uma medida de evidência (valor-p)
Em termos gerais um teste de hipótese funciona assim:
- Nós assumimos que algo é verdade
- Depois nós tentamos provar que é impossível que o que dissemos em 1 seja verdade
- Se nós verificarmos que com os resultados realmente não é provável que 1 seja verdade, nós rejeitamos a hipótese
“O Teste de hipóteses é um argumento de reductio ad absurdum adaptado para estatística. Na sua essência, uma hipótese é dita válida se o seu oposto for improvável”. — P-value
No nosso caso estamos lidando com variáveis categóricas (variáveis que podem assumir um valor a partir de um número fixo de possíveis valores). Por conta disso iremos usar a distribuição Qui-quadrado.
A distribuição χ2 ou qui-quadrado é uma das distribuições mais utilizadas em inferência estatística, principalmente para realizar testes de χ2. Este teste serve para avaliar quantitativamente a relação entre o resultado de um experimento e a distribuição esperada para o fenômeno. Isto é, ele nos diz com quanta certeza os valores observados podem ser aceitos como regidos pela teoria em questão. — Qui-quadrado
“Os estatísticos identificaram várias distribuições comuns, conhecidas como distribuições de probabilidade. A partir dessas distribuições é possível calcular a probabilidade de se obter um determinado valor baseado na frequência em que este valor ocorre na distribuição.” — Discovering Statistics Using R, tradução nossa
O teste qui-quadrado para homogeneidade
Queremos saber se a distribuição de menções é a mesma para cada cidade. Primeiro nós assumimos que as menções pertencem à mesma população e somamos todas a menções de cada cidade. Esta distribuição (todas as menções de todas as cidades) deve ser a mesma para cada cidade caso elas realmente pertençam à mesma população.
Nós não podemos provar que as distribuições são diferentes usando estatística, mas podemos rejeitar a hipótese delas serem iguais.
“Precisamos da hipótese nula porque não podemos provar a hipótese experimental usando estatística, mas podemos rejeitar a hipótese nula. Se os dados te dão confiança para rejeitar a hipótese nula então temos suporte para considerar a hipótese alternativa. No entanto, esteja ciente que se nós rejeitarmos a hipótese nula, isso não prova a hipótese experimentar, apenas nós dá suporte para considerá-la — Discovering Statistics Using R, tradução nossa
Esse é um ponto muito importante. Não estamos provando que a hipótese alternativa é verdade, estamos afirmando que com este nível de significância é provável que ela seja verdadeira.
“Então em vez de falarmos sobre aceitar ou rejeitar uma hipótese (o que alguns livros te mandam fazer) nós devemos falar sobre ‘as chances de se obter os resultados que obtivemos assumindo que a hipótese nula é verdadeira’.” — Discovering Statistics Using R, Tradução nossa
Em sua essência, quando coletamos dados para testar teorias nós só podemos falar em termos da probabilidade de se obter um determinado conjunto de resultados. (Field, Andy). E para julgar isso nós utilizamos o valor-p.
- Valor-p alto: seus resultados são prováveis com a hipótese nula verdadeira
- Valor-p baixo: seus resultados são pouco prováveis dado que a hipótese nula seja verdade, (How to Correctly Interpret P Values)
Vamos definir nosso nível de significância em 5% (limite do valor-p em 0.05).
Ok, agora podemos voltar ao teste.
Os dados
Vamos usar os dados de toda a atividade nas salas do freeCodeCamp no Gitter. O conjunto de dados pode ser encontrado aqui.
Nosso sample possui mensagens de São Francisco, Toronto, Boston, Belgrade, Londres e São Paulo enviadas entre 16/08/2015 e 16/08/2016 (1 ano de mensagens).
Condições para o teste qui-quadrado para homogeneidade
Precisamos dessas condições para realizar o teste:
- O método utilizado para criar o conjunto de amostras é o de amostras aleatórias simples
- O valor esperado para todas as amostras é maior ou igual a 5
Vamos assumir a primeira condição é válida (1 ano de dados para cada cidade). Para verificar se a segunda condição é válida precisamos analisar os dados.
Explorando os dados
Eu criei um arquivo JSON com os dados, vamos usar a biblioteca jsonlite do R para explorar o conteúdo:
> library(jsonlite)
> df <- fromJSON("experiment_sample_data.json")
> library(mosaic)
> mentiontable <- tally(~city+mention, data=df, margins=T)
> mentiontable
mention
city NO YES
Belgrade 184 45
Boston 383 121
London 278 98
SanFrancisco 156 51
SaoPaulo 153 132
Toronto 379 81
Agora precisamos introduzir outro conceito da Estatística: tabelas de contingência.
- Tabelas de Contingência: uma tabela de contingência é um tipo de tabela no formato de matriz, mostrando a frequência de distribuição das variáveis.
Com o método chisq.test
podemos criar tabelas de contingência e realizar o teste qui-quadrado. Vamos calcular o valor esperado para esta amostra.
Valor esperado = (soma dos dados na linha)×(soma dos dados na coluna) / valor total dos dados.
Seguindo esta fórmula, o valor esperado para o número de mensagens com menções (mention=YES) para a cidade de São Paulo é:
285*407/1557 = 74,49903
O valor expected
de chisq.test
nos mostra os valores esperados dado que a hipótese nula seja verdadeira pra todas as cidades:
> chisq.test(mentiontable)$expected
mention
city NO YES
Belgrade 170.3333 58.66667
Boston 374.8821 129.11790
London 279.6739 96.32606
SanFrancisco 153.9694 53.03057
SaoPaulo 211.9869 73.01310
Toronto 342.1543 117.84571
Todos os valores esperados são maiores que 5, então podemos realizar o teste.
O teste qui-quadrado
Nós assumimos que as distribuições do número de menções em todas as cidades são iguais, então a coluna ‘total’ é a estimativa desta distribuição:
> tally(~mention, data=df)
mention
NO YES
1150 407 matcher = Matcher(nlp.vocab)
O teste qui-quadrado é usado para determinar se existe uma diferença significativa entre a frequência esperada e a frequência observada.
Para cada célula, a frequência esperada é subtraída da frequência observada, este valor é elevado ao quadrado e dividido pela frequência esperada. Os valores para todas as células são somados. Esta soma é o valor do teste qui-quadrado. — The chi-square test, tradução nossa
Com o valor do teste qui-quadrado e o grau de liberdade (quantidade_de_linhas - 1 × quantidade_de_colunas - 1) podemos calcular a probabilidade de termos esse valor ‘por acaso’.
Pearson's Chi-squared test
data: mentiontable
X-squared = 84.667, df = 5, p-value < 2.2e-16
O valor-p é menor que o alpha (0.05), então nós rejeitamos a hipótese nula. Isto quer dizer que com esses valores de menções para cada cidade é pouco provável que as cidades apresentem as mesmas distribuições de menções.
Nós também podemos examinar a fonte das diferenças nos padrões de menções.
Examinando o residual para encontrar a fonte das diferenças
Já que temos os valores esperados para cada cidade é possível calcular o residual: (observado - esperado) / sqrt(esperado)
O residual é a medida da variação entre o valor esperado e o valor observado, o que mostra a direção da variação (se o valor esperado foi maior ou menor, o que é interessante para interpretar os resultados). Esta medida se apresenta como uma distribuição normal, com valores de variações altas maiores que 2 ou 3. — Intermediate Statistics with R, tradução nossa
mosaicplot(mentiontable, shade=T)
Mosaic plot
Para as cidades de São Paulo e Toronto o número de mensagens com menção e sem menção está a 2.4 desvios padrão distante do valor esperado. As salas de chat de São Paulo tem mais pessoas mencionando as outras do que é esperado, e nas salas de Toronto existem menos pessoas mencionando outras do que é esperado.
Um próximo passo seria identificar a fonte dessas diferenças. Talvez por causa do número de pessoas em cada sala de chat? Ou talvez as pessoas já se conheçam e por isso elas conversam mais entre si?
Considerações finais
Na Estatística de Inferência nós fazemos deduções a partir das propriedades de uma distribuição de probabilidade. Quando você tem variáveis categóricas é possível utilizar o teste qui-quadrado para encontrar a probabilidade da distribuição ser a mesma para duas ou mais populações (ou subgrupos de uma população).
Os passos para o teste de hipótese são:
- Assumir a a hipótese nula é verdadeira
- Tentar provar que é impossível que a hipótese nula seja verdadeira
- Se de fato o teste mostrar que é poupo provável que a hipótese nula seja verdadeira, rejeitamos a hipótese nula.
Além disso também vimos como a classe Spacy.Matcher é útil para extrair informações de textos. Neste artigo fizemos o teste extraindo as menções para no código podemos ver outros exemplos de padrões que podem ser extraídos.
É isso! Obrigada pela leiturara! 😄