[PYTHON] Antworten und Eindrücke von 100 Sprachverarbeitungsklopfen - Teil 2

Adventskalender 17. Tag Ich war zu spät .. ..

das ist

Da ich [100 Schläge auf die Sprachverarbeitung] gelöst habe (http://www.cl.ecei.tohoku.ac.jp/nlp100/), werde ich die Antwort und den Eindruck einzeln schreiben (zweiter Teil) Es hat viel länger gedauert als beim letzten Mal ~~~

Voraussetzungen

Für die Umwelt usw. hier (vorheriger Link)

Hauptgeschichte

Kapitel 5: Abhängigkeitsanalyse

Verwenden Sie CaboCha, um den Text (neko.txt) von Natsume Sosekis Roman "Ich bin eine Katze" abhängig zu machen und zu analysieren, und speichern Sie das Ergebnis in einer Datei namens neko.txt.cabocha. Verwenden Sie diese Datei, um ein Programm zu implementieren, das die folgenden Fragen beantwortet.

import CaboCha
c = CaboCha.Parser()
with open('./neko.txt') as f:
    text = f.read()
with open('./neko.txt.cabocha', mode='w') as f:
    for se in  [s + '。' for s in text.split('。')]:
        f.write(c.parse(se ).toString(CaboCha.FORMAT_LATTICE))

Eigentlich ist es die erste Abhängigkeitsanalyse, also habe ich allein damit viel gesucht

40 Lesen der Ergebnisse der Abhängigkeitsanalyse (Morphologie)

Implementieren Sie die Klasse Morph, die die Morphologie darstellt. Diese Klasse hat eine Oberflächenform (Oberfläche), eine Basisform (Basis), ein Teilwort (pos) und eine Teilwortunterklassifikation 1 (pos1) als Elementvariablen. Lesen Sie außerdem das Analyseergebnis von CaboCha (neko.txt.cabocha), drücken Sie jeden Satz als Liste von Morph-Objekten aus und zeigen Sie die morphologische Elementzeichenfolge des dritten Satzes an.

# 40
class Morph:
    def __init__(self, surface, base, pos, pos1):
        self.surface = surface
        self.base = base
        self.pos = pos
        self.pos1 = pos1

doc = []
with open('./neko.txt.cabocha') as f:
    sentence = []
    line = f.readline()
    while(line):
        while('EOS' not in line):
            if not line.startswith('*'):
                cols = line.split('\t')
                m = Morph(
                    surface=cols[0],
                    base=cols[1].split(',')[-3],
                    pos=cols[1].split(',')[0],
                    pos1=cols[1].split(',')[1],
                )
                sentence.append(m)
            line = f.readline()
        doc.append(sentence)
        sentence = []
        line = f.readline()
print([t.surface for t in doc[2]])

Tun Sie dies, während Sie das Ausgabeformat von CaboCha überprüfen

41 Lesen des Abhängigkeitsanalyseergebnisses (Phrase / Abhängigkeit)

Implementieren Sie zusätzlich zu> 40 die Klauselklasse Chunk. Diese Klasse enthält eine Liste von Morph-Elementen (Morph-Objekten) (Morphs), eine Liste verwandter Klauselindexnummern (dst) und eine Liste verwandter ursprünglicher Klauselindexnummern (srcs) als Mitgliedsvariablen. Lesen Sie außerdem das Analyseergebnis von CaboCha des Eingabetextes, drücken Sie einen Satz als Liste von Chunk-Objekten aus und zeigen Sie die Zeichenfolge und den Kontakt der Phrase des achten Satzes an. Verwenden Sie für die restlichen Probleme in Kapitel 5 das hier erstellte Programm.

# 41
class Chunk:
    def __init__(self, morphs, dst, srcs):
        self.morphs = morphs
        self.dst = dst
        self.srcs = srcs
        
doc = []
with open('./neko.txt.cabocha') as f:
    sentence = []
    line = f.readline()
    while(line):
        if line.startswith('*'):
            cols = line.split(' ')
            #Setzen Sie nichts eine Zeile über die vorherige EOS
            if cols[1] != '0':
                sentence.append(c)
            c = Chunk(
                morphs=[],
                dst=int(cols[2].split('D')[0]),
                srcs=[]
            )
        elif 'EOS' in line:
            sentence.append(c)
            #Der Prozess, etwas zu finden, das von Ihnen abhängt
            for i, c in enumerate(sentence):
                c.srcs = [idx for idx, chk, in enumerate(sentence) if chk.dst == i ]
                
            doc.append(sentence)
            sentence = []
        else:
            cols = line.split('\t')
            if cols[1].split(',')[0] != "Symbol":
                m = Morph(
                    surface=cols[0],
                    base=cols[1].split(',')[-3],
                    pos=cols[1].split(',')[0],
                    pos1=cols[1].split(',')[1],
                )
                c.morphs.append(m)
        line = f.readline()
for c in doc[7]:
    print(c.dst, end=', ')
    for m in c.morphs:
        print(m.surface, end="")
    print()
for c in doc[0]:
    print(c.dst, end=', ')
    for m in c.morphs:
        print(m.surface)
        print(m.pos)
    print()

Ich habe darüber nachgedacht, wie ich den Ausdruck finden kann, der mit mir zusammenhängt, aber ich konnte mir keinen guten vorstellen, also habe ich einfach eine Schleife erstellt und gescannt.

42 Anzeige des Satzes der betroffenen Person und der betroffenen Person

Extrahieren Sie den gesamten Text der ursprünglichen Klausel und der zugehörigen Klausel in tabulatorgetrenntem Format. Geben Sie jedoch keine Symbole wie Satzzeichen aus.

# 42
#Alle sind jupyter(chrome)Weil es 50 härtet
for i, d in enumerate(doc[:50]):
    for c in d:
        if int(c.dst) == -1:
            continue
        for m in c.morphs:
            if m.pos == 'Symbol':
                continue
            print(m.surface, end="")
        print('\t', end="")
        for m in d[c.dst].morphs:
            if m.pos == 'Symbol':
                continue
            print(m.surface, end="")
        print()

Tun Sie dies, während Sie sich der Sätze, Phrasen und Morphologie bewusst sind

43 Klauseln mit Nomenklatur extrahieren, die sich auf Klauseln mit Verben beziehen

Wenn sich Klauseln mit Nomenklatur auf Klauseln mit Verben beziehen, extrahieren Sie sie in tabulatorgetrennten Formaten. Geben Sie jedoch keine Symbole wie Satzzeichen aus.

# 43
#Alle sind jupyter(chrome)Weil es 50 härtet
for i, d in enumerate(doc[:50]):
    for c in d:
        if int(c.dst) == -1:
            continue
        contain_noun = 'Substantiv' in [m.pos for m in c.morphs]
        contain_verb = 'Verb' in [m.pos for m in d[c.dst].morphs]
        if contain_noun and contain_verb:
            for m in c.morphs:
                if m.pos == 'Symbol':
                    continue
                print(m.surface, end="")
            print('\t', end="")
            for m in d[int(c.dst)].morphs:
                if m.pos == 'Symbol':
                    continue
                print(m.surface, end="")
            print()

Ich habe einfach mit if gesucht

44 Visualisierung abhängiger Bäume

Visualisieren Sie den Abhängigkeitsbaum eines bestimmten Satzes als gerichteten Graphen. Zur Visualisierung ist es ratsam, den Abhängigkeitsbaum in die DOT-Sprache zu konvertieren und Graphviz zu verwenden. Verwenden Sie pydot, um gerichtete Diagramme direkt aus Python zu visualisieren.

# 44
import random, pathlib
from graphviz import Digraph

f = pathlib.Path('nekocabocha.png')
fmt = f.suffix.lstrip('.')
fname = f.stem
target_doc = random.choice(doc)
target_doc = doc[8]
idx = doc.index(target_doc)

dot = Digraph(format=fmt)
dot.attr("node", shape="circle")

N = len(target_doc)
#Knoten hinzufügen
for i in range(N):
    dot.node(str(i), ''.join([m.surface for m in target_doc[i].morphs]))

#Kante hinzufügen
for i in range(N):
    if target_doc[i].dst >= 0:
        dot.edge(str(i), str(target_doc[i].dst))

# dot.engine = "circo"
dot.filename = filename
dot.render()

print(''.join([m.surface for c in target_doc for m in c.morphs]))
print(dot)
from IPython.display import Image, display_png
display_png(Image(str(f)))

Ich habe nicht viel getan, während ich dachte, dass Visualisierung Spaß machen würde, also habe ich es zum ersten Mal gemacht, und Wikipedia war genug, um eine grobe Vorstellung von der DOT-Sprache zu bekommen.

45 Extraktion von Verbfallmustern

Ich möchte den diesmal verwendeten Satz als Korpus betrachten und die möglichen Fälle japanischer Prädikate untersuchen. Stellen Sie sich das Verb als Prädikat und das Hilfsverb der Phrase, die sich auf das Verb bezieht, als Fall vor und geben Sie das Prädikat und den Fall in einem durch Tabulatoren getrennten Format aus. Stellen Sie jedoch sicher, dass die Ausgabe den folgenden Spezifikationen entspricht. In einer Phrase, die ein Verb enthält, wird die Grundform des Verbs ganz links als Prädikat verwendet. Verwenden Sie die Hilfswörter, die sich auf das Prädikat beziehen Wenn das Prädikat mehrere Hilfswörter (Phrasen) enthält, ordnen Sie alle Hilfswörter in Wörterbuchreihenfolge an, die durch Leerzeichen getrennt sind. Betrachten Sie den Beispielsatz (8. Satz von neko.txt.cabocha), der besagt, dass "ich hier zum ersten Mal einen Menschen gesehen habe". Dieser Satz enthält zwei Verben, "begin" und "see", und die Phrase, die sich auf "begin" bezieht, wird als "here" analysiert, und die Phrase, die sich auf "see" bezieht, wird als "I am" und "thing" analysiert. Sollte die folgende Ausgabe erzeugen. "Beginnen" See is Speichern Sie die Ausgabe dieses Programms in einer Datei und überprüfen Sie die folgenden Elemente mit UNIX-Befehlen. Eine Kombination von Prädikaten und Fallmustern, die häufig im Korpus vorkommen Fallmuster der Verben "do", "see" und "give" (in der Reihenfolge der Häufigkeit des Auftretens im Korpus anordnen)

# 45
with open("neko_verb.txt", mode="w") as f:
    for s in doc:
        for c in s:
            if 'Verb' in [m.pos for m in c.morphs]:
                row = c.morphs[0].base
                j_list = []
                for i in c.srcs:
                    if len(s[i].morphs) < 2:
                        continue
                    srclast = s[i].morphs[-1]
                    if srclast.pos == 'Partikel':
                        j_list.append(srclast.surface)
                if len(j_list) > 0:
                    j_list.sort()
                    row += "\t" +  " ".join(j_list)
                    f.write(row + "\n")
$ cat neko_verb.txt | sort  | uniq -c  | sort -rn -k 3
$ cat neko_verb.txt | grep "^Machen" | sort  | uniq -c  | sort -rn -k 3
$ cat neko_verb.txt | grep "sehen" | sort  | uniq -c  | sort -rn -k 3
$ cat neko_verb.txt | grep "geben" | sort  | uniq -c  | sort -rn -k 3

Kombinieren Sie bisher den "Teil der Wörter" und "Empfang"

46 Extraktion von Verbfallrahmeninformationen

Ändern Sie das Programm> 45 und geben Sie den Begriff (die Klausel selbst in Bezug auf das Prädikat) in einem durch Tabulatoren getrennten Format aus, das dem Prädikat und dem Fallmuster folgt. Erfüllen Sie zusätzlich zu den 45 Spezifikationen die folgenden Spezifikationen. Der Begriff sollte eine Wortfolge der Klausel sein, die sich auf das Prädikat bezieht (es ist nicht erforderlich, das nachfolgende Verb zu entfernen). Wenn es mehrere Klauseln gibt, die sich auf das Prädikat beziehen, ordnen Sie sie in derselben Norm und Reihenfolge wie die Hilfswörter an, die durch Leerzeichen getrennt sind. Betrachten Sie den Beispielsatz (8. Satz von neko.txt.cabocha), der besagt, dass "ich hier zum ersten Mal einen Menschen gesehen habe". Dieser Satz enthält zwei Verben, "begin" und "see", und die Phrase, die sich auf "begin" bezieht, wird als "here" analysiert, und die Phrase, die sich auf "see" bezieht, wird als "I am" und "thing" analysiert. Sollte die folgende Ausgabe erzeugen. "Beginnen Sie hier" "Sehen Sie, was ich sehe"

# 46
#Obwohl es sich vom Ausgabebeispiel unterscheidet, entspricht dieses Beispiel der Spezifikation des Problems
for s in doc:
    for c in s:
        if 'Verb' in [m.pos for m in c.morphs]:
            row = c.morphs[0].base
            j_list = []
            c_list = []
            for i in c.srcs:
                if len(s[i].morphs) < 2:
                    continue
                srclast = s[i].morphs[-1]
                if srclast.pos == 'Partikel':
                    j_list.append(srclast.surface)
                    c_list.append(''.join([m.surface for m in s[i].morphs]))
            if len(j_list) > 0:
                j_list.sort()
                c_list.sort()
                row += "\t" +  " ".join(j_list) + "\t"+  " ".join(c_list)
                print(row)

Wenn es mehrere Klauseln gibt, die sich auf das Prädikat beziehen, ordnen Sie sie in derselben Norm und Reihenfolge an wie die Hilfswörter, getrennt durch Leerzeichen.

Es unterscheidet sich also vom Ausgabebeispiel, aber die Klauseln werden auch unabhängig voneinander sortiert

47 Mining der funktionalen Verbsyntax

Ich möchte nur auf den Fall achten, in dem das Verb wo case eine Sa-hen-Verbindungsnomenklatur enthält. Ändern Sie 46 Programme, um die folgenden Spezifikationen zu erfüllen. Nur wenn die Phrase bestehend aus "Sahen-Verbindungsnomen + (Hilfsverb)" mit dem Verb verwandt ist Das Prädikat lautet "Sahen-Verbindungsnomen + ist die Grundform von + Verb", und wenn eine Phrase mehrere Verben enthält, wird das Verb ganz links verwendet. Wenn das Prädikat mehrere Hilfswörter (Phrasen) enthält, ordnen Sie alle Hilfswörter in Wörterbuchreihenfolge an, die durch Leerzeichen getrennt sind. Wenn sich mehrere Klauseln auf das Prädikat beziehen, ordnen Sie alle durch Leerzeichen getrennten Begriffe an (richten Sie sie nach der Reihenfolge der Hilfswörter aus). Zum Beispiel sollte die folgende Ausgabe aus dem Satz erhalten werden: "Der Meister wird auf den Brief antworten, selbst wenn er an einen anderen Ort kommt." "Wenn ich antworte, steht mein Mann im Brief" Speichern Sie die Ausgabe dieses Programms in einer Datei und überprüfen Sie die folgenden Elemente mit UNIX-Befehlen. Prädikate, die häufig im Korpus vorkommen (Sahen-Verbindungsnomenklatur + + Verb) Prädikate und Verbmuster, die häufig im Korpus vorkommen

# 47
with open("neko_func_verb.txt", mode="w") as f:
    for s in doc:
        for c in s:
            if 'Verb' in [m.pos for m in c.morphs]:
                verb = c.morphs[0].base
                for i in c.srcs:
                    v_head = s[i].morphs[-2:]
                    if len(v_head) < 2:
                        continue
                    if v_head[0].pos1 == "Verbindung ändern" and v_head[1].surface == "Zu":
                        verb = ''.join([m.surface for m in v_head]) + verb
                        joshi_dic = {}

                        for j in c.srcs:
                            if len(s[j].morphs) < 2:
                                continue
                            srclast = s[j].morphs[-1]
                            if srclast.pos == 'Partikel' and srclast.surface != "Zu":
                                joshi_dic[srclast.surface] =  ''.join([m.surface for m in s[j].morphs])

                        if len(joshi_dic.keys()) > 0:
                            joshi_list = list(joshi_dic.keys())
                            joshi_list.sort()
                            row = verb + "\t" +  " ".join(joshi_list) + "\t" + " ".join([joshi_dic[joshi] for joshi in joshi_list])
                            f.write(row + "\n")
$ cat neko_func_verb.txt | sed "s/\t/ /g"| cut -f 1 -d " " | sort | uniq -c  | sort -rn -k 3
$ cat neko_func_verb.txt | sed "s/\t/+/g"| cut -f 1,2 -d "+" | sed "s/+/\t/g" | sort | uniq -c  | sort -rn -k 3

Wenn das Prädikat mehrere Klauseln enthält, ordnen Sie alle durch Leerzeichen getrennten Begriffe an (richten Sie sie nach der Reihenfolge der Hilfswörter aus).

Da dies dasselbe war, habe ich es zu einem Wörterbuchtyp gemacht und es zugeordnet Egal wie oft ich das Problem lese, ich kann es nicht verstehen und bekomme von hier aus Probleme

48 Pfade von der Nomenklatur zu den Wurzeln extrahieren

Extrahieren Sie für eine Klausel, die die gesamte Nomenklatur des Satzes enthält, den Pfad von dieser Klausel zum Stamm des Syntaxbaums. Der Pfad im Syntaxbaum muss jedoch die folgenden Spezifikationen erfüllen. Jede Klausel wird durch eine (oberflächliche) morphologische Sequenz dargestellt Verketten Sie von der Startklausel bis zur Endklausel des Pfads die Ausdrücke jeder Klausel mit "->" Aus dem Satz "Ich habe hier zum ersten Mal einen Menschen gesehen" (8. Satz von neko.txt.cabocha) sollte die folgende Ausgabe erhalten werden. Ich sah-> sah Hier-> Zum ersten Mal-> Mensch-> Ich habe etwas gesehen-> Mensch-> Ich habe etwas gesehen-> Ich habe etwas gesehen->

# 48
for s in doc:
    for c in s:
        if "Substantiv" in [m.pos for m in c.morphs]:
            row = "".join([m.surface for m in c.morphs])
            chunk_to = c.dst
            if chunk_to == -1:
                continue
            while(chunk_to != -1):
                row += " -> " + "".join([m.surface for m in s[chunk_to].morphs])
                chunk_to = s[chunk_to].dst
            print(row)

Dies wurde im Vergleich zum vorherigen Problem reibungslos gelöst

49 Extraktion von Abhängigkeitspfaden zwischen Nomenklaturen

Extrahieren Sie den kürzesten Abhängigkeitspfad, der alle Nomenklaturpaare im Satz verbindet. Wenn jedoch die Klauselnummern des Nomenklaturpaars i und j sind (i <j), muss der Abhängigkeitspfad die folgenden Spezifikationen erfüllen. Ähnlich wie bei Problem 48 wird der Pfad ausgedrückt, indem die Ausdrücke (oberflächenmorphologische Elemente) jeder Phrase von der Startklausel bis zur Endklausel mit "->" verkettet werden. Ersetzen Sie die in den Abschnitten i und j enthaltene Nomenklatur durch X bzw. Y. Darüber hinaus kann die Form des Abhängigkeitspfads auf zwei Arten betrachtet werden. Wenn Klausel j auf dem Pfad von Klausel i zum Stamm des Syntaxbaums vorhanden ist: Zeigen Sie den Pfad von Klausel i zu Klausel j an Anders als oben, wenn sich Klausel i und Klausel j an einer gemeinsamen Klausel k auf dem Pfad von Klausel j zur Wurzel des Syntaxbaums überschneiden: der Pfad unmittelbar vor Klausel i zu Klausel k und der Pfad unmittelbar vor Klausel j zu Klausel k, Klausel k Der Inhalt von wird durch "|" verbunden und angezeigt. Die folgende Ausgabe sollte beispielsweise aus dem Satz "Ich habe hier zum ersten Mal einen Menschen gesehen" (8. Satz von neko.txt.cabocha) erhalten werden. X ist|In Y.->Beginnen mit->Mensch->Dinge|sah X ist|Genannt Y.->Dinge|sah X ist|Y.|sah X-> Start-> Y X-> Start-> Mensch-> Y X-> Y

# 49
for s in doc:
    # i <Keine Notwendigkeit für das Ende wegen j
    for i, c in enumerate(s[:-1]):
        if "Substantiv" in [m.pos for m in c.morphs] and c.morphs[-1].pos == "Partikel":
            #Finden Sie j
            for c_rest in s[i+1:]:
                if "Substantiv" in [m.pos for m in c_rest.morphs] and c_rest.morphs[-1].pos == "Partikel":
                    i_clause =  "".join([m.surface if m.pos != "Substantiv" else "X" for m in c.morphs])
                    j_clause =  "".join([m.surface if m.pos != "Substantiv" else "Y" for m in c_rest.morphs])
                    
                    row = i_clause
                    chunk_to = c.dst
                    #Fragen Sie nach dem Pfad, um zu sehen, ob sich j auf dem Pfad befindet
                    kkr_path = [chunk_to]
                    while(kkr_path[-1] != -1):
                        kkr_path.append(s[chunk_to].dst)
                        chunk_to = s[chunk_to].dst
                    
                    if s.index(c_rest) in kkr_path:
                        chunk_to = c.dst
                        while(chunk_to != s.index(c_rest)):
                            row += " -> " + "".join([m.surface for m in s[chunk_to].morphs])
                            chunk_to = s[chunk_to].dst
                        row += " -> " + j_clause
                    else:
                        row += " | " + j_clause
                        chunk_to = c_rest.dst
                        while(s[chunk_to].dst != -1):
                            row += " -> " + "".join([m.surface for m in s[chunk_to].morphs])
                            chunk_to = s[chunk_to].dst
                        row += " | " + "".join([m.surface for m in s[chunk_to].morphs])
                        
                    print(row)

Ersetzen Sie die in den Abschnitten i und j enthaltene Nomenklatur durch X bzw. Y.

Die Spezifikationen und Ausgabebeispiele waren auch hier etwas anders, aber ich habe sie durch eine Nomenklatur wie "X ga" ersetzt.

Kapitel 6: Verarbeiten von englischem Text

Führen Sie die folgende Verarbeitung für den englischen Text (nlp.txt) durch.

$ wget http://www.cl.ecei.tohoku.ac.jp/nlp100/data/nlp.txt

50 Satz Pause

(. Oder; oder: oder? Oder!) → Leerzeichen → Betrachten Sie das Muster des englischen Kapitals als Satzbegrenzer und geben Sie das Eingabedokument in Form eines Satzes pro Zeile aus.

# 50
import re
sentence_sep = re.compile(r'(\.|;|:|\?|!) ([A-Z])')

with open("./nlp.txt") as f:
    txt = f.read()
txt = re.sub(sentence_sep, r'\1\n\2', txt)
print(txt)

Ich habe es beim Nachdenken gelöst

51 Wortausschnitt

Behandeln Sie Leerzeichen als Wortumbrüche, nehmen Sie 50 Ausgaben als Eingabe und geben Sie sie in Form eines Wortes pro Zeile aus. Geben Sie jedoch am Ende der Anweisung eine Leerzeile aus.

# 51
def space2return(txt):
    sentence_sep = re.compile(r'(\.|;|:|\?|!)\n([A-Z])')
    txt = re.sub(sentence_sep, r'\1\n\n\2', txt)
    return re.sub(r' ', r'\n', txt)

txt = space2return(txt)
print(txt)

Empfängt 50 Ausgaben, reagiert jedoch ad hoc, da es sich aufgrund von Zeilenumbrüchen im Satz etwas unerwartet verhält

52 Stemming

Nehmen Sie die Ausgabe von> 51 als Eingabe, wenden Sie den Stemming-Algorithmus von Porter an und geben Sie das Wort und den Stem in tabulatorgetrennten Formaten aus. In Python sollte das Stemming-Modul als Implementierung des Stemming-Algorithmus von Porter verwendet werden.

# 52
from nltk.stem import PorterStemmer
ps = PorterStemmer()

def stem_text(txt):
    for l in txt.split('\n'):
        yield l + '\t' + ps .stem(l)
    
for line in stem_text(txt):
    print(line)

Es war nicht in Links bereitgestellt, also habe ich es stattdessen verwendet. Ich habe versucht, Yield zu verwenden, was ich normalerweise vermeide, aber festgestellt, dass der Rückgabewert ein Iterator ist.

53 Tokenization

Verwenden Sie Stanford Core NLP, um das Analyseergebnis des Eingabetextes im XML-Format zu erhalten. Lesen Sie auch diese XML-Datei und geben Sie den Eingabetext in Form eines Wortes pro Zeile aus.

$ wget http://nlp.stanford.edu/software/stanford-corenlp-full-2018-10-05.zip
$ unzip stanford-corenlp-full-2018-10-05.zip
$ java -cp "./stanford-corenlp-full-2018-10-05/*" edu.stanford.nlp.pipeline.StanfordCoreNLP -annotators tokenize,ssplit,parse,lemma,ner,coref -file ./nlp.txt

Dieser Typ, anstatt unter XML-Parsing zu leiden Lesen Sie die Referenz für -annotators, wenn Sie Java ausführen, und ändern Sie sie gegebenenfalls

# 53
import xml.etree.ElementTree as ET

tree = ET.parse("./nlp.txt.xml")
root = tree.getroot()
for token in root.iter("token"):
    print(token.find("word").text)

Ist dies eine Möglichkeit, das Ganze auszugeben und die Tags zu überprüfen?

54 Kennzeichnung von Teilwörtern

Lesen Sie das XML-Analyseergebnis von Stanford Core NLP und geben Sie Wörter, Deckspelzen und Teile in tabulatorgetrennten Formaten aus.

# 54
for token in root.iter("token"):
    print(token.find("word").text + "\t" + token.find("lemma").text + "\t" + token.find("POS").text)

Sehr schwer zu sehen

55 Extraktion eindeutiger Ausdrücke

Extrahieren Sie alle Personennamen im Eingabetext.

# 55
for token in root.iter("token"):
    NERtag = token.find("NER").text
    if NERtag == "PERSON":
        print(token.find("word").text)

Ich dachte, es sei eine Implementierung, aber sie wurde markiert

56 Co-Referenzanalyse

Ersetzen Sie den Referenzausdruck (Erwähnung) im Satz durch den repräsentativen Referenzausdruck (repräsentative Erwähnung) basierend auf dem Ergebnis der Co-Referenzanalyse von Stanford Core NLP. Achten Sie beim Ersetzen jedoch darauf, dass der ursprüngliche Referenzausdruck verstanden wird, z. B. "Repräsentativer Referenzausdruck (Referenzausdruck)".

# 56
rep_dic_list = []

#Ein Wörterbuch erstellen
for coreferences in root.findall("document/coreference"):
    for mentions in coreferences:
        for m in mentions:
            if "representative" in m.attrib:
                rep_txt = m.find("text").text
            else:
                tmp_dic = {}
                tmp_dic["sentence"] = m.find("sentence").text
                tmp_dic["start"] = m.find("start").text
                tmp_dic["end"] = m.find("end").text
                tmp_dic["rep_txt"] = rep_txt
                rep_dic_list.append(tmp_dic)
                
#Ausgabe
for s in root.iter("sentence"):
    rep_sent_list = [rd for rd in rep_dic_list if rd["sentence"] == s.attrib["id"]]
    #Gibt an, ob die Anweisung ersetzt werden muss
    if len(rep_sent_list) == 0:
            print(" ".join([token.find("word").text for token in s.iter("token")]), end=" ")
    else:
        for token in s.iter("token"):
            tid = token.attrib["id"]
            rep_token_list = [rd for rd in rep_sent_list if rd["start"] == tid or rd["end"] == tid]
            
            if len(rep_token_list) > 0:
                #Da es nur einen gibt, nehmen Sie ihn heraus
                rep_dic = rep_token_list[0]
                
                #Dekoration
                if tid == rep_dic["start"]:
                    print("「" + rep_dic["rep_txt"] + " (", end=" ")
                if tid == rep_dic["end"]:
                    print(")」", end=" ")
                    
            print(token.find("word").text, end=" ")

Ich konnte die Problemstellung nicht verstehen und habe sie lange hier gelassen. Erstellen Sie ein Wörterbuch und ändern Sie es, anstatt es zu ersetzen

57 Abhängigkeitsanalyse

Visualisieren Sie die reduzierten Abhängigkeiten des Stanford Core NLP als gerichteten Graphen. Zur Visualisierung ist es ratsam, den Abhängigkeitsbaum in die DOT-Sprache zu konvertieren und Graphviz zu verwenden. Verwenden Sie pydot, um gerichtete Diagramme direkt aus Python zu visualisieren.

# 57
import random, pathlib
from graphviz import Digraph

f = pathlib.Path('nlp.png')
fmt = f.suffix.lstrip('.')
fname = f.stem

dot = Digraph(format=fmt)
dot.attr("node", shape="circle")

sent_id = 3

for sents in root.findall(f"document/sentences/sentence[@id='{sent_id}']"):
    for deps in sents:
        for dep in deps.findall("[@type='collapsed-dependencies']"):
            for token in dep:
                gvnr = token.find("governor")
                dpnt = token.find("dependent")
                dot.node(gvnr.attrib["idx"], gvnr.text)
                dot.node(dpnt.attrib["idx"], dpnt.text)
                dot.edge(gvnr.attrib["idx"], dpnt.attrib["idx"])


dot.filename = fname
dot.render()

# print(dot)
from IPython.display import Image, display_png
display_png(Image(str(f)))

Zuerst habe ich "Gouverneur" und "abhängig" durchlaufen, also habe ich überhaupt nicht verstanden.

58 Taple-Extraktion

Geben Sie die Menge des "Subjekt-Prädikat-Objekts" in tabulatorgetrenntem Format basierend auf dem Ergebnis der Abhängigkeitsanalyse (kollabierte Abhängigkeiten) von Stanford Core NLP aus. Im Folgenden finden Sie jedoch die Definitionen des Subjekts, Prädikats und Objekts. Prädikat: Ein Wort, das Kinder (Angehörige) von nsubj- und dobj-Beziehungen hat Betreff: Kind (abhängig), das eine nsubj-Beziehung zum Prädikat hat Objekt: Ein Kind (abhängig), das eine dobj-Beziehung zum Prädikat hat

# 58
for sents in root.findall(f"document/sentences/sentence"):
    for deps in sents:
        for dep in deps.findall("[@type='collapsed-dependencies']"):
            nsubj_list = []
            for token in dep.findall("./dep[@type='nsubj']"):
                gvnr = token.find("governor")
                dpnt = token.find("dependent")
                nsubj_list.append( {
                    (gvnr.attrib["idx"], gvnr.text): (dpnt.attrib["idx"], dpnt.text)
                })
            for token in dep.findall("./dep[@type='dobj']"):
                gvnr = token.find("governor")
                dpnt = token.find("dependent")
                dobj_tuple = (gvnr.attrib["idx"], gvnr.text)
                
                if dobj_tuple in [list(nsubj.keys())[0] for nsubj in nsubj_list]:
                    idx =  [list(nsubj.keys())[0] for nsubj in nsubj_list].index( dobj_tuple )
                    jutugo = gvnr.text
                    shugo = nsubj_list[idx][dobj_tuple][1]
                    mokutekigo = dpnt.text
                    print(shugo + "\t" + jutugo + "\t" + mokutekigo)

Richtlinie zum einmaligen Erstellen eines Wörterbuchs und anschließendes Suchen nach einem Wörterbuch, das die Bedingungen erfüllt

59 Analyse der S-Gleichung

Lesen Sie das Ergebnis der Phrasenstrukturanalyse von Stanford Core NLP (S-Formel) und zeigen Sie alle Nomenklaturphrasen (NP) im Satz an. Alle verschachtelten Nomenklaturen anzeigen.

# 59 
import xml.etree.ElementTree as ET
import re

def search_nest(t):
    if isinstance(t[0], str):
        if isinstance(t[1], str):
            if t[0] == "NP":
                print(t[1])
            return t[1]
        else:
            if t[0] == "NP":
                np_list = []
                for i in t[1:]:
                    res = search_nest(i)
                    if isinstance(res, str):
                        np_list.append(search_nest(i))
                if len(np_list) > 0:
                    print(' '.join(np_list))
            else:
                for i in t[1:]:
                    search_nest(i)
    else:
        for i in t:
            search_nest(i)


tree = ET.parse("./nlp.txt.xml")
root = tree.getroot()
sent_id = 30

for parse in root.findall(f"document/sentences/sentence[@id='{sent_id}']/parse"):
    S_str = parse.text
    S_str = S_str.replace("(", "('")
    S_str = S_str.replace(")", "')")
    S_str = S_str.replace(" ", "', '")
    S_str = S_str.replace("'(", "(")
    S_str = S_str.replace(")'", ")")
    exec(f"S_tuple = {S_str[:-2]}")
    search_nest(S_tuple)
    

Ich konnte die Verschachtelung von () nicht erkennen und habe die größte schmutzige Implementierung in meinem Leben vorgenommen. Ich habe sie fest in einen Taple-Typ codiert und rekursiv extrahiert. Ich habe "Regex" ausprobiert, konnte es aber nicht selbst lösen, daher habe ich der Antwort Priorität eingeräumt.

Ende

Es dauerte ungefähr doppelt so lange wie in den Kapiteln 1 bis 4, da beide Kapitel die ersten Bibliotheken waren und die Anzahl der Sprachverarbeitungsbegriffe plötzlich zunahm. Der Rest sind jedoch DB, ML und Vektor, daher bin ich nicht vorsichtig.

Recommended Posts

Antworten und Eindrücke von 100 Sprachverarbeitungsklopfen - Teil 1
Antworten und Eindrücke von 100 Sprachverarbeitungsklopfen - Teil 2
Überblick über die Verarbeitung natürlicher Sprache und ihre Datenvorverarbeitung
Arten der Vorverarbeitung in der Verarbeitung natürlicher Sprache und ihre Leistungsfähigkeit
100 Sprachverarbeitung Knock-42: Anzeige der Phrase der betroffenen Person und der betroffenen Person
Künstliche Sprache Logivan und Verarbeitung natürlicher Sprache (Verarbeitung künstlicher Sprache)
100 Sprachverarbeitung Knock-59: Analyse der S-Formel
Zusammenfassung der Mehrprozessverarbeitung der Skriptsprache
100 Sprachverarbeitung Knock-91: Vorbereitung von Analogiedaten
Sprachverarbeitung 100 Knocks-44: Visualisierung abhängiger Bäume
Verarbeiten Sie den Namen der Yugioh-Karte in natürlicher Sprache - Yugiou Data Science 2. NLP
100 Sprachverarbeitung Knock-22: Extraktion des Kategorienamens
100 Sprachverarbeitung Knock-26: Entfernen von hervorgehobenem Markup
Rehabilitation von Python- und NLP-Kenntnissen ab "100 Language Processing Knock 2015" (Kapitel 1)
100 Sprachverarbeitungsklopfen 03 ~ 05
100 Sprachverarbeitungsklopfen (2020): 40
100 Sprachverarbeitungsklopfen (2020): 32
100 Sprachverarbeitungsklopfen (2020): 47
100 Sprachverarbeitungsklopfen (2020): 22
100 Sprachverarbeitungsklopfen (2020): 26
100 Sprachverarbeitungsklopfen (2020): 34
100 Sprachverarbeitungsklopfen (2020): 28
100 Sprachverarbeitungsklopfen (2020): 42
100 Sprachverarbeitungsklopfen (2020): 29
100 Sprachverarbeitungsklopfen (2020): 49
100 Sprachverarbeitungsklopfen 06 ~ 09
100 Sprachverarbeitungsklopfen (2020): 43
100 Sprachverarbeitungsklopfen (2020): 24
100 Sprachverarbeitungsklopfen (2020): 45
100 Sprachverarbeitung Knock-32 (mit Pandas): Prototyp des Verbs
100 Sprachverarbeitungsklopfen (2020): 10-19
100 Sprachverarbeitungsklopfen (2020): 30
Sprachverarbeitung 100 Schläge-45: Extraktion von Verbfallmustern
100 Sprachverarbeitungsklopfen (2020): 00-09
100 Sprachverarbeitungsklopfen (2020): 31
100 Sprachverarbeitungsklopfen (2020): 38
100 Sprachverarbeitung Knock-75 (mit Scicit-Learn): Gewicht der Identität
100 Sprachverarbeitungsklopfen (2020): 48
100 Sprachverarbeitungsklopfen (2020): 44
100 Sprachverarbeitungsklopfen (2020): 41
100 Sprachverarbeitungsklopfen (2020): 37
100 Sprachverarbeitung klopfen 00 ~ 02
100 Sprachverarbeitungsklopfen (2020): 25
100 Sprachverarbeitungsklopfen (2020): 23
100 Sprachverarbeitungsklopfen (2020): 33
100 Sprachverarbeitungsklopfen (2020): 20
100 Sprachverarbeitungsklopfen (2020): 27
100 Sprachverarbeitungsklopfen (2020): 46
Zusammenfassung der Pickle- und Unpickle-Verarbeitung von benutzerdefinierten Klassen
Unerträgliche Aufmerksamkeitsmangel bei der Verarbeitung natürlicher Sprache
100 Sprachverarbeitungsklopfen (2020): 21
100 Sprachverarbeitungsklopfen (2020): 36
Rehabilitation von Python- und NLP-Kenntnissen ab "Knock 100 Language Processing 2015" (Kapitel 2, zweite Hälfte)
Rehabilitation von Python- und NLP-Kenntnissen ab "100 Language Processing Knock 2015" (Kapitel 2, erste Hälfte)
[Sprachverarbeitung 100 Schläge 2020] Zusammenfassung der Antwortbeispiele von Python
Verarbeitung von CSV-Daten in voller und halber Breite in Python
Sprachverarbeitung 100 Knocks-46: Extraktion von Verbfall-Frame-Informationen
100 Sprachverarbeitung Knock-36 (unter Verwendung von Pandas): Häufigkeit des Auftretens von Wörtern
[Kapitel 5] Einführung in Python mit 100 Klopfen Sprachverarbeitung
[Kapitel 6] Einführung in Scicit-Learn mit 100 Klopfen Sprachverarbeitung
Leistungsüberprüfung der Datenvorverarbeitung in der Verarbeitung natürlicher Sprache