2016-05-06 2 views
0

J'ai créé un classificateur Gaussian Naive Bayes sur un ensemble de données email (spam/non spam) et j'ai pu le lancer avec succès. J'ai vectorisé les données, divisé en trains et ensembles de tests, puis calculé la précision, toutes les caractéristiques qui sont présentes dans le classificateur Naive Bayes sklearn-Gaussien.Comment prédire l'étiquette d'un e-mail à l'aide d'un classificateur NB qualifié dans sklearn?

Maintenant, je veux être en mesure d'utiliser ce classificateur pour prédire les «étiquettes» pour les nouveaux courriels - que ce soit par spam ou non. Par exemple dis que j'ai un email. Je veux l'alimenter à mon classificateur et obtenir la prédiction quant à savoir si c'est un spam ou non. Comment puis-je atteindre cet objectif? S'il vous plaît aidez.

Code pour le fichier classificateur.

#!/usr/bin/python 
 

 
import sys 
 
from time import time 
 
import logging 
 

 
# Display progress logs on stdout 
 
logging.basicConfig(level = logging.DEBUG, format = '%(asctime)s %(message)s') 
 

 
sys.path.append("../DatasetProcessing/") 
 
from vectorize_split_dataset import preprocess 
 

 
### features_train and features_test are the features 
 
for the training and testing datasets, respectively### labels_train and labels_test are the corresponding item labels 
 
features_train, features_test, labels_train, labels_test = preprocess() 
 

 
######################################################### 
 
from sklearn.naive_bayes import GaussianNB 
 
clf = GaussianNB() 
 
t0 = time() 
 
clf.fit(features_train, labels_train) 
 
pred = clf.predict(features_test) 
 
print("training time:", round(time() - t0, 3), "s") 
 
print(clf.score(features_test, labels_test)) 
 

 
## Printing Metrics 
 
for Training and Testing 
 
print("No. of Testing Features:" + str(len(features_test))) 
 
print("No. of Testing Features Label:" + str(len(labels_test))) 
 
print("No. of Training Features:" + str(len(features_train))) 
 
print("No. of Training Features Label:" + str(len(labels_train))) 
 
print("No. of Predicted Features:" + str(len(pred))) 
 

 
## Calculating Classifier Performance 
 
from sklearn.metrics import classification_report 
 
y_true = labels_test 
 
y_pred = pred 
 
labels = ['0', '1'] 
 
target_names = ['class 0', 'class 1'] 
 
print(classification_report(y_true, y_pred, target_names = target_names, labels = labels)) 
 

 
# How to predict label of a new text 
 
new_text = "You won a lottery at UK lottery commission. Reply to claim it"

Code pour Vectorisation

#!/usr/bin/python 
 

 
import os 
 
import pickle 
 
import numpy 
 
numpy.random.seed(42) 
 

 
path = os.path.dirname(os.path.abspath(__file__)) 
 

 
### The words(features) and label_data(labels), already largely processed.###These files should have been created beforehand 
 
feature_data_file = path + "./createdDataset/dataSet.pkl" 
 
label_data_file = path + "./createdDataset/dataLabel.pkl" 
 

 
feature_data = pickle.load(open(feature_data_file, "rb")) 
 
label_data = pickle.load(open(label_data_file, "rb")) 
 

 
### test_size is the percentage of events assigned to the test set(the### remainder go into training)### feature matrices changed to dense representations 
 
for compatibility with### classifier functions in versions 0.15.2 and earlier 
 
from sklearn import cross_validation 
 
features_train, features_test, labels_train, labels_test = cross_validation.train_test_split(feature_data, label_data, test_size = 0.1, random_state = 42) 
 

 
from sklearn.feature_extraction.text import TfidfVectorizer 
 
vectorizer = TfidfVectorizer(sublinear_tf = True, max_df = 0.5, stop_words = 'english') 
 
features_train = vectorizer.fit_transform(features_train) 
 
features_test = vectorizer.transform(features_test)#.toarray() 
 

 
## feature selection to reduce dimensionality 
 
from sklearn.feature_selection import SelectPercentile, f_classif 
 
selector = SelectPercentile(f_classif, percentile = 5) 
 
selector.fit(features_train, labels_train) 
 
features_train_transformed_reduced = selector.transform(features_train).toarray() 
 
features_test_transformed_reduced = selector.transform(features_test).toarray() 
 

 
features_train = features_train_transformed_reduced 
 
features_test = features_test_transformed_reduced 
 

 
def preprocess(): 
 
    return features_train, features_test, labels_train, labels_test

code pour la production de jeux de données

#!/usr/bin/python 
 

 
import os 
 
import pickle 
 
import re 
 
import sys 
 

 
# sys.path.append("../tools/") 
 

 

 
"" 
 
" 
 
    Starter code to process the texts of accuate and inaccurate category to extract 
 
    the features and get the documents ready for classification. 
 

 
    The list of all the texts from accurate category are in the accurate_files list 
 
    likewise for texts of inaccurate category are in (inaccurate_files) 
 

 
    The data is stored in lists and packed away in pickle files at the end. 
 
" 
 
"" 
 

 

 
accurate_files = open("./rawDatasetLocation/accurateFiles.txt", "r") 
 
inaccurate_files = open("./rawDatasetLocation/inaccurateFiles.txt", "r") 
 

 
label_data = [] 
 
feature_data = [] 
 

 
### temp_counter is a way to speed up the development--there are### thousands of lines of accurate and inaccurate text, so running over all of them### can take a long time### temp_counter helps you only look at the first 200 lines in the list so you### can iterate your modifications quicker 
 
