Como criar um racista de IA sem muito esforço

Uma lição de advertência.

Vamos fazer um classificador de tonalidade!

A análise de sentimentos (análise de sentimentos) é uma tarefa muito comum no processamento de linguagem natural (PNL), e isso não é surpreendente. É importante que uma empresa entenda o que as pessoas estão dizendo: positivas ou negativas. Essa análise é usada para monitorar redes sociais, feedback dos clientes e até mesmo na negociação algorítmica de ações (como resultado, os bots compram ações da Berkshire Hathaway depois de postarem críticas positivas sobre o papel de Anne Hathaway no último filme ).

Às vezes, o método de análise é muito simplificado, mas é uma das maneiras mais fáceis de obter resultados mensuráveis. Basta enviar o texto - e o resultado é positivo e negativo. Não há necessidade de lidar com a árvore de análise, criar um gráfico ou outra representação complexa.

É isso que faremos. Seguiremos o caminho de menor resistência e tornaremos o classificador mais simples, que provavelmente parece muito familiar para todos os envolvidos em desenvolvimentos relevantes no campo da PNL. Por exemplo, esse modelo pode ser encontrado no artigo Deep Averaging Networks (Iyyer et al., 2015). Não estamos tentando desafiar seus resultados ou criticar o modelo; simplesmente fornecemos um método bem conhecido de representação vetorial de palavras.

Plano de trabalho:

  • Introduzir uma representação vetorial típica de palavras para trabalhar com significados (significados).
  • Introduzir conjuntos de dados de treinamento e teste com listas padrão de palavras positivas e negativas.
  • Treine o classificador de descida de gradiente para reconhecer outras palavras positivas e negativas com base em sua representação vetorial.
  • Use este classificador para calcular classificações de tonalidade para frases de texto.
  • Para ver o monstro que criamos.

E então veremos "como criar um racista de IA sem esforços especiais". Obviamente, você não pode deixar o sistema de uma forma tão monstruosa, então vamos:

  • Avaliar o problema estatisticamente, para que seja possível medir o progresso conforme ele é resolvido.
  • Melhore os dados para obter um modelo semântico mais preciso e menos racista.

Dependências de software


Este tutorial foi escrito em Python e baseia-se em uma pilha típica de aprendizado de máquina Python: numpy e scipy para computação numérica, pandas para gerenciamento de dados e scikit-learn para aprendizado de máquina. No final, também seaborn matplotlib e seaborn para criar diagramas.

Em princípio, o scikit-learn pode ser substituído por TensorFlow ou Keras, ou algo assim: eles também são capazes de treinar o classificador em descidas gradientes. Mas não precisamos de suas abstrações, porque aqui o treinamento ocorre em um estágio.

 import numpy as np import pandas as pd import matplotlib import seaborn import re import statsmodels.formula.api from sklearn.linear_model import SGDClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score #     %matplotlib inline seaborn.set_context('notebook', rc={'figure.figsize': (10, 6)}, font_scale=1.5) 

Etapa 1. Representação vetorial de palavras


As representações vetoriais são frequentemente usadas quando há entrada de texto. As palavras se tornam vetores no espaço multidimensional, onde vetores adjacentes representam significados semelhantes. Usando representações vetoriais, você pode comparar as palavras pelo significado (aproximadamente) e não apenas pelas correspondências exatas.

O aprendizado bem-sucedido requer centenas de gigabytes de texto. Felizmente, várias equipes de pesquisa já fizeram esse trabalho e forneceram modelos pré-treinados de representações vetoriais disponíveis para download.

Os dois conjuntos de dados mais conhecidos para o idioma inglês são word2vec (treinado nos textos do Google Notícias) e GloVe (nas páginas da web de rastreamento comum). Qualquer um deles dará um resultado semelhante, mas usaremos o modelo GloVe porque ele tem uma fonte de dados mais transparente.

