为什么数据清理会降低准确性?
Why data cleaning decreases accuracy?
使用 scikit 中的 20 个新闻组学习可重复性。当我训练 svm 模型然后通过删除页眉、页脚和引号来执行数据清理时,准确性会降低。不是应该通过数据清理来改进吗?做所有这些然后得到更差的准确性有什么意义?
我创建了这个带有数据清理的示例,以帮助您理解我指的是什么:
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import accuracy_score
categories = ['alt.atheism', 'comp.graphics']
newsgroups_train = fetch_20newsgroups(subset='train', categories=categories, shuffle=True, random_state=2017,
remove=('headers', 'footers', 'quotes') )
newsgroups_test = fetch_20newsgroups(subset='test', categories=categories,shuffle=True, random_state=2017,
remove=('headers', 'footers', 'quotes') )
y_train = newsgroups_train.target
y_test = newsgroups_test.target
vectorizer = TfidfVectorizer(sublinear_tf=True, smooth_idf = True, max_df=0.5, ngram_range=(1, 2),stop_words='english')
X_train = vectorizer.fit_transform(newsgroups_train.data)
X_test = vectorizer.transform(newsgroups_test.data)
from sklearn.svm import SVC
from sklearn import metrics
clf = SVC(C=10, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma=1, kernel='rbf', max_iter=-1,
probability=False, random_state=None, shrinking=True, tol=0.001,
verbose=False)
clf = clf.fit(X_train, y_train)
y_train_pred = clf.predict(X_train)
y_test_pred = clf.predict(X_test)
print('Train accuracy_score: ', metrics.accuracy_score(y_train, y_train_pred))
print('Test accuracy_score: ',metrics.accuracy_score(newsgroups_test.target, y_test_pred))
print("-"*12)
print("Train Metrics: ", metrics.classification_report(y_train, y_train_pred))
print("-"*12)
print("Test Metrics: ", metrics.classification_report(newsgroups_test.target, y_test_pred))
数据清理前的结果:
Train accuracy_score: 1.0
Test accuracy_score: 0.9731638418079096
数据清理后的结果:
Train accuracy_score: 0.9887218045112782
Test accuracy_score: 0.9209039548022598
不一定是你的数据清理,我假设你运行脚本两次?
问题是这行代码:
clf = SVC(C=10, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma=1, kernel='rbf', max_iter=-1,
probability=False, random_state=None, shrinking=True, tol=0.001,
verbose=False)
random_state=None
您应该将随机状态修改为例如random_state=42
,否则你无法产生相同的结果,如果你现在再次 运行 这段代码,你将再次得到不同的结果。
编辑:
解释在 dataset 网站本身:
如果您实施:
import numpy as np
def show_top10(classifier, vectorizer, categories):
feature_names = np.asarray(vectorizer.get_feature_names())
for i, category in enumerate(categories):
top10 = np.argsort(classifier.coef_[i])[-10:]
print("%s: %s" % (category, " ".join(feature_names[top10])))
您现在可以看到这些特征过度拟合的许多事物:
几乎每个组都是通过 headers 来区分的,例如 NNTP-Posting-Host: 和 Distribution: 出现的频率高低。
另一个重要特征涉及发件人是否隶属于大学,如他们的 headers 或他们的签名所示。
“文章”一词是一个重要特征,基于人们引用以前帖子的频率,例如:“在文章 [文章 ID],[名称] <[e-mail 地址]> 中写道:”
其他特征与当时发帖的特定人员的姓名和 e-mail 地址匹配。
有了如此丰富的区分新闻组的线索,分类器几乎不需要从文本中识别主题,而且它们的表现都处于相同的高水平。
因此,加载 20 个新闻组数据的函数提供了一个名为 remove 的参数,告诉它从每个文件中删除哪些信息。 remove 应该是一个包含
的任何子集的元组
总结:
remove thingy 防止你的数据泄露,这意味着你的训练数据中有你在预测阶段不会有的信息,所以你必须删除它,否则你会得到更好的结果,但是这个将不会出现新数据。
使用 scikit 中的 20 个新闻组学习可重复性。当我训练 svm 模型然后通过删除页眉、页脚和引号来执行数据清理时,准确性会降低。不是应该通过数据清理来改进吗?做所有这些然后得到更差的准确性有什么意义?
我创建了这个带有数据清理的示例,以帮助您理解我指的是什么:
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import accuracy_score
categories = ['alt.atheism', 'comp.graphics']
newsgroups_train = fetch_20newsgroups(subset='train', categories=categories, shuffle=True, random_state=2017,
remove=('headers', 'footers', 'quotes') )
newsgroups_test = fetch_20newsgroups(subset='test', categories=categories,shuffle=True, random_state=2017,
remove=('headers', 'footers', 'quotes') )
y_train = newsgroups_train.target
y_test = newsgroups_test.target
vectorizer = TfidfVectorizer(sublinear_tf=True, smooth_idf = True, max_df=0.5, ngram_range=(1, 2),stop_words='english')
X_train = vectorizer.fit_transform(newsgroups_train.data)
X_test = vectorizer.transform(newsgroups_test.data)
from sklearn.svm import SVC
from sklearn import metrics
clf = SVC(C=10, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma=1, kernel='rbf', max_iter=-1,
probability=False, random_state=None, shrinking=True, tol=0.001,
verbose=False)
clf = clf.fit(X_train, y_train)
y_train_pred = clf.predict(X_train)
y_test_pred = clf.predict(X_test)
print('Train accuracy_score: ', metrics.accuracy_score(y_train, y_train_pred))
print('Test accuracy_score: ',metrics.accuracy_score(newsgroups_test.target, y_test_pred))
print("-"*12)
print("Train Metrics: ", metrics.classification_report(y_train, y_train_pred))
print("-"*12)
print("Test Metrics: ", metrics.classification_report(newsgroups_test.target, y_test_pred))
数据清理前的结果:
Train accuracy_score: 1.0
Test accuracy_score: 0.9731638418079096
数据清理后的结果:
Train accuracy_score: 0.9887218045112782
Test accuracy_score: 0.9209039548022598
不一定是你的数据清理,我假设你运行脚本两次?
问题是这行代码:
clf = SVC(C=10, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma=1, kernel='rbf', max_iter=-1,
probability=False, random_state=None, shrinking=True, tol=0.001,
verbose=False)
random_state=None
您应该将随机状态修改为例如random_state=42
,否则你无法产生相同的结果,如果你现在再次 运行 这段代码,你将再次得到不同的结果。
编辑:
解释在 dataset 网站本身: 如果您实施:
import numpy as np
def show_top10(classifier, vectorizer, categories):
feature_names = np.asarray(vectorizer.get_feature_names())
for i, category in enumerate(categories):
top10 = np.argsort(classifier.coef_[i])[-10:]
print("%s: %s" % (category, " ".join(feature_names[top10])))
您现在可以看到这些特征过度拟合的许多事物:
几乎每个组都是通过 headers 来区分的,例如 NNTP-Posting-Host: 和 Distribution: 出现的频率高低。
另一个重要特征涉及发件人是否隶属于大学,如他们的 headers 或他们的签名所示。
“文章”一词是一个重要特征,基于人们引用以前帖子的频率,例如:“在文章 [文章 ID],[名称] <[e-mail 地址]> 中写道:”
其他特征与当时发帖的特定人员的姓名和 e-mail 地址匹配。
有了如此丰富的区分新闻组的线索,分类器几乎不需要从文本中识别主题,而且它们的表现都处于相同的高水平。
因此,加载 20 个新闻组数据的函数提供了一个名为 remove 的参数,告诉它从每个文件中删除哪些信息。 remove 应该是一个包含
的任何子集的元组总结:
remove thingy 防止你的数据泄露,这意味着你的训练数据中有你在预测阶段不会有的信息,所以你必须删除它,否则你会得到更好的结果,但是这个将不会出现新数据。