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).
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).
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).
Extrahieren Sie alle Originalformen des Verbs.
Weggelassen, weil es fast das gleiche ist wie 31.
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.
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
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()
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.
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.
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()
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).
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()
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.
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()
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.
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()
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.
itertools
map()
, filter()
matplotlib
--Transferdict.keys()
, dict.values()
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