<jupyter_start><jupyter_text>Skript4: Finetuning eines Multilanguage BERT-Modells für NER anhand von GermEval2014Dieses Notebook beschreibt das Training eines Transformer Modells für die Task des Named Entity Recognition. Es wird ein BERT-Modell mit der nativen Hugging Face Transformers Bibliothek trainiert. Das Training erfolgt gemäß des Splits wie es die Shared Task 2014 vorgab.<jupyter_code># Installation der benötigten Bibliotheken
#!pip install transformers
#!pip install datasets<jupyter_output><empty_output><jupyter_text>Zunächst werden die Skriptparameter gesetzt. Die `task` Variable gibt an, für welche Aufgabe das Modell trainiert werden soll.`ner` steht hier für Named Entity Recognition, dabei handelt es sich um ein Token-Klassifizierungsproblem. Die Variable `model_checkpoint` beinhaltet den Namen des zu nutzenden vortrainierten Transformer Modells. Das Modell `bert-base-multilingual-cased` ist ein BERT-Modell, welches mithilfe von Texten in 104 unterschiedlichen Sprachen trainiert wurde. Der Name kann durch einen beliebigen Modellcheckpoint aus dem Transformers Model Hub ersetzt werden:  https://huggingface.co/models<jupyter_code>task = "ner"
model_checkpoint = 'bert-base-multilingual-cased'
batch_size=32<jupyter_output><empty_output><jupyter_text>Herunterladen des Datasets germeval2014 Neben der Transformers Bibliothek bietet die Hugging Face Inc. mit der `Datasets` Bibliothek eine Sammlung von Datensätzen und Metriken zum herunterladen an. Um diese zu nutzen, werden zuerst die beiden Methoden `load_dataset` und `load_metric` importiert.<jupyter_code>from datasets import load_dataset, load_metric<jupyter_output><empty_output><jupyter_text>Ebenso wie es für die vortrainierten Modelle einen Hub gibt, gibt es einen Hub für die verfügbaren Datasets: https://huggingface.co/datasets/germeval_14. Mit der Methode `load_dataset` kann das Dataset anschließend heruntergeladen werden.<jupyter_code>datasets = load_dataset("germeval_14")<jupyter_output><empty_output><jupyter_text>Exploration des Aufbaus der Daten Das heruntergeladene Dataset ist ein `DatasetDcit-Objekt`, welches die Keys `train, validation` und `test` besitzt. Der Value für jeden Key ist das `Dataset-Objekt`, welches die jeweiligen Daten für den Split enthält. Im Falle des GermEval2014 Datasets bestehen die Daten aus insgesamt 31300 Datensätzen mit den Features `id, source, tokens, ner_tags` und `nested_ner_tags`. Die `nested_ner_tags` finden im Rahmen dieses Anwendungsbeispiels keine Verwendung.<jupyter_code>datasets<jupyter_output><empty_output><jupyter_text>Möchte man auf ein einzelnes Item aus dem Datensatz zugreifen, so wählt man den Key des Splits aus wählt anschließend den Index des gewünschten Items aus:<jupyter_code>print(datasets["train"][0])<jupyter_output>{'id': '0', 'ner_tags': [19, 0, 0, 0, 7, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'nested_ner_tags': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'source': 'n-tv.de vom 26.02.2005 [2005-02-26] ', 'tokens': ['Schartau', 'sagte', 'dem', '"', 'Tagesspiegel', '"', 'vom', 'Freitag', ',', 'Fischer', 'sei', '"', 'in', 'einer', 'Weise', 'aufgetreten', ',', 'die', 'alles', 'andere', 'als', 'überzeugend', 'war', '"', '.']}<jupyter_text>Die NER Tags sind bereits Integer ID codiert:<jupyter_code>datasets["train"][0]['ner_tags']<jupyter_output><empty_output><jupyter_text>Das zugehörige Textlabel findet man unter dem `features`-Attribut des Datasets. Das Dataset GermEval2014 besitzt insgesamt 25 verschiedene Klassen:<jupyter_code>datasets["train"].features["ner_tags"]<jupyter_output><empty_output><jupyter_text>Die Klassenliste der Label kann wie folgt extrahiert werden:<jupyter_code>label_list = datasets["train"].features[f"{task}_tags"].feature.names
label_list<jupyter_output><empty_output><jupyter_text>Visualisierung von zufälligen Beispieldaten aus dem Dataset Die folgende Funktion wählt zufällig `N` Items aus dem übergebenen Dataset aus und gibt diese in einem `Pandas DataFrame` aus. Dabei werden die `ner_tags` in ihre entsprechenden Textlabel dekodiert.<jupyter_code># Quelle in Anlehnung an: https://colab.research.google.com/github/huggingface/notebooks/blob/master/examples/text_classification.ipynb#scrollTo=X6HrpprwIrIz
from datasets import ClassLabel, Sequence
import random
import pandas as pd
from IPython.display import display, HTML

