Traitement du langage 100 coups 2015 ["Chapitre 5: Analyse des dépendances"](http: //www.cl.ecei. Il s'agit de l'enregistrement de 45e "Extraction du motif de cas des verbes" de tohoku.ac.jp/nlp100/#ch5). Le nombre de branches conditionnelles de «si» a également augmenté, et cela devient de plus en plus compliqué. C'est un peu fastidieux de penser à l'algorithme.
Lien | Remarques |
---|---|
045.Extraction de modèles de cas verbaux.ipynb | Lien GitHub du programme de réponse |
100 coups de traitement du langage amateur:45 | 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 de verbe fonctionnel, Chemin de dépendance, [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 considérer la phrase utilisée cette fois comme un corpus et enquêter sur les cas possibles de prédicats japonais. Considérez le verbe comme un prédicat et le verbe auxiliaire de la phrase liée au verbe comme une casse, et affichez le prédicat et la casse dans un format délimité par des tabulations. Cependant, assurez-vous que la sortie répond aux spécifications suivantes.
--Dans une clause contenant un verbe, la forme de base du verbe le plus à gauche est utilisée comme prédicat. --La casse est le mot auxiliaire lié au prédicat --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.
Prenons l'exemple de la phrase (8ème phrase de neko.txt.cabocha) que "j'ai vu un être humain pour la première fois ici". Cette phrase contient deux verbes, «commencer» et «voir», et la phrase liée à «commencer» est analysée comme «ici», et la phrase liée à «voir» est analysée comme «je suis» et «chose». Devrait produire la sortie suivante.
Au début À voir
Enregistrez la sortie de ce programme dans un fichier et vérifiez les éléments suivants à l'aide des commandes UNIX.
--Combinaison de prédicats et de modèles de cas qui apparaissent fréquemment dans le corpus --Le modèle de casse des verbes "faire", "voir" et "donner" (organiser par ordre de fréquence d'apparition dans le corpus)
Je n'en suis pas particulièrement conscient dans le but de compléter le programme, mais le mot japonais «cas» semble être profond. Si vous êtes intéressé, jetez un œil à Wikipedit "Rate". Je suis juste en train de le regarder. Je me souviens que lorsque je faisais un échange linguistique en Australie, on m'a demandé quelle était la différence entre «ha» et «ga».
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)
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.verb = ''
self.joshi = ''
for morph in morphs:
if morph.pos != 'symbole':
self.joshi = '' #Vide pour les non-symboles pour obtenir la dernière ligne de verbes à l'exclusion des symboles
if morph.pos == 'verbe':
self.verb = morph.base
if morph.pos == 'Particule':
self.joshi = morph.base
#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)
with open('./045.result_python.txt', 'w') as out_file:
for sentence in sentences:
for chunk in sentence:
if chunk.verb != '' and len(chunk.srcs) > 0:
#Créer une liste de commis
sources = [sentence[source].joshi for source in chunk.srcs if sentence[source].joshi != '']
if len(sources) > 0:
sources.sort()
out_file.write(('{}\t{}\n'.format(chunk.verb, ' '.join(sources))))
Voici la partie commande UNIX. J'ai utilisé la commande grep
pour la première fois, mais c'est pratique.
Section de commande UNIX
#Tri, déduplication et comptage, tri décroissant
sort 045.result_python.txt | uniq --count | sort --numeric-sort --reverse > "045.result_1_tout.txt"
# 「(Début de ligne)Faire(Vide)Extraire, trier, déduplication et compter, tri décroissant
grep "^Faire\s" 045.result_python.txt | sort | uniq --count | sort --numeric-sort --reverse > "045.result_2_Faire.txt"
# 「(Début de ligne)à voir(Vide)Extraire, trier, déduplication et compter, tri décroissant
grep "^à voir\s" 045.result_python.txt | sort | uniq --count | sort --numeric-sort --reverse > "045.result_3_à voir.txt"
# 「(Début de ligne)donner(Vide)Extraire, trier, déduplication et compter, tri décroissant
grep "^donner\s" 045.result_python.txt | sort | uniq --count | sort --numeric-sort --reverse > "045.result_4_donner.txt"
La classe Chunk stocke les prototypes de verbes et de mots auxiliaires. S'il y a plusieurs verbes dans une phrase, nous gagnons en second. L'assistant de cas devrait apparaître à la fin de la phrase, mais nous avons inclus une branche conditionnelle qui prend en compte le symbole.
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.verb = ''
self.joshi = ''
for morph in morphs:
if morph.pos != 'symbole':
self.joshi = '' #Vide pour les non-symboles pour obtenir la dernière ligne de verbes à l'exclusion des symboles
if morph.pos == 'verbe':
self.verb = morph.base
if morph.pos == 'Particule':
self.joshi = morph.base
Les mots auxiliaires originaux sont listés dans une notation d'inclusion de liste et triés pour satisfaire "Disposer dans l'ordre lexical". Et enfin, la fonction join
est utilisée pour sortir séparés par des espaces. Le nid est profond et je me sens mal à l'aise d'écrire.
python
with open('./045.result_python.txt', 'w') as out_file:
for sentence in sentences:
for chunk in sentence:
if chunk.verb != '' and len(chunk.srcs) > 0:
#Créer une liste de commis
sources = [sentence[source].joshi for source in chunk.srcs if sentence[source].joshi != '']
if len(sources) > 0:
sources.sort()
out_file.write(('{}\t{}\n'.format(chunk.verb, ' '.join(sources))))
Lorsque le programme est exécuté, les résultats suivants sont affichés. Comme il y en a beaucoup, seules 10 lignes sont affichées ici.
bash:045.result_python.txt(10 premières lignes)
Être né
Tsukugato
En pleurant
Ou
Au début
À voir
Ecoutez
Attraper
Ébullition
Manger
Comme il y en a beaucoup, seules 10 lignes sont affichées ici.
bash:045.result_1_tout.txt(10 premières lignes)
Il y a 3176
1997 Tsukugato
800
721
464 à être
330
309 je pense
305 voir
301
Jusqu'à ce qu'il y ait 262
bash:045.result_2_Faire.txt(10 premières lignes)
1099
651
221
109 Mais
Jusqu'à 86
59 Qu'est-ce que
41
27 Qu'est-ce que c'est?
Jusqu'à 24
18 comme
bash:045.result_3_à voir.txt(10 premières lignes)
305 voir
99 voir
31 à voir
24 Voir
19 de voir
11 Voir
7 Parce que je vois
5 à voir
2 En regardant
2 Juste en regardant
"Give" a une fréquence d'apparition faible, et c'est tout.
bash:045.result_4_donner.txt
7 pour donner
4 pour donner
3 Que donner
Donnez 1 mais donnez
1 Quant à donner
1 donner