Schwache Überwachung mit Named-Entity Recognition (NER) – Transformers | von dp | Juni 2023

0
28


Vollständig Durchgang Hier optimieren wir einen Transformer für die Named-Entity Recognition (NER) mithilfe von Weak Supervision.

Schwache Supervision ist ein Ansatz für maschinelles Lernen, bei dem hochwertige und oft lautere Supervisionsquellen verwendet werden, um viel schneller viel größere Trainingssätze zu erstellen, als dies sonst durch manuelle Supervision möglich wäre
Schnorchel-KI

In diesem Beitrag werden „viele“ Beschriftungs- und Aggregatfunktionen verwendet, um eine einzige Quelle für die Feinabstimmung unseres Transformers zu erstellen.

Die schwache Überwachung mit Token-Klassifizierung ist etwas umständlich, wenn verschiedene Ausgaben der Kennzeichnungsfunktion miteinander kombiniert werden. Um dies zu umgehen, werden wir die Methoden „Mehrheitsabstimmung“ und „Union Combination“ verwenden, um „viele“ Bezeichnungen auf eine einzige nutzbare Quelle zu reduzieren.

Dieser gesamte Prozess wird über die Befehlszeile mithilfe von verwaltet extr-ds Bibliothek (Github-Repository).

pip set up extr-ds

Der Code für dieses Projekt ist zu finden – Github-Repository.

Daten

Beschriftung

Einrichten von sechs kleinen Beschriftungsfunktionen, um unseren Datensatz programmgesteuert zu kennzeichnen. Die Ausgabe dieser Beschriftungsfunktionen wird zusammengeführt, um unseren schwach beschrifteten (IOB2) Datensatz zu erstellen.

from typing import Record, Dict, Optionally available

import re
import nltk

from extr import RegExLabel, RegEx
from extr.entities import create_entity_extractor
from extr_ds.guidelines import StaticUnit

class RegExStaticUnit(StaticUnit):
def __init__(self,
regex_labels: Record[RegExLabel],
kb: Optionally available[Dict[str, List[str]]] = None) -> None:
tremendous().__init__(
nltk.tokenize.word_tokenize,
create_entity_extractor(
regex_labels=regex_labels,
kb=kb
)
)

Spieler

class Participant(RegExStaticUnit):
def __init__(self) -> None:
tremendous().__init__(
regex_labels=[
RegExLabel(
label='PLAYER',
regexes=[
RegEx(
expressions=[
r'b[A-Z][a-z]?.[A-Z][a-z]+b',
r'b[A-Z][a-z]?.[A-Z]'[A-Z][a-z]+b',
r'(?<=Go From ).+?(?= for)',
r'(?<=) ).+?(?= Go From)',
]
)
]
)
]
)

Crew

class Crew(RegExStaticUnit):
def __init__(self) -> None:
tremendous().__init__(
regex_labels=[],
kb={
'TEAM': [
'ARZ',
'Arizona',
'ATL',
...
]
}
)

Zeitraum

class Time(RegExStaticUnit):
def __init__(self):
tremendous().__init__(
regex_labels=[
RegExLabel(
label='TIME',
regexes=[
RegEx(
expressions=[
r'b[0-9]{1,2}:[0-9]{2}b',
]
)
]
)
]
)

class Interval(RegExStaticUnit):
def __init__(self):
tremendous().__init__(
regex_labels=[],
kb={
'PERIOD': [
'1st',
'2nd',
'3rd',
'4th',
'OT',
],
}
)

Menge/Einheiten

class Amount(StaticUnit):
def __init__(self):
tremendous().__init__(
regex_labels=[
RegExLabel(
label='QUANTITY',
regexes=[
RegEx(expressions=[
r'(?<=[s(])-?d{1,3}(?=b)',
])
]
)
]
)

class Models(StaticUnit):
def __init__(self):
tremendous().__init__(
regex_labels=[
RegExLabel(
label='UNITS',
regexes=[
RegEx(
expressions=[
r'b(y(?:ar)?ds)b',
],
flags=re.IGNORECASE
)
]
)
]
)

Verschmelzen

Wir werden ein grundlegendes Merge-Setup (Union) verwenden. Benutzen StaticUnit erzeugt eine höhere Konfidenz für gefundene Entitäten (99 %) und eine etwas geringere, aber konsistente Konfidenz für nicht gefundene Anmerkungen (90 %).

labeling_functions = [
Player(),
Team(),
Time(),
Period(),
Quantity(),
Units(),
]

def clear(textual content: str) -> str
...
return textual content

def annotate(doc: str) -> Dict[str, List[str]]:
textual content = clear(doc)

