利用主题建模挖掘在线评论的NLP方法(附Python代码)

star2017 1年前 ⋅ 3640 阅读

电子商务彻底改变了我们的购物方式。你攒了几个月的钱买电话?这可能只是一次搜索和一些点击然后退出,项目就能在几天(有时甚至是第二天!)内完成交付。

对于在线零售商来说,没有与库存管理或空间管理相关的约束。他们可以根据自己的需要销售许多不同的产品。实体店只能保留有限数量的产品,因为它们的空间有限。

我记得以前我在当地书店订书的时候,这本书花了一个星期的时间才到。这好像是一个古老的故事!

但是网上购物也有自己的注意事项。最大的挑战之一是验证产品的真实性。它和电子商务网站上的广告一样好吗?这个产品会持续一年以上吗?其他客户的评论是真的还是虚假广告?这些都是顾客在挥霍钱财之前需要问的重要问题。

这是一个伟大的实验和应用自然语言处理(NLP)技术的地方。这篇文章将帮助您理解利用主题建模处理在线产品评论的意义。

请参阅下面的文章,以备快速主题建模:

基于LSA的主题建模介绍

Python主题建模初学者指南

目录

  1. 在线评论的重要性
  2. 问题陈述
  3. 为什么要进行主题建模?
  4. Python实现
  • 阅读数据
  • 数据预处理
  • 建立LDA模型
  • 主题可视化

5.其他利用在线评论的方法

6.下一步是什么?

1.在线评论的重要性

前几天,我用了电子商务,并在网上购买了智能手机。这款手机很好地在我的预算内,它有5以上的4.5以上的体面评级。

不幸的是,这是一个坏的决定,因为电池备份远远低于标准杆。我没有浏览对产品的评论就匆忙做出决定,仅仅根据它的评分就买下它。我知道我不是唯一一个犯了这个错误的人!

单凭评分并没有给出我们想要购买的产品的完整画像,正如我发现的那样。所以,作为一种预防措施,我总是建议人们在决定是否购买产品之前先阅读产品的评论。

但随后出现了一个有趣的问题。如果评论数量是成百上千还是怎么办?不可能去阅读所有的评论吧?这就是自然语言处理的优势所在。

2.设置问题陈述

问题陈述是你的分析问题的基础。因此,有一个坚实、清晰、明确的问题陈述是非常重要的。

如何使用自然语言处理(NLP)来分析大量的在线评论?让我们来定义这个问题。

在线产品评论是消费者的重要信息来源。从卖家的角度来看,在线评论可以用来衡量消费者对他们所销售的产品或服务的反馈。然而,由于这些在线评论在数量和信息方面常常是压倒一切的,因此能够从这些评论中找到关键见解(主题)的智能系统将对消费者和卖方都有很大的帮助。这个系统有两个目的:

  1. 使消费者能够快速地提取评论所涵盖的关键主题而不必去浏览它们。
  2. 帮助卖家/零售商以主题的形式获得消费者反馈(从消费者评论中提取)

为了解决这个任务,我们将在亚马逊汽车评论数据使用主题建模(LDA)。你可以从这个链接下载它。类似的可用于其他类别的产品数据集在这里可以找到。

3.0 为什么要使用主题建模来完成这个任务?

顾名思义,主题建模是一个自动识别文本对象中存在的主题并导出文本语料库所显示的隐藏模式的过程。主题模型对于多种用途非常有用,包括:

  1. 文档聚类
  2. 组织大文本数据块
  3. 非结构化文本的信息检索
  4. 特征选择

当训练一些关于股票市场的文本时,一个好的主题模型应该产生诸如“出价”、“交易”、“股息”、“交易所”之类的主题。

在我们的例子中,我们没有文本文档,而是有“汽车”类别下列出的项目的数千个在线产品评论。我们的目的是从评论中抽取一定数量的重要单词组。这些词组基本上是主题,有助于确定消费者在评论中实际在谈论什么。

4. Python的实现

在这一节中,我们将使用Jupyter Note(或任何其他用于Python的IDE)。这里,我们将使用Latent Dirichlet Allocation(LDA)的概念研究上面定义的问题陈述,以从在线评论数据集中提取有用的主题。

注:正如我在引言中提到的,我强烈建议要通过本这篇文章了解LDA以及它是如何工作的。

让我们先加载所有必要的库。

import nltk
from nltk import FreqDist
nltk.download('stopwords') # run this one time


import pandas as pd
pd.set_option("display.max_colwidth", 200)
import numpy as np
import re
import spacy

import gensim
from gensim import corpora

# libraries for visualization
import pyLDAvis
import pyLDAvis.gensim
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

要导入数据,首先将数据提取到工作目录,然后使用pandas的 read_json() 函数将其读取到pandas数据帧中。

