From 5fbd0a05bf4be603b6a0e499ef07f3ec858c42e5 Mon Sep 17 00:00:00 2001
From: Alice Pain <apain@clipper.ens.fr>
Date: Mon, 4 Jul 2022 11:06:40 +0200
Subject: [PATCH] plot anchors

---
 trytorch/check_parse.py                       |  16 ++
 trytorch/check_rich.py                        |  34 +++
 trytorch/parse_corpus.py                      |  52 ++--
 ...sed_fra.sdrt.annodis_train-mini.conllu.npz | Bin 37377 -> 0 bytes
 trytorch/test_model.py                        | 100 ++++----
 trytorch/train_model_baseline.py              |  16 +-
 trytorch/train_model_rich.py                  | 233 ++++++++++++++++++
 7 files changed, 373 insertions(+), 78 deletions(-)
 create mode 100644 trytorch/check_parse.py
 create mode 100644 trytorch/check_rich.py
 delete mode 100644 trytorch/parsed_data/parsed_fra.sdrt.annodis_train-mini.conllu.npz
 create mode 100644 trytorch/train_model_rich.py

diff --git a/trytorch/check_parse.py b/trytorch/check_parse.py
new file mode 100644
index 0000000..ecb1fb3
--- /dev/null
+++ b/trytorch/check_parse.py
@@ -0,0 +1,16 @@
+import sys
+import numpy as np
+
+path = sys.argv[1]
+data = np.load(path, allow_pickle=True)
+tok_ids, toks, labels = [data[f] for f in data.files]
+
+for i, tok in enumerate(toks):
+    if isinstance(tok, str):
+        if len(tok) > 35:
+            print(tok)
+    else:
+        print(tok_ids[i])
+        print(type(tok))
+
+
diff --git a/trytorch/check_rich.py b/trytorch/check_rich.py
new file mode 100644
index 0000000..6233fe5
--- /dev/null
+++ b/trytorch/check_rich.py
@@ -0,0 +1,34 @@
+import sys
+import numpy as np
+
+path = sys.argv[1]
+data = np.load(path, allow_pickle=True)
+tok_ids, toks, labels, upos, idheads, deprels = [data[f] for f in data.files]
+
+print(len(toks))
+print(len(upos))
+
+labs_upos = np.unique(upos)
+labs_idheads = np.unique(idheads)
+labs_deprel = np.unique(deprels)
+print(labs_upos)
+print(labs_idheads)
+print(labs_deprel)
+
+for i, tok in enumerate(toks):
+    if isinstance(tok, str):
+        if len(tok) > 35:
+            print(tok)
+    else:
+        print(tok_ids[i])
+        print(type(tok))
+
+for i, tok in enumerate(upos):
+    if isinstance(tok, str):
+        if len(tok) > 35:
+            print(tok)
+    else:
+        print(tok_ids[i])
+        print(type(tok))
+
+
diff --git a/trytorch/parse_corpus.py b/trytorch/parse_corpus.py
index 59f8e91..f24fc23 100644
--- a/trytorch/parse_corpus.py
+++ b/trytorch/parse_corpus.py
@@ -6,16 +6,22 @@ import mmap
 import re
 import numpy as np
 
-def parse(corpus):
+def parse(corpus, rich):
         """Turn corpus into a list of sentences then save it"""
         print(f'parsing of {corpus} begins')
         split = corpus.split("_")
         corpus_dir = split[0]
         input_file = os.path.join("data/", corpus_dir, corpus)
         output_dir = 'parsed_data'
-        output_file = os.path.join(output_dir, f'parsed_{corpus}')
+        if rich:
+            if not corpus.endswith('conllu'):
+                print('rich parsing only possible with conllu file')
+                sys.exit()
+            output_file = os.path.join(output_dir, f'parsedrich_{corpus}')
+        else:
+            output_file = os.path.join(output_dir, f'parsed_{corpus}')
         if not os.path.isdir(output_dir):
-                os.system(f"mkdir {output_dir}")
+                os.mkdir(output_dir)
         if os.path.isfile(output_file + '.npz'):
                 print(f'{corpus} already parsed. do you wish to overwrite? (Y/n)')
                 user = input()
@@ -23,11 +29,11 @@ def parse(corpus):
                     print('done')
                     sys.exit()
 
