当前位置:   article > 正文

d2l 文本预处理textDataset_self.idx_to_token = [''] + reserved_tokens

self.idx_to_token = [''] + reserved_tokens

这一节极其重要,重要到本来是d2l的内容我也要归到pyhon封面,这里面class的操作很多,让我娓娓道来!

目录

1.要实现的函数

2.读取数据集

3.词元化

4.Vocab类

4.1count_corpus(tokens)

4.2class中的各种self

4.2.1 _token_freqs是经过sorted排序后的list

4.2.2 token_to_idx是{token:idx}的字典

4.2.3两大索引to_tokens与原getitem

4.2.4 idx_to_token是所有token按出现次数多到少排列的list

4.2.5其它

5.该函数最终返回的东西:


1.要实现的函数

  整文都是围绕以下这个函数来展开的,因为后续就直接用了。包括返回的Vocab类:

  1. def load_corpus_time_machine(max_tokens=-1): #@save
  2. """返回时光机器数据集的词元索引列表和词表"""
  3. lines = read_time_machine()
  4. tokens = tokenize(lines, 'char')
  5. vocab = Vocab(tokens)
  6. # 因为时光机器数据集中的每个⽂本⾏不⼀定是⼀个句⼦或⼀个段落,
  7. # 所以将所有⽂本⾏展平到⼀个列表中
  8. corpus = [vocab[token] for line in tokens for token in line]
  9. if max_tokens > 0:
  10. corpus = corpus[:max_tokens]
  11. return corpus, vocab
  12. corpus, vocab = d2l.load_corpus_time_machine()
  13. len(corpus), len(vocab)
  14. '''
  15. (170580, 28)
  16. '''

2.读取数据集

 re.sub('[^A-Za-z]+',' ', line).strip().lower()
  re.sub表示将字符串中除了A-Z和a-z之外的所有字符用空格替换
  .strip()表示去掉每一行首尾的换行符、空格、缩进等。注意只有首尾!!
  .lower()表示结果转换为小写

  1. def read_time_machine(): #@save
  2. """将时间机器数据集加载到⽂本⾏的列表中"""
  3. with open(d2l.download('time_machine'), 'r') as f:
  4. lines = f.readlines()
  5. return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]
  6. lines = read_time_machine()
  7. print(f'# ⽂本总⾏数: {len(lines)}')
  8. print(lines[0])
  9. print(lines[10])
  10. '''
  11. # ⽂本总⾏数: 3221
  12. the time machine by h g wells
  13. twinkled and his usually pale face was flushed and animated the
  14. '''

3.词元化

  输入的是原txt中,每一行为元素组成的list(['1','2',...])

 将每个文本序列拆分成词元列表,看下处理代码:

  1. def tokenize(lines, token='word'): #@save
  2. """将⽂本⾏拆分为单词或字符词元"""
  3. if token == 'word':
  4. return [line.split() for line in lines]
  5. elif token == 'char':
  6. return [list(line) for line in lines]
  7. else:
  8. print('错误:未知词元类型:' + token)
  9. tokens = tokenize(lines)
  10. for i in range(11):
  11. print(tokens[i])

看一下最终得到的词元列表是什么:

   以word,输入的是文本所有的行列表,得到的是二维列表,每一行为元素,该元素中包含该行中的每个单词为元素。

  其中注意在char中,有一个list(line)操作:

   对一个字符串使用list('zifuchuan')的时候,会把里面每个字母拆开返回,因为字符串是可迭代对象。

4.Vocab类

