[PYTHON] [Tutorial] Erstellen Sie mithilfe von maschinellem Lernen in 30 Minuten einen einzigartigen Ausdrucksextraktor

Einführung

** Extraktion eindeutiger Ausdrücke ** ist eine Technologie, die die richtige Nomenklatur wie ** Personenname ** und ** Ortsname **, die im Text erscheinen, sowie numerische Ausdrücke wie ** Datum ** und ** Uhrzeit ** extrahiert. .. Die Extraktion eindeutiger Ausdrücke wird auch als Elementartechnologie für angewandte Anwendungen verwendet, die die Verarbeitung natürlicher Sprache verwenden, z. B. ** Frage- und Antwortsystem **, ** Dialogsystem ** und ** Informationsextraktion **.

Dieses Mal werde ich einen einzigartigen Ausdrucksextraktor mit ** Technologie für maschinelles Lernen ** erstellen.

※Vorsichtsmaßnahmen Es kommt keine theoretische Geschichte heraus. Wenn Sie die Theorie wissen wollen, schlagen Sie bitte die andere. </ font>

Zielgruppe

  • Diejenigen, die etwas über die Extraktion einzigartiger Ausdrücke wissen
  • Diejenigen, die einen einzigartigen Ausdrucksextraktor erstellen möchten
  • Diejenigen, die Python-Code lesen können

Was ist Eigenexpressionsextraktion?

Dieser Abschnitt bietet einen Überblick und eine Methode zur Extraktion eindeutiger Ausdrücke.

Überblick

Die Extraktion eindeutiger Ausdrücke ist eine Technologie, die die richtige Nomenklatur wie Personennamen und Ortsnamen, die in Texten vorkommen, sowie numerische Ausdrücke wie Datum und Uhrzeit extrahiert. Schauen wir uns ein konkretes Beispiel an. Extrahieren wir den richtigen Ausdruck aus dem folgenden Satz.

Taro besuchte Hanako am 18. Mai um 9 Uhr morgens.

Wenn die im obigen Satz enthaltenen eindeutigen Ausdrücke extrahiert werden, ** Taro ** und ** Hanako ** als ** Personenname **, ** 18. Mai ** als ** Datum **, ** Zeit ** als ** 9 Uhr ** kann extrahiert werden.

Im obigen Beispiel wurden der Name, das Datum und die Uhrzeit der Person als Klassen eindeutiger Ausdrücke extrahiert. Im Allgemeinen die folgenden acht Klassen (Übung zum Abrufen und Extrahieren von Informationen (IREX) Aufgabe zum Extrahieren spezifischer Ausdrücke Definition) in: //nlp.cs.nyu.edu/irex/NE/) wird häufig verwendet.

Klasse Beispiel
ART einzigartiger Produktname Nobelpreis für Literatur, Windows 7
LOC Ortsname Präfektur Chiba, USA
ORG Organisation LDP, NHK
PSN Personenname Shinzo Abe, Mercel
DAT Datum 29. Januar 2016/01/29
TIM Zeit 15 Uhr, 10 Uhr:30
MNY Betrag 241 Yen, 8 Dollar
PNT-Verhältnis 10%, 30%

Methode

Eine Möglichkeit, Eigenausdrücke zu extrahieren, besteht darin, Sätze zu kennzeichnen, die morphologisch analysiert wurden. Das Folgende ist ein Beispiel für die morphologische Analyse des Satzes "Taro ist am 18. Mai um 9 Uhr morgens ..." und die anschließende Kennzeichnung.

スクリーンショット 2016-01-28 14.35.17.png

Die Bezeichnungen B-XXX und I-XXX geben an, dass diese Zeichenfolgen eindeutige Ausdrücke sind. B-XXX bedeutet den Beginn der eindeutigen Ausdruckszeichenfolge, und I-XXX bedeutet, dass die richtige Ausdruckszeichenfolge fortgesetzt wird. Der XXX-Teil enthält eine eindeutige Ausdrucksklasse wie ORG oder PSN. Der nicht geschützte Teil ist mit O gekennzeichnet.

