[Kapitel 4] Einführung in Python mit 100 Klopfen Sprachverarbeitung

Dieser Artikel ist eine Fortsetzung meines Buches Einführung in Python mit 100 Knock. Ich werde [100 Schläge Kapitel 4] erklären (https://nlp100.github.io/ja/ch04.html).

Installieren Sie zuerst den morphologischen Analysator MeCab, laden Sie neko.txt herunter, analysieren Sie das morphologische Element und überprüfen Sie den Inhalt.

$ mecab < neko.txt > neko.txt.mecab

Es ist "Ich bin eine Katze" von Aozora Bunko.

Das System des Standardwörterbuchs von MeCab ähnelt der Schulgrammatik, aber die Adjektivverben sind Nomenklatur + Hilfsverben und die sa-variablen Verben sind Nomenklatur + Verben. Das Ausgabeformat ist wahrscheinlich wie folgt:

Oberflächentyp\t Teil Texte,Teiltexte Unterklassifizierung 1,Teil Teil Unterklassifizierung 2,Teiltexte Unterklassifizierung 3,Nutzungsart,Nutzungsart,Prototyp,lesen,Ausspracheform

Außerdem werden die Sätze durch "EOS" getrennt. Übrigens nehmen viele morphologische Analysegeräte Zeichen voller Breite an, daher ist es besser, Zeichen halber Breite bei der Analyse von Webtexten zu ersetzen.

itertools Es ist eine große Sache, also machen wir uns mit dem Modul itertools vertraut. Es gibt Methoden zum Erstellen eines praktischen Iterators.

islice() Es erschien auch in Kapitel 2. Sie können den Iterator mit "islice (iterable, start, stop, step)" in Scheiben schneiden. Wenn "Schritt" weggelassen wird, ist es 1, und wenn "Start" weggelassen wird, ist es "Start = 0". stop = None bedeutet bis zum Ende. Es ist sehr praktisch, also lass es uns benutzen.

groupby() Sie können so etwas wie die "Uniq" von Unix-Befehlen ausführen.

from itertools import groupby
a = [1,1,1,0,0,1]
for k, g in groupby(a):
    print(k, list(g))
1 [1, 1, 1]
0 [0, 0]
1 [1]

Wenn Sie als erstes Argument "iterable" übergeben, wird ein Paar aus dem Wert dieses Elements und dem Iterator erstellt, der diese Gruppe zurückgibt. Wie bei "sort" können Sie auch "key" als zweites Argument angeben. Ich benutze oft operator.itemgetter (was Sie wissen, wenn Sie Sort HOW TO in Kapitel 2 lesen). Wahrscheinlich). Wir verwenden auch Lambda-Ausdrücke, die Boolesche Werte zurückgeben. ..

from operator import itemgetter
a = [(3, 0), (4, 0), (2, 1)]
for k, g in groupby(a, key=itemgetter(1)):
    print(k, list(g))
0 [(3, 0), (4, 0)]
1 [(2, 1)]

chain.from_iterable() Sie können ein quadratisches Array in einer Dimension "reduzieren".