O GloVe vem em três tamanhos: 6 bilhões, 42 bilhões e 840 bilhões.O modelo mais recente é o mais poderoso, mas requer recursos de processamento significativos. A versão de 42 bilhões é muito boa, e o dicionário é bem aparado para 1 milhão de palavras. Estamos no caminho de menor resistência, então pegue a versão de 42 bilhões.

- Por que é tão importante usar um modelo "conhecido"?

"Estou feliz que você perguntou sobre isso, interlocutor hipotético!" Em cada etapa, tentamos fazer algo extremamente típico, e o melhor modelo para a representação vetorial de palavras por algum motivo ainda não foi determinado. Espero que este artigo desperte o desejo de usar modelos modernos de alta qualidade , especialmente aqueles que levam em conta um erro algorítmico e tentam corrigi-lo. No entanto, mais sobre isso mais tarde.

Faça o download do arquivo glove.42B.300d.zip no site da GloVe e extraia o arquivo data/glove.42B.300d.txt . Em seguida, definimos uma função para ler vetores em um formato simples.

 def load_embeddings(filename): """  DataFrame      ,   word2vec, GloVe, fastText  ConceptNet Numberbatch.            . """ labels = [] rows = [] with open(filename, encoding='utf-8') as infile: for i, line in enumerate(infile): items = line.rstrip().split(' ') if len(items) == 2: # This is a header row giving the shape of the matrix continue labels.append(items[0]) values = np.array([float(x) for x in items[1:]], 'f') rows.append(values) arr = np.vstack(rows) return pd.DataFrame(arr, index=labels, dtype='f') embeddings = load_embeddings('data/glove.42B.300d.txt') embeddings.shape 

(1917494, 300)

Etapa 2. Dicionário de tonalidade padrão-ouro


Agora precisamos de informações sobre quais palavras são consideradas positivas e quais são negativas. Existem muitos dicionários, mas usaremos um dicionário muito simples (Hu e Liu, 2004), que é usado no artigo da Deep Averaging Networks .

Faça o download do dicionário no site do Bing Liu e extraia os dados em data/positive-words.txt e data/negative-words.txt .

Em seguida, determinamos como ler esses arquivos e os atribuímos como neg_words e neg_words :

 def load_lexicon(filename): """       (https://www.cs.uic.edu/~liub/FBS/sentiment-analysis.html)      Latin-1.      ,    - .    ,    ';'   ,   . """ lexicon = [] with open(filename, encoding='latin-1') as infile: for line in infile: line = line.rstrip() if line and not line.startswith(';'): lexicon.append(line) return lexicon pos_words = load_lexicon('data/positive-words.txt') neg_words = load_lexicon('data/negative-words.txt') 

Etapa 3. Treinamos o modelo para prever a tonalidade


Com base nos vetores de palavras positivas e negativas, usamos o comando Pandas .loc[] para procurar representações vetoriais de todas as palavras.

Algumas palavras estão faltando no dicionário GloVe. Na maioria das vezes, esses são erros de digitação, como "fantasiar". Aqui vemos um monte de NaN , que indica a ausência de um vetor, e os .dropna() com o comando .dropna() .

pos_vectors = embeddings.loc[pos_words].dropna()
neg_vectors = embeddings.loc[neg_words].dropna()


Agora, criamos matrizes de dados na entrada (representações vetoriais) e na saída (1 para palavras positivas e -1 para negativa). Também verificamos que os vetores estão anexados às palavras para que possamos interpretar os resultados.

vectors = pd.concat([pos_vectors, neg_vectors])
targets = np.array([1 for entry in pos_vectors.index] + [-1 for entry in neg_vectors.index])
labels = list(pos_vectors.index) + list(neg_vectors.index)


- Espere. Algumas palavras não são positivas nem negativas, são neutras. Uma terceira classe não deveria ser criada para palavras neutras?

