文本多分类之Doc2Vec实战篇

2023-10-26

 

本文链接:https://blog.csdn.net/weixin_42608414/article/details/88391760

版权

在我之前的几篇博客中,我介绍了两种文档向量化的表示方法,如Sklearn的CountVectorizer和TfidfTransformer,今天我们再来学习另外一种文档的向量化表示方法-Doc2Vec。如果你还不太了解Doc2Vec的话,我提供一些资料以便你可以对它有深入的了解:

本文不会对Doc2Vec的原理进行深入的介绍,我们的目的在于“使用”和“实战”,如果想要深入了解Doc2Vec内部机制和原理可以参考我推荐的上述文档和教程。我们这次使的用数据来自于我上次的博客使用python和sklearn的中文文本多分类实战开发中使用的数据,不过这次我们不再使用CountVectorizer和TfidfTransformer,我们将使用Gensim的Doc2Vec技术对中文文本数据进行量化处理和文档多分类。好了,废话少说,让我们撸起袖子干起来吧!

数据

我们可以从这里下载数据,数据中包含了10 个类别(书籍、平板、手机、水果、洗发水、热水器、蒙牛、衣服、计算机、酒店),共 6 万多条评论数据 首先查看一下我们的数据,这些数据都是来自于电商网站的用户评价数据,我们最终的目的是把不同评价数据归类到不同的分类中去,且每条数据只能对应10个类中的一个类。

%matplotlib inline
import pandas as pd
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import jieba as jb
import re
from sklearn import utils
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from gensim.models.doc2vec import TaggedDocument
import multiprocessing

df = pd.read_csv('./data/shopping.csv')
df=df[['cat','review']]
print("数据总量: %d ." % len(df))
df.sample(10)

接下来我们还是要做一下数据清洗工作,删掉数据中的空值:

print("在 cat 列中总共有 %d 个空值." % df['cat'].isnull().sum())
print("在 review 列中总共有 %d 个空值." % df['review'].isnull().sum())
df[df.isnull().values==True]
df = df[pd.notnull(df['review'])]
df = df.reset_index(drop=True)

接下来我们统计一下各个类别的数据量:

d = {'cat':df['cat'].value_counts().index, 'count': df['cat'].value_counts()}
df_cat = pd.DataFrame(data=d).reset_index(drop=True)
print(df_cat)

df_cat.plot(x='cat', y='count', kind='bar', legend=False,  figsize=(8, 5))
plt.title("类目数量分布")
plt.ylabel('数量', fontsize=18)
plt.xlabel('类目', fontsize=18)

 

我们看到各个类别的数据量不一致,洗发水、衣服、酒店、水果、平板的数据量最多各有1万条,而热水器的数据量最少只有574条,分布很不均匀。接下来还是老规矩,我们要做数据预处理的工作。

数据预处理

我们要删除文本中的标点符号,特殊符号,还要删除一些无意义的常用词(stopword),因为这些词和符号对系统分析预测文本的内容没有任何帮助,反而会增加计算的复杂度和增加系统开销,所有在使用这些文本数据之前必须要将它们清理干净。首先我们要定义几个清洗文本的函数:

#定义删除除字母,数字,汉字以外的所有符号的函数
def remove_punctuation(line):
    line = str(line)
    if line.strip()=='':
        return ''
    rule = re.compile(u"[^a-zA-Z0-9\u4E00-\u9FA5]")
    line = rule.sub('',line)
    return line

#停用词列表
def stopwordslist(filepath):  
    stopwords = [line.strip() for line in open(filepath, 'r', encoding='utf-8').readlines()]  
    return stopwords  

#加载停用词
stopwords = stopwordslist("./data/chineseStopWords.txt")

然后我们开始数据清洗工作,清洗工作包括删除标点符号和停用词等,我们将会在数据集中增加两个字段clean_review和cut_review。

#删除除字母,数字,汉字以外的所有符号
df['clean_review'] = df['review'].apply(remove_punctuation)

#分词,并过滤停用词
# df['cut_review'] = df['clean_review'].apply(lambda x: " ".join([w for w in list(jb.cut(x)) if w not in stopwords]))
df['cut_review'] = df['clean_review'].apply(lambda x: [w for w in list(jb.cut(x)) if w not in stopwords])
df.head()

 

 数据清洗工作完成以后,我们要开始创建训练集和测试集,我们将使用7:3的比例来拆分数据,然后就是创建训练集和测试集的标签化文档TaggedDocument:

#创建训练集和测试集
train, test = train_test_split(df, test_size=0.3, random_state=42,stratify = df.cat.values)

#创建标签化文档
train_tagged = train.apply(
    lambda r: TaggedDocument(words=r['cut_review'], tags=[r['cat']]), axis=1)
test_tagged = test.apply(
    lambda r: TaggedDocument(words=r['cut_review'], tags=[r['cat']]), axis=1)

Doc2vec模型配置

Doc2vec是基于Word2Vec的方法,在Word2Vec架构中有两个算法:连续词袋(CBOW)和Skip-gram(SG)。而在Doc2vec架构中也有两个算法与之相似的算法它们是分布式存储(DM)和分布式词袋(DBOW).

分布式词袋(DBOW)

我们将首先使用Doc2vec的DBOW算法,它类似于word2vec中的Skip-gram算法。 通过训练神经网络来获得文档向量,该神经网络用于预测段落中的单词的概率分布,给出来自段落的随机采样的单词。我们将使用下列DBOW算法的参数:

  • dm=0 : 使用Doc2vec的DBOW算法,如果dm=1 使用DM算法。
  • min_count=2 : 忽略词频小于2的词语。
  • negative=5 : 将使用负采样,并指定应绘制多少“噪音词”(通常在5-20之间)。 如果设置为0,则不使用负采样。
  • hs=0 :  如果设置为0,则负数将不为零,负采样将会用到。
  • sample=0 : 配置哪些高频词随机下采样的阈值,可以用范围是(0,1e-5)。
  • workers=cores : 指定多少个工作线程来训练模型(在多核CPU上训练,速度更快)。
#CPU内核数
cores = multiprocessing.cpu_count()

下面开始创建词汇表 

from gensim.models import Doc2Vec
from tqdm import tqdm

model_dbow = Doc2Vec(dm=0,  negative=5, hs=0, min_count=2, sample = 0, workers=cores)
model_dbow.build_vocab([x for x in tqdm(train_tagged.values)])

 训练模型

 下面我们开始训练模型,我对模型进行30个周期的训练:

%%time
for epoch in range(30):
    model_dbow.train(utils.shuffle([x for x in tqdm(train_tagged.values)]), total_examples=len(train_tagged.values), epochs=1)
    model_dbow.alpha -= 0.002
    model_dbow.min_alpha = model_dbow.alpha

 我们完成了dbow模型训练耗时1分15秒。

 创建特征集

这里有些概念需要陈清一下,我们的模型dbow并不是用来预测的,训练模型的目的仅仅是让dbow可以生成文本的特征向量,其作用类似于Sklearn的CountVectorizer和TfidfTransformer。 模型训练完成以后就可以创建文本的特征向量。

def vec_for_learning(model, tagged_docs):
    sents = tagged_docs.values
    targets, regressors = zip(*[(doc.tags[0], model.infer_vector(doc.words, steps=20)) for doc in sents])
    return targets, regressors

y_train, X_train = vec_for_learning(model_dbow, train_tagged)
y_test, X_test = vec_for_learning(model_dbow, test_tagged)

预测

有了特征向量,接下来我们可以进行预测了,我们使用sklearn的逻辑回归来进行训练和预测。

#使用逻辑回归来预测
logreg = LogisticRegression(n_jobs=1, C=1e5)
logreg.fit(X_train, y_train)
y_pred = logreg.predict(X_test)

评估

预测完成以后,接下来我们对预测结果进行评估

from sklearn.metrics import accuracy_score, f1_score

print('Testing accuracy %s' % accuracy_score(y_test, y_pred))
print('Testing F1 score: {}'.format(f1_score(y_test, y_pred, average='weighted')))

准确率为77%,这个成绩还算只能算一般般,在我之前的博客中 我们用TfidfVectorizer分别在朴素贝叶斯、逻辑回归、支持向量机进行了预测和评估,其中其中逻辑回归和支持向量机的预测准确率都在80%以上,有心的读者可以将DBOW模型的特征向量在别的分类器上测试一下,看看效果如何。

分布式存储(DM)

接下来我们将使用Doc2vec的DM算法,它类似于word2vec中的CBOW算法。回我们将dm参数设置为1,同样在训练30个周期

model_dmm = Doc2Vec(dm=1, dm_mean=1, window=10, negative=5, min_count=1, workers=5, alpha=0.065, min_alpha=0.065)
model_dmm.build_vocab([x for x in tqdm(train_tagged.values)])
%%time
for epoch in range(30):
    model_dmm.train(utils.shuffle([x for x in tqdm(train_tagged.values)]), total_examples=len(train_tagged.values), epochs=1)
    model_dmm.alpha -= 0.002
    model_dmm.min_alpha = model_dmm.alpha