-        column_names = ['tok_id','tok','1','2','3','4','5','6','7','label']
-        if corpus == 'eng.rst.rstdt_train.conllu':
-            df = pd.read_csv(input_file, names = column_names, skip_blank_lines=True, comment="#", sep="\t", engine='python', error_bad_lines=False, header=None)
-        else:
-            df = pd.read_csv(input_file, names = column_names, skip_blank_lines=True, comment="#", sep="\t")
+        column_names = ['tok_id','tok','lemma','upos','xpos','gram','idhead','deprel','type','label']
+        #if corpus.startswith('eng.rst.rstdt_train') or corpus.startswith('por.rst.cstn'):
+        #    df = pd.read_csv(input_file, names = column_names, skip_blank_lines=True, sep="\t", quoting=3, comment='#')
+        #else:
+        df = pd.read_csv(input_file, names = column_names, skip_blank_lines=True, comment="#", sep="\t", quoting=3)
         tok_ids = df['tok_id'].values
         toks = df['tok'].values
         labels = df['label'].values
@@ -38,21 +44,35 @@ def parse(corpus):
                     new_labels[i] = 1
                 else: new_labels[i] = 0
         else:
-            new_labels = np.where((labels == ("BeginSeg=Yes")), 1, 0) #labels == BeginSeg=Yes
+            new_labels = np.where((labels == "BeginSeg=Yes"), 1, 0) 
         labels = new_labels
         nb_segs = np.sum(labels)
-        
-        np.savez_compressed(output_file, tok_ids = tok_ids, toks = toks, labels = labels)
+       
+        if rich:
+            upos = df['upos'].values
+            idheads = df['idhead'].values
+            deprels = df['deprel'].values
+            np.savez_compressed(output_file, tok_ids = tok_ids, toks = toks, labels = labels, upos = upos, idheads = idheads, deprels = deprels)
+
+        else:
+            np.savez_compressed(output_file, tok_ids = tok_ids, toks = toks, labels = labels)
         
         print(f'done parsing. data saved at {output_file}')
 
 def main():
-        if len(sys.argv) < 2:
-                print("usage: parse_corpus.py <corpus>")
+        if len(sys.argv) < 2 or len(sys.argv) > 3:
+            print("usage: parse_corpus.py <corpus> [<rich>]")
+            sys.exit()
+        corpus = sys.argv[1]
+        rich = False
+        #rich = True means we collect not only token and label but also dependency relationship for conllu files
+        if len(sys.argv) > 2:
+            if sys.argv[2] == 'rich':
+                rich = True
+            else:
+                print("usage: parse_corpus.py <corpus> [<rich>]")
                 sys.exit()
-        corpora = sys.argv[1:]
-        for corpus in corpora:
-                parse(corpus)
+        parse(corpus, rich)
 
 if __name__ == '__main__':
         main()
diff --git a/trytorch/parsed_data/parsed_fra.sdrt.annodis_train-mini.conllu.npz b/trytorch/parsed_data/parsed_fra.sdrt.annodis_train-mini.conllu.npz
deleted file mode 100644
index 6821ad66bd027b64da05151676c2a8d414e9875f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 37377
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

diff --git a/trytorch/test_model.py b/trytorch/test_model.py
index 26bc6ff..df60cfc 100644
--- a/trytorch/test_model.py
+++ b/trytorch/test_model.py
@@ -1,27 +1,28 @@
 import numpy as np
 import sys
 import os
-from transformers import BertTokenizer, BertModel
-from transformers.tokenization_utils_base import BatchEncoding
+import argparse
 import torch
 from torch import nn
-from torch.nn.utils.rnn import pad_sequence
 from torch.utils.data import DataLoader
-#from torchmetrics import F1Score
-#from torch.autograd import Variable
 from tqdm import tqdm
-from train_model_baseline import LSTM, SentenceBatch, generate_sentence_list, toks_to_ids, make_labels, make_tok_types, make_tok_masks, collate_batch
+from train_model_baseline import LSTM, SentenceBatch, generate_sentence_list, collate_batch
+from train_model_rich import RichLSTM, generate_rich_sentence_list, collate_rich_batch
 
 bert = 'bert-base-multilingual-cased'
-tokenizer = BertTokenizer.from_pretrained(bert)
 
-def test(corpus, model_path, test_set, fmt):
+def test(model_path, model_type, corpus, test_set, fmt, show_errors):
         model = torch.load(model_path)
