如何用 python 轻松创建自己的问答系统
如何使用 cdQA-suite 在您自己的(私人)数据上创建 QA 系统
机器理解的历史起源于人工智能中第一个概念的诞生。聪明的艾伦·图灵在他的著名文章《T2》中提出了计算机器和智能“现在被称为图灵测试作为智能的标准。近 70 年后,问答(QA)仍然是人工智能中最困难的任务之一,它是 MC 的一个分支。
然而,自去年以来,由于深度学习研究的发展和迁移学习技术的出现,自然语言处理领域经历了快速的发展。强大的预先训练的 NLP 模型,如 OpenAI-GPT 、 ELMo 、 BERT 和 XLNet 等,均由该领域的顶尖研究人员提供。
随着这些进步,一些改进的系统和应用程序将会出现。其中一个系统是 cdQA-suite ,这是我和一些同事在法国工程学院巴黎电信和欧洲个人理财领导者法国巴黎银行的合作下开发的一个软件包。
开放域质量保证与封闭域质量保证
当我们考虑 QA 系统时,我们应该知道两种不同的系统:开放域 QA (ODQA)系统和封闭域 QA (CDQA)系统。
开放域系统几乎可以处理任何问题,并且只能依赖于一般的本体和世界知识。这样一个系统的一个例子是 DrQA ,一个由脸书研究公司开发的 ODQA,它使用维基百科的大量文章作为它的知识来源。由于这些文件涉及几个不同的主题,我们可以理解为什么这个系统被认为是一个 ODQA。
另一方面,封闭领域系统处理特定领域下的问题(例如,医学或汽车维修),并且可以通过使用适合唯一领域数据库的模型来利用特定领域的知识。cdQA 套件的构建是为了让任何想要构建封闭领域 QA 系统的人都能轻松完成。
cdQA 套件
[## cdQA
一个端到端的封闭领域问答系统。- cdQA
github.com](https://github.com/cdqa-suite)
cdQA 套件由三部分组成:
- cdQA :一个易于使用的 python 包,用于实现 QA 管道
- cdQA-annotator :一个为模型评估和微调方便问答数据集注释的工具
- cdQA-ui :一个可以耦合到任何网站并可以连接到后端系统的用户界面。
我将解释每个模块是如何工作的,以及你如何使用它在你自己的数据上建立你的 QA 系统。
cdQA
cdQA 架构基于两个主要组件:检索器和阅读器。你可以在下面看到系统机制的示意图。
Mechanism of cdQA pipeline
当一个问题被发送到系统时,检索器在数据库中选择最有可能包含答案的文档列表。它基于与 DrQA 相同的检索器,该检索器基于一元语法和二元语法创建 TF-IDF 特征,并计算问句与数据库中每个文档之间的余弦相似度。
在选择了最有可能的文档后,系统将每个文档分成段落,和问题一起发送给读者,这基本上是一个预先训练好的深度学习模型。使用的模型是著名的 NLP 模型 BERT 的 Pytorch 版本,由 HuggingFace 提供。然后,阅读器在每段中输出它能找到的最可能的答案。在阅读器之后,系统中还有最后一层,它通过使用内部得分函数来比较答案,并根据得分输出最可能的答案。
使用 cdQA python 包
在开始使用这个包之前,让我们安装它。您可以使用pip
来安装它,或者从源代码中克隆存储库。对于本教程,我还将下载法国巴黎银行的数据集(一个从他们的公共新闻网页上摘录文章的数据集)。
# Installing cdQA package with pip
pip install cdqa# From source
git clone [https://github.com/cdqa-suite/cdQA.git](https://github.com/cdqa-suite/cdQA.git) &&
cd cdQA &&
pip install .
现在,您可以打开 jupyter 笔记本,按照下面的步骤来查看 cdQA 是如何工作的:
您应该有如下输出:
The output of a QAPipeline prediction
您可以注意到,系统不仅输出一个答案,还输出找到答案的段落以及文档/文章的标题。
在上面的代码片段中,需要预处理/过滤步骤来将 BNP Paribas 数据帧转换为以下结构:
Structure of the Dataframe that should be sent to cdQA pipeline
如果您使用自己的数据集,请确保您的数据框架具有这样的结构。
当使用模型的 CPU 版本时,每个预测需要 10 到 20 秒才能完成。这个适中的执行时间是由于 BERT 阅读器,这是一个非常大的深度学习模型(约 110M 参数)。如果你有 GPU,可以直接用型号models/bert_qa_vGPU-sklearn.joblib
的 GPU 版本。这些预先训练好的模型也可以在 cdQA github 的发布页面上找到:https://github.com/cdqa-suite/cdQA/releases
培训/微调读者
您还可以提高预训练阅读器的性能,该阅读器在 SQuAD 1.1 数据集上进行了预训练。如果您有一个注释数据集(可以在 cdQA-annotator 的帮助下生成),其格式与小队数据集相同,您可以在其上微调阅读器:
# Put the path to your json file in SQuAD format here
path_to_data = './data/SQuAD_1.1/train-v1.1.json'cdqa_pipeline.fit_reader(path_to_data)
请注意,这种微调应该使用 GPU 来执行,因为 BERT 模型太大,无法用 CPU 来训练。
你也可以在官方教程中找到其他方法来完成同样的步骤:https://github.com/cdqa-suite/cdQA/tree/master/examples
cdQA-注释器
为了方便数据注释,团队构建了一个基于 web 的应用程序,即 cdQA-annotator 。
为了使用它,您应该将您的数据集转换为一个 JSON 文件,格式类似于 SQuAD:
from cdqa.utils.converters import df2squad# Converting dataframe to SQuAD format
json_data = df2squad(df=df, squad_version='v1.1', output_dir='.', filename='dataset-name.json')
现在您可以安装注释器并运行它了:
# Clone the repo
git clone https://github.com/cdqa-suite/cdQA-annotator# Install dependencies
cd cdQA-annotator
npm install# Start development server
cd src
vue serve
现在,您可以转到 http://localhost:8080/ ,在加载您的 JSON 文件后,您将看到如下内容:
cdQA-annotator interface
要开始注释问答配对,您只需写下一个问题,用鼠标光标突出显示答案(答案将自动写出),然后点击Add annotation
:
Annotating question-answer pairs with cdQA-annotator
注释完成后,您可以下载它,并使用它根据您自己的数据对 BERT 阅读器进行微调,如前一节所述。
cdQA-ui
该团队还提供了一个基于 web 的用户界面来耦合 cdQA。在这一节中,我将描述如何使用链接到cdQA
后端的 de UI。
首先,您必须通过在您的 shell 上执行来部署一个cdQA
REST API(确保您在cdQA
文件夹上运行它):
export dataset_path=path-to-dataset.csv
export reader_path=path-to-reader-model
FLASK_APP=api.py flask run -h 0.0.0.0
其次,您应该继续安装 cdQA-ui 包:
git clone [https://github.com/cdqa-suite/cdQA-ui](https://github.com/cdqa-suite/cdQA-ui) &&
cd cdQA-ui &&
npm install
然后,启动开发服务器:
npm run serve
您现在可以在 http://localhost:8080/ 上访问 web 应用程序。您将看到类似下图的内容:
Web application of cdQA-ui
由于应用程序通过 REST API 很好地连接到后端,您可以提出一个问题,应用程序将显示答案、找到答案的段落上下文以及文章的标题:
Demonstration of the web application running
在网站中插入界面
如果你想在你的网站上连接界面,你只需要在你的 Vue 应用程序中导入以下内容:
import Vue from 'vue'
import CdqaUI from 'cdqa-ui'
Vue.use(CdqaUI)import Vue from 'vue'
import BootstrapVue from "bootstrap-vue"
Vue.use(BootstrapVue)
import "bootstrap/dist/css/bootstrap.css"
import "bootstrap-vue/dist/bootstrap-vue.css"
然后插入 cdQA 接口组件:
演示
你也可以在官方网站上查看该应用的演示:https://cdqa-suite.github.io/cdQA-website/#demo
结论
在本文中,我介绍了cdQA-suite
,这是一个用于部署端到端封闭领域问答系统的软件套件。
如果你有兴趣了解更多关于这个项目的信息,可以随时查看官方的 GitHub 库:https://github.com/cdqa-suite。如果您喜欢这个项目,并且认为它对您和您的应用程序有价值,那么请不要犹豫开始并跟踪这个库。
我们最近发布了 1.0.2 版本的cdQA
包,它是高性能的,显示了非常有希望的结果。然而,仍有改进的余地。如果你希望对这个项目有所贡献,并有助于这些改进,你可以看看我们目前的问题:https://github.com/cdqa-suite/cdQA/issues。请随意选择一个并进行拉取请求:)。
干杯!
来源:
- GitHub 上的 cdQA 套件库:https://github.com/cdqa-suite
- 来自谷歌的官方 BERT 版本:https://github.com/google-research/bert
- 拥抱脸的 Pytorch 版伯特:https://github.com/huggingface/pytorch-pretrained-BERT
- 阵容数据集:https://rajpurkar.github.io/SQuAD-explorer/
- https://github.com/facebookresearch/DrQA/脸书研究公司的 DrQA:
- DeepPavlov,一个拥有开放域 QA 系统的库:https://medium . com/DeepPavlov/Open-Domain-question-answering-with-DeepPavlov-c 665 D2 ee 4d 65
- https://openai.com/blog/better-language-models/
- https://allennlp.org/elmo
- XLNet:https://arxiv.org/abs/1906.08237
如何在谷歌助手上创建你的个人习惯跟踪器
一个程序员为所有程序员设计的跟踪你的习惯的最懒的方法!
序言
在很长一段时间里,我一直试图在日常生活中加入新的习惯。我尝试了各种应用程序、纸张模板等。但是都不好用。我通常会忘记填充它们,或者觉得这样做太累了。最近,我得到了一个新的谷歌 nest mini,睡觉前用它聊天很有趣。所以,我想为什么不让谷歌助手帮我追踪我的习惯。
它是如何工作的
我:“嘿谷歌,跟习惯追踪器聊聊”
助手:“获得习惯追踪器的测试版”
习惯追踪器:“你今天锻炼了吗?”
我:“是”
……更多问题……
HabitTracker:“你看了什么论文吗?”
我:“没有”
HabitTracker:“我问了我所有的问题”
之后,在我的“习惯”google sheet 中插入新的一行:
Nothing feels better than filling a spreadsheet with your voice!
如何创造你自己的
本教程我们要做的:
1。创建一个 Google 表单并添加您自己的问题
2。创建一个可以编辑您的工作表
3 的服务。设置您的 Dialogflow 项目
4。和你的习惯追踪者谈谈
您需要一些基本的编程知识和一个 Google 开发人员帐户来完成这个演练。如果您想修改代码的某些部分,了解一点 Dialogflow 概念是有益的。完成演练大约需要一个小时。
1.创建您的谷歌表单
我用来填充 google 表单的脚本有一些假设,您应该遵守:
- 为时间保留第一列
- 保留前两行提问
你基本上可以复制这张表并添加你自己的问题。为后面的步骤保存您的电子表格键。
2.创建用于编辑工作表的服务
现在,您需要创建一个 google 服务帐户,并与它共享此文档。查看本节教程。经过这一步,你应该有你的client_email
和private_key
。
3.设置您的 Dialogflow 项目
Dialogflow 是用于创建对话机器人的谷歌服务。我们需要设置它,并将其连接到我们自己的 web 服务,以使事情正常工作。你需要在 Dialogflow 中上传我的 GitHub 项目中的一些文件,这些文件可以直接从这里下载。
- 首先,您需要创建一个新项目。
- 从左侧菜单,转到实体部分并上传是-否实体。实体是 Dialogflow 可以从对话中检测到的概念,并将其传递给我们的服务。
- 从左侧菜单中,转到 intents 部分并删除默认的欢迎意图。然后,上传动态意图。
- 从左侧菜单,进入完整菜单,并启用行内编辑器。将中的
index.js
内容复制到中,将中的package.json
内容复制到中,并粘贴到它们的标签页中。现在你应该修改index.js
并添加你自己的配置。这基本上是代码的前 3 行。
所有的逻辑都在里面index.js
它创建一个 Dialogflow 应用程序来处理请求,它连接到 google 电子表格,读取问题,并在所有问题都得到回答时添加一个新行。 - 部署您的功能!可惜,这不是结局。Firebase 函数不允许您向测试计划中的其他服务发出请求。你也必须升级你在 Firebase 的计划。Blaze 计划几乎是免费的,因为你的函数每天被调用的次数不会超过几次。
4.测试一切
在 Dialogflow 的右边部分,你可以通过说或输入“跟踪我的习惯”来开始与你的习惯跟踪器对话。你可以检查 Firebase 函数日志,看看是否一切顺利。最后,你可以直接在谷歌助手上测试它,只需点击“查看它如何在谷歌助手上工作”链接,然后从那里将你的机器人部署到你的所有设备上。
收场白
我用谷歌助手追踪我的习惯已经有 10 天了,感觉真的比其他方法好。首先,我有更多的动力去做我的习惯,因为当谷歌助手询问我的习惯时,对它说“是”的感觉真的很好;不知何故,这和我小时候老师问我有没有做作业的时候很像。说好的时候感觉真的很好,说不的时候感觉很丢人
第二,真的很简单,不打扰你睡觉。你不需要看着屏幕,你不需要你旁边的手机或者纸和笔。
最后但并非最不重要的一点是,数据保存在谷歌表单上的感觉真的很好。我可以随心所欲地处理我的数据,任何第三方都无法访问。这对于纸质习惯跟踪器和没有导出功能的第三方应用来说都不容易。
希望你喜欢我的文章和快乐习惯追踪!
如何在分析中避开 SQL 中间人
不断地为您的客户手动执行 SQL 查询?这里有一个让他们自助的方法。
我目前的人生目标之一是帮助数据分析师削减他们工作中无聊、麻木的方面,以便他们可以专注于更有趣、有用和酷的东西。
我在分析团队中看到的一种常见情况是,分析师扮演了一个不必要且高度重复的中间人角色,即业务用户反复需要某些特定数据,而由分析师手动执行这些重复的 SQL 查询来提取数据并将其发送给客户端。相同或非常相似的查询,一次又一次。不好玩。实际上在今天的技术下完全没有必要。
我爱 R 生态系统。我喜欢它的原因之一是因为它可以让你轻松地做一些神奇的事情,将数据源与基于 web 的交互联系起来。在这篇文章中,我将向您展示如何使用 R Shiny 建立一个简单的 web 应用程序,它将允许您的非技术专业客户从 SQL 数据库中选择他们想要的原始数据,并将其提取和下载到 Excel 电子表格中。这是去掉中间人的安全方法,因为您可以控制谁可以访问 Web 应用程序,以及允许它从数据库中检索哪些数据。
我将在这里使用一个简单的场景来说明这些概念,但是这个想法可以扩展到能够向您的客户端提供大量可下载的预处理数据。
你需要什么
- r 安装了
shiny
、dplyr
、openxlsx
、rmarkdown
和odbc
包。 - 您希望从中检索特定数据的 SQL 数据库。在本文中,我将假设它是一个 Oracle SQL 数据库。
- RStudio Connect 文档/应用托管平台,或至少访问一个闪亮的服务器。
我们的简单示例场景
让我们假设你是一家连锁兽医诊所的数据分析师。每天您都会收到一些关于预约和预约取消的数据请求。我们会问两个问题:在这几年中,我们为每种动物预约了多少次?其中有百分之多少被取消了?您已经厌倦了一次又一次地使用相同的 SQL 查询来回答这些问题。
您的约会数据库表称为APPTS_DB
,它有许多列,特别是DATE
(格式为DD-MMM-YYYY
,例如01-MAR-2017
)、ANIMAL_TYPE
(例如Cat
、Dog
)、CANCEL_FLAG
(如果约会被取消,则为二进制1
,否则为0
)。
我假设你知道闪亮应用的结构。在这篇文章中,我将把这个闪亮的应用写成一个交互式 R markdown .Rmd
文档。有关这方面的更多信息,请参见此处。
步骤 1:将您的 SQL 查询转换成 R 中的函数
将常用的 SQL 查询转换成 R 函数确实是一个好主意,即使您在本文中没有做任何其他事情。它允许您在 R 会话中用一个命令执行常见的查询。
为了将这一点构建到您的应用程序中,这一步可以在一个单独的 R 脚本中完成,您可以将其加载到您闪亮的应用程序中,或者它可以作为应用程序本身的代码块来完成。我们假设是后者。
首先,我们建立一个到数据库的连接。如果您打算将代码存储在 Github 或其他任何可能被他人看到的地方,我建议将您的凭证放在系统环境中。
```{r db_connect}db_conn <- odbc::dbConnect(odbc::odbc(),
dsn = Sys.getenv("DSN"), # <- database
uid = Sys.getenv("UID"), # <- user id
pwd = Sys.getenv("PASS")) # <- password```
首先,我们用占位符编写 SQL 查询,然后使用gsub()
用函数参数替换占位符,然后运行查询。我们希望设置它来提取从指定的起始年到结束年的时间段内按动物类型的约会总数,并计算取消率。理想情况下,我会建议您使用dbplyr
以整洁的形式完成这个查询,但是我在这里将使用原始 SQL 来完成,因为大多数读者对此都很熟悉。
```{r query_fn}# create query functionappt_query <- function (start_yr, end_yr) {# write query with placeholders qry <- "SELECT ANIMAL_TYPE, COUNT(*) NUM_APPTS,
SUM(CANCEL_FLAG)/COUNT(*) PERC_CANCELLED
FROM APPTS_DB
WHERE EXTRACT(YEAR FROM DATE) BETWEEN start_year AND end_year
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE"# replace placeholders with function arguments qry <- gsub("start_year", start_yr, qry)
qry <- gsub("end_year", end_yr, qry)# execute query odbc::dbGetQuery(db_conn, qry)} ```
这非常强大,因为它允许使用简单的命令如appt_query(2015, 2017)
获取信息。您也可以使用一个简单的paste()
函数将 SQL 查询粘贴在一起,但是我发现使用gsub()
更容易管理和检测错误。
步骤 2:设置闪亮的应用程序输入和下载按钮
现在,我们为最终用户设置了一些简单的输入,以及一个下载按钮,他们将按下该按钮来执行查询并下载他们需要的数据。
在这个简单的例子中,只需要用户输入起始年份和结束年份。我们将从 2010 年开始我们的年度期权,到今年结束
```{r user_input}# get current yearcurr_year <- format(Sys.Date(), "%Y")# set up panel to select start and end yearsmainPanel(
HTML("<br>"),
selectInput("start_yr", "Select start year:",
choices = c(2010:curr_year)),
selectInput("end_yr", "Select end year:",
choices = c(2010:curr_year)),
HTML("<br>"),
uiOutput("downloadExcel")
)# generate download button confirming the input selectionoutput$downloadExcel <- renderUI(
downloadButton("downloadData", paste("Download Data for", input$start_yr, "to", input$end_yr, "in Excel"))
)```
这将创建一个带有下载按钮的用户输入面板,确认所选择的年份。这个 download 按钮将链接到一个名为downloadData
的服务器进程,在这里我们将执行查询并写入一个 Excel 文件供用户下载。
步骤 3:编写后台代码来执行查询和下载数据
现在我们编写服务器进程来执行查询和下载数据。这变得更简单了,因为我们设置了一个简洁的函数来执行查询(参见步骤 1)。我们还将建立一个整洁的进度条,以便用户可以看到该进程是如何进展的。对于一个可以立即完成的简单查询来说,这是不必要的,但是如果您正在使用许多不同的查询构建一个多选项卡的电子表格,那么它是必不可少的,以便让用户确信正在发生一些事情。
```{r query_and_download}# use downloadHandleroutput$downloadData <- downloadHandler(# give download file a name filename = function() {
paste0("animal_appt_data_", input$start_yr, "_", input$end_yr, ".xlsx")
},# download and populate excel file content = function(file) {# create progress bar for user with first step
shiny::withProgress(
min = 0,
max = 1,
value = 0,
{
shiny::incProgress(
amount = 1/2,
message = "Retrieving data from database..."
)
# get data using function data <- appt_query(input$start_yr, input$end_yr)# set up an excel file in a tab called "Appointment Data" shiny::incProgress(
amount = 1/2,
message = "Writing to Excel..."
) wb <- openxlsx::createWorkbook()
openxlsx::addWorksheet(wb, "Appointment Data") # design a nice header style so the results look professional hs1 <- openxlsx::createStyle(fontColour = "#ffffff",
fgFill = "#4F80BD",
halign = "left",
valign = "center",
textDecoration = "bold",
border = "TopBottomLeftRight",
wrapText = TRUE)# write the results into the "Appointment Data" tab with a nice border openxlsx::writeData(wb, "Appointment Data", x = data,
startRow = 1, startCol = 1,
borders = "surrounding",
headerStyle = hs1)# save Excel file and send to download openxlsx::saveWorkbook(wb, file, overwrite = TRUE) } # <- end progress bar
) # <- end withProgress}) # <- close content wrapper and downloadHandler function```
步骤 4:向客户端提供访问权限
使用这种方法,客户端只能访问您为其设计的数据。如果您使用 RStudio Connect 共享平台,您可以将其发布为应用程序,并仅向特定个人或群组提供访问权限,确保只有授权的客户端才能访问。如果您使用 Shiny Server Pro,请从用户文档中寻求如何控制用户访问的建议。
结论和延伸
如果你是一个流利的闪亮的用户,你可能会立即掌握这里发生了什么。如果没有,你可能需要更多的培训,在你接受这个之前。这种方法可以扩展到非常强大。仪表板可以使用ggplot2
或plotly
来设计,而不是——或者除了——Excel 下载。像async
、future
和promises
这样的包可以用于使用异步编程的多个并发用户的伸缩(更多信息见这里)。在最高级的情况下,可以使用这里介绍的初始概念在 Shiny 上构建和托管一个完整的灵活的商业智能平台。
最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在LinkedIn或Twitter上找我。
如何应对冒名顶替综合症
诀窍?把冒名顶替综合征当做优点,而不是缺点。
Photo by Shuto Araki on Unsplash
我第一次走进人工智能聚会时,我觉得我不应该在那里。
第二次走进一个机器学习的活动,我觉得我不应该在那里。
当我第 20 次走进一个人工智能聚会时,我觉得我不应该在那里。这是在做了一年机器学习工程师之后。
但还是有所不同。第一次和第二十次的区别。
除了实地经验外,我还有实践经验。我参加过很多活动,我知道那种感觉会在那里,我越来越擅长处理它。我用它作为动力。提升自己的动力。
我意识到其他人可能也有同样的感受。我会对自己说,我们来这里都是有原因的,我们来这里都是为了学习,我们来这里都是因为我们对相似的东西感兴趣。
问题是,这个过程,冒名顶替的感觉,不会止于事件。到处都有。
当我开始在网上写文章时,我害怕点击发表按钮。
当我写一个关于我生活的故事时,我问自己,谁会想读这个?
当我走进政府大楼,编写我在网上学会的数据科学代码时,我觉得我不应该在那里。
当我开始在我的卧室里制作视频时,同样的事情。谁会想看这个?
我。
就是他。我想要阅读这篇文章。我希望看到我的代码被很好地使用。我想要去参加这个活动。我想在 20 年后看这个视频,以此来提醒我从哪里开始。
你可能会把冒名顶替综合症视为一种弱点。我曾经。不再是了。现在我认为这是我最大的优势之一。
最大的优势?
通常,价值来自于发现它的弱点并找出它的反面。
冒名顶替综合症可能是你最大的优势,因为它意味着你意识到了自己的能力。这意味着你意识到你可以改进。因为你意识到了这一点,如果你以正确的方式去做,你就会进步。
冒名顶替综合症可能永远不会消失。但是你会更好地处理它。
而不是让冒名顶替综合症阻碍我。我用它来推动我前进。
如果我承担了编写代码的责任,它最好运行良好。
如果我承担了发表文章的责任,它们最好值得一读。
如果我承担了制作视频的责任,它们最好值得一看。
我告诉自己。
你不是骗子,你就是你。
你也应该这样做。
如何处理嘈杂人群中的异常值?
定义异常值可能是一项简单的任务。另一方面,决定如何处理它们总是需要一些更深入的研究。
动机
数据可能会有噪音。当你有一个小的(相对于人口规模),随机样本的人口,尤其是嘈杂的人口,它可以是一个相当大的挑战,如果不是不可能的,建立一个模型,将概括得很好。
假设您构建了一个简单的线性模型,该模型对您的数据表现不佳。然后,您决定计算学生化残差,并移除超出特定范围的所有观察值。因此,您的模型更符合数据。最后,你把它投入生产,这是一场噩梦。
噪声数据并不罕见,它会极大地影响您的发现。知道如何识别和如何处理对任何准确的发现都很重要。模拟是帮助我们探索和更好理解这个问题的一个很好的工具。
模拟异常值和简单的线性模型
如果你还没有,你应该建立自己的模拟。这是巩固你从统计教科书或课程中学到的知识的好方法。您可以尝试从头开始创建示例,甚至可以随意修改。
为此,我喜欢使用 Rstudio。比方说,我们正在就二手车相对于里程数的定价向二手车经销商提供建议。让我们假设这两个变量的大小为 100,可以使用简单的线性回归很好地建模。我将用以下系数定义真实人口回归线:
b0 <- 21345
b1 <- -0,1349
让我们通过从均值为 76950.45、标准偏差为 16978.58 的正态分布中取样来创建独立变量里程:(这些值是根据可用的数据集选择的,此处为。)
mileage <- rnorm(n = 100, mean = 76950.45, sd = 16978.58)
接下来,我将引入带有随机误差项的噪声。我将从标准偏差等于 500 的正态分布中对其进行采样,并且我将更改单个值以创建合适的异常值。
eps <- rnorm(n = 100, mean = 0, sd = 500)
eps[81] <- 15000
通过改变这个单一值,随机误差项标准偏差增加了三倍:
> sd(eps)
[1] 1586,312
因变量的时间:
price <- (b0 + b1*mileage + eps)
让我们绘制数据:
Figure 1: Scatter plot of mileage versus price showing the true regression line in black, the least-squares line in blue and two outliers colored yellow and red.
我们可以清楚地看到图 1 中的两个异常值。其余里程值方面,两者都有不寻常的值。两者都是高杠杆点。但是,如果我们只去掉红点,我们会发现它是唯一有影响的点:
Figure 2: Scatter plot after the removal of the influential point. Although the yellow point is influencing the least-squares line by decreasing its slope, its influence is so small it can be ignored.
如果我们比较这两个模型的统计数据,我们可以看到一些非常不同的值。例如,在我们去除影响点之后,剩余标准误差从 1518 下降到 514,这分别非常接近误差项标准偏差的实际值 1586 和 500。
这是两个残差图:
Figure 3: Left: Scatter plot of the residuals before removing the influential point. Right: Scatter plot of the residuals after removing the influential point.
我们在本例中没有看到但应该提到的一点是,有时不影响最小二乘方线的异常值可能具有较大的残差。这仍然是一个问题,因为正如我们在上面看到的,一个大的残差会产生一个大的残差标准差,我们用它来确定置信区间和 p 值。
解决示例问题
现在我们需要决定是否要完全移除影响点。对这个问题要格外小心。你需要一个非常好的理由来删除它。如果我们观察这两个模型的 R 平方,我们会看到很大的不同。具有影响点的模型具有大约 60%的 R 平方,而当影响点被移除时,R 平方为 95%。这种差异可能看起来是删除的一个足够好的理由,但就其本身而言,它不是。
为了更好地理解这一点,我们需要了解一个经常被忽视的简单事实。我们的目标不是预测过去,而是预测未来。上述数据的小窗口由 100 个单独的观察值组成。在该窗口上计算的每个统计量都是真实总体统计量的点估计。简单的线性回归确实擅长捕捉窗口内两个变量之间的关系,但不一定能捕捉到窗口外的关系。在使用你的模型进行推断时,你应该非常小心。当我们从这两个模型中选择一个时,我们实质上是对总体做了一个假设。没有影响点 RSE 的模型小三倍。这意味着 95%的置信区间将缩小三倍。本质上,我们的预测会更有信心。数据中没有任何东西告诉我们可以对人口做出如此自信的假设。为了了解种群的样子,我们需要做一些研究。与模拟不同,我们永远不会知道真实的人口统计是什么样子。所以我们需要一个想法,我们需要对人口进行假设。
让我们想象一下,我们明显的目的地是我们的客户,汽车拍卖商。车主告诉我们,这辆车是一辆不寻常的旧车,吸引了一小群非常想要它的买家的注意。他们相互竞价,把价格抬得异常高。此外,老板向我们保证,这是该公司 20 多年历史中唯一的一次,不会再发生了。他们处理普通的日常车辆。
有了这些知识,我们回到我们的模型,自信地去除异常值。就模型统计而言,这意味着我们确信模型的剩余标准误差为 514,这进一步意味着我们可以假设真实误差项标准偏差接近该数字(因为数据是模拟的,所以我们知道它等于 500)。如果我们想得到正确的其他点估计,这个人口估计是至关重要的。
如果所有者不是如此自信,我们就不应该决定移除异常值。相反,我们可以探索二手车市场,并试图找到真实误差项标准差的外部估计。如果我们的模型,或者任何其他的模型,忽略了我们不能确信在生产中不会发生的极端值,那么它在投入生产时会表现很差。剔除不当的异常值会导致过于自信的估计。
结论
忽略或删除异常值是很诱人的。没有非常好的理由不要做它。总是做外部研究,以便找到假设的真实人口统计数据。这可能是说起来容易做起来难。
在这个例子中,真实世界不像模拟数据那样容易理解。尽管如此,我认为这个例子应该作为进一步研究的动力。它应该激励你去解决一个现实世界的问题,不仅仅是用一个数学公式来决定你的数据中哪些离群值应该被删除,而是去实验和假设真实的人口统计数据。只有深入了解总体情况,才能回答要剔除哪些异常值的问题。
参考
戴维·M·迭斯、克里斯托弗·D·巴尔(2015 年)。统计学第三版。openintro.org
加雷斯·詹姆斯,丹妮拉·威滕,特雷弗·哈斯蒂,罗伯特·蒂布拉尼(2017)。统计学习导论及其在 r。
阿里尔·马尔登(2018)。模拟!模拟!—第 1 部分:线性模型。
安德鲁·盖尔曼,约翰·卡林(2014)。超越功率计算:评估 S 型(符号)和 M 型(幅度)误差(2014)。心理科学透视第 9 卷第 6 期 641-651 页。
布兰登·福尔茨(2019)。统计学 101:线性回归、异常值和有影响的观察。
深度学习时代如何应对不确定性
TensorFlow 在深度学习社区中引入了概率建模
Photo by Hossein Soltanloo on Unsplash
最近,每天都有新的出色的机器学习应用发布,很可能是由一些深度学习模型驱动的。在表面之下,成千上万的公司将相同的技术应用于各种不同的过程。最迟当它支持关键决策时,你应该考虑每一个预测的确定程度。我们将解释为什么会这样,如何定义不确定性,并最终查看一些代码示例,以便您能够在下一个项目中应用我们的发现。
特洛伊斑马的故事
我们来做一个思维实验。假设你是一家组织旅行的公司,你想为客户的冒险创造一个更安全的体验。作为一名机器学习工程师,你的目标可能是创建一个图像分类器,将周围的动物标记为“潜在危险”或“可能无害”。这个程序会让顾客感到安全,并在必要时给予他们预防措施。
幸运的是,一个月前你在所有的车上安装了摄像头,这样你现在就有了大量斑马、蛇、长颈鹿等的图像。你马上开始训练你的神经网络。初步评估显示,您的模型运行得相当好,可以检测出各种潜在危险的蛇和无害的斑马。
“那太好了”,你想,“但是如果我在实践中使用这个模型,而一只在数据中被低估甚至完全不存在的动物出现在我的相机前,那该怎么办?”
这个模型被迫在两个可能的结果中选择一个,尽管它实际上没有任何线索。进一步想象一下,在这种情况下,(几乎)未知的动物是一只老虎。由于某些相似性(条纹、四条腿等),模型可能会在其内部表示中定位照片。)更接近斑马,而不是捕食者,因此错误地分类了情况。
Photo by Smit Patel on Unsplash
如果模型能够传达其不确定性,并且因为您主要对客户的安全感兴趣,您可以校准您的系统,以便在有疑问时做出防御性反应,这不是很好吗?
预测不确定性有许多原因,但从我们的建模角度来看,基本上可以归结为两类。最简单的方法是把它看作与数据和模型相关的不确定性。
任意不确定性
前者可能是更明显的一个。每当你在相同的环境下进行多次测量时,每次都不可能得到完全相同的结果。这是为什么呢?原因有几个:如果你用的是传感器,每个设备本身都有它的准确度、精密度、分辨率等。在手动实验室样本的情况下,所使用的技术、个人技能和扮演其角色的经验。基本上,测量的每个方面都是未知的,因此会引入某种随机性,这属于这一类。
如果你能够减少随机的不确定性,取决于你对收集数据的方式有多大的影响力。
认知不确定性
既然我们已经涵盖了数据中的不确定性,那么模型呢?这不仅仅是模型解释给定数据的能力的问题,而是数据包含所有已知信息的确定程度的问题。看待认知不确定性的另一种方式是衡量一个(无限的)模型集合对结果的认同程度。如果多个模型得出严重偏离的结论,这些数据显然没有描绘出全貌。
例如,试图拟合复杂函数的简单模型、太少或缺少数据等都可能导致认知上的高度不确定性。这就是你作为建模者的经验可以大放异彩的地方。是不是缺少了一个重要的特性?在你的训练数据中,有没有代表不足的情况?你选对型号了吗?
实用的方法
由于两种类型的不确定性在所有预测中都不是恒定的,所以我们需要一种方法来为每个预测分配特定的不确定性。这就是新的 TensorFlow Probability 软件包介入拯救世界的地方。它提供了一个框架,将概率建模与我们钟爱的深度学习模型的能力相结合。
chart 1: example data
为了演示的目的,我们将采取一个非常简单的回归问题,只有一个输入和一个输出维度。训练数据的两个 blobs 在它们的标准偏差方面不同,并且在它们之间是我们没有任何数据的空间。模型能够以任何有意义的方式考虑和交流这些方面吗?
我们将采用两层神经网络。第一个以 sigmoid 为激活,第二个以 identity 函数为激活。到目前为止,一切如常。
最后缺少的步骤是来自张量流概率的新TFP . layers . distributionλ层。它返回的不是一个张量,而是一个TFP . distributions . distribution,你可以用它来执行你期望从分布中得到的所有类型的操作,比如采样,导出它的均值或标准差等等。
chart 2: aleatoric uncertainty
chart 3: aleatoric uncertainty (standard deviation)
你注意到第二致密层的两个神经元了吗?他们需要学习输出分布的均值和标准差。
你可以看到,通过预测一个分布而不是一个单一的值,我们越来越接近我们实际想要达到的目标。如前所述,两个斑点具有不同的方差,并且模型在其预测中反映了这一点。可以认为,对于每个斑点,该模型预测了关于拟合的平均曲线的恒定方差,该方差似乎与数据不匹配,但是这是由于有限的模型复杂性,并且将随着自由度的增加而解决。
但是在两个 blobs 之间发生了什么呢?这不是我们对一个没有数据的空间中的不确定性度量的期望,对吗?谁说在那个空间里,在远离拟合函数的某个地方,没有另一个不可测量的斑点?没人;我们只是不知道。模型也没有。不管怎样,你不应该对模型的插值感到太惊讶。
毕竟,这就是模型的作用:在没有数据的情况下,学习最符合已知数据且不损害这一目的的函数。
那么,我们如何弥补这种信息的缺乏呢?事实证明,我们之前已经讨论过解决方案:考虑认知不确定性。
基本方法是将使用分布代替单个变量的想法向前推进一步,并将其应用于所有模型参数。因此,我们以之前的示例为例,用 TFP . layers . dense variative 层替换两个 Keras 密集层。因此,该模型不仅学习一组权重和偏差,而且将其所有参数视为随机变量,其或多或少的方差取决于它找到最佳拟合的确定程度。在推断期间,模型从参数分布中取样,这导致每次运行的不同预测。因此,必须进行几次推断,并计算总体平均值和标准偏差。
chart 4: aleatoric and epistemic uncertainty
chart 5: aleatoric and epistemic uncertainty (standard deviation)
这个升级版的模型如何处理我们的玩具数据?我们可以看到,它仍然反映了两个 blobs 附近的不同方差,尽管它们似乎都增加了。这实际上是有意义的,因为我们看到的是两者的总和,即任意的和认知的不确定性。
此外,在两个数据点之间,行为发生了更剧烈的变化:由标准偏差表示的模型不确定性现在在我们没有任何可用数据的情况下达到峰值。这正是我们所希望的。
让我们再看一下我们的例子,并思考为什么它实际上是有效的。概括地说,该模型试图找到最符合数据的函数。难道没有很多其他函数能像图表 4 中的函数一样很好地拟合数据吗?例如,如果将曲线沿 x 轴稍微向左或向右移动,损耗不会显著变化。因此,造成这种移动的模型参数具有广泛的分布。在给定数据的情况下,模型对这个参数相当不确定。
如果您对完整的代码示例感兴趣,可以看看 jupyter 笔记本。它基于tensor flow probability团队与他们的博客就同一主题发表的一篇文章。如果你想更深入地研究,我推荐查看一本 jupyter 笔记本的重写版由 Cameron Davidson-Pilon 撰写的《黑客的贝叶斯方法》一书。我非常喜欢他们展示内容的互动方式。
结论
通过查看一个使用张量流概率的简单示例,我们看到了在我们的模型中考虑不确定性的重要性,以及如何克服随之而来的挑战。虽然这个库还很年轻,但我预计它很快就会变得成熟起来,因为它提供了一种简单的方法,通过无缝地适应 Keras 来结合概率建模和深度学习。
希望在从预测中得出重要决策之前,关注模型的可靠性将成为越来越普遍的做法。看到可以说是最广泛使用的深度学习库为此奠定基础,至少是朝着正确的方向迈出了一大步。
如果你觉得这篇文章有帮助,请在评论中告诉我你的想法和经历,别忘了在 Medium 和 LinkedIn 上关注我。
如何使用梯度检查调试神经网络
理解数学并学习如何执行梯度检查
Photo by Sue Thomas on Unsplash
当从零开始实现一个神经网络时,反向传播可以说是更容易出错的地方。因此,在调试神经网络时,调试此步骤的方法可能会节省大量时间和麻烦。
这里将介绍梯度检查的方法。简而言之,该方法包括使用数值方法来近似梯度。如果它接近计算的梯度,那么反向传播是正确实现的!
让我们深入了解更多的细节,看看如何在项目中实现它。
对于机器学习、深度学习和人工智能的实践视频教程,请查看我的 YouTube 频道。
Bugs are scary… Let’s get rid of them with gradient checking!
一点微积分
假设你有一些微积分的知识,梯度检验会非常容易理解。
我们知道反向传播计算导数(或梯度)。在微积分课程中,你可能记得导数的定义如下:
Definition of the derivative
上述定义可用作导数的数值近似值。取足够小的ε,计算出的近似值将在ε平方的范围内具有误差。
换句话说,如果ε为 0.001,则近似值将偏离 0.00001。
因此,我们可以用它来近似梯度,进而确保反向传播正确实现。这构成了梯度检查的基础!
矢量化实现
现在,在用 Python 实现梯度检查之前,我们需要定义一种矢量化形式的梯度检查。
让我们将权重和偏差矩阵重新整形为一个大向量 *theta。*同样,它们各自的所有导数都将被放入一个向量 d_theta 。因此,近似梯度可以表示为:
Vectorized approximation of the gradient
注意上面的等式和极限的定义几乎是一样的!
然后,我们应用以下公式进行梯度检查:
Gradient check
上面的等式基本上是由向量的范数之和归一化的欧几里德距离。在其中一个向量非常小的情况下,我们使用归一化。
作为ε的值,我们通常选择 1e-7。因此,如果梯度检查返回值小于 1e-7,则意味着反向传播被正确地实现。否则,您的实现中可能会出现错误。如果该值超过 1e-3,则可以肯定代码不正确。
代码
为了便于理解,让我们编写梯度检查代码,并将其应用于一个简单的示例。如果你卡住了,代码在这里可用。
我们从定义一个非常简单的激活函数开始:
然后,我们实现反向传播:
当然,您会注意到反向传播是正确实现的。随意放一个错误,以测试梯度检查的鲁棒性。
现在,我们实现梯度检查:
完美!让我们检查一下反向传播是否正确实现了:
您应该会看到以下内容:
恭喜你!您现在知道如何使用梯度检查来调试您的神经网络了!如果您在不使用框架的情况下构建神经网络,这尤其有用。否则,像 TensorFlow 和 Keras 这样的框架会自动处理反向传播步骤,您可以放心地假设它已正确实现。
在未来的帖子中,我将展示如何使用正则化来改进神经网络。
干杯!
如何在亚马逊 SageMaker 和微软 Azure 机器学习工作室之间抉择
两者都可以更快地构建模型,但是针对的用户类型非常不同
我最近发表了一篇微软 Azure Machine Learning Studio(Studio)的走查,对它的简单和强大印象良好。但是,还有其他工具也声称可以使机器学习更容易,并加快模型开发。我想知道他们如何比较?所以,本周,我要看看亚马逊 SageMaker (SageMaker)以及它与 Studio 的比较。
当我将 SageMaker 与 Studio 进行比较时,我发现了一种非常不同的建模方法。每种工具的供应商都声称提供全面管理的服务,覆盖整个机器学习工作流程,以快速构建、训练和部署机器学习模型。这是完全正确的。然而,他们以截然不同的方式实现这一点。
Azure Studio 有一个拖放 UI,其中机器学习建模过程是在画布上构建的(如果用户没有太多偏离,完全没有代码)。用户可以避开复杂的数据工程、开源库和 Python 编码。该产品面向数据分析师、公民数据科学家以及其他希望以简单、直观的方式构建模型的人。
另一方面,SageMaker 严重依赖代码,大部分用户交互都是在熟悉的 Jupyter 笔记本上进行的(当然,这是数据科学家最常用的工具之一。)SageMaker 环境将允许最大的灵活性(使用 Python——数据科学家最流行的编码语言),但需要比 Studio 更多的数据工程、数据存储和计算资源方面的知识。
因此,虽然这两种产品都使数据科学变得更容易,但这实际上是比较苹果和橙子的情况,因为它们的运作方式如此不同。SageMaker 不适合 Studio 的目标用户,他们不了解编码和数据工程,Studio 似乎限制了精通软件的数据科学家和开发人员,他们习惯于编码他们想要的任何东西。
要了解为什么这些产品是为不同的用户设计的,最好是通过屏幕截图浏览模型构建的过程,了解每个产品如何进行设置、获取数据、准备数据、构建和训练模型、对模型进行测试和评分以及部署。
对于 SageMaker,我将使用 Python3 实现 XGBoost 算法,为一家银行的市场部预测一位客户是否会购买 CD。对于 Studio,我将使用各种汽车属性进行线性回归,以预测汽车的价格。下面是这两种产品的工作原理。
设置—创建环境
亚马逊 SAGEMAKER
使用 Amazon SageMaker,我们首先在云中创建一个 Jupyter 笔记本实例。
创建笔记本实例是为了让用户可以访问 S3 (AWS 存储)和其他服务。请注意,在这个设置过程中,用户正在决定他们应该访问哪些 S3 存储桶,选择他们的云实例的大小和其他技术细节,这可能会让公民数据科学家感到困惑。
AZURE 工作室
Azure 机器学习工作室的启动点是主页。
与 SageMaker 中所需的初始设置和实例管理相比,Studio 看起来更像一个业务应用程序,并且跳过了复杂性。基本布局显示在左侧的以下选项卡中:
项目——代表单个项目的实验、数据集、笔记本和其他资源的集合
实验-您创建或保存的实验
Web 服务——您从实验中部署的 WEB 服务模型
笔记本—您创建的 Jupyter 笔记本
数据集-您已上传到 Studio 的数据集
训练模型-您在实验中训练并保存的模型
获取数据
AZURE 工作室
Studio 允许您在该屏幕截图的左侧导入和保存数据集。在这个例子中,我选择了一个标签为**汽车价格数据(原始数据)**的数据集,然后将这个数据集拖到实验画布上。
studio 的工作方式是通过创建画布来进行机器学习实验。在画布上,用户拖放必要的组件,如数据集、转换、算法等…在有序的流程中进行模型实验。在测试和决定模型之后,实验被转换为工作模型并发布。
数据科学家欣赏的一个非常好的特性是能够快速查看数据列和分布,以了解他们正在处理的数据。要查看这些数据,只需单击数据集底部的输出端口,然后选择 Visualize。
亚马逊 SAGEMAKER
在本例中,将数据放入 SageMaker 的过程是用 Python 以编程方式完成的。用户选择数据集(可以是 CSV 文件等。)并将其导入熊猫数据框架进行分析。这被集成到后面显示的 SageMaker 的数据准备部分。在本例中,代码类似于 Python 命令:
model_data = pd.read.csv(…。)
准备数据
亚马逊 SAGEMAKER
在 SageMaker 中,一旦用 Python 编写了数据,用户就可以自由地以编程方式转换列,删除缺少数据的行等…完全灵活。稍后,我将向您展示一些样例代码,其中包括重新格式化标题和列,作为模型选择部分的一部分。
为了在训练模型之前在 SageMaker 中完成数据准备,还需要完成许多步骤来配置环境。注意:这里再次强调容器、数据框架、库,定义正确的 S3 桶和国家区域。这种复杂性对 Studio 中的用户是屏蔽的。
首先,我们需要选择我们正在使用的 Python 版本——conda _ Python 3。
为了准备数据、训练机器学习模型并部署它,我们需要导入一些库并定义一些环境变量。在这种情况下,这样做的代码如下所示。我们将运行 Jupyter 笔记本中的代码。
我们将需要一个 S3 桶来存储我们的训练数据,一旦我们处理了它,这也需要定义。
接下来,我们需要将数据下载到我们的 SageMaker 实例,并如上所述将其加载到 Pandas 数据帧中。要做到这一点,应该如下所示:
AZURE 工作室
与基于代码的方法相比,Studio 提供了一种拖放的可视化方法。Studio 中的数据集和模块具有由小圆圈表示的输入和输出端口——输入端口在顶部,输出端口在底部。要在实验中创建数据流,需要将一个模块的输出端口连接到另一个模块的输入端口。您可以随时单击数据集或模块的输出端口,查看数据流中该点的数据。
Studio 使数据准备过程对业务用户来说非常容易。它们提供了一个模块(选择数据集中的列,以完全删除不需要的列(在本例中为归一化损失列,它有许多缺失值)。我们只需将数据集模块中的选择列连接到我们的汽车数据集,并选择要排除的列。
类似地,为了删除丢失数据的行,我们将清除丢失数据模块拖到实验画布上,并将其连接到数据集模块中的选择列。
建立&训练模型
这一步包括将数据分成训练和测试子集,选择预测所基于的特征,并选择最适合数据的算法。
分割数据并选择特征
亚马逊 SAGEMAKER
将数据分成训练集和测试集是通过几行 Python 代码完成的。训练数据(本例中为客户数据集的 70%)将在一个称为梯度优化的迭代周期中使用,以学习模型要素并以最小的误差从输入要素中推断分类标签。这似乎是 SageMaker 在这个例子中的一个优势,因为功能选择(独立变量)是自动执行的,而在 Studio 中,我们手动选择功能,正如您将看到的。剩下的测试数据(30%)将用于稍后评估模型的性能。
AZURE 工作室
为了在 studio 中分割数据和选择特性,我们使用 Dataset 和 split data 模块中的 select 列。
Studio 允许我们通过选择我们认为将提供预测能力的列来选择传递给训练算法模块的特性,并进行迭代,直到我们获得所需的性能。我确实发现 Studio 中的一些机器学习算法确实使用特征选择或维度缩减作为训练过程的一部分。当我们使用这些算法时,我们可以跳过特征选择过程,让算法像 SageMaker 一样决定最佳输入。对于线性回归,我们手动选择特征。
为了分割数据,我们将使用分割数据模块,直观地选择分割百分比,而不是像在 SageMaker 中那样进行编码。
训练模型
亚马逊 SAGEMAKER
我们已经预先确定将使用 SageMaker 预构建的 XGBoost 算法。类似于我们在准备数据部分如何在 Studio 中消除列和行,我们可以在 SageMaker 中用 Python 进行相同类型的数据清理和重新格式化。下面的代码(在单元格#6 中)重新格式化训练数据的头和第一列,并从 S3 存储桶加载数据。
接下来,我们需要设置 SageMaker 会话,创建 XGBoost 模型的实例(估计器),并定义模型的超参数。这个的代码在 7 号单元格。
加载数据并设置 XGBoost 估计器后,我们现在可以在 ml.m4.xlarge 实例上使用梯度优化来训练模型,方法是使用单元格#8 中的代码在 Jupyter 笔记本中选择 run。
AZURE 工作室
为了添加我们希望使用的学习算法,我们展开画布左侧的机器学习类别,并展开初始化模型部分。我们已经预先确定我们将使用线性回归,所以选择线性回归模块并将其拖到画布上。接下来,我们将找到火车模型模块并将其拖动到实验画布上。将线性回归模块的输出连接到训练模型的输入,并将分割数据模块的训练数据(左端口)连接到训练模型,如图所示。
单击火车模型模块,然后在属性窗格中单击启动列选择器,然后选择价格列。价格是我们的模型将要预测的价值…我们将价格从可用列移动到选定列列表中。
我们终于可以进行实验了。我们现在有了一个经过训练的回归模型,可以进行价格预测,我们在 Studio 中的模型创建流程如下所示:
测试、评分和部署模型
亚马逊 SAGEMAKER
要在 Sagemaker 中测试模型,我们必须首先部署它,这是一个与在 Studio 中不同的过程。为了在服务器上部署模型并创建端点,我们在 Jupyter 的 cell 9 中运行以下代码。为了预测测试数据中的客户是否注册了银行产品,我们将在 Jupyter 的单元格 10 中运行代码。
为了评估性能,我们编写 Python 代码来比较实际性能和预测性能,并生成如下结果表。
从这些结果中,我们可以得出结论,该模型准确地预测了测试数据中 90%的客户的结果,对于注册的客户,精度为 65% (278/429),对于未注册的客户,精度为 90% (10,785/11,928)。
最后,在 Sagemaker 中,我们还需要记住终止我们的会话并清理云资源,以消除我们帐户中的进一步费用。下面的代码删除了 SageMaker 端点和 S3 存储桶中的对象。
AZURE 工作室
既然我们已经在 75%的数据上训练了 Studio 模型,我们可以使用它来对另外 25%的数据进行评分,以查看我们的模型运行得有多好。我们通过将乐谱模型模块拖到实验画布上,并将训练模型的输出连接到它来实现这一点。然后,我们将分割数据模块的测试数据输出(右端口)连接到评分模型模块,如图所示。
然后,我们运行实验,并通过单击底部端口并选择 Visualize 来查看分数模型的输出。预测价格与模型使用的所有已知要素数据一起显示在“评分标签”列中。列 price 是数据集中实际已知的价格。
与 SageMaker 一样,我们希望评估我们的模型表现如何。为此,我们将评估模型模块拖到画布上,并简单地将其连接到得分模型的输出。现在,当我们再次运行这个实验时,我们可以看到平均误差和 R 平方等的统计结果…
在对模型的准确性感到满意之后,Studio 通过一个设置 Web 服务按钮就可以轻松地将模型发布给其他人使用。在我们决定了模型的特征和算法之后,该选项通过消除模型中的数据分割、训练和其他不必要的步骤,将模型从实验转换为预测实验。我们最后一次运行这个模型来检查结果,它已经准备好了一个 API 密匙供其他人在 Azure 上使用。
总结
微软和亚马逊都提供了一个强大的流程和基于 UI 的工具,以加速和简化 Azure Studio 和亚马逊 SageMaker 的机器学习模型开发过程。但是这些工具是为完全不同的用户设计的。
Studio 提供了一个漂亮的拖放界面,带有简单的模块来执行常见的功能,如访问数据、清理数据、评分和测试模型以及部署等…它旨在引导公民数据科学家和初学者完成构建机器学习模型的过程,同时保护他们免受管理云实例、Python 编码和 Jupyter 笔记本的复杂性的影响。
SageMaker 是为开发人员和数据科学家的需求而构建的,他们习惯于在 Jupyter 笔记本上工作,用 Python 编程,并希望获得灵活性和对资源的完全控制。但是 SageMaker 的用户无法避免其他云操作复杂性,如云实例管理——知道要选择的集群大小、位置以及完成工作后关闭集群。除了 Python 编程之外,这些类型的任务会使 SageMaker 成为大多数试图构建模型的业务分析师的不合适的选择。
但是一个产品比另一个产品能产生更精确的模型吗?我不认为模型的准确性会将一个与另一个区分开来,因为这两个产品都允许我们导入任何所需的算法,并且这两个产品都在不同的模型上提供了一些自动化的功能选择。我怀疑一个产品能比另一个产品始终产生更精确的建模结果,这有什么可概括的区别。
真正的区别在用户设计点。SageMaker 面向数据科学家/开发人员,Studio 面向公民数据科学家。但是,Studio 也支持 Jupyter 笔记本界面,这使得数据科学家也可以使用 Studio 和 Azure 机器学习服务的云基础设施来完成 SageMaker 在亚马逊云基础设施上提供的功能。为此,对于更多类型的用户来说,Studio 可能是一个更通用的选择。
关于作者
史蒂夫·迪尔(Steve Dille)是硅谷的产品管理和营销领导者,曾在数据管理、分析、商业智能和大数据领域的公司高管团队中成功完成了 5 次公司收购和 1 次 IPO。最近,他是 SparkPost 的 CMO,在他的帮助下,SparkPost 从一家内部高容量电子邮件发送者转变为领先的预测分析驱动的云电子邮件 API 服务,并从 1300 万美元增长到超过 5000 万美元。他目前正在通过在加州大学伯克利分校攻读信息和数据科学硕士学位,建立数据科学、人工智能和机器学习方面的深厚知识。他过去的学历包括芝加哥大学布斯商学院的 MBA 学位和匹兹堡大学的计算机科学/数学学士学位。他曾在 NCR 担任软件开发人员,在惠普担任产品经理,在赛贝斯(Sybase)担任数据仓库总监,在许多其他初创公司和中型公司担任产品或 CMO 副总裁。
如何定义和执行你的数据和 AI 策略?
迄今为止,许多公司都在投资数据和人工智能(AI)。随着术语的变化,这些活动可能被称为人工智能、高级分析、数据科学或机器学习,但公司的目标是相同的:增加当前业务的收入和效率,并开发新的数据支持产品。众所周知,要在数字经济中保持竞争力,公司的内部流程和产品需要智能——而智能来自数据和人工智能。没有数据和 AI,成功的数字化转型是不可能的。
根据我们的经验,评估一家公司的数据和人工智能成熟度的最佳方式是从关注公司如何利用其数据和分析人员开始。不太成熟的公司会错过某些角色,例如,他们可能有数据科学家,但没有数据工程师,这意味着数据环境没有正确地产品化。或者数据和分析专家分散在整个组织中,但没有以系统的方式表明招聘决策是由个别有远见的业务领导做出的,而不是与公司范围的战略保持一致。
在过去的三年里,我们公司 DAIN 工作室参与了芬兰、德国、奥地利、瑞士和荷兰不同公司和行业的 40 多个数据和人工智能项目。我们的客户通常是大型上市公司。在我们的工作中,我们定义了数据和人工智能战略,评估了人工智能执行项目,并就数据治理、组织和运营模式等主题向公司提供建议。我们还建立了云基础设施,设计了数据,并开发了可扩展的机器学习模型。我们已经就如何成为数据驱动和使用人工智能为他们带来好处向数十位商业领袖提供了建议。这篇文章回顾了我们的一些发现,并提出了前进的最佳实践。
当我们在 2016 年初成立我们的公司时,人工智能一词刚刚从 20 世纪 60 年代开始复活。在 2016 年之前,很酷的术语是“大数据”(现在听起来已经无可救药地过时了),在此之前是“高级分析”和“数据科学”(仍在使用!).虽然许多数字化本土公司在 2016 年的业务中应用了先进的数据和人工智能方法,但许多老牌公司却没有。数字化以及由此产生的对数据和人工智能的需求扰乱了许多老牌公司的商业模式,令它们措手不及。面临来自数字原生公司竞争的行业,如媒体和零售业,不得不转变自己,快速采用数据利用。相比之下,许多制造企业仅处于数字化和数据转型的初级阶段。
由于数据和人工智能意识的增加,许多老牌公司已经开始了有针对性的数据和人工智能计划,并对扭转业务和吸引明星人才抱有很大期望。然而,项目进行了几年后,许多人表现出疲惫的迹象,并且没有满足高级经理和领导对进度不满意的期望。已经在选定的领域进行了试点,甚至可能已经推出了支持数据的产品,但预期的大规模业务转型尚未发生。数据和 AI 仍然是小众活动,而不是商业的前提。在某些情况下,人们会私下谈论“不能透露名字的项目”结果,管理层变得越来越不耐烦,不知道如何摆脱常规。
现实是没有捷径可走。亚马逊、谷歌、苹果和脸书都使用了非常不同的商业策略来获得他们目前的市场主导地位和全球影响力,但他们的共同成功可以说是他们对数据价值的理解和早期定位的远见。他们由内而外地工作,不断强调能力建设,同时在内部开发、测试和部署顶级技术,以便为客户提供最佳产品。对于老牌的非数字公司来说,道路更加崎岖。旧公司已经建立了工作方式,数字不成熟的人,和遗留的基础设施。克服这些问题需要公司领导层坚定的决心和毅力。这意味着将数据和人工智能纳入决策制定的所有方面的核心——从战略到运营,并得到与数据驱动的决策制定相一致的关键绩效指标的支持。这种行动通常表现为在领导层会议的议程上关注数据和人工智能能力发展——从董事会到首席执行官,再到高级经理。这通常是高瞻远瞩的人力资源经理的议程,他们明白数字人才对公司至关重要。
根据我们的经验,商业领袖需要高度参与数据和人工智能战略执行的所有方面,以及支持计划所涉及的能力。我们发现,全身心投入的领导力是成功实现数字化转型和成为数据驱动型公司的共同特征之一。
有时,领导层理解成为数据和人工智能驱动的重要性,但觉得自己对主题的知识不足。这是一个好迹象。许多大学和咨询公司为商业领袖提供数据和人工智能培训。一个有效的方法是定制一个数据和人工智能研讨会,作为领导力战略日的一部分。一句警告的话:有时商业领袖错误地将注意力集中在统计学、计算机科学和编码上,以此来增强他们对人工智能的理解。虽然编码对于数据科学家和数据工程师来说是一项关键技能,但商业领袖最好将精力放在为数据和人工智能创造有效的公司环境上。这意味着设定业务目标,雇用合适的人,教育员工,承诺投资,并为数据和人工智能实施有效的运营模式和组织。最好的方法是为组织设定明确的目标和激励,并遵循这些目标和激励。
在下一节中,我们将深入探讨在定义和执行数据和人工智能策略时应该考虑的主题。
1.设定数据和人工智能愿景
数据和 AI 策略成功的前提是知道自己的商业目标。你有哪些必胜的战役?未来需要在哪些方面取得成功?显然,访问数据将有助于定义业务优先级,但重要的是要记住,数据和人工智能不会解决你在商业模式、产品和服务方面的问题。数据和人工智能将帮助你做出更明智的决策,更快地获取信息,自动化流程,并比人脑更快地交付产品——但它不会构建或取代商业愿景和想法的缺乏。
AI 优先级源自业务优先级。由于数据和人工智能将在不同的领域做出不同的贡献,因此在评估公司的数据和人工智能工作的重点时,应该考虑每个业务领域的业务案例以及人工智能对案例的相对重要性。
例如,在销售和营销中使用数据和人工智能通常会很快产生结果,而在产品开发中使用它们需要较长时间,但最终会产生巨大而有影响力的结果。通常从流程优化案例开始是有意义的。效率提高 1%或避免停机可能意味着节省数百万欧元。计算成本节约案例的业务案例比计算新业务的业务案例更容易。早期成功对于沟通以获得组织的认同以及增加对已展示的人工智能优势的总体理解非常重要。
获得对数据和人工智能愿景的支持和认同同样重要。这样做的传统方法是为数据和人工智能建立一个业务案例,显示计划投资的基线内部回报率(IRR)(当前状态),并将其与数据和人工智能投资的 IRR(未来状态)进行比较。沿着这些路线制定战略是理解大局的一个很好的练习,然而,需要记住的是,对于许多数字产品、服务和企业来说,“不做数据和人工智能”的选择是不可行的。如果没有数据和人工智能,谷歌会是谷歌吗?
数据和人工智能利用的自然起点是当前业务流程的优化:业务模型、产品、服务、内部流程和功能(如营销、人力资源)。一旦你对帮助你当前业务的数据和人工智能用例有了坚实的理解,也应该调查新的数据驱动的商业机会。这些包括数据货币化(例如,出售数据)和数据合作伙伴关系(通过汇集来自多个组织的数据来创建新产品)。这两个话题都不容易,但其中的机会值得研究。
2.数据资产管理/数据治理
高质量数据的可用性是成功的产品化人工智能的基础。如果数据是根据欧盟地平线 2020 计划(2016)建议的公平原则(可发现—可访问—可互操作—可重用)构建的,则可以称为资产。以不同格式和本体驻留在不同系统中的数据,缺少关键属性(如唯一标识符),不是资产。如果数据资产不可重用,每一项数据科学/人工智能活动都将是一项独立的、可能是大型的 IT 工作。“一次构建,多次使用”的原则是实现数据资产价值最大化的关键。例如,对于在线服务的个性化,您可能希望使用来自在线和移动渠道的行为数据、CRM 数据以及消费者在线和离线交易,而不仅仅是来自在线服务本身的数据。产品化数据资产的目标是支持所有用例。
构建公司的数据资产时,从优先业务机会/用例所需的数据开始。这听起来不言自明,但在许多公司中,设计数据的 IT 团队和业务职能之间存在组织上的脱节。在最坏的情况下,数据工程团队忙于构建一个数据资产,将各种数据源集成到一个公共的数据环境中,但是这些不是业务需要的数据源。结果,双方都以沮丧告终。
开始构建数据资产的一个好的实用方法是评估当前数据的“公平”程度。这一过程被称为数据尽职调查或数据清点。数据尽职调查回答如下问题:存在哪些数据?它在哪里?如何访问它?它的质量如何?能和其他数据联系起来吗?它的恢复需要多少努力?,我们是否遗漏了一些明显的数据源(考虑用例)?一旦确定了数据资产的当前状态,就可以制定其开发的路线图。
3.解决方案架构和技术
解决方案架构和技术指的是数据资产的技术方面。除了数字原生公司,现有的公司通常有大量的遗留基础设施。定义业务和人工智能愿景以及数据尽职调查后的首要任务之一是让一位经验丰富的数据和解决方案架构师对当前的技术架构进行批判性研究,并定义目标架构及其开发路线图。这个任务也应该遵循端到端用例逻辑,用于从操作系统(例如 CRM、ERP)、数据仓库、云环境、分析环境和业务接口系统收集数据。传统上,来自 BI 世界的许多数据解决方案架构停留在数据仓库级别解决报告用例。然而,自动机器学习/人工智能解决方案需要链接回运营系统,这意味着运营系统需要成为数据和解决方案架构的一个组成部分。例如,要将您的消费者数据资产(包括单个微细分、次佳报价和其他消费者评分)实时用作现代全渠道营销自动化系统的一部分,您需要建立端到端架构。有时营销部门监管营销技术,而它负责后端系统。这可能导致营销只使用营销数据(例如在线、电子邮件),而丢弃许多其他有趣的数据源,因为他们没有意识到它们的存在。在最糟糕的情况下,应该创建公司范围内的 ML/AI 算法的数据科学团队不参与任何活动。
管理从传统 IT 系统到数字世界的过渡通常是一个漫长的过程。虽然自动化和人工智能最终会降低成本,但在过渡期间,随着新旧解决方案并存,成本可能会增加。此外,一个典型的 IT 部门的预算与当前系统的操作和维护紧密相关,而开发预算却不多。新的技术解决方案需要新的投资。
4.数据保护和隐私
数据保护和隐私是消费者和那些有权访问消费者数据的人最关心的问题。数据保护涉及数据收集、处理和利用。根据欧盟通用数据保护条例(GDPR ),必须定义数据处理的合法权益,并告知用户其数据的收集、处理和组合。必须为用户提供退出和拒绝数据处理的机制。必须定义不同数据处理系统之间数据流的用户标识级别。
当使用数据并确保遵守隐私立法时,根据人工智能用例的期望状态而不是当前用例来编写隐私策略是至关重要的。重点是避免这样一种情况,即当你想开发超目标、个性化的人工智能模型时,你的隐私政策允许你仅出于报告目的使用你的数据。
建立公司范围隐私政策的良好团队由企业所有者、隐私律师和人工智能策略师(或数据科学家)组成。具有技术背景的人工智能策略师将帮助将业务用例转化为数据和人工智能需求,并与隐私律师讨论不同选项的解释(包括用户体验)。
5.人类技能
数据和人工智能之旅需要组织中的新角色。虽然确切的角色术语各不相同,但四个不同级别的业务流程都需要数据和人工智能角色:
1)业务单位(损益)和业务职能(如销售、营销、财务)
2)数据科学(和商业智能)
3)数据资产管理
4)数据平台和技术解决方案
业务用例来自业务层面(#1)。除了实际的业务人员,人工智能战略家的角色也在这里。人工智能战略家将业务愿景和目标转化为数据和人工智能需求,监督项目执行,并确保项目成果被业务流程所利用。大多数公司没有这个角色,但我们认为它是成功执行数据和人工智能项目的最关键角色之一。如果没有人工智能策略师,具有商业/工程背景的人和数据科学家之间的沟通距离往往太远,可能需要一些时间来调整。人工智能战略家的良好背景是希望将自己发展成为商业和管理人才的高级数据科学家。随着时间的推移,人工智能战略家将开发人工智能产品所有权任务的责任。
一些咨询公司以“分析翻译”的形式呈现这一角色,尽管这与我们的定义相似,但我们强调人工智能战略家作为业务影响驱动者的角色。
除了人工智能战略家,商业领袖本身也需要了解数据和人工智能的机会,以便推动主题向前发展,并将人工智能成果融入各自的业务流程。
虽然大多数公司缺乏人工智能策略师的角色,但许多公司已经聘请了数据科学家(#2)。数据科学家以各种形式出现,有着不同的背景。作为教育背景,许多人学习了定量方法,如计算机科学、数学、统计学、物理学或工程学。拥有不同类型教育背景的数据科学团队是有意义的。例如,具有统计学或计量经济学背景的人擅长统计推断,而具有计算机科学背景的人精通机器学习技术和编码。物理学家被训练来处理物理现象和模型,并跳出框框思考。有时精通数据的社会学家、心理学家或生物学家可以给团队带来不同的观点。
由于机器学习/人工智能是一个新领域,因此对有经验的数据科学家有很大的需求。我们建议招聘一名高级数据科学家或人工智能策略师作为第一批雇员,让他们建立一个由经验丰富的人和有前途的年轻人才组成的平衡团队。
一个常见的错误是只雇用数据科学家,而不填补技术角色,如数据工程师和数据架构师(#3)或平台工程师和解决方案架构师(#4)。这导致了数据科学家的高度沮丧,因为他们必须从源系统中检索数据并自己构建数据库。在实践中,这通常意味着数据资产和数据基础设施将无法正确构建。数据科学团队将进行试点并构建单点解决方案,但可扩展的数据基础将遥不可及。数据科学家接受的培训是建立机器学习模型,而不是进行提取、转换和加载(ETL)、数据库和云解决方案。随着试点规模的扩大,这种挫败感将蔓延到管理层。
现在很多人自称数据科学家或者数据工程师。可能很难区分走路和说话。除了查看该领域潜在招聘者的教育和过去的工作经验,我们建议在招聘中使用评估测试。根据手头的角色,它可以被定义为强调工作的各个方面。在我们自己的招聘过程中,我们使用评估测试,这比面试更能揭示候选人的更多信息。你可以用一种有趣和富有挑战性的方式来定义评估,这样候选人就会喜欢并乐于这样做。
一个好的开始是聘请一位在商业、数据、数据科学和技术方面有经验的首席数据和人工智能官来雇用人才并建立团队。除了主题专业知识之外,此人还应该具备出色的领导能力和沟通技巧,因为他们需要与组织中不同层次的人进行有效沟通。
6.数据和人工智能组织
最佳的数据和人工智能组织结构取决于整体公司规模和组织、文化、人工智能成熟度水平以及数据/人工智能任务的类型。
一般来说,要让事情进展顺利,建立卓越中心(CoE)会将注意力集中到这个主题上。根据 CoE 在公司中的位置,它将负责不同的领域。CoE 可能仅由数据科学和 BI 团队组成,而技术团队(数据工程、平台)驻留在其中。或者,CoE 可以负责技术方面,而数据科学家则在业务部门工作。需要仔细研究最佳设置。根据我们的经验,大多数公司将受益于通用的技术基础设施和数据资产,以及某种类型的集中式数据科学团队,这可以解决最困难的用例,并创建可扩展的人工智能产品组合,供所有业务部门和功能使用。
人工智能策略师应该最佳地坐在业务单元中,以推动人工智能用例向前发展,但在开始时,他们也可以驻留在数据科学团队中,并从那里帮助业务。
在一个成熟的数据/人工智能驱动的公司中,随着整个公司在日常业务中使用数据,CoE 的作用将变得越来越小。在成熟阶段,CoE 将继续关注常见的数据治理主题,如数据质量和完整性、技术系统、本体和标准。
有时,为了让开始变得容易,引入一个公司范围的人工智能计划来推动数据和人工智能议程是有意义的——前提是该计划存在 2-3 年,然后将被解散。一个项目的好处是,你不需要在早期阶段做出直线组织的决策,但是随着时间的推移,你会了解什么类型的团队结构适合你的组织。
7.运营模式
与数据和 AI 组织密切相关的一个话题是不同业务部门之间的运营模式。优先的业务用例应该驱动数据和人工智能的发展。为了让数据专家在最重要的用例上工作,企业领导人应该建立一个人工智能指导小组,或者将数据和人工智能开发纳入现有的领导团队会议。CoE 负责人应该推动会议议程。除了一个跨单元的指导小组,单独的用例领域应该有他们自己的,可操作的指导小组。
对于 CoE 的第一年,数据和 AI 开发预算应该集中。预算推动优先化,如果没有集中的预算,数据和人工智能活动将无法扩大规模。单个业务单位不希望承担公司范围内的能力建设(例如,通用数据模型、基础设施、API)的成本,即使这对整个公司来说是最佳的。这意味着人工智能解决方案往往会成为独立的、不相连的孤岛。此外,如果没有一个共同的路线图、优先顺序和明确的治理,贡献最大的业务将要求他们获得资源,即使资源在战略上可以更好地用于其他领域。
重要的是要记住,这不仅仅与数据专家有关。业务流程和业务人员从根本上受到数据和人工智能利用的影响,例如,在营销中,为了推动基于触发的个性化营销,数据和目标模型需要可用,但营销内容制作、客户处理模型、渠道策略、前端系统等也是如此。与传统营销相比,持续、数据驱动的营销需要营销人员具备不同的技能和能力。流程自动化也是如此:如果数据科学家构建了一个预测性的服务维护模型,那么只有当服务车队和技术系统能够对预测做出及时的干预时,才能获得业务影响。
增加业务影响的一个聪明方法是给数据/人工智能项目中的每个人相同的激励。例如,如果目标是通过人工智能驱动的目标定位将营销活动提升 20%,那么这个目标应该交给营销人员、数据科学家和数据工程师。这可能会招致一些反对,但最终会给公司带来最好的结果。
8.数据科学和 ML/AI 算法
像数据资产一样,算法也可以被视为算法资产。这意味着,随着时间的推移,机器学习/人工智能算法的组合将变得公平。每一个新的分析建模练习都不需要从头开始,而是建立在经过测试的代码之上。随着时间的推移,这将使数据科学团队更加高效。像软件编码团队一样,它要求数据科学团队使用通用的代码库和标准。
为数据和算法资产建立维护流程也很重要。如果维护过程仍然没有部署,开发团队仍然处于停滞状态,因为他们的努力是为了保持生产中的当前资产。通过对数据和算法组合应用维护过程,可以发现和开发新的解决方案。
最后的话
总而言之,成功执行数据和人工智能需要以下步骤:
1.根据您的业务优先级,制定您的数据和人工智能用例;
2.了解您的数据和人工智能项目及促成因素的当前状态;
3.定义您的数据和人工智能愿景以及执行路线图,包括投资;
4.执行旨在生产就绪的第一个用例;
5.扩大运营规模。
有时人们会认为,AI 驱动的公司的最高水平是当所有的决策和业务流程都由自动化算法完成时。然而,这是一种误解。自动化和人工智能不会自己做出明智的商业决策。AI 成熟度的最高水平是当整个公司走向一个方向,筒仓被解散,数据和 AI 被每个人作为日常业务的一部分使用。一切能自动化的都将自动化,人类需要确保自动化以智能的方式完成。
如何定义公平性以检测和防止机器学习中的歧视性结果
为了检测机器学习预测中的歧视性结果,我们需要比较我们的模型如何对待不同的用户群。
这可以通过在我们的模型中定义一个描述公平概念的度量来实现。例如,在看大学录取时,我们可以比较男女的录取率。这相当于使用人口统计上的均等作为公平的数学定义。它指出,在理想世界中,获得积极结果(例如:被大学录取)的群体之间的差异应该为零。然而,这很少发生,这就是为什么我们需要跟踪差距。
人口均等是我们可以用来描述数学公平的定义之一。在本帖中,我们将回顾分类模型中最常见的三个定义。选择正确的公平类型非常重要;否则,错误的指标会导致有害的决策,我们将对此进行探讨。
从示例开始
在这篇文章中,我将用一个信用模型的例子来解释数学公平的主要定义。我们将研究何时以及如何使用它们是有意义的。
我们将使用的历史数据可以描述如下:
- *已还贷款:*全额还贷款者。
- *违约:*无力偿还贷款而违约的人。
Figure 1: example of a classification credit model
让我们假设我们正在建立一个纯粹基于“收入”的信用模型。我们的模型旨在了解那些能够全额偿还贷款的人的典型收入,并将他们与那些倾向于违约的人区分开来。
这意味着我们只需要在我们的训练集中设置一个收入阈值,以决定未来谁可以获得贷款(这是图 1 中的虚线)。那些超过阈值的人将获得贷款(正面预测)。门槛以下的人是得不到贷款的人(负面预测)。
数学公平的第一个例子:人口均等
人口统计均等表明,受保护阶层(如性别)的每个部分的比例应平等地获得积极成果。积极的结果是首选的决定,如“上大学”、“获得贷款”或“看到广告”。如前所述,理想情况下差值应该为零,但通常情况下并非如此。
让我们假设我们正在建立一个完全基于“收入”的信用模型(见图 2)。我们可以决定对每个组使用不同的需求水平,这样 A 组获得贷款的人的百分比就等于 b 组获得贷款的人的百分比。
数学定义
在数学术语中,人口统计均等要求结果独立于受保护的 A 类:
Equation 1: Probability of getting an outcome is independent of A
关于混淆矩阵,我们要求正率(PR)对于保护类的每个段都是相同的。
正比率(A=0) =正比率(A=1)
在实践中,我们可能不要求正利率的差异等于零,但我们的目标是将这一差距最小化。
什么会出错?
假设我们想要创建一个舞蹈团体。我们正试图从一群专业舞者、流行歌手和一些演员中挑选我们的舞蹈团队。历史上的刻板印象告诉我们,舞蹈演员和流行歌手将非常适合这份工作。然而,我们几乎可以肯定演员们可能不会。
假设我们得到了上面 GIF 中的结果,职业舞者和流行歌手在这种情况下会被认为是天生的高手。憨豆先生糟糕的舞蹈表演确实会加强我对演员不擅长舞蹈的偏见。
当决定做出时,演员们还没有像专业舞者和流行歌手一样有机会学习舞蹈。如果我们立即要求人口统计均等,这可能导致促进历史偏见。
现在来看一个更严肃的例子。比方说,我们希望让更多女性加入由典型的“男生俱乐部”组成的董事会。这可能不是最欢迎女性的环境。我们需要有一个适当的计划,以便环境是包容性的,新的少数群体得到正确的支持。否则,我们有强化历史偏见的风险。
何时使用人口统计均等
在以下情况下,我们应该使用人口统计均等作为公平的定义:
- 我们希望改变我们当前世界的状态,以改善它 (例如:我们希望看到更多的少数群体获得成功)
- 我们意识到历史偏见可能影响了我们数据的质量 (例如:ML solution 被培训来雇佣软件工程师,而以前几乎没有女性被雇佣)
- 我们制定了一个计划来支持无特权群体和**,以防止历史偏见** (例如:制定惩罚董事会非包容性行为的政策)
大学录取倾向于实现人口均等。一个很好的例子是牛津大学通过招收更多来自弱势背景的学生来提高多样性。在这种情况下,学生有很高的学术潜力,但他们的教育可能已经中断,或者他们必须克服个人的劣势。这一组的学生在开始他们的学位课程之前将得到额外的支持,延伸到一个完整的基础学年。
数学公平的第二个例子:机会均等
Figure 3: use of different income thresholds to achieve Equal Opportunity
平等机会是指每个群体都应该以平等的比率获得积极的结果,假设这个群体中的人有资格获得积极的结果。
如果我们看一下图 3 中的例子,我们可以看到准确预测的阳性百分比在两组中都是 50%。
如果我们仔细想想,这就像是在说:
假设你会跳舞,你可以成为我们舞蹈队的一员。
数学定义
机会均等要求积极结果独立于受保护的 A 类,条件是 Y 实际上是积极的:
Equation 2: Probability of getting a positive outcome is independent of A, conditional on Y being an actual positive
基于混淆矩阵,我们要求受保护类的每个片段的真实肯定率(TPR)相同。
真阳性率(A=0) =真阳性率(A=1)
在实践中,我们可能不要求实际正利率之差等于零,但我们的目标是将差距最小化。
什么会出错?
Figure 4: many False Positives are introduced in Group B to be able to achieve Equal Opportunity
如果我们看一下图 4,我们可以看到两个组的真实阳性率(TRP)是相同的,这是机会均等所要求的。
但是,如果我们关注 B 组,我们可以注意到引入了许多假阳性。在这种情况下,误报是指那些在实际上可能违约的情况下获得贷款的人。这意味着我们将在 B 组中更大范围地损害信用评分,这将导致完全不同的影响。
何时使用平等机会
在以下情况下,我们应该使用平等机会作为公平的定义:
- 非常强调正确预测积极结果 (例如:我们需要非常擅长检测欺诈交易)
- 引入误报对用户和公司来说都不昂贵 (例如:错误地通知客户欺诈活动对客户和发送警报的银行来说都不一定昂贵)
- 目标变量是不被认为是主观的 (例如:给谁贴上“好”员工的标签会引起偏见,因此非常主观)
如上所述,考虑到“误报”形式的错误不会对客户或处理该情况的公司产生代价高昂的负面影响,使用平等机会可能是欺诈检测的合适案例。此外,将交易标记为欺诈应该是一个明确的决定,而不是受到重大偏见的。
数学公平的第三个例子:均等的赔率
Figure 5: use of different income thresholds to achieve equalised odds
数学公平的最终定义是均等赔率,这是我们将在本博客中讨论的最具限制性的概念。
这个概念规定模型应该:
- 正确识别各组之间比率相等的积极结果*(与机会均等相同)*,而且
- 在各组之间以相等的比率误分类阳性结果*(在各组之间产生相同比例的假阳性)*
我们可以在图 5 中看到这样一个例子,其中我们以 50%的正确率识别出两组的阳性结果,但两组的假阳性比例相同,均为 25%。
数学定义
均等赔率要求正结果独立于受保护的 A 类,以实际 Y:
Equation 3: Probability of getting a positive outcome is independent of A, conditional on Y
基于混淆矩阵,我们要求保护类的每个片段的真阳性率(TPR)和假阳性率(FPR)相同。
真阳性率(A=0) =真阳性率(A=1) 和
假阳性率(A=0) =假阳性率(A=1)
在实践中,我们可能不要求真阳性率和假阳性率之差等于零,但我们将致力于使这两个差距最小化。
什么会出错?
Figure 6: The False Positive Rate (bar chart, left y-axis) is minimised when enforcing Equalised Odds at the expense of lower profits (line chart, right axis)
鉴于这是最具限制性的定义,试图为每个群体实现平等的 TPR 和 FPR 可能会导致利润下降。这是因为模型性能可能会因无法优化多数群体的准确性而受到影响。
图 6 是实施均等赔率时可能发生的情况的一个例子。我建立了一个信贷模型来确定谁应该获得贷款,并分析了 40 岁以上和 40 岁以下人群的公平定义。在这种情况下,与其他公平定义相比,利润在均等赔率期间受到严重惩罚。
对于这个例子,在建立模型之前,没有做任何工作来检测或减轻偏差,这可能解释了为什么利润如此之低。这也表明了应用偏差缓解技术(如“重新称重”)和对缺失数据进行良好分析的重要性,以便在不损害货币价值的情况下为每个人建立良好的模型。
何时使用均等赔率
在以下情况下,我们应该使用均等赔率作为公平的定义:
- 重点强调正确预测积极结果 (例如:正确识别谁应该获得贷款来推动利润),以及
- 我们非常关心最大限度地减少代价高昂的误报 (例如:减少对无力还款者的贷款发放)
- 目标变量是不被认为是主观的 (例如:标注谁是‘好’员工会导致偏见,因此非常主观)
- 模型的回报功能没有受到严重影响 (例如:业务的收入或利润功能仍然很高)
信用模型是一个很好的例子,用均等的赔率来定义公平。我们通过接受尽可能多的能够全额偿还贷款的客户来创造商业价值。然而,我们也关心最大限度地减少“误报”,即那些获得贷款但无法偿还的人。
误报会损害客户的信用评分,从而影响他们未来的金融机会。这也会给发放贷款的银行带来很高的成本。
同时,将贷款标记为全额支付或违约是一个非主观的决定和清晰的过程。
结论
在这篇博客中,我们学习了可以应用于分类模型的“数学公平”的三个最常见的定义。我们研究了何时使用每个公平指标是有意义的,以及在应用它们时需要考虑什么。
我们必须开始分析我们的模型如何对不同的客户群产生不同的影响。否则,我们就有大规模传播系统性歧视的风险。
如果您对本文有任何反馈或建议,请在下面的评论框中留下👇。
如何与您的数据科学团队一起交付具体的商业价值?
机器学习和深度学习领域的快速发展带来了先进的算法。这些先进的算法能够转变组织,从而获得多重商业价值。组织已经开始投资于数据科学团队,以引领数字化转型之旅,在竞争中脱颖而出。
Image by Gerd Altmann from Pixabay
大多数组织是否都在加快数字化转型的市场速度?
对于许多组织来说,数字化转型是一个非常缓慢而痛苦的过程。根据行业统计,70%到 80%的数据科学项目没有达到预期。
让我们探究为什么…
这一探索为什么数据科学解决方案无法达到预期结果的尝试是基于我自己的个人经历,从其他世界的经历中得到验证,并得到了我的另一半 Arshad 的贡献。我相信会有其他观点,我乐于听取。
在开始之前,让我简单解释一下数据科学
数据科学是一个多学科领域,通过理解数据模式从结构化和非结构化数据中获取相关见解,从而预测未来。数据科学是一门艺术和科学,它使用数学、机器学习、计算机编程、统计建模、数据工程和可视化、模式识别和学习、不确定性建模、数据仓库和云计算。
我们是否了解富达正在努力解决的业务痛点?
大多数数据科学项目都是从高层次的目标开始,没有足够清晰的细节。让我们用一个例子来检验
高层次目标-增加业务部门或特定产品组合的销售额。
- 是否有我们正在努力解决的特定最终用户/业务难题,或者我们正在解决的业务期望是什么?一个企业 可能正在努力理解基于动态市场条件增加产品组合销售的杠杆。
- 预期用途是什么,谁将使用该解决方案,他们将如何使用该解决方案? 品类经理希望做一个假设分析,以了解如果他们增加/减少一个影响因素,会对销售产生多大影响。
- 如何衡量数据科学解决方案的成功? 本季度产品组合的销售预测应该在实际销售额的 15%-20%上下,或者企业是否希望了解趋势,或者他们只是希望了解可以用来更好地管理销售的杠杆。
一旦我们清楚了为什么我们需要数据科学解决方案来解决业务问题,我们就可以开始设计解决方案来解决什么问题和如何解决。
为了让数据科学解决方案取得成功,我们使用了极限协作方法
极端协作:持续协调协作问题定义、解决方案设计,以及与所有利益相关方一起优先考虑具有最高业务价值的业务目标
合作理解并设定现实的期望
业务/终端用户有他们希望数据科学解决方案解决的痛点或期望。即使需求有冲突,我们也需要理解不同利益相关者的期望。这包括最终用户、与问题密切相关的任何人,还包括领导团队。
我们需要使用极端的协作方法来考虑利益相关者的所有需求,如采访不同的利益相关者以获得不同的观点,通过观察他们和举办设计研讨会来了解客户的旅程。这些将在下面用来理解业务需求的工具和技术中详细提及。
有时,利益相关者可能有不切实际的期望。期望需要重新设定,以设定正确的范围和成功标准。所有利益相关方应就范围和成功标准达成一致。在某些情况下,我们可能认为一个小的业务流程变化就能解决问题,而不是一个复杂的数据科学解决方案。因此,这是设定正确方向的非常关键的一步。
基于业务价值协作确定业务目标的优先级
毕竟,利益相关者有共同和明确的期望,优先考虑痛点或期望。这需要所有利益相关者的合作,我称之为极端合作。极度协作是建立在彼此的想法和优势之上,以实现共同的目标或目的。**
在确定了业务目标之后,对具有最大业务价值的难点或期望结果进行优先级排序,业务价值可以根据
- **数字化转型让您的组织更上一层楼。**通过量化上市延迟的成本,可以很好地理解这一点。
- 业务或流程改进。如果流程改进完成了,投资回报会是多少?
- 确保生物的安全。生物安全和可持续生活的环境与商业收益一样重要
在协作确定优先级时,我们还需要考虑以下问题
- 数据充足性挑战: 正确数据的可用性是一项挑战。我们可能没有解决问题所需的所有关键数据元素,或者数据标签可能是问题所在
- 数据质量问题: M 缺失数据、不一致的数据、不兼容的数据格式是大多数非数字化组织的常见问题
- 数据安全: 保护数据免受内部和外部风险。数据敏感性分类不正确可能会成为安全威胁
谁最适合适度的业务期望和业务目标的优先级?
这个练习最好由了解业务的人来完成,他们可以用自己的语言交流,而不会被技术细节所困扰。对数据有很好的理解,对数据科学有详细的了解,能够使用技术语言。在与业务人员交谈时,反映业务术语的用法是关键,同样,向数据科学团队反映数据科学术语的用法有助于弥合差距。
有哪些工具和技术可以用来理解业务需求?
探索客户之旅,了解当前问题以及他们对解决方案的期望。这可以通过以下方式实现
- 采访不同但相关的业务领域。每个小组都有不同的视角,这将有助于构建更大的图景。对于产品组合的销售预测,与销售和营销团队、品类经理、生产团队、财务团队讨论,以构建更大的图景。
- 观察最终用户的行动,如有可能。这将有助于了解他们当前的切入点,也有助于通过了解终端用户使用的数据来设计数据科学解决方案
- 获取利益相关者之外的不同观点:通过在白板上陈述要解决的问题,搅动海洋以获得清晰的观点。让组织中的其他人提出他们的观点。在与所有利益相关者的共同会议中进行讨论后,根据相关性和事实筛选出观点
- 设计或解决方案研讨会用业务用户自己的语言向他们重述痛点和旅程。在这里,我们会仔细考虑所有相互冲突的要求,考虑所有不同的观点,并就数据科学解决方案的期望和商业价值达成一致,该解决方案涉及包括领导团队在内的所有利益相关方
极端协作的优势是多方面的
- 痛点、期望和想法的交流有助于清晰地阐明潜在的问题。
- 每个既是问题的一部分又是解决方案的一部分的人都说同样的语言,并且更好地理解彼此的世界
- 由于假设大大减少,澄清是即时的
- 过度沟通可能会发生,但这比沟通不足和做出错误假设要好
他们是否有与不同利益相关者合作的规则?
- **设定正确的期望:**所有利益相关方应对为什么需要数据科学解决方案以及该解决方案将实现的目标有一个共同的看法
- **减少/消除假设:**小组做出的任何假设都将得到讨论和验证。如果假设无法得到验证,那么就让数据来说明问题。
- **多学科团队的协作:**一个团队的强大取决于它相互协作以及与其他团队为业务目标而工作的能力。致力于数据科学解决方案的不同学科必须协同工作,以减少返工
协作消除了假设,在不同的团队和团队成员之间建立了信任,并创造了一个发挥彼此优势的环境
总是进行小的、增量的、迭代的解决方案开发
通过短时间、快速、迭代的增量周期来获取业务数据洞察,这使得数据科学解决方案变得异常重要。这是一种快速而正确的快速进近
这种方法有两方面的帮助:
- 快速准确的数据和业务知识。
- 理解什么与我们试图解决的问题相关,什么不相关的能力。不是所有的数据都是好的。
快速失败和立即纠正的好处
企业对将要实现的目标有了清晰的了解,对不断变化的市场趋势有了数据洞察。数据工程团队可以更好地了解需要提供给数据科学团队的相关数据,数据科学团队可以构建多个模型,然后决定哪一个模型更适合当前的问题。
成功执行数据科学解决方案的态度
拥抱失败,不断学习
失败是件好事,因为它教会你错过了什么。对于每一次迭代,理解什么对解决方案有效,什么无效。就下一步的改进措施进行头脑风暴讨论。
失败不是致命的,但不承认失败并从中吸取教训绝对是致命的
“成功不是最终的,失败也不是致命的:重要的是继续下去的勇气.”——温斯顿·丘吉尔
持续学习、监控和改进是成功的关键。失败只是成功的垫脚石。
所有利益相关方持续学习数据科学基础知识、数据和模型改进,以达到成功标准。
当设定对数据科学解决方案的期望或成为数据科学解决方案的一部分时 “无知根本不是福”。
了解可以利用数据科学的领域对企业有好处。
同样,对于数据工程、数据科学和数据可视化团队成员来说,拥有扎实的业务理解也非常重要。
数据科学解决方案的所有利益相关方需要理解并使用同一种语言。这确保了团队中的每个人都清楚地相互理解,这对成功非常关键。
总结要点以满足对数据科学解决方案的期望:
- 明确业务期望/痛点。我们为什么选择数据科学解决方案,谁将使用该解决方案,以及如何使用该解决方案。
- 为理解所有利益相关方并为其设定现实的期望而进行的极端协作
- 使用极限协作,根据业务价值确定业务目标的优先级
- 使用工具和技术找出潜在的问题和棘手问题
- 短而快速的迭代增量循环解决问题。一次一步
- 拥抱失败,并通过短时间的反复循环从失败中学习
- 确保所有利益相关者使用相同的易于理解的语言,不使用团队中每个人都不理解的任何技术术语。
- 所有交叉学科之间的交叉教育是强制性的
分享你的想法,评论!!!
参考资料:
当今的企业不断产生大量数据,但这并不总是转化为可操作的数据…
hbr.org](https://hbr.org/2016/12/why-youre-not-getting-value-from-your-data-science) [## Gartner 表示,近一半的首席信息官正计划部署人工智能
据 Gartner 公司称,有意义的人工智能(AI)部署才刚刚开始
www.gartner.com](https://www.gartner.com/en/newsroom/press-releases/2018-02-13-gartner-says-nearly-half-of-cios-are-planning-to-deploy-artificial-intelligence)
如何部署机器学习模型
机器学习
使用 FastAPI+uvicon 创建生产就绪的 API
你在网上看到的任何机器学习文章都在讨论模型的复杂性以及如何正确应用它们。尽管这些文章可能很有趣也很有价值,但只有少数文章考虑了创建模型后会发生什么:
部署 ML 模型需要哪些步骤?
不幸的是,我能找到的大多数文章都讨论了如何使用 Flask 快速创建端点,但是没有意识到 Flask 本身很难用于生产。
从命令行运行 Flask 时,您首先看到的是以下内容:
显然,要使它完全投入生产,还需要做更多的工作和考虑。
部署模型时要考虑的事情
- 扩展您的 API
- 容器化您的 API 环境
- 记录您的 API
- 重新训练您的模型以避免模型漂移
- 记录您的 API 和模型
- 云还是内部部署?
在本文中,我们将一起经历几个步骤,让您的 API 为生产做好准备,无论是在本地还是在云上,重点是文档、日志和伸缩。
我们将使用 FastAPI 代替 Flask。这并不是因为 Flask 有什么问题,而是我相信 FastAPI 可以让你更快地投入生产。
文档结构
你可以在这里从得到所有的数据和文件。对于本指南,请确保您的文档结构如下:
.
├── **app**
│ └── main.py
│ └── sample.log
│ └── **data** │ └── encoder.pickle
│ └── features.pickle
│ └── model.pickle
│
├── **notebooks** │ └── preprocessing.ipynb
│ └── test_connection.ipynb
│ └── data.csv
│
├── requirements.txt
└── Dockerfile
这将有助于防止错误,尤其是在创建 Docker 容器时。
1.准备文件
我们将要部署的模型用于预测人员流动。你可以在这里得到数据。前几行如下所示:
我们首先加载数据并保存我们希望在模型中使用的特征的名称。这有助于跟踪列的顺序。当您指的是薪水时,您不希望意外地输入年龄值。
接下来,由于列 Sales 和 Salary 是分类的,我们将应用并保存一个 hot 编码实例。一键编码将一个列转换为具有 0 或 1 的 n 列,其中 n 等于唯一类别的数量。我这样做是因为它在部署您的模型时显示了一些额外的复杂性。
最后,我使用现成的 LightGBM 分类器来预测营业额。该模型被保存,以便可以在我们的 API 中使用。
Preprocessing the data and creating the model
在我们准备好数据并保存了所有必要的文件之后,是时候开始创建 API 来服务我们的模型了。
注意:保存模型有几种方法,每种方法都有自己的优缺点。除了酸洗,你还可以使用 Joblib 或者使用 LightGBM 的内部程序。
2.生产就绪 API
生产通常意味着终端用户可以访问的 API 形式的端点。对于 python 来说,有很多选择,比如烧瓶、猎鹰、小星星、 Sanic 、 FastAPI 、龙卷风等。
FastApi
出于三个原因,我们将在本文中使用 FastApi:
- 像 Flask 一样,您可以用最小代码设置一个端点
- 它是难以置信的快,它的速度与 NodeJS 和 Go 不相上下
- 它自动创建open API(Swagger)和 ReDoc 文档
然而,这是个人经验,幸运的是,您可以很容易地将 FastApi 换成其他东西。
紫玉米
我们用 Uvicorn 来服务我们的 FastAPI 服务器。与更传统的 WSGI 服务器相比,Uvicorn 是允许异步进程的 ASGI 服务器。这将加快应用程序的速度,并使您更接近生产性能。
美国石油学会
首先,我们需要安装 FastAPI 和 Uvicorn:
pip install fastapi
pip install uvicorn
安装完必要的包后,我们可以开始创建主文件。在这个文件中,我们确保加载了之前保存的所有必要文件。
然后,我们创建一个名为Data
的类,它定义了模型中使用的所有变量。这有助于跟踪我们使用的变量,而且还基于我们创建的类创建文档。
最后,我们创建了预测方法。在这种情况下,数据被提取出来并按正确的顺序排列。像我们之前所做的那样,应用了一键编码。然后,预测以 0 或 1 的形式返回。
main.py
现在我们已经安排好了一切,我们可以从您的控制台使用以下命令加载服务器:
uvicorn main:app
main
是指文件的名称(main.py ),而app
是指 main.py 中 FastApi 实例的名称。如果一切正常,您可以看到服务器运行在 http://127.0.0.1:8000 。
要测试它是否返回预测,您可以运行以下代码:
还可以用 Postman 测试 API,这是一个很棒的 API 开发工具。
虽然从技术上讲,您的 API 现在可以用于生产,但是包含文档、记录 API 中发生的事情以及将您的解决方案容器化将会很有帮助。
3.证明文件
很有可能您不是在现有服务中实现 API 的人。如果您记录了端点,以便可以毫无困难地使用它,那就更好了。幸运的是,FastApi 会基于我们之前创建的Data
类自动创建文档。
FastApi 有自动文档内置的方法:OpenApi (Swagger)和 ReDoc。
OpenApi
启动 FastAPI 服务器后,您可以访问http://127 . 0 . 0 . 1:8000/docs查看自动生成的服务器文档。你甚至可以按“试试看”来看看服务器是否如预期的那样工作。
雷多克
像 OpenAPI/Swagger 一样,ReDoc 生成参考文档。它通过允许您创建一个高度可定制的基于 react 的模板来扩展它们。FastAPI 在http://127 . 0 . 0 . 1:8000/redoc自动创建文档。
注:如果你想看 ReDoc 的大范围现场版,可以去看看http://redocly.github.io/redoc/。
4.记录
我见过许多人使用print()
语句来跟踪他们代码内部发生的事情。这对小型应用程序来说没问题,但是当您在开发、测试、验收、**、**和生产 (DTAP)之间切换时,您可能不想显示相同的消息。
这就是日志的用武之地。它允许您为应用程序设置特定的日志记录级别,并且只在超出该级别时显示消息。
我们的 API 将受益于日志,主要有两个原因:
- 我们可以跟踪 API 是否还在工作,以及它遇到了哪些问题
- 我们可以跟踪模型的输入并检查其性能
如果我们保留所有输入数据以便进一步分析,这将非常有趣。这将为我们提供以前从未见过的数据信息,并可能改进模型。
日志记录级别
有些错误可能不如其他错误有趣。在生产中,您可能希望显示致命错误,而不是应用程序的进度信息。当您调试应用程序时,这可能会有所不同。
为了解决这个问题,我们可以使用日志记录的级:
**DEBUG**
—调试应用程序时有用的信息。值= 10**INFO**
—申请进度信息。值= 20**WARNING**
—关于潜在有害情况的信息。值= 30**ERROR**
—关于非致命错误的信息。值= 40**CRITICAL**
—关于严重和致命错误的信息。值= 50
如果我们将记录器设置在**WARNING**
级别,那么将只显示**WARNING**
、**ERROR**
和**CRITICAL**
。
本地记录器
为了在本地使用记录器,我们初始化记录器并设置其最低级别:
import loggingapp = FastAPI()# Initialize logging
my_logger = logging.getLogger()
my_logger.setLevel(logging.DEBUG)
最低级别现在设置在**DEBUG**
,这意味着基本上所有级别的记录都会显示。当你将你的模型投入生产时,我建议你将它设置为**WARNING**
。
要使用记录器,只需调用它并指定日志记录的级别。该消息将被打印到控制台:
my_logger.error("Something went wrong!")
现在,你可能想要保存日志到一个文件。为此,只需用此语句代替上面的setLevel
:
logging.basicConfig(level=logging.INFO, file='sample.log')
5.使用 Docker
既然我们已经有了要部署的 API,我们可能希望使用 Docker 将应用程序容器化。Docker 将您的应用程序及其所有依赖项打包,以确保它在任何环境下都能无缝工作。这使得跨环境部署应用程序变得更加容易,而不需要太多额外的集成步骤。
首先确保你已经安装了 Docker 。因为我们希望有一个跨环境的稳定的应用程序,所以为应用程序指定一个requirements.txt
是很重要的。
下一步是创建 Dockerfile 本身,它是运行我们的 API 的一个包含版本所需要的。幸运的是,FastAPI 的开发人员已经创建了 python 映像,允许在适当的环境中运行 FastAPI:
Dockerfile
将上面的代码保存在 docker 文件中,导航到该文件夹并运行以下命令:
docker build -t myimage ./
docker run -d --name mycontainer -p 80:80 myimage
这将构建并运行我们在 Dockerfile 文件中指定的映像。
您的 API 现在已经准备好了,可以从 http://127.0.0.1/docs 访问。
结论
在这个(有点)全面的指南中,我们已经经历了为您的模型创建 API 和将应用程序容器化的 5 个步骤。现在,您可以选择在本地托管它,或者通过云解决方案(如 AWS 或 Azure)部署 Docker。
请注意,我试图尽可能全面地阐述这一点,同时包括我认为重要的主题。但是,一些更高级的主题被排除在外,例如:
- 处理概念漂移
- 保护您的 API
- 配置 Gunicorn 服务器
- 为不同阶段创建单独的 docker 文件(DTAP)
- 使用 CI/CD 自动重新训练您的模型
- 使用 Kubeflow 和 Kubernetes 简化生产
- 等等。
所有的代码都可以在这里找到:
关于创建一个生产就绪的 API 来为您的 ML 模型服务的指南。
github.com](https://github.com/MaartenGr/ML-API)
感谢您的阅读!
如果你像我一样,对人工智能、数据科学或心理学充满热情,请随时在 LinkedIn 上添加我,或者在 Twitter 上关注我。
如何从贝鲁特部署神经网络
Photo by Zheka Boychenko on Unsplash
贝鲁特是黎巴嫩华丽的首都,也伴随着繁华都市的典型问题。除此之外,它还遭受着频繁的停电和世界上最慢的互联网连接之一。
这里也是我度过暑假的地方,也是本文的理想试验场:如何用亚马逊的 SageMaker 和 PyTorch 以 web 应用的形式部署神经网络。
在继续之前,建议将存储库克隆到 SageMaker 中,以遵循这个漫长的过程。整个项目从开始到结束都托管在这个 GitHub 库中。
下载数据
对于这个任务,我们将使用 Maas 等人的 IMDb 数据集,它包含 25,000 条用于训练的高度极性电影评论,以及 25,000 条用于测试的评论。我们创建一个目录并下载数据:
加工和清洁
Photo by Pablo Lancaster Jones on Unsplash
下载完数据后,我们需要将其转换成可读的格式。下面的 read_ibmd_data 函数读入每个评论,并将它们组合成一个单一的输入结构。
然后,我们将正面和负面的评论结合起来,并使用 prepare_imdb_data 函数对结果记录进行洗牌。
在继续之前,让我们检查一下我们做得怎么样。下面的评论值为 1,表示它是正面的。
Contains *spoilers* - also, my quotes may not be exact.<br /><br />Everyone always notes the satire in social commentary and economic parallels - how true. But to me, I see this movie as much more than that. I love the symbolism of this guy in a glowing white suit. There is so much confusion and filth in the world around him, but it won't stick. Alec Guiness was the perfect guy to play this - his boyish grins and eternal curiousity are so appropriate:<br /><br />"That's ingenious - can you tell me, what is the ratio of ink to petrol?"<br /><br />The only moment of defeat is when he realizes that his invention hasn't worked after all - standing there almost naked. Yet, more than shame is the simple disappointment that "it didn't work." He's never really intimidated by people. Remember,<br /><br />"But Sidney, we want to stop it too."<br /><br />Barely a moments hesitation before he's off trying to get away again. Does he show any sign of the pain such a betrayal must've caused? No.<br /><br />Also notable is Dapne's role. She is sick and tired of money and power. She thinks she's finally found love, outside of her father's company. At first she doesn't really care about Sidney anymore than anyone else. But that moment when he falls off her car and she goes back to see if maybe she killed him - and yet he is still thinking only of the beauty of his invention. She's finally found something she thinks is worth living for. The funny thing is that it's not even romance. It is friendship, but of such an ephemeral nature that the title almost doesn't fit. It's more admiration, and perhaps even inspiration.<br /><br />Upon her discovery that Michael has no real love for her, and that her father is completely incompetent to take care of her, she gives into cynicism and tries to temp Sidney. Fortunately she finds that there really are people in this world living for more than power, money and lust. What a refreshment:<br /><br />"Thank you Sidney. If you would've said 'yes' I think I'd have strangled you."<br /><br />I love the very end, when all of this crazy business seems to have come to nothing. But then, the bubbly, quirky beat starts up and Sidney goes off, his stride matching the tune: dauntless. Where is Daphne? We don't really know - but they weren't really in love and she wasn't really a scientist. He got help escaping and she got "a shot in the arm of hope." (Pollyanna) A cont'd relationship would've been nice, but as Billy Joel says "it's more than I'd hoped for..."<br /><br />
巧合的是,这是一篇很长的评论,但是略读就能看出它是积极的。它带有许多 html 标签,我们将删除这些标签,因为它们没有增加情感价值。我们还想对我们的输入进行标记,以便在进行情感分析时,像娱乐和娱乐这样的词被认为是相同的。
review_to_words 助手函数就是这样做的,它依赖于 NLTK 库。
我们在下面的预处理 _ 数据函数中使用审查 _ 到 _ 单词。它读入数据并缓存结果。这是因为执行该处理步骤可能需要很长时间。这样,如果我们无法在当前会话中完成笔记本,我们可以返回,而无需再次处理数据。
转换数据
对于我们将在本笔记本中实现的模型,我们将为所有单词构建一个特征表示,作为将评论中出现的单词映射到整数的一种方式。首先,我们将每个单词表示为一个整数。然而,评论中出现的一些词很少出现,因此可能不包含太多用于情感分析的信息。
我们处理这个问题的方式是,我们将固定我们工作词汇的大小,我们将只包括最频繁出现的单词。然后,我们将把所有不常用的单词组合成一个类别,在我们的例子中,我们将把它标记为 1 。
由于我们将使用递归神经网络,如果每次复习的时间长度相同,将会很方便。为了做到这一点,我们将确定评论的大小,然后用“无词”类别填充短评论(我们将把它标记为 0 ),并截断长评论。
build_dict 实现了对数据的特征转换。注意,即使 vocab_size 被设置为 5000 ,我们只想为最频繁出现的 4998 个单词构建一个映射。这是因为我们想为’无字’保留特殊标签 0 ,为’生僻字’保留特殊标签 1 。
我们评论中最常见的五个词是什么?不出所料他们是: movi , film , one , like , time 。
稍后,当我们构建一个端点来处理提交的评审时,我们将需要使用我们已经创建的 word_dict 。因此,我们现在将它保存到一个文件中以备将来使用。
现在我们有了单词字典,它允许我们将评论中出现的单词转换成整数,我们使用它将评论转换成它们的整数序列表示,确保填充或截断到固定长度,在我们的例子中是 500 。
我们首先创建 convert_and_pad 函数来填充单个审查。
然后我们在 convert_and_pad_data 中实现它,将其应用于整个数据。
让我们回顾一下在上面的步骤中我们做了什么。为了处理短评论和长评论,我们将所有评论填充或删减到特定长度。对于短于某个填充长度的评论,我们将用 0 填充。这可能会导致内存问题,但这是标准化评论的必要步骤。
当我们构建包含所有词汇的 word_dict 变量时,我们只使用了训练数据。这意味着在训练和测试数据集之间不会发生数据泄漏。然而,如果训练数据集不是详尽的,我们将会遇到限制。
上传到 S3
我们需要将训练数据集上传到一个简单的存储服务( S3 )中,以便我们的训练代码能够访问它。现在我们将把它保存在本地,稍后我们将上传到 S3。
注意我们保存的数据的格式是很重要的,因为我们在编写训练代码时需要知道它。在我们的例子中,数据集的每一行都具有形式为的标签、的长度、的评论【500】,其中*评论【500】*是表示评论中单词的 500 整数序列。
接下来,我们需要将训练数据上传到 SageMaker 默认 S3 存储桶,以便在训练我们的模型时可以访问它。
下面的代码块上传了我们的数据目录的全部内容。这包括 word_dict.pkl 文件。这是幸运的,因为我们将在稍后创建接受任意审查的端点时需要它。现在,我们将只注意到这样一个事实,即它驻留在数据目录中(因此也在 S3 培训桶中),并且我们将需要确保它保存在模型目录中。
构建和培训 PyTorch 模型
Credits: Udacity
SageMaker 上的模型由三个对象组成:
- 模型工件
- 培训代码
- 推理代码
每个组件都相互作用。这里我们将使用 Amazon 提供的容器,并编写我们自己的定制训练和推理代码。
我们将从在 PyTorch 中实现我们自己的神经网络以及一个训练脚本开始。出于这个项目的目的,我们在火车文件夹内的 model.py 文件中提供了必要的模型对象。下面的代码块展示了实现。
我们可能希望调整三个参数来提高模型的性能:
- 嵌入维度
- 隐藏维度
- 词汇量
我们可能希望在训练脚本中配置这些参数,这样,如果我们希望修改它们,就不需要修改脚本本身。首先,我们将编写一些训练代码,这样我们可以更容易地诊断出现的任何问题。
首先,我们将加载一小部分训练数据集作为样本。尝试在笔记本中完全训练模型将非常耗时,因为我们无法访问 GPU,并且我们使用的计算实例不是特别强大。然而,我们可以处理一小部分数据来感受一下我们的训练脚本是如何运行的。
接下来,我们需要编写训练代码本身。我们将把复杂的方面,如模型保存/加载和参数加载留到稍后。
假设我们有上面的训练方法,我们将通过编写代码来测试它是否工作,该代码在我们之前加载的小样本训练集上执行我们的训练方法。尽早这样做的原因是为了让我们有机会修复早期出现的、更容易诊断的错误。
为了使用 SageMaker 构建 PyTorch 模型,我们必须为 SageMaker 提供一个训练脚本。我们可以选择包含一个目录,这个目录将被复制到容器中,我们的训练代码将从这个目录中运行。当执行训练容器时,它将检查上传目录(如果有)中的 requirements.txt 文件,并安装任何所需的 Python 库,之后将运行训练脚本。
当在 SageMaker 中构造 PyTorch 模型时,必须指定一个入口点。这是将在模型训练时执行的 Python 文件。在 train 目录中有一个名为 train.py 的文件,它包含了训练我们的模型所需的大部分代码。唯一缺少的是我们之前编写的 train() 方法的实现。
SageMaker 将超参数传递给训练脚本的方式是通过参数。然后,这些参数可以被解析并在训练脚本中使用。要了解这是如何完成的,请随意查看提供的 train/train.py 文件。
部署测试模型
既然我们已经训练了我们的模型,我们想要测试它,看看它的表现如何。目前,我们的模型接受形式为 review_length , review[500] 的输入,其中 review*【500】*是一系列 500 整数,它们描述了评论中出现的单词,使用 word_dict 进行编码。幸运的是,SageMaker 为具有简单输入的模型提供了内置的推理代码。
我们需要提供一个函数来加载保存的模型。这个函数必须被调用 model_fn() ,并把模型工件存储目录的路径作为它唯一的参数。这个函数也必须存在于我们指定为入口点的 python 文件中。在我们的例子中,已经提供了模型加载功能,因此不需要进行任何更改。
注意,当运行内置推理代码时,它必须从 train.py 文件中导入 model_fn 方法。这也是为什么训练代码被包裹在一个主护中(即if _ _ name _ _ = ’ _ _ main _ _ ':)
由于我们不需要对培训期间上传的代码进行任何修改,我们可以简单地按原样部署当前的模型。
在部署模型时,我们要求 SageMaker 启动一个计算实例,该实例将等待数据发送给它。因此,该计算实例将继续运行,直到关闭。了解这一点很重要,因为部署端点的成本取决于它已经运行了多长时间。
使用模型进行测试
部署完成后,我们可以读入测试数据,并将其发送到我们部署的模型,以获得一些结果。一旦我们收集了所有的结果,我们就可以确定我们的模型有多精确。
我们现在有一个经过训练的模型,该模型已经部署,我们可以向其发送经过处理的评论,并返回预测的情绪。然而,最终我们希望能够给我们的模型发送一个未处理的评审。也就是说,我们希望将评论本身作为一个字符串发送。例如,假设我们希望向我们的模型发送以下评论。
我们现在需要回答的问题是,我们如何将这个评论发送给我们的模型?
回想一下,在前面的部分中,我们做了两件事:
- 移除所有 html 标签并阻止输入
- 使用 word_dict 将评论编码为一个整数序列
为了进行审核,我们需要重复这两个步骤。使用之前的 review_to_words 和 convert_and_pad 方法,我们将 test_review 转换成一个名为 test_data 的 numpy 数组,适合发送给我们的模型。回想一下,我们的模型期望输入形式为 review_length , review[500] 。然后我们可以使用预测器对象来预测情绪。
Web 应用程序的部署模型
现在我们知道我们的模型正在工作,是时候创建一些定制的推理代码了,这样我们就可以向模型发送一个尚未处理的评论,并让它决定评论的情绪。
正如我们在上面看到的,默认情况下,我们创建的评估器,在部署时,将使用我们在创建模型时提供的入口脚本和目录。然而,由于我们现在希望接受一个字符串作为输入,并且我们的模型期望一个经过处理的审查,我们需要编写一些定制的推理代码。
我们将把编写的代码存储在目录中。这个目录中提供的是我们用来构建模型的 model.py 文件,一个 utils.py 文件,它包含我们在初始数据处理过程中使用的 review_to_words 和 convert_and_pad 预处理函数,以及 predict.py ,这个文件将包含我们的定制推理代码。还要注意的是, requirements.txt 会告诉 SageMaker 我们的定制推理代码需要哪些 Python 库。
在 SageMaker 中部署 PyTorch 模型时,我们需要提供 SageMaker 推理容器将使用的四个函数。
- model_fn:这个函数与我们在训练脚本中使用的函数相同,它告诉 SageMaker 如何加载我们的模型。
- input_fn:这个函数接收已经发送到模型端点的原始序列化输入,它的工作是反序列化输入,使输入可用于推理代码。
- output_fn:这个函数获取推理代码的输出,它的工作是序列化这个输出,并将其返回给模型端点的调用者。
- predict_fn:推理脚本的核心,这是进行实际预测的地方。
对于我们在这个项目中构建的简单网站,我们只需要能够接受一个字符串作为输入,我们希望返回一个单一的值作为输出。我们可以推断,在更复杂的应用程序中,输入或输出可能是图像数据或其他一些二进制数据,这需要更多的努力来序列化。
在 serve/predict.py 中,我们编写如下推理代码:
既然已经编写了定制推理代码,我们将创建并部署我们的模型。首先,我们需要构造一个新的 PyTorch 模型对象,它指向训练期间创建的模型工件,还指向我们希望使用的推理代码。然后我们可以调用 deploy 方法来启动部署容器。
既然我们已经用定制推理代码部署了我们的模型,我们应该测试一下是否一切正常。这里,我们通过加载第一个 250 正面和负面评论来测试我们的模型,并将它们发送到端点,然后收集结果。只发送部分数据的原因是,我们的模型处理输入然后执行推理所花费的时间相当长,因此测试整个数据集是不允许的。
为 Web 应用程序使用模型
现在我们知道我们的端点正在按预期工作,我们可以设置与之交互的 web 页面。
到目前为止,我们一直通过构建一个使用端点的预测器对象来访问我们的模型端点,然后只使用预测器对象来执行推理。如果我们想创建一个访问我们模型的 web 应用程序会怎么样?
目前的设置方式使得这不可能,因为为了访问 SageMaker 端点,应用程序必须首先使用 IAM 角色向 AWS 进行身份验证,其中包括对 SageMaker 端点的访问。但是,有一个更简单的方法!我们只需要使用一些额外的 AWS 服务
Credits: AWS
上图概述了各种服务将如何协同工作。最右边是我们上面训练过的 endoint 模型,它是使用 SageMaker 部署的。最左边是我们的 web 应用程序,它收集用户的电影评论,发送出去,并期望得到正面或负面的反馈。
在中间,我们将构建一个 Lambda 函数,我们可以把它想象成一个简单的 Python 函数,只要特定的事件发生,它就可以被执行。我们将授予该函数从 SageMaker 端点发送和接收数据的权限。
最后,我们将用来执行 Lambda 函数的方法是我们将使用 API Gateway 创建的一个新端点。这个端点将是一个 url,它侦听要发送给它的数据。一旦它得到一些数据,它将把这些数据传递给 Lambda 函数,然后返回 Lambda 函数返回的任何内容。本质上,它将充当一个接口,让我们的 web 应用程序与 Lambda 函数进行通信。
设置 Lambda 函数
每当我们的公共 API 接收到数据时,Lambda 函数就会被执行。当它被执行时,它将接收数据,执行任何需要的处理,将数据(评论)发送到我们创建的 SageMaker 端点,然后返回结果。
因为我们希望 Lambda 函数调用 SageMaker 端点,所以我们需要确保它有这样做的权限。为此,我们将构造一个角色,稍后我们可以赋予 Lambda 函数。
使用 AWS 控制台,导航到 IAM 页面并点击角色。然后,点击创建角色。确保 AWS 服务是所选的可信实体类型,并选择λ作为将使用该角色的服务,然后单击 Next: Permissions 。
在搜索框中键入sagemaker
并选中amazonsagemakerfullcaccess策略旁边的复选框。然后,点击下一步:复习。
最后,给这个角色一个名字。确保你使用一个我们以后会记住的名字,例如lambdasagemakerole。然后,点击创建角色。
现在我们可以创建 Lambda 函数。使用 AWS 控制台,导航到 AWS Lambda 页面,点击创建功能。当我们进入下一页时,确保选择了从头开始创作。
现在,用一个我们以后会记得的名字来命名这个 Lambda 函数,例如情绪分析函数。确保选择了 Python 3.6 运行时,然后选择在上一部分中创建的角色。然后,点击创建功能。
在下一页,我们可以看到一些关于我们刚刚创建的 Lambda 函数的信息。向下滚动可以看到一个编辑器,我们可以在其中编写 Lambda 函数被触发时将执行的代码。在我们的例子中,我们将使用下面的代码。
我们需要将端点名称添加到 Lambda 函数中。在 SageMaker 笔记本中,我们可以获得这个端点名称:
一旦我们将端点名称添加到 Lambda 函数中,点击保存。Lambda 函数现在已经启动并运行。接下来,我们需要为我们的 web 应用程序创建一个执行 Lambda 函数的方法。
设置 API 网关
既然我们的 Lambda 函数已经设置好了,是时候使用 API Gateway 创建一个新的 API 了,它将触发我们刚刚创建的 Lambda 函数。
使用 AWS 控制台,导航到亚马逊 API 网关,然后点击开始。
在下一页上,确保选择了新 API ,并为新 API 命名,例如sensation _ analysis _ API。然后,点击创建 API 。
现在我们已经创建了一个 API,但是它目前什么也不做。我们想要它做的是触发我们之前创建的 Lambda 函数。
选择动作下拉菜单,点击创建方法。将创建一个新的空白方法,选择其下拉菜单并选择 POST ,然后点击旁边的复选标记。
对于集成点,确保选择了 Lambda 函数并点击使用 Lambda 代理集成。该选项确保发送给 API 的数据不经处理直接发送给 Lambda 函数。这也意味着返回值必须是正确的响应对象,因为它也不会被 API Gateway 处理。
在 Lambda 函数文本输入框中输入之前创建的 Lambda 函数的名称,然后点击保存。在弹出的对话框中点击 OK ,允许 API Gateway 调用您创建的 Lambda 函数。
创建 API 网关的最后一步是选择动作下拉菜单并点击部署 API 。我们需要创建一个新的部署阶段,并将其命名为相关的名称,例如 prod 。
我们现在已经成功地建立了一个公共 API 来访问您的 SageMaker 模型!请确保复制或记下所提供的 URL,以调用新创建的公共 API,因为下一步需要用到它。该 URL 位于页面顶部,在文本调用 URL 旁边以蓝色突出显示。一个示例 URL 如下所示:
与端点相关联的链接是:https://ltii177nx3.execute-api.us-west-2.amazonaws.com/prod
部署 Web 应用程序
现在我们有了一个公开可用的 API,我们可以开始在 web 应用程序中使用它。出于我们的目的,我们有一个简单的静态 html 文件,它可以利用前面创建的公共 API。
在网站的文件夹中有一个名为index.html的文件。将文件下载到您的计算机上,并在您选择的文本编辑器中打开该文件。应该有一行包含*** 替换为公共 API URL*** 。用上一步中的 url 替换这个字符串,然后保存文件。
现在,如果您在本地计算机上打开index.html
,浏览器将作为本地 web 服务器运行,您可以使用提供的站点与您的 SageMaker 模型进行交互。
更进一步,你可以把这个 html 文件放在任何你想放的地方,例如使用亚马逊 S3 上的静态站点。
结果
让我们看看我们的模型在正面和负面评论中的表现。
恭喜你!你现在有一个神经网络驱动的网络应用程序!
这个项目之所以成为可能,得益于 Udacity 的深度学习 nanodegree。我强烈推荐这门课程,作为获得对人工智能的坚实理解的一种方式!
如何使用 Amazon Free ec2 实例部署 Streamlit 应用程序?
Image by Gerd Altmann from Pixabay
10 分钟内将数据应用程序上传到网上
如果我们没有一个好的方式来展示它,机器学习项目就永远不会真正完成。
在过去,一个制作精良的可视化或一个小 PPT 足以展示一个数据科学项目,但随着 RShiny 和 Dash 等仪表板工具的出现,一名优秀的数据科学家需要具备相当多的 web 框架知识。
Web 框架很难学。为了一些看似简单的事情,我仍然会对所有的 HTML、CSS 和 Javascript 感到困惑。
更不用说做同一件事的许多方法,这让我们数据科学的人感到困惑,因为 web 开发对他们来说是次要技能。
这就是 StreamLit 的用武之地,它承诺只用 Python 创建 web 应用。
在我关于 Streamlit 的上一篇文章中,我谈到了如何使用简单的 Python 为数据科学家编写 Web 应用。
但是,一个主要的抱怨,如果你去看看那个帖子的评论部分,是关于不能在网络上部署 Streamlit 应用。
这是一个有效的投诉。
开发人员不能在每次客户想要使用应用程序时都带着笔记本电脑出现。这样的 app 有什么用?
所以在这篇文章中,我们将进一步使用 Amazon Free ec2 实例在 Web 上部署我们的 Streamlit 应用程序。
设置 Amazon 实例
在开始使用 amazon ec2 实例之前,我们需要设置一个实例。您可能需要使用您的电子邮件 ID 注册,并在 AWS 网站上设置支付信息。就像简单的登录一样。从这里开始,我将假设您有一个 AWS 帐户,因此我将解释接下来的重要部分,以便您可以继续操作。
- 使用https://us-west-2.console.aws.amazon.com/console进入 AWS 管理控制台。
- 在 AWS 管理控制台上,您可以选择“启动虚拟机”。在这里,我们尝试设置一台机器,用于部署我们的 Streamlit 应用程序。
- 第一步,您需要为机器选择 AMI 模板。我选择 18.04 Ubuntu 服务器,因为它适用于免费层。还有 Ubuntu。
- 在第二步中,我选择了
t2.micro
实例,因为它同样符合自由层的条件。如您所见,t2.micro
只是一个具有 512 MB RAM 的 CPU 实例。如果你正在处理一个强大的模型或愿意支付,你可以选择一个更大的机器。
- 继续按下一步,直到你到达“6。配置安全组”选项卡。您需要添加一个规则,类型为:“自定义 TCP 规则”,端口范围:8501,源:Anywhere。我们在这里使用端口 8501,因为它是 Streamlit 使用的自定义端口。
- 您可以单击“查看并启动”,最后单击“启动”按钮来启动实例。单击启动后,您可能需要创建一个新的密钥对。在这里,我创建了一个名为 streamlit 的新密钥对,并使用“Download Key Pair”按钮下载它。请妥善保管此密钥,因为每次您需要登录到此特定机器时都会用到它。下载密钥对后,单击“启动实例”
- 现在,您可以转到您的实例,查看您的实例是否已经启动。提示:查看实例状态,它应该显示“正在运行”
- 选择您的实例,从描述中复制 公共 DNS(IPv4)地址 。应该是 ec2 开头的东西。
- 一旦你在你保存了
streamlit.pem
文件的文件夹中运行以下命令。我在这里屏蔽了一些信息。
chmod 400 streamlit.pemssh -i "streamlit.pem" ubuntu@<Your Public DNS(IPv4) Address>
安装所需的库
哇,那可真难。完成上述所有步骤后,您应该能够看到虚拟机的 ubuntu 提示符。我们需要设置这台机器来运行我们的应用程序。我将使用我在上一篇文章中使用的同一个streamlit_football_demo
应用程序。
我们首先安装 miniconda,并将其路径添加到环境变量中。
sudo apt-get updatewget [https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh](https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh) -O ~/miniconda.shbash ~/miniconda.sh -b -p ~/minicondaecho "PATH=$PATH:$HOME/miniconda/bin" >> ~/.bashrcsource ~/.bashrc
然后,我们为我们的应用程序安装额外的依赖项来运行。这意味着我安装了 streamlit 和 plotly_express 。
pip install streamlit
pip install plotly_express
我们的机器已经准备就绪,可以运行了。
在 Amazon ec2 上运行 Streamlit
当我设置好实例后,我可以从 Github 获取我的演示应用程序的代码。或者你可以选择创建或复制另一个应用程序。
git clone [https://github.com/MLWhiz/streamlit_football_demo.git](https://github.com/MLWhiz/streamlit_football_demo.git)cd streamlit_football_demo
streamlit run helloworld.py
现在,您可以转到浏览器并键入外部 URL 来访问您的应用程序。我的地址是[http://35.167.158.251:8501](http://35.167.158.251:8501)
。这是输出。如果你想玩这个应用程序,现在就可以打开。
不过这是一个很小的问题
我们已经开始运行我们的应用程序,让全世界都可以看到。但是每当你要关闭 SSH 终端窗口时,这个过程就会停止,你的应用程序也会停止。
那我们怎么办?
TMUX 来救援了。TMUX 允许我们甚至在离开终端窗口后继续运行我们的会话。这也有助于许多其他事情,但我将只是通过我们需要的步骤。
首先,我们停止使用Ctrl+C
并安装tmux
sudo apt-get install tmux
我们使用下面的命令启动一个新的tmux
会话。我们将会话的名称保留为 StreamSession。这里你可以用任何名字。
tmux new -s StreamSession
您可以在屏幕底部看到会话名称为“StreamSession”。您现在可以在tmux
会话中开始运行 streamlit。
streamlit run helloworld.py
您将能够在[外部 URL](http://35.167.158.251:8501/) 看到您的应用。 下一步是分离我们的 TMUX 会话 ,这样当您离开 SSH shell 时,它将继续在后台运行。为此,只需按下Ctrl+B and then D
(按 D 时不要按 Ctrl)
您现在可以关闭您的 SSH 会话,应用程序将继续在外部 URL 运行。
瞧啊。我们开始运行了。
Pro TMUX 提示: 您可以使用下面的attach
命令重新连接到同一个会话。最棒的是,您可以关闭 SSH shell,然后几个小时后再回来,重新连接到一个会话,从关闭 SSH shell 时所在的位置继续工作。
tmux attach -t StreamSession
简单的故障排除:
如果您的应用没有在 8501 托管, 这意味着 streamlit 应用的一个实例已经在您的系统上运行,您需要停止它。为此,您可以首先找到进程 ID
ps aux | grep streamlit
您将看到如下内容:
ubuntu **20927** 2.4 18.8 713780 189580 pts/3 Sl+ 19:55 0:26 /home/ubuntu/miniconda/bin/python /home/ubuntu/miniconda/bin/**streamlit** run helloworld.py
你将需要 杀死这个进程。你可以简单地通过
kill -9 20947
结论
Our Final App
Streamlit 使创建应用程序的整个过程民主化了,我不能再推荐它了。如果你想了解更多关于如何用 Streamlit 创建令人敬畏的网络应用程序,那么请阅读我的上一篇帖子。
在本帖中,我们 使用亚马逊 ec2 在 AWS 上部署了 一个简单的 web app。
在这个过程中,我们创建了自己的 Amazon ec2 实例,登录到 SSH shell,安装了 miniconda 和依赖项,运行了我们的 Streamlit 应用程序并了解了 TMUX。一天的学习够吗?
所以去展示这些疯狂的技能吧。以轻松的语气结束,正如斯登冲锋枪·苏特拉在他的讽刺作品中所说,我非常喜欢:
秘诀:重要的不是你知道什么,而是你表现出什么。
如果你想了解更多关于如何构建机器学习项目和最佳实践的信息,我想调出他在 Coursera 深度学习专业化中出色的第三门课程名为构建机器学习项目。一定要去看看。
谢谢你的阅读。将来我也会写更多初学者友好的帖子。通过媒体关注我或者订阅我的博客来了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系到我
此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。
如何部署大模型
AppEngine 和 Kubernetes 上的 500 MB py torch
我最近部署了一个 500MB Pytorch 模型。出乎意料的难!在这篇文章中,我记录了我犯的错误和权衡。
对于非批处理,在 CPU 上运行几乎和 GPU 一样快,所以如果可以的话,我建议从 GPU 开始。
简单的方法会失败
Tensorflow Serving 看起来还可以,但是将我们的模型从 Pytorch 转换成 ONNX 可能会有的困难。我们还想让本地代码尽可能简单,以便于开发。为了确保服务器快速启动,我将模型复制到带有. gitignore 条目的代码库中。我将 pytorch-pretrained-bert 添加到我的 requirements.txt 中,这增加了超过 300MB 的依赖项。
首先我尝试了谷歌 AppEngine (GAE)标准环境。当我尝试部署时,远程构建失败,并显示一条神秘的错误消息。我最终发现这是因为我的应用程序已经超出了远程构建环境的最大值。根据支持论坛,没有办法增加内存限制。
我想也许 Heroku 会支持更大的有效载荷,但它原来有同样的 500MB 限制和一个更合理的错误信息:“编译的 slug 大小:634M 太大了(最大是 500M)。”
然后我设置了一个 docker 容器来部署在 GAE 灵活环境上。这也失败了,因为机器在运行时耗尽了内存,并被无声地终止了。我通过查看内存使用量发现了这一点,并看到它超过了默认限制。我提高了的内存需求,它开始服务了!但是它在服务器上仍然非常慢(仅加载静态页面就需要 30 秒),但是在本地却很快。
我发现主要的区别是 Gunicorn vs Flask 开发服务器。由于某种原因,Gunicorn 没有对健康检查做出反应。我试图在 Flask 中手动实现这些检查,但是没有用。然后我尝试用 Flask dev 服务器进行部署,我知道这是不允许的,因为它不提供像请求队列这样的东西。每个请求都很快,但是 flask dev 服务器不是按比例构建的。我在本地用 Gunicorn 测试了 Docker 容器,发现它和 AppEngine 上的一样慢。我尝试了许多神奇的配置选项,包括详细日志记录,但没有任何帮助或揭示问题。在评估了许多备选方案后,我最终选定了女服务员。这是非常糟糕的记录,但我最终找到了神奇的调用。成功了!
出于某种原因,部署仍然需要一个半永恒的时间(大约 15-30 分钟),所以为了加快速度,我在本地执行我的docker build
,然后再执行docker push
已经构建好的映像。
添加 GPU 支持
AppEngine 不支持 GPU,所以我用了Google Kubernetes Engine(GKE)。事实证明,仅仅给你的节点添加 GPU 是不够的。您还需要安装驱动程序。创建集群和设置服务应该是这样的:
gcloud config set compute/zone us-west1-b
cloud container clusters create duet-gpu --num-nodes=2 --accelerator type=nvidia-tesla-k80,count=1 --image-type=UBUNTU
gcloud container clusters get-credentials duet-gpu
kubectl apply -f [https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/ubuntu/daemonset-preloaded.yaml](https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/ubuntu/daemonset-preloaded.yaml)
kubectl apply -f [cloud.yaml](https://github.com/JasonBenn/duet/blob/master/cloud.yaml)
然后使用kubectl get ingress
找到你的公共 IP。这需要一分钟来调配。
像 Heroku 和 AppEngine 这样的托管服务试图将开发人员与 DevOps 隔离开来,但这种承诺似乎并没有扩展到大型模型,尤其是 Pytorch 模型。在这篇文章中,我展示了如何使用 Flask 和服务员部署到 GAE 灵活环境和 GKE。现在我有了一个有效的食谱,以后就可以轻松地主持更多的节目了。好的一面是,我们仍然可以从 GAE 免费获得自动缩放、日志记录等功能。对 GKE 来说,这只是一个配置。
你找到更简单的方法了吗?留个条!
如何使用 DeepStream 在 NVIDIA Jetson Nano 上部署 ONNX 模型
在 Jetson Nano 上测试 DeepStream 的多流神经网络推理性能的实验。
Jetson Nano. (Source)
将复杂的深度学习模型部署到小型嵌入式设备上是一项挑战。即使有针对深度学习优化的硬件,如 杰特森纳米 和推理优化工具,如 TensorRT ,瓶颈仍然可以在 I/O 管道中出现。如果模型必须处理具有多个输入和输出流的复杂 I/O 管道,这些瓶颈可能会加剧。拥有一个能够以端到端的方式处理所有瓶颈的工具不是很好吗?
向深溪问好
原来有一个 SDK 试图缓解这个问题。 DeepStream 是一款 SDK,针对 NVIDIA Jetson 和 T4 平台进行了优化,以提供无缝的端到端服务,将原始流数据转换为可操作的见解。它构建在 GStreamer 框架之上。在这里,“原始流数据”通常是连续的(和多个)视频流,“可操作的见解”是深度学习或其他分析算法的最终输出。
The DeepStream pipeline. (Source)
DeepStream SDK 使用其定制的 GStreamer 插件来提供各种功能。值得注意的是,它有基于推理和物体跟踪的插件。下图列出了他们插件的功能。关于他们插件的详尽技术指南,你可以参考他们的插件手册。
Plugins available in DeepStream. (Source)
我特别喜欢 DeepStream 的一个特性是,它以流水线方式优化了整个 I/O 处理。我们还可以堆叠多个深度学习算法,异步处理信息。这允许您增加吞吐量,而没有手动创建和管理多处理系统设计的麻烦。
最好的部分是,对于一些支持的应用程序,如对象检测,跟踪,分类或语义分割,DeepStream 易于使用!对于这样的应用,只要你有一个兼容格式的深度学习模型,只需要在一些文本文件中设置几个参数,就可以轻松启动 DeepStream。
在这篇博客中,我们将在 DeepStream 上设计并运行一个实验来测试它的功能,并看看它是否易于在 Jetson Nano 上使用。
实验
为了测试 DeepStream 的功能,让我们在 Jetson Nano 上部署一个预训练的对象检测算法。出于几个原因,这是一个理想的实验:
- DeepStream 针对英伟达 T4 和杰特森平台上的推理进行了优化。
- DeepStream 有一个使用 TensorRT 进行推理的插件,支持对象检测。此外,它会自动将 ONNX 格式的模型转换为优化的 TensorRT 引擎。
- 它有支持多种流输入的插件。它也有插件来保存多种格式的输出。
ONNX 模型动物园有一堆预先训练好的物体探测模型。我从动物园选择了微型 YOLO v2 型号,因为它很容易与 DeepStream 兼容,而且足够轻,可以在杰特森纳米上快速运行。
**注:**我确实试过使用来自动物园的 SSD 和 YOLO v3 型号。但是有一些兼容性问题。我的 GitHub 知识库中讨论了这些问题,以及验证和处理此类情况的技巧。我最终使用微型 YOLO v2,因为它很容易兼容,没有任何额外的努力。
现在,我们要研究的特性如下:
- **多个输入流:**运行 DeepStream,同时对多个视频流进行推理。具体来说,我们将尝试使用多达 4 个视频流。
- **多输出接收器:**在屏幕上显示结果,并使用 RTSP 进行流式传输。该流将被连接到网络的另一设备访问。
实验将评估性能(每秒帧数,FPS)和易用性。接下来的几节将指导您如何在 Jetson Nano 上设置 DeepStream 来运行这个实验。这个实验使用的所有代码都可以在我的 GitHub 库上获得。如果你只是好奇结果如何,请随意跳到结果部分。
入门指南
在本节中,我们将浏览一些说明,为我们的实验做好准备。
第 1 部分:设置您的 Jetson Nano
按照Jetson Nano 开发工具包上的说明设置并启动您的 Jetson Nano。如果你在设置上遇到一些问题,我强烈推荐以下这些 资源。
我想强调一些可能会帮你省去一些麻烦的要点:
- 建议至少用 32GB 的 MicroSD 卡(我用的是 64GB)。
- 您需要有线以太网连接。如果您需要将 Jetson Nano 连接到 WiFi,您需要使用 Edimax EW-7811Un 等加密狗。
- 你需要一个直接接受 HDMI 输入的显示器。我无法使用带有 VGA-HDMI 适配器的 VGA 显示器。
第 2 部分:安装 DeepStream SDK
现在你已经有了你的 Jetson Nano,我们可以安装 DeepStream 了。Nvidia 已经整理了 DeepStream 快速入门指南,你可以按照 Jetson 设置部分下的说明进行操作。
在您使用上面的链接安装 DeepStream 之前,我想强调一下我的安装经验:
- 安装程序会建议您使用 Nvidia SDK 管理器安装 Jetpack。我跳过了这一步,因为我意识到在第 1 部分(上面)中使用操作系统映像在默认情况下具有大多数必需的依赖性。
- 在快速入门指南的“安装 DeepStream SDK”小节中,我使用了方法 2。
在安装了 DeepStream 并提升了时钟之后(如指南中所述),我们可以运行他们的一个示例来验证安装是否正确完成。将(**cd**
)移动到您的 DeepStream 安装文件夹中,并运行以下命令:
deepstream-app -c ./samples/configs/deepstream-app/source8_1080p_dec_infer-resnet_tracker_tiled_display_fp16_nano.txt
在执行时,您应该会看到类似这样的内容:
Output on executing DeepStream using the sample configuration file.
如果你看到类似的东西,恭喜你!如果你愿意,你可以尝试更多的样品。该指南有一个名为“参考应用程序源详细信息”的部分,提供了示例的描述。
第 3 部分:设置实验
现在你已经安装并测试了 DeepSteam,我们可以继续我们的实验了。我已经将实验所需的所有文件打包在我的 GitHub 存储库中。您可以按照存储库的 readme 文件中关于设置说明的逐步说明进行操作。
在继续实验之前,如果您以前没有使用过 GStreamer,那么浏览一下他们的 基础 页面是值得的。这有助于更好地理解 DeepStream 文档中使用的一些术语。
将您的自定义 ONNX 模型与 DeepStream 接口
在这一节中,我们将探讨如何将 ONNX 模型的输出与 DeepStream 进行接口。更具体地说,我们将逐步完成在 C++ 中创建自定义处理函数的过程,以从 ONNX 模型的输出中提取边界框信息,并将其提供给 DeepStream。
第 1 部分:理解 Tiny YOLOv2 的输出
ONNX 模型以通道优先格式输出形状为**(125, 13, 13)**
的张量。然而,当与 DeepStream 一起使用时,我们获得了形状为**(21125)**
的张量的展平版本。我们的目标是从这个展平张量中手动提取包围盒信息。
让我们首先尝试直观地理解 ONNX 模型输出的输出张量。考虑输出张量是一个维度为**(B, H, W)**
的长方体,在我们的例子中是B=**125**,H=**13**,W=**13**
。我们可以分别沿着宽度(W)、高度(H)和深度(B)考虑 X、Y 和 B 轴。现在,XY 平面中的每个位置代表一个网格单元。
让我们想象一个网格单元**(X=0, Y=0)**
。对于这个给定的(X,Y)位置,沿着深度轴(B)有 125 个值。让我们以 25 个为一组重新排列 125 个值,如下所示:
Figure A: Interpreting the meaning of the 125 b-values along the B-axis for the grid cell (X = 0, Y = 0).
正如我们在这里看到的,每个连续的 25 个值属于一个单独的边界框。在每组 25 个值中,前 5 个值是边界框参数,后 20 个值是类别概率。利用这一点,我们可以提取 5 个边界框中每一个的坐标和置信度得分,如下所示:
Formulae for extracting the bounding box parameters. (Source)
请注意,我们只在一个网格单元(X=0,Y=0)上执行了此操作。我们必须迭代 X 和 Y 的所有组合,以在每个网格单元找到 5 个边界框预测。
既然我们对信息是如何存储的有了一个直观的概念,让我们尝试使用索引来提取它。在展平输出张量后,我们得到一个存储信息的数组,如下图所示:
Figure B: Flattened representation of the output tensor.
展平的数组有125 * 13 * 13 = **21125**
个元素。如上所示,数组中的每个位置对应于索引**(b, y, x)**
。我们可以观察到,对于给定的**(y,x)**
值,对应的**b**
值由13 * 13 = **169**
隔开。
下面的 Python 中的代码片段展示了我们如何获得对应于给定**(y, x)**
位置中 5 个边界框中每一个的**b**
值的位置。请注意,如图 A 所示,对于给定的**(y, x)**
位置,每个边界框有 25 个**b**
值。
## Let **arr** be the flattened array.
## The array **values** contains the value of **arr** at the 25 b_values per ## bbox,x,y combination. **num_anchors** = 5
**num_classes** = 20
**xy_offset** = y * 13 + x
**b_offset** = 13 * 13
**bbox_offset** = 5 + num_classes
for **bbox** in range(**num_anchors**):
**values** = []
for **b** in range(**bbox_offset**):
value = **arr**[xy_offset + b_offset * (b + bbox * bbox_offset)]
values.append(value)
剩下要做的就是编写与此相同的 C++ 代码。
第 2 部分:编写边界框解析函数
现在我们已经了解了输出是如何存储和提取的,我们需要用 C++编写一个函数来做同样的事情。DeepStream 需要一个具有如下所示参数的函数:
extern "C" bool **NvDsInferParseCustomYoloV2Tiny**(
std::vector<NvDsInferLayerInfo> const& **outputLayersInfo**,
NvDsInferNetworkInfo const& **networkInfo**,
NvDsInferParseDetectionParams const& **detectionParams**,
std::vector<NvDsInferParseObjectInfo>& **objectList**
);
在上面的函数原型中,**outputLayersInfo**
是一个**std::vector**
,包含了我们 ONNX 模型的各个输出层的信息和数据。在我们的例子中,因为我们只有一个输出层,我们可以使用**outputLayersInfo[0].buffer**
来访问数据。变量**networkInfo**
具有模型期望的高度和宽度信息,变量**detectionParams**
具有关于某些配置的信息,例如**numClassesConfigured**
。
变量**objectList**
应在每次调用该函数时用作为**NvDsInferParseObjectInfo**
类型对象存储的边界框信息**std::vector**
进行更新。因为变量是通过引用传递的,所以我们不需要返回它,因为更改会在源中反映出来。但是,函数在执行结束时必须返回**true**
。
对于我们的用例,我们创建**NvDsInferParseCustomYoloV2Tiny**
,这样它将首先解码 ONNX 模型的输出,如本节第 1 部分所述。对于每个边界框,我们创建一个类型为**NvDsInferParseObjectInfo**
的对象来存储它的信息。然后我们应用非最大抑制来移除相同对象的重复边界框检测。然后,我们将生成的边界框添加到**objectList**
矢量中。
我的 GitHub 库的**custom_bbox_parser**
目录下有**nvdsparsebbox_tiny_yolo.cpp**
,已经为你写好了函数。下面的流程图解释了文件中的逻辑流程。代码可能看起来很大,但那仅仅是因为为了便于理解,它被大量地记录和注释了!
Flowchart approximately describing the flow of logic in the code file.
第 3 部分:编译函数
现在剩下的就是把函数编译成一个**.so**
文件,这样 DeepStream 就可以加载和使用它了。在编译它之前,您可能需要在 Makefile 中设置一些变量。你可以参考我的 GitHub 库中自述文件的第 4 步获取说明。一旦完成,进入 GitHub 库并运行下面的命令:
make -C custom_bbox_parser
设置配置文件
好消息是大部分繁重的工作已经完成。剩下的就是设置一些配置文件,告诉 DeepStream 如何运行实验。一个配置文件有一组“组”,每个“组”有一组以密钥文件格式编写的“属性”。
对于我们的实验,我们需要设置两个配置文件。在本节中,我们将探究这些配置文件中的一些重要属性。
第 1 部分:Tiny YOLOv2 的配置文件
我们的 ONNX 模型由 DeepStream 的 Gst-Nvinfer 插件使用。我们需要设置一些属性来告诉插件信息,比如 ONNX 模型的位置,编译后的边界框解析器的位置等等。
在 GitHub 存储库中,已经为我们的实验设置了名为**config_infer_custom_yolo.txt**
的配置文件。文件中给出了每个属性设置的注释和理由。有关所有受支持属性的详细列表,请查看此链接。
我们没有使用的一些有趣的属性是“净比例因子”和“偏移”属性。他们基本上使用公式net_scale_factor * (x — mean)
缩放输入(x)
。我们没有使用这些属性,因为我们的网络直接将未缩放的图像作为输入。
第 2 部分:DeepStream 的配置文件
我们还需要为 DeepStream 设置一个配置文件,以启用和配置它将使用的各种插件。如前所述,GitHub 存储库包含配置文件**deepstream_app_custom_yolo.txt**
,它已经为我们的实验设置好了。
与上一部分不同的是,这个配置有“osd”(屏幕显示)、“primary-gie”(初级 GPU 推理机)等一大堆组。此链接包含所有可配置的可能组的信息以及每个组支持的属性。
在我们的实验中,我们定义了一个源组(source0
)和三个宿组(sink0
、sink1
和sink2
)。单源组负责并行读取四个输入视频流。三个接收器组分别用于在屏幕上显示输出、使用 RTSP 传输输出以及将输出保存到磁盘。我们在primary-gie
组中提供了 Tiny YOLOv2 的配置文件路径。此外,我们还设置了titled-display
和osd
组来控制输出在屏幕上的显示方式。
运行深流
这是最简单的部分。您只需运行以下命令:
deepstream-app -c ./config/deepstream_app_custom_yolo.txt
首次启动 DeepStream 需要一段时间,因为 ONNX 模型需要转换为 TensorRT 引擎。建议在此过程中关闭 Chromium 等内存密集型应用。一旦创建了引擎文件,如果在微小的 YOLOv2 配置文件中定义了引擎文件的路径,后续的启动将会很快。
结果
在运行 DeepStream 时,一旦创建了引擎文件,我们就会看到一个2x2
平铺显示,如下图所示。拼接显示器中的每个单元对应于不同的流输入。正如所料,所有的四个不同的输入被同时处理。
Output displayed by DeepStream.
因为我们还启用了 RTSP,所以我们可以在rtsp://localhost:8554/ds-test
访问流。我使用 VLC 和 RTSP 的地址(在用我的 Jetson Nano 的 IP 地址替换了localhost
之后)来访问连接到同一网络的笔记本电脑上的流。请注意,另一个接收器也用于将输出流保存到磁盘。令人印象深刻的是,控制台定期记录每视频流接近 6.7 的 FPS!
FPS per video stream while simultaneously using four video streams.
如果我们有一个单一的输入流,那么我们的 FPS 应该是四个视频的四倍。我通过更改配置文件中的值并再次启动 DeepStream 来测试这一点。正如所料,我们得到了一个巨大的接近 27 FPS 的单一视频流!考虑到它仍然向三个不同的接收器发送输出,性能令人印象深刻。
FPS while using a single video stream.
然而,我们注意到微小的 YOLOv2 的检测精度没有 FPS 那么惊人。这尤其是因为该模型是以牺牲一些准确性为代价来优化速度的。此外,视频中的人面部模糊,模型在训练时可能不会遇到这种模糊。因此,该模型可能会面临额外的困难。
判决和想法
深溪速度惊人。尽管 Tiny YOLOv2 针对速度而非准确性进行了优化,但稳定的高 FPS 性能,同时提供无缝多流处理和 RTSP 流等惊人的功能,是值得赞赏的。
然而,使用 DeepStream 可能并不简单,尤其是如果您的模型与 TensorRT 不完全兼容。在这种情况下,手动编写自己的 TensorRT 层可能是一个更可行的(尽管很乏味)选择。此外,可能会出现这样的情况,即现成的 ONNX 模型的 opset 版本可能高于 DeepStream 当前接受的版本。
尽管如此,我确实觉得 DeepStream 提供的功能是值得努力的。我建议你通过复制我的实验来尝试一下!
如何用 Azure 在边缘设备上部署你的 AI 模型
1。简介
边缘计算是一种模式,其中部分计算在分散的边缘设备上完成,是扩展云计算的一种很好的方式。使用这种模式,人工智能(AI)模型在云中训练并部署在边缘,这具有以下优势:
- 速度当需要实时决策时,云计算意味着太多的延迟
- 可用性允许设备在与云的连接受限的情况下离线工作
- 减少带宽当产生大量数据时,在设备上进行过滤以防止所有带宽被消耗
在这篇博客中,创建了一种功能,可以使用 Azure IoT Edge 和自定义视觉 AI 检测火车上的涂鸦。这是按如下方式完成的:
- 涂鸦检测模型使用 Azure 自定义视觉进行训练,并导出为 TensorFlow 模型。
- 模型作为 docker 容器部署在边缘(相机,由 Ubuntu 虚拟机模拟)
- Edge 设备分析火车视频中的涂鸦。只有在检测到涂鸦时,视频才会放在 Blob on Edge 上,并上传到链接的 Azure 存储中
- 一旦视频在 Azure 中,视频可以被进一步处理(从视频中提取文本,在 Power BI 仪表板上显示结果,参见我以前的博客
该项目的架构可描述如下:
1. Using AI with Cognitive Services on Azure IoT Edge
在博客的剩余部分,架构的边缘部分通过以下步骤实现:
- 2.创建和导出人工智能模型
- 3.将人工智能模型作为容器部署在边缘设备上
- 4.结论
2.创建和导出人工智能模型
Azure 认知服务是一组可以注入到你的应用中的 API。它包含语音识别、图片中的对象识别和语言翻译的智能算法。还可以通过使用自定义视觉扩展另一个模型来创建自己的 AI 模型。这可以看作是“在预训练图像识别模型的神经网络中添加最后一个自定义层”。该项目采取了以下步骤:
- 2a。训练自定义视觉模型来检测火车上的涂鸦。
- 2b。将自定义视觉模型导出为 docker 文件
- 2c。将导出的模型添加到 Visual Studio 代码项目
2a。训练和部署自定义视觉模型来检测火车上的涂鸦
前往 Custom Vision 网站,使用您的 Azure 广告凭证登录。登录后,选择创建一个具有属性“分类”和多类(每个图像一个标签)的自定义视觉项目。确保选择 General (compact)作为域,否则模型无法作为容器导出,另请参见下文。
2a1. Create Custom Vision API project
然后将以下图像下载到以下 git 项目中的文件夹cognitive services/custom vision images 中:
[https://github.com/rebremer/realtime_video_processing.git](https://github.com/rebremer/realtime_video_processing.git)
第一步,将带有涂鸦标签的涂鸦图片添加到您的项目中。其次,将带有标记涂鸦的 no_graffiti 图片添加到您的项目中,然后进行底片处理。然后使用快速通道训练模型,也见下文。
2a2. Train Custom Vision Api project
您可以通过点击“快速测试”来测试模型,然后使用之前下载的 git 项目从测试文件夹中选择一个图像。
2b。将自定义视觉模型导出为 docker 文件
一旦您定型并测试了模型,您就可以创建模型的端点或者导出它。在这个场景中,模型被导出为 dockerfile。转到您的项目,选择您想要导出的迭代,然后选择 export。随后,选择将模型导出为包含张量流的 dockerfile。pb 文件。
2b1. Export model as dockerfile
在下一章中,模型被添加到项目中。
2c。将导出的模型添加到 Visual Studio 代码项目
在这个项目中, Visual Studio 代码用作编辑器。安装完成后,选择 Open Folder,然后选择打开在步骤 2a 中克隆的 github 项目中的“RealTime_Video_Processing”文件夹。然后替换 EdgeCustomVision/modules/ImageClassifierService/app 文件夹中的 model.pb 和 label.txt,另见下文
2c1. Adding CustomVision model to project
3.将人工智能模型作为容器部署在边缘设备上
在这一部分,项目部署在边缘。博客的这一部分扩展了以下标准 Azure 教程,并执行以下步骤:
- 3a。安装准备工作
- 3b。在物联网集线器上安装边缘设备
- 3c。在边缘设备上安装模块
3a。安装准备工作
需要安装以下预备设备:
- 安装 Azure 核心工具版本 2.x 。
- 安装 Azure CLI 。此博客需要 Azure CLI 版或更高版本。运行
az --version
找到您拥有的版本。 - 安装对接器
- 安装 Azure 物联网边缘扩展:一个连接到你的物联网中心的扩展,让你通过 Visual Studio 代码管理你的物联网设备
此外,创建一个存储帐户、物联网中心和 Azure 容器实例,这是本教程剩余部分需要的。
az login# Create resource group
az group create -n blog-rtvideoedge-rg -l westeurope# Create storage account and container
az storage account create -n <stor name> -g blog-rtvideoedge-rg --sku Standard_LRS
az storage container create -n videoblob --account-name <stor name># Create IoT Hub
az iot hub create --resource-group blog-rtvideoedge-rg --name blog-rtvideoedge-iothub --sku F1# Create Azure Container registry
az acr create -n <your unique acr name> -g blog-rtvideoedge-rg --sku Standard -l westeurope
3b。在物联网集线器上安装边缘设备
一个 Ubuntu VM 将作为这个博客中的边缘设备。执行以下命令
# Install extension
az extension add --name azure-cli-iot-ext# Create VM that will serve as Edge device
az vm create --resource-group blog-rtvideoedge-rg --name blog-rtvideoedge-vm --image microsoft_iot_edge:iot_edge_vm_ubuntu:ubuntu_1604_edgeruntimeonly:latest --admin-username azureuser --generate-ssh-keys --size Standard_DS1_v2# Open port such that video processing on Ubuntu VM can be seen in webbrowser
az network nsg rule create --resource-group blog-rtvideoedge-rg --nsg-name blog-rtvideoedge-vmNSG --name port_5012 --priority 1020 --destination-port-range 5012
现在,使用以下命令将虚拟机作为边缘设备添加到物联网中心:
# Create edge registration in IoT Hub
az iot hub device-identity create --hub-name blog-rtvideoedge-iothub --device-id blog-rtvideoedge-vm --edge-enabled# Retrieve keys from edge registration
az iot hub device-identity show-connection-string --device-id blog-rtvideoedge-vm --hub-name blog-rtvideoedge-iothub# And add this key to your VM using the following command:
az vm run-command invoke -g blog-rtvideoedge-rg -n blog-rtvideoedge-vm --command-id RunShellScript --script "/etc/iotedge/configedge.sh '<device_connection_string from previous step>'"
正确创建物联网集线器和边缘设备后,您应该会在门户中看到以下内容
3b1. Edge device created in IoT Hub
3c。在边缘设备上安装模块
在博客的这一部分,将在边缘设备上安装以下模块:
- 边缘上的 Azure Blob 将用作边缘设备的本地存储,并异步将数据放入链接的存储帐户
- 由摄像机模块和网络服务器组成的自定义视觉模块,可在其中跟踪视频处理。
现在找到。env 并填写以下变量:
# Replace the value of these variables with your own container registry
CONTAINER_REGISTRY_ADDRESS="<Your ACR address>" CONTAINER_REGISTRY_USERNAME="<Your ACR username>" CONTAINER_REGISTRY_PASSWORD="<Your ACR password>" BLOB_STORAGE_CONNECTIONSTRING="<Your storage account key>" BLOB_STRORAGE_CONTAINER="videoblob" PRIVATE_IP_VM="10.0.0.4" LOCAL_STORAGE_NAME="localvideostor" LOCAL_STORAGE_KEY="<create string using [https://generate.plus/en/base64?gp_base64_base%5Blength%5D=64](https://generate.plus/en/base64?gp_base64_base%5Blength%5D=64)>"
随后,通过右键单击deployment.edgecamera.template.json
文件并选择Build and push IoT Edge Solution
来构建整个解决方案,参见下文。
3c1. Build and push IoT Edge Solution
如果出现认证错误,首先在命令行中运行以下命令:az acr login --name <your acr> -g blog-rtvideoedge-rg
在下一步中,构建并推送两个 docker 容器(这可能需要一段时间),并创建一个新的 config/deployment . edge camera . JSON。需要完成以下步骤:
- 从 Visual Studio 代码将其连接到您的物联网中心(为此需要安装 2a 中提到的物联网边缘扩展)
- 转到新创建的 config/deployment . edge camera . jsonle,选择
Create Deployment for Single device
并选择我们在 3b 中创建的边缘设备。然后 docker 映像将被构建并部署到该设备上(这可能需要一段时间)
如果一切顺利,您可以点击物联网边缘在物联网门户中查找设备,另请参见下文:
3c2. Edge modules deployed sucessfully
随后,当您通过使用端口 5012 访问 Ubuntu VM 的公共 IP 来查找正在实时分析的视频时,也请参见下文
3c3. Videos being analyzed in realtime
使用ssh azureuser@<public ip ubuntu vm>
和类型sudo docker start camera-capture
通过 ssh 进入您的虚拟机可以重启视频处理。用于记录sudo docker logs camera-capture
、journalctl -u iotedge
和sudo systemctl status iotedge
。由于视频包含涂鸦,因此将其放在 blob on edge 上,该 blob 将视频异步上传到附带的 blob 存储帐户上。然后可以进一步加工,看我之前的博客怎么做这个。
4.结论
在这篇博客中,我们讨论了带人工智能的边缘计算对扩展集中式云计算非常重要,因为它允许 1)实时决策,2)离线可用性,3)降低带宽以实现成本效益。在这种情况下,创建了一个可以在边缘进行智能处理的项目,如下所示
- 使用自定义视觉模型对边缘进行涂鸦检测
- 仅当检测到涂鸦时,才使用 Blob on Edge 将视频添加到 Azure 存储帐户
- 一旦视频在 Azure 中,数字识别使用 OCR 完成,结果显示在 Power BI 上(参见我之前的博客)
项目的架构如下所示。
4. Using AI with Cognitive Services on Azure IoT Edge