def show_random_elements(dataset, num_examples=10,seed=None):
    assert num_examples <= len(dataset), "Can't pick more elements than there are in the dataset."
    picks = []
    random.seed(seed)
    #Befüllen mit Random indexes
    for _ in range(num_examples):
        pick = random.randint(0, len(dataset)-1)
        while pick in picks:
            random.seed(seed)
            pick = random.randint(0, len(dataset)-1)
        picks.append(pick)
    
    df = pd.DataFrame(dataset[picks])
    for column, typ in dataset.features.items():
       # print(column)
       # print(typ)
        if isinstance(typ, ClassLabel):
            df[column] = df[column].transform(lambda i: typ.names[i])
            #die zeile hier unten ist aktiv
        elif isinstance(typ, Sequence) and isinstance(typ.feature, ClassLabel):
            df[column] = df[column].transform(lambda x: [typ.feature.names[i] for i in x])
    display(HTML(df.to_html()))<jupyter_output><empty_output><jupyter_text>Die Methode kann nun dazu genutzt werden, eine tabellarische Ausgabe von Beispieldaten aus dem Dataset zu erzeugen. Dafür übergibt man das `datasets` Objekt und gibt den gewünschten Split an:<jupyter_code>show_random_elements(datasets["train"], seed = 43)<jupyter_output><empty_output><jupyter_text>Preprocessing der Daten Für das Preprocessign der Daten wird der Tokenizer des genutzen Modells benötigt. Dieser kann durch den folgenden Methodenaufruf heruntergeladen werden. `AutoTokenizer.from_pretrained()` lädt den zum Modell passenden Tokenizer sowie das Vokabular, welches für das Pretraining des Modelcheckpoints genutzt wurde, herunter.<jupyter_code>from transformers import  AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint, use_fast = True)<jupyter_output><empty_output><jupyter_text>Der Tokenizer kann direkt genutzt werden, um eine Inputsequenz zu tokenisieren. Dabei erhält man ein Dictionary mit Mappings zu den input_ids, token_type_ids und eine attention_mask.Die input_id ist die Identifikation des jeweiligen Tokens im Vokabluar des Modells.Token_type_ids markieren Tokens in Seq2Seq Tasks und geben dem Modell Informationen darüber, zu welchem Teil einer zweiteiligen Eingabesequenz ein Token gehört.Die attention_mask teilt dem Modell mit, für welche Token die Attention berechnet werden soll. Ist eine Eingabesequenz z. B. sehr kurz im Gegensatz zu den anderen, dann wird diese per Padding auf die gleiche Länge gebracht. Die attention_mask verhindert anschließend, dass die Attention für diese Padding Token berechnet wird. Übergibt man dem Tokenizer nun eine String Sequenz, erhält man die oben beschriebene Ausgabe zurück:<jupyter_code>tokenizer("Hallo, das ist ein Satz!")<jupyter_output><empty_output><jupyter_text>Wenn im Datensatz, wie hier gegeben (Germeval_2014) die Inputs schon in einzelne Wörter gesplittet sind, dann kann man diese Liste und den Parameter `is_split_into_words=True` an den Tokenizer übergeben:<jupyter_code>tokenizer(["Hallo",",","das", "ist", "ein","Satz","der","in","Wörter","aufgeteilt","wurde","!"],is_split_into_words=True)<jupyter_output><empty_output><jupyter_text>Alignment- Problematik Transformer Tokenizer nutzen meistens Subword Tokenizer, daher kann es vorkommen, dass selbst diese Wortliste noch in weitere Token zerlegt wird:<jupyter_code>example = datasets["train"][5]
