Vetores de palavra de sobrecarga

Uma técnica simples para impulsionar o fastText e outros vetores de palavras em seus projetos de PNL

Josh Taylor Blocked Unblock Seguir Seguindo 31 de dezembro

Nos últimos anos, os vetores de palavras foram transformadores em sua capacidade de criar vínculos semânticos entre as palavras. Agora é a norma para estes serem introduzidos em modelos de aprendizagem profunda para tarefas como classificação ou análise de sentimentos.

Apesar disso, sempre fiquei impressionado com o simples poder da análise baseada em frequência de termos. Freqüência de Prazo A Frequência de Documento Inversa (TF-IDF) pode ser facilmente explicada para públicos não técnicos e os resultados são fáceis de interpretar.

Este artigo explora como a combinação do TF-IDF com vetores de palavras pode fornecer saídas que são facilmente interpretáveis e também podem capturar as sutis relações semânticas existentes na linguagem.

Enquanto a internet está repleta de exemplos de análise de 'sondagens de palavras' usando TF-IDF ( veja aqui ) e abordagens de vetores de palavras ( veja aqui ), estas são quase sempre vistas como técnicas mutuamente exclusivas. Este artigo explora como a combinação do TF-IDF com vetores de palavras pode fornecer saídas que são facilmente interpretáveis e também podem capturar as sutis relações semânticas existentes na linguagem. Usando o método fastText para criar vetores de palavras, também seremos capazes de criar um modelo que possa lidar com palavras fora do vocabulário, além de ser robusto para erros ortográficos e erros de digitação.

vetores de palavras de fastText

Este artigo pressupõe conhecimento prévio de vetores de palavras, mas vale a pena tocar em fastText e como isso difere da abordagem word2vec mais amplamente conhecida para criar representações vetoriais de palavras. A FastText foi desenvolvida pelo Facebook com um lançamento estável sendo aberto em 2017.

A diferença mais notável entre o fastText e o word2vec é que o fastText divide palavras usando caracteres n-gram. Por exemplo, 'Lincolnshire', (um condado no Reino Unido) seria dividido em:

 Lin, inc, nco, col, né, lns, nsh, shi, hir, ire 

Onde n = 3. Essa abordagem é uma melhoria significativa em relação ao word2vec por dois motivos:

  1. A capacidade de inferir palavras fora do vocabulário. Por exemplo, o modelo acima entenderia que 'Lancashire' (também um condado no Reino Unido) é relacionado a Lincolnshire devido à sobreposição de 'shire' (ou 'shi', 'hir' e 'ira') entre os dois palavras.
  2. A robustez para erros ortográficos e erros de digitação. É fácil ver que a mesma modelagem de nível de caractere também significa que o fastText é robusto o suficiente para lidar com variações de ortografia. Isso é particularmente útil na análise de conteúdo de mídia social.

Uma revisão detalhada de como o fastText funciona pode ser visualizada aqui .

Mostre-me o código!

O restante deste artigo aborda um exemplo simples que treinará um modelo de texto rápido em uma série de documentos, aplicará o TF-IDF a esses vetores e usará isso para realizar análises adicionais.

Os documentos em questão são declarações de Escravidão Moderna apresentadas por empresas para explicar os passos que estão tomando para erradicar a Escravidão Moderna, tanto internamente quanto dentro de suas cadeias de suprimentos. O artigo abaixo mostra como esses dados foram limpos antes da análise:

Limpe seus dados com aprendizado de máquina não supervisionado
A limpeza de dados não precisa ser dolorosa! Este post é um exemplo rápido de como usar o aprendizado de máquina sem supervisão para… em direção a

Se você gostaria de acompanhar, um notebook colab pode ser encontrado aqui contendo todo o código.

Etapa 1. tokenize o texto e crie frases

Nós usaremos spaCy para dividir cada um dos documentos em uma lista de palavras (tokenização). Também vamos limpar os dados removendo as palavras stop, pontuação e convertendo para minúsculas usando a biblioteca Gensim:

 #O dataframe é chamado 'combinado' tem uma coluna chamada 'texto' que contém os dados de texto de cada empresa 
 #cria uma lista de documentos com uma lista de palavras dentro: 
text = []
para i em combined.text.values:
doc = nlp (remove_stopwords (strip_punctuation (strip_non_alphanum (str (i). menor ()))))
tokens = [token.text para token no doc]
text.append (tokens)

Nós então uniremos termos comuns. Por exemplo, como cada um dos documentos escreve sobre a escravidão moderna, é útil combinar essas duas palavras em uma única frase 'modern_slavery'. A biblioteca Gensim facilita isso e o código está abaixo:

 common_terms = ["of", "with", "without", "and", "or", "the", "a"] 
# Crie as frases relevantes na lista de frases:
frases = Frases (texto, common_terms = common_terms, threshold = 10, min_count = 5)
# O objeto Phraser é usado de agora em diante para transformar sentenças
bigrama = Phraser (frases)
# Aplicar o Phraser para transformar nossas frases é simplesmente
tokens = lista (bigrama [texto])

Agora temos uma lista de documentos, cada um contendo uma lista de palavras. Frases comuns foram combinadas em palavras.

