从零实现爬虫和情感分类模型(二)

共 3465字,需浏览 7分钟

 ·

2021-01-28 22:30

大家好,我是Giant,这是我的第5篇文章。

上一篇文章中我们完成了python环境搭建和百万级评论爬虫,本文将利用爬取的数据练评论类模型。

开源代码:

https://github.com/yechens/RestaurantCrawler/blob/main/demo_01.ipynb

01 数据处理三剑客

pandas、numpy、matplotlib功能强大使用方便,被誉为python数据处理三剑客。

之前爬取的数据保留在mongodb中,可以用mogoexport或数据库可视化软件将其导出到csv文件。

数据清洗

简单起见,这里分别导出评分5星和1星的评论各6800条。后续处理中,每类情感取6000条用于模型训练和校验,剩余800条作为测试。

将导出的数据分别命名为10_star.csv、50_star.csv,借助pandas库导入。

接下来遍历评论列的每一行,过滤其中的非中文字符和长度小于10的无效评论。

得到训练数据后,我们手工创建一个labels数组存放标签,将其转换为numpy对象,便于后期输入到神经网络中。

import numpy as np
y_data = [0 for i in range(6000)] + [1 for i in range(6000)]
y_data = np.asarray(y_data, dtype=np.float32)
y_test_data = [0 for i in range(800)] + [1 for i in range(800)]
y_test_data = np.asarray(y_data, dtype=np.float32)

乱序处理

聪明的读者可能发现了一个问题:这份数据太有规律啦,正负情感刚好前后各占一半。假如前3000条评论机器全判断为负面,能证明准确率有100%吗?

为了避免数据分布不规律的现象,我们需要为数据“洗牌”。

X_train, y_train = [], []
nums = np.arange(12000)
# 随机打乱12000个训练数据
np.random.shuffle(nums)
for i in nums:
    X_train.append(X_data[i])
    y_train.append(y_data[i])

简单的数据预处理完成后,还有一个问题。

这儿的数据全都是中文,即便是英文字母,计算机也一概不认识。所以需要一个额外的“翻译”步骤。

02 快速获得中文词向量

在自然语言处理任务中,需要考虑词如何在计算机中表示。常见的表示方法有两种:

  • one-hot representation (独热编码)
  • distribution representation

第一种是离散表示方法,得到高维度的稀疏矩阵;第二种方法是将词表示成固定长度的密集型向量,即词向量

从头训练一个有效的语言模型耗时又耗能。本例中,我们借助腾讯AI实验室发布的bert-as-service接口,通过两行代码,即可使用预训练的Bert模型生成句向量和词向量。

这两行代码怎么用呢?

from bert_serving.client import BertClient
bc = BertClient
# 将待训练的中文数据转换为(,768)维的句向量
input_train = bc.encode(X_train)

bert-as-service服务将一个句子统一转换成768维的句向量,最终我们得到了[12000 * 768]维度的特征矩阵,也就是神经网络的真正输入。

03 情感分类模型实现

有了输入特征,模型训练部分就比较简单了,尤其是有Keras这样的工具。

Keras是一个高层神经网络API,纯python编写并使用Tensorflow等框架作为后端,特点是简洁、快速。

直接使用pip或conda指令即可安装Keras和Tensorflow。

# 使用国内镜像加速安装
$ pip install keras -i https://pypi.douban.com/simple
$ pip install tensorflow -i https://pypi.douban.com/simple

使用Keras实现一个神经网络模型大致分四步:

  • 定义训练数据:输入张量和目标张量
  • 逐层定义网络,将输入映射到目标
  • 配置学习过程:选择损失函数、优化器和监控指标
  • 调用模型的 fit 方法在训练数据上多次迭代

我们直接使用使用Sequential类来定义模型(仅用于层的线性堆叠,是最常见的网络架构)。

from keras.models import Sequential
from keras.layers import Dense, Dropout
import tensorflow as tf
model = Sequential()
# 搭建模型
model.add(Dense(32, activation='relu', input_shape=(768,)))
model.add(Dropout(0.3))
model.add(Dense(32, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

对于简单的二分类问题,使用Dense全连接层已经足够,最后的输出是0~1之间的小数,代表了正面/负面情感的概率。为了防止过拟合,在模型中加入了Dropout层,

接下来,我们指定模型使用的优化器和损失函数,以及训练过程中想要监控的指标。

model.compile(
    loss='binary_crossentropy',
    optimizer=tf.train.AdamOptimizer(),
    metrics=['acc']
)

最后,通过fit方法将输入数据传入模型。我们留出20%的数据作为验证集:

history = model.fit(
    X_train, y_train,
    epochs=30,
    batch_size=128,
    validation_split=0.2,
    verbose=1
)

模型开始迭代训练了!

观察发现,随着迭代次数的增加,模型损失逐渐下降,准确度逐渐上升,直到趋于稳定。

运行结束后,使用matplotlib库将结果可视化呈现。

因为任务比较简单,加上Bert的特征抽取能力,模型对于判别好评还是差评有96%的准确率!

另外还有1600条数据当作测试集没有使用,调用evaluate方法测试:

test_loss = model.evaluate(
    X_test,
    y_test,
    batch_size=64,
    verbose=1
)
print(test_loss)

得到结果:[0.079560, 0.973125],表示测试集损失和准确率分别为0.0797%

04 小结

本文是NLP情感分类任务的入门和实现,可以让读者利用简单的数据和工具实现一个分类模型。整个过程涉及了数据处理、特征编码、模型训练和结果分析。

实际开发中,使用的模型和特征抽取方法会更加复杂,涉及更严格的测试和部署环节。今后的文章中我们将为读者继续呈现!

推  荐  阅  读

参考资料

[1] bert-as-service: https://github.com/hanxiao/bert-as-service
[2] 两行代码玩转Google BERT句向量: https://www.colabug.com/5332506.html




由于微信平台算法改版,订阅号内容将不再以时间排序展示,如果大家想第一时间看到我们的推送,强烈建议星标我们帮我们点【在看】。星标具体步骤:

(1)点击页面最上方“NLP情报局”,进入主页

(2)点击右上角的小点点,在弹出页面点击“设为星标”,就可以啦

感谢支持❤️


原创不易,有收获的话请帮忙点击分享、点赞在看🙏

浏览 31
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报