阅读理解实战(一)

BIDAF基线模型 【阅读理解实战(一)】基线系统实现
数据集分析 数据集是DuReader,特点是一个问题对应着多篇文章,我们要从多篇文章中抽取出正确的答案。
一条训练数据样式如下:
阅读理解实战(一)
文章图片

预处理 这里使用的是训练好的sgns.wiki.word的词向量
下载地址为sgns.wiki.word
也可以建立词表,随机初始化词向量

def prepare(args): """ checks data, creates the directories, prepare the vocabulary and embeddings 检查数据,创建目录,准备词汇表和嵌入 """ logger = logging.getLogger("brc") logger.info('Checking the data files...') #检查路径是否存在 for data_path in args.train_files + args.dev_files + args.test_files: assert os.path.exists(data_path), '{} file does not exist.'.format(data_path) logger.info('Preparing the directories...') #准备路径,不存在则创建目录 for dir_path in [args.vocab_dir, args.model_dir, args.result_dir, args.summary_dir]: if not os.path.exists(dir_path): os.makedirs(dir_path) #建立词表 logger.info('Building vocabulary...') brc_data = https://www.it610.com/article/BRCDataset(args.max_p_num, args.max_p_len, args.max_q_len, args.train_files, args.dev_files, args.test_files) vocab = Vocab(lower=True) for word in brc_data.word_iter('train'):#将训练集中的问题和文章中的token加入到vocab中 vocab.add(word)unfiltered_vocab_size = vocab.size()#没有过滤的词表大小 vocab.filter_tokens_by_cnt(min_cnt=2) #过滤频次小于2的token filtered_num = unfiltered_vocab_size - vocab.size()#filtered过滤的token 数量 logger.info('After filter {} tokens, the final vocab size is {}'.format(filtered_num, vocab.size())) #经过多少个token的过滤,最后词表的规模是 logger.info('Assigning embeddings...')#构建词向量 ,随机初始化词向量 #vocab.randomly_init_embeddings(args.embed_size) vocab.load_pretrained_embeddings('../data/sgns.wiki.word')logger.info('Saving vocab...') with open(os.path.join(args.vocab_dir, 'vocab.data'), 'wb') as fout:#写入 pickle.dump(vocab, fout)logger.info('Done with preparing!') #准备完成

同时因为加载的wiki第一排显示的是词表大小和维度,所以要注意跳过词表的第一行
def load_pretrained_embeddings(self, embedding_path): """ loads the pretrained embeddings from embedding_path, tokens not in pretrained embeddings will be filtered Args: embedding_path: the path of the pretrained embedding file """ trained_embeddings = {} #字典 with open(embedding_path, 'r') as fin: for i,line in enumerate(fin): if i==0: continue contents = line.strip().split() #split 以空格为分隔符切片 token = contents[0]#.decode('utf8') #contents[0]是token单词 if token not in self.token2id: #若原先训练好的词没有在新建立的词表中,则跳过本次循环,相当于过滤掉原先训练好词表中在训练集没有出现的词 continue trained_embeddings[token] = list(map(float, contents[1:]))#将一组向量转换成float #token对应embedding建立映射 if self.embed_dim is None: self.embed_dim = len(contents) - 1 filtered_tokens = trained_embeddings.keys()#过滤掉后剩余的词 #也就是筛选出训练好的词向量与训练集词表重合的词向量trained_embeddings = {} # rebuild the token x id map重新建立映射 self.token2id = {} self.id2token = {} for token in self.initial_tokens: #向token2id,id2token中增加特殊字符 self.add(token, cnt=0) for token in filtered_tokens:#遍历筛选出的token加入token2id,id2token self.add(token, cnt=0) # load embeddings加载embedding self.embeddings = np.zeros([self.size(), self.embed_dim]) for token in self.token2id.keys(): if token in trained_embeddings: #若token在训练好的trained_embeddings中 self.embeddings[self.get_id(token)] = trained_embeddings[token] #建立该词新ID和embedding的映射

第一步,词表建立完成,准备完成!
阅读理解实战(一)
文章图片

    推荐阅读