K-fold cross validation de la mise en œuvre de python
Je suis en train de mettre en œuvre la k-fold cross-validation de l'algorithme en python.
Je sais SKLearn fournit une mise en œuvre, mais encore...
C'est mon code à partir de maintenant.
from sklearn import metrics
import numpy as np
class Cross_Validation:
@staticmethod
def partition(vector, fold, k):
size = vector.shape[0]
start = (size/k)*fold
end = (size/k)*(fold+1)
validation = vector[start:end]
if str(type(vector)) == "<class 'scipy.sparse.csr.csr_matrix'>":
indices = range(start, end)
mask = np.ones(vector.shape[0], dtype=bool)
mask[indices] = False
training = vector[mask]
elif str(type(vector)) == "<type 'numpy.ndarray'>":
training = np.concatenate((vector[:start], vector[end:]))
return training, validation
@staticmethod
def Cross_Validation(learner, k, examples, labels):
train_folds_score = []
validation_folds_score = []
for fold in range(0, k):
training_set, validation_set = Cross_Validation.partition(examples, fold, k)
training_labels, validation_labels = Cross_Validation.partition(labels, fold, k)
learner.fit(training_set, training_labels)
training_predicted = learner.predict(training_set)
validation_predicted = learner.predict(validation_set)
train_folds_score.append(metrics.accuracy_score(training_labels, training_predicted))
validation_folds_score.append(metrics.accuracy_score(validation_labels, validation_predicted))
return train_folds_score, validation_folds_score
L'apprenant paramètre est un classificateur de SKlearn bibliothèque, k est le nombre de plis, des exemples est une matrice creuse produite par le CountVectorizer (nouveau SKlearn) qui est la représentation du sac de mots.
Par exemple:
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from Cross_Validation import Cross_Validation as cv
vectorizer = CountVectorizer(stop_words='english', lowercase=True, min_df=2, analyzer="word")
data = vectorizer.fit_transform("""textual data""")
clfMNB = MultinomialNB(alpha=.0001)
score = cv.Cross_Validation(clfMNB, 10, data, labels)
print "Train score" + str(score[0])
print "Test score" + str(score[1])
Je suis en supposant qu'il existe une certaine logique erreur quelque part car les scores sont à 95% sur l'ensemble de la formation (comme prévu), mais pratiquement 0 sur le test de test, mais je ne le trouve pas.
J'espère avoir été clair.
Merci à l'avance.
________________________________MODIFIER___________________________________
C'est le code qui charge le texte dans le vecteur qui peut être transmis à la vectorizer. Il renvoie également l'étiquette de vecteur.
from nltk.tokenize import word_tokenize
from Categories_Data import categories
import numpy as np
import codecs
import glob
import os
import re
class Data_Preprocessor:
def tokenize(self, text):
tokens = word_tokenize(text)
alpha = [t for t in tokens if unicode(t).isalpha()]
return alpha
def header_not_fully_removed(self, text):
if ":" in text.splitlines()[0]:
return len(text.splitlines()[0].split(":")[0].split()) == 1
else:
return False
def strip_newsgroup_header(self, text):
_before, _blankline, after = text.partition('\n\n')
if len(after) > 0 and self.header_not_fully_removed(after):
after = self.strip_newsgroup_header(after)
return after
def strip_newsgroup_quoting(self, text):
_QUOTE_RE = re.compile(r'(writes in|writes:|wrote:|says:|said:'r'|^In article|^Quoted from|^\||^>)')
good_lines = [line for line in text.split('\n')
if not _QUOTE_RE.search(line)]
return '\n'.join(good_lines)
def strip_newsgroup_footer(self, text):
lines = text.strip().split('\n')
for line_num in range(len(lines) - 1, -1, -1):
line = lines[line_num]
if line.strip().strip('-') == '':
break
if line_num > 0:
return '\n'.join(lines[:line_num])
else:
return text
def raw_to_vector(self, path, to_be_stripped=["header", "footer", "quoting"], noise_threshold=-1):
base_dir = os.getcwd()
train_data = []
label_data = []
for category in categories:
os.chdir(base_dir)
os.chdir(path+"/"+category[0])
for filename in glob.glob("*"):
with codecs.open(filename, 'r', encoding='utf-8', errors='replace') as target:
data = target.read()
if "quoting" in to_be_stripped:
data = self.strip_newsgroup_quoting(data)
if "header" in to_be_stripped:
data = self.strip_newsgroup_header(data)
if "footer" in to_be_stripped:
data = self.strip_newsgroup_footer(data)
if len(data) > noise_threshold:
train_data.append(data)
label_data.append(category[1])
os.chdir(base_dir)
return np.array(train_data), np.array(label_data)
C'est ce "de Categories_Data importer des catégories" importations...
categories = [
('alt.atheism',0),
('comp.graphics',1),
('comp.os.ms-windows.misc',2),
('comp.sys.ibm.pc.hardware',3),
('comp.sys.mac.hardware',4),
('comp.windows.x',5),
('misc.forsale',6),
('rec.autos',7),
('rec.motorcycles',8),
('rec.sport.baseball',9),
('rec.sport.hockey',10),
('sci.crypt',11),
('sci.electronics',12),
('sci.med',13),
('sci.space',14),
('soc.religion.christian',15),
('talk.politics.guns',16),
('talk.politics.mideast',17),
('talk.politics.misc',18),
('talk.religion.misc',19)
]
Eh bien, il est bien entendu que pour les fins de la compréhension de ce que je fais mal. Depuis il a été une couple de jours et je ne peux pas comprendre, je lui ai demandé si il n'y a peut-être une évidente erreur de logique ou de quelque chose que je ne sais pas à propos de scipy ecc... je ne connais pas d'autre façon d'expliquer le problème à quelqu'un d'autre sans le code (surtout car je ne sais pas quel est le problème)
Est-il possible pour vous de télécharger quelques dataset nous pouvons tester cela sur et aussi importer toutes les scikit paquets?
J'ai édité la question. Vous pouvez trouver le jeu de données ici qwone.com/~jason/20Newsgroups . J'utilise la version originale (premier). Merci
Grand. Jetons un coup d'oeil 🙂
OriginalL'auteur Lorenzo Norcini | 2016-08-09
Vous devez vous connecter pour publier un commentaire.
La raison pour laquelle votre validation score est faible, c'est subtil.
La question est de savoir comment vous avez partitionné le jeu de données. Rappelez-vous, lors de la validation croisée, vous devriez au hasard diviser le jeu de données. C'est le hasard qui vous manquent.
Vos données est chargé de la catégorie par catégorie, ce qui signifie dans votre jeu de données d'entrée, les étiquettes de classe et des exemples à suivre l'une après l'autre. En ne faisant pas le hasard split, vous avez complètement enlevé une classe qui votre modèle ne voit jamais au cours de la phase de formation et, par conséquent, vous obtenez un mauvais résultat de votre test/validation de phase.
Vous pouvez résoudre ce problème en faisant un random shuffle. Donc, faites ceci:
Mon plaisir. Je suis également pas d'accord avec les commentaires que c'est inutile.
OriginalL'auteur Pankaj Daga