df = pd.read_json('Automotive_5.json', lines=True)
df.head()

如您所见,数据包含以下列:

  1. ReviewerID——评论者ID
  2. asin——产品ID
  3. ReviewerName——评论者名字
  4. helpful——评论是否有帮助,比如2/3
  5. reviewText——评论内容
  6. overall——产品评分
  7. summary——评论摘要
  8. UnixReviewtime——审查时间(unix time)
  9. review——评论时间(原始)

本文我们的分析范围是评论内容,即reviewText。

4.1 数据预处理

数据预处理和数据清洗是任何文本挖掘任务之前的重要步骤,在这个步骤中,我们将删除标点符号、停顿词并尽可能地规范评论。在每个预处理步骤之后,检查数据中最频繁的单词是一个很好的做法。因此,让我们定义一个函数,它将绘制数据中n个最常用词的条形图。

# function to plot most frequent terms
def freq_words(x, terms = 30):
  all_words = ' '.join([text for text in x])
  all_words = all_words.split()

  fdist = FreqDist(all_words)
  words_df = pd.DataFrame({'word':list(fdist.keys()), 'count':list(fdist.values())})

  # selecting top 20 most frequent words
  d = words_df.nlargest(columns="count", n = terms) 
  plt.figure(figsize=(20,5))
  ax = sns.barplot(data=d, x= "word", y = "count")
  ax.set(ylabel = 'Count')
  plt.show()

让我们试试这个函数,找出哪些是评论数据集中最常见的单词。

freq_words(df['reviewText'])

最常见的词是“the”、“and”、“to”等等。这些单词对我们的任务来说并不重要,也说明不了什么。我们必须去掉这些词。在此之前,我们需要从文本数据中删除标点符号和数字。

# remove unwanted characters, numbers and symbols
df['reviewText'] = df['reviewText'].str.replace("[^a-zA-Z#]", " ")

让我们把评论中的停用词和短词(<2个字母)去掉。

from nltk.corpus import stopwords
stop_words = stopwords.words('english')


# function to remove stopwords
def remove_stopwords(rev):
    rev_new = " ".join([i for i in rev if i not in stop_words])
    return rev_new

# remove short words (length < 3)
df['reviewText'] = df['reviewText'].apply(lambda x: ' '.join([w for w in x.split() if len(w)>2]))

# remove stopwords from the text
reviews = [remove_stopwords(r.split()) for r in df['reviewText']]

# make entire text lowercase
reviews = [r.lower() for r in reviews]

让我们再找出最常用的单词,看看是否有更重要的单词出现。

freq_words(reviews, 35)

我们可以看到一些改进。诸如“battery”、“price”、“product”、“oil”之类的术语已经出现,它们与汽车类别非常相关。然而,我们仍然有中立的术语,比如‘the’,‘this’,‘much’,‘they’,它们并不相关。

为了进一步消除文本中的噪声,我们可以从SpaCy库中使用词元化(lemmatization)。它能有效地减少任何给定单词的歧义,它减少任何给定的单词到它的基本形式,从而减少单词到一个单词的多种形式

!python -m spacy download en # one time run


nlp = spacy.load('en', disable=['parser', 'ner'])

def lemmatization(texts, tags=['NOUN', 'ADJ']): # filter noun and adjective
       output = []
       for sent in texts:
             doc = nlp(" ".join(sent)) 
             output.append([token.lemma_ for token in doc if token.pos_ in tags])
       return output

让我们把评论托词化,然后把标记化的评论归纳起来。

tokenized_reviews = pd.Series(reviews).apply(lambda x: x.split())
print(tokenized_reviews[1])


['these', 'long', 'cables', 'work', 'fine', 'truck', 'quality', 'seems', 'little', 'shabby', 
'side', 'for', 'money', 'expecting', 'dollar', 'snap', 'jumper', 'cables', 'seem', 'like', 
'would', 'see', 'chinese', 'knock', 'shop', 'like', 'harbor', 'freight', 'bucks']


reviews_2 = lemmatization(tokenized_reviews)
print(reviews_2[1]) # print lemmatized review


['long', 'cable', 'fine', 'truck', 'quality', 'little', 'shabby', 'side', 'money', 'dollar', 
'jumper', 'cable', 'chinese', 'shop', 'harbor', 'freight', 'buck']

正如你所看到的,我们不仅对单词进行了修饰,而且只过滤了名词和形容词。让我们把最简化的评论和最常见的单词勾画出来。

reviews_3 = []
for i in range(len(reviews_2)):
    reviews_3.append(' '.join(reviews_2[i]))

df['reviews'] = reviews_3

freq_words(df['reviews'], 35)

现在看来,我们数据中最常见的术语是相关的。现在我们可以开始建立我们的话题模型了。

4.2 建立LDA模型

