# 论文原文代码《Neural Machine Translation of Rare Words with Subword Units | Byte Pair Encoding》
import re, collections
def get_stats(vocab):
pairs = collections.defaultdict(int) # defaultdict还可以被用来计数,将default_factory设为int即可
for word, freq in vocab.items():
symbols = word.split()
for i in range(len(symbols) - 1):
pairs[symbols[i], symbols[i + 1]] += freq
return pairs
def merge_vocab(pair, v_in):
v_out = {}
bigram = re.escape(' '.join(pair))
p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)') #re.complie 生成正则表达式对象
for word in v_in:
w_out = p.sub(''.join(pair), word) #re.sub()实现字符串的替换。对word按照p的pattern替换成pair
v_out[w_out] = v_in[word]
return v_out
# vocab = {
# 'l o w </w>': 5,
# 'l o w e r </w>': 2,
# 'n e w e s t </w>': 6,
# 'w i d e s t </w>': 3
# }
vocab = {
'网 络</w>': 5,
'中 国 网 络</w>': 2,
'网 络 安 全 </w>': 6,
'中 国 安 全 </w>': 3
}
num_merges = 8
for i in range(num_merges):
pairs = get_stats(vocab)
if not pairs:
break
best = max(pairs,key=pairs.get) #max(序列,key)key可以接受1个函数,对key之前的参数进行运算.dict.get返回键值
vocab = merge_vocab(best, vocab)
print(best)
('安', '全')
('安全', '</w>')
('网', '络</w>')
('网', '络')
('网络', '安全</w>')
('中', '国')
('中国', '安全</w>')
('中国', '网络</w>')
# 手动实现实现BPE
import re, collections
def get_vocab(filename):
vocab = collections.defaultdict(int)
with open(filename,'r',encoding='utf-8') as fhand:
for line in fhand:
words = line.strip().split() #1行里的单词
# #strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
# split()通过指定分隔符(默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等)对字符串进行切片。
for word in words:
vocab[' '.join(list(word))+' </w>']+=1
return vocab
def get_stats(vocab):
pairs = collections.defaultdict(int)
for word, freq in vocab.items():
symbols = word.split()
for i in range(len(symbols)-1):
pairs[symbols[i],symbols[i+1]] += freq
return pairs
def merge_vocab(pair, v_in):
v_out = {}
bigram = re.escape(' '.join(pair))
p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)')
for word in v_in:
w_out = p.sub(''.join(pair), word)
v_out[w_out] = v_in[word]
return v_out
def get_tokens(vocab):
'''获取原始token'''
tokens = collections.defaultdict(int)
for word, freq in vocab.items():
word_tokens = word.split()
for token in word_tokens:
tokens[token] += freq
return tokens
vocab = get_vocab('pg16457.txt')
# vocab = {'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w e s t </w>': 6, 'w i d e s t </w>': 3}
# vocab = {
# '网 络</w>': 5,
# '中 国 网 络</w>': 2,
# '网 络 安 全 </w>': 6,
# '中 国 安 全 </w>': 3
# }
print('==========')
print('Tokens Before BPE')
tokens = get_tokens(vocab)
print('Tokens: {}'.format(tokens))
print('Number of tokens: {}'.format(len(tokens)))
print('==========')
num_merges = 10
for i in range(num_merges):
pairs = get_stats(vocab)
if not pairs:
break
best = max(pairs, key=pairs.get)
vocab = merge_vocab(best, vocab)
print('Iter: {}'.format(i))
print('Best pair: {}'.format(best))
tokens = get_tokens(vocab)
print('Tokens: {}'.format(tokens))
print('Number of tokens: {}'.format(len(tokens)))
print('==========')
==========
Tokens Before BPE
Tokens: defaultdict(<class 'int'>, {'\ufeff': 1, 'T': 4, 'h': 15, 'e': 59, '</w>': 267, 'P': 2, 'r': 24, 'o': 36, 'j': 2, 'c': 7, 't': 35, 'G': 2, 'u': 16, 'n': 29, 'b': 4, 'g': 15, 'E': 4, 'B': 4, 'k': 9, 'f': 4, 'A': 6, 'l': 23, 'd': 8, 'M': 2, ',': 3, 'y': 6, 'J': 2, 's': 23, 'V': 2, 'i': 26, 'a': 27, 'w': 9, 'm': 3, 'v': 2, '.': 3, 'Y': 1, 'p': 11, '-': 1, 'L': 2, ':': 5, 'R': 2, 'D': 1, '6': 2, '2': 3, '0': 6, '5': 2, '[': 1, '#': 1, '1': 5, '4': 1, '7': 1, ']': 1, 'I': 5, '!': 5, '预': 2, '计': 2, '菲': 2, '利': 6, '佩': 1, '·': 4, '库': 4, '蒂': 4, '尼': 4, '奥': 4, '将': 5, '签': 2, '署': 2, '一': 6, '份': 2, '为': 3, '期': 4, '四': 4, '年': 4, '半': 2, '的': 12, '新': 2, '协': 1, '议': 1, '。': 12, '普': 1, '合': 3, '同': 3, '物': 2, '浦': 2, '中': 4, '场': 2, '核': 1, '心': 1, '目': 1, '前': 1, '于': 2, '8': 2, '到': 4, '这': 1, '位': 1, '球': 1, '员': 1, '布': 2, '伦': 1, '丹': 1, '罗': 2, '杰': 2, '斯': 2, '对': 6, '阵': 2, '切': 2, '尔': 2, '西': 2, '表': 2, '现': 2, '感': 2, '高': 2, '兴': 2, '兰': 1, '登': 1, '德': 6, '国': 4, '人': 3, '在': 2, '加': 3, '时': 2, '赛': 6, '以': 2, '比': 2, '击': 4, '败': 4, '阿': 2, '根': 2, '廷': 2, ',': 4, '第': 4, '次': 6, '举': 2, '起': 2, '奖': 2, '杯': 8, '队': 1, '他': 2, '是': 2, '个': 6, '全': 2, '职': 2, '安': 2, '慰': 2, '被': 2, '手': 2, '七': 4, '甲': 2, '冠': 4, '军': 4, '、': 2, '两': 2, '联': 4, '和': 2, '增': 2, '添': 1, '了': 1, '世': 2, '界': 2, '胜': 2, '至': 1})
Number of tokens: 161
==========
Iter: 0
Best pair: ('e', '</w>')
Tokens: defaultdict(<class 'int'>, {'\ufeff': 1, 'T': 4, 'h': 15, 'e</w>': 21, 'P': 2, 'r': 24, 'o': 36, 'j': 2, 'e': 38, 'c': 7, 't': 35, '</w>': 246, 'G': 2, 'u': 16, 'n': 29, 'b': 4, 'g': 15, 'E': 4, 'B': 4, 'k': 9, 'f': 4, 'A': 6, 'l': 23, 'd': 8, 'M': 2, ',': 3, 'y': 6, 'J': 2, 's': 23, 'V': 2, 'i': 26, 'a': 27, 'w': 9, 'm': 3, 'v': 2, '.': 3, 'Y': 1, 'p': 11, '-': 1, 'L': 2, ':': 5, 'R': 2, 'D': 1, '6': 2, '2': 3, '0': 6, '5': 2, '[': 1, '#': 1, '1': 5, '4': 1, '7': 1, ']': 1, 'I': 5, '!': 5, '预': 2, '计': 2, '菲': 2, '利': 6, '佩': 1, '·': 4, '库': 4, '蒂': 4, '尼': 4, '奥': 4, '将': 5, '签': 2, '署': 2, '一': 6, '份': 2, '为': 3, '期': 4, '四': 4, '年': 4, '半': 2, '的': 12, '新': 2, '协': 1, '议': 1, '。': 12, '普': 1, '合': 3, '同': 3, '物': 2, '浦': 2, '中': 4, '场': 2, '核': 1, '心': 1, '目': 1, '前': 1, '于': 2, '8': 2, '到': 4, '这': 1, '位': 1, '球': 1, '员': 1, '布': 2, '伦': 1, '丹': 1, '罗': 2, '杰': 2, '斯': 2, '对': 6, '阵': 2, '切': 2, '尔': 2, '西': 2, '表': 2, '现': 2, '感': 2, '高': 2, '兴': 2, '兰': 1, '登': 1, '德': 6, '国': 4, '人': 3, '在': 2, '加': 3, '时': 2, '赛': 6, '以': 2, '比': 2, '击': 4, '败': 4, '阿': 2, '根': 2, '廷': 2, ',': 4, '第': 4, '次': 6, '举': 2, '起': 2, '奖': 2, '杯': 8, '队': 1, '他': 2, '是': 2, '个': 6, '全': 2, '职': 2, '安': 2, '慰': 2, '被': 2, '手': 2, '七': 4, '甲': 2, '冠': 4, '军': 4, '、': 2, '两': 2, '联': 4, '和': 2, '增': 2, '添': 1, '了': 1, '世': 2, '界': 2, '胜': 2, '至': 1})
Number of tokens: 162
==========
Iter: 1
Best pair: ('的', '</w>')
Tokens: defaultdict(<class 'int'>, {'\ufeff': 1, 'T': 4, 'h': 15, 'e</w>': 21, 'P': 2, 'r': 24, 'o': 36, 'j': 2, 'e': 38, 'c': 7, 't': 35, '</w>': 234, 'G': 2, 'u': 16, 'n': 29, 'b': 4, 'g': 15, 'E': 4, 'B': 4, 'k': 9, 'f': 4, 'A': 6, 'l': 23, 'd': 8, 'M': 2, ',': 3, 'y': 6, 'J': 2, 's': 23, 'V': 2, 'i': 26, 'a': 27, 'w': 9, 'm': 3, 'v': 2, '.': 3, 'Y': 1, 'p': 11, '-': 1, 'L': 2, ':': 5, 'R': 2, 'D': 1, '6': 2, '2': 3, '0': 6, '5': 2, '[': 1, '#': 1, '1': 5, '4': 1, '7': 1, ']': 1, 'I': 5, '!': 5, '预': 2, '计': 2, '菲': 2, '利': 6, '佩': 1, '·': 4, '库': 4, '蒂': 4, '尼': 4, '奥': 4, '将': 5, '签': 2, '署': 2, '一': 6, '份': 2, '为': 3, '期': 4, '四': 4, '年': 4, '半': 2, '的</w>': 12, '新': 2, '协': 1, '议': 1, '。': 12, '普': 1, '合': 3, '同': 3, '物': 2, '浦': 2, '中': 4, '场': 2, '核': 1, '心': 1, '目': 1, '前': 1, '于': 2, '8': 2, '到': 4, '这': 1, '位': 1, '球': 1, '员': 1, '布': 2, '伦': 1, '丹': 1, '罗': 2, '杰': 2, '斯': 2, '对': 6, '阵': 2, '切': 2, '尔': 2, '西': 2, '表': 2, '现': 2, '感': 2, '高': 2, '兴': 2, '兰': 1, '登': 1, '德': 6, '国': 4, '人': 3, '在': 2, '加': 3, '时': 2, '赛': 6, '以': 2, '比': 2, '击': 4, '败': 4, '阿': 2, '根': 2, '廷': 2, ',': 4, '第': 4, '次': 6, '举': 2, '起': 2, '奖': 2, '杯': 8, '队': 1, '他': 2, '是': 2, '个': 6, '全': 2, '职': 2, '安': 2, '慰': 2, '被': 2, '手': 2, '七': 4, '甲': 2, '冠': 4, '军': 4, '、': 2, '两': 2, '联': 4, '和': 2, '增': 2, '添': 1, '了': 1, '世': 2, '界': 2, '胜': 2, '至': 1})
Number of tokens: 162
==========
Iter: 2
Best pair: ('。', '</w>')
Tokens: defaultdict(<class 'int'>, {'\ufeff': 1, 'T': 4, 'h': 15, 'e</w>': 21, 'P': 2, 'r': 24, 'o': 36, 'j': 2, 'e': 38, 'c': 7, 't': 35, '</w>': 222, 'G': 2, 'u': 16, 'n': 29, 'b': 4, 'g': 15, 'E': 4, 'B': 4, 'k': 9, 'f': 4, 'A': 6, 'l': 23, 'd': 8, 'M': 2, ',': 3, 'y': 6, 'J': 2, 's': 23, 'V': 2, 'i': 26, 'a': 27, 'w': 9, 'm': 3, 'v': 2, '.': 3, 'Y': 1, 'p': 11, '-': 1, 'L': 2, ':': 5, 'R': 2, 'D': 1, '6': 2, '2': 3, '0': 6, '5': 2, '[': 1, '#': 1, '1': 5, '4': 1, '7': 1, ']': 1, 'I': 5, '!': 5, '预': 2, '计': 2, '菲': 2, '利': 6, '佩': 1, '·': 4, '库': 4, '蒂': 4, '尼': 4, '奥': 4, '将': 5, '签': 2, '署': 2, '一': 6, '份': 2, '为': 3, '期': 4, '四': 4, '年': 4, '半': 2, '的</w>': 12, '新': 2, '协': 1, '议': 1, '。</w>': 12, '普': 1, '合': 3, '同': 3, '物': 2, '浦': 2, '中': 4, '场': 2, '核': 1, '心': 1, '目': 1, '前': 1, '于': 2, '8': 2, '到': 4, '这': 1, '位': 1, '球': 1, '员': 1, '布': 2, '伦': 1, '丹': 1, '罗': 2, '杰': 2, '斯': 2, '对': 6, '阵': 2, '切': 2, '尔': 2, '西': 2, '表': 2, '现': 2, '感': 2, '高': 2, '兴': 2, '兰': 1, '登': 1, '德': 6, '国': 4, '人': 3, '在': 2, '加': 3, '时': 2, '赛': 6, '以': 2, '比': 2, '击': 4, '败': 4, '阿': 2, '根': 2, '廷': 2, ',': 4, '第': 4, '次': 6, '举': 2, '起': 2, '奖': 2, '杯': 8, '队': 1, '他': 2, '是': 2, '个': 6, '全': 2, '职': 2, '安': 2, '慰': 2, '被': 2, '手': 2, '七': 4, '甲': 2, '冠': 4, '军': 4, '、': 2, '两': 2, '联': 4, '和': 2, '增': 2, '添': 1, '了': 1, '世': 2, '界': 2, '胜': 2, '至': 1})
Number of tokens: 162
==========
Iter: 3
Best pair: ('t', 'h')
Tokens: defaultdict(<class 'int'>, {'\ufeff': 1, 'T': 4, 'h': 5, 'e</w>': 21, 'P': 2, 'r': 24, 'o': 36, 'j': 2, 'e': 38, 'c': 7, 't': 25, '</w>': 222, 'G': 2, 'u': 16, 'n': 29, 'b': 4, 'g': 15, 'E': 4, 'B': 4, 'k': 9, 'f': 4, 'A': 6, 'l': 23, 'd': 8, 'th': 10, 'M': 2, ',': 3, 'y': 6, 'J': 2, 's': 23, 'V': 2, 'i': 26, 'a': 27, 'w': 9, 'm': 3, 'v': 2, '.': 3, 'Y': 1, 'p': 11, '-': 1, 'L': 2, ':': 5, 'R': 2, 'D': 1, '6': 2, '2': 3, '0': 6, '5': 2, '[': 1, '#': 1, '1': 5, '4': 1, '7': 1, ']': 1, 'I': 5, '!': 5, '预': 2, '计': 2, '菲': 2, '利': 6, '佩': 1, '·': 4, '库': 4, '蒂': 4, '尼': 4, '奥': 4, '将': 5, '签': 2, '署': 2, '一': 6, '份': 2, '为': 3, '期': 4, '四': 4, '年': 4, '半': 2, '的</w>': 12, '新': 2, '协': 1, '议': 1, '。</w>': 12, '普': 1, '合': 3, '同': 3, '物': 2, '浦': 2, '中': 4, '场': 2, '核': 1, '心': 1, '目': 1, '前': 1, '于': 2, '8': 2, '到': 4, '这': 1, '位': 1, '球': 1, '员': 1, '布': 2, '伦': 1, '丹': 1, '罗': 2, '杰': 2, '斯': 2, '对': 6, '阵': 2, '切': 2, '尔': 2, '西': 2, '表': 2, '现': 2, '感': 2, '高': 2, '兴': 2, '兰': 1, '登': 1, '德': 6, '国': 4, '人': 3, '在': 2, '加': 3, '时': 2, '赛': 6, '以': 2, '比': 2, '击': 4, '败': 4, '阿': 2, '根': 2, '廷': 2, ',': 4, '第': 4, '次': 6, '举': 2, '起': 2, '奖': 2, '杯': 8, '队': 1, '他': 2, '是': 2, '个': 6, '全': 2, '职': 2, '安': 2, '慰': 2, '被': 2, '手': 2, '七': 4, '甲': 2, '冠': 4, '军': 4, '、': 2, '两': 2, '联': 4, '和': 2, '增': 2, '添': 1, '了': 1, '世': 2, '界': 2, '胜': 2, '至': 1})
Number of tokens: 163
==========
Iter: 4
Best pair: ('a', 't')
Tokens: defaultdict(<class 'int'>, {'\ufeff': 1, 'T': 4, 'h': 5, 'e</w>': 21, 'P': 2, 'r': 24, 'o': 36, 'j': 2, 'e': 38, 'c': 7, 't': 15, '</w>': 222, 'G': 2, 'u': 16, 'n': 29, 'b': 4, 'g': 15, 'E': 4, 'B': 4, 'k': 9, 'f': 4, 'A': 6, 'l': 23, 'd': 8, 'th': 10, 'M': 2, ',': 3, 'y': 6, 'J': 2, 's': 23, 'V': 2, 'i': 26, 'a': 17, 'w': 9, 'at': 10, 'm': 3, 'v': 2, '.': 3, 'Y': 1, 'p': 11, '-': 1, 'L': 2, ':': 5, 'R': 2, 'D': 1, '6': 2, '2': 3, '0': 6, '5': 2, '[': 1, '#': 1, '1': 5, '4': 1, '7': 1, ']': 1, 'I': 5, '!': 5, '预': 2, '计': 2, '菲': 2, '利': 6, '佩': 1, '·': 4, '库': 4, '蒂': 4, '尼': 4, '奥': 4, '将': 5, '签': 2, '署': 2, '一': 6, '份': 2, '为': 3, '期': 4, '四': 4, '年': 4, '半': 2, '的</w>': 12, '新': 2, '协': 1, '议': 1, '。</w>': 12, '普': 1, '合': 3, '同': 3, '物': 2, '浦': 2, '中': 4, '场': 2, '核': 1, '心': 1, '目': 1, '前': 1, '于': 2, '8': 2, '到': 4, '这': 1, '位': 1, '球': 1, '员': 1, '布': 2, '伦': 1, '丹': 1, '罗': 2, '杰': 2, '斯': 2, '对': 6, '阵': 2, '切': 2, '尔': 2, '西': 2, '表': 2, '现': 2, '感': 2, '高': 2, '兴': 2, '兰': 1, '登': 1, '德': 6, '国': 4, '人': 3, '在': 2, '加': 3, '时': 2, '赛': 6, '以': 2, '比': 2, '击': 4, '败': 4, '阿': 2, '根': 2, '廷': 2, ',': 4, '第': 4, '次': 6, '举': 2, '起': 2, '奖': 2, '杯': 8, '队': 1, '他': 2, '是': 2, '个': 6, '全': 2, '职': 2, '安': 2, '慰': 2, '被': 2, '手': 2, '七': 4, '甲': 2, '冠': 4, '军': 4, '、': 2, '两': 2, '联': 4, '和': 2, '增': 2, '添': 1, '了': 1, '世': 2, '界': 2, '胜': 2, '至': 1})
Number of tokens: 164
==========
。。。。。。。
# BPE编码 没有保留初始的vovab,当num_merges过大时,初始的token将都会消失,英文中文都得用词. 输入时,每个单词后面都要加</w>
'''
在之前的算法中,我们已经得到了 subword 的词表,对该词表按照字符个数由多到少排序。
编码时,对于每个单词,遍历排好序的子词词表寻找是否有 token 是当前单词的子字符串,如果有,则该 token 是表示单词的 tokens 之一
我们从最长的 token 迭代到最短的 token,尝试将每个单词中的子字符串替换为 token。
最终,我们将迭代所有 tokens,并将所有子字符串替换为 tokens。
如果仍然有子字符串没被替换但所有 token 都已迭代完毕,则将剩余的子词替换为特殊 token,如 <unk>
'''
import re, collections
def get_vocab(filename):
vocab = collections.defaultdict(int)
with open(filename, 'r', encoding='utf-8') as fhand:
for line in fhand:
words = line.strip().split()
for word in words:
vocab[' '.join(list(word)) + ' </w>'] += 1
return vocab
def get_stats(vocab):
pairs = collections.defaultdict(int)
for word, freq in vocab.items():
symbols = word.split()
for i in range(len(symbols)-1):
pairs[symbols[i],symbols[i+1]] += freq
return pairs
def merge_vocab(pair, v_in):
v_out = {}
bigram = re.escape(' '.join(pair))
p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)')
for word in v_in:
w_out = p.sub(''.join(pair), word)
v_out[w_out] = v_in[word]
return v_out
def get_tokens_from_vocab(vocab):
tokens_frequencies = collections.defaultdict(int)
vocab_tokenization = {}
for word, freq in vocab.items():
word_tokens = word.split()
for token in word_tokens:
tokens_frequencies[token] += freq
vocab_tokenization[''.join(word_tokens)] = word_tokens
return tokens_frequencies, vocab_tokenization
def measure_token_length(token):
if token[-4:] == '</w>': #取倒数4个,即判断token是否以</w>结尾,</w>算1个长度
return len(token[:-4]) + 1
else: #不以token结尾的token
return len(token)
def tokenize_word(string, sorted_tokens, unknown_token='</u>'):
if string == '':
return []
if sorted_tokens == []:
return [unknown_token]
string_tokens = []
for i in range(len(sorted_tokens)):
token = sorted_tokens[i]
token_reg = re.escape(token.replace('.', '[.]'))
matched_positions = [(m.start(0), m.end(0)) for m in re.finditer(token_reg, string)]
if len(matched_positions) == 0:
continue
substring_end_positions = [matched_position[0] for matched_position in matched_positions]
substring_start_position = 0
for substring_end_position in substring_end_positions:
substring = string[substring_start_position:substring_end_position]
string_tokens += tokenize_word(string=substring, sorted_tokens=sorted_tokens[i+1:], unknown_token=unknown_token)
string_tokens += [token]
substring_start_position = substring_end_position + len(token)
remaining_substring = string[substring_start_position:]
string_tokens += tokenize_word(string=remaining_substring, sorted_tokens=sorted_tokens[i+1:], unknown_token=unknown_token)
break
return string_tokens
vocab1 = get_vocab('pg16457.txt')
print('==========')
print('Tokens Before BPE')
tokens_frequencies, vocab_tokenization = get_tokens_from_vocab(vocab)
print('All tokens: {}'.format(tokens_frequencies.keys()))
print('Number of tokens: {}'.format(len(tokens_frequencies.keys())))
print('==========')
#### 编码
num_merges = 600
vocab=vocab1
for i in range(num_merges):
pairs = get_stats(vocab)
if not pairs:
break
best = max(pairs,key=pairs.get)
vocab = merge_vocab(best,vocab)
print('Iter: {}'.format(i))
print('Best pair: {}'.format(best))
tokens_frequencies,vocab_tokenization = get_tokens_from_vocab(vocab)
print('Number of tokens:{}'.format(len(tokens_frequencies.keys())))
print('==========')
def mer_ini_vovab(v_init,v_aft):
'''加上最初的vocab'''
v_out= {}
for word in v_init:
v_out[word] = v_init[word]
for word in v_aft:
v_out[word] = v_aft[word]
return v_out
vocab2 = mer_ini_vovab(vocab1,vocab)
tokens_frequencies,vocab_tokenization = get_tokens_from_vocab(vocab2)
print('Number of tokens:{}'.format(len(tokens_frequencies.keys())))
==========
Tokens Before BPE
All tokens: dict_keys(['\ufeff', 'T', 'h', 'e</w>', 'P', 'r', 'o', 'j', 'e', 'c', 't</w>', 'G', 'u', 't', 'n', 'b', 'er', 'g</w>', 'E', 'B', 'k', '</w>', 'f', 'A', 'l', 'd', 'th', 'M', ',', 'y', 'J', 'le', 's', 'V', 'i', 'a', 'w', 'at', 'm', 'v', '.', 'Y', 'p', 'g', '-', 'L', ':', 'R', 'D', '6', '2', '0', '5', '[', '#', '1', '4', '7', ']', 'I', '!', '预', '计', '菲', '利', '佩', '·', '库', '蒂', '尼', '奥', '将', '签', '署', '一', '份', '为', '期', '四', '年', '半', '的</w>', '新', '协', '议', '。</w>', '普', '合', '同', '物', '浦', '中', '场', '核', '心', '目', '前', '于', '8', '到', '这', '位', '球', '员', '布', '伦', '丹', '罗', '杰', '斯', '对', '阵', '切', '尔', '西', '表', '现', '感', '高', '兴', '兰', '登', '德', '国', '人', '在', '加', '时', '赛', '以', '比', '击', '败', '阿', '根', '廷', ',', '第', '次', '举', '起', '奖', '杯</w>', '队', '他', '是', '个', '全', '职', '安', '慰', '被', '手', '七', '甲', '冠', '军', '、', '两', '联', '和', '增', '添', '了', '世', '界', '胜', '至'])
Number of tokens: 168
==========
Iter: 0
Best pair: ('e', '</w>')
Number of tokens:162
==========
Iter: 1
Best pair: ('的', '</w>')
Number of tokens:162
==========
Iter: 2
Best pair: ('。', '</w>')
Number of tokens:162
==========
Iter: 3
Best pair: ('t', 'h')
Number of tokens:163
==========
Iter: 4
Best pair: ('a', 't')
Number of tokens:164
==========
Iter: 323
Best pair: ('核心', '</w>')
Number of tokens:151
==========
Iter: 324
Best pair: ('目', '前')
Number of tokens:150
==========
Iter: 325
Best pair: ('目前', '</w>')
Number of tokens:150
==========
Iter: 326
Best pair: ('这', '位')
Number of tokens:149
==========
Iter: 327
Best pair: ('这位', '</w>')
Number of tokens:149
==========
Iter: 328
Best pair: ('球', '员')
Number of tokens:148
==========
Iter: 329
Best pair: ('球员', '</w>')
Number of tokens:148
==========
Iter: 330
Best pair: ('布', '伦')
Number of tokens:148
==========
Iter: 331
Best pair: ('布伦', '丹')
Number of tokens:147
==========
Iter: 332
Best pair: ('布伦丹', '</w>')
Number of tokens:147
==========
Iter: 333
Best pair: ('布', '兰')
Number of tokens:146
==========
Iter: 334
Best pair: ('布兰', '登')
Number of tokens:145
==========
Iter: 335
Best pair: ('布兰登', '</w>')
Number of tokens:145
==========
Iter: 336
Best pair: ('德国', '人</w>')
Number of tokens:146
==========
Iter: 337
Best pair: ('德国', '队')
Number of tokens:145
==========
Iter: 338
Best pair: ('德国队', '</w>')
Number of tokens:145
==========
Iter: 339
Best pair: ('为', '</w>')
Number of tokens:145
==========
Iter: 340
Best pair: ('两', '个</w>')
Number of tokens:145
==========
Iter: 341
Best pair: ('增', '添')
Number of tokens:145
==========
Iter: 342
Best pair: ('增添', '</w>')
Number of tokens:145
==========
Iter: 343
Best pair: ('了', '</w>')
Number of tokens:145
==========
Iter: 344
Best pair: ('增', '加')
Number of tokens:144
==========
Iter: 345
Best pair: ('增加', '</w>')
Number of tokens:144
==========
Iter: 346
Best pair: ('至', '</w>')
Number of tokens:143
==========
Iter: 347
Best pair: ('两', '次</w>')
Number of tokens:143
==========
Iter: 348
Best pair: ('一', '次</w>')
Number of tokens:142
==========
Number of tokens:303
# Let's check how tokenization will be for a known word
word_given_known = 'Scientists</w>have</w>known</w>for</w>years</w>that animals</w>'
word_given_unknown = '在</w>一篇</w>新</w>的</w>《</w>跟单</w>汇票</w>·</w>热诺</w>维斯</w>》</w>中 '
# 按token长度排序
sorted_tokens_tuple = sorted(tokens_frequencies.items(), key=lambda item: (measure_token_length(item[0]), item[1]), reverse=True)
sorted_tokens = [token for (token, freq) in sorted_tokens_tuple]
def tokenize_unkown_word(word_given):
print('Tokenizing word: {}...'.format(word_given))
if word_given in vocab_tokenization:
print('Tokenization is of the known word:')
print(vocab_tokenization[word_given])
print('Tokenization treating the known word as unknown:')
print(tokenize_word(string=word_given, sorted_tokens=sorted_tokens, unknown_token='</u>'))
else:
print('Tokenizating of the unknown word:')
print(tokenize_word(string=word_given, sorted_tokens=sorted_tokens, unknown_token='</u>'))
print('==========')
tokenize_unkown_word(word_given_known)
tokenize_unkown_word(word_given_unknown)
Tokenizing word: Scientists</w>have</w>known</w>for</w>years</w>that animals</w>...
Tokenizating of the unknown word:
['c', 'i', 'e', 'n', 't', 'i', 's', 't', 's', '</w>', 'h', 'a', 'v', 'e', '</w>', 'k', 'n', 'o', 'w', 'n', '</w>', 'for</w>', 'y', 'e', 'a', 'r', 's', '</w>', 't', 'h', 'a', 't', 'a', 'n', 'i', 'm', 'a', 'l', 's', '</w>']
==========
Tokenizing word: defaultdict(<class 'int'>, {'艺 术 总 监 </w>': 2, '托 马 斯 </w>': 40, '· </w>': 7206, '朱 连 恩 </w>': 1, '“ </w>': 1788, '从 </w>': 645, '混 乱 </w>': 22, '中 </w>': 1525, '创 造 </w>': 30, '结 构 </w>': 8, '” </w>': 1777, ', <三 届 </w>': 4, '科 斯 蒂 </w>': 4, '根 </w>': 4, 'D V O </w>': 4, '斧 子 </w>': 4, '亨 内 格 </w>': 2, '希 思 </w>': 6, '罗 宾 逊 </w>': 18, '阿 德 莱 </w>': 2, '山 区 </w>': 4, '雄 性 </w>': 8, '考 拉 </w>': 6, '冲 向 </w>': 6, '雌 性 </w>': 4, '扭 打 </w>': 4, '哺 乳 动 物 </w>': 12, '交 配 季 节 </w>': 2, '素 养 </w>': 2, '深 爱 </w>': 2, '悼 念 </w>': 4, '奥 克 兰 </w>': 6, '看 人 </w>': 2, '阿 多 </w>': 2, '韦 厄 </w>': 2, '沃 拉 </w>': 2, '遗 书 </w>': 4, '火 山 口 </w>': 8, '小 径 </w>': 2, '费 拉 </w>': 2, '信 该 </w>': 2, '跌 倒 </w>': 4, '四 十 五 分 钟 </w>': 1, '奶 </w>': 3, '奶 瓶 </w>': 2, '马 德 里 队 </w>': 2, '淘 汰 赛 </w>': 4, '帕 梅 拉 </w>': 4, '柯 兰 </w>': 2, '柯 林 斯 </w>': 4, '县 法 院 </w>': 2, '财 产 法 </w>': 2, '卡 梅 伦 想 </w>': 2, '同 僚 </w>': 2, '达 考 </w>': 2, '拉 普 </w>': 4, '翅 膀 </w>': 6, '迅 猛 </w>': 2, '敏 捷 </w>': 2, '凶 残 </w>': 2, '南 达 科 他 州 </w>': 4, '地 狱 </w>': 2, '溪 组 </w>': 2, '达 科 </w>': 2, '电 子 设 备 </w>': 2, '滤 网 </w>': 2, '西 莉 亚 </w>': 2, '光 线 </w>': 2, '八 小 时 </w>': 2, '于 海 军 </w>': 2, '这 么 久 </w>': 2, '奥 尔 登 </w>': 2, 'M a t t h e w </w>': 2, 'B r a y </w>': 2, '嗑 </w>': 2, '药 </w>': 6, '人 行 道 </w>': 6, '碳 纤 维 </w>': 2, '小 休 </w>': 2, '弗 洛 伦 斯 </w>': 4, '吉 朗 </w>': 2, '抱 负 </w>': 2, '持 球 </w>': 2, '洞 穴 </w>': 12, '约 翰 斯 顿 </w>': 4, '人 质 危 机 </w>': 2, '东 北 部 </w>': 2, '巴 达 赫 尚 </w>': 2, '长 征 </w>': 2, '山 洞 </w>': 6, '............... '德 利 布 </w>': 2, 'C M </w>': 2, '朋 克 </w>': 2, '真 名 </w>': 2, '不 利 </w>': 2, '成 龙 </w>': 2, '梅 楚 忠 </w>': 2, '玛 丽 安 </w>': 2, '王 和 钟 </w>': 2, '担 当 </w>': 2, '客 座 </w>': 2, '投 </w>': 2, '做 爱 时 </w>': 2, '更 改 </w>': 2, '柯 利 </w>': 2, '你 们 </w>': 2, '0 4 6 </w>': 2, '赠 款 </w>': 2, '1 9 7 9 </w>': 2, '科 波 </w>': 2, '拉 未 </w>': 2, '启 示 录 </w>': 2, '坎 皮 恩 </w>': 2, '钢 琴 </w>': 2, '金 棕 榈 奖 </w>': 2, '低 俗 小 说 </w>': 2, '塔 伦 </w>': 2, '萨 芬 娜 </w>': 2, '可 悲 </w>': 2, '奖 池 </w>': 2, '挣 得 </w>': 2, '人 患 </w>': 2, '4 4 % </w>': 2, '贫 困 县 </w>': 1, '发 病 率 </w>': 2, '贫 困 地 区 </w>': 1, '普 赖 尔 </w>': 2, '拆 毁 </w>': 2, '吹 </w>': 2, '情 绪 反 应 </w>': 2})...
ubword-nmt的使用
英文预处理要将所有大写字母改为小写字母 ;将英文句尾结束符与句尾最后一个单词用空格分开
获取corpus.bpe这个子词词表和 vocab.en,vocab.de的双语词典(里面是这两种语言的子词及其出现的频率)
word-nmt learn-joint-bpe-and-vocab --input source.txt target.txt -s 32000 -o corpus.bpe --write-vocabulary vocab.en vocab.de
接下来我们使用以下命令来对双语的语料进行subword切分处理,EN2CHtest.bpr.txt 是bep分词后的,‘@@ ’作为subwords内部的分隔符
subword-nmt apply-bpe -c corpus.bpe --vocabulary vocab.en --vocabulary-threshold 50 <EN2CHtest.txt> EN2CHtest.bpr.txt
解码,在linux服务器上 。 sed's/旧字符串/新字符串/g' 文件名
sed -r 's/(@@ )|(@@ ?$)//g' EN2CHtest.bpr.txt > 1.txt
collections----容器数据类型介绍 &re
# collections----容器数据类型介绍
import collections
## collections模块包含了除list、dict、和tuple之外的容器数据类型,如counter、defaultdict、deque、namedtuple、orderdict。
def use_counter():
'''Counter : 一个简单的计数器,字典形式{‘key’:key出现的次数,...},统计字符出现的个数.'''
s = 'abbcccdddd'
c = collections.Counter(s)
print('Counter:',s)
c.update('kkkkhhhhaaaa')
print('Counter_update:',c)
print ('Counter_elements:',list(c.elements())) # elements()方法可以返回一个包含所有Counter数据的迭代器
for letter, count in c.most_common(2): # most_common()返回前n个最多的数据,
print ('Counter.most_common(2) %s: %d' % (letter, count))
use_counter()
def use_defaultdict():
'''
defaultdict: 使用dict字典类型时,如果引用的key不存在,就会抛出KeyError。如果希望Key不存在时,返回一个默认值,就可以用defaultdict。
其余操作与dict相同,其第一个参数为default_factory属性提供初始值,默认为None;
defaultdict还可以被用来计数,将default_factory设为int即可
'''
s=[('yellow',1),('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = collections.defaultdict(lambda: 'defaultvalue',s) # 这里的lambda argument_list: expression表示的是一个函数。这个函数叫做lambda函数。
print('defaultdict:',d.items())
print(max(d,key=d.get))
use_defaultdict()
Counter: abbcccdddd
Counter_update: Counter({'a': 5, 'd': 4, 'k': 4, 'h': 4, 'c': 3, 'b': 2})
Counter_elements: ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd', 'd', 'k', 'k', 'k', 'k', 'h', 'h', 'h', 'h']
Counter.most_common(2) a: 5
Counter.most_common(2) d: 4
defaultdict: dict_items([('yellow', 3), ('blue', 4), ('red', 1)])
blue
# re 正则表达式
import re
## re.complie compile 函数用于编译正则表达式。
pattern = re.compile(r'\w+') #匹配字母数字及下划线
## re.sub是re模块重要的组成部分,并且功能也非常强大,主要功能实现正则的替换。
## 定义sub(pattern, repl, string, count=0, flags=0), 对字符串string按照正则表达式pattern,将string的匹配项替换成字符串repl。
result = pattern.sub('**',"(ji) (4) (af),(g^q)")
print('sub_result:',result)
## re.escape() 对特殊字符进行转义
re.escape('www.python.org')
sub_result: (**) (**) (**),(**^**)
'www\\.python\\.org'