-        print(f'Model:\t{model_path}\nEval:\t{corpus}_{test_set}\nFormat:\t{fmt}')
-        data = generate_sentence_list(corpus, test_set, fmt)
+        print(f'Model:\t{model_path}\nType:\t{model_type}\nEval:\t{corpus}_{test_set}\nFormat:\t{fmt}')
+
         batch_size = 32
-        dataloader = DataLoader(data, batch_size=batch_size, shuffle=True, collate_fn=collate_batch)
-        
+        if model_type == 'baseline':
+            data = generate_sentence_list(corpus, test_set, fmt)
+            dataloader = DataLoader(data, batch_size=batch_size, shuffle=True, collate_fn=collate_batch)
+        else:
+            data, _, _ = generate_rich_sentence_list(corpus, test_set, fmt)
+            dataloader = DataLoader(data, batch_size=batch_size, shuffle=True, collate_fn=collate_rich_batch)
+
         model.eval()
         loss_fn = nn.BCELoss()
         
@@ -29,27 +30,25 @@ def test(corpus, model_path, test_set, fmt):
         errors = []
         
         with torch.no_grad():
-                total_acc = 0
-                total_loss = 0
-                tp = 0
-                fp = 0 
-                fn = 0
+                total_acc, total_loss = 0, 0
+                tp, fp, fn = 0, 0, 0
         
                 for sentence_batch in tqdm(dataloader):
                         label_batch = sentence_batch.labels
-                        #print("label_batch", label_batch.shape)
-                        pred = model(sentence_batch.getBatchEncoding())
-                        #print("pred", pred.shape)
+                        if model_type == 'baseline':
+                            pred = model(sentence_batch.getBatchEncoding())
+                        else:
+                            pred = model(sentence_batch.getBatchEncoding(), sentence_batch.upos, sentence_batch.deprels, sentence_batch.dheads)
                         loss = loss_fn(pred, label_batch)
                         pred_binary = (pred >= 0.5).float()
                         
                         for i in range(label_batch.size(0)):
                                 for j in range(label_batch.size(1)):
-                                                if pred_binary[i,j] == 1.:
-                                                        if label_batch[i,j] == 1.:
-                                                                tp += 1
-                                                        else: fp += 1
-                                                elif label_batch[i,j] == 1.: fn += 1
+                                        if pred_binary[i,j] == 1.:
+                                                if label_batch[i,j] == 1.:
+                                                        tp += 1
+                                                else: fp += 1
+                                        elif label_batch[i,j] == 1.: fn += 1
                         sum_score = ((pred_binary == label_batch).float().sum().item()) / label_batch.size(1)
                         assert (sum_score <= batch_size)
                         for i, sentence_id in enumerate(sentence_batch.sentence_ids):
@@ -61,8 +60,9 @@ def test(corpus, model_path, test_set, fmt):
                 precision = tp / (tp + fp)
                 recall = tp / (tp + fn)
                 f1 = 2 * (precision * recall) / (precision + recall)
-
-        #print_errors(errors, data)
+    
+        if show_errors > 0:
+            print_errors(errors, data, max_print=show_errors)
 
         print(f"Acc\t{total_acc/l}\nLoss\t{total_loss/l}\nP\t{precision}\nR\t{recall}\nF1\t{f1}\n\n")
 
@@ -72,10 +72,9 @@ def print_segmentation(toks, labels):
                 if i+1 < len(labels) and labels[i+1] == 1:
                         s += "| "
                 s += str(tok) + " "
-        print(s)
+        print(s + '\n')
 
 def print_errors(errors, data, max_print=25):
-        
         print(f'Reporting {max_print} errors')
         max_print = min(max_print, len(errors))
         for sentence_id, pred in errors[:max_print]:
@@ -88,32 +87,23 @@ def print_errors(errors, data, max_print=25):
                 print_segmentation(toks, labels)
 
 def main():