"Eu acho que ele teria sido útil." Mais tarde, veremos quais problemas surgem devido à atribuição de tonalidade a palavras neutras. Se pudermos identificar com segurança palavras neutras, é bem possível aumentar a complexidade do classificador para três categorias. Mas você precisa encontrar um dicionário de palavras neutras, porque no dicionário de Liu existem apenas palavras positivas e negativas.

Então, tentei minha versão com 800 exemplos de palavras e aumentei o peso para prever palavras neutras. Mas os resultados finais não foram muito diferentes do que você verá agora.

- Como esta lista distingue palavras positivas e negativas? Isso não depende do contexto?

Boa pergunta. A análise das chaves gerais não é tão simples quanto parece. A fronteira é bastante arbitrária em alguns lugares. Nesta lista, a palavra "insolente" é marcada como "ruim" e "ambiciosa" como "boa". "Comic" é ruim e "engraçado" é bom. Um "reembolso" é bom, embora geralmente seja mencionado em um contexto ruim quando você deve dinheiro a alguém ou deve a alguém.

Todo mundo entende que a tonalidade é determinada pelo contexto, mas em um modelo simples, você precisa ignorar o contexto e esperar que a tonalidade média seja adivinhada corretamente.

Usando a função train_test_split , dividimos simultaneamente os vetores de entrada, valores de saída e rótulos em dados de treinamento e teste, deixando 10% para o teste.

 train_vectors, test_vectors, train_targets, test_targets, train_labels, test_labels = \ train_test_split(vectors, targets, labels, test_size=0.1, random_state=0) 

Agora crie um classificador e passe vetores através de iterações. Usamos a função de perda logística para que o classificador final possa deduzir a probabilidade de a palavra ser positiva ou negativa.

 model = SGDClassifier(loss='log', random_state=0, n_iter=100) model.fit(train_vectors, train_targets) SGDClassifier(alpha=0.0001, average=False, class_weight=None, epsilon=0.1, eta0=0.0, fit_intercept=True, l1_ratio=0.15, learning_rate='optimal', loss='log', n_iter=100, n_jobs=1, penalty='l2', power_t=0.5, random_state=0, shuffle=True, verbose=0, warm_start=False) 

Avaliamos o classificador em vetores de teste. Mostra uma precisão de 95%. Nada mal.

accuracy_score(model.predict(test_vectors), test_targets)
0.95022624434389136


Definimos a função de previsão de tonalidade para certas palavras e, em seguida, a usamos para alguns exemplos de dados de teste.

 def vecs_to_sentiment(vecs): # predict_log_proba  log-    predictions = model.predict_log_proba(vecs) #        #  log-    . return predictions[:, 1] - predictions[:, 0] def words_to_sentiment(words): vecs = embeddings.loc[words].dropna() log_odds = vecs_to_sentiment(vecs) return pd.DataFrame({'sentiment': log_odds}, index=vecs.index) #  20      words_to_sentiment(test_labels).ix[:20] 

tonalidade
inquietação-9.931679
interromper-9.634706
firmemente1.466919
imaginário-2,989215
tributação0.468522
mundialmente famoso6.908561
barato9.237223
desapontamento-8.737182
totalitário-10.851580
beligerante-8,328674
congela-8,456981
pecado-7.839670
frágil-4,018289
enganado-4,309344
não resolvido-2,816172
habilmente2.339609
demoniza-2.102152
despreocupado8.747150
impopular-7,887475
simpatizar1.790899

É visto que o classificador está funcionando. Ele aprendeu a generalizar a tonalidade em palavras fora dos dados de treinamento.

Etapa 4. Obtenha uma pontuação de tonalidade para o texto.


Existem várias maneiras de adicionar vetores a uma estimativa geral. Novamente, seguimos o caminho de menor resistência, portanto, basta pegar o valor médio.

 import re TOKEN_RE = re.compile(r"\w.*?\b") # regex  ,     (\w)   #   (.+?)    (\b).   #       . def text_to_sentiment(text): tokens = [token.casefold() for token in TOKEN_RE.findall(text)] sentiments = words_to_sentiment(tokens) return sentiments['sentiment'].mean() 

