使用 BigQuery ML 为市场细分构建 k-means 聚类模型

使用 BigQuery ML 创建 k-means 聚类,了解如何出于营销目的细分 Google Analytics 360 受众群体数据。

概览

您可能面临的常见营销分析挑战是确定消费者行为方面的主题,然后您可以借此开发客户个人资料或角色。这些个人资料可帮助您将更多客户知识运用到营销活动中。

要根据您的数据快速构建客户细分,您可以使用一种称为聚类的技术。利用聚类,您可以将具有类似行为的客户组合在一起,以构建不同的受众群体,用于市场营销。您可以根据每个客户所属的客户所指示的偏好和行为,通过为客户定制广告和其他通信来个性化您与客户的联系。

在本教程中,您将学习如何在 BigQuery ML 中使用 k-means 模型创建客户聚类。您可以根据包含交易和受众特征信息的样本客户数据训练模型,并且模型会返回有关这些数据中识别出的客户聚类的信息。然后,您就可以从模型中获取预测,以便根据客户的受众特征和交易记录,将每个客户分配到合适的聚类。将每个客户分配到聚类后,您可以将更新后的客户数据发回 Google Analytics 360,以用于营销激活。

本教程将指导您创建 AI Platform Notebooks 笔记本以完成这些步骤,并提供规范指导和分步过程。如果您只想改用完成的笔记本来开始操作,则可以在您选择的笔记本服务器上使用如何使用 BigQuery ML 为市场细分构建 k-means 聚类模型笔记本。

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

  • 机器学习概念
  • Python
  • 标准 SQL

聚类算法的工作原理

聚类是一种非监督式机器学习。在这种情况下,您将运行一种算法“k-means 聚类”,以按逻辑对数据进行分组。该算法会评估相似性的训练数据,并根据这些数据进行分组,而不是根据人工提供的标签对数据进行分组。例如,假设您希望按年龄和估算收入对客户进行分组。您可以使用聚类来帮助您根据这些属性确定数据中存在多少个集群。当您仅考虑一到两个客户属性时,聚类可能会看起来很简单,但随着您考虑更多客户属性,人工分析会变得越来越困难。

使用聚类的一个挑战是确定聚类数量正确无误。本教程介绍如何在构建初始版本后改进模型,最终您就会获得一个模型,该模型可为您的使用场景创建合适数量的聚类。

数据集

本教程使用在 BigQuery 上公开托管的 Google Analytics(分析)示例数据集。此数据集提供来自 Google Merchandise Store(销售 Google 品牌商品的真实电子商务商店)的 12 个月(2016 年 8 月至 2017 年 8 月)经过模糊处理的 Analytics 360 数据。

如果您有自己的 Analytics 360 数据,就可以改用该数据。整个教程中包含关于在这种情况下采取不同措施的信息。

目标

  • 将客户数据处理为正确的格式,以创建 k-means 聚类模型。
  • 使用 BigQuery ML 创建、训练和部署 k-means 模型。
  • 迭代模型,以制定可创建最佳数量聚类的版本。
  • 分析模型生成的聚类,获悉它们对您的客户细分的了解。
  • 从已部署的模型获取预测结果,将客户分配到相应的聚类。
  • 从 BigQuery 导出更新后的客户数据,以便在 Analytics 360 的营销激活中使用这些数据。

费用

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

  • AI Platform
  • BigQuery
  • BigQuery ML

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

准备工作

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

    转到“项目选择器”

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

  4. 启用 AI Platform Notebooks and Compute Engine API。

    启用 API

完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

创建笔记本

  1. 打开 AI Platform Notebooks 控制台
  2. 点击新建实例
  3. 选择 Python 2 和 3
  4. 对于实例名称,输入 kmeans
  5. 点击创建。创建笔记本实例可能需要几分钟时间。
  6. 当实例可用时,点击打开 JupyterLab
  7. 在 JupyterLab 启动器的笔记本部分中,点击 Python 3

安装库

