培养你自己的 RNN 细胞:简化
一窥单个 RNN 细胞的“深层”世界
什么是 RNN 细胞?
根据 Tensorflow 文档,“在最抽象的设置中,RNN 单元是指 具有状态 并执行一些需要输入矩阵的操作的任何东西。”
RNN 细胞在某种意义上区别于普通神经元,因为它们有一个状态,因此可以记住过去的信息。RNN 细胞构成了循环网络的主干。
在数学层面上,一系列输入通过 RNN 单元,一次一个。单元的状态有助于它记住过去的序列,并将该信息与当前输入相结合以提供输出。一个更简单的方法是展开序列中发生的事情,揭示一个更简单的深层网络。
常见的 RNN 单元架构
两种最常用的 RNN 单元是 GRUs 和 LSTMs。这两个单元都有“门”,基本上是对应于每个输入的 0 和 1 之间的值。这些门背后的直觉是忘记和保留少数选定的输入,表明这些细胞既可以记住来自过去的信息,也可以在需要时让它离开。这使得他们能够更好地处理序列。
要详细了解这些细胞的工作,请参考这个包含动画的相当不错的博客,以便于解释。
gif 中的递归神经网络细胞
towardsdatascience.com](/animated-rnn-lstm-and-gru-ef124d06cf45)
单个节点本身就是一个深度网络!!
让我们看看 LSTM 工作的方程,它是最常用的 RNN 池之一。这里 x_t 表示单元的输入,而 h_t-1,h_t 和 c_t-1,c_t 表示隐藏状态和单元状态。所有其余的变量都是可训练的权重和偏差。
它们看起来确实很吓人,想想这些都发生在 RNN 的一个牢房里。在不深入细节的情况下,这些等式是否让你想起了其他事情?让我强调一下,矩阵与输入的权重相乘,然后是激活函数!!! 是的!!!人脉深厚!!!
RNN 细胞本身包含一个小而深的网络。虽然 LSTMs 和 GRUs 中的架构是最常用的,但这并不意味着它们是手头每项任务的最佳选择。可能有比这些标准单元性能更好的更复杂、看起来不可思议的架构。
RNN cell created by WeNet, performing better than complex Recurrent networks containing LSTM cells, on the Penn Treebank dataset.
就像神经架构搜索(NAS) 和 *AutoML 的发展一样,*研究人员也一直致力于创建他们自己的 RNN 细胞架构。如果你不知道 NAS 或 AutoML 是什么,可以看看我之前在 AutoML 上的博客。
常用方法
- 搜索整个参数空间:从所有可能的连接开始,然后删除多余的连接,留下重要的连接。由于从真正“所有”可能的连接开始在计算上是一场噩梦,这些方法中的实际搜索空间通常是有限的。
- 生长细胞,一次一个节点:这些方法依赖于类似于生长决策树的策略。每次迭代后,都会在图的顶部添加一个新节点。树从 h_t(输出)开始生长,当我们在叶节点同时得到 x_t 和 h_t-1(输入)时结束。
- 遗传算法 : RNN 细胞架构是当前一代中的明星,杂交产生下一代更好的细胞架构。
下一步是什么?
AutoML 和 NAS 领域的工作和开发是最近的事,而且每年都在快速增长。然而,不仅没有一种算法能够集成并真正创建任何深度学习网络(包括 CNN 和 RNNs ),而且现有算法所花费的计算时间也是巨大的。这些都是未来研究可以并且将会改进的方向。
本博客是为机器学习领域创建简化介绍的努力的一部分。点击此处查看完整系列
在你一头扎进去之前就知道了
towardsdatascience.com](/machine-learning-simplified-1fe22fec0fac)
或者干脆阅读本系列的下一篇博客
看看机器学习新阶段的开始
towardsdatascience.com](/automl-and-autodl-simplified-b6786e5560ff)
参考
[1]拉瓦尔、阿迪蒂亚、里斯托·米库拉宁。"从节点到网络:进化循环神经网络.“arXiv 预印本 arXiv:1803.04439 (2018)。
[2]Schrimpf,Martin 等人,“一种灵活的自动化 RNN 架构生成方法”arXiv 预印本 arXiv:1712.07316 (2017)。
[3] Pham,Hieu 等,“通过参数共享进行有效的神经结构搜索”arXiv 预印本 arXiv:1802.03268 (2018)。
[4]黄、智衡、秉祥。” WeNet:用于递归网络体系结构搜索的加权网络."arXiv 预印本 arXiv:1904.03819 (2019)。
Golang
使用 gRPC 构建一个简单的 API 服务
在很长一段时间里,REST API 一直统治着 web 编程世界,直到 gRPC 的到来,颠覆了这个行业。网上有很多帖子讨论 gRPC 的优势,并将其与 REST 进行比较,因此我不打算在这一点上做多余的评论。我的理解是 gRPC 继承了 REST 的功能,并用更快、更轻、更灵活的服务对其进行了扩展。在这篇文章中,让我们看一下 gRPC 并使用 Golang 实现一个简单的服务。
先决条件
- 安装 Go:https://golang.org/doc/install
- 安装
protoc
: gRPC 使用protobuf
进行通信,为了生成相关文件,需要安装protoc
:
brew install protobuf // For MacOS
- 安装
protoc-gen-go
:因为我们在这篇文章中使用go
,你将需要protobuf
的 go-support
go get -u github.com/golang/protobuf/protoc-gen-go
- 安装
grpc
:go 的 grpc 包
go get -u google.golang.org/grpc
(注意:确保您的GOPATH
设置正确,这样您的包和项目将位于GOPATH/src
下)
gRPC 概述
与传统的 REST API 相比,在传统的 REST API 中,客户端通过指定一系列约束条件与服务器进行通信,如发送到特定的 url — localhost/api/v1/hello
、localhost/api/v1/doSomething
并指定哪种操作,如 PUT、POST、GET……我认为 gRPC 在某种程度上抽象了这个概念,并通过简单地调用函数来定义通信,这些函数中的消息以 *protobuf*
格式定义。
使用 gRPC,客户机可以直接调用服务器中的函数,正如您稍后将看到的,它们实际上共享同一个 protobuf 文件。上图的一个巨大优势是,用不同语言编写的服务器和客户端可以很容易地相互通信,因为它们共享一个 protobuf 文件。
如果到目前为止您对 gRPC 和 protobuf 有点困惑,让我们继续并实现一个服务,看看 protobuf 如何在通信中发挥作用。在这篇文章中,我们将实现一个简单的一元服务,即发送一个问候请求并接收一个响应。客户端会发送一个对其名称的请求,服务器会返回一串 *Hello + client_name*
。
原蟾蜍
在 protobuf 中,它定义了可用的服务和消息。打开具有结构的项目:
并且在hello.proto
里面写着:
所以service
关键字定义了一个服务,rpc
定义了服务的功能。在这个例子中,我们的helloService
提供了一个Hello
函数,它需要输入helloRequest
消息并输出一个helloResponse
消息。如果你熟悉任何一门编程语言,我们大致可以打个比方:service => class
、rpc => function
和message => global variables
。
转到您的终端并运行:
protoc --go_out=plugins=grpc:. YOUR_ROOT_FOLDER/hellopb/hello.proto
--go_out
选项指定了生成文件的输出目录,也告诉我们需要使用 grpc 插件。第二部分是目标文件。
结果给你一个hello.pb.go
文件。如果你查看文件,你会发现 gRPC 的神奇之处在于,所有这些信息都是用 go 特定语言表示的,而如果你使用其他语言,同样的 protobuf 会用其他特定语言表示,这也是 protobuf 可以跨语言交流的原因。
计算机网络服务器
服务器接收来自客户端的请求并相应地做出响应。
在main
函数中,我们注册了一个服务器,让它监听地址0.0.0.0:50051
,它是本地主机,端口50051
是 gRPC 连接的端口。
函数RegisterHelloServiceServer
是从我们刚刚编写的 protobuf 文件自动生成的。如果你仔细研究这个函数,你会发现第二个参数需要一个 struct 类型来实现服务接口——做“实际工作”:
// HelloServiceServer is the server API for HelloService service.
type HelloServiceServer interface {
Hello(context.Context, *HelloRequest) (*HelloResponse, error)
}
上面的代码是在hello.pb.go
中生成的。为了实现服务器,struct 类型需要在接口内部实现函数Hello
。
然后在实现中,它从请求中接受名称并返回一个字符串Hello + name
。
客户
客户端发送请求并接收响应。
代码很简单,我们创建一个客户端hellopb.NewHelloServiceClient
拨号到端口50051
并通过函数client.Hello
发送请求。注意,所有这些函数都在自动生成的文件中提供。
现在,请再次理解文档中所说的内容:
在 gRPC 中,客户端应用程序可以直接调用不同机器上的服务器应用程序的方法,就像它是一个本地对象一样,这使得您可以更容易地创建分布式应用程序和服务。
client.Hello
正是上面所描述的,因为客户端可以直接调用服务器端的函数。
运行应用程序
服务器和客户端都准备好了,让我们先运行服务器,然后运行客户端,您将得到结果:
这是 gRPC 在 golang 中最简单的用法,当然,还有很多其他应用,特别是 gRPC 支持流调用,允许客户端和服务器以流格式相互通信。我希望这只是一个起点,还有更多值得探索。
参考:
- https://grpc.io/docs/guides/
- https://github.com/golang/protobuf
- https://github.com/grpc/grpc-go
- https://code . tuts plus . com/tutorials/rest-vs-grpc-battle-of-the-API-CMS-30711
GRU 和 LSTM 的
递归神经网络是保存信息的网络。它们对序列相关的任务很有用,如语音识别、音乐生成等。然而,RNN 患有短期记忆。如果一个序列足够长,它们将很难把信息从前面的时间步带到后面的时间步。这就是所谓的消失梯度问题。在这篇文章中,我们将研究门控循环单位(GRU)和长短期记忆(LSTM)网络,它们解决了这个问题。如果你没有读过 RNN 氏症,这里有一个链接指向我解释 RNN 是什么以及它如何工作的帖子。
Basic Architecture of RNN Cell
一个标准 RNN 的架构表明,中继模块具有非常简单的结构,只有一个 tanh 层。GRU 和 LSTM 都有类似 RNN 的重复模块,但是重复模块有不同的结构。
GRU 和 LSTM 的关键思想是细胞状态或记忆细胞。它允许两个网络保留任何信息而不会丢失太多。这些网络也有闸门,帮助调节流向细胞状态的信息流。这些门可以知道序列中哪些数据是重要的,哪些是不重要的。通过这样做,它们以长序列传递信息。现在,在我们进入 LSTM 之前,让我们先试着理解 GRU 或门控循环单元。
Basic Architecture of a GRU Cell
我们可以清楚地看到,GRU 单元的架构比简单的 RNN 单元复杂得多。我觉得方程式比图表更直观,所以我会用方程式来解释一切。
在 GRU 单元中,我们需要注意的第一件事是单元状态h等于时间 t 的输出。现在,让我们一个一个地看所有的方程。
在每个时间步长,我们有两个选项:
- 保留以前的单元状态。
- 更新其值。
上面的等式示出了在时间 t 可以替换单元状态的更新值或候选值。它依赖于前一时间步h的单元状态和一个称为r的相关性门,该相关性门在计算当前单元状态时计算前一单元状态的相关性。**
如我们所见,关联门 r < t > 具有 sigmoid 激活,其值在 0 和 1 之间,决定了先前信息的相关程度,然后用于更新值的候选中。
当前单元状态h是先前单元状态 h < t-1 >和更新候选状态 h(tilde) < t > 的过滤组合。这里,更新门z决定计算当前单元状态所需的更新候选的部分,这又决定保留的先前单元状态的部分。**
像关联门一样,更新门也是一个 sigmoid 函数,它帮助 GRU 在需要时保持单元状态。现在,让我们看看在《RNN 邮报》上看到的例子,以便更好地理解 GRU
史密斯太太养的狗意识到房子里有人,正在吠叫。
这里的“dogs”一词是必要的,因为 dogs 是复数,所以要知道单词“were”在末尾。让我们有一个单元格状态c= 1 为复数。因此,当 GRU 到达单词“dogs”时,它理解我们在这里讨论的是句子的主语,并在单元状态中存储值 c < t > = 1。这个值一直保留到单词“were ”,在这里它理解主语是复数,单词应该是“were”而不是“was”。这里的更新门知道什么时候保留值,什么时候忘记值。所以一旦单词“were”完成,它就知道细胞状态不再有用,并忘记了它。这就是 GRU 如何保持记忆,从而解决渐变消失的问题。
虽然 LSTM 的核心思想是相同的,但它是一个更复杂的网络。让我们试着用类似的方式来理解它。
Basic Unit of a LSTM Cell
乍一看,LSTM 单元看起来确实很可怕,但让我们试着像对 GRU 一样将其分解为简单的方程。GRU 有两个门,称为更新门和关联门,而 LSTM 有三个门,即遗忘门f,更新门I和输出门 o < t > 。**
在 GRU,细胞状态等于激活状态/输出,但在 LSTM,它们并不完全相同。时间“t”处的输出由h表示,而单元状态由c表示。**
如同在 GRU,在时间‘t’的单元状态具有候选值 c(波形符)< t > ,其依赖于先前的输出 h < t-1 > 和输入 x < t >。
像在 GRU,LSTM 的当前单元格状态 c < t > 是前一单元格状态和候选值的过滤版本。然而,这里的过滤器由两个门决定,即更新门和忽略门。遗忘门与 GRU 中(1-updateGate < t >的值非常相似,遗忘门和更新门都是 sigmoid 函数。
遗忘门计算当前单元状态需要多少来自前一单元状态的信息。
更新门计算在当前单元状态中需要多少候选值 c(波形符)< t > 。更新门和遗忘门的值都在 0 和 1 之间。
最后,我们需要决定我们要输出什么。这个输出将是我们的细胞状态的过滤版本。因此,我们通过一个 tanh 层传递单元状态,将值推到-1 和 1 之间,然后乘以一个输出门,该输出门有一个 sigmoid 激活,因此我们只输出我们决定输出的内容。
LSTM 氏症和 GRU 氏症在深度学习中基于序列的问题上都非常流行。虽然 GRU 的工作对某些问题有效,但 LSTM 的工作对其他问题也有效。GRU 的简单得多,需要较少的计算能力,因此可以用来形成真正的深度网络,然而 LSTM 的更强大,因为它们有更多的门,但需要大量的计算能力。至此,我希望你对 LSTM 和 GRU 有了基本的了解,并准备好深入序列模型的世界。
参考资料:
- http://colah.github.io/posts/2015-08-Understanding-LSTMs/
- 【https://www.coursera.org/learn/nlp-sequence-models
数据科学项目包管理工具选择指南
从 pipenv,conda,anaconda project,docker 等选择合适的工具。
Photo by Clem Onojeghuo on Unsplash
如果您曾经从事过数据科学项目,您一定问过这个问题。
如何管理包、依赖、环境?
谷歌了一段时间,应该会看到一些关键词,康达,巨蟒,迷你康达,巨蟒-项目,Pipenv,木星,木星实验室,Docker …
这个列表可以更长。这样的调查很无聊,可能会占用你一整天的时间。为了节省您的时间,我写这篇文章作为一个总结,帮助您为您的项目选择最好的工具。
工具的快速总结
Python 世界中有许多工具可以进行不同种类的包管理,但是没有一种工具是万能的。我们应该根据自己的需要选择合适的。
- pip 可以管理 Python 包。pip 包是一个源包。安装后还得编译,经常因为系统 OS 原因编译失败。此外,pip 不会检查与已安装软件包的冲突。
- pyenv 可以管理 Python 版本
- Virtualenv 和 venv 可以创建不同的虚拟 Python 环境。您可以为特定项目选择不同的环境。
- pipenv 将 pip、pyenv 和 virtualenv 组合在一起。但是仍然不能解决 pip 的编译问题。
- 康达是一个环境管理体系。它支持二进制包,这意味着我们不需要在安装后编译源代码。
- Anaconda 是由 conda 管理的 Python 科学计算发行版,包含 Conda、numpy、scipy、ipython notebook 等百个包,
- Conda Forge 是另一个比 Anaconda 更通用的 Python 发行版。但是这里有个坑。康达锻炉和蟒蛇并不完全兼容。如果您有一个同时使用 Anaconda 和 Conda Forge 包的项目,这可能会导致冲突。
- Anaconda 项目可以在一个项目中创建多个虚拟环境,同时管理 conda 依赖和 pip 依赖,但是缺少 CUDA 等系统包和一些命令行工具。
- 像 Apt 这样的系统包管理工具可以安装系统包,但是受到操作系统发行版的限制。比如 Ubuntu 14.04 不能安装 CUDA 9。
- Docker 可以在容器中安装一个操作系统发行版,方便切换操作系统版本。但是容器和主机必须共享相同的操作系统内核,所以没有办法直接在 macOS 上运行 Linux 发行版的 docker 容器。
- nvidia-docker 可以将 GPU 设备文件和驱动挂载到 docker 容器,但只支持 Linux。
一些建议
- 如果您临时编写了几行项目中没有的代码,请使用 Anaconda 环境。
- 如果您需要创建多个数据挖掘或科学计算项目,那么使用 Anaconda 项目来隔离这些项目,而不是使用 pipenv。
- 如果你需要使用 Python 为网站创建多个项目,那么用 pipenv 而不是 conda 来隔离这些项目。
- 对于 Anaconda 项目管理的那些项目,如果需要安装纯 Python 库,先用 pip 包。如果是需要额外编译的库,先用 conda 包。
- 如果需要隔离系统环境,使用 Docker 的 Linux 版本在容器中安装系统依赖项。
- conda 和 Linux 发行版都有二进制包,我们更喜欢使用 conda。因为 Linux 发行版的发布周期很慢,而且版本很旧。
查看我的其他帖子 中 同 一个分类查看 !
GitHub:bramble Xu LinkedIn:徐亮 博客:bramble Xu
参考
- 【pyenv,virtualenv,anaconda 有什么区别?
- https://docs . conda . io/projects/conda-build/en/latest/resources/variants . html
- 用 Anaconda 项目包装你的回购协议
AWS Textract 设置指南
如何使用 AWS 的 OCR 即服务准确处理 PDF 文件
Photo by Raphael Schaller on Unsplash
异步 API 响应
最近,异步 API 响应的新范例变得非常突出。它通过返回 Job-ID 而不是 API 响应来工作。然后,为了检查状态,用户需要使用作业 ID 向 API 提交第二次调用。这里有一个很好的指南。
Sync vs. Async API responses in Flask
异步 API 响应通常用于重量级机器学习应用程序或移动大量数据的应用程序,即任何需要花费很长时间才能将结果同步返回给用户的应用程序。
AWS Textract 可以检测和分析 PDF 格式的多页文档中的文本。Textract 对其 API 使用异步响应。在后台,每个 PDF 被分成单页格式并发送到处理引擎,以便每个页面可以独立于 PDF 文档进行处理,并且系统可以水平扩展。此外,异步操作允许用户提交超过 1,000 页的 PDF 文件进行处理,并在稍后返回以检查结果,而不是等待请求。
在 EC2 上使用 Python 设置 Textract 的分步说明
让我们来看一下设置 EC2 机器来用 Python 调用 Textract 所需的步骤:
1 — 设置一个 AWS 角色从 EC2 实例访问 Amazon Textract。
Create a role for an EC2 in IAM
a) 在创建角色页面上,将使用该角色的服务—选择 EC2 并转到下一步:权限
b) 我们将需要授予以下 4 个权限来设置 text ract—AmazonTextractFullAccess
amazonsreadonlyaccess
amazonsfnfullaccess
AmazonSQSFullAccess
(一旦设置了 SNS、SQS 和 Textract 配置,您可能需要降低访问权限)
c) 跳过标签,进入审核。称之为爽快的东西。
d) 转到 EC2 页面,在实例下选择将调用 Textract 的机器,并附加您从 a) 创建的角色,如下图所示
Associate newly created role with an EC2 Instance
2 — 登录到您添加了角色的 EC2 机器,安装 Python-boto 3 所需的 AWS SDK
> pip install boto3
3 — 创建一个 IAM 服务角色,授予 Amazon Textract 访问您的 Amazon SNS 主题的权限。这将允许 Textract 在文件分析完成时通知您。
参见 授予亚马逊 Textract 访问您的亚马逊社交网络主题 的详细访问权限。保存服务角色的亚马逊资源名称(ARN) ,因为您需要将它提供给 Textract。
根据上述参考,您创建的角色将在策略声明中指出以下内容—
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
你需要把它替换成—
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "textract.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
4 — 在 EC2 实例中运行以下代码,使用 Textract 分析 pdf。pdf 必须位于您的 S3 存储桶中。
结论
我们已经通过上面提供的代码介绍了如何在您的 S3 中的图像和 pdf 上使用 AWS Textract。
设置 Textract 有点复杂,但是如果您查看一下代码,就会明白为什么会这样。该代码创建了一个新的 SQS 队列和一个新的 SNS 主题,并为该队列订阅了我们创建的主题。
接下来,在代码中,我们指示要处理的所需 PDF 的 Textract 位置,以及进行通信的 SNS 通道。
用 Python 构建大学篮球机器学习模型指南
Photo by Martin Sanchez on Unsplash
让我们比较神经网络性能和 Vegas 线精度。
介绍
感恩节假期,我有一些空闲时间,偶然发现了由罗伯特·克拉克创建的伟大的 Python 公共 API 。这个 API 允许用户从 sports-reference.com 的非常容易地获得美国主要体育项目的任何统计数据。通常,任何数据科学工作中最困难的部分是收集和清理数据。虽然仍有一些工作要做,但我自然会被那些最难的部分变得简单的项目所吸引。我的目标是快速创建一个接近众所周知的公开可用系统质量的模型。赌博市场真的很难击败,他们将提供一个很好的准确性的衡量标准。尽管赛季初的大学篮球经常被认为是一个疲软的市场,但这种模式在拉斯维加斯不太可能盈利——有几个关键因素超出了它的范围。我这个项目的代码可以在 Github 上找到。
概述
我的计划是找到与预测大学篮球比赛结果相关的最重要的统计数据。然后我可以利用两个强大的模型,一个光梯度推进机(LGBM),一个神经网络来预测大学篮球传播。神经网络和 LGBM 模型都有不同的优点和缺点,通常两者的组合优于各自。他们都在 Kaggle 上的机器学习比赛中人气极高。如果我即将失去你,这里的是一个关于神经网络的很好的讲解视频。另一方面,LGBM 模型具有线性回归的优势,但也可以很好地处理非线性数据和空值。下面深入解释一下它为什么会在 Kaggle 上流行。这些模型虽然比简单的线性回归器复杂得多,但可能不会明显优于线性回归器(我们将测试它!).
收集数据
我们需要在大学篮球比赛开始前找到最有预见性的特征。这可能会很棘手,因为样本量会随着季节的变化而变化。进入赛季,我们只能使用季前赛的功能。在赛季后期,季前赛的特点不太可能是重要的,我们可以依靠 20+场比赛的样本量。
为了组装这些功能,我们需要每个游戏的游戏日志。这样,我们就可以汇总游戏开始时的赛季统计数据。我用以下代码编译了一个 box score URLs 列表:
import numpy as np
import pandas as pdfrom sportsreference.ncaab.teams import Teams
from tqdm import tqdmseasons = range(2011, 2020) # python is odd, this is 2011 - 2019master_array = []for season in tqdm(seasons): #tqdm shows progress bar
# a couple of teams don't have links for every season, thus #"try/except"
try:
season_team_list = Teams(str(season))
for team in season_team_list:
team_schedule = team.schedule
for game in team_schedule:
boxscore = game.boxscore_index
master_array.append([str(season),team.name,boxscore])
except:
continue
schedule_df = pd.DataFrame(master_array, columns=['Season','TeamName','BoxscoreIndex'])schedule_df.to_csv('./output/schedule.csv',index=None)
所有这些 API 调用总共需要大约 30 分钟。出于这个原因,我把数据集发布在 Kaggle 上,这样你就可以下载了。
现在我们有了 boxscore 链接,我们可以遍历 box score 并捕获几乎所有内容。因为我还不知道什么是有用的,所以我会全部下载下来。幸运的是,令人惊讶的运动参考 API 有一个简单的命令来做到这一点。我一次跑了大约 4 季,仍然花了几个小时。所以,再一次,你可能只想从 Kaggle 下载它。花名册数据可以单独收集(这样做的说明可以在 API 文档中找到)。
from sportsreference.ncaab.boxscore import Boxscoreseason = 2011 # will run once for each season
box_df = Noneschedule_df = pd.read_csv('./output/schedule.csv')season_df = schedule_df.loc[schedule_df.Season==season]
for index, row in tqdm(season_df.iterrows()):
box_link = row['BoxscoreIndex']
_df = Boxscore(box_link).dataframe
if box_df is not None:
box_df = pd.concat([box_df,_df],axis=0)
else:
box_df = _dfbox_df.to_csv('./output/{}_boxscores.csv'.format(season),index=None)
数据清理
从 2011 年到 2019 年,我们总共有大约 50,000 场比赛和票房成绩。数据清理可能非常混乱,但也非常重要。让我们向数据科学之神祈祷好运,然后首先检查空值:
print(df.isnull().sum(axis=0).sort_values(ascending=False))away_ranking 95468
home_ranking 92529
location 14172
away_offensive_rebound_percentage 2329
home_minutes_played 2329
away_turnover_percentage 2329
away_true_shooting_percentage 2329
away_total_rebound_percentage 2329
away_steal_percentage 2329
away_assist_percentage 2329
away_offensive_rating 2329
away_free_throw_attempt_rate 2329
away_effective_field_goal_percentage 2329
away_defensive_rebound_percentage 2329
away_defensive_rating 2329
away_block_percentage 2329
away_three_point_attempt_rate 2329
home_offensive_rebound_percentage 81
home_assist_percentage 81
home_defensive_rating 81
...
date 0
away_wins 0
away_win_percentage 0
away_two_point_field_goals 0
away_two_point_field_goal_percentage 0
away_two_point_field_goal_attempts 0
away_turnovers 0
home_total_rebounds 0
home_offensive_rebounds 0
away_three_point_field_goals 0
winning_name 0
首先,很多重要的列没有空值!考虑到我们依靠公共 API 和网站来收集 100,000 个 boxscore,这是令人兴奋的(上面的代码收集每个 box score 两次,每个团队一次)。
让我们继续前进。因为一次只有 25 个团队被排名,所以许多团队的排名列为空是有道理的。如果我们没有太多的数据,我会依赖排名列作为输入。但是,我认为我们可以安全地删除这些列。在某些情况下,地点也很难确定。我不打算将旅行合并到这个模型中,因此我将忽略该列。旅行,或在一段时间内的累积旅行,将是一个有趣的补充!
在进一步的检查中,很明显高级统计数据只在 I 级团队中被追踪。这就是为什么客场高级统计比主场高级统计有更多的空值——二级球队通常必须在一级竞技场比赛。我们其实并不关心二级的高级属性,所以这不是问题。这次数据清理比我预期的要顺利得多。
除了检查空值之外,数据清理还有其他步骤。我浏览了一些关键栏目(得分、助攻、胜场等)。)并检查它们的最小值和最大值,同时使用 seaborn 的 distplot 来检查它们是否有意义。目前一切似乎都很好!
特征创建
简单的得分统计将帮助我们预测 NCAA 篮球队未来的成功。有不同的方法将团队质量输入到我们的模型中。我们可以使用过去 10 场比赛的平均得分。我们可以使用过去 5 个赛季的平均得分。我们只需输入前 25 名的排名,模型就会知道排名 1-5 的团队是真正的好团队。我试图合理地限制这个项目的范围,但有近乎无限的组合可以尝试。
作为题外话,我想谈谈指数加权平均(EWA)。不要对过去的 X 个游戏进行平均统计,有时更好的方法是对最近的游戏进行加权(甚至稍微)使其比旧游戏更重。我将使用 EWA 和赛季平均版本的盒子得分统计数据。具有高游戏间差异的统计数据(3 分命中率,失误)将从长期样本中受益。
另外,我必须坦白。我已经做了大量的特征选择工作。如果下面的统计数据看起来特别具体,那是因为我已经排除了相似但不太有用的特性。有这么多的组合可以尝试,我不想浪费读者宝贵的时间去经历整个过程。我将添加一些未经测试的、可能无用的特性来展示我如何测试重要性。
我将从长期特征开始。我们谈的是非常长远的计划。对于以下特性,我采用了过去 5 季的指数加权平均值:
- 获胜%
- 进攻等级(每 100 次进攻得分)
- 进攻篮板百分比(导致进攻篮板的可用进攻篮板百分比)
- 允许对手 FG%
- 节奏
- 罚球得分的百分比
- 投篮命中率
- 三分球得分的百分比
- 三分球命中率
- 失误百分比(导致失误的进攻型进攻的百分比)
- 抢断百分比(导致抢断的防守控球百分比)
我们已经有 11 个功能了。然而,我们也需要同样的 11 个特征给对手。所以我们有 22 个功能。太多了!你可以看到这很容易失控。
好的,所以我们还需要比过去五年更多的样本。下面的统计数据我将使用一个季度的样本。
- 防御等级
- 获胜%
- Opp 3PT 拍摄%
- 犯规了
- 三分球得分的百分比
- 节奏
- 罚球命中率%
最后但同样重要的是,我们需要统计过去几场比赛的数据:
- 攻击性评级
- 偷窃百分比
- 辅助百分比
- 块百分比
- 两分投篮命中率
- 允许的助攻百分比
所以每支球队有 24 个特色,或者每场比赛有 48 个特色。告诉我们的模型赛季进行到什么程度以及主队是谁也是非常重要的。
上下文特征:
- 季节的某一天
- 主场/客场
现在我们有一个很好的,甚至 50 个功能。你能找到可以添加到模型中的特性吗?绝对的!这个模型是你玩的。出于演示的目的,我将添加几个可能没有用的。我其实还没测试过,所以不能排除!
- 本赛季平均个人犯规数
- 赛季罚球百分比
- 季节更替百分比
功能重要性和选择
我喜欢用三种主要方法来测试特性的重要性。按照从最懒到最不懒的顺序:
- LGBM 增益——我们的 LGBM 模型可以指出它认为最重要的特征。虽然这给出了一个粗略的重要性的概念,但是只使用增益也有缺点。我将在整篇文章中谈到所有这些方法的缺点。
- LOFO 重要性—“去掉一个特征”,这种方法通过每次运行去掉一个特征来测试模型。明显的缺点是要花很多时间。这个缺点被它非常广泛地适用于不同的模型和输入数据的事实所抵消。我最近才知道这种方法,我想感谢艾哈迈德·艾尔丹姆开源了这种方法并使其易于使用。
- 皮尔逊、斯皮尔曼和赫夫丁的 D 相关性——假设,在现实世界中,有时你不得不捍卫你的工作。在这种情况下,说“我把它扔进了一个黑盒机器学习模型,这就是我得到的结果”是不够的。谢天谢地,统计学家为我们做了繁重的工作。皮尔逊相关性衡量线性关系,斯皮尔曼相关性衡量单调关系,赫夫丁衡量非线性关系。我们可以针对模型中的每个特征和目标运行这些相关性,并计算出相对有用性。这些在寻找某些参数时也非常有用。例如,如果我想知道我的助攻百分比指数加权平均值衰减多少,我可以优化 Spearman 相关来找到最佳衰减值。
Pearson’s would estimate the first well, Spearman’s the first and second, and Hoeffding’s D the third. You can read more about these correlations here or here. If I had to guess, Spearman’s would work on almost all of these college basketball features.
基线结果
我们如何给我们的模型评分?这个模型试图预测维加斯的扩散。所以如果一个好的队和一个差的队比赛,这个模型会给出一个预期的胜率。假设模型预测好的队伍赢 10 分,但他们实际上赢了 8 分。那么我们的平均绝对误差是 2。同样,如果好队赢了 12 分,而我们的模型再次预测 10 分,我们的平均绝对误差也是 2。
这是我的模型代码。你会注意到我正在使用五重交叉验证来帮助给出一个可靠的模型误差估计,并且我还记录了特征的重要性。
平均绝对误差,使用上述 56 个特征:
Sklearn's Linear Regressor: 9.17 LightGBM model: 9.09
这意味着平均而言,我们的预测大约有 9 个百分点的误差。这样好吗?谁知道呢!让我们把它和维加斯的利差比较一下。前几天发现历史线和结果。很抱歉链接我自己的 twitter 帖子,但我谈论的是赛季与赛季之间的错误和赛季过程中的错误:
TL;DR:维加斯的开盘价误差约为 8.48,收盘价格误差约为 8.41。一方面,我们离得很远。那是可以预料的。如果线性模型能打败拉斯维加斯,我就不会写中等水平的文章了。我可能会离开意大利海岸。另一方面,我确实认为这显示了简单线性回归的力量,平均误差已经在维加斯 0.75 分之内。这也展示了 LightGBM 的威力。它以与线性回归相似的速度消除了十分之一的误差。
特征选择
让我们用我上面提到的最懒惰的方法,更仔细地看看我们的特性有什么贡献:
LGBM Feature Importance, using the ‘gain’ setting
我很抱歉,上面的 y 轴有点难以阅读,因为有超过 50 个功能。LGBM 模型喜欢的两组特征是加权赛季进攻等级和五年加权胜率。它也真的很喜欢整个赛季的防守评分。这对那些熟悉篮球的人来说是有意义的。
需要注意的一点是,每个特性都有一点贡献。情况并非总是如此。有时,该图中有一些明显的特征,但没有任何贡献。如果我制造一列随机噪声,它将显示为无用的(否则我们就有问题了)。我还不小心给了 LGBM 两份同一专栏的副本——在这种情况下,其中一份将显示为没有贡献任何内容。这些特性是可以安全丢弃的。
之前我提到了只使用 LGBM 增益的缺点。开始放弃增益图底部显示的特性不一定安全。“在家”是最清晰、最有用的特征之一。然而,它位于增益图的中间。有时特征可能是共线的,这可能会混淆甚至阻碍模型。“赛季罚球百分比”与“赛季罚球得分百分比”非常相似——即,在一个方面做得好的球队可能在另一个方面也做得好。该模型可能很难区分使用哪一个。让我们看看 LOFO 方法是否能帮助我们。下面是使用 LOFO 方法的重要性图表:
LOFO highlights “At home” — because it’s telling us something no other feature is!
好多红色啊!回购协议的作者表示,删除任何红色特征都是安全的。然而,在这种情况下,误差线延伸到绿色区域。可能只有两个确定的下降——季节英尺%和季节到%。这两个特性都是我为了演示我的特性选择过程而添加的。你会注意到一些红色的特征与我们添加的相似。例如,五年英尺百分比和五年到百分比。这些可能是红色的,因为我添加了共线要素。最后,赛季平均个人犯规只有一点红色,但绝对没有帮助。我不一定会在这一批中放弃这个功能,但它也是 LGBM 增益图上的最后一个。因此,我认为这也是安全的下降。让我们再试一次,这次只有 50 个原始功能:
好多了!全绿!
但是,我们牺牲了性能吗?不,两种型号实际上得分完全相同,但少了 6 个特征:
Sklearn's Linear Regressor: 9.17LightGBM model: 9.09
使用的数据更少,性能差异很小。我每次都会做这个交易。使用太多的特征会导致过度拟合,这意味着你的模型不能推广到未来的篮球比赛。事实上,我可能会添加大约 20 个类似于现有的 50 个功能,也许会提高 CV 分数。02。问题是这是否值得。对我来说,不是这样的。
也就是说,有一些特性可以显著提高性能。稍后会详细介绍。
神经网络
既然我们已经剔除了可能导致过度拟合的特征,是时候给神经网络(NN)一个机会了。实际上我对这里的期望很低。我们没有处理大量的非线性特征,我们也无法受益于像卷积这样的神经网络特定层。因此,轻型 GBM 是绰绰有余的。我们还优化了我们的功能选择,以提高 LGBM 的性能。从神经网络中分别增加和减少一些特征是值得的。
除了典型的密集神经网络层,我将利用辍学。脱落层随机“脱落”一定比例的神经元。这防止了对单个神经元的过度依赖,从而防止了过度拟合和局部极小值。由于我们几乎所有的功能都是有用的,而且我们有一个基本的神经网络,我们不需要大量的辍学。然而,如果你创建了自己的网络,我建议你使用 dropout 值(尤其是在添加了一些功能之后)。这是我使用的普通前馈网络:
使用五折交叉验证重复五次,这花了 15 分钟训练!增加的复杂性和性能不是免费的。最终结果:
Neural Network: 9.22Sklearn's Linear Regressor: 9.17LightGBM model: 9.09Vegas Open: 8.4833Vegas Close: 8.4110
等等,一个 NN 花了 15 分钟训练还打不过一个线性回归器?没错。这部分是由于优化了线性模型的特征。这部分也是由于我们的特征的线性性质。最后,我们的神经网络可以更深,这将提高性能。因为我爱我的读者,我尝试了这个模式:
def get_model():
x = keras.layers.Input(shape=[X.shape[1]])
fc1 = keras.layers.Dense(units=450, input_shape=[X.shape[1]])(x)
act1 = keras.layers.PReLU()(fc1)
bn1 = keras.layers.BatchNormalization()(act1)
dp1 = keras.layers.Dropout(0.45)(bn1)
gn1 = keras.layers.GaussianNoise(0.15)(dp1)
concat1 = keras.layers.Concatenate()([x, gn1])
fc2 = keras.layers.Dense(units=600)(concat1)
act2 = keras.layers.PReLU()(fc2)
bn2 = keras.layers.BatchNormalization()(act2)
dp2 = keras.layers.Dropout(0.45)(bn2)
gn2 = keras.layers.GaussianNoise(0.15)(dp2)
concat2 = keras.layers.Concatenate()([concat1, gn2])
fc3 = keras.layers.Dense(units=400)(concat2)
act3 = keras.layers.PReLU()(fc3)
bn3 = keras.layers.BatchNormalization()(act3)
dp3 = keras.layers.Dropout(0.45)(bn3)
gn3 = keras.layers.GaussianNoise(0.15)(dp3)
concat3 = keras.layers.Concatenate([concat2, gn3])
output = keras.layers.Dense(units=1)(concat2)
model = keras.models.Model(inputs=[x], outputs=[output])
return model
这是由布鲁诺·梅洛在 Kaggle 上发现的竞争性神经网络的修改。我还在模型中添加了一些我之前已经删除的特性。用了 4 个多小时(!)来训练,并且得了 9.05 分。
未来方向
敏锐的读者,或者至少是那些有广泛篮球知识的读者,会指出我遗漏了一些非常重要的特征。时间表的力量是最明显和最有用的。事实上,有一个很棒的讲解者讲述了如何将阿洛克·帕蒂和艾丽莎·勒纳的时间表的力量结合起来。伤病、招募排名和教练变动也会有所帮助。最后,基本的球员名单特征,比如身高,或者休赛期特征,比如“上个赛季的篮板数占总篮板数的百分比”也可以提高球员的表现。
我非常乐观地认为,使用这些基础知识和上述一些特性的组合,您可以朝着令人垂涎的 Vegas 误差值前进。我会更新这篇文章,增加一些功能吗?如果我开始接近维加斯错误,我会分享我的代码吗?没有人知道,尤其是我。
TensorFlow Core 中自定义卷积神经网络编码指南
低级 API 开发教程
下面演示了如何使用低级 TensorFlow 内核创建卷积神经网络(ConvNet)模型,而无需 Keras 等高级 API。本教程的目标是更好地理解深度神经网络中的后台进程,并演示如何使用 TensorFlow 创建自定义代码的概念。
本教程将展示如何将 MNIST 手写数字数据集加载到数据迭代器中,使用图形和会话,创建一个新颖的 ConvNet 架构,用不同的选项训练模型,进行预测,并保存训练好的模型。然后,将提供完整的代码以及 Keras 中的等效模型,以允许直接比较,从而为使用 Keras 的人提供进一步的见解,并显示高级 API 对于创建神经网络是多么强大。
MNIST 数据集
MNIST 是一组手写数字的 28x28 灰度图像,训练集中有 60,000 幅图像,测试集中有 10,000 幅图像。首先,我将加载并处理 MNIST 图像。
模型将期望输入形状是[batch_size, height, width, channels]
。由于图像是灰度的(单通道),它们有形状[60000,28,28]
,所以它们需要增加一个通道尺寸来获得形状[60000,28,28,1]
。它们还具有 uint8 类型(像素值范围为 0–255),因此需要通过除以 255 将其缩放至 0–1 之间的范围。然后显示第一幅图像作为示例。
标签是整数值(例如,0,1,2),但是标签是分类值,因此它们需要被一热编码(例如,[1,0,0],[0,1,0],[0,0,1])用于训练。Keras 有一个编码器to _ categorial,我将使用它来转换标签(Scikit-learn 也有 OneHotEncoder 作为另一个选项)。
正如下面将要看到的,我们不需要将测试标签转换为一键编码。
图表和会话
使用 TensorFlow 制作模型有两个部分:创建一个图,并在一个会话中运行该图。
该图概述了计算数据流。它组织何时以及如何对张量(多维数据数组)执行操作。该图形可以在会话内部或外部创建,但只能在会话内部使用。在会话中,张量被初始化,操作被执行,模型被训练。
数据迭代器
为了演示数据流图和会话,我将创建一个数据集迭代器。由于 MNIST 图像和地面实况标签是 NumPy 数组的切片,因此可以通过将数组传递给方法TF . data . dataset . from _ tensor _ slices来创建数据集。然后我们可以为数据集创建一个迭代器。我们希望它在每次运行时返回batch_size
数量的图像和标签,并在不确定的时期内重复。
我们现在已经定义了一个数据流图,为了获得一批新的图像和标签,我们可以在一个会话中运行data_batch
。
但是,还没有。数据流图已经完成,但是图像还没有真正传入。为此,迭代器需要在会话中初始化。
现在一个会话正在运行,只需运行data_batch
就可以检索到第一批图像。图像将具有形状[batch_size, height, width, channels]
,标签具有形状[batch_size, classes]
。我们可以通过以下方式检查这一点:
Images shape: (128, 28, 28, 1)
Labels shape: (128, 10)
我们可以通过运行两次data_batch
来显示前两批中的第一幅图像。
在第一批中,第一张图片是 5。在第二批中,第一张图片是 1。
然后,会话可以在sess.close()
前关闭。但是,请记住,当会话关闭时,信息将会丢失。例如,如果我们如下所示关闭并重新启动会话,数据迭代器将从头开始重新启动。(注意迭代器需要在每个会话中初始化。)
因为会话被关闭并且创建了一个新的会话,所以数据迭代器从头重新启动并再次显示相同的图像。
同“同”
会话也可以通过“with”语句启动和自动关闭。在“with”块的末尾,会话被关闭,如下所示。
ConvNet 模型
下面将演示如何使用 TensorFlow 构建所示的基本 ConvNet:
该架构有四个卷积层。前两层有 16 个滤镜,后两层有 32 个滤镜,所有滤镜的大小都是 3x3。四个卷积层中的每一个都添加了偏置和一个 relu 激活。最后两层是全连接(密集)层。
权重和偏差
ConvNet 中的初始权重需要是对称破缺的随机值,这样网络将能够学习。 xavier_initializer “旨在保持所有层中渐变的比例大致相同”,通常用于初始化模型的权重。我们可以通过使用这个带有 tf.get_variable 的初始化器来创建层的权重。每个卷积层都有形状为[filter_height, filter_width, in_channels, out_channels]
的过滤器。由于密集层是完全连接的,并且没有 3×3 的过滤器,所以它们的形状简单地是[in_channels, out_channels]
。还会创建偏差,每个偏差的大小与相应层的out_channels
相同,并且用零初始化。
为了组织和简化,我将创建weights
和biases
字典。
因为 MNIST 图像是灰度的,所以第一层的in_channels
是 1。输出层需要将out_channels
设为 10,因为有 10 个类。其他层中的过滤器数量可以根据性能或速度进行调整,但每个in_channels
需要与前一层的out_channels
相同。下面创建 ConvNet 时将解释第一个密集层的大小为 7732。
卷积层
TensorFlow 有一个 tf.nn.conv2d 函数,可用于将张量与权重进行卷积。为了简化卷积层,我将创建一个函数,它接受输入数据x
,应用带权重的 2D 卷积W
,添加偏差b
,使用 relu 激活。
模型图
另一个函数可以用来制作模型图。这将采用 MNIST 图像作为data
,并使用不同层的权重和偏差。
如体系结构所示,在第二和第四卷积层之后,各层的高度和宽度会减小。最大汇集将滑动一个窗口,仅使用该区域内的单个最大值。通过使用 2×2 的窗口(ksize=[1,2,2,1]
)和 2 的跨距(strides=[1,2,2,1]
),尺寸将减少一半。这有助于减小模型尺寸,同时保留最重要的特征。对于奇数输入大小,输出形状由除以 2 后的上限确定(例如 7/2 = 4)。
在第四个卷积层之后,张量需要在完全连接的层之前整形,这样它就变平了。全连接层的权重不用于 2D 卷积,而是仅用于矩阵乘法,因此不使用conv2d
函数。
在最后两层之间添加一个示例下降层,以帮助减少过拟合,其中下降权重的概率为 0.2。只应在训练期间使用丢弃层,因此如果模型用于预测,则包含一个training
标志来绕过该层。如果在预测过程中包含了下降图层,则由于随机下降的权重,模型的输出将会不一致且精度较低。
不同层的形状在代码注释中给出。从一个 28x28 的图像开始,大小被两个最大池层缩小了一半,因此其宽度和高度都减小到大小(28/2)/2 = 7。在用于密集图层之前,权重需要通过整形来展平。由于第四个卷积层中有 32 个滤波器,所以展平层的第一个形状维度的大小为 7x7x32(这就是为什么使用它来获得weights['d1']
的形状)。
构建 ConvNet 图
接下来,我们可以构建将用于训练模型的数据流图。
一个重要的概念是使用占位符,所以我将首先使用它们创建 ConvNet。但是,我还将展示如何在没有占位符的情况下制作模型(参见下面的无占位符培训)。
占位符
我们需要定义如何将数据迭代器中的数据输入到模型图中。为此,我们可以创建一个占位符,指示形状为[batch_size, height, width, channels]
的张量将被输入到conv_net
函数中。我们可以将height
和width
设置为 28,将channels
设置为 1,并通过将其设置为None
来保持批量大小不变。
我们现在可以使用带有weights
和biases
字典的Xtrain
占位符作为conv_net
函数的输入来获取输出逻辑。
这一步将允许我们通过向Xtrain
占位符中输入一个或一批图像来训练模型(参见下面的输入图像)。
失败
该模型基于 10 个互斥的类别对图像进行分类。在训练期间,可以通过使用 softmax 将 logits 转换为图像属于每个类别的相对概率,然后可以通过 softmax 的交叉熵来计算损失。这些都可以使用 TensorFlow 的 softmax 交叉熵一步完成。由于我们正在测量一批图像的损失,我们可以使用 tf.reduce_mean 来获得该批图像的平均损失。
我们可以再次为图表使用占位符ytrain
,它将用于输入 MNIST 标签。回想一下标签是一个热编码的,批次中的每个图像都有一个标签,所以形状应该是[batch_size, n_classes]
。
优化器
该损失用于通过网络反向传播该损失来更新模型权重和偏差。学习率用于按比例缩小更新,这防止了权重偏离最优值或在最优值附近跳跃。
Adam 优化器源自 Adagrad 和 RMSProp 与 momentum 的组合,并且已经证明与 ConvNets 一起工作一直很好。这里我使用 Adam 优化器,学习率为 1e-4。然后计算梯度,并通过运行最小化方法来更新权重。
train_op
现在是训练模型的关键,因为它运行optimizer.minimize
。为了训练模型,只需要将图像输入图表,然后运行train_op
来根据损失更新权重。
训练模型
精度
我们可以在训练期间使用测试图像来测量准确度。对于每个图像,我们执行模型推断,并使用具有最大 logit 值的类作为预测。准确度就是正确预测的比例。我们需要使用整数值而不是独热编码来比较预测和标签,所以我们需要通过使用 argmax 来转换它们(这就是为什么test_labels
没有被转换为独热编码,否则它必须被转换回来)。
精度可以用 TensorFlow 的精度算子来测量,该算子有两个输出。第一个输出是没有更新指标的准确性,第二个输出是我们将使用的返回具有更新指标的准确性的输出。
初始化变量
需要初始化局部变量(临时变量,如精度中的total
和count
度量)和全局变量(如模型权重和偏差),以便在会话中使用。
输送图像
回想一下,对于每一批,需要创建一组新的图像和基本事实,并输入占位符Xtrain
和ytrain
。如上图所示,我们可以从data_batch
得到batch_images
和batch_labels
。然后,通过创建一个将占位符作为键、将数据作为值的字典,然后在sess.run()
中运行train_op
时将字典传递给feed_dict
参数,可以将它们输入到占位符中。
培训课程
通过调用会话中的train_op
,图形中的所有步骤都将如上所述运行。我将使用 tqdm 查看每个时期的训练进度。在每个历元之后,测量精度并打印出来。
该模型将继续训练给定的时期数。在 5 个时期之后,该模型具有大约 0.97 的准确度。
没有占位符的培训
上面的例子演示了用于输入图像的占位符,但是如果直接在conv_net
中使用batch_images
,在tf.nn.softmax_cross_entropy_with_logits_v2
的labels
参数中使用batch_labels
,这个图形会变得更加简洁。然后,可以训练模型,而不必像这里所示的那样将任何张量输入到图形中。
访问其他节点
图中的不同节点可以通过在会话中调用它们来访问,可以是单独的,也可以是列表形式的。如果运行了一个节点列表,那么将会给出一个输出列表。例如,假设我们想要查看训练期间每个图像批次的损失。这可以通过在带有train_op
的列表中运行会话中的loss
来完成。在这里,我将使用 tqdm 来打印该时期内每批的损失。
预言
测试预测
我们可以使用测试精度中的test_predictions
来可视化分类一些示例图像的性能。在这里,我将显示前 25 个测试图像,并使用整数预测作为标题。
预测新的图像批次
如果您想要预测一组新的图像,只需在会话中对一批图像运行conv_net
功能即可进行预测。例如,以下内容可用于获得测试集中前 25 幅图像的预测:
然后predictions
可以像上面一样用于显示图像。
预测单个图像
回想一下,模型期望输入具有形状[batch_size, height, width, channels]
。这意味着,如果正在对单个图像进行预测,则该图像需要将其维度扩展到第一维度(即batch_size
)作为一个维度。这里预测了测试集中的第 1000 幅图像。
预测概率
预测的标准化概率分布可使用 softmax 对来自conv_net
模型的对数进行计算。
该模型预测该数字为 9 的概率很高。
对于模型来说,有些数字不容易预测。例如,这里是测试集中的另一个图像(idx=3062
)。
虽然模型预测 8 是最有可能的类别,但它的概率只有 0.48,而且还有其他几个数字的概率在增加。
下面是一个不正确预测的例子(idx=259
):
该模型错误地预测了 0,数字 6 是第二高的预测值。
保存模型
正如所讨论的,只要会话仍然打开,就可以进行预测。如果会话关闭,训练的权重和偏差将会丢失。通过使用 tf.train.Saver ,可以将会话和模型图以及训练好的权重和偏差保存为检查点。
完整的代码示例
结合上面的信息,下面是一个创建、训练和保存 ConvNet 并显示手写数字样本预测的示例脚本。
Keras 中的等效模型
Keras 是一个高级 API,可以通过使用其顺序模型 API 来极大地简化上述代码。功能 API 也是更复杂的神经网络的一个选项。对于那些有使用该 API 经验的人来说,这是一个有用的比较,并向那些没有使用过它的人展示它的价值。
请注意,不需要使用会话。此外,模型权重和偏差不需要在模型之外定义。它们是在添加层时创建的,并且它们的形状是自动计算的。
摘要
张量流图为如何训练模型创建计算数据流,会话用于进行实际训练。本文演示了在培训会话中创建图表和运行图表时使用的不同步骤和选项。当您大致了解如何创建图表并在会话中使用它们时,开发自定义神经网络并使用 TensorFlow Core 来满足您的特定需求将变得更加容易。
此外,可以看出,Keras 更加简洁,这也是为什么这个 API 更适合测试新的神经网络的原因。然而,对于新的 AI 开发者来说,许多步骤可能是黑盒,本教程旨在帮助展示后台发生的事情。
机器学习文件格式指南:列式、训练、推理和特征存储
TLDR;大多数机器学习模型都是使用文件中的数据进行训练的。这篇文章是 Python 中机器学习开源框架中使用的流行文件格式的指南,包括 TensorFlow/Keras、PyTorch、Scikit-Learn 和 PySpark。我们还将描述特性存储如何在选择的文件系统上以选择的文件格式生成训练/测试数据,从而使数据科学家的工作变得更加轻松。
文件格式定义了存储在其中的数据的结构和编码,通常由文件扩展名来标识,例如,以结尾的文件名。txt 表示该文件是一个文本文件。然而,尽管文件被用来存储世界上的大部分数据,但是大部分数据并不是可以直接用于训练 ML 模型的格式。
这篇文章主要关注的是结构化数据的文件格式,我们将讨论 Hopsworks 特性库如何以 ML 的流行文件格式轻松创建训练数据,例如。tfrecords,。csv,。npy 还有。petastorm,以及用于存储模型的文件格式,如。pb 和。pkl。我们将不涉及其他众所周知的文件格式,如图像文件格式(例如。png,。jpeg)、视频文件格式(例如. mp4、.mkv 等)、档案文件格式(例如,zip,。gz,。tar、. bzip2)、文档文件格式(例如,docx,。pdf,。txt)或网络文件格式(例如,html)。
数据源
文件存储在文件系统上,并且在云中,越来越多地存储在对象存储上。文件系统有不同的风格。本地文件系统(POSIX)通常将其数据存储在一个或多个磁盘上(磁盘(硬盘)、SSD(固态存储)或 NVMe 驱动器)。这种文件系统可以通过网络(例如 NFS)访问,或者如果需要大量的容量,可以使用分布式文件系统,可以扩展到在数千个服务器上存储数百 Pb 的数据,如 HDFS、HopsFS 和 CephFS。在云中,对象存储是最便宜的文件存储选项,应用程序可以以合理的性能读取/写入文件。
文件格式与其文件系统相关联。例如,如果您在 Nvidia V100 GPU 上运行 TensorFlow/Pytorch 应用程序来训练 ImageNet 处理存储在 S3(对象存储)中的图像,您可能能够每秒处理 100 张图像,因为这是单个客户端可以从 S3 读取的数据。但是,V100 可能每秒处理 1000 个图像——这是文件系统的 I/O 瓶颈。新的文件格式似乎可以解决这类问题。例如,petastorm 文件格式是由优步开发的,用于存储存储在 HDFS 的自动驾驶车辆的 PBs 数据。petastorm 文件很大,可拆分,并使用 TensorFlow 和 PyTorch 的阅读器进行压缩,使它们能够并行处理大量 V100,确保它们不会成为文件 I/O 的瓶颈,如果在较慢的网络文件系统上使用传统的多媒体文件格式,就会出现这种情况。另一个替代方案是在由数百或数千个 NVMe 磁盘组成的存储设备上使用传统的文件格式,但这要昂贵得多。
机器学习框架希望将训练数据作为样本序列来使用,因此用于训练 ML 模型的文件格式应该具有易于使用的布局,并且与存储平台或用于读/写文件的语言没有阻抗不匹配。此外,分布式训练(同时在许多 GPU 上训练 ML 模型以使训练进行得更快)要求文件是可拆分的,并且可以通过分布式文件系统或对象存储来访问,以便不同的 GPU 可以从不同的服务器并行读取不同的数据碎片(分区)。
大数据—从二进制数据到结构化数据
机器学习在许多领域取得了技术突破,如图像分类、语音识别、语音合成、自然语言处理和神经机器翻译。这些系统中使用的文件格式类型通常是压缩的二进制或明文数据格式。
机器学习的影响已经超出了这些最初的领域,现在正在应用于企业数据,以解决可以建模为监督机器学习问题的业务问题。然而,许多企业数据是以结构化数据的形式提供的,这些数据来自数据仓库、数据库、文档存储库和数据湖。结构化企业数据还可以用于各种基于文本的二进制文件格式。通常,如果您有大量数据,那么您应该考虑使用二进制文件格式(而不是传统的基于文本的格式,如 CSV),因为二进制文件格式可以显著提高导入管道的吞吐量,有助于减少模型训练时间。二进制文件格式需要更少的磁盘空间,从磁盘读取所需的时间也更少。二进制文件格式意义重大,因为机器学习的另一个主要趋势是深度学习的使用越来越多。深度学习对数据如饥似渴——它在上训练的数据越多,它就会变得越好——随着数据量的增加,高效的压缩文件格式将在未来的深度学习战争中发挥作用。
机器学习框架中的文件格式
较旧的文件格式(例如,csv)可能不被压缩,可能不可分割(例如,HDF5 和 netCDF)以便它们在与许多工作者并行训练时可以无缝地工作,并且可能使得难以组合多个数据集。然而,如果您用于机器学习的框架,如 TensorFlow、PyTorch、ScikitLearn,不提供与那些文件格式功能和数据源无缝集成的数据导入和预处理功能,那么您可能无法获得更好的文件格式的好处。例如,TFRecord 文件格式是为 TensorFlow 设计的,在 tf.data 中有完整的支持,而 PyTorch 的 DataLoader 首先是围绕 Numpy 文件设计的,然后扩展到其他文件格式。类似地,ScikitLearn 最初设计用于 CSV 和 Pandas,然后扩展用于其他文件格式。因此,尽管很明显您应该使用更现代的文件格式来进行机器学习,但您仍然面临着将数据转换为这种格式的挑战,并且关于如何做到这一点的可用文档可能有限。幸运的是,Feature Store(稍后介绍)使您可以轻松地将数据转换为最重要的文件格式,以便进行机器学习。
文件格式
本节介绍了最广泛使用的 ML 文件格式,将它们分为众所周知的文件格式类型:柱状、表格、嵌套、基于数组和分层。还有为模型服务设计的新文件格式,如下所述。
柱状数据文件格式
除了可能的 Excel 之外,企业数据最常见的位置是数据仓库或数据湖。通常使用结构化查询语言(SQL)来访问这些数据,并且这些数据可以以面向行的格式(通常是提供低延迟访问、高写入吞吐量的 OLTP 数据库)或者更常见的面向列的格式(可以从 TB 扩展到 PBs 并提供更快的查询和聚合的 OLTP 列数据库)来存储。在数据湖中,结构化数据可以存储为文件(。拼花地板和。orc ),仍然可以使用 SparkSQL、Hive 和 Presto 等可伸缩的 SQL 引擎通过 SQL 访问。这些柱状数据文件和后端数据库通常是企业 ML 模型的训练数据的来源,对它们的特征工程通常需要数据并行处理框架(Spark、Beam 和 Flink ),以使特征工程能够在许多服务器上横向扩展。这种可伸缩的处理之所以能够实现,是因为 parquet/orc/petastorm 数据中的数据路径实际上是一个目录——而不是一个文件。该目录包含许多可以并行处理的文件。因此,当您想要读取列文件格式的数据时,通常需要提供基本路径(目录),处理引擎会计算出要读取的文件。如果您只想从表中读取列的子集,则不会从磁盘中读取包含排除列的文件,并且如果您执行范围扫描,文件中的统计信息(文件中列的最大/最小值)会启用数据跳过-如果您的查询要求值超出文件中存储的值范围的列,则跳过此文件。
虽然 parquet 和 orc 具有相似的属性,但 Petastorm 是为支持 ML 数据而独特设计的,它是唯一一种本地支持多维数据的列式文件格式。列式文件格式通常假设二维关系数据,但是张量可以具有比一维向量或二维关系数据源更高的维数。Petastorm 通过使用自己的 Unischema 扩展 Parquet 来提供多维数据能力,Unischema 是专门为机器学习用例设计的。Unischema 支持 petastorm 文件在 Parquet 中本地存储多维张量。unischema 还与 PyTorch 和 TensorFlow 兼容,因此您可以将 petastorm 架构直接转换为 TensorFlow 架构或 PyTorch 架构,从而为 petastorm 启用本机 TensorFlow/PyTorch 读取器。
列式文件格式是为分布式文件系统(HDFS、霍普斯福斯)和对象存储(S3、GCS、ADL)设计的,在这些系统中,工作人员可以并行读取不同的文件。
- 文件格式:。拼花地板。兽人、. petastorm.
- 特色工程 : PySpark,Beam,Flink。
- 训练:。petastorm 在 TensorFlow 和 PyTorch 有原生读者;
。兽人,。Spark 的拼花地板有本地读者;由 Spark 支持的 JDBC/Hive 源
基于表格文本的文件格式
用于机器学习的表格数据通常在。csv 文件。Csv 文件是基于文本的文件,包含逗号分隔值(csv)。Csv 文件在 ML 中很流行,因为它们易于查看/调试,并且易于从程序中读取/写入(没有压缩/索引)。但是,它们不支持列类型,文本列和数字列之间没有区别,并且它们的性能很差,当数据量增长到 GB 或更大时,这一点更加明显—它们不可拆分,没有索引,并且不支持列过滤。。csv 文件可以使用 GZIP 压缩以节省空间。ML 中通常不使用的其他流行表格格式是电子表格文件格式(例如。xlsx 和。xls)和非结构化文本格式(。txt)。
- 文件格式:。csv,。xslx
- 特色工程:熊猫、Scikit-Learn、PySpark、Beam 等等
- 训练:。csv 在 TensorFlow、PyTorch、Scikit-Learn、Spark 中有本地读者
嵌套文件格式
嵌套文件格式以 n 级分层格式存储它们的记录(条目),并有一个模式来描述它们的结构。分层格式意味着一个记录可以有一个父记录(或者是根记录,没有父记录),但也可以有子记录。嵌套文件格式模式能够被扩展(在保持向后兼容性的同时添加属性),并且属性的顺序通常并不重要。的。json 和。xml 文件格式是最著名的纯文本嵌套文件格式,而二进制嵌套文件格式包括协议缓冲区(。pb)和 avro(。avro)。
TFRecords 是二进制记录的序列,通常是带有模式“Example”或“SequenceExample”的 protobuf。开发人员决定是将样本存储为“示例”还是“序列示例”。如果您的要素是相同类型数据的列表,请选择序列示例。TFRecords 文件可以是一个目录(包含许多。tfrecords 文件),并且支持用 Gzip 压缩。关于如何使用 TFRecords 的更多细节可以在官方文档和这篇好博文中找到。
- 文件格式:。tfrecords,。json,。xml,。avro
- 特征工程:熊猫、Scikit-Learn、PySpark、Beam 等等
- 培训:。tfrecords 是 TensorFlow 的本机文件格式;
。json 在 TensorFlow、PyTorch、Scikit-Learn、Spark
都有原生阅读器。avro 文件可以用 LinkedIn 的库作为 TensorFlow 中的训练数据。
基于数组的格式
Numpy 是 Numerical Python 的缩写,是一个非常流行的科学计算和数据分析库。通过对矢量化的支持,Numpy(。npy)也是一种高性能的文件格式。Numpy 数组是具有相同类型元素的密集数组。文件格式。npy 是一种二进制文件格式,存储单个 NumPy 数组(包括嵌套的记录数组和对象数组)。
- 文件格式:。npy
- 特色工程 : PyTorch、Numpy、Scikit-Learn、TensorFlow
- 训练:。npy 在 PyTorch、TensorFlow、Scikit-Learn 都有原生读者。
分层数据格式
HDF5 (.h5 或. HDF5)和 NetCDF(。nc)是流行的分层数据文件格式(HDF ),旨在支持大型、异构和复杂的数据集。特别是,HDF 格式适用于不能很好地映射到像 parquet 这样的列格式的高维数据(尽管 petastorm 既是列格式的,也支持高维数据)。许多医疗设备数据以 HDF 文件或相关文件格式存储,如 VCF BAM 的基因组数据。在内部,HDF5 和 NetCDF 以压缩布局存储数据。NetCDF 在气候科学和天文学等领域很受欢迎。HDF5 在 GIS 系统等领域广受欢迎。它们是不可分割的,因此不适合分布式处理(使用 Spark 这样的引擎)。
- 文件格式 : .h5 (HDF5),。nc (NetCDF)
- 特色工程:熊猫、Dask、XArray
- Training : .h5 在 TensorFlow 或 PyTorch 中没有原生阅读器;
。据我们所知,nc 没有本地阅读器。
模型文件格式
在监督机器学习中,训练后创建的用于对新数据进行预测的人工制品称为模型。例如,在训练深度神经网络(DNN)之后,训练的模型基本上是包含 DNN 中的层和权重的文件。通常,模型可以保存在一个可能被压缩的文件中,因此模型文件通常具有二进制文件格式。TensorFlow 将模型保存为协议缓冲文件,带有**。pb** 文件扩展名。Keras 将模型原生保存为 .h5 文件。Scikit-Learn 将模型保存为 pickled python 对象,带有一个**。pkl** 文件扩展名。基于 XML 的模型服务的旧格式,预测模型标记语言()。pmml ),在一些框架上仍然可用,比如 Scikit-Learn。
模型文件用于对新数据进行预测,通过(1)通常将模型作为文件读入的批处理应用程序,或(2)将模型读入内存的实时模型服务服务器(如 TensorFlow 服务服务器),甚至可能在内存中有模型的多个版本用于 AB 测试。
使用的其他模型文件格式包括 SparkML 模型,这些模型可以保存为 MLleap 文件格式,并使用 ml leap 模型服务器进行实时服务(文件打包在中)。zip 格式)。苹果公司开发了**。mlmodel** 文件格式,用于存储嵌入 iOS 应用程序的模型,作为其核心 ML 框架的一部分(该框架对 ObjectiveC 和 Swift 语言具有卓越的支持)。受过 TensorFlow、Scikit-Learn 和其他框架培训的应用程序需要将其模型文件转换为。iOS 上使用的 mlmodel 文件格式,可以使用 coremltools 和 Tensorflow converter 等工具帮助文件格式转换。ONNX 是一种独立于 ML 框架的文件格式,由微软、脸书和亚马逊支持。理论上,任何 ML 框架都应该能够将其模型导出到。onnx 文件格式,因此它为跨不同框架的统一模型服务提供了很大的希望。然而,截至 2019 年末,ONNX 并不支持最流行的 ML 框架(TensorFlow、PyTorch、Scikit-Learn)的所有操作,因此 ONNX 对于那些框架还不实用。在 PyTorch 中,推荐的服务模型的方式是使用 Torch 脚本跟踪并保存一个模型作为一个**。pt** 文件,并从 C++应用程序中提供它。
这里要提到的最后一个文件格式是 YAML,用于打包模型,作为 Spark 上 ML 管道的 MLFlow 框架的一部分。MLFlow 存储一个 YAML 文件,该文件描述了它为模型服务而打包的文件,以便部署工具可以理解模型文件格式并知道要部署什么文件。
- 文件格式:。pb,。onnx,。pkl,。mlmodel,。zip,。pmml,。pt
- 推论:。pb 文件由 TensorFlowServing 服务器提供服务;
。onnx 文件由微软的商业模式服务平台提供服务;
。pkl 文件用于 Scikit-Learn 模型,通常在 Flask 服务器上;
。mlmodel 文件由 iOS 平台提供服务;
。zip 文件用于打包在 MLeap 运行时提供的 MLeap 文件;
。pt 文件用于封装 PyTorch 模型,这些模型可以在 C++应用程序中使用。
ML 数据文件格式摘要
下表总结了不同 ML 管道阶段(特征工程/数据准备、培训和服务)的不同文件格式:
获胜者是…
用于深度学习的训练数据的文件格式中,功能最完整、语言独立且可扩展的是 petastorm 。它不仅支持高维数据,并在 TensorFlow 和 PyTorch 中具有本机读取器,而且它还可针对并行工作机进行扩展,而且它还支持下推索引扫描(仅从磁盘中读取您请求的那些列,甚至跳过文件中的值不在所请求的值范围内的文件),并可扩展到存储许多 TB 的数据。
对于模型服务,我们真的找不到任何优于其他文件格式的文件格式。部署和操作最简单的模型服务解决方案是协议缓冲区和 TensorFlow 服务服务器。虽然 ONNX 和 Torch Script 都有潜力,但服务于服务器的开源模型还不适合它们。同样,上菜。flask 服务器上的 pkl 文件虽然在生产中大量使用,但仍然需要 ML 操作工程师做更多的工作——您必须编写自己的 Python 服务程序、管理安全性、负载平衡等等。
Hopsworks 和 ML 文件格式
在本节中,我们将讨论使用 Hopsworks 功能库将 ML 功能数据转换为您选择的文件格式的支持,以及使用 HopsFS 文件系统在 Hopsworks 中对主要 ML 框架文件格式的支持。Hopsworks 是一个开源企业平台,用于大规模开发和运营机器学习(ML)管道,基于业界第一个 ML 功能商店。
用于文件格式转换的特征存储
Hopsworks 功能存储可以在您选择的数据存储(S3、HDFS、HopsFS)上以您选择的文件格式创建训练/测试数据。
Hopsworks 功能存储是一个仓库,用于存储 ML 的可重用功能。它旨在充当要素数据的缓存。特征数据是特征工程的输出,特征工程将来自后端系统的原始数据转换成可直接用于训练 ML 模型的特征。数据科学家通过浏览可用的功能与功能库进行交互,然后,在找到构建预测模型所需的功能后,他们会在自己选择的存储平台上以自己选择的文件格式生成训练/测试数据。在上图所示的示例中,我们可以看到我们有 3 个特征和一个来自 Titanic 数据集的目标变量,然后我们可以选择一种文件格式(从 10 多种可用的文件格式中)和一个将创建训练/测试数据的目标文件系统。功能存储使团队能够通过使用不同方法(例如,TensorFlow 和 PyTorch 上的深度学习和 Scikit-Learn 上的决策树)在不同框架中轻松尝试解决方案,从而轻松协作解决问题,而无需将训练/测试数据转换为各自框架的最高效、易用的文件格式。
Hopsworks 中的文件格式示例
Hopsworks 提供 HopsFS(下一代 HDFS 文件系统)作为其默认的分布式文件系统。HopsFS 是一个很好的用于机器学习的分布式文件系统,因为它具有高吞吐量和低延迟,并且在 ML 的流行框架中有广泛的原生 HDFS 阅读器:Spark、TensorFlow、Pandas (Scikit-Learn)和 PyTorch(通过 petastorm)。
这里包含了一些在 Hopsworks 中使用不同文件格式的笔记本的例子,接着是 Python 中 ML 的流行框架的具体例子(PySpark,TensorFlow/Keras,PyTorch,Scikit-Learn):
- 熊猫和霍普斯
- Numpy 和 HopsFS
- Scikit-Learn 和 HopsFS
- 使用张量流和 HopsFS 的 Tfrecords】
- 使用 PyTorch 和 HopsFS 的 Petastorm】
- 使用 TensorFlow 和 HopsFS 的 Petastorm】
在接下来的部分中,我们将简要概述主要 python ML 框架的推荐文件格式:PySpark、TensorFlow/Keras、PyTorch 和 Scikit-Learn,以及一个示例代码片段和一个来自 Hopsworks 的 python 笔记本链接。
PySpark
文件格式:。csv,。拼花地板。兽人,。json,。avro,。佩塔斯托姆
数据来源:本地文件系统,HDFS,S3
模型服务文件格式:。zip (MLeap)
柱状文件格式与 PySpark(.拼花地板。兽人,。petastorm),因为它们压缩得更好,可拆分,并支持列的选择性读取(只有那些指定的列才会从磁盘上的文件中读取)。当您需要使用 PySpark 快速编写时,经常会使用 Avro 文件,因为它们是面向行的并且是可拆分的。PySpark 可以从本地文件系统、HDFS 和 S3 数据源读取文件。
熊猫/Scikit-学习
文件格式:。csv,。npy,。拼花、. h5、。json,。xlsx
数据来源:本地文件系统,HDFS,S3
模型服务文件格式:。pkl
熊猫可以在本地读取文件。csv,。拼花、. hdf5、.json,。xlsx,也来自 SQL 源代码。熊猫可以从本地文件系统、HDFS、S3、http 和 ftp 数据源读取文件。在 Hopsworks 中,您可以使用 Panda 自带的 HDFS 阅读器和一个助手类来读取 HopsFS 中的文件:
张量流/Keras
文件格式:。csv,。npy,。tfrecords,。佩塔斯托姆
数据来源:本地文件系统,S3 HDFS
模型服务文件格式:。平装书
Tensorflow 的原生文件格式是。如果您的数据集不是很大,并且您不需要从数据集中只读取列的子集,那么这是我们推荐的文件格式。但是,如果您只想从数据集中读取列的子集(数据库术语中的投影),那么。petastorm 是要使用的文件格式。TensorFlow 可以从本地文件系统、HDFS 和 S3 数据源读取文件。
PyTorch
培训文件格式:。csv,。npy,。佩塔斯托姆
数据来源:本地文件系统,HDFS ( petastorm),S3
模型服务文件格式:。元素铂的符号
PyTorch 与 Numpy 紧密集成,并且。npy 是 PyTorch 的本地文件格式。然而,np.load()本身并不与 HopsFS 一起工作,所以您必须使用我们在库中包含的包装器函数,该函数首先将来自 HopsFS 的数据具体化到本地文件系统,然后将其作为 numpy 数组读入。如果您有大型数据集,我们建议使用。petastorm 通过自己的阅读器与 PyTorch 一起工作。
Numpy/Scikit-Learn
文件格式:。神经肽 y
数据来源:本地文件系统
模型服务文件格式:。pkl
参考
https://www.neonscience.org/about-hdf5
https://www.tensorflow.org/tfx/transform/get_started
https://www.logicalclocks.com/featurestore
[TF records]https://medium . com/mosely-ai/tensor flow-records-what-them-and-how-to-use-them-c 46 BC 4 BBB 564
https://luminousmen.com/post/big-data-file-formats
【PETA storm】https://qcon . ai/system/files/presentation-slides/yevgeni - PETA storm _ 16 日 _2019 年 4 月 _ 日。pdf
初学者财务报表分析指南
很多刚入门财务的人,经常会觉得处理财务报表是一件很头疼的事情。其实做财务报表分析,只需要掌握“思路+内容+工具”这个公式就可以了。明确报表分析的思路,知道分析什么,确定指标,最后选择好的报表工具,达到最终的分析结果。
1.财务报表分析的目的
不同的人出于不同的目的进行财务分析,但共同的目的是从财务报表中获取对其经济决策有用的信息。因此,财务报表分析的对象有三个:财务状况、经营成果、现金流量。基于此,我们需要做的偿债能力分析、盈利能力分析和营运能力分析构成了财务报表分析的总体框架。
比如企业主管部门、母公司、财务部门重点分析检查企业相关资源的配置情况、对财经政策和财务制度的遵守情况、资本保值增值情况等。
投资者重点分析盈利能力、运营能力和资金使用情况,了解投资收益和投资风险。
债权人重点分析企业的偿债能力,评价企业的财务安全或风险程度,等等。
考虑到内部管理的不同要求,财务报表分析的内容非常广泛。它有助于报表使用者总结和评价企业的财务状况和经营成果,为经济预测和决策提供可靠的依据。
2.财务报表分析的思路
2.1 基本思想
- 捕获
报表每一项的具体数据只是表面,结构(各种比率或指标)是骨架,趋势才是核心。结构比价值更重要,趋势比结构更重要。
- 比较
财务报表只有通过比较阅读才有意义。
- 掌握
各种会计原则都有天然的局限性。不能局限于报告分析就妄下结论。
2.2 分析方法
- 结构分析
理清报表的各种核对关系,这是基本功。
对报表结构进行横向比较,找出与同业公司的主要指标差异并分析原因。重要的指标有毛利率、净利润率、∑经营活动现金流量/∑销售收入、销售收入/固定资产、流动资产/非流动资产、存货/固定资产、负债/总资产等等。不必拘泥于课本上的经典指标。根据行业特点创建自己的比率。
结构差异罗列出来之后,就需要从竞争力、产品细分、商业模式、规模、地域等方面进行推理。如果没有正确的理由,我们可能会怀疑报告的真实性。
- 趋势分析
趋势分析的重要内容是资产、收入、利润。
分析资产的增加是来自债务还是权益(利润还是股东投入)。此外,关注每个资产账户比例的变化,这往往反映了企业模式的变化。
弄清楚收入的增加是因为合并范围的扩大还是自身业务的扩大。并关注毛利率和市场份额的变化。总的来说,在毛利率小幅度波动的前提下,市场份额的逐步提升是最可靠、最可持续的情况。
利润的增加应该是综合资产和收入增长的逻辑推理,但利润经过多次加减后在报表末尾,客观性最弱。要辩证地认识权责发生制的缺陷和漏洞。
你要考虑资产和收入的增加来分析利润的增加。但是经过一系列的数据操作,利润是最不客观的。你应该深入了解权责发生制的缺陷和弱点,然后辩证地分析利润。
3.三大财务报表的内容
3.1 资产负债表
资产负债表主要告诉我们公司的资产和负债在那种现状下是怎样的。所以,报告的关键是看到的时间。而且时间对报告影响很大。最重要的检验关系是负债加权益等于资产。在会计上,我目前拥有的叫资产,借来的钱叫负债,自己的钱叫股权。
3.2 利润表
损益表或利润表主要告诉我们公司在一段时间内的利润和亏损。利润表的重点是看这个周期有多长,一般是一个月,一个季度或者一年。在损益表中,最重要的核对关系是收入减去成本等于利润。
3.3 现金流量表
现金流量表主要告诉我们公司在一段时间内收到了多少现金,付出了多少现金,银行里还剩多少现金。这个报表的关键也是看这个周期有多长,和利润表一样。现金流量表最重要的核对关系是现金流入减去现金流出等于剩余现金。这个关系也很简单,就不多解释了。
Cash Flow Analysis Made with FineReport
4.财务报表分析工具
如果数据量不够大,不能用数据库,可以用 excel 做财务报表。当然,如果你写的是 VB 语言,excel 也可以连接数据库。专业统计软件如 SPSS 、 SAS 、 Stata 适用于线性回归、f 统计、抽样、假设检验等。
但是,如果财务分析涉及到数据库,就要选择专业的软件。首先,Excel 对数据的处理性能有限,很难实现数据的实时更新。在具体报表工具的选择上, PowerBI 、 Tableau 、 Crystal Repor t、 Qlikview 和 FineReport 都是不错的选择。下面我使用零编码工具 FineReport 来演示各种财务报告风格。FineReport 采用的是拖拽操作,类似 excel 的界面,财务新手很容易上手。比如我们可以用 FineReport 做一个仪表盘,形成一个财务管理驾驶舱。操作是拖拽数据字段生成分析图表,合并成一个主题分析。
财务管理仪表板
标准福利审查
杜邦分析
每日运费
产品成本分析
2020 年指导如何学习和掌握计算机视觉
这篇文章将关注资源,我相信这将最大程度地提高你在计算机视觉方面的知识,并且主要基于我自己的经验。
在开始学习计算机视觉之前,了解机器学习和 python 的基础知识将会很有帮助。
看看我的机器和深度学习博客https://diyago.github.io/
结构
Star Wars: Luke Skywalker & Darth Vader
你不必一开始就选择它,但应用新获得的知识是必要的。
没有太多可选项: pytorch 或者keras(tensor flow)。Pytorch 可能需要编写更多的代码,但是它提供了很大的灵活性,所以请使用它。除此之外,大部分深度学习的研究者开始使用 pytoch。
albumination(图像增强)和 catalyst (框架,pytorch 上面的高级 API)可能也有用,用它们吧,尤其是第一个。
五金器具
- Nvidia GPU 10xx+会绰绰有余(300 美元以上)
- Kaggle 内核 —每周仅 30 小时(免费)
- Google Colab — 12 小时会话限制,未知周限制(免费)
理论&实践
在线课程
- CS231n 是顶级在线,涵盖了计算机视觉中所有必要的基础知识。Youtube 在线视频。他们甚至有练习,但我不能建议解决它们。(免费)
- Fast.ai 是你应该注意的下一道菜。还有,fast.ai 是 pytorch 上面的高层框架,但是他们改变自己的 API 太频繁,文档的缺乏让它用起来不靠谱。然而,理论和有用的技巧只是花时间观看本课程的幻想。(免费)
在学习这些课程的时候,我鼓励你将理论付诸实践,将它应用到一个框架中。
商品和编码
- ArXiv.org——所有最近的信息都会在这里。(免费)
- https://paperswithcode.com/sota——最常见的深度学习任务的最新水平,不仅仅是计算机视觉。(免费)
- Github —如果有什么东西被实现了,你可以在这里找到它。(免费)
书
没什么可读的,但我相信这两本书会有用,不管你选择用 pytorch 还是 keras
- 用 Python 进行深度学习Keras 创造者、谷歌人工智能研究员弗朗索瓦·乔莱(Franç ois Chollet)。易于使用,并可能获得一些你以前不知道的洞察力。(不免费)
- py torch 深度学习py torch 团队 Eli Stevens & Luca Antiga(免费)
卡格尔
竞赛 — kaggle 是一个知名的在线平台,提供各种机器学习竞赛,其中许多都是关于计算机视觉的。您甚至可以在没有完成课程的情况下开始参与,因为从比赛开始,将会有许多开放的内核(端到端代码),您可以直接从浏览器运行这些内核。(免费)
强硬(绝地)方式
Star Wars`s Jedi: Yoda
另一条路可能会很艰难,但你将获得所需的知识,不仅可以进行拟合预测,还可以进行自己的研究。谢尔盖·别洛乌索夫又名贝斯。
你只需要阅读并实现下面所有的文章(免费)。光是阅读它们也会很棒。
结构
- Alex net:https://papers . nips . cc/paper/4824-imagenet-class ification-with-deep-convolutional-neural-networks
- ZF net:https://arxiv.org/abs/1311.2901
- vgg 16:https://arxiv.org/abs/1505.06798
- ResNet:https://arxiv.org/abs/1704.06904
- Google net:https://arxiv.org/abs/1409.4842
- Inception:https://arxiv.org/abs/1512.00567
语义分割
- FCN: https://arxiv.org/abs/1411.4038
- SegNet: https://arxiv.org/abs/1511.00561
- UNET: https://arxiv.org/abs/1505.04597
- PSPNet: https://arxiv.org/abs/1612.01105
- DeepLab: https://arxiv.org/abs/1606.00915
- ICNet: https://arxiv.org/abs/1704.08545 * ENT: https://arxiv.org/abs/1
生成对抗网络 Generative adversarial Networks
- GAN: https://arxiv.org/abs/1406.2661
- DCGAN: https://arxiv.org/abs/1511.06434
- WGAN: https://arxiv.org/abs/1701.07875
- Pix2Pix: https://arxiv.org/abs/1611.07004
- CycleGAN: https://arxiv.org/abs/1703.10593
对象检测 Object Detection
- RCNN: https://arxiv.org/abs/1311.2524
- Fast-RCNN: https://arxiv.org/abs/1504.08083
- Faster-RCNN: https://arxiv.org/abs/1506.01497
- SSD: https://arxiv.org/abs/1512.02325
- YOLO: https://arxiv.org/abs/1506.02640 * YOLO9000: https://arxiv.org/abs/1612.08242
实例 Segmentation
- Mask-RCNN: https://arxiv.org/abs/1703.06870
- YOLACT: https://arxiv.org/abs/1904.02689
姿势估计
- PoseNet: https://arxiv.org/abs/1505.07427
*DensePose:https://arxiv.org/abs/1802.00434
一本 Jupyter 笔记本中的 R 和 Python 指南
当你可以同时使用两者时,为什么要选择一个?
r 主要用于统计分析,而 Python 为数据科学提供了更通用的方法。r 和 Python 是面向对象面向数据科学的编程语言。学习这两者是一个理想的解决方案。Python 是一种具有可读语法的通用语言。——
本文基于哈佛大学 AC209b 讲座,大部分内容由 IACS 大学的威尔·克莱博撰写和教授。
R 和 Python 用户之间的战争已经肆虐了好几年。由于大多数老派的统计学家都是在 R 上接受培训的,而且大多数大学的计算机科学和数据科学系都更喜欢 Python,所以两者都有利有弊。我在实践中注意到的主要缺点是每种语言都有可用的软件包。
截至 2019 年,聚类分析和样条的 R 包优于同类型的 Python 包。在本文中,我将通过编码示例向您展示如何获取 R 函数和数据集,然后在基于 Python 的 Jupyter 笔记本中导入和利用它们。
本文的主题是:
- 导入(基本)R 函数
- 导入 R 库函数
- 填充向量 R 理解
- 填充数据帧 R 理解
- 填充公式 R 理解
- R 中的运行模式
- 将结果返回给 Python
- 获取 R 中的模型预测
- 在 R 中绘图
- 阅读 R 的文档
在我的 GitHub 页面上可以找到这篇文章的附带笔记本。
这个存储库包含与我的媒体文章相关的代码相关内容。此存储库是主存储库…
github.com](https://github.com/mrdragonbear/Articles)*
线性/多项式回归
首先,我们将看看使用导入的 R 函数执行基本的线性和多项式回归。我们将研究一个关于糖尿病的数据集,其中包含 C 肽浓度和酸度变量的信息。不要担心模型的内容,这是广义可加模型领域中一个常用的例子,我们将在本文的后面讨论。
*diab = pd.read_csv("data/diabetes.csv")print("""
# Variables are:
# subject: subject ID number
# age: age diagnosed with diabetes
# acidity: a measure of acidity called base deficit
# y: natural log of serum C-peptide concentration
#
# Original source is Sockett et al. (1987)
# mentioned in Hastie and Tibshirani's book
# "Generalized Additive Models".
""")display(diab.head())
display(diab.dtypes)
display(diab.describe())*
然后我们可以绘制数据:
*ax0 = diab.plot.scatter(x='age',y='y',c='Red',title="Diabetes data") #plotting direclty from pandas!
ax0.set_xlabel("Age at Diagnosis")
ax0.set_ylabel("Log C-Peptide Concentration");*
用statsmodel
进行线性回归。你可能需要安装这个包来遵循代码,你可以用pip install statsmodel
来完成。
- 在 Python 中,我们从目标值的向量和我们自己构建的设计矩阵(例如,从多项式特征)开始工作。
- 现在,
statsmodel
的公式界面可以帮助您构建目标值和设计矩阵。
*#Using statsmodels
import statsmodels.formula.api as sm
model1 = sm.ols('y ~ age',data=diab)
fit1_lm = model1.fit()*
现在,我们构建一个数据框架来预测值(有时这只是测试或验证集)
- 对于制作模型预测的漂亮图表非常有用-预测大量值,而不仅仅是训练集中的任何值
*x_pred = np.linspace(0,16,100)
predict_df = pd.DataFrame(data={"age":x_pred})
predict_df.head()*
使用get_prediction(<data>).summary_frame()
获得模型的预测(和误差线!)
*prediction_output = fit1_lm.get_prediction(predict_df).summary_frame()
prediction_output.head()*
绘制模型和误差线
*ax1 = diab.plot.scatter(x='age',y='y',c='Red',title="Diabetes data with least-squares linear fit")
ax1.set_xlabel("Age at Diagnosis")
ax1.set_ylabel("Log C-Peptide Concentration")
ax1.plot(predict_df.age, prediction_output['mean'],color="green")
ax1.plot(predict_df.age, prediction_output['mean_ci_lower'], color="blue",linestyle="dashed")
ax1.plot(predict_df.age, prediction_output['mean_ci_upper'], color="blue",linestyle="dashed");
ax1.plot(predict_df.age, prediction_output['obs_ci_lower'], color="skyblue",linestyle="dashed")
ax1.plot(predict_df.age, prediction_output['obs_ci_upper'], color="skyblue",linestyle="dashed");*
我们还可以拟合三次多项式模型,并以两种方式绘制模型误差线:
- Route1:为
age
、age**2
、age**3
各建一个设计 df
*fit2_lm = sm.ols(formula="y ~ age + np.power(age, 2) + np.power(age, 3)",data=diab).fit()
poly_predictions = fit2_lm.get_prediction(predict_df).summary_frame()
poly_predictions.head()*
- 方法 2:编辑公式
*ax2 = diab.plot.scatter(x='age',y='y',c='Red',title="Diabetes data with least-squares cubic fit")
ax2.set_xlabel("Age at Diagnosis")
ax2.set_ylabel("Log C-Peptide Concentration")
ax2.plot(predict_df.age, poly_predictions['mean'],color="green")
ax2.plot(predict_df.age, poly_predictions['mean_ci_lower'], color="blue",linestyle="dashed")
ax2.plot(predict_df.age, poly_predictions['mean_ci_upper'], color="blue",linestyle="dashed");
ax2.plot(predict_df.age, poly_predictions['obs_ci_lower'], color="skyblue",linestyle="dashed")
ax2.plot(predict_df.age, poly_predictions['obs_ci_upper'], color="skyblue",linestyle="dashed");*
这没有使用 R 编程语言的任何特性。现在,我们可以使用 r 中的函数重复分析。
线性/多项式回归,但使其为 R
在这一节之后,我们将了解使用 R 模型所需的一切。实验室的其余部分只是应用这些概念来运行特定的模型。因此,这一节是你在 r 中工作的“备忘单”。
我们需要知道的是:
- 导入(基本)R 函数
- 导入 R 库函数
- 填充向量 R 理解
- 填充 R 理解的数据帧
- 填充 R 理解的公式
- 在 R 中运行模型
- 将结果返回给 Python
- 在 R 中获取模型预测
- 在 R 中绘图
- 阅读 R 的文档
导入 R 函数
为了导入 R 函数,我们需要rpy2
包。根据您的环境,您可能还需要指定 R 主目录的路径。下面我举了一个例子来说明如何指定这一点。
*# if you're on JupyterHub you may need to specify the path to R
#import os
#os.environ['R_HOME'] = "/usr/share/anaconda3/lib/R"
import rpy2.robjects as robjects*
要指定一个 R 函数,只需使用robjects.r
后跟方括号中的包名作为字符串。为了防止混淆,我喜欢对从 r 导入的函数、库和其他对象使用r_
。
*r_lm = robjects.r["lm"]
r_predict = robjects.r["predict"]
#r_plot = robjects.r["plot"] # more on plotting later
#lm() and predict() are two of the most common functions we'll use*
导入 R 库
我们可以导入单个函数,但也可以导入整个库。要导入整个库,您可以从rpy2.robjects.packages
中提取importr
包。
*from rpy2.robjects.packages import importr
#r_cluster = importr('cluster')
#r_cluster.pam;*
填充向量 R 理解
要指定一个可以与 Python 包接口的浮点向量,我们可以使用robjects.FloatVector
函数。这个函数的参数引用了您希望转换成 R 对象的数据数组,在我们的例子中,是来自糖尿病数据集中的age
和y
变量。
*r_y = robjects.FloatVector(diab['y'])
r_age = robjects.FloatVector(diab['age'])
# What happens if we pass the wrong type?
# How does r_age display?
# How does r_age print?*
填充数据帧 R 理解
我们可以指定单独的向量,也可以指定整个数据帧。这是通过使用robjects.DataFrame
功能完成的。这个函数的参数是一个字典,它指定了名称和与名称相关的向量(从robjects.FloatVector
获得)。
*diab_r = robjects.DataFrame({"y":r_y, "age":r_age})
# How does diab_r display?
# How does diab_r print?*
填充公式 R 理解
例如,要指定一个回归公式,我们可以使用robjects.Formula
函数。这遵循 R 语法dependent variable ~ independent variables
。在我们的例子中,输出y
被建模为age
变量的函数。
*simple_formula = robjects.Formula("y~age")
simple_formula.environment["y"] = r_y #populate the formula's .environment, so it knows what 'y' and 'age' refer to
simple_formula.environment["age"] = r_age*
注意,在上面的公式中,我们必须指定与公式中每个变量相关的 FloatVector。我们必须这样做,因为公式不会自动将我们的变量名与我们之前指定的变量相关联——它们还没有与robjects.Formula
对象相关联。
R 中的运行模式
要指定一个模型,在本例中是一个使用我们之前导入的r_lm
函数的线性回归模型,我们需要将我们的公式变量作为参数传递(除非我们传递一个 R 公式对象,否则这将不起作用)。
*diab_lm = r_lm(formula=simple_formula) # the formula object is storing all the needed variables*
我们可以在公式本身中引用数据集,而不是指定与robjects.Formula
对象相关的每个单独的浮点向量(只要它已经成为 R 对象本身)。
*simple_formula = robjects.Formula("y~age") # reset the formula
diab_lm = r_lm(formula=simple_formula, data=diab_r) #can also use a 'dumb' formula and pass a dataframe*
将结果返回给 Python
使用 R 函数和库是很棒的,但是我们也可以分析我们的结果,并将它们返回给 Python 进行进一步的处理。要查看输出:
*diab_lm #the result is already 'in' python, but it's a special object*
我们还可以检查输出中的名称:
*print(diab_lm.names) # view all names*
以我们输出的第一个元素为例:
*diab_lm[0] #grab the first element*
要计算系数:
*diab_lm.rx2("coefficients") #use rx2 to get elements by name!*
要将系数放入 Numpy 数组中:
*np.array(diab_lm.rx2("coefficients")) #r vectors can be converted to numpy (but rarely needed)*
得到预测
为了使用我们的 R 模型获得预测,我们可以创建一个预测数据帧并使用r_predict
函数,类似于使用 Python 的方式。
*# make a df to predict on (might just be the validation or test dataframe)
predict_df = robjects.DataFrame({"age": robjects.FloatVector(np.linspace(0,16,100))})# call R's predict() function, passing the model and the data
predictions = r_predict(diab_lm, predict_df)*
我们可以使用rx2
函数提取“年龄”值:
*x_vals = predict_df.rx2("age")*
我们还可以使用 Python 绘制数据:
*ax = diab.plot.scatter(x='age',y='y',c='Red',title="Diabetes data")
ax.set_xlabel("Age at Diagnosis")
ax.set_ylabel("Log C-Peptide Concentration");ax.plot(x_vals,predictions); #plt still works with r vectors as input!*
我们也可以使用 R 来绘图,尽管这稍微复杂一些。
在 R 中绘图
要在 R 中绘图,我们需要使用以下命令打开%R magic 函数:
*%load_ext rpy2.ipython*
- 以上开启了%R“魔法”。
- r 的 plot()命令根据您传递给它的内容做出不同的响应;不同的模式得到不同的剧情!
- 对于任何特定的模型,搜索 plot.modelname。例如,对于 GAM 模型,搜索
plot.gam
以获得绘制 GAM 模型的任何细节。 %R
“magic”在“笔记本”模式下运行 R 代码,所以数字显示得很好- 在
plot(<model>)
代码之前,我们传入 R 需要了解的变量(-i
代表“输入”)
*%R -i diab_lm plot(diab_lm);*
阅读 R 的文档
lm()
功能的文档在这里是,一个更漂亮的版本(相同内容)在这里是。谷歌搜索时,尽可能选择 rdocumentation.org。部分:
- 用法:给出函数签名,包括所有可选参数
- 参数:每个功能输入控制什么
- 细节:关于函数做什么以及参数如何交互的附加信息。经常从正确的地方开始阅读
- 值:函数返回的对象的结构
- 参考文献:相关学术论文
- 参见:其他感兴趣的功能
示例
作为测试我们新获得的知识的例子,我们将尝试以下内容:
- 将 R 中计算的置信区间添加到上面的线性回归图中。使用
interval=
参数到r_predict()
(文档此处)。你必须处理一个由 r 返回的矩阵。 - 用一个 5 次多项式拟合 r 中的糖尿病数据。在网上搜索一个比用所有 5 个多项式项写出一个公式更简单的方法。
置信区间:
*CI_matrix = np.array(r_predict(diab_lm, predict_df, interval="confidence"))
ax = diab.plot.scatter(x='age',y='y',c='Red',title="Diabetes data")
ax.set_xlabel("Age at Diagnosis")
ax.set_ylabel("Log C-Peptide Concentration");
ax.plot(x_vals,CI_matrix[:,0], label="prediction")
ax.plot(x_vals,CI_matrix[:,1], label="95% CI", c='g')
ax.plot(x_vals,CI_matrix[:,2], label="95% CI", c='g')
plt.legend();*
五次多项式:
*ploy5_formula = robjects.Formula("y~poly(age,5)") # reset the formula
diab5_lm = r_lm(formula=ploy5_formula, data=diab_r) #can also use a 'dumb' formula and pass a dataframe
predictions = r_predict(diab5_lm, predict_df, interval="confidence")
ax = diab.plot.scatter(x='age',y='y',c='Red',title="Diabetes data")
ax.set_xlabel("Age at Diagnosis")
ax.set_ylabel("Log C-Peptide Concentration");
ax.plot(x_vals,predictions);*
洛斯平滑
现在我们知道了如何在 Python 中使用 R 对象和函数,我们可以看看我们可能想要这样做的情况。第一个例子是 Lowess 平滑。
Lowess smoothing 在 Python 和 r 中都实现了。我们将在转换语言时使用它作为另一个例子。
Python
在 Python 中,我们使用statsmodel.nonparametric.smoothers_lowess
来执行 lowess 平滑。
*from statsmodels.nonparametric.smoothers_lowess import lowess as lowessss1 = lowess(diab['y'],diab['age'],frac=0.15)
ss2 = lowess(diab['y'],diab['age'],frac=0.25)
ss3 = lowess(diab['y'],diab['age'],frac=0.7)
ss4 = lowess(diab['y'],diab['age'],frac=1)ss1[:10,:] # we get back simple a smoothed y value for each x value in the data*
请注意绘制不同模型的清晰代码。一会儿我们会看到更干净的代码。
*for cur_model, cur_frac in zip([ss1,ss2,ss3,ss4],[0.15,0.25,0.7,1]): ax = diab.plot.scatter(x='age',y='y',c='Red',title="Lowess Fit, Fraction = {}".format(cur_frac))
ax.set_xlabel("Age at Diagnosis")
ax.set_ylabel("Log C-Peptide Concentration")
ax.plot(cur_model[:,0],cur_model[:,1],color="blue")
plt.show()*
R
要在 R 中实现 Lowess 平滑,我们需要:
- 导入黄土功能。
- 把数据发给 r。
- 调用函数并获得结果。
*r_loess = robjects.r['loess.smooth'] #extract R function
r_y = robjects.FloatVector(diab['y'])
r_age = robjects.FloatVector(diab['age'])ss1_r = r_loess(r_age,r_y, span=0.15, degree=1)ss1_r #again, a smoothed y value for each x value in the data*
可变跨度
接下来,一些非常干净的代码,以适应和绘制具有各种参数设置的模型。(尽管之前看到的zip()
方法在标签和参数不同时非常有用)
*for cur_frac in [0.15,0.25,0.7,1]:
cur_smooth = r_loess(r_age,r_y, span=cur_frac) ax = diab.plot.scatter(x='age',y='y',c='Red',title="Lowess Fit, Fraction = {}".format(cur_frac))
ax.set_xlabel("Age at Diagnosis")
ax.set_ylabel("Log C-Peptide Concentration")
ax.plot(cur_smooth[0], cur_smooth[1], color="blue")
plt.show()*
我们要看的下一个例子是平滑样条,Python 不太支持这些模型,所以最好使用 R 函数。
平滑样条
从现在开始,我们将使用 R 函数;Python 不(很好地)支持这些模型。
为了清楚起见:这是一个奇特的样条模型
跨越所有可能的功能 f 。获胜者将始终是一个连续的三次多项式,在每个数据点都有一个结。
需要考虑的一些事情是:
- 知道为什么赢家是立方吗?
- 这个模型的可解释性如何?
- 有哪些可调参数?
为了实现平滑样条,我们只需要两条线。
*r_smooth_spline = robjects.r['smooth.spline'] #extract R function# run smoothing function
spline1 = r_smooth_spline(r_age, r_y, spar=0)*
平滑样条交叉验证
r 的smooth_spline
函数有一个内置的交叉验证来为 lambda 找到一个好的值。参见包文档。
*spline_cv = r_smooth_spline(r_age, r_y, cv=True) lambda_cv = spline_cv.rx2("lambda")[0]ax19 = diab.plot.scatter(x='age',y='y',c='Red',title="smoothing spline with $\lambda=$"+str(np.round(lambda_cv,4))+", chosen by cross-validation")
ax19.set_xlabel("Age at Diagnosis")
ax19.set_ylabel("Log C-Peptide Concentration")
ax19.plot(spline_cv.rx2("x"),spline_cv.rx2("y"),color="darkgreen")*
自然样条和基本样条
这里,我们在模型复杂性上后退了一步,但在编码复杂性上前进了一步。我们将再次使用 R 的公式接口,所以我们需要填充公式和数据框架。
更多值得思考的问题:
- 自然样条和基本样条在哪些方面不如我们刚刚使用的样条复杂?
- 是什么让样条曲线变得“自然”?
- 什么使样条成为“基础”?
- 调优参数是什么?
*#We will now work with a new dataset, called GAGurine.
#The dataset description (from the R package MASS) is below:
#Data were collected on the concentration of a chemical GAG
# in the urine of 314 children aged from zero to seventeen years.
# The aim of the study was to produce a chart to help a paediatrican
# to assess if a child's GAG concentration is ‘normal’.#The variables are:
# Age: age of child in years.
# GAG: concentration of GAG (the units have been lost).*
首先,我们导入并绘制数据集:
*GAGurine = pd.read_csv("data/GAGurine.csv")
display(GAGurine.head())
ax31 = GAGurine.plot.scatter(x='Age',y='GAG',c='black',title="GAG in urine of children")
ax31.set_xlabel("Age");
ax31.set_ylabel("GAG");*
标准的东西:导入函数,将变量转换成 R 格式,调用函数
*from rpy2.robjects.packages import importr
r_splines = importr('splines')# populate R variables
r_gag = robjects.FloatVector(GAGurine['GAG'].values)
r_age = robjects.FloatVector(GAGurine['Age'].values)
r_quarts = robjects.FloatVector(np.quantile(r_age,[.25,.5,.75])) #woah, numpy functions run on R objects*
当我们从 r_splines 调用 ns 或 bs 函数时会发生什么?
*ns_design = r_splines.ns(r_age, knots=r_quarts)
bs_design = r_splines.bs(r_age, knots=r_quarts)print(ns_design)*
ns
和bs
返回设计矩阵,而不是模型对象!这是因为它们应该与lm
的公式接口一起工作。为了得到一个模型对象,我们填充一个包含ns(<var>,<knots>)
的公式,并拟合数据。
*r_lm = robjects.r['lm']
r_predict = robjects.r['predict']
# populate the formula
ns_formula = robjects.Formula("Gag ~ ns(Age, knots=r_quarts)")
ns_formula.environment['Gag'] = r_gag
ns_formula.environment['Age'] = r_age
ns_formula.environment['r_quarts'] = r_quarts
# fit the model
ns_model = r_lm(ns_formula*
像往常一样预测:构建一个数据框架进行预测并调用predict()
。
*# predict
predict_frame = robjects.DataFrame({"Age": robjects.FloatVector(np.linspace(0,20,100))})ns_out = r_predict(ns_model, predict_frame)ax32 = GAGurine.plot.scatter(x='Age',y='GAG',c='grey',title="GAG in urine of children")
ax32.set_xlabel("Age")
ax32.set_ylabel("GAG")
ax32.plot(predict_frame.rx2("Age"),ns_out, color='red')
ax32.legend(["Natural spline, knots at quartiles"]);*
例题
让我们看两个实现基样条的例子。
- 用相同的结拟合一个基本样条模型,并将其添加到上面的图中。
*bs_formula = robjects.Formula("Gag ~ bs(Age, knots=r_quarts)")
bs_formula.environment['Gag'] = r_gag
bs_formula.environment['Age'] = r_age
bs_formula.environment['r_quarts'] = r_quarts
bs_model = r_lm(bs_formula)
bs_out = r_predict(bs_model, predict_frame)ax32 = GAGurine.plot.scatter(x='Age',y='GAG',c='grey',title="GAG in urine of children")
ax32.set_xlabel("Age")
ax32.set_ylabel("GAG")
ax32.plot(predict_frame.rx2("Age"),ns_out, color='red')
ax32.plot(predict_frame.rx2("Age"),bs_out, color='blue')
ax32.legend(["Natural spline, knots at quartiles","B-spline, knots at quartiles"]);*
2.在[2,4,6…14,16]处用 8 个节点拟合一个基本样条,并将其添加到上面的图中。
*overfit_formula = robjects.Formula("Gag ~ bs(Age, knots=r_quarts)")
overfit_formula.environment['Gag'] = r_gag
overfit_formula.environment['Age'] = r_age
overfit_formula.environment['r_quarts'] = robjects.FloatVector(np.array([2,4,6,8,10,12,14,16]))
overfit_model = r_lm(overfit_formula)
overfit_out = r_predict(overfit_model, predict_frame)ax32 = GAGurine.plot.scatter(x='Age',y='GAG',c='grey',title="GAG in urine of children")
ax32.set_xlabel("Age")
ax32.set_ylabel("GAG")
ax32.plot(predict_frame.rx2("Age"),ns_out, color='red')
ax32.plot(predict_frame.rx2("Age"),bs_out, color='blue')
ax32.plot(predict_frame.rx2("Age"),overfit_out, color='green')
ax32.legend(["Natural spline, knots at quartiles", "B-spline, knots at quartiles", "B-spline, lots of knots"]);*
GAMs
最后,我们来看看我们最先进的模型。这里的编码并不比我们以前做的更复杂,尽管幕后工作很棒。
首先,让我们得到我们的多元数据。
*kyphosis = pd.read_csv("data/kyphosis.csv")print("""
# kyphosis - wherther a particular deformation was present post-operation
# age - patient's age in months
# number - the number of vertebrae involved in the operation
# start - the number of the topmost vertebrae operated on""")
display(kyphosis.head())
display(kyphosis.describe(include='all'))
display(kyphosis.dtypes)#If there are errors about missing R packages, run the code below:
#r_utils = importr('utils')
#r_utils.install_packages('codetools')
#r_utils.install_packages('gam')*
为了适应游戏,我们
- 导入
gam
库 - 在我们想要平滑的变量上填充包含
s(<var>)
的公式。 - 调用
gam(formula, family=<string>)
,其中family
是一个命名概率分布的字符串,根据响应变量被认为如何出现来选择。
粗略的family
指导方针:
- 响应是二进制的或“M 次尝试中的 N 次”,例如,患疾病的实验鼠(10 只中的)数量:选择
"binomial"
- 响应是没有逻辑上限的计数,例如售出的冰淇淋数量:选择
"poisson"
- 响应是真实的,有正态分布的噪声,如人的身高:选择
"gaussian"
(默认)
*#There is a Python library in development for using GAMs (https://github.com/dswah/pyGAM)
# but it is not yet as comprehensive as the R GAM library, which we will use here instead.
# R also has the mgcv library, which implements some more advanced/flexible fitting methods
r_gam_lib = importr('gam')
r_gam = r_gam_lib.gam
r_kyph = robjects.FactorVector(kyphosis[["Kyphosis"]].values)
r_Age = robjects.FloatVector(kyphosis[["Age"]].values)
r_Number = robjects.FloatVector(kyphosis[["Number"]].values)
r_Start = robjects.FloatVector(kyphosis[["Start"]].values)
kyph1_fmla = robjects.Formula("Kyphosis ~ s(Age) + s(Number) + s(Start)")
kyph1_fmla.environment['Kyphosis']=r_kyph
kyph1_fmla.environment['Age']=r_Age
kyph1_fmla.environment['Number']=r_Number
kyph1_fmla.environment['Start']=r_Start
kyph1_gam = r_gam(kyph1_fmla, family="binomial")*
拟合的 gam 模型包含许多有趣的数据:
*print(kyph1_gam.names)*
还记得密谋吗?在 gam 模型上调用 R 的plot()
是查看拟合样条的最简单方法
在[ ]:
*%R -i kyph1_gam plot(kyph1_gam, residuals=TRUE,se=TRUE, scale=20);*
预测像正常情况一样工作(建立一个数据框进行预测,如果您还没有数据框,并调用predict()
)。但是,“预测”总是报告单个变量效果的总和。如果family
为非默认,这可能与该点的实际预测不同。
例如,我们正在进行“逻辑回归”,因此原始预测是对数概率,但我们可以通过使用 in predict(..., type="response")
获得概率
*kyph_new = robjects.DataFrame({'Age': robjects.IntVector((84,85,86)),
'Start': robjects.IntVector((5,3,1)),
'Number': robjects.IntVector((1,6,10))})print("Raw response (so, Log odds):")
display(r_predict(kyph1_gam, kyph_new))
print("Scaled response (so, probabilty of kyphosis):")
display(r_predict(kyph1_gam, kyph_new, type="response"))*
最终意见
一旦您熟悉了这个过程,在 Python 中使用 R 函数就相对容易了,如果您需要使用 R 包来执行数据分析,或者您是一个已经获得了 R 代码的 Python 用户,那么它可以省去很多麻烦。
我希望你喜欢这篇文章,并发现它的信息和有用的。对于那些希望在 Jupyter 环境中体验 R 和 Python 函数和对象之间的接口的人来说,这本笔记本中使用的所有代码都可以在我的 GitHub 页面上找到。
时事通讯
关于新博客文章和额外内容的更新,请注册我的时事通讯。
丰富您的学术之旅,加入一个由科学家,研究人员和行业专业人士组成的社区,以获得…
mailchi.mp](https://mailchi.mp/6304809e49e7/matthew-stewart)*
制导摄像头坏了。显著图的健全性检查
某些理解 CNN 在看什么的技术不起作用。它们与模型的权重或训练数据没有关系,可能仅仅充当边缘检测器。
在本帖中,我们将讨论 NeurIPS 2018 年的论文“显著性图的健全性检查”,该论文证明了几种流行的显著性图方法实际上并没有提供对模型正在做什么的洞察。具有随机权重的模型和基于具有随机标签的数据训练的模型仍然会对某些显著性图技术产生看起来令人信服的“解释”,包括导向梯度图和导向反向传播,这意味着这些显著性图方法与模型的参数或训练数据无关。
论文
下面的文章应用了几个聪明的健全性检查来确定特定的技术是否提供了对模型的洞察:
Adebayo J,Gilmer J,Muelly M,Goodfellow I,Hardt M,Kim B .显著图的健全性检查。神经信息处理系统进展 2018(第 9505–9515 页)。
除非另有说明,本文中的任何引用都来自本文。
CNN 显著图(热图)技术
以下是本文评估的显著图技术:
- 渐变:在这种技术中,我们可视化每个输入像素的变化对最终预测的改变程度。梯度是分数相对于输入图像的导数,有时被称为“显著性”或“反向传播”有关更多详细信息,请参见 CNN 热点图:显著性/反向传播和 CNN 热点图:梯度与去显著性和导向反向传播。
- SmoothGrad (SG): 这是一种通过对从输入的噪声拷贝产生的显著性图进行平均来平滑显著性图的技术。
- 渐变 x 输入:这是输入和渐变的元素乘积。
- 综合梯度(IG) :这种基于梯度的技术对输入的缩放版本求和。
- 导向反向传播(GBP): 这种方法与梯度方法的区别仅在于 ReLU 非线性。详细解释见 CNN 热图:梯度 vs .去配置 vs .引导反向传播。
- grad cam:“grad cam 解释对应于类得分(logit)相对于最后一个卷积单元的特征图的梯度。”GradCAM 是基于 CAM 构建的。关于 CAM 的细节见 CNN 热图:职业激活映射。
- 引导式 GradCAM :这是一个带有引导式反向传播的 GradCAM 的元素级产品。
通过或未通过健全性检查
作者的简短总结:“在我们测试的方法中,梯度和梯度相机通过了健全性检查,而导向后投影和导向梯度相机失败了。”
这是个大新闻。制导 GradCAM 是一种特别流行的技术。第一篇介绍 GradCAM 和引导 GradCAM 的论文被引用了一千多次。
在接下来的章节中,我们将深入研究 Adebayo 等人设计的健全性检查的细节,以评估这些 CNN 显著图技术。
健全性检查 1:模型参数随机化测试
如果我们要使用显著性图来了解模型如何进行预测或为什么会出错,那么我们希望显著性图与模型在训练期间学习的参数有关。因此,第一组健全性检查包括随机化模型的权重:我们破坏模型已经学习的内容,并检查这种破坏是否影响显著性图。
如果随机化权重“破坏”了显著性图,这意味着显著性图取决于模型已经学习了什么(好)。如果随机化权重对显著性图没有影响,那么这意味着显著性图与模型已经学习的内容无关(坏。)
有两个子实验:(1)随机化模型中的所有权重,(2)一次随机化一层。
健全性检查 1 结果:
- 通过:渐变,GradCAM
- 失败:导向反向传播,导向梯度摄像
这是论文中的图 2:
这里,每一行对应不同的显著图方法。随着 CNN 的权重从顶层到底层逐渐随机化,我们看到了由不同方法产生的显著图解释。在最右边,已经实现了所有权重的完全随机化,我们希望显著图解释已经被破坏。
Adebayo 等人强调,显著图的定性视觉评估不足以理解显著图是否被破坏。因此,它们在图 3 和图 4 中提供了定量评估(未示出),报告了原始显著性图和随机化模型显著性图之间的等级相关性、HOGs 相似性和 SSIM。详见论文。
健全性检查 2:数据随机化测试
在数据随机化测试中,模型根据随机化的训练数据进行训练,对于这些数据,所有训练标签都已被置换,即,模型根据数据内容和数据标签之间没有关系的数据进行训练。也许一个狗的图像被标记为“鸟”,另一个狗的图像被标记为“飞机”,而一个飞机的图像被标记为“人”。
Adebayo 等人解释了这项测试的动机:
我们的数据随机化测试评估了解释方法对实例和标签之间关系的敏感性。对随机化标签不敏感的解释方法不可能解释依赖于数据生成过程中存在的实例和标签之间的关系的机制。
神经网络能够在标签已经被随机化的任务上做得很好的唯一方法是,如果网络记忆了训练数据集。在这种健全性检查中,模型被训练,直到它们已经记住足够的训练数据,以获得大于 95%的训练准确度。然而,他们的测试准确性永远不会比随机猜测更好,因为他们没有学到任何可概括的原则(在标签被随机化的数据集中没有可概括的原则可学。)
最后,使用刚刚描述的模型(在随机置换标签上训练的模型)和在真实标签上训练的不同模型,为测试集中的所有示例计算显著图解释。如果显著性图解释完全依赖于神经网络学习的可概括原则来解决任务,那么它应该看起来不同,这取决于模型是在真实标签上训练的还是在随机标签上训练的。
健全性检查 2 结果:
- 通过/正常:渐变、渐变-SG、渐变-CAM
- 失败:导向反向传播、导向梯度凸轮、集成梯度、梯度 x 输入
下面是图 5 所示的显著性图的定性比较:
在该图中,我们可以看到 CNN 在真实标签(顶行)和随机标签(底行)上对 MNIST 训练的数字 0 的显著性图解释。)对于有效的显著性方法,我们希望顶行(“真实标签”)看起来不错,底行(“随机标签”)看起来很糟糕。
和以前一样,重要的是不要仅仅依赖主观视觉评估。因此,作者也提供了定量的比较。在图 5 的另一部分中,我们可以看到在真实标签上训练的模型的显著性图与在随机标签上训练的模型的显著性图之间的等级相关性:
在这种情况下,我们希望等级相关性尽可能接近 0。等级相关的高值是不好的,因为它们意味着在真实标签上训练的模型和在随机标签上训练的模型之间的显著图是相似的。请注意,“Abs”意味着我们采用了显著性图解释的绝对值,而“无 Abs”意味着我们保持显著性图解释不变。我们可以看到,梯度在两种情况下都具有低相关性(好),而积分梯度在 Abs 情况下具有极高的相关性(差)。
边缘检测
在讨论中,Adebayo 等人提供了一个单层和池 CNN 模型的案例研究。这个案例研究表明,一些显著性方法可能像边缘检测器一样工作,因为图像中对应于边缘的区域具有与周围像素不同的激活模式,因此将在视觉上“突出”他们注意到,
当将突出显示的边缘解释为类别预测的解释时,人类观察者有确认偏差的风险。[……]根据我们的发现,将一些显著性方法解释为隐式实现无监督图像处理技术(类似于边缘检测)并非不合理。
总结
如果你在工作中使用显著图解释,请坚持使用梯度或普通梯度图,因为这些方法似乎依赖于训练模型的权重以及训练示例和它们的标签之间的关系。可能最好避免引导反向传播和引导梯度摄像,因为这些方法可能仅仅起到边缘检测器的作用,而不是可靠的解释。
特色图像
特色图片结合了罗丹的这幅《思想者》维基百科图片和该知识库中的显著图。
原载于 2019 年 10 月 12 日http://glassboxmedicine.com。
引导健忘的机器
在说机器之前,先说人类。更像是孩子。
还记得学校里的乘法表吗?老实说,我很害怕。每天数学老师都会出现,开始背诵数字和它们的倍数。每天一张新桌子!几个星期后,我开始忘记基础知识。即使我能说出 12 * 5 是多少,我也没记住 5 * 2!然后,老师介绍了“躲避桌子”的概念——更可怕,但它帮助我比以前更好地记住了桌子。
为什么会这样?我现在意识到她确保了旧桌子的记忆不会离开我的小脑袋,即使我正在学习新的更复杂的东西。最终目标是让一个人能够“不断学习”。
持续学习是从一系列数据中连续学习的能力,建立在以前所学的基础上,并且能够记住那些所学的任务。这是人类能够做到的,也是人工智能机器的最终目标。在我们的大脑中,新皮层依赖于突触巩固&突触中编码的先前任务的知识,这些知识是不可改变的,因此在很长一段时间内是稳定的。
所以我想让我们来谈谈如何引导智能机器不要忘记!
我们可以从数据入手,假设有一个我们搭建的猫狗图像识别器(分类器)。现在,如果我们想给它添加一个‘dear’类(我们已经有了这个类的支持数据集图像),我们该如何着手呢?
We let the Task A (cat&dog) train, and weights are updated as inferred by the machine.
Now we put in the set 2 — Dear images to train & as the machine learns, it updates the weights
太好了,现在我们的机器可以识别三种东西了!一只猫/狗/亲爱的
希望一切正常,我们测试我们的模型…
And as expected the model predicts a fine result
正如预期的那样,模型预测了一个很好的结果!
现在让我们测试一些猫的图像🤞
但是这个失败了!怎么会?为什么?
原因:当添加新任务时,典型的深度神经网络容易出现灾难性遗忘。
我们需要的是能够随着时间的推移吸收新记忆的网络,我们需要努力克服这种限制,训练网络能够在他们很长时间没有经历过的任务上保持专业知识。我们基本上是在努力实现一般的智能 &它需要特工们记住许多不同的任务。持续学习是一项挑战,因为随着新任务/当前任务相关信息的临近,先前学习任务的知识有突然丢失的趋势。当一个网络在多项任务上按顺序训练时,会发生这种情况,导致网络中对任务 A 重要的权重发生变化,以满足最近任务 b 的目标。简单的方法是,我们可以-
- 让所有数据在培训期间同时可用。
- 交错数据又名多任务学习
为什么我们不能继续培训和再培训模特?—因为一个合适的算法将比每次需要学习新任务时从头重新训练模型更有效,而这是非常昂贵的$$$!!!也不是可扩展的解决方案。
哺乳动物的新大脑皮层依赖于特定任务 突触整合和先前任务的知识。它被编码在可塑性较小的突触中,因此长期稳定。科学家和研究人员做了大量的实验来了解我们大脑的内部运作。
oooh Brainnyy stuffz!
所以从聪明人那里得到了帮助,我指的是神经学家&把他们的知识与酷孩子、ML 的人结合起来
-生->神经网络突触巩固!
突触巩固(在人工神经网络中)意味着,随着机器学习更多的任务,对先前任务至关重要的突触的可塑性(或修改能力)会降低。这就引出了我们将要讨论的第一个解决方案!
弹性重量合并[EWC]
这种算法(用外行的话来说)减缓了对某些权重的学习,这些权重是基于它们对之前看到的任务的重要性。它使用贝叶斯网络和寻找局部最小值的概念。像 EWC 这样的许多方法使用类似的方法,如无遗忘学习、增量矩匹配等。
对 EWC 来说,的诀窍就是在为下一个任务训练时 锁定 用于解决第一个任务的权重。通过锁定,神经网络能够学习新的任务,而不会忘记以前的任务。
https://deepmind.com/blog/enabling-continual-learning-in-neural-networks/
嗯,不是字面上锁定权重,而是收敛到一个点,在这个点上,两个任务的 A & B 都有一个低误差,使用下面的损失函数—
cool looking loss function
EWC 确实有一个很大的缺点。如前所述,它是基于贝叶斯学习的,因此这些方法将任务 B 的参数限制在任务 A 的最优值周围的局部区域,以便最小程度地干扰任务 A 已经学习的内容。这可能会阻止神经网络在参数空间的偏远区域找到其他区域, 这可能包含任务 A & B 的联合问题分配的损失函数的更好的最小值。我们可以采取一种变通办法,例如存储大部分工作存储器,并在训练新任务时在训练期间重放它,但是这样会占用大量存储器以及大量训练时间。 考虑到图像处理大部分是在 GPU 上完成的,这是不会省钱的!
现在在神经生物学中,我们知道我们的大脑制造记忆——短期的(就像你脑中的声音为你朗读的),储存在一个地方。现在,当我们睡觉时,对你影响最大的事件的重要记忆将存储在大脑的其他部分*,这些神经元以这种方式保持无弹性(不可修改),因此帮助我们记住学到的知识,并在必要时应用它们。*
brain stuff for cool kids
让我们混合 EWC 和记忆细胞的牵连吧!(耶?!)
对抗性记忆网络
这是代表长期记忆的对立子空间的交集,网络中的长期记忆是为每个任务独立存储在记忆单元中的*。*
任务相关记忆单元(浮点张量)。
https://www.ijcai.org/proceedings/2017/0311.pdf
记忆单元
- 扮演类似于对抗性输入图像的角色
- 抓住每堂课的精髓
- 跨越网络参数空间中高级空间的交集
使用这些记忆单元,我们就有了一个针对每个任务的的不同类的联合抽象长期记忆。
结论将是看不到最容易做到的解决方案,因为它可能有主要围绕 GPU 使用和内存和成本的缺点!而且,这对环境也不好。看这个!
原来如此!你很好地理解了避免灾难性遗忘的重要性和方法。
如果您有任何问题,请随时向我发送 推文。
关注我 随时更新我的帖子。祝您愉快!🎉
H2O 无人驾驶人工智能:端到端的机器学习(对任何人!)
Photo by Markus Spiske on Unsplash
做人工智能的人工智能——今天就开发你的第一个模型。
任何人都可以成为数据科学。不需要编码。
一. ||简介||
Photo by Frank Albrecht on Unsplash
当今世界,成为数据科学家并不局限于没有技术知识的人。虽然了解一点代码是推荐的,有时也是很重要的,但是你可以只凭直觉就能搞定。尤其是如果你在 H2O 的无人驾驶人工智能平台上。
如果你没有听说过 H2O.ai,它是创建开源机器学习平台 H2O 的公司,该平台被许多财富 500 强使用。H2O 旨在通过利用其用户友好的界面和模块化功能来创建效率驱动的机器学习环境。
注意 : 不要把 开源的 H2O AI 平台 和 无人驾驶 AI 混为一谈。 他们是两个独立的东西。我建议通读每一项的文档以了解更多信息。
H2O Open Source vs H2O DAI
H2O 3(开源)是 python/R 上的一个免费库,包含许多 ML 算法、模型和调优功能,使机器学习更加高效。
另一方面,无人驾驶人工智能是一种企业产品,拥有自己的平台、UI 和 UX。它就像一个 web 应用程序,可以使用旋钮和其他调整参数的可视化设备来创建和配置模型,本质上取代了实际编码模型的繁琐过程。
H2O 戴可以从头开始建立和验证人工智能模型,唯一需要的就是你的数据集。数据甚至不必进行清理或特征工程,因为 H2O DAI 可以处理这些任务,并允许您配置重要步骤的自动化,如特征缩放或对变量应用分类编码。
事不宜迟,我将开始 H2O 无人驾驶人工智能教程。
二。||安装||
H2O 无人驾驶 AI 是一款企业产品,因此不建议个人购买。相反,您的公司应该在本地部署 H2O,并允许员工利用其强大的界面。然而,你和我都是独立的个体,出于本教程的目的,我使用 H2O 的 21 天免费试用版。如果你想跟进,但还没有准备好购买产品,你也可以这样做。
注意: 在你的机器上运行 h2o 有一些要求。建议您在 Linux 或 Windows 上运行 h2o,但是,您可以使用 docker 在 Mac 上运行它。你可以在这里学习如何使用*。我将详细介绍 Windows 的要求,因为这是我在本教程中使用的。如果你在 Linux (prod。环境推荐),遵循* 这些指令 。
从访问 h2o.ai 开始。寻找无人驾驶 AI 产品,填写表格,下载最新稳定版无人驾驶 AI DEB 。
visit the website and install H2O driverless AI
在 Windows 上,有 2 个附加要求:
- 必须按照https://docs.microsoft.com/en-us/Windows/wsl/install-win10的规定启用 Linux 的 windows 子系统(WSL)
- 来自 Windows 商店的 Ubuntu 18.04。(注意,不再支持用于 WSL 的 Ubuntu 16.04。)
所以,你需要首先安装 Ubuntu 18.04 for WSL(如果你“以管理员身份运行”(第一个链接中的说明)就可以激活)。完成后,在 Ubuntu 18.04 LTS 中运行以下命令来安装和运行 H2O-戴:
*# Install Driverless AI. Expect installation of the .deb file to take several minutes on WSL.sudo dpkg -i dai_VERSION.deb
# Run Driverless AI.sudo -H -u dai /opt/h2oai/dai/run-dai.sh*
在 windows 上安装 H2O 戴的另一种方法是通过 Docker。你可以在这里找到那个的具体说明。
三。||推出 H2O 无人驾驶 AI ||
在你的浏览器上,在 URL 框中输入下面的
localhost:12345
如果您在本地机器上安装了 H2O,这应该可以工作。运行实例的一般语法是
<服务器> :12345
在本地服务器上使用“localhost”。然后,它应该会自动启动登录页面,如下所示。
对于试用用户,登录 ID 和密码都是“h2oai”。登录详细信息,然后单击登录。您现在应该看到数据集页面,其中 H2O 将向您显示任何过去上传的数据或存储在系统上的其他文件。
四。||上传数据||
H2O 无人驾驶人工智能在获取数据集方面非常灵活。由于其大多数应用程序都基于实时/系列数据,H2O 有能力从许多来源提取信息,如亚马逊 S3 服务器、Hadoop 文件系统(通过本地上传)或 H2O 文件系统。
我从我的电脑上传了一个文件,这是电信客户流失数据库(来自 Kaggle)。该文件包含客户数据,每一列(除了客户 ID)都考虑了客户流失预测。
动词 (verb 的缩写)|| Autoviz ||
我的数据集一上传,我就可以访问 Autoviz 选项卡。当你通过 Autoviz 可视化一个数据集时,它会给你不同种类的可能的图表来总结你的数据。你所要做的就是上传你的数据,Autoviz 就可以使用了。
有些图形也是交互式的,可以像在 Plotly 中一样移动。所有的视频都是可以下载的,所以你可以把它们保存在你的服务器或者文件系统中。
Interactive graphs on Autoviz
不及物动词||项目||
要开始任何实验或活动,你需要有一个项目。因此,转到“项目”选项卡,它应该是这样的:
现在,您需要创建一个新项目,只需选择一个名称和描述即可。一旦完成,你将会有一个像下面这样的屏幕。这是您管理项目、数据和实验的地方。
使用链接数据集按钮将您的文件链接到该项目。我已经附上了我的客户流失数据集,它显示在左侧的培训下。如果右键单击数据集,我可以选择分割它。我需要分割数据集以进行训练和测试,因此我单击“分割”并获得以下选项:
我选择两个不同数据集的名称,选择一个目标列(我们想要预测的列),折叠和时间列(如果需要的话),并选择拆分比率。我选择 0.75,因为这将使我的测试集中有 2500 个值,这足以测试模型。
七。||实验||
每次你在一个数据集上运行一个特定的模型,就叫做实验。有了这个功能,H2O 使型号选择过程变得更加容易。你可以通过多次实验来选择合适的模型。转到您项目的仪表板,然后单击“新建实验”。
实验设置助手应该会打开。你现在可以开始填写这个实验的细节了。从名称开始,然后选择训练集。更多的细节将会显示出来(正如你在上面的 GIF 中看到的)。现在,您可以选择您的目标列、测试数据集,并且可以根据您的需要更改培训设置。根据您选择的设置,该型号的个性化描述将显示在屏幕的左侧。你甚至可以点击专家设置来更深入地改变其他参数。
Experiments on H2O Driverless AI
一旦你点击启动实验,一个新的屏幕将出现。你会看到类似这样的东西,如果你看到了,那就意味着 H2O 正在运行你的实验——直播!
随着实验的进行,它将开始显示模型的迭代数据,以及最重要的变量(可能会随着模型的进展而改变)。在右下角,您还可以在屏幕之间切换,以查看:
-
*~ ROC 曲线
- Precision-Recall
- Gain/Lift 图表
- K-S 测试图(Kolmogorov-Smirnov)
- CPU 使用率。*
一旦您的实验完成,您应该能够看到这样的屏幕,您的 CPU 使用选项卡将更改为摘要:
在变量重要性的正上方,有一个可供选择的操作菜单。屏幕上唯一不可用的选项是部署。这是有原因的。这是因为我们还没有下载我们的 MOJO/POJO 文件。我们将在最后做那件事。首先,我们来解读一下这个模型。
八。||解释模型||
导航回实验选项卡并找到您的实验。再次打开它,点击按钮解释这个模型。 翻译窗口将开始加载,可能需要一些时间。它应该是这样的:
一旦解释页面被加载到 100%,您将会得到一个解释模型的菜单。也可以通过 MLI 选项卡访问该页面。正如你在下面的 gif 图中看到的,页面左侧有许多标签。
- ***摘要:*向我们概述了 MLI(机器学习解释器)以及模型的一些参数,例如其最重要的变量及其定义、所使用的石灰聚类的数量、代理模型的摘要。下面的 GIF 显示了一个示例摘要页面:
Summary of MLI
- ***戴模型:*这里可以看到无人驾驶 AI 开发的模型。在 DAI 模型中,您可以看到该模型中功能重要性的全貌,当您将鼠标悬停在变量上时,每个变量都会弹出解释。它还可以向您显示合同变量的部分依赖关系图,此外,您可以从我们的实验中看到带有完整混淆矩阵的不同影响分析。
- ***代理模型:*除了 DAI 模型分析,我们还可以获得关于代理模型的信息。这些位于代理选项卡中,允许我们查看来自其他模型的参数和数据,如 K-Lime 聚类、决策树模型和随机森林模型。
在随机森林中,我们还可以看到特征重要性、部分相关性和局部相关性。
- ***仪表盘:*下面是 MLI 仪表盘的样子。它在一个页面上包含了我们所有重要的图表和参数,因此我们可以快速导航到我们想要的位置。
九。||诊断||
Diagnostics 选项卡包含一个页面,其中包含某些准确性指标和图形,可用于在运行实验后诊断模型。它包含了 ROC 曲线、精确回忆曲线、收益/提升、K-S 图和真/假阳性/阴性混淆矩阵的所有内容。
诊断页面如下所示:
X.||部署||
正如我上面提到的,部署是不可能的,因为我们没有 MOJO 文件。要在本地或云服务器上部署您的模型,您首先需要创建 MOJO 文件。根据他们的网站,“ H2O 生成的 MOJO 和 POJO 模型旨在方便地嵌入任何 Java 环境。
*因此,回到实验选项卡并加载您的实验。您将再次看到带有绿色选项按钮的菜单。继续点击按钮**建立 MOJO 评分管道。*它现在会在你的左边显示屏幕,并开始建立你的 MOJO 管道。
一旦您的 MOJO Pipeline 可用,您将可以选择部署您的模型。你可以选择把它放在 Amazon Lambda 服务器上,也可以使用 REST API 服务器。一旦你选择了你的目的地,H2O 将自动部署你的模型,并给你它的位置。
XI。||资源和结论||
“资源”选项卡有许多选项可用于。首先,它会有一个选项带你去无人驾驶人工智能文档。它还包含下载用于 R 和 Python 的 H2O 无人驾驶 AI 客户端 API 的链接。如果你想了解更多关于无人驾驶人工智能的能力,并在你的业务中使用它,这是非常有用的。
最后,我只想提一下,我与开发该产品的 H2O 公司没有任何关系。我是他们产品的用户,我认为发布这个教程是个好主意,因为目前还没有很多这样的产品。我花了一段时间来学习 H2O 无人驾驶人工智能,我想我会通过这个教程让其他人更容易。
欢迎对这篇文章发表评论,问我关于我的工作的任何问题,或者我打算如何在我的个人/工作项目中使用 H2O。我可能会在未来写另一篇帖子,将无人驾驶人工智能与 H2O 3(开源)进行比较,任何对此的反馈都将是巨大的。
感谢阅读。我希望这能以难以想象的方式帮助你。
更多关于 H2O 无人驾驶 AI 的信息和教程,请访问 h2o.ai 。
Catch H2O.ai on Twitter!
Photo by Borna Bevanda on Unsplash
十二。||参考资料||
- https://H2O-release . S3 . Amazon AWS . com/H2O/rel-ueno/2/docs-website/H2O-docs/welcome . html
- https://www.h2o.ai/products/h2o-driverless-ai/
- http://docs.h2o.ai/?_ ga = 2.1983044548-16871447156686
H2O 适合没有经验的用户
一些背景:我是一名高三学生,2018 年夏天,我在 H2O.ai 实习。除了吴恩达在 Coursera 上的机器学习入门课程和他的几门深度学习课程之外,我没有任何 ML 经验,最初我发现自己有点被 H2O 在其开源和企业软件中提供的各种新算法所淹没。但是通过探索各种资源,到夏天结束时,我已经能够在 Kaggle 上的 TGS 盐识别挑战中使用无人驾驶人工智能和 H2O-3 算法。在这篇博文中,我将讲述我在 H2O.ai 工作期间的经历和收获,以及为那些新手提供的学习 H2O 和数据科学的资源。
入门
H2O-3
为了开始使用 H2O,我首先下载了 H2O-3 包以及 Python 客户端。尽管安装说明很简单,但在安装和使用 Python 客户端时,请确保:
- H2O Python 安装和下载的包版本匹配。
- H2O 运行的是 Java 8
如果你不希望使用 Python,H2O 3 有一个 GUI API,H2O 流,可以在浏览器上访问;python 客户端易于使用且灵活,具有直观的命令和其他 python 优势,如 numpy、pandas 和 opencv。
让 H2O 3 号运行起来后,下一个任务是熟悉它的功能。对此有用的资源包括:
- 文档:侧边栏中的页面绝对值得一读(随意跳过或浏览)。该文件提供了一个全面的看法,你可以做什么与 H2O-3,以及细节和解释有关的实施。在 R 和 Python 的一些页面上都可以找到示例代码。如果示例代码在某些页面上不可用——例如,在深度学习页面上——它可能在 GitHub 存储库中可用(很可能在 tutorials 文件夹中;如果不容易找到,您可以搜索整个存储库)
- H2O-3 GitHub :浏览你心目中项目的教程。再看一些,看看你能包括的其他函数和算法。我发现教程中的示例代码对于学习如何使用每个函数非常有用。源代码读起来很有趣。如果你想了解每件事是如何实现的,读一读它;尽管要理解如何使用所有的东西,浏览文档会更容易,因为源代码阅读和解释起来相当长。
- Coursera : H2O 在 Coursera 上有一门课程,你可以免费获取资料,但需要为作业付费。虽然我没有尝试过,但是如果您喜欢更结构化的方法,可以尝试一下。
随着我对 H2O-3 越来越熟悉,我浏览了打印到终端窗口的日志,在那里,当我运行各种算法时,H2O 实例通过 Java 启动。这也非常有助于理解它在做什么,监控进展,并在数据或模型超参数中找到潜在的改进。
从 H2O 无人驾驶 AI 开始
我开始使用无人驾驶 AI(戴)的方式与 3 相同。我按照安装说明下载安装了戴。这非常简单,但是值得注意的是,如果您的机器上没有足够的 RAM(指令要求 DAI 至少运行 10 gb),那么无论如何都要尝试运行 DAI,它仍然可以工作。我在一台内存为 8 gb 的 Mac 上分配了 4 gb,它仍然能够运行。
为了熟悉戴,首先浏览一下文档侧栏中的所有页面。模型解释和转换是戴所独有的。为了理解模型解释,我试图通过查看其 GitHub 库和本文来理解 LIME。原文也值得一读。
戴使用起来很直观。很容易理解如何使用它。毕竟,它是为非数据科学家打造的!
组装
H2O-3 AutoML(以及一些固有集合模型)和 DAI 集合模型来提高性能。在 Kaggle 上也经常使用集合模型。这篇文章从概念上解释了集成,这篇博文展示了如何实现它。相关:【mlwave.com是一个从顶级 Kagglers 和数据科学家那里学习机器学习概念、用途和工作流的绝佳资源。强烈推荐阅读;这些文章非常有趣,可能对您的数据科学项目有所帮助。
小项目
我从印度国家股票交易所下载了塔塔钢铁 24 个月的股票数据,开始用戴和 3 做日内交易的实验。我打算使用前一天的标记和当天的开盘价来预测当天的收盘价。
我第一次处理这个数据集是通过在某一天移动标记列中的元素,使得当天的收盘价与前一天的标记在同一行中——这不是处理时间序列的正确方法;戴的时间序列特征对数据进行了适当的自动处理。然后我在这个数据集上运行了 DAI。由于 H2O-3 算法运行得更快,当戴运行时,我也能够在这个数据集上训练多个 H2O-3 模型。使用 3 算法的训练分数约为 10,使用戴算法的训练分数约为 9.1,在小型测试数据集上的测试分数约为 213,这使得该模型对任何日内交易应用程序都没有用。
Initial DAI model without time series
在寻找提高模型性能的想法时,我找到了 Marios Michailidis 关于如何在 Kaggle 上使用戴的视频。他使用 DAI 和如下所示的其他算法来堆叠模型,并充分利用 DAI 的特征工程:
在试图遵循这一点,我首先饲料戴衍生数据与额外的功能(但与地面真实价格值即。来自原始数据集的接近价格列)到显示更多多样性的各种 3 模型,然后将它们的预测馈送到戴(最终模型)。这在训练阶段更有希望,RMSE 约为 3.5,但在得分约为 288 的测试数据集上表现较差。这是不正确的堆叠。翻翻前面提到的博文,看看怎么做才正确。
后来,我在未编辑的数据集上尝试了戴的时间序列特性,其性能显著提高到约 0.05 训练和约 6 测试。然而,即使性能有所提高,模型在测试集上的显著性能下降表明它没有足够的数据来创建准确的模型。
DAI model with time series
卡格尔
在试用并熟悉了 3 和戴之后,由于我无法找到足够的数据让塔塔钢铁做出更好的模型,所以我转向了数据科学竞赛平台【】Kaggle 。TGS 盐鉴定竞赛看起来很有趣,而且是一个相当大的数据集。这场比赛涉及在给定地震数据(以图像的形式)和每个图像的深度的情况下,识别地下目标是否是盐,换句话说,就是盐在地震图像上的位置和边界。
我强烈建议你看看 Kaggle,即使你不打算参加比赛,因为它为数据科学新手提供了大量资源,包括数据集、讨论(初学者的部分)、计算资源和代码(内核)。
有用的 Python 模块
Python 有各种各样的模块,使得数据操作更加容易。看看 numpy 和 pandas 进行计算和数据操作, csv 进行 csv 读写,以及 opencv 处理图像。
数据集生成
因为 H2O 不接受图像数据,所以我生成了以下列格式的数据集,其中每一行都对应于图像上的一个像素,使用的是这个脚本:
Id(字符串)
深度(真实)
灰度像素值(实数)
盐地真相(布尔/枚举)
将这些数据提供给戴非常简单;我刚刚用上传文件按钮上传了它。然而,对于 H2O-3,它需要被压缩,否则 Python 会抛出[Errno 22]无效参数。注意: Python 3 似乎很难处理超过 2–4gb 的文件;H2O.ai 会通过升级他们的导入库来修复这个 bug。
python 脚本创建了 3600 个图像像素的训练集、400 个图像像素的验证集和 18000 个图像像素的测试集;这些测试预测将被提交到 Kaggle 上。
戴和 3 算法
为了防止算法记住数据,在训练之前删除了 id 列。由于训练和测试数据集相当大(分别约 4100 万和 1.83 亿行),在没有 GPU 的情况下,戴花了很长时间进行训练。这次,我尝试了 H2O-3 深度学习估计器。对于两者,我都使用 AUC 指标作为计分器,并为 DAI 最终管道启用 Tensorflow 模型和 RuleFit 支持(在专家设置菜单中)。戴获得了大约 0.75 训练 AUC,而 3 深度学习获得了大约 0.72。
预测的像素值被转换成映射到 id 的 RLE 编码,如比赛计分员使用这个脚本所要求的。在这里找到的 numpy 数组到 rle 函数的功劳拉赫林。由 Kaggle 评分的深度学习和 DAI 模型在测试数据集上的交集(IoU) 分数如下:
模型:H2O-3 深度学习,IoU: 0.263
型号:戴,借据:0.176
First salt detection DAI model trained on 2 features
缺乏特色
潜在的模型准确性的最大障碍是缺乏特征。数据集的每个像素只有两个要素(因为 id 已被删除)。通过增加更多的特征,包括像素位置、相邻像素灰度值以及图片灰度最大值、最小值和平均值,这一点得到了弥补。
然而,随着训练、验证和测试文件(尤其是测试文件)从 4 列膨胀到 13 列,这暴露了更多的硬件限制。戴运行时间长,我的笔记本电脑 RAM 用完,Python 不支持上传大文件,都拖慢进度。
资源
Kaggle 论坛对于改进模型的可能途径非常有用,无论是通过理解和扩充数据,探索更合适的模型,还是精炼模型。除此之外,每当出现问题时,谷歌搜索通常会让我找到有一些答案(或至少有趣)的研究论文、Stackoverflow 或 Kaggle 讨论。
我还从 H2O 的 Megan 那里得到了很多关于如何提高模型性能的想法和建议,包括额外的特性和自动编码(见下文)。H2O 也是您学习数据科学和改进模型的绝佳资源。
向前发展的想法
特征工程通常是 Kaggle 竞赛的关键部分(正如我从 Kaggle 论坛上了解到的那样),因此包含更多的特征很可能会提高模型性能。这些特征可以包括到沙簇的像素距离、沙簇的一般形状,或者可能是更多邻居的盐真相。尝试找到更多功能。
自动编码器或 GLRM 也可以用于对输入图像和/或预测进行去噪。在检查初始(2 个特征)DAI 序列预测时,我注意到有很多噪声,特别是在应该是空的图像上。Kaggle 已经实现了 IoU 指标,因此如果在应该为空的图像上预测到任何 salt,则该图像将得到 0 分。通过在训练预测和训练集上训练的 H2OAutoEncoderEstimator 运行测试预测应该减少噪声并去除否则为空的图像上的杂散像素。
空图像也可以通过让输入图像通过另一个模型来捕捉,该模型首先检查它是否是空的。如果预测为空,而不是冒几个像素的风险,则在该图像上将有 0 个真实像素被预测。
更适合图像的其他模型也可能提供更好的解决方案。从论坛可以看出,UNets 在竞争中似乎相当成功。其他卷积网络也应该在性能和速度上提供超过常规深度神经网络模型的提升。正如 Sri 所建议的,GAN 方法也可以工作,因为模型需要生成掩模图像。
就速度而言, Cython 似乎是加速数据集处理的一个有前途的途径。更高的效率和更少的硬件限制也将使集合(堆叠/混合)成为提高模型性能的更可行的途径。
如果您有时间、愿望和计算资源,请拿起指挥棒,参加竞赛!
杂学
命令行技巧
熟悉命令行虽然不是使用 H2O 所必需的,但可以使大多数任务变得更容易。对我来说,知道如何浏览文件、启动 Java、使用 Python 和 pip、连接到远程机器并在其上运行任务就足够了。
远程机器
如果您在远程机器上使用 DAI 或 H2O(或其他任何东西),这些命令可能会有所帮助:
下载到机器上
ssh:连接到机器的命令行
Byobu 可以用来保存远程会话(即使在断开连接的情况下,你也可以让 DAI 或 H2O-3 在远程机器上运行),并且非常易于使用。
用于机器学习的机器
如前所述,我在生存能力和速度方面遇到了许多硬件限制。为机器学习设置一台机器将使一切变得更容易和更快。这篇文章可能会对你有所帮助。GPU 注意:GPU 的指数级加速 H2O 性能,但 H2O 的 GPU 并行化是使用 CUDA 构建的(ML 中使用的许多其他脚本也是如此),所以当决定使用 GPU 时,请使用 CUDA。
前进
在熟悉 H2O 之后,下一个好的步骤是探索和理解更多的算法,这样你就可以将合适的算法应用到用例中。这也可以改善模型集合的结果。此外,研究更多的数据科学可以更好地理解和操作数据集,这也将提高模型性能。最后,只是阅读论文、Kaggle 讨论和跟上 H2O 文档将是学习更多和产生新想法的有趣和有趣的方式。