-        if len(sys.argv) < 2 or len(sys.argv) > 4:
-                print("usage: test_model.py <model> [<test_corpus>] [<test/dev/train>]")
-                sys.exit()
-        model_path = sys.argv[1]
-        if not os.path.isfile(model_path):
-                print("model not found. please train the model first. please provide a relative path from discut dir.")
-                sys.exit()
-        test_set = 'test'
-        if len(sys.argv) == 4:
-                if sys.argv[3] == 'dev':
-                        test_set = 'dev'
-                elif sys.arvg[3] == 'train':
-                        test_set = 'train'
-                elif sys.argv[3] != 'test':        
-                        print("usage: test_model.py <model> [<test_corpus>] [<test/dev/train>]")
-                        sys.exit()
-        model_split = model_path.split("/")
-        corpus = model_split[1]        
-        if len(sys.argv) >= 3:
-                corpus = sys.argv[2] 
-        fmt = 'conllu'
-        params = model_split[2]
-        params_split = params.split("_")
-        if params_split[1] == 'tok':
-                fmt = 'tok'
-        test(corpus, model_path, test_set, fmt)        
+        parser = argparse.ArgumentParser(description='Test a model on a dataset')
+        parser.add_argument('--model', help='Path to .pth saved model')
+        parser.add_argument('--format', default='conllu', help='tok or conllu')
+        parser.add_argument('--type', default='baseline', help="baseline or rich model")
+        parser.add_argument('--corpus', help='corpus to test on')
+        parser.add_argument('--set', default='test', help='portion of the corpus to test on')
+        parser.add_argument('--errors', default=0, help='number of prediction errors to display on standard output')
+
+        params = parser.parse_args()
+
+        if not os.path.isfile(params.model):
+            print("model not found. please train the model first. please provide a relative path from discut dir.")
+            sys.exit()
+        if params.type == 'rich' and params.format == 'tok':
+            print('a rich model requires a .conllu file')
+            sys.exit()
+        test(params.model, params.type, params.corpus, params.set, params.format, params.errors)
 
 if __name__ == '__main__':
         main()
diff --git a/trytorch/train_model_baseline.py b/trytorch/train_model_baseline.py
index 4acbd84..b6038b5 100644
--- a/trytorch/train_model_baseline.py
+++ b/trytorch/train_model_baseline.py
@@ -12,7 +12,6 @@ from torch.utils.data import DataLoader
 from tqdm import tqdm
 
 bert = 'bert-base-multilingual-cased'
-tokenizer = BertTokenizer.from_pretrained(bert)
 #bert_embeddings = BertModel.from_pretrained(bert)
 
 class LSTM(nn.Module):
@@ -42,14 +41,16 @@ class LSTM(nn.Module):
                 #lstm_out, self.hidden = self.lstm(output, self.hidden)
 
 class SentenceBatch():
-
-        def __init__(self, sentence_ids, tokens, tok_ids, tok_types, tok_masks, labels):
+        def __init__(self, sentence_ids, tokens, tok_ids, tok_types, tok_masks, labels, uposes = None, deprels = None, dheads = None):
                 self.sentence_ids = sentence_ids
                 self.tokens = tokens
-                self.tok_ids = pad_sequence(tok_ids, batch_first=True)
+                self.tok_ids = pad_sequence(tok_ids, batch_first=True) #bert token ids
                 self.tok_types = pad_sequence(tok_types, batch_first=True)
                 self.tok_masks = pad_sequence(tok_masks, batch_first=True)
                 self.labels = pad_sequence(labels, batch_first=True)
+                self.uposes = pad_sequence(upos, batch_first=True)
+                self.dheads = pad_sequence(dheads, batch_first=True)
+                self.labels = pad_sequence(labels, batch_first=True)
 
         def getBatchEncoding(self):
                 dico = { 'input_ids': self.tok_ids, 'token_type_ids': self.tok_types, 'attention_mask': self.tok_masks }
@@ -102,6 +103,7 @@ def toks_to_ids(sentence):
         #print("sentence=", sentence)
         tokens = ['[CLS]'] + list(sentence) + ['[SEP]']
         #print("tokens=", tokens)
+        tokenizer = BertTokenizer.from_pretrained(bert)
         return torch.tensor(tokenizer.convert_tokens_to_ids(tokens)) #len(tokens)
         #print("token_ids=", token_ids)
 
@@ -189,10 +191,10 @@ def train(corpus, fmt):
                 print(f"Epoch {epoch} Accuracy {total_acc/l} Loss {total_loss/l} F1 {f1}")
         
         print('done training')
-        output_file = save_model(model, corpus, params)
+        output_file = save_model(model, 'baseline', corpus, params)
         print(f'model saved at {output_file}')
 
