简而言之:我编写了一个运行良好的自定义模型,但尝试在 scikit-learn 中重新实现它,但效果不佳。 我不确定我的代码(如下)是否有错误,是否缺少 scikit-learn 项目的推荐预处理,或者我选择的模型是否错误。
该项目的目标是:根据有关产品的博客文章的标题,预测正在撰写的实际产品。总共约有 2,000 种产品。
首先,我使用我从教科书中采用的一些“语言模型”原则构建了一个自定义模型。
我查看了每个产品的标签数据,并统计了其所有标题中使用的所有单词(例如汽车:10、挡风玻璃:3、丈夫:2、轮胎:5})。然后,为了对未见过的标题进行新的预测,我对标题进行了标记并为每个产品构建了一个分数:分数 =(产品计数中单词 1 的百分比频率)*(产品计数中单词 2 的百分比频率)等。我有一个默认的低百分比产品中缺少的单词的频率(而不是使用 0,因为 0 会扰乱排名)。
然后,我会按分数对产品进行排序,并返回前 5 名。我发现,在我执行此操作的情况下,87% 的情况下,正确的产品都位于前 5 名中。
所以现在我尝试在 scikit-learn 中使用朴素贝叶斯来实现它。目前,作为评估指标,我使用默认的 Score() 方法,该方法更加严格,因为模型的顶部(唯一)预测必须是正确的。但我得到了 44% 的准确率,这让我感到惊讶。
- 值得注意的是,我在训练数据上评分时也得到了 44%;我认为这个值应该更高,因为模型已经看到了这些数据。
- 使用线性回归时,我也得到了低分:在已见过的训练数据上得分为 88%,但在未见过的测试数据上得分为 47%。
我的代码:
titles = []
products = []
with open('1pct_singlelabel.csv', 'r', encoding="utf8") as one_pct:
reader = csv.reader(one_pct, delimiter=',', quotechar='"', lineterminator='\n')
for i, row in enumerate(reader):
if (i == 0):
continue # skip header
titles.append(row[2])
products.append(row[1])
text_train, text_test, y_train, y_test = train_test_split(titles, products, random_state=0)
vect = CountVectorizer(min_df=0)
vect.fit(titles)
X_train = vect.transform(text_train)
X_test = vect.transform(text_test)
le = preprocessing.LabelEncoder()
le.fit(products)
y_train = le.transform(y_train)
y_test = le.transform(y_test)
clf = LogisticRegression()
clf.fit(X_train, y_train)
print("Logistic Regression: ")
print(clf.score(X_train, y_train))
print(clf.score(X_test, y_test))
总之,我不明白为什么 scikit-learn 比我的自定义代码差这么多,我的自定义代码并不复杂,而且(据我所知)与朴素贝叶斯类似。我不确定我是否正确使用 scikit-learn。
最佳答案
我认为您误解了 MultinomialNB
的分数值。 Sklearn 没有提供用于评估 top-k 准确性的内置方法。您看到的分数结果是模型准确预测的样本百分比。我想如果你要从 sklearn 中的朴素贝叶斯模型计算前 5 个,它会与你的自定义模型非常相似。
您可以使用predict_proba
方法来获取分配给每个类的概率。从那里您可以对输出进行排序并获取 top-k 值并检查实际输出是否在该输出中。
predictions = clf.predict_proba(test)
k = 5
top_k = np.argsort(probs, axis=1)[-k:]
top_k_preds = clf.classes_[top_k]
从那里您可以检查您的实际类(class)是否位于前 5 名预测之内。
关于python - 自定义模型移至 scikit-learn,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48291032/