自助式机器学习与关系型深度学习

张开发
2026/4/8 9:07:23 15 分钟阅读

分享文章

自助式机器学习与关系型深度学习
原文towardsdatascience.com/self-service-ml-with-relational-deep-learning-beb693a21d5b?sourcecollection_archive---------9-----------------------#2024-10-22直接在关系型数据库上进行机器学习https://medium.com/brechterlaurin?sourcepost_page---byline--beb693a21d5b--------------------------------https://towardsdatascience.com/?sourcepost_page---byline--beb693a21d5b-------------------------------- Laurin Brechter·发布于 Towards Data Science ·阅读时间 7 分钟·2024 年 10 月 22 日–https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/fd3ee51120626ff5eccf5c3fc113c1db.png我们数据集的关系模式来源图像由作者提供在这篇博客中我们将深入探讨一种有趣的新型深度学习DL方法——关系型深度学习RDL。我们还将通过在一个实际的电子商务公司数据库而不是数据集上进行 RDL来获得一些实践经验。简介在现实世界中我们通常会有一个关系型数据库我们希望在其上执行一些机器学习任务。但是特别是当数据库高度规范化时这意味着需要大量耗时的特征工程而且由于需要进行许多聚合操作细节会丢失。此外我们可以构造出许多不同的特征组合而每种组合可能都会带来良好的性能[2]。这意味着我们很可能会遗漏一些对机器学习任务相关的信息。这类似于计算机视觉的早期阶段在深度神经网络出现之前当时的特征是通过像素值手工构建的。如今模型直接处理原始像素而不再依赖于这一中间层。关系型深度学习关系型深度学习RDL承诺为表格学习带来相同的效果。也就是说它通过直接在关系型数据库上进行学习去除了构建特征矩阵的额外步骤。它通过将数据库及其关系转化为图形来实现这一点其中表格中的每一行成为一个节点表格之间的关系成为边缘。行的值存储在节点内部作为节点特征。在这篇博客文章中我们将使用来自 Kaggle 的这个电子商务数据集它包含了一个电子商务平台的交易数据采用星型模式中央事实表交易和一些维度表。完整的代码可以在这个笔记本中找到。在整篇博客文章中我们将使用 relbench 库来执行 RDL。在 relbench 中我们必须做的第一件事是指定我们关系数据库的模式。下面是我们如何为数据库中的“transactions”表指定模式的一个示例。我们将表格作为 pandas 数据框传递并指定主键和时间戳列。主键列用于唯一标识实体。时间戳确保当我们想要预测未来的交易时我们只能从过去的交易中学习。在图中这意味着信息只能从时间戳较低即过去的节点流向时间戳较高的节点。此外我们还指定了关系中存在的外键。在本例中“transactions”表有一列“customer_key”它是一个指向“customer_dim”表的外键。tables[transactions]Table(dfpd.DataFrame(t),pkey_colt_id,fkey_col_to_pkey_table{customer_key:customers,item_key:products,store_key:stores},time_coldate)其余的表格需要以相同的方式进行定义。请注意如果你已经有了数据库模式这个过程也可以自动化。由于数据集来自 Kaggle我需要手动创建模式。我们还需要将日期列转换为实际的 pandas 日期时间对象并去除任何 NaN 值。classEcommerceDataBase(Dataset):# example of creating your own dataset: https://github.com/snap-stanford/relbench/blob/main/tutorials/custom_dataset.ipynbval_timestamppd.Timestamp(year2018,month1,day1)test_timestamppd.Timestamp(year2020,month1,day1)defmake_db(self)-Database:tables{}customersload_csv_to_db(BASE_DIR/customer_dim.csv).drop(columns[contact_no,nid]).rename(columns{coustomer_key:customer_key})storesload_csv_to_db(BASE_DIR/store_dim.csv).drop(columns[upazila])productsload_csv_to_db(BASE_DIR/item_dim.csv)transactionsload_csv_to_db(BASE_DIR/fact_table.csv).rename(columns{coustomer_key:customer_key})timesload_csv_to_db(BASE_DIR/time_dim.csv)ttransactions.merge(times[[time_key,date]],ontime_key).drop(columns[payment_key,time_key,unit])t[date]pd.to_datetime(t.date)tt.reset_index().rename(columns{index:t_id})t[quantity]t.quantity.astype(int)t[unit_price]t.unit_price.astype(float)products[unit_price]products.unit_price.astype(float)t[total_price]t.total_price.astype(float)print(t.isna().sum(axis0))print(products.isna().sum(axis0))print(stores.isna().sum(axis0))print(customers.isna().sum(axis0))tables[products]Table(dfpd.DataFrame(products),pkey_colitem_key,fkey_col_to_pkey_table{},time_colNone)tables[customers]Table(dfpd.DataFrame(customers),pkey_colcustomer_key,fkey_col_to_pkey_table{},time_colNone)tables[transactions]Table(dfpd.DataFrame(t),pkey_colt_id,fkey_col_to_pkey_table{customer_key:customers,item_key:products,store_key:stores},time_coldate)tables[stores]Table(dfpd.DataFrame(stores),pkey_colstore_key,fkey_col_to_pkey_table{})returnDatabase(tables)至关重要的是作者引入了训练表的概念。这个训练表本质上定义了机器学习任务。这里的思路是我们希望预测数据库中某个实体的未来状态即未来的值。我们通过指定一个表来实现这一点该表中的每一行都有一个时间戳、实体的标识符和我们希望预测的某些值。id 用于指定实体时间戳则指定我们需要预测该实体的时间点。这也将限制可用于推断该实体值的数据即仅限过去的数据。值本身就是我们想要预测的内容即真实值。在我们的案例中我们有一个在线平台和顾客。我们想要预测顾客在接下来的 30 天内的收入。我们可以通过执行 DuckDB 的 SQL 语句来创建训练表。这就是 RDL 的巨大优势因为我们可以仅通过 SQL 创建任何类型的机器学习任务。例如我们可以定义一个查询来选择买家在接下来的 30 天内的购买次数从而做出客户流失预测。dfduckdb.sql(f select timestamp, customer_key, sum(total_price) as revenue from timestamp_df t left join transactions ta on ta.date t.timestamp INTERVAL {self.timedelta} and ta.date t.timestamp group by timestamp, customer_key ).df().dropna()结果将是一个表格其中卖家 ID 作为我们要预测的实体的键收入作为目标时间戳作为我们需要进行预测的时间即我们只能使用直到这个时间点的数据来进行预测。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/249add07383580218f2c4e9e3b3cf33d.png训练表格图片来源作者以下是创建“customer_revenue”任务的完整代码。classCustomerRevenueTask(EntityTask):# example of custom task: https://github.com/snap-stanford/relbench/blob/main/tutorials/custom_task.ipynbtask_typeTaskType.REGRESSION entity_colcustomer_keyentity_tablecustomerstime_coltimestamptarget_colrevenuetimedeltapd.Timedelta(days30)# how far we want to predict revenue into the future.metrics[r2,mae]num_eval_timestamps40defmake_table(self,db:Database,timestamps:pd.Series[pd.Timestamp])-Table:timestamp_dfpd.DataFrame({timestamp:timestamps})transactionsdb.table_dict[transactions].df dfduckdb.sql(f select timestamp, customer_key, sum(total_price) as revenue from timestamp_df t left join transactions ta on ta.date t.timestamp INTERVAL {self.timedelta} and ta.date t.timestamp group by timestamp, customer_key ).df().dropna()print(df)returnTable(dfdf,fkey_col_to_pkey_table{self.entity_col:self.entity_table},pkey_colNone,time_colself.time_col,)有了这些我们已经完成了大部分工作。剩下的工作流程将是类似的独立于 ML 任务。我能够从示例笔记本中复制大部分代码这些代码是 relbench 提供的。例如我们需要对节点特征进行编码。在这里我们可以使用 GloVe 嵌入来编码所有文本特征如产品描述和产品名称。fromtypingimportList,Optionalfromsentence_transformersimportSentenceTransformerfromtorchimportTensorclassGloveTextEmbedding:def__init__(self,device:Optional[torch.device]None):self.modelSentenceTransformer(sentence-transformers/average_word_embeddings_glove.6B.300d,devicedevice,)def__call__(self,sentences:List[str])-Tensor:returntorch.from_numpy(self.model.encode(sentences))之后我们可以将这些转换应用于我们的数据并构建出图。fromtorch_frame.config.text_embedderimportTextEmbedderConfigfromrelbench.modeling.graphimportmake_pkey_fkey_graph text_embedder_cfgTextEmbedderConfig(text_embedderGloveTextEmbedding(devicedevice),batch_size256)data,col_stats_dictmake_pkey_fkey_graph(db,col_to_stype_dictcol_to_stype_dict,# speficied column typestext_embedder_cfgtext_embedder_cfg,# our chosen text encodercache_diros.path.join(root_dir,frel-ecomm_materialized_cache),# store materialized graph for convenience)剩下的代码将是从标准层构建 GNN、编写训练循环以及进行一些评估。我会将这些代码省略在这篇博客中因为它非常标准且在任务之间相同。你可以在这里查看该笔记本。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/885dfaed5f9ea9705ffb86ecb8d1fca9.png训练结果图片来源作者因此我们可以训练这个 GNN使其达到大约 0.3 的 r2 和 500 的 MAE。这意味着它预测卖家未来 30 天的收入时平均误差为±$500。当然我们无法知道这是否算好可能通过结合经典 ML 和特征工程我们能够获得 80%的 r2。结论关系深度学习是一种有趣的新型 ML 方法特别是在我们拥有复杂的关系模式时人工特征工程会显得过于繁琐。它使我们能够仅通过 SQL 定义 ML 任务这对于那些没有深入数据科学背景但懂一些 SQL 的人尤其有用。这也意味着我们可以快速迭代并进行大量不同任务的实验。与此同时这种方法也存在一些问题例如训练 GNN 的难度和从关系模式构建图的复杂性。此外问题在于 RDL 在性能上能否与经典的 ML 模型竞争。过去我们已经看到像 XGBoost 这样的模型在表格预测问题上比神经网络更优。参考文献[1] Robinson, Joshua, 等. “RelBench: A Benchmark for Deep Learning on Relational Databases.”arXiv, 2024,arxiv.org/abs/2407.20060。[2] Fey, Matthias, 等. “Relational deep learning: Graph representation learning on relational databases.”arXiv 预印本 arXiv:2312.04615(2023)。[3] Schlichtkrull, Michael, 等. “使用图卷积网络对关系数据建模。”语义网第十五届国际会议ESWC 2018希腊克里特岛赫拉克利翁2018 年 6 月 3 日至 7 日会议录 15. 施普林格国际出版社2018 年。

更多文章