11import json
22
33import numpy as np
4+ from numpy .typing import NDArray
45from datasets import Dataset
56from transformers import (
67 AutoTokenizer ,
1011)
1112
1213
13- def tokenize_and_align_labels (examples ) :
14- """Tokenize each sample and align the original token labels
14+ def tokenize_and_align_labels (examples : dict [ str , list ]) -> dict [ str , list ] :
15+ """Tokenize each sample and align the original token labels
1516 to the new subword (tokenized) structure."""
1617
1718 tokenized_outputs = tokenizer (
@@ -23,14 +24,14 @@ def tokenize_and_align_labels(examples):
2324 max_length = 200 # adjust as needed
2425 )
2526
26- labels_aligned = []
27+ labels_aligned : list [ list [ int ]] = []
2728 for i , labels in enumerate (examples ["labels" ]):
2829 # The tokenizer may split single words into multiple subwords.
2930 # We create a label list the same length as input_ids,
3031 # repeating the label for all subwords of the original token.
31- word_ids = tokenized_outputs .word_ids (batch_index = i )
32- label_ids = []
33- previous_word_idx = None
32+ word_ids : list [ int | None ] = tokenized_outputs .word_ids (batch_index = i )
33+ label_ids : list [ int ] = []
34+ previous_word_idx : int | None = None
3435
3536 for word_idx in word_ids :
3637 if word_idx is None :
@@ -42,30 +43,32 @@ def tokenize_and_align_labels(examples):
4243
4344 labels_aligned .append (label_ids )
4445
45- # We don’ t need offset_mapping during model training, so we remove it
46+ # We don' t need offset_mapping during model training, so we remove it
4647 tokenized_outputs ["offset_mapping" ] = [None for _ in examples ["tokens" ]]
47-
48+
4849 tokenized_outputs ["labels" ] = labels_aligned
4950 return tokenized_outputs
5051
5152
52- def compute_metrics (eval_pred ) :
53- """Compute accuracy at the token level (simple example).
53+ def compute_metrics (eval_pred : tuple [ NDArray , NDArray ]) -> dict [ str , float ] :
54+ """Compute accuracy at the token level (simple example).
5455 You can also compute F1, precision, recall, etc. by ignoring
5556 the -100 special tokens."""
57+ logits : NDArray
58+ labels : NDArray
5659 logits , labels = eval_pred
57- predictions = np .argmax (logits , axis = - 1 )
60+ predictions : NDArray = np .argmax (logits , axis = - 1 )
5861
5962 # Flatten ignoring -100
60- true_predictions = []
61- true_labels = []
63+ true_predictions : list [ int ] = []
64+ true_labels : list [ int ] = []
6265 for pred , lab in zip (predictions , labels ):
6366 for p , l in zip (pred , lab ):
6467 if l != - 100 : # skip special tokens
6568 true_predictions .append (p )
6669 true_labels .append (l )
6770
68- results = accuracy_metric .compute (
71+ results : dict [ str , float ] = accuracy_metric .compute (
6972 references = true_labels ,
7073 predictions = true_predictions
7174 )
@@ -74,24 +77,24 @@ def compute_metrics(eval_pred):
7477
7578if __name__ == '__main__' :
7679 with open ("sentences.jsonl" , "rt" ) as f :
77- sentences = [json .loads (line ) for line in f ]
80+ sentences : list [ dict ] = [json .loads (line ) for line in f ]
7881
79- dataset_dict = {
82+ dataset_dict : dict [ str , list ] = {
8083 "tokens" : [sentence ["words" ] for sentence in sentences ],
8184 "labels" : [sentence ["types" ] for sentence in sentences ]
8285 }
8386
84- full_dataset = Dataset .from_dict (dataset_dict )
87+ full_dataset : Dataset = Dataset .from_dict (dataset_dict )
8588
86- max_words = max ([len (sentence ["words" ]) for sentence in sentences ])
89+ max_words : int = max ([len (sentence ["words" ]) for sentence in sentences ])
8790
8891
89- labels = set ()
92+ labels : set [ str ] = set ()
9093 for sentence in sentences :
9194 labels |= set (sentence ["types" ])
9295 print (labels )
93- label_to_id = {label : i for i , label in enumerate (labels )}
94- id_to_label = {i : label for label , i in label_to_id .items ()}
96+ label_to_id : dict [ str , int ] = {label : i for i , label in enumerate (labels )}
97+ id_to_label : dict [ int , str ] = {i : label for label , i in label_to_id .items ()}
9598
9699 dataset = full_dataset .train_test_split (test_size = 0.25 , seed = 42 )
97100 train_dataset = dataset ["train" ]
@@ -101,14 +104,14 @@ def compute_metrics(eval_pred):
101104 print ("Num test samples: " , len (test_dataset ))
102105
103106
104- model_checkpoint = "distilbert-base-multilingual-cased"
107+ model_checkpoint : str = "distilbert-base-multilingual-cased"
105108 tokenizer = AutoTokenizer .from_pretrained (model_checkpoint , use_fast = True , add_prefix_space = True )
106109
107110 # Apply to train/test datasets
108111 train_dataset = train_dataset .map (tokenize_and_align_labels , batched = True )
109112 test_dataset = test_dataset .map (tokenize_and_align_labels , batched = True )
110113
111- # Remove columns we don’ t feed directly to the model
114+ # Remove columns we don' t feed directly to the model
112115 # train_dataset = train_dataset.remove_columns(["tokens", "labels"])
113116 # test_dataset = test_dataset.remove_columns(["tokens", "labels"])
114117
@@ -125,7 +128,7 @@ def compute_metrics(eval_pred):
125128
126129 accuracy_metric = evaluate .load ("accuracy" ) # type: ignore[attr-defined]
127130
128- training_args = TrainingArguments (
131+ training_args : TrainingArguments = TrainingArguments (
129132 output_dir = "./test-roberta-token-classifier" ,
130133 eval_strategy = "epoch" ,
131134 save_strategy = "epoch" ,
@@ -139,7 +142,7 @@ def compute_metrics(eval_pred):
139142 report_to = "none" # Set to "tensorboard" if you want logs
140143 )
141144
142- trainer = Trainer (
145+ trainer : Trainer = Trainer (
143146 model = model ,
144147 args = training_args ,
145148 train_dataset = train_dataset ,
@@ -150,7 +153,7 @@ def compute_metrics(eval_pred):
150153
151154 trainer .train ()
152155
153- results = trainer .evaluate (test_dataset ) # type: ignore[arg-type]
156+ results : dict [ str , float ] = trainer .evaluate (test_dataset ) # type: ignore[arg-type]
154157 print ("Test set results:" , results )
155158
156159 trainer .save_model ("./token-classifier" )
0 commit comments