列变换器与异构数据源

在数据科学领域,数据集往往包含需要不同特征提取和处理流程的组件。这种情况可能发生在数据集包含异构数据类型(例如,栅格图像和文本标题)时,或者数据集存储在pandas.DataFrame中,不同的列需要不同的处理流程。本文将展示如何使用列变换器处理包含不同类型特征的数据集。虽然选择的特征不是特别有用,但它们可以很好地说明这种技术。

20个新闻组数据集

将使用20个新闻组数据集,该数据集包含来自20个主题的新闻组帖子。这个数据集根据特定日期前后发布的帖子被划分为训练和测试子集。为了加快运行时间,只使用2个类别的帖子。每个特征包括有关该帖子的元信息,例如主题和新闻帖子的正文。

from sklearn.datasets import fetch_20newsgroups categories = ["sci.med", "sci.space"] X_train, y_train = fetch_20newsgroups(random_state=1, subset="train", categories=categories, remove=("footers", "quotes"), return_X_y=True) X_test, y_test = fetch_20newsgroups(random_state=1, subset="test", categories=categories, remove=("footers", "quotes"), return_X_y=True)

例如,打印出训练数据集中的第一个帖子,可以看到它包含了发件人、主题、文章ID、组织和行数等信息。

创建变换器

首先,希望创建一个变换器,它能够提取每个帖子的主题和正文。由于这是一个无状态转换(不需要从训练数据中获取状态信息),可以定义一个执行数据转换的函数,然后使用FunctionTransformer创建一个scikit-learn变换器。

def subject_body_extractor(posts): features = np.empty(shape=(len(posts), 2), dtype=object) for i, text in enumerate(posts): headers, _, body = text.partition("\n\n") features[i, 1] = body prefix = "Subject:" sub = "" for line in headers.split("\n"): if line.startswith(prefix): sub = line[len(prefix):] break features[i, 0] = sub return features subject_body_transformer = FunctionTransformer(subject_body_extractor)

还将创建一个变换器,它能够提取文本的长度和句子数量。

def text_stats(posts): return [{"length": len(text), "num_sentences": text.count(".")} for text in posts] text_stats_transformer = FunctionTransformer(text_stats)

分类管道

下面的管道使用SubjectBodyExtractor从每个帖子中提取主题和正文,生成一个(n_samples, 2)数组。然后使用ColumnTransformer计算主题和正文的标准词袋特征,以及正文的文本长度和句子数量。将它们结合起来,加权后训练一个分类器。

from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.decomposition import PCA from sklearn.svm import LinearSVC pipeline = Pipeline([ ("subjectbody", subject_body_transformer), ("union", ColumnTransformer([ ("subject", TfidfVectorizer(min_df=50), 0), ("body_bow", Pipeline([ ("tfidf", TfidfVectorizer()), ("best", PCA(n_components=50, svd_solver="arpack")) ]), 1), ("body_stats", Pipeline([ ("stats", text_stats_transformer), ("vect", DictVectorizer()) ]), 1), ], transformer_weights={"subject": 0.8, "body_bow": 0.5, "body_stats": 1.0})), ("svc", LinearSVC(dual=False)) ], verbose=True) pipeline.fit(X_train, y_train) y_pred = pipeline.predict(X_test) print("Classification report:\n\n{}".format(classification_report(y_test, y_pred)))

最后,在训练数据上拟合管道,并使用它来预测X_test中的主题。然后打印出管道的性能指标。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485