calendrier de l'avent 17e jour J'étais en retard. .. ..
Depuis que j'ai résolu 100 coups sur le traitement du langage, j'écrirai la réponse et l'impression un par un (deuxième partie) Cela a pris beaucoup plus de temps que la dernière fois ~~~
Pour l'environnement etc. ici (lien précédent)
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.
import CaboCha
c = CaboCha.Parser()
with open('./neko.txt') as f:
text = f.read()
with open('./neko.txt.cabocha', mode='w') as f:
for se in [s + '。' for s in text.split('。')]:
f.write(c.parse(se ).toString(CaboCha.FORMAT_LATTICE))
En fait, c'est la première analyse de dépendance, donc j'ai beaucoup cherché avec ça seul
Implémentez la classe Morph qui représente la morphologie. Cette classe a une forme de surface (surface), une forme de base (base), un mot de partie (pos) et une sous-classification de mot de partie 1 (pos1) en tant que variables membres. De plus, lisez le résultat de l'analyse de CaboCha (neko.txt.cabocha), exprimez chaque phrase comme une liste d'objets Morph et affichez la chaîne d'éléments morphologiques de la troisième phrase.
# 40
class Morph:
def __init__(self, surface, base, pos, pos1):
self.surface = surface
self.base = base
self.pos = pos
self.pos1 = pos1
doc = []
with open('./neko.txt.cabocha') as f:
sentence = []
line = f.readline()
while(line):
while('EOS' not in line):
if not line.startswith('*'):
cols = line.split('\t')
m = Morph(
surface=cols[0],
base=cols[1].split(',')[-3],
pos=cols[1].split(',')[0],
pos1=cols[1].split(',')[1],
)
sentence.append(m)
line = f.readline()
doc.append(sentence)
sentence = []
line = f.readline()
print([t.surface for t in doc[2]])
Faites-le en vérifiant le format de sortie de CaboCha
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.
# 41
class Chunk:
def __init__(self, morphs, dst, srcs):
self.morphs = morphs
self.dst = dst
self.srcs = srcs
doc = []
with open('./neko.txt.cabocha') as f:
sentence = []
line = f.readline()
while(line):
if line.startswith('*'):
cols = line.split(' ')
#Ne mettez rien une ligne au-dessus de l'EOS précédent
if cols[1] != '0':
sentence.append(c)
c = Chunk(
morphs=[],
dst=int(cols[2].split('D')[0]),
srcs=[]
)
elif 'EOS' in line:
sentence.append(c)
#Le processus pour trouver quelque chose qui dépend de vous
for i, c in enumerate(sentence):
c.srcs = [idx for idx, chk, in enumerate(sentence) if chk.dst == i ]
doc.append(sentence)
sentence = []
else:
cols = line.split('\t')
if cols[1].split(',')[0] != "symbole":
m = Morph(
surface=cols[0],
base=cols[1].split(',')[-3],
pos=cols[1].split(',')[0],
pos1=cols[1].split(',')[1],
)
c.morphs.append(m)
line = f.readline()
for c in doc[7]:
print(c.dst, end=', ')
for m in c.morphs:
print(m.surface, end="")
print()
for c in doc[0]:
print(c.dst, end=', ')
for m in c.morphs:
print(m.surface)
print(m.pos)
print()
Je réfléchissais à la façon de trouver la phrase qui me concernait, mais je ne pouvais pas en trouver une bonne, alors j'ai simplement bouclé et scanné.
Extrayez tout le texte de la clause originale et de la clause liée au format délimité par des tabulations. Cependant, n'émettez pas de symboles tels que les signes de ponctuation.
# 42
#Tous sont jupyter(chrome)Parce qu'il durcit 50
for i, d in enumerate(doc[:50]):
for c in d:
if int(c.dst) == -1:
continue
for m in c.morphs:
if m.pos == 'symbole':
continue
print(m.surface, end="")
print('\t', end="")
for m in d[c.dst].morphs:
if m.pos == 'symbole':
continue
print(m.surface, end="")
print()
Faites-le tout en étant conscient des phrases, des phrases et de la morphologie
Lorsque des clauses contenant une nomenclature se rapportent à des clauses contenant des verbes, extrayez-les au format délimité par des tabulations. Cependant, n'émettez pas de symboles tels que les signes de ponctuation.
# 43
#Tous sont jupyter(chrome)Parce qu'il durcit 50
for i, d in enumerate(doc[:50]):
for c in d:
if int(c.dst) == -1:
continue
contain_noun = 'nom' in [m.pos for m in c.morphs]
contain_verb = 'verbe' in [m.pos for m in d[c.dst].morphs]
if contain_noun and contain_verb:
for m in c.morphs:
if m.pos == 'symbole':
continue
print(m.surface, end="")
print('\t', end="")
for m in d[int(c.dst)].morphs:
if m.pos == 'symbole':
continue
print(m.surface, end="")
print()
J'ai simplement cherché avec ʻif`
Visualisez l'arbre de dépendance d'une phrase donnée sous forme de graphe orienté. Pour la visualisation, il est conseillé de convertir l'arborescence de dépendances dans le langage DOT et d'utiliser Graphviz. De plus, pour visualiser des graphiques dirigés directement à partir de Python, utilisez pydot.
# 44
import random, pathlib
from graphviz import Digraph
f = pathlib.Path('nekocabocha.png')
fmt = f.suffix.lstrip('.')
fname = f.stem
target_doc = random.choice(doc)
target_doc = doc[8]
idx = doc.index(target_doc)
dot = Digraph(format=fmt)
dot.attr("node", shape="circle")
N = len(target_doc)
#Ajouter un nœud
for i in range(N):
dot.node(str(i), ''.join([m.surface for m in target_doc[i].morphs]))
#Ajouter un bord
for i in range(N):
if target_doc[i].dst >= 0:
dot.edge(str(i), str(target_doc[i].dst))
# dot.engine = "circo"
dot.filename = filename
dot.render()
print(''.join([m.surface for c in target_doc for m in c.morphs]))
print(dot)
from IPython.display import Image, display_png
display_png(Image(str(f)))
Je n'ai pas fait grand-chose en pensant que la visualisation serait amusante, alors je l'ai fait pour la première fois, et Wikipedia était suffisant pour avoir une idée approximative du langage DOT.
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 phrase contenant un verbe, la forme de base du verbe le plus à gauche est utilisée comme prédicat Utilisez les mots auxiliaires liés au prédicat comme cas S'il existe plusieurs mots auxiliaires (phrases) liés au prédicat, organisez tous les mots auxiliaires dans l'ordre du dictionnaire, séparés par des espaces. Prenons l'exemple de la phrase (8e 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.
Commencer
Voir est
Enregistrez la sortie de ce programme dans un fichier et vérifiez les éléments suivants à l'aide des commandes UNIX. Une combinaison de prédicats et de modèles de cas qui apparaissent fréquemment dans le corpus Modèles de casse des verbes "faire", "voir" et "donner" (organiser par ordre de fréquence d'apparition dans le corpus)
# 45
with open("neko_verb.txt", mode="w") as f:
for s in doc:
for c in s:
if 'verbe' in [m.pos for m in c.morphs]:
row = c.morphs[0].base
j_list = []
for i in c.srcs:
if len(s[i].morphs) < 2:
continue
srclast = s[i].morphs[-1]
if srclast.pos == 'Particule':
j_list.append(srclast.surface)
if len(j_list) > 0:
j_list.sort()
row += "\t" + " ".join(j_list)
f.write(row + "\n")
$ cat neko_verb.txt | sort | uniq -c | sort -rn -k 3
$ cat neko_verb.txt | grep "^Faire" | sort | uniq -c | sort -rn -k 3
$ cat neko_verb.txt | grep "à voir" | sort | uniq -c | sort -rn -k 3
$ cat neko_verb.txt | grep "donner" | sort | uniq -c | sort -rn -k 3
Combinez la "partie des mots" et la "réception" jusqu'à présent
Modifiez le programme> 45 et affichez le terme (la clause elle-même liée au prédicat) au format délimité par des tabulations suivant le modèle de prédicat et de cas. En plus des 45 spécifications, répondez aux spécifications suivantes.
Le terme doit être une chaîne de mots de la clause liée au prédicat (il n'est pas nécessaire de supprimer le verbe de fin)
S'il existe plusieurs clauses liées au prédicat, disposez-les dans le même standard et dans le même ordre que les mots auxiliaires, séparés par des espaces.
Prenons l'exemple de la phrase (8e 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.
«Commencez ici»
Regarde ce que je vois
# 46
#Bien qu'il soit différent de l'exemple de sortie, celui-ci répond à la spécification du problème
for s in doc:
for c in s:
if 'verbe' in [m.pos for m in c.morphs]:
row = c.morphs[0].base
j_list = []
c_list = []
for i in c.srcs:
if len(s[i].morphs) < 2:
continue
srclast = s[i].morphs[-1]
if srclast.pos == 'Particule':
j_list.append(srclast.surface)
c_list.append(''.join([m.surface for m in s[i].morphs]))
if len(j_list) > 0:
j_list.sort()
c_list.sort()
row += "\t" + " ".join(j_list) + "\t"+ " ".join(c_list)
print(row)
S'il existe plusieurs clauses liées au prédicat, arrangez-les dans le même standard et dans le même ordre que les mots auxiliaires, séparés par des espaces.
C'est donc différent de l'exemple de sortie, mais les clauses sont également triées indépendamment
Je voudrais prêter attention uniquement au cas où le verbe wo case contient une nomenclature de connexion sa-hen. Modifiez 46 programmes pour répondre aux spécifications suivantes. Uniquement lorsque la phrase consistant en "Sahen connectant le nom + (auxiliaire)" est liée au verbe Le prédicat est «nom de connexion Sahen + est la forme de base du + 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, organisez 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, mon mari est dans la lettre» 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
# 47
with open("neko_func_verb.txt", mode="w") as f:
for s in doc:
for c in s:
if 'verbe' in [m.pos for m in c.morphs]:
verb = c.morphs[0].base
for i in c.srcs:
v_head = s[i].morphs[-2:]
if len(v_head) < 2:
continue
if v_head[0].pos1 == "Changer de connexion" and v_head[1].surface == "À":
verb = ''.join([m.surface for m in v_head]) + verb
joshi_dic = {}
for j in c.srcs:
if len(s[j].morphs) < 2:
continue
srclast = s[j].morphs[-1]
if srclast.pos == 'Particule' and srclast.surface != "À":
joshi_dic[srclast.surface] = ''.join([m.surface for m in s[j].morphs])
if len(joshi_dic.keys()) > 0:
joshi_list = list(joshi_dic.keys())
joshi_list.sort()
row = verb + "\t" + " ".join(joshi_list) + "\t" + " ".join([joshi_dic[joshi] for joshi in joshi_list])
f.write(row + "\n")
$ cat neko_func_verb.txt | sed "s/\t/ /g"| cut -f 1 -d " " | sort | uniq -c | sort -rn -k 3
$ cat neko_func_verb.txt | sed "s/\t/+/g"| cut -f 1,2 -d "+" | sed "s/+/\t/g" | sort | uniq -c | sort -rn -k 3
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).
Comme c'était la même chose, j'en ai fait un type de dictionnaire et l'ai associé Peu importe combien de fois j'ai lu le problème, je ne peux pas le comprendre et je commence à avoir des ennuis à partir d'ici
Pour une clause contenant toute la nomenclature de la phrase, extrayez le chemin de cette clause jusqu'à la racine de l'arbre de syntaxe. Cependant, le chemin sur l'arbre de syntaxe doit satisfaire aux spécifications suivantes. Chaque clause est représentée par une séquence morphologique (superficielle) De la clause de début à la clause de fin du chemin, concaténez les expressions de chaque clause avec "->" A partir de la phrase "J'ai vu un être humain pour la première fois ici" (8ème phrase de neko.txt.cabocha), la sortie suivante devrait être obtenue. «J'ai vu-> vu»
Ici-> Première fois-> Humain-> J'ai vu quelque chose->
Humain-> j'ai vu quelque chose->
J'ai vu quelque chose->
# 48
for s in doc:
for c in s:
if "nom" in [m.pos for m in c.morphs]:
row = "".join([m.surface for m in c.morphs])
chunk_to = c.dst
if chunk_to == -1:
continue
while(chunk_to != -1):
row += " -> " + "".join([m.surface for m in s[chunk_to].morphs])
chunk_to = s[chunk_to].dst
print(row)
Cela a été résolu en douceur par rapport au problème précédent
Extraire le chemin de dépendance le plus court qui relie toutes les paires de nomenclatures de la phrase. Cependant, lorsque les numéros de clause de la paire de nomenclatures sont i et j (i <j), le chemin de dépendance doit satisfaire aux spécifications suivantes. Similaire au problème 48, le chemin est exprimé en concaténant les expressions (éléments morphologiques de surface) de chaque phrase de la clause de début à la clause de fin avec "->". Remplacez la nomenclature contenue dans les clauses i et j par X et Y, respectivement. De plus, la forme du chemin de dépendance peut être considérée des deux manières suivantes. Si la clause j existe sur le chemin de la clause i à la racine de l'arbre de syntaxe: Afficher le chemin de la clause i à la clause j Autre que ce qui précède, lorsque la clause i et la clause j se croisent à une clause commune k sur le chemin de la clause j à la racine de l'arbre syntaxique: le chemin immédiatement avant la clause i vers la clause k et le chemin immédiatement avant la clause j vers la clause k, clause k Le contenu de est connecté par "|" et affiché. Par exemple, la sortie suivante doit être obtenue à partir de la phrase "J'ai vu un être humain pour la première fois ici" (8ème phrase de neko.txt.cabocha).
X est|En Y->Commencer avec->Humain->Des choses|vu
X est|Appelé Y->Des choses|vu
X est|Oui|vu
X-> Début-> Y
X-> Démarrer-> Humain-> Y
X-> Y
# 49
for s in doc:
# i <Pas besoin de la fin à cause de j
for i, c in enumerate(s[:-1]):
if "nom" in [m.pos for m in c.morphs] and c.morphs[-1].pos == "Particule":
#Trouver j
for c_rest in s[i+1:]:
if "nom" in [m.pos for m in c_rest.morphs] and c_rest.morphs[-1].pos == "Particule":
i_clause = "".join([m.surface if m.pos != "nom" else "X" for m in c.morphs])
j_clause = "".join([m.surface if m.pos != "nom" else "Y" for m in c_rest.morphs])
row = i_clause
chunk_to = c.dst
#Demandez le chemin pour voir si j est sur le chemin
kkr_path = [chunk_to]
while(kkr_path[-1] != -1):
kkr_path.append(s[chunk_to].dst)
chunk_to = s[chunk_to].dst
if s.index(c_rest) in kkr_path:
chunk_to = c.dst
while(chunk_to != s.index(c_rest)):
row += " -> " + "".join([m.surface for m in s[chunk_to].morphs])
chunk_to = s[chunk_to].dst
row += " -> " + j_clause
else:
row += " | " + j_clause
chunk_to = c_rest.dst
while(s[chunk_to].dst != -1):
row += " -> " + "".join([m.surface for m in s[chunk_to].morphs])
chunk_to = s[chunk_to].dst
row += " | " + "".join([m.surface for m in s[chunk_to].morphs])
print(row)
Remplacer la nomenclature contenue dans les clauses i et j par X et Y, respectivement.
Les spécifications et les exemples de sortie étaient également légèrement différents ici, mais je les ai remplacés par une nomenclature telle que "X ga".
Effectuez le traitement suivant sur le texte anglais (nlp.txt).
$ wget http://www.cl.ecei.tohoku.ac.jp/nlp100/data/nlp.txt
(. Ou; ou: ou?
# 50
import re
sentence_sep = re.compile(r'(\.|;|:|\?|!) ([A-Z])')
with open("./nlp.txt") as f:
txt = f.read()
txt = re.sub(sentence_sep, r'\1\n\2', txt)
print(txt)
Je l'ai résolu en pensant
Traitez les blancs comme des sauts de mots, prenez 50 sorties en entrée et en sortie sous la forme d'un mot par ligne. Cependant, affichez une ligne vide à la fin de l'instruction.
# 51
def space2return(txt):
sentence_sep = re.compile(r'(\.|;|:|\?|!)\n([A-Z])')
txt = re.sub(sentence_sep, r'\1\n\n\2', txt)
return re.sub(r' ', r'\n', txt)
txt = space2return(txt)
print(txt)
Reçoit 50 sorties, mais répond ad hoc car il se comporte de manière un peu inattendue en raison de sauts de ligne dans la phrase
Prenez la sortie de> 51 comme entrée, appliquez l'algorithme de dérivation de Porter et affichez les mots et les racines au format délimité par des tabulations. En Python, le module de dérivation doit être utilisé comme une implémentation de l'algorithme de dérivation de Porter.
# 52
from nltk.stem import PorterStemmer
ps = PorterStemmer()
def stem_text(txt):
for l in txt.split('\n'):
yield l + '\t' + ps .stem(l)
for line in stem_text(txt):
print(line)
Ce n'était pas dans Liens fournis, donc je l'ai utilisé à la place. J'ai essayé d'utiliser yield, ce que j'évite généralement, mais j'ai trouvé que la valeur de retour est un itérateur.
53 Tokenization
Utilisez Stanford Core NLP pour obtenir le résultat de l'analyse du texte d'entrée au format XML. Lisez également ce fichier XML et sortez le texte d'entrée sous la forme d'un mot par ligne.
$ wget http://nlp.stanford.edu/software/stanford-corenlp-full-2018-10-05.zip
$ unzip stanford-corenlp-full-2018-10-05.zip
$ java -cp "./stanford-corenlp-full-2018-10-05/*" edu.stanford.nlp.pipeline.StanfordCoreNLP -annotators tokenize,ssplit,parse,lemma,ner,coref -file ./nlp.txt
Ce type, plutôt que de souffrir de l'analyse XML
Voir la référence pour -annotators
lors de l'exécution de java et la modifier si nécessaire
# 53
import xml.etree.ElementTree as ET
tree = ET.parse("./nlp.txt.xml")
root = tree.getroot()
for token in root.iter("token"):
print(token.find("word").text)
Est-ce un moyen de sortir le tout et de vérifier les balises?
Lire le code XML des résultats d'analyse de Stanford Core NLP et afficher les mots, les lemmes et les parties au format délimité par des tabulations.
# 54
for token in root.iter("token"):
print(token.find("word").text + "\t" + token.find("lemma").text + "\t" + token.find("POS").text)
Très difficile à voir
Extrayez tous les noms de personne dans le texte d'entrée.
# 55
for token in root.iter("token"):
NERtag = token.find("NER").text
if NERtag == "PERSON":
print(token.find("word").text)
Je pensais que c'était une implémentation mais elle était taguée
Remplacer l'expression de référence (mention) dans la phrase par l'expression de référence représentative (mention représentative) basée sur le résultat de l'analyse de co-référence de Stanford Core NLP. Cependant, lors du remplacement, veillez à ce que l'expression de référence d'origine puisse être comprise, telle que «expression de référence représentative (expression de référence)».
# 56
rep_dic_list = []
#Faire un dictionnaire
for coreferences in root.findall("document/coreference"):
for mentions in coreferences:
for m in mentions:
if "representative" in m.attrib:
rep_txt = m.find("text").text
else:
tmp_dic = {}
tmp_dic["sentence"] = m.find("sentence").text
tmp_dic["start"] = m.find("start").text
tmp_dic["end"] = m.find("end").text
tmp_dic["rep_txt"] = rep_txt
rep_dic_list.append(tmp_dic)
#production
for s in root.iter("sentence"):
rep_sent_list = [rd for rd in rep_dic_list if rd["sentence"] == s.attrib["id"]]
#Si la déclaration doit être remplacée
if len(rep_sent_list) == 0:
print(" ".join([token.find("word").text for token in s.iter("token")]), end=" ")
else:
for token in s.iter("token"):
tid = token.attrib["id"]
rep_token_list = [rd for rd in rep_sent_list if rd["start"] == tid or rd["end"] == tid]
if len(rep_token_list) > 0:
#Puisqu'il n'y en a qu'un, sortez-le
rep_dic = rep_token_list[0]
#Décoration
if tid == rep_dic["start"]:
print("「" + rep_dic["rep_txt"] + " (", end=" ")
if tid == rep_dic["end"]:
print(")」", end=" ")
print(token.find("word").text, end=" ")
Je n'ai pas pu comprendre l'énoncé du problème et je l'ai laissé ici pendant longtemps. Créer un dictionnaire et modifier plutôt que remplacer
Visualisez les dépendances réduites de la PNL Stanford Core sous forme de graphe orienté. Pour la visualisation, il est conseillé de convertir l'arborescence de dépendances dans le langage DOT et d'utiliser Graphviz. De plus, pour visualiser des graphiques dirigés directement à partir de Python, utilisez pydot.
# 57
import random, pathlib
from graphviz import Digraph
f = pathlib.Path('nlp.png')
fmt = f.suffix.lstrip('.')
fname = f.stem
dot = Digraph(format=fmt)
dot.attr("node", shape="circle")
sent_id = 3
for sents in root.findall(f"document/sentences/sentence[@id='{sent_id}']"):
for deps in sents:
for dep in deps.findall("[@type='collapsed-dependencies']"):
for token in dep:
gvnr = token.find("governor")
dpnt = token.find("dependent")
dot.node(gvnr.attrib["idx"], gvnr.text)
dot.node(dpnt.attrib["idx"], dpnt.text)
dot.edge(gvnr.attrib["idx"], dpnt.attrib["idx"])
dot.filename = fname
dot.render()
# print(dot)
from IPython.display import Image, display_png
display_png(Image(str(f)))
Au début, je suis passé par «gouverneur» et «dépendant», donc je n'ai pas compris du tout.
Sortie de l'ensemble des "objets de prédicat sujet" au format délimité par des tabulations en fonction du résultat de l'analyse des dépendances (dépendances réduites) de Stanford Core NLP. Cependant, reportez-vous à ce qui suit pour les définitions du sujet, du prédicat et de l'objet.
Prédicat: un mot qui a des enfants (dépendants) des relations nsubj et dobj
Sujet: enfant (dépendant) qui a une relation nsubj du prédicat
ʻObject: Un enfant (dépendant) qui a une relation dobj du prédicat`
# 58
for sents in root.findall(f"document/sentences/sentence"):
for deps in sents:
for dep in deps.findall("[@type='collapsed-dependencies']"):
nsubj_list = []
for token in dep.findall("./dep[@type='nsubj']"):
gvnr = token.find("governor")
dpnt = token.find("dependent")
nsubj_list.append( {
(gvnr.attrib["idx"], gvnr.text): (dpnt.attrib["idx"], dpnt.text)
})
for token in dep.findall("./dep[@type='dobj']"):
gvnr = token.find("governor")
dpnt = token.find("dependent")
dobj_tuple = (gvnr.attrib["idx"], gvnr.text)
if dobj_tuple in [list(nsubj.keys())[0] for nsubj in nsubj_list]:
idx = [list(nsubj.keys())[0] for nsubj in nsubj_list].index( dobj_tuple )
jutugo = gvnr.text
shugo = nsubj_list[idx][dobj_tuple][1]
mokutekigo = dpnt.text
print(shugo + "\t" + jutugo + "\t" + mokutekigo)
Politique pour créer un dictionnaire une fois, puis rechercher celui qui remplit les conditions
Lisez le résultat de l'analyse de la structure des phrases de Stanford Core NLP (formule S) et affichez toutes les phrases de nomenclature (NP) dans la phrase. Afficher toute la nomenclature imbriquée.
# 59
import xml.etree.ElementTree as ET
import re
def search_nest(t):
if isinstance(t[0], str):
if isinstance(t[1], str):
if t[0] == "NP":
print(t[1])
return t[1]
else:
if t[0] == "NP":
np_list = []
for i in t[1:]:
res = search_nest(i)
if isinstance(res, str):
np_list.append(search_nest(i))
if len(np_list) > 0:
print(' '.join(np_list))
else:
for i in t[1:]:
search_nest(i)
else:
for i in t:
search_nest(i)
tree = ET.parse("./nlp.txt.xml")
root = tree.getroot()
sent_id = 30
for parse in root.findall(f"document/sentences/sentence[@id='{sent_id}']/parse"):
S_str = parse.text
S_str = S_str.replace("(", "('")
S_str = S_str.replace(")", "')")
S_str = S_str.replace(" ", "', '")
S_str = S_str.replace("'(", "(")
S_str = S_str.replace(")'", ")")
exec(f"S_tuple = {S_str[:-2]}")
search_nest(S_tuple)
Je n'ai pas pu reconnaître l'imbrication de ()
et j'ai fait la plus grosse implémentation sale de ma vie. Je l'ai codée en dur dans un type taple et l'ai extraite récursivement.
J'ai essayé regex
mais je n'ai pas pu le résoudre moi-même, j'ai donc donné la priorité à la réponse.
Cela a pris environ deux fois plus de temps que les chapitres 1 à 4, car les deux chapitres étaient les premières bibliothèques et le nombre de termes de traitement du langage a soudainement augmenté. Cependant, les autres sont DB, ML et vector, donc je ne fais pas attention.
Recommended Posts