[PYTHON] 100 coups de traitement du langage amateur: 41

C'est un record de défi de 100 langues de traitement knock 2015. L'environnement est Ubuntu 16.04 LTS + Python 3.5.2 : : Anaconda 4.1.1 (64 bits). Cliquez ici pour une liste des coups passés (http://qiita.com/segavvy/items/fb50ba8097d59475f760).

Chapitre 5: Analyse des dépendances

Utilisez CaboCha pour effectuer une analyse de dépendance sur le texte (neko.txt) du roman de Natsume Soseki "Je suis un chat" et enregistrez le résultat dans un fichier appelé neko.txt.cabocha. Utilisez ce fichier pour implémenter un programme qui répond aux questions suivantes.

41. Lecture du résultat de l'analyse des dépendances (expression / dépendance)

En plus de> 40, implémentez la classe de clause Chunk. Cette classe contient une liste d'éléments morph (objets Morph) (morphs), une liste de numéros d'index de clause associés (dst) et une liste de numéros d'index de clause d'origine (srcs) associés comme variables membres. De plus, lisez le résultat de l'analyse de CaboCha du texte d'entrée, exprimez une phrase sous forme d'une liste d'objets Chunk et affichez la chaîne de caractères et le contact de la phrase de la huitième phrase. Pour le reste des problèmes du chapitre 5, utilisez le programme créé ici.

Le code fini:

main.py


# coding: utf-8
import CaboCha
import re

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


def parse_neko():
	'''Analyse basée sur "Je suis un chat"
"Je suis un chat"(neko.txt)Analyse dépendante et neko.txt.Enregistrer dans 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:
	'''
Classe morphologique
Forme de surface (surface), forme de base (base), paroles de partie (pos), sous-classification des paroles de partie 1 (pos1)
Avoir dans les variables membres
	'''
	def __init__(self, surface, base, pos, pos1):
		'''Initialisation'''
		self.surface = surface
		self.base = base
		self.pos = pos
		self.pos1 = pos1

	def __str__(self):
		'''Représentation sous forme de chaîne de l'objet'''
		return 'surface[{}]\tbase[{}]\tpos[{}]\tpos1[{}]'\
			.format(self.surface, self.base, self.pos, self.pos1)


class Chunk:
	'''
Classe de phrase
Liste des éléments morph (objets Morph) (morphs), numéro d'index de la clause de destination (dst),
Il contient une liste (srcs) des numéros d'index de la clause d'origine en tant que variable membre.
	'''

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

	def __str__(self):
		'''Représentation sous forme de chaîne de l'objet'''
		surface = ''
		for morph in self.morphs:
			surface += morph.surface
		return '{}\tsrcs{}\tdst[{}]'.format(surface, self.srcs, self.dst)


def neco_lines():
	'''Générateur de résultats d'analyse de dépendance pour "Je suis un chat"
Lisez les résultats de l'analyse des dépendances de "Je suis un chat" dans l'ordre,
Renvoie une liste de classes Chunk phrase par phrase

Valeur de retour:
Liste des classes Chunk 1 phrase
	'''
	with open(fname_parsed) as file_parsed:

		chunks = dict()		#Store Chunk avec idx comme clé
		idx = -1

		for line in file_parsed:

			#Jugement de la fin d'une phrase
			if line == 'EOS\n':

				#Renvoie une liste de morceaux
				if len(chunks) > 0:

					#Trier les morceaux par clé et récupérer uniquement la valeur
					sorted_tuple = sorted(chunks.items(), key=lambda x: x[0])
					yield list(zip(*sorted_tuple))[1]
					chunks.clear()

				else:
					yield []

			#Le début est*Puisque la ligne de est le résultat de l'analyse des dépendances, créez Chunk
			elif line[0] == '*':

				#Obtenir le numéro d'index du bloc et le numéro d'index du contact
				cols = line.split(' ')
				idx = int(cols[1])
				dst = int(re.search(r'(.*?)D', cols[2]).group(1))

				#Générer (sinon) Chunk et définir le numéro d'index du contact
				if idx not in chunks:
					chunks[idx] = Chunk()
				chunks[idx].dst = dst

				#Générer (si non) un morceau du contact et ajouter le numéro d'index du contact
				if dst != -1:
					if dst not in chunks:
						chunks[dst] = Chunk()
					chunks[dst].srcs.append(idx)

			#Les autres lignes sont les résultats de l'analyse morphologique, alors créez Morph et ajoutez-le à Chunk.
			else:

				#La couche de surface est délimitée par des tabulations, sinon','Séparer par pause
				cols = line.split('\t')
				res_cols = cols[1].split(',')

				#Créer un morphing, ajouter à la liste
				chunks[idx].morphs.append(
					Morph(
						cols[0],		# surface
						res_cols[6],	# base
						res_cols[0],	# pos
						res_cols[1]		# pos1
					)
				)

		raise StopIteration


#Analyse des dépendances
parse_neko()

#Créer une liste une phrase à la fois
for i, chunks in enumerate(neco_lines(), 1):

	#Afficher la 8ème phrase
	if i == 8:
		for j, chunk in enumerate(chunks):
			print('[{}]{}'.format(j, chunk))
		break

Résultat de l'exécution:

Le problème est "Afficher le contact", mais la source du contact est également affichée pour confirmer l'implémentation de la classe Chunk.

Terminal


[0]Je suis srcs[]	dst[5]
[1]Ici srcs[]	dst[2]
[2]Pour la première fois srcs[1]	dst[3]
[3]Srcs humains[2]	dst[4]
[4]Choses srcs[3]	dst[5]
[5]vu. srcs[0, 4]	dst[-1]

Format des résultats d'analyse CaboCha

Le résultat de l'analyse de dépendance par CaboCha se présente sous la forme qu'une ligne commençant par «*» est insérée dans le résultat de l'analyse morphologique et le résultat de l'analyse de dépendance y est affiché.

Exemple de résultat d'analyse des dépendances


* 3 5D 1/2 0.656580

Cette ligne est séparée par des espaces et a le contenu suivant.

colonne sens
1 La première colonne est*.. Indique qu'il s'agit d'un résultat d'analyse des dépendances.
2 Numéro de phrase (entier à partir de 0)
3 Numéro de contact +D
4 Adresse principale/Position du mot de fonction et nombre illimité de colonnes d'identité
5 Score d'engagement. En général, plus la valeur est élevée, plus il est facile de s'engager.

Seules les colonnes 2 et 3 sont utilisées dans ce numéro. Veuillez vous référer au site officiel CaboCha / Yet Another Japanese Dependency Structure Analyzer pour les détails des résultats de l'analyse.

Ordre de création des objets chunk

Le problème cette fois était l'ordre dans lequel les objets Chunk étaient créés. Pour le moment, lisez neko.txt.cabocha ligne par ligne, créez l'objet Chunk correspondant quand même une seule information à stocker dans l'objet Chunk peut être obtenue, et ajoutez-y les informations si elles ont déjà été créées. J'ai essayé de l'implémenter dans le flux de. L'ordre de création des objets Chunk n'est pas l'ordre d'apparition, et comme le contenu n'est pas dans un ordre particulier car le dictionnaire est également utilisé, il est trié par numéro de clause et extrait à la fin. J'ai pensé après l'avoir fait, mais il aurait peut-être été plus efficace de créer d'abord les objets Chunk dans l'ordre du numéro de clause sans informations de dépendance, puis de définir les informations de dépendance plus tard.   C'est tout pour le 42e coup. Si vous avez des erreurs, je vous serais reconnaissant de bien vouloir les signaler.


Recommended Posts

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