先上代码,再逐个讲解:

  1. class Vocab:
  2. """Vocabulary for text."""
  3. def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):
  4. """Defined in :numref:`sec_text_preprocessing`"""
  5. if tokens is None:
  6. tokens = []
  7. if reserved_tokens is None:
  8. reserved_tokens = []
  9. # Sort according to frequencies
  10. counter = count_corpus(tokens)
  11. self._token_freqs = sorted(counter.items(), key=lambda x: x[1],
  12. reverse=True)
  13. # The index for the unknown token is 0
  14. self.idx_to_token = ['<unk>'] + reserved_tokens
  15. self.token_to_idx = {token: idx for idx, token in enumerate(self.idx_to_token)}
  16. for token, freq in self._token_freqs:
  17. if freq < min_freq:
  18. break
  19. if token not in self.token_to_idx:
  20. self.idx_to_token.append(token)
  21. self.token_to_idx[token] = len(self.idx_to_token) - 1
  22. def __len__(self):
  23. return len(self.idx_to_token)
  24. def __getitem__(self, tokens):
  25. if not isinstance(tokens, (list, tuple)):
  26. return self.token_to_idx.get(tokens, self.unk)
  27. return [self.__getitem__(token) for token in tokens]
  28. def to_tokens(self, indices):
  29. if not isinstance(indices, (list, tuple)):
  30. return self.idx_to_token[indices]
  31. return [self.idx_to_token[index] for index in indices]
  32. @property
  33. def unk(self): # Index for the unknown token
  34. return 0
  35. @property
  36. def token_freqs(self): # Index for the unknown token
  37. return self._token_freqs
  38. def count_corpus(tokens): # @save
  39. """统计词元的频率"""
  40. # 这⾥的tokens是1D列表或2D列表
  41. if len(tokens) == 0 or isinstance(tokens[0], list):
  42. # 将词元列表展平成⼀个列表
  43. tokens = [token for line in tokens for token in line]
  44. return collections.Counter(tokens)

4.1count_corpus(tokens)

这里面tokens魔法函数:tokens = [token for line in tokens for token in line],等价于如下命令:

 在外面套一个list相当于先创建一个空list,然后依次将返回的最终元素append到这个空list中

  其中第一个for loop读取2Dlist中的每个元素,即为每一行;第二个for读取的是每一行中的每一个字符,此时这个token表示的是2Dlist中每个元素list里的每一个字符元素,再通过append添加到新创的list中

  对于之后的Counter用处:
  举例来说,如果 tokens = ['apple', 'banana', 'apple', 'orange'],则 collections.Counter(tokens) 的结果为 Counter({'apple': 2, 'banana': 1, 'orange': 1}),表示列表中有 2 个 'apple'、1 个 'banana' 和 1 个 'orange'。在自然语言处理中,collections.Counter() 经常被用于统计单词的出现次数。

  也就是传入所有词的列表(拉成了一维),然后返回一个dict,key为上个list的元素名,对应value为该key的出现次数。

4.2class中的各种self

4.2.1 _token_freqs是经过sorted排序后的list

注意传入sorted是要传入dict,所以源码中对counter进行了.item()处理:

在此可得: .items()是将字典返回一个包含所有(key-value)元组为元素的列表,可用于sorted

  1. vocab.token_freqs
  2. '''
  3. [(' ', 29927),
  4. ('e', 17838),
  5. ('t', 13515),
  6. ('a', 11704),
  7. ('i', 10138),
  8. ...]
  9. '''

4.2.2 token_to_idx是{token:idx}的字典

  1. vocab.token_to_idx
  2. '''
  3. {'<unk>': 0,
  4. ' ': 1,
  5. 'e': 2,
  6. 't': 3,
  7. 'a': 4,
  8. ...]
  9. '''

对应4.2.1说的.item()处理:

items()是将字典返回一个包含所有(key-value)元组为元素的列表

4.2.3两大索引to_tokens与原getitem

to_tokens是传入idx返回token

  1. vocab.to_tokens((0,1,2,3))
  2. '''
  3. ['<unk>', ' ', 'e', 't']
  4. '''

 getitem是传入token返回idx

  1. vocab[('a','b','d')]
  2. '''
  3. [4, 21, 11]
  4. '''

4.2.4 idx_to_token是所有token按出现次数多到少排列的list

  1. vocab.idx_to_token[:10]
  2. '''
  3. ['<unk>', ' ', 'e', 't', 'a', 'i', 'n', 'o', 's', 'h']
  4. '''

4.2.5其它

list里面套两个元素的元组,用两个元素遍历,则会返回元组里面的两个元素!!

5.该函数最终返回的东西:

  返回的是词元索引(将原txt按顺序依次返回索引对应原文内容的idx),还有语料库,可以用to_tokens返回对应索引的token。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/79185
推荐阅读
相关标签
  

闽ICP备14008679号