Python: texte japonais: caractéristique du discours à partir de la similitude des mots

Connaître le mot similitude

Analyse morphologique du texte parlé

Dans Python: texte japonais: analyse morphologique J'ai appris "lire les données à analyser" et "les bases du prétraitement pour le traitement du langage naturel". Dans cet article, vous utiliserez ce que vous avez appris jusqu'à présent pour apprendre la «méthode de traitement des ensembles de données vocales» qui fait l'objet de l'analyse. En particulier, nous mettrons en œuvre un prétraitement axé sur la similitude des mots.

Le drapeau de cet ensemble de données O Parler ce n'est pas un échec On ne peut pas dire que T est un échec, mais c'est un discours étrange. X Il existe trois types d'énoncés qui semblent clairement étranges.

Ici, nous traiterons en fonction du drapeau de l'énoncé qui n'est pas un échec.

À propos des variables qui apparaissent dans l'exemple

Contenu de la variable df_label_text_O qui extrait uniquement les énoncés non brisés (ligne 49) Ndarray du tableau NumPy qui contient l'index et la colonne.

 0                                1
1 O Excusez-moi, qui êtes-vous?
24 O Est-ce vrai? Aimez-vous le baseball au lycée?
48 O Koshien, non?
...  ..                              ...
2376 O Vraiment?

Contenu de la ligne variable utilisée lors du traitement de l'ensemble de données vocales non interrompues (ligne 62) row utilise tolist () Tableau NumPy ndarray df_label_text_O converti en type liste Python.

[['O', 'Excusez-moi, qui êtes-vous?'], ['O', 'Vraiment. Aimez-vous le baseball au lycée?'], ['O', 'Koshien, non?'], ... ['O', 'Est-ce vrai.']]

Cliquez ici pour un exemple

import os
import json
import pandas as pd
import re
from janome.tokenizer import Tokenizer


#spécifier le répertoire init100
file_path = './6110_nlp_preprocessing_data/init100/'
file_dir = os.listdir(file_path)

#Créez une liste vide pour stocker les indicateurs et les énoncés
label_text = []

#Traitez 10 fichiers JSON un par un
for file in file_dir[:10]:
    #Lecture en mode lecture seule
    r = open(file_path + file, 'r', encoding='utf-8')
    json_data = json.load(r)

    #Tableau de données vocales`turns`Extraire le contenu de l'énoncé et les indicateurs de
    for turn in json_data['turns']:
        turn_index = turn['turn-index'] #Parler tour non
        speaker = turn['speaker'] #ID de l'orateur
        utterance = turn['utterance'] #Contenu du discours
        #Excluez la première ligne car il s'agit d'un énoncé système
        if turn_index != 0:
            #Extraire le contenu du discours d'une personne
            if speaker == 'U':
                u_text = ''
                u_text = utterance
            else:
                a = ''
                for annotate in turn['annotations']:
                    #Extraire le drapeau d'échec
                    a = annotate['breakdown']
                    #Stockez les drapeaux et la parole humaine dans une liste
                    tmp1 = str(a) + '\t' + u_text
                    tmp2 = tmp1.split('\t')
                    label_text.append(tmp2)

#liste`label_text`Vers DataFrame
df_label_text = pd.DataFrame(label_text)

#Supprimer les lignes en double
df_label_text = df_label_text.drop_duplicates()

#Extraire uniquement les énoncés non réduits
df_label_text_O = df_label_text[df_label_text[0] == 'O']

t = Tokenizer()

#Créer un ensemble de données vocales non vide
morpO = []  #Stocker les mots séparés
tmp1 = []
tmp2 = ''

#Lire ligne par ligne
# .values:Lire sauf index et colonne
# .tolist:Convertir le tableau NumPy ndarray en type de liste Python
for row in df_label_text_O.values.tolist():
    #Supprimer les majuscules et les minuscules des nombres et des alphabets avec des expressions régulières
    reg_row = re.sub('[0-9a-zA-Z]+', '', row[1])
    reg_row = reg_row.replace('\n', '')

    #Effectuer une analyse morphologique avec Janome
    for token in t.tokenize(reg_row):
        #Le système de surface des mots`morpO`Veuillez ajouter à
        tmp1.append(token.surface)
        tmp2 = ' '.join(tmp1)
    morpO.append(tmp2)
    tmp1 = []

#Sortie de mots analysés morphologiquement
pd.DataFrame(morpO)

image.png

Qu'est-ce qu'une matrice de document Word?

Il a expliqué que pour analyser les données en langage naturel, les données de mots (données de phrases) devraient être converties en données numériques. Une des méthodes de conversion

Matrice de document Word (terme-Il y a quelque chose appelé matrice de document).

La matrice de document Word est une représentation tabulaire de la fréquence des mots qui apparaissent dans un document.

Les données de mots contenues dans chaque document peuvent être obtenues par analyse morphologique. À partir de là, le nombre d'occurrences de chaque mot est compté et converti en données numériques.

La matrice de document Word est un document mot / colonne dans le sens des lignes ou un document / colonne dans le sens opposé des lignes. Il est exprimé dans un format matriciel dans lequel les mots sont disposés.

image.png

Lorsqu'il y a tous les N types de mots et tous les M documents, on appelle cela une matrice de document Word de N lignes x M colonnes.

Dans la matrice de document Word de la figure, le document 1 contient le mot 1 deux fois, le mot 2 une fois, le mot 3 trois fois, ..., le mot N 0 fois. Indique qu'il apparaîtra.

Pour compter le nombre de fois où un mot apparaît

