[PYTHON] Classification multi-étiquettes par forêt aléatoire avec scikit-learn

Préface

Cet article est basé sur ❷ de Collecte et classification des informations relatives à l'apprentissage automatique (concept).

Par exemple, disons que vous avez des nouvelles selon lesquelles une entreprise a construit un système de questions-réponses en utilisant un service sur le cloud.

Ensuite, comme vous pouvez le déduire de Exemple de dossier du système de fichiers local dans ❷, Raccourcis Internet pour cette actualité

・ Outils / Cloud / Certains services ・ Machine learning / application / Bot ・ Système de dialogue ・ Tendances sociales / entreprises / certaines entreprises

Doit être placé dans au moins trois endroits. Ces classifications ne sont pas exclusives, ce sont donc des classifications dites multi-étiquettes.

Il existe divers algorithmes qui traitent de tels problèmes dans Python / scikit-learn, mais il semble que l'interface de l'API soit unifiée telle quelle, et vous pouvez écrire du code qui fonctionne simplement en remplaçant l'algorithme.

Par conséquent, cet article est de vérifier l'interface API.

Étant donné que le script qui gère le résultat réel de l'exploration n'est pas général à introduire dans Qiita, je le publierai sur GitHub, et dans cet article je vérifierai l'interface Seuls les exemples de scripts sont traités. Il est également facile de choisir une forêt aléatoire [^ 1]. Les données utilisent également des valeurs artificielles pour confirmer la correspondance entre les valeurs numériques et ne sont pas vraiment des données significatives. Veuillez comprendre ce point.

Algorithmes multi-classes et multi-étiquettes dans scikit-learn

En tant que cadre de gestion des algorithmes multi-classes et multi-étiquettes avec scikit-learn, [Français] scikit-learn 0.18 Guide de l'utilisateur 1.12. Algorithmes multi-classes et algorithmes multi-labels Il existe un sklearn.multiclass décrit dans / 9decf45d106accc6afe1). Cependant, ce module est un module à usage général qui décompose le problème en problèmes de classification binaire et les gère, et n'est pas optimisé pour les algorithmes de classification individuels.

