В настоящее время я создаю простой спам-фильтр для электронной почты с помощью Naive Bayles.Как я могу сделать nltk.NaiveBayesClassifier.train() работать с моим словарем
Чтобы понять мою логику алгоритма: у меня есть папка с большим количеством файлов os, которые являются примерами спама/сообщений ham. У меня также есть два других файла в этой папке, содержащие заголовки всех моих примеров ветчины, а другой - заголовки всех моих примеров спама. Я организовал это так, чтобы я мог правильно открывать и читать эти письма.
Я помещаю все слова, которые, как я сужу, важны в структуре словаря, с меткой «спам» или «ветчина» в зависимости от того, из какого рода файлов я их извлекал.
Тогда я использую nltk.NaiveBayesClassifier.train(), так что я могу тренировать классификатор, но я получаю сообщение об ошибке:
для featureset, этикетки в labeled_featuresets: ValueError: слишком много значений в unpack
Я не знаю, почему это происходит. Когда я искал решение, я обнаружил, что строки не хешируются, и я использовал список, чтобы сделать это, а затем превратил его в словарь, который, насколько мне известно, хэшируется, но он продолжает получать эту ошибку. Кто-то знает, как его решить? Благодаря!
Весь мой код приведен ниже:
import nltk
import re
import random
stopwords = nltk.corpus.stopwords.words('english') #Words I should avoid since they have weak value for classification
my_file = open("spam_files.txt", "r") #my_file now has the name of each file that contains a spam email example
word = {} #a dictionary where I will storage all the words and which value they have (spam or ham)
for lines in my_file: #for each name of file (which will be represenetd by LINES) of my_file
with open(lines.rsplit('\n')[0]) as email: #I will open the file pointed by LINES, and then, read the email example that is inside this file
for phrase in email: #After that, I will take every phrase of this email example I just opened
try: #and I'll try to tokenize it
tokens = nltk.word_tokenize(phrase)
except:
continue #I will ignore non-ascii elements
for c in tokens: #for each token
regex = re.compile('[^a-zA-Z]') #I will also exclude numbers
c = regex.sub('', c)
if (c): #If there is any element left
if (c not in stopwords): #And if this element is a not a stopword
c.lower()
word.update({c: 'spam'})#I put this element in my dictionary. Since I'm analysing spam examples, variable C is labeled "spam".
my_file.close()
email.close()
#The same logic is used for the Ham emails. Since my ham emails contain only ascii elements, I dont test it with TRY
my_file = open("ham_files.txt", "r")
for lines in my_file:
with open(lines.rsplit('\n')[0]) as email:
for phrase in email:
tokens = nltk.word_tokenize(phrase)
for c in tokens:
regex = re.compile('[^a-zA-Z]')
c = regex.sub('', c)
if (c):
if (c not in stopwords):
c.lower()
word.update({c: 'ham'})
my_file.close()
email.close()
#And here I train my classifier
classifier = nltk.NaiveBayesClassifier.train(word)
classifier.show_most_informative_features(5)
Помимо проблемы, которую вы описываете (и которую я рассмотрел ниже), ваш код имеет ряд проблем: вы не должны использовать тот же самый диктофон для сбора слов как от писем спама, так и от ветчины - вместо этого используйте отдельный пакет, слова dict для каждого письма. Кроме того, 'c.lower()' не имеет никакого эффекта - вы должны написать 'c = c.lower()'. – lenz