Collections de bibliothèques standard Python.Counter()Il existe plusieurs méthodes telles que l'utilisation
Ici scikit-learn (Sykit Learn) Count Vectorizer()En utilisant
Voici un exemple de création d'une matrice de document Word.
CountVectorizer()Décompose le texte en mots et compte le nombre de fois où le mot apparaît.
from sklearn.feature_extraction.text import CountVectorizer

# `CountVectorizer()`Générer un convertisseur en utilisant
CV = CountVectorizer()
corpus = ['This is a pen.',
          'That is a bot.',]

# `fit_transform()`alors`corpus`Et convertissez le nombre d'occurrences de mots en un tableau
X = CV.fit_transform(corpus)
print(X)

>>>Résultat de sortie
  (0, 2)    1
  (0, 1)    1
  (0, 4)    1
  (1, 0)    1
  (1, 3)    1
  (1, 1)    1

# `get_feature_names()`Consultez la liste qui contient les mots que vous avez appris
print(CV.get_feature_names())

>>>Résultat de sortie
['bot', 'is', 'pen', 'that', 'this']

#Le nombre d'apparitions comptées`toarray()`Convertir en vecteur et afficher
print(X.toarray())

>>>Résultat de sortie
#ligne:`corpus`Ordre des phrases prononcées en
#Colonne:`get_feature_names()`Ordre des mots confirmé dans
[[0 1 1 0 1]
 [1 1 0 1 0]]

Cliquez ici pour des exemples d'utilisation

import os
import json
import pandas as pd
import numpy as np
import re
from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import CountVectorizer


#spécifier le répertoire init100
file_path = './6110_nlp_preprocessing_data/init100/'
file_dir = os.listdir(file_path)

#Créez une liste vide pour stocker les indicateurs et les énoncés
label_text = []

#Traitez 10 fichiers JSON un par un
for file in file_dir[:10]:
    r = open(file_path + file, 'r', encoding='utf-8')
    json_data = json.load(r)

    #Tableau de données vocales`turns`Extraire le contenu de l'énoncé et les indicateurs de
    for turn in json_data['turns']:
        turn_index = turn['turn-index']
        speaker = turn['speaker']
        utterance = turn['utterance']
        if turn_index != 0:
            if speaker == 'U':
                u_text = ''
                u_text = utterance
            else:
                a = ''
                for annotate in turn['annotations']:
                    a = annotate['breakdown']
                    tmp1 = str(a) + '\t' + u_text
                    tmp2 = tmp1.split('\t')
                    label_text.append(tmp2)

#liste`label_text`Vers DataFrame et supprimer les doublons
df_label_text = pd.DataFrame(label_text)
df_label_text = df_label_text.drop_duplicates()
#Extraire uniquement les énoncés non réduits
df_label_text_O = df_label_text[df_label_text[0] == 'O']

t = Tokenizer()

#Créer un ensemble de données vocales non vide
morpO = []
tmp1 = []
tmp2 = ''

#Supprimer les majuscules et les minuscules des nombres et des alphabets
for row in df_label_text_O.values.tolist():
    reg_row = re.sub('[0-9a-zA-Z]+', '', row[1])
    reg_row = reg_row.replace('\n', '')
    #Analyse morphologique avec Janome
    for token in t.tokenize(reg_row):
        tmp1.append(token.surface)
        tmp2 = ' '.join(tmp1)
    morpO.append(tmp2)
    tmp1 = []

#Convertir du format de liste au tableau NumPy (car le tableau est plus rapide)
morpO_array = np.array(morpO)

#Comptez le nombre de fois qu'un mot apparaît
cntvecO = CountVectorizer()

#Apprenez et convertissez les occurrences de mots en tableau
morpO_cntvecs = cntvecO.fit_transform(morpO_array)

#Convertir en tableau ndarray
morpO_cntarray = morpO_cntvecs.toarray()

#Afficher le nombre d'occurrences de mots au format DataFrame
#colonnes: mots séparés
#index (ligne): données vocales d'origine
pd.DataFrame(morpO_cntarray, columns=cntvecO.get_feature_names(),
             index=morpO).head(20)

image.png

Note de mot d'une lettre

Par défaut, les mots à une seule lettre ne sont pas comptés. Il y a des mots en japonais qui ont un sens même dans une seule lettre, alors soyez prudent lorsque vous traitez avec le japonais. Pour compter même les mots d'une lettre, spécifiez token_pattern = '(? U) \ b \ w + \ b'in CountVectorizer ().

CountVectorizer(token_pattern='(?u)\\b\\w+\\b')

Qu'est-ce qu'une matrice de document Word pondérée?

Dans une matrice de document Word qui a le nombre d'occurrences (fréquence) d'un mot comme valeur Les mots qui apparaissent universellement (par exemple, "I" et "desu") ont tendance à apparaître plus fréquemment dans tout document.

En revanche, les mots qui n'apparaissent que dans des documents spécifiques apparaissent moins fréquemment. Il devient difficile de caractériser chaque document à partir de mots. Par conséquent, dans la matrice de document Word

Dans TF (fréquence de terme)
Fréquence inverse des documents multipliée par IDF (fréquence inverse des documents)
TF-Les valeurs IDF sont souvent utilisées.

La valeur IDF d'un mot peut être calculée par log (nombre total de documents / nombre de documents dans lesquels un mot apparaît) + 1. Par exemple, si un mot est inclus dans 3 documents sur 4 La valeur IDF est log (4/3) + 1 ≒ 1,1 Les mots qui n'apparaissent que dans un document spécifique ont une valeur IDF plus élevée.

Une valeur IDF élevée est une caractéristique du document, car le mot est d'une grande importance.

Vous pouvez calculer l'IDF à partir du TF et calculer la valeur TF-IDF en multipliant le TF par l'IDF.

Ci-dessous est TfidfVectorizer()A été utilisé

Voici un exemple de création d'une matrice de document Word pondérée basée sur la valeur TF-IDF.