Das Beschriften kann mithilfe von Regeln erfolgen, diesmal jedoch mithilfe der ** Technologie für maschinelles Lernen **. Das heißt, es erstellt ein Modell aus vorbeschrifteten Trainingsdaten und verwendet dieses Modell, um unbeschriftete Anweisungen zu kennzeichnen. Insbesondere lernen wir die Verwendung eines Algorithmus namens CRF.

Bewegen wir tatsächlich unsere Hände.

Installation

Beginnen Sie mit der Installation der erforderlichen Python-Module. Führen Sie den folgenden Befehl im Terminal aus, um das Modul zu installieren. Ich habe CRFsuite als CRF-Bibliothek installiert.

pip install numpy
pip install scipy
pip install sklearn
pip install python-crfsuite

Importieren Sie nach der Installation die erforderlichen Module. Führen Sie den folgenden Code aus.

from itertools import chain
import pycrfsuite
import sklearn
from sklearn.metrics import classification_report
from sklearn.preprocessing import LabelBinarizer

Daten, die zum Erstellen des Eigenexpressionsextraktors verwendet werden

Da CRF das Lernen überwacht, benötigen wir Daten, die mit Lehrerdaten gekennzeichnet sind. Dieses Mal habe ich die markierten Daten im Voraus vorbereitet. Bitte herunterladen von hier. Der Dateiname lautet "hironsan.txt".

Definieren wir nun zunächst eine Klasse zum Lesen der heruntergeladenen Daten.

import codecs

class CorpusReader(object):

    def __init__(self, path):
        with codecs.open(path, encoding='utf-8') as f:
            sent = []
            sents = []
            for line in f:
                if line	== '\n':
                    sents.append(sent)
                    sent = []
                    continue
                morph_info = line.strip().split('\t')
                sent.append(morph_info)
        train_num = int(len(sents) * 0.9)
        self.__train_sents = sents[:train_num]
        self.__test_sents = sents[train_num:]

    def iob_sents(self, name):
        if name == 'train':
            return self.__train_sents
        elif name == 'test':
            return self.__test_sents
        else:
            return None

Laden Sie als Nächstes die heruntergeladenen Daten mit der erstellten Klasse. Die Anzahl der Trainingsdaten beträgt 450 Sätze und die Anzahl der Testdaten beträgt 50 Sätze.

c = CorpusReader('hironsan.txt')
train_sents = c.iob_sents('train')
test_sents = c.iob_sents('test')

Das Format der gelesenen Daten ist wie folgt. Das IOB2-Tag wird nach Durchführung der morphologischen Analyse mit dem morphologischen Analysegerät "MeCab" angebracht. Die Daten sind in Sätze unterteilt, und jeder Satz besteht aus einer Sammlung mehrerer morphologischer Informationen.

>>> train_sents[0]
[['2005', 'Substantiv', 'Nummer', '*', '*', '*', '*', '*', 'B-DAT'],
 ['Jahr', 'Substantiv', 'Suffix', 'Hilfswörter', '*', '*', '*', 'Jahr', 'Nen', 'Nen', 'I-DAT'],
 ['7', 'Substantiv', 'Nummer', '*', '*', '*', '*', '*', 'I-DAT'],
 ['Mond', 'Substantiv', 'Allgemeines', '*', '*', '*', '*', 'Mond', 'Mond', 'Mond', 'I-DAT'],
 ['14', 'Substantiv', 'Nummer', '*', '*', '*', '*', '*', 'I-DAT'],
 ['Tag', 'Substantiv', 'Suffix', 'Hilfswörter', '*', '*', '*', 'Tag', 'Nichi', 'Nichi', 'I-DAT'],
 ['、', 'Symbol', 'Lesepunkt', '*', '*', '*', '*', '、', '、', '、', 'O'],
...
]

