我正在尝试训练和测试数据集中的多项式贝叶斯,并进行相应拆分。处理完数据后,我得到了一个消息数组和一个标签数组。我正在尝试将.fit()和.predict()与这些数据一起使用,但是它不起作用。
我的数据如下:
emails = ['example mail', 'another example mail', ..]
labels = ['ham', 'spam', ..]
这是我目前正在尝试的:
bayes = sklearn.linear_model.MultinomialNB().fit(emails, labels)
答案 0 :(得分:0)
在训练模型之前,您需要对数据进行更多处理。 该模型不能直接在纯字符串上工作。 您可以使用任何nlp库(我建议使用Spacy或nltk stanford)来处理您的数据(例如:标记化,词形化和获得段落的基本概念...) 建议您添加一个热门编码get_dummies()
答案 1 :(得分:0)
请发布完整的信息,例如实际错误
首先,Sklearn .fit()接受两个参数,1)2D训练数据数组,以及2)1D标签/目标数组。因此,您需要将输入变量重新格式化为列表列表(即使您只有1个预测变量)
from sklearn.naive_bayes import MultinomialNB
model = MultinomialNB()
emails = [['example mail'], ['another example mail']]
labels = ['ham', 'spam']
model.fit(emails, labels)
一旦运行,您将收到另一个错误:
TypeError: '<' not supported between instances of 'numpy.ndarray' and 'int'
因为您要将单词传递给数学方程式。根据文档https://nlp.stanford.edu/IR-book/html/htmledition/naive-bayes-text-classification-1.html中链接的实现细节,您应该从输入文本中构建自己的参数(例如,字数统计,情感分析,二值化特征(当前存在/不存在)等)。
如果您正确格式化数据,为每封电子邮件生成字符数和字数,您可能会有一些帮助:
from sklearn.naive_bayes import MultinomialNB
model = MultinomialNB()
emails = [['example mail'], ['another example mail']]
emails = [[len(x[0]), len(x[0].split())] for x in emails]
labels = ['ham', 'spam']
model.fit(emails, labels)
然后,如果您通过相似格式的测试数据,您将获得输出
emails = [['test mail'], ['another test mail']]
emails = [[len(x[0]), len(x[0].split())] for x in emails]
model.predict(emails)
Out[17]: array(['ham', 'spam'], dtype='<U4')
由于两封测试邮件的字数相同,而字符数相似,因此可以得到预期的火腿/垃圾邮件输出
答案 2 :(得分:0)
没有机器学习算法可以将文本作为输入或输出进行处理。两者始终都是数字。您需要找到一种将输入(电子邮件)和输出(标签)都映射到数值从而保留信息的方式。
关于标签,您需要做的可能是将每个标签映射到不同的整数,然后再使用它们来训练分类器:
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
encoded_labels = le.fit_transform(labels)
Sklearn模型可以自己完成这项工作,因此可能没有必要。
关于您的输入,可能会变得更加棘手。 这是您真正的问题所在。
您可以进行一次热编码,但是这是一个非常糟糕的主意,因为这样两封邮件就只能是相同或不同的(而且大多数情况下它们是不同的),无论它们多么相似。 ,而且您的输入将具有很高的维度。
word2vec(https://radimrehurek.com/gensim/models/word2vec.html)是一种通过分析句子的词之间的逻辑将词映射到向量的方法。与一次性编码相反,类似的邮件将包含一些相同的单词或句子结构,即使它们不是完全相等,它们在潜在空间中也很接近。这意味着可以保留信息。
您只需要找到一种方法即可将句子映射到向量,因为句子是基于词向量的输入。也许将句子中单词的单词向量连接起来,并使用0填充,以便将所有句子(即使单词数不同)都映射到长度相同的向量。
但是它可能无法很好地工作,而且即使您已经用word2vec映射了单词,也找不到一种可以保留信息的方式将句子映射到向量的方法并不明显。看到这篇文章:How to calculate the sentence similarity using word2vec model of gensim with python。
另一种方法是尝试使用 doc2vec 实现而不是word2vec。旨在将整个句子映射到矢量,而不仅仅是单词,而这正是您想要做的。