[PYTHON] 100 Amateur-Sprachverarbeitungsklopfen: 41

Es ist ein Herausforderungsrekord von 100 Sprachverarbeitungsklopfen 2015. Die Umgebung ist Ubuntu 16.04 LTS + Python 3.5.2 : : Anaconda 4.1.1 (64-Bit). Klicken Sie hier, um eine Liste der vergangenen Schläge anzuzeigen (http://qiita.com/segavvy/items/fb50ba8097d59475f760).

Kapitel 5: Abhängigkeitsanalyse

Verwenden Sie CaboCha, um eine Abhängigkeitsanalyse für den Text (neko.txt) von Natsume Sosekis Roman "Ich bin eine Katze" durchzuführen und das Ergebnis in einer Datei namens neko.txt.cabocha zu speichern. Verwenden Sie diese Datei, um ein Programm zu implementieren, das die folgenden Fragen beantwortet.

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.

Der fertige Code:

main.py


# coding: utf-8
import CaboCha
import re

fname = 'neko.txt'
fname_parsed = 'neko.txt.cabocha'


def parse_neko():
	'''Analyse basierend auf "Ich bin eine Katze"
"Ich bin eine Katze"(neko.txt)Abhängige Analyse und Neko.txt.Speichern Sie zu Cabocha
	'''
	with open(fname) as data_file, \
			open(fname_parsed, mode='w') as out_file:

		cabocha = CaboCha.Parser()
		for line in data_file:
			out_file.write(
				cabocha.parse(line).toString(CaboCha.FORMAT_LATTICE)
			)


class Morph:
	'''
Morphologische Klasse
Oberflächenform (Oberfläche), Grundform (Basis), Teil des Wortes (pos), Teil des Wortes Unterklasse 1 (pos1)
Haben in Mitgliedsvariablen
	'''
	def __init__(self, surface, base, pos, pos1):
		'''Initialisieren'''
		self.surface = surface
		self.base = base
		self.pos = pos
		self.pos1 = pos1

	def __str__(self):
		'''Zeichenfolgendarstellung des Objekts'''
		return 'surface[{}]\tbase[{}]\tpos[{}]\tpos1[{}]'\
			.format(self.surface, self.base, self.pos, self.pos1)


class Chunk:
	'''
Phrasenklasse
Liste der Morph-Elemente (Morph-Objekte) (Morphs), Zielklausel-Indexnummer (dst),
Es enthält eine Liste (srcs) der Indexnummern der ursprünglichen Klausel als Mitgliedsvariable.
	'''

	def __init__(self):
		'''Initialisieren'''
		self.morphs = []
		self.srcs = []
		self.dst = -1

	def __str__(self):
		'''Zeichenfolgendarstellung des Objekts'''
		surface = ''
		for morph in self.morphs:
			surface += morph.surface
		return '{}\tsrcs{}\tdst[{}]'.format(surface, self.srcs, self.dst)


def neco_lines():
	'''Generator der Ergebnisse der Abhängigkeitsanalyse für "Ich bin eine Katze"
Lesen Sie die Ergebnisse der Abhängigkeitsanalyse von "Ich bin eine Katze" nacheinander.
Gibt Satz für Satz eine Liste der Chunk-Klassen zurück

Rückgabewert:
Liste der 1-Satz-Chunk-Klassen
	'''
	with open(fname_parsed) as file_parsed:

		chunks = dict()		#Speichern Sie Chunk mit idx als Schlüssel
		idx = -1

		for line in file_parsed:

			#Beurteilung des Endes eines Satzes
			if line == 'EOS\n':

				#Gibt eine Liste von Chunks zurück
				if len(chunks) > 0:

					#Sortieren Sie Chunks nach Schlüssel und rufen Sie nur den Wert ab
					sorted_tuple = sorted(chunks.items(), key=lambda x: x[0])
					yield list(zip(*sorted_tuple))[1]
					chunks.clear()

				else:
					yield []

			#Der Anfang ist*Da die Zeile von das Ergebnis einer Abhängigkeitsanalyse ist, erstellen Sie Chunk
			elif line[0] == '*':

				#Holen Sie sich die Chunk-Indexnummer und die Kontaktindexnummer
				cols = line.split(' ')
				idx = int(cols[1])
				dst = int(re.search(r'(.*?)D', cols[2]).group(1))

				#Generieren Sie (falls nicht) Chunk und legen Sie die Indexnummer des Kontakts fest
				if idx not in chunks:
					chunks[idx] = Chunk()
				chunks[idx].dst = dst

				#Generieren Sie (falls nicht) einen Teil des Kontakts und fügen Sie die Indexnummer des Kontakts hinzu
				if dst != -1:
					if dst not in chunks:
						chunks[dst] = Chunk()
					chunks[dst].srcs.append(idx)

			#Die anderen Zeilen sind die Ergebnisse der morphologischen Analyse. Erstellen Sie also Morph und fügen Sie es Chunk hinzu.
			else:

				#Andernfalls wird die Oberflächenebene durch Tabulatoren getrennt','Durch Pause trennen
				cols = line.split('\t')
				res_cols = cols[1].split(',')

				#Morph erstellen, zur Liste hinzufügen
				chunks[idx].morphs.append(
					Morph(
						cols[0],		# surface
						res_cols[6],	# base
						res_cols[0],	# pos
						res_cols[1]		# pos1
					)
				)

		raise StopIteration


#Abhängigkeitsanalyse
parse_neko()

#Erstellen Sie eine Liste Satz für Satz
for i, chunks in enumerate(neco_lines(), 1):

	#Zeigen Sie den 8. Satz an
	if i == 8:
		for j, chunk in enumerate(chunks):
			print('[{}]{}'.format(j, chunk))
		break

Ausführungsergebnis:

Das Problem ist "Kontakt anzeigen", aber die Kontaktquelle wird auch angezeigt, um die Implementierung der Chunk-Klasse zu bestätigen.

Terminal


[0]Ich bin srcs[]	dst[5]
[1]Hier srcs[]	dst[2]
[2]Zum ersten Mal srcs[1]	dst[3]
[3]Menschliche srcs[2]	dst[4]
[4]Dinge srcs[3]	dst[5]
[5]sah. srcs[0, 4]	dst[-1]

Ergebnisformat der CaboCha-Analyse

Das Ergebnis der Abhängigkeitsanalyse von CaboCha hat die Form, dass eine Zeile, die mit "*" beginnt, in das Ergebnis der morphologischen Analyse eingefügt wird und das Ergebnis der Abhängigkeitsanalyse dort ausgegeben wird.

Beispiel für das Ergebnis der Abhängigkeitsanalyse


* 3 5D 1/2 0.656580

Diese Zeile ist durch Leerzeichen getrennt und enthält den folgenden Inhalt.

Säule Bedeutung
1 Die erste Spalte ist*.. Zeigt an, dass es sich um ein Ergebnis der Abhängigkeitsanalyse handelt.
2 Phrasennummer (Ganzzahl ab 0)
3 Kontaktnummer +D
4 Hauptadresse/Funktionswortposition und beliebig viele Identitätsspalten
5 Verlobungspunktzahl. Im Allgemeinen ist es umso einfacher, sich zu engagieren, je größer der Wert ist.

In dieser Ausgabe werden nur die Spalten 2 und 3 verwendet. Einzelheiten zu den Analyseergebnissen finden Sie auf der offiziellen Website CaboCha / Noch ein weiterer japanischer Abhängigkeitsstrukturanalysator.

Erstellungsreihenfolge für Chunk-Objekte

Das Problem war diesmal die Reihenfolge, in der die Chunk-Objekte erstellt wurden. Lesen Sie vorerst zeilenweise neko.txt.cabocha, erstellen Sie das entsprechende Chunk-Objekt, wenn Sie auch nur eine Information im Chunk-Objekt speichern können, und fügen Sie die Informationen dort hinzu, wenn sie bereits erstellt wurden. Ich habe versucht, es im Fluss von zu implementieren. Die Reihenfolge beim Erstellen von Chunk-Objekten ist nicht die Reihenfolge des Erscheinungsbilds. Da der Inhalt in keiner bestimmten Reihenfolge aufgeführt ist, da das Wörterbuch ebenfalls verwendet wird, wird er nach Klauselnummer sortiert und am Ende extrahiert. Ich dachte nach dem Erstellen, aber es war möglicherweise effizienter, zuerst Chunk-Objekte in der Reihenfolge der Klauselnummer ohne Abhängigkeitsinformationen zu erstellen und die Abhängigkeitsinformationen später festzulegen.   Das ist alles für den 42. Schlag. Wenn Sie Fehler haben, würde ich mich freuen, wenn Sie darauf hinweisen könnten.


Recommended Posts

100 Amateur-Sprachverarbeitungsklopfen: 41
100 Amateur-Sprachverarbeitungsklopfen: 71
100 Amateur-Sprachverarbeitungsklopfen: 56
100 Amateur-Sprachverarbeitungsklopfen: 24
100 Amateur-Sprachverarbeitungsklopfen: 50
100 Amateur-Sprachverarbeitungsklopfen: 59
100 Amateur-Sprachverarbeitungsklopfen: 70
100 Amateur-Sprachverarbeitungsklopfen: 62
100 Amateur-Sprachverarbeitungsklopfen: 60
100 Amateur-Sprachverarbeitungsklopfen: 92
100 Amateur-Sprachverarbeitungsklopfen: 30
100 Amateur-Sprachverarbeitungsklopfen: 06
100 Amateur-Sprachverarbeitungsklopfen: 84
100 Amateur-Sprachverarbeitungsklopfen: 81
100 Amateur-Sprachverarbeitungsklopfen: 33
100 Amateur-Sprachverarbeitungsklopfen: 46
100 Amateur-Sprachverarbeitungsklopfen: 88
100 Amateur-Sprachverarbeitungsklopfen: 89
100 Amateur-Sprachverarbeitungsklopfen: 40
100 Amateur-Sprachverarbeitungsklopfen: 45
100 Amateur-Sprachverarbeitungsklopfen: 43
100 Amateur-Sprachverarbeitungsklopfen: 55
100 Amateur-Sprachverarbeitungsklopfen: 22
100 Amateur-Sprachverarbeitungsklopfen: 61
100 Amateur-Sprachverarbeitungsklopfen: 94
100 Amateur-Sprachverarbeitungsklopfen: 54
100 Amateur-Sprachverarbeitungsklopfen: 04
100 Amateur-Sprachverarbeitungsklopfen: 63
100 Amateur-Sprachverarbeitungsklopfen: 78
100 Amateur-Sprachverarbeitungsklopfen: 12
100 Amateur-Sprachverarbeitungsklopfen: 14
100 Amateur-Sprachverarbeitungsklopfen: 08
100 Amateur-Sprachverarbeitungsklopfen: 42
100 Amateur-Sprachverarbeitungsklopfen: 19
100 Amateur-Sprachverarbeitungsklopfen: 73
100 Amateur-Sprachverarbeitungsklopfen: 75
100 Amateur-Sprachverarbeitungsklopfen: 98
100 Amateur-Sprachverarbeitungsklopfen: 83
100 Amateur-Sprachverarbeitungsklopfen: 95
100 Amateur-Sprachverarbeitungsklopfen: 32
100 Amateur-Sprachverarbeitungsklopfen: 96
100 Amateur-Sprachverarbeitungsklopfen: 87
100 Amateur-Sprachverarbeitungsklopfen: 72
100 Amateur-Sprachverarbeitungsklopfen: 79
100 Amateur-Sprachverarbeitungsklopfen: 23
100 Amateur-Sprachverarbeitungsklopfen: 05
100 Amateur-Sprachverarbeitungsklopfen: 00
100 Amateur-Sprachverarbeitungsklopfen: 02
100 Amateur-Sprachverarbeitungsklopfen: 37
100 Amateur-Sprachverarbeitungsklopfen: 21
100 Amateur-Sprachverarbeitungsklopfen: 68
100 Amateur-Sprachverarbeitungsklopfen: 11
100 Amateur-Sprachverarbeitungsklopfen: 90
100 Amateur-Sprachverarbeitungsklopfen: 74
100 Amateur-Sprachverarbeitungsklopfen: 66
100 Amateur-Sprachverarbeitungsklopfen: 28
100 Amateur-Sprachverarbeitungsklopfen: 64
100 Amateur-Sprachverarbeitungsklopfen: 34
100 Amateur-Sprachverarbeitungsklopfen: 36
100 Amateur-Sprachverarbeitungsklopfen: 77
100 Amateur-Sprachverarbeitungsklopfen: 01