import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer

#Affichage après la virgule décimale avec 2 nombres valides
np.set_printoptions(precision=2)
docs = np.array([
    "Blanc noir rouge", "Blanc blanc noir", "Rouge noir"
])

# `TfidfVectorizer()`Générer un convertisseur en utilisant
vectorizer = TfidfVectorizer(use_idf=True, token_pattern="(?u)\\b\\w+\\b")

# `fit_transform()`alors`docs`Et convertissez le nombre d'occurrences de mots pondérés en un tableau
vecs = vectorizer.fit_transform(docs)
print(vecs.toarray())
# >>Résultat de sortie
[[ 0.62  0.62  0.48]
[ 0.93  0.    0.36]
[ 0.    0.79  0.61]]
①vectorizer = TfidfVectorizer()alors
Génère un convertisseur qui effectue une représentation vectorielle (quantification des mots).

②use_idf=S'il est défini sur False, seul tf sera pondéré.

③vectorizer.fit_transform()Convertit le document en vecteur.
L'argument est un tableau séparé (divisé) par des espaces blancs.

④toarray()Convertit la sortie en un tableau NumPy ndarray.
np.set_printoptions()Est une fonction qui définit le format d'affichage du tableau NumPy.
print()La valeur d'origine ne change pas avec le paramètre qui n'est valide que lors de l'affichage de la valeur avec.

Précision de l'argument=Spécifiez le nombre de chiffres à afficher après la virgule décimale dans.

Cliquez ici pour des exemples d'utilisation

import os
import json
import pandas as pd
import numpy as np
import re
from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import TfidfVectorizer


#spécifier le répertoire init100
file_path = './6110_nlp_preprocessing_data/init100/'
file_dir = os.listdir(file_path)

#Créez une liste vide pour stocker les indicateurs et les énoncés
label_text = []

#Traitez 10 fichiers JSON un par un
for file in file_dir[:10]:
    r = open(file_path + file, 'r', encoding='utf-8')
    json_data = json.load(r)

    #Tableau de données vocales`turns`Extraire le contenu de l'énoncé et les indicateurs de
    for turn in json_data['turns']:
        turn_index = turn['turn-index']
        speaker = turn['speaker']
        utterance = turn['utterance']
        if turn_index != 0:
            if speaker == 'U':
                u_text = ''
                u_text = utterance
            else:
                a = ''
                for annotate in turn['annotations']:
                    a = annotate['breakdown']
                    tmp1 = str(a) + '\t' + u_text
                    tmp2 = tmp1.split('\t')
                    label_text.append(tmp2)

#liste`label_text`Vers DataFrame et supprimer les doublons
df_label_text = pd.DataFrame(label_text)
df_label_text = df_label_text.drop_duplicates()
#Extraire uniquement les énoncés non réduits
df_label_text_O = df_label_text[df_label_text[0] == 'O']

t = Tokenizer()

#Créer un ensemble de données d'énoncés qui n'est pas un repli vide
morpO = []
tmp1 = []
tmp2 = ''

#Supprimer les majuscules et les minuscules des nombres et des alphabets
for row in df_label_text_O.values.tolist():
    reg_row = re.sub('[0-9a-zA-Z]+', '', row[1])
    reg_row = reg_row.replace('\n', '')
    #Analyse morphologique avec Janome
    for token in t.tokenize(reg_row):
        tmp1.append(token.surface)
        tmp2 = ' '.join(tmp1)
    morpO.append(tmp2)
    tmp1 = []

#Convertir du format de liste au tableau NumPy (car le tableau est plus rapide)
morpO_array = np.array(morpO)

#(1) Générer un convertisseur qui effectue une représentation vectorielle
tfidf_vecO = TfidfVectorizer(use_idf=True)

#② Convertir les mots en représentation vectorielle
morpO_tfidf_vecs = tfidf_vecO.fit_transform(morpO_array)

#③ Convertir en tableau ndarray
morpO_tfidf_array = morpO_tfidf_vecs.toarray()

#Afficher les mots (représentation vectorielle) au format DataFrame
pd.DataFrame(morpO_tfidf_array, columns=tfidf_vecO.get_feature_names(), 
             index=morpO).head(20)

image.png

Calculer la similitude des mots (corrélation)

Une quantité d'entités est une entité différente des autres données dont les données disposent.

Dans la matrice de document Word créée par CountVectorizer (), le nombre de fois qu'un mot apparaît Dans la matrice de document Word créée par TfidfVectorizer (), la valeur TF-IDF d'un mot est utilisée comme quantité de caractéristiques du mot.

Par exemple, pour distinguer si l'objet de l'image est un chien ou un chat Tout d'abord, vous remarquerez peut-être sans le savoir la forme de vos oreilles.

Dans ce cas, l'oreille (la zone y compris) est la quantité de fonction. Le problème de classification des documents utilise chaque mot comme une caractéristique pour créer un modèle d'apprentissage supervisé.

Voici à quel point les deux mots sont similaires, ce qui est différent de ce qui précède

En d'autres termes, créez un modèle d'apprentissage non supervisé avec une fonctionnalité similaire.

Une méthode familière pour mesurer la similitude est le coefficient de corrélation.

De plus, la similarité cosinus qui mesure la similitude entre les vecteurs
Le coefficient de Jaccard, qui mesure la similitude entre les ensembles, est célèbre.

Ici, la méthode corr () de pandas.DataFrame est utilisée pour trouver la similitude. Calculez le coefficient de corrélation entre chaque colonne.

La méthode corr () calcule les colonnes dont le type de données est numérique ou booléen. Les chaînes et les valeurs manquantes NaN sont exclues.

corr = DataFrame.corr()

