[PYTHON] 100 Sprachverarbeitung klopft Morphologische Analyse in Kapitel 4 gelernt

Einführung

Ich löse 100 Klopfen bei der Sprachverarbeitung in einer Studiensitzung, die sich auf Mitglieder des Unternehmens, aber den Antwortcode und die Lösung konzentriert Dies ist eine Zusammenfassung der Tricks, die ich dabei nützlich fand. Der größte Teil des Inhalts wurde von mir selbst untersucht und verifiziert, enthält jedoch auch Informationen, die von anderen Mitgliedern der Studiengruppe geteilt wurden.

Bis zu Kapitel 3 war der Inhalt für alle Python-Programmierungen verwendbar, aber da es sich bei diesem Kapitel um eine morphologische Analyse handelt, ähnelt es endlich mehr der Sprachverarbeitung.

Serie

Umgebung

Code

Vorverarbeitung

Legen Sie neko.txt im selben Verzeichnis wie die ipynb- (oder Python-) Datei ab

!mecab neko.txt -o neko.txt.mecab

Das Ergebnis der morphologischen Analyse wird dann in "neko.txt.mecab" aufgezeichnet.

30. Lesen der Ergebnisse der morphologischen Analyse

import re
import itertools

def parse_text(flat=True):
    with open('neko.txt.mecab') as file:
        morphs = []
        sentence = []

        for line in file:
            if re.search(r'EOS', line):
                continue

            surface, rest = line.split('\t')
            arr = rest.split(',')
            sentence.append({
                'surface': surface,
                'base': arr[6],
                'pos': arr[0],
                'pos1': arr[1],
            })
                
            if surface == ' ': #Leerzeichen gelten nicht als morphologische Elemente
                sentence.pop(-1)
            if surface in [' ', '。']: #Betrachten Sie Leerzeichen und Interpunktion als das Ende eines Satzes
                morphs.append(sentence)
                sentence = []
        
        if flat:
            return list(itertools.chain.from_iterable(morphs))
        else:
            return morphs

parse_text(flat=False)[:10]

Ergebnis


