Réponses et impressions de 100 chocs de traitement de la langue - Partie 2

calendrier de l'avent 17e jour J'étais en retard. .. ..

c'est

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 ~~~

Conditions préalables

Pour l'environnement etc. ici (lien précédent)

Histoire principale

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.

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

40 Lecture des résultats de l'analyse des dépendances (morphologie)

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

41 Lecture des résultats de l'analyse des dépendances (phrase / 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.

# 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é.

42 Affichage de la phrase de l'intéressé et de l'intéressé

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

43 Extrait des clauses contenant la nomenclature liée aux clauses contenant des verbes

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`

44 Visualisation des arbres dépendants

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.

45 Extraction de modèles de cas verbaux

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

46 Extraction des informations sur le cadre de la casse verbale

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

47 Exploration de la syntaxe des verbes fonctionnels

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

48 Extraction des chemins de la nomenclature aux racines

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

49 Extraction des chemins de dépendance entre nomenclature

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".

Chapitre 6: Traitement du texte anglais

Effectuez le traitement suivant sur le texte anglais (nlp.txt).

$ wget http://www.cl.ecei.tohoku.ac.jp/nlp100/data/nlp.txt

50 phrase pause

(. 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

Découpe de 51 mots

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

52 Tiges

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?

54 Marquage de mots partiels

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

55 Extraction d'expression unique

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

56 Analyse de co-référence

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

57 Analyse des dépendances

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.

58 Extraction de taple

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

59 Analyse de l'équation S

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.

fin

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

Réponses et impressions de 100 chocs de traitement linguistique - Partie 1
Réponses et impressions de 100 chocs de traitement de la langue - Partie 2
Vue d'ensemble du traitement du langage naturel et de son prétraitement des données
Types de prétraitement dans le traitement du langage naturel et leur puissance
100 traitement de la langue knock-42: Affichage de la phrase de la personne concernée et de la personne concernée
Logivan du langage artificiel et traitement du langage naturel (traitement du langage artificiel)
100 traitement du langage knock-59: analyse de la formule S
Résumé du traitement multi-processus du langage de script
100 traitement du langage knock-91: Préparation des données d'analogie
Traitement du langage 100 knocks-44: Visualisation des arbres dépendants
Traiter le nom de la carte Yugioh en langage naturel --Yugiou Data Science 2. PNL
100 traitement de langue knock-22: Extraction du nom de la catégorie
100 Language Processing Knock-26: suppression du balisage accentué
Réhabilitation des compétences Python et PNL à partir de "100 Language Processing Knock 2015" (Chapitre 1)
100 traitements linguistiques frappent 03 ~ 05
100 coups de traitement linguistique (2020): 40
100 coups de traitement linguistique (2020): 32
100 coups de traitement linguistique (2020): 47
100 coups de traitement linguistique (2020): 22
100 coups de traitement linguistique (2020): 26
100 coups de traitement linguistique (2020): 34
100 coups de traitement linguistique (2020): 28
100 coups de traitement linguistique (2020): 42
100 coups de traitement linguistique (2020): 29
100 coups de traitement linguistique (2020): 49
Le traitement de 100 langues frappe 06 ~ 09
100 coups de traitement linguistique (2020): 43
100 coups de traitement linguistique (2020): 24
100 coups de traitement linguistique (2020): 45
100 Language Processing Knock-32 (utilisant des pandas): Prototype de verbe
100 coups de traitement linguistique (2020): 10-19
100 coups de traitement linguistique (2020): 30
Traitement du langage 100 knocks-45: Extraction de modèles de cas verbaux
100 coups de traitement linguistique (2020): 00-09
100 coups de traitement linguistique (2020): 31
100 coups de traitement linguistique (2020): 38
100 traitement du langage knock-75 (en utilisant scicit-learn): poids de l'identité
100 coups de traitement linguistique (2020): 48
100 coups de traitement linguistique (2020): 44
100 coups de traitement linguistique (2020): 41
100 coups de traitement linguistique (2020): 37
100 traitement de la langue frapper 00 ~ 02
100 coups de traitement linguistique (2020): 25
100 coups de traitement linguistique (2020): 23
100 coups de traitement linguistique (2020): 33
100 coups de traitement linguistique (2020): 20
100 coups de traitement linguistique (2020): 27
100 coups de traitement linguistique (2020): 46
Résumé du traitement pickle et unpickle des classes définies par l'utilisateur
Insoutenable manque d'attention dans le traitement du langage naturel
100 coups de traitement linguistique (2020): 21
100 coups de traitement linguistique (2020): 36
Réhabilitation des compétences Python et PNL à partir de «Knock 100 Language Processing 2015» (chapitre 2 deuxième semestre)
Réhabilitation des compétences Python et PNL à partir de "100 Language Processing Knock 2015" (Chapitre 2 premier semestre)
[Traitement du langage 100 coups 2020] Résumé des exemples de réponses par Python
Traitement pleine largeur et demi-largeur des données CSV en Python
Traitement du langage 100 knocks-46: Extraction des informations de trame de cas de verbe
100 traitement du langage knock-36 (en utilisant des pandas): fréquence d'occurrence des mots
[Chapitre 5] Introduction à Python avec 100 coups de traitement du langage
[Chapitre 6] Introduction à scicit-learn avec 100 coups de traitement du langage
Vérification des performances du prétraitement des données dans le traitement du langage naturel