Als Nächstes werde ich die Funktionen erläutern, die zum Extrahieren eindeutiger Ausdrücke verwendet werden.

Identität zu verwenden

Wir geben Ihnen einen Überblick darüber, was Sie verwenden werden, und codieren es dann.

Überblick

Als nächstes werde ich die zu verwendende Natur erklären. Dieses Mal werden wir Wörter mit zwei Buchstaben vor und nach der Unterklassifizierung von Teiltexten, Zeichentyp und eindeutigem Ausdruckstag verwenden. Ein Beispiel für die Verwendung dieser Eigenschaften ist unten dargestellt. Der vom Rahmen umgebene Teil ist die verwendete Natur. ner.png

Die Klassifizierung der Zeichentypen ist wie folgt. Insgesamt gibt es 7 Typen.

Zeichentyp-Tag Erläuterung
ZSPACE Leer
ZDIGIT Arabische Zahlen
ZLLET Niedrigere alphabetische Zeichen
ZULET Alphabet Hauptstadt
HIRAG Hiragana
KATAK Katakana
OTHER Andere

Der als Identität verwendete Zeichentyp ist eine Kombination aller im Wort enthaltenen Zeichentypen. Zum Beispiel umfasst das Wort "viele" Kanji und Hiragana. Das Zeichentyp-Tag für Hiragana ist HIRAG und das Zeichentyp-Tag für Kanji ist OTHER. Daher ist der Zeichentyp des Wortes "viele" "HIRAG-OTHER".

Codierung der Identitätsextraktion

Beurteilung des Zeichentyps

Der Code zum Bestimmen des Zeichentyps lautet wie folgt. Alle in der Zeichenfolge enthaltenen Zeichentypen werden mit- (Bindestrich) kombiniert.

def is_hiragana(ch):
    return 0x3040 <= ord(ch) <= 0x309F

def is_katakana(ch):
    return 0x30A0 <= ord(ch) <= 0x30FF

def get_character_type(ch):
    if ch.isspace():
        return 'ZSPACE'
    elif ch.isdigit():
        return 'ZDIGIT'
    elif ch.islower():
        return 'ZLLET'
    elif ch.isupper():
        return 'ZULET'
    elif is_hiragana(ch):
        return 'HIRAG'
    elif is_katakana(ch):
        return 'KATAK'
    else:
        return 'OTHER'

def get_character_types(string):
    character_types = map(get_character_type, string)
    character_types_str = '-'.join(sorted(set(character_types)))

    return character_types_str

Extraktion der Unterklassifizierung von Teiltexten

Der Code zum Extrahieren der Teilwort-Unterklasse aus den morphologischen Informationen lautet wie folgt.

def extract_pos_with_subtype(morph):
    idx = morph.index('*')

    return '-'.join(morph[1:idx])

Extraktion der Identität aus Sätzen

Basierend auf dem Obigen ist der Code zum Extrahieren der Identität für jedes Wort wie folgt. Es ist ein bisschen überflüssig, aber Sie können es sehen.

def word2features(sent, i):
    word = sent[i][0]
    chtype = get_character_types(sent[i][0])
    postag = extract_pos_with_subtype(sent[i])
    features = [
        'bias',
        'word=' + word,
        'type=' + chtype,
        'postag=' + postag,
    ]
    if i >= 2:
        word2 = sent[i-2][0]
        chtype2 = get_character_types(sent[i-2][0])
        postag2 = extract_pos_with_subtype(sent[i-2])
        iobtag2 = sent[i-2][-1]
        features.extend([
            '-2:word=' + word2,
            '-2:type=' + chtype2,
            '-2:postag=' + postag2,
            '-2:iobtag=' + iobtag2,
        ])
    else:
        features.append('BOS')

    if i >= 1:
        word1 = sent[i-1][0]
        chtype1 = get_character_types(sent[i-1][0])
        postag1 = extract_pos_with_subtype(sent[i-1])
        iobtag1 = sent[i-1][-1]
        features.extend([
            '-1:word=' + word1,
            '-1:type=' + chtype1,
            '-1:postag=' + postag1,
            '-1:iobtag=' + iobtag1,
        ])
    else:
        features.append('BOS')

    if i < len(sent)-1:
        word1 = sent[i+1][0]
        chtype1 = get_character_types(sent[i+1][0])
        postag1 = extract_pos_with_subtype(sent[i+1])
        features.extend([
            '+1:word=' + word1,
            '+1:type=' + chtype1,
            '+1:postag=' + postag1,
        ])
    else:
        features.append('EOS')

    if i < len(sent)-2:
        word2 = sent[i+2][0]
        chtype2 = get_character_types(sent[i+2][0])
        postag2 = extract_pos_with_subtype(sent[i+2])
        features.extend([
            '+2:word=' + word2,
            '+2:type=' + chtype2,
            '+2:postag=' + postag2,
        ])
    else:
        features.append('EOS')

    return features


