[PYTHON] Traitement du langage 100 knocks-49: Extraction de chemins de dépendances entre nomenclature

Traitement du langage 100 coups 2015 ["Chapitre 5: Analyse des dépendances"](http: //www.cl.ecei. Il s'agit d'un enregistrement de 49ème "Extraction de chemin de dépendance entre nomenclature" de tohoku.ac.jp/nlp100/#ch5). .. C'est finalement le tournant de 100 coups. Voici ** un coup vicieux qui devient une porte démoniaque **. ** Le problème est difficile à comprendre, et même si vous le comprenez, il est difficile de le résoudre **. J'ai l'impression d'avoir terminé 100, mais c'est le coup le plus gênant pour mon propre algorithme (il y en a d'autres plus compliqués, mais je laisse fondamentalement cela au paquet, donc je n'ai pas beaucoup de problèmes).

Lien de référence

Lien Remarques
049.Extraction de chemins de dépendances entre nomenclature.ipynb Lien GitHub du programme de réponse
100 coups de traitement du langage amateur:49 Copiez et collez la source de nombreuses pièces source
Officiel de CaboCha Page CaboCha à regarder en premier

environnement

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)

Chapitre 5: Analyse des dépendances

contenu de l'étude

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/)

Contenu frappé

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.

49. Extraction de chemins de dépendances 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 nomenclature 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 "->". --Remplacer 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 * est présente 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 de ce qui précède, lorsque la phrase * i * et la clause * j * se croisent en une clause commune * k * sur le chemin de la clause * j * à la racine de l'arbre de syntaxe: Le chemin et la clause * immédiatement avant la clause * i * vers la clause * k * Le chemin de j * à juste avant la clause * k * et le contenu de la clause * k * sont concaténés avec "|" et affichés

Par exemple, à 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.

X est|En Y->Commencer avec->Humain->Des choses|vu
X est|Appelé Y->Des choses|vu
X est|Oui|vu
Avec X->Commencer avec-> Y
Avec X->Commencer avec->Humain-> Y
Appelé X-> Y

Supplément de problème

Le contenu du coup est long et difficile à comprendre. Article ["Traitement du langage amateur 100 coups: 49"](https://qiita.com/segavvy/items/dfbf9d5dd5885e807d49#%E5%95%8F%E9%A1%8C%E3%81%AE%E6% J'ai finalement compris après avoir vu 84% 8F% E5% 91% B3). Je vais omettre mon explication ...

Répondre

Programme de réponse [049. Extraction de chemins de dépendance entre nomenclature.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/05.%E4%BF%82%E3%82%8A%E5% 8F% 97% E3% 81% 91% E8% A7% A3% E6% 9E% 90 / 049.% E5% 90% 8D% E8% A9% 9E% E9% 96% 93% E3% 81% AE% E4 % BF% 82% E3% 82% 8A% E5% 8F% 97% E3% 81% 91% E3% 83% 91% E3% 82% B9% E3% 81% AE% E6% 8A% BD% E5% 87 % BA.ipynb)

Il y a 150 lignes ... Il semble que cela puisse être fait un peu plus simple si cela prend du temps, mais je suis cassé.

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)
NOUN_REPLACE = '@@noun@@'
SEP1 = ' -> '
SEP2 = ' | '

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.dst  = dst  #Numéro d'index de la clause de contact
        self.dsts = []
        
        self.phrase = ''
        self.phrase_noun = ''
        self.noun = False
        
        for morph in morphs:
            if morph.pos != 'symbole':
                self.phrase += morph.surface #Pour les non-symboles
                if morph.pos == 'nom':
                    
                    #S'il s'agit du premier nez, traitez-le comme une expression de nomenclature
                    if self.noun == False:
                        self.noun = True
                        self.phrase_noun += NOUN_REPLACE
                        continue
                    
                    #Si le précédent est une nomenclature, ne remplacez pas le système de surface
                    elif self.noun and self.phrase_noun.endswith(NOUN_REPLACE):
                        continue
                        
                #Sauf pour le remplacement et le saut, ajoutez le système de surface tel quel
                self.phrase_noun += morph.surface

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:
            
            #Ajouter des contacts(Ajoutez la dernière ligne pour plus d'efficacité)
            for chunk in chunks[::-1]:
                if chunk.dst!= -1:
                    chunk.dsts.extend([chunk.dst])
                    if chunks[chunk.dst].dst != -1:
                        chunk.dsts.extend(chunks[chunk.dst].dsts)
            sentences.append(chunks)
            chunks = []

