如何在NLTK电影短评分类代码中计算混淆矩阵与ROC曲线?
没问题,我来帮你搞定混淆矩阵和ROC曲线的计算!你的现有代码已经完成了数据预处理和分类器训练,只需要补充几部分代码就能得到这两个评估指标,下面一步步来:
第一步:导入所需的库
首先需要导入sklearn的评估模块和绘图库,在代码开头加上:
from sklearn.metrics import confusion_matrix, roc_curve, auc import matplotlib.pyplot as plt import numpy as np
第二步:计算混淆矩阵
混淆矩阵需要真实标签和预测标签的对应数据,我们先从测试集中提取真实标签,再获取两个分类器的预测结果:
提取测试集真实标签
# 从测试集中取出所有真实标签 y_true = [category for (features, category) in testing_set]
计算朴素贝叶斯分类器的混淆矩阵
# 获取原生Naive Bayes的预测标签 y_pred_nb = [classifier.classify(features) for (features, category) in testing_set] # 生成混淆矩阵,指定标签顺序为['pos', 'neg']确保结果对应正确 cm_nb = confusion_matrix(y_true, y_pred_nb, labels=['pos', 'neg']) print("Naive Bayes 混淆矩阵:") print(cm_nb)
计算MultinomialNB的混淆矩阵
# 获取MNB分类器的预测标签 y_pred_mnb = [MNB_classifier.classify(features) for (features, category) in testing_set] cm_mnb = confusion_matrix(y_true, y_pred_mnb, labels=['pos', 'neg']) print("\nMultinomialNB 混淆矩阵:") print(cm_mnb)
第三步:绘制ROC曲线
ROC曲线需要分类器对正类(这里是'pos')的概率预测值,所以我们需要把标签转换成数值,并获取概率输出:
标签数值化
# 将文本标签转为数值:pos=1,neg=0,方便ROC计算 y_true_num = np.array([1 if label == 'pos' else 0 for label in y_true])
处理MultinomialNB的概率预测
因为MNB_classifier是用SklearnClassifier包装的,我们可以直接访问底层的sklearn模型来获取概率:
# 把NLTK格式的特征转换为sklearn能处理的特征矩阵 def features_to_matrix(featuresets): feature_matrix = [] for (feat_dict, _) in featuresets: # 按照words_features的顺序提取特征值,保证和训练时一致 feat_list = [feat_dict[word] for word in words_features] feature_matrix.append(feat_list) return np.array(feature_matrix) # 转换测试集特征 X_test = features_to_matrix(testing_set) # 获取MNB对正类(pos)的预测概率 y_proba_mnb = MNB_classifier._clf.predict_proba(X_test)[:, 1]
计算并绘制MNB的ROC曲线
# 计算ROC曲线参数和AUC值 fpr_mnb, tpr_mnb, thresholds_mnb = roc_curve(y_true_num, y_proba_mnb) roc_auc_mnb = auc(fpr_mnb, tpr_mnb) # 绘制ROC曲线 plt.figure(figsize=(8, 6)) plt.plot(fpr_mnb, tpr_mnb, color='darkorange', lw=2, label=f'MultinomialNB ROC曲线 (AUC = {roc_auc_mnb:.2f})') # 绘制随机猜测的基准线 plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--') plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel('假阳性率(FPR)') plt.ylabel('真阳性率(TPR)') plt.title('受试者工作特征曲线(ROC)') plt.legend(loc="lower right") plt.show()
处理原生NaiveBayes的概率预测
NLTK的原生NaiveBayesClassifier没有predict_proba,但可以用prob_classify方法获取概率分布:
# 获取原生NaiveBayes对正类的预测概率 y_proba_nb = [] for (features, _) in testing_set: prob_dist = classifier.prob_classify(features) # 取出pos类的概率 y_proba_nb.append(prob_dist.prob('pos')) y_proba_nb = np.array(y_proba_nb) # 计算ROC曲线和AUC fpr_nb, tpr_nb, thresholds_nb = roc_curve(y_true_num, y_proba_nb) roc_auc_nb = auc(fpr_nb, tpr_nb) # 把两个分类器的ROC画在一起对比 plt.figure(figsize=(8, 6)) plt.plot(fpr_nb, tpr_nb, color='green', lw=2, label=f'Naive Bayes ROC曲线 (AUC = {roc_auc_nb:.2f})') plt.plot(fpr_mnb, tpr_mnb, color='darkorange', lw=2, label=f'MultinomialNB ROC曲线 (AUC = {roc_auc_mnb:.2f})') plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--') plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) plt.xlabel('假阳性率(FPR)') plt.ylabel('真阳性率(TPR)') plt.title('受试者工作特征曲线对比') plt.legend(loc="lower right") plt.show()
关于投票分类器的补充
如果你的VoteClassifier支持概率输出(比如你的confidence方法返回的是正类概率),可以类似上面的方式获取y_proba_voted,然后计算它的ROC曲线。比如如果sentiment函数返回的第二个值是pos类的置信度,那可以这样:
y_proba_voted = [] for (rev, _) in documents[100:]: # 对应测试集的原文本 _, conf = sentiment(rev) y_proba_voted.append(conf) y_proba_voted = np.array(y_proba_voted) # 后续计算ROC的步骤和上面一致
最后提醒一下:你的训练集只取了前100个样本,这可能会导致模型效果很差,建议增大训练集的比例(比如training_set = featuresets[:int(len(featuresets)*0.8)],测试集取剩下的20%),这样评估指标会更有参考价值。
内容的提问来源于stack exchange,提问作者ASIM USMAN
相关产品推荐
相关产品推荐