print(example["tokens"])
tokenized_input = tokenizer(example["tokens"],is_split_into_words=True)
tokens = tokenizer.convert_ids_to_tokens(tokenized_input["input_ids"])
print(tokens)<jupyter_output>['[CLS]', 'ARD', '-', 'Programm', '##chef', 'Günter', 'St', '##ru', '##ve', 'war', 'wegen', 'eines', 'vier', '##w', '##ö', '##chi', '##gen', 'Ur', '##laub', '##s', 'für', 'eine', 'Stellung', '##nahme', 'nicht', 'erre', '##ich', '##bar', '.', '[SEP]']<jupyter_text>Hier wurde zum Beispiel "Struve" in 3 Subtoken zerlegt und "vierwöchigen" sogar in 5 Subtoken.Des Weiteren fällt auf, dass das hier verwendete Multilanguage BERT-Modell die Token in eine größere Anzahl von Subtokens zerlegt. Dies ist auch nachvollziehbar, da das Vokabular des Modells 104 Sprachen anstatt nur eine Sprache wie das deutsche BERT-Modell abdecken muss. Jeder Subtoken nimmt nämlich einen Platz im Vokabular des Modells ein.Durch das Einfügen von SpecialToken [CLS] und [SEP] sowie die Subword Tokenisierung ist die Liste der Token länger als die Liste der zugehörigen Tags. Das Allignment aus dem Dataset ist somit kaputt:<jupyter_code>len(example[f"{task}_tags"]),len(tokenized_input['input_ids'])<jupyter_output><empty_output><jupyter_text>Um dieses Problem zu lösen und das Alignment wiederherzustellen besitzt das Rückgabeobjektdes Tokenizer die `word_ids()` Methode.- Sie liefert eine Liste die genauso lang ist, wie die Liste mit den Input-IDs- Sie mapped Special Token zu `None` und alle anderen zum zugehörigen Original Wort-Input, bspw. markiert eine `0` die Zugehörigkeit des Subtokens zum ersten Token der Eingabesequenz<jupyter_code>tokenized_input.word_ids()<jupyter_output><empty_output><jupyter_text>Nun kann man das Alignment zwischen den `ner_tags` und den `input_ids` wiederherstellen. Im Ergbnis haben die Label und die Input_ids die gleiche Anzahl.<jupyter_code>word_ids = tokenized_input.word_ids()
aligned_labels = [-100 if i is None else example[f"{task}_tags"][i] for i in word_ids]
print(len(aligned_labels), len(tokenized_input["input_ids"]))<jupyter_output>30 30<jupyter_text>Mit der obigen Funktion wurden die `ner_tags` für die eingefügten Special Token  auf -100 gestellt und somit von Pytorch ignoriert. Die anderen `input_ids` haben das entsprechene Label ihres zugehörigen Wortes erhalten. Eine andere Strategie ist es nur das Label für den ersten Token eines Wortes zu setzen und -100 für die weiteren Subtoken des Wortes zu vergeben. Dafür muss folgendes Flag geädnert werden:<jupyter_code>label_all_tokens = True<jupyter_output><empty_output><jupyter_text>Preprocessing Funktion Mit der folgenden Funktion werden die übergebenen Datensätze des Datasets zunächst tokenisiert und anschließend werden die `ner_tags` mit den tokenisierten `input_ids` alligned. Dafür wird ein `labels` Attribut angelegt, welches diese Zuordnung enthält. Als Rückgabe erhält man die um das `labels` Attribut erweiterte Ausgabe des Tokenizers.<jupyter_code># Quelle https://colab.research.google.com/github/huggingface/notebooks/blob/master/examples/token_classification.ipynb#scrollTo=n9qywopnIrJH
def tokenize_and_align_labels(examples):
    # Tokenisierung der Eingabetoken
    tokenized_inputs = tokenizer(examples["tokens"], truncation=True, is_split_into_words=True)
    labels = []
    
    for i, label in enumerate(examples[f"{task}_tags"]):
        word_ids = tokenized_inputs.word_ids(batch_index=i)
        previous_word_idx = None
        label_ids = []
        for word_idx in word_ids:
            # Special Tokens haben den Wert None als word id. Durch das Setzen des Wertes -100 als Label
            # wird dieser Token automatisch in der Loss Funktion ignoriert.
            if word_idx is None:
                label_ids.append(-100)
            # Setzen des Labels für den ersten Token eines Wortes.
            elif word_idx != previous_word_idx:
                label_ids.append(label[word_idx])
            # Abhängig vom label_all_tokems_flag wird für den nächsten Token eines Wortes das gleiche Label oder -100
            # gesetzt
            else:
                label_ids.append(label[word_idx] if label_all_tokens else -100)
            previous_word_idx = word_idx

        labels.append(label_ids)

    tokenized_inputs["labels"] = labels
    return tokenized_inputs<jupyter_output><empty_output><jupyter_text>Die Funktion kann mit einem oder mehreren Examples genutzt werden. Wenn mehrere Datensätze übergeben werden, dann gibt der interne Tokenizer der Funktion eine  Liste mit Listen für jeden Key zurück:<jupyter_code>tokenize_and_align_labels(datasets['train'][:3])<jupyter_output><empty_output><jupyter_text>Um die Funktion auf alle Datensätze im Datensatz anzuwenden kann man die `map` Methode des `datasets` Objekts nutzen. Dies wendet die Funktion auf alle Splits im `dataset` an, (training, valid, test set werden alle mit der einen Zeile Code preprocessed). - Durch `batched=True` wird dem Tokenizer ermöglicht mehrere Datensätze parallel zu verarbeiten<jupyter_code>tokenized_dataset = datasets.map(tokenize_and_align_labels,batched=True)<jupyter_output><empty_output><jupyter_text>Durch das Preprocessing werden die Ausgaben des Tokenizers als Features des DataSets ergänzt.In den folgenden Ausgaben sieht man, dass nun die `attention_mask, die input_ids, die labels und die token_type_ids` als Features ergänzt wurden.<jupyter_code>tokenized_dataset