outcomes = labeling_functions[0](textual content)
for labeling_function in labeling_functions[1:]:
outcomes = create_static_inference_result(
labels=Majority().merge([
results,
labeling_function(text),
]),
weight=outcomes.weight
)

return {
'tokens': nltk.tokenize.word_tokenize(textual content),
'labels': outcomes.labels
}

[
'B-PLAYER',
'O',
'B-QUANTITY',
'B-UNITS',
'O',
'B-TEAM',
'B-QUANTITY',
'O',
'B-TEAM',
'B-QUANTITY',
'O',
'B-PLAYER',
'O',
'B-TEAM',
'B-QUANTITY',
'O',
'B-QUANTITY',
'B-UNITS',
'O',
'B-PLAYER',
'O',
'B-PLAYER',
'O',
'O'
]

*** Dies könnte leicht erweitert werden, sodass Beschriftungsfunktionen miteinander konkurrieren. — Sie könnten eine Reihe verschiedener NER-Modelle trainieren und eine Mehrheitsabstimmung auf ihre Beobachtungen anwenden, um einen beschrifteten Datensatz zu erstellen. ***

Feinabstimmung

Dieser Teil wurde in einem früheren Beitrag behandelt – siehe Erstellen benutzerdefinierter NER-Modelle (Named-Entity Recognition) – Transformers.

import random

okay = 1000

with open('./supply.txt', 'r') as source_input:
rows = source_input.learn().cut up('n')

random.seed(42)
random.shuffle(rows)

annotations = []
for row in rows[0:k]:
annotations.append(
annotate(row)
)

with open('./ents-iob.json', 'w') as output_iob:
output_iob.write(json.dumps(annotations))

Nach dem Coaching können wir sehen, dass es mit einem kleinen Datensatz einfach nicht möglich battle, 100 % zu erreichen. In diesem Fall findet unser Transformator tatsächlich Entitäten in unserem Trainings-/Testdatensatz, die nicht gekennzeichnet sind.

Im folgenden Beispiel ist unser Transformator beschriftet Okay.Van Noy als [B-PLAYER, I-PLAYER] was unser Participant Die Beschriftungsfunktion hätte nur beschriftet Okay.Van als B-PLAYER

[
{
'text': '(6:51 - 1st) (Shotgun) P.Mahomes scrambles right end to LAC 34 for 2 yards (S.Joseph; K.Van Noy). FUMBLES (S.Joseph), and recovers at LAC 34.',
'iob': [
{
'tokens': ['(', '6:51', '-', '1st', ')', '(', 'Shotgun', ')', 'P.Mahomes', 'scrambles', 'right', 'end', 'to', 'LAC', '34', 'for', '2', 'yards', '(', 'S.Joseph', ';', 'K.Van', 'Noy', ')', '.', 'FUMBLES', '(', 'S.Joseph', ')', ',', 'and', 'recovers', 'at', 'LAC', '34', '.'],
'labels': ['O', 'B-TIME', 'O', 'B-PERIOD', 'O', 'O', 'O', 'O', 'B-PLAYER', 'O', 'O', 'O', 'O', 'B-TEAM', 'B-QUANTITY', 'O', 'B-QUANTITY', 'B-UNITS', 'O', 'B-PLAYER', 'O', 'B-PLAYER', 'I-PLAYER', 'O', 'O', 'O', 'O', 'B-PLAYER', 'O', 'O', 'O', 'O', 'O', 'B-TEAM', 'B-QUANTITY', 'O']
}
]
}
]

An diesem Punkt könnten wir unseren Transformator in unsere Etikettierung integrieren oder die vorhandenen Etikettierungsfunktionen aktualisieren und noch einmal verfeinern. In jedem Fall wird dies zu einem iterativen Prozess.

Nutzen – Der Datensatz, den ich hier verwendet habe, enthält über 40.000 Zeilen. Dieser Ansatz erzeugte innerhalb weniger Minuten einen vollständig beschrifteten Datensatz.

Warnung – Wenn Sie sich die Mühe machen, den Datensatz zu überprüfen, stellen Sie sicher, dass Sie diese Anmerkungen speichern und sie bei jeder Iteration an Ihren Trainingssatz anhängen.

Es gibt verschiedene Methoden, um Ihre Ergebnisse iterativ zu verbessern, siehe Feinabstimmung eines vorab trainierten Sprachmodells mit schwacher Überwachung: Ein kontrastiv-regulierter Selbsttrainingsansatz zum Beispiel.

Foto von Erika Fletcher An Unsplash



Source link

HINTERLASSEN SIE EINE ANTWORT

Please enter your comment!
Please enter your name here