[PYTHON] Faisons un clustering qui donne une belle vue d'ensemble de l'ensemble de données texte

Que présenter dans cet article

--Introduction de packages qui favorisent le clustering tout en utilisant plusieurs méthodes de clustering ensemble [https://pypi.org/project/flexible-clustering-tree/)

Pourquoi avez-vous besoin de clustering?

Il existe de nombreuses occasions où vous rencontrez de nouvelles données lorsque vous êtes impliqué dans des recherches ou des travaux liés aux données.

Le contenu des nouvelles données n'étant pas clair en premier lieu, il faut d'abord comprendre les données avant d'envisager des politiques de recherche et des politiques d'analyse.

Le clustering est nécessaire dans de tels cas. [^ 1]

Par exemple, quel type de cas d'utilisation de clustering avez-vous?

J'ai travaillé dans le traitement du langage naturel dans le domaine de la recherche. La PNL dans l'industrie de la recherche peut être appelée text mining.

L'industrie de la recherche repose sur __ l'agrégation de données__. L'idée de base est de créer un rapport d'enquête basé sur les données agrégées et les connaissances de l'industrie.

Et, bien sûr, les données textuelles doivent également être agrégées. Dans de nombreux cas, une "étiquette appropriée aux fins de l'enquête" est utilisée comme unité d'agrégation.

Il n'y a pas de problème si le "label approprié à des fins d'enquête" est connu dès le début.

Cependant, dans le cas de nouvelles données textuelles, "Quel type d'étiquette dois-je utiliser en premier lieu? Je ne sais pas", vous devez d'abord considérer l'étiquette.

Dans un tel cas, il sera plus facile de penser aux étiquettes si vous pouvez obtenir un aperçu rapide des données par clustering.

N'y a-t-il pas une méthode autre que le clustering?

Bien entendu, des approches autres que le clustering sont également possibles.

Par exemple, l'approche suivante est possible.

  1. Échantillonnez et étiquetez les données. Dans certains cas, il est normal que seul le nombre de sections fiables puisse être échantillonné.
  2. Utilisez divers outils d'exploration de texte. Khcoder est un bon logiciel établi de longue date. Je l'utilise aussi de temps en temps.

Chacun a ses propres avantages et inconvénients, je pense donc que la méthode qui convient à votre cas d'utilisation est la meilleure.

Cependant, quand je suis fatigué de penser comme ça, j'ai une idée approximative de "l'observation avec clustering pour le moment".

Clustering? N'est-ce pas d'accord avec Kmeans?

Je pense que la combinaison de "texte vectorisé + Kmeans" est une voie royale utilisée depuis longtemps.

Cependant, ce n'est pas la meilleure combinaison.

―― Un énorme cluster comme "Autre" est formé. Cependant, en regardant le contenu du cluster, je pense qu'il peut encore être divisé __ HenLors du regroupement avec un grand nombre de clusters depuis le début, il est devenu difficile à interpréter. __ J'aimerais pouvoir diviser la première fois grossièrement et la deuxième fois un peu plus finement __ ――Il y a des quantités de caractéristiques auxquelles «je veux que vous fassiez attention à ceci et au cluster», et j'aimerais que vous puissiez voir les différentes quantités de caractéristiques dans le premier clustering et le second clustering __

J'ai souligné la partie "Je souhaite que cela se produise" en noir.

Il est plutôt difficile d'écrire un tel programme de clustering par vous-même. Pour être honnête, c'est gênant.

J'ai donc créé un package qui effectue un tel clustering.

Introduction de flexible_clustering_tree

Ce package effectue les opérations suivantes, par exemple:

―― La première fois est grossièrement divisée (nombre de grappes = 3), et la deuxième fois est divisée un peu plus finement (nombre de grappes = 8). ――La première fois est divisée par Kmeans à peu près, et la deuxième fois est groupée par DBSCAN tout en considérant la distribution. --Il existe un ensemble de données textuelles et je veux que vous le divisiez par la quantité de fonctionnalités du titre pour la première fois. Dans le deuxième regroupement, veuillez diviser par le corps du texte. --Avec une méthode pour visualiser l'arborescence avec D3.js après le clustering

Par exemple, l'image ci-dessous est une image lorsqu'elle est mise en cluster dans les conditions suivantes.

N'est-ce pas d'accord avec le clustering hiérarchique ascendant?

Le clustering hiérarchique ascendant n'est pas mauvais non plus. Au contraire, il y a des moments où le clustering hiérarchique est préférable pour les cas d'utilisation.

Cependant, le clustering hiérarchique ascendant a la caractéristique que lorsque le nombre de données devient énorme, il devient difficile à calculer et à exécuter.

L'idée de ce package est toujours la version inversée du clustering hiérarchique ascendant.

Je l'ai essayé avec Live Door News Corpus

Il existe un ensemble de données appelé Live Door News Corpus publié par Ronwitt Co., Ltd.

Le Livedoor News Corpus est divisé par catégorie d'actualités, mais supposons qu'il n'y ait pas d'étiquette de catégorie ici.

Ce n'est pas amusant de simplement «l'essayer», alors j'ai pensé qu'il serait intéressant d'avoir une histoire d'analyse. Par conséquent, j'ai considéré l'exemple suivant comme un exemple proche du cas d'utilisation métier.

――Vous êtes une personne qui fait quelque chose comme l'analyse des données d'une entreprise qui exploite un service Web. «Un jour, un tel thème est venu de quelque part.

~~ Ah. .. .. Ce cas d'utilisation semble avoir été mon exemple ... ~~

Quel type de procédure souhaitez-vous observer?

Je suivrai les étapes ci-dessous.

  1. Prétraitement des données. Cela s'appelle la division des mots.
  2. Quantification des fonctionnalités de texte.
  3. Effectuez la mise en cluster.
  4. Visualisation du contenu avec l'arborescence D3.js
  5. Préparez les données pour expliquer le cluster

Prétraitement des données et fractionnement de mots

Le corpus Live Door News comprend deux types de texte, "Titre" et "Corps".

Cette fois, traitons ces deux comme des quantités de caractéristiques distinctes.

Utilisez Mecab pour séparer les mots. Ce script pré-processus.

Quantification des fonctionnalités de texte

Le corpus Live Door News comprend deux types de texte, "Titre" et "Corps".

Tout d'abord, le texte du titre. Le titre est un texte court. Avec cette brièveté, l'intégration de mots en moyenne devrait convenir.

Vient ensuite le texte. Le texte est assez long. Il semble un peu difficile de faire la moyenne de cette longueur par intégration de mots.

Doc2vec est une perte de temps et d'efforts pour créer un modèle. Il est également difficile de préparer des ressources informatiques capables d'exécuter Bert rapidement.

Il existe d'autres options pour l'incorporation vectorielle des documents, mais __ je n'ai pas beaucoup de temps __

Par conséquent, nous utilisons l'approche classique de la matrice de fréquence des mots et de la compression matricielle.

L'ensemble du flux est ce script.

Exécution du clustering

Je vais vous expliquer ici en montrant le code. L'ensemble du flux est ce script.

Tout d'abord, définissez la matrice de quantité d'entités.

La première matrice de titre est «title_vectors». La deuxième matrice de corps est low_dim_matrix.

Les deux sont des matrices de (nombre de documents * nombre de dimensions de fonction).

Spécifiez le nombre de fois que vous souhaitez définir sur level lors de la définition d'une matrice sur flexible_clustering_tree.FeatureMatrixObject.

import flexible_clustering_tree

#Divers traitements sont omis ici
feature_1st_layer = flexible_clustering_tree.FeatureMatrixObject(level=0, matrix_object=numpy.array(title_vectors))
feature_2nd_layer = flexible_clustering_tree.FeatureMatrixObject(level=1, matrix_object=low_dim_matrix)

Ensuite, combinez ces deux FeatureMatrixObjects en un seul.

Les attributs dict_index2 peuvent stocker des informations qui peuvent être utilisées comme explication auxiliaire pour les données (option). Il n'est pas du tout utilisé comme quantité de caractéristiques. Ces informations seront affichées dans l'arborescence que vous aurez visualisée ultérieurement, ce qui facilite leur interprétation. Ici, le titre, le corps et l'étiquette de catégorie sont stockés.

Le champ text_aggregation_field peut contenir une liste bidimensionnelle [[mot]] (option). Les mots sont agrégés avec ces informations et les informations agrégées sont affichées dans l'arborescence visualisée, ce qui facilite l'interprétation. La liste bidimensionnelle est "nombre de documents * nombre de mots (variable et OK)".

multi_matrix_obj = flexible_clustering_tree.MultiFeatureMatrixObject(
    matrix_objects=[feature_1st_layer, feature_2nd_layer],
    dict_index2label={i: label for i, label in enumerate(livedoor_labels)},
    dict_index2attributes={i: {
        'file_name': livedoor_file_names[i],
        'document_text': ''.join(document_text[i]),
        'title_text': ''.join(title_text[i]),
        'label': livedoor_labels[i]
    } for i, label in enumerate(livedoor_labels)},
    text_aggregation_field=document_morphs_text_aggregation
)

Ensuite, spécifiez la méthode de clustering. Disons que HDBSCAN divise la première fois tout en considérant la distribution globale [^ 2] Puisque HDBSCAN ne spécifie pas le nombre de clusters, spécifiez n_cluster = -1.

from hdbscan import HDBSCAN
clustering_operator_1st = flexible_clustering_tree.ClusteringOperator(level=0, n_cluster=-1, instance_clustering=HDBSCAN(min_cluster_size=3))

La deuxième fois, je vais le diviser en 8 groupes.

from sklearn.cluster import KMeans
clustering_operator_2nd = flexible_clustering_tree.ClusteringOperator(level=1, n_cluster=8, instance_clustering=KMeans(n_clusters=8))

Ensuite, combinez ces deux opérateurs de clustering en un seul.

multi_clustering_operator = flexible_clustering_tree.MultiClusteringOperator([clustering_operator_1st, clustering_operator_2nd])

Ensuite, le clustering est exécuté.

Si vous spécifiez max_depth = 3, il sera divisé autant que la profondeur de 3. S'il ne peut pas être divisé, il s'arrêtera automatiquement.

La dernière condition de clustering spécifiée est utilisée pour le deuxième clustering et les suivants.

En d'autres termes, les entités textuelles sont regroupées avec Kmeans.

# run flexible clustering
clustering_runner = flexible_clustering_tree.FlexibleClustering(max_depth=3)
index2cluster_no = clustering_runner.fit_transform(multi_matrix_obj, multi_clustering_operator)

Visualisez l'arbre et enregistrez-le en html.

html = clustering_runner.clustering_tree.to_html()
with open(PATH_OUTPUT_HTML, 'w') as f:
    f.write(html)

Je veux agréger les données plus tard, alors sortons le tableau dans tsv.

#Vous pouvez obtenir des informations de table à des fins d'agrégation
import pandas
table_information = clustering_runner.clustering_tree.to_objects()
pandas.DataFrame(table_information['cluster_information']).to_csv('cluster_relation.tsv', sep='\t')
pandas.DataFrame(table_information['leaf_information']).to_csv('leaf_information.tsv', sep='\t')

Visualisation du contenu avec l'arborescence D3.js

Ce cluster est le résultat d'être divisé uniquement par le titre. Les informations d'agrégation de mots sont affichées à côté du nœud dans le cadre rouge. D'après le contenu des applications, Android et Google, cela semble être un sujet sur les smartphones Android. 001.png

Ensuite, comme vous pouvez le voir à partir de ce cluster ... agrégation de mots, il s'agissait encore d'une communication d'une seule femme. Il pourrait y avoir des balises comme «# Je veux épouser un homme riche».

002.png

Cet arbre est trié par taille de cluster de haut en bas. Jetons un coup d'œil au meilleur cluster. La taille du cluster est écrite dans le champ data-id. Il semble que 6 515 documents appartiennent à ce groupe. Cela ressemble à un "autre" cluster. Ceci est courant dans le clustering de densité tel que HDBSCAN. 003.png

Maintenant, divisons le cluster «autre». Il est divisé par Kmeans. L'image est un cluster avec beaucoup d'actualités sportives. D'après les mots, on peut déduire que le contenu est quelque chose comme "Japan National Sports News".

004.png

Eh bien, tout d'abord, j'ai pu confirmer le contenu approximatif du résultat du clustering comme celui-ci.

Préparation des données pour expliquer le cluster

Vous pouvez regarder l'arbre de vos propres yeux, mais c'est un peu dur. Puisque le but est de concevoir des balises, nous avons besoin de bonnes informations pour réfléchir aux balises.

En outre, à partir du contexte de ce thème, il y a une forte possibilité que «des données ou du matériel dont l'équipe de gestion de service peut comprendre la raison de l'étiquette» soient demandés.

Puisque vous êtes une personne qui fait quelque chose comme l'analyse de données, vous ne pouvez pas demander à l'équipe de gestion du service la raison de la balise et dire «Je ne sais pas». Je voudrais aller "sur la base de ces données" (lunettes rapides).

Par conséquent, considérez la stratégie suivante.

  1. Obtenez des mots caractéristiques avec TF-IDF pour chaque cluster. Exporter vers un fichier Excel.
  2. Écrivez les balises appropriées déduites des mots caractéristiques dans le fichier Excel (manuel)

Tout d'abord, j'ai écrit le résultat de la pondération TFIDF en csv. label est le numéro de cluster. Le groupe 374 est probablement un contenu lié aux vêtements.

スクリーンショット 2019-10-31 16.03.47.png

Par conséquent, écrivez «vêtements» dans la colonne «tag».

スクリーンショット 2019-10-31 16.06.33.png

Il vous suffit de répéter ce travail.

Quand je l'ai essayé, j'ai pu deviner le tag en 20 à 30 secondes par cluster.

Puisqu'il y a 348 clusters cette fois, ce travail sera terminé en 348 clusters * 30 secondes = 10440 secondes = 178 minutes.

~~ Durée de visionnage de Youtube ~~ Même compte tenu du temps de pause, le travail de devinette des balises sera terminé en 4-6 heures.

Ensuite, vous pouvez facilement mettre en place un horaire de travail, et il sera plus facile de négocier "Hey boss ~. Le travail de marquage prend environ 8 heures, donc c'est bon (temps de travail + temps tampon + temps de saut)". Je vais.

Après le travail de devinettes d'étiquettes, si vous créez un beau matériau de diapositive et le donnez à l'équipe de gestion du service, vous serez reconnaissant ~


Ceci est mon poème cérébral.

En passant, j'ai présenté le package flexible_clustering_tree.

Le code utilisé pour le poème dans le cerveau peut être trouvé dans ce référentiel.

Où ce paquet n'est pas encore allé

Il reste encore beaucoup à faire dans ce package. Les relations publiques sont les bienvenues.

Par exemple

--Lorsqu'un grand nombre de clusters se produit, le traitement ralentit. Étant donné que le processus de recherche de priorité de largeur est écrit dans une instruction while, il a tendance à prendre beaucoup de temps proportionnellement au nombre de clusters.

[^ 1]: Elle est également appelée analyse exploratoire des données. [^ 2]: une version évoluée de DBSCAN. La quantité de calcul est inférieure à celle de DBSCAN en termes d'algorithme, et la mise en œuvre est conçue et rapide.

Recommended Posts

Faisons un clustering qui donne une belle vue d'ensemble de l'ensemble de données texte
Article qui vous aidera à comprendre un peu l'algorithme de collision de sphères rigides
Une histoire qui réduit l'effort de fonctionnement / maintenance
Créez un BOT qui raccourcit l'URL Discord
#Une fonction qui renvoie le code de caractère d'une chaîne de caractères
Générer cette forme du fond d'une bouteille pour animaux de compagnie
Une histoire qui a analysé la livraison de Nico Nama.
[Python] Un programme qui compare les positions des kangourous.
Clustering G-means qui détermine automatiquement le nombre de clusters
Un outil qui transforme automatiquement le gacha de Soshage
Faisons l'analyse des données de naufrage du Titanic comme ça
Un programme qui supprime des caractères spécifiques du texte saisi
Faisons un robot qui résout le Rubik Cube! 2 Algorithme
Faisons un robot qui résout le Rubik Cube! 3 Logiciel
Faisons un robot qui résout le Rubik Cube! 1. Vue d'ensemble
Un ensemble de fichiers de script qui font wordcloud avec Python3
Script Python qui compare le contenu de deux répertoires
Résumons les fonctions de base de TensorFlow en créant un réseau neuronal qui apprend les portes XOR.