show_random_elements(tokenized_dataset["train"],seed=43,num_examples=2)<jupyter_output><empty_output><jupyter_text>Finetuning des Models Für die Konstruktion des Modells wird ein Label-ID Mapping erzeugt. Dieses Mapping wird anschließend in der Configuration des Modells hinterlegt. Es ermöglicht dem Modell die vorhergesagten Label als Texte auszugeben anstatt ihrer numerischen Kodierung.<jupyter_code>id2label = {}
label2id= {}
for i,l in enumerate(label_list):
    id2label[str(i)] = l
    label2id[l]=str(i)
print(id2label)
print(label2id)<jupyter_output>{'0': 'O', '1': 'B-LOC', '2': 'I-LOC', '3': 'B-LOCderiv', '4': 'I-LOCderiv', '5': 'B-LOCpart', '6': 'I-LOCpart', '7': 'B-ORG', '8': 'I-ORG', '9': 'B-ORGderiv', '10': 'I-ORGderiv', '11': 'B-ORGpart', '12': 'I-ORGpart', '13': 'B-OTH', '14': 'I-OTH', '15': 'B-OTHderiv', '16': 'I-OTHderiv', '17': 'B-OTHpart', '18': 'I-OTHpart', '19': 'B-PER', '20': 'I-PER', '21': 'B-PERderiv', '22': 'I-PERderiv', '23': 'B-PERpart', '24': 'I-PERpart'}
{'O': '0', 'B-LOC': '1', 'I-LOC': '2', 'B-LOCderiv': '3', 'I-LOCderiv': '4', 'B-LOCpart': '5', 'I-LOCpart': '6', 'B-ORG': '7', 'I-ORG': '8', 'B-ORGderiv': '9', 'I-ORGderiv': '10', 'B-ORGpart': '11', 'I-ORGpart': '12', 'B-OTH': '13', 'I-OTH': '14', 'B-OTHderiv': '15', 'I-OTHderiv': '16', 'B-OTHpart': '17', 'I-OTHpart': '18', 'B-PER': '19', 'I-PER': '20', 'B-PERderiv': '21', 'I-PERderiv': '22', 'B-PERpart': '23', 'I-PERpart': '24'}<jupyter_text>Erzeugen und Konfiguration des Modells mit Label-ID Mapping: - `AutoModelForTokenClassification.from_pretrained` lädt automatisch das entsprechende Modell herunter und initialisiert einen Token-Klassifizierungskopf am Ende des Modells. - Die auftretenden Warnungen geben nur Auskunft darüber, dass der Kopf des Modells ausgetauscht wurde und demzufolge keine trainierten Weights hat<jupyter_code>from transformers import  AutoModelForTokenClassification, TrainingArguments, Trainer
model = AutoModelForTokenClassification.from_pretrained(model_checkpoint, num_labels=len(label_list), id2label=id2label, label2id=label2id)<jupyter_output><empty_output><jupyter_text>Vorbereitung für die Erzeugung des `Trainers`:Es müssen zunächst die `TrainingArguments` konfiguriert werden, dabei handelt es sich um die Hyperparameter des Trainings: - Dazu zählen z.B. die Anzahl der Epoch, die Learning Rate, die Batchsize und der weight_decay - `load_best_model_at_end` und `metric_for_best_model` sorgen dafür, dass am Ende des Trainings das Model mit der höchsten `F1_Score` geladen wird<jupyter_code>metric_name = 'eval_f1'
args = TrainingArguments(
    f"test-{task}",
    evaluation_strategy = "epoch",
    learning_rate=2e-5,
    per_device_train_batch_size=batch_size,
    per_device_eval_batch_size=batch_size,
    num_train_epochs=5,
    weight_decay=0.01,
    load_best_model_at_end=True,
    metric_for_best_model=metric_name,
)<jupyter_output><empty_output><jupyter_text>Der `DataCollator` fügt die Beispieldaten zu Batches zusammen und fügt das nötige Padding für die Inputs und Labels ein. (Hierfür wird die Länge des längsten Datensatzes gewählt)<jupyter_code>from transformers import DataCollatorForTokenClassification