-def save_model(model, corpus, params):
+def save_model(model, model_type, corpus, params):
 
         models_dir = 'saved_models'
         if not os.path.isdir(models_dir):
@@ -200,7 +202,7 @@ def save_model(model, corpus, params):
         corpus_dir = os.path.join(models_dir, corpus)        
         if not os.path.isdir(corpus_dir):
                 os.system(f'mkdir {corpus_dir}')
-        model_file = f"{corpus}_{params['fm']}_{params['bs']}_{params['ne']}_{params['lr']}_{params['rg']}_{params['do']}_{params['bi']}.pth"
+        model_file = f"{model_type}_{corpus}_{params['fm']}_{params['bs']}_{params['ne']}_{params['lr']}_{params['rg']}_{params['do']}_{params['bi']}.pth"
         output_file = os.path.join(corpus_dir, model_file)
         if not os.path.isfile(output_file):
                 torch.save(model, output_file)
diff --git a/trytorch/train_model_rich.py b/trytorch/train_model_rich.py
new file mode 100644
index 0000000..ccb72b3
--- /dev/null
+++ b/trytorch/train_model_rich.py
@@ -0,0 +1,233 @@
+import numpy as np
+import sys
+import os
+from transformers import BertModel
+from transformers.tokenization_utils_base import BatchEncoding
+import torch
+from torch import nn
+from torch.nn.utils.rnn import pad_sequence
+from torch.utils.data import DataLoader
+from tqdm import tqdm
+from train_model_baseline import SentenceBatch, add_cls_sep, toks_to_ids, make_labels, make_tok_types, make_tok_masks, save_model
+
+bert = 'bert-base-multilingual-cased'
+#bert_embeddings = BertModel.from_pretrained(bert)
+
+class RichLSTM(nn.Module):
+
+        def __init__(self, batch_size, hidden_size, n_upos, upos_emb_dim, n_deprel, deprel_emb_dim, num_layers=1, bidirectional=False):
+                super().__init__()
+                self.batch_size = batch_size
+                self.hidden_size = hidden_size
+
+                #embedding dims 
+                self.bert_emb_dim = 768
+                self.upos_emb_dim = upos_emb_dim
+                self.deprel_emb_dim = deprel_emb_dim
+
+                #embedding layers
+                self.bert_embeddings = BertModel.from_pretrained(bert)
+                self.upos_embeddings = nn.Embedding(n_upos + 1, self.upos_emb_dim, padding_idx=0)
+                self.deprel_embeddings = nn.Embedding(n_deprel + 1, self.deprel_emb_dim, padding_idx=0)
+                lstm_input_size = self.bert_emb_dim + self.upos_emb_dim + self.deprel_emb_dim + 1
+                self.lstm = nn.LSTM(lstm_input_size, hidden_size, num_layers, batch_first=True, bidirectional=bidirectional)
+                d = 2 if bidirectional else 1
+                self.hiddenToLabel = nn.Linear(d * hidden_size, 1)
+                self.act = nn.Sigmoid()
+
+                #convenient values for slicing the vectors: [ bert (768) | upos (U) | deprel (R) | dhead (1) ]
+                self.bert_upos = self.bert_emb_dim + self.upos_emb_dim
+                self.bert_upos_deprel = self.bert_emb_dim + self.upos_emb_dim + self.deprel_emb_dim
+
+        def forward(self, tok_batch, upos_batch, deprel_batch, dhead_batch):
+                # batch: [B x L], where
+                # B = batch_size
+                # L = max sentence length in batch
+                
+                bert_output = self.bert_embeddings(**tok_batch)
+                bert_output = bert_output.last_hidden_state
+                # bert_output: [B x L x 768]
+                upos_output = self.upos_embeddings(upos_batch)
+                # upos_output: [B x L x U]
+                deprel_output = self.deprel_embeddings(deprel_batch)
+                # deprel_output: [B x L x R]
+                dhead_output = dhead_batch[:,:,None]
+                # dhead_output: [B x L x 1]
+                #print("bert_output=", bert_output.shape)
+                #print("upos_output=", upos_output.shape)
+                #print("deprel_output", deprel_output.shape)
+                #print("dhead_output", dhead_output.shape)
+
+                full_output = torch.cat((bert_output, upos_output, deprel_output, dhead_output), dim=2)
+                output64, (last_hidden_state, last_cell_state) = self.lstm(full_output)
+                output1 = self.hiddenToLabel(output64)
+                #print("output1=", output1.shape)
+                return self.act(output1[:,:,0])
+
+                #lstm_out, self.hidden = self.lstm(output, self.hidden)
+
+#class RichSentenceBatch():
+#
+#        def __init__(self, sentence_ids, tokens, tok_ids, tok_types, tok_masks, upos, deprels, dheads, labels):
+#                self.sentence_ids = sentence_ids
+#                self.tokens = tokens
+#                self.tok_ids = pad_sequence(tok_ids, batch_first=True)
+#                self.tok_types = pad_sequence(tok_types, batch_first=True)
+#                self.tok_masks = pad_sequence(tok_masks, batch_first=True)
+#                self.upos = pad_sequence(upos, batch_first=True)
+#                self.deprels = pad_sequence(deprels, batch_first=True) #LOG SCALE
+#                self.dheads = pad_sequence(dheads, batch_first=True)
+#                self.labels = pad_sequence(labels, batch_first=True)
+#
+#        def getBatchEncoding(self):
+#                dico = { 'input_ids': self.tok_ids, 'token_type_ids': self.tok_types, 'attention_mask': self.tok_masks }
+#                return BatchEncoding(dico)
+        
+def cat_to_id(instance, cat):
+        return np.where(cat == instance)[0][0] + 1
+
+def dh_list(tok_ids, idheads, s, e):
+        l = e - s
+        ret = [0] * l 
+        new_tok_ids = tok_ids[s:e]
+        new_idheads = idheads[s:e]
+        for i, idhead in enumerate(new_idheads):
+            if idhead == 0:
+                ret[i] = 0
+            else:
+                ret[i] = np.log(abs(idhead - new_tok_ids[i]))
+        return ret
+
+def generate_rich_sentence_list(corpus, sset, fmt):
+        parsed_data = os.path.join("parsed_data", f"parsedrich_{corpus}_{sset}.{fmt}.npz")
+        #print("PATH", parsed_data)
+        if not os.path.isfile(parsed_data):
+                print("you must parse the corpus before training it")
+                sys.exit()
+        data = np.load(parsed_data, allow_pickle = True)
+        tok_ids, toks, labels, upos, idheads, deprels = [data[f] for f in data.files]
+        
+        unique_upos = np.unique(upos)
+        unique_deprels = np.unique(deprels)
+        nb_upos = len(unique_upos)
+        nb_deprels = len(unique_deprels)
+
+        sentences = []
+
+        previous_i = 0
+        for index, tok_id in enumerate(tok_ids):
+                if index > 0 and (tok_id == 1 or tok_id == '1' or (isinstance(tok_id, str) and tok_id.startswith('1-'))):
+                        if index - previous_i <= 510:
+                                sentences.append((toks[previous_i:index], [cat_to_id(u, unique_upos) for u in upos[previous_i:index]], [cat_to_id(d, unique_deprels) for d in deprels[previous_i:index]], dh_list(tok_ids, idheads, previous_i, index), labels[previous_i:index]))
+                                previous_i = index
+                        else: 
+                                sep = previous_i + 510
+                                sentences.append((toks[previous_i:sep], labels[previous_i:sep]))
+                                if sep - previous_i > 510:
+                                        print("still too long sentence...")
+                                        sys.exit()
+                                sentences.append((toks[sep:index], [cat_to_id(u, unique_upos) for u in upos[sep:index]], [cat_to_id(d, unique_deprels) for d in deprels[sep:index]], dh_list(tok_ids, idheads, sep, index), labels[sep:index]))
+
+        indexed_sentences = [0] * len(sentences)
+        for i, sentence in enumerate(sentences):
+                indexed_sentences[i] = (i, sentence)
+
+        return indexed_sentences, nb_upos, nb_deprels
+
+def int_add_zeros(sentence):
+        zero = torch.zeros(1).int()
+        return torch.cat((zero, torch.tensor(sentence).int(), zero))
+
+def add_zeros(sentence):
+        zero = torch.zeros(1)
+        return torch.cat((zero, torch.tensor(sentence), zero))
+
+def collate_rich_batch(batch):
+        sentence_ids, token_batch, upos_batch, idhead_batch, deprel_batch, label_batch = [i for i, (_, _, _, _, _) in batch], [j for _, (j, _, _, _, _) in batch], [k for _, (_, k, _, _, _) in batch], [l for _, (_, _, l, _, _) in batch], [m for _, (_, _, _, m, _) in batch], [n for _, (_, _, _, _, n) in batch]
+        labels = [make_labels(sentence) for sentence in label_batch]
+        tokens = [add_cls_sep(sentence) for sentence in token_batch]
+        tok_ids = [toks_to_ids(sentence) for sentence in token_batch]
+        lengths = [len(toks) for toks in tok_ids]
+        tok_types = [make_tok_types(l) for l in lengths]
+        tok_masks = [make_tok_masks(l) for l in lengths]
+        uposes = [int_add_zeros(sentence) for sentence in upos_batch]
+        deprels = [int_add_zeros(sentence) for sentence in deprel_batch]
+        dheads = [add_zeros(sentence) for sentence in idhead_batch]
+        
+        return SentenceBatch(sentence_ids, tokens, tok_ids, tok_types, tok_masks, labels, uposes = uposes, deprels = deprels, dheads = dheads)
+        
+def train(corpus):
+        print(f'starting rich training of {corpus}...')
+        data, nb_upos, nb_deprels = generate_rich_sentence_list(corpus, 'train', 'conllu') 
+        upos_emb_dim = int(np.sqrt(nb_upos))
+        deprel_emb_dim = int(np.sqrt(nb_deprels))
+
+        torch.manual_seed(1)
+
+        #PARAMETERS
+        batch_size = 32 
+        num_epochs = 5
+        lr = 0.0001
+        reg = 0.001
+        dropout = 0.01
+        bidirectional = True
+        params = { 'fm' : 'conllu', 'bs': batch_size, 'ne': num_epochs, 'lr': lr, 'rg': reg, 'do': dropout, 'bi': bidirectional }
+
+        dataloader = DataLoader(data, batch_size=batch_size, shuffle=True, collate_fn=collate_rich_batch)
+        model = RichLSTM(batch_size, 64, nb_upos, upos_emb_dim, nb_deprels, deprel_emb_dim, num_layers=1, bidirectional=bidirectional) 
+        loss_fn = nn.BCELoss() 
+        optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=reg)
+        model.train()
+        
+        l = len(dataloader.dataset)
+        
+        for epoch in range(num_epochs):
+                total_acc = 0
+                total_loss = 0
+                tp = 0
+                fp = 0 
+                fn = 0
+        
+                for sentence_batch in tqdm(dataloader):
+                        optimizer.zero_grad()
+                        label_batch = sentence_batch.labels
+                        #print("label_batch", label_batch.shape)
+                        #print("tok_ids", sentence_batch.tok_ids.shape)
+                        pred = model(sentence_batch.getBatchEncoding(), sentence_batch.uposes, sentence_batch.deprels, sentence_batch.dheads)
+                        #print("pred", pred.shape)
+                        loss = loss_fn(pred, label_batch)
+                        loss.backward()
+                        optimizer.step()
+                        pred_binary = (pred >= 0.5).float()
+                        
+                        for i in range(label_batch.size(0)):
+                                for j in range(label_batch.size(1)):
+                                        if pred_binary[i,j] == 1.:
+                                                if label_batch[i,j] == 1.:
+                                                        tp += 1
+                                                else: fp += 1
+                                        elif label_batch[i,j] == 1.: fn += 1
+                        #print("tp,fp,fn=",tp/label_batch.size(1),fp/label_batch.size(1),fn/label_batch.size(1))
+                        #nb_1 = pred_binary.sum()
+                        #print("nb predicted 1=", nb_1)
+                        sum_score = ((pred_binary == label_batch).float().sum().item()) / label_batch.size(1)
+                        assert (sum_score <= batch_size)
+                        total_acc += sum_score
+                        total_loss += loss.item() #*label_batch.size(0)
+
+                f1 = tp / (tp + (fp + fn) / 2)
+                print(f"Epoch {epoch} Accuracy {total_acc/l} Loss {total_loss/l} F1 {f1}")
+        
+        print('done training')
+        output_file = save_model(model, 'rich', corpus, params)
+        print(f'model saved at {output_file}')
+
+def main():
+        if len(sys.argv) != 2:
+                print("usage: train_model_rich.py <corpus>")
+                sys.exit()
+        corpus = sys.argv[1]
+        train(corpus) 
+
+if __name__ == '__main__':
+        main()
-- 
GitLab