This release fixes compatibility bugs with the newest PyTorch and SciPy versions, and adds a number of small improvements and new features.
Improvements and new featuresSegtokTokenizer
: Add option to customize SegtokTokenizer, by @alanakbik in #3592RegexpTagger
: Add option to define matching groups to RegexpTagger, by @alanakbik in #3598RelationClassifier
: Optimize RelationClassifier by adding the option to filter long sentences and truncate context, by @alanakbik in #3593RelationClassifier
: Modify printouts in RelationClassifier evaluation to remove clutter by @alanakbik in #3591Adds a new Nearest Class Mean classification approach to Flair that classifies data points to the class with the closest class data mean. This approach can be used as an alternative to fitting a Softmax Classifier. It is now available for any class in Flair that implements DefaultClassifier. For instance, to train a TextClassifier with DeepNCMs you can use the following code:
from flair.data import Corpus from flair.datasets import TREC_50 from flair.embeddings import TransformerDocumentEmbeddings from flair.models import TextClassifier from flair.nn import DeepNCMDecoder from flair.trainers import ModelTrainer from flair.trainers.plugins import DeepNCMPlugin # load the TREC dataset corpus: Corpus = TREC_50() label_type = "class" # make a transformer document embedding document_embeddings = TransformerDocumentEmbeddings("distilbert-base-uncased", fine_tune=True) # create the label_dictionary label_dictionary = corpus.make_label_dictionary(label_type=label_type) # create a text classifier with a special DeepNCM decoder classifier = TextClassifier( document_embeddings, label_type=label_type, label_dictionary=label_dictionary, decoder=DeepNCMDecoder( mean_update_method="condensation", embeddings_size=document_embeddings.embedding_length, label_dictionary=label_dictionary, ), ) # initialize the trainer trainer = ModelTrainer(classifier, corpus) # train the model using the DeepNCM plugin trainer.fine_tune( "resources/taggers/deepncm_baseline", plugins=[DeepNCMPlugin()], )
Contributed by @sheldon-roberts in #3532
DatasetsFull Changelog: v0.15.0...v0.15.1
Release 0.15.0 Release 0.14.0This release adds major new support for biomedical text analytics! It adds improved biomedical NER and a state-of-the-art model for biomedical entity linking. Other new features include (1) support for parameter-efficient fine-tuning and (2) various new datasets, bug fixes and enhancements! We also removed a few dependencies, so Flair should install faster and take up less space!
Biomedical NER and Entity LinkingWith Flair 0.14.0, you can now detect and normalize biomedical entities in text.
For example, to analyze the sentence "We correlate genetic variants in IFNAR2 and POLG with long-COVID syndrome
", use this code snippet:
from flair.models import EntityMentionLinker from flair.nn import Classifier from flair.data import Sentence # A sentence from biomedical literature sentence = Sentence("We correlate genetic variants in IFNAR2 and POLG with long-COVID syndrome.") # Tag named entities in the text ner_tagger = Classifier.load("hunflair2") ner_tagger.predict(sentence) # Normalize disease names disease_linker = EntityMentionLinker.load("gene-linker") disease_linker.predict(sentence) # Normalize gene names gene_linker = EntityMentionLinker.load("disease-linker") gene_linker.predict(sentence) # Iterate over predicted entities and print for label in sentence.get_labels(): print(label)
This should print out:
Span[5:6]: "IFNAR2" → Gene (1.0) Span[5:6]: "IFNAR2" → 3455/name=IFNAR2 Span[7:8]: "POLG" → Gene (1.0) Span[7:8]: "POLG" → 5428/name=POLG Span[9:11]: "long-COVID syndrome" → Disease (1.0) Span[9:11]: "long-COVID syndrome" → MESH:D000094024/name=Post-Acute COVID-19 Syndrome
The printout shows that:
"IFNAR2" is a gene. Further, it is recognized as gene 3455 ("interferon alpha and beta receptor subunit 2") in the NCBI database.
"POLG" is a gene. Further, it is recognized as gene 5428 ("DNA polymerase gamma, catalytic subunit") in the NCBI database.
"long-COVID syndrome" is a disease. Further, it is uniquely linked to "Post-Acute COVID-19 Syndrome" in the MESH database.
Big thanks to @sg-wbi @WangXII @mariosaenger @helpmefindaname for all their work:
Flair 0.14.0 also adds support for PEFT.
For instance, to fine-tune a BERT model on the TREC question classification task using LoRA, use the following snippet:
from flair.data import Corpus from flair.datasets import TREC_6 from flair.embeddings import TransformerDocumentEmbeddings from flair.models import TextClassifier from flair.trainers import ModelTrainer # Note: you need to install peft to use this feature! from peft import LoraConfig, TaskType # Get corpus and make label dictionary corpus: Corpus = TREC_6() label_type = "question_class" label_dict = corpus.make_label_dictionary(label_type=label_type) # Define embeddings with LoRA fine-tuning document_embeddings = TransformerDocumentEmbeddings( "bert-base-uncased", fine_tune=True, # set LoRA config peft_config=LoraConfig( task_type=TaskType.FEATURE_EXTRACTION, inference_mode=False, ), ) # define model classifier = TextClassifier(document_embeddings, label_dictionary=label_dict, label_type=label_type) # train model trainer = ModelTrainer(classifier, corpus) trainer.fine_tune( "resources/taggers/question-classification-with-transformer", learning_rate=5.0e-4, mini_batch_size=4, max_epochs=1, )
Big thanks to @janpf for this new feature!
Smaller LibraryWe've removed dependencies such as gensim
from the core package, since they increased the size of the Flair library and caused some compatibility/maintenance issues. This means the core package is now smaller and fast to install.
Install as always with:
For certain features, you still need gensim
, such as training a model that uses classic word embeddings. For this use case, install with:
pip install flair[word-embeddings]
Or just install gensim
separately.
Big thanks to @helpmefindaname for this new feature!
TextPairRegressor
: Fix data point iteration by @ya0guang in #3413TextPairRegressor
: Fix GPU memory leak by @MattGPT-ai in #3490TextRegressor
: Fix label_name bug by @sheldon-roberts in #3491SequenceTagger
: Fix _all_scores_for_token in ViterbiDecoder by @mauryaland in #3455SentenceSplitter
: Fix linking of sentences by @mariosaenger in #3397SentenceSplitter
: Fix case where split was performed on special characters by @helpmefindaname in #3404Classifier
: Fix loading by moving error message to main load function by @alanakbik in #3504Trainer
: Fix edge case by loading best model at end, even when there is no final evaluation by @helpmefindaname in #3470TransformerEmbeddings
: Fix special tokens by not replacing replace_additional_special_tokens by @helpmefindaname in #3451data_folder
in unit test by @ya0guang in #3412NER_ESTONIAN_NOISY
: Support for Estonian NER dataset with noise by @teresaloeffelhardt in #3463MASAKHA_POS
: Support for two new languages by @stefan-it in #3421UD_BAVARIAN_MAIBAAM
: Add support for new Bavarian MaiBaam UD by @stefan-it in #3426tests
package being incorrectly included in builds by @asumagic in #3440Full Changelog: v0.13.1...v0.14.0
Release 0.13.1 Release 0.13.0This release adds several major new features such as (1) faster and more memory-efficient transformer training, (2) a new plugin system for custom logging and training, (3) new API docs for better documentation - still in beta, and (4) various new models, datasets, bug fixes and enhancements. This release also increases the minimum requirement to Python 3.8!
New Feature: Faster and more memory-efficient transformer trainingThis release integrates @helpmefindaname's transformer-smaller-training-vocab into the ModelTrainer. This temporarily reduces a transformer's vocabulary to only the tokens in the training dataset, and after training restores the full vocabulary. Depending on the dataset, this may effect huge savings in GPU memory and tuning speeds.
To use this feature, simply add the flag reduce_transformer_vocab=True
to the fine_tune
method. For example, to fine-tune a distilbert model on TREC_6, run this code (step 7 has the flag to reduce the vocabulary):
# 1. get the corpus corpus: Corpus = TREC_6() # 2. what label do we want to predict? label_type = "question_class" # 3. create the label dictionary label_dict = corpus.make_label_dictionary(label_type=label_type) # 4. initialize transformer document embeddings (many models are available) document_embeddings = TransformerDocumentEmbeddings("distilbert-base-uncased", fine_tune=True) # 5. create the text classifier classifier = TextClassifier(document_embeddings, label_dictionary=label_dict, label_type=label_type) # 6. initialize trainer trainer = ModelTrainer(classifier, corpus) # 7. fine-tune the model, but **reduce the vocabulary** for faster training trainer.fine_tune( "resources/taggers/question-classification-with-transformer", reduce_transformer_vocab=True, # set this to False for slow version )
Involved PR: add reduce transformer vocab plugin by @helpmefindaname in #3217
New Feature: Trainer PluginsA new "Plugin" system was added to the ModelTrainer
, allowing far greater options to customize the training cycle (and slimming down the code of the ModelTrainer somewhat). For instance, it is now possible to customize logging to a far greater degree and integrate third-party logging tools.
For instance, if you want to integrate ClearML logging into the above script, simply instantiate the plugin and attach it to the trainer:
[...] # 6. initialize trainer trainer = ModelTrainer(classifier, corpus) # NEW: instantiate a special logger and attach it to the trainer before the training run ClearmlLoggerPlugin(clearml.Task.init(project_name="test", task_name="test")).attach_to(trainer) # 7. fine-tune the model, but **reduce the vocabulary** for faster training trainer.fine_tune( "resources/taggers/question-classification-with-transformer", reduce_transformer_vocab=True, # set this to False for slow version )
Involved PRs:
ModelTrainer
train function by @plonerma in #3084We are working towards improving our documentation. A first step was the release of our tutorial page. Now, we are adding (in beta) online API docs to make navigating the code and options offered by Flair easier. To enable it, we changed all docstrings to Google docstrings. However, this process is still ongoing, so expect the API docs to improve in coming versions of Flair.
You can find the API docs here: https://flairnlp.github.io/flair/master/api/index.html
Involved PRs:
In an effort to unify class names, we now offer models that inherit from DefaultClassifier
for each label type we predict, i.e.:
TokenClassifier
for predicting Token
labelsTextPairClassifier
for predicting TextPair
labelsRelationClassifier
for predicting Relation
labelsSpanClassifier
for predicting Span
labelsTextClassifier
for predicting Sentence
labelsAn advantage of such a structure is that most functionality (such as new decoders) needs to only be implemented once in DefaultClassifier
and then is immediately usable for all model classes.
To enable this, we renamed and extended WordTagger
as TokenClassifier
, and renamed Entity Linker
to SpanClassifier
. This is not a breaking change yet, as the old names are still available. But in the future, WordTagger
and Entity Linker
will be removed.
Involved PRs:
TokenClassifier
model by @alanakbik in #3203We also add two new model classes: (1) a TextPairRegressor
for regression tasks on pairs of sentences (such as STS-B), and (2) an experimental Label Encoder method for few-shot classification.
Involved PRs:
TextPair
regression model by @plonerma in #3202LabelVerbalizer
so that it also works for non-BIOES span labes by @alanakbik in #3231flair/py.typed
and requirements.txt
in source distribution by @dobbersc in #3206to_dict
and add relations by @helpmefindaname in https...Another follow-up release to 0.12 that fixes a several bugs and adds a new multilingual frame tagger. Further, our new documentation website at https://flairnlp.github.io/docs/intro is now online!
New frame tagging model #3172Adds a new model for detecting PropBank frame. The model is trained using the "FLERT" approach, so it is much stronger than the previous 'frame' model. We also added some training data from the universal proposition bank to improve multilingual frame detection.
Use it like this:
# load the large frame model model = Classifier.load('frame-large') # English sentence with the verb "return" in two different senses sentence = Sentence("Dirk returned to Berlin to return his hat.") model.predict(sentence) print(sentence) # German sentence with the verb "trug" in two different senses sentence_de = Sentence("Dirk trug einen Koffer und trug einen Hut.") model.predict(sentence_de) print(sentence_de)
This should print:
Sentence[9]: "Dirk returned to Berlin to return his hat." → ["returned"/return.01, "return"/return.02] Sentence[9]: "Dirk trug einen Koffer und trug einen Hut." → ["trug"/carry.01, "trug"/wear.01]
The printout tells us that the verbs in both sentences are correctly disambiguated.
DocumentationThis is a quick follow-up release to 0.12 that fixes a few small bugs and includes an improved version of our Zelda entity linker.
New Entity Linking modelWe include a new version of our Zelda entity linker with improved predictions. Try it as follows:
from flair.nn import Classifier from flair.data import Sentence # load the model tagger = Classifier.load('linker') # make a sentence sentence = Sentence('Kirk and Spock met on the Enterprise.') # predict NER tags tagger.predict(sentence) # print predicted entities for label in sentence.get_labels(): print(label)
This should print:
Span[0:1]: "Kirk" → James_T._Kirk (0.9969) Span[2:3]: "Spock" → Spock (0.9971) Span[6:7]: "Enterprise" → USS_Enterprise_(NCC-1701-D) (0.975)
Indicating correctly that the span "Kirk" points to "James_T._Kirk". As the prediction for the string "Enterprise" shows, the model is still beta and will be further improved with future releases.
Bug fixesRelease 0.12 is out! This release greatly simplifies model usage for our users, includes our first entity linking model, adds support for the Ukrainian language, adds easy-to-use multitask learning, and many more features, improvements and bug fixes!
New Features Simplify Flair model usage #3067You can now load any Flair model through its parent class. Since most models inherit from Classifier
, you can load and run multiple different models with exactly the same code. So, to run three different taggers for sentiment, entities and frames, do:
from flair.data import Sentence from flair.nn import Classifier # load three taggers to tag entities, frames and sentiment tagger_1 = Classifier.load('ner') tagger_2 = Classifier.load('frame') tagger_3 = Classifier.load('sentiment') # example sentence sentence = Sentence('Dirk celebrated in Essen') # predict with all three models tagger_1.predict(sentence) tagger_2.predict(sentence) tagger_3.predict(sentence) # print all predictions for label in sentence.get_labels(): print(label)
With this change, users no longer need to know which model classes implement which model. For more advanced users who do know this, the regular way for loading a model still works:
sentiment_tagger = TextClassifier.load('sentiment')Entity Linking (BETA)
As of Flair 0.12 we ship an experimental entity linker trained on the Zelda dataset. The linker not only tags entities, but also attempts to link each entity to the corresponding Wikipedia URL if one exists.
To illustrate, let's use a short example text with two mentions of "Barcelona". The first refers to the football club "FC Barcelona", the second to the city "Barcelona".
from flair.nn import Classifier from flair.data import Sentence # load the model tagger = Classifier.load('linker') # make a sentence sentence = Sentence('Bayern played against Barcelona. The match took place in Barcelona.') # predict NER tags tagger.predict(sentence) # print sentence with predicted tags print(sentence)
This should print:
Sentence[12]: "Bayern played against Barcelona. The match took place in Barcelona." → ["Bayern"/FC_Bayern_Munich, "Barcelona"/FC_Barcelona, "Barcelona"/Barcelona]
As we can see, the linker can resolve what the two mentions of "Barcelona" refer to:
Additionally, the mention "Bayern" is linked to "FC_Bayern_Munich", telling us that here the football club is meant.
Entity linking support includes:
This version adds support for Ukrainian taggers, embeddings and datasets. For instance, to do NER and POS tagging of a Ukrainian sentence, do:
# Load Ukrainian NER and POS taggers from flair.models import SequenceTagger ner_tagger = SequenceTagger.load('ner-ukrainian') pos_tagger = SequenceTagger.load('pos-ukrainian') # Tag a sentence from flair.data import Sentence sentence = Sentence("Сьогодні в Знам’янці проживають нащадки поета — родина Шкоди.") ner_tagger.predict(sentence) pos_tagger.predict(sentence) print(sentence) # ”Сьогодні в Знам’янці проживають нащадки поета — родина Шкоди." → # [“Сьогодні"/ADV, "в"/ADP, "Знам’янці"/LOC, "Знам’янці"/PROPN, "проживають”/VERB, "нащадки"/NOUN, "поета"/NOUN, "—"/PUNCT, "родина"/NOUN, "Шкоди”/PERS, "Шкоди"/PROPN, "."/PUNCT]Multitask Learning (#2910 #3085 #3101)
We add support for multitask learning in Flair (closes #2508 and closes #1260) with hopefully a simple syntax to define multiple tasks that share parts of the model.
The most common part to share is the transformer, which you might want to fine-tune across several tasks. Instantiate a transformer embedding and pass it to two separate models that you instantiate as before:
# --- Embeddings that are shared by both models --- # shared_embedding = TransformerDocumentEmbeddings("distilbert-base-uncased", fine_tune=True) # --- Task 1: Sentiment Analysis (5-class) --- # corpus_1 = SENTEVAL_SST_GRANULAR() model_1 = TextClassifier(shared_embedding, label_dictionary=corpus_1.make_label_dictionary("class"), label_type="class") # -- Task 2: Binary Sentiment Analysis on Customer Reviews -- # corpus_2 = SENTEVAL_CR() model_2 = TextClassifier(shared_embedding, label_dictionary=corpus_2.make_label_dictionary("sentiment"), label_type="sentiment", ) # -- Define mapping (which tagger should train on which model) -- # multitask_model, multicorpus = make_multitask_model_and_corpus( [ (model_1, corpus_1), (model_2, corpus_2), ] ) # -- Create model trainer and train -- # trainer = ModelTrainer(multitask_model, multicorpus) trainer.fine_tune(f"resources/taggers/multitask_test")
The mapping part here defines which tagger should be trained on which corpus. By calling make_multitask_model_and_corpus
with a mapping, you get a corpus and model object that you can train as before.
We improve our FLERT model by now explicitly marking up context boundaries using a new [FLERT]
special token in our transformer embeddings. Our experiments show that the context marker leads to improved NER results:
[SEP]
91.38 +- 0.18 [FLERT]
91.56 +- 0.17 xlm-roberta-large none 93.73 +- 0.2 [SEP]
93.76 +- 0.13 [FLERT]
93.92 +- 0.14
In the table, none is the approach used in previous Flair versions. [SEP]
means using the standard separator symbol as context delimiter. [FLERT]
means using a new dedicated special token.
As [FLERT]
performs best in our experiments, the [FLERT]
context marker is now activated by default.
More details: Assume the current sentence is Peter Blackburn
and the previous sentence ends with to boycott British lamb .
, while the next sentence starts with BRUSSELS 1996-08-22 The European Commission
.
In this case,
use_context_separator=False
, the embedding is produced from this string: to boycott British lamb . Peter Blackburn BRUSSELS 1996-08-22 The European Commission
use_context_separator=True
, the embedding is produced from this string to boycott British lamb . [FLERT] Peter Blackburn [FLERT] BRUSSELS 1996-08-22 The European Commission
We integrate the transformer-smaller-training-vocab
library into the ModelTrainer
. With it, you can reduce the size of transformer models when training and evaluating models on specific datasets. This leads to faster training times and a smaller memory footprint. Documentation on this new feature will be added soon!
We now include BETA support a new type of relation extraction model that leads to much higher accuracies than our vanilla relation extraction, but increases computational costs. Documentation for this will be added as we iterate on the model.
ONNX compatible models #2640 #2643 #3041 #3075This release continues the journey on making our models more ONNX compatible.
Other featuresexclude_labels
parameter to trainer.train #2724 ...Release 0.11 is taking us ever closer to that 1.0 release! This release makes large internal refactorings and code quality / efficiency improvements to prepare Flair 1.0. We also add new features such as text clustering, a regular expression tagger, more dataset manipulation options, and some preview features like a prototype decoder.
New Features Regular Expression Tagger (#2533)You can now do sequence labeling in Flair with regular expressions! Simply define a RegexpTagger
and add some regular expressions, like in the example below:
# sentence with a number and two quotes sentence = Sentence('Figure 11 is both "too colorful" and "not informative enough".') # instantiate regex tagger with a quote matching pattern tagger = RegexpTagger(mapping=(r'(["\'])(?:(?=(\\?))\2.)*?\1', 'QUOTE')) # also add a number mapping tagger.register_labels(mapping=(r'\b\d+\b', 'NUMBER')) # tag sentence tagger.predict(sentence) # check out matches for entity in sentence.get_labels(): print(entity)Clustering with Flair (#2573 #2619)
Flair now supports clustering by ways of sklearn. Embed your sentences with a pre-trained embedding like below, then cluster then with any algorithm. Check the example below where we use sentence transformers and k-means clustering. A 'trained' clustering model can be saved and loaded for prediction, just like and other Flair classifier:
from sklearn.cluster import KMeans from flair.data import Sentence from flair.datasets import TREC_6 from flair.embeddings import SentenceTransformerDocumentEmbeddings from flair.models import ClusteringModel embeddings = SentenceTransformerDocumentEmbeddings() # store all embeddings in memory which is required to perform clustering corpus = TREC_6(memory_mode='full').downsample(0.05) clustering_model = ClusteringModel(model=KMeans(n_clusters=6), embeddings=embeddings) # fit the model on a corpus clustering_model.fit(corpus) # save the model clustering_model.save(model_file="clustering_model.pt") # load saved clustering model model = ClusteringModel.load(model_file="clustering_model.pt") # make example sentence sentence = Sentence('Getting error in manage categories - not found for attribute "navigation _ column"') # predict for sentence model.predict(sentence) # print sentence with prediction print(sentence)Dataset Manipulations
You can now change label names, ignore labels and add custom preprocessing when loading a dataset.
For instance, the standard WNUT_17 dataset comes with 7 NER labels:
corpus = WNUT_17(in_memory=False) print(corpus.make_label_dictionary('ner'))
which prints:
Dictionary with 7 tags: <unk>, person, location, group, corporation, product, creative-work
With the following code, you rename some labels ('person' is renamed to 'PER'), merge 2 labels into 1 ('group' and 'corporation' are merged into 'LOC'), and ignore 2 other labels ('creative-work' and 'product' are ignored):
corpus = WNUT_17(in_memory=False, label_name_map={ 'person': 'PER', 'location': 'LOC', 'group': 'ORG', 'corporation': 'ORG', 'product': 'O', 'creative-work': 'O', # by renaming to 'O' this tag gets ignored })
which prints:
Dictionary with 4 tags: <unk>, PER, LOC, ORG
You can manipulate the data even more with custom preprocessing functions. See the example in #2708.
Other New Features and Data SetsWordTagger
class for simple word-level predictions (#2607)WordEmbeddings
can now be fine-tuned in Flair (#2491) by setting fine_tune=True. Also adds fine-tuning mode of https://arxiv.org/abs/2110.02861 which seem to "reduce gradient variance that comes from the highly non-uniform distribution of input tokens"NER_MULTI_CONER
Dataset (#2507)Some preview features in beta stage, use at your own risk.
Prototypical networks in Flair (#2627)Prototype networks learn prototypes for each target class. For each data point to be classified, the network predicts a vector in class-prototype-space, which is then compared to all class prototypes.The prediction is then the closest class prototype. See paper Prototypical Networks for Few-shot Learning for more info.
@plonerma implemented a custom decoder that can be added to any Flair model that inherits from DefaultClassifier
(i.e. early all Flair models). For instance, use this script:
from flair.data import Corpus from flair.datasets import UP_ENGLISH from flair.embeddings import TransformerWordEmbeddings from flair.models import WordTagger from flair.nn import PrototypicalDecoder from flair.trainers import ModelTrainer # what tag do we want to predict? tag_type = 'frame' # get a corpus corpus: Corpus = UP_ENGLISH().downsample(0.1) # make the tag dictionary from the corpus tag_dictionary = corpus.make_label_dictionary(label_type=tag_type) # initialize simple embeddings embeddings = TransformerWordEmbeddings(model="distilbert-base-uncased", fine_tune=True, layers='-1') # initialize prototype decoder decoder = PrototypicalDecoder(num_prototypes=len(tag_dictionary), embeddings_size=embeddings.embedding_length, distance_function='euclidean', normal_distributed_initial_prototypes=True, ) # initialize the WordTagger, but pass the prototype decoder tagger = WordTagger(embeddings, tag_dictionary, tag_type, decoder=decoder) # initialize trainer trainer = ModelTrainer(tagger, corpus) # run training trainer.fine_tune('resources/taggers/prototypical_decoder')Other Beta features
With Flair expanding to many new NLP tasks (relation extraction, entity linking, etc.) and model types, we made a number of refactorings to reduce redundancy and make it easier to extend Flair.
Major refactoring of Label Logic in Flair (#2607 #2609 #2645)The labeling logic was growing too complex to accommodate new tasks. With this release, we refactored this logic such that complex label classes like SpanLabel
, RelationLabel
etc. are removed in favor of a single Label
class for all types of label. The Sentence
object will now be automatically aware of all labels added to it.
To illustrate the difference, consider a before-and-after of how to add an entity label to a sentence.
Before:
# example sentence sentence = Sentence("Humboldt Universität zu Berlin is located in Berlin .") # create span for "Humboldt Universität zu Berlin" span = Span(sentence[0:4]) # make a Span-label span_label = SpanLabel(span=span, value='University') # add Span-label to sentence sentence.add_complex_label(typename='ner', label=span_label)
Now:
# example sentence sentence = Sentence("Humboldt Universität zu Berlin is located in Berlin .") # directly add a label to the span "Humboldt Universität zu Berlin" sentence[0:4].add_label("ner", "Organization")
So you can now just get a span from the sentence and add a label to it directly. It will get registered on the sentence as well.
Refactoring of printouts (#2704)We changed and unified printouts across all Flair data points and labels, and updated the documentation to reflect this. Printouts should hopefully now be more concise. Let us know what you think.
Unified classes to reduce redundancyNext to too many Label classes (see above), we also had too many corpora that essentially do the same thing, two partially overlapping transformer embedding classes and too much redundancy in our tokenization classes. This release makes many refactorings to make the code more maintainable:
ColumnCorpus
, UniversalDependenciesCorpus
, CoNNLuCorpus
, and EntityLinkingCorpus
, which resulted in too much redundancy. Now, there is only the ColumnCorpus
for all such datasetsTransformerWordEmbedding
and TransformerDocumentEmbedding
. Thanks to @helpmefindaname, they now both inherit from the same base object and now share all features.Tokenizer
classes no longer return lists of Token
, rather lists of strings that the Sentence
object converts to tokens, centralizing the offset and whitespace_after detection in one place.The DefaultClassifier
is the base class for nearly all models in Flair. With this release, we make a number of simplifications to reduce redundancy across classes and make it more modular.
forward_pass
simplified to return 3 instead of 4 argumentsforward_pass
returns embeddings instead of logits allowing us to easily switch out the decoder (see Beta feature on Prototype Networks below)spawn
logic we no longer need due to Label refactoringMajor refactoring of SequenceTagger
for better modularity and cod...
This release adds several new features such as in-built "model cards" for all Flair models, the first pre-trained models for Relation Extraction, better support for fine-tuning and a refactoring of the model training methods for more flexibility. It also fixes a number of critical bugs that were introduced by the refactorings in Flair 0.9.
Model Trainer EnhancementsBreaking change: We changed the ModelTrainer
such that you now no longer pass the optimizer during initialization. Rather, it is now passed as a parameter of the train
or fine_tune
method.
Old syntax:
# 1. initialize trainer with AdamW optimizer trainer = ModelTrainer(classifier, corpus, optimizer=torch.optim.AdamW) # 2. run training with small learning rate and mini-batch size trainer.train('resources/taggers/question-classification-with-transformer', learning_rate=5.0e-5, mini_batch_size=4, )
New syntax (optimizer is parameter of train method):
# 1. initialize trainer trainer = ModelTrainer(classifier, corpus) # 2. run training with AdamW, small learning rate and mini-batch size trainer.train('resources/taggers/question-classification-with-transformer', learning_rate=5.0e-5, mini_batch_size=4, optimizer=torch.optim.AdamW, )Convenience function for fine-tuning (#2439)
Adds a fine_tune
routine that sets default parameters used for fine-tuning (AdamW optimizer, small learning rate, few epochs, cyclic learning rate scheduling, etc.). Uses the new linear scheduler with warmup (#2415).
New syntax with fine_tune
method:
from flair.data import Corpus from flair.datasets import TREC_6 from flair.embeddings import TransformerDocumentEmbeddings from flair.models import TextClassifier from flair.trainers import ModelTrainer # 1. get the corpus corpus: Corpus = TREC_6() # 2. what label do we want to predict? label_type = 'question_class' # 3. create the label dictionary label_dict = corpus.make_label_dictionary(label_type=label_type) # 4. initialize transformer document embeddings (many models are available) document_embeddings = TransformerDocumentEmbeddings('distilbert-base-uncased', fine_tune=True) # 5. create the text classifier classifier = TextClassifier(document_embeddings, label_dictionary=label_dict, label_type=label_type) # 6. initialize trainer trainer = ModelTrainer(classifier, corpus) # 7. run training with fine-tuning trainer.fine_tune('resources/taggers/question-classification-with-transformer', learning_rate=5.0e-5, mini_batch_size=4, )Model Cards (#2457)
When you train any Flair model, a "model card" will now automatically be saved that stores all training parameters and versions used to train this model. Later when you load a Flair model, you can print the model card and understand how the model was trained.
The following example trains a small POS-tagger and prints the model card in the end:
# initialize corpus and make label dictionary for POS tags corpus = UD_ENGLISH().downsample(0.01) tag_type = "pos" tag_dictionary = corpus.make_label_dictionary(tag_type) # simple sequence tagger tagger = SequenceTagger(hidden_size=256, embeddings=WordEmbeddings("glove"), tag_dictionary=tag_dictionary, tag_type=tag_type) # initialize model trainer and experiment path trainer = ModelTrainer(tagger, corpus) path = f'resources/taggers/model-card' # train for a few epochs trainer.train(path, max_epochs=20, ) # load best model and print "model card" trained_model = SequenceTagger.load(path + '/best-model.pt') trained_model.print_model_card()
This should print a model card like:
------------------------------------
--------- Flair Model Card ---------
------------------------------------
- this Flair model was trained with:
-- Flair version 0.9
-- PyTorch version 1.7.1
-- Transformers version 4.8.1
------------------------------------
------- Training Parameters: -------
------------------------------------
-- base_path = resources/taggers/model-card
-- learning_rate = 0.1
-- mini_batch_size = 32
-- mini_batch_chunk_size = None
-- max_epochs = 20
-- train_with_dev = False
-- train_with_test = False
[... shortened ...]
------------------------------------
Resume training any model (#2457)
Previously, we distinguished between checkpoints and model files. Now all models can function as checkpoints, meaning you can load them and continue training them. Say you want to load the model above (trained to epoch 20) and continue training it to epoch 25. Do it like this:
# resume training best model, but this time until epoch 25 trainer.resume(trained_model, base_path=path + '-resume', max_epochs=25, )Pass optimizer and scheduler instance
You can also now pass an initialized optimizer and scheduler to the train and fine_tune methods.
Multi-Label Predictions and Confidence Threshold in TARS models (#2430)Adding the possibility to set confidence thresholds on multi-label prediction in TARS, and setting whether a problem is single-label or multi-label:
from flair.models import TARSClassifier from flair.data import Sentence # 1. Load our pre-trained TARS model for English tars: TARSClassifier = TARSClassifier.load('tars-base') # switch to a multi-label task (emotion detection) tars.switch_to_task('GO_EMOTIONS') # sentence with two emotions sentence = Sentence("I am happy and sad") # predict normally tars.predict(sentence) print(sentence) # predict with lower label threshold (you can set this to 0. to get all labels) tars.predict(sentence, label_threshold=0.01) print(sentence) # predict and enforce a single-label prediction tars.predict(sentence, label_threshold=0.01, multi_label=False) print(sentence)Relation Extraction ( #2471 #2492)
We refactored the RelationExtractor for more options, hopefully better code clarity and small speed improvements.
We also added two few relation extraction models, trained over a modified version of TACRED: relations
and relations-fast
. To use these models, you also need an entity tagger. The tagger identifies entities, then the relation extractor possible entities.
For instance use this code:
from flair.data import Sentence from flair.models import RelationExtractor, SequenceTagger # 1. make example sentence sentence = Sentence("George was born in Washington") # 2. load entity tagger and predict entities tagger = SequenceTagger.load('ner-fast') tagger.predict(sentence) # check which entities have been found in the sentence entities = sentence.get_labels('ner') for entity in entities: print(entity) # 3. load relation extractor extractor: RelationExtractor = RelationExtractor.load('relations-fast') # predict relations extractor.predict(sentence) # check which relations have been found relations = sentence.get_labels('relation') for relation in relations: print(relation)Embeddings
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4