Há muito a ser solicitado para otimização:

  • Introduzir uma relação inversa entre a palavra peso e sua frequência, para que as mesmas preposições não afetem muito a tonalidade.
  • Configuração para que frases curtas não terminem com valores extremos de tonalidade.
  • Frases de contabilidade.
  • Um algoritmo de segmentação de palavras mais confiável que apóstrofos não são interrompidos.
  • Contabilizando negativos como "não satisfeito".

Mas tudo requer código adicional e não altera fundamentalmente os resultados. Pelo menos agora você pode comparar aproximadamente ofertas diferentes:

 text_to_sentiment("this example is pretty cool") 3.889968926086298 

 text_to_sentiment("this example is okay") 2.7997773492425186 

 text_to_sentiment("meh, this example sucks") -1.1774475917460698 

Passo 5. Veja o monstro que criamos


Nem toda frase tem uma tonalidade pronunciada. Vamos ver o que acontece com frases neutras:

 text_to_sentiment("Let's go get Italian food") 2.0429166109408983 

 text_to_sentiment("Let's go get Chinese food") 1.4094033658140972 

 text_to_sentiment("Let's go get Mexican food") 0.38801985560121732 

Eu já encontrei esse fenômeno ao analisar resenhas de restaurantes, levando em consideração representações vetoriais de palavras. Por nenhuma razão aparente , todos os restaurantes mexicanos têm uma pontuação geral mais baixa .

As representações vetoriais capturam diferenças semânticas sutis no contexto. Portanto, eles refletem os preconceitos da nossa sociedade.

Aqui estão algumas outras sugestões neutras:

 text_to_sentiment("My name is Emily") 2.2286179364745311 

 text_to_sentiment("My name is Heather") 1.3976291151079159 

 text_to_sentiment("My name is Yvette") 0.98463802132985556 

 text_to_sentiment("My name is Shaniqua") -0.47048131775890656 

Bem, droga ...

O sistema associado aos nomes das pessoas sentimentos completamente diferentes. Você pode ver esses e muitos outros exemplos e ver que a tonalidade é geralmente mais alta para nomes estereotipicamente brancos e menor para nomes estereotipados pretos.

Este teste foi usado por Caliscan, Bryson e Narayanan em seu trabalho de pesquisa publicado na revista Science em abril de 2017. Prova que a semântica do corpus da linguagem contém os preconceitos da sociedade . Vamos usar esse método.

Etapa 6. Avaliando o problema


Queremos entender como evitar esses erros. Vamos passar mais dados pelo classificador e medir estatisticamente seu “viés”.

Aqui temos quatro listas de nomes que refletem diferentes origens étnicas, principalmente nos EUA. Os dois primeiros são listas de nomes predominantemente “brancos” e “negros”, adaptados com base em um artigo de Kaliskan et al. Também adicionei nomes espanhóis e muçulmanos do árabe e do urdu.

Esses dados são usados ​​para verificar o viés do algoritmo durante o processo de construção do ConceptNet: ele pode ser encontrado no módulo conceptnet5.vectors.evaluation.bias . Existe uma idéia de expandir o dicionário para outros grupos étnicos, levando em consideração não apenas nomes, mas também sobrenomes.

