[PYTHON] Apprenez les catégories de texte japonais avec tf-idf et Random Forest ~ [Tuning]

Apprendre les catégories de texte japonais avec tf-idf et forêt aléatoire ~ news liveoor semble avoir de la place pour le réglage, alors faites de votre mieux Je vais.

Code à utiliser

C'est la même chose que l'article précédent.

import glob
import random
import numpy as np
from natto import MeCab
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.ensemble import RandomForestClassifier

def load_livedoor_news_corpus():
    category = {
        'dokujo-tsushin': 1,
        'it-life-hack':2,
        'kaden-channel': 3,
        'livedoor-homme': 4,
        'movie-enter': 5,
        'peachy': 6,
        'smax': 7,
        'sports-watch': 8,
        'topic-news':9
    }
    docs  = []
    labels = []

    for c_name, c_id in category.items():
        files = glob.glob("./text/{c_name}/{c_name}*.txt".format(c_name=c_name))

        text = ''
        for file in files:
            with open(file, 'r') as f:
                lines = f.read().splitlines() 

                url = lines[0]
                datetime = lines[1]
                subject = lines[2]
                body = "\n".join(lines[3:])
                text = subject + "\n" + body

            docs.append(text)
            labels.append(c_id)
    
    return docs, labels

docs, labels = load_livedoor_news_corpus()


random.seed()
indices = list(range(len(docs)))
random.shuffle(indices)

split_size = 7000

train_data = [docs[i] for i in indices[0:split_size]]
train_labels = [labels[i] for i in indices[0:split_size]]
test_data = [docs[i] for i in indices[split_size:]]
test_labels = [labels[i] for i in indices[split_size:]]



def tokenize(text):
    tokens = []
    with MeCab('-F%f[0],%f[6]') as nm:
        for n in nm.parse(text, as_nodes=True):
            # ignore any end-of-sentence nodes
            if not n.is_eos() and n.is_nor():
                klass, word = n.feature.split(',', 1)
                if klass in ['nom']:
                    tokens.append(word)

    return tokens


vectorizer = TfidfVectorizer(tokenizer=tokenize)
train_matrix = vectorizer.fit_transform(train_data)
test_matrix = vectorizer.transform(test_data)


clf2 = RandomForestClassifier(n_estimators=100, max_features=3000, oob_score=True)
clf2.fit(train_matrix, train_labels)

print(clf2.score(train_matrix, train_labels))
print(clf2.score(test_matrix, test_labels))

résultat

Dataset Score
Training 1.0
Test 0.901

Étant donné que le taux d'identification des données d'entraînement est de 100%, il semble bon de supprimer les mots de partie et de réduire les fonctionnalités.

Limiter les mots de pièces à la nomenclature uniquement

def tokenize(text):
    tokens = []
    with MeCab('-F%f[0],%f[6]') as nm:
        for n in nm.parse(text, as_nodes=True):
            # ignore any end-of-sentence nodes
            if not n.is_eos() and n.is_nor():
                klass, word = n.feature.split(',', 1)
                if klass in ['nom']:
                    tokens.append(word)

    return tokens

résultat

Dataset Score
Training 1.0
Test 0.918

Le taux d'identification des données de test est passé à 91,8%.

Augmenter max_features dans la forêt aléatoire

Tel que mesuré par la méthode get_feature_names de TfidfVectorizer, la fonctionnalité était 31258.

Le max_features de RandomForestClassifier était sqrt par défaut, 176 dans ce cas. Je pense que c'est trop petit, alors je vais l'augmenter un peu.

clf2 = RandomForestClassifier(n_estimators=100, max_features=num_features)
clf2.fit(train_matrix, train_labels)

résultat

num_features = 1000

Dataset Score
Training 1.0
Test 0.931

num_features = 3000

Dataset Score
Training 1.0
Test 0.937

Le taux d'identification des données de test est passé à 93,7%.

Utilisez oob_score

Le document de l'API sklearn indique "S'il faut utiliser des échantillons hors sac pour estimer l'erreur de généralisation.", Et si les performances de généralisation s'améliorent, c'est mieux que ça ...

Je ne peux pas comprendre comment il se comporte à partir du document. ..

clf2 = RandomForestClassifier(n_estimators=100, max_features=3000, oob_score=True)
clf2.fit(train_matrix, train_labels)

résultat

Dataset Score
Training 1.0
Test 0.948

Dans ce cas, il était préférable de s'accorder avec oob_score = True.

Résumé

Avant le réglage, il était de 90,1%, mais finalement le taux d'identification s'est amélioré à 94,8%.

Recommended Posts

Apprenez les catégories de texte japonais avec tf-idf et Random Forest ~ [Tuning]
Apprenez les catégories de texte japonais avec TF-IDF et Random Forest ~ Liveoor News
Forêt aléatoire (classification) et réglage des hyperparamètres
Arbre de décision et forêt aléatoire
Parlez du texte japonais avec OpenJTalk + python
Classification de texte non supervisée avec Doc2Vec et k-means
Classification multi-étiquettes par forêt aléatoire avec scikit-learn
Extraire du texte japonais d'un PDF avec PDFMiner