Revisão Previsão de classificação: uma abordagem combinada

Combinando o RTC (Revisão de Conteúdo de Texto) e a Matriz de Similaridade do Usuário para obter mais informações e melhorar a previsão de classificação de revisão (RRP)

Yereya Berdugo Blocked Desbloquear Seguir Seguindo 2 de janeiro Fonte: pixabay

Abertura

O aumento do comércio eletrônico trouxe um aumento significativo na importância das revisões de clientes. Existem centenas de sites de resenhas on-line e grandes quantidades de resenhas para cada produto. Os clientes mudaram sua maneira de fazer compras e, de acordo com uma pesquisa recente, 70% dos clientes dizem usar filtros de classificação para filtrar itens com baixa classificação em suas pesquisas.

A capacidade de decidir com sucesso se uma revisão será útil para outros clientes e, assim, dar ao produto mais exposição é vital para as empresas que suportam essas revisões, empresas como Google, Amazon e Yelp !.

Existem dois métodos principais para abordar esse problema. O primeiro é baseado na análise de conteúdo de texto de revisão e usa os princípios do processo de linguagem natural (o método NLP). Este método não possui os insights que podem ser extraídos do relacionamento entre clientes e itens. O segundo é baseado em sistemas de recomendação, especificamente na filtragem colaborativa, e se concentra no ponto de vista do revisor. O uso da matriz de similaridade do usuário e a aplicação da análise de vizinhos fazem parte desse método. Esse método ignora qualquer informação da análise de conteúdo de texto de revisão.

Em um esforço para obter mais informações e melhorar a previsão do índice de revisão, os pesquisadores neste artigo propuseram uma estrutura combinando o conteúdo do texto de revisão com a análise de matriz de similaridade do usuário anterior. Eles então fizeram alguns experimentos em dois conjuntos de dados de revisão de filmes para examinar a eficiência de suas hipóteses. Os resultados que obtiveram mostraram que sua estrutura realmente melhorou a previsão do rating de revisão. Este artigo descreverá minha tentativa de seguir o trabalho feito em sua pesquisa através de exemplos do conjunto de dados de revisões da Amazon. O caderno que documenta este trabalho está disponível aqui e encorajo a execução do código no seu computador e a comunicação dos resultados.

Os dados

O conjunto de dados usado aqui foi disponibilizado pelo Dr. Julian McAuley da UCSD. Ele contém análises e metadados de produtos da Amazon, incluindo 142,8 milhões de avaliações abrangendo maio de 1996 a julho de 2014. O conjunto de dados de avaliações de produtos contém ID do usuário, ID do produto, classificação, votos de ajuda e texto de revisão para cada revisão.
Os dados podem ser encontrados aqui

A hipótese

Neste trabalho meu objetivo foi verificar a tese dos pesquisadores. Não foi para encontrar o melhor modelo para o problema. Tentarei provar que a combinação de dados anteriormente conhecidos sobre a similaridade de cada usuário com outros usuários, com a análise de sentimento do próprio texto de revisão, nos ajudará a melhorar a previsão do modelo de qual avaliação o usuário receberá.

Fonte: pixabay

O fluxo de trabalho

Como primeiro passo, realizarei o RRP com base na análise RTC. O próximo passo será aplicar uma análise de vizinhos para executar o RRP com base na similaridade entre os usuários. O passo final será comparar os três métodos (RRP baseado no RTC, RRP baseado na análise de vizinhos e a combinação dos dois) e verificar a hipótese.

Pré-processando

O pré-processamento é um passo fundamental em qualquer análise e neste projeto também.
A cabeça da tabela principal é a seguinte:

A cabeça da mesa principal

Primeiro, excluí linhas sem texto de revisão, linhas duplicadas e colunas extras que não serão usadas.
O segundo passo foi criar uma coluna que contém os resultados da divisão do numerador útil e do denominador útil e depois segmentar esses valores em compartimentos. Ficou assim:

 reviews_df = reviews_df [~ pd.isnull (reviews_df ['reviewText'])] 
reviews_df.drop_duplicates (subset = ['reviewerID', 'asin', 'unixReviewTime'], inplace = True )
reviews_df.drop ('Sem nome: 0', eixo = 1, inplace = Verdadeiro )
reviews_df.reset_index (inplace = True )

reviews_df ['helpful_numerator'] = comentários_df ['útil']. apply ( lambda x: eval (x) [0])
reviews_df ['helpful_denominator'] = comentários_df ['útil']. apply ( lambda x: eval (x) [1])
reviews_df ['helpful%'] = np.where (reviews_df ['helpful_denominator']> 0,
reviews_df ['helpful_numerator'] / reviews_df ['helpful_denominator'], -1)

reviews_df ['helpfulness_range'] = pd.cut (x = reviews_df ['help%'], bins = [- 1, 0, 0,2, 0,4, 0,6, 0,8, 1,0],
labels = ['empty', '1', '2', '3', '4', '5'], include_lowest = True )