安装本教程所需的库。

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

    # Install libraries.
    !pip install pandas-gbq
    !pip install google-cloud-bigquery
    !pip install google-cloud-bigquery-storage
    # Needed to setup flex slots for flat-rate pricing
    !pip install google-cloud-bigquery-reservation
    
    # Automatically restart kernel after installs
    import IPython
    app = IPython.Application.instance()
    app.kernel.do_shutdown(True)
    
  2. 点击菜单栏中的运行

导入软件包

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

from google.cloud import bigquery
import numpy as np
import pandas as pd
import pandas_gbq
import matplotlib.pyplot as plt

# used to display float format
pd.set_option('display.float_format', lambda x: '%.3f' % x)

创建 BigQuery 客户端

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

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

处理数据

在本部分中,您需要准备训练 k-means 模型所需的数据。准备数据的操作包括汇总 Analytics 360 的客户交易数据、生成示例客户受众特征数据,然后联接这两个数据集以创建训练数据集。

在本教程中,您将使用 Google Analytics(分析)示例数据,但在生产使用场景中,您可以使用自己的 Analytics 360 数据。

创建 BigQuery 数据集

创建 BigQuery 数据集以包含客户数据和 k-means 模型,方法是将以下代码复制到笔记本的下一个空单元,然后运行它:

! bq mk myProject:kmeans

汇总交易数据

在本部分中,您将汇总来自示例 Analytics 360 数据集的客户交易数据。通过汇总数据,您可以更清楚地了解客户购买商品的频率、购买的商品类型和购买费用。

在本教程中,我们假设是在 pagetype = "EVENT" 的情况下进行购买。在生产使用场景中,您可能需要以其他方式识别购买交易,具体取决于您的 Analytics 360 配置。

本教程还使用 fullVisitorID 作为客户数据的键。在生产使用场景中,您应该在此查询和后续查询中将 fullVisitorID 的实例替换为 clientId。这是因为在将受众群体数据导入 Analytics 360 时,您必须使用 clientId 作为键字段。clientId 通常是 fullVisitorId 的经过哈希处理的版本,但此列未填充到 Google Analytics(分析)示例数据集中。如需在您自己的 Analytics 360 数据中使用 clientId,您需要创建一个自定义维度并进行填充。

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

    ga360_only_view = 'GA360_View'
    shared_dataset_ref = client.dataset('kmeans')
    ga360_view_ref = shared_dataset_ref.table(ga360_only_view)
    ga360_view = bigquery.Table(ga360_view_ref)
    
    ga360_query = '''
    SELECT
      fullVisitorID,
      # This will be used to generate random data.
      ABS(farm_fingerprint(fullVisitorID)) AS Hashed_fullVisitorID,
      # You can aggregate this because an
      # operating system is tied to a fullVisitorID.
      MAX(device.operatingSystem) AS OS,
      SUM (CASE
           WHEN REGEXP_EXTRACT (v2ProductCategory,
                               r'^(?:(?:.*?)Home/)(.*?)/')
                               = 'Apparel' THEN 1 ELSE 0 END) AS Apparel,
      SUM (CASE
           WHEN REGEXP_EXTRACT (v2ProductCategory,
                               r'^(?:(?:.*?)Home/)(.*?)/')
                               = 'Office' THEN 1 ELSE 0 END) AS Office,
      SUM (CASE
           WHEN REGEXP_EXTRACT (v2ProductCategory,
                               r'^(?:(?:.*?)Home/)(.*?)/')
                               = 'Electronics' THEN 1 ELSE 0 END) AS Electronics,
      SUM (CASE
           WHEN REGEXP_EXTRACT (v2ProductCategory,
                               r'^(?:(?:.*?)Home/)(.*?)/')
                               = 'Limited Supply' THEN 1 ELSE 0 END) AS LimitedSupply,
      SUM (CASE
           WHEN REGEXP_EXTRACT (v2ProductCategory,
                               r'^(?:(?:.*?)Home/)(.*?)/')
                               = 'Accessories' THEN 1 ELSE 0 END) AS Accessories,
      SUM (CASE
           WHEN REGEXP_EXTRACT (v2ProductCategory,
                               r'^(?:(?:.*?)Home/)(.*?)/')
                               = 'Shop by Brand' THEN 1 ELSE 0 END) AS ShopByBrand,
      SUM (CASE
           WHEN REGEXP_EXTRACT (v2ProductCategory,
                               r'^(?:(?:.*?)Home/)(.*?)/')
                               = 'Bags' THEN 1 ELSE 0 END) AS Bags,
      ROUND (SUM (productPrice/1000000),2) AS totalSpent_USD
      FROM
      `bigquery-public-data.google_analytics_sample.ga_sessions_*`,
      UNNEST(hits) AS hits,
      UNNEST(hits.product) AS hits_product
    WHERE
      _TABLE_SUFFIX BETWEEN '20160801'
      AND '20160831'
      AND geoNetwork.country = 'United States'
      AND type = 'EVENT'
    GROUP BY
      1,
      2
    '''
    
    ga360_view.view_query = ga360_query.format('myProject')
    ga360_view = client.create_table(ga360_view)
    
    
  2. 如需查看汇总客户交易数据的示例,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    # Show a sample of GA360 data
    
    ga360_query_df = f'''
    SELECT * FROM {ga360_view.full_table_id.replace(":", ".")}
    ORDER BY fullVisitorID
    LIMIT 5
    '''
    
    job_config = bigquery.QueryJobConfig()
    
    # Start the query
    query_job = client.query(ga360_query_df, job_config=job_config) #API Request
    df_ga360 = query_job.result()
    df_ga360 = df_ga360.to_dataframe()
    
    df_ga360
    

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

    前 5 行汇总交易数据。

