TowardsDataScience 博客中文翻译 2019(四百六十)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

全局优化策略

原文:https://towardsdatascience.com/strategies-for-global-optimization-79fca001c8bb?source=collection_archive---------6-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一旦我们离开高中微积分,局部和全局优化通常是已知的,但有些被忽略了。快速回顾一下,看看这篇博客的封面图片。对于一个给定的函数,在空间上有多个点有倾角。每次下降都是最小的。但是,你可以看到只有一个点是最深的,称为全局最小值。所有其他点都是局部最小值。第一部分,我将回顾计算一个已知函数的全局值。然而,一旦我们离开高中数学的这个已知函数的领域,大多数优化问题只处理局部优化。即使这样,我也要说明原因。快速注意,还有很多其他的策略我没有在这篇博客中提到。然而,我希望它能让你有足够的兴趣去探索更多的选择。

已知函数

我们来复习一些基础的高中微积分。首先,看一下这个简单的一元函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

f(x) = 1/4x⁴ + 1/3x³ — 3x² — 7

从图表中,我们可以看到全球最小值在-3 左右。然而,让我们尝试使用微积分,因为我们知道这个情节的功能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们看到 f(-3)=-22.75 ,f(x)的最小可能值。我们甚至可以超越 2D,进入多元微积分领域来解决这个问题。

未知函数

在处理数据科学的大部分时间里,我们无法访问函数来执行任何演算。通常,f(x)是一个系统,我们可以输入变量 x,并获得一些输出 y。一个可能的解决方案是执行随机梯度下降,我们迭代地沿着斜坡下降,直到我们达到最小值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Stochastic Gradient Descent

现在让我们用 python 来实现这个问题,假设 f 是一个黑盒函数。

#Unknown Function
f = lambda x:(1/4*x**4)+(1/3*x**3)-(3*x**2)-7def next_step(x,f,step_size):
  y=f(x)
  #Left Point
  x_left=x-step_size
  y_left=f(x_left)
  diff_left=y_left-y
  #Right Point
  x_right=x+step_size
  y_right=f(x_right)
  diff_right=y_right-y
  #Comparison
  if diff_right<diff_left:
    return x_right, y_right, diff_right
  else:
    return x_left, y_left, diff_leftdef gradient_descent(f,start,step_size=0.01,tol=0.1, debug=False):
  x=start
  diff=9999999
  while abs(diff)>tol:
    x, y, diff=next_step(x,f,step_size)
    if debug:
      print("Current Point: (%.2f,%.2f), Change: %.2f"%(x,y,diff))
  print("Minimum Point: (%.2f,%.2f)"%(x,y))

现在我们有了函数,让我们试着从 x=4 开始搜索。

gradient_descent(f, start=4)#Minimum Point: (2.65,-9.54)

这给了我们 2.65 的最低分。现在,让我们对另一个起点 x=-4 做同样的尝试。

gradient_descent(f, start=-4)#Minimum Point: (-3.51,-20.43)

使用 x=-5,我们得到全局最小值-3.51。这是寻找全局和局部最小值变得棘手的时候。我们的最终结果取决于起点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Stochastic Gradient Descent gives different minima based on starting point

由于它是一个未知函数,我们不知道:

  • 理想的起点
  • 理想的步长
  • 理想域(我们不能穿越无限大的 x 空间)

一个可能的解决方案是使用模拟退火,它给我们一个达到全局最小值的合理概率。

模拟退火

这个名字和灵感来自冶金中的退火,一种涉及加热和控制冷却材料以增加其晶体尺寸并减少其缺陷的技术。两者都是依赖于热力学自由能的物质属性。加热和冷却材料会影响温度和热力学自由能。退火的模拟可用于寻找具有大量变量的函数的全局最小值的近似。

在模拟退火算法中实现的这种缓慢冷却的概念被解释为随着解空间的探索,接受更差解的概率缓慢降低。接受更差的解是元启发式算法的一个基本属性,因为它允许对全局最优解进行更广泛的搜索。