O último passo foi criar um processador de texto que extraísse as palavras significativas do texto de revisão confuso.

 def text_process (reviewText): 
nopunc = [i for i in reviewText se não estiver em string.punctuation]
nopunc = nopunc.lower ()
nopunc_text = '' .join (nopunc)
return [i para i em nopunc_text.split () se eu não estiver em stopwords.words ('english')]

Depois de ser aplicado isso teve –
1. Pontuação removida
2. Convertido para minúsculas
3. Palavras Paradas Removidas (palavras não relevantes no contexto do treinamento do modelo)

Uma olhada nos dados

O chefe da tabela principal, depois de todo o pré-processamento, é assim:

As figuras abaixo mostram como a faixa de utilidade dos usuários é distribuída sobre a classificação do produto:

HeatmapBarplot

Pode-se ver facilmente a tendência para as classificações mais altas. Esse fenômeno é bem conhecido e também é apoiado na mesma pesquisa acima. Segundo essa pesquisa:

“As críticas estão cada vez mais mudando de um lugar onde os consumidores expõem suas queixas a um lugar para recomendar itens depois de uma experiência positiva”.

Mais adiante, explicarei como o problema dos dados distorcidos foi resolvido (métodos de reamostragem).

Etapa 1: RRP com base no conteúdo de texto de revisão

Os modelos

Para verificar e escolher o melhor modelo, construí um pipeline que seguiu as etapas a seguir. O pipeline primeiro executará a ponderação e a vetorização do termo TF-IDF e, então, executará o algoritmo de classificação. Em geral, o TF-IDF processará o texto usando minha função “text_process” de cima e, em seguida, converterá o texto processado em um vetor de contagem. Em seguida, será aplicado um cálculo que atribuirá maior peso às palavras de maior importância.

 Pipeline = Pipeline ([ 
('Tf-Idf', TfidfVectorizer (ngram_range = (1,2), analisador = text_process)),
('classificador', MultinomialNB ())
])
X = reviews_df ['reviewText']
y = reviews_df ['helpfulness_range']
review_train, review_test, label_train, label_test = train_test_split (X, y, test_size = 0,5)
pipeline.fit (review_train, label_train)
pip_pred = pipeline.predict (review_test)
print (metrics.classification_report (label_test, pip_pred))

Note que eu escolhi ngram_range = (1, 2) e que o algoritmo era Multinomial Naïve Bayes. Essas decisões foram tomadas de acordo com os resultados de um teste de validação cruzada. O teste de validação cruzada que fiz está além do escopo deste artigo, mas você pode encontrá-lo no bloco de anotações.
Os modelos verificados foram:
1. Regressão logística multinomial, como referência
2. Bayes Naïves Multinomiais
3. Árvore de Decisão
4. Floresta aleatória

Naïve Bayes multinomial deu a melhor pontuação de precisão¹ (0,61) e, portanto, as previsões feitas por ele foram escolhidas para representar o RRP com base no RTC.

A parte final desta etapa é exportar as previsões feitas pelo modelo escolhido para um arquivo csv:

 rev_test_pred_NB_df = pd.DataFrame (data = {'review_test': review_test2, 'predição': pip_pred2}) 
rev_test_pred_NB_df.to_csv ('rev_test_pred_NB_df.csv')

Etapa 2: RRP baseado na semelhança do usuário

Pré-processando

Nesta etapa, a matriz de similaridade do usuário é construída e é a base sobre a qual calcularei a similaridade de cosseno entre cada usuário. Alguns problemas ocorreram quando construí a matriz usando os nomes dos itens, mas foram resolvidos convertendo-os em uma sequência de inteiros única (igual à propriedade IDENTITY no SQL).

 temp_df = pd.DataFrame (np.unique (Reviewer_rating_df ['reviewerID']), columns = ['unique_ID']) 
temp_df ['unique_asin'] = pd.Series (np.unique (revisores_rating_df ['asin']))
temp_df ['unique_ID_int'] = intervalo (20000, 35998)
temp_df ['unique_asin_int'] = intervalo (1, 15999)
 reviewers_rating_df = pd.merge (Reviewer_rating_df, temp_df.drop (['unique_asin', 'unique_asin_int'], axis = 1), left_on = 'reviewerID', right_on = 'unique_ID') 
 reviewers_rating_df = pd.merge (Reviewer_rating_df, temp_df.drop (['unique_ID', 'unique_ID_int'], axis = 1), left_on = 'asin', right_on = 'unique_asin') 
 reviewers_rating_df ['overall_rating'] = Reviewer_rating_df ['overall'] 
id_asin_helpfulness_df = Reviewer_rating_df [['reviewerID', 'unique_ID_int', 'helpfulness_range']]. copy ()
 # Exclua as colunas que não estão em uso: 