from itertools import chain
a = [[1,2], [3,4], [5,6]
print(list(chain.from_iterable(a))
[1, 2, 3, 4, 5, 6]

zip_longest() Die integrierte Funktion zip () passt auf kurze Iterables, aber verwenden Sie sie, wenn Sie möchten, dass sie auf lange Iterables passt. Wenn Sie es normal verwenden, wird es mit "Keine" gefüllt, aber Sie können den Wert angeben, der zum Füllen mit dem zweiten Argument "Füllwert" verwendet werden soll.

product() Berechnen Sie das direkte Produkt. Außerdem sind "Permutationen ()" und "Kombinationen ()" schwer selbst zu implementieren, daher denke ich, dass es sich lohnt, dies zu wissen.

Dies sind nur einige der "itertools". Wenn Sie also interessiert sind, lesen Sie die Dokumentation (https://docs.python.org/ja/3/library/itertools.html).

30. Lesen der Ergebnisse der morphologischen Analyse

Implementieren Sie ein Programm, das die Ergebnisse der morphologischen Analyse liest (neko.txt.mecab). Jedes morphologische Element wird jedoch in einem Zuordnungstyp mit dem Schlüssel der Oberflächenform (Oberfläche), der Grundform (Basis), einem Teil des Wortes (pos) und einem Teil der Wortunterklassifizierung 1 (pos1) gespeichert, und ein Satz wird als Liste morphologischer Elemente (Zuordnungstyp) ausgedrückt. Machen wir das. Verwenden Sie für die restlichen Probleme in Kapitel 4 das hier erstellte Programm.

Wenn Sie eine objektorientierte Sprachperson sind, möchten Sie eine Klasse verwenden, aber das ist bis zum nächsten Kapitel. Sie können Pandas auch wie in Kapitel 2 verwenden, aber ich werde es stoppen, da es von der Absicht der Problemstellung abzuweichen scheint.

Unten finden Sie ein Beispiel für die Antwort.

q30.py


import argparse
from itertools import groupby, islice
from pprint import pprint
import sys


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('num', type=int)
    args = parser.parse_args()
    for sent_lis in islice(read_mecab(sys.stdin), args.num-1, args.num):
        pprint(sent_lis)

            
def read_mecab(fi):
    for is_eos, sentence in groupby(fi, lambda line: line.startswith('EOS')):
        if not is_eos:
            yield list(map(line2dic, sentence))


def line2dic(line):
    surface, info = line.rstrip().split('\t')
    col = info.split(',')
    dic = {'surface': surface,
          'pos': col[0],
          'pos1': col[1],
          'base': col[6]}
    return dic


if __name__ == '__main__':
    main()

$ python q30.py 2 < neko.txt.mecab

[{'base': '\ u3000', 'pos': 'symbol', 'pos1': 'blank', 'surface': '\ u3000'}, {'base': 'I'm', 'pos': 'noun', 'pos1': 'synonym', 'surface': 'I'}, {'base': 'ist', 'pos': 'auxiliary', 'pos1': 'teilnehmer', 'oberfläche': 'ist'}, {'base': 'cat', 'pos': 'noun', 'pos1': 'general', 'surface': 'cat'}, {'base': 'da', 'pos': 'Hilfsverb', 'pos1': '', 'Oberfläche': 'in'}, {'base': 'Are', 'pos': 'Auxiliary verb', 'pos1': '', 'surface': 'Are'}, {'Base':'. ',' pos ':' Symbol ',' pos1 ':' Phrase ',' Oberfläche ':'. '}]

main () schränkt die Ausgabe ein. Wenn Sie "pprint.pprint ()" anstelle von "print ()" verwenden, wird (hübscher Druck) mit angepassten Zeilenumbrüchen ausgegeben.

Diese Art von Format kann intelligent geschrieben werden, indem eine Funktion übergeben wird, die zurückgibt, ob eine Zeile "EOS" ist, an "key" von "groupby ()". Sie haben in Kapitel 2 "nachgegeben".

Das Problem ist list (map ()). map (func, iterable) wendet die Funktion func auf jedes Element von iterable an und gibt einen Iterator zurück. Das Ergebnis ist das gleiche wie "[line2sic (x) für x im Satz]", aber es scheint, dass Python seine eigene Funktion in der "for" -Anweisung nur langsam aufruft, daher habe ich diese Notation übernommen ([line2sic (x) für x im Satz] "). Referenz).

31. Verb

Extrahieren Sie alle Oberflächenformen des Verbs.

Unten finden Sie ein Beispiel für die Antwort.

q31.py


from itertools import islice
import sys

from q30 import read_mecab


def main():
    for sent_lis in islice(read_mecab(sys.stdin), 5):
        for word in filter(lambda x: x['pos'] == 'Verb', sent_lis):
            print(word['surface'])

                
if __name__ == '__main__':
    main()

$ python q31.py < neko.txt.mecab

Geboren Tsuka Shi Weinen Shi Ist

Ich versuche die ersten N Sätze zu holen. argpase wird auch weggelassen, weil es nervt.

Ich hatte nichts anderes zu sagen, also habe ich gewaltsam filter () verwendet. Dies entspricht "(x für x in iterierbar, wenn Bedingung (x))" und gibt nur die Elemente zurück, die der Bedingung entsprechen. Um ehrlich zu sein, reicht es aus, die if-Anweisung zu verwenden, daher gibt es nicht viele Umdrehungen (in diesem Fall denke ich, dass die Verwendung von filter () langsam ist).

32. Prototyp des Verbs

Extrahieren Sie alle Originalformen des Verbs.

Weggelassen, weil es fast das gleiche ist wie 31.

33. "B von A"

Extrahieren Sie die Nomenklatur, in der zwei Nomenklaturen durch "Nein" verbunden sind.

Es gibt nichts zu sagen, weil es durch Drücken getan werden kann. Unten finden Sie ein Beispiel für die Antwort.

q33.py


from itertools import islice
import sys


from q30 import read_mecab


def main():
    for sent_lis in islice(read_mecab(sys.stdin), 20):
        for i in range(len(sent_lis) - 2):
            if (sent_lis[i+1]['base'] == 'von' and sent_lis[i]['pos'] == 'Substantiv'
                and sent_lis[i+2]['pos'] == 'Substantiv'):
                print(''.join(x['surface'] for x in sent_lis[i: i+3]))

                
if __name__ == '__main__':
    main()

$ python q33.py < neko.txt.mecab

Seine Handfläche Auf der Handfläche Studentengesicht Sollte Gesicht Mitten im Gesicht In dem Loch Kalligraphiepalme Die Rückseite der Handfläche

Ich habe bereits erwähnt, dass die Zeilenfortsetzung in Python "" ist, aber Sie können Zeilen in Klammern frei unterbrechen. Der bedingte Ausdruck der if-Anweisung ist nutzlos in () eingeschlossen, um das zu sagen.

34. Verkettung der Nomenklatur

Extrahieren Sie die Verkettung der Nomenklatur (Substantive, die nacheinander erscheinen) mit der längsten Übereinstimmung.

Mach einfach group by () mit dem Teiltext. Unten finden Sie ein Beispiel für die Antwort.

q34.py


import sys
from itertools import groupby, islice

from q30 import read_mecab


def main():
    for sent_lis in islice(read_mecab(sys.stdin), 20):
        for key, group in groupby(sent_lis, lambda word: word['pos']):
            if key == 'Substantiv':
                words = [word['surface'] for word in group]
                if len(words) > 1:
                    print(''.join(words))

                
if __name__ == '__main__':
    main()

$ python q34.py < neko.txt.mecab

In Menschen Das Schlechteste Rechtzeitig Ein Haar Dann Katze einmal Puupuu und Rauch

35. Häufigkeit des Auftretens von Wörtern

Finden Sie die Wörter, die im Satz erscheinen, und ihre Häufigkeit des Auftretens, und ordnen Sie sie in absteigender Reihenfolge der Häufigkeit des Auftretens an.

Verwenden Sie einfach collection.Counter. Unten finden Sie ein Beispiel für die Antwort.

q35.py


import sys
from collections import Counter
from pprint import pprint

from q30 import read_mecab


def get_freq():
    word_freq = Counter(word['surface'] for sent_lis in read_mecab(sys.stdin) 
                            for word in sent_lis)
    return word_freq.most_common(10)


if __name__ == '__main__':
    pprint(get_freq())

$ python q35.py < neko.txt.mecab

[('Nein', 9194), ('。', 7486), ("Te", 6868), ('、', 6772), ("Ha", 6420), ('To', 6243), ('To', 6071), ('Und', 5508), ("Ga", 5337), ('Ta', 3988)]

matplotlib Jetzt, wo ich ein Diagramm für die nächste Frage zeichne, ist es endlich Zeit für diesen Kerl. Lassen Sie uns pip install machen. Ich möchte externe Module im Artikel "Einführung in Python" nicht sehr viel erklären, und wenn ich das ernsthaft erkläre, kann ich ein Buch schreiben. Lesen Sie zuerst diesen Qiita-Artikel, um die hierarchische Struktur von matplotlib zu verstehen. Es ist sehr chaotisch, nicht wahr? Es ist "Pyplot", das den Bereich entsprechend einstellt. Dieses Mal werde ich keine feinen Anpassungen am Erscheinungsbild vornehmen, also werde ich es auf diese Weise tun. Hier ist ein einfaches Beispiel.

import matplotlib.pyplot as plt
#Geben Sie den Diagrammtyp und die Daten an
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
#Irgendwie eingestellt
plt.title('example')
plt.ylabel('some numbers')
#Zeichnung
plt.show()

output_28_0.png

Die Bedeutung der import-Anweisung lautet "Importieren Sie das Submodul" pyplot "des Moduls" matplotlib "mit dem Namen" plt "".

Entscheiden Sie sich zunächst für den Diagrammtyp. Für Liniendiagramme "plt.plot ()", für horizontale Balkendiagramme "plt.barh ()", für Säulendiagramme "plt.bar ()" usw. (Iterable ist "numpy" innerhalb des Pyplots. Es kann besser sein, ein "numpy" -Array zu übergeben, da es selbst in ein Array konvertiert wird.

Als nächstes stellen Sie das Erscheinungsbild von etwas ein. plt.yticks () kann die y-Koordinate und die dazugehörigen Zeichen festlegen. Mit plt.xlim () können Sie die Maximal- und Minimalwerte für die x-Achse festlegen. plt.yscale (" log ") macht die y-Achse zu einer logarithmischen Skala.

Zum Schluss zeichnen. Ich benutze Jupyter, also benutze ich plt.show (). Diejenigen, die das Skript ausführen, sollten "plt.savefig (Dateiname)" verwenden, um die Datei auszugeben.

Um ehrlich zu sein, ist diese Methode MATLAB-ähnlich und nicht pythonisch, aber einfach.

Japanisch mit matplotlib anzeigen

Da die Standardschrift kein Japanisch unterstützt, wird sie zu Tofu. Um Japanisch in der Grafik anzuzeigen, können Sie daher eine Schriftart festlegen, die Japanisch unterstützt. Abhängig von Ihrer Umgebung finden Sie die japanische Schrift möglicherweise nicht oder müssen sie installieren, da sie überhaupt nicht enthalten ist. Es ist schwer. Wir werden es Ihnen unter japanize-matplotlib leichter machen.

36. Top 10 der häufigsten Wörter

Zeigen Sie die 10 am häufigsten vorkommenden Wörter und ihre Häufigkeit des Auftretens in einem Diagramm an (z. B. einem Balkendiagramm).

from collections import Counter

from q30 import read_mecab
import matplotlib.pyplot as plt
import japanize_matplotlib

word_freq = Counter(word['base'] for sent_lis in read_mecab(open('neko.txt.mecab')) 
                            for word in sent_lis)
word, count  = zip(*word_freq.most_common(10))
len_word = range(len(word))

plt.barh(len_word, count, align='center')
plt.yticks(len_word, word)
plt.xlabel('frequency')
plt.ylabel('word')
plt.title('36.Top 10 der häufigsten Wörter')
plt.show()

output_31_0.png

Was ist das "" im "zip ()"? Aber was ich hier machen möchte, ist Translokation. Das heißt, Daten wie "[[a, b], [c, d]]" werden in "[[a, c], [b, d]]" umgewandelt. Daher ist der einfachste Weg, es zu übertragen, das Schreiben von "zip ( seq)". Dies entspricht zip (seq [0], seq [1], ...) (Argumentliste entpacken # Argumentationslisten entpacken)). zip ([a, b], [c, d]) ist [(a, c), (b, d)], nicht wahr? Sie können auch die entpackte Zuweisung verwenden, um verschiedene Variablen gleichzeitig zuzuweisen.

(Dies ist das Ende der Erklärung der alternativen Lösung der ngram-Funktion in Kapitel 1)

Beachten Sie, dass die obersten Wörter in der Worthäufigkeit funktionale Wörter sind (Hilfswörter, Satzzeichen).

37. Top 10 Wörter, die häufig zusammen mit "Katze" vorkommen

Zeigen Sie 10 Wörter an, die häufig zusammen mit "cat" (hohe Häufigkeit des gemeinsamen Auftretens) und deren Häufigkeit des Auftretens in einem Diagramm (z. B. einem Balkendiagramm) vorkommen.

word_freq = Counter()
for sent_lis in read_mecab(open('neko.txt.mecab')):
    for word in sent_lis:
        if word['surface'] == 'Katze':
            word_freq.update(x['base'] for x in sent_lis if x['surface'] != 'Katze')
            break
            
words, count  = zip(*word_freq.most_common(10))
len_word = range(len(words))

plt.barh(len_word, count, align='center')
plt.yticks(len_word, words)
plt.xlabel('frequency')
plt.ylabel('word')
plt.title('37.Top 10 Wörter, die häufig zusammen mit "Katze" vorkommen')
plt.show()

output_34_0.png

Sie können das Counter-Objekt mit Counter.update (iterable) aktualisieren. Wenn Sie sich jedoch nicht auf unabhängige Wörter konzentrieren, ist das Ergebnis völlig uninteressant.

38. Histogramm

Zeichnen Sie ein Histogramm der Häufigkeit des Auftretens von Wörtern (die horizontale Achse repräsentiert die Häufigkeit des Auftretens und die vertikale Achse repräsentiert die Anzahl der Arten von Wörtern, die die Häufigkeit des Auftretens als Balkendiagramm verwenden).

word_freq = Counter(word['base'] for sent_lis in read_mecab(open('neko.txt.mecab')) 
                        for word in sent_lis)
data = Counter(count for count in word_freq.values())

x, y = data.keys(), data.values()

plt.bar(x, y)
plt.title("38.Histogramm")
plt.xlabel("frequency")
plt.ylabel("number of the words")
plt.xlim(1, 30)
plt.show()

output_34_0.png

Sie können alle Schlüssel mit "dict.keys ()" und alle Werte mit "dict.values ()" erhalten.

Wenn wir uns die Anzahl der Worttypen ansehen, können wir feststellen, dass viele Wörter selten vorkommen. Es sieht so aus, als wäre es umgekehrt proportional. Aus diesem Grund ist beim Deep Learning auch die niederfrequente Textverarbeitung wichtig.

39. Zipfs Gesetz

Zeichnen Sie beide logarithmischen Diagramme mit der Häufigkeit des Auftretens von Wörtern auf der horizontalen Achse und der Häufigkeit des Auftretens auf der vertikalen Achse.

word_freq = Counter(word['base'] for sent_lis in read_mecab(open('neko.txt.mecab')) 
                        for word in sent_lis)
_, count = zip(*word_freq.most_common())
plt.plot(range(1, len(count)+1), count)
plt.yscale("log")
plt.xscale("log")
plt.title("39.Zipfs Gesetz")
plt.xlabel("log(rank)")
plt.ylabel("log(frequency)")
plt.show()

output_37_0.png

Die Steigung beider logarithmischer Graphen beträgt etwa -1. Dies bedeutet "Frequenz" Rang ^ (-1). Es scheint mit dem 38. Ergebnis zu tun zu haben. Lassen Sie uns die Details des Zipf-Gesetzes googeln.

Zusammenfassung

Als nächstes folgt Kapitel 5

Ich werde endlich die Klasse benutzen. Ist dies die nächste und letzte Einführung in Python?

(5/16) Ich schrieb → https://qiita.com/hi-asano/items/5e18e3a5a711a752ad99

Recommended Posts

[Kapitel 5] Einführung in Python mit 100 Klopfen Sprachverarbeitung
[Kapitel 3] Einführung in Python mit 100 Klopfen Sprachverarbeitung
[Kapitel 2] Einführung in Python mit 100 Klopfen Sprachverarbeitung
[Kapitel 4] Einführung in Python mit 100 Klopfen Sprachverarbeitung
[Kapitel 6] Einführung in Scicit-Learn mit 100 Klopfen Sprachverarbeitung
100 Sprachverarbeitungsklopfen mit Python (Kapitel 1)
100 Sprachverarbeitungsklopfen mit Python (Kapitel 3)
100 Sprachverarbeitungsklopfen mit Python (Kapitel 2, Teil 2)
100 Sprachverarbeitungsklopfen mit Python (Kapitel 2, Teil 1)
100 Sprachverarbeitungsklopfen ~ Kapitel 1
Einführung in die Python-Sprache
100 Sprachverarbeitung klopft Kapitel 2 (10 ~ 19)
Erste Schritte mit Python mit 100 Klopfen bei der Sprachverarbeitung
100 Sprachverarbeitungsklopfen mit Python 2015
100 Sprachverarbeitung Knock Kapitel 1 (Python)
[Sprachverarbeitung 100 Schläge 2020] Zusammenfassung der Antwortbeispiele von Python
Einführung in die verteilte Parallelverarbeitung von Python durch Ray
Ich habe versucht, die 2020-Version von 100 Sprachverarbeitungsproblemen zu lösen [Kapitel 3: Reguläre Ausdrücke 20 bis 24]
Ich habe versucht, die 2020-Version von 100 Sprachverarbeitungsproblemen zu lösen [Kapitel 1: Vorbereitungsbewegung 00-04]
Ich habe versucht, die 2020-Version von 100 Sprachverarbeitungsproblemen zu lösen [Kapitel 1: Vorbereitungsbewegung 05-09]
[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 Sprachverarbeitungsklopfen 2020: Kapitel 4 (morphologische Analyse)
[Sprachverarbeitung 100 Schläge 2020] Kapitel 5: Abhängigkeitsanalyse
[Einführung in Python3 Tag 13] Kapitel 7 Zeichenfolgen (7.1-7.1.1.1)
[Einführung in Python3 Tag 14] Kapitel 7 Zeichenfolgen (7.1.1.1 bis 7.1.1.4)
Einführung in Protobuf-c (C-Sprache ⇔ Python)
[Sprachverarbeitung 100 Schläge 2020] Kapitel 1: Vorbereitende Bewegung
Die Bildverarbeitung mit Python 100 klopft an die Binärisierung Nr. 3
[Sprachverarbeitung 100 Schläge 2020] Kapitel 7: Wortvektor
[Einführung in Python3 Tag 15] Kapitel 7 Zeichenfolgen (7.1.2-7.1.2.2)
10 Funktionen von "Sprache mit Batterie" Python
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 Bildverarbeitung mit Python Knock # 2 Graustufen
100 Sprachverarbeitung Knock Kapitel 1 von Python
[Sprachverarbeitung 100 Schläge 2020] Kapitel 4: Morphologische Analyse
[Einführung in Python3 Tag 21] Kapitel 10 System (10.1 bis 10.5)
Sprachverarbeitung 100 Schläge-48: Extraktion des Weges von der Nase zur Wurzel
[Raspi4; Einführung in den Sound] Stabile Aufzeichnung der Toneingabe mit Python ♪
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)
100 Sprachverarbeitungsklopfen 03 ~ 05
100 Sprachverarbeitungsklopfen (2020): 40
Grundlagen der binärisierten Bildverarbeitung durch Python
100 Sprachverarbeitungsklopfen (2020): 32
Zusammenfassung von Kapitel 2 der Einführung in Entwurfsmuster, die in Java gelernt wurden
IPynb-Bewertungssystem mit TA von Introduction to Programming (Python)
Ich habe mit GiNZA v3.1 Kapitel 4 100 Sprachverarbeitungsklopfen 2020 durchgeführt
100 Sprachverarbeitungsklopfen (2020): 35
100 Sprachverarbeitungsklopfen (2020): 47
100 Sprachverarbeitungsklopfen (2020): 39
[Einführung in Python3, Tag 17] Kapitel 8 Datenziele (8.1-8.2.5)
Kapitel 4 Zusammenfassung der Einführung in Entwurfsmuster, die in Java gelernt wurden
100 Sprachverarbeitung Knock-22: Extraktion des Kategorienamens
100 Sprachverarbeitungsklopfen (2020): 26