def sent2features(sent):
    return [word2features(sent, i) for i in range(len(sent))]


def sent2labels(sent):
    return [morph[-1] for morph in sent]


def sent2tokens(sent):
    return [morph[0] for morph in sent]

Extrahieren Sie die Identität mit sent2features aus dem Satz. Die Eigenschaften, die tatsächlich extrahiert werden, sind wie folgt.

>>> sent2features(train_sents[0])[0]
['bias',
 'word=2005',
 'type=ZDIGIT',
 'postag=Substantiv-Nummer',
 'BOS',
 'BOS',
 '+1:word=Jahr',
 '+1:type=OTHER',
 '+1:postag=Substantiv-Suffix-Hilfswörter',
 '+2:word=7',
 '+2:type=ZDIGIT',
 '+2:postag=Substantiv-Nummer']

Es stellt sich heraus, dass die Identität aus den Daten extrahiert werden kann. Extrahieren Sie die Qualitäten und Etiketten für Trainings- und Testdaten aus den Daten für die spätere Verwendung.

X_train = [sent2features(s) for s in train_sents]
y_train = [sent2labels(s) for s in train_sents]

X_test = [sent2features(s) for s in test_sents]
y_test = [sent2labels(s) for s in test_sents]

Modelllernen

Um das Modell zu trainieren, erstellen Sie ein pycrfsuite.Trainer-Objekt, laden Sie die Trainingsdaten und rufen Sie dann die Zugmethode auf. Erstellen Sie zunächst ein Trainer-Objekt und laden Sie die Trainingsdaten.

trainer = pycrfsuite.Trainer(verbose=False)

for xseq, yseq in zip(X_train, y_train):
    trainer.append(xseq, yseq)

Als nächstes stellen Sie die Lernparameter ein. Ursprünglich sollte anhand von Entwicklungsdaten entschieden werden, diesmal wird dies jedoch behoben.

trainer.set_params({
    'c1': 1.0,   # coefficient for L1 penalty
    'c2': 1e-3,  # coefficient for L2 penalty
    'max_iterations': 50,  # stop earlier

    # include transitions that are possible, but not observed
    'feature.possible_transitions': True
})

Jetzt, da wir fertig sind, trainieren wir das Modell. Geben Sie den Dateinamen an und führen Sie die Zugmethode aus.

trainer.train('model.crfsuite')

Nach Abschluss der Ausführung wird eine Datei mit dem angegebenen Dateinamen erstellt. Darin ist das trainierte Modell gespeichert.

Vorhersage von Testdaten

Um das trainierte Modell zu verwenden, erstellen Sie ein pycrfsuite.Tagger-Objekt, laden Sie das trainierte Modell und verwenden Sie die Tag-Methode. Erstellen Sie zunächst ein Tagger-Objekt und laden Sie das trainierte Modell.

tagger = pycrfsuite.Tagger()
tagger.open('model.crfsuite')

Lassen Sie uns nun den Satz markieren.

example_sent = test_sents[0]
print(' '.join(sent2tokens(example_sent)))