Dans l'argument de corr (), spécifiez la méthode de calcul du coefficient de corrélation parmi les suivantes.

'pearson': Coefficient de corrélation du facteur produit de Pearson (par défaut)
'kendall': Coefficient de corrélation de rang de Kendall
'spearman': Coefficient de corrélation de rang de Spearman

Cliquez ici pour des exemples d'utilisation

import os
import json
import pandas as pd
import numpy as np
import re
from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import TfidfVectorizer


#spécifier le répertoire init100
file_path = './6110_nlp_preprocessing_data/init100/'
file_dir = os.listdir(file_path)

#Créez une liste vide pour stocker les indicateurs et les énoncés
label_text = []

#Traitez 10 fichiers JSON un par un
for file in file_dir[:10]:
    r = open(file_path + file, 'r', encoding='utf-8')
    json_data = json.load(r)

    #Tableau de données vocales`turns`Extraire le contenu de l'énoncé et les indicateurs de
    for turn in json_data['turns']:
        turn_index = turn['turn-index']
        speaker = turn['speaker']
        utterance = turn['utterance']
        if turn_index != 0:
            if speaker == 'U':
                u_text = ''
                u_text = utterance
            else:
                a = ''
                for annotate in turn['annotations']:
                    a = annotate['breakdown']
                    tmp1 = str(a) + '\t' + u_text
                    tmp2 = tmp1.split('\t')
                    label_text.append(tmp2)

#liste`label_text`Vers DataFrame et supprimer les doublons
df_label_text = pd.DataFrame(label_text)
df_label_text = df_label_text.drop_duplicates()
#Extraire uniquement les énoncés non réduits
df_label_text_O = df_label_text[df_label_text[0] == 'O']

t = Tokenizer()

#Créer un ensemble de données vocales non vide
morpO = []
tmp1 = []
tmp2 = ''

#Supprimer les majuscules et les minuscules des nombres et des alphabets
for row in df_label_text_O.values.tolist():
    reg_row = re.sub('[0-9a-zA-Z]+', '', row[1])
    reg_row = reg_row.replace('\n', '')
    #Analyse morphologique avec Janome
    for token in t.tokenize(reg_row):
        tmp1.append(token.surface)
        tmp2 = ' '.join(tmp1)
    morpO.append(tmp2)
    tmp1 = []

# TF-Créer une matrice de document Word pondérée par valeur IDF
morpO_array = np.array(morpO)
tfidf_vecO = TfidfVectorizer(use_idf=True)
morpO_tfidf_vecs = tfidf_vecO.fit_transform(morpO_array)
morpO_tfidf_array = morpO_tfidf_vecs.toarray()

#Convertir le nombre d'occurrences de mots au format DataFrame
dtmO = pd.DataFrame(morpO_tfidf_array, columns=tfidf_vecO.get_feature_names(), 
             index=morpO).head(20)

#Créer une matrice de corrélation
corr_matrixO = dtmO.corr().abs()
# `.abs()`Est une méthode pour trouver la valeur absolue
#Affichage de la matrice de corrélation
corr_matrixO

image.png

Connaître les caractéristiques de la parole à partir de la similitude des mots

Créer une liste de similitudes

A partir de là, par analyse de réseau en utilisant le coefficient de corrélation des deux mots créés dans la section précédente comme quantité de caractéristiques. Nous effectuerons une analyse quantitative.

Convertissez le coefficient de corrélation du format matriciel au format liste pour l'analyse de réseau

Pour convertir le format de matrice en format de liste
pandas.Pile DataFrame()Utilisez la méthode.
from pandas import DataFrame

#Préparer DataFrame
df=DataFrame([[0.1,0.2,0.3],[0.4,'NaN',0.5]],
             columns=['test1','test2','test3'],
             index=['AA','BB'])
print(df)

# >>>Résultat de sortie
      test1      test2      test3
AA       0.1       0.2       0.3
BB       0.4       NaN       0.5
# stack :Conversion de colonne en ligne
print(df.stack())

# >>>Résultat de sortie
AA   test1    0.1
     test2    0.2
     test3    0.3
BB   test1    0.4
     test2    NaN
     test3    0.5
#unstack: conversion de ligne en colonne
print(df.unstack())

# >>>Résultat de sortie
test1  AA    0.1
       BB    0.4
test2  AA    0.2
       BB    NaN
test3  AA    0.3
       BB    0.5

Cliquez ici pour des exemples d'utilisation

import os
import json
import pandas as pd
import numpy as np
import re
from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import TfidfVectorizer


#spécifier le répertoire init100
file_path = './6110_nlp_preprocessing_data/init100/'
file_dir = os.listdir(file_path)

#Créez une liste d'indicateurs et d'énoncés
label_text = []
for file in file_dir[:10]:
    r = open(file_path + file, 'r', encoding='utf-8')
    json_data = json.load(r)
    for turn in json_data['turns']:
        turn_index = turn['turn-index']
        speaker = turn['speaker']
        utterance = turn['utterance']
        if turn_index != 0:
            if speaker == 'U':
                u_text = ''
                u_text = utterance
            else:
                a = ''
                for annotate in turn['annotations']:
                    a = annotate['breakdown']
                    tmp1 = str(a) + '\t' + u_text
                    tmp2 = tmp1.split('\t')
                    label_text.append(tmp2)

#Supprimer les doublons et extraire uniquement les énoncés non cassés
df_label_text = pd.DataFrame(label_text)
df_label_text = df_label_text.drop_duplicates()
df_label_text_O = df_label_text[df_label_text[0] == 'O']

#Analyse morphologique par Janome
t = Tokenizer()

morpO = []
tmp1 = []
tmp2 = ''