Etapa 2. Treinar o modelo fastText

Isso requer apenas uma única linha de código usando o modelo fastText da biblioteca Gensim. Você pode definir o tamanho do n-grama ('window'), bem como o tamanho da dimensão dos vetores ('size'). Aqui criamos vetores com 100 dimensões e usamos um tamanho n-grama de 3:

 model = FastText (tokens, tamanho = 100, janela = 3, min_count = 1, iter = 10, sorted_vocab = 1) 

Podemos verificar o modelo usando o seguinte:

 semelhanças = model.wv.most_similar (restrict_vocab = 10000, positivo = ['contrato']) 

Isso retorna:

 subcontrato 0.9493274688720703 
sub_contract 0.9349175095558167
contratual 0.9346154928207397
contratos 0.9312876462936401
contratante 0.9068889617919922

Apenas para mostrar como o FastText pode lidar com palavras fora do vocabulário, podemos tentar um contrato de erro de ortografia como ' contracct '. A partir do abaixo, podemos ver que o modelo não tem problema em interpretar essa palavra, mesmo que ela nunca tenha visto isso antes!

 contrato 0.9389102458953857 
contratos 0.9058693051338196
contrário 0.9027011394500732
empreiteiro 0,8995087742805481
0,885408341884613 contratual

Etapa 3. Aplique o TF-IDF aos vetores

Esta etapa primeiro cria informações do TF-IDF para cada documento usando o Scikit. Em seguida, aplica a ponderação a cada vetor de palavra em um documento e, em seguida, calcula a média entre eles no documento:

 # TF-IDF 
text = []
para i em tqdm (tokens):
string = '' .join (i)
text.append (string)
tf_idf_vect = TfidfVectorizer (stop_words = nenhum)
final_tf_idf = tf_idf_vect.fit_transform (text)
tfidf_feat = tf_idf_vect.get_feature_names ()
 #Aplicar as pontuações do TF-IDF aos vetores modelo 
 tfidf_sent_vectors = []; # o tfidf-w2v para cada frase / revisão é armazenado nesta lista 
linha = 0;
erros = 0
para enviado em tqdm (tokens): # para cada revisão / sentença
sent_vec = np.zeros (100) # como vetores de palavras são de comprimento zero
weight_sum = 0; # num de palavras com um vetor válido na frase / revisão
para a palavra enviada: # para cada palavra em uma revisão / sentença
experimentar:
vec = model.wv [palavra]
# obter o tf_idfidf de uma palavra em uma frase / revisão
tfidf = final_tf_idf [row, tfidf_feat.index (word)]
sent_vec + = (vec * tfidf)
weight_sum + = tfidf
exceto:
erros = + 1
passar
sent_vec / = weight_sum
#print (np.isnan (np.sum (sent_vec)))
 tfidf_sent_vectors.append (sent_vec) 
linha + = 1
print ('erros registrados:' + str (errors))

Agora temos nossos vetores de palavras TF-IDF supercharged para cada documento em nosso corpus! Hora de testá-lo…

Resultados

Agora que temos nossos vetores de fastText combinados com ponderações TF-IDF, é fácil detectar os resultados usando semelhança de cosseno. O código abaixo localiza uma empresa correspondente com base em uma string de consulta e, em seguida, produz uma lista das empresas mais semelhantes com base em seus retornos Modern Slavery.

 compName = 'Deloitte' 
 consulta = [combinado.loc [combinado.Empresa.str.contains (compName)]. iloc [0] ['FT_tfidf']] 
consulta = np.array (list (query))
consulta = np.nan_to_num (consulta)
 vectors = np.array (list (combinado.FT_tfidf.values)) 
vetores = np.nan_to_num (vetores)
 cosine_similarities = pd.Series (cosine_similarity (consulta, vetores) .flatten ()) 
 para i, j em cosine_similarities.nlargest (10) .iteritems (): 
print (str (i) + '-' + combinado.Empresa.iloc [i] + "" + str (j))

O exemplo aqui foi a Deloitte, uma empresa de serviços profissionais. Dos resultados abaixo podemos ver que os retornos mais similares são de empresas relacionadas (nomeadamente o próprio retorno da Deloitte para outro ano financeiro, bem como a DLA, uma parceria de direito e a Ernst & Young, outra das firmas de contabilidade 'Big 4'):

 Deloitte LLP 1.0000000000000002 
Deloitte LLP 0.949480726712043
DLA Piper International LLP 0.8635928917765654
Travers Smith LLP 0,8495683187822698
EBSCO International Inc. 0,8405915834557236
Vink UK 0.8356471225683573
Ernst & Young LLP 0,8345225966043321
IFS UK Ltd 0,8288755547154663
Primeiro Seguro Central 0.8279939308519769
TalkTalk Telecom Group PLC 0,8260778120395709

Espero que este post tenha demonstrado que combinar vetores de palavras com técnicas de TF-IDF pode produzir resultados poderosos que também são simples de explicar e interpretar. Os vetores de documentos produzidos neste passo a passo podem agora ser usados na classificação de texto, agrupamento, bem como em análises posteriores (por exemplo, descobrindo tendências em como os retornos da empresa mudaram ao longo do tempo ou entre setores).