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.
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))
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.
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
Dataset | Score |
---|---|
Training | 1.0 |
Test | 0.918 |
Le taux d'identification des données de test est passé à 91,8%.
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)
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%.
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)
Dataset | Score |
---|---|
Training | 1.0 |
Test | 0.948 |
Dans ce cas, il était préférable de s'accorder avec oob_score = True.
Avant le réglage, il était de 90,1%, mais finalement le taux d'identification s'est amélioré à 94,8%.
Recommended Posts