Aqui estão as listagens:

 NAMES_BY_ETHNICITY = { #           . 'White': [ 'Adam', 'Chip', 'Harry', 'Josh', 'Roger', 'Alan', 'Frank', 'Ian', 'Justin', 'Ryan', 'Andrew', 'Fred', 'Jack', 'Matthew', 'Stephen', 'Brad', 'Greg', 'Jed', 'Paul', 'Todd', 'Brandon', 'Hank', 'Jonathan', 'Peter', 'Wilbur', 'Amanda', 'Courtney', 'Heather', 'Melanie', 'Sara', 'Amber', 'Crystal', 'Katie', 'Meredith', 'Shannon', 'Betsy', 'Donna', 'Kristin', 'Nancy', 'Stephanie', 'Bobbie-Sue', 'Ellen', 'Lauren', 'Peggy', 'Sue-Ellen', 'Colleen', 'Emily', 'Megan', 'Rachel', 'Wendy' ], 'Black': [ 'Alonzo', 'Jamel', 'Lerone', 'Percell', 'Theo', 'Alphonse', 'Jerome', 'Leroy', 'Rasaan', 'Torrance', 'Darnell', 'Lamar', 'Lionel', 'Rashaun', 'Tyree', 'Deion', 'Lamont', 'Malik', 'Terrence', 'Tyrone', 'Everol', 'Lavon', 'Marcellus', 'Terryl', 'Wardell', 'Aiesha', 'Lashelle', 'Nichelle', 'Shereen', 'Temeka', 'Ebony', 'Latisha', 'Shaniqua', 'Tameisha', 'Teretha', 'Jasmine', 'Latonya', 'Shanise', 'Tanisha', 'Tia', 'Lakisha', 'Latoya', 'Sharise', 'Tashika', 'Yolanda', 'Lashandra', 'Malika', 'Shavonn', 'Tawanda', 'Yvette' ], #         . 'Hispanic': [ 'Juan', 'José', 'Miguel', 'Luís', 'Jorge', 'Santiago', 'Matías', 'Sebastián', 'Mateo', 'Nicolás', 'Alejandro', 'Samuel', 'Diego', 'Daniel', 'Tomás', 'Juana', 'Ana', 'Luisa', 'María', 'Elena', 'Sofía', 'Isabella', 'Valentina', 'Camila', 'Valeria', 'Ximena', 'Luciana', 'Mariana', 'Victoria', 'Martina' ], #       # ,   .     . # #          # -   .    #   ,    . # #       . 'Arab/Muslim': [ 'Mohammed', 'Omar', 'Ahmed', 'Ali', 'Youssef', 'Abdullah', 'Yasin', 'Hamza', 'Ayaan', 'Syed', 'Rishaan', 'Samar', 'Ahmad', 'Zikri', 'Rayyan', 'Mariam', 'Jana', 'Malak', 'Salma', 'Nour', 'Lian', 'Fatima', 'Ayesha', 'Zahra', 'Sana', 'Zara', 'Alya', 'Shaista', 'Zoya', 'Yasmin' ] } 

Usando Pandas, compilaremos uma tabela de nomes, sua origem étnica predominante e classificações de tonalidade:

 def name_sentiment_table(): frames = [] for group, name_list in sorted(NAMES_BY_ETHNICITY.items()): lower_names = [name.lower() for name in name_list] sentiments = words_to_sentiment(lower_names) sentiments['group'] = group frames.append(sentiments) #           return pd.concat(frames) name_sentiments = name_sentiment_table() 

Dados de exemplo:

name_sentiments.ix[::25]
tonalidadeo grupo
mohammed0.834974Árabe / muçulmano
alya3.916803Árabe / muçulmano
terryl-2,858010Preto
josé0.432956Hispânico
luciana1.086073Hispânico
hank0,391858Branco
megan2.158679Branco

Faremos um gráfico da distribuição da tonalidade para cada nome.

 plot = seaborn.swarmplot(x='group', y='sentiment', data=name_sentiments) plot.set_ylim([-10, 10]) 

(-10, 10)



Ou como um histograma com intervalos de confiança para a média de 95%.

 plot = seaborn.barplot(x='group', y='sentiment', data=name_sentiments, capsize=.1) 



Por fim, execute o pacote de estatísticas statsmodels sério. Ele mostrará o quão grande é o viés do algoritmo (junto com várias outras estatísticas).


Resultados da regressão OLS
Dep. Variável:sentimentoR-quadrado:0,208
Modelo:OLSAdj. R-quadrado:0,192
Método:Mínimos quadradosEstatística F:13/04
Data:Qui, 13 Jul 2017Prob (estatística F):1.31e-07
Hora:11:31:17Probabilidade de log:-356,78
Não. Observações:153AIC:721,6
Df Residuals:149BIC:733,7
Modelo Df:3
Tipo de covariância:antiferrugem

Estatística F é a razão de variação entre os grupos para a variação dentro dos grupos, que pode ser tomada como uma avaliação geral do viés.

Imediatamente abaixo está indicada a probabilidade de vermos a estatística F máxima com a hipótese nula: ou seja, na ausência de uma diferença entre as opções comparadas. A probabilidade é muito, muito baixa. Em um artigo científico, chamaríamos o resultado de "muito estatisticamente significativo".

Precisamos melhorar o valor F. Quanto menor, melhor.

ols_model.fvalue
13.041597745167659


Etapa 7. Tentando outros dados.


Agora temos a oportunidade de medir numericamente o viés prejudicial do modelo. Vamos tentar ajustá-lo. Para fazer isso, você precisa repetir várias coisas que costumavam ser apenas etapas separadas em um bloco de notas Python.

Se eu escrevesse um código bom e suportado, não usaria variáveis ​​globais, como model e embeddings . Mas o código atual do espaguete permite que você examine melhor cada etapa e entenda o que está acontecendo. Reutilizamos parte do código e pelo menos definimos uma função para repetir algumas etapas:

 def retrain_model(new_embs): """      . """ global model, embeddings, name_sentiments embeddings = new_embs pos_vectors = embeddings.loc[pos_words].dropna() neg_vectors = embeddings.loc[neg_words].dropna() vectors = pd.concat([pos_vectors, neg_vectors]) targets = np.array([1 for entry in pos_vectors.index] + [-1 for entry in neg_vectors.index]) labels = list(pos_vectors.index) + list(neg_vectors.index) train_vectors, test_vectors, train_targets, test_targets, train_labels, test_labels = \ train_test_split(vectors, targets, labels, test_size=0.1, random_state=0) model = SGDClassifier(loss='log', random_state=0, n_iter=100) model.fit(train_vectors, train_targets) accuracy = accuracy_score(model.predict(test_vectors), test_targets) print("Accuracy of sentiment: {:.2%}".format(accuracy)) name_sentiments = name_sentiment_table() ols_model = statsmodels.formula.api.ols('sentiment ~ group', data=name_sentiments).fit() print("F-value of bias: {:.3f}".format(ols_model.fvalue)) print("Probability given null hypothesis: {:.3}".format(ols_model.f_pvalue)) #        Y plot = seaborn.swarmplot(x='group', y='sentiment', data=name_sentiments) plot.set_ylim([-10, 10]) 

Tentamos word2vec


Pode-se supor que apenas o GloVe tenha o problema. Provavelmente existem muitos sites duvidosos no banco de dados do Common Crawl e pelo menos 20 cópias do Dicionário Urbano de gírias de rua. Talvez em uma base diferente seja melhor: e a boa e velha word2vec treinada no Google Notícias?

Parece que a fonte mais autorizada para dados do word2vec é esse arquivo no Google Drive . Faça o download e salve-o como data/word2vec-googlenews-300.bin.gz .

 #   ConceptNet   word2vec   Pandas     from conceptnet5.vectors.formats import load_word2vec_bin w2v = load_word2vec_bin('data/word2vec-googlenews-300.bin.gz', nrows=2000000) #  word2vec    w2v.index = [label.casefold() for label in w2v.index] #  ,    w2v = w2v.reset_index().drop_duplicates(subset='index', keep='first').set_index('index') retrain_model(w2v) 

Accuracy of sentiment: 94.30%
F-value of bias: 15.573
Probability given null hypothesis: 7.43e-09


Portanto, o word2vec acabou sendo ainda pior com um valor F superior a 15.

Em princípio, era tolice esperar que as notícias fossem melhor protegidas contra preconceitos.

Tentando ConceptNet Numberbatch


Finalmente, posso falar sobre meu próprio projeto sobre a representação vetorial de palavras.

O ConceptNet com o recurso de apresentação vetorial é o gráfico de conhecimento em que estou trabalhando. Normaliza as representações vetoriais na fase de treinamento, identificando e removendo algumas fontes de racismo algorítmico e sexismo. Esse método de correção de viés é baseado em um artigo científico de Bulukbashi et al., “Debiasing Word Embeddings” e é generalizado para eliminar vários tipos de viés ao mesmo tempo. Até onde eu sei, este é o único sistema semântico em que existe algo assim.

Periodicamente, exportamos vetores pré-computados do ConceptNet - esses lançamentos são chamados ConceptNet Numberbatch . Em abril de 2017, o primeiro lançamento com correção de viés foi lançado, portanto, carregaremos os vetores no idioma inglês e treinaremos novamente nosso modelo.

numberbatch-en-17.04b.txt.gz , salvamos no diretório data/ e treinamos novamente o modelo:

 retrain_model(load_embeddings('data/numberbatch-en-17.04b.txt')) 

Accuracy of sentiment: 97.46%
F-value of bias: 3.805
Probability given null hypothesis: 0.0118




Então, o ConceptNet Numberbatch resolveu completamente o problema? Chega de racismo algorítmico? Não.

O racismo se tornou muito menos? Definitivamente .

Os intervalos principais para grupos étnicos se sobrepõem muito mais do que nos vetores GloVe ou word2vec. Comparado ao GloVe, o valor de F diminuiu mais de três vezes e comparado ao word2vec - mais de quatro vezes. E, em geral, vemos diferenças muito menores na tonalidade ao comparar nomes diferentes: deve ser assim, porque os nomes realmente não devem afetar o resultado da análise.

Mas uma ligeira correlação permaneceu. Talvez eu possa pegar esses dados e parâmetros de treinamento que o problema parece estar resolvido. Mas essa será uma opção ruim, porque , de fato, o problema permanece, porque no ConceptNet não identificamos e compensamos todas as causas do racismo algorítmico. Mas este é um bom começo.

Sem armadilhas


Observe que, com a mudança para o ConceptNet Numberbatch, a precisão da previsão de tonalidade melhorou.

Alguém pode ter sugerido que a correção do racismo algorítmico pioraria os resultados de alguma outra maneira. Mas não. Você pode ter dados melhores e menos racistas.Os dados estão realmente melhorando com essa correção. O racismo word2vec e GloVe adquirido de pessoas não tem nada a ver com a precisão do algoritmo.

Outras abordagens


Obviamente, essa é apenas uma maneira de analisar a tonalidade. Alguns detalhes podem ser implementados de maneira diferente.

Em vez disso, ou além de alterar a base do vetor, você pode tentar corrigir esse problema diretamente na saída. Por exemplo, geralmente elimine a avaliação da tonalidade para nomes e grupos de pessoas.

Em geral, existe uma opção para recusar calcular a tonalidade de todas as palavras e calculá-la apenas para palavras da lista. Esta é talvez a forma mais comum de análise de sentimentos - sem aprendizado de máquina. Os resultados não terão mais viés do que o autor da lista. Mas recusar o aprendizado de máquina significa reduzir o recall (recall), e a única maneira de adaptar o modelo a um conjunto de dados é editar manualmente a lista.

Como uma abordagem híbrida, você pode criar um grande número de estimativas de tonalidade estimadas para palavras e instruir uma pessoa a editá-las pacientemente, fazer uma lista de palavras de exceção com tonalidade zero. Mas este é um trabalho extra. Por outro lado, você realmente verá como o modelo funciona. Eu acho que, em qualquer caso, isso deve ser buscado.

Source: https://habr.com/ru/post/pt436506/


All Articles