data_collator = DataCollatorForTokenClassification(tokenizer)<jupyter_output><empty_output><jupyter_text>Damit das Modell während des Trainings die gewünschten Metriken berechnen kann, muss eine Funktion definiert werden die diese Metriken berechnet. Das übernimmt die `compute_metric` Funktion:- Die Datasets Bibliothek ermöglicht es, Funktionen zur Berechnung von Metriken herunterzuladen.- `Seqeval` eignet sich gut für Tasks im Bereich der TokenClassification: https://github.com/chakki-works/seqeval<jupyter_code>#Installieren von seqeval falls nötig
#!pip install seqeval<jupyter_output><empty_output><jupyter_text>Mit `load_metric` kann man eine gewünschte Funktion aus der Datasets Bibliothek herunterladen:<jupyter_code>metric = load_metric("seqeval")<jupyter_output><empty_output><jupyter_text>Beispiel für die Anwendung der Metrik Um die Metriken zu berechnen, müssen der Funktion 2 Listen an die Parameter `predictions` und ` references` übergeben werden.  Für dieses Beispiel wird die Labelliste für den `predictions` Parameter durch ein Mapping der `ner_tags` auf die Indizies der `label_list` erstellt:<jupyter_code>labels = [label_list[i] for i in example[f"{task}_tags"]]
labels<jupyter_output><empty_output><jupyter_text>Für den `references` Parameter wird die Labelsliste leicht angepasst:<jupyter_code>labels_ref = labels.copy()
labels_ref[-1] = 'B-ORGpart'
labels_ref<jupyter_output><empty_output><jupyter_text>Anschließend kann die `compute` Methode des Metrikobjekts benutzt werden, um die Metrik zu berechnen:<jupyter_code>metric.compute(predictions=[labels], references=[labels_ref])<jupyter_output><empty_output><jupyter_text>Damit diese Metrik vom Modell berechnet werden kann, muss sie in eine Funktion gewrappt werden.Diese Funktion erhält während des Trainings das Ergebnis des Methodenaufrufs `Trainer.evaluate`. Dabei handelt es sich um ein Tuple aus den `predictions` und den tatsächlichen `labels`. Die `predictions` sind der letzte Hidden State des Modells, daher muss hiervon der maximale Wert ausgewählt werden, um tatsächlich vorhergesagten Wert zu erhalten. Die Funktion `compute_metrics` kümmert sich um das nötige Postprocessing und gibt die berechneten Metriken zurück.<jupyter_code>import numpy as np

