【DS】Doc2Vec和Logistic回归的多类文本分类

笔者邀请您,先思考:

1 您理解Word2Vec和Doc2Vec吗?

2 您如何做文本分类?

Doc2vec是一个NLP工具,用于将文档表示为向量,是word2vec方法的推广。为了理解doc2vec,最好理解word2vec方法。

Doc2vec是一个NLP工具,用于将文档表示为向量,是word2vec方法的推广。 为了理解doc2vec,最好理解word2vec方法。但是,完整的数学细节超出了本文的范围。如果您是word2vec和doc2vec的新手,以下资源可以帮助您入门:

  • 单词和短语的分布式表示及其组合
  • 句子和文档的分布式表示
  • Doc2Vec的简介
  • 关于IMDB情感数据集的Gensim Doc2Vec教程
  • word嵌入的文档分类教程

在使用Scikit-Learn进行多类文本分类时使用相同的数据集,在本文中,我们将使用Gensim中的doc2vec技术对产品的投诉进行分类。让我们开始吧!

数据

目标是将消费者金融投诉分为预先定义好的12类。这些数据可以从data.gov下载。

 1import pandas as pd
 2import numpy as np
 3from tqdm import tqdm
 4tqdm.pandas(desc="progress-bar")
 5from gensim.models import Doc2Vec
 6from sklearn import utils
 7from sklearn.model_selection import train_test_split
 8import gensim
 9from sklearn.linear_model import LogisticRegression
10from gensim.models.doc2vec import TaggedDocument
11import re
12import seaborn as sns
13import matplotlib.pyplot as plt
14
15df = pd.read_csv('Consumer_Complaints.csv')
16df = df[['Consumer complaint narrative','Product']]
17df = df[pd.notnull(df['Consumer complaint narrative'])]
18df.rename(columns = {'Consumer complaint narrative':'narrative'}, inplace = True)
19df.head(10)

在删除叙述性列中的null值之后,我们需要重新索引数据框架。

1df.shape

(318718, 2)

1df.index = range(318718)
2df['narrative'].apply(lambda x: len(x.split(' '))).sum()

我们有超过6300万字,这是一个比较大的数据集。

探索

1cnt_pro = df['Product'].value_counts()
2
3plt.figure(figsize=(12,4))
4sns.barplot(cnt_pro.index, cnt_pro.values, alpha=0.8)
5plt.ylabel('Number of Occurrences', fontsize=12)
6plt.xlabel('Product', fontsize=12)
7plt.xticks(rotation=90)
8plt.show();

然而,这些类是不平衡的,一个朴素分类器预测所有要收债的东西只会达到20%以上的准确率。 让我们看几个投诉叙述及其相关产品的例子。

1def print_complaint(index):
2    example = df[df.index == index][['narrative', 'Product']].values[0]
3    if len(example) > 0:
4        print(example[0])
5        print('Product:', example[1])
6
7print_complaint(12)
8print_complaint(20)

文本预处理

下面我们定义了一个函数,用于将文本转换为小写,并从单词中删除标点/符号等等。

1from bs4 import BeautifulSoup
2def cleanText(text):
3    text = BeautifulSoup(text, "lxml").text
4    text = re.sub(r'\|\|\|', r' ', text) 
5    text = re.sub(r'http\S+', r'<URL>', text)
6    text = text.lower()
7    text = text.replace('x', '')
8    return text
9df['narrative'] = df['narrative'].apply(cleanText)

下面的步骤包括训练测试分离为70/30,使用NLTK标记器删除停止字和标记文字。在我们的第一次尝试中,我们给每一个投诉故事都贴上了产品标签。

 1train, test = train_test_split(df, test_size=0.3, random_state=42)
 2
 3import nltk
 4from nltk.corpus import stopwords
 5def tokenize_text(text):
 6    tokens = []
 7    for sent in nltk.sent_tokenize(text):
 8        for word in nltk.word_tokenize(sent):
 9            if len(word) < 2:
10                continue
11            tokens.append(word.lower())
12    return tokens
13
14train_tagged = train.apply(
15    lambda r: TaggedDocument(words=tokenize_text(r['narrative']), tags=[r.Product]), axis=1)
16test_tagged = test.apply(
17    lambda r: TaggedDocument(words=tokenize_text(r['narrative']), tags=[r.Product]), axis=1)

这就是培训条目的样子——一个以“信用报告”为标签的投诉叙述示例。

1train_tagged.values[30]

建立Doc2Vec训练/评估模型

首先,我们实例化一个doc2vec模型——分布式词袋(DBOW)。在word2vec体系结构中,两个算法名称分别为“连续词袋”(CBOW)和“skip-gram”(SG);在doc2vec架构中,相应的算法有“分布式内存”(DM)和“分布式词袋”(DBOW)。

分布式词袋(DBOW)

DBOW是doc2vec模型,类似于word2vec中的Skip-gram模型。通过训练神经网络来预测段落中随机抽取的单词的概率分布,得到段落向量。 我们会更改以下参数:

  • 如果dm=0,则使用分布式词袋包(PV-DBOW);如果dm=1,则使用“分布式内存”(PV-DM)。
  • 300维特征向量。
  • min_count=2,忽略总频率低于这个值的所有单词。
  • negative = 5, 指定应该绘制多少个“噪声字”。
  • hs=0,负是非零,用负抽样。
  • sample=0,用于配置哪些高频率单词是随机向下采样的阈值。
  • workers=cores,使用这些工人线程来训练模型(=用多核机器进行更快的训练)。
1import multiprocessing
2
3cores = multiprocessing.cpu_count()

建立词汇

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

在Gensim中,doc2vec模型的训练相当简单,我们对模型进行了初始化,并对其进行了30次的训练。

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

为分类器构建最终的向量特征

1def vec_for_learning(model, tagged_docs):
2    sents = tagged_docs.values
3    targets, regressors = zip(*[(doc.tags[0], model.infer_vector(doc.words, steps=20)) for doc in sents])
4    return targets, regressorsdef vec_for_learning(model, tagged_docs):
5    sents = tagged_docs.values
6    targets, regressors = zip(*[(doc.tags[0], model.infer_vector(doc.words, steps=20)) for doc in sents])
7    return targets, regressors

训练逻辑回归分类器。

 1y_train, X_train = vec_for_learning(model_dbow, train_tagged)
 2y_test, X_test = vec_for_learning(model_dbow, test_tagged)
 3
 4logreg = LogisticRegression(n_jobs=1, C=1e5)
 5logreg.fit(X_train, y_train)
 6y_pred = logreg.predict(X_test)
 7
 8from sklearn.metrics import accuracy_score, f1_score
 9
10print('Testing accuracy %s' % accuracy_score(y_test, y_pred))
11print('Testing F1 score: {}'.format(f1_score(y_test, y_pred, average='weighted')))

Testing accuracy 0.6683609437751004 Testing F1 score: 0.651646431211616

分布式内存(DM)

分布式内存(DM)充当的是一种内存,它可以记住当前上下文中缺少的内容——或者作为段落的主题。虽然单词向量表示单词的概念,但是文档向量打算表示文档的概念。我们再次实例化一个向量大小为300字的Doc2Vec模型,并在训练语料库中迭代30次。

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

训练逻辑回顾分类器

1y_train, X_train = vec_for_learning(model_dmm, train_tagged)
2y_test, X_test = vec_for_learning(model_dmm, test_tagged)
3
4logreg.fit(X_train, y_train)
5y_pred = logreg.predict(X_test)
6
7print('Testing accuracy %s' % accuracy_score(y_test, y_pred))
8print('Testing F1 score: {}'.format(f1_score(y_test, y_pred, average='weighted')))

Testing accuracy 0.47498326639892907 Testing F1 score: 0.4445833078167434

模型匹配

根据Gensim doc2vec教程关于IMDB情绪数据集的介绍,将分布式词汇包(DBOW)和分布式内存(DM)中的段落向量组合在一起可以提高性能。接下来,我们将把这些模型组合在一起进行评估。

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

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

连接两个模型

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

构建特征向量

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

训练逻辑回归模型

