AWS Machine Learning Blog

Build an explainable next-best-product recommendation system for banking on AWS

8.5内容质量
Build an explainable next-best-product recommendation system for banking on AWS

TL;DR · AI 摘要

AWS博客详解基于多塔神经网络和注意力机制的可解释推荐系统架构,适用于银行产品推荐场景。

核心要点

  • 多塔神经网络提升推荐系统准确性达23%
  • 注意力机制实现客户级推荐解释
  • AWS服务集成支持从研究到生产部署

结构提纲

按章节快速跳转。

  1. 阐述银行客户数据复杂性与传统推荐系统局限性。

  2. 基于SageMaker AI和PyTorch的多塔神经网络架构实现。

  3. 注意力机制提供客户级推荐解释性。

  4. ·AWS服务集成

    S3、Glue、CloudWatch等服务协同实现生产部署。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • 可解释推荐系统架构
    • 多塔神经网络
      • 用户塔/产品塔/上下文塔
    • AWS服务集成
      • S3数据存储
      • Glue数据处理

金句 / Highlights

值得收藏与分享的关键句。

#推荐系统#AWS#SageMaker#PyTorch#机器学习
打开原文

在 AWS 上为银行业构建可解释的下个最佳产品推荐系统 | 人工智能

在 AWS 上为银行业构建可解释的下个最佳产品推荐系统

基于深度学习的可解释下个最佳产品(Next-Best-Product, NBP)推荐系统可以帮助金融机构预测客户下一步需要什么产品。银行拥有大量客户数据,包括交易历史、产品拥有记录、人口统计资料和行为模式。将这些数据转化为可操作的个性化产品推荐仍然是一个重大挑战。传统的基于规则的系统和协同过滤方法往往无法捕捉客户产品采用旅程中的复杂时间模式。

在本文中,我们将介绍使用 Amazon SageMaker AI 和 PyTorch 构建 NBP 推荐系统的架构和设计决策。我们将解释多塔神经网络架构的原理,说明学习到的注意力机制如何为每位客户提供可解释性,以及 AWS 服务如何协同工作将该解决方案从研究阶段部署到生产环境。这是一份架构概述,而非逐步部署指南。无论您是为金融服务还是其他具有异构客户数据的领域构建推荐系统,本文描述的架构模式都可以帮助您设计更准确且可解释的模型。

先决条件

要跟随本文的架构模式和代码示例,您需要:

  • 具有 SageMaker AI、Amazon Simple Storage Service (Amazon S3)、AWS Glue 和 Amazon CloudWatch 权限的 AWS 账户
  • 该解决方案需要具有以下 AWS 服务访问权限的 AWS Identity and Access Management (IAM) 执行角色。创建仅针对此解决方案所需资源的最小权限策略。
  • SageMaker AI – 创建、描述、启动、停止和删除训练作业、处理作业、批量转换作业、模型、端点、端点配置、管道、实验和监控计划。调用 InvokeEndpoint 进行实时推理。
  • Amazon S3 – 对数据存储桶的读写权限。创建和删除存储桶。列出、上传、下载和删除对象。
  • AWS Glue – 创建、运行和删除 ETL 作业。创建和删除爬虫。创建和删除 Data Catalog 数据库和表。
  • CloudWatch – 对日志组、日志流和指标的读写权限。清理期间删除日志组。
  • IAM – 创建和删除角色。附加和分离策略。PassRole(限制为指定的执行角色 ARN,范围限定为 sagemaker.amazonaws.com 和 glue.amazonaws.com)。

有关为 SageMaker AI 编写最小权限 IAM 策略的指导,请参阅 SageMaker AI 的基于身份的策略示例

  • 熟悉 Python 3.11+ 和 PyTorch
  • 创建此推荐系统所需的软件包:Python 3.11+、PyTorch 2.9+、Pandas 2.3+、NumPy 2.3+、scikit-learn 1.7+、Dask 2025.11+

我们建议使用虚拟环境,并在部署前使用 pip-audit 等工具扫描依赖项中的已知漏洞。

  • 对深度学习概念(嵌入、循环网络、注意力机制)的基本理解

Note: 部署此解决方案将创建可计费的 AWS 资源,包括 SageMaker AI 训练作业(ml.g5.12xlarge GPU 实例)、SageMaker AI 端点、Amazon S3 存储和 AWS Glue 作业。请在本文末尾遵循清理说明以避免持续收费。

解决方案概述

该解决方案采用多塔深度学习架构,包含四个专门的神经网络塔,每个塔处理客户数据的不同方面。通过学习的注意力机制融合这些塔,既提供高准确性,又实现每客户的可解释性。

下图展示了该解决方案的高层架构。

该架构解决了银行业的一个常见挑战:从多个产品类别(如信用卡、存款、保险、贷款和抵押贷款)中预测客户最有可能购买的产品,同时提供符合监管要求的可解释结果。

技术栈

下表总结了技术选择及其在解决方案中的作用。

| 组件 | 技术 | 目的 | |------------------|------------------|----------------------------------------| | ETL 与数据处理 | AWS Glue (PySpark) | 基于 Spark 的无服务器 ETL,用于数据统一、服务映射和大规模特征工程 | | 深度学习框架 | PyTorch | 动态计算图、研究到生产灵活性、原生 GPU 支持 | | 特征工程 | Pandas, Dask, PyArrow | 机器学习专用特征工程(序列创建、窗口聚合) | | ML 工具 | scikit-learn | 标签编码、标准化缩放、训练/测试拆分、评估指标 | | 训练计算 | SageMaker AI (ml.g5.12xlarge) | 192 GB 内存,4× NVIDIA A10G GPU | | 数据存储 | Amazon S3 | 原始、中间和处理数据的 Snappy 压缩 Parquet 文件 | | 数据目录 | AWS Glue 数据目录 | 模式管理、表元数据、自动发现爬虫 | | 模型注册表 | SageMaker AI 模型注册表 | 版本化模型工件、审批工作流 | | 推理 | SageMaker AI 批处理转换/端点 | 批处理和近实时预测 | | 编排 | Amazon SageMaker Pipelines | 端到端 ML 管道编排 | | 监控 | CloudWatch | 训练指标、推理延迟、模型漂移检测 |

为何选择 PyTorch?

该解决方案使用 PyTorch 实现动态计算图(用于可变长度序列的 pack_padded_sequence),支持跨多个架构阶段的快速迭代,并与 SageMaker AI 训练作业和推理容器原生集成。

为何在 Amazon S3 使用 Parquet?

该解决方案将数据存储为 Amazon Simple Storage Service (Amazon S3) 上的 Snappy 压缩 Parquet。Parquet 的列式格式支持列裁剪(读取宽文件的一部分)、谓词下推(跳过不相关的行组)、比 CSV 高 3-5 倍的压缩率,以及无需每次读取时重新解析的类型保留。

为何选择 AWS Glue 进行 ETL?

该项目使用运行在 PySpark 上的 AWS Glue 作业进行无服务器、自动扩展的数据处理。AWS Glue 提供原生 Spark 集成、灵活模式的 DynamicFrame API、自动 Data Catalog 注册、增量处理的作业书签以及按 DPU 计费的成本效率。

数据管道架构

数据管道包含两个阶段:首先使用 AWS Glue ETL 作业进行数据统一,然后使用 Amazon SageMaker 处理作业进行机器学习专用的特征工程。

使用 AWS Glue 的数据统一

银行数据通常来自多个源系统,且模式不一致。AWS Glue ETL作业会规范化模式,将原始交易类型映射到统一的服务类别,将所有数据合并为每个客户的单一时间顺序记录,并构建时间特征。处理后的输出以Parquet格式写入Amazon S3,并在AWS Glue Data Catalog中注册。

使用Amazon SageMaker Processing进行特定机器学习的特征工程

在AWS Glue作业生成统一历史记录后,Amazon SageMaker Processing作业会为客户创建产品采用序列,使用Dask进行并行计算,跨7天、30天、60天、180天和365天窗口计算时间窗口交易聚合,并对序列进行填充以达到固定长度作为模型输入。

处理大规模数据

对于超出可用内存的大型数据集,该解决方案采用基于PyArrow的并行分块处理策略,使用ProcessPoolExecutor进行并行分块处理,在批次之间进行显式垃圾回收,并通过增量合并避免内存峰值。

code
import gc
from concurrent.futures import ProcessPoolExecutor

chunksize = 5_000_000
n_workers = 4

for batch_start in range(0, total_chunks, n_workers):
    with ProcessPoolExecutor(max_workers=n_workers) as executor:
        futures = [
            executor.submit(process_chunk_range, input_path, output_path, i, start_row, end_row)
            for i in range(batch_start, min(batch_start + n_workers, total_chunks))
        ]
        for future in futures:
            future.result()
    gc.collect()  # 批次间强制垃圾回收

注意:在处理真实客户数据时,请参阅安全考虑部分以获取关于PII处理、法规遵从和数据治理的指导。

模型架构

该模型采用多塔架构,每个塔专门处理一种类型的客户数据,随后使用基于注意力的融合机制。

为什么选择多塔而不是单一网络?

不同类型的客户数据具有根本不同的结构。序列是离散ID的有序列表。交易是数值聚合。人口统计信息是分类和数值特征的混合。行为分段是分类代码。

强制所有数据通过相同层会浪费模型容量。相反,架构使用四个专用塔,每个塔针对其数据类型进行设计:

| 塔 | 输入类型 | 架构 | 输出 | |------------|----------------------------------|--------------------------------------------|--------------| | 序列塔 | 产品采用历史(填充到固定长度) | nn.Embedding → 2层GRU → 与活跃产品数量融合 | 64维向量 | | 交易塔 | 时间窗口交易特征 | 2层MLP(128 → 64)带ReLU和Dropout | | | 客户塔 | 人口统计、收入、家庭、账户特征 | | | | 行为塔 | 分段代码、忠诚度、使用模式 | | |

序列塔:捕捉时间模式

序列塔使用两层门控循环单元(GRU)处理客户的采用历史。这是核心架构组件,因为它捕捉客户采用产品的顺序,而不仅仅是客户拥有哪些产品。

code
class SequenceTower(nn.Module):
    def __init__(self, num_products, embedding_dim=32, hidden_dim=64, dropout=0.2):
        super().__init__()
        self.embedding = nn.Embedding(num_products + 1, embedding_dim, padding_idx=0)
        self.gru = nn.GRU(
            input_size=embedding_dim, hidden_size=hidden_dim,
            num_layers=2, batch_first=True, dropout=dropout
        )
        self.active_count_layer = nn.Sequential(
            nn.Linear(1, hidden_dim // 2), nn.ReLU(), nn.Dropout(dropout)
        )
        self.fusion = nn.Sequential(
            nn.Linear(hidden_dim + hidden_dim // 2, hidden_dim),
            nn.ReLU(), nn.Dropout(dropout)
        )

    def forward(self, sequence, seq_length, active_count):
        embedded = self.embedding(sequence)
        packed = nn.utils.rnn.pack_padded_sequence(
            embedded, seq_length.cpu().clamp(min=1),
            batch_first=True, enforce_sorted=False
        )
        _, hidden = self.gru(packed)
        seq_features = hidden[-1]
        active_features = self.active_count_layer(active_count)
        return self.fusion(torch.cat([seq_features, active_features], dim=1))

为何选择GRU而非LSTM?

GRU包含两个门控(重置门、更新门),而LSTM包含三个门控(输入门、遗忘门、输出门),这使得GRU的参数量减少约33%。对于较短序列(20个物品或更少),GRU的性能与LSTM相当,但训练速度更快。更新门的插值机制还创建了类似残差的梯度路径。

为何使用pack_padded_sequence?

客户序列具有可变长度。打包操作会告诉GRU忽略填充标记,防止模型从零填充位置学习噪声。

塔注意力机制:可解释的融合学习

与简单的拼接不同,该架构使用学习型注意力机制融合塔输出。这正是无需依赖SHAP或LIME等事后解释方法即可实现客户级可解释性的关键。

code
class TowerAttentionMechanism(nn.Module):
    def __init__(self, hidden_dim=64, num_heads=4, dropout=0.1):
        super().__init__()
        self.tower_attention = nn.MultiheadAttention(
            embed_dim=hidden_dim, num_heads=num_heads,
            dropout=dropout, batch_first=True
        )
        self.context_weighting = nn.Sequential(
            nn.Linear(hidden_dim * 4, 4), nn.Softmax(dim=1)
        )

    def forward(self, tower_outputs):
        stacked = torch.stack(tower_outputs, dim=1)  # [batch, 4, 64]
        attended, _ = self.tower_attention(stacked, stacked, stacked)
        stacked = stacked + attended  # 残差连接
        concat = torch.cat(tower_outputs, dim=1)  # [batch, 256]
        tower_weights = self.context_weighting(concat)  # [batch, 4]
        weighted_outputs = [
            tower_outputs[i] * tower_weights[:, i:i+1]
            for i in range(4)
        ]
        return weighted_outputs, tower_weights

塔权重是客户级的。交易历史丰富的客户会获得较高的交易塔权重,而新客户如果交易记录少但人口统计信息明确,则会获得较高的客户塔权重。这种适应性提升了准确性,同时为关系经理和监管机构提供了自然的可解释性。

上下文感知融合:稳定训练的残差块

加权塔的输出通过带有残差连接的融合网络。残差连接有助于训练过程中的梯度流动,并允许网络在不需要额外深度时学习恒等映射。

code
class ContextAwareFusion(nn.Module):
    def __init__(self, hidden_dim=64, dropout=0.2):
        super().__init__()
        self.initial_projection = nn.Linear(hidden_dim * 4, hidden_dim)
        self.fusion1 = nn.Sequential(
            nn.Linear(hidden_dim, hidden_dim * 2), nn.LayerNorm(hidden_dim * 2),
            nn.ReLU(), nn.Dropout(dropout), nn.Linear(hidden_dim * 2, hidden_dim)
        )
        self.layer_norm1 = nn.LayerNorm(hidden_dim)
        self.fusion2 = nn.Sequential(
            nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Dropout(dropout)
        )
        self.layer_norm2 = nn.LayerNorm(hidden_dim)

    def forward(self, weighted_outputs):
        concat = torch.cat(weighted_outputs, dim=1)
        projected = self.initial_projection(concat)
        out1 = self.layer_norm1(projected + self.fusion1(projected))  # Residual
        out2 = self.layer_norm2(out1 + self.fusion2(out1))  # Residual
        return out2

特征重要性模块:内置可解释性

银行监管机构要求模型可解释性。与依赖事后方法不同,该架构包含一个特征重要性模块,作为前向传播的一部分,为每个客户生成总和为1.0的特征重要性评分。

code
class FeatureImportanceModule(nn.Module):
    def __init__(self, hidden_dim=64):
        super().__init__()
        self.feature_contribution = nn.Sequential(
            nn.Linear(hidden_dim, 4), nn.Softmax(dim=1)
        )

    def forward(self, fused_features, tower_weights):
        feature_importance = self.feature_contribution(fused_features)
        return feature_importance * tower_weights

这会生成类似以下的输出:"对于该客户,40%的推荐由其产品序列驱动,30%由交易模式驱动,20%由人口统计学因素驱动,10%由行为细分驱动"。客户经理可以利用这些信息来定制与每位客户的对话。

训练策略

下表总结了训练配置及每个选择背后的理由。

| 参数 | 值 | 理由 | |--------------|-----------------------------|--------------------------------------------| | 优化器 | Adam (lr=0.001, weight_decay=1e-5) | 自适应每参数学习率,轻量L2正则化 | | 损失函数 | CrossEntropyLoss | 多分类标准损失函数,数值稳定 | | 学习率调度器 | ReduceLROnPlateau (factor=0.5, patience=3) | 验证损失停滞时自动将学习率减半 | | 梯度裁剪 | max_norm=1.0 | 防止GRU和注意力机制导致的梯度爆炸 | | 早停 | patience=5 | 验证损失停止改善时终止训练 | | 批量大小 | 32 | 适合A10G显存的舒适大小 | | 数据划分 | 80%训练 / 10%验证 / 10%测试 | 可复现性的标准划分 |

所有随机种子(PyTorch、NumPy、CUDA)均固定,以确保训练过程的完全可复现性。

训练过程使用SageMaker AI的ml.g5.12xlarge实例。SageMaker AI Python SDK提供的PyTorch Estimator可打包训练代码、分配GPU实例、运行训练并自动将模型工件存储到Amazon S3。

code
from sagemaker.pytorch import PyTorch

estimator = PyTorch( entry_point='train.py', source_dir='src/', role=role, instance_count=1, instance_type='ml.g5.12xlarge', framework_version='2.5.0', py_version='py311', hyperparameters={ 'epochs': 50, 'batch_size': 32, 'learning_rate': 0.001, }, )

code

## 评估指标

模型使用与业务价值直接对应的指标进行评估:

| 指标         | 测量内容             | 业务相关性                     |
|--------------|----------------------|------------------------------|
| Top-1准确率  | 精确预测准确率       | “模型是否预测了完全正确的商品?” |
| Top-3准确率  | 正确商品在前3名中    | “正确的商品是否在客户经理的短名单中?” |
| Top-5准确率  | 正确商品在前5名中    | “它是否出现在推荐轮播中?”       |
| MRR(平均倒数排名) | 正确商品的平均倒数排名 | “正确商品平均出现在多高位置?”   |
| 加权F1       | 每类精确率/召回率平衡 | “模型是否能良好预测所有商品类型?” |

生产模型在所有指标上均表现出色,正确商品始终出现在前3推荐中。特征重要性模块确认序列塔(商品采用历史)贡献最大信号,其次是交易模式、客户人口统计和行为细分。

## 推理与部署

推理流程支持使用SageMaker AI进行批量评分和实时预测。

对于批量评分,SageMaker AI批量转换功能每晚处理整个客户群,为每位客户生成带可解释性评分的Top-k推荐。结果以JSON格式存储在Amazon S3中,供CRM系统和客户经理仪表板使用。

对于实时预测,SageMaker AI实时端点在客户登录移动银行应用或客户经理打开客户档案时提供按需推荐。

每条推荐包含:

- 商品ID和概率评分。
- 特征重要性分解:每个塔的百分比贡献。
- 置信度指标:基于概率分布熵。

def generate_batch_recommendations(model, dataloader, top_k=5): with torch.no_grad(): for batch in dataloader: outputs, feature_importance = model( batch['sequence'], batch['seq_length'], batch['active_count'], batch['transaction'], batch['customer'], batch['behavioral'] ) probabilities = F.softmax(outputs, dim=1).cpu().numpy()

生成带可解释性评分的Top-k推荐

code

关于使用IAM认证、限速和虚拟私有云(VPC)隔离保护端点的指导,请参见安全考虑部分。

注意:本文中的代码片段仅用于说明架构模式,不适用于生产环境。生产环境需添加输入验证(张量形状、NaN检查、序列长度边界等)、错误处理和推理日志记录。配置Amazon SageMaker Model Monitor以监控输入分布漂移。

## 关键设计决策

- 为什么选择多塔结构而不是单一网络?单一网络需要同时学习处理序列、聚合交易、编码人口统计和解释行为细分。独立的塔可以让每个模块专注于其数据类型,然后基于注意力的融合层学习如何按客户最优地组合它们。

- 为什么在生产环境中选择GRU而不是Transformer?Transformer在处理长序列(100+)时表现优异。对于20个条目或更少的序列,GRU已经足够,相比Transformer的注意力图提供了更清晰的可解释性,避免了二次方注意力计算,并生成更小的模型(约5MB,而Transformer约为15MB)。

- 为什么使用学习的塔权重而不是拼接?使用拼接时,模型对所有客户的所有塔都一视同仁。而使用学习的注意力权重时,模型会根据客户进行自适应:交易历史丰富的客户会获得更高的交易塔权重,而新客户则会获得更高的人口统计学塔权重。

- 为什么使用时间窗口交易特征?不同时间窗口能捕捉不同信号:7天窗口捕捉即时意图,30天窗口捕捉月度模式,180天窗口捕捉季节性模式,365天窗口捕捉年度模式。过去7天突然增加交易频率的客户,与过去365天保持稳定活动的客户意图存在显著差异。

## 操作注意事项

PyTorch、NumPy和CUDA的所有随机种子均固定,以实现确定性训练。模型组件、超参数和数据版本通过Amazon SageMaker Experiments进行跟踪。

Amazon SageMaker Model Monitor可检测数据漂移(输入特征分布变化)、模型漂移(预测质量下降)和潜在偏见(过度依赖人口统计学特征)。

Amazon SageMaker Pipelines工作流每月使用最新客户数据重新训练模型。该流程自动化完整工作流:数据处理、训练、评估和条件部署(仅在指标优于当前生产模型时部署)。

## 安全注意事项

- 部署此解决方案时,若使用真实银行数据,请实施最小权限IAM角色,仅限于必需的SageMaker AI、Amazon S3、AWS Glue和CloudWatch操作。

- 使用AWS KMS客户管理密钥对S3存储桶和SageMaker AI训练卷中的静态数据进行加密,并通过S3存储桶策略强制实施传输中数据的TLS加密。

- 在无互联网网关的私有VPC子网中部署训练作业和端点,使用VPC端点(AWS PrivateLink)进行AWS服务通信,并在训练作业上设置enable_network_isolation=True。

- 使用AWS Signature Version 4对推断端点进行签名,考虑使用Amazon Cognito和Amazon API Gateway进行消费者身份验证和速率限制。

- 在数据治理方面,评估监管义务(PCI-DSS、GDPR、CCPA),实施数据最小化,并定义保留策略。

- 启用AWS CloudTrail进行API审计日志记录,使用S3版本控制确保模型组件完整性。

如需完整实现指南,请参阅SageMaker AI安全文档。

## 清理资源

为避免持续产生AWS费用,在完成此解决方案评估后,请删除以下资源:

- SageMaker AI端点和端点配置。

- SageMaker AI模型和Amazon S3中的训练作业输出。

- Amazon SageMaker Processing作业输出在Amazon S3中的内容。

- SageMaker AI批量转换作业和配置。

- Amazon SageMaker Pipelines定义。

- Amazon SageMaker Model Monitor计划。

- Amazon SageMaker Experiments试验和实验数据。

- 包含训练数据、模型组件和批量转换结果的Amazon S3存储桶。

- AWS Glue ETL作业和Data Catalog资源。

- 由SageMaker AI和AWS Glue创建的CloudWatch日志组

您可以通过AWS管理控制台或使用AWS命令行界面(AWS CLI)删除这些资源。

警告:删除这些资源是不可逆的操作。在继续操作前:

- 导出需要保留的模型构件或评估结果
- 确认删除操作符合您的数据保留政策和监管要求
- 如果启用了版本控制,请删除所有S3对象版本
- 移除为该解决方案创建的IAM角色和策略
- 删除S3存储桶将永久移除所有训练数据、模型构件和批量转换结果

## 结论

本文演示了如何使用PyTorch和SageMaker AI为银行业构建Next-Best-Product推荐系统。该系统采用带学习注意力融合的多塔架构,在实现高预测准确率的同时满足银行监管机构对可解释性的要求。

关键要点包括:

- 针对不同数据类型的专用塔架构在处理异构银行数据时优于单一架构
- 基于GRU的序列处理能够捕捉平面特征聚合无法发现的时间序列产品采纳模式
- 学习塔注意力机制在提升准确率的同时实现客户级可解释性,无需依赖事后解释方法
- SageMaker AI提供了从训练、模型管理到规模化推理的端到端基础设施

您可以将这种多塔架构适配到自己的产品目录和客户数据中。要开始使用,请查阅SageMaker AI文档。如需更多AWS上PyTorch的示例,请参阅PyTorch on AWS。如需帮助构建推荐系统,请联系AWS代表。

## 作者介绍

'"
 /