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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

人工智能的软件设计模式和原则#1: SOTA 测试

原文:https://towardsdatascience.com/software-design-patterns-and-principles-for-a-i-1-sota-tests-3dd265c6bf97?source=collection_archive---------19-----------------------

我决定写一系列关于人工智能世界中软件系统设计模式的博客文章…

在我们工作的过程中,我感觉到(并且继续感觉到)在人工智能世界中软件系统的设计模式和原则领域缺乏文献和关注。

我们提出了许多设计想法,我们发现这些想法是解决重复出现的问题的好方法(根据定义,它们是设计模式)。

从我与业内同事的交谈中,我也相信它们对人工智能和算法领域的许多其他团队来说可能是通用和有用的。

我将在这些博客帖子中介绍的所有模式和原则已经在我们的团队中广泛使用了几年,我们确信它们是我们快速可靠地扩展能力的关键组成部分,在短短几年内为数百家医院提供了 10 多种危及生命的医疗状况的解决方案。

我相信这些职位对人工智能团队中的高级和初级工程师和研究人员都非常有价值,他们认为缺乏工程流程和方法正在导致巨大的开销,降低敏捷性,以及降低开发、研究和向客户交付的速度。

在这篇博文中,我决定把重点放在“SOTA 测试”上,这是一种测试人工智能系统的核心设计模式。在未来的博客文章中——我将涵盖测试和其他领域的额外模式,例如算法的持续交付——并乐意听取读者对主题的想法。

模式 1: SOTA(最先进的)测试

一般来说,在软件测试中,为高级组件编写测试(例如,为整个系统编写端到端测试)和为较小的模块编写低级测试之间总是存在冲突。前者为您提供了非常好的覆盖率,而后者为您提供了问题所在的非常本地化的概念——但是您必须编写大量的代码才能获得覆盖率。

两者对于扩大规模都很重要。

同时,根据我的经验,我提倡从编写端到端测试开始,原因有二:

  1. 它们编写起来要简单得多,并且在测试设计中需要的专业知识也少得多。
  2. 人工智能系统往往有许多高度复杂的移动部件,当你给你的算法增加更多的复杂性时,它们会不断变化和进化。端到端测试将让您立即意识到某个地方有问题。你可能要花几个小时才能找到问题所在,但是这比在问题产生 3 个月后才发现要好得多在这段时间内,你的代码中引入了如此多的变化,甚至可能需要几周的时间(根据我们的经验)来查明问题

一个好的“整个系统”的端到端测试设计,是构建一个测试,通过系统运行一个特定的“用户故事”。这是端到端测试的一般原则,适用于软件的每个领域。我所说的“用户故事”是指用户与你的系统之间有意义的、完整的交互。

如果我们看看我们的“研究系统”,通常称为“研究管道”。为了澄清,这是接收数据和算法配置(例如超参数)作为输入,并输出新算法的二进制文件(例如训练的权重)及其性能测量值(例如带度量的 excel)的代码部分。

这个系统的用户当然是算法工程师\研究人员。

假设他们已经使用这个系统建立了一个检测脊柱骨折的算法,并实现了 SOTA 性能(目前为止在这个问题上实现的最好性能)。

SOTA 测试将测试“用户故事”,其中包括工程师构建该算法和实现 SOTA 性能所采取的所有步骤,它将验证— 当使用相同的数据和超参数时,我们仍然可以使用当前版本的研究基础设施代码实现 SOTA 性能(这可能与 6 个月前最初实现 SOTA 性能所使用的版本有很大不同)。

实际上,为了运行它,您需要:

a.运行一些与工程师运行的脚本非常相似的东西来构建算法;在许多人工智能系统中,由于许多组件的随机性质,多次运行相同的 SOTA 脚本将导致不同的性能。因为我们对可再现性感兴趣——建议“播种”您的基础设施正在使用的所有随机数生成器(例如 python 的 random、numpy、tensorflow 等)。),与最初实现 SOTA 时使用的“随机种子”相同。你可能不知道所有这些(例如,你正在使用的库就在你的脚下使用它们中的一些),但是努力去理解所有被随机化的东西并确保所有东西都被播种是很重要的。

b.断言 SOTA 已经实现:

  1. 确定哪些指标真正定义了您的 SOTA(例如,召回率、精确度、AUC 或任何其他指标),并确定每个指标的 SOTA 值(例如,95%召回率@ 90%精确度)。在这方面**,我建议测量“下游指标”——尽可能接近用户感受的指标。**
  2. 在前面的一段中,我提到了播种随机数发生器的可重复性。事实是,在许多深度学习系统中,这将有很大帮助,但这还不够。一些随机性来源不容易控制(例如,如果您在训练期间使用多线程将数据预取到 RAM 中,一个“竞争条件”将导致数据样本的确切顺序在运行之间不同)。因此,在构建测试时,我建议在您的 SOTA 上运行“噪声实验”,以测量几次相同运行的标准偏差。使用该测量偏差作为再现结果和原始 SOTA 结果之间比较的公差。

【tests 测试对研究基础设施的优势:

  1. 可靠性 —大多数公司开发的许多算法都与他们以前的算法非常相似(“从你的管道中挤出果汁”)。例如,构建脊柱骨折检测算法可以使用系统的许多功能来实现,这些功能与用于构建中风检测算法的功能相同。如果你把事情做对了——当你到了第 10 个算法的时候——训练一个新的算法可以变成一个“单击”的动作(如果很多读者有需求,我可以在不同的博客上分享更多)。因此,测试系统仍然能够在以前的算法上实现 SOTA 性能,这也验证了未来算法所需的绝大多数特征。因此— 在开始开发新算法之前,这是确保您的系统可靠运行的一个非常好的起点。用一个有漏洞的研究系统开发一个新算法,可能会让你得出这样的结论:你正面临一个不可行的算法挑战——而实际上你的系统中有一个非常狡猾的漏洞。
  2. 确保可再现性 —敏捷和精益的基础之一是能够将最小可行的产品(您的愿景的最小版本)快速交付给您的客户——获得用户反馈,并迭代改进。因此,在您的算法中做出妥协,快速交付它,并使用客户反馈来指导未来的改进工作是一个很好的实践。

**促进这种迭代过程的第一步是有能力复制上一代——SOTA 测试将你需要的时间从几周减少到一次点击。**因此,我认为 SOTA 测试是人工智能团队中精益和敏捷流程的推动者

众所周知,测试不仅在可靠性方面非常有价值,而且可以作为系统用户的文档;我和许多团队交谈过,他们不记得在几个月前为他们开发的算法存储数据注释(或者他们如何预处理数据)的地方。他们不得不将数据发送到重新标注,浪费了大量的时间和风险,他们仍然无法重现他们的结果。

我和许多不得不重新开发旧算法的团队谈过,而这位研究员挠着头,不记得“这五个脚本中的哪一个是用来开发它的,如果有的话”

SOTA 测试是你的研究的一个可执行文档**——这是最好的一种文档,因为当它过期时,它会给你一个巨大的红色警报**。它准确地告诉您存储数据的位置,以及在每个步骤中对数据执行了哪些操作。它准确地告诉你什么超参数你用来达到 SOTA 性能。它确切地告诉您您使用了哪种环境来达到 SOTA 性能以及如何构建它。因为您一直在运行它,所以它向您保证这些信息总是最新的(例如,如果有人将数据移动到不同的路径,测试就会失败)。

构建一个能够重现您的 SOTA 的自动化测试,是一个很好的方法来确保您没有在任何地方都没有记录的过程中执行任何手动转换,这是一个非常常见的现象,尤其是在数据准备阶段和不同培训阶段之间。

何时进行 SOTA 测试

最理想的情况是,测试应该尽可能频繁地运行,即使是在开发和重构代码的时候。这对于您的测试套件的“快速”子集来说是正确的,根据经验法则,它应该以每秒数百个测试的速度运行。

通常我上面描述的测试需要更多的时间——对于许多类型的算法,每个测试可能需要几分钟甚至几天。这使得在开发/重构过程中运行这些测试变得不现实。

同时,我相信这些测试具有很高的补充价值,并且不能通过仅仅使用“快速”单元测试来实现。我们发现对这些(通常)缓慢的测试最有益的工作模式如下

每周运行一次 SOTA 测试,并在合并重要的变更之前运行**(每个测试需要一到几天的时间来完成)。在早期,我们会在这些时间段手动运行测试,最终我们实现了一个在云虚拟机上运行这些测试的 Jenkins 管道。测试以完全自动化的方式运行,我们在专用的 Slack 通道上接收状态(成功/失败)。**

一旦 SOTA 测试失败,我们通常会在一天之内优先安排某人进行调查和修复。在这方面,我们受到了丰田制造方法的启发,该方法规定,一旦你的生产线的一部分出现故障(研究基础设施就是我们的生产线),立即解决问题将获得最佳的整体制造效率。

重述——在这篇博文中,我们介绍了一种测试人工智能软件的中心设计模式——SOTA 测试。正确地构建这些测试将花费您很小的努力(第一个版本需要几天,它将为您提供 80%的价值,其余的需要几周),并为您提供非常显著的好处——在您的管道的可靠性方面,以及在过去开发的算法的再现性方面。这些好处将导致你的团队的研究\开发\发布速度的显著加速,并将促进一个“精益”的开发过程。

这种模式已经在我们的团队中广泛使用了几年,我们确信这是我们快速可靠扩展能力的一个关键组成部分,在短短几年内为数百家医院提供了支持治疗 10 多种危及生命的医疗状况的解决方案。

在未来的博客文章中,我将涵盖测试和其他领域的额外模式,例如算法的持续交付,并乐意听取读者对主题的想法。

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

Taken from Pixabay

软件开发人员:你在颠倒地学习机器学习

原文:https://towardsdatascience.com/software-developers-youre-learning-machine-learning-upside-down-3867dc140862?source=collection_archive---------17-----------------------

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

Don’t be this guy.

我们大多数人都是从头开始学习机器学习的。但是开发人员成为 ML 的有效用户所需的技能是完全不同的。那么今天有远见的软件工程师应该学习什么关于 AI 的知识呢?

我记得我第一次尝试学习编码。我上中学的时候,我的爸爸,一个程序员,打开了一个文本编辑器,在屏幕上打出了这个:

public class HelloWorld {
    public static void main(String[] args) {  
        System.out.println("Hello World.");
    }
}

“请问?”我说。

“上面印着‘你好,世界’,”他回答道。

“什么是公开的?什么是阶级?什么是静电?什么——”

“暂时忽略这一点。这只是样板文件。”

但是我被那些我不理解的所谓样板文件吓坏了,所以我开始学习这些关键词的意思。这被证明是复杂和无聊的,几乎扼杀了我年轻的程序员的抱负。

今天学习软件开发比我上高中时要容易得多,这要归功于像 codecademy.com 这样的网站,建立基本开发环境的容易程度,以及 T2 倾向于教授像 Python 和 Javascript 这样的高级解释语言。你可以在几分钟内从对编码一无所知到在浏览器中编写你的第一个条件语句。没有杂乱的环境设置、安装、编译器或样板文件需要处理——您可以直接进入有趣的部分。

这正是人类最好的学习方式。首先,我们在高层次上学习核心概念,只有然后我们才能欣赏和理解引擎盖下的细节以及它们为什么重要。我们学 Python,然后 C,然后汇编,而不是反过来。

不幸的是,今天许多开始学习机器学习的人都有着和我第一次接触 Java 时一样的经历。他们提前了解了所有底层细节——层架构、反向传播、辍学等——并开始认为 ML 真的很复杂,也许他们应该先上一堂线性代数课,然后放弃。

这是一个遗憾,因为在不久的将来,大多数有效使用机器学习的软件开发人员将不需要考虑或了解任何底层的东西。正如我们(通常)不编写汇编或实现我们自己的 TCP 栈或加密库一样,我们将使用 ML 作为工具,并将实现细节留给一小组专家。到那时——在机器学习被“大众化”之后——开发人员将需要理解的不是实现细节,而是在世界上部署这些智能算法的最佳实践。

我们现在在哪里

今天,如果你想建立一个神经网络来识别照片中你的猫的脸,或者预测你的下一条推文是否会火起来,你可能会开始学习 TensorFlowPyTorch 。这些基于 Python 的深度学习库是当今设计神经网络最流行的工具,它们都不到 5 岁。

在它短暂的生命周期中,TensorFlow 已经变得比五年前更加用户友好。在早期,要成为一名有效的 TensorFlow 程序员,你不仅要理解机器学习,还要理解分布式计算和延迟图架构。即使是写一份简单的打印声明也是一个挑战。

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

Breakdown of Keras/TensorFlow/PyTorch popularity, courtesy this Quora answer.

就在今年秋天早些时候,TensorFlow 2.0 正式发布,使得该框架对开发人员更加友好。下面是 TensorFlow 2.0 中 Hello-World 风格的模型的外观:

如果你以前设计过神经网络,上面的代码是简单易懂的。但是如果你还没有或者刚刚开始学习,你可能会有一些问题。比如,什么是辍学?这些密集层是什么,需要多少,放在哪里?什么是sparse_categorical_crossentropy?TensorFlow 2.0 消除了构建模型中的一些摩擦,但它没有抽象掉设计这些模型的实际架构。

我们要去哪里

那么易用的 ML 工具的未来会是什么样子呢?从谷歌到亚马逊到微软和苹果,每个人都在花时间试图回答这个问题。此外——免责声明——这也是我作为谷歌工程师花费全部时间思考的问题。

首先,我们将开始看到更多的开发人员使用预先训练好的模型来完成常见任务,也就是说,我们不会收集自己的数据和训练自己的神经网络,而是使用谷歌/亚马逊/微软的模型。许多云提供商已经在做类似的事情。例如,通过点击 Google Cloud REST 端点,您可以使用预训练的神经网络来:

  • 从图像中提取文本
  • 标记照片中的常见对象
  • 将语音转换为文本
  • 在不同语言间翻译
  • 识别文本的情感
  • 更多

你也可以在设备上运行预先训练好的模型,在移动应用程序中,使用像谷歌的 ML 工具包或苹果的 Core ML 这样的工具。

与你在 TensorFlow 中自己构建的模型相比,使用预训练模型的优势(除了易用性之外)在于,坦率地说,你可能无法亲自构建一个比谷歌研究人员更准确的模型,谷歌研究人员在整个数据互联网和大量 GPU 和TPU上训练神经网络。

使用预先训练好的模型的缺点是,它们解决的是一般性问题,比如识别图像中的猫和狗,而不是特定领域的问题,比如识别装配线上某个部件的缺陷。

但是,即使在为特定领域的任务训练定制模型时,我们的工具也变得更加用户友好。

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

Screenshot of Teachable Machine, a tool for building vision, gesture, and speech models in the browser.

谷歌的免费可教机器网站让用户使用拖放界面在浏览器中收集数据和训练模型。今年早些时候,麻省理工学院发布了一个类似的无代码界面,用于构建在触摸屏设备上运行的定制模型,专为医生等非编码人员设计。微软和 lobe.ai 等初创公司也提供类似的解决方案。同时, Google Cloud AutoML 是一个针对企业级工作负载的自动化模型训练框架。

现在学什么

随着 ML 工具变得更容易使用,希望使用这种技术(但不是成为专家)的开发人员的技能将会改变。所以,如果你试图像韦恩-格雷特斯基那样计划冰球要去哪里,你现在应该学习什么?

知道何时使用机器学习总是很难的

机器学习算法与标准软件的不同之处在于它们是概率性的。即使是高度精确的模型有时也会出错,这意味着它不是许多问题的正确解决方案,尤其是就其本身而言。以 ML 驱动的语音到文本算法为例:偶尔,当你让 Alexa“关掉音乐”时,她会把你的闹钟设置为凌晨 4 点,这可能没问题。如果一个医学版本的 Alexa 认为你的医生给你开的是 Enulose 而不是 Adderall,那就不对了。

理解什么时候以及如何在生产中使用模型是一个微妙的问题。在以下情况下尤其棘手:

  1. 赌注很高
  2. 人力资源有限
  3. 人类对自己的预测有偏见或不准确

以医学影像为例。我们在全球范围内缺少医生,而在诊断疾病方面,人工智能模型通常比训练有素的医生更准确。但你会希望一种算法对你是否患有癌症拥有最终决定权吗?帮助法官决定刑期的模型也是如此。模特可以有偏见,但人也一样。

理解什么时候使用 ML 是有意义的,以及如何正确地部署它并不是一个容易解决的问题,但这是一个不会很快消失的问题。

可解释性

机器学习模型是出了名的不透明。这就是为什么它们有时被称为“黑匣子”用“我的神经网络告诉我的”作为唯一的证据,你不太可能说服你的副总裁做出重大商业决策。此外,如果你不明白为什么你的模型做出这样的预测,你可能没有意识到它做出了有偏见的决定(即拒绝向特定年龄组或邮政编码的人提供贷款)。

正是因为这个原因,ML 领域的许多参与者都专注于构建“可解释的 AI”功能——让用户更密切地检查模型使用什么功能来进行预测的工具。作为一个行业,我们还没有完全解决这个问题,但我们正在取得进展。例如,11 月,谷歌推出了一套解释工具以及一种叫做模型卡的东西——一种帮助用户理解 ML 模型局限性的视觉指南。

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

Google’s Facial Recognition Model Card shows the limitations of this particular model.

利用应用创造创意

有几个擅长机器学习的开发人员,几个擅长神经科学的研究人员,很少有人处于那个交叉点。几乎任何足够复杂的领域都是如此。未来几年,我们将从 ML 中看到的最大进步可能不是来自改进的数学方法,而是来自不同专业领域的人,他们至少学习了足够多的机器学习,以将其应用于他们的领域。这主要是医学成像领域的情况,例如,最令人兴奋的突破——能够在扫描中发现恶性疾病——不是由新的神经网络架构驱动的,而是由应用于新问题的相当标准的模型驱动的。因此,如果你是一个软件开发人员,幸运地拥有额外的专业知识,你已经领先了。

如果我从头开始我的人工智能教育,这至少是我今天会关注的。与此同时,我发现自己花在从零开始在 TensorFlow 中构建定制模型的时间越来越少,而花在使用 AutoML 和 AI APIs 等高级工具以及专注于应用程序开发的时间越来越多。

但这只是我的看法——你认为呢?请在下面的评论中告诉我。

感谢反馈莎拉·罗宾逊约书亚·戈登

深度学习环境中的软件开发最佳实践

原文:https://towardsdatascience.com/software-development-best-practices-in-a-deep-learning-environment-a1769e9859b1?source=collection_archive---------8-----------------------

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

软件开发:深度学习环境中的最佳实践

eep 学习系统现在被广泛应用于许多环境中。它们与传统软件系统的不同之处在于产生输出的方式:产生结果的决策是从训练数据中学习的,而不是像传统软件系统那样手工编码。

这导致人们错误地认为软件开发对于机器学习系统来说不是必要的,因为算法是任何实际系统的核心,是由系统本身学习的。此外,最先进的机器学习(ML)发展如此之快,以至于数据科学家们主要关注模型精度等短期目标。鉴于深度学习世界将在几个月内发生变化,为什么要浪费时间今天就正确地设计你的系统呢?目前,深度学习工程的谎言是,一个系统被一起实验,直到达到某个精度目标,然后被投入生产。

