根据现有客户生命周期价值打造新的受众群体

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

了解如何预测客户生命周期价值 (CLV),然后在 Google Ads 中利用这些数据通过构建类似受众群体来识别潜在的新客户。

概览

本教程介绍如何根据客户的交易历史记录,预测指定时间段内每个客户的可能消费金额。您可以通过以下步骤来实现此目的:

  • 将交易和客户数据导入 BigQuery。
  • 处理要搭配机器学习 (ML) 模型使用的数据。
  • 使用 BigQuery ML 构建机器学习模型。
  • 通过模型获取预测结果,根据 CLV 识别最佳客户。
  • 从客户数据表中检索这些客户的电子邮件地址。
  • 利用这些合并数据创建可在 Google Ads 中使用的再营销名单
  • 以此再营销名单为基础,生成类似受众群体以用在广告定位中。

本教程将指导您创建 Vertex AI Workbench 用户管理的笔记本实例,以实现这些目标,并提供规范指导和分步过程。如果您只想改用完成的笔记本来开始操作,则可以在您选择的笔记本服务器上使用 bqml_automl_ltv_activate_lookalike.ipynb

本教程适用于构建机器学习数据集和模型以支持业务决策的数据工程师、数据科学家和数据分析师。本教程假定您基本了解以下各个方面:

  • 基本了解机器学习概念和 Python
  • 标准 SQL

本教程重构了使用 AutoML Tables 预测客户生命周期价值(预测 CLV 教程系列第 4 部分,也就是最后一部分)中使用的示例。如果您想更好地了解特定于执行特征工程和模型开发的关键决策要点以进行 CLV 发现,请参阅本系列中的第一个教程使用 AI Platform 预测客户生命周期价值:简介

本教程中的示例与使用 AutoML Tables 预测客户生命周期价值中的示例在以下方面有所不同:

  • 它会为每个客户创建多个记录,以用于训练模型。为此,它会将客户交易细分为重叠的时间范围。
  • 使用模型,您只需更改模型输入参数,即可预测不同时间段(例如一个月或一个季度)的 CLV。
  • 它直接从 BigQuery ML 使用 AutoML,最大限度地缩短开发时间。
  • 它对销售数据和客户数据使用不同的数据集。
  • 它展示了如何使用 CLV 预测在 Google Ads 中创建类似受众群体。

数据集

如需创建可以从中构建类似受众群体的高 CLV 客户列表,您需要两组数据:

  • 您想要评估的客户的销售交易。您可以使用以这些数据为基础的计算来训练 CLV 模型。在生产使用场景中,您可以从订单处理系统中提取此信息。
  • 客户电子邮件地址。在生产使用场景中,您需要从客户关系管理 (CRM) 系统中提取这些信息。

本教程使用两个 CSV 文件提供示例数据,您可以将这两个文件加载到 BigQuery 表中。这两个数据集都包含一个客户 ID,您可以使用该 ID 来联接表以将客户电子邮件地址与其 CLV 信息相关联。

模型

本教程介绍如何创建回归模型,以预测客户未来的消费金额,因为这种类型的模型非常适合预测连续变量(也称为连续值),例如 CLV 金额。

具体来说,本教程使用 BigQuery ML 创建 AutoML 回归模型。使用 AutoML 可以通过以下方式最大限度地减少开发开销:

  • 特征工程 - AutoML 会自动处理多项常见的特征工程任务
  • BigQuery ML 集成 - 您可以使用 BigQuery ML SQL 语句创建 AutoML 模型,此语句限制了在不同开发环境之间来回切换的需求。
  • 拆分训练数据集 - 在训练模型时,最佳做法是将数据拆分为三个非重叠的数据集:训练、验证和测试。AutoML 默认处理此作业,但如果您愿意,也可以指定特定拆分

计算特征和标签

在本教程中,您使用阈值将一段时间内的客户交易细分为多个重叠时段。阈值日期会将输入事务与目标事务分离。输入交易在阈值日期之前发生,用于计算您输入到模型中的特征。目标交易在阈值日期之后发生,用来计算该时间段内的 CLV,CLV 用作您正在训练的待预测模型的标签

RFM 特征

CLV 模型中使用的三个重要特征是上次消费时间、消费频率和消费金额 (RFM) 值,您可以通过客户交易历史数据计算得出:

  • 上次消费时间:客户上次下单是在什么时候?
  • 消费频率:客户每隔多久消费一次?
  • 消费金额:客户的消费金额是多少?

下图显示了四位客户在过去一段时间内的一系列消费情况。

4 位客户的消费记录

该图表示的是客户的 RFM 值,展示了每个客户在以下各个方面的表现:

  • 上次消费时间:上次消费距离今的时间,以最右边的圆与标记为 Now(现在)的垂直虚线之间的距离表示。
  • 消费频率:两次相邻消费间隔的时间,以每条线上两个圆之间的距离表示。
  • 消费数额:每次消费的金额,以圆的大小表示。

Google Ads 集成要求

本教程中关于 Google Ads 集成部分的示例代码需要访问正常运作的 Google Ads 环境才能运行。如需使示例代码能在您自己的 Google Ads 环境中运行,您必须具备以下各项:

  • Google Ads 经理帐号及 Google Ads API 的访问权限。如果您还没有这些项,请按照注册过程中的说明获取这些 ID。
  • Google Ads 开发者令牌、OAuth 客户端 ID 和客户端密钥,以及 Google Ads Python 客户端库的 OAuth 刷新令牌。如果您还没有这些项,请按照设置 AdWords API 访问权限中的说明获取这些项。对于该过程中的第 5 步,您可以使用 googleads-python-lib/examples/adwords/authentication/generate_refresh_token.py 查看如何获取刷新令牌。
  • 可用于计算 CLV 的交易数据以及包含客户电子邮件地址的客户数据。使用这些数据来替换导入数据部分提供的示例数据。您需要确保您的数据使用与样本数据相同的表名称和架构。下表介绍了预期的 BigQuery 表:

clv.sales

数据类型
customer_id INTEGER
order_id STRING
transaction_date DATE
product_sku STRING
qty INTEGER
unit_price FLOAT

clv.customers

数据类型
customer_id INTEGER
full_name STRING
age INTEGER
job_title STRING
email STRING

目标

  1. 使用 BigQuery 准备和探索训练数据。
  2. 使用 BigQuery ML 构建、训练和部署机器学习模型。
  3. 通过已部署的模型获取 CLV 预测结果。
  4. 创建代表 CLV 前 20% 的客户列表。
  5. 基于热门 CLV 客户名单创建一个 Google Ads 再营销名单,然后您可以使用该再营销名单生成与这些客户类似的受众群体。

费用

本教程使用 Google Cloud 的以下收费组件:

  • AI Platform
  • BigQuery
  • BigQuery ML
  • Compute Engine

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

准备工作

  1. 登录您的 Google Cloud 帐号。如果您是 Google Cloud 新手,请创建一个帐号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  3. 确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能

  4. 启用 Compute Engine, BigQuery, and Notebooks API。

    启用 API

  5. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  6. 确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能

  7. 启用 Compute Engine, BigQuery, and Notebooks API。

    启用 API

创建笔记本

  1. 在 Google Cloud Console 中,前往 Notebooks 页面。

    前往 Notebooks

  2. 点击 新建笔记本

  3. 选择 Python 3

  4. 对于实例名称,输入 clv

  5. 点击创建。创建笔记本实例可能需要几分钟时间。

  6. 当实例可用时,点击打开 JupyterLab

  7. 在 JupyterLab 启动器的笔记本部分中,点击 Python 3

安装库

安装本教程所需的 googleads 和其他库:

  1. 将以下代码复制到笔记本的第一个单元中:

    # Install libraries.
    %pip install -q googleads
    %pip install -q -U kfp matplotlib Faker --user
    
    # Restart kernel after installs
    import IPython
    app = IPython.Application.instance()
    app.kernel.do_shutdown(True)
    
  2. 点击菜单栏中的运行

导入软件包

如需安装本教程所需的软件包,请将以下代码复制到笔记本的下一个空单元,然后运行它:

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os, json, random
import hashlib, uuid
import time, calendar, math
import pandas as pd, numpy as np
import matplotlib.pyplot as plt, seaborn as sns
from datetime import datetime
from google.cloud import bigquery
from googleads import adwords

创建 BigQuery 客户端

如需为适用于 BigQuery 的 Python 客户端库创建 BigQuery 客户端,请将以下代码复制到笔记本的下一个空单元,然后运行它。将 myProject 替换为您用于完成本教程的项目的 ID。您可以在 Google Cloud 项目信息中心项目信息卡片中找到项目 ID。

bq_client = bigquery.Client(project="myProject")

导入数据

按照以下部分中的说明将示例数据导入 BigQuery,然后对其进行处理,以用于训练机器学习模型。

如果您拥有正常运作的 Google Ads 环境,则可以使用自己的数据,而无需导入示例。使用可用于计算 CLV 的交易数据填充 clv.sales 表,并使用包含客户电子邮件地址的客户数据填充 clv.customers 表。

创建数据集

在为示例数据创建 BigQuery 表之前,必须先创建包含表的数据集。

如需创建 clv 数据集,请将以下代码复制到笔记本的下一个空单元,然后运行它。将 myProject 替换为您用于完成本教程的项目的 ID。

PROJECT_ID = "myProject"
! bq mk $PROJECT_ID:clv

导入销售数据

如需创建并填充 clv.sales 表,请将以下代码复制到笔记本的下一个空单元,然后运行它:

! bq load \
--project_id $PROJECT_ID \
--skip_leading_rows 1 \
--max_bad_records 100000 \
--replace \
--field_delimiter "," \
--autodetect \
clv.sales \
gs://solutions-public-assets/analytics-componentized-patterns/ltv/sales_*

导入客户数据

如需创建并填充 clv.customers 表,请将以下代码复制到笔记本的下一个空单元,然后运行它:

! bq load \
--project_id $PROJECT_ID \
--skip_leading_rows 1 \
--max_bad_records 100000 \
--replace \
--field_delimiter "," \
--autodetect \
clv.customers \
gs://solutions-public-assets/analytics-componentized-patterns/ltv/crm.csv

准备数据

如需准备客户交易数据以用于训练机器学习模型,您必须完成以下任务:

  • 设置用于确定订单金额和商品数量所允许标准差值的参数。在执行客户交易数据的初始汇总时,使用这些参数标识和移除每个客户的离群值记录。
  • 汇总客户交易数据。
  • 查看汇总数据跨条件(每个客户的交易数量、每个订单的商品数量等)的分布情况,以确定您可能需要进一步优化数据的区域。
  • 定义通过汇总数据计算的特征,例如 RFM 值。
  • 设置用于定义特征计算所用时间范围的参数。例如,阈值日期之间的间隔天数。
  • 计算训练模型所需的特征。

设置聚合参数

在聚合过程中使用以下参数来定义最大标准差值:

  • MAX_STDV_MONETARY - 每个客户的消费金额的标准差
  • MAX_STDV_QTY - 每个客户商品数量的标准差。

如需设置参数以确定要使用的标准变体值,请将以下代码复制到笔记本的下一个空单元,然后运行它:

AGG_PARAMS = {
    'MAX_STDV_MONETARY': 500,
    'MAX_STDV_QTY': 100
}

在生产使用场景中,您可以修改这些参数以确定订单价值和商品数量可以接受的值范围。

汇总客户交易数据

以下查询汇总了每个客户每天的所有订单。由于机器学习任务是预测一段时间(如几周或几个月)内的消费金额,因此,天数可以作为时间单位很好地对每个客户的交易进行分组。

此查询还会移除每个客户的离群值订单。商品订单价值或数量不在 MAX_STDV_MONETARYMAX_STDV_QTY 指定的可接受标准差值范围内的订单会过滤掉。

  1. 如需创建一个包含汇总客户交易数据的表,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery --params $AGG_PARAMS --project $PROJECT_ID
    
    DECLARE MAX_STDV_MONETARY INT64 DEFAULT @MAX_STDV_MONETARY;
    DECLARE MAX_STDV_QTY INT64 DEFAULT @MAX_STDV_QTY;
    
    CREATE OR REPLACE TABLE `clv.aggregation` AS
    SELECT
      customer_id,
      order_day,
      ROUND(day_value_after_returns, 2) AS value,
      day_qty_after_returns as qty_articles,
      day_num_returns AS num_returns,
      CEIL(avg_time_to_return) AS time_to_return
    FROM (
      SELECT
        customer_id,
        order_day,
        SUM(order_value_after_returns) AS day_value_after_returns,
        STDDEV(SUM(order_value_after_returns)) OVER(PARTITION BY customer_id ORDER BY SUM(order_value_after_returns)) AS stdv_value,
        SUM(order_qty_after_returns) AS day_qty_after_returns,
        STDDEV(SUM(order_qty_after_returns)) OVER(PARTITION BY customer_id ORDER BY SUM(order_qty_after_returns)) AS stdv_qty,
        CASE
          WHEN MIN(order_min_qty) < 0 THEN count(1)
          ELSE 0
        END AS day_num_returns,
        CASE
          WHEN MIN(order_min_qty) < 0 THEN AVG(time_to_return)
          ELSE NULL
        END AS avg_time_to_return
      FROM (
        SELECT
          customer_id,
          order_id,
          -- Gives the order date vs return(s) dates.
          MIN(transaction_date) AS order_day,
          MAX(transaction_date) AS return_final_day,
          DATE_DIFF(MAX(transaction_date), MIN(transaction_date), DAY) AS time_to_return,
          -- Aggregates all products in the order
          -- and all products returned later.
          SUM(qty * unit_price) AS order_value_after_returns,
          SUM(qty) AS order_qty_after_returns,
          -- If negative, order has qty return(s).
          MIN(qty) order_min_qty
        FROM
          `clv.sales`
        GROUP BY
          customer_id,
          order_id)
      GROUP BY
        customer_id,
        order_day)
    WHERE
      -- [Optional] Remove dates with outliers per a customer.
      (stdv_value < MAX_STDV_MONETARY
        OR stdv_value IS NULL) AND
      (stdv_qty < MAX_STDV_QTY
        OR stdv_qty IS NULL);
    
  2. 如需查看生成的 clv.aggregation 表中的数据示例,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery
    
    SELECT * FROM clv.aggregation LIMIT 5;
    

    您应该会看到如下所示的结果:

    前 5 行汇总数据。

在生产使用场景中,您可能需要通过应用其他选择条件(例如下列选项)来进一步优化数据:

  • 移除项数和交易额不是正数的记录。
  • 移除没有客户 ID 的记录。
  • 只保留活跃的客户,但要定义这一点。例如,您可能希望重点关注在过去 90 天内购买过商品的客户。

检查数据分布情况

本教程最大程度地清理数据,而不是专注于处理交易数据的基本转换,这样就可以搭配模型使用。在本部分中,您将检查数据分布情况,以确定是否存在离群值并确定需要进一步优化数据的区域。

按日期检查分布情况

  1. 如需创建 df_dist_dates DataFrame 并在其中填充来自汇总交易的日期数据,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery df_dist_dates --project $PROJECT_ID
    
    SELECT count(1) c, SUBSTR(CAST(order_day AS STRING), 0, 7) as yyyy_mm
    FROM `clv.aggregation`
    WHERE qty_articles > 0
    GROUP BY yyyy_mm
    ORDER BY yyyy_mm
    
  2. 如需使用 seaborn 可视化日期数据,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    plt.figure(figsize=(12,5))
    sns.barplot( x='yyyy_mm', y='c', data=df_dist_dates)
    

    您应该会看到如下所示的结果:

    直观呈现日期数据分布情况。

    订单会在整个年内分布均匀,但在此数据集中捕获的前几个月内要低一些。在生产使用场景中,您可以将基于日期的数据分布用作一个因素来考虑何时为特征计算过程设置时间范围参数。

依客户按交易检查分布情况

  1. 如需创建 df_dist_customers DataFrame 并在其中填充来自汇总交易的客户交易次数,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery df_dist_customers --project $PROJECT_ID
    
    SELECT customer_id, count(1) c
    FROM `clv.aggregation`
    GROUP BY customer_id
    
  2. 如需使用 seaborn 可视化客户交易数据,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    plt.figure(figsize=(12,4))
    sns.distplot(df_dist_customers['c'], hist_kws=dict(ec="k"), kde=False)
    

    您应该会看到如下所示的结果:

    直观呈现客户数据分布情况。

    这些数据具有良好的分布,并且每个客户收到的事务数量均在狭窄范围内,并且没有明确的离群值。

按商品数量检查分布情况

  1. 如需创建 df_dist_qty DataFrame 并在其中填充来自汇总交易的商品数量数据,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery df_dist_qty --project $PROJECT_ID
    
    SELECT qty_articles, count(1) c
    FROM `clv.aggregation`
    GROUP BY qty_articles
    
  2. 如需使用 seaborn 可视化商品数量数据,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    plt.figure(figsize=(12,4))
    sns.distplot(df_dist_qty['qty_articles'], hist_kws=dict(ec="k"), kde=False)
    

    您应该会看到如下所示的结果:

    直观呈现商品数量数据分布情况。

    一些客户的订单数量非常大,但分布情况通常良好。在生产使用场景中,您可以在此区域执行更多数据工程。如果个别客户通常购买 1 到 2 件商品,但突然购买 20 件商品,那么这样的客户的离群值交易需移除。如果客户有的商品买的少,有的商品买的多,那么这样的客户的离群值交易需保留。

按消费金额检查分布情况

  1. 如需创建 df_dist_values DataFrame 并在其中填充来自汇总交易的消费金额数据,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery df_dist_values --project $PROJECT_ID
    
    SELECT value
    FROM `clv.aggregation`
    
  2. 如需使用 seaborn 可视化消费金额数据,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    axv = sns.violinplot(x=df_dist_values["value"])
    axv.set_xlim(-200, 3500)
    

    您应该会看到如下所示的结果:

    直观呈现消费金额数据的分布情况。

    分布情况显示一些开销明显超出平均值的离群值。在生产使用场景中,您可以在此区域执行更多数据工程。如果个别客户每次交易通常只花费 50 美元,但突然进行了一笔 1000 美元的交易,那么这样的客户的离群值交易需移除。如果客户有的商品花的钱少,有的商品花的钱多,那么这样的客户的离群值交易需保留。

定义特征

下表介绍了为训练模型而进行计算的特征:

特征名称 类型 说明
monetary FLOAT 给定客户在给定时间范围内的所有交易的总消费金额。
frequency INTEGER 给定客户在给定时间范围内的交易次数。
recency INTEGER 给定客户在给定时间范围内第一次交易到最后一次交易之间的时间间隔。
T INTEGER 数据集中的第一次交易与输入交易范围结束之间的时间间隔。
time_between FLOAT 给定客户在给定时间范围内两次交易之间的平均时间间隔。
avg_basket_value FLOAT 客户在给定时间范围内的购物篮的平均消费金额。
avg_basket_size FLOAT 给定客户在给定时间范围内在购物车中存放的平均商品数量。
has_returns STRING 给定客户是否退回给定时间段内至少一次交易的商品。
avg_time_to_return FLOAT 给定客户退回交易的第一件商品所需的时间。
num_returns INTEGER 客户退回的与给定时间范围内的交易关联的商品件数。

设置特征计算参数

以下参数定义要用于计算特征的时间范围:

  • WINDOW_STEP - 指定阈值之间的天数。这决定了特征和标签的计算频率。
  • WINDOW_STEP_INITIAL - 指定训练数据中第一个订单日期与第一个阈值之间的天数。
  • WINDOW_LENGTH - 指定可重新用于输入交易的天数。默认情况是使用值 0,这会将给定阈值前的所有交易都考虑在内。
  • LENGTH_FUTURE - 指定未来预测用作机器学习标签的 monetary 值的天数。在每个阈值中,BigQuery 都会计算阈值日期之后 LENGTH_FUTURE 内发生的所有订单的标签值。

例如,假设某个数据集的最早交易日期为 2015 年 1 月 1 日且具有下列参数值:

  • WINDOW_STEP:30
  • WINDOW_STEP_INITIAL:90
  • WINDOW_LENGTH:0
  • LENGTH_FUTURE:30

特征创建过程的前几次循环的时间范围的工作原理如下所示:

第一个循环

参数 如何计算
阈值日期 最早交易日期 + WINDOW_STEP_INITIAL 值,因此为 1/1/2015 + 90 天。 4/1/2015
时间范围开始时间 WINDOW_LENGTH 为 0,因此使用阈值之前的所有交易。最早的交易日期为 1/1/2015。 1/1/2015
输入交易时段 从时间范围开始日期开始,直到阈值日期(含边界值)为止。 1/1/2015 - 4/1/2015
目标交易时段 从阈值日期(不含)到阈值日期 + LENGTH_FUTURE 指定的天数(4/1/2015 + 30 天) 4/2/2015 - 5/1/2015

第二个循环

参数 如何计算
阈值日期 上一个循环的阈值日期 + WINDOW_STEP 值,因此为 4/1/2015 + 30 天 5/1/2015
时间范围开始时间 WINDOW_LENGTH 为 0,因此使用阈值之前的所有交易。最早的交易日期为 1/1/2015。 1/1/2015
输入交易时段 从时间范围开始日期开始,直到阈值日期(含边界值)为止。 1/1/2015 - 5/1/2015
目标交易时段 从阈值日期(不含)到阈值日期 + LENGTH_FUTURE 指定的天数(5/1/2015 + 30 天) 5/2/2015 - 5/31/2015

如果将 WINDOW_LENGTH 修改为值 15,则时间范围的工作原理改为如下所示:

第一个循环

参数 如何计算
阈值日期 最早交易日期 + WINDOW_STEP_INITIAL 值,因此为 1/1/2015 + 90 天。 4/1/2015
时间范围开始时间 阈值日期 - WINDOW_LENGTH 值,因此为 4/1/2015 - 15 天。 3/17/2015
输入交易时段 从时间范围开始日期开始,直到阈值日期(含边界值)为止。 3/17/2015 - 4/1/2015
目标交易时段 从阈值日期(不含)到阈值日期 + LENGTH_FUTURE 指定的天数(4/1/2015 + 30 天) 4/2/2015 - 5/1/2015

第二个循环

参数 如何计算
阈值日期 上一个循环的阈值日期 + WINDOW_STEP 值,因此为 4/1/2015 + 30 天 5/1/2015
时间范围开始时间 阈值日期 - WINDOW_LENGTH 值,因此为 5/1/2015 - 15 天 4/16/2015
输入交易时段 从时间范围开始日期开始,直到阈值日期(含边界值)为止。 4/16/2015 - 5/1/2015
目标交易时段 从阈值日期(不含)到阈值日期 + LENGTH_FUTURE 指定的天数(5/1/2015 + 30 天) 5/2/2015 - 5/31/2015

如需设置参数以确定特征计算时间范围,请将以下代码复制到笔记本的下一个空单元,然后运行它:

CLV_PARAMS = {
    'WINDOW_LENGTH': 0,
    'WINDOW_STEP': 30,
    'WINDOW_STEP_INITIAL': 90,
    'LENGTH_FUTURE': 30
}

在生产使用场景中,您将更改这些参数以获取最适合您正在使用的数据的结果。例如,如果您的客户每周购买多次,您可以使用每周时间范围来计算特征。或者,如果您拥有大量数据,则可以创建更多时间范围,方式是减小时间范围大小,并且在可能的情况下减少阈值之间的天数。除超参数调节外,使用这些参数进行实验也可以提高模型的性能。

