谷歌的气流:对 Cloud Composer 的第一印象
日前,Google Cloud 公布了 Cloud Composer 的测试版。简而言之,Cloud Composer 是针对气流的托管解决方案,这是一个开源平台,用于以编程方式创作、调度和监控工作流。对于不熟悉气流的数据人员:您主要使用它来编排您的数据管道。
Airflow
由于我一直在寻找气流的托管解决方案,所以我决定本周带着 Cloud Composer 去兜一圈。托管解决方案的好处在于,作为一名数据工程师或数据科学家,您不必在开发运维上花费太多时间——这是您可能不太擅长的事情(至少我不擅长!).
因此,下面是一篇非常简短的关于测试 Cloud Composer 的体验的文章。这绝不是一个详尽的评价——这只是我对 Cloud Composer 的第一印象。
我喜欢云作曲家的地方
设置非常简单**。如果你有一个 Google Cloud 帐户,只需点击几下鼠标(外加大约 20 分钟等待你的环境启动)。您还可以从 Python 包索引(PyPI)中轻松列出所需的 Python 库,设置环境变量,等等。**
部署简单。你的 DAGs 文件夹位于谷歌云存储的一个专用桶中。这意味着您可以直接拖放 DAG 文件夹的内容来部署新的 DAG。几秒钟之内,DAG 就会出现在气流 UI 中。当然,拖放并不是唯一的选择。您还可以通过使用 Google Cloud 的 gcloud 以编程方式进行部署。
当您的环境启动并运行时,Google Cloud UI 是干净的并且没有麻烦:它只是链接到 DAG 文件夹和您的 Airflow 服务器,这是您将花费大部分时间的地方。
Cloud Composer
总的来说,积极方面的主题是简单和易用,这可能是您在托管解决方案中寻找的。
有哪些可以改进的地方
Cloud Composer 运行 Python 2.7 。至少应该有一个运行 Python 3.6 的选项——老实说,我希望它是默认选项。
仍然有一些错误需要解决——毕竟,这是一个测试版。例如,当我试图清除一个任务时,我得到了这个屏幕:
TypeError: can’t pickle thread.lock objects
定价可以更加透明。运行 Cloud Composer 3 天后,我收到了一张€25 英镑的账单,所以假设这是线性的,我大概每月支付€250 英镑。这与谷歌云提供的定价示例非常一致(注意,他们在示例中假设使用率为 25%)。
老实说,如果你的初创公司需要气流,并且你的内部没有很多 DevOps 人员,这是非常有价值的。但是,如果你的业余爱好项目主要着眼于气流,这可能太贵了。
如果你正在寻找另一个气流托管解决方案,在那里你可以获得更多的实践支持和培训,天文学家可能是一个不错的选择。
您的气流设置是什么样的?请在下面的评论栏告诉我。
Akkordeon:神经网络的演员模型
介绍
这个问题我琢磨了很久:有没有可能实现一个神经网络作为演员模型?我终于开发了一个实现,我觉得有必要写一篇关于它的文章。
本文的重点是探索一种思想以及如何实现它,而不是将这种实现与其他框架和实现进行比较。我甚至不确定这是不是个好主意。但是这是可以做到的,正如我希望在下面的内容中所展示的。
源代码在 github 上:https://github.com/botkop/akkordeon/tree/medium
TLDR;
我为神经网络的并行训练开发了两个角色模型。第一种,我称之为“触发器”,为每种消息类型交换状态,其中消息类型是向前传递、向后传递和验证(或测试)之一,并且只能处理符合其状态的消息。第二个,昵称为“轮子”,能够在任何给定的时刻处理所有类型的消息。它训练用于测试触发器场景的相同网络,速度快 2 倍,并且使用 2 倍多的资源。
演员模型
actor 模型是一个用于并发计算的系统。
参与者模型中的参与者是独立的单元,可以有状态。
参与者的状态是私有的:参与者不与其他参与者共享内存。
演员之间的交流是通过消息传递的。消息以异步方式发送,到达接收方参与者的邮箱,在那里按先进先出的顺序进行处理。
尽管参与者邮箱中的消息是一个接一个处理的,但参与者之间的消息是异步发送的。这意味着不同参与者中的计算同时运行。
Actor 系统可以部署在单台机器上,也可以部署在集群中。这允许水平和垂直缩放,允许计算资源的最佳使用。
神经网络
简单地说:
神经网络是一种试图定义未知函数的计算。我们有一个输入 x 和一个已知的输出 y,但我们不知道如何从 x 到 y。让我们尝试一下:我们用 x 和一组随机数(权重)对 x 进行一些计算(激活),然后看看它与想要的输出 y 相比如何。这就是所谓的前向传递。显然,结果不会很好。
接下来,我们引入一种方法来衡量我们的结果有多错误(损失函数),并在预期输出的方向上稍微调整一下权重(导数)。这是反向传递,调整权重被称为优化。
我们反复这样做,直到我们发现结果令人满意。这叫‘训练’。
我们可以尝试通过增加更多的权重和前向函数来改进网络。这些是层层叠叠的,一个接一个。在正向传递中,正向结果从一层传递到下一层,在反向传递中,调整从下一层传递到上一层。
多于一层的网络称为深度网络。
尽管我们可能永远也找不到我们想要的确切函数,但是只要有足够的数据和训练,我们可以计算出几乎总是能产生好结果的东西。希望当我们把它应用到一个从未见过的 x 上时,它能给我们一个未知 y 的好预测。
总而言之:
神经网络由层组成,在训练过程中,通过输入变量的激活向前遍历,通过损失函数计算的导数向后遍历。随后通过优化函数,例如随机梯度下降,用导数更新层的参数。
神经网络和演员模型
神经网络有许多活动的部分,我们可能会发现一些计算可以同时运行。
让我们从定义一个参与者模型开始,其中每一层都作为一个独立的参与者运行。
让我们也称这个层为一个演员的大门。它更好地反映了演员的独立性,我喜欢这个术语,因为它是安德烈·卡帕西在他关于 CS231n 反向传播的精彩讲座中创造的。
在正向传递中,激活作为消息从一个门发送到下一个门。在反向传递中,导数作为消息被发送到前一个门。到目前为止,没什么新发现。然而,每个门独立于网络的其余部分运行的事实,允许一些新奇的东西。
首先,优化(用下一个门的后向梯度或损失函数更新一个门的参数)可以异步完成,即。同时,前一个门正在处理该门新到达的梯度。
第二,不需要为了执行验证或测试过程而停止训练过程。所有可以同时运行。
第三,如果可用的话,不需要等待由网络的其余部分以及最终损失函数计算的梯度来开始处理下一批输入数据的前向传递。
想到的另一件事是,门可以任意复杂,每个门本身组成一个完整的神经网络。因为门是参与者,所以它们可以垂直和水平缩放。在一台机器中,gates 将在所有可用的 CPU/GPU 上执行。Gates 可以很容易地部署在不同的机器上进行水平扩展。单个机器和/或集群上所有资源的最佳使用可以避免昂贵 GPU 的成本。
履行
我们如何实现这一点?
我会用 Scorch ,一个用 Scala 写的神经网络框架。它有一个非常像 PyTorch 的编程接口。因为它是用 Scala 编写的,所以它允许与演员建模工具箱 Akka 集成。
让我们看看它是如何一起工作的,然后我会解释细节。
体系结构
这仅仅显示了训练阶段,但是其他阶段,比如验证和测试,都是类似的,而且更简单,因为没有反向传播。
有 3 个组件。
- Gates: actors,每个 actors 由一个模块和一个优化器组成。这些类似于传统网的层。
- 哨兵:也是一个行动者,负责向关口提供数据(输入)和计算/评估输出的损失。
- 主程序,定义演员系统、网络、数据加载器,并开始训练。
sentinel 只有一个,它从训练数据集中读取一批数据,并将其作为消息转发给网络中的第一个网关。这个门执行其转发功能,并将结果发送到下一个门。依此类推,直到最后一个门,它将结果转发回哨兵。
哨兵接收转发信息,这是现在网络的最终结果,并与预期的结果进行比较。它会计算损失,并将带有导数的反向消息发送到最后一个门。该门计算其函数的局部梯度,并将其作为反向消息发送给之前的门。然后,它更新其权重(优化)。如此下去,直到反向信息再次到达哨兵。
然后哨兵读取下一批数据。诸如此类。
两种情况
我开发了两个场景,我称之为人字拖和轮子场景。
在触发器场景中,所有参与者(哨兵和门)的状态在向前和向后处理状态之间交换。当转发消息到达某个参与者时,该参与者对其进行处理,并转换到向后状态。反之亦然,当一个反向消息到达参与者时,它会转换到正向状态。这种情况的缺点是,它在同一时间只能处于一种状态,因此只能处理当前状态允许的消息。
wheels 场景通过只有一个状态来解决这个问题,它处理所有类型的消息。这允许高度并发的模型,其中正向传播、反向传播和验证都同时运行。该场景依赖于参与者模型定义,即参与者邮箱中的消息按顺序处理。当演员需要跟踪前向通道激活时,为了计算后向通道中的梯度,简单的队列数据结构足以满足这一需求。
盖茨
门类似于层。不同之处在于,每个门都是一个参与者,它有自己的优化器,而在传统网络中,整个网络只有一个优化器。然而,在功能上没有区别,因为优化器不在层/门之间共享数据。
因此,门由一个模块和它自己的优化器组成。
“模块”是 Scorch(和 PyTorch)术语,指带有数据或参数(也称为重量)和转发功能的容器。forward 函数接受一个输入,使用权重执行计算,并产生一个可微分的输出。
模块还可以包含其他模块,允许将它们嵌套在一个树形结构中。
例如:
这个模块,由另一个模块(线性,一个完全连接的层)组成。它将通过全连接层传递其输入,然后是 relu 函数。请注意,模块可以根据您的需要变得非常复杂。你可以把卷积,池化,批处理,辍学,…等等放在那里。
盖茨和触发器场景
在触发器场景中,门有两种状态:正向状态和反向状态。
在转发状态下,门接受来自前一个门或哨兵的转发消息,通过转发功能运行消息内容,并将结果传递给下一个门或哨兵。
然后它切换到向后状态。
在反向状态下,它接受来自下一个门或哨兵的反向消息。
该消息包含上述激活的梯度。该门计算局部梯度,并依次将这些梯度作为反向消息传递给前一层。
一旦这个反向消息被发送,优化器使用诸如梯度下降或 Adam 之类的函数用梯度更新门的权重。
然后,它交换回转发状态,并等待下一条转发消息到达。
上面代码中的 wire 对象包含指向下一个和上一个参与者的指针,或者是另一个门,或者是哨兵。
盖茨和轮子的场景
在 Wheels 实现中,gate 只有一个状态,处理所有的消息类型。
因为这个场景的目标是能够同时执行向前和向后过程,所以我们需要跟踪向前过程中的激活,以便我们可以在向后过程中使用它们进行梯度计算。我使用一个列表来做这件事,这个列表充当一个队列。在正向传递中,输入变量和结果一起被添加到列表中。
在向后传递中,弹出列表的第一个元素,并用于梯度计算。反向消息的梯度和激活列表的第一个元素被保证属于一起,因为在 actors 中,消息被顺序处理,并且我们的网络由一条线(每个节点正好 1 个父节点,正好 1 个子节点)组成,而不是树或图。
哨兵
哨兵做了几件事:
- 为培训和验证提供数据
- 计算并报告培训和验证期间的损失和准确性
- 触发培训和验证的向前传递
- 训练时触发向后传球
哨兵和触发器场景
sentinel 有 3 种状态:起点、终点和验证。
在 Startpoint 状态下,它接受开始和反向消息。
开始消息指示新的训练时期的开始。
反向消息意味着最新的正向消息已经循环了一整圈,并且系统准备好接受新的一批训练数据。否则将忽略反向消息。
在这两种情况下,哨兵然后转发下一批训练到第一个门。
然后状态改变到终点。
在端点状态下,它接受转发消息。这些包含最新训练批次的网络结果,因此执行损失函数,并且梯度与反向消息一起反向传播到网络的最后一个门。
sentinel 试图从数据加载器中检索下一批训练数据。如果这是可能的,状态将变为 start point,为其提供批处理。
如果到达训练数据集的结尾,并且不可能检索下一批,则它进行一些时期结束管理,并且状态变为验证。
在验证状态下,它成批地将验证数据发送到第一个关口,第一个关口对其执行转发,并将其转发到下一个关口,直到验证消息返回 sentinel。哨兵累计损失和准确性,并报告平均值。
然后,它向自己发送一个开始消息,并将状态转换为转发。
哨兵和轮子的场景
在 wheels 场景中,除了一些变量之外,我们没有状态来跟踪验证分数以及训练和验证损失。
当收到开始消息时,它请求数据提供者向第一个门一个接一个地发送多个训练批次。这些消息将由正向传递一个接一个地处理,而不需要等待每个消息的反向传递。反向消息将按照正向消息的顺序到达。有可能在下一个前向消息之前处理一个后向消息,但这不是问题,因为网关使用队列来跟踪消息。
开始消息还触发通过网络发送第一批验证。因此,第一个时期的验证结果将是几乎未经训练的网络的验证结果。
但是重要的是要理解,这允许训练和验证同时运行,并且所有类型的消息(转发、反向和验证)都由网络同时处理。
关于 MNIST 的结果
训练样本数量:60000
测试样本数量:10000
运行一个简单的网络,该网络有 3 个完全连接的层,大小分别为 784x50、50x20 和 20x10。,每个之后是 relu 非线性和随机梯度下降优化。
硬件:2.3 GHz 英特尔酷睿 i7(四核,带超线程技术)。没有 GPU。
触发器
在 10 个时期后给出+96%的准确度。平均 CPU 使用率约为 150%。平均历元持续时间(包括验证):18 秒。
车轮
培训的并发级别设置为 4,验证的并发级别设置为 1。平均 CPU 使用率约为 300%。精度堪比触发器。平均历元持续时间(包括验证):8 秒。
结论
在本文中,我演示了如何在 actor 模型中实现神经网络,以及如何同时运行神经网络训练的不同阶段。
我讨论了两种场景,一种是状态切换,在给定时刻只允许处理一种消息类型,另一种是允许同时处理所有消息类型。后者的速度是同等精度的两倍多。
资源
源代码
演员模型
神经网络
算法复杂性[101]
思考可伸缩性的介绍
计算机速度很快:它们使用电子信号存储和处理数据,这些电子信号以每小时几十万英里的速度穿过它们的硅内部。相比之下,人类神经系统中最快的信号传播速度约为 250 英里/小时,慢了 3 个数量级,而且这些速度只可能用于无意识信号——为有意识思维和计算观察到的信号速度通常更慢。基本上,我们永远不可能在计算上胜过计算机。
Good luck, Alan.
尽管速度很快,但事实上计算机确实有其极限,而且这些极限很容易量化。如今,处理速度是以 GHz 来衡量的:一个 3GHz 的单核处理器每秒可以执行 30 亿条基本指令。一条基本指令可以被认为是一种算术或逻辑运算,例如将两个数相加,对两个布尔值进行“与”运算,或者在内存中给一个变量赋值。Python、C、Java 或(此处插入您最喜欢的编程语言)等人类可读代码在执行之前被转换为机器可读代码,一行简单的人类可读代码可以转化为十几个或更多的机器基本操作。几十亿条指令看起来很多,但实际上,当你编写和运行一个程序时,除非你是一个拥有自己的专业超级计算机的奇特科学家,否则你的系统在运行你的代码的同时,在后台平衡和运行数百个其他程序。处理能力有限,所以计算机必须给每个程序公平地分配处理器时间。
Processor hogs are almost as bad as ice cream hogs.
就像任何其他有限的资源一样,尽可能地提高效率和避免浪费计算是非常重要的。这对数据科学家来说很重要,因为他们经常处理需要快速运行的复杂算法,以及需要处理、转换或重组的大型数据集;如果我们在方法上不够谨慎和聪明,这些任务会花费大量的时间。
进入算法复杂性的概念——一个相当简单的概念有两个相当大的词:
算法复杂度 对于给定的任务,完成该任务的算法(即步骤列表)被称为更复杂,如果它需要更多的步骤来完成**。**
关于复杂性的推理
根据我的经验,通常最简单的方法是解释如何推理算法的复杂性,并通过使用一个例子来证明它在可伸缩性方面的有用性。所以我们来设定一个简单的任务吧!
**任务:**给定一个数,得到重复位数的集合。例如 301143523->【1,3】
一个简单的方法是检查我们看到的任何数字是否与该数字的字符串表示中的任何其他数字匹配,如果它不在那里,就将其添加到返回的集合中。
def simple(x): #convert x to string so we can iterate over digits
s = str(x)
repeated = [] for i in range(len(s)):
for j in range(len(s)):
if (i is not j) and (s[i] is s[j])\
and (int(s[i]) not in repeated):
repeated.append(int(s[i])) return repeated
我们需要计算出算法运行的步骤数。什么是台阶?是单行代码吗?我们能计算出运行这个算法需要多少行代码吗?下面是算法在一些样本数据上的执行情况:
Nope.
被执行的 Python 代码的行数很难计算出来,幸运的是,不能用来衡量一个算法的步骤数。这个标准取决于我们如何编写 Python 代码——如果我们让代码更 Python 化(可读性更差),我们可以把上面的代码压缩成一两行。代码仍然会被翻译成相同的机器代码,也就是计算机实际运行的代码。
That’s not how this works, Kevin.
因此,如果我们能以某种方式看到我们的代码被翻译成一行行的机器代码,我们能计算并使用这些代码来衡量一个算法需要的步骤数吗?
这将非常乏味,所以谢天谢地答案是否定的。不同的计算机架构运行不同类型的机器代码,每一种都可能将我们的 Python 代码翻译成不同的二进制表示,并且不一定能用相同数量的“机器代码行”来表示。
那么,从代码的角度来看,算法的步骤是由什么组成的呢?典型地,我们使用代码块的概念,一段代码表示关于输入数据的恒定时间操作。
一个代码块可以被标识为一行或多行代码从第一行到最后一行线性运行而没有真循环**。**
真正的循环是可变长度的循环。如果我们可以通过查看循环来判断它将迭代多少次,即for i in range(3): do_something()
,那么我们可以等效地写do_something()
3 次来形成一个固定长度的代码块,因此它不是一个真正的循环。
for i in range(len(s)):
for j in range(len(s)): **if (i is not j) and (s[i] is s[j])\
and (s[i] not in repeated):
repeated.append(int(s[i]))**return repeated
前面定义的simple
函数中嵌套的 for 循环内部的体就是一个代码块的例子。
对于代码中的算法步骤,这是一个很好的定义,因为它是不变的,即使我们增加或减少不影响算法所做的语义的代码的语法行,它们也只是重新构造它们相应的代码块。
你可能很高兴听到我们可以更进一步,完全忘记代码。事实上,这绝对是做复杂性分析的最好方法。复杂性与代码几乎没有关系;它是算法的属性,而不是算法的实现。在编程中,我们经常强调将算法翻译成代码的重要性,但反过来的过程同样重要,如果不是更重要的话:优秀的程序员应该能够查看代码,通过将其分解成代码块,将其翻译回预期的算法,然后可视化该算法。
def simple(n):#convert n to string so we can iterate over digits
s = str(n)
repeated = []for i in range(len(s)):
for j in range(len(s)):
if (i is not j) and (s[i] is s[j])\
and (int(s[i]) not in repeated):
repeated.append(int(s[i]))return repeated
simple
的代码用英语翻译成预定的算法:
给定整数 n
为 n:
中的每一位设置一个集合
,为 n:
_ _ _ _ 中的每一位设置一个集合,比较两者,如果匹配,则添加到集合中归还器械包
该算法转化为一些样本数据的可视化:
我们可以从这种可视化中推理出算法的复杂性。让我们来计算一下:对于n
中的每一个数字,我们取该数字并与其他数字进行比较,如果比较的数字匹配,就将其添加到一个集合中。这对应几个步骤?对于n
中的每个数字,我们执行len(n) — 1
步骤,所以我们总共执行len(n) x (len(n) — 1)
恒定时间步骤,相当于len(n)
— len(n)
步骤。
那么算法的复杂度是多少?说是len(n)
— len(n)
会不会正确?算是吧。这准确地表示了算法完成给定任务所需的步骤数。然而,在实践中,我们实际上并不关心步骤的数量:一个算法比另一个算法少 100 步完成同样的任务听起来好得多,但实际上这种差异可能会转化为纳秒级的计算时间。我们更关心步骤的数量如何与输入数据的大小成比例。
大 O
大 O 符号是一种用来简洁地描述算法伸缩性的符号。在除了最理论化的计算机科学家之外的所有人看来,算法的大 O 值和它的复杂性是一回事。如果你在求职面试中被问到算法的复杂性,他们会说计算算法的大 O 值。
我们如何做到这一点?在我们已经做的基础上还有一个额外的步骤。首先,我们对算法的复杂性进行推理,就像我们刚刚对simple
算法所做的那样,然后我们得到我们最终得到的表达式,并且丢弃所有非主导项和常系数。例如:len(n)
— len(n)
正好变成len(n)
,因为这是主导项,我们现在可以表示由simple
编码的算法具有复杂度**O**(N²)
,其中N
是输入的位数(即N = len(n)
)。通常这被解释为“simple
就是**O**(N²)
”。
这是什么意思?这意味着,随着输入的位数增加,我们的算法完成任务所需的时间将呈二次方增加。这告诉我们我们的算法将如何扩展!
Computation time scales quadratically with the number of digits in our input.
让我们将这种可扩展性与解决相同任务的另一种编码算法进行比较:
def better(n):
#convert n to string so we can iterate over digits
s = str(n)
#create 10 counting buckets
buckets = [0 for x in range(10)]
repeated = []
#count number of each digit using buckets
for i in range(len(s)):
buckets[int(s[i])] += 1
#get which digits occurred more than once
for i in range(len(buckets)):
if(buckets[i]) > 1:
repeated.append(i)
return repeated
语义翻译:
给定整数 n
创建 10 个起始值为 0 的计数桶
为每个数字创建一个集合
:
_ _ 递增该数字的桶
中的计数返回集合
视觉翻译:
现在来计算算法的复杂度,给定一个输入n
。首先,我们列出 10 个计数桶,每个数字一个。这是在固定时间内完成的,因此计为 1 步。接下来,我们迭代数字的位数,并增加相应的计数。这需要len(n)
个步骤,每个步骤对应n
中的一个数字。最后,我们对计数桶进行迭代,看看是否有计数大于 1 的桶。这也需要恒定的时间,因为有固定数量的桶,所以也只计为 1 步。
加起来,better
的复杂度可以表示为len(n) + 2
。去掉非主导项并去掉常系数:我们得到better
是**O**(N)
,其中N = len(n)
。
比较
那么**O**(N) better
与**O**(N²) simple
相比如何呢?
Comparison of actual complexity of simple (red) and better (blue)
不出所料,better
比simple
扩展性强多了!有趣的是,由于在better
中创建计数桶列表并在之后遍历它所带来的开销,对于非常小的输入数据,simple
实际上比better
执行得更好。回想一下,当输入较小时,计算差异最多是相对较少的指令,导致较小输入的时间差异可以忽略不计,而better
实现了可伸缩性方面的巨大改进。
当我们要讨论可伸缩性时,为什么要去掉非主导术语和主要常量?
在我们最初的复杂性计算中,前导常数可以被吸收到一个步骤中…就像我们看到非真循环的想法一样。如果我们重复一个步骤有限次,我们可以简单地重新定义我们的步骤来考虑这个因素。这相当于用代数方法进行替换,去掉了常数。
我们去掉了非主导项,因为我们只关心可伸缩性,这意味着我们只关心随着输入数据变得越来越大,我们的算法的性能如何变化。让我们最后一次以simple
为例,考虑它的实际复杂度与其大 O 值的比率:
(N² — N) / N² = 1 - 1/N
注意,随着N
的增加,项 1 - 1/N
越来越接近 1。事实上,我们可以通过选择足够大的N
,使这一项尽可能接近 1。如果两个数之比是 1 意味着什么?他们是平等的。所以随着我们的输入数据N
的增长,(N² — N)
和N²
变得越来越接近。这意味着对于足够大的数据来说,大的 O 值是我们算法复杂性的一个很好的度量,这告诉我们我们算法的伸缩性如何,并允许我们轻松地将其与解决相同任务的其他算法进行比较。我们知道,如果一种算法比另一种算法具有更小的大 O 值,那么对于足够大的数据,它会更快。我们还知道,如果两个算法具有相同的大 O 值,那么它们的伸缩性将相似。优秀的程序员平衡代码的可伸缩性和可读性,并且知道什么时候优先考虑这两者。
速度不是一切
我们从讨论计算机处理指令的速度比人快多少开始了这个话题。这只是在某种意义上是正确的:他们在处理线性指令时更快。人类的大脑已经进化到非常擅长平行化。他们可以同时看到、听到、闻到、触摸和品尝某种东西,同时有意识地思考其他东西,并下意识地控制所有正常的身体功能,如呼吸、消化和温度调节。单个处理器必须在这些任务之间快速切换,无法同时处理所有的信号。如今的计算机确实拥有多核处理器——多个相连的处理器有助于并行执行程序,但与普通人相比,它们的能力仍然非常有限。
人类也有很多记忆。我们可以保存一生的信息,并且(我们大多数人)可以有效地回忆起这些信息来帮助解决问题。关于算法复杂性的讨论的另一个方面是时间复杂性(速度)和空间复杂性(内存)之间的区别,以及什么时候一个应该优先于另一个——我们将留待另一天讨论。
这是一个总结——感谢阅读!
如果您喜欢关于复杂性和可伸缩性的讨论,请随时联系我( )了解您的想法或疑问!
二元分类中 k 近邻算法的不完全性
我们都知道经典的机器学习分类算法,K-最近邻作为最成功的非参数机器学习算法之一。Fix 和 Hodges 于 1951 年在一份未发表的美国空军航空医学学校报告中首次提出了这一规则[1],该规则被称为 k-最近邻规则,并在随后的几年中经历了进一步的修改。近来,众所周知,在与计算机视觉相关的图像分类问题上工作良好。
但是,在数据高度平衡的情况下,我们是否意识到或小心它的不可预测性呢?事实上,我们中的许多人都太习惯于像 Python 中的 Scikit-Learn、R 编程、MATLAB 机器学习工具箱或 WEKA 这样的机器学习工具箱,以至于机器学习算法在它们的实现层面上往往不被重视。根据一些洗钱从业者的说法:
对引擎盖下发生的事情有什么必要了解?…谁会要求你给出学习算法的算法描述或者概述?使用工具箱(即 Scikit-Learn)实现(函数调用它们)……最终结果是唯一重要的……深入学习 ML 算法是浪费时间 ”
此外,在许多书籍中,如
使用 Scikit Learn 进行机器实践学习& TensorFlow [2]
不要给出任何算法概述,直接跳到机器学习算法的 Scikit-Learn 实现。我并不认为这本书不合适,只要这本书的作者希望读者在学习 Scikit-Learn 的正确用法之前,至少精通机器学习算法的概述或直观方法。
总之,我深入研究了 kNN 算法,在实现层面上,我发现了算法中一个有趣的异常。
kNN 实际上是使用特征空间欧几里德几何构建的,使其成为一种无参数的学习算法。在进入伪代码之前,可视化特征空间中的所有数据点是很重要的。
二进制分类中 kNN 算法的伪代码如下所示:
有几个函数将用在伪代码中,仅用于解释工作原理,而不是用任何语言编程或编码,
- nearest_neighbors(x):返回一个二维样本数组,其中第一维表示数组中不同的欧氏距离(降序),第二维表示与 x 具有相同欧氏距离的样本。
- find(nb,data):它通过将 nearest_neighbors,nb 返回的样本映射到原始数据集 data 来返回索引。
- count(p,num):返回 num(任意数字,此处为标签)在数组 p 中出现的频率
- size(m):返回向量的长度,m
- y:数据集的原始目标标签。
伪代码如下
1\. kNN(x)
2\. {
3\. k = 0
4\. c = k
5\. nearest = nearest_neighbors(x)
6\. indices = find(nearest[0],data)
7\. label = y[indices]
8\. if(size(label)==1)
9\. {
10\. prediction = label[0]
11\. }
12\. else
13\. {
14\. while c == k:
15\. {
16\. n_0 = count(prediction,0)
17\. n_1 = count(prediction,1)
18\. if (n_1 > n_0)
19\. {
20\. prediction = 1
21\. break
22\. }
23\. else if(n_0 > n_1)
24\. {
25\. prediction = 0
26\. break
27\. }
28\. else
29\. {
30\. k = k + 1
31\. indices = find(nearest[k],data)
32\. if(size(y[indices])==1)
33\. {
34\. prediction = y[indices][0]
35\. break
36\. }
37\. else
38\. {
39\. c = c + 1
40\. }
41\. }
42\. }
43\. }
44\. result = [prediction;c]
45\. return result
46.}
这里,使用函数 kNN()构造 k-最近邻算法伪代码,该函数采用单个测试样本或实例 x 作为自变量,并返回包含预测结果作为第一元素和 k 值作为第二元素的 2-D 向量。
现在,到此为止,没有任何问题,算法的公式似乎很好,很具体。但是,里面的算法有很大的异常。
现在,通过深入研究,让我们看看使用 k-最近邻进行二元分类时最坏情况的可能性。
异常解释:
最坏的情况出现在偶数(> 1)的时候,比如说 n 个最近的邻居,n 个邻居中的一半属于标签 0,另一半属于标签 1。然后,必须找到第(n+1)个最近的邻居(根据算法),如果再次出现相同的情况,则找到第(n+2)个最近的邻居,依此类推。如果这种情况继续出现(可能出现在高度平衡的数据集中),在特定时刻,数据集中将不再有剩余的样本,并且在每个第 n 个最近邻考虑中,找到两个标签的相同数量的实例。因此,即使在达到数据集的最大 k 值后,也不能对测试样本的预测做出决定。
证明异常的样本数据:
样本数据集在包含 12 个实例的特征空间中示出,并且每个实例具有 2 个特征,F1 和 F2。
Faulty Case of kNN in Binary Classification
未来读者范围:
读者需要深刻理解,为什么上面的样本数据集的可视化是 kNN 的一个错误案例。还建议他们准备这样一个数据集,并选择适当的测试样本。之后,使用 Scikit-Learn 或 R programming 之类的工具箱来查看分类器做出的预测或决策。如果看到任何新的变化,或者如果有任何关于 kNN 错误案例的复杂情况,请在下面的评论部分提到。
避免这种错误情况的可能解决方案:
在特征空间可视化中显示的这样一个数据集处理起来确实非常复杂,选择这样一个测试样本(同心圆的中心)也是如此。当然,可以得出结论,数据集中存在离群值(不重要的实例或性能下降的实例)。因此,这个问题的一个可能的解决方案是欠采样。数据挖掘领域最常见和最成功的欠采样算法之一是基于聚类质心的多数欠采样技术(CCMUT)【3】。因此,通过**欠采样,**数据集的均匀平衡可以被打破,因此 kNN 可以被应用于如此选择的测试样本的分类。
参考文献:
[1]http://www.scholarpedia.org/article/K-nearest_neighbor
[2]盖伦,奥雷连诺。用 Scikit-Learn 和 TensorFlow 实践机器学习:构建智能系统的概念、工具和技术。《奥莱利媒体公司》,2017。
算法是新药
从前,药剂师和治疗师在后街和集市上出售他们的药物洗液和药剂,向所有购买他们产品的人承诺坚韧和活力。蛇油和奇迹疗法放在一起,其中大多数除了作为安慰剂之外没有任何作用。最终,循证实践诞生了,现代医学到来了。只有那些被证明有效的治疗方法会被保留下来,而成熟药物的处方集会缓慢但肯定地增长。现在,医生开处方,药剂师检查和配药,病人基本上好转了。今天,我们有一个监管严格、竞争激烈、利润高得离谱的全球制药业。去年,十大制药公司的总收入超过 4000 亿美元。现在,我们正处于一个全新的十亿美元产业的尖端;“医学算法”,准备将医学提升到更高的高度…
算法是新药,医生是新技术的处方者。
为了理解人工智能(AI)和算法行业(也称为“大技术”、“大算法”、“数字健康”)的未来,人们只需要看看制药公司最初是如何变得如此之大的,包括新药是如何开发并进入市场的,医疗实践是如何围绕药物的安全交付和监控进行的,以及医生是如何学会理解药物的作用机制和副作用的。
因此,根据从大型制药公司的现有实践中吸取的经验教训,我预测围绕算法会出现几个辅助行业。
广告和营销
在英国,英国制药工业协会(ABPI),在美国,美国药物研究和制造商协会( PHRMA )有行为准则,所有制药公司在推广产品和与医疗专业人员互动时都必须遵守。如果你愿意,可以称之为道德框架,以罚款为后盾。这些准则详细规定了公司在向临床医生和患者推销药物时应该如何表现。其中包括公司可以在招待客户上花费多少钱的规定、免费钢笔、继续医学教育优惠以及“交流试验结果”的最佳实践。其目的是防止错误信息、夸大和统计上的疏忽——这是它在很大程度上成功做到的。
然而,批评者仍然存在。Ben Goldacre 博士是一个道德沦丧的世界的坚定反对者,他称之为坏制药,他写道,尽管有道德规范,制药公司仍然逃脱了“……设计不良的试验,在不可救药的少数古怪的、不具代表性的患者身上进行,并使用设计有缺陷的技术进行分析,以这种方式夸大了好处……”。听起来熟悉吗?其他有效的批评包括制药公司没有压力公布负面试验结果。
显然,算法开发者也是如此。我还没有遇到一篇关于深度学习的论文公开说“我们的算法不起作用”,一些有“积极”结果的论文有一些相当可疑的统计烟雾和镜子在进行。当然,总的来说,围绕人工智能仍然有炒作和煽风点火的气氛。我认为,这在一定程度上是因为风险投资支持的公司害怕失去未来的投资兴趣,不愿承认某些东西不起作用。每一篇关于人工智能的学术论文(顺便说一句,这些论文很少经过同行评审)都会很快被一篇夸大其词的媒体新闻稿报道,称“X 算法胜过 Y 医生!”,这当然也于事无补。!"。
这不仅仅是媒体的责任。今年,人们只要逛逛 RSNA 的货摊,就能了解一些公司的说法有多夸张。我们需要记住,强大的临床研究和随后的算法营销的前景和框架仍处于起步阶段,随着监管机构和开发人员找到自己的方式,正是这种前景将出现大规模加速增长。在那之前,我们将不得不费力地通过炒作来找到实际的真相。
所有制药公司都有一个专门的团队来处理临床事务的外部沟通——被称为医疗事务。这包括一个在医疗事务、医学写作和科学联络方面受过培训的专家医生团队,他们的工作是签署任何外部学术出版物、品牌和营销,处理与意见领袖和客户的科学交流,并确保所有交流在临床上是准确的。毕竟,任何被发现虚假广告的制药公司都会被处以重罚。因此,我预测人工智能开发者也需要雇佣一个“医疗事务”团队来处理同等的沟通任务。让未经临床培训的员工担任人工智能公司的临床沟通员是不可接受的,尤其是在直接与医疗保健打交道时。
我还预测,我们将会看到一个算法营销的监督机构,以及一个道德行为规范的引入,独立于 FDA 及其对等机构的验证和监管框架。该机构可能会大量借鉴制药行业关于营销、销售和广告的行为准则,以确保医院不会被卖给数字蛇油,而不是圣杯技术。它很可能会照搬“招待客户”的规则,并为业务开发经理能说什么和不能说什么设定指导方针,甚至可能会为如何撰写关于算法有效性的新闻稿设定指导方针。如果有人已经在某个地方建立了这样一个机构,我不会感到惊讶——这应该会非常有利可图…
但是,如果没有临床研究和调查性试验的坚实基础,这一切都不可能实现。我之前已经讨论过统计分析报告和监管框架——但还没有讨论算法实施的后遗症——这将我带到大型制药公司生命周期的下一部分——一旦算法被发布到临床工作流程的内部,就对它们进行持续监控。
算法安全和技术警戒
世界上每家医院都有一名药剂师,他的工作是监督药品安全。无论他们关注的是处方错误、出院沟通、无菌制剂还是配药错误,他们的任务都是确保在临床实践中将药物的危害和副作用降至最低。这是整体患者安全的一个非常重要的部分,通常在日常临床护理的聚光灯之外进行。(医院中的物理医疗设备也是如此——我保证会有人负责确保套件的电气合规性、质量保证和维护。)
算法安全将需要同样程度的监督。算法不仅有可能造成意想不到的伤害(没有算法是完美的),而且它们需要按照监管要求进行严格的上市后监控。医疗器械国际标准(包括 ISO13485)明确规定,开发商应建立一个强大的系统来监控真实世界的设备性能。这包括对算法输出的定期审计,以及一个反馈机制来确保错误得到处理。
技术警戒是一个新术语——受大型制药公司“药物警戒”的启发。与英国的黄牌系统和美国的药物评估和研究中心系统一样,技术警戒旨在确保公司和最终用户向中央管理机构报告所有新的或意想不到的危害。例如,如果检测患者房颤发作的算法未能触发,患者受到伤害,则必须向开发商和相关监管安全机构报告该事件。
我想说的是,我预测一个围绕安全和技术警戒概念的行业将会出现,但事实上它已经出现了!监管第三方公司已经提供技术警戒咨询,并帮助建立医疗器械的监管合规流程。这个行业将扩展到为算法安全监控提供服务。该行业不仅将确保持续的安全监控,还将与至关重要的IV 期临床研究相结合,在该研究中,算法性能将在现场环境中进行临床评估,以评估安全性能。
医学教育和联合健康专家
医学教育也必须适应新的数字化未来。正如今天的医学学生必须了解作用、半衰期、生物有效性和化学级联的药理学机制一样,未来的学生将需要了解统计偏差、人工神经网络功能、数据结构和算法输出的解释。除了学习药物类别及其副作用,医生还需要了解不同类别的算法、它们的适应症和局限性,以及如何在上下文中解释它们的输出。就像药物安全一样,医生需要意识到算法安全。例如,一种药物具有已知的功效、预期目标人群、推荐剂量和监测要求。医生在开处方前会知道大多数关于药物的事实(如果他们不知道,他们就不应该开处方!).算法是相似的,因为它们有一个已知的准确性,一个预期的目标人群,一个推荐的用法,并需要监测。医生应该像了解药物的副作用一样了解算法的局限性,这难道不合理吗?
出于这些原因,我预计医学院的培训将不得不适应并开始包括基本的数据科学教学,并更加注重对统计的理解。我们需要超越基本的卡方和 T 检验研究,现在学生们也简单地介绍了这些研究。我们必须确保下一代医生能够处理更复杂的统计方法,包括(但不限于)ROC 曲线、AUC、概率建模、推断和比值比。只有到那时,我们才有足够的临床人才来引领医学的数字化发展。
因此,我预测一个基于向医生提供数据科学教育的新行业将会兴起。这已经开始发生,在线课程和 MOOCs 向任何自认为是数据科学家的人开放。我认为,我们将开始看到专门针对临床医生的课程,重点是医学背景下的算法和概率环境下的输出解释。
当然,在临床实践中,不仅仅是医生会成为算法的最终用户。医学走廊充满了非医师的专业,几乎医学的每个方面都有一个。我们有做超声波检查的声谱仪师,做外科手术的手术室护士,做行政管理的病房办事员,做运输的搬运工,做药品的药剂师。因此,我预测一个全新的联合健康专业将会出现,完全专注于 algorithmia。让我们称他们为“算法专家”。
作为临床算法功能的专家,算法专家将检查医院是否在正确的情况下使用正确的算法,帮助采购流程选择好的算法,就哪些技术用于哪些用例提供建议,监督医院内的算法安全,并管理“技术警戒”报告。我想成为一名算法专家所需的技能将非常特殊——既要有基本的临床基础,又要有数据科学背景。
你可能想知道为什么需要一个单独的专业。好问题!在我看来,即使我们有效地教育了医生,他们也没有时间或知识成为真正的全职算法专家。事实上,让医生远离一线医学是对临床培训的浪费。是的,一些临床学者很好地具备了必要的技能,并可能领导由算法学家组成的部门,但在医院的日常临床潮起潮落中,对这种专业知识将有巨大的需求,而且许多工作将需要经过专门培训和专门的专职医疗人员。拥有一个专家团队也比花钱让医生从病人身上抽身更划算。
那么,我们学到了什么?
药物不能提供安全有效的医疗保健,但人和系统可以。AI 和算法也是如此。
通过观察大型制药公司,人工智能开发人员可以开始预测他们所在行业及其周围将发生的趋势。准备好适应这些变化对持续增长至关重要。
从医疗事务和营销指南,到安全和技术警戒,到教育和培训专业劳动力,人工智能开发者可以参与并受益于整个支持行业的生态系统。如果他们参与其中,那么最终,我们的患者将从大算法的承诺中受益最多。
如果你和我一样对人工智能在医学中的未来感到兴奋,并想讨论这些想法,请联系我们。我在推特@drhughharvey
如果你喜欢这篇文章,如果你点击推荐并分享它,那会很有帮助。
关于作者:
哈维博士是一名委员会认证的放射科医生和临床学者,在英国国民医疗服务体系和欧洲领先的癌症研究机构 ICR 接受过培训,在那里他两次获得年度科学作家奖。他曾在 Babylon Health 工作,领导监管事务团队,在人工智能支持的分诊服务中获得了世界第一的 CE 标记,现在是顾问放射科医生,皇家放射学家学会信息学委员会成员,以及人工智能初创公司的顾问,包括 Kheiron Medical。
Python 中超参数优化算法
超参数通常对机器学习算法的成功有重大影响。一个配置不良的 ML 模型可能不会比一个配置良好的 ML 模型表现得更好,而一个配置良好的 ML 模型可以达到最先进的结果。
寻找最佳超参数的过程可能非常乏味,与其说是科学,不如说是艺术。这个微调模型参数的过程被称为超参数优化。在模型调整的过程中,我们经常会发现自己处于以下状态:
- 厌倦了一次又一次地手动重新训练模型(没有任何性能增益)。
- 等待彻底的网格搜索返回结果。(总感觉像是永恒)
- 运行固定迭代次数的随机搜索,只希望它返回一些性能增益。
- 你与原力(YODA)融为一体,并完善了微调模型的艺术。(如果你属于这一类,请与我们普通人分享你的神秘知识)
如果你经常发现自己处于状态 1-3,那么这篇文章将帮助你变得更好。
手动调谐并不都是不好的,因为它在选择下一个参数集时考虑了先前运行的结果( )通知搜索 )。这为我们节省了一些迭代,因为我们不会盲目地运行所有的排列。与此相反,网格/随机搜索独立运行每个排列,但不需要人工干预。为了两全其美,我们需要一个基于历史运行识别有希望的样本空间的自动化过程。实现这一点的有效方法之一是贝叶斯优化。这种技术有效地权衡了参数空间的探索和利用,以返回最佳优化评估标准的配置。一个额外的优势是,即使被优化的基础函数 f 是随机的、非凸的或者甚至是非连续的,它们仍然有效。
基于序列模型的优化(SMBO)是贝叶斯优化的简洁形式。SMBO 是一种通用的函数优化技术,号称是最有效的调用技术之一。
SMBO 通过识别可能已经绘制的超参数赋值来工作,并且根据损失函数值在其他点看起来是有希望的。
在这篇博客中,我们将介绍超参数优化的理论,然后使用 hyperopt 进行实际演示。Hyperopt 是 python 中的一个超参数优化库,它使用 TPE(SMBO 的一种风格)进行优化。在深入 SMBO 之前,让我们回顾一下超参数、网格搜索和随机搜索的基础知识。如果您已经熟悉第(1–3)部分,您可以跳过它们。
目录
- 基本定义
- 基于序列模型的优化(SMBO)
- SMBO 的类型:基于高斯的和基于 TPE 的
- 使用 Hyperopt 的实际操作示例
基本定义
- 超参数 是模型内置的配置变量。这些变量需要微调以产生性能更好的模型。这些参数取决于型号,并且因型号而异。例如,随机森林模型将具有以下超参数
Internal features of a random forest model
以上所有特征都是模型的固有特征。对于基于树的集成方法,如随机森林或梯度推进 max_depth、min_sample_leaf 和 n_estimators(集成中的树的数量)是最重要的。
2.网格搜索是超参数优化最基本的算法。这就像在内置特性的所有可能值上运行嵌套循环。以下示例中的 rf_params 包含需要微调的模型特征。
在上述情况下,模型将被重新训练 300 次。
2(n _ estimator)* 3(max _ features)* 10(max _ depth)* 5(cv runs)= 300
这是一个非常狭窄的搜索空间,因为我们只搜索 3 个特征。如果我们进行彻底的搜索,组合的数量很容易超过 10k。
3.随机搜索是网格搜索,随机选择下一个特征集,总运行次数有上限。
随机搜索的代码与 GridSearch 相同,唯一的区别是我们添加了 n_iter=100,它固定了允许运行次数的上限。网格/随机搜索是 无信息搜索 的例子,意味着下一个特征集独立于上一次运行的输出。这两种方法都需要在每次迭代中进行重新训练,这导致了巨大的成本。
基于序列模型的优化(SMBO)
SMBO 通过顺序选择不同的超参数集来最小化验证损失,其中下一个集是通过贝叶斯推理选择的(取决于之前的运行)。直观地说,SMBO 会回顾上次运行的结果,以将未来的搜索集中在看起来更有希望的领域。
只要评估适应度函数( f : X - > R )的成本很高,就使用 SMBO。在这种情况下,计算一个近似的 f ( 代理M)。这款 M 算起来比较便宜。通常,SMBO 中的内部循环是该代理的数值优化或该代理的某种转换(下面代码中的*第 3 行)。最大化替代值的点 x 成为应该评估真实损失函数 f 的建议(行 4 )。**
Figure 1 : The pseudo-code of generic Sequential Model-Based Optimisation
*H:观察历史
T:试验次数
f:真函数
M:逼近 f 的替代函数
S:计算下一个超参数赋值
x :M 最小化的样本实例
伪代码解释:
*第 1 行:*初始化一个空的 H.
第 2 行:初始化固定次数的循环尝试。
第三行:
1。L 为 f 获得一个名为 *M.
2 的代理函数。定义一个需要最小化的评估标准。
3。对 x 的多个实例运行 S(x,M)以找到 x 哪个最小化 S.
行 4 : f 被评估为最佳 x.
行 5 : H 用当前值 x,f(x)更新。
第 6 行:M 在每次迭代后被更新,以成为 f 的更好近似。
采集函数定义了在目标空间中探索新区域和利用已知具有有利价值的区域之间的平衡。不同风格的 SMBO 使用不同的算法来优化预期的改进(EI,采集函数的流行选择)。例如,Hyperopt 通过 TPE (Tree Parzen Estimators)优化 EI,而 Spearmint 使用高斯过程优化 EI。
SMBO optimises the EI ( Expected Improvement )
- Pm:后 GP 知道 H
- y*:新候选人的替代值
- y:上一个候选人的替代值
直观地说,它定义了在给定位置 x 的最佳先前观察客观值上的非负 EI。
基于高斯过程的 EI 优化
高斯过程(GP) 是一个随机过程(由时间或空间索引的随机变量的集合),使得这些随机变量的每个有限集合都有一个多元正态分布,即它们的每个有限线性组合都是正态分布的。
GP 是贝叶斯优化中建模目标函数( f )的标准代理。在这种设置中,假设 f 是具有均值 u 和协方差核K的 GP,核 K 的选择可以对替代重建有重大影响。在这种方法中,模型 *M(图 1 的第 6 行)*定义了预测分布 p(y|x,D)。
树形结构 Parzen 估计器方法(TPE )
TPE 是以树形结构组织的核估计器,以保持条件相关性。与直接对 p(y|x) 建模的基于 GP 的方法相反,TPE 通过 p(x|y) 和 p(y) 对其进行近似。
TPE 对 GP 优化预期改进的方式进行了两项更改。
- p(y|x)替换为 p(x|y) * p(y)/p(x)
- 情况 1 : p(x|y) = l(x) if y 情况 2 : p(x|y) = g(x) if y≥y*
- l(x) 是使用观测值{ x }形成的密度,使得相应的损失 f(x) 小于y∫
- g(x) 包含剩余的观测值
利用这两种分布,可以优化与预期改善成比例的封闭形式项。
这导致了下面的结论
EI after TPE specific optimisations
最后一个表达式表明,为了最大化改进,我们希望点 x 在 l(x) 下具有高概率,而在 g(x) 下具有低概率。这仅仅意味着选择 x 的,其具有小于先前报告值的 EI 的概率更高。
使用 Hyperopt 进行参数优化
Hyperopt 是用于通过 SMBO 执行自动化模型调优的 Python 库。应用 hyperopt 进行超参数优化是一个 3 步流程:
- 定义目标函数。
- 定义搜索空间(xgb_space)。
- 定义一个试验数据库来保存每次迭代的结果。
以下代码块是如何对 xgboost(梯度增强库)执行超参数优化的示例。
为了对其他模型使用相同的脚本,只需对模型进行少量修改。您需要对 xgb_space 变量进行修改,以适应您选择的模型的搜索空间。在目标函数中,您需要更改交叉验证的运行方式(如我们使用的 xgb 特定方法),以及您希望最小化的指标。例如,对于 LightGBM(转到 LightGBM 了解这个令人敬畏的库),您可以通过做一些小的修改来使用代码。
将来我会在 hyperopt 库上发布一个更详细的 hands on blog。
这个博客是对我们目前可用的超参数优化技术的一个简要概述。我们从不知情的搜索开始,如网格/随机搜索,然后转移到不同的贝叶斯方法,如基于 GP 的 SMBO 和基于 TPE 的 SMBO,最后是 hyperopt 的工作示例。
参考
如果你想深入了解,请浏览以下材料
请在评论区分享你的想法和主意。
C++中的算法
完全搜索,贪婪,分治,动态规划
介绍
本文旨在向读者介绍四种主要的算法范式:完全搜索、贪婪算法、分而治之、和动态规划。许多算法问题可以映射到这四个类别中的一个,掌握每一个将使你成为一个更好的程序员。
本文是从竞技编程的角度来写的。在参考资料部分,您可以找到一些资源来帮助您入门,或者通过编码竞赛来提高您的编程技能。
完整搜索
完全搜索(又名蛮力或递归回溯)是一种通过遍历整个搜索空间寻找解决方案来解决问题的方法。在搜索过程中,我们可以删除搜索空间中我们确信不会导致所需解决方案的部分。在编程竞赛中,完全搜索可能会导致超时,然而,这是一个解决小输入问题的好策略。
完整搜索示例:8 皇后问题
我们的目标是在棋盘上放置 8 个皇后,这样就不会有两个皇后互相攻击。在最天真的解决方案中,我们需要列举 64 种选择 8 ~ 4B 的可能性。一个更好的天真的解决方案是认识到我们可以将每个皇后放在一个单独的列中,这导致了 8⁸~17M 可能性。我们可以做得更好,把每个皇后放在一个单独的列和一个单独的行,结果是 8!约 40K 有效行排列。在下面的实现中,我们假设每个皇后占据不同的列,并且我们为 8 个皇后中的每一个计算有效的行号。
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std; //row[8]: row # for each queen
//TC: traceback counter
//(a, b): 1st queen placement at (r=a, c=b)
int row[8], TC, a, b, line_counter; bool place(int r, int c)
{
// check previously placed queens
for (int prev = 0; prev < c; prev++)
{
// check if same row or same diagonal
if (row[prev] == r || (abs(row[prev] — r) == abs(prev — c)))
return false;
}
return true;
}void backtrack(int c)
{
// candidate solution; (a, b) has 1 initial queen
if (c == 8 && row[b] == a)
{
printf(“%2d %d”, ++line_counter, row[0] + 1);
for (int j=1; j < 8; j++) {printf(“ %d”, row[j] + 1);}
printf(“\n”);
} //try all possible rows
for (int r = 0; r < 8; r++)
{
if (place(r, c))
{
row[c] = r; // place a queen at this col and row
backtrack(c + 1); //increment col and recurse
}
}
}int main()
{
scanf(“%d”, &TC);
while (TC--)
{
scanf(“%d %d”, &a, &b); a--; b--; //0-based indexing
memset(row, 0, sizeof(row)); line_counter = 0;
printf(“SOLN COLUMN\n”);
printf(“ # 1 2 3 4 5 6 7 8\n\n”);
backtrack(0); //generate all possible 8! candidate solutions
if (TC) printf(“\n”);
}
return 0;
}
对于 TC=8 和(a,b) = (1,1)的初始皇后位置,上述代码产生以下输出:
SOLN COLUMN
# 1 2 3 4 5 6 7 8 1 1 5 8 6 3 7 2 4
2 1 6 8 3 7 4 2 5
3 1 7 4 6 8 2 5 3
4 1 7 5 8 2 4 6 3
这表明在给定初始皇后位置(r=1,c=1)的情况下,有四种可能的布局。注意,与迭代解决方案相比,递归的使用允许更容易地修剪搜索空间。
贪婪算法
贪婪算法在每一步采取局部最优选择,希望最终达到全局最优解。贪婪算法通常依赖于贪婪启发式算法,人们经常可以找到贪婪算法不能达到全局最优的例子。
贪婪的例子:分数背包
贪婪背包问题包括选择将什么物品放置在有限容量 W 的背包中,以便最大化背包物品的总价值,其中每个物品具有相关联的重量和值。我们可以将贪婪试探法定义为物品价值与物品重量的比率,即我们希望贪婪地选择同时具有高价值和低重量的物品,并基于该标准对物品进行分类。在分数背包问题中,我们被允许取一个物品的分数(相对于 0-1 背包)。
#include <iostream>
#include <algorithm>
using namespace std; struct Item{
int value, weight;
Item(int value, int weight) : value(value), weight(weight) {}
}; bool cmp(struct Item a, struct Item b){
double r1 = (double) a.value / a.weight;
double r2 = (double) b.value / b.weight;
return r1 > r2;
} double fractional_knapsack(int W, struct Item arr[], int n)
{
sort(arr, arr + n, cmp); int cur_weight = 0; double tot_value = 0.0;
for (int i=0; i < n; ++i)
{
if (cur_weight + arr[i].weight <= W)
{
cur_weight += arr[i].weight;
tot_value += arr[i].value;
}
else
{ //add a fraction of the next item
int rem_weight = W — cur_weight;
tot_value += arr[i].value *
((double) rem_weight / arr[i].weight);
break;
}
}
return tot_value;
}
int main()
{
int W = 50; // total knapsack weight
Item arr[] = {{60, 10}, {100, 20}, {120, 30}}; //{value, weight}
int n = sizeof(arr) / sizeof(arr[0]);
cout << “greedy fractional knapsack” << endl;
cout << “maximum value: “ << fractional_knapsack(W, arr, n);
cout << endl;
return 0;
}
由于排序是开销最大的操作,该算法的运行时间为 O(n log n)。给定三个项目的(值,重量)对:{(60,10),(100,20),(120,30)},并且总容量 W=50,上面的代码产生以下输出:
greedy fractional knapsack
maximum value: 240
我们可以看到,输入项目按价值/成本的递减比率排序,在贪婪地选择项目 1 和 2 后,我们取项目 3 的 2/3 分数,总价值为 60+100+(2/3)120 = 240。
各个击破
分而治之(D&C)是一种技术,它将一个问题分成更小的、独立的子问题,然后组合每个子问题的解决方案。
分而治之技术的例子包括排序算法,例如快速排序、合并排序和堆排序以及二分搜索法。
D&C 的例子:二分搜索法
二分搜索法的经典用法是在一个排序的数组中搜索一个值。首先,我们检查数组的中间,看看是否包含我们要找的东西。如果是这样,或者没有其他项目需要考虑,我们就停止。否则,我们决定答案是在中间元素的左边还是右边,并继续搜索。由于每次检查后搜索空间的大小减半,因此算法的复杂度为 O(log n)。
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;int bsearch(const vector<int> &arr, int l, int r, int q)
{
while (l <= r)
{
int mid = l + (r-l)/2;
if (arr[mid] == q) return mid;
if (q < arr[mid]) { r = mid — 1; }
else { l = mid + 1; }
}
return -1; //not found
}int main()
{
int query = 10;
int arr[] = {2, 4, 6, 8, 10, 12};
int N = sizeof(arr)/sizeof(arr[0]);
vector<int> v(arr, arr + N);
//sort input array
sort(v.begin(), v.end()); int idx;
idx = bsearch(v, 0, v.size(), query);
if (idx != -1)
cout << "custom binary_search: found at index " << idx;
else
cout << "custom binary_search: not found"; return 0;
}
上面的代码产生以下输出:
custom binary_search: found at index 4
注意如果没有找到查询元素,但是我们希望找到不小于查询的第一个条目或者大于查询的第一个条目,我们可以使用 STL lower_bound 和 upper_bound。
动态规划
动态编程(DP)是一种技术,它将一个问题分成更小的重叠的子问题,计算每个子问题的解决方案,并将其存储在 DP 表中。从差压表中读取最终解。
掌握动态编程的关键技能是确定问题状态(DP 表的条目)以及状态之间的关系或转换的能力。然后,在定义了基本情况和递归关系之后,可以用自顶向下或自底向上的方式填充 DP 表。
在自顶向下的 DP 中,根据需要递归地填充表格,从顶部开始,向下到更小的子问题。在自底向上的 DP 中,从最小的子问题开始迭代地填充表格,并使用它们的解决方案来构建和达到更大的子问题的解决方案。在这两种情况下,如果已经遇到了子问题,那么只需在表中查找它的解决方案(而不是从头开始重新计算解决方案)。这大大降低了计算成本。
DP 示例:二项式系数
我们用二项式系数的例子来说明自顶向下和自底向上 DP 的使用。下面的代码基于带有重叠子问题的二项式系数的递归。设 C(n,k)表示 n 选择 k,那么,我们有:
Base case: C(n,0) = C(n,n) = 1
Recursion: C(n,k) = C(n-1, k-1) + C(n-1, k)
请注意,我们有多个重叠的子问题。例如,对于 C(n=5,k=2 ),递归树如下:
C(5, 2)
/ \
C(4, 1) C(4, 2)
/ \ / \
C(3, 0) C(3, 1) C(3, 1) C(3, 2)
/ \ / \ / \
C(2, 0) C(2, 1) C(2, 0) C(2, 1) C(2, 1) C(2, 2)
/ \ / \ / \
C(1, 0) C(1, 1) C(1, 0) C(1, 1) C(1, 0) C(1, 1)
我们可以如下实现自顶向下和自底向上的 DP:
#include <iostream>
#include <cstring>
using namespace std; #define V 8
int memo[V][V]; //DP table int min(int a, int b) {return (a < b) ? a : b;} void print_table(int memo[V][V])
{
for (int i = 0; i < V; ++i)
{
for (int j = 0; j < V; ++j)
{
printf(" %2d", memo[i][j]);
}
printf("\n");
}
} int binomial_coeffs1(int n, int k)
{
// top-down DP
if (k == 0 || k == n) return 1;
if (memo[n][k] != -1) return memo[n][k];
return memo[n][k] = binomial_coeffs1(n-1, k-1) +
binomial_coeffs1(n-1, k);
}int binomial_coeffs2(int n, int k)
{
// bottom-up DP
for (int i = 0; i <= n; ++i)
{
for (int j = 0; j <= min(i, k); ++j)
{
if (j == 0 || j == i)
{
memo[i][j] = 1;
}
else
{
memo[i][j] = memo[i-1][j-1] + memo[i-1][j];
}
}
}
return memo[n][k];
}
int main()
{
int n = 5, k = 2;
printf("Top-down DP:\n");
memset(memo, -1, sizeof(memo));
int nCk1 = binomial_coeffs1(n, k);
print_table(memo);
printf("C(n=%d, k=%d): %d\n", n, k, nCk1);
printf("Bottom-up DP:\n");
memset(memo, -1, sizeof(memo));
int nCk2 = binomial_coeffs2(n, k);
print_table(memo);
printf("C(n=%d, k=%d): %d\n", n, k, nCk2);
return 0;
}
对于 C(n=5,k=2),上面的代码产生以下输出:
Top-down DP:
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 2 -1 -1 -1 -1 -1 -1
-1 3 3 -1 -1 -1 -1 -1
-1 4 6 -1 -1 -1 -1 -1
-1 -1 10 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
C(n=5, k=2): 10Bottom-up DP:
1 -1 -1 -1 -1 -1 -1 -1
1 1 -1 -1 -1 -1 -1 -1
1 2 1 -1 -1 -1 -1 -1
1 3 3 -1 -1 -1 -1 -1
1 4 6 -1 -1 -1 -1 -1
1 5 10 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1
C(n=5, k=2): 10
时间复杂度为 O(n * k),空间复杂度为 O(n * k)。在自顶向下 DP 的情况下,子问题的解决方案根据需要存储(存储),而在自底向上 DP 中,整个表是从基本情况开始计算的。注意:出于打印目的,选择了较小的 DP 表格尺寸(V=8 ),建议使用更大的表格尺寸。
密码
所有代码可在:https://github.com/vsmolyakov/cpp获得
要编译 C++代码,您可以运行以下命令:
>> g++ <filename.cpp> --std=c++11 -Wall -o test
>> ./test
结论
有很多学习算法的好资源。我强烈推荐 Steven Halim 关于竞争性编程的书[1]。除了经典的算法设计手册[2]和 CLRS [3]。有许多伟大的编码挑战网站,其中一些在[4]中提到。此外,[5]有一个奇妙的算法集合和易于理解的实现。如果您正在构建自己的库或参加编程竞赛,这是一个很好的资源。
希望这篇文章对你有所帮助。编码快乐!!
参考
- Steven Halim,“竞争性编程”,第 3 版,2013 年
- 史蒂文·斯基埃纳,《算法设计手册》,施普林格,2011 年
- 托马斯·科尔曼等人,《算法导论》,麻省理工学院出版社,2009 年
- https://medium . freecodecamp . org/the-10-most-popular-coding-challenge-websites-of-2016-fb8a 5672d 22 f
- 【https://www.geeksforgeeks.org/
用卷积自动编码器对齐手写数字
Photo by Chris Ried on Unsplash
自动编码器是广泛使用的神经网络的无监督应用,其原始目的是发现数据集的潜在低维状态空间,但它们也能够解决其他问题,如图像去噪、增强或着色。
在这篇文章中,我想分享我对卷积自动编码器的实验,我训练它将 MNIST 数据集中随机旋转的手写数字对齐到它们的原始位置。请注意,这篇文章不是用来介绍自动编码器的,而是一个应用的展示和不同解码架构的比较。在接下来的部分中,我将展示一个案例,该案例强化了具有卷积层的上采样块比去卷积层性能更好的共识,并且还展示了卷积层与全连接层的组合在简单自动编码器和仅具有卷积层的卷积自动编码器上都具有优势。
如果您已经熟悉卷积自动编码器和上采样技术,可以跳过下一节,如果不熟悉,我推荐您阅读它和相关文章。
介绍
自动编码器背后的主要思想是将输入减少到具有更少维度的潜在状态空间中,然后尝试从该表示中重构输入。第一部分称为编码,第二步是解码阶段。通过减少代表数据的变量数量,我们迫使模型学习如何只保留有意义的信息,从这些信息中输入是可重构的。它也可以被视为一种压缩技术。
下面这个帖子是我推荐的一个很棒的介绍:
特色:数据压缩,图像重建和分割(附实例!)
hackernoon.com](https://hackernoon.com/autoencoders-deep-learning-bits-1-11731e200694)
如果您也对实现感兴趣,下一篇文章是基于第一个链接编写的,但它也包括 Tensorflow 中的详细实现:
简介和概念:
towardsdatascience.com](/autoencoders-introduction-and-implementation-3f40483b0a85)
这个实现的一个有趣部分是上采样的使用。由于内核的重叠,反转卷积层可能相当具有挑战性。大多数深度学习框架都包括反卷积层(有人称之为转置卷积层),它只是一个反向卷积层。尽管这些层在重建输入时直观上有意义,但它们也有产生棋盘假象的缺点。为了解决这个问题,它们已经被上采样和简单卷积层所取代。以下两个链接的帖子都是对这个问题的详细解释。
当我们仔细观察神经网络生成的图像时,我们经常会看到一种奇怪的棋盘图案…
蒸馏. pub](https://distill.pub/2016/deconv-checkerboard/) [## 转置卷积上采样
如果你听说过转置卷积,并对它的实际含义感到困惑,这篇文章是为…
towardsdatascience.com](/up-sampling-with-transposed-convolution-9ae4f2df52d0)
该项目
正如我前面提到的,我使用了 MNIST 数据集,并将每张图像旋转了某个随机角度。模型的任务是将它们重新排列成原始状态。在实验过程中,我比较了以下架构;
- 一个简单的自动编码器,有三个隐藏层,我用它作为基准
- 一种卷积自动编码器,仅由编码器中的卷积层和解码器中的转置卷积层组成
- 另一种卷积模型,在编码器部分使用卷积块和最大池,在解码器中使用卷积层的上采样
- 最后一个模型是卷积层和全连接层的组合
所有模型都在具有相同超参数的相同数据集上训练,并且在瓶颈层中具有 256 个变量。
基线模型
首先,让我们看看基线自动编码器,它具有以下结构。
Architecture of the Baseline Model
我在训练中使用了均方误差,最佳模型在训练数据上达到了 0.0158,在验证数据上达到了 0.0208,正如预期的那样,在测试数据上达到了 0.0214。下图是测试数据集中的一个示例,显示了模型如何成功地重新排列数字 4。
From left to right: input image, target image and the image predicted by the model
该模型意识到图像显示的是数字 4,并将其旋转回原来的位置。预测仍然是一个明显的数字 4,然而,边缘有点模糊,顶部两条线之间的差距几乎消失了,这可能是低维瓶颈的结果。总的来说,该模型能够完成任务并产生可接受的结果,但是,它在一些输入方面存在问题。所有模型中最具挑战性的一张图片如下。
中间的真实图像清楚地显示了数字 4,然而,由于长的水平线,旋转后的图像有点像数字 5。该模型努力识别数字,最终得到一个水平质量,它显示的是数字 5 而不是数字 4。
具有转置卷积的卷积自动编码器
第二种模型是卷积自动编码器,它只包括卷积层和解卷积层。在编码器中,输入数据通过 12 个具有 3×3 内核的卷积层,滤波器大小从 4 开始增加到 16。由于卷积层没有填充,并且步长大小为 1,瓶颈的大小为 16x4x4,这意味着瓶颈中的变量数量与基线模型的数量相匹配。解码器利用转置卷积层来反映这种架构。仅使用卷积层可能看起来不寻常,但在这种情况下,目标是比较技术,而不是实现出色的结果。
就度量标准而言,这种架构无法接近基准模型。训练 MSE 损失为 0.0412,验证损失为 0.0409,测试损失为 0.0407。较大的损失可能是由于可训练参数的尺寸较小。使用卷积层将基准测试中的参数数量从大约 100 万减少到只有 23000 个。
在许多情况下,如上面的数字 9 所示,模型能够解决问题并预测与所需输出匹配的可识别数字,但一般来说,它无法生成更好性能所需的如此精细和狭窄的线条,并且生成模糊的图像,其数字难以识别,如下所示。
这种效果可以归因于去卷积层,因为除了边缘之外的每个像素都是作为重叠滤波器的总和而生成的。这个模型在上面考虑的复杂例子中表现得更差,不仅产生了模糊的输出,而且产生了一个类似于数字 3 而不是期望的数字 4 的数字。
带上采样的卷积自动编码器
我考虑的下一个架构是具有卷积层、最大池层和上采样层的卷积自动编码器。
Architecture of the Convolutional Autoencoder with Upsampling
在训练指标方面,它获得了比基准模型稍大的 MSE 值;0.0293 关于训练,0.0293 关于验证,0.0297 关于测试数据集。但与之前的模型类似,更差的分数也带来了好处,该模型的规模不到基准的三分之一,只有 2.9 万个可训练参数,但它的表现仍然可以接受。此外,度量的狭窄分布表明,它在没有额外正则化的情况下概括得很好。
在上面的图片上,我们可以看到它仍然能够识别数字并重新排列它。它仍然稍微模糊了边缘,但没有以前的模型那么多。在这种情况下,它甚至删除了顶部循环中不重要的部分。
这个模型也不能识别之前讨论的硬例子,但是它比之前的模型更简单。它的输出部分类似于数字 5,这表明它在识别数字和重建数字时有问题。
组合模型
在看到上采样提供了更好的结果和更精确的输出后,我制作了另一个架构,它以下面的方式组合了上采样模型中的块和完全连接的层。
Architecture of the Combined model
卷积层和池层成功地取代了基准测试的第一个密集层,并产生了迄今为止最好的模型,只有 40 万个可训练参数,这仍然远远少于基准测试的大约一百万个参数。它在训练数据上实现了 0.0151 MSE 损失,在验证数据上实现了 0.0151 MSE 损失,在测试数据上实现了 0.0151 MSE 损失。它生成的情节也比以前的好。
通过混合这两种类型的图层,模型能够生成更精细的线条和更模糊的图像,但重建仍然不完美,如下图所示。
这个硬例子的问题在这个模型的输出上更加明显。
显然,该模型试图重新排列输入的数字,就好像它是数字 5 一样,这加强了这样一种假设,即该模型在这个例子中遇到了困难,因为这个数字是不可识别的。
评论
即使我使用 MSE 作为性能的度量,关于任务本身的一个有趣的评论是,在某些情况下,高 MSE 并不意味着错误的输出。例如,以下预测是由组合模型做出的。
预测图像是基于输入图像预期的绘制得很好的零,但是目标图像上的数字不是以常规方式书写的,因此预测 MSE 误差很高。自然,我们不能通过神经网络来了解这些信息。此外,我之前预计模型会混淆数字 6 和数字 9,反之亦然,但输出图像显示这种情况只是偶尔发生。例如,下图显示了来自验证数据集的 upsamplig 模型的输出之一,该模型已被很好地识别,并且除了尾部模糊之外,被重构为正常的数字 9。
另一方面,我用来演示数据集中的困难样本的问题似乎是一个更大挑战的一部分,因为许多模型在一些情况下很难将数字 4 旋转回来。特别是,具有转置卷积层的模型很难解决这个问题,并生成了如下图像。
但是,其他模型也没有什么不同。例如,基线模型犯了以下错误。
令人惊讶的是,旋转数字 4 产生的图像与数字 5 甚至数字 2 有更多的相似之处。
结论
正如该项目所示,仔细选择模型不一定会提高其性能,但它有助于构建最简单的合适模型,从而减少过度拟合的可能性,正如我们在训练指标的较小分布中看到的那样。一般来说,使用简单的自动编码器似乎是一个合适的选择,因为它以令人满意的方式解决了这个问题,但在指标中可以观察到过度拟合的痕迹,并且它的大小明显大于其他模型。我们可以尝试通过减少中间层的节点数量或简单地省略它们来简化这个模型,但是,如果我们仍然保持 256 个大瓶颈,可实现的最低参数数量大约是 40 万个。此外,额外的正则化技术可能有助于泛化,但这似乎是不必要的,因为具有上采样层的卷积自动编码器能够在网络小十倍以上的情况下实现几乎同样好的结果。这两种类型的层的组合最终以合理的架构提供了最佳的性能。
在这篇文章中,我只挑选了一些图片来展示这些架构的性能。在链接的 Github 存储库中可以找到更多图片的更详细的评估,其中也包括 Keras 中的实现。
https://github.com/pasztorb/Rotational_CAD
关于朴素贝叶斯的一切
学习朴素贝叶斯分类器就是计算每个属性在每个类中出现的次数
朴素贝叶斯是可以应用于数据的最简单的算法。顾名思义,这种算法做出了一个假设,因为数据集中的所有变量都是“天真的”,即彼此不相关。
朴素贝叶斯是一种非常流行的分类算法,主要用于获得数据集的基本精度。
像我五岁一样解释
让我们假设你正在操场上散步。现在你看到一些红色的物体在你面前。这个红色的物体可以是一只蝙蝠或者一只猫或者一个球。你肯定会假设它会是一个球。但是为什么会这样呢?
让我们假设你正在制造一台机器,你已经给了上面的任务,把一个物体分类在球棒、球和猫之间。首先,你会想到创建一个机器,它将识别对象的特征,然后将它与你的分类对象进行映射,这样,如果一个对象是圆形,那么它将是一个球,或者如果该对象是生物,那么它将是一只猫,或者在我们的情况下,如果我们的对象是红色的,那么它最有可能是一个球。
为什么会这样?因为我们从小就见过红色的球,但红色的猫或红色的蝙蝠对我们来说是不太可能的。
所以在我们的例子中,我们可以通过用我们的分类器分别映射一个对象的特征来对其进行分类。在我们的例子中,这个红色是用一只蝙蝠、一只猫和一个球映射的,但是最终,我们得到了一个有球的红色物体的最大概率,因此我们把那个有球的物体分类。
公式
这里 c 代表类别,例如球、猫、球棒。
x 代表单独计算的特征。
在哪里,
例子
假设我们有 1000 个水果的数据。水果是香蕉、橘子或其他水果,假设我们知道每种水果的 3 个特征,不管是长还是短、甜还是甜、黄还是黄,如下表所示。
从表中我们已经知道了什么?
- 50%的水果是香蕉
- 30%是橘子
- 20%是其他水果
基于我们的训练集,我们还可以说:
- 500 根香蕉中,400 根(0.8)长,350 根(0.7)甜,450 根(0.9)黄
- 300 个橙子中,0 个是长的,150 个(0.5)是甜的,300 个(1)是黄的
- 在剩余的 200 个水果中,100 个(0.5)长,150 个(0.75)甜,50 个(0.25)黄
这将提供足够的证据来预测另一种水果的种类。
假设我们得到了一块水果的特征,我们需要预测它的类别。如果我们被告知额外的水果是长的、甜的和黄色的,我们可以使用下面的公式对它进行分类,并代入每个结果的值,不管它是香蕉、桔子还是其他水果。概率(得分)最高的一方为获胜者。
formula for reference
香蕉:
橙色:
其他水果:
在这种情况下,基于较高的分数(香蕉 0.252),我们可以假设这个长而甜的黄色水果实际上是香蕉。
用 python 实现
- 用 python 从头开始实现朴素贝叶斯算法并在每一步都有解释,上传到我的 Github 库。
- 在 Scikit learn 的帮助下,朴素贝叶斯的实现也被添加到我的 Github 存储库中。****
这是一个非常深入的解释朴素贝叶斯 w.r.t 在 python 中的实现,可用于机器学习…
github.com](https://github.com/2796gaurav/Naive-bayes-explained)**
优势
- 预测测试数据集的类别是容易且快速的。在多类预测中也表现出色。
- 当独立性假设成立时,朴素贝叶斯分类器与其他模型(如逻辑回归)相比表现更好,并且您需要更少的训练数据。
- 与数字变量相比,它在分类输入变量情况下表现良好。对于数值变量,假设正态分布(钟形曲线,这是一个强假设)。
不足之处
- 如果分类变量具有在训练数据集中未观察到的类别(在测试数据集中),则模型将分配 0(零)概率,并且将无法进行预测。这就是通常所说的零频率。为了解决这个问题,我们可以使用平滑技术。最简单的平滑技术之一叫做拉普拉斯估计。
- 另一方面,朴素贝叶斯也被认为是一个糟糕的估计,所以概率输出不要太认真。
- 朴素贝叶斯的另一个限制是独立预测者的假设。在现实生活中,我们几乎不可能得到一组完全独立的预测值。
应用程序
- ****实时预测:朴素贝叶斯是一个学习能力很强的分类器,而且速度非常快。因此,它可以用于实时预测。
- ****多类预测:该算法也以多类预测特性而闻名。这里我们可以预测多类目标变量的概率。
- ****文本分类/垃圾邮件过滤/情感分析:朴素贝叶斯分类器最常用于文本分类(由于在多类问题中的更好结果和独立性规则)与其他算法相比具有更高的成功率。因此,它被广泛用于垃圾邮件过滤(识别垃圾邮件)和情感分析(在社交媒体分析中,识别积极和消极的客户情感)
- ****推荐系统:朴素贝叶斯分类器和协同过滤一起构建了一个推荐系统,该系统使用机器学习和数据挖掘技术来过滤看不见的信息,并预测用户是否喜欢给定的资源。
何时使用
- 文本分类
- 当数据集很大时
- 当你的训练量很小的时候
此外,我将添加其他机器学习算法。这篇文章的主旨是深入了解朴素贝叶斯,不使用任何硬词,从头开始解释。此外,如果您想实现朴素贝叶斯,从这些数据集开始,您可以在注释部分用代码注释您的预测得分。
在那之前,
快乐编码:)
别忘了拍手拍手拍手…
关于音乐的一切— 01
音乐和机器学习
你好。你一天花多少时间听音乐?几个小时,一周呢?据《福布斯》 的一篇文章称,美国人平均每周花 32 个小时听音乐,而且这个数字每年都在增长。嗯,我们都有自己的疯狂和不同的音乐品味。让我们玩一些数据,并试图找出是什么使一些歌曲比其他歌曲获得更多的赞赏。
受到这里的一些文章和数据科学社区在音乐方面所做工作的启发,我决定也做一个实验。因此,今天我们将利用可视化的力量对 Spotify 本周的全球 200 强进行统计分析。
数据集
该数据集由 Spotify 每周全球 200 首歌曲及其各自的 24 个歌曲属性组成,即声音、活力、舞蹈性等。我将描述用于分析目的的最重要的属性。
节拍 —每分钟的节拍数。
能量 —强度和活动的感性度量。它是从 0.0 到 1.0 测量的。数值越高,就越有活力。
数值越高,越容易随着这首歌起舞。
响度 —值越高,歌曲的音量越大(以 dB 为单位)。
效价 —从 0.0 到 1.0 的一个度量,描述一首曲目所传达的音乐积极性。高价曲目听起来更积极。
音质 —数值越高,歌曲越有音质。
如果你想知道更多关于这些歌曲属性的技术描述,你可以访问 Spotify 的这个链接。
数据提取
我使用 Spotify 图表来获取数据集,该数据集由 200 个链接到板上相应歌曲的 URL 组成。接下来我做了一些文本挖掘来提取每首歌的 id。我写了一个脚本,使用 Spotify 的 API 从 ID 中提取歌曲属性,并使用任务所需的适当的身份验证令牌。您可以一次提取多个轨迹的属性,但最多只能提取 100 个,所以我运行了两次相同的脚本来获取所需的数据集。替代方法可以是使用 Echonest API,但从中提取的信息和属性将少于 Spotify API 方法。
不浪费时间,让我们深入研究数据集
Histogram Distribution plot of song attributes
见解:-
1)根据上面的直方图分布图,本周人们更喜欢高能量的歌曲,即更适合于具有高价系数的舞蹈的歌曲。
2)音乐爱好者似乎是一个多样化的群体,他们中的一些人更喜欢每分钟节拍数更多的喧闹音乐,而一些人则更喜欢相反的组合。
3)从分布图中可以明显看出,大多数听众喜欢音乐中的声音较低。
Correlation Matrix
从上图所示的相关矩阵中,我们可以观察到,一首歌没有两个属性有很强的相关性。如果一首歌有活力,声音就会更大。这个事实似乎是真实的,因为可以看出它们具有显著的关系(蓝色的0.68)但不太真实,因为响度不是一首歌曲是否有活力的唯一标准**。**
一般来说,特征的数量越多,模型就越健壮。有了太多的特征,可视化和处理特征工程就成了一项乏味的任务。12 个特征将导致 144(12*12)个成对的图,以理解一对一的相似性。NAHH!我们不会那样做,我们会做降维。
主成分分析
主成分分析是一种从数据集中大量可用变量中提取重要变量(以成分形式)的方法。它从高维数据集中提取低维特征集,目的是获取尽可能多的信息。随着变量的减少,观想也变得更有意义。
它总是在对称相关或协方差矩阵上执行。这意味着矩阵应该是数字的,并且有标准化的数据。
The scattered plot of two after PCA
PCA 后 99%的方差被恢复,不错…一点都不差!
因此, 64%方差由主成分 1 解释, 35% 由主成分 2 解释。这表明,我们已经从数据集的两个主要部分中提取了大部分见解。因此,在降维之后,我们没有遭受任何重大的信息损失。
如果两个分量不相关,它们的方向应该是正交的。该图像基于具有 2 个预测值的模拟数据。请注意组件的方向,正如所料,它们是正交的。这表明这些成分的相关性 b/w 接近于零。
Outlier Detection using Support Vector Machines
例如,如果我们有兴趣知道是否有任何一首发行的歌曲可以根据上周的歌曲进入全球 200 强名单。我们会比较它是否能把它们放在橙色区域内。这个橙色区域代表本周最受欢迎的歌曲。
让我们做一些可视化
Song Attributes scattered into 3D space
灰色和蓝色看起来不错,但是我想看看更多的颜色
多色…嗯!我知道…我知道,你现在已经看够了那些圆形的斑点,让我们一起来建造一些坚实而科学的东西吧。
标准环面方程
标准圆环被参数化为一个旋转面:一个圆围绕一个轴旋转。这种环面的一般方程是
f(u, v) = [ (a + b*cos(v))*cos(u), (a + b*cos(v))*sin(u),
c*sin(v) ]
这里,输入 u 和 v 可以是来自上述歌曲属性集的任何数字特征。环面主要应用于拓扑学领域,但与环面作用相关的具体问题出现在数学和数学物理的不同领域。
Scientific 3-D plot using the attributes danceability and tempo
C 颂歌和技术描述:-
如果您一直关注这个博客,并且有兴趣了解代码和详细分析的内容。上述分析是在 Python 中完成的,使用 sci-toolkit 库:Sckit- Learn、pandas、seaborn 和 plotly 进行可视化。代码、数据和 Jupyter 笔记本可在 Github 上获得。
这是我将尝试不同声音和演讲的一系列博客文章的第一篇。将它们分成片段,将声音的和弦聚在一起,产生新的回声等等。感谢阅读,敬请关注!
所有的鸟都是黑色的
考虑偏差-方差权衡的一个简单方法
Photo by Hannes Wolf on Unsplash
我遇到过多种方法和哲学来构建模型来代表现实世界的关系。我的统计学教授无情地强调奥卡姆剃刀和吝啬。社会科学家痴迷于在模型中寻找因果关系,通常是通过实验。
Don’t go there, Simba!
在机器学习中,我们很早就被引入了偏差-方差权衡,以及过度拟合的危险。
根据维基百科,基本的想法是:
…偏差-方差权衡是一组预测模型的属性,其中参数估计偏差较低的模型在样本间具有较高的参数估计方差,反之亦然。
迷路了吗?外面有很多很好的解释,但是让我们试着不用图表、数学或者希腊语来解决这个问题。
让我们从最简单的模型开始。一个心智模型。
所有的鸟都是黑色的:最简单的模型
假设你以前从未见过鸟。曾经。(你想象中的老板)要求你:
- 描述鸟类,一般来说,是什么样子的;
- 解释是什么造就了鸟,鸟;或者
- 预测下一只鸟在任何给定的时间和地点会是什么样子。
你可能会观察一只或几只鸟的样子,并对这种鸟做出一些概括。
接下来,假设你遇到一群乌鸦,你得出如下结论:
- 所有的鸟都有两条腿
- 所有的鸟都有喙
- 所有的鸟都有羽毛
- 所有的鸟都是黑色的
恭喜你!你已经建立了你的第一个鸟体模型。
当然,一个人不必是鸟类专家就能知道“所有的鸟都是黑色的”是一个不正确的结论,但是请记住——你从来没有见过鸟!你的模型是过度拟合,你从乌鸦身上挑出了太多的细节,并试图将其推广到整个鸟类种群。你想描述鸟,结果却描述了乌鸦。
在被老板训了一顿之后,你又回到了 bird-verse,建立了另一个模型。建议是“保持简单,笨蛋”。然后你观察一些其他的鸟,得出结论:
- 所有的鸟都有羽毛
Dame Edna has feathers. Is she a bird?
这也不太对。我们已经避免了根据某些鸟类的特殊特征进行归纳的问题。然而,我们已经走得太远了,因为我们对鸟类的普遍特征做了一个单一的声明。
不管怎么说都不是不合理的,但仍然是错误的。
这就是我们说一个模特不合身的时候。你只取了一个特征,但它并没有对鸟类的现状或未来给出一致的预测或解释。在这种情况下,你想描述鸟类,但你最终抓住了每一只有羽毛的鸟。
让我们试着把这带回统计学和机器学习的说法。在第一个模型中,我们减少了解释当地鸟类样本的偏差,但是当推广到另一个样本时,会有更多的方差。
在第二个模型中,我们得到了一个低方差预测器,它在推广到更多鸟类样本时表现良好,但在面对一个有羽毛但显然不是鸟类的样本时面临更多偏差!
我们每天都在建造模型
我们被过度拟合和欠拟合模型所吸引,迭代通过事物如何运作的各种模型,直到我们对事物如何运作有了满意的理解。一旦你开始简单地考虑模型,你会开始注意到到处都有偏差-方差权衡。
Greg learnt about bias-variance trade-off the hard way
建立关系、建立模型和找到我们在环境中观察到的事物的根源是人类的本性。这与我们为机器学习建立模型的方式真的没什么不同。难怪机器最终会像我们一样。
感谢阅读!如果这对您有用,或者您想提出一些改进建议,请留下评论或反馈。
所有 ICML 甘斯/生成论文
我去了斯德哥尔摩和 ICML(7 月 10 日至 15 日),理解了 academese,所以你不必这样做!域自适应,3D GANs,使用 GANs 的数据输入等等。
Adversarial Domain adaptation based on CycleGAN — such as CyCADA — are an interesting way to use synthetic or augmented data to help training with e.g. autonomous cars.
然而,严肃地说,我非常尊重 ICML 研究人员展示的所有令人惊叹的工作。我不可能接近他们的工作水平,所以他们推动了这个领域的发展,这是值得称赞的!
总的来说,ICML 是一次令人敬畏的经历。但这篇文章不是关于我的想法、印象或经历。该行业正在慢慢渗透到学术会议中——不管你认为这是不是一件好事——我想我可以更进一步,展示一下在这次会议上出现的从业者观点中最有趣的结果。
这意味着,如果我看不出这些学术贡献如何适用于那些最终目标并不是首先要发表论文的人,我会对一些学术贡献打折扣。这也意味着我将会使用更容易理解的语言,而不会进入任何给定的论文。我会试着用一种更容易理解的方式来表达,这也意味着我会不时地贡献一些你们可能不同意的观点和想法。我的希望是,这将是有用的,特别是对该领域的新来者,给他们一些我在准备这次会议时读过的大约 50 篇论文的背景。
很多时候,解释会变得又快又脏,因为事实上并不是每一篇论文都是严格意义上的生成性对抗网络。所以开始了。
作为我在 Mudano 培训预算的一部分,我选择去 ICML,一个机器学习领域排名前三的会议。这是一次非常丰富和独特的经历。但为了从会议中获得最大收益,我决定跟踪我遇到的大多数论文。然后这些按照它们在会议中出现的时间顺序呈现。我不包括周六和周日,这两天主要是关于研讨会。[1]
11 日星期三
放射杆
GANs 的承诺一直部分在于半监督学习和数据增强。这项工作基本上允许我们利用来自几个来源的多个数据集来获得更好的性能,即使一些数据集质量不高或与手头的任务无关。这是通过首先将数据集转换到某个共享的潜在空间,然后将该空间转换回手头任务的目标域来完成的。
我的想法:我真的很喜欢这篇论文。在工业上可能非常有用。也很清晰的呈现出来。我的一个同事对这种潜力感到非常兴奋。如果适用于你的问题,这篇论文真的可以改变游戏规则。
发现深度生成和判别模型的可解释表示
这基本上是一种人在回路中的主动学习方式,确保我们能够最(人)有意义地解释潜在空间。潜在地降低了准确性,但是允许我们说潜在空间的哪个维度正在影响什么属性。
我的想法:潜在的有趣,因为经常计算潜在空间如何转化为生成的样本是很重要的。陈述不是很清楚。
GANS 的哪些训练方法确实趋同?
在这篇论文中,Lars 等人提出了一种方法——从一个玩具例子开始——在整个训练过程中对 GANs 施加特定等级的梯度惩罚。他们显示的结果与最先进的(SOTA) [2]相匹配,甚至与旧的架构相匹配。作者进一步证明了 GAN 的纳什均衡附近的局部稳定性的一些有趣的性质。代码也可以在上面的链接中找到。
我的想法:相当令人印象深刻的壮举。这种技术相当复杂,但是花时间去理解可能是值得的。其他人也有类似的想法。但在这种情况下,结果是不言自明的。PGGAN-质量结果,无需渐进增长!
These images were generated by pretty standard GAN without progressive growing, just using the techniques from Lars et al.
卡方生成对抗网络
到目前为止,这项工作连接了三个不相连的 GANs 方法—见下图。
我的想法:我对这项工作的看法是,这可能是一个重要的理论,但对从业者的用途可能有限。充分解释什么是力矩匹配偏差超出了这篇文章的范围。我们可以将 IPM 简化为简单地提取产生的和真实的分布与推土机距离的差异,f-GANs 基于f-divergence。
对于从业者来说似乎有点太复杂了。
基于分类的 GAN 分布协变量偏移研究
这是一个很酷的检测模式崩溃的研究。这通常是有意义的,尤其是对于试图发现培训问题的学者。这意味着我们现在终于可以开始讨论这些缺失模式和间隙的影响了。
我的想法:我认为有一个一致的/独特的基准来评估培训质量是有价值的。但是有一些我更喜欢的度量标准,但是这可能是一个整体。
NETGAN:通过随机漫步生成图形
想法:通常有趣的工作表明,GANs 可以用于生成更复杂的图形。根据链路预测精度达到了现有技术水平。
12 日星期四
几何分数:一种比较生成性对抗网络的方法
这项工作表明,使用拓扑分析,我们可以构建一个通用度量来评估我们已经设法覆盖了多少原始数据集。使用一个近似值,我们可以计算出在我们生成的数据集中有多少差异。
想法:我真的对这项工作感到兴奋,因为它允许我们评估任何领域的 GANs,并检查它的模式崩溃。到目前为止,通用的评估方法完全缺失。也许有一天我们甚至会看到质量的衡量标准。
优化生成网络的潜在空间
本文偏离了典型的 GAN 设置,而是着手创建一个能够生成更好样本的模型。这里,我们集中讨论模式崩溃和生成不相同但足够相似的样本的问题。
想法:我对这篇论文有一种复杂的感觉。一方面,我认为这次演讲出人意料地固执己见——对学术界来说是不寻常的——我不同意很多陈述。另一方面,非正式的海报讨论真的很好,也提供了很多信息。在这次讨论中,一位研究人员提出了一个有趣的观点,即模式崩溃是 GANs 工作的原因。这是一个有趣的论断,我很想知道这是否是真的。关于这篇论文有趣的事情是,当我研究它的时候,我发现它差点被 ICLR 拒绝,所以作者重新发表到 ICML。
采用局部坐标编码的对抗学习
本文试图解决与上一篇论文相似的问题,但使潜在空间更加复杂。演示不是很清楚,但要点是探索流形假设,即存在从一些低维潜在空间到复杂流形(如图像)的映射。所有的 GANs 最终都依赖于这个假设,但是如果你考虑一下这个映射,你能从这么低的空间表现所有的图像似乎有点奇怪。出于某种原因,本文无法与现有技术方法相比。
3D 点云的学习表示和生成模型
谁不爱 3D 点云?太棒了。在本文中,作者创建了一个更强大的模型来生成通用对象的三维点云。虽然还有很多工作要做,但它看起来棒极了。
对立学习下的意象翻译理论分析
本文分析了成对翻译 GANs,并指出成对图像到图像翻译的损失本质上有两个组成部分。确保图像正确的身份损失,以及确保图像清晰的对抗性损失。
想法:有趣的理论工作,但可能还不适合从业者。报纸上也没有照片,所以这里至少有一张模糊的(抱歉!)来自海报环节。
生成对抗模型的复合功能梯度学习
想法:这篇文章介绍了一个更复杂的训练机制,看起来在理论上是有支持的,但是接下来创建了一个近似的版本,在训练过程中添加了一个 if 语句,这对我来说有点特别的味道。结果超越了艺术的状态,但是我通常喜欢增加较少复杂性的方法。
缓和的敌对网络
这篇论文背后的高层次思想很有趣。与 PGGAN 相似,作者认为 GAN 从一开始就面临的问题有点太难了。因此,作者创建了一个网络,将图像变形一点,这样生成器就更容易工作了。一个腐朽的版本,胜过最先进的。
使用代表性特征改进生成性对抗网络的训练
本文主要是将生成的图像的自动编码版本连接起来,作为帮助传递给鉴别器。作者的海报非常清晰地描述了该建筑,但不幸的是,这些图片似乎已经从我的手机中消失了。
他们的结果比最先进的要好,但也差不了多少,所以我不确定这是否真的是一个突破。
精确的 GAN WASSERSTEIN 距离的两步计算
本文引入线性规划来计算 Wasserstein 距离的精确值,然后用它来改进训练。Wasserstein 距离的问题是,当你考虑到即使是简单的点云的组合有多复杂时,计算精确的距离似乎也很复杂。本文实现了这一点,并超越了现有技术水平
本文用作基准的数据集既简单又有限(MNIST,CIFAR-10),所以我很想看看这种方法在 Celeb-A HQ 或 IMAGENET-1000 上的表现如何。
发电机调节与 GAN 性能有因果关系吗?
和其他一些论文一样,我几年前就读过这篇论文了,但是作者做了很好的工作,简明扼要地总结了结果,尤其是对海报而言。基本上,它们使用雅可比箝位来抑制生成器更新,从而实现更稳定的训练。性能没有实质性的提升,但是稳定性的提升是值得的。
作为一个从业者,如果你有 GAN 稳定性的问题,这是可以尝试的论文。
GAIN:使用生成式对抗网络的缺失数据插补
这篇论文可能是从业者最感兴趣的论文之一,因为它处理了一个我们很多人都会遇到的问题——缺失数据。它创建了一个带有提示机制的 GAN 设置,基本上可以智能地推断出缺失值以匹配分布。我们知道 GANs 擅长创建合成分布。提示机制是必要的,因为鉴别器的问题太难了——有许多部分缺失/真实数据的组合有效排列使得这变得难以处理。
我已经向我的一些同事推荐了这篇论文。说够了。
具有有限查询和信息的黑盒对抗性攻击
这是为数不多的现实对抗性攻击论文之一。技术上不涉及 GAN /生成模型——我猜除了干扰——但非常有趣,做对抗性攻击的现实方式。
我仍然不认为深度学习模型足够广泛,也不认为对它们有足够的信任会造成任何真正的伤害,但这篇论文讨论了真正的问题。
一阶生成敌对网络
本文背后的思想是,在梯度惩罚(如 WGAN-GP)的情况下,不是针对 WGAN 损失进行优化,然后添加惩罚,而是直接针对损失进行优化。作者表示,当针对损失进行优化,然后添加惩罚时,会出现病态情况,使得生成的分布本身不太接近目标分布。海报周围有一些非正式的拷问(不是我)/证据,但我不会让作者这样做,哈哈。
利用强化对抗学习合成图像程序
在这里,我不是链接这篇论文本身,而是链接 DeepMind 的一篇出色的博客文章,这篇文章很好地解释了这篇论文。TL;甘博士使用类似 Photoshop 的 API 生成笔触,很好地学习了任意绘制。
MAGAN:对齐生物歧管
好的,所以我现在很确定 MAGAN 代表多种排列 GAN(虽然在演示中没有提到),但当我第一次看到一个美国人介绍它时,我认为它有一些政治内涵,哈哈。这种 GAN 基本上通过增加对应损失来确保我们总是以相同的对应来对齐两个流形(而不是像其他算法那样随机对齐)。
有趣的花絮,在演讲后的一个“问题”中,有人声称已经有一家报纸在做这件事了。作者不知道这篇论文。你的想法?
对抗性事件时间建模
在与 GAIN 论文类似的领域,除了现在专注于时间序列,并基本上获得了某些事件的时间分布的更好的概率分布(基本上能够自动推断),例如医院环境中的并发症。
可能对处理时间序列的人非常有用。
苏铁:周期一致的对抗性领域适应
这篇论文讨论了一个问题,这个问题是很多从业者反复发现的:我们的模型不能一般化(原谅这个笑话)。通常,您可能会采用一个模型,例如在 ImageNet 上训练的模型,部署它,然后发现它表现很差。因为现实世界比 ImageNet 复杂得多,即使我们只关心 ImageNet 类。CyCADA 扩展了 CycleGAN,基本上能够使用正确的语义进行域到域的翻译,从而有可能在安全、可扩展的计算机生成环境中构建例如自动驾驶汽车,然后将 ML 系统翻译到现实世界中。
真有意思!一定会尝试。
用于生成建模的自回归分位数网络
所以从技术上讲,这篇论文没有什么内容。“只是”自回归模型,但它们取得的结果可与 GANs 的最新技术水平相媲美。非常令人印象深刻的工作,但与每个自回归模型一样,这种设置将难以扩展。演讲结束后,作者提议使用自动编码器来扩大规模,但这带来了一系列其他挑战。
有趣的方法,但类似的(尽管质量较低)作品已经出现,从未超过 32x32 像素的限制,这里也是如此。在这个问题解决之前(许多人已经尝试过了),不确定这是否真的是可扩展的;另外请注意,甘已经在 1024x1024。
用于 GAN 训练的混合批次和对称鉴别器
与常规 GAN 不同,本文使用混合批次的真实和合成数据来使鉴别器更好。正如作者在总结中所说的“一个简单的架构技巧使得有可能可证明地将批处理的所有函数恢复为一个无序集”。
我真的很喜欢这篇论文,因为它是一个优雅的想法,而且摘要实际上总结了这篇论文。这是否会成为主流框架还有待观察,但是我认为作者引用其他架构的方式有点奇怪(他们都来自一篇论文)。
JOINTGAN:利用生成对抗网的多领域联合分布学习
在这里,作者有一个类似于 CycleGAN 的架构,但不是单独推断条件分布,而是联合学习每个域的边际概率分布。我们从产生 X 的噪声开始,然后在从边缘产生 Y 时以 X 为条件。
我发现演示有点不清楚,但结果似乎真的很有趣。文本生成似乎真的令人印象深刻,但作者说这实际上是由自动编码器从 GAN 生成的潜在空间中完成的。
AUGMENTED CYCLEGAN:从未配对数据中学习多对多映射
通过在第一代和第二代中注入潜在空间,这是对标准形式的 CycleGAN 的一个非常好的扩展。回想一下,周期一致性损失是用 diff(X1,X2)来度量的,其中 X1 -> Y -> X2。基本上,作者给了我们额外的变量来创建具有特定质量的样本。例如,如果我们在 Y 域中有一只鞋的轮廓,我们可以在 X 域中生成一个样本,其中同一类型的鞋是蓝色或橙色或我们选择的任何颜色。
如果你喜欢 CycleGAN,但想更多地控制翻译,你会喜欢这个。
论 GAN 动力学中一级近似的局限性
这是一篇纯理论论文,主要只是在简单例子的层面上进行推理。关键是解释为什么多次鉴别器更新可能是有意义的。本文将它发挥到极致,在最佳鉴别器的情况下,显示出良好的收敛性。但除此之外,目前从业者可能不感兴趣。
ICML 的生成性对抗性网络论文到此结束。我希望你觉得这很有用,如果你想让我在 12 月去的地方制作《来自日本》(或者写一篇关于如何充分利用会议的文章),请告诉我。
感谢凯伦·特里普勒和米哈伊·尔玛柳克的想法和评论!
想加入对话吗?详见或推特@ langrjakub!我也正在写一本关于 生成性对抗网络的书,你可以在这里查看 。
[1]我去了可重复的机器学习,这应该是大多数机器学习从业者所熟悉的。但是如果有兴趣的话,我也可以读一下。
[2] SOTA 只是意味着在这个基准上打破以前最好的学术成绩。例如, DAWNBench 是目前在 Imagenet 上达到 93%分类准确率的最先进的存储库。
所有模型都是错误的:第 3 周数据科学沉浸式
机器学习中的模型选择和我第一次 Kaggle 比赛的结果。
著名统计学家乔治·博克斯提出了一个经常被引用的观点:“所有的模型都是错误的。”根据我创建和解释金融模型的经验,我不得不同意。模型是一种有缺陷的尝试,试图用简单的术语描述一种复杂的关系,同时在此过程中做出许多假设。然而,模型也是有用的。他们有能力让我们的生活变得更好。
天气预报是模型力量的一个很好的例子。气象学家从气象气球上收集数据,这些气球被释放到大气的不同层次,并报告观测结果,如空气密度、压力、湿度和温度。这些气球数据被输入到一个预测模型中,这个模型的核心使用了“空气包裹”的简单概念。空气包可以被认为是一个盒子或气泡,其行为符合流体动力学定律。该模型使用这些定律来计算电流梯度的估计值(环境温度、压力等的差异)。)影响气团,然后将梯度的变化率扩展到我们所依赖的 7 天预报中。
Visualization of Air Parcels — http://www.srh.noaa.gov
天气预报模型是否给了我们大气未来(甚至当前)状态的完整知识?不,大气是混乱和动荡的,模型只是近似大块空气的行为,让气象学家充满信心地说,“一个低压系统正在移动,这可能意味着本周末会下雨。”虽然这些天气模型确实有点复杂,但重点是这些模型——现实的简化版本——可以让我们处理生活中的决定——比如是否推迟周六的野餐。
数据科学中一个反复出现的主题是,我们试图选择一个模型(或几个模型)来满足我们的目的。最常用的预测机器学习模型之一是线性回归。为了形成一个线性回归模型,我们手工挑选了一些变量或“特征”,其中每个特征都被假设对最终值“目标”有一个可量化的(标量)直接影响从单一线性关系开始,特性的递增与目标的成比例增加或减少相关联。这种关系可以是积极的——你的房子每增加一平方英尺就会增加它的增值——也可以是消极的——每增加一项信用活动就会降低你的总体信用评分。
Simple Linear Regression with One Feature (Living Area) and One Target Variable (Sale Price)
单一线性关系的概念然后扩展到多变量关系,其中我们结合(添加)每个增量变量的影响来计算最终的目标值。在此过程中,我们将通过权衡每个变量的影响来测试和调整我们的计算,并添加一个常数项来调整基本情况。一个重要的注意事项是,在线性回归中,目标始终是通过扩展从以前实例中学习到的关系来计算新实例的预测值。
数据科学家必须能够识别线性回归是模型的正确选择的情况。如房价和信用评分示例所示,线性回归很容易推广并应用于各种数据集。然而,只有当数据集满足一些基本要求时,它才是合适的。这些要求包括目标预测必须是连续的,每个特征应该独立于其他特征,并且每个特征必须与目标具有近似线性的关系。
本周,我应用我的线性回归知识,开发了一个预测模型,参加了爱荷华州埃姆斯市房屋价格数据集的 Kaggle 竞赛,链接如下:https://www . ka ggle . com/c/house-prices-advanced-Regression-techniques。在这篇文章的剩余部分,我将概述这个挑战,描述我的方法,并分析我的结果。
概述:
Kaggle.com 提供了 2006 年至 2010 年间售出的 1500 套房屋的“训练”数据集。对于训练集中的每一笔房屋销售,我们都会得到销售价格,以及其他 79 条可能影响销售价格的潜在信息。这里是这些特征的一个例子:总的宜居平方英尺,以平方英尺为单位的地段大小,卧室数量,建造年份,砖石饰面类型,地下室装修类型,等等。
对于这个练习,我所有的工作都是在 Jupyter 笔记本上,使用 Python、Pandas 和 Scikit-Learn 库。要了解更多细节,请查看我的公共 GitHub 上的 Jupiter 笔记本“Ames-Submit.ipynb”文件:https://github.com/eversdyk/kaggle-linreg-ames-housing。
第一步:数据探索。
在将数据导入我的 jupyter 笔记本之前,我花了大约一个小时阅读数据集作者的文档,让我对每个功能的可能值以及它们如何影响销售价格有了一个很好的概述。然后我拉了拉。csv 训练文件到我笔记本上的熊猫数据框中,并进行一些探索性分析。在此期间,我发现许多列都有需要处理的空值。我还做了一个功能相关性的快速热图,让我了解影响销售价格的驱动功能。
Continuous Variables Correlation Heat Map
步骤 2:清理测试数据。
首先,我重新排列了 79 个特征,按照变量类型对它们进行分组:连续型、离散型、有序型和分类型。接下来,我检查了每个变量的空值,并适当地填充了它们。对于数值,我用该列的平均值填充了少量缺失的点。对于其他人,我根据其他专栏进行了猜测。例如,在缺少的“车库建造”年份中填入房屋建造的年份。缺失的类别值大多用众数或该类别中出现频率最高的值来填充。对于最后两个清理步骤,我为分类变量创建了‘dummy’布尔列,最后对所有列的值进行规范化,使它们保持在-1 和 1 之间。这种归一化是保持每个要素的最终系数或权重更加平衡的好方法。
第三步:创建一个模型并检查它是否有效。
最初,我尝试了一个简单的线性回归模型,我使用 KFolds 方法对其进行了 10 次训练和拟合。这种 KFold 策略是一种将数据分解成块以进行快速训练和预测的常用方法,它减少了训练数据中异常值的影响。快速检查我的 R 平方值显示,这是…完全胡说八道。R 平方度量是由给定模型解释的响应数据可变性比率的度量。它预计位于 0%到 100%的范围内,其中 0%意味着你的模型不会比平均响应值的随机猜测更好,而 100%意味着你的模型每次都会完美地确定每个家庭的正确销售价格。我的值是一个非常小的数字,接近于零,这意味着我需要做更多的工作来找到一个有用的模型。
第四步:改进模型,或者尝试另一种技术。
幸运的是,本周我们学习了一种叫做“套索”的技术顾名思义,套索法通过关注变量的一个更小的子集来简化线性回归。简而言之,Lasso 会将冗余要素的权重强制为零,从而消除一些会影响线性回归近似的共线性问题。这一次,R 平方得分显示销售价格预测接近 90%,这意味着我们的模型非常好,解释了测试数据中 90%的可变性。使用 Scikit-Learn 的一个名为 GridSearch 的特性,我还对 Lasso 最重要的参数——惩罚值 alpha——做了一些调整。这让我的分数提高到了 91%左右。在这一点上,我有足够的信心根据我还没有接触过的测试数据做出一些预测。
第五步:查看模型是否对测试数据有效,并将结果提交给 Kaggle。
到目前为止,我只处理过训练数据。训练数据包含特征(售出的每套房屋的 79 个变量)和响应(其销售价格)。现在是使用测试数据验证我的模型的时候了。测试数据集包含埃姆斯市销售的 1000 多个新房屋实例的信息(相同的 79 个特征),这次没有列出销售价格。我获取了这些新数据,并完全按照之前清理训练数据的方式对其进行了转换:组织特征,填充它们的空值,创建虚拟变量,并对所有值进行规范化。由于该模型之前已经与定型数据相匹配,因此它可以为测试数据集中的每个观察值预测销售价格。模型做出了它的预测,我给了他们一个快速的视力测试,以确保他们在正确的范围内。然后,我将预测的销售价格上传到 Kaggle 进行评分。
我的预测结果是用均方根误差法评分的,这是一种衡量我的预测与实际有多接近的方法。值越低越好,我的分数低到足以让我在排名中接近中间。对我的第一场比赛来说还不错!
我仍然不熟悉数据科学和机器学习模型,但第一次比赛是一次宝贵的经历,让我磨练了我的技能。我对我的过程很满意,尽管我会第一个指出我在清理和组织数据时可以做出的改进,比如编写函数来处理批量清理操作,或者以不同的方式填充空值。代替使用套索方法,我可以使用脊或弹性网方法来惩罚系数。我还希望有其他更复杂的连续值预测模型,我还没有学会。
所有的模型在技术上可能都是错的,但是它们可以让我们非常接近解决方案。作为一名数据科学家,我的工作是为每种情况找到合适的模型。
所有的统计学,科学和认识论在 8 分钟内。
所有的统计学、科学、认识论、“数据分析”、“机器学习”(或者更确切地说,“学习”)等等。归结到一点:通过看尽可能少的页数来“判断”尽可能多的书。更一般地说,它们都遵循以下步骤(这实际上是一篇前一篇的扩展):
- 现实就是这样。它很复杂,很大,并且有许多活动部件。如果我们对处理一个特定的问题感兴趣,我们可能永远不会看到全部,也不需要真正理解全部。
- 有数据,我们可以看到和测量的现实的子集。它是从现实中取样的,几乎肯定是通过某种实际上并非随机的机制。
- 我们对现实有一些想法。我们如何得到它们,没有一致的逻辑。有些事情,我们只是相信。有些事情,我们通过查看数据来了解。有些事情,我们相信通过按照某种逻辑把点连接起来。
造就“科学”的是将信念和数据联系起来的态度:至少,原则上,我们不会把信念看得太重,以至于我们不会忽视数据。然而,即便如此,数据和信念的相对权重还是不同的。阿里尔·鲁宾斯坦对 Dani Rodrik 的新书的精彩评论为一场关于经济学(就此而言,整个社会科学)有多“科学”的长期争论提供了一个窗口。是对数据的态度,比如对科学方法的整体强调,良好的研究设计,以及对数据的有效利用,有利于科学吗?或者,正如罗德里克所强调的那样,是演绎逻辑思维使某些东西成为科学吗?或者更现实地说,是两者的结合?当然,这是一个古老的争论,可以追溯到几个世纪以前,甚至更久。Vladimir Vapnik 不仅是统计学习方法的发明者,也是一位专注于哲学思考的严肃思想家,他关于支持向量机的书在一旁引导了波普尔和其他人对科学和经验思维之间联系的思考——例如,占星术(其从业者越来越多地开发出一致的逻辑和复杂的数学模型来支持他们的工艺,不管它有什么价值)或气象学(其产品仍然不完全可靠,特别是中期或长期)是否符合科学的条件。
值得指出的是,鉴于牛顿物理学(或后来的量子力学)诞生时可用的技术,它们提供了相对较少的明显可检验的预测,许多预测是相当错误的(尽管它们也解释了为什么它们是错误的——并且潜在地为如何评估它们铺平了道路,如果可用的技术允许它们的话)。看起来,科学之所以存在,是因为某种东西并不盲目地服从于经验主义或理论。它让自己被经验数据证明是错误的,但只是在它自己的内在逻辑中提出的条件下。换句话说,科学依赖于一个条件逻辑:不是 X 无条件地是 X,而是只要 A、B 和 C 成立,X 就是 X。因此,从经验证据来看,第一运动定律并不是明显错误的——因为在地球上很少看到永恒的运动,而大多数人都是在地球上收集数据的——因为它列出了它成立的条件(例如,缺乏摩擦,这排除了我们拥有的大部分数据)。
科学的条件逻辑对于它在现实生活中的实际应用,或者说缺乏(直接的)普遍的实际适用性是至关重要的。科学奠定了围绕其理论基础构建的大图景,但现实是噪音。为了科学地对待现实生活,我们需要分两步走:放下大局,然后确定现实生活偏离大局的不同方式。通常,成功的工程利用了第二步,而不是第一步。继续一个愚蠢的例子,牛顿第一运动定律对于实际用途来说是相当无用的——如果所有的东西永远保持运动,我们就不需要担心燃料效率之类的问题。交通运输面临的真正挑战是摩擦,也就是牛顿第一定律所说的“噪音”。但是没有必要完全理解摩擦为什么以及如何工作,只需要理解摩擦在特定情况下的作用。所以我们有一个巨大的表格,里面有各种情况下的摩擦常数,可以用来近似摩擦如何影响运动,我们可以用它来实际应用牛顿定律。(顺便说一句,这就是为什么我发现对“数据科学”中的“科学”的痴迷可能令人不安。我看不出大数据及其噪音如何能提供比牛顿物理学更具体应用的一般理论。我希望大数据能够发现可以作为有用起点的一般原则,但对于特定应用,我们需要弹簧常数、摩擦常数和所有其他半规则基础上重复出现的条件噪声测量值——半规则是指它们的影响是概率分布,而不是无噪声的标量。我们拥有的数据越大,我们就越能够将数据分割成符合特定条件的子集,并为这些条件估计适当的“常数”,以及建立规则和常数可能不可靠适用的子集——本质上是建立效应分布方差的一部分。本质上,我们需要更好地理解噪音,对大模式的偏离。非常坦率地说,要看到大的模式,我们不需要该死的大数据——如果它们足够大,我们甚至可以在小数据中看到它。当然,这更多的是一种工程思维,也许是一种古老的思维。)
这种更倾向于附加条件的思维方式,意味着数据收集的方法不同于目前的做法。目前太多的想法似乎集中于收集更多的数据,而不考虑数据来自哪里。但是大多数数据是无趣的、普通的、可预测的。为了估算火星的“常数”,我们需要火星数据,而不是地球数据。如果我们真的想知道火星常数,我们需要花费数十亿美元发送探测器到那里收集一些观察数据,而不是派人去纽约市周围收集大量数据。换句话说,大数据更有用,因为作为收集它的副产品,我们可能会捕捉到更多我们可以使用的不寻常数据——数据越大,在大量不太有用的数据中可能会有越多有用的小数据。但是,根据数据收集过程,即使是最大的数据也可能无法捕捉到我们需要的足够多的数据。
当然,我们估计的这些常数不会是“真理”,而是“有条件的真理”——我们认为是真实的东西,因为我们在特定的条件下,从我们所拥有的我们(应该)知道是不完整的数据中归纳地了解到了它们。(但是,演绎真理也不是——它们之所以是真理,只是因为我们认为现实的逻辑基础实际上是广泛适用的逻辑基础。除了通过公理化的断言,我们怎么知道呢?甚至建立我们“演绎地”认为是真实的东西也需要经验主义,或者至少可以从经验主义中获益。)它们把我们带回了统计学的根本问题(相对于概率论):我们不知道真相。我们只能从现有的数据中推断出真相。如果我们看到数据中的模式,我们只在我们能扔出数据的范围内信任它们——有时,我们不能扔得很远。知道我们能把数据扔多远(以及收集和分析它们的方法)是我们需要时刻牢记的事情。现代技术大大增强了数据分析的力量,但一些数据仍然非常沉重,难以丢弃,而且无论如何,没有数据可以跨越无限的距离。如果数据说答案是三,不代表答案是三。这仅仅意味着,在我们的询问下,数据显示答案是三。因此,我们相信我们收集和分析数据的方式如此反映现实,以至于我们认为答案是三——这在大多数情况下可能足够好——但有时可能不是。我们可能想知道“有时”可能是什么,也许是考虑我们是否应该购买保险的时候。
我在这里并不完全公平:实验的精神,或数据科学人士的 A/B 测试,反映了这种逻辑,即“自然”可用的数据是有限的,有时需要寻找非自然的数据。然而,更早的实验设计著作,对拉丁方块和其他怪物的详细描述,更热衷于为正确的比较建立适当的匹配,以及为理论产生必要的信心所需的功效计算。人们可能会考虑如何在现代环境中创造性地使用过去精心设计的实验设计。条件均值和方差对于建立实验效应的显著性是至关重要的:我们知道如果 P(X1 |除了 A=0 之外,其他都一样)!= P(X1 |除了 A = 1 之外所有我们知道的都一样),也许 A 和 X1 有关系。但这将概率论的逻辑叠加到了统计学上:我们(认为我们)知道 A 有影响,所以我们会审问数据来找出答案,即使是通过创造自然界罕见的半人工数据(通过实验。)但是,通常,我们并没有一个很好的理由来预测 A 是否对 X1 有影响。我们希望依靠某种算法来发现是否存在像 a 这样的变量。
嗯,我们已经一直在做这种事情:我们有列联表(或数据透视表)。我们切割数据,并显示它们的条件均值和其他统计数据,这取决于它们属于哪个子集。潜在的警告是,表越大越难理解——但算法不会被这种事情困扰。我们已经在分类方案中使用相似性度量:利用这一点来人为地为所有感兴趣的变量创建“除了一个(或两个或三个)之外,所有变量都相似”的分数,并比较条件均值,这并不是一个很大的飞跃。条件上足够大的差距意味着→值得用人眼进一步看的东西。这在逻辑上相当于一个巨大的拉丁方,存在有趣的缺口,无论是样本中条件平均值的计算值,还是潜在分组缺乏足够的数据,都由编程到算法中的逻辑确定。(潜在的同样有趣的方法是关注条件方差:一些变量组合在一起,可能会产生非常可靠的预测;其他组可能会导致真实数据到处都是。预测分析人士可能会对发现这样的团块感到震惊,但这只是寻求人类更密切的关注和想象力。)
科学不是数据,数据不是科学,科学也不是演绎逻辑。事实上,科学是对数据的巧妙利用与基于条件概率的演绎逻辑的创造性融合:不是 A → B,而是 A →B|X,Y,但不是 Z,所有有趣的发现与其说与 A →B 有关,不如说与“X,Y,但不是 Z”有关(A → B 很好,但它可能不需要大数据或巧妙的实验。)我认为,当科学被应用于实际目的时,条件概率理论更加适用。我们没有永动机。我们需要知道在不同的环境下需要担心多少摩擦——噪音,如果你愿意的话。重要的是,我们现在越来越多地拥有技术和数据来系统地分析大量数据中的噪声,也就是说,如果我们愿意走这条路的话。不幸的是,有条件的部分经常被委托给“技术细节”:所以人们被说服,“嘿,科学!说 A →B!”不,不是真的。真正的“科学”在于“X,Y,而不是 z”。具有讽刺意味的是,经过适当的训练,人类实际上非常擅长破译条件概率,即使有大量的细微差别。人类不擅长的是钻研大量数据,并看到大的模式——因此人类过度拟合和过度概括,看到罕见的情况太多了。如果人工智能可以帮助指出人类真正有用的地方,并让他们远离他们容易看到不存在的东西的地方,那将是一件很酷的事情。
PS。原标题是 3 分钟,然后我岔开话题,继续说了很长时间…
所有的新闻
使用 KMeans 对 143,000 篇文章进行聚类。
我最近策划了这个数据集,探索构成我们新闻的类别的一些算法近似,这是我在不同时间阅读和创作的东西。如果你有成千上万篇来自各种渠道的文章,这些文章似乎或多或少地代表了我们的国家新闻格局,你把它们变成结构化数据,你用枪指着这些数据的头,强迫它们分组,这些分组会是什么?
我决定,简单性和有效性的最佳平衡是使用无监督聚类方法,让数据自己排序,无论多么粗糙(类别,无论它们来自什么算法,几乎总是粗糙的,因为没有理由媒体不能无限小地分类)。出于各种原因(本地内存限制、能力、来自更有学问的人的建议),我选择通过 KMeans 运行一个单词包——换句话说,如果每个单词都成为它自己的维度,每篇文章都成为单个数据点,那么会形成什么样的文章簇呢?如果你渴望跳到“那又怎样”和/或不关心代码,向下滚动直到你看到粗体字母告诉你不要这样做。代码在这里,如果有人想同行审查这一点,告诉我,如果/哪里我搞砸了,和/或给我建议。
因为 KMeans 是非确定性的,所以结果会有所不同;聚类在运行之间会有一点点变化,但是,现在已经做了很多,我可以证明它们不会有很大的变化。这里的结果或多或少是数据所固有的。
简要概述
数据看起来是这样的:
The number of articles in the dataset
这些出版物是基于完全不科学的笛卡尔内省过程选择的,我审视了自己,得出了一个粗略的总结,我认为这是我们国家新闻景观的合理样本。抓取这些文章的方法大致如下:
- 从无价的 archive.org 上获取过去一年半中每份出版物的存档主页或 RSS 订阅源的链接(如此珍贵,以至于我后来给了他们钱以表示感谢(如果有人在阅读,感谢存在))。
- 使用一个由 BeautifulSoup 拼凑而成的非常非常粗糙的 web scraper 从存档的主页上的每个链接中抓取每一篇文章。
- 无趣的数据。
- 清理不干净的数据。
- 等等。
也就是说,这里的数据包含了主要从 2016 年初到 2017 年 7 月的这些出版物的文章,并且是在主页或 RSS 提要上出现的文章——即,这不是像 2016 年 8 月 13 日那样对整个领域进行贪得无厌的真空处理。
词干分析
这是数据的一部分:
我做了一个判断调用(你可以判断这个判断)从语料库中删除专有名词。这种想法是,A)它们太多了,B)它们没有告诉我们太多关于写作的内容和方式,C)当试图归结这些类别的本质时,它们是另一种形式的噪音。稍后您将会看到,Python 的 NLTK 是一个很棒的包,但是它并不完美,在试图清除掉一些专有名词之后,它们仍然留在了 corupus 中。
此外,我决定删除数字。这里有一行是关于 NLTK 的标记器有时会在单词末尾留下句点的倾向,我认为这是一个 bug。
堵塞过程看起来像:
import nltk
from nltk import pos_tag
from nltk.stem import PorterStemmer
from nltk import word_tokenize
from collections import Counter
import timestemmer = PorterStemmer()
tokenizer = nltk.data.load(‘tokenizers/punkt/english.pickle’)progress = 0 #for keeping track of where the function isdef stem(x):
end = time.time()
dirty = word_tokenize(x)
tokens = []
for word in dirty:
if word.strip(‘.’) == ‘’: #this deals with the bug
pass
elif re.search(r’\d{1,}’, word): #getting rid of digits
pass
else:
tokens.append(word.strip(‘.’))
global start
global progress
tokens = pos_tag(tokens) #
progress += 1
stems = ‘ ‘.join(stemmer.stem(key.lower()) for key, value in tokens if value != ‘NNP’) #getting rid of proper nouns
end = time.time() sys.stdout.write(‘\r {} percent, {} position, {} per second ‘.format(str(float(progress / len(articles))),
str(progress), (1 / (end — start)))) #lets us see how much time is left start = time.time()
return stemsstart = time.time()
articles['stems'] = articles.content.apply(lambda x: stem(x))
结果是一篇文章由此而来:
Queen Elizabeth II made her first public appearance in almost a month on Sunday, allaying concerns about her health after she missed Christmas and New Year’s Day church services because of what Buckingham Palace described as a persistent cold. The queen, who will turn 91 in April, attended services at St. Mary Magdalene Church in Sandringham...
对此:
made her first public appear in almost a month on , allay concern about her health after she miss and s church servic becaus of what describ as a persist cold the queen , who will turn in , attend servic at in...
词干处理大大减少了语料库的规模。“实现”和“实现”不是被认为是不同的词,并被赋予各自的维度,而是被简化为它们共有的词干,“现实”。这减少了噪音,因此算法不会对出版物使用过去时态而不是现在时态的决定产生影响,或者不会将复数名词视为词汇的不同部分而不是单数名词,等等。
创造词汇
现在进行人数统计,统计整个语料库中的每一个词干,然后可以将其转化为数据帧,用于文档术语矩阵和词汇表。
from collections import Counter
all_words = Counter()
start = time.time()
progress = 0
def count_everything(x):
global start
global all_words
global progress
x = x.split(‘ ‘)
for word in x:
all_words[word] += 1
progress += 1
end = time.time()
sys.stdout.write(‘\r {} percent, {} position, {} per second ‘.format((str(float(progress / len(articles)))),
(progress), (1 / (end — start))))
start = time.time()for item in articles.stems:
count_everything(item)
然后将其传送到新的数据帧:
allwordsdf = pd.DataFrame(columns = [‘words’, ‘count’])
allwordsdf[‘count’] = pd.Series(list(all_words.values()))
allwordsdf[‘words’] = pd.Series(list(all_words.keys()))
allwordsdf.index = allwordsdf[‘words’]
在数据帧的开头给出:
Republican 的加入是一个很好的例子,说明词性标注者并没有完全去除专有名词。但忽略这一点,语料库现在是一个数据框架,词汇表中的每个术语都是索引中的项目,这在不久的将来会很有用。
当处理来自因特网的文本数据时的一个挑战是,非单词,如字符和符号的组合(例如,“@username”,“#hashtags”,用类似“well 1…”的省略号连接的单词),以相对频率出现。我决定只保留 NLTK 的完整英语语料库中的单词,而不是找到并清理每一个单词。语言学家们还在争论这个语料库有多完整,但是有 236,736 个单词,这是一个相当大的数字。我们将首先通过对整个英语语料库进行词干分析,然后将该语料库与我们自己的语料库进行比较,来完成我们的数据框架的最终精简:
from nltk.corpus import wordsnltkstems = [stemmer.stem(word) for word in words.words()] #stem the #words in the NLTK corpus so that they’re equivalent to the words in #the allwordsdf dataframenltkwords = pd.DataFrame() #make a new dataframe with the stemmed #NLTK wordsnltkwords[‘words’] = nltkstemsallwordsdf = allwordsdf[allwordsdf[‘words’].isin(nltkwords[‘words’])] #keep only #those in the stemmed NLTK corpus
这将总词汇量从 89216 减少到 34527。它处理了词汇表中的每一个细节,我花了几个星期才考虑这个解决方案。
将单词矢量化
粗略地说,TfIdf(术语频率-逆文档频率)矢量器为每篇文章中的每个词给出一个值,该值由该词在整个语料库中的频率加权。逆向文档频率是从单词在整个数据集中的频率得出的分母。以“perspicacious”这个词为例,由于它在英语中有许多更好的替代词,这个词是一个我们很幸运几乎看不到的扯淡词。由于这种稀缺性,它的反向文档频率,或妖魔化,是低的。如果它在一篇文章中出现 15 次,那么它的 Tf 值或分子将会很高。因此,它的 TfIdf 值将是一个大分子,而不是一个小恶魔,从而产生一个大数字。因此,在我们数千维的空间中,文章在“洞察力”维度上具有价值。(当然,这还不包括向量的归一化和寻找 TfIdf 值所涉及的其他任务。)
当使用这种类型的矢量器时,包含非索引词(算法忽略的词的列表)并不重要,因为不常用的词被赋予较低的值。但它仍然是有用的,因为至少它降低了内存的使用,减少了我们的空间已经非常高的维度。此外,创建一个单词库可以确保出现在一篇文章中的非常罕见的单词不会自己聚集在一起。我选择了第 40 个分位数以上的单词。乍一看,这似乎很高,直到你看到这个分位数包含的内容:
allwordsdf[allwordsdf[‘count’] == allwordsdf[‘count’].quantile(.4)][:10]
因此,第 40 个分位数包括在整个语料库中只出现 9 次的单词——非常低,因此不倾向于提供信息。为什么不是第 50 或 60 分位数?因为必须在某个地方选择一个数字,它可能就是这个。
创建停用词,矢量词汇和矢量。写停用词和词汇表可能是多余的;我把两者都加进来是为了更好的衡量,因为我们以后需要这个词汇列表。
from sklearn.feature_extraction.text import TfidfVectorizerstopwords = list(allwordsdf[(allwordsdf[‘count’] >= allwordsdf[‘count’].quantile(.995)) | (allwordsdf[‘count’] <= allwordsdf[‘count’].quantile(.4))][‘words’])vecvocab = list(allwordsdf[(allwordsdf[‘count’] < allwordsdf[‘count’].quantile(.995)) & (allwordsdf[‘count’] > allwordsdf[‘count’].quantile(.4))][‘words’])vec = TfidfVectorizer(stop_words = stopwords, vocabulary = vecvocab, tokenizer=None)
现在要转换数据帧:
vec_matrix = vec.fit_transform(articles[‘stems’])
这就产生了一个矩阵形状的(142570, 20193)
,也就是大约 20,000 个单词。
降维
把我们的 20,193 维矩阵降多少维很难回答。Sklearn 的官方推荐声明,“对于潜在语义分析(我们在这里做的),推荐值为 100。”我用所有 20,193 个维度对这些数据进行了聚类,用 100 个维度进行了聚类,用 3 个维度进行了聚类,每一次,这些聚类看起来都与有多少个维度无关。这最终归结为减少处理时间,因为创造这个包的人的智慧规定了 100 个维度,所以它是 100 个维度。
from sklearn.decomposition import TruncatedSVDpca = TruncatedSVD(n_components=100)vec_matrix_pca = pca.fit_transform(vec_matrix)
使聚集
更难回答的是给数据分配多少个聚类。对于 KMeans,数据过于紧密地聚集在一起,不适合分层聚类或任何自己查找聚类的算法。如上所述,我选择了十作为起点。
from sklearn.cluster import KMeansclf10 = KMeans(n_clusters=10, verbose = 0)clf10.fit(vec_matrix_pca)
现在,将我们刚刚创建的标签分配给原始数据帧,以便进行分组、可视化和分析:
articles[‘labels’] = clf10.labels_
我们可以看看每个出版物的文章被分配到每个标签的百分比:
labelsdf = articles.groupby([‘publication’, ‘labels’]).count()
pubslist = list(articles[‘publication’].unique())
labelsdf[‘percentage’] = 0for index, row in labelsdf.iterrows():
for pub in pubslist:
for label in range(10):
try:
labelsdf.loc[(pub, label), ‘percentage’] = labelsdf.loc[(pub, label), ‘id’] / labelsdf.loc[(pub), ‘id’].sum()
except:
passlabelsdf = labelsdf[['publication', 'labels', 'percentage']]
等于
诸如此类。
如果你向下滚动,这里是停止的地方
这些图表是在 RStudio 中用 Plotly 制作的,plot ly 是一个有时质量不佳但仍然有用的数据软件包。
这些是聚类,每个聚类中的前 200 个单词及其 TfIdf 值。单词越大,确定是什么组成的集群就越重要。它们不会被政治联盟、基调或其他任何东西所瓦解;当数据聚集在一起时,会按类别分解。记住,我们选了十个;我们可以选择 8 或 20 个并得到不同的集群,但这些是最突出的。一个是关于俄罗斯的所有事情-丑闻,另一个是关于外交政策,另一个是关于教育等等。随意探索。(Plotly 允许用户放大,但字不会变大;我已经通知了当局来解决这个问题。)
下面是出版物是如何按组分类的。(同样,对于隐私獾用户来说,这个就是。)
还有最后一个 viz,如果它大小引起了问题,我很抱歉,但是我认为它很重要。
它的名字(“articlestest”)应该表明我在创建它时处于什么准备阶段,它与最终的数据集略有不同——除了其他所有东西,它还包括来自 the Verge 的长篇文章,我选择了去掉它。它是将所有数据缩减为三维的可视化,而不是 20,000 多个维度(或上面主成分分析中使用的 100 个维度)。添加边缘会给人一种与移除边缘时截然不同的形状,我完全不确定这是为什么。但是如果你观察它,你可以看到每个集群在三维空间中形成的位置,你可以双击右边的每个出版物名称,只保留那个出版物。如果你点击它们,你会看到几乎每一个都是无形的数据点云,除了路透社,它形成了一个几乎完美的 l。
推论性的结论
不同的人可能会对这些数据和图表有不同的解读,但我是这样解读的:当被迫分组时,出版物被归类为路透社和其他。
我不认为这是对数据的过度提取。数据科学的一个主要哲学基础是,潜在的真理和联系是由表面现象引发的,一个人说话的语气或穿着的风格比我们愿意承认的方式泄露了更多关于我们的信息。这些出版物中的一个以与其他出版物如此不同的形式出现,完全基于它覆盖的主题,这将被合理地认为是考虑它与数据集的其他成员根本不同的原因。
诸如此类的结论应该经得起纯粹反思的考验——考虑到阅读这些出版物的体验,这些结论有意义吗?
在 Medium 的几个门下,兰詹·罗伊 写了一篇文章关于 Vice 的夏洛茨维尔分部看似不可思议的病毒式传播。他提醒我们,Vice 现在是另一个默多克资助的暴行机器。我不同意罗伊的观点,即视频的点击率如此容易地归因于 HBO 的阴谋诡计(因此暗示病毒传播可以被预测地设计,但它不能),但就我们的目的而言,他以一个有益的反思结束了这篇文章:
我们越是接受耸人听闻的现实,我们就越糟。只要我们让我们的蜥蜴脑控制我们对世界的感知,我们就没有机会。如果我们没有意识到我们所观看的背后的动机,疯狂的人总是会赢。
这是价值十亿美元的媒体,由拥有福克斯的同一个人出资。它完善了让你下去的艺术。记住,在一个我们每天花费 116 分钟消费广告资助的社交媒体的世界里,最响亮的声音总是会赢得。[强调他的]
除了路透社之外,该数据集中的所有出版物都有一些共同点。它们完全由广告和/或订阅资助(Vox 和 BuzzFeed 也有风险投资,但它们是基于广告的模式),它们的存在依赖于点击。相比之下,路透社的新闻产品仅仅是一家大型信息集团的公众形象。或许更重要的是,它是一家新闻通讯社,其报道包括我们金融世界的事务,因此被赋予了不同于其他媒体的使命——可以说比《纽约时报》更重要,它必须覆盖所有新闻,而不会陷入人物驱动的真人秀,而该数据集的每个其他公民似乎都非常喜欢这样做。在所有这些事件中,它的声音倾向于保持最适度的室内音量,如果路透社能够激起愤怒的话,没有一个全球性事件会激起比生活更大的愤怒。也许这是隶属于财经出版社,宏观分析世界的产物;非金融媒体的叙述未能对伦敦银行间同业拆借利率(LIBOR)的变化和一个疯子的政策提议给予同等的重视,尽管按理说应该如此。这里的所有其他出版物似乎都带有乌托邦的暗示,它们内容的潜台词通常是,如果我们在食谱中混合了正确的成分,一个完美的世界就会实现,而你感到愤怒的事情实际上是我们和天堂之间的事情。在我作为读者的经历中,我从来没有感觉到路透社有任何类似的东西。
这不应被解释为断言《纽约时报》和《布莱巴特》因此是同一批中风患者。我今天在《泰晤士报》上读到了一篇设计精美的文章,内容是关于生物发光在深海生物中是多么普遍。不言而喻,在布莱巴特找到这样一份文件的可能性几乎为零,这是我对政治光谱的这一领域感到非常悲哀的事情之一,也是对其截然相反的反对者的一份谈话要点备忘录。但这才是重点:给一个算法看你写的关于深海生物的故事数量,它就会显示你是谁。在更精细的分辨率下,我们可能会发现《纽约时报》和《福克斯新闻频道》之间的鸿沟,或者《NPR 时报》和《纽约邮报》之间的鸿沟。看到上面的第三个聚类了吗,所有的单词都用较低的 TfIdf 值进行了压缩,没有突出的内容。它实际上是其他主题的整个丛林,你可以在那个集群上运行算法,并获得新的分组和区别——这些集群中的一个也将是不同类型故事的压缩,你可以在机器学习的分形中一遍又一遍地这样做。这里的区别不是唯一的,但从数据的空中视角来看,这是第一个。
作为一个创造内容的人,我在法律上有义务经营一份个人时事通讯。可以在这里 报名参加 。
您需要了解的所有机器人流程自动化(RPA)统计数据
如果你在过去几年里一直关注科技行业,你可能已经听到了很多关于机器人过程自动化(RPA)及其改变我们工作方式的潜力的讨论。专业领域正从智能自动化初创企业及其应用的爆炸式增长中受益匪浅,这些应用的目的是简化工作流程、实现任务自动化,并让人类工人专注于高价值的工作。WorkFusion 拥有一套智能自动化产品来帮助您扩大运营规模并降低管理成本。
没有一个放之四海而皆准的统计数据可以准确评估 RPA 可以为您的公司节省多少资金,它可以自动化多少工作流程,以及在不雇佣数百名员工的情况下您的运营规模可以有多大。这主要是因为不同的公司有不同的技术、系统、流程,并且他们在不同的行业工作。然而,有一些 RPA 数字可以让您了解该技术可以提供多少自动化,以及它可以提高您的 ROI 多少。
以下是围绕该技术的一些关键数据:
1)它能帮你实现什么自动化
RPA 在各种规模的企业中变得越来越普遍,帮助他们自动化繁重的工作,如会计和 IT 任务,以帮助保持您的运营顺利进行。这项技术非常有助于减少任何人工操作中必然会出现的人为错误。得益于人工智能(AI)、机器学习(ML)、大数据、语音识别技术和深度神经网络方面的最新进展,RPA 在后台和前台实现了基于规则的流程自动化。
该技术有助于降低成本、提高准确性、改善服务交付、帮助解决合规和监管问题,同时还能改善客户体验。这些基于规则的流程中大约 70%到 80%可以实现自动化,从而让企业以比离岸更低的成本在国内运营。使用 RPA 的公司不需要依赖离岸或外包合作伙伴,从而确保 100%的准确性。
2)减少工时
根据 软件测试和大数据 Hadoop 的研究,大约 10%到 20%的人类工作时间花费在枯燥、重复的计算机任务上,相当大一部分时间浪费在可以轻松自动化的流程上。该公司的研究人员估计,IT 部门也有 30%的时间花在低级别的基本任务上。此外,大约 50%的公司在每张人工处理的发票上花费 5-25 美元。
企业平均错过了大约 50%的自动化机会,而 13%的员工认为这些重复的任务是浪费时间。此外,98%的 IT 业务领导表示,自动化流程对于推动业务收益至关重要。可以自动化的主要任务依次为:
- 文件和记录管理。
- 索赔、预订和发票管理。
- 客户关系管理。
- 人力资源流程。
- 它处理。
WorkFusion 有一个 RPA 平台,可以帮助公司在 RPA Express 中自动化这些任务和更多任务。
3)RPA 的未来
Hadoop 的研究人员估计,到 2025 年,公司将通过 RPA 节省 5 万亿至 7 万亿美元。该公司还预测,到同一年,RPA 软件将能够完成相当于 1 . 4 亿全时当量的任务。 Statista 认为,到 2019 年,RPA 行业价值将达到 31 亿美元,到 2020 年将达到 49 亿美元。据 Forrester 预测,到 2021 年,这一数字更有可能达到 29 亿美元左右。
AB Newswire 补充道,RPA 市场目前由北美地区主导,亚太地区在医疗保健、零售、IT、BFSI 和电信行业也在高速采用该技术。中国和印度已经开始推出外包服务,推动了这些地区的市场。在欧洲,RPA 预计将在制造业和物流业增长,尤其是在德国、俄罗斯、西班牙和丹麦。
底线…
没有人知道 RPA 在以前只能手动执行的自动化任务中会走多远,但该技术在转变企业运营方式方面有很大的潜力。未来几年,世界各地的几乎每个行业都将受益于智能自动化系统的功能。只要企业在寻找新的解决方案、更低的开销和更高的投资回报,RPA 就会继续变得更加复杂和流行。
关于正规化,你需要知道的是
过度拟合的原因以及正则化如何改善它
爱丽丝 : 嘿鲍勃!!!我已经对我的模型进行了 10 个小时的训练,但是我的模型产生了非常差的准确性,尽管它在训练数据上表现得非常好,这是什么问题?
鲍勃:哦!!看起来你的模型在训练数据上过度拟合了,你使用正则化了吗?
艾丽斯:那是什么?
这种与过度拟合相关的问题在 ML 中很常见,有许多方法可以避免这种问题,但是为什么会出现这种问题?
训练一个模型的过程似乎很简单:
- 收集数据
- 预处理数据
- 设计一个模型
- 训练模型
但是在这个过程中间发生了什么呢?什么导致过度拟合,为什么正则化给出了解决方案?
过度拟合的主要原因可以追溯到开始的两个过程,数据的收集和预处理。具有不均匀特征分布、包含噪声、数据中的随机波动、非常高的方差的数据集合可能对模型训练产生相反的影响。这些随机误差和波动在训练时被模型很好地学习,以至于训练数据模型的精度变得非常高,导致数据的过度拟合。有时超过要求的训练会导致过度适应。
source : https://stats.stackexchange.com/
那么,怎样才能避免过度拟合的问题呢?
可以容易地观察到,权重越高,非线性就越高,因此一种简单的方法是在更新权重时惩罚权重。在这一点上,我们有两个这样的技术使用这个想法。
- L1 定额:
其工作方式是在我们需要减少的误差函数中添加一个带有参数 λ 的惩罚项。这里 w 不过是权重矩阵。
这里, λ 是一个超参数,其值由我们决定。如果 λ 很高,它会对误差项增加很高的惩罚,使得学习到的超平面几乎是线性的,如果 λ 接近 0,它对误差项几乎没有影响,不会导致正则化。
L1 正则化也经常被视为一种特征选择技术,因为它将不需要的特征的相应权重清零。L1 在非稀疏情况下的计算效率也很低。L1 有时可能被称为套索回归。
- L2 常模:
L2 的正规化可能看起来与 L1 没有太大的不同,但它们有着几乎不相似的影响。这里重量“w”分别平方,然后相加。L1 的特征选择属性在这里丢失了,但是它在非稀疏情况下提供了更好的效率。有时 L2 被称为山脊回归。参数 λ 的作用与 L1 相同。
提前停止:到目前为止,我们已经添加了惩罚来控制权重值,但也有其他方法来调整,如果在训练过程中,训练误差开始下降,测试误差开始上升,我们会停止训练。这将为我们提供所需的列车测试误差设置。这种技术通常被称为提前停止。这种技术可能会给我们想要的结果,但一般来说,有些人不建议这样做。
source : deeplearning4j.org
**退出:**这是 Srivastava 等人(2014 年)首次提出的一种有趣的正则化神经网络的方法,该论文提出,一个层中的一些节点必须随机选取,并且应该在训练期间被丢弃/忽略。
source : commonlounge.com
每个节点都有被丢弃的概率,假设一个节点的 drop_prob =0.4,那么它有 40%的机会被丢弃,60%的机会被拾起。每次这个概率都会导致神经网络改变形状,每次看起来都是一个新的网络。这种技术似乎很好地解决了正则化的问题。丢弃的概率不是很高,因为这将使网络稀疏,从而导致不匹配。
**数据扩充:**我们可能会看到计算机视觉中的过拟合问题,数据扩充是解决这一问题的更好方法。我们只需要自己放大图像,比如翻转、裁剪、旋转图像。
source: medium.com
这种类型的增强似乎产生更好的结果,因为它提供了在一些变形图像和其他变化上进行训练的机会,并且当可用数据较少时,数据增强也有帮助。
这些是一些有助于解决过度拟合的正则化技术。有时调整超参数可能会得到想要的结果,但如果没有改善,那么上述技术肯定可以解决这个问题。
关于区块链,你需要知道的
Photo by Daniil Peshkov | Dreamstime.com
当你周围的几乎每个人都在谈论完全不属于你专业领域的事情时,你会感到困扰吗?他们用一些听起来很奇怪的术语,脸上带着公事公办的表情,这让你更加恼火。你只捕捉到一些像区块链、比特币之类的词,但作为一个整体,你无法解读这些胡言乱语,即使这个主题听起来对你来说很有趣。所以,一个简单易懂的解释正是医生所要求的,对吗?我也这么认为。这就是为什么你在正确的地方得到你需要知道的关于区块链的一切,以摆脱那些自鸣得意的万事通。
一些专家认为它是未来几十年最有影响力的技术,甚至称之为“下一代互联网”。由于区块链如今受到媒体的广泛关注,这个概念对于外行人来说应该比较容易理解。但是在现实生活中,事情要复杂一些。因此,我邀请你加入我的旅程,探索区块链及其衍生品的基本原理——智能合约、分布式账本、比特币和许多其他东西。
在区块链出现之前是怎样的
为了弄清楚区块链是什么,有必要了解在这项技术还没有出现的时候,情况是怎样的。
我们的日常运营会产生持续的数据流。当你用信用卡给你亲爱的侄子转账或者给你的合伙人发合同签字时,你给他们的是复印件,而不是原件。如果在 Word 文档中,一个文件可能有两个样本(原始版本和您发送的版本),那么其他一些资产(比如钱)是不能复制的。所以,每个人都必须确定,在你付款后,你没有另一个版本的相同货币可以转移给别人。
传统上,我们依赖一些中介,如银行,将所有数据保存在一个数据库或数据中心。它拥有数据的唯一副本,而且从理论上讲,每个相关人员都可以访问它。然而,现实有所不同,也更加复杂。
除了我们在提交信息时必须信任这些中介这一事实之外,随着时间的推移,还会出现一些问题。事实上,所有东西都存储在一个地方(意味着它是集中的),这使得它容易受到攻击。此外,在上述合同的情况下,双方不能同时处理同一份文件,这就产生了版本可能丢失、文件在接收方之间来回移动以及时间延迟等其他不便的问题。
区块链的到来(红利:它是什么)
为了解决上面提到的问题,科学家 Stuart Haber 和 W. Scott Stornetta 在 1991 年开始研究一种密码保护系统,其中文档的时间戳不能被调整或回溯。然而,区块链领域的第一个重大成果是在十多年后由中本聪取得的,当时他利用哈伯和斯托纳塔的想法开发了比特币的基础设施。
在某种程度上,区块链引入了一种新的做事方法:每个节点都可以看到系统中发生的所有事务,并且应该收到每一个事务的副本,以更新其数据,并从本质上批准它。
基本上,它只是一种存储数据的新方式。它与现有数据存储技术的唯一区别在于整个过程是如何完成的。区块链建立在这样一个原则上,即所有信息都应该分布在多个位置,而不是一个位置,使用最高级别的加密技术。这意味着所有参与者都相互连接,并拥有给定数据的相同副本。如果你过去使用过种子,你可能会注意到一些相似之处。
区块链如何改变过程
因此,技术给了我们一个分散的数据库版本,或者是网络中任何人都可以使用的交易的数字分类账。它允许用户通过在几乎任何操作中绕过第三方(数据存储)来利用彼此的对等通信。
但是这给每个参与者个人带来了大量的工作。这个问题由一个名为“矿工”的特殊群体解决,他们获得令牌(比特币或其他数字货币)来处理这个问题。在硬件能力的帮助下,矿工创建信息块,存储在给定时间内系统中发生的所有交易,并验证它们。
我不会深入研究这个过程,但基本上,它涉及到解决一个计算问题(更详细的解释见下面的信息图)。然后,这些块被添加到已经存在的块中,创建一个链(因此得名),其中所有信息都按时间顺序保存,并且可以很容易地访问(这使其真正公开)。
Image is created by the author and all rights reserved for X1 Group
一旦你成为系统的一部分,你就有了两个密钥:公共密钥(你的地址,或者,为了简单起见,你的用户名)和私人密钥(你的密码)。换句话说,黑客不能犯任何错误,因为他或她应该找到并改变一个特定的块加上所有前面的块,但是正如你已经知道的,所有的块同时位于所有现有的计算机上。最重要的是,它们用特殊的数学函数(用户的私钥)加密。有了这样一种优雅的、乍一看并不显眼的技术,漏洞问题就变得几乎无关紧要了。
加密货币
现在,在 2018 年,它成为一种资产形式,可以投资于那些寻求有利可图的机会并且不怕承担风险的人。尽管市场波动很大,但需求是巨大的。加密货币是一种数字货币,它使用加密技术来控制其金额并验证资金转移,独立于中央银行运行。
在 2009 年,比特币出现的那一年,没有人会想到 9 年后超过 1900 种加密货币会提供给每个愿意放弃一些钱来换取数字货币 的人。其中最受欢迎的是比特币和以太坊。让我们来讨论一下这两者有什么不同,以及为什么他们成功地更好地了解了这种势不可挡的隐热。
比特币是众多获得国际认可的货币中的第一种,现在,它是价值最高的加密货币之一。不清楚为什么大家都对比特币如此狂热。有人说骗子让它流行是因为你做的交易是匿名的,几乎无法追踪;其他人说,这只是因为它很容易设置,你可以快速,安全地进行支付,交易费用最低。
Photo by Thought Catalog on Unsplash
但是不要搞错,以太坊可以做同样的事情,甚至更多。它在已经蓬勃发展的技术中达到了一个全新的水平。以太坊基本上不仅仅是加密货币,还是一个有自己虚拟语言的中心化平台。使用这个平台,作为一个功能更强大、更灵活的工具,开发者可以创建新的区块链应用程序。
此外,以太坊使用智能合约,并包括一种同名的数字货币,但只是作为副产品。智能合约本质上就是它听起来的样子。这是一个自我实现和执行任何算法的合同,你把它放入使谈判者之间达成协议更容易。这个工具有可能比区块链本身更具革命性。
区块链可能影响的行业
金融科技(银行和支付)
最有可能的是,从区块链的出现中获益的第一个行业是金融业。这项技术的集成让世界各地的每个人都可以获得金融服务,包括那些无法获得传统银行服务的人。与通常的方式相比,在通常的方式下,信息会通过一整套公司传递,每家公司都从中分一杯羹,从而降低了交易速度。相比之下,基于区块链的交易可以让你汇款无国界,费用几乎可以忽略不计。
更重要的是,收款人不必等几天才能拿到钱;整个过程发生在几分钟内。一些银行已经对这项技术表现出极大的兴趣,并开始投资——甚至采用——它来使他们的操作更快、更有效、更安全。
保险
全球保险业是一个相当复杂的机构,它的一些职能很难把握。通过使用区块链,消费者将能够看到他们投保了什么,他们是如何确保的,哪一方参与了,以及他们为什么会收到那么多的赔付。本质上,这意味着用户可以跟踪整个过程,并更好地了解整个市场以及他们可以选择的价值。
此外,通过使用区块链,整个行业可能会大大简化,因为将消除这么多参与方的需要。它将使所有形式的保险过程更加高效、自动化和透明,为消费者带来更加顺畅的体验。
政府和投票系统
这也许是区块链可能扰乱的最重要的社会领域。历史上有很多政党被指控操纵选举结果的例子。合法计票系统保证没有选票被篡改或删除,此外还有不可更改的公开注册,这将是对我们现有制度的巨大改进,使选举更加公平和民主。
Photo by Arnaud Jaegers on Unsplash
考虑到政府系统是多么缓慢和容易腐败,使用区块链可以大大减少官僚作风,提高政府运作的效率和透明度。
募捐
ICO(首次公开募股)是一种为你的创业公司获得投资的全新方式。这个过程有两个阶段——私人的,也称为“预售”和公共的。愿意启动项目的新公司向私人投资者发放品牌代币,以获得启动项目的第一笔也是最重要的融资。
这一步通常包括为准备投资的人提供巨大的折扣,但这也限制了最低购买金额。实施这样的政策是因为潜在投资者可能获得巨大的投资回报,因为预售通常发生在规划阶段。当一家公司证明了自己的价值,现在需要资金来支付运营成本、开发甚至可能部署产品原型时,第二个(公开)阶段就开始了。
在这个阶段,每个感兴趣并愿意参与的人都可以获得代币。在任何时候购买的所有代币都可以在以后兑换成产品、服务或现金。即使这些投资还远未确定,初创公司也通过这种方式筹集了数百万美元。
我们的身份
区块链提供的整套工具使得验证和管理某人的身份或者在愿意交互的各方之间建立至少某种程度的信任变得更加容易。在我们的一生中,我们创造了一些信息碎片来构建我们的虚拟形象。评论、评级、位置和证书:这些甚至都不是一个人数字足迹的重要组成部分,你可以拼凑起来,用来降低你在与谁打交道的不确定性。
听起来很容易,但事实上并非如此:这些信息都是碎片化的,因为我们每个人在网上都有大量的个人资料。区块链允许我们创建一个开放的全球平台来存储每个人的所有凭据。这也意味着我们可以通过选择我们想要透露的信息来保护我们的隐私,例如,达到法定年龄或从大学毕业。
什么会出错
尽管整个事情听起来很美好,但这项技术有一些需要注意的缺点。
首先也是最重要的是,区块链很复杂,而且不是真正的用户友好型。你可以在软件上花费数百万美元,开展大规模营销活动来展示你的产品有多好,但最终用户可能不会分享你的兴奋。为什么?因为大多数时候,消费者评价的是软件的前端部分,并不关心让一切运转的巧妙技术。听起来很刺耳,但事实就是如此。区块链驱动的软件对于普通用户来说远没有那么方便易用。
由于其复杂、加密的特性,区块链的交易可能会很慢,尤其是与现代的信用卡交易相比。相比之下,比特币交易可能需要 5 个小时才能完成,这使得使用加密货币支付晚餐的可能性非常小。此外,随着规模的增长,所有这些区块链变得越来越复杂,难以置信地笨拙,最终将使它们变得更慢。
它为常见问题提供了许多可能的解决方案,加强了我们的金融安全,保护了我们的数字身份;然而,这项技术不是万灵药,它还没有很好地融入我们的生活,这就产生了一些问题。
其次,缺乏监管创造了一个危险的环境。由于监管不力,区块链是骗子和市场操纵者的温床。例如,一种非常有前景(乍一看)的加密货币 Oncecoin ,它承诺其投资者成为“下一个比特币”,结果却是一个聪明的庞氏骗局,夺走了数百万人的钱。
随着区块链的疯狂,识别欺诈变得非常困难,即使你决定坚持使用成熟的硬币(如比特币或以太坊),也不能保证你的钱是安全的。交易所网站或你的在线钱包(你存放硬币的地方)被黑的几率非常高。相信我,我知道我在说什么——我的钱包被黑过一次;我的钱不知去了哪里,所有这些“高度安全的钥匙”都没有帮助(不要搞错,我说的主要是这些存储的脆弱性,而不是区块链本身)。另外,政府可能会因为一些不正当的行为关闭你使用的平台,或者交易所可能会“意外丢失”你的硬币。而且不要以为你能在这里得到公正——一切都是匿名的,所以无处可去。
如果你认为那些事情真的不能被称为问题,这里是真正导致一个死胡同。如您所知,成为区块链的一部分意味着存储系统中每个节点发生的所有交易,这导致需要保存的信息量不断增加,在某些情况下,还需要重新处理和重新记录。因此,要成为系统的一部分,每个新节点都必须获得事务的完整副本,这可能需要相当长的时间,大大降低了速度。此外,对于新交易的发生,你可能不得不考虑优先处理一些交易,从而为滥用你的系统开辟新的途径,因为你鼓励只处理有价值的数据以获得更大的回报,而完全忽略另一个有用的数据。
结论
据预测,区块链将影响我们日常生活的几乎所有方面。随着比特币的价格在 2017 年达到创纪录的 19783.21 美元,可能没有比区块链及其加密货币更被炒作的投资机会了。私营公司和公众越来越意识到它的优势,而围绕这项技术的大多数担忧却被忽视或反驳。谁知道呢,也许我今天解释的问题对明天的区块链不再适用。
它为常见问题提供了许多可能的解决方案,加强了我们的金融安全,保护了我们的数字身份;然而,这项技术不是万灵药,它还没有很好地融入我们的生活,这就产生了一些问题。不友好的界面、复杂的加密特性和钱包安全性是该行业要成为核心经济建设者必须克服的三个主要陷阱。
考虑到这一点,商界看起来更像是区块链仙境中的爱丽丝——发生了很多事情,但不清楚具体发生了什么,以及会导致什么。但是,你知道吗,如果你愿意冒险,你绝对应该追随苹果、IBM 和美国银行等世界领先企业,因为区块链很有可能会以这样或那样的方式影响你的业务。唯一的问题是什么时候。
为赶时间的人准备的 Matplotlib 指南
“person working on MacBook Pro” by rawpixel on Unsplash
Matplotlib 是最流行的二维图形库,但有时很难让你的图形看起来恰到好处。
如何更改图例上的标签名称?我如何设置刻度线?如何将刻度改为对数?如何向我的绘图添加注释和箭头?如何在绘图中添加网格线?
本文是关于如何自定义 Matplotlib 绘图的常见问题和答案的汇编。这是快速 Matplotlib 绘图的一个很好的备忘单,而不是 Matplotlib 库的介绍。如果您不熟悉这个库,请在这里查看文档。本文涵盖的主题包括地块和地块属性、轴、图例、注释和地块保存。从今天开始编写生产质量的图形!
开始提示
首先,确保导入 matplotlib。
import matplotlib.pyplot as plt
在 Jupyter Notebook 中,您可以在下面包含这一行,这样您就不必每次想要制作一个情节时都调用plt.show()
。
%matplotlib inline
另一个方便的提示是,如果你不想让这个烦人的消息出现<matplotlib.collections.PathCollection at 0x1182bc710>
,只需在你的代码行中添加一个分号,如下图所示。
之前:
之后:
剧情和支线剧情
问:我如何增加我身材的尺寸?
很多时候,默认大小太小。您可以添加参数 figsize,并以英寸为单位指定宽度和高度,如下所示。
plt.figure(figsize=(20,10))
问:什么是支线剧情?我如何创建和浏览支线剧情?
子图是存在于单个图形中的多组较小的轴。下面是一个 2 x 2 形式的四个支线剧情的例子。
这些支线剧情是用下面的代码创建的。我们调用plt.subplot
并指定三个号码。它们指的是行数、列数和你想要激活的子情节数。
for i in range (1, 5):
plt.subplot(2, 2, i)
plt.text(0.5,0.5, str((2, 2, i)), ha=’center’, fontsize = 10)
plt.tight_layout()
在上面的支线剧情中,剧情中的文字是对这三个数字的引用。子情节编号的排序是从左上角开始的,从数字 1 开始。例如,左上图是 1 号支线剧情,右上图是 2 号支线剧情,左下图是 3 号支线剧情,右下图是 4 号支线剧情。
请注意,您必须专门调用plt.subplot(2, 2, 1)
来激活该支线剧情。
问:我的支线剧情安排看起来不太好。我如何修理它?
这是一个你的支线剧情被挤压的例子。我们可以通过调用plt.tight_layout()
来修复它,它会清理支线剧情之间的填充,以获得更清晰的外观。
在之前
在之后
问:。如何在绘图中添加网格线?
plt.grid(True)
样式和属性
问:我如何改变我的线条颜色/宽度/样式?
您可以传入参数 color、linewidth 和 linestyle。
plt.plot(x, y, color = ‘green’ , linewidth = 2, linestyle = “-”)
以下是您可以设定的一些线型选项。
Photo from https://python-graph-gallery.com/121-line-chart-customization/
问:如何更改我的标记样式或颜色?
您可以像下面这样传入参数标记和颜色。
plt.scatter(x, y, marker = ‘o’, color = ‘red’)
这里有一些标记选项,您可以根据自己的喜好设定。
问:我如何改变线条的透明度?
将 alpha 参数传入您的绘图。Alpha 可以设置为 0 到 1,其中 0 表示完全透明,1 表示不透明。
plt.plot(x, y, alpha = 0.1)
下图显示了透明度在 alpha 级别为 0.9、0.5 和 0.1 时的样子
神话;传奇
问:我如何给我的剧情添加一个传说?
如果图例没有自动出现在您的绘图上,您可以使用以下代码来显示图例。
plt.legend()
问:我如何改变我的图例出现的位置?
您可以将以下选项传递给loc
参数:右上、左上、左下、右下、右下、左中、右中、下中、上中、居中。
plt.legend(loc = ‘lower right’);
问:如何更改图例上的标签名称?
选项 1:
假设您有十个图例项,您只想更改第一个图例项的标签。将图例保存到变量 L 后,可以用“L.get_texts()[0]”
调用图例的第一项,手动将文本设置成你想要的。在下面的例子中,我将图例设置为“123 行”。
L = plt.legend()
L.get_texts()[0].set_text('line123')
选项 2:
或者,您可以创建一个标签名称列表,并将图例标签设置为与您创建的列表相同。
mylabels = ['happy', 'sad', 'nervous', 'angry', 'neutral']
plt.legend(labels = my_labels)
问:我如何改变我的图例的大小?
要设置特定绘图的图例大小,可以传入 fontsize 参数。
plt.legend(fontsize = 10);
或者,不使用数字,您可以这样做。
plt.legend(fontsize = 'x-large');
轴线
问:如何命名我的 x 轴和 y 轴标签,如何更改字体大小?
根据您想要使用的轴,您可以调用“ylabel”或“xlabel ”,如下所示。第一项是轴的名称。要设置字体的大小,插入 fontsize 参数,如下所示。
plt.ylabel('Income', fontsize = 15) #for y label
plt.xlabel('Age', fontsize = 15) #for x label
问:如何设置刻度线?
第一个参数是要设置刻度线的位置,第二个参数是刻度线旁边的标签。
plt.yticks([0,2,4,6,7,10], [“0”, “2B”, "4B”, “8B”, “10B”])
plt.xticks([0,1,2,3,4,5], [“0”, “1oz”, "2oz”, “3oz”, “4oz”])
问:我如何设置坐标轴的范围?
plt.ylim(-1.0,1.0) #for y axis
plt.xlim(0, 50) #for x axis
问:如何将刻度改为对数?
plt.yscale(“log”) #for y axis
plt.xsclae("log") #for x axis
附注
问:如何给我的剧情添加注释和箭头?
我们可以创建注释并指定坐标来注释到xy
参数。xytext
定义标签的坐标。如果我们也想要箭头,我们需要使用arrowprops
来显示箭头。
plt.annotate(‘sentosa’, xy = (5.0, 3.5), xytext(4.25, 4.0), arrowprops={'color': 'red'})
保存绘图
现在你已经有了自己喜欢的定制剧情,那就保存吧!我把我的地块叫做“地块 1”,但是给你的地块起一个更独特的名字!这将把绘图保存到您的工作目录中。
plt.savefig('plot1.jpg')
最后一点
如果你的 Jupyter 笔记本上有大量的二维图形,你的笔记本会变得很慢。这发生在我参与的一个项目中。如果您将鼠标悬停在图形的左侧,将会出现如下所示的灰色框。通过双击那个灰框,我可以隐藏我的情节,这样 Jupyter 笔记本就可以正常运行了。这也有助于滚动。
希望你喜欢这个 Matplotlib 概述。不可能涵盖大规模 Matplotlib 库中的所有内容,但是如果您认为本文中应该包含其他 Matplotlib 特性,请告诉我。
期待我的下一篇关于在 Matplotlib 中制作动画的文章!