即使与传统系统不同,这种设计 ML 系统的方法也是有害的,原因如下:

  • 很容易出错,从而产生不正确的精度。例如,由于数据加载或转换中的错误,或者训练/测试/验证集的不正确处理。
  • 复制培训结果非常耗时,因为所使用的数据和配置通常没有记录,也没有版本。
  • 在生产环境中运行 ML 模型是很困难的,因为系统只在文档记录不良的开发环境中进行测试。
  • 使 ML 系统适应变化的需求也是棘手的,因为代码库的可维护性不是一个问题,并且系统缺乏自动化测试。

鉴于这些挑战,你如何设计深度学习系统,同时避免抛弃编码和实验的有害影响?在本文中,我们分享了开普勒视觉技术公司开发和采用的最佳实践。这些实践深深植根于现代软件开发实践,并解释了开发机器学习系统的独特性。那么,与传统系统相比,开发深度学习系统有什么特殊之处呢?

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

Photo by Shane Rounce on Unsplash

深度学习工程的特性

在本节中,我们列出了深度学习工程的特征,这些特征对采用传统软件工程的最佳实践构成了主要障碍。在本节的下一节中,我们将介绍我们采取的措施,以使我们的深度学习开发过程更加稳健和高效,克服(部分)这里列出的障碍。

1.快速发展的深度学习框架

在深度学习革命的黎明,模型是基于低级库建立的。一段时间后,专门的图书馆开始出现,以帮助 ML 工程师,最引人注目的是 2013 年成立的 Caffe 图书馆的推出。三年后,大量其他深度学习库出现了。滚动到今天,不同图书馆的数量继续增加,尽管已经形成了一批领先的领跑者。除了新的个体库的诞生之外,每个库本身必须不断地经历快速进化,因为它们试图跟上神经网络研究的新发展。

2.数据管理

深度学习系统的一个主要特点是,与传统软件系统相比,输入数据量要大得多,单个数据项的大小也是如此。在训练阶段尤其如此,在此阶段使用的数据量通常非常大。虽然由传统软件系统管理的数据存储可能会变得非常庞大,但这些系统仍然可以通过使用给定数据的一小部分来运行和测试。另一方面,训练深度学习系统永远不会成功,除非利用大量数据。

3.结构管理

管理配置数据是软件工程中的一门复杂的艺术,最佳实践是以这样一种方式对配置数据进行版本控制,即明确哪个配置数据属于哪个版本的源代码。这种最佳实践也适用于机器学习系统,但仍然很难实现,因为与传统系统相比,配置数据的规模非常大。毕竟,一个经过训练的神经网络的权重是配置数据,可以很容易地测量到总共 1Gb。

训练深度学习模型时使用的所谓超参数也是配置数据,必须进行实物管理。事实证明,这些超参数通常分散在代码中,以能够满足精度目标的方式进行调整。

4.测试深度学习系统

测试自动化现在广泛应用于软件开发中。然而,在深度学习领域,测试自动化的使用程度几乎不一样。原因有两个:首先,深度学习开发人员没有在现代软件工程实践中受过适当的培训,其次,开发深度学习模型需要大量的实验。

此外,训练深度学习系统是一个不确定的过程。这使得培训过程的自动化测试更加困难,因为对培训结果的简单断言是不够的。考虑到漫长的培训时间,很容易明白为什么大多数深度学习工程师放弃自动化测试。

推理的自动化测试更加简单。一旦模型被训练,由于舍入误差,只剩下少量的不确定性。

5.深度学习系统的部署

两个核心特征将深度学习系统的部署与传统系统区分开来:首先,大多数深度学习系统需要特殊的硬件,即 GPU,以足够的吞吐量运行。其次,深度学习系统需要一个大的配置文件,即权重文件,才能进行预测。这使得实现开发/生产对等,即开发和测试的相似环境变得更加困难。此外,由于其大小,将权重文件与源代码一起打包在一个部署包中是不明智的。这导致您需要使用单独的工件来部署权重文件和系统,同时保持它们的同步。

我们设计深度学习系统的方法

我们的方法基于一个指导原则,即训练和运行深度学习系统应该尽可能自动化。它不应该基于一个人需要在几周的实验后训练和评估模型。

使用持续集成构建 Docker 映像

我们使用 Docker 来指定我们深度学习系统的开发和运行时环境。当我们对版本控制系统进行修改时——在我们的例子中是 GitHub——Travis 会介入并运行测试,如果成功的话,就会构建最新的 Docker 映像并将它们推送到 Docker 存储库。Docker 图像将不包含模型,因为这会使我们的 Docker 图像太大而不容易分发。

使用 Docker,运行时环境与代码一起得到保护,并且可以在任何支持 Docker 的环境中可靠地部署和运行系统,而不管使用的深度学习框架如何。

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

Photo by elCarito on Unsplash

将云放在首位

我们努力在云中的一个实例上训练和评估我们的模型(我们使用 Amazon AWS),因为这从运行我们的系统中解开了平台细节。上面描述的 Docker 镜像方法和 Amazon AWS 巧妙地结合在一起实现了这种抽象。

将数据存储在中央位置

数据管理是深度学习系统不可或缺的一部分。我们将数据和注释存储在中央存储库中(AWS S3 存储桶),并使用脚本在本地同步数据,这样我们的应用程序、作业和开发人员就可以访问最新的数据。作业总是使用干净的数据副本运行,我们认为下载数据所花的时间是值得的;这让我们确信使用了正确的训练和测试数据。

将重量文件存储在中央位置

我们将权重文件存储在一个中心位置,如果需要启动推理服务器或评估作业,可以将它们提取出来。当训练作业产生了模型的改进版本时,权重文件被更新。集中存储权重文件可确保乔布斯和开发人员能够轻松访问最新的模型。

将超参数配置存储在中央位置

我们将用于训练和评估的超参数存储(更改)在配置文件中。这可以防止这些参数分散在源代码中。我们使用一个中心位置来存储这些配置文件,以便作业和开发人员可以访问它们。

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

Jenkins training job

将培训和评估整合到工作中

我们使用 Jenkins 自动化服务器将培训和评估整合到工作中。这些作业获取最新的 Docker 图像、数据和注释,并将在 Docker 容器中运行培训或评估。Docker 容器具有附加的卷,在评估的情况下,这些卷指向数据、注释和模型文件。

训练工作完成后,将生成一个权重文件,如果该文件符合模型的 KPI,则可以存储该文件。

这项工作将把所有需要的知识和数据整合到脚本中,任何人都将能够可靠地训练或评估模型,而不需要理解模型的复杂性。

但是,我们会存档注释文件、配置文件和生成的重量文件,以便可以重现作业结果。

使用 PyCharm 的远程开发特性

当开发人员可以使用集成开发环境(IDE)时,效率会更高。有时,开发人员可能需要在 GPU 上测试和调试源代码和模型,而这通常无法在他们的开发机器上直接获得。在 GPU 上运行代码的同时结合使用 IDE 的一种方法是在一台有 GPU 的机器上启动 Docker 容器,然后使用 PyCharm 的特性让运行远程解释器。与将源代码上传到远程服务器并为调试添加日志记录语句相比,远程解释器大大减少了往返时间。

使用测试自动化

如上所述,对于深度学习系统来说,编写有效且高效的自动化测试比传统软件系统更难。我们确实使用 pytest 框架为深度学习系统编写了自动化测试,但没有像我们为传统软件系统所做的那样广泛。

我们专注于测试数据输入和重要的算法。我们也为训练和评估编写测试,但仅限于代码能流畅运行的程度。我们不会检查一次完整的训练运行是否产生了正确的结果,因为这太耗费时间了。相反,我们编写一个自动化测试,在一个非常小的数据集上运行一到两个时期,然后我们检查输出指标是否产生,但不断言它们的值。

我们的测试自动化工作的结果是我们的代码库更容易理解,并且实现更改需要更少的努力。

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

Photo by Miguel A. Amutio on Unsplash

测量可维护性度量

一个软件系统需要维护,才能适应不断变化的需求和环境,深度学习系统也不例外。系统的可维护性越高,修改和扩展系统就越容易。我们使用bettercodehub.com来检查 10 个软件工程指导方针,并在系统偏离轨道时通知我们。与代码违规工具相比,我们更喜欢这个工具,因为它允许我们专注于重要的可维护性准则,而不是处理像 PyLint 这样的工具将报告的大量违规。

结论

深度学习是组织 IT 工具箱中相对较新的一项内容。它部分源于传统的软件开发,部分源于数据科学。考虑到深度学习仍处于起步阶段,标准工程实践尚未建立也就不足为奇了。然而,深度学习软件的开发是软件工程的一个组成部分,我们必须从现代软件工程的原则中获得灵感,作为改进深度学习软件工程的起点。

上面列出的实践使我们的深度学习模型开发过程更加健壮和可重复,并为深度学习实践者和软件工程师之间的合作创造了一个共同的基础。这个过程并不完美,因为没有一个过程是完美的,我们一直在寻找改进我们目前工作方法的方法。

可靠编程:单一责任原则

原文:https://towardsdatascience.com/solid-programming-part-1-single-responsibility-principle-efca5e7c2a87?source=collection_archive---------19-----------------------

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

坚实的原则是软件工程中最有价值的原则之一。它们允许编写干净、可伸缩且易于扩展的代码。在这一系列的文章中,我将解释每一个原则是什么,以及为什么应用它是重要的。

有些人认为 SOLID 只适用于 OOP,而实际上它的大部分原理可以用于任何范式。

实线中的“s”代表单责任。很多程序员新手的错误就是写复杂的函数和做很多事情的类。然而,根据单一责任原则,一个模块、一个类或一个函数必须只做一件事。换句话说,他们必须只有一个责任。这样代码更健壮,更容易调试、阅读和重用。

让我们来看看这个函数,它将一个单词和一个文件路径作为参数,并返回该单词在文本中出现的次数与单词总数的比率。

def percentage_of_word(search, file):
    search = search.lower()
    content = open(file, "r").read()
    words = content.split()
    number_of_words = len(words)
    occurrences = 0
    for word in words:
        if word.lower() == search:
            occurrences += 1
    return occurrences/number_of_words

该代码在一个函数中做许多事情:读取文件,计算总字数,单词出现的次数,然后返回比率。

如果我们想遵循单一责任原则,我们可以用下面的代码来代替它:

def read_localfile(file):
    '''Read file'''

    return open(file, "r").read()

def number_of_words(content):
    '''Count number of words in a file'''

    return len(content.split())

def count_word_occurrences(word, content):
    '''Count number of word occurrences in a file'''

    counter = 0
    for e in content.split():
        if word.lower() == e.lower():
            counter += 1
    return counter

def percentage_of_word(word, content):
    '''Calculate ratio of number of word occurrences to number of    
       all words in a text'''

    total_words = number_of_words(content)
    word_occurrences = count_word_occurrences(word, content)
    return word_occurrences/total_words

def percentage_of_word_in_localfile(word, file):
    '''Calculate ratio of number of word occurrences to number
       of all words in a text file'''

    content = read_localfile(file)
    return percentage_of_word(word, content)

现在每个函数只做一件事。第一个读取文件。第二个计算总字数。有一个函数可以计算一个单词在文本中出现的次数。另一个函数计算单词出现的次数与单词总数的比率。如果要得到这个比率,我们更愿意传递文件路径而不是文本作为参数,有一个专门的函数。

那么,以这种方式重组代码,我们能得到什么呢?

  • 这些功能很容易重用,并且可以根据任务进行混合,从而使代码很容易扩展。例如,如果我们想要计算包含在 AWS S3 桶而不是本地文件中的文本中的单词的频率,我们只需要编写一个新函数read_s3,其余的代码无需修改就可以工作。
  • 代号是。没有重复的代码,所以如果我们需要修改其中一个函数,我们只需要在一个地方做。
  • 代码干净、有条理,非常容易阅读和理解
  • 我们可以分别为每个函数编写测试,这样就更容易调试代码了。你可以在这里检查这些功能的测试。

GitHub 中的代码

这篇文章中的代码和测试可以在 GitHub 中找到:
https://github.com/AnnaLara/SOLID_blogposts

原载于 2019 年 9 月 21 日https://dev . to

已解决:一个 DbContext 不能将多个 DbSet 指向同一个对象

原文:https://towardsdatascience.com/solved-one-dbcontext-cant-point-to-multiple-dbset-to-the-same-object-a7231a72ff1d?source=collection_archive---------17-----------------------

在本指南中,我们将解决实体框架不允许我们解决的一个主要问题

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

Photo by Olav Ahrens Røtne on Unsplash

问题是

最近我在做一个项目,需要我创建多个表,其中每个表包含相同数量的相同数据类型的列,即每个表必须遵循相同的结构。众所周知,实体框架 6 期望我们用不同的名字创建单独的模型(类),所以从开发人员的角度来看,用不同的名字多次创建相同的模型并不是一个好方法,当我们同时考虑维护时,这是如此的无聊和复杂。

让我们来看看下面的代码摘录

从给定的代码中可以看出,我创建了一个名为 CommanEntity 的类,它包含两个属性,即 idname ,然后我在 MyDbContext 中继承了 DbContext 类,最后创建了两个显然名称不同的表对象。所以当你运行上面的代码时,你会得到异常。现在我们来看一下解决方案。

我想我们大多数人会认为这是一个非常简单和常见的问题,我们希望他们能提供简单的解决方案,但他们提供的解决方案非常复杂和冗长,所以我们不想深入讨论。我们将用魔法解决它。

神奇的戏法

首先,我创建了名为 GetTable() 的用户定义方法,并将表名作为我们之前创建的参数传递,然后创建了 DbSet 对象作为通用模型。最后我调用了 First() 方法,用简单的 Sql 命令作为参数,在 MyDbContext 对象上使用表名,就这样。

结论

我们已经解决了 entity framework 6 的问题,其中在 DbSet 对象上用不同的名称创建多个表是不受官方支持的。

解决数据科学挑战——可视化方法

原文:https://towardsdatascience.com/solving-a-data-science-challenge-the-visual-way-355cfabcb1c5?source=collection_archive---------14-----------------------

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

对于视觉学习者来说

在这篇文章中,我将向您展示一些使用 Foium 的很酷的地理空间可视化,包括时变制图,以及在 fo ium 地图上叠加数据宁滨,以便更深入地了解您的地理空间数据。这篇文章可以作为地理空间数据探索性分析的指南。

我在这里试图回答的主要问题是“对于一个城市的零售商来说,最理想的位置是哪里?”我做了一些假设来给这个问题提供一些背景,但事实上这与为客户做的实际研究相差不远。

  1. 假设零售商实际上是某种仓库
  2. 我们在整个城市有大量的 GPS 数据点,这些数据点是我们车队每天访问的目的地

数据

正如我提到的,我们在城市里有很多 GPS 数据点。她的是快照

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

GPS data showing lat, long of each data point as well as the the data & time

为了让这个更有趣,我找到了一个列出卡尔加里所有街区的数据集,也就是这个城市:)。我们将使用这些数据来收集每个社区中最常见的场馆的一些信息,这将有助于我们将它们分成一组簇。我们的假设是,与拥有更多咖啡店或公园的街区相比,拥有更多建筑或家具店的街区更适合作为仓库,这表明这是一个住宅区。

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

Calgary community data listing all the neighborhoods. Author of this data set has already labeled each neighborhood but since we are bunch of bad ass folks, we’d like to ignore them for now and find label each neighborhood ourselves.

好了,无聊的事情说够了。下面是你如何为我们的 GPS 数据制作一个漂亮的热图。多田…

图表

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

代码

# Add a column with ones, then calculate sum and generate the heat
sliceDF[‘count’] = 1 
# create map of Calgary using latitude and longitude values
base_heatmap = folium.Map(location=[calgLat, calgLng], zoom_start=10)
# Just adding a marker for fun
folium.Marker((lat,lng), popup=”label”).add_to(base_heatmap)
HeatMap(data=sliceDF[[‘Lat’, ‘Lng’, ‘count’]].groupby([‘Lat’, ‘Lng’]).sum().reset_index().values.tolist(), radius=8, max_zoom=4).add_to(base_heatmap)
# If you want to save the map 
base_heatmap.save(outfile= “truckheatMap.html”)
# To show the map in jupyter
base_heatmap

上面的热图实际上并没有显示出准确的情况,因为我们是在综合所有的数据点,而不考虑时间。为了更好地了解我们的舰队大部分时间在哪里,我们需要以某种方式将时间纳入其中。这篇文章漂亮的动画标题就是一种方法。观察在城市中行驶的车队可以发现他们花费更多时间的区域。所以让我们使用酷的叶子制作动画…

图表

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

代码

# Creating list of hours that we need to slice by to generate the time variant map
df_hour_list = []
for hour in sliceDF.Hour.sort_values().unique():
    df_hour_list.append(sliceDF.loc[sliceDF.Hour == hour, ['Lat', 'Lng', 'count']].groupby(['Lat', 'Lng']).sum().reset_index().values.tolist())base_heattimemap = folium.Map(location=[latitude, longitude], zoom_start=11)
HeatMapWithTime(df_hour_list, radius=8, gradient={0.2: 'blue', 0.4: 'lime', 0.6: 'orange', 1: 'red'}, min_opacity=0.8, max_opacity=1, use_local_extrema=True).add_to(base_heattimemap)

base_heattimemap

现在,这一切都很好,但这不是一种量化的方法。我们仍然需要直观地追逐这些点,并猜测最终哪些区域比其他区域更密集。如果我们有一个基于密度的图,使用网格并显示每个细胞的相对密度,会怎么样?好的,你猜对了。

图表

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

代码

# Used a def so that if you wish to add interactivity you can do that easily later on.
def plot(min_hour,max_hour,n):
    #boundaries of the main rectangle
    upper_right = [51.1741,-113.8925]
    lower_left = [50.8672,-114.2715]

    # Creating a grid of nxn from the given cordinate corners     
    grid = get_geojson_grid(upper_right, lower_left , n)
    # Holds number of points that fall in each cell & time window if provided
    counts_array = []

    # Adding the total number of visits to each cell
    for box in grid:
        # get the corners for each cell
        upper_right = box["properties"]["upper_right"]
        lower_left = box["properties"]["lower_left"]# check to make sure it's in the box and between the time window if time window is given 
        mask = ((sliceDF.Lat <= upper_right[1]) & (sliceDF.Lat >= lower_left[1]) &
            (sliceDF.Lng <= upper_right[0]) & (sliceDF.Lng >= lower_left[0]) &
            (sliceDF.Hour >= min_hour) & (sliceDF.Hour <= max_hour))# Number of points that fall in the cell and meet the condition 
        counts_array.append(len(sliceDF[mask]))# creating a base map 
    m = folium.Map(zoom_start = 10, location=[latitude, longitude])# Add GeoJson to map
    for i, geo_json in enumerate(grid):
        relativeCount = counts_array[i]*100/4345
        color = plt.cm.YlGn(relativeCount)
        color = mpl.colors.to_hex(color)
        gj = folium.GeoJson(geo_json,
                style_function=lambda feature, color=color: {
                    'fillColor': color,
                    'color':"gray",
                    'weight': 0.5,
                    'dashArray': '6,6',
                    'fillOpacity': 0.8,
                })
        m.add_child(gj)

    colormap = branca.colormap.linear.YlGn_09.scale(0, 1)
    colormap = colormap.to_step(index=[0, 0.3, 0.6, 0.8 , 1])
    colormap.caption = 'Relative density of fleet activity per cell'
    colormap.add_to(m)return m# limiting time window for our data to 8 am - 5 pm and also grid is 20 x 20 