Arbre de décision, [Random Forest](https: //ja.wikipedia. org / wiki /% E3% 83% A9% E3% 83% B3% E3% 83% 80% E3% 83% A0% E3% 83% 95% E3% 82% A9% E3% 83% AC% E3% 82 % B9% E3% 83% 88), dans la méthode du voisin le plus proche, la classification multi-étiquette est implémentée dans chaque algorithme lui-même, vous utiliserez donc chaque algorithme directement.

Exemple de script

Écrivons maintenant un exemple de script.

random-forest.py


#from sklearn.tree import DecisionTreeClassifier as classifier
from sklearn.ensemble import RandomForestClassifier as classifier
from gensim import matutils

corpus = [[(1,10),(2,20)],[(3,30),(4,40)],[(5,50),(6,60)]]
labels = [[100,500,900],[300,400,800],[200,600,700]]

dense = matutils.corpus2dense(corpus, 7)

print(dense)   #=> (*1)

print(dense.T) #=> (*2)

clf = classifier(random_state=777)
clf.fit(dense.T, labels)

for target in [[[0,10,20, 0, 0, 0, 0]], #=> (*3)
               [[0,10,20,30,40,50,60]], #=> (*4)
               [[0,10,10,0,0,0,0],      #=> (*5)
                [0,0,0,20,20,0,0],
                [0,0,0,0,0,30,30]]]:
    print(clf.predict(target))
    print(clf.predict_proba(target))

classifier

Si vous modifiez la source d'importation de l'algorithme de classificateur comme dans l'exemple de commentaire, il sera classé par l'algorithme spécifié.

corpus et étiquettes

Le corpus d'entrée est une matrice clairsemée qui décrit les fréquences de vocabulaire des trois documents. ID du premier document: 1 mot 10 fois, ID: 2 mots 20 fois, autres mots fréquence 0 · ID du document suivant: 3 mots 30 fois, ID: 4 mots 40 fois, autres mots fréquence 0 ・ Dernier document-ID: 5 mots 50 fois, ID: 6 mots 60 fois, autres mots fréquence 0

Les étiquettes des données de l'enseignant décrivent la classification de chaque document. La première étiquette du premier document a une valeur de 100, la deuxième étiquette a une valeur de 500 et la dernière étiquette a une valeur de 900 Le document suivant - la première étiquette a une valeur de 300, l'étiquette suivante a une valeur de 400 et la dernière étiquette a une valeur de 800. · Dernier document - la première étiquette a une valeur de 200, la deuxième étiquette a une valeur de 600 et la dernière étiquette a une valeur de 700. En d'autres termes · Premier label-trois classes avec les valeurs 100, 200 et 300 · Étiquette suivante - trois classes avec les valeurs 400, 500 et 600 -Dernière étiquette-trois classes avec les valeurs 700, 800 et 900

conversion clairsemée → dense

L'algorithme de classification fourni par scikit-learn s'attend à une matrice dense en entrée, nous devons donc convertir la matrice clairsemée en une matrice dense.

Vous pouvez utiliser le corpus2dense dans le module gensim.matutils. Voyons le résultat (* 1).

dense.


[[  0.   0.   0.]
 [ 10.   0.   0.]
 [ 20.   0.   0.]
 [  0.  30.   0.]
 [  0.  40.   0.]
 [  0.   0.  50.]
 [  0.   0.  60.]]

cette?

Il est vrai que c'est une matrice dense qui exprime 0 sans l'omettre correctement, mais comme la ligne est le mot ID et la colonne est le numéro de document, il n'y a pas de correspondance avec les étiquettes telles quelles. Par conséquent, les lignes et les colonnes doivent être transposées pour être l'entrée de l'algorithme de classification (→ résultat (* 2)).

dense.T


[[  0.  10.  20.   0.   0.   0.   0.]
 [  0.   0.   0.  30.  40.   0.   0.]
 [  0.   0.   0.   0.   0.  50.  60.]]

Je pense qu'il existe une très grande majorité de cas d'utilisation où dense.T est utilisé pour dense et dense.T, mais je ne sais pas pourquoi corpus2dense a une telle spécification.

Classification

・ Génération de classificateurs

python


clf = RandomForestClassifier(random_state=777)

L'algorithme Random Forest utilise des nombres aléatoires en interne, donc si vous ne corrigez pas random_state, vous obtiendrez des résultats différents à chaque fois.

· Classification

print(clf.predict(target))
print(clf.predict_proba(target))

Dans cet exemple de script, prédire est utilisé pour calculer le résultat de la classification, et predict_proba est utilisé pour calculer la valeur de probabilité estimée [^ 2].

Regardons les résultats dans l'ordre.

(*3) [[0,10,20, 0, 0, 0, 0]]

[[ 100.  500.  900.]]
[array([[ 0.8,  0.1,  0.1]]), array([[ 0.1,  0.8,  0.1]]), array([[ 0.1,  0.1,  0.8]])]

Puisqu'il s'agit de l'un des modèles formés, on s'attend à ce que la classification soit conforme aux données des enseignants.

・ Première étiquette-Valeur 100: Probabilité 0,8, 200: Probabilité 0,1, 300: Probabilité 0,1 → Valeur 100. ・ Valeur d'étiquette suivante 400: Probabilité 0,1, 500: Probabilité 0,8, 600: Probabilité 0,1 → Valeur 500. -Dernière étiquette-Valeur 700: Probabilité 0,1, 800: Probabilité 0,1, 900: Probabilité 0,8 → Valeur 900.

Certes, les données des enseignants peuvent être reproduites.

Notez que les valeurs sont gérées par ordre numérique et non par ordre d'apparition.

(*4) [[0,10,20,30,40,50,60]]

[[ 200.  600.  700.]]
[array([[ 0.3,  0.5,  0.2]]), array([[ 0.2,  0.3,  0.5]]), array([[ 0.5,  0.2,  0.3]])]

・ Première étiquette-Valeur 100: Probabilité 0,3, 200: Probabilité 0,5, 300: Probabilité 0,2 → Valeur 200. ・ Valeur d'étiquette suivante 400: Probabilité 0,2, 500: Probabilité 0,3, 600: Probabilité 0,5 → Valeur 600. -Dernière étiquette-Valeur 700: Probabilité 0,5, 800: Probabilité 0,2, 900: Probabilité 0,3 → Valeur 700.

(*5) [[0,10,10,0,0,0,0],[0,0,0,20,20,0,0],[0,0,0,0,0,30,30]]]