生成人口特征数据

按照以下过程生成合成的客户人口统计数据。

在生产使用场景中,您需要使用客户关系管理 (CRM) 系统中的自有数据。您可以跳过此步骤,继续执行下一步,将 CRM 数据与汇总的客户交易数据合并在一起。

  1. 如需创建一个包含所生成客户数据的视图,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    CRM_only_view = 'CRM_View'
    shared_dataset_ref = client.dataset('kmeans')
    CRM_view_ref = shared_dataset_ref.table(CRM_only_view)
    CRM_view = bigquery.Table(CRM_view_ref)
    
    # The query below works by hashing the fullVisitorID, which creates a
    # random distribution. It uses modulo to artificially split gender and
    # household income distribution.
    CRM_query = '''
    SELECT
      fullVisitorID,
    IF
      (MOD(Hashed_fullVisitorID,2) = 0,
        "M",
        "F") AS gender,
      # Generate household income
      CASE
        WHEN MOD(Hashed_fullVisitorID,10) = 0 THEN 55000
        WHEN MOD(Hashed_fullVisitorID,10) < 3 THEN 65000
        WHEN MOD(Hashed_fullVisitorID,10) < 7 THEN 75000
        WHEN MOD(Hashed_fullVisitorID,10) < 9 THEN 85000
        WHEN MOD(Hashed_fullVisitorID,10) = 9 THEN 95000
      ELSE
      Hashed_fullVisitorID
    END
      AS hhi
    FROM (
      SELECT
        fullVisitorID,
        ABS(farm_fingerprint(fullVisitorID)) AS Hashed_fullVisitorID,
      FROM
        `bigquery-public-data.google_analytics_sample.ga_sessions_*`,
        UNNEST(hits) AS hits,
        UNNEST(hits.product) AS hits_product
          WHERE
        _TABLE_SUFFIX BETWEEN '20160801'
        AND '20160831'
        AND geoNetwork.country = 'United States'
        AND type = 'EVENT'
      GROUP BY
        1,
        2)
    '''
    
    CRM_view.view_query = CRM_query.format('myProject')
    CRM_view = client.create_table(CRM_view)
    
  2. 如需查看所生成客户数据的示例,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    # See an output of the synthetic CRM data
    
    CRM_query_df = f'''
    SELECT * FROM {CRM_view.full_table_id.replace(":", ".")}
    ORDER BY fullVisitorID
    LIMIT 5
    '''
    
    job_config = bigquery.QueryJobConfig()
    
    # Start the query
    query_job = client.query(CRM_query_df, job_config=job_config)
    df_CRM = query_job.result()
    df_CRM = df_CRM.to_dataframe()
    
    df_CRM
    

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

    生成的客户数据的前 5 行数据。

创建训练数据集

按照以下过程创建训练数据集,方法是联接汇总的客户交易数据和生成的客户受众特征数据。

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

    # Build a final view, which joins GA360 data with CRM data
    
    final_data_view = 'Final_View'
    shared_dataset_ref = client.dataset('kmeans')
    final_view_ref = shared_dataset_ref.table(final_data_view)
    final_view = bigquery.Table(final_view_ref)
    
    final_data_query = f'''
    SELECT
        g.*,
        c.* EXCEPT(fullVisitorId)
    FROM {ga360_view.full_table_id.replace(":", ".")} g
    JOIN {CRM_view.full_table_id.replace(":", ".")} c
    ON g.fullVisitorId = c.fullVisitorId
    '''
    
    final_view.view_query = final_data_query.format('myProject')
    final_view = client.create_table(final_view)
    
    print(f"Successfully created view at {final_view.full_table_id}")
    
  2. 如需查看所联接数据的示例,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    # Show final data used before modeling
    
    sql_demo = f'''
    SELECT * FROM {final_view.full_table_id.replace(":", ".")}
    ORDER BY fullVisitorID
    LIMIT 5
    '''
    
    job_config = bigquery.QueryJobConfig()
    
    # Start the query
    query_job = client.query(sql_demo, job_config=job_config)
    df_demo = query_job.result()
    df_demo = df_demo.to_dataframe()
    
    df_demo
    

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

    联接的客户数据和交易数据的前 5 行。

创建、训练和部署初始模型

在本部分中,您将创建一个 Python 函数,用于构建 k-means 模型。通过创建函数而不仅仅是使用 SQL,您可以定义多个模型并让 BigQuery 并行构建这些模型。您将在改进模型部分中再次使用此函数来创建几个版本的模型以进行比较。

请注意,请勿将 fullVisitorId 用作模型的输入,因为创建用于聚类的特征并不需要该数据。一般来说,唯一或非通用的数据对于此用途不适用。

通常,您还需要对数值特征进行归一化,但可以通过此处跳过该步骤,因为 BigQuery ML 会自动执行该操作。

  1. 如需定义 makeModel 函数,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    PROJECT_ID = "myProject"
    
    def makeModel (n_Clusters, Model_Name):
        sql =f'''
        CREATE OR REPLACE MODEL `{PROJECT_ID}.kmeans.{Model_Name}`
        OPTIONS(model_type='kmeans',
        kmeans_init_method = 'KMEANS++',
        num_clusters={n_Clusters}) AS
        SELECT * except(fullVisitorID, Hashed_fullVisitorID) FROM `{final_view.full_table_id.replace(":", ".")}`
        '''
        job_config = bigquery.QueryJobConfig()
        client.query(sql, job_config=job_config)
    
  2. 如需测试该函数,请创建将数据细分为三个聚类的 test 模型。请注意,构建模型大约需要 5 分钟。

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

    model_test_name = "test"
    makeModel(3, model_test_name)
    
  3. 如需确认模型是否已创建,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    for model in client.list_models('kmeans'):
      print(model)
    

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

    Model(reference=ModelReference(project_id='myProject', dataset_id='kmeans', model_id='test'))
    
  4. 如需删除 test 模型,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    model_id = "kmeans."+model_test_name
    client.delete_model(model_id)
    print(f"Deleted model '{model_id}'")
    

改进模型

本部分介绍如何通过调整模型来提供适用于您的使用场景的最佳聚类数量,从而改进模型。

确定适当的聚类数量 - 这是“k-means”中的“k”,取决于您的使用场景。有时,您可以轻松确定所需的聚类数量。例如,如果您正在处理手写数字的单个图片,则需要 10 个聚类,每个聚类对应 0-9 中的一个数字。在不太常见的使用场景中,您可以试验使用不同数量聚类的多个版本模型。通过比较模型的不同版本,您可以了解哪个数据分组的效果最好,并最大限度地减少每个聚类内的错误。

您可以使用 elbow 方法确定哪个模型版本提供最佳分组,这种方法可以将损失对照图表绘制出来模型中的聚类数量,与模型的 Davies–Bouldin 得分相结合。此分数表示聚类的数据点之间有何不同。它定义为给定聚类中的数据点散点与其聚类本身的散点之间的比率。值越小,聚类就越容易。

创建多个模型以进行比较

生成 k-means 模型的多个版本:从一个版本创建 3 个聚类,直到一个版本创建 15 个聚类。

  1. 生成多个版本的 k-means 模型。请注意,构建模型大约需要 7 分钟。

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

    low_k = 3
    high_k = 15
    model_prefix_name = 'kmeans_clusters_'
    
    lst = list(range (low_k, high_k+1)) #build list to iterate through k values
    
    for k in lst:
        model_name = model_prefix_name + str(k)
        makeModel(k, model_name)
    
  2. 如需获取生成的模型列表,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    models = client.list_models('kmeans')
    print("Listing current models:")
    for model in models:
        full_model_id = f"{model.dataset_id}.{model.model_id}"
        print(full_model_id)
    

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

    不同模型版本的列表。

比较模型性能

使用以下过程比较不同模型的性能,方法是查看均方距离(用于确定模型损失)和每个模型的 Davies–Bouldin 得分。

  1. 使用 ML.EVALUATE SQL 语句为每个模型生成均方距离和 Davies–Bouldin 得分。这可能需要 1 分钟左右的时间才能完成。

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

    # This creates a dataframe with each model name, the Davies Bouldin Index, and Loss.
    
    df = pd.DataFrame(columns=['davies_bouldin_index', 'mean_squared_distance'])
    models = client.list_models('kmeans')
    for model in models:
        full_model_id = f"{model.dataset_id}.{model.model_id}"
        sql =f'''
            SELECT
                davies_bouldin_index,
                mean_squared_distance
            FROM ML.EVALUATE(MODEL `{full_model_id}`)
        '''
    
        job_config = bigquery.QueryJobConfig()
    
        # Start the query, passing in the extra configuration.
        query_job = client.query(sql, job_config=job_config)
        df_temp = query_job.to_dataframe()  # Wait for the job to complete.
        df_temp['model_name'] = model.model_id
        df =  pd.concat([df, df_temp], axis=0)
    
  2. 如需更新数据帧,请添加用于标识模型所使用的聚类数量的列,同时还对图表数据进行排序。为此,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    df['n_clusters'] = df['model_name'].str.split('_').map(lambda x: x[2])
    df['n_clusters'] = df['n_clusters'].apply(pd.to_numeric)
    df = df.sort_values(by='n_clusters', ascending=True)
    df
    

    您应该会看到类似下表的结果:

    每个模型的均方距离和 Davies–Bouldin 得分信息。

  3. 如需创建数据图,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    df.plot.line(x='n_clusters', y=['davies_bouldin_index', 'mean_squared_distance'])
    

    您应该会看到类似下表的结果:

    此图根据每个模型的聚类数量,绘制均方距离和 Davies–Bouldin 得分。

    没有完美的方法可用来确定使用场景的最佳聚类数量。我们建议您采取以下方法来做此决定:

    1. 应用 elbow 方法,看看它是否会向您显示均匀损失所在的清晰位置。
    2. 考虑模型的 Davies-Bouldin 得分。
    3. 请考虑可能会影响您要使用的聚类数量的业务规则或要求。
    4. 选择符合您业务需求的模型,并提供低损失和低 Davies-Bouldin 得分的最佳组合。

    在上图中,橙色线表示每个模型的损失,以均方距离表示,根据该模型的聚类数量作图。此线条的趋势表明,增加聚类数量会降低损失,这是意料之中。此线条还会稳步降低,而不是达到均匀损失所在的点并创建肘部形状。这表示,对于该数据集,仅仅使用 Elbow 方法不足以确定最佳聚类数量。

    蓝线表示每个模型的 Davies-Bouldin 得分,根据该模型的聚类数量作图。由于肘部方法未明确识别性能最佳的模型,您也可以用较低的 Davies-Bouldin 得分选择一个模型来识别该模型。

    具有 11 个聚类的模型具有较低的损失和最佳 Davies-Bouldin 得分,因此如果您的业务规则没有说明您处理较少聚类的原因,那么这是最好的选择。如果业务规则确实规定了使用较少聚类的理由,则包含 4 个聚类的模型得分第二高的 Davies-Bouldin 得分。为简单起见,本教程使用具有 4 个聚类的模型。