print("Predicted:", ' '.join(tagger.tag(sent2features(example_sent))))
print("Correct:  ", ' '.join(sent2labels(example_sent)))

Sie sollten folgendes Ergebnis erhalten: Vorausgesagt ist die mit dem erstellten Modell vorhergesagte Tag-Zeichenfolge, und Richtig ist die richtige Tag-Zeichenfolge. Im Fall dieses Satzes stimmten das erwartete Ergebnis des Modells und die richtigen Antwortdaten überein.

Im Oktober letzten Jahres wurden 34 Menschen bei einer Explosion in Taba, Ägypten, in der Nähe des Ortes getötet.
Predicted: B-DAT I-DAT I-DAT O O O O O O O O O O O O B-LOC O B-LOC O O O O O O O O O O
Correct:   B-DAT I-DAT I-DAT O O O O O O O O O O O O B-LOC O B-LOC O O O O O O O O O O

Damit ist der Aufbau des Eigenexpressionsextraktors abgeschlossen.

Modellbewertung

Ich habe ein Modell erstellt, weiß aber nicht, ob dies gut oder schlecht ist. Daher ist es wichtig, das erstellte Modell zu bewerten. Lassen Sie uns nun das erstellte Modell bewerten. Die Bewertung basiert auf der Genauigkeitsrate, der Rückrufrate und dem F-Wert. Unten finden Sie den zu bewertenden Code.

def bio_classification_report(y_true, y_pred):
    lb = LabelBinarizer()
    y_true_combined = lb.fit_transform(list(chain.from_iterable(y_true)))
    y_pred_combined = lb.transform(list(chain.from_iterable(y_pred)))
        
    tagset = set(lb.classes_) - {'O'}
    tagset = sorted(tagset, key=lambda tag: tag.split('-', 1)[::-1])
    class_indices = {cls: idx for idx, cls in enumerate(lb.classes_)}
    
    return classification_report(
        y_true_combined,
        y_pred_combined,
        labels = [class_indices[cls] for cls in tagset],
        target_names = tagset,
    )

Tag-Anweisungen im Testdatensatz zur Verwendung bei der Auswertung.

y_pred = [tagger.tag(xseq) for xseq in X_test]

Die mit dem trainierten Modell markierten Daten und die richtigen Antwortdaten werden an die Bewertungsfunktion übergeben und das Ergebnis angezeigt. Für jede Kategorie werden die Genauigkeitsrate, die Rückrufrate, der F-Wert und die Anzahl der Tags angezeigt.

>>> print(bio_classification_report(y_test, y_pred))
             precision    recall  f1-score   support

      B-ART       1.00      0.89      0.94         9
      I-ART       0.92      1.00      0.96        12
      B-DAT       1.00      1.00      1.00        12
      I-DAT       1.00      1.00      1.00        22
      B-LOC       1.00      0.95      0.97        55
      I-LOC       0.94      0.94      0.94        17
      B-ORG       0.75      0.86      0.80        14
      I-ORG       1.00      0.90      0.95        10
      B-PSN       0.00      0.00      0.00         3
      B-TIM       1.00      0.71      0.83         7
      I-TIM       1.00      0.81      0.90        16

avg / total       0.95      0.91      0.93       177

Ich denke, das Ergebnis ist etwas zu gut, aber die verwendeten Daten enthielten wahrscheinlich ähnliche Aussagen.

※Hinweis Möglicherweise erhalten Sie eine UndefinedMetricWarning. Es scheint nicht möglich zu sein, die Genauigkeitsrate usw. für Etiketten zu definieren, die in der vorhergesagten Stichprobe nicht vorhanden sind. Weil die Anzahl der vorbereiteten Daten gering ist ...

abschließend

