数据科学家的商业策略:品牌评估
Photo by Nik Shuliahin on Unsplash
学习如何评估品牌和其他无形资产
在商业世界里,有有形资产和无形资产。像车辆和工厂这样的有形资产很容易估价——我们可以看到和触摸到它们,它们(被企业)用来产生可测量的现金流,我们可以用这些现金流来估计它的合理价格。
像品牌这样的无形资产——本刊关注的焦点——更难估价。我们看不见也摸不着它们。而且它们不会直接产生我们可以用来评估它们的任何现金流或有形收益。但在很多情况下,品牌就是业务——业务只能产生一定水平的利润,因为它有品牌。
因此,考虑到品牌可以而且经常是企业价值的主要驱动力,能够估计其价值就变得相当重要。例如:
- 投资者需要知道一个品牌值多少钱,这样他们才能判断一只股票的价值是过高还是过低。
- 数据科学家和分析师应该知道使品牌更有价值和更强大的关键杠杆,以及这对他们公司的影响。
我们如何测量无法直接观察到的东西?
鉴于品牌是无形的,我们如何衡量它们的价值?让我们集思广益,找出几个可能的解决方案:
- 我们可以估算一下一家新公司从零开始创建一个同等质量的品牌需要多少成本。
- 我们可以比较一个行业内品牌强势和品牌弱势公司的财务和股票表现。
- 我们可以对品牌如何改进的关键指标进行第一原则分解,如客户终身价值(CLTV)和客户获取成本(CAC)。****
注意每一个都包含了很多不确定性。不幸的是,对于一般的商业价值评估,尤其是品牌价值评估,没有快速的方法来得出合理的答案。相反,我们需要深入调查业务,以便我们了解品牌价值的关键驱动因素,然后让我们对品牌价值的估计进行三角分析。
为什么要有品牌?
在我们研究上面提到的 3 种方法之前,让我们先快速回顾一下公司试图用他们的品牌实现的商业目标。
优质图像
在一个企业投资一个品牌的所有原因中,这可能是最广为人知和研究得最多的。奢侈或优质品牌允许公司以更高的价格销售其产品,因为产品的稀缺性以及它所赋予的“地位”(苹果、蒂芙尼&公司、路易威登)。
注意,溢价不一定意味着奢侈。这也可能意味着在质量和价格(好市多)或可靠性和安全性(沃尔沃)或一致性(In-N-Out Burger)之间进行良好的权衡。
熟悉和情感联系
公司投资品牌的另一个原因是将自己与商品市场上的竞争对手区分开来(在商品市场上,每个公司的产品之间没有真正的差异)。这通常更难做到,因为每个公司都试图利用其品牌和营销来与潜在客户建立情感联系。而它建立这种联系的能力几乎与实际产品无关(壳牌的天然气和雪佛龙的天然气是一样的),一切都与它的营销头脑(加上运气)有关。但如果它能像麦当劳或星巴克那样成功做到这一点,就能大大增加对其产品的需求。这是因为面对非常相似的选择,消费者会选择最熟悉或让他们感觉最温暖和最模糊的东西(假设他们已经被有效地推销给了消费者)。
概述
因此,概括地说,公司试图通过品牌实现两件事情中的一件(或者两件都实现,如果他们执行得非常好的话)——优质的形象带来更高的价格,或者熟悉度和情感联系带来更高的销量。
dePhoto by 贝莉儿 DANIST on Unsplash
从头开始建造的成本
这可能是最容易估计的,但也是最没有帮助的。我们可以看看苹果、百事、宝马、路易威登等公司有多喜欢。每年在营销上的花费。我们可能希望按比例增加年度美元金额,以反映我们从零开始的事实(而我刚才提到的那些公司正在花钱维护和加强已经建立的品牌)。但是有两个问题。
****旁注:如果你分析的公司是一家折扣店,其品牌显示低价,那么你应该考虑包括与维持低价相关的费用(折扣、促销、买一送一等。).类似地,如果一家公司的品牌是围绕技术创新建立的,那么你会希望至少包括一些年度研发支出。通常,维护一个品牌的成本并不仅仅停留在公司损益表的营销行上。
皱纹 1
就像花大量的钱来推广和营销一部电影并不能保证成功一样,增加公司的营销预算并不意味着你一定会有一个强大的品牌。
即使有巨大的营销预算,仍然有机会和运气(和执行)的成分。尽管我们花了很多钱,但顾客可能不会认同我们的品牌或信息。如果花 200 亿美元能保证你拥有苹果的品牌,那么标准普尔 500 一半的公司都会这么做。
因此,如果我们决定用成本来估计品牌价值,就需要考虑这种不确定性。最明显的方法是估计成功的概率,并根据该概率调整值。例如,如果您决定从头开始打造品牌需要 50 亿美元,而您成功的几率为 50%,那么您对品牌价值的估计为 5B/0.5 = 100 亿美元。
皱纹 2
第二个问题是,我们只关注事物的成本方面,这可能会有问题。例如,如果行业中的所有参与者都高估了拥有一个强大品牌的优势,他们最终都会超支。这将导致我们基于成本的估价被高估。品牌的价值取决于它所带来的优势。因此,任何忽视收益的估值尝试都很可能是离谱的。
Photo by Glenn Carstens-Peters on Unsplash
强势与弱势品牌比较
理想情况下,我们会发现(某个行业中)有强大品牌的公司和没有品牌的公司。然后,我们可以将它们的财务表现和市场资本(投资者愿意为其股票支付的总额)与较弱的同行进行比较。
例如,在奢侈品这样的行业,我们可以根据品牌实力对玩家进行排名,尽管带有一定的主观性。然后,我们可以比较收入增长、利润率、投资资本回报率等。强势和弱势品牌。
放眼整个行业也很有帮助。一些更有趣的分析可能来自于将能源这样的大宗商品产业(实际上要么没有品牌,要么很弱)与奢侈品这样的品牌驱动型产业进行比较。
如果我们想以这种方式评估一个品牌,我们可以考虑使用一个统计模型。线性回归是我想到的一个问题,其中我们的 Y 变量是我们每家公司的市值,我们的 X 变量是我们想要控制的所有因素,加上一个分类变量来判断公司是否拥有一个强大的品牌。应注意控制哪些因素。感兴趣的参数是分类变量上的β系数,表示公司是否有一个强大的品牌。这个特定的回归测试版告诉我们,在其他条件相同的情况下,投资者对一个拥有强大品牌的公司比对没有品牌的公司更有价值。****
但在这里我们必须小心。只有在所有其他因素保持不变的情况下,β值才是准确的。但是,如果我们把一个强大品牌的存在所驱动的 X 个变量包括在内,那么我们就不能再以表面价值来衡量测试版了。
例如,假设我们发现贝塔系数是 50 亿美元。这意味着,在其他条件相同的情况下,投资者愿意为一家拥有强大品牌的公司多支付 50 亿美元。但是我们注意到我们的 X 变量之一是年销售额。假设一个强大的品牌可以推动更高的年销售额是非常合理的(毕竟这是拥有品牌的一个要点)。但这意味着我们再也不能说“所有其他事情都是平等的”。相反,归属于强势品牌的一些价值(强势品牌分类变量的β值)很可能已经泄露给年度销售变量的β值以及受品牌影响的任何其他变量。这将导致回归低估我们品牌的价值。解决这个问题的一个方法是通过在我们的回归中包含相互作用项来明确考虑相互作用的影响。
通过建立这样一个模型,我们可以学到很多东西。所以我们也可以在以后的文章中构建它。我一直想写一篇“理解线性回归”的文章。所以我们将把细节留到以后再说。
基本原则评估
这是我的首选方法。这比只关注成本更不容易出错,也比我之前建议的线性回归更直观和直接。
尽管如此,它需要我们估计许多事情。但使用第一原则方法的好处是,它迫使我们理解品牌和业务是如何相互作用的。
在早先的一篇文章中,我们介绍了两个关键指标:客户终身价值(CLTV)和客户获取成本(T3)。这一部分应该相当明显——一个强大的品牌应该:
- ****通过提高客户支出或增强客户忠诚度来增加 CLTV。一个强大的品牌应该带来更高的交易频率、更高的公司产品价格和更高的客户忠诚度(更长的平均客户寿命)。这些都会导致 CLTV 的增加。
- 增加 CAC——强大的品牌更容易吸引新客户。当你公司的品牌强大时,这本身就是一个广告,它极大地提高了市场对你的产品和服务的认知度。
随着你的品牌越来越强大,我们希望看到 CLTV 和 CAC 像下图这样发展:
The impact of a strong brand
像往常一样,棘手的部分是弄清楚这两个指标的改善有多少可以归因于强大的品牌。金额因企业和行业而异。
理想情况下,我们希望比较同一家公司在一个拥有强大品牌的世界和一个没有强大品牌的世界(其他一切或多或少相同)中 CLTV 和 CAC 的表现。但是一个品牌要么是,要么不是(这么哲学对吧?),所以实际上没办法做那个比较。因此,我们需要再次求助于调查方法:
- 列出品牌影响力从低到零的公司。这份名单是我们的控制组——我们对没有品牌的企业的最佳估计。
- 然后看看每个公司的 CLTV 和 CAC(如果你纯粹依靠公开的财务报表,那么你需要做一些估计,因为一些公司不直接公布这些数字)。
- ****将我们公司的 CLTV 和 CAC 与我们对照组公司的平均 CLTV 和 CAC 进行比较。我们公司与对照组平均值之间的指标差异主要归因于我们的品牌。我们可能希望缩小计算出的差异,因为其中一些可能归因于更好的执行或更严格的支出纪律。
- 最后,一旦我们对每个客户的品牌收益有了一个估计,我们就可以用我们公司拥有的客户数量乘以。****
直到下次
品牌估值没有 100%正确的答案。这绝对是一门不精确的科学。让我们面对现实吧,试图过于精确没有任何好处——估计我们的品牌价值 180 亿美元和 200 亿美元之间的差异并不显著(也不值得为此失眠)。更重要的是了解品牌赋予我们业务的优势。
希望这是有帮助的,干杯!
更多数据科学与分析相关帖子由我:
但是我喜欢开源——为什么我需要一个人工智能平台?
企业投资人工智能平台的 10 个原因
构建一个机器学习 (ML)模型从未如此简单。几行 R 或 Python 代码就足够了,网上有大量的资源和教程甚至可以训练一个复杂的神经网络。最好的部分:这是你能想到的几乎每一个人工智能算法的情况,而人工智能研究的几乎每一个新进展通常都伴随着相应的开源实现。
然而,正如我之前在这篇文章中讨论的,人工智能不仅仅是建立模型。这个旅程实际上是从数据 收集、策划、探索、特征工程、模型训练、评估、最后是部署。
Hadoop 生态系统似乎是收集和聚合不同数据源的开源选择。Hive 和 HBase 符合访问、混合和匹配多个数据源的要求。现在,对于数据准备(即监管、探索和特征工程),Apache Spark 可以通过 SparkSQL 对大型数据集进行切片和切块,甚至利用内存处理来加快响应时间。Spark 还为您提供了自然语言处理 (NLP)功能和特征提取器,如主成分分析 (PCA)。但可能开源软件最强的一套是它的大量不同的人工智能模型。scikit-learn、R、SparkML、TensorFlow、Keras 和 PyTorch 等等,提供了我和我的任何数据科学家伙伴们梦寐以求的一切。最后,像 Docker 和 Plumbr 这样的工具可以通过 HTTP 请求以 web 服务的形式简化机器学习模型的部署。
等等……这是否意味着人们可以仅仅使用开源堆栈来构建一个企业级的端到端人工智能系统?不完全是。
这可能是构建概念验证 (POC)的情况。回到 2012 年,作为我论文的一部分,我纯粹在开源的保护伞下构建了一个人类活动识别系统(包括这个手机 app)——谢谢 Java、Weka、Android 和 PostgreSQL!然而,对于企业来说,情况却大不相同。
别误会我的意思。我不仅是一个超级粉丝,也是开源软件的狂热用户,我确实意识到有这么多神奇的工具;但同时也有不少差距。我来分享一些企业投资 AI 平台的原因。让我告诉你一些我作为一个人工智能和人工智能从业者最痛苦的时刻。
1。开源集成、启动和运行以及版本更新
上次我试图在我的机器上安装 TensorFlow,它破坏了我的 Apache Spark 配置。几分钟后,当我认为我已经修复火花,我意识到张量流是烤面包。又来了!
长话短说:我花了整整一个下午的时间让这两只野兽跑起来。想象一下,当这么多其他工具需要共存于一个数据科学家的工作环境中时,会有多少事情出错:Jupyter、R、Python、XGboost、Hadoop、Spark、TensorFlow、Keras、PyTorch、Docker、Plumbr 等等。现在考虑一下,所有这些工具每隔一个月都会有新的发布,因此需要频繁的更新。有人说冲突吗?啊!让一个平台来帮我处理这件事。
2。协作
现在我和我的三人数据科学家团队一起工作。我们正在使用我们最喜欢的 Jupyter+Python+Spark+tensor flow 环境,并决定创建一个 GitHub 存储库来共享我们的代码和数据资产。但是我在我的环境中使用定制的软件包——这花了我一段时间来安装和配置——我的同事无法访问它们。他们将不得不经历和我一样的痛苦,在他们自己的机器上安装软件包。好吧,但是,我们如何共享我们部署的模型?创建 Docker 图像或 PMML 文件听起来一点也不性感!分享我们的预测、实验和评估(混淆矩阵、ROC 曲线、RMS 等)怎么样?)?啊!让平台为我处理这件事。
3.数据虚拟化
企业中最常见的挑战之一是数据集分散在多个系统中。一个典型的解决方案是将数据复制到中央数据存储中——那里有您的数据湖— 用于运行您喜欢的分析。然而,这种方法显然成本高且容易出错。
数据虚拟化允许跨多个系统查询数据,无需任何复制,简化了数据收集流程。
开源软件没有提供数据虚拟化解决方案。因此,让平台为我们处理这个问题。
4。治理和安全
这是企业关心的一个关键问题,也是开源留下巨大空白的一个领域。资产需要治理,我指的不仅仅是数据,还有代码、模型、预测、环境和实验!所有数据科学家都应该知道批准/拒绝向客户贷款的标准吗?或者哪些因素导致将交易标记为潜在欺诈?肯定不是!限制每个用户的资源利用率怎么样?让平台为我们处理这些。
5。模型管理、部署和再培训。
如果一个质量完美的人工智能模型只放在我的笔记本电脑上,它有什么用?一个模型是没有用的,除非它作为服务运行,提供预测并被最终用户消费。
在这篇文章中,我描述了如何为 Github 工作项目构建一个自动完成系统——换句话说,预测团队、受托人等。·给定一个工作项标题作为自由文本。建立模型(包括数据准备)花了我将近两周的时间。但是部署花了我的同事一个多月的时间,不得不创建模型的 docker 图像,以便稍后使用 plumbr 来连接东西。每当我创建一个新的模型时,我还想再经历一次吗?不了,谢谢你!那么如何跟踪不同的模型版本呢?还是关于各款车型性能的统计?如何检测模型退化?或者时常自动化整个再培训过程,以确保模型是最新的?让平台给我做!
6.偏差检测和校正
想象一下,一位数据科学家使用性别或年龄作为信用风险的预测指标。而且,生成的模型是给某个性别分配更高的风险。这不仅不道德,而且在大多数司法管辖区也是非法的。如何检测一个模特是否有性别偏见?如果是这样,如何在不必重建模型的情况下纠正这种偏差?点击了解更多关于偏置检测和校正的信息。再来,让平台给我做!
7。辅助数据管理
我的一个同事经常和我开玩笑,公然告诉我,鉴于我花了很多时间清理数据,我实际上不是一名数据科学家,而是一名数据管理员。
遗憾的是,他指出,在数据科学项目中,高达 80%的时间和精力经常用于数据管理和准备。让我们面对现实吧,来自开源的数据监管工具,包括 Spark,都涉及到繁重的编码工作,这可能非常乏味。但是,如果有一个可视化工具可以清理和提炼多个数据源而无需编写一行代码,那会怎么样呢?是的,让平台给我做吧!
8。GPU
在过去的十年中,计算能力有了巨大的提高,图形处理单元有了显著的进步。这对深度学习算法尤其有利。现在,配置 TensorFlow/Keras 等框架以获得最佳性能本身就是一个项目,需要的技术知识并不具备典型数据科学家的背景,包括我自己。再一次,让平台为我处理那件事!
9。可视化建模
许多统计学家、数据分析师甚至经理可能对构建机器学习模型感兴趣,尽管他们不精通 Python 和 r 等语言的编码。几十年来, SPSS 等工具一直在为 ML 和 AI 提供可视化接口,现在可以在云上利用这些接口。换句话说:
拖放您的数据集,然后是您喜欢的数据准备和建模算法,最后部署您的模型,而无需编写任何代码。
当谈到可视化建模时,开源中也有一个空白,因此,让平台为我提供它。
10。自动化人工智能
我们作为数据科学家的角色有一个很大的机械组成部分,即反复尝试不同的算法、超参数、特征组合等。但是,如果我们让它自动化,包括实验,也就是说,交叉验证、混淆矩阵、 ROC 曲线、精确回忆曲线等等,会怎么样呢?哦是的,请让平台为我做那件事!
在寻求一个利用开源但填补上述所有空白的人工智能平台吗?免费试用 沃森工作室 !
对全面的数据和人工智能解决方案感兴趣?看一下 IBM Cloud Pak 获取数据 。
关于作者
scar D. Lara Yejas 是高级数据科学家,也是 IBM 机器学习中心的创始成员之一。他与世界上一些最大的企业密切合作,将人工智能和人工智能应用到他们的特定用例中,包括医疗保健、金融、制造、政府和零售。他还为 IBM 大数据产品组合做出了贡献,特别是在大规模机器学习领域,是 Apache Spark 和 Apache SystemML 的贡献者。
scar 拥有南佛罗里达大学的计算机科学和工程博士学位。他是《人类活动识别:使用可穿戴传感器和智能手机》一书的作者,也是大量关于大数据、机器学习、以人为中心的传感和组合优化的研究/技术论文的作者。
但是,AI 到底是什么?
复杂问题的简单答案
多年来,人们认为计算机是执行数学运算的速度比人快得多的机器。它们最初被视为计算机器,就像被美化了的计算器。早期的科学家认为计算机永远无法模拟人脑。然后,科学家、研究人员和(可能是最重要的)科幻小说作者开始问“或者可能吗?”解决这个问题的最大障碍归结为一个主要问题:人类的大脑可以做科学家无法理解的事情,更不用说近似了。例如,我们如何为这些任务编写算法:
- 一首歌出现在收音机里,大多数音乐听众能很快辨认出流派,也许是艺术家,也许是歌曲。
- 一个艺术评论家看到了一幅他从未见过的画,但他很可能识别出时代、媒介,甚至可能是艺术家。
- 婴儿在很小的时候就能认出妈妈的脸。
简单的回答就是你不能为这些写算法。算法使用数学。完成这些任务的人无法从数学上解释他们如何得出这些结论。他们能够取得这些成绩是因为随着时间的推移,他们学会了做这些事情。人工智能和机器学习是为了在计算机上模拟人类学习而设计的。
人工智能(AI)和机器学习(ML)这两个术语从 20 世纪 50 年代就开始使用了。当时,它被视为计算机科学的未来理论部分。现在,由于计算能力的增加和对算法的广泛研究,人工智能现在是一个可行的现实。以至于我们每天使用的许多产品都内置了一些变异的人工智能(Siri、Alexa、Snapchat 面部过滤器、手机/耳机的背景噪音过滤等……)。但是这些术语是什么意思呢?
简单来说,AI 的意思是给机器编程,让它像人一样行动。一开始,研究人员开发算法试图接近人类的直觉。查看这段代码的一种方法是用一个巨大的 if/else 语句来确定答案。例如,这里有一些这个时代的聊天机器人的伪代码:
if(input.contains('hello'))
response='how are you'
else if (input.contains('problem'))
response = 'how can we help with your problem?')
...
print(response)
正如你所想象的,由于人类思维的复杂性,这被证明是一种非常低效的方法。这些规则非常僵化,随着时间的推移,随着情况的变化,很可能会过时。这就是军情六处介入的原因。这里的想法是,与其试图给机器编程来充当大脑,我们为什么不直接给它输入一堆数据,让它自己找出最佳算法?
ML 被证明是一个开创性的想法。以至于现在,研究人员和开发人员几乎可以互换使用术语 AI 和 ML。你会经常看到它被称为 AI/ML,这是我在本文的其余部分将使用的,但是,如果你遇到博士/数据科学家类型的人,要小心,因为他们无疑会纠正你。
在我们更进一步之前,我们需要考虑 AI/ML 的一个全局事实。输入数据总是数字。机器不能听音乐,不能读手写数字,也不能看视频。相反,这些必须用数字格式表示。以这个手写数字为例:
https://colah.github.io/posts/2014-10-Visualizing-MNIST/
左边是图像显示为图片时的样子。右边是它在计算机内部的实际视图。这些数字的范围在零(白色)和一(黑色)之间。这里的关键是,任何可以用数字表示的东西都可以用于 AI/ML,而且几乎任何东西都可以用数字表示。
AI/ML 的过程是创建一个模型,训练它,测试它,然后用新的数据推断结果。AI/ML 主要有三种学习类型。它们是监督学习、非监督学习和强化学习。我们来详细看看这些。
监督学习
在这种情况下,我们有输入数据,知道正确的“答案”是什么。可视化输入数据的一个简单方法是行和列的网格。至少有一列是“标签”,这是我们试图预测的值。其余的列是“特征”,是我们用来进行预测的值。这个过程就是不断地给我们的模型提供特性。对于每一行输入数据,我们的模型将提取特征并生成预测。在每一轮(“历元”)之后,模型会将其预测与标签进行比较,并确定准确性。然后,它将返回并更新其参数,以尝试为下一个时期生成更准确的预测。在监督学习中,有许多类型的模型和应用(预测分析、图像识别、语音识别、时间序列预测等)
无监督学习
在这种情况下,我们没有任何标签,所以我们能做的最好的事情就是试图找到相似的对象,并将它们分组到簇中。因此,无监督学习经常被称为“聚类”起初,这似乎不是很有用,但事实证明它在以下领域很有帮助:
- 客户细分——什么类型的客户正在购买我们的产品,我们如何针对每个细分市场定制营销
- 欺诈检测—假设大多数信用卡交易遵循相似的模式,我们可以识别不遵循该模式的交易,并调查这些交易是否存在欺诈。
- 医疗诊断——根据病史、生活方式、医疗读数等,不同的患者可能被分为不同的类别。如果一个病人脱离了这些聚类,我们可以进一步调查潜在的健康问题。
强化学习
在这里,没有“正确”的答案。我们试图做的是训练一个模型,使它能够以一种最终会产生最佳结果的方式做出反应。强化学习经常被用在电子游戏中。例如,我们可能想训练一个电脑化的乒乓球对手。对手将通过继续玩 pong 来学习,并在得分和赢得比赛等事情上获得正强化,在放弃分数和输掉比赛等事情上获得负强化。强化学习更有意义的应用是在自动驾驶汽车领域。我们可以训练一个模拟器在城市街道上行驶,当它做错事情(撞车,闯停车标志等)时惩罚它,并奖励它积极的结果(到达我们的目的地)。
结论
如果你是 AI/ML 的新手,希望这篇文章能帮助你对它背后的术语和科学有一个基本的了解。如果你是这些领域的专家,也许这篇文章会有助于向没有这方面经验的潜在客户解释。
但是什么是随机变量呢?
Coin toss from https://www.pexels.com
简介
通常简单的概念会因为术语和应用它们的上下文而变得难以理解。对我来说,随机变量就是这样一个令人困惑的方面(尽管事后看来很简单)。
对于软件工程师来说,变量有两种类型——局部变量和全局变量。当你写软件时,变量通常有一个范围和界限,但如果你给它们加上形容词*,这意味着它们可以有任何*值(尽管你仍然可以使用种子的概念来控制随机性)。**
对于一个密码学家来说,随机性是他/她的算法最重要的特性之一。他/她努力生成完全不应该重复的随机数。
从初等代数的角度来看,变量的概念是直截了当的,也就是说,它代表等式的输入,写在右边,也代表等式的输出,写在左边。随机方面通常不会出现或讨论到那个层次。
现在,如果你在维基百科或谷歌上阅读它的定义——什么是统计学中的随机变量?,您会看到这样的语句:
随机变量是将结果映射到真实值的函数。
实际上是函数的变量?
对于统计学家来说,这可能没问题,但对于来自其他学科(如软件工程)的人来说,这种说法开始严重破坏语义,因为它扰乱了他们对每天处理的 3 个非常基本的事情的理解——变量、函数和随机性!
显然,统计的随机变量是不同的生物,理解它们是使用它们和/或建立在它们之上的许多其他概念(高斯过程、贝叶斯统计等)的基础。
结果、样本空间和事件空间
随机变量在概率论中有其适用性,所以让我们先修改一下该领域的一些术语。
当你在观察一个现象或进行一个实验时,你会得到结果。通常给出的典型例子是-
- 扔硬币有两种可能的结果——正面或反面
- 掷骰子可能有 6 种结果——1、2、3、4、5 或 6
一个可能结果的列表(正式称为 集合 即列表中的项目不重复)称为一个 样本空间。
这意味着抛硬币的样本空间是{头,尾},掷骰子的样本空间是{1,2,3,4,5,6}。
这里的第二个重要术语叫做事件。什么是事件取决于你如何在你的样本空间中定义一个实验。****
考虑一个对应于投掷硬币两次的样本空间。可能的结果是{HH,HT,TH,TT}。现在,如果我对导致头先出现的结果感兴趣,那么我会将我的事件集描述为{HH,HT}。从这个事件的例子中,你应该开始看到一个事件实际上是样本空间的一个子集。
有一个符号用来代表样本空间**(即所有可能的结果),它是**ω****
类似地,对于事件空间**(即所有可能的事件)也有一个符号,它是 ∑**
另一个例子是为了更清楚。假设你正在掷骰子(ω= { 1,2,3,4,5,6} ),如果你的实验是观察甚至**的结果,那么事件空间将是— ∑ = {2,4,6}**
随机性和可变性
现在我们终于可以看到随机变量在所有这些中的位置,更重要的是,对应于随机性和可变性的部分。
随机性
你看,与你的实验相对应的事件有内在的不确定性(随机性)与之相关,也就是说,你在上面实验中的两次抛硬币可能是 HH 或 HT 或 TT 或 th。然后你用概率论来量化这些事件的不确定性。
我意识到归根结底这只是语义学,但我真的很喜欢不确定性这个词,因为它帮助我不把我对随机性的理解从其他学科带进来。这也意味着统计学中的随机变量 本来可以被 称为不确定变量。但是他们不这么叫:(……文献一直称它们为随机变量,所以如果有帮助的话,你可以(就像我经常做的那样)在你的脑海里翻译成不确定变量。
我将在文章的后半部分详细解释量化随机变量的不确定性。
可变性
在抛硬币实验中,我们在样本空间中使用了单词 HEAD & TAIL。相反,我们可以用数字来表示它们,比如我会用 1 表示头部,用 0 表示尾部。换句话说,我可以说我将头部映射到 1,尾部映射到 0。映射意味着执行这种转换的函数。回想一下你在维基百科或谷歌搜索中找到的早期定义— “随机变量是将结果映射到真实值的函数”。
你可能想知道为什么我选择把 1 赋给头部,0 赋给尾部…会不会是另一种方式,即 0 代表头部,1 代表尾部?。在许多方面,你可以自由分配(或者我应该说映射到)数值,但是正如你在更复杂的例子中看到的,这些映射有一定的意义和一致性,这主要取决于你对实验的定义。例如,即使对于一个简单的掷硬币的例子,我也可以通过将我的实验设定为“我对观察头的感兴趣”来证明 1 的分配是合理的。我会使用 1(=真),因为它表示这个实验定义的布尔逻辑。
为了不局限于布尔实验,我们来看另一个例子。这里我有两个抛硬币的例子,即ω= { HH,HT,TH,TT}** ,我对实验的定义是观察到的人头数。因此,我将定义我的(随机)变量来为{TT}生成(记住它是一个映射器/函数)0,为{TH} & {HT}生成 1,为{HH}生成 2。**
随机变量通常用大写字母表示。例如,对于上面的实验,我将把它写成 H = {0,1,2} 。
也就是说,样本空间(ω= { H,T})的结果到(实数)的映射看起来非常确定,即在映射(函数)方面没有随机性。这意味着不是“随机变量”的变量部分是随机的,而是它代表我们正在与具有与结果相关的不确定性(随机性)的样本空间一起工作。
如果你想知道——这只是简单地给样本空间中的结果分配一个数字,还是有更多的故事,那么你就在正确的道路上。事实上还有更多!
你看,给定样本空间的结果可以用来定义许多不同的实验。例如,这一次你将掷出两个骰子,这样如果它们不可区分(即你不关心哪个骰子产生哪个数字),那么可能的样本空间是ω= {(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(2,2,(2,3),(2,4),(3,3),(3,4),(3,4),(3,5),(3,5),(4,4),(4,5),(4,4)这里有 21 种可能的结果。从这里开始,我可以提出几个不同的实验,这些实验将导致它们各自的事件空间。一个实验可以是——两个骰子的和大于 8,另一个实验可以是——观察两个骰子的乘积何时为偶数,还有一个实验可以是——观察乘积减去 3 后的结果何时为偶数以及更多。****
这种使用样本空间的实验创建是随机变量开始使用其“函数”能力并将结果映射到实数的地方,这取决于你如何提出你的实验定义。
但为什么称之为变量呢?关于这一点,我想了很久,我能想到的最好的(应该说是唯一的)解释是,你的任务往往不是关于一个单一的样本空间。你的任务的最终结果可能取决于许多现象,它们有各自的样本空间。你将在这些样本空间上应用代数,因此你将结束加,减,乘的结果。因为你通常加/减/乘变量,而不是函数,所以他们最终称之为变量。
随机变量、事件空间和概率
随机变量的定义似乎暗示了与样本空间的强联系;毕竟,是一个 函数 将结果映射到实数,但现实是随机变量的应用与事件更相关。
你会意识到一个更有趣的方面是知道所有可能结果中的哪些事件已经发生,因此当你用随机变量做代数时,你实际上是在处理这些事件。
为了更加清晰,我们来看一个例子。在我们观察两次抛硬币的正面数量的例子中,我们定义了 H = {0,1,2}。这个集合中的每个元素对应一个事件。由于事件具有不确定性(随机性),我们利用概率论。我们通常说观察的概率
- 0 头是 p1
- 1 头是 p2
- 两个头是 p3
而且我们知道 p1 + p2 + p3 = 1。对此的另一种解释是,p1、p2 和 p3 正在量化与其各自事件相关的不确定性。
现在,当我们使用随机变量时,我们可以简单地写成
P(H=0) = p1,P(H=1) = p2,P(H=2) = p3
应该清楚的是,这里显示的事件和随机变量的输出范围(所有可能的值)之间有直接的对应关系。
这也意味着你所知道的概率计算的用法,即独立事件、联合事件、条件事件、求和规则、乘积规则等,也同样适用于随机变量。换句话说,你可以对独立或相关的随机变量和/或条件进行概率计算。
随机变量的类型
到目前为止,我们讨论的所有例子都只是一种称为离散随机变量的随机变量。这些变量(顾名思义)代表可以计算的结果。你可以数人头的数量,产品是 8 的次数,等等。
还有另一种类型的不确定现象是不可计数的,例如,如果我们正在处理一天中温度的实验和观察,那么你正在处理一个可以取无限多不同值的测量,因此实际上是不可计数的。然后使用连续随机变量来表示这些类型的随机/不确定现象。****
随机变量和概率分布
我们已经接触到了概率的关系,但是这需要一个单独的小章节,因为你很少谈论没有概率分布的随机变量。
什么是概率分布?
如果你取与随机变量 X 的输出范围相关的概率,那么你将得到 X. 的概率分布
方便的是,许多概率分布函数已经被定义来反映典型的数据生成过程。例如,我们的随机变量在任务是观察头部时取值 1,在任务是观察尾部时取值 0,使用伯努利分布来描述。
这篇文章不是关于各种分布的解释,甚至也不是对概率分布本身的深入探讨,但是如果你感兴趣,我强烈建议你阅读 https://medium.com/@aerinykim 写的文章。她在解释许多重要发行版背后的目的、起源和数学方面做了非凡的工作。
我想说的是,在实践中,概率分布往往比随机变量更有趣,更重要,因为它是描述随机现象各种特性的分布。换句话说,一旦你为你的实验确定了合适的概率分布(和所需的参数),那么原始的样本空间可以被处理掉,你可以简单地使用概率分布对未观察到的数据进行预测。
随机变量和各种工具包/库
本节的目的是说明我在上一节中提到的内容,也就是说,在实践中,您最终只会处理发行版。在这里,我提供了一些来自不同库的例子,这些库实现了随机变量(读取概率分布)以及它们如何互换使用这两个术语。
科学统计
scipy 有一个名为 stats 的子模块,它实现了各种发行版。它们定义了基类rv_continuous
& rv_discrete
,从中继承了一系列令人印象深刻的分布函数。
注意上图中随机变量和分布的概念是如何混淆的。文档上写着An alpha continuous random variable
,但它被列在标题Continuous distributions
下,即使文档上说该模块包含大量的概率分布。
pyMC3
谈到概率编程,pyMC3 可能是(没有双关语)使用最多的工具包。
你可以试试他们的笔记本这里但是正如我在上面的 pyMC3 截图中显示的,随机变量和分布是一回事。
张量流 _ 概率&爱德华 2
Tensorflow probability 是 Tensorflow 生态系统的一部分,它定义了各种分布和神经网络层,利用了 tensorflow 核心原语和加速功能。edward2 定义为使用 tensorflow_probability 构建的 概率编程语言 。唷!!….谈论称软件框架或库为编程语言会增加更多的混乱,但这似乎是概率建模领域的一种趋势。
至少 edward2 似乎有一个名为 RandomVariable 的 python 类,封装了随机变量的属性,即其分布、样本形状和可选值。我喜欢这个,因为它似乎更好地代表了软件设计中的理论。
结束语
- 把随机变量想象成不确定变量
- 随机变量是将结果映射到实数的函数
- 随机变量本身是确定性的,随机性(或者说不确定性)存在于样本空间中
- 你可以对随机变量进行概率计算
- 在实践中,随机变量和概率分布经常互换使用,即使它们是不同的东西(尽管一个没有另一个是没有用的)。
参考文献
[1]https://en.wikipedia.org/wiki/Random_variable
[2]样本空间和事件的一个很好的例子列表—https://faculty.math.illinois.edu/~kkirkpat/SampleSpace.pdf
**[3]math.stackexchange.com 的一个回答帮助我了解了术语“变量”的用法—【https://math.stackexchange.com/q/864839 **
[4]艾林·金(【https://medium.com/@aerinykim】)写了许多解释重要分布的文章。
但债务从何而来?
似乎没有人明白导致零售业末日的债务从何而来。这里有一个机器学习驱动的框架分析,可以帮助回答。
Payless ShoeSource 再次破产。这一次,它意味着我们所知道的公司的结束。商店将被清算。但该公司将继续存在:Payless Holdings 与其说是一家经营鞋店的公司,不如说是一家持有许可证的公司,其投资组合包括 Sperry、Stride Rite 和 AirWalk。如果你喜欢船鞋、滑板鞋,或者是个孩子,你的品牌将会继续。
但 Payless 为什么会拥有这么多品牌呢?因 Velcro 而闻名的折扣鞋类连锁店 Payless 自 2012 年被百隆资本、金门资本和金刚狼全球收购后就不再是原来的样子了。这些私人股本公司通过举债收购零售商,然后试图用它们来偿还收购费用。如果金门资本这个名字耳熟能详,那么它就是玩具反斗城和克莱尔破产等灾难背后的私人股本公司。如果你喜欢桌子,本·昂格尔斯比有一家很好的被私募股权收购的零售公司。
世代机遇
你可能会问,什么是杠杆收购?这是指一家公司带着债务收购另一家公司,并将收购的债务转移到被收购公司。假设一家对冲基金认为必胜客有一些他们可以解决的小问题,他们可以申请贷款,购买必胜客,然后将贷款转给必胜客。
如果一家公司的现金多于其发行在外的股票,掠夺者可以贷款收购一家公司,并立即偿还贷款。这是老牌企业攻略的核心活动。现在这种不可思议的情况非常罕见,所以通常公司并不打算迅速偿还贷款,相反,他们会在被收购的公司中进行这样的转变,以至于它可以简单地偿还自己的收购价格。这就引出了一个非常重要的问题:你有多少次真的发现了这家你可以免费买到的神奇公司?有多少公司能在杠杆收购过程中存活下来?
很少见,少之又少。
但这并不能阻止人们去尝试:毕竟,这些另类投资是真正致富的最佳途径之一。所以我们产生幻觉,认为一家成功的鞋店连锁店可以用信用卡购买。很明显,这是一个非常糟糕的主意。
人们是如何谈论它的?
表面上的金融新闻故事直截了当:Payless ShoeSource 破产了。在更深的层面上,我们经常使用一个叫做框架分析的想法来寻找更广泛的描述系统。框架是使故事有意义的隐喻、主题和风格的集合。你可能熟悉的一个特殊框架是政治中的“赛马”。这个故事依靠最近的民意调查来告诉我们两个候选人之间的竞争情况。一次民意调查的结果真的能告诉我们那么多吗?不。这就是为什么像王少伟或内特·西尔弗的聚合方法也很受欢迎,他们提供了对赛马的更深入的分析。个人投票的故事,以及它为什么继续的原因,是它可能是竞选中一个转变的指标。聚合模型可能会更明确地告诉你谁赢了,而快速投票故事可能会告诉你一匹马现在领先一个鼻子。
为了让赛马框架有意义,你必须接受民意调查背后的某种逻辑,即两个候选人相对平等,以及被讨论为与投票密切相关的新闻事件实际上是相关的。这里有很多结缔组织。框架也存在于其他领域,几乎每一项新的营养研究都可以被定位为值得报道的变化。
分析过程
在这个分析中,我假设 MALLET 提出的主题标签可以用来推断主题框架的特征。这种方法的结果包括文档主题概率的列表,以及这些主题之间的关系。因为我没有包括重复的,所以总的语料库是 270 段文本。我倾向于用经典的树状图来思考这些关系。
机器学习中的这种方法试图给每一段指定一个主题。这里有一个重要的警告,也是我们为什么要求助于人的判断,那就是系统无法解读更深层次的含义。同时,这种机器和人类阅读的结合有助于防止人类读者对主题和集群产生幻觉。
Balance of topic words to doc topics @ .7
您可以看到有两类主题,3–6/7 和 5–1–2–4/8。
原始主题输出可能难以阅读,并且依赖于一些解释工作。我的一般程序是检查自动生成的主题中的关键术语或专有名称。然后,在我对这个类别有了一些概念之后,我会检查概率最高的文件,寻找这些文本中的论点。
在这一点上,我建立了一个键,描述了哪些类型的令牌被检测为关联。作业将包括我的语义判断,基于我对 MALLET 提取的关键词的阅读以及对每个主题中最有可能出现的文本(段落)的仔细阅读:
- 加拿大的维度
- 在线竞争和债务
- 负债累累的零售业
- 与其他公司和房地产相关的零售问题
- 关于股票市场状况的一般性讨论
- 加拿大境外的清算和全球业务
- 崩溃的细节,付不起房租
- 零售商受到限制,缺乏强有力的员工,流动性问题
在我们继续之前,了解一下有多少数据集被分配给了一个特定的主题是很重要的。主题 7,崩溃的细节是目前分配最重的主题。这是新闻业建设中的一个重要环节,这是有意义的——这是行动所在。主题 6 和 4 也高于其他主题,这更有意义。需要理解的重要一点是,关于债务的讨论并没有很好地集中到故事的主要部分——我们知道大多数细节都是围绕第七类展开的。
这种关系也能告诉我们一些我们正在看的故事。一组是该行业背负债务的故事,附有清算的关键细节,以及那种淫秽的线索。另一个集群包括一个更完整、更复杂的商业故事中可能会出现的所有部分,最深入的棒球内部有几个层次,包括加拿大股市的总体状况,但高于特殊问题,如零售招聘和房地产。
仅有的两段讨论了金门公司和合伙人在玮伦鞋业灭亡中的作用,这两段被分配给了主题 7 和主题 2。主题 2 特别有趣,因为它是故事真正理论化的地方。鉴于主题 7 无处不在,我将沿着主题 2 更丰富的次要任务继续分析。考虑主题 2 中的这两段:
Valley Morning Star: 这家公司成立于 1956 年,以在自助环境下提供打折鞋为前提,2012 年被金门资本(Golden Gate Capital)和百隆资本(Blum Capital Partners)私有化,并因此举引发的严重债务问题而陷入困境。
彭博: Payless 成立于 1956 年,目标是在自助环境中销售价格合理的鞋子,并称其是西半球最大的专业鞋类连锁店。该公司努力管理 2012 年金门资本(Golden Gate Capital)和百隆资本(Blum Capital Partners)杠杆收购的债务,并于 2017 年 4 月申请破产保护。
这是整部文集里金门资本出现的两段。这是唯一一次记者将债务的原因归结于一个演员,而不是将其作为崩溃故事本身的一个父概念。我觉得这很荒唐:我们知道债务是导致公司破产的原因,但是我们可以插入任意数量的解释(主题 2 的孩子)来解释债务从何而来。
很明显,话题 2 的峰值附近的故事很少。这可以在对主题密度的分析中进一步看出:
低密度并不意味着某些东西不重要,而是意味着故事可能均匀分布,或者大部分段落不太可能出现在该段落中。例如,主题一是一个专业故事,分配给它的那些段落实际上是关于加拿大的。同样清楚的是,某些出版物和主题与某一天或某个作者有更密切的联系。像 2 或 5 这样的限制话题可以指向特别专业的故事。在主题 5 的情况下,真正关注股票市场的故事通常是一个特定和独特的子集。主题建模器可以有效地指向框架。当与其他语义方法相结合时,就有可能提取帧并将这些帧作为族进行关联,以便进一步分析。
在很大程度上,这项研究揭示了零售报告的一种按数字着色的方法。如果一家公司破产,请注意它是因为债务而倒闭的,这可能会导致戏剧性的一幕,其中将包括清算。从这个简短的研究中可以得出一个结论,主题模型可以为新新闻故事的自动生成提供一个简单的框架。
你为什么在乎?
这些商店失败的直接原因是,它们没有销售额来补偿它们的财务设计强加给它们的破坏。在零售业的背景下,这似乎是对整体经济的合理调整——美国的零售业空间太大了。同时,这也不需要发生。玩具反斗城和 Payless 的世界会更好,这些都是可行的业务。
在这个论述中,债务有一种本体论性质,它只是零售企业的一种财产。它不知从哪里冒出来,必须予以反击。这不同于教育、消费或抵押贷款债务的表现,后者似乎是个人做出不负责任的决定的结果,尽管有充分的证据表明,促进房屋交易的制度选择导致了大衰退,或者掠夺性的盈利机构而不是你所在的州是许多教育债务的来源。我们在谈论债务存在的原因方面做得很差,在让人们感到羞耻方面做得很好。
公司看起来像是法人,但不知何故,他们比普通人承担的责任要少。公司之间也存在差异:私人股本公司在某种程度上比普通公司享有更大的回旋余地。只有两名勇敢的记者在报道中提到了金门的名字。
Payless 倒闭是因为它在一次杠杆收购中被私有化。他们失败不是因为他们的库存系统、缺乏熟练的鞋类销售人员、DSW、著名的鞋履或互联网。这些文章中的分析包括一个强有力的非推论,即“债务”以某种方式简单地出现,然后允许其他因素在企业中发生。在这种框架下,承担债务的行为者不仅无可指责,而且是隐形的。谁被允许进入购买所需的现金池?你如何申请做这样的事情?尽管是大规模杀伤性金融武器,为什么这种做法还在继续?我能像这样得到一堆钱吗?
开始改变报告的一个重要地方:为什么我们不能讨论谁积累了债务,作为我们报告零售破产的一个关键因素?我们不需要的是又一个招牌竖起、周六开始清算销售、债务突然出现的故事。
但是泡菜去哪里了呢?
fast.ai《程序员实用深度学习》第五课
我正在学习 fast.ai 的“程序员实用深度学习”课程,并把我的经历写在博客上。由于非常慷慨的 fast.ai 社区已经为每一课做了详细的笔记(参见第 5 课的笔记,这里是),我只是写下讲座的部分内容,并附带 Jupyter 笔记本,我需要停下来思考几次。
从笔记本开始,我们导入 matplotlib 和 fast.ai 库:
%matplotlib inline
from fastai.basics import *
然后我们需要得到“腌制”的 MNIST 数据集,所以我下载它并试图找出我需要把它放在哪里。下面是笔记本中的下一行代码:
path = Config().data_path()/’mnist’
但是当我运行它时,我得到以下错误:
FileNotFoundError: [Errno 2] No such file or directory: '/home/jupyter/.fastai/data/mnist'
我检查笔记中的代码,它与笔记本不同:
path = Path('data/mnist')
看起来我们把数据放在了‘数据’子目录下的一个新文件夹里?好的,所以我在“数据”目录下创建了一个文件夹,命名为“mnist”,然后把 mnist.pkl.gz 上传到里面。那有效!
然后我们把图像展平,看到这个,比如,是数字 5:
下一个让我有点吃惊的是,杰里米谈到这些图像时说:“目前它们是 numpy 数组。我需要他们是张量。所以我可以把 torch.tensor 映射到它们上面,现在它们就是张量了。”我意识到我不知道 numpy 数组和张量之间的区别,所以我查了一下。事实证明,张量有许多不同的定义,其中一些直接相互矛盾。
最后,我决定伊恩·古德费勒的深度学习中的定义对我来说最有意义,无论如何,来自那本书意味着它对这些目的来说是正确的。Goodfellow 说:“在某些情况下,我们需要一个超过两个轴的阵列。在一般情况下,排列在具有可变轴数的规则网格上的数字阵列称为张量。”所以这符合那些说张量是多维数组的人,其中标量是 0 维张量,向量是 1 维张量,矩阵是 2 维张量。对我有用!我也通读了这个关于 numpy 如何处理张量运算的教程。
然后我做得很好,直到我们准备“线性化”我们的模型,而不是像我们在以前的课程中那样手动完成,Jeremy 说:“所以我们唯一想添加的是我们想在我们的类中创建一个包含线性层的属性,一个 nn。线性模块。什么是 nn?线性模块?它是做 x@a 的东西,但实际上它不仅仅做这个。它实际上是 x@a + b,换句话说,我们不需要把一列相加。这就是它的全部功能。如果你想玩玩,为什么不试着创建你自己的 nn。线性类?你可以创建一个叫做 MyLinear 的东西,这将花费你(取决于你的 PyTorch 背景)一两个小时。我们不希望这一切变得不可思议,现在你已经知道了创造这一切的所有必要条件。”
所以我盯着它看了几分钟,完全不知道该怎么做。我观察了它在下一个单元格中的调用方式:
class Mnist_Logistic(nn.Module):
def __init__(self):
super().__init__()
self.lin = nn.Linear(784, 10, bias=True)
def forward(self, xb): return self.lin(xb)
好的,我们给它传递图像的数量(784),10 (10 什么?),我们设置 bias=True,因为我们想给x@a
加上一个偏差,因此x@a + b.
我向下滚动笔记,记得 Jeremy 说:“我们的输入是 784 维的,我们需要能给出 10 个数的概率的东西。在这之后,我们有十个激活,然后我们想添加偏见,所以我们去了。”这就是 10 的由来。
但我不知道如何从那里开始,所以我转向 fast.ai 论坛,发现只有一个关于这个问题的帖子,没有任何回复,所以我想知道是否有很多人真的尝试这样做。本着真正的 fast.ai 精神,我决定把这个问题放在一边,继续下去,而不是陷入细枝末节。
我要停下来思考的下一点是损失函数的选择。在之前的课程中,我们使用了均方误差函数,即 MSE。当你做一个预测时,这个方法很有效,然后可以测量你的观察结果与你的预测“有多远”,如下所示。
但是正如 Jeremy 所说,损失函数对于像这样的分类问题没有意义,因为我们没有考虑图像中表示的数字的数值:我们考虑的是图像本身。因此,在图像识别环境中,认为 3 比 0 更接近 4 是不合理的,因为如果我们认为我们看到的数字是 3,但它实际上是 4,那就和认为它是 0 一样错误。
所以他说我们将使用交叉熵损失来代替,它不仅考虑预测是正确还是不正确,还考虑做出预测的置信度。在下面的例子中,我们预测一张图片是一只猫还是一只狗。
Screenshot from Lesson 5
该图显示了电子表格中的计算,但这是 Python 版本的计算:
**def** CrossEntropy(Pred)Cat), Cat):
**if** Cat == 1:
**return** -log(Pred(Cat))
**else**:
**return** -log(1 - Pred(Cat))
用杰里米的话来说:“如果是一只猫,那么就取猫性的对数,如果是一只狗(即,否则),就取一减去猫性的对数(换句话说,就是狗性的对数)。”我们在否定结果,我认为这一定是因为结果本身是负的,但在文字中,我们指的是“损失”的价值,如果“损失”是负的,就像失去了一个负值;即加,不亏。所以损失为非负值是有意义的。
因此,我们计算每次迭代的交叉熵损失,然后将所有这些值相加,以找到模型作为一个整体的交叉熵损失。
第五课到此结束!第六课再见。
在 GitHub 上查看 MNIST 笔记本中的代码。
关于此主题的其他帖子:
第一课:fast . ai 入门
第二课:对验孕结果进行分类
第二课(续):深度学习能比鸽子表现更好吗?
第三课:一万种行不通的方法
第四课:预测服务员的小费
我是加州大学东湾分校的数学讲师,也是一名有抱负的数据科学家。在 LinkedIn 上和我联系,或者在 Twitter 上和我打招呼。
买家请注意,虚假产品评论正在困扰着互联网。机器学习如何帮助发现它们。
使用机器学习识别虚假产品评论
例如,CBS 新闻报道,在 Walmart.com 发布的 52%的产品评论是“不真实或不可靠的”,而在亚马逊发布的评论中至少有 30%是假的。识别观点垃圾邮件的问题仍然是一个开放的话题,尽管事实上一些研究人员已经解决了这个问题。
是什么让商家招致产品欺骗性评论?主要驱动力是在竞争中领先,定位他们的产品或服务,以影响公众和组织进行购买,从而增加他们的销售。欺诈是通过张贴虚假的负面评论和给竞争对手的产品不公正的评级来进行的。
据了解,“亚马逊机械土耳其”,一个互联网众包市场,允许请求者(企业或个人)协调人力来执行一项任务,被用来为一家连锁酒店众包虚假评论。鉴于这一问题已经发展到令人担忧的程度,Yelp.com,一家发布众包评论的商业目录服务公司,发起了一项诱捕行动,以揭露那些购买虚假评论的商家。
我将讨论 Mukherjee 等人在他们的论文中提出的检测产品评论中垃圾邮件的方法。他们称他们的模型为“作者空间模型”(ASM)。它基于无监督学习,将空间建模为潜在的,简而言之就是模型变量是“隐藏的”。它也是一个贝叶斯推理框架。该模型的目的是将这种潜在的群体分布分类成垃圾邮件发送者和非垃圾邮件发送者。
请注意,当我提到产品时,我也将包括服务。
怎样才能识别一篇评论可能是假的?为了开发他们的模型,作者定义了九个变量作为观察到的特征,前五个他们将它们归类为值在区间[0,1]内的作者特征(表示 Beta 分布,其中接近 0 或 1 的值分别表示非垃圾邮件或垃圾邮件。另一方面,变量 5 至 9 代表评论特征,它们采用二进制值,0 代表非垃圾邮件,1 代表垃圾邮件(表示伯努利分布):
- 内容相似度【CS】。垃圾邮件发送者倾向于复制类似产品的评论。余弦相似度用于捕捉这些评论中的内容相似度。
- 最大评论数(MNR) 。同一个作者在一天内发表几篇评论的不寻常行为可能是垃圾邮件的迹象。
- **回顾突发性(BST)。**指作者发布评论的频率(短)。这个作者通常是网站的新成员。满足这一条件可能意味着有招致欺骗性评论的倾向。
- 初审者比例(RFR) 。该指标量化了早期评论对新推出产品的销售产生影响的事实。
- **重复/近似重复的评论(DUP)。**相同或近似相同的评论可能表示垃圾邮件行为。此功能类似于 CS,但在这种情况下属于 review 功能。
- **极限额定值(EXT)。**为了给评论带来最大或最小的好处,垃圾邮件发送者通常会给产品标上一星或五星。
- 评级偏差(开发)。垃圾邮件发送者会通过放置他们的评论来转移评论的平均情绪。当这种量化的偏差超过阈值时,这些类型的审查被识别。
- **早期时间框架(ETF)。**此功能捕获了评审的早期时间。基本原理是,垃圾邮件发送者最有可能更早地进行审查,接近产品的推出,以实现最大的影响。
- **评级滥用(RA)。**指多次对同一产品进行星级评定的行为。
ASM 是如何工作的?为了说明这个模型,我在下面的图表中简化了它的功能(见图 1-A 和 1-B),关于数学表示请参考论文。
Figure 1-A
Figure 1-B
ASM 从接受所有作者的所有评论开始,这些评论是按照我们已经讨论过的特性组织的。每个球体代表一个可观察变量(即特征)。一旦特征被收集(见图 1-A 节点 A),它们被模型处理并学习“垃圾邮件和非垃圾邮件的潜在行为分布”(Murkherjee 等人)。因此,ASM 解决了一个聚类问题( K = 2)。
在贝叶斯环境中,空间被建模为潜在的 ASM 函数。这是一个 的生成过程 因为它发出了 9 个特征和它们的滥发概率。
为了进行推断,该模型使用“ ”折叠吉布斯采样”(CGS),其表示用于近似后验概率分布的技术。CGS 属于 马尔可夫链蒙特卡罗 算法家族。
一旦推断出排名函数,就使用 学习排名 监督技术对其进行处理,该技术基本上采用 ASM 获得的排名,并生成单个聚合排名函数(见图 1-A 节点 C)。
在我看来,这篇文章提出了一种技术,可以显著提高产品评论中意见垃圾邮件制造者的检测。这是一个创新,因为提出了一个无监督的方法来检测虚假评论。作者声称,与强大的竞争对手相比,他们已经实现了更高水平的准确性。我相信,随着越来越多提供此类信息的企业开始实施像 ASM 这样的 ML 技术,垃圾观点将开始减少,同时,消费者必须持怀疑态度,并使用过滤虚假评论的网站获得信息。
使用行为足迹发现观点垃圾邮件发送者
A 慕克吉, A 库玛, B 刘, J 王,M 许……—2013 年第十九届会议录——
针对门外汉的吉布斯采样
统计分析中的贝叶斯推断
GC Tiao——2011——books.google.com GEP 盒子
加快潜在狄利克雷分配模型的标定,完善……
作者 JA lópez——2017 年
[## 买家当心:亚马逊、沃尔玛和其他主要零售商遭遇虚假评论的灾难
根据 Fakespot 的一项研究,虚假评论在许多顶级零售商网站上越来越普遍
www.cbsnews.com](https://www.cbsnews.com/news/buyer-beware-a-scourge-of-fake-online-reviews-is-hitting-amazon-walmart-and-other-major-retailers/)
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -
亲爱的读者,我有兴趣从你那里知道:
- 当你在网上购物时,你会被当地的评论所影响吗?或者除此之外,你寻找一个或多个外部评论?
- 如果您使用产品评论网站,您更信任哪个网站?
- 你认为如何解决这个以惊人速度增长的问题?
感谢参与,可以留言评论回应。
在荷兰买房(书呆子气)
如果你像我一样,当你不得不做出重大决定时,比如买房子,你可能会不知所措。在这种情况下,我总是喜欢采用数据驱动的方法,这将有助于我找到最佳解决方案。这涉及到两个步骤。首先,我们需要尽可能多地收集数据。其次,我们需要定义一个衡量成功的标准。
收集荷兰房价数据需要一些努力。我从 funda.nl 网站上获得了房价。需要注意的是,网站上的要价并不是房屋的实际售价。要价也没有明显偏向低于或高于售价,所以我无法纠正。这是处理真实数据时通常会发生的情况,它总是远非完美。
定义成功的衡量标准是个人的和主观的。我认为房子是一个不错的选择,如果:1。要价便宜;和/或,2。与投资相比,我可以从中获得的潜在租金很高。
- 为了知道要价是否便宜,我使用了网站上正在出售的房屋的要价,建立了一个机器学习模型,根据房屋的特点预测其要价。然后,我可以用那个模型来评估房子的要价应该是多少,如果实际要价低于模型预测的价格,那么我会认为这是一笔好交易。(注意:在这种情况下,好交易的定义是在数据集本身的范围内,而不是从市场价值的绝对角度;所以,举例来说,如果网站上的所有价格都是市场价格的两倍,我仍然可以通过比较房屋来获得一些不错的交易。
- 为了知道正在出售的房屋的租金价格,我使用了网站上提供的房屋出租数据,并建立了一个机器学习模型,根据房屋特征预测租金价格。然后,我可以用那个模型来评估一个正在出售的房子的租金价格应该是多少。如果要价与预期租金的比率很低,那么这意味着我可以租下房子,投资回收期很短。
最后一点需要注意的是,这里所做的所有分析都是针对静态数据的,不涉及价格趋势预测。
数据
从 funda.nl,我有 2019 年 7 月在阿姆斯特丹、Zaandam 和 Diemen 出售的 2150 套房屋和公寓的数据;出租的房屋和公寓有 1,046 套。
对于每栋房子,我都有以下数据(是的,网站是荷兰语的,你可以使用谷歌翻译):
['Aangeboden sinds', 'Aantal badkamers', 'Aantal kamers', 'Aantal woonlagen', 'Aanvaarding', 'Achtertuin', 'Badkamervoorzieningen', 'Balkon/dakterras', 'Bijdrage VvE', 'Bouwjaar', 'Capaciteit', 'Cv-ketel', 'Eigendomssituatie', 'Energielabel', 'Externe bergruimte', 'Gebouwgebonden buitenruimte', 'Gelegen op', 'Inhoud', 'Inschrijving KvK', 'Isolatie', 'Jaarlijkse vergadering', 'Lasten', 'Ligging', 'Ligging tuin', 'Onderhoudsplan', 'Oppervlakte', 'Opstalverzekering', 'Overige inpandige ruimte', 'Periodieke bijdrage', 'Reservefonds aanwezig', 'Schuur/berging', 'Servicekosten', 'Soort appartement', 'Soort bouw', 'Soort dak', 'Soort garage', 'Soort parkeergelegenheid', 'Soort woonhuis', 'Specifiek', 'Status', 'Tuin', 'Verwarming', 'Voorlopig energielabel', 'Voorzieningen', 'Vraagprijs', 'Warm water', 'Wonen', 'address']
我还使用以下代码创建了一些额外的功能:
def create_cols(df):
df[‘zip_code’]=df[‘address’].str.extract(pat=’([0–9]{4} [A-Z]{2})’)
df[‘zip_code’]=df[‘zip_code’].str.replace(‘ ‘, ‘’, regex=False)
df[‘zip_code_number’]=df[‘zip_code’].str.extract(pat=’([0–9]{4})[A-Z]{2}’).fillna(0).astype(int)
df[‘price’]=df[‘Vraagprijs’].str.extract(pat=’([0–9]{0,3}.?[0–9]{3}.[0–9]{3})’)
df[‘price’]=df[‘price’].str.replace(‘.’, ‘’, regex=False).astype(float)
df[‘nr_bedrooms’] = df[‘Aantal kamers’].str.extract(pat=’([0–9]) slaapkamer’).fillna(0).astype(int)
df[‘nr_rooms’] = df[‘Aantal kamers’].str.extract(pat=’([0–9]) kamer’).fillna(0).astype(int)
df[‘nr_floors’] = df[‘Aantal woonlagen’].str.extract(pat=’([0–9]) woonla’).fillna(0).astype(int)
df[‘nr_bathrooms’] = df[‘Aantal badkamers’].str.extract(pat=’([0–9]+) badkamer’).fillna(0).astype(int)
df[‘nr_toilet’] = df[‘Aantal badkamers’].str.extract(pat=’([0–9]+) aparte? toilet’).fillna(0).astype(int)
df[‘construction_year’]=df[‘Bouwjaar’].str.extract(pat=’([0–9]{4})’).astype(float)
df[‘cubic_space’] = df[‘Inhoud’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘external_storage_space’] = df[‘Externe bergruimte’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘outdoor_space’]=df[‘Gebouwgebonden buitenruimte’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘living_space’]=df[‘Wonen’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘montly_expenses’]=df[‘Bijdrage VvE’].str.extract(pat=’([0–9]+) per maand’).fillna(0).astype(float)
df[‘other_indoor_space’]=df[‘Overige inpandige ruimte’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘dont_have_frontyard’]=df[‘Achtertuin’].str.extract(pat=’(voortuin)’).isna()
df[‘not_straat’]=df[‘address’].str.extract(pat=’(straat)’).isna()
df[‘not_gracht’]=df[‘address’].str.extract(pat=’(gracht)’).isna()
df[‘not_plein’]=df[‘address’].str.extract(pat=’(plein)’).isna()
df[‘price_per_living_sqm’] = df[‘price’]/df[‘living_space’]
df[‘is_house’]=df[‘Soort appartement’].isnull()
df = df[df[‘price’].notna()]
df = df[df[‘living_space’]>0]
df = df[df[‘living_space’]<600]
df = df[df[‘price’]<4500000]
df[‘dont_have_backyard’] = df[‘Achtertuin’].isna()
df[‘backyard_size’] = df[‘Achtertuin’].str.extract(pat=’([0–9]+) m²’).fillna(0).astype(float)
df[‘has_garage’]=df[‘Soort garage’].isna()
df[‘total_area’] = df[‘outdoor_space’]+df[‘external_storage_space’]+df[‘living_space’]+df[‘other_indoor_space’]
df[‘address_nozip’]=df[‘address’].str.extract(pat=’^(.+)[0–9]{4} [A-Z]{2}’)
df[‘address_zip’]= df[‘address_nozip’] + ‘ ‘ + df[‘zip_code’]
df[‘parcela’]= df[‘Oppervlakte’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘price_per_parcela_sqm’] = df[‘price’]/df[‘parcela’]
return df
数据探索
需要导入包:
import pandas as pd
import re
import numpy as np
import seaborn as sns
import scipy.stats as stats
import matplotlib.pyplot as plt
from sklearn.model_selection import GridSearchCV, cross_val_score, KFold
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
from sklearn.preprocessing import LabelEncoder
from xgboost import XGBRegressor
加载数据:
df = pd.read_csv('data_funda.csv',sep = ',', encoding = 'utf-16')
df = create_cols(df)
我们来看看价格、居住空间和建造年份是什么关系。由于价格和生活空间的偏态分布,我还创建了这些变量的对数转换值,并分别将其命名为 price_log1p 和 living_space_log1p(参见*“特征分布”*一节)。
# Price vs. Living space
p_cor = df[['living_space','price']].corr(method ='pearson') ['price'].living_space
df.plot.scatter(x='living_space',y='price',c='construction_year',colormap='viridis', figsize=[12,8], vmin=1900, vmax=2000,label="corr:"+str(round(p_cor,4)))
plt.legend()
p_cor = df[['living_space_log1p','price_log1p']].corr(method ='pearson') ['price_log1p'].living_space_log1p
df.plot.scatter(x='living_space_log1p',y='price_log1p',c='construction_year',colormap='viridis', figsize=[12,8], vmin=1900, vmax=2000,label="corr:"+str(round(p_cor,4)))
plt.legend()
你可以清楚地看到,房子越大,价格越高(咄!),但同样有点令人惊讶的是(如果你对阿姆斯特丹一无所知的话)同样的平方米,非常古老的房子比较新的房子要贵。这是因为位置!。阿姆斯特丹市中心很贵,那里的房子也很旧。从图中还可以看出,2000 年左右建造的房屋往往比 1980 年建造的房屋更大。
价格如何随着卧室数量的变化而变化?
# Total bedrooms vs. Price
sns.boxplot(x=df['nr_bedrooms'], y=df['price'])
plt.show()
sns.boxplot(x=df['nr_bedrooms'], y=df['price_per_living_sqm'])
plt.show()
房间数量越多,要价越高(左地块),很可能是因为房子比较大。但是,如果我们看到每平方米的价格是如何随着房间数量的变化而变化的(右图),它似乎是相当平坦的,除了 3、4 和 5 卧室的房子中位数更低。
位置,位置,位置!
房价很大程度上取决于房子的位置。让我们来看看价格分布如何随邮政编码而变化。
df[['price','zip_code_number']].boxplot(by='zip_code_number', figsize=[25,8], rot=45)
plt.ylabel('Price')
从图中您可以看到,有些邮政编码的房屋具有较高的中值价格和标准差(例如,市中心的邮政编码,如 1071、1077、1017),而有些邮政编码的价格一直较低(例如,1102、1103、1104,位于 Bijlmermeer 地区)。
事实上,我发现更有趣的是看到每平方米价格的分布与邮政编码。
ax=df[['price_per_living_sqm','zip_code_number']].boxplot(by='zip_code_number', figsize=[25,8], rot=45)
plt.ylabel('Price per sqm')
ax.set_ylim([2000,12500])
在没有任何机器学习知识的情况下,如果我们有固定的预算和最小平方米的要求,人们可以使用之前的地块来查看要探索的街区和要去看房子。因此,如果我们正在寻找一个至少 100 平方米的房子,并且希望花费不超过 40 万欧元,我们应该关注邮政编码,如 1024,1060,1067,1069,> 1102。当然,你可能会在邮编为 1056 的地方买到一栋低于预算的房子(离群值),但要做好准备,不得不花一些额外的钱来装修:)。
谈装修…每平米价格如何随施工年份变化?我们来画个图。
df_filt = df[(df['construction_year']>1900)&(df['construction_year']<2019)]
df_filt['construction_year_10'] = df_filt['construction_year']/10
df_filt['construction_year_10'] = df_filt['construction_year_10'].apply(np.floor)
df_filt['construction_year'] = df_filt['construction_year_10']*10
data = pd.concat([df_filt['price_per_living_sqm'], df_filt['construction_year']], axis=1)
f, ax = plt.subplots(figsize=(20, 8))
fig = sns.boxplot(x='construction_year', y="price_per_living_sqm", data=data)
fig.axis(ymin=1000, ymax=11000)
plt.xticks(rotation=45)
正如我们之前看到的,非常旧的房子每平方米的价格比新房子要高。这是因为那些老房子位于非常昂贵的邮政编码。因此,从每平方米价格最高的 1900 年开始,直到 1970 年,价格下降,然后从那一年开始,价格再次上涨。
为了全面了解每对特征是如何相互关联的,让我们来看看相关矩阵。
plt.figure(figsize=(20,12))
sns.heatmap(df.drop(columns='index').corr(), annot=False, square=True)
有太多的事情在那里发生,但它给了我们一个概念,什么变量是正相关的(如居住面积与卧室、房间、地板、浴室等的数量。)以及哪些是负相关的(例如,作为一栋房子而没有后院或前院,或者每月有开销)。
如果我们只关注与价格相关性最高的前 10 个变量,那么相关性矩阵如下所示:
corrmat = df.corr()
cols = corrmat.nlargest(10, 'price')['price'].index
hm = sns.heatmap(np.corrcoef(df[cols].values.T), cbar=True, annot=True, square=True, fmt='.2f', annot_kws={'size': 10}, yticklabels=cols.values, xticklabels=cols.values)
plt.show()
我们可以看到,价格与所有直接或间接与房子大小相关的变量高度相关。
我们可以做的最后一项质量检查是查看每个要素缺失值的百分比。
df_na = (df.isnull().sum() / len(df)) * 100
df_na = df_na.drop(df_na[df_na == 0].index).sort_values(ascending=False)[:40]
missing_data = pd.DataFrame({'Missing Ratio' :df_na})
plt.figure(figsize=(15, 9))
sns.barplot(x=df_na.index, y=df_na)
plt.xticks(rotation='80')
plt.ylabel('Percent of missing values', fontsize=15)
这些变量中的一些有缺失值,因为数据不是由房地产代理商/业主提供的(例如能源标签),而对于其他一些缺失值实际上意味着缺少它(例如车库或花园-tuin-)。
特征分布
为了建立预测房价的 ML 模型,让我们仔细看看特征直方图。我在这里只画两个例子:月支出(欧元)和生活空间(平方米)。
for col in df.describe().columns.values:
if col<>'price_per_parcela_sqm':
axs = df.hist(column=col,bins=50)
从左边的图中我们可以看到,一些房子(主要是公寓)每月都有开销(荷兰语称为 Bijdrage VvE ),平均在 100 欧元左右,而其他一些房子则完全没有。
从右图中,您可以看到居住空间分布的模式大约为 100 平方米。分布不是正态分布,而是高度右偏;价格分布也是如此。让我们仔细看看价格分布。
for col in df.describe().columns.values:
try:
sns.distplot(df[col], label="Skewness: {:.3f}".format(df[col].skew()))
plt.title(col+' Distribution')
plt.ylabel('Frequency')
plt.xticks(rotation=45)
plt.legend()
plt.show()
qq = stats.probplot(df[col], plot=plt)
plt.show()
except:
pass
如此高的偏斜度对于输入到 ML 模型的特征和标签来说是不期望的。因此,让我们继续记录具有高偏斜分布的变换变量。
# Assign numeric features by excluding non numeric features
numeric = df.dtypes[df.dtypes != 'object'].index# Display the skewness of each column and sort the values in descending order
skewness = df[numeric].apply(lambda x: x.skew()).sort_values(ascending=False)# Create a dataframe and show 5 most skewed features
sk_df = pd.DataFrame(skewness,columns=['skewness'])
sk_df['skw'] = abs(sk_df)
sk_df.sort_values('skw',ascending=False).drop('skw',axis=1).head()# As a general rule of thumb, skewness with an absolute value less than 0.5 is considered as a acceptable range of skewness for normal distribution of data
skw_feature = skewness[abs(skewness) > 0.5].index# Transform skewed features to normal distribution by taking log(1 + input)
for col in skw_feature:
df[col+"_log1p"] = np.log1p(df[col])# let's check the result of the transformation
sns.distplot(df['price_log1p'],label="Skewness: {:.3f}".format(df['price_log1p'].skew()))
plt.legend()
plt.title('Price Log(price + 1) transform Distribution')
plt.ylabel('Frequency')plt.figure()
qq = stats.probplot(df['price_log1p'], plot=plt)
plt.show()
我们可以看到,对价格值进行对数变换后,分布更接近于正态分布(尽管还不完美)。
价格预测 ML 模型
数据探索到此为止,让我们建立一个 ML 模型!。
首先,让我们定义将要使用的特性。
#Label encoding
feat_enc = ['zip_code_number']# Features
feat_cols = ['nr_bedrooms','nr_rooms','nr_floors','nr_bathrooms','nr_toilet','zip_code_number_le','is_house','has_garage','dont_have_backyard','not_straat','not_gracht','not_plein','has_frontyard','backyard_size_log1p','living_space_log1p','cubic_space_log1p','outdoor_space_log1p','total_area_log1p','montly_expenses_log1p','parcela_log1p','construction_year']
我们将训练一个 XGBoost 回归模型,为超参数调整做一些小网格搜索,并且我们将使用交叉验证。
df_filt = df[df['price']<700000]#Missing values, impute with mode
for fr in ['construction_year']:
df_filt[fr].fillna(df_filt[fr].mode()[0], inplace=True)#Label encoding
for feat in feat_enc:
le = LabelEncoder()
le.fit(df_filt[feat])
df_filt[feat+'_le'] = le.transform(df_filt[feat])label='price_log1p'x = df_filt[feat_cols]
y = df_filt[label]
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.1, random_state=1)
print(X_train.shape, X_test.shape,y_train.shape)kfold = KFold(n_splits=5, random_state= 0, shuffle = True)def performance_metric(y_true, y_predict):
""" Calculates and returns the performance score between
true (y_true) and predicted (y_predict) values based on the metric chosen. """
score = r2_score(y_true, y_predict)
return scoreXGB = XGBRegressor()xg_param_grid = {
'n_estimators' :[900,400,1200],
'learning_rate': [0.04, 0.06, 0.08],
'max_depth': [3,6,8],
'min_child_weight':[0.2],
'gamma': [0,1],
'subsample':[0.8],
'colsample_bytree':[1]
}
gsXGB = GridSearchCV(XGB,param_grid = xg_param_grid, cv=kfold, scoring="neg_mean_squared_error", n_jobs= -1, verbose = 1)
gsXGB.fit(X_train,y_train)
XGB_best = gsXGB.best_estimator_
print(gsXGB.best_params_)
y_hat_xgb = np.expm1(gsXGB.predict(X_test))
让我们检查模型的性能。
r2_train = performance_metric(np.expm1(y_train), np.expm1(gsXGB.predict(X_train)))
r2_test = performance_metric(np.expm1(y_test), y_hat_xgb)
print "R2 train: ", r2_train
print "R2 test: ", r2_test
plt.scatter(np.expm1(y_train), np.expm1(gsXGB.predict(X_train)),label='R2:'+str(round(r2_train,4)))
plt.title('Train')
plt.xlabel('Price')
plt.ylabel('Price predicted')
plt.plot([100000,700000], [100000,700000], 'k-', alpha=0.75)
plt.legend()
plt.show()plt.scatter(np.expm1(y_test), y_hat_xgb,label='R2:'+str(round(r2_test,4)))
plt.plot([100000,700000], [100000,700000], 'k-', alpha=0.75)
plt.title('Test')
plt.xlabel('Price')
plt.ylabel('Price predicted')
plt.legend()
plt.show()
相关性高,这很好,从图中你可以看到一些要价的垂直模式。这是由于房地产经纪人/业主四舍五入价格。
查看特征重要性也很有用,可以了解哪些特征有助于预测房价。
from xgboost import plot_importanceplot_importance(XGB_best)
plt.show()
正如我们在数据探索部分已经看到的,房价与房子的位置、建造年份和大小高度相关。
现在,让我们使用模型来预测房价,并寻找要价低于预测价格的房屋。
Xtt = pd.concat([X_train,X_test],axis=0)
ypred=pd.DataFrame([np.expm1(gsXGB.predict(Xtt)),Xtt.index]).transpose()
ypred.columns = ['pred','idx']
ypred.set_index('idx',inplace=True)
ytt = ypred.join(df_filt)
ytt['ratio'] = ytt['price']/ytt['pred']
ytt['difference'] = ytt['price'] - ytt['pred']
现在,我希望看到室内面积超过 100 平方米、室外面积超过 5 平方米、要价和预测价格之间的差距非常大的房子:
x=ytt[['ratio','pred','price','outdoor_space','dont_have_backyard','dont_have_frontyard','living_space','nr_floors','difference','href']].sort_values(by='ratio')
print x[ (x['outdoor_space']>5)& (x['living_space']>100) ].head(10)
让我们看一个例子:
ratio pred price outdoor_space living_space difference
0.814140 368487 300000 16 116 -68487
href: [https://www.funda.nl/koop/zaandam/huis-40278208-lindenlaan-1/?navigateSource=resultlist](https://www.funda.nl/koop/zaandam/huis-40278208-lindenlaan-1/?navigateSource=resultlist)
在这里,预测价格和要价之间的差异是-68K 欧元。我在 huispedia.nl 上查了一下,根据他们的说法,那栋房子 30 万欧元似乎也很划算(尽管他们预测价值在 37.1 万到 39.7 万欧元之间)。当然,这是做出如此重大决定的冷酷无情的方式,但你仍然需要点击链接,查看照片,看看你是否不介意橙色的墙壁和倾斜的天花板。
租金预测
以类似的方式,我使用从 funda.nl 获得的租金价格来建立 ML 模型,该模型预测给定房屋特征的租金价格。我不打算描述确切的方法,但我使用租金模型来估计网站上正在出售的 2,150 所房屋和公寓的租金价值(我们没有租金价格)。
我使用租金预测来估计如果我买了房子后再出租,每套房子的回收期是多少(我称之为 ratio_sell_rent_year )。为了计算它,我将价格除以租金预测,再除以 12,得到一个年单位。
最后,我按邮政编码绘制了 ratio_sell_rent_year,看看哪些地区在投资回报方面比较方便。
ytt['ratio_sell_rent'] = ytt['price']/ytt['rent_prediction']
ytt['ratio_sell_rent_year'] = ytt['ratio_sell_rent'] /12
ax=ytt[['ratio_sell_rent_year','zip_code_number']].boxplot(by='zip_code_number', figsize=[25,8], rot=45)
ax.set_ylim([0,50])
像 1019/25、1032/6 和 1102/8 这样的邮政编码似乎投资回收期较短,平均为 15 年。
与要价 ML 模型类似,我使用租金模型来获得室内面积超过 100 平方米、室外面积超过 5 平方米且比率 _ 销售 _ 租金 _ 年值较低的房屋:
ratio_sell_rent_year ratio_sell_rent rent_prediction price outdoor_space living_space
7.932343 95.188121 3571.874268 340000.0 46.0 166.0
href: [https://www.funda.nl/koop/amsterdam/huis-40067181-moestuinlaan-12/?navigateSource=resultlist](https://www.funda.nl/koop/amsterdam/huis-40067181-moestuinlaan-12/?navigateSource=resultlist)
我不知道那栋房子的租金价格是多少,但我发现它旁边有一栋非常相似的房子这里。带家具、约 50 平方米大的房子租金为 7000 欧元。我实际上从外面去看了那栋房子,看起来像是我喜欢住的房子,但是当我们联系荷兰房地产经纪人时,房子已经卖完了。可悲的是,在阿姆斯特丹找房子的最佳方式似乎不是花里胡哨的 ML,而是快速行动😅。
有用的链接
- 查看荷兰的房价,以及基于 ML 模型的估计范围价格: huispedia.nl
- 查看阿姆斯特丹房价每平方米地图: maps.amsterdam.nl
- 查看 Mike 关于在阿姆斯特丹买房的精彩帖子:https://medium . com/@ MTO Connor 3/exploring-housing-prices-in-Amsterdam-b1d 3848 BDC 01
字节对编码——现代自然语言处理的黑马
1994 年首次推出的一种简单的数据压缩算法为当今几乎所有先进的 NLP 模型(包括 BERT)提供了增压。
背景
在 NLP 领域,过去几年是一段激动人心的时光。从稀疏的基于频率的词向量到密集的语义词表示预训练模型的演变,如 Word2vec 和 GloVe 为学习词义奠定了基础。多年来,它们作为可靠的嵌入层初始化,在缺乏大量特定任务数据的情况下训练模型。由于在维基百科上预先训练的单词嵌入模型要么受到词汇量的限制,要么受到单词出现频率的限制,像athazagoraphobia
这样的罕见单词将永远不会被捕获,从而导致在文本中出现未知的<unk>
标记。
处理生僻字
抛开字符级嵌入不谈,爱丁堡大学的研究人员通过使用字节对编码(BPE)在神经机器翻译中应用子词单元,在解决生僻字问题上取得了第一次真正的突破。今天,受 BPE 启发的子词标记化方案已经成为大多数高级模型的规范,包括非常流行的上下文语言模型家族,如 BERT 、 GPT-2 、罗伯塔等。有些人把伯特称为新时代的开端,然而,我认为 BPE 是这场竞赛中的一匹黑马,因为它在现代 NLP 模型的成功中没有得到应有的关注。在本文中,我计划更详细地介绍字节对编码是如何实现的,以及它为什么工作!
字节对编码的起源
像许多其他受传统科学启发的深度学习应用一样,字节对编码(BPE)子词标记化也深深植根于一种简单的无损数据压缩算法中。Philip Gage 在 1994 年 2 月版的 C Users Journal 的文章“A New Algorithm for Data Compression”中首次介绍了 BPE,这是一种数据压缩技术,它通过用一个不在数据中出现的字节替换常见的连续字节对来工作。
将 BPE 重新用于子词标记化
为了执行子词标记化,BPE 在其实现中被稍微修改,使得频繁出现的子词对被合并在一起,而不是被另一个字节替换以实现压缩。这将基本上导致罕见的单词athazagoraphobia
被分成更频繁的子单词,例如['▁ath', 'az', 'agor', 'aphobia'].
**第 0 步。**初始化词汇。
**第一步。**将语料库中的每个单词表示为字符的组合以及特殊的单词结束标记</w>
。
**第二步。**迭代统计词汇表所有记号中的字符对。
**第三步。**合并最频繁出现的对,将新字符 n-gram 添加到词汇表中。
**第四步。**重复步骤 3,直到完成期望数量的合并操作或达到期望的词汇大小(这是一个超参数)。
是什么让 BPE 成为秘制酱?
BPE 带来了字符和单词级混合表示之间的完美平衡,这使得它能够管理大型语料库。这种行为还支持使用适当的子词标记对词汇表中的任何罕见单词进行编码,而不会引入任何“未知”标记。这尤其适用于像德语这样的外语,在德语中,许多复合词的存在会使学习丰富的词汇变得困难。有了这种记号化算法,现在每个单词都可以克服他们对被遗忘的恐惧(athazagoraphobia)。
参考
- 菲利普·盖奇,一种新的数据压缩算法。《多布斯博士杂志》
- 森里奇(r .)、哈多(b .)、伯奇(a .)(2015 年)。具有子词单元的生僻字的神经机器翻译。 arXiv 预印本 arXiv:1508.07909 。
- Devlin,j .,Chang,M. W .,Lee,k .,& Toutanova,K. (2018 年)。Bert:用于语言理解的深度双向转换器的预训练。 arXiv 预印本 arXiv:1810.04805 。
- 刘,y .,奥特,m .,戈亚尔,n .,杜,j .,乔希,m .,陈,d,…和斯托扬诺夫,V. (2019)。Roberta:稳健优化的 bert 预训练方法。 arXiv 预印本 arXiv:1907.11692 。
数据科学的 c?
在数据科学领域,有许多语言可以用于统计分析和机器学习。通常,在这些情况下,语言的选择仅仅依赖于语言能够提供的功能。流行的选择包括像 R 和 Python 这样的统计语言。面向对象的编程语言经常被忽略,因为与函数式语言相比,它们的结构很难处理。
这一点在现代计算公式中最重要的语言之一 c 语言中表现得最为真实。
除非你曾经在岩石下编程,即使你曾经这样做过,你也可能听说过 C。C 是一种非常低级的语言,它也具有灵活进入真正高级开发领域的优势。虽然 C 语言是通用的,但 C 语言通常需要很长时间才能达到高水平。
这就是为什么有那么多语言是由 C 编写和解释的,比如 Python。但如果 Python 对数据科学如此伟大,为什么它的母亲不能持有同样的观点?
在很多方面,C 对于数据科学来说是完全可以接受的。这是因为像 C 的商标操作这样的低级语言是移动和管理数据的,因为这是低级语言的最大部分。但是确实有很多属性使得 C 语言不如 Python 这样的语言可行,例如。
实际上面向对象
尽管 Python 确实是面向对象的,但 Python 也拥有许多功能强大的特性。在一般的软件中,这往往是一个共同的主题。一种语言没有必要非此即彼,那么为什么不把两者的独特部分结合起来呢?
另一方面,C 天生就是百分之百通用的,但不管怎样,这对数据科学来说不一定是可怕的,但肯定可以更好一点。这不仅让初学者更加困难,也让数据科学家更加困难。当在数据科学中来回工作时,拥有一种具有更多函数属性的语言,函数可以在类之外运行,而不需要不断的回调,肯定会容易得多。
c 很难
从来不推荐 C 作为你的第一语言是有原因的;与 Python 等解释型语言以及其他语言相比,C 语言无疑是最难的语言之一。而且机器学习编程可能会出奇的难,尤其是在没有库的情况下从头开始。随之而来的是 Cs 最大的缺点,以及将 C 用于数据科学的致命弱点:
有这么多更简单、更好的语言(针对 DS)
那么为什么要用 C 呢?
除了很难写之外,C 语言也很难读,尤其是对于那些有大量数学运算的混乱的程序员来说。在大多数情况下,没有必要仅仅为了使用 c 就把能够阅读你的代码的程序员的数量分成 1/5,记住这一点,c 肯定有一些可取之处。
为什么它对数据科学有好处
在笔记本之外,在管道和数据软件工程领域,当机器学习算法本身也是用 C 语言编写时,许多强大的 C 代码基础会显著受益。对于使用 DS 的软件工程来说,C 语言对于知道如何使用它的每个人来说绝对是天赐之物。由于 Python 的速度问题,Python 通常在很多密集的情况下表现不佳。
除此之外,使用 C 的 Python 包的数量也令人印象深刻。不仅如此,就相对高级的编程而言,C 通常是最快的选择。
使用 C
我使用 C 已经很长时间了,但是我从来没有在数据科学中使用过 C。我最接近这样的事情是能够读写 CSV 文件。
但凡事都有第一次。
带着这个想法,我第一次去读 CSV。这相对简单,如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE* stream = fopen("l", "r");
char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp = strdup(line);
printf("Field 3 would be %s\n", getfield(tmp, 3)); return l;
}
}
现在是时候尝试一种算法了。我不想花太多的时间去创建一个构造函数,因为多亏了内核执行,我们可以把每个类命名为 main 并以这种方式运行函数。
int main()
{
int summation(arr) {
int arr[MAX_SIZE];
int i, n, sum=0;
for(i=0; i<n; i++)
{
scanf("%d", &arr[i]);
}
for(i=0; i<n; i++) { sum = sum + arr[i]; } return sum; }int length(arr){for(i=0; i<n; i++) { sum = sum + 1;
}
return sum;
}**int** llsq(**int** x[], **int** y[],xt[])
{
x = m.x
y = m.y
# Summatation of x*y
xy = x .* y
sxy = sum(xy)
# N
n = length(x)
# Summatation of x^2
x2 = x .^ 2
sx2 = sum(x2)
# Summatation of x and y
sx = sum(x)
sy = sum(y)
# Calculate the slope:
slope = ((n*sxy) - (sx * sy)) / ((n * sx2) - (sx)^2)
# Calculate the y intercept
b = (sy - (slope*sx)) / n
# Empty prediction list:
y_pred = []
for i in xt
pred = (slope*i)+b
append!(y_pred,pred)
return y_pred;}}
所以我认为,从创建一个函数来完成获取和操作数据所需的许多事情所用的代码行来看,C 语言显然不太适合数据科学。并不是说 C 在数据科学中没有一席之地,但是在很多方面,在数据科学和机器学习的特定情况下,使用更简单的语言比使用 C 容易得多,从而证明使用像 C 这样的低级语言是正确的。
通常,统计被区分为高级的函数式编程。这是有充分理由的,因为用 C 编写与我们用 Python、R 和 Scala 编写的算法相似的算法尤其困难,并且需要更多的方法。
计算相似性——简而言之,最相关的指标
Photo by Karolina Grabowska on Pexels
许多数据科学技术都基于测量对象之间的相似性和不相似性。例如,K-最近邻使用相似性来分类新的数据对象。在无监督学习中,K-Means 是一种聚类方法,它使用欧几里德距离来计算聚类质心与其指定的数据点之间的距离。推荐引擎使用基于邻居的协作过滤方法,该方法基于与其他用户的相似性/不相似性来识别个人的邻居。
在这篇博文中,我将看看实践中最相关的相似性度量。可以用多种方式来测量对象之间的相似性。
通常,我们可以将相似性度量分为两个不同的组:
- 基于相似性的指标:
- 皮尔逊相关
- 斯皮尔曼相关
- 肯德尔氏τ
- 余弦相似性
- 雅克卡相似性
2.基于距离的指标:
- 欧几里得距离
- 曼哈顿距离
基于相似性的度量
基于相似性的方法确定具有最高值的最相似的对象,因为这意味着它们生活在更近的邻域中。
皮尔逊相关
相关性是一种研究两个定量连续变量之间关系的技术,例如年龄和血压。皮尔逊相关系数是与线性关系的强度和方向相关的度量。我们用以下方式计算向量 x 和 y 的度量:
在哪里
皮尔逊相关可以取值范围从-1 到+1。只有直接相关的增加或减少不会导致 1 或-1 的皮尔逊相关。
Source: Wikipedia
用 Python 实现:
import numpy as np
from scipy.stats import pearsonr
import matplotlib.pyplot as plt# seed random number generator
np.random.seed(42)
# prepare data
x = np.random.randn(15)
y = x + np.random.randn(15)# plot x and y
plt.scatter(x, y)
plt.plot(np.unique(x), np.poly1d(np.polyfit(x, y, 1))(np.unique(x)))
plt.xlabel('x')
plt.ylabel('y')
plt.show()
# calculate Pearson's correlation
corr, _ = pearsonr(x, y)
print('Pearsons correlation: %.3f' % corr)
皮尔逊相关系数:0.810
斯皮尔曼相关
Spearman 相关就是所谓的非参数统计,即分布不依赖于参数的统计(服从正态分布或二项式分布的统计就是参数统计的例子)。通常,非参数统计对数据进行排序,而不是取初始值。斯皮尔曼相关系数就是如此,其计算方法与皮尔逊相关类似。这些指标的区别在于,Spearman 的相关性使用每个值的排名。
为了计算 Spearman 相关性,我们首先需要将我们的每个数据映射到排名数据值:
如果原始数据为[0,-5,4,7],则排名值将为[2,1,3,4]。我们可以用下面的方法计算 Spearman 相关性:
在哪里
斯皮尔曼的相关性基准单调关系,因此它可以有完美的非线性关系。它可以取值范围从-1 到+1。下面的情节阐明了皮尔逊和斯皮尔曼相关性之间的区别。
Source: Wikipedia
对于数据探索,我建议计算皮尔逊和斯皮尔曼的相关性。两者的比较会产生有趣的发现。如果 S>P(如上图),说明我们是单调关系,不是线性关系。由于线性简化了将回归算法拟合到数据集的过程,我们可能希望使用对数变换来修改非线性的单调数据,使其看起来是线性的。
用 Python 实现:
from scipy.stats import spearmanr
# calculate Spearman's correlation
corr, _ = spearmanr(x, y)
print(‘Spearmans correlation: %.3f’ % corr)
斯皮尔曼相关系数:0.836
肯德尔氏τ
肯德尔的τ和斯皮尔曼的相关系数很相似。这两个度量都是关系的非参数度量。具体来说,Spearman 和 Kendall 的系数都是基于排名数据而不是原始数据计算的。
与 Pearson 和 Spearman 的相关性类似,Kendall 的 Tau 总是在-1 和+1 之间,其中-1 表示两个变量之间的强负关系,1 表示两个变量之间的强正关系。
尽管 Spearman 和 Kendall 的测量值非常相似,但选择 Kendall 的测量值具有统计学优势,因为在使用较大样本量时,Kendall 的 Tau 具有较小的可变性。然而,Spearman 的度量在计算上更高效,因为 Kendall 的 Tau 是 O(n),而 Spearman 的相关性是 O(nLog(n))。
第一步是对数据进行分级:
然后我们计算肯德尔的τ值为:
其中 sgn 采用与排序值的差异相关联的符号。我们可以写
如下所示:
的可能结果
是-1,0,+1。这些相加给出了 x 和 y 的等级指向相同方向的次数的比例。
用 Python 实现
# calculate Pearson’s correlation
from scipy.stats import kendalltau
corr, _ = kendalltau(x, y)
print(‘Kendalls tau: %.3f’ % corr)
肯德尔斯τ:0.695
余弦相似性
余弦相似度计算两个向量之间角度的余弦。为了计算余弦相似性,我们使用以下公式:
回想一下余弦函数:左边的红色向量指向不同的角度,右边的图形显示了结果函数。
Source: mathonweb
因此,余弦相似度可以取-1 和+1 之间的值。如果向量指向完全相同的方向,余弦相似度为+1。如果向量指向相反的方向,余弦相似度为-1。
Source: O’Reilly
余弦相似度在文本分析中非常普遍。它用于确定文档之间的相似程度,而不考虑文档的大小。TF-IDF 文本分析技术有助于将文档转换成向量,其中向量中的每个值对应于文档中一个单词的 TF-IDF 得分。每个单词都有自己的轴,余弦相似度决定了文档的相似程度。
用 Python 实现
我们需要使用来改变向量 x 和 y 的形状。reshape(1,-1) 计算单个样本的余弦相似度。
from sklearn.metrics.pairwise import cosine_similarity
cos_sim = cosine_similarity(x.reshape(1,-1),y.reshape(1,-1))
print('Cosine similarity: %.3f' % cos_sim)
余弦相似度:0.773
雅克卡相似性
余弦相似度用于比较两个实值向量,而 Jaccard 相似度用于比较两个二元向量(集)。
在集合论中,看到公式的可视化通常是有帮助的:
我们可以看到 Jaccard 相似性将交集的大小除以样本集的并集的大小。
余弦相似度和雅克卡相似度都是计算文本相似度的常用度量。计算 Jaccard 相似性在计算上更昂贵,因为它将一个文档的所有术语与另一个文档匹配。Jaccard 相似性在检测重复项时非常有用。
用 Python 实现
from sklearn.metrics import jaccard_score
A = [1, 1, 1, 0]
B = [1, 1, 0, 1]
jacc = jaccard_score(A,B)
print(‘Jaccard similarity: %.3f’ % jacc)
雅克卡相似度:0.500
基于距离的度量
基于距离的方法优先考虑具有最低值的对象,以检测它们之间的相似性。
欧几里得距离
欧几里德距离是两个向量之间的直线距离。
对于两个矢量 x 和 y,可以计算如下:
与余弦和 Jaccard 相似性相比,欧几里德距离在 NLP 应用的上下文中并不经常使用。它适用于连续的数值变量。欧几里德距离不是比例不变的,因此建议在计算距离之前缩放数据。此外,欧氏距离会成倍增加数据集中冗余信息的影响。如果我有五个高度相关的变量,我们将这五个变量都作为输入,那么我们将用五来加权这个冗余效应。
用 Python 实现
from scipy.spatial import distance
dst = distance.euclidean(x,y)
print(‘Euclidean distance: %.3f’ % dst)
欧几里德距离:3.273
曼哈顿距离
与欧几里得距离不同的是曼哈顿距离,也称为“城市街区”,即一个向量到另一个向量的距离。当您无法穿过建筑物时,您可以将此度量想象为计算两点之间距离的一种方法。
我们计算曼哈顿距离如下:
绿线给出的是欧几里德距离,而紫线给出的是曼哈顿距离。
Source: Quora
在许多 ML 应用中,欧几里得距离是选择的度量。然而,对于高维数据,曼哈顿距离是优选的,因为它产生更稳健的结果。
用 Python 实现
from scipy.spatial import distance
dst = distance.cityblock(x,y)
print(‘Manhattan distance: %.3f’ % dst)
曼哈顿距离:10.468
摘要
这篇博文概述了实践中使用的最相关的相似性度量。没有简单的如果-那么流程图来选择合适的相似性度量。我们首先需要理解和研究这些数据。然后,对于给定的数据科学问题,找到量化相似性的正确方法总是一个案例一个案例的决定。
参考资料:
https://bib.dbvis.de/uploadedFiles/155.pdf
http://text2vec.org/similarity.html
使用移位β几何模型计算客户终身价值
Phot by Ihor Malytskyi on Unsplash
客户终身价值(CLV)是一个关键指标,被视为公司的北极星指标和所有综合 KPI,用于提供以下信息:
- 营销活动——我们应该花多少钱来获得客户?
- 客户细分——谁是我们最有价值的客户,他们的人口统计和行为特征是什么?
- 业务的整体健康状况——我们的 CLV 如何随着时间的推移而变化?
- 公司总价值——我们如何评估我们的现有和未来客户的价值?
但是什么是 CLV 呢?
当前客户的所有未来现金流的现值
在高层次上,为了估算你的 CLV,你需要了解两个简单的客户属性;a 客户生命周期和他们产生的经常性收入。顾客支付的越多,他们作为顾客停留的时间越长,他们的 CLV 就越大。
本帖将关注更具挑战性的部分——衡量客户的生命周期,这需要你了解你的企业当前的保留率。
本文旨在提供一种端到端的稳健方法来估算客户的终身价值。
CLV 公式中的常见陷阱
以下公式通常用于计算大多数经常性收入业务的 CLV。
然而,这种方法有 3 个主要问题:
问题#1:未能考虑不确定性
该公式计算出一个表示预期客户终身价值(或平均值)的数字。它忽略了我们估计中的任何不确定性。例如,在 SaaS 的企业中,客户对收入的贡献可能会有很大的不同,尤其是如果您有不同的服务计划(基本与高级)。
问题#2:恒定的保留率
可以说,最重要的问题是在你的客户中使用一个总留存率。所提议方法的本质是考虑不同客户的不同保留率。稍后会有更多内容。
问题#3:一刀切
2 固有的商业维度应该影响你的 CLV 方法。
**契约性与非契约性:**在契约性业务(如网飞、SaaS、信用卡)中,明显观察到客户流失。例如,大多数 SaaS 客户都是基于订阅的,因此客户必须取消订阅才能流失。非合同性企业(如在线零售、杂货店)不知道客户的最后一次购买是否真的是他们的最后一次购买,或者他们最终是否会再次购买。
**连续 vs 离散:**交易频率是第二维度。在的网飞和健身俱乐部等离散支付环境中,客户以固定周期(即每月、每年)支付。在持续的支付环境中,如亚马逊、信用卡,支付更不可预测。例如,尽管信用卡公司知道你何时流失(合同规定的),但他们不知道你在某个月产生交易的频率。
传统上预测保留
上述问题都会影响我们如何评估客户的生命周期。 这篇文章的剩余部分将展示一种更可靠的方法来评估你的客户的保留率,特别是在契约式的离散业务中。
数据
假设有一个跟踪逐年保持率的混合客户表。绿色值反映了当前活跃的客户。
Annual Customer Cohort Retention
保留率、流失率和存活率
保留率反映了在随后的周期中存活下来的客户的百分比。流失率是留存率的补充(即 1 减去留存率)。存活率反映了自开始阶段以来,从存活到的客户的百分比。在时间 t 的存活率可以定义为:
Survival at time t where r_t = retention rate at time t
让我们来计算我们最老的群组——群组 0——的保留率和流失率:
Annual Retention and Churn Rates for Cohort 0r1 = 84% (840 / 1000) --> c1 = 1 - .84 = 16%
r2 = 73% (618 / 840) --> c2 = 1 - .73 = 27%
r3 = 92% (570 / 618) --> c3 = 1 - .92 = 8%
r4 = 91% (519 / 570) --> c4 = 1 - .91 = 9%Average Retention = 85%
相同群组的最终存活率:
Annual Survival Rates for Cohort 0
S1 = r1 = 84%
S2 = r1 * r2 = 84% * 73% = 61%
S3 = r1 * r2 * r3 = 84% * 73% * 92% = 57%
S4 = r1 * r2 * r3 * r4 = 84% * 73% * 92% * 91% = 52%
挑战变成预测保留率和存活率,超越我们最老的队列;我们不知道来自群组 0 的 519 个当前客户明年(第 5 年)会有多大比例存活。
我们如何将 4 年的数据和预测扩展到 5 年以上?
一种方法是采用所有年份的平均留存率并进行预测。
Forecast survival rate using average retention
上面的图表反映了我们每个队列的存活率。这些队列的平均保留率约为 84.4%,可用于使用生存公式预测所有时间 t 的存活率。
从使用平均保留率的图表中可以看出,到第 9 年,群组中只有约 20%的客户会保留下来(.844⁹)。下一节提出了预测保留的另一种方法。
移位贝塔几何分布
对于具有离散支付周期的合同业务,sGB 模型是预测留存率的好方法。尽管这篇文章不会涉及数学细节,但它将有助于围绕这种方法发展一些基本的直觉。
上面的公式是 sGB 在时间 t 的保留率。参数α,β需要以最适合我们报道数据的方式进行估计。让我们围绕公式建立一些直觉:
Assume α = 2 and β = 10:r1 = (10+1-1) / (2+10+1-1) = 83.3%
r2 = (10+2-1) / (2+10+2-1) = 84.6%
...
r5 = (10+5-1) / (2+10+5-1) = 87.5%
请注意,保持率不仅不再是恒定的,而且*还会随着时间的推移而增加。*这微妙地提供了灵活性,以更准确地对保留行为建模,并且是使用 sGB 模型的关键增强。
保留异质性对生存曲线的影响
因为流失率和保留率是互补的,了解其中一个使我们能够衡量另一个。β分布是一种灵活的分布,用于使用前面提到的参数α和β来模拟流失率。
下图使用 beta 分布,根据抽样的流失概率对生存曲线的类型进行了分类。每个象限都有一对图表——左边的图表是给定α和β的流失率,右边的图表是其对应的生存曲线。
Survival Curves using various churn rate distributions
以下是解释,展示了不同的流失率如何影响存活率。
模型开发—求解α和β
剩下的问题是*“我如何确定α和β参数对我的业务是什么?”。模型参数的最大似然估计* (MLE)允许我们估计最适合我们企业观察到的综合数据的参数。
Log-Likelihood Function
TL;DR 找出使上述函数的输出最大化的α和β的值
用概率方法求解α和β
有许多方法可以优化上面的对数似然函数,如 scipy、pymc3,甚至是 excels solver 加载项。然而,如果您想通过概率优化来考虑参数估计中的不确定性, pymc3 是一个很好的选择。使用 pymc3,您可以对后验分布进行采样,以查看我们的参数的可能值,如下所示。
结果:α和β后验分布
我们可以对后验分布进行采样,并可视化与我们求解的参数相关的不确定性:
Posterior Samples
我们可以看到,平均α ≈ 1.1 和平均β ≈ 5.3 将我们的参数平均放置在右上象限*。然而,由于队列规模相对较小,我们的估计存在不确定性,这反映出α < 1 极有可能导致我们的流失分布落入右下象限*。**
模型讨论和解释
在衡量终身价值之前,下一节将解释不断增长的保留率的价值。
不断增长的客户忠诚度
Which customer is more likely to survive into the next period?
我们以上面的两个客户为例。如果只知道客户与企业续签订阅的次数,那么哪个客户更有可能再次续签(即继续到下一期)?客户 B 已经证明了自己是一个忠诚的客户,一个明显喜欢你的产品的客户,因此有 9 次续订。您会预计客户 B 更有可能再次续订。我们可以通过使用我们估计的参数测量在 t=2 和 t=10 年的保留率来衡量这个概念。
Retention Rates at t=2 and t=10
注意在 t=10 奖励直觉时,记忆力如何提高。客户 B 续订到第 10 年的可能性为 92.7%,但客户 A 续订到第 3 年的可能性为 84.5%。
使用平均保留率忽略了客户忠诚度的长期增长
流失率分布
我们也可以使用后验参数样本的 beta 分布来绘制流失概率。
Churn Rate using Beta Distribution
上面的每条线反映了给定α和β的流失分布。洋红色线条反映了α和β都大于 1 的样品(通常平均流失率更高)。黑线反映了假设我们的平均参数(α ≈ 1.1,β ≈ 5.3)的流失率分布。相反,当α <1 but β > 1 时出现绿线。
预测存活率— sGB
Comparison of Forecasted Survival Rates
能够在任何时间 t 计算留存率意味着我们可以使用之前的生存公式计算任何时间 t 的存活率。上图反映了我们使用 sGB 预测的存活曲线与恒定保留率的对比。
假设保持率不变会低估我们客户的寿命,这反过来也会低估 CLV。
计算 CLV
我们现在不仅可以计算未来客户的预期寿命,还可以计算现有客户的;当前活跃的客户。现有客户的 CLV 可以表示为他们的剩余终身价值(RLV) 或剩余终身价值。将它们的未来价值折算成现值,就得到所谓的贴现预期剩余寿命 (DERL)。**
Discounted Expected Residual Lifetime
₂F₁function 引用了超几何函数,它可以从 scipy 库中导入 python:
**from scipy.special import hyp2f1**
与前面展示的不断增加的保留率非常相似,RLV 背后的直觉是,在其他所有因素不变的情况下,已续订 n 次的现有客户可能拥有更长的生命周期,从而拥有更高的剩余价值。因此,我们预计 DERL 将随着续约次数的增加而增加。
假设每位客户每年的现金流为 1000 美元,前 20 年每次续约后的 DERL 如下图所示:
Assuming annual cashflow per customer is $1,000 and 10% discount rate
箱线图反映了我们估计的不确定性。例如,对于一个进行了 2 次续订的活跃客户,我们估计 DERL 在 5000 美元到 5700 美元之间,中位数在 5300 美元左右。如果我们解出一个α和β,我们会得到一条直线。也就是说,请注意剩余价值随时间的增长趋势——本质上,我们正在量化客户忠诚度。新获得的客户(续订次数= 0)的 DERL 中值约为 4,500 美元,而进行了 19 次续订的活跃客户的 DERL 中值约为 8000 美元(高出 78%)。
当前客户的总 DERL
回头参考我们的群组表,我们可以看到我们的最老的群组(群组 0)已经进行了 4 次续订,每个客户的平均 DERL 约为 5,900 美元。此外,我们的最新群组(群组 3)仅与我们进行了 1 次续约,因此 DERL 为 4900 美元。
Total Residual Value Across Customer Base
因为上面显示的 DERL 值是每个客户的,,所以整个群组的残值是通过将 DERL 乘以该群组的当前活动客户数量*而获得的(绿色值)。所有群组的总和反映了您现有客户的总剩余价值。*
请注意,我们对中值求和;在现实中,建议要么对平均值求和,要么继续将不确定性投影到最后,在这一点上,您可以计算任何您喜欢的统计数据(平均值、中值、百分位数)。
我们所有活跃客户的总(中值)剩余价值约为 1420 万美元
此外,假设您的业务团队预测下一年将有突破性进展,新增 1,000 名客户。新客户进行了 0 次续订,因此每位客户的 DERL 约为 4500 美元。因此,我们估计这些未来客户的总终身价值为【450 万美元】(1000 * 4500 美元)。
结论
这篇文章旨在展示评估 CLV 时的三个考虑因素:
- 考虑不确定性;如果你的客户数据集只有少数几个客户,那么在建模终身价值时你就不那么确定了。
- sGB 模型是评估契约式离散企业的优秀方法;更直观地模拟保留时间和生命周期
- 假设所有条件相同,剩余生命周期价值比新客户更信任忠诚客户(老客户)。
这些考虑因素使您能够更准确地计算当前客户的总价值,并最终提供一个更加稳健和动态的指标来:
- 评估 A/B 测试实验
- 告知营销收购工作
- 为你的创业公司筹集下一轮资金!
来源
[1] 这个 CLV 公式怎么了?
[2] 如何预测客户保持率
[3] 客户群分析的概率模型
订阅业务的终身价值计算
Photo by Austin Distel on Unsplash
这是千真万确的,如果你不能衡量它,你就不能管理你的业务。基于订阅的业务的一个关键指标是终身价值(LTV)或客户终身价值(CLV)。简而言之,LTV 意味着在客户的一生中产生的总预期价值。让我们进一步分解这个概念:
- LTV 是一个期望值,这意味着它是平均的或统计推断的。
- LTV 衡量价值,即企业关心的价值指标,如收入、利润等。
- LTV 已经过了他的一生。例外的情况是,一家企业在一段时间后会终止与客户的关系😢,这是极不可能的,也是违背常识的。
在数学上,客户 LTV 可以表示为:
LTV calculation
其中v_i
代表价值,s_i
代表计费周期i
的留存率或存活率。计费周期可以是一周、一个月、一个季度,甚至一年,这取决于商业模式。周期总数N
代表利息的持续时间,也取决于商业模式。对于按年订阅的模式,N = 100
应该足够好了。从数学公式来看,我想你已经知道为什么 LTV 度规越来越受欢迎了。它同时衡量盈利能力(v_i
)和客户忠诚度或粘性(s_i
),并将它们很好地结合成一个指标。让我们用下面的玩具例子来说明计算。
LTV calculation
如表中所示,订阅产品在每个计费周期从客户身上获得 10 美元的价值。周期流失率为 30%,因此保留的客户百分比为 100%、70%、56%……因此,第 1、2、3 周期产生的有效客户价值为 10 美元、7 美元、5.6 美元……将所有产生的价值相加,总 LTV 约为 45 美元(40 个周期后该数字稳定下来)。
如您所见,计算非常直观。然而,对于一个真正的企业或产品来说,这可能一点也不简单。一种情况是v_i
可能会受到通货膨胀、商品成本波动、季节性等因素的影响。另一种情况是,观察到的账单周期总数可能不足以构建计算 LTV 所需的s_i
,这最有可能发生在年轻企业。在接下来的内容中,我将关注后一种情况,并展示如何使用更系统的方法来计算s_i
。
模拟存活率
我们通常不会直接获得存活率s_i
,而是从计费周期流失率c_i
入手。s_i
和c_i
的关系如下图所示。
Survival rate calculated from churn rate
显然,流失率在 0%(没有客户在该周期后流失)和 100%(每个客户在该周期后流失)之间,因此随着周期数的增加,存活率总是从 100%下降到 0%。有几种方法可以获得流失率c_i
。
1.经验计算
获取流失率最简单的方法就是根据历史观察值计算每个计费周期的流失率,也称为卡普兰-迈耶估计量 (KM 曲线),可以表示如下
其中d_i
是周期i
中的下降次数,n_i
是周期i
开始时的客户数。
这种方法直观且易于实施和计算,但是,它通常不适用于年轻的企业。具体来说,一个年轻的企业通常没有很多计费周期,没有大量的n_i
可用于计算流失率。下图显示了年轻企业和成熟企业之间的比较。请注意,对于年轻的企业,流失率比已建立的企业跨越的周期更少,并且在接近结束时变得更嘈杂,因为其总样本量n_i
在接近最后一个周期时变得越来越小,而对于已建立的企业来说,情况并非如此。你要知道,嘈杂的流失率更多的是一种短暂的影响。随着企业客户群的增长和稳定,将会有更多的客户数据可用,因此嘈杂的蓝色曲线应该越来越接近平滑的橙色曲线。
Churn Rate Comparison
至于计算,可以用 excel、SQL、Python、R 等。在 R 中,已经存在一个名为suvival
的包来简化生存分析,包括 KM 生存曲线计算。以 IBM Watson telco 客户演示数据集为例,我们可以用如下所示的几行代码计算并绘制 KM 存活率和流失率曲线。
(Left) Survival curve in black with 95% confidence band in gray (Right) Churn rate
如果你有兴趣了解更多关于 KM 曲线的知识,你可以看看 Lauren Oldja 写的一篇关于它的详细文章。
2.统计推断
正如前面的方法所指出的,我们不能真的把卡普兰-迈耶方法用于年轻的企业。那么,还有别的办法吗?是的,统计数据来拯救我们了。为了构建一个合理的生存曲线来估计只有几个周期可用的 LTV,我们需要进行统计推断。
与非参数 Kaplan-Meier 方法(其中没有估计参数)不同,统计推断是参数化的。其思想是,我们假设客户流失事件遵循一定的概率分布。常用的分布模型有指数、对数正态、威布尔、伽玛等。给定统计分布模型,然后您可以使用最大似然法来找到符合历史流失数据的最佳参数。在拟合之后,可以使用该模型推断未来周期的流失概率。R 中的survival
包也为生存模型拟合提供了很好很简单的工具。继续前面的例子,我们可以使用下面的代码来生成拟合的生存曲线
Survival curve using Weibull Model
正如你所看到的,拟合的生存变动是平滑的,我们能够用它来估计未来的存活率,用于 LTV 计算。此外,我们可以从曲线中得出一些有趣的指标。例如,我们预计 50%的客户将在第 120 周期前离开,如上面的蓝色虚线所示。您还可以计算生存曲线下的面积,以获得客户的平均终身任期期望。
3。机器学习
机器学习无处不在,预测未来。我们还可以利用它来计算流失率。事实上,它是我最喜欢的选择,因为我们可以针对这个问题使用各种机器学习技术,如特征工程,交叉验证,正则化等。
客户流失建模本质上是一个二元分类问题。有许多机器学习模型可以解决这个问题,但是,我使用逻辑回归,因为我们需要推断未来的流失率,因此看不见的计费周期和模型,如随机森林和梯度提升机器无法执行这种推断。以下代码使用了 H2O 机器学习包,并拟合了流失和周期之间的单变量逻辑回归模型。
(Left) Survival rate by cycle (Right) churn rate by cycle
正如我们所看到的,虽然这个简单的模型可以拟合生存和流失曲线的整体趋势,但它并不能很好地拟合 cycle 1。为了减轻这种情况,一个技巧是您可以添加一个二进制特性special_cycle
,对于周期 1 为 1,其余为 0。修改后的代码和结果如下。
(Left) Survival rate by cycle (Right) churn rate by cycle
结论
在本帖中,我们讨论了订阅业务的 LTV 公式和计算方法,并重点讨论了计算存活率/流失率的 3 种不同方法。我希望你喜欢这篇文章,并让我知道你的想法!
计算 Yolo (v3)层的损耗
Yolo v3 模型的实现
Yolov3 是最先进的对象检测模型,使其成为快速准确的实时对象检测模型。有没有想过 Yolov3 车型的症结在哪里?秘密在于 Yolo 模型的 Yolo 层。
Yolov3 架构
Yolov3 模型接收 416x416 的图像,用经过训练的 Darknet-53 主干对其进行处理,并在三个尺度上产生检测。在每个比例下,输出检测的形状为(批量大小 x 锚盒数量 x 网格大小 x 网格大小 x 85 维)。
Output detections of shape (batch_size x num_of_anchor_boxes x grid_size x grid_size x 85 dimensions)
Yolov3 的架构在https://towardsdatascience . com/Yolo-v3-object-detection-53 FB 7d 3 bfe 6 b的 Yolo v3 网络架构图中描绘得非常好(请阅读这个故事了解 Yolo v3 架构)。在该图描述的所有组件中,有 3 个检测层,它们也是 Yolo 层。三个 Yolo 层中的每一层负责计算三个不同尺度的损耗。然后将三个不同尺度的损耗相加,用于反向传播。每个 Yolo 层利用 85 个维度来计算损耗。前 4 个维度对应于边界框的中心线、中心线、宽度和高度。接下来的 1 维对应于边界框的客观性分数,最后的 80 维对应于边界框的独热编码类预测。计算以下 4 种损失:
- 包围盒的中心线、中心线、宽度和高度的 MSE
2.包围盒的客观分数的 BCE
3.包围盒的无客观性分数的 BCE
4.包围盒的多类预测的 BCE
详细实现代码由https://towards data science . com/yolo-v3-object-detection-53 FB 7d 3 bfe 6 b。解释和张量形状被附加以帮助解释下面的代码。
Yolo 层采用一个复杂的形状特征(批量大小 x 锚盒数量 x 网格大小 x 网格大小 x 85 个维度)来计算上述 4 个损失。首先,基于标记的目标,它首先创建形状的 Obj 掩码((batch _ size x num _ of _ anchor _ boxes x grid _ size x grid _ size x 85 维)以指示哪些边界框应该包含预测,并创建形状的 Noobj 掩码(batch _ size x num _ of _ anchor _ boxes x grid _ size x grid _ size x 85 维)以指示哪些边界框不应该包含预测。有了掩模,可以成功地将目标与相同形状的预测进行比较,以计算四个损失。具体实现见下文。
YoloLayer Class from models.py from https://towardsdatascience.com/yolo-v3-object-detection-53fb7d3bfe6b
从数据集中选取 batch_size 目标,如下所示:
A batch_size targets
基于标记的目标,下面的 build_targets 函数创建形状的 obj 掩码(batch _ size x num _ of _ anchor boxes x gridsize x gridsize)来指示哪些边界框应该包含预测,并创建形状的 noobj 掩码(batch _ size x num _ of _ anchor boxes x gridsize x gridsize)来指示哪些边界框不应该包含预测。
Build_targets function from utils.utils.py from https://towardsdatascience.com/yolo-v3-object-detection-53fb7d3bfe6b
逐步手动计算最大似然估计
我写这个是因为我找不到很多教程来展示这个计算的详细数学。所以我决定把它彻底写出来,并展示所有的步骤,以防有一段时间没有做过微积分的人需要一点指导。
高斯分布很容易通过以平均值为中心的一组数据和围绕平均值的点的对称分布来识别。在分析数据时构建高斯分布,其中每个点都是独立实验的结果,这有助于可视化数据并应用于类似的实验。为了找到一组数据的最佳分布,计算最大似然估计(MLE)。
用于创建分布的两个参数是:
- 平均值 (μ)(mu)— 该参数决定分布的中心,较大的值导致曲线进一步向左平移。
- 标准偏差(σ)(sigma) — 该参数决定曲线的宽度,较大的值产生较短和较宽的曲线,较小的值产生较细和较高的曲线。
简化高斯分布函数
似然估计函数:
高斯函数的 Subbing
拿走木头
用多点简化方程
对函数相对于 **μ(平均值)**求导
对函数相对于 σ 求导(标准偏差)
将等式设为零,以找到μ的最佳值
将等式设为零,以找到σ的最佳值
在 R 中计算新客户和老客户
我最近遇到一个问题,我想计算新客户和老客户。所以,我很自然地谷歌了一下,惊讶地发现我在 R 中找不到任何关于它的解决方案,这通常是大多数 R 博客/教程的问题,它们不是非常面向商业的。
由于在网上找不到解决方案,我开始自己动手。我能够使用 DAX 和 Power Pivot 在 Excel 和 Power BI 中很快找到解决方案,但我想在 r 中完成它。实际上,我有点不好意思承认这个解决方案非常简单。我期望你对 R 中的 Tidyverse 包有一些基本的了解,主要是 dplyr 来理解本教程。
在继续之前,我们首先需要决定如何定义一个客户是“新客户”还是“回头客”
新客户
任何过去没有与我们合作过的客户都将被归类为“新客户”
回头客
任何过去与我们合作过的客户,如果在当前期间再次与我们合作,都被视为“回头客”
加载库
library(tidyverse)# For data manipulation
library(readxl) # Read in Excel File
library(lubridate)# Working with Dates
加载和查看数据
我们使用下面的代码读入销售数据,并查看一下数据类型。
**sales_data** <- read_xlsx(path="C:\\Users\\ACER\\Downloads\\sale_data.xlsx")glimpse(sales_data)
我们得到以下输出。销售日期显示为日期时间变量,而客户 ID 被识别为数字类型。
我们现在将使用 dplyr 中的 mutate 函数将“销售日期”和“客户 ID”列分别更改为日期和字符类型。
**sales_data** <- sales_data%>%
mutate(`Sale Date` = dmy(`Sale Date`),
`Customer ID`=as.character(`Customer ID`))
现在我们的数据已经准备好了,我们要做的第一件事就是计算每一行中每个客户的首次签约日期。这将决定他们在那个时间点是新客户还是回头客。
**sales_data** <- sales_data %>%
group_by(`Customer ID`)%>%
mutate(date_of_first_engagement=min(`Sale Date`))%>%
ungroup()
由于我们想计算每一行中每个客户的第一次接洽日期,我们将首先按“客户 ID”对数据进行分组,然后使用 mutate 函数计算他们在“销售日期”使用 min 函数与我们第一次接洽的时间。这基本上是在 r 中计算条件计算列的一种非常有用的方法。
一旦计算完成,我们将取消对它的分组,因为我们不想要任何基于“客户 ID”的进一步计算。下面是我们的数据集在计算完成后的样子
在第 10 行,客户“39099”于 2018 年 9 月 17 日与我们合作,但我们可以看到,他们与我们的首次合作日期是 2018 年 8 月 9 日,这意味着在 9 月 17 日,该客户是“回头客”,而在 8 月 9 日,他们是“新客户”。
使用这个逻辑,我们现在将创建一个新列——“客户状态”。我们将使用 case_when 函数,根据“销售日期”和“首次接洽日期”的差异,在每个时间点对每个客户进行分类
**sales_data** <- sales_data%>%
mutate(Customer_Status = case_when(`Date Interviewed`>date_of_first_engagement ~ "Returning",
`Date Interviewed` == date_of_first_engagement ~ "New",
TRUE ~ "Other"))
基本上,我们所做的是计算如果客户的“销售日期”大于客户的第一次合作日期,那么这意味着他们以前与我们合作过,因此是“回头客”,如果他们的“销售日期”等于他们的第一次合作日期,那么这意味着这是他们第一次与我们合作,因此在那个时间点上是“新客户”。以下是数据集的外观。
我们的数据终于准备好了!现在我们可以对它做一些有趣的分析。我想看看我们每个月有多少“新”和“回头客”。我们将使用 group by 和summary函数来得到这个结果
**New_and_Returning_Customers** <- sales_data%>%
group_by(floor_date(`Sale Date`,unit = 'month'))%>%
summarise
(New_Customers = n_distinct(`Customer ID`[Customer_Status=="New"]),Returning_Customers= n_distinct(`Customer ID`[Customer_Status=="Returning"]))
因为我想按月分组,所以我使用 lubridate 包中的 floor_date 函数将“销售日期”四舍五入到最近的月份,然后使用条件非重复计数来获得每月新老客户的唯一计数。
我们可以使用 ggplot2 包来制作一个简单的数据折线图
结论
现在我们已经了解了如何计算新客户和老客户,我们可以对他们进行各种分析。本教程的目的是让你了解如何以一种相对简单明了的方式进行计算。
在 Python 中计算字符串相似度
以任何方式、形状或形式比较字符串都不是一项简单的任务。除非它们完全相等,否则比较很容易。但大多数时候情况并非如此——最有可能的是,你想看看给定的字符串是否类似于学位,那完全是另一回事。
Photo by Tomasz Frankowski on Unsplash
让我们用一个例子来更深入地探讨这个问题。你有一个网页,它需要一些用户输入——假设出于某种原因,你决定使用文本字段而不是下拉菜单来显示位置信息。用户有可能会打错字,而您不希望错字存储在您的数据库中。你想要正确无误的版本。
但是你会如何着手纠正弦呢? 我的意思是你可以硬编码它,但是你真的要这么做吗?有太多的输入错误选项,硬编码通常不是一个好主意。
这就是本文的目的。我想让你们熟悉我最擅长的两种字符串匹配或相似性计算技术:
- 莱文斯坦距离
- 余弦相似性
第一个主要用于解决打字错误,我发现如果你想比较两个文档,它几乎没有用。这就是梯子的用处。恰恰相反,对错别字检测没用,但对一整句话,或者文档相似度计算很棒。
阅读完本文后,您将能够做到以下几点:
- 确定哪种相似性算法适合您的情况
- 用 Python 实现
好了,准备好潜水了吗? 走吧。
莱文斯坦距离
让我们从一个基本定义开始:
在信息论、语言学和计算机科学中,Levenshtein 距离是衡量两个序列之间差异的字符串度量。非正式地,两个单词之间的 Levenshtein 距离是将一个单词变成另一个单词所需的单个字符编辑(插入、删除或替换)的最小数量。[1]
用最简单的话来说,您想要计算需要对字符串 A 执行多少次转换才能使其等于字符串 B 。该算法也被称为 编辑距离 ,所以这可能是你更熟悉的术语。
要在 Python 中使用它,你需要安装它,比如说通过 pip :
pip install python-Levenshtein
仅此而已。现在让我们看看如何使用它。
因为’ Levenshtein '很难正确输入,而且我之前说过我主要用它来检测输入错误,这将是一个很好的第一个例子。但是首先,进口:
现在你可以计算距离了:
第一个打对了,第二个是我直接打出来的,你知道,没有先谷歌一下。乍一看,它们看起来一模一样,所以作为最终用户,您可能甚至不会注意到拼写错误。但是如果存储在某个数据库中,用于以后的分析,那就大不一样了。
我以前也说过,我不会对更长的字符串或整个文档使用这种算法,原因如下:
如你所见,两个句子传达了几乎相同的信息,但是从一个句子到另一个句子需要 20 次转换。所以,如果你已经设置字符串在低于某个阈值时自动匹配,20 可能不是那个阈值,因为它对于像这两个这样的简单短句来说太大了。
那是它的余弦兄弟来救援的地方。
余弦相似性
和以前一样,让我们从一些基本定义开始:
余弦相似性是内积空间的两个非零向量之间的相似性的度量,它度量它们之间角度的余弦。[2]
By Giphy: https://giphy.com/gifs/CiYImHHBivpAs/html5
我知道,这不是最干净的定义,但我觉得足够好了。它需要一些数学知识,如果你没有,请参考下面这篇文章(线性代数中的向量):
学习数据科学的基本线性代数技能—第 1/2 部分
towardsdatascience.com](/linear-algebra-essentials-with-numpy-part-1-af4a867ac5ca)
好吧,让我们进一步提炼。
根据定义,您应该首先计算两个矢量之间的角。但是你不能把一个句子,表示成 n 维空间中的一个向量。
你需要从所有你想计算相似度的“句子”中构造一个向量空间。这个向量空间将有多的维度,就像所有句子中唯一的单词加在一起一样多。
好吧,我们先导入,我会即时解释一切:
您将需要 string 模块来删除字符串中的标点符号——句子和句子和句子*。默认情况下,*是不同的,您希望避免这种情况。count vectorizer会负责将字符串转换成数字向量,这也很简洁。最后,由于这篇文章是用英语写的,你需要删除那些最常见的没有意义的单词——它们被称为停用词——比如“我”、“我”、“我自己”等等。
如果你不删除停用词,你会得到一个更高维的空间,向量之间的角度会更大——意味着更少的相似性——即使向量传达的信息几乎相同。
现在我将宣布一些任意的,在某种程度上相似的句子的列表。这是一个列表,因为向量空间将由所有唯一的单词创建,这将确保每个向量具有相同的维数,因为您无法计算不同维空间中向量之间的角度:
还记得进口吗? 我们进口了不少,是时候好好利用一下了。我将声明一个函数,它将执行以下操作:
- 从给定字符串中删除标点符号
- 将字符串小写
- 删除停用词
现在你实际上不需要一个循环来为每个句子应用那些变换,你可以使用内置的 映射 函数:
太好了,准备工作差不多完成了。现在,您将利用 计数矢量器 的能力来执行一些魔术(不是真正的)。它将在维空间中创建 k 个向量,其中 k 是句子的数量, n 是所有句子组合起来的唯一词的数量。然后,如果一个句子包含某个单词,则该值为 1,否则为 0:
准备工作到此结束。这太多了(有点像),但是值得。如果您现在从获得的数字向量计算余弦相似性,您将获得以下矩阵:
*对角线元素是 1,这是有意义的,句子 X 与句子 X 完全“相似”。然而,分割这个矩阵是不方便的,所以我决定定义一个函数来计算两个给定向量的相似性。请记住,***cosine _ similarity()**期望 2D 数组,输入向量默认为 1D 数组,所以这就是我们需要整形的原因:
为了确认一切正常:
太酷了。在现实世界的例子中,这可以用于向用户提供一些推荐,例如,基于他的评论与其他每个用户的评论的相似性。
在你走之前
计算数值向量之间的相似度并不难,诀窍是先把字符串转换成数值向量,在这个过程中丢弃一切不相关的东西。
作为一个练习,这将是一个好主意,找到一些未标记的电子邮件或其他一些文本的数据集,并尝试使用相似性度量将它们以某种方式分组。你看一下 TF-IDF 可能也是个好主意,因为我在本文中没有解释它。
无论如何,感谢你的阅读,我希望你能从中得到一些有用的东西。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
* [## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)*
参考
[1]https://en.wikipedia.org/wiki/Levenshtein_distance
https://en.wikipedia.org/wiki/Cosine_similarity
计算这个假期你在飞机上坐在前任旁边的几率
剧透:这比你一生中被闪电击中一次的可能性还小!
Credit Suhyeon Choi at Unsplash
最近,我坐上了从波士顿到 Ft 的飞机。劳德代尔来我家度假。我迟到了,是最后一批被允许登机的人之一。我走到飞机后部,找到我的座位,问坐在过道上的人是否可以让我坐在中间的座位上。她从笔记本电脑上抬起头——是我的前任!当我们在飞机上叙旧的时候,我不停地想,我们不太可能各自订了票,但是我们最后却坐在了一起。这种可能性有多大?让我们来计算一下!
我们需要做三件事才能坐到一起:
1)我们决定在同一天起飞
我们在同一天买了同一趟航班
航空公司给我们安排了相邻的座位
我们可以把我们坐在一起的概率写成:
在这个分析中,我们将做一个简化的假设,即航空公司随机分配座位给乘客,即使实际上有人可以支付额外的费用来获得他们选择的座位。
假设我们两个人都打算在 2019 年 12 月 16 日到 12 月 20 日这一周回家旅行,我们随机地统一决定了我们的旅行日期。类似地,让我们假设一天有 5 个航班选项,我们随机地统一选择航班。我们的等式现在是:
我们需要计算一家航空公司分配给我们相邻座位的概率。飞机可以有许多不同的座位安排,但让我们假设所有的飞机都有 30 排,每排有两组 3 个座位。这实际上非常接近精神航空公司运营的空客 A320 的实际座位图。
计算这个概率似乎令人生畏,但我们现在可以通过假设飞机只有一排来简化事情。在这种情况下,我和我的前任有 15 (6 选 2)对可能的座位,但其中只有 4 对是相邻的座位(左侧和右侧的靠窗和中间、过道和中间)。所以,拿到相邻座位的概率是 4/15。
如果有两排,则有 66 (12 选 2)对可能的座位,但其中只有 8 对是相邻的(每排 4 对)。我们可以从这种模式推断出下面的公式,其中 n 是飞机上的行数:
Probability of getting adjacent seats at random. n is the number of rows on the plane.
代入这个公式,概率是 0.007449。我们也可以通过模拟来验证这个答案。
为了得到最终的答案,我们代入我们的第一个方程,得到 0.0000119 或者大约十万分之一。这大约是你一生中 30 次少一次被雷击的概率!
一路平安,假期愉快。我希望你用这些时间与朋友和家人相聚:)
用 Python 计算语义品牌得分
大数据时代的品牌智能
语义品牌得分 ( SBS )是一个新颖的指标,旨在评估一个或多个品牌在不同背景下的重要性,只要有可能分析文本数据,甚至大数据。
相对于一些传统措施的优势在于,SBS 不依赖于对小样本消费者进行的调查。这一衡量标准可以根据任何文本来源进行计算,例如报纸文章、电子邮件、推文、在线论坛、博客和社交媒体上的帖子。这个想法是通过对大文本数据的分析来捕捉洞察和诚实信号 。消费者或其他品牌利益相关者的自发表达可以从他们通常出现的地方收集——例如,如果研究博物馆品牌的重要性,可以从旅游论坛收集。这样做的好处是减少了因使用问卷而产生的偏见,因为受访者知道他们正在被观察。SBS 还可以适应不同的语言,并研究特定单词或一组单词的重要性,不一定是“品牌”。
“品牌”可以是一个政治家的名字,或者是代表一个概念的一组词(例如,“创新”的概念或者一个公司的核心价值)。该指标用于评估一个新品牌取代一个旧品牌时发生的转变动态[1]。语义品牌得分也有助于将品牌的重要性与其竞争对手的重要性联系起来,或者分析单个品牌的重要性时间趋势。在一些应用中,分数被证明对于预测目的是有用的;例如,已经发现政治候选人在网络媒体上的品牌重要性与选举结果之间存在联系[4],或者博物馆品牌的重要性与游客数量的趋势之间存在联系[6]。使用 SBS 的出版物的更新列表是 ,可在此处 获得。
品牌重要性的三个维度
SBS 衡量品牌重要性,这是品牌资产的基础[1]。事实上,这一指标部分受到了众所周知的品牌资产概念化以及品牌形象和品牌意识结构的启发(参见凯勒的工作)【2】。
品牌重要性从三个维度来衡量:流行度、多样性和连通性。流行度衡量品牌名称的使用频率,即品牌被直接提及的次数。多样性衡量与品牌相关的词语的多样性。连接性代表品牌在其他单词或词组(有时被视为话语主题)之间架起连接桥梁的能力。
关于 SBS 的更多信息可以在这个网站【5】,在维基百科,或者阅读这篇论文【1】中找到。在本文中,我不会在这个指标上花太多时间,因为我的重点是描述使用 Python 3 计算它的主要步骤。
数据收集和文本预处理
语义品牌得分的计算需要结合文本挖掘和社会网络分析的方法和工具。图 1 说明了主要的初步步骤,包括数据收集、文本预处理和构建单词共现网络。
对于本入门教程,我们可以假设相关的文本数据已经收集并组织在一个文本文件中,其中每一行都是一个不同的文档。我将把两个想象的品牌*(‘BrandA’*和【T20’‘BrandB’)插入随机的英文文本中。
使用 Python 3 计算语义品牌得分
此演示的更新 GitHub 库可在 此处 获得。在那里,您将找到一个 Python 笔记本,以及示例文件。
**# Read text documents from an example CSV file**
import csv
readfile = csv.reader(open("AliceWonderland.csv", 'rt', encoding="utf8"), delimiter = "|", quoting=csv.QUOTE_NONE)texts = [line[0] for line in readfile]**#I imported 4 Chapters of Alice in Wonderland**
print(len(texts))
print(texts[0][:200])
我将文本文件作为文本文档列表( texts )导入 Python,现在对其进行处理以删除标点符号、停用词和特殊字符。单词被小写并拆分成记号,从而获得一个新的 texts 变量,这是一个列表的列表。更复杂的文本操作预处理总是可能的(比如移除 html 标签或’ # '),为此我推荐阅读 Python 中自然语言处理的众多教程之一。停用词列表取自 NLTK 包。最后,单词词缀通过滚雪球式词干去除。
**##Import re, string and nltk, and download stop-words**
import re
import nltk
import string
from nltk.stem.snowball import SnowballStemmer**#Define stopwords**
#nltk.download("stopwords")
stopw = nltk.corpus.stopwords.words('english')**#Define brands (lowercase)**
brands = ['alice', 'rabbit']**# texts is a list of strings, one for each document analyzed.****#Convert to lowercase**
texts = [t.lower() for t in texts]
**#Remove words that start with HTTP**
texts = [re.sub(r"http\S+", " ", t) for t in texts]
**#Remove words that start with WWW**
texts = [re.sub(r"www\S+", " ", t) for t in texts]
**#Remove punctuation**
regex = re.compile('[%s]' % re.escape(string.punctuation))
texts = [regex.sub(' ', t) for t in texts]
**#Remove words made of single letters**
texts = [re.sub(r'\b\w{1}\b', ' ', t) for t in texts]
**#Remove stopwords**
pattern = re.compile(r'\b(' + r'|'.join(stopw) + r')\b\s*')
texts = [pattern.sub(' ', t) for t in texts]
**#Remove additional whitespaces**
texts = [re.sub(' +',' ',t) for t in texts]**#Tokenize text documents (becomes a list of lists)**
texts = [t.split() for t in texts]**# Snowball Stemming**
stemmer = SnowballStemmer("english")
texts = [[stemmer.stem(w) if w not in brands else w for w in t] for t in texts]
texts[0][:6]
在文本预处理过程中,我们应该注意不要丢失有用的信息。表情符号:-),由标点符号组成,如果我们计算情感,它会非常重要。
我们现在可以继续计算流行度,它计算每个品牌名称的出现频率——随后标准化,考虑文本中所有单词的得分。我在这里选择的标准化是减去均值,除以标准差。其他方法也是可能的[1]。这一步对于比较考虑不同时间框架或文件集(例如,4 月和 5 月 Twitter 上的品牌重要性)的衡量标准非常重要。在合计流行度、多样性和连接性以获得语义品牌得分之前,绝对得分的标准化是必要的。
**#PREVALENCE**
**#Import Counter and Numpy**
from collections import Counter
import numpy as np**#Create a dictionary with frequency counts for each word**
countPR = Counter()
for t in texts:
countPR.update(Counter(t))**#Calculate average score and standard deviation**
avgPR = np.mean(list(countPR.values()))
stdPR = np.std(list(countPR.values()))**#Calculate standardized Prevalence for each brand**
PREVALENCE = {}
for brand in brands:
PR_brand = (countPR[brand] - avgPR) / stdPR
PREVALENCE[brand] = PR_brand
print("Prevalence", brand, PR_brand)
下一步也是最重要的一步是将文本(标记列表的列表)转换成一个社交网络,其中节点是单词和链接根据每对单词之间的共现次数进行加权。在这个步骤中,我们必须定义一个共现范围,即共现单词之间的最大距离(这里设置为 7)。此外,我们可能想要移除表示可忽略的同现的链接,例如那些权重= 1 的链接。如果这些不是品牌,有时去除隔离物也是有用的。
**#Import Networkx**
import networkx as nx**#Choose a co-occurrence range**
co_range = 7**#Create an undirected Network Graph**
G = nx.Graph()**#Each word is a network node**
nodes = set([item for sublist in texts for item in sublist])
G.add_nodes_from(nodes)**#Add links based on co-occurrences**
for doc in texts:
w_list = []
length= len(doc)
for k, w in enumerate(doc):
**#Define range, based on document length**
if (k+co_range) >= length:
superior = length
else:
superior = k+co_range+1
**#Create the list of co-occurring words**
if k < length-1:
for i in range(k+1,superior):
linked_word = doc[i].split()
w_list = w_list + linked_word
**#If the list is not empty, create the network links**
if w_list:
for p in w_list:
if G.has_edge(w,p):
G[w][p]['weight'] += 1
else:
G.add_edge(w, p, weight=1)
w_list = []**#Remove negligible co-occurrences based on a filter**
link_filter = 2
**#Create a new Graph which has only links above
#the minimum co-occurrence threshold**
G_filtered = nx.Graph()
G_filtered.add_nodes_from(G)
for u,v,data in G.edges(data=True):
if data['weight'] >= link_filter:
G_filtered.add_edge(u, v, weight=data['weight'])**#Optional removal of isolates**
isolates = set(nx.isolates(G_filtered))
isolates -= set(brands)
G_filtered.remove_nodes_from(isolates)**#Check the resulting graph (for small test graphs)**
#G_filtered.nodes()
#G_filtered.edges(data = True)
print("Filtered Network\nNo. of Nodes:", G_filtered.number_of_nodes(), "No. of Edges:", G_filtered.number_of_edges())
确定了共现网络之后,我们现在可以计算多样性和连通性,它们是品牌节点的独特性中心性(之前我们使用度)和加权介数中心性。我们对这些值进行标准化,就像我们对患病率进行标准化一样。关于显著性中心性的更多信息在**【7】和 这篇文章 中给出。你还需要安装 Pythondistinct ns包 。**
**#INSTALL AND IMPORT THE DISTINCTIVENESS PACKAGE**
#pip install -U distinctiveness
from distinctiveness.dc import distinctiveness**#DIVERSITY**
**#Calculate Distinctiveness Centrality**
DC = distinctiveness(G_filtered, normalize = False, alpha = 1)
DIVERSITY_sequence=DC["D2"]**#Calculate average score and standard deviation**
avgDI = np.mean(list(DIVERSITY_sequence.values()))
stdDI = np.std(list(DIVERSITY_sequence.values()))**#Calculate standardized Diversity for each brand**
DIVERSITY = {}
for brand in brands:
DI_brand = (DIVERSITY_sequence[brand] - avgDI) / stdDI
DIVERSITY[brand] = DI_brand
print("Diversity", brand, DI_brand)
如果我们将连通性计算为加权中间中心性,我们首先必须定义逆权重**,因为权重被 Networkx 视为距离(这与我们的情况相反)。**
**#Define inverse weights**
for u,v,data in G_filtered.edges(data=True):
if 'weight' in data and data['weight'] != 0:
data['inverse'] = 1/data['weight']
else:
data['inverse'] = 1**#CONNECTIVITY**
CONNECTIVITY_sequence=nx.betweenness_centrality(G_filtered, normalized=False, weight ='inverse')
**#Calculate average score and standard deviation**
avgCO = np.mean(list(CONNECTIVITY_sequence.values()))
stdCO = np.std(list(CONNECTIVITY_sequence.values()))
**#Calculate standardized Prevalence for each brand**
CONNECTIVITY = {}
for brand in brands:
CO_brand = (CONNECTIVITY_sequence[brand] - avgCO) / stdCO
CONNECTIVITY[brand] = CO_brand
print("Connectivity", brand, CO_brand)
每个品牌的语义品牌得分最终通过对流行度、多样性和连接性的标准化值求和得到。不同的方法也是可能的,例如取非标准化系数的几何平均值。
**#Obtain the Semantic Brand Score of each brand**
SBS = {}
for brand in brands:
SBS[brand] = PREVALENCE[brand] + DIVERSITY[brand] + CONNECTIVITY[brand]
print("SBS", brand, SBS[brand])**#Generate a final pandas data frame with all results**
import pandas as pdPREVALENCE = pd.DataFrame.from_dict(PREVALENCE, orient="index", columns = ["PREVALENCE"])
DIVERSITY = pd.DataFrame.from_dict(DIVERSITY, orient="index", columns = ["DIVERSITY"])
CONNECTIVITY = pd.DataFrame.from_dict(CONNECTIVITY, orient="index", columns = ["CONNECTIVITY"])
SBS = pd.DataFrame.from_dict(SBS, orient="index", columns = ["SBS"])SBS = pd.concat([PREVALENCE, DIVERSITY, CONNECTIVITY, SBS], axis=1, sort=False)
SBS
分析演示
这个链接指向一个简短的演示**,一旦计算出 SBS,就可以进行分析[8]。为了推断独特的和共享的品牌特征,词共现网络可以另外用于研究文本品牌关联。品牌情感的计算也可以补充分析。**
结论
本文简要介绍了语义品牌得分,并提供了使用 Python 3 简化计算的简短教程。在学习基础知识的同时,我们应该记住,有许多选择可以做出,并且会影响结果。例如,可以选择不同的加权方案或标准化方法,将 3 个维度合并为一个分数。应特别注意选择合适的词共现范围。此外,可以使用不同的技术来修剪那些假定代表可忽略的同现的链接。
最后,如果计算是在大数据上进行的,最终的代码会复杂得多。像介数中心性这样的度量在大型图上有很高的计算复杂度。 Graph-Tool 是一个对我帮助很大的库,因为它的性能明显高于 Networkx。在某些情况下,处理初始数据集可以降低复杂性。例如,对于在线新闻,人们可以选择只分析标题和第一段,而不是全部内容。
作为一名自学的 Python 程序员,我将感谢您对这个指标及其有效计算的任何评论或建议。随时 联系我 。
您也可以查看 GitHub 资源库中的笔记本来了解这个演示( 此处 )。
参考
[1] Fronzetti Colladon,A. (2018 年)。语义品牌得分。商业研究杂志, 88 ,150–160。https://doi.org/10.1016/j.jbusres.2018.03.026
[2]凯勒,K. L. (1993 年)。概念化,测量和管理基于顾客的品牌资产。市场营销杂志, 57 (1),1–22。
[3] 维基百科上的语义品牌评分页面。
**[4] Fronzetti Colladon,A. (2020 年)。通过研究在线新闻中的品牌重要性预测选举结果。国际预测杂志, 36 (2),414–427。【https://doi.org/10.1016/j.ijforecast.2019.05.013 **
[5]Semanticbrandscore.com,公制网站,有更新的链接和信息
[6] Fronzetti Colladon,a .,Grippa,f .,& Innarella,R. (2020 年)。研究线上品牌重要性与博物馆访客的关联性:语意品牌评分的应用。旅游管理透视, 33 ,100588。https://doi.org/10.1016/j.tmp.2019.100588
[7]弗伦泽蒂·科拉顿和纳尔迪,M. (2020 年)。社会网络中的独特性中心性。 PLoS ONE , 15 (5),e0233276。https://doi.org/10.1371/journal.pone.0233276
[8]弗伦泽蒂·科拉顿和格里帕(2020 年)。品牌情报分析。在 A. Przegalinska,F. Grippa 和 P. A. Gloor(编辑),协作的数字化转型(第 125–141 页)。瑞士斯普林格自然基金会。https://doi.org/10.1007/978-3-030-48993-9_10