分析选定模型中的数据聚类

如需了解数据如何在此模型中进行聚类,请查看模型的形心,然后分析每个聚类中的数据,以了解聚类中的用户数量和聚类实例针对客户行为所做的指示。

  1. 如需使用 ML.CENTROIDS SQL 语句获取每个聚类中 gender 特征形心的相关信息,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    model_to_use = 'kmeans_clusters_4' # Edit this to use a different model
    final_model = 'kmeans.'+model_to_use
    
    pd.set_option('max_colwidth', 400)
    
    sql_get_attributes = f'''
    SELECT
      centroid_id,
      feature,
      categorical_value
    FROM
      ML.CENTROIDS(MODEL {final_model})
    WHERE
      feature IN ('gender')
    '''
    
    job_config = bigquery.QueryJobConfig()
    
    # Start the query
    query_job = client.query(sql_get_attributes, job_config=job_config)
    df_attributes = query_job.result()
    df_attributes = df_attributes.to_dataframe()
    df_attributes
    

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

    kmeans 模型的性别特征的形心。

  2. 如需使用 ML.PREDICT 和 ML.CENTROIDS 中的信息计算聚类数据的摘要统计信息,请将以下代码复制到笔记本的下一个空单元,然后运行它:

    sql_get_numerical_attributes = f'''
    WITH T AS (
    SELECT
      centroid_id,
      ARRAY_AGG(STRUCT(feature AS name,
                       ROUND(numerical_value,1) AS value)
                       ORDER BY centroid_id)
                       AS cluster
    FROM ML.CENTROIDS(MODEL {final_model})
    GROUP BY centroid_id
    ),
    
    Users AS(
    SELECT
      centroid_id,
      COUNT(*) AS Total_Users
    FROM(
    SELECT
      * EXCEPT(nearest_centroids_distance)
    FROM
      ML.PREDICT(MODEL {final_model},
        (
        SELECT
          *
        FROM
          {final_view.full_table_id.replace(":", ".")}
          )))
    GROUP BY centroid_id
    )
    
    SELECT
      centroid_id,
      Total_Users,
      (SELECT value from unnest(cluster) WHERE name = 'Apparel') AS Apparel,
      (SELECT value from unnest(cluster) WHERE name = 'Office') AS Office,
      (SELECT value from unnest(cluster) WHERE name = 'Electronics') AS Electronics,
      (SELECT value from unnest(cluster) WHERE name = 'LimitedSupply') AS LimitedSupply,
      (SELECT value from unnest(cluster) WHERE name = 'Accessories') AS Accessories,
      (SELECT value from unnest(cluster) WHERE name = 'Bags') AS Bags,
      (SELECT value from unnest(cluster) WHERE name = 'ShopByBrand') AS ShopByBrand,
      (SELECT value from unnest(cluster) WHERE name = 'totalSpent_USD') AS totalSpent_USD,
      (SELECT value from unnest(cluster) WHERE name = 'hhi') AS HouseholdIncome
    
    FROM T LEFT JOIN Users USING(centroid_id)
    ORDER BY centroid_id ASC
    '''
    
    job_config = bigquery.QueryJobConfig()
    
    # Start the query
    query_job = client.query(sql_get_numerical_attributes, job_config=job_config)
    df_numerical_attributes = query_job.result()
    df_numerical_attributes = df_numerical_attributes.to_dataframe()
    df_numerical_attributes.head()
    

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

    聚类数据的摘要统计信息。