训练dm模型耗时3分9秒,这个要比前面训练dbow要慢一些。 接下来我们进行一下预测和评估:

y_train, X_train = vec_for_learning(model_dmm, train_tagged)
y_test, X_test = vec_for_learning(model_dmm, test_tagged)

logreg.fit(X_train, y_train)
y_pred = logreg.predict(X_test)

print('Testing accuracy %s' % accuracy_score(y_test, y_pred))
print('Testing F1 score: {}'.format(f1_score(y_test, y_pred, average='weighted')))

我们看到结果很不理想,准确率只有33.8%

合成一个新模型

Gensim Doc2Vec Tutorial on the IMDB Sentiment Dataset教程中提到一个新的方法,就是将分布式存储(DM)和分布式存储(DM)合成为一个新模型,然后再用这个新模型来创建文档特征向量,据说这样能提高模型的性能,我们也来试一下吧。

首先,我们删除临时训练数据以释放RAM。

model_dbow.delete_temporary_training_data(keep_doctags_vectors=True, keep_inference=True)
model_dmm.delete_temporary_training_data(keep_doctags_vectors=True, keep_inference=True)

 然后我们合成一个新模型:

from gensim.test.test_doc2vec import ConcatenatedDoc2Vec
new_model = ConcatenatedDoc2Vec([model_dbow, model_dmm])

接下来我们创建文档向量

def get_vectors(model, tagged_docs):
    sents = tagged_docs.values
    targets, regressors = zip(*[(doc.tags[0], model.infer_vector(doc.words, steps=20)) for doc in sents])
    return targets, regressors

y_train, X_train = get_vectors(new_model, train_tagged)
y_test, X_test = get_vectors(new_model, test_tagged)

最后我们来预测和评估一下新模型的表现

logreg.fit(X_train, y_train)
y_pred = logreg.predict(X_test)

print('Testing accuracy %s' % accuracy_score(y_test, y_pred))
print('Testing F1 score: {}'.format(f1_score(y_test, y_pred, average='weighted')))

似乎真的有改善,新模型的准确率比之前的分布式词袋(DBOW)模型提高了1%

 总结

今天我们学习了另一种文档表示法:Doc2vec,其中包含了2个算法:分布式词袋(DBOW)和分布式存储(DM)。在我们的数据集上经过测试后发现DBOW的表现要优于DM,但是将这两个模型合成一个新模型后,新模型的表现又比DBOW要好一些。总之如果大家还想更深入了解doc2vec的话请研读gensim的教程

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

文本多分类之Doc2Vec实战篇 的相关文章

