文本特征提取与评估

Machine LearningMachine LearningBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

scikit-learn 库提供了用于文本特征提取和评估的工具。在本实验中,我们将使用 20 新闻组数据集来演示如何从文本数据中提取特征、构建管道以及使用超参数调整来评估模型的性能。

虚拟机使用提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签页,以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们会及时为你解决问题。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn(("Sklearn")) -.-> sklearn/DataPreprocessingandFeatureEngineeringGroup(["Data Preprocessing and Feature Engineering"]) sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/naive_bayes("Naive Bayes") sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/feature_extraction("Feature Extraction") sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/pipeline("Pipeline") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/model_selection("Model Selection") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/datasets("Datasets") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/naive_bayes -.-> lab-49157{{"文本特征提取与评估"}} sklearn/feature_extraction -.-> lab-49157{{"文本特征提取与评估"}} sklearn/pipeline -.-> lab-49157{{"文本特征提取与评估"}} sklearn/model_selection -.-> lab-49157{{"文本特征提取与评估"}} sklearn/datasets -.-> lab-49157{{"文本特征提取与评估"}} ml/sklearn -.-> lab-49157{{"文本特征提取与评估"}} end

加载数据

我们将加载 20 新闻组数据集,该数据集包含大约 20,000 篇新闻组文档,分为 20 个不同类别。在本实验中,我们将关注两个类别:alt.atheism(无神论相关)和 talk.religion.misc(宗教杂谈相关)。

from sklearn.datasets import fetch_20newsgroups

categories = [
    "alt.atheism",
    "talk.religion.misc",
]

data_train = fetch_20newsgroups(
    subset="train",
    categories=categories,
    shuffle=True,
    random_state=42,
    remove=("headers", "footers", "quotes"),
)

data_test = fetch_20newsgroups(
    subset="test",
    categories=categories,
    shuffle=True,
    random_state=42,
    remove=("headers", "footers", "quotes"),
)

print(f"Loading 20 newsgroups dataset for {len(data_train.target_names)} categories:")
print(data_train.target_names)
print(f"{len(data_train.data)} documents")

定义带有超参数调整的管道

我们定义一个管道,它将文本特征向量化器与用于文本分类的简单分类器相结合。我们将使用互补朴素贝叶斯(Complement Naive Bayes)作为分类器,并使用词频 - 逆文档频率向量化器(TfidfVectorizer)进行特征提取。

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import ComplementNB
from sklearn.pipeline import Pipeline
import numpy as np

pipeline = Pipeline(
    [
        ("vect", TfidfVectorizer()),
        ("clf", ComplementNB()),
    ]
)

parameter_grid = {
    "vect__max_df": (0.2, 0.4, 0.6, 0.8, 1.0),
    "vect__min_df": (1, 3, 5, 10),
    "vect__ngram_range": ((1, 1), (1, 2)),  ## 一元语法或二元语法
    "vect__norm": ("l1", "l2"),
    "clf__alpha": np.logspace(-6, 6, 13),
}

超参数调整

我们使用随机搜索交叉验证(RandomizedSearchCV)来探索超参数网格,并为管道找到最佳的超参数组合。在这种情况下,我们设置 n_iter=40 以限制搜索空间。我们可以增加 n_iter 以获得更全面的分析,但这会增加计算时间。

from sklearn.model_selection import RandomizedSearchCV

random_search = RandomizedSearchCV(
    estimator=pipeline,
    param_distributions=parameter_grid,
    n_iter=40,
    random_state=0,
    n_jobs=2,
    verbose=1,
)

print("Performing grid search...")
print("Hyperparameters to be evaluated:")
pprint(parameter_grid)

random_search.fit(data_train.data, data_train.target)

test_accuracy = random_search.score(data_test.data, data_test.target)

结果可视化

我们可以使用 plotly.express 来可视化超参数调整的结果。我们使用散点图来可视化评分时间和平均测试分数之间的权衡。我们还可以使用平行坐标图来进一步可视化平均测试分数作为调整后的超参数的函数。

import pandas as pd
import plotly.express as px
import math

def shorten_param(param_name):
    """Remove components' prefixes in param_name."""
    if "__" in param_name:
        return param_name.rsplit("__", 1)[1]
    return param_name

cv_results = pd.DataFrame(random_search.cv_results_)
cv_results = cv_results.rename(shorten_param, axis=1)

param_names = [shorten_param(name) for name in parameter_grid.keys()]
labels = {
    "mean_score_time": "CV 评分时间 (秒)",
    "mean_test_score": "CV 分数 (准确率)",
}
fig = px.scatter(
    cv_results,
    x="mean_score_time",
    y="mean_test_score",
    error_x="std_score_time",
    error_y="std_test_score",
    hover_data=param_names,
    labels=labels,
)

fig.update_layout(
    title={
        "text": "评分时间与平均测试分数之间的权衡",
        "y": 0.95,
        "x": 0.5,
        "xanchor": "center",
        "yanchor": "top",
    }
)

column_results = param_names + ["mean_test_score", "mean_score_time"]

transform_funcs = dict.fromkeys(column_results, lambda x: x)
## 对 alpha 使用对数刻度
transform_funcs["alpha"] = math.log10
## L1 范数映射到索引 1,L2 范数映射到索引 2
transform_funcs["norm"] = lambda x: 2 if x == "l2" else 1
## 一元语法映射到索引 1,二元语法映射到索引 2
transform_funcs["ngram_range"] = lambda x: x[1]

fig = px.parallel_coordinates(
    cv_results[column_results].apply(transform_funcs),
    color="mean_test_score",
    color_continuous_scale=px.colors.sequential.Viridis_r,
    labels=labels,
)
fig.update_layout(
    title={
        "text": "文本分类器管道的平行坐标图",
        "y": 0.99,
        "x": 0.5,
        "xanchor": "center",
        "yanchor": "top",
    }
)

总结

在本实验中,我们展示了如何从文本数据中提取特征、构建管道,并使用超参数调整来评估模型的性能。我们使用 20 新闻组数据集展示了如何使用随机搜索交叉验证(RandomizedSearchCV)为管道找到最佳的超参数组合,并使用 plotly.express 可视化结果。