Dieses Mal konnte ich mithilfe von crfsuite, einer Python-Bibliothek, auf einfache Weise einen eindeutigen Ausdrucksextraktor erstellen. Basierend auf der Definition von IREX werden dem Tagging acht eindeutige Ausdrücke hinzugefügt. Die Definition von IREX ist jedoch für den praktischen Gebrauch oft grob. Daher ist es bei Verwendung der Eigenausdrucksextraktion für eine Aufgabe erforderlich, Daten mit den erforderlichen Tags entsprechend der Aufgabe vorzubereiten.

Ich denke auch, dass es eine gute Idee ist, nach besseren Eigenschaften und Modellparametern zu suchen.

Referenz

Recommended Posts

[Tutorial] Erstellen Sie mithilfe von maschinellem Lernen in 30 Minuten einen einzigartigen Ausdrucksextraktor
Eine Geschichte über einfaches maschinelles Lernen mit TensorFlow
Datenversorgungstricks mit deque beim maschinellen Lernen
Lassen Sie uns einen Teil des maschinellen Lernens mit Python berühren
Ersetzen Sie die eindeutige Darstellung der gelesenen Textdatei durch eine Beschriftung (mit GiNZA).
Ein Memorandum über Methoden, die häufig beim maschinellen Lernen mit Scikit-Learn (für Anfänger) verwendet werden.
Zusammenfassung des Lernprogramms für maschinelles Lernen
Anfänger des maschinellen Lernens versuchen, einen Entscheidungsbaum zu erstellen
Konstruktionsnotiz für eine maschinelle Lernumgebung von Python
MALSS (Einführung), ein Tool, das maschinelles Lernen in Python unterstützt
Maschinelles Lernen Eine Geschichte über Menschen, die mit GBDT in GBDT in Python nicht vertraut sind
Starten einer maschinellen Lernumgebung mit Google Compute Engine (GCE)
Ich habe versucht, Tensorboard zu verwenden, ein Visualisierungstool für maschinelles Lernen
Ich habe eine Stoppuhr mit tkinter mit Python gemacht
Maschinelles Lernen in Delemas (Praxis)
Pfeffer-Tutorial (5): Verwenden eines Tablets
Erstellen Sie ein Lesezeichen in Python
Erstellen Sie eine maschinelle Lernumgebung
Wird in EDA für maschinelles Lernen verwendet
Wie wäre es mit Anaconda zum Erstellen einer maschinellen Lernumgebung mit Python?
Erstellen Sie mit TensorFlow eine Gesichtserkennung
Automatisieren Sie Routineaufgaben beim maschinellen Lernen
Chainers einführendes Memorandum zum maschinellen Lernen
Klassifikation und Regression beim maschinellen Lernen
Inverse Analyse des maschinellen Lernmodells
Maschinelles Lernen in Delemas (Datenerfassung)
Python: Vorverarbeitung beim maschinellen Lernen: Übersicht
Vorverarbeitung beim maschinellen Lernen 2 Datenerfassung
Machen Sie matplotlib in 3 Minuten mit Japanisch kompatibel
Erstellen eines Lernmodells mit MNIST
Random Seed Research im maschinellen Lernen
Stellen Sie Django in 3 Minuten mit Docker-Compose bereit
Machen Sie einen Vorhanggenerator mit Blender
Vorverarbeitung beim maschinellen Lernen 4 Datenkonvertierung
Anwendungsentwicklung mit Azure Machine Learning
So erstellen Sie mit YOLO in 3 Stunden ein Modell für die Objekterkennung
Mit dem Ziel, ein Ingenieur für maschinelles Lernen zu werden, der MOOCs aus Vertriebspositionen verwendet
Ich habe versucht, Gitarrenakkorde in Echtzeit mithilfe von maschinellem Lernen zu klassifizieren
Ich habe FizzBuzz in Python mit der Support Vector Machine (Bibliothek LIVSVM) geschrieben.
Das maschinelle Lernen in einem Monat auf ein praktisches Niveau bringen # 1 (Startausgabe)
Erstellen eines Gesichtsbilddatensatzes für maschinelles Lernen (1: Erfassen von Kandidatenbildern mithilfe des Web-API-Dienstes)