考虑到形心和汇总统计信息数据,您可以确定模型的聚类的以下特征:

  • 聚类 1 – 此聚类中的客户购买了许多服装。他们购买了最多的商品,并且每件商品的支出均占第二位。品牌对他们的推动力不强。聚类会稍微偏向于女性。
  • 聚类 2 - 此聚类中的客户跨所有类别购买,但大部分购买服装。他们购买了数量少于聚类 1 中的客户的商品,但每件商品的支出却明显增加。极有可能是按品牌购物。此聚类更偏向于女性。
  • 聚类 3 - 此聚类是一个离群值,只有一个人。
  • 聚类 4 - 这是填充最多的聚类。此聚类中的客户购买量比较少,平均花费更少。这些客户通常是一次性买家,而非品牌忠诚用户。性别偏见很小。

获取预测结果

使用您选择的模型将用户分配到聚类,然后您就可以将它们用于营销活动。

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

    sql_score = f'''
    SELECT * EXCEPT(nearest_centroids_distance)
    FROM
      ML.PREDICT(MODEL {final_model},
        (
        SELECT
          *
        FROM
          {final_view.full_table_id.replace(":", ".")}
          LIMIT 10))
    '''
    
    job_config = bigquery.QueryJobConfig()
    
    # Start the query
    query_job = client.query(sql_score, job_config=job_config)
    df_score = query_job.result()
    df_score = df_score.to_dataframe()
    
    df_score
    

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

    已处理的训练数据的前 10 行。

将数据导出到 Analytics 360

通过 k-means 模型为客户获取聚类信息后,您可以将其导出到 Analytics 360,以便在营销广告系列中使用。

为此,请使用 BigQuery 控制台运行查询,此查询会返回要导出的数据,如以下 SQL 伪代码所示:

CREATE OR REPLACE TABLE myDataset.myCustomerDataTable AS (
    SELECT * EXCEPT(nearest_centroids_distance)
    FROM
      ML.PREDICT(MODEL myDataset.myModel,
        (
        SELECT
          *
        FROM
          myDataset.myTable)))

将查询结果保存为 CSV 文件,然后使用数据导入将数据导入 Analytics 360 中。请注意,导出的推荐数据中的列名称必须映射到 Analytics 360 数据导入架构。例如,如果数据导入架构是 ga:clientId, ga:dimension1, ga:dimension2,则数据中的列名称应为 ga:clientId, ga:dimension1, ga:dimension2。BigQuery 不允许在列名称中使用英文冒号,因此您必须先在导出的 CSV 文件中更新列名称,然后才能导入。

如果需要,您可以使用 BigQuery 机器学习模型MoDeM(营销模型部署)参考实现来方便将数据加载到 Analytics 360 中。按照 BQML 部署模板笔记本中的互动式说明开始操作。

清理

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

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

删除项目

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

  1. 在 Cloud Console 中,转到管理资源页面。

    转到“管理资源”

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

删除组件

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

删除 BigQuery 数据集

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

删除 AI Platform 笔记本

  1. 打开 AI Platform Notebooks 页面
  2. 选中 kmeans 笔记本实例对应的复选框。
  3. 点击删除
  4. 在出现的叠加窗口中,点击删除

后续步骤