Keras分词器 Tokenizer

介绍一下keras的分词器Tokenizer,以及我在上面吃过的亏。

Tokenizer

Tokenizer是一个将文本向量化,转换成序列的类。用来文本处理的分词、嵌入

1
2
3
4
5
6
7
keras.preprocessing.text.Tokenizer(num_words=None, 
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
lower=True,
split=' ',
char_level=False,
oov_token=None,
document_count=0)

参数说明:

  • num_words: 默认是None处理所有字词,但是如果设置成一个整数,那么最后返回的是最常见的、出现频率最高的num_words个字词。一共保留 num_words-1 个词。
  • filters: 过滤一些特殊字符,默认上文的写法就可以了。
  • lower: 是否全部转为小写。
  • split: 分词的分隔符字符串,默认为空格。因为英文分词分隔符就是空格。
  • char_level: 分字。
  • oov_token: if given, it will be added to word_index and used to replace out-of-vocabulary words during text_to_sequence calls

相关的类方法

方法 参数 返回值
fit_on_texts(texts) texts:要用以训练的文本列表 -
texts_to_sequences(texts) texts:待转为序列的文本列表 序列的列表,列表中每个序列对应于一段输入文本
texts_to_sequences_generator(texts) texts:待转为序列的文本列表 本函数是texts_to_sequences的生成器函数版,返回每次调用返回对应于一段输入文本的序列
texts_to_matrix(texts, mode) texts:待向量化的文本列表;mode:‘binary’,‘count’,‘tfidf’,
‘freq’之一,默认为‘binary’
形如(len(texts), nb_words)的numpy array
fit_on_sequences(sequences) sequences:要用以训练的序列列表 -
sequences_to_matrix(sequences) sequences:待向量化的序列列表; mode:同上 返回值:形如(len(sequences), nb_words)的numpy array

属性

  • word_counts: 字典,将单词(字符串)映射为它们在训练期间出现的次数。仅在调用fit_on_texts之后设置。
  • word_docs: 字典,将单词(字符串)映射为它们在训练期间所出现的文档或文本的数量。仅在调用fit_on_texts之后设置。
  • word_index: 字典,将单词(字符串)映射为它们的排名或者索引。仅在调用fit_on_texts之后设置。
  • document_count: 整数。分词器被训练的文档(文本或者序列)数量。仅在调用fit_on_texts或fit_on_sequences之后设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from keras.preprocessing.text import Tokenizer
# Using TensorFlow backend.

# 创建分词器 Tokenizer 对象
tokenizer = Tokenizer()

# text
text = ["今天 北京 下 雨 了", "我 今天 加班"]

# fit_on_texts 方法
tokenizer.fit_on_texts(text)

# word_counts属性
tokenizer.word_counts
# OrderedDict([('今天', 2),
# ('北京', 1),
# ('下', 1),
# ('雨', 1),
# ('了', 2),
# ('我', 1),
# ('加班', 1)])

# word_docs属性
tokenizer.word_docs
# defaultdict(int, {'下': 1, '北京': 1, '今天': 2, '雨': 1, '了': 2, '我': 1, '加班': 1})

# word_index属性
tokenizer.word_index
# {'今天': 1, '了': 2, '北京': 3, '下': 4, '雨': 5, '我': 6, '加班': 7}

# document_count属性
tokenizer.document_count
# 2

需要注意的点是,由于书写习惯,英文文本的单词之间是用空格隔开的,split=' ' 这个参数可以直接对英文文本进行空格分词。但是对中文不行,因此使用 tokenizer.fit_on_texts(text) 时,text如果是英文文本,可以直接 text = ["Today is raining.", "I feel tired today."] ,但是text是中文文本的话,需要先将中文文本分词再作为输入text: text = ["今天 北京 下 雨 了", "我 今天 加班"]

这里就是我踩过的坑了,之前拷代码下来跑的时候,别人用的是英文文本,没问题,但是我的输入是中文文本,导致分词步骤利用空格对中文分词,会将整句话当作一个token,而且是字典里找不到的token,这样会造成大量的相同的嵌入表达和相同的预测分数。

因此,keras的Tokenizer对于英文文档可以做分词+嵌入 两步,对于中文的话,其实只有嵌入这步。

嵌入示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences

# 1. 创建分词器 Tokenizer 对象
tokenizer = Tokenizer() # 里面的参数可以自己根据实际情况更改

# 2. 整理整体语料,中文需空格分词
text = ["今天 北京 下 雨 了", "我 今天 加班"]

# 3. 将Tokenizer拟合语料,生成字典,形成新的tokenizer
tokenizer.fit_on_texts(text)

# 4. 保存tokenizer,避免重复对同一语料进行拟合
import joblib
joblib.dump(tokenizer, save_path)

# 5. 整合需要做嵌入的文本,中文需要空格分词
new_text = ["今天 回家 吃饭", "我 今天 生病 了"]

# 6. 将文本向量化
list_tokenized = tokenizer.text_to_sequence(new_text)

# 7. 生成训练数据的序列
X_train = pad_sequences(list_tokenized, maxlen=200)

写在最后

当遇到一个不错的API,不妨把参数看全,免得栽在一个小参数上。

would you buy me a coffee☕~
0%