构造特征矩阵
- build_vocab(train_dir, vocab_dir, config.vocab_size) 构造词汇表,此时构造的词汇表示字符级的表示。
- words, word_to_id = read_vocab(vocab_dir) 读取上一步存储的词汇表,转换为{词: id}表示。
- x_train, y_train = process_file(train_dir, word_to_id, cat_to_id, config.seq_length) 将数据集从文字转换为固定长度的id序列表示,即构造特征矩阵。
build_vocab过程
- 首先read_file读取相应的文件,然后将每行的label和content分开,记住这步contents.append(list(native_content(content))),将content转为了list(不需要分词,直接采用字符级别特征)。此时返回的data_train结构类似为:[[],[],[]]。
- 然后在build_vocab里面利用一个for循环将all_data.extend(content),all_data结构为[,,,,]。
- 然后利用Counter统计每个字符出现的频率,并且筛选(count_pairs = counter.most_common(vocab_size - 1))(vocab_size - 1的原因是词表中需要添加一个padding字符)。
- 词表存储open_file(vocab_dir, mode=’w’).write(‘\n’.join(words) + ‘\n’),每个词后加一个换行符。
read_vocab过程
- 读取词表
- 转换为词到id的表示。利用dict(zip(words, range(len(words))))。
process_file过程
- 首先read_file读取相应的文件
- 将contents中的每一个文本中的每一个字符转换为相应的id表示。data_id.append([word_to_id[x] for x in contents[i] if x in word_to_id])。到这步你已经得到了类似[[],[],[]]的结构。得出这个结构就ok了。
- 此时我们不需要后面的几行使用keras提供的pad_sequences来将文本pad为固定长度。
一些说明
不管我们构造什么样的特征矩阵,我们最终要得到上述process_file过程中第二步得到的结构(结构整体是一个list,list中的每个元素x也是list,x中的元素是字符id)。因为IMDB英文数据集已经是这种结构,所以我们不需要进行转换。
示例代码是将每篇文档转换为字符id表示的list,我们的要求是转换为词id表示的list。最主要的改动有:
- build_vocab过程,第一步需要分词,统计词出现的频率,然后根据词出现的频率以及停用词表将某些词去掉。
我们要求得到词级别的矩阵化,主要改动有:
- build_vocab过程,第一步需要分词,统计词出现的频率,然后根据词出现的频率以及停用词表将某些词去掉。
- process_file过程的第二部分根据词表中是否出现某个词将我们的文档转换为string类型,以空格隔开词。
- 转换为特征向量。
参考代码如下。
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
if __name__ == "__main__":
count = CountVectorizer()
#定义一个文档数组
docs = np.array([
"The sun is shining",
"The weather is sweet",
"The sun is shining and the weather is sweet"
])
#创建词袋模型的词汇库
bag = count.fit_transform(docs)
#查看词汇的位置,词汇是以字典的形式存储
print(count.vocabulary_)
#{'the': 5, 'sun': 3, 'is': 1, 'shining': 2, 'weather': 6, 'sweet': 4, 'and': 0}
print(bag.toarray())
'''
[[0 1 1 1 0 1 0]
[0 1 0 0 1 1 1]
[1 2 1 1 1 2 1]]