build_vocab方法单词到整数映射

来源:4-26 动手实现RNN-LSTM循环神经网络(三):编写实用方法(中)

慕粉3504785

2018-10-15

老师,您好:
想请问下,build_vocab方法中通过对所有数据排序(key=lambda x: (-x[1], x[0])),排序是按照先对键值即出现次数降序排列,然后对key升序排,单词到整数的映射是通过如下形式:
words, _ = list(zip(*count_pairs))
# 单词到整数的映射
word_to_id = dict(zip(words, range(len(words))))
想问下这样单词是和数字的对应关系是什么意思,没太理解,还是这只是一种自己定义的单词到数字转换方法,单词和单词出现次数不需要对应?谢谢!

写回答

1回答

Oscar

2018-10-16

这个其实就是 Python 的 sorted 方法的使用。

你只要在这句代码

count_pairs = sorted(counter.items(), key=lambda x: (-x[1], x[0]))

后面加上类似这样的日志,即可理解:

count_pairs = sorted(counter.items(), key=lambda x: (-x[1], x[0]))
print("######### count_pairs BEGIN #########")
print(count_pairs)
print("######### count_pairs END #########")

然后你运行 python train.py, 它会输出:

######### count_pairs BEGIN #########
[
('the', 50770), ('<unk>', 45020), ('<eos>', 42068),
('N', 32481), ('of', 24400), ('to', 23638), ('a', 21196), 
('in', 18000), ('and', 17474) ... ## 此处省略很多对
('sim', 1), ('snack-food', 1), ('ssangyong', 1), ('swapo', 1),
('wachter', 1)
]
######### count_pairs END #########]

你可以看到,

the 这个单词在文本里出现频次最多,有 50770 次
<unk> (表示 unknown(未知))出现第二多,有 45020 次
sim 这个单词的出现频次是最少之一,有 1 次

等等。

可以看到这些对(pair)都是按照出现频次降序排列。

因为我们的代码经过 Counter 处理过之后,就从之前的只有单词,变成了 (单词,出现频次数目) 这样一对对的:

# 用 Counter 统计单词出现的次数,为了之后按单词出现次数的多少来排序
counter = collections.Counter(data)

然后 counter 又被传递给 sorted 方法去进行排序,那么根据什么来进行排序呢?就是这里的 key(关键字)这个参数发挥作用的时候了:

key=lambda x: (-x[1], x[0]))

lambda 是一个匿名函数。这里的 x 表示我们给 sorted 方法的输入 counter。优先按照 -x[1] 来排序,如果 -x[1] 相同的情况下,再按照 x[0] 来排序。

你可以看到对于每一个对(pair),例如 ('and', 17474),如果说它是 x,那么它的第一个元素是 x[0],也就是 'and' 这个单词;它的第二个元素是 17474,表示它的出现频次,是 17474 次。

因为如果不加 -x[1] 那个负号,那么就是按照正序排列(从小到大的顺序):1, 2, 3, 4, 5, 6, ... 17474, 18000, 21196, 23638, 24400, 32481, 42068, 45020, 50770

但是加了负号,就变成按照逆序排列了:-50770, -45020, -42068, -32481, -24400, -23638, -21196, -18000, -17474, ... -6, -5, -4, -3, -2, -1

这样就实现了我注释里说的:

# 构造从单词到唯一整数值的映射
# 后面的其他数的整数值按照它们在数据集里出现的次数多少来排序,出现较多的排前面
# 单词 the 出现频次最多,对应整数值是 0
# <unk> 表示 unknown(未知),第二多,整数值为 1

然后,因为 x[0] 表示如果在 -x[1] 相同(也就是出现频次数目相同)时,按照单词本身的字典顺序来排列,比如日志里输出的:

('good', 372), ('used', 372)

这两个单词,good 和 used,它们的输出频次都是 372 次,但 good 排在 used 前面,因为在字母顺序里,g 在 u 前面。

0
1
慕粉3504785
老师,您好,排序这块的问题我都清楚,我不明白的是单词到整数的映射: word_to_id = dict(zip(words, range(len(words)))) words是按照递减排序的words,range(len(words))是从0到len(words)-1的数组,对应出来的字典和之前单词和自己出现次数的对应就不再是相同的匹配关系了。 比如:之前{a:4,b:2,c:3},现在words是[a,c,b],而range(len(words))是[0,1,2],这样获得的dict是{a:0,b:1,c:2},我的理解应该没有错吧?请老师指点,谢谢!
2018-10-18
共1条回复

基于Python玩转人工智能最火框架 TensorFlow应用实践

机器学习入门,打牢TensorFlow框架应用是关键!

2214 学习 · 688 问题

查看课程