temp_counter = 0 
 

 

 
for name, from_text in [("accurate", accurate_files), ("inaccurate", inaccurate_files)]: 
 
    for path in from_text: ###only look at first 200 texts when developing### once everything is working, remove this line to run over full dataset 
 
temp_counter = 1 
 
if temp_counter < 200: 
 
    path = os.path.join('..', path[: -1]) 
 
print(path) 
 
text = open(path, "r") 
 
line = text.readline() 
 
while line: ###use a 
 
function parseOutText to extract the text from the opened text# stem_text = parseOutText(text) 
 
stem_text = text.readline().strip() 
 
print(stem_text)### use str.replace() to remove any instances of the words# stem_text = stem_text.replace("germani", "")### append the text to feature_data 
 
feature_data.append(stem_text)### append a 0 to label_data 
 
if text is from Sara, and 1 
 
if text is from Chris 
 
if (name == "accurate"): 
 
    label_data.append("0") 
 
elif(name == "inaccurate"): 
 
    label_data.append("1") 
 

 
line = text.readline() 
 

 
text.close() 
 

 
print("texts processed") 
 
accurate_files.close() 
 
inaccurate_files.close() 
 

 
pickle.dump(feature_data, open("./createdDataset/dataSet.pkl", "wb")) 
 
pickle.dump(label_data, open("./createdDataset/dataLabel.pkl", "wb"))

Aussi je veux savoir si je peux former le classificateur de manière incrémentielle, ce qui permet de recycler un modèle créé avec des données plus récentes pour affiner le modèle au fil du temps?

Je serais vraiment heureux si quelqu'un peut m'aider avec cela. Je suis vraiment bloqué à ce stade.

+0

Comme vous l'avez déjà fait, divisez train_test sur un ensemble déjà marqué, puis calculez la précision. Pour les nouvelles données de test, vous devez charger votre nouveau jeu de données de test dans la variable features_test. Pour la prédiction, vous pouvez faire deux choses, soit fit_transformer votre NB chaque fois que vous avez de nouvelles données de test, soit enregistrer le modèle NB (utilisez sklearn.externals.joblib.dump/load, et pour chaque nouvel ensemble de test, chargez votre modèle et utilisez Vous pouvez former le classificateur par incrément, mais l'ancien classificateur devra être remplacé – pmaniyan

Répondre

1

Vous utilisez déjà votre modèle pour prédire les libellés d'e-mails dans votre ensemble de tests. C'est ce que fait pred = clf.predict(features_test). Si vous voulez voir ces étiquettes, faites print pred.

Mais peut-être que vous savez comment prédire les étiquettes pour les courriels que vous découvrirez dans le futur et qui ne sont pas actuellement dans votre ensemble de test? Si c'est le cas, vous pouvez considérer vos nouveaux e-mails comme un nouvel ensemble de tests. Comme pour votre test précédent, vous devrez exécuter plusieurs étapes de traitement des données:

1) La première chose à faire est de générer des fonctionnalités pour vos nouvelles données de messagerie. L'étape de génération d'entités n'est pas incluse dans votre code ci-dessus, mais devra se produire.

2) Vous utilisez un vectorizer Tfidf, qui convertit une collection de documents en une matrice d'entités Tfidf basée sur la fréquence de terme et la fréquence de document inverse. Vous devez placer vos nouvelles données de fonctionnalité de test de courrier électronique dans le vectorizer que vous avez adapté à vos données d'entraînement. 3) Ensuite, vos nouvelles données de fonctionnalité de test de courrier électronique devront subir une réduction de dimensionnalité en utilisant le même code selector que vous avez adapté à vos données d'entraînement.

4) Enfin, exécutez prédire vos nouvelles données de test. Utilisez print pred si vous voulez voir les nouvelles étiquettes.

Pour répondre à votre dernière question concernant la ré-instruction itérative de votre modèle, oui vous pouvez certainement le faire. Il suffit de sélectionner une fréquence, de produire un script qui étend votre jeu de données avec les données entrantes, puis de ré-exécuter toutes les étapes, du prétraitement à la vectorisation Tfidf, en passant par la réduction de la dimensionnalité, l'ajustement et la prédiction.

+0

Merci pour la solution Jason Ouais c'est exactement ce que j'essayais de demander Comment générer des fonctionnalités pour les nouvelles données de courrier électronique. – harshlal028

+0

Salut @ user2168281, toutes les étapes d'ingénierie des fonctionnalités se déroulent en dehors du code que vous avez posté ci-dessus, donc impossible de le dire. feature_data_file = chemin + "./createdDataset/dataSet.pkl" 'et ici' feature_data = pickle.load (open (fichier_fichier_fichier, "rb")) '. Si vous n'avez pas fait vous-même l'ingénierie des fonctions, vous devez moins traquer le code source pour voir quelles sont les caractéristiques et comment elles ont été construites de sorte que vous pouvez refaire de votre côté pour de nouvelles données. Désolé je ne peux pas aider plus. Si vous trouvez le code source pour la génération d'entités, faites-le nous savoir. – user6275647

+0

Je dois dire qu'il est possible que les données d'entité ne soient en réalité que le texte de l'e-mail lui-même, et que ce soit le vectorizer Tfidf qui transforme ces données textuelles brutes en entités. Si tel est le cas, la génération de caractéristiques pour vos nouvelles données de courrier électronique se produira dans l'étape Tfidf mentionnée ci-dessus. Mais je ne peux pas dire avec certitude parce que nous n'avons pas de visibilité sur ce à quoi ressemble 'features_data' une fois qu'il a été importateur dans cette étape' feature_data = pickle.load (open (fichier_fichier_fichier, "rb")) '. – user6275647