二手车门户网站抓取和探索性数据分析项目
编辑:文章已修改,保持汽车门户网站的身份匿名。
简介
本项目的目的是开展一个小型项目,涵盖大部分数据科学流程,从数据收集、数据清理到探索性数据分析阶段。
数据来源是东南亚的二手车门户。为了保护公司的身份,省略了门户网站的名称。
考虑到拥有汽车的高昂成本,二手车市场的数据分析可能会为汽车门户网站、消费者和汽车经销商带来节约和收益。汽车门户网站拥有超过 10 万辆汽车的数据库,似乎没有分析或数据科学团队来分析这些数据。因此,这个项目的目的是进行探索性的数据分析,以获得对汽车门户、消费者和经销商有意义的见解。
使用的 Python 版本是 3.7.0。
第 1 部分:数据收集
数据是用 BeautifulSoup 4 v0.01 从汽车门户网站上刮下来的。
首先,我们导入模块:
二手车被列在单独的网页上,它们的 URL 包含唯一的 id,格式便于迭代。此外,所有有用的数据都包含在 html 的main_left
部分中。
定义 process_new()函数
接下来,我们定义一个函数process_new()
,该函数首次提取单个车辆的数据:
定义 update()函数
然后我们定义一个函数update()
,该函数为之前使用process_new()
函数抓取的列表重新抓取数据。该函数的目的是捕捉售出的车辆,以及捕捉价格等列表信息的变化。
update()
功能与process_new()
功能相似,但有一些不同之处,这些不同之处将在下面进行解释:
定义了process_new()
和update()
函数后,就可以通过现有的清单 id 运行这些函数了。我将每次迭代的休眠时间设置为 0.1 到 0.2 秒之间的随机浮动,以防止服务器过载。
第一次运行 process_new()时
接下来,我们通过运行下面的代码开始构建本地数据库(DB ),第一次一个一个地抓取清单:
SQLite3 用于与数据库接口,而 DB Browser for SQLite 用作 DBMS。一旦列表被抓取,我们就可以开始用update()
函数每天更新它们。
更新步骤 1:生成要更新的 id 列表
在运行update()
函数之前,我们生成一个应该更新的列表,即状态仍然为“可用”而不是“已售出”或“过期”的列表:
更新步骤 2:批量运行 update()
现在已经创建了 id 列表,我们可以开始在 DB 中更新它们对应的行。
一般来说,对数据库中现有的条目运行update()
的日常过程需要大约 2.5 小时,总共大约 12,000 个行/ID,每个行/ID 花费大约 0.7 秒。
每天为新列出的车辆运行 process_new()
process_new()
功能也每天运行,以捕捉新列出的车辆。要抓取的 id 范围(从range_start
开始,到range_end
结束,但不包括 T5)必须每天重新定义。由于数据收集过程是在 Jupyter 笔记本上完成的,特定一天的process_new()
执行的range_start
就是前一天保存在笔记本上的range_end
。通过在汽车门户网站上进行快速手动搜索,找到了range_end
。
第 2 部分:数据清理
经过一段时间的数据收集,数据库拥有 23,645 行数据。需要很大程度的清洁。
Snapshot of the Database in DB Browser for SQLite (id and other rows censored)
出于这种探索性数据分析的目的,我们只查看那些成功销售的列表。仍可出售的列表从数据库中删除。我们也不包括非私人机动车辆。因此,货车/卡车、公共汽车和货车等商用车辆不在分析范围内:
汽车门户网站上的一些列表没有年度折旧数字。因此,我们必须根据以下公式手动计算年折旧:
年折旧=(价格—退税)/剩余天数 365*
EC 是权利证书,一种给予一个人拥有和操作一辆汽车的权利的许可证。
退税是指车主只有在第一个 EC 的 10 年期满后注销车辆时才能获得的退税。这些车辆可能被报废或出口。对于该数据库中的车辆,退税为注册费(RF)的 50%。幸运的是,RF 数字包含在数据收集步骤中。
数据库中的depre
列没有被修改,以防需要原始值。创建了一个新列final_depre
来存储最终的折旧数字。然后运行以下查询来填充final_depre
列:
cat
栏在筛选符合退税条件的车辆时非常有用。符合退税条件的车辆在卡特彼勒一栏下有一个特定的标签。
随后,删除了不需要的列,包括avail
和depre
,并且为了更加清晰起见,重新排列了这些列。
移除了price
为 0 的车辆。此外,非高峰时段的车辆被删除,因为它们运行在不同的经济(较低的折旧,由于其独特的,有限的使用计划)。
接下来,我们计算每辆车售出的天数:
挑战:细分车辆
从基本的奇瑞 QQ 到豪华的宾利欧陆 GT,汽车的声望各不相同。从这个维度上分割车辆可以得到进一步的见解。浏览数据,我们可以通过几种潜在的方法对车辆进行细分:
- 车型 (
veh_type
):车型分为 12 类,分别是中型轿车、豪华轿车、掀背车、MPV、SUV、跑车、旅行车、全商用车、厢式车、货车、客车/小型客车、其他。每辆车只能分配一种车型。这种分类是模糊的,因为高档和大众市场品牌在所有这些细分市场生产汽车。此外,根据汽车门户网站的定义,丰田凯美瑞、宝马 520i 和劳斯莱斯 Ghost 都属于豪华轿车。车辆类型不是分割车辆的好方法。 - 类别 (
cat
):类别有 13 类,包括车主直接出售、拍卖车辆、稀有&异国车等。除了仅适用于一小部分汽车的“稀有外国汽车”之外,其他类别并不能告诉我们汽车的声望水平。这在分割车辆时也没有用。 - 品牌和型号:一辆车的品牌和型号很能说明它的声望。仅仅是品牌本身就能告诉我们很多关于对一辆车的期望——例如,当我们得知有人开宝马时,外行人的第一个想法可能是“这是一个有声望的品牌”。让我们根据汽车的品牌来分类。
需要在(1)使分析有意义和(2)避免过度分割车辆之间取得平衡。根据我对我国汽车品牌的了解,并通过谷歌搜索,6 个拟议的细分市场是异国情调、超豪华、豪华、中级、经济和预算。
提议的分段及其各自的构成如下:
- 异域 (4):阿斯顿马丁、法拉利、兰博基尼、迈凯轮、
- 超豪华 (5):宾利、路虎、玛莎拉蒂、保时捷、劳斯莱斯
- 豪华型 (9):奥迪、宝马、捷豹、吉普、雷克萨斯、莲花、奔驰、三雄、沃尔沃
- 中级 (7):阿尔法罗密欧、克莱斯勒、英菲尼迪、迷你、欧宝、萨博、大众
- 经济 (17):雪佛兰、雪铁龙、菲亚特、福特、本田、现代、起亚、马自达、三菱、日产、标致、雷诺、斯柯达、双龙、斯巴鲁、铃木、丰田
- 预算 (5):奇瑞、大发、吉利、Perodua、宝腾
在 DB 中创建了一个新列make
。运行以下查询从make_model
列提取品牌,并填充make
列:
然而,我们遇到了有空格的品牌的问题,如“阿尔法罗密欧”结果是“阿尔法”。然后,我们收集了一系列独特的品牌:
输出包含 47 行,其中 3 个品牌(Alfa Romeo、Aston Martin 和 Land Rover)需要使用以下查询进行修复:
接下来,我们在表格中创建一个新列segment
,并将其应用于品牌各自的细分市场:
标签溢价和直接所有者销售广告
接下来,在表格中添加一个premium_ad
列,将广告标记为高级(1)或非高级(0)。对于由直接所有者而非经销商出售或寄售/拍卖的车辆也是如此:
清理带有描述性文本的列
此外,features
(特性)、acc
(配件)和description
(描述)栏似乎有几行是空的。当运行 tf-idf 分析时,这将成问题。因此,我们用“Nil”替换空行或包含“-”的行:
瞧啊。数据库现在可以运行了。然后将其导出为. csv 文件。开始分析。
第 3 部分:探索性数据分析
项目的分析部分是在 Spyder IDE v3.3.2 上完成的。数据的可视化是在 Matplotlib v3.0.0 和 Seaborn v0.9.0 的帮助下完成的。
首先,我们导入模块:
接下来。csv 文件被作为 Pandas 数据帧读取,列标题被更新:
去除异常值
现在我们用散点图快速看一下数据,用Segment
给数据点着色,绘制Days to Sell
对Depreciation
:
输出如下所示:
Scatterplot of Days to Sell against Depreciation; Coloured by Vehicle Segment (Incl. Outliers)
快速浏览散点图可以发现几个异常值。为简单起见,我们排除了年折旧超过 75,000 新元的车辆数据。我们使用折旧而不是价格,因为在我的国家,车辆的使用寿命是有限的,这是由剩余的 EC 期限决定的,因此摊销费用的相关性更大。此外,我们将主数据帧df
分解成多个数据帧,代表不同的段:
接下来,为了直观检查分段的准确性,按顺序绘制各个分段:
输出图表已被处理成. gif 格式,如下所示:
Scatterplot of Days to Sell against Depreciation; Coloured by Vehicle Segment (Excl. Outliers)
分割看起来不错。各段大致占据Depreciation
轴上的正确区域。
问题 1:向直接所有者购买还是向经销商购买?
购车者通常会在经销商和直接车主之间进退两难。每一种都有其优点和缺点。经销商通常提供内部融资选项并提供短期保修,但众所周知,一些经销商隐瞒缺陷和磨损迹象,例如篡改车辆里程表以显示较低的里程读数。直接所有者不太可能篡改车辆,更愿意接受价格谈判,但时间表更紧,不提供私人融资选项等辅助服务。
汽车门户网站将直接所有者销售的广告标记为“直接所有者销售”。我们将“非直接车主”群体概括为汽车经销商,因为其他非直接车主广告,如寄售和拍卖广告相对不常见。让我们将数据集分成两种不同类型的卖家,并查看一下描述性统计数据:
Table 1: Direct Owner Sales Descriptive Statistics (Incl. 0 Mileage)
Table 2: Dealer Sales Descriptive Statistics (Incl. 0 Mileage)
从上面两张表中可以看出,经销商销售的平均和中间价格和折旧比低。对于经销商来说,平均和中间里程数也比平均里程数低。这与里程数少的车价格高的想法不一致!或许经销商销售的里程数据被大量里程数字为“0”的列表扭曲了?让我们通过更新directowner_df
和dealer_df
来过滤这些列表,重新运行描述性统计,并绘制里程直方图:
Table 3: Direct Owner Sales Descriptive Statistics (Excl. 0 Mileage)
Table 4: Dealer Sales Descriptive Statistics (Excl. 0 Mileage)
直接和非直接所有者销售的中间价格和平均价格以及折旧的差距已经缩小。平均里程和中值里程也是如此。然而,平均/中值折旧与里程数之间的正相关关系告诉我们,一些经销商可能在进行一些不正当的活动,即篡改待售车辆的里程表。让我们看看里程直方图:
Mileage Histograms for Direct Owner Sales vs Dealer Sales
查看内核密度估计(KDE)线图,经销商销售的车辆具有较平的右尾部,并且更偏向具有较高峰值的左侧。经销商的 KDE 曲线接近双峰,第二个峰值在 35,000 公里大关附近。经销商销售的折旧分布和 KDE 图会是什么样子?(注意两个 KDE 图中对于里程范围< 0 的微小误差。KDE 图是拟合分布的估计值,并不代表实际分布。)
Depreciation
Histograms for Direct Owner Sales vs Dealer Sales
经销商销售的 KDE 折旧图在峰值左侧有一个拐点。然而,里程和折旧有一个相反的关系——我们本以为在最高峰的右边会有第二个更低的峰,但 KDE 图显示的却不是这样。因此,我们可以合理地假设经销商更倾向于篡改车辆的里程数。
现在回到是从直接车主还是经销商处购买的问题上来:与其做出明确的选择,对于买家来说,更实际的做法是格外小心一辆里程数低但折旧也低的经销商车辆。类似地,买方应始终与经销商协商更低的折旧给某车型,该车型也可从类似情况下的直接所有者处获得。
问题 2:汽车门户网站是否放弃了来自低端市场的收入?
从表 3 和表 4 中观察到的另一个有趣现象是,直接所有者销售的车辆通常具有更高的发动机容量,平均值为 2,066.5cc,中位数为 1,984.0cc,而经销商销售的车辆的平均值为 1,863.2cc,中位数为 1,598.0cc。发动机容量与折旧有正相关,原因有两个——(1)高档车折旧高,通常配备大型发动机。(2)与发动机容量较低的相同型号相比,车辆的折旧较高,例如,2500 cc 的丰田凯美瑞与 2,000cc 的丰田凯美瑞。
这表明经销商销售较低细分市场车辆的比例较高,而直接所有者销售较高细分市场车辆的比例较高。为了调查这一说法,我们对各个细分市场的直接所有者与经销商销售进行了统计:
Table 5: Count of Vehicle Sales by Direct Owner vs Dealers, for the Various Segments
如表 5 所示,从超豪华到经济型,经销商直接向车主销售的比例大幅上升。之前的说法确实没错。高档车的车主更有可能以自己的身份进行销售。这可能是因为经销商向这些车主提供了很低的价格,以保护他们自己(经销商)免受高额维修费用的影响,这是高端大陆品牌普遍存在的问题。高档车的车主也可能更加精明,因此能够通过在汽车门户网站上进行销售。
另一方面,经济型轿车中较低级别车型的车主更倾向于向经销商交易或出售车辆,而不是自行销售。
从汽车门户网站的角度来看,如果车主决定在汽车门户网站上出售汽车或直接向经销商出售汽车,这很重要。交易有三种可能的方式:
- 车主直接销售给经销商而不在汽车门户上挂牌->经销商在汽车门户上挂牌->汽车销售给私人买家(汽车挂牌一次)
- 车主在汽车门户网站上列出汽车->经销商购买汽车->经销商在汽车门户网站上列出汽车->汽车出售给私人买家(汽车列出两次)
- 车主在汽车门户网站上列出汽车->卖给私人买家的汽车(汽车列出一次)
根据表 5,有太多的经济舱车主按照上述选项 1 进行交易。经销商销售的经济型轿车数量也超过了所有其他车型的总和。如果更多的经济型轿车车主选择自己上市,汽车门户网站的收入会显著增加,因为如果同一辆车被卖给经销商,它可能会第二次上市。截至目前,它对标准广告收取统一费用,直到汽车售出。
Comparison of Direct Owner Revenue and Dealer Markup for 2 Sales Sequences (estimated, not to scale)
上图显示了直接所有者销售之前和之前的经销商销售的估计收入和加价明细。通过鼓励车主自己挂牌,这些汽车中的一部分将不可避免地出售给私人买家。然而,经销商也很有可能是买家,因为他们积极寻找并达成汽车交易,这些汽车可以转手获利。如果第二类经销商销售增加,第一类经销商销售减少,汽车门户网站将获得更高的广告收入,同时减少经销商获得的加价。直接所有者也可能收到更高的价格,因为他将收到更多经销商的报价。
在没有车主信息的情况下,我们只能假设车主直接向经销商销售而不是自己销售的三个原因:
- 快速销售,急需现金——由于快速销售车辆的压力而难以捕捉
- 方便,不需要与挑剔的买家打交道——也很难捕获,因为这需要汽车门户网站提供托运服务
- 不精通技术,即无法自己列出汽车或之前从未听说过汽车门户网站— 目标群体
汽车门户网站可以通过提供帮助这些车主创建他们的列表的服务来捕获第三类车主。一旦车辆被张贴出来,车主只需要管理潜在买家的电话和短信。截至目前,汽车门户网站似乎没有这样的服务,所有的上市过程都是由车主在线完成的。
汽车门户网站已经提供了一项服务,帮助买家和卖家解决与交易相关的文书工作。通过帮助面临技术挑战的车主发布他们的清单,汽车门户网站可以提供真正的端到端服务,从而吸引更广泛的客户。
问题 3:优质广告——有用吗?
据一位在汽车门户网站工作的朋友说,优质广告会有更多的图片和更高的搜索优先级。只有经销商可以选择使用高级广告,并且经销商可以使用的高级广告数量有限。汽车门户网站上的优质广告在许多方面都很突出,例如,当它出现在搜索结果中时会有一个绿色标签。
现在,让我们创建一个新的数据框架,不包括Mileage
= 0 的车辆,然后将其分为两个数据框架,分别用于高级和非高级广告。然后我们运行描述性统计:
Table 6: Premium Ad Descriptive Statistics (Excl. 0 Mileage)
Table 7: Non-Premium Ad Descriptive Statistics (Excl. 0 Mileage)
根据上面的表 6 和表 7,溢价广告通常会导致更快的销售,平均需要 11.2 天才能销售,中位数为 7.0 天,而非溢价广告平均需要 12.8 天才能销售,中位数为 9.0 天。溢价广告的平均销售时间比非溢价广告少 12.5%。
人们可能会认为高价广告会以较低的价格快速销售,但描述性统计数据却表明并非如此。溢价广告的平均价格更高,折旧也更高。此外,平均而言,处于中值的优质广告里程数较低,剩余 EC 期较长,且制作时间较晚。换句话说,高价商品清单中包含的是更新、状况更好的车。
简而言之,溢价广告是有效的,因为它们导致更快的平均销售。
当分成不同的部分时,优质广告会显示出有趣的模式吗?
Table 8: Count of Vehicle Sales by Premium vs Non-Premium Ads, for the Various Segments
在细分市场和广告是否优质之间没有有意义的关系。在 6 个细分市场中,有 4 个市场的非溢价广告与溢价广告的比率在 2%以上。
问题 4:我应该使用什么关键词来描述车辆?
汽车门户网站上的每个列表都有 3 个描述性文本字段,即功能、附件和描述。目标是通过拟合几种类型的回归模型,即支持向量回归(SVR)、决策树回归、XGBoost 回归和线性回归,找出文本是否与销售速度(销售车辆所需的天数)有任何关系。我们做的第一件事是在主数据框df
中创建一个新列,合并所有三个字段的内容:
然后我们导入相关的模块并清理文本:
接下来,单词袋模型被创建。TfidfVectorizer()
的ngram_range
被设置为(1,2)
以捕获可能在语义上重要的单个单词以及单词对:
我们将探索一个回归模型,自变量为 tf-idf 矩阵,因变量为售出一辆车所需的天数。然后,我们将数据集分为训练集(85%)和测试集(15%):
然后,我们开始在 SVR 上执行网格搜索以获得最佳参数,以均方误差(MSE)作为评分标准:
多边形内核被排除,因为它无法收敛到一个解决方案。出于同样的原因,对于误差罚项 C = 10、100 和 1000 的线性核,也进行了同样的处理。接下来,生成结果:
Table 9: Grid Search Results on the SVR Model
SVR 的最佳参数是kernel = ‘rbf’
和C = 10
,最小均方误差为 152.55。这意味着 RMSE 为 12.35,考虑到Days to Sell
的平均值为 12.48,中位数为 8.00,这是一个非常差的拟合。接下来,我们将 SVR、决策树、XGBoost 和线性回归模型拟合到 tf-idf 矢量器,计算 10 次迭代的平均 RMSE:
Table 10: Mean RMSE for the 4 Regression Models
所有 4 个模型都有大量的 RMSE 数据,在预测汽车售出的天数时没有用。考虑到高 RMSE 数字,进一步调整参数没有什么好处,特别是对于 XGBoost。(在最近了解到 XGBoost 出色的性能和速度后,我很乐意为它这么做)。就我个人而言,我只会调整模型的参数,如果它的 RMSE 数低于 4 的话。因此,我们就到此为止。让我们研究单词/单词对的线性回归系数,以获得任何见解。
线性回归模型重新运行 10 次,以生成特征及其相应的系数:
Tf-idf Features and Their Coefficients for 10 Linear Regression Iterations
接下来,我们对系数进行快速粗略平均,并对平均值进行排序,以查看哪些系数可能是重要的:
系数值范围从-2.33 到 3.61。让我们看看系数最低的 10 个特征和系数最高的 10 个特征:
Table 11: Top Linear Regression Features Based on Coefficient Magnitude
一些特征名看起来很奇怪,因为在数据库中的Text
列被矢量化之前,它们被PorterStemmer
简化为词干。表 11 包括它们的翻译和它们适用的上下文。具有高绝对系数的特征表示在系数的正端和负端处。这些功能被忽略。让我们看看 5 个不重复的特征(上面橙色的)是否会影响卖出一辆车的天数。
我们在主数据框df
中为 5 个特征创建 5 个新列,在Text
列中搜索匹配项,如果特征出现则插入1
,如果没有出现则插入0
。幸运的是,汽车门户网站在其文本字段中将所有单词的首字母大写。因此,必须进行的单词置换的数量保持较低。
接下来,我们绘制直方图,以便快速直观地检查Days to Sell
的分布是否受到 5 个特征的影响:
Key Tf-idf Features and Their Impact on the Number of Days Taken to Sell a Vehicle
每个特征的两个直方图看起来非常相似。请注意,“sta vicom”功能提供的比较很差,因为包含该功能的样本数量很少。直方图没有提供任何信息。让我们看看熊猫综合数据框架中的描述性统计数据:
Table 12: Descriptive Statistics on 5 Key Tf-idf Features
对于“雾”和“评估”特性,销售天数的平均值和一般分布几乎没有区别。包含“非强制性”特征的样本具有更高的平均值和**,但是该特征在线性回归模型中具有负系数**。这可能是由于 1000 个文本特征的多重共线性,因为多个特征可以频繁地一起使用。单看一个单词或一对单词不太可能产生任何有意义的见解。
最后,包含“驱离”特征的样本比不包含“驱离”特征的样本具有更高的均值和中值。这与其正系数一致,但考虑到多重共线性问题,可能只是巧合。
简而言之,多重共线性问题导致 td-idf +回归分析产生有限的洞察力。我们无法判断哪些词会导致更快的销售。文本和卖出一辆车的天数之间可能没有关系。
tf-idf 分析在分类问题中可能比在回归问题中更有用。
探索性数据分析的结论
让我们总结一下各方的要点:
- 汽车门户网站:帮助不了解汽车的车主创建他们的列表,以便从没有在汽车门户网站上列表的大量经济型车主中获取一部分
- 车主销售:鉴于模糊的 tf-idf 分析结果,没有真正的外卖
- 购车者:当心经销商的廉价低里程汽车;始终与经销商协商低于所列的价格
- 经销商:明智地选择优质广告,因为它们的销售速度比非优质广告平均快 12.5%;如果你在篡改里程表,请三思!
第 4 部分:结束语
这个项目产生了比我最初预期的更多的见解。虽然我很想有机会与该公司合作,并获得更多的功能,我对这个项目的结果感到满意,因为它的时间表相当紧张,只有 3 个月。也许更长的数据收集期会有助于更好的探索性分析。
然而,我期待着任何关于改进领域的讨论或反馈。
欢迎在 LinkedIn上给我发消息或者在下面留言。
我们要马上建立透明模型吗?
可解释的人工智能(xAI)是新的酷小子,xAI 方法(建立一个黑盒,然后解释它)现在是机器学习从业者最珍视的工作方式。这真的是最好的路线吗?为什么我们不马上建立一个可解释的模型呢?
Rashomon (羅生門 Rashōmon) is a 1950 Jidaigeki film directed by Akira Kurosawa. The film is known for a plot device that involves various characters providing subjective, alternative, self-serving, and contradictory versions of the same incident. (wikipedia)
可解释与可解释的人工智能
可解释性和可解释性是两个不同的概念,尽管在不同的来源中,这两个概念似乎被错误地互换使用。在这篇博文中,我将根据以下定义[7]进行推理,至少从我的角度来看,这些定义似乎被最广泛地采用:
- 可解释的 ML:使用黑盒并在事后解释它
- 可解释的 ML:使用透明的模型,即不是黑盒
换句话说,基于这些定义,可解释性是一个模型属性,而可解释的 ML 指的是旨在解释黑盒模型的工具和方法论。
xkcd: curve fitting [0]
我们应该首先建立一个黑盒子吗?
辛西娅·鲁丁[1]的采访很好听,让人耳目一新,她的文章也是[2]。在众多观点中,辛西娅提出了两个有趣的观点:
1.可解释的 ML 方法提供了不可靠的解释
当前主流的可解释 AI / Ml 的解释没有多大意义:可解释 Ml 方法提供的解释并不忠实于原始模型计算的内容。根据定义,这是正确的,即使对于本地代理人也是如此;最重要的是,目前可用的局部替代方法是不稳定的,即不健壮[3]
2.准确性和可解释性之间没有权衡
福布斯写道"更复杂,但也可能更强大的算法,如神经网络,包括随机森林在内的集成方法,以及其他类似的算法牺牲了透明性和可解释性【可解释性,根据以上定义】以获得功率、性能和准确性【4】。按照同样的思路,DARPA [6]。真的吗?
Learning Performance vs Explainability (Interpretability according to the definitions above) [6]
不。准确性和可解释性之间没有权衡。罗生门集提供了一个证明:认为数据允许一个相当准确的预测模型的大集合存在。因为这组精确的模型很大,所以它通常包含至少一个可解释的模型。这个模型既可解释又准确。【2】
为什么我们不马上建立一个可解释的模型呢?
回到我们对可解释性的定义
在这篇博文的开始,我们介绍了可解释 ML 的概念。根据我们的定义,可解释的是那些不是黑箱的算法。这到底是什么意思?
如果我们看看罗生门集[2,10]:
Rashomon sets: existence of a simple but accurate model [10]
Rashomon sets: classes of functions F2 that can be approximated with functions from classes F1 within δ using a specified norm [10]
换句话说,可解释性是数学家标记为透明(黑盒的反义词)[9]的函数类的一个属性。
例如,线性模型类比深度神经网络更容易解释的事实似乎完全没有争议。然而,从实践的角度来看,线性模型并不比深度神经网络、更具可解释性,特别是对于高维度模型或存在大量工程特征的情况。线性模型的权重可能看起来很直观,但它们在特征选择和预处理方面可能很脆弱【9】。
换句话说,从业者对可解释性的定义中没有任何内容表明,属于可解释模型类别的模型将被关键决策者(例如:法官)或关键利益相关者(例如:申请假释的囚犯)理解。在我们对可解释性的定义中,没有任何东西暗示一个模型在可解释性方面最终会满足它的需求。
“但是在地下的某个地方,将会有各种各样的计算不可约性,我们永远也不能真正把它们带入人类理解的领域”——史蒂夫·沃尔夫勒姆[8]
可解释性的许多方面
从利益相关者的角度来看,使用一个可解释的模型类别,其中可解释的意思是透明的(与黑箱相反),并没有带来太多的东西。那么可解释性的定义应该是什么呢?不幸的是,可解释性有很多方面。
不同的任务可能需要不同的解释需求。[12]提供了一个非详尽的假设列表,说明是什么使任务在解释需求上相似:
- 全局与局部:全局可解释性意味着知道总体上存在什么模式(比如控制星系形成的关键特征),而局部可解释性意味着知道特定决策的原因(比如为什么某个贷款申请被拒绝)。前者在以科学理解或偏见检测为目标时可能很重要;后者是当一个人需要一个具体决定的理由时。
- 面积,不完整的严重程度:问题公式化的哪一部分不完整,有多不完整?一方面,人们可能会对自动驾驶汽车如何做出决策感到好奇。另一方面,可能希望检查特定的场景列表(例如,导致汽车偏离道路 10 厘米的传感器输入集)。在这两者之间,人们可能想要检查一个一般属性—安全的城市驾驶—而不需要场景和安全标准的详尽列表。不完整的严重程度也可能影响解释需求。
- 时间限制。用户能花多长时间来理解解释?
- 用户专业知识的性质。用户在任务中的经验如何?
简而言之,我看不到我们有任何机会在短期内就可解释性的一个独特的、银弹定义达成一致。
另一方面,我们有奥卡姆剃刀和泛化理论方法,旨在将算法的泛化属性表达为模型复杂性定义的函数[13]。一般化理论有一个严格的、公认的问题定义;是的,复杂性很可能与可解释性负相关(不管定义是什么)。为什么我们不把奥卡姆剃刀作为我们的指导原则呢?
结果
- 当前对可解释性(可解释的模型不是黑盒)的定义并没有给模型的涉众带来任何价值
- 奥卡姆剃刀原则应该仍然是指导原则
- 可解释的 ML 方法论(例如:LIME [11])提供了不可靠的解释。然而,在数据科学家手中,它们仍然是模型理解和调试的有价值的工具
参考
[0] xkcd,曲线拟合,【https://xkcd.com/2048/
[1]https://twimlai . com/twiml-talk-290-the-problem-with-black-box-with-Cynthia-rudin/
[2]辛西娅·鲁丁。“请停止解释高风险决策的黑箱模型.” arXiv 预印本 arXiv:1811.10154 (2018)。
[3] Alvarez-Melis、David 和 Tommi S. Jaakkola。“论可解释性方法的稳健性.” arXiv 预印本 arXiv:1806.08049 (2018)。
[4]理解可解释的 AI,福布斯,2019 ( 此处)
[5]奥卡姆的威廉
[6] XAI 计划更新,DARPA,(链接)
[7] Keith O’Rourke,可解释的 ML 与可解释的 ML
[8]史蒂夫·沃尔夫勒姆,逻辑,可解释性和理解的未来,(链接)
[9]利普顿,扎卡里·c .〈模型可解释性的神话〉。arXiv 预印本 arXiv:1606.03490 (2016)。(此处)
[10] Semenova、Lesia 和 Cynthia Rudin。“罗生门曲线和体积的研究:机器学习中一般化和模型简单性的新视角.” arXiv 预印本 arXiv:1908.01755 (2019)。
[11]里贝罗、马尔科·图利奥、萨梅尔·辛格和卡洛斯·盖斯特林。“我为什么要相信你?:解释任何分类器的预测。第 22 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集。ACM,2016。(此处)
[12]多希-维勒兹,大结局,和被金。“迈向可解释机器学习的严谨科学.” arXiv 预印本 arXiv:1702.08608 (2017)。(此处)
[13] Mattia Ferrini,一般化界限:依靠你的深度学习模型(此处)
浅层人类和深层人工智能
抱怨或对人工智能征税不会有任何帮助。放下你的智能手机,努力工作。
“How can I prevent AI to take my job”… not by spending your day on Instagram.
这是波士顿四月的一个寒冷多雨的星期二晚上,这里的春天通常比日历晚一周,更典型的是几个月。波士顿通常在六月之前不会收到天气应该变暖的通知。
除了作为我的许多教授朋友的客座讲师,在波士顿庞大的学术圈里给许多学生授课,还能做什么?
因此,我今年第 n 次讲述这个故事,我和我的两个联合创始人,如何从我们在波士顿大学艰苦而漫长的计算神经科学研究中开创了我们的人工智能公司。NSF,DARPA,NASA,然后是商业斗争,直到我们找到了在 3000 多万台设备上部署我们的人工智能的天堂。
虽然通常我的观众都是非常投入的学生,但这次他们中有一小部分人比平时更茫然地盯着我(雨?),特别是有一个人,在一个小时的课上,花了 59 分钟盯着她的 iPhone 翻东西(Instagram?谁知道)偶尔的微笑和咯咯的笑声。
“还好…”,我想…“……。人工智能和计算神经科学并不适合所有人。
但是一个醒着的学生问了我一个问题,我脑海中渗透的智力拼图开始在我没有意识控制的情况下拼凑起来。
Max,谢谢你的演讲,我有一个关于人工智能和工作的问题:随着人工智能变得越来越聪明,我们如何确保人类仍然有工作可做
我的大脑自动合成了答案,幸运的是在出来之前被堵在了嘴里:
“不是靠在 Instagram 上玩 1 小时课 59 分钟”。
我们深刻的思想变得有多肤浅?
我经常被问到这个问题。随着人工智能变得越来越聪明,我们如何才能生存下来并仍然获得工作?
是的。你猜对了。不是通过做我们正在做的事情。
我们都知道社会在变化。甚至从我父亲那一代到我这一代,我们在学校的学习方式也发生了巨大的变化。我父亲曾经告诉我,在意大利南部的学校里,他是如何学习但丁的《神曲》的——全部都是记忆中的!——并要求背诵其中任意一段来证明。(我不能……)
虽然现代自称的教育专家可能会说“背诵不是学习”,但我认为这是至高无上的废话。也不是标准化考试,我们的孩子在美国学校被洗脑。
问题是:用你的大脑做一些困难的事情是目标。
无论是记忆还是求解量子场方程系统,找出亚原子粒子的最终位置,都无关紧要。用脑努力才是关键。
这与今天的学生(以及其他非学生)的想法完全相反。
书是给=_$^=#+的!,随便看了一条推文。心态是在一堆话题上花最少的时间,然后继续前进。浅 vs 深。
有趣的是,将从浅薄的人类手中夺走工作的人工智能被称为深度学习。
失败者做什么?提出税收。
《NYT》最近的一篇文章题为“不要和机器人战斗。向他们征税“有天才般的洞察力,提出我们应该向他们征税,而不是与人工智能和机器人作战。
诺奖就在这里,现场。
Great idea: let’s tax the crap out of (robots) humans!
我的办公室在波士顿港口前,当新生的美国向其他想对他们征税的英国诺贝尔奖获得者伸出手指时,茶被扔进了水里。众所周知,英国的结局很好。
这种态度将最终导致我们在人工智能方面的灭亡。相反,努力工作来提高自己,一个人只是向另一个更好的人征税,希望像寄生虫一样生活在那些每天流汗创新并将人类推向下一个前沿的人的工作中。从基因组学到材料科学等不同领域的成千上万的创新者也是如此……对他们的想法征税吗?
不,NYT 作家,去工作吧,拿出点有价值的东西来,我不会为你的食物和假期买单。
解决方法:好好学习,更加努力
那么,我们该何去何从呢?随着人类越来越肤浅,而 AI 越来越深入,人们害怕自己的工作被 AI 抢走。
我的问题是:是什么让我们值得继续登上领奖台的第一步?我们是否在尽最大努力利用大自然赋予我们的思考和推理的奇妙天赋?
如果答案是肯定的,你(和我们作为一个物种)就在正确的轨道上。
答案很可能是否定的
在对艾指指点点之前,我鼓励每个人做一些反省,并仔细检查我们的生活和思考是否充分发挥了我们的潜力。这绝不是要引起像“我们只使用了 2%的脑力”这样愚蠢观念的共鸣(你试过用 100%的肌肉走路吗?试试看,你会看起来像一只癫痫醉酒章鱼)。
它告诉我们:我们变得如此懒惰,以至于我们不应该指责人工智能,而是应该把我们的屁股从椅子上拿开,把我们的大脑从我们正在使用的任何令人麻木的社交媒体应用上拿开,并打开大脑。
最终,我(也没有人……)无法告诉你该做什么、该学什么*、该把你的全部创造潜力奉献给什么*。**
Winning is possible when one works hard.
但肯定有正确的方法去做:带着激情、创造力和信念去做。人工智能没有,人类有。
把该死的社交媒体电话放下,这样你就有时间做了。
那么,AI 将会有一个强硬的,也许是不可战胜的对手。
浅层神经网络
当我们听到神经网络这个名字时,我们觉得它由许多许多隐藏层组成,但有一种神经网络只有少数几个隐藏层。浅层神经网络仅由 1 或 2 个隐藏层组成。理解一个浅层神经网络能让我们深入了解深层神经网络内部到底发生了什么。在这篇文章中,让我们看看什么是浅层神经网络及其在数学环境中的工作。下图显示了一个具有 1 个隐藏层、1 个输入层和 1 个输出层的浅层神经网络。
神经元
神经元是神经网络的原子单位。给定一个输入,它提供输出并将该输出作为输入传递给后续层。一个神经元可以被认为是两部分的组合:
- 第一部分使用输入和权重计算输出 、Z 。
- 第二部分对 Z 进行激活,给出神经元的最终输出 A 。
隐藏层
隐藏层由各种神经元组成,每个神经元执行上述两种计算。存在于我们的浅层神经网络的隐藏层中的 4 个神经元计算如下:
在上面的等式中,
- 上标数字***【I】***表示层数,下标数字 j 表示特定层中的神经元数。
- X 是由 3 个特征组成的输入向量。
- W[i]j 是与层 i 中存在的神经元 j 相关联的权重。
- b【I】j是与层 i 中存在的神经元 j 相关联的偏置。
- Z【I】j是与层 i 中存在的神经元 j 相关联的中间输出。
- A【I】j是与层 i 中存在的神经元 j 相关联的最终输出。
- 适马 是乙状结肠的激活功能。数学上它被定义为:
我们可以看到,上面的 4 个方程似乎是多余的。因此,我们将它们矢量化为:
- 第一个等式在单个矩阵乘法中计算所有中间输出 Z 。
- 第二个等式计算单个矩阵乘法中的所有激活 A 。
浅层神经网络
使用各种隐藏层来构建神经网络。现在我们知道了在特定层中发生的计算,让我们理解对于给定的输入 X ,整个神经网络如何计算输出。这些也可以称为 正向传播 方程。
- 第一个等式计算第一个隐藏层的中间输出Z【1】。
- 第二个等式计算第一个隐藏层的最终输出A【1】。
- 第三个等式计算输出层的中间输出Z【2】。
- 第四个等式计算输出层的最终输出A【2】,这也是整个神经网络的最终输出。
激活功能
我们知道神经网络基本上是一组数学方程和权重。为了使网络健壮,以便它在不同的场景中表现良好,我们利用激活功能。这些激活函数在神经网络中引入了非线性特性。让我们借助我们的浅层神经网络来尝试理解为什么激活函数对于任何神经网络都是至关重要的。
如果没有激活函数,我们的浅层神经网络可以表示为:
如果我们将等式 1 中 Z[1]的值代入等式 2,则我们得到以下等式:
如您所见,输出将变成新的权重矩阵 W 、输入 X 和新的偏差 b 的线性组合,这意味着隐藏层中存在的神经元和隐藏层中存在的权重没有任何意义。因此,为了在网络中引入非线性,我们使用激活函数。
有许多激活功能可以使用。其中包括TanhReLU漏液 ReLU 等等很多。对所有层使用特定的激活功能不是强制性的。您可以为特定层选择激活功能,并为另一层选择不同的激活,依此类推。你可以在这篇文章中读到更多关于这些激活功能的内容。
重量初始化
我们知道一个神经网络的权重矩阵 W 是随机初始化的。有人可能想知道,为什么不能用 0 或任何特定的值初始化 W 。让我们借助我们浅薄的神经网络来理解这一点。
设第一层的权重矩阵 W1 和第二层的权重矩阵 W2 初始化为 0 或其他值。现在,如果权重矩阵是相同的,隐藏层中神经元的激活将是相同的。此外,激活的导数将是相同的。因此,该隐藏层中的神经元将以类似的方式修改权重,即在特定隐藏层中具有多于 1 个神经元没有意义。但是,我们不想这样。相反,我们希望隐藏层中的每个神经元都是唯一的,具有不同的权重,并作为唯一的功能工作。因此,我们随机初始化权重。
最好的初始化方法是 Xavier 的初始化 。数学上它被定义为:
它陈述了特定层**【l】的权重矩阵W从正态分布中随机选取,其中 均值μ= 0方差σ=层 L1中神经元数量的乘积倒数。所有层的偏置 b 初始化为 0。
梯度下降
我们知道神经网络的权重是随机初始化的。为了使用神经网络进行正确的预测,我们需要更新这些权重。我们更新这些权重的方法被称为梯度下降。让我们用一个计算图来理解这一点。
在上图中,正向传播(用黑线表示)用于计算给定输入 X 的输出。反向传播(用红线表示)用于更新权重矩阵**【W[1】】、W[2]*** 和偏差***【b[1】、b[2】**。这个是通过计算图中每一步输入的导数来完成的。我们知道损耗 L 在数学上定义为 :
使用上述损耗等式 L 并使用 sigmoid 函数作为隐藏和输出层的激活函数,借助导数的链式法则,我们计算如下:
上面的等式可能会令人困惑,但是它们非常适合梯度下降。在 的等式中,dZ【1】, ***** 表示乘积明智乘法,**【σ’**表示σ的导数。
我强烈建议读者,如果他们懂微积分的话,自己算出上面的方程,以便更好地理解梯度下降是如何工作的。
因此,在这个故事中,我们研究了浅层神经网络如何在数学环境中工作。尽管如此,我已经尽可能详细地解释了一切,如果你觉得缺少了什么,请查看我以前的帖子,或者在下面的评论区提出你的疑问。
参考
感谢读者阅读了这个故事。如果你有任何问题或疑问,请在下面的评论区提问。我将非常乐意回答这些问题并帮助你。如果你喜欢这个故事,请关注我,以便在我发布新故事时获得定期更新。我欢迎任何能改进我的故事的建议。
SHAP:分析模型可解释性的可靠方法
by Steven Wright on Unsplash
我开始了这个关于可解释人工智能的系列博客,首先理解了准确性与可解释性之间的平衡,然后继续解释了一些基本的模型不可知技术,以理解模型预测背后的原因,最后解释了石灰的诀窍。以下是这些博客的链接,供您快速参考:
在这篇博客中,我将谈论一种最流行的模型不可知论技术,它被用来解释预测。 SHAP 代表SHapleyAadditive exPlanations。
通过结合来自 合作博弈论 和 局部解释 的概念获得匀称的值。给定一组玩家,合作博弈理论定义了如何在所有合作的支付者之间公平合理地分配收益。这里的类比是:玩家相当于独立的特征,收益是实例的平均预测减去所有实例的平均预测之间的差。
每个特征的 SHAP 值表示在调节该特征时预期模型预测的变化。对于每个特征,SHAP 值解释了解释平均模型预测和实例的实际预测之间的差异的贡献。从以前的帖子中选取相同的示例,我们想要预测实例拖欠信用卡付款的概率,给定年龄、性别和限额余额作为独立特征。
计算独立特征 SHAP 值的步骤:年龄。
- 对于每个实例,性别和极限平衡保持不变
- 年龄的值被从分布中随机选择的值替换
- 该模型预测了这一特定模拟实例的违约概率
- 所有实例的平均预测与该特定实例之间的差异归因于随机采样的年龄独立特征
- 对性别和极限平衡的所有组合重复步骤 1 至 4
- 年龄的 SHAP 值是所有可能组合的所有边际贡献的加权平均值
请参考我之前在 LIME 上发表的帖子,了解我挑选来解释的用例的细节。让我们探索 Python 中的 SHAP 包提供的一些基本视图。每个特征的 SHAP 值的全局视图:
1.每个特征的 SHAP 值的全局视图:
这是一个非常有用的视图,它在全局级别上显示了与平均模型预测相比,每个特征的贡献方向。右侧的 y 轴表示相应的特征值是低还是高。每个点代表数据中的一个实例,这就是为什么您可以看到一簇点,表明数据中有许多具有该特定 SHAP 值的实例。
- PAY_0 表示上月的账单还款情况。这告诉我们, PAY_0 特性的值越高(由红色表示),该实例拖欠信用卡付款的可能性就越大。
- LIMIT_BAL 表示信用余额。这告诉我们降低 LIMIT_BAL 特性的值(用蓝色表示)
2.单个实例视图
再次,我个人发现分析正确预测的实例和错误预测的实例。这只是给出了导致错误预测的特征的感觉。这里提到了基本(平均)值,并显示了每个特征对预测的贡献。指示红色的特征有助于预测高于基数,即趋向违约,而指示蓝色的特征有助于预测低于基数,即趋向非违约
从我之前的帖子中拿起同样的例子。不正确预测为非默认(实际:默认)
此实例被归类为非违约的主要原因似乎是 *PAY_0 = 0。*这表明,上个月的付款及时完成无疑增加了这种情况被预测为非违约的可能性。您可以进一步分析导致预测非默认的其他连续要素的行为。您可以首先检查他们的总体分布统计数据和每个默认和非默认标签的分布统计数据。
为什么 SHAP 是更受欢迎和可靠的技术?
**1\. Local Accuracy:**
解释模型应该与原始模型相匹配
**2\. Missingness:**
如果简化输入表示要素存在,则缺失要求原始输入中缺失的要素没有影响
**3\. Consistency:**
一致性表明,如果一个模型发生变化,使得一些简化输入的贡献增加或保持不变,而不管其他输入,该输入的属性不应减少
**4\. Efficiency:**
由于 SHAP 值的基础是基于计算博弈论,这是唯一的方法,可以分配功能的增益失败。
**5\. Global comparison:**
SHAP 值提供了一种在全局级别比较要素重要性的方法。您还可以将数据集从全局数据集更改为感兴趣的子集数据集。
缺点:
**1\. Computation time:**
随着特征数量的增加,特征的可能组合的数量呈指数增加。这反过来增加了计算 SHAP 值的周转时间,近似是唯一的解决办法。
**2\. Order of feature selection in all possible combinations:**
典型地,在解决真实世界的问题时,目标与独立特征非线性相关,并且在独立特征之间也存在一些相关性。在这种情况下,在组合中选择特征的顺序很重要,并且会影响 SHAP 值。
**3\. Simulation of scenarios:**
SHAP 不返回模型,像石灰。因此,如果你想模拟某个特定功能的增加会对输出产生多大影响,那么用 SHAP 是不可能的。
**4\. Correlation amongst independent features:**
同样,在大多数现实世界的问题中,独立的特征是相互关联的。在这种情况下,当我们从特征的边缘分布中取样时,可能会产生在现实世界中不可能产生的实例。
朱庇特笔记本的副本
如果您想要一份上面有使用案例的 Jupyter 笔记本,请在下面的评论部分或通过**“联系我们”**部分告诉我们您的电子邮件 ID。
下一步是什么?
在下一篇博客中,我计划解释 Python 中的 SHAP 包必须提供的一些其他可视化功能。
这个可解释的人工智能领域正在迅速发展,在工具和框架方面有很多新的发展。请在评论区写下你对博客的反馈,以及你在这个领域使用的最新工具。此外,如果你想让我写任何特定的主题,请发表评论。
这些内容最初发表在我的个人博客网站:http://datascienceninja.com/。点击此处查看并订阅即时接收最新博客更新。
借助土星云,您可以在任何地方共享、协作和运行
现在创建自己的服务器很容易
分享见解是每个数据科学家工作的一部分。
昨天,我发布了我的一个 Google Colab 笔记本。这是一个很棒的免费平台,但它不能解决我的主要用例。
我希望我的受众(主要是业务用户)看到我的分析被正确地呈现出来。
如果他们喜欢,可以自己运行它(在 Google Colab 上,任何新用户都必须使用他/她自己的 Google API 密钥,这对一些人来说是一个障碍)
另外,我真的不想像大多数免费软件那样,把自己局限在有限的计算上。
这就是我了解土星云的地方。现在它是由 Anaconda 的联合创始人之一,的 Hugo Shi 制作的产品。
是的,就是您用来在系统中创建数据科学环境的那条蟒蛇。
所以我必须调查一下。
Anaconda 自己解决了一个特殊的用例。下载和管理 Python 环境。
土星云解决在云端管理 Python 环境 。
怎么会?
请继续关注,因为这正是本文的内容。
什么是土星云?
所以让我首先说明一下土星云是什么。
我敢打赌,我们大多数人都尝试过在我们的机器上安装 Python。在安装 Jupyter 笔记本/实验室时遇到了麻烦。
只是在做了大量的摆弄之后,我们才开始真正的工作,即数据科学。
或者,当你需要大型计算时,你可能会遇到困难,于是你去找 AWS(亚马逊网络服务)/GCP(谷歌云平台)。这些系统的创建方式对我们很多人来说似乎很神秘。
是的,你并不孤单。 我自己也尝试过用 GCP 。实际上,我没能做到。
现在我们数据科学家热爱自动化。 我们为什么不摆脱这种设置数据科学工具的卑微过程?
这就是土星云的意义。
它为我们这些对设置不太感兴趣但对数据科学非常感兴趣的数据科学家提供了一种简单的入门方法。
它还帮助我们:
- 为我们的项目设置自定义计算
- 在网络上共享内容
开始并设置自定义计算
所以让我们开始吧。您可以从免费层开始。
你首先需要在 SaturnCloud 注册,然后进入仪表盘。
现在,为一个项目创建一个笔记本/实验室就像 一样简单,只需选择磁盘空间和机器大小,然后点击创建按钮 。谈到 配置 ,SaturnCloud 提供了不同的选项。
这些配置实际上可以满足许多实际数据科学项目的需求。
使用最后一个配置选项,设置带有 GPU 的机器是轻而易举的事情。所以你可以和 AWS/GCP 收购 GPU 的漫长流程说拜拜了。
您也可以为您的项目定义一个 自动关闭持续时间 。这是我特别喜欢 SaturnCloud 的一个功能。我已经被蛰过很多次了,我的 Google Colab 笔记本服务器在一个小时不活动后就关闭了。
在这里,我可以设置我的笔记本关机持续时间为 1 小时,6 小时或从不关机。 从来都不是我喜欢的。
您还可以选择使用高级选项 使用 apt-get、pip 和 conda 选择默认配置。但主要是我一开始并不担心,因为它预装了科学的 python 堆栈。
并且 一旦我创建了笔记本/实验室 ,我就可以使用终端本身下载任何我需要的新包。
因此,一旦您创建了 Jupyter 笔记本/实验室,您应该会在您的仪表板上看到以下内容:
在这里你可以点击去 Jupyter 实验室。瞧,你已经开始运行了。
在网络上共享内容
这是 SaturnCloud 提供的另一个对我非常有价值的功能。
我是一名数据科学家,我需要与我的业务合作伙伴共享报告。此外,我是一个技术博客,我需要与我的读者分享代码。
现在,我分享的报告需要在网络上正确呈现。
我与读者分享的代码需要是可执行的。
土星云为我解决了这两个用例。
怎么会?
我先举个例子。我渴望与我的读者分享对足球数据的分析。我将从我最喜欢的博客文章之一中摘录代码— 每个数据集的 3 个令人敬畏的可视化技术
首先,我用 Jupyter Lab 正常编码。我在那里为我的项目创建了一个名为visproject
的文件夹。我把数据上传到那里,然后在我的 jupyter 笔记本的那个文件夹里创建并编写代码
现在,为了分享我的工作,我需要做的就是在 Jupyter 实验室中打开一个终端并运行命令:
publish visproject
现在去出版部门。您应该看到:
现在我有不同的选择。我可以将我的笔记本保密(私人)/公开,我也可以点击“我将为其他人支付执行此笔记本”。
一旦您点击“我将为他人支付执行费用”,您应该会看到类似以下内容:
我已经公开了这个笔记本,并且可以使用上面分配的资源执行。对设置满意后,您可以单击保存按钮。
随后,点击预览链接。
这就是它的样子。结果是:
我喜欢代码块和所有可视化的渲染方式,没有任何混乱,就像我们在 Google Colab 笔记本上看到的那样。它看起来就像是一份预期的报告。
我也喜欢所提供的**“土星运行”**选项,用户可以直接点击运行这段代码,而不需要任何明确的登录。
一定要试着自己运行它这里。我相信你会喜欢的。
费用:
我喜欢土星云的一点是它的相关成本。
这并不是我对许多付费产品的说法。
我可以毫不费力地获得土星云的所有功能,对于我目前使用的基本计划,我只需要支付云提供商的费用加上一点点开销。
现在这是个人喜好的问题,但我愿意为所提供的服务质量和避免的麻烦支付这笔非常少的间接费用。
事实上,我收回了大部分费用,因为虽然在 AWS/GCP 上停止服务器有点麻烦,但对土星云来说却是小菜一碟。
这是您自己要查看的费用列表。
结论
土星云让数据科学家的生活变得更容易,因为他几乎不用花费任何费用就可以处理大量多余的工作。
我并不是说我永远不会创建定制服务器,但是只要我能使用土星云,我就会避免这样做。
即使当我确实需要创建一个定制服务器时,如果我的公司允许,我也可能会查看土星云提供的企业帐户。
正如他们在网站上所说:
在花时间从事数据科学以及构建数据科学工具之后,我们都非常熟悉数据科学、技术和开发人员操作交汇处的摩擦和痛点。
我们不能为您做模特——但我们可以减轻一些痛苦。
那你还在等什么?只需使用您自己的服务器开始数据科学。它肯定有它的好处。
您可以尝试自己运行已发布的土星云笔记本。
我以后也会写更多这样的帖子。在关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。
分享π:尊重被忽视的数学常数
酷数学的有趣回顾
圆周率得到了一切——一年中有两天(当然是 3 月 14 日和 7 月 22 日)享受甜蜜的放纵;一种人类对记忆和计算更多位数的执念(注意 39 位数计算可观测宇宙的周长精确到一个原子);流行文化中的大量引用。
Source: https://en.wikipedia.org/wiki/Pi#/media/File:Record_pi_approximations.svg
当然,圆周率很酷,但不是因为这些原因。圆周率在数学中无处不在——这是一个非常深刻的现实。欧拉恒等式使用圆周率将 5 个最重要的数字联系在一起。海森堡测不准原理包含圆周率,说明物体的位置和速度不能同时精确测量。Pi 是许多公式中的归一化常数,包括高斯/正态分布。在 2 处评估的 Reimann 函数收敛到π的因子。
但是这篇文章将向那些不太受重视、有时被遗忘、被忽视的数学常数致敬。深度不亚于圆周率,魅力不亚于圆周率,让我们开始吧!
欧拉数:e
T4 有几个特征。它是唯一的基数 a ,通过它,y = a ^x 是它自己的导数,在 x = 0 时有一个 1。也是无限指数增长的极限。它满足下面蓝色突出显示区域所示的积分范围。
The five colored regions are of equal area, and define units of hyperbolic angle along the hyperbola. Source: https://en.wikipedia.org/wiki/E_(mathematical_constant)#/media/File:Part38figure02.gif
e 可以写成连分数,下面是其中的两个。
这一现实产生了一个有趣的程序,叫做 spigot 算法,可以用来计算许多数字 e (还有圆周率……)。一个为 e 编写的 spigot 算法的 Python 实现是这里的,我在下面做了一些修改。
import numpy as npdef continued_fraction(a, b, n, base=10):
(p0, q0), (p1, q1) = (a(0), 1), (a(1) * a(0) + b(1), a(1))
k = 1
cnt = 0
while cnt <= n:
(d0, r0), (d1, r1) = divmod(p0, q0), divmod(p1, q1)
if d0 == d1:
cnt += len(str(d1))
yield d1
p0, p1 = base * r0, base * r1
else:
k = k + 1
x, y = a(k), b(k)
#print(x)
#print(y)
(p0, q0), (p1, q1) = (p1, q1), (x * p1 + y * p0, x * q1 + y * q0)#Generate
e = ''
for digit in continued_fraction(lambda k: 1 if k <= 1 else 4 * k - 2,
lambda k: 2 if k <= 1 else 1,
500000):
e += str(digit)
其工作原理是使用连分式在两个分数估计值(p0/q0 和 p1/q1)之间迭代。当观察到的那些分数的小数收敛时,你可以去掉一致的数字(例如:23/27 = 0.315068 和 34/108 = 0.314815 会让你去掉 0.31)。更有帮助的是,我们可以在去掉那些数字并保持分数的分子/分母小的情况下,对分数进行“重组”。
函数中的λ函数表示连分数的分子/分母。我们将数据存储为一个字符串,以简化成千上万位数字的存储。我通过另一个列表验证了 100k 位的算法。
2004 年,一个著名的谷歌广告牌上写着 e.
现代的 CPU、编程语言和 Google 本身使得解决这个问题变得容易得多,但它仍然超级有趣!在生成足够多的数字 e 开始工作后,我们需要生成 10 位数的素数——素数将是我们的下一个“常数”。
质数
好吧…质数并不是真正的常数,但它们仍然非常酷。最基本的是,质数是一个大于只能被 1 整除的数。这几乎是初等的,但是回想一下,任何本身不是质数的数都可以写成质数的唯一乘积。也就是说,质数是所有其他数的积木!从几个方面来说都是如此:
高达 4*10 ⁸的哥德巴赫猜想证明,每个大于 2 的整数都可以写成两个素数之和(例如 12 = 7 + 5)。一个令人信服的启发指出,随着数字的增长,有越来越多的机会来构建两个这样的数字:例如,100 有 6 对(3+97,11+89,17+83,29+71,41+59,47+53)。下图通过散点图说明了这一点。
Scatter Plot of Available pairs that satisfy Goldbach’s conjecture.
拉格朗日证明了每一个正整数都是四个平方的和(即 310 = 17 + 4 + 2 + 1。假设这个公式是这样的:在公式 x + 3y + 5z 中,3 个数产生一个正方形(例如 2+ 14 + 42 = 25,也就是 5)。
另一个超级酷的事实是:蝉一生中的大部分时间都是在地下度过的,但在 7、13 或 17 年后会在地面上飞行、繁殖,并在几周内死亡。生物学家假设,质数繁殖周期长度是一种进化策略,以防止捕食者与它们的繁殖周期同步。
素数有很多种,其中一种会出现在下面计算的常数中。“孪生素数”是指比另一个素数多 2 或少 2 的素数(例如 13 是孪生素数,因为它比 11 多 2)。斐波纳契素数是指同时也是斐波纳契数的素数。梅森素数有助于生成非常大的素数,它遵循 2^n — 1 的形式。
已知最大的素数有超过 2490 万位数,但没有生成素数的“公式”。许多算法是已知的,其中最容易理解的被称为厄拉多塞筛。该算法首先列出从 2 到 n 的所有整数,或者从 3 到 n 的所有奇数,以便进行一些初始性能调整。接下来(使用第一个公式),计算 2 的所有因子(即 21 = 2,22 = 4,2*3 = 6,等等。),并从您的列表中删除这些项目。移动到你清单中剩下的下一个项目(3),去掉所有的因素。当你移动到下一个项目时,4 不再在列表中,所以你移动到 5。随着你的前进,你逐渐从列表中剔除非素数。
下面的算法使用这种基本逻辑,效率很低。关于模数计算的一些编程注意事项:
//是楼师。7//2 返回 3(并丢弃 0.5 余数)。
%是模数运算符。7%2 返回 1(因为 7/2 = 3 + 1 /2)
|是位二进制 or 运算符。13|14(在二进制 1101 和 1110 中)对整数逐个取或,所以结果是二进制的 1111,也就是 15。
def primes(n):
""" Input n>=6, Returns a array of primes, 2 <= p < n """
sieve = np.ones(n//3 + (n%6==2), dtype=np.bool)
for i in range(1,int(n**0.5)//3+1):
if sieve[i]:
k=3*i+1|1
sieve[k*k//3 : : 2*k] = False
sieve[k*(k-2*(i&1)+4)//3 : : 2*k] = False
return np.r_[2,3,((3*np.nonzero(sieve)[0][1:]+1)|1)]
厄拉多塞的正常筛子大约在多项式时间内运行,这意味着随着 n(你的最大可能素数)的增长,时间增长 n(大约…)。直观地说,这里的问题是你在多次消去同一个数:5M 的 n 将分别消去 4,849,845 次(3,5,7,11,13,17,19),但只有 1 次是必需的。上面的算法通过使用两个不同且更复杂的公式来计算非素数列表,减少了这种重复。
回到我们的谷歌广告牌。我们将 e_list 分割成 10 位数,然后使用素数列表检查它们是否是素数。我们只需要检查 100,000,因为 100,000 不是 11 位数字。
x10 = primes(int(1e5))
print(np.max(x10))e_list = [int(e[i : i+10]) for i in range(0, len(e))]for i in range(len(e_list)):
print(i)
n = 0
for j in range(len(x10)):
n += 1 if e_list[i] % x10[j] == 0 else 0
if n == 0:
print(e_list[i])
break
结果是第 99 位数字给我们 7,427,466,391,这是一个 10 位数的质数!后续事件相当普遍。
布伦和梅塞尔-默滕斯常数
质数出现在我们接下来要讨论的两个迷人的常数中。
布伦常数的形式如下——所有素数对的倒数之和。
数字收敛速度极慢,这本身就很迷人。这些分数的分母迅速减小——问题是,即使对于非常大的数,素数对也相对常见。事实上,布伦常数是未知的。使用所有孪生素数直到 10 ⁶(即 10 万亿亿)时,它被估计为~1.902160583104,但仅被证明小于 2.347。
回到谷歌:在破产的北电公司的专利拍卖中,该公司以出价 1902160540 美元收购布伦常量而闻名。随后的出价为 2,614,972,128 美元,反映了梅塞尔-默滕斯常数(约为 0.26149……)。
Meissel-Mertens 常数也称为质数倒数常数,其定义如下:
这个数字也不是确切知道,虽然收敛速度比布伦常数快得多。
黄金比例和斐波那契数
从欧几里得时代开始研究,黄金分割率在几何中起着重要的作用,并且有许多几何表示。
Left: Let A and B be midpoints of the sides EF and ED of an equilateral triangle DEF. Extend AB to meet the circumcircle of DEF at C. The ratio of AB/BC = AC/AB = The Golden Ratio. Right: A pentagram colored to distinguish its line segments of different lengths. The four lengths are in golden ratio to one another.
Left: The golden ratio in a regular pentagon can be computed using Ptolemy’s theorem. Right: A Fibonacci spiral which approximates the golden spiral, using Fibonacci sequence square sizes up to 34. The spiral is drawn starting from the inner 1×1 square and continues outwards to successively larger squares.
最后一个螺旋图像被称为斐波那契螺旋,代表了黄金分割率的一个迷人的特性:取连续斐波那契数的比率收敛到黄金分割率,我们将在下面讨论。
斐波那契数的形式是 F(n) = F(n-1) + F(n-2)。序列的开始是 1,1,2,3,5,8,13,21,34,55,89,144。
斐波那契数的一些有趣的性质:每个正整数都可以写成斐波那契数的和,其中任何一个数只使用一次。当你考虑到序列前面部分相对于后面部分的密度时,这可能是直观的。斐波纳契数是帕斯卡三角形对角线的总和(由上面两个数的总和构成的每一连续层构成)。
The Fibonacci numbers are the sums of the “shallow” diagonals (shown in red) of Pascal’s triangle.
如上所述,当你取连续的斐波那契数的比率时,黄金分割率收敛。比如 89/55 = 1.61818,接近真实值 1.61803。黄金分割率可以用无理数根 5 来精确定义。
黄金分割率也可以表示为一个连分式,所以我们可以使用上面的 or e- 生成算法来生成黄金分割率的数字。具体来说:
phi = ''
for digit in continued_fraction(lambda k: 1,
lambda k: 1,
500000):
phi += str(digit)
你会注意到,与 e 代码相比,运行上面的代码要花一些时间。500,000 要求算法返回 500,000 位,而不考虑连分数需要迭代多少次。黄金分割连分数收敛很慢,这有一定的道理:分母中的数字越大,重复出现的加法分数就越小。
结论
我们可以讨论更多的常量,但是这篇文章已经有点漫无边际了!我们没有得到第一个大二学生的梦想常数(由 0 和 1 之间的曲线 x^x 界定的区域,因不正确但如此方便的恒等式而得名(x+y)^n = x^n + y^n,这将使这样的积分更容易解决));统计数据中出现的 Gamma 和 Reimann zeta 函数的值;、或在随机随机行走和其他分析应用中出现的任何其他常数。
这篇文章的主要观点:数学超级酷!而且谷歌很有幽默感!
分享就是关心算法
Photo by @maur1ts
开源机器学习&共享代码或数据
重要的是要考虑可以共享的公开许可的技术和内容。我们应该设法更快地在世界不同地区分享有益的解决方案,这显然符合我们的利益。虽然一种解决方案不一定能从一个地方移植到另一个地方,但重要的是要考虑到当地环境的相关方面,并相应地进行调整。因此,我决定探索当前流行的开源框架以及其他不太知名的框架。首先,我将从几个不同的与机器学习相关的开源解决方案开始,并继续讨论发布代码的平台。
“开源软件*(OSS)是一种计算机软件,其源代码是根据许可证发布的,在许可证中,版权所有者授予用户研究、更改和向任何人出于任何目的分发软件的权利。”*
机器学习(ML) 是计算机系统用来执行特定任务的算法和统计模型的科学研究,不使用明确的指令,而是依靠模式和推理。它被视为人工智能的子集。”
“Apache 许可证 是由 Apache 软件基金会编写的许可自由软件许可证。它允许用户出于任何目的使用软件、分发软件、修改软件以及根据许可证条款分发软件的修改版本,而无需考虑版税。”
这并不意味着整个应用程序或平台都可以改变。然而,在某些情况下,它可能是合作开发的,尽管情况并非总是如此。大多数大型开源项目都与一家或几家大型技术公司有关联,有时归谷歌、微软、亚马逊等公司所有。2017 年,谷歌推出了对人工智能的明确关注,声称它将成为一家“人工智能优先”的公司。因此,利用机器学习技术可用的开源平台开始探索与人工智能相关的解决方案并不是不合理的。
开源机器学习
有各种各样的参与者在为开源市场制作产品。当然,相当多的人似乎受到了构建软件的可能性的激励,这些软件可以促进对其云平台的热情使用——因此拥有最容易访问和最广泛的解决方案似乎是其中许多人的目标。然而,它可以被广泛使用,可以成为行业标准,并且是许多开发人员熟悉的框架。如果你在这个领域工作,那么熟悉一些不同的概念可能会有好处。
张量流
TensorFlow 是一个相对容易使用的开源机器学习(ML)框架。众所周知,它可以跨多种平台部署。因此,它是最广泛使用的机器学习框架之一,也可能是维护得最好的。TensorFlow 由谷歌大脑团队开发,供谷歌内部使用。于 2015 年 11 月 9 日在 Apache License 2.0 下发布。截至 10 月 8 日,这个由谷歌主导的项目已经在 GitHub 上有 69179 个提交和 2223 个贡献者,在其模型库上有 58095 颗星。
克拉斯
Keras 是一个开源软件库,旨在简化深度学习模型的创建。它是用 Python 编写的,可以部署在 TensorFlow、微软认知工具包和 Theano 等其他人工智能技术之上。Franç ois Chollet 是 Keras 的创始人,目前在谷歌担任人工智能研究员,他也是 Keras 开发的核心。根据 Keras 的说法,它认为自己是:“…一个为人类而不是机器设计的 API。Keras 遵循减少认知负荷的最佳实践:它提供一致的&简单 API,最大限度地减少常见用例所需的用户操作数量,并在用户出错时提供清晰可行的反馈。”首次发布是在 2015 年 3 月 27 日,首次稳定发布是在 2019 年 8 月 22 日。Keras 有 5,331 个提交,821 个贡献者和 44,571 颗星。
sci kit-学习
scikit-learn 最初发布于 2007 年,是一个为机器学习开发的开源库。这个传统的框架是用 Python 编写的,具有几个机器学习模型,包括分类、回归、聚类和降维。Scikit-learn 最初是由 David Cournapeau 在 2007 年作为 Google 代码之夏项目开发的。Scikit-learn 有 24,582 个提交,1,439 个贡献者和 37,343 个星级。
微软认知工具包
微软认知工具包是一个人工智能解决方案,它可以让你将你的机器学习项目提升到一个新的水平。微软表示,开源框架能够“训练深度学习算法像人脑一样工作。”最初发布于 2016 年。在 GitHub 上,它有 16,110 个提交,198 个贡献者和 16,455 颗星。
Theano
最初发布于 2007 年, Theano 是一个开源的 Python 库,允许你轻松地构建各种机器学习模型。由于它是最古老的图书馆之一,它被视为激励深度学习发展的行业标准。在 GitHub 上,Theano 有 28,090 次提交,331 个贡献者和 8,933 颗星。
咖啡
Caffe (用于快速特征嵌入的卷积架构)最初于 2017 年发布,是一个专注于表现力、速度和模块化的机器学习框架。开源框架是用 C++写的,附带一个 Python 接口。CAFFE 是一个深度学习框架,最初由加州大学伯克利分校开发。它是在 BSD 许可下的开源软件。BSD 许可证是一系列许可性自由软件许可证,对涵盖软件的使用和分发施加了最低限度的限制。在 GitHub 上,Caffe 有 4154 个提交,265 个贡献者和 29191 颗星。
共享代码的平台
重要的是要考虑共享数据的可能性。如果我们能够负责任地共享代码,这将是一个明显的优势。必须考虑与实现 2030 年议程的相关性。该议程承诺到 2030 年在全世界消除贫困和实现可持续发展,确保没有人被落下。代码或存储库本身当然不会以任何方式、形状或形式默认实现这一点。然而,如果我们希望在地球上实现更加公平和持续的存在,合作可能是我们社会的一个重要拼图或方面。按受欢迎程度排列,最大的平台如下:
Adjusted spreadsheet with comparison of source-code-hosting facilities ranked by Alexa rank
*大多数共享代码的平台使用分布式版本控制系统来跟踪软件开发过程中源代码的变化。它被称为 git,由 Linus Torvalds *(说瑞典语的芬兰裔美国开发人员)在 2005 年创建,用于开发 Linux 内核,其他内核开发人员为其最初的开发做出了贡献。它是为协调程序员之间的工作而设计的,但也可以用来跟踪任何一组文件中的变化。
开源代码库
美国公司 GitHub 使用 Git 为软件开发版本控制提供托管服务。该公司是微软的子公司,2018 年以 75 亿美元被收购。截至 2019 年 5 月,GitHub 报告拥有超过 3700 万用户和超过 1 亿(包括至少 2800 万公共存储库)。2014 年据估计,它是世界上最大的源代码主机。源代码是程序员使用计算机编程语言编写的一组指令和语句。该服务将由 Nat Friedman 领导,向微软云和人工智能执行副总裁 Scott Guthrie 报告。不得不说,GitHub 有机会注册非营利账号。然而,这些必须是非政府的,非学术的,非商业性的,非政治性的,没有宗教信仰。
一套合作式软件开发管理系统
由 VA Software 于 1999 年创立的 SourceForge 是第一家为免费和开源软件开发者提供集中位置来控制和管理软件开发并免费提供这项服务的提供商。SourceForge 是一项基于网络的服务,它为软件开发者提供了一个集中的在线位置来控制和管理免费和开源软件项目。SourceForge 是首批向开源项目免费提供这项服务的公司之一。自 2012 年以来,该网站一直在 Apache Allura 软件(根据上述 Apache 许可证)上运行。SourceForge 为自由/开源软件的开发者提供免费的主机和工具。然而,2015 年发生了一次权力滥用,导致许多用户离开平台或感到不满。
谷歌知识库
如果我们把目光从开源转向大型科技公司,谷歌的整体软件库(全球 95%的软件开发人员都在使用它)符合超大规模 4 系统的定义,证明了单一资源库模式可以成功扩展。谷歌有自己的 GitHub 替代品:云资源仓库。
联合国全球脉搏
从用户的角度来看,联合国全球脉动是联合国的一项倡议,旨在“为发展和援助项目带来实时监测和预测。”作为数据共享的一个例子,在 one one 项目页面的底部有一个链接,该链接指向一封电子邮件,这意味着你必须向联合国全球脉动办公室之一发送电子邮件,以请求访问代码。然而,在这些页面上共享代码并不总是这样。
数据共享计划
数据是另一个可以共享的点。最近在联合国全球脉搏的博客上有一篇文章,名为 数据和 AI 促进联合国大会 期间的进展。本文重点介绍了几个值得一提的项目。新任命的负责战略协调的助理秘书长(ASG)福尔克·蒂尔克会见了几个组织,讨论从发展角度使用数据的问题。
数据为现在倡议
数据为现在倡议是一项新的全球努力,旨在弥合数据促进发展方面的差距,副秘书长阿米娜·穆罕默德指出:“……我们可以通过共同努力解锁数据、保护人们的隐私和争取包容,开辟一条成功的道路。”在 Data for Now 活动期间,谷歌和可持续发展数据全球伙伴关系(GPSDD)宣布了一项协议,重点是为可持续发展目标开展跨平台地球观测合作。
饥饿地图平台
世界粮食计划署(WFP)和阿里巴巴周四展示了他们新的饥饿地图平台,该平台结合了不同的信息流——如天气、人口数量、冲突、危险、粮食安全、营养和市场信息——以近乎实时地监测和预测全球粮食安全形势。
全球数据共享空间
全球数据共享区(Global Data Commons)——目前由大约 70 个政府、组织和公司组成的非正式合作伙伴关系,致力于为可持续发展目标制定允许快速创新和安全使用人工智能的路线图。会议结束时制定了一项计划,旨在开发一个通用参考架构和治理框架,然后实施一个基于具体用例的工作模型。
这是#500daysofAI 的第 126 天。如果你喜欢这篇文章,请给我一个答复,因为我确实想提高我的写作或发现新的研究,公司和项目。
分享:上不上“AI for Everyone”课程?deeplearning.ai 的课程
参加吴恩达教授的“AI for Everyone”课程后的分享
https://www.coursera.org/learn/ai-for-everyone/
最近刚上了上图所示的课程,一门 AI 非技术入门课程,教授吴恩达, deeplearning.ai ,通过 Coursera 授课的AI for everybody。我不是在做广告,还是详细说说课程内容吧。相反,我想谈谈我的分享。下面是链接:https://www.coursera.org/learn/ai-for-everyone/。( Sik-Ho Tsang @中)
概述
- 包括哪些?
- 真的适合所有人吗?
- 懂 AI 的人需要吗?
- 已经学过吴恩达教授深度学习专业的人还需要吗?
1.包括哪些内容?
课程中有四个主要主题:
- 什么是 AI?
- 打造 AI 项目
- 在你的公司建立人工智能
- AI 与社会
1.1.AI 是什么?
我们可以看到,在第一节,它以一种大家都能理解的非常笼统的方式讲了什么是 AI 和机器学习(ML)。
1.2.打造 AI 项目
在这一节中,它谈到了如果我们需要应用 AI,ML 或数据科学,我们应该做些什么来将它们应用到我们的工作中?以及我们如何应用人工智能并与其他团队合作,以便公司可以降低成本或获得更多利润。
在本节中,也有一些简单的用例来说明。
1.3.在贵公司建立人工智能
在这一部分,它在**中提到了更多关于如何在公司中建立人工智能的细节。**还描述了更详细的用例。当启动一个人工智能项目时,我们应该避免哪些事情。当我们想在一个公司内部开始一个项目时,我们应该做些什么。
1.4. AI 与社会
最后,还提到了人工智能的伦理和偏见。我们如何减少 AI 的偏见等等。以及人工智能在未来如何影响我们的工作、社会和经济。
2.真的适合所有人吗?
是的,它是为每个人特别是那些以前不知道人工智能的人准备的。这里不涉及数学。每个人都可以很容易地理解材料。
对于那些正在经营企业的人,或者一些管理级别的人,如董事和经理,值得阅读一下它,以了解他们可以应用人工智能来改变业务的任何机会。
另外,了解人工智能的优缺点也很重要。
如果有现有的 AI 团队,了解 AI 的一些概念肯定有助于和 AI 团队的沟通。因为了解了 AI,就能知道 AI 能做什么,不能做什么。这也是对每个需要和 AI 团队一起工作的员工有用的地方。
3.懂 AI 的人需要吗?
是也不是。
对于这个问题,我觉得对于懂 AI,懂业务的人来说是不需要的。比如说,如果你已经在一个 AI 团队工作,并且和其他非 AI 团队合作得很好,我觉得没必要上这门课。
对于我来说,我只知道一些机器学习或深度学习,特别是在计算机视觉领域。我是深度学习专业化第四期课程(CNN)的导师(也是吴恩达教授讲授的深度学习系列课程。).对我来说,我也从这门课中学到了很多。
上了这门课,我可以了解更多计算机视觉(或者你的领域)之外的用例,比如制造业,临床诊断,招聘,市场营销,甚至农业等。(当然,有很多方法可以了解 AI 的用例比如在网上看文章或视频,或者参加 AI 研讨会讲座。如果你只是想了解更多的用例,我认为不值得参加这个课程。)
我学会了需要做什么才能让人工智能和业务团队相互交流。而且我还了解到了AI 团队内部的工作岗位。至少,当我需要在大学之外找工作时,它是有用的。
4。已经学过吴恩达教授深度学习专业的人还需要吗?
是也不是。
还是那句话,懂 AI 的,懂业务的,不需要。比如说,如果你已经在一个 AI 团队工作,并且和其他非 AI 团队合作得很好,我觉得没必要上这门课。
但如果你只上过深度学习专精,那么也值得上这门课。如前所述,它更多地谈论了 AI 团队如何在公司内部进行交互,以及如何与业务团队进行交互,这些都不包括在深度学习专业化中。
如果你不懂 AI,又想有一份 AI 的工作,我建议把“深度学习专精”和“ AI for Everyone ”都上。两者兼而有之,才是进入 AI 领域的第一步。之后更有可能对人工智能进行更多的研究。
如果只是想学习深度学习的核心,不如去上深度学习专精学技术的东西。当然,我只能分享我在课程中学到的东西。也许对你来说不是这样的。但希望这个故事能提供一些帮助。😃
嘘…建造伟大人工智能的秘密
我为这个有点点击诱饵的标题道歉,但在看到埃隆·马斯克的推文后,我不得不创造了上面的迷因:
我认为那很好笑…不管怎样,回到你的常规编程。
当你完成机器学习的博士学位时,他们会把你带到一个特别的房间,向你解释伟大的数据比你刚刚学到的所有花哨的数学和算法更重要
至少,我是这样想象的。我没有博士学位,所以我不能肯定地说,但似乎有可能。
数据>>算法
这就是构建伟大的人工智能系统的秘密——拥有大量的数据。我可以在这里结束这篇文章,但是让我们看看一些支持的事实:
F 这是论文结论的一部分深度学习的扩展是可预测的,来自百度一个小组的经验。这是他们研究结果的图表之一:
上述图表根据经验显示,“随着我们为最先进的(SOTA)模型架构增加训练集,深度学习模型的准确性以幂律形式提高。”基本上,您可以使用幂定律来预测在训练数据增加的情况下,您的模型的性能会提高多少。现在,停下来想一想。改善深度学习模型的一个几乎肯定的方法是收集更多数据。对于无休止的模型调整和发明新架构的尝试,很难说同样的话。谷歌在他们 2009 年的论文数据的不合理有效性中也看到了这一点。
其次,GitHub 充满了开源的最先进的算法,但公开的数据却少得多。想要代码运行最新的深度学习模型吗?你可以在 GitHub 上找到它的一些版本。想要一些关于谷歌搜索结果表现或网飞收视率的数据吗?祝好运。公司意识到数据优势几乎总是优于算法优势。例如,Deep Mind 被谷歌以大约 5 亿多美元的价格收购。这是对惊人的天赋和算法的购买。两年前,脸书以 10 亿美元收购了 Instagram。为什么照片分享应用的价值是 Deep Mind 的两倍?在我看来,一个最大的原因就是数据。正如这篇福布斯文章所引用的
脸书的数据库需要这些信息来优化它将带给你的媒体。这些数据非常有价值!想象一下,你是一个滑雪胜地,想要接触滑雪爱好者,Instagram 将为他们提供一种新的方式,同时比脸书更有针对性。
如果你坐下来创建一份“伟大”人工智能公司的名单,你几乎肯定会发现,它们都是伟大的数据公司。如果你能从大量数据入手,构建近乎神奇的人工智能会容易得多。
L 这是报纸上的一张图表:
Source: Revisiting Unreasonable Effectiveness of Data in Deep Learning Era
这表明性能随着训练数据量的增加而呈对数增长。论文结尾还有一段惊人的引言:
而大量的时间花在工程和参数扫描上;很少甚至没有时间花在数据上。我们的论文试图将焦点放回到数据上。
将焦点放回到数据上
今天有多少公司在谈论建立一个数据科学团队?我明白了——雇佣那个极其聪明的麻省理工博士生很性感。我并不是说这是一件坏事。酪这些公司中有多少在谈论投资建立更大更好的数据集?我经常看到公司将数据视为固定资产,或者他们对数据投资非常怀疑。来吧,要求 10 万美元来创建您自己的专有数据集,这将使您的数据规模增加 10-1000 倍。让我知道这次谈话的进展(不过,这位高管可能会对雇佣另一位数据科学家更感兴趣)。
我希望我已经说服你更战略性地思考数据及其在人工智能工作中的价值。我向你发出挑战今天坐下来,思考你如何为你试图解决的任何问题获得更多更好的数据。这可能就像为你刚起步的电子商务商店打开谷歌分析一样简单。你未来雇佣的数据科学独角兽会感谢你的。
这篇文章也可以在这里找到。
我读了很多关于数据科学和领导力的书。我认为这可能有助于其他人每周发送一封电子邮件,其中包含我本周最喜欢的 3 篇文章。如果你有兴趣,就在下面报名吧!
为什么以消费者为中心的战略需要正确的数据集
将产品和管理团队转变为以消费者体验为导向的思维模式。
作者:夏娜·斯图尔特——产品经理, YML
如果你已经成功地将你的产品和高管团队转变为消费者体验驱动的思维模式——在产品体验中优先考虑对消费者的同情,你应该受到表扬。
然而,在培训团队和建立新流程的所有工作之后,你的产品和分析团队可能会经历一点摩擦。
成长的烦恼之所以会出现,是因为随着问题从以业务为中心发展到以消费者为中心,数据集并没有发展:
- 分析团队只能在业务分析和营销分析范式中运作。
- 因此,他们很难进入以产品和消费者为中心的分析范式。
专注于客户满意度是一件好事——并且是整个品牌业内公认的游戏规则改变者。
通常,转向消费者体验思维模式的团队会意外地将业务或营销数据误认为是产品数据,所以你需要停止关注量化的行为数据。
以下是方法。
以消费者为中心对数据结构来说很难
这主要与数据结构的构建方式有关:
数据结构是你所提问题的函数。
从历史上看,业务数据集是最古老的。他们被设计来回答这样的问题,“我赚了多少钱,我有多少付费客户?
引入营销数据集是为了回答围绕营销活动的执行、范围和影响的问题。
除了这两种,大多数公司都停止构建数据结构。现在,各种品牌都在努力通过一个过时的系统来回答营销和业务开发团队的关键问题。
你可能想知道:
在数据量以秒为单位呈指数增长的时代,我们怎么可能在一天中缺少数据集?
又一个很棒的问题!🧐
现实情况是,数据需要特定的结构来回答特定的问题。通常,数据是以非结构化的方式捕获的,然后需要重新结构化,以回答关键的产品和以消费者为中心的问题。
发展您的数据集
构建这些数据集是一项跨职能的团队运动。这是一项运动,因为它需要指导和练习,并且可以在团队之间产生一些竞争,以创建一个伟大的数据集。
第一步
👉有一个清晰简洁的以消费者为中心的战略。
以消费者为中心的策略需要有一个消费者之旅,当用户在消费者之旅中移动时,消费者的反馈和基于消费者需求的状态会通知这个消费者之旅。一旦完成,确保每个人都知道并同意这个策略。
Source: The consumer decision journey, McKinsey
如果人们开始动摇他们对战略的认同程度,以消费者为中心的分析就会失败,因为分析旨在提供关于战略执行情况的反馈。
如果人们开始不同意该战略或遵循不同的战略,那么以消费者为中心的分析框架将不会提供关于该战略执行情况的信息。
第二步
👉从头开始构建 KPI 结构,首先从以消费者为中心的 KPI 开始。
您的以消费者为中心的 KPI 应该描述您在消费者旅程研究中确定为战略行动的基于消费者需求的状态。他们还应该预测你的业务和营销关键绩效指标。
第三步
👉确定业务、营销、产品和以消费者为中心的问题之间的差异。
我们建议分析团队成员对他们经常被问到的问题进行分类。更进一步,开始对哪些团队提出了什么问题进行分类。
这将有助于稍后建立您的数据民主化策略。不是每个人都有兴趣得到所有问题的答案。为了重温不同类型的分析,看看这篇文章。
第四步
👉选择正确的工具和/或更新您的实施,以确保回答所有问题。
以消费者为中心的问题总是最难回答的,因为它们需要最复杂的数据能力来回答。因此,您的需求应该由以消费者为中心的分析需求引导,然后向后工作,以确保您的工具能够回答更简单的三个问题。
最后
要真正拥有以消费者为中心的数据集,每个人都必须具备一些关键要求:
- 访问围绕用户总结的数据,而不是围绕访问量或页面。
- 跨平台链接用户数据的策略,即身份解析系统
- 建立用户群组并基于这些群组开发定制营销和产品体验的计划和承诺
—
Shayna 是一名产品经理,热衷于以消费者为中心的产品战略和设计,并倡导以消费者为导向的数据战略。
最初发表于 YML — 为什么以消费者为中心的战略需要正确的数据集 。
展示人工智能解决方案
以酷而直观的方式交付数据科学解决方案
Photo by Filip Varga on Unsplash
对于任何数据科学家来说,最重要的技能之一就是能够清晰地向普通受众传达和部署结果。这些人需要理解这些见解,以便采取进一步的行动。不幸的是,太多的数据科学项目陷入了普通读者难以理解的数学和计算中。这就是为什么像 Shiny 这样的工具正迅速成为每个数据科学家最好的朋友。
发光的
Shiny 是一个用于开发交互式 web 应用程序的 R 包。它的一些好处:
- 多样性。您可以通过交互式图表、可视化、文本或表格来交流结果。
- 易用型。如果你已经知道 R,你可以快速开发一个很酷的闪亮的应用程序。查看这篇优秀教程,快速学习核心概念。
- 分享能力。内置功能让您可以轻松地与同事和朋友分享您的工作。
- 设计。甚至闪亮应用的默认显示也是优雅而直观的。
为了说服你,让我给你看两个例子。要自己运行这些示例,请查看这些说明。
基于天气的车祸预测
为了预测纽约市的汽车事故,我和我的团队建立了一个模型,我们根据汽车事故的历史数据以及 IBM 的天气数据进行训练。我们使用每个邮政编码的天气条件作为特征来训练具有 Spark 的逻辑回归,输出特定区域、日期和时间的车祸概率。这是一个闪亮的应用程序的屏幕截图,它在一个交互式地图中显示结果:
Probability of Accident by Zip Code Given Date and Time
计划你的下一个假期
我决定继续用旅行数据做实验,但是从汽车跳到了飞机。具体来说,我决定开发一个闪亮的应用程序,让用户探索美国每个机场的平均航班到达延误时间(以分钟计)。互动功能让用户探索预测的月份和年份,并让用户查看额外的数据,如机场名称,代码,州,城市和平均延误。在下面的截图中,气泡的大小与每个机场的航班量相关。负的平均延迟表示航班通常会提前到达。
Flight Arrival Delays
你想建立自己的闪亮的应用程序吗?
这只是 Shiny 帮助我们实施的两个项目。我们还将推出更多产品,我将很快与大家分享。同时,我鼓励你加入进来。同样,按照这些指令运行闪亮的例子。
推特:@ castan LinkedIn:@jorgecasta
shinymeta——再现性的革命
郑中在 2019 年 7 月向用户展示了 shinymeta,实现了 shiny 的可再现性。这是一个使用 shinymeta 的简单应用程序。你会看到反应性和再现性是如何不互相排斥的。我真的很感谢郑中实现了木卫三项目。
Reproducible R Code created from reactive shiny outputs
介绍
在 2018 年的 R/Pharma 大会上,我第一次听说了使用报价的概念。引用让你闪亮的应用程序代码可复制。这意味着您可以在 shiny 中进行试验,然后获取代码,生成与 R 代码完全相同的输出。制药行业需要这一特性。为什么会这样呢?制药行业需要向监管机构报告数据和分析。我已经在的几篇文章中谈到了这一点。给监管部门提供一个闪亮的应用有多好?太好了。如果能提供一个闪亮的应用程序,让他们能够重现每一个图形或表格,那该有多好?甚至更好。
阿德里安·沃德尔和道格·凯尔科夫是我的两个大学,他们为这项任务提出了解决方案。Doug 构建了 scriptgloss 包,它从闪亮的应用程序中重建静态代码。Adrian 在 R/Pharma 2018 上展示了一个模块化的基于 shiny 的探索性框架。该框架提供动态编码、基于变量的过滤和 R 代码生成。在这种背景下,我在当前的开发项目中开始构思一些概念。如何让闪亮 app 内部的代码具有可复制性?与此同时,道格、郑中和卡森·西沃特开发了一款名为 shinymeta 的迷人工具,并于 7 月 11 日在 userR 大会上发布。
这个工具非常迷人,因为它为我谈到的任务创建了处理程序。它允许将一个简单的闪亮的应用程序变成一个可复制的闪亮的应用程序,只需要一些调整。由于制药行业的闪亮应用对这一功能有着强烈的需求,我是制药行业的闪亮开发者,我想知道:它是如何工作的?有多好?
让我们创建一个与制药相关的闪亮应用程序
作为制药行业中一个闪亮应用的简单例子,我将使用一个线性回归应用。该应用程序将检测有用的线性模型是否可以显示患者属性和存活率之间的相关性。患者的属性是年龄或性别。存活率包括患者将存活多长时间(OS =总生存期)、无进展生存期(PFS =无进展生存期)或无任何事件发生生存期(EFS)。每个病人都可能经历了全部三个生存阶段。让我们用随机数据为这个用例创建数据集:
library(tibble)
library(dplyr)# Patient listingpat_data <- list(
SUBJID = 1:200,
STUDYID = c(rep(1, 40), rep(2, 100), rep(3, 60)),
AGE = sample(20:88, 200, replace = T) %>% as.numeric(),
SEX = c(sample(c("M", "F"), 180, replace = T), rep("U", 20)) %>% as.factor()
) %>% as_tibble()# Days where Overall Survival (OS), Event free survival (EFS) and Progression Free Survival (PFS) happenedevent_data <- list(
SUBJID = rep(1:200, 3),
STUDYID = rep(c(rep(1, 40), rep(2, 100), rep(3, 60)), 3),
PARAMCD = c(rep("OS", 200), rep("EFS", 200), rep("PFS", 200)),
AVAL = c(rexp(200, 1 / 100), rexp(200, 1 / 80), rexp(200, 1 / 60)) %>% as.numeric(),
AVALU = rep("DAYS", 600) %>% as.factor()
) %>% as_tibble()
可以看到患者年龄和性别(性别)是随机分布的。存活天数将呈指数下降。通过这些分布,我们不期望在数据中看到任何东西,但是对于这个例子来说这很好。
Simple app showing a linear regression of patient data
在截图中,您可以看到应用于这些数据的应用程序。该应用程序包含回归图和用lm
创建的线性模型的摘要。它基本上有一个输入通过PARAMCD.
过滤event_data
,第二个输入从pat_data
中选择列。这个应用程序有趣的部分是服务器功能。在服务器函数内部,只有两个输出和一个反应值。反应执行多个步骤。它生成线性模型的公式,过滤event_data
,选择pat_data
,合并数据集,并通过lm
计算线性模型。这两个输出从线性模型生成一个图和一个摘要文本。
server function to create a plot and a summary output from a linear model
当然,你以为这个 app 可以被一个聪明的程序员轻松复制。现在想象你只看到用户界面和输出。少了什么?缺少两样东西:
- 如何创建数据?
- 用于创建线性模型的公式是什么?
让我们把 app 做的可复制!
通过 shinymeta 和元编程的方法,我们将使整个应用程序可复制。即使 shinymeta 仍然是实验性的,你会看到,现在它工作得很好。
但是我们需要一步一步来。元编程背后最重要的想法来自艾德里安·沃德尔。你不用在你的应用程序中添加代码,而是用引号将代码括起来。(第一步,也是最重要的一步)。
创建数据
我们可以将此用于添加到应用程序的数据:
我们不运行代码,而是将它包装到quote
中。这将返回一个call
,我们可以通过eval
对其进行评估。它实现了再现性。我们用来生成数据集的代码存储在data_code
中。我们可以在以后重用这个变量。这个变量将允许我们显示数据集是如何构建的。
过滤和选择数据
为了实现可重复的过滤和选择,我们将使用 shinymeta 函数。因此,我们将创建一个返回合并数据集的metaReactive
。metaReactive 的行为类似于reactive
,不同之处在于,您可以在之后获取内部使用的代码。这类似于引用的原理。但是对于metaReactive
你不需要使用eval
函数,你基本上可以像以前一样坚持使用()
评估。
metaReactive
内部一个重要的新操作符是!!
(bang,bang)操作符。它允许插入标准电抗值。它的行为有点像在rlang
包中。您可以使用它来内联标准无功值的值。或者您可以使用它将metaReactive
对象作为代码内联。总之,操作器!!
有两个功能:
- 取消对反应对象的引用—获取它们的值
- 通过将对象作为代码内联到彼此来链接
metaReactive
对象
为了更好地了解!!
操作者,请查看 shinymeta 简介:https://github.com/rstudio/shinymeta/tree/master/vignettes
此代码将用于过滤、选择和合并数据:
在代码内部,您可以看到!!
操作符与作为值的反应值input$select_regressor
和input$filter_param
进行交互。这意味着我们取消了对无功值的引用,用它的静态值替换它。这种反应的结果是合并的数据集。当然,这段代码不会运行,直到我们在服务器函数中的任何地方调用data_set_reactive()
。
创建模型公式
线性模型的公式将像以前一样创建:
有必要检查选择回归变量值,因为没有选择就不能导出模型
创建线性模型
无需元编程即可生成线性模型的代码如下:
lm(formula = formula_value, data = anl)
我们需要替换formula_value
和anl
。另外用一个metaReactive
代替无功。因此,我们使用函数metaReactive2
,它允许在元编程代码之前运行标准的闪亮代码。在这个metaReactive2
里面,有必要检查数据和公式:
validate(need(is.data.frame(data_set_reactive()), "Data Set could not be created"))validate(need(is.language(formula_reactive()), "Formula could not be created from column selections"))
metaReactive
data_set_reactive
可以像任何反应对象一样被调用。产生模型的代码应该是元编程的,因为用户想看到它。函数metaExpr
允许这样做。为了获得良好的可复制代码,调用需要如下所示:
metaExpr(bindToReturn = TRUE, {
model_data <- !!data_set_reactive()
lm(formula = !!formula_reactive(), data = model_data)
})
如果你不想在lm
调用中看到整个数据集,我们需要将它存储在一个变量中。
为了使代码可跟踪,您需要将!!
放在被动调用的前面。在data_set_reactive
之前,这允许回溯data_set_reactive
的代码,而不仅仅是输出值。
其次,我们可以通过!!
操作符取消对formula_reactive
的引用。这将直接将创建的公式插入到lm
调用中。
第三,bindToReturn
会强迫 shinymeta 写:
var1 <- merge(...)
model_data <- var_1
model_reactive <- lm(formula = AVAL ~ AGE, data = model_data)
代替
data_set_reactive <- merge(...)
{
model_data <- data_set_reactive
lm(AVAL ~ AGE, data = model_data
}
如果你想了解更多关于bindToReturn
特性的信息,github 上有一个关于 [bindToReturn](https://github.com/rstudio/shinymeta/issues/53)
参数的问题。最终的model_reactive
是这样的:
渲染输出
最后但同样重要的是,我们需要以可复制的方式输出图形和文本。代替标准的renderPlot
和renderPrint
函数,有必要将它们包装在metaRender
中。metaRender
支持输出元编程反应对象,代码可重复。为了获得模型的值和代码,再次使用了!!
操作符。
使用metaRender
也将使输出成为元编程对象。这允许以后检索代码,并使其可重复。
检索用户界面内的代码
重要!
很抱歉在这里使用大写字母,但这部分是真正的部分,这使得应用程序可复制。通过插入一个“ Show R Code ”按钮,该应用程序的每个用户都可以看到产生输出的代码。因此 shinymeta 提供了函数
expandChain
。下一节将展示如何使用它。
如果用户点击一个按钮,就像这个例子中的input$show_r_code
代码的模态应该弹出。在这个模态中,expandChain
函数可以处理(1)引用代码和(2) metaRender
对象。这种类型的每个对象都可以用在expandChain
的…
参数中。它将返回一个元表达式。从这个元表达式中,可以提取出 app 中使用的 R 代码。简单地使用formatCode()
和paste()
会让漂亮的代码出现在模态中。
请不要忘记metaRender
对象后的()
。
最终服务器功能和 app
All code can be found at https://github.com/zappingseb/shinymetaTest
在完成所有步骤后,您可以看到使用 shinymeta 的代码与标准的 shiny 代码没有太大的不同。主要是metaReactive
、metaReactive2
、metaExpr
、metaRender
、!!
、expandChain
是新学的函数。即使这个包仍然是实验性的,它在使一些反应性的东西也是可复制的方面做得非常好。我最喜欢的功能是混合使用reactive
和metaReactive
。通过在元代码中使用反应对象,开发人员可以决定哪些代码进入“ Show R Code ”窗口,哪些代码在幕后运行。您可以通过查看本教程的代码来检查自己。当然,这个特性是危险的,因为您可能会忘记将代码放在“显示 R 代码”窗口中,并且不是所有的代码都可以重新运行,或者您的可复制代码变得难看。
教程的全部代码发布在 github 上:https://github.com/zappingseb/shinymetaTest。
该应用程序在https://sebastianwolf.shinyapps.io/shinymetaTest运行。
App running at: https://sebastianwolf.shinyapps.io/shinymetaTest/
结束语
这是我第一次尝试将自己的作品打包成一个全新的包。这个例子中创建的应用程序是在我以前的日常工作中创建的。新的实验包 shinymeta 允许在大约 1 小时内从我的代码切换到元编程。我不仅切换了我的实现,而且由于这个包,我的实现也变得更好了。
Shinymeta 将在制药发光应用中发挥巨大作用。在郑中演讲一周后,我仍然对元编程的概念印象深刻。以及元编程是如何变得闪亮的。包装使闪亮真正可复制。它将为如何在监管领域使用 shiny 提供指导。此外,它将允许更多的用户用 R 编写代码,因为他们可以看到特定输出所需的代码。点击会让他们学习。
相关文章:
- 为什么我们需要对编程语言进行人类可读的测试?
- 让自定义输入变得简单的 7 个步骤
- 教程:R shiny 可视化活检数据的应用程序——在一家制药公司
购物者行为与购物车推荐系统探究
Photo by NeONBRAND on Unsplash
到更好地了解顾客并创造独特的购物体验是每一个商家为了给顾客创造价值而必须做的事情。我认为你可以通过使用机器学习分析你的客户购物体验/习惯来实现这一点。在这个项目中,我想通过分析客户以前的购买来探索他们的购物行为,并建立一个购物车推荐器,为他们提供量身定制的购物体验,以提高参与度。
我认为这对于企业来说是有价值的,原因有很多,例如:
- 有针对性的营销:分析你的客户在你的网站/应用程序上的虚拟足迹可以将你的有针对性的营销带到另一个层次!例如,您可以根据他们的购买历史,在个人层面推出他们最喜欢的商品的特价。
- 在一天中的特定时间,有策略地向每位客户推送不同的营销材料,因为这段时间是您的客户最喜欢购物或最喜欢登录您的应用程序的时间。
- 计算何时重新进货,提高库存周期的效率。
- 推荐他们可能想要添加到购物车中的商品,并通过个性化建议吸引您的客户。
以上只是你可以从顾客的购买历史中获得定量洞察的几件事。
我想解决的问题
对于这个项目,我想探讨以下几个问题:
- 通过分析购物者的购买历史,执行购物者行为分析,看看我是否能找到一些模式,比如顾客在一天/一周的不同时间喜欢购买什么样的商品,人们多长时间再订购一次他们以前购买过的相同产品等等。
- 购物车推荐器:利用顾客重新订购的商品和余弦相似度建立一个推荐系统。
项目设计
- 执行数据清理,将不同的表合并在一起,并进行探索性数据分析(EDA)。
- 分析客户行为,产生见解,并为讲述故事构建数据可视化。
- 定义模型评估的指标。
- 最后,创建一个购物车推荐系统,根据顾客的购买历史向他们推荐商品。
我使用的数据和技术
出于这个项目的目的,我能够在 Instacart 上找到一个客户购买历史数据集,这是 Instacart 在 2017 年发布的一个 Kaggle 挑战赛。
数据集有六种不同的。csv 文件,您需要使用主键和外键来连接它们,以获得完整的图片并执行分析。数据字典可以在这里找到。
我在这个项目中使用的工具是 numpy,pandas,matplotlib,seaborn,以及 sklearn 的 StandardScaler,OneHotEncoder 和 cosine_similarity。
清理&探索性数据分析(EDA)
该数据集拥有 20 多万客户的 300 多万份订单。它具有诸如星期几购买,一天中的时间购买,之前或之前重新排序等功能。
总共有 6 个不同的表:通道、部门、订单 _ 产品 _ 先验、订单 _ 产品 _ 系列、产品和订单。
经过一些检查,我发现数据集非常干净,只需要一些小的清理和争论,因为我在进一步分析之前将表合并在一起。
购物者行为分析
当我们分析数据集时,有些问题需要您回答。例如:
- 数据集有多少个订单?
- 我们有多少独特客户?
- 顾客多久购买一次?
- 他们喜欢什么时候购买?
- 他们每份订单购买多少件商品?
- 还有更多问题。
在本节中,我将探索数据集,以提取见解来回答不同的问题。
数据集有多少个订单?
在浏览 orders 表时,您可以使用下面的代码来找出数据集中有多少订单以及每个标签的订单数。
snapshot of orders table
print(orders.shape)
print('there are', len(orders[orders.eval_set == 'prior']), 'entries for prior')
print('there are', len(orders[orders.eval_set == 'train']), 'entries for train')
print('there are', len(orders[orders.eval_set == 'test']), 'entries for test')
- 一共 3421083 单。
- 有 3214874 个订单是优先订单。
- 训练集中有 131209 个订单。
- 测试集中有 75000 个订单。
数据集有多少不同的用户?
您可以使用下面的代码来找出有多少不同的用户。
print('there are', len(orders[orders.eval_set == 'prior'].user_id.unique()), 'unique customers in total')
print('there are', len(orders[orders.eval_set == 'train'].user_id.unique()), 'unique customers in train set')
print('there are', len(orders[orders.eval_set == 'test'].user_id.unique()), 'unique customers in test set')
- 共有 206209 个独立客户。
- 列车组中有 131209 个客户。
- 测试集中有 75000 个客户。
订单量如何分配?
你可以使用下面的代码来生成一个订单量分布图。
orders_amount_for_customer = orders.groupby('user_id')['order_number'].count().value_counts()
plt.figure(figsize=(20,8))
sns.barplot(x=orders_amount_for_customer.index, y=orders_amount_for_customer.values, color='mediumseagreen')
plt.title('Amount of Orders Distribution', fontsize=16)
plt.ylabel('Number of Customers', fontsize=16)
plt.xlabel('Amount of Orders', fontsize=16)
plt.xticks(rotation='vertical');
amount of orders distribution
- 每个客户的订单数量在 4 到 100 之间。大多数人购买了 4 到 10 次。
他们最喜欢在一周的哪一天购物?
您可以使用下面的代码将订单按一周中的不同日期分组。
plt.figure(figsize=(12,8))
sns.countplot(x=orders.order_dow, color='mediumseagreen')
*#plt.title("Order Amounts by Days", fontsize=16)*
plt.xlabel('', fontsize=16)
plt.xticks(fontsize=15)
plt.ylabel('Order Counts', fontsize=16)
plt.yticks(fontsize=15)
;
order amounts by day
- 0(周日)和 1(周一)一周订单最多,4(周四)订单最少。
人们在一天中的什么时候购物?
您可以使用下面的代码按一天中的小时将订单分组。
plt.figure(figsize=(12,8))
sns.countplot(x=orders.order_hour_of_day, color='mediumseagreen')
*#plt.title("Order Amounts by Hours", fontsize=16)*
plt.xlabel('Hour of Day', fontsize=16)
plt.xticks(fontsize=15)
plt.ylabel('Order Counts', fontsize=16)
plt.yticks(fontsize=15)
;
order amounts by hour
- 看起来人们喜欢在早上 8 点到下午 6 点之间点菜。
人们多久购买一次?
您可以使用下面的代码将订单按照最后一次购买的日期进行分组。
plt.figure(figsize=(12,8))
sns.countplot(x=orders.days_since_prior_order, color= 'mediumseagreen')
*#plt.title("Number of Orders per Days Since Last Purchase", fontsize=16)*
plt.xlabel('Days Since Last Purchase', fontsize=16)
plt.xticks(np.arange(31), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30], fontsize=15)
plt.xticks(rotation='vertical')
plt.ylabel('Order Counts', fontsize=16)
plt.yticks(fontsize=15)
;
days since last purchase
- 看起来大多数人一周点一次,在 0 点到 7 点之间。
- 而且还有 30 多天订一次的。
人们在一份订单中会购买多少件商品?
为了回答这个问题,我们将镜头转向另一组表:order_product_prior 和 order_product_train。
snapshot of order_product_prior and order_product_train
为了这个项目的目的,它不是为了 Kaggle 挑战提交,所以我把两个表连接在一起,以获得更好的图片。
# Concatenation of both tables.
order_products_total = pd.concat([order_products_prior, order_products_train]) # Create amounts of item per order.
frequency_per_number_of_order = order_products_total.groupby('order_id')['product_id'].count().value_counts()
plt.figure(figsize=(20,8))
sns.barplot(x=frequency_per_number_of_order.index, y=frequency_per_number_of_order.values, color='mediumseagreen')
plt.title('Amount of Items Per Order', fontsize=16)
plt.ylabel('Order Counts', fontsize=16)
plt.xlabel('Number of Items', fontsize=16)
plt.xticks(rotation='vertical');
amount of items per order
- 人们通常每份订单购买 4 件商品。
- 大多数人喜欢每份订单购买 3 到 8 件商品。
这个数据集中有多少交易和独特的产品?
我们可以用下面的代码来回答这个问题。
print('there are', order_products_total.shape[0], 'grocery products ordered')
print('there are', len(order_products_total.order_id.unique()), 'order transactions')
print('there are', len(order_products_total.product_id.unique()), 'unique products')
- 订购了 33819106 种杂货产品。
- 订单交易有 3346083 笔。
- 有 49685 个独特的产品。
在所有订单中,有多少是之前重新订购的,有多少是没有重新订购的?比例是多少?
下面的代码将回答这个问题。
# Find out how many products have been reordered before.
print(len(order_products_total[order_products_total.reordered == 1]), 'products have reordered before')
print(len(order_products_total[order_products_total.reordered == 0]), 'products haven**\'**t reordered before')# Find out the ratio.
print(len(order_products_total[order_products_total.reordered == 1])/order_products_total.shape[0], 'have reordered before')
print(len(order_products_total[order_products_total.reordered == 0])/order_products_total.shape[0], 'haven**\'**t reordered before')
- 19955360 产品之前有过再订购。
- 13863746 产品之前没有再订购过。
- 0.59 之前有重新排序。
- 0.41 之前没有重新排序。
每个产品类别中有多少个产品,拥有最多产品的前十个产品类别是什么?
为了回答这个问题,我们将研究过道、部门和产品表。
snapshot of aisle, department and products tables
# Merging tables together.
products_departments = products.merge(departments, left_on='department_id', right_on='department_id', how='left')
products_departments_aisles = products_departments.merge(aisles, left_on='aisle_id', right_on='aisle_id', how='left')
products_departments_aisles.head()# Counting how many items is in each product category.
products_departments_aisles.groupby('department')['product_id'].count().reset_index().sort_values(by='product_id', ascending=**False**).head(10)
top 10 product categories that have most items.
人们购买最多的物品是什么?
为了探究这个问题,我们需要将 products_departments_aisles 和 order_products_total 表合并在一起。
# Merging products_departments_aisles and order_products_total.
df = order_products_total.merge(products_departments_aisles, left_on='product_id', right_on='product_id', how='left')
df.head()# Find out the top 15 items people purchased the most.
top_15_products = df.product_name.value_counts(ascending=**False**).reset_index().head(15)
top_15_products.columns = ['product_name', 'count']
top_15_products
top 15 items people purchased the most.
- 人们购买最多的前 15 种商品在上面。
- 其中大部分是有机水果/蔬菜。所有的都是水果/蔬菜。
使用相同的逻辑,我们可以找出人们购买最多的前 15 个通道和前 15 个部门。
# Finding top 15 aisles.
top_15_aisles = df.aisle.value_counts(ascending=**False**).reset_index().head(15)
top_15_aisles.columns = ['aisle_name', 'count']
top_15_aisles# Finding top 15 departments.
top_15_department = df.department.value_counts(ascending=**False**).reset_index().head(15)
top_15_department.columns = ['department_name', 'count']
top_15_department
top 15 aisles and top 15 departments that has the most purchases in.
每个部门和通道的再订购率是多少?
# Find out reorder ratio per department.
reorder_ratio_per_dep = df.groupby('department')['reordered'].mean().reset_index()
reorder_ratio_per_dep.columns = ['department', 'reorder_ratio']
reorder_ratio_per_dep.sort_values(by='reorder_ratio', ascending=**False**)# Find out reorder ration per aisle.
reorder_ratio_per_aisle = df.groupby('aisle')['reordered'].mean().reset_index()
reorder_ratio_per_aisle.columns = ['aisle', 'reorder_ratio']
reorder_ratio_per_aisle.sort_values(by='reorder_ratio', ascending=**False**)
- 每个部门的乳制品鸡蛋的再订购率最高。
- 个人护理部门的再订购率最低。
- 牛奶通道的再订购率最高。
- 香料调味料的每条通道的再订购率最低。
定义指标
我想为我的购物车推荐者定义一个指标。人们喜欢使用不同的通用指标进行评估。例如:
precision vs. recall
对于我的项目,我决定使用回忆作为我的评估标准。也就是说,顾客购买的商品中有多少是来自推荐者的?
例如,如果我向顾客推荐 5 件商品,他/她买了 4 件,这意味着召回率= 0.80。换句话说,我推荐的商品有 80%在顾客的购物车里,20%是我推荐给顾客的新商品。
购物车推荐器
构建推荐系统有不同的方式,例如,基于内容的过滤,协同(基于项目或基于用户)过滤,以及两者的混合。在这个项目中,我将探索如何使用余弦相似度构建购物车推荐器,这是协同过滤下的一种方法。
推荐器的设计是先找出之前重新订购过的客户,以及之前重新订购过的商品。然后计算所有这些用户和产品之间的余弦相似度。然后生成一个包含 5 条建议的列表。
下面是如何找到以前重新排序的客户并计算余弦相似度的代码。
*# get the list of orders that have been reordered before*
reorders = order_products_total[order_products_total['reordered'] == 1]orders2 = orders[['order_id', 'user_id']]*# merge to get user_id and product_id*
user_orders = reorders.merge(orders2, on='order_id')*# filtering out the high volumn products that user reordered more than once*
user_orders['high_volume'] = (user_orders['product_id'].value_counts().sort_values(ascending=**False**)>1)
high_volume = user_orders[user_orders['high_volume'] == **True**]*# get a matrix of different high volume items that particular user purchased*
high_volume_users = high_volume.groupby(['user_id', 'product_name']).size().sort_values(ascending=**False**).unstack().fillna(0)*# calculate similarity between each user*
cosine_dists = pd.DataFrame(cosine_similarity(high_volume_users),index=high_volume_users.index, columns=high_volume_users.index)cosine_dists.head()
snapshot of how the matrix looks like.
这是为推荐系统定义一个功能。并尝试根据与我们的目标客户有相似购买历史的相似资料推荐 5 件商品。
**def** Recommender_System(user_id):
*'''*
*enter user_id and return a list of 5 recommendations.*
*'''*
u = high_volume.groupby(['user_id','product_name']).size().sort_values(ascending=**False**).unstack().fillna(0)
u_sim = pd.DataFrame(cosine_similarity(u), index=u.index, columns=u.index)
p = high_volume.groupby(['product_name','user_id']).size().sort_values(ascending=**False**).unstack().fillna(0)
recommendations = pd.Series(np.dot(p.values,cosine_dists[user_id]), index=p.index)
**return** recommendations.sort_values(ascending=**False**).head()# recommendation for customer id 175965.
Recommender_System(175965)
5 recommendations generated for customer id 175965
估价
为了更好地说明,我以自己为例:
purchase history and recommendation for user Ka.
在左边,是用户 Ka 之前购买的前 20 个项目的列表。右边是我的推荐者生成的 5 个推荐列表。如你所见,我推荐的 5 件商品中有 4 件与 Ka 的前 20 件购买记录相符。这意味着我推荐的商品有 80%的机会出现在用户的前 20 个商品列表中。
使用与评估标准相同的逻辑。为了计算推荐器的召回分数,我定义了一个函数来完成这项工作,下面是代码。数据帧太大,无法处理,所以我将数据帧分成 7 份进行度量计算。
# filter 1000 users for calculation
# because the dataframe is too large
users = high_volume.user_id.unique().tolist()# calculate recall for the :1000 users
**def** how_match():
res = []
**for** user **in** sorted(users)[:1000]:
recommendations = Recommender_System(user)
top_20_itmes = _[_.user_id == user].product_name.value_counts().head(20)
recommendations_list = recommendations.index.tolist()
top_20_items_list = top_20_itmes.index.tolist()
res.append((len(set(recommendations_list) & set(top_20_items_list)))/5)
**return** np.mean(res)*# get metric for the :1000 users*
how_match()*# calculate the mean of all the metric from all the Recommender notebooks.*
print('The Final Score for Metric is', (0.531 + 0.522 + 0.519 + 0.530 + 0.523 + 0.519 + 0.526)/7)
最终的召回分数是 0.524,这意味着我推荐的商品有大约 52%的机会出现在用户的前 20 个商品列表中,这比仅仅从 50k 多个产品中随机猜测要好得多。大约一半的商品是我向顾客推荐的新产品。
为了更好地了解我的推荐器有多有效/强大,我认为最好的方法是运行 A/B 测试实验。
经验教训
- 关于如何建立一个推荐器,有许多研究、类型和不同的方法。你真的需要花很多时间去做你的调查研究。没有捷径可走,你需要尝试不同的方法,使用你的数据来建立比较推荐。
- 预计你的数据框架将是巨大的后,你为每个客户和项目创建虚拟。所以需要探索方法,例如:矩阵,使你的输入更可读或更省时,让你的机器来做计算。
在将来
- 创建一个 Flask 应用程序,并将其部署到网上,让人们体验推荐者。
- 使用这个推荐者做一个可以练习/探索 A/B 测试的项目。
- 尝试使用数据集来构建不同类型的推荐器。
- 探索 Turi Create ,苹果现在拥有的开源 ML 工具,用于构建推荐器并与不同类型的推荐器进行比较。
非常感谢您的阅读,如果您有兴趣探索我使用的代码和资源,这个项目在我的 github repo 上。
用你的相机购物:视觉搜索如何改变电子商务
视觉搜索正在席卷零售业。
当客户进行视觉搜索时,他们使用图像而不是关键字来寻找产品。购物者可以给他们想买的东西拍照(比如路人穿的一双运动鞋),然后上传到他们选择的视觉搜索引擎——比如谷歌图片或 Pinterest Lens。视觉搜索引擎将有助于在网上找到它,并建议接近的匹配。
在数字时代注意力持续时间迅速缩短的情况下,视觉搜索能力在抓住顾客想象力方面发挥着不可或缺的作用。现在,顾客比以往任何时候都更容易在网上找到他们想要购买的商品或发现他们想要购买的商品。
Pinterest 首席执行官本·希伯尔曼说:“搜索的未来很大程度上将取决于图片,而不是关键词。
到 2021 年,重新设计网站以支持视觉和语音搜索的早期采用者品牌将使数字商务收入增加 30% 。
交付真正无缝的客户体验
人们每月在 Pinterest 上进行超过 6 亿次视觉搜索,而且这个数字还在增长。62%的千禧一代渴望视觉搜索超过任何其他新的数字购物技术。
有了视觉搜索工具,人们可以拍一张照片来发现多个网站和零售商的类似产品。例如,Google Lens 从 Google Shopping 中提取类似的产品示例。
其他零售商在他们自己的品牌中使用视觉搜索来缩小看到和购买之间的差距。例如,ASOS 的移动应用程序有一个名为 Style Match 的搜索工具,让购物者拍摄或上传照片,然后从他们的目录中发现与之匹配的产品。通过提供可以匹配 850 多个品牌和 85,000 多种产品的工具,ASOS 鼓励用户向他们购买。他们通过向用户展示他们不会像去其他地方那样花费太多来吸引用户。用户可以上传一张设计师产品的图片,找到更实惠的款式与之搭配。
在提供真正无缝的体验方面,人工智能支持的视觉搜索消除了观看和购买之间的摩擦。
当用户返回网站时,无摩擦的体验继续。下一次访问提供了更个性化、更强大的目标搜索,用户可以从上次离开的地方重新开始,更快地找到相关产品。
把“缺货”变成机会
一个访问者访问一个网站,想要购买一件特定的衣服。一旦她进入产品页面,她会看到一个模特穿着那条裙子,戴着项链、手表、帽子和一双高跟鞋——所有这些都可以在网站上找到。
视觉搜索人工智能将让游客知道他们可以轻松地购买整个外观,而不是一个项目,并将向他们展示类似的选项。这增加了顾客在完成购买前将额外物品放入购物车的可能性。
各大品牌也在利用视觉搜索,在顾客被诱惑离开电子商务网站时,给他们一个温和的提示,让他们继续购物。
当客户访问网站并发现他们想要购买的产品缺货时,他们会感到失望。通常,他们会关闭标签页,或者转到另一个有类似功能的网站。
视觉搜索技术有助于让购物者留在网站上,即使他们最初想要的商品已经售完,也可以通过向他们展示库存中的类似产品来实现。
领先的在线零售商 Boohoo 的电子商务网站在实施视觉搜索后出现了巨大的增长。在最近的一项案例研究中,Boohoo 报告称当访问者在产品展示页面上使用“查看相似”时,转化率会高出 100%以上。每个会话的页面增加了 135%以上。
模糊线下和线上的界限
Lonely Planet 最近收购了 TRILL Travel,这是一个人工智能驱动的视觉搜索平台,可以将社交媒体图像转化为即时可预订的体验。TRILL 利用人工智能技术分析图片,并自动创建预订网站的链接。
通过强大的视觉搜索机制简化预订流程有助于缩小旅游癖和现实之间的差距。
用户可以很容易地从浏览 Instagram 上的旅行照片到获得参观这些确切目的地的门票。只需触摸图片,他们就可以预订酒店、体验或在餐厅用餐。
线上和线下世界前所未有地融合在一起。有了视觉搜索,公司可以更接近许多消费者渴望的即时满足感。
视觉搜索的美妙之处在于,它可以点燃想象力,然后激发并捕捉由此产生的购买意图。视觉搜索将不可避免地在未来几年严重扰乱电子商务行业。
短篇小说:快速分析集
以下六个场景涉及到各种需要回答问题的情况。每个数据集只涉及几个变量,以帮助缩小分析的重点。当我们在每个小故事中寻找答案时,请跟着读。
下面介绍的练习册都可以在我的 Tableau 公共档案和 GitHub 上找到。
客户满意度
场景:一家公司收集一段时间内的客户满意度,记录有多少客户得到了服务,以及客户是否满意。2018 年 3 月,该公司失去了三名员工,然后在 2018 年 11 月,他们增加了两名新员工。客户满意度是如何受到影响的?
Customer satisfaction over time
在第一张图表中,我们可以看到客户满意度是如何随时间变化的。该公司平均每月约 90%,直到 2018 年 6 月,届时该百分比将下降。这可能是因为 3 月份损失了 3 名员工;该公司股价立即下跌,随后在 5 月份小幅回升,随后大幅下跌。满意度连续几个月保持低位,8 月份低至 68.4%。2018 年 11 月,该公司雇用了 2 名新员工,以帮助取代 3 月份失去的 3 名员工。这似乎对客户满意度有很大的影响,因为百分比立即增加到几乎 95%。
我们还可以研究客户满意度的变化是否与接受服务的客户数量有任何关系。在本研究的时间段内,总访问量从 2018 年 5 月的 13,000 次到 2018 年 1 月的 24,000 次不等。2018 年 3 月 3 名员工离职后,客户量似乎确实有所下降。虽然没有同期客户满意度下降那么显著,但似乎有更持久的影响。虽然在 11 月雇佣 2 名员工后客户满意度有所恢复,但随着时间的推移,客户数量似乎稳定在较低的水平。我们可以在客户数量的负斜率趋势线中看到这一点。
进入市场
场景:一家公司有兴趣进入城市市场。他们已经对市场进行了一段时间的监测,并试图预测他们自己的潜在销售额。数据库中的所有产品都是竞争对手(都是‘ville’产品)。他们相信他们能够在市场上实现中等或平均的销售额。他们实现目标的可能性有多大?
Market analysis for the ‘ville genre
这家公司有一个雄心勃勃的目标,即在“城市游戏”市场上达到平均或中等销售额。正如我们在面积图上看到的,市场平均每年的销售额约为 920 亿美元,而中位数略低,为 905 亿美元。将这些价值与每家公司的平均年销售额相比,前景并不乐观。最畅销的产品 Township 和 Harvest Moon 的平均总销售额不到 600 亿美元,这只是该公司设定的目标的一小部分。总体而言,公司每年的销售额约为 170 亿美元。更糟糕的是,2017 年市场总销售额下降。它在 2018 年开始复苏,但在市场本身勉强价值 1000 亿美元的情况下,将很难达到 900 亿美元的崇高目标。
对一家新公司来说,一个积极的方面是最近城市市场的多样化。尽管 Harvest Moon 和 Township 占据了几年的主导地位,但几个竞争对手的引入降低了它们的市场份额。热图显示了从 2012 年到 2015 年对市场的强大控制,但在 2016 年,像农场天堂这样的产品几乎与他们的销售持平。接下来的几年里,Farm Paradise 的销售额下降,但其他进入市场的产品帮助更多的公司扩大了市场价值。虽然新公司可能需要重新调整他们的目标,但很大一部分市场可能会按照他们的方式发展。
项目状态
场景:一个公司一直在收集它的项目状态(错过、满足、超过)。它关心的是它的项目状态如何随着时间的推移而变化。它想知道它的项目状态的百分比和绝对分数。随着时间的推移,我们可以看到项目状态的哪些模式?
Project status tracking over time
查看数据,我们可以看到该公司遇到了一个问题,即错过项目状态的频率越来越高。从 2016 年到 2018 年,项目总数有所增加,但目标也有明显差异。从 2016 年到 2017 年中期,该公司稳步达到或超过了项目目标。然而,2017 年 Q2 奥运会后,超额完成目标的数量从 88 个开始下降。在 2018 年 Q2 奥运会上,该公司的超额目标数量最低,同期只有 18 个。积极的一面是,met 目标在 2017 年保持相对稳定,然后在 2018 年初增加。
更令人担忧的是,未达到目标的比率开始上升,同时超过目标的比率开始下降。2018 年的失球率异常高,第三季度达到约 31.3%。2016 年为 2.6%,仅两年时间就发生了显著变化。虽然每个季度实现的目标保持在 9-13%左右,但从超额目标到未实现目标的变化值得关注。
功能满意度
场景:一家公司一直在收集客户对其功能的满意度信息,排名从完全不满意到完全满意。它想知道哪些功能是流行的,哪些是无用的。虽然调查使用了李克特量表的 5 个选项,但它认为完全满意和非常满意彼此非常相似。它还认为完全不满意和不太满意彼此非常相似。哪些功能提供最高和最低的满意度?哪些功能用得最少?
Feature ratings from high to low
平均而言,65%的客户对他们使用的功能评价很高。大约 24%的人认为功能仅有些满意,超过 10%的人认为他们使用的功能满意度较低。评分最高的功能包括安全性、性能和范围,而一些评分最低的功能包括加热方向盘和 LED 照明。性能和安全对于车辆的正常运行至关重要,这可以解释为什么很少有客户表示他们不使用这些功能。
一些功能也很少被用户使用。音频系统是最少使用的功能,超过一半的客户表示他们没有使用过。在使用过音响系统的人中,只有 55.1%的人表示非常满意,远低于所有功能 65%的平均水平。其他一些不太受欢迎的功能是交付时间和保修,可能是因为被客户视为车辆不太必要的功能。
信息视频
场景:一家公司对市场进行了初步调查,以确定潜在客户是否认为他们的产品会让他们满意。然后向顾客展示了一段详细介绍产品特性的短片。公司再次调查了潜在客户,以确定他们的产品是否会令他们满意。视频播出后,态度有变化吗?
Pre- and post-video survey results
我们可以看到,观看视频后,犹豫不决的客户数量明显下降,而意见则相应增加。总的来说,数据表明,视频有助于以一种大多数顾客感到满意的方式描述产品。在更广泛的层面上,视频似乎有助于解释或解决客户可能有的问题,并帮助引导他们做出明智的决定。
40%的顾客在观看视频前犹豫不决,但这一数字下降到 14%,因为他们能够做出决定。虽然这四种观点都有所增加,但增加最多的是那些强烈认为产品会让他们满意的人。在观看视频之前,只有 19%的顾客强烈认为产品令人满意,但之后这一比例翻了一番,达到了 38%。25%的人在看到视频前表示同意。这一比例略微上升至 30%,在视频放映后,这一比例位居第二。甚至负面意见也增加了,尽管不同意或强烈不同意的人各只增加了 1%。
音乐欣赏
场景:每年,一个非盈利机构要求潜在的捐赠者帮助推进它的音乐事业。它要求捐赠者支持不同的音乐流派(古典、乡村、爵士、歌剧和摇滚)。每年它都瞄准一批潜在的捐助者来帮助支持它的事业。筹款有多成功?什么是进步,什么不是?
Music donation trends over time
在这 5 个领域中,古典音乐和爵士乐似乎每年都有最大的增长。这两个领域都比其他三个领域有明显更陡的斜率,尽管值得注意的是,直到最近,爵士乐每年的资助人数都是最低的。2018 年,它超过了 Country,其趋势线可用于预测未来几年的持续增长。摇滚和乡村音乐似乎每年都略有增长,而歌剧几乎没有增长。2016 年,除了爵士乐,几乎所有领域都出现了下滑。
有理由假设爵士乐是 2016 年的重点,因为它是唯一一个正增长的领域。歌剧和摇滚每年分享相似的资金数字,表明它们经常同时被推向市场。国家明确定义了每年交替的“好”和“坏”年份,暗示该地区何时成为目标。Classical 每年的稳定增长可以表明两种理论:要么该区域几乎每年都有目标,要么不管该区域是哪一年的焦点,它都继续增长。该机构可能会受益最大,继续增长爵士乐,同时也培养国家,试图促进其年度增长。
短文本主题建模
直觉和代码来理解和实现短文本的主题建模,比如社交媒体(Tweets,Reddit 的帖子…)
Photo by Hello I’m Nik 🇬🇧 on Unsplash
主题建模的目的是在一个文本语料库(如邮件或新闻文章)中找到主题(或聚类),而不需要先知道那些主题。这就是主题建模的真正力量所在,你不需要任何带标签或带注释的数据,只需要原始文本,从这种混乱的主题建模算法中会找到你的文本所涉及的主题!
在这篇文章中,我们将描述最流行的主题建模方法 LDA 背后的直觉和逻辑,并了解它对短文本的限制。鉴于这篇文章是关于短文本主题建模** ( STTM )我们将不深究 LDA 的细节。想要加深对 LDA 的了解的读者可以在这里和这里找到关于 LDA 的优秀文章和有用资源。
然后,在第二部分中,我们将介绍一种新的 STTM 方法,最后在第三部分中了解如何在玩具数据集上轻松应用它(拟合/预测✌️)并评估其性能。**
已经熟悉 LDA 和主题建模的读者可能想跳过第一部分,直接进入第二和第三部分,这两部分介绍了一种新的短文本主题建模及其 Python 编码的方法🐍。
一.潜在的狄利克雷分配
最流行的话题建模算法是 LDA,潜在狄利克雷分配。让我们首先解开这个令人印象深刻的名字,对它的作用有一个直觉。
- 潜伏因为题目很“隐蔽”。我们有一堆文本,我们希望算法将它们分成对我们有意义的簇。例如,如果我们的文本数据来自新闻内容,通常发现的聚类可能是关于中东政治、计算机、空间…但我们还不知道它。
- 狄利克雷代表狄利克雷分布,该模型将其用作生成文档-主题和词-主题分布的先验。
- 因为我们想给我们的文章分配主题。
下面的图 1 描述了 LDA 步骤如何在文档语料库中清晰地找到主题。
“通过对这些主题的混合物进行采样,然后从该混合物中对单词进行采样,生成一个文档”(吴恩达、大卫·布莱和迈克尔·乔丹,来自 LDA 最初的 论文 )。
Figure 1: LDA documents generation process using Dirichlet distribution.
NB :在上面的图 1 中,为了便于说明,我们在词汇表中设置了 K=3 个主题和 N=8 个单词。为了便于说明,我们还将这些主题命名为计算机、空间和中东政治(而不是称它们为主题 1、主题 2 和主题 3)。事实上,我们的任务是理解 3 个发现的主题是关于计算机、空间和中东政治的内容(我们将在第三部分 STTM 管道的主题归属中更深入地了解这一部分)。
简而言之,LDA 通过使用狄利克雷分布作为先验知识来生成由主题组成的文档,然后更新它们,直到它们匹配基本事实。
二。短文本主题建模(STTM)
尽管 LDA 在中型或大型文本(> 50 个单词)上取得了很好的效果,但通常邮件和新闻文章都在这个大小范围内, LDA 在短文本上表现不佳,如 Tweets、Reddit 帖子或 StackOverflow titles 的问题。
Figure 2: Example of short texts and the topic they discuss.
查看上面图 2 中的短文本示例,很明显,假设文本是主题的混合物(记住图 1 中的第一步)不再正确。我们现在假设一篇短文仅由的一个主题组成。
Gibbs 抽样 Dirichlet 混合模型 ( GSDMM )是一种“改变的”LDA 算法,在 STTM 任务上表现出很好的结果,这使得最初的假设: 1 主题↔️1 文档。文档中的单词是使用相同的唯一主题生成的,而不是像在原始 LDA 中那样来自主题的混合。
在深入代码和实践方面之前,让我们先了解一下 GSDMM 和一个称为电影组过程的等效过程,它将帮助我们了解 STTM 的不同步骤和过程,以及如何有效地调优其超参数(我们记得 LDA 部分的 alpha 和 beta)。
想象一下,一群学生在餐馆里,随机坐在 K 张桌子旁。他们都被要求在纸上写下他们最喜欢的电影(但必须是一个简短的名单)。目标是以这样一种方式将他们聚集在一起,使得同一组中的学生分享相同的电影兴趣。为此,学生必须根据以下两条规则逐一选择新的桌子:
- 规则一:选择学生多的桌子。这条规则提高了完整性,所有对同一部电影感兴趣的学生都被分配到同一个桌子上。
- 规则 2:选择一张桌子,让学生分享相似电影的兴趣。这个规则旨在增加的同质性,我们只希望成员们在一张桌子上分享同一部电影的兴趣。
重复这个过程后,我们预计一些表格会消失,另一些会变得更大,最终会有一群学生符合他们对电影的兴趣。这就是 GSDMM 算法所做的事情!
三。STTM 实施
在这一部分中,我们将使用 Scikit-learn 中用于文本主题建模的 20 个新闻组数据集,从一个具体示例中构建完整的 STTM 管道。
首先,我们需要从 Github 下载 STTM 脚本到我们的项目文件夹中。
cd sttm_project
git clone [https://github.com/rwalk/gsdmm.git](https://github.com/rwalk/gsdmm.git)
现在,我们可以开始实现 STTM 管道(这是我使用的笔记本的静态版本)。
# Useful libs
from sklearn.datasets import fetch_20newsgroups
import pickle
import pandas as pd
import numpy as np# STTM lib from Github
from gsdmm import MovieGroupProcess# Custom python scripts for preprocessing, prediction and
# visualization that I will define more in depth later
from preprocessing import tokenize
from topic_allocation import top_words, topic_attribution
from visualisation import plot_topic_notebook# Load the 20NewsGroups dataset from sklearn
cats = ['talk.politics.mideast', 'comp.windows.x', 'sci.space']
newsgroups_train = fetch_20newsgroups(subset=’train’, categories=cats)
但是在这个练习中,我们不会用新闻的全部内容来从中推断一个话题,而是只考虑新闻的主题和第一句话(见下图 3)。事实上,我们需要短文本来进行短文本主题建模…很明显🙏
此外,为了便于说明,我们将只查看 3 个主题(均匀分布在数据集中)。这些主题如下:
- 中东政治🌍
- 空间👾
- Windows X 🖥
Figure 3: Example of a news about the topic: Windows X. We concatenate these 2 highlighted sentences together to have a document.
# Preprocessing and tokenization
tokenized_data = tokenize(df, form_reduction='stemming', predict=False)
以下是我在这项任务中遵循的预处理配方:
- 使用 spaCy 记号化器进行记号化。
- 删除停用词和 1 个字符的词。
- 使用 nltk 库的词干分析器进行词干分析(根据我的经验,我观察到词干分析比词干分析在短文本上给出了更好的聚类)。
- 删除空文档和超过 30 个令牌的文档。
- 移除唯一令牌(术语频率= 1)。
Figure 4: We do match the Short Text statistics regarding the number of token in our documents, referring to the STTM survey paper p.10.
然而,必须记住预处理是数据相关的,如果使用不同的数据集,应考虑采用其他预处理方法。
既然我们的数据已经被清理并处理成适当的输入格式,我们就可以训练模型了🚀
# Train STTM model# Init of the Gibbs Sampling Dirichlet Mixture Model algorithm
# K = number of potential topic (which we don't know a priori)
# alpha =
# beta =
# n_iters = number of iterations to
mgp = MovieGroupProcess(K=10, alpha=0.1, beta=0.1, n_iters=30)vocab = set(x for doc in docs for x in doc)
n_terms = len(vocab)y = mgp.fit(docs, n_terms)# Save model
with open(‘dumps/trained_models/v1.model’, “wb”) as f:
pickle.dump(mgp, f)
f.close()
让我们深入了解 gsdmm:模型的超参数机制
- K = 10。在实际情况下,我们不知道主题的确切数量,所以我们希望选择一个更高的值。理论上,GSDMM 应该清空无用的簇,并最终找到簇的确切数目。这里不会出现这种情况,但没什么可担心的,我们稍后会更深入地解释这种情况。
- 阿尔法= 0.1贝塔 = 0.1。在这里,我们保留了默认参数(对于几个数据集来说,这些参数工作得很好)。然而,人们可能希望对它们进行调优,以改善关于集群的完整性和同质性的主题分配。不要犹豫参考原文📖为了理解这两个参数之间的平衡。
- n_iters = 30。根据原始论文,GSDMM 在几个数据集上收敛得相当快(大约 5 次迭代),并且保持非常稳定。因此,对于任何类型的数据集,30 次迭代都是一个很好的默认值。
一旦模型被训练,我们想要探索发现的主题,并检查它们在内容上是否一致🔎
假设我们的模型已经将文档收集到 10 个主题中,我们必须给它们一个对其内容有意义的名称。因此,让我们深入研究我们的模型所发现的主题。
doc_count = np.array(mgp.cluster_doc_count)
print('Number of documents per topic :', doc_count)
print('*'*20)# Topics sorted by the number of document they are allocated to
top_index = doc_count.argsort()[-10:][::-1]
print('Most important clusters (by number of docs inside):', top_index)
print('*'*20)# Show the top 5 words in term frequency for each cluster
top_words(mgp.cluster_word_distribution, top_index, 5)
上面的代码显示了下面的统计数据,这些数据让我们了解我们的集群是由什么组成的。
Figure 5: 1) Number of documents by cluster (or topic) index. 2) The sorted list of clusters regarding the number of documents they contain. 3) The top 5 words regarding their frequency inside a cluster.
理想情况下,GSDMM 算法应该找到正确的主题数,这里是 3,而不是 10。我想到三种解释:
- 寻找其他超参数以清空较小的集群(参考原始论文以更深入地理解α和β参数)。
- 我们既有小数据集又有词汇表(大约 1700 个文档和 2100 个单词),这对于模型来说可能难以推断和区分主题之间的显著差异。像往常一样,数据越多越好。
- 该算法可能会在主题中找到主题。让我解释一下。众所周知,其中一个话题是关于中东的新闻。然而,该算法将该主题分成 3 个子主题:以色列和真主党之间的紧张局势(聚类 7)、土耳其政府和亚美尼亚之间的紧张局势(聚类 5)或以色列的犹太复国主义(聚类 0)。
然而,即使找到了 3 个以上的集群,我们也很清楚如何将它们分配到各自的主题中。
# Must be hand made so the topic names match the above clusters
# (Figure 5) regarding their contenttopic_dict = {}
topic_names = ['x',
'mideast',
'x',
'space',
'space',
'mideast',
'space',
'space',
'mideast',
'space']for i, topic_num in enumerate(top_index):
topic_dict[topic_num]=topic_names[i] df_pred = topic_attribution(tokenized_data, mgp, topic_dict, threshold=0.4)
有人可能会问,topic _ attribute函数的阈值输入参数是什么。实际上,主题被分配给给定概率的文本,并且topic _ attribute是一个定制函数,它允许选择考虑哪个阈值(置信度)以便属于一个主题。例如,查看主题到文本的最高概率分配,如果该概率低于 0.4,则该文本将被分配到“其他”主题中。
NB : 这个定制的topic _ attribute函数建立在 GSDMM 包中的原始函数之上: *choose_best_label,*输出最有可能属于某个文档的主题。
现在是时候将找到的主题分配给文档,并将它们与地面真相进行比较(✅对❌)
df_pred[['content', 'topic_name', 'topic_true_name']].head(20)
天真地比较预测的主题和真实的主题,我们会有 82%的准确率!🎯
仅用一个 9 字平均的文档,一个 1705 个文档的小语料库和很少的超参数调优!
🙌
拥有一个高效的模型当然很好,但如果我们能够简单地展示其结果并与之互动,那就更好了。为此, pyLDAvis 是一个非常强大的主题建模可视化工具,允许在二维空间维度中动态显示集群及其内容。
Screen-shot of pyLDAvis ability. Check out this video to see its full power.
现在轮到你用自己的数据(社交媒体评论、在线聊天的回答……)来尝试了💪
瞧啊!👌
感谢拉贾·埃尔·海姆达尼对我的评价和反馈。
参考资料和其他有用的资源 ——GSD mm
的原文——实现 STTM 的好看的 python 包。pyLDAvis 库漂亮地可视化了一堆文本中的主题(或者任何单词包一样的数据)。
-最近对 STTM 的一项对比调查看其他策略。
PS :对于那些愿意深入 STTM 的人来说,有一种有趣的更进一步的方法(我现在还没有亲自探索过)叫做 GPU-DMM ,它显示了 SOTA 在短文本主题建模任务上的结果。简而言之,GPU-DMM 正在使用预先训练的单词嵌入作为外部知识来源来影响单词的采样,以生成主题和文档。
最短路径相似性:基于项目的推荐的一股清新之风
在本文中,我描述了最短路径相似性——一种替代的基于项目的协同过滤推荐算法。
Image by bertvthul from Pixabay
任何推荐系统的目标都是吸引消费者。新闻网站希望读者阅读更多的新闻,视频主机希望观众观看更多的视频,在线商店希望买家购买更多的东西,等等。在这方面,常见的方法是找到与消费者刚刚阅读/观看/购买的内容相似的内容,并建议他们作为下一个要考虑的内容。这种类型的推荐通常被称为基于项目的,这就是我要解决的问题。
在过去的十年里,推荐系统有一个相当稳定的配方。简而言之,其内容如下:
我的建议是在列表中设置第 1a 段。也就是说,除了传统的协同过滤,还有另一种选择:最短路径相似性算法。
首先,它不存在冷启动问题。也就是说,在有一部新电影上映的情况下,我们知道十个人对后者进行了评级,我们也知道这十个人对二十部其他电影进行了评级:我们的余弦相似性算法有二十部电影可供选择,以推荐给新电影。不多,真的,特别是考虑到收视率不一定相等,也就是说,这二十部电影不太可能相似。同时,《最短路径》将遍历这个图,达到你想要的深度,并且可能会有更多的电影放在桌面上,这些最近的二十部电影中的大多数可能会排在一些更远但更相关的电影之后。
其次,在应用程序中,当相似性是必要的,但对于相关性来说是不充分的,最短路径产生更多的逻辑推荐。我们生活中做的很多事情都是有因果关系的。当一个人不打算喝咖啡的时候,他是不会给自己冲咖啡的,对吗?我们看了《真探》第一集后就不会看第三集了,但不会看第二集。余弦相似度算法在检查了用户的评分后对这三集了解多少?他们彼此几乎一样相似。猜顺序没线索。同时,最短路径确实说明了事情发生的顺序。无论何时定义用户的分级权利(例如,设置:观看整集:正面,中途停止观看:负面,加上忽略明星、喜欢和类似的其他人),最短路径毫不费力地预测最可能的序列。
但是,我并不是说余弦相似度算法本身有问题。当您将一个文档与已学习的特征矩阵进行匹配以找到相似的文档时(例如,针对 TFIDF 矩阵的搜索查询),它非常有用。它的常见问题是误用,余弦相似度不太适合用作独立的推荐算法,例如,在视频托管和新闻网站上,文章的相似度不一定转化为高点击概率。
请查看脚本,它使您能够通过余弦相似性和最短路径相似性并排比较推荐。该脚本是用 Python 编写的,包含对实现方面的详细解释。推荐基于 MovieLens 最新的小型数据集。示例输出如下所示:
让我试着解释一下它是如何工作的。考虑以下五部电影的图表,这五部电影由五个用户进行评估:
其中每个用户给出一个如表中所示的等级:
让我们对给定的输入应用余弦相似度。实际上,我们只需要第二个数字。设θ是矢量 M1 和 M2 之间的角度。为了求出该角度的余弦值,我们使用以下公式:
从欧几里得点积的公式中导出。请注意,在这种情况下,n = 3,我们无法考虑 U2 和 U3 给出的评级,因为他们对 M1 的评级是未知的。我们得到的是:
哇,看起来他们非常相似,虽然,一切都是相对的。让我们看看所有的相似之处:
Cosine similarity item-to-item recommendations
看,M5 碰巧更相似。请注意,在实际应用中,标准化输入值总是更好(例如,按比例缩放它们,使它们落在 0 和 1 之间)。在这种特殊情况下,规范化不会对排名产生任何影响,但是当相似性值之间的差异越来越接近浮点数的精度限制时,规范化就派上了用场。
好了,现在我们有了一些结果。但并不是所有的 5 部电影都得到了 4 个推荐,即使输入矩阵的稀疏度没有那么高。这就是通常所说的冷启动问题,也称为稀疏性问题。余弦相似性不仅需要更多的数据来产生更好的推荐,而且需要更多的数据来产生推荐。
还有另一个问题,没有前者那么明显。相似之处是镜像的。这意味着,例如,sim(M1-M2) = sim(M2-M1)。嗯,这听起来合乎逻辑,因为这是的相似性。但我们正试图在第一时间提出建议。想象一下,M1 是《回到未来》,M2 是《回到未来 2》。虽然它们在两个方面都很相似,但作为推荐,它们是否同样相关?你可能会说,当然,马蒂在第二集的开头就回到了 1955 年。但是让我请你向上滚动一点,看第一个图,沿着 M1 和 M2 之间的所有箭头。是的,两个用户选择了同一个方向,没有人选择相反的方向。如果这是相关性不平等的有效指示呢?用深度学习来整理会是一个很好的答案。但是有一个更简单的方法。
让我们看看最短路径相似性算法在这种情况下是否有什么好处。首先,为了清楚起见,让我们将原始图形展平成一个用户路径表:
Path of each user
很好,现在,既然我们有了一个图,我们可以给它的边分配不同的长度。在这种特殊情况下,最符合逻辑的是从电影分级中导出长度。我想出了下面的公式:
其中 v 和 v’是连接的顶点,r_iv 和 r _ iv’是由第 I 个用户给出的评级,w_r_i 是第 I 个用户意见的权重,w _ v’是给定推荐候选的全局权重。但是,当您想要尝试其他数据的最短路径相似性时,我鼓励您仔细考虑计算长度的最佳方式。我提出的公式对于最短路径相似性算法来说并不重要,也并不完美。顺便说一下,余弦距离可能是一个很好的选择。
在现实世界的应用中,用户意见和推荐候选的权重可以从学习数据集中的出现频率中导出。例如,当一个用户对一部电影的评价高于平均水平时,降低后者的权重是有意义的。如果一部电影太受欢迎,我们可以减轻它的重量。为了简单起见,在这种情况下,有 5 部电影和 5 个用户,我假设所有用户的权重相等,所有电影的权重相等。因此,我以下面的邻接表结束:
请注意,这还不是推荐列表,尽管每个最近的顶点将不可避免地成为最相关的推荐。现在,该说的都说了,该做的都做了,是时候寻找最短的路径了。我建议使用带有优先级队列的 Dijkstra 算法,对于 M1,该算法将如下工作:
从 M1 出发,它将引导我们前往 M2,然后通过 M2 到达 M4,因为没有直达航班,然后通过 M2 到达 M5,最后通过 M2 和 M4 到达 M3。通过每个顶点进入图表后,我们得到了以下建议表:
请注意,现在我们有完整的推荐,我们不能从五部电影中获得更多。虽然,我不会说这是一个伟大的成就,因为我们允许单个用户连接一些顶点,这在实际应用程序中不一定是一个好主意。但更重要的是,现在,尽管 M2 是与 M1 最相关的推荐,反过来,M1 与 M2 最不相关。
所以,就这么简单:跟随用户的路径,记录用户对每对文档的意见,找出对每对文档的平均意见,以确定它们之间的距离,使用最短路径算法,其中记录每个访问过的文档作为对你已经开始的文档的推荐,就这样。这样做是很自然的,因为推荐系统的目标是预测用户想要一个接一个消费的最可能的序列。在我提出的最短路径相似性算法中没有费马定理的证明。它的所有部分都是肤浅的,在软件开发中被广泛使用。如果您对更多细节感兴趣,或者有一个数据集或应用程序,您想尝试最短路径相似性:请不要犹豫联系我们。请查看 https://recom.live ,这是一个基于最短路径相似度的实时推荐系统。