plot(8,17,20)

这篇文章的第二部分旨在向您展示如何使用 Foursquare APIs 来获取一些关于不同邻居的地理空间信息,将邻居分组,并最终组合结果以得出我们的结论。

我在谷歌的 API 上工作了很长时间,后来当我开始研究数据科学时,被介绍到 Foursquare 上,感觉棒极了。所以,对于那些不熟悉 Foursquare 的人,我强烈推荐你去看看。值了。

社区数据如上所示。现在我们忽略作者使用的标签,并假设我们没有它们。我们的目标是自己将这些社区聚集起来,为我们的零售店(仓库)找到一个合适的区域。为此,我们使用 Foursquare explore API,但请随意查看他们的所有 API 列表,它们可能会在您的项目中派上用场。

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

现在,您应该知道如何绘制漂亮的地图,所以让我们使用原始标签从社区数据中制作一个地图,看看发生了什么。

接下来,我们试图为每个街区获取 n 个最常见的场所,并将这些信息输入到 k-means 聚类代码中,以便将街区分组。

要使用 explore Foursquare API 获得一个社区的公共场所列表,您需要做如下事情。

# Using Foursquare's explore API get 10 most common venues around # the latitude, longitude provided within 500 m radius. 
# You'll get the CLIENT_ID, CLIENT_SECRET and VERSION after signing up for Foursquare.(Pay attention to API call limits.)
url = "[https://api.foursquare.com/v2/venues/explore?client_id={}&client_secret={}&v={}&ll={},{}&radius=500&limit=10](https://api.foursquare.com/v2/venues/explore?client_id={}&client_secret={}&v={}&ll={},{}&radius=500&limit=10)".format(CLIENT_ID,CLIENT_SECRET,VERSION,neigh
borhood_lat,neighborhood_lng)# results come back in format of JSON 
results = requests.get(url).json()
results

我们可以把这个扩展到所有的社区。下面的数据框显示了几行结果。

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

Example of data frame including venues with their latitude and longitude

一个热编码

为什么?因为我们有字符串作为每个邻域的标签,需要一种方法来数字化它们,以便我们可以在分类算法中使用它们。“一个热编码”基本上解析您的标签,并为每个标签分配虚拟值,以及为每个标签创建新列,并使用 1 或 0 来确定该行表是否具有该功能。例如,云杉悬崖有咖啡馆,但可能没有健身房等等。下面的片段显示了如何“一次热编码”您的结果:

# one hot encoding
calgary_onehot = pd.get_dummies(calgary_venues[['Venue Category']], prefix="", prefix_sep="")# add neighborhood column back to dataframe
calgary_onehot['Neighbourhood'] = calgary_venues['Neighborhood']# move neighborhood column to the first column
fixed_columns = [calgary_onehot.columns[-1]] + list(calgary_onehot.columns[:-1])
calgary_onehot = calgary_onehot[fixed_columns]print("calgary_onehot shape is " , calgary_onehot.shape)
calgary_onehot.head()

生成的表格如下所示:

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

One hot encoded dataframe

为了更好地了解每个街区的性质,我们可以对这些结果进行分组,并对每个街区最常见的场馆进行罚款。然后,我们可以尝试标注每个邻域,例如,咖啡店和杂货店较多的邻域最有可能是住宅区,而建筑区或工厂较多的邻域可能是工业区。

我们将根据结果创建一个熊猫数据框架,包括每个社区的 10 个最常见的场馆。

num_top_venues = 10
indicators = ['st', 'nd', 'rd']def return_most_common_venues(row, num_top_venues):
    row_categories = row.iloc[1:]
    row_categories_sorted = row_categories.sort_values(ascending=False)
    return row_categories_sorted.index.values[0:num_top_venues]# create columns according to number of top venues
columns = ['Neighborhood']
for ind in np.arange(num_top_venues):
    try:
        columns.append('{}{} Most Common Venue'.format(ind+1, indicators[ind]))
    except:
        columns.append('{}th Most Common Venue'.format(ind+1))# create a new dataframe
neighborhoods_venues_sorted = pd.DataFrame(columns=columns)
neighborhoods_venues_sorted['Neighborhood'] = calgary_grouped['Neighbourhood']
neighborhoods_venues_sorted.rename(columns={'Neighborhood':"NAME"},inplace=True)for ind in np.arange(calgary_grouped.shape[0]):
    neighborhoods_venues_sorted.iloc[ind, 1:] = return_most_common_venues(calgary_grouped.iloc[ind, :], num_top_venues)neighborhoods_venues_sorted.head()

结果是这样的:

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

Common venues per each neighborhood, cropped to fit better here but the code above find the 10 most common venues

聚类邻域

现在,我们正处于根据我们拥有的一个热编码数据帧对我们的邻域进行聚类的阶段。在这种情况下,我使用 Sklearn 包中的 kmeans-clustering,为了能够在稍后将结果与我们社区数据中的原始分类标签进行比较,我选择使用 n=4 作为分类数。

# set number of clusters
kclusters = 4
calgary_grouped_clustering = calgary_grouped.drop('Neighbourhood', 1)
# run k-means clustering
kmeans = KMeans(n_clusters=kclusters, random_state=0).fit(calgary_grouped_clustering)
# check cluster labels generated for each row in the dataframe
neighborhoods_venues_sorted['labels'] = kmeans.labels_
neighborhoods_venues_sorted.head()

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

label column shows the clusters

让我们将我们的结果与包含地理位置的原始数据帧合并,并使用一些选择器绘制一个漂亮的图表,这样我们就可以过滤集群,看看发生了什么。

图表:

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

Clustering results plotted with a filtering control panel

实现这一点的代码:

calgary_merged['labels'] = calgary_merged['labels'].astype(int)map_clusters = folium.Map(location=[latitude, longitude], zoom_start=11)# set color scheme for the clusters
x = np.arange(kclusters)
ys = [i + x + (i*x)**2 for i in range(kclusters)]
colors_array = cm.rainbow(np.linspace(0, 1, len(ys)))
rainbow = [colors.rgb2hex(i) for i in colors_array]for cluster in range(0,kclusters): 
    group = folium.FeatureGroup(name='<span style=\\"color: {0};\\">{1}</span>'.format(rainbow[cluster-1],cluster))
    for lat, lon, poi, label in zip(calgary_merged['latitude'], calgary_merged['longitude'], calgary_merged['CLASS_CODE'], calgary_merged['labels']):
        if int(label) == cluster: 
            label = folium.Popup('ORIG. '+ str(poi) + 'Cluster ' + str(cluster), parse_html=True)
            folium.CircleMarker(
                (lat, lon),
                radius=5,
                popup=label,
                color=rainbow[cluster-1],
                fill=True,
                fill_color=rainbow[cluster-1],
                fill_opacity=0.7).add_to(group)
    group.add_to(map_clusters)folium.map.LayerControl('topright', collapsed=False).add_to(map_clusters)
map_clusters.save(outfile= "map_clusters.html")
map_clusters

将聚类与原始标签进行比较

好吧,一切都很好,那又怎样?这项研究的目的是将聚类与标签进行比较,并尝试确定一个靠近零售店或仓库最小距离中心的合适位置。

因此,让我们根据聚类标签和原始标签进行分组,并查看混淆矩阵。请记住,原始标签不一定是真正的标签,而仅仅是数据集作者的主观标签。因此,这应该会给我们一些想法,关于我们的标签的分布与原始标签相比有多相似,仅此而已。

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

我们发现的最终结果如下所示。红色圆圈包围了中等距离的中心(中间带中心)以及两个被确定为最有可能正在开发或工业的社区(最常见的场所是建筑、大型保留商店)

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

Most ideal area for a mid-size retail store.

结论

来自车队的 GPS 数据和城市社区数据被用来支持这一发现,并形成这一结论的基础。请记住,我试图向您展示如何在不深究太多细节的情况下,快速找到这类问题的近似解决方案。

使用实际路径数据寻找中间中心要复杂得多,建模和寻找更精确答案的下一步可能是使用每个点的相对权重。

参考

[## 地理空间

(开源地理空间 Python)“这是什么?”也称为最小距离的中心,中央中心是一个…

glenbambrick.com](https://glenbambrick.com/tag/median-center/) [## 0.8.3 文件

基于 Python 生态系统的数据优势和库的映射优势。操纵…

python-visualization.github.io](https://python-visualization.github.io/folium/) [## 数据 101s:使用 Folium 在 Python 中进行空间可视化和分析

这是我称之为数据 101 系列的第一篇文章,这个系列的重点是分解如何…

towardsdatascience.com](/data-101s-spatial-visualizations-and-analysis-in-python-with-folium-39730da2adf)

如何教你的电脑识别姓名

原文:https://towardsdatascience.com/solving-an-unsupervised-problem-with-a-supervised-algorithm-df1e36096aba?source=collection_archive---------18-----------------------

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

这篇文章来自一个非常具体的现实生活中的问题,这个问题产生于一个现实生活的数据集,并且通过所描述的方法成功地解决了这个问题。希望这一应用可以作为其他类似案例研究的灵感。

问题是:混淆了名和姓

假设您有一个巨大的数据集(超过 2000 万行),其中包含关于某些人的个人数据。数据集遭遇强重复问题,因为数据来自不同的来源。此外,唯一的 id(如社会保险号)很少出现,这使得重复数据删除变得困难。

在这种情况下,唯一可行的方法是概率记录链接:一组能够量化数据集的两行或多行被引用到同一个人的概率的方法。当然,名和姓是记录关联的基本特征

在这个设置中,您会注意到在行中发现一个人的姓和名被调换的情况并不少见(错误率约为 3%),如下表的第三行所示:

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

为什么会这样?因为收集数据的方式不同。数据输入一直是由人类进行的,人类会犯错误。

显然,这种现象会严重影响概率记录链接。因此,我们的目标是检测这样的错误,并通过转换姓名来修改它们。

考虑到标签不可用且无法获得(由于时间/资金限制),我们如何解决该问题?

让我们假设标签存在

让我们假设每行都有一个标签。如果存在这样的标签,它可以采用下列值之一:

  • ‘正确’:如果人的名字出现在“姓名”列,而人的姓氏出现在“姓氏”列
  • “错误”:如果这个人的名和姓被错误地交换了

(这里我们不考虑打字错误或任何其他类型的错误)

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

如果我们真的有标签,我们会怎么做?

朴素贝叶斯是一个很好的起点。这种算法通常用作文本分类的基线,因为它可以轻松处理许多级别(在我们的例子中,有几千个可能的字符串)并且高度可伸缩。

该问题的简单朴素贝叶斯分类器的数学公式如下:

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

朴素贝叶斯模仿人类思考的方式(针对一些简单的问题)。的确,是什么推理过程让我们相信 Name=‘Smith’/Surname='Will '很可能是数据录入错误?因为——基于我们对世界的了解——我们知道:

  • P(‘Smith’ =姓名|正确)=低
  • P(‘Will’ =姓氏|正确)=低

因此,我们隐含地计算:

  • p(正确| ‘史密斯’ =姓名,‘威尔’ =姓氏)=非常低

发明标签

现在我们有一种机器学习方法可以帮助我们解决这个问题。唯一缺少的是标签。所以问题是:我们如何获得标签?

提示是:数据集高度不平衡。因此,即使存在错误,记录在大多数情况下也是正确的。因此,直觉是:如果我们认为记录都是正确的,我们就很少会出错。

假设观察结果都是正确的(错误的)假设不会造成太大的伤害,因为:

  • 错误很少,所以经验概率不会受到它们太多的影响,因此它将接近真实概率,
  • 这些错误并不取决于具体的名字或姓氏。事实上,没有理由认为某些名字或姓氏比其他名字或姓氏更容易被交换。

对于上面看到的例子,这相当于制造一个总是“正确”的标签。

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

我知道这看起来很疯狂,但是坚持住。如果所有的观察都被标记为正确,那么上面看到的公式可以归结为:

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

其中:

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

因此,我们现在能够计算将朴素贝叶斯应用于手头问题所需的每个量。

数据

我们将使用模拟数据集,以便我们能够量化结果的好坏。

用于产生数据的基本事实由来自美国人口的统计数据提供:

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

Ground truth

前两列( distrib_firstnamedistrib_lastname )分别包含名字或姓氏的任何字符串的相对计数。这些列中的每一列总计为 1。

最后两列( proba_firstnameproba_lastname )包含每个字符串作为名字或姓氏出现的概率。每行的这两列之和等于 1。

然后,通过对名字和姓氏进行随机采样,并考虑 distrib_firstnamedistrib_lastname,获得数据集。 数据集由 100 万行组成。错误率 (名字和姓氏已经被交换的行的百分比)是 3% ,这意味着 30,000 行。

这是一个数据集预览。

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

当然,我们有最后一列(也就是标签),只是因为这是一个模拟数据集。但是,我们永远不会使用它,除了性能测量。

应用朴素贝叶斯

下一步是计算每个可能的字符串成为名字或姓氏的概率。基于我们在前面的段落中所看到的,一切都归结为简单地计算一个字符串作为名字或姓氏出现的次数。

我们只是做了一个额外的假设:如果一个字符串在整个数据集中出现的次数少于 10 次,我们将赋予它 50%的概率。

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

Empirical probability

现在我们可以计算数据集的每一行实际上是正确的概率。使用上面看到的公式,我们得到:

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

例如,第一行的概率如下获得:

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

现在我们有了一个新的列,称为 proba_correct ,它为每一行分配一个正确的概率,我们只需要选择一个概率阈值:低于该水平的观察将被视为错误

我们如何选择阈值?

由于这是一个任意的选择,它取决于几个方面,其中最主要的是假阳性和假阴性的成本。无论如何,看看分布总是一个好主意。

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

Empirical cumulative distribution of P(Correct | Name, Surname)

在我们的例子中,因为我们知道错误的发生率在 3%左右,我们将选择第 3 个百分位数 proba_correct ,它等于 0.0394921

在最初的实际问题中,我们没有标签,因此评估我们模型性能的唯一方法是对结果进行定性检查。

然而,由于我们使用了模拟数据,我们有能力计算输出质量的定量测量。例如,通过所选阈值获得的混淆矩阵为:

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

Confusion matrix

因此,精度等于 99.8248 % 。记住原始数据集的准确性是 97% ,这是一个非常强的结果,特别是考虑到模型是如此简单和可解释。

混淆矩阵意味着我们有 875 个假阳性和 877 个假阴性,总共 1752 个错误。出于好奇,我们可以看看其中的一些:

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

Errors (type I and type II)

事实上,即使是人类操作员也很难正确分类这些案例,从而确认我们工作的整体价值。

使用设计冲刺在四天内解决大挑战

原文:https://towardsdatascience.com/solving-big-challenges-in-four-days-using-a-design-sprint-3ad468bf91df?source=collection_archive---------16-----------------------

为期 4 天的黑客马拉松,推动团队通过形成和创造新想法、构建新产品或现有产品/功能的原型,然后与真实用户一起测试和验证这些概念来解决重大挑战。设计冲刺将几个月的工作压缩到一周,有助于节省资金。

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

Photo courtesy of AJ&Smart

这个概念

使用设计冲刺过程有助于测试一个新的想法、功能、产品或服务是否值得花时间和精力去开发和向公众介绍。因此,设计冲刺是在你投入时间和精力构建新想法之前验证新想法的最快方式,而不是在你需要等到发布后的投入数月和数千美元来检查客户的反应。

设计冲刺是一个在 4 天内解决大问题和验证新想法的循序渐进的过程。— AJ&Smart

在 sprint 期间,sprint 团队应用设计思维方法来解决业务挑战/问题。因此,公司或企业所有者可以提高向目标受众推出新功能的成功率,在这些目标受众中,大多数客户的需求都得到了满足和考虑。

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

The sprint gives teams a shortcut to learning without building and launching. (source: GV.com)

在做出任何昂贵的承诺之前,你可以快进到未来,看看你的成品和客户的反应。—GV.com

该过程

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

的第一天 ( 团队研讨会),sprint 团队与个人一起定义挑战和目标,然后找出如何提出一个解决方案,称为“概念”,一个想法的三帧图像表示。

第二 ( 团队研讨会)上,对第一天提出的所有概念进行投票,并决定一个方向。它是关于决定原型的挑战。然后,sprint 团队为获胜的概念创建一个详细的故事板,详细概述用户可能如何体验这个概念。

在**第三天,**sprint 团队必须将零件组装在一起,然后创建并构建一个原型;这个原型完全基于故事板。当团队在构建原型的时候,他们中的一个人应该在第二天招募真实的用户来测试原型。

在**第四天,**进行用户测试,然后在总结报告中总结用户测试反馈,以调整最终概念。总结报告包括原型的成功和挑战的详细分类。它还包括公司明确的后续行动步骤。

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

Adapted and Inspired by the new Design Sprint 2.0 at AJ&Smart

接下来,我们将通过一个 7 人团队进行设计冲刺的例子,他们应该同意一个问题,决定一个要尝试的解决方案,然后构建一个简单的测试,通过用真正的测试人员测试原型来验证该解决方案是否能解决问题。

澄清:

在开始举例之前,我想澄清一些要点:

  • 示例中的原始故事和场景基于 AJ&Smart 创建的一个示例。我的大部分作品和便利贴都是由 AJ & Smart 举办的研讨会改编的笔记和灵感。
  • 这不是关于如何进行或促进设计冲刺的指南或详细说明;这仅仅是每天成果的简要介绍,用来说明概念的过程和设计冲刺的力量。
  • 阿里的洗衣店只是一个例子。网站是我编辑修改的草稿,不会被分享或发表。
  • 本设计冲刺示例中提及的所有名称和人物均属虚构。任何与真人、活人或死人的相似之处,纯属巧合。

设计冲刺团队

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

第一天

这一切都是为了开始设计冲刺,通过分享知识和经验,与团队进行 360 度介绍,了解冲刺团队想要解决的挑战或问题,为一周的工作选择目标,并了解团队的目标方向。

第一天很重要,因为它为冲刺周开辟了道路。当 sprint 团队开会,主持人采访专家时,团队会在白天和下午做一些事情。

业务和挑战

**商家:**阿里的洗衣店

服务:提供各种洗衣服务。其中一项服务提供了全套服务,客户可以使用网站或应用程序来完成一项服务:
你订购>我们收取>我们清洗&清洁>我们送货

**问题:**人们认为这家企业只提供商务衬衫的干洗服务。此外,客户忘记在送货时间回家。

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

The Landing Page

第一步

当专家们谈论时,整个团队将会倾听并写下 HMW 便利贴,“我们该如何……”通过重新表述他们在便利贴上谈论的挑战/问题。这里的重点是关注数量,我们需要尽可能多的 HMW 有不同的观点和不同的挑战框架。

35–45 分钟
5–10 分钟每个
2 个红点,除了决定者得到 4 个点。

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

第二步

这里的目标是就一个长期目标达成一致,一个超级乐观的两年目标。这一切都是为了找到企业两年后的理想定位。sprint 团队的每个人都将在便利贴上写一句话,包括“**两年后……”**关于业务的未来,当然也非常乐观。

然后,短跑队用红点、除了决胜局得到一个大的绿点在 2 年后的时间便利贴上投票。每个人将投票选出他/她认为最清晰、最鼓舞人心的目标。一句话,一个陈述,作为一个 2 年的目标得到了大多数的投票,这将使 sprint 团队走上正轨。

10-20 分钟
1 张便利贴
1 个红点,除了决定者得到 1 个绿点

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

第三步

这里是 sprint 团队集思广益和单独合作的地方。每个人单独提出 1-3 个悲观的问题,“我们能不能…”,关于可能会阻止业务实现 2 年目标的事情。

然后,冲刺团队使用红点、除了决定者得到一个大的绿点来对他们认为最需要回答的前 3 个问题冲刺问题进行投票。

25-30 分钟
每人一张便利贴
每人一个红点,除了决定者得到一个绿点

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

第四步

到目前为止,该团队创建了 HMWs,陈述了主要挑战、业务未来的长期目标以及三个关于可能阻止公司实现其目标的事情的 sprint 问题。在这里,sprint 团队将绘制一张地图来帮助选择目标,这是 sprint 团队可以在本周剩余时间内解决的挑战。

为了确定一个有价值的目标,sprint 团队将拥有最多选票(点)的 HMW 一个接一个地放在地图上,看看它们在客户如何使用产品或服务的系统中的位置。因此,团队可以在剩下的冲刺阶段找到一个需要关注的领域。

然后,通过一点讨论,sprint 团队选择一个好的地方来提出或者测试新的解决方案。应该是大部分 HMW 聚集的区域。

30-45 分钟
1 冲刺地图
1-2 圈围绕选定的区域——由决定者决定

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

第五步

在这里,一切都与灵感有关;sprint 团队收集了许多公司、初创公司或任何组织的外部例子,这些公司、初创公司或任何组织都面临着类似于 sprint 团队试图解决的挑战。它向 sprint 团队展示了解决问题的方法。他们将受到其他解决方案的启发,每个人都在网上搜索真实的例子,并通过制作照明演示便利贴与团队分享发现。

为了确定一个有价值的目标,sprint 团队将拥有最多选票(点)的 HMW 一个接一个地放在地图上,看看它们在客户如何使用产品或服务的系统中的位置。因此,团队可以在剩下的冲刺阶段找到一个需要关注的领域。

然后,通过一点讨论,sprint 团队选择一个好的地方来提出或者测试新的解决方案。应该是大部分 HMW 聚集的区域。

25-30 分钟
每场 1-3 次灯光演示

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

第六步

在理解了挑战并选择了关注的目标后,sprint 团队通过将想法具体化来完成四部分草图

1.记笔记:写单词让思想形成。每个人写下并收集他们迄今为止在便利贴上收集的所有信息,包括但不限于 2 年目标、冲刺问题、照明演示等。没有新的东西要添加,只是收集笔记以帮助形成想法。

2.想法:私下里,sprint 团队的每个人都创造出反映他们笔记的视觉效果。这里的目标是将这些笔记转化为视觉形式。

3.疯狂八:超越最初的想法,为一个你想进一步追求和探索的有希望的想法画八张草图。这里的目标是用不同的方式画一个想法八次。

  1. 3 步概念:在这里,sprint 团队通过创建一个三面板故事板,将他们的想法组织成一个清晰的故事。一个概念,或一个故事,应该包括一个吸引人的标题和匿名,同时使其不言自明,并使用文字来说明想法。

然后,通过一点讨论,sprint 团队选择一个好的地方来提出或者测试新的解决方案。应该是大部分 HMW 聚集的区域。

1-1:30 小时
每个故事 1 个

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

Example of a Four-Part Sketch. (Photo courtesy of AJ&Smart)

第二天

这是所有关于批评每个解决方案,或概念,并帮助决策者做出好的选择。因此,sprint 团队创建了一种简单的方法来测试所选择的解决方案,这种方法最有可能实现团队的长期目标。在第二天,sprint 团队将专注于验证这个概念或解决方案想法是否能够解决达成一致的挑战。然后,重点将是让团队对概念是什么以及如何让用户接受这个想法有一个清晰的愿景。

第一步

现在是概念投票的时候了。sprint 团队会默默地阅读和回顾第一天结束时产生的每个概念,然后投票,点数不限。

sprint 团队使用红点对草图(概念)进行投票,选择最有影响力的一个,并回答可能阻止团队解决问题和实现 2 年目标的 sprint 问题。

这一步将创建一个热图,在那里投票给我们一个提示,sprint 团队的意见在哪里下降。

10–20 分钟
红点无限制

第二步

在讨论了最热门的概念并填写了缺少的目标以获得一个完整、完美的概念后,将进行投票* 投票,sprint 团队的每个人将同时进行同步投票,以选择最佳想法。sprint 团队告知决策者他们对最佳解决方案的看法。

除了决定者,sprint 团队使用较大的红点和他们的首字母来投票选出最好的想法,他们最终最喜欢的概念。决策者在 sprint 将要原型化和测试的概念上放置一个带星号的大绿点。

20–25 分钟
每分钟一个大红点,除了决胜局得到一个带星星的大绿点

***** 民意测验是“一种非官方投票。它被用来表达对某一问题的普遍看法

第三步

现在,sprint 团队已经同意了一个最终的概念,在发布之前用真实用户进行验证和测试。这是关于为原型准备一个包含 6 个步骤的用户测试流程。同样,要点不是构建一个完整的产品或功能,而是用一个简单的原型(测试)来验证和测试想法(解决方案或概念)。

sprint 团队将一步一步地用 6 个步骤创建一个简单的故事,从一个现实的切入点开始,以一个理想的结尾结束,测试用户是否真的会这样做。所有的步骤都基于所选择的概念。

sprint 团队使用红点、除了决定者得到一个大绿点、**、**对他们认为最露骨的故事的用户测试流程进行投票。决策者制定最终的测试流程,用真实用户进行测试。

35–45 分钟
1 个用户测试流程每个
1 个红点,除了决定者得到 1 个绿点

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

Photo courtesy of AJ&Smart

第四步

是时候绘制故事板了,它精确地说明和翻译了所选用户测试流程中的每一步,而没有添加任何不必要的东西或任何全新的想法。

故事板的目的是当 sprint 团队开始构建原型时,不要对原型有任何未解决的问题。但是,要知道,这一切都是为了打一个赌;没有什么是 100%确定的。

当 sprint 团队在为最终的故事板整理东西时,团队中的一个人应该开始根据他们的目标受众招募五个用户。例如,如果团队正在寻找一个广泛的目标,脸书广告或 Twitter 广告,或者如果他们正在寻找一个具体的目标,LinkedIn 广告。

2–2:30 小时
1 整个团队的故事板

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

Example of the Storyboard. (Photo courtesy of AJ&Smart)

第三天

今天是原型日。制作原型的主要目的是获得 sprint 问题的答案,这些问题可能会阻止理想解决方案解决主要挑战。因此,sprint 团队将在第二天结束时准确地获取故事板中创建的内容,并使其对用户来说足够真实;如果是登录页面(营销),创建包含所有所需信息的页面;如果是有形产品,例如咖啡豆,根据故事板中的决策,将咖啡豆包装成向客户销售的样子。

第一步

对原型来说只是一天;因此,专注于重要的事情是至关重要的。sprint 团队需要通过标记故事板中明确必须完成的 2 或 3 个关键部分来区分工作的优先级。

确定工作的优先顺序后,sprint 团队一起分配任务以确认谁负责什么任务。但是,应该有一个人全面负责原型的建立,并在一天结束时做好准备。

10- 20 分钟

第二步

在这里,一切都应该准备好开始构建原型。sprint 团队将从他们选择的 2 或 3 个关键部分开始,然后是故事板的下一部分。

与此同时,团队中的一个人应该与将亲自或实时测试原型的用户确认约会。

8-10 小时

第四天

在这一天,从设计冲刺开始的所有事情都汇集在一起。sprint 团队从一个巨大的挑战开始,然后创建了一个有希望的解决方案来克服问题,同时瞄准一个长期目标,最后构建了一个现实的原型来验证该解决方案是否能解决问题。是时候从真实的人那里得到真实的反馈,以评估长期目标和冲刺题的方向是否正确。

第一步

在对测试人员进行资格鉴定和安排测试之后,sprint 团队,最多 2 个人,准备一次访问一个用户。在采访用户之前,sprint 团队应该确认任务,审查原型,建立一个实时流,等等。

团队的其他成员应该准备一个反馈板来总结每次面试时的所有笔记,要么确认要点(正反馈),要么误解(负反馈)。—用不同颜色的便利贴。

20-30 分钟

第二步

是时候进行面试了,一次一个,整个 sprint 团队一起观察和学习。

6-7 小时

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

Example of the Feedback Board. (Photo courtesy of AJ&Smart)

结论

冲刺做好之后,冲刺团队需要把所有的反馈都拿过来总结一下,回顾一下长期目标和冲刺的问题,然后决定冲刺之后如何跟进。所有这些都被报告并格式化为最终的总结报告,其中包括基于反馈结果的下一步详细建议。这是一个很好的参考,可以记录在冲刺之前、之中和之后所做的一切。

这一切都始于:

经营: 阿里的洗衣店

问题: 人们认为商家只提供商务衬衫的干洗服务。此外,客户忘记在送货时间回家。

而且,在找到解决问题的方案之前,我们设定了一个长期目标:

长期目标: 成为每周必不可少的洗衣服务,比家里欠一台洗衣机更方便。

但是,我们发现一些陷阱会阻止我们达到目标:

陷阱(冲刺题): - 能不能让我们的接送系统不那么死板?
-我们能替代对洗衣机的需求吗?
-能不能说清楚我们不只是干洗服务?

所以,我们需要一个公司,一个真实的例子,一个经历过类似情况的公司:

灯光演示(外部示例): 懈怠

然后,我们制定解决方案,帮助我们克服陷阱,实现目标:

解决方案: -重新设计登陆页面
-突出显示其他服务
-在衬衫与其他衣服搭配时增加折扣

最后,基于有助于解决问题和克服陷阱解决方案(概念)创建了原型,用真实用户验证了原型,并在最终的总结报告中报告了反馈意见和详细建议。

sprint 团队可以做一个迭代周,在那里他们可以使用所有的结果、反馈、修改等等。从第一周开始。sprint 团队专注于根据建议调整原型。同样,sprint 的主要目标是避免投入数月和数千美元来分析客户对提交解决方案以解决重大挑战的反应。

求解验证码——机器学习与在线服务

原文:https://towardsdatascience.com/solving-captchas-machine-learning-vs-online-services-3596ad6f0137?source=collection_archive---------13-----------------------

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

机器学习在验证码求解领域已经走了多远?

机器学习现在已经不仅仅是一个时髦词了。随着大量的问题被 ML 解决,验证码破解只是问题的另一个分支。通过研究一些与卷积神经网络相关的问题,我们发现在这个领域还有很大的改进空间。用户还不接受这种精确度。让我们详细了解一下,为了解决这个问题,我们必须提供哪些服务,哪些服务是最好的。

什么是验证码?

验证码对网络用户来说不再是一个陌生的术语。它是许多网站上添加的烦人的人工验证检查。区分计算机和人类的全自动公共图灵测试的首字母缩写。验证码可以定义为一种计算机程序,用于区分人类和机器,以防止网站上的任何类型的非法活动。验证码概念的基础假设是,只有人类才能通过这个测试,而机器人或自动化脚本将会失败。

为什么我们需要破解验证码?

现在,人们使用自动验证码解决不同的用例,其中一些是非法的,而另一些是合法的目的。垃圾邮件制造者使用验证码解析来提取用户的电子邮件地址,以便能够生成尽可能多的垃圾邮件。合法的例子是,一个新的客户或商业伙伴加入了你,并需要访问你的应用程序编程接口(API ),由于一些安全问题或滥用它可能引起的问题,API 还没有准备好或不能共享。因此,我们只剩下使用自动化脚本绕过验证码。

有不同类型的验证码,基于文本的验证码,基于图像的验证码,验证码和数学验证码。解决一个问题有时会变得很有挑战性,因为随着定期更新,CAPTCHA 和 reCAPTCHA 中使用的技术变得越来越智能。

破解验证码的流行方法

以下是可供用户解决验证码和 reCAPTCHA 的常用验证码解决方法:

  1. **OCR(光学字符识别)**启用的机器人——这种特殊的方法使用光学字符识别(OCR)技术自动解决验证码。像 Ocrad、tesseract 这样的工具可以解决验证码问题,但是准确率非常低。
  2. 机器学习——使用计算机视觉、卷积神经网络,以及像 Keras、tensorflow 这样的 python 框架和库。我们可以训练深度卷积神经网络模型来找到验证码图像中的字母和数字。
  3. 在线验证码解答服务 —这项服务有人工工作人员随时在线解答验证码。当您发送验证码求解请求时,该服务会将其转发给解答者,解答者破解该请求并返回答案。

基于 OCR 的解决方案性能分析

以下是关于每种产品性能的一些统计数据和指标:

虽然 OCR 是解决大量琐碎验证码的经济有效的解决方案,但它无法提供所需的准确性。在 Google 发布 ReCaptcha V3 之后,基于 OCR 的解决方案变得越来越少。因此,启用 OCR 的机器人不是为了破解谷歌、脸书或 Twitter 等巨头使用的验证码而构建的。这将需要装备更好的验证码解决方案。

基于 OCR 的解决方案可以正确破解 1/3 的琐碎验证码。

基于最大似然法的性能分析

让我们看看基于机器学习的解决方案是如何工作的:

一个基于 ML 的解决方案采用 OpenCV 在图像中寻找轮廓,检测连续区域。使用阈值技术对图像进行预处理。所有的图像都转换成黑白的。我们使用 OpenCV findContour()函数将验证码图像分解成不同的字母。经过处理的图像现在只是单个的字母和数字。这然后被馈送到 CNN 模型来训练它。你训练过的 CNN 模型已经准备好解决真正的验证码了。

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

CNN architecture to predict CAPTCHAs from https://www.researchgate.net/publication/301620459_CAPTCHA_Recognition_with_Active_Deep_Learning

对于所有基于文本的验证码,这种解决方案的准确性比 OCR 解决方案好得多。这种解决方案也有很多缺点,只解决了一种特定的问题,谷歌一直在更新他们的 reCAPTCHA 生成算法。最后一次更新似乎是有史以来影响我们服务的最好的 ReCaptcha 更新:当自动化解决方案要么完全停止工作,要么开始非常缓慢地工作时,普通用户从未感觉到任何事情。

该模型使用正确和随机样本以及 1⁰⁵测试图像进行 1⁰⁴迭代训练,以下是其平均准确率约为 60%的表现

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

https://www.researchgate.net/publication/301620459_CAPTCHA_Recognition_with_Active_Deep_Learning

因此,如果您的用例是解决一种具有相当基本复杂性的验证码,您可以很好地利用这样一个经过训练的 ML 模型。一个比 OCR 更好的验证码解决方案,但仍然需要覆盖很多领域才能达到保证其准确性的阶段。

在线验证码解答服务

在线验证码解决服务是目前为止解决这个问题的最好方法。跟上谷歌 reCAPTCHA 的所有更新,他们提供了 99%的无可挑剔的准确性。

为什么在线反验证码服务比其他方法表现得更好?

根据到目前为止进行的研究和开发,基于 OCR 和 ML 的解决方案有许多缺点。他们只能解决琐碎的验证码,准确性不高。在这方面,有几点需要考虑:

  • 更高百分比的正确答案(对于非常复杂的验证码,OCR 给出了极高水平的错误答案;更不用说某些种类的验证码根本无法用 OCR 解决,至少目前是这样)
  • 连续完美的工作,没有任何中断,快速适应新增加的复杂性。
  • 成本效益高,资源有限,维护成本低,因为没有软件或硬件问题;所有你需要的是互联网连接,通过反验证码服务的 API 发送简单的请求。

在线解决服务的大玩家

现在我们知道了解决验证码的更好的技术,我们想在所有反验证码服务中选择最好的一个。一些服务提供高精度的解决方案、自动化的 API 支持,以及对我们请求的快速响应。我们有像 2captcha、Imagetyperz、CaptchaSniper 等组织。

2CAPTCHA 是我遇到的最好的服务之一。凭借超快的响应时间和准确性,他们提供无缝服务。这是我们用来绕过验证码的。

这就是为什么 2captcha 在同时代人中占优势的原因:

  • 高速解决方案,图形和文本验证码 17 秒,ReCaptcha 约 23 秒
  • 为所有流行的编程语言提供支持,包括它们现成库的全面文档。
  • 高准确度(根据验证码类型高达 99%)
  • 任何不正确的答案都将退款
  • 能够解决大量的验证码(每分钟超过 10,000)。

结论

卷积神经网络(CNN)已经学会了如何绕过最简单类型的验证码,这导致验证码的积极发展。当然,ANN 会努力适应这些变化,验证码会变得更加复杂——这场竞赛永远不会结束。这就是为什么涉及真实工作者的在线反验证码服务将暂时领先于这些解决方案。

用深度神经网络解决经典的无监督学习问题

原文:https://towardsdatascience.com/solving-classic-unsupervised-learning-problems-with-deep-neural-networks-768adb892201?source=collection_archive---------12-----------------------

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

3D embeddings of high dimensional data using PowerSFA

这篇文章讨论并总结了我的研究小组最近的两篇论文的思想: 通过神经估计互信息学习基于梯度的 ICA 基于梯度的慢特征分析和谱嵌入训练

最近几年,已经提出了许多不同的无监督学习方法。无监督学习方法对数据进行汇总或转换,从而增强一些所需的属性。这些特性通常很容易通过分析获得,但是当在随机优化(例如神经网络)框架中工作时更难实施。

归纳偏差

在创建模型或定义方法之前,需要做一些基础工作。我们对数据或模型做了什么假设?我们如何知道我们最终得到的模型是好的,我们所说的好的到底是什么意思?

每个模型都预装了一套*归纳偏差。*支持向量机旨在最大化类别之间的间隔,较短的决策树优于较长的决策树,例如,机器学习之外,一个著名的归纳偏差是科学中的奥卡姆剃刀(最简单的解决方案最有可能是正确的。)以及它的工程表弟,KISS 原理(保持简单,笨蛋!).

注:这在深度学习的书中被称为 正则化策略 而不是归纳偏差,但是我把“正则化”和用来减轻过拟合的东西联系在一起。虽然我们在这里不做推论,但我选择称之为用于指导学习的一般先验为归纳偏差。费伦茨·胡斯萨尔在他的 博客 中使用了这个术语,我现在也这样称呼它。

激发了一些归纳偏见

我们可能想用独立特征来描述事物。特征只是数据的附加属性,可以直接从数据中发现。比如一张照片中黑色像素的数量,你在一盘棋中的物质优势等等。对于(统计上)独立的特征来说,意味着对一个特征的了解并不能告诉你关于另一个特征的任何事情。

为什么我们希望特性是独立的?人们很容易忽视独立特征的重要性,因为认为世界由独立的部分组成是很自然的。我喜欢这个场景:

作为一个例子,想象如下:一种被称为 grue 的语言,具有以下两个概念(即,单词):“Grue”:白天是绿色的,但是晚上是蓝色的,以及“bleen”:白天是蓝色的,但是晚上是绿色的。现在,使用 grue 语言,描述一个蓝眼睛的人会非常复杂,因为你必须说:这个人的眼睛在晚上是 Grue,但在白天是 bleen。
——斯滕索尔

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

Describing Gru’s eyes using the “Grue” language is gruesome work.

我们可以看到,颜色和时间的概念在 grue 语言中并不是独立的(有些东西不能同时是“Grue”和“bleen ”),使用从属术语描述世界会引入许多不必要的复杂性。

我们可能想要描述我们世界的另一种方式是根据**慢速特征。**一个缓慢的特性并不是对它的抨击,而是强调它随时间缓慢变化。这是一种鼓励模型确定哪些元素在缓慢变化的具体方式,即使它们是由快速变化的组件组成的。例如,想象一个电影场景,摄像机正在轻轻地放大一张脸。即使我们感觉到没有什么发生(因为感知特征变化非常慢),像素级的值变化非常快。

让我们慢慢开始

慢速特征可以通过慢速特征分析 (SFA)找到。重复一下,这不是一个缓慢的“特征分析”,而是一种发现数据缓慢变化的特征的方法。这些缓慢的特征是通过解决优化问题找到的:

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

简单地说,我们希望找到随时间变化尽可能慢的术语来描述我们观察到的现象。约束(2)-(4)对它们施加零均值、单位方差和去相关。这有助于我们避免退化的解决方案(任何常数函数都可以轻松地解决(1)),并确保我们不会以冗余的特征结束。

在实践中,期望值被样本值代替,我们将经验风险最小化。SFA 按照以下思路解析地解决了这个问题:

  1. 对原始数据应用非线性函数。
  2. 球形数据满足(2)-(4)
  3. 计算球形数据的时间导数
  4. 使用 PCA 找到球形数据变化最小的方向。
  5. 通过将球形数据投影到对应于最低特征值的特征向量上来获得慢特征

这种方法已经被证明是我们视觉系统许多方面的精确模型。这种方法的一个局限是,非线性需要手动选取,这就提出了一个问题:以端到端的方式学习整个过程是否有利于提取更慢、更有意义的特征?

这正是我们在工作中所做的:基于梯度的慢速特征分析和光谱嵌入的训练(将在 ACML 2019 中呈现)。我们训练了一个深度神经网络来解决旋转物体视频的 SFA 优化问题。这可以简单地通过使用(1)作为损失函数来训练网络来完成,但是约束需要通过网络架构来实施。

关于滚圆的一些话

如果特征的数据集 X 的协方差矩阵等于单位矩阵,也就是说,如果每个特征不相关并且方差为 1,则称该数据集是球形的。数据可以通过乘以白化矩阵 W 进行变换,使得 WX = Y 具有单位对角协方差。

我们如何在神经网络中实现这一点?一种简单的方法是在损失函数中加入一种正则项,将输出的协方差矩阵限制在单位矩阵附近。这将在最小化目标函数和实施约束之间引入一种折衷,而它们的实施是不可协商的。为此,我们为 Keras 创建了一个可区分的球形层。通过在倒数第二层中执行球形化,所要做的就是最大化球形化信号的慢度。

可微分球形化

现在,可以用各种方法分析找到白化矩阵,例如用 PCA 白化。如果我们有带有协方差矩阵σ的零均值数据,我们可以执行特征分解并得到σ=uλuᵀ(其中σ的特征向量在 U 中,相应的特征值排列在λ的对角线上)。这给了我们美白基质的成分(1/√D)Uᵀ)。这可以使用*幂迭代、*以微分方式完成,如下迭代公式

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

会收敛到 C 的最大特征向量。一百次(计算快速)迭代就足够了,并且从 C 中减去特征向量

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

然后找到第二大的,依此类推,直到我们完成并得到我们的球形矩阵:

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

图形 SFA

既然我们有了深入学习 SFA 的所有要素,我们就可以更进一步。不是仅仅最小化在时间上相邻的数据点的表示之间的距离,我们可以使用一般的相似性函数,并促使对于先验已知的相似数据点的表示是相似的。例如,考虑 NORB 数据集:

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

“This database […] contains images of 50 toys belonging to 5 generic categories: four-legged animals, human figures, airplanes, trucks, and cars. The objects were imaged by two cameras under 6 lighting conditions, 9 elevations (30 to 70 degrees every 5 degrees), and 18 azimuths (0 to 340 every 20 degrees).” — source

球状可视化显示了相机角度如何连接不同的数据点。如果我们将每个数据点与它们的 4 个邻居(上、下、左、右)连接,那么我们可以最小化损失函数

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

r is 1 if data points i and j are connected, otherwise it is 0

得到一个本质上完美的数据球形嵌入:

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

Embeddings of a data set with images of an airplane toy from different viewpoints that differ in the height and rotation of the camera. The rotation angle of the viewpoint is color-coded on the left sphere and the height angle is color-coded on the right one.

请注意,与拉普拉斯特征映射等方法不同,这适用于样本外点!

独立特征

记住如果 P(A∩B) = P(A) P(B)随机变量 A 和 B 是独立的。学习数据独立特征的最著名算法是独立成分分析(ICA)。

在 ICA 中,假设我们的数据 X 是统计独立源 S 的线性混合,即 X = WS 其中 W 是混合矩阵。目标是对这个混合矩阵求逆,以得到源。这著名地解决了鸡尾酒会问题,我们有重叠对话的声音文件,我们可以分开。

通过最大化它们的非高斯性(你不想在这里知道,但是由于中心极限定理,随机变量的混合比每一项都更高斯)或者通过最小化每个分量之间的互信息来检索源,这是本文剩余部分的重点。

考虑变量 A 和 B 的交互信息:

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

This KL divergence term measures the distance between P(A∩B) and P(A)·P(B)

它衡量的是当你观察一个变量时,你对另一个变量了解了多少。右边是它们的联合分布和边际乘积之间的 KL 散度。A 和 B 的互信息为 0 意味着它们是独立的,因为 KL 散度测量概率分布之间的距离。由于 KL 散度是通过(通常)难以处理的积分来定义的,我们需要使用其他方法来估计它。

E(X) = S 表示我们的参数化向量值函数,以提取包含在向量 S 中的独立源。为了使输出在统计上独立,我们希望惩罚每个输出和所有其他输出之间的高互信息。关于互信息神经估计器 (MINEs)的工作为神经网络 M 引入了损失函数,以估计一些随机变量之间的互信息的紧下界:

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

-i 索引表示除了 sᵢ.之外的所有 sⱼ’ 的向量左边一项表示联合分布的期望值,右边一项是边缘的期望值。

很明显,我们希望使 M 的这个量最大化,以便对 E. 的输出之间的互信息进行精确估计,但是E——请原谅我的拟人化——希望这个量很小,以便提取独立分量。在一个系统中用一组矛盾的目标优化系统是很好理解的,从经典的期望最大化到 Goodfellow(或 Schmidhuber?)更近的生成性对抗网络。

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

The system learns statistically independent outputs by alternate optimization of an encoder E and a mutual information neural estimator (MINE) network M, parameterized by their respective *θ’*s. The mutual information (MI) loss L (Eq. 2) is minimized for E and maximized M.

包括一个可区分的球形层对于这个方法的工作也是至关重要的。我们假设这一层简化了计算问题,因为统计独立的随机变量必然是不相关的。作为概念验证,我们解决了一个简单的盲源分离问题:

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

Three independent, noisy sources (a) are mixed linearly (b). Our method recovers them © to the same extent as FastICA (d). The code for our solution is available at https://github.com/wiskott-lab/gradient-based-ica/blob/master/bss3.ipynb

训练两个网络,一个用于生成解决方案组件,一个用于估计它们之间的交互信息,效果很好。编码器的每个训练历元之后是 m 的七个训练历元。估计精确的互信息不是必需的,因此对于良好的梯度方向,少量迭代就足够了。

在实践中,我们制作了 K 个估计函数副本,并让每个副本处理一个分量和其余分量之间的互信息的估计。我们发现这比针对每个组件-剩余元组训练 K 个单独的估计器效果更好。以这种方式在估计器之间共享权重的好处表明特征重用在不同的估计器之间是有价值的。

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

It’s all about finding the right balance between the two

总结一下

在这篇文章中,我讨论了我的研究小组最近设计的几个深度无监督学习。它们解决了由慢特征分析 (SFA)以及独立分量分析(ICA)所提出的经典问题。这两种方法都依赖于可区分的白化层来工作,这是在 Keras 中为我们的工作创建的。深度学习的 SFA 方法对于高维图像工作良好,但是深度学习的 ICA 方法仍然仅仅处于概念验证阶段。对于未来,我们将研究无监督或半监督的方法,这些方法有助于基于模型的强化学习的学习环境动力学。

在社交媒体上找到我: GitHubMediumLinkedInredditTwitter

本组网页:https://www . ini . rub . de/research/groups/theory _ of _ neural _ systems/

球状可视化 改编自:王,小韩等,“以自我为中心的视觉对象变换的玩具盒数据集”arXiv 预印本 arXiv:1806.06034 (2018)。

利用多臂 Bandit 解决推荐系统的冷用户问题

原文:https://towardsdatascience.com/solving-cold-user-problem-for-recommendation-system-using-multi-armed-bandit-d36e42fe8d44?source=collection_archive---------2-----------------------

本文全面概述了如何使用 Multi-Armed Bandit 向新用户推荐电影

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

Umm not the cold user we are referring to

作者:Animesh Goyal,Alexander Cathis,Yash Karundia,Prerana Maslekar

简介

在紧张忙碌的工作一天后,你是否经常会觉得接下来我该看什么?至于我——是的,而且不止一次。从网飞到 Prime Video,考虑到现代消费者对个性化内容的巨大需求,构建健壮的电影推荐系统的需求极其重要。

一旦回到家,坐在电视机前似乎是一种徒劳的练习,没有控制力,也不记得我们消费的内容。我们倾向于选择一个智能平台,它能理解我们的口味和偏好,而不只是自动运行。

在这篇文章中,我试图建立一个推荐系统,在最短的时间内向你推荐最好的电影。该推荐系统也可以用于推荐广泛的项目。例如,它可以用来推荐产品、视频、音乐、书籍、新闻、脸书朋友、衣服、Twitter 页面、Android/ios 应用程序、酒店、餐馆、路线等。

推荐系统的类型

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

Types of Recommendation system

现有解决方案

1。基于流行度的推荐系统

顾名思义,基于流行度的推荐系统顺应了这一趋势。它基本上使用了现在流行的东西。例如,如果任何产品通常被每个新用户购买,那么它可能会向刚刚注册的用户推荐该产品。

基于流行度的推荐系统的问题在于,这种方法不能实现个性化,也就是说,即使你知道用户的行为,你也不能相应地推荐项目。

2。基于内容的推荐系统

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

Content-based recommendation system

基于内容的过滤使用该技术来分析一组文档和先前由用户评级的项目描述,然后基于那些评级项目的特征来建立用户兴趣的简档或模型。使用该简档,推荐系统可以过滤出适合用户的建议。

基于内容的推荐系统的问题是,如果内容不包含足够的信息来精确地区分项目,推荐将不会精确地结束

3。基于协作的推荐系统

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

Collaborative based recommendation system

基于协作的推荐系统背后的关键思想是相似的用户分享相同的兴趣,并且相似的项目被用户喜欢。基于协作的推荐系统有两种类型:基于用户的和基于项目的。我们将使用基于用户的过滤过程。

但是这些都无法解决冷用户的问题。

问题—冷启动

那么,什么是冷启动问题呢?这个术语来源于汽车。当天气真的很冷时,发动机的启动会出现问题,但一旦达到最佳工作温度,它就会平稳运行。对于推荐引擎,“冷启动”仅仅意味着环境还不是引擎提供最佳可能结果的最佳条件。我们的目标是尽量缩短加热发动机的时间。冷启动的两个不同类别:产品冷启动和用户冷启动。在这个博客中,我们集中讨论用户冷启动问题。

为了解决这个问题,我们引入了使用多臂土匪的概念

多臂土匪(MAB)

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

Multi-Armed Bandit Problem

多臂土匪问题是一个经典的问题,它模拟了一个代理人(或计划者或中心),该代理人希望最大化其总报酬,同时希望获得新知识(“探索”)并基于现有知识优化他或她的决策(“利用”)。MAB 问题描述了这样一个场景:游戏者面临着探索和剥削之间的权衡,前者乐观地拉动探索较少的手臂以寻找具有更好回报的手臂,后者拉动已知最好的手臂直到当前时刻,以获得最大回报。

MAB 为冷用户

我们的目标是使用不同的 bandit 算法为用户探索/利用最佳推荐。有几种 MAB 算法,每一种都在不同程度上倾向于开发而不是探索。最流行的三种是ε贪婪、Thompson 抽样和置信上限 1 (UCB-1):

1。ε贪心

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

Epsilon Greedy Approach

Epsilon Greedy,顾名思义,是三种 MAB 算法中最贪婪的。在ε贪婪实验中,常数ε(值在 0 和 1 之间)由用户在实验开始前选择。当将联系人分配到活动的不同变量时,随机选择的变量被选择ε次。其余的 1-ε时间,选择已知收益最高的变量。ε越大,该算法越有利于探索。对于我们所有的例子,ε设置为 0.1。