for row in df_label_text_O.values.tolist():
    reg_row = re.sub('[0-9a-zA-Z]+', '', row[1])
    reg_row = reg_row.replace('\n', '')
    for token in t.tokenize(reg_row):
        tmp1.append(token.surface)
        tmp2 = ' '.join(tmp1)
    morpO.append(tmp2)
    tmp1 = []

# TF-Créer une matrice de document Word pondérée par valeur IDF
morpO_array = np.array(morpO)
tfidf_vecO = TfidfVectorizer(use_idf=True)
morpO_tfidf_vecs = tfidf_vecO.fit_transform(morpO_array)
morpO_tfidf_array = morpO_tfidf_vecs.toarray()

#Convertir au format DataFrame et créer une matrice de corrélation
dtmO = pd.DataFrame(morpO_tfidf_array, columns=tfidf_vecO.get_feature_names(), 
             index=morpO)
corr_matrixO = dtmO.corr().abs()

#Matrice de corrélation`corr_matrixO`Conversion de la direction de la colonne à la direction de la ligne
corr_stackO = corr_matrixO.stack()
index = pd.Series(corr_stackO.index.values)
value = pd.Series(corr_stackO.values)

#Le coefficient de corrélation est 0.5 ou plus 1.Extraire moins de 0
tmp3 = [] #Le coefficient de corrélation est 0.5 ou plus 1.Liste des valeurs d'index avec des valeurs inférieures à 0
tmp4 = [] #Le coefficient de corrélation est 0.5 ou plus 1.Liste des valeurs de valeur inférieures à 0

for i in range(0, len(index)):
    if value[i] >= 0.5 and value[i] < 1.0:
        tmp1 = str(index[i][0]) + ' ' + str(index[i][1])
        tmp2 = [s for s in tmp1.split()]
        tmp3.append(tmp2)
        tmp4 = np.append(tmp4, value[i])

tmp3 = pd.DataFrame(tmp3)
tmp3 = tmp3.rename(columns={0: 'node1', 1: 'node2'})
tmp4 = pd.DataFrame(tmp4)
tmp4 = tmp4.rename(columns={0: 'weight'})

# DataFrame`tmp3`Quand`tmp4`Veuillez vous connecter dans le sens horizontal
df_corlistO = pd.concat([tmp3, tmp4], axis=1)

#Afficher le DataFrame créé
df_corlistO.head(20)

image.png

Créer un réseau de similitude

La mise en réseau est une manière d'exprimer la relation entre les objets. Un exemple bien connu est le réseau d'amitiés sur SNS.

Dans la structure du réseau
La cible est un nœud
Les relations sont représentées par des arêtes.

Les bords ont du poids et sont intimes dans les réseaux d'amitié. Plus vous êtes proche, plus la valeur de poids est élevée.

En outre, les cartes routières, les réseaux aéronautiques et les relations de cooccurrence / similaires de mots peuvent être exprimés dans des réseaux.

Pour visualiser un groupe de langages qui n'ont pas de concept de direction sur les bords et qui ne sont pas liés, comme la liste de similarité créée dans la section précédente.

Utilisez un graphe non dirigé (ou un réseau non dirigé).

Le graphe pondéré est également appelé réseau.

Un graphe non orienté est un graphe dans lequel les arêtes qui composent le réseau n'ont pas de direction. Au contraire, si l'arête est directionnelle

C'est ce qu'on appelle un graphe orienté (ou réseau orienté).

Création d'un graphe non dirigé (réseau non dirigé)

Python a une bibliothèque appelée NetworkX. Cette section utilise cette bibliothèque pour visualiser la liste de similarité créée dans la section précédente.

#Bibliothèque`NetworkX`Importer
import networkx as nx

#Créer un graphique non orienté
network = nx.from_pandas_edgelist(df, source='source', target='target', edge_attr=None, create_using=None)
① df: nom DataFrame de Pandas qui est la source du graphique

② source: nom de colonne du nœud source
Spécifiez avec str (type chaîne de caractères) ou int (type entier)

③ target: nom de colonne du nœud cible
Spécifiez avec str ou int

④edge_attr: Bord (poids) de chaque donnée
Spécifiez avec str ou int, iterable, True

⑤create_en utilisant: Type de graphique (facultatif)

Graphique non dirigé: nx.Graphique (par défaut)
Graphique dirigé: nx.DiGraph

Visualisation du graphe (réseau)

#Bibliothèque`Matplotlib`De`pyplot`Importer
from matplotlib import pyplot

#Calculez la position d'affichage optimale pour chaque nœud
pos = nx.spring_layout(graph)

#Dessinez un graphique
nx.draw_networkx(graph, pos)

#Afficher des graphiques à l'aide de Matplotlib
plt.show()

Cliquez ici pour des exemples d'utilisation

import os
import json
import pandas as pd
import numpy as np
import re
from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import TfidfVectorizer
import networkx as nx
import matplotlib.pyplot as plt


#spécifier le répertoire init100
file_path = './6110_nlp_preprocessing_data/init100/'
file_dir = os.listdir(file_path)

#Créez une liste d'indicateurs et d'énoncés
label_text = []
for file in file_dir[:10]:
    r = open(file_path + file, 'r', encoding='utf-8')
    json_data = json.load(r)
    for turn in json_data['turns']:
        turn_index = turn['turn-index']
        speaker = turn['speaker']
        utterance = turn['utterance']
        if turn_index != 0:
            if speaker == 'U':
                u_text = ''
                u_text = utterance
            else:
                a = ''
                for annotate in turn['annotations']:
                    a = annotate['breakdown']
                    tmp1 = str(a) + '\t' + u_text
                    tmp2 = tmp1.split('\t')
                    label_text.append(tmp2)

