您需要了解的关于 Python 的所有信息
看看我们如何使用 Python 通过 API 与网络通信
照片由 Pavan Trikutam 在 Unsplash 上拍摄
用 Python 在网上聊天,听起来很恐怖,对吧?幸运的是,互联网很长一段时间以来一直处于良好的状态。我们与互联网交流的方法已经很成熟,而且出奇的简单。
我们将跳过简短的介绍,直接进入正题。本文将涵盖我们通过网络进行有效沟通所需的所有内容,包括:
- Application Program Interfaces (**APIs**)
- JavaScript Object Notation (**JSON**)
- **Requests** with Python
- Real world **use-cases**
应用程序接口
应用编程接口就像一个魔术盒。我们以指定的格式发送数据。然后,我们以指定的格式获取数据。
这个神奇的盒子只是保存在服务器上的一个脚本。它就像一个看门人——我们告诉看门人我们想知道、更改或删除一些东西,看门人会(希望)执行我们要求的动作,并告诉我们进展如何。
幸运的是,API 通常都有很好的文档记录,并且遵循相同的使用模式。绝大多数的 Web APIs 使用代表性的状态转移(REST)结构——这听起来比实际情况复杂得多。
休息
RESTful API 体系结构应用了六个关键约束:
-
所有请求都通过 单个外向接口 处理。
-
客户机-服务器独立性——一方的开发和功能变化不应该影响另一方(客户机指我们,服务器指 API)。
-
无国籍状态——服务器不保留我们会话的任何信息;每个请求都被视为新的。
-
使用 分层系统——意味着 API 由层组成,其中每一层都连接到另一层,从而创建模块化结构。****
-
如果适用,API 应该能够根据请求 为用户提供可执行的 代码。
所有这些对我们来说意味着,我们将与单个位置进行通信,并期待特定的行为——这将使用一组 HTTP 方法进一步标准化。
方法
当与 API 通信时,我们倾向于使用四种方法:
- GET —用于从 API 中检索信息。
- POST —创建新资源(例如,GitHub repo)。
- 上传 —更新现有资源。
- 删除 —删除现有资源。
其中最常用的是 GET 协议。在大多数情况下,对于数据,我们更感兴趣的是下载它。
如果我们想使用 Google Maps API 获取一个地址的经度和纬度坐标,我们会发送一个 get 请求——因为我们实际上是从 API 获取 T21 数据。
修改信息时会用到发布、上传、删除。以 GitHub repo 为例,我们可以用 POST 创建它,用 PUT 更新它,用 DELETE 删除它。****
您可能还会看到补丁——这用于部分更新,类似于 PUT。我以前没用过这个,看起来不太常见但值得了解。
HTTP 代码
当使用 GET、POST、PUT 和 DELETE 时,我们通常会收到以下代码之一:
****2xx - Success Codes
200 OK** - success (most common with **GET**)
**201 Created** - request fulfilled and new resource created (**POST**/**PUT**)
**204 No Content** - success but no content is returned in response**4xx - Client Error Codes
400 Bad Request** - request could not be understood due to bad syntax
**401 Unauthorized** - most likely we missed the auth key
**403 Forbidden** - we're trying to go places we're not allowed
**404 Not Found** - what we're trying to access doesn't exist**Honorable Mentions**
**418 I'm a teapot** - stop asking a teapot to brew coffee
**420 Enhance Your Calm** - sending to many requests to Twitter**
记下最后两个——它们非常重要,永远不要忘记它们。
JavaScript 对象符号
当与 API 通信时,我们需要一个发送和接收数据的标准化模板,这样 API 和我们都可以正确地处理数据。这种格式是 JavaScript 对象符号(JSON)。
JSON 实现了与 Python 字典中相同的键值对层次结构。
点击此处将使用我们的浏览器向 Pokemon API(所有东西都有 API)发送请求,然后加载来自 API 的 JSON 响应:
来自口袋妖怪 API 的 JSON 响应
在 Python 中,我们使用字典和json
库来构建 JSON 字符串以包含在请求中,通常如下所示:
**request = {'name': 'John',
'age': 21}
json_obj = **json.dumps(**request**)**
requests.post('https://api.com', data=json_obj)**
Python 中的请求
好了,我们知道它是怎么工作的了。但是我们怎么做这些事情呢?
我们使用requests
——一个非常容易使用的库。例如,如果我们需要发送一个 GET 请求,我们只需编写:
**import requests
data = **requests.get(**http**)****
http
是 API 的网址,包括指定我们想要的信息的参数。
让我们以神奇宝贝 API 为例——它使用起来非常简单。
该 API 包括一种方法,用于查找每个新一代中添加的所有口袋妖怪——我特别记得有 151 个口袋妖怪,现在有多于896 个。所以让我们看看他们用第二代增加了多少。
1.调用 API
首先,我们简单地使用 GET 请求来请求数据,指定我们对**generation**
数据感兴趣,特别是**generation-ii**
:
**API_CALL = "https://pokeapi.co/api/v2/**generation/generation-ii**"
requests.**get**(API_CALL)**
**[Out]:** <Response [200]>
好的,<Response [200]>
是什么意思?嗯,这是 HTTP 200 OK
状态码。意味着我们的请求成功了!但是我们想要的数据在哪里呢?
2.提取数据
我们返回的是一个requests.Response Object
——它包含许多有用的方法,我们想要检索实际 JSON 响应的方法是:
**RES = requests.**get**(API_CALL)
RES**.json() # returns a dictionary****
来自 Pokemon API 的 JSON 响应—显示所有第二代相关数据。
现在,我们有一个非常详细的响应,包含了第二代中添加的所有内容。为了统计新口袋妖怪的数量,我们访问了pokemon_species
列表:
**DATA = RES.json()
DATA[**'pokemon_species'**]**
来自口袋妖怪 API 的 JSON 响应—显示所有第二代口袋妖怪物种
最后,我们可以键入len(DATA['pokemon_species'])
来查找新口袋妖怪的数量(它是 100 )。
现在我们可以找到我们需要知道的关于口袋妖怪的一切。这很好,但可能没那么有用。
真实世界的使用案例
让我们使用真正的 API 和用例来编写一些更相关的代码。
使用 Google Maps API 可视化地址
我写的第一个代码很大程度上依赖于谷歌地图地理编码 API。现在看着它让我感到恶心——所以我们要重写它。
我们的目标是在地图上绘制一个地址目录。为此,我们需要它们的相对 x-y 坐标(对于 Matplotlib 来说),这就需要我们找到它们的经纬度坐标。
我目前住在罗马——所以我整理了一份这里著名地标的小清单;我们将在示例中使用这些数据——所以请随意下载并跟随。
授权
首先,我们需要一个授权密钥来使用 Google Maps 地理编码 API ( ~每月 40,000 次请求是免费的)。大多数 API 总是需要我们在调用中包含一个授权密钥;否则,我们的请求将被拒绝:
我们在没有授权密钥的情况下尝试访问 API 时的反应,单击此处尝试相同的。
地理编码 API 文档包含获取 API 密钥的说明。
API 参数
如果我们想找到罗马斗兽场的坐标,我们从 HTTP 地址内部将街道地址传递给 API。
API 需要两个变量,address
和key
。我们在[http://maps.googleapis.com/maps/api/geocode](http://maps.googleapis.com/maps/api/geocode.)
访问地理定位 API。
**API = "http://maps.googleapis.com/maps/api/geocode"
ADDR = "piazza+del+colosseo,+1,+rome"
KEY = "API_KEY" # replace this with the API key from Googlerequests.get(f"{API}/json?address={ADDR}&key={KEY}")**
此代码将发送一个 GET 请求到:
**[http://maps.googleapis.com/maps/api/geocode/json?address=piazza+del+colosseo,+1,+rome&key=**AUTH_KEY**](http://maps.googleapis.com/maps/api/geocode/json?address=piazza+del+colosseo,+1,+rome&key=AUTH_KEY)**
如果您用**AUTH_KEY**
在浏览器中输入这个,我们将看到来自 API 的 JSON 响应:
当请求罗马斗兽场的位置数据时,来自 Google maps 的 JSON 响应。
请求数据
我们可以通过遍历列表并为每一项发送 GET 请求来找到地址列表中每一项的坐标:
结果
在收到我们的响应RES
后,我们使用json
方法将其转换成 Python 字典,允许我们访问纬度LAT
和经度LONG
的值。我们将坐标添加到COORDS
列表中——现在可以用来在地图上绘制位置。
该数据与我们新的 lat 和 long coordinate 列一致。
我们不会涉及绘图代码,但如果这是你想做的事情,我会建议使用 Matplotlib 的底图扩展 —尽管现在可能有更好的工具可用(我很久以前就这样做了)。
与 GitHub 交互
我们也可以使用 API 与 GitHub 交互。简单来说,我们将使用 POST 请求创建一个名为api_test
的新 repo。
授权
首先,和往常一样,我们需要一个授权令牌。幸运的是,我们可以比使用 Google Maps API 更快地完成这个设置——你可以在这里找到一个分步指南。
请注意,在第七步中,选择哪些权限完全由您决定——但是我们需要的只是repo
:
我们只需要回购许可。我避免勾选delete _ repo——这似乎是个坏主意
现在,我们可以通过在请求中添加headers={'Authorization': f'token {TOKEN}'}
来验证自己。
创建一个回购
要创建 repo,我们只需向[https://api.github.com/](https://api.github.com/)
user/repos
发送 POST 请求。这里唯一需要的字段是name
值,它指定了新的回购协议名称。我们还将public
设置为true
,这只是将回购隐私设置设置为 public——而不是 private(默认设置)。
注意,我们使用PAYLOAD
来包含我们对 API 的指令,我们将这些指令传递给requests.post
中的data
参数。我们还使用headers
参数包含了我们的授权密钥/令牌。
结果
如果我们成功创建了 repo,我们将收到代码**201 Created**
——表明请求已经成功,我们已经创建了一个新的资源。
我们也可以在 GitHub 上查看,果然api_test
回购就在那里:
GitHub API 非常酷,我们可以用它做很多事情,正因为如此,它非常适合学习——如果你想了解更多,我建议你看一下文档(也可以随时问我问题!).
最终注释
这就是开始使用 Python 中的 API 所需要知道的一切。当然,还有更多更相关的用例。
对我自己来说,我现在几乎只在公司环境中使用 APIs 主要用于数据传输和操作,以及模型设置和培训。
从互联网上获取数据也是一项经常性的任务,因此,这是一项非常重要的技能。理解并实践 API 是非常有用的。
希望这篇文章有用。如果你有任何问题或建议,请告诉我,随时通过 Twitter 或在下面的评论中联系我。
感谢阅读!
有兴趣学习更多关于数据和 web 开发的知识吗?试试我最近写的这篇关于使用 Angular 部署 Python 构建的 TensorFlow 模型的文章:
**** [## 如何使用 Angular 部署 TensorFlow Web 应用程序
在角度构建的 web 应用程序中使用 Python 构建的模型
towardsdatascience.com](/how-to-use-angular-to-deploy-tensorflow-web-apps-5675b5a042cc)****
在技术面试中你应该知道的关于操作系统的一切
意见
处理技术访谈中常见操作系统问题的完整指南
马库斯·斯皮斯克在 Unsplash 上的照片
“你现在准备好面试了吗?”
“是的,当然。”
“太好了。可以请你说说你对操作系统的理解吗?”
“嗯……嗯……”
“好的,谢谢你今天抽出时间。请在未来几天等待我们的进一步通知。”
你觉得这类似吗?
不要放弃。你肯定能做得更好。
以下是一些你在技术面试中会遇到的常见操作系统问题。你可以按照这个指南从零开始学习操作系统,并清楚地向你的面试官解释。
1.什么是操作系统?
操作系统的定义可以分为三个部分:
- 操作系统为用户提供了与计算机硬件交互的接口。
- 操作系统(OS)是管理计算机硬件和软件资源的程序。
- 操作系统由内核和其他一些基本组件构成。一般来说,内核是应用程序和硬件之间的桥梁。它负责管理进程、内存、文件和网络等东西,直接访问硬件,维护系统的稳定性和性能。
操作系统架构。作者图片
2.用户如何访问计算机资源?
计算机操作可分为两种模式:
- 用户模式:该级别下的流程只能访问用户提供的数据。
- 内核模式:该级别下的进程对计算机硬件有完全的访问权,可以执行机器的一些特殊操作(如 I/O)。
典型的应用程序通常运行在用户模式下。当内核模式下有服务需求时,应该发出系统调用。它是一个请求,要求内核进程执行设备管理、文件管理、进程管理和内存管理等功能。
用户和内核模式的范围(图片由作者提供)
3.进程和线程的区别是什么?
简而言之,进程是一个活动的程序。它可以在执行时生成多个线程。进程通常是相互独立的,但是线程不是必需的。进程会导致更多的开销,但也更便于管理,而线程正好相反。
以 JVM 进程为例,里面的线程是共享堆空间和方法区(metaspace)等全局变量的,但是程序计数器寄存器、JVM 栈、native 方法栈是私有的。
JVM 进程结构(图片由作者提供)
4.流程的状态是什么?
该过程有 7 个状态,分别是:
- 新建:流程正在创建。
- 就绪:进程准备运行,即等待来自处理器的资源(如时间片)。
- 运行:该进程当前正在 CPU 下运行。一次只允许一个进程。
- 等待(或阻塞):流程暂停,等待所需资源可用。
- 完成(或终止):流程执行完毕。它可能因某些原因或正常退出而中断。
- 暂停就绪:就绪队列已满,进程暂停。
- 暂停块:等待队列已满,进程暂停。
流程生命周期(作者图片)
5.什么是上下文切换?什么时候会发生?
上下文切换意味着保存正在运行的进程状态并加载另一个进程的状态。这通常发生在高优先级进程进入就绪状态或发生中断时。
6.什么是竞争条件?
当多个进程共享相同的代码或资源时,就会发生争用情况。在这种情况下,可能会出现意外的结果,因为每个进程都可以随时访问共享变量。
7.进程之间是如何通信的?
进程间通信(IPC)有六种方式:
- Pipe :使一个流程的输出成为与有共同原点的另一个流程的输入,即同一个流程。使用管道的数据流是单向的(例如,Linux 中的“|”命令)。
- 命名管道:这允许来自不同来源的进程的通信。它遵循先进先出(FIFO)规则。
- 消息排队:这两种管道都是低效的,因为将数据发送到缓冲区的进程需要等待,直到另一个进程取回数据。消息队列能够解决这个问题,生产者不需要等待消费者检索数据。
- **共享内存:**消息排队还有一个缺点,就是发送数据的规模太大的时候比较耗时。因此出现了共享内存的想法。它允许多个进程访问同一个内存区域。这是最有效的方法,因为每个进程都可以立即看到数据的更新。
- 信号量:共享内存最大的问题是多个进程会争夺资源。信号量是在进程同步中使用的程序计数器,用于控制访问共享内存的进程数量并避免竞争情况。它表示共享内存中有多少可用资源。
- 插座:上面提到的所有通信方式都只基于一个设备。套接字是允许多个设备之间远程通信的接口。它主要用于客户/服务器通信。
8.线程之间是如何同步的?
线程同步的目的类似于进程间通信,避免并发线程之间竞争共享资源。有三种常见的线程同步方式:
- 互斥:是一种互斥的机制。互斥一次只允许一个线程访问共享资源(如 Java 中的
synchronized
)。 - 信号量(Semaphore):它与互斥量非常相似,但是它的值可以大于 1,并且允许多个线程同时进入共享资源。
- 事件:通过通知(wait/notify)保持线程同步。
9.CPU 如何调度进程?
为了实现最大的 CPU 利用率,有几种 CPU 调度算法:
- 先来先服务(FCFS) :将资源分配给就绪队列中首先请求 CPU 的进程。它是一种非抢占式算法(计划的进程将一直运行,直到完成或被阻塞)。
- 最短作业优先(SJF) :将资源分配给就绪队列中执行时间最短的进程。它是一种非抢占式算法。此外,还有一个最长作业优先(LJF)调度算法。
- 最短剩余时间优先(SRTF) :将资源分配给就绪队列中剩余执行时间最短的进程。它是一种抢占式算法(当一个更高优先级的进程进入时,被调度的进程可以被抢占)。还有一种最长剩余时间优先(LRTF)调度算法。
- Round Robin :每个进程被分配给一个给定的时间,称为时间片,执行到时间用完为止。
- 基于优先级的:每个进程被赋予一个给定的优先级。优先级越高,越早被选中。
- 多级队列:流程按照优先级被分配到不同的队列中。低级队列中的进程被允许执行,直到高级队列中的进程完成。
- 多级队列反馈:这是 UNIX 系统中使用的调度算法,允许进程在各级队列之间移动。如果该进程花费太多的执行时间,它将被移到较低级别的队列中。
10.操作系统中的内存模型是如何设计的?
操作系统中有两种类型的内存:
- 主存储器(内部存储器) : CPU 寄存器、高速缓冲存储器和主存储器,可由处理器直接访问。
- 二级存储器(外部存储器):不同类型的磁盘(磁盘、光盘),是处理器可以通过 I/O 访问的一些存储设备。
操作系统内存模型(图片由作者提供)
11.操作系统中的内存管理是如何工作的?
操作系统的内存管理负责为进程分配内存,包括将逻辑地址转换为物理地址或在内部和外部内存之间交换进程。
12.什么是虚拟地址和物理地址?
举个常见的例子,我们在一些编程语言中看到的指针概念,存储的是内存的虚拟地址,这个地址是由操作系统决定的。物理地址是物理存储器中的地址,即存储器地址寄存器。
虚拟地址(图片由作者提供)
现代处理器使用虚拟寻址技术,通过 MMU(内存管理单元)将虚拟地址转换成物理地址。虚拟寻址的过程如下图所示:
13.操作系统如何分配内存?
有四种常见的内存分配技术:
- 分区分配:按块划分内存,每个块包含一个进程。如果进程只需要很小的内存来运行,空间就会被浪费。这是一种连续分配,因为这些块在内存中是连续的。
- 分页内存管理:按页帧划分内存,页帧是比块小的单位。这增加了内存的使用并减少了内部碎片。这是一种不连续的分配,因为页面框架可以分开。分页表用于将虚拟地址映射到物理地址。
- 分段内存管理:按段划分内存,段是数据或代码的逻辑组。它是不连续的分配,因为允许将数据段分开。段表用于将虚拟地址映射到物理地址。
- 带分页的分段:结合了分页和分段内存管理的优点。它将内存分成几个段,然后将每个段分成几个页帧。
14.什么是 TLB(翻译后备缓冲器)?
在分页内存管理中,有两个问题需要处理:
- 虚拟到物理的映射应该很快。
- 当虚拟地址空间很大时,页表会变得更大。
TLB 可以用来加速虚拟内存和物理内存之间的转换。它可以被看作是一个缓存,在一个页表中存储一部分数据。有了这个缓存,我们在执行 I/O 时只需要访问主内存一次,而不是两次。
将虚拟地址转换成物理地址的过程是:
- 搜索 TLB 内部的页码。
- 如果找到给定的页面,从 TLB 中读取相应的物理地址。
- 如果找不到给定的页,则读取页表中相应的物理地址,并将其存储到 TLB 中。
- 当页面满了的时候,通过一定的策略来消除 TLB 内部的页面。
15.什么是多级页表?
除了加速映射,我们还可以使用多级页表来处理由大的虚拟地址空间引起的问题。它避免了总是将所有的页表放在主存中,这样可以节省更多的空间。
16.什么是虚拟内存?
当一个软件的内存成本超过计算机的空间时,这是很常见的。之所以能实现这个,是因为虚拟内存。它将一个程序分成几个部分,并允许在程序需要之前将它们临时存储在外部存储器(磁盘)中。通过这样做,程序将认为自己拥有一片连续的空间。
17.如何实现虚拟内存?
虚拟内存实现有两种常见类型:
- 按需分页:基于分页技术,具有页面替换功能。如果我们在进程开始前找不到所需的页面,操作系统将在辅助内存中搜索它,并根据给定的页面替换算法交换在主内存中找到的页面。
- 需求细分:这是一种类似于需求分页的技术。它们之间唯一的区别是,根据给定的段替换算法,按需分段将段而不是页面交换到主存中。
18.页面替换算法是什么?
当所需页面不在主存储器中时,发生页面错误。我们需要页面替换算法将页面从辅助内存交换到主内存中。下面列出了一些常见类型的页面替换算法:
- 最佳页面替换:替换不再使用或最长时间不使用的页面。这将确保页面错误存在的最低可能性。然而,由于人们无法预测哪个页面在将来不会被再次使用,因此无法实现 OPT 替换。
- FIFO(先进先出)页面替换:清除在主存中停留时间最长的页面。
- LRU(最近最少使用)页面替换:清除自上次访问以来耗时最长的页面。
- LFU(最少使用的)页面替换:清除一段时间内最少使用的页面。
19.什么是操作系统中的死锁?
死锁是指两个以上的进程都在等待彼此持有的资源,但是没有一个进程会先释放资源。
如果系统满足以下所有条件,则会出现死锁:
- 互斥:一次只允许一个进程访问。
- Hold & wait :一个进程正在持有一个其他人可能需要的资源,同时也在等待其他人持有的资源。
- 无抢占:一个资源不能被其他进程访问,除非拥有者进程释放它。
- 循环等待:每个进程都在等待另一个进程持有的资源。
死锁示例(作者图片)
20.如何处理死锁?
有三种方法可以处理死锁:
- 死锁预防和避免:死锁是不允许的,应该被预防或避免。
死锁预防是为了消除上面提到的死锁条件中的一个,因为当其中四个条件都满足时,就会发生死锁。
死锁避免是一种测试进程发送的每个请求是否会导致死锁状态的技术。 - 死锁检测和恢复:允许死锁。一旦检测到死锁,就抢占进程。
- **忽略问题:**当死锁很少发生时,只需重新启动系统。
参考
- 现代操作系统(第四版)
- snail climb/Java guide—GitHub
- 操作系统介绍
- 操作系统中的微内核
- 内核(操作系统)
- 操作系统—维基百科
- 流程管理简介
- 进程同步介绍
- 进程间通信的方法
- 操作系统中的 CPU 调度
- 操作系统调度算法
- 操作系统分页
- 操作系统需求分页
- 什么是需求细分?
- 操作系统死锁介绍
通过学习操作系统,你会发现这个领域涉及到如此多的计算机科学概念,因此深入研究其中的每一个主题都是非常值得和重要的。希望你觉得有用,祝你下次面试好运!
关于深度学习你想知道的
2020 年夏季学期总结。路易斯·罗查在 Unsplash 上的照片
FAU 深度学习讲义
在综合视频和博客文章中
电晕对我们许多人来说是一个巨大的挑战,并以各种方式影响着我们的生活。几年来,我一直在德国弗里德里希-亚历山大-纽伦堡大学教授深度学习课程。今年夏天,我们大学决定完全“虚拟化”。因此,我开始用 15 分钟的短片记录我的演讲。
深度学习地标检测也在 X 射线投影中发挥作用。图片由 Bastian Bier 提供。
对于“深度学习”这样的课题,你每学期都要更新一次讲座的内容。因此,我至今无法提供课堂讲稿。然而,有了录像和自动语音识别的帮助,我能够转录整个讲座。这就是为什么我决定在媒体上为每一个视频发布一个相应的,手动更正的抄本。我很高兴“走向数据科学”在他们尊敬的出版物上发表了所有这些。他们甚至要求我创建一个专栏“ FAU 讲座笔记”。所以,我想借此机会感谢数据科学对这个项目的大力支持!
阿尔法星打塞拉勒。完整视频可以在这里找到。使用 gifify 生成的图像。
为了简化博客文章的创建,我创建了一个小工具链“ autoblog ”,并且免费提供。除非另有说明,这里的所有内容都是在 CC BY 4.0 下发布的。所以,你也可以自由地重用这些内容。
在下文中,我列出了按章节分组的个人帖子,并附有相应视频的链接。如果你喜欢视频,你也可以通过播放列表观看整个讲座。注意我这学期升级了两次录音设备。从第 7 章——架构和第 9 章——可视化&注意,您应该看到视频质量有所提高。
所以,希望你觉得这些帖子和视频有用。如果你喜欢,请留下评论,或者把这个项目推荐给你的朋友。
第 1 章—简介
显示 Yolo 能力的示例序列。完整的序列可以在这里找到。使用 gifify 生成的图像。
在这些视频中,我们介绍了深度学习的主题,并展示了一些文献和应用方面的亮点
第一部分:动机&高调应用 ( 视频 )
第二部分:FAU 集锦 ( 视频 )
第三部分:深度学习的局限性及未来方向 ( 视频 )
第四部分:模式识别短期课程 ( 视频 )
第五部分:【T20
第 2 章—前馈网络
经典特征提取。 CC 下的图片来自深度学习讲座的 4.0 。
在这里,我们介绍模式识别的基础,简单的前馈网络包括层抽象的概念。
第 1 部分:我们为什么需要深度学习? ( 视频 )
第二部分:网络究竟该如何训练? ( 视频 )
第三部分:反向传播算法 ( 视频 )
第四部分:图层抽象 ( 视频)
第 3 章—损失和优化
只需几个步骤,我们就可以转换高斯分布的对数似然。下图 CC BY 4.0 来自深度学习讲座。
损失函数的一些背景知识以及深度学习与支持向量机(SVM)等经典方法的关系。
第一部分:分类回归损失 ( 视频 )
第二部分:支持向量机打败深度学习了吗? ( 视频 )
第三部分:优化与亚当和超越… ( 视频)
第 4 章—激活、卷积和池化
使用多通道卷积的正向传递。 CC 下的图片来自深度学习讲座的 4.0 。
在这一章中,我们讨论经典的激活函数,现代版本,卷积层的概念以及池机制。
第一部分:经典激活 ( 视频 )
第二部分:现代激活 ( 视频 )
第三部分:卷积层 ( 视频 )
第四部分:池机制 ( 视频
第 5 章——正规化
将函数拟合到数据可能会导致过度拟合或拟合不足。 CC 下的图片来自深度学习讲座的 4.0 。
本章探讨了过拟合问题,并讨论了避免过拟合的几种常用方法。
第一部分:偏差-方差权衡 ( 视频 )
第二部分:古典技法 ( 视频 )
第三部分:归一化&辍学 ( 视频 )
第四部分:初始化&迁移学习 ( 视频 )
第五部分:多
第 6 章—常见做法
只有在我们设置了关于培训过程的所有其他重要选项之后,才会查看测试数据。 CC 下的图片来自深度学习讲座的 4.0 。
本章致力于你在实践中会遇到的常见问题,从超参数到性能评估和显著性测试。
第一部分:优化器&学习率 ( 视频 )
第二部分:超参数和集合 ( 视频 )
第三部分:班级失衡 ( 视频 )
第四部分:绩效评估 ( 视频)
第 7 章—架构
在这一章中可以看到很多很多的架构!下图 CC BY 4.0 来自深度学习讲座。
在这一章中,我们介绍了深度学习中最常见和最流行的架构。
第一部分:从 LeNet 到 GoogLeNet ( 视频 )
第二部分:更深层次的架构 ( 视频 )
第三部分:残余人脉 ( 视频 )
第四部分:残余人脉的崛起 ( 视频 )
第五部分:学习架构(
第 8 章——递归神经网络
作家一代可以创作手写文字。更多的细节可以在文森特的博客中找到。 CC 下的图片来自深度学习讲座的 4.0 。
递归神经网络允许处理和生成依赖于时间的数据。
第一部:艾尔曼细胞 ( 视频 )
第二部:穿越时间反向传播 ( 视频 )
第三部:致敬施密德胡伯— LSTMs ( 视频 )
第四部:门控循环单元 ( 视频 )
第五部:
第 9 章——视觉化和注意力
同样的说话者,用麦克风 1(蓝色)和麦克风 2(绿色)录音,这造成了我们想要抑制的混淆。 CC 下的图片来自深度学习讲座的 4.0 。
可视化方法用于探索深层网络的弱点,并提供理解它们的更好方法。
第一部分:架构&训练可视化 ( 视频 )
第二部分:混杂因素&对抗性攻击 ( 视频 )
第三部分:直接可视化方法 ( 视频 )
第四部分:基于梯度和优化的方法 ( 视频 )
第五部分:
第 10 章—强化学习
基于智能体的器官分割。图片由夏忠提供。
强化学习允许训练能够独立行动并控制游戏和过程的代理系统。
第一部分:序贯决策 ( 视频 )
第二部分:马尔可夫决策过程 ( 视频 )
第三部分:策略迭代 ( 视频 )
第四部分:备选方法 ( 视频 )
第五部分:深度 Q 学习 ( 视频
第 11 章——无监督学习
呼吸和心脏运动使得心脏可以被模拟。 CC 下的图片来自深度学习讲座的 4.0 。
无监督学习不需要训练数据,可以用来生成新的观察值。
第一部分:动机&受限玻尔兹曼机器 ( 视频 )
第二部分:自动编码器 ( 视频 )
第三部分:生成对抗网络——基础知识 ( 视频 )
第四部分:条件&循环甘斯 ( 视频 )
第五部分
第 12 章—分割和对象检测
在组织切片图像上检测有丝分裂是一项经典的检测任务。图片由 Marc Aubreville 提供。点击查看完整视频。
分割和检测是使用深度学习的常见问题。
第一部分:分割基础知识 ( 视频 )
第二部分:跳过连接&更多 ( 视频 )
第三部分:一族区域 CNN(视频 )
第四部分:单镜头检测器 ( 视频 )
第五部分:实例分割
第 13 章——弱自我监督学习
监管不力试图充分利用你的标签。 CC 下的图片来自深度学习讲座的 4.0 。
弱监督试图最小化所需的标签努力,而自我监督试图完全摆脱标签。
第一部分:从类到像素 ( 视频 )
第二部分:从二维到三维标注 ( 视频 )
第三部分:自监督标签 ( 视频 )
第四部分:对比损失 ( 视频)
第 14 章—图形深度学习
欢迎来到图形深度学习的世界。下图 CC BY 4.0 来自深度学习讲座。
图形深度学习用于处理图形和网格中可用的数据。
第一部分:光谱卷积 ( 视频 )
第二部分:从光谱到空间域 ( 视频)
第 15 章—已知操作员学习
什么是已知算子学习?来源;推特。图像在下 CC 乘 4.0
已知算子允许将先验知识插入到深度网络中,从而减少未知参数的数量并提高深度网络的泛化性能。
第一部分:不要重新发明轮子 ( 视频 )
第二部分:学习上的界限 ( 视频 )
第三部分: CT 重建重温 ( 视频 )
第四部分:深度设计模式 ( 视频)
承认
非常感谢 Katharina Breininger、Fu、Tobias Würfl、Vincent Christlein、Florian Thamm、Felix Denzinger、Florin Ghesu、、Yixing Huang Christopher Syben、Marc Aubreville 以及我们所有的学生导师在本学期和上个学期给予我们的支持,他们制作了这些幻灯片和相应的练习,在现场和虚拟环境中教授课程,以及在过去几年中伟大的团队工作!
如果你不是 Medium 的订阅者,并且在访问这些材料时有困难,我们还会在模式识别实验室的网站上发布所有的博客文章。
如果你喜欢这篇文章,你可以在这里找到更多的文章,或者看看我们的讲座。如果你想在未来了解更多的文章、视频和研究,我也会很感激关注 YouTube 、 Twitter 、脸书或 LinkedIn 。本文以 Creative Commons 4.0 归属许可发布,如果引用,可以转载和修改。如果你有兴趣从视频讲座中获得文字记录,试试自动博客。
几乎你需要知道的关于决策树的一切(带代码)
以你想不到的方式理解决策树的指南!
托德·夸肯布什在 Unsplash 上的照片
介绍
你一生中没有一天不做任何决定。从你早餐吃什么到你感兴趣的职业,你的生活被决定所包围。假设你想出去玩板球。出门前你会寻找哪些因素?今天会下雨吗?外面会不会太热?作为一名资深玩家,你被要求接最后的电话。你从气象部门网站上查了过去几天的数据。将这些数据与今天的天气状况进行了比较,并预测天气状况非常适合进行板球比赛。瞧啊。你只是在不知道的情况下用决策树解决了问题。
在使用决策树的实际功能之前,您需要精通以下术语
- 基尼杂质
- 熵
基尼杂质与熵
两个朋友乔和萨姆开始觉得无聊了。所以他们决定玩一个游戏。找到最能把下面的点分成蓝色和橙色的线的人赢得游戏。唯一的限制是这条线必须平行于任何轴。
图 1
两人都尝试了很多,想出了下面的台词。
图 2
仅仅通过视觉化的要点,很容易说乔的尝试比山姆好。然而,当我们有两种以上的颜色时,事情会变得疯狂。人们需要一个量化值来判断分裂。这就是基尼系数不纯的原因。它谈到了错误分类点的概率。
没拿到?
让我们看看拆分前的条件,即图 1。错误分类一个点的概率有多大?
我们可能有两种方法来错误地对一个点进行分类。首先,我们选择一个蓝点,将其归类为橙色。第二,我们选择一个橙色的点,将其归类为蓝色。
图 3
和
图 4
总概率= 0.25+0.25 =0.5(开始时的基尼杂质)
任何数据分割都会将该区域分成两个或多个部分。通过对所有部分进行加权求和,计算出最终的基尼系数。基尼系数越小,分割越好。
我们来分析一下乔的企图-
图 5
同样,我们也可以分析山姆的企图-
图 6
这两种尝试都显著降低了原始基尼系数的不纯度,但是,Joe 进行了更好的分割,因为他的分割得到了更大的基尼系数增益。
设 y 是一个随机变量,取值为{y₁,y₂,y₃,….,yₖ}那么计算基尼系数的一个简单方法是
图 7
基尼杂质的性质
设 y 取值 y₊,y₋(两个班)
案例一:
当 100%的数据点属于 y₊。在这种情况下,该系统的基尼系数为
图 8
案例二:
当 50%的数据点属于 y₊时。在这种情况下,该系统的基尼系数为
图 9
案例三:
当 0%的数据点属于 y₊时。在这种情况下,该系统的基尼系数为
图 10
基尼系数与 y₊的关系曲线如下:
图 11
受够了这种基尼不纯。先说一会熵。
熵,简单来说就是数据中的随机性。想象你面前有两个盒子。盒子 1 大部分是蓝色的球,而盒子 2 是不同颜色的球。
图 12
现在从每个盒子里抽出一个球。你认为从盒子 1 中抽出的球最有可能是什么颜色?蓝色,对吗?你能预测从盒子 2 中抽出的球的情况吗?我想不会。原因是盒子 2 与盒子 1 不同,具有很大的随机性。恭喜你,你已经知道熵意味着什么了!如果你选择熵作为度量,决策树会以这样一种方式分割数据,即在每次分割时,数据的随机性不断降低。
设 y 是一个随机变量,取值为{y₁,y₂,y₃,….,yₖ}接着计算出系统的熵为:
图 13
熵的性质
设 y 取值 y₊,y₋(两个班)
案例一:
99%的数据点属于 y₊。在这种情况下,系统的熵将是:-
图 14
案例二:
当 50%的数据点属于 y₊时。在这种情况下,系统的熵将是:-
图 15
案例三:
当 1%的数据点属于 y₊时。在这种情况下,系统的熵将是:-
图 16
从 H(y) w.r.t .到 y₊的曲线将会是:
图 17
必须注意的是,当所有值出现的概率相等时,熵最大= 1。
到目前为止一切顺利。但是如何用熵来分割数据呢?
类似于基尼增益,我们使用信息增益(I.G ),来决定分割的最佳特征。
它被定义为:-
图 18
图 19:显示基尼系数和熵随 y+变化的图表
为什么基尼不纯超过熵?
熵涉及对数计算,而基尼系数涉及计算开销较小的平方计算,这就是 S klearn 库使用基尼系数作为默认选择标准来构建决策树的原因。
但是,观察到它们之间的差异很小,可以使用这两个指标中的任何一个。
构建决策树的步骤
- 决定分解/分割数据的特征:计算每个特征的信息增益,选择最大的一个。
- 继续拆分数据
- 停止拆分数据,如果:-
a)我们得到纯节点,即仅包含正或负数据点的节点,或者
b)我们在一个节点上得到很少的点,或者
c)我们到达树的一定深度
一旦您构建了一个决策树,对于一个查询点,从根到适当的叶节点遍历树。如果叶节点是纯的,预测查询点对应的类标签,否则执行多数投票。
分裂分类特征
假设我们的数据集是:
图 20
有两个特点。如果有一个特征,我们会简单地选择它。然而,当我们有一个以上的特征时,我们需要查看在分割后提供最大信息增益的特征。
从特写 F₁:开始
图 21
信息增益将是:
图 22
现在检查功能 F₂:
图 23
而信息增益(IG)₂会是:
图 24
由于 IG₂ > IG₁,我们将首先使用 F₂.要素分割数据请注意,F₂=IND 之后的节点可以使用特征 F₁.进一步分解最终的树看起来会像-
图 25
直觉
让我们使用简单的 if-else 条件重写上面的决策树:
图 26
我的朋友,这就是你的决策树。
从程序上讲,决策树只不过是一系列 if-else 条件语句。
从几何学上讲,它是一组轴平行的超平面。
分割数字特征
假设我们的数据集是:
图 27
- 按 F₁值排序
- 如果我们用 F₁分割每个值
图 28
您可以看到,我们在每个节点中只获得一个值,这导致了数据的过度拟合。
我们处理这个问题的方法是定义一个阈值,然后将数据分成两部分——一部分的值小于或等于阈值,另一部分的值大于阈值。
门槛如何确定?
图 29
我们检查每个可能阈值的信息增益,并选择使其最大化的值。这里,如果我们使用 F₁=4.2 分割数据,信息增益将最大。
有许多类别的范畴特征
我们已经看到了如何处理分类和数字特征。然而,当一个分类特征有许多类别时,事情会变得疯狂。
假设我们有一个 pin 码功能。它可能有 1000 个 pin 码,当我们使用此功能拆分数据时,它将创建 1000 个子节点,每个节点只有很少的数据点,这将导致过度拟合。
一种方法是将分类特征转换成数字特征。
代替 pin 码,我们可以有一个新功能,例如:
图 30
所以,现在如果我们使用这个新特性来分割数据,子节点将有足够的点来避免过度拟合。
过度拟合和欠拟合
当决策树的深度越大,底部节点出现非常少的数据点的可能性就越大,如果这些点是离群值,我们就会过度拟合我们的模型。因为每一个分割都只是一个 if-else 条件语句,所以模型的可解释性也会随着树的深度的增加而降低。
当树太浅时,我们可能得不到任何纯节点。纯节点是只有正点或负点的节点。在这种情况下,我们必须进行多数投票才能得出结果。
那么决策树的高度应该是多少?
身高是一个超参数,我们必须使用交叉验证数据集进行超参数调整,以获得最佳值。
训练和测试时间复杂性
列车时间复杂性:
图 31
在训练阶段发生的事情是,对于数据集中的每个特征(维度),我们将对花费 O(n log n)时间的数据进行排序,然后我们遍历数据点以找到花费 O(n)时间的正确阈值。对于 d 维,总时间复杂度为:
图 32
列车空间复杂性:
在训练决策树时,我们需要的是通常作为 if-else 条件存储的节点。
因此,列车空间复杂度将为:【O 节点】
测试时间复杂度将是 O(深度) ,因为我们必须从决策树的根节点移动到叶节点。
测试空间复杂度将为***【O(节点)***
使用决策树的回归
当我们处理回归问题时,情况就变了。这里的输出不再是一个类,而是一个实数值。
我们如何拆分数据?
与分类中的熵或基尼系数不同,我们将使用均方误差(MSE)或中位数绝对偏差(MAD)来分割数据。选择降低 MSE 或 MAD 最大的特征进行分割。
我们如何预测一个测试数据点的值?
一旦我们到达一个叶节点,我们取那里已经存在的点的平均值/中值,并预测它是给定测试数据点的输出值。
真实案例
- 不平衡数据集:建议通过上采样或类别权重来平衡数据集,因为这可能会影响熵值。
- 高维数据:随着维数的增加,训练的计算时间也增加。建议如果一个特征有许多类别,应该避免一次性编码,而是将其转换为数字特征,如上所述。
- 多类分类:决策树自然可以扩展处理多类。因为熵或基尼系数杂质可以针对两个以上的类别进行计算,并且可以通过多数表决来做出决定。
- 特征交互:出现在遍历路径中的特征相互交互,因为子节点的条件取决于父节点的条件
- 离群值:如果树很深,离群值会影响并使树不稳定。
- 可解释性:由于决策树只不过是 if-else 语句的集合,所以它具有高度的可解释性。然而,可解释性随着树深度的增加而降低。
- **特征重要性:**那些信息增益高的特征是重要的。如果一个特征被多次用于分割,我们使用由于该特征的信息增益的归一化总和。
优势
- 它不需要缩放或标准化数据
- 高度的可解释性,尤其是当维数较少时
- 适用于低延迟系统
- 较少的超参数数量
- 处理分类数据和数值数据
- 容易理解
限制
- 训练模型通常需要更长的时间
- 当您有高维数据时,它可能不合适
- 过度拟合数据的可能性很高
- 数据的微小变化可能会导致决策树结构的整体变化
- 随着深度的增加,树变得更加复杂
- 决策树通常没有其他分类或回归算法那样的预测准确性
使用 Python 构建决策树
感谢 sci-kit 学习库的 plot_tree 函数可视化决策树。我们的决策树看起来会像-
图 33
参考
- https://victorzhou.com/blog/gini-impurity/
- 统计学习导论:R 中的应用
- https://towards data science . com/decision-tree-intuition-from-concept-to-application-530744294 bb6
- M. Gopal 的应用机器学习
字母表甘:AI 生成英文字母表!
这就是我如何创建一个可以生成英文字母的 GAN。
GAN 输出在各个时期的演变
首先,你需要知道 GAN 到底是什么。这里有一个简单的描述。生成对抗网络是两个模型的组合,即生成器和鉴别器。生成器试图生成模仿原始数据的假数据。另一方面,鉴别器试图辨别一个给定的数据是原始的还是伪造的。多亏了这种对抗性的设置,最终,这两种模式在完成任务方面都变得越来越好。当然,关于甘斯还有更多需要了解的。如果你好奇,请观看这个视频…
甘是如何工作的?
在本文中,我想向您展示如何实现这样一个 GAN。我还会提到一大堆帮助你训练第一个 GAN 的技巧。但是,在进入模型之前,让我们先了解一下数据集。
数据集:A-Z 手写字母
这里,我使用的是 MNIST 风格的手写英文字母数据集。 A-Z 数据集包含来自 26 类的 372,450 个字符。每个数据样本都是字母表的灰度图像。像 MNIST 数据集一样,每幅图像的维数是 28px28px* 并表示为一个784(28 * 28)维向量。让我们想象一下其中的一些…
来自 EMNIST Letters 数据集的 100 张随机图像
最初,像素值的范围在***【0,255】之间,但是我们应该在馈送到任何机器学习模型之前将它们归一化。一般情况下,我们通过划分255.0 来归一化*【0,1】之间的像素,但这里我们归一化的是 [-1,1】之间的像素。这是因为我们后面会用到tanh(tanh=[-1,1】)函数。**
现在让我们建立我们的 GAN。我喜欢按照 4 的步骤来做。
1.建造发电机(G)
生成器是一个神经网络,它将噪声向量(100-维)作为输入,并输出单个英文字母的图像。当我们处理图像数据时,使用卷积神经网络是有意义的。其想法是在输入通过不同层时增加输入的空间维度,直到它达到期望的输出形状( 28px28px )。网络的前两层是具有 ReLu 激活的密集层。我强烈建议在每个图层的输出上使用 BatchNormalization。*
注:批处理规范化使训练收敛更快。快多了。
注意,第一密集层包含 1024 神经元,第二密集层包含 6272 神经元。之后是整形层。整形是很重要的,因为我们希望以后使用卷积,为了应用卷积,我们需要类似矩阵的实体,而不是列/行向量。
注意:为了找到正确的尺寸,我们需要向后思考!首先,确定矩阵的维数( 7*7 )以及需要多少个矩阵( 128 ),然后将它们相乘得到密集层的维数( 77128 = 6272 )。
在应用卷积之前,我们将对矩阵进行上采样。我使用了( 2,2 )上采样,将维度从 77 增加到 1414 。**
上采样是池的一种反函数。
之后,我们有了 22 卷积滤波器( 64 )。注意,我已经根据正态分布初始化了内核的权重。这一层的激活是 LeakyReLu。同样,我们有一个上采样层,后面是卷积层。这一次上采样层将输出 2828 维矩阵。最后一个卷积层只包含 1 滤镜,因为我们只想要一个通道用于灰度图像。这里的激活函数是 tanh 。这就是我们把 ***[-1,1】*之间的像素值归一化的原因。
注意:我们可以通过使用转置卷积来避免对层进行上采样。因为它们也会增加矩阵的维数。
代码:
发电机
建筑:
**Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 1024) 103424
_________________________________________________________________
batch_normalization_1 (Batch (None, 1024) 4096
_________________________________________________________________
activation_1 (Activation) (None, 1024) 0
_________________________________________________________________
dense_2 (Dense) (None, 6272) 6428800
_________________________________________________________________
batch_normalization_2 (Batch (None, 6272) 25088
_________________________________________________________________
activation_2 (Activation) (None, 6272) 0
_________________________________________________________________
reshape_1 (Reshape) (None, 7, 7, 128) 0
_________________________________________________________________
up_sampling2d_1 (UpSampling2 (None, 14, 14, 128) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 14, 14, 64) 32832
_________________________________________________________________
batch_normalization_3 (Batch (None, 14, 14, 64) 256
_________________________________________________________________
leaky_re_lu_1 (LeakyReLU) (None, 14, 14, 64) 0
_________________________________________________________________
up_sampling2d_2 (UpSampling2 (None, 28, 28, 64) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 28, 28, 1) 577
=================================================================
Total params: 6,595,073
Trainable params: 6,580,353
Non-trainable params: 14,720
_________________________________________________________________**
你注意到我没有在这里编译生成器吗?这将在第 第三 步骤中完成。
2.构建鉴别器(D)
我们的鉴别器只是一个二元分类器,它将灰度图像作为输入,并预测它是原始图像还是伪造图像,即由生成器创建的图像。前两层是卷积层。请注意,我使用了一个步幅 2 ,这意味着输出尺寸将小于输入尺寸。所以,我们不需要池层。两层的滤波器大小都是 55 ,但是第二层中的滤波器数量更多。*
注意:在构建鉴别器时,你应该记住我们的目标是支持生成器,因为我们想要生成假图像。因此,使鉴别器比发生器弱一点。例如,这里我在鉴别器中使用了较少的卷积层。
在卷积层之后,我们需要展平输出,这样我们就可以把它传递到一个密集层。密集层的大小是 256 与 50% 的落差。最后,我们有了 sigmoid 层,就像任何其他二元分类器一样。我们现在必须编译鉴别器。损失应该是二进制交叉熵,我已经使用了一个定制的亚当优化器(学习率= 0.0002 )。
注意:默认的 Adam 学习率( 0.001 )对于 GANs 来说太高了,所以请始终定制 Adam 优化器。
代码:
鉴别器
建筑:
**Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_3 (Conv2D) (None, 14, 14, 64) 1664
_________________________________________________________________
leaky_re_lu_2 (LeakyReLU) (None, 14, 14, 64) 0
_________________________________________________________________
conv2d_4 (Conv2D) (None, 5, 5, 128) 204928
_________________________________________________________________
leaky_re_lu_3 (LeakyReLU) (None, 5, 5, 128) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 3200) 0
_________________________________________________________________
dense_3 (Dense) (None, 256) 819456
_________________________________________________________________
leaky_re_lu_4 (LeakyReLU) (None, 256) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 256) 0
_________________________________________________________________
dense_4 (Dense) (None, 1) 257
=================================================================
Total params: 1,026,305
Trainable params: 1,026,305
Non-trainable params: 0
_________________________________________________________________**
3.联合 G & D
根据原 GAN 论文我们要分别训练发生器和鉴别器。那为什么要走这一步?
可以通过反向传播在最后一个 sigmoid 层计算的损耗来直接训练鉴别器。但是为了训练生成器,我们需要在不影响鉴别器权重的情况下,将这种损失发送回生成器!
实现这一点的一种方法是通过堆叠生成器和鉴别器来创建新的模型。这也是我之前没有编译生成器的原因。我们把新型号叫做甘。它将噪声向量作为输入,然后通过生成器创建一个假图像。然后图像通过鉴别器,鉴别器计算它是原始图像的概率。当我们训练这个 gan 时,鉴别器不应该学习任何东西。因此,’ discriminator . trainiable = False '。 只有生成器的权重会被修改。
代码:
发电机+鉴频器= gan
建筑:
**Model: "model_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 100) 0
_________________________________________________________________
sequential_1 (Sequential) (None, 28, 28, 1) 6595073
_________________________________________________________________
sequential_2 (Sequential) (None, 1) 1026305
=================================================================
Total params: 7,621,378
Trainable params: 6,580,353
Non-trainable params: 1,041,025
_________________________________________________________________**
4.火车
终于准备好训练我们的 GAN 了!你觉得代码看起来奇怪吗?别担心,我会解释每一步。
代码:
GAN 的训练环路
外层用于遍历各个时期,内层用于批处理。我已经训练了 80 个时期的模型,并且批次大小是 128。因此,在一个时期中,我们将有 2909(每时期步数= ⌊数据数量 samples/batch_size⌋=⌊372,450/128⌋= 2909)步。
G 固定时的 D 列:
首先,通过从标准正态分布中随机抽取数字来形成噪声向量的 batch_size 数目。然后将这些向量交给生成器来创建假图像。现在我们从训练数据中画出真实图像的 batch_size 数。为了得到鉴别器的输入,我们需要连接假数据和真数据。相应的,我们需要提到标签向量(0:假数据,1:真数据)。但是等等,代码说的是 0.1 和 0.9!WTH 是怎么回事?
这种技术叫做水平平滑。它防止鉴别者对其预测过于自信。
然后,我们为鉴别器调用 train_on_batch 函数,并传递数据标签对。
G 固定时的 D 列:
这里,我们只需要噪声向量和标签。标签向量包含 1。等等,生成器制造假数据,所以标签不应该是 0 吗?
是的。但在这里我们故意给错误的标签,使歧视犯错误。原因是我们希望发电机的性能优于鉴别器。通过这样做,G 将知道 D 在被给定真实标签时的行为,并且它(G)将相应地改变它的权重来愚弄 D。记住,在这个阶段,我们没有改变鉴别器的权重,因此鉴别器没有“忘记”任何东西。
现在,我们为生成器调用 train_on_batch 函数,并传递数据标签对。而那就是朋友,一个甘是怎么练出来的!
让我向您展示一些我的模型产生的最佳(精选)结果…
人工智能生成的字母(T,P,J,S,A,E,L,U)
这里是这个项目的完整代码。瞧啊。现在你知道如何训练甘了!
如果你想进一步探索,请看这个…
人工智能生成 2 种语言的字母(英语和孟加拉语)
我希望你喜欢阅读。下次见…学习愉快!
一种新的强化学习算法
了解并实现 AlphaZero,完全用 JavaScript 实现!
在这篇博文中,你将了解并实现 AlphaZero ,这是一种令人兴奋的新颖的强化学习算法,用于在围棋和国际象棋等游戏中击败世界冠军。您将使用它来掌握一个钢笔和铅笔游戏(点和方框),并将其部署到一个 web 应用程序中,完全用 JavaScript 编写。
AlphaZero 的关键和最令人兴奋的方面是它能够在不依赖外部知识的情况下,在棋盘游戏中获得超人的行为。AlphaZero 通过与自己对弈(自我对弈)和从那些经历中学习来学习掌握游戏。
我们将利用 Github 中可用的 Surag Nair 的 AlphaZero 的“简化的、高度灵活的、有注释的、易于理解的实现”Python 版本。
你可以在这里玩游戏。WebApp 和 JavaScript 实现在这里可用。这段代码是从这个 Python 实现移植过来的。
https://carlos-aguayo.github.io/alphazero/
AlphaZero 是由 Silver,David 等人在论文中描述的“ 掌握没有人类知识的围棋游戏”nature 550.7676(2017):354–359。
点和盒子游戏
《点和盒子》是一个初级的儿童游戏,有着惊人的复杂程度。
两名玩家轮流在两个相邻的点之间放置一条水平线或垂直线。完成 1×1 方块第四边的玩家得一分,并获得另一轮机会。棋盘满了,游戏结束,得分最多的玩家获胜。
人工智能和桌游
我们已经思考了很长时间,如果机器可以证明智能。如何验证机器展现智能行为的能力?一种典型的方式是玩棋盘游戏,如国际象棋,并试图获得超人的行为来击败世界冠军。
1957 年,希尔伯特·西蒙预言计算机系统将在十年内击败国际象棋世界冠军 i 。它花了更长的时间,但在 1997 年 5 月的,一台计算机打败了国际象棋世界冠军加里·卡斯帕罗夫。
尽管这个里程碑意义非凡,但人们可能会争论这个计算机系统是否是“智能的”。
这些计算机系统由三部分组成:
- 自定义的评估函数。
- 博弈树搜索算法。
- 非常强大的硬件。
评估函数将棋盘作为输入,并返回棋盘的“值”。高值表示当前玩家处于非常有利的位置。例如,棋手将要将死的棋盘配置将具有非常高的值。
博弈树搜索算法(如 Minimax )搜索所有可能的走法,寻找一个能保证有高价值的棋盘配置的路径。通过不访问那些我们知道找不到更好价值的配置,可以提高搜索效率。这就是Alpha–beta 修剪的作用。
最后,添加非常强大的硬件,你将拥有一台能够击败世界冠军的机器。
有什么条件?有经验的玩家 手动工艺 这些评价函数。这些系统将依靠开局书来指示最著名的棋步。中级游戏将使用通过研究大师的游戏而创建的评估函数。然后大师们会进一步微调它们。
例如,我们可以为点和盒子游戏创建一个评估函数。一个合理而直接的评估函数是比较分数。分数中的正 delta 越高,棋盘游戏越有利。在大多数情况下,这是可行的。然而,在点和盒子游戏中,就像在许多棋盘游戏中一样,最好的行动可能包括牺牲短期利益以获得更好的长期收益。在点和盒子游戏中,有时最好不要在盒子中得分,以避免获得另一轮机会,相反,要迫使对方移动。然后,我们必须调整我们的评估函数,以考虑越来越多的复杂场景!
击败卡斯帕罗夫的评价函数有 8000 个特征!这些功能中的大部分都是手工创建和调整的!
因此,在不贬低像击败国际象棋世界冠军这样的重要里程碑的情况下,一个不可取的方面是需要顶级玩家定义这些计算机的行为,并手动调整如此多的变量。
alpha zero 是什么,为什么这么激动人心?
AlphaZero 是第一个能够在国际象棋或围棋等游戏中获得超人行为的计算机系统,它击败了世界冠军,仅依靠游戏规则而没有人类领域的知识。
如果只给定游戏规则,AlphaZero 将开始自相残杀。一点一点地学习策略和技术,相对快速地获得超人的行为。
像深蓝这样的系统需要国际象棋专家的帮助,而 AlphaZero 会通过与自己对弈变得强大。此外,AlphaZero 不仅在国际象棋上表现出超人的力量,在围棋上也是如此。围棋对电脑来说是一个更复杂的游戏,因为它的更大的游戏空间和其他因素。
虽然人类从数千年的数百万场游戏中积累了像 T4 围棋和国际象棋这样的游戏知识,但 AlphaZero,一种只使用游戏规则的简单算法,在几天内重新发现了这些知识和新策略。
甚至还有一部关于它的电影。
仅通过自我游戏,AlphaZero 将如何学习?
回想一下,像 DeepBlue 这样的系统依赖于人定义的“评估函数,它将电路板状态作为输入,并输出状态的“值”。
如今,深度学习模型非常容易将图像作为输入,并将其分类为狗或猫。这个想法是将棋盘作为深度学习模型的输入,并训练它预测棋盘是赢还是输的配置。
但是训练机器学习,需要数据,大量的数据。你从哪里得到游戏的数据集?很简单,我们让计算机自己玩,生成一组游戏,并从中制作一个数据集。
AlphaZero 训练算法
算法很简单:
- 让电脑和自己玩几局游戏,记录棋盘的每一步棋。一旦我们知道了结果,在游戏结束时用给定的结果更新所有的棋盘,“赢”或“输”。然后,我们建立了一个数据集,提供给神经网络(NN ),并开始学习给定的电路板配置是赢还是输。
- 克隆神经网络。使用上一步中生成的数据集训练克隆。
- 让克隆神经网络和原始神经网络相互对抗。
- 挑一个神经网络赢的,丢掉另一个。
- 转到步骤 1。
就像魔术一样,经过多次迭代,你就有了世界级的模型。这个模型仅用了 4 个小时就成功超越了最强的电脑象棋程序!
AlphaZero 组件
AlphaZero 有两个组成部分。我们已经讨论过第一个,也就是神经网络。第二个是“蒙特卡罗树搜索”或 MCTS。
- 神经网络(NN) 。将棋盘配置作为输入,输出棋盘的值,以及所有可能走法的概率分布。
- 蒙特卡罗树搜索(MCTS) 。理想情况下,神经网络足以选择下一步行动。我们仍然希望看到尽可能多的董事会配置,并确保我们确实选择了最好的行动。像极小极大一样,MTCS 是一种算法,它将帮助我们了解董事会的配置。不像极小极大,MTCS 将有助于有效地探索游戏树。
让我们深入细节,确定下一步行动
跟随 AlphaZero 更容易,首先看它在决定下一步棋(竞技模式)时的行为,然后再看训练套路。
神经网络已经很擅长对事物进行分类,比如猫和狗。这里的想法很简单,神经网络可以学习将棋盘配置分类为赢与输吗?更具体地说,神经网络将预测表示赢与输的概率的值。此外,它将输出所有可能移动的概率分布,表示我们下一步应该探索哪个动作。
神经网络将游戏状态作为输入,输出一个值和一个概率分布。具体对于点和方框来说,游戏状态由三个元素表示:首先,一条线是否已经玩过,使用 0 和 1 的数组表示穿过点的每条线。如果一个玩家已经给这条线着色,则为 1,否则为 0。第二,如果当前移动是通过,第三,分数。我们可以用这三个元素来表示所有需要的信息,以确定董事会的价值并预测其下一步行动。
我们来分析一下下面的博弈,该轮到蓝玩家了。蓝有两个选择,走上面的路输了,或者走下面的路赢了。
如果蓝色先玩 23 然后玩 21,红色赢。相反,如果蓝色先玩 23 再玩 9,蓝色就赢了。如果 AlphaZero 要出蓝色,它如何找到获胜的一步?
你可以用这个笔记本重现下面看到的结果。
如果我们将棋盘配置输入神经网络,我们将得到一个数组,其中包含每个动作移动概率:
move_probability[0]: 9.060527501880689e-12
move_probability[1]: 3.9901679182996475e-10
move_probability[2]: 3.0028431828490586e-15
move_probability[3]: 7.959351400188552e-09
move_probability[4]: 5.271672681717021e-11
move_probability[5]: 4.101417122592821e-12
move_probability[6]: 1.2123925357696643e-16
move_probability[7]: 6.445387395019553e-23
move_probability[8]: 2.8522254313207743e-22
**move_probability[9]: 0.0002768792328424752**
move_probability[10]: 1.179791128073232e-13
move_probability[11]: 5.543385303737047e-13
move_probability[12]: 3.2618200407341646e-07
move_probability[13]: 4.302984970292259e-14
move_probability[14]: 2.7477634988877216e-16
move_probability[15]: 1.3767548163795204e-14
move_probability[16]: 8.998188305575638e-11
move_probability[17]: 7.494002147723222e-07
move_probability[18]: 8.540691764924446e-11
move_probability[19]: 9.55116696843561e-09
move_probability[20]: 4.6348909953086714e-12
**move_probability[21]: 0.46076449751853943**
move_probability[22]: 2.179317506813483e-20
**move_probability[23]: 0.5389575362205505**
move_probability[24]: 5.8165523789057046e-15
我们还获得了板配置的值:
-0.99761635
你可以在这里找到生成这些值的代码。
这些输出中有一些有趣的东西:
- 在 8 个可能的移动中,最有可能的移动是 23、21 和 9。如果 NN 打 23 或 21,他得一分。23 是赢棋,其值(0.53)略高于 21 的值(0.46)。
- 神经网络将输出概率,即使是无效的移动。遵循游戏规则并确保我们不玩无效的动作是代码的工作。
- 该值为-0.99。这表明 AlphaZero 认为它已经输掉了这场比赛。该值的范围从-1(失败)到 1(成功)。这个值应该更接近于 1(赢)而不是-1(输),因为我们知道这是一个赢的状态。也许我们需要更多的训练回合来达到这样一种状态,即 AlphaZero 将学习这种板配置的正确值。
利用神经网络的输出来决定我们的下一步很有诱惑力。
在桌游中(在生活中!),玩家在决定自己的下一步棋时,通常会看到许多“前面的棋”。这里也没什么不同。我们使用神经网络预测来选择下一步要探索的状态,并忽略那些低价值的状态。像 Minimax 一样,传统的人工智能博弈树搜索算法效率低下,因为它们必须在进入下一步之前分析每一步棋。即使有很小的分支因素的游戏也使他们的游戏空间难以处理。分支因子是可能的移动次数。随着游戏的进行,可能的移动次数会发生变化。如果是这样,你计算一个平均分支因子。国际象棋的平均分支因子是 35。围棋是 250。
这意味着,在国际象棋中,仅仅走了两步,就有 1,225 (35)种可能的棋盘布局,而在围棋中,可能是 62,500 (250)。在点和框中,对于一个 3x3 的游戏,初始分支因子是 24,并且随着每一步棋而减少(除非是一次通过)。所以在中局中,当分支因子为 15 时,仅三步棋就有 2730(15 * 14 * 13)种棋盘布局。
相反,NN 会引导我们,告诉我们应该探索哪里,避免被许多无用的路径淹没。NN 告诉我们 23 和 21 是很强的移动。
这是蒙特卡洛树搜索的工作。
蒙特卡罗树搜索(MCTS)
神经网络已经给了我们下一步行动的指示。蒙特卡洛树搜索算法将帮助我们遍历节点,选择下一步行动。
看看这个链接中这篇论文对蒙特卡罗树搜索的图形描述。
MCTS 的工作方式是,对于给定的电路板,它将运行 N 次模拟。n 是我们模型的一个参数。在这些模拟的最后,下一步将是最受欢迎的。你可以跟随代码到这里。
运行 n MCTS 模拟
MCTS 模拟包括遍历游戏树,从当前棋盘开始,通过选择具有最高“置信上限(UCB)”值(定义如下)的节点,直到我们到达我们以前没有访问过的游戏状态,这被称为“叶子”。这就是本文所称的 A 部分“选择”。
UCB 是什么?就是 Q(s,a) + U(s,a)。其中“s”是状态,“a”是动作。Q(s,a)是我们期望从动作“a”之后的状态“s”中得到的期望值,与 Q-Learning 中的值相同。请记住,在这种情况下,该值的范围将从-1(输)到 1(赢)。 U ( s ,a)∧P(s,a)/(1+N(s, a )。这意味着 U 与 P 和 N 成比例,其中 P(s,a)是元组(s,a)的先验概率,即 NN 返回的值,N(s,a)是我们访问状态 s 并采取行动 a 的次数。
# Upper Confidence Bound
ucb = Qsa[(s,a)] + Ps[s,a] * sqrt(Ns[s]) / (1 + Nsa[(s,a)]
UCB 的要点是最初偏好具有高先验概率§和低访问计数(N)的动作,但是渐近地偏好具有高动作值(Q)的动作。
你可以沿着这里的看代码。
A 部分—选择置信上限最高的行动(UCB)
一旦找到一片叶子,我们就用神经网络来搜索这块板子。这就是本文所说的 B 部分,“扩展和评估”。你可以跟随代码到这里。
B 部分—扩展和评估
最后,我们将传播神经网络返回的值。这就是论文所说的 C 部分“备份”。你可以跟随代码到这里。
C 部分—备份
决定下一步棋
我们来看看 AlphaZero 是如何针对上面提到的状态确定下一步行动的。
AlphaZero 将运行 50 次蒙特卡罗树搜索模拟。
您可以使用这个笔记本重现下面看到的结果。
这些是每次迭代遵循的路径:
Simulation #1 -> Expand root node
**Simulation #2 -> 23**
Simulation #3 -> 21
Simulation #4 -> 9
Simulation #5 -> 17
Simulation #6 -> 12
Simulation #7 -> 19
Simulation #8 -> 3
Simulation #9 -> 18
**Simulation #10 -> 23,24**
Simulation #11 -> 21,24
**Simulation #12 -> 23,24,21**
Simulation #13 -> 21,24,23,24
**Simulation #14 -> 23,24,9**
**Simulation #15 -> 23,24,17**
Simulation #16 -> 21,24,9
**Simulation #17 -> 23,24,12**
**Simulation #18 -> 23,24,18**
Simulation #19 -> 21,24,17
**Simulation #20 -> 23,24,21,24,9**
Simulation #21 -> 21,24,19
**Simulation #22 -> 23,24,3**
Simulation #23 -> 21,24,18
**Simulation #24 -> 23,24,19**
Simulation #25 -> 21,24,23,24,17
**Simulation #26 -> 23,24,21,24,18**
**Simulation #27 -> 23,24,21,24,3**
Simulation #28 -> 21,24,3
**Simulation #29 -> 23,24,21,24,19**
Simulation #30 -> 21,24,12
**Simulation #31 -> 23,24,21,24,9,24**
Simulation #32 -> 21,24,23,24,12
**Simulation #33 -> 23,24,21,24,9,24,18**
Simulation #34 -> 21,24,23,24,9,24,17
**Simulation #35 -> 23,24,21,24,9,24,12**
**Simulation #36 -> 23,24,21,24,9,24,3**
Simulation #37 -> 21,24,23,24,9,24,19
**Simulation #38 -> 23,24,21,24,9,24,18,17**
Simulation #39 -> 21,24,23,24,9,24,18,17,24
**Simulation #40 -> 23,24,21,24,9,24,18,17,24,19**
Simulation #41 -> 21,24,23,24,9,24,18,17,24,19,24
**Simulation #42 -> 23,24,9,21**
**Simulation #43 -> 23,24,9,18**
**Simulation #44 -> 23,24,9,17**
**Simulation #45 -> 23,24,9,19**
**Simulation #46 -> 23,24,9,12**
**Simulation #47 -> 23,24,9,21,24**
**Simulation #48 -> 23,24,9,3**
**Simulation #49 -> 23,24,9,21,24,18**
**Simulation #50 -> 23,24,9,21,24,17**
上面的意思是:在第一个模拟中,我们以前没有见过那个板,因此它是一个“叶”节点,并“扩展”它。扩展意味着它用神经网络评估该板。
Simulation #1 -> Expand root node
在第二个模拟中,我们已经扩展了根节点,因此它不再是“叶子”,因此我们可以搜索具有最高 UCB 的节点
UCB 最高的动作是 23。它进入那个状态,因为它以前没有见过那个状态,因此它是一个叶节点,它展开它,第二个模拟完成。
Simulation #2 -> 23
在这种情况下,神经网络给出 23 的损失值。我们之前讨论过这个。神经网络可以使用更多的训练来了解它确实是一个糟糕的状态。但是现在,这仍然有效,我们将在下面看到。
对于接下来的模拟,每次,具有最高 UCB 的选项是剩余的选项。这是因为在访问每个动作后,它发现它的值很低,因此 UCB 也很低。
Simulation #3 -> 21
Simulation #4 -> 9
Simulation #5 -> 17
Simulation #6 -> 12
Simulation #7 -> 19
Simulation #8 -> 3
Simulation #9 -> 18
在接下来的模拟中,一个令人兴奋的模式开始浮现。记住中奖顺序是 23,24(跳过),9。
Simulation #10 -> 23,24
Simulation #11 -> 21,24
Simulation #12 -> 23,24,21
Simulation #13 -> 21,24,23,24
Simulation #14 -> 23,24,9
Simulation #15 -> 23,24,17
Simulation #16 -> 21,24,9
Simulation #17 -> 23,24,12
Simulation #18 -> 23,24,18
Simulation #19 -> 21,24,17
Simulation #20 -> 23,24,21,24,9
Simulation #21 -> 21,24,19
Simulation #22 -> 23,24,3
Simulation #23 -> 21,24,18
Simulation #24 -> 23,24,19
在模拟 10 到 24 中,MCTS 已经将其注意力集中在节点 21 和 23 上。这是有意义的,因为这两条路中的任何一条,我们都得了一分。
Simulation #33 -> 23,24,21,24,9,24,18
Simulation #34 -> 21,24,23,24,9,24,17
Simulation #35 -> 23,24,21,24,9,24,12
Simulation #36 -> 23,24,21,24,9,24,3
Simulation #37 -> 21,24,23,24,9,24,19
Simulation #38 -> 23,24,21,24,9,24,18,17
Simulation #39 -> 21,24,23,24,9,24,18,17,24
Simulation #40 -> 23,24,21,24,9,24,18,17,24,19
Simulation #41 -> 21,24,23,24,9,24,18,17,24,19,24
然后在模拟 33 到 41 中,它开始深入失败的组合。注意一个有趣的事情。尽管深入,它永远不会到达游戏的结尾,因为仍然有可玩的移动。
Simulation #42 -> 23,24,9,21
Simulation #43 -> 23,24,9,18
Simulation #44 -> 23,24,9,17
Simulation #45 -> 23,24,9,19
Simulation #46 -> 23,24,9,12
Simulation #47 -> 23,24,9,21,24
Simulation #48 -> 23,24,9,3
Simulation #49 -> 23,24,9,21,24,18
Simulation #50 -> 23,24,9,21,24,17
然后,在模拟 42 至 50 中,在 NN 的帮助下,它认识到 23、24、21 或 21、24、23 不是好的选项,并完全集中在获胜序列 23、24、9 上。
50 次模拟后,我们的时间到了,我们需要选择一步棋。MCTS 选择了我们去过最多的地方。以下是我们每次移动的次数(在第一次行动中):
counts[3] = 1
counts[9] = 1
counts[12] = 1
counts[17] = 1
counts[18] = 1
counts[19] = 1
counts[21] = 15
counts[23] = 28
在前 10 个模拟中,动作 3、9、12、17、18 和 19 仅被访问一次。然后 MCTS 把注意力集中在第 21 步和第 23 步。最近 9 次模拟访问行动 23。鉴于我们访问 23 号行动最多,达 28 次,MCTS 将其作为下一步行动。
有哪些外卖?
- 通过每次模拟,MCTS 将依靠神经网络,使用累积值(Q)、神经网络给出的移动先验概率§以及它访问节点的频率的组合,来跟随看起来最有希望的路径。或者换句话说,具有最高 UCB 的路径。
- 在每次模拟期间,MCTS 将尽可能深入,直到它到达一个它以前没有见过的板配置,它将依赖神经网络来评估板,以告诉板有多好。
如果我们将它与经典方法进行比较,如使用带有 Alpha-Beta 修剪和评估函数的 Minimax,我们可以说:
- 在 Minimax 中,深度是由设计者建立的参数。它会深入到那个深度,然后使用评估函数。如果没有 Alpha-Beta 修剪,它将不得不访问给定深度的所有节点,效率非常低。在上面的场景中,还剩 8 步棋,深度为 3,这意味着评估 336 个棋盘。在 MTCS,有 50 个模拟,我们只需要评估 50 个板,并设法深入得多。
- 阿尔法-贝塔剪枝会帮助我们减少 336 这个数字。然而,它不允许我们走一条智能的道路。
- 我们依靠神经网络随时告诉我们电路板的“价值”,而不是使用人类定义的评估函数。
- 有趣的是,神经网络在最初的移动中没有预测到正确的值。然而,当我们深入游戏而没有一直到游戏结束时,它有正确的预测。
- 最后,注意 AlphaZero 的优雅和简单。而在 Alpha-Beta 剪枝中,您必须跟踪 Alpha 和 Beta 参数才能知道在哪里剪枝,并且人工定义的评估函数可能很难使用。MCTS 和 NN 让一切变得优雅而简单。你可以用 JavaScript 实现这一切!
训练神经网络
我们遗漏了最后一个关键方面。我们如何训练神经网络?
幸运的是这很简单。我们之前提到过这些步骤:
- 让电脑在“训练模式”下和自己玩几局,记录棋盘的一举一动。一旦我们知道了结果,在游戏结束时用给定的结果更新所有的棋盘,“赢”或“输”。然后,我们建立了一个数据集,提供给神经网络(NN ),并开始学习给定的电路板配置是赢还是输。
- 克隆神经网络。使用上一步中生成的数据集训练克隆。
- 让克隆神经网络和原始神经网络相互对抗。
- 挑一个神经网络赢的,丢掉另一个。
- 转到步骤 1。
玩“训练模式”是什么意思?差别很小。当在“竞争模式”下玩时,我们总是选择访问量最高的棋步。而在“训练模式”中,对于游戏开始时的一定数量的移动,计数成为我们的概率分布并鼓励探索。例如,假设有 3 个可能的操作,访问次数为[2,2,4]。在竞争模式下,我们总是选择第三个动作,因为它有最高的访问计数。但是在训练模式中,[2,2,4]变成了概率分布,2+2+4 = 8,因此[2/8,2/8,4/8]或[0.25,0.25,0.5]。换句话说,我们 50%的时间选择第三个动作,而 25%的时间探索第一个和第二个动作。
然后我们用一个简单的井字游戏来描述数据集。
在上面的游戏中,第一个玩家,Xs 获胜。
我们可以这样配置棋盘的状态:如果方块还没有下完,则为 0;如果第一个玩家下了方块,则为 1;如果第二个玩家下了方块,则为-1。
例如,董事会如下:
0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0
0 0 0 -> 0 0 0 -> -1 0 0 -> -1 1 0 -> -1 1 0 -> -1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 -1 0 1
或者:
[0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0,-1, 0, 0, 0, 0, 0]
[1, 0, 0,-1, 1, 0, 0, 0, 0]
[1, 0, 0,-1, 1, 0,-1, 0, 0]
[1, 0, 0,-1, 1, 0,-1, 0, 1]
然后我们必须做两件事。首先,更新每个棋盘,就好像轮到玩家 1 了。我们总是从第一个玩家的角度向神经网络提供训练数据。在 TicTacToe,这很简单。每次轮到第二个玩家时,我们可以翻转棋子,变成玩家 1 的视角。
我们从这里开始:
[0, 0, 0, 0, 0, 0, 0, 0, 0] # Player 1 turn
**[1, 0, 0, 0, 0, 0, 0, 0, 0] # Player 2 turn**
[1, 0, 0,-1, 0, 0, 0, 0, 0] # Player 1 turn
**[1, 0, 0,-1, 1, 0, 0, 0, 0] # Player 2 turn**
[1, 0, 0,-1, 1, 0,-1, 0, 0] # Player 1 turn
**[1, 0, 0,-1, 1, 0,-1, 0, 1] # Player 2 turn**
对此:
[ 0, 0, 0, 0, 0, 0, 0, 0, 0] # Player 1 turn
**[-1, 0, 0, 0, 0, 0, 0, 0, 0] # Player 1 turn**
[ 1, 0, 0,-1, 0, 0, 0, 0, 0] # Player 1 turn
**[-1, 0, 0, 1,-1, 0, 0, 0, 0] # Player 1 turn**
[ 1, 0, 0,-1, 1, 0,-1, 0, 0] # Player 1 turn
**[-1, 0, 0, 1,-1, 0, 1, 0,-1] # Player 1 turn**
第二,我们追加游戏结果。如果一号玩家赢了,我们就用“1”,如果输了,就用“0”。
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, **1**] # Winning board
[-1, 0, 0, 0, 0, 0, 0, 0, 0, **0**] # Losing board
[ 1, 0, 0,-1, 0, 0, 0, 0, 0, **1**] # Winning board
[-1, 0, 0, 1,-1, 0, 0, 0, 0, **0**] # Losing board
[ 1, 0, 0,-1, 1, 0,-1, 0, 0, **1**] # Winning board
[-1, 0, 0, 1,-1, 0, 1, 0,-1, **0**] # Losing board
数据集开始有一些形状了!正如你从上面看到的,我们可以把它输入神经网络来学习棋盘上的输赢值。
不过,我们忽略了概率。那些是从哪里来的?请记住,在训练模式下,我们仍然会在每一步运行 MCTS 模拟。与我们记录棋盘配置的方式相同,我们将记录概率。
然后,我们克隆神经网络,并使用该数据集训练克隆,预计它会随着使用新数据而稍微变强。我们通过让它与原来的 NN 竞争来验证它确实更强。如果它赢了 55%以上的时间,我们认为它更强,并放弃原来的,克隆成为我们新的神经网络。
我们不断重复这个过程,神经网络会不断变强。
你可以从论文这里看到图表。
为什么数据集有更强的动作可以学习?通过学习 MCTS 生成的概率,他们通常会选择比神经网络给出的原始移动概率更强的移动。我们通过让 MCTS 深入许多路径来提供神经网络知识!
用这个笔记本训练一个点和方框模型。
将其部署到 WebApp 中
几个月前,我发表了一篇博文,带你完成将 Keras 或 Tensorflow 模型转换成供 Tensorflow.js 使用的 JavaScript 的过程。我们将转换我们在 Keras 中训练的模型,以便在 Tensorflow.js 中使用。
这个笔记本将预先训练的点和方框模型转换成 Tensorflow.js 模型。
一旦我们这样做了,我们就可以轻松地用 JavaScript 加载模型,如这里的所示。
结论
在这篇博文中,你了解了 AlphaZero,这是一种新颖的强化学习算法,可以在双人零和棋盘游戏中击败世界冠军。
您了解了它如何沿着神经网络使用蒙特卡罗树搜索来找到最佳的下一步行动。你也学会了如何训练这个神经网络。
我希望你喜欢这篇博文,并发现它很有价值。如果是,伸出!
我是 Appian 的软件开发高级总监兼机器学习工程师。我在 Appian 工作了 15 年,我一直很开心。这个疫情并没有让我们放慢脚步,我们正在招聘!给我发一条消息如果你想知道我们是如何制作软件的,请取悦我们的客户,玩得开心!
AlphaZero 和人工智能之美
自我学习人工智能如何重新定义我们的创造力概念
Natasha Reddy 在 Unsplash 上的照片
2016 年,谷歌的 AlphaGo 以 4:1 击败围棋世界冠军 Lee Sedol 的胜利引起了不仅仅是围棋界的轰动,超过 1 亿人观看了比赛。这是人工智能发展的一个里程碑:围棋经受住了计算机科学家构建可以在人类水平上玩很长时间的算法的尝试。现在,一个人造大脑已经建立起来,控制着一个花了数千小时练习来相对轻松地磨练技艺的人。
这已经是相当大的成就了,但随后 AlphaGoZero 出现了,给 AlphaGo 吃了点自己的药:它以 100:0 的优势战胜了 AlphaGo,仅在 Lee Sedol 失败一年后。这更加壮观,而且不仅仅是因为显而易见的原因。AlphaGoZero 不仅是 AlphaGo 的改进版本。AlphaGo 曾在最好的人类围棋选手进行的专家游戏的帮助下进行训练,AlphaGoZero 则从零开始,在没有任何监督的情况下解决了游戏的复杂性。
给定的无非是游戏规则和如何赢 ,它把自己锁在自己的虚拟房间里,和自己对弈只有 34 个小时。它不仅将人类历史上建立起来的对游戏原则和美学的理解与计算机毋庸置疑的超强数字能力结合起来,而且它本身就成为了已知宇宙中的主导力量。
它是如何做到这一点的?
国际象棋和围棋
在西方,国际象棋远比围棋更受欢迎。部分原因可能是文化上的,某种与东西方知识分子性格相关的亲缘关系。国际象棋有时被比作基于规则的西方思维,而围棋更类似于东方思维的整体倾向。围棋被认为比象棋更开放,更直观。
这个角度有助于解释科学家们在建造围棋计算机和象棋计算机方面的巨大成功差异。毕竟,人工大脑的统治地位对于国际象棋界来说已经是很久以前的新闻了。
计算机一出现,人们就试图建造下棋计算机(计算机科学先驱巴贝奇、图灵、香农和冯·诺依曼都在设计特定的象棋硬件),使象棋成为历史上所有人工智能中研究得最彻底的问题。
作为这一发展的高潮,深蓝在 1997 年赢得了世界冠军加里卡斯帕罗夫赢得了国际赞誉。三年后,最好的围棋计算机仍然被一个 9 岁的男孩打败(包括九步障碍)。
这种差异是相当深刻的,并且与游戏的基本构成的差异有关。理解它有助于解释为什么构建围棋引擎比象棋引擎困难得多,也有助于解释为什么它一旦成功,就是我们追求人工智能的一个里程碑。
战术与战略
“国际象棋是表现逻辑科学的艺术.”
米哈伊尔·博特文尼克
为了克服这个问题,程序员需要 好的试探法和决策表来排除明显不好的走法 并树桩决策树(参见这里关于国际象棋中决策树的好介绍)。
这些在国际象棋中比在围棋中更容易获得:一个棋子大约值 1,一个主教和骑士 3,一辆车 4,一个皇后 9,如果你控制了中心,你通常更好,如果你的棋子被开发,那通常是好的,如果你的棋子被连接,那是好的,等等。(和所有事情一样,例外证实了规则)。
在对未来棋步树进行了深入的、启发式的增强搜索之后,国际象棋的位置可以被数值化地评估为黑棋或白棋的某个值。因此,人工智能的符号化、基于规则的方法在上个世纪的大部分时间里最受欢迎,似乎最有前途,这种方法自然适用于国际象棋,而构建更好的引擎的问题是找到更有效的算法来搜索决策树,并提升计算能力。
但是对于围棋来说,这是行不通的:用同样的方法评估围棋的位置要困难得多。人类所说的“直觉”和长期策略起着更大的作用。在许多情况下,即使是职业围棋手也无法解释他们对棋局的直觉。可能发生的事情太多了,搜索树膨胀得太快,无法建立具有明确标准的算法,从而使它们能够与人类竞争。
所以围棋需要用完全不同的方法来破解。深度学习革命在一个方便的时间到来,提供了大量的新技术。正如 AlphaGo 团队的领导者 David Silver 解释的那样,AlphaGo 是第一个不依赖于结构化搜索,而是使用强化学习和深度神经网络的算法。
正如他们的成功所证明的那样,这种方法非常有效。
强化学习
“强化学习感觉就是智能。”
大卫·西尔弗
强化学习可以粗略地定义为在环境中交互的智能代理。正如我在这里使用的“智能”一词已经表明的那样,强化学习的问题更清楚地表述了人工智能的整体问题。我们自己的智慧最明显地体现在我们在我们称之为世界的复杂而不确定的环境中运作的能力上。我们可以设定自己的目标,或者通过探索我们的环境和解决挡在我们和目标之间的问题来追求目标。
我们可以想象一个围棋手坐下来开玩笑地探索游戏,可以想象以这种方式发现一个新的创造性想法意味着什么。因此,与我们对智力的直觉理解相比,AlphaGoZero 背后的原理非常切中要害。
这就是为什么大卫·西尔弗认为人工智能的未来很可能建立在强化学习的基础上。
直觉在象棋中的作用
虽然在国际象棋中构建符号人工智能是可能的,但不应该忘记,我们所说的“直觉”在游戏中对人类玩家也起着巨大的作用。虽然现代国际象棋引擎可以通过计算大量可能的走法并将其与专家游戏数据库进行比较来评估任何位置,但大师们没有这种奢侈,尽管他们可以提前计算许多走法,但他们也依赖于对位置优点和走法质量的直观估计,特别是在快速、闪电战或火箭棋等更快的时间格式中(每个玩家只有 15 到 1 分钟)。
“不是所有的艺人都是棋手,所有的棋手都是艺人”
马塞尔·杜尚
国际象棋从来不仅仅是一门科学。国际象棋也是一项运动,国际象棋也是一门艺术,一种独特的奇观,在这种奇观中,永恒的美可以与表演同时发生,就像在爵士乐唱片上一样。所以在国际象棋中,艺术和科学元素之间总是有相互影响的。这些在每一个优秀的棋手和每一局棋中都有体现,尽管侧重点明显不同。但正如所料,在过去的二十年里,这一重点一直在转移。
计算机的出现在现代国际象棋上留下了痕迹,并在国际象棋界引发了一股迷人的活力。这一发展可能预示着人类的许多发展,质疑我们如何定义自己和一些使我们最像人类的东西:我们的艺术,我们的创造力,我们的美感。
机器如何改变了国际象棋
为了和棋而战,至少是用白棋,在某种程度上是对国际象棋的一种犯罪。
米哈伊尔·塔尔
继 1997 年世界冠军卡斯帕罗夫击败深蓝之后,国际象棋再也不一样了。如果电脑比人类更擅长下棋,那么肯定有东西可以向它们学习。因此,现代国际象棋大师开始在引擎的帮助下研究位置,检查组合,评估位置,并在组合力和远见的帮助下研究最好的移动。2013 年阿南德对阵卡尔森的冠军赛被许多人认为是老一代国际象棋选手与新一代新星之间的比赛,新一代新星是第一个在超级计算机的帮助下训练他们一生的人。卡尔森赢了,开创了国际象棋的新时代,这可能在 2018 年的世界锦标赛中得到最好的概括,卡尔森和卡鲁阿纳以平局结束了所有 12 场锦标赛。
当然,错误对于一盘棋来说是不好的,但是错误是不可避免的,而且在任何情况下,一盘没有错误的棋,或者如他们所说的“完美的棋”是无色的。
一些人批评说,高水平的国际象棋越来越不在于大胆的牺牲和漂亮的攻击,而在于不犯任何错误,很好地理解位置,并从里到外知道许多开口中的最佳步骤(然后赢得平局的残局,正如世界冠军卡尔森所熟知的那样)。当然,这也是由于极高的比赛质量,这是今天达到国际象棋世界的顶峰所必需的。
国际象棋中人的因素
对我来说,国际象棋与其说是一门科学,不如说是一门艺术。
米哈伊尔·塔尔
但部分原因也是由于引擎:社区中的一些人声称“机器毁了国际象棋”,现代国际象棋缺乏“人”的元素,缺乏早期大师们在经典游戏中发现的灵感和新鲜感。保罗·墨菲或阿道夫·安德森的游戏,如常青树或歌剧院之夜在玩了 150 年后仍被分析,而卡帕布兰卡或塔尔等大师的游戏继续让人们爱上这个游戏。但是“人类”国际象棋的时代真的结束了吗?“人类”国际象棋是由扭断脖子的攻击和灵感的击打来定义的吗?
米哈伊尔·塔尔有很多绰号:在国际象棋界,他被简单地称为来自里加 的 魔术师。像除他之外的少数人一样,他把棋手描绘成艺术家、诗人、古怪、大胆和有趣的人。他的许多戏剧性的牺牲在国际象棋界获得了传奇般的地位。他玩游戏不是为了画画,而是为了让每一场游戏都像一首诗:独特、激动人心、感人肺腑,如果一切顺利的话,还会很美。尽管如此,许多人认为现代大师会轻松战胜老大师。因为虽然戏剧性的牺牲有时会压垮对手,动摇阵地,招致错误(塔尔将其比作将对手带入黑暗森林),并在残局中带来优势,但如果小心应对,它们也很容易导致浪费材料,不稳定的阵地,并最终导致失败。
但也许我们的二分法是错误的。机器思维一定要表现机械僵化,蛮算吗?是不是要拿出游戏的精神?对我们来说,人造思维一定看起来是人造的和陈腐的吗?还是有另一种美有待发现?
AlphaZero 说是的:它可能会再次改变现代国际象棋。
AlphaZero 和人工智能之美
机器毁了国际象棋。自学式人工智能可能会拯救国际象棋。
agadmator
AlphaZero 是一个多面手:它从围棋转到了国际象棋,经过不到 24 小时的训练,它击败了目前市场上最强大的国际象棋引擎 Stockfish。
AlphaZero 的下棋有些奇特。它做出的动作看起来像人类,而且具有根本性的创造力。AlphaZero 可以玩得很激进,追求长期策略,看似戏弄对手,聪明而富有想象力地关闭棋子。几乎像一个人,几乎像棋盘的那些诗人,几乎像塔尔,但更好:像打了类固醇的塔尔。
我一直在想,如果有一个高级物种降落在地球上,向我们展示他们是如何下棋的,那会是怎样的。现在我知道了。
彼得·海恩·尼尔森
观看 AlphaZero 的一些游戏会是一次鼓舞人心的经历。它的玩法对于人类玩家来说几乎是不可思议的。外星象棋,即使是大师级的。包括世界冠军芒努斯·卡尔森在内的许多人都在研究 AlphaZero 的国际象棋游戏。根据卡尔森的说法,他们给他带来了关于游戏的新想法和观点,并帮助他改善了自己的风格。阿尔法在训练阶段通过不同“人类”入口的方式也引起了人们的兴趣。
深蓝 20 年后,人工智能再次改变了国际象棋。
在围棋中也观察到了类似的模式:在与李·塞多尔(Lee Sedol)的第二场比赛中,AlphaGo 做出了著名的“37 步棋”。它违背了围棋选手从小就被教导的所有规则,没有一个职业选手预料到这一点。它被计算机发现,成为人类共享知识的一部分。同样,在最初的失败震惊之后,Lee Sedol 甚至说 AlphaZero 让他重新感受到了游戏的乐趣,因为他意识到在他一生都在探索的游戏中还有很多东西需要探索。
这会把我们引向何方
“创造力是充满乐趣的智慧.”
爱因斯坦
照片由 Tim Mossholder 在 Unsplash 上拍摄
创造力意味着发现以前不知道的东西。随着 AlphaZero 通过一个发现过程进行训练,它有空间变得真正有创造力,甚至提出了我们所说的创造力是什么的问题。
对于加里·卡斯帕罗夫(Gary Kasparov)来说,AlphaZero 的出现是人工智能历史上比深蓝更深远的时刻,因为它是基于发现的。当我们想到 AI 的曙光时,我们会想到机器思维慢慢接管人类的冰冷理性。我们通常不会想到创造力,以及由此带来的乐趣。
我们是万有引力无法阻止我们冒险进入太空的类人猿。我们是以接近光速的速度向对方发射质子,并发现数十亿光年外黑洞的引力涟漪的类人猿。我们是现实中难以置信的复杂性和错综复杂性的代理人,不断探索,不断学习。AlphaZero 向我们展示了人工大脑的发现如何为我们不断的好奇心提供灵感。还有许多其他领域,错综复杂的模式的相互作用丰富了我们的生活。有音乐(Deepfake 音乐开始听起来令人恼火的好)、诗歌、艺术、科学。
在这些领域中,我们可能过于执着于我们的理想,即创造性和有意义的意义。
AlphaZero 之所以如此伟大,正是因为它展示了人工智能可以为这种组合增加什么:而且人工智能不必剥夺我们相信让我们成为最具人性的人的快乐。
牛郎星情节解构:可视化天气数据的相关结构
使用交互式 Altair plots、Python 和 Pandas 更有效地探索天气数据集的相关结构
本文的一个 Jupyter 笔记本,包括资料,在我的 GitHub 上有 。另外,这是我写的关于用 Python 制作朱朱情节的 系列文章 的一部分。
即使在我的上一篇文章中对 plotnine 大加赞赏之后,它在一个主要方面还是有所欠缺:交互性。幸运的是,一篇关于媒介的文章为我指出了一个专门研究交互性的绘图框架。Altair 是一个用于 Python 的声明式统计可视化库,基于 Vega 和 Vega-Lite 。Vega-Lite 是由华盛顿大学交互数据实验室(UW IDL)开发的,它提供了一种简单、直观和一致的定义绘图的方法。定义地块的风格与 plotnine 和 ggplot2 具有类似的声明性原理(视觉语法):您不指定单独的线和点,而是指定地块轴和地块层。在我看来,这使得代码更加易读和紧凑。
本文的主要情节使用两个相连的子情节探索了天气数据集的相关性结构:一个相关性热图和一个显示点密度的 2d 直方图。下面的动画 gif 展示了实际的情节:
单击热图中的矩形,将显示与该特定单元格相关的变量在 2d 直方图中的相应数据。该图使您能够使用热图快速查看相关性模式,并允许您放大 2d 直方图中这些相关性背后的数据。
在本帖中,您将了解以下主题:
- 如何通过在 2d 直方图中聚合数据来处理 Altair 和大量数据。
- 如何在 Altair 中使用相同数据中的数值对分类轴上的值进行排序。当数据动态变化并且您无法预先计算值应该如何排序时,这尤其有用。
- 如何动态连接热图和二维直方图?这里的主要困难在于如何格式化数据以使其工作,另请参见 Altair Github 页面上的这个问题。
在本文中,我将读取和处理数据,并慢慢构建静态版本的关联热图和 2d 直方图。最后,我将把情节连接在一起,实现交互性,并创建一个有凝聚力的交互情节。
读取数据
本文中的数据集包含我从荷兰皇家气象研究所( KNMI )下载的气候数据。下面的代码将文本文件读入一个熊猫DataFrame
:
DataFrame
包含单个气象站 nr 277 (Lauwersoog)在 2009 年和 2020 年之间的天气数据。除了日期(数据)和站 id,所有其他列包含天气相关变量的测量值。在这种情况下,Wsp
代表风速,T
代表温度,Precip
代表降雨量,humid
代表湿度。KNMI 使用这些数据来跟踪荷兰各地不同时间的所有天气变量。比如:6 月份的平均气温是如何随时间变化的,或者说降水量与平均气温有什么相关性。
静态关联热图
本文的主要目标是理解我们数据集中 12 个天气变量的相关模式。如果有的话,这个数据集中不同变量之间的相互作用是什么。本部分的最终目标是静态版本的关联热图。
我们在 pandas 中使用`. corr '函数来计算相关性,这产生了一个相关性矩阵。请注意,我使用堆栈将相关矩阵中的数据转换为长格式数据集,这是在 Altair 中绘图所需要的。
有了这些数据,我们可以制作关联热图:
该图由两层组成:具有相关性的文本层(text)和颜色对应于相关性的矩形层(cor_plot)。标签显示了实际的相关性,矩形层显示了相关性中的模式。
静态二维直方图
既然我们可以可视化相关的模式,我们可以构建 2d 直方图来显示单个相关的细节。我选择使用 2d 直方图而不是常规散点图来:
- 减少数据量。我们不必单独显示所有点,而只需显示分箱的数据。尤其是在绘图时,点太多会显著降低绘图速度。
- 使重叠点清晰可见。在正常的散点图中,重叠点往往会聚集在一起。在 2d 直方图中,重叠点导致该条柱中的点密度更高,使观察者清楚地看到这里有更多的点。
牛郎星可以执行宁滨的飞行,但随着我们的数据量牛郎星情节变得非常缓慢。为了加快绘图速度,我们使用 numpy.histogram2d 预先计算 2d 直方图。我们首先定义一个执行宁滨的函数,并将数据转换为 Altair 所需的长格式:
然后,我们使用该函数计算每个变量组合的面元 2d 数据:
还要注意raw_left_value
列,它们是宁滨区间的左侧。这些将用于在绘图中正确排序轴标签。
根据该数据,这产生了下面的Rel_humid
对Precip_hrmax
的 2d 直方图:
这很好地说明了这两个变量之间 0.17 的低相关性。还要注意使用EncodingSortField
根据 raw_left_value 变量对 x 轴和 y 轴上的标签进行正确排序。通常这些是按字母顺序排列的,但现在是从小到大。
交互所需的 2d 直方图数据的格式化
也许你已经注意到我组织 2d 直方图数据的方式有些奇怪。对于我在上面展示的单个图,我可以更简单地组织数据,就像在下图的原始表格中所做的那样:简单地为每个入库的变量列出一列:
但是,2d 直方图的数据格式类似于图中的 Melt2 表。我们:
- 将数据从宽格式转换为长格式
- 用长格式合并原始数据
- 再次转换为长格式
这是获得关联热图和 2d 直方图工作之间的交互性所必需的。当我们点击关联热图时,Altair 会跟踪选择了哪个变量,例如Precip_hrmax
和Rel_humid
。接下来,我们需要更新二维直方图。Altair 的一个怪癖是我们只能基于行而不是列进行子集划分。所以我们不能简单地取Precip_hrmax
列和Rel_humid
列中的值。复杂的熔融-合并-熔融数据格式对于仅使用行选择获得每个变量组合的装箱数据至关重要。核心是简单地重复每个变量的数据。
有了这种数据格式,我们就可以为Precip_hrmax
选择所有数据,通过variable2
仍然可以获得所有其他变量:
通过在“变量 2”上设置子集,我们得到了绘图所需的最终数据:
结合两个图
现在我们已经设置了两个图,我们需要连接两个图。连接通过选择器完成,在本例中为selection_single
:
我们将选择器耦合到数据集(corr 和 binned 2d)中的变量和变量 2 字段,并将选择器分别初始化为变量和变量 2 的蒸发和 T_max。现在我们要做的就是:
- 将选择器连接到关联热图。这意味着,如果我单击热图,它会记录单击了 variable 和 variable2 的哪个值。
- 在绘制图之前,使用选择器对 2d 直方图数据进行子集划分。这自动化了我们之前通过调用
knmi_data_2dbinned.query()
手动完成的工作。
使用transform_filter
完成 2d 面元数据的子集化:
以下代码定义了所有的图,通过选择器将它们连接起来,并生成所需的连通交互式图形:
这张最终的图表允许您自由探索数据的关联结构,并产生一些有趣的见解:
Global_radiation
对Sol duration
显示了 0.87 的高相关性。2d 直方图支持这一点,但也使图片有细微差别。大多数点位于图的左下边缘。这表明相关性严重依赖于数据的尾部。Wsp_1hravg
对Precip_total
显示 0.31 的低相关性,但是 2d 直方图显示有一个信号:在较高风速期间,风速的增加似乎与降雨量的增加相关。这种相关性主要被较低的风速所抵消。
这使得读者可以很容易地发现相关性的趋势,但也可以深入到一个特定相关性的细节。
现在这个图的一个缺陷是轴的标题还没有更新。现在最好的方法就是记住value
和variable
属于同一个地方,而value2
和variable2
属于同一个地方。但是让这一点更清楚是我留给读者的一个很好的练习。
最后
Altair 是一个很棒的工具,它通过交互性极大地扩展了你创作引人注目的相关插图的选择。语法是一致的,选项是无穷无尽的。此外,与 Jupyter 笔记本的集成是无缝的,并且部署到现有网站上也很容易。为了让你的牵牛星更上一层楼,我建议你去看看人物画廊,探索一下哪些类型的情节是可能的。
我要感谢 Rob Wanders 为本文的早期草稿提供反馈。
本文的一个 Jupyter 笔记本,包括数据,在我的 GitHub 上有 。
如果你喜欢这篇文章,你可能也会喜欢我的其他一些文章:
Altair vs. Matplotlib
Python 可视化库的比较
如果你刚刚开始学习 Python,你可能听说过 Matplotlib。Matplotlib 是任何 Python 初学者的首选可视化库,但它是最好的吗?
在这篇文章中,我将介绍和讨论 Altair 和 Matplotlib 的区别,它们擅长什么,谁应该使用它们?
首先,我们来分析一下 Matplotlib 擅长什么。
我将使用数据面板来嵌入来自每个库的可视化,以便图形保留它们的特征。
Matplotlib
Matplotlib 是一个详尽的可视化库,包含许多功能。它的概念是基于 MATLAB 的绘图 API。使用过 MATLAB 的人会感觉更自在。这很可能是科学家将学习的第一个 Python 可视化库数据。
Matplotlib 让简单的事情变得简单,让困难的事情变得可能。
上图描述了 Matplotlib 图形的一般概念。
图片来自 Matplotlib 文档。
赞成的意见
- 可定制
由于 Matplotlib 的底层接口特性,它可以绘制任何东西。如果你只是想要一个快速的实验,几行代码就可以绘制出你想要的任何数学函数。如果你想绘制复杂的观想,稍加修改,你就能做到!甚至支持 3D 可视化。
先说一个简单的情节。
import numpy as np
import matplotlib.pyplot as pltx = np.linspace(1, 100)
y = 3 * x ** 2fig = plt.figure()
plt.plot(y)
plt.title(r"$y = 3x^2$")
它甚至可以绘制以下文本:
# [https://gist.github.com/khuyentran1401/d0e7397ecefcb8412a161817d1e23685#file-text-py](https://gist.github.com/khuyentran1401/d0e7397ecefcb8412a161817d1e23685#file-text-py)fig = plt.figure()plt.text(0.6, 0.7, "learning", size=40, rotation=20.,
ha="center", va="center",
bbox=dict(boxstyle="round",
ec=(1., 0.5, 0.5),
fc=(1., 0.8, 0.8),
)
)plt.text(0.55, 0.6, "machine", size=40, rotation=-25.,
ha="right", va="top",
bbox=dict(boxstyle="square",
ec=(1., 0.5, 0.5),
fc=(1., 0.8, 0.8),
)
)
- 动画
Matplotlib 还提供了一个实时动画包。它允许你绘制实时数据,如正弦波,甚至纳斯达克股票市场指数!
"""
==================
Animated line plot
==================
"""
# [https://matplotlib.org/3.1.1/gallery/animation/simple_anim.html](https://matplotlib.org/3.1.1/gallery/animation/simple_anim.html)import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animationfig, ax = plt.subplots()x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))def animate(i):
line.set_ydata(np.sin(x + i / 50)) # update the data.
return line,ani = animation.FuncAnimation(
fig, animate, interval=20, blit=True, save_count=50)# To save the animation, use e.g.
#
# ani.save("movie.mp4")
#
# or
#
# writer = animation.FFMpegWriter(
# fps=15, metadata=dict(artist='Me'), bitrate=1800)
# ani.save("movie.mp4", writer=writer)plt.show()
骗局
- 不灵活
由于其低级接口的性质,绘制简单的数据将是容易的。然而,当数据变得非常复杂时,诸如格式化之类的琐碎问题将需要更多的代码行。
我将使用本文中的 GitHub 数据集来演示:
[## 我收集了超过 1k 的顶级机器学习 Github 配置文件,这就是我的发现
从 Github 上的顶级机器学习档案中获得见解
towardsdatascience.com](/i-scraped-more-than-1k-top-machine-learning-github-profiles-and-this-is-what-i-found-1ab4fb0c0474)
下图显示了当数据变得庞大而复杂时,它看起来是多么杂乱无章。
接下来,我们来了解一下牛郎星。
阿尔泰尔
Altair 采用了与 Matplotlib 完全不同的方法。这是一个声明性的统计可视化库,最初于 2016 年发布,基于 Vega 和 Vega-Lite 构建。它还使用 Pandas Dataframe 进行数据表达。他们心中有三种设计方法:
- 受约束的、简单的和声明性的,以允许关注数据而不是诸如格式化之类的琐碎问题。
- 发出遵循 Vega 和 Vega-Lite 规范的 JSON 输出
- 使用现有的可视化库呈现规格
赞成的意见
- 直观且结构化
Altair 提供了一种非常直观和结构化的绘图方法。我将使用 Matplotlib 部分中的简单示例:
import numpy as np
import altair as altx = np.linspace(1, 100)
y = 3 * x ** 2df_alt = pd.DataFrame({'x': x, 'y': y})alt.Chart(df_alt).mark_line().encode(
x='x',
y='y'
)
你可以看到我们如何用 Matplotlib 做同样的事情,但是代码更少!
牛郎星的基本特征:
- 马克斯(英格兰人姓氏)
标记指定数据在图中的表示方式。例如,mark_line()
将数据表示为线形图,mark_point()
使其成为散点图,mark_circle()
创建带有实心圆的散点图。
- 编码
编码由encode()
调用。它允许将数据映射到不同的通道,如 x、y、颜色、形状等。例如,如果我的数据框架中有多列,我可以将 x 轴和 y 轴映射到不同的数据列。或者,如果我想用不同的颜色给我的图着色,我可以改变我的编码通道。
- 互动
《牛郎星》最独特的特点之一就是互动剧情。使用interactive()
你可以让任何情节互动,允许你放大和缩小,突出情节的某些区域等等。当您有大量复杂的数据时,此功能特别有用。
- 灵活
凭借其声明性,Altair 只需几行代码就可以绘制复杂的数据集!这使得数据科学家在数据可视化方面有更好的用户体验,而不必担心琐碎的绘图问题。
下面的例子展示了 Altair 的交互性和灵活性。直方图绘制了突出显示的区域。想组合多个剧情?使用&
符号即可!您已经可以看到构建这样复杂的东西所需的代码有多少了。
# [https://altair-viz.github.io/gallery/selection_histogram.html](https://altair-viz.github.io/gallery/selection_histogram.html)
from vega_datasets import datasource = data.cars()brush = alt.selection(type='interval')points = alt.Chart(source).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color=alt.condition(brush, 'Origin:N', alt.value('lightgray'))
).add_selection(
brush
)bars = alt.Chart(source).mark_bar().encode(
y='Origin:N',
color='Origin:N',
x='count(Origin):Q'
).transform_filter(
brush
)plot = points & bars
plot
骗局
- 不可定制
通过 Altair 的声明式和高级绘图方法,它使绘制复杂的机器学习模型变得更加困难。在 Altair 文档中,他们也不建议创建超过 5000 行的图,这会导致错误。
- 没有三维可视化
数据科学家通常需要在 3D 平面上进行可视化,以便更好地解释数据。它的例子包括降维技术,如主成分分析(PCA),或 word2vec 等等。在这种情况下,我会默认使用 Matplotlib 或其他具有更好 3D 可视化支持的可视化库。
结论
就是这样!我希望你学到了一些关于 Matplotlib 和 Altair 的新知识。现在,你应该在你的项目中实践你所学到的东西。如果您热衷于学习更多关于数据可视化的知识,您应该探索其他库,如 Seaborn、Plotly、Bokeh 和 Folium。
对使用哪种可视化工具感到困惑?我为你分析了每个图书馆的利弊
towardsdatascience.com](/top-6-python-libraries-for-visualization-which-one-to-use-fe43381cd658)
上面由 Khuyen 写的文章包括了 6 个不同可视化库的概要。
最后,如果你想和我聊天,请在 LinkedIn 上联系我!
替代数据:利用记者的行为进行交易
利用出版行为预测市场波动
为什么不是情感分析?
新闻情感分析作为一种替代数据形式正在成为主流。数据提供商已经在他们的平台上提供文本挖掘产品,金融机构的内部研究团队已经研究了一段时间。NLP 模型在试图解释报告中的单词、短语和数字时也会变得非常复杂。
https://www . Bloomberg . com/news/news/news/2020-06-12/开始新的一天需要知道的五件事
在这种情况下,像 130 这样的数字意味着什么?消极的词比积极的词多,这是否意味着该段落有积极的情绪?对谁有利?即使考虑了文章的上下文,人类读者可能仍然无法理解这些数字对谁意味着什么,更不用说机器了。这让我想到了另一种方法,我们可以系统地从这些报告中获取价值。
气泡诱导回声室
【http://g.foolcdn.com/image/? URL = https % 3A % 2F % 2fg . fool cdn . com % 2f editorial % 2f images % 2f 152771% 2f broker-ratings . jpg&w = 1200&h = 630&op = resize
我偶然看到关于市场分析师的回声室性质的评论,这使我有一种直觉,最大最早的记者往往能够直接或通过他们报道的回声影响每日市场。我时常有这样的印象,当一家极具影响力的媒体报道他们认为重要的日常事件时,当天晚些时候的报道听起来往往非常相似。发生的事件肯定是市场的关键驱动因素,但报告本身可能会影响市场的势头和狂热。
一个新的保守的想法
你熟悉这个吗?
http://www . Bloomberg . com/news/news/news/2020-06-12/开始新的一天需要知道的五件事
我认为这份来自彭博的每日报告代表了我所提到的内容。虽然它可能不是对前一天+前一夜发生的个别事件的最快报道,但我认为它是我能访问的最受欢迎和最快的事件摘要之一。你可能没有注意到报告的出版日期和时间。
http://www . Bloomberg . com/authors/ARIYqLnEHrg/lor can-Roche-Kelly
我注意到 Lorcan Roche Kelly 几乎是自 2015 年 4 月以来这份报告背后唯一的人。事实上,我发现这是在他作为编辑加入彭博市场后不久出现的。
【http://www.linkedin.com/in/lorcan-roche-kelly-8aa31422/
这让我对他的出版行为感兴趣,这导致了我的假设和最终的交易信号。
我们能利用出版行为来预测每日市场波动吗?
虽然他可能有 101 个原因来提前或推迟发布报告,例如,度过了一个糟糕的夜晚,错过了上班的交通工具,有一个讨厌的实习生不愿意一大早离开他,但我愿意首先相信信号的可能性。假设他这些年来一直在处理日常事务,我预计,在一个普通的日子里,如果他在前一天有更多的事件要报道,或者如果他必须报告一篇可能需要更多事实核查的重要文章,他可能需要更长的时间来发表报告。然后,我们可以用这个时间作为代理,来确定市场在开盘时对消息数量或大小的反应会有多不稳定。
这一想法的优点在于,从报告发布之时起,就可以立即、系统地表明对波动性的立场。它也不会暴露于任何可能是不必要的风险的消息解密。假设这份报告在市场上有分量,我们可以在势头到来之前低价买入。
数据
彭博是出了名的难刮,所以我求助于我的快速手得到报告的日期和时间。如果你有其他选择,请告诉我!我把 UTC 00:00:00 开始的秒数作为我的自变量。我用 yfinance 得到了 S & P500 的价格,并采用了一个 10 大小的滚动窗口每日回报标准差作为我的每日波动性度量,这被用作我的因变量。然后 X 和 Y 都被归一化。
我们可以观察到最近的黑天鹅,波动率飙升至 8 SDs。我去掉了超过 3sd 的点,做了一个散点图。一个简单的回归结果显示 publish_time 的 R 平方为 0.02,t-stat 为 5.075。
模型
该模型是两个变量的简单线性回归,用于使用看不见的报告的 publish_time 预测样本外波动率。出于方便,我使用了 VIX 指数,并把它当作一只股票来交易,但你可以使用从 VIX 期货到 SPX 跨界的东西,从及时性和模型成本中获取更多阿尔法。如果预测波动率 z 值比前一天增加至少 0.05,模型将买入开盘价,卖出收盘价。同样,如果预测它将减少至少 0.05,则模型会将其做空。否则,不会采取任何立场。
结果
包括新冠肺炎期和异常值在内的整个数据集被分为训练:2015 年 4 月 1 日至 2019 年 8 月 19 日和测试:2019 年 8 月 20 日至 2020 年 6 月 11 日。在整个测试期间,该模型的表现优于持有长期 VIX 的基准。它产生了正的预期回报,但由于 0.02 的无风险利率,夏普比率为负。
Model
Expected Return: 0.0064269
Daily Volatility: 0.076790
Sharpe Ratio: -0.17676
Long VIX throughout
Expected Return: -0.0048733
Daily Volatility: 0.079744
Sharpe Ratio: -0.31192
结论
我提出了一个观察每日早市电话/报告的及时性的原始想法,以获得市场每日波动的信号。甚至使用目前的替代数据流似乎是一个回音室,正在慢慢失去它的优势。我希望这可以推广到其他数据源,用于各种产品的交易,或者以其他方式补充当前替代数据的使用。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
用于数据科学的替代 Python 库
旨在为初学者简化数据科学过程的一些有用的库
马克·弗莱彻·布朗在 Unsplash 上的照片
机器学习领域正在突飞猛进地发展。以同样的速度,新的库正在被添加到数据科学武库中。如今,一个任务可以用多个库以多种方式执行。在所有这些过多的新库中,有几个因其易用性和开箱即用的实现而脱颖而出。在本文中,我将介绍五个这样的库,它们可以加速传统机器学习的过程,从而降低入门门槛。
下面是代码的链接。
1.数据分析基线库
Dabl 库由 Andreas Mueller 创建,他是 scikit-learn 机器学习库的核心开发者和维护者之一。dabl 背后的想法是让监督机器学习对初学者来说更容易理解,并减少常见任务的样板文件。Dabl 从 scikit-learn 和 auto-sklearn 中获得灵感。该库正在积极开发中,因此不建议用于生产。参考官方网站获取更多信息和示例。
装置
*# Installing the library*
!pip install dabl
使用
Dabl 可用于数据集的自动化预处理、快速 EDA 以及初始模型构建,作为典型机器学习管道的一部分。让我们在泰坦尼克号数据集的帮助下演示这个库的一些用例。我们将从导入库和数据集开始。
#import the basiclibraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt#importing dabl
import dabl#import the dataset
titanic_df = pd.read_csv('../input/titanic/train.csv')
titanic.info()
titanic.info() |作者图片
- 检测特征类型
作为预处理的一部分, dabl 试图识别缺失值、特征类型和错误数据。如果检测语义类型(连续、分类、序数、文本等。)失败,用户可以提供 [type_hints](https://amueller.github.io/dabl/dev/user_guide.html#data-cleaning)
也可以提供。
titanic_df_clean = dabl.clean(titanic_df, verbose=1)
2。使用 dabl 进行探索性数据分析
dabl 提供了一个高级界面,总结了几个常见的高级图。显示低维数据集的所有特征;对于高维数据集,仅显示给定任务的最具信息性的特征。让我们看看这个过程是如何进行的。
dabl.plot(titanic_df, target_col="Survived")
目标分布|作者图片
作者图片
作者图片
作者图片
上面所有的图都是用一行代码生成的。
3。使用 dabl 建立初始模型
dabl 还可以快速找到我们数据的基线模型。SimpleClassifier 实现了拟合和预测的标准 scikit-learn API。
ec = dabl.SimpleClassifier(random_state=0).fit(titanic_df, target_col="Survived")
作者图片
2.情感
Emot 是 Python 的表情符号和表情检测包。当我们必须预处理我们的文本数据以消除表情符号和表情符号时,它会非常方便。这个库接受一个字符串作为输入,并返回一个字典列表。
装置
*# installation and importing the library*
!pip install emot
使用
我们来看几个包含表情符号和表情符号的字符串。我们将使用表情符号将这些表情符号转换成文本。
import emot
text = "The weather is ☁️, we might need to carry our ☂️ :# Detecting emojis
("emot.emoji(text)
作者图片
# Detecting emoticons
emot.emoticons(text)
作者图片
3.Flashtext
Flastext 是一个 Python 包,让你从一个句子中提取关键词或者替换句子中的关键词。它基于 FlashText 算法,比 NLP 任务的正则表达式要快得多。
装置
# installation and importing the library
!pip install flashtext -q
使用
数据集来自之前的 Kaggle 比赛:真实与否?灾难推文 NLP,目标是创建一个机器学习模型来预测推文是否属于灾难类别。这是一个二元分类问题的恰当例子。让我们导入库和数据集,并快速浏览一下数据。
from flashtext import KeywordProcessor
twitter_df = pd.read_csv('data/tweets.csv')
twitter_df.head()
作者图片
让我们为训练集中的所有 tweets 创建一个语料库。
corpus = ', '.join(twitter_df.text)
corpus[:1000]
作者图片
- 提取关键词/搜索语料库中的单词
我们来计算一下’ flood '这个词在语料库中出现了多少次?
processor = KeywordProcessor()
processor.add_keyword(‘flood’)
found = processor.extract_keywords(corpus)
print(len(found))
58
单词flood
在上述语料库中出现 58
次。
2。替换文本文档中的单词
我们还可以轻松替换文档中的单词。让我们用这个库来替换所有出现的单词。forest fire
’(不区分大小写)与fire'
同。
processor = KeywordProcessor(case_sensitive = False)
processor.add_keyword('forest fire','fire')
found = processor.replace_keywords(corpus)
print(found[:100])
作者图片
单词Forest Fire
被替换成了单词 fire。类似地,我们也可以替换特殊字符、超链接等。从一份文件中。
4.SweetViz
Sweetviz 是一个开源的 Python 库,它可以用一行代码为 kickstart EDA(探索性数据分析)生成漂亮的高密度可视化效果。输出是一个完全独立的 HTML 应用程序。
该库可以执行以下任务的快速分析:
- 目标分析
- 想象和比较
- 混合型协会
- 类型推断:自动检测数字、分类和文本特征,可选手动覆盖,等等
让我们通过泰坦尼克号数据集来看看它的演示
装置
# Installing the library
!pip install sweetviz
使用
Sweetviz 有一个名为 **Analyze(),**的函数,该函数分析整个数据集并提供详细的可视化报告。
# importing sweetviz
import sweetviz as sv
#analyzing the dataset
advert_report = sv.analyze(titanic_df)
#display the report
advert_report.show_html('titanic.html')
HTML 报告视图|来源:https://github.com/fbdesignpro/sweetviz
SweetViz HTML 报告视图|作者视频
5.数字计算器
Numerizer 是一个 Python 模块,用于将自然语言数字转换成整数和浮点数。它是红宝石编号器的端口。这在预处理文本数据时很有用。
装置
!pip install numerizer
使用
我们将看到 numerizer 如何快速地将文本数字转换成数字。
作者图片
结论
这些是我最近遇到的一些有趣且有用的数据科学 python 库。这些库在某种程度上替代了现有的库,但可以用来补充它们。最终目标是增强和优化机器学习过程,降低初学者的门槛。如果你知道其他可以添加到列表中的人,请在下面的评论中提到他们。