2。置信上限(UCB

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

Upper confidence bound approach

对于活动的每个变体,我们将确定置信上限(UCB ),它代表我们对该变体的可能收益的最高猜测。该算法会将联系人分配给具有最高 UCB 的变量。

每个变量的 UCB 是根据变量的平均收益以及分配给变量的联系数计算的,公式如下:

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

详细描述:https://www.youtube.com/watch?v=RPbtzWgzD9M

3。汤普森采样

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

Thompson Sampling Approach

相比之下,汤普森抽样是一种更有原则的方法,它可以在边际情况下产生更平衡的结果。对于每个变体,我们使用观察到的结果建立真实成功率的概率分布(出于计算原因,最常见的是 beta 分布)。对于每个新联系人,我们从对应于每个变体的 beta 分布中采样一个可能的成功率,并将该联系人分配给具有最大采样成功率的变体。我们观察到的数据点越多,我们对真实的成功率就越有信心,因此,随着我们收集到更多的数据,抽样成功率将越来越有可能接近真实的成功率。

详细描述:https://www.youtube.com/watch?v=p701cYQeqew

方法论

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

Infrastructure for solving MAB cold start problem

我们已经使用了电影镜头数据集来解决包含 4 个文件的 MAB 问题。这些文件被合并并用于协同过滤。

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

Sparse Matrix from User Ratings

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

Matrix after application of Collaborative Filtering and Clustering

从上述步骤中获得聚类后,我们将它们按降序排序,并首先推荐每个聚类中评分最高的项目,这有助于更快地了解用户的偏好。例如,上述矩阵中的对应θ1 将具有等于{i5,i4,i1,i3,i2,i6,i7}的项目排序列表,而对于θ2,我们将具有{i4,i2,i3,i5,i6,i1,i7}。

该方法被应用于向最初是新用户的用户做出推荐,这些新用户保持冷淡,直到他们提供了关于推荐项目的一定量的偏好/反馈。确定用户何时不再冷的阈值可以是不同的。在这篇博客中,我们使用 NDCG 指标(排名列表的大小)测量了 5、10、15、40、100 条推荐后的性能。一旦用户不再感冒,系统就可以切换到个性化预测模型。

奖励功能

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

Reward function

奖励函数被定义为用户提供的反馈与用户提供的最高评级的比率。这样,当一个用户对一个推荐的商品给出较高的反馈时,我们就会有较高的奖励。例如,假设冷用户进入系统并使用 UCB 算法,从θ1 中选择项目 i5。如果用户给出的反馈是 4,那么对于聚类θ1,这部电影的回报将是 4/5 = 0.8。在下一个建议中,如果选择了群集θ2,则选择了项目 i4,并且它收到的反馈为 1,则群集θ2 的奖励为 1/5 = 0.2。此时,聚类θ1 的平均回报为 0.8,聚类θ2 的平均回报为 0.2。下一个建议是从θ1 开始的 i1,θ1 代表此时平均奖励最高的手臂。

评估指标

我们将使用 NDCG(标准化折扣累积收益),它更重视早期的准确推荐,而不是后期的推荐。由于我们专注于对冷用户的推荐,我们重视早期的准确结果。

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

在哪里

DCG(u):目标用户 u 的预测排名的折扣累积收益

DCG∫(u):地面真相

n:结果集中的用户数量

r (u,1):首先推荐给用户 u 的项目的评级(根据用户反馈)

r (u,t):用户对依次推荐的项目的反馈

t:推荐时间

t:排名列表的大小

结果

下表提供了等级规模为 5、10、15、40 和 100 的 NDCG 分数。汤普森的表现一直比贪婪和 UCB 要好。预热时间更短,并且能够快速提供更好的结果。另一方面,UCB 在不同的 N 和 t 值下表现最差

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

NDCG Results for varying rank-size and number of users

嵌入网络

虽然嵌入网络通常用于不同的问题,但我们希望看到它们在冷启动问题上的有效性。嵌入网络是学习特征之间的嵌入的神经网络。有了这些知识,它应该能够填充空值。因此,对于电影镜头数据集,它可以嵌入用户和电影之间的关系,然后可以填充用户没有为电影提供的缺失评级。虽然我们刚刚用协同过滤执行了这项任务,但使用神经网络可以学习复杂的非线性特征。

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

Embedding network

因此,如上所示的嵌入网络可用于填充以下嵌入的缺失值:

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

一般嵌入式网络用于有温暖用户的推荐系统。这样,网络就不必猜测太多。对于热情的用户来说,学习到的关系有望被很好地建立,并且不会发生变化。通过这种设置,嵌入式神经网络可以在密集的数据集上训练一次,学习非常复杂的关系,并给出受过良好教育的建议。然而,我们的问题没有温暖用户的奢侈,导致一个大的数据集。

对于冷启动问题,我们必须向没有提供反馈的用户提供好的建议。本质上,他们的数据是空的,对于这个用户没有任何可以推断的关系。对于这个问题,使用嵌入网络的简单解决方案可以是首先给出一个随机的推荐,并且对于每个后续的推荐:接受反馈,重新训练,对预测的评级进行排序,并且返回最高的预测推荐。然而,这将导致疯狂的计算成本和延迟的推荐,这可能给用户体验带来灾难性的后果。

我们的想法是,即使嵌入网络不知道冷用户,用户和项目之间的数据集关系的网络知识仍然可以提供一些价值。因此,我们希望分析性能,如果对于每个用户请求,我们考虑多个建议。这些推荐可以来自全局推荐器,例如随机、全局平均或最受欢迎。它们也可能来自 MAB 算法,如汤普森算法、ε-贪婪算法和 UCB 算法。我们可以首先让嵌入式网络估计这些推荐中哪一个得分最高,而不是直接反馈单个算法推荐。最高的推荐将被提供给用户。根据计算和时间限制,网络可以根据用户的反馈进行重新训练。

这个想法在一个玩具例子中得到了验证,这个例子重用了前面章节中描述的 MAB 评估框架。由于时间限制,嵌入式网络几乎没有接受任何训练(5 个时期),也没有超参数调整。它也没有根据用户反馈进行再培训。对于每个用户请求,它会考虑 3 个随机推荐,并给用户一个它认为得分最高的。然而,在这个 15 次试验和 5 个随机用户的小测试中,它给出了比 UCB 算法更好的结果。必须注意,严格使用随机建议会从下面所示的有限测试中获得更好的结果:

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

虽然这些结果并不是突破性的,但应该指出的是,进一步的实验有机会展示更好的性能。更多的训练,实际上调整超参数,根据用户反馈重新训练网络,以及使用其他采样推荐器(而不仅仅是随机的)都有可能极大地提高性能。

结论和未来工作

尽管由于缺乏对用户的了解,冷启动用户在推荐系统中造成了独特的问题,但 MAB 在推荐电影方面做得相当好,并且随着数据输入不断发展。总而言之,我们的贡献是:

多臂土匪问题模型选择的形式化

使用 UCB、汤姆逊抽样和ε贪婪算法,这是一种为没有先验边信息的用户进行推荐的有效方法

基于电影镜头数据集的 NDCG 实证评估

推荐系统中嵌入网络的有效性评估

对于未来的工作,我们可以尝试

使用不同的 bandit 算法作为武器,正如我们看到的,epsilon-greedy 在一开始执行得更好,而 Thompson 在更多次迭代中执行得更好

扩展这个实现以在每次迭代中提供多个推荐——目前,最好的电影被反复推荐

我们依靠 NDCG 评分来评估我们的方法,主要是因为我们在调查推荐质量。总的来说,它表现出很高的准确性,但我们可能会检查其他指标,以确保公平的评估

调整嵌入网络的超参数,根据用户反馈重新训练网络,以及使用其他采样推荐器(而不仅仅是随机的)

非常感谢您的阅读,我们希望您能从项目中学到一些东西!

请随意查看:

Github 资源库本帖

我的其他中等帖子

我的 Linkedin 个人资料

参考文献

https://medium . com/datadriveninvestor/how-to-build-a-recommender-system-RS-616 c 988d 64 b 2

https://hal.inria.fr/hal-01517967/document

http://klerisson.github.io/papers/umap2017.pdf

https://www . analyticsvidhya . com/blog/2018/06/comprehensive-guide-recommendation-engine-python/

https://towards data science . com/variable-implementations-of-collaborative-filtering-100385 c 6 dfe 0

https://medium . com/the-andela-way/foundations-of-machine-learning-singular-value-decomposition-SVD-162 AC 796 c 27d

https://sebastianraschka . com/Articles/2014 _ PCA _ step _ by _ step . html

https://medium . com/datadriveninvestor/how-to-build-a-recommender-system-RS-616 c 988d 64 b 2

https://medium . com/@ iliazaitsev/how-to-implementation-a-recommendation-system with-deep-learning-and-py torch-2d 40476590 F9

https://github . com/dev for fu/py torch _ playground/blob/master/movie lens . ipynb

https://nipunbatra.github.io/blog/2017/recommend-keras.html

https://towards data science . com/neural-network-embeddings-explained-4d 028 E6 f 0526

https://medium . com/hey car/neural-network-embeddings-from-inception-to-simple-35 e 36 CB 0 c 173

为运营决策解决机器学习的“最后一英里问题”

原文:https://towardsdatascience.com/solving-machine-learnings-last-mile-problem-for-operational-decisions-65e9f44d82b?source=collection_archive---------25-----------------------

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

Photo by Denny Luan on Unsplash

如果没有被使用,一个分析性的洞察力或训练过的模型就没有什么价值。

事实上,数据科学价值主张的一个核心原则是,机器学习(ML)模型可以在业务环境中进行解释和应用。洞察、分类和预测需要影响决策者,触及一线员工,或者嵌入业务应用。然而,许多机器学习项目在这方面失败了。这是数据科学版本的最后一英里问题,也是更广泛的“操作化”ML 的主要障碍之一。

当试图将 ML 用于运营决策时,即在运营应用和业务流程中嵌入基于 ML 的模型时,最后一英里问题可以细分为:

  • 解释模型响应以做出决策
  • 创造信任、透明度和组织变革
  • 管理数据科学、IT 和业务的生命周期和资产

本文将关注突出显示的第一项,这是关于我们如何调用 ML 模型,解释响应,并将响应与业务策略相结合,以便做出决策。

今天,有一个令人印象深刻的机器学习软件和硬件堆栈,支持端到端的数据收集,数据管道的创建,特征工程。REST APIs 背后的模型训练、结果可视化、模型监控和模型部署。这个过程非常简单,可以这样来说明:

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

Machine Learning Pipeline vs The Last Mile

迄今为止,还没有充分考虑模型“部署”后,即“最后一英里”会发生什么。在 REST API 背后部署机器学习模型是一个很好的起点,但这是旅程的开始,而不是结束。为了使基于 ML 的预测在业务应用或流程中有用,您需要弄清楚何时调用模型,如何解释响应,以及如何将响应转换为可操作的决策。

调用模型

首先,您需要决定何时可以安全地使用 ML 模型做出的预测。通常一个模型在它被训练的数据范围之外是不可靠的。例如,一个针对年龄在 25 岁到 65 岁之间的司机的汽车保险风险模型,在预测年轻司机的风险方面可能不够稳健。这也适用于功能组合。一个用城市地区年轻司机的足够数据训练的模型不一定能提供关于农村年轻司机的可靠预测。保护 ML 模型免受未经培训的案例的影响对于保护您的业务至关重要。

这导致需要业务规则来决定什么时候不使用模型,什么时候按原样使用它,以及什么时候使用它并进行一些后验调整。无论您是瞄准新的客户群、推出新产品还是处理新型交易,这种选择都会频繁出现。

第一种选择是一开始忽略这个模型,启动业务,直到你有足够的数据对预测有信心。通常,这意味着依赖于使用人工编写的业务规则或决策表的不太精确的预测。如果这是您在采用 ML 之前使用的,那么在升级时可以方便地保存它们。

在其他情况下,你可以大胆地认为新产品/交易/细分市场与你已经有足够数据的东西足够相似。也许“年轻农村司机的风险=年轻城市司机的风险-5%”是一个比完全没有基于数据的预测更好的风险评估。同样,一些业务规则可以建立这种联系,调用模型并进行调整。

在实践中,对于企业决策来说,几乎所有 ML 模型的调用都会被至少一些业务规则或表所包围,这些规则或表决定了对于每个特定的情况调用什么模型。

调整预测

数据的可用性可能会限制机器学习模型的预测能力。我们可能没有足够的关于我们知道或怀疑会影响预测的特征的数据。在这种情况下,有必要在调用 ML 模型后调整分数或修改分类。

例如,房地产交易的公共数据集在多个国家和地区都可用。法国政府的版本相当全面,包含了 2014 年到 2018 年法国所有的房地产交易。这些数据包括房产位置、房间数量、内部居住空间大小、地块大小等。然而,不包括的是该房产是否有景观、游泳池、内部设施状况和最后一次装修日期。因此,虽然有可能建立一个回归模型来估计房地产的价值,但如果不单独考虑这些额外的参数,它可能会有+/- 20%的误差。一组业务规则或决策表可以很容易地用来上下调整属性值,从而得到更好的预测。

这种情况不是房地产独有的。金融服务中的风险评分、零售中的产品推荐、支付中的欺诈检测等,它们都可以受益于基于实时数据的调整,而这些数据在模型训练时是不可用的。

也许有一天,我们的算法可以获得清晰易懂的每一份数据,但与此同时,我们经常需要对基线预测进行调整。

组合模型

经营企业就是要平衡风险和回报。做出这种判断也延伸到了运营业务决策。例如,相对于客户违约的风险,发放特定贷款的估计利润是多少?如果我们不提供贷款,客户流失的可能性有多大?如果我们阻止信用卡交易,会对客户忠诚度产生什么影响?如果是欺诈,会有什么损失风险?

为了做出运营决策,我们通常需要将一组预测模型和策略规则缝合在一起。例如,在金融服务领域,以下是做出明智决策时需要考虑的典型因素:

  • 风险评分(预测模型或风险表)
  • 资格(政策规则)
  • 生命周期价值(预测模型)
  • 流失分数(预测模型)
  • 定价策略(策略规则)

有时,甚至有必要将多个旨在预测同一事物的模型结合起来,但这些模型是从不同的数据源中获得的。例如,在医疗保健领域,围绕糖尿病存在大量研究,但研究方法的差异——研究时间长度、对照组设计、收集的数据等——使得合并数据和训练单个 ML 模型变得困难。事实上,最好的方法可能是训练和部署多种风险模型,并使用业务规则计算基于被评估患者的加权分数。

实际上,在商业决策中经常使用多个 ML 模型,并结合表达策略的商业规则。决策建模是结合这些预测性和规范性资产的艺术。

应用策略

绝大多数企业决策要么受制于业务政策、行业法规,要么应该遵循“常识”规则。以下是一些例子:

产品推荐

  • 不要推销客户已经有的优惠
  • 不要促销与突出优惠相冲突的优惠
  • 不要促销不必要的高折扣(按客户群/层级)

广告

  • 根据人口统计、地理位置和渠道限制显示哪些广告
  • 不要展示冲突广告或竞争品牌的广告(“品牌安全广告”)
  • 优化广告投放,以满足但不超出广告预算

保险

  • 对以前欺诈客户的索赔实施人工索赔审查
  • 自动支付低价值、低风险的索赔(基于客户细分/层级)

在某些情况下,像这样的业务规则是软偏好而不是硬规则,它们可以通过训练嵌入到 ML 模型中。在其他情况下,这是困难的或不可取的。你如何确保不向特定客户展示竞争广告(最好是跨会话和渠道)?什么样的 ML 反馈机制会阻止模型提供客户已经拥有的产品?你的公司将如何向审计员和代理机构证明你的决定遵守了法规(100%的时间)?

事实是,机器学习是一种概率方法,并不理想地适合遵守确定性的政策和规则。在基于 ML 的预测或分类之后应用业务规则通常会提供更好的一致性和透明度。

结论

机器学习的“纯粹主义”观点可能认为不需要商业政策,或者这种政策可以而且应该从数据中学习。这一学派认为,通过将学习与正确的现实世界结果联系起来,并设计有效的反馈回路(可能包括随机化和 A/B 测试),ML 系统将逐渐学会在没有后验干预的情况下做出正确和最优的决定。

纯粹的“纯 ML”方法可能很适合下棋、识别图像或分类文本。对于企业决策,ML 本身很少是足够的。

在实践中,是通过“用规则应用策略”还是“训练 ML 模型”来实现特定的需求,这是一个具体情况具体分析的问题。对于刚接触机器学习的组织,或者当将 ML 注入到现有的业务流程中时,在 ML 模型之外实施策略要求通常更容易,至少在开始时是这样。

你可能会问,你可以利用什么软件来跨越机器学习的最后一英里?虽然典型的机器学习框架没有扩展到模型部署之外,但还有另一种软件类别填补了 ML 模型和业务应用程序之间的空白。

最常被称为决策管理——或者 Forrester 的“数字决策平台”——这些平台来自业务规则管理系统(BRMS)的时代,但已经发展到关注决策建模和整体执行。这意味着决策管理平台涵盖预测模型、规范的业务规则,并且通常支持运营决策的建模、监控和治理。

格雷格在 IBM 工作,常驻法国。以上文章为个人观点,不代表 IBM 的立场、策略或观点。

求解 DAG 上的最小路径覆盖

原文:https://towardsdatascience.com/solving-minimum-path-cover-on-a-dag-21b16ca11ac0?source=collection_archive---------13-----------------------

我们讨论了一个算法来寻找一个 DAG 上的最小路径覆盖。

介绍

在这个故事中,我们将首先定义图上的最小路径覆盖问题(MPC ),然后将一个虚构的场景建模为 MPC。接下来,我们将分析我们的模型的结构,并将 MPC 简化为某些特殊情况下的最大匹配问题。我们将用解决方案来结束这个故事。

图的 MPC 是具有最小基数的顶点不相交路径的集合,使得这些路径的并集包含图中的所有节点。换句话说,在 MPC 中,我们希望用最少数量的不共享任何顶点的路径覆盖所有节点。这种划分不一定是唯一的。MPC 的应用范围很广,从软件测试到调度[1]。

一个示例场景

让我们定义一个假设的场景如下。假设你受雇于一家管理某城市地铁线路的公司。地铁总共有 4 个站,每个站都可以互相到达。市议会已经决定了车站之间应该进行的运输以及发车时间。因此,你剩下的就是决定你应该购买多少辆火车来实现所有的运输。当然,你想最小化这个数字来最大化公司的利润。

市议会向你提供了交通时刻表,以及从一个车站到另一个车站需要多少小时。这些表格如下:

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

Hours to take to reach from one station to another (left) and time table of desired transports (right).

现在让我们考虑一个解决方案。最坏的情况下,我们可以为每次运输分配一辆列车,购买 7 辆列车。但是,我们可以从表中观察到,一些运输可以由同一列车依次实现,如 T2 和 T1。如果我们最大化这种运输的数量,那么我们可以最小化购买的数量。因此,我们找到了目标函数最大化!

在最好的情况下,每次运输由同一列火车进行,一列火车就足够了。然而,我们可以看到,这是不可能的,因为有运输冲突的时间表,如 T2 和 T3。因此,我们定义了必须满足的约束。现在我们可以把这个问题表述为:

我们如何在完成所有运输的同时,最大化同一列车完成的运输总数?

为了对我们的约束进行建模,让我们为运输构建一个可行性图。在这个图中,我们用一个节点来模拟每一次运输,并画出一条从一次运输到另一次运输的有向边,当且仅当这两次运输可以由同一列火车顺序进行。例如,从 T1 到 T5 将存在有向边,因为火车可以在 6:00 从 S1 出发并在 8:00 到达 S2。然后 13:00 到达 S3,16:00 执行 T3。另一方面,T2 和 T3 不相邻,因为火车不能同时从 S2 和 S3 出发。生成的图表如下:

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

Feasibility graph of given constraints.

在这个图中,一条路径对应于一系列可以由同一列火车依次进行的运输。因此,如果我们找到覆盖所有节点所需的最小路径数,我们就找到了执行所有运输所需的最小列车数。

因此,我们的目标是在构建的可行性图上找到一个 MPC。

解决方案

对于一般的图,寻找一个 MPC 收敛于寻找一个哈密尔顿路径,不幸的是,这使得 MPC 成为一个 NP 难问题。幸运的是,对于有向无环图(Dag ),我们可以通过简化为二部最大匹配在多项式时间内解决 MPC,这可以在多项式时间内解决。

现在让我们检查一下我们的可行性图是否能包含任何圈。我们说过,一条路径对应于同一列车可以进行的一系列运输。对于一个周期的发生,我们应该至少有一对运输 TᵢTⱼ ,这样 Tⱼ 可以在之后进行 TᵢTᵢ 可以在之后 Tⱼ 进行**。但是,如果 Tⱼ 可以在tᵢ*之后进行,则意味着 Tᵢtⱼ之后开始。因此, Tⱼ 无法在** Tᵢ 之后进行,除非我们能时光倒流!*

因此,由于时间限制,我们的可行性图是一个 DAG,我们可以在多项式时间内解决我们的问题。

为了解决这个问题,我们将构造一个辅助图 G ,并在 G 上找到一个最大匹配。为了构造 G ,我们将把原始图的每个节点一分为二。其中一个节点将保留原始节点的输出边,另一个节点将保留输入边。例如,考虑可行性图中的节点 tt 将被一分为二为 t₁t₂ ,我们将从 t₁t 的邻居绘制一条边,而我们将从 tt₂ 的邻居节点绘制边。注意这样的图总是二分的。对于我们的可行性图,G 可以绘制如下。

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

Auxillary graph constructed from the feasibility graph.

寻找最大匹配意味着最小化不匹配节点的数量。如果右边部分的节点在 G 的最大匹配中不匹配,则在列车执行的序列中,在相应的运输之前,不应执行任何运输。这意味着我们需要这样一个节点一列火车。因此,最小化这样的节点相当于最小化所需的列车数量,在 G 上找到最大匹配就解决了我们的问题!

下面我们可以看到 G 的最大匹配,匹配中的边和节点用粗线表示,其余的边用虚线表示。

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

A maximum matching of G

注意,我们保证不存在完全匹配,因为在右边部分总是至少有一个节点没有输入边。该节点对应于最早的运输,因为最早的运输不能在任何其它运输之后进行。因此,总有至少一个不匹配的节点,我们至少需要一列火车。

有了最大匹配,我们可以通过从左到右追踪匹配来构建路径。这些路径对应于应由同一列车执行的运输,以最小化所需列车的数量。对于上图,我们可以追踪路径为{{ T1,T4,T5 },{ T2,T6 },{ T3,T7 }。因此,我们需要至少 3 列火车来完成所有的运输,并在多项式时间内解决我们的问题!

参考

[1]https://www.wikiwand.com/en/Path_cover

我感谢tnaz Ekim在 MPC 上的演讲,让我首先听到了这个问题。

解决妻子的问题“我今天该穿什么?”用人工智能

原文:https://towardsdatascience.com/solving-my-wifes-problem-what-should-i-wear-today-with-ai-9283e6503ec9?source=collection_archive---------13-----------------------

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

faAi, Fashion Assistant Artificial Intelligence

概观

我妻子几乎每天都会问我这个问题。

今天该穿什么?

这是一个很难回答的问题,因为首先我没有时尚感,而白纬玲恰恰相反,她也有时装设计学位。其次,我有一个不好的记忆,记得她在过去几周穿了什么衣服,以便能够为我的回答提供多样性。

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

What should I wear today?

因此,有一天我决定利用周末时间开发一项技术,我认为这项技术可以解决她的问题。

在我开始之前,我想感谢她在这个项目和我所有其他疯狂的项目中给我的所有支持。亲爱的,你是最棒的!

研究

我开始做一些研究,以找出我需要建立什么。我试着把自己放在她的位置,我需要什么信息来决定今天穿什么衣服。

我有什么衣服?(CH)

显然,我需要从我目前拥有的目录中推荐一件衣服。所以我推测这是一个必须的信息。

过去几周我穿了什么?(光盘)

你肯定不想连续几天一遍又一遍地穿同样的衣服。尽管这并不是非常关键,但知道你在过去几周穿了什么将有助于提供更多不同的建议。最重要的是,当你穿那件衣服时,天气和活动的信息对推荐系统也很有用,可以知道哪件衣服适合哪种场合和天气。

今天的天气(W)

不用想,你穿什么会受到当天天气的影响。

事件(E)

当你去参加一个聚会时,你想穿一些有点花哨的衣服,但是如果你要去远足,你想穿一些有点运动的衣服。

综上所述,今天(CTWT)穿的衣服可以用以下功能来描述:

CTWT = Func(CH,CD,W,E)

所有我需要建立的是一个系统,执行这样的功能:)听起来很简单吧?我开始发挥我的想象力,最终在她的衣柜上想象出一个带屏幕的语音助手设备,她可以问“我今天应该穿什么?”并配有推荐衣服照片的回答。更好的是,它将显示她穿那些衣服的样子,以提供更多的视觉背景。它也能够解释这种建议的理由。为什么?这样它就可以回答白纬玲的后续问题“你为什么推荐我?”通常在我推荐之后。

这项技术肯定会涉及很多人工智能。兴奋之余,我开始为这个人工智能寻找一个名字和一个角色,并提出了 faAi。它的发音是“费”,代表时尚助理人工智能。

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

faAi

行动(或活动、袭击)计划

我开始记下我需要执行的任务:

  • 建立一个她每天穿什么的照片日记(CD),用事件和天气标记。
  • 建立她自己的服装照片目录(CH)
  • 制作一个语音助手机器人,安装在她的衣柜上

建立服装目录的一个简单方法是逐一拍下她所有的衣服。而对于日记来说就是每天自拍。然而,作为客户体验和自动化的倡导者,这对我来说是不可以的。我需要一个系统,自动建立她的衣服目录和零努力日记。

经过一番思考,我想出了这个计划。如果我在房子里的某个地方安装一台照相机,自动拍摄她全身的照片,会怎么样?相机应该足够智能,只拍她的照片,而不是我或我的父母或我的姻亲(是的,以防你怀疑,我的父母和姻亲都不时与我们住在一起,幸运的是他们相处得很好)。它还需要能够识别她穿的衣服,将它们存储到衣服日记,只存储唯一的衣服目录。

除了相机,我还需要一个计算设备来执行上述所有的智能。最完美的设备应该是 AWS DeepLens。这是一个支持深度学习的相机,你可以在设备上部署无数的人工智能模型(在边缘)。

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

AWS DeepLens

从这一点上,我开始意识到这将是一个大项目。我肯定需要建立一个人工智能模型,在视频帧中识别人脸和身体,并执行面部识别。如果白纬玲的脸被识别,下一个人工智能模型需要捕捉她的衣服,并执行搜索,如果我们已经在她的目录中添加了这件衣服,否则创建一个新的条目。不管怎样,如果这是一件新的衣服,一个条目也会被添加到衣服日记中,用天气和事件来标记。

为了保持理智,我决定将这个项目分成几个阶段,第一阶段专注于自动建立衣服日记。由于我不需要建立服装目录,我还不需要建立服装识别系统。即使最终目标是在她的衣柜里有一个语音助手,但是我希望在第一阶段完成时,她已经可以使用一些东西。因此,我增加了一个额外的任务来构建一个移动应用程序,她可以用它来浏览她的服装日记,至少可以帮助她决定穿什么。

自动服装日记生成器

我的第一个任务是找到我应该安装这个相机的位置。在她的衣柜里安装相机可能不是一个好主意,因为我真的不想意外曝光我不应该曝光的照片,如果你知道我的意思。除此之外,我只想在她穿着这些衣服出去的时候,把它们加入她的日记。没有必要录下她在家穿着睡衣的样子。

经过一番寻找,我找到了一个完美的地方。在橱柜顶上,直接看到我的前门。好吧,你需要从前门出去。

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

AWS DeepLens’ mounting position

用 AWS DeepLens 检测人和人脸

我的下一个任务是建立一个在我的 AWS DeepLens 中运行的人工智能对象检测模型,它可以检测人和脸的存在和位置。面部识别他们是谁,人裁剪他们的全身图像存储到衣服日记。

我使用 Amazon SageMaker 构建了一个自定义的对象检测模型,并将它们部署到 AWS DeepLens 中。然而,为了让这个博客在一个更高的层次上讲述这个故事,我将在一个单独的博客上发布完整的细节。

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

Face and Person Object Detection running on AWS DeepLens, seen from Project Stream window showing some debugging annotations

AWS DeepLens 附带了一个超级有用的功能,称为项目流,您可以显示和注释视频帧,并在您的网络浏览器上观看它们。这样,我可以很容易地观察我的模型的性能,并绘制一些文本和方框来协助我进行调试。正如你在上面的图片中看到的,我的模型准确地识别出了白纬玲的全身和她的脸。我对准确性很满意。

在正确的位置检测人员

下一个要解决的问题是,只有当人在门区域附近时才触发捕获,这可能表示想要离开房子。然而,下面的示例镜头显示了一个错误的肯定检测,其中一个人只是从前面的起居室走向餐厅。

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

False Positive Detection

查看下面我家的平面图,可以清楚地看到两个红色的箭头,它们指示了导致误报检测的人的行走路径。而我们只想捕捉绿色区域中的人。对此最简单的解决方案是仅当人的边界框的顶部和底部完全在屏幕内时捕捉人。用上面的假阳性情况测试这个逻辑将正确地跳过这个图像,因为边界框的底部在屏幕之外。

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

而下面的肯定情况将触发正确的图像捕获,因为边界框的顶部和底部都完全在屏幕内。

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

Correct Detection

为了确保我已经覆盖了所有可能的假阳性病例,我需要全天运行该系统。首先,我必须完成系统的下一部分,将被检测人的裁剪图像发送到我的图像记录器 S3 桶。这样,我可以在没有我监督的情况下运行系统一天,并在试运行结束时简单地检查桶中的所有图像。

从物联网设备发送图像的最佳方式是通过 MQTT 消息系统,这非常容易做到,尤其是在您创建 AWS DeepLens 项目时提供了很好的示例代码。我只需要添加几行额外的代码,将裁剪后的图像编码成 jpeg 流,然后进行 base64 编码,这样我就可以通过 MQTT 将它作为字符串消息发送出去。

client = greengrasssdk.client('iot-data')
iotTopic = '$aws/things/{}/infer'.format(
            os.environ['AWS_IOT_THING_NAME'])
personImageRaw = cv2.imencode('.jpg', personImage)[1]
personImageStr = base64.b64encode(personImageRaw)
client.publish(topic=iotTopic, payload=personImageStr)

消息将由云中的 MQTT 主题订阅者接收,然后触发我的 lambda 函数对图像进行 base64 解码,并将它们保存到 S3 桶中。从 MQTT 字符串中解码图像非常简单,只需要下面的一行代码。

jpgStream = base64.b64decode(event)

具备了以上所有条件,我运行了一整天的系统,并享受了周末的剩余时间:)