#Supprimer les doublons et extraire uniquement les énoncés non cassés
df_label_text = pd.DataFrame(label_text)
df_label_text = df_label_text.drop_duplicates()
df_label_text_O = df_label_text[df_label_text[0] == 'O']

#Analyse morphologique par Janome
t = Tokenizer()

morpO = []
tmp1 = []
tmp2 = ''

for row in df_label_text_O.values.tolist():
    reg_row = re.sub('[0-9a-zA-Z]+', '', row[1])
    reg_row = reg_row.replace('\n', '')
    for token in t.tokenize(reg_row):
        tmp1.append(token.surface)
        tmp2 = ' '.join(tmp1)
    morpO.append(tmp2)
    tmp1 = []

# TF-Créer une matrice de document Word pondérée par valeur IDF
morpO_array = np.array(morpO)
tfidf_vecO = TfidfVectorizer(use_idf=True)
morpO_tfidf_vecs = tfidf_vecO.fit_transform(morpO_array)
morpO_tfidf_array = morpO_tfidf_vecs.toarray()

#Convertir au format DataFrame et créer une matrice de corrélation
dtmO = pd.DataFrame(morpO_tfidf_array)

corr_matrixO = dtmO.corr().abs()

#Création d'un ensemble de données vocales non interrompu
corr_stackO = corr_matrixO.stack()
index = pd.Series(corr_stackO.index.values)
value = pd.Series(corr_stackO.values)

tmp3 = []
tmp4 = []
for i in range(0, len(index)):
    if value[i] >= 0.5 and value[i] < 1.0:
        tmp1 = str(index[i][0]) + ' ' + str(index[i][1])
        tmp2 = [int(s) for s in tmp1.split()]
        tmp3.append(tmp2)
        tmp4 = np.append(tmp4, value[i])

tmp3 = pd.DataFrame(tmp3)
tmp3 = tmp3.rename(columns={0: 'node1', 1: 'node2'})
tmp4 = pd.DataFrame(tmp4)
tmp4 = tmp4.rename(columns={0: 'weight'})
df_corlistO = pd.concat([tmp3, tmp4], axis=1)

#① Créez un graphe non orienté
G_corlistO = nx.from_pandas_edgelist(df_corlistO, 'node1', 'node2', ['weight'])

#② Visualisez le graphique créé
#Paramètres de mise en page
pos = nx.spring_layout(G_corlistO)
nx.draw_networkx(G_corlistO, pos)
plt.show()

image.png

Fonctionnalités du réseau de similarité

Comme le montre le graphique visualisé dans la section précédente, le réseau réel a de nombreuses structures compliquées. À première vue, il est difficile de saisir les caractéristiques.

Dans un tel cas, saisissez les caractéristiques quantitativement avec un certain indice. Certains des indicateurs servent à comprendre l'ensemble du réseau (mondial). Il y a aussi des choses (locales) qui se concentrent sur un certain nœud et le saisissent.

Voici quelques exemples d'indicateurs couramment utilisés:

Ordre: indique le nombre d'arêtes du nœud.
Distribution de l'ordre: représente un histogramme du nombre de nœuds avec un certain ordre.
Coefficient de cluster: indique à quel point les nœuds sont connectés.
Longueur de l'itinéraire: distance d'un nœud à un autre.
Centralité: représente le degré auquel un nœud joue un rôle central dans le réseau.

Maintenant, pour le réseau créé dans la section précédente, calculez le coefficient de cluster et la centralité de la médiation. Regardons les fonctionnalités.

Dans ce réseau Le coefficient de cluster est la densité de connexion entre les mots La centralité de la médiation représente le degré de plaque tournante d'un mot dans un réseau.

Comparaison du coefficient de cluster moyen pour chaque réseau, parole non défaillante et parole interrompue Vous pouvez voir que les mots du discours qui sont brisés sont plus étroitement liés.

Aussi, si vous comparez les 5 premiers mots avec une centralité de médiation élevée Les mots concernant les vacances d'Obon sont inclus dans les énoncés non condensés On peut en déduire que les mots de baseball tôt le matin jouent un rôle central dans le discours effondré.

① Parler ce n'est pas un échec
<Coefficient de cluster moyen> 0.051924357
<Top 5 des mots à forte centralité de médiation>
Vacances, Obon, ici, peu, aube

② Une histoire qui est cassée
<Coefficient de cluster moyen> 0.069563257
<Top 5 des mots à forte centralité de médiation>
Cette fois, jouons au baseball, tôt le matin, il

Cliquez ici pour des exemples d'utilisation

import os
import json
import pandas as pd
import numpy as np
import re
from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import TfidfVectorizer
import networkx as nx
import matplotlib.pyplot as plt


#spécifier le répertoire init100
file_path = './6110_nlp_preprocessing_data/init100/'
file_dir = os.listdir(file_path)

#Créez une liste d'indicateurs et d'énoncés
label_text = []
for file in file_dir[:10]:
    r = open(file_path + file, 'r', encoding='utf-8')
    json_data = json.load(r)
    for turn in json_data['turns']:
        turn_index = turn['turn-index']
        speaker = turn['speaker']
        utterance = turn['utterance']
        if turn_index != 0:
            if speaker == 'U':
                u_text = ''
                u_text = utterance
            else:
                a = ''
                for annotate in turn['annotations']:
                    a = annotate['breakdown']
                    tmp1 = str(a) + '\t' + u_text
                    tmp2 = tmp1.split('\t')
                    label_text.append(tmp2)

#Supprimer les doublons et extraire uniquement les énoncés non cassés
df_label_text = pd.DataFrame(label_text)
df_label_text = df_label_text.drop_duplicates()
df_label_text_O = df_label_text[df_label_text[0] == 'O']

#Analyse morphologique par Janome
t = Tokenizer()