首先我们将创建我们的语料库的术语词典,其中每个唯一的术语被分配索引。

dictionary = corpora.Dictionary(reviews_2)

然后,我们将使用以上编写的词典将评论列表(reviews_2)转换成文档术语矩阵。

doc_term_matrix = [dictionary.doc2bow(rev) for rev in reviews_2]


# Creating the object for LDA model using gensim library
LDA = gensim.models.ldamodel.LdaModel

# Build LDA model
lda_model = LDA(corpus=doc_term_matrix, id2word=dictionary, num_topics=7, random_state=100,
                chunksize=1000, passes=50)

上面的代码需要一段时间。请注意,我已经使用 num_topic 参数为这个模型指定了7个主题的数量。可以使用相同的参数指定任意数量的主题。

打印出我们的LDA模型所学到的主题。

lda_model.print_topics()


[(0, '0.030*"car" + 0.026*"oil" + 0.020*"filter" + 0.018*"engine" + 0.016*"device" + 0.013*"code" 
+ 0.012*"vehicle" + 0.011*"app" + 0.011*"change" + 0.008*"bosch"'), 
(1, '0.017*"easy" + 0.014*"install" + 0.014*"door" + 0.013*"tape" + 0.013*"jeep" + 0.011*"front" + 
0.011*"mat" + 0.010*"side" + 0.010*"headlight" + 0.008*"fit"'), 
(2, '0.054*"blade" + 0.045*"wiper" + 0.019*"windshield" + 0.014*"rain" + 0.012*"snow" + 
0.012*"good" + 0.011*"year" + 0.011*"old" + 0.011*"car" + 0.009*"time"'), 
(3, '0.044*"car" + 0.024*"towel" + 0.020*"product" + 0.018*"clean" + 0.017*"good" + 0.016*"wax" + 
0.014*"water" + 0.013*"use" + 0.011*"time" + 0.011*"wash"'), 
(4, '0.051*"light" + 0.039*"battery" + 0.021*"bulb" + 0.019*"power" + 0.018*"car" + 0.014*"bright" 
+ 0.013*"unit" + 0.011*"charger" + 0.010*"phone" + 0.010*"charge"'), 
(5, '0.022*"tire" + 0.015*"hose" + 0.013*"use" + 0.012*"good" + 0.010*"easy" + 0.010*"pressure" + 
0.009*"small" + 0.009*"trailer" + 0.008*"nice" + 0.008*"water"'), 
(6, '0.048*"product" + 0.038*"good" + 0.027*"price" + 0.020*"great" + 0.020*"leather" + 
0.019*"quality" + 0.010*"work" + 0.010*"review" + 0.009*"amazon" + 0.009*"worth"')]

第四部分的主题3有“towel”、“clean”、“wax”、“water”等术语,表明话题与洗车非常相关。类似地,主题6似乎与产品的总体价值有关,因为它有诸如“price”、“quaity”和“worth”之类的术语。

4.3 主题可视化

为了在二维空间中可视化我们的主题,我们将使用 pyLDAvis 库。这种可视化在本质上是交互的,并且显示和主题最相关的词。

# Visualize the topics
pyLDAvis.enable_notebook()
vis = pyLDAvis.gensim.prepare(lda_model, doc_term_matrix, dictionary)
vis

5.其他利用在线评论的方法

除了主题建模之外,还有许多其他的NLP方法用于分析和理解在线评论。比如:

  1. 文本摘要:将评论归纳为一个段落或几个要点。
  2. 实体识别:从评论中提取实体,并确定哪些产品在消费者中最流行(或不受欢迎)。
  3. 识别新趋势:基于评论的时间戳,可以识别新的和新出现的主题或实体。这将使我们能够弄清楚哪些产品正变得流行,哪些市场失去了控制力。
  4. 情感分析:对于零售商来说,理解评论的情绪有助于改善他们的产品和服务。

6.下一步是什么?

信息检索把我们从一个接一个的产品评论中解放出来。它让我们对其他消费者谈论的产品有一个公平的概念。

然而,它并没有告诉我们评论是积极的、中立的还是消极的。这成为了信息检索问题的一个扩展,在这里我们不仅需要提取主题,而且还需要确定情感。这是一个有趣的任务,我们将在下一篇文章中介绍。

7.小结

主题建模是具有降维、文本摘要和推荐引擎等实际应用的最流行的NLP技术之一。本文的目的是演示LDA在原始的、人群生成的文本数据上的应用。我鼓励您在其他数据集上实现代码并共享您的发现。

如果您对主题建模有任何建议、疑问或任何其他希望分享的内容,那么请随意使用下面的评论部分。

这里有完整的代码


原文链接:An NLP Approach to Mining Online Reviews using Topic Modeling (with Python codes)

翻译:Vivian

更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: