图机器学习(18)——使用图构建文档主题分类模型

图机器学习(18)------使用图构建文档主题分类模型

    • [0. 前言](#0. 前言)
    • [1. 构建文档主题分类器](#1. 构建文档主题分类器)
    • [2. 模型训练](#2. 模型训练)
    • [3. 模型性能评估](#3. 模型性能评估)

0. 前言

我们已经学习了如何处理非结构化信息,并掌握了如何用图结构表征这类信息。我们从 Reuters-21578 基准数据集出发,通过标准 NLP 工具对文本信息进行标记和结构化处理。随后利用这些高层特征构建了多种网络类型:基于知识的网络、二分网络、节点子集的投影网络,以及反映数据集主题关联的网络。通过局部和全局属性展示了这些量化指标如何表征和描述结构各异的网络类型。在本节中,将介绍利用这些图结构构建机器学习模型,运用无监督技术识别语义社区,将主题/话题相似的文档进行聚类。

1. 构建文档主题分类器

为演示图结构的应用价值,我们将重点利用二分实体-文档图提供的拓扑信息和实体关联来训练多标签分类器,从而实现文档主题预测。具体而言分析浅层机器学习方法,使用从二分网络中提取的嵌入来训练传统分类器,例如随机森林分类器。

(1) 选取前 10 个主题进行建模,这些主题已具备足够的文档数据用于模型训练与评估:

python 复制代码
from collections import Counter
topics = Counter([label for document_labels in corpus["label"] for label in document_labels]).most_common(10)

输出结果如下所示,显示了我们将在后续分析中关注的主题名称:

python 复制代码
[('earn', 3964), ('acq', 2369), ('money-fx', 717),
('grain', 582), ('crude', 578), ('trade', 485),
('interest', 478), ('ship', 286), ('wheat', 283),
('corn', 237)]

(2) 在训练主题分类器时,我们需要将焦点限制在仅属于这些标签的文档上,获得过滤后的语料库:

python 复制代码
topicsList = [topic[0] for topic in topics]
topicsSet = set(topicsList)
dataset = corpus[corpus["label"].apply(lambda x: len(topicsSet.intersection(x))>0)]

完成数据集提取与结构化处理后,即可开始训练主题模型并评估其性能。接下来,我们将利用网络信息实现主题分类任务的浅层学习方法。

(3) 首先,在二分图上应用 Node2Vec 算法计算嵌入向量。经过过滤的文档-文档网络通常具有包含大量孤立节点的外围结构,这些节点无法从拓扑信息中受益;而未过滤的文档-文档网络则存在过多边连接,会导致算法可扩展性问题。因此,使用二分图对于有效利用拓扑信息及实体与文档间的关联至关重要:

python 复制代码
from node2vec import Node2Vec
node2vec = Node2Vec(G, dimensions=10)
model = node2vec.fit(window=20)
embeddings = model.wv

其中,嵌入向量的维度以及用于生成随机游走的窗口大小都属于需要通过交叉验证优化的超参数。

(4) 为提高计算效率,可以预先计算向量集并保存到本地,并在优化过程中直接调用存储结果。该方案基于半监督或转导学习场景的假设,即在训练时我们已经掌握整个数据集的连接信息(除标签外)。将嵌入向量存储至文件:

python 复制代码
pd.DataFrame(embeddings.vectors,
            index=embeddings.index2word
).to_pickle(f"graphEmbeddings_{dimension}_{window}.p")

(5) 这些嵌入可以集成到 scikit-learn 转换器中,以便在网格搜索交叉验证过程中使用:

python 复制代码
from sklearn.base import BaseEstimator

class EmbeddingsTransformer(BaseEstimator):
    
    def __init__(self, embeddings_file):
        self.embeddings_file = embeddings_file
        
    def fit(self, *args, **kwargs):
        self.embeddings = pd.read_pickle(self.embeddings_file)
        return self
        
    def transform(self, X):
        return self.embeddings.loc[X.index]
    
    def fit_transform(self, X, y):
        return self.fit().transform(X)

(6) 构建建模训练管道时,我们先将语料库划分为训练集和测试集:

python 复制代码
def train_test_split(corpus):
    graphIndex = [index for index in corpus.index if index in graphEmbeddings.embeddings.index]
    
    train_idx = [idx for idx in graphIndex if "training/" in idx]
    test_idx = [idx for idx in graphIndex if "test/" in idx]
return corpus.loc[train_idx], corpus.loc[test_idx]
train, test = train_test_split(dataset)

(7) 构建函数提取特征和标签:

python 复制代码
def get_labels(corpus, topicsList=topicsList):
    return corpus["label"].apply(
        lambda labels: pd.Series({label: 1 for label in labels}).reindex(topicsList).fillna(0)
    )[topicsList]
def get_features(corpus):
    return corpus["parsed"] #graphEmbeddings.transform(corpus["parsed"])
def get_features_and_labels(corpus):
    return get_features(corpus), get_labels(corpus)

(8) 实例化建模管道:

python 复制代码
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier 
from sklearn.multioutput import MultiOutputClassifier
pipeline = Pipeline([
    ("embeddings", graphEmbeddings),
    ("model", model)
]) 

2. 模型训练

定义参数空间以及交叉验证网格搜索配置:

python 复制代码
param_grid = {
    "embeddings__embeddings_file": files,
    "model__estimator__n_estimators": [50, 100], 
    "model__estimator__max_features": [0.2,0.3, "auto"], 
    #"model__estimator__max_depth": [3, 5]
}
grid_search = GridSearchCV(pipeline, param_grid=param_grid, cv=5, n_jobs=-1, 
                           scoring=lambda y_true, y_pred: f1_score(y_true, y_pred,average='weighted'))

最后,使用 sklearn APIfit 方法训练主题模型:

python 复制代码
model = grid_search.fit(features, labels)

3. 模型性能评估

确定最佳模型后,我们可以在测试数据集上使用该模型评估其性能。定义辅助函数用于获取一组预测结果:

python 复制代码
def get_predictions(model, features):
    return pd.DataFrame(
        model.predict(features), 
        columns=topicsList, 
        index=features.index
)
preds = get_predictions(model, get_features(test))
labels = get_labels(test)

查看训练分类器的性能:

python 复制代码
from sklearn.metrics import classification_report
print(classification_report(labels, preds))

输出结果如下所示:

shell 复制代码
              precision    recall  f1-score   support

           0       0.97      0.94      0.95      1087
           1       0.93      0.74      0.83       719
           2       0.79      0.45      0.57       179
           3       0.96      0.64      0.77       149
           4       0.95      0.59      0.73       189
           5       0.95      0.45      0.61       117
           6       0.87      0.41      0.56       131
           7       0.83      0.21      0.34        89
           8       0.69      0.34      0.45        71
           9       0.61      0.25      0.35        56

   micro avg       0.94      0.72      0.81      2787
   macro avg       0.85      0.50      0.62      2787
weighted avg       0.92      0.72      0.79      2787
 samples avg       0.76      0.75      0.75      2787

可以尝试调整分析流程的类型和超参数,变换不同模型,并在编码嵌入向量时试验不同取值。上述方法属于转导式学习,因为它使用了基于完整数据集训练的嵌入向量。这种情形在半监督任务中十分常见------当标注信息仅存在于少量数据点子集时,我们的任务就是推断所有未知样本的标签。

相关推荐
xixixi777772 分钟前
英伟达Agent专用全模态模型出击,仿冒AI智能体泛滥成灾,《AI伦理安全指引》即将落地——AI治理迎来“技术-风险-规范”三重奏
人工智能·5g·安全·ai·大模型·英伟达·智能体
直奔標竿4 分钟前
Java开发者AI转型第二十六课!Spring AI 个人知识库实战(五)——联网搜索增强实战
java·开发语言·人工智能·spring boot·后端·spring
数据皮皮侠AI8 分钟前
中国城市可再生能源数据集(2005-2021)|顶刊 Sci Data 11 种能源面板
大数据·人工智能·笔记·能源·1024程序员节
G311354227312 分钟前
如何用 QClaw 龙虾做一个规律作息健康助理 Agent
大数据·人工智能·ai·云计算
幂律智能13 分钟前
零售行业合同管理数智化转型解决方案
大数据·人工智能·零售
旺财矿工14 分钟前
零基础搭建 OpenClaw 2.6.6 Win11 本地化运行环境
人工智能·openclaw·小龙虾·龙虾·openclaw安装包
九成宫16 分钟前
动手学深度学习PyTorch版初步安装过程
人工智能·pytorch·深度学习
Traving Yu16 分钟前
Prompt提示词工程
人工智能·prompt
NOCSAH17 分钟前
统好AI CRM功能解析:智能录入与跟进
人工智能
He少年18 分钟前
【AI 辅助编程做设备数据采集:一个真实项目的迭代复盘(OpenSpec 驱动)】
人工智能