morpO = []
tmp1 = []
tmp2 = ''

for row in df_label_text_O.values.tolist():
    reg_row = re.sub('[0-9a-zA-Z]+', '', row[1])
    reg_row = reg_row.replace('\n', '')
    for token in t.tokenize(reg_row):
        tmp1.append(token.surface)
        tmp2 = ' '.join(tmp1)
    morpO.append(tmp2)
    tmp1 = []

# TF-Créer une matrice de document Word pondérée par valeur IDF
morpO_array = np.array(morpO)
tfidf_vecO = TfidfVectorizer(use_idf=True)
morpO_tfidf_vecs = tfidf_vecO.fit_transform(morpO_array)
morpO_tfidf_array = morpO_tfidf_vecs.toarray()

#Convertir au format DataFrame et créer une matrice de corrélation
dtmO = pd.DataFrame(morpO_tfidf_array, columns=tfidf_vecO.get_feature_names(), 
             index=morpO)
corr_matrixO = dtmO.corr().abs()

#Création d'un ensemble de données vocales non interrompu
corr_stackO = corr_matrixO.stack()
index = pd.Series(corr_stackO.index.values)
value = pd.Series(corr_stackO.values)

tmp3 = []
tmp4 = []
for i in range(0, len(index)):
    if value[i] >= 0.5 and value[i] < 1.0:
        tmp1 = str(index[i][0]) + ' ' + str(index[i][1])
        tmp2 = [s for s in tmp1.split()]
        tmp3.append(tmp2)
        tmp4 = np.append(tmp4, value[i])

tmp3 = pd.DataFrame(tmp3)
tmp3 = tmp3.rename(columns={0: 'node1', 1: 'node2'})
tmp4 = pd.DataFrame(tmp4)
tmp4 = tmp4.rename(columns={0: 'weight'})
df_corlistO = pd.concat([tmp3, tmp4], axis=1)

#Créer un graphique non dirigé
G_corlistO = nx.from_pandas_edgelist(df_corlistO, 'node1', 'node2', ['weight'])

#Pour les ensembles de données vocales non interrompues
#① Calcul du coefficient de cluster moyen
print('Coefficient de cluster moyen')
print(nx.average_clustering(G_corlistO, weight='weight'))
print()

#② Calcul de la centralité de la médiation
bc = nx.betweenness_centrality(G_corlistO, weight='weight')
print('Centralité de la médiation')
for k, v in sorted(bc.items(), key=lambda x: -x[1]):
    print(str(k) + ': ' + str(v))

image.png

Calcul du coefficient de cluster moyen

Plus le coefficient de cluster moyen de tous les nœuds est élevé, plus le réseau est dense. La moyenne des coefficients de cluster est calculée à l'aide de nx.average_clustering ().

nx.average_clustering(G, weight=None)
①G
Spécifiez le graphique.
(Graphe non dirigé G créé dans la section précédente_corlistO)

②weight
Spécifie l'arête avec le nombre à utiliser comme poids. Si aucun, le poids de chaque arête sera de 1.

Calcul de la centralité de la médiation

Il est déterminé par le nombre de nœuds inclus dans l'itinéraire le plus court entre tous les nœuds. En d'autres termes, les nœuds les plus utilisés pour transmettre efficacement des informations sont plus intermédiaires et centraux.

nx.betweenness_centrality(G, weight=None)
①G
Spécifiez le graphique.
(Graphe non dirigé G créé dans la section précédente_corlistO)

②weight
Spécifie l'arête avec le nombre à utiliser comme poids. Si aucun, tous les poids de bord sont considérés comme égaux.

Extraction de sujets de réseau de similarité

Un réseau est composé de plusieurs réseaux partiels (= communautés). Chaque nœud de la communauté est caractérisé par le fait qu'il est étroitement connecté à la périphérie.

Si vous supprimez les bords clairsemés d'un réseau, vous pouvez le diviser en réseaux partiels. En d'autres termes, la communauté peut être extraite = les réseaux à forte similitude peuvent être extraits.

Pour diviser le réseau

Nous utilisons un index appelé Modularité.

Modularité De "Rapport du nombre d'arêtes dans la communauté au nombre total d'arêtes dans un réseau" "Pour l'ordre total de tous les nœuds dans un réseau (égal au nombre d'arêtes dans le réseau x 2) Quantifiez la qualité de la scission en soustrayant le «pourcentage total de l'ordre des nœuds dans la communauté».

Plus la valeur de modularité est élevée, plus les nœuds de la communauté sont serrés.

Extrayons maintenant la communauté en utilisant la modularité. Énoncés intacts et énoncés brisés dans leurs réseaux respectifs Quand j'ai vérifié les mots de la communauté avec le plus grand nombre de nœuds, j'ai obtenu les résultats suivants.

① Parler ce n'est pas un échec
Obon, fin, juste, repos, coupe, problème, peu, retour à la maison, oubliant, paresseux, aube, continuer, vacances consécutives, concentration

② Une histoire qui est cassée
S'il vous plaît, à propos de, à propos de, puis prenez, qui, dépendance, bien sûr, bien, travail, biais, division, danger, attendez, esprit, temps, nutrition, insouciance, sommeil, repas

Pour les énoncés non réduits, par exemple, "J'ai beaucoup de vacances à Obon et j'ai du mal à rentrer chez moi" Vous pouvez deviner qu'il y a un sujet.

Les énoncés qui sont brisés comprennent, par exemple, «essayez de ne pas biaiser la nutrition de l'alimentation» et «dormez suffisamment». Il semble y avoir un sujet.

De même, vous devriez être capable de deviner à partir des mots quels sujets sont inclus dans d'autres communautés.

Extraction de communautés en utilisant la modularité

greedy_modularity_communities(G, weight=None)
①G
Spécifiez le graphique.
(Graphe non dirigé G créé dans la section précédente_corlistO)

②weight
Spécifie l'arête avec le nombre à utiliser comme poids. Si aucun, tous les poids de bord sont considérés comme égaux.

Cliquez ici pour des exemples d'utilisation

import os
import json
import pandas as pd
import numpy as np
import re
from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import TfidfVectorizer
import networkx as nx
import matplotlib.pyplot as plt
from networkx.algorithms.community import greedy_modularity_communities


#spécifier le répertoire init100
file_path = './6110_nlp_preprocessing_data/init100/'
file_dir = os.listdir(file_path)

#Créez une liste d'indicateurs et d'énoncés
label_text = []
for file in file_dir[:20]:
    r = open(file_path + file, 'r', encoding='utf-8')
    json_data = json.load(r)
    for turn in json_data['turns']:
        turn_index = turn['turn-index']
        speaker = turn['speaker']
        utterance = turn['utterance']
        if turn_index != 0:
            if speaker == 'U':
                u_text = ''
                u_text = utterance
            else:
                a = ''
                for annotate in turn['annotations']:
                    a = annotate['breakdown']
                    tmp1 = str(a) + '\t' + u_text
                    tmp2 = tmp1.split('\t')
                    label_text.append(tmp2)

#Supprimer les doublons et extraire uniquement les énoncés non cassés
df_label_text = pd.DataFrame(label_text)
df_label_text = df_label_text.drop_duplicates()
df_label_text_O = df_label_text[df_label_text[0] == 'O']

#Analyse morphologique par Janome
t = Tokenizer()

morpO = []
tmp1 = []
tmp2 = ''

for row in df_label_text_O.values.tolist():
    reg_row = re.sub('[0-9a-zA-Z]+', '', row[1])
    reg_row = reg_row.replace('\n', '')
    for token in t.tokenize(reg_row):
        tmp1.append(token.surface)
        tmp2 = ' '.join(tmp1)
    morpO.append(tmp2)
    tmp1 = []

# TF-Créer une matrice de document Word pondérée par valeur IDF
morpO_array = np.array(morpO)
tfidf_vecO = TfidfVectorizer(use_idf=True)
morpO_tfidf_vecs = tfidf_vecO.fit_transform(morpO_array)
morpO_tfidf_array = morpO_tfidf_vecs.toarray()

#Convertir au format DataFrame et créer une matrice de corrélation
dtmO = pd.DataFrame(morpO_tfidf_array, columns=tfidf_vecO.get_feature_names(), 
             index=morpO)
corr_matrixO = dtmO.corr().abs()

#Création d'un ensemble de données vocales non interrompu
corr_stackO = corr_matrixO.stack()
index = pd.Series(corr_stackO.index.values)
value = pd.Series(corr_stackO.values)

tmp3 = []
tmp4 = []
for i in range(0, len(index)):
    if value[i] >= 0.5 and value[i] < 1.0:
        tmp1 = str(index[i][0]) + ' ' + str(index[i][1])
        tmp2 = [s for s in tmp1.split()]
        tmp3.append(tmp2)
        tmp4 = np.append(tmp4, value[i])

tmp3 = pd.DataFrame(tmp3)
tmp3 = tmp3.rename(columns={0: 'node1', 1: 'node2'})
tmp4 = pd.DataFrame(tmp4)
tmp4 = tmp4.rename(columns={0: 'weight'})
df_corlistO = pd.concat([tmp3, tmp4], axis=1)

#Créer un graphique non dirigé
G_corlistO = nx.from_pandas_edgelist(df_corlistO, 'node1', 'node2', ['weight'])

#Pour les ensembles de données vocales non interrompues
#Extraction communautaire
cm_corlistO = list(greedy_modularity_communities(G_corlistO, weight='weight'))

#Afficher les nœuds appartenant à chaque communauté
cm_corlistO

image.png

Recommended Posts

Python: texte japonais: caractéristique du discours à partir de la similitude des mots
Python: texte japonais: caractéristique de la parole à partir de la continuité des mots
[Python] Récupérez le texte de la loi à partir de l'API e-GOV law
Python: texte japonais: analyse morphologique
[Python] Extrayez des données texte à partir de données XML de 10 Go ou plus.
Existence du point de vue de Python
Extraire du texte d'images avec Python
Extraction de sujets de texte japonais 1 Bases
Parlez du texte japonais avec OpenJTalk + python
De l'introduction de JUMAN ++ à l'analyse morphologique du japonais avec Python
[Python] Formater du texte plein de codes de saut de ligne copiés à partir d'un PDF bien
Recherche de synonymes dans la liste de mots (csv) par Python Japanese WordNet
Extraction de thèmes de texte japonais 2 Édition pratique
Comparaison des modules de conversion japonais en Python3
Notes d'apprentissage depuis le début de Python 1
[Python] Calcul de la similarité d'image (coefficient de dés)
Extraire du texte japonais d'un PDF avec PDFMiner
Text mining avec Python ② Visualisation avec Word Cloud
[Python] Localisation japonaise de matplotlib sur Ubuntu
Notes d'apprentissage depuis le début de Python 2
Traduction japonaise: PEP 20 - Le Zen de Python
[Version japonaise] Jugement de la similitude des mots pour les mots polynomiaux utilisant ELMo et BERT
Récupérer le contenu de git diff depuis python
Essayez-le avec JupyterLab en Python japonais Word Cloud.
Un mémorandum sur l'appel de Python à partir de Common Lisp
Appelez la bibliothèque Python pour la normalisation de texte depuis MATLAB
Utilisons différentes versions de SQLite3 de Python3!
[Python] Get the day (anglais et japonais)