一般来说,模拟退火算法工作如下:

  • x = x 0
  • 对于 k = 0 到 k max(不含):
    • T 每步递减
      -随机选取一个邻居, x_ new ←邻居(x)
      -IfP(E(x【T22)), E ( 【T25
  • 输出:最终状态 x

以下是我们特定函数的 Python 实现:

import numpy as np#Unknown Function
f = lambda x:(1/4*x**4)+(1/3*x**3)-(3*x**2)-7def acceptance_probability(E, E_new, T):
    return np.exp(-(E-E_new)/T)def random_neighbour(x):
    return x += np.random.uniform(-1,1)def simulated_annealing(f, steps):
    x = np.random.random()
    E = f(x)
    print("x=%.2f, fmin=%.2f"%(x, E))
    for k in range(steps):
        T = T*0.9
        x = random_neighbour(x)
        E_new = f(x)
        P = acceptance_probability(E, E_new, T)
        if P > np.random.random():
            E = E_new
        print("x=%.4f, fmin=%.4f, Prob.=%.4f"%(x,E,P))
    return Esimulated_annealing(f,20)

运行该等式,我们得到以下输出:

x=0.62, fmin=-8.04
x=-0.3446, fmin=-7.3664, Prob.=0.4753
x=-0.8717, fmin=-9.3559, Prob.=11.6601
x=-0.8329, fmin=-9.1534, Prob.=0.7575
x=-1.6213, fmin=-14.5791, Prob.=3903.7178
x=-2.3907, fmin=-20.5342, Prob.=23982.6510
x=-1.8220, fmin=-20.5342, Prob.=0.0003
x=-1.1582, fmin=-20.5342, Prob.=0.0000
x=-0.2298, fmin=-20.5342, Prob.=0.0000
x=-0.8731, fmin=-20.5342, Prob.=0.0000
x=-1.8032, fmin=-20.5342, Prob.=0.0000
x=-2.1873, fmin=-20.5342, Prob.=0.0110
x=-1.8673, fmin=-20.5342, Prob.=0.0000
x=-2.7618, fmin=-22.3598, Prob.=1315.6210
x=-2.3266, fmin=-22.3598, Prob.=0.0001
x=-2.5017, fmin=-22.3598, Prob.=0.0036
x=-2.6164, fmin=-22.3598, Prob.=0.0466
x=-1.7016, fmin=-22.3598, Prob.=0.0000
x=-1.7248, fmin=-22.3598, Prob.=0.0000
x=-1.6569, fmin=-22.3598, Prob.=0.0000
x=-1.5051, fmin=-22.3598, Prob.=0.0000

如上所示,该值收敛到-22.75。虽然这种方法不能保证全局最优,但是如果我们不限制我们的领域,它是相当接近的。还要注意,尽管初始值非常接近局部最小值,但它仍然设法找到了全局最小值。

动态规划

这部分更多的是时间复杂性而不是准确性。动态编程主要是对普通递归的优化。每当我们看到递归解决方案重复调用相同的输入时,我们可以使用动态编程来优化它。其思想是简单地存储子问题的结果,这样我们就不必在以后需要时重新计算它们。这种简单的优化将时间复杂度从指数级降低到多项式级。例如,如果我们为斐波纳契数编写简单的递归解决方案,我们得到指数时间复杂度,如果我们通过存储子问题的解决方案来优化它,时间复杂度降低到线性。

让我们以斐波那契数列为例:

def f(n):
    if n <= 1:
        return n
    else:
        return f(n-1)+f(n-2)

这个问题的复杂性在于 O(2^n).如果你问我,我会觉得非常复杂!然而,让我们更好地分析这个问题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fibonacci at n=6

如果你看一个 n=6 的递归树,有很多重复。只需计算 f(3)的值的个数。在动态编程中,我们将把值存储在内存中,如果再次调用,就不会重新计算。下面是斐波那契的动态编程版本:

store = {}
store[0] = 0
store[1] = 1def f(n):
    store[n] = f(n-1)+f(n-2)
    return store[n]

使用新方法,每一步的复杂度为 O(1)。这允许我们探索 n 的整个域,以找到具有最小时间复杂度的最优解。

模型调试的现实策略

原文:https://towardsdatascience.com/strategies-for-model-debugging-aa822f1097ce?source=collection_archive---------8-----------------------

测试和修复机器学习模型的系统方法

内容:

  1. 简介 1.1 关于信任和理解的快速说明
    1.2 例题和数据集
  2. 检测策略 2.1 敏感度分析
    2.2 残差分析
    2.3 基准模型
    2.4 针对 ML 攻击的安全审计
  3. 补救策略 3.1 数据扩充
    3.2 噪声注入和强正则化
    3.3 模型编辑
    3.4 模型断言
    3.5 不需要的社会学偏见补救
    3.6 模型管理和监控
    3.7 异常检测
  4. 进一步阅读和结论
  5. 参考文献

1.介绍

所以,你已经训练了一个机器学习(ML)模型。你做的一切都是对的:交叉验证、提前停止、网格搜索、单调性约束和正则化。它在过时的测试数据中是准确和稳定的,并且比它所取代的线性模型要好。您甚至为您的数据工程和信息技术(IT)伙伴将您的模型包装在 Docker 容器中,以及它的所有依赖项。部署时间到了?没那么快。目前 ML 模型训练和评估的最佳实践并没有告诉我们如何发现和修复所有可能在现实世界 ML 系统中发生的讨厌的事情。如果这些系统能像常规应用程序一样被测试和调试就好了…输入:模型调试。模型调试是一门新兴学科,致力于发现和修复 ML 系统中的问题。模型调试试图像测试代码一样测试 ML 模型(因为它们通常是代码),并探测复杂的 ML 响应函数和决策边界,以系统地检测和纠正 ML 系统中的准确性、公平性和安全性问题。

1.1 关于信任理解的快速说明

在 ML 中,信任和理解是相似但不相同的。解开这种差异有助于我思考模型调试以及它与 ML 工作流的其他部分的关系。如图 1 所示,现在有很多工具可以用来促进人们对 ML 的信任和理解。一些技术,如模型调试和社会偏见测试和补救,帮助我们使 ML 更加准确、公平和安全,而无需告诉我们模型是如何工作的。这些帮助我们信任一个模型,而不是帮助我们理解它。其他技术,如可解释的 ML 模型和事后解释,通过揭示模型机制或总结模型决策来直接增加我们的理解。当我们喜欢模型或解释时,这些技术只会增加信任。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1: Many tools exist today to increase trust and understanding of ML systems. Some promote trust directly, while others promote understanding directly. Figure courtesy of Patrick Hall and H2O.ai.

这篇文章将集中在调试 ML 和促进 ML 信任的许多方面。然而,考虑负责任的 ML 工作流程的这两个额外方面是至关重要的:

  • 促进对 ML 的理解
  • 测试和强化支持 ML 模型的 IT 系统

即使您重视信任,特别是准确性,而不是公平性、可解释性或安全性,也需要使 ML 系统可理解,以实现逻辑上诉或操作员推翻错误的 ML 决策。很难反驳黑箱。[1]你不会喜欢你的孩子被一个精确但不可思议的 ML 系统拒之门外。你也不会喜欢被同样的黑箱系统拒绝医疗保健。你希望有机会对影响你生活的错误的 ML 决策提出上诉,这就是为什么商业或生活关键的 ML 系统总是可以理解的。图 2 提出了一个工作流程,包括在 ML 系统中增加信任和理解的步骤。当与图 2 中提出的其他技术一起使用时,模型调试可能工作得最好。

你们中的许多人可能比我更了解向消费者展示 ML 模型的测试和强化系统。那种工作还是有必要的,我就不多说了。仅仅因为一个系统包含一个 ML 模型并不能免除它的测试。此外,谷歌(可能还有其他公司)已经在这个问题上提出了一些可行的想法和框架。[2]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2: A ML workflow that can enhance trust and understanding. Figure courtesy of Patrick Hall and H2O.ai.

现在,让我们进入如何调试 ML 模型的内部。首先,我们将讨论本帖中使用的示例问题和数据集,然后讨论如何检测 bug,最后讨论如何消除 bug。

1.2 例题和数据集

下面的一些例子基于来自加州大学欧文分校(UCI) ML 知识库的著名的台湾信用卡数据集。[3]在这个数据集中,我们试图预测某人是否会在下一次信用卡付款时付款,DEFAULT_NEXT_MONTH = 0,或 DEFAULT,DEFAULT_NEXT_MONTH = 1。关于支付的变量用于产生违约概率,或 p_DEFAULT_NEXT_MONTH。我将使用我最喜欢的模型之一,一个可解释的单调约束梯度推进机(M-GBM)来进行这些预测。在 M-GBM 中,当某个输入变量增加时,p_DEFAULT_NEXT_MONTH 必须只增加,或者只减少。这使得解释和调试模型变得非常非常容易,并且不会真正影响该数据集模型的整体准确性。M-GBM 接受支付变量的训练,包括 PAY _ 0-PAY _ 6,或客户最近至前六个月的还款状态(较高的值是延迟付款),PAY _ am t1-PAY _ AMT 6,或客户最近至前六个月的付款金额,以及 BILL _ am t1-BILL _ AMT 6,或客户最近至前六个月的账单金额。所有货币价值均以台币(新台币)为单位。

一些示例结果还包含变量 LIMIT_BAL 和 r_DEFAULT_NEXT_MONTH。LIMIT_BAL 是客户的信用限额。r_DEFAULT_NEXT_MONTH 是一个 logloss 残差值,或者是 M-GBM 预测 p_DEFAULT_NEXT_MONTH 与已知正确答案 DEFAULT_NEXT_MONTH 之间差距的数值度量。我还将使用数据集中的人口统计变量,如性别,来测试不想要的社会学偏见。在很大程度上,这篇文章将示例信用贷款问题视为一般的预测建模练习,而不考虑适用的法规。(当然,违规处罚可能会使模型调试更具商业吸引力。)

2.检测策略

我们如何发现 ML 模型中的数学 bug?我至少能想到四种主要方式:敏感性分析、残差分析、基准模型、ML 安全审计。你大概也能想到别人。

2.1 敏感性(“假设”)分析

敏感性分析,有时称为“假设”分析,是一个简单而强大的想法。只需模拟代表有趣场景的数据,然后查看您的模型在这些场景中做出何种预测。因为几乎不可能知道一个非线性 ML 模型将如何对它在训练期间没有看到的数据作出反应,所以对我们所有重要的 ML 模型进行敏感性分析是非常重要的。[4]你可能对测试什么样的场景有一些想法。如果是这样,那太好了,就这么做吧。也许你也想玩你的模型?也很棒。对于这些情况,一定要检查一下假设工具,它为某些类型的 ML 模型提供了交互式沙盒体验。

这也有助于采用更结构化的方法进行敏感性分析。本小节将介绍结构化敏感性分析的三种策略:

  • 部分相关、个体条件期望(ICE)和累积局部效应图(ALE)
  • 对抗性示例搜索
  • 随机攻击

在我们开始之前,最好知道哪些变量对你的模型最重要。我总是首先将我的测试工作集中在那些变量上。图 3 是使用 XGBoost 通过 Shapley 值计算的精确一致的变量重要性图。[5] (Shapley 变量重要性测量在 H2OLightGBM 中也是本地可用的。)图 3 向我们展示了 PAY_0 非常重要,而且可能太重要了,我们将在后面看到。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3: An accurate and consistent variable importance chart for the M-GBM model and the credit card dataset. Figure courtesy of Patrick Hall and H2O.ai.

2.1.1 部分依赖、ICE 和 ALE

部分相关将感兴趣的数据集中的感兴趣的列(例如 PAY_0)的所有值(例如验证数据集中的值)设置为感兴趣的值(例如 missing 或 NaN)或任何其他合理的值。这个新数据集通过训练好的模型运行,为每一行创建一个预测。取所有这些预测的平均值就是该变量、该数据集、该值和该模型的估计部分相关性。现在,我们对我们感兴趣的几个不同的值重复这个过程,以创建一个部分依赖曲线来绘制。在图 4 中,该图向我们展示了 M-GBM 模型中 PAY_0 的大致平均行为。

尽管这很容易理解,但是部分依赖并不完美。众所周知,当数据集中存在强烈的交互或相关性时,会显示不可信的结果。我们至少有两种选择来改善部分依赖,麦芽酒和冰块。听起来很有趣,对吧?ALE 几乎是部分依赖的直接替代。计算起来更有效率,通常也更准确。ALE 有 R 包,比如: ALEPlotDALEXiml

冰经常和部分依赖一起使用。ICE 是与部分依赖非常相似的计算。除了感兴趣的数据集只有一行之外,遵循与上述相同的步骤。我们通常计算数据集中许多不同行的 ICE 曲线。当代表许多不同的真实或模拟个体的 ICE 曲线跟随由部分相关性代表的整体平均行为时,这是部分相关性足够准确的好迹象。当 ICE 曲线偏离部分相关性时,这可能表明模型中存在相互作用(可能是部分相关性的平均值)。简而言之,ICE 可以告诉我们在我们的模型下有趣的真实或模拟个体的行为,部分依赖是否值得信任,以及我们是否应该在我们的模型中寻找任何强相互作用。部分依赖和 ICE 的组合和变体可以在几个开源包中获得,如 PDPboxPyCEboxICEboxpdp

图 4 结合了部分相关、ICE 和直方图,提供了关于 M-GBM 模型中最重要的变量 PAY_0 的更多信息。首先,我们可以看到,对于 PAY_0 > 1,训练数据非常稀疏。这通常是一个不好的迹象。ML 模型需要大量的数据来学习。这个模型几乎没有数据来了解最近一次还款逾期超过 1 个月的人。看看部分依赖,我们可以看到其他一些潜在的问题。该模型给出了缺失(即 NaN)数据的最低平均违约概率。这有商业意义吗?我不知道怎么做。此外,从安全角度来看,这有点可怕。如果我想从这个模型中得到一个好的分数,我可能只需要将一个带有缺失值 PAY_0 的对立示例放入 M-GBM 的生产评分队列中。此外,我们可以看到预测从 PAY_0 = 1 到 PAY_0 = 2 的巨大变化。从商业角度来看,这有意义吗?也许是这样,这很好,但从安全性和数据漂移的角度来看,这是另一件需要注意的事情。如果我想对这个模型的客户进行拒绝服务攻击,我只需要将他们的 PAY_0 值更改为大于 1。对于这个模型,我们可能希望让我们的 IT 伙伴知道监视涉及 PAY_0 = NaN 和 PAY_0 > 1 的对抗性示例攻击。此外,如果我们的市场向衰退条件转变,客户有更多的逾期账单,记住这个 M-GBM 对 PAY_0 > 1 的值有多敏感是很重要的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 4: Histogram, partial dependence, and ICE for PAY_0. Figure courtesy of Patrick Hall and H2O.ai.

另一方面,部分相关性和 ICE 曲线显示了平均和许多个体对 PAY_0 的单调性约束。单调约束幸运地帮助我们处理了数据稀疏问题。由于单调性约束,该模型从有一些训练数据的 PAY_0 = 2,一直到没有训练数据的 PAY_0 > 8,保持违约概率。如果没有约束,在 PAY_0 的这个域中的模型预测可能只是随机噪声。最后,因为 ICE 和部分相关几乎是一致的,我们可以看到 PAY_0、这个数据集和 M-GBM 模型的部分相关曲线可能是相当可信的。现在,你只需要对其余最重要的变量进行分析。为了简洁起见,我将转移到下一个敏感性分析调试策略,对抗性示例搜索。

2.1.2 对抗性示例搜索

对立的例子是使模型产生意外结果的数据行。寻找对立的例子是一种很好的调试技术。搜索过程使我们能够看到我们的模型在许多不同场景中的表现。发现和理解实际的对立例子可以指引我们找到使我们的模型更健壮的方法,并告诉我们当模型进入生产环境时要寻找的异常。如果你在 Python 深度学习领域工作,可以看看 cleverhansfoolbox 来寻找对立的例子。对于结构化数据,有更少的免费软件可以帮助我们,但是我有一个小的启发式搜索方法,你可以尝试或修改。图 5 显示了启发式搜索的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 5: Maximum predicted probability of default for adversarial example search across several important variables. Figure courtesy of Patrick Hall and H2O.ai.

对于 M-GBM 模型和数据,启发式搜索从 PAY_0 开始,像我在图 4 中做的那样计算 ICE,找到预测中摆动最大的 ICE 曲线。对于此数据集和模型,这是 p_DEFAULT_NEXT_MONTH 的第 90 个百分位数处的 ICE 曲线。然后,p_DEFAULT_NEXT_MONTH 的第 90 个百分位数的数据行被扰动 10,000 次,通过四个重要变量的十个不同值:PAY_0、PAY_3、PAY_AMT1 和 PAY_AMT2。(选择这些变量是因为它们的 Shapley 值范围很大,而不是直接来自图 3 中的变量重要性图。)然后,M-GBM 模型对 p_DEFAULT_NEXT_MONTH 的第 90 个百分位的 10,000 个受干扰的行实例的数据集进行重新存储,结果绘制在图 5 中。

图 5 向我们展示了 M-GBM 模型的一些有趣之处。首先,我们可以看到单调性约束甚至适用于几个变量的组合。其次,我们可能发现了 M-GBM 模型的一个逻辑缺陷。似乎无论某人最近或第二次最近的付款金额有多大,如果他们最近的付款逾期超过一个月,该模型都会产生很高的违约概率。这意味着 M-GBM 模型在不发布违约预测的情况下,可能无法考虑提前还款,或某人支付大笔款项以弥补逾期付款。如果我确实想在我的 M-GBM 模型或基于 M-GBM 模型的基于 ML 的信贷系统中考虑这些条件,我可以考虑编辑 M-GBM 模型或使用模型断言来使信贷系统能够处理这些更复杂的场景。(参见第 3.3 和 3.4 小节。)第三,这次调查确实发现了至少一个对立的例子。极低的 PAY_AMT1 和 PAY_AMT2 值,当与用于初始化搜索的行中的其他值组合时,将导致 M-GBM 模型生成高得惊人的违约概率。当 M-GBM 模型投入生产时,需要对这些值进行监控。他们可能会指出模型受到了恶意攻击。

如果你认为提出的对抗性搜索方法似乎有用,试试看。启发式搜索过程可以总结如下。

对于每个重要变量:

  1. 计算模型预测每十分位数的冰曲线。
  2. 找到预测中摆动最大的冰曲线。
  3. 隔离与此 ICE 曲线相关的数据行。
  4. 对于这一行数据:
  • 扰乱行中 1-3 个额外的重要变量。(很难绘制超过 1-3 个变量的结果。)
  • 重新对受干扰的行进行评分。
  • 继续 直到每个额外的重要变量循环通过其在训练数据中的域,并通过缺失或其他有趣的超范围值。

5.绘制并分析结果。

随机攻击

随机攻击是通过将模型暴露给各种随机数据来进行的。想想:双字节字符集,一行一列的数据集,一千万列一行的数据集等等。等等。等等。随机攻击可以发现传统的 IT 错误和数学错误。考虑一下,当暴露于一个有 1000 万列和 1 行的数据集时,您的 API 会表现失常,吐出一个包含太多私有或内部信息的 stacktrace。或者它只是以一种非常丑陋的、服务崩溃的方式失败了?也许您的 API 和模型将双字节字符视为缺失值,并且总是为包含它们的记录分配低违约概率?谁知道呢?不是你…如果你不测试这种东西。此外,如果你完全不知道从哪里开始你的模型调试工作,从随机攻击开始。我打赌你会发现一些非常有趣的东西。

2.2 残差分析

残差分析长期以来一直是线性模型诊断的基石,在 ML 时代仍然如此。残差指的是已知的真实结果和模型预测的结果之间的差异。计算残差的方法有很多,但通常较大的残差意味着模型是错误的,较小的残差意味着模型是正确的。残差图将您的所有输入数据和预测放入二维可视化中,有影响的异常值和其他类型的数学错误可以清晰可见。残差分析的唯一缺点是,为了计算残差,我们需要真实的结果。因此,如果我们在一段时间内无法获得真实结果的情况下进行预测,有时我们无法实时处理残差。(比如在抵押贷款中。)

图 6 显示了 M-GBM 模型的对数损失残差,由重要变量 PAY_0 的水平绘制。洋红色残差来自实际违约的客户。蓝色残差来自没有违约的客户。可悲的是,图 6 描绘了我的 M-GBM 模型的糟糕的一面。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 6: Logloss residuals plotted by PAY_0. Figure courtesy of Patrick Hall and H2O.ai.

在图 6 中,我们可以看到,对于 PAY_0 < 1, i.e. NO CONSUMPTION (-2), PAID DULY (-1), or USE OF REVOLVING CREDIT (0), there are a lot of large magenta residuals. This means that the model basically fails to predict default when someone made their most recent payment. For PAY_0 > 1 的理想值,模型误差由大的蓝色残差驱动,这意味着当客户的 PAY_0 值不理想时,即延迟几个月,M-GBM 模型无法预测按时付款。将这些信息与图 3 中的可变重要性图结合起来,可以看出 M-GBM 病态地过度依赖于 PAY_0。我可能会部署一个业务规则:如果 PAY_0 > 1,那么 DEFAULT_NEXT_MONTH = 1,并且具有与 M-GBM 或几乎任何 GBM 相同的准确性。那样的话,我只会将一个脆弱的规则释放到野外,而不是成千上万个破碎的、潜在的有偏见的、可破解的规则。

我们可以尝试用数据扩充、强正则化、模型编辑或模型断言来修复这个危险的错误,所有这些都将在本文的补救部分讨论。但有一点是清楚的,这个模型是破碎的,不可信的,不适合在现实世界中使用。这个问题没有出现在 fit 统计、lift 或 AUC 图中,如果不看残差,我永远不会如此清楚地看到它。事实上,残差图向我们展示的看似健康的模型可能会令人震惊。[6]希望我已经让你相信绘制残差是一种高效的调试技术。用你喜欢的任何语言和一个像样的绘图库来做自己通常很容易,但是像 DALEXthemis-mlauditor 这样的包提供了开箱即用的功能。

2.2.1 不同的影响、准确性和错误分析

不同影响(DI)大致指决策系统中的无意歧视。DI 测试方法是在训练数据和预测建模结果中发现某些类型的不想要的社会学偏见的众所周知的方法。他们完美吗?不。它们是你能做的最起码的事情来阻止你的 ML 模型延续或加剧不必要的社会学偏见吗?大概吧。还有几个开源包可以帮助您进行 DI 测试,包括 aequitasAIF360Themis 。基本的 DI 测试方法着眼于人口统计学变量的准确性和错误率。理想情况下,我们希望这些准确率和错误率在不同的人群中大致相等。如果不是,这强烈表明你的模型正在延续或加剧不必要的社会学偏见。在图 7 中,我们可以看到,就可变性别而言,男性和女性的准确率和错误率看起来相当相似。这是一个好现象,但这并不意味着我们的模型没有不必要的社会学偏见,即使是在性方面。

所有模型都有能力根据输入数据的微小变化来区别对待相似的人,这可能会导致局部偏差,或者缺乏个体公平性。地方偏见的一个例子是,对一个有良好还款记录且收入为新台币 100,000 元的年轻女性给予信贷延期,但对一个收入为新台币 99,999 元的非常相似的年轻女性拒绝信贷。我们知道新台币 1 元的收入差异不会产生真正的差异,但 ML 模型可以任意地将这两个相似的人置于非线性决策边界的不同侧。更糟糕的是,标准的 DI 测试通常无法发现局部偏差问题。我们如何在个人层面上确保公平?到今天为止,这仍然是一个多少有些开放的问题,许多恒星研究人员正在试图回答。[7]我能给出的一个实际建议是,仔细观察最接近你的模型的决策边界或概率截止点的个人。在大多数情况下,非常相似的个人不应该在该边界的不同侧。现在,在讨论作为一个通用的错误检测工具的不同的准确性和错误率之前,重要的是要说 ML 中的公平性远远超出了这里的小讨论。如果你想了解更多,请查看公平、问责和透明的 ML (FATML)会议和相关资源,并试用上面链接的一些软件包。[8]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 7: Accuracy and different types of error for PAY_0 and SEX across levels of these categorical variables. Figure courtesy of Patrick Hall and H2O.ai.

传统的 DI 测试方法也可以应用于一般的分类变量,我发现这是一个很好的 bug 检测方法。图 7 显示了重要变量 PAY_0 在不同分类级别上的许多准确性和误差指标。在这里,我们可以看到 M-GBM 的性能与 PAY > 1 之间的巨大差异,这可能是由该领域中训练数据的稀疏性造成的。该表很好地展示了该领域中模型性能的脆弱性,以及 PAY > 1 时模型性能的差异。这种缺陷检测技术也可以应用于数值变量,只需对它们进行宁滨。

残差的解释

在过去的几年里,我们已经有了许多解释 ML 模型预测的技术。这些技术也可以用来改进我们的残差分析。可以创建局部可解释的模型不可知解释(LIMEs)、部分相关或残差的单个条件期望图。最近添加到 shap 包中的功能使得计算 Shapley 对残差的贡献成为可能,这意味着您可以准确地了解哪些变量在局部(如单行)和全局(如整个数据集)产生误差。解释残差的另一个好方法是拟合模型。图 8 是当 DEFAULT_NEXT_MONTH = 1 时适合 M-GBM 残差的决策树。图 8 显示了为什么 M-GBM 模型错过了未来违约的模型,这可能会导致现实世界中的冲销。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 8: Decision tree model of residuals for DEFAULT_NEXT_MONTH = 1. Figure courtesy of Patrick Hall and H2O.ai.

对于 DEFAULT_NEXT_MONTH = 1 残差,图 8 中决策树的交叉验证 R 平方为 0.89,平均绝对百分比误差约为 17%。所以这是相当准确的,这意味着在 M-GBM 的错误猜测中有很强的模式。此外,决策树可以帮助我们看到那些模式可能是什么。最大的残差出现在 PAY_0 < 0.5 和 PAY_AMT2

2.3 基准模型

基准模型是稳定的、可信的、透明的模型,通常类似于线性模型、单一决策树、简单的基于规则的模型,或者先前存在的和被很好理解的 ML 模型。检查您的新 ML 模型在过时的测试数据中的表现是否优于已知的基准测试,这总是一个好主意。如果你的新 ML 模型没有超越一个更传统或透明的模型,请不要使用它。

一旦你确定了你的 ML 模型至少比一个简单的或者预先存在的基准更准确,那么这个基准模型就可以成为一个可靠的调试工具。我使用基准模型来问这样的问题:我的 ML 模型错了谁,而我的基准模型对了谁?如果您可以隔离错误的 ML 模型行为,您可以考虑将基准模型预测与 ML 模型预测相结合,以便对这些情况做出更好的预测。此外,您还可以推理为什么透明模型对于某些数据子集表现更好,并开发潜在的补救策略。例如,当将行为不当的 ML 模型与线性模型进行比较时,ML 模型不准确的一个可能原因是过度强调 ML 模型中的非鲁棒交互。此外,基准模型可用于实时发现异常。在大多数低信噪比情况下,面向人的 ML 问题,简单模型和 ML 模型预测应该不会有太大差异。实时比较基准模型和 ML 模型预测可以帮助您捕捉一些正在发生的准确性、公平性或安全性异常。

2.4 针对洗钱攻击的安全审计

有几种针对 ML 模型的已知攻击可以导致改变的、有害的模型结果或者暴露敏感的训练数据。[9][10]图 9 概述了一些最著名的 ML 攻击。不幸的是,传统的模型评估方法并不能告诉我们模型是否安全。除了其他调试步骤,将一些或所有已知的 ML 攻击添加到您的组织已经进行的任何白帽黑客练习或红队审计中可能是谨慎的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 9: A cheat sheet that describes several different types of known attacks against ML. A full size version of this cheat sheet is available: https://github.com/jphall663/secure_ML_ideas. Figure courtesy of Patrick Hall and H2O.ai.

3.补救策略

现在我们已经讨论了一些系统的方法来发现基于 ML 的系统中的准确性、公平性和安全性问题,让我们考虑一些补救策略来修复任何检测到的问题。

3.1 数据扩充

如果您的模型调试暴露了定型数据中的稀疏位置或模型中与缺少数据相关的逻辑错误,则您可能需要获取更多数据。您可以模拟所需的数据,将其添加回您的训练数据中,重新训练您的模型,并重新测试您的模型。更有可能的是,您必须返回白板,重新思考您的培训数据是如何收集的,并等待更完整的数据可用。为了帮助避免将来出现这种问题,可以考虑实验设计技术。[11]在这里的例子中,收集关于债务收入比或就业状况的信息可能有助于在 M-GBM 模型中降低 PAY_0 的重要性。

数据扩充也可以是对 ML 模型中不必要的社会学偏见的补救策略。ML 中社会学偏见的一个主要来源是人口统计学不平衡的训练数据。如果你的模型将用于各种各样的人,最好确保你的训练数据也能代表各种各样的人。性别阴影线的研究既是一个警示故事,也是一个成功的故事,除了其他重要的事情,人口统计平衡的训练数据的必要性。[12]

3.2 噪声注入和强正则化

今天,我们大多数人在 ML 模型中使用 L1 和 L2 正则化。我们也许应该继续这样做。不幸的是,标准类型的正则化可能无法克服我们训练数据中强烈的病态偏差、相关性或依赖性。在讨论的例子中,PAY_0 就是这种情况。一个潜在的解决办法是启动 L1 和 L2 正则化。如果这种补救措施不够有力,你可以考虑其他措施,比如 L∞正则化、丢弃、权重裁剪或噪声注入技术。

采取如此极端的方式来修复你的训练数据也可能表明数据收集存在问题。如果一个变量驱动着你的整个模型,你可能至少遗漏了一个混杂的输入变量。在这种情况下,考虑将数据扩充作为另一种补救策略。

3.3 模型编辑

一些 ML 模型被设计成可解释的,所以你可以直接理解它们是如何工作的。其中一些模型,如决策树或 GA2M (又名可解释的助推机器,EBM)的变体,可以由人类用户直接编辑。如果您在 GA2M 模型的内部工作中发现了您不喜欢的东西,那么更改模型方程来去掉您不喜欢的东西并不困难。其他模型可能不像 GA2M 或决策树那样容易编辑,但是如果它们生成人类可读的评分代码,它们是可以编辑的。如果你的 M-GBM 评分代码中有很多错误的规则,也许你可以修复它们,也许你可以删除它们。当然,可以尝试 GA2M,但是也可以考虑为其他模型进行编辑,作为一种可行的错误修复策略。

关于模型编辑要考虑的一件事是,它可能会使您的模型在训练或验证数据中看起来更差。无论你的模型中有什么,因为它使训练和验证误差变得更好。所以,如果你编辑一个模型,你需要有坚实的理由来支持你的决定。

3.4 模型断言

模型断言,也称为预测后业务规则,是关于模型预测的断言语句,可以帮助纠正错误的或有问题的模型预测。[13]在我的例子中,我看到我的 M-GBM 模型不能说明在客户最近一次付款逾期超过一个月之后的预付或超额付款。在发布默认决定之前,明智的做法可能是检查客户上次付款是预付还是超额支付。生产中 M-GBM 模型的模型断言可以说:IF((PAY _ 0 > 1)AND(PAY _ am t1 > LIMIT _ BAL))那么 DEFAULT_NEXT_MONTH = 0

(一个滑稽的、来自头条新闻的模型断言可能更接近于:在将与怀孕相关的优惠券送到客户家中之前,检查以确保客户不是未成年人。[14])

3.5 不想要的社会学偏见补救

今天,有许多人和技术的方法来修正 ML 模型中不必要的社会学偏见。许多人为修正涉及促进数据科学团队观点和经验的多样性,并确保不同的知识分子参与模型构建的所有阶段。技术补救方法分为三个基本类别:

数据预处理:

  1. 明智的特征选择,例如使用存档时间作为输入变量,而不是破产标志。[15]
  2. 对训练数据中的行进行采样和重新加权,以尽量减少训练数据中不必要的社会学偏差,例如在 AIF360 中重新加权。

模特培训与选拔:

  1. 选择超参数和截止阈值时考虑公平性度量。
  2. 直接培训展会模特:
  • AIF360 中学习公平陈述(LFR)和对抗性去偏见。
  • 使用考虑准确性和公平性度量的双目标函数。

**预测后处理:**训练后改变模型预测,如 AIF360themis-ml 中的拒绝选项分类。

(当然,在 2019 年的 ML 模型中给出两段关于修正不想要的社会学偏见的主题近乎荒谬和冒犯。今天,有许多技术可以修正不必要的社会学偏见。了解更多关于他们的信息。今天真的没有借口部署种族主义模型,但它一直在发生,甚至在高风险的生命危急的情况下。[16])

3.6 模型管理和监控

知道你有多少模型,谁训练了他们,什么时候训练的。像记录其他软件资产一样记录它们。此外,监控重要的已部署 ML 模型输入和预测。注意相关的趋势和异常情况。不要只关注准确性。还要考虑公平和安全问题。

大多数数据科学家现在明白,模型通常是根据现实快照的数据进行训练的。随着时间的推移,现实会发生变化。新数据会偏离该快照,并且新数据的模型准确性会降低。这种模型漂移可能在模型输入和预测的统计趋势中很明显。这种漂移会影响模型的公平性吗?大概吧。因此,除了您今天可能要做的任何输入或预测监控之外,还要考虑对 DI 进行实时测试。

最后,当旧型号被拆卸下来进行更换时,旧型号应该退役,这意味着要小心保存,以备将来任何诊断、取证或诉讼需要。重要的模型不应该只是删除。

3.7 异常检测

异常的输入和预测总是令人担忧,并且可能预示着对手正在攻击您的模型。在示例 M-GBM 模型中,我们看到它对 PAY_0 的缺失值、PAY_0 的高值以及 PAY_AMT1 和 PAY_AMT3 的极低值特别敏感。在这种情况下,缺失和其他不合逻辑的值可能甚至不允许进入 M-GBM 的生产评分队列。对具有高值 PAY_0 或极低值 PAY_AMT1 和 PAY_AMT3 的新数据进行实时监控,可能会将这些客户转移到人工个案工作者或更透明的模型中进行处理。

要实时捕捉异常预测,请考虑传统的统计过程控制方法,将 ML 预测与稳定透明的基准模型预测进行比较,或者监控新数据如何流经您的模型。(后者有时被称为激活分析。)对于基准模型,将 ML 模型预测与基准模型预测进行比较。如果它们非常不同,在发布预测之前仔细看看,或者只对这些数据使用基准模型预测。对于激活分析,新数据通常不应该流过在模型训练期间不频繁激活的模型机制(例如,决策树节点或神经网络隐藏单元)。如果这种情况经常发生,最安全的做法可能是调查原因。

4.进一步阅读和总结

这篇文章介绍了 ML 模型的几种调试策略,主要集中在结构化数据和标准商业数据挖掘用例上。如果您感兴趣,可以深入研究用于在 GitHub 上创建我的示例的代码。[17]要了解 ML 研究社区中模型调试的情况,请查看学习表示国际会议(ICLR)调试机器学习模型研讨会会议录。[18]

虽然从业者和研究人员正在围绕模型调试展开讨论,但该学科可能仍处于起步阶段。从这里到哪里很大程度上取决于我们。每当 ML 被用于商业或生活关键决策时,我个人希望看到更多值得信赖的 ML 和模型调试。

5.参考

[1]参见: 当一台电脑把你关在监狱里

[2]如测试调试机器学习模型机器学习:技术债 的高息信用卡,或tensor flow 的模型分析工具

[3]参见:信用卡客户数据集的默认

[4]参见: 教我数据分析

[5]参见: 可解释性机器学习 ,第 5.9 节

[6]参见: 残(Sur)实在论

[7]例如, 公平通过认识相关的工作

[8] 机器学习中的公平、问责和透明

[9] 模型漏洞与安全建议

[10] 警告信号:机器学习时代的安全和隐私的未来

【11】机器学习中的受控实验

【12】IBM、微软、Face++ AI 服务对人脸性别的猜测有多准?

【模型断言】用于调试机器学习

[14] 塔吉特如何在她父亲之前发现一名少女怀孕了

[15] 负责任的数据科学:识别并修复有偏见的人工智能

【16】数百万黑人受医疗算法中的种族偏见影响

[17] 用 Python 进行可解释的机器学习

调试机器学习模型

生产机器学习模型的策略

原文:https://towardsdatascience.com/strategies-for-productionizing-our-machine-learning-models-53399a3199da?source=collection_archive---------22-----------------------

让我们的最佳模式更快见天日,帮助企业更好地做出决策

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by ian dooley on Unsplash

因此,您已经编写了您最好的机器学习代码,并且现在已经将模型调至最佳精度。

现在怎么办?

您将如何部署您的模型,以便业务能够真正利用该模型并做出更好的决策?

这是我上一篇讨论生产大数据 ETL 的文章的后续。在这篇文章中,我将讨论生产我们的机器学习模型的不同策略。

典型的培训工作流程

我们都熟悉机器学习,以及如何找到最佳模型。这是我们工作流程的样子-

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Typical EDA and Training workflow

作为一名数据科学家,我们通常将数据分为训练和测试数据,并用训练数据训练模型,然后我们预测测试数据,并根据误差指标或准确性微调我们的模型。

在此活动结束时,我们将获得具有最佳准确度分数的最佳模型。

典型部署工作流

通常,一旦我们找到了最佳模型,我们会想把它保存在某个地方。保存模型很重要,因为我们在训练阶段经过大量努力和时间后实现了这一模型。我们希望重用该模型,并为新数据的预测阶段加载该模型。

这是典型部署工作流的样子——

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Typical Prediction workflow

在这个工作流中,我们需要一些机制来加载我们保存的模型,并通过新到达的数据运行它。此阶段的输出是输入数据的预测数据/标签。

企业可能希望将这些数据保存在某个地方,或者根据实时预测数据采取一些措施。

部署策略

有各种策略来部署我们的机器学习模型。策略的选择完全取决于我们计划如何消耗输出预测的业务需求。

批量预测

这种预测策略通常在一天中的特定时间运行预测,或者以固定的时间间隔在一天中运行多次。当我们不需要等待实时决策并且可以按时间批量输入数据时,这种策略非常有用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Batch Prediction strategy

主要步骤如下

  • 代码以固定的时间/间隔运行
  • 代码从保存的位置加载模型
  • 代码读取一批输入数据
  • 输入数据是我们想要预测的新的和未标记的数据
  • 输入数据可能包含分组在一起的多个用户/实体的数据
  • 代码对输入批次运行模型预测,并产生一个预测批次
  • 预测批次包含输入数据中每条记录的预测标签
  • 预测的数据然后被保存在一些新的位置

随着批预测管道继续运行,新的预测数据将继续追加到该位置。这些数据可用于分析和决策。

流式/实时预测

当必须立即做出决定时,这种策略非常有用。通常有一个应用程序需要根据用户的交互/行为/属性动态地做出一些决定。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Streaming / Realtime prediction strategy

主要步骤如下

  • 我们有一个包装代码的 web 服务
  • web 服务公开 Rest 端点以获取预测
  • 消费者应用程序进行 web 服务调用,并以 Json 格式发送输入数据
  • 输入数据包含预测所需的所有特征。它通常只有一条记录,而不是一批
  • 代码从保存的位置加载模型
  • 当调用 web 服务端点时,代码获取输入数据
  • 代码对输入数据运行模型预测,并产生预测数据
  • 预测数据被返回给消费者应用程序
  • 消费者应用程序可以决定如何使用预测数据来获得更好的用户体验

通过 SQL 进行即席预测

这是最近在业内流行的一种新趋势。这种方法将 ML 模型公开为 SQL 函数。这种方法将新的输入数据视为表格,并允许通过将 ML 模型作为函数运行来对数据进行特别分析。输出也以表格形式显示,如果需要,可以保存下来供将来使用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Ad-hoc / SQL based prediction strategy

主要步骤如下

  • ML 模型被包装在 SQL UDF 中
  • 有一个理解 UDF 的 SQL 执行引擎(如 Spark 或 Google Big Table)
  • SQL 执行引擎在 UDF 中加载代码
  • 用户向执行引擎发出 SQL 查询,在 SQL 查询中选择特征表
  • 执行引擎通过 UDF 运行输入要素来计算预测
  • 预测数据被返回给用户
  • 用户可以将预测数据保存为新表

实施思路

业内有各种方法解决这个问题。

气流调度程序

气流调度程序非常适合*批量预测策略。*它可以将最大似然训练和最大似然预测作为独立的作业在不同的时间间隔运行。气流还提供了过去所有跑步的可视性。所有预测运行都可以记录预测详细信息,以供将来分析。

码头集装箱

这是 Kaggle 在比赛中采用的方法之一。我们可以为训练和预测工作旋转 Docker 容器。容器可用于批量和实时预测策略。

亚马逊 SageMaker

这是最流行的部署策略之一。最好的部分是它由亚马逊管理,我们不需要模型部署的基础设施。

我们可以在 Jupyter 笔记本中提供我们的 ML 代码。部署在 sagemaker 上的每个 ML 模型都有一个惟一的部署端点,可以用于预测。

这里有一个关于 SageMaker 入门的很棒的教程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Amazon Sage maker — Web Interface

谷歌大查询 ML

谷歌已经开始在 BigQuery 之上提供机器学习功能。它允许我们在现有的 BigQuery 表之上使用 ML 模型作为 SQL 函数。

这里有一个关于开始使用 BigQuery ML 的很棒的教程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Big Query ML — SQL predictions

毫升流量

ML flow 是 Databricks 的一项新举措。ML flow 是开源,并为用户提供模型跟踪和服务的能力。ML flow 对于培训生命周期来说也是很棒的,因为它提供了一个 web 界面来显示模型在多次运行中的性能和准确性。ML flow 还允许我们将多次运行作为单个实验的一部分进行分组。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ML Flow — Model tracking and serving

ML flow 的伟大之处在于,我们不必为保存和加载模型而编码。ML flow 为我们提供了 Python 库来加载和保存模型。

ML flow 的另一个优点是,一旦模型与 ML flow 一起保存,就可以通过上面提到的三种策略中的任何一种进行部署。

这里有一个关于开始使用 ML flow 的很棒的教程

这个帖子到此为止。在下一篇文章中,我计划写一篇关于 ML flow 或 SageMaker 的深度文章。敬请关注。

原载于 2019 年 3 月 4 日confusedcoders.com

分层抽样以及如何在 R

原文:https://towardsdatascience.com/stratified-sampling-and-how-to-perform-it-in-r-8b753efde1ef?source=collection_archive---------6-----------------------

对大型数据集进行采样的正确方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Giorgio Tomassetti on Unsplash

之前的一篇文章中,我写了关于以适当的方式从人群中选择样本的重要性。今天我将向大家展示一种叫做分层抽样的技术,它可以帮助我们从一个庞大的数据集中创建一个具有统计显著性的样本。

对大量人口进行抽样的正确方法

当我们从总体中执行一个样本时,我们想要实现的是一个更小的数据集,它保持总体的相同的统计信息

产生一个相当好的样本的最好方法是统一收集人口记录,但是这种工作方式并不是完美的。事实上,虽然平均来说效果很好,但单个样本与总体差异太大的概率仍然很低,有限。这种概率非常小,但它会在我们的样本中引入偏差,这将破坏我们在其上训练的任何机器学习模型的预测能力。

真正的要点是,我们不想要一个理论上正确的方法,这个方法适用于大数;我们想要提取一个正确的样本,并尽可能具有最高的统计显著性。

在这一点上,统一的抽样已经不够了,我们需要一个更强的方法。

分层抽样

分层抽样是为了从一个人口记录到另一个记录构建样本,尽可能忠实地保持原始多元直方图而创建的一种方法。

它是如何工作的?好吧,让我们从一个单一的,单变量直方图开始。对这种直方图进行采样的最佳方式是将 0–1 区间分割成子区间,子区间的宽度与直方图条的概率相同。然后,我们从 0 和 1 之间的均匀分布生成一个伪随机数。我们将根据随机数的位置从直方图中选择一个值。然后我们想重复多少次就重复多少次。

下图让一切都变得更加清晰。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这张图表是由以下代码制成的:

library(“ggplot2”)s = c(rep(“A”,50),rep(“B”,35),rep(“C”,15))d = as.data.frame(table(s))p = ggplot(d,aes(x=s,y=Freq,fill=s)) + geom_bar(stat=”identity”)+
 geom_text(aes(label=Freq),vjust=1.6) +
 theme(legend.position = “none”)

p

如何在 R 中进行采样?强大的样本功能可以指定赋予每个值的权重,即概率。

因此,如果我们想要该数据的 10 个样本观察值,我们可以简单地使用这一行代码:

sample(d$s,replace = TRUE,prob = d$Freq,10)

通过这种方式,我们能够创建具有高置信度的直方图,迫使样本遵循相同的总体分布。

多元方法

多元直方图怎么样?嗯,多元直方图只是许多直方图的层次结构,通过条件概率贝叶斯公式粘合在一起。我们可以轻松地将多变量直方图转换为单变量直方图来标记每个聚类组合,但是如果我们有太多的列,那么在计算上很难将它们全部聚集起来。当我试图在 200 列上聚合 3000 万条记录的数据集时,我亲眼目睹了强大的 RDBMS 的失败。

通过下面的过程,我们可以独立地管理每一列**,而不用关心它们的数量,也不会让我们的 CPU 遭受太多的痛苦。**

程序如下:

  • 根据第一个变量聚集整个数据集(即根据第一个变量创建数据集的直方图)。
  • ****根据用于单变量直方图的相同技术,选择该变量的一个值。
  • ****过滤整个数据集,仅考虑那些在所选变量上具有该值的记录。
  • 继续处理第二个变量(聚合并选择一个值)等等,直到最后一个变量。由于过滤器的作用,每一步都会产生一个更小的数据集。
  • 最后,您有一个非常小的数据集,但没有变量留给切片。此时,您可以从该数据集中选择一个随机记录统一并重复整个过程,直到您得到想要的样本大小。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Stratified sampling procedure

连续值和分类值

会发生什么呢?有些变量是连续的,有些是分类的?嗯,问题现在变得非常困难。我能给你的唯一答案是用直方图标准(如斯特奇斯或赖斯的)离散化连续变量。

给定数据集中的 n 点,用于直方图的仓的数量 k 通过以下公式从两个规则中导出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Sturges’ rule

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Rice rule

让我们看看他们的行动。使用下面的代码,我们将从对数正态分布(本质上是偏斜的)中创建 10000 个随机数,绘制原始密度函数和由这两个规则生成的直方图。

x = rlnorm(10000,0,0.5)
windows()
layout(matrix(c(1,1,2,3), 2, 2, byrow = TRUE))plot(seq(0,3,length.out=1000),dlnorm(seq(0,3,length.out=1000),0,0.5),xlab="x",ylab="Density",main="Lognormal distribution with mean = 0 and sd = 0.5")hist(x,probability = TRUE,main="Sturges rule",xlim=c(0,3))hist(x,breaks=2*length(x)**(1/3),probability = TRUE,main="Rice rule",xlim=c(0,3))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如你所见,莱斯法则能够非常有效地再现原始概率分布形状。这就是为什么它是我个人最喜欢的直方图标准,我总是用它来离散数值变量。****

R 中的一个例子

现在是时候让所有的理论在 r 变成实践了。

首先,我们将模拟一些数据,确定维度和所需的样本大小:

**# Generate a random 10000 records data frame
set.seed(1)
n = 1000
d = data.frame(
    a = sample(c(1,NA),replace=TRUE,n),
    b = sample(c("a 1","b 2","c 3"),replace=TRUE,n),
    c = c(runif(n-100,0,1),rep(NA,100)),
    id = 1:n
  )# Remove the useless "id" column
dimensions = setdiff(names(d),"id")# Desired sample size
n_sample = 100**

然后,我们执行分层采样,目标是用样本填充生成的数据帧,而不重复。为了应用最后一条规则,我们将使用强大的 sqldf 库。

现在“生成”的数据帧包含了我们想要的样本。

结论

在本文中,我介绍了数据科学家应该知道的最重要的采样技术。记住:一个生成良好的样本真的可以在机器学习中发挥作用,因为它可以让我们用更少的数据工作,而不会失去统计意义。****

Gianluca Malato 是意大利的一名小说作家和数据科学家。他的书可以在 亚马逊 上找到,他的文章可以在 中型 上找到。

面向数据工程师的从 S3 存储桶到雪花数据库的数据流

原文:https://towardsdatascience.com/streaming-from-s3-buckets-to-snowflake-db-for-data-engineers-8e4827b81b16?source=collection_archive---------7-----------------------

如何使用 Snowpipe REST API 调用将文件加载到表中的工作示例。这是一个关于如何连接雪花以及如何使用 Snowpipe 将文件摄取到雪花表中的小教程。因此,为了向我们亲爱的读者提供本教程,我们在雪花开设了一个免费试用账户。本课包含三个步骤,第一步是将数据从您的计算机加载到内部阶段,第二步是将数据从 S3 存储桶手动加载到外部阶段,最后一步是使用 AWS Lambda 函数将数据加载到外部阶段。

我们为什么要这么做?为什么我们不把它从 S3 桶自动加载到雪花表呢?

这个过程背后的原因是为了更好地理解 S3 桶和雪花表如何和谐地一起工作。所以你可以用更少的工作,最少的努力享受更多的满足感。但是在我们开始玩雪花和 S3 之前,让我们检查一下需求。

要求

  1. 通过 AWS 帐户访问 S3 时段。
  2. 通过雪花帐户访问雪花控制台。
  3. 通过 AWS 帐户访问 EC2 实例。

第一步:从内部阶段加载数据

在本文档的这一部分中,您将在 Snowflake 中准备好创建表、阶段和管道的环境,通过遵循以下语句,您将能够实现这一点:

  • 在文件~/中定义与您的用户、帐户和密码的连接。snowsql/config,连接的名称是 zaid_connection
  • 在您终端和雪花工作表中运行这些命令
snowsql -c zaid_connection -o log_level=DEBUGalter user almalikz set RSA_PUBLIC_KEY="your_public_key"desc user almalikzcreate user zaid_user password='your_password';alter user zaid_user set rsa_public_key='your_public_key';use role securityadmin; create or replace role snowpipe_s3; grant usage on warehouse compute_wh to role snowpipe_s3; grant usage on database demo_db to role snowpipe_s3; grant usage on schema demo_db.public to role snowpipe_s3; grant insert, select on demo_db.public.TABLE_S3 to role snowpipe_s3; grant read on stage demo_db.public.STAGE_S3 to role snowpipe_s3; grant ownership on pipe demo_db.public.PIPE_S3 to role snowpipe_s3; grant role snowpipe_s3 to user zaid_user; alter user zaid_user set default_role = snowpipe_s3;create or replace table TABLE_S3(c1 number, c2 string); 
create or replace stage STAGE_S3; 
put file:///data/test_file.csv @STAGE_S3; 
create or replace pipe demo_db.public.PIPE_S3 as copy into TABLE_S3 from @STAGE_S3;

所以我们创建了这个程序simple _ ingest _ snow flake . py来访问雪花,使用用户、帐户、主机、端口、管道名、pem 格式的私钥,在下面的文件中检查这些参数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ingest_manager = SimpleIngestManager(account='by16910',
 user='almalikz',
 private_key=private_key_pem, 
 pipe=pipe_name,
 scheme='https',
 host='by16910.eu-west-1.snowflakecomputing.com',
 port=443)

在上面提到的 python 程序中,我们使用这些参数来构建 JWT。让我们从一个抽象的定义开始。

JSON Web 令牌(JWT)是一个 JSON 对象,它在RFC 7519中被定义为一种安全的方式来表示双方之间的一组信息。令牌由报头、有效载荷和签名组成。

米奇·斯泰基-埃凡蒂斯

在 Snowflake 中,jwt 的生成是预先构建到 Snowflake API 提供的 python 库中的(并且记录在 Snowflake 文档中),所以理想情况下,我们只需编写一个简单的脚本,使用这些库来为我们自动处理 jwt。通过包装器的 python 代码 简单-摄取-雪花

在我们运行程序几秒钟后,我们成功地将文件从内部暂存区摄取到雪花的表区,您可以检查接下来的日志,一切都很顺利。

*DEBUG:botocore.vendored.requests.packages.urllib3.connectionpool:"POST/v1/data/pipes/demo_db.public.PIPE_S3/insertFiles?requestId=b9f27491-6434-4c5f-93b6-c6831afae12d HTTP/1.1" 200 88 DEBUG:snowflake.ingest.simple_ingest_manager:Ingest response: {'requestId': 'b9f27491-6434-4c5f-93b6-c6831afae12d', 'responseCode': 'SUCCESS'}*

如果您检查上面的日志,您可以看到,首先是 POST 操作,其次是响应代码成功,这是积极的反馈。

*'pipe': 'DEMO_DB.PUBLIC.PIPE_S3', 'completeResult': True, 'nextBeginMark': '1_0', 'files': [ {'path': test_file.csv.gz', 'stageLocation': 'stages/b3767d50-e0f8-4bb2-a52a-6677122c8223/', 'fileSize': 64, 'timeReceived': '2019-05-14T13:48:30.725Z', 'lastInsertTime': '2019-05-14T13:49:00.579Z', 'rowsInserted': 4, 'rowsParsed': 4, 'errorsSeen': 0, 'errorLimit': 1, 'complete': True, 'status': 'LOADED'}*

然而,第二个日志是一个 GET 操作,由我们代码中的表达式调用,用于检查文件大小、接收时间、看到的错误、是否完成以及状态类型(在我们的例子中是 loaded)。

第二步:从 S3 外部阶段加载数据

在本节中,我们将讨论如何使用雪花和通知事件的自动摄取新功能来摄取数据,我们成功地将数据从 S3 存储桶传输到雪花表,但我们是手动完成的,为什么要手动呢?因为我们的免费帐户没有自动摄取激活选项,这就是为什么我们没有通知和自动摄取。我们通过执行以下任务来完成这一步:

第一项任务:设置你的 AWS 账户。

对于此任务,您必须遵循 AWS 安全的良好实践,并考虑以下规则:

  1. 删除 root 密码。
  2. 创建一个 IAM 用户。
  3. 创建一个新组。
  4. 定义新的 IAM 密码策略。

第二项任务:更改仓库以支持自动恢复模式

我们有两种类型的用户,一种是管理员用户 almalikz ,另一种是普通用户 zaid_user ,因此该任务只能使用管理员用户激活:

**alter warehouse compute_wh resume;**

第三个任务:将数据加载到雪花表中

在此任务中,我们使用普通用户帐户 zaid_user,而不是管理员用户。

**create or replace stage s3_stage*
 *url= 's3://outputzaid/'*
 *credentials = (AWS_KEY_ID = 'your_key' AWS_SECRET_KEY='your_secret');
create or replace table s3_table(c1 number, c2 string);
copy into s3_table*
 *from s3://outputzaid/test_file_trusted.csv credentials=(AWS_KEY_ID = 'your_key' AWS_SECRET_KEY='your_secret')*
 *file_format = (type = csv field_delimiter = ',' );**

第三步:使用 Lambda 函数从 S3 阶段加载数据

在这一节中,我们将引导您完成使用 AWS Lambda 函数自动化 Snowpipe 的过程。

AWS Lambda 是一个事件驱动的无服务器计算平台,由 Amazon 作为 Amazon Web Service 的一部分提供。它在被事件触发时运行,并执行已经加载到系统中的代码。您可以修改本主题中提供的示例 python 代码,并创建一个 Lambda 函数,该函数调用 Snowpipe REST API 从外部阶段 S3 加载数据。该功能部署到您的 AWS 帐户中,在那里托管它。您在 Lambda 中定义的事件(例如,当您的 S3 存储桶中的文件被更新时)调用 Lambda 函数并运行 python 代码。

本节描述了配置 Lambda 函数以使用 Snowpipe 连续地以微批处理方式自动加载数据的必要步骤。因此,让我们开始遵循以下步骤:

第一项任务:访问 AWS 实例

  1. 访问您的 EC2 微实例,并检查关于 your-ssh-key-name 的信息。
  2. 使用 AWS 控制台的 web 向导创建并运行 EC2 的实例。
  3. 下载 ssh-key。
  4. 使用 ssh 命令选项连接实例。
**ssh -i "zaid_key.pem" ubuntu@ec2-3-91-26-48.compute-1.amazonaws.com**

第二个任务:创建 Lambda 执行环境

为了完成本指南,您需要首先创建一个包含您的代码及其依赖项的部署包。一种简单的方法是获取一个 t2.micro 实例,并建立一个模拟 python Lambda 运行环境的执行环境。这是您必须在 EC2 微实例中执行的步骤,遵循以下命令:

**sudo apt-get install gcc make zip awscli libffi-dev openssl libssl-dev zlib1g-dev
wget* [*https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz*](https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz) *tar -xzvf Python-3.6.1.tgz
cd Python-3.6.1 && ./configure && make
sudo make install
sudo pip3 install --upgrade pip 
/usr/local/bin/virtualenv ~/zaid_venv* 
s*ource zaid_venv/bin/activate
pip install Pillow
pip install boto3
pip install requests
pip install snowflake-ingest**

第三个任务:创建 Python 部署包

  1. 编辑 lambda 处理函数 为一个基本的 Lambda 处理函数创建文件【Lambda _ Function . py,该函数使用 python 的雪花连接器。调整连接变量、表名和 S3 存储桶,以匹配您的环境。
  2. 创建并打包 python 虚拟环境 脚本Package _ lambda _ function . sh包含为您的 Lambda 函数创建并打包 Python 环境的命令。这里要小心,因为如果你改变包含 Lambda 处理程序的文件名,你也必须修改这个脚本。
  3. 使用 将代码复制到 AWS EC2 实例运行package _ Lambda _ function . sh后,将生成文件 lambda_function.zip 包含您的 python Lambda 处理程序代码/文件以及在 AWS Lambda 环境中运行所需的 python 依赖项。
  4. 在雪花中创建阶段、表格和管道
**create or replace stage s3_stage url= 's3://outputzaid/' credentials = (AWS_KEY_ID = 'your_key' AWS_SECRET_KEY='your_secret');create or replace table s3_table(c1 number, c2 string);create or replace pipe s3_pipe as copy into s3_table from @s3_stage file_format = (type = 'CSV');create or replace pipe s3_pipe as copy into s3_table from @s3_stage file_format = (type = 'CSV');**

第四项任务:创建和配置 AWS Lambda 权限

  1. 运行 aws configure 并编写您的凭证和您的默认区域
  2. 为了执行 Lambda,您需要使用 aws 命令为角色和策略创建和设置适当的权限,然后上传包含我们的 python 环境的 zip 存档。这些命令可以在文件AWS _ lambda _ setup . sh中找到

第五项任务:使用测试文件测试 Lambda 函数

此时,您可以测试启动 Lambda,并在 AWS Web 控制台 UI 中查看输出。导航至λ>函数>λ_ 函数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

您现在应该看到右上方的列表框,因此您需要在这里配置一个测试,您选择一个名称,并将以下语句放入测试框中

*{ "Records": [ { "eventVersion": "2.0", "eventSource": "aws:s3", "awsRegion": "us-east-1", "eventTime": "1970-01-01T00:00:00.000Z", "eventName": "ObjectCreated:Put", "userIdentity": { "principalId": "AIDAJDPLRKLG7UEXAMPLE" }, "s3": { "s3SchemaVersion": "1.0", "configurationId": "testConfigRule", "bucket": { "name": "outputzaid", "ownerIdentity": { "principalId": "A3NL1KOZZKExample" }, "arn": "arn:aws:s3:::sourcebucket" }, "object": { "key": "test_file_lambda.csv", "size": 1024, "eTag": "d41d8cd98f00b204e9800998ecf8427e", "versionId": "096fKKXTRTtl3on89fVO.nfljtsv6qko" } } } ] }*

结论

你完成了任务,我亲爱的朋友,干得好!
您已经创建了一个 Lambda 函数,将数据从 S3 桶传输到雪花表,这是您成为数据工程师的第一步!
我已经创建了相当多的教程来告诉你如何做流数据。所有这些都是从最基本的开始。我们将在接下来的几周开始放更多的文章。因此,请与我们保持联系,并探索一种学习流式数据的简单方法。

干杯,
扎伊德·阿利萨·阿尔马利基

或者,你可以获得 5 美元/月的中等订阅。如果你使用这个链接,它会支持我。

在 Twitch 上寻找成功

原文:https://towardsdatascience.com/streaming-recommender-twitch-e40d4a45e4ee?source=collection_archive---------8-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Caspar Camille Rubin on Unsplash

介绍

似乎就在几周前,我在 Metis 开始了我的旅程,这是一个位于旧金山的沉浸式和挑战性的数据科学项目,十二周后,我们在这里进行我们的最终项目。在这篇博客文章中,我们将介绍我们如何为 Twitch 构建流媒体推荐器,以及我们用来制作应用程序的各种工具,现在可以在 Heroku 上使用。这个项目的代码可以在这里找到。

这一切都始于一个想法。在我的沉浸式活动工作室挂灯笼工作两年后,我加入了创意内容创作者的行列,与他们非常熟悉。不断努力向观众或参与者提供愉快的体验是一个艰难但令人兴奋的挑战,所以我在 Metis 工作期间,通过研究 Kickstarter 活动的过程和公众对《权力的游戏》的看法,探索了它的各个方面。

当选择最终项目的时候,我正在考虑为流行的流媒体网站 Twitch 上的内容创作者制作一个推荐系统,以表达我对视频游戏的热爱和帮助内容创作者的热情。当时看起来好像没有这样的推荐者,尽管有很多文章对流媒体内容提供建议,还有几个网站致力于 Twitch running stats。这似乎是一个完美而过于雄心勃勃的最终项目,我不是我们团队中唯一一个对视频游戏和 Twitch 充满热情的人。与 Jeremy ChowRandy Macaraeg一起,我们开始了Metis 有史以来第一个三人最终项目工作,我们着手为 Streamers 制作一个全功能的 Twitch 推荐器。

抽动是怎么工作的?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Ninja’s channel page on Twitch

对于那些不熟悉它的人来说,Twitch 是一个流媒体视频网站,内容创作者通过播放流行的视频游戏或其他娱乐内容来吸引大量观众和订户。仅在 2018 年,Twitch 上就消费了超过100 万年的内容,每月有超过 400 万条独特的流媒体提供这些内容。正如你所想象的,有这么多的选择看什么,流光是相互竞争的观众和专门的订户。

选择一个游戏(或类别)在 Twitch 上播放是最难做出的选择之一,也是最能影响你成功的一个选择**。(作者《涌现》的马克·朗赫斯特(Mark Longhurst)在《如何选择流媒体游戏》一书中写道)**

这正是我们的推荐者要解决的问题,这样的问题不是 Twitch 独有的,许多公司将内容、商品或服务的提供商与这些产品的消费者联系起来,因此消费者可以获得的产品的多样性和质量对公司的福利有直接影响。

特别是对于 Twitch 来说,我们的目标是帮助流媒体公司选择最佳的增长游戏,吸引观众和订户,发展他们的频道并分享他们喜欢的内容。

让我们来看看两条假设的抽动彩带:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by KAL VISUALS on Unsplash

Melany 是一个全新的流人,她知道她喜欢什么,但不确定她喜欢的流派和游戏是否会给她带来观众订户**。**

如果我们知道她喜欢角色扮演冒险游戏,并且她最喜欢的游戏是巫师 3:疯狂狩猎龙腾世纪:起源**,我们可以向她展示这些类型和游戏目前在 Twitch 上的表现,这样她就可以决定她是否想要继续玩下去。我们还可以展示当前的流媒体趋势,以帮助她了解市场,确定她可以填补的供应缺口,并确保她可以专注于她已经熟悉的游戏类型。**

她需要知道:

她应该把她最喜欢的视频串流吗?

哪些内容会产生更多的浏览量?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Unsplash

亚历克斯,另一方面,是一个现有的流光。她的堡垒之夜马登 NFL** 游戏已经有了观众,她希望探索增长选项,带来现有的粉丝,进一步扩大她的观众群,探索她最喜欢的射手体育游戏类型。**

她需要知道:

她现有的观众会喜欢的下一个大型游戏是什么?

她还应该尝试哪些游戏来保持势头?

让我们建立一个数据管道

记住这两个 streamer 案例,让我们浏览一下我们的数据收集过程。

只有三周的时间来实现我们脑海中的复杂愿景,我们投入到数据收集中。在研究了几个 Twitch 分析网站后,我给 SullyGnome 的所有者发了一条 Twitter 消息,他慷慨地向我们提供了 40 天的 Twitch 汇总数据,为我们提供了收视率和频道流信息

为了提取恒定的流数据,我们构建了一个查询 API 的管道,通过 Amazon EC2 实例将数据传输到我们使用 Amazon 关系数据库服务创建的 PostgreSQL 数据库中,并保存在那里供我们使用。然后,我们获取这些数据进行数据分析和开发,并使用 Heroku 推出我们的应用程序。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个管道的架构确保我们在任何时候都可以访问相同的信息流,Python 脚本每小时收集一次 Twitch 数据,将结果存放到我们为接收信息而设置的三个 PostgreSQL 表中。

 **Our PostgreSQL Tables Schema****stream_data                              game_information**stream_id text                           game_id text
 user_id text                             game_name text
 user_name text                           pic_url
 game_id text                            
 stream_type text
 title text                              **game_genres**
 viewer_count int                         
 started_at timestamp                     game_name text
 language text                            game_genres text
 time_logged timestamp

表格完成后,我们直接查询数据并开始探索性的数据分析。这种分析的精华可以在推荐应用程序的第一个标签和我们的 Tableau 仪表盘中找到。例如,我们通过观察观众与频道的比率变化,检查了哪些类型的内容正在增长,并找到了那些有流媒体增长和进入空间的类型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Taste of our Tableau graphs, the entire selection is linked below.

** [## 随着时间的推移,Twitch 的游戏、类型、频道和收视率的趋势。GitHub…

随着时间的推移,Twitch 的游戏、类型、频道和收视率的趋势。GitHub…

随着时间的推移,Twitch 的游戏、类型、频道和收视率的趋势。GitHub…public.tableau.com](https://public.tableau.com/views/TwitchVisualizations/PickYourGame?:embed=y&:display_count=yes&:origin=viz_share_link)

惊喜!我们的推荐创建流程

我们使用了惊奇 Python 库,它是开发推荐系统的一个很好的工具。对于这个框架,我们所需要的是关于我们的流媒体工具、他们喜欢的类型和游戏或者已经流媒体化的信息,以及我们开发的自定义游戏成功指标,该指标的范围从 1 到 5,并作为每个流媒体工具-游戏关系的评级。

我们的算法选择侧重于准确性和速度——较低的测试均方根误差意味着这些算法在处理未知数据时表现最佳,并且工作速度快,这意味着当可用的流数据量不断增加时,可以轻松地重新训练和部署。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这三者协同工作,根据流媒体工具的偏好、他们现有的体验(如果有的话)以及具有类似内容的其他流媒体工具的相对成功来确定最合适的游戏和流派。我们将它们融合在一起,为每个流媒体工具生成一个单一的推荐列表,提供各种类型和游戏进行流媒体播放,所有这些都有可能提高他们的收视率并留住订户。你可以在 Heroku 上亲自试用推荐者。目前,推荐应用程序中使用的模型是我们测试过的更简单、更快的模型,但如果服务器能够处理大量的流媒体数据,我们可以利用我们开发的更强大的算法。**

时机就是一切

除了推荐飘带和什么可以传送,我们还希望能够告诉他们什么时候是传送的好时机。考虑到 Twitch 的收视率在本质上是周期性的,通常收视率的峰值出现在晚上,识别一天或一周内的供应缺口变得非常重要。我们使用长短期记忆(LSTM)网络模型来研究观众和频道随时间的波动,旨在预测预期的变化。

LSTM 使用长期记忆来量化一段时间内的增长并检查季节性趋势,使用短期记忆来考虑最近/每天的趋势,其遗忘能力允许其进一步回顾,而没有其他网络如递归神经网络(RNNs)的速度损失。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们查看了整个上周的数据(168 小时),检查了 24 个最后的模型状态,并预测了接下来的一周(168 小时)。

当样本内和测试 RMSE 为 10%时,我们能够很好地预测流媒体频道随时间的波动。

成长得分

除了提供推荐和指定何时进行流媒体播放,我们还希望能够根据一个通用指标对我们推荐的游戏进行排名,该指标不仅包括我们之前讨论过的推荐评级,还包括作为前 8 大流媒体市场份额函数的增长潜力。这种方法可以防止流媒体工具试图闯入一个已经被少数人垄断、没有扩张空间的游戏。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Doesn’t this look clear and uncomplicated?

它真正的意思是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Ah, much better!

第一项,流媒体亲和力,来自推荐者本身,并且针对每个流媒体游戏的成功潜力而言是个人的,游戏增长游戏受欢迎程度随着时间而变化,并且可以从输入的数据流中推断出来,市场渗透性源自每个游戏被其顶级流媒体所垄断的程度。作为一个整体,成长分数反映了每个游戏的每个流的全部潜力。它目前正在开发中,我们希望将来在我们的建模中实现它。

总的来说,我们的推荐系统完成了几件重要的事情:它改善了流媒体体验和保留,它鼓励了频道的增长和内容的多样性,并增加了 Twitch 的收入。这种内容创建者推荐系统可以适用于其他公司和类型的内容创建。这个项目一直是一个令人惊叹的挑战,我们希望扩展我们的模型,以用于 Twitch 实时流数据,收集所有实时数据,并不断训练我们的推荐模型以提高其准确性,并将其完全集成到 Twitch 上的流媒体体验中。

你可以在 Heroku 上找到我们的应用程序。该推荐器的代码可在 GibHub 上找到。

感谢您的阅读。如果你想联系我,可以在 GithubLinkedInTwitter 上找到我。

** [## 娜塔莎·鲍德斯

具有市场研究和品牌管理、CPG、宠物和沉浸式活动行业背景的数据科学家…

www.natashaborders.com](https://www.natashaborders.com/)**

流式 scikit-通过 PySpark 学习

原文:https://towardsdatascience.com/streaming-scikit-learn-with-pyspark-c4806116a453?source=collection_archive---------8-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://www.maxpixels.net/Water-Creek-Stream-River-Cascade-Nationalpark-4324529

第八章《生产中的数据科学》节选

本章探索了模型管道,当记录到达一个流式 ML 框架时,在管道中对它们进行评估。这本书涵盖了 AWS 上的 Spark 和 Kafka 以及 GCP 上的 PubSub 和 Dataflow 的流工作流,而这篇博客文章则涵盖了前者。本章中所有例子的源代码都可以在 GitHub 上找到。

[## 生产中的数据科学

从初创公司到数万亿美元的公司,数据科学在帮助组织最大化…

leanpub.com](https://leanpub.com/ProductionDataScience)

第 8 章流模型工作流

许多组织现在都在使用流平台来构建实时数据管道,以转换数据流并在云环境中的不同组件之间移动数据。这些平台通常是分布式的,并为流数据提供容错。除了将不同的系统连接在一起,这些工具还提供了存储记录和创建事件队列的能力。

最受欢迎的流平台之一是 Apache Kafka,这是一个开源解决方案,用于跨公共云和私有云提供消息流。Kafka 是一个托管解决方案,需要供应和管理一个机器集群以便扩展。GCP 提供了一个名为 PubSub 的全托管流媒体平台,AWS 提供了一个名为 Kinesis 的托管解决方案。最佳选择取决于您的云平台、吞吐量和延迟要求以及开发运维问题。

借助流媒体平台,您可以在云环境中的不同组件之间以及外部系统之间传递数据。比如,现在很多游戏公司都在使用这些平台从手机游戏中收集游戏性事件,其中一个事件从游戏客户端传输到游戏服务器,然后以流的形式传递到数据平台。在这种情况下,消息生产者是将消息传递给消费者的游戏服务器,消费者是转换和存储事件的数据平台。

与生产中的数据科学的联系是,流平台可用于应用 ML 模型,作为流管道中的转换步骤。例如,您可以设置一个 Python 流程,该流程从一个主题读入消息,应用 sklearn 模型,并将预测输出到一个新主题。该过程可以是为用户提供实时 ML 预测的更大工作流的一部分,例如移动游戏中的物品推荐。对于扩展到大量消息的模型应用步骤,我们需要使用 Spark 和 Cloud Dataflow 等分布式系统,而不是单一的 Python 流程。

虽然流模型管道中的模型应用步骤类似于设置 Lambda 或 Cloud 函数,这已经提供了接近实时的预测,但一个关键的区别是易于与云平台中的其他组件集成。例如,使用 Cloud Dataflow,您可以将事件路由到 BigQuery 进行存储以及模型应用程序步骤,这可能会将输出推送给新的消息消费者。另一个好处是,它支持使用分布式工具(如 PySpark)来处理模型应用程序的请求,而不是使用基于端点的方法来孤立地处理请求。

在云平台中使用消息传递系统的好处之一是,它允许不同的工具和不同的编程语言使用标准化的接口进行通信。在本书中,我们将重点介绍 Python 和 PySpark,但是这些平台也支持 Java、Go 和许多其他语言。在本章中,我们将首先使用 Apache Kafka 在不同的 Python 进程之间传递消息,然后使用 PySpark 流来消费、转换和生成新消息。接下来,我们将使用 GCP 上的 PubSub,在流模式下使用云数据流提供近乎实时的模型预测。

8.1 火花流

Spark 从 0.7 版本开始就支持流数据集,但直到 2.3 版本才发布了一种称为结构化流的低延迟模式。借助结构化流,当扩展到高容量工作负载时,可以使用连续处理来实现毫秒级延迟。结构化流的一般流程是从输入流(如 Kafka)读取数据,使用 Spark SQL、Dataframe APIs 或 UDF 应用转换,并将结果写入输出流。Spark Streaming 还可以与包括 PubSub 和 Kinesis 在内的托管流平台以及包括 Flume 在内的 Apache 生态系统中的其他框架协同工作。

在这一节中,我们将首先设置一个 Kafka 实例,然后在同一台机器上使用 Kafka 生成和使用消息。接下来,我们将展示如何使用 PySpark 中的readStream函数消费来自 Kafka 的消息,然后构建一个应用 sklearn 模型的流管道。

8.1.1 阿帕奇卡夫卡

Kafka 是在 LinkedIn 孵化的开源流媒体平台。它旨在处理高吞吐量和低延迟的实时数据流。它是用 Java 和 Scala 编写的,但是支持一系列编程语言,用于通过标准化的 API 产生和消费流。通过使用水平扩展和分区将工作负载分布在称为代理的服务器集群上,该平台可以扩展到大型数据集。虽然开源的 Kafka 是一个托管的消息流解决方案,但一些云提供商现在提供完全托管版本的 Kafka,如 Amanon 的 MSK 产品。

为了展示 Kafka 如何集成到流工作流中,我们将使用单节点设置来启动和运行。对于生产环境,您会希望设置一个多节点集群来实现冗余和改进延迟。由于本章的重点是模型应用程序,因此我们不会深入探讨为高可用性设置 Kafka 的细节,而是为小团队的入门者推荐托管解决方案。要安装 Kafka,浏览到网站并找到最新版本是很有用的。为了安装 Kafka,我们首先需要安装 Java,然后下载并解压 Kafka 版本。在 EC2 机器上设置单节点 Kafka 实例所需的步骤如下面的代码片段所示。我们还将安装一个用于在 Python 中使用 Kafka 的库,名为kafka-python

sudo yum install -y java
pip install --user kafka-python
wget http:**//**mirror.reverse.net/pub/apache/kafka/2.4.0/
                                               kafka_2.12-2.4.0.tgz
tar -xzf kafka_2.12-2.4.0.tgz
cd kafka_2.12-2.4.0
bin/zookeeper-server-start.sh config/zookeeper.properties

***# new terminal*** bin/kafka-server-start.sh config/server.properties

***# new terminal*** bin/kafka-topics.sh --create --bootstrap-server localhost:9092 
                 --replication-factor 1 --partitions 1 --topic dsp

***# output*** [2019-12-18 10:50:25] INFO Log partition=dsp-0, dir=**/**tmp/kafka-logs 
    Completed load of log with 1 segments, log start offset 0 and 
    log end offset 0 **in** 56 **ms** (kafka.log.Log)

在设置 Kafka 时,我们需要生成三个独立的进程来运行依赖项,启动 Kafka 服务,并为发布消息创建一个新主题。上面的代码片段运行以下流程:

  • Zookeeper: 为分布式系统提供配置和服务发现的 Apache 项目。
  • Kafka 推出启动服务,支持设置 Kafka 主题和使用流式 API。
  • **主题:**创建一个名为“dsp”的新主题。

ZookeeperKafka任务是长期运行的进程,将继续执行直到终止,而Topics进程将在新的 Kafka 主题建立后关闭。代码片段底部的输出显示了运行该命令的输出,它将显示在运行Kafka流程的终端中。在这个配置中,我们为主题设置了一个单独的分区,没有复制。我们现在有了一个用于测试消息流的单节点 Kafka 集群。

我们将探索的第一个 API 是Producer API,它使流程能够向主题发布消息。为了向我们的 Kafka 服务器发布消息,我们通过传入一个地址和一个序列化函数来创建一个 producer 对象,该函数指定如何将 Python 对象编码成可以传递给 Kafka 服务器的字符串。下面的 Python 代码片段展示了如何创建生产者,如何将 dictionary 对象作为消息发送给服务器,并将消息发布到dsp主题。dict对象包含hellotime键。如果我们运行这段代码,消息应该会成功地传输到服务器,但是还没有消费者来处理消息。

from kafka import KafkaProducer
from json import dumps
import time

producer = **KafkaProducer**(bootstrap_servers=['localhost:9092'],
          value_serializer=lambda x: **dumps**(x)**.encode**('utf-8'))

data = {'hello' : 'world', 'time': **time.time**()}
**producer.send**('dsp', data)

为了建立一个消费消息的流程,我们将探索“消费者”API,它用于读入数据流。下面的 Python 片段展示了如何创建一个连接到 Kafka 服务器的消费者对象并订阅dsp主题。返回的consumer对象是可迭代的,可以与 for 循环结合使用来处理消息。在下面的例子中,for 循环将暂停执行,直到下一条消息到达,并继续迭代,直到进程终止。value对象将是我们从生产者那里传递过来的 Python 字典,而deserializer函数定义了如何将字符串转换成 Python 对象。这种方法适用于小规模的流,但是对于较大的数据量,我们还希望分布消息处理逻辑,我们将在下一节用 PySpark 演示这一点。

from kafka import KafkaConsumer
from json import loads

consumer = **KafkaConsumer**('dsp',
     bootstrap_servers=['localhost:9092'],
     value_deserializer=lambda x: **loads**(**x.decode**('utf-8')))

**for** x **in** consumer:
    **print**(x.value)

现在我们有了用于生成和消费消息的 Python 脚本,我们可以用 Kafka 测试消息流。首先,在 Jupyter 笔记本中运行Consumer脚本,然后在单独的笔记本中运行Producer脚本。在多次运行生产者单元之后,您应该看到来自消费者单元的输出,类似于下面显示的结果。

{'hello': 'world', 'time': 1576696313.876075}
{'hello': 'world', 'time': 1576696317.435035}
{'hello': 'world', 'time': 1576696318.219239}

我们现在可以使用 Kafka 在云部署中的不同组件之间可靠地传递消息。虽然本节使用了一个测试配置来启动 Kafka 服务,但是我们探讨的 API 适用于数据量大得多的生产环境。在下一节中,我们将探索用于处理流数据的Streams API,比如应用 ML 模型。

8.1.2 Sklearn 流

为了使用 Kafka 构建端到端的流管道,我们将利用 Spark 流来处理和转换到达的数据。Spark 2.3 中引入的结构化流增强支持使用数据帧和 Spark SQL,同时抽象出处理批处理和数据集的许多复杂性。在这一节中,我们将建立一个 PySpark 流管道,从 Kafka 主题中获取数据,应用 sklearn 模型,并将输出写入一个新主题。整个工作流是一个连续运行和处理来自 Kafka 服务的消息的 DAG。

为了让 Kafka 与 Databricks 一起工作,我们需要编辑 Kafka 配置以与外部连接一起工作,因为 data bricks 运行在独立的 VPC 上,并且可能与 Kafka 服务分开。此外,我们之前使用 bootstrap 方法来指代使用localhost作为 IP 的经纪人。在 AWS 上,Kafka 启动脚本将使用内部 IP 监听连接,为了启用来自远程机器的连接,我们需要更新配置以使用外部 IP,如下所示。

vi config/server.properties 
advertised.listeners=PLAINTEXT:**//**{external_ip}:9092

在进行了这个配置更改之后,您需要重新启动 Kafka 进程,以便从 Databricks 接收入站连接。您还需要通过修改安全组来启用来自远程机器的入站连接,这将在第 1.4.1 节中介绍。端口 9092 需要为将连接到 Kafka 服务的 Spark 节点打开。

我们还将设置第二个主题,用于发布模型应用步骤的结果。我们将建立的 PySpark 工作流将使用来自一个主题的消息,应用一个 sklearn 模型,然后将结果写入一个单独的主题,称为preds。这个工作流程的一个主要好处是,您可以替换掉进行预测的管道,而不会影响系统中的其他组件。这类似于云工作流中的组件调用端点进行预测,但我们可以无缝地交换新的后端逻辑,而不会影响工作流中的其他组件,而不是更改调用端点的组件的配置以指向新的端点。

bin/kafka-topics.sh --create --bootstrap-server localhost:9092 
                --replication-factor 1 --partitions 1 --topic preds

在考虑如何构建预测性建模管道之前,从简单地使用消息的基本工作流开始是一个很好的实践,尤其是在处理流数据时。为了确保我们已经正确地设置了 Kafka 与 Databricks 的远程连接,我们可以编写一个最小的脚本来使用流中的消息并输出结果,如下面的 PySpark 片段所示。Databricks 将定期刷新输出,并在新数据到达时在输出表中显示新数据。将startingOffsets值设置为earliest意味着我们将从最后一个 Kafka 检查点加载数据。移除此设置将意味着只有新消息显示在可视化表格中。

df = spark **.readStream.format**("kafka")
  **.option**("kafka.bootstrap.servers", "{external_ip}:9092")
  **.option**("subscribe", "dsp") 
  **.option**("startingOffsets", "earliest")**.load**()
**display**(df)

让 Databricks 与 Kafka 服务通信可能是让这个示例管道工作的主要挑战之一,这就是为什么我建议从最简单的 PySpark 脚本开始。编写简单的 UDF 来处理接收到的消息的value字段也很有用,这样可以确保 PySpark 中解码的消息与 Python 进程中编码的数据相匹配。一旦我们可以消费消息,我们将使用 UDF 来应用 sklearn 模型,其中 UDF 指的是 Python 函数,而不是熊猫 UDF。作为一般实践,向 Spark 工作流添加检查点是很好的,上面的代码片段是检查接收的数据是否与传输的数据匹配的一个很好的例子。

对于 Spark 流示例,我们将再次使用游戏数据集,它有十个属性和一个标签列。在这个工作流中,我们将把特征向量作为输入发送到流管道,并输出一个额外的预测列作为输出。我们还将添加一个惟一的标识符,如下面的 Python 片段所示,以便跟踪管道中的模型应用程序。下面的代码片段展示了如何用模型所需的 10 个属性创建一个 Python dict,将一个 GUID 附加到字典,并将对象发送到流模型主题。

from kafka import KafkaProducer
from json import dumps
import time
import uuidproducer = **KafkaProducer**(bootstrap_servers= ['{external_ip}:9092'],
          value_serializer=lambda x: **dumps**(x)**.encode**('utf-8'))data = { 'G1': 1, 'G2': 0, 'G3': 0, 'G4': 0, 'G5': 0, 
         'G6': 0, 'G7': 0, 'G8': 0, 'G9': 0, 'G10': 0, 
        'User_ID': **str**(**uuid.uuid1**())}
result = **producer.send**('dsp', data)
**result.get**()

为了实现流模型管道,我们将使用 PySpark 和 Python UDF 来在新元素到达时应用模型预测。Python UDF 对单行进行操作,而熊猫 UDF 对行的分区进行操作。下面的 PySpark 片段显示了该管道的代码,它首先在 driver 节点上训练一个模型,为 Kafka 流设置一个数据接收器,为应用 ML 模型定义一个 UDF,然后将分数作为管道输出发布到一个新主题。

from pyspark.sql.types import StringType
import json 
import pandas as pd
from sklearn.linear_model import LogisticRegression***# build a logistic regression model*** gamesDF = pd.read_csv("https://github.com/bgweber/Twitch/raw/
                       master/Recommendations/games-expand.csv")
model = LogisticRegression() 
model.fit(gamesDF.iloc[:,0:10], gamesDF['label'])***# define the UDF for scoring users*** def score(row):
    d = json.loads(row)
    p = pd.DataFrame.from_dict(d, orient = "index").transpose()   
    pred = model.predict_proba(p.iloc[:,0:10])[0][0]
    result = {'User_ID': d['User_ID'], 'pred': pred }
    return str(json.dumps(result))***# read from Kafka*** df = spark.readStream.format("kafka") 
  .option("kafka.bootstrap.servers", "{external_ip}:9092") 
  .option("subscribe", "dsp").load() ***# select the value field and apply the UDF*** df = df.selectExpr("CAST(value AS STRING)")
score_udf = udf(score, StringType())    
df = df.select( score_udf("value").alias("value"))***# Write results to Kafka*** query = df.writeStream.format("kafka") 
  .option("kafka.bootstrap.servers", "{external_ip}:9092") 
  .option("topic", "preds") 
  .option("checkpointLocation", "/temp").start()

该脚本首先使用从 GitHub 获取的数据训练一个逻辑回归模型。模型对象是在驱动程序节点上创建的,但在 UDF 使用时会被复制到工作节点。下一步是定义一个 UDF,我们将应用于管道中的流记录。Python UDF 将一个字符串作为输入,使用json库将字符串转换成字典,然后将字典转换成 Pandas 数据帧。dataframe 被传递给 model 对象,UDF 返回带有User_IDpred键的 dictionary 对象的字符串表示,其中预测值是用户购买特定游戏的倾向。

管道中的下三个步骤定义了 PySpark 流工作流。readStream调用建立了与 Kafka 代理的连接,并订阅了dsp主题。接下来,在将值传递给 UDF 之前,使用 select 语句将流记录的value列转换为字符串,然后使用 Python UDF 的结果创建一个新的数据帧。最后一步将输出数据帧写入preds主题,使用本地目录作为 Kafka 的检查点位置。这三个步骤作为连续处理工作流的一部分运行,其中这些步骤没有完成,而是暂停执行,直到新数据到达。结果是操作的流 DAG 在数据到达时对其进行处理。

运行流式管道时,Databricks 将在单元下方显示有关工作流的详细信息,如图 8.1 所示。绿色图标表示这是一个将继续执行直到终止的流式操作。还有一些图表可以直观显示数据吞吐量和延迟。对于生产管道,使用流程编排工具(如带有 Databricks 操作符的气流)来运行代码很有用,但笔记本环境确实提供了一个运行和调试流管道的有用环境。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

FIGURE 8.1: Visualizing stream processing in Databricks.

既然我们正在将模型预测流式传输到一个新的主题,我们需要为这些消息创建一个新的消费者。下面的 Python 代码片段显示了如何为新的预测主题使用来自代理的消息。与以前的消费者相比,唯一的变化是 IP 地址和deserializer函数,它不再在将字符串转换为字典之前应用编码。

from kafka import KafkaConsumer
from json import loadsconsumer = **KafkaConsumer**('preds',
     bootstrap_servers=['{external_ip}:9092'],
     value_deserializer=lambda x: **loads**(x))**for** x **in** consumer:
    **print**(x.value)

我们现在一切就绪,可以用 Spark streaming 和 Kafka 测试流媒体管道了。首先,在 Databricks 单元格中运行 PySpark 管道。接下来,在 Jupyter 笔记本中运行消费者脚本。要完成工作流,请在单独的 Jupyter 笔记本中运行生产者脚本,以向管道传递消息。结果应该是打印到消费者笔记本控制台的预测字典,如下所示。

{'User_ID': '4be94cd4-21e7-11ea-ae04-8c8590b3eee6', 
 'pred': 0.9325488640736544}

我们现在有一个 PySpark 流管道,它以接近实时的性能应用模型预测。我们可以执行额外的调整,将延迟控制在 1 毫秒以内,这对各种模型和 web 应用程序都很有用。使用 Spark 执行模型应用程序的好处是,我们可以扩展集群以满足需求,并且可以根据需要换入新的管道来提供模型更新。Spark streaming 最初的启动和运行有点棘手,但是最近的增强使得使用模型应用程序管道变得容易多了。在这个管道中,我们使用了一个简单的回归模型,但流式工作流也可以用于深度学习任务,如图像分类

8.3 结论

流式模型管道对于需要实时应用 ML 模型的系统非常有用。为了构建这些类型的管道,我们开发了两个消息代理,它们可以扩展到大量事件,并为这些管道提供数据源和数据接收器。由于延迟要求,流管道通常会限制您可以执行的操作类型。例如,构建对用户数据执行特征生成的流管道将是一项挑战,因为需要检索历史数据并将其与流数据相结合,同时保持低延迟。有一些模式可以实现这种类型的结果,例如为用户预先计算聚合并将数据存储在应用程序数据库中,但是与批处理模式相比,让这种类型的管道在流模式下工作可能需要更多的工作。

我们首先探索了 Kafka 作为一个流消息平台,并使用 structure streaming 和 PySpark 构建了一个实时管道。接下来,我们构建了一个数据流管道,重用了上一章中的组件,这些组件现在与 PubSub 流服务接口。Kafka 通常会在这两个消息代理之间的延迟方面提供最佳性能,但是与使用托管解决方案相比,维护这种类型的基础设施需要更多的资源。对于刚入门的小团队,PubSub 或 Kinesis 提供了很好的扩展选项来满足需求,同时减少了 DevOps 支持。

本·韦伯是 Zynga 的一名杰出的数据科学家。我们正在招聘

破产预测的简化模型调整

原文:https://towardsdatascience.com/streamline-model-tuning-on-bankruptcy-predictions-aabbc2fe62c0?source=collection_archive---------21-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

大家好,今天的主题是关于使用 sklearn、xgboost 和 h2o 软件包简化机器学习模型。特别是,我们将检查预测破产的波兰公司使用他们的财务报表。在我早期的机器学习建模中,我总是想知道是否有更简单的方法来调整模型。从这个问题开始,我偶然发现了自动化机器学习,我们可以通过 h2o 包访问它。这是我们要复习的内容的大纲:

  1. 为什么预测破产很重要
  2. 为建模设置数据
  3. 用逻辑回归和 xgboost 预测破产
  4. 用 h2o 预测破产
  5. 结论

这篇文章的数据来自这里:https://www.kaggle.com/c/companies-bankruptcy-forecast/data

为什么预测破产很重要

在信贷或借贷领域,破产相当重要。例如,银行贷款给企业获取利息,并期望在一定时间后得到回报。如果银行有业务没有偿还(如破产),那么银行本身将不会盈利,必须关闭。这个小例子也有助于解释为什么不同的企业在衰退期间会合并。一旦一家公司倒下,另一家公司通常会受到影响——引起连锁反应。

在更个人的层面上,人们可以应用破产预测来更好地保护他们的股票投资组合。例如,你知道你有高风险的股票,并想知道这些公司破产的可能性?不要再看了!你可以有自己的破产预测来卖出可能变坏的股票。对于那些愿意承担更多风险的人,你也可以开发一个短期策略模型。基本上,做空是指你押注一只股票的价格将会下跌,但这被视为比押注一只股票上涨风险更大。

为建模设置数据

像其他 Python 代码一样,我们需要首先加载包:

# Load up packages
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.linear_model import LogisticRegression
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, auc, roc_auc_score
import h2o
from h2o.automl import H2OAutoML

接下来,我们将加载名为变量 data 的数据:

# Load data
data = pd.read_csv('bankruptcy_Train.csv')

就我个人而言,我知道这个数据集非常干净,但我们将经历一些动作:

# Seeing how big the dataset is
data.shape

(10000, 65)

上面显示了 10,000 行 65 列。这里会看到一个表格:

# Glancing at what some of the values are
data.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了便于机器学习预测,一切看起来都包含在一个规范化的形式中,但是让我们检查任何空值:

# Checking for null values
data.isnull().values.any()

错误的

很好,不用担心 Nan 值。在这个数据集中,我们期望的破产输出被称为“类”我不喜欢它,所以我打算把它改名为“目标”,如下图所示:

data.rename(columns={'class':'target'}, inplace=True)

现在,我们可以为我们的模型拆分特性和输出:

# For features in h2o model
cont_names = data.columns[:-1]

#Setting up desired output and features for logistic regression and xgboost models
output = data[data.columns[-1]]
features = data[data.columns[:(data.shape[1]-1)]]

出于好奇,我们来看看数据集有多不平衡。

#Check the balance of outputs
output.value_counts()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

0 表示非破产公司,1 表示破产公司。这里没有那么多破产就不足为奇了。这导致了一些棘手的情况,比如如何预测逻辑回归的数据不平衡,但由于算法的工作方式,xgboost 对它没有太大影响。幸运的是,对于逻辑回归来说,该模型有一个参数来调整阶级不平衡,我们很快就会看到!

用逻辑回归和 xgboost 预测破产

在所有的数据建立之后,我们终于可以开始建立破产预测的模型了。在预测模型中,标准做法是将数据分成定型集和测试集。模型将从训练集中学习,我们将看到它如何从测试集中学习。

#splits data into X (features) and y (predictions)
X_train, X_test, y_train, y_test = train_test_split(features, output, test_size=0.2, random_state=42)
train = pd.concat([X_train, y_train], 1)
test = pd.concat([X_test, y_test], 1)

因为我们想要查看两个模型(logistic 和 xgboost),所以我设置了下面的代码来运行这两个模型,并进入相同的接收器操作特性(ROC)曲线。

plt.figure()# Add the models to the list that you want to view on the ROC plot
models = [
{
    'label': 'Logistic Regression',
    'model': LogisticRegression(class_weight='balanced'),
},
{
    'label': 'XGBoost Classifier',
    'model': XGBClassifier(max_depth=10, n_estimators=300),
}
]# Below for loop iterates through your models list
for m in models:
    model = m['model'] # select the model
    model.fit(X_train, y_train) # train the model
    y_pred=model.predict(X_test) # predict the test data
# Compute False postive rate, and True positive rate
    fpr, tpr, thresholds = roc_curve(y_test, model.predict_proba(X_test)[:,1])
# Calculate Area under the curve to display on the plot
    auc = roc_auc_score(y_test,model.predict(X_test))
# Now, plot the computed values
    plt.plot(fpr, tpr, label='%s ROC (area = %0.2f)' % (m['label'], auc))
# Custom settings for the plot 
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('1-Specificity (False Positive Rate)')
plt.ylabel('Sensitivity (True Positive Rate)')
plt.title('Logistic Regression v. XGBoost ROC')
plt.legend(loc="lower right")
plt.show()

对于 ROC 曲线,数值越高,模型越好。把 ROC 曲线想象成一种更好的衡量分类问题准确性的形式。它将真阳性(实际预测为目标变量)和假阳性(预测但不是实际目标变量)比率绘制到一个模型性能统计数据中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在我们的例子中,在给定的设置下,逻辑回归比 xgboost 更好。但是鉴于 xgboost 像几乎所有 Kaggle 比赛一样获胜的历史,我们知道 xgboost 可以做得更好。对于模型调整来说,这也是一种更简单的方法。

用 h2o 预测破产

这就是 h2o 的乐趣所在——为我们的机器学习模型增加自动化!

# starting up h20
h2o.init()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

您将看到类似上面列表的内容,只是时间更长。这只是意味着你的 h2o 的东西工作。有些人可能需要安装 Java,但是 h2o 会告诉你。现在我们可以开始训练了(在训练一小时的时候喝杯茶):

# Training phase set up
data = h2o.H2OFrame(train)

# Setting up features and output for h2o models
data['target'] = data['target'].asfactor()
y = "target"
cont_names = cont_names.tolist()
x = cont_names

# Setting up max time of model training
aml = H2OAutoML(max_runtime_secs= 3600, max_models=60, sort_metric='AUC')
aml.train(x = x, y = y, training_frame = data)

# Displaying best models built
lb = aml.leaderboard
lb.head(rows=lb.nrows)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上表向我们展示了 h2o 为我们打造的前 5 款产品。前 4 名显示了所有的梯度增强模型(xgboost 属于该类型的模型),第五名是堆叠集成模型。堆叠集成基本上是一堆用来一起预测的机器学习模型。相比之下,我们的 GBM 模型只是一种单一类型的机器学习模型。

不管怎样,让我们用我们最好的 GBM 模型做一些预测,看看 ROC 分数。

# Creating Predictions of best model
hf = h2o.H2OFrame(test)
preds = aml.predict(hf)
preds = preds.as_data_frame()
preds['p_p0'] = np.exp(preds['p0'])
preds['p_p1'] = np.exp(preds['p1'])
preds['sm'] = preds['p_p1'] / (preds['p_p0'] + preds['p_p1'])

# ROC score of best model
roc_auc_score(y_test, preds['sm'])

0.887

好吧,ROC 得分 0.89 击败了我们上面的逻辑模型 0.78——耶!对于那些对 h2o 模型的设置感兴趣的人,我们可以这样看它:

# Settings of best model
aml.leader.summary()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最酷的是,如果你的工作不允许 h2o 包,但允许底层模型,那么你可以复制设置!另一件要注意的事情是,你可以保存你的模型,以后再加载它,以节省训练时间。

# Saving model for future use
h2o.save_model(aml.leader, path = "/model_bankrupt", force=True)

’ c:\ \ model _ 破产\ \ GBM _ grid _ 1 _ AutoML _ 2019 09 11 _ 090503 _ model _ 23 ’

# Loading model to avoid training time again
saved_model = h2o.load_model('C:\\model_bankrupt\\GBM_grid_1_AutoML_20190911_090503_model_23')

一旦加载了模型,您就可以使用它进行预测,如下面的代码所示:

# Examlple on how to predict with loaded model
saved_model.predict(hf)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们回顾一下如何读取上面的输出。到达行是来自测试集的预测。第一列“预测”显示模型预测的内容。在我们的例子中,0 表示没有破产。p0 是模型认为预测应该为 0 的概率,而 p1 是模型认为第一行应该破产的概率。所以,我们的 GBM 模型认为第一家测试公司 99%不会破产。很酷,对吧?

最后,不要忘记关闭你的 h2o 会话:

# Closing an h2o session after use
h2o.shutdown()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

太棒了,我们在这篇文章中做了很多事情!首先,我们讨论了破产的重要性,以及如何将这个模型应用到我们自己的个人投资组合中。接下来,我们从 Kaggle 加载了破产的波兰公司的数据集。第三,我们应用了逻辑回归和 xgboost 来获得一些模型表现的基线。最后,我们通过引导 h2o 的流线型力量,自动化了一个更好的预测模型!

希望你喜欢这个小教程,下次再见!

免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。投资带有严重的风险,在采取任何投资行动之前,请咨询您的投资顾问。

Streamlit 101:深入介绍

原文:https://towardsdatascience.com/streamlit-101-an-in-depth-introduction-fc8aad9492f2?source=collection_archive---------3-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Streamlit app with code

使用 Airbnb 纽约数据深入了解 Streamlit

Streamlit 是一个令人敬畏的新工具,它允许工程师围绕他们的数据、机器学习模型和几乎任何东西快速构建高度交互式的网络应用。

Streamlit 最大的优点是它不需要任何 web 开发知识。如果你懂 Python,你就可以开始了!

这是本教程的完整代码,如果你想继续学习本教程的话。

为什么细流是超级酷的

一句话:它给了你一个惊人的快速、迭代和交互式的开发循环。

分割你的屏幕,使你的代码编辑工具在一半,你的浏览器在另一半,编辑你的代码,并看到你的应用程序即时更新!关于 Streamlit,我最喜欢的部分是它如何在几个小时内让您从 Jupyter 笔记本变成一个值得向客户展示的时尚 web 应用程序。

设置它

安装步骤:

$ pip install streamlit
$ streamlit hello

进口:

import pandas as pd
import streamlit as st
import plotly.express as px

要运行您的 Streamlit 应用程序:

$ streamlit run app.py

获取 Airbnb 纽约房源数据

Airbnb 没有正式发布任何数据。Airbnb 内部的另一个名为的小组定期发布 Airbnb 房源并审核数据。

**@st.cache**
defget_data():
    url = "http://data.insideairbnb.com/united-states/ny/new-york-city/2019-09-12/visualisations/listings.csv"
    return pd.read_csv(url)df = get_data()

数据缓存

st.cache decorator 表示 Streamlit 将执行内部魔术,这样数据将只下载一次并缓存以备将来使用。

在幕后,Streamlit 跟踪函数名、函数体中的代码以及我们在函数调用中传递的输入参数。在第一次调用时,它将函数的返回值存储在本地缓存中。在随后使用完全相同的参数调用该函数时,Streamlit 从本地缓存返回结果。

Streamlit 数据缓存的主要限制是它不能跟踪函数体外部发生的数据更改。

以标题(和引用)开始

**st.title**("Streamlit 101: An in-depth introduction")
**st.markdown**("Welcome to this in-depth introduction to [...].")**st.header**("Customary quote")
**st.markdown**("> I just love to go home, no matter where I am [...]")

上面的代码呈现了以下内容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Title, section header, and Markdown content rendered by Streamlit

st.title 适合主标题。对于章节标题,使用第一标题第二标题

st.markdown 呈现使用 Github 风格的 Markdown 编写的任何字符串。它也支持 HTML,但 Streamlit 建议不要允许,因为存在潜在的用户安全问题。

数据一览

这是我们开始探索性分析时通常做的第一件事。 st.dataframe 渲染熊猫数据帧。

**st.dataframe**(df.head())

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Pandas dataframe rendered using streamlit.dataframe

我喜欢它允许在点击任何列标题时对数据帧进行排序(注意 host_name 标题中的小 v 形符号)。

右上角有一个方便的小按钮,可以切换到全屏视图。非常适合查看较大的数据框,无需过多滚动。

它还支持样式的数据帧。

代码块

st.code 渲染单行和多行代码块。还有一个指定编程语言的选项。

st.code("""
@st.cache
def get_data():
    url = "http://data.insideairbnb.com/[...]"
    return pd.read_csv(url)
""", language="python")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Code rendered using streamlit.code

或者,使用一个with [st.echo](https://streamlit.io/docs/api.html#streamlit.echo)块执行其中的代码,并将其作为应用程序中的一个代码段。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Code rendered using streamlit.echo

纽约最贵的 Airbnb 房源

Airbnb 最贵的房产都在哪里?

在地图上

st.map 在地图上显示位置,无需编写一行样板代码来准备地图对象。唯一的要求是 dataframe 必须包含名为 lat / latitudelon/longitude的列。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Streamlit map with markers based on latitude and longitude

不出所料,曼哈顿岛是昂贵的航空公司最集中的地方。一些分散在布鲁克林。最贵的标价是 10000 美元。

st.deck_gl_chart 允许更多参数创建更有趣的定制地图。

选择列的子集

Streamlit 有一个 multiselect 小部件,允许从项目列表中选择或删除项目。这让我们可以为 dataframe 构建一个列选择器小部件。

cols = ["name", "host_name", "neighbourhood", "room_type", "price"]
st_ms = st.multiselect("Columns", df.columns.tolist(), default=cols)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Streamlit multi-select widget with auto-completion

multiselect 小部件是 Streamlit 中最强大、最方便的工具之一。除了列选择之外,还有一个用途是基于列的一个或多个值来过滤数据帧。另一种方法是根据不同模型的预测,为并排比较 ROC 曲线选择支线图。

按房间类型划分的平均价格

哪种房型平均最贵?

在静态表中

st.table 显示一个静态表。但是,您不能通过单击列标题对其进行排序。

**st.table**(df.groupby("room_type").price.mean().reset_index()\
.round(2).sort_values("price", ascending=False)\
.assign(avg_price=lambda x: x.pop("price").apply(lambda y: "%.2f" % y)))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Static table rendered by Streamlit

哪些主机列出的属性最多?

Sonder (NYC) 以 387 个房产列表位居榜首。Blueground 排名第二,有 240 个条目。下面是从使用[st.json](https://streamlit.io/docs/api.html#streamlit.json)呈现为 JSON 的两个清单中随机选择的清单。

Streamlit 呈现完全交互式的 JSON 部分,支持折叠/展开对象和数组,以及复制到剪贴板功能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

JSON section rendered by Streamlit

房产价格分布是怎样的?

我们使用 st.plotly_chart 将房地产价格直方图显示为 Plotly 图表。

边栏和价格范围滑块

我们使用 st.slider 来提供一个滑块,允许选择直方图的自定义范围。我们把它藏在一个侧边栏里。

values = **st.sidebar.slider**(“Price range”, float(df.price.min()), 1000., (50., 300.))
f = px.histogram(df.query(f”price.between{values}”), x=”price”, nbins=15, title=”Price distribution”)
f.update_xaxes(title=”Price”)
f.update_yaxes(title=”No. of listings”)
**st.plotly_chart**(f)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

In the sidebar

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

On the main page

最高的条形对应于 60-79 美元的价格范围,有 7229 个列表。

注意:在本教程中,我将滑块的最大值限制为 1000,这样范围选择就会清晰可见。

不同社区的可用性分布

availability_365表示酒店全年可用的天数。我们按邻居组检查availability_365的汇总统计数据。

使用 st.radio ,我们显示一个可供选择的邻居组列表。默认情况下,我们排除价格≥200 美元的物品,并使用 st.checkbox 提供一个包含昂贵物品复选框。

st.write 是一种伞状函数,接受字符串、数据帧、字典、绘图、地图等等(文档中的完整列表)。它允许传入多个参数,其行为取决于它们的类型。

**st.write**("Using a radio button restricts selection to only one option at a time.")
neighborhood = **st.radio**("Neighborhood", df.neighbourhood_group.unique())
show_exp = **st.checkbox**("Include expensive listings")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Radio group and checkbox rendered by Streamlit

169 天,布鲁克林的平均可用性最低。斯塔滕岛的平均可用性最高,为 226。如果我们包括昂贵的清单(价格> = 200 美元),这个数字分别是 171 和 230。

注意: 有 18431 条记录带有 *availability_365* 0(零),我已经忽略了。

按邻居组列出的平均可用性

st.pyplot 渲染使用 matplotlib 构建的地块,如下图所示。

df.query("availability_365>0")\
.groupby("neighbourhood_group")\
.availability_365.mean()\
.plot.bar(rot=0)\
.set(title="Average availability by neighborhood group",
xlabel="Neighborhood group", ylabel="Avg. availability (in no. of days)")
**st.pyplot**()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Created with pandas (matplotlib)

评论数量

我们希望查看评论数量在我们可以自定义的范围内的属性。

在侧栏中,我们使用 st.number_input 提供了一个数字范围选择器。如果minimum > maximum,我们使用 st.error 显示错误信息。

minimum = **st.sidebar.number_input**("Minimum", min_value=0)
maximum = **st.sidebar.number_input**("Maximum", min_value=0, value=5)
if minimum > maximum:
    **st.error**("Please enter a valid range")
else:
    df.query("@minimum<=number_of_reviews<=@maximum")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

486 是最高评论数。两个列表有这么多评论。两家都在东埃尔姆赫斯特街区,都是价格分别为 65 美元和 45 美元的私人房间。一般来说,超过 400 条评论的列表价格低于 100 美元。有几款在 100 美元到 200 美元之间,只有一款定价在 200 美元以上。

图像和下拉菜单

使用 st.image 显示猫、小狗、特征重要性图、标记视频帧等的图像。

现在来点好玩的。

pics = {
    "Cat": "https://cdn.pixabay.com/photo/2016/09/24/22/20/cat-1692702_960_720.jpg",
    "Puppy": "https://cdn.pixabay.com/photo/2019/03/15/19/19/puppy-4057786_960_720.jpg",
    "Sci-fi city": "https://storage.needpix.com/rsynced_images/science-fiction-2971848_1280.jpg"
}
pic = **st.selectbox**("Picture choices", list(pics.keys()), 0)
**st.image**(pics[pic], use_column_width=True, caption=pics[pic])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Cat image source: https://cdn.pixabay.com/photo/2016/09/24/22/20/cat-1692702_960_720.jpg

魔法

请注意,在上面的评论数量部分,我们将df.query("@minimum<=number_of_reviews<=@maximum")写在了它自己的一行上,而没有将其包装在对st.dataframe的调用中。这仍然呈现了一个数据帧,因为 Streamlit 在其自己的行上检测到一个变量或文字,并使用st.write来呈现它。

结论

我们已经讨论了交互式小部件、数据框、表格、图像、降价、绘图渲染、地图和文本内容。Streamlit 允许对现有元素和显示进度的进行修改,这在本教程中没有涉及。例如,您可以向现有表格中添加行,或者向图表中添加新数据。您还可以显示长时间运行的进程的进度条。

恭喜,您已经准备好开始构建自己的 Streamlit 应用程序。

派对时间!

当你运行为这个教程创建的应用时,点击 庆祝! 按钮由下面的代码呈现。

**st.markdown**("## Party time!")
**st.write**("Yay! You're done with this tutorial of Streamlit. Click below to celebrate.")
btn = **st.button**("Celebrate!")
if btn:
    **st.balloons**()

下一步是什么?

我的下一篇文章将是关于我在 Kaggle 上的沃尔玛购物旅行类型分类竞赛中获得银牌(排名 35 /前 4%)的解决方案。

参考和链接

Streamlit-部署机器学习模型,无需学习任何 web 框架。

原文:https://towardsdatascience.com/streamlit-deploy-a-machine-learning-model-without-learning-any-web-framework-e8fb86079c61?source=collection_archive---------13-----------------------

用一个演示项目来解释-

对于许多人来说,从事一个实际的数据科学项目,然后花更多的时间在 web 框架、后端和前端上工作是非常令人厌倦的。对于数据科学家或机器学习工程师来说,研究这些技术是次要任务。所以问题是,在没有学习 flask(一个非常著名的最小 python 框架)的情况下,如何部署 ML 模型呢?在这篇博客中,我将向您展示最有用的工具,即 Streamlit,它可以帮助您专注于数据科学家的工作。但是,它将负责您的模型的部署,您的模型可以作为工作的 web 应用程序发布。

让我们了解一下 streamlit 工具对于像你我这样的 ML/数据科学从业者部署我们的模型是如何有用的。我们将使用著名的 首都自行车共享数据集 ,并实现各种分类算法来确定用户的会员类型,无论他/她是会员、临时会员还是未知的。在开始之前,让我告诉你们,我是一个博客新手,因为我没有写太多的习惯,这也是我的第一个博客。所以,请原谅我可能犯的任何错误。我会尽可能简单地解释,所以在阅读这篇文章时请耐心等待。您应该了解基本的 python 编程语言,并且通过 scikit-learn 库了解一点实现 ML 算法的工作知识就足以理解这个项目。

要开始使用 Streamlit,您需要使用 pip 在您的系统上安装它。在您的终端/cmd 上键入" $ pip install streamlit" 。对于 Linux 和 Windows 用户,该命令是相同的。

让我们从导入几个和 streamlit 开始,如下所示:

Import Libraries

我们将训练决策树、神经网络和 KNN 分类器模型来预测用户的成员类型。看看我们数据集的一个实例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Capital Bike Share Dataset

现在,让我们从定义我们的 main() 函数开始,在这里我们将调用其他函数来对我们的数据集执行预处理并调用我们的 ML 模型。

Main function beginning

在上面的代码片段中, st.title() 是一个 streamlit 函数,它帮助显示我们项目的标题。它将在您的 web 应用程序上显示为标题,一旦您在本地系统上运行此 streamlit 代码,它将自动部署在本地主机上。要运行 Streamlit 代码,移动到您的代码所在的目录,并在您的终端或 cmd 上键入Streamlit run your _ file _ name . py,它将在 localhost:8501 上运行您的 web 应用程序。

现在,我们必须通过调用我们的用户定义函数 loadData() 来加载数据集。然后我们会进行预处理,通过调用**预处理()**函数(loadData()和预处理()函数的片段如下所示)将数据拆分成训练和测试数据。函数 st.checkbox() 也是一个 streamlit 函数,有助于在 web 应用程序上启用复选框小部件。因此,当用户单击复选框时,将调用 st.write() 函数,从而在我们的应用程序中弹出数据集的一个实例。

看看函数 loadData()预处理():

Loading and Preprocessing Dataset

streamlit 最有趣也是最有用的功能在上面的代码中有介绍,即 @st.cache 。它有助于缓存在相应函数中执行的每个任务。在这里,数据集被缓存,所以下次加载时不会有延迟。现在,我们已经将独立和从属特征分别指定为 X 和 y。我们考虑的独立特征是持续时间、起点站号和终点站号。依赖特性是数据集的成员类型列,但它需要编码,因为它由分类数据组成。这里,我使用了 scikit-learnlabel encoder(),但是您可以使用您选择的任何编码器。最后,我们将使用 scikit-learn 库的 train_test_split() 方法将数据分成训练和测试数据集。

现在我们已经准备好了训练和测试数据,让我们实现 ML 算法,并在我们的 web 应用程序上显示结果。

首先,我们将让用户使用 Streamlit 的 st.sidebar.selectbox() 方法从侧边栏的选择框中选择所需的 ML 模型,如下所示。

The function call to Decision Tree Classifier

由于这是一个带有动手项目的 streamlit 工具演示,解释 ML 算法超出了范围。所以,我希望你们有一些用 python 实现 ML 算法的知识。好吧!让我们回到上面显示的代码。如果用户选择我们的第一个模型,这是一个决策树分类器,那么 decisionTree() 函数(如下所示)将被调用,返回混淆矩阵和训练模型的准确性。再次使用 st.write() ,我们可以在我们的 web 应用程序上显示混淆矩阵和分数。

此外,如果用户想要将他的测试样本输入到模型中并得到预测,该怎么办呢?为此,我们可以在应用程序中使用复选框。如果用户点击复选框,则 accept_user_data() 函数(accept_user_data()函数代码如下所示)被调用,用户可以手动填充三个独立的特性。因此,模型将预测相同的成员类型。

accept_user_data() 函数的代码:

Code for accepting user data needed for performing prediction on user data

此外,我们可以通过调用构建 KNN 分类器和神经网络分类器的函数来重复同样的事情。请注意,我们刚刚讨论了对这些模型的函数调用,我们还没有看到实际模型被训练的那些函数定义。看看这些函数调用的代码片段:

The function call to Neural Network and KNN Classifier

其次,ML 算法将使用scikit-learn库来编写,这是 python 中一个众所周知且广泛使用的机器学习库。

决策树分类器编写如下:

Decision Tree Classifier Model

在 scikit-learn 中使用 MLPClassifier 也以有点类似的方式编写了神经网络。这里,我们必须在训练模型之前缩放数据,因为这样,它会给出更准确的结果。请注意,我们已经使用 streamlit 缓存了模型,如上所述。这将有助于立即加载模型,从而减少执行中的延迟。

参见下面的神经网络实现:

Neural Network Classifier Model

类似地, KNN 分类器模型是使用 scikit-learn 库中的 KNeighborsClassifier 编写的:

KNN Classifier Model

就数据科学和机器学习领域而言,我们都知道数据可视化的重要性。

最后,让我们探索如何使用 Streamlit 在我们的 web 应用程序上展示漂亮的交互式可视化效果。

出于演示目的,我们将基于这些数据开发两个可视化工具。第一个是来自数据集的车辆的几个开始位置的可视化。Streamlit 无法在地图上直接显示地理空间点的散点图;但是,它需要数据集中的纬度和经度列。因此,我个人更喜欢使用 地理库 来解码数据集的起始位置列中存在的 1000 个地址的纬度和经度。如果你有兴趣知道我是如何解码的,那么请访问我的 GitHub 库 。否则,您可以从我的 GitHub 存储库中为这个项目下载带有和不带有坐标的数据集。

此外, st.map() 函数会根据纬度和经度自动绘制世界地图以及数据点。请参见下面的示例:

Plotting Scatter Plot on the World Map

对于最后一个可视化,我们将绘制直方图来确定特定特征中每个元素的计数。例如,根据我们的数据集,有三种类型的成员。所以,我们将使用 plotly 库 绘制一个直方图来查看每种类型的大概计数。让我们使用三个特征的直方图来可视化计数,即起点桩号、终点桩号和构件类型。此外,让用户使用 streamlit 选择框功能选择要查看的可视化。

参见下面的代码:

Plotly Histogram using Streamlit

下面是一些使用 streamlit web 应用程序获得的惊人结果的快照:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ML Model Running

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Prediction on User Input

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Streamlit Map Plot

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Plotly Histogram Plot

那可是相当可观的教程,我知道!但是,最令人兴奋的事实是,您已经学会了如何部署机器学习 web 应用程序,而无需学习 Flask 或 Django。此外,streamlit 非常容易使用,因为在这个项目中,我们刚刚进行了 33 次 streamlit 调用,其中很多都是相同类型的函数调用。我希望你喜欢这篇文章,并发现它很有帮助。如果是的话,请与你的朋友和同事分享。

注意:不要复制并运行代码片段,因为这可能会导致缩进错误。因此,为了节省您的时间,我将我的 GitHub 链接添加到这段代码— 点击这里

你可以用 Streamlit 做很多很酷的事情。所以,查阅一下Streamlit的官方文档。

Airbnb 新加坡的严格法律——分析

原文:https://towardsdatascience.com/strict-laws-in-airbnb-singapore-an-analysis-92ad7cf9a8cc?source=collection_archive---------23-----------------------

将挑战短期住宿法则的房源比例可视化

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Swapnil Bapat on Unsplash

新加坡短期居留法

除了缺乏值得探索的自然景点和是最昂贵的居住地之一外,新加坡无疑是东南亚短期旅行的最佳城市之一,拥有最高效的公共交通系统,实惠的餐饮和干净的环境。

住在 Airbnb 酒店一直是许多旅行者的首选,他们希望在预算有限的情况下探索一些地方,获得一种宾至如归的体验。然而,新加坡颁布了一项针对房东的法律,如果客人在私人房产中停留不到 3 个月,将被处以高达 20 万美元的罚款。更严厉的法律适用于 HDB(住房发展委员会)房产的业主,这是一种设施有限、更实惠的房产。你可以通过下面的链接了解更多。

[## Airbnb 在新加坡违法吗?SingaporeLegalAdvice.com

希望通过出租房屋获得额外收入?在房屋共享网站 Airbnb 上挂牌越来越…

singaporelegaladvice.com](https://singaporelegaladvice.com/law-articles/is-airbnb-illegal-singapore) [## 两名新加坡房东因非法合租房屋被罚款:Airbnb 在不同城市的法律

新加坡——4 月 3 日,两名 Airbnb 房东因提供未经授权的短期…

www.straitstimes.com](https://www.straitstimes.com/singapore/two-hosts-charged-over-illegal-home-sharing-airbnb-laws-in-various-cities)

在你犹豫要不要在新加坡预订 Airbnb 之前,先别着急!客人在新加坡的 Airbnb 停留任何时间都不违法。但由于害怕被罚款,一些客人被公寓保安赶走了。你可以在下面了解更多。

[## NZ family 的 Airbnb 困境凸显了房源的不透明性

一个新西兰的四口之家出现在加勒比海的吉宝湾,期望拿起公寓的钥匙…

www.straitstimes.com](https://www.straitstimes.com/singapore/housing/nz-familys-airbnb-woes-highlight-lack-of-clarity-on-listings)

好了,法律已经够了。我们在这里探索新加坡“高风险”房源的分布。在这个项目中,我将在 Airbnb 中使用来自 的最新 Airbnb 数据集。

数据预处理

在我们深入研究数据集中的要素之前,我想专门针对新加坡禁止短期停留的严格法律创建一个新要素。这将是一个分类特征,取值为“高风险”、“中等风险”或“低风险”。由于私有财产和 HDB 财产分类等可用特征的限制,分类特征定义如下:

  • 高风险:最低夜数< 90 天,评论数< 90%
  • 中等风险:最低夜数< 90 天,审查数量≥90%
  • 低风险:最低夜数≥ 90 天

除了增加一个新功能,我还使用标准的 1.5x +/- IQR 和超过 365 天的最小住宿时间删除了异常价格。此分析不需要的列也被删除。

df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

探索性数据分析

价格分布

价格的分布与上市的风险几乎没有任何关联。然而,找出上市物业的预期价格范围仍然很有趣,这样我们就可以知道我们在新加坡的平均 Airbnb 住宿的预期价格。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上市价格的这种分布似乎是右偏的。如果我们更仔细地观察其按地区的分布,我们随后会发现至少有一个地区不符合总体平均价格。这可以很容易地用一个简单的非参数多重独立样本检验来证实:克鲁斯卡尔-沃利斯检验。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

像任何其他大都市一样,在中心地区看到更高的价格分布并不奇怪,因为大多数游客会在购物区/酒吧/景点/夜生活丰富的中心地区附近闲逛。与任何其他地区相比,中部地区的私有财产比例也要高得多。

列表的地理位置分布

很难通过地理位置来可视化风险列表,因为它们往往会相互重叠。下面的填充地图对于查找新加坡风险列表的分布几乎没有任何作用:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A Tableau-generated distribution of listings by risk rating

但一旦按地区划分,很明显,大部分房源都集中在中部地区:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Credits: Baval

使用 python 中漂亮的叶库,我们可以大致观察各个地区的房源数量:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

folium 包允许每个列表的地理位置的交互式可视化。从这里可以很明显地看出大部分房源来自哪里,但是这些房源中有多少是符合法律的呢?

符合法律的列表

在本节中,我们将查看符合法律的列表的分布情况:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我使用评论数量作为感兴趣的特征,因为让许多不同的客人住在最低夜数较低的酒店是有意义的,这最终会导致更多的评论。从这个散点图中,我们可以清楚地看到分布在 90°/180°/365°夜标的图的区别。由于我们无法区分哪些房源是 HDB 的,哪些是私人房产,所以我假设入住至少 90 晚的房源是符合法律的。乍一看,似乎大多数上市公司都不遵守短期居留的规定。此外,某些情节似乎没有意义。以 90 晚最低 285 条评论为例。这怎么可能呢?经过进一步调查,似乎上市在 2017 年法律生效之前就已经存在,这导致了高审查数。此外,该列表只出租可能获得更高评论数的私人房间,因为它将容纳更多的独特客人。

无论如何,让我们通过一个甜甜圈图来看看上市的比例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我第一次观察到这一点时,我很惊讶有这么多的主人如此大胆地列出他们违反法律的财产。不过话说回来,由于 Airbnb 在预订得到确认之前不会给出房源的确切地址,这给当局抓住这些房东带来了挑战,尤其是在新加坡的大多数房产都是多层的情况下。在我的分析的最后我会更多地谈到这一点。但是现在,让我们看看风险上市的比例。

高风险上市

知道了大部分房源都集中在中部地区,让我们来看看各地区风险房源的分布情况:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

再说一次,这一点也不奇怪。许多海外客人只是喜欢住在当地景点的附近,而这些景点恰好聚集在中心区域,但是不同类型房间的分布情况如何呢?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,我们能够看到符合法律的列表与不符合法律的列表之间的差异。与整个公寓相比,低风险房源的私人房间出租比例更高。我们可以在下面的链接中看到新加坡各个地区的房间/公寓的平均租金。

[## 2019 年新加坡租金-租房或租房的成本指南

乔安妮·波这么说,你是被这个岛国的高薪承诺和机会吸引,要搬到新加坡去了…

blog.moneysmart.sg](https://blog.moneysmart.sg/property/rent-singapore-cost-guide/)

新加坡非常高的房租使得租房子而不是整间公寓成为更明智的选择。这恰好是使新加坡成为生活成本最高的国家之一的驱动力之一。Airbnb 产生的额外费用让这种选择变得更加明显。大多数公寓租赁是通过适当的房地产代理或双方之间的私人协议来降低费用。

如果你想知道哪个街区的房源数量最多,我整理了以下 5 个街区的房源数量:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

拿走

虽然还不清楚是否决定实施严格的短期居留法,但大多数私房业主似乎支持《3 个月住宿法》的决定:

2018 年下半年,URA 委托对一千多名私人房主进行的全国调查发现,大多数新加坡人支持拟议的 STA 监管框架。— CNA

[## 私人住宅物业的最短逗留时间不变:URA

市区重建局(市建局)周三(5 月 8 日)宣布,将维持现行的规例。

www.channelnewsasia.com](https://www.channelnewsasia.com/news/singapore/no-change-to-3-month-minimum-stay-duration-for-private-11513474)

URA 维持现状的决定是一个信号,表明它认识到这个问题的复杂性,需要更多时间来研究。— CNA

作为一名私人房产的居民,以及在法律生效前将我的备用房间转租给客人的人,我能够看到硬币的两面(支持和不支持)。

**不支持:**与 HDB 的业主相比,私人业主为现场设施支付额外费用,如游泳池/网球场/健身房/私人停车场等…这些设施有可能被游客滥用,这是非常不雅观的,特别是因为私人财产设施的维护不如公共设施那样详细。

**支持:**随着现代旅行的出现,Airbnb 一直是提供平价住宿的最佳平台之一,每支付一美元就能获得更多空间(例如,以酒店房间的价格购买整个公寓)。作为一个意识到自己消费习惯的千禧一代旅行者,每当我出国旅行时,我都会选择 Airbnb,因为它的价格和便利性。因此,我认为这一举措是针对那些更愿意将旅行预算花在体验上而不是住宿质量上的客人的一种手段。

看着明显不符合短期住宿法的房源比例,我真的很怀疑这项法律的严格性。也许只要客人不会造成任何干扰,就不值得去追捕房主?也许吧。

法律漏洞

列出最短住宿时间少于 90 天的房产并不一定意味着房主将房产出租给客人是违法的。

正如我提到的,当客人通过 Airbnb 预订时,将收取费用,作为房主和客人的一种保险和责任形式。房主可能会选择租赁一个月来“评估”他们的客人,然后再延长到 3 个月。

这正是我在加拿大呆了 4 个月进行冬季交流时所经历的程序。房主所要做的就是在他们的 Airbnb 列表中屏蔽剩余的 3 个月,基于信任,我们用现金支付租金。我们设法把整个公寓的租金每月减少了 100-200 美元。

如果你正在阅读这篇文章,请对来自蒙特利尔的卡尔大声喊出来!这是一个非常愉快和难忘的冬天!

其他漏洞

房主通知他们的客人让保安知道他们是要来拜访的朋友是很常见的。在新加坡,朋友在别人家过夜并不违法。

这高度依赖于不同公寓的保安。有些人会让你摆脱困境,但有些人会用他们的方式把你赶走,就像可怜的新西兰家庭所发生的那样。

你应该注意什么?

如果你仍在阅读,并愿意不顾风险在新加坡预订 Airbnb,请继续阅读。但是请理解,我只是说如果我预订的话,我会怎么做,这并不能保证你不会被驱逐,尽管风险会降低。

  • 检查评论和最近评论的数量。如果上一次好评是在你访问网站的几天后,这意味着之前的客人没有被驱逐出酒店。
  • 尽量避免在公寓里挂牌,这些地方有保安,他们负责把你赶出去。如果你必须呆在一个房间里,给你的主人发信息,让他/她去警卫室接你。这会让警卫相信你们是熟人。也不要和庞大的群体一起旅行,这只会引起怀疑。
  • 无论如何,一定要告诉你的主人,你知道新加坡的短期住宿法律,并为你即将到来的逗留寻求指导。

现在你知道了新加坡的短期住宿法,你会冒险住在 Airbnb 吗?

我知道我会的。

如果你热衷于复制我的作品供自己使用,这里有我的 Github 库的链接:

[## bobby muls/新加坡-Airbnb

在这个库中只有 3 个感兴趣的文件,这包含新加坡 Airbnb 的数据,这包含…

github.com](https://github.com/bobbymuls/Singapore-Airbnb)

尽情享受吧!

在探索和开发之间取得平衡

原文:https://towardsdatascience.com/striking-a-balance-between-exploring-and-exploiting-5475d9c1e66e?source=collection_archive---------24-----------------------

强化学习中探索与利用的困境

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们的代理在学习玩井字游戏[ Medium article ]时面临的探索-开发困境。这种困境是强化学习以及现实生活中的一个基本问题,当我们在选项之间做出选择时,你会选择:

  • 挑选你熟悉的东西,以最大化获得你想要的东西的机会
  • 或者选择一些你没有尝试过的东西,可能会学到更多,这可能会(也可能不会)让你在未来做出更好的决定

这种权衡将会影响你是尽快获得奖励,还是先了解环境再获得奖励。

直觉

假设你搬到了一个新城镇,你正在考虑从你的办公室到你的新家该走哪条路。你快速搜索了一下,发现有几种方法:

  1. 坐地铁 A 线,跟着 B 线
  2. 乘地铁 A 线,然后乘 123 路公共汽车
  3. 步行到地铁 C 线,然后是 B 线

最初,您不知道哪种方式是最好的,但是您信任技术,所以选择了选项 1,因为它的持续时间最短。你设法在第一天到家,所以你决定选择 1 作为你的回家路线。你继续利用你所知道的有用的东西,并通过选项 1 旅行。

也许有一天,你决定去探索,认为从办公室回家可能有更好的方式,所以你决定尝试选项 2。结果可能是你设法在更短的时间内回到家,或者花了你更多的时间(也许还会花更多的钱)。在尝试了选项 2 之后,确实比选项 1 花了更长的时间。可能是因为在高峰时段,交通对 123 路公交车不好。所以你决定选择 2 不好。但这是否意味着你再也不会尝试第二种选择了呢?在非高峰时间,这可能是一个更好的选择。

如果选项 3 实际上是回家的最佳方式,但决定不再探索而坚持选项 1,该怎么办?那么你将永远不会意识到选项 3 比选项 1 更好。

取得平衡

学习做出这些选择是强化学习的一部分。这意味着有时你不得不故意决定不选择你认为最有回报的行动,以便获得新的信息,但有时在探索的过程中最终会做出一些糟糕的决定。但与此同时,你想通过利用你知道最有效的方法来最大化你的回报。

那么,我们如何在充分探索未知和利用最佳行动之间取得平衡呢?

  • 充分的初步探索,以便确定最佳方案
  • 利用最佳选择以最大化总回报
  • 继续留出一个小概率来试验次优和未开发的选项,以防它们在未来提供更好的回报
  • 如果这些实验选项表现良好,算法必须更新并开始选择这个选项

ε贪婪

在强化学习中,我们可以决定要做多少探索。这是ε贪婪参数,范围从 0 到 1,它是探测的概率,通常在 5%到 10%之间。如果我们设置 0.1ε-greedy,该算法将在 10%的时间里探索随机选项,在 90%的时间里利用最佳选项。

评估不同的ε贪婪

我已经创建了一个井字游戏,代理可以通过相互对抗来学习游戏。首先,让我向你介绍我们的代理人,他们是代理人 X 和代理人 o。代理人 X 总是先走,实际上比代理人 o 更有优势赢得更多的机会。

为了找出最适合这个游戏中每个代理的ε贪婪值,我将测试不同的ε贪婪值。首先,用ε贪婪值 0.01 初始化代理 X,意味着有 1%的概率代理 X 会选择探索而不是利用。然后,特工们互相对战 10000 场,我记录下 X 特工获胜的次数。在 10,000 场游戏之后,我将ε-greedy 值增加到 0.02,代理将再玩 10,000 场游戏。

代理 X (eps 增量)vs 代理 O (eps 0.05),结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Number of games (out of 10,000) won by agent X on different epsilon-greedy value

蓝线是代理 X 赢代理 o 的次数。胜率随着ε-贪婪值的增加而降低,并在ε-贪婪值为 0.05 时达到赢得 9268 场游戏的峰值(代理 X 探索 5%的时间)。特工 O 开始赢得更多的游戏,因为特工 X 有超过 50%的时间在探索。

让我们尝试一下,代理 O 用最优的 5%ε贪婪挑战代理 X,让我们看看代理 O 在不同ε贪婪值下的表现。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Number of games won by agent O on different epsilon-greedy value

给定代理 X 具有最优ε贪婪并且在游戏中首先开始的优势,代理 O 在它能够学习游戏之前输掉了大部分游戏。

让我们把代理人 X 的 epsilon greedy 调整到 100%,代理人 X 将一直玩随机动作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Number of games won by agent O on different epsilon-greedy value, where agent X play randomly

代理人 O 能够学习这个游戏并战胜代理人 X,在 4% epsilon greedy 时达到顶峰,在 30%时开始失败。

最后

探索在线演示并在井字游戏中挑战我们的代理。

只想以这张图结束。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 [## 数据科学家:21 世纪最肮脏的工作

40%的吸尘器,40%的看门人,20%的算命师。

towardsdatascience.com](/data-scientist-the-dirtiest-job-of-the-21st-century-7f0c8215e845)

嗨!,我是叮当。我喜欢构建机器学习项目/产品,我在向数据科学写关于它们的文章。在媒体上关注我或者在 LinkedIn 上联系我。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基于分布式云计算的大数据字符串相似性匹配

原文:https://towardsdatascience.com/string-similarity-matching-for-big-data-using-distributed-cloud-computations-ea7cfc918b9f?source=collection_archive---------18-----------------------

将 BigQuery、Python 的 Scikit-Learn & Dask(分布式)和 Kubernetes 组合在一个项目中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by daveynin on flickr

e̶x̶i̶s̶t̶e̶n̶t̶i̶a̶l̶问题设置

像大多数故事一样,我们的故事始于一项雄心勃勃的事业!我们得到了两个大型数据集(来自 BigQuery 中的两个表)。一个包括来自 Google Play 和 iOS 应用商店的所有应用名称——大约 1400 万个条目——我们称之为“干净的”应用名称。另一个包含大约 5K 个“脏”应用程序名称。肮脏是指遗漏的单词、某些单词的拼写错误、涉及操作系统或其他信息的附加单词等。可以通过查看“将所有东西放在一起并运行它”一节来找到例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Choose wisely — Photo by W.carter on Wikimedia Commons

除了数据集,我们还为提供了蓝色和红色药丸。我们认为自己足够勇敢,决定服用红色药丸,接受挑战,寻求残酷的真相。

请求是将“脏”数据集中的条目与“干净”数据集中的条目进行匹配,然后将结果存储为查找表。

旅程——测试和失败

在成为男人和面对 t̶h̶e̶ ̶r̶e̶a̶l̶ ̶w̶o̶r̶l̶d̶制作之前,一个男孩需要在操场上发展他的技能。一个奇特的例子是谷歌合作实验室,这是一个托管在云上的 Jupyter 笔记本电脑,提供免费的强大计算资源(包括 GPU/TPU),这是第一次测试运行的地方。

计算机科学家会把我们的问题归类为近似字符串匹配问题。这些问题的传统解决方案使用不同的字符串度量来得出两个给定字符序列之间的距离。例如Jaro-Winkler 距离Levenshtein 距离

我们的第一个尝试是使用 fuzzy wuzzy ,一个实现 Levenshtein 距离的 Python 库。(请保留下面的粗略数字,而不是适当的基准。最终的差异如此显著,以至于完美的精度并不重要。)Fuzzy wuzzy 需要大约 15 分钟来计算来自“脏”数据集的单个条目和来自“干净”数据集的所有条目之间的距离。重复这个过程 5K 次相当于大约 52 天,这比我们希望的每天至少运行一次的过程稍微多了*。如果时间就是金钱,我们早就破产了!*

最终(目前)算法

为了避免严重的贷款和破产,采用了一种略有不同的方法:通过数字的力量提高业绩。基于TF–IDF将字符串数据集转换成向量,以便使用余弦相似度。该算法的核心之前已经用于类似的问题这里,这里这里和这里这里。为了进一步提高性能,本文引入了一些修改,以支持在云 Dask 客户端上运行分布式计算。

为什么是达斯克?Dask 是什么?

Dask 是一个库,它提供了在本地扩展 Pandas、Scikit-Learn 和 Numpy 工作流的方法,只需最少的重写。因此,普通的 Python 操作可以在不同的节点/CPU 内核之间分布/并行化。它也可以(但不是必须)在分布式集群上运行。也就是说,Dask 只不过是提供基础设施来将数据(如 Pandas 数据帧)分割成不同的节点,然后使用多个内核执行操作,并确保分割数据之间的通信。

设置事物

注:下面的 干净 命名约定分别用于基线和待匹配数据集。

下面是这个项目使用的基本库的列表:

从 BigQuery 导入数据

为了从 BigQuery 获取数据,我们使用了 Python 的 BigQuery 客户端库。客户端将数据加载到 Pandas 数据帧中,该数据帧立即转换为 Dask 数据帧。Dask 数据帧只不过是分布在许多分区( npartitions )上的 Pandas 数据帧的组合,具体取决于 CPU 架构。

转换为向量

使用 tf-idf 将数据帧从字符串转换为向量实际上需要 3 行代码:

使用 Scikit-Learn 中的TfidfVectorizer函数并通过定义分析器函数来初始化矢量化函数(参见下面的信息)。干净的数据帧用于定义特征向量(基于分析器),同时计算干净的 tf-idf 矩阵(fit_transform),然后计算脏的 tf-idf 矩阵(transform)。

分析器是用于将每个应用程序名称(字符串)分割成较小部分的功能。从干净数据帧的所有条目中收集所有这些较小的比特定义了特征向量。如果一个特定的应用程序名称包含这一位,那么当转换为向量时,它将在相应的位置获得一个浮点值——如果不是 0。浮点值取决于该位在应用程序名称中出现的次数,并且该值被修改,使得该应用程序名称的向量被归一化(向量范数等于 1 个单位)。举个例子:如果分析仪定义如下

干净的数据帧简单如下,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么特征向量具有这样的形式:

***['ACE',
 'AGR',
 'BOO',
 'CEB',
 'EBO',
 'FAC',
 'GRA',
 'INS',
 'NST',
 'OOK',
 'RAM',
 'STA',
 'TAG']***

干净的数据帧被转换成下面的向量矩阵(输出矩阵以稀疏矩阵(CSR)格式给出,但在这里显示为数组)

***[[0.40824829 0\.         0.40824829 0.40824829 0.40824829 0.40824829
  0\.         0\.         0\.         0.40824829 0\.         0.
  0\.        ]
 [0\.         0.37796447 0\.         0\.         0\.         0.
  0.37796447 0.37796447 0.37796447 0\.         0.37796447 0.37796447
  0.37796447]]***

余弦相似性

一旦干净和脏数据集处于向量模式,我们就可以继续获得余弦相似性得分矩阵。在干净和脏的矢量化矩阵之间执行点积足以给出余弦值,因为向量是归一化的。即,点积与余弦(相似性)一致。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为此,使用了以下代码:

这里使用了 sparse_dot_topn 包,它提供了一种快速的方法来执行稀疏矩阵乘法,然后使用 Cython 进行 top-n 乘法结果选择。余弦相似性将以稀疏矩阵形式给出,其中行对应于脏数据集,列对应于干净数据集。

使用这个相似性矩阵,我们可以提取在 干净 之间匹配的条目以及它们的相似性分数,使用:

上传到 BigQuery

最后但同样重要的是,我们需要将匹配过程的结果作为查找表上传回 BiqQuery。这样做的代码如下所示:

比起算法的千言万语,你会更喜欢一张图片吗?这是它的简图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

部署(在 Kubernetes)

节由 盖亚尔 撰写

Dask 是一个如此通用的工具,甚至通过使用其内置的 Pandas API 支持在本地运行它也能让您受益。然而,当它在分布式系统上运行时——也就是集群——显示了它的全部能力。通过与 DevOps 工程师的合作,我们可以访问部署在谷歌云平台(GCP)上的托管 Kubernetes (k8s)集群。在大多数情况下,在获得对集群的访问权后,可以使用 helm package manager 通过运行以下命令在 k8s 上轻松部署 Dask:

***helm install —name my-dask stable/dask***

过一会儿,你会部署 5 个吊舱:

  • 调度程序—主 Dask 任务管理器
  • 3 名工作人员—处理数据和应用操作
  • Jupyter 舱——一个预先设置的 Jupiter 实验室舱,是与 Dask 互动的好方法

为了获得部署后的 pod 列表,我们创建了一个简单的 shell 脚本。运行它,它将显示所有新创建的 pod 的 IP 地址列表:

如果你不再需要它,或者你弄坏了什么东西,想要一个新的开始,你可以跑:

***helm delete dask —purge***

是不是看起来太容易不真实了?你说得对;通用的解决方案很少奏效。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Made with imgflip.com

这里有一点定制,使它为我们的需要工作。

在最初的测试之后,我们已经发现了几个在使用 Dask helm 时的问题*。***

  1. 它有几个 bug。幸运的是,所有的修复都在官方回购中作为未决的拉请求(PRs) 存在,但是没有被合并。
  2. 我们需要的一些软件包缺少默认图像。
  3. 一个包在 pip 中没有二进制版本,并且在pip install ...部分失败。
  4. 默认的 pod 配置不足以处理我们的大型数据帧。

继续讨论解决方案*😗**

1。头盔配置中的错误
幸运的是,这些错误已经通过待定的 PRs 在官方回购中修复了。要应用它们,我们必须制作一个 repo 的本地克隆,并将所有 PRs 与解决方案合并为补丁。这当然不是理想的解决方案,但却是一种快速有效的方法。
另一个问题是回购协议中定义的 Jupyter Lab 版本有一些 UI 问题。为了克服它们,必须通过指定包版本来升级。方法包含在第二个问题的解决方案中。

2。由于我们的数据管道是基于 GCP 的,我们需要包含 SDK 包和一些其他的库。幸运的是,Dask helm chart 支持使用 YAML 配置文件。因此,可以指定包含哪个pipconda包,分配给工人多少 RAM 以及更多。
在我们的例子中,我们添加了以下内容:

大多数软件包将通过conda使用conda-forgegaiar通道安装(见下文为什么也需要这个通道)。其余通过pip安装。

3。缺少二进制包版本
为了加速稀疏矩阵乘法,我们使用的是sparse_dot_topn,在算法部分提到过,它依赖于 Cython。像这样的包通常以两种方式提供:或者作为二进制预编译包,或者当库在安装主机上编译它的一部分时。在我们的例子中,我们遗漏了二进制发行版,这意味着我们应该在已经“不那么轻”的映像中添加编译工具。相反,我们选择了另一种方式。我已经有了在自己的渠道中构建和维护 conda 包的经验。conda 的一个显著优势是它以二进制方式发送包,这正是我们所需要的。
根据 pip 分布使用 conda 配方定义 YAML 文件相对容易:

有了这个配方,您就可以运行conda build命令并将包上传到您可以访问的频道。然后,可以用conda -c CHANNEL_NAME PACKAGE_NAME或者在我们的例子中用conda -c gaiar sparse_dot_topn来安装这个包。我准备了两个版本——一个用于 Linux,另一个用于 MacOS(因为它在安装上也有一些问题)。

4。吊舱的有限资源
这部分是具体情况,取决于 Dask 正在运行的任务类型和约束条件。在我们的例子中,我们需要更多的 RAM,并希望定义每个 pod 可以消耗的内存上限。这通过配置 YAML 文件再次完成:

也就是说:每个员工的最低限额是 3G,但是如果需要的话,可以申请 6G。

下面是 Dask 在 GCP k8s 上工作的简单演示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

把所有东西放在一起并运行它

结合上述算法和部署,我们的代码在大约 20-30 分钟内执行匹配过程;与最初的 52 天相比,速度大大加快了。😆

这是我们一次运行的输出表中的一小部分:

这张表和获取它所需的执行时间表明,红色药丸可能是这次更明智的决定。

编后记

让我们试着用一句话来说:部署在 Kubernetes 中的 Tf-idf 矢量化和余弦相似性结合高效的稀疏矩阵计算和并行执行操作使用 Dask 的分布功能,被证明是处理大规模字符串相似性问题的非常有效的方法。

特别感谢 盖亚尔·白木拉托夫 做出部署并撰写相应章节。

大脑和神经元的结构。

原文:https://towardsdatascience.com/structure-of-brain-and-neurons-examination-of-rewiring-in-brain-38f5a7c0d850?source=collection_archive---------31-----------------------

用建议的大脑和神经元结构检查脑瘤切除。

当我们谈论大脑时,我们首先说什么?我们说它太复杂了,以至于我们仍然不能完全理解它。我将对大脑的结构做一个假设,并且,我将检验“大脑重塑自身”中提到的情况。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Daniel Hjalmarsson on Unsplash

神经的结构是什么?

神经只是二元开关。当它们用于一个信息时,它们是 1。不使用时为 0。它是如何发生的?当一个信息到来时,该信息被连接到离输入门最近的空神经元(0)。举一个基本的例子,让我们假设当我们看到一只狗时,一个连接并靠近视觉输入门的神经元被激活。我们看到的狗的图像被分配给那个神经元。当我们看到同一只狗处于与我们之前看到的完全相同的状态时,神经元被激活,这样我们就知道它是同一只狗。如果我们很长时间看不到那只狗会怎么样?那只狗的图像到神经元的分配被删除,这意味着我们忘记了那只狗。那么,我们如何忘记呢?

大脑中有一个遗忘规则。如果分配给一个信息的神经元长时间或以必要的频率不被激活(如果任何电流不通过该神经元),则分配给该神经元的信息被擦除。

大脑的结构是什么?

首先,正如大家所说,我们有神经元和轴突。大脑只由神经元和轴突组成。在大脑的所有区域,神经元的类型完全相同。在大脑中,没有为执行特定任务而保留的特殊区域。这些场是由大脑的一般工作原理创建的,在我解释了它的结构之后,我也会解释。由于学习时间的原因,这些区域用于特定的任务。我这么说是什么意思?

第一个获得输入并将其处理到大脑的地方是传感器首次连接的地方。所以,当一个输入来临时,它首先会被放置在大脑中与输入相连的最近的空神经。

当一个婴儿出生时,它实际上感觉到的第一件事是光(婴儿不能像正常人一样看东西,它只能感觉到光)。所以,大脑的第一个输入来自眼睛。眼睛首先与大脑的后场相连。因此,婴儿获得的视觉输入开始被放置在最靠近视神经连接区域的空神经元中。

这个条件适用于人体内所有的传感器活动。听觉信息开始被放置在最靠近听觉输入门的神经元中。

包含复杂认知行为、决策、社会行为和个性的区域是什么?

要回答这个问题,我们先来看看哪个地方离听觉、视觉等输入门最远……答案是额叶。我们分配给神经元的第一个信息来自我们的传感器(输入门)。大脑中离这些区域最远的地方包含了负责最复杂信息的神经元。我们通过传感器获得并分配给神经元的信息是更复杂信息的基础。首先分配的神经元代表最基本的信息,而最后分配的神经元代表我们学习的最复杂的信息。

在图 1 中,大脑的结构以简化的结构示出。圆圈表示神经元,神经元之间的箭头表示轴突,用红色绘制的神经元表示被分配给第一听觉信息的第一神经元,用黑色绘制的神经元表示被分配给第一视觉信息的第一神经元,Hear6 表示包含听觉信息的神经元之一,See7 表示包含视觉信息的神经元之一,Hear6+See7 表示被分配给与 Hear6 和 See7 中的信息相关的复杂信息的神经元。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1 - An Example of Brain Structure

对“再造自身的大脑中讲述的案例的检验

这个案子是关于一个男孩的。这个男孩的大脑后部有一个肿瘤。医生切除了肿瘤,切除了他大脑右半球的 1/3。手术后他可能会失明,因为被切除的区域被分配给了视力,但他没有失明。

我将从文章中提取部分内容,并通过将案例与我上面解释的大脑和神经的结构联系起来进行解释。我不会用男孩的名字,因为他的父母可能不想要。我就写“男孩”来表达他吧。

外科医生切除了对处理通过我们眼睛的视神经传递的信息很重要的脑叶,使我们能够看到,同时它们对识别面孔和物体以及贴上相应的名字也很关键。没有办法确定这个男孩手术后是否能再次看见,认出他的父母,甚至正常发育。

  • 1)根据我的大脑结构模型,大脑被切除部分的神经会导致男孩失去信息。如果基础神经元(首先连接到输入门的神经元)被移除,男孩将在第一时间看到问题。但是过一段时间后,他的视力会在大脑的另一边发育,就像新生儿一样。分配给视觉信息的新区域将是大脑中最靠近视神经的地方。如果分配给更复杂视觉信息的神经元被移除,那么男孩的视觉不会受到显著影响,但他拥有的更复杂的视觉信息将受到影响。他可能无法识别和命名周围的物体和人。一段时间后,男孩将能够认出他的父母和物品,同时他也能正确地说出他们的名字。因为连接到分配复杂视觉信息的被移除神经元的基础视觉神经元仍然存在,男孩的大脑将使用与具有基础信息的神经元最接近(剩余)的神经元来分配复杂视觉信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2 — Closest Neurons to Optical Nerve (L1, L3, L6, R1, R3, R6)

尽管失去了超过 15%的大脑,这个男孩还是很好。

唯一的例外是他的左眼失去了周边视觉。

“它不像是模糊的或者只是那里黑。就像,都是混合的,”男孩说。

  • 2)正如我上面解释的,这个男孩会没事的。首先认识到的问题是他留下了他的周边视觉。但是周边视觉的问题并不像他说的那样是一片漆黑或者模糊。所以,他实际上没有失去视力,他的大脑只是忘记了,因为分配给这些部分的神经元被移除了。基本上,他的周边视觉就像一个新生儿的视觉。他只能从他周围的景象看到原始的视觉输入。

他的左脑承担了他现在基本缺失的右脑的所有责任和任务。

  • 3)如上所述,被去除的神经元被分配给视觉信息。当它们被移除时,新的神经元将被用来分配这些信息。他大脑的哪一侧会被使用并不重要。大脑中最靠近视神经的神经元将被用于此。

大脑具有可塑性(可伪造的)改变自身的能力这一事实并不新鲜。较少了解的是大脑究竟是如何做到的。

据说大脑锻造自己的方式是未知的。按照我的大脑结构模型是怎么做到的,在第一篇里讲了。

男孩大脑的剩余结构能在多大程度上接管他被移除的那部分大脑的功能?

答案是肯定的。男孩大脑的剩余结构可以接管他大脑被移除部分的功能。他将和任何人一样正常。

科学能描述大脑如何进行这些变化,一直到细胞水平吗?

下面的图 1 解释了这些变化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2 - How information is received and assigned to neurons

当男孩癫痫发作时:“我的大脑就像冻僵了一样,”他说。“我真的很困惑,然后我真的感到恶心,呕吐,然后我又会表现得很正常。”

大脑中的电活动紊乱会导致癫痫发作。神经元在没有任何输入的情况下开始随机传递电流。原因是他得了肿瘤。肿瘤细胞在大脑中产生了无计划的电活动。这就像给你的神经元一个随机输入。因此,他会感到困惑和恶心。当随机输入结束时,癫痫发作结束,他又感觉正常了。但长时间癫痫发作会导致他的神经元结构紊乱,这可能会导致永久性记忆丧失或神经元功能丧失。这就是为什么手术对他来说至关重要。

“我们知道儿童的大脑具有可塑性,我们不断在大脑中创造新的算法来生活。但除此之外,当你癫痫发作时,这些被破坏的电网络会阻止任何有意义的重新映射。”克里斯蒂娜·帕特森说。

意义重映射有问题的原因是不平衡的电活动。如图 2 所示,就神经元的电荷而言,在神经元之间产生了新的连接。

手术后,男孩认出了他的父母,但他无法将他们的脸和名字对应起来。这个问题几天后就自行解决了。

看起来,这个男孩也失去了一些连接他父母名字和面孔的轴突和神经元。在图 2 中可以看到之前分配了信息的两个神经元之间的连接创建的例子。手术后,男孩失去了大脑中的这种联系。所以,他不能匹配他父母的脸和名字。

儿童的大脑年轻,仍在发育,因此最有可能发生神经可塑性变化。

神经元是按顺序分配的。我告诉他们,离输入门最近的神经元开始给他们分配信息。当我们变老时,我们学到的信息变得更加复杂。正因为如此,失去负责基本信息的神经元对成年人的影响可能比男孩更大。但是,如果成年人失去了分配给复杂信息的神经元(例如从额叶移除一部分),则更容易恢复丢失的信息,同时对成年人的生活影响较小。

20 世纪 60 年代,科学家 David Hubel 和 Torsten Wiesel 绘制了小猫的视觉皮层,以了解视觉是如何处理的。然后,在一个公认的可怕的过程中,科学家们合上(缝合)了研究中一只小猫的眼睑。打开眼睑后,他们发现小猫大脑中负责处理来自那只眼睛的图像的视觉区域没有发育,导致小猫的那只眼睛失明,尽管这只眼睛在生物学上没有任何问题。研究人员发现,如果小猫的大脑正常发育,它们必须在出生后的第三周到第八周之间能够看到周围的世界。

正如我们所见,被缝了一只眼睛的小猫用被缝的眼睛看不清楚,但它可以很好地使用另一只眼睛。David Hubel 和 Torsten Wiesel 关闭了眼睛到大脑的输入门。因为没有输入,所以在输入门附近没有分配给视觉信息的神经元。

但是这项研究的另一个发现被证明更加重要——并为胡贝尔和威塞尔赢得了诺贝尔奖。“小猫的大脑中被剥夺了闭眼输入的那部分没有保持空闲,”Doidge 写道。“它已经开始处理来自睁着的眼睛的视觉输入,就好像大脑不想浪费任何‘皮质不动产’,并且已经找到了自我重组的方法。”

一段时间后,即使没有来自闭眼的输入,也需要更多的神经元来分配来自睁眼的视觉信息。最近的地方是另一个未使用的一侧,靠近闭眼的视神经。因此,他们继续从那里接受信息。

在男孩的案例中,问题是完整无损的左半球是否会恢复缺失的三分之一大脑的功能,特别是面部识别任务,这通常是由右半球执行的。

通过使用被称为扩散张量成像的神经成像技术分析大脑扫描,Behrmann 发现大脑的白质(强调多个神经区域之间通信的电线)实际上发生了变化,扩散张量成像显示了水如何沿着大脑的白质束流动。之前没有连接的大脑区域产生了新的连接,这是一个神经可塑性的例子,可以保护大脑功能。但是科学家仍然不知道是什么引发了白质细胞的这种行为。

上面的段落保证了我在图 2 中展示的结构和功能。

在玛琳·贝尔曼对这个男孩和其他九个孩子(他们都失去了左半球或右半球的部分区域)进行的后续研究中,包括男孩在内的八个孩子显示出绝对正常的视觉功能。两个没有死的孩子在手术前由于癫痫发作造成的脑损伤更严重。

正如我上面所说,癫痫发作可能会导致永久性记忆丧失或神经元功能丧失。在无功能神经元的情况下,如果在大脑中有足够数量的健康神经元留在足够靠近输入门的地方以进行连接,则视觉信息仍然可以分配给那些健康神经元。如果不再有健康的神经元留下,或者如果剩余的健康神经元没有足够近以在神经元之间形成极性从而使它们连接,那么被剥夺的视觉信息不能被分配给新的神经元。

泰勒·阿贝尔和贝尔曼指出,甚至可能是这样,男孩大脑中发生的一些重组在他预定的手术之前就开始了。这不是贝尔曼能证明的,因为所有对男孩的研究都是在手术后进行的。

“当你的大脑出现异常导致癫痫发作时,这种异常实际上会导致大脑重组,或者在手术实际发生前就开始重组,”Abel 说。“但有时会发生的另一件事是,癫痫发作会影响大脑的功能,大脑不会重组。”

根据提出的神经元和大脑的结构,如果癫痫发作是局部的并且不影响整个大脑,那么靠近受癫痫发作影响的神经元的未使用的神经元可以连接到受影响神经元的基底神经元来分配信息。由此,信息被检索。

所有哺乳动物的大脑结构都一样吗?

答案是肯定的。结构相同,但神经元的数量与输入门结构和输出门结构(手臂、舌头、嘴、腿等)相同。)都不一样。神经元的数量只能影响分配给神经元的信息量。但是输入结构和输出结构是人类和所有其他哺乳动物的唯一区别。如果我们能够将狗的输入门改造成与人类完全相同的输入门,我们将会看到狗能够像人类一样说话。我们还需要记住,哺乳动物的输入门已经足够发达,可以像我们一样感受到痛苦和悲伤。所以,当我们想起对动物的不良行为时,会变得更加悲伤。因为对人和对动物做出那些不好的行为没有任何区别。

泰京·埃夫林·奥兹默默

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值