我不确定如何使用 Scikit Learn 解释此分类的准确性
I'm not sure how to interpret accuracy of this classification with Scikit Learn
我正在尝试使用 Scikit Learn 使用此处显示的方法对文本数据进行分类。 (http://scikit-learn.org/stable/tutorial/text_analytics/working_with_text_data.html) 除了我正在加载我自己的数据集。
我正在获取结果,但我想了解分类结果的准确性。
from sklearn.datasets import load_files
text_data = load_files("C:/Users/USERNAME/projects/machine_learning/my_project/train", description=None, categories=None, load_content=True, shuffle=True, encoding='latin-1', decode_error='ignore', random_state=0)
from sklearn.pipeline import Pipeline
from sklearn.linear_model import SGDClassifier
text_clf = Pipeline([('vect', CountVectorizer()),
('tfidf', TfidfTransformer()),
('clf', LinearSVC(loss='hinge', penalty='l2',
random_state=42)),
])
_ = text_clf.fit(text_data.data, text_data.target)
docs_new = ["Some test sentence here.",]
predicted = text_clf.predict(docs_new)
print np.mean(predicted == text_data.target)
for doc, category in zip(docs_new, predicted):
print('%r => %s' % (doc, text_data.target_names[predicted]))
在这里,我得到 np.mean 预测为 0.566。
如果我尝试:
twenty_test = load_files("C:/Users/USERNAME/projects/machine_learning/my_project/testing", description=None, categories=None, load_content=True, shuffle=True, encoding='latin-1', decode_error='ignore', random_state=0)
docs_test = twenty_test.data
predicted = text_clf.predict(docs_test)
np.mean(predicted == twenty_test.target)
现在打印为 1。
我不明白它是如何工作的,np.mean 到底是什么,以及为什么在对相同数据进行训练时显示不同的结果。
"train" 文件夹有大约 15 个文件,文本文件夹也有大约 15 个文件,以防万一。一般来说,我对 Scikit Learn 和机器学习还很陌生,所以非常感谢任何帮助。谢谢!
precict()
returns 给定未知文本的预测 class 标签的数组。查看来源 here.
docs_new = ['God is love', 'OpenGL on the GPU is fast', 'java', '3D', 'Cinema 4D']
predicted = clf.predict(X_new_tfidf)
print predicted
for doc, category in zip(docs_new, predicted):
print('%r => %s' % (doc, twenty_train.target_names[category]))
[3 1 2 1 1]
'God is love' => soc.religion.christian
'OpenGL on the GPU is fast' => comp.graphics
'java' => sci.med
'3D' => comp.graphics
'Cinema 4D' => comp.graphics
如您所见,predicted
returns 一个数组。数组中的数字对应于标签的索引,这些索引在随后的 for 循环中访问。
当您执行 np.mean
时,这是为了确定 classifier 的准确性,并且不适用于您的第一个示例,因为文本 "Some text here"
没有标签。这段文字虽然可以用来预测它属于哪个标签。这可以通过更改脚本在您的脚本中实现:
for doc, category in zip(docs_new, predicted):
print('%r => %s' % (doc, text_data.target_names[predicted]))
至:
for doc, category in zip(docs_new, predicted):
print('%r => %s' % (doc, text_data.target_names[category]))
当您第二次调用 np.mean
returns 1
时,这意味着 classifier 能够以 100% 的准确度预测未见过的文档的正确标签.因为, twenty_test
数据也有标签信息。
要获得有关 classifier 准确性的更多信息,您可以:
from sklearn import metrics
print(metrics.classification_report(twenty_test.target, predicted,
target_names=twenty_test.target_names))
precision recall f1-score support
alt.atheism 0.95 0.81 0.87 319
comp.graphics 0.88 0.97 0.92 389
sci.med 0.94 0.90 0.92 396
soc.religion.christian 0.90 0.95 0.93 398
avg / total 0.92 0.91 0.91 1502
如果你想要一个混淆矩阵,你可以:
metrics.confusion_matrix(twenty_test.target, predicted)
array([[258, 11, 15, 35],
[ 4, 379, 3, 3],
[ 5, 33, 355, 3],
[ 5, 10, 4, 379]])
text_data = load_files("C:/Users/USERNAME/projects/machine_learning/my_project/train", ...)
根据 the documentation,该行将文件内容从 C:/Users/USERNAME/projects/machine_learning/my_project/train
加载到 text_data.data
。它还会将每个文档的目标标签(由其整数索引表示)加载到 text_data.target
中。所以 text_data.data
应该是一个字符串列表, text_data.target
应该是一个整数列表。标签源自文件所在的文件夹。您的解释听起来好像您在 C:/.../train/
和 C:/.../test/
中没有任何子文件夹,这可能会产生问题(例如,所有标签都相同)。
from sklearn.pipeline import Pipeline
from sklearn.linear_model import SGDClassifier
text_clf = Pipeline([('vect', CountVectorizer()),
('tfidf', TfidfTransformer()),
('clf', LinearSVC(loss='hinge', penalty='l2',
random_state=42)),
])
_ = text_clf.fit(text_data.data, text_data.target)
以上几行是在您的示例文档上训练(在 .fit()
中)分类器。粗略地说,您是在告诉分类器 (LinearSVC
) 哪些词在哪些文档中出现的频率 (CountVectorizer
、TfidfTransformer
) 以及每个文档具有哪个标签 (text_data.target
).然后,您的分类器会尝试学习一个规则,该规则基本上将这些词频(TF-IDF 值)映射到标签(例如 dog
和 cat
强烈指示标签 animal
)。
docs_new = ["Some test sentence here.",]
predicted = text_clf.predict(docs_new)
在示例数据上训练分类器后,您提供一个全新的文档,让分类器根据它学到的知识为该文档预测最合适的标签。 predicted
应该是只有一个元素的标签(索引)列表(因为你有一个文档),e。 G。 [5]
.
print np.mean(predicted == text_data.target)
在这里,您将预测列表(1 个元素)与训练数据中的标签列表(15 个元素)进行比较,然后取结果的平均值。这没有多大意义,因为列表大小不同,而且您的新示例文档实际上与训练标签没有任何关系。 Numpy 可能会将您预测的标签(例如 5
)与 text_data.target
中的每个元素进行比较。这将创建一个像 [False, False, False, True, False, True, ...]
这样的列表,np.mean
将其解释为 [0, 0, 0, 1, 0, 1, ...
],结果是 1/15 * (0+0+0+1+0+1+...)
.
你应该做的是e。 G。类似于:
docs_new = ["Some test sentence here."]
docs_new_labels = [1] # correct label index of the document
predicted = text_clf.predict(docs_new)
print np.mean(predicted == docs_new_labels)
至少你不应该与你的训练标签进行比较。
请注意,如果 np.mean
returns 1
那么所有文档都正确分类了。对于您的测试数据集,这似乎发生了。确保你的测试和训练数据文件实际上是不同的,因为 100% 的准确率不是很常见(但是可能是你的训练文件数量少的产物)。在旁注中,请注意当前未使用标记化,因此对于您的分类器 here
和 here.
将是完全不同的词。
我正在尝试使用 Scikit Learn 使用此处显示的方法对文本数据进行分类。 (http://scikit-learn.org/stable/tutorial/text_analytics/working_with_text_data.html) 除了我正在加载我自己的数据集。
我正在获取结果,但我想了解分类结果的准确性。
from sklearn.datasets import load_files
text_data = load_files("C:/Users/USERNAME/projects/machine_learning/my_project/train", description=None, categories=None, load_content=True, shuffle=True, encoding='latin-1', decode_error='ignore', random_state=0)
from sklearn.pipeline import Pipeline
from sklearn.linear_model import SGDClassifier
text_clf = Pipeline([('vect', CountVectorizer()),
('tfidf', TfidfTransformer()),
('clf', LinearSVC(loss='hinge', penalty='l2',
random_state=42)),
])
_ = text_clf.fit(text_data.data, text_data.target)
docs_new = ["Some test sentence here.",]
predicted = text_clf.predict(docs_new)
print np.mean(predicted == text_data.target)
for doc, category in zip(docs_new, predicted):
print('%r => %s' % (doc, text_data.target_names[predicted]))
在这里,我得到 np.mean 预测为 0.566。
如果我尝试:
twenty_test = load_files("C:/Users/USERNAME/projects/machine_learning/my_project/testing", description=None, categories=None, load_content=True, shuffle=True, encoding='latin-1', decode_error='ignore', random_state=0)
docs_test = twenty_test.data
predicted = text_clf.predict(docs_test)
np.mean(predicted == twenty_test.target)
现在打印为 1。
我不明白它是如何工作的,np.mean 到底是什么,以及为什么在对相同数据进行训练时显示不同的结果。
"train" 文件夹有大约 15 个文件,文本文件夹也有大约 15 个文件,以防万一。一般来说,我对 Scikit Learn 和机器学习还很陌生,所以非常感谢任何帮助。谢谢!
precict()
returns 给定未知文本的预测 class 标签的数组。查看来源 here.
docs_new = ['God is love', 'OpenGL on the GPU is fast', 'java', '3D', 'Cinema 4D']
predicted = clf.predict(X_new_tfidf)
print predicted
for doc, category in zip(docs_new, predicted):
print('%r => %s' % (doc, twenty_train.target_names[category]))
[3 1 2 1 1]
'God is love' => soc.religion.christian
'OpenGL on the GPU is fast' => comp.graphics
'java' => sci.med
'3D' => comp.graphics
'Cinema 4D' => comp.graphics
如您所见,predicted
returns 一个数组。数组中的数字对应于标签的索引,这些索引在随后的 for 循环中访问。
当您执行 np.mean
时,这是为了确定 classifier 的准确性,并且不适用于您的第一个示例,因为文本 "Some text here"
没有标签。这段文字虽然可以用来预测它属于哪个标签。这可以通过更改脚本在您的脚本中实现:
for doc, category in zip(docs_new, predicted):
print('%r => %s' % (doc, text_data.target_names[predicted]))
至:
for doc, category in zip(docs_new, predicted):
print('%r => %s' % (doc, text_data.target_names[category]))
当您第二次调用 np.mean
returns 1
时,这意味着 classifier 能够以 100% 的准确度预测未见过的文档的正确标签.因为, twenty_test
数据也有标签信息。
要获得有关 classifier 准确性的更多信息,您可以:
from sklearn import metrics
print(metrics.classification_report(twenty_test.target, predicted,
target_names=twenty_test.target_names))
precision recall f1-score support
alt.atheism 0.95 0.81 0.87 319
comp.graphics 0.88 0.97 0.92 389
sci.med 0.94 0.90 0.92 396
soc.religion.christian 0.90 0.95 0.93 398
avg / total 0.92 0.91 0.91 1502
如果你想要一个混淆矩阵,你可以:
metrics.confusion_matrix(twenty_test.target, predicted)
array([[258, 11, 15, 35],
[ 4, 379, 3, 3],
[ 5, 33, 355, 3],
[ 5, 10, 4, 379]])
text_data = load_files("C:/Users/USERNAME/projects/machine_learning/my_project/train", ...)
根据 the documentation,该行将文件内容从 C:/Users/USERNAME/projects/machine_learning/my_project/train
加载到 text_data.data
。它还会将每个文档的目标标签(由其整数索引表示)加载到 text_data.target
中。所以 text_data.data
应该是一个字符串列表, text_data.target
应该是一个整数列表。标签源自文件所在的文件夹。您的解释听起来好像您在 C:/.../train/
和 C:/.../test/
中没有任何子文件夹,这可能会产生问题(例如,所有标签都相同)。
from sklearn.pipeline import Pipeline
from sklearn.linear_model import SGDClassifier
text_clf = Pipeline([('vect', CountVectorizer()),
('tfidf', TfidfTransformer()),
('clf', LinearSVC(loss='hinge', penalty='l2',
random_state=42)),
])
_ = text_clf.fit(text_data.data, text_data.target)
以上几行是在您的示例文档上训练(在 .fit()
中)分类器。粗略地说,您是在告诉分类器 (LinearSVC
) 哪些词在哪些文档中出现的频率 (CountVectorizer
、TfidfTransformer
) 以及每个文档具有哪个标签 (text_data.target
).然后,您的分类器会尝试学习一个规则,该规则基本上将这些词频(TF-IDF 值)映射到标签(例如 dog
和 cat
强烈指示标签 animal
)。
docs_new = ["Some test sentence here.",]
predicted = text_clf.predict(docs_new)
在示例数据上训练分类器后,您提供一个全新的文档,让分类器根据它学到的知识为该文档预测最合适的标签。 predicted
应该是只有一个元素的标签(索引)列表(因为你有一个文档),e。 G。 [5]
.
print np.mean(predicted == text_data.target)
在这里,您将预测列表(1 个元素)与训练数据中的标签列表(15 个元素)进行比较,然后取结果的平均值。这没有多大意义,因为列表大小不同,而且您的新示例文档实际上与训练标签没有任何关系。 Numpy 可能会将您预测的标签(例如 5
)与 text_data.target
中的每个元素进行比较。这将创建一个像 [False, False, False, True, False, True, ...]
这样的列表,np.mean
将其解释为 [0, 0, 0, 1, 0, 1, ...
],结果是 1/15 * (0+0+0+1+0+1+...)
.
你应该做的是e。 G。类似于:
docs_new = ["Some test sentence here."]
docs_new_labels = [1] # correct label index of the document
predicted = text_clf.predict(docs_new)
print np.mean(predicted == docs_new_labels)
至少你不应该与你的训练标签进行比较。
请注意,如果 np.mean
returns 1
那么所有文档都正确分类了。对于您的测试数据集,这似乎发生了。确保你的测试和训练数据文件实际上是不同的,因为 100% 的准确率不是很常见(但是可能是你的训练文件数量少的产物)。在旁注中,请注意当前未使用标记化,因此对于您的分类器 here
和 here.
将是完全不同的词。