本文语料仍然是上篇所用的搜狗新闻语料,采用中文预训练词向量模型对词进行向量表示。上篇文章将文本分词之后,采用了TF-IDF的特征提取方式对文本进行向量化表示,所产生的文本表示矩阵是一个稀疏矩阵,本篇采用的词向量是一个稠密向量,可以理解为将文本的语义抽象信息嵌入到了一个具体的多维空间中,词之间语义关系可以用向量空间中的范数计算来表示。本文代码在GitHub上。本文博客地址。
1. 读取语料
读取语料与上一篇略有区别,这里读取原始语料,划分训练集和测试集,放在了后面预处理部分。
texts, labels = load_raw_datasets()
label: C000008, len: 1990
label: C000010, len: 1990
label: C000013, len: 1990
label: C000014, len: 1990
label: C000016, len: 1990
label: C000020, len: 1990
label: C000022, len: 1990
label: C000023, len: 1990
label: C000024, len: 1990
Done. 9 total categories, 17910 total docs. cost 224.0759744644165 seconds.
注意到,所有文本读入到texts
列表中,标签信息读入到labels
列表中。每个文本所在目录名称作为分类标签,在创建labels
列表时,代码中做了一步处理,读入目录时的序号存入labels
列表中(第一个标签为0,第二个标签为1,依次类推),后面在使用keras对文本进行预处理的过程中,将调用to_categorical
将整数类别标签转为向量分类编码,这是为了使用分类交叉熵损失函数categorical_crossentropy
。这里可以了解一下关于各类统计变量间的区别:Difference between categorical and ordinal variables。
下表是转换后的标签表示:
序号 | 标签 | 名称 | 分类编码 |
---|---|---|---|
0 | C000008 | Finance | [1, 0, 0, 0, 0, 0, 0, 0, 0] |
1 | C000010 | IT | [0, 1, 0, 0, 0, 0, 0, 0, 0] |
2 | C000013 | Health | [0, 0, 1, 0, 0, 0, 0, 0, 0] |
3 | C000014 | Sports | [0, 0, 0, 1, 0, 0, 0, 0, 0] |
4 | C000016 | Travel | [0, 0, 0, 0, 1, 0, 0, 0, 0] |
5 | C000020 | Education | [0, 0, 0, 0, 0, 1, 0, 0, 0] |
6 | C000022 | Recruit | [0, 0, 0, 0, 0, 0, 1, 0, 0] |
7 | C000023 | Culture | [0, 0, 0, 0, 0, 0, 0, 1, 0] |
8 | C000024 | Military | [0, 0, 0, 0, 0, 0, 0, 0, 1] |
分类编码其实就是one-hot编码,可以用代码解释一下这个转换过程:
def to_one_hot(labels):
one_hot = np.zeros((len(labels), len(labels)))
for i, label in enumerate(labels):
one_hot[i, label] = 1.
return one_hot
print(to_one_hot([0,1,2,3,4,5,6,7,8]))
在keras有内置函数
from keras.utils import to_categorical
print(to_categorical([0,1,2,3,4,5,6,7,8]))
如果想要将向量分类编码转回整数类别标签,可以用numpy
中的argmax
函数:
from numpy import argmax
argmax(labels[0])
2. 加载预训练词向量模型
解压之后的中文预训练词向量模型的文件格式是文本文件,首行只有两个空格隔开的数字:词的个数和词向量的维度,从第二行开始格式为:词 数字1 数字2 …… 数字300,形式如下:
364180 300
人民文学出版社 0.003146 0.582671 0.049029 -0.312803 0.522986 0.026432 -0.097115 0.194231 -0.362708 …
…
# 读取预训练模型
import numpy as np
embeddings_index = {
}
with open('Embedding/sgns.sogou.word') as f:
num, embedding_dim = f.readline().split()
for line in f:
values = line.split()
word = values[0]
coefs = np.asarray(values[1:], dtype='float32')
embeddings_index[word] = coefs
print('Found %s word vectors, dimension %s' % (len(embeddings_index), embedding_dim))
Found 364180 word vectors, dimension 300
3. 使用Keras对语料进行处理
在上篇文章中,我们使用了TfidfVectorizer,将训练语料转换为TFIDF矩阵,每个向量的长度相同(等于总语料库词汇量的大小)。本文将使用Keras中的Tokenizer对文本进行处理,每个向量等于每个文本的长度,