使用 Amazon SageMaker Clarify 解释德甲赛况 xGoals

45eb7a7ff3f8bbc3662af09c8edcb126.gif

最激动人心的 Amazon re:Invent 2020 公告 https://www.youtube.com/watch?v=PjDysgCvRqY 之一是新增一项 Amazon SageMaker https://aws.amazon.com/sagemaker/ 功能,帮助检测机器学习 (ML) 模型中的偏差并解释模型预测:Amazon SageMaker Clarify https://aws.amazon.com/sagemaker/clarify/ 。在当今世界,人们大规模运用 ML 算法进行预测,对于大型科技组织而言,能够向客户解释他们为什么会根据 ML 模型的预测做出某项决策正变得越来越重要。关键是,这直接摆脱了原有的基础模式,这种模式如同一个“封闭盒子”,我们可以观察输入和输出,但看不到内部运作情况。这不仅开辟了进一步分析的途径,以便对模型配置进行迭代和进一步改进,还为客户提供了前所未有的高水平模型预测分析。

Amazon SageMaker Clarify 一个特别值得关注的使用案例来自 Deutsche Fußball Liga (DFL) 由亚马逊云科技提供支持的德甲赛况,旨在提供有关 xGoals https://aws.amazon.com/blogs/machine-learning/the-tech-behind-the-bundesliga-match-facts-xgoals-how-machine-learning-is-driving-data-driven-insights-in-soccer/ 模型预测的有趣见解。由亚马逊云科技提供支持的德甲赛况在足球比赛期间,为世界各地的德甲球迷提供更具吸引力的球迷体验。它为观众提供有关射门难度的信息、他们最喜欢的球员的表现,并可说明球队的攻防趋势。

借助 Amazon SageMaker Clarify,DFL 现在能够以互动的方式解释,在确定 ML 模型依靠什么来预测 xGoals 值时,需要使用哪些关键的基本特征。xGoal(预期进球的缩写)是经计算得出的球员从球场上任意位置射门得分的概率。了解各自的特征属性并解释相关结果有助于模型调试,从而提高预测质量。或许最重要的是,透明度的提高有助于建立对 ML 模型的信心和信任,为未来的合作和创新提供无数机会。更佳的可解释性可推动更广泛的采用。话不多话,我们一起详细了解一下吧!

德甲赛况

由亚马逊云科技提供支持的德甲赛况为德甲比赛提供根据官方比赛数据实时生成的先进统计数据和深入见解。这些统计数据通过国内外广播公司以及 DFL 的平台、频道和应用程序提供给观众。如此一来,全球 5 亿多德甲球迷可以更深入地了解球员、球队和联赛,并获得更加个性化的体验和下一代统计数据。

通过德甲赛况 xGoals https://aws.amazon.com/blogs/machine-learning/the-tech-behind-the-bundesliga-match-facts-xgoals-how-machine-learning-is-driving-data-driven-insights-in-soccer/ ,DFL 可以评估球员从球场上任意位置射门得分的概率。实时计算每次射门的进球概率,以便让观众了解射门的难度和进球的几率。xGoals 值越高(所有值都介于 0 到 1 之间),进球的可能性就越大。在本博文中,我们将仔细研究这个 xGoals 指标,深入了解基础 ML 模型的内部运作情况,以确定其为何对个人射门和整个足球赛季的数据进行预测。

编制和检查训练数据

德甲 xGoals ML 模型将射门得分事件数据与通过帧率为 25-Hz 的先进跟踪技术获得的高精度数据相结合,较以前的 xGoals 模型更佳。通过实时跟踪足球和球员的位置,定制模型可以确定更多特征,例如射门角度、球员与球门之间的距离、球员的速度、对方防守球员数量以及对方门将的扑救范围等。我们使用 ROC 曲线下面积 https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#AUC (AUC) 作为训练作业的客观指标,并自 2017 年开始就使用 Amazon SageMaker XGBoost 算法 https://docs.aws.amazon.com/sagemaker/latest/dg/xgboost.html ,通过德甲联赛超过 4 万次历史射门数据训练 xGoals 模型。有关使用 Amazon SageMaker Python SDK https://sagemaker.readthedocs.io/en/stable/frameworks/xgboost/using_xgboost.html 和 XGBoost 超参数优化 https://github.com/awslabs/amazon-sagemaker-examples/blob/master/hyperparameter_tuning/xgboost_direct_marketing/hpo_xgboost_direct_marketing_sagemaker_python_sdk.ipynb 进行 xGoals 训练的更多信息,请参阅 The tech behind the Bundesliga Match Facts xGoals: How machine learning is driving data-driven insights in soccer https://aws.amazon.com/blogs/machine-learning/the-tech-behind-the-bundesliga-match-facts-xgoals-how-machine-learning-is-driving-data-driven-insights-in-soccer/ 。