[[{'surface': 'ich', 'base': 'ich', 'pos': 'Substantiv', 'pos1': '代Substantiv'},
  {'surface': 'Ist', 'base': 'Ist', 'pos': 'Partikel', 'pos1': '係Partikel'},
  {'surface': 'Katze', 'base': 'Katze', 'pos': 'Substantiv', 'pos1': 'Allgemeines'},
  {'surface': 'damit', 'base': 'Ist', 'pos': 'Hilfsverb', 'pos1': '*'},
  {'surface': 'Gibt es', 'base': 'Gibt es', 'pos': 'Hilfsverb', 'pos1': '*'},
  {'surface': '。', 'base': '。', 'pos': 'Symbol', 'pos1': 'Phrase'}],
 [{'surface': 'Name', 'base': 'Name', 'pos': 'Substantiv', 'pos1': 'Allgemeines'},

Für dieses Problem muss "ein Satz als Liste morphologischer Elemente ausgedrückt werden (Zuordnungstyp)". Bei Verwendung dieser Funktion in Problem 31 und höher wurde der Rückgabewert jedoch abgeflacht (nicht verschachtelt). ) Ist einfacher zu handhaben, deshalb habe ich beschlossen, ein formelles Argument namens "flach" vorzubereiten. Der Standardwert für diese "flache" ist "wahr", aber in dieser Ausgabe übergebe ich das Argument "flach = falsch", weil ich eine nicht abgeflachte Liste möchte.

Der Grund, warum in der letzten Zeile "[: 10]" steht, ist, dass es genau richtig war, dass die Anzahl der zur Bestätigung anzuzeigenden Elemente etwa 10 betrug, sodass keine besondere Notwendigkeit besteht.

31. Verb

import numpy as np

def extract_surface():
    verbs = list(filter(lambda morph: morph['pos'] == 'Verb', parse_text()))
    return [verb['surface'] for verb in verbs]

print(extract_surface()[:100])

Ergebnis


['Geboren', 'Tsuka', 'Shi', 'Weinen', 'Shi', 'Ist', 'Start', 'Sie sehen', 'Hör mal zu', 'Fang', 'Gekocht', 'Essen', 'Gedanken', 'Wird geladen', 'Sein', 'Aufzug', 'Sein', 'Shi', 'Ah', 'Beruhigen', 'Sie sehen', 'Sie sehen', 'Gedanken', 'Verbleibend', 'Ist', 'Sa', 'Re', 'Shi', 'Treffen', 'Treffen', 'Shi', 'nur', 'Wenn', 'Shi', 'Ist', 'Schlag', 'einstellen', 'Schwach', 'trinken', 'Kennt', 'Hinsetzen', 'Oh', 'Machen', 'Shi', 'Start', 'Bewegung', 'Bewegung', 'Verstehen', 'Herumgehen', 'Werden', 'Vom Assistenten', 'Gedanken', 'Ist', 'Saり', 'Shi', 'aus', 'Shi', 'Ist', 'Gedankenausそ', 'Verstehen', 'Mit', 'Sie sehenる', 'ich', 'Oh', 'Sie sehenえ', '隠Shi', 'Shiまっ', 'Anders', '明ich', 'ich', 'Sein', '這ichausShi', 'Sie sehenる', 'Wegschmeißen', 'Sein', '這ichausす', 'Gibt es', 'Hinsetzen', 'Shi', 'Gedanken', 'Sie sehen', 'aus', 'Shi', 'Weinen', 'Kommen', 'くReる', 'GedankenMit', 'Schließlich', 'Sie sehen', 'Kommen', 'Gekreuzt', 'Nehmen', 'Verringert', 'Kommen', 'Weinen', 'aus', 'Gibt es', 'Gibt es', 'Shi', 'Es ist Zeit']

Der Rückgabewert kann auch als "Liste (Karte (Lambda Morph: Morph ['Oberfläche'], Verben))" erstellt werden. Die Verwendung der Einschlussnotation wie oben ist jedoch ein präziserer Code.

Dies hängt auch davon ab, wie Sie die Problemanweisung interpretieren. Wenn Sie jedoch keine doppelten Elemente in der Rückgabeliste zulassen möchten, setzen Sie die letzte Zeile der Funktion.

return set([verb['surface'] for verb in verbs])

Es gibt Methoden wie.

32. Prototyp des Verbs

def extract_base():
    verbs = list(filter(lambda morph: morph['pos'] == 'Verb', parse_text()))
    return [verb['base'] for verb in verbs]

print(extract_base()[:100])

Ergebnis


['Geboren', 'Tsukuri', 'Machen', 'Schrei', 'Machen', 'Ist', 'Start', 'sehen', 'Hör mal zu', 'Erfassung', 'Kochen', 'Essen', 'Überlegen', 'Stellen', 'Sein', 'Aufzug', 'Sein', 'Machen', 'Gibt es', '落ちTsukuri', 'sehen', 'sehen', 'Überlegen', 'Bleiben übrig', 'Ist', 'Machen', 'Sein', 'Machen', 'Treffen', 'Treffen', 'Machen', 'Nomu', 'Werden', 'Machen', 'Ist', 'Schlag', 'Machen', 'Schwach', 'trinken', 'kennt', 'Hinsetzen', 'Oru', 'Machen', 'Machen', 'Start', 'Bewegung', 'Bewegung', 'Verstehen', 'Herumgehen', 'Werden', 'Gerettet werden', 'Überlegen', 'Ist', 'Saru', 'Machen', 'Geh raus', 'Machen', 'Ist', 'Ausdenken', 'Verstehen', 'Anfügen', 'sehen', 'Ist', 'Oru', 'erscheinen', 'ausblenden', 'Enden', 'Falsch', 'Deutlich sein', 'Ist', 'Sein', 'Herauskriechen', 'sehen', 'Verwerfen', 'Sein', 'Herauskriechen', 'Gibt es', 'Hinsetzen', 'Machen', 'Überlegen', 'sehen', 'Geh raus', 'Machen', 'Schrei', 'Kommen Sie', 'くSein', '考えAnfügen', 'machen', 'sehen', 'Kommen Sie', 'Kreuz', 'Nehmen', 'verringern', 'Kommen Sie', 'Schrei', 'Geh raus', 'Gibt es', 'Gibt es', 'Machen', 'Rasieren']

Fast das gleiche wie 31.

33. Sahen Substantiv

def extract_sahens():
    return list(filter(lambda morph: morph['pos1'] == 'Verbindung ändern', parse_text()))

extract_sahens()[:20]

Ergebnis


[{'surface': 'Registrieren', 'base': 'Registrieren', 'pos': 'Substantiv', 'pos1': 'Verbindung ändern'},
 {'surface': 'Erinnerung', 'base': 'Erinnerung', 'pos': 'Substantiv', 'pos1': 'Verbindung ändern'},
 {'surface': 'Geschichte', 'base': 'Geschichte', 'pos': 'Substantiv', 'pos1': 'Verbindung ändern'},
 {'surface': 'Dekoration', 'base': 'Dekoration', 'pos': 'Substantiv', 'pos1': 'Verbindung ändern'},
 {'surface': 'Vorsprung', 'base': 'Vorsprung', 'pos': 'Substantiv', 'pos1': 'Verbindung ändern'},
 ...

Fast das gleiche wie 31.

34. "B von A"

def extract_noun_phrases():
    morphs = parse_text()
    phrases = []

    for i, morph in enumerate(morphs):
        if morph['surface'] == 'von' and morphs[i - 1]['pos'] == 'Substantiv' \
                and morphs[i + 1]['pos'] == 'Substantiv':
            phrases.append(
                morphs[i - 1]['surface'] + 'von' + morphs[i + 1]['surface'])

    return phrases
    
print(extract_noun_phrases()[:100])

Ergebnis


['Seine Handfläche', 'Auf der Handfläche', 'Studentengesicht', 'Sollte Gesicht', 'Mitten im Gesicht', 'In dem Loch', 'Kalligraphiepalme', 'Die Rückseite der Handfläche', 'Was', 'Essentielle Mutter', 'Auf dem Strohhalm', 'In Sasahara', 'Vor dem Teich', 'Auf dem Teich', 'Loch im Zaun', 'Drei Nachbarn', 'Zeitablauf', 'Im Haus', 'Sein Schüler', 'Andere Menschen als', 'Vorheriger Schüler', 'Deine Chance', 'Drei von euch', 'Juckreiz in der Brust', 'Haushälterin', 'Meister', 'Unter der Nase', 'Mein Gesicht', 'Mein Zuhause', 'Mein Ehemann', 'Heimzeug', 'Unsere', 'Sein Studium', 'Auf dem Buch', 'Hautfarbe', 'Auf dem Buch', 'Seine jede Nacht', 'Außer', 'Neben meinem Mann', 'Sein Knie', 'Auf dem Knie', 'Aus Erfahrung', 'Auf der Reisschüssel', 'Auf dem 炬 燵', 'Von hier', 'Begleitetes Bett', 'Zwischen ihnen', 'Begleiter', 'Beispiel Nerv', 'Sexueller Meister', 'Nächster Raum', 'Egoistisch', 'Für mich', 'Zwischen den Brettern in der Küche', 'Respekt für mich', 'Mukai weiß', 'Wie ein Ball', 'Haus dort', 'Heimschüler', 'Hinterer Teich', 'Eltern-Kind-Liebe', 'Weitere Diskussion', 'Kopf stechen', 'Regenschirm von 鰡', 'Für Sie', 'Militärhaus', 'Meister des Ersatzes', 'Lehrerhaus', 'Katzenzeit', 'Mein Haus', 'Haushälterin', 'Voller Englisch', 'Schwache Magengewohnheit', 'Im Gepäckträger', 'Hira no Sect', 'Monatliches Gehalt', 'Vorerst', 'Wie unten', 'Wie jetzt', 'Memoiren des Meisters', 'Sein Freund', 'Brille mit Goldrand', 'Das Gesicht des Meisters', 'Phantasie im Inneren', 'Übersetzt', 'Vermieter von Interesse', 'Hinter dem goldenen Rand', 'Hinter mir', 'Sein Freund', 'Mein Kreis', 'Um das Gesicht', 'Das Ergebnis der Zugabe', 'Gesichtszüge', 'Andere Katzen', 'Unbeholfener Diener', 'Mein Ehemann', 'Katze der gleichen Produktion', 'Gefleckte Haut', 'Färbung des Meisters', 'Relative Muskeln']

Wenn Sie "enumerate ()" verwenden, können Sie die Information, dass "morph" in "morphs" "i" ist, als Variable verwenden, was ein ordentlicher Code ist.

35. Verkettung der Nomenklatur

def extract_continuous_nouns():
    morphs = parse_text()
    continuous_nouns = []

    for i, morph in enumerate(morphs):
        if morph['pos'] == 'Substantiv' and morphs[i + 1]['pos'] == 'Substantiv':
            continuous_noun = morph['surface'] + morphs[i + 1]['surface']
            
            j = 1
            while morphs[i + 1 + j]['pos'] == 'Substantiv':
                continuous_noun += morphs[i + 1 + j]['surface']
                j += 1

            continuous_nouns.append(continuous_noun)
            
    return continuous_nouns

print(extract_continuous_nouns()[:100])

Ergebnis


['In Menschen', 'Rechtzeitig', 'Dann Katze', 'Puupuu und Rauch', 'In der Villa', 'Drei Haare', 'Anders als Student', 'Fünfundvierzig Henne', 'Gohen', 'Neulich', 'Mima', 'Deine Küche', 'Mama zurück', 'Wohnhaus', 'Ganztägiges Studium', 'Fleißiger Arbeiter', 'Fleißiger Arbeiter', 'Fleißig', 'Ein paar Seiten', 'Drei Seiten', 'Anders als mein Mann', 'So weit ich bin', 'Morgenmeister', 'Zwei Personen', 'Zuletzt schwer', '--Katze', 'Neurogastrische Schwäche', 'Magenschwäche', 'Finger', 'Schrecklicher Arsch', 'Sprachpause', 'Meine Frau', 'Insgesamt', 'Muskelrichtung', 'Shiro', 'Jedes Mal', 'Shiro', 'Neulich Ball', 'Vier', 'dritter Tag', 'Tag', 'Vier', 'Shiro', 'Unsere Katzen', 'Etc.', 'Katzen', 'Familienleben', 'Leben', 'Drei Haare君', 'Mao', 'Eigentum', 'Zwischen uns', 'Zwischen derselben Familie', 'Augenstich', 'Sie sind Menschen', 'Wir', 'ich', 'Shiro', 'Drei Haare君', 'Mao', 'Voller Fehler', 'Herr Hoshi', 'Munemori', 'Munemori', 'Monatliches Gehaltsdatum', 'Aquarellfarbe', 'Jeden Tag jeden Tag lernen', 'Tägliches Studium', 'Person', 'Bürste selbst', 'Über Brille', 'Itari', 'Vermieter Andrea del Salt', 'Tau', 'Kalt 鴉', 'Diese Breite', 'Live malen', 'Am nächsten Tag', 'Würziger Stock', 'Jetzt ich', 'Jetzt ich', 'Wellenprodukt', 'Wunder', 'Blinde Katze', 'Geheimnis in meinem Herzen', 'Wie viel Andrea del Salt', 'Ein weiterer großer', 'Brechen', 'Dummer Typ', 'Dummer Typ', 'Würziger Stock', 'Dummer TypAnruf', 'Ruf einen Bastard an', 'Anruf', 'Hirai', 'Dummer Typ', 'Jeder wächst', 'Wo hin', 'Mehrmals', '10 tsubo']

36. Häufigkeit des Auftretens von Wörtern

import pandas as pd

def sort_by_freq():
    words = [morph['base'] for morph in parse_text()]
    
    return pd.Series(words).value_counts()

sort_by_freq()[:20]

Ergebnis


9194
。     7486
6868
、     6772
Ist 6420
...

Importieren Sie als alternative Lösung die Standardbibliothek "Sammlungen" wie unten gezeigt.

from collections import Counter

Sie können auch die Methode "most_common ()" des Objekts "Counter ()" verwenden (anstelle der "value_counts ()" der "Pandas").

return Counter(words).most_common()

Ergebnis


[('von', 9194),
 ('。', 7486),
 ('Hand', 6868),
 ('、', 6772),
 ('Ist', 6420),
 ...

Der Unterschied zwischen diesen beiden Lösungen besteht darin, dass "value_counts ()" "Series" zurückgibt, während "most_common ()" ein Array von Tapples zurückgibt, sodass eines für eine einfachere nachfolgende Verarbeitung verwendet werden sollte. Ist es nicht gut

37. Top 10 der häufigsten Wörter

import japanize_matplotlib

def draw_bar_graph():
    sort_by_freq()[:10].plot.bar()

draw_bar_graph()

bar.png

Es dauert eine Weile, bis Japanisch angezeigt wird, aber es war einfach, die im Artikel hier eingeführte Bibliothek namens "japanize_matplotlib" zu verwenden.

Auch in Bezug auf den Inhalt der Funktion wollte ich sie kurz schreiben, also habe ich ".plot.bar ()" für das "Series" -Objekt verwendet.

import matplotlib.pyplot as plt

Nach dem Import von matplotlib as funktioniert es auch dann, wenn Sie wie folgt schreiben.

morph_freqs = sort_by_freq()[:10]
plt.bar(morph_freqs.index, morph_freqs)

38. Histogramm

import matplotlib.pyplot as plt

def draw_hist():
    plt.xlabel('Häufigkeit des Auftretens')
    plt.ylabel('Anzahl der Worttypen')
    plt.hist(sort_by_freq(), bins=200)
    
draw_hist()

hist.png

Wenn Sie das Ganze anzeigen möchten, handelt es sich um einen solchen Code, der jedoch etwas schwer zu erkennen ist. Daher ist es möglicherweise realistischer, den Anzeigebereich wie folgt einzuschränken.

def draw_hist_2():
    plt.xlabel('Häufigkeit des Auftretens')
    plt.ylabel('Anzahl der Worttypen')
    plt.title('Erscheinungsfrequenz 20 oder weniger')
    plt.hist(sort_by_freq(), bins=20, range=(1, 20))

draw_hist_2()

hist2.png

39. Zipfs Gesetz

def draw_log_graph():
    plt.xscale('log')
    plt.yscale('log')
    plt.xlabel('Rangfolge der Erscheinungshäufigkeit')
    plt.ylabel('Häufigkeit des Auftretens')
    plt.scatter(range(1, len(sort_by_freq()) + 1), sort_by_freq(), s=10)
    
draw_log_graph()

zipf.png

Beim Aufrufen der "Scatter" -Methode können Sie die Größe der Punkte mit der Option "s" angeben. Der Standardwert ist 20, aber er war etwas groß, also habe ich ihn auf "10" gesetzt.

Zusammenfassung

MeCab ist Open Source Software, aber es war interessant zu wissen, dass es immer noch so viele Dinge kann.

Andererseits hatte ich auch das Gefühl, dass die Genauigkeit der Analyse allein damit nicht perfekt war (zum Beispiel wurde "Puuputo" zurückgegeben, da das Ausgabeergebnis bei 35 keine Nomenklatur, sondern ein Zusatz ist). Um dieses Problem zu lösen, ist es meiner Meinung nach notwendig, verschiedene Wörterbücher auszuprobieren und selbst anzupassen.

Das ist alles für dieses Kapitel, aber wenn Sie einen Fehler machen, kommentieren Sie bitte.

Recommended Posts

100 Sprachverarbeitung klopft Morphologische Analyse in Kapitel 4 gelernt
100 Sprachverarbeitungsklopfen 2020: Kapitel 4 (morphologische Analyse)
[Sprachverarbeitung 100 Schläge 2020] Kapitel 4: Morphologische Analyse
Sprachverarbeitung 100 Schläge Kapitel 4: Morphologische Analyse 31. Verben
100 Sprachverarbeitung Knock 2020 Kapitel 4: Morphologische Analyse
[Sprachverarbeitung 100 Schläge 2020] Kapitel 5: Abhängigkeitsanalyse
100 Sprachverarbeitung Knock Kapitel 4: Morphologische Analyse
100 Language Processing Knock 2015 Kapitel 4 Morphologische Analyse (30-39)
100 natürliche Sprachverarbeitung klopft Kapitel 4 Morphologische Analyse (erste Hälfte)
100 natürliche Sprachverarbeitung klopft Kapitel 4 Morphologische Analyse (zweite Hälfte)
100 Sprachverarbeitungsklopfen ~ Kapitel 1
100 Sprachverarbeitung klopft Kapitel 2 (10 ~ 19)
100 Sprachverarbeitung Knock UNIX-Befehle in Kapitel 2
100 Sprachverarbeitung Klopfen Sie auf reguläre Ausdrücke, die Sie in Kapitel 3 gelernt haben
100 natürliche Sprachverarbeitung klopft Kapitel 5 Abhängigkeitsanalyse (zweite Hälfte)
100 natürliche Sprachverarbeitung klopft Kapitel 5 Abhängigkeitsanalyse (erste Hälfte)
100 Sprachverarbeitung Knock 2015 Kapitel 5 Abhängigkeitsanalyse (40-49)
[Sprachverarbeitung 100 Schläge 2020] Kapitel 3: Reguläre Ausdrücke
100 Klicks in der Verarbeitung natürlicher Sprache Kapitel 4 Kommentar
[Sprachverarbeitung 100 Schläge 2020] Kapitel 6: Maschinelles Lernen
100 Sprachverarbeitung Knock Kapitel 1 in Python
[Sprachverarbeitung 100 Schläge 2020] Kapitel 1: Vorbereitende Bewegung
[Sprachverarbeitung 100 Schläge 2020] Kapitel 7: Wortvektor
100 Sprachverarbeitung Knock 2020 Kapitel 5: Abhängigkeitsanalyse
100 Sprachverarbeitung klopfen 2020: Kapitel 3 (regulärer Ausdruck)
[Sprachverarbeitung 100 Schläge 2020] Kapitel 8: Neuronales Netz
[Sprachverarbeitung 100 Schläge 2020] Kapitel 2: UNIX-Befehle
[Sprachverarbeitung 100 Schläge 2020] Kapitel 9: RNN, CNN
100 Sprachverarbeitungsklopfen 03 ~ 05
100 Sprachverarbeitungsklopfen (2020): 40
100 Sprachverarbeitungsklopfen (2020): 32
100 Sprachverarbeitungsklopfen (2020): 35
100 Sprachverarbeitungsklopfen (2020): 39
100 Sprachverarbeitungsklopfen (2020): 22
100 Sprachverarbeitungsklopfen (2020): 26
100 Sprachverarbeitungsklopfen (2020): 34
100 Sprachverarbeitungsklopfen (2020): 42
100 Sprachverarbeitungsklopfen (2020): 29
100 Sprachverarbeitungsklopfen 06 ~ 09
100 Sprachverarbeitungsklopfen (2020): 43
100 Sprachverarbeitungsklopfen (2020): 24
100 Sprachverarbeitungsklopfen (2020): 45
100 Sprachverarbeitungsklopfen (2020): 10-19
100 Sprachverarbeitungsklopfen (2020): 30
100 Sprachverarbeitungsklopfen (2020): 00-09
100 Sprachverarbeitungsklopfen (2020): 31
100 Sprachverarbeitungsklopfen (2020): 48
100 Sprachverarbeitungsklopfen (2020): 44
100 Sprachverarbeitungsklopfen (2020): 41
100 Sprachverarbeitungsklopfen (2020): 37
100 Sprachverarbeitungsklopfen (2020): 25
100 Sprachverarbeitungsklopfen (2020): 23
100 Sprachverarbeitungsklopfen (2020): 33
100 Sprachverarbeitungsklopfen (2020): 20
100 Sprachverarbeitungsklopfen (2020): 27
100 Sprachverarbeitungsklopfen (2020): 46
100 Sprachverarbeitungsklopfen (2020): 21
100 Sprachverarbeitungsklopfen (2020): 36
100 Amateur-Sprachverarbeitungsklopfen: 71
100 Amateur-Sprachverarbeitungsklopfen: 56
100 Amateur-Sprachverarbeitungsklopfen: 24