0%

文本预处理-文本数据分析

文本预处理-文本数据分析

文本数据分析的作用

  • 文本数据分析能够有效帮助我们理解数据语料,快速检查出语料可能存在的问题,并指导之后模型训练过程中一些超参数的选择

常用的几种文本数据分析方法

  • 标签数量分布
  • 句子长度分布
  • 词频统计与关键词词云

实验数据

  • 中文酒店评论语料:

    • 属于二分类的中文情感分析语料,该语料存放在"./cn_data"目录下
    • 其中train.tsv代表训练集,dev.tsv代表验证集,二者数据样式相同
  • train.tsv数据样式

    sentence label

    早餐不好,服务不到位,晚餐无西餐,早餐晚餐相同,房间条件不好,餐厅不分吸烟区,房间不分有无烟房. 0

  • train.tsv数据样式说明

    • train.tsv中的数据内容共分为2列,第一列数据代表具有感情色彩的评论文本;第二列数据,0或1,代表每条文本数据是积极或消极的评论,0代表消极,1代表积极

获得训练集和验证集的标签数量分布

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')

# 分别读取训练集和验证集
train_data = pd.read_csv("./cn_data/train.tsv", sep="\t")
valid_data = pd.read_csv("./cn_data/dev.tsv", sep="\t")

# 获得训练数据标签数量分布
sns.countplot("label", data=train_data)
plt.title("train_data")
plt.show()

# 获取验证数据标签数量分布
sns.countplot("label", data=valid_data)
plt.title("valid_data")
plt.show()

  • 分析:

    • 在深度学习模型评估中,我们一般使用ACC作为评估指标,若想将ACC的基线定义在50%左右,则需要正负样本比例维持在1:1左右,否则就要进行收入必要的数据增强或数据删减。

获取训练集和验证集的句子长度分布

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 在训练数据中添加新的句子长度列,每个元素的值都是对应的句子列的长度
train_data['sentence_length'] = list(map(lambda x:len(x), train_data['sentence']))
# 绘制句子长度列的数量分布图
sns.countplot("sentence_length", data=train_data)
# 主要关注count长度分布的纵坐标,不需要绘制横坐标,横坐标范围通过dict图进行查看
plt.xticks([])
plt.show()

# 绘制dist长度的分布图
sns.distplot(train_data["sentence_length"])

# 主要关注dist长度分布横坐标,不需要绘制纵坐标
plt.yticks([])
plt.show()

# 在验证数据中添加新的句子长度列,每个元素的值都是对应的句子列的长度
valid_data["sentence_length"] = list(map(lambda x:len(x), valid_data["sentence"]))

# 绘制句子长度列的数量分布图
sns.countplot("sentence_length", data=valid_data)
# 主要关注count长度分布的纵坐标,不需要绘制横坐标,横坐标范围通过dist图进行查看
plt.xticks([])
plt.show()

# 绘制dist长度分布图
sns.distplot(valid_data["sentence_length"])
# 主要关注dist长度分布横坐标,不需要绘制纵坐标
plt.yticks([])
plt.show()

  • 分析
    • 通过绘制句子长度分布图,可以得知语料中大部分句子长度的分布范围,因为模型的输入要求固定尺寸的张量,合理的长度范围对之后进行句子截断补齐(规范长度)直到关键的指导作用。上图中大部分句子就是在20~250之间

获取训练集和验证集正负样本长度散点分布

1
2
3
4
5
6
# 绘制训练集长度分布的散点图
sns.stripplot(y="sentence_length", x="label", data=train_data)
plt.show()
# 绘制验证集长度分布的散点图
sns.stripplot(y="sentence_length", x="label", data=valid_data)
plt.show()

  • 分析
    • 通过查看正负样本长度散点图,可以有效定位异常点的出现位置,帮助我们更准确进行人工语料审查。上图中在训练集正样本中出现了异常点,它的句子长度近3500左右,需要人工审查

获得训练集与验证集不同词汇总数统计

1
2
3
4
5
6
7
8
9
10
# 导入jieba用于分词
# 导入chain方法用于扁平化列表
import jieba
from itertools import chain
# 进行训练集的句子进行分词,并统计出不同词汇的总数
train_vocab = set(chain(*map(lambda x : jieba.lcut(x), train_data["sentence"])))
print("训练集共包含不同词汇总数为:", len(train_vocab))
# 进行验证集的句子进行分词,并统计出不同词汇的总数
valid_vocab = set(chain(*map(lambda x:jieba.lcut(x), valid_data["sentence"])))
print("验证集共包含不再词汇总数为:", len(valid_vocab))

训练集共包含不同词汇总数为: 12162

验证集共包含不再词汇总数为: 6857

获得训练集上正负样本的高频形容词词云

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 使用jieba中的词性标注功能
import jieba.posseg as pseg
def get_a_list(text):
"""用于获取形容词列表"""
# 使用jieba的记性标注方法切分文本,获得具有词性属性flag和词汇属性的word的对象,从而判断flag是否为形容词,来返回对应的词汇
r = []
for g in pseg.lcut(text):
if g.flag == "a":
r.append(g.word)
return r

# 导入绘制词云的工具包
from wordcloud import WordCloud
def get_word_cloud(keywords_list):
# 实例化绘制词云的类,其中参数font_path是字体路径,为了能显示中文
# max_words指词云图像最多显示多少个词,background_color为背景颜色
wordcloud = WordCloud(font_path="./SimHei.ttf", max_words=100, background_color="white")
# 将传入的列表转化成词云生成器需要的字符串形式
keywords_string = " ".join(keywords_list)
# 生成词云
wordcloud.generate(keywords_string)

# 绘制图像并显示
plt.figure()
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis("off")
plt.show()

# 获得训练集上正样本
p_train_data = train_data[train_data["label"]==1]["sentence"]
# 对正样本的每个句子的形容词
train_p_a_vocab = chain(*map(lambda x: get_a_list(x), p_train_data))
#print(train_p_n_vocab)

# 获得训练集上负样本
n_train_data = train_data[train_data["label"]==0]["sentence"]
#print()

# 获取负样本的每个句子的形容词
train_n_a_vocab = chain(*map(lambda x:get_a_list(x), n_train_data))

get_word_cloud(train_p_a_vocab)
get_word_cloud(train_n_a_vocab)

获得验证集上正负样本的形容词词云

1
2
3
4
5
6
7
8
9
# 获得验证集上正样本
p_valid_data = valid_data[valid_data["label"]==1]["sentence"]
# 对正样本的每个句子的形容词
valid_p_a_vocab = chain(*map(lambda x: get_a_list(x), p_valid_data))
# 获得验证集上负样本
n_valid_data = valid_data[valid_data["label"]==0]["sentence"]
valid_n_a_vocab = chain(*map(lambda x: get_a_list(x), n_valid_data))
get_word_cloud(valid_p_a_vocab)
get_word_cloud(valid_n_a_vocab)

  • 分析
    • 根据高频形容词词云显示,可以对当前语料质量进行简单评估,同时对违反语料标签含义的词汇进行人工审查和修正,来保证绝大多数语料符合训练标准。上图中的正样本大多数是褒义词,而负样本大多数是贬义词,基本符合要求,但负样本中也存在“便利”这样的褒义词,因此可以人工进行审查