Kubernetes,ML 管道的开放和可扩展方法
还在等 ML 训练结束?厌倦了手动运行实验?不确定如何重现结果?在开发运维及数据争论上浪费太多时间?
如果你是一个业余爱好者,这没关系,但是数据科学模型应该被整合到真正的商业应用中。如果看不到积极的投资回报,企业就不会投资数据科学。这就要求采用“工程化”的方法——否则它只不过是一个美化了的有数据的科学项目。
工程师在现代敏捷开发中使用微服务和自动化 CI/CD ( 持续集成和部署)。你写代码,推送,它会在大规模的集群上自动测试。如果通过测试,它将进入某种形式的 beta/ 金丝雀测试阶段,并从那里投入生产。 Kubernetes ,一个云原生集群编制器,是现在被开发人员和开发者广泛使用的工具,用来构建一个敏捷的应用交付环境。
领先的 ML 工程师和 AI/ML 驱动的公司已经在使用 Kubernetes,它带有预集成的工具和可扩展的框架,用于数据处理、机器学习和模型部署。一些 Kubernetes 框架还支持水平扩展和高效使用 GPU,这进一步减少了总体等待时间和成本。
不要满足于专有的 SaaS/云解决方案或传统架构,如 Hadoop 。获得基于 Kubernetes 的解决方案,打造可扩展的前瞻性数据科学平台。以下帖子回顾了用于扩展和操作数据科学工作的流程和 Kubernetes 框架的最佳实践,并提供了有关 Kubernetes (K8s)的 KubeFlow ML 工具包的详细信息。
数据科学管道
数据科学家在开发阶段通常会经历以下步骤:
- 从 CSV 或密集格式(如拼花地板)收集数据,需要从外部来源手动提取。
- 手动标记、探索和丰富数据,以识别潜在的模式和特征。
- 模型训练和验证。
- 使用真实/新鲜数据进行模型测试,或者作为更大应用程序的一部分。
- 如果对结果不满意,冲洗并重复。
Data Science Pipeline and Output Artifacts
一旦完成了开发,尽管困难重重,模型还是被部署到生产环境中,在那里展示了花哨的仪表板来识别异常或预测行为。我们中那些在人工智能旅程中更先进的人也创建人工智能驱动的用户交互/应用程序或触发警报和行动。
但随后数据发生了变化…模型精度漂移…用户要求更新应用程序和仪表板等…现在我们发现自己再次运行大部分管道来生产新模型。这是我们开始谷歌持续开发和集成方法的地方,但是稍后会有更多的内容。
构建管道所需的工具可分为以下六类:
A.来自离线或在线来源的自动数据收集器。
B.用于数据标注、探索和模型开发的交互式工具。
C.用于大规模聚合、连接和透视数据的分析工具/数据库。
D.并行模型培训框架。
E.模型和 API 服务框架。
F.管理、监控和仪表板。
将所有这些工具集成到一个平台下的唯一明智的方法就是使用 Kubernetes!
Kubernetes,ML 平台的选择
Kubernetes 在同一个集群上托管多个打包的和预集成的数据和数据科学框架。它们通常是可伸缩的或者是自动伸缩的,并且它们是通过声明性的方法来定义/管理的:指定您的需求是什么,服务将不断地寻求满足它们,这提供了弹性并最大限度地减少了手动干预。
KubeFlow 是一个开源项目,集合了领先的相关 K8 框架。KubeFlow 组件包括 Jupyter 笔记本、KubeFlow Pipeline (工作流和实验管理)、可扩展培训服务(针对 TensorFlow 、 PyTourch 、 Horovod 、 MXNet 、 Chainer )、模型服务解决方案以及 Iguazio 的无服务器框架 (Nuclio 。KubeFlow 还提供了示例和预集成/测试组件。
除了典型的数据科学工具,Kubernetes 还可以托管数据分析工具,如 Spark 或 Presto ,各种数据库和监控/日志解决方案,如 Prometheus 、 Grafana 、 Elastic Search 等。它还支持使用无服务器功能(即自动构建/部署/扩展代码,如 AWS Lambda )执行各种数据相关任务或 APIs 模型服务,请在我的帖子(无服务器:它能简化数据科学项目吗?)。
Using Kubernetes for Data-Science and Analytics
与专有云或 SaaS 解决方案相比,Kubernetes 的主要优势在于其工具会定期添加和升级,谷歌的搜索和堆栈溢出通常是最快的帮助途径,并且该解决方案可以部署在任何地方(任何云,甚至是本地或笔记本电脑)。社区项目还迫使相关的组件/服务符合一组简化互操作性、安全性、监控等的标准/抽象。
您可以自己构建和管理 Kubernetes 数据科学平台(遵循文档),或者使用云提供商或 Iguazio 等公司的托管和预集成解决方案。
构建高效的数据科学管道
不幸的是,仅仅押注于一个可信的平台是不够的。相信我,这是我的经验之谈:一旦你采纳了三条指导原则,生活会变得更容易:
- 使其功能化 —创建可重用的抽象函数/步骤,可以接受参数。
- 使其可扩展 —将并行性应用于每一步(或者尽可能经常地,在合理的范围内)。
- 自动化 —通过使用声明性语义和工作流来避免手动和重复的任务。
数据科学的当前趋势是建立“ML 工厂”,即非常类似于敏捷软件开发,建立自动管道来获取数据、预处理数据、运行培训、生成、部署和监控模型。Kubernetes 提供的声明式自动化部署和扩展方法是一个很好的基线,但它缺少一种在此基础上管理此类管道的方法。
KubeFlow 项目中一个相对较新的工具是 Pipelines ,这是一组旨在创建和管理 ML 管道的服务和 UI。我们可以编写自己的代码,或者从谷歌、亚马逊、微软、IBM、英伟达、 Iguazio 等公司提供的大量预定义组件和算法中构建。
Kubeflow Piplines UI
一旦我们有了一个工作流,我们就可以按预定的时间间隔运行它一次,或者自动触发它。管道、实验和运行被管理,并且它们的结果被存储和版本化。管道解决了复制和解释我们的 ML 模型的主要问题。这也意味着我们可以直观地比较运行,并在各种对象/文件存储库中存储版本化的输入和输出工件。
一个主要的挑战是如何大规模地进行实验和数据处理。管道协调各种水平扩展和 GPU 加速的数据和 ML 框架。单个逻辑流水线步骤可以在 TensorFlow、Spark 或 Nuclio 函数的十几个并行实例上运行。管道也有映射到现有云服务的组件,因此我们可以提交一个逻辑任务,该任务可能在托管的谷歌人工智能和数据服务上运行,或者在亚马逊的 SageMaker 或 EMR 上运行。
KubeFlow 和它的管道,就像这个类别中的大多数工具一样,仍然在发展,但是它背后有一个庞大而活跃的多厂商社区。这保证了一个可行和开放的框架。很像 Kubernetes 的第一天,云提供商和软件供应商有他们自己的管理容器的专有解决方案,随着时间的推移,他们都让位于社区要求的开源标准。
如果你下周碰巧在巴塞罗那的 KubeCon,请参观 KubeFlow 会议和各种成员展示的演示,包括我自己。我将于 5 月 20 日出席无服务器从业者峰会(Fira Gran Via Hall 8.0 Room D4+cc 8.17–20),并于 5 月 23 日下午与谷歌的 Maulin Patel 会面https://KC cnce u19 . sched . com/event/MPaf/economics-and-best-practices-of-running-aiml-workloads-on-kubernetes-maul in-Patel-Google-yaron-haviv-iguazio。
气流 KubernetesExecutor
在 Kubernetes 上自然缩放气流
在 1.10 版本中,Airflow 引入了一个新的执行器来大规模运行 workers:Kubernetes 执行器。在本文中,我们将探讨:
- 什么是气流,它解决什么问题
- 库伯内特遗嘱执行人及其与芹菜遗嘱执行人的比较
- minikube 上的示例部署
TL;速度三角形定位法(dead reckoning)
气流有了一个新的执行者,可以在 Kubernetes 上自然产生工蜂。在这个 git 库中有一个导航图,以及一些帮助你开始使用 KubernetesExecutor 的例子。
气流作为工作流调度程序
数据工程领域迅速发展,以处理和存储不断增长的数据量。现在有很多技术可以在所谓的数据湖或数据仓库中存储和查询数 Pb 的原始数据。想想开源平台——Hadoop、Kafka、Druid、Ceph——或者云原生解决方案——亚马逊红移和 S3、谷歌 BigQuery 和 GCS、Azure 数据仓库和数据湖。你可以使用 Spark、Flink、Storm 或 Beam 等工具来处理这些海量数据。或者在数据仓库上运行查询,并将结果存储在新表中。数据管道通常由许多步骤和工具组成,用于移动数据。那么,我们如何将这些组件缝合到一个可靠的工作流中呢?
工作流调度程序管理任务之间的依赖关系,并协调它们的执行。知名的调度有气流、路易吉、 Oozie 和阿兹卡班。Airflow 因其丰富的 UI、灵活的配置和编写定制扩展的能力而获得了社区的大力支持。Airbnb 启动了这个项目,并将其开源为 Apache 孵化器。
想象一下,我们有一堆数据放在谷歌云存储(GCS)的某个地方,等待处理。我们希望使用 Spark 清理数据,并将其移动到 BigQuery 进行分析。预算紧张,所以我们没有全天候运行的 Hadoop 集群。我们首先要创建一个新的 Dataproc 集群(Dataproc 是 Google Cloud 上的 Hadoop)。然后,Spark 作业从 GCS 获取数据,对其进行处理并将其转储回 GCS。最后,BigQuery 作业将数据从 GCS 加载到一个表中。同时,我们可以关闭 Dataproc 集群来清理我们的资源。这是这样一个气流工作流程的样子。
气流本身支持上述所有步骤以及更多。Airflow 还负责对 GCS、Dataproc 和 BigQuery 的认证。这是一个简单的示例,说明了气流如何在任务之间创建工作流。如果你是气流的新手,我强烈推荐你在 Github 上查看这个资源管理。这篇文章假设你已经理解了气流的本质。
规模化气流
气流不仅仅可以运行数据管道。它可以触发任何带有 API 的作业。这开启了一个充满机遇的世界!不知不觉中,你的气流装置变得挤满了管道。是时候扩大规模了。Kubernetes 是扩展应用的领先技术之一。应用程序的各个部分在所谓的 pod 中作为独立的容器运行。当应用程序需要更多功率时,Kubernetes 会复制这些 pod。
Airflow 的架构非常适合这种模式。在其核心,调度程序决定哪些任务需要运行下一步。web 服务器使用户能够与 Dag 和任务进行交互。数据库跟踪当前和过去作业的状态。最后,气流有运行任务的工人。调度程序、web 服务器和数据库通常不需要扩展。完成繁重任务的是工人节点。Airflow 有两个流行的执行器可以大规模部署工作人员 CeleryExecutor 和 KubernetesExecutor。
Celery 是一个分布式任务队列,在多个节点之间平衡工作负载。使用芹菜在工人节点上调度作业是一种流行的扩展气流的方法。在这里您可以找到一张导航图,使用 CeleryExecutor 自动完成部署。但是,如果使用芹菜效果如此之好,那么我们为什么还需要另一个 Kubernetes 的执行者呢?因为芹菜挺复杂的。您需要在系统中部署芹菜作为额外的组件。而芹菜需要 RabbitMQ 或 Redis 这样的经纪人作为后端。此外,您可能希望用 web 界面 Flower 来监控芹菜。也许这些组件对于手头的任务来说增加了太多的开销?我们不能来点更简单的吗?是啊!Airflow 1.10 引入了一个新的执行器来扩展工作人员:Kubernetes 执行器。
对于芹菜,你在前面部署几个工人。然后,队列将在它们之间调度任务。相比之下,KubernetesExecutor 不会持续运行任何工人。相反,它为每项工作产生了一个新的工人群体。工作完成后,气流会立即清理资源。现在我们充分利用 Kubernetes 的潜力。不再需要额外的组件。扩展仅受限于集群的大小。只要你有足够的 CPU 和内存可用,气流可以不断调度更多的任务。当 Airflow 不再有作业运行时,只有调度程序、web 服务器和数据库保持活动状态。您的群集可以将其资源用于其他应用程序。
实践中的 Kubernetes 执行者
让我们深入实际细节。这篇文章的剩余部分将通过一个简单的例子来说明。我们将使用掌舵图在 minikube 上设置气流,但是如果你愿意,你可以在任何云提供商上部署它。我们的部署将定期从 Airflow 的 git 存储库中同步 Dag。让我们从克隆 git 存储库开始。
git clone [https://github.com/BrechtDeVlieger/airflow-kube-helm](https://github.com/BrechtDeVlieger/airflow-kube-helm)
cd airflow-kube-helm
在继续之前,请确保 minikube 已启动并正在运行。在 minikube 开始旋转仪表板后,您可能需要等待一分钟。
minikube start
minikube dashboard
首先,我们需要一个包含 Airflow 版本 1.10.2 或更高版本的 docker 映像。确保您已经安装了 Docker,并且 minikube 已经启动并正在运行。按照这些指南来安装和设置 docker 和 minikube。该存储库包含一个构建 docker 映像的脚本。
./examples/minikube/docker/build-docker.sh
该脚本使用 Kubernetes 依赖关系从 docker-airflow 构建了一个新的图像。当脚本完成时,图像将在 minikube 的注册表中作为airflow:latest
出现。
Helm charts 允许开发人员创建可重用的 Kubernetes 部署。Helm 读取 values.yaml 文件并生成一组 yaml 文件。这些文件描述了一个 Kubernetes 部署。我们只需创建一个新的 yaml 文件来覆盖默认设置,从而创建一个定制部署。你可以在这里找到所有的默认值及其解释。我们将逐一介绍必要的更改。首先创建一个新的 values.yaml 文件。
Airflow 使用 fernet 密钥对数据库中的密码进行加密。当然,我们不想以纯文本的形式存储它们。下面是生成这样一个密钥的方法。
python -c "from cryptography.fernet import Fernet; FERNET_KEY = Fernet.generate_key().decode(); print(FERNET_KEY)"
将生成的密钥粘贴到 values.yaml 文件中。
airflow:fernet_key: "j0PNE8131Vx-ix7BsNDwskFUlnLa00mWU17BRujVcdY="
接下来,我们必须告诉使用哪个图像。如果您在 minikube 上构建映像,那么配置如下所示:
airflow:
...
image:
repository: airflow
tag: latest
pull_policy: IfNotPresent
pull_policy
在 minikube 上无关紧要,因为它使用其本地注册表来获取气流图像。
我们必须告诉气流从哪里得到这些数据,以及如何存储它们。我们的示例定期从气流存储库获取示例 Dag,并将它们复制到 Dag 文件夹中。以下代码片段向您展示了如何做到这一点:
airflow:
...
dags:
persistence:
enabled: false
git:
url: [https://github.com/apache/airflow](https://github.com/apache/airflow)
branch: master
subpath: airflow/example_dags
wait: 60
要从 git 中提取 Dag,必须禁用持久性。在大多数情况下,dag 不存在于根 git 文件夹中。在我们的例子中,我们必须在子目录./airflow/example_dags
中寻找它们。我们将把这个目录传递给subpath
参数。其默认值为dags
。您可以使用wait
字段配置从 git 获取 Dag 的频率。
在继续部署之前,确保您的 values.yaml 文件看起来像下面的代码片段。
airflow:fernet_key: "j0PNE8131Vx-ix7BsNDwskFUlnLa00mWU17BRujVcdY="
image:
repository: airflow
tag: latest
pull_policy: IfNotPresent
dags:
persistence:
enabled: false
git:
url: [https://github.com/apache/airflow](https://github.com/apache/airflow)
branch: master
subpath: airflow/example_dags
wait: 60
教程的其余部分是小孩子的游戏。只需几个命令,我们就能让气流流动起来。但首先,我们需要在 minikube 上安装 Helm。顺便说一下,我们把运行在 Kubernetes Tiller 上的 Helm 部分称为。我们还将安装所需的舵依赖。
kubectl apply -f airflow/tiller.yaml
helm init --service-account tiller
helm dependency update
使用 Helm 生成 yaml 文件并部署 Airflow。
helm upgrade --install airflow airflow/ \
--namespace airflow \
--values values.yaml
几分钟之内,气流就会开始流动。如果需要一点时间,请不要担心。通常,web 服务器和调度程序会在 Postgres 数据库准备好之前尝试连接到它。在 pod 失败并重新启动之前,连接需要超时。为了加速这个过程,只要数据库准备好,就手动重新启动 web 服务器和调度程序窗格。
当所有的 pods 都准备好时,您可以使用这个命令将 web UI 转发到 http://localhost:8080 。
kubectl port-forward --namespace airflow $(kubectl get pod --namespace airflow --selector="app=airflow-web,release=airflow" --output jsonpath='{.items[0].metadata.name}') 8080:8080
现在尝试通过取消暂停来运行example_bash_operator
。DAG 现在应该运行两次。在 minikube 仪表板上观察气流如何启动新的 pod 并清理已完成的 pod。您可以在图形和树视图中查看日志。遗憾的是,您无法从任务实例面板查看日志。这仍然是 KubernetesExecutor 中的一个 bug。
结论
气流 1.10 引入了一个新的执行器来大规模运行气流:KubernetesExecutor。调度器直接与 Kubernetes 交互,在任务开始和结束时创建和删除 pods。因此,当 Airflow 空闲时,只有调度程序和 web 服务器在运行。这为集群中的其他应用程序释放了资源。气流现在能够在 Kubernetes 上自然扩展,而不需要芹菜等附加组件。部署更加简单明了。
然而,新的执行程序仍然很新,有时表现有点出乎意料。1.10.2 版本解决了大部分问题,所以我建议只使用这个版本或更高版本。不过还有一个棘手的问题。日志卷需要允许从所有 Airflow pods 进行读写访问。云提供商本身不支持读写多个卷,因此您必须自己提供解决方案。该存储库包含一个 NFS 服务器的示例。
尽管如此,executor 按照预期工作,并且足够稳定,可以投入生产。气流的开发团队做得很棒。太棒了。谢谢你坚持到最后,希望这篇帖子能对你接下来的部署有用。
释放数据的价值
Photo by Sereja Ris on Unsplash
标签编码—通过编码释放您的数据
在这篇文章中,我分享了一些处理标签的技巧。我提出方法来揭示你的字符串数据的内部值。第一部分回顾了经典的方法,下面几节讨论更具体的方法。
如何处理:
1。标签
2。颜色
3。位置
4。周期性特征
1.如何转换标签
Photo by Max Baskakov on Unsplash
大多数机器学习算法无法处理带标签的特征。字符串列很难转换成数值。
让我们考虑以下卡特彼勒特性数据集:
id hair breed
1 naked sphynx
2 short siamois
3 naked sphynx
4 angora ankara
.. ... ...
列hair
和breed
包含字符串格式的数据**。**
要将hair
特征转换成数值,可以给每个头发标签设置一个数字。例如naked
变成 0,short
变成 1 等等;
id hair breed
1 0 sphynx
2 1 siamois
3 0 sphynx
4 2 ankara
.. ... ...
这种标签编码方法在头发值之间创建了一个层次。/naked
小于1
/ short
和2
/ angora
。这个等级在这里不是问题,因为它反映了猫毛的长度。
由于猫品种之间没有****的特定顺序**,应用以前的标签编码方法会误导算法。在这种情况下, One Hot Encoding 方法最合适。它用布尔值(0-假/1-真)按品种创建一个列。结果是:**
id hair sphynx siamois ankara
1 0 1 0 0
2 1 0 1 0
3 0 1 0 0
4 2 0 0 1
. ... ... ... ...
通过使用虚拟矩阵,每个品种都被认为是独立的。这种标签编码变体不涉及层次结构。
Photo by Linnea Sandbakk on Unsplash
小心,一个热点编码一个栏目会产生更多可供学习的功能。如果品种的数量与数据集中猫的数量相比较小,则应使用此方法。
注意:创建虚拟对象会给你的数据集带来冗余。事实上,如果一只猫既不是斯芬克斯猫也不是暹罗猫,那么它必然是安卡拉猫。因此,可以安全地删除一个虚拟列,而不会丢失任何信息:
id hair sphynx siamois
1 0 1 0
2 1 0 1
3 0 1 0
4 2 0 0
.. ... ... ...
****奖金。认为不同品种的猫相互独立简化了现实。例如,一只猫可能一半是暹罗猫,一半是安卡拉猫。在我们的编码数据集中,我们可以通过在 siamois 和 ankara 列中写入 0.5 来轻松表示这种混合。
id hair sphynx siamois
1 0 1 0
2 1 0 0.5
3 0 1 0
4 2 0 0
.. ... ... ...
第一部分介绍了编码标签的经典方法。但是更具体的技术可能更适合。这取决于标签信息以及您需要如何处理数据。F 跟随技术可能会有更好的效果。****
2.如何转换颜色
假设我们现在有了每只猫的眼睛颜色:
Photo by Antonio Lapa on Unsplash
id eyecolor
1 light_green
2 dark_cyan
3 medium_sea_green
4 yellow_green
.. ...
这一次,以前的方法不太适合表达颜色标签中的价值。相反,我们可以将颜色列分为红绿蓝三种色调:
id eye_red eye_green eye_blue
1 173 237 150
2 70 138 139
3 105 178 117
4 168 205 67
.. ... ... ...
一般来说,颜色有几种编码方式。人们可能需要添加透明度信息。根据数据的使用方式,可以用 HSB(色调饱和亮度)而不是 RGB 进行编码。
3.如何转换位置
现在我们考虑猫的位置。我们有他们居住地的城市名。
Photo by Anthony DELANOIX on Unsplash
id city
1 Paris
2 New-York
3 Cairo
4 New-York
.. ...
这里,我们可以用城市的 GPS(纬度/经度)十进制度坐标来代替城市名称,而不是使用常规的标签编码方法:
id latitude longitude
1 48.85341 2.3488
2 37.6 -95.665
3 30.06263 31.24967
4 37.6 -95.665
.. ... ...
如您所见,我们根据地理属性对位置进行了编码。
根据我们的需要,城市可以用其他指标来表征。例如,如果我们需要预测猫的预期寿命,那么 城市发展指数 ,或者 平均家庭收入 可能更适合。
这些翻译带来了其他类型的信息。人们可以结合指标来丰富数据集。
4.如何转换周期性特征
最后但同样重要的是,让我们关注循环特性。我们现在有了猫外出夜游的平均时间:
Photo by Agê Barros on Unsplash
id avg_night_walk_time
1 11:30 PM
2 00:12 AM
3 10:45 PM
4 01:07 AM
.. ...
首先让我们把它转换成十进制小时:
id avg_night_walk_time
1 23.5
2 0.2
3 22.75
4 1.12
.. ...
所以现在我们有了0
和23.99
之间的时间。作为人类,我们知道 23:59 和 00:00 很接近,但它没有出现在数据中。要改变它,我们可以用余弦和正弦来转换时间。它将数据投影到一个圆形空间中,在该空间中 00:00 AM 和 11:59 PM 靠得很近。
id avg_nwt_cos avg_nwt_sin
1 0.99 -0.13
2 0.99 0.05
3 0.94 -0.32
4 0.95 0.28
.. ... ...
通过转换时间,我们失去了一些人类的理解,但我们可以在任何时候将余弦和正弦数据转换回小时。这种转换并不意味着信息的丢失。
这种循环转换也应该应用于角度和周期过程。
正确处理周期性特征会大大增加数据集的价值。当你用小时、工作日、月、角度工作时,不要忘记它…
PS:在本文中,我没有谈论特性缩放,因为我关注的是数据转换。如有必要,考虑在转换后缩放/居中数据。
标签平滑:更高模型精度的一个要素
1.介绍
图像分类是从一组固定的类别中给输入图像分配一个标签的任务。这是计算机视觉中的核心问题之一,尽管它很简单,却有大量的实际应用。
**示例:*例如,在下图中,一个图像分类模型获取一张图像,并将概率分配给两个标签:{猫,狗} 。如图所示,请记住,对于计算机来说,图像是一个大型的三维数字数组。在这个例子中,猫图像是 248 像素宽,400 像素高,并且具有三个颜色通道红色、绿色、蓝色(或简称为 RGB)。因此,图像由 248 x 400 x 3 个数字组成,即总共 297,600 个数字。每个数字都是从 0(黑色)到 255(白色)的整数。我们的任务是将这 25 万个数字转换成一个标签,比如“cat”*。
同样地,你可以训练一个模型,让它通过看卡戴珊的照片告诉你你在看哪个——金,凯莉,还是其他
2.训练分类模型
训练将图像分类为猫图像或狗图像的模型是二元分类的一个例子。
图像分类流水线。我们已经看到,图像分类的任务是获取代表单个图像的像素阵列,并为其分配标签。我们的完整渠道可以概括如下:
- **输入:**我们的输入由一组 N 图像组成,每个图像都标有一个 K 不同的类。我们将该数据称为训练集。
training dataset
**学习:**我们的任务是使用训练集来学习每个类的样子。我们称这个步骤为训练分类器或学习模型。
3。数据标注错误问题
但是如果你的训练数据包含不正确的标注呢?如果一只狗被贴上猫的标签会怎样?如果凯莉被贴上肯德尔的标签,或者金被贴上坎耶的标签怎么办?如果你从互联网上获取数据,这种错误的数据标注可能会发生。
这最终会导致您的问题要么学习数据集中的噪声,要么学习不正确的要素。但是,这在一定程度上是可以避免的。如果你在一个小数据集上训练,你可以检查所有的标签并手动检查,或者使用你的爪牙来做脏活。下一节将分享另一种数学方法。
所以,问题是你的模型将会学习不正确的特征(从一只狗身上),并将这些特征与标签“猫”联系起来。我们如何解决这个问题?为了深入了解这一点,让我们看看在图像分类问题中使用的损失函数。
在我们得到损失函数之前,我们应该确定分段模型给出了每类的概率**😗*
…maybe this is not how you see her…
在图像分类问题中,我们使用 softmax loss ,其定义如下两类:
l =(ylog(p)+(1y)log(1p))
这里, L 为损失, y 为真实标签(0 —猫,1 —狗), p 为图像属于 1 类即狗的概率。模型的目标是减少损失。
损失本质上驱动了你的“梯度”,简单来说就是决定了模型的“学习”。因此,我们需要密切关注损失。
比方说,你得到一张狗的图片,概率为 0.99。你的损失将是:
l =-(1 (log(0.99)+(1–0.99) log(0.01))≈0
哪个好!预测准确的情况下损失应该不大!
如果你的数据有不正确的标签,这种损失会特别大,从而导致 在学习 时出现问题。
那么我们该如何处理呢?在下一节中,我们将看到一种在标签不正确的情况下将损失最小化的方法。
3。标签平滑 —一种可能的解决方案
向标签平滑问好!
当我们将交叉熵损失应用于分类任务时,我们期望真正的标签为 1,而其他标签为 0。换句话说,我们毫不怀疑真正的标签是真的,其他的不是。总是这样吗?也许不是。许多手动注释是多个参与者的结果。他们可能有不同的标准。他们可能会犯一些错误。他们毕竟是人。因此,我们一直坚信的地面真相标签可能是错误的。
一个可能的解决办法是放松我们对标签的信心。例如,我们可以将损失目标值从 1 稍微降低到 0.9。自然地,我们稍微增加了其他人的目标值 0。这种想法被称为标签平滑。
下面是张量流中定义的交叉熵损失的论点:
arguments in softmax cross entropy loss
这是 Tensorflow 文档对label_smoothing
参数的描述:
如果
label_smoothing
不为零,则将标签向 1/num_classes 方向平滑:new _ onehot _ labels = onehot _ labels *(1-label _ smoothing)+label _ smoothing/num _ classes
这是什么意思?
假设你正在训练一个二元分类模型。你的标签应该是 0-猫,1-不是猫。
现在,假设你label_smoothing
= 0.2
使用上面的等式,我们得到:
new _ onehot _ labels =[0 1](1—0.2)+0.2/2 =[0 1](0.8)+0.1
new_onehot_labels =[0.9 0.1]
这些是软标签,而不是硬标签,即 0 和 1。当有一个不正确的预测时,这将最终给你较低的损失,随后,你的模型将惩罚和学习不正确的程度稍低。
本质上,标签平滑将帮助您的模型围绕错误标签的数据训练*,从而提高其健壮性和性能。*
4.进一步阅读
使用机器学习标记法律文档
简介
标记数据的问题通常被认为是机器学习项目的第一步,其中开发了一个训练数据集,该数据集精确地表示看不见的、预期的“测试”数据。然而,对于大型数据集,包括自然语言语料库,标注工作本身就可以给组织带来巨大的价值。
图书馆,尤其是那些旨在教育学生和未来研究人员的学术机构,承担着这样的负担。虽然在使用光学字符识别(OCR)对无数数量的信息进行数字化方面已经取得了长足的进步,但是如果文本没有与基础附录或其他参考材料的链接,研究仍然会被证明是乏味和耗时的。
数据
在最近与一家受人尊敬的图书馆的项目中,我的任务是通过识别和标记所提交的证据文件的来源,促进历史法庭的抄本的易用性。这些文件要么是审判文件,要么是证据文件,要么是检方或辩方用来为自己的案件辩护的文件,证据文件是更广泛的文件领域的一部分,包含它们自己的命名方案。
每个人都有自己特定的识别方式。对于证据文件文档,正则表达式(regex)用于查找一组预定义的编码文档组中的任何一个。另一方面,区分控方和辩方的审判文件依赖于更微妙的上下文线索,并且经常需要仔细阅读记录以便正确地跟踪谈话。
该方法
在第一遍中,所有可能的引用都用 regex 标记,并且证据文件文档被分区。在剩余的参考文献中,那些明显是起诉或明显是辩护的参考文献被立即分类并搁置,以用作随机森林算法的训练集,以便对更模糊的情况做出决定。
这是模型最容易出错的地方。标签的准确性是最重要的,但紧接着是回忆(找到尽可能多的参考文献)。因此,我们与客户进行了定期的交流,客户对结果进行了人工检查,并向我们汇报。通过这种方式,我们可以对算法进行微调,例如,提供额外的功能、超参数调整或增加较少表示的类。
使用的主要特征是参考上下文。在所讨论的引用的任意一侧收集给定数量的单词或标记后,对实体进行词干分析和词汇化,并最终转换为词频逆文档频率(tf-idf)嵌入。这种方法根据最常见单词在每个“文档”中出现的频率(在这种情况下是围绕单个引用的上下文)对最常见单词的计数进行加权。因此,所有单词都将具有整数表示,能够作为输入提供给机器学习算法。
同样的方案也适用于现任议长。其他特征是基于关键触发词的存在或不存在而构建的,例如“起诉”,或者律师或被告之一的名字。随机森林实现为:
forest = RandomForestClassifier(criterion='entropy', n_estimators=500, random_state=0, n_jobs=-1)
其中使用了“熵”分离选择标准。尽管计算量更大,但它通常更适合分类数据。确定在一系列概率阈值的每一个处的算法性能,以便最大化准确性和召回率。此后,任何大于这个界限的都被标为“起诉”,小于这个界限的都被标为“辩护”。
问题
从一开始,该模型的准确性就很高,几乎不需要进一步增强。更大的挑战是确保我们获得大部分的引用。引用参考文献的方式有很大的不同,包括从缩写到零散的标点符号。必须构建正则表达式来接受跨多行出现的引用。此外,许多引用包含不同可能类型的组合,对于正则表达式定义来说,这看起来像多个唯一的标记机会。当在末尾用标签重新构造文本时,后者会变得特别麻烦,因为引用的尾部很容易被切断,并过早地被标签替换。
这些边缘情况的唯一共同点是存在一个长度不超过五位数的数字。在第二次浏览抄本时,我们识别了所有剩余的数字,过滤掉任何可能发现的假阳性(日期、页码、基本形容词)。在剩下的那些中,规则被开发以确保参考(某些介绍性短语的存在)和分配的标签。
经验教训
虽然是功能性的,但是第二遍中所做的工作是非常特殊的,并且不容易在其他数据集上使用。然而,大部分工作,以及整个项目中的工作,非常类似于作为斯坦福大学潜泳项目一部分的标记函数(LFs)的应用。意识到标记数据是机器学习中最耗时和不一致的部分,他们使用基于规则的 LFs 来编码标记数据的方法。在这种情况下,覆盖率通常比精确度更难控制,因此,考虑到我们对回忆的限制,这个公式能有多好的帮助还有待观察。
我们使用的数据集不应被视为异常独特或不规则。法律文本是所有职业中最密集的,对于自然语言处理(NLP)提供的许多节省成本和时间的措施来说,似乎已经成熟。搜索速度至关重要,无论是像这里描述的那样,还是将文本实体与更广泛的关键词联系起来的一种手段。尽管我们的工作因文本不一致而变得复杂,这可能是 OCR 的产物,但我们不能指望更现代的文档会好得多。
滞后变量回归和真理
动态回归模型提供了巨大的代表性,但也有偏见风险
Variables related to each other over adjacent time steps, originally in the context of dynamic Bayesian networks (Wikimedia user Guillaume.lozenguez, CC BY-SA 4.0)
- 使用有理传递函数和公共滤波器,将非线性结构时间序列模型转化为滞后变量的回归
- 见普通最小二乘滞后变量回归中的偏差由于误差中剩余的序列相关性,
- 使用广义最小二乘法消除偏差,恢复过程参数,即“真相”
托布勒(Tobler)的(非常可信的)地理第一定律指出:“耳边的事物比远处的事物更加相关。无论我们对底层的数据生成机制知之甚少,我们经常可以利用纯粹的邻近性——在时间或空间上——来获得优势。但我们也知道,回归因变量的时移副本,即受所有相同因素影响的副本,会带来一些警告。
最大的警告是普通最小二乘(OLS)回归中潜在的渐近偏差,这是任何额外数据都无法缓解的。当回归变量与误差项同时相关时,就会发生这种情况。正如 Peter Kennedy 在计量经济学指南中所解释的,“这是因为 OLS 程序在为解释因变量的变化而将‘信用’分配给回归变量时,错误地将因变量的一些扰动产生的变化分配给了与扰动同时相关的回归变量”简而言之,当回归变量和误差相关时,OLS 无法将两者的影响分开。
从被动预测的角度来看,偏差可能无关紧要,本文标题中的“t ruth ”指的是时间序列背后的真实数据生成过程。此后,我们的目标是过程参数的质量评估。对于客观事实和参数具有科学意义的情况,我将转向非线性、非平稳、结构化的时间序列模型,即运动表现的“体能-疲劳”模型。该模型通过潜在的健康和疲劳结构将训练历史与运动表现联系起来,并通过有科学意义的参数进行调整。
通过使用输入到输出的合理传递函数重写这个模型,一组“公共过滤”操作将变得显而易见。应用这些过滤器会将模型转换为动态线性回归,但是过滤操作也会有副作用:MA(2)相关结构的错误。我们将在 OLS 回归中看到回归变量和误差之间同期相关性的破坏力,但最终,我们将通过适应这种结构的 GLS 回归得到真相。
非线性结构时间序列模型
运动表现的“体能-疲劳”模型具有以下形式:
其中 p_t 是(运动)表现的数字测量值, w_t 是训练“剂量”,而 ϵ_t 是同分布高斯误差。该模型可以被视为具有两个非线性特征的线性回归,
运动员“健康”和“疲劳”的潜在表征。这些特征是具有指数衰减的运动训练历史的卷积,不同之处仅在于衰减速率。通常,疲劳 ( g_t )相对短暂,并与更快的指数衰减相关联,但与适应度相比,也具有相对较大的回归权重。
借助一点代数知识,体能和疲劳可以转化为动态形式:
其中*θ_*1 = exp(-1/*τ_*1)*θ_*2 = exp(-1/*τ_*2)。
如果我们将健康和疲劳的动态表示插入到原始模型中,我们会得到
这看起来更好,但不是立即有用的,因为 h _t 和 g _t 取决于未知参数。
理性传递函数到救援
再努力一点,我们可以对任何时间索引变量 y 使用由By _ t=y_ {t-1 }定义的“后移运算符” B ,得到
求解 h _ t 和 g _ t 并将它们插回到原始模型中,我们得到:
因此,我们有两个对外生输入序列 w_t 进行操作的有理传递函数。对于有理传递函数,形式为(1- θ B)的分母项对应于一个自回归脉冲响应,即一个具有长记忆的过程,这对我们来说是一个麻烦。我们可以选择去掉分母成分,但这不是没有代价的。
在多输入传递函数模型的识别(刘& Hanssens,1982)中讨论的“公共滤波器”通过(1- θ B 来预乘时间序列方程的右侧和左侧。它不会改变传递函数权重,因此您可以连续应用多个公共滤波器,除了会导致复杂性和由于滞后而丢失一些行之外,您还没有破坏输入和输出序列之间的关系。
关键是,如果我们要使用公共滤波器(1-θ_ 1b)(1-θ_ 2b),我们就可以去除自回归成分:
上面的内容看起来仍然很难看,但是在展开应用后移运算的多项式之后,我们得到:
这是对两个自身滞后版本和外部培训输入的性能回归,但有一个转折。存在由公共滤波器引起的 MA(2)误差结构的问题,并且它具有真实的后果。
R 中的一个模拟例子
本节将使用可从 R 要点复制或直接下载为 csv 文件的模拟数据。要运行下面的 R 代码,请在下面的 R 代码块中更改文件路径:
train_df <- read.csv("c:/devl/data/train_df.csv")
head(train_df)
以下计算显示了模拟的滞后变量模型中所有系数的理论值:
# True parameter values:
mu <- 496
theta1 <- exp(-1 / 60)
theta2 <- exp(-1 / 13)
k1 <- .07
k2 <- .27#Theoretical coefficient for intercept is
(1 - theta1) * (1 - theta2) * mu#Theoretical coefficient for performance lagged once is
theta1 + theta2#Theoretical coefficient for performance lagged twice is
-theta1 * theta2#Theoretical coefficient for training lagged once is
k1 * theta1 - k2 * theta2#Theoretical coefficient for training lagged twice is
-theta1 * theta2 * (k1 - k2)
因此,目标是恢复以下等式:
侧注: 反其道而行之,通过代入求解θ_1 和θ_2,得出两个参数之一的二次方程。它们导致相同的两个根,所以选择θ_1 为两者中较大的一个。有了θ_1 和θ_2,求解μ就变得简单了,k1 和 k2 构成了一个含有两个方程和两个未知数的线性系统。
拟合滞后回归模型
为了准备回归,下面的代码将性能和训练变量分别延迟一次和两次。dplyr
套装让一切变得简单:
library(dplyr)train_aug <- train_df %>%
mutate(perf_lag1 = lag(perf, n = 1, order_by = day),
perf_lag2 = lag(perf, n = 2, order_by = day),
train_lag1 = lag(w, n = 1, order_by = day),
train_lag2 = lag(w, n = 2, order_by = day))
让我们看看当我们使用 OLS 回归这些滞后变量的表现时会发生什么:
my_lm <- lm(perf ~ perf_lag1 + perf_lag2 + train_lag1 + train_lag2,
data = train_aug[3:nrow(train_aug), ])
summary(my_lm)
上面的代码产生了部分输出:
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 33.99821 12.09470 2.811 0.005327 **
perf_lag1 0.48066 0.05619 8.553 1.18e-15 ***
perf_lag2 0.46189 0.05504 8.393 3.45e-15 ***
train_lag1 -0.15602 0.04406 -3.541 0.000475 ***
train_lag2 -0.02346 0.04516 -0.520 0.603807
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 8.518 on 252 degrees of freedom
Multiple R-squared: 0.9117, Adjusted R-squared: 0.9103
F-statistic: 650.4 on 4 and 252 DF, p-value: < 2.2e-16
由于残差中仍然存在序列相关,OLS 系数估计中明显存在偏差。
幸运的是,R 的nlme
包通过gls
函数提供了广义最小二乘(GLS)模型拟合,它处理 MA(2)误差结构:
library(nlme)
my_gls <- gls(perf ~ perf_lag1 + perf_lag2 + train_lag1 +
train_lag2,
data = train_aug[3:nrow(train_aug), ],
corARMA(form = ~day, p = 0, q = 2))
summary(my_gls)
下面的部分输出来自上面的代码:
Correlation Structure: ARMA(0,2)
Formula: ~day
Parameter estimate(s):
Theta1 Theta2
-1.9059497 0.9117409
Coefficients:
Value Std.Error t-value p-value
(Intercept) 0.6571088 0.11700730 5.61596 0
perf_lag1 1.9187158 0.00815689 235.22646 0
perf_lag2 -0.9200058 0.00815495 -112.81568 0
train_lag1 -0.1662026 0.02238219 -7.42566 0
train_lag2 0.1664704 0.02241510 7.42671 0
通过 GLS 回归,我们已经将真实的参数值恢复到合理的估计误差范围内。
讨论
之前关于体能-疲劳模型的文章已经使用重型机械来估计参数:非线性最小二乘法、l 具有复杂样条卷积特征的线性回归和卡尔曼滤波器,仅举三个例子。对几个滞后变量的线性回归(通过 GLS 拟合)能够恢复理论上的基本过程说明了动态回归模型的表达能力
在投入和产出各滞后几次的情况下盲目回归的代价是什么?只关注提前一步的预测精度,大概不会很多。带有滞后变量的 OLS 回归“解释”了 next 性能值的大部分变化,但它也表明了一个与用于模拟数据的过程完全不同的过程。这个过程的内部被 GLS 回归恢复了,这就谈到了标题中提到的“真相”。
进一步研究和讨论的主题是,对所有动态回归使用具有 MA( q )误差结构的 GLS 回归是否明智。通过nlme
在 R 中实现非常容易。另一方面,它的预报功能没有使用误差结构,因此需要用户作出额外的努力,使 GLS 的预报能与 OLS 的预报竞争。对于开箱即用的一步预测,可能很难证明 GLS 过程的额外复杂性。为了获得真正的底层系统参数,通过 GLS 合并 MA( q )误差结构很可能使我们更接近真相*。*
拉格朗日乘数与可视化和代码
终极优化武器,端到端解释。
在这个故事中,我们将通过拉格朗日乘数进行一次空中优化之旅。我们什么时候需要它们?每当我们遇到有约束的优化问题时。以下是一些例子:
- 对冲基金希望决定其投资组合中包含的股票比例,以使他们获得最大可能的预期回报,并保持在一定的风险偏好范围内(例如,风险可以根据回报的方差来衡量)。
- 一个学区想要为他们的学生确定午餐菜单上各种项目的分配。他们希望将每顿午餐的成本降至最低,同时确保孩子们获得一定量的所有必需营养。
- 一家卡车运输公司想要将货物从源仓库运输到目的地城市。给定每个仓库-城市对的运输成本、每个仓库的总供应量和每个城市的总需求,决定从每个仓库向每个城市运送多少,以使总成本最小化并满足需求(约束)。
我们可以看到,约束优化可以解决从物流到金融领域中出现的许多实际的、真实的问题。在博客的其余部分,我们将从没有约束的普通优化开始。然后,我们将添加等式约束。然后,我们将描述具有等式和不等式约束的完全一般约束优化问题的解(这些条件被称为 KKT —卡鲁什、库恩、塔克条件)。最后,我们在一些玩具问题上展示了这些条件的力量。许多人认为 Nocedal 和 Wright 的书是数值优化的圣经,我们将大致遵循第 13 章,避开严格的证明(总是可以从文本中读到)并更多地关注视觉直觉。
无约束优化
在这个场景中,我们的控制中有一些变量和一个依赖于它们的目标函数。对变量没有约束,目标函数将被最小化(如果这是一个最大化问题,我们可以简单地否定目标函数,然后它将变成一个最小化问题)。
在任何一点,对于一个一维函数,函数的导数指向一个增加它的方向(至少对于小的步长)。这意味着,如果我们有一个函数 f(x)并且导数f’(x)为正,那么增加 x 将增加 f(x),减少 x 将减少 f(x)。如果我们要最小化 f(x),我们只需向与 f’(x) 符号相反的方向迈出一小步,就可以减小 f(x)。如果我们在一个点上f’(x)= 0 呢?然后,我们可能已经到达 f(x)的一个最优值,因为没有别的地方可去。
如果有多个变量(比如 x 和 y),我们可以对每个变量求导。如果我们用这两个数字构造一个二维向量,我们就得到了函数的梯度。现在,沿梯度方向移动将增加函数,而向相反方向移动将减少函数(对于小步长)。
这意味着只要梯度不为零,我们就不可能处于最小值,因为我们可以简单地沿着与梯度相反的方向迈出一小步,并进一步减小函数。这意味着最小化函数的点的必要(但非充分)条件是梯度在该点必须为零。
让我们举一个具体的例子,这样我们就可以想象这是什么样子。考虑函数 f(x,y) = x +y,这是一个抛物面,当 x=0,y=0 时最小化。关于 x 和 y 的导数分别变成 2x 和 2y。所以,梯度变成了矢量∇f = [2x,2y]。我们可以看到,只有当 x=0,y=0 时,这才是零。否则,梯度指向 f(x,y)将增加的方向。所以,与梯度相反的方向会减少 f(x,y)。如下图所示。粉色曲线是在绿点(0,0)处最小化的目标函数 f(x,y)。紫色箭头是梯度,它指向 f(x,y)增加的方向。为了减少它,我们向相反的方向移动,直到到达绿点。
Fig 1: Paraboloid with gradients. Made using https://github.com/ryu577/pyray
总而言之,当优化函数 f 时,在无约束优化问题中,处于局部最优的必要(但非充分)条件是:
∇f = 0
这就像当你站在山顶时(那将是一匹千里马)。你怎么知道你在顶端?无论你朝哪个方向走,你最终都会降低你的高度。所以你肯定是在当地的一个最佳状态。现在,你旁边可能还有一座更高的山。所以,你可能不在环球 optima。事实上,如果我们将地球表面视为我们的领域(将海拔高度视为我们的目标函数),如果你在任何一座古老的山峰(或建筑)的顶部,那么你就处于局部最优,但只有当那座山是珠穆朗玛峰时,你才处于全局最优。在本文中,我们将满足于寻找局部最优解。
如果我们想待在一个国家的范围内呢?这将意味着限制我们可以搜索最优解的空间,使这成为约束优化的一个例子。在某种程度上,无约束优化只是约束优化的一个特例。
平等约束
对于无约束最小化/最大化问题,我们简单地寻找梯度为零向量的点。如果梯度不为零,我们就向它指向的相反方向迈一小步(如果我们最小化;沿着它,如果我们最大化)并继续这样做,直到我们确实到达一个点,在那里它是零,因此,没有其他地方可去(这种优化方法被称为梯度下降)。请注意,我们不必完全沿着梯度移动。只要我们沿着梯度有正投影(阴影)的方向移动,我们最终会增加目标函数(如果我们沿着负梯度有正投影,则目标函数会减少)。下图说明了这一点。绿色箭头是蓝色平面的梯度(因此与其垂直),红色箭头是负梯度。因为浅蓝色的箭头位于平面上,如果我们沿着它们走一步,平面的方程将产生 0。黄色箭头沿着绿色箭头有一个正阴影(投影)。因此,沿着它们移动将导致当插入平面的方程时产生正数的点(“增加”它)。类似地,粉色箭头沿着红色箭头有一个正阴影(反向渐变)。因此,沿着它们移动将导致在插入平面方程时产生负数的点(“减少”它)。
Fig 2: Vectors on opposite sides of a plane. See text for explanation. Made using https://github.com/ryu577/pyray
对于无约束最小化,我们寻找梯度为零的点。这是因为如果不是这样,我们可以通过与梯度相反的方向来降低目标函数。
同样的想法可以扩展到我们有等式约束的情况。像以前一样,我们需要找到一个点,在这个点上我们找不到任何可能的方向来移动目标函数减小的地方。对于无约束优化,这仅仅意味着不存在这样的方向。当我们有一个约束时,还有另一种可能性。如果减少目标函数的方向存在,但是约束禁止我们沿着它前进。
假设你想最大化你银行账户里的钱。一个立即增加收入的方法是卖掉一个肾。但是你可能有一个约束,说你不会失去一个重要的器官。所以,即使有一条简单的途径可以增加你的收入,你的约束也会阻止你去实现它。
这意味着等式约束的存在实际上降低了梯度条件的严格性。虽然对于没有等式约束的局部最优,它需要为零,但现在只要沿着任何有正阴影的方向移动会导致我们违反约束,它就可以非零。这只有在约束平面垂直于渐变时才会发生(如图 2 中的平面和绿色箭头)。
让我们回到我们的目标函数 f(x,y)=x +y。让我们添加一个等式约束,y=1。这是架飞机。在下面的图 3 中,目标函数是粉红色的,平面是蓝色的。由于我们被约束在平面上,我们不能沿着平面的梯度(下图中的蓝色箭头)在任何有正或负阴影的方向上移动,因为这将增加或减少约束的等式,而我们希望保持它不变。该平面与我们的目标函数(粉红色抛物面)的方程相交于一条抛物线上。下图中的粉色箭头是目标函数在这条抛物线上各点的梯度。如果粉红色的箭头有一个沿着蓝色平面的投影,我们可以沿着与该投影对应的向量相反的方向移动。这将使我们保持在平面上,确保我们不违反约束,同时仍然减少目标函数。然而,在下面图 3 中的绿点处,粉色箭头(目标函数的梯度)在蓝色平面上没有任何投影。换句话说,粉色箭头平行于蓝色箭头(这是约束平面的渐变)。
Fig 3: Constraint gradient aligns with objective function gradient at optima. Made using https://github.com/ryu577/pyray
为了降低目标函数,我们需要沿着负梯度的方向移动。但是一旦我们这么做了,我们就会离开约束平面。因此,该约束使得不可能在绿点处进一步降低目标函数。这意味着它一定是局部最小值。检查该条件的一个简单方法是要求目标函数的粉色渐变平行于约束平面的蓝色渐变。如果两个向量平行,我们可以把其中一个写成另一个的倍数。我们称这个倍数为λ。如果目标函数的梯度是∇f,约束的梯度是∇c,则上述条件是:
∇f = λ ∇c
上面的λ叫做拉格朗日乘数。因此,我们现在有一个具体的条件来检查时,寻找局部最优的约束优化问题。
不等式约束
不等式约束意味着你必须呆在定义约束函数的边界的一边,而不是在边界上(等式约束就是这种情况)。例如,呆在栅栏的边界内。如果我们知道如何处理不等式约束,我们就可以解决任何约束优化问题。这是因为等式约束可以转换为不等式约束。假设我们要求:c(x) = 0。另一种表达方式是:c(x)≥0,c(x)≤ 0。因此,每个等式约束总是可以用两个不等式约束来代替。
正如带有等式约束的约束优化可以用前面部分描述的拉格朗日乘子来处理一样,带有不等式约束的约束优化也可以。将不等式约束条件与等式约束区分开来的是不等式约束的拉格朗日乘数必须为正。要知道为什么,再次考虑沿着梯度有一个正分量的方向迈出一小步。如果我们能沿着这个方向迈出一步(如果我们是最大化;相反,如果我们是最小化);我们不可能处于最大值/最小值。对于不等式约束,这意味着拉格朗日乘数为正。要了解原因,让我们回到我们之前考虑的约束优化问题(图 3)。
最小化:f(x,y) = x +y
服从:c(x,y)=y-1=0
现在,让我们将等式约束改为不等式约束。这可以通过两种方式实现,结果完全不同。我们可以要求:
c(x,y) = y-1 ≥0。在这种情况下,约束允许图 3 中蓝色平面前面的任何东西。很容易看出,图 3 中的绿点仍然是局部最优。此外,由于表示约束梯度的蓝色箭头和表示目标函数梯度的粉色箭头指向相同的方向,因此我们有:
∇f = λ ∇c
λ>0。
另一种可能是,c(x,y) = y-1≤0。现在,可行区域变成了蓝色飞机后面的一切*。约束梯度将翻转。因此,图 3 最终将看起来像这样:*
Fig 4: Flipping the sign of inequality constraint from figure 3.
请注意,现在,
- 绿点不再是局部最优,因为我们可以自由移动到(0,0);也就是上面图 4 中的黄点。
- 在绿点,我们仍然有∇f=λ ∇c.,因为蓝色向量指向粉红色向量的相反方向,我们有λ <0.
So, it is clear that for an inequality constraint, the condition ∇f=λ ∇c indicates we’re at a local optima only when λ> 0。
将所有这些放在一起,对于一般的优化问题:
最小化 f( x )
服从于:
对于 i ∈等式,c_i( x ) =0
对于 i ∈不等式,c_i( x )≥0
我们得到了达到局部最优所需的全套条件:
拉格朗日乘数条件;
**∇f =∑_ Iλ_ I ∇c_i(x)+∑_ jλ_ j ∇c_j(x);**等式(1)
其中 i ∈等式和 j ∈不等式约束。
对于所有 I,c _ I(x)= 0;等式(2)
对于所有 j,c _ j(x)≥0;等式(3)
λ_ j≥0;等式(4)
还要注意,对于我们考虑的两个不等式约束问题,当我们有 y-1≥0 时,图 3 中的绿点就是解。此时,我们在约束平面上(y-1=0)。所以,我们实际上有 c( x )=0 和λ > 0。
另一方面,当我们考虑 y-1≤0 时,图 4 中的黄点(x=0,y=0)成为局部最小值。这一点也是无约束问题的解决方案。所以,我们这里只有∇f=0。由于拉格朗日条件要求∇f = λ ∇c,我们得到λ ∇c = 0。现在,∇c 在这一点上≠0,这意味着我们必须有:λ=0。
这意味着如果约束是活动的(c( x )=0),我们应该得到λ≥0,而如果不是(c( x )≠ 0),我们应该得到λ=0。所以,在所有情况下,其中一个应该是零。这导致了最后一个条件(互补条件):
λ_j c_j( x ) = 0 对于所有 j ∈不等式;等式(5)
等式(1)到(5)被称为 KKT 条件。请注意,我们并没有真正为它们提供严格的证明,只是基于简单的例子来构造它们。为了证明这一点,读者应该参考诺塞达尔和赖特的书的第 13 章。
很多人看到这五个方程时,觉得问题变得更加复杂了。这些方程实际上如何帮助我们解决约束优化问题。感受这一点的最好方法是通过一些具体的例子。在下一节中,我们拿一个我们事先知道答案的样本问题,看看 KKT 条件如何帮助我们正确地识别所有局部最优解。
代码示例
广义优化问题的特殊情况涉及线性目标函数和线性约束。这被称为线性约束线性规划(LCLP)。目标函数和约束也可以是二次的,这样的优化问题称为二次约束二次规划(QCQP)。有一些软件包能够解决这类针对大量约束条件(数百万)的优化问题。然而,对于具有更多可管理的约束的简单问题,我们可以利用能够解决大多数(更一般的)多项式约束多项式程序的算法。这意味着目标函数和约束可以是任意多项式函数。这是因为有一个用于求解多项式方程组的通用框架,称为“Buchberger 算法”,并且上述 KKT 条件可以简化为多项式方程组。我在这里写了一篇关于 Buchberger 求解多项式方程组的算法的详细博客。有一个名为“sympy”的 python 库,它在幕后使用类似这样的算法,并求解一般的多项式方程组。所以,事不宜迟,让我们框架我们的第一个约束优化问题。
平等约束
Minimize: x³+y³
Subject to: x²+y²=1
注意,约束(x +y =1)意味着我们在半径为单位的圆的边界上。所以,我们可以说:x=cos(t),y=sin(t)。目标函数于是变成:sin (t)+cos (t)。如果我们用 t 来绘制,我们会得到下图:
Fig 5: Objective function sin³(t)+cos³(t) plotted with t at the boundary of the constraint.
我们可以看到 t=0,π/2 和 5π/4 对应于局部极大值,而 t=π/4,π和 3π/2 对应于局部极大值。既然我们预先知道了答案,让我们看看上面描述的 KKT 条件是否也能找到这些。
等式(1)给出(取目标函数和约束的导数):
[3x,3y ] = λ[2x,2y]
使两侧向量的两个分量相等会得到两个等式:
3x -2λx=0
3y -2λy=0
等式(2)简单地要求等式约束得到满足:
x +y =1
并且由于没有不等式约束,我们不需要方程(3)到(6)。现在,我们可以将上面的三个方程输入到 python 库 sympy 提供的符号方程求解器中。
这导致以下结果(上述系统的所有可能解,其中 x、y 和λ的值按此顺序排列):
[(-1, 0, -3/2),
(0, -1, -3/2),
(0, 1, 3/2),
(1, 0, 3/2),
(-sqrt(2)/2, -sqrt(2)/2, -3*sqrt(2)/4),
(sqrt(2)/2, sqrt(2)/2, 3*sqrt(2)/4)]
(-1,0)对应 t =π;(0,-1)对应 t = 3π/2;(-sqrt(2)/2,-sqrt(2)/2)对应于 t=5π/4,(sqrt(2)/2,sqrt(2)/2)对应于 t=π/4。因此,我们可以看到,我们上面确定的所有局部最大值和局部最小值都是由 KKT 条件确定的。现在,我们可以简单地在这些候选点找到目标函数的最大值和最小值。
不等式约束
现在,让我们把上面问题中的等式约束改为不等式约束,看看它如何改变我们的解。
Minimize: x³+y³
Subject to: x²+y²≤1
在前面的例子中,约束意味着我们只能在单位圆的边界上,现在我们可以在单位圆内的任何地方。
约束盘内目标函数的完整热图绘制如下(看起来像一个右上角有一颗星的行星)。红色箭头是约束边界的梯度,而黑色箭头是目标函数的梯度。
Fig 6: x³+y³ plotted within the disk x²+y²≤1
等式约束问题是一维问题,而不等式约束优化问题是二维的。而在一维中只有两种方法接近一个点(从左或右);在二维空间中有无数种方法可以接近它。这意味着我们需要小心鞍点。这些点有资格成为最优点,但不是真正的最优点,因为当你从一个方向接近它们时,它们是最大值,而当你从另一个方向接近它们时,它们是最小值。下图显示了鞍点的样子。
Fig 7: A saddle point. Maxima when you approach it from one direction, but minima when you approach it from another.
因此,我们需要重新评估在等式约束的情况下是局部最小值或最大值的所有点,并确保它们都不会成为鞍点。
图 5 告诉我们,当沿着边界接近时,t=0 (x=1,y=0)是局部最大值。当我们也从圆盘内部接近该点时(比如沿着连接 x=0,y=0 到该点的线),目标函数值随着我们接近它而增加。所以,t=0 是一个局部最大值,不管我们从哪里接近它。使用类似的论点(或者注意 x 和 y 的对称性),t=π/2 也是如此。
类似地,我们可以证明 t=π和 t=3π/2 是局部极小值,不管我们从可行域内的什么地方去接近它们。
然而,看看 t=π/4,我们从图 5 中注意到,沿着边界接近它使它成为局部最小值。然而,从圆盘内部接近它(例如,沿着原点到该点的连线)会使它成为局部最大值。所以,它总体上既不是局部极大值也不是局部极小值。这样的点称为鞍点。用类似的论证,t=5π/4 也是鞍点。
现在,让我们看看 KKT 条件对我们的问题是怎么说的。将目标函数和约束代入 KKT 方程(1)至(5),我们得到:
Equations 6 (a) through (e).
为了利用多项式方程解算器,我们需要将它们转换成一个多项式方程组。前两个条件(6-(a)和(b))已经是方程了。第三个,x +y ≤1 (6-©)是一个不等式。但我们可以通过引入松弛变量 k,将其转化为等式;x +y +k =1。最后一个等式,λ≥0 同样是一个不等式,但是如果我们简单地用λ代替λ,就可以把它去掉。现在,我们演示如何将这些输入 python 提供的符号方程求解库。
Code solving the KKT conditions for optimization problem mentioned earlier.
这产生了以下结果(上述系统的各种解,变量 x,y,λ,k 按顺序排列):
[(-1, 0, -sqrt(6)/2, 0),
(-1, 0, sqrt(6)/2, 0),
(0, -1, -sqrt(6)/2, 0),
(0, -1, sqrt(6)/2, 0),
(0, 0, 0, -1),
(0, 0, 0, 1),
(0, 1, -sqrt(6)*I/2, 0),
(0, 1, sqrt(6)*I/2, 0),
(1, 0, -sqrt(6)*I/2, 0),
(1, 0, sqrt(6)*I/2, 0),
(-sqrt(2)/2, -sqrt(2)/2, -2**(1/4)*sqrt(3)/2, 0),
(-sqrt(2)/2, -sqrt(2)/2, 2**(1/4)*sqrt(3)/2, 0),
(sqrt(2)/2, sqrt(2)/2, -2**(1/4)*sqrt(3)*I/2, 0),
(sqrt(2)/2, sqrt(2)/2, 2**(1/4)*sqrt(3)*I/2, 0)]
以上解决方案中的大写“I”指的是单位的平方根。我们想要拒绝这些解,因为我们要求λ ≥0。这意味着满足 KKT 条件的点是:(-1,0);(0,-1);(0,0)😭-1/sqrt(2),-1/sqrt(2))。如前所述,点(-1,0)(对应 t=π)和(0,-1)(对应 t=3π/2)为极小值。(0,0)和(-1/sqrt(2),-1/sqrt(2))是也陷入网中的鞍点。但是请注意,没有一个局部最大值被捕获。我留给你们一个小小的挑战。修改上面的代码,让它捕捉最大值而不是最小值。
如果你喜欢这个故事,成为推荐会员:)
https://medium.com/@rohitpandey576/membership
巴西亚马逊地区的土地利用和森林砍伐
使用卫星图像和深度学习进行环境保护
简介和问题陈述
为什么是卫星图像?
去年 11 月,在大会上参加数据科学沉浸式课程时,我很兴奋,并确信我将要学习的工具将有许多应用。我几乎不了解 Python,没有接触过数据帧,也不能告诉你太多关于神经网络的知识。但我确信会有令人兴奋的事情发生。
从那以后,我完成了这个项目,最值得骄傲的是,我的顶点项目使用来自星球的卫星图像,根据天气、土地利用和土地覆盖对巴西亚马逊地区的场景进行分类。
这个项目令人兴奋的原因有很多:
- 它给了我直接应用新技术解决生态保护问题的经验。
- 这项工作提供了一个机会,让我足不出户就可以研究地球上任何地方的任何生态系统。(这并不是因为我懒。这并不是因为我不喜欢旅行。我在生态学领域的一个关注点是找到我们可以研究这个星球的方法,而不用年复一年地乘飞机去实地考察和参加会议。这种目前的做法令人感到讽刺和质疑——随着我职业生涯的进一步发展,我仍在试图解开这一点。也许这是我们无法避免的。或者我们可以用新技术来推进这个领域,以更可持续的方式发展。)
- 它为未来的科学探索打开了新问题、新方法和新项目的潘多拉魔盒!
为什么是亚马逊?
许多生态学研究人员将注意力集中在热带和亚热带森林,因为地球上大部分的生物多样性和生物量都集中在这些地区。这些生态系统处于地球生态气候系统的中心,通过水、二氧化碳和氧气的循环影响区域和全球气候动态。
当然,这些森林是大量资源的家园,反过来又面临着来自森林砍伐和土地使用变化的巨大压力——以及全球气候变化。借助 Planet 等公司改进的卫星技术,我们可以找到远程监控这些珍贵生态系统的方法。通过机器学习模型,我们可以实时跟踪这些生态系统的变化,向当地政府和保护组织发出非法林业活动的警报,这些活动威胁着我们森林的生物多样性和生态气候功能。
收集数据
这个项目的数据来自这个 2017 Kaggle 比赛,由 Planet 收集和清理。
然而,为了演示用 Planet 的 API 生成我自己的图像,我构建了脚本来过滤和下载给定感兴趣区域(AOI)的图像。这是该项目的一个令人兴奋的方面,因为我非常喜欢数据管道工程任务,并探索新 API 的功能。
为监督学习分类问题生成我自己的图像的一些挑战是标记和格式化。图像没有固有的标签,因此如果我要收集足够多的图像(可能有数千个)来训练一个健壮的模型,标记可能是一个机械而费力的过程。此外,图像必须是标准大小才能用作神经网络的输入——编写一个程序将图像裁剪和剪切成标准格式本身就是一个项目!
考虑到时间限制,我决定继续研究 Kaggle 数据集。然而,随着时间和权限的增加(即访问 Planet 免费开放的加州图像之外的数据),Planet 的 API 对于未来的项目和应用来说是一个不可思议的资源。
Kaggle 数据集
这是我第一次涉足更严肃的大数据项目。该数据集包括一个训练数据集(40,000 张带标签的图像)和一个测试数据集——在竞赛网站上提交和评分的无标签图像。总的来说,这代表了超过 50 GB 的数据—远远超过了我的计算机上的 RAM(稍后会详细介绍)。
这些图像来自 PlanetScope 卫星,分辨率为 3m。包括分析 Geotiff 和可视 JPEG 格式,裁剪为 256 x 256 像素。图像包含四个颜色波段(红、绿、蓝、近红外),而 JPEGs 被校正为 EDA 的 3 波段视觉产品。
探索性数据分析
我的 EDA 的很大一部分包括更广泛地研究卫星图像数据。这是我第一次深入研究计算机视觉项目,所以这对我来说是一项相当大的任务。要了解更多这方面的内容,请查看我的另一篇媒体文章,主题是理解卫星图像中的图像数据和颜色通道。
在建模之前,了解数据集中不同标注分类的分布也至关重要。标签分为两类——天气和土地覆盖。图像只包含一个天气标签,但可以包含多个土地覆盖标签(这是多标签分类)。标签按类别组织如下:
- **天气标签:**晴,霾,多云,局部多云
- **土地使用和土地覆盖标签:**原始森林、道路、水、农业、住宅、裸地、耕作、开花、手工采矿、选择性伐木、刀耕火种、常规采矿、排放
下面,我绘制了图像标签在数据集中的出现频率。
Frequency of labels in the train dataset. Images can contain multiple labels
重要的是要注意到我们标签的严重不平衡。这在模型训练中是很重要的——模型将很难识别预测它没有频繁看到的标签所需的模式。
图像预处理
由于数据集庞大,需要克服各种障碍。为了准备用于建模的图像,必须从目录中读入图像以供神经网络处理。一种方法是通过名为 rasterio 的库。Rasterio 是一个很棒的库,因为它将地理位置数据保存在 tiffs 中,以防您在项目中使用这些信息。
我编写了一个自定义函数来实现这一点,但是,我缺少在单台机器上实现这一点所需的 RAM,我不得不尝试其他工具。
使用 AWS 迁移到云
一旦我掌握了在笔记本电脑上工作的挑战,我就改变了方式,使用亚马逊网络服务的深度学习 GPU 将项目转移到了云上。这让我在使用云中提供的大数据工具方面有了新的体验,并且需要调整弹性块存储卷来适应我的大型数据集。
然而,在使用 AWS 服务器时,我仍然面临内存限制,所以我必须使用 KERAS 自带的图像预处理工具来准备我的数据集进行建模。
测试时间增加
神经网络通过识别图像特征中的模式来“学习”。对于每个图像,特征是一个像素。然而,如果某种天气或土地类型只出现在图像的某个区域,神经网络将不会识别出图像中不同位置的完全相同的特征。
在 Keras 图像预处理中,我接触到了 ImageDataGenerator 类。这允许我应用测试时增强(随机翻转、旋转、缩放训练图像)来获得更好的建模方法。
Example TTA technique
图像数据生成器成批地从它们的目录中提取图像,读入图像,应用 TTA,并通过网络运行它们。这极大地减少了内存负载,并允许我训练神经网络,并在我的远程服务器上仅使用 7.5 GB RAM 的情况下对超过 50 GB 的图像进行预测。GPU 是令人难以置信的深度学习工具——如此不可思议,以至于我为它们创造了一个迷因!
建模
我构建了一个建模管道,可以适应多种模型和交叉验证。我计划训练一个更深层次的神经网络,并设置了一些功能来简化这个过程。不幸的是,在我不得不结束我的项目时,代码中的错误阻止了我在多个交叉验证折叠上训练神经网络(参见下面的限制和未来步骤部分)。
我使用了一个中等大小的卷积神经网络,带有调整大小的训练图像——由于内存和时间限制,缩小到 3 波段,128 x 128 像素。网络架构如下:
- 输入的批量规范化
- 32 过滤卷积层+最大池层+漏失(0.5)
- 64 过滤卷积层+最大池层+下降(0.5)
- 展平输出-128 节点密集连接图层+下降(0.5)
- 17 节点输出层(代表 17 个目标标签类)。
我在 25 个时期内训练了我的模型(首先,20 个时期→权重重新初始化→ 5 个时期)。
结果
我跟踪了准确性和 F-Beta 分数(它们遵循相似的趋势),但主要关注 F-Beta 分数。F-beta 是精确度和召回率(灵敏度)的平均值,包括对假阳性和假阴性的加权惩罚,因此与精确度相比分数较低。与准确度相比,它可以是更严格的分类度量,尤其是对于多标签分类。
验证数据的最终 F-Beta 分数为 0.843 。测试数据集上的预测被提交给 Kaggle,并具有相似的 F-Beta (0.834),表明我的模型在大范围的未知数据上概括得很好。该模型稍有欠拟合,这可能是由于网络中过度激进的 TTA 或过度正则化(在多个层中的 0.5 的下降),或者是由于对看不见的数据的标注的过度预测。
过度预测导致验证集上 F-beta 分数的相对不稳定性。对于验证数据(其中我们可以跟踪预测与真实标签),该模型预测了 10,000 张图像的 43,000 多个标签,其中只有 28,000 个真实标签。这可能导致 F-Beta 分数的不稳定性和更高的准确度分数。例如,如果预测每个图像的所有 17 个标签,则预测的准确度为 1(因为每个正确的标签都被考虑在内)。但是,F-Beta 分数会低得多,因为对于实际上不在图像中的所有标签,会有许多假阳性。
Comparison of True and Predicted Label frequencies after model validation.
不平衡的类别也极大地影响了模型预测。模型预测很少包括训练数据中初始观察值少于 1,000 的标签(见上文)。虽然这些图像可能在测试数据集中的代表性较低,但我们的模型能够区分和预测这些特征对于模型的实时应用仍然很重要。
未来的步骤和限制
- 限制每个图像或每个数据集的标签预测数量:为了纠正过度预测的问题,我可以在转换模型输出(概率)时限制可能的标签总数,以更好地反映标签的可能数量。这会是什么样子?第一,只考虑排名前T5【n的概率。在那些最高概率中,只接受那些高于阈值的概率。
- **使用多个阈值测试预测的 F-beta 分数:**模型输出 17 个概率,表示某个标签出现在每个图像中的可能性。然后,我们设置一个阈值,只接受高于阈值的概率。这些被转换为 1,意味着该特征在图像中。我对所有标签使用一个阈值。然而,改善模型结果的一种方法是更积极地为各个类别寻找最佳阈值。成功实现 k 重交叉验证和训练 k 个模型将允许 k 搜索最佳阈值。然后,我们可以选择每个折叠的平均阈值。
- **引导以平衡标签类别:**我还将通过具有低采样标签的目标图像来引导(创建“复制”不频繁标签的样本),增强那些图像并将增强的副本添加回数据集中。这可能会改进训练,而不管数据集中标签的初始频率(更多数据,由于扩充而不同的图像)。
- **投资强大的计算资源:**我的项目中的主要限制是 RAM。虽然访问远程 GPU 对于减少训练时间至关重要,但在整个项目中,我遇到了 RAM 过载的相当大的障碍(尽管我采取了措施来减少批量)。这些内存挑战,以及使用基于云的服务器的自付费用,也使得实验更深层次的神经网络变得困难(我对使用具有“ImageNet”权重的 ResNet 50 的潜力特别兴奋)。
- **用模型集成进行实验:**我通过在 Kaggle 讨论中的研究了解到集成对于神经网络的价值。在基本水平上,可以训练多个 CNN,并且可能对数据集中的某些标签做出更好的预测。然后可以组合来自每个神经网络的预测,并且对于每个输出(可能的标签),可以使用线性回归模型来预测每个图像的标签的“真实值”。不同的 CNN 预测将是预测目标值(1 或 0,存在或不存在)的特征。这些新值将仍然受制于用于在每个图像中存在或不存在标签时最终着陆的相同阈值。
- **考虑模型的有效性和资源的使用:**最有效的建模技术本质上需要无限的资源。虽然复杂的多模型集成方法可能会产生最佳的预测能力,但利益相关者必须考虑构建这样一个庞大的建模系统所需的成本(金钱和时间),以及如果模型要实时使用,分类速度会降低。这是一个正在进行的,逐例权衡的过程,但必须在深度学习的背景下考虑。
感谢阅读!请随意查看我在 GitHub 上的完整项目库。请分享你对我如何改进这个项目的方法的想法——我很想听听你的想法!
卡梅隆
使用生产数据的语言检测基准
这是多语言语言检测算法的真实社交媒体数据基准。
The Tower of Babel by Pieter Bruegel the Elder (1563)
作为数据科学家,我们习惯于处理许多不同类型的数据。但是对于基于文本的数据,了解数据的语言是重中之重。在为英语、西班牙语、法语和塞尔维亚语开发四种基于语言的算法时,我亲身经历了这一挑战。
一般来说,处理多语言 NLP 算法的第一步是:检测文本的语言。然而,在生产过程中,数据在需要处理的不同语言之间通常是不平衡的,这意味着在将数据发送给算法之前,必须定义每个数据点的语言。对于任何处理数据中语言不平衡的产品来说,显然不“丢失”数据是产品成功的关键。因此,为了确保产品不会丢失数据,我们必须确保数据不会因为 LD 故障而被发送到错误的算法。了解数据分布对于为任何研究项目找到一个好的关键绩效指标(KPI) 至关重要,尤其是对于这个基准测试项目。
测试集的采样数据:
对于这个基准测试,我希望测试集尽可能地代表我在生产中通常拥有的东西。因此,我从 Twitter 上选择了有语言参数的 10 万条帖子,包括 95780 条英语推文、1093 条西班牙语推文、2500 条法语推文和 627 条塞尔维亚语推文。这个分布代表了生产中大约两周的数据。
此外,为了获得最好的测试集,一些注释者手工检查并纠正了 Twitter 语言参数中的潜在错误。这意味着我将测试过的模型与这个事实进行了比较。我还可以通过正确标记数据来消除 Twitter LD 偏见。(这里有个好办法)。
测试算法:
对于这个语言检测(LD)基准,我对比了 多语种 LD ,Azure Text Analytics LD,Google Cloud LD,fast Text LD。
为了重现下面的代码,您需要 pip 安装所有导入的包。此外,您需要下载 FastText 算法,以创建 Azure API 信用和 Google Cloud API JSON 信用。
结果分析:
我的基准测试项目的结果表明,不同的模型服务于不同的度量。
**准确性:**如果准确性是最重要的指标,那么所有模型的表现几乎都是一样的(图 1)。
Figure 1: Global accuracy per model
然而,在我的项目中,准确的语言检测并不是唯一重要的 KPI。此外,防止数据丢失也很重要,因为如果数据丢失,产品将会失败。
**召回:**召回图(图 2)显示,尽管每个模型都非常精确,但总体而言,谷歌的模型在召回方面优于其他模型。
Figure 2: Recall by model for all languages
结论:
虽然第一直觉是只看准确性指标,这将导致有人假设 Azure 是语言检测的最佳表现者,但当其他指标发挥作用时,其他模型可能更好。在这种情况下,Google Cloud LD 在召回率方面优于 Azure(和所有其他测试的模型),特别是当正在处理的语言之间的数据不平衡时,其中有一个较大的数据集(英语),然后是其他语言(西班牙语、法语和塞尔维亚语)的明显较小的数据集。在我的特定项目中,回忆是主要的衡量标准,Google Cloud LD 最终是我的 LD 模型选择。
我要感谢来自 Zencity 的同事,他们在这个项目中发挥了重要作用:Inbal Naveh Safir、Ori Cohen 和 Yoav Talmi。
Samuel Jefroykin 是 Zencity.io 的一名数据科学家,他试图积极影响城市的生活质量。他还共同创立了 Data For Good Israel,这是一个致力于利用数据的力量解决社会问题的社区。
使用 RNNs 进行语言翻译
建立一个将英语翻译成法语的递归神经网络
2018 年 8 月 29 日由 托马斯·特雷西 ,原载 发布于 Github
西班牙语版本——此贴的西班牙语译文在此处,由*Ibidem Group提供。非常感谢!***
Image Credit: Peter Booth and Alexandra Booth / iStock
这篇文章探索了我在 Udacity 人工智能纳米学位项目的最终项目中的工作。我的目标是帮助其他学生和专业人士在机器学习(ML)和人工智能(AI)方面建立直觉的早期阶段。
尽管如此,请记住,我的职业是产品经理(不是工程师或数据科学家)。因此,接下来的内容是对这个项目中的 ML 概念和算法的半技术性但可接近的解释。如果下面提到的任何事情不准确,或者如果你有建设性的反馈,我很乐意听到你的意见。
我对这个项目的 Github 回购可以在这里找到。本项目的原始 Udacity 源回购位于此处。
项目目标
在这个项目中,我建立了一个深度神经网络,作为机器翻译管道的一部分。管道接受英语文本作为输入,并返回法语翻译。目标是尽可能实现最高的翻译准确性。
为什么机器翻译很重要
相互交流的能力是人类的一个基本组成部分。全世界有将近 7000 种不同的语言。随着我们的世界变得越来越紧密,语言翻译为来自不同国家和种族的人们提供了重要的文化和经济桥梁。一些比较明显的用例包括:
- 商业:国际贸易、投资、合同、金融
- 商业:旅游、购买外国商品和服务、客户支持
- 媒体:通过搜索获取信息,通过社交网络分享信息,内容本地化和广告
- 教育:分享想法,合作,翻译研究论文
- 政府:外交关系,谈判
为了满足这些需求,技术公司正在大力投资机器翻译。这项投资和深度学习的最新进展极大地提高了翻译质量。根据谷歌的说法,与之前在谷歌翻译中使用的基于短语的方法相比,切换到深度学习使翻译准确度提高了 60%。今天,谷歌和微软可以翻译 100 多种不同的语言,其中许多语言的准确度已经接近人类水平。
然而,尽管机器翻译已经取得了很大的进步,但它仍然不完美。😬
Bad translation or extreme carnivorism?
本项目的方法
为了将英语文本的语料库翻译成法语,我们需要建立递归神经网络(RNN)。在深入实现之前,让我们先对 rnn 建立一些直觉,以及为什么它们对 NLP 任务有用。
RNN 概述
rnn 被设计成接受文本序列作为输入,或者返回文本序列作为输出,或者两者都接受。之所以称之为递归,是因为网络的隐藏层有一个循环,其中每个时间步的输出和单元状态成为下一个时间步的输入。这种重现是一种记忆形式。它允许上下文信息在网络中流动,以便先前时间步的相关输出可以应用于当前时间步的网络操作。
这类似于我们阅读的方式。当你读这篇文章的时候,你正在储存以前的单词和句子中的重要信息,并用它作为理解每个新单词和句子的上下文。
其他类型的神经网络(还)做不到这一点。想象一下,您正在使用卷积神经网络(CNN)来执行电影中的对象检测。目前,没有办法从先前场景中检测到的对象信息通知模型在当前场景中检测到的对象。例如,如果在前一个场景中检测到法庭和法官,该信息可以帮助正确分类当前场景中法官的木槌,而不是将其错误分类为锤子或木槌。但是 CNN 不允许这种类型的时间序列上下文像 RNNs 一样在网络中流动。
RNN 设置
根据不同的用例,您可能希望设置您的 RNN 来以不同的方式处理输入和输出。对于这个项目,我们将使用多对多流程,其中输入是一系列英语单词,输出是一系列法语单词(下图中左起第四个)。
Diagram of different RNN sequence types. Credit: Andrej Karpathy
每个矩形是一个向量,箭头代表函数(如矩阵乘法)。输入向量是红色的,输出向量是蓝色的,绿色向量代表 RNN 状态(稍后会有更多介绍)。
从左到右:(1)没有 RNN 的普通处理模式,从固定大小的输入到固定大小的输出(例如图像分类)。(2)序列输出(例如图像字幕拍摄图像并输出一句话)。(3)序列输入(例如,情感分析,其中给定句子被分类为表达积极或消极情感)。(4)顺序输入和顺序输出(例如机器翻译:一个 RNN 读一句英语,然后输出一句法语)。(5)同步序列输入和输出(例如,视频分类,其中我们希望标记视频的每一帧)。请注意,在每种情况下,长度序列都没有预先指定的约束,因为递归转换(绿色)是固定的,可以应用任意多次。
— Andrej Karpathy,递归神经网络的不合理有效性
建设管道
下面是各种预处理和建模步骤的总结。高级步骤包括:
- 预处理:加载和检查数据、清洗、分词、填充
- 建模:构建、训练、测试模型
- 预测:生成英语到法语的特定翻译,并将输出翻译与实际翻译进行比较
- 迭代:迭代模型,试验不同的架构
要获得包括源代码在内的更详细的演练,请查看项目报告中的 Jupyter 笔记本。
结构
在这个项目中,我们使用 Keras 作为前端,TensorFlow 作为后端。我更喜欢在 TensorFlow 上使用 Keras,因为语法更简单,这使得构建模型层更直观。但是,Keras 有一个代价,因为您失去了进行细粒度定制的能力。但这不会影响我们在这个项目中构建的模型。
预处理
加载&检查数据
这是一个数据样本。输入是英语句子;输出是法语的相应翻译。
当我们进行字数统计时,我们可以看到数据集的词汇非常少。这是这个项目的设计。这允许我们在合理的时间内训练模型。
清洁
此时不需要进行额外的清洁。数据已经被转换为小写并被拆分,因此所有单词和标点符号之间都有空格。
注意:对于其他 NLP 项目,您可能需要执行额外的步骤,例如:移除 HTML 标签、移除停用字词、移除标点符号或转换为标签表示、标注词性或执行实体提取。
标记化
接下来,我们需要对数据进行标记化——即,将文本转换成数值。这允许神经网络对输入数据执行操作。对于这个项目,每个单词和标点符号将被赋予一个唯一的 ID。(对于其他 NLP 项目,给每个字符分配一个唯一的 ID 可能是有意义的。)
当我们运行 tokenizer 时,它会创建一个单词索引,然后用来将每个句子转换成一个向量。
填料
当我们将单词 id 序列输入到模型中时,每个序列都需要有相同的长度。为了实现这一点,填充被添加到任何比最大长度短的序列(即比最长的句子短)。
一键编码(未使用)
在这个项目中,我们的输入序列将是一个包含一系列整数的向量。每个整数代表一个英文单词(如上图)。然而,在其他项目中,有时需要执行一个额外的步骤来将每个整数转换成一个独热编码向量。我们在这个项目中没有使用一键编码(OHE),但是你会在某些图中看到它的引用(如下图所示)。我只是不想让你困惑。
OHE 的优势之一是效率,因为它可以以比其他编码更快的时钟速率运行。另一个优点是,OHE 可以更好地表示不同值之间没有顺序关系的分类数据。例如,假设我们将动物分为哺乳动物、爬行动物、鱼类或鸟类。如果我们将它们分别编码为 1,2,3,4,我们的模型可能会假设它们之间有一个自然的排序,但实际上并没有。把我们的数据组织成哺乳动物在爬行动物之前是没有用的。这可能会误导我们的模型,导致糟糕的结果。然而,如果我们随后对这些整数应用一键编码,将它们更改为二进制表示形式(分别为 1000、0100、0010、0001 ),那么模型就无法推断出序数关系。
但是,OHE 的一个缺点是向量会变得很长很稀疏。向量的长度由词汇表决定,即文本语料库中唯一单词的数量。正如我们在上面的数据检查步骤中看到的,我们这个项目的词汇量非常小——只有 227 个英语单词和 355 个法语单词。相比之下,牛津英语词典有 172000 个单词。但是,如果我们包括各种专有名词、单词时态和俚语,每种语言可能有数百万个单词。例如,谷歌的 word2vec 是在 300 万个独特词汇的基础上训练出来的。如果我们在这个词汇表中使用 OHE,每个单词的向量将包括一个被 2,999,999 个零包围的正值(1 )!
而且,由于我们正在使用嵌入(在下一步中)来进一步编码单词表示,我们不需要为 OHE 费心。对于这么小的数据集,任何效率提升都是不值得的。
建模
首先,让我们从高层次上分析一下 RNN 的架构。参考上图,我们需要了解模型的几个部分:
- 输入。输入序列被输入到模型中,每个时间步长一个单词。每个单词都被编码为一个唯一的整数或独一无二的编码向量,映射到英语数据集词汇。
- 嵌入层。嵌入用于将每个单词转换成一个向量。向量的大小取决于词汇的复杂程度。
- ****递归层(编码器)。这是将先前时间步骤中的单词向量的上下文应用于当前单词向量的地方。
- ****密集层(解码器)。这些是典型的全连接层,用于将编码输入解码成正确的翻译序列。
- 输出。输出以整数序列或独热编码向量的形式返回,然后可以映射到法语数据集词汇表。
嵌入
嵌入允许我们捕捉更精确的句法和语义单词关系。这是通过将每个单词投影到 n 维空间中来实现的。意义相似的词占据这个空间的相似区域;两个词越接近,就越相似。单词之间的向量通常代表有用的关系,如性别、动词时态,甚至地缘政治关系。
Photo credit: Chris Bail
从头开始在大型数据集上训练嵌入需要大量的数据和计算。因此,我们通常使用预先训练好的嵌入包,如手套或 word2vec ,而不是自己动手。以这种方式使用时,嵌入是一种迁移学习的形式。然而,由于我们这个项目的数据集只有很少的词汇和很低的语法变化,我们将使用 Keras 来训练我们自己的嵌入。
编码器和解码器
我们的序列到序列模型链接了两个递归网络:编码器和解码器。编码器将输入汇总到一个上下文变量中,也称为状态。然后解码该上下文,并生成输出序列。
Image credit: Udacity
由于编码器和解码器都是递归的,它们有循环,在不同的时间步处理序列的每个部分。为了描述这一点,最好展开网络,这样我们就可以看到每个时间点发生了什么。
在下面的例子中,编码整个输入序列需要四个时间步长。在每个时间步,编码器“读取”输入单词,并对其隐藏状态进行转换。然后将隐藏状态传递给下一个时间步。请记住,隐藏状态表示流经网络的相关上下文。隐藏状态越大,模型的学习能力越大,但计算需求也越大。当我们讨论门控循环单元(GRU)时,我们将更多地讨论隐藏状态中的转换。
Image credit: modified version from Udacity
现在,请注意,对于序列中第一个单词之后的每个时间步长,有两个输入:隐藏状态和序列中的一个单词。对于编码器,它是输入序列中的下一个字。对于解码器,它是输出序列中的前一个字。**
此外,请记住,当我们提到“单词”时,我们实际上是指来自嵌入层的单词的矢量表示*。*
这是另一种可视化编码器和解码器的方法,除了普通话输入序列。
Image credit: xiandong79.github.io
双向层
现在我们已经了解了上下文是如何通过隐藏状态在网络中流动的,让我们更进一步,允许上下文双向流动。这就是双向层的作用。
在上面的例子中,编码器只有历史上下文。但是,提供未来的上下文可以获得更好的模型性能。这似乎与人类处理语言的方式相违背,因为我们只能单向阅读。然而,人类经常需要未来的上下文来解释正在说的话。换句话说,有时直到最后提供了一个重要的单词或短语,我们才理解一个句子。尤达一说话就会这样。😑 🙏
为了实现这个,我们同时训练两个 RNN 层。第一层按原样输入输入序列,第二层输入反向拷贝。
Image credit: Udacity
具有门控递归单元的隐藏层(GRU)
现在让我们让我们的 RNN 更聪明一点。与其让隐藏状态的所有信息在网络中流动,不如我们更有选择性?也许一些信息更相关,而其他信息应该被丢弃。这基本上就是门控循环单元(GRU)所做的。
GRU 中有两个门:更新门和复位门。西蒙·科斯塔迪诺夫的这篇文章详细解释了这些。总之,更新门 (z)有助于模型确定有多少来自先前时间步骤的信息需要传递到未来。同时,复位门 ®决定要忘记多少过去的信息。
Image Credit: analyticsvidhya.com
最终模型
既然我们已经讨论了模型的各个部分,让我们来看看代码。同样,所有的源代码都可以在笔记本 ( )的中找到。html 版本)。
结果
最终模型的结果可以在笔记本的单元格 20 中找到。
验证准确率:97.5%
训练时间:23 个时代
未来的改进
- 进行适当的数据分割(培训、验证、测试)。目前,没有测试集,只有训练和验证。显然,这不符合最佳实践。
- LSTM +关注。这是过去几年中 rnn 的事实架构,尽管有一些限制。我没有使用 LSTM,因为我已经在另一个项目中用 TensorFlow 实现了它,我想在这个项目中用 GRU + Keras 做实验。
- 在更大更多样化的文本语料库上训练。这个项目的文本语料库和词汇非常小,语法变化很小。因此,模型非常脆弱。为了创建一个更好的概括模型,你需要在语法和句子结构上有更多可变性的更大的数据集上进行训练。
- 残留层。你可以添加残余层到一个深 LSTM RNN,如本文所述。或者,使用剩余层作为 LSTM 和 GRU 的替代,如这里所述。
- 嵌入。如果你在一个更大的数据集上训练,你肯定应该使用一组预训练的嵌入,比如 word2vec 或者 GloVe 。更好的是,使用 ELMo 或 BERT。
- 嵌入语言模型(ELMo) 。2018 年通用嵌入最大的进步之一是 ELMo ,由艾伦人工智能研究所开发。ELMo 的主要优势之一是它解决了一词多义的问题,即一个单词有多个意思。ELMo 是基于上下文的(不是基于单词的),因此一个单词的不同含义在嵌入空间中占据不同的向量。使用 GloVe 和 word2vec,每个单词在嵌入空间中只有一个表示。例如,“queen”这个词可以指皇室的女族长、蜜蜂、棋子或 20 世纪 70 年代的摇滚乐队。对于传统的嵌入,所有这些含义都与单词 queen 的一个向量联系在一起。对于 ELMO,这是四个不同的向量,每个向量都有一组独特的上下文单词,占据嵌入空间的相同区域。例如,我们期望在与国际象棋游戏相关的类似向量空间中看到像皇后*、车和卒这样的词。我们期待看到蜂后、蜂房和蜂蜜出现在与蜜蜂相关的不同向量空间中。这极大地促进了语义编码。*
- 双向编码器表示来自 变压器 (BERT) 。2019 年到目前为止,双向嵌入最大的进步是 BERT ,由谷歌开源。伯特有什么不同?
诸如 word2vec 或 GloVe 之类的上下文无关模型为词汇表中的每个单词生成单个单词嵌入表示。例如,单词“bank”在“bank account”和“bank of the river”中具有相同的上下文无关的表示相反,上下文模型根据句子中的其他单词生成每个单词的表示。例如,在句子“我访问了银行帐户”中,单向上下文模型将基于“我访问了”而不是“帐户”来表示“银行”然而,BERT 使用它的上一个和下一个上下文来表示“银行”——“我访问了……账户”——从深度神经网络的最底层开始,使其具有深度双向。
—雅各布·德夫林和张明蔚,谷歌人工智能博客
接触
我希望你觉得这很有用。同样,如果你有任何反馈,我很想听听。欢迎在评论中发表。
如果你想讨论其他合作或职业机会,你可以在 LinkedIn 这里找到我,或者在这里查看我的作品集。
Laravel 和 Vue.js:这对情侣为什么会红?
你可能想知道 VueJS 和 Laravel 怎么会有关系。VueJS 是一个 Javascript 框架,Laravel 是一个 PHP 框架,它们不可能互相服务于任何目的,不是吗?记住,如果在任何时候你觉得事情超出了你的能力范围,你可以随时雇佣一个开发人员。
然而,要理解这一点,您首先需要用这么多的事实来启发自己,这是一个详尽的停止,在这里您将找到您需要了解的关于这两个框架的一切,更不用说它们如何对彼此有用了。再来说说 Vue。JS 第一。
简单介绍一下 Vue。射流研究…
如果你还不知道的话,Vue。JS 是一个非常高级的 Javascript 框架,是为设计用户界面和单页应用程序而构建的。VueJS 由尤雨溪开发,是一个开源的 javascript 框架,具有自适应的架构。它侧重于声明性呈现和组件组合。
目前 Vue.js 在 GitHub 上有超过 148k 颗星,这说明了它在开发者中的受欢迎程度。如果你是一个前端框架爱好者,那么你会惊讶于它是如何无缝地集成到大型项目中并简化 web 开发过程的。
好书 : 将统治 2020 年的顶级软件趋势
VueJS 的 5 大特点
到目前为止,我上面所说的一切都是空谈,但让我们深入了解它的具体特性,并向您展示为什么 Vue 应该是您的下一个框架
虚拟 Dom
您在 Vue 中引入的任何修改都不会直接反映在 DOM 中。相反,DOM 的副本是作为 Javascript 数据结构创建的。如果需要进行更改,那么它们会被引入到数据结构的 Javascript 中。然后将它与初始数据结构进行比较,这样可以节省大量时间。
数据绑定
数据绑定是一个过程,通过该过程,用户可以使用 web 浏览器操纵网页的元素。它利用动态 HTML,不需要任何复杂的脚本或编程。在这个函数的帮助下,您可以轻松地管理值或将它们分配给 HTML 属性。
成分
VueJS 的一个特征是它能够重用组件。这些组件帮助您扩展基本的 HTML 元素来封装可重用的代码。
动画/过渡
在 VueJS 中,当 HTML 元素被添加到 DOM 或从 DOM 中删除时,您会发现几种在 HTML 元素中应用转换的方法。它有一个内置的过渡组件,必须环绕元素才能获得过渡效果。我们也可以添加第三方动画库。
模板
Vue。JS 附带了基于 HTML 的模板,这些模板将 DOM 与 Vue 实例数据绑定在一起。Vuejs 将这些模板编译成虚拟 DOM 渲染函数。为了使用渲染函数模板,我们必须用渲染函数替换模板。
关于拉勒维尔的一点简介
Laravel 是一个基于 PHP 的免费开源 web 框架。Laravel 由 Taylor Otwell 创建,旨在提高生产率。他们每 6 个月推出一个新版本,最近他们在两周前的 9 月 3 日推出了最新版本,这个版本有长期支持(LTS)。Laravel 具有过多的功能。让我们来看看其中的一些。
也读: 如何在预算内 雇佣 React 开发者 ?
Laravel 的五大特点
雄辩的 ORM
ORM 或对象关系映射是活动记录模式的 PHP 实现。它允许我们做的是将数据库表表示为类。如果您感到困惑,这意味着您可以定义一个类,比如说“User”,它将绑定到数据库中的“users”表。现在“users”表中的每一行都将被表示为 Laravel 中 User 类的一个实例。
模板引擎
Laravel 因其轻量级模板而得到高度认可,该模板可以帮助您使用动态内容播种来创建令人惊叹的布局。最重要的是,它有多个包含 CSS 和 JS 代码的小部件,结构坚固。laravel 框架的模板是专门设计来创建具有独特部分的简单布局的。
技工
Laravel 提供了一个名为 Artisan 的内置命令行工具。它们用于创建数据库结构、框架代码,并构建它们的迁移,这使得管理数据库系统变得非常容易。不仅如此,它还可以通过命令行瞬间交错生成基本的 MVC 文件,并管理那些资产及其各自的配置。
自动包裹递送
过去,安装数据包并不容易,直到 Laravel 5.5 推出了一个方便的解决方案。顾名思义,Automatic Package Delivery 自动检测用户想要安装的软件包,而不需要设置任何别名或提供者来安装新的软件包。
数据库迁移
Laravel 的命令行界面(CLI)Artisan 使数据库迁移和播种变得极其容易。如果您将所有数据库工作都放在迁移和种子中,那么您可以轻松地将更改迁移到您拥有的任何其他开发机器上。
好读: 现在你可以 以 60%的成本雇佣 laravel 开发者
VueJS 是如何工作的?
如果您在事件驱动的前端 JavaScript 框架出现之前曾经为 web 编程,那么您可能会理解尝试更新文档对象模型(DOM)会带来相当大的困难和低效。
更新 DOM 仅仅意味着您必须获取页面,对其中的一小部分进行必要的更改,然后重新加载整个 DOM,这样更改才能生效。例如,如果你正在观看一个 YouTube 视频,并且添加了新的评论,那么整个页面都必须重新加载,这也意味着你的视频将从头开始。
Vue 通过整合虚拟 DOM 来管理用户将看到的内容,努力应对这些挑战。就像我上面说的,Vue 本质上做的是创建 DOM 的副本并存储它。如果对 DOM 的一部分做了任何更改,它只更新 DOM 的那个部分,而不重新加载整个 DOM。这意味着评论会在你没有注意到的情况下更新。
Vue 提供了可反应的和可组合的视图组件。它响应任何更新,并立即触发 DOM 中所需的更改。它的可组合组件可以选择和组装成各种组合,以满足任何需要。你可以为所有的事情准备组件,并根据你的需要重用它们。如果这很难理解,你可以雇佣一个 VueJS 开发者。
好读: 如何能在印度 雇佣安卓开发者 以更少的成本
为什么我们应该将 Vue 与 Laravel 一起使用?
尽管 Laravel 和 VueJS 来自不同的编程语言,而且 VueJS 如何支持 Laravel 似乎无关紧要,但令我惊讶的是,它支持的方式不止一种。以下是您应该将 VueJS 与 Laravel 一起使用的原因:-
1.一切都发生在前端
当今的 Web 应用程序是事件驱动的。它们的构建是为了确保用户拥有无缝的体验,就像他们使用安装在他们计算机上的应用程序一样。所有的改变都发生在前端,用户再也不用重新加载页面了(感谢 JavaScript)。
2.反应式组件构成了一个优秀的事件驱动应用程序
Vue 可以帮助您构建一个全面的事件驱动的 web 应用程序,处理前端的所有活动。它还提供了可以任意使用的可组合组件。鉴于它与 Laravel 配合得很好,您只需往返几次就可以从 Laravel 应用程序请求数据,并通过切换组件来更改 UI,而无需重新加载页面。
您可以简单地在您的 Vue(前端)中提示 UI 更改,这反过来为您的用户提供了一个惊人的体验。它可以简单到使页面上的文本可编辑,或者换出整个组件来加载用户请求的视频,而无需重新加载页面。
鉴于 Vue 的速度和性能,这发生得非常快和顺利,而不占用你的电脑资源这么多。
3.构建最佳复杂前端页面
如果您考虑构建一个部分需要频繁更新的应用程序,除了让前端完全运行在 JavaScript 上,您没有其他选择。
没有虚拟 DOM 的普通 JavaScript 或 jQuery 或其他 JavaScript 库面临的挑战是,随着更新频率的增加或跟踪变化的数据量的显著增加,您很快就会遇到性能问题。对 DOM 的更改将逐渐不再是即时的,您将开始体验到明显的性能滞后。
当您使用 Vue 组件编写应用程序时,每个组件的依赖关系都会在呈现过程中被自动跟踪,因此当数据发生变化时,系统可以准确地知道哪个组件实际上需要更新。这使得对 DOM 的所有更新使用最少的资源,从而提高了整个应用程序的效率。
Vue 还与 Flux、Redux 和 Vuex 等状态管理器兼容,这些管理器在管理复杂应用程序中的数据流方面表现出色。Vue 对单向数据绑定模型的利用也使得复杂应用程序中的状态管理更加容易。
4.单页应用程序
我想分享一个个人观点——单页应用程序是过去十年中互联网上发生的最伟大的事情。它向比以前更广泛的用户开放了应用程序。
当你考虑到美国和欧洲某些地区之外的许多互联网用户在上网方面有困难时,你开始意识到单页应用程序在向他们提供丰富的网络体验方面所起的作用。
您的整个应用程序资产被加载一次(其中大部分被缓存),当用户使用它时,您的应用程序所做的只是请求数据,这通常需要很低的带宽来完成。
5.易于学习和使用
Vue 很容易进入。作为开发人员,它为您提供的选项很少,而且抽象了很多。当你使用 Vue 时,你会觉得你在编写普通的 JavaScript,你可以用普通的 JavaScript 编写一个简单的应用程序,它在 Vue 中仍然有效。
Vue 的另一个优点是你的有效 HTML 也是一个有效的 Vue 模板。您可以将 CSS 保留在外部,也可以根据您的应用程序需求用 JavaScript 来处理它。您还可以利用作用域样式,在不影响其他组件的情况下,动态地将样式更改应用于单个组件。
如果您熟悉 JavaScript,只需花一天时间阅读文档,就可以用 Vue 构建一个不平凡的应用程序。
结论
现在,您已经非常详细地了解了 Vue 和 Laravel,并且了解了如何将 Laravel 和 VueJS 集成在一起,将有助于您获得两者的最佳效果。这些框架分别为世界上一些主要的 web 应用程序做出了贡献,想象一下你可以用它们一起做什么。如果你想雇佣一个 PHP 开发人员或者甚至雇佣一个 VueJS 开发人员,你可以很容易地找到他们,因为他们是市场上最受欢迎的一些框架。
大型图形可视化工具和方法
怎么办,如果你需要可视化一个大型网络图但是你尝试的所有工具都只能画一个毛球或者吃掉你所有的 RAM 挂你的机?两年多来,我一直从事大型图形(上亿个节点和顶点)的工作,并且尝试了很多工具和方法。但是我仍然没有找到任何好的调查,所以现在我自己写这样一份调查。
(这是我在 habr 上的文章的翻译,原文是俄语)
为什么要可视化一个图表呢?
- 找什么找什么
通常,我们只是简单地有一组顶点和边作为输入。我们可以根据这样的数据计算一些统计数据或图形度量,但这还不足以了解结构。一个好的可视化可以清楚地显示图形中是否有一些集群或桥,或者可能是均匀的云,或者其他什么。 - 为了给公众留下深刻印象,数据可视化显然是用来展示的。这是展示已完成工作的结论的好方法。例如,如果您解决了一个聚类问题,您可以通过标签为您的图着色,并显示它们是如何连接的。
- 获取特征
尽管大多数图形可视化工具只是为了制作一些图片而创建的,但它们也是很好的降维工具。表示为邻接矩阵的图是高维空间中的数据。当我们画它的时候,每个顶点有两个(通常)坐标。这些坐标也可以用作特征。这个空间中顶点之间的接近意味着相似。
大图表有什么问题?
我的意思是“大图”的大小大约从 10K 顶点和/或边。尺寸小一点的通常没有问题。通过几分钟的搜索,你能找到的所有工具很可能至少可以接受。大型网络有什么问题?主要有两个问题:可读性和速度。通常,大型图形的可视化看起来很混乱,因为在一个图中有太多的对象。此外,图形可视化算法大多有可怕的算法复杂性:边或顶点的数量的二次或三次依赖。就算等一次结果,找到更好的参数也太久了。
关于这个问题已经写了什么?
[1] Helen Gibson,Joe Faith 和 Paul Vickers:“信息可视化二维图形布局技术综述”
本文的作者讲述了现有的图形可视化方法以及它们是如何工作的。还有一个很好的表格,里面有关于算法、它们的特性和复杂性的信息。我在这篇文章中使用了那篇论文中的一些图片。
[2]Oh-Hyun Kwon、Tarik Crnovrsanin 和 Kwan-刘妈“在这种布局下,图表看起来会是什么样?大型图形可视化的机器学习方法"
作者做了大量的工作。他们尝试了所有可能的算法。然后他们画出来,人工评估相似度。之后,他们拟合模型来预测图表在这种布局下会是什么样子。我也使用了这幅作品中的一些图片。
理论部分
布局是一种将坐标映射到每个顶点的方法。通常,这是 2D 平面上的坐标。
什么是好的布局?
很容易判断某物看起来是好是坏。命名标准并不容易,机器怎么能评估它。为了做出所谓的“好”布局,可以使用美学度量。以下是其中的一些:
- 最小边缘交点
显而易见:过多的交点会使情节看起来混乱。 - 相邻的顶点比不相邻的顶点彼此更靠近
这是连接的节点应该彼此靠近的逻辑。根据定义,它代表了图表中的主要信息。 - 社区被分组为簇
如果有一组顶点相互之间的连接比图中的其他部分更频繁,它们应该看起来像一朵密集的云。 - 最小重叠边和节点。
同样显而易见的是:如果我们不能确定顶点是少还是多,那么绘图的可读性就很差。
存在哪种布局?
我认为提及这三种类型的布局很重要。然而,可以用许多其他方式对它们进行分类。但是这种分类足以浏览所有可能的类型。
- 力导向和基于能量
- 降维
- 基于节点特征
力导向和基于能量
Force-directed layouts examples. Source of the picture is [1]
这类方法基于物理系统模拟。顶点被表示为相互排斥的带电粒子,边被视为弹性弦。这些方法试图模拟这个系统的动态或找到最小能量。
这种方法通常给出非常好的结果。结果图很好地反映了图形的拓扑结构。但是它们也很难计算,并且有许多参数需要调整。
这个家族的重要成员有原力·阿特拉斯、弗吕赫特曼-莱因戈尔德、卡马达·卡哇伊和奥彭德。最后一个使用巧妙的优化来加快计算速度,例如,它切割长边。因为一个有用的副作用图表变得更加聚集。
降维
Dimension reduction layouts examples. Source of the picture is [1]
一个图可以定义为邻接矩阵 NxN,其中 N 是节点数。这个矩阵也可以被视为 N 维空间中的 N 个对象的表格。这种表示允许我们使用通用的降维方法,如 PCA、UMAP、tSNE 等。另一种方法是计算节点之间的理论距离,然后在移动到低维空间时尝试节省比例。
基于特征的布局
Hive Plot example. Source of the picture is [1]
通常,图形数据与现实世界中的一些对象相关。因此顶点和边可以有自己的特征。因此我们可以用这些特征在平面上表示它们。我们可以使用上述降维方法或通过直接绘制成对特征的散点图,像处理通常的表格数据一样处理节点特征。值得一提的是蜂巢图,因为它与所有其他方法都很不同。在蜂巢图中,节点与几个径向轴对齐,边是它们之间的曲线。
大型图形可视化工具
The joy of graph visualization.
尽管图形可视化问题相对古老和流行,但对于可以处理大型图形的工具来说,情况非常糟糕。大部分都被开发商抛弃了。几乎每一种都有它们的大缺点。我将只讲述那些值得一提并能处理大图的人。关于小图,没有问题。你可以很容易地找到一个工具来实现你的目的,而且很有可能它会工作得很好。
GraphViz
Bitcoin transaction graph before 2011
Sometimes it’s hard to tune the parameters
这是一个老派的 CLI 工具,有自己的图形定义语言“dot”。这是一个有几种布局的包。对于大型图形,它有sfdp
布局,来自 force-directed 系列。这个工具的优点和缺点是一样的:它从命令行运行。这对自动化很有用,但是没有交互性就很难调整参数。你甚至不知道你需要等待结果多久,也不知道你是否需要停止它,用其他参数重新运行。
格菲
Image from gephi.org
137K movies recommendation graph from iMDB
A few million is already too much for Gephi
我所知道的最强大的图形可视化工具。它有图形用户界面,它包含几个布局和大量的图形分析工具。还有很多社区写的插件。例如,我最喜欢的布局“Multigravity Force-Atlas 2”或 sigma.js 导出工具,它可以根据您的项目创建交互式网页模板。在 Gephi 中,用户可以根据它的特性给节点和边着色。
但是 Gephi 被开发者抛弃了。它也有一个有点过时的图形用户界面,缺乏一些简单的功能。
igraph
Last.fm music recommendation graph. Source, description and interactive version are here
我需要向这个通用图形分析包致敬。最令人印象深刻的图形可视化之一是由 igraph 的作者之一制作的。
igraph 的缺点是 python API 的文档很糟糕,但是源代码是可读的,并且有很好的注释。
LargeViz
Several tens of million vertices (transactions and addresses) in one of the largest bitcoin clusters
当你需要画一张真正巨大的图表时,它是一个大救星。LargeViz 是一个降维工具,不仅可以用于图形,还可以用于任意表格数据。它从命令行运行,工作速度快,消耗一点内存。
制图
Addresses that could be hacked in one week and their transactions
Intuitive and pretty looking GUI, but very limited
它是本次调查中唯一的付费工具。Graphistry 是一项服务,它获取你的数据,并在其端进行所有的计算。客户只看他浏览器中的漂亮图片。其他特性并不比 Gephi 好多少,除了 Graphistry 有合理的默认参数,良好的配色方案和略好的交互性。它只提供一种强制布局。它也有 80 万个节点或边的限制。
图形嵌入
对于疯狂的尺寸也有一种方法。从大约一百万个顶点开始,只看顶点密度是合理的,根本不画边和特定的顶点。仅仅是因为没有人能够在这样的地块上辨认出单个的物体。此外,大多数为图形可视化设计的算法在这样的规模下需要工作很多小时,甚至几天。如果我们稍微改变一下方法,这个问题就可以解决。有许多方法可以获得反映图顶点特征的固定大小的表示。在得到这样的表示之后,你唯一需要做的就是把维数减少到两个,以便得到一幅图像。
Node2Vec
Node2Vec + UMAP
这是 word2vec 对图形的改编。它使用图中的随机游走而不是单词序列。因此,该方法仅使用关于节点邻域的信息。在大多数情况下,这就足够了。
诗
VERSE + UMAP
通用图形表示的高级算法。我经历中最好的之一。
图形卷积
Graph Convolutions + Autoencoder. Bipartite graph.
有很多方法可以定义图上的卷积。但实际上,这是顶点的邻居对特征的简单“传播”。我们也可以把局部拓扑信息放在顶点特征中。
小奖励
我做了一个没有神经网络的简化图卷积的小教程。它位于[这里](https://github.com/iggisv9t/graph-stuff/blob/master/Universal Convolver Example.ipynb)。我还制作了一个[图形嵌入教程](https://github.com/iggisv9t/graph-stuff/blob/master/Graph Embeddings Tutorial.ipynb),在那里我展示了如何使用上面提到的一些工具。
链接
【arxiv.org/pdf/1902.07153.pdf】简化图卷积网络
T4
GraphVizgraphviz.org
Gephigephi.org
igraph.org
arxiv.org/abs/1602.00370
github.com/lferry007/LargeVis
www.graphistry.com
制图
node 2 vecsnap.stanford.edu/node2vec
github.com/xgfs/node2vec-c
第节
tsitsul.in/publications/verse
github.com/xgfs/verse
带简化图形卷积的笔记本示例
github . com/iggisv 9t/graph-stuff/blob/master/Universal % 20 convolver % 20 example . ipynb
图卷积关于图卷积网络的论文列表:github.com/thunlp/GNNPapers
TL;博士:
graphia[2020 年 6 月 5 日更新]
This is the neuron connections of the part of the fly brain from https://neuprint.janelia.org/
这篇文章发表于大约一年前。现在有了一个新的非常有前途的图形可视化工具,特别是大型图形: Graphia 。它正在积极开发中,而不是早已废弃的 Gephi,而且运行速度也快得多。因为 Gephi 集成了很多工具,你可以在这里阅读:https://graphia.app/userguide.html
缺点是可以原谅的:
- 目前,它只有一个力导向的布局和非常有限的方法来调整它。
- 渲染选项不适用于大型图形。至少选择关闭边缘显示或增加不透明度将是非常有用的。
- 目前 Graphia 相对来说还不成熟。例如,我必须用 Gephi 转换图形格式,以便放入 Grapia,它在表示为 CSV 的相同图形上崩溃。但是我相信这些小事情很快都会得到改善的。
优点不胜枚举。想象一下,Gephi 拥有所有这些分析工具,但在 C++上从头开始重写,速度更快,并且正在积极开发中。做个对比:Gephi 布局 173K 节点图需要几个小时,Graphia 只需要几分钟。
我相信这个评论很快就会过时,所以最好自己检查一下这个 app 的当前状态。
【2022 年 7 月更新】
不得不说这篇文章有些观点有点过时了:
- 格菲不再被遗弃了
- Graphia 看起来还很原始。它很快,但是可视化太混乱,而且不可能调整视图使其可用。
- 现在有几个很棒的在线工具
新工具
宇宙摄影仪
[## Cosmograph:大图的可视化分析
在您的笔记本电脑上处理由成千上万个节点和边组成的网络图。
cosmograph.app](https://cosmograph.app/)
在 webgl、开源核心和 sane 默认设置上使用强制布局的超快速工具。简单,漂亮,简约,但有许多有用的功能。可以处理成千上万的顶点和边。甚至比桌面工具还快。
Image from cosmograph’s site
视网膜
[## 视网膜
共享网络可视化的 web 应用程序
ouestware.gitlab.io](https://ouestware.gitlab.io/retina/beta/)
我能够使用视网膜约 10K 顶点,但这个工具的主要功能是出版。在网上的某个地方托管 gexf 或 graphml 文件(他们甚至提供指令)并获得可以共享的图形分析工具。许多最常见的场景不需要使用桌面工具,如节点搜索、节点邻居探索、按属性过滤等。
Graph hosted online loaded in Retina
例如,我在 Github 上找到了哈利·波特人物互动图,现在我可以分享可视化效果
应该只有一个!
Photo by George Hiles on Unsplash
如何在 Python 类中最有效地加载大型模型(和其他对象)
由于开源的机器学习框架,每个人都可以将强大(和大型)的模型集成到数据管道中。这样做的机会带来了大多数数据科学家没有能力应对的挑战。这篇博客文章解决了其中的一个问题:如何在不使计算系统过载的情况下,以集成最先进模型的方式构建代码?
这里有一个具体的例子。想象一下,你的工作是构建一个处理产品评论的 Python 管道。目标是检测那些试图降低你产品分数的虚假评论。您决定采用多步骤方法来实现这一点:
- 首先,你检查是否有条新评论可用。
- 第二,你检查他们的评级是否低到足以证明进一步调查的正当性。
- 第三,机器学习流水线通过计算嵌入并应用分类模型来检查通过两次检查的文本。
所有产品每天都运行这一流程。这是我们最初版本的ReviewClassifier
类:
从输出中可以看到,分类器的每个实例都重新加载了复杂的模型。我们假设每次加载一个模型大约需要一分钟。如果每天有 100 个产品有可疑评论,那就已经是 100 分钟的加载时间了!这是你的管道需要做的最重要的事情。
为了改进这一点——并节省 99%的加载时间——我们需要将加载从实例转移到类级别。这是我们的下一个版本:
这好得多,但我们可以进一步改进。目前,当您导入类时,分类器会立即加载模型:
from review_pipeline import ReviewClassifier
# Loaded: A Complicated Model
我们不想过早装货。也许我们根本不需要模型。它还会很快搞乱单元测试。
为了改变这一点,当我们计算嵌入时,我们检查模型是否在类级别上加载,如果没有,就这样做。这是我们的最终版本:
现在我们已经实现了我们的目标。模型在第一次需要时被加载,因此可供以后使用。
一旦你意识到这个模式,你会发现许多有用的应用。例如,有些情况下,带有后续本地过滤的单个数据库导出比重复的小查询更适合您的基础设施。对于大型预计算来说也是如此。
尽管这是一种巧妙的模式,但有些替代方案更适合某些用例。如果您应用上面的设计,类对象将保留在内存中,这会导致难以检测的问题。在这些情况下,最好创建一个本地副本(一次),并为每个新的类实例从文件系统重新加载对象。
如果这篇文章对你有所帮助,或者你想补充什么,请在评论或 Twitter 上告诉我。我也很乐意在 LinkedIn 上联系。感谢阅读!
pySpark 中使用隐式数据的大规模工作推荐引擎
为什么是隐式数据?因为我们作为懒惰的用户,几乎不会为我们在任何平台上做的任何事情提交评分(显性数据),无论是网飞、亚马逊、LinkedIn 等等。
我们所做的,只是看电影(隐含数据),查看产品或点击 LinkedIn 上的工作项目,然后继续前进。
在几乎每一个面向消费者的企业中提供相关的推荐,对于将潜在客户转化为客户是非常重要的。个性化是建立推荐引擎(RE)的关键,我们在网飞、亚马逊、LinkedIn 上看到它,它甚至存在于在线黑市。
这个项目的完整代码在我的 GitHub 档案。
Because you have not built a Recommendation Engine Bruh! 😄 [1]
激发我在 RE 上写这篇博客的是隐式数据的使用。我们已经看到了很多使用显式数据的 RE 案例研究,但是很少有使用隐式特征的例子。让我们先了解一下这两种数据的根本区别:
显式数据:用户明确给出的偏好,它可以是评级、喜欢或不喜欢方面的任何分数。
隐式数据:用户隐式给出的偏好,这些偏好不太明显,如查看、点击、在购物车中添加商品等。
所以,使用隐式数据,你实际上不知道,如果客户点击了一个项目,他们是否真的喜欢它?
让我们解决构建 RE 时处理隐式数据的问题。
我们将本博客主要分为三个部分:
- 构建 Rec 引擎的协同过滤算法
- 了解协同过滤如何处理隐式数据
- 让我们编码:使用 pySpark (MLlib)练习上面两个
1。协同过滤(CF)
如果你已经理解了协同过滤的概念,你可以跳过这一节。
CF 背后的基本思想非常简单。假设你有一个用户“X ”,你想推荐工作给“X ”, CF 将帮助你找到一组用户“N ”,他们的喜好和厌恶与用户“X”相似。一旦计算出这组 N 个用户,我们就可以向用户 x 推荐这组 N 喜欢的作业。
Source: [2]
现在,问题是 CF 如何帮助你找到一组与 X 相似的用户。主要有两种方法来找到“N”个相似用户的组:
- 基于记忆的方法:使用余弦相似性的概念并找到 k 个最近的邻居来计算未被用户评级的项目的评级(假设用户‘X’)
- 基于模型的方法:使用矩阵分解(SVD)、聚类或深度学习模型(受限波尔兹曼机器)的概念来预测用户评级。
在本帖中,我们将更多地讨论 CF 最常用的方法:
假设你有这种由不同用户给出的电影评级矩阵。在现实世界的例子中,这个矩阵非常稀疏。
Original user-movies(items) ratings matrix [4]
矩阵分解(MF):
Source: [3]
上图中解释的 MF 背后的直觉是使用用户-电影(项目)矩阵的降维,该矩阵由具有 k 个潜在因子(嵌入)的两个小矩阵近似,这两个小矩阵是用户嵌入矩阵和电影嵌入矩阵。
奇异值分解(SVD)就是这样一种降维技术,它在内部执行矩阵分解。
Factorized matrix [4]
现在,一旦生成了用户和电影嵌入矩阵,任何用户(假设为“X”)的用户嵌入向量(任何单行)就与电影嵌入向量相乘,以获得预测的评级值。
评级模型预测(黄色单元格中的 3.25)= 2 个绿色向量(嵌入向量)的点积+ 0.14(电影偏差)+ 0.87(用户偏差)[4]
我们可以对所有用户-电影组合执行此操作,以获得评级的预测值。我们将使用实际评级和相应的预测评级来计算 RMSE 损失。
注:在计算 RMSE 时,我们不会考虑实际收视率缺失的预测收视率。
最后,我们稍后将在 pySpark 中实现的最后一件事是交替最小二乘法,它使用梯度下降优化来计算用户和项目嵌入矩阵。
可选:为了了解更多关于 CF 算法的内容,你可以在 Coursera 上观看吴恩达的这个视频:链接(基于模型的方法),另一个视频解释了斯坦福大学数据挖掘课上的基于记忆的方法:链接。对于 excel 中的动手练习:链接和不同类型的 CF: 链接
2.隐式数据协同过滤
以上是一些大剂量的算法,但当数据是等级形式(显式)时,理解 CF 是非常必要的。一旦您理解了 CF 的基本原理,就很容易用隐式数据功能来调整 CF。我们开始吧:
本节中使用的大部分方法都来自本研究论文: 链接
隐式反馈的数值描述了行动的频率,例如,你点击数据科学职位的次数,你看网飞电视连续剧的时间,你听一首歌的次数等。我们利用用户给出的这些隐含数字来获取用户偏好或不偏好的置信度。用户‘u’对项目‘I’的偏好( pui )由以下等式捕获:
其中’*瑞’*是该项目的记录值(例如,你听一首歌的次数)。因此,如果记录的值大于 0,则首选项为 1,如果它等于 0,则首选项为 0。
现在,假设你只听了一首歌一次,这并不意味着你喜欢它,它可能在你的 YouTube 上处于自动播放模式。同样,如果记录值为零,并不意味着你不喜欢这首歌,这可能意味着你从来不知道这首歌的存在,或者你还没有发现它。因此,为了捕捉这种偏好关系,我们需要明确信心的概念:
总的来说,随着“ rui ”的增长,我们有更强的迹象表明用户确实喜欢这个项目。【Cui】,衡量我们对观察*g【pui】的信心。*我们可以注意到,即使对于“rui”为 0 的用户项目对(表示对该项目没有偏好),我们也有相关的最小置信度 1。并且“pui”等于 1 的置信度随着积极偏好证据的增加而增加。
增加速率由常量调谐参数α控制。
偏好被假设为内积:pui =(转置)U. X
现在,我们将计算两个矩阵:用户嵌入矩阵(U’)和项目嵌入矩阵(X’),就像我们在如上所述的协同过滤技术中所做的那样,与我们在显式数据的情况下所做的相比,只有两个区别:
- 我们需要考虑不同的置信水平
- 优化应考虑所有可能的用户-项目对,而不仅仅是那些与观察数据相对应的用户-项目对
嵌入/因子通过最小化以下成本函数来计算:
[5]
这可以通过使用 ALS 优化过程来近似我们的偏好矩阵并基于偏好向用户提供推荐来解决。
3。PySpark 代码构建大规模作业 Rec 引擎
最后,是时候把我们到目前为止学到的关于协同过滤或推荐引擎的知识进行编码了。
让我们编造一些数据。
job posts clicks by different users (job_clicks.csv)
jobs category like IT, Finance, HR etc (jobs.csv)
因此,第一步是将上面显示的数据加载到 rdd 中并处理它。接下来,为了建模的目的,我们需要将它分成训练、验证和测试集。
Data load and splitting
将数据分成三组后,使用训练和验证组来训练模型并调整超参数(或使用交叉值)。
[7]
观察上面代码中用于交替最小二乘法(ALS.trainImplicit function)调整的 4 个超参数:
- 秩:表示嵌入矩阵的宽度/列
- iters(迭代):表示我们在 ALS 过程中振荡多少次来生成嵌入矩阵
- alpha:与置信度等式中的记录规模(用户执行任何动作:观看电影的次数)相关
- reguls (lambda):是防止过度拟合的正则化参数
最后,您可以使用最佳超参数集来训练模型,并使用它来预测用户偏好的推荐或置信度,以显示前 N 个推荐。
下面是加载和处理数据、建立模型以及为所有用户预测推荐的代码。
要获得本文中使用的数据集的完整项目演示,请查看 GitHub 链接。
下一步可能是将该模型放入云中,并根据您的需求实时显示建议。此外,还有其他一些很酷的库,如用于构建 Rec 引擎的“implicit ”,但其基本概念与我们在前两节中讨论的相同。
此外,请分享您的宝贵意见或反馈,让它变得更好,更具可扩展性。我有另一个关于使用 Docker 容器构建和部署模型的博客,所以如果你喜欢缩放你的模型,请查看一下。
参考文献
【2】https://www.youtube.com/watch?v=h9gpufJFF-0&t = 23s
[3]https://www . EDX . org/course/big-data-analysis-Apache-spark-UC-berkeleyx-cs110 x
【4】https://towards data science . com/collaborative-filtering-and-embedding-part-1-63 b 00 b 9739 ce
[6]https://databricks . com/session/building-a-implicit-recommendation-engine-with-spark
基于线性回归和深度学习的 Lasso 正则化
对套索惩罚的影响及其对线性回归的影响的数学分析,包括对深度学习的可能扩展
介绍
曲线拟合-欠拟合和过拟合
正如我在上一篇文章中所讨论的,当问题不适当时,就会出现“曲线拟合”的问题。不足通常不是一个大问题,因为我们可以通过获取/设计新特性来扩展特性集。然而,过度拟合并不容易处理。
回归中的最佳子集选择
考虑一个有 p 个预测变量的线性回归。假设整个数据集用于训练。众所周知,训练集 R 不会随着特征的增加而减少。因此,R 不是一个很好的拟合优度的度量。调整后的-R,马洛的 Cₚ,AIC,BIC 等。是用来衡量拟合优度的。然而,在添加/移除预测变量时,不存在关于这些测量值的变化的先验知识。因此,可能需要所有 2ᵖ-1 独特模型来判断为结果变量建模所需的特征的“最佳子集”。然而,这在计算上非常昂贵。这就需要一种适当的方法来减少变量,而不需要建立指数级的大量模型。套索惩罚有助于部分实现这一目标。
制定
线性回归和正规方程
Regression equation
Linear regression estimated on sample
OLS solution — same as MLE under certain conditions
Normal equation
我们观察到,如果协方差矩阵是不可逆的,则 OLS 解不存在(可能不是唯一的)。
套索公式
Regression equation
Lasso solution estimated on sample
Lasso solution
对于这种最小化,不存在解析解。梯度下降也不能保证收敛于这个损失函数,即使它是凸的。需要另一个公式来计算解决这个问题。
解决办法
正交协方差的软阈值处理
Equations copied from my personal notes
Assumption to simplify the analysis
Separating out the dimensions
Soft thresholding
可以在每个维度上单独执行软阈值处理。这种更新将收敛到最佳β,因为它们是独立的。这种想法类似于轮廓似然 —关键参数的估计是通过描绘出(固定)噪声参数并最大化似然(假设为凸的)来完成的,然后通过将关键参数固定在其计算出的最佳值来估计噪声参数:这在参数独立时有效。
这种一次更新一个参数的方法称为坐标下降法。
坐标下降:一般情况
对于没有正交设计的一般情况,坐标下降可总结如下:
- 从猜测套索解开始,设置收敛参数ϵ
- 迭代 I,从 1 到 max_iter:
- —从 1 到 p 迭代 j:
- — —通过设置βⱼ = 0 来计算残差
- — —回归第 j 个预测因子上的残差,得到第 j 个β的 OLS 解
- — —对 OLS 解应用软阈值,获得第 j 个β的套索解
- — —检查收敛:β < ϵ?
- Return final β. Did β converge in max_iter iterations?
Coordinate descent is guaranteed to converge in one iteration for orthogonal design. It is not guaranteed to converge in 1 iteration if the design matrix is not orthogonal, but it will converge in finite number of iterations.
Geometric interpretation
Dual form of optimization
Lasso loss
Dual form of optimization
Contour plot for lasso. Image credits: https://stats.stackexchange.com/questions/30456/geometric-interpretation-of-penalized-linear-regression
The blue squares correspond to |β|₁ ≤ s for different s, where |β|₁ = constant along a square. Increasing λ decreases the size of the square. The red ellipses correspond to different distinct values of (y-xβ)₂² where (y-xβ)₂² = constant along an ellipse. For a fixed λ the value of s is fixed: this corresponds to one of the blue squares.
The minimum value of (y-xβ)₂² in unconstrained case occurs at the center of the ellipse. However, under the constrained case of |β|₁ ≤ s the solution will be displaced towards the origin.
The unique lasso solution is located at the point where these two ‘curves’ touch. Since the curve |β|₁ ≤ s is non-differentiable at few points the lasso solution for few βᵢs can be zero. On increasing λ (decreasing s) these βᵢs remain 0; other βᵢs tend to 0. This causes sparsity in the coefficients of lasso.
Extension to deep learning
Deep learning networks inevitably have fully-connected layers. These layers perform linear transformation on the input and apply an activation on the transformed variables. When the transformed outputs are small in magnitude (typically less than 1) the non-linearity can be ignored. With lasso penalty on the weights the estimation can be viewed in the same way as a linear regression with lasso penalty. The geometric interpretation suggests that for λ > λ₁中更新的 L1 范数(最小λ,其中只有一个β估计为 0)我们将至少有一个权重= 0。这造成了权重的稀疏性。这一论点也适用于具有较大转换输入值的非线性情况。
结论
套索惩罚通过将一些系数驱动到 0 来创建系数的稀疏性。这适用于线性回归和深度神经网络中的全连接层。因此,对于合适的λ值,lasso 惩罚可以降低深度学习模型的复杂性。然而,它不是所有问题的解决方案。
如果基础模型是线性的(Y = Xβ + ϵ),非零λ会导致套索解(E(βˡᵃˢˢᵒ)中的偏差≠ β,但估计量的方差低于最大似然法),因此,即使对于简单的情况,它也不能同时实现估计和选择的一致性。尽管有这个缺点,但它是对有限样本过度拟合的一个好的解决方案,特别是在具有大量参数的深度神经网络中,这些参数往往会过度拟合。
潜在狄利克雷分配
潜在狄利克雷分配 (LDA)是由零件组成的复合物集合的“生成概率模型”。就主题建模而言,组合是文档,部分是单词和/或短语(n 元语法)。但是你可以将 LDA 应用于 DNA 和核苷酸,比萨饼和配料,分子和原子,雇员和技能,或者键盘和面包屑。
潜在狄利克雷分配(LDA)是一种自动发现这些文档包含的主题的技术。
假设你有下面这组句子:
根据上面的句子,LDA 可能会将红色单词归类到主题 F 下,我们可以将其标记为“食物”。类似地,蓝色单词可能被归类到一个单独的主题 P 下,我们可以将其标记为“宠物”。LDA 将每个主题定义为一个单词包,你必须按照你认为合适的方式给主题贴上标签。
LDA 在单词级别定义主题有两个好处:
1)我们可以通过字数来推断每个句子的内容传播:
第一句 : 100%话题 F
第二句 : 100%话题 P
第三句 : 33%话题 P 和 67%话题 F
2)我们可以推导出每个单词在给定主题中所占的比例。例如,主题 F 可能包含以下比例的单词:40%吃,40%鱼,20%蔬菜,…
LDA 分三步实现上述结果。
为了说明这些步骤,假设您现在正在文档中发现主题,而不是句子。假设您有两个包含以下单词的文档:
第一步
**你告诉算法你认为有多少个题目。**您可以使用可靠的估计(例如之前分析的结果),也可以简单地试错。在尝试不同的估计时,你可以选择一个产生你想要的可解释性水平的话题,或者一个产生最高统计确定性(即对数可能性)的话题。在上面的例子中,主题的数量可以通过目测文档来推断。
步骤 2
算法会将每个单词分配给一个临时主题。主题分配是临时的,因为它们将在步骤 3 中更新。临时主题以半随机的方式(确切地说,根据狄利克雷分布)被分配给每个单词。这也意味着,如果一个词出现两次,每个词可能被分配到不同的主题。注意,在分析实际文档时,功能词(例如“the”、“and”、“my”)被移除,并且不被分配给任何主题。
步骤 3(迭代)
该算法将检查并更新主题分配,遍历每个文档中的每个单词。对于每个单词,其主题分配基于两个标准进行更新:
- 这个词在各种话题中有多普遍?
- 文档中的主题有多普遍?
为了理解这两个标准是如何工作的,假设我们现在正在检查文档 Y 中单词“fish”的主题分配:
- 这个词在各种话题中有多普遍?由于两个文档中的“鱼”字包括几乎一半的剩余主题 F 字,但是 0%的剩余主题 P 字,所以随机挑选的“鱼”字更可能是关于主题 F 的
- 文档中的主题有多普遍?因为文档 Y 中的单词以 50:50 的比例分配给主题 F 和主题 P,所以剩余的“鱼”单词似乎同样可能与任一主题有关。
权衡两个标准得出的结论,我们将把 Doc Y 的“鱼”字分配给 Topic f。Doc Y 可能是一个关于喂小猫什么的文档。
对每个文档中的每个单词重复检查主题分配的过程,在整个文档集合中循环多次。这种迭代更新是 LDA 的关键特征,它生成具有连贯主题的最终解决方案。
潜在狄利克雷分配(LDA)初学者指南
发现抽象话题又名 话题建模 的统计模型。
Photo by Giulia Bertelli on Unsplash
什么是主题建模?
主题建模是一种对文档进行无监督 分类的方法,类似于对数字数据进行聚类,即使我们不确定我们在寻找什么,它也会找到一些自然的项目(主题)组。
一个文档可以是多个主题的一部分,有点像模糊聚类(软聚类)中每个数据点属于多个聚类。
为什么要主题建模?
主题建模提供了自动组织、理解、搜索和总结大型电子档案的方法。
它可以在以下方面提供帮助:
- 发现收藏中隐藏的主题。
- 将文档分类到发现的主题中。
- 使用分类来组织/总结/搜索文档。
例如,假设一个文档属于主题食品、狗和健康。因此,如果用户查询“狗粮”,他们可能会发现上述文档相关,因为它涵盖了这些主题(以及其他主题)。我们能够计算出它与查询的相关性,甚至不需要浏览整个文档。
因此,通过注释文档,基于建模方法预测的主题,我们能够优化我们的搜索过程。
皱胃向左移
它是最流行的主题建模方法之一。每个文档由各种单词组成,每个主题也有属于它的各种单词。LDA 的目的是根据文档中的单词找到文档所属的主题。很困惑吗?这里有一个例子来引导你。
模型定义
Each document is a collection of words.
我们有 5 个文档,每个文档都包含前面列出的单词(按出现频率排序)。
我们要搞清楚的是不同题目中的单词,如下表所示。表格中的每一行代表一个不同的主题,每一列代表语料库中的一个不同的单词。每个单元格包含单词(列)属于主题(行)的概率。
Each topic contains a score for all the words in the corpus.
寻找主题的代表词
- 我们可以根据单词的概率得分对单词进行排序。
从每一个题目中选出最上面的 x 个单词来代表题目。如果 x = 10,我们将根据得分对 topic1 中的所有单词进行排序,并取前 10 个单词来代表该主题。这一步可能并不总是必要的,因为如果语料库很小,我们可以按照分数来存储所有的单词。 - 或者,我们可以在分数上设置一个阈值。主题中分数高于阈值的所有单词可以按照它们的分数顺序存储为其代表。
Photo by Anusha Barwa on Unsplash
假设我们有两个主题,可以分类为与猫相关的和与狗相关的。一个话题对每个单词都有概率,所以像牛奶、喵和小猫这样的单词,在猫 _ 相关话题中的概率会比在狗 _ 相关话题中的概率高。同样地,与狗相关的话题中出现小狗、吠叫和骨头等词语的概率也很高。
如果我们有一个包含以下句子的文档:
狗喜欢啃骨头上的并捡棍子。
“小狗喝奶”
“都喜欢对吠叫。”
我们可以很容易地说它属于话题狗 _ 相关,因为它包含了诸如狗、骨头、小狗和吠叫等词语*。尽管它包含属于主题 CAT_related 的单词 milk ,但该文档属于 DOG_related ,因为更多的单词与之匹配。*
假设:
- 每个文档只是一个单词的集合或一个“单词包”。因此,单词的顺序和单词(主语、宾语、动词……)的语法角色在模型中不被视为。
- 像 am/is/are/of/a/the/but/…这样的词不携带任何关于“主题”的信息,因此可以作为预处理步骤从文档中删除。事实上,我们可以 **消除至少在文档的%80 ~ %90 中出现的单词,**而不会丢失任何信息。例如,如果我们的语料库只包含医学文档,则像人类、身体、健康等词可能出现在大多数文档中,因此可以被移除,因为它们没有添加任何使文档突出的特定信息。
- 我们预先知道我们想要多少主题。k‘是预先决定的。
- 除了正在讨论的当前单词之外的所有主题分配都是正确的,然后使用我们的文档生成模型更新当前单词的分配
LDA 是如何工作的?
LDA 有两个部分:
- 这个字,属于一个文档 ,这个我们已经知道了。
- 属于主题 的 个单词或者单词属于一个主题的概率,我们需要计算。
找到后者的算法
- 浏览每个文档,并随机将文档中的每个单词分配到 k 主题中的一个(事先选择了 k )。
- 对于每个文档 d ,遍历每个单词 w 并计算:
- p(主题 t |文档 d ) :文档 d 中分配给主题 t 的文字比例*。*试图捕捉给定文档 d 中有多少单词属于主题 t 。排除当前单词。
如果来自 d 的很多字属于 t 的话,字 w 属于 t 的可能性更大。
(中的#字数 d 带t+alpha/中的#字数 d 带任意话题+ k * alpha ) - p(wordw| topict):分配给 topic t 的任务占所有来自 word w 的文档的比例。试图捕获多少文档在主题 t 中,因为单词 w 。LDA 将文档表示为主题的混合物。同样,一个题目也是单词的混合体。如果一个单词出现在主题中的概率很高,那么所有带有 w 的文档也将与 t 有更强的关联。类似地,如果 w 不太可能出现在 t 中,则包含 w 的文档出现在 *t、*中的概率很低,因为 d 中的其余单词将属于其他主题,因此 d 出现在这些主题中的概率更高。所以即使 w 被添加到 t 中,也不会给 t 带来很多这样的文档。
- 更新单词 w 属于主题 t 的概率,如下所示
p(word w with topic t) = p(topic t | document d) * p(word w | topic t)
外行的例子
假设你有各种各样的照片(文档)和标题(文字)。您希望在画廊中展示这些照片,因此您决定根据不同的主题(主题)对照片进行分类,并根据这些主题在画廊中创建不同的部分。
Photo by Soragrit Wongsa on Unsplash
你决定在你的相册中创建 k=2 个部分——自然与城市。自然,分类不是很清楚,因为一些城市的照片有树和花,而自然的照片可能有一些建筑。首先,你决定将只有自然或城市元素的照片归入各自的类别,而你随机分配其余的。
你会注意到《自然》杂志上的许多照片标题中都有“T2 树”这个词。所以你断定树这个词和 topi c 自然一定是密切相关的。
接下来,你选择单词 building 并检查有多少张照片出现在 nature 中,因为它们的标题中有单词 building 。你不会发现很多人现在不太确定建筑属于主题自然并更强烈地将其与主题城市联系起来。
然后你选择一张标题为**“树在建筑物前,车后”**的照片,你会发现它现在属于自然类别。
然后你选择文字 树 ,并计算第一概率 p(题目 t |文件 d ): 标题中的其他文字是楼和车,大多数带有标题的照片都是在市的楼或车
现在第二个概率 p(单词 w |题目 t ) :我们知道自然界很多照片里面都有树木这个单词。所以你在这里得到高分。
你通过将两者相乘来更新树属于自然的概率。你在主题自然中得到的树的值比之前低,因为现在你已经看到在同一个标题中树和建筑 / 汽车等词,暗示着城市中也可以找到树。
出于同样的原因,当你更新主题城市中树归属的概率时,你会注意到它会比以前大。
在对所有照片和每个主题进行多次迭代后,你将获得每个主题的每个单词的准确分数。你的猜测会越来越好,因为你会从上下文中得出结论,建筑物、人行道、地铁等词一起出现,因此肯定属于同一个主题,我们可以很容易地猜到是城市。
像山、田野、海滩这样的词可能不会在很多标题中同时出现,但它们确实经常在没有城市词的情况下出现,因此自然的得分较高。
而像树、花、狗、天空这样的词在两个主题中出现的概率几乎相同。
至于照片,你看到它有 1 个词(平均概率)来自自然类别,2 个词(高概率)来自城市,你得出结论,它属于城市比属于自然更强烈,因此你决定将它添加到城市。
边注
LDA 的应用不需要局限于自然语言处理。我最近完成了一篇论文,其中我们使用 LDA(以及神经网络)来提取图像的特定场景上下文。如果你有兴趣了解更多,请留下评论或留言。
参考
- 如果你正在寻找 LDA 的实现,这里有一篇关于数据科学的惊人的文章,它做得很好!
- 参见 Edwin Chen 博客中的“一个外行的例子”以获得更多关于 LDA 的直觉。
我认为你会喜欢的其他文章😄
- NLP 模型评估—最新基准
- 理解深度学习中的注意力
- 变形金刚——谷歌的 BERT 和 OpenAI 的 GPT 等模型的基本模块。
我很高兴你坚持到了这篇文章的结尾。🎉我希望你的阅读体验和我写这篇文章时一样丰富。💖
请点击这里查看我的其他文章。
如果你想联系我,我的选择是推特。
2019 年 CVPR 最新计算机视觉趋势
用数据做酷事!
2019 年 IEEE 计算机视觉和模式识别大会(CVPR)于今年 6 月 16 日至 6 月 20 日举行。 CVPR 是计算机视觉领域全球三大学术会议之一(与 ICCV 和 ECCV 并列)。今年共有 1300 篇论文从创纪录的 5165 篇提交中被接受(25.2%的接受率)。
CVPR 带来了计算机视觉领域的顶尖人才,每年都有许多令人印象深刻的论文。
我从 CVPR 拿了被接受的论文,并对它们做了分析,以了解论文标题中的主要研究领域和常见关键词。这可以显示出研究的进展方向。
底层数据和代码可以在我的 Github 上找到。随意拉这个,加入你自己的旋转。
CVPR 给每篇论文指定一个主要的主题领域。被接受的论文按学科领域分列如下:
不奇怪,大部分研究都集中在深度学习上(现在不都是深度学习吗!),检测和分类以及人脸/手势/姿势。这种分类非常笼统,并没有给出很好的见解。所以接下来我从接受的论文中提取了所有的单词,并用一个计数器来计算它们的频率。最常见的 25 个关键词如下:
现在这个更有趣了。最受欢迎的研究领域是检测、分割、3D 和对抗训练。它也显示了无监督学习方法的研究日益增长。
最后我还画了云这个词。
你可以使用我的 Github 按主题提取热门论文,如下所示
Papers with research on “face”
我经营一家机器学习咨询公司。点击查看我们的网站。我喜欢从事计算机视觉项目。如果你有我们可以合作的想法,请随时通过网站或电子邮件联系 info@deeplearninganalytics.org。
接下来,我在博客中选择了 5 篇来自关键研究领域的有趣论文。请注意,我挑选了最吸引我的论文。
人类视觉系统有一种非凡的能力,可以从 2D 投影中理解我们的 3D 世界。即使在具有多个移动对象的复杂环境中,人们也能够保持对对象的几何形状和深度排序的可行解释。在过去的几年中,已经使用相机图像在深度估计方面做了大量的工作,但是在许多情况下,鲁棒的重建仍然是困难的。当相机和场景中的对象都自由移动时,会出现一个特别具有挑战性的情况。这混淆了基于三角测量的传统 3D 重建算法。
要了解更多关于深度图像和估计场景深度的信息,请查看这个博客。
本文通过在相机和主体都自由移动的场景上建立深度学习模型来解决这一问题。见下图 gif:
Depth estimation on moving people
为了创建这样一个模型,我们需要移动摄像机捕捉的自然场景的视频序列,以及每幅图像的精确深度图。创建这样一个数据集将是一个挑战。为了克服这一点,该论文非常创新地使用了现有的数据集——YouTube 视频,其中人们模仿人体模特摆出各种各样的自然姿势,同时手持摄像机巡视现场。因为场景是静止的,只有相机在移动,所以可以使用三角测量技术来构建精确的深度图。这篇论文非常有趣。它解决了一个复杂的问题,并在为其创建数据集方面极具创造性。
经过训练的模型在移动摄像机和人的互联网视频剪辑上的性能比以前的任何研究都好得多。见下文:
Model comparison through the paper
你可以在这里阅读全文。
2。BubbleNets:通过深度排序帧学习选择视频对象分割中的引导帧
我看过几篇关于视频对象分割的论文(VOS)。这是在第一帧提供单个注释的情况下分割视频中的对象的任务。这在视频理解中有应用,并且在过去的一年中有很多研究。
视频中对象的位置和外观可能会逐帧发生显著变化,并且该论文发现,使用不同的帧进行注释会显著改变性能,如下所示。
Bubblenets video demo
BubbleNets 迭代地比较和交换相邻的视频帧,直到具有最大预测性能的帧排名最高,此时,选择该帧供用户注释和用于视频对象分割。
BubbleNet first frame selection
该模型的视频描述在 youtube 上分享,源代码在 Github 上开源。
BubbleNets 模型用于预测两个帧之间的相对性能差异。相对性能通过区域相似性和轮廓准确度的组合来测量。
它将 2 个要比较的帧和 3 个参考帧作为输入。然后,它通过 ResNet50 和完全连接的层来输出表示 2 帧比较的单个数字 f。为了执行冒泡排序,我们从前 2 帧开始,并对它们进行比较。如果 BubbleNet 预测帧 1 比帧 2 具有更好的性能,则交换帧的顺序,并将下一帧与迄今为止最好的帧进行比较。在整个视频序列的处理结束时,最好的帧保留下来。下图显示了 BubbleNets 架构和冒泡排序过程。
总体而言,作者表明,在不改变底层分割算法的情况下,改变标注帧的选择方式,可以使 DAVIS 基准数据集的性能提高 11%。
Bubblenets architecture
三维手形和姿态估计是最近非常活跃的研究领域。这在虚拟现实和机器人技术中有应用。本文使用单目 RGB 图像来创建一个 3D 手姿态和手周围的 3D 网格,如下所示。
3D hand mesh from single image
本文使用图形细胞神经网络重建手的全三维网格。这里很好的介绍了图形 CNN 这个话题。为了训练网络,作者创建了一个包含地面真实 3D 网格和 3D 姿态的大规模合成数据集。在真实世界的 RGB 图像上手动注释地面真实 3D 手网格是极其费力和耗时的。然而,在合成数据集上训练的模型通常在真实数据集上产生不令人满意的估计结果,因为它们之间存在领域差距。为了解决这个问题,作者提出了一种新的弱监督方法,通过利用深度图作为 3D 网格生成的弱监督,因为在收集真实世界训练数据时,深度图可以很容易地被 RGB-D 相机捕获。本文在数据集、训练过程等方面有丰富的细节。如果这是你感兴趣的领域,请通读。
对我来说,一个有趣的学习是 CNN 用于网格生成的图形架构。这个网络的输入是来自 RGB 图像的潜在向量。它经过 2 个完全连接的图层,在粗略的图形中输出 80x64 的要素。然后,它通过层层上采样和图形 CNN 来输出更丰富的细节,最终输出 1280 个顶点。
3D hand mesh model architecture
Reasoning RCNN output
随着许多常见的计算机视觉应用,对象检测已经获得了很大的普及。快速 RCNN 是一种常用的目标检测模型。要了解更多关于物体检测和更快的 RCNN 检查这个博客。然而,当检测类别的数量很少时(少于 100),对象检测是最成功的。本文研究了具有数千个类别的大规模目标检测问题,该问题由于长尾数据分布、严重遮挡和类别歧义性而面临严峻挑战。
推理-RCNN 通过构建一个知识图来编码人类常识知识来实现这一点。什么是知识图?知识图对对象之间的信息进行编码,如空间关系(上,近),主语-动词-宾语(例如。驾驶、跑步)关系以及属性相似性,如颜色、尺寸、材料。如下所示,彼此具有视觉关系的类别彼此更接近。
Knowledge Graph
就架构而言,它在标准对象检测器(如更快的 RCNN)之上堆叠了一个推理框架。收集先前分类器的权重以生成所有类别的全局语义池,该语义池被馈送到自适应全局推理模块。增强的类别上下文(即推理模块的输出)通过软映射机制被映射回区域提议。最后,每个区域的增强特征用于以端到端的方式提高分类和定位的性能。下图显示了模型架构。请参考论文更详细的了解他们的架构。
该模型在 3 个主要数据集上进行训练和评估——Visual Gnome(3000 个类别)、ADE (445 个类别)和 COCO (80 个类别)。该模型能够在地图得分上在视觉侏儒上获得 16%的提升,在阿德上获得 37%的提升,在可可上获得 15%的提升。
培训代码将在此链接处开源。尚不可用。
在过去的几年中,面部检测已经取得了很大的进步,现在面部检测和识别系统在许多应用中普遍使用。事实上,用 8 行代码就能建立一个检测人脸、识别人脸并理解其情绪的系统是可能的。见博客这里。
然而,也存在人脸检测被欺骗以获得非法访问的持续风险。人脸反欺骗旨在防止人脸识别系统将伪造的人脸识别为真正的用户。虽然开发了先进的人脸反欺骗方法,但是新类型的欺骗攻击也正在被创建,并成为对所有现有系统的威胁。介绍了检测未知欺骗攻击的概念,即零枪击人脸反欺骗(ZSFA)。之前的 ZSFA 著作只研究了 1- 2 种类型的欺骗攻击,比如 print/replay,限制了对这个问题的洞察。这项工作调查了 ZSFA 问题的范围广泛的 13 种类型的欺骗攻击,包括打印,重放,三维面具,等等。下图显示了不同类型的欺骗攻击。
面部欺骗可以包括各种形式,如打印(打印面部照片)、重放视频、3D 面具、带有眼睛剪切的面部照片、化妆、透明面具等。该论文提出使用深度树网络以无监督的方式从欺骗图片中学习语义嵌入。这里的嵌入可以模拟像人类凝视这样的事情。它创建了一个欺骗图像的数据集来学习这些嵌入。在测试过程中,未知攻击被投射到嵌入中,以找到最接近欺骗检测的属性。
阅读论文以获得关于深度树网络的模型架构和训练它的过程的更多细节。该论文能够创建嵌入,将具有各种类型的欺骗的真实面部(真实面部)分离出来。见下面的 t-SNE 图
这篇论文太棒了。解决实际问题的有希望的研究。
结论
看到计算机视觉的所有最新研究令人着迷。这里分享的 5 篇论文只是冰山一角。我希望你会用我的 Github 来整理文件,选出你感兴趣的。
我对计算机视觉和深度学习充满热情。我有自己的深度学习咨询公司,喜欢研究有趣的问题。我已经帮助许多初创公司部署了基于人工智能的创新解决方案。请到 http://deeplearninganalytics.org/.来看看我们吧
你也可以在https://medium.com/@priya.dwivedi看到我的其他作品
如果你有一个我们可以合作的项目,请通过我的网站或 info@deeplearninganalytics.org 联系我
参考文献:
- CVPR
- 博客中使用的图片是从报纸上借来的