创建特征

  1. 如需创建一个包含训练模型所需计算特征的表,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery --params $CLV_PARAMS --project $PROJECT_ID
    
    -- Length
    -- Date of the first order in the dataset.
    DECLARE MIN_DATE DATE;
    -- Date of the final order in the dataset.
    DECLARE MAX_DATE DATE;
    -- Date that separates inputs orders from target transactions.
    DECLARE THRESHOLD_DATE DATE;
    -- How many days back for inputs transactions. 0 means from the start.
    DECLARE WINDOW_LENGTH INT64 DEFAULT @WINDOW_LENGTH;
    -- Date at which an input transactions window starts.
    DECLARE WINDOW_START DATE;
    -- How many days between thresholds.
    DECLARE WINDOW_STEP INT64 DEFAULT @WINDOW_STEP;
    -- How many days for the first window.
    DECLARE WINDOW_STEP_INITIAL INT64 DEFAULT @WINDOW_STEP_INITIAL;
    -- Index of the window being run.
    DECLARE STEP INT64 DEFAULT 1;
    -- How many days to predict for.
    DECLARE LENGTH_FUTURE INT64 DEFAULT @LENGTH_FUTURE;
    
    SET (MIN_DATE, MAX_DATE) = (
      SELECT AS STRUCT
        MIN(order_day) AS min_days,
        MAX(order_day) AS max_days
      FROM
        `clv.aggregation`
    );
    
    SET THRESHOLD_DATE = MIN_DATE;
    
    -- For more information about the features of this table,
    -- see https://github.com/CamDavidsonPilon/lifetimes/blob/master/lifetimes/utils.py#L246
    -- and https://cloud.google.com/solutions/machine-learning/clv-prediction-with-offline-training-train#aggregating_data
    CREATE OR REPLACE TABLE clv.features
    (
      customer_id STRING,
      monetary FLOAT64,
      frequency INT64,
      recency INT64,
      T INT64,
      time_between FLOAT64,
      avg_basket_value FLOAT64,
      avg_basket_size FLOAT64,
      has_returns STRING,
      avg_time_to_return FLOAT64,
      num_returns INT64,
      -- threshold DATE,
      -- step INT64,
      target_monetary FLOAT64,
    );
    
    -- Using a BigQuery LOOP procedural language statement
    -- (https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#loop)
    -- lets you enhance the logic of your query without the need of another
    -- programming language or client code.
    
    LOOP
      -- Can choose a longer original window in case
      -- there were not many orders in the early days.
      IF STEP = 1 THEN
        SET THRESHOLD_DATE = DATE_ADD(THRESHOLD_DATE, INTERVAL WINDOW_STEP_INITIAL DAY);
      ELSE
        SET THRESHOLD_DATE = DATE_ADD(THRESHOLD_DATE, INTERVAL WINDOW_STEP DAY);
      END IF;
      SET STEP = STEP + 1;
    
      IF THRESHOLD_DATE >= DATE_SUB(MAX_DATE, INTERVAL (WINDOW_STEP) DAY) THEN
        LEAVE;
      END IF;
    
      -- Takes all transactions before the threshold date unless you decide
      -- to use a different window length to test model performance.
      IF WINDOW_LENGTH != 0 THEN
        SET WINDOW_START = DATE_SUB(THRESHOLD_DATE, INTERVAL WINDOW_LENGTH DAY);
     ELSE
        SET WINDOW_START = MIN_DATE;
      END IF;
       INSERT clv.features
      SELECT
        CAST(tf.customer_id AS STRING),
        ROUND(tf.monetary_orders, 2) AS monetary,
        tf.cnt_orders AS frequency,
        tf.recency,
        tf.T,
        ROUND(tf.recency/cnt_orders, 2) AS time_between,
        ROUND(tf.avg_basket_value, 2) AS avg_basket_value,
        ROUND(tf.avg_basket_size, 2) AS avg_basket_size,
        has_returns,
        CEIL(avg_time_to_return) AS avg_time_to_return,
        num_returns,
        ROUND(tt.target_monetary, 2) AS target_monetary,
      FROM (
          -- This SELECT uses only data before THRESHOLD_DATE to make features.
          SELECT
            customer_id,
            SUM(value) AS monetary_orders,
            DATE_DIFF(MAX(order_day), MIN(order_day), DAY) AS recency,
            DATE_DIFF(THRESHOLD_DATE, MIN(order_day), DAY) AS T,
            COUNT(DISTINCT order_day) AS cnt_orders,
            AVG(qty_articles) avg_basket_size,
            AVG(value) avg_basket_value,
            CASE
              WHEN SUM(num_returns) > 0 THEN 'y'
              ELSE 'n'
            END AS has_returns,
            AVG(time_to_return) avg_time_to_return,
            THRESHOLD_DATE AS threshold,
            SUM(num_returns) num_returns,
          FROM
            `clv.aggregation`
          WHERE
            order_day <= THRESHOLD_DATE AND
            order_day >= WINDOW_START
          GROUP BY
            customer_id
        ) tf
          INNER JOIN (
        -- This SELECT uses all data after threshold as target.
        SELECT
          customer_id,
          SUM(value) target_monetary
        FROM
          `clv.aggregation`
        WHERE
          order_day <= DATE_ADD(THRESHOLD_DATE, INTERVAL LENGTH_FUTURE DAY)
          -- For the sample data, the overall value is similar to the value
          -- after threshold, and prediction performs better using the overall
          -- value. When using your own data, try uncommenting the following
          -- AND clause and see which version of the procedure gives you better
          -- results.
          -- AND order_day > THRESHOLD_DATE
        GROUP BY
          customer_id) tt
      ON
          tf.customer_id = tt.customer_id;
      END LOOP;
    
  2. 如需查看生成的 clv.features 表中某一客户的数据示例,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery
    
    SELECT * FROM `clv.features` WHERE customer_id = "10"
    UNION ALL
    (SELECT * FROM `clv.features` LIMIT 5)
    ORDER BY customer_id, frequency, T LIMIT 5
    
    

    您应该会看到如下所示的结果:

    前 5 行特征数据。

训练模型

本教程使用 BigQuery ML 中的 AUTOML_REGRESSOR 创建、训练以及部署 AutoML 回归模型。

本教程使用默认设置来训练模型;在生产使用场景中,为了改进模型,您可以尝试使用其他特征工程技术和不同的训练数据拆分。

如需创建并填充 clv_model 模型,请将以下代码复制到笔记本的下一个空单元,然后运行它:

%%bigquery

CREATE OR REPLACE MODEL `clv.clv_model`
       OPTIONS(MODEL_TYPE="AUTOML_REGRESSOR",
               INPUT_LABEL_COLS=["target_monetary"],
               OPTIMIZATION_OBJECTIVE="MINIMIZE_MAE")
AS SELECT
  * EXCEPT(customer_id)
FROM
  `clv.features`

这应该会为您提供一个良好的基本模型作为工作起点。如需根据您自己的数据和使用场景来调整模型,您可以使用超参数调节、特征工程和其他技术优化模型。

预测 CLV

下一步是通过模型获取每个客户的 CLV 预测结果,然后将这些数据写入表中。预测记录包含下表中所述的字段:

字段名称 类型 说明
customer_id STRING 客户 ID
monetary_so_far FLOAT 客户在预测日期之前支出的总金额。
monetary_predicted FLOAT 预测客户支出的总金额,即 monetary_so_farmonetary_future 字段值的总和。
monetary_future FLOAT 预测客户将来在预测日期和预测期结束日期之间花费的金额。
  1. 如需创建并填充 clv.predictions 表,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery --params $CLV_PARAMS --project $PROJECT_ID
    
    -- How many days back for inputs transactions. 0 means from the start.
    DECLARE WINDOW_LENGTH INT64 DEFAULT @WINDOW_LENGTH;
    -- Date at which an input transactions window starts.
    DECLARE WINDOW_START DATE;
    
    -- Date of the first transaction in the dataset.
    DECLARE MIN_DATE DATE;
    -- Date of the final transaction in the dataset.
    DECLARE MAX_DATE DATE;
    -- Date from which you want to predict.
    DECLARE PREDICT_FROM_DATE DATE;
    
    SET (MIN_DATE, MAX_DATE) = (
      SELECT AS STRUCT
        MIN(order_day) AS min_days,
        MAX(order_day) AS max_days
      FROM
        `clv.aggregation`
    );
    
    -- You can set any date here. In production, it is generally today.
    SET PREDICT_FROM_DATE = MAX_DATE;
    IF WINDOW_LENGTH != 0 THEN
      SET WINDOW_START = DATE_SUB(PREDICT_FROM_DATE, INTERVAL WINDOW_LENGTH DAY);
    ELSE
      SET WINDOW_START = MIN_DATE;
    END IF;
    
    CREATE OR REPLACE TABLE `clv.predictions`
    AS (
    SELECT
      customer_id,
      monetary AS monetary_so_far,
      ROUND(predicted_target_monetary, 2) AS monetary_predicted,
      ROUND(predicted_target_monetary - monetary, 2) AS monetary_future
    FROM
      ML.PREDICT(
        -- To use your own model, set the model name here.
        MODEL clv.clv_model,
        (
          SELECT
            customer_id,
            ROUND(monetary_orders, 2) AS monetary,
            cnt_orders AS frequency,
            recency,
            T,
            ROUND(recency/cnt_orders, 2) AS time_between,
            ROUND(avg_basket_value, 2) AS avg_basket_value,
            ROUND(avg_basket_size, 2) AS avg_basket_size,
            has_returns,
            CEIL(avg_time_to_return) AS avg_time_to_return,
            num_returns
          FROM (
            SELECT
              customer_id,
              SUM(value) AS monetary_orders,
              DATE_DIFF(MAX(order_day), MIN(order_day), DAY) AS recency,
              DATE_DIFF(PREDICT_FROM_DATE, MIN(order_day), DAY) AS T,
              COUNT(DISTINCT order_day) AS cnt_orders,
              AVG(qty_articles) avg_basket_size,
              AVG(value) avg_basket_value,
              CASE
                WHEN SUM(num_returns) > 0 THEN 'y'
                ELSE 'n'
              END AS has_returns,
              AVG(time_to_return) avg_time_to_return,
              SUM(num_returns) num_returns,
            FROM
              `clv.aggregation`
            WHERE
              order_day <= PREDICT_FROM_DATE AND
              order_day >= WINDOW_START
            GROUP BY
              customer_id
          )
        )
      )
    )
    
  2. 如需查看生成的 clv.features 表中的数据示例,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery
    
    SELECT * FROM clv.predictions
    ORDER BY customer_id
    LIMIT 5;
    

    您应该会看到如下所示的结果:

    前 5 行预测数据。

评估预测数据

直观呈现预测数据并生成预测数据的统计信息,以更好地了解数据分布并查看是否存在任何明显的趋势。

  1. 根据 clv.predictions 表创建 DataFrame:

    %%bigquery df_predictions --project $PROJECT_ID
    
    clv.predictions
    
  2. 如需使用 pandas.DataFrame.describe 生成预测数据的描述性统计信息,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    df_predictions.describe()
    

    您应该会看到如下所示的结果:

    预测数据的统计信息。

  3. 使用 matplotlib.gridspec 直观呈现预测数据,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    from matplotlib.gridspec import GridSpec
    
    fig = plt.figure(constrained_layout=True, figsize=(15, 5))
    gs = GridSpec(2, 2, figure=fig)
    
    sns.set(font_scale = 1)
    plt.tick_params(axis='x', labelsize=14)
    
    ax0 = plt.subplot(gs.new_subplotspec((0, 0), colspan=1))
    ax1 = plt.subplot(gs.new_subplotspec((0, 1), colspan=1))
    ax2 = plt.subplot(gs.new_subplotspec((1, 0), colspan=2))
    
    sns.violinplot(df_predictions['monetary_so_far'], ax=ax0, label='monetary_so_far')
    sns.violinplot(df_predictions['monetary_predicted'], ax=ax1, label='monetary_predicted')
    sns.violinplot(df_predictions['monetary_future'], ax=ax2, label='monetary_future')
    

    您应该会看到如下所示的结果:

    直观呈现预测数据分布。

    货币分布分析显示,下个月的货币金额与整体历史金额相比较小。一个原因是,我们会训练模型以根据 LENGTH_FUTURE 参数中所指定的那样,预测下个月的值。您可以尝试更改该值以训练和预测下一季度(此值为 LENGTH_FUTURE = 90),然后查看分布如何变化。

创建类似受众群体

通过本部分中的过程来创建和导出具有较高 CLV 的客户列表,然后使用该列表在 Google Ads 中创建类似受众群体。

只有当您有权访问正常运行的 Google Ads 环境时,通过 CLV 确定顶级客户后续部分中的代码示例才能运行。解决 Google Ads 集成要求,使此示例代码可在您自己的 Google Ads 环境中运行。

通过 CLV 识别顶级客户

如需创建类似受众群体,您首先需要根据预测的 CLV 确定顶级客户,然后将电子邮件地址与他们相关联。为此,您可以使用客户 ID 将预测表与包含此类信息的客户数据表相联接。

本教程根据 CLV 使用前 20% 的客户。您可以通过修改 TOP_CLV_RATIO 参数来更改要选择的客户百分比。用于选择客户的 SQL 语句使用 PERCENT_RANK 函数来识别客户,这些客户的预测未来支出会使其达到或超过 TOP_CLV_RATIO 值所标识的百分比。

  1. 如需设置 TOP_CLV_RATIO 参数,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    CLV_PARAMS = {
        'TOP_CLV_RATIO': 0.2
    }
    
  2. 如需创建并填充 df_top_ltv DataFrame,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    %%bigquery df_top_ltv --params $CLV_PARAMS --project $PROJECT_ID
    
    DECLARE TOP_CLV_RATIO FLOAT64 DEFAULT @TOP_CLV_RATIO;
    
    SELECT
      p.customer_id,
      monetary_future,
      c.email AS email
    FROM (
      SELECT
        customer_id,
        monetary_future,
        PERCENT_RANK() OVER (ORDER BY monetary_future DESC) AS percent_rank_monetary
      FROM
        `clv.predictions` ) p
    INNER JOIN (
      SELECT
        customer_id,
        email
      FROM
        `clv.customers` ) c
    ON
      p.customer_id = c.customer_id
    WHERE
      -- Decides the size of your list of emails. For similar-audience use cases
      -- where you need to find a minimum of matching emails, 20% should provide
      -- enough potential emails.
      percent_rank_monetary <= TOP_CLV_RATIO
    ORDER BY monetary_future DESC
    
  3. 如需查看 df_top_ltv 数据的示例,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    df_top_ltv.head(5)
    

    您应该会看到如下所示的结果:

    依 CLV 数据排列的顶级客户的前 5 行数据。

创建 Google Ads 配置文件

为 Google Ads 客户端创建配置 YAML 文件。

  1. 如需设置 YAML 文件变量以控制对 Google Ads API 的访问权限,请将下面的占位符变量替换为适合您的环境的值。如果您没有所需的令牌和 OAuth 凭据,但又想获取,请参阅 Google Ads 集成要求了解详情。

    将以下代码复制到笔记本的下一个空单元,然后运行它:

    DEVELOPER_TOKEN = "myDeveloperToken"
    OAUTH_2_CLIENT_ID = "myClientId"
    CLIENT_SECRET = "myClientSecret"
    REFRESH_TOKEN = "myRefreshToken"
    
  2. 如需创建 YAML 文件内容,请将以下代码复制到笔记本的下一个空单元,然后运行它。

    ADWORDS_FILE = "/tmp/adwords.yaml"
    
    adwords_content = f"""
    # AdWordsClient configurations
    adwords:
      #############################################################################
      # Required Fields                                                           #
      #############################################################################
      developer_token: {DEVELOPER_TOKEN}
      #############################################################################
      # Optional Fields                                                           #
      #############################################################################
      # client_customer_id: INSERT_CLIENT_CUSTOMER_ID_HERE
      # user_agent: INSERT_USER_AGENT_HERE
      # partial_failure: True
      # validate_only: True
      #############################################################################
      # OAuth2 Configuration                                                      #
      # Below you may provide credentials for either the installed application or #
      # service account flows. Remove or comment the lines for the flow you're    #
      # not using.                                                                #
      #############################################################################
      # The following values configure the client for the installed application
      # flow.
      client_id: {OAUTH_2_CLIENT_ID}
      client_secret: {CLIENT_SECRET}
      refresh_token: {REFRESH_TOKEN}
      # The following values configure the client for the service account flow.
      # path_to_private_key_file: INSERT_PATH_TO_JSON_KEY_FILE_HERE
      # delegated_account: INSERT_DOMAIN_WIDE_DELEGATION_ACCOUNT
      #############################################################################
      # ReportDownloader Headers                                                  #
      # Below you may specify boolean values for optional headers that will be    #
      # applied to all requests made by the ReportDownloader utility by default.  #
      #############################################################################
        # report_downloader_headers:
        # skip_report_header: False
        # skip_column_header: False
        # skip_report_summary: False
        # use_raw_enum_values: False
    
    # AdManagerClient configurations
    ad_manager:
      #############################################################################
      # Required Fields                                                           #
      #############################################################################
      application_name: INSERT_APPLICATION_NAME_HERE
      #############################################################################
      # Optional Fields                                                           #
      #############################################################################
      # The network_code is required for all services except NetworkService:
      # network_code: INSERT_NETWORK_CODE_HERE
      # delegated_account: INSERT_DOMAIN_WIDE_DELEGATION_ACCOUNT
      #############################################################################
      # OAuth2 Configuration                                                      #
      # Below you may provide credentials for either the installed application or #
      # service account (recommended) flows. Remove or comment the lines for the  #
      # flow you're not using.                                                    #
      #############################################################################
      # The following values configure the client for the service account flow.
      path_to_private_key_file: INSERT_PATH_TO_JSON_KEY_FILE_HERE
      # delegated_account: INSERT_DOMAIN_WIDE_DELEGATION_ACCOUNT
      # The following values configure the client for the installed application
      # flow.
      # client_id: INSERT_OAUTH_2_CLIENT_ID_HERE
      # client_secret: INSERT_CLIENT_SECRET_HERE
      # refresh_token: INSERT_REFRESH_TOKEN_HERE
    
    # Common configurations:
    ###############################################################################
    # Compression (optional)                                                      #
    # Below you may specify whether to accept and automatically decompress gzip   #
    # encoded SOAP requests. By default, gzip compression is not enabled.         #
    ###############################################################################
    # enable_compression: False
    ###############################################################################
    # Logging configuration (optional)                                            #
    # Below you may specify the logging configuration. This will be provided as   #
    # an input to logging.config.dictConfig.                                      #
    ###############################################################################
    # logging:
      # version: 1
      # disable_existing_loggers: False
      # formatters:
        # default_fmt:
          # format: ext://googleads.util.LOGGER_FORMAT
      # handlers:
        # default_handler:
          # class: logging.StreamHandler
          # formatter: default_fmt
          # level: INFO
      # loggers:
        # Configure root logger
        # "":
          # handlers: [default_handler]
          # level: INFO
    ###############################################################################
    # Proxy configurations (optional)                                             #
    # Below you may specify an HTTP or HTTPS Proxy to be used when making API     #
    # requests. Note: You must specify the scheme used for the proxy endpoint.    #
    #                                                                             #
    # For additional information on configuring these values, see:                #
    # http://docs.python-requests.org/en/master/user/advanced/#proxies            #
    ###############################################################################
    # proxy_config:
      # http: INSERT_HTTP_PROXY_URI_HERE
      # https: INSERT_HTTPS_PROXY_URI_HERE
      # If specified, the given cafile will only be used if certificate validation
      # is not disabled.
      # cafile: INSERT_PATH_HERE
      # disable_certificate_validation: False
    ################################################################################
    # Utilities Included (optional)                                                #
    # Below you may specify whether the library will include utilities used in the #
    # user agent. By default, the library will include utilities used in the user  #
    # agent.                                                                       #
    ################################################################################
    # include_utilities_in_user_agent: True
    ################################################################################
    # Custom HTTP headers (optional)                                               #
    # Specify one or more custom headers to pass along with all requests to        #
    # the API.                                                                     #
    ################################################################################
    # custom_http_headers:
    #   X-My-Header: 'content'
    """
    
  3. 如需填充 YAML 文件,请将以下代码复制到笔记本的下一个空单元,然后运行它。

    with open(ADWORDS_FILE, "w") as adwords_file:
        print(adwords_content, file=adwords_file)
    

创建 Google Ads 再营销名单

使用顶级 CLV 客户的电子邮件地址创建 Google Ads 再营销名单。

  1. 如需创建包含顶级 CLV 客户电子邮件地址的列表,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    ltv_emails = list(set(df_top_ltv['email']))
    
  2. 如需创建再营销名单,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    """Adds a user list and populates it with hashed email addresses.
    
    Note: It may take several hours for the list to be populated with members. Email
    addresses must be associated with a Google account. For privacy purposes, the
    user list size will show as zero until the list has at least 1000 members. After
    that, the size will be rounded to the two most significant digits.
    """
    
    import hashlib
    import uuid
    
    # Import appropriate modules from the client library.
    from googleads import adwords
    
    def main(client):
      # Initialize appropriate services.
      user_list_service = client.GetService('AdwordsUserListService', 'v201809')
    
      user_list = {
          'xsi_type': 'CrmBasedUserList',
          'name': 'Customer relationship management list #%d' % uuid.uuid4(),
          'description': 'A list of customers that originated from email addresses',
          # CRM-based user lists can use a membershipLifeSpan of 10000 to indicate
          # unlimited; otherwise normal values apply.
          'membershipLifeSpan': 30,
          'uploadKeyType': 'CONTACT_INFO'
      }
    
      # Create an operation to add the user list.
      operations = [{
          'operator': 'ADD',
          'operand': user_list
      }]
    
      result = user_list_service.mutate(operations)
      user_list_id = result['value'][0]['id']
    
      emails = ['customer1@example.com', 'customer2@example.com',
                ' Customer3@example.com ']
      members = [{'hashedEmail': NormalizeAndSHA256(email)} for email in emails]
    
      # Add address info.
      members.append({
          'addressInfo': {
              # First and last name must be normalized and hashed.
              'hashedFirstName': NormalizeAndSHA256('John'),
              'hashedLastName': NormalizeAndSHA256('Doe'),
              # Country code and zip code are sent in plaintext.
              'countryCode': 'US',
              'zipCode': '10001'
          }
      })
    
      mutate_members_operation = {
          'operand': {
              'userListId': user_list_id,
              'membersList': members
          },
          'operator': 'ADD'
      }
    
      response = user_list_service.mutateMembers([mutate_members_operation])
    
      if 'userLists' in response:
        for user_list in response['userLists']:
          print('User list with name "%s" and ID "%d" was added.'
                % (user_list['name'], user_list['id']))
    
    def NormalizeAndSHA256(s):
      """Normalizes (lowercase, remove whitespace) and hashes a string with SHA-256.
    
      Args:
        s: The string to perform this operation on.
    
      Returns:
        A normalized and SHA-256 hashed string.
      """
      return hashlib.sha256(s.strip().lower()).hexdigest()
    
    if __name__ == '__main__':
      # Initialize the client object with the config
      # file you created in the previous section.
      adwords_client = adwords.AdWordsClient.LoadFromStorage(ADWORDS_FILE)
      main(adwords_client)
    

添加类似受众群体

在获得再营销名单后,请按照 Google Ads 文档中的说明将类似受众群体添加到定位中

后续步骤(可选)

使用以下部分中的信息选择性地改进模型性能并自动化机器学习工作流。

改进模型

本教程为您介绍一种可行的方法来构建基本模型以预测客户未来的消费金额。若您决定进一步研究此方法,我们建议在以下方面进行改进或实验:

  • 如果您的数据中有许多离群值,请另外进行数据工程设计或者查找其他训练数据。
  • 如需尝试使用其他方法来创建特征,请调整时间范围边界或更改输入比例来定位交易。
  • 比较模型时,请确定使用相同的一组测试数据,以合理地比较模型的性能。例如,本教程将准备数据,以更好地预测未来 30 天的订单。如果您想要模型预测下一季度,则应更新 LENGTH_FUTURE 参数并重新计算特征。
  • 示例数据集使用有限数量的字段。如果您自己的数据中有其他维度,例如商品类别、地理区域或受众特征信息,请尝试为您的模型创建额外特征。

自动化机器学习工作流

在前面的步骤中,您学习了如何使用 BigQuery 和 BigQuery ML 准备机器学习数据、创建和训练模型、获取预测结果,以及准备 Google Ads 集成数据。

在生产使用场景中,这些都将是周期性任务。您每次都可以随时手动运行这些步骤,但我们建议自动执行该流程。本教程在 GitHub 中有配套代码,提供一组用以自动执行这些步骤的 BigQuery 存储过程,还提供一个可以用来执行这些步骤的 Shell 脚本 run.sh

如果您调用 run.sh 脚本,则可以使用以下参数将其配置为在您的环境中工作:

变量 说明 默认
PROJECT_ID 项目 ID 必填
DATASET_ID 数据集 ID 必填
TRAIN_MODEL_ID 经过训练的模型的名称。如果您不想训练模型,请设置为 *null*。 基于时间的字符串。
USE_MODEL_ID 用于预测的模型的名称。必须包含数据集: [DATASET].[MODEL] 基于时间的字符串。
WINDOW_LENGTH 输入交易的时间范围(天)。 0
WINDOW_STEP 两个时间范围之间的间隔天数。等同于两个阈值日期之间的时间。 30
WINDOW_STEP_INITIAL 设置第一个阈值日期后的最初天数。 90
LENGTH_FUTURE 进行预测的天数。 30
MAX_STDV_MONETARY 每个客户的消费金额的标准差,超过此值时脚本会移除交易。 500
MAX_STDV_QTY 每个客户商品数量的标准差,超过此值时脚本会移除交易。 100
TOP_LTV_RATIO 要提取的顶级客户所占的百分比。 0.2

请按照以下步骤使用 run.sh 脚本实现自动化:

  1. 克隆 GitHub 代码库:

    git clone https://github.com/GoogleCloudPlatform/analytics-componentized-patterns.git
    
  2. 更新 run.sh 脚本以设置与您的环境匹配的参数值。

  3. 如果您使用自己的交易数据,请更新 10_procedure_match.sql,以指定事务表中的相应列。

  4. 调整 run.sh 脚本的权限,让您可以运行它:

    chmod +x run.sh
    
  5. 请参阅命令行帮助,了解如何设置参数:

    ./run.sh --help
    
  6. 运行脚本:

    ./run.sh --project-id [YOUR_PROJECT_ID] --dataset-id [YOUR_DATASET_ID]
    

在生产使用场景中,您可以与数据工程师和 DevOps 团队联系,了解他们是否可以将存储的过程集成到自己的工具中,以方便使用。

清除数据

为避免系统因本教程中使用的资源而向您的 Google Cloud 帐号收取费用,请删除包含资源的项目,或者保留项目但仅删除这些资源。

无论采用哪种方式,您都应移除这些资源,以免日后再为这些资源付费。以下部分介绍如何删除这些资源。

删除项目

为避免支付费用,最简单的方法是删除您为本教程创建的项目。

  1. 在 Google Cloud 控制台中,转到管理资源页面:

    转到“管理资源”

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

删除组件

如果您不想删除项目,请使用以下几个部分删除本教程的可计费组件。

删除 BigQuery 数据集和表

  1. 打开 BigQuery 控制台
  2. 资源部分中,展开要在其中完成本教程的项目,然后选择 clv 数据集。
  3. 点击数据集窗格标题中的删除数据集
  4. 在出现的叠加窗口中,输入 clv,然后点击删除

删除用户管理的笔记本实例

  1. 打开“用户管理的笔记本”标签页
  2. 选中 clv 笔记本实例对应的复选框。
  3. 点击删除
  4. 在出现的叠加窗口中,点击删除

后续步骤