市场营销的机器学习和生成式人工智能-全-

市场营销的机器学习和生成式人工智能(全)

原文:annas-archive.org/md5/83a239e384affb58e49aef6cce500be9

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

在营销的动态世界中,人工智能AI)和机器学习ML)的整合已不再仅仅是优势——它已成为一种必需。营销策略中的 AI/ML 整合代表着向更加数据驱动、高效和有影响力的营销实践范式转变。随着数据科学的兴起,企业现在可以深入理解其营销成功与失败的动力机制,以前所未有的清晰度理解客户行为和互动。此外,生成式人工智能GenAI)的兴起正在创造新的机会,便于轻松创建高度个性化的、引人入胜的内容,这些内容在全新的层面上与目标受众产生共鸣。本书提供了一套全面的工具包,用于利用 ML 和 GenAI 的力量来制定营销策略,这些策略不仅能够预测客户行为,还能吸引并转化客户,从而提高获取成本、提升转化率和增加净销售额。

从 Python 数据分析的基础开始,逐步深入到更复杂的 ML 和 GenAI 模型,本书是您理解和应用 AI 以增强营销策略的全面指南。我们将通过实际案例向您展示如何利用 AI 的能力来深入了解客户行为,制定个性化的营销信息,并推动显著的业务增长。我们还将探讨 AI 的伦理影响,这将帮助您确保您的营销策略不仅有效,而且负责任,并符合当前标准。

在本书结束时,您将获得针对营销的多种数据科学、ML 和 GenAI 技术的扎实理解。凭借这些知识,您将能够设计、启动和管理不仅成功而且前沿的营销活动,确保您的业务保持在数字营销革命的前沿。

本书面向的对象

本书针对的是技术营销交叉领域的多元化专业人士群体,包括:

  • 任何级别的营销专业人士,希望利用 AI/ML 进行数据驱动决策并增强其客户参与策略

  • 希望将高级 AI/ML 技术应用于解决实际营销挑战的营销领域的数据科学家和分析师

  • 致力于为营销目的构建或整合 AI 驱动工具和应用的 ML 工程师和软件开发者

  • 必须理解 AI 对营销的影响以推动创新并保持其在当今竞争环境中的竞争优势的企业领导者和企业家

假设每位读者都具备 Python 编程的基础熟练度,并对机器学习原理和数据科学方法有基本的至中等掌握。他们可能已经在或渴望进入那些 AI/ML 的直接应用能够直接影响营销成果和商业策略的角色。

本书涵盖内容

第一章AI 时代营销的演变及准备您的工具包,探讨了 AI 时代营销的演变,塑造营销未来的核心 AI/ML 技术,以及为营销项目设置 Python 环境。

第二章用 KPI 解码营销绩效,解释了每个数据驱动或 AI/ML 驱动的营销策略都始于与关键绩效指标KPIs)相关的优化和提升目标。理解和分析这些 KPI 对于评估营销活动和策略的有效性至关重要。本章讨论了如何识别和计算关键营销 KPI,利用它们进行解释性数据分析,并使用这些洞察来驱动营销决策。

第三章揭示营销成功的动态,调查了导致营销成功的潜在动态。通过利用数据科学和 AI/ML 技术,您可以深入了解推动成功营销活动的因素。涵盖的主题包括分析客户互动、识别成功的营销模式,以及基于数据驱动洞察优化策略。

第四章利用季节性和趋势进行战略规划,讨论了季节性和趋势,这在塑造营销策略中起着至关重要的作用。本章重点介绍如何利用 AI/ML 来识别和利用消费者行为和市场动态中的可预测波动。通过理解这些模式,您可以战略性地规划和执行与消费者兴趣和市场条件相一致的营销活动。

第五章利用情感分析提升客户洞察,讨论了客户情感,这是品牌认知和客户满意度的重要指标。本章探讨了由 AI/ML 驱动的情感分析如何提升客户洞察。您将学习如何分析客户反馈、评论和社交媒体互动,以调整您的策略,改善客户体验和参与度。

第六章利用预测分析和 A/B 测试提升客户参与度,涵盖了预测分析和 A/B 测试,这些是提升客户参与度的关键工具。本章解释了如何使用 AI/ML 模型来预测客户行为和参与度水平。它还涵盖了有效 A/B 测试的设计和执行,以优化营销决策并提升用户体验。

第七章个性化产品推荐,探讨了个性化产品推荐,这通过将产品与客户偏好和行为对齐,显著提高了购买的可能性。本章涵盖了生成个性化推荐的各种技术,包括篮子分析、协同过滤和其他推荐方法。

第八章利用机器学习进行客户细分,讨论了客户细分,这是精准营销的关键方面。本章讨论了如何根据各种因素,如购买行为、人口统计和兴趣,使用机器学习对客户进行细分。它涵盖了诸如 K-means 聚类和利用大型语言模型LLMs)以获得更深入的客户细分洞察力的技术。

第九章使用零样本学习创建引人入胜的内容,介绍了零样本学习ZSL),这是一种允许 AI 模型在没有先前直接示例的情况下生成相关营销内容的技术。ZSL 增强了创造力和速度,允许您使用学习到的模式和知识外推来为新类别和情境生成内容。您将找到将 ZSL 整合到营销策略中的实用示例和最佳实践,展示如何为产品描述、博客文章和社交媒体创建动态内容。

第十章利用少样本学习和迁移学习增强品牌影响力,涵盖了少样本学习FSL),这是一种使用少量标记示例来适应 AI 模型新任务的方法。

本章涵盖了 FSL 的原则,包括元学习,这些原则使模型能够有效地推广到新的场景。实际示例演示了您如何将 FSL 应用于营销活动,强调其在捕捉品牌精神细微方面的重要性,并根据客户反馈完善营销策略。

第十一章使用检索增强生成进行微目标定位,本章探讨了检索增强生成RAG)作为精准营销工具,结合了 GenAI 和实时信息检索。这种混合方法允许在生成过程中访问和整合当前数据,从而创建高度个性化的内容。本章详细介绍了 RAG 的操作框架及其在微目标定位中的应用,展示了它如何通过提供上下文相关和准确的内容来提高消费者参与度和转化率。

第十二章营销中 AI 和 ML 的未来格局,综合了前几章的关键 AI 和 ML 概念,并讨论了它们在营销中的未来应用。它涵盖了新兴技术,如多模态 GenAI、高级模型架构以及 AI 与增强和虚拟现实的集成。这些进步承诺将创造更动态、响应和个性化的营销策略。本章提供了关于这些技术如何塑造营销未来的见解,使消费者体验更加沉浸式,营销实践更加创新。

第十三章AI 赋能营销中的伦理和治理,讨论了与营销中 AI 技术相关的伦理考虑和治理挑战。它探讨了数据隐私、算法偏见以及透明度的必要性,强调它们对消费者信任和品牌完整性的影响。本章还涵盖了主要的监管框架,如 GDPR 和 CCPA,提供了负责任 AI 部署、模型透明度和合规性的策略。最后,它讨论了减轻偏见、确保数据隐私和建立稳健治理结构以促进营销中道德 AI 使用的实际指南。

为了充分利用这本书

为了最大限度地发挥这本书的益处,建议您对 Python 有基本的了解。然而,这本书的结构旨在适应广泛的技能水平,从初学者到高级实践者。以下是一些建议,帮助您充分利用这本书:

  1. 与代码示例互动:本书提供了大量实际示例来阐述关键概念。通过运行代码和尝试不同的变体来积极互动这些示例,将加深您的理解并提高您的技能。

  2. 应用知识:尝试将书中讨论的技术和策略应用到您自己的营销项目中。这种实际应用将有助于巩固概念并展示其在现实世界中的相关性。

  3. 保持更新:AI 和 ML 领域正在迅速发展。通过持续学习和职业发展,了解最新的进展、工具和最佳实践,将确保您始终处于这个激动人心的领域的最前沿。

这本书中的线形图可能与提供的代码生成的略有不同。这是因为图表已被优化以确保清晰度和易于理解;请随意尝试不同的可视化方法,以达到您需要的类型的结果!

下载示例代码文件

本书代码包托管在 GitHub 上,网址为github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing。我们还有其他来自我们丰富图书和视频目录的代码包,可在github.com/PacktPublishing/找到。查看它们吧!

下载彩色图像

我们还提供了一个包含本书中使用的截图/图表的彩色图像的 PDF 文件。您可以从这里下载:packt.link/gbp/9781835889404

使用的约定

本书使用了多种文本约定。

CodeInText:表示文本中的代码单词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 昵称。例如:“将下载的WebStorm-10*.dmg磁盘映像文件作为系统中的另一个磁盘挂载。”

粗体:表示新术语、重要单词或屏幕上看到的单词。例如,菜单或对话框中的单词在文本中显示如下。例如:“从管理面板中选择系统信息。”

重要注意事项或建议看起来像这样。

小贴士和技巧看起来像这样。

联系我们

欢迎读者反馈。

一般反馈:请通过feedback@packtpub.com发送电子邮件,并在邮件主题中提及本书的标题。如果您对本书的任何方面有疑问,请通过questions@packtpub.com发送电子邮件给我们。

勘误:尽管我们已经尽一切努力确保内容的准确性,但错误仍然可能发生。如果您在这本书中发现了错误,我们非常感谢您向我们报告。请访问www.packtpub.com/submit-errata,点击提交勘误,并填写表格。

盗版:如果您在互联网上以任何形式遇到我们作品的非法副本,如果您能提供位置地址或网站名称,我们将不胜感激。请通过copyright@packtpub.com与我们联系,并提供材料的链接。

如果您有兴趣成为作者:如果您在某个领域有专业知识,并且您有兴趣撰写或为书籍做出贡献,请访问authors.packtpub.com

分享您的想法

一旦您阅读了《营销中的机器学习和生成式 AI》,我们很乐意听听您的想法!请点击此处直接进入此书的亚马逊评论页面并分享您的反馈。

您的评论对我们和科技社区都很重要,并将帮助我们确保我们提供高质量的内容。

下载本书的免费 PDF 副本

感谢您购买本书!

你喜欢在路上阅读,但又无法携带你的印刷书籍到处走吗?

您的电子书购买是否与您选择的设备不兼容?

别担心,现在每购买一本 Packt 书籍,您都可以免费获得该书的 DRM 免费 PDF 版本。

在任何地方、任何设备上阅读。直接从您喜欢的技术书籍中搜索、复制并粘贴代码到您的应用程序中。

优惠不止于此,您还可以获得独家折扣、时事通讯和每日邮箱中的精彩免费内容。

按照以下简单步骤获取优惠:

  1. 扫描下面的二维码或访问以下链接:

packt.link/free-ebook/9781835889404

  1. 提交您的购买证明。

  2. 就这些!我们将直接将您的免费 PDF 和其他优惠发送到您的电子邮件。

第一章:人工智能时代营销的演变及准备您的工具箱

在信息时代,数据科学和人工智能(AI)/机器学习(ML)技术的出现从根本上改变了营销格局。这种变革重塑了营销人员使用的工具和方法,重新定义了品牌与客户互动的方式。它导致了营销策略从目标广告转向更加个性化的客户体验,以及使用更多数据驱动、高效和有影响力的营销实践。本书旨在为您提供在导航和利用这一变革所需的知识和技能。我们将为您提供一套全面的工具箱,使您能够掌握数据驱动的营销策略,增强客户参与度,并在不断发展的数字领域中保持竞争力。

在本章中,我们开始探索人工智能时代营销的演变,探讨正在塑造营销未来核心数据科学和 AI/ML 技术。我们将回顾营销技术的历史,数字营销的兴起,以及 AI/ML 在革命性变革领域中的关键作用。

本章还将指导您设置 Python 环境,使您能够在营销项目中实施 AI/ML,并介绍本书中将使用的必要工具和库。然后,我们将通过一个端到端示例演示开发 ML 模型时的一些基本最佳实践。这些基础知识将使您了解如何在这个复杂而令人兴奋的 AI/ML 驱动营销领域中导航,为您的营销策略创新和增长开辟新的机会。

在本章中,我们将特别涵盖以下主题:

  • 人工智能/机器学习(AI/ML)在营销领域的演变

  • 营销中的核心数据科学技术

  • 为 AI/ML 项目设置 Python 环境

本章为后续的高级讨论奠定了基础,确保您具备充分参与后续章节中将要探讨的 AI/ML 方法所需的知识和工具。

人工智能/机器学习在营销领域的演变

在过去几十年中,营销领域经历了根本性的变革,这一变革受到了人工智能(AI)和机器学习(ML)技术的出现和整合的显著影响。这一领域的演变重新定义了所使用的工具和策略,并重塑了品牌与受众连接的方式。从传统营销方法向数据驱动和人工智能增强方法的转变标志着营销领域的一次重大转变,带来了更加个性化、高效和吸引人的营销实践。

从大众媒体到人工智能和机器学习

人工智能和机器学习已经将营销格局从基于大众媒体的策略转变为个性化和数据驱动的策略,增强了品牌与受众的连接方式。

下面的时间线展示了营销的关键里程碑,从传统方法到数字时代,最终到人工智能/机器学习技术的整合:

图 1.1:营销简史

让我们在以下章节中看看这些时期的特征。

人工智能之前的营销时代

要欣赏人工智能和机器学习对营销的影响,回顾人工智能之前的时代是很重要的。当时,营销策略主要是由广泛的人口统计洞察力决定的,个性化程度不高,对大众媒体的依赖性很大。营销人员被迫撒大网以捕捉潜在客户,客户互动的主要渠道是印刷、电视和广播广告。

传统营销还包括直接邮寄和优惠券等技术。这可以从克莱德·霍普金斯在 20 世纪初提出的科学广告原则中看出,这些原则与今天的定向数字广告有类似的作用。然而,尽管在一定程度上有效,但这些策略缺乏现代消费者所期望的精确性和个性化。为了说明数字时代之前的营销格局,让我们看看以下传统营销材料的例子,包括传单和广告牌,突出了对物理媒体的依赖性,用于广告:

图 1.2:传统营销材料示例,如传单、广告牌和印刷广告

数字营销的出现

在 1990 年代,数字革命带来了第一次重大转变,引入了工具和平台,使营销人员能够更直接地定位受众,更准确地衡量他们活动的效果。电子邮件营销、社交媒体和搜索引擎的出现,基于客户偏好、行为和反馈的数据,为客户互动开辟了新的途径。

图 1.3:数字营销通过社交媒体、搜索引擎和电子邮件营销的定向活动革命性地改变了广告

然而,到了 2000 年初,数据的庞大数量和复杂性很快就超过了人类分析和有效利用这些数据的能力。这种复杂性源于来自各种数字渠道的大量数据生成,包括不同的格式、数据创建的高速度以及实时处理的需求。这一数据景观凸显了旧有数字技术的局限性,如基本的电子邮件营销和静态网页广告,这些技术无法轻易处理以获得可操作的见解。这为人工智能和机器学习在营销中的整合奠定了基础。

数字营销的影响

数字时代带来了目标广告和可衡量的活动,这得益于搜索引擎、社交媒体和电子邮件营销等新兴工具的出现,这些工具为人工智能和机器学习在营销中的应用铺平了道路。

人工智能/机器学习在营销中的整合

人工智能时代可以追溯到 20 世纪中叶,当时人工智能首次成为热门词汇,但实际的技术应用开始得较晚。在营销领域,自 2010 年代初以来,人工智能和机器学习技术已被用于利用大数据进行洞察和个性化。这些技术的出现标志着营销领域的转型时代,并实现了前所未有的精确性和效率。

营销人员现在可以超越基本的人口统计目标,创建高度个性化的体验,并以惊人的准确性预测客户需求和行为。在我们讨论这个最关键的时期时,我们将探讨这些技术如何正在改变营销的各个方面,从客户细分到实时分析和个性化内容创作。

以下是将人工智能/机器学习整合到营销中的关键方面:

  • 预测分析和客户洞察:本书的第二部分,我们将探讨人工智能和机器学习如何通过预测分析赋予营销人员能力,根据历史数据预测未来客户行为。这种预测能力使得主动营销策略成为可能,从预测客户需求和偏好到识别潜在的流失风险。此外,我们还将讨论如聚类等解释技术,这些技术有助于理解客户细分和行为,而无需必然预测未来结果。聚类可以揭示客户数据中的自然分组。这些聚类有助于识别不同的市场细分,并指导更精准的营销策略。营销人员可以利用这些洞察实现以下目标:

    • 做出明智的决策:预测分析有助于识别哪些营销策略可能成功。例如,零售商可以预测哪些产品在假日季节可能受欢迎,从而优化库存和营销活动。

    • 优化营销努力:预测分析可以帮助营销人员更有效地分配资源。例如,公司可以使用这些洞察来确定推出促销活动或接触目标受众的最有效渠道,从而最大化投资回报率。

    • 培养更牢固的客户关系:营销人员可以通过预测客户需求和偏好来创建更个性化的体验。例如,流媒体服务可以根据用户的过去观看习惯推荐节目和电影,这增加了用户满意度和忠诚度。

  • 大规模个性化:人工智能/机器学习对营销最显著的贡献之一是能够在规模上个性化营销努力。在本书的第三部分中,我们介绍了如何以惊人的精确度细分受众,我们可以利用这一点来定制信息、优惠和内容,以匹配每位客户的兴趣和需求。这种程度的个性化导致更有效的营销策略,增强了客户体验,并提高了参与度和转化率。

    例如,一个在线书店可以根据用户的过去购买和浏览历史向不同用户推荐不同的书籍。一个经常购买悬疑小说的客户可能会收到该类别的最新发行书籍的个性化推荐,而另一个更喜欢自助书籍的客户可能会看到最新自助书籍的精选列表。

    个性化为什么重要?

    在规模上实现个性化是人工智能/机器学习在营销中的一个重大成就,它允许根据个人客户偏好定制信息、优惠和内容,从而推动参与度和转化率。

  • 通用人工智能在内容创作和分析中的作用:展望未来,本书的第四部分探讨了通用人工智能(GenAI)在营销中的作用以及它如何可能进一步革命化内容创作、客户参与和分析。通用人工智能模型能够生成文本、图像甚至视频内容,为动态和个性化的营销材料提供新的可能性。例如,一个在线零售商使用通用人工智能为水瓶创建数字广告,针对不同的用户画像。对于注重环保、希望过可持续生活的消费者,可以展示一个在自然风光中设置的相关产品放置的图像,如图中左侧所示。相反,对于城市爱好者,右侧的图像将同一产品放置在一个繁忙的城市场景中。

图片

图 1.4:通用人工智能针对不同的用户画像定制广告,为注重环保的消费者使用自然风光,为城市爱好者使用城市景观

此外,由人工智能和机器学习驱动的先进分析继续优化客户细分、活动优化和投资回报率测量,确保营销策略既有效又高效。

通用人工智能的重要性

通用人工智能模型处于营销下一场演变的尖端,能够创建个性化的文本、图像和视频内容,并提供更深入的客户洞察的高级分析。

随着我们站在这个新时代的门槛上,人工智能和机器学习在营销策略中的整合不再是奢侈品,而是品牌为了保持竞争力并与受众产生共鸣的必需品。我们通过人工智能/机器学习在营销演变中的旅程不仅突显了一场技术革命,而且标志着品牌与客户连接方式的根本转变,提供了更加个性化、吸引人和有意义的互动。

营销中的核心数据科学技术

将数据科学技术应用于动态的营销领域对于理解复杂的客户数据、优化营销策略和提升客户体验至关重要。本书全面探讨了塑造现代营销努力的核心数据科学方法,其中第二章专注于通过关键绩效指标KPIs)解码营销绩效。这将为您理解这些技术如何驱动洞察力提供一个坚实的基础。

当对客户数据和预测分析如何结合有深入理解时,结果可以是一个高度有效的客户策略。以下图表说明了涉及的一般端到端流程,从数据收集开始,以定向营销活动结束:

图片

图 1.5:数据驱动营销的一般流程,从数据收集到使用数据科学技术进行定向活动

在以下小节中,我们将更深入地探讨特定的数据科学技术,如预测分析、客户细分和 A/B 测试,以及洞察力和实际示例,以说明它们在现代营销中的应用。

预测分析

预测分析是数据科学在营销中的基石。在第三章中,我们讨论了如何利用统计模型和机器学习算法根据历史数据预测未来客户行为。这一应用范围从预测最有可能进行购买的客户到识别有流失风险的客户。通过利用预测分析,营销人员可以就资源分配、如何设计他们的活动以及何时与客户互动做出明智的决策。利用季节性和趋势的能力,这是第四章的重点,在定制营销策略以利用可预测的消费行为和市场动态的波动中也发挥着重要作用。

预测分析预测客户行为

预测模型通过分析历史数据并识别可以反映未来行为的模式来提高预测的准确性。

不同预测模型及其在营销中的应用示例包括:

  • 电子邮件打开可能性:预测客户打开营销邮件的概率,以优化活动参与度。例如,预测客户更有可能在工作日打开发送的电子邮件。

  • 购买/转化可能性:预测哪些客户更有可能购买,有助于提高转化率的有针对性的营销。例如,识别对类似产品表示过兴趣的客户。

  • 客户流失预测:识别有流失风险的客户,使营销人员能够实施有针对性的保留策略以最小化流失。例如,检测在一定时期内未与该服务互动的用户。

  • 网站登录频率建模:分析登录模式,以告知参与策略并定制再参与活动。例如,认识到每天登录的用户更有可能参与新功能。

  • 联系频率建模:确定最佳接触频率,以保持参与度而不使客户感到疲惫。例如,发现每周更新可以保持客户参与度而不引起疲劳。

理解客户数据

理解客户数据对于任何数据驱动的营销策略至关重要。这包括以下不同类型的信息:

  • 人口统计细节:了解年龄、性别、位置和其他人口统计因素有助于营销人员针对特定受众定制他们的信息。例如,根据季节性向寒冷地区的客户推广冬季服装。

  • 购买历史:分析过去的购买行为使营销人员能够推荐类似或互补的产品,增加未来销售的可能性。例如,向最近购买智能手机的客户建议配件。

  • 在线行为模式:跟踪网站导航和交互数据有助于营销人员优化网站布局和内容,以提升用户体验和参与度。例如,识别购买过程中的常见退出点,并简化结账程序以降低购物车放弃率。

  • 社交媒体互动:监控社交媒体活动和情绪使营销人员能够实时与客户互动,解决他们的需求或担忧。例如,利用社交媒体平台上的客户反馈来改进产品和服务的营销活动,以及基于热门讨论创建与受众产生共鸣的活动。

对于营销人员来说,挑战不仅在于收集这些数据,还在于分析和解释它们以获得可操作的见解。我们将在第五章中进一步讨论这一点,其中我们将探讨情感分析如何增强客户洞察,提供对客户情绪和意见的更好理解,从而为有针对性的营销活动提供信息。稍后,第七章将介绍个性化产品推荐,展示分析和解释客户数据以获得可操作见解的重要性。

从数据到洞察

数据挖掘和分析可以将原始且可能令人不知所措的数据转化为宝贵的客户洞察金矿。

A/B 测试和实验

A/B 测试是营销人员工具箱中的基本数据科学技术。它涉及比较营销资产的两个版本,如网页、电子邮件或广告,以确定在给定的指标上哪个版本表现更好,例如点击率或转化率。一个版本(A)作为控制组,而另一个版本(B)是 A 的变体,包含旨在提高性能的更改。如第六章所述,A/B 测试基于统计假设检验,提供了一种基于实际客户行为而非直觉的数据驱动方法来优化营销材料和策略。以下流程图简要描述了从 A/B 测试创建到最终选择更有效版本的步骤:

图片

图 1.6:A/B 测试过程总结

细分和定位

数据科学在营销中的基本应用之一是细分。这个过程涉及根据共享的特征或行为将广泛的客户群划分为更小的子群体。例如,聚类分析等技术使营销人员能够识别其受众中的不同细分市场,从而实现更精准和个性化的营销努力。通过了解每个细分市场的具体需求和偏好,营销人员可以调整他们的信息、优惠和内容,使其与目标受众产生更深的共鸣。在第八章中进一步探讨了细分的方法和益处,其中我们强调数据科学如何帮助营销人员识别其受众中的不同细分市场。

针对定制内容的细分

细分对于确保预期的信息传达给理想的目标群体至关重要。

客户终身价值建模

客户终身价值CLV)提供了关于客户在其与品牌的关系中预期产生多少收入的见解。CLV 建模是最大化营销努力盈利性的关键方面,我们将在第二章中讨论。数据科学技术允许营销人员为单个客户或细分市场建模和计算 CLV,提供在优先考虑营销努力、优化客户获取成本和培养与高价值客户长期关系方面极具价值的见解。

CLV 在长期中的价值

CLV 建模从长期视角看待客户关系,有助于在客户获取和保留方面取得更好的结果。

集成 AI 以增强洞察力

AI 与数据科学技术的集成标志着营销分析的重大飞跃。第九章至第十一章重点介绍使用零样本学习创建引人入胜的内容,使用少量样本学习增强品牌存在感,以及使用检索增强生成进行微定位,展示了 AI 算法如何在大规模数据集中分析复杂数据集以识别模式和获得新的见解。第十二章进一步探讨了 AI/ML 在营销中的未来格局,突出了即将到来的趋势以及新的 AI 创新塑造营销策略的潜力。

在实施这些强大的 AI/ML 能力的同时,我们还必须了解伦理考虑和治理框架,以确保我们遵循负责任的营销实践,这将是第十三章的重点。

关键 GenAI 概念

以下 GenAI 概念将在本书的第四部分中详细讨论:

  • 零样本学习:在没有先前训练示例的情况下预测新类别

  • 少量样本学习和迁移学习:使用少量训练示例进行预测

  • 检索增强生成RAG):结合数据检索和响应生成以获得更准确的输出

为 AI/ML 项目设置 Python 环境

对于相对较新的 AI/ML 世界的营销人员来说,设置一个健壮的 Python 环境是解锁数据科学在营销策略中潜力的第一步技术步骤。Python 以其简洁和强大的库而闻名,是当今技术公司中大多数 AI/ML 项目的基石。本节将指导您设置针对营销项目优化的 Python 环境,确保您拥有必要的工具和库。Python 的魅力在于其庞大的库生态系统,这些库专为数据分析、机器学习、自然语言处理NLP)等设计。对于 AI/ML 项目,由于 Anaconda 发行版在管理包和环境方面的简便性,强烈推荐使用它。让我们看看如何开始。

安装 Anaconda 发行版

访问 Anaconda 网站www.anaconda.com/download,下载 Python 3 的安装程序。一旦下载了 Anaconda 发行版,您可以按照安装说明进行操作,创建一个新的环境。这可以通过打开一个终端窗口并输入以下命令来完成:

conda create --name ai_marketing python=3.8
conda activate ai_marketing 

运行这些命令后,您应该有一个名为ai_marketing的新 Python 环境,其中安装并激活了 Python 3.8。此环境将帮助您有效地管理 AI/ML 项目的依赖项,将它们与系统上的其他项目隔离开来。

安装 AI/ML 所需的 Python 库

在你的环境设置完成后,下一步是安装将推动你的 AI/ML 营销项目的关键 Python 库。以下是一些 AI/ML 项目的基本 Python 库,按其一般功能分组。你可以使用 Anaconda 通过以下终端命令安装这些库:

  • NumPy 和 pandas 用于数据处理:

    conda install numpy pandas 
    
  • Matplotlib 和 Seaborn 用于数据可视化:

    conda install matplotlib seaborn 
    
  • scikit-learn 用于机器学习:

    conda install scikit-learn 
    
  • TensorFlow 和 Keras 用于深度学习:

    conda install tensorflow keras 
    
  • NLTK 和 spaCy 用于 NLP:

    conda install nltk spacy 
    
  • Hugging Face 的 Transformers 用于高级 NLP 和生成式 AI:

    pip install transformers 
    

将你的环境与 JupyterLab 集成

JupyterLab 提供了一个理想的交互式编码环境,非常适合数据探索、可视化和逐步展示 AI/ML 分析。这可以通过以下终端命令安装:

conda install jupyterlab 

要启动 JupyterLab,在那里你可以创建和管理你的笔记本,请在终端中键入以下内容:

jupyter lab 

你现在应该在新启动的浏览器窗口中看到类似于以下屏幕的界面:

图 1.7:启动后的 JupyterLab UI 图像

验证你的设置

为了确保一切设置正确,请在 Jupyter 笔记本中运行一个简单的 Python 脚本来验证关键库的安装。点击 图 1.7 下方的 笔记本 标题下的图标,并键入以下代码行:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn
import tensorflow as tf
import transformers
print("Environment setup successful!") 

Shift + Enter 将执行单元格中的代码:

图 1.8:环境设置成功消息

在 Jupyter 笔记本中导航

  • 使用你的 Jupyter 笔记本,你现在可以按步骤编写、运行和记录你的 Python 代码。你可以在 jupyter.org 网站上找到广泛的文档和教程。以下是一些基本知识,帮助你开始:

  • 创建新单元格:你可以通过点击工具栏顶部的 + 按钮来向你的笔记本添加新单元格。这将直接在你当前选择下方插入一个新单元格。

  • 运行单元格:要执行单元格中的代码,请选择单元格,然后按 Shift + Enter 或点击工具栏中的 运行 按钮。这将运行代码并在单元格下方显示任何输出。

你也可以使用 Ctrl + Enter 来运行单元格而不移动到下一个单元格。

  • 更改单元格类型:Jupyter Notebook 支持不同类型的单元格,包括用于 Python 代码的代码单元格和用于文本的 Markdown 单元格。

你可以使用工具栏中的下拉菜单更改单元格类型。选择 代码 用于 Python 代码或 Markdown 用于叙述文本、方程式或 HTML。

  • 使用 Markdown 进行文档编写:Markdown 单元允许你添加格式化文本、项目符号、编号列表、超链接、图片等,使你的笔记本更易于阅读和信息丰富。基本的 Markdown 语法包括:

    • # 用于标题(例如,# 标题 1## 标题 2

    • * 用于项目符号列表

    • 1., 2. 等,用于编号列表

    • `code` 用于内联代码

    • 链接文本 用于超链接

    • 替代文本 用于图片

  • 保存和共享笔记本:通过点击工具栏中的保存图标或使用 Ctrl + S(或在 Mac 上使用 Cmd + S)来定期保存您的笔记本。

您可以通过从文件 -> 下载为菜单下载各种格式(包括.ipynbHTMLPDF等)来共享您的笔记本。

  • 提高效率的快捷键:Jupyter 支持几个键盘快捷键用于常见操作。按 Esc 进入命令模式,在那里您可以:

    • 使用 A 在当前单元格上方插入一个新单元格。

    • 使用 B 在下面插入一个新单元格。

    • 使用 M 将当前单元格切换到 Markdown 单元格。

    • 使用 Y 将其切换回代码单元格。

    • 使用 DD(按 D 两次)来删除当前单元格。

训练您的第一个机器学习模型

随着我们开始在营销中应用 AI/ML,了解任何数据科学项目中涉及的基本步骤至关重要。Iris 数据集是一个经典的分类示例,由于其简单性和信息性特征,在机器学习中得到了广泛的应用。这将通过以下步骤为您提供一个动手实践,介绍在 Jupyter Notebook 环境中执行 AI/ML 数据分析的端到端过程:

  • 第 1 步:导入必要的库

  • 第 2 步:加载数据

  • 第 3 步:探索性数据分析(EDA)

  • 第 4 步:数据预处理

  • 第 5 步:模型训练

  • 第 6 步:评估模型

第 1 步:导入必要的库

在进入步骤之前,让我们首先使用以下代码导入所有必需的库:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeClassifier, plot_tree
from sklearn.metrics import precision_score, recall_score, f1_score 

第 2 步:加载数据

Iris 数据集包含 150 条鸢尾花记录,包括它们的萼片和花瓣的测量以及花的种类。Scikit-learn 提供了轻松访问此数据集并将其加载到 pandas DataFrame 的方法:

iris = load_iris()
iris_df = pd.DataFrame(data=iris.data, columns=iris.feature_names)
iris_df['species'] = iris.target_names[iris.target]
iris_df.head() 

一旦将代码输入到您的 Jupyter 笔记本并运行,它应该如下所示:

图 1.9:Iris 数据集前 5 行的视图

第 3 步:探索性数据分析

在加载数据集后,是时候深入挖掘潜在的数据特征了:

  1. 我们可以通过以下命令首先了解我们数据的结构:

    print(iris_df.info()) 
    

这将给出以下输出:

图 1.10:Iris 数据集的数据结构视图

上述结果使我们深入了解数据结构,包括列名和数据类型、非空计数(缺失值可能会显著影响机器学习模型的表现),以及内存使用(在管理计算资源时很有用,尤其是在处理大型数据集时)。

  1. 接下来,我们可以可视化特征的分布,以了解我们处理的数据的性质。直方图是通过将数据分成区间或“桶”并显示每个桶中数据点的数量来总结数值数据分布的图形表示:

    iris_df.hist(figsize=(12, 8), bins=20)
    plt.subtitle('Feature Distribution')
    plt.show() 
    

图 1.11:Iris 数据集中特征分布的直方图

红色鸢尾花数据集的特征直方图为我们提供了关于其特征特性的宝贵见解,包括它们的分布形状(它们是钟形还是偏斜的),异常值和异常情况(这些可以显著影响模型性能),以及特征可分性(如果一个特征始终落入一个与其他物种重叠不多的物种分类中,它可能对该物种是一个好的预测因子)。

  1. 最后,我们可以利用散点图来可视化特征之间的成对关系,并使用配对图来深入了解每个特征如何与其他物种中的其他特征相互作用。我们可以通过以下方式生成特征对的散点图:

    sns.scatterplot(x='sepal length (cm)', y='sepal width (cm)', hue='species', data=iris_df)
    plt.title('Sepal Length vs. Sepal Width')
    plt.show()
    sns.scatterplot(x='petal length (cm)', y='petal width (cm)', hue='species', data=iris_df)
    plt.title('Petal Length vs. Petal Width')
    plt.show() 
    

这给我们以下输出:

图片

图 1.12:红色鸢尾花数据集中不同物种特征之间的成对关系散点图

如上图散点图所示,花瓣长度和花瓣宽度可能表现出明显的物种聚类,表明它们是物种分类的强预测因子。

配对图通过显示数据集中每对特征的散点图提供了更全面的视角。此外,对角线上的直方图提供了每个特征的分布,按物种分段:

sns.pairplot(iris_df, hue='species')
plt.show() 

这会产生以下输出:

图片

图 1.13:红色鸢尾花数据集的配对图,显示每对特征的散点图和对角线上的直方图

上述配对图使我们能够快速识别哪些特征具有线性关系或多个维度上物种之间的清晰分离。例如,花瓣长度和花瓣宽度的组合显示出物种之间的明显分离,表明这些特征特别适用于分类任务。对角线上的直方图有助于理解每个物种内每个特征的分布,提供了如何利用这些分布进行预测建模的见解。例如,如果一个特征在物种内显示出紧密、定义良好的分布,这表明该特征是该物种的可靠预测因子。相反,在物种内分布较宽的特征可能作为预测因子不太可靠。

可视化 EDA 的重要性

可视化 EDA 是建模过程中的一个强大第一步。通过识别模式、集群和异常值,我们可以就特征选择、预处理和选择机器学习模型做出明智的决定。

第 4 步:为机器学习准备数据

下一个关键步骤是为机器学习准备我们的数据。这个过程通常涉及为模型选择特征,将数据分为训练集和测试集,有时还需要将特征转换为更适合你计划使用的算法。

在像这里给出的监督学习任务中,我们区分特征(自变量)和目标(因变量)。在Iris数据集中:

  • 特征包括测量值:花瓣长度、花瓣宽度、花萼长度和花萼宽度。

  • 目标是鸢尾花植物的物种。

对于我们的示例,我们将遵循以下步骤:

  1. 我们使用所有四个测量值作为特征来预测鸢尾花植物的物种,这使得这是一个多类分类问题:

    X = iris_df[['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']]
    y = iris_df['species'] 
    
  2. 为了评估机器学习模型的表现,我们将数据集分为训练集和测试集。训练集用于训练模型,测试集用于评估其在未见数据上的性能。常见的拆分比例是 80%用于训练,20%用于测试。我们可以使用 scikit-learn 的train_test_split函数轻松拆分数据:

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) 
    

数据拆分的重要性

将数据分为训练集和测试集是机器学习中的一个基本实践。这有助于准确评估模型的性能,并确保模型能够很好地泛化到新的、未见过的数据。通过在不同的数据集上进行训练和测试,我们降低了过拟合的风险,即模型在训练数据上表现良好,但在新数据上表现不佳。

  1. 一些机器学习算法对数据的规模很敏感。例如,计算数据点之间距离的算法(如 K 最近邻算法)可能会受到不同尺度的特征的影响。可以通过以下代码应用特征缩放:

    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train)
    X_test_scaled = scaler.transform(X_test)
    X_train_scaled_df = pd.DataFrame(X_train_scaled, columns=X_train.columns)
    X_train_scaled_df.head() 
    

这将给出以下输出:

图 1.14:鸢尾花数据集前 5 行的缩放特征

现在,每个特征值都围绕 0 中心,具有单位方差。这一步对于某些对数据规模敏感的机器学习算法至关重要,并确保每个特征按比例对最终模型做出贡献。

第 5 步:训练模型

在加载数据、探索和准备数据后,我们现在可以继续到机器学习项目中最激动人心的部分之一:训练模型。对于这个示例,我们将使用决策树分类器,这是一种多才多艺的机器学习算法,适用于分类任务,易于理解和解释,因为它模仿人类的决策过程。决策树将帮助我们根据我们之前准备的特征预测鸢尾花植物的物种。

决策树通过从根节点到某个叶节点的路径对实例进行分类,该叶节点提供了实例的分类。树中的每个节点代表正在分类的实例中的一个特征,每个分支代表节点可以假设的值。我们可以使用 scikit-learn 训练我们的决策树分类器:

dt_classifier = DecisionTreeClassifier(random_state=42)
dt_classifier.fit(X_train, y_train) 

模型训练完成后,我们可以使用它进行预测。我们将使用测试集中的特征来预测鸢尾花植物的物种:

y_pred = dt_classifier.predict(X_test)
print("First few predictions:", y_pred[:5]) 

以下是其输出:

First few predictions: ['versicolor' 'setosa' 'virginica' 'versicolor' 'versicolor'] 

为什么使用决策树?

决策树是分类任务中的一种流行选择,因为它们不需要太多的数据准备,易于解释和可视化,并且可以处理数值数据和分类数据。对于 ML 初学者来说,决策树提供了一种清晰直观的方式来理解模型训练和预测的基本原理。

可视化决策树可以提供模型如何做出决策的见解:

plt.figure(figsize=(20,10))
plot_tree(dt_classifier, filled=True, feature_names=iris.feature_names, class_names=iris.target_names.tolist()) 

这给我们以下输出:

图 1.15:基于 Iris 数据集构建的决策树分类器的可视化

上述可视化显示了树在特征上的分割,这些分割的标准,以及最终预测的叶节点,这些预测基于落入该叶节点的训练样本中的多数类。对于 ML 新手来说,看到这个过程可以阐明看似简单的算法如何有效地分类实例。可视化你的模型还可以突出模型可能过度拟合的区域,通过创建过于复杂的决策路径。

第 6 步:评估模型

最后一步是使用模型在测试集上的预测并评估其性能。这一步至关重要,因为它帮助我们了解我们的模型在未见数据上的泛化能力。

使用训练好的决策树分类器,我们现在可以计算精确率、召回率和 F1 分数。让我们看看它们究竟是什么:

  • 精确率衡量正预测的准确性。它是真正例预测与总正预测(包括真正例和假正例)的比率。高精确率表明模型在正预测方面是可靠的。

  • 召回率(或灵敏度)衡量模型捕捉所有实际正例的能力。它是真正例预测与总实际正例(包括真正例和假阴性)的比率。高召回率意味着模型擅长捕捉正例,而不会遗漏很多。

  • F1 分数是精确率和召回率的调和平均数,提供了一个单一指标来评估它们之间的平衡。F1 分数在 1(完美的精确率和召回率)时达到最佳值,在 0 时达到最差值。

我们将使用 scikit-learn 中的内置函数来计算这些指标。然后,这些预测可以与实际物种进行比较,以评估我们模型的某些性能指标:

precision = precision_score(y_test, y_pred, average='macro')
recall = recall_score(y_test, y_pred, average='macro')
f1 = f1_score(y_test, y_pred, average='macro')
print(f"Precision: {precision:.2f}")
print(f"Recall: {recall:.2f}")
print(f"F1-Score: {f1:.2f}") 

这给我们以下输出:

Precision: 1.00
Recall: 1.00
F1-Score: 1.00 

在精确度、召回率和 F1 分数上达到 1.0 的分数是卓越的,表明模型在测试集上表现出完美的性能;然而,在现实场景中,尤其是在复杂和嘈杂的数据中,这样的完美分数是罕见的,应该谨慎对待,因为它们可能并不总是反映模型泛化到未见数据的能力。Iris 数据集相对较小且结构良好,类之间有明确的区别。因此,这种简单性使得与真实世界数据集相比,更容易实现高性能指标,因为真实世界数据集的训练和评估通常更复杂。正如我们将在未来的章节中讨论的,进一步的输出诊断,如混淆矩阵,也可以用来深入了解模型的优势和劣势。

理解模型性能

模型准确率是评估机器学习模型有效性的一个重要指标。接近 1.0 的准确率表明有很高的正确预测水平。然而,考虑其他指标,如精确度、召回率和混淆矩阵,进行更全面的评估也很重要,尤其是在类别不平衡的数据集中。

恭喜!通过完成这些步骤——训练模型、进行预测和评估其性能——你已经掌握了机器学习项目的基本工作流程。在这里你练习的技能和概念可以直接应用于后续章节中你将要执行的创建有效、数据驱动型营销活动的练习。

摘要

在本章中,我们通过设置一个针对人工智能/机器学习项目定制的 Python 环境开始了我们的基础之旅,重点关注营销领域。我们还提供了一段时间内的营销概述,并给你介绍了一些关于该领域目前状况的背景信息。以 Iris 数据集作为一个实际例子,我们带你了解了加载数据、执行 EDA、准备数据用于机器学习以及最后训练和可视化模型的基本步骤。我们还为理解这些步骤如何转化为营销分析奠定了基础。这个练习展示了 Python 的通用性和其丰富的库生态系统,突出了它们在数据处理、机器学习、自然语言处理和数据可视化中的作用。

虽然这个例子与营销没有直接关系,但它教授了你在现实世界中可能面临的营销挑战(如客户细分、预测分析和活动优化)中直接可用的基本技能。熟悉这些流程为你应对更复杂和专业的营销数据分析提供了坚实的基础。数据科学工作的迭代和探索性,提供了灵活的技术来测试假设、可视化数据和分享见解。这就是它对有效分析如此有用的原因。随着我们继续前进,本章中介绍的工具、技术和原则将成为我们探索更高级 AI/ML 应用的基石。进入 AI/ML 驱动的营销之旅充满了利用数据获得战略优势、增强客户参与和推动业务增长的机会。在设置好 Python 环境和完成初步 ML 项目后,你现在可以深入探索 AI 和 ML 在营销中的变革潜力。

第二章中,我们将讨论使用 KPI 解码营销绩效的核心概念,为您提供有效衡量和优化营销策略的基本工具。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人见面,并在以下地点与超过 5000 名成员一起学习:

packt.link/genai

第二章:使用 KPI 解码营销表现

每个数据驱动或 AI/ML 驱动的营销策略都以一系列优化和增强目标开始,这些目标与关键性能指标相关联。这些关键性能指标或措施通常被称为关键绩效指标(KPI),它们有助于你跟踪营销活动的表现并定义营销努力的成功标准。在本章中,我们将定义并探讨一些在数字和数据驱动营销中常用的 KPI,包括转化率获取成本(CPA)、客户终身价值(CLV)和投资回报率(ROI)。

在本章中,我们将讨论一组常用的营销 KPI,它们能告诉你关于你的营销活动的哪些信息,以及如何利用它们进一步改进和优化你的营销策略和业务成果。我们将以一个保险产品营销数据集为例,说明如何使用 Python 及其数据分析与可视化库,如pandas, numpy, matplotlibplotly,来分析、可视化和从营销 KPI 中获取洞察。

在本章中,我们将特别涵盖以下主题:

  • 理解营销 KPI

  • 使用 Python 计算和可视化 KPI

  • 使用 KPI 跟踪营销表现

源代码和数据github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/tree/main/ch.2

数据来源www.kaggle.com/datasets/pankajjsh06/ibm-watson-marketing-customer-value-data

理解营销 KPI

作为营销人员或营销数据科学家,KPI 是衡量任何营销努力成功与失败的关键。在开展任何营销活动之前,正确使用和定义 KPI 对于有效衡量营销成功与失败至关重要。然而,KPI 的不当使用可能导致收集到错误信息,并常常浪费大量财务和人力资源,这对业务产生直接的负面影响。

例如,如果你的营销目标是提高目标群体(即,阿尔法世代)的品牌知名度,但你没有正确地分解营销内容印象的来源(即,文本与图片与视频,或 YouTube 与 Instagram 与 TikTok,或网红推荐与付费广告),那么它可能讲述的故事与实际情况完全不同。在本节中,我们将回顾一些常用的 KPI,并在接下来的章节中继续讨论其实施和实际应用案例。

什么是 KPI?

KPI 是关键绩效指标,用于衡量和量化实现特定目标或目标的进展。KPI 帮助组织识别优势和劣势,并在商业的各个方面,如营销、财务、销售和运营,做出基于数据的决策。

在营销漏斗的每个阶段,都有与之相关的 KPI。以下图表展示了一个典型营销漏斗的总结以及每个阶段常用的某些 KPI。

图片

图 2.1:典型营销漏斗的不同阶段

现在,让我们更详细地看看这些阶段中的每一个。

意识阶段

意识阶段,目标是让客户了解您的组织和企业产品。因此,品牌建设和曝光是最终的市场营销目标。在这个阶段衡量营销活动成功的一些典型 KPI 包括页面浏览量广告点击量访问者数量SEO 排名。关键在于优化营销支出以实现最大的品牌印象和曝光。

参与阶段

参与阶段,目标是开始与潜在客户互动并建立关系。您可能希望潜在客户通过打开电子邮件、阅读通讯、点击链接和注册活动来与您的组织和企业产品互动。在这个阶段衡量营销活动成功的一些关键指标或 KPI 包括打开次数点击次数点赞次数合格潜在客户数量

特别是,跟踪潜在客户的数量以及潜在客户的质量与未来的潜在收入直接相关。这里要记住的关键指标或度量是每次点击成本(CPL),其计算公式为:

图片

在这个阶段,跟踪 CPL(每次点击成本)的起伏对于成功的营销活动至关重要,因为 CPL 的上升表明您的营销策略效率正在下降。

转化阶段

转化阶段是我们收获所有辛勤工作的地方。对于不同类型的客户,转化的定义可能不同。对于电子商务企业,转化可能意味着潜在客户进行商品购买。对于媒体企业,转化可能意味着潜在客户注册或支付订阅费以获取通讯。无论如何,这是潜在客户成为客户的时候。在这个阶段要关注的某些关键指标包括购买次数购买金额订阅次数购物车中的商品数量

在这个阶段,跟踪转化率对于衡量营销活动的成功和失败至关重要。转化率很简单:

图片

跟踪转化率的起伏变化非常重要,因为下降的转化率可能表明在这一阶段的营销策略效率低下、产品功能不足或市场兴趣转移。除了跟踪这一关键绩效指标(KPI)之外,深入了解转化率起伏背后的驱动因素更为重要。我们将在下一节进一步探讨一些可以采取的方法来深入了解转化率,并在下一章中更详细地讨论,揭示转化率起伏背后的驱动因素和因素。

保留阶段

保留阶段,你专注于将客户转变为回头客,为客户提供持续的价值,并使他们坚持使用你的服务或产品。保留客户并将他们转变为一致的回头客与产生稳定的收入流直接相关。一些关键指标包括客户保留率(CRR)、客户流失率(CCR)、客户终身价值(CLV)和获取成本(CPA)。

CRR 和 CCR 可以使用以下方程计算:

图片 3图片 4

上升的 CRR 表明客户认为你的服务和产品具有持续使用价值;另一方面,CCR 的增加则表明相反的情况。客户流失可能有多种原因,深入数据以了解潜在原因是构建这一阶段成功营销策略的关键。我们将在下一节讨论如何从不同角度审视数据,以全面理解某些客户行为,并在下一章中讨论更深入的分析技术,包括使用机器学习。

保留阶段,理解 CLV 和 CPA 对可持续业务至关重要。即使 CLV 很高,每个客户都能带来显著收入,但如果 CPA 超过 CLV,那么这将是一个净负面的业务。尽管计算 CLV 并不简单,但 CPA 和 CLV 的公式如下:

图片 1图片 2

正如你可能注意到的,CLV 公式中的客户价值可能取决于许多因素,例如业务类型和价值定义。我们将在第八章从人工智能/机器学习的角度深入探讨 CLV 的估算,但本节的关键要点是 CPA 抵消 CLV,对这两个 KPI 的适当测量和优化是保留阶段成功营销策略的关键路径。

忠诚阶段

这个阶段是您的客户成为您服务或产品的倡导者,并通过推荐、口碑或评论带来更多新线索和客户。向这些忠诚客户表示感谢,帮助他们传播您的服务产品信息,并继续与您的忠诚客户建立强大的人际关系和联系。

所讨论的所有关键指标对于这个阶段都是相关且重要的,需要持续监控。例如,页面访问次数和页面浏览次数,这些是意识阶段的 KPI 之一,仍然适用于这个阶段,这样您可以持续监控和评估忠诚客户群体的兴趣水平。点击次数和点赞数,这些是参与阶段的 KPI,例如,在忠诚度阶段仍然相关,这样您可以跟踪这一客户群体的持续参与。购买数量和金额,以及保留率和流失率,这些是转化保留阶段的 KPI 之一,仍然需要监控,因为这些忠诚客户是给企业带来最稳定收入流的人。

除了上述 KPI 之外,净推荐值NPS)、推荐数量评论数量也可以是忠诚度阶段需要监控的其他重要 KPI。

为了获得 NPS,需要进行调查以收集客户反馈,并根据调查结果,按照以下公式计算 NPS:

图片

例如,如果 60%的调查受访者是推荐者,10%的受访者是贬低者,那么你的 NPS 将是 50。NPS 的范围从-100 到 100,分数越高,客户对您服务和产品的满意度就越高。定期进行此类满意度调查并监控 NPS 是明智的,因为不解决 NPS 下降问题可能会导致客户流失率增加和转化率降低。

我们已经涵盖了客户旅程和营销漏斗的关键阶段,以及如何为每个阶段制定 KPI 来跟踪营销漏斗的健康状况,以及如何衡量每个阶段的营销策略的成功与失败。你不仅需要持续监控 KPI,还需要深入数据以识别漏斗中哪些部分存在弱点,以及不同客户群体对不同的营销策略有何不同的行为。在下一节中,我们将以保险营销数据集为例,使用 Python 讨论如何将这些知识应用到实践中,并开始生成可重复使用和可追踪的 KPI,并从这些 KPI 中得出可操作的项目。

使用 Python 从数据中计算和可视化 KPI

在我们已经讨论的各种营销 KPI 的基础上,让我们深入探讨一些这些 KPI 在现实世界中的潜在应用案例,如何计算和可视化它们,以及如何解释它们以进行进一步的数据驱动决策。我们将使用一个保险产品营销数据集作为示例。

从财务角度来看,营销的成功在于以更少的支出带来更多的收入。跟踪和衡量这一点最直接的方法是查看转化率、客户终身价值(CLV)和客户获取成本(CPA)。转化率告诉我们转化为付费客户的潜在客户的百分比,CLV 告诉我们每个获取的客户的估计收入,CPA 告诉我们获取一个付费客户所需的成本。通过结合这三个 KPI,我们可以理解投资回报率(ROI)和对净收入的贡献。

使用上述示例数据集,让我们讨论如何使用 Python 来衡量这些关键绩效指标(KPIs),帮助生成更深入的见解,并最终影响更高效和更好的营销策略的决策过程。

转化率

我们将在这些数据中查看的第一个 KPI 是转化率。记得从上一节中,转化率是转化为购买产品的潜在客户的百分比。在这个数据的上下文中,转化为的是在Response列中响应的潜在客户。

整体转化率

为了计算整体转化率,我们使用pandas库:

  1. 假设数据文件名为data.csv,你可以使用以下代码导入并读取数据到DataFrame中:

    import pandas as pd
    df = pd.read_csv("./data.csv") 
    
  2. 接下来,我们需要将Response列中的文本响应转换为二进制值 0 或 1,这样我们就可以轻松地计算转化率。执行此操作的代码如下:

    df["conversion"] = df["Response"].apply(lambda x: 1 if x == "Yes" else 0) 
    
  3. 为了使用这些数据计算整体转化率,你只需将新创建的conversion列中的值取平均值,如下面的代码所示:

    df["conversion"].mean() 
    
  4. 一种可视化和轻松理解整体转化率的方法是使用饼图,这是展示数据中不同段落的组成或分解的绝佳方式。生成此类饼图的代码如下:

    ax = df.groupby("conversion")["Customer"].count().reset_index().plot.pie(
        figsize=(5, 5),
        y="Customer",
        autopct='%1.1f%%',
        legend=False,
        labels=["No Conversion", "Conversion"],
        explode=[0.05, 0.05]
    )
    ax.set_ylabel(None) 
    

在这里,我们首先按列分组,按段计数客户数量。这导致了已转化客户与未转化客户的数量。

  1. 然后,我们为这两个群体绘制饼图。结果如下所示:

图 2.2:转化率与未转化的饼图

如明显可见,大多数潜在客户没有转化。只有 14.3%的合格潜在客户转化为保单续费或对续费优惠做出了的响应。这在营销中通常是这种情况。通常,转化率非常低,甚至在数字营销中低个位数的转化率并不异常。

该图表本身很有洞察力,因为它有助于业务利益相关者了解目标潜在客户中有多少比例成功转化,但这还不够。为了全面了解数据对我们转化率的说明,我们需要从多个角度来审视。

人口统计学和转化率

深入挖掘以生成更多关于转化率的洞察的一种方法是查看客户的人口统计学特征及其可能对转化率的影响。例如,在我们的数据中,有一个名为收入的列。我们可以根据不同的收入水平来分解转化率,以了解数据可能告诉我们关于收入和转化率之间关系的故事。

在我们的示例数据中,报告的收入范围从 0 美元到 100,000 美元。为了便于理解和更好的可视化,我们将将其分为 10 个收入级别,并检查收入和转化率之间的关系,如下面的代码所示:

df["income_category"] = df["Income"].apply(
    lambda x: 0 if x == 0 else x//10000
)
income_conversion = df.groupby("income_category")["conversion"].mean() * 100
ax = (
    income_conversion
).plot.bar(
    figsize=(5, 5),
    rot=45,
)
ax.set_xticklabels(["$0" if x == 0 else f"${x}0-{x+1}0k" for x in income_conversion.index])
ax.set_ylabel("Conversion Rate (%)")
ax.set_xlabel("Reported Income")
ax.set_title("Conversion Rate across Reported Income") 

此代码的输出如下:

图片

图 2.3:不同收入段的转化率柱状图

如从此柱状图可见,收入在 10k 至 20k 之间的人群具有最高的转化率。另一个值得注意的有趣点是,此图表显示双峰分布,一个在 10-20k,另一个在 70-80k。最后,报告收入为 0 的客户似乎显示出最低的转化率。

尝试使用其他人口统计学变量,如性别、教育和婚姻状况来分解转化率!

销售渠道和转化率

客户如何被接触也可能是影响转化率的一个关键因素。我们可以根据销售渠道来分解转化率,如下面的代码所示,以了解销售渠道和转化率之间的关系:

ax = (
    df.groupby("Sales Channel")["conversion"].mean() * 100
).plot.bar(
    figsize=(5, 5),
    rot=45
)
ax.set_ylabel("Conversion Rate (%)")
ax.set_title("Conversion Rate per Sales Channel") 

生成的柱状图如下:

图片

图 2.4:不同销售渠道的转化率柱状图

如此图表所示,当客户通过代理商接触时,转化的可能性最高。其他三个渠道,即分支呼叫中心网络,在转化率方面具有相似的可能性。这可能与代理商与客户之间的个人联系以及个人互动如何影响客户转化倾向有关。

并非令人惊讶的是,不同销售渠道的转化率构成如下:

图片

图 2.5:不同销售渠道的转化率饼图

生成此饼图的代码如下:

sales_channel_count = df.groupby("Sales Channel")["conversion"].sum()
ax = sales_channel_count.reset_index().plot.pie(
    figsize=(5, 5),
    y="conversion",
    autopct='%1.1f%%',
    legend=False,
    labels=sales_channel_count.index,
    explode=[0.02]*df["Sales Channel"].nunique()
)
ax.set_ylabel(None) 

此饼图表明,在转化中,略高于 50%是通过代理商互动实现的,其次是分支,然后是呼叫中心网络对转化贡献的影响相似。

总结来说,从不同角度看待转化率告诉我们关于它们的不同故事。它告诉我们,低收入($10-20k)和高收入($70-80k)人群的转化率很强,而中等收入($40-50k)和$0 报告收入人群的转化率较弱。它还提供了关于哪些营销渠道在本次续订营销活动中效果最好的洞察,显示在四个渠道中,代理商联系效果最好。基于这些 KPI 分析,我们更好地了解了哪些方面需要改进,哪些方面已知效果良好。

尝试更深入地研究转化率,不仅与其他变量,如续订优惠类型和车辆类别,还与多个变量,如销售渠道和州或教育以及政策和车辆尺寸一起研究。

将隐藏的洞察力带到表面!

CLV

如前所述,CLV 是计算 ROI 的关键指标之一,因为它告诉我们每位客户带来的潜在收入。在本节中,我们将利用数据集中给出的预计算 CLV。然而,我们将在第八章中深入讨论如何为每位客户构建和预测 CLV。为了专注于 KPI 并从 KPI 中得出可操作的项目和洞察力,我们将在本章中使用给定的 CLV。

总体 CLV

使用pandas库,有多种方式来理解 CLV 的分布。一种方式是使用 DataFrame 的describe函数,如下所示:

df["Customer Lifetime Value"].describe() 

此代码将显示以下输出中的分布:

图 2.6:CLV 的分布

如您所见,describe函数为我们提供了关于客户终身价值列的高级分布信息,其中平均 CLV 为$8,004.94,中位数为$5,780.18。另一种查看分布的方式是使用箱线图,通过 DataFrame 的plot.box函数实现,如下所示代码:

df["Customer Lifetime Value"].plot.box() 

这给我们以下输出:

图 2.7:CLV 的箱线图

如上图中的箱线图所示,存在一个非常长的尾部或一组异常值。这与describe函数的输出相吻合,其中平均值远高于中位数,这表明存在长尾。这种数据偏斜性也如以下直方图所示可见:

ax=df["Customer Lifetime Value"].hist(bins=25)
plt.show() 

然后,我们看到以下输出:

图 2.8:CLV 的直方图

如直方图所示,右侧有一个长尾,这与之前箱线图和描述性统计输出中显示的异常值相对应。

从市场营销和商业角度来看,这意味着大多数客户的终身价值将低于$10,000,并且将有一小部分高知名度客户的终身价值超过$10,000。由于这些群体对不同营销策略的反应和反应会有很大差异,因此考虑针对不同客户群体个性化营销信息和方法将是明智的。我们将在第七章中深入探讨个性化营销;然而,理解本节中显示的 CLV 和其他 KPI 显示了需要针对不同营销信息进行定位的不同潜在群体是至关重要的。

地理定位和 CLV

在分析客户终身价值时,我们不仅应该关注 CLV 的整体分布,还应该从多个角度进行观察。一个角度可以是地理定位以及地理定位如何影响 CLV。在示例保险营销数据集中,有一个名为State的列。我们可以使用以下代码分别查看不同州的 CLV:

ax = df.groupby("State")["Customer Lifetime Value"].mean().plot.bar(
    figsize=(5, 5),
    rot=45
)
ax.bar_label(ax.containers[0], fmt='$%.1f')
ax.set_ylabel("Customer Lifetime Value ($)")
ax.set_title("CLV per State") 

生成的条形图看起来如下:

图片

图 2.9:不同州 CLV 的条形图

我们已经使用groupby函数根据State列对数据进行分组,并计算了客户终身价值的平均值。通过使用plot.bar函数,我们可以可视化不同州的 CLV。尽管不同州的平均 CLV 相似,但俄勒冈州的平均 CLV 最高,而亚利桑那州的平均 CLV 最低。

由于同一州内的地区也可能存在差异,我们可以通过以下代码进一步细化分析,按地区类型进行更深入的分组:

ax = df.groupby([
    "State", "Location Code"
])[
    "Customer Lifetime Value"
].mean().unstack().plot.bar(
    figsize=(5, 5),
    rot=45
)
ax.set_ylabel("Customer Lifetime Value ($)")
ax.set_title("CLV per State") 

这给我们以下输出:

图片

图 2.10:不同州和位置的 CLV 条形图

与之前的图表相比,我们现在不仅按State分组,还按Location Code分组。这为我们提供了关于不同类型的地区如何进一步影响 CLV 的额外见解。之前,我们已经看到与其他州相比,亚利桑那州的整体 CLV 最低;然而,正如这个条形图所示,亚利桑那州的城区 CLV 最高,CLV 的下降主要是由亚利桑那州内的RuralSuburban地区驱动的。一般来说,城区的 CLV 高于农村和郊区,除了俄勒冈州华盛顿州。俄勒冈州和华盛顿州内的农村地区 CLV 高于城区。从这项练习中可以注意到,从不同角度分析 KPI 可以揭示不同的见解。

产品和 CLV

客户购买的产品的不同通常会导致 CLV 的差异。我们可以通过查看Policy列来检查我们的数据集中这种关系,该列是客户已购买的保险产品:

ax = df.groupby("Policy")["Customer Lifetime Value"].mean().plot.bar(
    figsize=(5, 5),
    rot=45
)
ax.bar_label(ax.containers[0], fmt='$%.1f', fontsize=6)
ax.set_ylabel("Customer Lifetime Value ($)")
ax.set_title("CLV per Product") 

这给我们以下条形图:

图片

图 2.11:不同产品 CLV 的条形图

通过按Policy分组并平均 CLV,我们得到了之前图表中显示的分布。值得注意的是,拥有Special L3政策或产品的客户具有最高的 CLV,而拥有Corporate L2的客户具有最低的 CLV。由于客户购买的产品类型本质上与客户的需求和欲望相关,因此在针对不同的客户群体时应该考虑这一点。使用预测机器学习建模进行个性化营销策略可以是一个更有效地针对不同客户群体的好方法。

CPA

如前所述,CPA 是衡量营销效果的一个重要指标。获取新客户所花费的成本因业务而异。一些常见的新客户获取营销成本包括通过不同渠道的广告,如电子邮件、邮件、电视、社交媒体、促销商品、电话营销和客户服务电话,以及其他工具,如网站推广、聊天机器人和客户关系管理系统。

正如我们在分析转换率时所见,在我们的保险营销数据集示例中,使用了四个渠道来推广保险续保优惠:AgentBranch Call CenterWeb。不幸的是,这个例子中的数据没有每个销售渠道的成本;因此,我们将做一些假设。

让我们假设每个Agent销售的成本约为$200,每个Branch销售的成本约为$85,每个Call Center销售的成本约为$30,每个Web销售的成本约为$2。在现实世界中,您需要跟踪您使用的每个营销渠道的营销支出。例如,您需要知道每个销售代理通话的每分钟成本,每个在线广告点击的成本,以及每封电子邮件或直接邮件的成本。基于这个假设,我们将为每个客户分配估计获取成本,如下所示:

import numpy as np
cost_distr = {
    "Agent": {"avg": 200, "std": 40},
    "Branch": {"avg": 85, "std": 17},
    "Call Center": {"avg": 30, "std": 6},
    "Web": {"avg": 2, "std": 0.5}
}
df["est_acquisition_cost"] = df["Sales Channel"].apply(
    lambda x: np.random.normal(cost_distr[x]["avg"], cost_distr[x]["std"], 1)[0]
) 

如您从这段代码中可以看到,我们创建了一个cost_distr字典,其中包含了我们对每个营销渠道成本的假设。然后,我们使用numpy库的random.normal函数从我们的假设中为每条记录生成随机数,并将它们插入到一个列中,即est_acquisition_cost,这个列将在接下来的小节中使用:

df["est_acquisition_cost"].describe() 

这是从假设分布创建合成数据的一种方法。生成的分布应该看起来像以下这样:

图 2.12:生成的估计获取成本的分布

由于这些数字是从正态分布中随机生成的,所以每次运行此代码时,具体的数字都会有所不同。然而,整体分布将类似于以下输出。

总体 CPA

正如我们在上一节中讨论的那样,CPA 是计算为总营销成本除以总转换数,这可以在 Python 中完成,如下面的代码所示:

campaign_cost = df["est_acquisition_cost"].sum() / df["conversion"].sum() 

我们只需对 est_acquisition_cost 列的所有值求和,这将给出总的营销支出,然后除以转化数量,这是通过在 conversion 列的所有值上求和来完成的:

print(f"${campaign_cost:.1f}") 
$739.8 

campaign_cost 的值应该类似于 $739.8

在撰写本文时,campaign_cost 的值是 $739.8;然而,鉴于我们在使用假设创建合成数据时随机性的本质,这个值每次运行时可能会有所不同,但应该在大致范围内。

销售渠道和 CPA

由于不同的销售和营销渠道有不同的成本,CPA 会因渠道而异。我们也可以从我们的数据中观察到这一点。为了计算每个渠道的 CPA,我们只需计算每个渠道的总营销成本,然后除以每个渠道的转化数量,如下面的代码示例所示:

channel_cpa = (
df.groupby("Sales Channel")["est_acquisition_cost"].sum()
/
df.groupby("Sales Channel")["conversion"].sum()
) 

在此代码中,我们首先将 Sales Channel 列应用 groupby 函数,并对 est_acquisition_cost 列求和。然后,我们再次将 Sales Channel 列应用 groupby 函数,但这次是对 conversion 列求和。当我们把前一个 pandas Series 除以后一个 pandas Series 时,它将每个 Sales Channel 列的 est_acquisition_cost 的总和除以 conversion 的总和:

ax = (
    channel_cpa
).plot.bar(
    figsize=(5, 5),
    rot=45
)
ax.bar_label(ax.containers[0], fmt='$%.1f')
ax.set_ylabel("Cost per Acquisition ($)")
ax.set_title("CPA per Sales Channel") 

新创建的变量 channel_cpa 的条形图看起来如下:

图片

图 2.13:不同销售渠道的 CPA 条形图

如预期的那样,CPA 在 Agent 渠道最高,在 Web 渠道最低。尽管从 Agent 渠道的转化率最高,正如我们在上一节讨论不同销售渠道的转化率时所见,但 CPA 仍然是最高的。这是一个很好的例子,说明了管理营销支出的成本与拥有高转化率一样重要。

促销活动和 CPA

与 CPA 因销售渠道而异类似,CPA 也可能因营销促销的类型而异。我们也可以从我们的数据集中观察到这一点。为了计算每个促销活动的 CPA,你可以使用以下代码:

promo_cpa = (
df.groupby("Renew Offer Type")["est_acquisition_cost"].sum()
/
df.groupby("Renew Offer Type")["conversion"].sum()
) 

在这里,我们按 Renew Offer Type 列分组,并对 est_acquisition_costconversion 列求和,然后将前者除以后者。得到的条形图如下所示:

ax = (
    promo_cpa
).plot.bar(
    figsize=(5, 5),
    rot=45
)
ax.bar_label(ax.containers[0], fmt='$%.1f')
ax.set_ylabel("Cost per Acquisition ($)")
ax.set_title("CPA per Promotion") 

图片

图 2.14:不同促销活动的 CPA 条形图

从这张图表中可以突出两件事。一是 Offer3 的 CPA 是最高的,另一个是 Offer4 的 CPA 没有显示。Offer4 的 CPA 没有显示在这张图表中的原因是没有任何转化。

这可以在你深入研究每个促销活动的转化率时找到,如下所示:

df.groupby("Renew Offer Type")["conversion"].mean() 

图片

图 2.15:不同续订优惠类型的转化率

虽然这解释了为什么Offer4的 CPA 没有在之前的柱状图中显示,因为没有转化,但这仍然不能完全解释为什么Offer3的 CPA 如此之高,因为仍然有一些转化。更有趣的是,从以下代码生成的图表显示,Offer3的总营销支出在四个促销活动中是第二低的:

ax = df.groupby("Renew Offer Type")["est_acquisition_cost"].sum().plot.bar(
    figsize=(5,5),
    rot=45
)
ax.bar_label(ax.containers[0], fmt='$%.1f')
ax.set_ylabel("Total Cost ($)")
ax.set_title("Total Cost per Promotion") 

这里是柱状图:

图 2.16:不同促销活动的总成本柱状图

这是一个很好的例子,说明了低转化率如何抵消低营销支出,反之亦然。Offer1有最高的营销支出,比Offer3高出近 3 倍,因此Offer1的高转化率抵消了营销成本,这导致了比Offer3低得多的 CPA。另一方面,Offer3有第二低的营销支出,但 CPA 最高,因为Offer3的低转化率抵消了低营销支出。这表明有必要从各个方面分析 KPI,并理解某些 KPI 起伏的关键因素。

ROI

我们已经走了很长的路,最终能够计算我们营销活动的 ROI。到目前为止,我们已经分析了的转化率、CLV 和 CPA 将被结合起来得到 ROI,并决定营销资金是否被合理使用。

总体 ROI

简而言之,ROI 是总收入或利润除以总支出。在我们的例子中,一种方法是计算已转化的客户的“客户终身价值”总和,然后除以“预计获取成本”列的总和,如下面的代码所示:

campaign_cost = df["est_acquisition_cost"].sum()
converted_clv = (df["Customer Lifetime Value"] * df["conversion"]).sum()
print(f"Total CLV: ${converted_clv:,.02f}")
print(f"Total Cost: ${campaign_cost:,.02f}")
print(f"Overall ROI: {(converted_clv-campaign_cost)/campaign_cost:.01f}x") 

输出如下:

Total CLV: $10,274,171.74
Total Cost: $972,130.58
Overall ROI: 9.6x 

如此输出所示,从已转化的客户中增加的总 CLV 约为 1030 万美元,在我们例子中的总营销支出约为 96.8 万美元。这给我们带来了 9.6 倍的 ROI 或 960%,这表明这次营销活动的价值增加超过了 9.6 倍的开支。如果这是一个具有如此表现的现实世界营销活动,这将是一个杰出的营销活动。通常,5:1 的 ROI 是一个坚实的成果,任何更高的都被认为是很好的。2:1 或以下的 ROI 被认为是令人失望的。

另一种可视化这个 KPI 的有效方法是直观地展示价值流入与流出。展示这种信息的一种方法是使用瀑布图,如下所示:

图 2.17:净回报瀑布图

正如你所想象的那样,你可以通过影响价值增加和减少的因素进行分解。例如,你可以通过每个销售渠道可视化价值增加,并展示其如何汇总到总 CLV 增加,以及通过每个销售渠道可视化价值减少,并展示其如何汇总到总营销成本。水图是可视化价值增加和减少以及在一个视图中展示净回报的绝佳方式。以下代码可以使用plotly库来可视化水图:

import plotly.graph_objects as go
fig = go.Figure(
    go.Waterfall(
        name = "Waterfall",
        orientation = "v",
        measure = ["relative", "relative", "total"],
        x = ["Total CLV", "Total Marketing Cost", "Net Return"],
        textposition = "outside",
        text = [
            f"${converted_clv:.01f}",
            f"${campaign_cost:.01f}",
            f"Return: ${converted_clv-campaign_cost:.1f} ({(converted_clv-campaign_cost)/campaign_cost:.01f}x)"
        ],
        y = [converted_clv, -campaign_cost, 0],
        connector = {"line":{"color":"rgb(63, 63, 63)"}},
    )
)
fig.update_layout(
    height=500,
    width=500,
    title = "ROI",
    title_x = 0.5,
    showlegend = True
)
fig.show() 

如此代码所示,你可以在plotly库中使用Waterfall对象来创建水图。这里的关键参数包括:

  • measure:这是一个值类型的数组。使用relative来显示相对值,例如增加和减少,使用total来计算总和值。

  • x:这是一个 x 坐标的数组,其中包含每个增加和减少的标签。

  • y:这是一个 y 坐标的数组,其中包含增加和减少的值。

水图可以是一种直观且高效展示价值流入和流出的方式。尝试将其分解以进一步展示对价值增加和减少有贡献的因素!

每个销售渠道的 ROI

如前一小节简要提到的,分析哪些因素以何种方式对 ROI 有贡献,这对于帮助理解哪些营销策略或渠道最有效以及哪些无效非常重要。我们将首先关注的 ROI 角度是销售渠道。我们首先要做的是计算净回报并计算每个销售渠道的 ROI,如下所示:

df["return"] = (
df["Customer Lifetime Value"] * df["conversion"]
) - df["est_acquisition_cost"]
channel_roi = (
df.groupby("Sales Channel")["return"].sum()
/
df.groupby("Sales Channel")["est_acquisition_cost"].sum()
) 

此代码创建了一个新变量,名为return,它是 CLV 减去获取成本,对于未转化的客户,它只是一个负获取成本,因为没有价值增加。然后,通过按Sales Channel列分组并除以return的总和与est_acquisition_cost的总和来计算每个渠道的 ROI。为了可视化每个销售渠道的 ROI,可以使用以下代码:

ax = (
    channel_roi
).plot.bar(
    figsize=(5, 5),
    rot=45
)
ax.bar_label(ax.containers[0], fmt='%.1fx')
ax.set_ylabel("Return on Investment (multiple)")
ax.set_title("ROI per Sales Channel") 

生成的图表如下所示:

图片

图 2.18:不同销售渠道的 ROI 柱状图

此柱状图表明,Web渠道的 ROI 最高,其次是呼叫中心渠道,而代理商渠道最低。正如你所想象的那样,ROI 与 CPA 呈负相关,与 CLV 呈正相关。

Web渠道的低 CPA 可能是导致极高 ROI 的最高贡献因素,因为该销售渠道的转化率与其他渠道相似。另一方面,代理商渠道的高 CPA 可能是相对低 ROI 的最关键因素,因为其转化率在四个渠道中是最高的。正如你所见,ROI 及其分解是深入了解如何最佳管理营销成本和产生回报的洞察力 KPI。

每个促销的 ROI

最后一个我们将考虑的因素,以理解不同角度的 ROI 动态,是促销类型。我们将查看Renew Offer Type如何影响 ROI,如下面的代码所示:

promo_roi = (
    df.groupby("Renew Offer Type")["return"].sum()
    /
    df.groupby("Renew Offer Type")["est_acquisition_cost"].sum()
) 

如代码所示,我们按Renew Offer Type列分组,并将return的总和除以est_acquisition_cost的总和。这可以通过以下代码用柱状图可视化:

ax = (
    promo_roi
).plot.bar(
    figsize=(5, 5),
    rot=45,
    color=(promo_roi > 0).map({True: 'cornflowerblue', False: 'salmon'})
)
ax.bar_label(ax.containers[0], fmt='%.1fx')
ax.set_ylabel("Return on Investment (multiple)")
ax.set_title("ROI per Promotion") 

我们得到了如下柱状图:

图片

图 2.19:不同优惠的 ROI 柱状图

此柱状图显示Offer2具有最高的 ROI,其次是Offer1,而Offer4最低。正如之前发现的,Offer4没有转化;因此,所有的营销支出都损失了,导致-100%的回报或-1x ROI。

如前所述,从 CPA 的讨论中可以预期,Offer3Offer4之后具有最低的 ROI。这可能是由于Offer3的高 CPA,这负面影响了 ROI。另一方面,Offer2的 CPA 最低,这有助于它在促销优惠中拥有最高的 ROI。

KPI 之间的相关性

如我们所见,有多个因素影响着 ROI,这反过来又需要从不同的角度进行分析。我们已经检查了从Engagement阶段到Conversion阶段的基本 KPI 及其解释,直到本节。

不仅可以通过一组定义的因素来检查 KPI,我们还可以利用更数据驱动和统计的方法来揭示各种指标之间的关系。一种方法可能是分析 KPI 之间的相关性,以及 KPI 与其他因素之间的相关性。热力图是一种巧妙的方式来可视化这些关系,并提供对数据中隐藏关系的更直观理解。这种分析技术揭示了不同的 KPI 如何相互关联,以及单个因素如何与 KPI 相关联,为优化营销活动提供战略见解。以下代码可以用于使用我们的示例数据构建热力图:

import seaborn as sns
import matplotlib.pyplot as plt
correlation_matrix = df[[
    'Income', 'Monthly Premium Auto',
    'Months Since Last Claim', 'Months Since Policy Inception',
    'Number of Open Complaints', 'Number of Policies', 'Total Claim Amount',
    'conversion', 'Customer Lifetime Value', 'est_acquisition_cost', 'return'
]].corr()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, fmt=".2f", cmap='coolwarm', cbar=True)
plt.title('Correlation Matrix Heatmap of Marketing KPIs')
plt.show() 

此代码生成了以下热力图:

图片

图 2.20:变量之间关系的热力图

值得注意的是,Monthly Premium AutoTotal Claim Amount之间的相关性突出,系数为0.632,表明存在强烈的正相关关系。这表明随着汽车保险月保费的增加,索赔总额也会增加。这样的见解对于希望平衡保费率与索赔成本以最大化利润的保险公司来说是无价的。

此外,收入总索赔金额显示出显著的负相关系数-0.355,突显出高收入客户往往有较低的总索赔金额。这可能意味着高收入细分市场可能代表较低的风险特征,这可能会指导针对性的营销策略或保费调整。

在分析和构建 KPI 时要富有创意,并专注于构建一个好的数据故事!

使用 KPI 跟踪营销表现

计算和构建 KPI 是解码营销表现的关键方面之一,但跟踪 KPI 的进展和变化同样重要的是掌握营销表现的重要方面。有无数种方法可以可视化 KPI,以及无数种跟踪和与关键利益相关者共享 KPI 的方法。在本节中,我们将分享一些常见的可视化方法和持续 KPI 跟踪的方法。

选择合适的 KPI 可视化

当展示 KPI 数据时,选择合适的可视化方式在有效传达洞察力方面起着至关重要的作用。以下是一些有助于选择最合适的可视化类型的指南:

  • 柱状图:非常适合比较不同类别之间的数量,例如不同地区或产品的销售表现。

  • 饼图:用于说明整体的组成或比例,如市场份额分布。

  • 散点图:用于探索两个变量之间的关系,例如广告支出与销售收入。

  • 折线图:适合展示随时间变化的趋势,例如网站流量增长或销售趋势。

  • 面积图:通常用于比较一个或多个系列随时间的变化,或数值,例如不同渠道的网站流量。

  • 热图:适用于展示大型数据集中相关或模式,例如各种营销关键绩效指标(KPI)之间的关系。

  • 漏斗图:非常适合可视化过程中的各个阶段,尤其是在营销或销售漏斗中的转化率方面特别有用。

  • 瀑布图:常用于展示总和为总值的增加和减少,例如现金流。

持续的 KPI 跟踪

现在我们已经尝试了在给定数据集的情况下如何在 Python 中计算 KPI,你可能想知道接下来是什么。你也可能会质疑你是否每次想要报告 KPI 指标时都必须运行你的 Python 脚本。通常采用并推荐用于持续 KPI 跟踪的方法是利用可访问的仪表板。

什么是仪表板?

仪表板是一种展示数据多种视觉形式的方式,以便利益相关者可以轻松地共享和消化信息。它包括需要监控的关键绩效指标和其他业务指标。仪表板的范围不仅限于跟踪营销 KPI,还可以用于各种业务线,如财务、运营、技术、客户服务等。

在商业环境中,仪表盘通常与数据仓库相连,以便可视化的数据直接从数据仓库中摄取。这使得仪表盘能够进行实时或接近实时的更新。如果数据仓库中的数据被更新,仪表盘上的视觉元素也会自动更新。通常,数据是复杂的、混乱的或不容易消化的,因此会构建数据摄取管道来将数据转换成更易于消化的结构。跟踪营销 KPI 的典型数据流向仪表盘的流程如下:

图片

图 2.21:数据流向仪表盘的典型流程

数据 ETL 管道开发的详细讨论超出了本书的范围,但这是一个从各种来源提取原始数据,将其转换成易于使用的格式,并加载到数据存储中的过程。提取、转换和加载这三个关键步骤组成了 ETL 的缩写。营销数据的 ETL 管道的成果是易于消化的数据,用于营销 KPI 的计算,然后这些数据在营销仪表盘上被总结和可视化。在行业中,一些常用的仪表盘软件产品包括 Tableau、Power BI 和 Looker。

优秀的 KPI 指标和仪表盘应该能够激发有意义的行动项并协助决策!考虑构建以目标为导向的 KPI 指标和仪表盘,使其针对每个营销目标和计划具体化。

摘要

在本章中,我们为构建数据和 AI/ML 驱动的营销模型和策略奠定了坚实的基础。我们讨论了常用的营销 KPI 指标,这些指标不仅帮助业务衡量营销绩效,而且基于通过多层次分析发现的优缺点激发改进的行动项。以一个保险产品营销数据集为例,我们看到了如何使用 Python 来衡量和分析这些 KPI,以便在未来的营销工作中进行进一步的改进和优化。

我们还讨论了如何使用各种仪表盘工具,如 Tableau、Power BI 和 Looker,进行可重复使用的实时 KPI 跟踪。正如每个人所强调的,AI/ML 始于数据以及深入的探索性分析,以决定用哪些数据来训练 AI/ML 模型以及优化什么。本章涵盖的项目和 KPI 将在未来设计和开发先进的营销 AI/ML 模型时派上用场。

在下一章中,我们将学习如何利用数据科学和机器学习算法来揭示营销成功和失败背后的驱动因素。更具体地说,我们将讨论如何使用回归分析和模型来剖析影响营销参与度的因素,如何使用基于树的模型来识别转化背后的驱动因素,以及如何通过因果推断来理解客户流失背后的推理。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人相聚,并与其他 5000 多名成员一起学习:

packt.link/genai

二维码

第三章:揭示营销成功的动态

关键绩效指标KPIs)擅长捕捉营销活动的当前状态或结果。然而,它们缺乏展示驱动这些结果的能力以及不同因素可能如何影响营销活动的最终结果。我们在上一章简要介绍了如何通过相关性分析进一步分析各种变量和 KPI 之间的关系。在本章中,我们将深入探讨如何利用数据科学DS)和机器学习ML)技术和工具来揭示营销成功的动态。

本章涉及客户旅程的三个关键阶段:参与、转化和流失。这三种客户行为是优化营销目标的关键组成部分,营销人员经常质疑哪些因素实际上影响了某些结果,例如为什么人们的参与度更多或更少,为什么人们最终转化更多或更少,以及为什么人们流失或没有流失。除了我们在上一章中进行的相关性分析之外,揭示影响营销结果的因素的三个最常见方法包括(1)回归分析,(2)决策树解释和(3)因果推断。在本章中,我们将讨论如何在 Python 中执行这些 ML 技术,以更好地深入理解营销成功和失败背后的驱动因素。

本章将涵盖以下主题:

  • 为什么人们会进行回归分析

  • 为什么人们会使用决策树解释进行转化

  • 为什么人们会使用因果推断进行流失分析

为什么人们会进行回归分析

通常,提高参与度是营销的第一步。潜在客户需要首先与公司或产品互动,然后才能转化为付费客户,最终成为重复或忠诚的客户。会有许多因素影响潜在客户如何参与或点击您的营销活动。具有某些社会经济背景的客户可能比其他人更容易被您的服务或产品所吸引。来自某些地区的人可能比其他人更频繁地参与您的营销活动。一些之前接触过您销售的人可能对您的服务或产品有更积极的胃口,从而比其他人有更高的参与度。

理解潜在客户如何与不同组件互动是实现更高参与率和个人化营销的关键。回归分析,一个在各个领域广为人知且广泛使用的技巧,通常被认为是机器学习中的基本概念,是一种直观且有效的方法,我们可以用它来理解可能影响目标客户参与度高低的各种组件之间的相互作用。最常用的两种回归分析类型是线性回归逻辑回归

线性回归假设目标变量与其他因素之间存在线性关系。线性关系定义为:

图片

其中 Y 是目标变量,即观察到的结果,每个 是可能影响结果的因素,每个 是每个因素对目标变量影响的系数和程度,a 是截距。当目标变量是连续变量时,如客户终身价值、销售额和客户任期,线性回归被使用。

另一方面,当目标变量是二元变量时,如通过 vs. 未通过 vs. ,和 1 vs. 0,使用逻辑回归。当线性回归估计结果值时,逻辑回归估计成功的概率,关系定义为:

图片

其中 log 表示自然对数,P(y = 1) 是结果为 1 的概率

由于逻辑回归估计结果的概率,它在理解各种因素对二元结果的影响时是一个非常有用的工具,例如客户是否会回应电子邮件营销或是否会点击电子邮件消息。在本节中,我们将使用一个汽车保险营销数据集来讨论如何使用逻辑回归揭示客户参与背后的驱动因素。

源代码和数据

github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/blob/main/ch.3/Why%20People%20Engage.ipynb

数据来源:www.kaggle.com/datasets/pankajjsh06/ibm-watson-marketing-customer-value-data

目标变量

我们需要做的第一件事是定义我们想要分析的目标或结果。由于我们感兴趣的是了解各种因素如何影响客户参与度,我们将把响应变量作为我们的目标变量,它告诉我们客户是否对营销电话做出了回应。以下代码可以用来用0编码目标变量,表示客户没有回应,用1表示客户做出了回应:

import pandas as pd
df = pd.read_csv("./engage-data.csv")
df["Engaged"] = df["Response"].apply(lambda x: 1 if x == "Yes" else 0) 

此代码首先使用 pandas 库的 read_csv 函数将数据加载到变量 df 中,并从 Response 列中创建一个新变量 Engaged,将 Yes 编码为 1,将 No 编码为 0

连续变量

影响结果或目标变量的因素变体主要有两种类型:

  • 连续变量:这些是具有实数值的变量,可以包括分数或小数,例如货币金额、销售数量和页面浏览量。

  • 分类变量:这些是有明确选项或类别值的一组离散变量,例如教育水平、性别和客户账户类型。

我们将首先查看我们汽车保险营销数据集中的一些连续变量与目标变量 Engaged 之间的关系:

df.describe() 

图片

图 3.1:数据集中连续变量的分布

如此截图所示,当我们运行 df.describe() 函数时,它显示了连续变量的总体统计信息。在我们的汽车保险示例数据集中,有八个连续变量:Customer_Lifetime_ValueIncomeMonthly_Premium_AutoMonths_Since_Last_ClaimMonths_Since_Policy_InceptionNumber_of_Open_ComplaintsNumber_of_PoliciesTotal_Claim_Amount

为了分析这些变量与结果变量 Engaged 之间的关系,我们将使用 statsmodels 包中的 Logit。拟合逻辑回归模型的代码如下:

import statsmodels.api as sm
continuous_vars = [
    x for x in df.dtypes[(df.dtypes == float) | (df.dtypes == int)].index if x != "Engaged"
]
logit = sm.Logit(
    df['Engaged'],
    df[continuous_vars]
).fit() 

在这里,我们首先导入所需的模块 statsmodels.api,并定义连续变量 continuous_vars。然后,我们可以使用 statsmodels 包中的 Logit 对象来训练一个逻辑回归模型。我们可以使用以下代码查看训练好的逻辑回归模型:

logit.summary() 

这段代码的输出如下所示:

图片

图 3.2:逻辑回归结果摘要

让我们分析这个逻辑回归输出。需要关注的两件最重要的事情是,coefP>|z|。在底部表格的最左侧列,coef,代表每个变量的系数。例如,变量 Monthly_Premium_Auto 的系数是 -0.0084,而变量 Total_Claim_Amount 的系数是 0.0001。这意味着支付更高月保费的客户不太可能对营销活动做出反应,这与高价值客户通常更难获取并鼓励参与的经验法则相符。另一方面,索赔金额较高的客户更有可能参与,因为他们可能是利用保险政策最多的人。

P>|z|列表示每个变量对结果的影响的统计显著性。通常认为小于0.05的值对结果有显著的统计影响,因为小于0.05的 p 值表明有强有力的证据反对无影响的原假设,即这个变量对目标变量没有影响。然而,大于0.05的值并不一定意味着它对结果没有任何显著性。你也可能注意到Customer_Lifetime_ValueIncome的系数非常小。

这并不表明它们对结果的影响低。正如你可能猜到的,这两个变量具有货币价值,这两个变量的尺度在千位,这导致了小的系数值,但它们对结果有显著的影响。

分类变量

我们已经看到连续变量如何以积极或消极的方式与结果Engaged相互作用。那么,关于分类或离散变量呢?在我们的汽车保险示例数据集中,我们有一些分类变量;然而,我们将使用EducationGender变量作为例子来讨论在进行回归分析时如何处理分类变量。

因式分解

我们可以采取的第一种方法是利用pandas库中的factorize功能。以Education为例,你可以运行以下代码将文本离散变量编码为数值变量:

 labels, levels = df['Education'].factorize() 

这个因式分解的结果看起来如下:

labels, levels = df['Education'].factorize()
labels 
array([0, 0, 0, ..., 0, 1, 1]) 
levels 
Index(['Bachelor', 'College', 'Master', 'High School or Below', 'Doctor'], dtype='object') 
factorize function for the Education variable and get the two variables, labels and levels. The newly created labels variable contains numerical values for each record and the levels variable contains information about what each numerical value of the labels variable means. In this example, Bachelor is encoded as 0, College as 1, Master as 2, High School or Below as 3, and Doctor as 4.

分类

我们可以采取的第二种方法是将分类变量编码为使用pandas库中的Categorical函数。以下代码展示了如何使用Categorical函数的示例:

categories = pd.Categorical(
    df['Education'], 
    categories=['High School or Below', 'Bachelor', 'College', 'Master', 'Doctor'],
categories.categories 
Index(['High School or Below', 'Bachelor', 'College', 'Master', 'Doctor'], dtype='object') 
categories.codes 
array([1, 1, 1, ..., 1, 2, 2], dtype=int8) 

Categorical函数中的categories参数允许你定义类别的顺序。在这里,我们将Education类别定义为从High School or BelowDoctor的顺序。你可以通过调用categories属性来访问类别,通过调用codes属性来获取每个记录的编码。例如,在我们的案例中,High School or Below被编码为0Bachelor1Doctor4

虚拟变量

另一种可以采取的方法是将分类变量编码为创建虚拟变量。虚拟变量是每个类别的单热编码变量。

例如,在我们的例子中,可以为Education变量创建以下虚拟变量:

pd.get_dummies(df['Education']).head(10) 

图片

图 3.3:为教育变量创建的虚拟变量

如您从这个例子中看到的,使用了pandas库的get_dummies函数来为Education变量创建虚拟变量。这创建了五个新变量:BachelorCollegeDoctorHigh School or BelowMaster。这些新创建的每个变量都是0/1(或False/True)编码,如果给定记录属于给定类别,则编码为1True

如何选择用于分类变量编码的方法

独热编码/虚拟变量:当变量没有自然顺序时,可以使用这些方法。两种方法都会为每个类别创建二进制变量。请注意,为所有类别创建独热编码和虚拟变量可能会导致数据维度很大,使数据稀疏。因此,您可能希望为独热编码/虚拟变量子选择重要的类别。

因子化:当您有没有固有顺序的名义分类变量时,可以使用此方法作为另一种快速高效的方法。

分类:当分类变量有自然顺序时,例如教育水平,最好使用指定顺序的Categorical()。这确保了编码尊重类别的层次结构,从而在顺序重要的分析中导致准确的模型预测和评估,如 AUC-ROC。

回归分析

既然我们已经探讨了可以采取的不同方法来编码分类变量,我们可以运行回归分析来了解一些分类变量如何影响结果。使用上一节中创建的新分类变量GenderFactorizedEducationFactorized,我们可以使用以下代码拟合逻辑回归模型,以建模GenderEducation水平对营销参与度水平的影响和影响:

logit = sm.Logit(
    df['Engaged'],
    df[[
        'GenderFactorized',
        'EducationFactorized'
    ]]
).fit() 

运行logit.summary()将导致以下拟合逻辑回归模型的总结:

图 3.4:逻辑回归结果总结

如您从这个逻辑回归模型输出中看到的,两个变量GenderFactorizedEducationFactorized对结果Engaged都有负系数或影响。由于Gender编码为女性为0,男性为1,这表明男性比女性不太可能做出回应。

同样,教育水平从 0 编码到 4,拥有负系数表明教育水平越高,客户做出回应的可能性就越小。

除了上一节中回归分析中看到的连续变量的结果外,这些都是很好的见解,显示了各种因素与参与度结果之间的方向关系。

交互变量

回归模型擅长识别和估计变量与目标变量之间的线性关系。然而,变量之间可能存在一些关系。例如,收入可能与教育水平高度相关。在回归分析中解决变量内部这种内在关系的一种方法是在以下公式中引入乘法项:

图片

这样,回归模型考虑了具有内在关系的变量之间的交互。Python 中statsmodels库中的相同Logit可以用于运行包含交互项的回归分析。以下代码将拟合一个包含交互项的逻辑回归模型:

logit = sm.Logit.from_formula(
  data=df,
  formula="Engaged ~ Income + EducationFactorized + Income:EducationFactorized"
).fit()
logit.summary() 

如代码所示,我们正在拟合一个包含两个变量Income(收入)和Education(教育)以及一个交互项Income x Education的逻辑回归模型。以下是对拟合逻辑回归模型的总结:

图片

图 3.5:逻辑回归结果总结

观察前两个成分,Income(收入)和EducationFactorized(教育因素化),这个输出表明Income(收入)和Education(教育)对参与可能性有积极影响。然而,交互项Income:EducationFactorized抵消了IncomeEducation的个体积极影响,因为它有一个负系数。在我们的市场营销案例中,这意味着当你比较同一收入水平的客户时,教育水平越高,他们的参与率就越低。同样,这也表明对于具有相同教育水平的客户,他们的收入越高,他们的参与率就越低。正如您从这个例子中可以看到的,通过引入交互项,我们可以更深入地分析变量之间的关系,并获得在单独分析时可能无法揭示的见解。

正如我们在本节中看到的,回归分析是揭示营销努力成功与失败背后驱动因素动态的强大工具。在我们的例子中,我们看到了各种变量如何对客户参与率产生积极和消极的影响。正如所示,回归分析擅长识别各种因素与结果之间的线性关系,并可用于理解因素之间的相互作用。

然而,通常认为回归模型缺乏对变量之间关系的理解。这部分限制是因为我们必须为所有可能的变量间关系引入交互项。正如我们在之前创建IncomeEducation交互项时所看到的,我们将不得不构建类似的交互项来处理其他可能的变量间交互。此外,如果您想引入或考虑两个以上变量之间的交互,事情开始变得复杂。

与线性回归分析不同,决策树在处理变量之间的复杂交互方面具有优势。我们将在下一节中检查决策树的使用,该节捕捉了各种因素之间的交互以及这些交互最终如何影响最终结果。

为什么人们会通过决策树解释进行转化

一旦潜在客户开始参与您的营销活动,就是开始将他们转化为付费客户的时候了。与各种背景可能影响参与倾向一样,有许多因素影响谁比其他人更频繁地转化。当然,社会经济因素在影响转化率方面始终扮演着至关重要的角色。年龄、地区和性别也可能是不同转化结果的重要因素。月份或季节也可能根据您提供的服务或产品导致转化率的变化。

不仅单个因素,而且各种因素的组合也可能对谁可能转化有重大影响。一个有工作和拥有房产的人比一个拥有房产但已退休的人更有可能为了再融资贷款而转化。一个 25 岁的学生比一个 25 岁的企业家更不可能寻找信用卡。我们简要讨论了如何通过引入交互或乘法因素,回归分析可以帮助识别相互作用的因素如何影响客户行为。另一种揭示为什么某些人比其他人更容易转化的隐藏洞察力的绝佳方法是使用决策树及其理解各种因素之间相互作用和关系的能力。

决策树,正如其名所示,通过生长树来从数据中学习。从一个根节点开始,树通过将数据分割成子类别来分支,最终达到叶节点,从叶节点可以了解哪些因素以何种方式受到影响,以到达相应的叶节点。一个决策树的示例可能如下所示:

图片

图 3.6:决策树的示例

我们将详细讨论如何使用示例数据集来解释决策树结果,因此我们将进一步解释和讨论留到以后。让我们首先谈谈决策树是如何从每个节点分支出来的。

常用的两种方法用于分割数据或分支到子节点:

  • Gini 不纯度:Gini 不纯度衡量一个划分的纯度。Gini 不纯度度量的公式如下:

图片

在这个公式中,c 代表类别标签,图片 代表具有类别标签 i 的记录被选中的概率。当树中每个节点的所有记录都是纯的,即所有记录都属于单一目标类别时,Gini 不纯度度量达到 0

  • 熵和信息增益:熵衡量通过测试的准则分割数据所获得的信息量。熵的公式如下:

至于基尼系数c代表类别标签,而代表具有类别标签i的记录被选中的概率。将导致熵度量最大变化的分割将用于分支到子节点,因为它表明这将带来最高的信息增益。

关于决策树的基本知识,我们将深入探讨如何应用它来了解是什么因素推动了成功的营销活动,以实现更高的转化率。

源代码和数据

github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/blob/main/ch.3/Why%20People%20Convert.ipynb

数据来源

archive.ics.uci.edu/dataset/222/bank+marketing

目标变量

我们将使用一个银行营销数据集来完成这个练习,其中营销活动是将客户转化为订阅定期存款。首先,让我们将数据加载到 DataFrame 中,并编码我们的目标变量。请看以下代码:

df = pd.read_csv("./convert-data.csv", sep=";")
df["conversion"] = df["y"].apply(lambda x: 1 if x == "yes" else 0) 

在这里,我们将数据加载到变量df中,并将y列编码为1表示“是”,0表示“否”。当你运行df["conversion"].mean()时,你应该看到大约 12%的客户已经转化并订阅了定期存款。

连续变量与分类变量

对于我们的分析,我们将使用以下变量,它们具有连续值:agebalancedurationcampaignprevious。你可以使用以下代码来查看这些变量的分布:

continuous_vars = [
    "age", "balance", "duration", "campaign", "previous"
]
df[continuous_vars].describe() 

分布如下所示:

图 3.7:连续变量的分布

与之前的练习类似,这个数据集中也有一些分类变量。我们将首先将第一个离散文本变量month转换为数值。如果你查看month变量的值,你会注意到这些值是 3 个字母的月份缩写。由于月份有固有的顺序,我们将使用以下代码将这些值转换为相应的数值:

months = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
df['month'] = df['month'].apply(
    lambda x: months.index(x)+1
) 

现在,变量month将具有从112的值,分别对应于从JanuaryDecember的月份。

变量job是另一个分类变量。与month变量不同,job变量在其内部没有固有的顺序。因此,我们将为每个job类别创建虚拟变量,这些变量将对应于相应的职业类别进行独热编码。请看以下代码:

jobs_encoded_df = pd.get_dummies(df['job']
jobs_encoded_df.columns = ['job_%s' % x for x in jobs_encoded_df.columns] 

此代码的输出将如下所示:

jobs_encoded_df.head() 

图 3.8:编码后的虚拟变量

与之前的练习类似,我们使用了 get_dummies 函数为数据集中的每个工作类别创建虚拟变量。您可以使用以下代码将这些新创建的虚拟变量添加回 DataFrame:

df = pd.concat([df, jobs_encoded_df], axis=1) 

使用此代码运行后,DataFrame df 将会添加新创建的 job 列的虚拟变量。

最后,我们还将使用以下代码将 maritalhousing 变量进行编码:

marital_encoded_df = pd.get_dummies(df['marital'])
marital_encoded_df.columns = ['marital_%s' % x for x in marital_encoded_df.columns]
df = pd.concat([df, marital_encoded_df], axis=1)
df['housing'] = df['housing'].apply(lambda x: 1 if x == 'yes' else 0) 

如此代码所示,我们为婚姻类别中的每一个创建了虚拟变量,这些类别包括 divorcedmarriedsingle。然后,我们将这些新创建的虚拟变量连接回 DataFrame df。我们还已将 housing 列的文本值转换为 1 表示 yes0 表示 no

由于分类变量编码在之前的练习中已经进行了深入探讨,所以我们在这个练习中快速地跳过了这一步。请花时间仔细研究这一步,并尝试在之前的练习中讨论的不同方法!

决策树分析

我们收集了我们感兴趣的变量,包括 agebalancedurationcampaignprevioushousingmonthjobmarital status。我们将开始研究这些因素是如何影响这次营销活动的转换率结果的。首先,我们将定义我们的特征和目标或响应变量,如下面的代码所示:

features = (
    continuous_vars
    + ["housing", "month"]
    + list(jobs_encoded_df.columns)
    + list(marital_encoded_df.columns)
)
response_var = 'conversion' 

如此代码所示,我们使用 conversion 列作为我们的结果或目标变量,以及我们之前创建的连续变量和编码后的分类变量。生成的特征列表应如下所示:

features 

图片

图 3.9:特征列表

在定义了特征集和目标变量后,我们就准备好构建决策树了。首先看看以下代码:

from sklearn import tree
dt_model = tree.DecisionTreeClassifier(
    max_depth=3
)
dt_model.fit(df[features], df[response_var]) 

我们在 sklearnscikit-learn 库中使用 tree 模块,并使用 DecisionTreeClassifier 类来训练决策树模型。您会注意到我们定义了一个参数,max_depth。此参数控制树的生长程度。树生长得越深,树学习数据的准确性就越高;然而,它很可能会过拟合到数据集,并且不具有泛化性,这意味着它在未观察到的数据上的表现会更差。最好限制树的生长,并在树学习数据的准确性和知识泛化得有多好之间取得平衡。在这个练习中,我们将 max_depth 设置为 3。最后,您可以使用 fit 函数让树从数据中学习。

尝试通过将数据集分为训练集和测试集,并选择最小化训练集和测试集之间差异的深度,来找到一个决策树应该生长多深的黄金点。

使用决策树从数据中获取的知识最直观的方法是可视化它从每个节点分支出来以及变量之间的交互如何导致叶节点。为此,我们将使用 graphviz 包,您可以使用以下命令进行安装:

conda install python-graphviz 

您可以使用以下代码来绘制训练好的决策树:

import graphviz
dot_data = tree.export_graphviz(
    dt_model,
    out_file=None,
    feature_names=features, 
    class_names=['0', '1'], 
    filled=True,
    rounded=True, 
    special_characters=True
)
graph = graphviz.Source(dot_data, format="png")
graph.render("conversion-dt-depth-3") 

如代码所示,我们正在向函数提供训练好的模型 dt_model 和用于训练模型的特征 features。然后,您可以使用图形的 render 函数将图形输出到图像文件。此代码将生成一个名为 conversion-dt-depth-3.png 的图像文件,其外观如下:

图片

图 3.10:决策树图

如您从决策树图中所见,树的深度为 3,这是我们训练决策树时定义的。让我们更仔细地看看这个图。

根节点是根据变量 duration 进行分割的。正如箭头所示,如果持续时间小于或等于 521.5,则移动到左侧子节点;否则,移动到右侧子节点。如果我们沿着持续时间大于 827.5marital_married 大于 0.5 的路径遍历到最右侧的叶节点,那么这个叶节点中的大多数客户已经转化。换句话说,那些接触持续时间超过 827.5 秒并且已婚的客户转化率更高。

另一方面,如果我们遍历到最左侧的叶节点,则表明那些接触持续时间小于或等于 521.5 秒(根节点)、0 次先前联系(深度 1 的左侧子节点)并且年龄小于或等于 60.5(深度 2 的最左侧子节点)的客户不太可能转化,与其他客户相比。

您可以使用其他参数来构建决策树。尝试微调您的树,看看不同的参数如何影响决策树的形成,以及您如何从同一数据集中得出各种其他见解!

如您从本例中可以看到,通过遍历树及其分支和节点,我们可以看到不同营销因素对转化客户行为的影响。与我们在上一节中进行的回归分析相比,这个决策树有更好地理解不同因素之间更复杂相互作用和相互关系的优势,以及它们如何影响结果变量。需要注意的是,回归分析和决策树分析的结果都显示了因素与结果之间的相关性,而不是某些结果的原因关系。检验某些结果的原因并不是一件容易的任务;然而,在下一节中,我们将讨论如何从数据中估计特征与结果之间的因果关系。

为什么人们会因因果推断而流失

高流失率在市场营销中尤其成问题,因为它抵消了之前营销活动产生的所有良好营销收入。深入了解人们为什么会流失以及需要优化哪些因素以降低客户流失率至关重要。正如我们在前面的章节中看到的,回归分析和决策树分析在识别潜在因素与结果之间的线性关系以及各种因素与结果变量之间的相互关系方面非常出色。然而,正如之前提到的,这些识别出的关系或相关性并不一定意味着因果关系。

识别某些结果的原因(例如,客户流失的原因)通常是一项困难且复杂的任务。这就是因果分析发挥作用的地方。如果回归分析用于识别变量之间的关系,决策树分析用于识别变量之间的相互作用,那么因果分析用于识别某些结果的原因效果

这通常是通过各种带有对照组和治疗组或实验组的实验来完成的。正如其名所示,对照组是未接受任何治疗的组。在医学实验环境中,这个对照组是将会接受安慰剂的组。另一方面,治疗组是实际接受治疗的组。同样,在医学实验环境中,这个治疗组是接受实际医疗治疗的组,例如正在开发的新药片。

在营销活动运行之前设置实验的必要性这一范式限制了事后的分析。然而,有了数据,我们仍然可以运行因果分析来估计不同因素对结果的影响。我们将使用 Python 包dowhy来基于营销活动数据运行因果分析。我们将使用银行客户流失数据作为例子来讨论如何进行因果分析,以揭示某些变量对营销结果的原因和影响。

源代码和数据

github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/blob/main/ch.3/Why%20People%20Churn.ipynb

数据来源

www.kaggle.com/datasets/shrutimechlearn/churn-modelling

安装dowhy包:

pip install dowhy 

(注意:你可能需要安装dowhy包的额外组件。请参阅官方文档pypi.org/project/dowhy/。)

因果效应估计

估计某些变量对结果产生因果效应的第一步是定义问题并做出一些假设。让我们以银行客户流失数据集为例。首先,当你将数据加载到 DataFrame 中时,你会看到以下变量:

df.info() 

图 3.11:DataFrame 快照

在这里,Exited(退出)列是我们感兴趣分析其因果的指标。正如你可能注意到的,还有其他几个列可能对分析客户流失的因果效应很有趣。有些人可能想看看高或低的信用评分是否会影响客户流失。其他人可能想看看长期或短期的工作期限是否会影响客户流失。你也可能好奇拥有多个产品是否会影响客户流失。

在本章的练习中,我们将定义我们的问题或我们感兴趣的因果效应如下:

“拥有多个产品会影响客户流失吗?”

在这个问题定义的基础上,我们可以建立一些假设,这些假设最终可能导致客户流失:

  • 拥有多个产品可能会影响客户流失率,因为拥有多个产品的人可能觉得切换到不同银行更困难或更繁琐。

  • CreditScore(信用评分)可能影响客户是否可以拥有多个产品,因为信用评分被用来决定一个人是否有资格拥有某些银行产品,例如信用卡或定期贷款。

  • Age(年龄)也可能影响客户是否拥有多个产品,因为年龄越大,可能需要更多的银行产品。

  • 同样,Tenure(客户服务期限)、Balance(账户余额)和Salary(薪水)都可能影响客户是否拥有多个产品。这些因素也可能影响客户流失。

基于这些假设和问题陈述,让我们分析MultipleProduct变量对客户流失的因果效应,使用 do-calculus 记号,可以表示为:

图片

这反过来意味着由于变量MultipleProduct的变化,客户流失可能性预期的变化。正如我们的假设一样,可能有一组其他变量会影响结果,我们可能对估计这些协变量对结果的影响感兴趣。在我们的例子中,这些协变量是TenureBalanceSalary,这些协变量对客户流失的估计因果效应可以表示为:

图片

因果模型

基于预定义的问题陈述和我们的假设,让我们开始构建一个因果模型。

首先,我们需要构建一个我们将用作处理的变量。看看下面的代码:

df["MultipleProduct"] = df["NumOfProducts"].apply(lambda x: 1 if x > 1 else 0) 

在我们的数据集中,有一个名为NumOfProducts的列。我们只是将其编码为 0 和 1,其中拥有多个产品的客户将被编码为 1,其余的为 0。

现在,我们将使用dowhy包中的CausalModel类来定义基于我们假设的因果模型,如下面的代码所示:

from dowhy import CausalModel
model = CausalModel(
    data=df,
    treatment="MultipleProduct",
    outcome="Exited",
    common_causes=["Balance", "EstimatedSalary", "Tenure"],
    instruments=["Age", "CreditScore"]
) 

如您从这段代码中看到的,我们定义了新创建的变量MultipleProduct作为我们感兴趣学习的因果效应的干预,即对结果变量Exited的因果效应。我们将BalanceEstimatedSalaryTenure定义为可能对客户流失以及客户是否可能有多个产品有因果效应的共同原因。最后,我们将AgeCreditScore定义为工具变量,因为它们可能影响客户拥有多个产品的能力。

您可以使用以下代码可视化这个因果模型:

model.view_model() 

结果的因果图如下所示:

图片

图 3.12:因果图的可视化

注意,每次运行此代码时,实际输出可能不同。

在这里,工具变量CreditScoreAge影响处理变量MultipleProduct,而MultipleProduct影响结果变量Exited,以及协变量或共同原因BalanceEstimatedSalaryTenure也影响处理变量以及结果变量。

然后,我们可以让模型识别因果效应,如下面的代码所示:

estimands = model.identify_effect()
print(estimands) 

此代码将在我们的假设下显示以下因果效应的表达式:

图片

图 3.13:因果效应的代码表达式

这应该看起来很熟悉,因为这与我们之前讨论的因果效应公式相同。

估计

在定义了因果模型之后,我们现在可以估计处理变量MultipleProduct的影响。estimate_effect函数使得这些影响的估计变得简单,如下面的代码所示:

estimate = model.estimate_effect(
    estimands,
    method_name = "backdoor.propensity_score_weighting"
)
print(estimate) 

这应该产生以下结果:

图片

图 3.14:因果估计结果

根据这个结果,我们估计治疗变量MultipleProduct对结果Exited的平均效应为-0.1390。这意味着拥有多个产品会导致客户流失概率降低约 14%。这证实了我们的假设,即拥有多个产品将增加对银行的粘性并降低客户流失的可能性。

您可以使用多种方法进行估计。以下是一些例子:

  • 线性回归

  • 距离匹配

  • 倾向得分分层

  • 倾向得分匹配

  • 倾向得分加权

我们在示例中使用了倾向得分加权,但我们建议尝试不同的估计方法,并分析它们如何影响因果效应估计。

反驳

一旦我们估计了治疗对结果的影响,就需要对其进行验证。这个假设验证步骤被称为反驳。我们将通过几种方法对假设进行稳健性检查。

第一种方法是引入一个随机共同原因或协变量变量。您可以按以下方式运行此检查:

refute_results = model.refute_estimate(
    estimands,
    estimate,
    "random_common_cause"
)
print(refute_results) 

输出看起来如下:

Refute: Add a random common cause
Estimated effect:-0.13904650583124545
New effect:-0.13904650583124542 

我们在因果模型model中使用refute_estimate函数,参数为“random_common_cause”。这种反驳方法引入了一个新的、随机生成的变量来测试因果估计是否显著变化,有助于评估模型对遗漏变量偏差的稳健性。如您从输出中看到,引入随机共同原因后的原始估计效应和新效应相同,估计的因果效应值约为-0.1390。这证实了我们的假设是正确的。

反驳我们假设的第二种方法是随机子采样数据并在该随机子集上进行测试。您可以按以下方式运行此检查:

refute_results = model.refute_estimate(
    estimands,
    estimate,
    "data_subset_refuter"
)
print(refute_results) 

输出看起来如下:

Refute: Use a subset of data
Estimated effect:-0.13904650583124545
New effect:-0.13842175180225635 

与前一个案例类似,我们使用了相同的refute_estimate函数,但这次使用了“data_subset_refuter”参数。输出表明,原始估计效应和新估计效应(使用数据的一个随机子集)非常接近。这证实了我们对MultipleProduct变量和Exited结果变量之间因果关系的假设是正确的,并且是跨数据集的可推广结果。

与多种估计方法选项类似,您有多种方式可以运行反驳。在本章中,我们尝试了随机共同原因添加和随机子集替换。然而,还有其他多种方式可以验证您的假设。以下是一些例子:

  • 用安慰剂替换治疗:将治疗变量替换为一个已知不会对结果产生因果效应的变量。

  • 用虚拟结果替换:不是替换治疗变量,而是用与治疗无关的结果变量替换。

  • 使用自举随机样本进行反驳:从数据中生成多个自举样本,并估计每个样本上的因果效应。

我们还建议尝试不同的反驳方法!官方文档中的示例可能是一组有用的资源,您可以通过以下链接找到:www.pywhy.org/dowhy/v0.11.1/example_notebooks/nb_index.html

图形因果模型

虽然之前的因果效应估计是为了分析和识别处理变量的影响,但图形因果模型能够进行根本原因分析,以及分析各种因素的因果效应和联系。当你想要理解潜在变量的因果效应以及它们最终如何导致某些结果时,这将是一个非常有用的工具。

在与之前相同的假设下,我们将学习如何使用dowhy图形因果模型来更好地理解变量之间的因果联系。

因果影响

使用图形因果模型的一个关键区别是我们需要构建一个有向图,其中我们定义一个起始节点到下一个节点。让我们通过运行以下代码进一步讨论这个问题:

import networkx as nx
causal_graph = nx.DiGraph([
    ('CreditScore', 'MultipleProduct'),
    ('Age', 'MultipleProduct'),
    ('MultipleProduct', 'Exited'),
    ('Balance', 'MultipleProduct'),
    ('EstimatedSalary', 'MultipleProduct'),
    ('Tenure', 'MultipleProduct'),
    ('Balance', 'Exited'),
    ('EstimatedSalary', 'Exited'),
    ('Tenure', 'Exited'),
]) 

要安装networkx包:

pip install networkx 

如您所见,我们正在使用networkx包的DiGraph类来创建一个有向图。您可以使用以下代码可视化这个有向图:

 nx.draw_networkx(causal_graph, arrows=True) 

输出将如下所示:

图片

图 3.15:有向图

如您可能注意到的,这是一个与我们之前章节中看到的类似的图,其中存在从AgeCreditScoreMultipleProduct的有向边。同样,也存在从BalanceEstimatedSalaryTenureMultipleProductExited的有向边。最后,存在一个从MultipleProductExited的有向边。总之,这是我们对不同变量可能相互产生因果效应的假设的视觉表示。

使用这个有向图,我们现在可以拟合一个图形因果模型,如下面的代码所示:

from dowhy import gcm
scm = gcm.StructuralCausalModel(causal_graph)
gcm.auto.assign_causal_mechanisms(scm, df)
gcm.fit(scm, df) 

在这里,我们使用dowhy包中的gcm模块,并在gcm模块中使用StructuralCausalModel类定义因果模型。然后,我们使用assign_causal_mechanisms函数将我们的数据集分配给图中的每个节点,最后,使用fit函数和结构因果模型以及数据集作为fit函数的输入来拟合图形因果模型。

现在我们已经学习了各种变量对结果的影响的因果效应,我们可以使用arrow_strength函数对这些学习到的关系进行量化,如下面的代码所示:

arrow_strengths = gcm.arrow_strength(scm, target_node='Exited') 

您可以使用以下代码进行可视化:

total = sum(arrow_strengths.values())
arrow_strengths_perc = {key: val/total*100 for key, val in arrow_strengths.items()}
gcm.util.plot(
    causal_graph,
    causal_strengths=arrow_strengths_perc,
    figure_size=[8, 5]
) 

从这段代码中,你可能注意到,在前两行代码中,我们将箭头强度归一化为总量的百分比。生成的图表应类似于以下:

图片

图 3.16:带有箭头强度的图表

如此图表所示,MultipleProductExited之间存在最强的因果关联,贡献率约为 45%,而Tenure作为第二个对客户流失影响最大的变量,贡献率约为 25%。这个具有对结果估计因果影响的定向图,为理解不同变量对结果的量化因果效应提供了极大的洞察力。

虽然箭头强度显示了直接链接到结果的影响,但它们并没有显示工具变量AgeCreditScore与结果变量Exited之间的间接关系。我们可以采取的一种计算和可视化所有因果因素对结果变量影响的方法是量化内在因果贡献,这些贡献将结果变量的方差归因于定向图中的所有上游节点。

我们可以使用intrinsic_causal_influence函数来量化内在因果贡献,如下面的代码所示:

influence = gcm.intrinsic_causal_influence(
    scm,
    target_node='Exited',
    num_samples_randomization=100
) 

在这里,我们使用 100 个随机样本进行评估,如你从num_samples_randomization参数输入中看到的。在我们可视化量化的内在因果影响之前,我们将尺度归一化,使它们加起来达到 100%,然后使用以下代码以条形图的形式可视化它们:

total = sum([val for key, val in influence.items() if key != "Exited"])
influence_perc = {key: val/total*100 for key, val in influence.items() if key != "Exited"}
xlabels = sorted(influence_perc.keys())
yvals = [influence_perc[x] for x in xlabels]
plt.bar(xlabels, yvals)
plt.xticks(rotation=45)
plt.grid()
plt.ylabel("Variance attribution in %")
plt.show() 

这段代码的输出应生成一个类似于以下条形图的图表:

图片

图 3.17:每个因素的方差分配条形图

如预期,变量MultipleProduct在所有变量中对结果变量的方差贡献最大。Balance作为第二个贡献最大的变量。变量AgeCreditScore似乎对结果变量Exited的方差贡献很小。

什么是 Shapley 值?

你可能注意到,在运行因果推理代码时会出现“Shapley 值”。简单来说,Shapley 值是单个变量对目标变量影响程度的估计。如果你想了解更多,我们建议你查看关于如何计算特征相关性的包文档:www.pywhy.org/dowhy/main/user_guide/causal_tasks/root_causing_and_explaining/feature_relevance.html

异常归因

到目前为止,我们已经看到了分析个体变量对结果变量整体因果效应的方法。然而,在有些情况下,我们可能想要深入了解哪些变量可能以何种方式做出了贡献。例如,在我们的数据集中,有人可能好奇某个客户的Balance金额是如何导致他们流失的,或者那个人的银行Tenure是如何影响他们的流失的。为了找出不同变量对个体客户流失的因果贡献,我们可以使用attribute_anomalies函数,如下所示:

attributions = gcm.attribute_anomalies(
    scm,
    target_node='Exited',
    anomaly_samples=df.loc[df["Exited"] == 1].iloc[0:1]
) 

在我们的例子中,我们选择了第一个流失的客户作为例子,如您从anomaly_samples参数的输入中看到的。我们可以使用以下代码在结果上可视化个体归因:

total = sum([abs(val[0]) for key, val in attributions.items() if key != "Exited"])
attributions_perc = {
    key: val[0]/total*100 for key, val in attributions.items() if key != "Exited"
}
xlabels = sorted(attributions_perc.keys())
yvals = [attributions_perc[x] for x in xlabels]
plt.bar(xlabels, yvals)
plt.xticks(rotation=45)
plt.grid()
plt.ylabel("Anomaly Attribution (%)")
plt.show() 

如此代码所示,我们正在对归因进行归一化,以便它们加起来达到 100%,然后使用条形图可视化个体归因。

生成的条形图将看起来如下:

图片

图 3.18:每个因素的异常归因条形图

在我们深入解释这个条形图之前,让我们首先看看我们选择的用于量化个体因果贡献的样本。看看以下代码,以便更仔细地查看一个个体样本:

 df.loc[df["Exited"] == 1].iloc[0][list(attributions_perc.keys())] 

这段代码的输出将如下所示:

图片图 3.19:选择的样本

如果我们将归因结果与这位客户的个人信息结合起来,我们可以分析出哪些因素是最具影响力的,最终导致了这位客户的流失。从这位客户的记录中我们可以看到,这个人只与银行有一个产品,这是导致这位客户流失的最主要因素。另一方面,Balance(余额)、EstimatedSalary(估计薪资)和Tenure(任期)实际上降低了客户流失的可能性,因为它们有负分。让我们再看另一个样本,如下所示:

 df.loc[df["Exited"] == 1].iloc[1][list(attributions_perc.keys())] 

这将产生如下输出:

图片

图 3.20:选择的样本

这位客户的因果贡献条形图看起来如下:

图片

图 3.21:客户因果贡献条形图

如您从第二个例子中看到的,与第一个例子相比,这位客户的余额更高,任期更长,并且与银行有超过一个产品。对于这位客户来说,更高的余额、更长的任期和更高的估计薪资对客户流失有积极影响,而这位客户拥有多个产品的事实降低了客户流失的可能性。

从这些例子中我们可以看到,因果分析和因果效应估计可以深入了解人们为何会从您的产品中流失。当与其他方法和 AI/ML 模型结合使用时,这种因果分析将带来可操作的见解,您可以在未来的营销活动中加以应用。

摘要

在本章中,我们深入了解了影响某些客户行为的因素。我们探讨了如何通过回归分析帮助我们理解各种因素与客户行为结果之间的方向性关系。以我们的车险营销数据集为例,我们看到了如何使用 Python 中的statsmodels包进行回归分析,揭示参与率营销活动背后的成功。我们还讨论了决策树如何帮助我们识别导致特定结果复杂交互。以银行营销数据集为例,并使用 Python 中的scikit-learn包,我们成功构建了一个揭示各种因素之间导致客户转换的潜在交互的决策树。最后,使用银行客户流失数据集和 Python 中的dowhy包,我们看到了因果分析如何对事件的根本原因和结果的方向性贡献带来深刻的洞察。

在下一章中,我们将探讨时间序列数据。在营销中,存在某些以特定方式重复出现的时序模式。我们将讨论如何将时间序列数据分解为总体趋势、季节性和随机噪声成分,以及如何利用通过时间序列分解识别出的趋势和季节性来开展营销活动,以及如何进行时间序列预测,这可以帮助你为未来可能发生的事件进行更好的规划和准备。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人交流,并与其他 5000 多名成员一起学习,请访问:

packt.link/genai

二维码

第四章:利用季节性和趋势进行战略规划

除非是一次性营销活动,例如开设临时商店或偶尔的产品促销活动,否则时间成分总会对营销结果产生影响。例如,销售雨伞的公司在雨季自然会看到显著的销售增长。不仅业务会受到季节性影响,而且业务中也可能存在一般趋势。例如,销售固定电话的业务随着人们越来越多地使用移动电话,其销售额将逐渐下降。

本章深入讨论了时间对营销活动的影响以及如何利用这些影响来制定最有效的营销策略。我们将介绍时间序列分析的基础,例如识别整体趋势和异常的一些常见方法,以及可视化时间序列数据。然后,我们将探讨如何将时间序列数据分解为趋势和季节性,这将告诉我们基于这些因素某些事件分解的贡献,以及这种分解如何帮助构建更有效的营销策略。我们将通过学习如何构建时间序列预测模型,以及理解这些预测如何被用于适当的营销活动来结束本章。我们将使用产品销售数据集作为例子,并讨论如何在 Python 中进行时间序列分析和建模。

更具体地说,我们将涵盖以下主题:

  • 时间序列分析基础

  • 时间序列数据中的趋势和季节性分解

  • 时间序列预测模型

时间序列分析基础

理解企业中的自然趋势对于营销人员、运营人员、销售人员以及大多数其他业务部门来说至关重要。如果没有很好地掌握业务及其产品是如何演变,以及客户是如何围绕你提供的服务和产品做出反应和行为的,很容易落后,导致收入增长不理想,甚至业务增长放缓至停止。

很容易发现企业是如何围绕商业周期的时间成分构建其产品策略的。在时尚行业,服装企业通常从冬季晚期到春季早期开始推广春夏季服装,而秋冬服装则从夏季早期到秋季早期进行宣传,因为客户倾向于在季节真正到来之前购物作为准备。然后,春夏季服装通常在夏季进行促销,通常从 7 月中旬开始,因为这些服装在季节真正到来时的需求较低。这说明了企业如何根据自然形成的客户需求优化不同季节的商业周期,以及他们如何最大化销售同时最小化过剩库存。

时间序列分析在尝试理解企业中的这些自然时间成分时非常有用。简而言之,时间序列分析是一种分析随时间变化的一系列数据点及其如何影响数据值变化的方法。在本章中,我们将使用一个历史销售数据集作为例子来讨论如何进行时间序列分析和建模。

源代码和数据:

github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/tree/main/ch.4

数据来源: community.tableau.com/s/question/0D54T00000CWeX8SAL/sample-superstore-sales-excelxls

基本时间序列趋势

让我们使用示例数据集查看整体月度产品销售额。我们首先需要将此数据加载到 DataFrame 中,并按月汇总数据。请看以下代码(注意,这里使用的 CSV 文件包含在本书的 GitHub 仓库中):

df = pd.read_csv("./data.csv", encoding="latin")
df["OrderDate"] = pd.to_datetime(df["OrderDate"])
ts_df = df[[
    "OrderID", "OrderDate", "Quantity", "Sales", "Category"
]].copy().set_index("OrderDate")
df.columns = [x.replace(" ", "") for x in df.columns] 

在这里,我们将数据加载到pandas DataFrame 中。与之前章节不同的是,编码参数。这个数据集包含非 UTF 字符,所以我们使用latin编码来加载数据。然后,我们将OrderDate列中的值转换为日期时间类型,并将关键列复制到一个新的DataFramets_df。最后,为了便于使用,我们通过将所有空格替换为空字符串来删除列名中的空格。

将数据重新采样并按月频率汇总的一种方法如下:

monthly_unique_orders = ts_df["OrderID"].resample("MS").nunique()
monthly_unique_order_changes = (
    monthly_unique_orders - monthly_unique_orders.shift()
)/monthly_unique_orders.shift()*100 

我们在pandas中使用resample函数,并带有MS参数,这将把数据重新采样到月度时间框架,然后使用nunique函数计算唯一的OrderID值的数量,这将给我们提供每月独立订单计数数据。然后我们通过从当前月的值中减去上个月的值并除以上个月的值来计算月度百分比变化。shift函数将数据移动一个周期,从而给出上个月的值。

我们可以将同样的方法应用于计算每月订单数量和销售额,如下所示:

monthly_quantities = ts_df["Quantity"].resample("MS").sum()
monthly_quantities_changes = (
    monthly_quantities - monthly_quantities.shift()
)/monthly_quantities.shift()*100
monthly_sales = ts_df["Sales"].resample("MS").sum()
monthly_sales_changes = (
    monthly_sales - monthly_sales.shift()
)/monthly_sales.shift()*100 

可视化时间序列数据最简单的方法是使用折线图。请看以下代码:

fig, axes = plt.subplots(
nrows=3, ncols=1, figsize=(10, 10), sharex=True
)
monthly_unique_orders.plot(
    ax=axes[0], grid=True
)
monthly_unique_order_changes.plot(
    ax=axes[0], secondary_y=True, color="silver", linestyle="dashed"
)
axes[0].set_title("Monthly Unique Orders")
axes[0].set_ylabel("# Unique Orders")
axes[0].right_ax.set_ylabel("Month over Month Change (%)")
monthly_quantities.plot(
    ax=axes[1], grid=True
)
monthly_quantities_changes.plot(
    ax=axes[1], secondary_y=True, color="silver", linestyle="dashed"
)
axes[1].set_title("Monthly Order Quantities")
axes[1].set_ylabel("Order Quantity")
axes[1].right_ax.set_ylabel("Month over Month Change (%)")
monthly_sales.plot(
    ax=axes[2], grid=True
)
monthly_sales_changes.plot(
    ax=axes[2], secondary_y=True, color="silver", linestyle="dashed"
)
axes[2].set_title("Monthly Sales")
axes[2].set_ylabel("Sales")
axes[2].right_ax.set_ylabel("Month over Month Change (%)")
plt.show() 

在这段代码中,我们创建了三个折线图。第一个是每月独立订单数,第二个是每月订单数量,最后一个是每月销售额。此代码生成了以下图表:

图 4.1:月度时间序列数据的可视化

让我们更深入地研究这些图表。如您所注意到的,所有三个图表都显示出明显的重复模式。它们在三月、九月和十一月到十二月期间达到峰值。这可以通过查看实线(表示整体月度值)和虚线(表示月度值的变化)来确认。这表明该业务具有周期性,相应月份的销售量较大。营销人员应通过在高峰季节前稍作营销来捕捉最大的销售潜力。此外,营销人员可以在显示较弱销售量的月份提供折扣,以管理库存并促进淡季销售。

如您所见,可视化时间序列数据本身就能提供关于业务周期以及如何为高峰和低谷季节做准备的深刻见解。您可能还会注意到,这些图表整体呈上升趋势,这意味着值通常每年都在上升。当我们查看时间序列图表中的移动平均值时,这种整体趋势更容易识别。

您不仅可以按月频率采样时间序列数据,还可以按日、周或年频率采样。您可以根据许多选项进行重采样,所以尝试不同的重采样频率,看看您能观察到哪些其他趋势!

参考https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#resampling

移动平均值

移动平均值,即特定时间段的平均值,擅长平滑尖峰或噪声的时间序列数据,并显示整体趋势。它们是回答诸如“我们的产品销售是整体上升还是下降趋势?”等问题的重要工具。在我们的示例数据中,我们可以执行以下操作来计算移动平均值:

m6_ma_sales = monthly_sales.rolling(6).mean()
m12_ma_sales = monthly_sales.rolling(12).mean() 

如您从这段代码中看到的那样,您可以在pandas中使用rolling函数并应用mean函数来获取月度销售的移动平均值。rolling函数的输入定义了您想要平均值的周期数。在这里,我们计算了月度销售的 6 周期移动平均值和 12 周期移动平均值。

您可以使用以下代码来可视化移动平均值:

ax = monthly_sales["2015-01-01":].plot(figsize=(10,5))
m6_ma_sales["2015-01-01":].plot(ax=ax, grid=True)
m12_ma_sales["2015-01-01":].plot(ax=ax, grid=True)
ax.set_ylabel("Sales Amount")
ax.set_xlabel("Order Date")
ax.set_title("Monthly Sales Amount")
plt.legend(["Monthly Sales", "6mo Moving Average", "12mo Moving Average"])
plt.show() 

生成的图表将如下所示:

图片

图 4.2:包含 6 个月和 12 个月移动平均值的月度销售

如预期的那样,12 个月移动平均值图表比 6 个月移动平均值图表更平滑。然而,6 个月移动平均值图表比 12 个月移动平均值图表更敏感或更接近于捕捉月度销售图表中的趋势,同时仍然平滑了月度销售图表中的尖峰。如您所注意到的,移动平均值图表显示了月度销售数据的一般上升趋势,这在仅查看月度图表时可能更难注意到。

移动平均还可以帮助您了解某些月份的峰值是否在正常范围内或是不正常。看看以下代码:

m6_ma_sales_std = monthly_sales.rolling(6).std()
ax = monthly_sales["2015-01-01":].plot(figsize=(10,5))
m6_ma_sales["2015-01-01":].plot(ax=ax, grid=True)
(m6_ma_sales["2015-01-01":] + m6_ma_sales_std["2015-01-01":]).plot(
    ax=ax, grid=True, linestyle="dashed", color="silver", linewidth=1
)
(m6_ma_sales["2015-01-01":] - m6_ma_sales_std["2015-01-01":]).plot(
    ax=ax, grid=True, linestyle="dashed", color="silver", linewidth=1
)
ax.set_ylabel("Sales Amount")
ax.set_xlabel("Order Date")
ax.set_title("Monthly Sales Amount")
dates = m6_ma_sales["2015-01-01":].index
plt.fill_between(
    dates,
    m6_ma_sales["2015-01-01":] + m6_ma_sales_std["2015-01-01":],
    m6_ma_sales["2015-01-01":] - m6_ma_sales_std["2015-01-01":],
    facecolor="grey",
    alpha=0.2,
)
plt.legend(["Monthly Sales", "6mo Moving Average (MA)", "6mo MA Upper", "6mo MA Lower"])
plt.show() 

此代码通过使用std函数计算 6 个月期间的移动标准差(与移动平均相同,但测量过去一定时间内的标准差)并使用带有上下边界的带状图可视化数据,其中上边界是 6 个月移动平均线上一个标准差,下边界是 6 个月移动平均线下一个标准差。图表将如下所示:

图片

图 4.3:带有 6 个月移动平均和 1-std 边界的月销售

此图表显示了月销售量与移动平均线和一个标准差边界相比的情况。根据您的偏好,您可能希望将一个标准差内的值视为正常,或将两个标准差内的值视为正常。使用此示例,如果我们假设一个标准差内的值为正常值,我们可以看到二月、九月、十一月和十二月是不正常的月份,超出了定义的边界,其中二月份的销售量显著低于预期,而九月、十一月和十二月销售量显著高于预期。

理解企业的整体趋势与理解企业内的季节性或周期同样重要。根据一般趋势,您可以更好地了解是否比去年有更高的或更低的销售和营销潜力。如果整体趋势是上升趋势,您应该预计某个月的需求可能比去年同月的需求更高。此外,对超出或低于正常范围的销售有良好的掌握,例如在黑色星期五或圣诞节期间,可以帮助构建有效的营销策略来克服短缺和营销潜力的过剩。移动平均和移动标准差是识别整体趋势和正常预期范围的便捷工具。

自相关

另一个有用的基本时间序列分析是自相关。自相关表示与自身滞后版本的关联。以下将通过一个例子来讨论。看看以下代码:

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
plot_acf(
    monthly_sales, lags=25
)
plt.show() 

在这里,我们使用statsmodels包,您可以使用pip install statsmodels命令安装它。plot_acf函数将为您绘制给定序列的自相关图。在这里,我们绘制了过去 25 期月销售的自相关图。图表应该如下所示:

图片

图 4.4:月销售数据的自相关图

让我们更仔细地分析这张图表。x 轴代表滞后阶段数,y 轴是关联程度。这张图表显示了当前时间点与一个周期前、两个周期前,以及直到 25 个周期前的关联。在这里,在月度销售数据中,我们有三滞后阶段的相对较强的正相关,与第四和第五个周期有轻微的负相关。这表明如果过去 3 个月有销售增加,那么本月销售很可能会增加,反之亦然。这也意味着观察 4-5 个月前的销售增加很可能会导致本月销售减少。正如这个例子所示,自相关是观察不同时间段如何影响当前时间段结果的一种方法。在本章的“时间序列预测模型”部分,我们将尝试自回归积分移动平均ARIMA)模型,其中它的自回归部分使用这些滞后变量进行时间序列预测建模。

偏自相关,与自相关相比,忽略了中间滞后阶段的影响。与自相关不同,偏自相关测量的是每个滞后阶段的直接影响和关联。可以使用plot_pacf函数来绘制偏自相关,如下面的代码所示:

plot_pacf(
    monthly_sales, lags=15
)
plt.show() 

在这里,我们绘制了直到周期 15 的偏自相关图。图表应该如下所示:

图 4.5:月度销售数据的偏自相关图

如您所见,与之前的自回归图相比,每个滞后阶段的关联程度不同。这是因为偏自回归测量的是每个滞后阶段的直接关联,而自回归包括中间滞后阶段的影响。在这个例子中,我们可以看到在滞后 1 处存在显著的积极偏自相关,在滞后 4 处存在消极偏自相关。这表明上个月的销售增加或减少很可能会分别导致本月销售的增加和减少,而四个月前的销售增加很可能会导致本月销售的减少,排除中间月份销售结果的影响。直观地说,这些可能是自然商业周期的影响,如果你的商业周期是季度性的,那么你很可能会在滞后 3-4 处看到负自相关,而对于半年周期,你很可能会在滞后 6-7 处看到负自相关。

产品趋势

我们之前讨论的所有分析和可视化都可以应用于更细粒度的水平。我们只看了整体月度销售时间序列数据。然而,我们可以按不同的产品来剖析,发现每个产品可能具有不同的整体趋势和需求周期性。我们还可以观察不同州或地理区域如何显示出与整体销售趋势可能不同的趋势和商业周期。

为了说明目的,我们将按不同产品类别来剖析趋势。请看以下代码:

furniture_monthly_sales = ts_df.loc[
    ts_df["Category"] == "Furniture"
]["Sales"].resample("MS").sum()
office_monthly_sales = ts_df.loc[
    ts_df["Category"] == "Office Supplies"
]["Sales"].resample("MS").sum()
tech_monthly_sales = ts_df.loc[
    ts_df["Category"] == "Technology"
]["Sales"].resample("MS").sum()
fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(10, 10), sharex=True)
furniture_monthly_sales.plot(ax=axes[0], grid=True)
axes[0].set_title("Monthly Furniture Sales")
office_monthly_sales.plot(ax=axes[1], grid=True)
axes[1].set_title("Monthly Office Supplies Sales")
tech_monthly_sales.plot(ax=axes[2], grid=True)
axes[2].set_title("Monthly Technology Sales")
plt.show() 

首先,我们为每个产品类别创建时间序列记录。主要来说,我们创建了三个月度销售时间序列,即“家具”、“办公用品”和“技术”,然后并排展示这些图表。生成的图表如下:

图 4.6:家具、办公用品和技术产品月度销售数据的可视化

这三个产品线之间的整体趋势相似,销售在九月和十一/十二月达到峰值。然而,三月销售峰值在技术销售中最为突出,家具销售从 2017 年 1 月开始快速增长。此外,办公用品销售似乎比其他两个产品线更频繁地达到峰值;它们似乎每季度达到一次峰值,这可能是由于季度办公用品补货的结果。正如这些结果所示,不同的产品线往往在时间上表现出略有不同的行为。

尝试深入了解细分以及时间序列数据如何因不同的细分而异。尝试剖析不同的变量,如地区、城市和子类别!

趋势和季节性分解

我们已经看到,从时间序列数据中显示了自然趋势和周期。通过可视化图表和利用移动平均线,我们能够识别出整体趋势和季节性。然而,还有更多统计方法可以将时间序列数据分解为趋势和季节性成分。主要来说,有两种主要的时间序列分解方法:

  • 加法分解:正如其名所示,加法分解的时间序列分解方法将数据分解为趋势、季节性和误差(这是不能由整体趋势和季节性解释的成分),这样当它们相加时,可以重建原始时间序列数据:

Y[t] = Trend[t] + Seasonality[t] + Error[t]

  • 乘法分解:另一方面,乘法分解的时间序列分解方法将数据分解为趋势、季节性和误差(这是不能由整体趋势和季节性解释的成分),当它们相乘时,可以重建原始时间序列数据。方程如下:

Y[t] = Trend[t] * Seasonality[t] * Error[t]

现在我们更详细地看看这些方法。

加法时间序列分解

便利的是,statsmodels包提供了一个易于进行趋势和季节性分解的函数。作为一个例子,我们将分解月度家具销售数据,看看它有什么趋势和季节性。请看以下代码:

import statsmodels.api as sm
decomposition = sm.tsa.seasonal_decompose(
    furniture_monthly_sales, model='additive'
)
fig = decomposition.plot()
plt.show() 

如此代码所示,我们正在使用seasonal_decompose函数对月度家具销售数据进行时间序列分解,该数据存储在名为furniture_monthly_sales的变量中。另一个需要注意的事项是seasonal_decompose函数的model参数,通过它可以决定是否使用加法或乘法方法。

可以通过seasonal_decompose函数输出的plot函数轻松可视化此时间序列分解。图表应类似于以下内容:

图片

图 4.7:月度家具销售数据的时间序列分解图

顶部图表显示了原始时间序列数据,在我们的案例中是月度家具数据。顶部第二张图表显示了分解的趋势。正如预期的那样,存在一个明显的上升趋势,销售额逐年增长。第三张图表是分解的季节性图表。在这里,它显示了 9 月、11 月和 12 月销售量的明显峰值,以及 2 月销售量的下降。最后,底部图表显示了分解后的残差或误差项。根据前一小节中讨论的方程,这三张底部图表对应于原始时间序列数据的每个分解成分。

当适当分解时,误差项应该是平稳的,这意味着残差中不应有依赖于时间的明显模式。在我们的例子中,残差在时间上没有明显的模式,因此分解序列似乎是合理的。我们可以通过基于趋势和季节性分解重构时间序列数据以及原始序列与重构序列之间的差距来检验分解序列捕捉原始序列的效果。请看以下代码:

reconstructed_wo_resid = decomposition.trend + decomposition.seasonal
corr = np.corrcoef(
    list(furniture_monthly_sales[dates]),
    list(reconstructed_wo_resid[dates])
)[0,1]
dist = np.sqrt(
    np.square(
        furniture_monthly_sales[dates] - reconstructed_wo_resid[dates]
    ).sum()
)
rmse = np.sqrt(
    np.square(
        furniture_monthly_sales[dates] - reconstructed_wo_resid[dates]
    ).mean()
) 

第一行显示了如何使用分解的趋势和季节性来重构时间序列数据。由于在本例中我们使用了加法方法进行时间序列分解,我们只需简单地将趋势和季节性成分相加即可得到重构序列。

我们使用三个指标来衡量原始序列与重构序列之间的相似性或差异性:

  • 相关性:使用numpy包的corrcoef函数,此指标衡量原始序列与重构序列之间的相似性。

  • 欧几里得距离:这是平方误差和的平方根。此指标衡量原始序列与重构序列之间有多大差距。

  • 均方根误差RMSE):这是平方误差均值的平方根。此指标衡量原始序列和重建序列之间的误差程度。

可以使用以下代码:

print(f"Correlation: {corr:.02f}\nEuclidean Distance: {dist:.02f}\nRMSE: {rmse:.02f}") 

结果应如下所示:

Correlation: 0.95
Euclidean Distance: 15995.62
RMSE: 2665.94 

你也可以使用以下代码直观地比较重建序列与原始序列:

dates = reconstructed_wo_resid.dropna().index
ax = furniture_monthly_sales[dates].plot(figsize=(10,5))
reconstructed_wo_resid[dates].plot(ax=ax, grid=True)
decomposition.trend[dates].plot(ax=ax, grid=True)
ax.set_ylabel("Sales Amount")
ax.set_xlabel("Order Date")
ax.set_title("Monthly Furniture Sales Amount")
plt.legend(["Monthly Furniture Sales", "Reconstructed (Additive)", "Trend Decomposed"])
plt.show() 

图表应如下所示:

图 4.8:家具月销售数据及其分解趋势和重建序列

如您从这张图表中可以看到,并且正如之前指标所预期的那样,重建序列并没有捕捉到原始序列的 100%。然而,它们紧密地移动在一起,并且重建序列与原始序列具有高度相似性。

乘法时间序列分解

我们将比较加法方法的成果与乘法方法的成果,以查看哪一个更接近原始时间序列。正如你可能已经猜到的,你可以将seasonal_decompose函数的model参数替换为multiplicative,如下所示:

decomposition = sm.tsa.seasonal_decompose(
    furniture_monthly_sales, model='multiplicative'
)
fig = decomposition.plot()
plt.show() 

生成的图表应如下所示:

图 4.9:使用乘法方法对家具月销售数据进行的时间序列分解图

这应该与加法方法的图表非常相似。然而,有两个关键的不同之处值得注意:

  • 季节图的 y 轴,即从底部数的第二个图表,范围从0到大约2.0,而加法图的季节性成分的 y 轴范围从大约-10,000 到 35,000。

  • 同样,残差图的 y 轴,即最底部的图表,范围从0到大约1.5

如您所猜到的,这是因为我们在本例中使用了乘法方法,而不是加法方法。为了从分解的趋势和季节性成分中重建原始序列,我们需要将这两个成分相乘,如下所示:

reconstructed_wo_resid = decomposition.trend * decomposition.seasonal 

与之前类似,我们可以使用以下代码,通过我们之前使用的三个指标(相关系数、欧几里得距离和 RMSE)来衡量从乘法方法重建的序列与原始序列之间的相似度:

corr = np.corrcoef(
    list(furniture_monthly_sales[dates]),
    list(reconstructed_wo_resid[dates])
)[0,1]
dist = np.sqrt(
    np.square(
        furniture_monthly_sales[dates] - reconstructed_wo_resid[dates]
    ).sum()
)
rmse = np.sqrt(
    np.square(
        furniture_monthly_sales[dates] - reconstructed_wo_resid[dates]
    ).mean()
) 

可以使用以下代码查看相似度指标:

print(f"Correlation: {corr:.02f}\nEuclidean Distance: {dist:.02f}\nRMSE: {rmse:.02f}") 

这给我们以下结果:

Correlation: 0.95
Euclidean Distance: 15307.16
RMSE: 2551.19 

如果你将这些结果与使用加法方法的前期结果进行比较,你会注意到,使用乘法方法时,欧几里得距离和 RMSE 要低得多,而相关度指标相似。乘法方法的欧几里得距离比加法方法低约700,乘法方法的 RMSE 比加法方法低约100。这表明,在这种情况下,乘法分解方法可能比加法方法更好地捕捉原始时间序列数据。

同样,我们可以使用以下代码可视化检查乘法方法的重建结果:

dates = reconstructed_wo_resid.dropna().index
ax = furniture_monthly_sales[dates].plot(figsize=(10,5))
reconstructed_wo_resid[dates].plot(ax=ax, grid=True)
decomposition.trend[dates].plot(ax=ax, grid=True)
ax.set_ylabel("Sales Amount")
ax.set_xlabel("Order Date")
ax.set_title("Monthly Furniture Sales Amount")
plt.legend(["Monthly Furniture Sales", "Reconstructed (Additive)", "Trend Decomposed"])
plt.show() 

生成的图表应如下所示:

图片

图 4.10:使用乘法方法分解趋势和重建系列后的月度家具销售图

在本节中,我们看到了如何使用statsmodels包统计地分解时间序列数据。如前所述,深入了解一般趋势以及季节性趋势对于制定产品和目标营销策略至关重要,因为营销策略与这些趋势的匹配以及提前于预期趋势采取行动的时间决定了营销活动的成功与失败。你不想在趋势中太晚,但也不想在趋势中太早。这种时间序列分解技术应该是一个便于策略规划和时间营销活动的实用工具。

时间序列预测模型

整体趋势和季节性为高效的及时营销活动提供了宝贵的见解。我们讨论了时间序列分解如何帮助营销人员及时推出促销活动,以便在需求预期上升时捕捉最大的销售和营销潜力,以及在需求预期下降时通过季节性销售促销或专注于具有不同峰值和谷值周期的产品来最小化下降和过剩库存。

我们可以进一步利用机器学习ML)和人工智能AI)来构建时间序列预测模型。这些 AI/ML 模型的未来预测不仅对营销至关重要,而且对销售、运营、财务、供应链、采购等多个业务单元也起着关键作用。通过利用时间序列预测,营销人员可以以多种方式优化他们的营销目标:

  • 如果营销目标是推广一个新产品,那么时间序列预测模型输出可以告知营销人员何时开始推广最为合适,这基于对类似产品类别预期需求上升或下降的预测。

  • 如果营销目标是促进季节性销售的增长,那么可以构建时序模型来预测可能导致最高销售额的季节性促销类型。

  • 如果营销目标是清理过剩库存,那么可以预测不同地区或人口统计数据的不同需求的时序模型可以帮助营销人员针对特定地区或人口统计数据进行最大效率的过剩库存减少。

有许多时间序列预测算法可以用来构建预测模型。从传统的统计时间序列模型到更现代的基于深度学习的时间序列模型,有各种算法可以用来预测时间序列数据。在本节中,我们将实验两种最常用的时序模型:ARIMA 和 Prophet。

ARIMA

ARIMA模型是一种统计模型,通常用于根据历史值预测未来的时间序列数据。ARIMA 是我们讨论过的回归分析的一种形式,它在第三章中有所提及,但 ARIMA 模型由以下三个关键组成部分构成:

  • 自回归:ARIMA 模型中的AR部分

与我们讨论的自相关类似,自回归是对其滞后变量的回归,其中每个滞后变量都是预测模型的一个特征。

  • 差分:ARIMA 模型中的I部分

这是指值与其前一个值之间的差异,以实现平稳性,正如之前讨论的,这意味着误差不依赖于时间成分。

  • 移动平均:ARIMA 模型中的MA部分

如前所述,移动平均是在滚动窗口上的平均,ARIMA 模型对这些移动平均进行回归。

ARIMA 模型中的这三个组成部分——自回归AR)、差分I)和移动平均MA)——各自有自己的参数。通常,这些参数用pdq表示,定义如下:

  • p:模型中 AR 部分的滞后期数

  • d:I 部分的差分次数

  • q:MA 部分的移动平均滚动窗口

训练 ARIMA 模型

Python 中的statsmodels包有一个模块,使我们能够轻松构建 ARIMA 模型。请看以下代码:

from statsmodels.tsa.arima.model import ARIMA
model = ARIMA(furniture_monthly_sales[:"2017-06-01"], order=(12,1,3))
model_fit = model.fit() 
ARIMA class to build an ARIMA model in Python. For the inputs for the model, we are giving the monthly furniture sales time-series data, which is the variable furniture_monthly_sales in our case, and the parameters that we have discussed previously. As an example, we are using 12 for the *p* or AR component, 1 for the *d* or I component, and 3 for the *q* or MA component. 

我们建议您在用 ARIMA 实际构建预测模型时尝试各种组合,以找到最优的参数集。在这里,我们正在训练我们的 ARIMA 模型,直到 2017 年 6 月,并将测试 2017 年 7 月至 12 月的预测。

使用以下命令,我们可以查看训练好的模型结果:

print(model_fit.summary()) 

模型总结如下:

图 4.11:ARIMA 模型拟合的总结

在此模型总结输出中需要注意的一些关键事项如下:

  • ar:这些是 ARIMA 模型中的 AR 成分。由于我们为 AR 成分给出了 12,因此有 12 个滞后变量是这个模型回归的,每个coef显示了每个滞后变量与目标变量的系数。

  • ma:这些是 ARIMA 模型中的 MA 成分。在我们的例子中,我们为 MA 成分给出了 3,因此有三个变量是模型回归的,每个coef显示了每个 MA 变量与目标变量的系数。

  • AIC/BIC:我们不会过多地详细介绍这些指标,但赤池信息量准则AIC)和贝叶斯信息准则BIC)是可以用来评估模型拟合度并比较不同模型的指标。值越低,模型的拟合度越好,且没有过度拟合。

要找到一组最优的参数,您将不得不运行多个具有不同(p, q, d)参数集的模拟。或者,您也可以使用像pmdarima这样的包来自动发现 ARIMA 模型的最优参数。

参考:alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.auto_arima.html

ARIMA 模型诊断

statsmodels包提供了一个方便的方式来诊断训练好的 ARIMA 模型。ARIMA模型的plot_diagnostics函数可以用来可视化关键诊断图,如下面的代码所示:

model_fit.plot_diagnostics(figsize=(12, 6))
plt.show() 

图表应如下所示:

图 4.12:ARIMA 模型诊断图

如此图表所示,此诊断图中包含四个组件。让我们深入探讨每个组件:

  • 标准化残差随时间变化(左上角图表):此图表显示了随时间变化的残差或误差。对于一个完美的模型,我们期望它是完全随机的,没有任何明显的模式。然而,在我们的案例中,仍然有一些微小的季节性模式是可观察到的。

  • 直方图和标准化残差的估计密度(右上角图表):此图表显示了标准化残差的分布。对于一个完美的模型,我们期望它显示一个均值为 0、标准差为 1 的高斯或正态曲线。我们的模型非常接近理论上的正态曲线,这表明残差几乎呈正态分布。

  • 正态 Q-Q 图(左下角图表):此图表显示了理论分位数分布与拟合模型的实际分位数分布。它表明,当点紧密地与直线对齐时,残差是正态的。在我们的案例中,它并不完美,但与直线有些接近,这表明残差几乎呈正态分布。

  • 自相关图(右下角图表):此图表显示了滞后期间残差项的自相关。相关值越小,残差越随机。我们的示例显示了最小的相关性,这表明残差彼此之间没有相关性。

总结来说,这些诊断图告诉我们,在我们的情况下,残差通常是正态分布的。

使用 ARIMA 模型进行预测

现在,终于到了使用我们训练好的 ARIMA 模型进行预测的时候了。首先看看以下代码:

pred = model_fit.get_forecast(steps=6)
pred_ci = pred.conf_int() 

statsmodels包的ARIMA模型提供了一个名为get_forecast的函数。steps参数用于定义您希望预测的未来步骤数。它还提供了一个名为conf_int的函数,它给出了预测的置信带。

我们可以用以下代码轻松地绘制预测结果:

ax = furniture_monthly_sales["2015-01-01":].plot(figsize=(15,5))
pred.predicted_mean.plot(
    ax=ax, grid=True
)
ax.fill_between(
    pred_ci.index,
    pred_ci.iloc[:, 0],
    pred_ci.iloc[:, 1],
    color='cornflowerblue',
    alpha=.3
)
ax.set_xlabel('Date')
ax.set_ylabel('Furniture Sales')
plt.legend(["Observed", "Forecasted"])
plt.show() 

当您运行此代码时,您应该得到一个类似于以下图表的图表:

图 4.13:ARIMA 模型预测图

此图表显示了之前的月度家具销售数据以及预测和置信带或区间。如您所记得,我们使用截至 2017 年 6 月的数据训练了模型,并对 2017 年 7 月至 12 月的六个步骤进行了预测,即从 7 月到 12 月。

如您从这些预测中可以看到,ARIMA 模型的预测结果与实际观察到的数据方向上很好地吻合。此外,实际值落在置信带内,这表明基于置信区间的预测使用是可靠的。衡量时间序列预测准确率常用的指标之一是 RMSE,以下代码展示了如何使用:

rmse = np.sqrt(
    np.square(furniture_monthly_sales["2017-07-01":] - pred.predicted_mean).mean()
)
rmse 
5913.227463714012 

这给出了结果5913.227463714012

在这里,我们对未来 6 个月的预测的 RMSE 大约是 5913。我们将在接下来的章节中与其他时间序列预测模型的值进行比较。

除了 RMSE 之外,还有许多其他指标可以用来衡量时间序列模型的表现。一些其他常用的指标包括平均绝对误差MAE)、平均绝对百分比误差MAPE)和平均绝对缩放误差MASE)。尝试一些其他的回归指标,看看它们之间有何不同!

Prophet 时间序列建模

Prophet是 Meta(前身为 Facebook)的一个开源包,用于时间序列预测。与刚刚讨论的 ARIMA 模型类似,Prophet 模型也考虑了趋势和季节性,但具有更多的灵活性,并且可以调整更多参数来微调时间序列模型,还包括假日效应。因此,Prophet 模型主要包含以下三个部分:

  • 增长(或趋势):Prophet 模型整体的增长或趋势。对于时间序列数据中的增长因子,您可以做出以下三个假设:

    • 线性:这是 Prophet 的默认假设,当整体趋势预期为线性时使用。

    • 对数:当您的时序数据趋势中存在上限或下限时,应使用此选项。

    • 平稳:这是指您假设随着时间的推移没有增长。

  • 季节性:默认情况下,这设置为auto,但根据您在时间序列数据中的观察,您可以将其设置为模型每日、每周或年度季节性。

  • 节假日:Prophet 的一个关键区别在于其对节假日的理解。由于节假日对时间序列结果有重大影响,因此能够使用 Prophet 对时间序列数据中的节假日效应进行建模是有益的。

在本节中,我们将使用 Prophet 对月度家具销售进行建模实验。

关于您可以使用 Prophet 微调的参数的更详细信息,我们建议您访问他们的官方网站(facebook.github.io/prophet/docs/quick_start.html)或他们的 GitHub 页面(github.com/facebook/prophet/blob/main/python/prophet/forecaster.py)。

训练 Prophet 模型

为了训练一个 Prophet 模型,请确保您已经安装了该包。您可以使用以下命令来安装包:

pip install prophet 

训练 Prophet 模型的第一个步骤是准备它期望的数据。请看以下代码:

from prophet import Prophet
monthly_furniture_sales_df = pd.DataFrame(
    furniture_monthly_sales[:"2016-12-01"]
).reset_index()
monthly_furniture_sales_df.columns = ["ds", "y"] 

如您从这段代码中可以看到,我们使用截至 2016 年 12 月的月度家具数据作为我们的训练集。对于 Prophet 模型对训练集的要求是列dsy,其中ds用于给定记录的日期和时间,而y用于时间序列值。

使用此训练集,我们可以轻松地使用以下代码训练一个 Prophet 模型:

model = Prophet()
model.fit(monthly_furniture_sales_df) 

在这里,我们使用Prophet类和默认参数初始化模型,这实际上指示模型假设线性增长趋势和没有节假日效应的季节性。然后,我们使用fit函数和之前准备好的训练集 DataFrame 来训练模型。

使用 Prophet 模型进行预测

现在我们已经训练了一个 Prophet 模型,是时候进行一些预测了。为了使 Prophet 模型能够进行预测,我们需要做的一件事是生成一系列它应该预测的日期。Prophet 提供了一个方便的函数来完成这项工作,如下所示:

dates = model.make_future_dataframe(periods=24, freq='MS') 

在这里,我们使用make_future_dataframe函数。periods参数定义了我们希望预测多少未来的日期或周期,而freq参数定义了每个未来日期或周期的频率,我们将它定义为每月,以'MS'作为参数的输入。

新创建的变量现在应包含从 2014 年 1 月到 2018 年 12 月的日期。如您所记得,我们已将截至 2016 年 12 月为止的月度序列用作我们的训练集,因此从 2017 年 1 月到 2018 年 12 月基本上是我们想要进行预测的样本外预测。

您可以使用以下代码生成训练模型的预测:

forecast = model.predict(dates) 

predict函数生成一个 DataFrame,名为forecast,其中包含每个时期的预测数据,例如预测值、上下限、模型趋势等。forecast DataFrame 中与我们最相关的几个关键字段如下:

图片

图 14.14:Prophet 模型预测结果

yhat列是给定时期的预测值,yhat_loweryhat_upper是预测置信区间的下限和上限。

我们可以使用以下代码轻松地可视化这些预测和预测置信区间:

fig = model.plot(forecast, uncertainty=True)
ax = fig.axes[0]
outsample_dates = furniture_monthly_sales["2017-01-01":].index
ax.plot(
    outsample_dates,
    furniture_monthly_sales.loc[outsample_dates],
    "k.",
    marker="x",
    color="red"
)
plt.legend([
    "actual (in-sample)", "predicted", "pred band", "actual (out-sample)"
])
plt.show() 

让我们仔细看看这段代码。Prophet 模型对象有一个plot函数,它生成一个包含预测值的折线图、预测区间为面积图、实际值为散点图的图表。然后,我们添加样本外数据点作为带有标记x的散点图。此图表应如下所示:

图片

图 4.15:Prophet 模型预测图

与我们使用 ARIMA 模型所做的一样,我们也可以使用以下代码查看 Prophet 模型预测的 RMSE:

rmse = np.sqrt(
    np.square(
        forecast.loc[
            forecast["ds"].isin(outsample_dates)
        ]["yhat"].to_numpy() - furniture_monthly_sales.loc[outsample_dates].to_numpy()
    ).mean()
)
print(f"Out-Sample RMSE: {rmse:.02f}") 

结果如下:

Out-Sample RMSE: 4295.65 

与 ARIMA 模型的 RMSE 大约为 5913 相比,RMSE 约为 4295 的 Prophet 模型似乎有更接近实际的预测。

最后,Prophet 还建模趋势和季节性分解,并提供了一种简单的方式来可视化它们,如下面的代码所示:

model.plot_components(forecast) 

生成的图表应如下所示:

图片

图 4.16:Prophet 模型时间序列分解图

与我们之前将时间序列数据分解为趋势和季节性时所见到的类似,Prophet 模型也识别出整体上升趋势、12 月份的峰值和 1 月份的下降。到目前为止,我们已经看到,Prophet 提供了方便且可靠的工具来建模时间序列数据。

基于这些知识,我们将在下一节探讨使用深度学习方法建模时间序列数据的另一种方式。

其他时间序列模型

在本章中,我们讨论了使用 ARIMA 和 Prophet 进行时间序列建模。然而,还有各种其他算法和模型可以用来建模时间序列数据。时间序列建模主要有以下三种方法:

  1. 统计模型:用于建模时间序列数据的统计方法已经存在了几十年。ARIMA 模型是最常用的统计模型之一,于 20 世纪 70 年代开发,至今仍在使用。以下是一些常用的其他统计模型:

    • 指数平滑法:这是最古老的时间序列预测方法之一,它对最近的观测值给予更大的权重,用于平均时间序列数据点。

    • 广义自回归条件异方差(GARCH):在金融领域常用的模型,用于建模误差项的方差,这些误差项依赖于时间,如随时间增加或减少波动性或方差。

    • 季节性 ARIMA(SARIMA):ARIMA 模型的扩展,在 ARIMA 组件之上加入了季节性成分。

  2. 机器学习(ML)模型:尽管不如其他统计模型和深度学习模型常用,ML 模型仍被用于时间序列预测和快速检查时间序列的可预测性。ML 模型相对于统计模型的优势在于,在构建预测模型时可以使用各种特征,而用于时间序列预测的统计模型通常具有单变量性质。以下是一些常用的 ML 模型:

    1. 线性回归:在机器学习中是最基本的回归模型之一,可以用来模拟具有各种特征的时间序列数据。特征工程是使线性回归模型强大的关键。

    2. 基于树的模型:XGBoost 通过顺序构建决策树来学习数据,这些决策树从先前树的错误中学习,或者随机森林,通过构建一个决策树集合来学习数据,每个决策树学习数据的一部分,可以用于时间序列预测。能够模拟各种特征之间的交互和关系,为建模具有复杂特征相互关系的时序数据提供了优势。

    3. 支持向量机(SVM):当数据集有噪声或数据集的维度很大时,SVM 无法执行,因为它通过找到最大化不同类别之间分离的超平面来学习数据,在高维空间中构建这样一个有效的超平面是困难的,但 SVM 仍被用于时间序列预测。

  3. 深度学习(DL)模型:随着计算资源的可用性和可访问性的提高,DL 驱动的时序建模已经取得了许多进展。与其他任务,如图像识别和自然语言处理(NLP),类似,DL 模型越来越多地被用于制作准确的时间序列预测:

    1. 循环神经网络(RNN)模型:RNN 是一种设计用于处理序列数据的神经网络。由于 RNN 模型“记住”之前的输入以进行未来的预测,因此它们在处理如语音和时间序列数据等序列数据时表现良好。DeepAR、ESRNN 和 AR-Net 是一些基于 RNN 的时间序列预测模型。

    2. 多层感知器(MLP)模型:MLP 是一种具有多个神经元层的神经网络,其中每个层都学习数据并提取特征。基于 MLP 的模型,如 N-BEATS、NHiTs 和 TSMixer,通常具有深度堆叠的全连接层。这一组模型在实践中的应用已被证明效果良好。

    3. 基于 Transformer 的模型:随着基于 Transformer 的模型在自然语言处理领域的成功,这些模型使用多头注意力机制,能够捕捉输入中的不同关系和依赖,因此基于 Transformer 的时间序列模型和架构也在积极开发中。时间融合 Transformer(TFT)是一个基于 Transformer 的时间序列预测模型的例子,它适用于多步和多元时间序列预测。

      如何构建用于时间序列数据的深度学习模型

      有许多 Python 包可以帮助你构建时间序列模型。Darts、Kats、PyCaret 和 PyTorch Forecasting 是一些常用的 Python 包,它们提供了易于使用的深度学习模型实现,用于时间序列预测。如果你想查看本章 N-BEATS 模型应用的示例,请访问以下 GitHub 仓库:

      github.com/yoonhwang/Machine-Learning-and-Generative-AI-for-Marketing/blob/main/ch.4/TimeSeriesAnalysis.ipynb

摘要

在本章中,我们讨论了时间序列分析的重要性及其在市场营销中的应用。从分析数据随时间进展的基本方法,以及从这些分析中可以收集到的故事和洞察,到高级时间序列预测模型的发展,我们触及了时间序列分析中的广泛主题。我们看到了移动平均数、自相关及其可视化在理解随时间发生的事件的全貌中扮演的关键角色。我们还介绍了如何将时间序列数据分解为趋势和季节性,从而揭示商业和不同产品线中周期性的隐藏洞察。最后,我们尝试了两种常用的统计方法来建模时间序列数据,以及如何对未来进行预测,以便用于更高效和及时的市场营销活动。尽管本章没有深入讨论,但我们分享了一些其他正在使用和开发的 AI/ML 模型。请确保查看本章的 GitHub 仓库,以了解构建用于时间序列预测的深度学习模型的示例。我们将在本书的第四章中更深入地探讨深度学习和生成式 AI。

在下一章中,我们将探讨语言建模以及您如何从它中获得益处,用于您接下来的市场营销活动。我们将讨论如何使用和应用一些自然语言处理技术,以情感分析为例,以及它如何使营销人员能够衡量公众对品牌或产品的看法,并监控和优化营销信息,以更好地与客户偏好保持一致。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人相聚,并和超过 5000 名成员一起学习,详情请见:

packt.link/genai

二维码

第五章:利用情感分析增强客户洞察

在当今的数字时代,理解客户情感对于塑造营销策略、完善品牌信息和提升客户体验至关重要。情感分析,作为自然语言处理(NLP)的一个子集,赋予营销人员处理大量非结构化文本数据的能力,如客户反馈、社交媒体对话和产品评论,以衡量公众情绪。这种分析方法不仅有助于监控品牌声誉,还能根据客户偏好定制营销信息,从而增强整体客户洞察。

本章探讨了营销领域的情感分析世界。利用 Python 的力量,你将学习如何将情感分类为正面、负面或中性,并识别客户反馈中嵌入的细微差别。我们还将使用基于 Kaggle 的“Twitter 航空情感”数据集的实战示例,为你提供执行情感分析、解读结果并将这些见解应用于制定更有效的营销策略的技能。

总体而言,本章将为你全面介绍营销中情感分析的基础知识,然后指导你通过数据准备、分析和结果可视化的实际方面。到本章结束时,你将精通:

  • 理解情感分析在营销中的关键作用

  • 预处理文本数据以准备分析

  • 应用 Python 库使用传统自然语言处理和生成式 AI 元素执行情感分析

  • 解释和可视化结果以得出可操作的营销见解

营销中情感分析简介

在营销这个快节奏的世界里,关注客户情感不仅有益,而且是必需的。情感分析,即检测文本数据中的正面、负面或中性语调的过程,是这个努力的前沿,为营销人员提供了一个观察和理解客户互动情感基调的视角。这种方法使用自然语言处理(NLP)、机器学习和计算语言学来系统地识别、提取、量化和研究文本中的模式。这些模式可以从某些关键词和短语的呈现到句子的结构和术语使用的上下文。

情感分析的重要性

情感分析在营销中的重要性不容小觑。它就像指南针,引导品牌穿越浩瀚且常常波涛汹涌的公众舆论大海。通过分析客户反馈、社交媒体对话和产品评论,情感分析帮助营销人员理解人们说了什么,以及他们的感受。

关于营销中情感分析的进一步阅读

关于营销中自动化文本分析方法的概述,请参阅文章“团结各部落:利用文本进行营销洞察”(journals.sagepub.com/doi/full/10.1177/0022242919873106)。

更具体地说,情感分析在营销中的应用开辟了一系列机会:

  • 品牌监控:情感分析能够实时监控品牌在各个数字平台上的感知。通过跟踪情感变化,营销人员可以预测并减轻潜在的公关危机。例如,在 2017 年 4 月 9 日,由于超售,一名乘客被从航班上强制带离的事件中,情感分析本可以帮助联合航空检测到社交媒体上病毒式传播的负面情绪的迅速升级,并更积极地做出反应。

  • 活动分析:了解营销活动引起的情感反应,允许灵活调整策略。情感分析可以揭示活动是否与目标受众产生积极共鸣,或者是否偏离了目标。例如,百事公司在 2017 年推出的以肯达尔·詹纳为特色的广告,因其被认为轻视社会正义运动而受到抨击。早期的情感分析本可以识别出负面反馈,并允许及时调整活动策略。

  • 产品反馈:详细的情感洞察有助于精确指出产品或服务中令客户满意或不满意的特定方面。这种反馈循环对于持续改进和创新至关重要。以苹果公司发布 iPhone 6 为例,对客户反馈的情感分析突出了“弯曲门”问题,促使苹果公司迅速解决问题。

  • 市场研究:情感分析为更广泛的市场格局提供了一个窗口,通过揭示趋势、竞争对手地位和市场空白,提供竞争优势。例如,Netflix 利用情感分析来了解观众偏好和趋势,这有助于内容创作和推荐算法。

通过利用情感分析获得的洞察,营销人员不仅可以监控品牌声誉,还可以调整他们的沟通方式,使其更深入地与受众产生共鸣,从而实现更有效和有影响力的营销策略。

人工智能和情感分析方面的进步

大型语言模型(LLMs)和生成式人工智能(GenAI)的出现已经改变了情感分析,为理解文本数据提供了前所未有的深度和准确性。LLMs 在包含各种语言模式的庞大数据集上训练,使它们能够理解和生成类似人类的文本。例如,LLMs 可以以以前无法实现的方式理解上下文和细微差别,最先进的模型可以区分讽刺和真正的不满,或者识别包含改进建议的投诉中的潜在积极因素。

这些进步对于情感分析尤其相关,因为在满意和不满意的客户之间,差异往往微妙且依赖于上下文。然而,需要注意的是,尽管 LLMs 提供了这些优势,但它们也带来了一定的局限性。它们可能计算成本高昂,需要大量的处理能力,这可能不是所有用户都能负担得起,或者可能需要付出代价。此外,LLMs 并非完美无缺,它们有时可能会基于训练数据产生有偏见或不准确的结果。

尽管对 GenAI 模型及其局限性的更深入讨论将在本书的第四部分中展开,但本章将涉及 GenAI 在情感分析方面的针对性应用。

实际示例:Twitter Airline Sentiment 数据集

我们对情感分析的研究将基于Twitter Airline Sentiment数据集。这个针对不同航空公司的推文集合为理解如何将情感分析应用于现实世界的营销挑战提供了一个丰富的数据集。

在这里,情感通过人工标注被分类为正面、负面或中性,反映了从满意到挫败的多种客户情绪。

源代码和数据github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/blob/main/ch.5/SentimentAnalysis.ipynb

数据来源www.kaggle.com/datasets/crowdflower/twitter-airline-sentiment

便利的是,这个数据集不仅包含推文及其情感分类,在某些情况下还包含对负面情感推文的解释。这些将为我们提供有用的基准,以评估我们在本章中开发的方法。

在深入数据之前,以下是几个样本推文,突出了情感分类、存在的主题以及推文内容的性质。正如您所看到的,数据集的前几行包含由现实世界数据输入错误产生的术语,这些问题将在数据预处理阶段解决。

图片

图 5.1:Twitter 航空公司情绪数据集的样本推文

在接下来的章节中,我们将处理数据准备、模型构建、分析和可视化阶段,同时采用传统的 NLP 技术和使用 LLMs 的更现代方法。最初,我们将应用 NLP 工具进行数据清理和结构化,为传统的情绪分析打下基础。

认识到类别不平衡的挑战,我们将展示如何使用 GenAI 作为工具,根据需要通过添加额外的示例来增强我们的数据集。然后,我们将使用我们构建的模型来得出可操作的见解,这些见解可以帮助指导营销活动。

准备数据以进行情绪分析

在进行情绪分析之前,有效地准备数据至关重要。数据准备是一个涉及清理、结构和增强数据以改善分析结果的过程。这些步骤的目标是确保数据以可以直接用于分析的形式存在,并消除任何不准确或不规则性。

让我们从加载Twitter Airline Sentiment数据集开始:

import pandas as pd
df = pd.read_csv('Tweets.csv')
df.head(5) 

使用df.columns,我们可以看到许多列,例如包含推文本身的text列,以及几个有价值的元数据和情绪相关字段。以下是对列的总结,以及它们含义的简要描述:

描述
tweet_id 推文的 ID
airline_sentiment 推文的类别标签(正面、中性或负面)
airline_sentiment_confidence 情绪分类的置信水平
negative_reason 负面情绪的原因
airline 航空公司的官方名称
airline_sentiment_gold 航空公司情绪分类的黄金标准
name 用户的名称
negativereason_gold 负面原因背后的黄金标准
retweet_count 表示转发次数的数值
text 用户输入的推文文本
tweet_coord Twitter 用户的纬度和经度
tweet_created 推文的创建日期
tweet_location 发送推文的位置
user_timezone 用户的时区

表 5.2:Twitter 航空公司情绪数据集的列及其描述

传统的 NLP 数据准备技术

在传统的 NLP 技术中,仔细的文本准备——包括清理、分词、停用词去除和词形还原——对于构建输入文本以进行有效分析非常重要。我们将在本节中详细讨论这些过程。

相比之下,现代技术如词嵌入(例如 Word2Vec 和 GloVe)和上下文嵌入(例如 BERT 和 GPT-4)提供了更高级的表示和处理文本数据的方法。这些现代技术将在本书的第 IV 部分中更详细地解释。与依赖于手动特征提取的传统方法不同,现代技术会自动从其他文本的预训练中学习单词和上下文的密集表示。

为了说明,我们将选取五个推文文本的样本,并使用它们作为示例来观察传统数据准备步骤的影响。我们还将通过pd.set_option设置列宽来显示 DataFrame 的全列宽,从而显示完整的推文文本:

pd.set_option("max_colwidth", None)
examples_idx = df.sample(5).index # [1106, 4860, 6977, 8884, 9108]
df_sample = df.loc[examples_idx] 

清洗文本数据

文本清洗通过去除噪声并使文本格式统一,从而提高了数据分析的质量。其主要优势包括提高模型准确性和加快计算速度。然而,谨慎地处理清洗过程是必要的,以避免删除上下文中重要的信息。对于 Twitter 数据集来说,由于社交媒体文本的非正式和多样性,清洗特别有用。推文通常包含 URL、提及、表情符号和标签,这些有时会分散对主要情感分析的关注。

我们的方法针对这些具体内容,以保留核心信息的同时消除无关元素:

!python -m space download en_core_web_sm
import re
import spacy
nlp = spacy.load("en_core_web_sm")
def clean_text(text):
    text = re.sub(r'@\w+|#\w+|https?://\S+', '', text)
    text = re.sub(r'[^\w\s]', '', text)
    return text.lower()
df_sample['cleaned_text'] = df_sample['text'].apply(clean_text)
df_sample[["text", "cleaned_text"]] 

这产生了以下输出:

图 5.2:清洗前后推文文本的示例

注意,从文本中移除(@)提及对上下文的影响很小,因为我们的数据集已经通过airline列捕获了推文的主题。

额外的文本预处理包

在本节中没有使用的其他有用的 Python NLP 和文本预处理工具包括:

分词和停用词移除

分词将文本划分为更小的单元,如单词或短语,这使得算法更容易理解语言结构。停用词是常用词,如“是”、“和”、“the”,它们通常被移除,因为它们添加的语义价值很小,允许模型关注更有意义的内容。

在此实现中,我们使用 spaCy 的模型来应用分词和停用词移除,并展示每个步骤的结果:

def tokenize_and_remove_stopwords(row):
    doc = nlp(row['cleaned_text'])
    all_tokens = [token.text for token in doc]
    tokens_without_stop = [token.text for token in doc if not token.is_stop]
    processed_text = ' '.join(tokens_without_stop)
    row['all_text_tokens'] = all_tokens
    row['without_stop_words_tokens'] = tokens_without_stop
    row['processed_text'] = processed_text
    return row
df_sample = df_sample.apply(tokenize_and_remove_stopwords, axis=1)
df_sample[['cleaned_text', 'all_text_tokens', 'without_stop_words_tokens', 'processed_text']] 

这给我们以下输出:

图 5.3:分词和停用词移除后的推文文本示例

词形还原

词形还原将单词还原为其词典形式,确保结果是一个有效的单词。这个过程旨在将单词的不同形式合并为单个项目进行分析,从而提高下游任务的效率和准确性。

观察以下代码的最后一行,我们看到最终词元还原后的文本将wheels标准化为单数形式wheel,并将thanks转换为基本动词形式thank

def lemmatize_text(text):
    doc = nlp(text)
    lemmatized = [token.lemma_ for token in doc]
    return ' '.join(lemmatized)
df_sample['final_text'] = df_sample['processed_text'].apply(lemmatize_text)
df_sample[['processed_text', 'final_text']] 

这给我们以下输出:

图片

图 5.4:词元还原后的推文文本示例

类别不平衡

现在,我们将通过在我们数据集上的探索性数据分析来介绍理解类别平衡的重要性。类别平衡直接影响模型从数据中有效学习的能力。未解决的类别不平衡可能会掩盖洞察力,导致模型在实际应用中表现不佳。

在接下来的章节中,我们不仅将量化类别不平衡,还将讨论解决它的简单和更高级的策略。

评估类别平衡

确定整体情感分布至关重要,因为它有助于我们了解数据集中表达的一般情绪和观点。这种理解对于理解由于类别不平衡可能存在的任何偏差也是必不可少的。

以下代码按航空公司和情感分组推文,计算每个组的大小,并生成条形图来可视化结果:

import matplotlib.pyplot as plt
from datetime import datetime
sentiment_by_airline = df.groupby(['airline', 'airline_sentiment']).size().unstack().fillna(0)
plt.figure(figsize=(14, 6))
sentiment_by_airline.plot(kind='bar', stacked=True, color=['red', 'yellow', 'green'])
plt.title('Sentiment Distribution by Airline')
plt.xlabel('Airline')
plt.ylabel('Number of Tweets')
plt.xticks(rotation=45)
plt.legend(title='Sentiment')
plt.tight_layout()
plt.show() 

此代码生成了以下图表,展示了该数据集中捕获的航空公司推文的情感主要是负面的:

图片

图片

如果我们查看数据集中的类别平衡,我们可以看到有 9,178 个负面示例,3,099 个中性示例,以及 2,363 个正面推文。这可以通过以下方式展示:

df['airline_sentiment'].value_counts() 

在现实世界的数据集中,经常遇到具有类别不平衡的数据集,因此,我们将保留本章中的数据特征,以便我们能够理解类别不平衡对建模结果可能产生的影响。

解决类别不平衡

以下是一些可以用来解决类别不平衡的传统策略:

  • 欠采样通过减少多数类的样本大小以匹配少数类来平衡数据集。这有助于平衡数据集,但可能会导致丢失有价值的多数类示例。

  • 过采样通过复制现有示例来增加少数类的样本大小以匹配多数类。这改善了平衡,但可能导致模型在重复数据示例上过拟合。

  • 合成少数过采样技术SMOTE)与过采样类似,不同之处在于它生成合成示例而不是简单地复制现有的示例。它是通过基于特征空间中相似的示例生成新实例来实现的。

作为一项练习,你可以对多数类(负面情感)进行欠采样,以实现更平衡的数据集。这可以通过以下代码实现,我们首先将我们的训练数据分为负面、中立和正面类别,然后对负面类别进行下采样以匹配少数(正面)类别的示例数量,从而得到一个更平衡的起始数据集:

from sklearn.utils import resample
negative = df[df.airline_sentiment == 'negative']
neutral = df[df.airline_sentiment == 'neutral']
positive = df[df.airline_sentiment == 'positive']
negative_downsampled = resample(negative, n_samples=len(positive))
df_downsampled = pd.concat([negative_downsampled, neutral, positive]) 

进行欠采样实验

作为一项练习,运行文本中给出的下采样代码,并在本章剩余部分将df_downsampled替换为df,以查看你的结果如何随着更平衡的数据集而变化。

数据增强的 GenAI

在本节中,我们将展示一种通过使用 GenAI 的种子文本生成新示例来增强代表性不足的正面类别的策略。这种更新颖的方法补充了传统技术以解决类别不平衡问题,但新示例具有更大的潜在多样性。然而,使用 AI 生成数据可能会引入风险,例如过度拟合到生成的模式或反映生成模型本身的潜在偏差。确保种子文本的多样性可以帮助减轻这些问题。

我们将利用 Hugging Face 的 Transformers 库中的distilgpt2模型来增强我们的数据集。这个模型是 GPT-2 的简化版本,旨在提高资源效率,因此使得这个例子对具有不同计算资源的用户都易于访问:

from transformers import pipeline
generator = pipeline('text-generation', model='distilgpt2')
def augment_text(text, augment_times=2):
    augmented_texts = []
    for _ in range(augment_times):
        generated = generator(text, max_length=60, num_return_sequences=1)
        new_text = generated[0]['generated_text'].strip()
        augmented_texts.append(new_text)
    return augmented_texts
seed_text = "Fantastic airline service on this flight. My favorite part of the flight was"
augmented_examples = augment_text(seed_text)
def remove_extra_spaces(text):
    words = text.split()
    return ' '.join(words)
for example in augmented_examples:
    print("------\n", remove_extra_spaces(example)) 

记住,GenAI 的概率性质意味着输出可能随着每次执行而变化。通过使用精心选择的种子文本“``这次航班的航空公司服务太棒了。我最喜欢的飞行部分是”我们能够生成关于航空公司服务的各种正面情感。当在上述text-generation管道中使用此种子文本时,我们生成如下输出:

  • 这次航班的航空公司服务太棒了。我最喜欢的飞行部分是 享受所有乘务员和跑道的壮观景色

  • 这次航班的航空公司服务太棒了。我最喜欢的飞行部分是 这是我第一次乘坐它,而且非常值得

默认情况下,大多数 LLM 将产生反映你期望在日常生活中听到的语言的输出。例如,尝试移除种子语句的结尾部分“我最喜欢的飞行部分是"并看看 LLM 产生具有正面情感的示例有多困难。

GenAI 模型选择和提示敏感性的重要性

探索 Hugging Face 提供的更复杂的模型,如gpt-neogpt-jEleutherAI/gpt-neo-2.7B,将产生更细腻和逼真的增强效果。

提示的选择在引导生成模型输出中也起着至关重要的作用。种子文本的微妙变化可能导致结果发生巨大变化,这强调了提示设计在 GenAI 应用中的重要性。这个主题在本书的第九章中进行了详细探讨。

虽然这个增强步骤增强了我们数据集中积极情感推文的代表性,但要实现真正的类别平衡需要更广泛的数据增强以及各种种子文本,以确保模型不会过度拟合推文的开始部分。我们可以通过更改上述 augment_text() 函数中的 augment_times 参数来增加生成的增强示例的数量:

augmented_data = pd.DataFrame({
    'text': augmented_examples,
    'airline_sentiment': ['positive'] * len(augmented_examples)
})
df_augmented = pd.concat([df, augmented_data], ignore_index=True) 

通过仔细使用 GenAI 进行数据增强,我们现在有了 df_augmented 数据框,其中包含了可以添加到现有数据集以减轻类别不平衡并增强数据集中积极情感表达的额外数据。然而,为了说明原始数据集中类别不平衡对我们结果的影响,我们将不将这些示例添加到我们的数据集中。

执行情感分析

情感分析的力量在于其揭示文本数据背后情感的能力,为顾客情感提供了无价的见解。虽然 Twitter Airline Sentiment 数据集的焦点是将情感分类为积极、消极和中性类别,但情感分析也可以超出这些基本类别。根据应用的不同,情感可以分析以检测更细微的情感状态或态度,如快乐、愤怒、惊讶或失望。

构建自己的 ML 模型

训练 sentiment analysis 模型的基本方面,尤其是在使用传统 NLP 技术时,是预标注数据的需求。这些标签通常来源于人工标注,这个过程涉及个人评估文本的情感并根据其进行分类。这个 Twitter 数据集中的情感分数是在志愿者的帮助下收集的,其中一些负面推文也根据它们所强调的具体问题进行了分解,例如航班延误或服务质量差,从而提供了对客户不满的更细致的视角。

使用 scikit-learn,我们将构建利用此预标注数据集的 sentiment analysis 模型。这些模型将利用前一小节中展示的文本预处理方法从文本中提取 TF-IDF 特征,这些特征反过来又作为机器学习推理的输入,可以预测未见过的推文的情感。

特征工程

在训练模型之前,我们需要将文本数据转换为数值特征。一种常见的方法是使用TF-IDF词频-逆文档频率)技术。TF-IDF 是一种用于评估一个词在集合或语料库中对于文档重要性的统计度量。我们将利用之前执行的文本预处理步骤,并将tfidf向量器直接应用于处理后的文本,将特征限制在顶级 1,000 个术语(max_features=1000)。这一步很重要,因为降低维度有助于简化模型,使其训练更快,并减少过拟合的风险。通过关注最相关的词语,我们确保模型捕捉到数据中最显著的模式,同时忽略不那么重要的细节:

from sklearn.feature_extraction.text import TfidfVectorizer
df['cleaned_text'] = df['text'].apply(clean_text)
df = df.apply(tokenize_and_remove_stopwords, axis=1)
df['processed_text'] = df['cleaned_text'].apply(tokenize_and_remove_stopwords)
df['final_text'] = df['processed_text'].apply(lemmatize_text)
tfidf_vectorizer = TfidfVectorizer(max_features=1000)
X = tfidf_vectorizer.fit_transform(df['final_text'])
y = df['airline_sentiment'] 

探索 TF-IDF 的特征工程

在 TF-IDF 特征工程期间,你可以探索的另一个参数是ngram_range

N-gram 允许你超越单个单词,将连续单词的成对(bigram)或三元组(trigram)视为单个特征。这可以捕捉到更多的上下文和词语之间的关系——例如,虽然“not”和“good”单独可能并不很有信息量,但 bigram“not good”却传达了明确的情感。

模型训练

我们的特性准备就绪后,我们可以继续使用 scikit-learn 训练一个简单的模型。逻辑回归是一种简单而强大的算法,适用于包含在这些简短推文中的数据的维度。它为具有两种可能结果的分类问题建模概率,但它可以扩展以处理多个类别,这在我们的案例中适用:

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train) 

我们的逻辑回归模型训练完成后,现在我们可以解释模型的系数,以了解特定词语如何影响情感分类。对于每个情感类别,系数代表这些术语对文本被分类为该特定情感类别的可能性的影响,而其幅度代表每个术语在模型决策过程中的重要性。

为了实现这一点,我们遍历每个类别标签,提取并显示系数绝对值排序的最具影响力的特征:

feature_names = tfidf_vectorizer.get_feature_names_out()
class_labels = model.classes_
for index, class_label in enumerate(class_labels):
    coefficients = model.coef_[index]
    coefficients_df = pd.DataFrame({
        'Feature': feature_names,
        'Coefficient': coefficients
    })
    coefficients_df['Absolute_Coefficient'] = coefficients_df['Coefficient'].abs()
    coefficients_df = coefficients_df.sort_values(by='Absolute_Coefficient', ascending=False)
    print(f"Class: {class_label}")
    print(coefficients_df[['Feature', 'Coefficient']].head(10)) 

这产生了以下输出:

图 5.6:逻辑回归模型按情感类别排序的最具影响力的特征

我们可以从上述系数中看到以下词语对三个情感类别的影响:

  • 负面情感:单词thank(-3.88)降低了推文被分类为负面的可能性,而像hour(3.61)、bad(2.96)、delay(2.84)和cancel(2.63)这样的词语则增加了这种可能性,并且是投诉的特征。

  • 中性情感:例如,customer-2.24)、experience-1.91)和fix-1.88)等词语会降低中性分类的可能性,表明这些术语更常用于非中性语境中。

  • 正面情感:例如,thank4.36)、great3.54)、awesome3.18)和amazing3.07)等词语会显著增加推文被分类为正面的可能性。

模型评估

训练模型后的关键一步是评估我们的模型性能。如果没有适当的评估,我们可能会部署一个在实际场景中表现不佳的模型,这可能导致基于其预测的错误结论。

分类报告

scikit-learn 的分类报告为我们提供了每个类别的精确度、召回率和 F1 分数。这些指标至关重要,因为它们不仅告诉我们整体准确度,还告诉我们模型在每个情感类别上的表现:

from sklearn.metrics import accuracy_score, classification_report
y_pred = model.predict(X_test)
print(classification_report(y_test, y_pred)) 

图 5.7:评估逻辑回归模型性能的分类报告指标

宏平均和加权平均分数让我们了解模型在所有类别上的性能。宏平均对待所有类别同等,而加权平均则考虑了类别不平衡。这些分数之间的差异突出了类别不平衡对模型性能的影响。

让我们更仔细地看看每个类别的结果:

  • 负面情感,作为多数类,具有高精确度(0.82)和高召回率(0.92),表明模型在识别负面推文方面特别出色。这是由于我们的类别不平衡的预期副作用,因为模型有更多这个类别的例子来学习,导致预测这个类别正确的可能性更高。

  • 中性情感,比负面情感少,但比正面情感多,显示出显著较低的精确度(0.61)和召回率(0.49)。精确度相当好,这意味着当模型预测一条推文为中性时,正确率略超过一半。

  • 正面情感,最少代表的类别,具有相对较高的精确度(0.79),但比负面类别的召回率(0.61)低。这里的精确度较高表明,大多数被预测为正面的推文确实是正面的,但模型未能捕捉到许多正面情感(召回率低)。

混淆矩阵

混淆矩阵是进一步了解模型性能的一个很好的下一步。它显示了一个矩阵,其中实际类别在一轴上,预测类别在另一轴上。通过分析混淆矩阵,我们可以看到哪些类别被相互混淆。例如,如果许多中性推文被错误地分类为负面,这可能会表明模型倾向于预测负面,并且中性推文的特征不够独特。我们可以使用以下方法计算和可视化混淆矩阵:

from sklearn.metrics import confusion_matrix
import seaborn as sns
cm = confusion_matrix(y_test, y_pred, labels=['negative', 'neutral', 'positive'])
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['negative', 'neutral', 'positive'], yticklabels=['negative', 'neutral', 'positive'])
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.title('Confusion Matrix')
plt.show() 

我们可以接着看到以下混淆矩阵:

图片

图 5.8:逻辑回归模型的推文情感类别混淆矩阵

让我们将其分解以更好地理解:

  • 与我们从分类报告中观察到的结果一致,模型在正确识别负面推文方面表现出色,这在混淆矩阵的第一行中有所体现。

  • 当涉及到中性情感时,第二行表明模型倾向于将中性推文与负面推文混淆。

  • 最后,第三行对应于积极情感。虽然模型正确识别积极推文的时间超过一半,但仍有一大部分被误认为是负面或中性情感。

理解误分类

在用各种指标评估我们的模型后,我们可以调查模型失败时的示例,从而了解其局限性和改进的机会。

让我们看看模型预测与airline_sentiment_gold数据标签提供的可信分类发生冲突的实例:

gold_df = df[df['airline_sentiment_gold'].notnull()]
X_gold = tfidf_vectorizer.transform(gold_df['final_text'])
y_gold = gold_df['airline_sentiment_gold']
y_gold_pred = model.predict(X_gold)
gold_df['predicted_sentiment'] = y_gold_pred
misclassified = gold_df[gold_df['airline_sentiment_gold'] != gold_df['predicted_sentiment']]
misclassified[['airline_sentiment_gold', 'predicted_sentiment', 'text', 'final_text', 'negativereason_gold']] 

我们得到以下输出:

图片

图 5.9:数据集标签与逻辑回归模型预测不一致的示例推文

对误分类示例的分析表明,我们的模型的predicted_sentiment在准确捕捉完整推文语境方面存在不足。例如,一个表达对取消航班失望的推文的第二个误分类示例,以幽默的语气包装,突显了检测讽刺的内在挑战,并强调了模型训练涵盖更广泛情感表达的重要性。然后,对于最后一个例子,我们有一个令人鼓舞的推文,承认从负面经历中看到改进的机会,但预测为负面。这说明了 TF-IDF 特征在模型中解释细微积极情感时的困难,尤其是在与负面词汇交织在一起时。这些误分类可以从更先进的 NLP 模型中受益,这些模型能够更好地辨别语境和细微差别,这是我们将在下一节关于预训练 LLMs 的讨论中探讨的主题。

提高传统情感模型性能

  • 解决训练数据差距:确保您的数据集包括广泛的情感表达,如讽刺、幽默和条件积极。模型准确解释情感的能力直接与其从中学到的例子多样性相关。可以使用分层抽样等采样技术来确保所有情感类型在训练集中得到充分代表。

  • 理解特征表示的限制:传统的特征表示方法,如 TF-IDF,可能无法完全捕捉复杂的情感细微差别,尤其是在整体情感不是其各部分之和的情况下。

  • 增强模型中的上下文特征:通过结合上下文线索如 n-gram 或词性标注来丰富特征集。这些添加有助于通过考虑词序和语法结构来捕捉情感细微差别。

  • 探索更稳健的机器学习算法:除了像逻辑回归和朴素贝叶斯这样的简单方法之外,集成方法如随机森林和提升算法(XGBoost)能更好地捕捉复杂模式。此外,对逻辑回归进行超参数调整(例如,调整正则化强度)可以显著提高性能。深度学习方法如 CNN 和 RNN 通常提供最佳性能,前提是有足够的训练示例。

在探索了各种增强传统情感模型的技术,包括解决数据差距、特征表示和适当的算法之后,我们现在将注意力转向情感分析领域的一项更现代的进步,即使用预训练的 LLM。

使用预训练的 LLM

在应用预训练的 LLM 进行情感分析之前,理解嵌入的概念非常重要,这些嵌入是这些高级模型的基础。本质上,嵌入是数据的密集向量表示,可以是任何东西,从单词和整个文档到图像和关系数据。这些向量被设计用来在多维空间中捕捉数据的关键特征。

自然语言处理嵌入的早期例子包括 Word2Vec 和 GloVe,它们生成静态嵌入。在 Word2Vec 中,嵌入受到局部上下文的影响,通过跳字模型和连续词袋模型(CBOW)等技术,但一旦训练完成,相同的词无论在更广泛的上下文中都有相同的向量表示。然而,像 BERT 和 GPT 这样的最先进 LLM 引入了真正的上下文嵌入,其中词的表示根据其上下文使用动态变化。有效的 NLP 嵌入的关键属性是它在向量空间中保留了原始数据的语义关系,这意味着相似的向量(单词、短语或文档)比不相似的数据更接近。

将 LLM 应用于情感分析标志着自然语言处理领域的一项重大进步,简化了理解复杂文本数据的过程。这些模型通过在多样化的数据集上进行广泛的预训练,在捕捉人类语言的细微差别方面表现出色,从而绕过了复杂的文本预处理、超参数调整——甚至预标注数据的需要。对于市场营销专业人士来说,这意味着更有效地衡量不同平台上的客户情绪。

实施预训练模型

为了展示预训练 LLM 的有效性,我们将使用 Transformers 库中 distilbert-base-uncased-finetuned-sst-2-english 模型的 sentiment-analysis 管道。DistilBERT 是 BERT 的一个更小、更快的版本,保留了 95% 的上下文嵌入性能。这个特定的变体在斯坦福情感树库SST-2)数据集上进行了微调,这是一个情感分析的标准基准,包含带有人类标注的正面负面情感的电影评论。

由于其二元分类性质,中性情感被排除在我们的测试集之外,以使模型在正面负面之间的可用预测保持一致。在这个例子中,我们还将timetqdm模块纳入我们的代码中,以跟踪执行时间。在模型加载后,使用sentiment-analysis管道对所有测试文本进行推理可能需要几分钟才能完成:

from tqdm.auto import tqdm
import time
filtered_df = df[df['airline_sentiment'] != 'neutral']
X = filtered_df['text']
y = filtered_df['airline_sentiment']
X_train_texts, X_test_texts, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
sentiment_pipeline = pipeline("sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english")
start_time = time.time()
results = []
for text in tqdm(X_test_texts, desc="Analyzing sentiments"):
    result = sentiment_pipeline(text)
    results.append(result[0]['label'].lower())
end_time = time.time()
total_time = end_time - start_time
print(f"Total time for analyzing {len(X_test_texts)} tweets: {total_time:.2f} seconds") 

使用 DistilBERT 的 sentiment-analysis 管道简化了情感分析过程,因为它将几个复杂的步骤封装成一个高效的过程。如果没有这个,标记化、文本嵌入、推理和后处理都需要单独处理。

评估模型性能

可以使用以下代码从 LLM 推理中获取分类报告:

print(classification_report(y_test, results)) 

这产生了以下结果:

图片

图 5.10:评估 LLM 性能的分类报告指标

接下来,让我们生成混淆矩阵:

cm = confusion_matrix(y_test, results, labels=['negative', 'positive'])
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['negative', 'positive'], yticklabels=['negative', 'positive'])
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.title('Confusion Matrix')
plt.show() 

这给出了以下输出:

图片

图 5.11:LLM 对推文情感类别的混淆矩阵

当比较使用 TF-IDF 特征的前一个逻辑回归模型和我们的预训练 LLM 的性能时,出现了一些观察结果。虽然逻辑回归模型为情感分析提供了一个强大的基线,但在处理自然语言的细微差别方面存在局限性。虽然类别不平衡可能在模型性能问题中起到了一定作用,但重要的是要注意,LLM 理解语言细微差别的能力,源于其广泛的预训练和微调,可能在其优越性能中发挥了更大的作用。此外,逻辑回归模型仅使用了 TF-IDF 的单词,这未能捕捉到上下文,并导致了错误的描述。因此,它在分类主导的负面情感类别中的正面(和中性)情感分类上尤其困难。

LLM(考虑到我们排除了中性类别以保持与微调过程性质的一致性)表现出更稳健的性能。

这通过其在区分积极和消极情感方面的提高准确性得到展示。需要注意的是,逻辑回归模型从不平衡数据开始,以说明其对结果的影响,而 LLM 没有在 Twitter 数据上进行任何特定任务的训练,而是在 SST-2 电影评论上进行了训练。关键要点是 LLM 的知识被有效地推广,从电影评论到 Twitter 数据,突显了其强大的语言理解能力。对于消极情感的精确度为0.96,召回率为0.90,该模型强调了利用预训练神经网络进行情感分析的可能性。在积极情感检测方面的改进,精确度达到0.68,召回率为0.84,进一步强调了模型的预测能力。

使用像 LLM(大型语言模型)这样的高级机器学习模型的一个缺点是它们缺乏可解释性。理解这些黑盒模型中确切是什么创造了负面情绪可能具有挑战性。可以使用如LIME(局部可解释模型无关解释)等技术来提高可解释性。有关模型透明度和阐明 LLM 决策的技术更详细讨论,请参阅第十三章

虽然 LLM 的表现值得注意,但将 LLM 微调到我们航空公司推文数据集中存在的特定情感标签将进一步提高其性能。微调使模型更紧密地适应任务的独特上下文,使模型能够利用并理解分类任务的细微差别。

除了微调之外,迁移学习和少样本学习是进一步细化模型在情感分类上高精度分类能力的强大方法。迁移学习涉及将预训练模型在相关任务上调整以在目标任务上表现良好,即使只有最少量的额外训练数据。相反,少样本学习训练模型仅使用少量目标任务的示例来做出准确预测。

改进 LLM:迁移和少样本学习

在本书的第四部分中,我们将更深入地探讨这些尖端方法。我们将探讨如何将微调、迁移学习和少样本学习应用于预训练模型,将它们转化为针对特定领域任务(如情感分类)的高度专业化的工具。

当我们到达本书的第四部分时,我们将更深入地探讨适应预训练模型以用于特定领域任务的尖端方法。

将情感转化为可操作的见解

到目前为止,在本章中,我们已经探讨了理解和应用情感分析到您的数据中所需的工具和策略,从使用传统 NLP 方法的数据准备和预测的基础技术到 GenAI 的高级功能。在本章的最后一部分,我们将讨论如何分析这些见解以生成可操作的战略,这些战略可以指导品牌在营销活动的各个阶段取得成功。

创建您的数据集

在将此分析应用于您的用例之前,我们需要一种收集数据的方法,该方法能够捕捉与您的品牌相关的潜在客户情绪。虽然本章以 Twitter 航空数据集为例,但我们探讨的技术适用于任何行业或数据源。本节将介绍您可以采取的一般步骤,以创建用于分析的专有数据集,无论这些数据来自 Twitter 还是其他主要数据平台。

人工智能赋能营销中的伦理和治理

在人工智能赋能的营销中的伦理和治理是第十三章的主题,在收集数据时遵守尊重消费者隐私和数据保护法律的伦理准则和治理框架至关重要。营销中的伦理实践包括为数据收集获得同意,确保数据匿名化以保护个人身份,以及提供明确的退出机制。公司应建立强大的数据治理政策,定义数据处理程序和遵守如欧盟的通用数据保护条例GDPR)或加利福尼亚消费者隐私法案CCPA)等法律标准。

收集 Twitter 数据

要开始,请确保您拥有 Twitter 开发者账户并可以访问 Twitter(现在更名为 X)API。您可以遵循以下步骤:

  1. 您首先需要创建一个项目并获取您的 API 密钥和令牌,然后,使用您的 Twitter 开发者账户的凭证(developer.twitter.com/en/portal/petition/essential/basic-info),验证您的会话以访问 Twitter API。以下是一般步骤:

    !pip install tweepy
    import tweepy
    # Replace these with your API keys and tokens
    consumer_key = 'YOUR_CONSUMER_KEY'
    consumer_secret = 'YOUR_CONSUMER_SECRET'
    access_token = 'YOUR_ACCESS_TOKEN'
    access_token_secret = 'YOUR_ACCESS_TOKEN_SECRET'
    auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_token_secret)
    api = tweepy.API(auth) 
    
  2. 现在我们已经可以访问 Twitter API,您可以使用与您的品牌相关的 Twitter 账号或相关标签,并结合search_tweets方法来查找相关推文。以下示例收集了提及"@YourBrandHandle"的最新 100 条推文:

    query = "@YourBrandHandle -filter:retweets"
    tweets = api.search_tweets(q=query, lang="en", count=100) 
    

由于最近的变化,Twitter(X)API 可能访问受限,某些端点可能需要提高访问级别。如果您遇到403 Forbidden错误,您可能需要升级访问级别或使用 API 文档中提供的替代端点。更多详情可以在 Twitter 开发者门户(developer.twitter.com/en/portal/petition/essential/basic-info)找到。

  1. 收集推文后,我们可以提取相关信息,例如推文 ID、文本、创建时间和位置。然后我们可以将这些数据结构化为pandas DataFrame,以便更容易分析:

    data = [{
        'tweet_id': tweet.id,
        'text': tweet.text,
        'tweet_created': tweet.created_at,
        'tweet_location': tweet.user.location,
        } for tweet in tweets]
    your_brand_df = pd.DataFrame(data) 
    

API 响应文档中还有许多其他值得考虑的元数据字段,包括转发计数(tweet.retweet_count)、标签(tweet.entities['hashtags'])和提及(tweet.entities['user_mentions'])。如以下章节所述,这些字段可以为理解您的品牌情感叙事提供有价值的见解,包括显著话题、推文参与度和病毒性。

从其他平台收集数据

分析品牌情感不仅限于 Twitter,还包括 Facebook、Instagram、Google 评论等多种社交媒体平台。每个平台都面临着独特的挑战和机会,以收集和分析数据。收集数据的方法根据每个平台的 API 功能和数据可用性而有所不同。对于 Google 评论等平台,API 可能允许您直接访问评论和评分。在 Facebook 和 Instagram 等平台上,您可能需要依赖帖子、评论和标签来衡量情感。

访问开发者 API

要从不同的社交媒体平台收集数据,您需要访问它们各自的开发者 API。以下是一些有用的链接,以帮助您开始:

一旦获取数据,一个主要挑战就是准确识别与您的品牌相关的提及和讨论。这正是命名实体识别(NER)和实体映射技术发挥作用的地方。NER 可以帮助识别文本中的专有名词,如品牌名称或产品,而实体映射可以将这些提及与数据集中的您的品牌联系起来。

在一个虚构零售商的数据集上执行命名实体识别(NER)

例如,让我们考虑一系列来自虚构在线零售商 Optimal Hiking Gear(销售户外装备)的客户评论。为了提取品牌提及,我们可以使用 spaCy 语言模型内建的 NER 功能,并查找其ORG标签以识别相关提及:

nlp = spacy.load("en_core_web_sm")
reviews = [
    "I recently purchased a sleeping bag from Optimal Hiking Gear and it exceeded my expectations.",
    "The tent I bought from Optimal Hiking was damaged on arrival. Very disappointed.",
    "The Optimal Hiking company makes a backpack that's the best. I've been using mine for years without any issues."
]
for review in reviews:
    doc = nlp(review)
    for ent in doc.ents:
        print(f"Entity: {ent.text}, Label: {ent.label_}") 

这会产生以下结果:

Entity: Optimal Hiking Gear, Label: ORG
Entity: Optimal Hiking, Label: ORG
Entity: Optimal Hiking, Label: ORG
Entity: years, Label: DATE 

通过定制训练增强 NER

为了使 NER 模型更贴近您的需求,考虑使用您的数据进行训练。这包括提供一些文本示例,其中包含您品牌或行业特有的手动标注实体。通过这样做,模型可以更准确地识别和分类这些自定义实体。spaCy 等工具提供了训练您的 NER 模型的功能。

理解主题和主题

本节深入探讨了各种工具,以从您的数据集中提取见解,概述关键主题和主题。这些见解对于理解数据中客户情绪的更广泛背景至关重要。作为一个起点,我们可以参考该数据集标注者标记的负面情感的不同原因的数量:

df.negativereason.value_counts() 

这给我们以下输出:

图 5.12:Twitter 数据集中不同负面情感推文原因的计数

使用词云

词云,其中每个词在图中的大小对应其出现的频率,是可视化文本数据的有价值起点工具。为了丰富我们的词云并确保可视化不仅反映最频繁的术语,还反映最能指示独特情感和主题的术语,我们将结合 TF-IDF 分析来生成我们的图。通过将 ngram_range=(1, 2) 参数引入我们的 tfidf_vectorizer,我们创建了单语和双语。利用 WordCloud 库,我们可以通过以下方式创建词云:

from wordcloud import WordCloud
tfidf_vectorizer = TfidfVectorizer(max_features=1000, ngram_range=(1, 2))
tfidf_matrix = tfidf_vectorizer.fit_transform(df['final_text'])
tfidf_scores = dict(zip(tfidf_vectorizer.get_feature_names_out(), tfidf_matrix.sum(axis=0).tolist()[0]))
wordcloud_tfidf = WordCloud(width=800, height=400, background_color='white').generate_from_frequencies(tfidf_scores)
plt.figure(figsize=(10, 5))
plt.imshow(wordcloud_tfidf, interpolation='bilinear')
plt.axis('off')
plt.show() 

我们接下来会看到类似以下这样的词云:

图 5.13:显示 TF-IDF 分析中不同术语出现频率的词云

到目前为止的分析通过诸如 delaycancelhelp 等常见词汇揭示了关键主题。通过包含双语,我们还可以捕捉到诸如 customer servicecancel flight 这样的关键术语。在 Twitter 数据的背景下,标签提供了直接了解核心主题和情感的方法。为了深入了解,我们将继续从推文中提取标签,创建一个词云来以不同的方式可视化这些关键短语。这种方法旨在为我们数据集中的主题提供不同的视角:

import nltk
def extract_hashtags(text):
    return re.findall(r"#(\w+)", text)
hashtags = sum(df['text'].apply(extract_hashtags).tolist(), [])
hashtag_freq_dist = nltk.FreqDist(hashtags)
wordcloud_hashtags = WordCloud(width=800, height=400, background_color='white').generate_from_frequencies(hashtag_freq_dist)
plt.figure(figsize=(10, 5))
plt.imshow(wordcloud_hashtags, interpolation='bilinear')
plt.axis('off')
plt.show() 

我们接下来看到以下内容:

图 5.14:显示 Twitter 标签出现频率的词云

排除直接提及航空公司的情况,词云通过诸如 #Fail#Disappointed#BadCustomerService 这样的标签清晰地突出了普遍的负面情绪。与这些相反,#DestinationDragons 也显著出现,这标志着西南航空公司的广为人知的旅游活动,展示了我们数据集中捕获的客户反馈的双重性。

使用 LDA 发现潜在主题

潜在狄利克雷分配LDA)是一种超越简单频率指标的高级技术,如词云中所示,它通过无监督机器学习识别文本语料库中的潜在主题。与仅突出最频繁单词的词云不同,LDA 通过将文档视为主题的混合体来辨别隐藏的主题结构,其中每个主题由一组特定的单词定义。这个过程涉及贝叶斯推理,使用狄利克雷分布来估计文档中主题的存在及其比例。例如,在酒店评论集合中,LDA 可能会识别与位置、停车、浴室清洁和入住体验相关的主题。LDA 的复杂性在于其能够捕捉语料库中单词的上下文和共现,从而在不进行预先标记的情况下提供对文本主题内容的更细致的理解。

我们可以通过以下方式实施这种方法:

from sklearn.decomposition import LatentDirichletAllocation
from sklearn.feature_extraction.text import CountVectorizer
count_vect = CountVectorizer(max_df=0.95, min_df=2, stop_words='english')
doc_term_matrix = count_vect.fit_transform(df['final_text'])
LDA = LatentDirichletAllocation(n_components=5, random_state=42)
LDA.fit(doc_term_matrix)
for i, topic in enumerate(LDA.components_):
    print(f"Top words for topic #{i}:")
    print([count_vect.get_feature_names_out()[index] for index in topic.argsort()[-10:]])
    print("\n") 

这给我们以下输出:

Top words for topic #0:
['fly', 'follow', 'send', 'dm', 'flight', 'hour', 'sit', 'gate', 'seat', 'plane']
Top words for topic #1:
['tomorrow', 'change', 'amp', 'time', 'late', 'delay', 'fly', 'flightle', 'cancel', 'flight']
Top words for topic #2:
['response', 'bad', 'good', 'time', 'flight', 'bag', 'great', 'customer', 'service', 'thank']
Top words for topic #3:
['wait', 'need', 'help', 'problem', 'delay', 'luggage', 'hour', 'miss', 'bag', 'flight']
Top words for topic #4:
['service', 'number', 'customer', 'minute', 'email', 'hour', 'help', 'try', 'phone', 'hold'] 

分析 LDA 生成的聚类使我们能够确定推文中的重要主题,例如在主题#1#2中分别表示的航班延误和客户服务问题。通过改变n_components参数,我们可以改变算法对存在主题数量的假设,随着参数值的增加,导致更细粒度的主题。

重要的是要认识到,LDA 识别出的所有主题并不都会直接与关键情感表达相一致,其中一些可能只是简单地反映了数据集中普遍存在的、非特定的语言,正如在主题#0中看到的那样。

为了提取有意义的见解,通常需要额外的审查来辨别哪些主题对于分析最为相关。这个过程可以通过人工审查或通过为语言模型设计一个精心设计的提示来促进,帮助根据可能的主题总结单词分组。

时间趋势:追踪品牌叙事

在社交媒体的动态领域,推文的病毒性往往充当衡量对品牌感知最具影响力的情感的温度计。这对于负面情感尤其如此,因为它们对品牌形象的风险很大。通过审查围绕航空公司(如 JetBlue)的 Twitter 活动,我们可以揭示可能显著影响品牌声誉的推文。

本文介绍了一种基于社交媒体的品牌声誉追踪器,该追踪器实时监控品牌事件,并将它们与品牌声誉的具体驱动因素相连接:ora.ox.ac.uk/objects/uuid:00e9fcb7-9bf1-486a-b4dd-3c1d086af24e/files/rz316q188f

这项分析涉及筛选提及@JetBlue账号的推文。下面的代码将随着时间的推移对这些推文的情感进行分类,其中每个数据点的气泡大小对应于那天总的转发量,提供了一个参与度的视觉尺度:

df['tweet_created'] = pd.to_datetime(df['tweet_created']).dt.tz_convert(None)
df['date'] = df['tweet_created'].dt.date
airline_handle = "@JetBlue"
airline_tweets = df[df.text.str.contains(airline_handle)]
grouped = airline_tweets.groupby(['airline_sentiment', 'date']).agg({'tweet_id':'count', 'retweet_count':'sum'}).reset_index()
positive_tweets = grouped[grouped['airline_sentiment'] == 'positive']
neutral_tweets = grouped[grouped['airline_sentiment'] == 'neutral']
negative_tweets = grouped[grouped['airline_sentiment'] == 'negative']
plt.figure(figsize=(14, 7))
scale_factor = 3
for tweets, sentiment, color, linestyle in zip(
    [positive_tweets, neutral_tweets, negative_tweets],
    ['Positive', 'Neutral', 'Negative'],
    ['green', 'orange', 'red'],
    ['-', '--', '-.']
):
    scaled_retweet_count = tweets['retweet_count'] * scale_factor
    plt.plot(tweets['date'], tweets['tweet_id'], linestyle=linestyle, label=sentiment, color=color)
    plt.scatter(tweets['date'], tweets['tweet_id'], scaled_retweet_count, color=color)
plt.title(f'Daily Sentiment Trend for {airline_handle} with Bubble Size Indicating Retweets')
plt.xlabel('Date')
plt.ylabel('Number of Tweets')
plt.legend()
plt.xticks(rotation=45)
plt.tight_layout()
plt.show() 

这产生了以下图表:

图 5.15:JetBlue 推文随时间变化的情感,其中每个数据点的气泡大小对应于那天总的转发量

在 2 月 22 日和 23 日观察到显著的负面情感推文高峰,后者转发量的异常激增表明广泛的参与。那些关注 JetBlue 品牌声誉的人可能会发现深入研究这些推文的细节很有价值。

我们可以根据转发量最高的推文,以及在此日期范围内以及前一天,对这些推文进行汇总和排名,以下代码可以实现:

dates_of_interest = [pd.to_datetime('2015-02-22').date(), pd.to_datetime('2015-02-23').date(), pd.to_datetime('2015-02-24').date()]
filtered_df = airline_tweets[(airline_tweets['date'].isin(dates_of_interest)) & (airline_tweets['airline_sentiment'] == 'negative')]
top_tweets_per_date = filtered_df.groupby('date').apply(lambda x: x.nlargest(3, 'retweet_count'))
top_tweets_per_date[['text', 'retweet_count', 'negativereason']] 

这给我们以下结果:

图 5.16:2015 年 2 月 22 日至 24 日 JetBlue 负面情感推文高峰的分析

结果的第一天和最后一天揭示了典型的抱怨,如晚点航班和糟糕的服务,这在航空业很常见。然而,2 月 23 日的反弹突显了 JetBlue 一项营销活动的争议,该活动被短语“我们的机队很酷”所概括。正如本章引言中讨论的,实时监控品牌认知将使他们能够及早跟踪这种营销情感的变化,使他们能够预测并可能减轻随之而来的公关问题。

这种负面宣传的潜在长期影响需要进一步的监控和分析——使用第二章中讨论的 KPI 等指标——以评估对品牌声誉的影响。尽管如此,这项分析说明了随着时间的推移监控社交媒体趋势的重要性,以便提前解决可能损害品牌认知的问题。

使用地理空间分析映射情感

地理空间分析提供了一个强大的视角,通过这个视角可以观察客户情感,使公司能够识别出关注点——从客户服务问题到设计不佳的市场营销活动——甚至在这些问题对现场工作人员变得明显之前。为了说明如何生成这样的见解,让我们利用folium包创建一个热图,该热图基于推文坐标精确指出负面情感的来源:

!pip install folium
import folium
from folium.plugins import HeatMap
filtered_df = df[(df['text'].str.contains('@JetBlue') & (df['airline_sentiment'] == 'negative'))]
filtered_df = filtered_df.dropna(subset=['tweet_coord'])
valid_coords = []
for coord in filtered_df['tweet_coord']:
    try:
        lat, long = eval(coord)
        valid_coords.append((lat, long))
    except (TypeError, SyntaxError, NameError):
        continue
if valid_coords:
    map_center = [sum(x)/len(valid_coords) for x in zip(*valid_coords)]
else:
    map_center = [0, 0]
tweet_map = folium.Map(location=map_center, zoom_start=4)
HeatMap(valid_coords).add_to(tweet_map)
tweet_map 

这段代码产生了以下地图:

图 5.17:基于推文坐标的热图,精确指出负面 JetBlue 情感的来源

生成的热图揭示了 JetBlue 主要运营区域中负面情感的集中——这一相关性是预期的,因为更多的航班自然会导致更多负面经历的报告。然而,通过观察这些模式的时间演变,我们可以看到这种方法可以作为实时工具来发现异常的情感模式。

例如,来自新位置的负面推文的突然涌入可能表明服务问题,并预示着可能出现的公关挑战。相反,识别出拥有大量正面推文的高频区域可能凸显出公司内的优势。将地理空间分析与之前介绍的主题建模方法相结合,也可以解锁更多见解,不仅揭示讨论的内容,还揭示这些对话发生的地方,提供宝贵的可操作营销情报。

摘要

本章强调了情感分析在现代营销策略中的重要性。它介绍了情感分析作为一项关键工具,用于解释大量非结构化文本数据,例如社交媒体对话,以精炼营销策略、品牌信息或客户体验。通过利用 Twitter 航空公司数据集,我们涵盖了将情感分类为正面或负面的端到端流程,使用了传统的 NLP 和更先进的涉及预训练 LLMs 的 GenAI 方法。然后,我们介绍了一系列工具,用于可视化这些结果,以得出可操作的营销见解。本章应该使你具备有效利用情感分析所需的基本技能,适用于从品牌声誉监控到将营销信息与客户偏好对齐的各种应用。

展望下一章,我们将从理解客户情感进步到利用预测分析积极塑造客户参与度,重点关注通过 A/B 测试对营销策略的实证验证。我们将讨论识别预测客户参与度的特征、训练机器学习模型、模型评估以及 A/B 测试的实施。本章旨在通过提供特征选择、构建预测模型、优化模型性能、进行 A/B 测试以及将见解融入有效营销策略的技能来提升你的知识。这一步将使你不仅能够预测客户行为,而且能够通过实证验证和精炼营销策略以提高其有效性。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人交流,并与其他 5000 多名成员一起学习:

packt.link/genai

二维码

第六章:利用预测分析和 A/B 测试提升客户参与度

我们可以通过多种方式从数据驱动和 AI/ML 驱动的营销技术中受益。例如,您可以根据我们已在第二章第三章中讨论的先前营销活动的成功和失败背后的关键驱动因素来优化您的营销策略。您还可以根据您业务中的趋势和季节性,或者根据您产品和业务周围的客户情绪来优化您的营销策略,正如我们在第四章第五章中所讨论的那样。目标产品推荐(第七章)和利用生成式 AI 优化营销内容(第九章第十章)是应用 AI/ML 在营销中的其他一些关键好处。

在所提及的主题中,我们将在本章中尝试预测分析,以及如何在您的下一次营销活动中利用这些预测模型。通过智能预测客户的预期行为,您可以针对可能对您有利的客户群体进行定位。这样,您就不必对整个潜在客户群进行大规模营销,而可以更好地定制您的营销信息,并且由于您只针对成功率更高的群体,因此还可以节省营销成本。我们还将讨论如何进行 A/B 测试来决定您下一次营销活动的最佳预测模型。

在本章中,我们将涵盖以下主题:

  • 使用基于树的算法预测客户转化

  • 使用深度学习算法预测客户转化

  • 进行 A/B 测试以选择最佳模型

使用基于树的算法预测客户转化

预测分析或建模可以在客户生命周期的各个阶段应用。如果您还记得第二章,我们可以将客户生命周期分解为以下五个主要阶段:意识参与转化保留忠诚度,如下面的图所示:

图片

图 6.1:第二章中的客户生命周期图

预测建模的应用范围很广,取决于你的营销目标。例如,如果你有一个新品牌或产品发布,并希望通过社交媒体上的广告提高新产品知名度,你可以构建预测模型来帮助你识别可能点击广告的目标客户。另一方面,如果你想提高产品购买转化率,你可以构建预测模型来识别在接下来的 X 天内更有可能进行购买的客户,并针对他们进行营销。这会导致更有效的营销,因为你可以避免客户因频繁接触不相关的内容而感到疲劳,这种情况通常发生在你没有针对正确的客户子群体进行大规模营销时。此外,你可以通过只向特定的客户子群体发送营销材料来降低营销成本。这将帮助你将剩余的营销预算重新用于其他营销活动。

不仅你可以利用预测分析来提高品牌知名度、参与度和转化率,预测分析还可以用来提高客户保留率。通常,会建立客户流失可能性模型来识别哪些客户有离开你生意的风险。通过这些客户流失预测,你可以构建针对这一高流失风险群体的定制化营销策略和营销内容,以将他们重新变为活跃客户。折扣、免费订阅试用或免费计划升级通常作为保留策略的一部分提供给这一高流失风险群体。

基于树的机器学习算法

可以使用多种 AI/ML 算法进行预测建模,例如线性回归、逻辑回归和决策树模型,这些我们在前面的章节中已经讨论过,以及正在日益普及的深度学习模型。在本章中,我们将使用基于树的模型构建预测模型,例如随机森林和梯度提升树,以及神经网络模型,它们是深度学习模型的核心。任何基于树的机器学习模型下面都有一个决策树。正如我们在第三章中讨论的,决策树就像一个流程图,它根据获得的信息分成子节点。每个节点代表一个分割的问题或标准,每个分支或边代表在节点提出的问题的结果。以下图表展示了决策树可能构建的高级概述:

图片

图 6.2:决策树的示意图

在众多的基于树的机器学习模型中,梯度提升决策树(GBDT)和随机森林是最常用的两种模型,经常用于预测建模。GBDT 和随机森林模型都是由多个决策树构建的。然而,主要区别在于这些决策树是如何构建的。

简而言之,随机森林模型是一个包含许多决策树的模型,其中每个决策树都是使用数据集的随机子样本和特征子集构建的。这样,随机森林中的每个决策树都会以略微不同的方式学习数据中的信息或关系,并具有不同的关注区域。

最终预测是这些单个决策树的所有结果或预测的平均值。以下是一个随机森林的示意图:

图片

图 6.3:随机森林的示意图

与此同时,GBDT 模型也由许多决策树组成,但每个决策树是顺序构建的,每个后续的决策树都是基于前一个决策树所犯的错误进行训练的。GBDT 模型的最终预测是所有单个决策树预测的加权平均值。以下是一个 GBDT 模型的示意图:

图片

图 6.4:GBDT 的示意图

构建随机森林模型

在本章中,我们将使用在线购买数据集作为示例来构建一个预测模型,以预测客户是否会进行转换。首先,我们将讨论如何使用scikit-learn包在 Python 中构建随机森林模型。

源代码和数据github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/tree/main/ch.6

数据来源archive.ics.uci.edu/dataset/468/online+shoppers+purchasing+intention+dataset

目标变量和特征变量

我们首先需要定义目标和特征变量,其中目标变量是我们想要预测的因素,特征变量是模型将学习以进行预测或决策的因素。为此,你可以遵循以下步骤:

  1. 让我们先加载数据到一个 DataFrame 中,并检查我们可以用于我们的随机森林模型的特征:

    import pandas as pd
    df = pd.read_csv("./data.csv")
    df.info() 
    

当你运行此代码时,你应该看到以下输出,这是关于此数据的信息:

图片

图 6.5:示例数据集摘要

  1. 在前面的输出中,首先要注意的是列,Revenue,这是目标变量,它告诉我们客户是否进行了购买或转换,其类型为布尔型。另一列,Weekend,也具有布尔型数据类型。我们将使用以下代码将它们编码为0表示 False 和1表示 True:

    df["Revenue"] = df["Revenue"].astype(int)
    df["Weekend"] = df["Weekend"].astype(int) 
    
  2. 然后,有两列的数据类型为 object,分别是 MonthVisitorType。如果你仔细观察,Month 列的月份值是字符串,我们将将其转换为相应的月份数字。VisitorType 列有三个唯一值,New_VisitorReturning_VisitorOther。我们将分别将其编码为 012,如下所示:

    from time import strptime
    df["MonthNum"] = df["Month"].apply(lambda x: strptime(x[:3],'%b').tm_mon)
    df["VisitorTypeNum"] = df["VisitorType"].apply(
            lambda x: 0 if x == "New_Visitor" else 1 if x == "Returning_Visitor" else 2
    ) 
    

如此代码所示,我们正在使用 time 模块的 strptime 函数将三个字母的月份字符串值编码为相应的月份数字。然后,我们使用 pandas DataFrame 的 apply 函数将 VisitorType 列的每个值编码为相应的整数值。

  1. 现在我们已经将所有列值转换为数值,我们将定义目标和特征变量,如下所示:

    TARGET = "Revenue"
    FEATURES = [
        'Administrative',
        'Administrative_Duration',
        'BounceRates',
        'Browser',
        'ExitRates',
        'Informational',
        'Informational_Duration',
        'MonthNum',
        'OperatingSystems',
        'PageValues',
        'ProductRelated',
        'ProductRelated_Duration',
        'Region',
        'SpecialDay',
        'TrafficType',
        'VisitorTypeNum',
        'Weekend'
    ]
    X = df[FEATURES]
    Y = df[TARGET] 
    

如此代码所示,我们已定义目标变量 TARGET 使用 Revenue 列,其余列作为特征变量 FEATURES。然后,我们创建了一个 DataFrame X,它是特征集,以及 Y,它是目标序列。

  1. 最后,我们将使用以下代码将这些目标和特征集拆分为训练集和测试集:

    from sklearn.model_selection import train_test_split
    train_x, test_x, train_y, test_y= train_test_split(
        X, Y, test_size=0.2
    ) 
    

我们正在使用 sklearn.model_selection 模块中的 train_test_split 函数。从 test_size 参数可以看出,我们正在使用数据集的 80%进行训练,其余 20%用于测试。

使用这些训练集和测试集,我们现在可以准备训练一个随机森林模型。

训练随机森林模型

Python 的 scikit-learn 包提供了一个方便的方式来创建随机森林模型。看看以下代码:

from sklearn.ensemble import RandomForestClassifier
rf_model = RandomForestClassifier(
    n_estimators=250, max_depth=5, class_weight="balanced", n_jobs=-1
)
rf_model.fit(train_x, train_y) 

让我们更仔细地看看这段代码。我们正在使用 sklearn.ensemble 模块中的 RandomForestClassifier 类,并使用 n_estimatorsmax_depthclass_weightn_jobs 参数初始化一个随机森林模型:

  • n_estimators 参数定义了要构建多少个单独的决策树。

  • max_depth 参数定义了每个决策树可以生长多深。与其他参数,如 min_samples_splitmin_samples_leafmax_features 一起,max_depth 通过限制决策树的生长来帮助防止过拟合问题。

  • class_weight 参数定义了每个类的权重。当数据集不平衡时,此参数非常有用。在我们的示例数据集中,只有大约 15%属于正类,这意味着只有 15%的目标变量,收入,其值为 1,或者只有 15%的客户已经转化。你可以为每个类提供自定义权重,作为一个字典,或者使用 "balanced" 选项来自动调整与实际类频率成反比的权重。

  • 最后,n_jobs 参数定义了要并行运行多少个作业。如果您还记得我们关于随机森林和 GBDTs 的讨论,随机森林是一系列决策树,因此可以并行构建单个树,而不依赖于其他树。通过将 -1 作为此参数的输入,您指示它使用所有可用资源来训练此随机森林模型。

使用这些参数,我们现在可以使用 fit 函数和训练集来训练这个随机森林模型。

过拟合与欠拟合?

过拟合是指模型拟合到训练集过于紧密,在训练数据上表现良好,但在模型之前未见过的数据上表现较差。另一方面,欠拟合是指模型过度泛化或没有足够地调整到训练集,以至于没有学习到特征变量和目标变量之间的关系。通常需要多次迭代超参数调整,以找到最小过拟合的最佳点。

预测和评估随机森林模型

RandomForestClassifier 对象提供了从训练好的随机森林模型进行预测的便捷函数。请看以下代码:

rf_pred = rf_model.predict(test_x)
rf_pred_proba = rf_model.predict_proba(test_x)[:,1] 

如其名所示,predict 函数对给定的输入进行预测。在我们的例子中,结果将是测试集中每个记录的 0 和 1 的列表,因为我们正在预测客户是否已经转换。

predict_proba 函数也对给定的输入进行预测,但不同之处在于它给出介于 01 之间的预测概率。它为每个记录和每个类别返回预测概率,因此,在我们的例子中,它为每个记录返回两个值,其中第一个元素是预测为类别 0 的概率,第二个元素是预测为类别 1 的概率。由于我们只对类别 1 的预测概率感兴趣,我们使用 [:,1] 来切片,这样我们就有了一个转换预测概率的列表。

现在我们有了预测的转换概率,我们需要评估我们的预测有多好。

评估预测模型的准确性和有效性的方法有很多,但我们将主要关注整体准确率、精确率、召回率、曲线下面积AUC)- 接收者操作特征ROC)曲线和混淆矩阵。我们将通过示例深入探讨这些指标。

正如其名所示,准确率是所有预测中正确预测或真正例TP)的百分比。精确率是预测正例中正确预测的百分比,或者是预测为正例中包括假正例FP)的真正例的百分比。召回率是模型识别出的正例的百分比,或者是实际正例中包括真正例和假负例的真正例的百分比。准确率、精确率和召回率的公式如下:

图片

图片

图片

在 Python 中,scikit-learn 包提供了一个方便的工具来计算这些指标,如下面的代码所示:

from sklearn import metrics
accuracy = (test_y == rf_pred).mean()
precision = metrics.precision_score(test_y, rf_pred)
recall = metrics.recall_score(test_y, rf_pred) 

在我们的例子中,当运行这些代码时,这些关键指标的结果如下:

图片

图 6.6:随机森林模型性能指标摘要

这些结果表明,我们训练的随机森林模型具有相当的整体准确率和召回率,但在精确率方面似乎表现不佳。这表明,在这个模型预测为正例或可能转换的客户中,只有大约 54%实际上已经转换。然而,如果你还记得,实际的总体转换率是 15%;换句话说,如果你随机猜测谁会转换,你可能只有 15%的时间是正确的。

因此,由于这个模型有 54%的时间预测了转换客户,这证明了它在选择更有可能转换的客户方面比随机猜测要有效得多。此外,高召回率表明,实际上已经转换的客户中有大约 85%是那些被这个模型预测为高度可能转换的客户。

从实际的市场营销角度来看,如果你只针对这个模型预测可能转换的客户进行营销,你仍然会捕获到大多数这些转换。此外,如果你针对你的整个客户群进行营销,85%(100%减去 15%,这是整体转换率)的营销支出将会浪费。但是,如果你只针对这些高度可能的客户进行营销,只有大约 46%(100%减去 54%,这是该模型的精确度)的营销支出将会浪费。

我们将要关注的另一个关键评估指标是AUC-ROC 曲线。简单来说,ROC 曲线显示了在牺牲假正率FPR)的情况下,每个牺牲所获得的真正率TPR)的权衡。AUC,正如其名所示,是 ROC 曲线下的面积,告诉我们模型在区分正例和负例方面的表现如何。AUC 的范围从01,数值越高,模型越好。在 AUC 为0.5时,表明模型的表现与随机猜测相同。

下面的代码可以用来绘制 ROC 曲线:

dp = metrics.RocCurveDisplay.from_predictions(
    test_y,
    rf_pred_proba,
    name="Conversion",
    color="darkorange",
)
_ = dp.ax_.set(
    xlabel="False Positive Rate",
    ylabel="True Positive Rate",
    title="ROC Curve",
)
plt.grid()
plt.show() 

在这里,我们再次使用metrics模块来绘制 ROC 曲线。计算准确率、精确率和召回率与计算 AUC-ROC 曲线之间的主要区别在于我们如何使用预测概率rf_pred_proba而不是预测标签pred。这是因为 ROC 曲线检查在不同概率水平下 TPR 和 FPR 如何变化。通过使用预测概率,我们可以计算随着决策阈值的改变,TPR 和 FPR 如何变化。生成的图表如下所示:

图片

图 6.7:随机森林模型预测的 AUC-ROC 曲线

如您从这张图表中可以看到,您可以轻松评估每个 FPR 的牺牲如何影响 TPR。例如,在这张图表中,在 20% FPR 的情况下,我们已经实现了大约 90%的 TPR,这表明该模型在区分正例和负例方面表现良好。这里的 AUC 为0.93,这也表明模型在识别正例和负例方面表现良好。

最后,我们将查看混淆矩阵。正如其名所示,混淆矩阵是查看模型在何处以及如何最容易被混淆的好方法。以下是一个示例,可以帮助理解。请看以下代码:

import seaborn as sns
cf_matrix = metrics.confusion_matrix(test_y, rf_pred)
ax = plt.subplot()
sns.heatmap(
    cf_matrix,
    annot=True,
    annot_kws={"size": 10},
    fmt="g",
    ax=ax
)
ax.set_xlabel("Predicted")
ax.set_ylabel("Actual")
ax.set_title(f"Confusion Matrix")
plt.show() 

与之前类似,我们使用metrics模块构建混淆矩阵。confusion_matrix函数接受实际值和预测值,并构建混淆矩阵。然后,我们使用seaborn Python 包中的heatmap函数绘制热图。生成的图表如下所示:

图片

图 6.8:随机森林模型预测的混淆矩阵

如您从这张图中可以看到,y 轴表示实际类别,x 轴表示预测类别。例如,左上方的框是实际类别为 0 或无转换,预测类别也是0的地方。右上方的框是实际类别为 0,但模型预测它们属于类别1或转换的地方。

如您所见,混淆矩阵显示了模型最困惑的地方。一个预测结果准确率高的模型将在对角线框中有大量数字或百分比,而在其他框中有小数字。

我们已经尝试使用随机森林模型预测客户转换的可能性。在这里,我们观察并讨论了如何使用这个随机森林预测模型帮助定位客户群的一部分,同时不会失去太多已转换的客户,以及这如何导致更具成本效益的营销策略。

梯度提升决策树(GBDT)建模

我们将使用相同的 dataset 和 train/test sets 来构建 GBDT 模型,并将其性能与我们刚刚构建的随机森林模型进行比较。XGBoost 是 Python 中用于训练 GBDT 模型最常用的库。您可以在终端或 Jupyter Notebook 中使用以下命令安装此包:

pip install xgboost 

训练 GBDT 模型

XGBoost 包遵循与scikit-learn包相同的模式。请看以下代码:

from xgboost import XGBClassifier
xgb_model = XGBClassifier(
    n_estimators=100,
    max_depth=5,
    scale_pos_weight=1/train_y.mean(),
)
xgb_model.fit(train_x, train_y) 

如此代码所示,我们使用n_estimatorsmax_depthscale_pos_weight参数初始化了一个XGBClassifier

  • 与随机森林模型的情况类似,n_estimators参数定义了要构建多少个单个决策树。你可能已经注意到,我们为这个参数使用了一个非常低的数字。如果你还记得,GBDT 模型是顺序构建的,其中每个后续的决策树都会学习前一个决策树犯的错误。这通常会导致更少的单个树表现出与随机森林模型相当或更好的性能。

此外,由于 GBDT 模型是顺序构建的,与可以并行构建单个决策树的随机森林模型相比,大量决策树会导致训练时间更长。

  • 另一个参数max_depth与随机森林模型的情况相同。此参数限制了每个决策树可以生长的深度。

  • 最后,scale_pos_weight参数定义了正负类权重的平衡。你可能还记得,我们有一个不平衡的数据集,其中正类仅占数据的约 15%。通过使用1/train_y.mean()对正类给予成反比的权重,我们指示模型调整不平衡数据集。这强制 GBDT 模型对正类的不正确预测进行更多惩罚,从而使模型对正类更加敏感。

当 GBDT 模型中包含大量单个决策树时,通常会存在潜在的过拟合问题,处理这些问题的方法有很多。除了max_depth参数之外,XGBoost 包还提供了其他各种参数,例如max_leavescolsample_bytreesubsamplegamma,这些参数可以帮助减少过拟合。

我们建议您查看文档,并尝试各种参数,看看它们如何帮助您防止过拟合。

这里是文档:xgboost.readthedocs.io/en/latest/python/python_api.html#xgboost.XGBClassifier

预测和评估 GBDT 模型

与随机森林模型的RandomForestClassifier类似,XGBClassifier对象也提供了相同的语法来预测训练好的 GBDT 模型。请看以下代码:

xgb_pred = xgb_model.predict(test_x)
xgb_pred_proba = xgb_model.predict_proba(test_x)[:,1] 

如此代码所示,你可以使用predict函数预测测试集中每个记录的正负标签,并使用predict_proba函数预测测试集中每个个体记录的每个类别的概率。与之前一样,我们通过使用[:,1]切片输出以获取正类预测概率(即转换的预测概率),来获取测试集中每个记录的预测概率。

为了比较这个 GBDT 模型与随机森林模型的性能,我们将使用相同的评估指标和方法。你可能还记得,我们可以使用以下代码来获取准确率、精确率和召回率的关键指标:

accuracy = (test_y == xgb_pred).mean()
precision = metrics.precision_score(test_y, xgb_pred)
recall = metrics.recall_score(test_y, xgb_pred) 

由于构建这些树时存在一些随机性,每次训练 GBDT 模型时都可能会有一些方差和差异,但在此写作时,结果如下所示:

图片

图 6.9:GBDT 模型性能指标总结

这些关键指标看起来与随机森林模型非常相似。这个 GBDT 模型的整体准确率和精确率略高于随机森林模型。然而,召回率略低于随机森林模型。

同样,可以使用以下代码绘制 AUC-ROC 曲线:

dp = metrics.RocCurveDisplay.from_predictions(
    test_y,
    xgb_pred_proba,
    name="Conversion",
    color="darkorange",
)
_ = dp.ax_.set(
    xlabel="False Positive Rate",
    ylabel="True Positive Rate",
    title="ROC Curve",
)
plt.grid()
plt.show() 

生成的 AUC-ROC 曲线如下所示:

图片

图 6.10:GBDT 模型预测的 AUC-ROC 曲线

当你将此与随机森林模型进行比较时,结果几乎相同。AUC 约为0.93,在 FPR 为0.2时,GBDT 模型的 TPR 也约为0.9,这与之前构建的随机森林模型的情况相同。

最后,让我们通过以下代码查看混淆矩阵:

import seaborn as sns
cf_matrix = metrics.confusion_matrix(test_y, xgb_pred)
ax = plt.subplot()
sns.heatmap(
    cf_matrix,
    annot=True,
    annot_kws={"size": 10},
    fmt="g",
    ax=ax
)
ax.set_xlabel("Predicted")
ax.set_ylabel("Actual")
ax.set_title(f"Confusion Matrix")
plt.show() 

生成的混淆矩阵如下所示:

图片

图 6.11:GBDT 模型预测的混淆矩阵

当你将此与随机森林模型的混淆矩阵进行比较时,你会注意到 GBDT 模型的 TPs 较低,但 GBDT 模型的假阴性也较低。这是预期的,因为我们已经看到 GBDT 模型的精确率较高,但与随机森林模型相比,召回率较低。

总体而言,随机森林和 GBDT 模型的性能非常相似,从这些例子中难以区分。根据你如何微调你的模型,你可能会得到一个更好的随机森林或 GBDT 模型。

有许多方法和参数可以微调基于树的模型。我们建议你尝试不同的参数集,看看它们如何影响模型性能!

使用深度学习算法预测客户转化

深度学习已成为热门话题,其流行度和使用率都在上升,因为深度学习模型已被证明在数据变量之间存在复杂关系时表现良好,并且可以从数据中自主学习和提取特征,尽管基于树的模型也非常频繁地被使用,并且在预测建模方面非常强大。我们在第五章中提到了深度学习,当时我们使用了预训练的语言模型进行情感分析和分类。在本节中,我们将在此基础上构建知识,并实验开发深度学习模型用于预测建模,特别是用于预测哪些客户可能转化的预测。

深度学习基本上是一种人工神经网络ANN)模型,具有许多隐藏和复杂的神经元层,或者说,是一种深度 ANN。ANN 是一种受动物和人类大脑中生物神经网络启发的模型。ANN 通过类似动物和人类大脑的相互连接的神经元层来学习数据。以下图表显示了 ANN 的高级结构:

图表

图 6.12:示例 ANN 架构

如此图表所示,任何深度学习或 ANN 模型都有三个层次:输入层、隐藏层和输出层。ANN 模型如何学习或构建隐藏层权重的详细解释超出了本书的范围,但就高层次而言,它们通过前向传播和反向传播的迭代进行:

  • 前向传播是将数据从输入层通过网络传递到输出层,并应用激活函数的过程,无论每个神经元是否被激活,并返回每个节点的输出。

  • 反向传播是从输出层到输入层的移动过程,通过分析前一次迭代的损失或误差来调整网络的权重。

通过这些前向和反向传播的迭代,神经网络学习每个神经元的权重,以最小化预测误差。

应该尝试不同的隐藏层数量和每层的神经元数量,以找到最适合每个预测模型案例的最佳神经网络架构。在本节中,我们将实验比较宽神经网络架构与深度神经网络架构的性能。

何时使用宽神经网络与深度神经网络?

宽神经网络指的是具有较少层但每层有更多神经元的 ANN 模型,而深度神经网络指的是具有许多隐藏层的 ANN 模型。除了比较模型性能以确定哪种架构更适合您的案例之外,还有一些关键因素您可能需要考虑或限制采取哪种方法:

  • 训练时间和计算资源:随着层数的增加,训练需要更多的时间,因为每一层的反向传播都是计算密集型的,这也导致了更高的计算成本。宽神经网络可能在缩短训练时间和降低计算成本方面具有优势。

  • 模型可解释性:与深度神经网络相比,较浅的架构可能提供更好的可解释性。如果可解释性是一个要求,浅层架构可能更适合。

  • 泛化能力:深度神经网络模型通常能够通过更多的层捕获更抽象的模式,并且与宽神经网络相比,能够学习更高阶的特征。这可能导致深度架构模型在新的和未见过的数据上具有更好的性能。

深度学习模型的训练集和测试集

为了神经网络模型的最佳性能,您需要在训练模型之前对数据进行归一化。我们将使用之前用于树模型的相同训练集和测试集,但对其进行归一化。看看以下代码:

mean = train_x.mean()
std = train_x.std()
normed_train_x = (train_x - mean)/std
normed_test_x = (test_x - mean)/std 

如此代码所示,我们首先从训练集中获取均值和标准差,并通过减去均值并除以标准差来归一化训练集和测试集。标准化后,normed_train_x DataFrame 的所有列的均值应为0,标准差为1

宽神经网络建模

我们将首先使用 Python 中的keras包构建宽神经网络模型。

要在您的机器上安装keras,请在您的终端中运行以下命令:

pip install keras 

训练宽神经网络模型

使用归一化的训练集和测试集,让我们开始构建神经网络模型。看看以下代码,了解如何初始化神经网络模型:

import keras
model = keras.Sequential(
    [
        keras.Input(shape=normed_train_x.shape[1:]),
        keras.layers.Dense(2048, activation="relu"),
        keras.layers.Dropout(0.2),
        keras.layers.Dense(1, activation="sigmoid"),
    ]
) 

如您从以下代码中可以看到,我们使用Sequential类创建了一系列层。我们以Input类定义的输入层开始,其中我们定义了形状或输入神经元的数量,以匹配训练集的列数或特征数。然后,我们有一个包含 2,048 个神经元的宽隐藏层。我们添加了一个Dropout层,它定义了要丢弃的神经元百分比,这有助于减少过拟合问题。我们指示神经网络模型在隐藏层和输出层之间丢弃 20%的神经元。最后,我们有一个输出层的Dense层,它有一个输出神经元,将输出正例的预测概率或转换的可能性。

您可能已经注意到我们用于隐藏层和输出层的两个激活函数。ReLU(修正线性单元)激活函数是最常用的激活函数之一,它只激活正值并关闭所有负值。ReLU 激活函数的方程如下:

ReLU(x) = max(0, x)

ReLU 激活函数的行为如下:

图 6.13:ReLU 激活函数

另一方面,sigmoid函数将值转换为01的范围。这使得 sigmoid 函数成为预测概率输出的首选。sigmoid 函数的方程如下:

sigmoid 函数的行为如下:

图 6.14:sigmoid 激活函数

除了 ReLU 和 sigmoid 之外,还有许多其他激活函数,如 tanh、leaky ReLU 和 softmax。我们建议您做一些研究,并实验不同激活函数的工作方式和它们对神经网络模型性能的影响!

在我们能够训练神经网络模型之前,还有一些步骤需要完成:

  1. 首先,我们需要定义我们将通过模型训练迭代跟踪的关键指标,并编译模型。请看以下代码:

    model_metrics = [
        keras.metrics.Accuracy(name="accuracy"),
        keras.metrics.Precision(name="precision"),
        keras.metrics.Recall(name="recall"),
    ]
    model.compile(
        optimizer=keras.optimizers.Adam(0.001),
        loss="binary_crossentropy",
        metrics=model_metrics
    ) 
    

正如我们之前与树形模型讨论的那样,我们将跟踪准确度、精确度和召回率。我们将使用 Adam 优化器进行此练习。简单来说,优化器是用于根据损失函数(在这种情况下是binary_crossentropy,它衡量预测值和实际二进制结果之间的差异)更新网络权重的算法。由于我们的预测输出或目标变量是一个表示转换与否的二进制变量,binary_crossentropy将适合作为损失函数。对于多类预测,其中目标变量不是二进制变量并且有超过两个可能的结果,categorical_crossentropy将是一个更好的损失函数。

  1. 接下来,我们将在训练模型时运行的所有迭代或 epoch 中保存最佳模型。请看以下代码:

    best_model_path = "./checkpoint.wide-model.keras"
    model_checkpoint_callback = keras.callbacks.ModelCheckpoint(
        filepath=best_model_path,
        monitor="val_precision",
        mode="max",
        save_best_only=True
    ) 
    

在这里,我们使用精确度作为指标来监控并基于该指标值将最佳模型存储到本地驱动器。最佳模型将被存储在best_model_path变量中定义的方式。

  1. 最后,现在是时候使用以下代码训练这个宽神经网络模型了:

    class_weight = {0: 1, 1: 1/train_y.mean()}
    history = model.fit(
        normed_train_x.to_numpy(),
        train_y.to_numpy(),
        batch_size=64,
        epochs=30,
        verbose=2,
        callbacks=[
            model_checkpoint_callback,
        ],
        validation_data=(normed_test_x.to_numpy(), test_y.to_numpy()),
        class_weight=class_weight,
    ) 
    

与我们之前给树形模型的类权重类似,我们也将定义与类组成成反比的类权重。正如您从代码中可以看到的,我们指示模型以 64 个批次的规模运行 30 次迭代或 epoch。我们将之前创建的用于存储最佳模型的回调与自定义类权重注册。当您运行此代码时,它将运行 30 个 epoch 并报告我们之前定义的准确度、精确度和召回率指标。此代码的输出应类似于以下内容:

图 6.15:神经网络模型的样本输出

预测和评估宽神经网络模型

为了从我们刚刚训练的模型中进行预测,我们首先需要加载最佳模型。您可以使用以下代码来加载最佳模型:

wide_best_model = keras.models.load_model(best_model_path) 

使用此模型进行预测与scikit-learn包的语法相似。请看以下代码:

wide_pred_proba = wide_best_model.predict(normed_test_x).flatten()
wide_preds = [1 if x > 0.5 else 0 for x in wide_pred_proba] 

如您从这段代码中可能注意到的,您可以使用keras模型的predict函数来获取每个记录的预测概率。我们使用flatten函数将预测概率输出从二维数组转换为一个预测概率列表。然后,为了说明目的,我们将预测概率高于0.5的任何记录视为有很高的转换可能性,并假设它们是阳性案例。概率阈值是您可以为转换与否的最终预测进行微调的另一个因素。

我们将使用之前用于基于树的模型的关键指标、AUC-ROC 曲线和混淆矩阵的相同代码。结果如下所示:

图片

图 6.16:宽神经网络模型的评估结果总结

如果您将这些结果与基于树的模型进行比较,您会注意到宽神经网络模型的表现略逊于基于树的模型。精确度和召回率略有下降,与基于树的模型相比,AUC 也有所下降。我们将在更深入地讨论 A/B 测试时,更深入地探讨这些模型的实际用途以及如何选择最适合营销活动的最佳模型。

深度神经网络建模

在本节中,我们将讨论如何构建深度神经网络模型,并将结果与我们在上一节中构建的宽神经网络模型进行比较。这两个神经网络模型之间的唯一区别在于我们如何构建或设计它们。

训练深度神经网络模型

请看以下代码:

model = keras.Sequential(
    [
        keras.Input(shape=normed_train_x.shape[1:]),
        keras.layers.Dense(128, activation="relu"),
        keras.layers.Dense(128, activation="relu"),
        keras.layers.Dropout(0.2),
        keras.layers.Dense(128, activation="relu"),
        keras.layers.Dropout(0.2),
        keras.layers.Dense(1, activation="sigmoid"),
    ]
) 

与之前一样,我们使用keras.Sequential来构建模型,但这次在第一个Input层和最终的Dense输出层之间有更多的层:

  • 我们有四个隐藏层,每个层包含 128 个神经元,并使用 ReLU 激活函数。

  • 在最后一个隐藏层和输出层之间,以及最后一个隐藏层和倒数第二个隐藏层之间,也有两个Dropout层。

与之前的宽神经网络模型相比,每个层中的神经元数量更少,但层数更多。正如您从这个示例中可以看到的,模型架构取决于构建模型的人,并且应该基于性能。我们建议尝试不同的模型架构,并分析它如何改变模型性能。

使用之前用于宽神经网络模型的相同 Keras 模型训练代码,你也可以训练这个深度神经网络模型。确保你有保存最佳模型的回调函数,这样我们就可以用它来评估模型的表现。

预测和评估深度神经网络模型

如前所述,你可以使用以下代码根据从训练深度神经网络模型中找到的最佳模型进行预测:

deep_best_model = keras.models.load_model(best_model_path)
deep_pred_proba = deep_best_model.predict(normed_test_x).flatten() 

使用预测概率,你可以运行相同的评估指标和图表。由于模型中的随机性,每次训练模型时结果可能会有所不同。在这次运行时,结果如下所示:

图片

图 6.17:深度神经网络模型评估结果总结

与我们之前构建的宽神经网络模型相比,深度神经网络模型的表现略差。AUC 值大致相同,但精确率和召回率低于宽神经网络模型。这些评估指标和图表有助于检查模型在表面价值和训练时间时的表现。对于模型之间更实际的评估,你可能想要考虑运行 A/B 测试来选择你营销活动的最终模型。

进行 A/B 测试以选择最佳模型

A/B 测试,简单来说,就是比较两个版本的功能或模型,以确定哪一个更好。它在各个行业的决策过程中发挥着关键作用。网页开发者可能会使用 A/B 测试来测试两个版本的软件哪个表现更好。营销人员可能会使用 A/B 测试来测试哪种营销信息版本可能更有效地吸引潜在客户。同样,A/B 测试可以用来比较两个不同模型在性能和有效性方面的差异。在本章的例子中,我们可以使用 A/B 测试来选择我们基于训练和测试集构建的模型中哪一个在实际的真实世界环境中可能表现最佳。

A/B 测试通常在一个预定义的时期内进行,或者直到收集到预定义数量的样本。这是为了确保你有足够的样本来基于它们做出决策。例如,你可能想要进行为期两周的 A/B 测试,并在两周结束时收集测试期间的结果进行分析。或者,你可能想要为 A 和 B 两种场景设定 2,000 个样本的目标,而不设定特定的时期。

你可能还想将周期和样本数量都设置为目标,哪个先到就哪个。例如,你将样本目标设置为 2,000 个样本和两周的时间框;如果你在两周内收集到 2,000 个样本,你可能想早点结束测试,因为你已经收集了足够多的样本来分析结果。A/B 测试的周期和样本大小应根据业务需求或限制以及测试结果的置信度来确定。

检查 A/B 测试的结果通常使用统计假设检验。两样本 t 检验经常用于确定 A/B 测试中 A 和 B 案例观察到的差异是否具有统计学意义。t 检验中有两个重要的统计量——t 值p 值

  • t 值衡量两个均值之间的差异程度,相对于两个总体的方差。t 值越大,两组之间的差异就越明显。

获取两个样本t 检验t 值的方程如下:

图片

M[1]和M[2]是平均值,S[1]和S[2]是标准差,N[1]和N[2]是第一组和第二组的样本数量。正如你可能从这个方程中推断出的,大的负t 值将表明第二组的平均值显著大于第一组的平均值,而大的正t 值将表明第一组的平均值显著大于第二组的平均值。这也被称为双尾t 检验

  • 另一方面,p 值衡量结果偶然发生的概率。因此,p 值越小,两组之间的差异就越具有统计学意义,差异不是偶然的。

模拟 A/B 测试

我们将模拟 A/B 测试,就像我们正在用我们的模型实时运行这个实验一样。为了说明目的,我们将对之前构建的 XGBoost 或 GBDT 模型和宽神经网络模型进行 A/B 测试。我们将为每种情况运行 1,000 个样本,并分析结果,以查看哪个模型可能更适合我们的营销活动,以最大化客户转化率。

首先,我们将随机将流量分配到 A 组(GBDT 模型)和 B 组(宽神经网络模型)。请看以下代码:

group_a_indexes = sorted(list(np.random.choice(2000, 1000, replace=False)))
group_b_indexes = [x for x in range(2000) if x not in group_a_indexes] 

在这里,我们使用numpy包的random.choice函数从 2,000 个项目中随机选择 1,000 个项目。我们将这些项目分配到 A 组,其余的分配到 B 组。然后,我们像以下代码那样模拟 A/B 测试:

group_a_actuals = test_y.iloc[group_a_indexes].to_numpy()
group_b_actuals = test_y.iloc[group_b_indexes].to_numpy()
group_a_preds = []
group_b_preds = []
for customer in range(2000):
    if customer in group_a_indexes:
        # route to XGBoost
        conversion = test_y.iloc[customer]
        pred_prob = xgb_model.predict_proba(
            np.array([test_x.iloc[customer].to_numpy(),])
        )[0][1]
        pred = 1 if pred_prob > 0.5 else 0
        group_a_preds.append(pred)
    elif customer in group_b_indexes:
        # route to Wide Net
        conversion = test_y.iloc[customer]
        pred_prob = wide_best_model.predict(
            np.array([normed_test_x.iloc[customer].to_numpy(),]), verbose=0
        )[0][0]
        pred = 1 if pred_prob > 0.5 else 0
        group_b_preds.append(pred) 

如此代码所示,对于前 2,000 名客户,我们将一半分配到 A 组,其余的分配到 B 组。A 组客户使用 XGBoost 或 GBDT 模型预测其转换的可能性。B 组客户使用宽神经网络模型预测其转换的可能性。

然后,我们将检查这些预测的实际结果。在实际测试设置中,这些结果可能在预测做出后的几天或几周后出现,因为客户需要时间来决定是否购买。我们将评估那些被预测会转换的客户以及被预测不会转换但已经转换的客户(即被遗漏的机会)。请看以下代码:

def get_cumulative_metrics(actuals, preds):
    cum_conversions = []
    missed_opportunities = []

    customer_counter = 0
    cum_conversion_count = 0
    missed_opp_count = 0
    for actual, pred in zip(actuals, preds):
        customer_counter += 1
        if pred == 1:
            if actual == 1:
                cum_conversion_count += 1
        else:
            if actual == 1:
                missed_opp_count += 1
        cum_conversions.append(cum_conversion_count/customer_counter)
        missed_opportunities.append(missed_opp_count/customer_counter)
    return cum_conversions, missed_opportunities 

如你所见,我们正在计算那些被预测会转换的客户以及那些被预测不会转换但已经转换的客户的总转换累积数。这些本质上是被遗漏的机会,因为我们没有向这些客户发送我们的营销信息,但他们本可以完成转换。我们将使用以下代码对这些每个组的这些结果进行汇总:

a_cum_conv_rates, a_missed_opp_rates = get_cumulative_metrics(
    group_a_actuals, group_a_preds
)
b_cum_conv_rates, b_missed_opp_rates = get_cumulative_metrics(
    group_b_actuals, group_b_preds
)
ab_results_df = pd.DataFrame({
    "group_a_cum_conversion_rate": a_cum_conv_rates,
    "group_a_cum_missed_opportunity_rate": a_missed_opp_rates,
    "group_b_cum_conversion_rate": b_cum_conv_rates,
    "group_b_cum_missed_opportunity_rate": b_missed_opp_rates,
}) 

现在,让我们用以下代码查看随时间推移的累积转换率:

ax = (
    ab_results_df[[
        "group_a_cum_conversion_rate", "group_b_cum_conversion_rate"
    ]]*100
).plot(
    style=['-', '--'],
    figsize=(8, 5),
    grid=True
)
ax.set_ylabel("Conversion Rate (%)")
ax.set_xlabel("Customer Count")
ax.set_title(
    "Cumulative Conversion Rates over Time (A: XGBoost, B: Wide Net)"
)
plt.show() 

这将生成如下图表:

图 6.18:A 组和 B 组随时间推移的累积转换率

如此图表所示,接受宽神经网络模型预测的 B 组,与接受 XGBoost 模型预测的 A 组相比,整体转换率更高。让我们也看看每个组在遗漏机会方面的表现,以下代码:

ax = (
    ab_results_df[[
        "group_a_cum_missed_opportunity_rate",
        "group_b_cum_missed_opportunity_rate"
    ]]*100
).plot(
    style=['-','--'],
    figsize=(8, 5),
    grid=True
)
ax.set_ylabel("Missed Opportunity Rate (%)")
ax.set_xlabel("Customer Count")
ax.set_title(
    "Cumulative Missed Opportunity Rates over Time (A: XGBoost, B: Wide Net)"
)
plt.show() 

当你运行这段代码时,你应该得到一张看起来类似于以下图表的图:

图 6.19:A 组和 B 组随时间推移的累积遗漏机会率

此图表表明,使用 XGBoost 模型预测的 A 组遗漏机会率高于使用宽神经网络模型预测的 B 组。

这些视觉图表是检查不同组或模型表现的好方法。然而,为了验证这些差异是否具有统计学意义,我们不得不运行 t 检验。

双尾 T 检验

Python 中的scipy包提供了一个方便的工具来计算双尾 t 检验的 t 值和 p 值。

要在你的机器上安装scipy,请在你的终端中运行以下命令:

pip install scipy 

一旦你安装了scipy包,你可以运行以下命令来检查 A 组和 B 组在转换率和遗漏机会率之间的差异的统计学意义:

from scipy.stats import ttest_ind
t, p = ttest_ind(a_cum_conv_rates, b_cum_conv_rates)
print(
    f"Conversion Rate Difference Significance -- t: {t:.3f} & p: {p:.3f}"
)
t, p = ttest_ind(a_missed_opp_rates, b_missed_opp_rates)
print(
    f"Missed Opportunity Rate Difference Significance -- t: {t:.3f} & p: {p:.3f}"
) 

如你所见,从这段代码中,scipy.stats模块中的ttest_ind函数让你可以轻松地得到两组之间的双尾 t 检验的 t 值和 p 值。这段代码的输出应类似于以下内容:

图 6.20:双尾 t 检验结果

让我们更仔细地看看这个输出。首先,转换率 t 检验的 t 值和 p 值分别是-13.1680。这表明两组之间的转换率差异在统计学上是显著的。t 检验的负值表明 A 组的平均值小于 B 组。

由于从 p 值我们得出差异是显著的,这转化为结果,即 A 组的转换率显著低于 B 组。换句话说,宽神经网络模型在捕捉高转换可能性客户方面比 XGBoost 模型表现显著更好。

其次,错过机会率 t 检验的 t 值和 p 值分别是2.4180.016。这表明 A 组的平均值显著大于 B 组。这意味着 A 组的错过机会显著多于 B 组。换句话说,XGBoost 模型比宽神经网络模型错过的机会更多。

如你所见,从 A/B 测试模拟结果来看,A/B 测试为现实世界设置中哪个模型表现更好提供了强大的见解。每个构建数据科学或 AI/ML 模型的人都应该养成一种习惯,不仅基于训练集和测试集评估模型,而且通过 A/B 测试评估模型,以便他们可以了解所构建的模型在现实世界设置中的实际性和适用性。通过短期的小样本 A/B 测试,你可以选择用于即将到来的营销活动的最佳模型。

摘要

在本章中,我们讨论了使用在线购买数据集构建预测模型的大量内容。我们探讨了两种不同的基于树的模型,即随机森林和 GBDT,以及如何构建预测模型来预测谁可能进行转换。使用相同的例子,我们还讨论了如何构建神经网络模型,这些模型是深度学习模型的基础。在构建神经网络模型时,你有很大的灵活性,例如宽网络、深网络或宽深网络。我们在构建神经网络模型时简要提到了激活函数和优化器,但我们建议你深入研究它们如何影响神经网络模型的表现。最后,我们讨论了 A/B 测试是什么,如何进行 A/B 测试,以及如何解释 A/B 测试结果。我们使用我们构建的模型模拟了 A/B 测试,以选择捕捉最多客户转换的最佳模型。

在接下来的章节中,我们将进一步探讨使用 AI/ML 进行精准营销。更具体地说,我们将讨论如何以各种方式构建个性化的产品推荐,以及这如何导致微目标营销策略。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人交流,并在以下地点与超过 5000 名成员一起学习:

packt.link/genai

第七章:个性化产品推荐

随着技术的进步和收集的数据量的增加,个性化无处不在。从流媒体服务,如 Netflix 和 Hulu,到你在手机上看到的营销信息和广告,现在展示给你的大部分内容都是个性化的。在营销中,个性化的或目标营销活动已被证明比通用的或大众营销活动在推动客户参与和转化方面效果显著。

在本章中,我们将讨论如何构建个性化的推荐模型,以便我们能更好地针对客户推荐他们最感兴趣的产品。我们将探讨如何在 Python 中执行市场篮子分析,这有助于营销人员更好地理解哪些商品经常一起购买,如何构建两种方法的协同过滤算法以实现个性化产品推荐,以及为推荐针对个别客户的个性化产品所采取的其他方法。

在本章中,我们将涵盖以下主题:

  • 基于市场篮子的产品分析

  • 基于用户和基于项目的协同过滤

  • 其他常用的推荐方法

基于市场篮子的产品分析

市场篮子分析的经典例子是研究人员发现,购买尿布的客户也倾向于购买啤酒。尽管啤酒和尿布看起来像是太远的商品而无法搭配,但这一发现表明,我们可以从数据中找到不同产品之间隐藏的关联。市场篮子分析的目标是找到这些产品之间的隐藏关系,并有效地为或向客户安排或推荐产品。市场篮子分析有助于回答以下问题:

  • 应该向购买产品 X 的客户推荐哪些产品?

  • 在商店中,哪些产品应该放在一起,以便客户可以轻松找到他们想要购买的产品?

为了回答这些问题,需要找到市场篮子分析的关联规则。简单来说,关联规则通过基于规则的机器学习方法展示一个项集在交易中出现的信心或显著性。一个关联规则有两个部分:先行词,即规则的条件,和结果词,即规则的结果。考虑以下陈述:

“购买尿布的客户很可能也会购买啤酒。”

在这个陈述中,尿布是先行词,啤酒是结果词。使用五个指标来评估这些关联规则的强度:

  • 支持:支持表示一个项集在数据集中出现的频率。计算项集(X, Y)的支持的方程式是:

图片

例如,如果数据中的 10 笔交易中有 3 笔是尿布交易,那么尿布的支持度为 3/10 或 0.3。如果数据中的 10 笔交易中有 2 笔是尿布和啤酒的交易,那么尿布和啤酒的支持度为 2/10 或 0.2。

  • 置信度:置信度是在前导事件 X 发生的情况下,项集(X, Y)发生的条件概率。计算给定前导事件 X 的后续事件 Y 的置信度的公式为:

图片

例如,如果数据中的 10 笔交易中有 3 笔是尿布交易,2 笔是尿布和啤酒的交易,那么在尿布购买的情况下购买啤酒的置信度为 2/3 或 0.67。如果后续事件总是与前导事件一起发生,置信度值将为 1。

  • 提升比:提升比是一个度量项集(X, Y)与前导事件和后续事件独立事件相比同时发生的频率的指标。前导事件 X 和后续事件 Y 的提升比公式为:

图片

例如,如果尿布和啤酒的置信度为 2/3,啤酒的支持度为 5/10,那么尿布对啤酒的提升比为 2/3 除以 5/10,即 20/15 或 4/3。如果前导事件和后续事件是独立的,提升分数将为 1。

  • 杠杆率:杠杆率是一个度量前导事件和后续事件同时发生的频率与它们独立时发生的频率之间差异的指标。杠杆率的公式为:

图片

例如,如果尿布和啤酒在总共 10 笔交易中的 4 笔交易中发生,尿布和啤酒的支持度分别为 0.6 和 0.5,那么杠杆率将是 0.4 减去(0.6 * 0.5),即 0.1。杠杆率的值介于-1 和 1 之间,如果前导事件和后续事件是独立的,杠杆率值将为 0。

  • 信念度:信念度衡量后续事件对前导事件依赖的程度。信念度的公式为:

图片

例如,如果尿布和啤酒之间的置信度为0.67,啤酒的支持度为0.2,意味着在总共 10 笔交易中有 2 笔是啤酒交易,那么信念度大约为2.42。如果前导事件和后续事件是独立的,那么信念度将为 1。另一方面,如果前导事件和后续事件的置信度为 1,或者后续事件总是与前导事件一起发生,那么分母变为 0,信念度值变为无穷大。

在这个基础上,让我们深入探讨如何在电子商务数据集中寻找关联规则。我们将使用在线零售数据集和mlxtend包来展示如何使用 Python 进行市场篮子分析。

源代码和数据: github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/tree/main/ch.7

数据来源: github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/blob/main/ch.7/data.csv

这是原始数据源的链接:archive.ics.uci.edu/dataset/352/online+retail

以下是为安装mlxtend包的命令:

pip install mlxtend 

Apriori 算法 – 寻找频繁项集

Apriori 算法用于识别和生成我们之前讨论的关联规则。我们将通过一个示例来讨论如何在 Python 中使用 Apriori 算法进行市场篮子分析。首先,我们使用以下代码将数据加载到 DataFrame 中:

import pandas as pd
df = pd.read_csv("./data.csv")
df = df.dropna(subset=['CustomerID']) 

一旦运行此代码,我们现在就有所有客户所做的购买。如果你还记得我们之前讨论过的市场篮子分析,两个关键组件是找到项集和找到项集之间的规则。在本节中,我们将专注于找到项集,即商品的组合。

当你运行df["StockCode"].nunique()命令时,你会看到在这个数据集中有 3,684 个独特的商品或产品。正如你可以想象的那样,你可以创建的商品组合的数量会随着商品数量的增加而呈指数增长。所有可能商品组合的数量是:

在我们的数据集中有超过 3,000 个商品,检查所有可能的项集是不切实际的,因为有 2³⁶⁸⁴-1 个项集需要检查。这就是 Apriori 算法发挥作用的地方。直观地说,交易频率低或支持度低的商品或项集在结果中可能价值较低。因此,Apriori 算法提取了被认为足够频繁的项集,这些项集由预定义的支持度阈值确定。

要使用 Apriori 算法找到频繁项集,我们需要将 DataFrame 转换成一种矩阵形式,其中每一行代表客户,每一列代表商品或产品。看看以下代码:

customer_item_matrix = df.pivot_table(
    index='CustomerID',
    columns='StockCode',
    values='Quantity',
    aggfunc='sum'
) 

在这里,我们使用pivot_table函数来创建一个客户到商品的矩阵,每个值将代表每个客户购买的商品的总数量。有了这个客户到商品的矩阵,我们可以使用以下代码运行 Apriori 算法来找到频繁项集:

from mlxtend.frequent_patterns import apriori
frequent_items = apriori(
    customer_item_matrix,
    min_support=0.03,
    use_colnames=True
)
frequent_items["n_items"] = frequent_items["itemsets"].apply(
lambda x: len(x)
) 

如此代码所示,我们正在使用 mlxtend 包中的 apriori 函数。我们使用 min_support 参数定义每个项集所需的最低支持为 0.03,这意味着我们将忽略那些在交易中发生次数少于 3% 的项集。然后,我们添加一个名为 n_items 的列,它简单地计算每个项集中的项目数量。

最终的 DataFrame 看起来如下所示:

图 7.1:频繁项 DataFrame

如果您还记得,项集的可能组合总数是 2³⁶⁸⁴-1。然而,正如您从应用 Apriori 算法的结果中可以看到的,我们现在有 1,956 个项,这是一个可管理的合理数量的项集,我们可以检查其关联规则。

关联规则

使用我们构建的频繁项集,我们现在可以生成关联规则,这些规则将告诉我们哪些项集经常一起购买。请看以下代码:

from mlxtend.frequent_patterns import association_rules
rules = association_rules(
    frequent_items,
    metric="confidence",
    min_threshold=0.6,
    support_only=False
) 

在这里,我们使用 mlxtend 包中的 association_rules 函数。有几个关键参数需要考虑:

  • metric:此参数定义了用于选择关联规则要使用的指标。在这里,我们使用 confidence 来选择具有高 confidence 的关联规则,但如果您对找到具有高 lift 的规则感兴趣,也可以使用 lift

  • min_threshold:此参数定义了基于您选择的指标选择关联规则的阈值。在这里,我们只对找到 confidence 超过 60% 阈值的规则感兴趣。

  • support_only:如果您只对计算规则的 support 感兴趣,或者由于某些数据缺失而无法计算其他指标,可以将此参数设置为 True。在这里,我们将其设置为 False,因为我们对找到具有高 confidence 的规则感兴趣。

这些规则的输出应如下所示:

图 7.2:基于 confidence 超过 60% 的关联规则

关联规则输出包含先行项、后续项和关键指标,例如 supportconfidencelift。您可以按每个指标排序,并生成关于哪些项集具有紧密关系的见解。例如,您可能希望找到具有最高 lift 的前 20 个项集或具有最高 confidence 的前 10 个项集。您还可以可视化这些关系,以便您可以轻松查看关系及其强度。请看以下代码:

most_lift = rules.sort_values(
    by="lift", ascending=False
).head(20).pivot_table(
    index='antecedents',
    columns='consequents',
    values='lift',
    aggfunc='sum'
)
most_lift.index = [
    " + ".join([
        df.loc[df["StockCode"] == item]["Description"].unique()[0]
        for item in list(x)
    ]) for x in most_lift.index
]
most_lift.columns = [
    " + ".join([
        df.loc[df["StockCode"] == item]["Description"].unique()[0]
        for item in list(x)
    ]) for x in most_lift.columns
] 

在这里,我们首先使用 sort_values 函数选择具有最高 lift 的前 20 个规则。然后,我们将表格进行转置,使得每一行是先行项,每一列是后续项,单元格的值是 lift。可以使用热图轻松可视化这些规则的强度。以下代码可以用于可视化这 20 个具有最高 lift 的规则:

ax = plt.subplot()
sns.heatmap(
    most_lift,
    annot=True,
    annot_kws={"size": 6},
    # fmt=".1f",
    ax=ax
)
ax.set_title("Top 20 Rules by Lift")
ax.set_xlabel("Consequent")
ax.set_ylabel("Antecedent")
ax.yaxis.set_ticklabels(list(most_lift.index), fontsize=6)
ax.xaxis.set_ticklabels(list(most_lift.columns), fontsize=6)
plt.show() 

这将生成如下所示的热图:

图片

图 7.3:具有最高升力的前 20 个关联规则

在这个图表中,颜色越浅,给定规则的升力就越高。例如,当前提项目集是GREEN REGENCY TEACUP AND SAUCERREGENCY TEA PLATE ROSES,而结果项目集是ROSES REGENCY TEACUP AND SAUCERREGENCY TEA PLATE GREEN时,升力约为 26,是最高的。另一方面,当前提项目集是ROSES REGENCY TEACUP AND SAUCERREGENCY TEA PLATE ROES,而结果项目集是GREEN REGENCY TEACUP AND SAUCERREGENCY TEA PLATE GREEN时,升力约为 20,是前 20 条规则中最低的。

从这个例子中可以看出,通过关联规则,我们可以轻松地找出哪些产品是共同购买的,以及它们之间的关系。这可以用于个性化营销,根据这些规则推荐某些产品。如果一个客户购买了项目集 A,那么自然可以推荐项目集 B,因为关联规则表明 A 和 B 经常一起购买,具有显著性。这比在营销信息中盲目推荐随机产品集,希望客户对购买它们表示兴趣,更接近一步推荐个性化的产品集。

最后,如果你还记得,升力与置信度呈线性关系,与支持度呈反向关系,因为升力定义为:

图片

这个关系可以通过我们用mlxtend包找到的规则轻松展示。看看下面的代码:

fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()
rules[["support","lift"]].plot(
    kind="scatter", x="support", y="lift", ax=ax1
)
rules[["confidence","lift"]].plot(
    kind="scatter", x="confidence", y="lift", ax=ax2, color="orange", alpha=0.3
)
ax1.legend(["lift vs. support",], loc="upper right")
ax2.legend(["lift vs. confidence",], loc="upper left")
plt.grid()
plt.show() 

在这里,y 轴上有升力值,x 轴上有支持度和置信度值。图表将如下所示:

图片

图 7.4:升力与置信度以及升力与支持之间的关系

从这个图表中可以看出,x 轴的顶部显示了置信度值,升力与置信度的散点图显示了一种线性关系,即随着置信度值的增加,升力值也增加。另一方面,x 轴的底部显示了支持度值,升力与支持度的散点图显示了一种反向关系,即随着支持度值的增加,升力值减少。

协同过滤

在构建推荐系统中有各种方法,通常有多种方法参与其中。在构建推荐系统中,一些常用的基于 AI/ML 的方法包括:

  • 协作过滤:这种方法使用之前用户的行为,如他们查看的页面、购买的产品或之前给出的评分。该算法利用这类数据来找到与用户之前表示兴趣的产品或内容相似的产品或内容。例如,如果用户在流媒体平台上观看了几部惊悚电影,可能会向这位用户推荐其他一些惊悚电影。或者,如果一位客户在电子商务平台上购买了连衣裙衬衫和连衣裙鞋,可能会向这位客户推荐连衣裙裤。协作过滤算法通常基于用户或项目之间的相似性构建:

    • 基于用户的协作过滤使用数据来根据之前查看的页面或购买的产品找到相似的用户。

    • 基于项目的协作过滤使用数据来寻找经常一起购买或查看的项目。

  • 基于内容的过滤:正如其名所示,这种方法使用产品、内容或用户的特征。协作过滤算法侧重于用户到用户或项目到项目的相似性,而基于内容的过滤算法侧重于特征相似性,例如流派、关键词和元数据。例如,如果你正在推荐观看的电影,这种方法可能会查看电影的描述、流派或演员,并推荐那些符合用户偏好的电影。另一方面,如果你正在推荐时尚商品,那么这种方法可能会查看产品类别、描述和品牌,以向用户推荐某些商品。

  • 预测建模:如第六章所述,也可以为推荐系统构建预测模型。用户之前查看的内容、他们购买的产品或网页会话历史可以作为识别用户很可能感兴趣查看或购买的项目特征。这些预测模型的概率输出可以用来对项目进行排序,以便在显示其他不太可能的项目之前向用户展示更可能的项目。

  • 混合模型:通常,推荐系统会结合之前提到的所有方法来构建。将不同的推荐方法混合使用可以帮助提高推荐准确性,这是单一方法推荐系统可能遗漏的。

在本章中,我们将重点关注协同过滤算法,因为它作为许多推荐系统常用的骨干算法,并且更具体地,我们将探讨如何使用基于用户的协同过滤和基于商品的协同过滤算法来构建推荐系统。这种技术在推荐系统中经常被使用,因为它以非常直观的方式很好地捕捉了用户和商品之间的交互。许多在业务中推荐至关重要的组织,如 Netflix、Amazon 和 Spotify,都将协同过滤算法作为其推荐系统的一部分。

协同过滤算法的关键是找到相似的用户或商品。可以有多种度量标准来衡量用户或商品之间的相似性,例如欧几里得距离、曼哈顿距离或 Jaccard 距离。然而,余弦相似度是协同过滤中最常用的相似性度量之一,因为它更多地关注距离的定向相似性,而不是距离的大小。

余弦相似度简单地说就是两个向量之间角度的余弦值。在这里,向量可以是协同过滤算法中的用户向量或商品向量。由于余弦相似度在高维空间中具有优势,它通常被选为协同过滤算法的距离度量。计算两个向量之间余弦相似度的方程如下:

图片

在这个方程中,V[1][i]和V[2][i]代表每个向量中的每个商品,这些向量可以是用户向量或商品向量。这些余弦相似度值介于-1 和 1 之间。如果两个向量相似,余弦相似度值将接近 1;如果两个向量独立,则余弦相似度值将为 0;如果两个向量是相反向量,则余弦相似度值将接近-1。

要构建协同过滤算法,我们首先需要构建客户-商品矩阵。我们将使用与市场篮子分析相同的代码,如下所示:

customer_item_matrix = df.pivot_table(
    index='CustomerID',
    columns='StockCode',
    values='Quantity',
    aggfunc='sum'
) 

如前所述,这个矩阵显示了每个客户(行)为每个商品(列)购买的量。我们不是使用商品购买的原始数量,而是将要使用独热编码,使得如果某个客户购买了某个商品,则值为 1,如果没有购买,则值为 0,如下面的代码所示:

customer_item_matrix = customer_item_matrix.map(
    lambda x: 1 if x > 0 else 0
) 

customer_item_matrix矩阵应该看起来像下面这样:

图片

图 7.5:客户-商品矩阵

如预期的那样,每一行代表一个特定用户是否购买了每个商品。这个矩阵将成为我们在以下章节中构建基于用户协同过滤和基于商品协同过滤算法的基础矩阵。

基于用户的协同过滤

构建基于用户的协同过滤模型的第一步是构建相似用户矩阵。看看下面的代码:

from sklearn.metrics.pairwise import cosine_similarity
user_user_sim_matrix = pd.DataFrame(
    cosine_similarity(customer_item_matrix)
)
user_user_sim_matrix.columns = customer_item_matrix.index
user_user_sim_matrix['CustomerID'] = customer_item_matrix.index
user_user_sim_matrix = user_user_sim_matrix.set_index('CustomerID') 

如果你还记得,余弦相似度度量是协同过滤算法中最常用的相似度指标之一。在这里,我们使用 scikit-learn 包的cosine_similarity函数来计算用户之间的余弦相似度。新创建的变量user_user_sim_matrix将是一个矩阵,其中每一行和每一列代表一个用户,以及两个用户之间的相似度。

看看下面的示例:

user_user_sim_matrix.loc[
    [12347.0, 12348.0, 12349.0, 12350.0, 12352.0],
    [12347.0, 12348.0, 12349.0, 12350.0, 12352.0]
] 

图片

图 7.6:用户之间的相似性样本

这个示例显示了用户之间的余弦相似度指标。正如预期的那样,对角线上的值是 1,因为它们代表用户与其自身的相似度。例如,用户1234912350的余弦相似度约为0.057,而用户1234912352的余弦相似度为0.138。这表明用户12349与用户12352的相似度高于与用户12350的相似度。这样,你可以通过用户与目标用户的相似度来识别和排名用户。

让我们选择一个客户来看看我们如何可能构建一个推荐系统。我们将选择用户 ID14806作为这个练习的示例:

TARGET_CUSTOMER = 14806.0
print("Similar Customers to TARGET")
user_user_sim_matrix.loc[
TARGET_CUSTOMER
].sort_values(ascending=False).head(10) 

在这里,我们通过在user_user_sim_matrix矩阵中选择TARGET_CUSTOMER并按降序排序值,选择具有最高余弦相似度测量的前 10 个用户。输出应如下所示:

图片

图 7.7:与目标客户相似的客户

在这里,你可以看到客户13919与目标客户14806最相似,客户12561排在第二位,客户13711排在第三位。

通过最相似客户进行推荐

向目标客户推荐产品的最简单方法就是查看目标客户已经购买的商品,并将它们与最相似客户13919进行比较。然后,推荐目标客户尚未购买但最相似客户已经购买的商品。这是基于之前的讨论,即相似的客户可能具有相似的行为或兴趣,并且他们可能购买相似的产品。

要做到这一点,我们可以遵循以下步骤:

  1. 我们将首先找出目标客户已经购买的商品,使用以下代码:

    items_bought_by_target = set(
        df.loc[
            df["CustomerID"] == TARGET_CUSTOMER
        ]["StockCode"].unique()
    ) 
    

这将获取目标客户购买的所有商品,并将它们存储在items_bought_by_target变量中。

  1. 接下来,我们需要获取与最相似客户13919购买的所有商品。看看下面的代码:

    items_bought_by_sim = set(
        df.loc[
            df["CustomerID"] == 13919.0
        ]["StockCode"].unique()
    ) 
    

这将找出最相似客户13919购买的所有商品,并将它们存储在items_bought_by_sim变量中。

  1. 使用set操作,很容易找出最相似客户购买但目标客户未购买的商品,如下所示代码所示:

    items_bought_by_sim_but_not_by_target = items_bought_by_sim - items_bought_by_target 
    

如您所见,我们只是从items_bought_by_target集合中减去另一个集合items_bought_by_sim,这将得到所有目标客户尚未购买但最相似客户已购买的商品,并将它们存储在items_bought_by_sim_but_not_by_target中。

  1. 我们可以使用以下代码获取这些商品的详细信息:

    df.loc[
        df["StockCode"].isin(items_bought_by_sim_but_not_by_target)
    ][["StockCode", "Description"]].drop_duplicates() 
    

此输出应如下所示:

图 7.8:推荐给目标客户的项目

这是购买但尚未被目标客户购买的最相似客户13919购买的商品及其描述列表。在推荐产品的最简单方法中,此列表可以显示给目标客户作为推荐商品。

由于这两个客户在过去购买相似商品时表现出相似的兴趣,因此目标客户购买这些商品的可能性比随机选择产品要高。您可以为每个客户应用相同的流程,并根据最相似客户的购买历史构建推荐产品集合。

根据相似客户购买的前列产品进行推荐

另一种方法是按照最相似客户购买产品的频率来对产品进行排名。

我们可以从以下代码开始:

top10_similar_users = user_user_sim_matrix.loc[
    TARGET_CUSTOMER
].sort_values(
    ascending=False
).head(11).to_dict()
potential_rec_items = {}
for user, cos_sim in top10_similar_users.items():
    if user == TARGET_CUSTOMER:
        continue

    items_bought_by_sim = list(set(
        df.loc[
            df["CustomerID"] == user
        ]["StockCode"].unique()
    ))
    for each_item in items_bought_by_sim:
        if each_item not in potential_rec_items:
            potential_rec_items[each_item] = 0
        potential_rec_items[each_item] += cos_sim
potential_rec_items = [(key, val) for key, val in potential_rec_items.items()]
potential_rec_items = sorted(
    potential_rec_items, key=lambda x: x[1], reverse=True
) 

在这里,我们首先通过余弦相似度得到前 10 个最相似客户。然后,对于每个相似客户,我们遍历那些由相似客户购买但目标客户未购买的商品。我们计算相似客户购买指定产品的次数,按购买频率降序排序,并将结果存储在potential_rec_items变量中。结果应如下所示:

图 7.9:相似客户购买的前列产品

这表明 10 个客户中有 7 个购买了2150021499产品,10 个客户中有 4 个购买了21498POST产品,等等。我们可以通过以下代码查询从这些产品 ID 获取产品描述:

top_10_items = [x[0] for x in potential_rec_items[:10]]
df.loc[
    df["StockCode"].isin(top_10_items)
][["StockCode", "Description"]].drop_duplicates().set_index(
    "StockCode"
).loc[top_10_items] 

此输出应如下所示:

图 7.10:相似客户购买的前列产品

然而,这种方法并没有考虑到每个客户与目标客户之间的相似度或差异度。它只是对每个产品的前 10 个相似客户进行了计数,并基于简单的总和进行推荐。

由于我们为前 10 个相似客户中的每一个都设置了相似度度量,因此在我们推荐产品时,我们也可能想要考虑这一点。我们不仅可以进行简单的计数,还可以进行加权计数。请看以下代码:

potential_rec_items = {}
for user, cos_sim in top10_similar_users.items():
    if user == TARGET_CUSTOMER:
        continue

    items_bought_by_sim = list(set(
        df.loc[
            df["CustomerID"] == user
        ]["StockCode"].unique()
    ))
    for each_item in items_bought_by_sim:
        if each_item not in potential_rec_items:
            potential_rec_items[each_item] = 0
        potential_rec_items[each_item] += cos_sim
potential_rec_items = [(key, val) for key, val in potential_rec_items.items()]
potential_rec_items = sorted(
    potential_rec_items, key=lambda x: x[1], reverse=True
) 

如您可能注意到的,与之前的代码不同的是potential_rec_items[each_item] += cos_sim。我们不再只是计数,现在我们正在添加一个余弦相似度指标,该指标衡量每个客户与目标客户相似或不同的程度。

当我们根据余弦相似度查询前 10 个物品时,结果如下所示:

图 7.11:类似客户购买的前列产品(按余弦相似度加权)

在这个例子中,简单计数的结果与加权计数的结果相同。您不仅可以做余弦相似度的加权求和,还可以做加权平均。您还有许多其他方法可以聚合分数并推荐产品,所以富有创意是构建最终推荐输出的关键,这个输出是基于余弦相似度度量的。

如您从这些示例中可以看到,我们可以构建基于过去表现出相似行为的客户的产品集进行推荐。通常情况下,有相似口味的人会购买相似的商品,所以当根据客户群中的相似性推荐产品时,基于用户的协同过滤效果很好。除了基于客户相似性进行推荐外,我们还可以根据单个物品与其他物品的相似性进行推荐。在下一节中,我们将讨论如何基于物品的协同过滤构建推荐系统。

基于物品的协同过滤

与基于用户的协同过滤的情况一样,构建基于物品的协同过滤算法的关键起点是构建一个物品-物品相似度矩阵。从我们之前构建的客户-物品矩阵中,我们可以使用以下代码来构建一个物品-物品相似度矩阵:

item_item_sim_matrix = pd.DataFrame(
    cosine_similarity(customer_item_matrix.T)
) 

如此代码所示,我们首先转置客户-物品矩阵,customer_item_matrix,这将使其成为一个物品-客户矩阵,其中每一行是一个物品,每一列是一个客户,每个值是 0 或 1,表示给定列是否购买了给定物品。然后,我们使用cosine_similarity函数计算余弦相似度,并将结果保存为名为item_item_sim_matrix的 pandas DataFrame 变量。

结果应该看起来像以下这样:

图 7.12:物品-物品相似度矩阵

根据最相似物品进行推荐

基于项目相似性生成推荐的最简单方法是为给定项目找到最相似的项目并推荐它们。当一个人查看某个产品时,您想展示相关或相似的项目,可以使用这种方法。例如,当您在亚马逊上搜索产品并点击搜索页面上的某个产品时,亚马逊将在页面底部显示经常一起购买的相关或相似项目。这就是基于项目的协同过滤可以发挥作用的地方,更具体地说,当您想根据一个给定的产品推荐产品时。

使用我们的示例数据集,假设一位客户正在查看一个产品,“中号陶瓷顶盖储物罐”,其产品代码为23166。从我们刚刚构建的项目到项目矩阵item_item_sim_matrix中,我们可以使用以下代码找到最相似的 10 个项目:

most_similar_items = item_item_sim_matrix.loc[
    "23166"
].sort_values(ascending=False).head(10) 

如您在这段代码中所见,我们通过按余弦相似度降序排列项目来选择最相似的 10 个项目。输出结果应如下所示:

图 7.13:与产品 23166 最相似的 10 个项目

我们也可以根据这些产品代码查询描述,如下所示:

rec_items = [
    x for x in most_similar_items.index if x != "23166"
]
df.loc[
    df['StockCode'].isin(rec_items),
    ['StockCode', 'Description']
].drop_duplicates().set_index('StockCode').loc[rec_items] 

如您所见,我们排除了产品23166,因为它是要查看的目标项目或客户当前查看的项目,并展示了其余的 10 个最相似的项目。输出结果应如下所示:

图 7.14:包括自身在内的与产品 23166 最相似的 10 个项目

如您所想象,当客户查看目标产品时,我们可以在页面上展示这 10 个项目,包括它本身。这样,我们展示了最相似或最常一起购买的项目,以便客户有更多选择或更多商品可以购买。

根据购买历史推荐

在之前基于单个项目推荐产品的例子基础上,我们还可以为多个项目构建基于项目的协同过滤推荐系统。特别是当您可能正在发送营销邮件或新闻通讯时,您可能希望随邮件或通讯发送产品推荐。在这种情况下,考虑客户的购买历史将很有用,例如他们购买过哪些产品,他们在线查看过哪些产品页面,或者他们放入购物车中的产品。使用这些信息,我们可以利用基于项目的协同过滤算法为每位客户构建个性化的产品推荐,这些推荐对每位客户都是不同的。

以我们的示例数据集为例,假设一位客户购买了三个产品,产品代码分别为231662272023243。在我们的数据集中,这些项目是“3 个蛋糕托盘储物设计套装”、“中号陶瓷顶盖储物罐”和“茶咖啡糖罐储物套装”。您可以使用以下代码为这些项目获取最相似的 10 个项目:

item_item_sim_matrix[[
    "23166", "22720", "23243"
]].mean(axis=1).sort_values(
    ascending=False
).head(10) 

如您从以下代码中看到的,我们查询了客户购买的那 3 个物品的物品到物品矩阵,并计算了余弦相似度的平均值。然后,我们将这些平均值按降序排序,以获取给定 3 个物品的最相似的前 10 个物品。输出应如下所示:

图片

图 7.15:与给定 3 个物品最相似的 10 个物品

排除已经购买的商品,产品22722排在第一位,是与给定项目集最相似的物品,其次是23165。我们可以查询数据以获取这些最相似的前 10 个物品的产品描述。请看以下代码:

rec_items = [
    x for x in item_item_sim_matrix[[
        "23166", "22720", "23243"
    ]].mean(axis=1).sort_values(ascending=False).head(13).index
    if x not in ["23166", "22720", "23243"]
]
df.loc[
    df['StockCode'].isin(rec_items),
    ['StockCode', 'Description']
].drop_duplicates().set_index('StockCode').loc[rec_items] 

在这里,我们从推荐列表中排除了客户已经购买的那 3 个物品,并检索了与这 3 个物品最相似或最常一起购买的顶级 10 个物品。此查询的输出应如下所示:

图片

图 7.16:与给定 3 个物品最相似的 10 个物品

如您所想,这些基于物品协同过滤算法结果的产品推荐可以用于任何营销活动。如果您正在构建电子邮件营销活动,您可以使用这个基于物品的协同过滤算法来选择基于先前购买、页面浏览或购物车项目的前相似产品,并将它们作为营销电子邮件的一部分。您还可以在网页上设置弹出窗口,以便当用户下次登录您的在线页面时使用。对这些商品提供折扣或其他促销活动也可以提高转换率。

您可以以多种方式应用基于用户和基于物品的协同过滤来构建推荐系统。随着您在推荐系统中的进展,跟踪您的推荐表现并调整您对它们的使用方式将是明智的。您很可能会想要跟踪您推荐的项目中有多少已经转换。

如在第二章中讨论 KPI 时所述,跟踪推荐项目中的转换和其他 KPI 可以告诉您您的推荐系统的有效性以及哪种方法更有效。

其他常用的推荐方法

我们已经深入讨论了市场篮子分析和协同过滤来构建个性化推荐系统。然而,还有许多其他方法可以构建这些推荐系统。如前所述,一些常见的基于 AI/ML 的方法是关联规则和协同过滤算法,这些我们在本章中已经介绍;预测建模方法也经常被使用,如今,所有这些方法的混合是构建更全面的推荐系统的典型方法。

不仅存在 AI/ML 驱动的推荐系统方法,还可以有各种其他方式来推荐产品或内容,甚至无需使用 AI/ML。以下是一些常用的推荐方法:

  • 畅销书或热门观看:正如其名所示,基于畅销产品或最常观看的内容的推荐仍然被频繁使用。这有助于新用户或客户通过轻松查看他人查看或购买最多的内容来熟悉您的产品或平台。这也可以是构建您的入门级营销内容的好方法。

  • 趋势:与畅销书类似,趋势商品显示了在特定时刻流行的内容。可能会有一些事件,例如某些地区的灾难、特定时刻的突发新闻或社区周围的假日活动,这些事件会偶尔激发客户的兴趣。对这些事件进行调整是明智的,因为这些特殊事件会触发某些客户行为,并且可以成为极佳的营销机会。

  • 新品上市:作为营销人员,您很可能不想错过推广新产品的机会。现有客户或新客户通常会被新品吸引,这可以是一个很好的营销机会,以保留现有客户,同时吸引新客户。通过向对类似商品表示过兴趣的客户推荐新品,营销活动可以取得巨大成功。

  • 促销:您不仅可以根据流行度或相关性推荐产品或内容,还可以推荐正在促销的产品或内容。客户通常会被特别优惠所吸引,您希望尽可能积极地展示和营销特别促销。这些是清理过剩库存、提高品牌知名度、吸引新客户和保留不活跃客户的好方法。

正如您所看到的,您可以在利用 AI/ML 驱动的技术基础上,以多种方式构建推荐系统。鉴于竞争环境和全球范围内几乎所有企业进行的营销活动丰富多样,仅使用一种方法来推荐产品或内容不太可能取得成功。您拥有的推荐系统越全面,您在吸引和保留客户方面就越成功。在设计推荐系统时,明智的做法是考虑本章中提到的所有方法,并在适当的时间和地点应用它们。

摘要

在本章中,我们讨论了构建个性化产品推荐系统。首先,我们讨论了如何通过分析哪些项目集经常一起购买来识别产品之间的关系。我们介绍了如何使用 Apriori 算法和关联规则在 Python 中进行市场篮子分析。然后,我们深入探讨了构建推荐系统的一种 AI/ML 驱动方法。我们看到了如何使用基于用户和基于物品的协同过滤算法来识别相似的用户或物品以及经常一起购买的产品。反过来,这些发现可以用来推荐其他客户很可能感兴趣并购买的产品。最后,我们讨论了可用于推荐产品和内容的各种其他方法。我们展示了如何结合非 AI/ML 方法可以导致一个更全面和多样化的推荐系统。

在下一章中,我们将继续讨论个性化的精准营销努力。更具体地说,我们将探讨如何在 Python 中进行客户细分,以及为什么深入了解您客户群中不同的客户细分有助于并影响您营销活动的成功与失败。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人相聚,并在以下超过 5000 名成员的陪伴下学习:

packt.link/genai

第八章:使用机器学习进行客户细分

随着关于客户特征和行为数据的日益丰富,用更深入的见解来接近客户变得更加容易。从分析我们在第三章中讨论的客户参与背后的驱动因素,到理解个人客户可能喜欢哪些具体产品,这是我们第七章中提到的,这些方法的假设是基于存在某些行为方式相似的客户群体这一事实。

由于定向营销方法已被证明比大众营销更有效,因此客户细分一直是该领域经常讨论的话题。此外,随着无 cookie 世界的到来,第一方数据预计将发挥更加关键的作用。因此,基于客户细分(如地理细分、人口统计细分或兴趣主题细分)的策略,这些细分在浏览器 cookie 不可用的情况下仍然可用,对于成功至关重要。

在本章中,我们将涵盖以下主题:

  • 一次性客户与回头客

  • 使用 K-means 聚类和购买行为进行客户细分

  • 使用大型语言模型LLMs)和产品兴趣进行客户细分

一次性客户与回头客

根据提供了一些非常清晰的指标的BIA 顾问服务,回头客平均比新客户多花费 67%。此外,BIA 顾问服务进行的一项调查表明,超过一半的调查企业收入来自回头客,而不是新客户。这表明保留现有客户与扩大客户基础同样重要。然而,企业往往为了获取新客户而牺牲客户服务。

BIA 顾问服务报告

www.bia.com/small-business-owners-shift-investment-from-customer-acquisition-to-customer-engagement-new-report-by-manta-and-biakelsey/

保留客户的需求

保留客户对业务来说如此重要的几个好处表明了原因:

  • 投资减少:第一个显而易见的原因是新客户成本更高。如果您还记得第二章中典型的客户生命周期,您需要投入资本和营销资源来提高潜在新客户的品牌知名度,与潜在客户建立业务联系,然后最终将他们转化为付费客户。

图 8.1:客户生命周期

对于现有客户,您可以跳过这些步骤,专注于通过提供优质的客户服务和介绍他们感兴趣的产品,将他们作为回头客保留下来。获取新客户通常比保留现有客户成本高出数倍。

  • 更高的可靠性: 重复客户为你的业务带来了更可靠和可重复的收入。如前所述,重复客户通常贡献了超过一半的业务收入,并且比新客户花费更多。随着你提供现有客户喜欢的产品或服务,以及你提供更好的客户服务,你的客户可能会对你的品牌忠诚,并继续购买产品。

例如,如果你在销售宠物产品,比如宠物食品或宠物玩具,并且他们喜欢你的产品,他们下个月可能会回来购买更多,甚至订阅以每月获得宠物食品的配送。这导致了一个可靠且可重复的收入流,这将加强你业务的现金流,你可以用这些资金投资更多到你的产品上,这将带来更多的收入。这开始了你业务的积极循环。

  • 建立品牌忠诚度: 对你的业务忠诚的重复客户会带来更多的新客户。如你可能在 第二章 中回忆的那样,忠诚的客户充当你的品牌大使和营销代理,他们传播关于你业务的信息并吸引新客户。无需花费更多的营销费用,这些忠诚的客户就会推广你的业务并吸引新客户。

拥有一个强大的重复客户基础还有许多其他微妙的好处,但这些都是拥有重复客户最明显的三个好处,并展示了它们如何显著帮助业务。

分析保留客户的影响

让我们看看一个实际例子,看看这些重复客户与新客户相比对业务产生的影响:

源代码和数据: github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/tree/main/ch.8

数据来源: archive.ics.uci.edu/dataset/352/online+retail

和往常一样,我们将首先将数据导入到一个 pandas DataFrame 中。看看下面的代码:

import pandas as pd
df = pd.read_csv("./data.csv")
df = df.dropna()
df = df.loc[
    df["Quantity"] > 0
] 

这里,我们将数据加载到一个 pandas DataFrame,df 中。因为我们只对比较新客户和重复客户感兴趣,我们将使用 dropna 函数删除包含 NaN 值的行,并通过 df["Quantity"] > 0 过滤只取至少购买了一件或更多商品的客户。

  1. 然后,我们将创建以下额外的变量:

    • 销售额: 通过简单地将客户购买的数量乘以单个商品的价格,我们可以得到每个订单的总销售额。在下面的代码中,我们创建了一个名为 Sales 的新列,它包含每个订单的总销售额:

      df["Sales"] = df["Quantity"] * df["UnitPrice"]. 
      
    • 月份变量:为了确定一个客户是否是新客户,我们需要考虑数据的时间范围。如果一个客户之前没有购买任何商品,那么这个客户将被视为新客户。另一方面,如果一个客户之前购买过商品,那么我们将这个客户视为回头客。在这个练习中,我们将查看月度数据,这需要我们创建一个变量来表示发票是在哪个月创建的。在下面的代码中,我们将InvoiceDate列转换为datetime类型,并将InvoiceDate转换为每个月。例如,日期2011-02-23将被转换为2011-02-01

      df["InvoiceDate"] = pd.to_datetime(df["InvoiceDate"])
      df["month"] = df["InvoiceDate"].dt.strftime("%Y-%m-01") 
      
  2. 现在我们有了这两个变量,我们可以开始分析销售是否来自新客户或回头客。看看下面的代码:

    monthly_data = []
    for each_month in sorted(df["month"].unique()):
        up_to_last_month_df = df.loc[
            df["month"] < each_month
        ]
        this_month_df = df.loc[
            df["month"] == each_month
        ]
        curr_customers = set(this_month_df["CustomerID"].unique())
        prev_customers = set(up_to_last_month_df["CustomerID"].unique())
    
        repeat_customers = curr_customers.intersection(prev_customers)
        new_customers = curr_customers - prev_customers
    
        curr_sales = this_month_df["Sales"].sum()
    
        sales_from_new_customers = this_month_df.loc[
            this_month_df["CustomerID"].isin(new_customers)
        ]["Sales"].sum()
        sales_from_repeat_customers = this_month_df.loc[
            this_month_df["CustomerID"].isin(repeat_customers)
        ]["Sales"].sum()
    
        avg_sales_from_new_customers = this_month_df.loc[
            this_month_df["CustomerID"].isin(new_customers)
        ]["Sales"].mean()
        avg_sales_from_repeat_customers = this_month_df.loc[
            this_month_df["CustomerID"].isin(repeat_customers)
        ]["Sales"].mean()
    
        monthly_data.append({
            "month": each_month,
    
            "num_customers": len(curr_customers),
            "repeat_customers": len(repeat_customers),
            "new_customers": len(new_customers),
    
            "curr_sales": curr_sales,
            "sales_from_new_customers": sales_from_new_customers,
            "sales_from_repeat_customers": sales_from_repeat_customers,
            "avg_sales_from_new_customers": avg_sales_from_new_customers,
            "avg_sales_from_repeat_customers": avg_sales_from_repeat_customers,
        }) 
    

让我们更仔细地看看这段代码。我们首先遍历month变量中的每个月。对于每次迭代,我们找到给定月份的唯一客户,并将它们存储为一个集合,命名为curr_customers。我们同样为过去客户做同样的操作,通过获取到给定月份的唯一客户,并将它们存储为一个集合,命名为prev_customers。基于这两个变量,我们可以通过一些集合操作来识别新客户和回头客:

  1. 首先,我们找到curr_customersprev_customers的交集,这代表回头客,因为我们已经在销售数据中看到了这些客户。

  2. 接下来,我们从curr_customers集合中减去prev_customers集合,这给出了新客户,因为这些是我们之前没有见过的客户。通过这些操作,我们已经成功识别了新客户和回头客。

基于这些prev_customerscurr_customers集合,我们可以找到新客户和回头客带来的收入。使用isin函数,我们选择与new_customers集合中的 ID 匹配的CustomerIDs,通过将这些客户的全部销售额相加来计算新客户的总销售额,并通过取这些客户的全部销售额的平均值来计算新客户的平均销售额。同样,使用isin函数,我们选择与repeat_customers集合中的 ID 匹配的CustomerIDs,通过将这些客户的全部销售额相加来计算回头客的总销售额。我们通过取这些客户的全部销售额的平均值来计算回头客的平均销售额。我们将这些数据保存到一个变量中,名为monthly_data

  1. 我们进行最后一组计算,如下所示,并将准备好查看新客户和回头客之间的差异:

    monthly_data_df = pd.DataFrame(monthly_data).set_index("month").iloc[1:-1]
    monthly_data_df["repeat_customer_percentage"] = monthly_data_df["repeat_customers"]/monthly_data_df["num_customers"]
    monthly_data_df["repeat_sales_percentage"] = monthly_data_df["sales_from_repeat_customers"]/monthly_data_df["curr_sales"] 
    

这段代码只是将数据转换成pandas DataFrame,并计算有多少比例的客户是回头客,以及有多少比例的销售来自回头客。

现在我们已经完成了,让我们使用以下代码查看每月客户数量以及新客户和回头客之间的细分:

ax = monthly_data_df[[
    "new_customers", "repeat_customers"
]].plot(kind="bar", grid=True, figsize=(15,5))
(monthly_data_df["repeat_customer_percentage"]*100).plot(
    ax=ax, secondary_y=True, color="salmon", style="-o"
)
ax.right_ax.legend()
ax.right_ax.set_ylim([0, 100.0])
ax.right_ax.set_ylabel("repeat customer percentage (%)")
ax.set_ylabel("number of customers")
ax.set_title("number of new vs. repeat customers over time")
plt.show() 

这应该生成以下图表:

图 8.2:新客户与回头客的数量对比

每个时间段的左侧条形表示每个月的新客户数量,右侧条形表示回头客的数量。正如你所看到的,回头客的构成随着时间的推移而增长,新客户的流入量也存在某种周期性。我们在年初和年底看到更多的新客户,而在六月至八月夏季期间有所下降。

线形图显示了每个月客户中回头客所占的百分比,正如这个图表所暗示的,它从 2011 年 1 月的大约 40%增长到 2011 年 11 月的大约 80%。

这表明这是一个非常健康的业务。它显示了来自已经从这个业务中进行过购买的客户持续的需求和购买。回头客的数量持续增长,这表明这个业务提供的产品和服务持续吸引那些曾经与这个业务互动过的客户。对于一个缺乏吸引人的产品以及/或者良好客户服务的业务,回头客的数量通常会减少。不过,这里需要注意的是,新客户的流入率相对稳定,并没有增长。当然,这比随着时间的推移新客户数量减少要好,但这表明有增长潜力来吸引更多的新客户。鉴于有一个健康的回头客和重复购买客户群,营销人员可以更多地关注这个业务的新客户获取。

同样,让我们看看新客户和回头客的销售金额。看看以下代码:

ax = (monthly_data_df[[
    "sales_from_new_customers", "sales_from_repeat_customers"
]]/1000).plot(kind="bar", grid=True, figsize=(15,5))
(monthly_data_df["repeat_sales_percentage"]*100).plot(
    ax=ax, secondary_y=True, color="salmon", style="-o"
)
ax.set_ylabel("sales (in thousands)")
ax.set_title("sales from new vs. repeat customers over time")
ax.right_ax.legend()
ax.right_ax.set_ylim([0, 100.0])
ax.right_ax.set_ylabel("repeat customer percentage (%)")
plt.show() 

这段代码生成以下图表:

图 8.3:新客户与回头客的销售对比

与之前类似,左侧的条形表示新客户的销售额,右侧的条形表示回头客的销售额。正如之前在许多客户比较中看到的那样,回头客的销售额超过了新客户的销售额。这表明回头客有很强的持续重复收入。回头客的销售额百分比在 2011 年 11 月达到了 80%以上。这在我们之前讨论过回头客通常占企业收入一半以上时是预料之中的。之前讨论并报告的另一个观点是由BIA Advisory Services提出的,即回头客通常比新客户多花费 67%。

现在让我们通过比较新客户和回头客的平均月销售额来查看我们的数据对这个业务说了什么。看看以下代码:

monthly_data_df["repeat_to_new_avg_sales_ratio"] = (
    monthly_data_df["avg_sales_from_repeat_customers"]
    /
    monthly_data_df["avg_sales_from_new_customers"]
)
ax = monthly_data_df[[
    "avg_sales_from_new_customers", "avg_sales_from_repeat_customers"
]].plot(kind="bar", grid=True, figsize=(15,5), rot=0)
ax.set_ylabel("average sales")
ax.set_title("sales from new vs. repeat customers over time")
monthly_data_df["repeat_to_new_avg_sales_ratio"].plot(
    ax=ax, secondary_y=True, color="salmon", style="-o"
)
ax.right_ax.set_ylim([0, 2.0])
ax.right_ax.set_ylabel("repeat to new customer avg sales ratio")
plt.show() 

这段代码应该生成以下图表:

图片图 8.4:新客户与回头客的平均销售额

类似地,左侧的柱状图是新客户的平均销售额,右侧的柱状图是回头客的平均销售额,每个月都有。折线图显示了新客户平均销售额与回头客平均销售额之间的比率。例如,如果比率是1.5,这意味着回头客在那个月平均花费是新客户的1.5倍。根据这个示例数据集,我们看到,在所有报告的月份中,回头客的平均花费都高于平均客户。在 2011 年 11 月,比率是1:1.58,这意味着回头客平均比新客户多花费了大约 60%。这与BIA 顾问服务的报告相符,该报告指出回头客平均比新客户花费更多。

在这个练习中,我们将客户基础划分为两个简单的部分:新客户与回头客。正如你可能已经注意到的,这是一项简单的分析练习,但它能产生对业务动态和健康状况的深刻见解,同时也告诉营销人员应该关注哪一群客户。

如果有一个强大的回头客基础,并且有持续的收入,但新客户基础显示出稳定或下降的趋势,这表明营销人员应该更加关注新客户的获取。

另一方面,如果回头客的数量下降,这可能表明产品和服务可能对顾客没有吸引力,或者客户服务未能达到顾客的期望。在这种情况下,营销人员应该专注于改进产品营销策略、客户满意度策略或其他营销策略,以吸引顾客进行重复购买。

基于购买行为的客户细分

根据新客户与回头客对客户进行细分是进行的基本且关键的分析之一。然而,很多时候,我们希望根据多个因素对客户进行细分,这些因素可以是人口统计因素,如年龄、地理位置和职业,或者是购买历史,如他们在过去一年中花费了多少钱,他们购买了哪些商品,以及他们请求了多少次退货。你还可以根据客户的网络活动进行细分,例如过去 X 天内登录的次数,他们在你的网页上停留的时间,以及他们查看的页面。

根据这些因素对客户进行细分仍然存在挑战,因为你可以以无数种方式和值来细分客户。例如,如果你根据年龄细分客户,可能会出现一些问题,比如“我应该创建多少个桶?”或者“我应该选择什么年龄截止阈值?”类似地,如果你想根据过去销售量细分客户,你仍然需要选择用于细分客户基础和希望创建多少个细分的阈值。

此外,当你将多个因素结合这些细分时,细分数量会呈指数增长。例如,如果你基于销售量有 2 个细分,并将其与其他基于购买数量的 2 个细分相结合,你将最终得到 4 个细分。如果你对两个因素都有 3 个细分,那么总共将得到 9 个细分。总之,在执行客户细分时,主要有三个关键问题需要回答:

  1. 应该使用哪些因素进行客户细分?

  2. 应该创建多少个细分?

  3. 应该使用什么阈值来细分到细分?

我们将使用之前使用过的在线零售数据集作为示例,并讨论如何使用 K-means 聚类算法和轮廓分数来回答这些关键问题,以衡量聚类的有效性。

K-means 聚类

K-means 聚类是用于聚类和分割的最常用的机器学习算法之一。它是一种将数据划分为k个聚类的算法。简而言之,该算法迭代地找到质心并将数据点分组到最近的质心,直到数据点比其邻近的质心更接近其质心。正如你可以想象的那样,我们案例中的数据点将是感兴趣的因子,例如销售额、数量和退款,而在 K-means 聚类中的“k”是我们希望创建多少个聚类或客户细分。

为了根据总销售额、订单数量和退款创建客户细分,我们需要做一些准备工作。看看以下代码:

# Net Sales & Quantity
customer_net_df = df.groupby('CustomerID')[["Sales", "Quantity"]].sum()
customer_net_df.columns = ['NetSales', 'NetQuantity']
# Total Refunds
customer_refund_df = df.loc[
    df["Quantity"] < 0
].groupby("CustomerID")[["Sales", "Quantity"]].sum().abs()
customer_refund_df.columns = ['TotalRefund', 'TotalRefundQuantity']
customer_df = customer_net_df.merge(
    customer_refund_df, left_index=True, right_index=True, how="left"
).fillna(0) 

在这里,我们首先获取每个客户的净销售额和数量。这将减去任何退款和退货项,因为有一些记录的销售额和数量值为负。接下来,我们获取关于退款的信息。我们假设任何负数数量都是退款。因此,我们通过求和所有负数量值的销售额来获取总退款金额,通过求和所有负数量值的订单数量来获取总退款数量。最后,我们通过索引(即客户 ID)合并这两个 DataFrame。生成的 DataFrame 应该看起来像以下这样:

图片

图 8.5:生成的净销售额、净数量、退款金额和退款数量

这里要注意的一点是数据高度偏斜。看看以下代码,这是我们用来生成直方图的代码:

customer_df.hist(bins=50, figsize=(15,10))
plt.show() 

这给我们以下图表:

图 8.6:数据分布

如从这些直方图中所见,数据高度右偏斜。这种情况经常发生,尤其是在数据具有货币或数量值时。数据的偏斜会导致不均衡的聚类,数据分割不理想。克服这种偏斜的一个简单方法是对数据进行对数变换,以下代码为证:

log_customer_df = np.log(customer_df - customer_df.min() + 1) 

我们可以使用以下代码生成对数变换数据的直方图:

log_customer_df.hist(bins=50, figsize=(15,10))
plt.show() 

以下是由此生成的直方图:

图 8.7:对数变换后的数据分布

如预期的那样,对数变换后的数据更集中在平均值周围,更接近钟形曲线。我们将检查带有和对数变换的聚类,并看看它如何影响聚类结果。

无对数变换

在 Python 中训练 K-means 聚类算法很简单。看看以下代码,我们在scikit-learn包中导入KMeans模块来构建 K-means 聚类算法:

from sklearn.cluster import KMeans
COLS = ['NetSales', 'NetQuantity', 'TotalRefundQuantity']
kmeans = KMeans(
    n_clusters=4, n_init="auto"
).fit(
    customer_df[COLS]
) 

在这个例子中,我们根据三个列,NetSalesNetQuantityTotalRefundQuantity构建客户细分。然后,我们使用参数n_clusters构建四个聚类。训练好的KMeans模型的labels_属性为每一行或客户分配了标签(0 到 3),而cluster_centers_属性显示了每个聚类的中心。

K-means 聚类中的随机性

由于 K-means 聚类是一种迭代方法,用于从原始随机选择的中心更新中心,因此 K-means 聚类中存在随机性,导致每次运行时结果略有不同。如果您希望每次都得到相同的结果,您应该设置random_state变量。

本章中的示例没有使用random_state变量,所以您的结果可能看起来与您看到的图表略有不同。

现在,让我们可视化聚类,这样我们就可以直观地检查 K-means 聚类算法如何使用我们感兴趣的三个因素(NetSalesNetQuantityTotalRefundQuantity)将客户群分割开来:

import matplotlib.colors as mcolors
def plot_clusters(c_df, col1, col2):    colors = list(mcolors.TABLEAU_COLORS.values())
    clusters = sorted(c_df["cluster"].unique())
    for c in clusters:
        plt.scatter(
            c_df.loc[c_df['cluster'] == c][col1],
            c_df.loc[c_df['cluster'] == c][col2],
            c=colors[c]
        )
    plt.title(f'{col1} vs. {col2} Clusters')
    plt.xlabel(col1)
    plt.ylabel(col2)
    plt.legend(clusters)
    plt.show()
cluster_df = customer_df[COLS].copy()
cluster_df["cluster"] = kmeans.labels_
plot_clusters(cluster_df, "NetSales", "NetQuantity")
plot_clusters(cluster_df, "NetSales", "TotalRefundQuantity")
plot_clusters(cluster_df, "NetQuantity", "TotalRefundQuantity") 

在这里,我们首先定义一个函数,plot_clusters,用于绘制每个聚类的 2D 图,它接受 DataFrame 作为输入,其中包含用于 x 轴和 y 轴的两个列。然后,我们创建三个图表:一个用于根据NetSalesNetQuantity可视化聚类,另一个用于NetSalesTotalRefundQuantity,第三个用于NetQuantityTotalRefundQuantity。这三个生成的图表应该看起来像以下这样:

图 8.8:基于 NetSales 与 NetQuantity 的聚类

图 8.9:基于 NetSales 与 TotalRefundQuantity 的聚类

图 8.10:基于 NetQuantity 与 TotalRefundQuantity 的聚类

图 8.88.98.10中,我们可以很容易地看到聚类是如何基于成对形成的。例如,聚类0似乎代表的是那些净销售额、净数量和退款都较低的客户,而聚类1似乎代表的是那些净销售额、净数量和退款处于中低水平的客户。然而,在这个例子中有两点值得关注:

  • 一些聚类具有广泛的点范围。以聚类0为例,如果查看图 8.10,其退款数量范围从080,000,这使得描述聚类0实际上代表什么以及它与其他聚类有何不同变得困难。

  • 这里还有一个需要注意的事项,那就是大多数数据点都在聚类0中,而其他聚类中的数据点非常少。聚类3似乎只包含两个数据点。这些聚类大小的巨大不平衡使得从这些聚类中得出的概括不太可靠,因为基于少量数据点的见解并不可靠。

您可以使用以下代码查看每个聚类中的数据点数量:

cluster_df.groupby('cluster')['NetSales'].count() 

下面是每个聚类的详细信息:

图 8.11:每个聚类中的数据点数量

数据偏斜经常导致这些问题,因为它使得 K-means 聚类算法难以找到或有效地聚类数据点。这就是为什么当数据存在偏斜时,我们需要在应用聚类算法之前对数据进行归一化的原因。

使用对数变换

让我们看看对数变换如何可能帮助使用 K-means 聚类进行客户细分。看一下以下代码:

COLS = ['NetSales', 'NetQuantity', 'TotalRefundQuantity']
kmeans = KMeans(
    n_clusters=4, n_init="auto"
).fit(
    log_customer_df[COLS]
)
cluster_df = log_customer_df[COLS].copy()
cluster_df["cluster"] = kmeans.labels_ 

在这里,我们使用之前定义的变量log_customer_df,它是使用np.log函数进行对数变换的数据。然后我们拟合了一个包含四个聚类的 K-means 聚类模型。现在我们可以看到聚类的大小如下:

cluster_df.groupby('cluster')['NetSales'].count() 

这给我们以下输出:

图 8.12:对数变换后每个聚类中的数据点数量

与本章早期我们拟合聚类模型时没有进行对数变换相比,聚类现在更加均衡,每个聚类都有显著数量的客户。这将使我们能够更好地了解客户是如何基于我们感兴趣的三个因素(净销售额、净数量和总退款)进行细分的。让我们用以下代码可视化聚类:

plot_clusters(cluster_df, "NetSales", "NetQuantity")
plot_clusters(cluster_df, "NetSales", "TotalRefundQuantity")
plot_clusters(cluster_df, "NetQuantity", "TotalRefundQuantity") 

这段代码应该创建三个类似于以下图表:

图 8.13:转换后的 NetSales 与 NetQuantity 的聚类

图 8.14:NetSales 与转换后的 TotalRefundQuantity 的聚类

图 8.15:转换后的 NetQuantity 与 TotalRefundQuantity 的聚类

让我们深入探讨这些集群的可视化。如果您查看 图 8.13,基于净销售额和净数量,集群之间没有明显的分离。集群 3 似乎更集中在平均值附近,而集群 1 则更倾向于更高的净销售额和更高的净数量,集群 02 则更倾向于更低的净销售额和更低的净数量。尽管有这些细微的差异,所有集群似乎都聚集在净销售额和净数量的平均值周围。

图 8.14图 8.15 中,集群之间的区别更为明显。集群 1 似乎是一个具有高总退款的客户群体,其截止阈值在对数尺度上约为 4。您可以通过撤销我们之前应用的转换或使用以下代码来转换这个对数转换的值:

np.exp(X) + customer_df.min()[COLUMN] - 1 

代码中的 X 是对数尺度上的值,而 COLUMN 是感兴趣的因子。让我们更仔细地看看这些集群:

  • 集群 0:这个集群似乎是一个具有低总退款和低净数量的集群。TotalRefundQuantity 在对数尺度上的阈值约为 26.7 对于 NetQuantity。这些数字相当于总退款中的 6.4 和净数量中的 811.4,使用前面的公式。这表明这个集群中的客户总退款少于 6.4,净数量少于 811.4

  • 集群 1:这个集群似乎是一组退款频率最高的客户。集群 1 的截止阈值在对数尺度上 TotalRefundQuantity 中约为 4,使用上面的代码,这相当于 54 (np.exp(4) + customer_df.min()["TotalRefundQuantity"] - 1)。因此,集群 1 是总退款超过 54 的客户群体。

  • 集群 2:这个集群似乎是一个具有中等总退款且对数尺度上 TotalRefundQuantity 的阈值约为 2 的客户群体,这相当于实际总退款中的 6。因此,集群 2 是总退款在 654 之间的客户群体。

  • 集群 3:集群 3 中的客户似乎具有低总退款但高净数量的特点。这个客户群体可能是业务的甜点,因为它表明他们经常从该业务购买,但退款数量并不像其他不同客户群体中的客户那么多。鉴于他们在对数尺度上总退款的下限约为 26.7 对于净数量,这个客户群体在总退款中少于 6,而在净数量中多于 811

正如你在这次练习中看到的,K-means 聚类算法有助于以机器学习的方式对客户进行分段,而无需你自己手动为每个客户分段定义阈值。这种程序化方法帮助你更动态、更数据驱动地定义客户分段。这样,你可以更好地理解不同的客户分段是如何组合的,以及分离因素是什么,这些因素随后可以用来为你的未来营销工作制定策略和优先级。

轮廓系数

我们已经看到了如何使用 K-means 聚类算法构建客户分段。构建聚类的一个关键论点是聚类的数量。然而,你可能想知道在构建这样的聚类之前,你如何决定或如何知道正确的聚类数量。在实际环境中,你可能想要构建具有不同数量的聚类的多个聚类,并决定哪一个效果最好。这就是轮廓系数发挥作用的地方。简单来说,轮廓系数是一个度量,它量化了给定数据点与其聚类中其他点的匹配程度以及它与其他聚类的可区分性。轮廓系数的公式如下:

在这里,a[i] 是第 i 个数据点到同一聚类中所有其他点的平均距离,而 b[i] 是第 i 个数据点到其他聚类中所有点的最小平均距离。

为了获得聚类算法的轮廓系数,你需要计算每个数据点的所有单个轮廓系数的平均值。轮廓系数的范围在 -11 之间。分数越接近 1,数据点聚在一起的程度就越好,它们与相邻聚类的区别就越明显。

轮廓系数在 Python 中很容易计算。Python 的 scikit-learn 包中有一个名为 silhouette_score 的函数,它可以计算聚类的平均轮廓系数:

from sklearn.metrics import silhouette_score
silhouette_score(
    log_customer_df[COLS],
    kmeans.labels_
) 

由于更高的轮廓系数值表明聚类更好,我们可以利用这一点来决定理想的聚类数量。看看以下代码,我们在 48 之间尝试不同的聚类大小:

COLS = ['NetSales', 'NetQuantity', 'TotalRefundQuantity']
f, axes = plt.subplots(2, 3, sharey=False, figsize=(12, 7))
for i, n_cluster in enumerate([4,5,6,7,8]):
    kmeans = KMeans(n_clusters=n_cluster, n_init="auto").fit(
        log_customer_df[COLS]
    )
    silhouette_avg = silhouette_score(
        log_customer_df[COLS],
        kmeans.labels_
    )

    print('Silhouette Score for %i Clusters: %0.4f' % (n_cluster, silhouette_avg))

    each_cluster_size = [
        (kmeans.labels_ == i).sum()/len(kmeans.labels_) for i in range(n_cluster)
    ]
    ax = axes[i//3][i%3]
    pd.DataFrame(each_cluster_size).plot(ax=ax, kind="barh", color="orange")
    for p in ax.patches:
        ax.annotate(f'{p.get_width()*100:.01f}%', (p.get_width(), p.get_y()+0.2))
    ax.axvline(x=(1/n_cluster), color="red", linestyle="--")
    ax.set_xlabel("Cluster Size", size=8)
    ax.set_title(f"Cluster #{n_cluster} - Silhouette: {silhouette_avg:.02f}")
    ax.title.set_size(8)
f.subplots_adjust(hspace=0.3)
plt.show() 

对于每个聚类,我们计算轮廓系数并检查每个聚类中有多少百分比的数据点。理想情况下,最佳的聚类是轮廓系数最高且每个聚类中数据点均匀分布的聚类。以下代码应该生成以下输出:

图 8.16:聚类大小实验结果

此图表显示了当你确定最佳聚类大小时应考虑的几个重要决策因素:

  • 轮廓得分:首先,我们可以看到每个簇大小的轮廓得分,其中大小为4的簇得分为0.4986,大小为5的簇得分为0.5391,依此类推。在这里,大小为5的簇的轮廓得分似乎是最高的,为0.5391

  • 簇大小和组成:我们还应该评估每个簇中的数据点是否分布得相对均匀,因为簇之间的大规模不平衡可能不足以生成最佳的洞察。图 8.16中的水平条形图显示了每个簇大小的簇组成。虚线垂直线显示了如果组成完全均匀分布,条形应该在哪里。从这些图表中可以看出,高轮廓得分的簇并不一定意味着最佳的簇。例如,簇5具有最高的整体轮廓得分,但存在很大的不平衡,其中第0个簇有接近 70%的数据点,其余部分共享一小部分数据。这不是一个理想的簇,因为数据过于集中在单个簇中。

在这个例子中,大小为4的簇可能是最佳选择,因为与其它簇相比,数据点在簇之间分布得更均匀,尽管轮廓得分不是最高的。

基于产品兴趣的客户细分

我们在上一节中讨论了如何根据他们的购买历史构建客户细分,以及这如何帮助营销人员确定优先考虑和为下一次营销活动制定策略的细分。我们不仅可以根据购买历史或更具体地说,根据数值对客户进行细分,还可以根据他们的产品兴趣找到客户细分。

客户购买的商品中隐藏着关于每个客户感兴趣的商品类型以及他们可能购买更多的商品的见解。根据客户过去购买的产品进行客户细分有多种方法,例如简单地根据他们购买的产品类别进行分组。然而,在这个练习中,我们将扩展到第五章中提到的嵌入向量这一主题。

如果您还没有安装,您可能需要使用pip安装 Hugging Face 的transformers

pip install transformers 

如前文在第五章中所述,现代 LLM 如BERTGPT引入了上下文嵌入,将单词和句子转换成表示上下文意义的数值或向量。我们将使用 Hugging Face 的预训练 LLM all-MiniLM-L6-v2对示例数据集中每个客户的过去产品购买进行编码,并使用这些嵌入向量构建客户细分。请看以下代码:

import os
os.environ["TOKENIZERS_PARALLELISM"] = "false"
from sentence_transformers import SentenceTransformer, util
customer_item_df = pd.DataFrame(
    df.groupby("CustomerID")["Description"].apply(
        lambda x: ", ".join(list(set(x)))
    )
)
embedding_model = SentenceTransformer(
    "sentence-transformers/all-MiniLM-L6-v2"
)
encoded = embedding_model.encode(
    list(customer_item_df["Description"]),
    show_progress_bar=True
)
with open('tmp.npy', 'wb') as f:
    np.save(f, encoded) 

在这里,我们首先获取客户购买的所有产品描述,然后为每个客户创建一个以逗号分隔的列表,该列表存储在变量customer_item_df中。然后,我们加载预训练的 LLM,sentence-transformers/all-MiniLM-L6-v2,并使用预训练 LLM 的encode函数将每个客户的商品描述列表编码成数值向量。这将导致每个客户有一个 384 值的向量。然后我们将这个数组保存到tmp.npy中,以供将来使用。

在高维空间中,随着维度的增加,数据点之间的距离变得不那么有意义,因为更大的维度使得数据过于稀疏。由于 K-means 聚类算法使用距离度量来聚簇数据点,这成为一个问题。为了克服这个问题,我们需要应用一些降维技术。在这个练习中,我们将简单地应用主成分分析PCA)来降低嵌入向量的维度,同时保留数据中的大部分方差:

  1. 请看以下代码:

    from sklearn.decomposition import PCA
    with open('tmp.npy', 'rb') as f:
        encoded = np.load(f)
    pca = PCA(n_components=5)
    transforemd_encoded = pca.fit_transform(encoded) 
    

在这里,我们导入scikit-learn包中的PCA模块。我们从临时位置tmp.npy导入之前构建的嵌入向量,并使用fit_transform函数对向量进行拟合和转换。我们将其定义为返回 5 个成分,正如您可以从n_components参数中看到的那样。结果向量transforemd_encoded应该有 5 个向量,每个客户一个。

其他降维方法

除了 PCA 之外,还有许多降维技术。在我们的练习中,我们使用 PCA 是因为它的简单性,但 T-SNE 和 UMAP 是处理高维数据时经常使用的另外两种技术。务必查看它们,看看它们是否可能更适合这个练习!

T-SNE: scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html

UMAP: umap-learn.readthedocs.io/en/latest/

  1. 现在是时候根据这些嵌入向量构建客户细分或聚类了,这些嵌入向量对每个客户购买的产品有上下文理解。请看以下代码:

    from sklearn.cluster import KMeans
    from sklearn.metrics import silhouette_samples, silhouette_score
    for n_cluster in [4,5,6,7,8]:
        kmeans = KMeans(n_clusters=n_cluster, n_init="auto").fit(
            transforemd_encoded
        )
    
        silhouette_avg = silhouette_score(
            transforemd_encoded,
            kmeans.labels_
        )
    
        print('Silhouette Score for %i Clusters: %0.4f' % (n_cluster, silhouette_avg)) 
    

这段代码看起来应该很熟悉,因为这与我们之前使用 K-means 聚类算法根据购买历史构建聚簇时几乎完全相同的代码。这里的主要区别是,我们不是使用销售指标,而是使用嵌入向量作为KMeans的输入来构建聚类。这段代码的输出应该看起来像以下这样:

图 8.17:不同聚类大小的轮廓得分

实际值可能会有所不同,因为拟合 K-means 聚类算法时存在一些随机性,但趋势应该是相似的。

  1. 基于此,我们打算基于嵌入向量构建 7 个集群,如下面的代码所示:

    n_cluster = 7
    kmeans = KMeans(n_clusters=n_cluster, n_init="auto").fit(
        transforemd_encoded
    )
    customer_item_df["cluster"] = kmeans.labels_
    from collections import Counter
    n_items = 5
    common_items = []
    for i in range(n_cluster):
        most_common_items = Counter(list(df.set_index("CustomerID").loc[
                customer_item_df.loc[
                customer_item_df["cluster"] == i
            ].index
        ]["Description"])).most_common(n_items)
    
        common_items.append({
            f"item_{j}": most_common_items[j][0] for j in range(n_items)
        })
    common_items_df = pd.DataFrame(common_items) 
    

在此代码中,我们构建了 7 个集群。然后,对于每个集群,我们使用 Python 中的collections库获取每个集群中客户购买的最常见的 5 个商品。然后,我们将每个集群中最常购买的 5 个商品存储在一个名为common_items_df的 DataFrame 中。这个 DataFrame 应该能让我们了解哪些类型的商品最吸引每个客户细分市场。

让我们更仔细地看看这个 DataFrame:

图 8.18:每个集群前 5 个常见商品

这给我们带来了以下见解:

  • 第一集群或索引为 0 的集群的客户似乎对一些装饰品最感兴趣,例如饰品和木框。

  • 第二集群或索引为 1 的集群的客户似乎对与派对相关的商品感兴趣,例如烘焙套装、派对彩旗和卡片。

  • 第三集群或索引为 2 的集群的客户似乎对茶或茶道很感兴趣,因为他们购买了茶杯和茶托。

  • 第四集群的客户似乎喜欢购买包。

  • 第五集群的客户似乎喜欢水壶等等。

如您所见,这些客户集群显示了他们最感兴趣的商品,以及如何根据他们的产品兴趣将不同的客户分组在一起。这些信息将在您构建下一轮营销策略和活动时非常有用。您可能不想向那些对购买水壶感兴趣的人推广茶具,反之亦然。这种不匹配的目标定位将导致浪费的营销活动,参与和转化的成功率低。您希望根据不同客户细分市场的产品兴趣,为每个细分市场构建更精准的营销活动,并针对他们最感兴趣的品类进行推广。

这样做,你更有可能进行成功的营销活动,在吸引客户参与和转化方面取得更多成功。

摘要

在本章中,我们讨论了不同分割客户群的方法。我们首先探讨了新客户与回头客对收入的影响,以及新客户和回头客数量的月度进展如何告诉我们下一次营销活动应关注哪个细分市场或客户群体。然后,我们讨论了如何使用 K-means 聚类算法编程构建和识别不同的客户细分市场。通过销售金额、订单数量和退款,我们实验了如何使用这些因素构建不同的客户细分市场。在不进行实际操作的情况下,我们提到了轮廓分数作为寻找最佳聚类数量的标准,以及在对高度偏斜的数据集进行处理时,对数变换可能是有益的。最后,我们使用单词和句子嵌入向量将产品描述转换为具有上下文理解的数值向量,并基于他们的产品兴趣进一步构建客户细分市场。

在接下来的章节中,我们将进一步探索 LLMs。从使用预训练的零样本模型创建引人入胜的内容,到更高级的少样本和 RAG 方法,我们将在下一章更多地涉及 LLMs 和生成式 AI。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人交流,并和超过 5000 名成员一起学习:

packt.link/genai

第九章:使用零样本学习创建引人入胜的内容

第五章中介绍了大型语言模型的潜力之后,我们将在本章深入探讨相关主题,将我们的分析从其在数据增强和情感分析中的作用扩展到其在不同领域的更广泛影响。本章介绍了零样本学习ZSL),这是一种机器学习方法,模型可以在没有为这些类别接收任何特定训练示例的情况下,正确地对新、未见过的类别进行预测。它讨论了 ZSL 的潜力及其在生成式人工智能领域创建营销文案中的应用。讨论突出了 ZSL 作为一种高效工具,可以补充传统的营销内容创作流程,如何革命性地改变营销文案的生成。

我们将深入讨论生成式人工智能的核心原则,并探讨这些技术的能力和局限性,这将为我们随后对预训练模型重要性的探索奠定基础。我们将以 ZSL 的实际操作演练结束本章,通过动手示例展示这种方法的优势以及我们如何利用它来生成营销内容。这将使你具备理解和利用这项技术,将你的营销策略提升到新高度的能力。

到本章结束时,你将熟练掌握:

  • 生成式人工智能的基础及其在市场营销中的多方面应用

  • ZSL 的原则及其在提高传统内容创作流程效率中的价值

  • 在应用 ZSL 创建营销文案时的实际策略和考虑因素

生成式人工智能的基础

生成式人工智能GenAI)是指能够生成新内容的人工智能子集,无论是文本、图像、视频,甚至是反映现实世界示例的合成数据。与旨在根据输入解释、分类或预测数据的传统 AI 模型不同,GenAI 更进一步,通过理解和学习现有数据模式来产生新的、以前未见过的输出。它通过理解并从现有数据模式中学习,以产生与输入数据保持逻辑连续性的新颖输出。

我们在第一章中介绍了 GenAI,并在第五章中进一步探讨了它及其在情感分析中的应用。在开始我们关于预训练模型和 ZSL 的讨论之前,我们将探讨 GenAI 的基本技术考虑因素,它是什么(以及不是什么),以及为什么它对生成营销内容有如此大的影响。虽然本章的动手示例将涉及文本生成,但也将讨论支撑 GenAI 在其他应用(如图像和视频)中能力的重要概念。

概率方法

GenAI 的核心是对数据分布的概率建模方法。这涉及到学习数据集的潜在概率分布,以从同一分布中生成新的样本。这种方法的一个基石是贝叶斯推理,这是一个随着更多证据或信息的出现而更新假设概率的原则。例如,考虑一个简单的方程,它是贝叶斯推理数学基础的基石,即贝叶斯定理:

其中:

  • P(AB) 是在证据 B 下假设 A 的后验概率

  • P(BA) 是在假设 A 为真的情况下观察证据 B 的可能性

  • P(A) 是假设 A 的先验概率,或者在我们看到证据之前我们认为 A 为真的可能性

  • P(B) 是在所有可能假设下观察证据 B 的概率

    贝叶斯定理 – 概率推理的支柱

    贝叶斯定理不仅是 GenAI 的基石,也是统计学、计算机科学、哲学和医学等多个学科的基本原则。在其核心,贝叶斯定理允许我们在新证据的背景下完善我们的假设,为从经验中学习这一概念提供了一种严谨的数学方法。

当将贝叶斯推理的原则扩展并融入如循环神经网络RNNs)、长短期记忆网络LSTMs)或转换器等深度学习模型到序列生成中时,我们进入了条件概率的领域。这个序列生成过程可以通过预测每个元素基于其前驱元素的概念来观察,这一概念不仅对视频和音频至关重要,也对时间序列建模和其他形式的序列数据生成应用,包括文本,至关重要。

训练 GenAI 模型需要大量的数据,在文本的情况下,这些数据必须被分解成更小的单元,称为标记。这些标记通常由子词单元或短语组成,这使得模型在理解和生成自然语言方面更加高效。文本标记化过程至关重要,因为它允许模型学习不同序列的单词或子词的概率分布。

当我们对文本进行标记化时,我们将其分解成模型可以处理的可管理部分。然后,每个标记在训练期间被用作模型的输入。模型学习预测序列中下一个标记的概率,给定之前的标记。这种概率方法正是贝叶斯原理发挥作用的地方。通过随着新数据的引入不断更新标记的概率分布,模型在生成连贯且上下文相关的输出方面变得更加出色。

例如,在文本生成中,一个模型可能会根据前面的单词预测句子中的下一个单词。这个预测过程涉及计算条件概率:

其中 x[t] 代表时间 t 的标记,P(x[t]∣x[1],x[2],…,x[t-1]) 表示在给定所有先前标记的序列的情况下生成 x[t] 的概率。

在视频和音频生成的案例中,利用基于贝叶斯原理的深度学习模型有助于理解和预测时间进程。在时间 t 的每一帧或音频样本 x[t] 是基于所有先前帧或样本的序列(x[1],x[2],…,x[t-1])预测的。从数学上讲,这种关系由前面的方程式捕捉:

其中 x[t] 代表时间 t 的帧或音频样本, 表示在给定所有先前样本的序列的情况下生成 x[t] 的概率。

源代码和数据

github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/tree/main/ch.9

基础模型

在生成式 AI 中,有几个重要的基础模型,每个模型都对图像、文本和序列生成中的应用做出了独特的贡献。本节将涵盖一些最重要和最广泛使用的案例,例如:

  • 生成对抗网络GANs

  • 变分自编码器VAEs

  • 长短期记忆网络LSTMs

  • 基于 Transformer 的模型,如生成预训练 TransformerGPT

尽管每个这些模型的全面实现示例和理论超出了本章的范围,但我们将讨论每种模型类型的核心概念,并提供其架构的简化、说明性示例,以便理解这些模型在营销应用中的重要性。在第十二章中,我们将扩展我们的讨论,提及最近获得更多关注并有望推进生成式 AI 领域的模型进展。

使用 Google Colab 笔记本探索机器学习模型

训练自己的最先进机器学习模型可能成本高昂。然而,使用 Google Colab 笔记本,您可以在自己的机器上无需任何设置的情况下训练和调整模型。以下是一些入门链接:

生成对抗网络

GAN 已在广泛的应用领域找到应用,从图像生成和风格迁移到数据增强等。它们在需要真实图像生成至关重要的应用中特别有影响力,NVIDIA 和 Adobe 已在其照片编辑软件中使用 GAN 生成和修改图像。它们的应用包括以下内容:

  • 内容创作:GAN 可以生成高质量、逼真的图像、艺术作品和视频,从而实现新的创意内容生产形式

  • 图像到图像的翻译:像照片增强、从草图生成逼真渲染和领域适应(如日夜转换和夏季到冬季转换)等应用利用 GAN 将图像从一个领域转换到另一个领域,同时保留上下文细节。

在其核心,GAN 由两个通过竞争过程同时训练的神经网络组成:

  • 生成器(G)旨在生成与真实数据无法区分的数据

  • 判别器(D)旨在准确地将数据分类为真实或生成

这可以通过以下图示来说明:

生成器图示 自动生成描述

图 9.1:GAN 工作流程

GAN 的目标函数封装了生成器和判别器之间的训练动态,创造了一个动态环境,其中两个模型都会根据对方的性能而提高。这类似于一个双玩家游戏,每个玩家的成功都基于智胜对手。在 GAN 的情况下,当生成器产生真实数据的完美复制品时,游戏达到平衡,这使得判别器无法区分真实和伪造,理想情况下,判别器正确猜测的概率为0.5

为了使 GAN 在诸如高分辨率图像生成等任务上高度有效,生成器和判别器的架构都必须精心设计。这可能涉及采用有效的架构来处理空间层次数据,例如卷积神经网络(CNNs)

什么是卷积神经网络(CNNs)

CNNs 是处理空间数据(如图像)的机器学习基石。它们使用卷积滤波器识别模式,在需要理解空间层次的任务中表现出色。这使得 CNNs 在许多 GAN 应用(如图像生成和识别)中变得不可或缺。

在基于图像的 GAN 应用中,生成器使用技术将潜在表示扩展到详细图像,而判别器则应用方法降低输入图像的维度以高效地评估其真实性。潜在维度,作为生成新数据实例的种子,是一个紧凑的高维空间,以压缩格式封装潜在的数据变化。

以下代码展示了使用 Python 构建简化 GAN 图像核心结构的流程,其中关键步骤在此描述:

  1. 导入构建生成器和判别器所需的库:

    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense 
    
  2. 定义生成器模型,它接受一个潜在空间向量并通过一系列密集层生成一个 28x28 的图像:

    def build_generator(latent_dim):
        model = Sequential([
            Dense(128, activation='relu', input_dim=latent_dim),  # maps from latent space
            Dense(256, activation='relu'),  # expands representation
            Dense(784, activation='tanh')  # produces 28x28 image
        ])
        return model 
    
  3. 定义判别器模型,它接受一个图像并通过一系列密集层将其分类为真实或生成:

    def build_discriminator(input_shape):
        model = Sequential([
            Dense(256, activation='relu', input_shape=(input_shape,)),  # processes input image
            Dense(128, activation='relu'),  # reduces dimensionality
            Dense(1, activation='sigmoid')  # classifies input as real or generated
        ])
        return model
    Define the latent dimension and initialize the models:
    latent_dim = 100  # size of input noise vector
    generator = build_generator(latent_dim)
    discriminator = build_discriminator(784)  # for 28x28 images 
    

为了解决常见的挑战,如输出多样性有限和确保生成数据在保持与真实数据分布紧密相似的同时具有多样性,需要进一步的技术考虑。这些考虑包括激活函数(用于非线性变换的relu)的选择、确保层间输入分布一致的技术,以及如训练期间随机省略单元以防止过拟合的策略。

更多关于这方面的细节,您可以参考关于 GANs 的最新论文:www.researchgate.net/publication/380573076_Understanding_GANs_fundamentals_variants_training_challenges_applications_and_open_problems

变分自编码器

与 GANs 相比,VAEs(变分自编码器)在生成建模方面提出了不同的方法。VAEs 提供了一种概率学习数据潜在表示的方法,并包含两个主要组件:

  • 编码器将输入数据压缩到潜在空间表示

  • 解码器从该潜在空间重建数据

与传统的自动编码器不同,VAEs 引入了一种概率转折,即它们不是将输入编码为单个点,而是将其编码为潜在空间上的分布。

VAEs 的多用途应用

VAEs 在理解和建模复杂数据分布方面发挥着重要作用。VAEs 表现优异的关键领域之一是数据插补,其中它们可以预测缺失信息或预测时间序列数据的未来趋势。

VAE(变分自编码器)的损失函数结合了重建损失与学习到的潜在变量分布与先验分布之间的Kullback-Leibler(KL)散度。重建损失衡量生成的输出与原始输入匹配的程度,确保模型能够创建准确的数据复制品,而 KL 散度在训练期间充当正则化形式,确保模型学习到高效且有意义的数据表示。这种正则化通过鼓励模型生成不仅准确而且对新、未见数据具有良好泛化能力的输出,防止模型过拟合。通过结合这两个组件,VAE 学习生成高质量、多样化的输出,并鼓励模型学习数据的有效编码。

以下是一个使用 Keras 构建 VAE 的简化示例:

  1. 我们将使用一个 28x28 的扁平图像输入作为另一个示例,我们首先在sampling()函数中从潜在分布中采样:

    from tensorflow.keras.layers import Input, Lambda
    from tensorflow.keras import Model, backend as K
    def sampling(args):
        z_mean, z_log_var = args
        batch = K.shape(z_mean)[0]
        dim = K.int_shape(z_mean)[1]
        epsilon = K.random_normal(shape=(batch, dim))
        return z_mean + K.exp(0.5 * z_log_var) * epsilon 
    
  2. 我们随后使用编码器将输入映射到潜在空间:

    inputs = Input(shape=(784,)) # Encoder
    h = Dense(256, activation='relu')(inputs)
    z_mean = Dense(2)(h)
    z_log_var = Dense(2)(h)
    z = Lambda(sampling, output_shape=(2,))([z_mean, z_log_var]) 
    
  3. 我们随后使用解码器从潜在空间重建图像:

    decoder_h = Dense(256, activation='relu') # Decoder
    decoder_mean = Dense(784, activation='sigmoid')
    h_decoded = decoder_h(z)
    x_decoded_mean = decoder_mean(h_decoded)
    vae = Model(inputs, x_decoded_mean) 
    

对于 VAE 的有效应用,选择合适的编码器和解码器架构至关重要,通常涉及密集连接层进行基本任务,或更复杂的结构,如 CNN(卷积神经网络)进行图像数据。潜在空间的空间维度也非常关键——它必须足够大以捕捉相关的数据变化,但不能太大以至于导致过拟合或无意义的重建。当设计正确时,VAE 提供了一种原则性的生成建模方法,在准确数据重建的需求与从学习到的数据分布生成新、多样化样本的灵活性之间取得平衡。

长短期记忆网络

LSTM 是一种专门设计的 RNN(循环神经网络),用于学习序列数据中的长期依赖关系。RNN 是一类包含循环的神经网络,允许信息通过将信息从一个网络步骤传递到下一个步骤来持续存在。这种循环机制使 RNN 适合处理时间序列或文本等数据序列。然而,标准 RNN 由于梯度消失和梯度爆炸等问题,在学习长期依赖关系时往往遇到困难。这是因为,在反向传播过程中,梯度可能变得非常小(消失)或非常大(爆炸),这使得有效地更新网络权重变得困难。LSTM 通过一个更复杂的内部结构来解决这些挑战,使其能够有效地记住信息更长时间。

LSTM(长短期记忆网络)的显著特征是它们能够更有效地记住信息,这得益于它们的细胞状态以及三种类型的门:输入门、输出门和遗忘门。这些组件共同工作,调节信息的流动,使网络能够在长时间内记住重要信息,并忘记无关数据。

LSTM 的关键组件

LSTM 的核心是其细胞状态和具有以下功能的门:

  • 输入门:决定在细胞状态中存储多少新信息

  • 遗忘门:从细胞状态中丢弃哪些信息

  • 输出门:细胞状态输出到下一层

以下代码设置了一个简单的 LSTM 网络,用于时间序列预测,可用于根据前一天的不同特征预测第二天销售额。在这个架构中,我们允许sequence_length捕获 10 天的数据,然后通过num_feature捕获 5 个特征,这些特征可能包括如网站流量或之前的销售额等数据点。具有 50 个单位的 LSTM 层学习识别序列数据中的模式,而Dense层输出预测。最后,该模型使用 Adam 优化器和均方误差(mse)损失函数编译,这些是回归任务的常见选择:

from tensorflow.keras.layers import LSTM
sequence_length = 10
num_features = 5
model = Sequential([
    LSTM(50, activation='relu', input_shape=(sequence_length, num_features)),
    Dense(1)
])
model.compile(optimizer='adam', loss='mse') 

为了演示训练过程,我们可以生成模拟销售预测数据的合成时间序列数据。合成数据包括一个基本正弦波和添加的噪声,模拟具有随机波动的每日模式:

import numpy as np
import matplotlib.pyplot as plt
def generate_synthetic_data(num_samples, sequence_length, num_features):
    X = []
    y = []
    for i in range(num_samples):
        base = np.array([np.sin(x) for x in range(sequence_length)]) + np.random.normal(0, 0.1, sequence_length)
        features = np.tile(base, (num_features, 1)).T + np.random.normal(0, 0.1, (sequence_length, num_features))
        target = np.sum(base) + np.random.normal(0, 0.1)
        X.append(features)
        y.append(target)
    return np.array(X), np.array(y)
X_train, y_train = generate_synthetic_data(100, sequence_length, num_features)
model.fit(X_train, y_train, epochs=10, verbose=1) 

训练后,我们可以通过比较预测的销售额值与实际值来在测试数据上评估模型:

X_test, y_test = generate_synthetic_data(10, sequence_length, num_features)
y_pred = model.predict(X_test)
plt.plot(y_test, label='Actual')
plt.plot(y_pred, label='Predicted')
plt.xlabel('Days')
plt.ylabel('Sales Prediction')
plt.title('Actual vs Predicted Sales Over Time')
plt.legend()
plt.show() 

代码生成了以下图表,展示了如何通过训练一个简单的 LSTM 模型,如果给定适当的输入特征,可以快速提供有用的预测,例如销售额:

图 9.2:LSTM 销售预测模型的输出

Transformer

基于 Transformer 的模型,如 GPT 系列,通过引入一个在捕捉数据中的上下文和关系方面表现卓越的模型架构,彻底改变了自然语言处理。Transformer 模型的核心创新是注意力机制,它使模型能够根据输入数据的不同部分以不同的方式权衡其重要性。这种机制允许 GPT 和类似模型理解上下文并生成连贯且上下文相关的文本。

GPT 模型利用 Transformer 架构进行生成任务,在大量文本数据上进行训练以理解语言模式、语法和上下文。这种预训练使 GPT 模型能够根据输入提示生成高度连贯且上下文相关的文本。虽然从头开始构建 GPT 是一个艰巨的任务,但在概念层面上,GPT 架构中存在一些关键组件:

  • 嵌入层:将标记索引转换为固定大小的密集向量

  • 多头注意力:允许模型同时关注输入序列的不同部分,捕捉各种上下文关系

  • 层归一化和残差连接:有助于稳定和优化训练过程,确保梯度在整个网络中顺畅流动

以下代码展示了如何使用 Keras 和上述组件创建一个简化的类似 GPT 的架构:

from tensorflow.keras.layers import Embedding, LayerNormalization, MultiHeadAttention
def simplified_gpt_model(vocab_size=10000, embed_dim=256, max_length=40, num_heads=4, ff_dim=512)
    inputs = Input(shape=(max_length,))  # input layer for sequences of tokens
    embedding_layer = Embedding(input_dim=vocab_size, output_dim=embed_dim)(inputs) # convert token indices to vectors
    # self-Attention layer with multiple heads
    attn_output = MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim)(embedding_layer, embedding_layer)
    # normalization and residual connection for the attention output
    attn_output = LayerNormalization(epsilon=1e-6)(attn_output + embedding_layer)
    # feed Forward network to processes attention output
    ff_network = Dense(ff_dim, activation="relu")(attn_output)
    ff_network_output = Dense(embed_dim)(ff_network)
    # second normalization and residual connection
    sequence_output = LayerNormalization(epsilon=1e-6)(ff_network_output + attn_output)
    # output layer to predict the next token in the sequence
    outputs = Dense(vocab_size, activation="softmax")(sequence_output)
    model = Model(inputs=inputs, outputs=outputs)
    return model
gpt_model = simplified_gpt_model()
gpt_model.compile(optimizer='adam', loss='sparse_categorical_crossentropy') 

GPT 中自注意力的力量

自注意力是 GPT 模型背后的关键创新,它允许网络权衡句子中不同单词的重要性,增强其对上下文和单词之间关系的理解。

要了解更多信息,请参阅 Illia Polosukhin 等人撰写的论文《Attention Is All You Need》(arxiv.org/pdf/1706.03762)。

当 GenAI 是合适的选择时

虽然 GenAI 为内容创作和数字营销带来了新的可能性,但了解其局限性同样重要。GenAI 在需要创新、创造力和动态扩展个性化内容的环境下表现出色。更普遍地说,以下情况下,GenAI 可以成为您营销活动的绝佳选择:

  • 创意活动的头脑风暴:生成独特且引人入胜的内容,无论是文本、图像还是视频,以促进创意营销活动的头脑风暴,使其在拥挤的数字领域中脱颖而出。例如,我们将在本章和第十章中使用 GenAI 生成新产品发布文案。

  • 动态内容个性化:使营销人员能够大规模定制内容,同时仍然关注个别用户的偏好和行为,以提高参与度和转化率。例如,我们将在第十一章中展示如何将 GenAI 与检索增强生成RAG)相结合,根据个人的浏览历史和购买行为创建个性化的推荐和电子邮件内容。

  • 内容生产效率:自动化内容生成过程,显著减少生产营销材料所需的时间和资源。

然而,GenAI 并非万能的解决方案,尤其是在需要准确性和深度上下文理解的营销场景中。例如,在高度监管的行业或围绕社会问题的敏感活动中,任何失误都可能对品牌声誉造成重大影响,因此必须谨慎行事。虽然 GenAI 可以帮助这些情况下的头脑风暴,但如果未经仔细监控就部署 GenAI 内容,其不可预测性可能会带来重大风险。关于这一主题的进一步讨论将在第十三章中呈现,以及在第十章和第十一章中介绍提高其上下文理解策略。

GenAI 在高度监管的行业中的应用

当在医疗保健、金融服务、保险和法律服务等行业应用 GenAI 时,遵守严格的监管标准至关重要。这些应用的营销内容需要额外的审查,因为它们不仅需要准确和透明,还需要符合行业特定的合规措施。

预训练模型和 ZSL 的介绍

建立在前面章节所讨论的 GenAI 基础之上,我们现在将介绍一些与预训练模型和零样本学习ZSL)相关的核心概念。这些概念解释了模型如何利用大量现有数据,在不进行额外训练的情况下,为尚未遇到的情况生成真实、新的输出。重点关注文本数据,我们将讨论上下文嵌入和语义邻近性是如何作为两个关键概念来促进这一能力的。有了这些知识,你将能够理解并应用这些概念在本章以及后续章节中。

上下文嵌入

上下文嵌入,得益于之前讨论过的 LSTM 和 GPT 模型的进步,对于大型语言模型LLMs)如何理解和生成语言至关重要。正如在第五章中讨论的那样,嵌入是数据的密集向量表示,在多维空间中捕捉关键特征。早期的模型如 Word2Vec 和 GloVe 生成静态嵌入,其中相同的单词总是有相同的向量。相比之下,先进的模型如 BERT 和 GPT 创建上下文嵌入,其中单词表示根据其在上下文中的使用而变化。有效的 NLP 嵌入保留了原始数据的语义关系,这意味着在向量空间中相似的向量彼此更接近。这种适应性是 ZSL 等应用的基础,这些应用依赖于模型将学习到的知识应用于新任务的能力,而无需特定的训练数据。

在本章早期对 GenAI 的概率性质的探索中,我们注意到文本生成与视频或音频中的序列预测类似,即每份数据的相关性取决于其前驱。作为一个类比,考虑一下谷歌的自动补全功能如何根据已输入单词的上下文来调整建议。这个相同的概念是模型如 BERT 的变革性潜力之所在,它通过上下文嵌入分析前后的文本上下文,以增强语言理解和预测准确性。

GPT 模型更进一步,采用自回归框架。术语“自回归”意味着模型基于其自身的先前输出进行预测,这意味着它根据模型的所有先前输出作为上下文来预测后续的单词。例如,当为营销博客开发内容日历时,GPT 模型可以分析过去的文章和热门话题,以建议与品牌声音和受众兴趣相符的新帖子。这与本章前面讨论的基于转换器的模型不同,后者可以同时查看前后的单词。然而,这种自回归模型可以提供更细致的文本生成,使它们能够创建具有更高一致性的叙事,这可能比双向模型更无缝地实现。

上下文嵌入的重要性

LSTM 或 GPT 模型的上下文嵌入可以通过评估文本的整体更多内容来实现细微的理解。

例如,在填写“暴风雨的海面平静下来,因为 ___ 驶进了港口”的空白处时,一个利用先前和后续上下文的模型可以更准确地推断出“船”,而一个只有先前上下文的更简单模型可能会错误地预测“天”这个词。

语义邻近度

从我们对上下文嵌入及其在语言模型中关键作用的讨论中过渡,我们现在将探讨语义邻近度。上下文嵌入不仅通过考虑文本的动态上下文来增强对文本的理解;它们还作为评估文本中单词或短语之间语义关系的基本工具。当我们考察语义邻近度的概念时,这种细微的理解至关重要,它涉及量化两个语言项目在意义上的密切程度或距离。

例如,考虑短语“限时优惠”和“独家交易”。这两个短语具有紧密的语义邻近度,因为它们都与针对潜在客户的定向促销相关。相反,“限时优惠”和“客户反馈”这两个短语会有更大的语义距离。

通过余弦相似度等方法,可以有效地评估语义邻近度,这些方法测量的是在多维空间中代表这些项目的向量的角度。这个基于向量空间几何的度量,提供了一种清晰、数学的方式来捕捉和比较嵌入编码的意义。数学上,余弦相似度如下所示:

图片

其中 AB 是向量(一个词、短语、文档等的语义嵌入),AB 表示它们的点积,而 ∥A∥ 和 ∥B∥ 表示它们的模长。余弦相似度的值范围从 -1 到 1。值为 1 表示向量在方向上完全相同,表示最大相似度。值为 0 表示向量正交,表示没有相似度。

虽然,在实践中,许多复杂的文本嵌入是高维的,可以从几百维到几千维不等,但我们可以通过两个向量在二维空间中更直观地说明余弦相似度的概念。在下面的代码中,我们通过向量 AB 说明了余弦相似度的计算,以及与它们余弦相似度相关的角度:

A, B = np.array([2, 2]), np.array([3, 0])
cos_sim = np.dot(A, B) / (np.linalg.norm(A) * np.linalg.norm(B))
angle = np.arccos(cos_sim)
plt.figure(figsize=(6,6))
for vector, color, label in zip([A, B], ['red', 'green'], ['Vector A', 'Vector B']):
    plt.quiver(0, 0, vector[0], vector[1], angles='xy', scale_units='xy', scale=1, color=color, label=label)
plt.plot(0.5 * np.cos(np.linspace(0, angle, 100)), 0.5 * np.sin(np.linspace(0, angle, 100)), color='blue', label=f'Cosine Similarity = {cos_sim:.2f}')
plt.axis([-1, 4, -1, 4])
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.title('Cosine Similarity between Vectors')
plt.legend()
plt.show() 

图片

图 9.3:两个向量 A 和 B 之间余弦相似度的可视化,显示了它们在二维空间中的角度关系

在余弦相似度的数学基础上继续,我们可以将这个相同的概念应用于探索不同上下文中单词的多义性。考虑在两个不同句子中使用的单词“light”:

他打开 来阅读

这种 轻质 织物非常适合夏天

这些句子展示了“光”这个词的不同语义实例,通过使用 BERT 等上下文嵌入模型,我们可以使用余弦相似度来量化这些情况下“光”的语义差异。

例如,在以下代码中,我们:

  1. 导入库并加载预训练的 BERT 模型和分词器。

  2. 将句子分词,将它们转换为 BERT 模型期望的格式。

  3. 将分词句子通过 BERT 模型传递以获得嵌入。

  4. 通过在每个分词句子中找到“光”这个词的索引并从模型输出中提取其对应的嵌入来提取“光”的嵌入。

  5. 计算余弦相似度并打印结果。

要做到这一点,请使用以下代码:

import tensorflow as tf
from transformers import BertTokenizer, TFBertModel
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = TFBertModel.from_pretrained('bert-base-uncased')
sentence_1 = "He turned on the light to read."
sentence_2 = "The light fabric was perfect for summer."
tokens_1 = tokenizer(sentence_1, return_tensors="tf")
tokens_2 = tokenizer(sentence_2, return_tensors="tf")
outputs_1 = model(tokens_1)
outputs_2 = model(tokens_2)
light_index_1 = tokens_1['input_ids'][0].numpy().tolist().index(tokenizer.convert_tokens_to_ids('light'))
light_index_2 = tokens_2['input_ids'][0].numpy().tolist().index(tokenizer.convert_tokens_to_ids('light'))
embedding_1 = outputs_1.last_hidden_state[0, light_index_1]
embedding_2 = outputs_2.last_hidden_state[0, light_index_2]
cosine_similarity = tf.keras.losses.cosine_similarity(embedding_1, embedding_2, axis=0)
cosine_similarity = -cosine_similarity.numpy()
print("Cosine similarity between 'light' embeddings in the two sentences:", cosine_similarity) 
Cosine similarity between 'light' embeddings in the two sentences: 0.47577658 

余弦相似度值范围从-1 到 1。如前所述,1 表示向量完全相同,而 0 表示正交向量,没有相似性。在这种情况下,余弦相似度为 0.48 表明两个句子中“光”的嵌入相似但并不相同。

预训练模型

预训练模型是之前在大型数据集上训练过的机器学习算法,用于执行通用任务,如理解自然语言或识别图像中的对象。预训练模型的作用根本在于它们使用训练时使用的嵌入。对于文本,这些嵌入不仅使模型能够动态地掌握上下文,而且也是将这些模型适应特定任务(如第五章中讨论的情感分析)的基础,而无需或仅需少量额外的训练。这种适应性对于 ZSL 等应用至关重要。

预训练模型的出现通过提供可以微调或直接用于推理的基础模型,使最先进的 AI 访问民主化。这些模型不仅降低了 AI 驱动解决方案的部署成本和时间,还降低了计算资源和能源消耗,使 AI 更加易于访问且环保。在营销领域,预训练模型提供了显著的优势。它们使营销人员能够快速部署先进的 AI 解决方案,用于个性化内容创建、客户情绪分析和定向广告等任务。

以前只有大型或高度专业化的科技公司才能获得的复杂人工智能模型,现在以极低成本成为小型企业和甚至个人消费者的可能。以 GPT-3 为例,2020 年发布时从头开始训练这样一个模型估计需要数百万美元,这个数字包括了计算成本和人力专业知识。如今,用户可以通过公司的 API 使用这个(或更先进的)模型进行推理,生成文本,费用仅为数百字内容的几分钱。

预训练模型的关键组件包括:

  • 权重:它们代表从训练数据集中学习到的参数,并编码了迁移学习所需的广泛知识和模式

  • 架构:模型的详细结构,说明输入如何通过各个层处理以生成输出

  • 预处理步骤:如分词和归一化等程序,以确保数据与模型训练的兼容性

让我们详细看看这些组件。

模型权重

模型权重是神经网络的核心,包括预训练模型。权重是通过大量训练得到的优化参数,以最小化损失,作为模型学习知识的存储库。例如,在 GPT 等语言模型中,这些权重捕捉了语言的复杂性,如语法和上下文,使得生成的文本不仅连贯,而且上下文丰富。预训练模型在 ZSL 等任务中的有效性源于这些权重,它们使您能够从模型训练数据中泛化到新的、未见过的数据,并具有显著的准确性。

为了更好地理解模型权重从何而来,考虑以下人工神经网络ANN)的例子,如图所示:

图 9.4:第六章中的示例 ANN 架构

这由三个主要层组成:输入层、隐藏层和输出层。在训练过程中,神经网络会经历正向传播和反向传播。正向传播涉及将数据通过网络生成输出,而反向传播则根据预测误差调整权重。通过这些迭代,网络学习每个神经元的最佳权重,最小化预测误差并提高模型性能。

模型架构

预训练模型的架构与其权重密切相关。它界定了数据在模型层之间处理和转换的结构,并指导模型适应执行新任务。例如,更深层的语言模型架构可能更适合复杂推理任务,而具有特别配置的注意力机制的模型可以在推理过程中提供更精细的控制。对于图像识别,这些模型产生的中间表示,如预训练 CNN 在各个层提取的特征,也可以作为分类任务的宝贵起点。

在理解机器学习模型的架构时,绘制其架构及其参数有助于可视化其关键方面。在此,我们使用 Keras 的plot_model()来展示这一点,作为由两个 LSTM 层组成的简单 LSTM 模型的演示:

!conda install pydot
!conda install graphviz
from tensorflow.keras.utils import plot_model
model = Sequential([
    LSTM(64, return_sequences=True, input_shape=(10, 128)),
    LSTM(64),
    Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
plot_model(model, show_shapes=True, show_layer_names=True) 

图 9.5:基于简单 LSTM 的神经网络架构

这张可视化图清晰地描绘了模型的结构,显示了从输入经过两个具有 64 个单元(或神经元)的 LSTM 层,到配置有 10 个 softmax 单元的最终密集输出层的演变。根据图中的标签,结构可以进一步分解如下:

  • 输入层(lstm_input):接受形状为 (10, 128) 的数据,处理 10 个时间步长的序列,每个时间步长有 128 个特征。

  • 第一层 LSTM(lstm):包含 64 个单元,返回序列,处理输入并将相同长度的序列传递给下一层 LSTM。

  • 第二层 LSTM(lstm_1):也有 64 个单元,但不返回序列,将第一层 LSTM 的输出压缩成一个单一向量。

  • 密集输出层(密集):最后一层是一个包含 10 个单元的密集层,并使用 softmax 激活函数,输出 10 个类别(分类或标签)的概率分布。

预处理步骤

预处理步骤对于确保数据与预训练模型的训练过程兼容至关重要。以下是一些例子:

  • NLP 分词将文本分解成 LLM 模型期望的单词或子词。

  • 对于图像,归一化可以调整图像像素值到一个共同尺度,以促进模型从数据中学习和生成预测的能力。

这些预处理步骤对于有效地利用预训练模型至关重要,确保输入数据与模型训练时所用的数据形式相匹配。

零样本学习

在我们探索了预训练模型及其基本组件之后,现在我们将关注它们在零样本学习(ZSL)中的应用。正如我们稍后将要讨论的,ZSL 背后的基本原理允许营销人员动态生成相关内容,甚至几乎实时地针对个别消费者进行营销活动。在我们进入这些例子之前,本节将提供一些关于 ZSL 的背景信息以及它是如何使模型能够应用所学知识并推断在训练期间未明确涵盖的任务或类别的信息的。这种能力扩展了预训练模型的应用范围,使它们能够泛化到未见过的数据和场景。

学习和预测的机制

ZSL 的核心操作是通过在高维嵌入空间中使用输入和输出的变换和映射,使用两个主要功能:

  • 一个嵌入函数 f,它将输入(如图像或文本)转换为嵌入空间内的特征向量。

  • 一个语义属性函数 g,它将类别标签与嵌入空间中的语义属性关联起来。这些属性用普遍的、可区分的特征来描述类别,存在于属性空间 A 中。

作为简化的例子,考虑将 ZSL 应用于区分动物的情况。嵌入函数f将动物的视觉图像转换为嵌入空间中的高维特征向量——例如,处理麻雀和鹰的图像以显示不同的特征向量,代表它们的视觉特征。同时,语义属性函数g根据语义属性将类标签,如麻雀,映射到相同的嵌入空间中的向量。麻雀的属性可能包括[′small_size′, ′brown_color′, ′has_wings′],而鹰可能被描述为[′large_size′, ′sharp_beak′, ′has_wings′]。然后对这些属性进行量化,其中small_size可能编码为尺寸尺度上的0.2,而large_size0.8

图 9.6:从输入图像或类标签到嵌入空间的示例映射

图 9.6所示,通过将图像和类属性放置在相同的嵌入空间中,模型可以将图像的特征向量与最近的类属性向量相匹配。即使模型在训练过程中从未见过麻雀或鹰的图像,这种匹配也可以通过识别它们属性与已知类之间的重叠来实现。为了找到最佳的类匹配,算法负责优化兼容性函数,该函数量化了输入特征向量与类属性向量之间的匹配程度。ZSL 预测随后涉及选择对未见实例兼容性最大的类。

输出参数

有许多关键参数可以指定以影响 ZSL 模型的输出。这些参数通过调整模型在采样过程中的行为来定制输出。在 GPT 等模型用于文本生成的情况下,最常用的三个参数包括:

  • 温度

  • Top P(核采样)

  • 频率惩罚

通过影响模型从兼容性函数生成的概率分布中采样的方式,每个参数都允许调整模型输出的创造力、连贯性和多样性。以下各节提供了关于每个这些参数背后理论的进一步细节。

温度

温度参数在确定预测分布的随机性或置信水平方面起着至关重要的作用。从数学上讲,调整温度会以以下方式修改用于计算下一个单词概率的softmax函数:

其中 T 是温度,logit 代表模型的原生输出。较低的温度使分布更尖锐,使模型的预测更确定性和更少变化,而较高的温度则使分布更平坦,鼓励预测的多样性,但可能会引入较少的连贯性,因为模型更有可能采样不太可能的单词。

为了说明这个概念,让我们考虑一个预测文本生成场景,即句子“The cat sat on the ___.”中的下一个词。为了简化,假设我们的模型考虑了五种可能的完成方式:“mat”,“tree”,“ball”,“bed”,和“table”,其初始 logit 反映了它们的概率(在这种情况下为了简化,手动分配)。我们可以使用以下代码来生成一个可视化,展示如何改变温度参数 T 影响 softmax 函数,改变这些潜在下一个词的概率分布:

logits = np.array([2, 1, 0.1, 5, 3])
labels = ['mat' , 'tree', 'ball', 'bed', 'table']
def softmax_temperature_adjusted(logits, temperature):
    exp_logits = np.exp(logits / temperature)
    return exp_logits / np.sum(exp_logits)
temperatures = [0.5, 1, 2, 4]
plt.figure(figsize=(12, 8))
for T in temperatures:
    probabilities = softmax_temperature_adjusted(logits, T)
    plt.plot(labels, probabilities, marker='o', label=f'Temperature = {T}')
plt.title('Effect of Temperature on Prediction Distribution')
plt.ylabel('Probability')
plt.xlabel('Words')
plt.legend()
plt.grid(True)
plt.show() 

这给我们以下输出:

图 9.7:温度参数对句子“The cat sat on the ___”中潜在下一个词的 softmax 概率分布的影响可视化

如图中所示,在较低的温度下,分布更尖锐,将概率质量集中在更少、更可能的输出上,如“bed”。随着温度的升高,分布变得更平坦,给更广泛的、可能不太可能的单词输出更高的概率,如tablemat

Top P

Top P,或称为核采样,提供了一种动态的方式来聚焦生成过程,使其集中在最可能的输出集上。模型不是考虑整个词汇表,而是将其选择限制在累积概率超过阈值 P 的最小单词集。

这种方法可以被视为根据模型置信度动态调整考虑范围,其公式如下:

其中 N 是考虑的单词数量,P(w[i]) 是第 i 个单词的概率。这项技术有助于在多样性和相关性之间保持平衡,确保生成的文本既合理又不受最可能预测的过度约束。

频率惩罚

频率惩罚解决了模型倾向于重复相同单词或短语的问题,增强了输出的多样性。它根据生成文本中每个单词的先前出现次数修改每个单词的概率:

其中 P(w[i]) 是单词 w[i] 的原始概率,Occurrence (w[i]) 是 w[i] 在文本中出现的次数。这种调整通过惩罚模型已经使用的单词来鼓励探索新的词汇和想法,从而促进更丰富和更多样化的输出。

市场文案的零样本学习(ZSL)

现在,我们将通过一个电子商务品牌推出新的环保厨房用品和时尚产品线的例子来讨论 ZSL 的实际应用。传统上,创作吸引人的产品描述和促销内容可能需要熟悉品牌语气和可持续设计复杂性的作家进行大量研究和创意工作。然而,有了 ZSL,品牌可以将产品线的简洁描述输入到一个预训练模型中,强调“可持续”和“环保运动装”等关键词,立即生成适合品牌且适用于数字平台的适当内容输出。通过自动化内容生成的初始阶段,品牌现在可以更多地关注战略、参与度和分析其营销活动的有效性等高价值工作。

通常,为了有效地将 ZSL 整合到您的营销策略中,请考虑以下迭代过程作为模板:

  1. 定义你的内容目标以及你想要传达的关键信息。

  2. 创建简洁的提示,包含这些目标和信息,并融入相关关键词和主题。

  3. 尝试不同的参数(温度Top P频率惩罚)来调整生成内容的风格和多样性。

  4. 生成多个内容变体,以探索不同的角度和想法。

  5. 审查和精炼输出,选择与您品牌语气和目标一致的最佳选项。

  6. 根据受众反馈和性能指标,将生成的内容作为进一步定制和优化的起点。

在以下子节中,我们将重点关注先前工作流程的第 1-4 步,第 5 和 6 步将在后续章节的示例中介绍。

在 Python 中准备 ZSL

为了演示 ZSL 的 Python 设置过程,本节将介绍使用免费开源模型以及需要付费 API 实现的更高级模型的基本步骤。我们将使用 Hugging Face Transformers 库中的模型演示前者,并使用 OpenAI 的 API 服务演示后者的设置。

紧跟 Hugging Face 更新

Hugging Face 的 Transformers 库经常更新,使得之前仅通过付费 API 服务才能获得的先进模型现在可以免费使用。有关最新 Hugging Face 模型的详细信息,请参阅他们的文档:https://huggingface.co/models

使用 Hugging Face 上可用的 gpt2 模型进行 ZSL 任务的基本设置如下:

from transformers import pipeline
generator = pipeline('text-generation', model='gpt2')
prompt = "Write a compelling product description for eco-friendly kitchenware emphasizing sustainability:"
completion = generator(prompt, max_length=100, num_return_sequences=1, temperature=0.7)
print("Generated text using HuggingFace's GPT model:", completion[0]['generated_text']) 

运行此提示将产生如下输出:

"Your kitchen will save you time and energy. It will save you money. It will make you feel good. It will help you get the most out of your kitchen and minimize waste. It will help you get good results. You'll save money and your home will be healthier." 

我们可以将这与其他具有相同参数但使用 OpenAI 的 GPT-4 更先进文本生成能力的模型的输出进行对比。执行此模型目前需要创建一个 OpenAI 账户,然后生成一个可以替换到以下代码中的 API 密钥:

from openai import OpenAI
client = OpenAI(api_key = 'XXX') #insert your api key here
completion = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user",  "content": "Write a compelling product description for eco-friendly kitchenware emphasizing sustainability:"}],
    max_tokens=100, n=1, temperature=0.7)
print(completion.choices[0].message) 

这会导致以下类型的响应:

"Introducing our premium range of eco-friendly kitchenware, designed for the conscious home cook. Every item in this collection is expertly created from sustainable materials, ensuring minimal impact on our environment. From bamboo cutting boards to recycled stainless-steel knives, each piece combines functionality with eco-friendly design. Our eco-friendly kitchenware is not only durable and high-performing, but also promotes a healthier lifestyle and a greener planet." 

从这两个响应中可以看出,像 GPT-4 这样的高级模型显著提高了生成内容的关联性和质量。这是因为,与 GPT-2 相比,GPT-4 在深度学习架构、更大的训练数据集和更复杂的微调技术方面取得了重大进步。因此,我们将使用 GPT-4 获得的结果在本章的剩余部分进行使用。

然而,有效利用 ZSL 的关键不仅在于模型的能力,还在于有效地选择塑造输出的输入信息。这里最关键的部分包括创建一个有效的提示,以及设置其他参数,如温度和 Top P,如本章前面所讨论的。

谨慎使用 LLM 的输出

在没有人工审查的情况下直接依赖任何 LLM 的输出作为关键活动内容可能存在风险!始终考虑将 GenAI 模型的初始输出视为创意起点,然后根据需要迭代和改进它们,以确保与您的品牌声音和目标保持一致。

创建一个有效的提示

创建一个有效的提示是利用 ZSL 进行营销文案的关键步骤。在 ZSL 中,提示实际上成为了一个模型的操作手册,告诉它需要生成什么类型的内容,以及其风格、语气和实质。

以下是一些关于如何制定提示以从模型中获得最佳营销文案内容的指南:

  • 清晰:确保您的提示具体说明您想要的内容,无论是产品描述、标题还是行动号召。

  • 情境:提供足够的背景信息以引导模型。对于环保产品,提及关键卖点,如可持续性或生物降解性。

  • 创意:虽然清晰度至关重要,但留出创意空间可以产生令人惊讶和创新的成果。像“想象...”或“创造一个故事,其中...”这样的短语可能特别有效。

  • 简洁:冗长的提示会分散焦点。在包含必要细节的同时追求简洁,确保模型保持主题。

在以下章节中,我们将通过示例展示提示质量的影响,包括不同类型的营销文案。虽然好的提示可以引发详细、相关和吸引人的内容,但差的提示可能导致模糊和缺乏灵感的结果。为了生成这些响应,我们将定义以下函数:

def generate_response(prompt, model="gpt-4", max_tokens=100, temperature=0.7, n=1):
    response = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": prompt}],
        max_tokens=max_tokens,
        n=n,
        temperature=temperature)
return response.choices[0].message.content 

在接下来的示例中,这个功能将与不同的提示类型一起使用。

示例 1:产品描述

在本例中,我们将为我们的电子商务品牌生成产品描述,该品牌即将推出环保厨房用品的新系列。

以下是一个差的提示的例子:

poor_product_description = "Talk about bamboo cutlery."
generate_response(poor_product_description) 

这会产生:

Bamboo cutlery is a type of eating utensil made from bamboo, a fast-growing renewable resource. This form of cutlery includes items such as forks, knives, spoons, and chopsticks. They are an eco-friendly alternative to plastic disposable cutlery due to their reusable nature and biodegradable properties. Bamboo cutlery is lightweight and durable, making it a popular choice for camping, picnics, and travel. 

现在,让我们看看以下良好提示的例子:

good_product_description = "Write a captivating description for a bamboo cutlery set designed for eco-conscious consumers, emphasizing its sustainability and style."
generate_response(good_product_description) 

此提示将产生以下输出:

Discover the perfect harmony of sophistication and sustainability with our Bamboo Cutlery Set. Designed for the eco-conscious consumer, this set is not only a statement of your commitment to the environment but also a reflection of your exquisite taste. Each piece is crafted from 100% organic bamboo, a renewable resource that grows significantly faster than traditional hardwoods. This set boasts a sleek, minimalist design that perfectly complements any table setting, from casual picnic to elegant dinner parties. 

从营销角度来看,这个例子说明了在为产品描述使用 ZSL 时创建详细且针对特定受众的提示,以及这如何导致生成的响应更加具体。然而,值得注意的是,年长的消费者可能更重视直接、事实性的信息,因此,从参与度的角度来看,他们可能更喜欢更通用的提示的响应。在个人消费者层面调整 GenAI 的输出同样至关重要,这也是第十一章讨论的主题。

示例 2:博客标题

在我们的下一个例子中,我们将专注于另一种类型的营销文案,通过为我们的电子商务品牌生成博客标题。

我们首先将生成一个差的提示:

poor_blog_title = "Write a title about kitchenware benefits."
generate_response(poor_blog_title) 

这会产生以下输出:

Exploring the Numerous Benefits of High-Quality Kitchenware 

这里是一个良好提示的例子:

good_blog_title = "Create an intriguing title for a blog post highlighting the top five benefits of biodegradable kitchenware for sustainable living."
generate_response(good_blog_title) 

这给我们带来了更吸引人的结果:

Unlocking Sustainable Living: Top 5 Benefits of Biodegradable Kitchenware 

比较这些用于博客标题的提示,可以说明具体性和受众定位对内容有效性的影响,其中强调可生物降解厨房用品的具体提示会产生与可持续性更一致的内容。相比之下,模糊的提示会导致一个通用的标题,在众多类似内容中无法脱颖而出。为了进一步调整 LLM 生成的语言,我们还可以使用少量样本学习FSL),这是下一章的主题。如果使用得当,FSL 可以在语言上实现相同的具体性,但以一种与品牌独特声音一致的方式,以便区分 LLM 的输出与其他 LLM 可能产生的输出,即使给出相同的提示。

使用 AI 导航主题内容

在生成博客文章时,了解您模型的训练数据的新鲜度至关重要。如果没有当前数据或网络搜索功能,您可能会基于过时的趋势创建内容,这些趋势缺乏相关输出的必要背景。

示例 3:社交媒体配文

在本例中,我们将为关于我们电子商务品牌的帖子生成 Instagram 配文。

让我们先看看一个差的提示:

poor_social_media_caption = "Make an Instagram post for kitchenware."
generate_response(poor_social_media_caption) 

这会产生以下结果:

'Spice up your kitchen game with our premium-quality kitchenware! 🍳🥄 From non-stick pans to sharp, durable knives, we have everything you need. Cook like a pro and serve in style! Get yours today at our store. 🍽️👩🍳👨🍳 

接下来,我们将查看一个良好提示的例子:

good_social_media_caption = "Create an engaging and witty Instagram caption for our latest eco-friendly kitchenware line, focusing on reducing plastic waste."
generate_response(good_social_media_caption) 

这会产生:

Kiss plastic goodbye👋and say hello to our chic, eco-friendly kitchenware!🍃Because every meal should be a feast for the eyes and gentle on the earth. #SustainableGourmet" 

这两个 Instagram 配文提示之间的差异说明了具体提示如何生成一个配文,不仅以其机智的语言吸引人,而且直接吸引环保意识强的消费者,这可能会增加点赞、分享和评论——所有都是社交平台上的关键指标。相比之下,模糊的提示导致了一个通用的、广泛的配文,虽然信息丰富,但缺乏专注的吸引力,可能无法吸引寻找环保产品的某些潜在客户。

参数调整的影响

虽然创建一个有效的提示是基础,但调整模型的参数同样重要,以确保生成的内容与期望的营销风格相一致。在本节中,我们将探讨如何通过调整温度和 Top P 等参数来影响语言模型的输出。从厨房用品过渡到,我们将通过为环保和可持续时尚线的发布生成营销口号来展示这一点。

我们将通过定义以下 Python 函数来完成这项工作,输出每个参数调整后口号的三种变体:

def generate_slogan(prompt, temperature=1.0, top_p=1.0):
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}],
        max_tokens=15,
        temperature=temperature,
        top_p=top_p,        n=3)
    return (response.choices[0].message.content, response.choices[1].message.content, response.choices[2].message.content) 

让我们使用基础情况,将temperatureTop P都设置为1.0的值:

generate_slogan(prompt) 

这会产生:

('"Dress with Purpose: Eco-Elegance Never Goes Out of Style."',
 '"Style with Substance, Fashion with Consciousness!"',
 '"Dressing the world, Preserving the planet."') 

现在,让我们调整每个参数并查看我们得到的输出:

  • Temperature:提高温度会使响应更加多样化和富有创意,但可能不那么连贯:

    generate_slogan(prompt, temperature=1.8) 
    

这会产生:

('"Drape Yourself in Earth Love: Stylishly Sustainable Fashion Favorites"',
 '"Wear the change, leave no trace."',
 '"Leave no carbon footprints, only stylish one - Wear Eco in Style"') 

相反,降低温度会导致更可预测和一致性的输出:

generate_slogan(prompt, temperature=0.3) 

这次,提示产生了以下输出:

('"Style with Sustainability: Dress Green, Live Clean!"',
 '"Style with Sustainability: Fashion for a Better Tomorrow"',
 '"Style with Sustainability: Fashion for a Future"') 
  • Top P:将top_p从其最大值 1.0 降低,会使生成的口号的多样性减少,因为模型变得更加保守,它倾向于只选择最可能的输出:

    generate_slogan(prompt, top_p=0.4) 
    

这会产生:

('"Style with Sustainability: Fashion for a Better Future"',
 '"Style with Sustainability: Fashion for a Greener Tomorrow"',
 '"Style with Sustainability: Fashion for a Greener Tomorrow"') 

通过这些示例,我们可以观察到参数调整对生成内容性质的重大影响。这证明了参数调整在创建既相关又吸引人、又符合品牌风格和信息的营销口号中的重要性。

摘要

在这一章中,我们探讨了 GenAI 和 ZSL 在营销内容创作中的变革潜力。我们介绍了基础 GenAI 概念,并讨论了这些模型生成文本、图像等机制,特别关注文本生成。分析上下文嵌入和语义邻近性突出了预训练模型如 GPT 和 BERT 在理解和生成语言时带来的细微差别,这些模型具有显著的可适应性和准确性。

我们讨论的核心是将 ZSL 应用于创建营销文案,这允许品牌在没有大量训练数据的情况下生成引人入胜的内容。我们概述了一个战略过程,通过强调创建清晰、情境化和创造性的提示的重要性,将 ZSL 整合到营销策略中。这种逐步的方法——定义内容目标、实验参数和优化输出——使营销人员能够有效地利用 LLMs 的力量。我们还学习了如何调整温度和 Top P 等参数可以帮助微调生成内容的创造力、连贯性和多样性。这些实用见解将帮助您优化营销文案,使其与品牌信息和活动目标保持一致。

展望未来,下一章将深入探讨更高级的领域,即少样本学习和迁移学习。在 ZSL 的基础上,我们将探讨这些技术如何进一步优化 GenAI 模型以实现目标信息传播。这包括通过最小示例(FSL)调整模型以适应新环境,以及通过品牌或客户特定信息(迁移学习)更新模型,确保生成内容的一致性和相关性。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人相聚,并与其他 5000 多名成员一起学习,详情如下:

packt.link/genai

第十章:通过少样本学习和迁移学习增强品牌影响力

本章探讨了少样本学习FSL)的能力及其通过定制营销策略增强品牌影响力的价值。在上一章中介绍了零样本学习ZSL)的见解之后,我们现在关注 FSL 如何通过利用少量示例,使 AI 模型能够快速有效地适应新任务。这种方法在市场营销中尤其有价值,因为能够迅速调整内容以适应不断变化的消费者偏好和市场趋势至关重要。

首先,我们将介绍 FSL 在元学习背景下的基本概念,作为促进从小数据集快速学习的技术。然后,我们将通过实际示例探索 FSL 与迁移学习之间的协同作用;虽然 FSL 在快速适应新任务时效果显著,但迁移学习通过利用针对特定任务微调的预训练模型来补充这一点,从而减少了大量模型重新训练的需求。

本章强调了将 FSL 与相关策略相结合如何优化营销工作,使其更具响应性和效率。本章将为您提供以下理解:

  • 理解 FSL 的核心概念及其与迁移学习的相似之处和不同之处

  • 认识到在有限数据下快速适应新营销条件的 FSL 的实际好处

  • 将 FSL 和迁移学习技术应用于现实世界的营销场景,以增强品牌信息和消费者参与度

探索 FSL 导航

在市场营销领域,能够快速调整内容策略以满足品牌不断变化的需求是非常宝贵的。FSL 因其能够有效地从有限的数据中学习和执行任务而脱颖而出。虽然 ZSL 旨在推理时无需任何新类别的具体示例,而是依赖于从先前学习任务中得出的对任务的通用、抽象理解,但 FSL 使用少量示例来适应新任务。这种适应通常依赖于对学习到的模式更直接的应用,并且可以通过数据微调,这使得在有示例数据的情况下特别有效。这种效率使得营销人员能够快速测试新的策略,例如为不同的客户细分市场个性化电子邮件活动或快速调整社交媒体内容以反映新兴趋势,而无需花费大量时间收集和训练大量数据集。例如,一位营销经理可能会使用 FSL 来生成符合公司品牌重塑计划的定制营销文案,正如我们将在将 FSL 应用于提高品牌一致性部分中讨论的那样,即使这种重塑内容的示例有限。

随着我们进一步探索 FSL 在增强品牌存在感方面的效用,构建对上一章中引入的概念生成式 AI(GenAI)的概念理解至关重要。FSL 基于这样一个观点,即智能系统可以通过仅使用少量训练示例来学习新的概念或任务,大量借鉴先前知识和应用复杂的元学习算法。这次讨论将扩展你对这一概念的基础知识,弥合高级概念与实际应用之间的差距,这些实际应用对于理解本章后面给出的实际例子非常有用。

在其核心,FSL 通常通过元学习得到促进,这是一种使模型能够通过使用先前各种任务的学习来快速适应新任务的方法。然而,元学习只是众多可能方法中的一种,其他方法,如基于度量的学习,其中模型被训练去比较新实例与少数标记示例,使用学习到的度量或距离函数,也可以被使用。鉴于其作为 FSL 方法的广泛适用性和有效性,让我们在下一节进一步探讨元学习。

通过元学习理解 FSL

FSL(元学习)通常涉及元学习,或称为“学习如何学习”,其中模型被设计成能够根据从大量先前任务中学习到的知识快速适应新任务。

这在营销领域尤为重要,因为消费者的行为和偏好可能是动态的,需要能够快速调整而无需大量重新训练的模型。FSL 中的元学习框架在多种任务上训练模型,使它们能够发展出一种通用的理解或内部表示,可以高效地将新任务映射到最小额外的输入。元学习的一些关键组成部分包括:

  • 任务多样性:元学习算法在训练阶段接触到广泛的学习任务。这种接触帮助模型学习到更稳健的特征,这些特征不是过于特定于某一任务,但足够通用,可以适用于一系列未来的任务。这类似于一个营销团队在不同的活动类型(如电子邮件或社交媒体)中工作,并学会识别无论具体产品或受众如何都能预测成功的核心元素。

  • 快速适应:元学习的主要目标是实现对新任务的快速学习。这是通过模型能够使用最少量的训练数据对自己的条件进行微调来实现的。例如,如果一个在元学习框架中训练的模型面临一个新的产品发布,它可以快速调整其参数,根据其对类似产品的先前知识来优化产品的营销内容。

  • 优化技术:元学习涉及特殊的训练方案,如周期性训练,其中模型经历模拟的训练周期。每个周期涉及从一小组数据中学习,然后在新的一组来自同一任务的数据上进行测试。这训练模型能够很好地从小的数据样本中泛化。

现在,让我们在以下示例中看看这些基本原理的实际应用。

在营销中实现模型无关元学习

让我们考虑一个使用简单的模型无关元学习MAML)适应的元学习模型示例,以及它如何应用于优化营销策略。MAML 通过优化模型参数,使得少量梯度更新就能在新任务上实现快速学习。

了解更多关于 MAML

MAML 是由 Finn 等人于 2017 年在论文《模型无关元学习用于快速适应深度网络》中引入的广为人知的元学习算法。要深入了解该主题,包括交互式示例,请查看资源:https://interactive-maml.github.io/.

在这个简化的实现中,我们将模拟单个营销任务作为训练输入,作为在完整 MAML 部署中考虑的多个任务的代理。然后,我们将对任务训练一个简单的神经网络模型,然后使用我们的元训练结果来提高模型在不同任务上的适应性。以下图表提供了元学习框架的机制说明,以及将其应用于多个营销任务作为示例的可能外观:

图 10.1:在营销活动背景下可能的 MAML 框架的关键组件

源代码和数据

github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/tree/main/ch.10

模型无关技术旨在广泛适用于各种模型架构和任务。为了更好地理解 MAML 方法的机制,我们将将其应用分解为几个函数,这些函数是完整实现中可能涉及的简化:

  1. 首先,我们有一个函数generate_task,它创建具有自己系数集的模拟营销任务,这些系数代表活动数据,在这种情况下,它被表示为带噪声的二次关系。每个任务随机生成的系数决定了输入数据(如电子邮件活动长度、预算或覆盖范围)如何影响结果(如参与度或转化率)。然后task函数根据输入和系数计算活动的成功指标。请注意,我们提供了种子值,以便您的输出应与这里显示的一致,但您的结果可能仍然会因并行处理或 GPU 使用中的随机性而有所不同:

    import numpy as np
    import matplotlib.pyplot as plt
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense
    from tensorflow.keras.optimizers import Adam
    import tensorflow as tf
    np.random.seed(123)
    tf.random.set_seed(123)
    def generate_task():
        coefficients = np.random.randn(3) 
        def task(x):
            return coefficients[0] * x**2 + coefficients[1] * x + coefficients[2] + np.random.randn(*x.shape) * 0.1
        return task, coefficients 
    
  2. 接下来,我们有一个函数train_model_on_task,它通过在任务上执行短时间段的训练并使用Adam优化器更新模型权重来在之前函数生成的任务之一上训练模型。然后使用 TensorFlow 的GradientTape进行自动微分,计算用于最小化损失的梯度,该损失衡量模型的预测与活动实际结果之间的匹配程度:

    def train_model_on_task(model, task, steps=50, learning_rate=0.01):
        optimizer = Adam(learning_rate)
        for _ in range(steps):
            x = np.random.uniform(-3, 3, (50, 1))
            y = task(x)
            with tf.GradientTape() as tape:
                predictions = model(x, training=True)
                loss = tf.reduce_mean((predictions - y) ** 2)
            gradients = tape.gradient(loss, model.trainable_variables)
            optimizer.apply_gradients(zip(gradients, model.trainable_variables)) 
    
  3. 然后我们有meta_train_model函数,这是元学习的核心。这个函数通过优化模型在最小接触后快速适应新任务的能力来处理元训练过程。在实践中,模型首先在一个任务上接受训练,然后在新数据上对该任务进行评估。

从这次评估计算出的损失指导调整模型的初始参数,以便仅通过几次更新就能在新任务上带来显著的改进。请注意,在完整实现中,我们可能会使用reset_weights参数,以便在每个任务之后将模型的权重重置到任务特定训练之前的状态,并使用meta_optimizer根据任务性能更新模型的初始参数。这确保了模型不会过度拟合到特定任务,并保持其在任务之间的泛化能力:

def meta_train_model(base_model, meta_steps=50,                      meta_learning_rate=0.1):
    for _ in range(meta_steps):
        task, _ = generate_task()
        train_model_on_task(base_model, task, learning_rate=0.1) 
  1. 为了说明这个简化的示例在实际中的应用,我们可以首先初始化一个非常简单的神经网络,包含两层,以应用我们的元训练函数。在这里,首先是一个包含 10 个神经元的密集层,具有 sigmoid 激活,然后是一个最终只有一个神经元的密集层,用于捕捉模型基于输入特征的营销活动成功预测:

    model = Sequential([
        Dense(
            10,
            activation='sigmoid',
            kernel_initializer='random_normal',
            input_shape=(1,)
        ),
        Dense(1)])
    model.summary() 
    

这给我们以下总结:

图 10.2:简单的神经网络模型架构

  1. 现在让我们使用你的二次函数生成一个复杂任务的代理,并在训练之前绘制模型在这个任务上的性能:

    def plot_predictions(model, task, title):
        x = np.linspace(-3, 3, 100).reshape(-1, 1)
        y_true = task(x)
        y_pred = model.predict(x)
        plt.figure(figsize=(10, 5))
        plt.scatter(x, y_true, color='blue', label='True Values')
        plt.scatter(x, y_pred, color='red', label='Predictions')
        plt.title(title)
        plt.xlabel("Input Feature")
        plt.ylabel("Output Value")
        plt.legend()
        plt.show()
    complex_task, _ = generate_task()
    plot_predictions(model, complex_task, "Model Performance Before Meta-training on Task") 
    

下面的图表显示了在经过元训练之前模型的性能。正如我们所见,模型最初无法准确预测真实值,这表明需要进一步的训练和优化:

图 10.3:在任务上进行元训练前的模型性能

  1. 现在我们可以使用我们的算法进行元训练,然后再次绘制模型在相同任务上的性能:

    meta_train_model(model)
    plot_predictions(model, complex_task, "After Meta-training on Task") 
    

这产生了以下图表:

图 10.4:在任务上进行元训练后的模型性能

图 10.310.4所示,模型最初无法掌握数据中的任何二次关系。然而,在元训练之后,预测得到了改善。虽然这是一个只包括简单任务的简化实现,但这个实现框架为 MAML 作为准备模型进行 FSL 的工具的机制提供了一个基准。

克服 FSL 中的挑战

FSL 旨在充分利用最少的数据,但这可能伴随着固有的挑战,如过拟合和泛化能力差。过拟合发生在模型在非常小的数据集上训练时,学习到了噪声和不相关的细节,以至于它对新数据的性能产生了负面影响。为了减轻这一点,可以使用如 L2 正则化和 dropout 等正则化技术来简化神经网络模型的复杂度,帮助防止模型学习过于复杂的模式,这些模式泛化能力不佳。

防止过拟合的正则化技术

神经网络中两种常见的正则化技术是:

  • L2 正则化(权重衰减)在损失函数中添加了一个基于模型权重平方大小的惩罚。这阻止了权重过大,导致更简单且泛化能力更好的模型。

在这里了解更多,包括如何比较学习曲线以评估正则化的影响:developers.google.com/machine-learning/crash-course/regularization-for-simplicity/l2-regularization

  • Dropout 随机地在训练过程中停用(“丢弃”)神经元,以防止模型过度依赖特定的路径。

在 Srivastava 等人撰写的开创性论文《Dropout: a simple way to prevent neural networks from overfitting》中了解更多。

例如,在构建适合回归任务的神经网络模型时,我们可以添加这些类型的正则化。作为一个例子,该模型设计了一个适度的复杂架构,并包含具有两种类型正则化的多层:

from tensorflow.keras.layers import Dropout
from tensorflow.keras.regularizers import l2
def build_regularized_model(input_shape):
    model = Sequential([
        Dense(64, activation='relu', input_shape=input_shape,
              kernel_regularizer=l2(0.001)),
        Dropout(0.3), 
        Dense(32, activation='relu', kernel_regularizer=l2(0.001)), 
        Dropout(0.3), 
        Dense(16, activation='relu', kernel_regularizer=l2(0.001)),
        Dropout(0.3),
        Dense(1, activation='linear') 
    ])
    model.compile(optimizer=Adam(learning_rate=0.001),
                  loss='mean_squared_error')
    return model
input_shape = (10,)
model = build_regularized_model(input_shape)
model.summary() 

这导致了以下总结:

图片

图 10.5:模型架构摘要

该模型在其密集层中嵌入 L2 正则化,以控制权重大小并鼓励更简单的模型。在每个密集层之后也应用了 0.3 的 dropout,通过在训练期间停用随机神经元输出,减少了过拟合。这种正则化模式应用于隐藏层,以促进模型泛化能力。以下图展示了 dropout 在训练期间如何随机停用神经元:

图片

图 10.6:Dropout 神经网络模型。左:一个带有两个隐藏层的标准神经网络。右:对左侧网络应用 dropout 后产生的稀疏网络示例。交叉的单元已被丢弃。(来源:https://jmlr.org/papers/volume15/srivastava14a/srivastava14a.pdf)

如前所述,泛化是另一个关键挑战。在图像处理领域,数据增强技术,如图像旋转、裁剪或颜色调整,通常被用来人为地增强数据集的大小和变异性,帮助模型学习更通用的特征,这些特征在新任务上表现更好。在 NLP 应用中,可以采用如第五章中所述的数据增强技术,以及其他如同义词替换等技术,以增加鲁棒性并帮助在不同上下文中更好地泛化。

在 FSL(功能磁共振成像)中,一个显著的挑战也是如何在有限的训练数据下实现稳健的性能。根据学习模式的复杂性,模型可能需要更大的数据集来良好地泛化,因此如果没有这样的数据集,它们将难以学习有用的模式,导致在新任务上的表现不佳。迁移学习可以作为一种强大的、补充的策略来应对这一挑战。通过从在大规模和多样化的数据集上预训练的模型开始,你可以利用学习到的特征,并在你特定的 FSL 任务上微调模型。这种方法可以在最小数据量的情况下快速适应新任务,同时保留广泛的知识库,通过提供需要仅做轻微调整而不是从头开始学习的丰富初始特征集来补充 FSL。这种强大的方法也有其局限性和挑战,然而,这些是我们将在下一节讨论的主题。

优化 FSL 技术

提高 FSL 模型有效性的关键策略:

  • 防止过拟合:实施正则化技术,帮助模型专注于更简单、更一般的模式,而不是记住训练数据中的特定噪声。

  • 增强泛化:使用数据增强来扩展训练数据集。对于文本,像释义或注入同义词这样的方法有助于模型学习语言变体。

  • 利用迁移学习:利用在大规模数据集上预训练的模型,然后针对你特定的 FSL 任务进行微调。

导航迁移学习

迁移学习可以通过在新任务上仅进行少量调整来更有效地使用预训练模型来增强营销专业人士对 AI 的利用。虽然 FSL 使用新任务的一组示例进行快速适应,但迁移学习侧重于重新利用现有模型,而无需从新领域获取额外的示例。

这种方法利用了模型从前一任务中从大规模数据中获取的知识,将其应用于完全不同的领域的营销努力,而无需从头开始重新训练模型。换句话说,FSL 通过使用非常有限的数据示例来提高模型的适应性,而迁移学习在历史任务和当前任务之间关系强烈但为新任务训练基础模型所需的大规模标记数据集难以获得或成本高昂的环境中表现卓越。

迁移学习相较于 FSL 的另一个优势可能来自成本角度。例如,当使用付费 API 服务最先进的 GenAI 模型时,定价可能与生成响应所使用的输入大小相关。在 NLP 应用中,这通常由令牌计数来衡量。通过迁移学习进行微调时,基础模型只需调整一次。这意味着在微调阶段支付的令牌计数不会随着模型每次使用而重复,与 FSL 不同,FSL 可能需要每次都输入相同的相关示例。

使用迁移学习,模型微调的初始成本可以通过每次推理的较低成本来抵消,因为不需要向模型输入额外的示例。因此,当微调后的推理次数超过某个阈值时,迁移学习变得具有成本效益,从长远来看比 FSL 更便宜。

例如,以下是一个分解,说明了 FSL 和迁移学习之间潜在成本差异:

  • FSL API 费用

    • 基础成本:提示中使用的令牌的成本(每个令牌的成本 × 提示中的令牌数)

    • 每个示例的额外成本:每个令牌的成本 × 每个示例的令牌数

  • 迁移学习 API 费用

    • 初始微调成本:使用更大示例数据集调整预训练模型的一次性成本

    • 每次推理的成本:使用微调模型进行每次推理的成本

何时使用迁移学习而非 FSL

与 FSL 相比,在以下情况下迁移学习可能更有优势:

  • 使用频率高:模型使用得越频繁,初始微调成本就越快摊销。

  • 稳定的任务需求:新任务必须足够相似,以便微调后的模型无需进一步调整就能表现良好。

  • 复杂模式适应:虽然需要更多的数据,但它可以适应更深的模型层来学习更复杂的模式。

迁移学习的工作原理

在高层次上,迁移学习和其微调过程建立在类似于 ZSL 和 FSL 等技术建立的基础之上。ZSL 和 FSL 都旨在将现有知识应用于新任务。然而,它们在适应方法上主要存在差异。ZSL 基于学习到的抽象概念对未见任务进行假设,而不需要任何具体示例,而 FSL 使用少量示例来引导适应。迁移学习通过利用可以针对新任务进行特定微调的广泛训练的模型基础,扩展了这些概念,在 ZSL 的广泛泛化能力和 FSL 的快速适应特性之间提供了实用的平衡。当存在一个健壮的预训练模型,并且有来自高度相关领域的示例,但缺乏与新任务具体相关的示例时,迁移学习通常是首选的方法。

在更技术层面上,迁移学习中的微调涉及对已经在大型、多样化的数据集上经过良好训练的模型参数进行微妙但重要的调整。这种微调使学习到的特征适应于新、相关任务的具体情况,通常涉及调整模型的更深、更具判别性的层。这些修改使模型能够在保持其泛化能力的同时,优化在新领域特定任务上的性能。这与 FSL 不同,FSL 的微调旨在通过最小调整(通常仅限于模型的最终层或通过提示工程,其中无法调整可训练参数)使用非常少的示例快速适应模型。

下图说明了 ZSL、FSL 和迁移学习之间的差异:

图片

图 10.7:典型的 ZSL、FSL 和迁移学习实现及其机制之间的关键差异

使用 Keras 的迁移学习

在本节中,为了在自然语言处理领域之外提供多样性,我们将展示一个框架,说明如何将迁移学习应用于图像分类任务。本例将展示如何将预训练的图像识别模型适应于您选择的新的与营销相关的新挑战,例如识别所需的产品特征。

迁移学习过程的第一步是寻找一个在大型和多样化的数据集上经过广泛训练的预训练模型。在这里,我们将使用 VGG16 模型,该模型以其在图像识别中的稳健性能而闻名。VGG16 是一个卷积神经网络,通过在 ImageNet 数据集上使用超过一百万张图像进行训练,以将它们分类为一千个图像类别,如 Simonyan 和 Zisserman 在他们 2014 年的论文《非常深的卷积网络用于大规模图像识别》中详细描述的那样。

首先,我们将使用model.summary来总结这个模型的完整架构,以便更好地理解其层和组件:

from keras.applications.vgg16 import VGG16
base_model = VGG16()
base_model.summary() 

图 10.8:模型架构摘要

如此所示,VGG16 架构是一个由多个层组成的深度神经网络,这些层被设计用来处理和将图像转换成越来越抽象的形式,这对于分类任务是有用的。以下是基于前面摘要的简单分解:

  • 输入层:该层接受尺寸为 224 x 224 像素的图像,这是许多图像处理任务的标准化尺寸。每个图像有三个颜色通道(红色、绿色和蓝色),这解释了图 10.8中给出的形状中的3。在开始时每个层中给出的None实际上是一个批量大小的占位符,允许处理任意数量的图像。

  • 卷积层(Conv2D):这些层在网络中执行核心工作。VGG16 有多个卷积层堆叠在一起,每个层都有一定数量的过滤器,用于在图像的不同粒度级别检测不同的特征。例如,第一层卷积可能检测边缘,而深层层可能识别更复杂的模式,如纹理或特定对象。从 64 到 512 的过滤器数量增加反映了随着图像通过网络移动,检测到的图像特征复杂性的增加。

  • 最大池化层(MaxPooling2D):这些层与卷积层交错排列,用于减少输入到下一个卷积层的空间维度(宽度和高度)。例如,一个跟随 224 x 224 卷积层输出的池化层将其减少到 112 x 112,从而减少了所需的计算量,并有助于检测输入图像中小位移和旋转的不变主要特征。

  • 全连接层(Dense):在网络接近末端,卷积层的展平输出被送入这些密集连接层。这些层用于结合先前卷积层中的所有特征,最终将图像分类为 1,000 个类别之一。

  • 输出层(预测):最后一层输出图像属于 ImageNet 数据集中训练的 1,000 个类别的概率。具有最高概率的类别被作为模型的预测。

下面的可视化是从杨等人发表在医学研究文章中的摘要(www.nature.com/articles/s41598-021-99015-3)中提取的:

图 10.9:VGG16 深度神经网络架构的可视化

现在我们将适应这个模型进行迁移学习:

  1. 我们将再次将模型加载到内存中,但这次使用include_top=False选项,以便在最后一个卷积层之后截断模型。这将移动负责分类的顶层到预定义的类别中,并允许模型作为特征提取器,这意味着它输出一个复杂的特征图,代表输入图像的关键特征,但不输出特定的类别预测:

    base_model = VGG16(weights='imagenet', include_top=False, input_shape=(224, 224, 3)) 
    
  2. 我们可以在此基础上,通过添加自己的分类层来适应我们的新任务——产品分类,这些分类层将在特征提取器之上进行训练:

    from tensorflow.keras import layers, models
    model = models.Sequential()
    model.add(base_model)
    model.add(layers.Flatten()) 
    model.add(layers.Dense(256, activation='relu')) 
    model.add(layers.Dense(1, activation='sigmoid')) 
    
  3. 最后,可以使用新的、特定于任务的数据进行迁移学习来微调模型。这涉及到将预训练的基础模型层设置为不可训练的,从而冻结预训练层的权重,这通常建议避免训练的初始阶段忘记基础模型的大部分初始特征提取权重:

    base_model.trainable = False
    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) 
    

    自我引导练习:根据您的数据微调 VGG16

    要使用 VGG16 模型进行迁移学习并分类产品特征图像,请按照以下步骤操作:

    • 收集图像:收集您公司旨在分类的产品特征图像。来源可以包括在线目录、社交媒体或直接捕捉的实物库存。

    • 准备数据:将图像调整大小为 224 x 224 像素,以匹配 VGG16 的输入大小,并将像素值归一化到范围 [0, 1]

    • 训练模型:使用编译好的模型,并拟合您的图像(new_data)及其二进制标签 [0, 1],例如使用:

       model.fit(new_data, labels, epochs=5, batch_size=32) 
      
    • 评估和微调:根据性能,考虑调整学习率或逐渐解冻基础 VGG16 模型中的层。

使用 API 服务进行迁移学习

通过 API 服务进行迁移学习为希望利用前沿 AI 而无需处理本地实现复杂性的市场营销专业人士提供了一个实用的解决方案。使用可用的 API 服务进行迁移学习的实际好处包括以下几方面:

  • 访问高级模型:API 可访问模型的持续更新和优化确保了使用比公开可用的技术更先进的前沿技术。

  • 计算效率:将计算需求卸载到基于云的服务中,消除了对可能对个人或小型企业不可及的复杂硬件的需求。

  • 简化参数管理:这指的是自动处理学习率、梯度调整以及其他可能影响模型性能的复杂训练参数。

为了有效地应用迁移学习,微调数据集必须反映您品牌独特的特征。这可能包括客户反馈或经过审查的营销文案和产品描述。如果无法获得专有数据集,可以使用公开可访问的数据,例如关于类似产品或服务的评论或社交媒体帖子。关键是将这些数据编译成一个单独的文件,通常以 CSV 格式,并放置在 API 可访问的位置。然后,每个条目都需要根据其预期的标签或输出进行清晰标注。

以下是一个 CSV 格式的示例输入,它使模型更深入地理解在我们特定品牌背景下可持续性的含义,为下一节中将要讨论的动手示例奠定了基础:

text,label
"Our new line of kitchenware not only uses recycled materials but also ensures fair labor practices are upheld.",positive
"While our products are designed to be eco-friendly, we are also committed to improving our supply chain to support local communities.",positive
"Our brand continues to strive for environmental sustainability, though we have not yet addressed labor conditions in our factories.",negative
"We ensure that all our materials are ethically sourced and provide support to the local economies where we operate.",positive
"Despite using recycled materials, our company has been criticized for poor working conditions in our overseas manufacturing plants.",negative 

现在,我们可以使用 OpenAI 的 API 和 GPT-4 模型启动模型微调,用您的实际密钥替换openai.api_key,并用数据集的位置路径替换path/to/your/dataset.csv。在执行此代码之前,请记得查阅最新的 OpenAI API 文档(beta.openai.com/docs/),以了解 API 使用方面的任何更新或更改:

import openai
openai.api_key = 'XXX' #your API key here
response = openai.File.create(
    file=open("path/to/your/dataset.csv", "rb"),
    purpose='fine-tune')
file_id = response['id']
fine_tune_response = openai.FineTune.create(training_file=file_id,
    model="gpt-4",
    n_epochs=5) 

克服迁移学习中的挑战

虽然迁移学习可以是一种强大的方法,用于微调预训练模型以在新任务上表现更好,但它并非没有其挑战和局限性。以下是在应用迁移学习时需要考虑的几个关键挑战:

  • 模型漂移:在迁移学习的背景下,模型漂移指的是随着用于微调的数据变得不再代表当前环境或趋势,模型准确性的逐渐下降。

例如,想象一下使用 2019 年营销数据预训练的模型来预测 2024 年的消费者偏好。最初,该模型在通过迁移学习使用更近期的 2020 年数据进行微调后可能表现良好。然而,由于像 TikTok 等新社交媒体平台越来越受欢迎或经济条件发生重大变化等原因,消费者行为发生变化,该模型可能开始推荐过时的信息策略。

为了解决模型漂移问题,需要使用目标域的最新数据持续更新模型,并密切监控其性能。这可以通过允许模型随着新数据的到来而动态调整的持续学习技术来实现。本节中的信息框提供了有关持续学习的进一步资源。

  • 领域不匹配:在迁移学习中,当源领域(模型最初训练的地方)和目标领域(模型进行微调的地方)存在显著差异时,就会发生领域不匹配。在迁移学习中,这意味着预训练模型的知识可能无法很好地推广到新领域,从而导致性能不佳。

例如,考虑一个在电子商务平台的英语语言客户评论上预训练的模型,然后微调以分析针对本地市场的日语评论。即使在微调之后,该模型可能也难以捕捉文化细微差别和语言差异,导致情感分析错误。这可能是因为预训练模型依赖于从英语数据中学习的模式,当应用于表达和文化参考不同的日语评论时,其效果较差。

为了解决这个问题,一个更合适的方法是使用精心挑选的日本客户评论数据集来微调模型,这个数据集专门捕捉了当地市场的特定语言和文化细微差别。

保持模型漂移的前沿

为了保持迁移学习模型的准确性,尤其是在消费者行为演变的情况下,持续学习是关键。

持续学习通常在 MLOps 实践中得到实施。了解更多关于 MLOps 原则和最佳实践的信息,请访问cloud.google.com/architecture/mlops-continuous-delivery-and-automation-pipelines-in-machine-learning

在介绍了 FSL 和迁移学习如何将预训练模型适应以更好地解决新的营销任务的基本原理和技术之后,我们现在将通过一个实际营销示例来展示 FSL 的重要性。

应用 FSL 提高品牌一致性

在我们之前对 ZSL 的探索中,第九章,我们展示了如何使用像 GPT-4 这样的预训练模型为推出环保产品的电子商务品牌生成营销文案。这种 ZSL 方法虽然强大,但主要依赖于模型从泛化预训练中推断上下文和内容的能力,这通过强调诸如sustainableeco-friendly等术语的提示来实现。

如本节中的示例所示,虽然 ZSL 为生成与品牌相关的内内容提供了坚实的基础,但它往往缺乏捕捉品牌精神更深层次、更细微方面的精确度。这对于那些身份与特定实践或原则紧密相连的品牌尤其如此,这些实践或原则在大型语言模型LLM)的泛化训练中可能没有得到很好的体现。

营销活动中有效 FSL 的步骤

  1. 提示优化和执行:从一个基本的提示开始,比如用于 ZSL 的提示,但现在添加一些期望的输出或上下文示例,这些示例反映了品牌的独特之处。

  2. 输出分析:评估内容以确保其保持必要的品牌一致性。注意与这些期望的偏差,因为它们提供了需要进一步示例的领域见解。

  3. 迭代优化:根据初始输出的反馈和性能,迭代地优化示例和提示,直到达到你期望的营销 KPIs(见第二章)。

在第九章中“零样本学习用于营销文案”的部分,我们继续我们的场景,回顾我们之前介绍的关注可持续性的电子商务品牌。现在,为了应对不断变化的市场趋势和公司指令,以其环保厨房用品而闻名的公司正在进行品牌重塑,以适应日益增长的消费者对社会责任的需求。最新的洞察显示,消费者越来越有兴趣支持那些不仅提供可持续产品,而且表现出对公平劳动实践和积极社区贡献的实质性承诺的品牌。这种转变在富裕的年轻消费者中尤为明显,他们重视道德生产,并愿意为真正改变工人和社区生活的产品支付溢价。此外,这个群体希望他们的产品不仅要有环保包装,而且要被认为是“零浪费”。

让我们通过增强输出内容并通过提示工程来展示 GPT-4 如何有效地捕捉我们新定义的可持续性营销目标。这包括对之前提到的可持续性的微妙澄清:

  • 对公平劳动实践承诺

  • 零浪费包装

  • 活跃的社区参与

我们将通过一个旨在提升电子邮件营销活动的案例研究来展示这一点。这涉及到迭代地改进提示,与第二章中讨论的关键性能指标紧密相关,以确保与我们的重新定位营销目标保持一致。

使用 ZSL 和 FSL 进行基准测试

在将 FSL 整合到我们的电子邮件营销活动之前,评估 ZSL 在捕捉 FSL 新品牌战略方面的有效性是很重要的。在这里,我们将比较使用 ZSL 生成的基线响应,该响应没有与我们的重新定位的可持续性焦点相符合的具体例子。我们将定义一个函数来执行 API 补全,然后展示 ZSL 在没有我们更新后的营销目标细微背景的情况下如何表现:

from openai import OpenAI
client = OpenAI(api_key = 'XXX' ) #your API key here
base_prompt = "Write a product description for an eco-friendly kitchenware product focusing on brand ethics."
def generate_chat_completion(client, prompt, max_tokens=150, n=1, temperature=0.7, advanced_usage=False):
    if not advanced_usage:
        messages = [{"role": "user", "content": prompt}]
    else:
        messages = prompt
    completion = client.chat.completions.create(
        model="gpt-4",
        messages=messages,
        max_tokens=max_tokens,
        n=n,
        temperature=temperature)
    return completion.choices[0].message.content
zsl_response = generate_chat_completion(client, base_prompt)
print(zsl_response) 

这给我们以下响应:

Product Name: EcoPure Bamboo Kitchen Utensil Set
Enrich your cooking experience with our EcoPure Bamboo Kitchen Utensil Set. This set, which includes a spatula, slotted spoon, mixing spoon, and fork, is not just an ordinary kitchen tool set but a reflection of our commitment to sustainable living and ethical product creation.
Each piece in this set is made from 100% organic bamboo, a renewable and biodegradable resource, offering an environmentally friendly alternative to plastic. 

如您所见,虽然响应是清晰的,但它过于笼统,缺乏满足我们重新品牌化倡议特定目标所需的具体性和背景。

为了看到 FSL 可以提供的价值,这里,我们回顾了之前完全相同的基线提示,但还通过 FSL 包括了针对我们更新后的营销目标的具体上下文:

fsl_prompts = [
    {"role": "system", "content": "Describe a product using sustainable materials that supports fair labor practices."},
    {"role": "user", "content": "Our latest kitchenware range not only uses biodegradable materials but is also produced in factories ensuring fair wages and safe working conditions."},
    {"role": "system", "content": "Write about a kitchenware product that exemplifies zero waste in packaging."},
    {"role": "user", "content": "Each item in our new line of cookware comes in completely recyclable packaging, designed to leave no environmental footprint."},
    {"role": "system", "content": "Explain how a purchase supports community engagement projects."},
    {"role": "user", "content": "With every purchase, a portion of the proceeds goes towards community gardens, supporting urban greening projects."},
    {"role": "system", "content": base_prompt}]
fsl_response = generate_chat_completion(client, fsl_prompts, max_tokens=150, temperature=0.7, advanced_usage=True)
print(fsl_response) 

这产生了以下输出:

Introducing our new line of eco-friendly kitchenware, designed with the **utmost respect for our planet and its inhabitants**. Each piece in this range is crafted from sustainable, biodegradable materials, making it a guilt-free addition to your kitchen.
**We believe in the power of ethical production and fair labor****factories that ensure fair wages, safe working conditions, and equal opportunities for all workers**, which is why all our products are sourced from .
But our commitment doesn't stop there. **For every purchase, we contribute towards community development projects**, particularly urban greening initiatives, to make our cities more livable. 

在前面的文本中,与我们的特定目标——环境可持续性、公平劳动实践和社区参与——有机相关的 LLM 生成内容被突出显示以增强清晰度。这种与 ZSL 的比较强调了 FSL 通过利用初始上下文示例产生更符合我们重新品牌化战略细微差别的内容的能力。

制定电子邮件营销活动

现在,让我们探讨 FSL 在增强电子邮件营销活动的个性化和相关性方面的应用,显著提高客户参与度和转化率。以下是如何有效利用 FSL 优化电子邮件活动的简要指南:

  1. 初始电子邮件创建:使用 FSL 生成初始批次的电子邮件,特别关注您的核心营销目标——在本例中,是可持续性和道德实践。

  2. 收集初始指标和反馈:分析客户的初始反应,了解哪些内容方面最能引起共鸣。这种分析对于识别成功元素和可能需要额外优化的领域至关重要。

  3. 迭代优化:根据从客户那里收到的参与指标和反馈,优化电子邮件的内容。

  4. 持续反馈整合:持续整合新的见解,使电子邮件营销活动动态地与不断变化的客户偏好和市场趋势保持一致。

现在我们来审视这些步骤包含的内容。

第一步:初始电子邮件创建

在电子邮件营销活动中采用 FSL 的第一步是明确界定活动的目标。对于我们这个环保型电子商务品牌来说,目标可能是推出一系列与品牌重塑目标相符的环保厨房用品。让我们假设这个场景的目标如下:

Introducing a new line of sustainable kitchenware that embodies the brand's commitment to zero waste, ethical manufacturing practices, and community engagement. 

活动目标明确后,下一步是创建提示,指导 AI 生成适合电子邮件信息的适当内容。

构建营销活动的初始电子邮件结构

以下的一般结构有助于创建一个有效的初始信息,用于您的电子邮件营销活动,从而提高与受众的参与度和转化率:

  • 介绍:热情地问候客户并介绍新产品系列。

  • 正文:提供关于产品核心方面的详细信息——在本例中,是可持续性和道德制造方面。

  • 行动号召:包含一个行动号召,鼓励收件人采取具体步骤,例如进行购买或访问网站。

  • 结束语:以热情的结束语结束,强调品牌对产品核心方面的承诺。

我们将为模型定义一个起始提示,该提示将用于生成初始批次的电子邮件。类似于早期产品描述的例子,fsl_prompts的每个元素都旨在逐步构建围绕品牌对可持续性、道德实践和社区参与的承诺的叙事,如下所示:

  • 第一组提示确保内容适当地强调了厨房用品的环保和零浪费特性。

  • 第二组提示针对的是讨论生产过程中涉及的道德劳动实践时的预期背景。

  • 最后两个提示将产品与社区参与努力联系起来,将购买与对社会负责任的消费者重要的倡议联系起来

为了确保生成的内容与我们的活动目标一致,我们将调整我们的基本提示以更具体地针对电子邮件活动,并将max_tokens增加到反映更长的内容:

base_prompt = "Compose a short email to introduce our latest line of eco-friendly kitchenware. The email should be engaging, informative, and conclude with a strong call to action."
fsl_prompts = [
    {"role": "system", "content": "Make sure to highlight the eco-friendly and zero waste aspects of the kitchenware."},
    {"role": "user", "content": "Our kitchenware is designed with the planet in mind, featuring products made entirely from recycled materials and ensuring zero waste in our packaging."},
    {"role": "system", "content": "Include information about the fair labor practices in the manufacturing process."},
    {"role": "user", "content": "We are committed to ethical production practices. All our products are manufactured under fair labor conditions, ensuring all workers are paid fairly and work in safe environments."},
    {"role": "system", "content": "Mention how purchasing these products supports community engagement projects."},
    {"role": "user", "content": "Every purchase supports community initiatives, including urban greening projects and community gardens that help local environments thrive."},
    {"role": "system", "content": base_prompt}]
fsl_completion = client.chat.completions.create(
    model="gpt-4",
    messages=fsl_prompts,
    max_tokens=300,
    n=1,
    temperature=0.7
)
print(fsl_completion.choices[0].message.content) 

这产生了以下电子邮件内容:

Subject: Discover Our New Eco-Friendly Kitchenware - Upgrade Your Kitchen, Save the Planet!
Hello,
We are thrilled to announce the arrival of our latest line of eco-friendly kitchenware, designed with both style and sustainability in mind.
Our new collection is a testament to our commitment to protecting our planet. Each piece is crafted from 100% recycled materials, ensuring that your cooking experience is as kind to the Earth as it is to your culinary creations.
But we don't stop at just the products. We've committed to zero waste in our packaging, meaning when you unbox your new kitchenware, you can do so guilt-free.
We believe in ethical production and are proud to say that all our products are made under fair labor conditions. Every worker involved in creating our kitchenware is paid fairly and operates in a safe and healthy environment.
Moreover, when you purchase from us, you're also giving back to the community. A portion of each sale goes towards local community initiatives, including urban greening projects and community gardens. This means that with every purchase, you're helping local environments to flourish.
We invite you to explore our new line of eco-friendly kitchenware and make your kitchen a beacon of sustainability. Let's cook up a storm, with a side of environmental consciousness!
Click here [insert hyperlink] to begin your sustainable cooking journey with us.
Best,
[Your Name] 

第 2 步:收集和分析初始指标和响应

在部署了新创建内容的电子邮件活动之后,评估其效果至关重要,使用关键绩效指标(KPIs)进行评估。为此评估,我们假设我们已经有了启动后前七天的代表性数据,这将使我们能够检查打开率、点击率、转化率和取消订阅率的指标。这种分析有助于我们通过可视化这些 KPIs 随时间的变化来识别改进的领域。

import pandas as pd
df_initial = pd.read_csv('initial_launch_data.csv')
def plot_campaign_kpis(df, title='Email Campaign KPIs'):
    plt.figure(figsize=(10, 8))
    plt.plot(df['Date'], df['Open Rate (%)'], label='Open Rate (%)', marker='o')
    plt.plot(df['Date'], df['Click-Through Rate (%)'], label='Click-Through Rate (%)', marker='o')
    plt.plot(df['Date'], df['Conversion Rate (%)'], label='Conversion Rate (%)', marker='o')
    plt.plot(df['Date'], df['Unsubscribe Rate (%)'], label='Unsubscribe Rate (%)', marker='o')
    plt.xlabel('Date')
    plt.ylabel('Percentage')
    plt.title(title)
    plt.legend()
    plt.grid(True)
    plt.show()
plot_campaign_kpis(df_initial, 'Email Campaign KPIs First Week after Launch') 

在以下图表中,我们可以观察到活动启动后第一周内打开率、点击率、转化率和取消订阅率的变化趋势。这使我们能够快速识别模式,这对于诊断活动内容或交付的问题可能至关重要:

图 10.10:启动后第一周的电子邮件活动 KPIs

基准测试您的电子邮件活动表现

评估营销活动指标的表现可能很棘手,尤其是在没有行业基准作为参考的情况下。为了快速评估您的 KPIs 是否达标,首先将它们与既定的基准进行比较。

这里是最近电子邮件营销基准的比较:www.webfx.com/blog/marketing/email-marketing-benchmarks/

我们还可以计算并审查这些指标的平均表现:

print(f"Average Open Rate: {df_initial['Open Rate (%)'].mean():.2f}%")
print(f"Average Click-Through Rate: {df_initial['Click-Through Rate (%)'].mean():.2f}%")
print(f"Average Conversion Rate: {df_initial['Conversion Rate (%)'].mean():.2f}%")
print(f"Average Unsubscribe Rate: {df_initial['Unsubscribe Rate (%)'].mean():.2f}%") 

这会产生以下结果:

Average Open Rate: 13.07%
Average Click-Through Rate: 2.43%
Average Conversion Rate: 1.21%
Average Unsubscribe Rate: 1.61% 

根据这些 KPIs,以下是一些观察和可能的解释,我们可能在下一轮电子邮件活动中考虑解决:

  • 低打开率:这可能表明电子邮件的主题行不够吸引人。

  • 点击率:一些收件人查看电子邮件,但点击率低于预期,可能是由于内容或优惠不够吸引人。

  • 低转化率:这表明需要更强的行动号召或提高着陆页的有效性。

  • 取消订阅率上升:这可能表明内容频率或相关性存在问题。

除了这些 KPI 之外,假设我们还收集了直接回复此电子邮件并表达他们的疑问和担忧的电子邮件收件人的反馈。我们还可以通过采用第五章中讨论的情感分析技术来收集信息,这样我们就可以确定阅读我们电子邮件的客户的产品评论和社交媒体帖子中的核心主题和情感。以下是我们将假设收到的积极反馈概述:

  • 可持续实践的赞赏:“我喜欢你们的厨房用品是用回收材料制成的。”

  • 道德制造的认可:“看到品牌承诺公平工资和安全的劳动条件,让人感到放心。”

  • 产品系列的热情:“不锈钢炊具看起来非常棒!”

以下是对负面反馈的要点:

  • 对更多产品多样性的渴望:“我希望你们为产品系列提供更多颜色选择。”

  • 产品保养的疑问:“我担心如何保养这些产品以确保它们更耐用。”

  • 价格点的担忧:“产品很好,但与不环保的替代品相比,它们有点贵。”

虽然积极的评论验证了我们的活动核心信息,但批评和问题为我们未来的电子邮件信息提供了可操作的见解。利用这些反馈,在下一节中,我们将专注于如何利用负面批评来优化我们的电子邮件营销策略并提高我们的 KPI。

第 3 步:迭代优化

在审查了前几部分的初始指标和客户反馈后,很明显,尽管一些方面与活动很好地产生了共鸣,但还有一些关键领域需要改进。下一步是根据初始指标优化我们的 FSL 提示,解决客户反馈中的具体批评,更好地满足客户期望,并提高活动的整体效果。以下是提示的新要素,每个要素后面都有注释,突出其对我们任务的价值:

fsl_prompts = [
    {"role": "system", "content": "Compose a short email to introduce our latest line of eco-friendly kitchenware. Highlight our zero waste and ethical manufacturing processes in terms of the labor force, and emphasize the practical benefits these practices offer to the consumer. The email should be engaging, informative, and conclude with a strong call to action. Importantly, the subject line should be as engaging as possible."},
    {"role": "user", "content": "Discover our new line of eco-friendly kitchenware! Designed with sustainability at heart, each piece not only supports zero waste but is ethically made, ensuring fair labor practices and substantial benefits to the environment."}, 

这个提示为电子邮件设定了基调,捕捉了我们之前 FSL 尝试的关键要素,同时也强调了在直接回应初始 KPI 指标中观察到的低打开率时,一个吸引人的主题行的重要性。

 {"role": "system", "content": "Mention the product variety and colors."},
    {"role": "user", "content": "Now available in a range of vibrant colors, our kitchenware allows you to personalize your kitchen while maintaining a commitment to sustainability."}, 

这个回应迎合了希望有更多样化的反馈。它强调了可用的颜色范围,旨在吸引那些希望个性化购买的客户。

 {"role": "system", "content": "Provide care instructions."},
    {"role": "user", "content": "Caring for your eco-friendly kitchenware is easy. Here are some simple tips to ensure your items last longer, enhancing their sustainability."}, 

针对客户对维护的担忧,这个提示向客户保证产品不仅可持续,而且易于保养,通过确保产品的耐用性来增强其吸引力。

 {"role": "system", "content": "Address concerns about pricing."},
    {"role": "user", "content": "Invest in quality and sustainability. While initially more expensive, our kitchenware offers long-term savings and a positive impact on the planet."}] 

这个提示直接解决了反馈中提到的价格敏感性问题。它将成本重新定义为对质量和可持续性的投资,主张长期价值和环境影响。

fsl_response = generate_chat_completion(client, fsl_prompts, max_tokens=500, temperature=0.7, advanced_usage=True)
print(fsl_response) 

执行 API 召回后,我们得到以下结果:

Subject: Revolutionize Your Kitchen With Our New Eco-Friendly Line!
Dear [Customer],
We're thrilled to introduce our latest line of eco-friendly kitchenware! Designed with both style and sustainability in mind, our new collection showcases a commitment to zero waste and ethical manufacturing processes.
Our kitchenware is crafted using environmentally friendly materials and methods, minimizing waste and harm to our planet. Plus, we're proud to assure you that all products are produced under fair labor conditions, promoting a more equitable and sustainable global workforce.
Available in a variety of shapes, sizes, and vibrant colors, our kitchenware allows you to personalize your kitchen while maintaining a steadfast commitment to sustainability. From our durable cutlery to our stylish serving bowls, each item in our collection is a testament to our dedication to quality and environmental responsibility.
Caring for your new eco-friendly kitchenware is a breeze - just a gentle handwash with mild soap and they're good as new. And remember, every eco-friendly choice you make contributes to a healthier, more sustainable planet.
While our items may seem initially more expensive, consider them an investment. They are designed to endure, offering long-term savings and a positive impact on the environment. Plus, you'll gain a sense of satisfaction knowing you're using items that are kind to our Earth and its workers.
Ready to make the switch to a more sustainable kitchen? Visit our website today to explore our new collection. Together, we can make a difference in our homes and our world. 

在 4 月 7 日部署这些更新后的电子邮件后,假设我们收集了接下来的七天 KPI 数据,并观察到以下更新趋势:

df_improved = pd.read_csv('improved_data.csv')
plot_campaign_kpis(df_improved, 'Improved Email Campaign KPIs After FSL Refinements') 

这给我们以下图表,其中我们观察到在 FSL 优化后 KPI 的显著变化:

图 10.11:在针对客户反馈进行更改和改进后,电子邮件营销活动的 KPI

基于此,我们有以下平均 KPI:

print(f"Average Open Rate: {df_improved['Open Rate (%)'].mean():.2f}%")
print(f"Average Click-Through Rate: {df_improved['Click-Through Rate (%)'].mean():.2f}%")
print(f"Average Conversion Rate: {df_improved['Conversion Rate (%)'].mean():.2f}%")
print(f"Average Unsubscribe Rate: {df_improved['Unsubscribe Rate (%)'].mean():.2f}%") 
Average Open Rate: 21.00%
Average Click-Through Rate: 5.50%
Average Conversion Rate: 3.50%
Average Unsubscribe Rate: 0.59% 

通过将这些指标与之前的指标进行比较,我们发现所有领域都取得了显著的改进。虽然没有使用如 A/B 测试(第六章)或因果推断(第三章)等技术来确定这些改进的确切原因,但人们仍然可以推测这些改进的 KPI 可能背后的原因:

  • 打开率显著提高,这可能反映了更具吸引力的主题行,包括“革命你的厨房…”

  • 点击率有所上升,这可能归因于包括所需功能(如产品多样性和详细的护理说明)在内的内容,这些内容增加了客户参与度

  • 转化率提高,表明电子邮件内容不仅更具吸引力,而且更有效地说服客户产品的价值和相关性,尤其是在解决价格问题之后

  • 取消订阅率下降,反映了更高的内容满意度

第 4 步:持续反馈整合

利用 FSL 进行电子邮件营销活动的最后一步是建立一个强大的系统,用于持续反馈整合。这种方法确保活动保持动态,并能对客户不断变化的需求和偏好以及更广泛的市场趋势做出响应。通过整合持续反馈,活动不仅保持相关性,而且随着时间的推移加强了客户参与度和品牌忠诚度。

有效的反馈整合需要允许客户轻松分享他们的想法和经验的机制。这包括直接在电子邮件中嵌入快速调查链接,启用直接电子邮件回复,并通过与活动相关的社交媒体互动与客户互动。这些渠道促进了信息从客户流向营销人员,提供了有价值的见解,这些见解可用于持续改进和优化活动。

示例反馈收集策略

以下是一些收集直接客户反馈的额外方法:

  • 实时聊天反馈:在您的网站上实施实时聊天,以允许实时互动和即时反馈。

  • 互动内容:在您的电子邮件或数字平台上使用测验和投票,使反馈收集更具吸引力。

  • 反馈二维码:产品或广告上的二维码可以链接到反馈表单,以便客户可以轻松地在他们的设备上做出回应。

为了有效地分析和利用持续的反馈,设置一个实时反馈仪表板可以带来巨大的好处。这个仪表板可以作为监控和分析反馈以及标准营销关键绩效指标的中心枢纽,提供对活动表现的全面视图。为了构建这样的仪表板,考虑使用像 Tableau、Microsoft Power BI 或 Google Data Studio 这样的软件解决方案,它们提供了创建交互式和实时数据可视化的强大工具和直观界面。

以下是你创建自己的反馈仪表板的步骤:

  1. 选择仪表板工具:选择最适合你的技术能力和预算的平台。Tableau、Microsoft Power BI 和 Google Data Studio 因其强大的功能和可扩展性而成为流行的选择。

  2. 集成数据源:将仪表板工具连接到收集你的营销关键绩效指标和反馈的数据源。这可能包括电子邮件活动管理工具、社交媒体分析和客户反馈系统。

  3. 设计仪表板:创建清晰显示你需要跟踪的关键指标的视觉呈现。根据活动表现的趋势、峰值和低谷定制仪表板。

  4. 安排定期审查:设定定期的时间间隔,例如每两周或每月,来审查仪表板洞察。利用这些会议来评估最近变化的有效性,并根据数据洞察规划进一步的策略调整。

    防止你的电子邮件进入垃圾邮件文件夹

    为了最大限度地提高你电子邮件活动的影响力,防止你的信息进入垃圾邮件文件夹至关重要。以下实现这一目标的三项关键策略:

    • 设置电子邮件认证:实施 SPF、DKIM 和 DMARC 等标准来验证你的电子邮件。这有助于与电子邮件提供商建立信任,以降低你的电子邮件被标记为垃圾邮件的风险。

    • 维护名单卫生:定期清理电子邮件名单,移除不活跃的订阅者,并确保所有收件人都已选择接收你的电子邮件。这不仅提高了参与度,还有助于保护你的发送者声誉。

    • 优化电子邮件内容:其他优化策略包括使用 FSL 个性化你的电子邮件、限制链接数量以及保持图像与文本比例的平衡。

摘要

本章探讨了 FSL 的潜力及其对改进 AI 驱动营销策略、增强品牌影响力的承诺。基于通过 ZSL 引入的原则,我们探讨了 FSL 如何利用有限的数据集,使 AI 模型能够快速适应新任务。这在营销领域尤为重要,因为快速适应不断变化的消费者偏好和市场趋势可以对品牌的关联性和参与度产生重大影响。

虽然 FSL 侧重于使用最小示例快速适应,但迁移学习通过应用针对特定任务微调的预训练模型来补充这一点,从而最小化大量重新训练的需求。本章强调了结合这些方法来优化您的营销努力的实用策略。通过如 MAML 方法等途径,我们展示了您如何使用元学习框架进行营销。

随着我们继续前进,下一章将介绍检索增强生成RAG)的概念。我们将探讨如何通过将生成模型与高级信息检索技术相结合,RAG 可以动态生成反映最新可用数据的内容。这种方法不仅增加了生成内容的关联性,还提高了消费者定位的精确性,使您的营销工作显著更加有效。即将进行的讨论将涵盖知识检索系统的技术设置以及 RAG 在营销中的实际应用,我们希望通过这些内容为您提供编写与您当前和潜在客户产生共鸣的精准营销内容的强大工具。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人交流,并在以下地点与超过 5000 名成员一起学习:

packt.link/genai

二维码

第十一章:基于检索增强生成的微目标

本章介绍了检索增强生成RAG)的高级功能及其在精准营销中的战略应用,这是在前两章讨论的零样本学习ZSL)和少样本学习FSL)的基础上建立的。与 ZSL 不同,ZSL 在无先验示例的情况下运行,而 FSL 依赖于最小数据集,RAG 利用实时检索系统来增强生成模型,使其能够访问和纳入最最新和最具体的信息。这种能力使 RAG 能够超越 ZSL 和 FSL 的限制,提供针对个人消费者档案或当前市场状况的个性化内容——这对于营销中的微目标至关重要。

本章将详细阐述 RAG 的操作框架,强调其混合结构,该结构将生成式 AI 与动态信息检索相结合。这种综合不仅确保了生成符合上下文和准确的内容,还引入了一种以前仅通过 ZSL 或 FSL 单独使用无法实现的程度上的个性化。我们将探讨 RAG 的实时数据检索组件如何通过以一个多产品电子商务平台的消费者交互数据为例,迅速调整营销策略以适应消费者行为和偏好,从而发挥关键作用。

到本章结束时,你将具备以下知识:

  • 理解 RAG 与传统生成模型的集成及其在处理实时、相关数据方面的优越性,与 ZSL 和 FSL 相比。

  • 认识到 RAG 在微目标和个性化内容方面的增强能力,这可以显著提高消费者参与度和转化率。

  • 将 RAG 概念应用于开发前沿的营销策略,这些策略不仅数据驱动,而且能够高度适应消费者的细微差别。

RAG 在精准营销中的介绍

生成模型,尤其是那些在生成预训练转换器GPT)等转换器框架上开发的模型,已经彻底改变了机器理解和生成类似人类文本的方式。这些模型在庞大的文本数据语料库上训练,能够学习语言的复杂模式和结构,从而能够预测和生成连贯且符合上下文的文本序列。然而,尽管这些模型非常复杂,纯生成模型通常缺乏将实时、特定信息纳入其训练数据的能力。

这就是 RAG 的“检索”组件发挥作用的地方。RAG 是生成式人工智能GenAI)与信息检索系统的融合,形成一个旨在提高生成内容质量和相关性的混合模型。RAG 通过在生成过程中结合动态检索组件,从外部数据集或知识库中检索相关信息来实现这一点。RAG 中的检索系统旨在查询结构化或非结构化数据库,以获取与生成任务上下文相关的信息。这种方法确保生成模型能够访问最新和最相关的数据,以增强其生成内容的准确性和相关性。

RAG 是如何工作的

除了增强内容的相关性之外,RAG(Retrieval-Augmented Generation)还实现了生成模型和外部数据库之间信息的双向流动。如图 11.1 所示,RAG 的过程可以分解为几个关键步骤,每个步骤都将进一步讨论:

图片

图 11.1:RAG 工作流程的关键组件

让我们进一步探讨这些步骤:

  1. 输入提示:在这一步中,生成模型被输入用户的输入提示或当前的(微调的)生成上下文。

  2. 查询生成:最初,生成模型根据第 1 步中提供的输入生成一个查询。这个查询被编写来从知识库中检索最相关的信息。生成模型和外部数据库之间的这种双向信息流动促进了共生关系,丰富了数据利用和模型性能。

  3. 信息检索:在第 3 步中,查询被检索系统处理,该系统通过数据库搜索以找到匹配项或密切相关信息。这个系统的复杂性可能有所不同,从简单的基于关键词的搜索到更复杂的理解语义意义的神经网络模型。检索到的数据随后将在下一步整合到内容生成过程中。

  4. 内容生成:在第 4 步中,生成模型利用检索到的数据,将其纳入其持续的文字生成过程中。这一步至关重要,因为它涉及到将新检索到的数据与生成内容混合,以保持连贯性和流畅性。这种内容可能成为上述示例中营销活动等倡议的基础。

  5. 迭代优化:通常,这个过程是迭代的,生成模型根据已生成内容和需要生成的内容之间的反馈循环调整查询。这体现在第 5 步中,迭代优化循环确保根据如营销 KPI 或客户反馈等反馈持续调整和优化生成过程。

接下来,我们将从数学角度讨论查询生成和检索步骤的工作原理。

RAG 检索的数学模型

RAG 的数学模型捕捉了文档查询与其检索组件之间的关系(分别对应于 图 11.1 中的步骤 2 和 3),为其动态内容生成过程奠定了基础。在其核心,RAG 结合概率框架将文本生成与信息检索相结合,这可以通过量化给定输入和检索到的文档生成文本中涉及的概率的方程来表示。

该过程始于生成模型根据输入提示或持续上下文创建查询 q。同时,检索系统处理此查询以从数据库中检索相关文档。检索过程受一个概率模型控制,该模型根据查询 q 估计数据库中每个文档的相关性。这种估计包括诸如语义相似性和文档新鲜度等因素,确保检索到的信息与生成任务的上下文紧密一致。从数学上讲,给定查询 q 从数据库中选择文档 r 的概率可以表示为:

图片

其中 D 代表数据库中所有可能的文档集合,而 score(q,r) 是一个计算文档 r 对查询 q 相关性的函数。该评分函数通常通过训练学习,可能涉及复杂的嵌入,这些嵌入可以捕捉查询与文档之间的语义相似性。方程中的分母确保从数据库中选择任何文档的概率之和为 1

现在我们已经了解了模型的工作原理,让我们讨论外部数据在 RAG 系统中的关键重要性。

数据在 RAG 中的重要性

外部数据是 RAG 框架的基石,影响着生成内容的质量和信息检索的准确性。在营销领域,精确性和相关性直接关联着消费者参与度和转化率,因此,在 RAG 系统中正确应用和管理数据变得至关重要。检索框架中嵌入的两个基本组件值得深入探讨,并且由于它们对结果的影响深远,应优先考虑:

  • 数据新鲜度:保持数据更新使模型能够利用当前趋势、事件和行为,从而增强消费者参与度。

  • 数据特定性:通过整合详细的消费者数据,内容可以精确地针对个人偏好和行为进行定制。这种特定性不仅增加了营销信息的相关性,还可以显著提高转化率。

现在我们来详细探讨这些概念。

数据新鲜度

在实际意义上,数据新鲜度意味着系统持续访问和优先考虑可用的最新信息。这在营销中尤为重要,因为信息可能会由于市场条件或消费者偏好的快速变化而迅速过时。例如,在像黑色星期五这样的主要销售活动中,拥有最新数据允许 RAG 系统生成强调当前促销活动、可用库存水平或最后时刻交易的内容,大大提高了营销活动的有效性。与之前讨论的 GenAI 方法(如 ZSL 和 FSL)不同,这些方法主要依赖于预存在的数据集,并且可能不会实时更新其知识库,RAG 系统集成了动态检索机制,主动获取并利用最新的可用数据。

为了确保内容保持相关性,RAG 系统可以调整其检索过程,优先考虑较新的文档。从数学上讲,这种调整可以通过修改相关性评分来包括一个术语,该术语增加较新文档的权重:

图片

其中图片是一个参数,用于确定文档的新鲜度对其评分的影响。通过优先考虑最新数据,RAG 系统可以更动态地响应最新趋势,确保它们生成的内容与当前消费者的行为和偏好产生共鸣。

数据特异性

数据特异性指的是信息与特定查询的相关性和详细程度。在 RAG 系统中,高数据特异性确保检索和生成的内容直接与用户的当前需求或问题对齐,从而增强用户参与度和满意度。虽然其他方法如迁移学习也允许访问详细的数据集,但 RAG 将实时数据检索与生成能力相结合,使其特别适合需要最新信息的应用。

在技术术语中,RAG 系统可以使用高级语义匹配算法来确保检索到的内容不仅与用户的查询关键字匹配,而且在整体意义和上下文中也匹配。这种方法涉及调整评分机制,以优先考虑不仅相关而且与用户查询上下文特定的文档:

图片

例如,考虑一个用户正在搜索“针对敏感皮肤的最好护肤品”。具有高数据特异性的 RAG 系统能够检索和生成不仅提及护肤品,而且专门针对敏感皮肤设计的产品的内容,可能包括用户评论、专家建议和最新的产品创新。这种程度的内容生成可以显著提高个性化营销活动的有效性,提高客户转化率并建立品牌忠诚度。

理解检索索引

检索索引是任何 RAG 系统的基本组成部分,它是检索功能运作的基础。它确保系统处理的查询与准确和上下文相关的响应相匹配。有效地管理此索引对于系统的性能至关重要,可能涉及几个关键策略。让我们看看一些管理方法。

索引策略

有效的索引对于快速准确地检索信息至关重要。一个强大 RAG 系统的核心在于其快速筛选大量数据并找到与用户查询最佳匹配信息的能力。这是通过复杂的索引策略实现的,这些策略以优化搜索过程的方式组织数据,例如:

  • 倒排索引:这些用于存储从内容关键词到其在数据库中位置的映射。例如,在电子商务环境中,倒排索引可能会将“无线耳机”或“保暖夹克”等术语直接链接到相关的产品列表。这允许系统在查询期间快速收集所有相关文档,提高搜索效率和响应速度。

  • 向量空间模型:这种方法涉及将文本转换为易于比较和分析的向量形式或嵌入。使用 TF-IDF 或基于神经网络的嵌入算法,如第五章、第九章和第十章中介绍的那样,这些模型有助于理解并比较用户查询与可用文档之间的语义相似性,从而产生更细微和上下文相关的响应。

  • 基于图的索引:这种方法对于社交媒体分析等应用很有用,在这些应用中,理解复杂的用户关系可以增强内容定位。更普遍地说,当数据点之间的关系与数据本身一样重要时,这种方法非常有价值。

  • 多维索引:这种技术在需要高效搜索多个属性(如位置和时间)的地理数据应用(如房地产分析)中很有用。这种方法对于涉及范围或需要同时考虑多个维度的查询尤其有价值。

选择适当的索引策略取决于应用程序的数据需求和查询复杂性。倒排索引针对快速关键词查找优化,对于速度至关重要的环境来说非常理想。向量空间模型提供了更丰富的语义分析,更适合需要更深入理解内容的环境。对于处理更复杂的数据关系或多个查询维度,基于图和多维索引提供了有价值的解决方案。

数据整理和更新

为了保持其有效性,检索索引必须定期更新和维护。以下是一些需要考虑的概念:

  • 动态更新:随着新信息的出现或旧信息的过时,索引需要更新以反映这些变化。这确保了 RAG 系统随着时间的推移保持有效和相关性。例如,在营销活动中,促销内容可能需要频繁更新以反映公司最新的优惠,从而使 RAG 系统能够调整其响应。

  • 自动监控:实施自动系统以持续监控和更新索引可以大大提高 RAG 系统对变化的响应能力。在数字营销中,这可能包括根据新的消费者趋势分析调整策略,以确保营销内容与经济环境保持一致。

正确的数据更新和整理对于保持 RAG 系统的有用性至关重要,尤其是在营销领域,因为这些系统目前不包括高级数据管理功能,通常需要单独的实践来管理数据整理和更新。

RAG 实施挑战

在 RAG 实施中存在一些值得强调的挑战。如前所述,确保底层外部数据库的质量和相关性至关重要,通常需要单独的数据工程实践来实现这一点。以下是一些 RAG 系统可能面临的其他重大问题:

  • 处理长文档:RAG 系统需要将检索文档分解成更小的块以避免内存问题和缓慢的响应时间。然而,将较长的文档分解成更小的块可能会导致上下文丢失。为了解决这个问题,可以使用摘要算法和上下文感知分块方法等解决方案。

  • 从多个来源检索相关数据:由于数据格式的不一致和差异,从各种来源结合数据可能具有挑战性。例如,如果客户数据来自聊天历史和表格购买数据,系统可能会面临将两个来源链接起来并基于不一致信息生成营销信息的问题。多模态 AI 模型(见第十二章)和知识图谱等技术可以帮助解决这个问题。

尽管存在这些挑战,Meta AI Research、Google AI 和 Microsoft 等主要组织已经成功实施了 RAG 系统。例如,Google 已将 RAG 集成以增强其搜索结果的相关性,而 Microsoft 则将 RAG 集成到 Azure AI 服务中,以提升虚拟助手的性能。通过提供将现有企业数据整理成与 RAG 应用兼容格式的服务,RAG 也越来越容易为小型组织所采用。

RAG 在营销中的应用

将实时数据检索与高级内容生成独特结合的 RAG 系统在营销中提供了许多变革性应用。

由于这些系统通过将最相关的数据整合到内容创作过程中,使营销人员能够制作出个性化的、上下文感知的内容,因此 RAG 系统可以在以下关键领域显著提升营销策略:

  • 动态个性化内容创建:RAG 系统在生成实时适应用户互动、浏览行为或购买历史变化的广告内容方面表现出色。通过访问与个人近期活动相关的数据,RAG 可以定制广告以匹配个人偏好和兴趣。

示例:想象一个用户最近在网上探索露营装备。RAG 系统可以利用这些数据动态创建相关物品如徒步靴或旅行指南的广告。这种有针对性的广告不仅增加了广告的相关性和吸引力,而且提高了参与率和潜在转化率。我们将在本章后面的动手练习中讨论其他此类示例。

  • 针对特定细分市场的个性化内容生成:RAG 使营销人员能够生产出针对特定人口细分市场的精细内容,并丰富这些群体相关的最新数据。这种策略确保内容与其目标受众产生深刻共鸣,从而增强读者参与度和品牌忠诚度。

示例:一个 RAG 系统可能会为首次购房的人生成包含最新抵押贷款利率和实时房地产市场趋势的博客文章。这不仅提供了有价值的信息,而且使品牌在购房之旅中成为一个可信的资源。

  • 增强客户参与度:通过利用实时数据检索和高级内容生成的力量,这些系统能够生产出与个别客户产生深刻共鸣的高度个性化内容。无论是通过个性化的电子邮件、有针对性的社交媒体帖子还是定制新闻通讯,RAG 系统确保所有沟通都是及时的、相关的,并且针对每个客户的独特档案进行定制。

示例:对于一个最近庆祝了重要事件(如周年纪念日)的客户,RAG 可以生成反映客户偏好和品牌过往互动的个性化问候或优惠。这可能包括精选内容、特别促销或品牌大使的个性化信息,从而创造一个高度个性化且难忘的客户体验。

  • 面向客户的自动响应生成:RAG 通过生成针对性强、与上下文相关的响应来增强客户支持。通过从常见问题解答、产品手册或客户数据库中提取信息,RAG 系统提供精确、定制的答案。

示例:当客户询问在线购买的退货政策时,RAG 可以生成一个包含针对商品类别或购买日期定制的详细信息的响应。这种 RAG 在客户支持中的应用不仅提高了响应时间,还提升了整体客户满意度。

现在你已经具备了理论知识,让我们继续应用,熟悉构建知识检索系统的过程。

如果你想进一步探索 RAG,以下是一些有价值的资源:

  • 知识密集型 NLP 任务中的检索增强生成 (arxiv.org/pdf/2005.11401) 是 Meta AI 研究人员的一篇开创性论文,探讨了检索和生成的集成,以增强语言模型在知识密集型任务中的应用。

  • 检索增强生成中的最佳实践搜索 (arxiv.org/abs/2407.01219) 是对涵盖关键进展和当前挑战的文献的最新综述/调查。

使用 LangChain 构建营销知识检索系统

本节将探讨使用 LangChain(一个旨在促进语言模型与检索系统集成库)为营销目的设置知识检索系统的实际方面。我们将通过一个读者可以跟随的示例来完成这项工作,以构建他们自己的检索系统,以增强他们在营销策略中生成 AI 的能力。

LangChain 简介

LangChain 通过将检索系统集成到语言模型中,显著增强了语言模型的能力。其灵活的设计允许它支持各种后端数据库和可定制的检索策略,使用模块如 langchain-retrievallangchain-storage

LangChain 精要

LangChain 促进语言模型与强大检索系统的结合。这种集成捕捉了 RAG 的原则,使应用程序能够生成既像人类又高度相关且由最新数据信息的内容。

更多的文档和资源可以在 LangChain 的官方文档页面上找到:python.langchain.com/docs/get_started/introduction/

LangChain 作为 Python 开发者将高级 AI 功能集成到其营销策略中的首选工具脱颖而出。虽然其他工具如 LlamaIndex 专注于数据索引和检索,以便快速访问大量数据集,但 LangChain 提供了一个更通用的平台,用于创建复杂的 NLP 应用程序。使 LangChain 成为 Python 开发者理想选择的一些关键特性如下:

  • 易于集成:LangChain 通过高级抽象简化了复杂 AI 模型与检索数据库的结合,让您可以更多地关注创建独特的应用逻辑,而不是与后端复杂性搏斗,从而加快开发和部署过程。

  • 模块化:框架的高模块化支持多种语言模型和检索数据库,以及针对特定交互的定制逻辑。

  • 可扩展性:LangChain 被设计成能够轻松地从处理小任务扩展到管理大规模应用,例如实时个性化广告和广泛的电子邮件营销活动。这种可扩展性确保了随着营销策略的增长和演变,其技术基础设施可以增长而无需进行全面的重构。

在接下来的章节中,我们将深入探讨 LangChain 的设置、检索模型的设计以及将该系统与生成模型集成,以展示其在现实世界营销场景中的应用。

理解外部数据集

我们将用作检索模型外部数据源的数据集来自一个大型多品类电子商务平台,并捕捉了用户在 2019 年 12 月一个月内的交互。它包括与产品交互相关的不同类型的事件,例如查看、添加到购物车、从购物车中移除和购买。

我们将以此为基础,使用 LangChain 构建知识检索系统的设置流程,因为它将为我们在章节最后部分将进行实操的示例奠定基础。在这个部分,我们将使用来自同一数据库的用户交互数据,用于对消费者进行 RAG 微定位。

源代码和数据github.com/PacktPublishing/Machine-Learning-and-Generative-AI-for-Marketing/tree/main/ch.11

数据来源www.kaggle.com/code/annettecatherinepaul/ecommerce-analysis-and-recommendations/input

在将此数据集纳入我们的检索模型之前,了解其特征对于确保在检索系统中有效摄取和利用数据至关重要。对数据的初步检查可以定制检索架构和优化索引策略,从而促进优化的查询响应。首先,让我们检查前几条记录,以了解每列包含的数据类型:

import pandas as pd
df = pd.read_csv("2019-Dec.csv")
df.head(3)) 

这产生了以下结果:

图 11.2:Kaggle 电子商务用户交互数据集的前三行

数据集包含诸如event_time等列,它标记了事件发生的时间,event_type表示交互的性质(查看、购买或添加或从购物车中删除),以及其他标识符,如product_idcategory_idbrandprice。综合来看,这将帮助我们了解用户在电子商务平台上的旅程,包括他们的行为、涉及的产品以及会话期间的定价动态。

为了加深我们的理解,我们可以通过运行describe函数来执行基本的统计分析,以突出显示关键数据点的分布和范围:

df.describe() 

输出显示数据集包含超过 350 万个事件:

图片

图 11.3:数据集中数值列的关键统计数据

产品价格范围从低至-79.37 美元(可能表示退货或定价错误)到高达 327.80 美元,平均约为 8.87 美元。这种可变性表明消费者行为和购买力的多样性,这对于细分和定位营销活动至关重要。

我们还可以更深入地了解两个未包含在上文总结中的关键列,即event_typebrand,这些列帮助我们识别消费者偏好和购买模式:

df['event_type'].value_counts() 

这给出了以下输出:

图片

图 11.4:数据集中event_type值的计数

第一个输出显示,查看是最常见的event_type(约 173 万次实例),其次是添加到购物车、从购物车中删除和购买。从购物车交互到实际购买的巨大下降(比购物车添加少 700,000 次购买)是提高转化率的一个关注点。更普遍地说,从查看到购物车交互再到整体购买的计数减少突出了典型的电子商务销售漏斗。

通过在brand列上运行我们的第二个命令value_counts,我们还可以看到哪些品牌在数据集中出现得最频繁:

df['brand'].value_counts() 

以下为输出结果:

图片

图 11.5:数据集中品牌值的计数

理解数据中的空值也很重要。这为我们提供了一种理解数据质量和关键信息的方法,这些信息将需要在为我们的检索索引索引数据时考虑:

df.isnull().sum() 

以下结果表明category_code(近 350 万个缺失值)和brand(超过 150 万个缺失值)数据存在重大差距:

图片

图 11.6:数据集中各列缺失值的计数

这可能会阻碍我们使用此数据集进行详细的产品类别分析和品牌特定的市场营销。user_session中的轻微缺失计数(779)表明用户会话的跟踪几乎完整,这对于我们分析用户在整个会话中的行为的目标至关重要。

使用 LangChain 设计检索模型

随着我们使用 LangChain 构建我们的知识检索系统,下一步涉及有效地索引我们的电子商务数据集。索引是一个基础过程,它使得高效检索数据成为可能。本节概述了索引系统的设置,以支持查询,这将使我们能够根据他们的购物行为实现基于微目标的定位。为了实现我们的检索系统,我们将利用 Elasticsearch 作为我们的后端系统,因为它具有强大的全文搜索功能,并且适合处理大型数据集。

安装并连接到 Elasticsearch

在创建索引之前,我们需要确保 Elasticsearch 已安装并在我们系统上运行。根据您的操作系统遵循以下步骤:

下面是 Windows 用户需要遵循的步骤:

  1. 下载:访问 Elasticsearch 官方下载页面(www.elastic.co/downloads/elasticsearch),并下载 Windows 的最新版本。

  2. 安装:将下载的 ZIP 文件提取到您希望的位置,并导航到提取的文件夹。

  3. 启动:以管理员身份打开命令提示符,更改到 Elasticsearch 安装的目录(例如,cd C:\path\to\elasticsearch-<version>\bin),并执行elasticsearch.bat以启动 Elasticsearch。将<version>替换为从官方下载页面下载的 Elasticsearch 的具体版本。

macOS/Linux 用户可以遵循以下步骤:

  1. 下载:在终端窗口中使用以下命令,将<version>替换为最新版本:

    curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-<version>-darwin-x86_64.tar.gz 
    
  2. 安装:使用以下命令提取文件,并导航到新创建的目录:

    tar -xzf elasticsearch-<version>-darwin-x86_64.tar.gz 
    
  3. 启动:打开终端窗口并切换到bin目录:

    cd elasticsearch-<version>/bin 
    

通过运行以下命令启动 Elasticsearch:

./elasticsearch 

如果您使用的是 ARM 芯片的 MacBook,您可能需要通过 Homebrew 进行安装。有关此操作以及安装 Elasticsearch 的替代方法的说明,可以在他们的网站上找到:www.elastic.co/guide/en/elasticsearch/reference/7.17/install-elasticsearch.html

在启动 Elasticsearch 后,使用以下curl命令在您的终端或命令提示符中验证它是否正在运行:

curl http://localhost:9200 

您应该会看到 Elasticsearch 返回的 JSON 响应,表明它正在正确运行,如下所示:

{
  "name" : "Device-name.local",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "2QND1H4pxAyi75_21C6rhw",
  "version" : {
    "number" : "7.17.4",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "79878662c54c126ae89206c685d9f1051a9d6411",
    "build_date" : "2022-05-18T18:04:20.964345128Z",
    "build_snapshot" : false,
    "lucene_version" : "8.11.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
} 

当 Elasticsearch 运行时,您现在可以使用 Elasticsearch 客户端从 Python 连接。以下是设置方法:

!conda install elasticsearch
from elasticsearch import Elasticsearch
es = Elasticsearch(["http://localhost:9200"])
if not es.ping():
    raise ValueError("Connection failed")
else:
    print("Connected to Elasticsearch!") 

在 Elasticsearch 中索引数据

接下来,我们可以定义数据架构并从数据集中索引数据。鉴于数据集中数据类型的多样性和数据量,配置我们的索引映射以有效地处理现有数据的范围和类型非常重要。我们的索引映射是基于我们对该数据集进行的早期探索性分析,我们发现我们的数据集包含超过 350 万个条目,数据类型从整数和浮点数到类别和文本数据不等。这种多样性需要一种稳健的索引策略,以确保高效的数据检索和查询性能:

mapping = {
    "mappings": {
        "properties": {
            "event_time": {"type": "date"},
            "event_type": {"type": "keyword"},
            "product_id": {"type": "integer"},
            "category_id": {"type": "long"},
            "category_code": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "brand": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            },
            "price": {"type": "float"},
            "user_id": {"type": "long"},
            "user_session": {"type": "keyword"}
        }
    }
} 

在定义上述映射类型时所做的决策的一些关键方面如下:

  • 数值和标识字段product_idcategory_iduser_id 都存储为具有显著范围的整数。鉴于它们作为标识符的使用,它们被映射到 Elasticsearch 的整数和长数据类型,这些类型针对数值操作和比较进行了优化。price 是一个浮点字段,显示广泛的值范围,从负数(可能表示退款)到超过 300。此字段被映射为浮点数,以准确地表示和查询价格数据。

  • 类别和文本字段event_typeuser_session 是具有高基数值的类别字段。这些字段被映射为关键词类型,支持过滤和聚合所需的精确匹配。然而,brandcategory_code 包含可能用于全文搜索以及精确匹配的文本数据。这些字段使用文本类型和关键词多字段定义,以允许全文搜索和聚合。

  • 日期字段event_time 表示时间戳,被映射为日期类型。这允许基于时间的查询,这对于分析随时间变化的趋势至关重要。

接下来,我们将使用以下方式创建基于上述映射的索引:

es.indices.create(index='ecommerce_data', body=mapping, ignore=400) 

执行后,应产生如下响应:

ObjectApiResponse({'acknowledged': True, 'shards_acknowledged': True, 'index': 'ecommerce_data'}) 

通过这些配置,您的 Elasticsearch 环境现在已完全配备用于索引和查询我们的数据集。

数据导入到 Elasticsearch

将数据集导入到 Elasticsearch 索引是涉及将我们的 DataFrame 中的数据传输到 Elasticsearch 的步骤。此过程使用高效的批量索引方法,这对于有效地处理大量数据至关重要。

从数据集加载步骤开始,我们包括处理之前识别的不一致和缺失值,并用 None 类型替换这些值以避免索引过程中的错误。根据您的设备硬件,索引过程可能需要一些时间,从几分钟到几小时不等,具体取决于数据集的大小。您可以使用 tqdm 进度条跟踪此进度。

为了进一步优化索引性能,我们在批量索引方法中包含 chunk_size 参数。此参数控制每个批量请求中处理的文档数量,调整其值可能会影响索引速度和内存使用。除了 chunk_size 之外,如果您仍然遇到内存问题,我们还建议在索引之前截断数据。要截断数据,您可以使用 pandas 函数,例如 df = df.head(n),将 DataFrame 限制为前 n 行。让我们看一下代码:

from elasticsearch import helpers
from tqdm import tqdm
def generate_data(df):
    for index, row in tqdm(df.iterrows(), total=len(df), desc="Indexing documents"):
        doc = {
            "_index": "ecommerce_data",
            "_source": {
                "event_time": pd.to_datetime(row['event_time']).isoformat() if pd.notna(row['event_time']) else None,
                "event_type": row['event_type'],
  "product_id": int(row['product_id']) if pd.notna(row['product_id']) else
None,
                "category_id": int(row['category_id']) if pd.notna(row['category_id']) else None,
                "category_code": row['category_code'] if pd.notna(row['category_code']) else None,
                "brand": row['brand'] if pd.notna(row['brand']) else None,
 "price": float(row['price']) if pd.notna(row['price']) else None,
                "user_id": int(row['user_id']) if pd.notna(row['user_id']) else None,
                "user_session": row['user_session'] if pd.notna(row['user_session']) else None
            }
        }
        yield doc
success, _ = helpers.bulk(es, generate_data(df), chunk_size=500)
print(f"Indexed {success} documents successfully.") 

在索引过程完成后,您应该看到以下类似的输出:

Indexing documents: 100%|██████████████████████████████████| 3533286/3533286 [19:36<00:00, 3004.23it/s]
Indexed 3533286 documents successfully. 

使用 GPT 与 LangChain 集成

将 LangChain 与您的 Elasticsearch 后端集成涉及设置环境,以便 LangChain 可以使用 LLM 动态根据从 Elasticsearch 获取的数据生成内容。我们将使用 gpt-3.5-turbo LLM 进行演示,但您应参考最新的 LangChain 文档以获取最新的模型信息 (api.python.langchain.com/en/latest/chat_models/langchain_openai.chat_models.base.ChatOpenAI.html):

  1. 第一步涉及初始化 GPT 模型作为 LangChain 模型。如果您还没有完成此步骤,您可能还需要为该模型生成一个 OpenAI API 密钥,这个过程目前包括创建一个 OpenAI 账户。有关此指令的更多详细信息,可以在 OpenAI 网站上找到 (platform.openai.com/docs/introduction):

    from langchain_openai import ChatOpenAI
    # Replace 'XXX' with your OpenAI API key
    llm = ChatOpenAI(openai_api_key='XXX', model= "gpt-3.5-turbo") 
    
  2. 一旦模型设置完成,下一步就是构建查询以从 Elasticsearch 获取相关数据。这些数据作为 GPT 的输入,使其能够根据用户行为生成上下文相关的內容。

例如,以下是您如何定义一个函数来根据任何匹配的查询从 Elasticsearch 获取数据:

def retrieve_data_from_es(query):
    response = es.search(index="ecommerce_data", body={"query": {"match": query}})
    return response['hits']['hits'] 

此函数 retrieve_data_from_es 接收一个表示 Elasticsearch 查询的字典,并返回与该查询匹配的文档列表。提供的示例检索与特定用户 ID 相关的记录,允许根据用户的先前交互生成个性化内容,例如查看或添加到购物车的产品。例如,要获取与 user_id 576802932 相关的内容,我们可以执行以下操作:

query = {"user_id": "576802932"}
data = retrieve_data_from_es(query) 
  1. 从 Elasticsearch 获取的 data 响应包括用户活动的详细记录,每条记录都带有精确的时间戳、产品标识符、类别细节和会话信息。我们可以通过以下方式查看这些类型交互的示例:

    removal_example = next(item for item in data if item['_source']['event_type'] == 'remove_from_cart')
    view_example = next(item for item in data if item['_source']['event_type'] == 'view')
    print("Removal Example:\n", removal_example)
    print("\nView Example:\n", view_example) 
    

以下截图显示了输出结果:

图片

图 11.7:从数据集中移除购物车和查看事件类型的示例条目

在这些例子中,一条记录显示用户在午夜左右从购物车中移除商品,这表明重新考虑或偏好改变。第二条记录捕捉到一个查看事件,其中用户正在浏览产品,但尚未做出购买决定。理解这些交互可以帮助设计个性化的重新参与策略,鼓励用户完成购买并提高转化率。

现在我们已经设计、实施并测试了我们的知识检索模型框架,让我们通过一个例子来探索这个模型的应用。

基于客户数据实现 RAG 的微定位

在彻底分析数据集并构建了一个稳健的检索系统之后,我们现在从理论框架过渡到实际实施。在本节中,我们将学习如何应用 RAG 来动态解决数字营销中常见的挑战,例如训练模型中的过时信息和捕捉最新的用户交互。尽管传统的零样本学习ZSL)和少样本学习FSL)模型功能强大,但它们往往在实时响应方面落后,并且依赖于现有数据,限制了它们在这样快节奏的营销场景中的有效性。

为了克服这些限制,我们将利用 RAG 生成不仅是最新的,而且与当前消费者行为高度相关的营销内容。通过将我们的检索系统与 GPT 集成,我们可以直接从我们的数据库中提取最新的用户交互数据。借助 RAG,我们还可以根据个别用户场景生成实时内容,有效地重新吸引那些已经放弃购物车的客户。这种方法使我们能够生成基于最新和最相关用户活动的营销策略,这是静态模型无法实现的。

确定营销活动策略

随着我们从之前讨论的理论框架过渡,了解即将展示的例子中的战略基础非常重要,我们将演示如何应用 RAG。在深入现实世界例子之前,我们将通过在数据集上执行更多关键探索性分析来设定我们微定位策略的基础,以确定我们的最佳营销策略及其目标。

消息时间

数字营销的效率不仅降低了成本,还提高了营销活动的有效性。我们营销活动的战略组成部分之一将是优化营销信息的时间安排。如第四章所述,理解用户交互的时间序列趋势可以特别有洞察力。由于我们只有一个月的数据,我们不会基于日期进行分析,而是将检查交互如何随一天中的时间变化,以便我们可以使用这些信息来了解用户参与的最佳时间,为下个月提供洞察。我们可以通过以下方式提取做出此决策所需的见解:

import matplotlib.pyplot as plt
df['event_time'] = pd.to_datetime(df['event_time'])
df['time_of_day'] = df['event_time'].dt.hour
time_of_day_data = df.groupby(['time_of_day', 'event_type']).size().unstack()
fig, ax = plt.subplots(figsize=(12, 6))
time_of_day_data.plot(ax=ax, title='User Interactions by Time of Day')
plt.xlabel('Hour of the Day')
plt.ylabel('Number of Events')
plt.xticks(range(0, 24))
plt.grid(True)
plt.show() 

这给我们带来了以下图表:

图片

图 11.8:不同时间跨度的用户交互事件类型数量

从绘制的数据中,我们观察到一天中几个明显的用户行为模式,这对我们微目标策略的时间安排具有重要意义:

  1. 高峰观看时间:最高的用户活动,特别是观看,发生在17:0020:00之间。这个高峰期是推送广告和个性化内容的最佳时期,以最大化曝光和参与度。

  2. 高交易活动:购物车添加和购买行为通常在17:0020:00之间也较高。这不仅表明了活跃的浏览行为,还表明了更高的最终购买倾向,使其成为促销活动的理想时间。

  3. 购物车移除洞察:购物车移除趋势与前面提到的两个趋势紧密相关,并在18:0020:00之间达到峰值,这表明用户处于重新考虑阶段。这个时期可以通过提醒或激励措施,如折扣优惠或免费送货,将犹豫转化为销售。

  4. 早晨和晚上的趋势:虽然从早晨开始活动逐渐增加,但在21:00之后急剧下降,这表明晚上的时间可能并不适合进行针对性的营销活动。

考虑到这些模式,可以在19:0021:00的时间窗口内实施针对性的策略,以降低购物车放弃率。在此期间,部署个性化的重新参与活动,如发送提醒邮件、提供限时折扣代码或显示带有特别优惠的弹出消息,可以特别有效。

在进行自己的分析时,重要的是要考虑,当分析不同时区的用户交互时,行为模式会有所不同。因此,重要的是要确认用户时区被准确记录并存储在您的数据库中,或者根据用户的地区在事后对时区差异进行考虑。未能做到这一点可能会导致涉及跨区域用户行为的分析,从而导致信息发送时间不当。

选择品牌

随着我们继续完善我们的营销策略,确定我们数据集中哪些品牌具有最高的提高转化率潜力至关重要。在之前的分析中,我们探索了品牌出现的频率来衡量它们的普遍性。现在,让我们通过检查前五个品牌来深入了解,了解不同类型的互动如何在这些品牌之间变化:

top_brands = df['brand'].value_counts().nlargest(5).index
brand_event_type_counts = df[df['brand'].isin(top_brands)].groupby(['brand', 'event_type']).size().unstack()
Brand_event_type_counts 

这产生了以下输出:

图片

图 11.9:五个最受欢迎的品牌按事件类型用户互动数量

分析品牌互动,bpw.style在需要重点改进的候选者中脱颖而出,尤其是在购物车放弃率方面。虽然bpw.style在数据集中有显著的存在,但添加到购物车中的商品数量(21995)与移除的数量(18014)之间存在明显的差异。这种模式表明,从初始兴趣到最终购买决策之间存在重大差距。

为了量化改进的机会,让我们计算bpw.style品牌的购物车放弃率:

abandon_rate_bpw = brand_event_type_counts.loc['bpw.style', 'remove_from_cart'] / brand_event_type_counts.loc['bpw.style', 'cart']
print(f"Cart Abandonment Rate for bpw.style: {abandon_rate_bpw:.2f}") 
Cart Abandonment Rate for bpw.style: 0.82 

解决购物车放弃率的问题可以显著提高bpw.style的表现,将潜在销售转化为实际购买。

使用 LangChain 进行微定位

之前,我们建立了一个与 GPT 集成的检索系统,根据 Elasticsearch 的数据动态生成内容。现在,我们将利用我们刚刚定义的营销活动目标,通过分析用户行为(按品牌和时间)获得的见解,创建高度个性化的内容,旨在提高客户参与度。我们将从两个针对特定用户的例子开始,然后过渡到第三个专门针对bpw.style品牌消费者的例子。

案例研究 1:目标产品折扣

由于我们的数据显示用户互动,尤其是购物车添加和移除,大致在17:0021:00之间达到峰值,我们将利用这个时间段作为发送营销信息的最佳窗口,捕捉用户最活跃和可能重新考虑购买决策的时刻。这种接触的首选媒介将是电子邮件,它允许发送丰富、个性化的内容,并通过提醒用户他们购物车中的商品或提供限时优惠来有效地重新吸引用户。

为了生成定制营销内容,我们部署了一个函数,该函数根据用户互动为 GPT 构建提示,将这些数据点转化为可操作的营销策略:

def generate_content(data):
    if not data:
        return "No data available to generate content."
    messages = [
        ("system", "You are an assistant that generates marketing strategies based on user activities.")
    ]
    for item in data:
        source = item['_source']
        product_description = f"{source['event_type']} the product {source['brand']} priced at ${source['price']} on {source['event_time']}."
        messages.append(("human", product_description))
    messages.append(("human", "Based on these interactions, suggest a targeted marketing message to improve engagement that focuses on product discounts."))
    try:
        response = llm.invoke(messages)
        return response.content
    except Exception as e:
        return f"Error generating content: {str(e)}" 

此函数构建了一系列要输入到 LLM 的消息,每条消息代表一个重要的用户互动,例如添加到购物车或从中移除。这些描述最终归结为一个请求,要求为这些活动生成定制营销策略,提示 LLM 生成定制消息。

回到我们之前对存储在我们检索索引中的“user_id": “576802932"数据存储的分析,我们可以对此客户进行分析,并获得如下响应:

query = {"user_id": "576802932"}
data = retrieve_data_from_es(query)
generate_content(data) 

这产生了以下:

Dear customer, we have noticed that you've recently removed a few items from your cart. We'd like to offer you a special discount on those products to help complete your purchase. This discount of 10% is valid only for the next 24 hours and can be claimed using discount code LOVE10 at checkout. Add them to your cart now and let's get those items home! 

我们的营销活动可以根据大约17:00的最新客户互动数据来生成此提示,然后稍后发送电子邮件。这不仅提供了一个直接激励以减少放弃,而且还创造了一种紧迫感,使客户更有可能采取行动。

案例研究 2:产品促销

在基于第一个案例研究的洞察的基础上,该案例研究专注于通过高峰互动时段的目标性折扣来降低购物车放弃率,第二个案例研究探索了一种补充策略。在这里,我们旨在通过根据用户在类似高峰时段的行为和偏好提供个性化产品推荐来增强产品促销:

此函数旨在利用用户数据,不仅提醒他们注意他们遗弃的购物车,而且根据他们的浏览和购买历史,促销相关或互补产品。通过这样做,我们不仅旨在恢复遗弃的购物车,而且旨在提高平均订单价值:

def generate_upsell_content(data):
    if not data:
        return "No data available to generate content."
    messages = [("system", "You are an assistant that generates upsell opportunities based on user purchase history.")]
    for item in data:
        source = item['_source']
        messages.append(("human", f"Identify complementary products for {source['brand']} priced at ${source['price']} that were viewed but not purchased on {source['event_time']}."))
    messages.append(("human", "Suggest an upselling strategy that could be included in a follow-up marketing email."))
    try:
        response = llm.invoke(messages)
        return response.content
    except Exception as e:
        return f"Error generating content: {str(e)}" 

此函数旨在构建一个故事,不仅解决减少购物车放弃的即时需求,而且战略性地建议一些可以增强用户初始选择的产品,从而可能增加交易价值。

我们现在可以将此函数应用于上次相同的消费者,并查看结果,这次提示模型返回一个完整的电子邮件消息:

query = {"user_id": "576802932"}
data = retrieve_data_from_es(query)
output = generate_upsell_content(data) 

这产生了以下电子邮件内容:

图片

图 11.10:为用户 576802932 生成的定制促销内容策略,基于从 Elasticsearch 数据库检索到的交互数据

案例研究 3:为 bpw.style 提供实时内容定制

在利用 RAG 进行微目标定位的策略基础上,本案例研究特别关注提高bpw.style品牌的参与度和降低购物车放弃率。认识到购物车添加和完成之间的差异,正如之前分析的那样,我们针对可能从温和提醒或激励中受益的用户进行目标定位。此查询将特别寻找购物车添加和移除事件:

  1. 这里是一个包含 Elasticsearch 查询以获取此类特定品牌互动数据的函数:

    def retrieve_bpw_style_data(es_client):
        query = {
            "bool": {
                "must": [
                    {"match": {"brand": "bpw.style"}},
                    {"terms": {"event_type": ["cart", "remove_from_cart"]}}
                ]
            }
        }
        response = es_client.search(index="ecommerce_data", body={"query": query, "size": 100})
        return response['hits']['hits'] 
    
  2. 在获取了目标数据后,我们现在可以将这些数据整合到我们的generate_reengagement_content函数中。修改后的函数将使用我们新的查询函数获取的数据来生成个性化的重新参与策略:

    def generate_reengagement_content(es_client):
        data = retrieve_bpw_style_data(es_client)
        if not data:
            return "No data available to generate content."
        messages = [
            ("system", "You are an assistant that creates re-engagement strategies for users who have shown interest in bpw.style products but abandoned their carts.")
        ]
        for item in data:
            source = item['_source']
            interaction_desc = f"User showed interest in {source['brand']} priced at ${source['price']} but abandoned the cart on {source['event_time']}."
            messages.append(("human", interaction_desc))
        messages.append(("human", "Generate a short personalized email to re-engage the user and encourage them to complete their purchase."))
    
        try:
            response = llm.invoke(messages)
            return response.content
        except Exception as e:
            return f"Error generating content: {str(e)}" 
    
  3. 我们可以通过以下方式运行我们新的查询和内容生成命令:

    marketing_message = generate_reengagement_content(es)
    print(marketing_message) 
    

这产生了以下:

图片

图 11.11:为对 bpw.style 产品感兴趣但已放弃购物车的用户创建的个性化重新参与策略

如输出所示,通过专注于表现出高购物车放弃率的特定品牌,我们可以定制针对品牌认知和客户参与度相关独特挑战的营销策略。这种方法允许创建与品牌受众产生共鸣的高度特定内容,有可能将浏览行为转化为完成的交易。虽然这种策略强调品牌特定数据,但它可以无缝集成之前展示的用户特定洞察,包括可用的人口统计信息,以增强营销信息的精确性和相关性。

摘要

本章详细探讨了 RAG 及其对精准营销的变革性影响。通过将生成式 AI 与动态检索系统相结合,RAG 通过将实时、特定上下文的数据纳入内容生成,克服了先前模型(如 ZSL 和 FSL)固有的局限性。这使得营销策略在个性化方面达到了前所未有的水平,增强了针对个人消费者偏好和当前市场状况的营销内容的关联性和有效性。

我们通过实际示例和数学模型展示了 RAG 如何有效地结合数据的新鲜性和特异性,从而提升消费者参与度并优化转化率。

讨论还涵盖了支撑 RAG 的技术机制,从查询生成和信息检索到生成内容的迭代优化。这些元素确保内容不仅与受众产生共鸣,而且与最新的趋势和数据洞察保持一致,这在当今快速发展的数字营销环境中是一个至关重要的优势。

面向未来,在下一章中,我们将转向营销中 AI 和 ML 的更广泛领域,巩固本书所学知识,同时探索新兴技术。我们将结合当前方法和 AI 的预测性进步,这将进一步革命化营销。此外,我们还将探讨 AI 如何成为新兴数字平台的核心,这些平台提供了与客户互动和个性化营销努力的新方法。这种前瞻性视角将为您提供在不断演变的 AI 环境中导航所需的见解和技能,为您的数字营销未来做好准备。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人见面,并在以下地点与超过 5000 名成员一起学习:

packt.link/genai

二维码

第十二章:营销中 AI 和 ML 的未来格局

我们现在正进入探索机器学习ML)和生成式 AIGenAI)在营销中集成的最后阶段。AI 和 ML 的格局是动态的,并且正在迅速演变,这为更多的激动人心的变化奠定了基础。到目前为止,我们已经探讨了生成式 AI 和数据驱动洞察如何革命性地改变营销策略,从解码营销 KPI 和获得详细的客户洞察,到制作引人入胜的内容、增强品牌存在感和对消费者进行微定位。本章旨在整合我们对关键 AI 和 ML 概念的理解,并预测它们在营销中的未来应用。

尤其是首先,我们将回顾前几章中介绍的生成式 AI 基础,然后探索诸如多模态生成式 AI、高级模型架构以及用于创建针对消费者行为和偏好的个性化内容的综合多种数据类型的技术等新兴技术。虽然第七章讨论了使用市场篮子分析、协同过滤和其他传统推荐方法进行个性化推荐,但本章介绍了如何使用多模态生成式 AI 通过多种数据类型(如文本、图像和视频)来实现这一点。我们还探讨了更高级的模型架构,如 ReAct,它结合推理和行动以实时适应用户行为,从而进一步推动用户个性化的边界。最后,我们将探讨 AI 如何与增强现实(AR)和虚拟现实(VR)等新型平台集成,将传统营销策略转变为更沉浸式的消费者体验。

到本章结束时,你将获得:

  • 对过去章节中介绍的基本生成式 AI 概念的整合视图

  • 对当前塑造营销并预期如何演变的 AI 和 ML 技术的更全面理解

  • 对 AI 与新型数字平台集成及其对未来营销实践影响的洞察

整合关键 AI 和 ML 概念

在本节中,我们将简要回顾前几章中讨论的核心生成式 AI 概念,为我们探索新兴技术和未来趋势做准备。在每种情况下,你可以参考原始章节以获得对内容和其理论的更深入讨论。

第九章中,我们首先通过讨论概率模型和上下文嵌入来为理解生成式 AI 模型(GenAI)的起源奠定基础。本章需要记住的关键概念包括:

  • 贝叶斯推理和概率模型:贝叶斯定理通过将先验知识与新的证据相结合,引导模型调整其理解。这个过程对于模型遇到完全新的情境至关重要——它使模型能够在无需大量重新训练的情况下改进其预测。

  • GenAI 模型:基础模型如生成对抗网络GANs)、变分自编码器VAEs)、长短期记忆LSTM)网络和生成预训练转换器GPTs)推动了文本、图像和序列生成中的创新内容创作。

  • 上下文嵌入和预训练模型:上下文嵌入允许 AI 根据周围文本动态调整理解,而预训练模型在大型数据集上训练,显著降低了 AI 驱动解决方案的成本和部署时间。这为零样本学习ZSL)铺平了道路,其中模型可以执行其初始训练中未涵盖的任务。

第十章中,我们介绍了如何通过少样本学习FSL)和迁移学习来调整预训练模型,以在新任务上表现更好。该章节讨论的核心主题包括:

  • FSL:FSL 训练机器学习模型通过仅使用少量标记示例来适应新任务。这项技术涉及元学习或“学习如何学习”,使模型能够开发出能够有效推广到新情境的表示。

  • 迁移学习:迁移学习将先前任务的知识应用于提高新任务的表现,减少了大量训练数据的需求。这种方法在先前任务与当前任务之间有强烈关系时特别有用。

  • FSL 和迁移学习的成本效益分析:根据具体需求和约束条件评估何时使用每种方法,考虑因素包括成本、使用频率和捕捉复杂模式的需求。

下图展示了这些技术之间的一些差异:

几种不同类型的神经网络 描述由中等置信度自动生成

图 12.1:典型零样本学习(ZSL)、少样本学习(FSL)和迁移学习实现及其机制的关键差异

最后,在第十一章中,我们讨论了如何通过检索增强生成RAG)实现针对单个消费者的微定位。该章节的讨论包括:

  • RAG: RAG 通过整合实时数据检索,增强了传统的生成模型,从而产生个性化且及时的内容。这种混合方法依赖于外部数据库来提供上下文相关的信息。

  • RAG 在市场营销中的应用:RAG 用于个性化广告、动态内容创建、按人口统计学的针对性营销以及增强客户参与度。它使营销人员能够通过整合最新和最具体的信息来创建高度个性化的内容。

  • 使用 LangChain 构建知识检索系统:LangChain 促进了语言模型与强大检索系统的结合。这种集成支持根据最新可用数据生成内容。

现在我们已经回顾了这些关键概念,让我们展望一下一些下一代技术,您可以使用这些技术。

营销领域的下一代人工智能技术

本节突出了在人工智能营销领域重新定义可能性的重大进步和新型模型架构。这些技术中的每一个都有助于我们推动边界,创造更多动态、响应和个性化的营销解决方案。这些技术的当前成熟度也将被讨论,在 ReAct 和多模态 GenAI 的情况下,这些技术已经可以在产品中使用,并且可以被早期采用者用于他们的营销策略。

从 RAG 到 ReAct

ReAct,即“推理与行动”,代表了 GenAI 系统的一个重大进步,通过整合复杂的推理和外部工具交互。ReAct 建立在 RAG、ZSL、FSL 和提示工程的能力之上,通过结合思维链过程,这些过程涉及 AI 系统将复杂任务分解成一系列较小、可管理的步骤。思维链提示在 GenAI 中至关重要,因为它引导 AI 通过一系列逻辑步骤达到结论,提高其响应的准确性和相关性。这模仿了人类的推理,并促进了交互式工具的使用,使 AI 不仅是一个响应者,而且在现实世界应用中也是一个主动的代理。

ReAct 的工作原理

ReAct 将人工智能能力与操作行动相结合,体现了一个模型,其中 AI 的输出可以启动现实世界中的任务和交易。在其核心,ReAct 可以通过增强决策框架来理解,其中输出不仅仅是信息性的,而且是可操作的。

ReAct 的真正力量在于其与外部工具无缝交互的能力——不仅包括用于实时数据检索的数据库,还包括用于即时计算的计算器和甚至互联网以收集更广泛的上下文洞察。这种交互使系统能够执行复杂任务,从计算最佳营销支出到根据竞争对手网站的最新更新找到其产品信息。以下图表提供了 ReAct 系统关键组件的概述:

图 12.2:ReAct 系统可以整合各种工具以支持营销活动

市场营销应用

ReAct 可以通过实现不仅数据检索,而且在各种外部系统中的直接、实时交互和执行,将营销活动推进到 RAG(Retrieval-Augmented Generation)领域之外。这种高级功能允许营销策略自动化复杂流程,并以数据检索系统如 RAG 无法实现的方式个性化客户互动。这些能力的应用可以包括以下方面:

  • 实时库存管理:ReAct 可以直接与库存系统交互,根据库存水平调整营销策略。例如,如果一个产品的销售速度比预期快,ReAct 可以增加广告支出并加强促销活动以利用这一趋势,同时通知供应链管理系统调整库存水平。

  • 动态定价调整:利用 ReAct,公司可以实施动态定价模型,其中价格根据需求、竞争对手定价和库存状况实时调整。这可能涉及 ReAct 监控在线竞争对手的价格,并在如黑色星期五等高流量事件期间自动调整其定价以保持竞争力。

  • 互动式客户服务:ReAct 不仅可以通过基于常见问题解答和客户数据的生成响应来提升客户服务,还可以通过执行诸如预约、处理退货或直接通过客户服务聊天机器人发放退款等操作。

模型架构的进步

随着生成式人工智能(GenAI)领域的持续发展,一些显著的进步已经出现,这些进步将边界推进到了基础模型如 GANs、VAEs、LSTMs 和 transformers 等模型之外。这些发展不仅增强了现有模型的能力,还引入了新的范式,这些范式正在以创造性和影响力的方式塑造人工智能的未来。在这里,我们探讨三种这样的创新:

  • 扩散模型:这些模型正在革命性地改变生成图像的质量和多样性。对消费者来说逼真的高质量图像是优化营销内容与客户互动的核心。

  • 神经辐射场(NeRFs):这些正在改变我们创建和交互 3D 内容的方式,使得 VR 和 AR 应用的市场营销成为可能,这些内容将在本章后面讨论。

  • 胶囊网络:这些提供了一种理解复杂数据结构和空间层次结构的新方法,这些结构也是 VR 和 AR 应用的核心。

让我们更详细地看看这些内容。

扩散模型

生成模型中最显著的近期进展之一是扩散的发展。这些创新模型通过一个复杂的过程运行,逐渐学会逐步逆转数据中噪声的添加,有效地“去噪”它,逐步恢复原始数据。这种方法已被证明在生成高质量、高分辨率图像方面非常有效,在许多场景中往往超过了传统 GANs 的性能。通过采用一系列逐步提高数据质量的转换,扩散模型擅长产生详细且多样化的输出。这种能力使它们特别适用于需要高保真度和多样性的应用,如数字艺术创作和市场营销材料的逼真渲染。

扩散模型所采用的过程可以通过一系列变换来可视化,其中每一步都会逐步去除输入数据中的噪声,使其逐渐接近原始结构。以下图表展示了这一变换序列,展示了模型如何通过几个步骤从噪声状态迭代地细化,最终恢复到清晰、结构化的数据:

图片

图 12.3:扩散模型中的迭代降噪过程(来源:https://arxiv.org/pdf/2208.11970)

在这个图表中,x[0]代表真实数据观测,如自然图像,x[T]代表纯高斯噪声,而x[t]是x[0]的中间噪声版本。每个q(x[t]|x[(][t−1][)])被建模为一个高斯分布,其前一个状态输出作为其均值。

扩散模型目前被应用于最先进的文本到图像模型中,如 DALL-E 3、谷歌的 Imagen 和 Midjourney。OpenAI 还有一个名为 Sora 的扩散模型,它可以生成视频,尽管目前这个模型尚未向公众发布。

神经辐射场

在 3D 内容生成的领域,尤其是在 VR 和 AR 应用中,NeRFs(神经辐射场)已经出现成为一种突破性的技术。NeRFs 使用一个全连接的神经网络来从一组稀疏的 2D 图像中建模场景的体积密度和颜色。然后,这个模型可以用来从任何视角渲染逼真的 3D 场景,为创建沉浸式虚拟环境提供了一个极其强大的工具。对于市场营销的影响是巨大的,允许品牌创建更真实、更具交互性的 3D 广告或虚拟产品展示。在市场营销之外,NeRFs 还被用于其他应用,包括视频游戏和自动驾驶车辆导航。

从技术角度来看,NeRFs 使用一组输入视图,并使用位置编码技术训练网络,将这些视图转换成连续的 5D 场景表示。在这里,5D 指的是 NeRF 模型用来表示场景的 5D 连续函数,其中 3 个维度由空间位置xyz给出,另外两个维度定义了视图方向。因此,这个 5D 空间包含了从任何视角观察位置的位置和方向,这对于从任何视角准确渲染场景至关重要。

渲染过程涉及通过场景投射光线,并使用体积渲染技术计算颜色和透明度,这些技术由学习到的神经网络参数定义。这个过程计算量很大,通常需要优化,如分层采样,以有效地生成图像。以下图是过程的视觉描述:

图 12.4:通过 NeRF 使用从不同视角随机捕获的一组输入视图来渲染新视图(来源:https://arxiv.org/pdf/2003.08934)

胶囊网络

胶囊网络是神经网络领域的一个有趣的发展,通过更好地模拟数据中的层次关系,为传统的卷积网络提供了一个有希望的替代方案。这种能力在空间关系至关重要的任务中特别有用,例如在 AR 应用中解析复杂场景或理解网页布局以进行自动化设计任务。到目前为止,关于胶囊网络架构在商业产品和技术中应用的报道有限,尽管有各种开源项目和实现,如 CapsNet-Keras 和 CapsNet-TensorFlow,可用于实验和研究。

胶囊网络围绕称为胶囊的神经元组构建其架构,这些胶囊被设计用来捕获和保持数据中不同类型实体存在的概率和实例化参数。与传统卷积网络不同,由于池化层导致特征之间的空间层次丢失,胶囊通过动态路由保留这些信息——这是一个允许一个层的胶囊根据胶囊之间学习到的“协议”将它们的输出发送到下一层适当父胶囊的过程。这种机制需要实现路由算法,如基于协议的动态路由,这通常涉及复杂的迭代过程,调整胶囊之间的耦合系数。作为一个简化的胶囊网络说明,我们可以将标准神经网络中发现的传统人工神经元与胶囊进行比较:

图 12.5:(a)标准神经网络中发现的人工神经元和(b)胶囊网络中发现的胶囊的描述(来源:https://arxiv.org/pdf/2206.02664)

多模态 GenAI

第九章中介绍基于 Transformer 的架构的基础上,多模态 GenAI 系统代表了这些系统的先进演变。这些架构可以通过处理多种数据模态(如文本、图像和视频)来解释和生成内容,并超越了单模态模型,通过整合和交叉引用来自不同来源的数据。这种整合促进了更深入的内容和上下文的理解,使 AI 能够执行复杂的“跨模态”操作。

技术基础

多模态模型修改了传统的 Transformer 架构,将不同的数据形式编码到共享的潜在空间中,从而允许跨模态操作。例如,这些系统可以从视频剪辑中生成描述性文本,或从文本描述中合成视频,展示了它们无缝连接不同类型信息的能力。多模态 AI 有效性的核心在于其复杂的神经网络架构,这些架构具有跨模态注意力机制。这些机制对于模型有效地聚焦和整合来自不同模态的特征至关重要。

以下图表简化了这一过程在概念层面的工作方式:

图片

图 12.6:多模态 GenAI 系统的简化架构

在这个例子中,文本、图像和音频数据的不同输入模态被输入到编码器中,由融合层进行处理。融合层使用如跨模态注意力等方法结合这些模态,然后再将它们输入到核心生成模型中。这个核心模型被设计用来处理融合的多模态数据以生成新的输出预测。然后,这些输出被解码成所需的模态格式——在本例中是文本和视频——供最终用户使用。

多模态应用

多模态 GenAI 的复杂方法允许营销人员通过整合多样化的数据源,更深入地理解和与消费者互动。随着多模态 AI 处理这一广泛的输入,它能够实现更个性化、相关性和动态适应的营销策略,这些策略能够在多个层面上引起消费者的共鸣。以下是一些具体的应用实例,展示了这项技术创造更有效的营销活动的潜力。在每个应用中,都给出了在实施这些策略时需要考虑的营销关键绩效指标(KPI)。这些指标应被跟踪以评估多模态 GenAI 方法的有效性,并确定其相对于成本的回报率(ROI),通过如 A/B 测试(第六章)等技术来实现。

增强消费者参与度

考虑通过综合各种数据形式来增强叙事,使多模态 AI 能够生成丰富的叙事体验。例如,一家旅行社可能会根据客户的先前搜索、在 Instagram 上探索的目的地和类似旅行的正面评论创建个性化的旅行视频。这种有针对性的叙事可以与消费者建立更强的情感联系,导致更高的参与度。在实施这一策略时,值得跟踪的关键绩效指标(KPI)如点击率,以查看用户与多模态 GenAI 内容互动的可能性比与传统内容更高的程度。

实时内容适配

多模态 AI 对于营销中的实时内容适配至关重要,它能够有效地从多个来源分析和综合数据。例如,考虑一个使用多模态 AI 优化其营销策略的服装品牌。这个 AI 系统不仅分析文本数据,如天气预报,还评估社交媒体趋势中的视觉数据和最近时装秀的视频内容。通过评估这种文本、图像和视频的组合,AI 可以检测消费者偏好的微妙变化或天气模式的突然变化。在这种情况下,监控转化率的关键绩效指标(KPI)是查看从 GenAI 生成的可能更相关的内容如何导致比不考虑最新趋势的传统内容更高的销售额的一种方法。

互动式客户支持

零售商可以通过实施多模态 AI,通过能够理解和处理文本和图像输入的聊天机器人提供互动式客户支持。例如,客户可以上传损坏产品的图片,AI 系统可以分析图片,识别问题,并提供适当的解决方案或启动退货流程。这种能力通过提供快速准确的支持,减少对人工干预的需求,从而提高整体客户满意度和品牌忠诚度。在这种情况下,我们可以监控用户与 GenAI 系统互动时的首次响应时间、问题解决和客户保留的关键绩效指标(KPI)。虽然首次响应时间很可能得到改善,但在部署时保持问题解决的质量是一个重要的考虑因素。

AR 和 VR 作为新兴的数字平台

在数字营销的动态世界中,AR 和 VR 将变得越来越关键。它们提供沉浸式和吸引人的体验,帮助品牌在不断演变的数字市场中脱颖而出。AR 通过智能手机等设备将数字元素叠加到物理世界中,而 VR 通过头戴式设备将用户带入完全数字化的环境,使品牌能够打造独特的客户旅程。

VR 和 AR 之间的区别

VR 涉及一种完全沉浸式的体验,它将现实世界屏蔽在外。通过 VR,用户可以体验一个数字环境,在其中他们可以与 3D 世界互动。

AR 通过在现实世界之上叠加数字信息来增强现实。AR 用户可以在与放置在其中的虚拟对象互动的同时看到他们周围的世界。

混合现实MR)是一种新兴趋势,它将这些体验融合在一起,使用户能够在同一会话中与物理和虚拟元素互动。

这些进步得益于 AI 的预测和自适应能力,为营销专业人士提供了与受众互动的新维度。随着预测这些技术采用量将显著增加,营销人员应该了解它们重塑客户互动的潜力。

图 12.7:VR、AR 和 MR 的示意图(来源:https://onlinelibrary.wiley.com/doi/10.1002/adfm.202007952)

ML 在 AR 营销中的作用

AR 不仅仅是将数字内容叠加到现实世界,它是以个性化、相关性和无缝集成到用户环境中的方式来做到这一点。AR 转变为强大的营销工具的转型在很大程度上是由 AI 和 ML 的集成驱动的。让我们讨论一些如何实现这一点的例子。你已经在许多智能手机应用程序中看到了这些例子。

个性化 AR 体验

AI 算法是个性化 AR 体验的核心。通过分析用户互动、偏好和以往行为的数据,这些算法可以定制 AR 内容以满足个人需求和兴趣。

例如,当用户将智能手机摄像头对准商店的货架时,AI 可以显示基于其购物历史的 AR 叠加层,显示他们可能感兴趣的产品。这不仅增强了用户体验,还增加了购买的可能性。

面部识别技术的使用可以进一步个性化体验,例如实时应用虚拟化妆,让顾客在购买前就能看到产品在他们脸上的效果。这种程度的定制让购物体验更加吸引人,并可能导致更高的转化率。

基于地理位置的 AR 活动

地理定位技术与 AI 的结合使营销人员能够提供高度针对性的 AR 内容,这不仅基于用户的个人资料,还基于他们的物理位置。这在基于位置的营销中尤其有效,因为促销活动可以根据当地事件或商店的邻近性进行定制。

例如,靠近音乐场馆的用户可能会看到相关商品或附近餐厅优惠的 AR 促销。人工智能通过考虑用户的情境,不仅包括位置,还包括时间或天气条件等因素,来增强这些体验,提供更相关、更及时的内容,从而提高参与率。

无缝的产品集成

机器学习对于将虚拟产品无缝集成到现实世界环境中至关重要。高级图像识别和空间感知能力允许 AR 系统将虚拟物品真实地放置在用户的周围环境中。

例如,一个由本章前面提到的 NeRF 模型架构驱动的 AR 家具应用程序可以分析房间内可用的空间,并建议既符合物理尺寸又符合美学的家具物品。

机器学习在 VR 营销中的作用

VR 提供了沉浸式的品牌故事叙述,将用户带入一个完全品牌化、互动的宇宙,通过完全沉浸用户在品牌化的虚拟环境中,将客户参与度提升到新的水平。借助人工智能和机器学习,这些虚拟世界可以个性化、动态和响应,创造加强品牌与客户之间关系的体验。尽管这些应用目前不如 AR 常见,但以下章节概述了一些这些原则在实际中的应用示例。

沉浸式故事叙述和品牌体验

人工智能通过根据用户的兴趣和行为个性化内容,使品牌能够在 VR 中提供引人入胜的故事叙述。用户可以探索适应他们偏好的动态剧情,而不是通用的体验。

例如,在一个汽车品牌的 VR 展厅中,客户可以探索针对他们兴趣定制的不同虚拟环境,如探险或家庭旅行。人工智能分析他们的过去选择和行为,动态地建议相关功能或体验,从而增强参与度,使内容更加难忘。

行为数据洞察

在 VR 环境中,每个用户动作都可以被跟踪和分析。人工智能和机器学习算法将这些交互转换为有价值的用户行为数据洞察。

一些例子可以是用户探索某些产品的时间长短、他们遵循的路径,或者他们的目光停留的地方,这些都可以提供关键的数据点。然后,这些洞察力可以用来完善未来的活动、个性化推荐,并实时调整内容。这些行为数据还可以通过帮助品牌了解哪些功能和属性最能引起目标受众的共鸣,来指导产品开发。

虚拟店面和活动

人工智能使得创建高度个性化的虚拟店面和活动成为可能,这些店面和活动提供独特的购物体验。这些店面可以设计成复制甚至增强实体购物体验。用户会根据他们之前的购买、浏览历史和人口统计数据获得个性化的推荐。

在虚拟活动中,由人工智能驱动的聊天机器人和虚拟形象也可以提供即时客户服务并回答问题,使互动感觉自然且信息丰富。品牌还可以在这些虚拟空间内举办现场活动,让客户能够直接与品牌大使和影响者互动。

摘要

随着我们结束对营销领域机器学习和通用人工智能未来前景的探索,我们反思了那些彻底改变营销策略的进步。在这本书中,我们探讨了人工智能和数据驱动的洞察如何指导营销的各个方面——从解码关键绩效指标和收集深入客户洞察,到制作引人入胜的内容和微目标受众。营销领域的 AI 不仅动态变化,而且迅速发展,为未来的进一步变革奠定了基础。

在下一个发展前沿,我们强调了新兴技术,如多模态通用人工智能和高级模型架构,这些架构可以综合多种数据来创建针对消费者定制的内容。我们还研究了人工智能与新型平台(如 AR 和 VR)的结合,这些平台可以将传统的营销方法转变为更沉浸式的消费者体验。

考虑到这些技术的长期影响,未来值得关注的关键发展是多模态人工智能,它将实现高度个性化的营销。通过整合来自各种来源(文本、图像、视频和音频)的数据,营销人员可以创建与每个消费者个人共鸣的高度定制化内容。我们也在朝着半自主营销系统迈进,这些系统能够在最小的人为干预下监督整个活动。虽然完全自主的系统还遥不可及,但这些系统将有助于人类更有效地处理从策略开发到内容创作、部署和实时优化的所有事务。高级人工智能通过分析多个渠道的大量数据,提供更深入和更准确的消费者洞察,从而为消费者行为预测模型带来更好的预测。人工智能与增强现实(AR)和虚拟现实(VR)的结合将创造更沉浸式的消费者体验,模糊数字和物理交互之间的界限。

展望未来,最后一章将探讨 AI 驱动的营销中的关键主题——伦理和治理。这次讨论将聚焦于在部署 AI 时,如何应对复杂的伦理问题和监管框架。通过解决数据隐私、算法偏见和透明度的必要性等问题,我们将强调保护消费者信任和品牌完整性的伦理实践的重要性。通过这一关注点,您将获得理解稳健治理结构和合规策略要素的见解,确保您的 AI 应用既有效又符合伦理。

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人相聚,并和超过 5000 名成员一起学习,详情如下:

packt.link/genai

二维码

第十三章:AI 赋能营销中的伦理与治理

人工智能和机器学习在营销中的广泛应用引发了各种道德问题,包括数据隐私、算法偏见以及透明度的需求,这些问题都可能直接影响到消费者的信任和品牌完整性。在本章的最后,我们讨论了与之前章节中引入的 AI 技术相关的道德考量和管理挑战的至关重要的话题。

本章还将探讨主要的监管框架,如通用数据保护条例GDPR)和加州消费者隐私法案CCPA),它们在解决这些道德问题中发挥着关键作用。这些法规有助于塑造营销中 AI 技术的部署和数据管理政策。了解这些道德和监管方面对于在营销策略中负责任和有效地利用 AI 至关重要。本章涵盖了营销人员如何通过建议的 ML 最佳实践、治理结构和合规性考虑来应对这些挑战。

到本章结束时,您将获得:

  • 对营销中负责任 AI 部署的道德理解

  • 了解监管框架在营销中治理 AI 和数据使用

  • 促进负责任 AI 使用的模型透明度、治理政策和合规性策略

营销中 AI/ML 的道德考量

在营销领域机器学习不断发展的格局中,道德考量对于维护消费者信任和遵守负责任的企业实践至关重要。随着人工智能在客户互动、个性化定位方面的日益重要,营销人员必须意识到他们数据驱动策略的道德影响。透明度、偏见和公平性等问题需要仔细考虑,以确保 AI/ML 应用既有效又符合道德标准。

为了解决这些问题,本节将讨论使您的 ML 预测尽可能可解释的策略,减轻偏见,并将您的生成式 AI 输出建立在真相之上。敏感消费者数据的处理也是需要仔细考虑的另一个话题。未能适当处理消费者数据不仅可能产生法律后果,还可能对品牌的声誉和消费者信任造成毁灭性的公关影响。

模型透明度和可解释性

在营销领域,AI 部署的透明度至关重要。消费者常常对他们的数据如何被使用以及 AI 系统如何做出影响他们与品牌互动的决定持怀疑态度。透明度要求明确沟通 AI 模型是如何训练的、如何运作的以及数据是如何处理的,重点关注理解 AI 模型的决策过程。

一个突出透明度重要性的例子是 2018 年涉及亚马逊 AI 招聘工具的事件。这个旨在帮助自动化招聘流程的工具被发现对女性存在偏见。它被发现更倾向于男性候选人而不是女性,因为它是在过去十年中提交的简历上训练的,而这些简历主要来自男性。亚马逊在发现偏差后不得不废弃这个工具,导致声誉受损。

为了实现透明度,营销人员应优先考虑可解释性——这是用简单术语阐述其 AI 模型如何做出特定决策的能力。透明度通过模型可解释性工具得到促进,我们将在下一节中讨论。以下是解释性对于营销中使用的 AI 模型为何如此重要的几个原因:

  • 消费者信任:解释 AI 决策可以建立消费者信任,尤其是在模型推荐影响敏感事项,如个性化广告时。

  • 合规性:某些数据隐私法规,如 GDPR,要求组织可能需要解释自动化决策。

  • 偏差检测:可解释性有助于识别 LLM(大型语言模型)中的潜在偏差,确保对不同群体公平对待。

    大型语言模型(LLMs)中可解释性的挑战

    由于 LLMs 和其他大型 AI 模型的复杂架构和大量参数,可解释性可能具有挑战性。随着这些模型变得更加准确,它们的决策可能变得更加复杂和难以解释。这强调了模型可解释性技术的重要性。

接下来,我们将讨论一些有助于在现代 AI 模型中实现更高透明度的模型可解释性工具。

模型可解释性工具

如逻辑回归或决策树等 ML 模型具有高度可解释的参数,这些参数为其预测提供了直接的解释性。例如,在第三章中展示的决策树,我们可以可视化导致模型做出决策的逻辑分支。然而,在复杂、现代的 AI 模型中追求透明度带来了更大的挑战,尤其是在深度学习和 LLM 中。这些模型通过复杂、多层网络运行,这些网络不易于解释。然而,已经出现了一些工具和技术来应对这种复杂性。

其中一个工具是 OpenAI 为 GPT-4 引入的概念提取框架。这个框架通过提取模型用于预测的关键概念来提高透明度。它通过分析模型内部的表示和激活来识别影响其决策的模式和概念。通过隔离这些关键概念,该工具可以提供对模型如何解释和处理数据的更清晰理解。

由 Google Research 开发的 Patchscopes 框架是另一个有价值的工具,它提供了一种全面和统一的检查 LLM 中隐藏表示的方法。Patchscopes 允许更广泛地探索 LLM 的内部动态。它通过可视化和分析模型中的隐藏状态和注意力模式来实现。它允许用户跟踪信息在网络中的流动,识别在不同层和头部的 Transformer 架构中哪些输入文本部分被关注,从而提供对模型如何处理和生成语言的详细理解。有关隐藏状态和注意力模式的进一步讨论,请参阅第九章。

LLM 可解释性工具

Patchscopes:有关 Patchscopes 及其应用范围的更多详细信息,请访问 Google Research 博客(research.google/blog/patchscopes-a-unifying-framework-for-inspecting-hidden-representations-of-language-models/)上的 Patchscopes 部分。您还可以探索 pathscopes Python 包以了解其实施情况。

概念提取:有关更多详细信息,请参阅 OpenAI 的帖子(openai.com/index/extracting-concepts-from-gpt-4/),包括链接到研究论文、代码和示例特征可视化。

例如,可以使用 Patchscopes 来调查不同的语言模式如何在模型中表示,以及这些模式如何影响模型的预测。这对于理解营销信息中哪些部分被 AI 模型优先考虑特别有用,使营销人员能够生成更有效的个性化推荐信息,避免潜在的偏见。

下图显示了 Patchscopes 解码源提示中 It 的表示中编码的内容(左侧),通过使用预定义的目标提示(右侧):

图片

图 13.1:Patchscopes 工作流程(来源:research.google/blog/patchscopes-a-unifying-framework-for-inspecting-hidden-representations-of-language-models/

作为例子,让我们看看我们如何可视化 LLM 决策过程的一个基本组成部分:注意力。为了说明这一点,我们将考虑从我们在第十章中为我们的环保厨房用品电子商务品牌引入的早期提示中可以了解到的单词重要性。如果您还记得,我们首次使用零样本学习(ZSL)为我们公司的重新品牌化可持续营销活动引入的提示是:

为一种环保厨房用品撰写产品描述,重点关注品牌道德。

我们将使用 BERT LLM 作为此示例,而不是 GPT-4,以便我们能够分析注意力头。选择 BERT 作为此示例的原因是,GPT-4 API 目前不向用户公开其内部注意力权重,而这种方法需要完全访问这些状态以进行分析和可视化。我们可以首先使用以下代码提取模型注意力值:

import numpy as np
import tensorflow as tf
from transformers import TFAutoModel, AutoTokenizer
model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = TFAutoModel.from_pretrained(model_name, output_attentions=True)
text = "Write a product description for an eco-friendly kitchenware product focusing on brand ethics."
inputs = tokenizer(text, return_tensors='tf')
outputs = model(inputs)
attention = outputs[-1][-1].numpy() 

代码最后一行的 attention 权重数组表示模型如何在输入文本的不同标记之间分配其关注点。每个值表示模型在变压器架构的各个层和头部中给予特定标记的重要性。高值表明模型在处理文本和生成输出时认为这些单词更为重要。

我们可以使用热力图来可视化这些注意力权重,以获得对模型如何处理我们的文本提示的更直观的理解。简单来说,代码将执行以下三个主要步骤:

  1. 处理注意力权重以移除对于图表不需要的额外维度。

  2. 将标记从它们的数字 ID 转换回实际单词,排除用于模型内部处理但不代表实际单词的特殊标记,例如用于指示句子边界的分隔符。

  3. 创建热力图来可视化注意力权重,并查看模型对文本提示中的每个单词的关注程度。

这里是完整的代码:

import matplotlib.pyplot as plt
import seaborn as sns
attention = attention.squeeze(axis=0)
tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"].numpy()[0])
tokens = tokens[1:-1] 
attention = attention[:, 1:-1, 1:-1]
fig, ax = plt.subplots(figsize=(12, 10))
sns.heatmap(attention[0], annot=True, ax=ax, cmap="viridis", xticklabels=tokens, yticklabels=tokens, fmt='.2f', annot_kws={"size": 8})
ax.set_title('Attention Weights for Marketing Prompt')
plt.xticks(rotation=45, ha='right', fontsize=10)
plt.yticks(fontsize=10)
plt.show() 

这给我们以下图表:

图 13.2:营销提示“为环保厨房用品产品撰写产品描述,重点关注品牌道德”的注意力权重

从这个可视化中,我们可以看到模型如何在各种标记之间分配其注意力。以下是在解释此视觉中的注意力值时需要考虑的一些关键点:

  • 对角线模式:沿着对角线的注意力通常表明模型正在关注单个单词及其直接上下文。这可以显示模型如何考虑单词本身及其在序列中的邻近单词。

  • 交叉注意力:非对角线模式揭示了模型如何连接句子中的不同单词。例如,在前面的热力图中,单词 ethics(y 轴)与 eco(x 轴)等术语之间的联系显示出更高的注意力权重,这表明模型理解这些术语在描述产品中的相关性。

  • 单个权重:检查单个权重,我们发现诸如 eco、kitchen 和 ethics 等单词具有更高的注意力值,这表明模型在生成相关产品描述时优先考虑这些术语。

模型随后使用这些注意力权重来确定在提示上下文中哪些单词最重要以及它们如何相互关联,从而使其能够确定最有意义的文本输出。从营销人员的角度来看,这些权重可以用来确保模型强调了您营销信息的关键价值——如果没有,您可以使用这个工具迭代,直到找到合适的提示。

偏差缓解

缓解偏差和确保公平性是市场营销中道德和准确人工智能的核心,因为它们直接影响营销活动的可信度和有效性。未经检查的偏差可能导致某些人口群体的不公平待遇,损害消费者信任,并可能导致法律和声誉上的后果。正如第八章所讨论的,偏差也可能导致不良的细分,这对营销活动的有效性可能造成极大的损害。与透明度和可解释性不同,它们关注的是理解和传达模型如何做出决策,而偏差缓解和公平性则是确保这些决策不会不成比例地伤害或偏袒特定群体。

在以下章节中,我们将讨论解决人工智能中各种偏差方面的策略,并附带市场案例来说明它们的重要性。

缓解人工智能营销模型偏差的策略

  • 训练数据偏差:审计和多样化训练数据以确保适当的代表性。

  • 训练过程中的算法公平性:使用如对抗性去偏等方法来最小化基于受保护数据的预测。

  • 多样化的评估数据:测试模型在各个不同的群体中,以识别和解决差异。

  • 地面 LLMs:使用外部来源来验证和细化生成式人工智能输出的事实准确性。

  • 思维链推理:将生成式人工智能的决策分解为逻辑步骤,以促进公平性。

解决训练数据偏差

训练数据可能反映了社会偏差,这些偏差可能会嵌入到人工智能模型的预测中。这在营销中尤其成问题,因为带有偏差的推荐或广告可能会疏远消费者群体的一部分。为了解决训练数据偏差,对数据进行彻底审计,以确保适当的代表性是非常有价值的。过去章节中讨论的技术,如对代表性不足的群体进行过采样或对现有的训练样本进行排列,也可以通过使训练数据更加平衡来帮助减少这种偏差。

例如,考虑一个主要基于城市、富裕消费者数据的营销模型。正确细分客户基础至关重要,并且由于训练数据中缺乏代表性,该模型在针对农村或低收入群体时可能会表现不佳。通过纳入来自各种社会经济背景的数据,模型可以更好地理解和预测基于人口统计的更广泛受众的行为。

算法公平性技术

通过在模型训练或微调期间使用更专业的技术来确保 AI 模型的算法公平性。这些技术包括均衡机会,确保不同群体具有相似的错误率,以及差异影响消除器,它通过预处理数据来减少偏差并创造更公平的结果。此外,优化中的公平约束将公平指标直接集成到训练过程中,使模型的优化能够考虑公平标准。

例如,对抗性去偏通过训练一个模型来最小化预测错误,同时减少另一个分类器预测受保护属性的能力。这种实现的实施涉及创建一个尝试从主模型的输出或内部表示中预测受保护属性(如种族)的对抗性模型。在训练过程中,主模型不仅因预测错误而受到惩罚,还因对抗性模型在预测受保护属性方面的成功而受到惩罚。这样,主模型就学会了做出与受保护属性相关性较低的预测,从而促进公平性。

在营销应用中,预测消费者对金融产品兴趣的模型不应过度偏向某一种族群体,除非它是专门设计来作为明确目标解决现有金融服务差异。未能考虑这一点可能导致模型基于种族进行预测,而使用与金融产品兴趣直接相关的因素,如收入、信用评分或地理位置,将更加道德。

模型评估数据中的多样性

使用包含不同人口群体的数据进行模型评估,确保预测结果不会不公平地偏向特定群体。这涉及到在模型验证过程中纳入人口属性,以识别和解决任何差异。TensorFlow 的公平指标和 IBM 的 AI 公平 360 等工具和框架可以帮助通过提供突出模型预测中偏差的指标和可视化来评估模型公平性。

模型评估的工具和框架

TensorFlow 的公平指标:允许计算公平性指标,允许跨子组进行比较,并突出差异。了解更多信息请访问www.tensorflow.org/tfx/guide/fairness_indicators

IBM 的 AI 公平 360:提供了一套开源工具包,包括算法和指标,用于检测和减轻偏差。了解更多信息请访问aif360.res.ibm.com/

以用于推荐职位广告的模型为例。这样的模型应该被评估以确保它在不同的群体中表现良好,例如性别和种族。如果模型倾向于向白人男性用户推荐高薪职位,可以通过调整来平衡推荐,确保合格的女性用户和不同种族的用户都能获得同等相关和高质量的职业建议。

LLM 的基础信息

由于训练数据中的偏差,LLM 可能会生成有偏见或事实错误的信息。基础信息涉及使用外部数据库或知识源来验证和细化模型输出,以确保更多的真实性。通过使用权威来源来基础化 LLM,品牌可以确保为营销活动生成的内容是准确且偏见较小的。此外,基础信息有助于减轻幻觉——或者模型生成不基于现实的信息的情况。

你可能还记得,在第十一章中,我们讨论了使用检索增强生成RAG)的微目标定位。基础信息对于有效的微目标定位同样有用,因为它允许大型语言模型(LLM)从之前的客户互动中提取可靠信息,以生成准确和个性化的营销信息。例如,指导模型访问经过验证的产品数据库可以确保描述和规格更加准确,防止模型在内容创作过程中虚构特性或好处。虽然降低模型中的 LLM 温度参数(如第九章中探讨的那样)可以减少幻觉,但这并不能保证幻觉会被完全消除。

思维链推理

最后,我们还有思维链推理,这是在第十二章中介绍ReAct时提出的。思维链推理将复杂任务分解为更简单、顺序化的步骤,使 AI 能够遵循逻辑过程以得出解决方案。思维链推理可以用于营销,通过明确考虑每个决策步骤的公平性,促进更准确和公平的决策。

考虑一个用于个性化产品推荐的营销模型,这是一个在第七章中探讨过的话题。如果没有思维链推理,该模型可能会基于与种族或社区相关的偏见数据模式,不成比例地向少数申请人推荐金融产品,如次级信用卡,从而导致歧视性做法。通过实施思维链推理,我们可以提示模型系统地评估相关因素,如个人信用历史、交易模式和特定的金融需求,以便生成其决策。将这种逻辑分解存储在模型的记忆中,现在它可以遵循一个更公平的过程,根据个人的金融行为来做出推荐。

平衡隐私与个性化

对消费者数据进行日益依赖以驱动机器学习营销模型可能会引发重大的隐私问题。虽然消费者渴望个性化的体验,但他们同样重视自己的隐私,这使得营销人员在这两个优先事项之间找到一个微妙的平衡变得至关重要。道德人工智能的部署需要保护敏感的个人数据,同时提供个性化的推荐和有针对性的营销活动。实现这种平衡不仅对于遵守法律标准至关重要,而且对于维护消费者信任和品牌声誉也是必不可少的。以下是一些策略,可以帮助您的营销活动在满足客户隐私需求的同时,达到所需的精确度和个性化。

联邦学习

联邦学习是一种可以通过数据处理的去中心化显著提高隐私的技术。不是将原始客户数据发送到中央服务器进行分析,而是联邦学习在消费者设备上本地处理数据,并且只向中央系统传输加密的模型更新。然后中央服务器将这些更新聚合起来,以改进共享的全球模型,而不直接访问参与者的敏感数据。这最小化了数据泄露风险,并确保数据保持隐私——允许组织基于敏感的金融或医疗保健数据提供个性化服务,同时保持个人信息的安全。

在实践中,联邦学习的工作原理如下:

  1. 一个基线模型存储在中央服务器上,然后该模型的副本被共享给客户端设备。

  2. 当用户与模型互动时,在个人设备上生成的本地数据被用来本地训练和改进模型。

  3. 定期地,本地训练的模型参数被发送回中央服务器,在那里它们被聚合以增强整体模型。

  4. 更新的中央模型随后被重新分配到用户设备,这些设备继续根据新的本地数据进行改进。

这个迭代过程确保了持续改进的同时维护数据隐私。工作流程在以下图中展示:

图片

图 13.3:联邦学习工作流程

联邦学习最普遍的应用之一可以在智能手机中找到,增强面部识别、单词预测和语音识别等功能。在营销环境中,联邦学习可以用于个性化医疗记录管理,同时遵守 HIPAA 规定。例如,医疗服务提供者可以使用联邦学习在设备上本地分析患者数据,改进诊断模型,而无需将敏感健康信息传输到中央服务器。

差分隐私和匿名化

差分隐私涉及向数据添加噪声,以掩盖原始数据的识别特征,同时不丢失从数据特征中可以学习到的有意义趋势或信号。在实践中,差分隐私在分析之前应用于保护收集到的数据隐私。匿名化是一个互补的概念,它涉及将个人身份信息(PII)转换为无法追溯到个人的格式。

例如,如果公司想了解特定地区客户的购买行为,可以采取以下步骤:

  1. 数据收集: 从目标区域的客户收集购买数据。

  2. 数据匿名化: 应用匿名化技术,如匿名化,用唯一但不可识别的键替换标识符。

  3. 噪声添加: 应用差分隐私技术向数据添加噪声,确保个人购买行为或人口统计数据被掩盖。

  4. 汇总分析: 对匿名化数据进行分析,以识别可以告知广告定位策略的趋势和模式。

  5. 广告定位: 使用分析中获得的知识来优化广告定位,确保广告与受众相关,同时不泄露个人数据。

我们接下来将讨论您如何实现此过程的 步骤 2(数据匿名化)和 步骤 3(噪声添加)。对于剩余的步骤,您可以参考前几章的内容,其中涵盖了这些步骤的基本原理:

  • 步骤 1: 第五章 中的 数据收集

  • 步骤 4: 第八章 中的 通过分段进行汇总分析

  • 步骤 5: 第 7、10 和 11 章 中的 通过个性化推荐进行广告定位

数据匿名化

数据匿名化涉及将个人身份信息(PII)转换为无法追溯到个人的格式。一种有效的方法是匿名化,其中标识符被替换为唯一但不可识别的键。以下是一个示例,说明如何通过将客户购买和人口统计记录中的姓名字段替换为唯一的但不可识别的 customer_id 来实现这一点:

import pandas as pd
import hashlib
customer_data = pd.DataFrame({
    'first_name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace', 'Hannah', 'Ivy', 'Jack'],
    'last_name': ['Smith', 'Jones', 'Brown', 'Johnson', 'Davis', 'Wilson', 'Moore', 'Taylor', 'Anderson', 'Thomas'],
    'age': [25, 30, 22, 40, 35, 28, 26, 33, 29, 37],
    'income': [20000, 35000, 27000, 50000, 45000, 30000, 32000, 38000, 31000, 47000],
    'purchase_amount': [100, 150, 200, 250, 220, 140, 180, 160, 190, 230]
})
def pseudonymize_id(first_name, last_name):
    return hashlib.sha256((first_name + last_name).encode()).hexdigest()
customer_data['customer_id'] = customer_data.apply(lambda row: pseudonymize_id(row['first_name'], row['last_name']), axis=1)
anonymized_data = customer_data.drop(columns=['first_name', 'last_name'])
display(anonymized_data) 

这会产生以下输出:

图片

图 13.4:匿名化后的客户购买数据

在此代码中,我们使用hashlib.sha256函数对first_namelast_name的组合进行哈希处理。SHA-256是一种加密哈希函数,它产生一个独特且固定大小的哈希值。在生成customer_id之后,我们删除了first_namelast_name的原始 PII 列,以防止重新识别。

噪声添加

在匿名化数据后,我们应用差分隐私技术添加噪声并模糊个体购买行为,以进一步保护消费者隐私。我们将通过以下步骤执行此操作:

  1. 使用MinMaxScaler对数值特征(年龄、收入和购买金额)进行缩放,以确保噪声添加在不同数据尺度上是成比例的。

  2. 将控制隐私和数据效用之间权衡的参数![](https://github.com/OpenDocCN/freelearn-ml-zh/raw/master/docs/ml-genai-mkt/img/B30999_13_001.png)设置为例如5.0的值。较小的![](https://github.com/OpenDocCN/freelearn-ml-zh/raw/master/docs/ml-genai-mkt/img/B30999_13_002.png)值,例如1.0,提供更高的隐私性,但会引入更多的噪声并降低数据效用。

  3. 使用拉普拉斯机制(np.random.laplace)添加从拉普拉斯分布中抽取的噪声,噪声量由敏感度(数据的范围)除以 epsilon 决定。

  4. 最后,将数据逆变换回其原始尺度,这对于在原始上下文中解释结果非常重要。

    使用拉普拉斯机制添加噪声

    为了保护隐私,我们使用拉普拉斯机制添加从拉普拉斯分布中抽取的噪声。拉普拉斯分布是一种连续概率分布,在差分隐私中广泛用于向数据添加噪声,以确保个体数据点不能轻易被识别。

    numpy.org/doc/stable/reference/random/generated/numpy.random.laplace.html了解更多信息。

可以使用以下代码执行前面的步骤并将结果可视化:

from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
anonymized_data[['age', 'income', 'purchase_amount']] = scaler.fit_transform(anonymized_data[['age', 'income', 'purchase_amount']])
epsilon = 5.0 
def add_noise(data, epsilon):
    sensitivity = np.max(data) - np.min(data)
    noise = np.random.laplace(0, sensitivity / epsilon, data.shape)
    return data + noise
noisy_data = anonymized_data.copy()
noisy_data[['age', 'income', 'purchase_amount']] = add_noise(anonymized_data[['age', 'income', 'purchase_amount']].values, epsilon)
noisy_data[['age', 'income', 'purchase_amount']] = scaler.inverse_transform(noisy_data[['age', 'income', 'purchase_amount']])
print("Noisy Data: \n", noisy_data)
average_purchase = noisy_data['purchase_amount'].mean() 

我们可以使用以下绘图函数查看这些数据变换的结果,比较原始、匿名化和噪声数据,以突出差分隐私如何模糊个体数据点,同时仍然保持一般数据趋势:

def plot_data_with_trend_lines(original_data, anonymized_data, noisy_data):
    fig, ax = plt.subplots(1, 3, figsize=(18, 6))
    ax[0].scatter(original_data['age'], original_data['purchase_amount'], color='blue')
    z = np.polyfit(original_data['age'], original_data['purchase_amount'], 1)
    p = np.poly1d(z)
    ax[0].plot(original_data['age'], p(original_data['age']), "r--")
    ax[0].set_title('Original Data')
    ax[0].set_xlabel('Age')
    ax[0].set_ylabel('Purchase Amount')
    ax[1].scatter(anonymized_data['age'], anonymized_data['purchase_amount'], color='green')
    z = np.polyfit(anonymized_data['age'], anonymized_data['purchase_amount'], 1)
    p = np.poly1d(z)
    ax[1].plot(anonymized_data['age'], p(anonymized_data['age']), "r--")
    ax[1].set_title('Anonymized Data')
    ax[1].set_xlabel('Age')
    ax[1].set_ylabel('Purchase Amount')
    ax[2].scatter(noisy_data['age'], noisy_data['purchase_amount'], color='red')
    z = np.polyfit(noisy_data['age'], noisy_data['purchase_amount'], 1)
    p = np.poly1d(z)
    ax[2].plot(noisy_data['age'], p(noisy_data['age']), "r--")
    ax[2].set_title('Noisy Data with Differential Privacy')
    ax[2].set_xlabel('Age')
    ax[2].set_ylabel('Purchase Amount')
    plt.tight_layout()
    plt.show()
plot_data_with_trend_lines(customer_data, anonymized_data, noisy_data) 

然后,我们得到以下图表:

图片

图 13.5:差分隐私对客户购买数据影响的说明

如第三幅图所示,应用差分隐私后,数据点存在显著扭曲,但尽管有噪声,整体趋势仍然可以辨认。

需要注意的是,隐私和效用之间存在权衡。一般来说,随着隐私的增加,数据效用会降低。然而,这种差分隐私技术有效地掩盖了个体数据点,同时增强了隐私性,并且仍然保留了整体趋势。这种平衡对于营销应用至关重要,在这些应用中,在保护消费者个人数据的同时保持有意义的见解是必不可少的。

管理和合规性

在维护监管合规的同时遵守适当的治理实践至关重要。在本节中,我们将探讨与这些主题相关的许多方面,包括知识产权保护和构建道德治理框架的关键组成部分。

然后,我们将探讨一些关于数据使用和处理的关键监管合规考虑因素,突出关键框架如 GDPR 和 CCPA,以及简要提及其他全球法规和行业特定指南。

知识产权保护

人工智能模型依赖于大量数据,这些数据通常包括专有内容甚至受版权保护的内容。确保保护你组织和其他组织的知识产权和版权权利对于避免在人工智能模型开发和部署中的法律问题至关重要。在以下子节中,我们将讨论数据和模型许可及归属、内部数据所有权和安全、数据管理和收集实践的关键方面。这些主题共同解决了在人工智能应用中使用数据的道德来源、管理和保护的需求,以保持符合知识产权法律。

数据和模型许可及归属

当从第三方获取数据用于人工智能和机器学习应用时,建立明确的许可协议以概述允许的使用至关重要。这对于可能包含受版权保护材料(如图像、视频和文本)的训练数据集尤为重要。不遵循这些指南可能导致诉讼,例如,当股票照片提供商 Getty Images 在 2023 年起诉 Stability AI,指控其使用超过 1200 万张其受版权保护的图像来训练其图像生成系统时。据 Getty 表示,一些图像高度相似,甚至一些输出还包括了其 Getty Images 水印的修改版本。公开可用数据的道德来源在解决这个问题中也起着重要作用。然而,尽管公开数据集具有成本效益且易于获取,但它们可能仍然包含受版权保护或敏感材料。例如,从 GitHub 或公共数据库等公开平台获取的数据集可能包括受版权保护的代码片段或敏感个人信息。必须进行尽职调查,以验证公开数据集是否符合知识产权法律及其开放许可条款,例如仅限于研究应用的使用。

内部数据所有权和安全

组织通常可以访问专有消费者数据,如购买历史或行为洞察,这对于制定有效的营销策略非常重要。然而,最近的数据泄露事件突出了保护这些信息的重要性。为确保这些数据免受滥用或未经授权的访问,必须在组织内部明确界定所有权和访问权。例如,一个突出数据安全重要性的近期例子是 2023 年 T-Mobile 的数据泄露事件。

这起事件涉及两个独立的安全漏洞:员工数据的泄露,包括电子邮件地址和部分社会保险号码,以及一个系统错误,暴露了客户支付数据。这样的违规行为突显了实施严格的权限和高级安全措施(如加密和多因素认证)以保护敏感信息的必要性。例如,营销团队可能使用加密来确保客户数据在传输和静止状态下都得到保护,即使数据被拦截或未经授权访问,也保持不可读。

数据管理和收集实践

作为一般规则,营销人员应采用数据最小化实践,只收集实现特定营销目标所需的数据。这通常涉及利用抽样技术收集整个数据集的代表性子集。通过分析这个较小但具有统计意义的样本,营销人员可以获取准确的见解,而无需从整个群体中收集数据。这减少了大规模数据泄露的风险,并促进了符合隐私法规(如本章后面将要讨论的 GDPR 和 CCPA)的合规性。

通过将数据收集限制在明确定义的目的上,组织还可以减少其面临潜在数据滥用的风险。任何收集的数据都应仅用于声明的目的,如果以后确定了额外的用途,则应从消费者那里获得明确的同意。例如,如果营销团队最初收集数据用于定向电子邮件活动,那么如果他们以后希望将此数据用于不同的、无关的营销活动,他们应寻求进一步的同意。消费者应清楚地了解收集了哪些数据,如何使用这些数据,以及他们关于数据控制的权利。实现这一目标的一种方式是通过隐私政策,这些政策清楚地传达了收集的数据、使用方式以及分享信息以实现个性化营销的好处。隐私政策应易于使用和理解,提供清晰的同意和退出机制。例如,公司的隐私政策可能解释说,从网站互动中收集的数据将用于个性化产品推荐,但用户可以选择退出,如果他们不希望以这种方式使用他们的数据。

道德治理框架

建立一个道德治理框架对于在营销中使用人工智能的组织来说可能非常有价值。这个框架包括创建内部结构和政策,以指导人工智能技术的负责任使用。为了有效,这个框架必须清楚地传达给所有与人工智能技术合作的员工,并在组织的每个层面得到接受,包括公司的资深领导团队。

通过组建内部 AI 伦理委员会、制定全面的 AI 政策和指南,以及在员工中培养持续培训和意识,组织可以主动应对伦理困境,并在成为问题之前在其 AI 应用中促进透明度和公平性。

内部 AI 伦理委员会

组建由多元成员组成的内部 AI 伦理委员会,使组织能够从多个角度评估 AI 营销策略。这些委员会可能包括伦理学家、律师、工程师和商业策略师。例如,伦理学家可以提供对复杂道德问题的见解,而工程师可以阐明技术细节。商业策略师帮助评估运营风险。

然而,这些委员会在保证透明度和公平性方面的有效性并不保证,并且对于这些委员会来说,拥有明确的授权和影响决策的权力至关重要,以确保它们真正能够影响伦理风险。虽然小型公司可能缺乏建立正式委员会的资源,但它们在 AI 实践中优先考虑伦理考量仍然至关重要,可能通过指定一名或一小队负责人来监督这些问题。

AI 政策发展和报告

制定清晰的 AI 政策和指南为负责任的全公司营销实践提供了一个基础框架。这些指南应涵盖数据使用、算法公平性、模型审计以及针对特定消费者群体的伦理影响。

例如,一个使用 AI 模型进行个性化广告营销的营销团队应该记录用于训练的数据集、应用于数据的任何预处理技术以及用于构建模型的算法。这份文档还应概述已知的局限性、偏见和潜在风险,例如模型倾向于偏袒某些人口统计群体。

从营销人员的角度来看,一旦确定了这些局限性和偏见,它们可以通过调整营销策略来解决。这可能涉及重新评估目标受众以促进更多样化的代表性,创造更具包容性的信息,这些信息能够与更广泛的受众产生共鸣,并持续监控活动表现以识别和纠正任何新兴的偏见。定期的合规审计和透明的报告对于跟踪遵守法规和确定改进领域至关重要。例如,审计可能审查消费者数据的存储和访问方式,确保实施了加密和访问控制措施。

持续培训和意识

对营销团队进行 AI 伦理、数据治理和新兴法规的教育,确保所有利益相关者了解他们的责任。持续的培训计划使团队能够识别道德困境并做出明智的决定,促进合规和道德行为的氛围。定期更新的培训课程还可以使员工了解最新的法规变化和最佳实践,确保道德考量融入日常营销活动中。

法规合规

遵守国际、国家和行业特定的法规对于确保数据隐私和道德标准得到维护、培养消费者信任以及避免法律后果至关重要。在本节中,我们将探讨关键的法规框架,例如 GDPR 和 CCPA,以及一些全球法规和行业特定指南,以更好地理解影响 AI 赋能营销的法规环境。

一般数据保护条例(GDPR)

GDPR 是一项全面的数据隐私法,主要影响欧盟公民,对个人数据的收集、存储和处理实施严格的规则。以下是其一些关键特性:

  • 营销人员必须确保数据收集的透明度,提供关于正在收集哪些数据以及为何收集的清晰和简洁信息。

  • 消费者必须被赋予对其数据的明确控制权,包括访问、更正和删除其信息的能力。

  • GDPR 要求实施安全的数据处理实践,以保护个人数据免受泄露和未经授权的访问。这包括实施适当的技术和组织措施,如加密和定期的安全审计。

  • GDPR 还规范了自动化决策过程。如果 AI 系统做出的决策对个人有重大影响,例如通过画像或个性化营销,必须制定人类干预的条款,并提供关于这些决策是如何做出的有意义的解释。

    熟悉 GDPR 以用于营销

    如需有关 GDPR 指南及其对营销实践影响的更详细信息,请访问官方 GDPR 网站(gdpr-info.eu/)。

对于营销专业人士来说,GDPR 第三章第 12 至 23 条特别有趣,这些条款描述了数据主体的权利。以下是从 GDPR 网站上的截图,突出了本章涵盖的关键主题:

图片

图 13.6:GDPR 第三章(https://gdpr-info.eu/chapter-3/)涵盖数据主体的权利

如果受 GDPR 管辖,您的公司必须了解这些法规的法律影响,并以一种允许完全遵守的方式开展活动。

加利福尼亚消费者隐私法案(CCPA)

在讨论 GDPR 之后,了解 CCPA 至关重要,它为加州的数据隐私提供了一个强大的框架。虽然 CCPA 仅针对加州,鉴于美国缺乏全面的联邦命令,加州经常充当潮流引领者。加州是第一个实施全面数据隐私立法的州,自那时起,十几个其他州也实施了全面数据隐私法。以下是一些关键的 CCPA 要求:

  • CCPA 赋予加州居民对其个人数据的特定权利,包括了解关于他们的个人数据正在被收集的内容、其用途以及披露给谁的权利。它还对企业收集和处理此类数据施加义务,并且它们必须提供明确且易于获取的隐私通知,详细说明这些方面。

  • 消费者有权访问其个人数据,请求其删除,并选择退出其个人信息的销售。例如,一家营销公司必须在其网站上包含一个易于访问的“不要出售我的个人信息”链接,允许消费者退出数据销售。

  • 除了这些权利外,CCPA 要求企业实施合理的安保措施,以保护消费者数据免受泄露和未经授权的访问。公司必须确保其数据处理实践符合这些要求,以避免巨额罚款和法律诉讼。

  • CCPA 还规定,企业必须在特定时间段内对经验证的消费者请求做出回应,确保个人能够有效行使他们的权利。

    遵守 CCPA

    有关 CCPA 合规性及其对营销实践的影响的详细信息,请访问官方 CCPA 网站(oag.ca.gov/privacy/ccpa)。

以下截图提供了加州消费者在 CCPA 下授予的权利的详细概述:

图片

图 13.7:加州消费者在 CCPA 下的隐私权概览(https://oag.ca.gov/privacy/ccpa#sectiona)

全球法规和标准

随着全球对数据隐私的关注日益增长,各国都制定了各自的法规来保护个人数据。在国际上运营的营销人员必须了解这些区域差异,并实施符合各种法规的全球数据策略。以下是一些主要国家和它们各自的数据法规:

  • 加拿大:个人信息保护与电子文件法案规范了私营部门组织在商业活动中收集、使用和披露个人信息的做法。更多详情,请访问加拿大隐私专员办公室网站 (www.priv.gc.ca/en/privacy-topics/privacy-laws-in-canada/the-personal-information-protection-and-electronic-documents-act-pipeda/)。

  • 巴西:通用个人数据保护法建立了类似于 GDPR 的全面数据保护规则,重点关注透明度、消费者权利和安全措施。更多详情可以在国家数据保护局网站上找到 (www.gov.br/anpd/en)。

  • 日本:个人信息保护法规范了日本个人数据的处理,强调保护个人权利和数据控制者的责任。更多信息,请查看个人信息保护委员会(PPC)网站 (www.ppc.go.jp/en/)。

  • 南非:个人信息保护法规定了合法处理个人信息的条件,以保护个人免受伤害并确保其隐私。更多详情可以在信息监管机构网站上找到 (www.justice.gov.za/inforeg)。

行业特定指南

除了政府法规外,各个行业还制定了针对数据使用的特定伦理标准和指南,以应对其独特的挑战和责任。根据其行业,营销人员应保持对这些要求的更新,以确保符合行业规范:

  • 医疗保健:美国的健康保险可携带性和问责法案(HIPAA)为保护患者健康信息设定了严格的标准。医疗保健行业的营销人员必须确保任何患者数据的用途都符合 HIPAA 的隐私和安全规则。更多信息可以在美国卫生与公众服务部网站上找到 (www.hhs.gov/hipaa/index.html)。

  • 金融金融行业监管机构(FINRA)为金融行业的数据使用提供指南,重点关注隐私和敏感金融信息的保护。遵守这些指南有助于防止数据泄露并维护消费者信任。更多详情,请访问 FINRA 网站 (www.finra.org/rules-guidance/key-topics/customer-information-protection)。

  • 教育家庭教育权利和隐私法案(FERPA)保护学生教育记录的隐私。与这些机构合作的教育机构和营销人员必须确保学生数据的使用符合 FERPA 的规定。更多信息可以在美国教育部网站(www2.ed.gov/policy/gen/guid/fpco/ferpa/index.html)上找到。

  • 零售业:支付卡行业数据安全标准为处理和保障信用卡信息提供了指导方针。零售商和营销人员应遵守这些标准以防止欺诈和数据泄露。更多详情,请访问 PCI 安全标准委员会网站(www.pcisecuritystandards.org/standards/pci-dss/)。

摘要

在本章的最后一章中,我们讨论了 AI 赋能营销中的伦理和治理的关键考虑因素和挑战。我们探讨了数据隐私、算法偏差以及模型透明度的必要性,强调这些因素如何直接影响消费者信任和品牌完整性。我们还考察了关键监管框架,如 GDPR 和 CCPA,并讨论了合规性在减轻法律风险和促进负责任的 AI 实践中的重要性。

我们讨论了确保营销中道德 AI 部署的实用策略,包括模型可解释性、偏差缓解以及平衡隐私与个性化的方法。通过建立强大的治理框架,包括成立内部 AI 伦理委员会、制定明确的 AI 政策以及培养持续培训和意识,组织可以有效地应对复杂的伦理景观。理解和遵守行业特定指南和全球数据法规对于维护合规性和保护不同地区的消费者权利至关重要。

随着我们探索营销中的 AI 和 ML 的结束,很明显,未来充满了创新和增长的巨大潜力。然而,随着这种潜力的到来,我们也有责任以道德和透明的方式实施这些技术。通过整合本章中讨论的见解和策略,您可以确保您的 AI 应用不仅有效,而且符合最高的道德标准。

以自信和创造力接受这些挑战,并在应用本书中涵盖的概念时,请记住,持续学习和适应是保持领先的关键。祝您未来之路好运!

加入我们书籍的 Discord 空间

加入我们的 Discord 社区,与志同道合的人见面,并在以下地点与超过 5000 名成员一起学习:

packt.link/genai

packt.com

订阅我们的在线数字图书馆,全面访问超过 7,000 本书籍和视频,以及领先的行业工具,帮助您规划个人发展和职业进步。更多信息,请访问我们的网站。

为什么订阅?

  • 使用来自 4,000 多名行业专业人士的实用电子书和视频,节省学习时间,增加编码时间

  • 通过为您量身定制的技能计划提高学习效果

  • 每月免费获得一本电子书或视频

  • 完全可搜索,便于快速访问关键信息

  • 复制粘贴、打印和收藏内容

www.packt.com,您还可以阅读一系列免费技术文章,订阅各种免费通讯,并享受 Packt 书籍和电子书的独家折扣和优惠。

您可能还喜欢的其他书籍

如果您喜欢这本书,您可能对 Packt 出版的以下其他书籍感兴趣:

《使用 LangChain 的生成式 AI

本·奥法特

ISBN: 978-1-83508-346-8

  • 理解 LLM,它们的优点和局限性

  • 掌握生成式 AI 的基本原理和行业趋势

  • 使用 LangChain 创建 LLM 应用程序,如问答系统和聊天机器人

  • 理解 Transformer 模型和注意力机制

  • 使用 pandas 和 Python 自动化数据分析可视化

  • 掌握提示工程以提升性能

  • 微调 LLM 并了解释放其力量的工具

  • 使用 LangChain 部署 LLM 作为服务并应用评估策略

  • 使用开源 LLM 私下交互文档,以防止数据泄露

构建由 LLM 驱动的应用程序

瓦伦蒂娜·阿尔托

ISBN: 978-1-83546-231-7

  • 探索 LLM 架构的核心组件,包括编码器-解码器块和嵌入

  • 了解 LLM 的独特功能,如 GPT-3.5/4、Llama 2 和 Falcon LLM

  • 使用 AI 编排器如 LangChain,配合 Streamlit 进行前端开发

  • 熟悉 LLM 组件,如内存、提示和工具

  • 学习如何使用非参数知识和向量数据库

  • 理解 LFMs 对 AI 研究和行业应用的影响

  • 通过微调自定义您的 LLM

  • 了解由 LLM 驱动的应用的伦理影响

《自然语言处理和计算机视觉中的 Transformer – 第三版

丹尼斯·罗思曼

ISBN: 978-1-80512-872-4

  • 分析并理解原始 Transformer、BERT、GPT 模型、T5、PaLM、ViT、CLIP 和 DALL-E 的架构

  • 微调 BERT、GPT 和 PaLM 2 模型

  • 了解不同的标记化器以及预处理语言数据的最佳实践

  • 从零开始预训练 RoBERTa 模型

  • 实施检索增强生成和基于规则的基,以减轻幻觉

  • 使用 BertViz、LIME 和 SHAP 可视化转换器模型活动,以获得更深入的见解

  • 深入了解视觉转换器,使用 CLIP、DALL-E 2、DALL-E 3 和 GPT-4V

Packt 正在寻找像你这样的作者

如果你有兴趣成为 Packt 的作者,请访问authors.packtpub.com并今天申请。我们已经与成千上万的开发者和技术专业人士合作,就像你一样,帮助他们将见解与全球科技社区分享。你可以提交一般申请,申请我们正在招募作者的特定热门话题,或者提交你自己的想法。

分享你的想法

现在你已经完成了《机器学习与营销生成 AI》,我们很乐意听听你的想法!如果你在亚马逊购买了这本书,请点击此处直接进入该书的亚马逊评论页面并分享你的反馈或在该购买网站上留下评论。

你的评论对我们和科技社区都很重要,并将帮助我们确保我们提供高质量的内容。

posted @ 2025-09-04 14:14  绝不原创的飞龙  阅读(16)  评论(0)    收藏  举报