def output_result(i, chunk, sentence):
    print('\tX:', i, chunk.phrase, chunk.dsts)
    
    #Nomenclature(X)Boucle pour rechercher Y après
    for i_y, y_chunk in enumerate(sentence[i+1:], i+1):
        
        #Y pour nomenclature
        if y_chunk.noun:
            
            #Sortie d'informations Y
            print('\t\tY:', i_y, y_chunk.phrase)
            
            result = ''
            
            #Y est la route(Contact)Si inclus dans
            if i_y in chunk.dsts:
                
                result = '\t\t\tP1:' + '\t' + sentence[i].phrase_noun.replace(NOUN_REPLACE, 'X') + SEP1
                
                #Sortie de X à Y
                for i_path in chunk.dsts:
                    
                    #Terminer lorsque Y est atteint
                    if i_path == i_y:
                        result += 'Y'
                        break
                    else:
                        result += sentence[i_path].phrase + SEP1
            
            #Y est la route(Contact)Si non inclus dans
            else:
                result = '\t\t\tP2:' + '\t' + sentence[i].phrase_noun.replace(NOUN_REPLACE, 'X')
                
                #Rechercher une clause commune avec la valeur minimale dans l'ensemble de produits
                i_goal = min(set(chunk.dsts).intersection(set(sentence[i_y].dsts)))
                
                #De X à Y avant la phrase courante
                for i_path in chunk.dsts:                    
                    if i_path == i_goal:
                        result += SEP2 + sentence[i_y].phrase_noun.replace(NOUN_REPLACE, 'Y')
                        break
                    else:
                        result += SEP1 + sentence[i_path].phrase                 
                
                #De la personne en charge de Y à la phrase courante
                for i_path in sentence[i_y].dsts:
                    if i_path == i_goal:
                        result += SEP2 + sentence[i_goal].phrase
                    else:
                        result += SEP1 + sentence[i_path].phrase
            print(result)

for i_sentence, sentence in enumerate(sentences):
    
    #Sortie de déclaration
    print(i_sentence, '\t', ''.join([chunk.phrase for chunk in sentence]))
    for i_chunk, chunk in enumerate(sentence):
        
        #Si la phrase est une nomenclature
        if chunk.noun and chunk.dst != -1:
            output_result(i_chunk, chunk, sentence)

    #Limité car il y en a beaucoup
    if i_sentence > 5:
        break

Répondre au commentaire

Classe de morceaux

Tout d'abord, nous élargissons considérablement la classe Chunk. Définissez le drapeau «noun» sur «True» s'il s'agit d'une nomenclature. Ensuite, créez phrase_noun de sorte que" X est "et" Y est ". À ce stade, cela peut être X ou Y, donc j'ai mis la valeur fixe NOUN_REPLACE dans les parties X et Y. En outre, en considérant le cas où la nomenclature est continue (exemple: colombe + horloge), ʻend avecest vérifié pour voir si la fin estNOUN_REPLACE (assurez-vous que NOUN_REPLACE` n'est pas continu).

python


class Chunk:
    def __init__(self, morphs, dst):
        self.morphs = morphs
        self.dst  = dst  #Numéro d'index de la clause de contact
        self.dsts = []
        
        self.phrase = ''
        self.phrase_noun = ''
        self.noun = False
        
        for morph in morphs:
            if morph.pos != 'symbole':
                self.phrase += morph.surface #Pour les non-symboles
                if morph.pos == 'nom':
                    
                    #S'il s'agit du premier nez, traitez-le comme une expression de nomenclature
                    if self.noun == False:
                        self.noun = True
                        self.phrase_noun += NOUN_REPLACE
                        continue
                    
                    #Si le précédent est une nomenclature, ne remplacez pas le système de surface
                    elif self.noun and self.phrase_noun.endswith(NOUN_REPLACE):
                        continue
                        
                #Sauf pour le remplacement et le saut, ajoutez le système de surface tel quel
                self.phrase_noun += morph.surface