只需查看原始训练数据集中的数行,便可了解我们正在处理的特征类型;海量射门尝试数据集中混合了二进制、分类和连续值。以下屏幕截图显示了用于模型训练和可解释性处理的 17 个特征中的 8 个。

1ee9fe0756c8212f51221faf3efa04db.png

Amazon SageMaker Clarify

Amazon SageMaker 可极大地帮助刚入门的数据科学家和经验丰富的 ML 学者编制数据集、构建和训练自定义模型,然后将其部署到医疗、媒体与娱乐、金融等众多垂直行业中。

与大多数 ML 工具一样,它缺乏一种深入研究和解释所述模型结果,或调查训练数据集是否存在偏差的方法。随着 Amazon SageMaker Carify 的发布,这一切都发生了变化,它使您能够以可重复和可扩展的方式检测偏差并实施模型可解释性。

缺乏可解释性通常会给组织采用 ML(机器学习)带来阻碍。近年来,解决这种缺乏模型可解释性的理论方法已经非常成熟,其中有一个出色的框架逐渐成为可解释人工智能 (AI) 领域中的关键工具:SHAP (SHapley Additive Explanations https://arxiv.org/pdf/1705.07874v2.pdf)。对这种方法的全面解释超出了本文的范围,故在此简要介绍一下:SHAP 的核心是通过提出以下问题来构建模型解释:“当某个特征从我们的模型中删除时,将会发生怎样的预测变更?” SHAP 值就是这个问题的答案 – 它们直接计算特征从幅度和方向这两个方面对预测的影响。基于联盟博弈论,SHAP 值旨在将数据实例的特征值描述为联盟中的参与者,然后告诉我们如何在各种特征之间公平分配支出(预测)。SHAP 框架的一个比较考究的特点是,它既与模型无关,又高度可扩展,可用于简单的线性模型,同时还适用于包含数百层的深度复杂神经网络。

使用 Clarify 解释德甲 xGoals 模型行为

现在,我们已经介绍了数据集和 ML 可解释性,可以开始初始化 Amazon SageMaker Clarify 处理器 https://docs.aws.amazon.com/sagemaker/latest/dg/clarify-configure-processing-jobs.html ,它可用于计算我们所需的 SHAP 值。此处理器中的所有参数都是通用的,且仅与您当前的生产环境和可供您使用的亚马逊云科技资源相关。

首先,让我们来定义 Amazon SageMaker Clarify 处理作业,以及 Amazon SageMaker 会话、Amazon Identity and Access Management http://aws.amazon.com/iam (IAM) 执行角色和 Amazon Simple Storage Service http://aws.amazon.com/s3 (Amazon S3) 存储桶,其代码如下:

from sagemaker import clarify
import os 

session = sagemaker.Session()
role = sagemaker.get_execution_role()
bucket = session.default_bucket()
region = session.boto_region_name

prefix = ‘sagemaker/dfl-tracking-data-xgb’ 

clarify_processor = clarify.SageMakerClarifyProcessor(role=role,
        instance_count=1,
        instance_type=’ml.c5.xlarge’,
        sagemaker_session=session,
        max_runtime_in_seconds=1200*30,
        volume_size_in_gb=100*10)

*左滑查看更多

我们可以将 CSV 训练文件保存到 Amazon S3,然后指定 Amazon SageMaker Carify 作业的训练数据和结果路径,如下所示:

DATA_LAKE_OBSERVED_BUCKET = ‘sts-openmatchdatalake-dev’
DATA_PREFIX = ‘sagemaker_input’
MODEL_TYPE = ‘observed’
TRAIN_TARGET_FINAL = ‘train-clarify-dfl-job.csv’

csv_train_data_s3_path = os.path.join(
                “s3://”,
                DATA_LAKE_OBSERVED_BUCKET,
                DATA_PREFIX,
                MODEL_TYPE,
                TRAIN_TARGET_FINAL
                )

RESULT_FILE_NAME = ‘dfl-clarify-explainability-results’ 

analysis_result_path = ‘s3://{}/{}/{}’.format(bucket, prefix, RESULT_FILE_NAME)

*左滑查看更多

现在我们已经对 Amazon SageMaker Carify 处理器进行了实例化,并定义了我们的可解释性训练数据集,接下来我们可以开始指定特定于问题的实验配置:

BASELINE = [-1, 61.91, 25.88, 16.80, 15.52, 3.41, 2.63, 1,
     -1, 1, 2.0, 3.0, 2.0, 0.0, 12.50, 0.46, 0.68]

COLUMN_HEADERS = [“target”, “1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”,
             “9”, “10”, “11”, “12”, “13”, “14”, “15”, “16”, “17”]

NBR_SAMPLES = 1000
AGG_METHOD = “mean_abs”
TARGET_NAME = ‘target’
MODEL_NAME = ‘sagemaker-xgboost-201014-0704-0010-a28f221a’

*左滑查看更多

以下是需要注意的重要输入参数,如前面的相关代码片段所示:

  • 基线– 这些基线对于计算我们的模型解释至关重要。每个特征都有一个基线值。在我们的实验中,我们为连续数值特征使用平均值,为分类特征使用模式。有关更多信息,请参阅用于可解释性的 SHAP 基准 https://docs.aws.amazon.com/sagemaker/latest/dg/clarify-feature-attribute-shap-baselines.html 。

  • NBR_SAMPLES – SHAP 算法中使用的样本数量。

  • AGG_METHOD – 用于计算 SHAP 总值的聚合方法,在我们的案例中,是所有实例的 SHAP 绝对值的均值。

  • TARGET_NAME – 基础 XGBoost 模型尝试预测的目标特征的名称。

  • MODEL_NAME –(之前)训练过的 Amazon SageMaker XGBoost 模型终端节点名称。

我们直接将重要的参数传递给 clarify.ModelConfigclarify.SHAPConfig 和 clarify.DataConfig实例。运行以下代码,启动正在处理的作业:

model_config = clarify.ModelConfig(model_name=MODEL_NAME,
                         instance_type=’ml.c5.xlarge’,
                         instance_count=1,
                           accept_type=’text/csv’)

shap_config = clarify.SHAPConfig(baseline=[BASELINE],
                       num_samples=NBR_SAMPLES,
                       agg_method=AGG_METHOD,
                       use_logit=False,
                       save_local_shap_values=True)

explainability_data_config = clarify.DataConfig(
     s3_data_input_path=csv_train_data_s3_path,
     s3_output_path=analysis_result_path,
     label=TARGET_NAME,
     headers=COLUMN_HEADERS,
     dataset_type=’text/csv’)

clarify_processor.run_explainability(data_config=explainability_data_config,
                         model_config=model_config,
                         explainability_config=shap_config)

*左滑查看更多

全局解释

在我们对整个 xGoals 训练集运行 Clarify 可解释性分析之后,我们可以快速轻松地查看 SHAP 总值及其每个特征的分布情况,从而能够绘制给定特征值的正面或负面变化如何影响最终预测。我们使用开源 SHAP https://github.com/slundberg/shap 库来绘制在我们的处理作业中计算的 SHAP 值。

下图是全局解释的示例,可让我们了解模型及其在多个数据点上的总特征组合。AngleToGoalDistanceToGoal 和 DistanceToGoalClosest 这些特征在预测我们的目标变量(即是否对目标进行评分)方面扮演着最重要的角色。

a319ff687650912e91950383c10a442f.png

这种类型的图可以更进一步,为我们提供比条形图更多的背景信息,让我们得以更深入地了解每个特征的 SHAP 值分布(允许您映射给定特征值的变化如何影响最终预测),以及预测工具与目标变量之间的正负关系。以下图中的每个数据点都表示一次射门尝试。

8d086fdab0ba59e99cf04567b177bc54.png

正如图右侧垂直轴所示,红色数据点表示特征值较高,蓝色数据点表示值较低。对射门预测值的正面和负面影响显示在 X 轴上,这是从 SHAP 值得出的。例如,据此您可以从逻辑上推断,射门角度增大会提高预测的对数几率(这与针对进球是否得分的 True 预测相关联)。

值得注意的是,对于结果垂直离度更高的区域,重叠数据点的集中程度更高,这使我们能够了解每个特征的 Shapley 值的分布情况。

这些特征是根据其重要性从高到低排序的。当我们在三个时间段(2017–2018、2018–2019 和 2019–2020 年)比较此图时,我们发现特征重要性及其相关的 SHAP 值分布几乎没有变化。在德甲联赛中,所有俱乐部的情况都是如此,只有少数俱乐部偏离了常规。

尽管我们所有的比赛事件中都未涉及到点球(特征值均 =1),但它仍然必须包含在 Clarify 处理作业 https://docs.aws.amazon.com/sagemaker/latest/dg/clarify-processing-job-run.html 中,因为它也包含在最初的 XGBoost 模型训练中。我们需要在模型训练和 Carify 处理的两个特征集之间保持一致。

xGoals 特征依赖关系

我们可以更深入地研究 SHAP 特征依赖关系图,这可以说是最简单的全局性解释。我们只需选择一个特征,然后在 X 轴上绘制特征值,在 Y 轴上绘制相应的 SHAP 值。下图显示了我们最重要特征的这一关系:

  • AngleToGoal – 小角度 (< 25) 会降低进球的几率,角度越大,进球几率越高。

  • DistanceToGoal – 远离球门中心时,进球的几率会急剧下降(模拟对数递减函数)。超过一定距离,它对 SHAP 值没有影响;在所有其他条件都相同的情况下,从 20 米开外射门与从 40 米开外射门,进球的几率是一样的。可以通过以下事实来解释这种观察结果:在此范围内的球员只会在出于某种特殊原因时射门,这会增加他们的进球几率;可能是守门员已弃门而出,或者是附近没有防守队员来接近球员并阻止射门。

  • DistanceToGoalClosest – 当然,这与 DistanceToGoal 具有很大的相关性,但是远远不及与线性关系的相关性:随着与球门最近点的距离不断增加,SHAP 值会单调递减。

9ee4d705829fab7bac666ad470332f94.png

如果我们仔细研究两个(影响力较小的)分类变量,会发现在所有其他条件都相同的情况下,头球始终会降低进球的几率,而任意球则会提升进球的几率。鉴于  FootShot=Yes 和 FreeKick=No 在 0 SHAP 值附近的垂直离散度,我们无法得出它们对进球预测的影响。

7f332fcf9fe15b872bd38bb008d6f377.png

xGoals 特征交互

在考虑各个特征影响之后,我们可以通过突出显示不同特征之间的相互作用(附加影响)来改进依赖关系图。我们使用博弈论中的 Shapley 交互指数 https://arxiv.org/abs/1902.05622#:~:text=The%20Shapley%20value%20is%20a,up%20to%20some%20size%20k 来计算所有特征的 SHAP 交互值,以获得每实例一个维度为 F X F  的矩阵,其中 F 是特征的数量。利用这一交互指数,我们可以为具有最强交互的 SHAP 特征依赖关系图着色。

例如,假设我们想知道变量 DistanceToGoal 和 PressureSum 如何交互,以及他们对 DistanceToGoal 的 SHAP 值的影响。PressureSum 的计算方法非常简单,就是将对方球员对射手施加的所有个人压力相加。我们可以看到DistanceToGoal  和目标变量之间的负相关,离球门的距离越近,进球的几率就越高。当然,在那些具有高进球预测率的比赛中,DistanceToGoal 和 PressureSum 之间存在着强大的反向关系;即前者减少,后者上升。

几乎所有接近球门的得分射门都是以大于 45 度的角度命中的。距离球门越远,角度会随之减小。这是合乎情理的;您曾几何时看到有人在距离球门 40 米开外的边线上射门得分?

73e61bb80a8705fec99adf1fe3bf9c93.png

请记住,根据前面的结果,射门的角度越大,进球的几率越高;我们可以查看防守球员数量的 SHAP 值,并确定只有一两个防守球员靠近进攻球员时才会出现这种情况。

76b253cf80561b85ab30a6448aeb70de.png

仔细回顾我们最初的全局汇总图,我们可以看到特征PressureSum 和 PressureMax 的一些不确定性(由零 SHAP 值标记周围的密集点簇表示)。我们可以使用交互图来深入研究这些值,然后尝试揭开并确定导致这种情况的原因。

通过检查,我们发现,即使对于两个最重要的特征,它们对更改 PressureSum 的 SHAP 值的影响也很小。此处的关键之处在于,当球员面临的压力很小或没有压力时,低DistanceToGoal 会增加进球的几率;而在接近球门面临很大压力时,情况则相反:球员进球的几率较小。这些影响对于 AngleToGoal 而言则是相反的:我们看到,随着压力的增加,增大 AngleToGoal 会降低 PressureSum 的 SHAP 值。令人欣慰的是,我们的特征交互图能够证实我们的先见之明,并量化游戏中的各种力量。

93295599c9706c086b25915cb0e4e11c.png

毫不奇怪,射门角度小于 25 度的得分头球屈指可数。但是,更有趣的是,当比较头球或 FootShot 对进球几率的影响时,我们发现在 25-75 这一角度范围内,无论是何种角度,头球都会降低进球的几率。这可以简化如下:如果您最喜欢的球员将球控制在脚边,而且射门角度较大,则进球的几率要高于球飞向空中的几率!

相反,如果角度大于 25 度,与以较快速度带球冲向球门的球员相比,以较慢的速度带球的球员可能会降低进球的几率。从这两张图可以看出,AngleToGoal < 25 和 AngleToGoal > 25 对进球预测的影响存在着明显差异。我们可以开始看到使用 SHAP 值来分析赛季数据的价值,因为我们迅速确定了数据中的普遍趋势。

1f4c895b18767d29f204d4dd19d70835.png

局部解释

到目前为止,我们的分析仅集中在整个数据集的可解释性结果(全局解释)上,现在,我们来探索一些特别有趣的比赛及其进球事件,看看什么是局部解释。

我们来回顾一下 2019-2020 赛季最有意思的比赛之一,那就是拜耳勒沃库森 (Bayer 04 Leverkusen) 在 2020 年 2 月 8 日以 4-3 击败多特蒙德 (Borussia Dortmund) 的比赛,这场比赛惊险刺激,我们可以看到每种特征对 xGoals 值的不同影响(我们在水平轴上看到的模型输出值)。我们看到,从底部开始,一直向上,这些特征开始对最终预测产生越来越大的影响,其中一些极端情况展示了 AngleToGoalDistanceToGoalClosest 和 DistanceToGoal 模型的概率预测中发挥最终决定作用的。虚线表示有进球的比赛事件。

ca62e708420f1b54edfe8e150dd25f47.png

如果我们来看比赛中由 Leon Bailey 所进的第六个球(对此模型之前已相对轻松地预测到),我们可以看到许多(关键)特征值都超过了平均值,并有助于提高目标的可能性,正如以下力量图中相对较高的 xGoals 值 0.36 所反映的那样。

8645a1c428347100cf619052e2ecbbc6.png

我们看到的基本值是过去三个赛季德甲每次尝试射门的平均 xGoals 值,即 0.0871!XGBoost 模型在此基线开始预测,正力和负力可能会提高或降低预测值。在图中,特征的 SHAP 值以箭头形式表示,可推动提高(正值)或降低(负值)预测值。此次射门拥有高 AngleToGoal (56.37)、低 AmountOfDefenders (1.0) 和低 DistanceToGoal ,而在之前的情况中,没有任何特征能够产生抵消影响。所有定性描述(例如小、低和大)都与数据集中每个相应特征的平均值相关。

另一个极端是,对于某些进球,我们的 XGBoost 模型无法预测,并且 SHAP 值也无法解释。Emre Can 被 22% 的德甲观众评选为 2019–2020 赛季的最佳进球员。考虑到他与球门的最佳距离(大约 30 米),与球门的角度接近平角(11.55 度),他进球的几率几乎为零 (3%),因此他最终取得这样的分数,真是令人惊叹。唯一有助于提高其得分几率的特征是,他当时的压力很小,附近只有两名球员能够阻止他进球。但是,这显然难以阻止 Can。与足球比赛中的常见情况一样,射门的各个方面可能都过于完美,以至于没人能预测最终结果,更不用说高级 ML 模型了。

488b36bfe49de0f72b3f636de73a2433.png

只需使用球员在进球时的位置跟踪数据,我们便可以 2D 动画演示 Can 的实际进球情况。

演示1

演示2

结论:关于德甲赛况的启示

由亚马逊云科技提供支持的德甲赛况的主要启示有两个方面。本文中的实验结果表明我们:

  • 开始以新颖的方式大规模自动探索和分析进球预测数据

  • 提供模型可解释性和偏差平台,此平台可以针对进一步捕捉有趣且重要的射门模式进行优化

在与足球比赛同样复杂的现实场景中,传统或特定逻辑的基于规则的系统开始在应用时崩溃,无法提供任何类型的赛事预测,更不用说关于具体情况的深度解释了。通过应用 Amazon SageMaker Carify,我们不仅可以增强进球预测模型,还可以根据每场比赛的情况分析足球赛事。

随着近年来捕获足球数据的技术取得了巨大进展,我们可以使用模型对这些堆积如山的数据进行建模。随着德甲赛况数据集的复杂性、深度和丰富性不断提高,团队正在不断探索新的令人兴奋的想法,以了解更多赛况,以及如何根据富有洞察力的可解释性结果调整我们出色的制作中模型。Amazon SageMaker Carify 更新和改进不可避免且持续进行,这为 xGoals 和德甲赛况开辟了许多令人兴奋的途径。

Sportec Solutions (STS)(由亚马逊云科技提供支持的德甲赛况的主要合作伙伴组织)的数据科学家 Gabriel Anzer 表示:“借助 Amazon SageMaker Carify,开发人员可以在几分钟内体验先进的可解释 AI 算法的强大功能,并将其与德甲赛况数字平台的其余部分无缝集成。该平台是我们用于在 Amazon SageMaker 上标准化 ML 工作流程的长期战略的关键部分。”

无论 Amazon SageMaker Carify 解决方案是帮助痴迷的足球运动员在当地联赛中占据优势,为经理提供对球员当前和预测性未来表现的客观评估,还是作为知名足球专家的对话开场白,帮助他们识别特定球员和球队的进攻和防守趋势,通过它在应用于德甲赛况中的表现,您已经可以领略它在足球生态系统的所有领域创造的切实价值。

本篇作者

bef441182ad0e7f09ee6f9eb22d70d2b.png

Nick McCarthy

亚马逊云科技专业服务团队数据科学家

Nick McCarthy 是亚马逊云科技专业服务团队的数据科学家。他与医疗保健、金融、体育和媒体等不同行业的亚马逊云科技客户合作,通过使用 AI/ML 加速实现业务成果。工作之余,他喜欢旅行,尝试新的美食以及阅读科学和技术相关信息。Nick 教育背景是天体物理学和机器学习专业,但是偶尔会关注德甲,而且他从小就是曼联 (Manchester United) 的粉丝!

46654d7685907d9636f833b4c41f4c54.png

Luuk Figdor

亚马逊云科技专业服务团队数据科学家

Luuk Figdor 是亚马逊云科技专业服务团队的数据科学家。他与各行各业的客户合作,帮助他们借助机器学习挖掘数据信息。业余时间,他喜欢了解思想方面的知识以及心理学、经济学和人工智能 (AI) 之间的交汇。

2d58cd957d655bb37a247abfebb2f91c.png

Gabriel Anzer

Sportec Solutions AG首席数据科学家

Gabriel Anzer 是 Sportec Solutions AG(DFL 的子公司)的首席数据科学家。他致力于借助 AI/ML 为球迷和俱乐部从足球数据中提取有趣的见解。Gabriel 的教育背景是数学和机器学习专业,但他还在图宾根大学攻读体育分析博士学位,并努力考取自己的足球教练执照。

618fd5b6dd09f50e3d34a4281022dd18.png

6966da1477e206b41a784efe96950b94.gif

dad932d9dce2214282842b8d160aec3e.gif

听说,点完下面4个按钮

就不会碰到bug了!

b9227e6ef45842c8171738955056dc25.gif

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值