def compute_metrics(p):
    # Unpacking des Tuple p
    predictions, labels = p
    # Größten Wert für die jeweilige Prediction auswählen
    predictions = np.argmax(predictions, axis=2)

    # Ignorieren aller Werte mit -100
    true_predictions = [
        [label_list[p] for (p, l) in zip(prediction, label) if l != -100]
        for prediction, label in zip(predictions, labels)
    ]
    true_labels = [
        [label_list[l] for (p, l) in zip(prediction, label) if l != -100]
        for prediction, label in zip(predictions, labels)
    ]

    results = metric.compute(predictions=true_predictions, references=true_labels)
    return {
        "precision": results["overall_precision"],
        "recall": results["overall_recall"],
        "f1": results["overall_f1"],
        "accuracy": results["overall_accuracy"],
    }<jupyter_output><empty_output><jupyter_text>- hier wird die Ausgabe pro Kategorie weggelassen und nur Gesamt precision/recall/f1/accuracy  ausgegeben Anschließend kann der `Trainer` erzeugt werden. Diesem wird das Modell, die Hyperparameter, die Trainings- und Evaluierungsdatensätze, der Tokenizer, der DataCollator sowie die `compute_metrics` Funktion übergeben.<jupyter_code>trainer = Trainer(
    model,
    args,
    train_dataset =tokenized_dataset["train"],
    eval_dataset =tokenized_dataset["validation"],
    data_collator = data_collator,
    tokenizer = tokenizer,
    compute_metrics = compute_metrics
)<jupyter_output><empty_output><jupyter_text>Nun kann das Training mit der `train` Methode gestartet werden<jupyter_code>trainer.train()<jupyter_output><empty_output><jupyter_text>Mit der evaluate Methode kann man das Model nochmals gegen das hinterlegte Dataset oder ein anderes Dataset validieren.<jupyter_code>trainer.evaluate()<jupyter_output><empty_output><jupyter_text>Evaluieren gegen das ungesehene Testset:<jupyter_code>trainer.evaluate(tokenized_dataset["test"])<jupyter_output><empty_output><jupyter_text>Im Anschluss kann man wieder die Precision/recall/f1/accuracy pro Kategorie berechnen indem man die `predict` Methode nutzt. Dazu wird die folgende `evaluate_all_categories` definiert. Sie erhält ein tokenisiertes Dataset als Eingabeparameter. Anschließend wird die Metrik für jede enthaltene Kategorie berechnet.<jupyter_code>def evaluate_all_categories(tokenized_dataset):
    predictions, labels, _ = trainer.predict(tokenized_dataset)
    predictions = np.argmax(predictions, axis=2)

    true_predictions = [
        [label_list[p] for (p, l) in zip(prediction, label) if l != -100]
        for prediction, label in zip(predictions, labels)
    ]
    true_labels = [
        [label_list[l] for (p, l) in zip(prediction, label) if l != -100]
        for prediction, label in zip(predictions, labels)
    ]

    return metric.compute(predictions=true_predictions, references=true_labels)
