1、数据加载如下
with open('data/letters_source.txt', 'r', encoding='utf-8') as f:
source_data = f.read()
with open('data/letters_target.txt', 'r', encoding='utf-8') as f:
target_data = f.read()
源数据souce_data:每行一个单词或字母序列
目标数据target_data:对应source_data每一行对字母排序后的序列
目的:训练数据集实现输出encoder一个单词或序列,输出对字母排序后的序列
2、数据预处理——函数初定义
函数:extract_character_vocab(data)
#首先是数据预处理函数
def extract_character_vocab(data):
special_words = ['' , '' , '' , '' ]
set_words = list(set([character for line in data.split('\n') for character in line]))
int_to_vocab = {idx: word for idx, word in enumerate(special_words + set_words)}
vocab_to_int = {word: idx for idx, word in int_to_vocab.items()}
return int_to_vocab, vocab_to_int
死扣 解读:
special_words = ['' , '' , '' , '' ]
特殊字符的设置,方便后面加入到字符序列
< PAD>: 补全字符。
< EOS>: 解码器端的句子结束标识符。
< UNK>: 低频词或者一些未遇到过的词等。
< GO>: 解码器端的句子起始标识符。
set_words = list(set([character for line in data.split('\n') for character in line]))
.split()
通过指定分隔符为字符串进行切片,不指定第二个num参数的情况下,默认分隔所有
data.split(’\n’)
将数据按照换行符进行切片,返回一个字符串列表
for line in data.split(’\n’)
每次取字符串列表中的一个元素(即一个字符串)保存到line中
for line in data.split(’\n’) for character in line
相当于一个嵌套循环,每次取字符串列表中的一个元素保存到line中,然后每次取line字符串的一个字符保存到character
[character for line in data.split(’\n’) for character in line]
自动追加元素形成一个关于character的列表
set([character for line in data.split(’\n’) for character in line]))
将这个关于character的列表转化为集合(去掉重复的字符,便于后续每个数字对应一个字符,用数字来表示每个字符串)
set_words = list(set([character for line in data.split(’\n’) for character in line]))
将去重复后的集合再次转化为列表,保存在列表set_words中
int_to_vocab = {idx: word for idx, word in enumerate(special_words + set_words)}
enumerate(special_words + set_words)
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列
enumerate(special_words + set_words)
将列表special_words + set_word连接成一个列表,将这个列表组合为一个索引序列
int_to_vocb={idx: word for idx, word in enumerate(special_words + set_words)}
字典解析,每次取出索引序列的一个索引和列表元素内容分别存到idx和word中,自动追加元素形成idx:word的字典
vocab_to_int = {word: idx for idx, word in int_to_vocab.items()}
与上一条代码结构类似,内涵为每次取字典中key:value分别存储在idx,word中,自动追加元素word:idx形成字典vocab_to_int
return int_to_vocab, vocab_to_int
最后函数返回两个字典
int_to_vocab:idx:word(数字:字符)
vocab_to_int:word:idx(字符:数字)
注意,因为中间步骤set集合,所得的字符是无重复的
3、函数调用
# 构造映射表
source_int_to_letter, source_letter_to_int = extract_character_vocab(source_data)
target_int_to_letter, target_letter_to_int = extract_character_vocab(target_data)
# 对字母进行转换
source_int = [[source_letter_to_int.get(letter, source_letter_to_int['' ])
for letter in line] for line in source_data.split('\n')]
target_int = [[target_letter_to_int.get(letter, target_letter_to_int['' ])
for letter in line] + [target_letter_to_int['' ]] for line in target_data.split('\n')]
前两行代码为调用第2部分定义的函数extract_character_vocab(data)产生的结果
source_int_to_letter, source_letter_to_int = extract_character_vocab(source_data)
意义为将source_data补全特殊字符后转化为(数字:字符,字符:数字 )字典分别存储在source_int_to_letter, source_letter_to_int中
target_int_to_letter, target_letter_to_int = extract_character_vocab(target_data)
同理上一条代码,这里将target_data补全特殊字符后转化为(数字:字符,字符:数字 )字典分别存储在target_int_to_letter, target_letter_to_int中
source_int = [[source_letter_to_int.get(letter, source_letter_to_int['' ])
for letter in line] for line in source_data.split('\n')]
表达式比较长,不同于多重循环的列表解析,是包含列表解析的多重循环,建议从后往前看
for line in source_data.split(’\n’)
对数据按照换行符进行切片,返回一个字符串的列表,循环编列列表,每次返回一个字符串赋值给line
for letter in line
第二层循环,遍历上一步得到的line,每次返回一个字符赋值给letter
[source_letter_to_int.get(letter, source_letter_to_int[’< UNK>’]) for letter in line]
将letter的值给表达式source_letter_to_int.get(letter, source_letter_to_int[’’]) 计算,字典的get函数用来返回指定键的值,如果值不在字典中返回默认值,这里每次返回一个字符串中一个字母的value值(数字),这里返回的是一个数字是因为字典source_letter_to_int的key是字母,value是对应的数字,如果没有呢就返回标签UNK对应的数字。这个表达式外面有一个列表的括号[],表示遍历完一个字符串,追加完成一个列表。
整个表达式最外层还有一层列表括号,表示这一个字符串大列表转化为包含若干个字符串小列表的列表。
target_int = [[target_letter_to_int.get(letter, target_letter_to_int['' ])
for letter in line] + [target_letter_to_int['' ]] for line in target_data.split('\n')]
for line in target_data.split(’\n’)]
将数据按照换行符进行切片,循环遍历字符串列表,每次返回一个字符串赋值给line
[target_letter_to_int.get(letter, target_letter_to_int[’< UNK>’] for letter in line]
这里将循环遍历line,每次返回一个字符赋值给letter,然后用letter计算get方法的表达式,这里get方法和上行代码一致,若在target_letter_to_int字典中找到字符对应的数字编码,那么返回value值,如果找不到,返回不常见字符的对应的数字编码
[target_letter_to_int.get(letter, target_letter_to_int[’< UNK>’]) for letter in line] + [target_letter_to_int[‘EOS>’]]
当把每个字符串转化为字典中对应的数字编码时,在每个字符串结尾追加一个结束字符对应的数字编码