Partie de boucle de lecture de fichier

Ce qui a changé depuis la dernière fois, c'est la dernière branche conditionnelle ʻif"lorsqu'il y a un résultat de dépendance dans EOS". Parcourez l'ensemble des clauseschunks` pour créer une liste de tous les contacts. La raison de la boucle en arrière à partir de la dernière ligne est que nous voulons créer tous les contacts à la fois et réutiliser la liste de contacts une fois créée.

python


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:
        
        #Ajouter des contacts(Ajoutez à partir de la dernière ligne pour plus d'efficacité)
        for chunk in chunks[::-1]:
            if chunk.dst!= -1:
                chunk.dsts.extend([chunk.dst])
                if chunks[chunk.dst].dst != -1:
                    chunk.dsts.extend(chunks[chunk.dst].dsts)
        sentences.append(chunks)
        chunks = []

Section de sortie

Pour faciliter la vérification plus tard, la phrase entière, les informations X et Y sont indentées et sorties, bien qu'elles ne soient pas incluses dans les instructions de tâche. La sortie cette fois peut être divisée en gros dans les deux modèles suivants.

--Pattern 1: X et Y sont la même route: Y remplace la clause entière-> Mis à P1 en sortie --Modèle 2: X et Y sont séparés par un autre chemin: |, Y remplace uniquement la nomenclature -> Mis à P2 au moment de la sortie