evaluate_all_categories(tokenized_dataset["test"])<jupyter_output><empty_output><jupyter_text>Das trainierte Modell schneidet besonders gut in den Hauptkategorien `LOC` und `PER` ab. Die nächstbesten Werte werden für die beiden anderen Hauptkategorien `ORG` und `OTH` erreicht. Dieses Ergebnis entspricht der Erwartung, da es für diese Kategorien auch die meisten Trainingsdaten gab. Besonders für die Klasse der `deriv` Token werden nicht so hohe F1-Werte erreicht.   Speichern des trainierten Modells<jupyter_code>trainer.save_model('models/deepset_finetuned/ner_multilang')
tokenizer.save_pretrained('models/deepset_finetuned/ner_multilang')<jupyter_output><empty_output><jupyter_text>Beispielhafte Anwendung des Modells Um ein Transformers Modell einfach anzuwenden, nutzt man die Methode `pipeline`. Diese baut automatisch in Abhängigkeit vom übergebenen Task und Modell eine Pipeline. Die Pipeline kümmert sich um die nötigen Schritte um aus einer Stringeingabe eine Modellvorhersage zu erzeugen:<jupyter_code>from transformers import pipeline
ner = pipeline("ner", model = f'models/deepset_finetuned/ner_multilang')<jupyter_output>Some weights of BertModel were not initialized from the model checkpoint at models/deepset_finetuned/ner_multilang and are newly initialized: ['bert.pooler.dense.weight', 'bert.pooler.dense.bias']
You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.<jupyter_text>Anschließend kann dem `ner` Objekt der zu Verarbeitende String übergeben werden um eine Vorhersage der enthaltenden Entitäten zu erhalten:<jupyter_code>ner('''In der CDU liegen die Nerven blank. Parteichef Laschet und andere führende Christdemokraten sprechen
    nach den Niederlagen in Mainz und Stuttgart von einem Warnschuss – und attackieren die SPD. ''')<jupyter_output><empty_output><jupyter_text>Das Modell konnte für obige Eingabe alle Token korrekt bestimmen.<jupyter_code>ner('''Die Europäische Union hat ein Verfahren gegen Großbritannien wegen Verletzung des EU-Austrittsvertrags
    eingeleitet. Dies teilte die EU-Kommission am Montag in Brüssel mit. ''')
ner('''Das sogenannte Nordirland-Protokoll im Austrittsvertrag sieht vor,
    dass einige Regeln des EU-Binnenmarkts für Nordirland weiter gelten.
    Dies soll Kontrollen an der Landgrenze zum EU-Staat Irland auf der gemeinsamen
    Insel überflüssig machen. Da Waren dennoch kontrolliert werden müssen, um EU-Standards zu wahren,
    wurden die Kontrollen auf Häfen an der Irischen See zwischen Nordirland und dem übrigen
    Großbritannien verschoben. So wurde das Problem zwischen Großbritannien und der
    EU – und insbesondere der europäischen Republik Irland – zu einem innerbritischen Problem.''')
ner('''@_A_K_K_ @CDU @jensspahn @_FriedrichMerz Die CDU muss für den packt und die betrügerische
    Wahl karrenbauer muss absteigen auf 12% Überall sind die Regierungen gegen den packt Deutschland
    wird von irren in den Abgrund gerissen.''')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09111402573981474, 'fraction_numerical': 0.011599311418968769, 'mean_word_length': 5.945345858240819, 'pattern_counts': {'":': 4, '<': 165, '<?xml version=': 0, '>': 164, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '42', 'dir': 'jupyter-structured-clean-dedup', 'id': '126145', 'license': 'CC0-1.0', 'n_tokens_mistral': 8256, 'n_tokens_neox': 8189, 'n_words': 2414, 'path': 'Experimente/NER/skript4_ner_transformer_training-multilang.ipynb', 'repo_name': 'DevShape/Bacherlorarbeit_NLP', 'size': '24398'}