NLP-新闻分类

来自天池:零基础入门NLP - 新闻文本分类

代码示例:

一、赛题简介

赛题以新闻数据为赛题数据,数据集报名后可见并可下载。赛题数据为新闻文本,并按照字符级别进行匿名处理。整合划分出14个候选分类类别:财经、彩票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐的文本数据。

赛题数据由以下几个部分构成:训练集20w条样本,测试集A包括5w条样本,测试集B包括5w条样本。为了预防选手人工标注测试集的情况,我们将比赛数据的文本按照字符级别进行了匿名处理。

label = {'科技': 0, '股票': 1, '体育': 2, '娱乐': 3, '时政': 4, '社会': 5, '教育': 6, '财经': 7, '家居': 8, '游戏': 9, '房产': 10, '时尚': 11, '彩票': 12, '星座': 13}

Dataset

file description size link
train_set.csv.zip 训练集数据(选手需要自行解压) 236.11MB https://tianchi-competition.oss-cn-hangzhou.aliyuncs.com/531810/train_set.csv.zip
test_a.csv.zip 测试集A榜数据(选手需要自行解压) 59.12MB https://tianchi-competition.oss-cn-hangzhou.aliyuncs.com/531810/test_a.csv.zip
test_a_sample_submit.csv 测试集A榜提交样例 97.66KB https://tianchi-competition.oss-cn-hangzhou.aliyuncs.com/531810/test_a_sample_submit.csv

二、数据集分析

1
2
3
import pandas as pd
path = '/content/drive/My Drive/Colab Notebooks/NLP/NewsClassification/data/train_set.csv'
train_df = pd.read_csv(path, sep='\t', nrows=15000) # nrows为读取行数目;sep为分隔符,csv设置为\t

数据分布

1
2
3
4
5
6
7
8
9
10
11
12
13
%pylab inline
# 空格隔开,统计单词个数
train_df['text_len'] = train_df['text'].apply(lambda x: len(x.split(' ')))
print(train_df['text_len'].describe()) #数据分布情况统计

# count 200000.000000
# mean 907.207110
# std 996.029036
# min 2.000000
# 25% 374.000000
# 50% 676.000000
# 75% 1131.000000
# max 57921.000000

标签统计

1
2
3
train_df['label'].value_counts().plot(kind='bar')
plt.title('News class count')
plt.xlabel("category")

句长分布直方图

1
2
3
_ = plt.hist(train_df['text_len'], bins=200)
plt.xlabel('Text char count')
plt.title("Histogram of char count")

字符分布统计

1
2
3
4
5
6
7
8
9
10
11
from collections import Counter
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])

三、词向量

一般数据可表示为(NxM)

图像数据(hight×width×channel)

但文本是不定长度

文本表示成计算机能够运算的数字或向量的方法一般称为词嵌入(Word Embedding)方法。词嵌入将不定长的文本转换到定长的空间内,是文本分类的第一步。

{'我': 1, '爱': 2, '北': 3, '京': 4, '天': 5,'安': 6, '门': 7, '喜': 8, '欢': 9, '上': 10, '海': 11}

  • OneHot 编码 (转换为稀疏向量)
1
2
3
4
我:[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
爱:[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
...
海:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
  • Bag of Words(词袋表示),也称为 Count Vectors,每种词汇在文本中出现的频率。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
corpus = [
'This is the first document.',
'This is the this second second document.',
'And the third one.',
'Is this the first document?'
]

词袋:
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']

词频编码:
[[0 1 1 1 0 0 1 0 1]
[0 1 0 1 0 2 1 0 2]
[1 0 0 0 1 0 1 1 0]
[0 1 1 1 0 0 1 0 1]]
  • N-gram

N-gram与Count Vectors类似,不过加入了相邻单词组合成为新的单词,并进行计数。

如果N取值为2,则句子1和句子2就变为:

1
2
3
> 句子1:我爱 爱北 北京 京天 天安 安门
> 句子2:我喜 喜欢 欢上 上海
>
  • TF-IDF

TF-IDF 分数由两部分组成:第一部分是词语频率(Term Frequency),第二部分是逆文档频率(Inverse Document Frequency)。其中计算语料库中文档总数除以含有该词语的文档数量,然后再取对数就是逆文档频率。

1
2
3
> TF(t)= 该词语在当前文档出现的次数 / 当前文档中词语的总数
> IDF(t)= log_e(文档总数 / 出现该词语的文档总数)
>
  • Word2vec

四、机器学习

1
2
3
4
5
6
7
8
9
10
11
# RidgeClassifier 岭回归分类器
from sklearn.linear_model import RidgeClassifier

# TfidfVectorizer 词向量编码
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
train_test = tfidf.fit_transform(train_df['text'])

clf = RidgeClassifier()
clf.fit(train_test[:10000], train_df['label'].values[:10000])

val_pred = clf.predict(train_test[10000:])

五、深度学习

  • LSTM
  • CNN
  • Transformer