reviewers_rating_df.drop (['asin', 'unique_asin', 'reviewerID', 'unique_ID', 'global', 'helpfulness_range'], axis = 1, inplace = True)

Construir a matriz: usei pivot para trazer os dados para a forma adequada e, em seguida, “csr_matrix” para convertê-los em matriz esparsa para economizar tempo de processamento.

 matrix = reviewers_rating_df.pivot (index = 'unique_ID_int', colunas = 'unique_asin_int', values = 'overall_rating') 
matriz = matrix.fillna (0)
user_item_matrix = sparse.csr_matrix (matrix.values)

Modelo KNN

Eu usei o algoritmo K-Nearest Neighbors para produzir a análise de vizinhos. O modelo KNN é fácil de implementar e interpretar. A medida de similaridade foi similaridade de cosseno e o número de vizinhos desejados foi dez.

Vizinhos

 model_knn = neighbors.NearestNeighbors (metric = 'cosine', algoritmo = 'brute', n_neighbors = 10) 
model_knn.fit (user_item_matrix)

Após o estágio de treinamento, extraí a lista dos vizinhos e a armazenei como uma matriz NumPy. Isso gerou uma matriz de usuários de 2-d e os dez usuários que são mais semelhantes a eles.

 vizinhos = np.asarray (model_knn.kneighbors (user_item_matrix, return_distance = False)) 

O próximo passo foi pegar os dez vizinhos mais próximos e armazená-los em um dataframe:

 unique_id = [] 
k_neigh = []
para eu na faixa (15998):
unique_id.append (i + 20000)
k_neigh.append (list (vizinhos [i] [1:10])) #Grabbing os dez vizinhos mais próximos
 neighbours_df = pd.DataFrame (data = {'unique_ID_int': unique_id, 
'k_neigh': k_neigh})
 id_asin_helpfulness_df = pd.merge (id_asin_helpfulness_df, neighbors_df, on = 'unique_ID_int') 
id_asin_helpfulness_df ['neigh_based_helpf'] = id_asin_helpfulness_df ['unique_ID_int']

Finalmente, para calcular a pontuação média das avaliações que os dez revisores mais próximos escreveram, codifiquei um loop aninhado que percorreria cada linha. O loop, então, percorrerá todos os dez vizinhos do usuário e calculará a pontuação média obtida por suas resenhas.

 para índice, linha em id_asin_helpfulness_df.iterrows (): 
linha = linha ['k_neigh']
lista = []
para eu na fila:
p = id_asin_helpfulness_df.loc [i] ['helpfulness_range']
lista.append (p)
id_asin_helpfulness_df.loc [index, 'neigh_based_helpf'] = np.nanmean (lista)

Terceiro passo: combinação

Combinação

Como terceiro passo, exportei os resultados do cálculo acima e os combinei com as previsões do modelo escolhido. Eu então tive um arquivo que consistia em quatro colunas:
1) Os comentários originais
2) As pontuações que eles obtiveram (a verdade fundamental)
3) As previsões do primeiro passo (abordagem PNL)
4) As previsões do segundo passo (abordagem de similaridade dos usuários)
A combinação dos dois métodos pode ser feita de várias maneiras diferentes. Neste artigo, escolhi a média aritmética simples, mas outros métodos também funcionariam.
Além das quatro colunas acima, agora tenho uma quinta coluna:
5) A média aritmética de cada linha nas colunas 3) e 4)

Etapa final: relatórios

A métrica usada para comparar os modelos foi o Root Mean Squared Error (RMSE). É uma medida muito comum e boa para comparar modelos. Além disso, escolhi apresentar o Erro Absoluto Médio (MAE) porque ele usa a mesma escala que os dados sendo medidos e, portanto, podem ser facilmente explicados. Os resultados² são mostrados abaixo:

 RMSE para neigh_based_helpf: 1.0338002581383618 
RMSE para previsão de NB: 1.074619472976386
RMSE para a combinação dos dois métodos: 0,9920521481819871
MAE para a predição combinada: 0.6618020568763793

O RMSE para o método combinado foi menor que o RMSE de cada método sozinho.

Conclusão

Em conclusão, minha tese foi comprovada como correta. Combinar os dados anteriormente conhecidos sobre a similaridade de cada usuário com outros usuários com a análise de sentimento do próprio texto de revisão ajuda a melhorar a previsão do modelo de qual taxa a revisão do usuário obterá

¹ O objetivo deste artigo é comparar os métodos e verificar se a estrutura oferecida pelos pesquisadores melhorará a precisão das previsões. Não foi para encontrar o modelo mais preciso para o RRP baseado no RTC.

² Embora o MAE de 0,66 não seja bom, o objetivo principal deste trabalho foi verificar a hipótese e não necessariamente buscar o melhor modelo de PRR.