1y_train, X_train = get_vectors(new_model, train_tagged)
2y_test, X_test = get_vectors(new_model, test_tagged)
3
4logreg.fit(X_train, y_train)
5y_pred = logreg.predict(X_test)
6
7print('Testing accuracy %s' % accuracy_score(y_test, y_pred))
8print('Testing F1 score: {}'.format(f1_score(y_test, y_pred, average='weighted')))

Testing accuracy 0.6778572623828648 Testing F1 score: 0.664561533967402

结果提高了1%。 在本文中,我使用训练集对doc2vec进行训练,但是在Gensim的教程中,使用整个数据集进行训练,我尝试了这种方法,使用整个数据集对doc2vec分类器进行训练,用于我们的消费者投诉分类,我的准确率达到了70%。你可以在这里找到Notebook,这是一个不同的方法。

上面分析的Jupyter笔记本可以在Github上找到。我期待着听到任何问题。

作者:Susan Li 原文链接: https://www.kdnuggets.com/2018/11/multi-class-text-classification-doc2vec-logistic-regression.html 版权声明:作者保留权利。文章为作者独立观点,不代表数据人网立场。 数据人网:数据人学习,交流和分享的平台,诚邀您创造和分享数据知识,共建和共享数据智库。

本文分享自微信公众号 - 数据科学与人工智能(DS_AI_shujuren)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-11-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器之心

学界 | 斯坦福提出神经任务编程NTP:让机器人从层级任务中学习

选自arXiv 机器之心编译 参与:朱乾树、蒋思源 斯坦福视觉与学习实验室与加州大学提出神经任务编程(NTP),它可以将指定任务作为输入,并递归地将该任务分解成...

38490
来自专栏机器之心

业界 | OpenAI提出新型神经网络:自动计算词对象,实现实体消岐

31170
来自专栏新智元

Facebook开源PyTorch版本fairseq翻译模型,训练速度提高50%

【新智元导读】FAIR的开源序列到序列(sequence-to-sequence)引擎现在可以在PyTorch使用了。FAIR今天发布了fairseq-py,这...

549110
来自专栏Python中文社区

Kaggle搭积木式刷分大法: LB 0.11666(排名前15%)

專 欄 ❈本文作者:王勇,目前感兴趣项目商业分析、Python、机器学习、Kaggle。17年项目管理,通信业干了11年项目经理管合同交付,制造业干了6年项目...

231100
来自专栏数据科学学习手札

(数据科学学习手札08)系统聚类法的Python源码实现(与Python,R自带方法进行比较)

聚类分析是数据挖掘方法中应用非常广泛的一项,而聚类分析根据其大体方法的不同又分为系统聚类和快速聚类,其中系统聚类的优点是可以很直观的得到聚类数不同时具体类中包括...

29550
来自专栏iOSDevLog

Python机器学习:Scikit-Learn教程

一个易于理解的scikit-learn教程,可以帮助您开始使用Python机器学习。

64560
来自专栏CreateAMind

keras中文文档

Keras是一个极简和高度模块化的神经网络库,Keras由纯Python编写而成并基于Theano或Tensorflow。Keras 为支持快速实验而生,如果你...

33750
来自专栏机器之心

资源 | Feature Tools:可自动构造机器学习特征的Python库

机器学习越来越多地从人工设计模型转向使用 H20、TPOT 和 auto-sklearn 等工具自动优化的工具。这些库以及随机搜索(参见《Random Sear...

22920
来自专栏AI科技大本营的专栏

课程 |《深度学习原理与TensorFlow实践》学习笔记(二)

作者 | 王清 TensorFlow基础使用 环境准备 TensorFlow安装 常用Python库介绍 实例解析 Kaggle平台及Titanic题目介绍 代...

42980
来自专栏AI研习社

从原理到实战 英伟达教你用PyTorch搭建RNN(下)

编者按:本文为《从原理到实战 英伟达教你用PyTorch搭建RNN》的下篇,阅读上篇请点击这里。文章原载于英伟达博客,AI 研习社编译。 ? 代码实操 在开...

45840

扫码关注云+社区

领取腾讯云代金券