岳母回避

运行该系统一整天后,我的图像记录器显示了许多有趣的图像。一些图像是正确的检测,如下所示,这很好。

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

Positive Detection

看到我的其他家庭成员被记录是意料之中的事,然而其他事情引起了我的注意。有很多我岳母的图像(更确切地说是她的上半身)占据了所有拍摄图像的 95%。

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

Mother in law is making her legendary dumpling

检查下面的原始视频录像日志揭示了原因。

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

Mother in law behind the kitchen bench

显然,她通过了检测逻辑,因为她个人的边界框的顶部和底部部分(由于与厨房长凳的遮挡,只有她的一半身体被检测到)完全在屏幕内。该系统捕捉到了她的许多照片,因为她在厨房里花了很多时间。这将导致该过程进一步进行大量不必要的面部识别,这是不好的。然而,看到她整天被记录的无数照片,让我想起她每天为我们做饭和帮助我们的宝宝有多忙。对我来说,她是世界上最好的婆婆…

好吧,尽管她有多棒,我不希望她的照片在今后的处理过程中占据主导地位。这个问题可以简单地通过引入一个禁区来解决。想法是在排除线的左边部分排除检测(显示为下面的红线)

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

Mother In Law Avoidance Zone

再次运行该系统一整天,显示厨房长椅后面不再有婆婆!

检测合适的人

我的下一个挑战是添加面部识别功能,并且只记录白纬玲或我自己的图像。只是澄清一下,并不是说我需要使用这个系统来推荐我穿的衣服,而是这样我就可以很容易地测试这个系统,而不用一直烦她在镜头前摆姿势。

我真的想在边缘做面部识别,以节省成本。然而,经过进一步的调查,这似乎很难。一个合适的面部识别系统需要大量的 GPU,这会给已经很慢的系统增加大量的处理时间。目前,我的面部/人物检测系统以 1 FPS 的速度运行。任何比这更慢的速度都会降低捕捉的机会。一个更简单的面部识别系统,如这里描述的对我不起作用,因为它只能识别正面脸。

有了以上,我决定在云端做面部识别。我设置了另一个 lambda 函数,当我的图像记录器中有一个新条目时,它将被触发。这个 lambda 函数将调用 AWS Rekognition —面部识别来识别人。如果该人被识别为本人或白纬玲,则创建 Postgres 数据库条目。这个 Postgres 数据库就是我们一直在说的衣服日记。拍摄图像时的时间、温度和天气状况(晴天、雨天、阴天)以及被识别的人的姓名也被存储为条目的一部分。当前的温度和天气是通过给气象局打一个 RSS feed 电话获得的。最后,图像也将被复制到另一个 S3 桶,作为一个公共图像服务器,将通过我的移动应用程序访问。这样,我可以确保只有受限的图像集是公开可用的,将来我甚至可以添加额外的检查,以确保没有敏感图像是公开可用的。

使用 AWS Rekognition 面部识别非常简单。我只需要创建一个包含我希望系统识别的人脸的人脸集合。对于每张脸(我自己和白纬玲),我需要调用 IndexFace 将它们添加到集合中。点击此处了解更多相关信息。检查一张脸是否在集合中就像制作一个名为 l 的 API 一样简单

打造时尚日记 App

这是第一阶段最令人兴奋的部分,因为最终我将能够在移动应用程序上可视化服装日记。我们都是 iPhone 用户,所以手机应用程序必须在 iPhone 上运行。现在有很多方法来构建移动应用程序,比如使用 PhoneGap 这样的 HTML5 框架,Ionic 和 Xamarin 这样的交叉开发框架,或者直接使用 XCode。然而,作为一名 iOS 开发者,我的首选是 XCode。

为了提供对我的 Postgres 服装日记的访问,我使用 lambda 函数构建了一个公共 REST API。用它来构建一个功能性 REST API 是如此简单,这给我留下了深刻的印象。传统上,您将花费大部分开发时间来处理基础设施和部署,例如编写 REST 应用程序框架、URL 路由、部署脚本等,而不是编写实际的 API 代码。如果您需要编写的 API 如此简单,就像我的情况一样,这种情况会更普遍。

最后,下面是整体端到端架构图。

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

faAi architecture diagram

我设法在一天内完成了应用程序和 REST API,包括设计应用程序闪屏和图标:)如下所示的应用程序界面非常简单。一个可滚动的垂直列表,显示记录的白纬玲图像,按日期分组。天气(下雨,多云或晴天)图标和当天的温度是一个额外的好主意。我现在可以说这个系统已经开发完成了!作为一名经验丰富的软件开发人员,我知道下一个明显的步骤是 QA。

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

faAi app

质量保证

我整个星期都在运行这个系统,看起来它在正确地工作。我拍到了白纬玲进出房子的照片,没有一次误报!我还在她的手机上安装了应用程序,这样她就可以开始使用它并给我反馈。

尽管结果很好,但在下一阶段我还需要改进和增加一些东西。

更好的姿势检测

一半的图像是以非理想的姿势拍摄的。例如,当她走向换鞋台时,笨拙地侧着脸,抬起一条腿,抱着我们的孩子,或者穿着盖住她实际穿着的衣服的夹克。我还发现了一些例子,她实际上并没有走出家门,而是穿着睡衣站在门前。faAi 还不够智能,无论姿势的质量如何,只要检测到人脸,它就会拍照。

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

Non ideal pose captured by faAi

对于这个阶段来说,这并不是什么大不了的事情,因为我们的目标是拥有一个移动应用程序,让她可以浏览服装日记。她可以很容易地在脑海中过滤掉那些糟糕的姿势或无关的照片。为了解决这个问题,我需要一个更复杂的系统,我将在未来阶段尝试。目前,最简单的解决办法是让她脱下外套,面对镜头,在她出门或进屋时迅速摆好姿势,这样拍的前几张照片就不错了。

事件检测

这是我在这一阶段没有时间完成的任务,我将在下一阶段处理。了解她为什么要出门也有助于过滤掉不想要的捕捉。例如,当她出去扔垃圾的时候。

这就是现在,我很高兴一个里程碑已经被勾选,但是仍然有更多的挑战等待我去解决,以拥有一个完整的端到端系统。但是什么是没有挑战的生活呢?

阅读这篇博客的续篇,它讲述了我是如何教 faAi 识别布料的。

结合统计学习和机器学习解决回归问题

原文:https://towardsdatascience.com/solving-regression-problems-by-combining-statistical-learning-with-machine-learning-82949f7ac18a?source=collection_archive---------6-----------------------

以 Airbnb 西雅图价格预测为例

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

Photo by Ben Dutton on Unsplash

在数据科学领域,统计学习和机器学习通常被视为两个独立的阵营。第一个阵营的人通常更倾向于理解统计意义,而后者更关心模型预测性能。但实际上,这两种不同的方法在携手解决数据科学问题时是互补的。

大多数数据科学项目分为两大类——回归问题(当目标变量是连续的/数字的)或分类问题(当目标变量是离散的/分类的)。这篇文章将只关注如何一步一步地结合统计学和机器学习来解决回归问题。

线性回归通常是我们在任何数据科学课程中学到的第一个模型。它简单,直接,最好的是它可以产生可解释的系数。后来,我们可能已经学习了许多其他更复杂和更高性能的基于树的算法,如随机森林和梯度推进树等,它们可以解决回归和分类问题,但在功能的基本假设方面具有更大的灵活性和容差。

树族算法是如此之好,以至于它们成为我们的首选模型,但它们在某种程度上让我们变得更懒,因为它们在特征预处理方面需要很少的努力。然而,使用线性回归等基本算法为学习如何选择和处理数据提供了很好的机会,我认为这是一项比运行模型本身更重要的技能。

目标

在这篇文章中,我将指导你使用 Kaggle 的最新版本的 Airbnb 西雅图数据集来完成一个回归项目。它面向具有回归算法基础知识的读者。其目的更多的是说明当您获得一个没有任何明确目标或方向的数据集时的整个工作流程,您需要定义自己感兴趣的问题并找出解决问题的路线图。

该项目的主要问题是:

  1. 使用西雅图个别房源的可用信息预测 Airbnb 房源价格。
  2. 探索影响西雅图 Airbnb 房源价格的重要因素。

像任何典型的数据科学项目一样,我对刚才提出的问题的解决方法将遵循下面的流程图。这是一个遍历所有步骤的迭代过程,而不是一个单向隧道。

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

data science project workflow

数据集概述

首先,我们来看看数据。Kaggle 上有 3 个数据集:

Listing.csv: 包含关于地点、主持人和平均评论分数的属性的综合列表

Calendar.csv: 包括列表 id 以及每天的价格和可用性

Review.csv: 包括列表 id、审阅者 id 和详细注释

对于这个项目,由于我的目标是预测上市价格,我将只使用上市数据集。评论数据集对于情绪分析来预测上市评级非常有用,但我将把这部分留给我未来的帖子。

列表数据中总共有 93 列。用数据帧头调用很难一次检查所有的列,所以我将按数据类型将它们分开,并分块检查。

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

透过柱子,一些东西引起了我的注意。首先,有几个应该是数值的特性目前在“对象”数据类型中,如’周 _ 价格’,‘月 _ 价格’,‘安全 _ 存款’,
,‘清洁 _ 费用’,'额外 _ 人’等。这是他们现在的样子。我将在后面的数据清理步骤中把它们转换成数字。

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

current string format of some numerical features

我还意识到两个特性组可能包含非常相似的信息——一个是关于列表邻域,另一个是关于评论评级。让我们一个一个地检查它们。

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

unique values of some categorical features

看起来“neighbourhood _ cleansed”和“neighborhood”几乎相同,只是后者包含 NaN,而前者不包含。我将放弃“neighborhood”列,而选择“neighbourhood _ cleansed ”,因为后者是一个更干净的版本,这样做不会导致任何信息丢失。

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

NaN count of the neighborhood feature group

对于审核功能组,“审核分数评级”似乎是其他 6 个单独评级类别的加权总和。我认为该功能组中可能存在很强的共线性,因此我可以只使用总体评级来表示组中的其他部分。我想以后验证这个理论。

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

探索性分析

1.1 超级主持人总是比 Airbnb 的普通主持人收视率高吗?超级主机的收费也和普通主机不一样吗?

我想验证的第一个假设是普通主机和超级主机之间评论评级和价格的差异。下面的 violin 图表显示了仅超级主机和普通主机以及所有主机组合之间的评论得分和列表价格分布。

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

评论评分显示了超级主机和普通主机之间的明显区别——大多数超级主机的评分都在 90-100 左右,相比之下,普通主机只有 61%的评分超过 90,这是由于较低评分中的长尾效应。另一方面,价格分布对于两种类型的主机似乎是相同的,除了来自常规主机的一些罕见的极高价格异常值。

1.2 按街坊划分,不同物业类型的挂牌均价是多少?

数据集中的原始属性类型相当分散。我整理了一下,把它们分成 4 大类。从下面的柱状图中,我们可以了解不同社区和不同物业类型的平均挂牌价格的差异。

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

与其他三个房地产群体相比,不同社区的公寓价格差异似乎要小得多。在所有的社区中,市中心和木兰区通常是最受欢迎的房产类型中最贵的——公寓、房子、联排别墅和避孕套。

这张图表也证实了社区和房产类型肯定会对挂牌价格产生影响。

1.3 评审特征组之间是否存在多重共线性?

我将它除以 10,使“review_scores_rating”达到与该组中其他功能相同的 1-10 等级。这是它们的分布是如何相互重叠的。他们看起来都严重右倾。

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

review feature groups histogram

为了进一步检验我的共线性理论,我认为最简单的方法是运行一个简单的线性回归,看看“review_scores_rating”是否可以用 rest 6 review 特征的一个线性方程来表示。

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

显然,答案是肯定的。因此,我可以确信,我可以使用总体评级来表示其他评级,而不会丢失太多信息,并减少线性模型中的多重共线性。

简单的数据清理和功能选择

因为我的目标是预测列表价格并理解普通主机和超级主机之间的区别,所以我只想包括与列表和主机相关的属性。以下是我决定保留的功能。

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

数字特征

正如我们在探索性分析中发现的,一些数字列目前都是字符串格式。下面的那些列应该通过从值中去掉“%”和“$”符号转换成浮点类型。

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

经过一个简单的清理步骤,现在他们看起来像数字。

现在,数字特征已经处理好了,让我们来看看相关热图。

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

显然,热图中有两个主要的相关组。一组是关于设施的列表,比如卧室、浴室的数量,可以容纳的人数等等。我想保留这个组中的所有特征,因为它们都告诉了关于列表本身的基本信息。另一个相关组是关于复习分数的,我们之前已经讨论过了。我决定只保留一个总体评价分数“review_scores_rating ”,并删除其余的评价列。

分类特征

在我对所有分类变量进行虚拟编码并将特征的数量增加三倍之前,我想看看它们在解释标价的可变性方面有多有效,以决定我是否要将它们全部用于模型。这一步是可选的,但我发现当数据集包含许多具有几十个级别的分类特征时,这一步特别有用。

您可能已经从其他关于 Medium 的文章中了解到三种特征选择技术:使用统计测试的过滤方法、使用机器学习算法(如 LASSO 和 Random Forest)的包装方法和嵌入方法。

因为我想测试连续目标变量的分类特征,最简单的统计过滤方法是 ANOVA 测试。对于那些像我一样对哪种统计检验可以用于什么类型的数据感到困惑的人来说,这是一个非常有用的参考。

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

source: Analytics Vindhya

