代码报错AttributeError: 'function'无iterrows属性,如何获取模型准确率?
垃圾文本分类代码错误排查与准确率实现
问题概述
编写了基于pandas、nltk的垃圾文本分类代码,运行时触发错误AttributeError: 'function' object has no attribute 'iterrows',同时希望正确获取模型准确率,查阅accuracy_score文档后仍无法解决。
错误原因分析
- 主函数参数传递错误:在
if __name__ == '__main__'中,最后一行print((text_classifier(accuracy_score)))将accuracy_score函数作为参数传给text_classifier,但text_classifier的第一个参数要求是pandas DataFrame,导致get_data函数中调用df.iterrows()时,df变成了accuracy_score函数,从而触发AttributeError。 - 特征提取逻辑混乱:
- 混淆了数据集的标签列和文本列:
spam.csv中v1是分类标签(ham/spam),v2是邮件文本,但原代码中错误地将row['v1']当作文本、row['v2']当作标签。 get_feature和get_feature_text函数逻辑不合理,比如text[-3]会在文本长度不足3时触发索引错误,且特征提取逻辑完全无法反映垃圾文本的特征;get_feature_text中错误使用DataFrame.rename处理字符串,属于API误用。
- 混淆了数据集的标签列和文本列:
- 准确率获取方式未正确落地:原代码中
text_classifier已经返回了准确率,但主函数调用错误,导致无法正确输出。
代码修正与优化
1. 修正核心错误点
- 调整数据集列的使用逻辑,正确区分标签和文本。
- 重写合理的特征提取函数(以文本长度和是否包含垃圾邮件常见关键词为例)。
- 修正主函数的调用方式,正确输出准确率。
- 同时支持用nltk自带的准确率方法和sklearn的
accuracy_score计算准确率。
2. 完整修正代码
import pandas as pd import nltk from sklearn.metrics import accuracy_score # 读取数据集,保留核心列并重命名 df = pd.read_csv('spam.csv', encoding='ISO-8859-1') df = df[['v1', 'v2']].rename(columns={'v1': 'label', 'v2': 'text'}) # 特征提取函数:提取对垃圾邮件有区分度的特征 def get_features(text): text = text.lower() return { 'text_length': len(text), 'has_free': 'free' in text, 'has_win': 'win' in text or 'winner' in text, 'has_money': '$' in text or 'dollar' in text, 'has_urgent': 'urgent' in text } # 生成nltk分类器所需的(特征字典, 标签)格式数据 def process_dataset(df, feature_func=get_features): dataset = [] for _, row in df.iterrows(): label = row['label'] text = row['text'] if isinstance(text, str): dataset.append((feature_func(text), label)) return dataset # 划分训练集与测试集 def split_train_test(dataset, train_ratio=0.9): total = len(dataset) train_size = int(total * train_ratio) return dataset[:train_size], dataset[train_size:] # 训练分类器并计算两种方式的准确率 def train_spam_classifier(df, feature_func=get_features): dataset = process_dataset(df, feature_func) train_data, test_data = split_train_test(dataset) # 训练朴素贝叶斯分类器 classifier = nltk.NaiveBayesClassifier.train(train_data) # 用nltk自带方法计算准确率 nltk_accuracy = nltk.classify.accuracy(classifier, test_data) # 用sklearn的accuracy_score计算准确率(验证结果) true_labels = [label for _, label in test_data] pred_labels = [classifier.classify(feat) for feat, _ in test_data] sklearn_accuracy = accuracy_score(true_labels, pred_labels) return classifier, nltk_accuracy, sklearn_accuracy # 预测单条文本并可选输出准确率 def predict_single_text(text, show_accuracy=False): classifier, nltk_acc, sklearn_acc = train_spam_classifier(df) if show_accuracy: print(f"NLTK计算准确率: {nltk_acc:.4f}") print(f"Sklearn计算准确率: {sklearn_acc:.4f}") pred_result = classifier.classify(get_features(text)) print(f"\n文本内容: {text}") print(f"预测分类: {pred_result}") classifier.show_most_informative_features(10) if __name__ == '__main__': print("模型训练中...") # 预测单条文本并显示准确率 predict_single_text("Win a free iPhone now! Click the link below!", show_accuracy=True) # 单独输出模型准确率 _, nltk_acc, sklearn_acc = train_spam_classifier(df) print("\n模型最终准确率:") print(f"NLTK方法: {nltk_acc:.4f}") print(f"Sklearn方法: {sklearn_acc:.4f}")
关键说明
- 错误修复:主函数不再传递错误参数,正确传入数据集
df,彻底解决iterrows的属性错误。 - 特征优化:替换原不合理的特征逻辑,改为提取垃圾邮件高频出现的关键词、文本长度等有效特征,提升模型分类能力。
- 准确率获取:
- 使用
nltk.classify.accuracy直接传入分类器和测试集,快速得到准确率。 - 同时用sklearn的
accuracy_score,通过提取测试集真实标签与预测标签计算结果,两种方法可互相验证。
- 使用
- 数据处理:对原始
spam.csv做了列精简与重命名,让数据结构更清晰,避免冗余列干扰。
内容的提问来源于stack exchange,提问作者Muhammadzakyyusufgmailcom Zmy2
相关产品推荐
相关产品推荐

