https://zh.d2l.ai/chapter_recurrent-neural-networks/language-models-and-dataset.html
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | import collections import re from d2l import torch as d2l #@save d2l.DATA_HUB[ 'time_machine' ] = (d2l.DATA_URL + 'timemachine.txt' , '090b5e7e70c295757f55df93cb0a180b9691891a' ) def read_time_machine(): #@save """将时间机器数据集加载到文本行的列表中""" with open (d2l.download( 'time_machine' ), 'r' ) as f: lines = f.readlines() #re.sub('[^A-Za-z]+', ' ', line):将line字符串中的 连续多个非字母的字符 变成 空格 #re.sub('[^A-Za-z]+', ' ', 'I\n') #Out[6]: 'I ' return [re.sub( '[^A-Za-z]+' , ' ' , line).strip().lower() for line in lines] #lines = read_time_machine() #print(f'# 文本总行数: {len(lines)}') #print(lines[0]) #print(lines[10]) def tokenize(lines, token = 'word' ): #@save """将文本行拆分为单词或字符词元""" if token = = 'word' : # 按照单词拆分 return [line.split() for line in lines] elif token = = 'char' : #按照字符拆分 return [ list (line) for line in lines] else : print ( '错误:未知词元类型:' + token) #tokens = tokenize(lines) # for i in range(16): # print("tokens",i,tokens[i]) def count_corpus(tokens): # """统计词元的频率""" # 这里的tokens是1D列表或2D列表 if len (tokens) = = 0 or isinstance (tokens[ 0 ], list ): # 将词元列表展平成一个列表 tokens1 = [] for line in tokens: #print("line",line) for token in line: #print("token",token) tokens1.append(token) tokens = tokens1 #tokens = [token for line in tokens for token in line] #print(tokens.shape) #最主要的作用是计算“可迭代序列”中各个元素(element)的数量 ''' #对字符串作用 temp=Counter('aabbcdeffgg') print(temp) #Counter({'a': 2, 'b': 2, 'f': 2, 'g': 2, 'c': 1, 'd': 1, 'e': 1}) ''' return collections.Counter(tokens) #count_corpus(tokens) #词表 #构建一个字典,通常也叫做词表(vocabulary),用来将字符串类型的词元映射到从开始的数字索引中. # 我们先将训练集中的所有文档合并在一起,对它们的唯一词元进行统计, 得到的统计结果称之为语料(corpus)。 # 然后根据每个唯一词元的出现频率,为其分配一个数字索引。 很少出现的词元通常被移除,这可以降低复杂性。 # 另外,语料库中不存在或已删除的任何词元都将映射到一个特定的未知词元“<unk>”。 # 我们可以选择增加一个列表,用于保存那些被保留的词元, 例如:填充词元(“<pad>”); 序列开始词元(“<bos>”); 序列结束词元 class Vocab: #@save """文本词表""" def __init__( self , tokens = None , min_freq = 0 , reserved_tokens = None ): if tokens is None : tokens = [] if reserved_tokens is None : #reserved_tokens = ["a","b"] reserved_tokens = [] # 按出现频率排序 ''' #对字符串作用 temp=Counter('aabbcdeffgg') print(temp) #Counter({'a': 2, 'b': 2, 'f': 2, 'g': 2, 'c': 1, 'd': 1, 'e': 1}) ''' counter = count_corpus(tokens) print ( "词频统计结果" ,counter) ''' 词频统计结果 Counter({' ': 29927, 'e': 17838, 't': 13515, 'a': 11704, 'i': 10138, 'n': 9917, 'o': 9758, 's': 8486, 'h': 8257, 'r': 7674, 'd': 6337, 'l': 6146, 'm': 4043, 'u': 3805, 'c': 3424, 'f': 3354, 'w': 3225, 'g': 3075, 'y': 2679, 'p': 2427, 'b': 1897, 'v': 1295, 'k': 1087, 'x': 236, 'z': 144, 'j': 97, 'q': 95}) ''' # 排序 已知词汇 reverse=True 从高到低 self ._token_freqs = sorted (counter.items(), key = lambda x: x[ 1 ], reverse = True ) # 未知词元的索引为0 self .idx_to_token = [ '<unk>' ] + reserved_tokens #{'<unk>': 0} #{'<unk>': 0, 'a': 1, 'b': 2} self .token_to_idx = {token: idx for idx, token in enumerate ( self .idx_to_token)} #print(self.token_to_idx ) ''' 1最开头是 未知词元 假设是 词源 idx_to_token['<unk>', ‘a’ ,'b'] 词源ID token_to_idx[0,1,2] 2将文本中统计出来的有效词源 加进去 例如 b1 2-1 剔除小于阈值的 2-2 加入新词源 频率 从高到低 词源 idx_to_token['<unk>', ‘a’ ,'b','b1'] 词源ID token_to_idx[0,1,2,3] ''' # 最开头是 未知词元 假设是 idx_to_token['<unk>', ‘a’ ,'b'] # 将文本中统计出来的有效词源 加进去 例如 b1 # for token, freq in self ._token_freqs: # 从高到低访问 if freq < min_freq: # 剔除小于阈值的词 break if token not in self .token_to_idx: # 未知词汇剔除 # 未知词元 添加 单词进入列表 # '<unk>' a b 加入 d1 self .idx_to_token.append(token) # token_to_idx【'd1'】= 4-1=3 self .token_to_idx[token] = len ( self .idx_to_token) - 1 #从0开始 添加 def __len__( self ): return len ( self .idx_to_token) def __getitem__( self , tokens): if not isinstance (tokens, ( list , tuple )): return self .token_to_idx.get(tokens, self .unk) return [ self .__getitem__(token) for token in tokens] def to_tokens( self , indices): if not isinstance (indices, ( list , tuple )): return self .idx_to_token[indices] return [ self .idx_to_token[index] for index in indices] @property def unk( self ): # 未知词元的索引为0 return 0 @property def token_freqs( self ): return self ._token_freqs # 整合所有功能 def load_corpus_time_machine(max_tokens = - 1 ): #@save """返回时光机器数据集的词元索引列表和词表""" # 1 读取所有文本 逐行存 lines = read_time_machine() # 2 # 2-1将所有行的字母拆出来,汇总到一个列表里面 # 2-2将所有字母,对每一个字母统计词频 tokens = tokenize(lines, 'char' ) # print("tokens",tokens) ''' tokens= [['a', 'b'],['c' 'd'],...] ''' # 3 获取词汇列表 ''' (频率 从高到底 前面是未知词源) 词源 idx_to_token['<unk>', ‘a’ ,'b','b1'] 词源ID token_to_idx[0,1,2,3] ''' vocab = Vocab(tokens) # 因为时光机器数据集中的每个文本行不一定是一个句子或一个段落, # 所以将所有文本行拆分成一个个字符,然后展平到一个列表中 corpus = [] ''' tokens= [['a', 'b'],['c' 'd'],...] ''' for line in tokens: for token in line: corpus.append(vocab[token]) # vocab[token] 字母’x‘的编码ID #corpus = [vocab[token] for line in tokens for token in line] if max_tokens > 0 : corpus = corpus[:max_tokens] #corpus 全文变成单独字符的列表结合 #vocab vocab[token] 字母’x‘的编码ID(非次数 ID就是从高到低按照次数排列到的) 集合 {“a”,1,"b","2",...} return corpus, vocab #===============================测试1 按照 单个字符拆分============================================== #在使用上述函数时,我们将所有功能打包到load_corpus_time_machine函数中, #该函数返回corpus(词元索引列表)和vocab(时光机器语料库的词表)。 ''' 为了简化后面章节中的训练,我们使用字符(而不是单词)实现文本词元化; 时光机器数据集中的每个文本行不一定是一个句子或一个段落,还可能是一个单词,因此返回的corpus仅处理为单个列表,而不是使用多词元列表构成的一个列表。 ''' corpus, vocab = load_corpus_time_machine() #170580 28 一共有corpus 170580个字符,其中重复字符的有vocab 28个(ABCD-FG 28个英文字符) print ( len (corpus), len (vocab)) ''' 词频统计结果 Counter({' ': 29927, 'e': 17838, 't': 13515, 'a': 11704, 'i': 10138, 'n': 9917, 'o': 9758, 's': 8486, 'h': 8257, 'r': 7674, 'd': 6337, 'l': 6146, 'm': 4043, 'u': 3805, 'c': 3424, 'f': 3354, 'w': 3225, 'g': 3075, 'y': 2679, 'p': 2427, 'b': 1897, 'v': 1295, 'k': 1087, 'x': 236, 'z': 144, 'j': 97, 'q': 95}) ''' |
分类:
1_4pytorch
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2017-10-09 智能开关 (2) 发射端软件工程
2017-10-09 智能开关(1)项目总预览