下面的代码遍历数据中的每个分类特征,并根据针对目标变量“价格”的双向 ANOVA 测试计算 F 统计量和 P 值。

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

ANOVA test results for categorical features

F 统计量的定义(AVONA) = 总体均值的组间方差/样本均值的组内方差。

如果 P 值高于 0.05(显著性水平的经验法则)并且 F 统计接近 1,这意味着组内(每个分类水平内)价格的方差与组间(不同分类水平之间)方差相同,因此我们可以说分类特征独立于连续变量(在这种情况下,价格),并且它不具有任何预测能力,因为分类水平之间没有观察到的价格方差。

相反,f 检验统计值越高,分类变量的不同级别之间的平均价格差异越大,分类特征能够解释的价格方差越大,其预测价格的能力就越强。

显然,从上面的 ANOVA 测试结果来看,我们可以首先排除底部的两个特征,因为它们的 P 值太高,不具有统计显著性。同样给定他们的小 F 统计,我们可以得出结论,在两个水平host_is_superhostinstant_bookable之间有非常小的价格变化。

此外,还有两个与neighbourbood相关的特性。从上面的探索性分析可以明显看出,邻里关系会影响挂牌价格。但是由于除了neighborhood_cleansed处于更细粒度的级别之外,它们基本上包含非常相似的信息,所以我想只保留其中的一个。F9 统计给出了一个非常清晰的选择思路。我会留着neighbourhood_group_cleansed,因为它的 F 分更高。

完成要素选择后,让我们看看数据集中缺失的值。

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

count of missing values

有超过 97%的 NaN 值,所以我将放弃它。对于其余的数字特征,我稍后将在机器学习管道中估算 NaN 值,以避免测试集中的数据泄漏。最后一步是将分类特征转换成虚拟变量。现在数据集已经准备好了,让我们直接进入建模。

机器学习

模型 1:原始价格的线性回归

首先,我想从最简单的模型——线性回归开始,看看在不对特征进行任何处理的情况下,基线会是什么样子。

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

我使用方便的回归软件包来获得模型系数 P 值。

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

在没有任何特征标准化的情况下,训练集的调整后的 R 平方约为 0.62。但是如果我们看一下 p 值,几乎所有的 p 值都太大,没有统计学意义。仅有的几个有改进想法的特性<0.05 are “accommodate”, “bedroom”, “bathroom” and “reviews_per_month”. That means only these couple variables contribute to the model performance even if most features have large coefficients.

现在有 51 个特征,不包括目标变量。由于我在一开始就亲自挑选了这些功能,所以我认为与上市价格相关的功能只是基于我的直觉,但我不能确定这是不是真的。为了确保线性模型不会被一些通常会导致过度拟合的不相关特征“分散注意力”,我将对线性回归模型应用正则化,以惩罚大的系数来换取更简单的模型,从而在缺乏足够训练数据的情况下减少方差。

L1 套索正则化具有防止过拟合和特征选择的优点,这是因为其惩罚项的性质倾向于在最小化成本函数 SSE 的过程中将不太相关的特征的系数权重收缩为零。此外,假设我们有一个小数据集(整个数据集中只有 3818 个列表),我还希望在训练期间利用交叉验证来使模型在泛化性能方面更加健壮。

最后但同样重要的是,数据集包含在很大范围内变化的数字要素。所以我需要在训练测试分割和运行模型之间做两个预处理步骤。首先,用中位数填充数值变量中缺失的值。第二,规范价值观。有了 sklearn pipeline,这些连续的步骤可以合二为一。

模式二 : 套索回归原价

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

LASSO regression model pipeline

请注意,这一次我只标准化了数字特征,没有改动虚拟变量。我区别对待它们的原因是,我不仅关心预测的准确性,而且希望以后以直观的方式解释虚拟变量的系数。如果你的目的只是预测,不在乎系数的可解释性,可能就不需要单独对待了。

****M1 模型性能用 R 平方衡量:

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

r 平方是用来衡量拟合优度的。它是模型中自变量解释的因变量方差的比例。

和上次线性回归差别不大。但我对系数更好奇。

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

Lasso regression coefficients

显然,LASSO 已经有效地将一些特征系数推到了零,就像中间的那些。

M1 系数解读

由于训练数据中的所有数字特征都已标准化,因此任何数字特征中的 1 个单位变化都不再是它们的原始比例,而是由标准偏差决定的。我们没有标准化分类变量,所以它们的变化单位是不变的。

因此,我们可以说,如果列表容纳的人数增加 1 个标准差(~ 2 人),列表的价格将平均增加 23 美元,其他一切保持不变。或者,如果评论分数等级增加 1 个标准(100 分中的 6.6),价格将平均上涨 27.5 美元。就分类变量而言,市中心一个房源的平均价格比其他地方的类似房源贵 33 美元。

模型 3 : 套索回归对数转换价格

现在我们来看看目标可变价格的分布。很明显是长尾形状。自然对数变换可以使其服从正态分布。这对于使数据中的模式更易解释和帮助满足推断统计的假设都是有价值的。

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

left: original price, right: log-transformed price

再次运行相同的管道,但这次是在 np.log(y_train)上。

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

M3 车型性能:

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

测试集性能提高了 12%,因此目标变量的对数变换确实有助于预测。

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

M3 系数解读

*我们以这种形式拟合模型:Log(Y) ~ scaled(数值变量)+虚拟变量。对数转换变量的一般解释如下:X 增加 1 个单位将导致(exp(系数)-1)100%。

*由于数值数据是标准化的,1 单位仍然意味着 1 标准差。以“容纳”为例,浴室数量每增加 1 std(约 0.6 个浴室),挂牌价平均会提高 24% ((exp(0.22)-1)100%)。

*图表底部的特征湖城区域与价格负相关程度最高。如果一个列表在湖城地区,价格将比非湖城地区平均低 36% ((exp(-0.45)-1)100%),保持其他一切不变。

关于标准化自变量或因变量背景下的系数解释的更多细节,我推荐阅读这两篇文章第一篇第二篇。两者都非常详细地提供了极好的解释。

模型 4 : 对数转换价格的随机森林回归量

由于线性模型没有产生非常令人满意的 R 平方结果,我想切换到基于树的模型,因为预测值和价格之间可能没有线性关系。

对于基于树的模型,我不需要标准化特征,因为决策树仅基于“信息增益”或“杂质(熵)减少”来决定最佳分割,缩放特征不会对树模型分割产生任何影响。我将在对数转换价格上拟合随机森林回归器,用 GridSearchCV 与以前的模型进行性能比较,以找到其最佳参数。

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

M4 车型性能

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

在相同的对数转换价格下,测试集的 R 平方得分从 LASSO 的 69%提高了 3%。

下面的残差与拟合值图显示了预测价格与实际价格的差距。不幸的是,残差看起来并不是随机分散在蓝线周围的。有些异常值与实际值有很大的误差。

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

M4 随机森林特征重要性

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

随机森林模型发现了一组不同的最重要的特征,特别是房间类型、卧室和浴室是三个主要特征。我们来看看房型是如何影响价格的。

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

列表中的 3 种房型有明确的定价等级,平均价格遵循以下顺序:合租房

最后的想法

在几次尝试不同的模型后,测试集中的 R 平方分数仍然不高于 0.8。我认为这可能是由几个原因造成的,最大的原因是数据样本太小(只有 3000 左右)。用这么小的样本量很难得出一个通用的模式,这也导致了随机森林的训练集中的过度拟合。

解决这个问题的一个方法是获取更多其他城市的 Airbnb 房源数据,以增加数据样本。当收集到足够的数据时,我还可以尝试运行梯度推进树模型以获得更好的预测准确性。

统计学习和机器学习是解决回归问题不可或缺的两个部分。虽然机器学习为我们提供了更复杂的预测模型,但统计测试在特征选择、多重共线性检测以及判断回归系数的统计意义方面非常有用。作为数据科学家,我们应该非常了解双方。

感谢阅读!由于学习从未停止,随着迭代的进行,我将不断更新这篇文章,提供更多的结果。敬请关注。

解决辛普森悖论

原文:https://towardsdatascience.com/solving-simpsons-paradox-e85433c68d03?source=collection_archive---------8-----------------------

偶然的因果推断

理解因果推理中的一个关键玩具例子

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

这是因果推理和数据科学系列文章的第四篇。前一个是“观察不干预”

辛普森悖论就是一个很好的例子。起初,它挑战了我们的直觉,但是如果我们能够适当地剖析它,它给出了许多关于如何处理观察数据(不是通过精心设计的实验获得的数据)的分析的想法。它出现在许多数据分析中。我们将用众所周知的肾结石的例子来说明。这里解释的技术可以在 Pearl 等人的“统计学中的因果推断:初级读本”中找到。

肾结石的例子

在医院里,一位医生正在处理肾结石。她有两种治疗方法,比如 A 和 B。她将两种方法各占一半(A 组 350,B 组 350 ),并测量每种治疗方法的成功率。结果可在下表中找到:

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

显然,治疗 B 是最好的。工作完成了,她可以回家了。但是……等等!她知道她有更多的信息,想看一看,以防万一…她也有宝石的大小,也许这些信息是相关的。然后她想出了这张表:

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

嗯……对于小石头 A 更好,对于大石头 A 更好,但是聚合 B 更好?!搞什么@#*!!

这是怎么回事?

然后她回忆起病人是如何被挑选出来的。一旦新病人来了,她就对他们的结石有了猜测。治疗 A 是进行某种手术,而治疗 B 基本上是给他们吃药。她知道给大结石吃药丸效果更差,所以疑难病例被分配到治疗 a。这个过程使得治疗比较更加困难!

使用图表,我们可以显示如下数据过程

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

Data generation process

大小影响治疗任务和康复的机会。这被称为混淆,因为你不能从恢复的大小来区分治疗的效果。

极端群体分配

为了理解任务如何影响我们的结论,想象一下这两个组成的极端情况:

  1. a 只收到大石块,而 B 只收到小石块
  2. 颠倒过来

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

Case 1

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

Case 2

正如你所看到的,将所有困难的情况分配给 A,会使 A 看起来效率最低,而将所有困难的情况分配给 B,会使 B 看起来效率最低。有道理!

干预

我们要回答的问题如下:如果医院必须选择只有一种治疗,会是哪一种?

正如我们在之前的帖子“观察不是干预”中看到的,这可以用一个图表来表示,这个图表代表我们想要知道的分布。

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

Intervening on treatment

这种分布会对我们给每个人 A 治疗的情况做出反应。对一个变量的干预是通过去除它相对于它的先行变量(它所依赖的那些变量)的依赖性来定义的。因果推断中的主要问题是,我们是否可以仅从数据生成分布中获得信息来对这种新的介入分布进行推断。

调整公式

诀窍如下:如果我们把注意力集中在小结石上,那么所有恢复的效果都可以从治疗中得到解释,所以我们可以测量它的有效性

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

Conditioning on small size stones

我们可以对大石块做同样的事情。但是我们怎么把这两个量结合起来呢?如果大小不影响治疗分配的话,就按照他们被分配的方式。这意味着我们使用结石大小的全球分布,而不是使用治疗分配的分布。

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

Distribution of sizes

正如你所看到的,大小石头的数量相当,而每种处理的大小分布不均匀。

把这个过程写下来我们就得到所谓的调整公式

P(R | A)= P(R |小,A) * P(小)+P(R |大,A) * P(大)

可以看出(虽然不简单),这个公式正是我们要寻找的:计算介入图中的恢复概率,但是只使用从数据生成图中获得的数据。

可以对治疗 B 进行同样的操作,然后比较结果。

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

我们从最初的“更好的 B”3%上升到“更好的 A”7%!!

好吧,那么,让我们总是调整!

没那么快…有些情况下调整会带来错误的结论。在上面的例子中,为了测量治疗的效果,大小变成了一个“嘈杂的东西”,我们想要去除它的影响。现在换个角度思考。想象一下你有某种疾病的治疗方法。此外,你知道(因为你测量它)影响病人的血压。同时,你知道(因为你在职业生涯中见过很多次)血压也影响你康复的机会。在这种情况下,您将以这种方式生成数据

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

现在治疗有直接的方式和间接的方式影响你的恢复。但你对两者都感兴趣!你不想从中去除任何影响。这个想法是,在这种情况下,你不需要应用任何调整,因为直接测量会给你正确的数量。或者等价地,如果你干预治疗(回想一下,这意味着消除对治疗原因的依赖),你会得到同样的图,所以你什么也不用做!

结论

这个简单的例子给了我们关于如何分析观察数据中的因果关系的有力结论。

  1. 数据本身不会说话:直接计算可能会得出错误的结论
  2. 更多的数据并不能解决问题:你可以增加病人的数量,但仍然会得到同样的悖论!
  3. 相关性是不够的:相关性是一个对称函数,而因果性不是。后者具有明确的方向性。
  4. 不同的模型导致不同的结论:根据不同的情况,我们必须应用或不应用调整公式,因此有不同的结论。这只是用图表来论证的!
  5. 图表是一个很好的交流工具:我们已经在"使用图表中看到了!“我们再次确认!

用卷积神经网络解决数独

原文:https://towardsdatascience.com/solving-sudoku-with-convolution-neural-network-keras-655ba4be3b11?source=collection_archive---------3-----------------------

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

Image from Pixabay

很久以前我曾经解过数独。几天前,我想知道我是否可以用卷积神经网络( CNN )来解决这个问题。我知道数独有空间特征,因为它有特殊的数字排列,CNN 擅长提取空间特征。让我们看看这个实验如何进行。

数据收集

我在 Kaggle 上找到了以下数据,里面包含了 100 万个未解和已解的数独游戏。请看看下面的数据。

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

Sudoku Dataset

数据集包含 2 列。列quizzes具有未解决的游戏,列solutions具有各自已解决的游戏。每场比赛由一串 81 个数字代表。下面是一个由字符串转换而来的9x9数独。数字0代表未破游戏中的空白位置。

[[0 0 4 3 0 0 2 0 9]
 [0 0 5 0 0 9 0 0 1]
 [0 7 0 0 6 0 0 4 3]
 [0 0 6 0 0 2 0 8 7]
 [1 9 0 0 0 7 4 0 0]
 [0 5 0 0 8 3 0 0 0]
 [6 0 0 0 0 0 1 0 5]
 [0 0 3 5 0 8 6 9 0]
 [0 4 2 9 1 0 3 0 0]]

数据处理

我们的任务是将未解决的数独输入到神经网络中,并从中获得已解决的数独。这意味着我们必须向网络提供 81 个数字,并且需要从网络获得 81 个输出数字。

我们必须将输入数据(未解决的游戏)转换成一个 3D 数组,因为我们必须将它提供给 CNN。我把每串 81 个数字转换成(9,9,1)的形状。然后,我将输入数据除以9并减去0.5进行归一化。通过这样做,数据变得以零均值为中心,并且在(-0.5 – 0.5)的范围内。神经网络通常使用以零为中心的标准化数据表现更好。

电力网设计

在典型的多类分类中,神经网络输出每个类的分数。然后,我们对最终分数应用 softmax 函数,将它们转换成概率。并且数据被分类到具有最高概率值的类中(参考下图)。

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

Multiclass Classification

但是在数独游戏中,场景是不同的。我们必须为数独游戏中的每个位置获取 81 个数字,而不仅仅是一个。对于每个数字,我们总共有 9 个类,因为一个数字可以在 1 到 9 的范围内。

为了符合这个设计,我们的网络应该输出81x9数字。其中每行代表 81 个数字中的一个,每列代表 9 个类别中的一个。然后,我们可以应用 softmax 并取每行的最大值,这样我们就有 81 个数字被分类到 9 类中的一类。

我为此任务创建了以下简单的网络。网络由 3 个卷积层和一个密集层组成,用于分类。

Sudoku CNN

注意,我正在将密集图层的输出整形为(81, 9)的形状,然后在上面添加一个 softmax 图层。我用sparse_categorical_crossentropy损失和adam优化器编译了这个模型。

因为我们使用的是SCC loss,所以我们不需要提供一个独热编码的目标向量。我们的目标向量形状是(81,1),其中向量元素表示 81 个数字的真实类别。

培养

我训练了 2 个纪元的网络,批次大小为 64。第一个时期的学习率是 0.001,第二个时期的学习率降低到 0.0001。最后的训练损失降到了 0.34。我尝试了一些不同的网络架构和策略,但无法进一步减少损失,所以我继续使用这个网络。是时候测试网络了。

解决数独

现在,我试着用我们训练有素的网络来解决这个游戏。我看到网络总是预测一些错误的值。下面是网络预测的一场比赛。您可以看到一些数字在行和列中重复出现。

> Input (Unsolved)[[0 1 6 9 0 4 0 0 7]
 [0 0 4 0 3 0 0 8 0]
 [0 0 3 0 6 1 9 2 0]
 [5 0 9 1 4 0 8 0 0]
 [1 7 0 0 0 0 0 0 0]
 [0 0 8 7 0 0 0 6 5]
 [6 0 0 0 0 2 0 4 0]
 [0 2 0 8 0 5 3 1 0]
 [0 3 0 0 0 0 0 0 9]]> Output[[2 1 6 9 8 4 5 3 7]
 [2 9 4 2 3 7 6 8 1]
 [7 8 3 5 6 1 9 2 4]
 [5 6 9 1 4 6 8 7 3]
 [1 7 2 5 5 8 4 9 4]
 [4 4 8 7 2 9 1 6 5]
 [6 9 1 3 1 2 5 4 8]
 [9 2 7 8 9 5 3 1 6]
 [4 3 1 4 1 6 2 5 9]]

我不得不尝试其他方法,而不是改变网络架构来解决游戏,因为训练损失不会低于某个数字。

一个更人性化的解决游戏的方法

作为人类,当我们解决数独时,我们一个接一个地填充数字。我们不会简单地看一遍数独,然后把所有的数字都填满。一个接一个地填写数字的好处是,每次我们填写一个数字,我们就能对下一步行动有更好的想法。

我现在在解数独的时候用了同样的方法。我没有一次预测所有 81 个数字,而是在所有空白位置中挑选一个概率值最高的数字,并将其填入数独中。在填完一个数字后,我们再次将这个谜题输入网络并进行预测。我们不断重复这个过程,用概率最高的数字一个接一个地填充空白位置,直到我们没有空白位置。

这种方法提高了性能,网络能够解决这个数据集中几乎所有的游戏。对 1000 个游戏的测试准确率为 0.99。

下面是一个从网上摘下来的数独游戏,模型正确地解决了它。你可以在我的jupyter笔记本中用你的数独游戏替换下面的game字符串,并检查结果。

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

Sudoku solved by CNN

然而,我需要在从网上挑选的更真实的游戏上检查我的模型,因为那些游戏可能与随机生成的不同。手动复制字符串格式的数独要花费很多时间,所以我把这部分留到将来。

下面是这个项目与保存模型的 GitHub 链接。我会继续张贴更多这样的项目。

[## shivaverma/数独求解器-CNN

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/shivaverma/Sudoku-Solver-CNN/blob/master/sudoku.ipynb)

如果你喜欢这篇文章,那么你也应该看看下面的文章。

[## 用神经网络解决拼图游戏

神经网络能解决一个 2x2 的拼图游戏吗?

medium.com](https://medium.com/@shivajbd/solving-jigsaw-using-neural-nets-cc543a5f025c)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值