随机推荐

  • 亲密关系-【沟通提示】-如何把学习到的东西用到生活中

    关于亲密关系 我学到了这么多 可为什么ta对这些毫不在意 我知道课里的观点都很重要 可我该怎么教会ta ta没有意识 看画面 案例 妈妈说话总是带有攻击性 总是骂她 怎么说 常见误区 你不要老师贬低我 对方苦苦思考 我到底该怎么办 你下意识
  • java中的多重循环

    多重循环 一个循环体内又包含另一个完整的循环结构 如下 while 循环条件1 循环操作1 while 循环条件2 循环操作2 do 循环操作1 do 循环操作2 while 循环条件2 while 循环条件1 for 循环条件1 循环操作
  • Docker - 使用Docker Compose部署应用

    简介 Docker Compose是一个基于Docker Engine进行安装的Python工具 该工具使得用户可以在一个声明式的配置文件中定义一个多容器的应用 在Docker节点上 以单引擎模式 Single Engine Mode 进行
  • 手写算法-python代码实现Lasso回归

    手写算法 python代码实现Lasso回归 Lasso回归简介 Lasso回归分析与python代码实现 1 python实现坐标轴下降法求解Lasso 调用sklearn的Lasso回归对比 2 近似梯度下降法python代码实现Las
  • 【直达本质讲运放】运放的“第一原理”式定量分析法

    数电 模电那两本书我也完整地翻过一 二遍 诶我为什么用 也 下面就是来点不复杂的 如果是那还不如直接把书的内容粘过来呢 对于运放的定量分析 虚短虚断 就如同 奇变偶不变 一样喜闻乐见的普及 但是对于什么时候用 虚短 什么时候用 虚断 学习的
  • Ridge和Lasso回归

    上周看了看回归方面的知识 顺便复 xue 习一下Ridge 岭回归 和Lasso回归 套索回归 瞅到了一篇英文博客讲得不错 翻译一下 本文翻译自 Ridge and Lasso Regression 本文是一篇Josh Starmer关于
  • 常用网络协议神图

  • 凸优化(一)——Introduction

    Introduction 一 最优化问题的数学表达 在最优问题中 其数学表达往往能化成标准形式 如下 minimizef0 x subject tofi x bi i 1 m begin aligned minimize quad f 0
  • 微信小程序对上传的图片进行裁剪

    背景 使用uniapp中uni chooseImage的裁剪参数crop只能在App中生效 在微信小程序中不生效 实现思路 uni chooseImage打开相册获取图片路径 uni chooseImage OBJECT uni app官网
  • c++面试记录

    1 数组与指针区别 数组 数组是用于储存多个相同类型数据的集合 指针 指针是一个变量 但是它和普通变量不一样 它存放的是其它变量在内存中的地址 赋值 数组 只能一个一个元素的赋值或拷贝 指针 指针变量可以相互赋值 表示范围 数组有效范围就是
  • flink table 使用Kafka Connector处理嵌套json

    使用flink table api 连接kafka 处理json类型数据 单层json处理比较简单 官方或网上都有很多例子 处理嵌套的json数据没什么介绍 处理嵌套json数据主要是schema定义 StreamExecutionEnvi
  • Linux系统之使用yum安装Redis数据库

    Linux系统之使用yum安装Redis数据库 一 redis介绍 1 redis解释 2 redis特点 3 redis使用场景 二 检查系统版本 1 检查系统版本 2 检查内核版本 三 检查yum仓库状态 四 查看系统默认提供的redi
  • mysql数据恢复,使用binlog配置恢复未备份数据

    使用mysqlbinlog配置 恢复数据库 什么是mysqlbinlog binlog是记录所有数据库表结构变更 例如CREATE ALTER TABLE 以及表数据修改 INSERT UPDATE DELETE 的二进制日志 binlog
  • 命令行参数设计

    1 目的 众多通用的小功能 制作为一个小工具 然后通过命令行来进行交互 使用非常的简便 本规范是为了统一命令行参数的设计 使得大家在制作或使用命令行工具时 能够更加有共享 进行会更加方便 2 适用范围 所有命令行工具参数的设计 3 基本原则
  • #SATA# SATA 实际管脚接线图

    前言 概述 实际接线管脚图 PATA 接口 M 2 U 2 AHCI NVMe 概述 SATA是Serial ATA的缩写 即串行ATA 它是一种电脑总线 主要功能是用作主板和大量存储设备 如硬盘及光盘驱动器 之间的数据传输 这是一种完全不
  • 迁移学习:他山之石,可以攻玉【VALSE Webinar】Panel实录

    编者按 迁移学习是机器学习与计算机视觉中的重要研究问题之一 旨在研究如何将一个领域的知识迁移到另外的领域 具有重要的研究意义与应用价值 但迁移学习又会存在哪些局限性 在实际应用中的价值是什么 未来的发展方向在哪里 为此 VALSE Webi
  • docker 数据持久化

    文章目录 定制镜像持久化 需求 实现 数据卷持久化 数据卷简介 数据卷的特性 创建读写数据卷 停止容器后的操作 查看数据卷详情 创建只写数据卷 查看数据卷详情 创建共享数据卷 Dockerfile持久化 创建Dockerfile 构建和运行
  • 大二上学期数据结构课程设计

    1 报数问题 问题描述 有n个小朋友围成一圈玩游戏 小朋友从1至n编号 2号小朋友坐在1号小朋友的顺时针方向 3号小朋友坐在2号小朋友的顺时针方向 1号小朋友坐在n号小朋友的顺时针方向 游戏开始 从1号小朋友开始顺时针报数 接下来每个小朋友
  • 安装TensorFlow遇到no module named ‘tensorflow’问题解决方法

    按照这个博客https blog csdn net qq 16633405 article details 79941696里的步骤安装TensorFlow时遇到no module named tensorflow 虽然作者给出了一个解决方
  • 文本多分类之Doc2Vec实战篇

    本文链接 https blog csdn net weixin 42608414 article details 88391760 版权 在我之前的几篇博客中 我介绍了两种文档向量化的表示方法 如Sklearn的CountVectorize