赛题介绍
零基础入门NLP - 新闻文本分类
赛题以新闻数据为赛题数据,数据集报名后可见并可下载。赛题数据为新闻文本,并按照字符级别进行匿名处理。整合划分出14个候选分类类别:财经、彩票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐的文本数据。
赛题数据由以下几个部分构成:训练集20w条样本,测试集A包括5w条样本,测试集B包括5w条样本。为了预防选手人工标注测试集的情况,我们将比赛数据的文本按照字符级别进行了匿名处理。处理后的赛题训练数据如下:
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 导入工具包
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from scipy import stats
import warnings
warnings.filterwarnings("ignore")
2 读取数据
test_data = pd.read_csv('./test_a.csv',sep='\t', encoding='UTF-8')
train_data = pd.read_csv('./train_set.csv',sep='\t', encoding='UTF-8')
3 数据集样例查看
查看数据集的前几行数据,了解数据集、测试集的字段信息
print(train_data.head(3))
label text
0 2 2967 6758 339 2021 1854 3731 4109 3792 4149 15…
1 11 4464 486 6352 5619 2465 4802 1452 3137 5778 54…
2 3 7346 4068 5074 3747 5681 6093 1777 2226 7354 6…
注意:第一行数据是序号,第二行的才是label,第三行是text
print(test_data.head(3))
text
0 5399 3117 1070 4321 4568 2621 5466 3772 4516 2…
1 2491 4109 1757 7539 648 3695 3038 4490 23 7019…
2 2673 5076 6835 2835 5948 5677 3247 4124 2465 5…
注意:测试集是没有label的,第一行的0-2是序号
4 查看数据类型和数据大小
(1)查看测试集信息数据
print(test_data.info())
RangeIndex: 50000 entries, 0 to 49999
Data columns (total 1 columns):
Column Non-Null Count Dtype
0 text 50000 non-null object
dtypes: object(1)
memory usage: 390.8+ KB
None
可以看到有50000条数据,其中text类型是object类型。数据大小是390.8KB
(2)查看 数据集信息数据
print(train_data.info())
RangeIndex: 200000 entries, 0 to 199999
Data columns (total 2 columns):
Column Non-Null Count Dtype
0 label 200000 non-null int64
1 text 200000 non-null object
dtypes: int64(1), object(1)
memory usage: 3.1+ MB
None
可以看到有200000条数据,其中label类型是int64,text类型是object类型。数据大小是3.1MB
5 查看缺失值
(1)计算数据集中label列的缺失率和缺失了label值的行数
# 计算label这一列的缺失率
print((train_data.shape[0]-train_data['label'].count())/train_data.shape[0])
# 计算缺失label值的行数
print(train_data[train_data['label'].isna()].count())
0.0
label 0
text 0
dtype: int64
注意:label是有值=0的,所以不能像以下的text去==0 去判断该行是否为空
可以看到label缺失率为0,也没有缺失的行数
(2)计算数据集中text列的缺失率和缺失了text值的行数
# 计算text这一列的缺失率
print((train_data.shape[0]-train_data['text'].count())/train_data.shape[0])
# 计算缺失text值的行数
print(train_data[train_data['text'].isna() | (train_data['text']==0)].count())
0.0
label 0
text 0
dtype: int64
可以看到text缺失率为0,也没有缺失的行数
6 观察数据分布
6.1 查看Label分布
(1)方法一:jupyter notebook下
import numpy as np
import matplotlib
from matplotlib import pylab, mlab, pyplot
plt = pyplot
import pandas as pd
train_data = pd.read_csv('./train_set.csv',sep='\t', encoding='UTF-8')
train_data['label'].value_counts().plot(kind='bar')
plt.title('News class count')
plt.xlabel("category")
Text(0.5, 0, 'category')
(2)方法二:VScode下使用pandas.core.series.Series 的方法
import pandas as pd
import matplotlib.pyplot as plt
train_data['label'].value_counts().plot(kind='bar')
plt.title('News class count')
plt.xlabel("category")
plt.text(0.5, 0, 'category')
plt.show()
(3)方法三:VScode下手写计数统计
import pandas as pd import matplotlib.pyplot as plt import numpy as np import seaborn as sns from scipy import stats import warnings warnings.filterwarnings("ignore") # 读取文件 test_data = pd.read_csv('./test_a.csv',sep='\t', encoding='UTF-8') train_data = pd.read_csv('./train_set.csv',sep='\t', encoding='UTF-8') # 统计label的各种类别数量 distribute_label = {0:0,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0} for i, v in train_data['label'].items(): if distribute_label.get(v)==None: distribute_label[v] = 1 else: distribute_label[v] =distribute_label.get(v)+1 label_list = distribute_label.keys() num_list1 = distribute_label.values() # 纵坐标值1 x = range(len(num_list1)) """ 绘制条形图 left:长条形中点横坐标 height:长条形高度 width:长条形宽度,默认值0.8 label:为后面设置legend准备 """ rects1 = plt.bar(x,height=num_list1, width=0.4, alpha=0.8, color='red', label="labelnumber") plt.ylim(0, 50000) # y轴取值范围 plt.ylabel("number") """ 设置x轴刻度显示值 """ plt.xticks([index + 0.2 for index in x], label_list) plt.xlabel("label") plt.title("label-distribution") plt.legend() # 设置题注 # 编辑文本 for rect in rects1: height = rect.get_height() plt.text(rect.get_x() + rect.get_width() / 2, height+1, str(height), ha="center", va="bottom") plt.show()
从图中可以看到数据的label分布很不均匀,这对模型准确率的是有非常大的影响。后面的数据预处理必须要通过相应的方法处理的。
6.2 查看句子长度分布
train_data['text_len'] = train_data['text'].apply(lambda x: len(x.split(' ')))
print(train_data['text_len'].describe())
plt.hist(train_data['text_len'], bins=200) #使用了%pylab,可以直接使用'plt'
plt.xlabel('sentence-length')
plt.ylabel('category-number')
# plt.text(0.5, 1.0, '')
plt.show()
count 200000.000000
mean 907.207110
std 996.029036
min 2.000000
25% 374.000000
50% 676.000000
75% 1131.000000
max 57921.000000
从输出的数据可以看到句子的平均长度907,最短的只有2。从图中可以看出,句子长度大多数分布在2000以下
6.3 句子中字符数量分布
from collections import Counter
all_lines = ' '.join(list(train_data['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])
6869
(‘3750’, 7482224)
(‘3133’, 1)
从统计结果中可以看出,在训练集中总共包括6869个不同字,其中编号3750的字出现的次数最多,编号3133的字出现的次数最少。
这里还可以根据字在每个句子的出现情况,反推出标点符号。下面代码统计了不同字符在句子中出现的次数,其中字符3750,字符900和字符648在20w新闻的覆盖率接近99%,很有可能是标点符号。
思考:如果是标点符号,这对模型的准确率是有影响的,是否应该去除去提高模型的准确率
7 总结分析
(1)总结
- 数据集中每个新闻包含的字符个数平均为1000个,还有一些新闻字符较长;
- 数据集中新闻类别分布不均匀,科技类新闻样本量接近4w,星座类新闻样本量不到1k;
- 数据集中总共包括7000-8000个字符;
- 数据集中存在高频的字符,有可能是标点符号
(2)分析
- 每个新闻平均字符个数较多,可能需要截断
- 由于类别不均衡,会严重影响模型的精度,需要对数据集预处理,使得类别尽量均衡
- 存在高频的字符,是标点符号,可能需要剔除