Traitement du langage 100 coups 2015 ["Chapitre 5: Analyse des dépendances"](http: //www.cl.ecei. Il s'agit d'un enregistrement du 47e "Minning of Functional verb syntax" de tohoku.ac.jp/nlp100/#ch5). En plus du coup précédent, la cible d'extraction devient des conditions plus compliquées. Il faut un peu de temps pour comprendre l'énoncé du problème, et bien sûr, il faut du temps pour le résoudre.
Lien | Remarques |
---|---|
047.Exploration de la syntaxe des verbes fonctionnels.ipynb | Lien GitHub du programme de réponse |
100 coups de traitement du langage amateur:47 | Copiez et collez la source de nombreuses pièces source |
Officiel de CaboCha | Page CaboCha à regarder en premier |
J'ai installé CRF ++ et CaboCha il y a trop longtemps et j'ai oublié comment les installer. Puisqu'il s'agit d'un package qui n'a pas du tout été mis à jour, nous n'avons pas reconstruit l'environnement. Je me souviens seulement d'avoir été frustré lorsque j'ai décidé d'utiliser CaboCha sous Windows. Je pense que je ne pourrais pas l'utiliser sur Windows 64 bits (j'ai une mémoire vague et peut-être qu'il y a un problème avec ma capacité technique).
type | version | Contenu |
---|---|---|
OS | Ubuntu18.04.01 LTS | Il fonctionne virtuellement |
pyenv | 1.2.16 | J'utilise pyenv car j'utilise parfois plusieurs environnements Python |
Python | 3.8.1 | python3 sur pyenv.8.J'utilise 1 Les packages sont gérés à l'aide de venv |
Mecab | 0.996-5 | apt-Installer avec get |
CRF++ | 0.58 | C'est trop vieux et j'ai oublié comment l'installer(Peut-êtremake install ) |
CaboCha | 0.69 | C'est trop vieux et j'ai oublié comment l'installer(Peut-êtremake install ) |
Appliquer l'analyseur de dépendances CaboCha à "Je suis un chat" et expérimenter le fonctionnement de l'arbre de dépendances et l'analyse syntaxique.
Classe, Analyse des dépendances, CaboCha, Clause, Dépendance, Cas, Syntaxe des verbes fonctionnels, Chemin des dépendances, [Graphviz](http: / /www.graphviz.org/)
Utilisation de CaboCha pour le texte (neko.txt) du roman de Natsume Soseki "Je suis un chat" Analysez la dépendance 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.
Je voudrais prêter attention uniquement au cas où le verbe wo case contient un nom de connexion sa-variant. Modifiez 46 programmes pour répondre aux spécifications suivantes.
--Uniquement lorsque la phrase consistant en "nom de connexion sahen + (verbe auxiliaire)" est liée au verbe --Le prédicat est "nom de connexion sahen + est la forme de base de + verbe", et lorsqu'il y a plusieurs verbes dans une phrase, le verbe le plus à gauche est utilisé. --S'il existe plusieurs mots auxiliaires (phrases) liés au prédicat, arrangez tous les mots auxiliaires dans l'ordre du dictionnaire, séparés par des espaces. --S'il y a plusieurs clauses liées au prédicat, arrangez tous les termes séparés par des espaces (alignez-vous sur l'ordre des mots auxiliaires).
Par exemple, la sortie suivante doit être obtenue à partir de la phrase «Le maître répondra à la lettre, même si elle vient à un autre endroit».
Quand je réponds à la lettre, mon mari
Enregistrez la sortie de ce programme dans un fichier et vérifiez les éléments suivants à l'aide des commandes UNIX.
--Prédicats qui apparaissent fréquemment dans le corpus (nomenclature de connexion sahénienne + + verbe) --Prédicats et modèles de verbes qui apparaissent fréquemment dans le corpus
Selon "Verbe fonctionnel / verbe composé", les verbes fonctionnels sont les suivants. En d'autres termes, il n'a de sens que s'il est attaché à une nomenclature comme «faire» et «manger».
Les verbes fonctionnels sont des verbes qui perdent leur sens originel et sont associés à la nomenclature des actions pour représenter le sens du verbe.
import re
#Délimiteur
separator = re.compile('\t|,')
#Dépendance
dependancy = re.compile(r'''(?:\*\s\d+\s) #Non soumis à la capture
(-?\d+) #Nombres(Contact)
''', re.VERBOSE)
class Morph:
def __init__(self, line):
#Diviser par tabulation et virgule
cols = separator.split(line)
self.surface = cols[0] #Type de surface(surface)
self.base = cols[7] #Forme basique(base)
self.pos = cols[1] #Partie(pos)
self.pos1 = cols[2] #Sous-classification des paroles des parties 1(pos1)
class Chunk:
def __init__(self, morphs, dst):
self.morphs = morphs
self.srcs = [] #Liste des numéros d'index des clauses d'origine
self.dst = dst #Numéro d'index de la clause de contact
self.phrase = ''
self.verb = ''
self.joshi = ''
self.sahen = '' #Sa étrange+À+Que ce soit ou non une cible de modèle de verbe
for i, morph in enumerate(morphs):
if morph.pos != 'symbole':
self.phrase += morph.surface #Pour les non-symboles
self.joshi = '' #Vide pour les non-symboles pour obtenir la dernière ligne de verbes à l'exclusion des symboles
if morph.pos == 'verbe' and self.verb == '':
self.verb = morph.base
if morphs[-1].pos == 'Particule':
self.joshi = morphs[-1].base
try:
if morph.pos1 == 'Changer de connexion' and \
morphs[i+1].surface == 'À':
self.sahen = morph.surface + morphs[i+1].surface
except IndexError:
pass
#Remplacez l'origine et ajoutez la liste Chunk à la liste d'instructions
def append_sentence(chunks, sentences):
#Remplacer l'entrepreneur
for i, chunk in enumerate(chunks):
if chunk.dst != -1:
chunks[chunk.dst].srcs.append(i)
sentences.append(chunks)
return sentences, []
morphs = []
chunks = []
sentences = []
with open('./neko.txt.cabocha') as f:
for line in f:
dependancies = dependancy.match(line)
#S'il ne s'agit pas d'EOS ou du résultat de l'analyse des dépendances
if not (line == 'EOS\n' or dependancies):
morphs.append(Morph(line))
#Lorsqu'il y a une analyse morphologique, le résultat de l'analyse EOS ou des dépendances
elif len(morphs) > 0:
chunks.append(Chunk(morphs, dst))
morphs = []
#En cas de dépendance résultat
if dependancies:
dst = int(dependancies.group(1))
#Lorsqu'il y a un résultat de dépendance dans EOS
if line == 'EOS\n' and len(chunks) > 0:
sentences, chunks = append_sentence(chunks, sentences)
def output_file(out_file, sahen, sentence, chunk):
#Créer une liste de commis
sources = [[sentence[source].joshi, sentence[source].phrase] \
for source in chunk.srcs if sentence[source].joshi != '']
if len(sources) > 0:
sources.sort()
joshi = ' '.join([row[0] for row in sources])
phrase = ' '.join([row[1] for row in sources])
out_file.write(('{}\t{}\t{}\n'.format(sahen, joshi, phrase)))
with open('./047.result_python.txt', 'w') as out_file:
for sentence in sentences:
for chunk in sentence:
if chunk.sahen != '' and \
chunk.dst != -1 and \
sentence[chunk.dst].verb != '':
output_file(out_file, chunk.sahen+sentence[chunk.dst].verb,
sentence, sentence[chunk.dst])
#Trier par prédicat, déduplication et trier par numéro
cut --fields=1 047.result_python.txt | sort | uniq --count \
| sort --numeric-sort --reverse > 047.result_unix1.txt
#Trier par prédicats et mots auxiliaires, supprimer les doublons et trier par nombre d'observations
cut --fields=1,2 047.result_python.txt | sort | uniq --count \
| sort --numeric-sort --reverse > 047.result_unix2.txt
Comme d'habitude, modifiez la classe Chunk de la ligne de vie. Si la valeur de la sous-classification du mot partiel «pos1» est «connexion sahen» et que l'entrée suivante est «o», alors la variable d'instance «sahen» est saisie avec une chaîne de caractères concaténée (exemple: réponse +).
python
class Chunk:
def __init__(self, morphs, dst):
self.morphs = morphs
self.srcs = [] #Liste des numéros d'index des clauses d'origine
self.dst = dst #Numéro d'index de la clause de contact
self.phrase = ''
self.verb = ''
self.joshi = ''
self.sahen = '' #Sa étrange+À+Que ce soit ou non une cible de modèle de verbe
for i, morph in enumerate(morphs):
if morph.pos != 'symbole':
self.phrase += morph.surface #Pour les non-symboles
self.joshi = '' #Vide pour les non-symboles pour obtenir la dernière ligne de verbes à l'exclusion des symboles
if morph.pos == 'verbe' and self.verb == '':
self.verb = morph.base
if morphs[-1].pos == 'Particule':
self.joshi = morphs[-1].base
try:
if morph.pos1 == 'Changer de connexion' and \
morphs[i+1].surface == 'À':
self.sahen = morph.surface + morphs[i+1].surface
except IndexError:
pass
La branche conditionnelle de la section de sortie est modifiée.
python
with open('./047.result_python.txt', 'w') as out_file:
for sentence in sentences:
for chunk in sentence:
if chunk.sahen != '' and \
chunk.dst != -1 and \
sentence[chunk.dst].verb != '':
output_file(out_file, chunk.sahen+sentence[chunk.dst].verb,
sentence, sentence[chunk.dst])
Lorsque vous exécutez le script Python, le résultat suivant est généré.
text:047.result_python.txt(Seulement les 10 premiers)
Décidez de prendre une décision
Donner une réponse, donner une réponse
Fais une sieste Fais une sieste
Il fait une sieste
Poursuivre et chasser la persécution
Vivre une vie de famille
Parler parler parler
Pour écrire une lettre à Totogisu
Parfois parler pour parler
Faire un croquis
Exécutez une commande UNIX et affichez "Prédicats qui apparaissent fréquemment dans le corpus (nom de connexion Sahen + + verbe)"
text:047.result_unix1.txt(Seulement les 10 premiers)
29 réponse
21 Dites bonjour
16 parler
15 imiter
13 querelle
9 Exercice
9 Poser une question
6 Soyez prudent
6 Faites une sieste
6 Poser des questions
Exécuter des commandes UNIX et générer des "prédicats et modèles complémentaires qui apparaissent fréquemment dans le corpus"
text:047.result_unix2.txt(Seulement les 10 premiers)
14 Lorsque vous répondez
9 Exercice
9 Faites l'imitation
8 Qu'est-ce qu'une réponse?
7 Se battre
6 Pour parler
6 Quand tu dis bonjour
5 pour parler
5 Pour dire bonjour
4 Poser une question
Recommended Posts