【新闻文本分类】(task1)赛题数据分析
学习总结
(1)要熟悉pandas、matplotlib等工具包,如train_df['text_unique'] = train_df['text'].apply(lambda x: ' '.join(list(set(x.split(' ')))))
以空格为分隔提取每个单词后存取set去重再转为list操作,得到去重后的text_unique
列。
(2)文本分类问题,需要根据每句的字符进行分类。难点是需要对匿名字符进行建模(不能直接使用中文分词等操作),进而完成文本分类的过程。由于文本数据是一种典型的非结构化数据,因此可能涉及到特征提取和分类模型两个部分。
(3)几个大体的思路:
【思路1】:TF-IDF提取特征 + 机器学习分类器
直接使用TF-IDF对文本提取特征,并使用分类器进行分类。在分类器的选择上,可以使用SVM、LR、或者XGBoost等机器学习分类器。
【思路2】:FastText
【思路3】:Word2Vec + 深度学习分类器:WordVec词向量,并通过构建深度学习分类完成分类。深度学习分类的网络结构可以选择TextCNN、TextRNN或者BiLSTM。
【思路4】:Bert词向量
一、NLP 赛题理解
1.1 题目
赛题介绍:https://tianchi.aliyun.com/competition/entrance/531810/introduction
赛题以匿名处理后的新闻数据为赛题数据,数据集报名后可见并可下载。赛题数据为新闻文本,并按照字符级别进行匿名处理。整合划分出 14 个候选分类类别:财经、彩票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐的文本数据。
赛题数据由以下几个部分构成:
训练集 20w 条样本,测试集 A 包括 5w 条样本,测试集 B 包括 5w 条样本。
为了预防选手人工标注测试集的情况,将比赛数据的文本按照字符级别进行了匿名处理。评价标准为类别 f1_score
的均值,选手提交结果与实际测试集的类别进行对比,结果越大越好。
处理后的赛题训练数据如下:
label | text |
---|---|
6 | 57 44 66 56 2 3 3 37 5 41 9 57 44 47 45 33 13 63 58 31 17 47 0 1 1 69 26 60 62 15 21 12 49 18 38 20 50 23 57 44 45 33 25 28 47 22 52 35 30 14 24 69 54 7 48 19 11 51 16 43 26 34 53 27 64 8 4 42 36 46 65 69 29 39 15 37 57 44 45 33 69 54 7 25 40 35 30 66 56 47 55 69 61 10 60 42 36 46 65 37 5 41 32 67 6 59 47 0 1 1 68 |
在数据集中标签的对应的关系如下:{‘科技’: 0, ‘股票’: 1, ‘体育’: 2, ‘娱乐’: 3, ‘时政’: 4, ‘社会’: 5, ‘教育’: 6, ‘财经’: 7, ‘家居’: 8, ‘游戏’: 9, ‘房产’: 10, ‘时尚’: 11, ‘彩票’: 12, ‘星座’: 13}
1.2 评测指标
评价标准为类别f1_score
的均值,选手提交结果与实际测试集的类别进行对比,结果越大越好。
1.3 大体思路
文本分类问题,需要根据每句的字符进行分类。难点是需要对匿名字符进行建模(不能直接使用中文分词等操作),进而完成文本分类的过程。由于文本数据是一种典型的非结构化数据,因此可能涉及到特征提取和分类模型两个部分。
思路1:TF-IDF + 机器学习分类器
直接使用TF-IDF对文本提取特征,并使用分类器进行分类。在分类器的选择上,可以使用SVM、LR、或者XGBoost。
思路2:FastText
FastText是入门款的词向量,利用Facebook提供的FastText工具,可以快速构建出分类器。
思路3:Word2Vec + 深度学习分类器
WordVec是进阶款的词向量,并通过构建深度学习分类完成分类。深度学习分类的网络结构可以选择TextCNN、TextRNN或者BiLSTM。
思路4:Bert词向量
Bert是高配款的词向量,具有强大的建模学习能力。
二、读取比赛数据
天池:https://account.aliyun.com/login/login.htm
下载比赛数据集,https://tianchi.aliyun.com/competition/entrance/531810/introduction
读取比赛数据集,读取代码:
import pandas as pd
# nrows为读取的行数
train_df = pd.read_csv('train_set.csv', sep='\t', nrows=100)
train_df['word'] = train_df['text'].apply(lambda x: len(x.split(' ')))
- 1
- 2
- 3
- 4
读取数据集的前几行,第一列(label
列)为新闻的类别,第二列(text
列)为新闻的字符:
label text word
0 2 2967 6758 339 2021 1854 3731 4109 3792 4149 15... 1057
1 11 4464 486 6352 5619 2465 4802 1452 3137 5778 54... 486
2 3 7346 4068 5074 3747 5681 6093 1777 2226 7354 6... 764
3 2 7159 948 4866 2109 5520 2490 211 3956 5520 549... 1570
4 3 3646 3055 3055 2490 4659 6065 3370 5814 2465 5... 307
- 1
- 2
- 3
- 4
- 5
- 6
三、对数据集字符进行可视化,统计标签和字符分布
统计数据集中所有句子所包含字符的平均个数
统计数据集中不同类别下句子平均字符的个数
统计数据集中类别分布的规律
统计数据集中不同类别下句子中最常见的5个字符
3.1 句子长度分析
# 句子长度分析
train_df['text_len'] = train_df['text'].apply(lambda x: len(x.split(' ')))
print(train_df['text_len'].describe())
- 1
- 2
- 3
apply是作用于每行中,lambda是匿名函数得到每坨东西的单词长度x。
# 绘制单词数直方图,bins指定区间长度
_ = plt.hist(train_df['text_len'], bins = 200)
plt.xlabel('Text char count')
plt.title("Histogram of char count")
- 1
- 2
- 3
- 4
绘制每个单词数对应的数量,bins
指定每个柱子的区间长度。
3.2 新闻类别分布
train_df['label'].value_counts().plot(kind = 'bar')
plt.title('News class count')
plt.xlabel("category")
hist2 = plt.hist(train_df['label'])
plt.xlabel('category')
plt.title("News class count")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
在训练集中科技类新闻最多,其次是股票类新闻,最少的新闻是星座新闻。
如果用上面hist2
的方法也能画:
3.3 字符分布统计
首先可以学习一个字典排序栗子(用到lambda
表达式):
# 字典排序栗子
dict1 = {'a': 1, 'b': 4, 'c': 0}
# 以列表形式输出字典dict1的key
# dict1.items()为字典的键值对
lst1 = [key for key, value in dict1.items()]
print(lst1) # ['a', 'b', 'c']
# 颠倒字典的key:value值
dict2 = {value: key for key, value in dict1.items()}
print(dict2) # {1: 'a', 4: 'b', 0: 'c'}
# 将字典dict1按照value值进行排序,得到列表形式
lst2 = sorted(dict1.items(), key = lambda x: x[1])
print(lst2) # [('c', 0), ('a', 1), ('b', 4)]
"""
这里的items()是字典的键值对,即待排序的对象;
key = lambda x: x[1]为前面对象的第二位数据的值(即value)进行排序
key = lambda 变量:变量[维数]
"""
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
有了上面基础后,我们现在要统计不同单词的出现次数(并进行排序):
# 字符分布统计
from collections import Counter
# 把所有text的元素拼接成一个大字符串
all_lines = ' '.join(list(train_df['text']))
word_count = Counter(all_lines.split(" "))
word_count = sorted(word_count.items(),
key = lambda d: d[1],
reverse = True)
print("不同的单词的个数:", len(word_count))
print("出现最多的单词:", word_count[0])
print("出现最少的单词:", word_count[-1])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
不同的单词的个数: 2405
出现最多的单词: ('3750', 3702)
出现最少的单词: ('5034', 1)
- 1
- 2
- 3
现在要统计不同字符在所有句子中的出现比率,和上面一样也是先拼接成一个包含所有字符的string
字符串,为了统计出现的每个单词的出现个数,先去重:' '.join(list(set(x.split(' '))))
以空格为分割找到每个单词,然后把这些单词用set去重后再转为list。
后面通过Counter
得到得到一个字典列表word_count({'3750': 99, '900': 99})
,value
即对应单词key
的个数。
(下面第一行代码不要被劝退到,看lambda
里面的东西,参考上面我的解释~)
# 统计不同字符在所有句子中的出现比率
train_df['text_unique'] = train_df['text'].apply(lambda x: ' '.join(list(set(x.split(' ')))))
# 拼接所有的单词成为一个大的字符串
all_lines = ' '.join(list(train_df['text_unique']))
# 得到一个字典列表word_count({'3750': 99, '900': 99})
word_count = Counter(all_lines.split(" "))
# print("===验证一波===", word_count)
word_count = sorted(word_count.items(),
key = lambda d: int(d[1]),
reverse = True)
print(word_count[0])
print(word_count[1])
print(word_count[2])
# ('648', 96)表示648字符在20w新闻的出现比率为96%
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
附:打卡清单
任务名称 | 难度 | 所需技能 |
---|---|---|
报名比赛,下载比赛数据集并完成读取 | 低 | Pandas |
对数据集字符进行可视化,统计标签和字符分布 | 中 | Pandas |
使用 TFIDF 提取文本特征 | 中 | Sklearn |
使用 TFIDF 特征 和 线性模型完成训练和预测 | 中 | Sklearn |
使用 TFIDF 特征 和 XGBoost 完成训练和预测 | 中 | Sklearn、XGBoost |
学会训练 FastText、Word2Vec 词向量 | 中 | FastText、gensim |
使用 Word2Vec 词向量,搭建 TextCNN 模型训练预测 | 高 | Pytorch、Keras |
使用 Word2Vec 词向量,搭建 BILSTM 模型训练预测 | 高 | Pytorch、Keras |
学会 Bert 基础,transformer 库基础使用 | 中 | Pytorch、transformer |
使用 Bert 在比赛数据集中完成预训练 | 高 | Pytorch、transformer |
使用 Bert 在比赛数据集上完成微调 | 高 | Pytorch、transformer |
具体打卡要求
需要使用Python环境下Notebook完成任务
需要完成所有的任务细节才算完成一个任务
所有的任务可以写在一个Notebook内
Reference
(1)https://tianchi.aliyun.com/competition/entrance/531810/introduction
文章来源: andyguo.blog.csdn.net,作者:山顶夕景,版权归原作者所有,如需转载,请联系作者。
原文链接:andyguo.blog.csdn.net/article/details/121109171
- 点赞
- 收藏
- 关注作者
评论(0)