def train_for_epoch(parser, train_data, dev_data, optimizer, loss_func, batch_size): """ Train the neural dependency parser for single epoch. @return dev_UAS (float): Unlabeled Attachment Score (UAS) for dev data """ parser.model.train( ) # Places model in "train" mode, i.e. apply dropout layer n_minibatches = math.ceil(len(train_data) / batch_size) loss_meter = AverageMeter() with tqdm(total=(n_minibatches)) as prog: for i, (train_x, train_y) in enumerate(minibatches(train_data, batch_size)): optimizer.zero_grad() # remove any baggage in the optimizer loss = 0. # store loss for this batch here train_x = torch.from_numpy(train_x).long() train_y = torch.from_numpy(train_y.nonzero()[1]).long() output_y = parser.model(train_x) loss = loss_func(output_y, train_y) loss.backward() optimizer.step() prog.update(1) loss_meter.update(loss.item()) print("Average Train Loss: {}".format(loss_meter.avg)) print("Evaluating on dev set", ) parser.model.eval( ) # Places model in "eval" mode, i.e. don't apply dropout layer dev_UAS = parser.evaluate(dev_data) print("- dev UAS: {:.2f}".format(dev_UAS * 100.0)) return dev_UAS
def learn(self, dataset, n_iters=100): train_data = self.create_instances([{ 'word': x.sentence, 'head': x.head } for x in dataset]) batch_size = 1024 n_epochs = int(math.ceil(batch_size * n_iters / len(train_data))) n_epochs = max(n_epochs, 5) # run at least 5 epochs print(n_epochs, "epochs, ", end='') self.model.train( ) # Places model in "train" mode, i.e. apply dropout layer for epoch in range(n_epochs): for i, (train_x, train_y) in enumerate(minibatches(train_data, batch_size)): train_x = torch.from_numpy(train_x).long() train_y = torch.from_numpy(train_y.nonzero()[1]).long() train_x = train_x.to(self.device) train_y = train_y.to(self.device) output_y = self.model(train_x) loss = self.criterion(output_y, train_y) self.optimizer.zero_grad( ) # remove any baggage in the optimizer loss.backward() self.optimizer.step()
def run_epoch(self, sess, train, dev, epoch): ''' Performs one complete pass over the train set and evaluates on dev Args: sess: tensorflow session train: large BIODataSentence list (training set) dev: large BIODataSentence list (dev set) epoch: (int) number of the epoch ''' nbatches = len(train) // self.config.batch_size if len(train) % self.config.batch_size != 0: nbatches += 1 prog = Progbar(target=nbatches) for i, sent_batch in enumerate( minibatches(train, self.config.batch_size)): fd, _ = self.prepare_feed_dict_optimized( \ bio_data_sentence_batch=sent_batch, \ dropout_keep_prob=self.config.dropout_keep_prob, \ learning_rate=self.config.learning_rate) #_, train_loss, summary = sess.run([self.train_op, self.loss, self.merged], feed_dict=fd) _, train_loss = sess.run([self.train_op, self.loss], feed_dict=fd) prog.update(i + 1, [('train loss', train_loss)]) # tensorboard #if i % 10 == 0: #self.file_writer.add_summary(summary, epoch*nbatches + i) acc, f1, mod_p = self.run_evaluate(sess, dev) self.logger.info( '- dev acc {:04.2f} - f1 {:04.2f} - mod prec {:04.2f}'.format( 100 * acc, 100 * f1, 100 * mod_p)) return acc, f1
def run_evaluate(self, sess, test): ''' Evaluates performance on specified test/dev set Args: sess: tensorflow session test: large BIODataSentence list (dev/test set) ''' #nbatches = len(test) // self.config.batch_size #if len(test) % self.config.batch_size != 0: # nbatches += 1 correct_preds = 0 total_preds = 0 total_correct = 0 correct_mod = 0 total_mod = 0 accs = [] #prog = Progbar(target=nbatches) for i, gold_sent_batch in enumerate( minibatches(test, self.config.batch_size)): pred_sent_batch = self.predict_batch(sess, gold_sent_batch) assert len(gold_sent_batch) == len(pred_sent_batch) for sidx in range(len(gold_sent_batch)): gold_chunks = gold_sent_batch[sidx].get_label_chunks() pred_chunks = pred_sent_batch[sidx].get_label_chunks() correct_chunks = gold_chunks & pred_chunks self.logger.debug('gold_chunks: ' + str(sorted(gold_chunks))) self.logger.debug('pred_chunks: ' + str(sorted(pred_chunks))) for (chunk_idx, chunk_label) in gold_chunks: if chunk_label.startswith('MOD') or chunk_label.startswith( 'B-MOD') or chunk_label.startswith('I-MOD'): total_mod += 1 for (chunk_idx, chunk_label) in correct_chunks: if chunk_label.startswith('MOD') or chunk_label.startswith( 'B-MOD') or chunk_label.startswith('I-MOD'): correct_mod += 1 correct_preds += len(correct_chunks) total_preds += len(pred_chunks) total_correct += len(gold_chunks) accs += map( lambda items: items[0] == items[1], list( zip(gold_sent_batch[sidx].labels, pred_sent_batch[sidx].labels))) self.logger.info('correct_preds: ' + str(correct_preds)) self.logger.info('total_preds: ' + str(total_preds)) self.logger.info('total_correct: ' + str(total_correct)) p = correct_preds / total_preds if correct_preds > 0 else 0 r = correct_preds / total_correct if correct_preds > 0 else 0 mod_p = correct_mod / total_mod if correct_mod > 0 else 0 f1 = 2 * p * r / (p + r) if correct_preds > 0 else 0 acc = np.mean(accs) return acc, f1, mod_p