机器学习是我们每天接触的许多产品背后的长期驱动力,从Apple的Siri和Google等智能助手,到建议您购买新产品的Amazon等推荐引擎,再到Google和Facebook使用广告排名系统。最近,由于“深度学习”的发展,机器学习进入公众视野,包括AlphaGo击败韩国围棋大师李世石,以及令人印象深刻的图像识别和机器翻译新产品发布。我们将介绍机器学习中一些强大但普遍适用的技术。阅读本文后,您应该具备在自己的领域中进行具体机器学习实验的知识。我们结合一个Python扩展“案例研究”:我们如何构建用于检测信用卡欺诈的机器学习模型?(虽然我们将使用欺诈检测语言,但所做的大部分工作都适用于其他分类问题稍作修改,例如广告点击预测。)随着时间的推移,我们将遇到机器学习中的许多关键思想和术语,包括逻辑回归、决策树、随机森林、正预测(TruePositive)和负预测(FalsePositive)、交叉验证(cross-validation),以及接受者操作特征(ReceiverOperatingCharacteristic,简称ROC)曲线和曲线下面积(AreaUndertheCurve,简称AUC)曲线。目标:信用卡欺诈在线销售产品的企业不可避免地需要处理欺诈问题。在典型的欺诈交易中,骗子使用窃取的信用卡号从在线站点购买商品。骗子随后会在别处以折扣价出售这些物品,中饱私囊,但商家必须承担“退款”的费用。您可以在此处获取有关信用卡欺诈的详细信息。假设我们是一家电子商务企业,处理诈骗已有一段时间了,我们想使用机器学习来提供帮助。更具体地说,每次进行交易时,我们都想预测它是否可以被证明是欺诈(例如,授权持卡人是否不是交易的人),以便我们采取相应的行动。这种类型的机器学习问题称为分类,因为我们所做的是将每笔收入分类为欺诈性或非欺诈性。对于每一笔历史支付,我们都有一个布尔值来指示交易是否是欺诈性的(fraudulent),以及一些我们认为可能指示欺诈的其他属性,例如以美元支付的金额(amount),卡的国家(card_country),以及这张卡在同一天(card_use_24h)在我们的业务中被支付的次数。因此,我们建立预测模型的数据很可能类似于以下CSV:fraudulent,charge_time,amount,card_country,card_use_24hFalse,2015-12-31T23:59:59Z,20484,US,0False,2015-12-31T23:59:59Z,1211,US,0False,2015-12-31T23:59:59Z,8396,US,1False,2015-12-31T23:59:59Z,2359,US,0False,2015-12-31T23:59:59Z,1480,US,3False,2015-12-31T23:59:59Z,535,US,3False,2015-12-31T23:59:59Z,1632,US,0False,2015-12-31T23:59:59Z,10305,US,1False,2015-12-31T23:59:59Z,2783,US,0在本次讨论中我们将跳过两个重要细节,但我们需要牢记它们,因为它们同样重要,如果不是更多我们在这里提出的模型构建问题。首先,识别我们认为是欺诈的特征是一个数据科学问题。在我们的案例中,我们已将支付金额、发卡国家和过去一天收到的卡交易数量确定为我们认为可有效预测欺诈的特征。一般来说,您将需要花费大量时间查看这些数据,以确定哪些有用,哪些无用。其次,在计算特征值时存在数据基准问题:我们需要所有的历史样本值来训练模型,但我们还需要加上它们的实时支付值才能正确训练新的交易。在你开始担心欺诈之前,你已经维护并记录了过去24小时的信用卡使用次数滚动记录,所以如果你发现有利于欺诈检测的特征,你将需要在生产环境中单独计算它们批处理环境使用它们。根据定义的不同特征,结果可能会有所不同。总而言之,这些问题通常被称为特征工程,并且通常是工业规模机器学习领域中最常解决(和影响)的部分。逻辑回归让我们从最基本的模型开始,一个线性模型。我们会求出系数a,b,...,z,如下对于每笔支付,我们将amount,card_country,card_use_24h的值代入上式,如果概率大于0.5,我们就“预测”此A付款是欺诈性的,而我们会预测它是合法的。在我们讨论如何计算a,b,...,z之前,我们需要解决两个当前的问题:概率(欺诈)需要一个介于0和1之间的数字,但右侧可以任意大(绝对值),取决于amount和card_use_24h的值(如果那些特征的值足够大,并且a或b中至少有一个不为零)。card_country不是一个数字,它取许多值中的一个(比如US、AU、GB等等)。这些特征称为分类特征,需要在我们训练模型之前进行适当的“编码”。Logit函数为了解决问题(1),我们会建立一个叫scammer的log-odds模型,而不是直接通过p=Probability(fraud)来建立模型,所以我们的模型就变成了如果一个事件发生的概率是p,它的概率是p/(1-p),这就是为什么我们称公式左边为“logodds”或“logit”。考虑到a,b,...,z的取值和特征,我们可以通过对上面给出的公式求逆来计算预测的欺诈概率,得到如下公式欺诈概率p是转换函数L的线性函数=axamount+bxcard_use_24h+...,看起来像这样:不管线性函数的值如何,sigmoid映射到0到1之间的数字,这是一个合理的概率。分类变量为了解决问题(2),我们将使用分类变量card_country(取N个不同值中的1个)并扩展为N-1个“虚拟”变量。这些新特征都是boolean格式的,card_country=AU,card_country=GB等,我们只需要N-1个“虚”,因为当N-1个虚值为false时,必然包含N个值。为简单起见,让我们假设card_country只能使用AU、GB和US这三个值之一。然后我们需要两个虚拟变量来编码这个值,我们想要拟合的模型(例如,找到系数值)是:模型类型称为逻辑回归。拟合模型我们如何确定a、b、c、d、Z的值呢?让我们从随机选择a、b、c、d和Z开始。我们可以将这组猜测的概率定义为:即,从我们的数据集中取出每个样本,并计算欺诈的预测概率p,给定猜测a、b、c、d和Z(每个样本的值)的特征值:对于每个实际欺诈的样本,我们希望p相对接近于1,而对于每个非欺诈的样本,我们希望p接近于0(因此1-p应该接近于1).因此,我们对所有欺诈样本使用p乘积,对所有非欺诈样本使用1-p乘积,以估计a、b、c、d和Z的猜测能力。我们希望似然函数尽可能大(例如,尽可能接近1)。开始我们的猜测,我们迭代地调整a、b、c、d和Z,增加概率,直到我们发现它不能再被扰动因子增加。一种常见的优化方法是随机梯度下降。Python实施现在我们将使用标准Python开源工具实施我们刚刚讨论的原则。我们将使用pandas,它将类似R的数据科学API(类似R的数据帧)引入Python,以及scikit-learn,一种流行的机器学习包。让我们将之前描述的CSV文件命名为“data.csv”;我们可以上传数据,看看下面的代码:模型。我们拆分目标(在这个欺诈案例中尝试预测变量)并使用scikit需要的属性作为不同的输入参数。在进行模型训练之前,我们还有一个问题要讨论。我们希望我们的模型能够很好地概括,例如,它在对付款进行分类时应该是准确的,它应该以我们以前从未见过的方式进行,而不仅仅是我们以前见过的在付款时计算的特殊模式.为了确保过拟合模型不会在现有数据中变成噪声,我们将数据拆分成两个训练集,一个训练集将用于评估模型参数(a、b、c、d和Z)和验证集(也称为测试集),另一个数据集将用于计算模型性能指标(我们将在下一章介绍)。如果模型过拟合,它将在训练集上表现良好(因为它学习了该集中的模式),但在验证集上表现不佳。还有其他交叉验证方法(例如,k折交叉验证),但“测试-训练”分离将适合我们的目的。我们可以使用sckit轻松地将数据拆分为训练集和测试集,如下所示:在本例中,我们将使用2/3的数据来训练模型,使用1/3的数据来验证模型。我们现在准备好训练模型了,这里很简单:拟合函数运行拟合过程(最大化上面提到的似然函数),然后我们可以将a、b、c、d(在coef_中)和Z(在intercept_)值查询返回对象。所以我们的最终模型是评估模型性能一旦模型被训练,我们需要确定模型预测感兴趣变量的程度(在这种情况下,一个布尔值表示支付是否是欺诈性的)。回想一下,我们说过我们想将付款归类为欺诈,如果概率(欺诈)大于0.5,我们想将其归类为合法。衡量模型和分类规则性能的方式通常使用两个变量,如下所示:误报率:所有合法费用中被错误分类为欺诈的部分,以及真阳性率(也称为召回率或敏感性指标)),所有欺诈收入中被正确归类为欺诈的部分。评估分类性能的方法有很多,我们将锁定这两个变量。理想情况下,误报率将接近0,真正率将接近1。当我们更改概率阈值(上面我们说0.5,但我们可以选择0到1之间的任何值)时,我们将收费归类为欺诈,较小的值意味着我们更积极地将付款标记为欺诈),而较高的值意味着我们更保守),误报率和真阳性率绘制一条曲线,这取决于我们的模型有多好.我们称之为接受者操作特征曲线(ROC曲线),可以使用scikit轻松计算:变量fpr、tpr和阈值包含所有ROC曲线的数据,但我们选择了一些有针对性的样本:如果概率(欺诈)大于0.514,而假阳性率为0.374,真阳性率为0.681,我们假设收费是欺诈性的。我们选择的ROC曲线和绘图点是:模型的性能越好,越接近ROC曲线(上图蓝线),就会越接近图形的左上边界。请注意,ROC曲线可以通过使用AUC数字或查看曲线下的面积来告诉您模型的好坏。AUC值越接近1,模型性能越好。当然,当你将模型值放到生产环境中使用时,通常需要经过我们上面使用的方式,即比较它们的阈值来采取行动,输出概率模型。如果概率(欺诈)>0.5,我们认为A费用被假定为欺诈。因此,对于特定的应用程序,模型性能对应于ROC曲线上的一个点,并且整个曲线再次简单地控制假阳性率和真阳性率之间的权衡,例如,政策选择中的处置不同。决策树与随机森林上面的逻辑回归模型是线性机器学习模型的一个例子。想象一下,我们的每一个支付例子都是空间中的一个点,这个点的坐标就是特征值。如果我们只有两个特征值,则每个示例点都是X-Y平面上的一个点。如果我们可以使用线性函数将非欺诈样本与欺诈样本分开,则逻辑回归等线性模型通常效果很好,这意味着几乎所有欺诈样本都位于一条线的一侧,而几乎所有非欺诈样本都位于这条线的一侧线的另一边。通常,为了预测特征和目标变量之间的关系,我们试图预测这种关系是非线性的,在这种情况下,我们需要使用非线性模型来计算这种关系。一个强大而直观的非线性模型是决策树,如下所示:对于每个节点,我们将特定特征的值与某个阈值进行比较,根据比较结果,我们可以区分是向左走还是向右走。我们以这种方式继续(类似于二十个问题的游戏,尽管数字不需要有二十个级别深)直到我们到达树叶。叶子由我们训练集中的所有样本组成。比较这棵树上每个节点的满意路径,根据模型报告预测的概率判断样本叶子的欺诈部分为欺诈。当我们有一个新的样本要分类时,直到我们到达一片叶子,我们生成它的特征并开始玩“二十问题游戏”,然后预测欺诈的可能性,如下所述。虽然我们不会详细讨论树是如何生成的(尽管简单来说,我们为每个节点选择特征和阈值,最大化信息增益或判别力的概念,也就是上图中报告的基尼系数,并递归直到达到某个预先指定的停止标准),使用scikit训练决策树模型就像训练逻辑回归(或实际上任何其他模型)一样容易:决策树的一个问题是它们很容易被矫枉过正,其中一棵非常深的树的每个叶子只是训练数据中的一个例子,通常计算每个例子的噪声,并且可能不是常见的趋势,但随机森林模型可以帮助解决这个问题。在随机森林中,我们训练了大量的决策树,但是每棵树只在我们现有数据的一个子集上进行训练,而且我们在构建每棵树时只考虑分割子集的特征。预测的欺诈概率是森林中所有树木产生的平均概率。每棵树仅在数据的一个子集上进行训练,并且只有一部分特征被视为每个节点的单独候选者,从而减少树之间的相关性并减少过度拟合。总之,当特征和目标变量之间的关系是线性的,或者当你希望分离任务特征对预测的影响时,像逻辑回归这样的线性模型是合适的(因为这允许直接读取回归系数).另一方面,决策树和随机森林等非线性模型难以解释,但它们可用于计算更复杂的关系。生产机器学习模型训练机器学习模型可以被认为只是使用机器学习解决业务问题的第一步。如上所述,模型训练通常必须在特征工程开始工作之前完成。一旦有了模型,就需要将其去产品化,也就是说,使模型在生产环境中可用,并允许采取适当的行动(例如,阻止被评估为欺诈的交易)。虽然我们不会在这里详细介绍,但生产化会带来许多挑战,例如,您可能使用Python来部署模型,但您的生产软件堆栈是用Ruby编写的。如果发生这种情况,你需要通过某种格式的序列化形式将你的模型从Python转换为Ruby,并让你的生产环境中的Ruby代码读取序列化,或者使用面向服务的系统架构来实现序列化PythonService向Ruby请求,两者任选其一。对于性质完全不同的问题,您还需要在生产中保持度量模型性能(而不是对验证数据进行大量计算)。根据您使用模型的方式,此过程可能会很困难,因为仅使用模型来控制行为可能会让您没有数据来计算指标。本系列的其他文章将考虑其中的一些问题。配套资料包括所有示例代码的Jupyter注释和模型训练示例数据,可在“阅读原文”原文链接中找到。作者介绍了MichaelManapat(@mlmanapat),他在Stripe领导机器学习产品开发,包括StripeRadar。在加入Stripe之前,他是谷歌的一名工程师,也是哈佛大学应用数学的博士后研究员和讲师。他拥有博士学位。麻省理工学院(MIT)数学博士。