Dans le cas du motif 1, puisque X et Y sont le même chemin, X à Y sont sortis dans l'ordre. Le motif 2 est compliqué car X et Y sont des chemins différents. J'utilise la fonction ʻintersection` pour trouver la terminaison partagée de X et Y. "Ce que j'ai fait dans le sixième chapitre du chapitre 1" C'est vrai.

python


def output_result(i, chunk, sentence):
    print('\tX:', i, chunk.phrase, chunk.dsts)

    #Nomenclature(X)Boucle pour rechercher Y après
    for i_y, y_chunk in enumerate(sentence[i+1:], i+1):

        #Y pour nomenclature
        if y_chunk.noun:

            #Sortie d'informations Y
            print('\t\tY:', i_y, y_chunk.phrase)

            result = ''

            #Y est la route(Contact)Si inclus dans
            if i_y in chunk.dsts:

                result = '\t\t\tP1:' + '\t' + sentence[i].phrase_noun.replace(NOUN_REPLACE, 'X') + SEP1

                #Sortie de X à Y
                for i_path in chunk.dsts:

                    #Terminer lorsque Y est atteint
                    if i_path == i_y:
                        result += 'Y'
                        break
                    else:
                        result += sentence[i_path].phrase + SEP1

            #Y est la route(Contact)Si non inclus dans
            else:
                result = '\t\t\tP2:' + '\t' + sentence[i].phrase_noun.replace(NOUN_REPLACE, 'X')

                #Rechercher une clause commune avec la valeur minimale dans l'ensemble de produits
                i_goal = min(set(chunk.dsts).intersection(set(sentence[i_y].dsts)))

                #De X à Y avant la phrase courante
                for i_path in chunk.dsts:                    
                    if i_path == i_goal:
                        result += SEP2 + sentence[i_y].phrase_noun.replace(NOUN_REPLACE, 'Y')
                        break
                    else:
                        result += SEP1 + sentence[i_path].phrase                 

                #De la personne en charge de Y à la phrase courante
                for i_path in sentence[i_y].dsts:
                    if i_path == i_goal:
                        result += SEP2 + sentence[i_goal].phrase
                    else:
                        result += SEP1 + sentence[i_path].phrase
            print(result)

Résultat de sortie (résultat de l'exécution)

Lorsque le programme est exécuté, les résultats suivants sont affichés. C'est peut-être vrai. Je n'ai pas beaucoup vérifié.

Résultat de sortie


0 un
1 je suis un chat
2 Pas encore de nom
	X:0 Le nom est[2]
3 Je n'ai aucune idée d'où je suis né
	X:0 où[1, 2, 4]
		Y:2 Katonto
			P1:Avec X->Née-> Y
		Y:3 J'ai un indice
			P2:Avec X->Née->Katonto|Oui|Ne pas utiliser
	X:2 Katonto[4]
		Y:3 J'ai un indice
			P2:Avec X|Oui|Ne pas utiliser
	X:3 J'ai un indice[4]
4 Je me souviens d'avoir pleuré seulement dans un endroit sombre et humide
	X:0 rien[1, 5, 7]
		Y:À 3
			P2:Même avec X->faible|En Y|En larmes->je me rappelle
		Y:6 Seulement ce qui était là
			P2:Même avec X->faible->En larmes|Seulement Y|je me rappelle
		Y:7 Souviens-toi
			P1:Même avec X->faible->En larmes-> Y
	X:À 3[5, 7]
		Y:6 Seulement ce qui était là
			P2:Avec X->En larmes|Seulement Y|je me rappelle
		Y:7 Souviens-toi
			P1:Avec X->En larmes-> Y
	X:6 Seulement ce qui était là[7]
		Y:7 Souviens-toi
			P1:Seulement X-> Y
5 J'ai vu des êtres humains pour la première fois ici
	X:0 je suis[5]
		Y:1 où
			P2:X est|En Y->Commencer avec->Humain->Des choses|vu
		Y:3 humain
			P2:X est|Appelé Y->Des choses|vu
		Y:4 choses
			P2:X est|Oui|vu
	X:1 où[2, 3, 4, 5]
		Y:3 humain
			P1:Avec X->Commencer avec-> Y
		Y:4 choses
			P1:Avec X->Commencer avec->Humain-> Y
	X:3 humain[4, 5]
		Y:4 choses
			P1:Appelé X-> Y
	X:4 choses[5]
De plus, j'ai entendu plus tard que c'était la race la plus méchante des êtres humains appelée Shosei.
	X:1 plus tard[2, 9]
		Y:3 c'est
			P2:Avec X->Quand tu entends|Y est|C'est tout
		Y:4 Appelé un étudiant
			P2:Avec X->Quand tu entends|Appelé Y->Chez l'homme->C'était une course|C'est tout
		Y:5 chez l'homme
			P2:Avec X->Quand tu entends|En Y->C'était une course|C'est tout
		Y:6 Ichiban
			P2:Avec X->Quand tu entends| Y ->Mal->C'était une course|C'est tout
		Y:7 mal
			P2:Avec X->Quand tu entends|Oui->C'était une course|C'est tout
		Y:Était 8 courses
			P2:Avec X->Quand tu entends|Était Y|C'est tout
		Y:9 C'est vrai
			P1:Avec X->Quand tu entends-> Y
	X:3 c'est[9]
		Y:4 Appelé un étudiant
			P2:X est|Appelé Y->Chez l'homme->C'était une course|C'est tout
		Y:5 chez l'homme
			P2:X est|En Y->C'était une course|C'est tout
		Y:6 Ichiban
			P2:X est| Y ->Mal->C'était une course|C'est tout
		Y:7 mal
			P2:X est|Oui->C'était une course|C'est tout
		Y:Était 8 courses
			P2:X est|Était Y|C'est tout
		Y:9 C'est vrai
			P1:X est-> Y
	X:4 Appelé un étudiant[5, 8, 9]
		Y:5 chez l'homme
			P1:Appelé X-> Y
		Y:6 Ichiban
			P2:Appelé X->Chez l'homme| Y ->Mal|C'était une course->C'est tout
		Y:7 mal
			P2:Appelé X->Chez l'homme|Oui|C'était une course->C'est tout
		Y:Était 8 courses
			P1:Appelé X->Chez l'homme-> Y
		Y:9 C'est vrai
			P1:Appelé X->Chez l'homme->C'était une course-> Y
	X:5 chez l'homme[8, 9]
		Y:6 Ichiban
			P2:Avec X| Y ->Mal|C'était une course->C'est tout
		Y:7 mal
			P2:Avec X|Oui|C'était une course->C'est tout
		Y:Était 8 courses
			P1:Avec X-> Y
		Y:9 C'est vrai
			P1:Avec X->C'était une course-> Y
	X:6 Ichiban[7, 8, 9]
		Y:7 mal
			P1:	X -> Y
		Y:Était 8 courses
			P1:	X ->Mal-> Y
		Y:9 C'est vrai
			P1:	X ->Mal->C'était une course-> Y
	X:7 mal[8, 9]
		Y:Était 8 courses
			P1:X-> Y
		Y:9 C'est vrai
			P1:X->C'était une course-> Y
	X:Était 8 courses[9]
		Y:9 C'est vrai
			P1:Était X-> Y

Recommended Posts

Traitement du langage 100 knocks-49: Extraction de chemins de dépendances entre nomenclature
Traitement du langage 100 knocks-48: Extraction du chemin du nez à la racine
100 Language Processing Knock-58: Extraction de Taple
100 Language Processing Knock-57: Analyse des dépendances
100 Language Processing Knock-25: Extraction de modèles
100 Language Processing Knock 2015 Chapitre 5 Analyse des dépendances (40-49)
100 Language Processing Knock-55: extraction d'expressions uniques
100 Language Processing Knock-82 (mot de contexte): Extraction de contexte
100 Language Processing Knock 2020 Chapitre 5: Analyse des dépendances
100 traitement du langage knock-59: analyse de la formule S
100 traitement du langage knock-91: Préparation des données d'analogie
Traitement du langage 100 knocks-44: Visualisation des arbres dépendants
100 traitement de langue knock-22: Extraction du nom de la catégorie
100 coups de traitement linguistique (2020): 28
100 Language Processing Knock-26: suppression du balisage accentué
100 traitement de la langue knock-96 (en utilisant Gensim): Extraction du vecteur lié au nom du pays
100 coups de traitement linguistique (2020): 38
100 traitement de la langue frapper 00 ~ 02
100 traitement du langage knock-41: lecture du résultat de l'analyse des dépendances (phrase / dépendance)
100 Language Processing Knock-32 (utilisant des pandas): Prototype de verbe
100 traitement du langage knock-75 (en utilisant scicit-learn): poids de l'identité
100 traitement du langage knock-72 (en utilisant Stanford NLP): Extraction d'identité
100 traitements linguistiques Knock 2020 [00 ~ 39 réponse]
100 langues de traitement knock 2020 [00-79 réponse]
100 traitements linguistiques Knock 2020 [00 ~ 69 réponse]
100 coups de traitement du langage amateur: 17
100 traitements linguistiques Knock 2020 [00 ~ 49 réponse]
100 Traitement du langage Knock-52: Stemming
100 Traitement du langage Knock Chapitre 1
100 coups de langue amateur: 07
100 Language Processing Knock 2020 Chapitre 3
100 coups de traitement du langage amateur: 09
100 coups en traitement du langage amateur: 47
Traitement 100 langues knock-53: Tokenisation
100 coups de traitement du langage amateur: 97
100 traitements linguistiques Knock 2020 [00 ~ 59 réponse]
100 coups de traitement du langage amateur: 67
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
Apprenez facilement 100 traitements linguistiques Knock 2020 avec "Google Colaboratory"
100 coups de traitement du langage avec Python 2015
100 traitement du langage Knock-51: découpage de mots
100 Language Processing Knock Chapitre 1 (Python)
100 Language Processing Knock Chapitre 2 (Python)
Traitement du langage 100 Knock-87: similitude des mots
J'ai essayé 100 traitements linguistiques Knock 2020
100 Language Processing Knock-56: analyse de co-référence
Résolution de 100 traitements linguistiques Knock 2020 (01. "Patatokukashi")
100 coups de traitement du langage amateur: Résumé
100 traitements linguistiques knock-77 (en utilisant scicit-learn): mesure du taux de réponse
Traitement du langage 100 knocks-43: Extraire les clauses contenant la nomenclature liée aux clauses contenant des verbes
100 traitement de la langue knock-42: Affichage de la phrase de la personne concernée et de la personne concernée
100 Language Processing Knock 2020 Chapitre 2: Commandes UNIX
100 traitements de langage avec Python
100 Language Processing Knock Chapitre 1 en Python
100 Language Processing Knock 2020 Chapitre 9: RNN, CNN
[Traitement du langage 100 coups 2020] Chapitre 5: Analyse des dépendances
100 traitement du langage knock-76 (en utilisant scicit-learn): étiquetage
J'ai essayé 100 traitements linguistiques Knock 2020: Chapitre 3
100 traitements de langage avec Python (chapitre 3)
100 Language Processing Knock 2020 Chapitre 6: Apprentissage automatique