我在改善运行朴素贝叶斯算法的结果方面遇到了一些困难。我的数据集由 39 列组成(一些是分类的,一些是数字的)。然而,我只考虑了主要变量,即文本,它包含所有的垃圾邮件和非垃圾邮件。
既然是垃圾邮件过滤,我觉得这个字段可以不错。因此,我在删除停用词后使用了 countvectorizer 并使用它们进行拟合变换。
我得到了 60% 的准确率,非常低!你认为什么可能导致这个低结果?有什么我可以做的来改进它吗?
这些是我正在考虑的 39 列中的列:
Index(['Date', 'Username', 'Subject', 'Target', 'Country', 'Website','Text', 'Capital', 'Punctuation'],
dtype='object')
Date
是日期格式 (eg 2018-02-06
)
Username
是字符串 (eg Math
)
Subject
是字符串 (eg I need your help
)
Target
是二进制变量 ( 1
-spam 或 -not 0
spam)
Country
是字符串 (eg US
)
Website
是字符串 (eg www.viagra.com
)
Text
是电子邮件的语料库和它是一个字符串 (eg I need your HELP!!
)
Capital
是一个字符串 (eg HELP
)
Punctuation
是字符串 ( !!
)
我所做的如下:
删除文本中的停用词:
def clean_text(文本):
lim_pun = [char for char in string.punctuation if char in "&#^_"] nopunc = [char for char in text if char not in lim_pun] nopunc = ''.join(nopunc) other_stop=['•','...in','...the','...you\'ve','–','—','-','⋆','...','C.','c','|','...The','...The','...When','...A','C','+','1','2','3','4','5','6','7','8','9','10', '2016', 'speak','also', 'seen','[5].', 'using', 'get', 'instead', "that's", '......','may', 'e', '...it', 'puts', '...over', '[✯]','happens', "they're",'hwo', '...a', 'called', '50s','c;', '20', 'per', 'however,','it,', 'yet', 'one', 'bs,', 'ms,', 'sr.', '...taking', 'may', '...of', 'course,', 'get', 'likely', 'no,'] ext_stopwords=stopwords.words('english')+other_stop clean_words = [word for word in nopunc.split() if word.lower() not in ext_stopwords] return clean_words
然后将这些更改应用于我的数据集:
from sklearn.feature_extraction.text import CountVectorizer
import string
from nltk.corpus import stopwords
df=df.dropna(subset=['Subject', 'Text'])
df['Corpus']=df['Subject']+df['Text']
mex = CountVectorizer(analyzer=clean_text).fit_transform(df['Corpus'].str.lower())
并将我的数据集拆分为训练和测试:
X_train, X_test, y_train, y_test = train_test_split(mex, df['Target'], test_size = 0.80, random_state = 0)
df
包括 1110 封电子邮件和 322 封垃圾邮件。
然后我考虑我的分类器:
# Multinomial Naive Bayes
from sklearn.naive_bayes import MultinomialNB
classifier = MultinomialNB()
classifier.fit(X_train, y_train)
print(classifier.predict(X_train))
print(y_train.values)
# Train data set
from sklearn.metrics import classification_report,confusion_matrix, accuracy_score
from sklearn.metrics import accuracy_score
pred = classifier.predict(X_train)
print(classification_report(y_train ,pred ))
print('Confusion Matrix: \n',confusion_matrix(y_train,pred))
print()
print("MNB Accuracy Score -> ",accuracy_score(y_train, pred)*100)
print('Predicted value: ',classifier.predict(X_test))
print('Actual value: ',y_test.values)
并在测试集上评估模型:
from sklearn.metrics import classification_report,confusion_matrix, accuracy_score
pred = classifier.predict(X_test)
print(classification_report(y_test ,pred ))
print('Confusion Matrix: \n', confusion_matrix(y_test,pred))
print()
print("MNB Accuracy Score -> ",accuracy_score(y_test, pred)*100)
得到大约 60%,这一点都不好。输出:
precision recall f1-score support
0.0 0.77 0.34 0.47 192
1.0 0.53 0.88 0.66 164
accuracy 0.59 356
macro avg 0.65 0.61 0.57 356
weighted avg 0.66 0.59 0.56 356
Confusion Matrix:
[[ 66 126]
[ 20 144]]
我不知道问题是停用词还是我只考虑文本或语料库作为列的事实(将大写字母和标点符号作为模型中的变量也很好)。