[[ 100.  500.  900.]
 [ 100.  400.  800.]
 [ 200.  600.  700.]]
[array([[ 0.7,  0.2,  0.1],
        [ 0.4,  0.2,  0.4],
        [ 0.3,  0.5,  0.2]]),
 array([[ 0.1,  0.7,  0.2],
        [ 0.4,  0.4,  0.2],
        [ 0.2,  0.3,  0.5]]),
 array([[ 0.2,  0.1,  0.7],
        [ 0.2,  0.4,  0.4],
        [ 0.5,  0.2,  0.3]])]

・ Première étiquette-Valeur 100: Probabilité 0,7, 200: Probabilité 0,2, 300: Probabilité 0,1 → Valeur 100. ・ Valeur d'étiquette suivante 400: Probabilité 0,1, 500: Probabilité 0,7, 600: Probabilité 0,2 → Valeur 500. -Dernière étiquette-Valeur 700: Probabilité 0,2, 800: Probabilité 0,1, 900: Probabilité 0,7 → Valeur 900.

・ Première étiquette-Valeur 100: Probabilité 0,4, 200: Probabilité 0,2, 300: Probabilité 0,4 → Valeur 100. ・ Valeur d'étiquette suivante 400: Probabilité 0,4, 500: Probabilité 0,4, 600: Probabilité 0,2 → Valeur 400. -Dernière étiquette-Valeur 700: Probabilité 0,2, 800: Probabilité 0,4, 900: Probabilité 0,4 → Valeur 800.

・ Première étiquette-Valeur 100: Probabilité 0,3, 200: Probabilité 0,5, 300: Probabilité 0,2 → Valeur 200. ・ Valeur d'étiquette suivante 400: Probabilité 0,2, 500: Probabilité 0,3, 600: Probabilité 0,5 → Valeur 600. -Dernière étiquette-Valeur 700: Probabilité 0,5, 800: Probabilité 0,2, 900: Probabilité 0,3 → Valeur 700.

Notez que la dimension la plus externe de predict_proba est le numéro d'étiquette.

Lorsque sklearn.multiclass décompose un problème en un problème de classification binaire et le gère, la répétition la plus externe est inévitablement l'étiquette n ° [^ 3], donc je pense que c'est une spécification naturelle.

Épilogue

De cette façon, ce à quoi correspond chaque dimension de la matrice d'interface est compliqué et difficile à comprendre, surtout dans le cas d'étiquettes multiples, et je pense qu'il était significatif de laisser un tel mémo.

Je vous serais reconnaissant si vous pouviez signaler tout malentendu.

[^ 1]: Concernant la forêt aléatoire, il y a un article Classifier les articles de presse par scikit-learn et gensim. [^ 2]: Selon l'algorithme de classification, il peut ne pas toujours être considéré comme une probabilité. Par exemple, dans le cas de DecisionTree, il est "décidé", donc cette valeur semble être 0. ou 1. [^ 3]: Je ne l'ai pas vraiment confirmé.

Recommended Posts

Classification multi-étiquettes par forêt aléatoire avec scikit-learn
Classification / régression par empilement (scikit-learn)
Forêt aléatoire (classification) et réglage des hyperparamètres
Forêt aléatoire (2)
Forêt aléatoire
Classification multi-étiquette d'images multi-classes avec pytorch
Classification des maladies par Random Forest en utilisant Python
Isomap avec Scikit-learn
Classification des textes du défi par Naive Bayes avec sklearn
DBSCAN avec scikit-learn
Clustering avec scikit-learn (1)
Clustering avec scikit-learn (2)
PCA avec Scikit-learn
kmeans ++ avec scikit-learn
Validation croisée avec scikit-learn
SVM multi-classes avec scikit-learn
Apprentissage Scikit-Learn avec la chimioinfomatique
DBSCAN (clustering) avec scikit-learn
Installez scikit.learn avec pip
Calculer tf-idf avec scikit-learn
Apprenez les catégories de texte japonais avec tf-idf et Random Forest ~ [Tuning]
Mesurer l'importance des entités avec un outil de forêt aléatoire
Classification d'images avec un réseau de neurones auto-fabriqué par Keras et PyTorch
"Classer les déchets par image!" Journal de création d'application day2 ~ Mise au point avec VGG16 ~
Décision Scikit-learn Générer du code Python à partir de règles d'arbre / forêt aléatoire