TowardsDataScience-博客中文翻译-2016-2018-十七-
TowardsDataScience 博客中文翻译 2016~2018(十七)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
使用 Keras 开始深度学习
原文:https://towardsdatascience.com/get-started-with-deep-learning-using-keras-a45ee421f3ef?source=collection_archive---------7-----------------------
深度学习处于人工智能革命的最前沿,这是有充分理由的——自然语言处理、图像识别,甚至计算机围棋方面令人难以置信的进步,都要归功于深度神经网络的帮助。
Alexa in the Amazon Echo uses deep learning to understand human language. Andres Urena on Unsplash
由于大多数神经网络必须完成的任务的复杂性,大多数人会认为很难建立一个神经网络。是的,也许 5 年前那是完全正确的,你必须从头开始建立你的神经网络。但是今天,有了像 Keras 这样的开源框架,开始变得非常简单。以下是方法。(这里是完整的脚本如果你想跳过前面!)
问题:用人口统计学变量预测薪水
首先,我们先找一个玩具问题入手。下面是我找到的一个:1994 年美国人口普查数据库的美国成年人收入数据。我们将尝试使用几个完全连接的神经元层来预测人口普查中给定人员的工资。
老实说,深度神经网络对于这项任务来说可能有点大材小用。传统的数据科学技术,如逻辑回归,非常适合这种情况,并且非常容易解释。尽管如此,这仍然是一个开始使用 Keras 的好方法。
Markus Spiske on Unsplash
进口
为了遵循这段代码,首先安装 Python 3 。完成后,打开您的操作系统终端,并键入以下内容:
pip install **pandas**
然后在熊猫之后安装以下包: sklearn 、 tensorflow ,最后是 keras 。
首先,我们将从我们的进口开始。该脚本需要:
- 熊猫用于数据操作、
- numpy 对于一些快速操作,
- sklearn 对于数据缩放和性能测量,
- 最后, keras ,我们的深度学习框架。
加载数据集
我们的数据集包含各种变量,如员工的年龄、教育水平、受教育年限、婚姻状况、职称等。该数据集中包含的最后一个值是工资范围,低于或高于$50,000。我们将使用前面的变量来预测这个目标。
准备数据集
下一步是为 Keras 准备数据集。我们需要做到以下几点:
- 平衡各阶级。不平衡的班级会干扰训练。
- 将分类变量(例如职业)转换成一个热点编码变量。基本上是为每个标签创建一个值为 0 或 1 的新列。
- 提取训练和测试数据集的 X (变量)和 y (目标)值。
- 标度变量。
喀拉斯的模型
现在是精彩的部分!构建 Keras 模型。在 Keras 中有两个接口来构建模型,顺序模型 API 和函数 API。今天,我们将使用顺序模型 API,因为它更容易理解和构建。
这是我们需要做的。
- 首先,我们将设置一个模型检查点对象,以允许我们在训练过程中保存最佳结果。
- 然后,我们将创建一个序列模型对象,我们将向其添加不同的神经层。
- 我们将需要选择适当的激活函数、优化器和损失函数来构建我们的二元分类模型(我们试图预测一个变量的值为 0 或 1)。
- 最后,我们将训练我们的网络。
评估模型的性能
我们表现如何?让我们来衡量我们的模型的性能!我们将测量精度,一个精确分类量的值。
- 我们将需要加载我们在模型训练期间保存的权重,并且用这些权重编译模型。
- 使用模型预测测试数据集中的值。
- 将预测的工资与测试数据集中的实际工资进行比较。
最终,该模型对于低于 50K 的工资获得了大约 87%的精度,对于高于 50K 的工资获得了大约 72%的精度。
对于一个没有任何特征工程的模型来说还不错…
GithubGist 上的提供了整个脚本。
我希望你喜欢我的教程!
艾蒂安
从闪亮应用的反应例子开始。
原文:https://towardsdatascience.com/get-started-with-examples-of-reactivity-in-in-shiny-apps-db409079dd11?source=collection_archive---------3-----------------------
Photo Credit : Pixabay
介绍
让闪亮的应用程序具有交互性的一个因素是反应能力。用最简单的术语来说,反应性/反应性编程是程序根据一组给定的用户输入计算输出的能力。一个闪亮的应用程序处理反应的能力在用户和现有信息之间建立了双向交流。
反应性适用于执行计算、数据操作、收集用户信息等情况。
作为一个开始构建闪亮应用的初学者,掌握处理反应的基本知识将有助于你探索闪亮应用的不同用例。
我们开始吧
直到下面的错误消息,人们才会想到反应性的概念。
error message
当电抗组件被放置在非电抗函数中时,会出现此错误。该应用程序将不会加载,并将解析此错误。让我们看看什么是反应函数,它有什么作用。
闪亮应用的反应组件
一个闪亮的应用程序有三个主要的反应组件:
无功输入
反应式输入被定义为用户通过浏览器界面提供的输入。例如,当用户填写表单、选择项目或单击按钮时。这些动作将触发从无功输入设置的值。
Text input and Add button are reactive inputs
无功输出
反应输出被定义为浏览器界面中程序提供的输出。例如图表、地图、曲线图或数值表。
Table of values as a reactive output
反应式表达
电抗表达式被定义为将电抗输入转换为电抗输出的表达式。它们在发送无功输出之前执行计算。这些还会屏蔽慢速操作,如从服务器读取数据、在其他场景中进行网络调用。我们将在我们的例子中看到一个。
例子
让我们从一个简单的例子开始,将两个整数相加,并在一个闪亮的应用程序中返回它们的和。
用户界面
titlePanel("Sum of two integers"),
#number input form
sidebarLayout(
sidebarPanel(
textInput("one", "First Integer"),
textInput("two", "Second Integer"),
actionButton("add", "Add")
),
# Show result
mainPanel(
textOutput("sum")
)
计算机网络服务器
server <- function(input,output,session) {#observe the add click and perform a reactive expression
observeEvent( input$add,{
x <- as.numeric(input$one)
y <- as.numeric(input$two)
#reactive expression
n <- x+y
output$sum <- renderPrint(n)
}
)
结果
Example
演示
现在,让我们在处理反应性的同时,构建一些稍微复杂的东西。
用户界面
fields <- c("name","age","height","weight")
ui <- fluidPage(
# Application title
titlePanel("Health card"),
# Sidebar with reactive inputs
sidebarLayout(
sidebarPanel(
textInput("name","Your Name"),
selectInput("age","Age bracket",c("18-25","25-45","above 45")),
textInput("weight","Please enter your weight in kg"),
textInput("height","Please enter your height in cm"),
actionButton("save","Add")
),
# a table of reactive outputs
mainPanel(
mainPanel(
DT::dataTableOutput("responses", width = 500), tags$hr()
)
)
)
)
计算机网络服务器
# Define server logic
server <- function(input, output,session) { #create a data frame called responses
saveData <- function(data) {
data <- as.data.frame(t(data))
if (exists("responses")) {
responses <<- rbind(responses, data)
} else {
responses <<- data
}
}
loadData <- function() {
if (exists("responses")) {
responses
}
}
# Whenever a field is filled, aggregate all form data
#formData is a reactive function formData <- reactive({
data <- sapply(fields, function(x) input[[x]])
data
})
# When the Save button is clicked, save the form data
observeEvent(input$save, {
saveData(formData())
})
# Show the previous responses
# (update with current response when save is clicked)
output$responses <- DT::renderDataTable({
input$save
loadData()
})
}
结果
When project is run.
项目演示:【https://rstudio.cloud/project/22236
这就对了。既然你已经掌握了基本知识,请继续尝试。欢迎分享、向我提问或在 twitter 上给出反馈 @lornamariak
使用 OpenCL 的 GPU 图像处理
原文:https://towardsdatascience.com/get-started-with-gpu-image-processing-15e34b787480?source=collection_archive---------2-----------------------
使用 Python 和 OpenCL 以不到 120 行代码实现两种图像处理方法
Large speed-ups can be achieved by using GPUs instead of CPUs for certain tasks. (Image: Joseph Greve)
除了图形处理单元(GPU)的明显用例,即渲染 3D 对象,还可以使用 OpenCL 或 CUDA 等框架执行通用计算。一个著名的用例是比特币挖矿。我们将看看另一个有趣的用例:图像处理。在讨论了 GPU 编程的基础之后,我们使用 Python 和 OpenCL 在不到 120 行代码中实现了膨胀和腐蚀。
为什么图像处理非常适合 GPU?
第一个原因
许多图像处理操作在图像中逐个像素地迭代,使用当前像素值进行一些计算,最后将每个计算值写入输出图像。图 1 示出了作为例子的灰度值反转操作。我们单独反转每个像素的灰度值。对于每个像素,这显然可以同时(并行)完成,因为输出值不相互依赖。
Fig. 1: Inverting the color of an image. The output pixel at some location can be computed by only taking the input pixel at the same location into account. Some corresponding pixels are shown by colored lines.
第二个原因
在进行图像处理时,我们需要快速访问像素值。GPU 是为图形目的而设计的,其中之一是纹理,因此访问和操作像素的硬件得到了很好的优化。图 2 显示了 3D 程序中纹理通常的用途。
Fig. 2: Textures are often used to make models (in this case a sphere) make look more realistic.
膨胀和侵蚀
让我们简单看一下我们实现的图像处理方法。这两种运算都属于形态学运算的范畴。掩模(通常称为结构化元素)在输入图像中逐像素移动。对于每个位置,掩膜下的最大(用于膨胀)或最小(用于腐蚀)像素值被写入输出图像。图 3 示出了如何计算膨胀的图示。
Fig. 3: The 3×3 mask is shifted through the image. For dilation, the maximum pixel value under the mask is taken as the resulting value. Two locations of the mask are shown, one resulting in a black pixel (0), the other one resulting in a white pixel (255).
为了了解这两种操作,请看图 4。此外,图 5 示出了灰度值图像及其腐蚀版本。
Fig. 4: Top: input image. Bottom: output images for dilation and erosion.
Fig. 5: This example shows how to increase the pen width using multiple erosions.
利用 GPU 的并行性
正如你所看到的,当应用膨胀或腐蚀时,蒙版在图像中移动。在每个位置,应用相同的基本操作(通过掩模选择像素组,输出最大或最小像素值)。此外,输出像素不相互依赖。
这意味着将基本操作实现为输入图像上的一个函数,并为位置添加一个参数。然后,我们同时(并行)对所有可能的位置(x 在 0 和 width-1 之间,y 在 0 和 height-1 之间)调用该函数,以获得输出图像。
让我们先做一个伪代码实现:要么我们调用 synchronous_work(image)并遍历所有(x,y)位置,在每个迭代步骤应用相同的操作。或者我们调用 parallel_work(image,x,y ),并为所有位置并行调用其附加位置参数(例如,通过为每个实例启动一个线程)。图 6 示出了如何并行计算输出像素值。
同步实施:
**synchronous_work**(image):
for all (x, y) locations in image:
1\. select pixels from 3×3 neighborhood of (x, y)
2\. take maximum (or minimum)
3\. write this value to output image at (x, y)in main: run one instance of **synchronous_work**(image)
并行实现:
**parallel_work**(image, x, y):
1\. select pixels from 3×3 neighborhood of (x, y)
2\. take maximum (or minimum)
3\. write this value to output image at (x, y)in main: run one instance of **parallel_work**(image, x, y) for each (x, y) location in the image at the same time
Fig. 6: Three mask locations are shown. The resulting pixel values do not depend on each other and can therefore be computed at the same time.
OpenCL 实施
让我们移植我们的伪代码,使它运行在真正的 GPU 上:我们将使用开放计算语言(OpenCL)框架。图 7 说明了我们的实现所做的事情:我们首先将输入图像复制到 GPU,编译内核(GPU 程序),对所有像素位置并行执行,最后从 GPU 复制回结果图像。
我们需要为主机和设备分别实现一个程序:
- CPU(“主机”):一个 Python 程序,它设置 OpenCL,发布 CPU 和 GPU 之间的数据传输,负责文件处理等等
- GPU(“设备”):一个 OpenCL 内核,它使用一种类似 C 的语言进行实际的图像处理
Fig. 7: A rough overview of what our OpenCL implementation does.
入门指南
- OpenCL 已安装并运行
- pyopencl 已安装并正常工作
- 从 GitHub 克隆存储库
CPU 程序(主机)
CPU 或主机代码的大部分可以被视为样板代码。大多数时候,设置主要的 OpenCL 数据结构都是以同样的方式完成的。此外,准备输入和输出数据遵循一定的模式,同样适用于 GPU 程序编译,执行和数据传输。您应该能够使用提供的代码实现其他算法,如边缘检测或亮度调整,而无需接触 CPU 程序。让我们快速浏览一下主要步骤。括号中的数字与代码中的数字相对应,以便于导航。
(1)首先,必须完成 OpenCL 初始化:
- 选择平台:一个平台对应一个安装的驱动程序,例如 AMD
- 从所选平台选择 GPU 设备:您可能安装了多个 GPU。我们只取 GPU 列表中的第一个条目
- 创建一个 cl。上下文对象:该对象将运行 GPU 程序的所有相关信息(选定的设备、数据等)联系在一起
- 创建 cl 类型的命令队列对象。CommandQueue:这个对象是一个 FIFO 队列,它允许我们发出命令向/从 GPU 发送/接收数据,还允许我们在 GPU 上执行程序
(2)准备资料:
- 将图像从文件读入数字图像
- 分配与占位符大小相同的输出数字图像。我们稍后将使用来自 GPU 的结果来填充它
- 创建 cl 类型的缓冲区。保存 OpenCL 图像数据的图像
(3)准备 GPU 程序(图 8 示出了表示 GPU 程序的对象层次):
- 从文件中读取 GPU 程序的源代码并创建 cl。从中选择程序对象
- 用 cl 编译程序。Program.build 方法
- 创建 cl 类型的内核对象。代表我们的 GPU 程序的入口点的内核
- 设置内核函数的参数:这是我们的 CPU 程序中的数据和 GPU 程序中访问的数据之间的连接。我们传递输入和输出图像缓冲区以及一个整数,该整数表示我们是要应用膨胀(=0)还是腐蚀(=1)。我们使用 cl。方法,并指定内核参数的索引(例如,0 对应于我们的内核函数的参数列表中的第一个参数)和 CPU 数据
Fig. 8: OpenCL objects representing GPU program and its arguments.
(4)执行 GPU 程序并传输数据:
- 使用 cl.enqueue_copy 发出一个命令,将输入图像复制到输入缓冲区
- 执行 GPU 程序(内核):我们实现了像素级的形态学操作,因此我们将为每个(x,y)位置执行一个内核实例。这种数据和内核的结合称为工作项。我们需要处理整个图像的工作项的数量等于宽度*高度。我们将内核和图像大小传递给 cl.enqueue_nd_range_kernel 函数来执行工作项
- 当 GPU 程序完成其工作时,我们使用 cl.enqueue_copy 将数据从输出缓冲区复制回输出图像(并等待直到该操作完成,以将填充的输出图像返回到调用 Python 函数)
总结:我们设置 OpenCL,准备输入和输出图像缓冲区,将输入图像复制到 GPU,在每个图像位置并行应用 GPU 程序,最后将结果读回 CPU 程序。
GPU 程序(设备上运行的内核)
OpenCL GPU 程序是用类似 c 的语言写的,入口点叫内核函数,我们这里是函数 morphOpKernel(…)。它的参数对应于我们在 CPU 程序中设置的参数。在内核中,有必要访问工作项 id。您要记住:工作项是代码(内核)和数据(在我们的例子中是图像位置)的组合。当在 CPU 程序中调用 cl.enqueue_nd_range_kernel 时,我们指定图像中的每个(x,y)位置需要一个工作项。我们通过使用函数 get_global_id 来访问工作项 id。因为我们有两个维度(因为图像有两个维度),所以我们得到两个维度的 id。第一个 ID 对应于 x,第二个 ID 对应于 y。现在我们知道了像素位置,我们可以读取 3×3 邻域中的像素值,计算输出值,并最终将其写入输出图像中的相同位置。
(1)内核:
- 执行 GPU 程序时的入口点(也可能有内核调用的子函数)
- 我们将一个只读的输入图像和一个只写的输出图像传递给内核。此外,我们传递一个整数,它告诉我们是否必须应用膨胀(=0)或腐蚀(=1)
(2)全局 id 标识工作项,在我们的例子中对应于 x 和 y 坐标。
(3)结构化元素(掩模)由两个嵌套循环实现,这两个嵌套循环表示围绕中心像素的 3×3 正方形邻域。
(4a)使用 read_imagef 函数访问像素数据,该函数返回 4 个浮点数的向量。对于灰度值图像,我们只需要可以用 s0 索引的第一个分量。它是介于 0 和 1 之间的浮点值,表示像素的灰度值。我们将图像、像素位置和一个采样器传递给这个函数。采样器允许在像素之间进行插值,但在我们的例子中,采样器只不过是返回给定位置的像素值。
(4b)采样器由选项组合定义。在我们的例子中,我们希望采样器使用非标准化的坐标(从 0 到 width-1,而不是从 0 到 1)。此外,我们禁用像素之间的插值(因为我们不在像素位置之间采样),并且我们还定义了当我们访问图像外部的位置时会发生什么。
(5)根据操作,我们寻找 3×3 邻域内的最大/最小像素值。
(6)将结果写入输出图像。同样,我们指定图像和位置。我们必须传递 4 个浮点数的向量,但是我们只需要填充第一个条目,因为我们的图像是灰度值的。
测试一下
执行 python main.py ,将这两个操作应用于图 9 所示的输入图像。执行后,目录中出现两个文件:dilate.png 和 erode.png,代表膨胀和腐蚀的结果。
Fig. 9: This image is used to test the implementation.
幕后发生了什么?
我们为每个像素创建一个工作项,如图 10 所示。GPU 为每个要并行处理的工作项启动某种硬件线程。当然,同时活动的线程数量受到硬件的限制。一个有趣的特性是,这些线程并不是完全独立的:有多组线程同步执行,对不同的数据实例应用相同的操作(SIMD)。因此,内核中的分支(if-else,switch-case,while,for)可能会降低执行速度:GPU 必须为所有在 lock-step 中执行的线程处理两个分支,即使只有一个线程发生分歧。
Fig. 10: Work-items are instances of the kernel created for all image-locations. Here, three work-items are shown.
GPU 上有不同类型的并行性(如使用向量类型、分区数据和并行应用操作到每个数据元素等)。我们只使用了其中一种类型,在像素级拆分数据,并单独计算每个像素位置的输出。
如果仔细观察 GPU 程序,您可能会注意到变量有不同的地址空间:输入和输出图像对所有工作项都是全局可见的,而在函数中用作暂存区的变量仅对工作项实例可见。这些地址空间对应于底层硬件。举个例子:图像由纹理单元及其采样器处理。这些单元也用于游戏和类似应用中的 3D 物体纹理。
进一步阅读
如果你想对 GPU 编程和 OpenCL 有更深入的了解,没有办法可以绕过阅读这方面的好书。有许多用例可以在 GPU 上高效地计算,而不仅仅是像图像处理和比特币挖掘这样的著名用例。
我推荐这本书[1]来帮助你开始使用 OpenCL。这本书从像 4D 矩阵向量乘法这样的简单程序开始,以像 FFT 或双调排序这样的复杂主题结束。
此外,这本书[2]也是一本很好的读物,但是它已经期望获得一些 OpenCL 的经验。
根据您的 GPU,您可能会找到有关其 OpenCL 实现的信息,以更好地了解 OpenCL 如何转换为硬件,例如,请参见 AMD 的[3]。
Khronos 提供了规范[4]和一个非常有用的 API 参考卡[5]。
[1] Scarpino — OpenCL 在行动
[2] Gaster 等人— OpenCL 的异构计算
[3] AMD 加速并行处理— OpenCL 编程指南
[4]Khronos—OpenCL 规范
[5] Khronos — OpenCL API 参考卡
自然语言处理入门
原文:https://towardsdatascience.com/get-started-with-natural-language-processing-a-multi-label-text-classification-example-in-r-part-bb8f064be5e4?source=collection_archive---------8-----------------------
R 中的多标签文本分类示例(第 1 部分)
文本分类是自然语言处理的一种。 NLP 可以简单地定义为教授一种算法,像人类一样阅读和分析人类(自然)语言,但速度更快,更准确,并且基于大量数据。
如果你是一个有抱负的数据科学家或分析师,你必须知道如何建立一个文本分类模型。从邮件分类到信息发现,实际应用层出不穷。多标签文本分类简单地说就是将文本数据分成两个以上的类别。初学的数据分析师、没有 NLP 经验的数据分析师或其他好奇的数据科学家会发现这个博客很有趣。
你需要对 R 和 RStudio 有所了解。我将使用 R 中的结构化主题模型(STM)包,这是一个使用文档级协变量的无监督聚类包。我已经用 STM 建模了许多文本分类器,它用最少的训练就给出了极好的结果。你可以在这里阅读更多关于 STM 的内容。
让我们开始编码吧!
第一步:获取数据。对于这个例子,我将使用。txt 文档,这些是我使用 Python 的 BeautifulSoup 从开源中搜集的新闻文章(是的,在搜集数据时,我更喜欢 Python)。
如果你不知道怎么做,不要担心!您可以在线复制粘贴自由文本数据,并将其另存为。txt 文件(确保阅读版权。只使用免费使用的 web 数据)。这是我的数据的样子:
我保存了我所有的。txt 文件放在一个名为 STM_trainingdata,的文件夹里,这个文件夹在我的当前目录下。
第二步:在 RStudio 中摄取数据。一个经验法则是为你经常重复的任务编写函数。为了将我的数据接收到 RStudio 中,我编写了一个简单的函数。根据您正在处理的项目和所需的输出,您的函数可以有不同的输入/输出。这是我的样子:
现在,调用如下所示的函数,您应该会得到“成功!”:
您的数据在 RStudio 中应该是这样的:
现在,每次我需要在我的文件夹中添加/修改训练数据时,我在 RStudio 中更新我的数据变量所要做的就是调用 ReadTxt() 。
第三步:预处理你的数据。数据预处理是任何机器学习过程中最重要的步骤之一。不良清理和/或结构化的数据将产生不良结果。在数据浏览期间,您可以使用各种统计和可视化方法来确保数据准备就绪。
因为我们的数据样本非常小,所以我编写了一个基本函数来清理它。你可以在函数里面读到具体的清洗步骤。此外,正如您将在第 2 部分中看到的,STM 提供了额外的数据修剪选项;所以我在这里只关注基础知识。
自然语言处理中一个非常重要的步骤是去除停用词。停用词是在你的语料库中常见的词,因此在确定文本中讨论的主题时没有权重(它们只是你的数据中的噪音)。一些常见的停用词有冠词、代词、感叹词等。
下面的功能是非常可定制的。根据您的训练数据,您可能需要删除更多的停用字词。你可以将它们直接添加到 rem 向量中。例如,您可能也不需要删除 URL。
编写函数时,最好使用描述性名称,并添加一些关于输入、输出和过程的解释。
接下来,按如下方式调用该函数:
您的干净数据应该如下所示:
此时,RStudio 的全局环境中应该有 4 个项目。见下文:
这就是第 1 部分!在第 2 部分,我们将进入有趣的部分:训练和测试我们的 STM 模型以及一些可视化。敬请期待!
如果你喜欢这个帖子,请为它鼓掌,并随时在LinkedIn和 Twitter上添加我!
坚持为熊猫做贡献
原文:https://towardsdatascience.com/get-stuck-in-with-contributing-to-pandas-fea87d2ac99?source=collection_archive---------9-----------------------
Photo by Polina Razorilova on Unsplash
如果这能引起任何数据人员的共鸣,请举手。你的老板给你一个数据集,让你找一些有趣的东西。你拿起数据,把它粘在笔记本上。现在怎么办?很可能你的手指已经下意识地打出了:
import pandas as pd
在这篇文章中,我们不打算浏览熊猫是什么或如何使用它的本质,你可能比我更了解图书馆!相反,我将专注于通过文档回馈数据分析社区。
在参加 PyData London 2018 时,我遇到了一场熊猫冲刺会议。正是在这里,我了解到开源包的受欢迎程度已经超过了贡献的程度,尤其是它的 API 文档。
类似于的群体智慧现象,这表明最好从一个群体中获取意见,而不是把个人的话当作真理——开源允许专家和业余爱好者在一个项目上合作,这可以使整个社区受益。
直到这个冲刺阶段,我还没有真正为开源做出贡献——老实说,我从来没有真正相信我的编码能力达到了标准。然而,我是一个坚持良好文档化代码的人,所以这个 sprint 关注文档的事实给了我一些非常需要的信心。
因此,如果我的故事引起了你的共鸣,而你从未为开源项目做出过贡献,但想这样做,请继续阅读,我将指导你完成这一过程。
让我们为熊猫做贡献
安装
我可以在这里通过设置步骤,但没有必要重新发明轮子…查看超级简洁的熊猫冲刺设置说明这里。
现在一切都准备好了🤞,让我解释一下好的文档是什么样子的,以及我们为什么需要它。
文件 101
文档是一组关于特定函数、方法、类或模块使用的简明信息。没有它,用户要么会误解工具的目的,要么会浪费时间去理解源代码。基本上,文档旨在减少理解如何使用工具所需的时间,以便用户可以继续他们的工作。
那么我包括哪些信息呢?
很高兴你问了这个问题,这里有一个包含在你的文档中的 7 个部分的列表…你不会相信第 5 个!
第 1 部分-简短总结
这是用户看到的第一个东西,所以要让它有冲击力!描述函数本质的简短有力的句子。
第 2 部分-扩展总结
不是所有的事情都可以用一句话来描述,没关系。本节允许您更深入地描述该函数的细微差别。
第 3 节-参数
在这里,您为用户提供了该功能所需的一组输入。这些必须包括每个参数的类型和描述。
第 4 节-退货
如果函数返回一个值或者改变一个状态,这必须引起用户的注意,因为误解可能会对下游产生严重的后果。请务必在此记录。
第 5 节——参见
在本节中,文档试图将用户的注意力吸引到其他相关功能上。与其他功能相关联可以给用户更直观的理解。
第 6 节-注释
这是一个可选部分,在“扩展总结”中没有解释的任何细节都可以在这里讨论。
第 7 节-示例
人们喜欢在实践中学习,没有比在真实场景中使用概念更好的方法来具体理解概念。你应该包括一些如何使用该功能的例子。
文档走查
在冲刺的那一天,每个参与者都有一个功能或方法来记录——我被指定为熊猫。Series.str.contains 。就像第 7 节一样,我会通过这个例子告诉你。
步骤 1-初始概述
查看文档的当前状态。创建一个潜在改进领域的清单,并在每一项都被勾掉后得到急需的多巴胺修复。
正如您所看到的,上面讨论的一些部分不存在,在参数类型和一些格式问题上有一些差异。总体来说,还不算太寒酸。
第 2 步-试用该功能
在你写一个函数之前,你必须理解这个函数,这很重要。想出尽可能多的理由,为什么你会想在日常编程中使用它,然后实现一些基本的用例。这些可在第 7 节中作为示例使用。您还可以通过编写几个单元测试来进一步阐明您对该函数的理解。
第三步——还有谁在同一条船上?
请记住,我们这样做的原因是为了帮助人们有效地理解代码。在 Google、Stack Overflow 或者 Github 上搜索该功能,看看之前有没有人出现过问题。如果类似的问题不断出现,针对这些问题修改文档以消除任何歧义。当搜索熊猫的问题时。Series.str.contains 我一直碰到涉及正则表达式的题。为了解决这个问题,我确保在相关的例子中包含一些这样的例子。
第四步——合规
不同的思想有不同的风格,一般来说,多样性是一件好事。然而,随着代码库的增长,一致性是至关重要的。对于 python,大多数库都试图遵循代码格式指南,pandas 遵循 PEP 257 。这包括从空白到不定式动词使用的所有指南。这听起来可能很迂腐,但是这些指导方针已经被修改和调整了近二十年,它们的存在是有原因的——所以使用它们吧!
幸运的是,pandas 的核心开发人员已经构建了一个脚本来检查您的代码是否符合他们的风格指南。偶尔运行一下并相应地修改代码是很方便的。
python scripts/validate_docstrings.py <insert-your-function-here>
你还应该运行著名的 python linter,flake8 来保持一切整洁。
git diff upstream/master -u -- "*.py" | flake8 --diff
一旦您觉得文档符合标准,请快速预览一下:
python make.py html — single pandas.Series.str.contains
好看吗?是时候发出拉取请求了。查看此页面以获得您的建议。
这个阶段包括你向核心开发者发布你的建议,如果他们喜欢你的建议,他们会在下一个版本中接受它。
还有一件事…核心开发人员会比你更了解好的文档,所以他们可能会对你的建议有一些意见。我的建议是不要把它放在心上,只是冲洗和重复,做修复和推动你的拉请求。
不要害怕公开你的错误,反馈是你的朋友。否则你永远不会从你的错误中吸取教训,或者更糟——养成一个坏习惯。请记住,核心开发人员迫切需要像您这样想要提供帮助的人!
所以在这里,在所有的荣耀中,检验我的改进版熊猫。Series.str.contains
你可以看到,我对该方法进行了清晰而简明的描述,添加了一个扩展的总结,整理了参数,整理了返回部分,并添加了大量典型用例。
如果这份美丽的文档激励你尝试为熊猫(或任何其他项目)做贡献,请在这里仔细阅读文档,尝试找出任何你认为可以改进的地方。如果您不确定要深入研究什么,可以使用以下脚本返回需要改进的文档列表:
python scripts/validate_docstrings.py
所以我们走吧!我希望这给了你一点信心,让你开始成为一名开源贡献者的旅程。感谢您的阅读,如果您有任何问题,请在下面的评论区留言。
我还要感谢马克·加西亚对熊猫文档冲刺的指导。
使用 Docker、Telegraf、Influxdb 和 Grafana 获取 5 分钟的系统指标
原文:https://towardsdatascience.com/get-system-metrics-for-5-min-with-docker-telegraf-influxdb-and-grafana-97cfd957f0ac?source=collection_archive---------2-----------------------
总之,这里有一个非常快速的指南,告诉你如何使用一系列现代技术,如 Grafana、Docker 和 Telegraf with Influxdb,为一台或多台服务器配置系统监控。
本文的主要目标是展示如何快速简单地从服务器获取系统指标,而无需花费大量时间来配置庞大而复杂的监控系统。尤其是如果您只需要管理少数几个 Web 服务器,而不是监控拥有数百台设备的大公司基础架构。
我们将使用 Docker 来快速部署我们的监控系统,这也将使我们能够自由地使用任何软件,并且保持我们的系统干净。话题性的,你也可以从这个角度看 Docker,作为一个跨平台的包系统。
此外,我们将使用 Tick 堆栈的一部分,即 Influxdb 库来存储我们的指标和 Telegraf,就像远程系统上的代理一样,对于漂亮的图形,我们将采用 Grafana。
图例:
服务器 1 —监控服务器
服务器 2、服务器 3 等—我们需要从中获取指标的服务器
在 server1 上,我们将准备我们的监控系统,为此我们需要一个安装了 Docker 和 Docker Compose 的 Linux。
如何获取并安装 Docker
首先为我们的项目创建一个文件夹,例如/opt/monitoring:
server1$ mkdir /opt/monitoring && cd /opt/monitoring
在目录中,我们需要用 Grafana 和 Influxdb 服务创建 docker-compose.yml 文件:
version: "2"
services:
grafana:
image: grafana/grafana
container_name: grafana
restart: always
ports:
- 3000:3000
networks:
- monitoring
volumes:
- grafana-volume:/var/lib/grafana influxdb:
image: influxdb
container_name: influxdb
restart: always
ports:
- 8086:8086
networks:
- monitoring
volumes:
- influxdb-volume:/var/lib/influxdbnetworks:
monitoring:volumes:
grafana-volume:
external: true
influxdb-volume:
external: true
如您所见,我们使用自己的 docker 网络来提供这些服务,包括名称监控和外部卷来存储数据和配置,我们使用外部卷来防止容器重启后的任何数据丢失。
实际上,为容器组使用自己的网络是一个很好的实践,便于逻辑分离属于同一项目的容器,也便于从 docker 引擎获得内置服务发现。
现在我们需要创建 Docker 网络和卷:
server1$ docker network create monitoring
server1$ docker volume create grafana-volume
server1$ docker volume create influxdb-volume
确保一切都创建得很好:
server1$ docker network ls
NETWORK ID NAME DRIVER SCOPE
8a744bc6ce04 bridge bridge local
a9fe3f026042 host host local
75c2b515def9 monitoring bridge local
c1a42ddaa998 none null local
server1$ docker volume ls
DRIVER VOLUME NAME
local 69c5364fab3baa7b1c9418ace9c91dfcf13e54f0adce247136d887e46a347baf
local grafana-volume
local influxdb-volume
如我们所见,网络和卷已创建完毕,现在我们需要准备 Influxdb 参数,为此,我们将使用一些环境变量来运行容器,以创建数据库和用户:
server1$ docker run --rm \
-e INFLUXDB_DB=telegraf -e INFLUXDB_ADMIN_ENABLED=true \
-e INFLUXDB_ADMIN_USER=admin \
-e INFLUXDB_ADMIN_PASSWORD=supersecretpassword \
-e INFLUXDB_USER=telegraf -e INFLUXDB_USER_PASSWORD=secretpassword \
-v influxdb-volume:/var/lib/influxdb \
influxdb /init-influxdb.sh
我们使用–RM 密钥运行此容器,这将仅创建配置并在之后删除容器。
所有准备工作都已完成,我们准备启动新的监控系统,使用 docker-compose,转到/opt/monitoring 目录并运行:
server1$ docker-compose up -d
Creating network "monitoring_monitoring" with the default driver
Creating grafana
Creating influxdb
server1$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8128b72bdf44 grafana/grafana "/run.sh" 23 seconds ago Up 20 seconds 0.0.0.0:3000->3000/tcp grafana
c00416d0d170 influxdb "/entrypoint.sh infl…" 23 seconds ago Up 21 seconds 0.0.0.0:8086->8086/tcp influxdb
好了,所有的容器都被创建并启动了,所以我们的监控系统准备好为传入的请求服务了。我们公开了几个端口,正如你在 docker-compose 文件中看到的,8086 HTTP API 端口用于 Influxdb 数据,3000 端口用于 Grafana web UI。
我们几乎完成了新的监控系统,使用 Docker 真是又快又简单。为了完全完成,我们只需要稍微配置 Grafana,为 Influxdb 创建一个仪表板和新的数据源。
为此,将在浏览器中访问我们的 server1 public_ip:3000(在我们的示例中为 192.168.0.1:3000 ),并使用以下命令首次登录 Grafana web UI:
登录:管理员
密码:admin
然后 Grafana 会要求您更改密码,之后您将进入:
选择 Add data source 菜单,告诉 Grafana 从哪里获取 Influxdb 数据:
在这里,我们需要选择 Type = InfluxDB,给出这个数据源的名称,然后使用我们的 InfluxDB 容器名称作为地址放置 URL。正如我之前所说,Docker 给了我们一个简单的服务发现。
好的,我们还需要为我们的数据库插入数据库名称和用户/密码,这些参数是通过之前运行 Influxdb 容器创建的。
单击保存和测试,查看您的数据源是否正常:
太好了,我们刚刚添加了我们的 influxdb 作为 Grafana 的数据源,为了节省时间,我们将准备一个包含最流行参数的仪表板,转到grafana.com并选择一个您喜欢的。举个例子:
复制数字 914,然后将其插入您的 grafana 导入菜单:
仅此而已,我们只需要在我们想要控制的系统上安装 telegraf,并将其配置为向 server1 上的 influxdb 发送数据。
您可以将 telegraf 作为软件包安装,或者编译最新版本并将其复制到远程服务器。
安装 Telegraf
更改 telegraf 配置并配置 influxdb 数据库参数。
还要启用你需要的插件。
*###############################################################################*
*# OUTPUT PLUGINS #*
*###############################################################################**# Configuration for sending metrics to InfluxDB*
[[outputs.influxdb]]
*## The full HTTP or UDP URL for your InfluxDB instance.#### Multiple URLs can be specified for a single cluster, only ONE of the*urls = ["http://server1_ip:8086"] *## The target database for metrics; will be created as needed.*
database = "telegraf" *## If true, no CREATE DATABASE queries will be sent. Set to true when using## Telegraf with a user without permissions to create databases or when the## database already exists.*
skip_database_creation = true *## Name of existing retention policy to write to. Empty string writes to## the default retention policy. Only takes effect when using HTTP.# retention_policy = ""* *## Write consistency (clusters only), can be: "any", "one", "quorum", "all".## Only takes effect when using HTTP.# write_consistency = "any"* *## Timeout for HTTP messages.*
timeout = "5s" *## HTTP Basic Auth*
username = "telegraf"
password = "secretpassword"
干得好:)现在,我们有了一个非常漂亮的仪表板,时间最短:
您可以在多台服务器上安装 Telegraf,也可以将系统指标发送到一个 InfluxDB base,然后您只需在 Grafana dashboard 中选择服务器名称即可查看它们。
还有一件重要的事情是关于在 InfluxDb 中保存数据的持续时间,默认情况下它设置为 7 天,所以如果您需要比这更长的时间,请执行到 influxdb 容器并手动更改保留策略。
嗯,我想现在我们在 5 分钟内就有了一个很好的监控系统:)
祝你好运。
获取和清理数据(JHU Coursera,课程 3)
原文:https://towardsdatascience.com/getting-and-cleaning-data-jhu-coursera-course-3-c3635747858b?source=collection_archive---------0-----------------------
Getting and Cleaning Data JHU Coursera Course 3 Review
数据科学专业的第三门课程“获取和清理数据”是一门基础课程。一如既往,测验和作业的代码位于我的 github 上。
第一周复习:阅读 Excel、XML、JSON 文件必不可少。我很满意关于数据表包的讲座,因为我用它来做这个专业的所有测验和作业。我希望他们有一个以上的讲座,虽然因为它不是那么容易学会。
Getting and Cleaning Data John Hopkins Quiz 1
第二周回顾:更多相同的内容。与各种数据源(MySQL、HDF5 等)交互。我希望他们能更多地谈论 github API。我注意到很多学生在那个问题上有很多困难。以至于我写了一篇关于如何用 Github API 访问数据的独立博文。
Getting and Cleaning Data John Hopkins Quiz 2
第 3 周和第 4 周回顾:看完 data.table 后再看 dplyr 似乎有点多。第 4 周复习了正则表达式和编辑文本变量,这非常重要,应该在第 3 周测验之前完成,因为这是必要的。
Getting and Cleaning Data John Hopkins Quiz 3
Getting and Cleaning Data John Hopkins Quiz 4
项目回顾:这个项目非常有用,因为它让人们下载文件、解压缩、清理和组织数据文件。具有讽刺意味的是,同一周我在工作中也做了类似的事情,这让我对这门课程评价很高。正式任务位于我的 github 上。
Getting and Cleaning Data John Hopkins Project
请让我知道你是否有任何问题,或者如果你有任何关于我如何改进我的编码技巧!这个约翰·霍普斯金专业甚至帮助了我的工作。下一门课程“探索性数据分析”的复习已上线。
将数据导入张量流估算模型
原文:https://towardsdatascience.com/getting-data-into-tensorflow-estimator-models-3432f404a8da?source=collection_archive---------2-----------------------
Photo by Mathew Schwartz on Unsplash
机器学习是关于你的数据的数量和质量。上述数据通常可从多种来源获得:
- 文本文件(CSV、TSV、Excel)
- 数据库
- 流媒体源
文本文件是由从其他来源提取数据的某个人或某些人提供的,但他们希望您不必亲自提取数据。数据可以在一个或多个文件中,有或没有标题。
张量流估计器使用输入函数。输入函数的签名返回一组要素和标注。特性是特性名称和数值数组的字典。标签是一组值。需要进行一些管理,比如对数据进行洗牌,然后分批返回。你采取的方法决定了你需要付出多少努力。
让我们从简单的选项开始。如果你把数据放在一个文件中,你可以把它完全读入内存(所谓的玩具例子),而且这个文件是以文本分隔的格式(CSV,TSV 等),所需的工作量是最小的。通常情况下,你可以用 numpy 或 pandas 来读取你的文件。
提醒一下,在使用tf.estimator
API 的时候,需要在训练的时候传入一个输入函数。这是用于训练的函数签名:
train(
input_fn,
hooks=None,
steps=None,
max_steps=None,
saving_listeners=None
)
我们的重点是input_fn
!我们将使用流行的波士顿住房数据,这些数据在这里托管。
如果你有 numpy 格式的数据,你可以使用tf.estimator.inputs.numpy_input_function
来获取你的数据。首先,您需要为您的特征定义一个字典:
# extract numpy data from a DataFrame
crim = train_df['crim'].values
zn = train_df['zn'].values
indus = train_df['indus'].values
chas = train_df['chas'].values
nox = train_df['nox'].values
rm = train_df['rm'].values
age = train_df['age'].values
dis = train_df['dis'].values
rad = train_df['rad'].values
tax = train_df['tax'].values
ptratio = train_df['ptratio'].values
black = train_df['black'].values
lstat = train_df['lstat'].values
medv = train_df['medv'].values# create a dictionary
x_dict = {
'crim': crim,
'zn': zn,
'indus': indus,
'chas': chas,
'nox': nox,
'rm': rm,
'age': age,
'dis': dis,
'rad': rad,
'tax': tax,
'ptratio': ptratio,
'black': black,
'lstat': lstat
}
有了字典,我们可以继续定义输入函数。
def np_training_input_fn(x, y):
return tf.estimator.inputs.numpy_input_fn(
x= x,
y= y,
batch_size= 32,
num_epochs= 5, # this way you can leave out steps from training
shuffle= True,
queue_capacity= 5000
)
在我们的函数中,我们传入 x 和 y,x 是我们的字典,y 是我们的标签。我们还可以传入我们的批量大小、时期数以及是否打乱数据。请注意,你总是想打乱你的数据。批量大小是一个超级参数,你应该凭经验归档。epochs 的数量是您想要查看数据的次数。对于训练,设置任何数字。对于测试,将其设置为 1。
在创建评估器之前,您需要特性列。
feature_cols = [tf.feature_column.numeric_column(k) for k in x_dict.keys()]lin_model = tf.estimator.LinearRegressor(feature_columns=feature_cols)lin_model.train(np_training_input_fn(x_dict, medv), steps=10)
您可以省略步骤,以便训练使用在训练输入函数中指定的时段,或者指定用于训练的步骤数。numpy 输入到此为止。
对于数据帧,您将继续定义输入函数如下:
def pd_input_fn(df, y_label):
return tf.estimator.inputs.pandas_input_fn(
x=df,
y=df[y_label],
batch_size = 32,
num_epochs = 5,
shuffle = True,
queue_capacity = 1000,
num_threads = 1
)
请注意,在上面的方法中,我们继续传入数据帧,并在其中添加标签。如果标签不在您传递给x
的内容中,您将得到一个错误。你把一个系列传给y
。其他参数与处理 numpy 时相同。
该模型在未来会得到同样的对待。创建模型并指定特征列。然后,您继续训练模式。
lin_model = tf.estimator.LinearRegressor(feature_columns=feature_cols)lin_model.train(pd_input_fn(train_df, 'medv'), steps=10)
当您可以将数据读入内存时,一切都很好。但是,当你不能的时候会发生什么。当你的训练数据集是 100GB 时会发生什么?
好消息是,这样的数据集通常由分布式系统生成,因此您的文件将是sharded
。这意味着数据将被存储在不同的文件名为data-0001-of-1000
的文件中。
如果你从未处理过大数据,你的第一个想法可能是使用glob
。不要这样做,除非你知道你正在处理一个玩具的例子。你会耗尽你的记忆,训练也会停止。
这些类型的文件通常没有头文件,这是一件好事。首先,您将定义一个列名列表,这些列名应该按照您的列在文件中存在的顺序排列。其次,定义一个标签列。最后,定义一个缺省值列表,以便在读取过程中遇到缺失值时可以处理它们。
CSV_COLUMNS = ['medv', 'crim', 'zn', 'lstat', 'tax', 'rad', 'chas', 'nox', 'indus', 'ptratio', 'age', 'black', 'rm', 'dis']
LABEL_COLUMN = 'medv'
DEFAULTS = [[0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0]]
接下来,我们定义一个函数来读入文本数据,并返回我们的格式,就像我们前面的函数处理它们一样。函数创建方式的一个优点是它可以处理通配符,比如data-*
。
**def** read_dataset(filename, mode, batch_size = 512):
**def** _input_fn():
**def** decode_csv(value_column):
columns = tf.decode_csv(value_column, record_defaults = DEFAULTS)
features = dict(zip(CSV_COLUMNS, columns))
label = features.pop(LABEL_COLUMN)
**return** features, label
*# Create list of files that match pattern*
file_list = tf.gfile.Glob(filename)
*# Create dataset from file list*
dataset = tf.data.TextLineDataset(file_list).map(decode_csv)
**if** mode == tf.estimator.ModeKeys.TRAIN:
num_epochs = None *# indefinitely*
dataset = dataset.shuffle(buffer_size = 10 * batch_size)
**else**:
num_epochs = 1 *# end-of-input after this*
dataset = dataset.repeat(num_epochs).batch(batch_size)
**return** dataset.make_one_shot_iterator().get_next()
**return** _input_fn
该函数接受三个参数:一个匹配多个文件的模式、一个模式(训练或评估)和一个批处理大小。注意read_dataset
返回一个函数。我们称这个函数为_input_fn
。在这个函数中,我们有一个名为decode_csv
的函数,它将创建一个字典,提取一个序列,并以我们在本文开头提到的元组格式返回两者。
其次,我们的函数使用glob
创建一个文件名列表。是的,glob
仍然被使用,但是我们不把结果传递给一个pandas.read_csv()
。反而遇到了tf.data.TextLineDataset()
。它有三个参数:文件名列表、压缩格式(none、ZLIB 或 GZIP)和缓冲区大小。read_csv
和TextLineDataset
的主要区别在于,前者将内容读入内存(我们可以批量读取),而后者返回一个Iterator
。
因此,我们的函数通过调用map
函数,传入decode_csv
,使用TextLineDataset
创建一个数据集。它做的下一件事是检查我们是否处于训练模式。如果不是,我们的历元数被设置为 1。如果是的话,它会被设置为我们想要的任意多个纪元。我们的训练数据集也被打乱了。然后,我们的数据集被设置为重复我们想要的历元数,并根据我们的批量大小进行配置。
最后,我们返回一个一次性迭代器,并调用get_next()
。所有这些工作都由我们前面看到的函数在幕后处理。我们可以使用以下方法创建我们的训练、评估和测试输入函数:
**def** get_train():
**return** read_dataset('./train-.*', mode = tf.estimator.ModeKeys.TRAIN)
**def** get_valid():
**return** read_dataset('./valid.csv', mode = tf.estimator.ModeKeys.EVAL)
**def** get_test():
**return** read_dataset('./test.csv', mode = tf.estimator.ModeKeys.EVAL)
剩下的过程和我们看到的完全一样。我们可以像往常一样创建我们的估计器并训练它。
对于真正的项目,你将从阅读一个使用熊猫和tf.estimator.inputs
的训练文件开始。但是,要在培训中使用所有文件,您需要使用tf.data.TextLineDataset
。
快乐编码。
为建模准备数据:特征工程、特征选择、降维(下)
原文:https://towardsdatascience.com/getting-data-ready-for-modelling-feature-engineering-feature-selection-dimension-reduction-39dfa267b95a?source=collection_archive---------4-----------------------
这是为建模准备数据系列的第二部分。如果您还没有阅读第 1 部分,那么我建议您先浏览一遍。因为特征工程通常是第一步。
[## 为建模准备数据:特征工程、特征选择、降维…
特征工程,特征选择,降维
…特征工程、特征选择、尺寸 Reductionmedium.com](https://medium.com/@desardaakash/getting-data-ready-for-modelling-feature-engineering-feature-selection-dimension-reduction-77f2b9fadc0b)
一旦有了足够的、更少的或没有丢失的数据或异常值,接下来就是特征选择或特征提取(这两者通常做相同的工作,可以互换使用)。通常有两种方法:
- 特征提取/选择
- 维度缩减或特征缩减
让我们一个一个地,一步一步地解决它们。
第 2 部分:特征提取/选择
那么什么是特征选择呢?特征提取?他们的区别?
→在机器学习和统计学中,特征选择也称为变量选择,是选择相关特征(变量、预测器)的子集用于模型构建的过程。
→特征提取用于创建一个新的、更小的特征集,该特征集仍能捕获大部分有用信息。
→同样,特征选择保留原始特征的子集,而特征提取创建新的特征。
特征选择/提取的重要性
→当特征数量非常大时,这变得更加重要。
→你不需要使用你所掌握的每一个特性来创建一个算法。
→你可以通过只输入那些真正重要的特征来帮助你的算法。
为什么要使用特征选择?
→它使机器学习算法能够更快地训练,降低复杂性,并使其更容易解释。
→如果选择了正确的子集,它会提高模型的准确性。
→减少过度拟合。
它可以大致分为两种技术(尽管这不是“T8”的唯一方法)
I .单变量特征选择
二。多元特征选择
U 访问每一个特征,并根据目标检查其重要性。为了实现单变量特征选择,你应该掌握一些技巧。
→如果你有适当的领域知识并且相信你的判断,那么总是从这一步开始。分析所有的特征,去掉所有不需要的。是的,这是费时费力的一步,但是,嘿,你更相信谁呢,“机器还是你自己”
→ 检查所有特征的方差(是的,永远令人困惑的偏差-方差权衡:)。这里的经验法则是设置一个阈值(假设一个特征的方差为 0,意味着它对每个样本都具有相同的值,因此这样的特征不会给模型带来任何预测能力)并相应地移除特征。
→ 皮尔森相关性的使用:这可能是三种技术中最适用的一种。如果你不知道或者对它感到困惑,那么先看看这篇文章。
- 因此,简而言之,它给了我们目标变量和特征之间的相互依赖性。
Thump Rule To analyse Pearson Correlation
- 使用皮尔逊相关性的经验法则:
I .仅选择与目标变量的中度至强关系。(见上图)。
二。当两个特征本身与目标变量有很强的相互关系时,选择其中任何一个(选择两个都不会增加任何值)。使用'seaborn . heat map()'进行可视化和挑选,很有帮助。
三。这里有一个陷阱😢。它最适用于线性数据,不适用于非线性数据(所以请避免使用它)。
M 所以用外行的话来说就是一次选择多个特性。
多元特征选择大致分为三类:
让我们来看看它们(我们将讨论每个类别中最广泛使用的技术)
过滤方法:
→过滤方法通常用作预处理步骤。特征的选择独立于任何机器学习算法。
→过滤方法对特征进行排序。等级表示每个特征对于分类的“有用”程度。一旦计算出这个排序,就创建了由最好的 N 个特征组成的特征集。
→根据其在各种统计测试中的得分选择特征,以确定其与结果变量的相关性。(这里的相关性是一个主观术语)。
Blueprint of Filter Method
- 皮尔逊相关:哦对!皮尔逊相关是过滤方法。我们已经讨论过了。
- 方差 阈值:这一点我们也已经讨论过了。
- 线性判别分析:目标是将数据集投影到一个具有良好类别可分性的低维空间,以避免过拟合()【维数灾难】,同时降低计算成本。
→没有进入数学领域,LDA 将所有的高维变量(我们不能绘制和分析)放到 2D 图上&同时这样做去除了无用的特征。
→ LDA 也是的 监督降维 技术,更像是特征提取而不是选择(因为它通过降低变量的维度来创建一种新的变量)。所以它只对带标签的数据有效。
→最大化类别间的可分性。(技术术语太多,对。不要担心看视频)。
Creator: Josh Starmer
其他:
ANOVA: 方差分析除了使用一个或多个分类独立特征和一个连续相关特征进行操作之外,它类似于 LDA。它提供了几个组的平均值是否相等的统计检验。
卡方:这是一种应用于分类特征组的统计检验,利用它们的频率分布来评估它们之间相关或关联的可能性。
需要记住的一点是,过滤方法不能去除多重共线性。因此,在为数据训练模型之前,还必须处理要素的多重共线性。
What to choose when
包装方法:
Blueprint Of Wrapper Method
→根据我们从之前的模型中得出的推论,我们决定在您的子集中添加或删除特征。
→包装方法之所以被称为包装方法,是因为它们将分类器包装在特征选择算法中。通常选择一组特征;这种设置的效率是确定的;进行一些扰动以改变原始集合,并评估新集合的效率。
→这种方法的问题是特征空间很大,查看每个可能的组合需要大量的时间和计算。
→问题本质上归结为一个搜索问题。这些方法通常在计算上非常昂贵。
- 正向选择:正向选择是一种迭代方法,我们从模型中没有特征开始。在每一次迭代中,我们不断地添加最能改进我们模型的特性,直到添加一个新变量不能改进模型的性能。
- 向后消除:在向后消除中,我们从所有特征开始,并在每次迭代中移除最不重要的特征,这提高了模型的性能。我们重复这一过程,直到在特征的移除上没有观察到改进。
- 【递归特征消除(RFE) : It 的工作原理是递归地删除属性,并在那些保留的属性上建立模型。它使用外部估计器为要素分配权重(例如,线性模型的系数),以确定哪些属性(以及属性组合)对预测目标属性的贡献最大。
→这是一种贪婪优化算法,旨在找到性能最佳的特征子集。
→它重复创建模型,并在每次迭代中保留最佳或最差的性能特征。
→它用剩下的特征构造下一个模型,直到所有的特征都用完。然后,它根据要素被消除的顺序对其进行排序。
*# Recursive Feature Elimination
from sklearn.feature_selection import RFE
from sklearn.linear_model import LinearRegression# create a base classifier used to evaluate a subset of attributes
model = LinearRegression()X, y = iowa.iloc[:,:-1], iowa.iloc[:,-1]
# create the RFE model and select 3 attributes
rfe = RFE(model, 10)
rfe = rfe.fit(X, y)# summarize the selection of the attributes
print(rfe.support_)
print(rfe.ranking_)
***Output:*** [False False True True False False False False False False False False
False False False True True True False True True True True False
True False False False False False False False False False]
[16 24 1 1 4 9 18 13 14 15 11 6 7 12 10 1 1 1 2 1 1 1 1 5 1
23 17 20 22 19 8 21 25 3]*
→下面是上面例子中发生的情况,
I . 'rfe . support _【T9]'按顺序给出了与特性相关的结果(显然是基于所选型号和需求编号)。
二。 rfe.ranking_ '分别给出所有特性的等级。当你需要的功能比输入给' n_features_to_select' (在上面的例子中是 10 个)的功能更多时,这真的很方便。所以,你可以设置一个阈值&分别选择它上面的所有特征。
4。顺序特征选择器 : 顺序特征选择算法是一类贪婪搜索算法,用于将初始的 d 维特征空间缩减为 k 维特征子空间(其中 k < d) 。
→逐步推进特性选择从评估每个单独的特性开始,并选择能够产生最佳性能选定算法模型的特性。
→后退功能选择密切相关,正如您可能已经猜到的,它从整个功能集开始,并从那里后退,删除功能以找到预定义大小的最佳子集。
→什么叫“最好?”
这完全取决于定义的评估标准(AUC、预测准确性、RMSE 等。).接下来,评估所选特征和后续特征的所有可能组合,并且选择第二特征,等等,直到选择了所需的预定数量的特征。
→简而言之,SFA 根据分类器性能一次删除或添加一个特征,直到达到所需大小的特征子集 k 。
注意:我建议你访问官方文档,通过例子了解更多细节
*[## 顺序特征选择器— mlxtend
包含日常数据科学任务的有用工具和扩展的库。
rasbt.github.io](http://rasbt.github.io/mlxtend/user_guide/feature_selection/SequentialFeatureSelector/)*
嵌入式方法:
Blueprint of Embbeded Methods
→嵌入式方法结合了过滤器和包装器方法的特性。它是由具有内置特征选择方法的算法实现的。
→因此,这不是任何类型的特殊特征选择或提取技术,它们也有助于避免过度拟合。
- 线性回归中的套索正则化
- 在随机森林中选择 k-best
- 梯度推进机
过滤器和包装器方法之间的区别
第 3 部分:降维
所以,还是从同一个问题开始,什么是降维?
简单来说,就是将一个初始的 d 维特征空间缩减为一个 k 维特征子空间(其中k<d】)。
那么特征选择&提取又是为什么呢?
某种程度上,是的(但只是俗人术语’)。为了理解这一点,我们必须深入研究。**
在机器学习中,维度简单来说就是指你的数据集中的个特征(即输入变量)的数量。当要素的数量相对于数据集中的观察值数量非常大时,某些算法很难训练出有效的模型。这被称为“维数灾难”,它尤其与依赖于距离计算的聚类算法相关。
(Quora 的一位用户为维度诅咒提供了一个很好的类比,看看吧)
因此,当你拥有 100 个甚至 1000 个特性时,你只有一个选择降维。让我们讨论两种非常健壮和流行的技术。
- 线性判别分析(LDA): 是的,与过滤方法(如上所述)一起,它也被用作降维技术。
→当特征被标记时,我们在监督学习中使用 LDA。
→请努力理解 LDA(如果您还没有理解的话)。
2。主成分分析(PCA): 主成分分析的主要目的是对数据进行分析,以识别模式并找出模式,从而以最小的信息损失降低数据集的维度。
→ PCA 将尝试通过探索数据的一个特征如何用其他特征来表示来降低维数(线性相关性)。相反,特征选择会考虑目标。
→ PCA 最适用于 3 维或更高维的数据集。因为随着维度的增加,从产生的数据云中做出解释变得越来越困难。
(PCA 有点复杂,没错。在这里解释会让这篇已经很长的博客更无聊。所以用这两个极好来源来理解,
一、主成分分析一站式服务
二。Josh Starmer 的视频解释(来自 StatQuest 的同一个人)
Creator: Josh Starmer
W 说唱起来:但不是通过包装方法(咄…😜).这是系列的结尾。最后(但不是列表)分钟提示:
永远不要忽视特征工程和特征选择,一切都要依靠算法。
二。在尾注上,我分享了两个非常有用并且非常棒的工具(记住我的话,这会对你有很大帮助)
→ 特征选择器 (这得感谢威廉·科尔森)
→ 特征工具 (或本)
为建模准备数据:特征工程、特征选择、降维(第 1 部分)
原文:https://towardsdatascience.com/getting-data-ready-for-modelling-feature-engineering-feature-selection-dimension-reduction-77f2b9fadc0b?source=collection_archive---------8-----------------------
即使在机器学习的幻想世界中,就像人类无法在崎岖的道路上正确驾驶车辆一样,ML 算法也无法在大量不需要的混杂数据上产生预期的结果。因此,让我们深入探讨优化数据所有选项。
注意:这可能有点冗长。所以我把它分成三个系列。因此,请一部分一部分地探索这一点。
第 1 部分:特征工程
什么是特色工程,为什么要纠结于此?
特征工程是使用数据的领域知识来创建使机器学习算法工作的特征的过程。特征工程是机器学习应用的基础,既困难又昂贵。但如果处理得当,会产生奇迹。这就是同一个算法工作得很差和工作得很棒的区别。
很重要,不容忽视。让我们看看它的大致思想:
- 数据清理&预处理
→处理异常值
→处理缺失值
→处理偏斜
- 缩放
- 编码
- 数据清理&预处理: 在现实世界中,我们永远不会得到适合某个算法的定制数据。我们需要通过以下方式做到这一点。
i)异常值的处理:异常值是不遵循数据一般趋势的数据点。许多算法对异常值很敏感。所以问题是怎么办?
→如果很少,那么就彻底清除。您可以设置阈值来识别它们,然后删除它们。如果一列有很多离群值,最好完全删除该列,行也是如此。
→您可以将所有内容转换为“日志形式”,因为日志会将所有内容带到相同的距离。(尽管只对数字数据有效)
→ 使用散点图、直方图和盒须图可视化数据,并寻找极值。还有很多其他的技术可以用来处理异常值,我建议你去尝试一下。
ii)处理缺失值: 为什么要处理缺失值?
训练数据集中的缺失数据会降低模型的功效/拟合度。缺少值会导致模型有偏差,因为我们没有正确分析行为以及与其他变量的关系。这很有用,因为有些算法无法处理或利用丢失的数据。因此,识别和标记这些丢失的数据是很重要的。一旦标记,就可以准备替换值。
→替换缺失值,均值、中值、众数(完全取决于判断)。你可以使用sk learn . preprocessing . impute来达到同样的目的。
→如果需要,可以用全新数据替换(再次判断)。
→或者,如果缺少的值太多,您可以删除整个列。因此,这主要需要再次判断!!!
iii)偏度:偏度是分布的不对称性的度量。偏斜度是对称性的一种度量,或者更准确地说,是对称性的缺乏。
The basic three types of Skewness
为什么要处理偏斜?
→许多模型构建技术都假设预测值呈正态分布并具有对称形状。因此,有时处理偏斜度是至关重要的。
→对称分布优于偏斜分布,因为它更容易解释和产生推论。
→使用对数变换、平方根变换等。
2。 缩放: 像处理缺失值是一种强制,缩放不是。但这并不意味着它是不太重要的技术。考虑一个场景,其中一个列(比如 A)的值在 10k 到 100k 的范围内,另一个列的值在 0 到 1 的范围内(比如 B),那么 A 将比 B 具有不适当的优势,因为它将承载更多的权重。
→缩放将特征修改为介于给定的最小值和最大值之间,通常介于 0 和 1 之间,或者将每个特征的最大绝对值缩放至单位大小,以提高某些模型的数值稳定性。
Effect Of Scaling
→但是标准化/缩放不能应用于分类数据,因此我们将分类数据和数值数据分开,以便对数值数据进行标准化。
→ 最小最大值定标器、标准巩膜、标准化器等是一些技术。都可以使用' sk learn . preprocessing . scaler '来执行
(建议你访问 本博客 更深入地研究缩放比例)
3。编码: 那么,编码是什么,为什么编码?
我们使用的大多数算法处理数值,而分类数据通常是文本/字符串(男性、女性)或 bin(0–4、4–8 等)。)形式。
一种选择是将这些变量排除在算法之外,只使用数字数据。但是在这样做的时候,我们可能会丢失一些关键的信息。因此,通过编码将分类变量转换成数值来将它们包含到算法中通常是一个好主意,但是,首先让我们学习一两件关于分类变量的事情。
Types of Variable
对数据做的编码一般有两种,标签编码&一种热编码(或 pandas.get_dummies)。
i)标签编码:每个类别被赋予一个标签(例如 0、1、2 等)。标签编码是编码分类变量的一种简便技术。然而,这种编码的名义变量可能最终被误解为序数。所以标签编码只在有序类型的数据上进行(这些数据有一定的顺序感)。
→因此,即使在标签编码后,所有数据也不会失去其排名或重要性水平。
eg of Label Encoding
可以使用' sk learn . preprocessing . label encoder '执行
ii)一个热编码:标签编码不能在名义或二进制上执行,因为我们不能根据它们的属性对它们进行排序。每个数据都被平等对待。考虑以下两个分类变量及其值,如
→颜色:蓝色、绿色、红色、黄色
→学历:小学、中学、研究生、研究生、博士。
Eg Of One hot Encoding
可以使用 'pd.get_dummies' 或' sk learn . preprocessing . onehotencoder '执行
具有更多维度的数据集需要模型理解更多的参数,这意味着需要更多的行来可靠地学习这些参数。使用一个热编码器的效果是增加了许多列(维度)。
如果数据集中的行数是固定的,添加额外的维度而没有添加更多的信息供模型学习,可能会对最终的模型准确性产生不利影响。
One Hot Encoding vs Label Encoding
以此表示第 1 部分告一段落。请务必阅读第 2 部分,其中将讨论特征提取和非常重要的降维。
让数据科学发挥作用
原文:https://towardsdatascience.com/getting-data-science-to-work-872d78865793?source=collection_archive---------4-----------------------
预测模型不仅仅是预测
在构建预测模型时,大多数初级(以及许多高级)数据科学家都陷入了一个思维陷阱,认为他们工作的成功恰恰取决于预测的准确性。这里有一个例子:一个数据科学家被拉进一个项目,“帮助预测哪些客户最有可能打开一封营销邮件。”他们花了数周时间想出如何做到这一点:线性回归还是随机森林?模型中应该包括哪些功能?我们应该在哪个时间段建立预测?模型是否应该包含正则化组件以避免过度拟合?数据科学家梳理谷歌学术,搜索交叉验证,并通过电子邮件向他们的同事征求建议。然后缩小到一个型号:这个型号有更好的 R,但是那个包括更少的功能。经过深思熟虑,做出了选择,数据科学家感到满意。
不幸的是,该模型从未投入使用,使得整个努力毫无价值。
这方面一个完美的案例研究是网飞奖:网飞向最能预测人们会喜欢哪部电影的团队支付了 100 万美元的奖金。不幸的是,解决方案从未实施。事实证明,获奖的解决方案是如此复杂,以至于工程团队实现它所涉及的工作不值得获得准确性。获胜的解决方案实际上是 107 种不同的机器学习方法的组合,因此试图让 107 种方法在生产中运行是没有意义的。
当建立一个预测模型时,你不能只选择最符合数据的模型,你需要设计一个人们想要实现的模型。要做到这一点,模型需要得到组织中许多人的认可。它需要由负责监控和维护模型的工程团队签署。这通常意味着实现一个更简单的模型——你可以在几乎任何系统中编写逻辑回归代码,但让深度学习网络为存储在传统数据库中的数据可靠地运行可能是一项更艰巨的任务。这也意味着快速创建一个解决方案:如果你可以花三周时间使用逻辑回归得到一个“体面”的解决方案,那么为什么要花六个月时间寻找一个更好的呢?到那时,业务问题可能不再相关,或者哎呀,你的资金几个月前就用完了。
同样重要的是,你需要让商业利益相关者参与进来。这些人将会使用模型的结果(并可能为开发付费)。在我的位置上,这往往是营销主管,他们将使用工具来预测客户行为。对于其他人来说,可能是产品设计团队或物流部门。这些人需要相信模型会提供一个比根本没有更好的解决方案,这并不容易,因为模型需要维护。
那么,如何让商业利益相关者参与进来呢?通过清晰的叙述展示模型。通过 PowerPoint 或其他方式向他们展示你在模型中使用的数据以及你选择它的原因。你在建立模型时做了什么选择,这对结果有什么影响?该模型是否倾向于在预测方面做得很好,以及有多少潜在的收入收益。模型中的特征重要性是否告诉了你如何以不同的方式进行营销?
You’d be amazed at how much colorful shapes can help sell your data science solution
如果你能有效地让人们同意“是的,这是我们应该有的东西”,那么建立模型就变得容易多了。人们会很兴奋地看到模型的结果对业务有所帮助,并渴望让你从事其他项目。除非您有能力将您的模型呈现给将要使用它的人,否则您无法达到这种状态,这意味着您要花时间围绕工作创建演示文稿,而不是优先构建更好的模型。
通常很难知道何时停止——如果你总能让模型变得更好,为什么不去做呢?最好的方法是让外界的约束为你做决定。如果在整个模型开发过程中,您不断地准备好模型的演示,并在模型发生变化时更新它,那么就很容易不断地使模型变得更好,直到其他因素(如您的老板)要求模型就位。使用诸如 Rmarkdown (R)或 Jupyter Notebooks (Python)之类的工具最容易做到这一点,这些工具让您只需点击一个按钮就可以轻松导出结果。
因此,当你致力于为你的企业建立新的预测能力时,请记住,让其他人想要使用它们和创造它们一样困难。虽然很容易(也很有趣!)要深入数据科学,尝试构建最佳预测模型,不要忘记你在一个也需要参与的团队中工作。
如果你想要一大堆帮助你在数据科学领域发展职业生涯的方法,看看我和艾米丽·罗宾逊写的书: 在数据科学领域建立职业生涯 。我们将带您了解成为数据科学家所需的技能,找到您的第一份工作,然后晋升到高级职位。
让 R 和 D3.js 在 R markdown 中正常运行
原文:https://towardsdatascience.com/getting-r-and-d3-js-to-play-nicely-in-r-markdown-270e302a52d3?source=collection_archive---------0-----------------------
因为已经有很多优秀的资源是由更有资格的人制作的,所以这并不是 JavaScript、D3.js、R 或 R markdown 的全面教程。相反,它的目的是展示在一个文件中使用所有这些文件的经验。
为了使本教程简单,让我们假设数据已经完全科学化,剩下的就是创建 D3 可视化。请看一下 R 附带的原始样本数据集
head(cars)## speed dist
## 1 4 2
## 2 4 10
## 3 7 4
## 4 7 22
## 5 8 16
## 6 9 10
在语言之间传递数据不像引用包含它们的变量的名称那么简单。如果您尝试在上面的 R 块后面添加 JavaScript 代码console.log(cars);
,它将返回一个ReferenceError
,因为cars
尚未在 JavaScript 中定义。
您可以将数据写入一个新文件,然后使用 D3 中适当的加载方法读回该文件。但是,可以将数据直接传递给。Rmd 文件。
cat(
paste(
'<script>
var data = ',cars,';
</script>'
, sep="")
)##
## <script>
## var data = c(4, 4, 7, ... 24, 24, 25);
## </script>
## <script>
## var data = c(2, 10, 4, ... 93, 120, 85);
## </script>
上面的代码确实会将数据传递到我们的 JavaScript 空间;然而,我们给自己制造了两个新问题:
- 数据中的每一列都作为 R 向量被传递,JavaScript 会将其解释为对某个函数
c()
的调用,每个值都作为参数被传递。 - 这些列被逐个传递给 JavaScript 变量
data
,用dist
列中的值覆盖speed
列中的值。
要同时解决这两个问题,可以利用 D3 的假设,即它处理的数据是 JSON 格式的。r 的jsonlite
库是轻量级的,有一个简单的toJSON()
方法,非常适合我们的目的。
library("jsonlite")
cat(
paste(
'<script>
var data = ',toJSON(cars),';
</script>'
, sep="")
)## <script>
## var data = [{"speed":4,"dist":2},
## {"speed":4,"dist":10},
## {"speed":7,"dist":4},
## ...
## {"speed":24,"dist":93},
## {"speed":24,"dist":120},
## {"speed":25,"dist":85}];
## </script>
**** 您必须在代码块顶部的花括号中包含 results="asis "选项,以便通过**** 传递数据
现在 JavaScript 有了数据,而且是它可以处理的格式。是时候开始 D3ing 了!
有两种方法可以加载 D3 库。在可视化之前的任何时候,将<script src="https://d3js.org/d3.v4.min.js"></script>
直接包含在您的降价文件中。或者在与您相同的目录中创建一个. html 文件,其中只包含相同的脚本标记。Rmd 文件和包含它
你现在可以在 R markdown 中自由地想象 D3.js,直到你满意为止。只需用 JavaScript 代码块添加代码,直接在 markdown 中的脚本标记之间,或者在用脚本标记链接的单独文件中。
我应该加一句警告。如果你是那种只从 https://bl.ocks.org T2 复制/粘贴的人,这没什么不好意思的——我个人不知道有谁使用 D3 不这么做——但是你必须记住他们的数据总是通过 D3 的加载方法从外部来源读入的。您必须删除这些代码行,并在 D3 的.data()
方法中代入您的数据变量。此外,一定要检查 D3 代码,更新对列名的所有数据引用。
查看 GitHub 上的代码
使用 Docker 开始使用气流
原文:https://towardsdatascience.com/getting-started-with-airflow-using-docker-cd8b44dbff98?source=collection_archive---------1-----------------------
最近,在受到 Robert Chang 的这篇介绍数据工程领域的伟大文章的启发后,我一直在集中阅读该领域的内容。这篇文章的潜在信息真的引起了我的共鸣:当大多数人想到数据科学时,他们会立即想到谷歌或 Twitter 等非常成熟的科技公司正在做的事情,比如一直部署超级复杂的机器学习模型。
然而,许多组织还没有达到将这类模型作为首要任务的阶段。这是因为,为了高效地构建和部署这类模型,您需要有一个基础数据基础设施来构建模型。是的,你可以用你组织中的数据开发一个机器学习模型,但你必须问:你花了多长时间做这件事,你的工作是可重复/可自动化的吗,你能够以有意义和可靠的方式部署或实际使用你的解决方案吗?这就是数据工程的用武之地:它是关于构建数据仓库和 ETL 管道(提取-转换-加载)的,这些管道提供了做其他事情所需的基础管道。
在我对数据工程的研究中不断出现的一个工具是 Apache Airflow ,它是“一个以编程方式创作、调度和监控工作流的平台”。本质上,气流是类固醇上的 cron :它允许你安排任务运行,以特定的顺序运行它们,并且监控/管理你所有的任务。它在数据工程师/数据科学家中变得非常流行,成为编排 ETL 管道并在它们运行时监控它们的一个很好的工具。
在这篇文章中,我将对气流中的一些关键概念做一个简单的概述,然后展示气流在 Docker 容器中的一步一步的部署。
关键气流概念
在我们开始部署气流之前,有几个基本概念需要介绍。参见气流文档中的这一页,其中详细介绍了这些内容,并描述了其他概念。
【DAG】:DAG 是你要运行的任务的集合,以及任务之间的关系和依赖关系。Dag 可以直观地表示为具有节点和边的图,其中节点表示任务,边表示任务之间的依赖性(即任务必须运行的顺序)。本质上,dag 表示您希望在 Airflow 中编排和监控的工作流。它们是“非循环的”,这意味着该图没有循环——在英语中,这意味着您的工作流必须有开始和结束(如果有循环,工作流将陷入无限循环)。
操作符 :操作符代表在组成 DAG 工作流的任务中实际完成的事情。具体来说,一个操作符代表 DAG 中的一个任务。Airflow 提供了许多预定义的类,这些类非常灵活,可以作为任务运行。这包括用于非常常见任务的类,如 BashOperator、PythonOperator、EmailOperator、OracleOperator 等。除了众多可用的操作符类之外,Airflow 还提供了定义自己的操作符的能力。因此,DAG 中的任务几乎可以做任何您想做的事情,并且您可以使用 Airflow 对其进行调度和监控。
任务 :一个操作符的运行实例。在实例化期间,您可以定义与操作符相关联的特定参数,并且参数化的任务成为 DAG 中的一个节点。
使用 Docker 部署气流并运行您的第一个 DAG
这篇文章的其余部分将重点介绍如何使用 docker 部署 Airflow,并且假设您对 Docker 有所了解,或者您已经阅读了我之前的文章关于如何开始使用 Docker 。
作为第一步,你显然需要安装 Docker 并拥有一个 Docker Hub 帐户。一旦你这样做了,进入 Docker Hub 并在存储库列表中搜索“Airflow ”,这会产生一堆结果。我们将使用第二个: puckel/docker-airflow ,它有超过 100 万个拉点和近 100 颗星。您可以在此处找到此回购的文档。你可以在这里找到与这个容器相关的 github repo。
因此,要让这个预制的容器运行 Apache Airflow,您只需输入:
docker pull puckel/docker-airflow
过了一会儿,你就有了一个 Docker 镜像,用于运行 Docker 容器中的气流。您可以通过键入以下命令来查看您的图像已被下载:
docker images
现在您已经下载了映像,您可以使用以下命令创建一个运行容器:
docker run -d -p 8080:8080 puckel/docker-airflow webserver
一旦你这样做了,Airflow 就在你的机器上运行,你可以通过访问http://localhost:8080/admin/来访问 UI
在命令行上,您可以通过运行以下命令来查找容器名称:
docker ps
您可以使用以下命令跳转到正在运行的容器的命令行:
docker exec -ti <container name> bash
(在我的例子中,我的容器被 Docker 自动命名为主管 _ 沃恩
运行 DAG
因此,您的容器已经启动并运行。现在,我们如何开始定义 Dag?
在 Airflow 中,DAGs 定义文件是 python 脚本(“配置为代码”是 Airflow 的优势之一)。您可以通过定义脚本并简单地将其添加到 AIRFLOW _ HOME 目录下的文件夹“dags”中来创建 DAG。在我们的例子中,我们需要在容器中添加 Dag 的目录是:
/usr/local/airflow/dags
事实是,您不希望直接跳到您的容器中并在其中添加 DAG 定义文件。一个原因是安装在容器中的 Linux 最小版本甚至没有文本编辑器。但一个更重要的原因是,在 Docker 中跳转到容器中并编辑它们被认为是不好的做法,而且是“hacky ”,因为您不能再从 Docker 文件中构建容器运行的映像。
相反,一个解决方案是使用“volumes”,它允许您在本地机器和 Docker 容器之间共享一个目录。您添加到本地容器中的任何内容都将被添加到 Docker 中与之连接的目录中。在我们的示例中,我们将使用以下命令创建一个卷,该卷映射本地计算机上保存 DAG 定义的目录,以及 Airflow 在容器上读取它们的位置:
docker run -d -p 8080:8080 -v /path/to/dags/on/your/local/machine/:/usr/local/airflow/dags puckel/docker-airflow webserver
我们要添加的 DAG 可以在中找到,这个 repo 是由 Manasi Dalvi 创建的。DAG 被称为 Helloworld,您可以在这里找到 DAG 定义文件。(另见这个 YouTube 视频,她介绍了气流,并展示了这个 DAG 的运行情况。)
要将其添加到 Airflow 中,请将 Helloworld.py 复制到/path/to/DAGs/on/your/local/machine。等待几分钟后,刷新您的 Airflow GUI,瞧,您应该会看到新的 DAG Helloworld :
您可以通过进入容器并运行命令气流测试来测试 DAG 中的单个任务。首先,使用前面描述的 docker exec 命令进入容器。一旦你进入,你可以通过运行气流列表 _dags 看到你所有的 Dag。您可以在下面看到结果,我们的 Helloworld DAG 位于列表的顶部:
在运行完整 DAG 之前,您可以在命令行上运行的一个有用的命令是 airflow test 命令,它允许您将单个测试作为 DAG 的一部分进行测试,并将输出记录到命令行。您指定一个日期/时间,它模拟当时的运行。该命令不考虑依赖性,也不与数据库交流状态(运行、成功、失败等),因此您不会在 Airflow GUI 中看到测试结果。因此,使用我们的 Helloworld DAG,您可以在 task_1 上运行测试
airflow test Helloworld task_1 2015-06-01
请注意,当我这样做时,它似乎运行没有错误;然而,我没有得到任何输出到控制台的日志。如果有人对为什么会这样有任何建议,请告诉我。
您可以运行回填命令,指定开始日期和结束日期,以便在这些日期运行 Helloworld DAG。在下面的示例中,我从 2015 年 6 月 1 日到 6 月 7 日每天运行 dag 7 次:
运行此命令时,您可以在 Airflow GUI 中看到以下内容,它显示了各个任务的成功以及 DAG 的每次运行。
资源
- 我对你能否用 UI 创建 Dag 感到困惑,并且这个 Stackoverflow 线程似乎表明你不能。注意在回答中,回答者提到了一些潜在有用的工具,用于开发用户可以在不了解 Python 的情况下定义 Dag 的 UI。
- 这个 Stackoverflow 线程有助于找出体积是将 Dag 添加到容器中运行的气流的解决方案。
- 来自阿帕奇气流的官方教程
- 与阿帕奇气流相关的常见陷阱
- 使用气流的 ETL 最佳实践
- 如果你对学习 Docker 感兴趣,我在我的网站上有一些资源的链接,还有 Anki 抽认卡,这样你就可以无限期地记住它们
原载于 2018 年 11 月 1 日【www.marknagelberg.com】。要访问我共享的 Anki deck 和 Roam Research notes 知识库,以及关于间隔重复和提高学习效率的技巧和想法的定期更新, 加入“下载马克的大脑”。
Apache Airflow 入门
原文:https://towardsdatascience.com/getting-started-with-apache-airflow-df1aa77d7b1b?source=collection_archive---------1-----------------------
Credit Airflow Official Site
在这篇文章中,我将讨论由 Airbnb 开发的工作流管理系统 Apache Airflow。
早些时候,我曾和讨论过用 Bonobo 编写基本的 ETL 管道。Bonobo 在编写 ETL 管道方面很酷,但是这个世界并不全是编写 ETL 管道来实现自动化。还有一些其他的用例,在这些用例中,您必须按照一定的顺序执行任务一次或者定期执行。例如:
- 监控 Cron 作业
- 将数据从一个地方传输到另一个地方。
- 自动化您的开发运维。
- 定期从网站上获取数据,并为你令人敬畏的价格比较系统更新数据库。
- 基于推荐系统的数据处理。
- 机器学习管道。
可能性是无穷的。
在我们进一步在我们的系统中实现气流之前,让我们讨论一下什么是气流及其术语。
什么是气流?
从网站:
Airflow 是一个以编程方式创作、调度和监控工作流的平台。
使用 airflow 将工作流创作为任务的有向无环图(Dag)。airflow scheduler 在遵循指定依赖关系的同时,对一组工作线程执行您的任务。丰富的命令行实用程序使在 Dag 上执行复杂的手术变得轻而易举。丰富的用户界面使得可视化生产中运行的管道、监控进度以及在需要时解决问题变得容易。
基本上,它有助于自动化脚本来执行任务。Airflow 是基于 Python 的,但是你可以执行一个程序,而不管它是什么语言。例如,工作流程的第一阶段必须执行一个基于 C++的程序来执行图像分析,然后执行一个基于 Python 的程序来将信息传输到 S3。可能性是无穷的。
Dag 是什么?
来自维基百科
在数学和计算机科学中,有向无环图(DAG /ˈdæɡ/(关于这个声音听))是没有有向圈的有限有向图。也就是说,它由有限数量的顶点和边组成,每条边从一个顶点指向另一个顶点,因此没有办法从任何顶点 v 开始,并沿着一致指向的边序列,最终再次循环回到 v。等价地,DAG 是具有拓扑排序的有向图,即顶点序列,使得每条边在序列中从前面指向后面。
让我试着用简单的话来解释:你只能是你父亲的儿子,而不是相反。好吧,这是蹩脚或怪异的,但找不到更好的例子来解释一个定向周期。
Airflow DAG(Credit: Apache Airflow)
在 Airflow 中,所有工作流都是 Dag。Dag 由操作符组成。操作员定义需要执行的单个任务。有不同类型的操作器可用(如 Airflow 网站上给出的):
BashOperator
-执行一个 bash 命令PythonOperator
-调用任意的 Python 函数EmailOperator
-发送电子邮件SimpleHttpOperator
-发送一个 HTTP 请求MySqlOperator
、SqliteOperator
、PostgresOperator
、MsSqlOperator
、OracleOperator
、JdbcOperator
等。-执行 SQL 命令Sensor
-等待一定的时间、文件、数据库行、S3 键等
你也可以根据自己的需要定制一个操作符。
安装和设置
气流是基于 Python 的。最好的安装方式是通过pip
工具。
pip install apache-airflow
要验证它是否已安装,请运行命令:airflow version
,它应该会显示如下内容:
[2018-09-22 15:59:23,880] {__init__.py:51} INFO - Using executor SequentialExecutor____________ _________________ |__( )_________ __/__ /________ ______ /| |_ /__ ___/_ /_ __ /_ __ \_ | /| / /___ ___ | / _ / _ __/ _ / / /_/ /_ |/ |/ /_/_/ |_/_/ /_/ /_/ /_/ \____/____/|__/v1.10.0
您还需要安装mysqlclient
来将 MySQL 整合到您的工作流程中。尽管这是可选的。
pip install mysqlclient
在开始任何操作之前,创建一个文件夹并将其设置为AIRFLOW_HOME
。我的情况是airflow_home
。创建完成后,您将调用export
命令将其设置在路径中。
export AIRFLOW_HOME='pwd' airflow_home
在运行export
命令之前,确保你是在airflow_home
之上的一个文件夹。在airflow_home
中,你将创建另一个文件夹来保存 Dag。叫它dags
如果您设置了load_examples=False
,它将不会在 Web 界面上加载默认示例。
现在你必须调用airflow_home
文件夹中的airflow initdb
。一旦完成,它就会创建airflow.cfg
和unitests.cfg
airflow.db
是一个 SQLite 文件,用来存储所有与运行工作流相关的配置。airflow.cfg
就是保持所有的初始设置,让事情保持运行。
在该文件中,您可以看到值为../airflow_home/airflow.db
的sql_alchemy_conn
参数
愿意的话可以用 MySQL。现在,只要坚持基本设置。
到目前为止一切顺利,现在不浪费任何时间,让我们启动 web 服务器。
airflow webserver
启动时,屏幕显示如下:
2018-09-20 22:36:24,943] {__init__.py:51} INFO - Using executor SequentialExecutor/anaconda3/anaconda/lib/python3.6/site-packages/airflow/bin/cli.py:1595: DeprecationWarning: The celeryd_concurrency option in [celery] has been renamed to worker_concurrency - the old setting has been used, but please update your config.default=conf.get('celery', 'worker_concurrency')),____________ _________________ |__( )_________ __/__ /________ ______ /| |_ /__ ___/_ /_ __ /_ __ \_ | /| / /___ ___ | / _ / _ __/ _ / / /_/ /_ |/ |/ /_/_/ |_/_/ /_/ /_/ /_/ \____/____/|__/v1.10.0[2018-09-19 14:21:42,340] {__init__.py:57} INFO - Using executor SequentialExecutor____________ _________________ |__( )_________ __/__ /________ ______ /| |_ /__ ___/_ /_ __ /_ __ \_ | /| / /___ ___ | / _ / _ __/ _ / / /_/ /_ |/ |/ /_/_/ |_/_/ /_/ /_/ /_/ \____/____/|__//anaconda3/anaconda/lib/python3.6/site-packages/flask/exthook.py:71: ExtDeprecationWarning: Importing flask.ext.cache is deprecated, use flask_cache instead..format(x=modname), ExtDeprecationWarning[2018-09-19 14:21:43,119] [48995] {models.py:167} INFO - Filling up the DagBag from /Development/airflow_home/dagsRunning the Gunicorn Server with:Workers: 4 syncHost: 0.0.0.0:8080
现在,当您访问0.0.0.0:8080
时,它会显示如下屏幕:
Airflow Web UI in action
你可以在这里看到一堆条目。这些是气流装置附带的示例。您可以通过访问airflow.cfg
文件并将load_examples
设置为FALSE
来关闭它们
DAG 运行告知某个 DAG 已经执行了多少次。最近的任务告知 DAG 内当前运行的许多任务中的哪个任务,以及它的状态如何。调度类似于您在调度 Cron 时使用的调度,因此,我现在不强调它。调度负责这个特定 DAG 应该在什么时间被触发。
DAG (Graph View)
这是我之前创建并执行的 DAG 的截图。您可以看到代表任务的矩形框。你还可以在灰色方框的右上角看到不同颜色的方框,分别命名为:成功、运行、失败等。这些都是传说。在上图中,您可以选择所有的框都有绿色边框,但是,如果您不确定,请将鼠标悬停在 success legend 上,您将看到如下屏幕:
你可能已经注意到这些盒子的背景/填充颜色是绿色和芦苇色。在灰色框的左上角,您可以看到它们为什么会有这样的颜色,这些背景色代表了此 DAG 中使用的不同类型的运算符。在本例中,我们使用的是 BashOperator 和 PythonOperator。
基本示例
我们将研究一个基本的例子,看看它是如何工作的。我将解释这个例子。在之前在airflow_home/
创建的dags
文件夹中,我们将创建我们的第一个 DAG 样本。因此,我将创建一个名为my_simple_dag.py
的文件
导入后你要做的第一件事就是编写例程,作为操作符的任务。我们将混合使用BashOperator
和PythonOperator
。
**import** datetime **as** dt
**from** airflow **import** DAG
**from** airflow.operators.bash_operator **import** BashOperator
**from** airflow.operators.python_operator **import** PythonOperator
**def greet**():
print('Writing in file')
**with** open('path/to/file/greet.txt', 'a+', encoding='utf8') **as** f:
now = dt.datetime.now()
t = now.strftime("%Y-%m-%d %H:%M")
f.write(str(t) + '\n')
**return** 'Greeted'**def respond**():
**return** 'Greet Responded Again'
这是两个简单的例程,除了返回一个文本什么也不做。稍后我会告诉你为什么我要在文本文件中写东西。接下来我要做的是定义default_args
并创建一个DAG
实例。
default_args = {
'owner': 'airflow',
'start_date': dt.datetime(2018, 9, 24, 10, 00, 00),
'concurrency': 1,
'retries': 0
}
这里你在default_args
dict
变量中设置了一堆参数。
start_date
告知自何时起该 DAG 应开始执行工作流。这个start_date
可能属于过去。对我来说,现在是世界协调时 9 月 22 日上午 11 点。这个日期对我来说已经过去了,因为对我来说已经是世界标准时间上午 11:15 了。您可以随时通过airflow.cfg
文件更改该参数,并设置您自己的本地时区。目前,UTC 对我来说很好。如果你仍然想知道气流使用了多少时间,检查一下气流网页界面的右上方,你应该会看到如下所示的内容。您可以将此作为参考来安排您的任务。
Current time on Airflow Web UI
在没有成功执行的情况下,retries
参数重试运行 DAG X 的次数。concurrency
参数有助于指定运行多个 Dag 所需的进程数量。例如,您的 DAG 必须运行 4 个过去的实例,也称为回填,间隔 10 分钟(我将很快介绍这个复杂的主题),并且您已经将concurrency
设置为2
,那么两个 DAG将同时运行并执行其中的任务。如果你已经在你的 Python 中实现了multiprocessing
,那么在这里你会有宾至如归的感觉。
**with** DAG('my_simple_dag',
default_args=default_args,
schedule_interval='*/10 * * * *',
) **as** dag:
opr_hello = BashOperator(task_id='say_Hi',
bash_command='echo "Hi!!"')
opr_greet = PythonOperator(task_id='greet',
python_callable=greet)
opr_sleep = BashOperator(task_id='sleep_me',
bash_command='sleep 5')
opr_respond = PythonOperator(task_id='respond',
python_callable=respond)opr_hello >> opr_greet >> opr_sleep >> opr_respond
现在,我们使用上下文管理器定义 dag 及其属性,第一个参数是 DAG 的 ID,在我们的例子中是my_simple_dag
,第二个参数我们已经讨论过,第三个参数需要与default_args
中提到的start_date
一起讨论。
在那个上下文管理器中,您正在分配操作符和任务 id。在我们的例子中这些操作符标记为:opr_hello
opr_greet
opr_sleep
和opr_respond
。这些名字然后出现在上面讨论的矩形框中。
在我继续之前,我最好讨论一下 DAG 运行和调度器以及它们在整个工作流中扮演什么角色。
什么是气流调度程序?
气流调度程序是一个一直运行的监控进程,根据schedule_interval
和execution_date.
触发任务执行
达格龙是什么?
一个 DagRun 是一次将运行的 DAG 的实例。当它运行时,它里面的所有任务都将被执行。
上图可能有助于理解一个 DAGRun 😃
假设start_date
是世界标准时间 2018 年 9 月 24 日下午 12:00:00,并且您已经在世界标准时间下午 12:30:00*使用 /10 * * * *(每 10 分钟后)的schedule_interval
启动了 DAG。通过使用上面讨论的相同的default_args
参数,以下将是将立即运行的 DAG 的条目,在我们的例子中,由于concurrency
是1
,所以一个接一个地运行:
Running DAGS since the start date
为什么会这样?嗯,你要对此负责。气流给你的设备运行过去的狗。跑过 Dag 的过程称为回填。回填的过程实际上让气流为所有 Dag 设置了某种状态。该功能适用于运行 DAG 的场景,DAG 查询一些数据库或 API,如 Google Analytics,以获取以前的数据,并使其成为工作流的一部分。即使没有过去的数据,Airflow 也会运行它,以保持整个工作流的状态不变。
运行完过去的 Dag 后,下一个 Dag(您打算运行的 Dag)将在 UTC 时间下午 12:40:00 运行。请记住,无论您设置什么计划,DAG 都会在该时间之后运行,在我们的情况下,如果它必须每 10 分钟在之后运行,它将在 10 分钟过后运行一次。
让我们一起玩吧。我打开my_simple_dag
,然后启动调度程序。
Starting the DAG
airflow scheduler
运行后,您将看到如下所示的 dag 屏幕:
DAG with status “Running”
一些任务正在排队。如果您单击 DAG Id,my_simple_dag
,您将看到如下屏幕:
DAGs backfilled
注意运行 Id 列中的时间戳。你看到模式了吗?第一次是在 10 点,然后是 10 点 10 分,10 点 20 分。然后它会停止,让我再次澄清,DAG 会在 10 分钟的持续时间过后运行。调度器在上午 10:30 开始。因此它用间隔的 10 分钟的差值填充通过了 3 。
DAG with Backfills and the current one
为 UTC 上午 10:30:00 执行的 DAG 实际上是在 UTC 上午 10:40:00 完成的,最新的 DAGRun 记录将始终比当前时间减一。在我们的例子中,机器时间是 UTC 时间上午 10:40:00****
DAG Tree View
如果您将鼠标悬停在其中一个圆圈上,您可以看到在 Run: 前面的时间戳,它告诉您它被执行的时间。你可以看到这些绿色的圆圈有 10 分钟的时间差。给出的树形视图有点复杂,但是给出了整个工作流程的完整画面。在我们的例子中,它运行了 4 次,所有任务都运行成功,深绿色。
有两种方法可以避免回填:将start_date
设置在未来,或者将catchup = False
设置在DAG
实例中。例如,您可以执行如下操作:
**with** DAG('my_simple_dag',
catchup=**False**,
default_args=default_args,
schedule_interval='*/10 * * * *',
# schedule_interval=None,
) **as** dag:
通过设置catchup=False
,你的start_date
是否属于过去并不重要。它将从当前时间开始执行并继续。通过设置end_date
,你可以让 DAG 停止运行。
opr_hello >> opr_greet >> opr_sleep >> opr_respond
你在上面看到的这条线说明了操作者之间的关系,因此构成了整个工作流程。这里的按位运算符讲的是运算符之间的关系。这里opr_hello
先跑,然后剩下的。流程从左到右执行。在图示形式中,它看起来如下:
DAG In GraphView
opr_hello >> opr_greet >> opr_sleep << opr_respond
如果您更改最后一个运算符的方向,流程将如下所示:
任务respond
将并行执行,而sleep
将在两种情况下执行。
结论
在这篇文章中,我讨论了如何引入一个全面的工作流系统来安排和自动化您的工作流。在第 2 部分中,我将给出一个真实的例子来展示如何使用气流。我想在这篇文章中掩盖它,但它已经够长了,解释 DAGRun 概念是必要的,因为我花了相当长的时间才弄明白。
一如既往,这个帖子的代码可以在Github上找到。
本帖原载 此处 。
如果你喜欢这篇文章,那么你应该订阅我的时事通讯。
Python 中的 Apache Kafka 入门
原文:https://towardsdatascience.com/getting-started-with-apache-kafka-in-python-604b3250aa05?source=collection_archive---------0-----------------------
Image Credit: linuxhint.com
在这篇文章中,我将讨论 Apache Kafka 以及 Python 程序员如何使用它来构建分布式系统。
什么是阿帕奇卡夫卡?
Apache Kafka 是一个开源的流媒体平台,最初由 LinkedIn 创建。它后来被移交给 Apache 基金会,并于 2011 年开源。
根据 维基百科 :
Apache Kafka 是由 Apache 软件基金会开发的开源流处理软件平台,用 Scala 和 Java 编写。该项目旨在为处理实时数据提供一个 统一的、高吞吐量、低延迟的 平台。它的存储层本质上是一个“大规模可扩展的发布/订阅消息队列,以分布式事务日志的形式构建”,[3]这使得它对于企业基础设施处理流数据非常有价值。此外,Kafka 通过 Kafka Connect 连接到外部系统(用于数据导入/导出),并提供 Kafka Streams,这是一个 Java 流处理库。
Credit: Official Website
可以把它想象成一个大的提交日志,数据按照发生的顺序存储在其中。该日志的用户可以根据自己的需要访问和使用它。
卡夫卡用例
卡夫卡的用途是多方面的。这里有几个用例可以帮助你理解它的用法。
- 活动监测:- Kafka 可以用于活动监测。该活动可能属于一个网站或物理传感器和设备。生产者可以发布来自数据源的原始数据,这些数据随后可用于发现趋势和模式。
- 消息传递:- 卡夫卡可以作为服务间的消息代理。如果您正在实现微服务架构,您可以将一个微服务作为生产者,将另一个微服务作为消费者。例如,您有一个微服务,负责创建新帐户,其他负责向用户发送有关帐户创建的电子邮件。
- 日志聚合:- 您可以使用 Kafka 从不同的系统收集日志,并存储在一个集中的系统中以供进一步处理。
- Kafka 有一个几乎实时流的特性,因此你可以根据自己的需要设计一个 ETL。
- 数据库:- 基于我上面提到的东西,你可能会说卡夫卡也充当数据库。这不是一个典型的数据库,它具有根据需要查询数据的功能,我的意思是,你可以在 Kafka 中保存数据,只要你想,而不用消耗它。
卡夫卡概念
让我们讨论卡夫卡的核心概念。
主题
馈入系统的每条消息都必须是某个主题的一部分。题目不过是一串记录。消息以键值格式存储。每条消息被分配一个序列,称为偏移。一个消息的输出可以是另一个消息的输入,以便进一步处理。
生产者
**制作者是负责将数据发布到 Kafka 系统的应用程序。他们根据自己选择的主题发布数据。
顾客
发布到主题中的消息然后被消费者应用利用。消费者订阅自己选择的主题并消费数据。
经纪人
负责消息交换的 Kafka 的每个实例被称为代理。Kafka 可以作为单机使用,也可以作为集群的一部分。
我试着用一个简单的例子来解释整个事情,有一个餐馆的仓库,所有的原材料都被倾倒在那里,比如大米、蔬菜等等。这家餐厅供应不同种类的菜肴:中国菜、德西菜、意大利菜等。每个菜系的厨师都可以参考仓库,挑选想要的东西,制作东西。有一种可能性是,用这种原料制成的东西以后可以被所有部门的厨师使用,例如,一些用于各种菜肴的秘制酱料。在这里,仓库是经纪人,货郎是生产者,厨师制作的商品和秘制酱料是话题而厨师是消费者。我的类比可能听起来很滑稽,也不准确,但至少它有助于你理解整件事:-)
设置和运行
安装 Kafka 最简单的方法是下载二进制文件并运行它。因为它是基于像 Scala 和 Java 这样的 JVM 语言,所以你必须确保你使用的是 Java 7 或更高版本。
卡夫卡有两种不同的版本:一种由 阿帕奇基金会 提供,另一种由 汇合 作为 包 。对于本教程,我将使用 Apache 基金会提供的教程。对了,合流是由卡夫卡的 原开发者 创立的。
启动动物园管理员
卡夫卡依赖于动物园管理员,为了让它运行,我们必须先运行动物园管理员。
bin/zookeeper-server-start.sh config/zookeeper.properties
它将在屏幕上显示大量文本,如果看到以下内容,这意味着它正常运行。
*2018-06-10 06:36:15,023] INFO maxSessionTimeout set to -1 (org.apache.zookeeper.server.ZooKeeperServer)
[2018-06-10 06:36:15,044] INFO binding to port 0.0.0.0/0.0.0.0:2181 (org.apache.zookeeper.server.NIOServerCnxnFactory)*
启动 Kafka 服务器
接下来,我们必须启动 Kafka 代理服务器:
bin/kafka-server-start.sh config/server.properties
如果您在控制台上看到以下文本,这意味着它已启动。
*2018-06-10 06:38:44,477] INFO Kafka commitId : fdcf75ea326b8e07 (org.apache.kafka.common.utils.AppInfoParser)
[2018-06-10 06:38:44,478] INFO [KafkaServer id=0] started (kafka.server.KafkaServer)*
创建主题
消息发布在主题中。使用此命令创建一个新主题。
*➜ kafka_2.11-1.1.0 bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
Created topic "test".*
您还可以通过运行以下命令列出所有可用的主题。
*➜ kafka_2.11-1.1.0 bin/kafka-topics.sh --list --zookeeper localhost:2181
test*
如你所见,它打印了,test
。
发送消息
接下来,我们必须发送消息,生产者用于该目的。让我们发起一个生产者。
*➜ kafka_2.11-1.1.0 bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test
>Hello
>World*
您启动基于控制台的生产者接口,默认情况下它运行在端口9092
上。--topic
允许您设置发布消息的主题。在我们的例子中,主题是test
它显示一个>
提示,你可以输入任何你想要的。
邮件存储在本地磁盘上。你可以通过检查config/server.properties
文件中log.dirs
的值来了解它的路径。默认情况下,它们被设置为/tmp/kafka-logs/
如果您列出这个文件夹,您会发现一个名为test-0
的文件夹。一旦列出,你会发现 3 个文件:00000000000000000000.index 00000000000000000000.log 00000000000000000000.timeindex
如果你在编辑器中打开00000000000000000000.log
,它会显示如下内容:
*^@^@^@^@^@^@^@^@^@^@^@=^@^@^@^@^BÐØR^V^@^@^@^@^@^@^@^@^Acça<9a>o^@^@^Acça<9a>oÿÿÿÿÿÿÿÿÿÿÿÿÿÿ^@^@^@^A^V^@^@^@^A
Hello^@^@^@^@^@^@^@^@^A^@^@^@=^@^@^@^@^BÉJ^B^@^@^@^@^@^@^@^@^Acça<9f>^?^@^@^Acça<9f>^?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ^@^@^@^A^V^@^@^@^A
World^@
~*
看起来像编码数据或分隔符分开,我不确定。如果有人知道这种格式,请告诉我。
不管怎样,Kafka 提供了一个实用程序,可以让您检查每个传入的消息。
*➜ kafka_2.11-1.1.0 bin/kafka-run-class.sh kafka.tools.DumpLogSegments --deep-iteration --print-data-log --files /tmp/kafka-logs/test-0/00000000000000000000.log
Dumping /tmp/kafka-logs/test-0/00000000000000000000.log
Starting offset: 0
offset: 0 position: 0 CreateTime: 1528595323503 isvalid: true keysize: -1 valuesize: 5 magic: 2 compresscodec: NONE producerId: -1 producerEpoch: -1 sequence: -1 isTransactional: false headerKeys: [] payload: Hello
offset: 1 position: 73 CreateTime: 1528595324799 isvalid: true keysize: -1 valuesize: 5 magic: 2 compresscodec: NONE producerId: -1 producerEpoch: -1 sequence: -1 isTransactional: false headerKeys: [] payload: World*
您可以看到带有其他详细信息的消息,如offset
、position
和CreateTime
等。
消费邮件
存储的消息也应该被消费。让我们开始一个基于控制台的消费者。
*➜ kafka_2.11-1.1.0 bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning*
如果您运行,它将转储从开始到现在的所有消息。如果您只是想在运行消费程序后消费消息,那么您可以省略--from-beginning
切换它并运行。它不显示旧消息的原因是,一旦消费者向 Kafka 代理发送关于处理消息的 ACK,偏移量就会更新。你可以看到下面的工作流程。
用 Python 访问卡夫卡
有多个 Python 库可供使用:
- Kafka-Python—一个开源的基于社区的图书馆。
- PyKafka —这个库由 Parsly 维护,它声称是一个 Pythonic API。与 Kafka-Python 不同,你不能创建动态主题。
在这篇文章中,我们将使用开源的 Kafka-Python 。
卡夫卡中的食谱提醒系统
在上一篇关于弹性搜索的 帖子 中,我搜集了所有的数据。在这篇文章中,我将使用相同的 scraper 作为数据源。我们要建立的系统是一个警报系统,如果达到一定的卡路里阈值,它将发送关于食谱的通知。将有两个主题:
- raw_recipes :-它将存储每个食谱的原始 HTML。这个想法是使用这个主题作为我们数据的主要来源,以后可以根据需要进行处理和转换。
- parsed_recipes:- 顾名思义,这将是 JSON 格式的每个食谱的解析数据。
卡夫卡题目名称长度不要超过 249 。
典型的工作流如下所示:
通过pip
安装kafka-python
pip install kafka-python
原料配方生产商
我们要写的第一个程序是制作人。它将访问 Allrecpies.com,获取原始 HTML 并存储在 raw_recipes 主题中。
这段代码将提取每个食谱的标记,并以list
格式返回。
接下来,我们要创建一个生产者对象。在我们继续之前,我们将对config/server.properties
文件进行修改。我们必须将advertised.listeners
设置为PLAINTEXT://localhost:9092
,否则您可能会遇到以下错误:
Error encountered when producing to broker b'adnans-mbp':9092\. Retrying.
我们现在将添加两个方法:connect_kafka_producer()
将为您提供 Kafka producer 的实例,而publish_message()
将只转储单个食谱的原始 HTML。
下面的__main__
会是什么样子:
*if __name__ == '__main__':
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36',
'Pragma': 'no-cache'
}all_recipes = get_recipes()
if len(all_recipes) > 0:
kafka_producer = connect_kafka_producer()
for recipe in all_recipes:
publish_message(kafka_producer, 'raw_recipes', 'raw', recipe.strip())
if kafka_producer is not None:
kafka_producer.close()*
如果运行良好,它会显示以下输出:
*/anaconda3/anaconda/bin/python /Development/DataScience/Kafka/kafka-recipie-alert/producer-raw-recipies.py
Accessing list
Processing..[https://www.allrecipes.com/recipe/20762/california-coleslaw/](https://www.allrecipes.com/recipe/20762/california-coleslaw/)
Processing..[https://www.allrecipes.com/recipe/8584/holiday-chicken-salad/](https://www.allrecipes.com/recipe/8584/holiday-chicken-salad/)
Processing..[https://www.allrecipes.com/recipe/80867/cran-broccoli-salad/](https://www.allrecipes.com/recipe/80867/cran-broccoli-salad/)
Message published successfully.
Message published successfully.
Message published successfully.Process finished with exit code 0*
我正在使用一个 GUI 工具,名为 Kafka Tool 来浏览最近发布的消息。它适用于 OSX、Windows 和 Linux。
KafkaToolKit in action
配方分析器
我们将要编写的下一个脚本将同时作为消费者和生产者。首先,它将消费来自raw_recipes
主题的数据,解析数据并将其转换成 JSON,然后在parsed_recipes
主题中发布。下面的代码将从raw_recipes
主题中获取 HTML 数据,解析后输入到parsed_recipes
主题中。
KafkaConsumer
除了主题名和主机地址之外,还接受一些参数。通过提供auto_offset_reset='earliest'
,你告诉卡夫卡从头开始返回信息。参数consumer_timeout_ms
有助于消费者在一段时间后断开连接。一旦断开连接,您可以通过调用consumer.close()
来关闭消费者流
在这之后,我使用相同的例程连接生产者并在新主题中发布解析的数据。 KafaTool 浏览器为新存储的消息带来喜讯。
到目前为止一切顺利。我们以 raw 和 JSON 两种格式存储食谱,以备后用。接下来,我们必须编写一个消费者,它将连接到parsed_recipes
主题,并在满足某些calories
标准时生成警报。
JSON 被解码,然后检查卡路里数,一旦符合标准就发出通知。
结论
Kafka 是一个可伸缩的、容错的、发布-订阅消息传递系统,使您能够构建分布式应用程序。由于其的高性能和高效率,它在那些从各种外部来源产生大量数据并希望从中提供实时发现的公司中越来越受欢迎。我刚刚谈到了它的要点。请仔细研究文档和现有的实现,它将帮助您理解它如何最适合您的下一个系统。
代码在 Github 上有。
本文原载 此处 。
点击 此处 订阅我的简讯以备日后发帖。
AutoML Vision alpha 入门
原文:https://towardsdatascience.com/getting-started-with-automl-vision-alpha-ba769121235c?source=collection_archive---------5-----------------------
May your path to machine learning be less twisted
我演讲时被问到的最多的事情之一是谷歌云自动化。让我们使用 AutoML Vision alpha 来构建和部署一个机器学习模型,该模型可以识别不同类型的椅子,以及一些其他项目。我们正在做所有的事情,从原始数据收集一直到为模型服务,以及中间的所有事情!
许多人一直嚷嚷着要访问 AutoML Vision alpha,我想对工作流程做一个简单的介绍,向您展示使用它的感觉,即使您还没有离开等待名单。在第一个视频中,我们将把数据转换成 AutoML Vision 的正确格式。然后在第二部分的中,我们将使用它建立一个模型来检测图片中的椅子是什么风格。让我们开始吧。
那么……什么是 AutoML?
Cloud Vision API can identify a chair, but it’s generic
AutoML 如此引人注目的原因之一是定制模型。像 Cloud Vision API 这样的现有模型和服务可以毫无问题地识别出一张给定的图片中可能有一把椅子,但是如果您设计并制造了椅子,并且需要一种方法来对库存中的各种品牌的椅子进行分类,该怎么办呢?可以说,如果能够使用一个“定制”视觉 API 来识别您的 特定椅子不是很好吗?这就是 AutoML Vision 的目标。
This is a yellow chair
Here are some more chairs 😃
AutoML Vision 将大量带标签的照片作为输入。你问多少张照片?理想情况下,每个对象数百个就不错了。所以走出去,开始拍照吧。如果你厌倦了点击快门按钮,你可以试试我一直在用的另一种方法。
用视频拍照!
为了更容易地为 AutoML Vision 捕获数据,我通过捕获我感兴趣的椅子的视频来收集我的训练数据,然后使用ffmpeg
来提取帧。
我去了谷歌桑尼维尔园区,拍了一些各种不同户外椅子的视频。我还拍了一些他们周围桌子的视频,还有一辆自行车,只是为了让事情更有趣一点。
让我们来看一个例子。
有不同形状、风格和颜色的椅子。没有视频长度超过 30 秒。我们有一张桌子的短片,还有一张自行车的短片。这就是我们将要处理的数据。
分割您的视频
我们想要的最终状态是一个 CSV 文件,每个图像有一行,两列,第一列是图像在 Google 云存储中的位置,第二列是标签,如“红椅子”、“桌子”或“蓝椅子”。
为了便于组织,我将每个视频放在了各自的文件夹中。然后我们可以依次对每个视频文件运行ffmpeg
。
提取帧后,每个标签都有一个文件夹,里面装满了该标签的图像。这是一种组织图片的便捷方式,比用一个巨大的文件夹存放所有图片要简单得多。
ffmpeg -i chair.mp4 chair%03d.jpg
(文件名中的%03d
会给我们 3 位数的填充编号,如chair003.jpg
、chair073.jpg
等。如果您有超过 999 张图像,您应该使用%04d
或其他合适的值)
接下来,我们可以使用gsutil
将图像上传到 Google 云存储,复制每个标签一个文件夹的文件夹结构:
gsutil -m cp -r all_data gs://cloudml-demo-vcm/dataset
(该命令递归复制/上传all_data
中的整个文件夹结构,并使用-m
对多个流进行复制/上传)
结构化您的数据
AutoML 需要一种方法来知道在哪里可以找到你所有的照片,以及每张照片中的对象。我们需要创建一个 CSV 文件,为我想要包含在数据集中的每张图像列出路径和标签。有许多方法可以实现这一点,但我选择了旋转本地 Jupyter 笔记本并创建一个熊猫数据帧以导出为 CSV 文件。让我们在下面的视频中浏览一下。
Looking for the code/notebook shown above? It’s here!
好了,现在我们有了一个 CSV 文件,它描述了数据集中所有图像的位置和标签。我们准备好训练我们的模型了!
这是你将图像加载到 AutoML Vision 后的样子。CSV 文件已经通知平台每个图像的正确标签是什么。如果您的图像还没有被标记,那也没关系——UI 中内置的工具可以帮助您完成标记过程,并显示哪些图像仍未被标记。
第 2 部分:培训和部署 AutoML Vision
训练模型
训练模型就像点击训练一样简单!这是我们一直在做的所有设置的要点。它使 AutoML Vision 能够获取数据,并在先进的图像模型上训练您的数据,并自动计算出适当的超参数,如网络结构。
但是在您尝试更高级的模型之前,我建议您先从简单的模型开始,看看它的性能如何。这将为您提供一个基线,您可以用它来比较其他模型的相对性能。
训练开始后,去散散步,或者抓一把 coffee☕.鉴于我们已经提供了这么多数据,这需要一点时间。
评估您的模型
一旦训练完成,您将获得关于您的模型的各种统计数据,您可以使用这些数据来查看它的表现,以及是否有一些图像被错误标记,或者其他方面值得纠正,然后再进行重新训练。
在我们的例子中,由于我们通过设计收集了非常具体、干净的数据,我们得到了一些非常高的指标。然而,真正重要的是它在新的、看不见的数据上的表现。
预测时间!
我拍了一些照片,试图挑战这个模型,看看它会返回什么。
让我们试试这张图片,它包含了自行车,以及黄色和蓝色的椅子。
好的,这张图片主要是自行车,但也有一点黄色和蓝色的椅子。它们在背景中,在这张照片中远没有那么突出。
让我们试试另一个。
这张图片大部分是黄色的椅子,但是也有一些蓝色的椅子。模特决定它主要看到黄色的椅子,和一点蓝色的椅子。
这张大部分是蓝色椅子的照片怎么样?
是的,这显示出大部分是蓝色的椅子,有一点桌子,有趣的是,有一点黄色的椅子,这不是预期的。不是所有的事情都是完美的,但是到目前为止,第一个选择已经被证明是相当好的。
最后,这张图片怎么样,和上一张非常相似,但是前面的椅子是黄色的?模特会怎么想?
哇,前景中的黄色椅子赢得了大奖!试图找出模型和数据集中的差距,以便更好地理解如何根据您的用例收集更可靠、更有代表性的数据,这可能是一件非常有趣的事情。
包扎
值得指出的是,在这一点上,模型可以通过它的 REST API 来调用。该服务利用 Cloud ML Engine 的在线预测功能来提供一个定制的、自动缩放的预测服务,,并在我们的数据集上进行训练。
You can call your service via REST API from any server or internet-connected device
所有这一切的巧妙之处在于,一旦你的数据管道都设计好了,训练和部署机器学习模型的过程就完全不用动手了!这使您可以专注于让您的数据处于良好状态,并摆脱构建合适的计算机视觉机器学习模型的挑战。
Notice the annotation “AutoDeployed” below the model name
现在,如果你不介意的话,我要去拍一些彩色椅子的视频,这样我就可以为我的 AutoML 视觉模型扩展我的数据集了!
快乐 p̵i̵c̵t̵u̵r̵e̵ 视频-拍摄和汽车视觉模型训练!
感谢阅读本集云 AI 冒险。如果你喜欢这个系列,请为这篇文章鼓掌让我知道。如果你想要更多的机器学习动作,一定要关注媒体上的me或订阅 YouTube 频道的来观看未来的剧集。更多剧集即将推出!
如果你还在读这篇文章,我希望收到你的来信!你有什么样的问题?你希望这个系列探索什么主题?有什么推荐的工具、技巧和窍门可以尝试吗?在下面的评论中分享吧!
Python 中的 Elasticsearch 入门
原文:https://towardsdatascience.com/getting-started-with-elasticsearch-in-python-c3598e718380?source=collection_archive---------0-----------------------
Image Credit: tryolabs.com
此贴为 Elasticsearch 7.x 更新版本 此处 。
在这篇文章中,我将讨论 Elasticsearch 以及如何将它与不同的 Python 应用程序集成。
什么是 ElasticSearch?
ElasticSearch (ES)是一个高度可用的分布式开源搜索引擎,构建在 Apache Lucene 之上。它是用 Java 构建的开源软件,因此适用于许多平台。你以 JSON 格式存储非结构化数据,这也使它成为一个 NoSQL 数据库。因此,与其他 NoSQL 数据库不同,es 还提供搜索引擎功能和其他相关功能。
弹性搜索用例
您可以将 ES 用于多种目的,下面给出了其中的几种:
- 你正在运营一个提供大量动态内容的网站;无论是电子商务网站还是博客。通过实现 ES,你不仅可以为你的 web 应用提供一个强大的搜索引擎,还可以在你的应用中提供原生的自动完成功能。
- 您可以接收不同种类的日志数据,然后使用来查找趋势和统计数据。
设置和运行
安装 ElasticSearch 最简单的方法就是 下载 并运行可执行文件。您必须确保您使用的是 Java 7 或更高版本。
下载后,解压并运行它的二进制文件。
elasticsearch-6.2.4 bin/elasticsearch
滚动窗口中会有大量文本。如果你看到下面这样的东西,那么它似乎是向上的。
[2018-05-27T17:36:11,744][INFO ][o.e.h.n.Netty4HttpServerTransport] [c6hEGv4] publish_address {127.0.0.1:9200}, bound_addresses {[::1]:9200}, {127.0.0.1:9200}
但是,因为,眼见为实,在你的浏览器中或通过 cURL 访问 URL http://localhost:9200
,像下面这样的东西应该会欢迎你。
{
"name" : "c6hEGv4",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "HkRyTYXvSkGvkvHX2Q1-oQ",
"version" : {
"number" : "6.2.4",
"build_hash" : "ccec39f",
"build_date" : "2018-04-12T20:37:28.497551Z",
"build_snapshot" : false,
"lucene_version" : "7.2.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
现在,在我开始用 Python 访问弹性搜索之前,让我们做一些基本的事情。正如我提到的,ES 提供了一个 REST API ,我们将使用它来执行不同的任务。
基本示例
你要做的第一件事就是创建一个索引。一切都存储在索引中。与索引相对应的 RDBMS 是一个数据库,所以不要把它与你在 RDBMS 中学到的典型索引概念相混淆。我正在使用 PostMan 来运行 REST APIs。
如果运行成功,您将会看到类似下面的响应。
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "company"
}
所以我们创建了一个名为 company 的数据库。换句话说,我们创建了一个名为公司的指数。如果您从浏览器访问http://localhost:9200/company
,您将看到如下内容:
{
"company": {
"aliases": {
},
"mappings": {
},
"settings": {
"index": {
"creation_date": "1527638692850",
"number_of_shards": "5",
"number_of_replicas": "1",
"uuid": "RnT-gXISSxKchyowgjZOkQ",
"version": {
"created": "6020499"
},
"provided_name": "company"
}
}
}
}
暂时忽略mappings
,我们稍后会讨论它。它实际上只是为您的文档创建一个模式。creation_date
不言自明。number_of_shards
告知将保存该索引的数据的分区数量。将全部数据保存在一个磁盘上毫无意义。如果您正在运行一个由多个弹性节点组成的集群,那么整个数据将在这些节点上进行拆分。简而言之,如果有 5 个分片,那么整个数据在 5 个分片上都是可用的,ElasticSearch 集群可以为来自任何节点的请求提供服务。
副本讨论数据的镜像。如果你熟悉主从概念,那么这对你来说应该不陌生。你可以在这里 了解更多 ES 基本概念 。
创建索引的 cURL 版本是一行程序。
➜ elasticsearch-6.2.4 curl -X PUT localhost:9200/company
{"acknowledged":true,"shards_acknowledged":true,"index":"company"}%
您还可以一次完成索引创建和记录插入任务。你所要做的就是以 JSON 格式传递你的记录。你可以在邮差里看到类似下面的东西。
确保将Content-Type
设置为application/json
它将在这里创建一个名为company
的索引,如果它不存在,然后在这里创建一个名为 employees 的新的类型。Type 实际上是 RDBMS 中一个表的 ES 版本。
上述请求将输出以下 JSON 结构。
{
"_index": "company",
"_type": "employees",
"_id": "1",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
你通过/1
作为你的记录的 ID。但是这不是必须的。它所做的只是用值1
设置_id
字段。然后以 JSON 格式传递数据,这些数据最终将作为新记录或文档插入。如果你从浏览器访问http://localhost:9200/company/employees/1
,你会看到如下内容。
{"_index":"company","_type":"employees","_id":"1","_version":1,"found":true,"_source":{
"name": "Adnan Siddiqi",
"occupation": "Consultant"
}}
您可以看到实际记录和元数据。如果您愿意,您可以将请求更改为http://localhost:9200/company/employees/1/_source
,它将只输出记录的 JSON 结构。
cURL 版本应该是:
➜ elasticsearch-6.2.4 curl -X POST \
> [http://localhost:9200/company/employees/1](http://localhost:9200/company/employees/1) \
> -H 'content-type: application/json' \
> -d '{
quote> "name": "Adnan Siddiqi",
quote> "occupation": "Consultant"
quote> }'
{"_index":"company","_type":"employees","_id":"1","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1}%
如果您想更新记录,该怎么办?嗯,这很简单。你所要做的就是改变你的 JSON 记录。如下图所示:
它将生成以下输出:
{
"_index": "company",
"_type": "employees",
"_id": "1",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
注意_result
字段现在被设置为updated
而不是created
当然,你也可以删除某些记录。
如果你快疯了,或者你的女朋友/男朋友把你甩了,你可以从命令行运行curl -XDELETE localhost:9200/_all
烧掉整个世界。
让我们做一些基本的搜索。如果运行http://localhost:9200/company/employees/_search?q=adnan
,它将搜索类型employees
下的所有字段,并返回相关记录。
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.2876821,
"hits": [
{
"_index": "company",
"_type": "employees",
"_id": "1",
"_score": 0.2876821,
"_source": {
"name": "Adnan Siddiqi",
"occupation": "Software Consultant"
}
}
]
}
}
max_score
字段告诉记录的相关程度,即记录的最高分。如果有多条记录,那么它会是一个不同的数字。
还可以通过传递字段名将搜索条件限制在某个字段。因此,http://localhost:9200/company/employees/_search?q=name:Adnan
将只在文档的name
字段中搜索。它实际上是SELECT * from table where name='Adnan'
的 SQL 等价物
我只是介绍了一些基本的例子。ES 可以做很多事情,但是我将让您通过阅读文档来进一步探索它,并将切换到用 Python 访问 ES。
用 Python 访问 ElasticSearch
老实说,ES 的 REST APIs 已经足够好了,你可以使用requests
库来执行你所有的任务。尽管如此,你还是可以使用一个 Python 库 来进行 ElasticSearch,从而专注于你的主要任务,而不是担心如何创建请求。
通过 pip 安装它,然后你可以在你的 Python 程序中访问它。
pip install elasticsearch
要确保安装正确,请从命令行运行以下基本代码片段:
➜ elasticsearch-6.2.4 python
Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 12:04:33)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from elasticsearch import Elasticsearch
>>> es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
>>> es
<Elasticsearch([{'host': 'localhost', 'port': 9200}])>
网页抓取和弹性搜索
我们来讨论一个使用 Elasticsearch 的小实际用例。目标是访问在线食谱,并将其存储在 Elasticsearch 中,以用于搜索和分析目的。我们将首先从 Allrecipes 中抓取数据,并将其存储在 es 中。在 ES 的情况下,我们还将创建一个严格的模式或映射,这样我们可以确保数据以正确的格式和类型被索引。我只是调出沙拉食谱的清单。我们开始吧!
抓取数据
import json
from time import sleepimport requests
from bs4 import BeautifulSoupdef parse(u):
title = '-'
submit_by = '-'
description = '-'
calories = 0
ingredients = []
rec = {}try:
r = requests.get(u, headers=headers)if r.status_code == 200:
html = r.text
soup = BeautifulSoup(html, 'lxml')
# title
title_section = soup.select('.recipe-summary__h1')
# submitter
submitter_section = soup.select('.submitter__name')
# description
description_section = soup.select('.submitter__description')
# ingredients
ingredients_section = soup.select('.recipe-ingred_txt')# calories
calories_section = soup.select('.calorie-count')
if calories_section:
calories = calories_section[0].text.replace('cals', '').strip()if ingredients_section:
for ingredient in ingredients_section:
ingredient_text = ingredient.text.strip()
if 'Add all ingredients to list' not in ingredient_text and ingredient_text != '':
ingredients.append({'step': ingredient.text.strip()})if description_section:
description = description_section[0].text.strip().replace('"', '')if submitter_section:
submit_by = submitter_section[0].text.strip()if title_section:
title = title_section[0].textrec = {'title': title, 'submitter': submit_by, 'description': description, 'calories': calories,
'ingredients': ingredients}
except Exception as ex:
print('Exception while parsing')
print(str(ex))
finally:
return json.dumps(rec)if __name__ == '__main__':
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36',
'Pragma': 'no-cache'
}
url = '[https://www.allrecipes.com/recipes/96/salad/'](https://www.allrecipes.com/recipes/96/salad/')
r = requests.get(url, headers=headers)
if r.status_code == 200:
html = r.text
soup = BeautifulSoup(html, 'lxml')
links = soup.select('.fixed-recipe-card__h3 a')
for link in links:
sleep(2)
result = parse(link['href'])
print(result)
print('=================================')
这是拉取数据的基本程序。由于我们需要 JSON 格式的数据,因此,我相应地转换了它。
创建索引
好了,我们得到了想要的数据,我们必须存储它。我们要做的第一件事就是创建一个索引。姑且称之为食谱。这种沙拉将被称为。我要做的另一件事是为我们的文档结构创建一个映射。
在我们创建索引之前,我们必须连接 ElasticSearch 服务器。
*import logging
def connect_elasticsearch():
_es = None
_es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
if _es.ping():
print('Yay Connect')
else:
print('Awww it could not connect!')
return _esif __name__ == '__main__':
logging.basicConfig(level=logging.ERROR)*
_es.ping()
实际上 pings 服务器,如果连接上了就返回True
。我花了一段时间想出如何捕捉堆栈跟踪, 发现 ou t 它刚刚被记录!
*def create_index(es_object, index_name='recipes'):
created = False
# index settings
settings = {
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"members": {
"dynamic": "strict",
"properties": {
"title": {
"type": "text"
},
"submitter": {
"type": "text"
},
"description": {
"type": "text"
},
"calories": {
"type": "integer"
},
}
}
}
}try:
if not es_object.indices.exists(index_name):
# Ignore 400 means to ignore "Index Already Exist" error.
es_object.indices.create(index=index_name, ignore=400, body=settings)
print('Created Index')
created = True
except Exception as ex:
print(str(ex))
finally:
return created*
这里发生了很多事情。首先,我们传递了一个包含整个文档结构映射的配置变量。 映射 是弹性图式的术语。就像我们在表中设置某些字段数据类型一样,我们在这里做一些类似的事情。检查文件,它涵盖了更多。所有字段的类型都是text
,但calories
的类型是Integer
接下来,我将确保该索引根本不存在,然后创建它。检查后不再需要参数ignore=400
,但如果您不检查是否存在,您可以抑制错误并覆盖现有索引。尽管这很冒险。就像覆盖数据库一样。
如果索引创建成功,您可以通过访问http://localhost:9200/recipes/_ mappings来验证它,它将打印出如下内容:
*{
"recipes": {
"mappings": {
"salads": {
"dynamic": "strict",
"properties": {
"calories": {
"type": "integer"
},
"description": {
"type": "text"
},
"submitter": {
"type": "text"
},
"title": {
"type": "text"
}
}
}
}
}
}*
通过传递dynamic:strict
,我们迫使 Elasticsearch 对任何传入的文档进行严格检查。这里,salads
实际上是文档类型。Type
实际上是 Elasticsearch 对 RDBMS 表的回答。
记录索引
下一步是存储实际的数据或文档。
*def store_record(elastic_object, index_name, record):
try:
outcome = elastic_object.index(index=index_name, doc_type='salads', body=record)
except Exception as ex:
print('Error in indexing data')
print(str(ex))*
运行它,您将受到以下欢迎:
*Error in indexing data
TransportError(400, 'strict_dynamic_mapping_exception', 'mapping set to strict, dynamic introduction of [ingredients] within [salads] is not allowed')*
你能猜到为什么会这样吗?由于我们没有在映射中设置ingredients
,ES 不允许我们存储包含ingredients
字段的文档。现在您知道了首先分配一个映射的好处。这样做可以避免损坏数据。现在,让我们改变映射一点,现在它将看起来如下:
*"mappings": {
"salads": {
"dynamic": "strict",
"properties": {
"title": {
"type": "text"
},
"submitter": {
"type": "text"
},
"description": {
"type": "text"
},
"calories": {
"type": "integer"
},
"ingredients": {
"type": "nested",
"properties": {
"step": {"type": "text"}
}
},
}
}
}*
我们添加了类型为nested
的ingrdients
,然后分配了内部字段的数据类型。在我们的例子中是text
嵌套 数据类型允许您设置嵌套 JSON 对象的类型。再次运行它,您将看到以下输出:
*{
'_index': 'recipes',
'_type': 'salads',
'_id': 'OvL7s2MBaBpTDjqIPY4m',
'_version': 1,
'result': 'created',
'_shards': {
'total': 1,
'successful': 1,
'failed': 0
},
'_seq_no': 0,
'_primary_term': 1
}*
由于您根本没有通过_id
,ES 本身为存储的文档分配了一个动态 id。我用 Chrome,我用 ES data viewer 借助一个叫 ElasticSearch 工具箱 的工具查看数据。
在我们继续之前,让我们在calories
字段中发送一个字符串,看看情况如何。记得我们把它设定为integer
。建立索引时,它给出了以下错误:
TransportError(400, 'mapper_parsing_exception', 'failed to parse [calories]')
现在您知道了为文档分配映射的好处。如果不这样做,它仍然会工作,因为 Elasticsearch 会在运行时分配自己的映射。
查询记录
现在,记录被索引,是时候根据我们的需要查询它们了。我将创建一个名为search()
的函数,它将显示我们的查询结果。
*def search(es_object, index_name, search):
res = es_object.search(index=index_name, body=search)*
这是非常基本的。您在其中传递索引和搜索标准。让我们尝试一些查询。
*if __name__ == '__main__':
es = connect_elasticsearch()
if es is not None:
search_object = {'query': {'match': {'calories': '102'}}}
search(es, 'recipes', json.dumps(search_object))*
上述查询将返回所有calories
等于 102 的记录。在我们的例子中,输出将是:
*{'_shards': {'failed': 0, 'skipped': 0, 'successful': 1, 'total': 1},
'hits': {'hits': [{'_id': 'YkTAuGMBzBKRviZYEDdu',
'_index': 'recipes',
'_score': 1.0,
'_source': {'calories': '102',
'description': "I've been making variations of "
'this salad for years. I '
'recently learned how to '
'massage the kale and it makes '
'a huge difference. I had a '
'friend ask for my recipe and I '
"realized I don't have one. "
'This is my first attempt at '
'writing a recipe, so please '
'let me know how it works out! '
'I like to change up the '
'ingredients: sometimes a pear '
'instead of an apple, '
'cranberries instead of '
'currants, Parmesan instead of '
'feta, etc. Great as a side '
'dish or by itself the next day '
'for lunch!',
'ingredients': [{'step': '1 bunch kale, large '
'stems discarded, '
'leaves finely '
'chopped'},
{'step': '1/2 teaspoon salt'},
{'step': '1 tablespoon apple '
'cider vinegar'},
{'step': '1 apple, diced'},
{'step': '1/3 cup feta cheese'},
{'step': '1/4 cup currants'},
{'step': '1/4 cup toasted pine '
'nuts'}],
'submitter': 'Leslie',
'title': 'Kale and Feta Salad'},
'_type': 'salads'}],
'max_score': 1.0,
'total': 1},
'timed_out': False,
'took': 2}*
如果您想获得大于 20 的记录呢?
search_object = {'_source': ['title'], 'query': {'range': {'calories': {'gte': 20}}}}
您还可以指定要返回的列或字段。上述查询将返回卡路里大于 20 的所有记录。此外,它将只在_source
下显示title
字段。
结论
Elasticsearch 是一款功能强大的工具,通过提供强大的功能来返回最准确的结果集,可以帮助您搜索现有或新的应用程序。我刚刚谈到了它的要点。一定要阅读文档,熟悉这个强大的工具。尤其是模糊搜索功能相当牛逼。如果有机会,我会在以后的帖子中讨论查询 DSL。
像往常一样,代码可以在 Github 上获得。
本文原载 这里 。
点击 此处 订阅我的简讯以备日后发帖。
AWS 中的 Fast.ai MOOC 入门
原文:https://towardsdatascience.com/getting-started-with-fast-ai-mooc-in-aws-d2ffcd65c7b0?source=collection_archive---------1-----------------------
Fast.ai 提供深度学习课程系列。程序由杰瑞米·霍华德教授。有一个入门页面跟随说明。然而,安装对我来说并不容易。我想分享一些我遇到的问题和解决方法。
首先,我打开了这个教学视频。我的计划是试图模仿教练。p2 类型实例不能立即使用,您需要从 AWS 请求它。AWS 的返回需要时间,所以可以在这段时间内使用 t2 类型的实例。让我们回到我们的电脑,我们需要用 Python 2.7 安装Anaconda和 Cygwin 。教学视频会警告你与 wget 有关。这是我的第一个暗示。你也应该小心宋承宪。你应该选择 openssh 和而不是跳过安装。如果跳过,您会在连接实例的最后一步收到以下消息:
-bash: ssh:找不到命令
如果你跳过它,你应该可以找到你几分钟前安装的安装文件。重复前面的点击,并选择 openssh 软件包和安装。在这些操作中不需要关闭终端。
好了,我们把视频调回来。安装 Cygwin 后,我们将在 AWS 控制台中创建一个用户。重点是赋予管理员权限和保存访问密钥 id 和密钥的凭证。他们需要连接我们的实例。
此后,我们跳到 Cygwin 并写道:
pip 安装 awscli
一切都是好的,但不要被愚弄。下一步可能是这样的:
c:\ Users \ serdar \ anaconda 2 \ python . exe:无法打开文件
[错误 2]没有这样的文件或目录
这个问题有一个解决页面。然而这并没有帮助我。我的解决方案来自这里。用 python 位置的路径更新 bash_profile 让我很开心。
$ echo " PATH = \ $ PATH:/cyg drive/c/python 27 " > >。bash_profile
$ source。bash_profile
好的。就是这样。AWS 配置目前可用。输入您之前保存的凭据、选定的区域和输出格式。现在我们需要通过脚本启动现成的实例。这里链接到。关键是使用原始代码链接。t2 的示例:
https://raw . githubusercontent . com/fastai/courses/master/setup/setup _ T2 . sh
通过使用 wget,我们可以得到它,例如,键入:
bash setup_t2.sh
将设置我们的实例。
安装完成后,它将打印连接信息。请注意这些信息。我的 ssh 问题是看到这一点。您将使用“ssh -l”和连接地址。终于,你进来了!你可以打开 Jupyter,通过你电脑的浏览器用“实例的 DNS:8888”连接。为了你的预算,不要忘记在完成工作后停止你的实例。祝你 MOOC 愉快..
使用 pandas 和 networkx 开始使用 Python 进行图表分析
原文:https://towardsdatascience.com/getting-started-with-graph-analysis-in-python-with-pandas-and-networkx-5e2d2f82f18e?source=collection_archive---------2-----------------------
图表分析并不是数据科学的一个新分支,但也不是数据科学家如今常用的“常用”方法。然而,图表可以做一些疯狂的事情。经典的使用案例包括欺诈检测、推荐或社交网络分析。NLP 中的一个非经典用例处理主题抽取(词图)。
visualisation of a graph-of-words, where each community represent a different topic
考虑一个欺诈检测用例
你有一个客户数据库,并且想知道他们是如何相互联系的。特别是,您知道有些客户涉及复杂的欺诈结构,但在个人层面上可视化数据并不会带来欺诈的证据。诈骗犯看起来和其他普通客户一样。
处理用户之间的联系可以显示出比仅仅通过查看原始数据更多的信息。具体而言,对于通常的基于机器学习的评分模型来说不被认为有风险的特征(电话号码、电子邮件地址、家庭地址)可以在基于图形的评分模型中变成有风险的特征。
例:三个电话号码相同的人,连接到其他电子邮件地址相同的人是不寻常的,有潜在的风险。电话号码的价值本身并不提供任何信息(因此,即使是最好的深度学习模型也不会从中获取任何价值),但个人通过电话号码或电子邮件地址的相同价值联系在一起的事实可能是风险的同义词。
让我们用 Python 来做这件事。
设置数据、清理和创建我们的图表
This will be our simulated user database
所以你从熊猫数据框架开始(这基本上是 Python 中的一个 Excel 表格)
好的,数据被载入 df 。现在,做些准备。您需要连接拥有相同电话号码和相同电子邮件的个人(由他们的 ID 表示)。我们首先从电话号码开始:
我们的数据看起来像这样:
好吧,我们有一些联系,但是有两个问题:
- 个人与他们自己联系在一起
- 当 X 与 Y 相连时,那么 Y 也与 X 相连,我们有两行相同的连接
让我们来清理一下:
我们的数据现在看起来像这样:
太好了,1 和 3 连在一起了,5 和 6 也是。我们对电子邮件地址也做了同样的处理(完整的代码在文章的最后分享)。现在让我们建立一个图表。我在这里只分享简单的代码部分,因为添加不同的链接类型有点棘手。
现在让我们可视化我们的数据。
使用 networkx 实现图形可视化
简单的 nx.draw(G) 给了我们以下内容:
Wooo 挺有意思的图案!但是等等,我们看不到个体是谁,有什么联系。让我们自定义它:
接得好。4 个人通过 2 个不同的电话号码和 1 个电子邮件地址联系在一起…接下来应该会有更多的调查!
真正工业化的下一步
让我们回顾一下我们所做的工作:
- 从我们的用户数据库创建一个图表
- 帮助我们看到奇怪模式的自定义可视化
如果你受业务驱动,并希望一些专家使用你所做的,你的下一个重点应该是:
- 自动执行寻找多名相关人员的过程,或危险模式检测
- 自动化创建可视化效果和创建带有图形可视化效果和原始数据的定制仪表板的过程
我不会在此详述,但会给你一些如何进行这两个步骤的想法
1.危险模式检测
这里有两种方法:
- 从您认为有风险的个人(或您发现的欺诈者)开始,检查他们与其他个人的关系。联系到机器学习,这将是一种“监督”的方法。为了更进一步,你还可以从机器学习评分开始,识别得分最高的节点,并在图中寻找它们的连接,以捕捉更多的节点
- 识别不寻常的模式(过多的连接、密集的网络……)。这将是类似于异常/异常值检测的“无监督”方法
在我们的示例中,我们没有已知的欺诈者,因此我们将采用第二种方法。
Networkx 已经实现了这样的算法:度(),中心性(), pagerank (), connected_components ()…我让您定义如何用数学方法定义风险。
2.为业务创建可视化和自动化分析
对于大多数数据科学家来说,这听起来很老套,但是在 Excel 中有一种快速的方法。
xlsxwriter 包帮助您粘贴风险人物图表中的数据,并将我们创建的图表图像直接粘贴到 Excel 文件中。您将获得每个风险网络的仪表板,如下所示:
对于每个有潜在风险的网络,您可以自动创建仪表板,将其发送给专家,让他们评估/确认风险。您可以在仪表板中添加一些指标:涉及的人数,不同电话号码的数量,电子邮件地址,每个节点的 ML 分数…
我希望这篇文章对你有用,如果有用,考虑至少给 50 次掌声:)
和往常一样,源代码
Hive 入门
原文:https://towardsdatascience.com/getting-started-with-hive-ad8a93862f1a?source=collection_archive---------5-----------------------
[Image [0] (Image courtesy: https://wall.alphacoders.com/big.php?i=380565)]
这篇博文的目的是帮助你开始使用 Cloudera Manager 使用 Hive。 Apache Hive 是一个数据仓库软件项目,构建在 Apache Hadoop 之上,用于提供数据汇总、查询和分析。Hive 给出了一个类似于 SQL 的接口来查询存储在与 Hadoop 集成的各种数据库和文件系统中的数据。
如果你对 R 编程感兴趣,可以看看我的其他文章——利用 R 和gg plot ' Em All | Pokemon on R对 FIFA 18 数据集的探索性分析。
我们将首先从莎士比亚开始,通过实现一个简单的字数统计程序来理解工作流程。然后,我们将移动到 MovieLens 数据,并使用 HQL 执行查询。
启动您的 Cloudera 虚拟机。去你的ip:7180.
Cloudera Manager Console [Image [1]]
我们将使用 Hdfs、Hive 和 Yarn。因此,请确保它们正在运行。
现在,我们必须创建一个目录来存储我们将在其上运行 wordcount 程序的输入文件。
# to view the contents of the root directory on HDFS
hdfs dfs -ls /# create a new directory named 'input' in the HDFS
hdfs dfs -mkdir /input
您将看到权限被拒绝,因为 hdfs 用户拥有超级用户(root)权限。我们将在本文后面看到如何对此进行排序。
Permission denied [Image [2]]
现在,下载要进行字数统计的文本文件。我们将使用莎士比亚的作品。下载并解压文件。里面有五个文件。我们今天将使用喜剧文件。
Shakespeare [Image [3]]
我们在本地文件系统中有喜剧文件。我们需要将它转移到/input
文件夹中的 hdfs 中。在此之前,我们需要给我们的根用户添加一个文件到/input
文件夹的权限。
# Give the su permission to root-user
hdfs dfs -chown root:root /input
hdfs dfs -ls /
root 用户现在对 /input
文件夹拥有超级用户权限。
回到根用户的状态。
exit
Chown [Image [4]]
编写一个 SQL 文件来执行字数统计。另存为wordcount.sql
。
DROP DATABASE IF EXISTS documents CASCADE;CREATE DATABASE documents;USE documents;CREATE TABLE docs(words string);LOAD DATA LOCAL INPATH '/root/shakespeare' INTO TABLE docs;CREATE TABLE word_count AS
SELECT word, count(*) AS count FROM
(SELECT explode(split(words, '\\W+')) AS word FROM docs) w
GROUP BY word;SELECT * FROM word_count limit 100;
我们需要对/shakespeare
目录的读写权限来运行wordcount.sql
程序。成为 hdfs 用户并输入以下命令。
su - hdfs # Change user to hdfs from roothdfs dfs -chmod -R 777 /shakespeareexit
现在,作为 root 用户,运行以下命令:
hive -f wordcount.sql
Execute Word Count program [Image [5]]
您应该会看到如下所示的输出。
Output [Image [6]]
接下来,我们将尝试在 MovieLens 数据集上运行 Hive 查询。
下载文件。当您看到前几行时,您会注意到该文件由::
分隔。将分隔符改为,
(csv)。
sed -i 's/::/,/g' ml-1m/movies.dat
sed -i 's/::/,/g' ml-1m/users.dat
sed -i 's/::/,/g' ml-1m/ratings.dat# Rename the files from .dat to .csv. Although, it doesn't really # matter. You can leave the files as .dat. I have OCD.mv ml-1m/movies.dat /ml-1m/movies.csv
mv ml-1m/ratings.dat /ml-1m/ratings.csv
mv ml-1m/users.dat /ml-1m/users.csv
MovieLens data [Image [7]]
在 hdfs 中创建一个名为movielens
的文件夹,并将文件移入其中。
File in hdfs [Image [8]]
作为 hdfs 用户,创建以下文件movies.sql
、ratings.sql
和users.sql
。
su - hdfs
nano movies.sql
nano ratings.sql
nano users.sql
要查看movies.csv
文件中的数据,在movies.sql
文件中复制以下代码并运行命令hive -f movies.sql
。
DROP DATABASE IF EXISTS movielens CASCADE;CREATE DATABASE movielens;USE movielens;CREATE EXTERNAL TABLE movies (MovieID INT,
Title varchar(60),
Genres varchar(60))ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LINES TERMINATED BY "\n"
STORED AS TEXTFILE
LOCATION '/movielens/ml-1m/mvs.txt';LOAD DATA INPATH '/movielens/ml-1m/movies.csv' INTO TABLE movies;SELECT * FROM movies LIMIT 10;
First 10 entries in the movies.csv [Image [9]]
要查看ratings.csv
文件中的数据,在ratings.sql
文件中复制以下代码并运行命令hive -f ratings.sql
。
DROP DATABASE IF EXISTS movielens CASCADE;CREATE DATABASE movielens;USE movielens;CREATE EXTERNAL TABLE ratings (UserID INT,
MovieID INT,
Rating INT,
Timestamp STRING)ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LINES TERMINATED BY "\n"
STORED AS TEXTFILE
LOCATION '/movielens/ml-1m/rts.txt';LOAD DATA INPATH '/movielens/ml-1m/ratings.csv' INTO TABLE ratings;SELECT * FROM ratings LIMIT 10;
First 10 entries in ratings.csv [Image [10]]
要查看users.csv
文件中的数据,在users.sql
文件中复制以下代码并运行命令hive -f users.sql
。
DROP DATABASE IF EXISTS movielens CASCADE;CREATE DATABASE movielens;USE movielens;CREATE EXTERNAL TABLE users (UserID INT,
Gender STRING,
Age INT,
Occupation INT,
ZIP INT)ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LINES TERMINATED BY "\n"
STORED AS TEXTFILE
LOCATION '/movielens/ml-1m/usr.txt';LOAD DATA INPATH '/movielens/ml-1m/users.csv' INTO TABLE users;SELECT * FROM users LIMIT 10;
First 10 entries in users.csv [Image [11]]
十大热门电影。
DROP DATABASE IF EXISTS movielens CASCADE;CREATE DATABASE movielens;USE movielens;CREATE EXTERNAL TABLE movies (MovieID INT,
Title varchar(60),
Genres varchar(60))ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LINES TERMINATED BY "\n";CREATE EXTERNAL TABLE ratings (UserID INT,
MovieID INT,
Rating INT,
Timestamp STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LINES TERMINATED BY "\n";LOAD DATA INPATH '/movielens/ml-1m/movies.csv'
OVERWRITE INTO TABLE movies;LOAD DATA INPATH '/movielens/ml-1m/ratings.csv'
OVERWRITE INTO TABLE ratings;SELECT movies.MovieID,movies.Title,COUNT(DISTINCT ratings.UserID) as views
FROM movies JOIN ratings ON (movies.MovieID = ratings.MovieID)
GROUP BY movies.MovieID, movies.Title
ORDER BY views DESC
LIMIT 10;
Top 10 viewed movies [Image [12]]
收视率最高的 20 部电影至少有 40 次观看。
DROP DATABASE IF EXISTS movielens CASCADE;CREATE DATABASE movielens;USE movielens;CREATE EXTERNAL TABLE movies (MovieID INT,
Title varchar(60),
Genres varchar(60))ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LINES TERMINATED BY "\n";CREATE EXTERNAL TABLE ratings (UserID INT,
MovieID INT,
Rating INT,
Timestamp STRING)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY "\n";LOAD DATA INPATH '/movielens/ml-1m/movies.csv' OVERWRITE INTO TABLE movies;LOAD DATA INPATH '/movielens/ml-1m/ratings.csv' OVERWRITE INTO TABLE ratings;SELECT movies.MovieID,movies.Title,AVG(ratings.Rating) as rtg,COUNT(DISTINCT ratings.UserID) as viewsFROM movies JOIN ratings ON (movies.MovieID = ratings.MovieID)
GROUP BY movies.MovieID,movies.Title
HAVING views >= 40
ORDER BY rtg DESC
LIMIT 20;
Top 20 rated movies. [Image [13]]
感谢您的阅读。希望您发现它对开始使用 Hive 很有用。欢迎提出建议和建设性的批评。:)你可以在 LinkedIn 和 Twitter 上找到我。
点击这里查看我的其他博客。
英特尔 Movidius 入门
原文:https://towardsdatascience.com/getting-started-with-intel-movidius-d8ba13e7d3ae?source=collection_archive---------2-----------------------
英特尔 Movidius 是一款有趣的硬件,可以在类似 Raspberry Pi 的嵌入式系统上工作,支持神经网络计算。即使 think 只在 Linux 下受支持,我们也可以使用 Oracle Virtual Box 让它在 Mac 或 Windows 平台上工作。
英特尔 Movidius 还支持 Caffe 和 TensorFlow 模型,典型的工作流程如下
Typical Intel Movidius workflow (Image courtesy: https://movidius.github.io/ncsdk/)
完整文档可从英特尔 Movidius NCSDK[1]获得
在这篇文章中,我将重点介绍如何使用 Ubuntu 16.x 变体在 Oracle Virtual Box 和 Rapsberry Pi 3 Model B 环境上入门。
Oracle 虚拟机箱
从 Oracle Virtual Box 下载[2]并安装扩展包。
在安装 Ubuntu 16.x 之前,配置/添加以下 USB 设备。请注意,英特尔 Movidius 有两种模式,因此需要两种不同的设备配置
配置 1
名称:Movidius VSC 环回设备【0100】
厂商 ID : 03e7
产品 ID : f63b
版本:0100
制造商:Movidius
产品:VSC 环回设备配置 2
名称:m ovidius ltd . Movidius MA2X5X[0001]
厂商 ID : 03e7
产品 ID : 2150
版本:0001
制造商:Movidius Ltd.
产品:m ovidius MA2X5X
如下图所示,使用配置 1 和配置 2 的 Oracle Virtual Box USB 设备的配置要求
Oracle Virtual Box USB setup
树莓 Pi 3 型号 B
目前我正在使用树莓官网的 NOOBS[3]。请注意,我们需要连接显示器和键盘+鼠标进行初始安装。之后,通过在 Raspberry Pi 3 Model B 上打开 SSH,一切都将无头化。Raspberry 的人从 Raspberry Documentation[4]获得了关于打开 SSH 登录的很好的文档
Raspberry Pi 需要做更多的工作来安装来自源代码[5]的 OpenCV,其中包括 e
1。增加交换空间
我们还需要通过编辑 /etc/dphys-swapfile 中的文件来增加交换空间,使用下面的命令,CONF _ 交换空间=2048 来拥有 2GB 的交换空间
,然后发出下面的命令来生效
$ sudo /etc/init.d/dphys-swapfile stop
$ sudo /etc/init.d/dphys-swapfile start
2 。我们将移除 wolfram 和 libreoffice 来节省一些 NOOBS 默认的空间
$ sudo apt-get purge wolfram-engine
$ sudo apt-get purge libreoffice*
$ sudo apt-get clean
$ sudo apt-get autoremove
3。安装依赖关系 依赖关系包括构建工具和一些开发库,这些是构建 Open CV 所必需的
$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install build-essential cmake pkg-config
$ sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev
$ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
$ sudo apt-get install libxvidcore-dev libx264-dev
$ sudo apt-get install libgtk2.0-dev libgtk-3-dev
$ sudo apt-get install libcanberra-gtk*
$ sudo apt-get install libatlas-base-dev gfortran
$ sudo apt-get install python2.7-dev python3-dev
4。下载 Open CV 源代码 我们需要构建 opencv 和 opencv_contrib 源代码
$ cd ~
$ wget -O opencv.zip [https://github.com/Itseez/opencv/archive/3.3.0.zip](https://github.com/Itseez/opencv/archive/3.3.0.zip)
$ unzip opencv.zip
$ wget -O opencv_contrib.zip [https://github.com/Itseez/opencv_contrib/archive/3.3.0.zip](https://github.com/Itseez/opencv_contrib/archive/3.3.0.zip)
$ unzip opencv_contrib.zip
5。编译开放 CV 源代码 我们将从 ARM 平台的源代码中编译开放 CV
$ cd ~/opencv-3.3.0/
$ mkdir build
$ cd build
$ cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.3.0/modules \
-D ENABLE_NEON=ON \
-D ENABLE_VFPV3=ON \
-D BUILD_TESTS=OFF \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D BUILD_EXAMPLES=OFF ..
$ sudo make install
6。打开 CV 的最后一步我们将把默认安装的库(cv2 . cpython-35m-arm-Linux-gnueabihf . so)移动为 cv2.so
$ cd /usr/local/lib/python3.5/site-packages/
$ sudo mv cv2.cpython-35m-arm-linux-gnueabihf.so cv2.so
7 .。安装 TensorFlow 我们需要为树莓 Pi 3 Model B 安装 ARM 版本的 TensorFlow
$ wget [https://github.com/lhelontra/tensorflow-on-arm/releases/download/v1.4.0/tensorflow-1.4.0-cp35-none-linux_armv7l.whl](https://github.com/lhelontra/tensorflow-on-arm/releases/download/v1.4.0/tensorflow-1.4.0-cp35-none-linux_armv7l.whl)
$ sudo pip3 install tensorflow-1.4.0-cp35-none-linux_armv7l.whl
英特尔 Movidius 常规安装
这些步骤适用于 Oracle Virtual Box 和 Raspberry Pi 3 Model B 设置
$ sudo apt-get install git
$ git clone [https://github.com/movidius/ncsdk](https://github.com/movidius/ncsdk)
$ cd ncsdk
$ sudo make install
测试和基准测试
我使用来自https://github.com/movidius/ncappzoo的 ncappzoo 按照以下步骤做了一些基准测试
$ git clone [https://github.com/movidius/ncappzoo](https://github.com/movidius/ncappzoo)
$ cd ncappzoo/apps/benchmarkncs
$ ./mobilenets_benchmark.sh | grep FPS
使用时间命令
Raspberry Pi 3 Model B:
real 40m 56.595s
user 36m 41.170s
sys 0m 58.780s
Oracle 虚拟盒子:
实 11m52.631s
用户 4m43.956s
sys 0m37.612s
英特尔 Movidius 的性能似乎介于嵌入式系统(Raspberry Pi 3 Model B)和台式机/笔记本电脑系统(Oracle Virtual Box)之间。测试期间唯一的缺点是运行测试的时间,但我认为重要的一点是运行神经网络模型。
根据英特尔 Movidius 官方网站[6],可能的应用涵盖机器人、AR/VR、可穿戴设备和智能安防。我能想到的一个很酷的想法是修改 Sun Founder[7]的机器人汽车解决方案,将英特尔 Movidius 作为自动驾驶能力和面部识别的视觉,可以检测入侵者。
如果你对这篇文章有任何问题,请不要犹豫,在下面留言或者给我发邮件:me@chclab.net
参考资料:-
【1】【https://movidius.github.io/ncsdk/】【2】https://www.virtualbox.org/wiki/Downloads
【3】https://www.raspberrypi.org/downloads/
【4】https://www . raspberrypi . org/documentation/remote-access/ssh/
【5】https://github.com/Itseez/opencv/archive/3.3.0.zip
【6】https://www.movidius.com/applications
【7】https://www.sunfounder.com/picar-s-kit-1502.html【
演练:Keras 入门,使用 Kaggle
原文:https://towardsdatascience.com/getting-started-with-keras-e9fc04f7ea6a?source=collection_archive---------14-----------------------
A boat on water. Also, a plane!
这是一个简短的帖子——真正的内容在下面的截屏中,我在那里浏览了代码!
如果你刚开始进入机器学习领域(说实话,谁不是呢?),工装好像只是越做越好。一段时间以来,Keras 一直是一个关键工具,现在它已经被集成到 TensorFlow 中。在一起更好,对吗?碰巧的是,使用 Keras 从未如此容易。
但是,等等,Keras 到底是什么,如何使用它来开始创建自己的机器学习模型?今天,我将向您展示如何以最快的方式开始使用 Keras。
不仅 Keras 通过tensorflow.keras
内置到 TensorFlow 中,如果你使用像 Kaggle Kernels 这样的工具,你不需要安装或配置任何东西。
[## Kaggle 内核简介
在《人工智能历险记》的这一集里,你会发现什么是 Kaggle 内核,以及如何开始使用它们。虽然没有…
towardsdatascience.com](/introduction-to-kaggle-kernels-2ad754ebf77)
和 Keras 一起玩
你需要做的就是创建你的 Kaggle 账户,然后登录。然后你就能接触到所有能提供的服务。
值得指出的是,Keras 也作为一个独立的库存在,位于 keras.io ,尽管 TensorFlow 版本具有完全相同的 API 和一些额外的功能。
让我们来看看我的 Kaggle 内核,在这里我将展示如何立即开始使用 Keras。
Screencast showing how to get going with Keras, on Kaggle!
结束语
Keras 有一个令人惊叹的社区和许多样本,当你与 Kaggle 的社区结合时,它会给你一组真正史诗般的资源,让你以正确的方式开始。
既然集成到 TensorFlow 中,就意味着可以在谷歌云 ML 引擎上训练 Keras 模型。甚至有办法在 Keras 和 TensorFlow 之间导出和转换模型,这样您也可以按比例服务于您的预测!如果你想了解更多,请在评论中告诉我,我会试着收集一些例子!
感谢阅读本集云 AI 冒险。如果你喜欢这个系列,请为这篇文章鼓掌让我知道。如果你想要更多的机器学习动作,一定要关注媒体上的me或订阅 YouTube 频道的来观看未来的剧集。更多剧集即将推出!
机器学习入门!
原文:https://towardsdatascience.com/getting-started-with-machine-learning-108622a1ef5c?source=collection_archive---------12-----------------------
“数据”世界和机器学习导论
近年来,关于“机器学习”、“数据分析”、“人工智能”、“深度学习”、“大数据”等术语有很多讨论。数据科学被评为 21 世纪最性感的工作。这些术语中的大多数很少互换使用。然而,每个术语虽然相关,但它们的含义是不同的,并且每个术语都为它们可以应用的各个领域提供了大量的机会。
分解“数据”的流行词汇
Data buzzwords
每个术语的含义可以借助下面的例子来分解
考虑一个专门设计来清洁地板的机器人。这个机器人正在工厂旁边的一所房子里使用。由于这个磨坊,白天会有大量灰尘进入室内。晚上工厂关门,因此灰尘相对较少。周末工厂也关门。因此,灰尘在周末也较少。现在,机器人必须明白应该如何、何时以及在哪里清洁地板。
Robot for cleaning the floor
机器人必须知道工作日白天灰尘较多,夜晚和周末灰尘较少。这个机器人通过一组给定的输入和输出进行学习的过程就是机器学习。【7】
既然机器人已经知道何时灰尘更多,它必须做出适当的决定,在白天多打扫,在晚上和周末少打扫。这就是人工智能。
机器人在传感器的帮助下收集灰尘堆积较多的区域的数据。传感器通过房屋成员的语音输入(以语音的形式)捕捉数据,通过房屋各个部分的照片(以图像的形式)等捕捉数据。处理这些结构化和非结构化的数据以获得有意义的信息就是大数据。【6】
从机器人捕获的数据中获得有意义的见解是数据分析。对某些细节的关注,如一天中不同时间不同的电池消耗模式,房屋角落有更多灰尘等。形成了数据分析的基础,这从业务角度来看非常重要。
比方说,通过数据分析,我们了解机器人不同的电池消耗周期。根据这些信息建立业务模型非常重要。这种数据模式形成了关键决策的基础,如引入在夜间自动触发的电池节电器,这最终有助于业务。这将有助于机器人获得更长的电池寿命。机器人可以以此作为 USP 在市场上推广。因此,基于精选的见解做出商业决策以获得最大利益被称为数据科学。【4】
潜入机器学习-
什么是机器学习?
通常,机器学习被定义为允许机器(计算机)理解或行动而不必显式地对系统或程序进行硬编码的技术。[11]
考虑以下给人阅读的信息-
在印度,从六月到九月都会下雨。沿海地区降雨量大,而内陆地区降雨量适中。大部分强降雨发生在七月。在过去的 4 年里(2013-2017 年), 7 月的前 2 周观察到强降雨
现在,如果我请你,作为一个人,回答以下问题
今天,即 2018 年 7 月 4 日,孟买下雨的概率有多大?
显而易见的答案是降雨概率大。现在我们希望机器也能理解和学习这一点。给机器输入一组过去的数据(输入和输出)后,机器应该能够“思考”新输入数据的输出是什么。
通常在机器学习问题中,我们有一组训练数据。该训练数据具有输入和相应的输出。现在,机器将被输入一个机器学习算法来学习这个数据集,并在此基础上形成一个假设。基于这个假设,机器应该能够预测未知输入的输出。
Basic Block diagram of a machine learning algorithm [8]
解决机器学习问题的步骤
机器学习不是一步到位的过程。通常遵循以下步骤来解决机器学习算法[14]。我已经用简单的‘T10’虹膜数据集解释过了。[1]
我修改了数据集中的一些值来解释下面的步骤。点击查看虹膜数据集
- 问题定义-
在从过去的数据集中学习之前,重要的是首先了解我们到底想要学习什么。这个问题可以是分类问题,也可以是回归问题。整个机器学习建模取决于目标或问题定义。在我们的数据集中,我们有花瓣和萼片的长度和宽度。我们必须首先理解我们期望解决这个数据集的什么问题。我们是否必须建立一个假设来预测花瓣长度、萼片长度、萼片宽度和花瓣宽度已知的新花的类别,或者我们是否必须只分析分类是否可能等等。
2。框架
下一步是理解我们的特征或属性(通常表示为 X)是什么,以及对于给定的训练数据集,我们的目标或输出(通常表示为 y)是什么。考虑虹膜数据集
特征 X =萼片长度(slen)、萼片宽度(swid)、花瓣长度(plen)和花瓣宽度(pwid)
目标 y =类别
Iris Data Set [1]
3。导入或获取数据集
我们必须了解如何将数据导入/获取到我们的程序中。数据可以是结构化或非结构化的,并且可以是逗号分隔的值(。csv)文件或 Excel(。xlsx)表等。对于. csv 文件,可以使用以下命令导入数据集-
dataSet = pandas . read _ CSV(' data frame _ name . CSV ')
Acquiring Data
4。清洁和精炼
数据集可能有丢失的值或垃圾值,因此无法处理数据。因此,需要对数据进行预处理。我们必须在采集的数据集中检查以下内容-
- 检查缺少的值-给定数据集中的一些值不可用
- 检查垃圾值——给定数据集中的一些值在逻辑上是不正确的(例如,如果我们在谈论萼片长度,而值是“紫色”)
- 检查异常值(与其他值相比,给定数据集中的一些值超出了范围。例如,如果萼片长度值为{1.5,2.3,3.2,2.2,1.75,15.2,3.2},那么 15.2 就是异常值。)
Null values in the data set
缺失/垃圾值的处理:
- 删除缺失/无用的值
- 将区间值转换为分类数据
- 使用建模技术
- 替换数据点(插补)
Replacing the null values using statistical methods
标准化 -在细化的同时也可以执行标准化。例如,如果有一个城市名称列表,那么我们可以有“纽约市”,“纽约市”,“纽约市”。因为所有这三个名字都代表同一个城市,所以我们可以用一个通用的表示法来表示所有这三个名字。同样,日期也可以用日/月/年格式或日/月/年或日/月/YY 等格式书写。只要所有的值都在谈论同一个日期,它们就必须以相同的方式表示。
5。探索数据
在获取和处理数据时,是时候探索数据集的属性了。这个过程被称为探索性数据分析(EDA)。它基本上是总结我们正在处理的数据集的过程。[2].
我们必须了解我们处理的是什么类型的数据,因为它对进一步的分析很有用。数据可分类如下-
数据集中数据的分类-
数字——数据集中的任何值,如人的身高或项目数量等,都是数字值。
分类数据点,其中可以分类为 A 类和 B 类,称为分类数据点。
A)有序数据-在数据点的分类中,如果类别的排序是可能的,因为类别 A 比类别 B 具有更高的排序,则它是有序数据点。
b)名义上的-在数据点的分类中,如果类别的排序是不可能的,或者如果所有类别被认为是相同的排序,那么它被称为名义上的数据点。
平衡和不平衡数据集-
数据集可以是平衡的或非平衡的数据集。假设数据集可以分为 2 类——第 1 类或第 2 类。如果属于类别 1 和类别 2 的数据点数量几乎相等,那么该数据集被称为平衡数据集。
类别比率达到 70-30 的数据集可以被认为是平衡数据集。
平衡数据集的示例-
如果数据集的类比率大于 70–30,比如说90–10,那么数据集被认为是不平衡数据集
不平衡数据集的示例-
在解决机器学习算法时,确保我们的数据集是平衡的数据集是极其重要的。否则,无论我们使用哪种算法,都不会得到合适的结果。
不平衡数据集的解决方案-
删除数据点数量较多的几个样本
通过复制或使用统计方法,添加数据点数较少的几个样本
通过获取少量数据点的重复样本,使用批处理执行机器学习
Iris 数据集是平衡数据集,所有 3 个类别具有几乎相同数量的数据点-
汇总数据-
可以使用统计方法和视觉方法来总结数据。
统计方法——包括寻找平均值、中位数、众数、标准差、协方差等。的数据点。统计方法帮助我们理解数据集的范围、中心值等
视觉方法-包括绘制直方图、箱线图、散点图、累积密度函数(CDF)、概率密度函数(PDF)等。可视化方法清楚地显示了数据集的分布方式、异常值、数据集中的位置等。
Plotting PDFs
6。变换-
一旦我们处理完数据集,我们就可以转换数据集,以便有效地使用它。我们可以执行特征选择、创建新特征、删除冗余特征等。
数据表的转换包括-
a)创建新功能
有时,可能需要创建新的功能。这可以包括从由现有特征管理的洞察中生成新特征,或者使用统计方法,例如使用现有特征的平均值或中值等。当我们必须减少数据集中的特征或列的数量时,这一步很重要。如果我们有两列“a”和“b ”,它们的数据可以用它们的平均值“c”来更好地表示,那么“a”和“b”可以被丢弃,新生成的“c”可以被添加到数据集中,从而降低数据的维数。可以使用以下技术创建新功能-
a)特征工具——可以使用 H2O、TPOT、Auto- sklearn 等自动化特征工程工具[13]
b)手动创建-通过分组、汇总、派生等。可以生成新的特征
b)编码(分类数据)
如果我们有一个列名是字符串形式的数据集,那么我们必须对这些列进行编码,将它们转换成数值,以便进一步计算。这可以使用以下任何一种编码技术来完成
a)一次热编码-扩展现有数据
Example of One hot encoding
因为一键编码扩展了表格,所以当特征的数量很大时,它不是优选的。
b)标签编码
下面是一个标签编码的例子。我使用了 Sci-kit Learn 的 LabelEncoder 库
Label Encoding
7。数据建模-
这一步包括选择正确的算法来训练我们的数据。必须根据算法是回归问题还是分类问题、精度要求等来选择合适的训练算法。
因为我们的问题是分类问题,所以我选择了决策树算法。
在构建模型时,必须拆分数据集,以便可以在同一个数据集上训练、验证和测试数据。
Code snippet for splitting the data into training and testing data sets
一次保持验证- 在该方法中,数据被分割,使得 70%的数据可用于训练模型,20%的数据可用于验证模型,10%的数据可用于测试模型
One hold
K 折交叉验证- 交叉验证或 K 折验证是机器学习中常用的验证方法。在这种方法中,训练和验证是在迭代中执行的,其中迭代的次数由 k 定义。整个数据集被划分成互补的子集,具有很少的折叠作为训练、很少的验证和很少的测试数据,其中测试数据与训练和验证数据保持分离。对于每次迭代,不同的子集被用于验证。因此,每个子集都用于训练和验证。这减少了可变性。[5]
Cross validation
8。数据验证
使用验证技术(如上一步中提到的一次保持验证和交叉验证)对照验证数据测试已在训练数据集上训练的数据。可以计算训练和验证数据集的准确性。训练和测试精度要高,相互接近。
Accuracy when Max depth=5
Accuracy when Max depth=10
9。超参数调谐
在验证数据集时,我们可以调整超参数以优化模型。该模型将被优化,直到它在训练和验证数据集上都令人满意地执行。
在我们的数据集中,对于 max_depth=5,我们得到了不错的训练(0.998)和验证准确度(0.923)。如果我们没有得到很好的准确性,我们可以改变一些超参数,如决策树中 max_depth 的值或 k(折叠或子集的数量)的值。我们得到了完美的训练集精度,但是验证精度相对较低,max_depth 为 10。因此,我们可以绘制一个图表,找出哪个 max_depth 将提供最佳精度,并将超级参数 max_depth 设置为相应的值。[10]
Training and testing accuracy for different max_depths
观察该图可以得出结论,对于 max_depth=3 或 4,测试精度高。因此,我们相应地调整我们的超参数 max_depth。
10。测试
一旦数据得到优化,就可以进行测试了。测试数据集与训练和验证数据集分开。它不参与优化过程。这是测试该模型是否适用于一般未知数据集的最后一步。
我们的模型在测试数据上给出了 0.866 的准确度。
Test data output
查看完整的代码这里
总结一下,机器学习的工作流程如下-
参考文献-
[1]虹膜数据集-https://archive.ics.uci.edu/ml/datasets/iris
www.appliedaicourse.com
www.dummies.com
https://youtu.be/w-8MTXT_N6A
[5]https://en . Wikipedia . org/wiki/Cross-validation _(statistics)
[6]https://www . simpli learn . com/data-science-vs-big-data-vs-data-analytics-article
[7]https://www . machine curve . com/index . PHP/2017/09/30/the-differences-between-artificial-intelligence-machine-learning-more/# now-what-a-data-scientist
[8]http://communication police . blogspot . com/2016/06/machine-learning-supervised unsupervised . html
[9]https://sci kit-learn . org/stable/modules/generated/sk learn . model _ selection . train _ test _ split . html
https://matplotlib.org/users/pyplot_tutorial.html
[11]https://www . coursera . org/lecture/machine-learning/what-is-machine-learning-Ujm7v
[12]https://sebastianraschka . com/Articles/2014 _ intro _ supervised _ learning . html
https://www.featuretools.com/
[14]由 Analytics Vidya 在为期三天的 Data Hack 峰会期间组织的应用机器学习研讨会。日期-2018 年 11 月 24 日,发言人- Amit Kapoor
马尔可夫决策过程入门:强化学习
原文:https://towardsdatascience.com/getting-started-with-markov-decision-processes-reinforcement-learning-ada7b4572ffb?source=collection_archive---------2-----------------------
第二部分:解释 马尔可夫决策过程、 贝尔曼方程和政策的概念
在这篇博文中,我将解释理解如何解决强化学习问题所需的概念。这一系列的博客文章包含了大卫·西尔弗在关于强化学习的介绍中解释的概念总结。
零件:1234…
到目前为止,我们已经在很高的层次上学习了设置强化学习问题所需的组件。现在,我们将更详细地正式描述强化学习的环境。在本帖中,我们将看看一个完全可观测的 环境以及如何将环境正式描述为 马尔可夫决策过程 (MDPs)。
如果我们能解决马尔可夫决策过程,那么我们就能解决一大堆强化学习问题。
MDPs 需要满足 马尔可夫性质 。
马尔可夫性质: 要求“未来独立于过去给定的现在”。
性质 :麟州 Sₜ 是马氏当且仅当:
简单地说,这意味着状态 Sₜ 从历史中获取所有相关信息。 S₁,S₂,…,Sₜ₋₁ 可以丢弃,我们仍然得到相同的 状态转移概率 到下一个状态 Sₜ₊₁ 。
状态转移概率 : 状态转移概率告诉我们,给定我们处于状态 s 下一个状态s’会发生的概率是多少。
P without the double lines represents the state transitions. The above equation has the transition from state s to state s’. P with the double lines represents the probability from going from state s to s’.
我们也可以根据一个状态转移矩阵 P 来定义所有的状态转移,其中每一行都告诉我们从一个状态到所有可能的后续状态的转移概率。
State transition matrix.
马尔可夫过程/马尔可夫链
第一个也是最简单的 MDP 是一个 马尔可夫过程 。
马尔可夫过程/马尔可夫链 : 具有马尔可夫性质的随机状态序列 S₁、S₂、… 。
下面是一个马尔可夫链的图示,其中每个节点代表一个状态,有可能从一个状态转移到下一个状态,其中 Stop 代表一个终止状态。
Markov Chain
我们可以拿一个 样本 集来遍历这个链,最后到达终点状态。一个示例情节是从阶段 1 到阶段 2 到赢得到停止。以下是几个样本集的代表:
- *S1 S2 赢停
- S1 S2 瞬移 S2 赢停
- S1 暂停 S1 S2 赢停*
上述马尔可夫链具有以下转移概率矩阵:
对于每个状态,该状态的转移概率之和等于 1。
马尔可夫奖励过程
在上面的马尔可夫链中,我们没有与达到目标的状态相关联的值。一个 马尔可夫奖励过程 是一个带有奖励值的马尔可夫链。
我们的目标是最大化 回报 。回报 Gₜ 是从时步 t 开始的总折扣奖励。
Equation to calculate return
折现因子 γ 是介于 0 和 1 之间的一个值(可以选择)。如果γ接近 0,则导致近视评估,而接近 1 的值有利于远视评估。
Markov Reward Process
注 :由于在马尔可夫奖励过程中我们没有采取行动,Gₜ是通过遍历随机样本序列来计算的。
MRP 的价值函数
状态值函数 v(s) :给出状态 s 的长期值。它是从状态 s 开始的预期收益
state-value function
我们可以这样看,从状态 s 开始,通过状态 s 的各种样本,我们的预期收益是多少。我们更喜欢给予更多总回报的州。
state-values for MRP with γ=1
MRPs 的贝尔曼方程
价值函数可以分解为两部分:
- 即时奖励: Rₜ₊₁
- 继承国贴现值:γ(sₜ₊₁)
我们可以使用上面的状态值函数和返回函数定义一个新的等式来计算状态值函数:
updated bellman state-value equation
或者,这可以写成矩阵形式:
使用这个等式,我们可以计算每个状态的状态值。由于我们在上面有一个简单的模型,带有γ=1 的 MRP 的“状态值”,我们可以使用一个联立方程,使用更新的状态值函数来计算状态值。
对于较小的 MRPs,求解上面的方程很简单,但是对于较大的数目,就变得非常复杂。为了解决大型 MRP,我们需要其他技术,如动态规划、蒙特卡洛评估和时差学习,这些将在后面的博客中讨论。
马尔可夫决策过程
一个 马尔可夫决策过程 是一个马尔可夫回报过程的扩展,因为它包含了一个代理必须做出的决策。环境中的所有状态都是马尔可夫的。
在马尔可夫决策过程中,我们现在对进入哪个状态有了更多的控制。在下面的 MDP 的例子中,如果我们选择进行传送动作,我们将在 40%的时间里回到状态阶段 2 中,在 60%的时间里回到状态阶段 1 中。当选择相应的动作时,其他状态转换以 100%的概率发生,例如采取动作前进 2 从阶段 2 将把我们带到胜利。
政策
一个策略 π 是给定状态下动作的分布。它完全定义了一个代理的行为。MDP 政策取决于现状,而不是历史。
Policy function
策略给出了从一个状态到下一个状态的映射。如果我在状态 s,它从那个状态映射出采取每一个行动的概率。示例如果我们有策略 π(杂务|阶段 1)=100%,这意味着代理将在处于状态阶段 1 时采取动作杂务 100%* 。*
MDP 的价值函数
因为我们采取行动,所以根据我们的行为会有不同的期望。
MDP 的 状态值函数v _π(s)是从状态* s 开始,然后遵循策略π的期望收益。*
状态值函数告诉我们通过遵循策略 π 处于状态 s 有多好。
动作值函数 q_π(s,a) 是从状态 s 开始,采取动作 a ,然后跟随策略 π的期望收益。
行动价值函数告诉我们从特定状态采取特定行动有多好。让我们知道我们应该在各州采取什么行动
贝尔曼期望方程
价值函数也可以以 的形式写成贝尔曼期望方程 如下:
状态值函数:
动作值功能:
最优值函数
在上述所有等式中,我们使用给定的策略来遵循,这可能不是要采取的最佳行动。强化学习的关键目标是找到能使我们的回报最大化的最优策略。
最优状态值函数v∫(s)*是所有策略的最大值函数。它告诉我们你能从系统中获得的最大回报。***
最优动作值函数q∫(s,a) 是所有策略上的最大动作值函数。它告诉我们,从状态 s 开始并采取行动 a 时,你能从系统中获得的最大回报是什么。
如果你知道q∫,那么你就知道在 MDP 中应该采取的正确行动和最佳表现,从而解决 MDP 问题。
q∑(s,a)表示采取哪些行动来获得最佳表现。
寻找最佳策略
通过最大化超过q∫(s,a) 可以找到最优策略:
贝尔曼最优方程 是非线性的,很难求解。在后面的博客中,我将讨论使用各种技术来解决这个方程的迭代解决方案,例如值迭代、策略迭代、Q-Learning 和 Sarsa。
参考
- 关于 RL 的 UCL 课程——第 2 讲
- 《强化学习导论》,萨顿和巴尔托,1998 年
如果你喜欢这篇文章,并想看到更多,不要忘记关注和/或留下掌声。
mlFlow 入门
原文:https://towardsdatascience.com/getting-started-with-mlflow-52eff8c09c61?source=collection_archive---------7-----------------------
什么是 mlFlow?
mlFlow 是一个支持机器学习生命周期的框架。这意味着它具有在训练和运行期间监控模型的组件,能够存储模型,在生产代码中加载模型并创建管道。
该框架引入了 3 个不同的特性,每个特性都有自己的功能。
物流跟踪
跟踪可能是该框架最有趣的特性。它允许您围绕您的模型创建一个广泛的日志框架。您可以定义自定义指标,以便在运行后可以将输出与之前的运行进行比较。
我们将主要关注这一部分,但也给你一窥其他功能。
MlFlow 项目
此功能允许您根据需要创建管线。该特性使用自己的模板来定义您希望如何在云环境中运行模型。由于大多数公司都有在生产中运行代码的方法,所以您可能对这个特性不太感兴趣。
ml 流程模型
最后,我们有模型功能。mlFlow 模型是包装机器学习模型的标准格式,可用于各种下游工具,例如,通过 REST API 或 Apache Spark 上的批处理推理进行实时服务。
理论完成:是时候开始了
理论总是好的,但现在是时候采取更实际的方法了。首先,在我们真正开始之前,我们需要启动一个 mlFlow 服务器。为了正确地做到这一点,我创建了一个 docker 容器以便于部署。
在展示代码之前,配置存储后端也很重要。因为我们希望我们的模型存储在某个地方,所以我选择了 Azure blob 存储(请注意,AWS S3 也是受支持的)。
所以创建一个 blob 存储帐户,并在里面创建一个容器。
Blob storage account Azure
一旦它被创建,你将需要写下 wasb 链接,因为你将需要这个值来启动 docker。url 通常定义如下:“wabss://
接下来,我们可以开始构建 docker。因为 mlFlow 需要 python,所以我从 python 图像开始,让我的生活变得简单了一些。基本上,只要确保 Python 在容器中可用,就可以从任何图像开始。对于本例,您只需安装以下两个软件包:
- mlflow 版本 0.8.0
- azure 存储 0.36.0
完整的 docker 解决方案只需看看我的 Github 账户:【https://github.com/Ycallaer/mlflowdocker
接下来你需要构建容器,如果你不知道怎么做,看看自述文件。
一旦您在本地机器上启动了 docker 映像,它应该可以通过以下 url 获得: http://localhost:5000/
如果一切顺利,你的主页可能会像这样。
Homepage mlFlow
调整模型以使用 mlFlow
一旦服务器部分准备好了,是时候修改我们的代码了。我创建了一个小的 ARIMA 模型实现来展示这个框架。
在开始之前,我们需要定义运行服务器的 URL。您可以通过调用方法“set_tracking_uri”来实现这一点。这已经为这个演示进行了硬编码,但理想情况下,这将指向一个公共端点。
接下来,我们需要创建一个实验。这应该是一个唯一的标识符。确保它唯一的一种方法是在每次调用实验方法时生成一个 uuid。在我的例子中,我硬编码它以加速演示。
通过调用“start_run()”方法,我们告诉 mlFlow 这是运行的起点,这将为您的运行设置开始日期。不要忘记将实验 id 传递给方法,这样所有的日志记录都保留在实验中。
省略实验 id 将导致所有日志被写入默认实验。
Start point mlFlow Tracking
接下来,我们需要指定在运行过程中要监控的值。一方面,您有“log_param()”,它为字符串值记录一个键值对。另一方面,我们有“log_metric()”,它只允许您将值定义为整数。
Example of log_param and log_metric
视觉效果
现在让我们回到 UI,看看我们运行的视觉结果是什么。在主页上,你会发现你的实验列在左侧。
Homepage with experiment
如果你点击日期,你会看到那次跑步的概况。
Detailed info of an experiment
在指标旁边,您会看到一个图形符号,如果您单击它,您可以看到在运行过程中该指标是如何变化的。
Detailed graph of a metric
保存模型
我们还希望能够使用框架保存模型。该框架允许您以与大多数流行框架兼容的格式加载和保存模型(例如:Scikit、Pytorch、Tensorflow 等)。完整的名单请看这里的。
将模型保存为工件的代码相当简单:
Example of log_model call in mlFlow
拟合的结果将作为第一个参数传递给函数,第二部分是目录。如果您导航到 UI 并单击 run,您将在页面底部找到工件信息。
Model saved on Azure from mlFlow
如果你是偏执狂类型的,你现在可以看看 blob 存储帐户,以验证模型确实被保存了。
Model on blob store
不错吧?如果你愿意,你可以看看加载特性,然后开始围绕这个模型构建应用程序。
用于该演示的完整回购可以在 Github 上找到。
问题
我发现这个框架更大的问题是,所有的日志都只存储在 docker 容器中,即使你已经定义了一个存储后端。这意味着,如果您重新启动容器,您的所有记录都将丢失。我记录了一个问题(https://github.com/mlflow/mlflow/issues/613),得到的回应是当前团队正在重新设计日志功能。所以祈祷吧。
OpenAI 健身房入门
原文:https://towardsdatascience.com/getting-started-with-openai-gym-932c7311d26c?source=collection_archive---------7-----------------------
OpenAI 健身房环境是了解更多机器学习的最有趣的方式之一。特别是强化学习和神经网络可以完美地应用到基准和雅达利游戏集合中。每个环境都有多种特色解决方案,并且您经常可以找到关于如何获得相同分数的文章。通过观察别人的方法和想法,你可以以一种有趣的方式快速提高自己。我注意到开始健身有点困难。虽然网上有很多算法教程,但第一步是理解你正在工作的编程环境。为了让新人更容易适应这个环境,我决定用 docker 容器和 jupyter 笔记本制作一个小教程。
你需要什么
开始之前,安装 Docker 。Docker 是一个让你在电脑上运行虚拟机的工具。我创建了一个“图像”,其中包含了几个你想要的东西:tensorflow、健身房环境、numpy、opencv 和一些其他有用的工具。
安装 docker 后,运行以下命令下载我准备好的 Docker 映像:
docker run -p 8888:8888 rmeertens/tensorflowgym
在浏览器中,导航到:localhost:8888,并打开 TRADR 文件夹中的 OpenAI Universe 笔记本。
自己玩个游戏
让我们从自己玩翻筋斗游戏开始。你控制一个上面有杆子的酒吧。“游戏”的目标是尽可能长时间地保持横杠直立。在这个游戏中,你可以做两个动作:向左用力,或者向右用力。要手动玩这个游戏,请执行代码的第一部分。
通过左右点击你施加一个力,你会看到新的状态。请注意,我将游戏编程为当您“丢失”游戏时自动重置。
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import widgets
from IPython.display import display
import gym
from matplotlib import animation
from JSAnimation.IPython_display import display_animation
def leftclicked(something):
""" Apply a force to the left of the cart"""
onclick(0)
def rightclicked(something):
""" Apply a force to the right of the cart"""
onclick(1)
def display_buttons():
""" Display the buttons you can use to apply a force to the cart """
left = widgets.Button(description="<")
right = widgets.Button(description=">")
display(left, right)
left.on_click(leftclicked)
right.on_click(rightclicked)
# Create the environment and display the initial state
env = gym.make('CartPole-v0')
observation = env.reset()
firstframe = env.render(mode = 'rgb_array')
fig,ax = plt.subplots()
im = ax.imshow(firstframe)
# Show the buttons to control the cart
display_buttons()
# Function that defines what happens when you click one of the buttons
frames = []
def onclick(action):
global frames
observation, reward, done, info = env.step(action)
frame = env.render(mode = 'rgb_array')
im.set_data(frame)
frames.append(frame)
if done:
env.reset()
重播
既然你已经玩过了,你可能想看重播。我们保存了游戏的每一次按钮点击状态,你可以在你的浏览器中显示出来:
def display_frames_as_gif(frames, filename_gif = None):
"""
Displays a list of frames as a gif, with controls
"""
plt.figure(figsize=(frames[0].shape[1] / 72.0, frames[0].shape[0] / 72.0), dpi = 72)
patch = plt.imshow(frames[0])
plt.axis('off')
def animate(i):
patch.set_data(frames[i])
anim = animation.FuncAnimation(plt.gcf(), animate, frames = len(frames), interval=50)
if filename_gif:
anim.save(filename_gif, writer = 'imagemagick', fps=20)
display(display_animation(anim, default_mode='loop'))
display_frames_as_gif(frames, filename_gif="manualplay.gif")
表现
在 OpenAI 网站上描述了弹球环境。观察参数中的值显示位置(x)、速度(x_dot)、角度(theta)和角速度(theta_dot)。如果杆的角度超过 15 度,或者手推车从中心移动超过 2.4 个单位,游戏“结束”。然后可以通过调用 env.reset()来重置环境。
开始学习
如果没有简单的“学习”机制,这篇博文将是不完整的。凯文·弗朗斯写了一篇关于简单算法的博文,你可以应用在这个问题上:【http://kvfrans.com/simple-algoritms-for-solving-cartpole/。
实现起来最简单的就是他的随机搜索算法。通过将参数与观察参数相乘,推车决定向左或向右施力。现在的问题是:什么是最好的参数?随机搜索随机定义它们,查看购物车在这些参数下可以持续多长时间,并记住找到的最佳参数。
def run_episode(env, parameters):
"""Runs the env for a certain amount of steps with the given parameters. Returns the reward obtained"""
observation = env.reset()
totalreward = 0
for _ in xrange(200):
action = 0 if np.matmul(parameters,observation) < 0 else 1
observation, reward, done, info = env.step(action)
totalreward += reward
if done:
break
return totalreward
# Random search: try random parameters between -1 and 1, see how long the game lasts with those parameters
bestparams = None
bestreward = 0
for _ in xrange(10000):
parameters = np.random.rand(4) * 2 - 1
reward = run_episode(env,parameters)
if reward > bestreward:
bestreward = reward
bestparams = parameters
# considered solved if the agent lasts 200 timesteps
if reward == 200:
break
def show_episode(env, parameters):
""" Records the frames of the environment obtained using the given parameters... Returns RGB frames"""
observation = env.reset()
firstframe = env.render(mode = 'rgb_array')
frames = [firstframe]
for _ in xrange(200):
action = 0 if np.matmul(parameters,observation) < 0 else 1
observation, reward, done, info = env.step(action)
frame = env.render(mode = 'rgb_array')
frames.append(frame)
if done:
break
return frames
frames = show_episode(env, bestparams)
display_frames_as_gif(frames, filename_gif="bestresultrandom.gif")
练习以了解更多关于 OpenAI 健身房的信息
接下来就是自己玩自己学了。以下是一些建议:
- 继续凯文·弗兰斯的教程:http://kvfrans.com/simple-algoritms-for-solving-cartpole/
- 上传并分享您的结果。比较随机算法的效果,或者你自己实现的算法与其他人相比的效果。如何做到这一点可以在这个页面找到:【https://gym.openai.com/docs#recording-and-uploading-results】T2 标题下的“记录和上传结果”
- 看看其他环境:【https://gym.openai.com/envs】T4。如果你能解决 cartpole 环境,你当然也能解决钟摆问题(注意,你必须调整你的算法,因为这个只有 3 个变量在观察中)。
结论
恭喜你!你在开放的健身房里制作了你的第一个自动平衡杆。既然这样做了,是时候要么改进你的算法,要么开始尝试不同的环境了。这个 Jupyter 笔记本跳过了很多关于你实际在做什么的基础知识,在 OpenAI 网站上有一篇关于这个的很棒的文章。
下一步
除非你决定把自己的算法作为练习,否则你不会在本教程中做很多机器学习(我不认为寻找随机参数是“学习”)。请看看:
- 第二部分:哪里会看深度 q 网络:预测每个动作的回报的神经网络。
- 第 3 部分:我们将使用深度 q 网络,以雅达利游戏的图片作为输入
感谢
这篇博客是我的 TRADR summerschool 关于在强化学习算法中使用人类输入的研讨会的第一部分。更多信息可以在他们的主页上找到。
OpenAI 健身房入门
原文:https://towardsdatascience.com/getting-started-with-openai-gym-d2ac911f5cbc?source=collection_archive---------2-----------------------
OpenAI gym 是一个开发和测试学习代理的环境。它是集中的,最适合强化学习代理,但不限制人们尝试其他方法,如硬编码游戏求解器/其他深度学习方法。
我为什么要使用 OpenAI 健身房环境?
- 你想学习强化学习算法——有各种各样的环境供你使用和尝试不同的强化学习算法。
- 你对学习代理有一个新的想法,并想测试一下——这个环境最适合在模拟中尝试新的算法,并与现有的算法进行比较。
- 想要在我们不想在现实中建模的情况下训练代理-深度学习需要大量的正面和负面的训练示例,并且很难提供这样的示例,例如训练自动驾驶汽车了解事故,自动驾驶汽车知道事故会发生什么以及如何发生是很重要的,并且在现实世界中建模既昂贵又有风险。模拟可以帮助我们。
- 将学习-做活动的速度提高 10 倍,在模拟中更好还是在现实生活中更好?当然是模拟,在这里我们的代理可以学得更快。
设置
开放式健身房很容易设置
要求
- Python 3.5+-我还没试过用 Python 2.7 安装。请随时尝试,并让我知道你所面临的问题。
- 无论是从源代码安装还是直接安装,都需要 pip- pip。
安装
- 使用 pip 安装
pip 安装健身房
2.从源安装
git 克隆https://github.com/openai/gym&&CD 馆
pip 安装-e。
示例
首先,进口健身房
进口健身房
创造试验环境
env = gym.make('MountainCar-v0 ')
等等,这是什么环境?健身房就是在这种环境下的这种互动。
有大量的环境供我们玩——到目前为止,有 797 个环境。使用下面的代码片段找出所有
随机代理
请在此处找到源代码
在上述示例中,我们使用了以下环境 APIs
- action_space: 该状态下的一组有效动作
- 步骤:采取指定的行动并返回从环境中收集的更新信息,如观察、奖励、是否达到目标以及对调试有用的其他信息。
观察针对环境;例如,在山地车中,它将返回速度,速度是建立动量以实现目标所需要的。在某些情况下,它将是原始像素数据。
奖励是上一次行动获得的金额。默认情况下,目标是报酬最大化(当然!)
搞定这个真的很有用。这告诉我们什么时候完成,代理人什么时候达到目标。
当出错时,它会发出有用的调试信息,你必须弄清楚代理到底在做什么。
现在,我们的上述随机代理只是为了实现目标一次。在训练其他深度学习算法时,添加外部循环,就像历元数一样。在这里,人们把时代称为插曲。
基本模板
持续 n 次
而目标未实现
take _ action()
take _ step()
结束而
结束
阅读更多并参考
- 更多环境:https://gym.openai.com/envs/
- 【https://gym.openai.com/docs/】
OpenCV 入门:在 Windows +图像混合上安装 OpenCV
原文:https://towardsdatascience.com/getting-started-with-opencv-installing-opencv-on-windows-using-anaconda-6d88d02f141f?source=collection_archive---------14-----------------------
Source: Author-generated.
这个简短的教程包括以下说明:
- 为 Windows 安装 Anaconda
- 安装 Jupyter 笔记本、OpenCV 和其他软件包
- 使用 OpenCV 实现图像混合
1.下载和设置 Anaconda
Anaconda 发行版的主要好处是它使得软件包的安装和维护变得方便快捷;此外,它还包含了 150 多个自动安装的软件包。
在继续学习本教程之前,请确保您的系统具备以下条件,以便确认可以安装 Anaconda 发行版:Windows、macOS 或 Linux x86 或 POWER8,32 位或 64 位,3GB HD 可用。
导航到 https://www.anaconda.com/download/的,点击 Windows 选项,下载 Windows 的 Python 3.6 版本。如果您有 64 位计算机,请单击 64 位图形安装程序(631 MB);如果您有 32 位计算机,请单击 32 位图形安装程序。
Source: Screenshot from https://www.anaconda.com/download/
打开。然后在“欢迎使用 Anaconda3”GUI 上单击 Next 继续安装。同意许可协议,选择您的首选安装类型(推荐“仅我”选项),并选择您的目标文件夹。我建议使用“C:\Users\User_Name\Anaconda3”目录路径,因为它使其他包/库更容易访问 Anaconda,也更容易被 Anaconda 访问。因此,在“高级选项”页面上,将 Anaconda 注册为您的默认 Python 3.6 这一步假设您之前没有在系统上安装 Python。现在,您将能够在您的系统上安装 Anaconda。
2.安装所需的软件包(包括 Jupyter 笔记本和 OpenCV)
安装 Anaconda 之后,在您的系统上搜索并打开 Anaconda 提示符。
您需要创建一个环境,在这个环境中您可以安装必要的包并使用 OpenCV。您可以通过在 Anaconda 提示符下输入以下命令来实现这一点;您可以用自己选择的环境名替换 env :
conda create -n env pip python=3.6
在这一步之后,Anaconda 提示符将显示一组需要下载、解压缩和安装的包;要继续安装,请按键盘上的 y 键。
然后,您需要通过键入以下内容来激活环境:
conda activate env
每次您想要使用为本教程安装的包,包括 Jupyter Notebook 和 OpenCV,您都需要使用上面的命令激活环境。
在本教程中,我将使用 Jupyter Notebook,这是一个开源的 web 应用程序,它允许用户创建包含实时代码和可视化效果的文档,还有许多其他好处。如果您愿意,也可以使用 Spyder IDE 或您选择的 IDE 来运行本教程的代码。
您需要使用以下命令安装 Jupyter Notebook:
pip install jupyter notebook
Source: Author
您还需要使用以下命令安装 matplotlib(这是一个常用的 Python 绘图库):
pip install matplotlib
Source: Author
现在,让我们安装 OpenCV,它代表开源计算机视觉库;该库的目的是支持实时计算机视觉应用。我们可以使用以下命令来执行安装:
pip install opencv-python
Here, I’m installing the OpenCV library release 3.4.2.17. Source: Author
请注意,如果您希望能够通过 OpenCV 操作/使用 JPEGs(专门用于图像混合任务),您将需要安装 Pillow 库,它使我们能够通过使用以下命令打开、操作和保存许多不同的图像文件格式:
pip install pillow
Source: Author
初步测试:熟悉 Jupyter 笔记本电脑
您可以在默认的 web 浏览器中打开 Jupyter Notebook,方法是在 Anaconda 提示符下输入以下命令:
jupyter notebook
Source: Author
在您的笔记本仪表盘(打开笔记本的 web 浏览器)中,单击“新建”按钮并选择一个 Python 3 笔记本。注意:如果你想看到完整的代码和结果,你可以访问这个链接:https://github . com/riacheruvu/DemystifyMLCode/blob/master/OpenCV _ Example/OpenCV _ Example . ipynb。您还可以下载位于https://github.com/riacheruvu/DemystifyMLCode的这个博客的主存储库的 zip 文件,提取 zip 文件的内容,导航到 OpenCV_Example 文件夹,然后上传。ipynb 文件和图像到 Jupyter 笔记本上,以便跟踪和运行代码。
如果您使用的是新的 Python 3 笔记本:您可以通过在笔记本中的一个“代码单元”或空框中输入print("Hello, world")
或5+5
来测试安装是否正常进行,然后单击 Run 按钮。如果你以前用 Python 编程过,你会注意到你可以得到一个等式的输出,比如 5+5,而不需要使用 print()语句。如果你想了解更多,请看 Jupyter 笔记本文档(https://jupyter-notebook.readthedocs.io/en/stable/)。
为了快速测试是否安装了 numpy 包,在其中一个单元格中键入以下内容,以创建一个 numpy 数组,将其分配给一个变量,并打印变量的类型:
import numpy as npa = np.array([0, 1, 2])print(type(a))
a
的类型应该是<class‘numpy . ndarray’>。
OpenCV 入门:混合图像
为了开始并测试 OpenCV 是否已经正确安装,让我们实现图像混合,这涉及到对图像执行算术运算,并允许我们执行时间交叉融合,类似于电影、摄影幻灯片等中流行的特殊效果。
首先我们需要导入所需的包;在 Python 中,注释通过#符号后跟文本来描述。
import numpy as npimport cv2%matplotlib inline#Comment: The purpose of the above line is to display matplotlib plots inlineimport matplotlib.pyplot as pltimport matplotlib.image as mpimg
如果在这一步出现任何问题,请返回并检查您是否正确安装了软件包。如果你对软件包安装有任何疑问,请在下面的评论中分享。
接下来,从互联网上下载两张您选择的图像(您可以使用。JPG 或者。本教程图像的 PNG 文件格式)。对于这个例子,我使用的是以下照片,分别由 Josiah Weiss 在 Unsplash 和 Gül Kurtaran 在 Unsplash 拍摄。您可以下载。JPG 图片文件在下面提供的链接,或者右键单击这篇文章中的图片,并保存它们。确保将图片放在与您正在处理的笔记本文件相同的目录中。
Photo by Josiah Weiss on Unsplash
Photo by Gül Kurtaran on Unsplash
下载完图片后,下一步就是从文件名中读取图片。对于这一步,我们将使用 matplotlib 的 image.imread 函数,该函数将图像从文件读入 Numpy 数组,如该函数的文档中所述(【https://matplotlib.org/api/image_api.html】)。从每个图像输出的阵列需要具有相同的大小/尺寸;否则,我们将收到一条错误消息,指出:
error: OpenCV(3.4.2) C:\projects\opencv-python\opencv\modules\core\src\arithm.cpp:659: error: (-209:Sizes of input arguments do not match) The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array' in function 'cv::arithm_op'
我们可以通过使用 cv2.resize 命令将两个图像的高度和宽度调整为(300,300)来避免这个错误;如果您愿意尝试,可以更改高度和宽度的值。接下来,使用 matplotlib,我们可以绘制图像,给它一个标题,并在笔记本中显示它。
img_water = mpimg.imread(‘photo.jpg’)resized = cv2.resize(img_water, (300, 300))plt.imshow(resized)plt.title(‘Image’)plt.show()
img_horse = mpimg.imread(‘photo2.jpg’)resized2 = cv2.resize(img_horse, (300, 300))plt.imshow(resized2)plt.title(‘Image’)plt.show()
OpenCV 让我们能够使用 cv2.addWeighted 函数轻松地混合这些图像(类似于图像相加),该函数对图像应用以下等式,如 OpenCV 3.0.0-dev 文档中的“图像算术运算”一文所述:
在 cv2.addWeighted 函数的下一行代码中,每个图像名称后面的数字是权重(在上面的等式中定义),它可以在 0 到 1 之间变化,以混合图像并使它们更透明/不透明。例如,下面我对水的图像使用了 0.5 的权重,对骑马的女人的图像使用了 0.6 的权重。作为一个快速练习,尝试用 addWeighted 代码行的权重来观察交叉叠化的变化。代码行末尾的附加 0 表示 gamma 或,出于本教程的目的,我们将把它设置为零。
blend = cv2.addWeighted(resized,0.5,resized2,0.6,0)plt.imshow(blend)plt.title(‘Blended Image’)plt.show()
显示混合图像会产生以下令人惊叹的结果:
本教程到此结束;感谢您的阅读!如果你有任何反馈或问题,请在下面的评论中分享。
原载于 2018 年 8 月 30 日demystifymachinelearning.wordpress.com。
Python 环境入门(使用 Conda)
原文:https://towardsdatascience.com/getting-started-with-python-environments-using-conda-32e9f2779307?source=collection_archive---------0-----------------------
无论你想要一个还是不知道它是什么,你最终都必须用 Python 来处理
环境。如果你像我一样是 Python 的新手
或者是为任何编程语言设置工作空间的新手,那么你可能已经第一次经历了设置环境的痛苦。
我不知道自己在做什么,也不知道为什么有必要这么做,许多不同的在线指南可能没有完全相同的说明,还有许多帮助解决特定情况的堆栈溢出帖子,我发现很难理解到底什么是环境,什么时候需要它们,以及如何设置自己的环境。本指南旨在帮助建立对环境的直觉,并提供一些处理环境的例子,特别是使用 Anaconda 的包管理器 conda 。
你的代码是你的环境的产物
Python 和很多其他编程语言一样,有不同的版本。有时,当我们创建软件时,软件需要在特定版本的语言上运行,因为我们的软件期望在旧版本中出现某种行为,但在新版本中会发生变化。同样,出于类似的原因,我们可能需要使用特定版本的库。但是我们的电脑上可能有很多项目,可能是一个运行在 0.11 版本上的 Flask 应用(你做的第一个!)和 Python 2.7 甚至更现代的 Flask app,运行在版本 0.12 和 Python 3.4 上。如果我尝试在 Python 2 或 Python 3 上同时运行两个,其中一个可能会中断,因为在 Python 2 上运行的一些代码在 Python 3 上不能运行,反之亦然。这就是虚拟环境变得有用的地方。
虚拟环境将这些依赖关系保存在单独的“沙箱”中,因此您可以在两个应用程序之间轻松切换,并让它们运行。对于那些更熟悉编程的人来说,虚拟环境类似于 Docker 容器。此外,其他语言的包管理器,比如 JavaScript 的 NPM ( 节点包管理器),会帮你处理大部分细节,但是你必须亲自动手处理 Python 的环境。
创建你玩的沙盒
创建环境有多种方式,包括使用 virtualenv、venv(内置于 Python 3 标准库中)和 conda,
与 Anaconda 关联的包管理器。关于你为什么应该选择 conda 而不是 virtualenv 有一些争论,正如这篇博客文章中的神话#5 所概述的,但我将在本指南中重点关注如何使用 conda ,因为它是数据科学的一个流行工具,这也是我现在关注的重点。
本指南假设您已经安装了 Anaconda 或miniconda;所有的指令都在 bash 命令行上。
作为参考,我在 Mac OS X 的终端上运行我的命令。
要使用 conda 快速创建环境,您可以键入以下命令:
conda create --name your_env_name python=3.7 -y
在这个命令中,‘python = 3.7’部分指定了我想要在哪个版本的 python
中设置环境;您可以根据自己的需要更改版本。在你在网上看到的其他片段中,你可能会看到' -n '而不是'-name';它们的意思完全一样。' -y '标志实际上是告诉命令行对随后出现的所有提示说“是”;这不是绝对必要的,但它确实为您节省了一点麻烦。
conda create --name your_env_name python=3.7 scipy=0.15.0 astroid babel
命令将有效地一次加载所有的包,这比一次加载一个包要好,因为这会导致依赖冲突。所以你可以手动添加所有你需要的包,但是如果你有很多包,这可能会很乏味;
除此之外,在命令行
上会有大量的输入,手指滑动可能会导致你重新输入命令。更糟糕的是,该命令可能不会保留在您的 shell 历史中,如果您想要在将来重新创建完全相同的环境,即使不困难,也会非常繁琐。
如果出于这些或其他原因,您不想从命令行创建环境,您可以创建一个 YAML (YAML 不是标记语言)文件,它的作用就像一个配置文件。你的 YAML 文件可能是这样的:
name: your_env_name
channels:
— defaults
dependencies:
— ca-certificates=2018.03.07=0
prefix: /Users/your_username/anaconda3/envs/your_env_name
如果该文件名为' environment.yml' ,那么我可以使用下面的命令创建环境:
conda env create -f environment.yml
“ -f 标志代表文件, YAML 文件的文件名
应该紧跟在“ -f 标志之后。
如果你能很容易地创建一个 YAML 文件,并且知道你需要的所有包,那就太好了。但是,如果您有一个想要复制的现有环境,该怎么办呢?也许您希望将应用程序复制到另一台服务器上,并希望有完全相同的设置来保持一致性。如果是这种情况,那么您可以运行下面的命令。
conda env export > my_environment.yml
大于号“>”表示输出正在将
写入名为“ my_environment.yml ”的文件。如果在此命令之前' my_environment.yml' 中有任何内容
,它们将被覆盖。
注意,对于 conda 你需要一个 YAML 文件;如果你决定使用 virtualenv ,
一个 txt 文件也能满足这里所做的一切,但是 conda 特别需要一个 YAML 文件。
掌控您的环境
现在您已经创建了一个环境,并假设您正在使用 conda,让我们使用以下命令快速验证它是否存在:
conda info --envs
该命令应该显示当前环境,可能如下所示:
practice /Users/your_username/anaconda3/envs/practice
base /Users/your_username/anaconda3
your_env_name /Users/your_username/anaconda3/envs/your_env_name
在确认您创建了环境之后,您现在可以实际使用它了。我们可以通过键入以下命令来实现这一点(假设您的环境在您的基础之下):
conda activate your_env_name
此时,您的终端提示符应该如下所示:
(your_env_name) Your_Machine:your_directory username$
如果该命令由于某种原因没有产生类似的输出,
您可以通过键入类似以下命令的内容来指定完整路径:
conda activate /Users/your_username/anaconda3/envs/your_env_name
如果像我一样,您想知道当您键入单词“activate”时会发生什么,它会运行一个 bash 脚本,该脚本存在于环境的一个子目录中。在我的例子中,脚本的文件路径看起来像这样:
/Users/my_username/anaconda3/envs/my_env_name/lib/python3.6/venv/scripts/common/activate
要停止使用环境,请键入
conda deactivate
与 activate 命令类似,deactivate 命令运行 activate bash 脚本中的一个函数。
如果您想要更新环境,请键入:
conda env update –f environment.yml –n your_env_name
如果您想摆脱整个环境,只需键入:
conda remove --name your_env_name --all
“ —所有”标志用于从环境中移除所有软件包,并且
是彻底清洁环境所必需的。
结论
作为一个快速总结,本指南介绍了如何通过在命令行以及从 YAML 文件中指定包来创建您的虚拟环境,如何进入和退出虚拟环境,如何更新它,以及如何在您不再需要它时将其删除。
在这一点上,您应该知道足够的信息来独立地配置您认为合适的环境,并且有足够的背景来解释为什么您应该创建一个虚拟环境。虽然本指南没有深入探讨 virtualenv 、 venv 和 conda 虚拟环境之间的区别,但我在下面提供了几个链接让你开始。
请让我知道,如果你有任何问题或建议如何做得更好。
https://jakevdp . github . io/blog/2016/08/25/conda-myths-and-misconcepts/
https://real python . com/python-virtual-environments-a-primer/
https://medium . freecodecamp . org/why-you-need-python-environments-and-how-to-management-them-with-conda-85f 155 f 4353 c【中
开始使用 Python 进行数据分析
原文:https://towardsdatascience.com/getting-started-with-python-for-data-analysis-64d6f6c256b2?source=collection_archive---------4-----------------------
此文最初出现在blog.zakjost.com
最近有个朋友问了这个问题,我觉得在这里发表可能会对别人有好处。这是给刚接触 Python 的人的,他们想要从 0 到 1 的最简单的路径。
- 下载 Python 3。适用于您的操作系统的 x 版 Anaconda 发行版此处为。通过选择这个预捆绑的发行版,您将避免许多与安装相关的麻烦。它附带了大多数预先安装的重要数据分析软件包。
- 一旦你安装了它,测试以确保默认的 python 解释器就是你刚刚安装的那个。这一点很重要,因为您的系统可能已经安装了 Python 版本,但是它不具备 Anaconda 捆绑包中的所有优点,所以您需要确保新版本是默认版本。在苹果/Linux 上,这可能意味着在终端上输入
which python
。或者您可以运行 Python 解释器,确保版本与您下载的内容相匹配。如果一切顺利,应该通过安装来完成。如果没有,你需要在这里停下来修理它。 - 在你的外壳中发出
jupyter notebook
命令。这将打开一个浏览器窗口。如果没有,打开浏览器,导航到[http://localhost:8888](http://localhost:8888)
。一到那里,就创建一个新的 Python 笔记本。 - 转至www.kaggle.com的果仁部分,过滤至 Python 果仁。这些大多是其他人在数据集上进行分析或建模的 jupyter 笔记本,可在 Kaggle 的网站上免费获取。寻找像 EDA(探索性数据分析)这样的标题,而不是那些构建预测模型的标题。找到一个有趣的,并开始在你的笔记本中重新创建它。
注意:您会发现当您尝试重新创建这些分析时,您会得到导入错误。这可能是因为他们安装了 Anaconda 发行版中没有捆绑的包。你最终需要学习如何与 conda 包管理器交互,这将是你最终会陷入的许多兔子洞之一。通常就像
conda install <package_name>
一样简单,但是你需要找到正确的包名,有时你需要指定其他细节。其他时候你需要使用pip install <other_package_name>
,但是你会在以后学到这些。
高级库摘要
这里有一个您将经常与之交互的重要库的快速总结。
- NumPy:拥有许多科学计算的核心功能。在引擎盖下调用 C 编译的代码,所以比用 Python 写的相同函数要快得多。不是最用户友好的。
- SciPy:类似于 NumPy,但是有更多的方法从分布中取样,计算测试统计…等等。
- MatPlotLib:主绘图框架。不可避免的邪恶。
- Seaborn:在 MatPlotLib 之后导入它,默认情况下它会让你的绘图漂亮很多。也有自己的功能,但我发现最酷的东西运行太慢。
- 熊猫:主要是一个薄薄的包装,让用户更加友好。非常适合与数据表交互,他们称之为数据框架。也有关于绘图功能的包装器,以支持快速绘图,同时避免 MPL 的复杂性。我最喜欢用熊猫来处理数据。
- Scikit-learn:有很多监督和非监督的机器学习算法。也有许多用于模型选择的度量标准和一个很好的预处理库,用于像主成分分析或编码分类变量这样的事情。
快速提示
- 在 jupyter 笔记本中,在运行单元格之前,在任何对象前面打一个问号,它将打开该对象的文档。当你忘记了你试图调用的函数期望你传递的细节时,这真的很方便。例如,
?my_dataframe.apply
将解释pandas.DataFrame
对象的apply
方法,这里用my_dataframe
表示。 - 你可能总是需要参考你正在使用的库的文档,所以只要在你的浏览器中打开它。有太多可选的论点和细微差别。
- 当谈到不可避免的故障排除任务时,s tackoverflow 可能有答案。
- 接受这样一个事实,你会做一些你暂时还不完全理解的事情,否则你会被那些不重要的细节所困扰。有一天,你可能需要了解虚拟环境,这真的不是很难,但有许多类似的弯路会给初学者增加不必要的痛苦。
- 看别人的代码。这是学习惯例和最佳实践的最佳方式。这就是 Kaggle 内核真正发挥作用的地方。GitHub 还支持在浏览器中显示 jupyter 笔记本,因此互联网上有大量的例子。
PyTorch 入门第 1 部分:了解自动微分的工作原理
原文:https://towardsdatascience.com/getting-started-with-pytorch-part-1-understanding-how-automatic-differentiation-works-5008282073ec?source=collection_archive---------1-----------------------
更新:这个帖子是 2018 年初写回来的。PyTorch 已经走过了漫长的道路,更新版本的帖子可以在这里找到。
当我开始编写神经网络代码时,我最终使用了我周围所有人都在使用的东西。张量流。
但是最近,PyTorch 已经成为深度学习框架之王的主要竞争者。真正吸引人的是它的动态计算图范例。如果最后一行对你来说没有意义,也不要担心。在这篇文章的结尾,它会的。但请相信我的话,它使调试神经网络的方式更容易。
If you’re wondering why your energy has been low lately, switch to PyTorch!
先决条件
在我们开始之前,我必须指出,你至少应该有这样的基本概念:
- 与神经网络训练相关的概念,特别是反向传播和梯度下降。
- 应用链式法则计算导数。
- Python 中类的工作原理。(或者关于面向对象编程的一般概念)
如果你错过了以上任何一个,我在文章的最后提供了链接来指导你。
所以,是时候开始使用 PyTorch 了。这是 PyTorch 系列教程的第一篇。
这是第 1 部分,我将描述基本的构建模块,以及亲笔签名的。
****注意:需要注意的一点是,本教程是为 PyTorch 0.3 及更低版本制作的。提供的最新版本是 0.4。我决定坚持使用 0.3,因为到目前为止,0.3 是在 Conda 和 pip 渠道中发布的版本。此外,开源中使用的大部分 PyTorch 代码还没有更新到包含 0.4 中提出的一些更改。然而,我会指出,在某些地方,事情在 0.3 和 0.4 不同。
积木#1:张量
如果你曾经用 python 做过机器学习,你很可能遇到过 NumPy。我们使用 Numpy 的原因是因为它在做矩阵运算时比 Python 列表快得多。为什么?因为它完成了 c 语言中的大部分繁重工作。
但是,在训练深度神经网络的情况下,NumPy 阵列根本不能满足它。我懒得在这里做实际的计算(Google for“FLOPS in a iteration of ResNet to get a idea”),但是仅使用 NumPy 数组的代码就需要几个月的时间来训练一些最先进的网络。
这就是张量发挥作用的地方。PyTorch 为我们提供了一种叫做张量的数据结构,与 NumPy 的 ndarray 非常相似。但与后者不同的是,张量可以利用 GPU 的资源来显著加快矩阵运算的速度。****
这是你做张量的方法。
In [1]: import torch In [2]: import numpy as npIn [3]: arr = np.random.randn((3,5))In [4]: arr
Out[4]:array([[-1.00034281, -0.07042071, 0.81870386],
[-0.86401346, -1.4290267 , -1.12398822],
[-1.14619856, 0.39963316, -1.11038695],
[ 0.00215314, 0.68790149, -0.55967659]])In [5]: tens = torch.from_numpy(arr)In [6]: tens
Out[6]:
-1.0003 -0.0704 0.8187
-0.8640 -1.4290 -1.1240
-1.1462 0.3996 -1.1104
0.0022 0.6879 -0.5597
[torch.DoubleTensor of size 4x3]In [7]: another_tensor = torch.LongTensor([[2,4],[5,6]])In [7]: another_tensor
Out[13]: 2 4
5 6
[torch.LongTensor of size 2x2]In [8]: random_tensor = torch.randn((4,3))In [9]: random_tensor
Out[9]:1.0070 -0.6404 1.2707
-0.7767 0.1075 0.4539
-0.1782 -0.0091 -1.0463
0.4164 -1.1172 -0.2888
[torch.FloatTensor of size 4x3]
构建模块#2:计算图
现在,我们在商业方面的事情。当训练神经网络时,我们需要计算损失函数相对于每个权重和偏差的梯度,然后使用梯度下降来更新这些权重。
随着神经网络达到数十亿个权重,高效地执行上述步骤可以决定训练的可行性。
构建模块#2.1:计算图表
计算图是现代深度学习网络工作方式的核心,PyTorch 也不例外。让我们先了解一下它们是什么。
假设,你的模型是这样描述的:
*b = w1 * a
c = w2 * a
d = (w3 * b) + (w4 * c)
L = f(d)*
如果我真的画出计算图,它可能会像这样。
Computation Graph for our Model
****现在,你必须注意到,上图并不完全是 PyTorch 在引擎盖下的图表的准确表示。然而,就目前而言,这足以证明我们的观点。
当我们可以顺序执行计算输出所需的操作时,为什么要创建这样的图形呢?
想象一下,如果你不仅要计算输出,还要训练网络,会发生什么。你必须计算所有紫色节点标记的权重的梯度。这将需要你找到自己的方式,然后更新权重。
计算图是一种简单的数据结构,允许您有效地应用链规则来计算所有参数的梯度。
Applying the chain rule using computation graphs
这里有一些需要注意的事情。首先,图中箭头的方向现在颠倒了。那是因为我们是反向传播,箭头标记的是梯度反向流动。
第二,为了这些例子,你可以把我写的渐变想象成边缘权重。注意,这些梯度不需要计算链式法则。
现在,为了计算任意节点的梯度,比如 L,相对于任意其他节点,比如 c ( dL / dc) 我们要做的就是。
- 追踪从 L 到 c 的路径。这将是L→d→c**
- 沿着这条路径遍历时,将所有的边权重相乘。你最终得到的数量是:(dL/DD)**(DD/DC)=(dL/DC)***
- 如果有多条路径,将它们的结果相加。例如,在 dL/da 的情况下,我们有两条路径。 L → d → c → a 和 L→d→b→a我们将它们的贡献相加得到L w r t a的梯度**
(dL/DD)**(DD/DC)**(DC/da)】+[(dL/DD)**(DD/db)(*db/da)】***
原则上,可以从 L 开始,开始向后遍历图形,计算沿途每个节点的梯度。
构建块#3:变量和亲笔签名
PyTorch 使用亲笔签名的包完成了我们上面描述的任务。**
现在,关于亲笔签名的是如何工作的,基本上有三件重要的事情需要理解。**
构建模块#3.1:变量
**变量,就像张量一样,是一个用来保存数据的类。然而,它的不同之处在于它的使用方式。 变量专门用于保存在神经网络训练期间变化的值,即我们网络的可学习参数。另一方面,张量用于存储不需要学习的值。例如,张量可用于存储每个示例产生的损失值。
**from torch.autograd import Variablevar_ex = Variable(torch.randn((4,3)) #creating a Variable**
一个变量类包装了一个张量。你可以通过调用 来访问这个张量。数据变量的属性。**
**变量也存储标量(比如说损耗)相对于它所保存的参数的梯度。这个渐变可以通过调用 来访问。grad 属性。这基本上是直到这个特定节点计算的梯度,并且每个后续节点的梯度可以通过将边权重乘以在它之前的节点计算的梯度来计算。
一个变量持有的第三个属性是一个 grad_fn ,一个函数对象,它创建了这个变量。****
注: PyTorch 0.4 将变量和张量类合二为一,张量可以通过一个开关做成一个“变量”而不是实例化一个新的对象。但是既然,我们在本教程中做的是 v 0.3,我们就继续吧。
构建模块#3.2:功能
我上面说功能了吗?它基本上是一个函数的抽象。接受输入并返回输出的东西。比如我们有两个变量, a 和 b ,那么如果,**
c = a + b
然后 c 是一个新变量,它的 grad_fn 是一个叫做 AddBackward (PyTorch 内置的两个变量相加的函数),这个函数以 a 和 b 为输入,创建了 c 。**
那么,你可能会问,既然 python 确实提供了定义函数的方法,为什么还需要一个全新的类呢?
训练神经网络时,有两个步骤:前向传递和后向传递。通常,如果您使用 python 函数来实现它,您将必须定义两个函数。一个是计算正向传递期间的输出,另一个是计算要传播的梯度。
PyTorch 将编写两个独立函数(用于向前传递和向后传递)的需求抽象成一个名为torch . autograded . function .的类的两个函数成员**
PyTorch 结合了变量和函数来创建一个计算图。****
积木#3.3:亲笔签名
现在让我们深入研究 PyTorch 如何创建计算图。首先,我们定义变量。
上面几行代码的结果是,
现在,让我们分析一下刚刚到底发生了什么。如果您查看源代码,事情是这样的。
- 定义图形的叶变量(第 5-9 行)。我们从定义一堆“变量”开始(正常的,python 语言的用法,不是 pytorch 变量)。如果您注意到,我们定义的值是我们的计算图中的叶节点。只有我们必须定义它们才有意义,因为这些节点不是任何计算的结果。现在,这些家伙占用了我们 Python 名称空间中的内存。意味着,它们是百分之百真实的。我们必须将requires _ grad***属性设置为 True,否则,这些变量将不会包含在计算图形中,并且不会为它们计算任何梯度(以及依赖于这些特定变量进行梯度流的其他变量)。*****
- 创建图表(第 12-15 行)。到目前为止,我们的记忆中还没有计算图之类的东西。只有叶节点,但是只要您写下第 12–15 行,一个图就会被动态生成。确定这个细节非常重要。在飞行中。**当你写 b =w1a 时,就是图形创建开始的时候,一直持续到第 15 行。当从输入中计算输出时,这正是我们模型的正向传递。每个变量的正向函数可以缓存一些输入值,以便在计算反向传递的梯度时使用。(例如,如果我们的 forward 函数计算出 Wx ,那么 d(Wx)/d(W) 就是 x ,需要缓存的输入)***
- 现在,我告诉你我之前画的图不准确的原因?因为 PyTorch 做图的时候,并不是变量对象才是图的节点。它是一个函数对象,确切地说,是构成图形节点的每个变量的 grad_fn 。PyTorch 图应该是这样的。****
Each Function is a node in the PyTorch computation graph.
- 我用名字表示了叶节点,但是它们也有自己的grad _ fn’(返回 None 值。这是有意义的,因为您不能反向传播到叶节点之外)。剩下的节点现在被它们的grad _ fn’所代替,我们看到单个节点 d 被三个函数代替,两个乘法,一个加法,而 loss 被一个减函数代替。****
- 计算梯度(第 18 行)。我们现在通过调用来计算梯度。 L 上的 backward() 功能。这到底是怎么回事?首先,L 处的梯度就是 1 ( dL / dL )。然后,我们调用它的向后函数,它的基本工作是计算函数对象的输出到函数对象的输入的梯度。**这里 L 是 10 — d 的结果,也就是说,逆向函数会将梯度( dL/dd) 计算为-1。****
- 现在,这个计算的梯度乘以累积的梯度(存储在当前节点对应的变量的 grad 属性中,在我们的例子中是 dL/dL = 1 ),然后发送到输入节点,存储在输入节点对应的变量 grad 属性中。技术上,我们所做的是应用链式法则(dL/dL)(dL/DD)=dL/DD。***
- 现在,让我们了解梯度是如何传播给变量 d 的。d 是从它的输入(w3,w4,b,c)计算出来的。在我们的图中,它由 3 个节点、2 个乘法和 1 个加法组成。**
- 首先,函数 AddBackward ( 在我们的图中表示节点 d 的加法运算)计算它的输出( w3b + w4c )相对于它的输入( w3b 和 w4c* )的梯度,这是(两者都是 1)。现在,这些局部梯度乘以累积梯度(两者都是 dL/dd x 1 = -1),结果保存在各自输入节点的 grad 属性中。***
- 然后,函数 MulBackward ( 代表 w4c 的乘法运算)分别计算其输入输出 w.r.t 到其输入( w4 和 c) a s (c 和 w4) 的梯度。局部梯度乘以累积梯度( dL/d(w4c) = -1)。结果值( -1 x c 和-1 x w4 )然后分别存储在变量* w4 和 c 的 grad 属性中。***
- 所有节点的梯度以相似的方式计算。
- L w.r.t 任何节点的梯度都可以通过调用来访问。 grad 在对应于那个节点的变量上,假设它是一个叶节点 (PyTorch 的默认行为不允许你访问非叶节点的渐变。稍后会有更多相关内容)。现在我们已经得到了梯度,我们可以使用 SGD 或任何你喜欢的优化算法来更新我们的权重。
*w1 = w1 — (learning_rate) * w1.grad #update the wieghts using GD*
诸如此类。
亲笔签名的一些俏皮细节
所以,我不是告诉过你不能访问非叶子变量的 grad 属性吗。是啊,这是默认行为。您可以通过调用来重写它。 retain_grad() 对变量进行定义,然后你就可以访问它的 grad 属性。但是说真的,到底发生了什么事。**
动态计算图
PyTorch 创建了一个叫做的动态计算图,这意味着这个图是动态生成的。在变量的 forward 函数被调用之前,图中不存在变量的节点(它是 grad_fn) 。*该图是调用多个变量的前进功能的结果。只有这样,缓冲区才会分配给图形和中间值(用于以后计算梯度)。当您调用 backward() 时,随着梯度的计算,这些缓冲区基本上被释放,图形被破坏。你可以尝试在一个图形上多次向后调用(),你会看到 PyTorch 会给你一个错误。这是因为图形在第一次调用 backward() 时被破坏,因此,第二次调用时没有图形可以向后调用。***
如果再次调用 forward ,会生成一个全新的图形。分配了新的内存。
默认情况下,只保存叶节点的渐变( grad 属性),非叶节点的渐变被破坏。但是这种行为是可以改变的,如上所述。
这与 TensorFlow 使用的静态计算图形成对比,tensor flow 在运行程序的 之前声明了 。动态图范例允许您在运行时对网络架构进行更改,因为只有在运行一段代码时才会创建一个图。这意味着一个图可以在程序的生命周期中被重新定义。然而,这对于静态图形是不可能的,在静态图形中,图形是在运行程序之前创建的,只是在以后执行。动态图也使调试更容易,因为错误的来源很容易追踪。
一些贸易技巧
要求 _grad
这是变量类的一个属性。默认情况下,它是 False。当你不得不冻结一些层,并阻止他们在训练时更新参数时,这是很方便的。您可以简单地将 requires_grad 设置为 False,这些变量不会包含在计算图中。因此,没有梯度会传播到它们,或者传播到依赖这些层进行梯度流动的那些层。 requires_grad ,设置为 True 时 会传染,意思是即使一个运算的一个操作数 requires_grad 设置为 True,结果也会如此。****
b is not included in the graph. No gradient is backpropagated through b now. a only gets gradients from c now. Even if w1 has requires_grad = True, there is no way it can receive gradients.
不稳定的
这也是一个变量类的属性,当变量被设置为真时,它会导致变量被排除在计算图之外。这可能看起来与要求 _grad 非常相似,因为当设置为真时也会传染。但是比要求 _ grad优先级高。带有 requires_grad 等于真且 volatile 等于真的变量将不包括在计算图中。****
你可能会想,当我们可以简单地将 requires_grad 设置为 False 时,为什么还需要另一个开关来覆盖 requires_grad ?我暂时跑题一下。
当我们进行推理时,不创建图形是非常有用的,并且不需要梯度。首先,消除了创建计算图的开销,提高了速度。第二,如果我们创建一个图形,由于没有向后被调用,用于缓存值的缓冲区永远不会被释放,这可能会导致内存耗尽。**
通常,我们在神经网络中有许多层,我们可能在训练时将 requires_grad 设置为 True。为了防止在推断时制作图表,我们可以做两件事中的任何一件。设置 r equires_grad False 在所有层上(也许,152 层?).或者,只在输入端设置 volatile 为真,我们保证没有任何结果操作会产生一个图形。你的选择。
No graph is created for b or any node that depends on b.
注意: PyTorch 0.4 没有组合张量/变量类的可变参数。相反,推理代码应该放在 torch.no_grad()上下文管理器中。
**with torch.no_grad():
----- your inference code goes here ----**
结论
所以,那是给你的签名。理解签名是如何工作的,可以在你被困在某个地方时,或者在你开始时处理错误时,帮你省去很多头痛。感谢阅读到目前为止。我打算在 PyTorch 上写更多的教程,讨论如何使用内置函数快速创建复杂的架构(或者,可能没有这么快,但比一个块一个块地编码要快)。所以,敬请期待!****
进一步阅读
- 理解反向传播
- 理解链式法则
- Python 中的类第一部分和第二部分
- PyTorch 官方教程
开始阅读深度学习研究论文:为什么和如何
原文:https://towardsdatascience.com/getting-started-with-reading-deep-learning-research-papers-the-why-and-the-how-dfd1ac15dbc0?source=collection_archive---------3-----------------------
在你读完那本书或完成那门令人惊叹的关于深度学习的在线课程后,你是如何继续学习的?你如何变得“自给自足”,这样你就不必依赖别人来分解该领域的最新突破?
你阅读研究论文。
Photo by Emma Frances Logan on Unsplash
开始前的一个小提示——我不是深度学习方面的专家。我最近才开始阅读研究论文。在这篇文章中,我将写下我开始时发现的所有有用的东西。
为什么
在 Quora 上的一个问题的回答中,问到如何测试一个人是否有资格从事机器学习的职业,吴恩达(Google Brain 创始人,百度 AI 集团前负责人)表示,任何人都有资格从事机器学习的职业。他说,在你完成了一些与 ML 相关的课程之后,“为了更进一步,阅读研究论文。更好的是,尝试在研究论文中复制这些结果。”
Dario amo dei(open AI 的研究员)说“为了测试你是否适合在 AI safety 或 ML 中工作,只需尝试非常快速地实现许多模型。从最近的一篇论文中找到一个 ML 模型,实现它,尝试让它快速工作。”
这表明阅读研究论文对加深一个人对该领域的理解至关重要。
每个月都有数百篇论文发表,任何认真研究这一领域的人都不能仅仅依靠导师式的文章或课程,在这些文章或课程中,其他人会为他/她分解最新的研究。当你阅读这篇文章时,新的、突破性的研究正在进行。该领域的研究步伐从未如此之快。你能希望跟上这种步伐的唯一方法是养成一种习惯,在研究论文发布时阅读它们。
在这篇文章中,我将尝试给你一些可行的建议,告诉你如何开始自己阅读论文。然后,最后,我会试着分解一份实际的文件,这样你就可以开始了。
怎么做
首先,阅读一篇科研论文是困难的。事实上—
“没有什么比阅读科学期刊文章更让你感到愚蠢的了。”
我只是想把它放在第一位,这样如果你觉得你不能真正理解一篇论文的内容,你就不会气馁。你不太可能在前几遍就理解它。所以,勇敢一点,再试一次!
现在,让我们来谈谈一些有价值的资源,它们将在你的阅读之旅中对你有所帮助..
arXiv.org
把它想象成互联网上的一个地方,研究人员在他们的论文真正发表在那些著名的科学杂志或会议(如果有的话)之前,在那里发表它们。
他们为什么要这么做?
嗯,事实证明做研究和实际写论文并不是它的结束。).从提交论文到在一些科学杂志上发表是一个相当长的过程。在一篇论文被提交到这些期刊之后,会有一个相当缓慢的同行评审过程,有时甚至会持续数年!)现在,对于机器学习这样一个快速发展的领域来说,这确实是不可取的。
这就是为什么, arXiv 。
研究人员将他们的论文发布在 arXiv 这样的预印库上,以便快速传播他们的研究并获得快速反馈。
Arxiv 理智保护者
好吧,所以允许研究人员容易地预印他们的研究论文是好的。但是读这些报纸的人呢?如果你去 arXiv 网站,很容易感到害怕和渺小和失落。绝对不是新人的地方(只是我的看法,欢迎你来试试虽然☺ )。
进入, Arxiv 理智保护者。
Built by Andrej Karpathy, director of AI at Tesla and a personal favourite AI guy of mine
Arxiv Sanity 对 Arxiv 的作用,就像 Twitter 的 newsfeed 对 Twitter 的作用一样(显然,除了它是完全开源和无广告的)。正如 newsfeed 可以让你从 Twitter 的汪洋大海中看到最有趣的推文,个性化到你自己的口味,类似地,Arxiv Sanity 为你带来了发表在 Arxiv 上的关于 ML 的论文,这可能是你最感兴趣的。它可以让你根据流行趋势,根据你过去的喜好和你关注的人的喜好对报纸进行分类。(只是那些我们在社交媒体上已经习以为常的个性化推荐功能。)
Check out this short introductory video of the website to know more about it
机器学习 Reddit 上的 WAYR 线程
WAYR 是你在读什么的简称。这是子编辑机器 learningg 上的一个线程,人们在这里发布他们本周阅读的 ML 论文,并讨论他们从中发现的有趣内容。
我说过,arXiv 上每周发表的机器学习领域的研究论文数量极其庞大。这意味着一个人几乎不可能每周读完所有的书,并做一些常规的事情,如上大学、去工作或与他人交流。此外,并不是所有的报纸都值得一读。
因此,你需要把精力放在阅读最有前途的论文上,我上面提到的思路就是一种方法。
时事通讯,时事通讯,时事通讯!
时事通讯是我个人了解人工智能领域最新进展的最佳来源。你只需订阅它们,每周一免费将它们发送到你的收件箱。就这样,你可以了解到本周与 AI 相关的最有趣的新闻、文章和研究论文。
以下是我订阅的内容:
- 杰克·克拉克这是我最喜欢的,因为除了提供我上面提到的所有信息外,它还有一个叫做“科技故事”的部分。本部分包含一个基于上周事件的新的人工智能相关的科幻短篇故事!
..坦白说:即使在我对人工智能的新事物不感兴趣的那几周,我也会浏览一下这份时事通讯,仅仅是因为科技故事) - Sam DeBrule他还经营着一家同名的媒体刊物。它包含了一些真正有趣的文章。一定要检查他们了。
- Nathan . ai by Nathan bena ich虽然以上两篇简讯都是周刊,这是季刊。因此,你每三个月就会收到一封长长的电子邮件,总结了过去三个月该领域最有趣的进展。
- 丹尼·布里兹的《AI 中的狂野一周》我很喜欢这本书,因为它干净、简洁,但似乎在过去的两个月里它变得不活跃了。无论如何,我在这里提一下,以防丹尼又开始发那些邮件。
推特上的“AI 人”
另一个好方法是关注 Twitter 上著名的研究人员和开发人员的账户,这样你就可以跟上这个领域最好的和最新的信息。这是我关注的人的名单:
- 迈克尔·尼尔森
- 安德烈·卡帕西
- 弗朗索瓦·乔莱
- 扬·勒村
- 克里斯·奥拉赫
- 杰克·克拉克
- 伊恩·古德费勒
- 杰夫·迪恩
- 我知道这不是“人”,但是是的..)
“那很好,但是我该怎么开始呢??"
是的,这是更紧迫的问题。
好的,首先要确保你理解机器学习的基础知识,比如回归和其他类似的算法,深度学习的基础知识——普通的神经网络,反向传播,正则化,以及比康涅茨,RNN 和 LSTM 的工作原理多一点的基础知识。我真的不认为阅读研究论文是明确你对这些主题的基础知识的最佳方式。为此,您可以参考大量其他资源。
一旦你做到了这一点,你应该开始阅读一篇最初介绍上述观点的论文。这样,你就可以专注于习惯一篇研究论文的样子。你不必太担心如何理解你的第一篇研究论文,因为你已经非常熟悉这个想法了。
我推荐你从Alex net 论文 入手。
为什么要这篇论文?
请看这张图表:
看看Computer Vision and Patter Recognition
曲线是如何在 2012 年直线上升的?这很大程度上是因为这篇论文。
T44!!!
就是这篇论文重新点燃了所有人对深度学习的兴趣。
由 Alex Krizhevsky、Ilya Sutskever、Geoffrey Hinton、和撰写,标题为ImageNet class ification with Deep convolution Networks,这篇论文被认为是该领域最有影响力的论文之一。它描述了作者如何使用 CNN (名为 AlexNet) 赢得 2012 年 ImageNet 大规模视觉识别挑战赛(ILSVRC)。
对于那些不知道的人来说,使计算机能够看到和识别物体(又称计算机视觉)是计算机科学的最早目标之一。ILSVRC 就像这种“视觉计算机”的奥运会,参与者(计算机算法)试图正确识别属于 1000 个类别之一的图像。而且,在 2012 年,AlexNet 能够以巨大的优势赢得这项挑战: 它取得了 15.3%的前五名错误率,而第二名的错误率为 26.2%。
不用说,整个计算机视觉社区都肃然起敬,该领域的研究以前所未有的速度发展。人们开始意识到深度神经网络的力量,那么,在这里你试图理解你如何才能得到一块馅饼!
也就是说,如果您通过一些课程或教程对 CNN 有了基本的了解,那么掌握本文的内容将会相当容易。所以,给你更多的力量!
一旦你完成了这篇论文,你可能会查阅其他与 CNN 相关的开创性论文,或者转向你感兴趣的其他架构(RNNs、LSTMs、GANs)。
Github 上也有很多仓库,里面收藏了深度学习方面的重要研究论文(这里有一个很酷的)。当你开始的时候,一定要检查它们。他们会帮助你建立自己的阅读清单。
如果我不提及这另一个来源,那将是非常不负责任的
- Distill . pub:* 关于这一点,我只有一句话要说——
如果所有的研究论文都发表在 distilt 期刊上,那么很可能,我就不会写这篇文章了,你也不需要阅读一篇文章来指导你阅读研究论文,互联网上也将需要更少(如果有的话)的课程和教程来试图用可理解的术语解释那些开创性的研究观点。 我会让迈克尔·尼尔森给你一个更恰当的《蒸馏日志》背后的动机:*
** [## 蒸馏:机器学习研究的交互式可视化期刊
《蒸馏》杂志今天发行。简而言之,Distill 是一个用于机器学习的交互式可视化杂志…
blog.ycombinator.com](https://blog.ycombinator.com/distill-an-interactive-visual-journal-for-machine-learning-research/)
因此,请务必查看中的篇文章。这真的是下一代的东西!**
感谢您从头到尾的阅读!我希望这篇文章能帮助你跟上最新的 ML 研究。记住,阅读科学论文是困难的。所以,没有必要气馁。如果你不理解,就再读一遍。
**编辑:发表这篇文章帮助我与世界各地令人惊叹的专业人士建立了数百种联系。
你想像我一样写作吗?
我开设了一门写作课程,教你如何在互联网上开始写作之旅。这就叫——清晰写作,清晰思考 而我 免费赠送 !
Clear Writing, Clear Thinking — a free 5-week email course that’ll teach you how to write well
你可以在 Twitter 上关注我,或者在 LinkedIn 上联系我,我不会给你发垃圾信息。;-)
强化 Q 学习入门
原文:https://towardsdatascience.com/getting-started-with-reinforcement-q-learning-77499b1766b6?source=collection_archive---------2-----------------------
简介
当 DeepMind 的 AlphaGo 击败围棋世界冠军李·塞多尔(Lee Sedol)时,人工智能(AI)真正崛起。人工智能代理的基本构建模块是 Q 学习,所以让我们直接进入它。正如著名作家安德鲁·特拉斯克所说的那样,“我用可以玩的玩具代码学得最好”。所以下面你会发现我们的玩具代码只使用了 Numpy,我们将在本文的其余部分更详细地讨论它。
什么是强化学习?
强化学习有一个“环境”和一个“代理”,前者是我们试图解决的问题集,后者是我们的人工智能算法。环境和代理之间的关系非常简单。代理将执行某些动作(像我们的玩具代码中的出租车上、下、右、左等移动),作为该动作的结果,他的状态将改变(出租车的新位置),这将导致代理获得奖励(到达其目的地的正奖励,或者如果您错误地搭载或放下乘客,则为负奖励)。通过行动和奖励过程的迭代,代理学习环境。它开始明白在哪个状态下,哪个动作给他最大的奖励,哪个动作给他负的奖励。这个执行一个动作并从奖励中学习的过程叫做强化学习。
贝尔曼方程
让我们假设我们的代理在相邻 gif 的“开始”图像所示的环境中开始。最初,它只是做一些随机的运动,比如向右、向左、向上、向下等,最终在某个时候,它会到达目的地。现在只要它到达目的地,它就会得到奖励,比如说+1 分。这触发算法意识到这个地方(绿色方块)是它需要的地方。然后代理开始问问题,我是怎么到这个方块的,我之前是什么状态,我做了什么让我得到奖励。因此,它回顾和回溯其先前的状态,如下图所示
它首先用虚拟奖励“1”标记绿色方块左边的方块,告诉自己他只需要到达前面的方块,然后它需要做的只是向右移动,他就会到达目的地。这个过程继续,直到他回溯他的完整路径。这种路由回溯,代理执行多次迭代。
现在,如果我们永远不重置代理,一切都可以工作了,它会一直保持在 ON 状态,并在内存中记忆他刚才绘制的地图。但是,如果代理重置,并且下次被调用时从不同的状态启动,会发生什么呢?现在他很困惑,不知道该做什么,这就是为什么这种方法没有真正发挥作用。
这就是贝尔曼方程发挥作用的地方。
贝尔曼方程-> V(s) = max(R (s,a)+γV(s′))其中 V(s)是任意给定状态下的一个值
s —状态,a —行动,R —奖励,γ —折扣,s' —采取行动‘a’后的下一个状态
贝尔曼方程说的是,一个国家的价值。V(s ),等于通过执行任何允许的动作 R(s,a)你可以从该状态获得的不同奖励的最大值,以及通过采取特定动作“a”你将到达的新状态的“贴现”值。参考下面的 gif 图可以更好的理解上面的公式。
目的地绿色方块左边的方块的值是 1,因为如果我们向右移动,我们可以得到 1 的奖励。回溯,现在不是像前面的情况一样将下一个左边的方块也指定为 1,而是使用伽玛值为 0.9 的贝尔曼方程,并将下一个方块的值指定为 0.9,对于路线的其余部分以此类推。
同样,我们可以原路返回,填满我们的地图。现在我们已经创建了我们的地图,对于我们的代理来说,无论它从哪个位置开始,它应该走哪条路都变得非常明显。
有了对强化学习和贝尔曼方程的清晰理解,让我们来看看我们的玩具代码,看看它是如何实现上述概念的。为了更好的理解,我将逐行解释完整的代码。
问题陈述:有 4 个地点(用不同的字母标注),你的工作是在一个地点接乘客,在另一个地点让他下车。你成功脱手可获得+20 分,每完成一个时间步长将失去 1 分。非法上下车行为还会被扣 10 分。在此环境中,实心正方形代表出租车,(" | ")代表墙壁,蓝色字母代表上车地点,紫色字母代表下车地点。出租车上有乘客时会变绿
代码走查
第 1–3 行:导入所需的库
#Importing Libararies
import gym
import numpy as np
第 5–8 行:设置开放的健身房环境。这只是建立任何健身房环境的标准方式
#Environment Setup
env = gym.make("Taxi-v2")
env.reset()
env.render()
第 10–17 行:首先,让我们看看我们的代理在随机选择要执行的动作时表现如何。
第 11 行:获取当前状态,即阻塞代理所处的状态。对于此特定环境,该值可以在 0–499 之间。
# Random Moments
state = env.reset()
第 12 行和第 13 行:初始化计数器和奖励。在这一点上,我会建议你手动玩环境,只是为了感受一下。在你的代码中使用下面两个例子来将代理置于特定的状态,或者使它向你喜欢的方向移动。
counter = 0
reward = None# Change state
env.env.s = 114
env.render()# Take an action
env.step(3)
env.render()
第 14 行:直到我们得到 20 英镑的奖励,这是我们正确放下乘客的奖励。
while reward != 20:
第 15 行:env.action_space.sample()是一个 gym 函数,它返回从允许的动作中选择的一个随机动作。我们调用 env.step()来执行这个随机选择的动作。env.step()总是返回新的状态、对前一个动作的奖励、挑战是否完成,以及一些对调试有用的附加信息。我们将所有这些值存储在各自的变量中,仅供参考。
state, reward, done, info = env.step(env.action_space.sample())
第 16 行:由于我们已经走了一步,我们将计数器加 1
counter += 1
第 17 行:每当我们最终将乘客送到正确的位置时,我们将退出 while 循环(因为收到的奖励将是 20)。打印计数器值,指示该特定迭代完成任务所用的步骤数。玩几次 while 循环,了解在随机采取行动的情况下完成挑战需要多少步。我们将把这个值与我们通过实现强化学习算法得到的值进行比较。
print(counter)
第 20 行:我们通过创建一个“可能状态的数量”到“可能动作的数量”维度的矩阵来开始 Q(强化)学习。记住,从我们的学习中,我们需要为每个状态和该状态下允许的每个动作保持一个 Q 值(贝尔曼方程中的 V(s))。正如在解释贝尔曼方程时所说的,最初代理不知道任何 Q 值,所以我们用全零初始化它。
Q = np.zeros([env.observation_space.n, env.action_space.n])
第 21 行:初始化奖励变量 G(因为变量‘reward’用于存储 env.step()给出的返回值,这里使用其他变量名 G)
G = 0
第 22 行:使用伽玛值 0.618。这纯粹是实验出来的。你可以试试你的价值观,在这里分享你的结果,只是为了比较。
gamma = 0.618
第 23 行:对于上千次迭代
for episode in range(1,1001):
第 24 行:初始化“done”值,我们将使用它在完成任务后退出 while 循环。
done = False
第 25 行:每次迭代各自的值初始化
G, reward, counter = 0,0,0
第 26 行:重置环境并获取其状态
state = env.reset()
第 27 行:虽然我们还没有“完成”
while done != True:
第 28 行:现在当创建 Q 矩阵时,记住我们已经创建了维度行= '可能状态的数量'和列= '可能动作的数量'。np.argmax(Q[state])从 Q 矩阵的行“state”中挑选出最大值。换句话说,它获取当前状态,在 Q 矩阵中查找,找到该状态的特定行,并返回沿着该行的最大值的索引(这将是“动作”号)
action = np.argmax(Q[state])
第 29 行:使用上面获得的“动作”来执行一个步骤并存储其结果。
state2, reward, done, info = env.step(action)
第 30 行:根据贝尔曼方程和上一步得到的结果更新我们的 Q 表。如果你遵循了本教程,你应该能够清楚地将这条线与上一节描述的贝尔曼方程对应起来。
Q[state,action] = (reward + gamma * np.max(Q[state2]))
第 31–33 行:更新了相应的变量
G += reward
counter += 1
state = state2
第 35 行:打印迭代,每 50 次迭代的奖励和计数器值。检查这些值,并将其与我们通过随机实现获得的“计数器”值进行比较。还要检查代理如何在初始迭代期间以负回报和高计数器值结束,以及它们如何随着它执行更多迭代而显著改善,从它的动作中学习并根据贝尔曼方程更新 Q 矩阵。
if episode % 50 == 0:
print('Episode {} Total Reward: {} counter: {}'.format(episode,G,counter))
这是完整的代码
#Importing Libararies
import gym
import numpy as np#Environment Setup
env = gym.make("Taxi-v2")
env.reset()
env.render()# Random Moments
state = env.reset()
counter = 0
reward = None
while reward != 20:
state, reward, done, info = env.step(env.action_space.sample())
counter += 1
print(counter)# Q table implementation
Q = np.zeros([env.observation_space.n, env.action_space.n])
G = 0
gamma = 0.618
for episode in range(1,1001):
done = False
G, reward, counter = 0,0,0
state = env.reset()
while done != True:
action = np.argmax(Q[state])
state2, reward, done, info = env.step(action)
Q[state,action] = (reward + gamma * np.max(Q[state2]))
G += reward
counter += 1
state = state2
if episode % 50 == 0:
print('Episode {} Total Reward: {} counter: {}'.format(episode,G,counter))
唷!!就是这样伙计们。深呼吸,祝贺你自己学会了一个 Q 学习人工智能代理的基本概念。高端 Atari 游戏中使用的 AI 代理的概念与本教程中解释的非常相似。不同的是,在这些游戏中,环境的状态数量变得非常多,所以不可能用 Q 矩阵表来实现,因为它的维数非常非常大。所以他们用神经网络来实现同样的功能。遵循 OpenAI 的文档来了解如何安装 openai 健身房环境。
如果你喜欢这篇文章,在推特上关注、转发将鼓励我开始我的博客世界之旅。
下次见。干杯!!
SAS 入门:初学者
原文:https://towardsdatascience.com/getting-started-with-sas-beginner-354a94a48f08?source=collection_archive---------1-----------------------
这本快速入门指南是为新的 SAS 用户准备的。我已经包括了 SAS 的基本要素,以帮助您尽快使用 SAS。
什么是 SAS?
SAS 是分析统计数据的工具。SAS 是统计分析软件的缩写。SAS 的主要目的是检索、报告和分析统计数据。SAS 环境中的每个语句都以分号结束,否则该语句将给出错误消息。它是一个强大的工具,用于运行 SQL 查询和通过宏自动执行用户的任务。
除此之外,SAS 通过图形提供描述性的可视化,还有各种 SAS 版本提供机器学习、数据挖掘、时间序列等报告。SAS 支持两种类型的语句来运行程序。广义地说,SAS 程序中的语句分为:数据步骤和过程。
在这篇文章中,我试图解释使用 SAS 的数据分析。为了解释这个问题,我创建了数据汽车,其中包含以美元为单位的价格、汽车的长度、汽车的维修等级(这是一个分类值)、国外价值(显示汽车是国外的还是国内的)、重量以及最终的 mpg(汽车的里程)。
SAS Essentials 入门:
数据步:
数据步骤由所有 SAS 语句组成,以行数据开始,以行数据行结束。它描述和修改你数据。在数据步骤中,您告诉 SAS 如何读取数据以及生成或删除变量和观察值。数据步骤将原始数据转换成 SAS 数据集。SAS 可以互换使用卡和数据线语句。数据导入、报告变量和描述性分析是数据步骤流程的一部分。在数据步骤中有四种常用的语句。
- 数据语句命名数据集
- 输入语句列出了变量的名称
- CARDS 语句表示数据行紧随其后。
- INFILE 语句表示数据在一个文件中,以及该文件的名称。
data newdata;
input name $ price mpg rep78 wgt len foreign;
datalines;AMC 4099 22 3 2930 186 0
AMC 4749 17 3 3350 173 0
AMC 3799 22 3 2640 168 0
Audi 9690 17 5 2830 189 1
Audi 6295 23 3 2070 174 1
BMW 9735 25 4 2650 177 1
Buick 4816 20 3 3250 196 0
Buick 4453 26 3 2230 170 0
Buick 5189 20 3 3280 200 0
Buick 10372 16 3 3880 207 0
Buick 4082 19 3 3400 200 0
Cad. 11385 14 3 4330 221 0
Cad. 14500 14 2 3900 204 0
Cad. 15906 21 3 4290 204 0
; run;
解释:在上面的代码中,我们创建了一个新的数据集 newdata,它包含变量 name、price、mpg、rep78(维修等级)、wgt、len 和 foreign。数据集 newdata 的维度包含 14 条记录和 7 个变量。
PROC 步骤:
PROC 步骤告诉 SAS 对数据执行了什么分析,比如回归、方差分析、均值计算等。每个 PROC 语句都以 PROC 关键字开始。
proc print data=newdata(obs=10);
run;
上述语句将以如下方式运行并输出数据:
SAS 编程:
1)导入 SAS 数据:
SAS 中的 PROC 导入功能用于从 excel 文件中导入数据集。除了将数据加载到 SAS 环境之外,SAS 还有内置的库,其中存储了数据集以供用户帮助。
- 临时数据:数据仅持续到当前 SAS 会话。这意味着当会话结束时,生命周期短的文件也会被删除。
- 永久数据:SAS 存储的终身数据,会话结束后不能删除。
2)统计描述性分析:
缺失值:
用句号()表示的缺失值函数。)标识数据中缺失记录的数量。在我们的数据集中,没有缺失值。
PROC 意思是:
SAS 有计算平均值的基本程序。
proc means data=newdata;
run;
解释:给定汽车数据的平均价格为$7790.71,其中最低价格为$3799,最高价格为$15906。
PROC FREQ:
SAS 有一个叫做 PROC FREQ 的程序来计算数据集中数据点的频率分布。频率分布是显示数据集中数据点频率的表格。表中的每个条目都有值在特定组或间隔内出现的频率或计数,这样,就可以使用表汇总值的分布。
proc freq data=newdata;
tables rep78;
run;
解释:评级为 3 的列修复评级在数据中频繁出现,这意味着比其余值出现的几率高 78.5%。
PROC CORR
两个变量 x 和 y 之间的关系可以使用 SAS 中的 CORR 函数来计算。相关性取-1 到+1 之间值,值 1 表示非常强的正相关性,而值-1 表示强的负相关性。
解释:在下面的输出中,汽车的长度和重量显示出 0.864 的正相关性,这意味着如果汽车的长度增加,那么它的重量可能会增加,也就是说,如果我们在这两个变量之间绘制一个图形,那么我们会得到一条直向上的对角线,可以看出-0.74 的值表示 len 和 mpg 之间的负关系。
3)图表和可视化
SAS 工具具有强大的图形功能,有助于分析和报告数据。
简单条形图:
条形图是最常用的表示分类数据的图表之一。在这种情况下,由值 1 表示的外国汽车相对多于国内汽车值 0。
直方图:
直方图解释了连续值的分布。长度值稍微向左倾斜,这意味着向左的长尾表明长度数据不是正态分布的。
散点图:
散点图表示的两个变量之间的关系。两个连续变量之间的图表。在这里,我们可以看到一个强劲的上升趋势,这表明长度和重量之间有很强的相关性。
方框图:
下图是箱线图的一个特例,其中我们通过分类变量来显示连续变量。如果数据集有异常值(极端值),盒须图可能不仅显示最小值或最大值。相反,胡须的末端代表四分位数范围(1.5*IQR),这是计算异常值的一个很好的属性。该变量的平均值为 7790.71,中位数更接近第一个四分位数。价格变量很少有极端值,在建模前需要进一步处理。
阅读:
第 1 课:SAS | STAT 480 入门—在线统计
【SAS.pdf 入门
Google 联合实验室 TensorFlow 入门
原文:https://towardsdatascience.com/getting-started-with-tensorflow-in-google-colaboratory-9a97458e1014?source=collection_archive---------5-----------------------
10 分钟学会两项激动人心的技术!
Photo by Franck V. on Unsplash
TensorFlow 是数据科学家的主导深度学习框架,Jupyter Notebook 是数据科学家的首选工具。如果您可以在任何地方使用 TensorFlow,而无需设置环境,那会怎么样?更好的是,如果你可以免费使用 GPU 来训练你的深度学习模型呢?
谷歌合作实验室(Colab)就是答案!这是一项非常令人兴奋的技术,它允许数据科学家专注于建立机器学习模型,而不是物流!
在本文中,我们不仅将介绍使用 Colab 的基础知识,还将通过易于理解的示例帮助您开始使用 TensorFlow。
开始了。
打开 Colab 笔记本
首次使用 Colab 时,您可以在此处启动新笔记本:
[## 谷歌联合实验室
编辑描述
colab.research.google.com](https://colab.research.google.com/)
创建笔记本后,它将保存在您的 Google Drive (Colab 笔记本文件夹)中。您可以通过访问您的 Google Drive 页面来访问它,然后双击文件名,或者右键单击,然后选择“用 Colab 打开”。
与 GitHub 连接
Colab 的构建者考虑得非常周到,他们甚至在 Github 中加入了承诺的功能。
要连接 GitHub,首先需要在 GitHub 上创建一个带有主分支的 repo。然后,从下拉菜单中选择“文件—在 GitHub 中保存副本”。您将仅在第一次被要求授权。方便的是,它甚至允许你在笔记本中包含一个“在 Colab 中打开”按钮,就像这样:
启用 GPU 支持
要为深度学习项目打开 GPU,只需进入下拉菜单,选择“运行时—更改运行时类型—硬件加速器”,然后选择 GPU:
使用单元格
在大多数情况下,这与本地 Jupyter 笔记本完全相同。例如,要运行代码单元格,只需按“Shift + Enter”即可。查看以下常用键盘快捷键(在使用 Chrome 的 Windows 上):
- 运行单元格:“Shift + Enter”
- 删除单元格:“Ctrl + M,然后 D”
- 撤消:“Ctrl + Shift + Z”
- 转换为代码单元格:“Ctrl + M,然后 Y”
- 转换为 markdown 单元格:“Ctrl + M,然后 M”
- 保存笔记本:“Ctrl + S”
- 打开快捷方式屏幕:“Ctrl + M,然后 H”
使用文件
您也可以将数据上传到您的 Colab 文件夹。见下图:
张量
TensorFlow 的名字基于“张量”一词。张量到底是什么?简而言之,多维数组。让我们看看这意味着什么!
- 我们有一个单一的数字,例如 6,我们称之为“标量”;
- 我们有三个数字,例如[ 6,8,9],我们称之为“向量”;
- 我们有一个数字表,例如[[6,8,9],[2,5,7]],我们称之为“矩阵”(有两行三列);
- 我们有一个数表的表格,例如[[[6,8,9],[2,5,7]],[[6,8,9],[2,5,7]]],还有……我们这里用词不多了:(朋友,那是一个张量!张量是数组的广义形式,可以有任意维数。
在张量流术语中,标量是秩为 0 的张量,向量是秩为 1 的,矩阵是秩为 2 的,等等。有三种常用的张量类型:常量、变量和占位符,解释如下。
张量的类型
常量顾名思义。它们是你等式中的固定数字。要定义一个常数,我们可以这样做:
a = tf.constant(1, name='a_var')
b = tf.constant(2, name='b_bar')
除了值 1,我们还可以为张量提供一个名称,比如“a_var ”,它独立于 Python 变量名“a”。这是可选的,但将有助于以后的操作和故障排除。
定义之后,如果我们打印变量 a,我们会得到:
<tf.Tensor 'a_var:0' shape=() dtype=int32>
变量是要优化的模型参数,例如,神经网络中的权重和偏差。同样,我们也可以定义一个变量,并像这样显示它的内容:
c = tf.Variable(a + b)
c
并且有这样的输出:
<tf.Variable 'Variable:0' shape=() dtype=int32_ref>
但是需要注意的是,所有变量在使用前都需要初始化,如下所示:
init = tf.global_variables_initializer()
你可能已经注意到 a 和 b 的值,也就是整数 1 和 2,没有出现在任何地方,为什么?
这是 TensorFlow 的一个重要特征——“惰性执行”,意思是首先定义事物,但不运行。它只有在我们告诉它去做的时候才会被执行,这是通过运行一个会话来完成的!(注意 TensorFlow 也有急切执行。查看此处的了解更多信息)
会话和计算图
现在让我们定义一个会话并运行它:
with tf.Session() as session:
session.run(init)
print(session.run(c))
请注意,在会话中,我们运行变量的初始化和 c 的计算。我们将 c 定义为 a 和 b 的和:
c = tf.Variable(a + b)
用 TensorFlow 和深度学习的话说,这就是“计算图”。听起来很复杂,对吧?但它实际上只是我们想要进行的计算的一种表达方式!
占位符
另一个重要的张量类型是占位符。它的用例是保存要提供的数据的位置。例如,我们定义了一个计算图,我们有大量的训练数据,然后我们可以使用占位符来表示我们将在以后输入这些数据。
让我们看一个例子。假设我们有这样一个等式:
我们有一个 x 的向量,而不是一个单一的 x 输入。所以我们可以用一个占位符来定义 x:
x = tf.placeholder(dtype=tf.float32)
我们还需要系数。让我们使用常数:
a = tf.constant(1, dtype=tf.float32)
b = tf.constant(-20, dtype=tf.float32)
c = tf.constant(-100, dtype=tf.float32)
现在让我们制作计算图,并提供 x 的输入值:
y = a * (x ** 2) + b * x + c
x_feed = np.linspace(-10, 30, num=10)
最后,我们可以运行它:
with tf.Session() as sess:
results = sess.run(y, feed_dict={x: x_feed})
print(results)
这给了我们:
[ 200\. 41.975304 -76.54321 -155.55554 -195.06174 -195.06174 -155.55554 -76.54324 41.97534 200\. ]
综合考虑
现在我们有了 TensorFlow 的基础知识,让我们做一个迷你项目来构建一个线性回归模型,也就是神经网络:)(代码改编自 TensorFlow 指南中的示例这里
假设我们有一堆 x,y 值对,我们需要找到最佳拟合线。首先,由于 x 和 y 都有值要输入到模型中,我们将它们定义为占位符:
x = tf.placeholder(dtype=tf.float32, shape=(None, 1))
y_true = tf.placeholder(dtype=tf.float32, shape=(None, 1))
行数被定义为 None,以便灵活地输入我们想要的任意行数。
接下来,我们需要定义一个模型。在这种情况下,我们的模型只有一个层,只有一个权重和一个偏差。
TensorFlow 允许我们非常容易地定义神经网络层:
linear_model = tf.layers.Dense(
units=1,
bias_initializer=tf.constant_initializer(1))
y_pred = linear_model(x)
单元的数量被设置为 1,因为我们在隐藏层中只有一个节点。
此外,我们需要有一个损失函数,并建立优化方法。损失函数基本上是一种使用训练数据来衡量我们的模型有多差的方法,所以当然,我们希望它最小化。我们将使用梯度下降算法来优化这个损失函数(我将在以后的文章中解释梯度下降)。
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
然后我们可以初始化所有的变量。在这种情况下,我们所有的变量包括权重和偏差都是我们上面定义的层的一部分。
init = tf.global_variables_initializer()
最后,我们可以为占位符提供培训数据并开始培训:
x_values = np.array([[1], [2], [3], [4]])
y_values = np.array([[0], [-1], [-2], [-3]])with tf.Session() as sess:
sess.run(init)
for i in range(1000):
_, loss_value = sess.run((train, loss),
feed_dict={x: x_values, y_true: y_values})
我们可以得到权重,并做出这样的预测:
weights = sess.run(linear_model.weights)
bias = sess.run(linear_model.bias)
preds = sess.run(y_pred,
feed_dict={x: x_values})
由此产生了这些预测:
[[-0.00847495] [-1.0041066 ] [-1.9997383 ] [-2.99537 ]]
如果你像我一样好奇,你可以通过以下方式验证模型是否使用其训练的权重和偏差进行预测:
w = weights[0].tolist()[0][0]
b = weights[1].tolist()[0]
x_values * w + b
这给了我们完全相同的结果!
array([[-0.00847495], [-1.00410664], [-1.99973834], [-2.99537003]])
瞧啊。Google Colab 中使用 TensorFlow 搭建的一个简单的神经网络!希望你觉得这个教程有趣和丰富。
包含所有代码的笔记本可以在这里找到。一定要试一试!
最后的想法
云计算绝对是深度学习计算的未来。谷歌 Colab 显然是一款面向未来的产品。当我们可以在云上启动笔记本电脑并开始构建模型时,很难想象人们还想花时间建立深度学习环境!
如何开始使用宇宙魔方
原文:https://towardsdatascience.com/getting-started-with-tesseract-part-i-2a6a6b1cf75e?source=collection_archive---------2-----------------------
Photo by Pierre Châtel-Innocenti.
从头开始设置您的开源 OCR 堆栈
众所周知,Tesseract 不是一个可以识别各种文本和图形的一体化 OCR 工具。事实上,这与事实相去甚远。如果这是一个秘密,我已经破坏了它,无论如何已经太晚了。所以,为什么不深入研究宇宙魔方,并分享一些可以改善你的结果的技巧和诀窍呢?
我喜欢免费的东西!
不过,真的。我真的很感谢那些为开源项目做出贡献而不期望任何回报的开发人员。毕竟,它们为我们提供了个人相对难以实现的能力,例如通过 TensorFlow 创建深度神经网络,而没有太多的麻烦。谁能想到机器学习会像今天这样触手可及?
宇宙魔方也帮助我们完成简单的 OCR 任务,成功率很高,并且是完全开源的。在这篇文章中,我将试着让你继续使用宇宙魔方,并希望帮助你清除在使用它时可能会遇到的一些障碍。
即使该领域有相当多的选择,例如, OCRopus ,宇宙魔方似乎仍然是大多数免费骑手的首选。嗯,如果你考虑到宇宙魔方仍在由谷歌社区开发,并随着时间的推移不断增长,这一切加在一起。然而,如果你以前有过使用 Tesseract 的经验,你可能会注意到,在图像预处理或自定义字体训练方面,Tesseract 很可能会让你失望。
自定义字体的训练留待以后讨论,现在,我将主要集中在复习基础知识,让你开始使用 Tesseract。首先,让我们快速检查一下安装。
装置
马科斯
我将使用家酿,一个软件包管理器,来安装宇宙魔方库。安装 HomeBrew 后,您应该提示以下命令。
$ brew install tesseract
或者,如果你愿意,你也可以用 MacPorts 做同样的事情。
$ sudo port install tesseract
人的本质
在 Ubuntu 上,这也很简单。
$ sudo apt-get install tesseract-ocr
Windows 操作系统
对于 Windows,可以从官方 GitHub 库下载非官方安装程序。多好的句子,嗯?
我如何知道安装是否正确?
要验证 Tesseract 是否安装成功,您可以点击您的终端并键入以下内容。
$ tesseract -v
如果您收到类似下面的几行提示,您的宇宙魔方安装正确。否则,您可能希望从系统中的 PATH 变量开始检查出了什么问题。
tesseract 3.05.01
leptonica-1.74.4
libjpeg 9c : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11
安装更多的库
首先,Tesseract 不是一个 Python 库。它也没有 Python 的官方包装器。这就是那些热心的开发者来为我们创造这个令人敬畏的 Python 包装器 pytesseract 的地方。我们还需要安装 OpenCV 和 PIL 来操作图像。
$ pip install pillow
$ pip install pytesseract
$ pip install opencv-python
就是这样!
图像预处理
现在,您已经将您的宇宙魔方安装在您的计算机上,准备好使用 Python 了。你还在等什么?嗯,没有人阻止你;请继续尝试。不过,这里有一个“但是”。正如许多文章(包括官方文档)所述,如果没有图像预处理,Tesseract 很可能会失败。
什么是图像预处理?
很长一段时间以来,我一直是 TensorFlow 知识库中提高质量页面的常客,在那里他们列出了一些你可以尝试提高准确度的方法。虽然它声称内部有各种图像处理操作,但这往往是不够的。在这里,我将尝试应用一些我们可以通过使用 OpenCV 完成的事情。
让我们定义一个简单的函数,它将图像路径作为输入,并将字符串作为输出返回。我要发挥超级创造力,把这个函数命名为“get_string”
def get_string(img_path):
# Read image using opencv
img = cv2.imread(img_path)
# Extract the file name without the file extension
file_name = os.path.basename(img_path).split('.')[0]
file_name = file_name.split()[0]
# Create a directory for outputs
output_path = os.path.join(output_dir, file_name)
if not os.path.exists(output_path):
os.makedirs(output_path)
重定比例:镶嵌立方体最适合 300 dpi 或更高的图像。如果您处理的图像的 DPI 小于 300 dpi,您可以考虑重新缩放。否则,重新调整可能不会产生你认为会产生的影响。
就我个人而言,我更倾向于确保图像至少为 300 dpi,而不是在后期重新缩放。但是,每个人都有自己的喜好。你做你的。
# Rescale the image, if needed.
img = cv2.resize(img, None, fx=1.5, fy=1.5, interpolation=cv2.INTER_CUBIC)
去噪:大多数打印文档都可能在某种程度上受到噪声的影响。虽然这种噪音的主要原因可能各不相同,但很明显,它使计算机更难识别字符。结合使用几种不同的技术可以去除图像上的噪声。这些包括但不限于将图像转换为灰度、膨胀、腐蚀和模糊。
膨胀、侵蚀和模糊需要一个内核矩阵来处理。简单地说,你的内核越大,你的方法工作的区域就越广。同样,没有一个内核大小值适合所有情况。你需要玩数字游戏,最终为你的图像找到正确的值。
然而,一个好的经验法则是从小字体的小内核值开始。同样,对于较大的字体,您可以尝试使用较大的内核。
# Convert to gray
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply dilation and erosion to remove some noise
kernel = np.ones((1, 1), np.uint8)
img = cv2.dilate(img, kernel, iterations=1)
img = cv2.erode(img, kernel, iterations=1) # Apply blur to smooth out the edges
img = cv2.GaussianBlur(img, (5, 5), 0)
正如您在上面的代码中可能注意到的,我们可以用两种类似的方式创建内核:使用 NumPy 数组或者直接将内核传递给函数。
二值化:这绝对是必须的。让我们试着像电脑一样思考一下。在这个一切最终归结为 1 和 0 的网络现实中,将图像转换为黑白极大地帮助宇宙魔方识别字符。但是,如果输入文档缺乏对比度或背景稍暗,这可能会失败。
# Apply threshold to get image with only b&w (binarization)
img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
在输出目录中保存过滤后的图像后,我们可以通过将处理后的图像传递给 Tesseract 来完成 get_string 函数的编写,如下所示。
# Save the filtered image in the output directory
save_path = os.path.join(output_path, file_name + "_filter_" + str(method) + ".jpg")
cv2.imwrite(save_path, img)
# Recognize text with tesseract for python
result = pytesseract.image_to_string(img, lang="eng")
return result
临终遗言
现在,你可能认为你已经准备好了一切——但是总有改进的空间。如果我们有更多的过滤选项不是更好吗?实际上,有很多!我将在我的下一个故事中解释其中的一些。
对于那些想在进入下一个故事之前看看我的源代码的人来说,这里是我在 GitHubGist 上的完整代码。你可能注意到了,它实际上不仅仅是文本识别。事实上,它在图像的给定区域查找正则表达式并返回值。
我们很快就会到达那里,别担心!同时,最好继续你的一天,寻找更好的机会。
如何利用图像预处理提高立方体的精度
原文:https://towardsdatascience.com/getting-started-with-tesseract-part-ii-f7f9a0899b3f?source=collection_archive---------1-----------------------
Photo by Pierre Châtel-Innocenti.
应用计算机视觉技术提高精确度
在之前的如何开始使用宇宙魔方中,我给了你一个关于使用 Python 使用宇宙魔方的实用快速入门教程。这是一个非常简单的概述,但它应该可以帮助您开始使用 Tesseract,并清除我在您的位置时所面临的一些障碍。现在,我热衷于向您展示更多的技巧和东西,您可以使用 Tesseract 和 OpenCV 来提高您的整体准确性。
我们上次讲到哪里了?
在之前的故事中,大部分内容我都懒得赘述。但是如果你喜欢第一个故事,续集来了!那么,我们在哪里停下来的?
啊,我们对重缩放、去噪和二值化做了一个简单的概述。现在,是时候进入细节并向您展示一些您可以使用的设置了。
改比例
被重新缩放的图像或者缩小或者放大。如果你对缩小你的形象感兴趣, INTER_AREA 是适合你的选择。(顺便说一下,参数 fx 和 fy 表示下面函数中的比例因子。)
img = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
另一方面,在大多数情况下,您可能需要将图像放大以识别小字符。在这种情况下, INTER_CUBIC 通常比其他替代方法执行得更好,尽管它比其他方法慢。
img = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)
如果您想牺牲一些图像质量来获得更快的性能,您可能想尝试使用 INTER_LINEAR 来放大图像。
img = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)
模糊
值得一提的是, OpenCV 库中有一些模糊滤镜可用。图像模糊通常通过将图像与低通滤波器核进行卷积来实现。虽然滤镜通常用于模糊图像或减少噪点,但它们之间还是有一些差异。
1.求平均值
在使用归一化的盒状滤波器对图像进行卷积之后,这将取核心区域下所有像素的平均值,并替换中心元素。我想这是不言自明的。
img = cv.blur(img,(5,5))
2.高斯模糊
这类似于求平均值,但它使用高斯核,而不是归一化的盒式滤波器进行卷积。这里,核的维数和两个方向上的标准偏差可以独立确定。高斯模糊对于去除非常有用——你猜怎么着?—图像中的高斯噪声。相反,高斯模糊不会保留输入中的边缘。
img = cv2.GaussianBlur(img, (5, 5), 0)
3.中间模糊
内核区域中的中心元素被替换为内核下所有像素的中值。特别是,在去除图像中的椒盐噪声方面,这优于其他模糊方法。
中值模糊是一种非线性滤波器。与线性过滤器不同,中值模糊用邻域值中的中值替换像素值。因此,中值模糊保留了边缘,因为中值必须是相邻像素之一的值。
img = cv2.medianBlur(img, 3)
4.双边过滤
说到锐边,双边滤波对于去除噪声而不平滑边缘是非常有用的。与高斯模糊类似,双边滤波也使用高斯滤波器来寻找邻域中的高斯加权平均值。但是,在模糊附近的像素时,它也考虑了像素差异。
因此,它确保只有那些与中心像素具有相似强度的像素被模糊,而具有不同像素值的像素不被模糊。这样,具有较大强度变化的边缘,即所谓的边缘,被保留下来。
img = cv.bilateralFilter(img,9,75,75)
总的来说,如果你对保留边缘感兴趣,选择中值模糊或双边滤波。相反,高斯模糊很可能比中值模糊更快。由于计算复杂,双边滤波是所有方法中最慢的。
再说一次,你做你的。
图像阈值处理
没有一种图像阈值方法适合所有类型的文档。实际上,所有的滤镜对不同的图像都有不同的表现。例如,虽然一些滤波器成功地将一些图像二值化,但是它们可能无法将其他图像二值化。同样地,有些滤镜可以很好地处理其他滤镜无法很好地二值化的图像。
我将尝试在这里涵盖基础知识,尽管我建议您阅读官方文档 OpenCV 关于图像阈值处理以获得更多信息及其背后的理论。
1.简单阈值
你可能记得你的一个朋友给你的生活提了一些建议,他说,“事情并不总是非黑即白的。”嗯,对于一个简单的门槛来说,事情相当简单。
cv.threshold(img,127,255,cv.THRESH_BINARY)
首先,你选择一个阈值,比如 127。如果像素值大于阈值,它会变成黑色。少的话就变成白色了。OpenCV 为我们提供了不同类型的阈值方法,可以作为第四个参数传递。我经常在大多数任务中使用二进制阈值,但是你可以访问的官方文档了解其他阈值方法。
2.自适应阈值
我们让算法为图像的小区域计算阈值,而不是设置一个全局阈值。因此,我们最终为不同的图像区域设置了不同的阈值,这太棒了!
cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2)
有两种计算阈值的自适应方法。自适应阈值均值返回邻域面积的均值,自适应高斯均值计算邻域值的加权和。
我们还有两个参数来决定邻域的大小和从结果中减去的常量值:分别是第五个和第六个参数。
3.大津的门槛
这种方法特别适用于双峰图像,这种图像的直方图有两个峰值。如果是这种情况,我们可能会热衷于在这些峰值之间选择一个阈值。不过,这就是 Otsu 的二值化实际做的事情。
cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
这在某些情况下非常有用。但是它可能无法对非双峰图像进行二值化。所以,请大家对这个滤镜半信半疑。
阈值处理的类型
您可能已经注意到有一个参数,或者在某些情况下是几个参数的组合,作为参数传递以确定阈值的类型,比如 THRESH_BINARY。我现在就不在这里赘述了,因为在官方文档里已经解释的很清楚了。
接下来呢?
到目前为止,我们已经讨论了一些图像预处理技术。你可能想知道你什么时候会弄脏你的手。好吧,时候到了。在你回到你最喜欢的 Python IDE——我的是 PyCharm ,顺便说一句——之前,我将向你展示几行代码,这将节省你一些时间,同时试图找到哪种过滤器和图像操作的组合适合你的文档。
让我们从定义一个带有一些阈值过滤器和模糊方法组合的开关函数开始。一旦你有了这个想法,你也可以添加更多的过滤器,结合其他图像预处理方法,如重新调整你的过滤器集。
在这里,我创建了 20 种不同的图像阈值方法、模糊方法和内核大小的组合。switcher 函数 apply_threshold 有两个参数:OpenCV image 和一个表示过滤器的整数。同样,由于这个函数返回 OpenCV 图像,它可以很容易地集成到我们上一篇文章中的 get_string 函数中。
def apply_threshold(img, argument):
switcher = {
1: cv2.threshold(cv2.GaussianBlur(img, (9, 9), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1],
2: cv2.threshold(cv2.GaussianBlur(img, (7, 7), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1],
3: cv2.threshold(cv2.GaussianBlur(img, (5, 5), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1], ** ... ** 18: cv2.adaptiveThreshold(cv2.medianBlur(img, 7), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2),
19: cv2.adaptiveThreshold(cv2.medianBlur(img, 5), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2),
20: cv2.adaptiveThreshold(cv2.medianBlur(img, 3), 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 2)
}
return switcher.get(argument, "Invalid method")
它来了。
def get_string(img_path, method):
# Read image using opencv
img = cv2.imread(img_path)
# Extract the file name without the file extension
file_name = os.path.basename(img_path).split('.')[0]
file_name = file_name.split()[0]
# Create a directory for outputs
output_path = os.path.join(output_dir, file_name)
if not os.path.exists(output_path):
os.makedirs(output_path) # Rescale the image, if needed.
img = cv2.resize(img, None, fx=1.5, fy=1.5, interpolation=cv2.INTER_CUBIC) # Convert to gray
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply dilation and erosion to remove some noise
kernel = np.ones((1, 1), np.uint8)
img = cv2.dilate(img, kernel, iterations=1)
img = cv2.erode(img, kernel, iterations=1) **# Apply threshold to get image with only black and white
img = apply_threshold(img, method)** # Save the filtered image in the output directory
save_path = os.path.join(output_path, file_name + "_filter_" + str(method) + ".jpg")
cv2.imwrite(save_path, img)
# Recognize text with tesseract for python
result = pytesseract.image_to_string(img, lang="eng") return result
临终遗言
现在,我们需要编写一个简单的 for 循环,遍历输入目录来收集图像,并对收集的图像应用每个过滤器。我更喜欢使用 glob 或 os 从目录中收集图像,使用 argparse 通过终端传递参数,就像任何其他正常人会做的那样。
如果你想看的话,我在这里做了和我的要点差不多的事情。然而,请随意使用您觉得舒服的工具。
到目前为止,我已经尝试介绍了一些有用的图像预处理概念和实现,尽管这可能只是冰山一角。我不知道在接下来的几周里我会有多少“闲暇时间”,所以我不能给你一个发表下一篇文章的具体时间框架。然而,我正在考虑在这个系列中至少增加一个部分来解释我遗漏的一些东西,比如图像的旋转和去歪斜。
在那之前,最好的办法是保持警惕,继续寻找迹象。 *
Vue.js for Data Science 入门
原文:https://towardsdatascience.com/getting-started-with-vue-js-for-data-science-f3c34d22cd38?source=collection_archive---------5-----------------------
Vue.js 是一个轻量级、易于使用的 JavaScript 框架,用于构建更复杂的前端网站。在这篇博客中,我将分享我作为一个从事数据科学项目的人对学习 Vue.js 的看法。我以前尝试过学习 jQuery 来做 JavaScript 工作,我发现它非常不直观并且难以使用。Vue.js 是一股新鲜空气,是与 jQuery — esp 完全不同的体验。对于主要生活在 HTML/CSS 世界中进行前端开发的人来说。
Vue.js is a light-weight JavaScript framework to build dynamic websites
I .我的数据科学工作流程与 web 开发:
- 像许多数据科学家一样,我通常使用像 Python 这样的脚本语言来构建模型。这些模型通常经过训练并存储在磁盘上的某个地方,通常用 Python 或另一种语言部署到生产中。(我曾经写过关于使用 Go 进行数据科学的文章——这是一种非常棒的语言,可以用于许多数据科学任务。)
- 对于我来说,构建网站的常见用例是从访问网站、登录并为您标记或分类数据的用户那里获取训练数据。
对于这个工作流程,我使用了 Flask 作为 web 框架,以及 Bootstrap 和 Jinja 前端模板引擎来构建小型网站。(这些可以通过 AWS 或 Heroku 部署) - 网站需要交互性怎么办?如果需要键盘快捷键怎么办?如果你希望需要动态图表来展示模型的不同状态呢?这些任务需要 JavaScript。通常人们使用 Angular、React 或 Vue 这样的框架来帮助编写代码。
二。Vue.js 入门:
Vue。JS 是轻量级的,有更温和的学习曲线,更直观,有很好的文档,在单页应用程序(spa)中越来越受欢迎。SPAs 允许大部分工作在客户端完成,不需要持续的页面重载。
Youtube 上的网络忍者视频的大呼小叫,他们是学习 Vue 的绝佳选择。让我们从一些 Vue 代码开始:
a)调用函数和动态访问数据:
在 HTML 代码中:添加带有id
、vue-app
的div
,这将让 Vue 实例控制应用程序。HTML 使用{{
和}}
与 Javascript 数据交互——这让 Vue 知道动态加载这些数据。在<script>
标签中,添加到托管在 CDN 上的 Vue Javascript 文件和本地 Javascript 文件的链接。
JavaScript 文件内部:
Vue 实例使用el
与 DOM 连接,data
有键值对来保存所有可以动态更新的数据——这个名称是固定的。methods
拥有所有可以使用{{
和}}
在 HTML 内部调用的函数。在methods
内部,可以使用this
访问data
。要得到name
,就会是this.name
: Vue 自动理解this
是指这个对象。
关于这个过程,我发现的最好的事情之一是,我们可以将所有逻辑保留在纯 JavaScript 代码中,并将所有数据保留在一个 JavaScript 对象中。这对我来说感觉比什么都合并干净。
b)事件处理: vue . js 的另一个伟大之处是它如何无缝地处理像click
和keyup
这样的事件。假设您希望用户使用两个按钮来编辑年龄。
在 JavaScript 文件中,编写了方法add
和subtract
:
上面的代码将在点击时增加或减少年龄,并在不重新加载页面的情况下动态显示给用户。其他事件可以是@keyup
、@dblclick, @mousemove
等。
如果你想通过使用n
在不同的divs
之间切换,你可以使用@keyup.78
来捕获这个事件,并引导用户使用你的 JavaScript 函数。
对循环和条件句使用 v-for 和 v-if:
比方说,用户在数据对象中有另一个名为favorites
的属性。它有一个数据数组[“Batman”, “Spider-Man”, “Iron-Man”, “Black Panther”]
。我们可以用<div v-for="(fav, index) in favorites"><h4>{{ fav }} </h4><div>
。这将允许 HTML 代码逐个呈现项目列表。类似地,v-if
可以用来检查条件和data
对象中值的存在。
d)基于逻辑操纵类: 类绑定是 Vue 中我最喜欢的特性之一。比方说,您正在显示一个项目列表,并且希望在用户按下向上或向下按钮时突出显示该项目。这在使用类绑定的 Vue 中是可能的。下面是代码的完整示例。
<li v-for=’item in items’ :class=’{“active-item”: currentItem === item.id}’>
currentItem
可以在data
对象中操作,当 currentItem 匹配当前项目的 id 时,它会使用类active-item
高亮显示。
我已经非常简要地介绍了这些概念,这些例子只是 Vue.js 可以做什么的预告片,Vue.js 实际上有一些令人惊讶的文档,你可以在这里找到。
三。数据科学的要点:
在最后一部分,我们将讨论关于 Vue.js 的数据科学关键要点。
- Vue.js 非常适合为全栈数据科学编写客户端代码:
虽然了解用于开发模型的服务器端语言很好,但了解客户端框架也很好。这使得全栈数据科学。通过服务器端和客户端代码之间的交互,数据科学模型可以成为网站的一部分。Vue.js 在客户端代码开发上确实大放异彩。 - Vue.js 允许快速 XHR 请求将数据发送回服务器: 在浏览器中收集了用户的数据后,Vue 允许快速 XHR 请求使用 POST 请求将数据发送回服务器。在 Vue 实例的方法中,您可以使用
this.$http.post(‘/post_url’, JSON.stringify(this.data))
将数据发送回服务器,您只需要在 HTML 脚本标签中添加vue-resource
库——您可以使用 CDN 链接来完成。 - Vue.js 对于已经熟悉 HTML 的人来说很棒: Vue 让你用 HTML 编辑网页,很多数据科学家已经很熟悉了。Vue 小巧、可扩展、直观。
已经在使用 Vue.js 的网站有阿里巴巴、小米、Gitlab、路透社和 Adobe。围绕 Vue 有很多真正令人兴奋的事情,学习了它并在项目中使用,很容易理解为什么。
学习 Vue 的优秀资源:
- Net Ninja 的 Youtube 视频系列是互联网上最好的视频系列之一
- Vue.js 文档非常干净,写得很好
3)awesome-VueGithub 页面,链接到世界各地的多个项目、资源和社区
希望你喜欢 Vue 和数据科学的世界!
PS,看看我的新播客!我开始了一个名为“数据生活播客”的新播客。如果你已经在工作中处理数据,并且想听听在数据科学中处理数据、工具和技术的真实生活经历,这是为你准备的播客。在最近的一期节目中,我谈到了使用 Flask 和 Vue.js 构建一个单页面 web 应用程序。你可以在这里或者任何你听播客的地方听播客。
My new podcast: The Data Life Podcast
如果你有任何问题,给我的 LinkedIn 个人资料留言,或者发邮件到 sanket@omnilence.com。感谢阅读!
为项目实施开绿灯
原文:https://towardsdatascience.com/getting-the-green-light-on-project-implementation-c400feae9eb?source=collection_archive---------6-----------------------
在我之前的博文中,我讨论了如何更好地销售数据科学项目。该职位虽然适用于整个流程,但在初始阶段尤其有用,尤其是在需求收集阶段。在这篇文章中,我想把天平向过程的下一个阶段倾斜,在这个阶段,你提出一个要实现的项目。
我想解释一下,我在这里的动机是,尽管至少在某些时候认为是数据科学固有的,但统计学与销售艺术相遇的地方并没有被谈论或书写。至少,如果有,我很难找到它。除非我错了,否则目前没有关于它的 MOOC,尽管可以说数据科学 MOOC 供过于求,如果它被博客讨论,它很少被博客讨论。我正试图填补这个空白——毕竟,当哈斯蒂等人免费发布机器学习算法的最终指南时,再写一篇关于核心机器学习算法之一如何工作的博文几乎没有意义。不过,在这种情况下,我最大的希望是有人在我的一篇帖子上写一条评论,把我带到商业统计的 Tukey 、 Breiman 或 Cleveland ,我就可以挂上键盘了。
这篇文章将重点介绍在实施前会议上向客户展示什么样的模型,您希望客户同意实施,从而投入更多的时间和金钱。这一阶段可能是最难克服的障碍,因为这是时间和金钱承诺从少量增加到潜在的更大承诺的阶段。在内部销售的情况下,这可能意味着高管正在决定是否将项目从一个小型数据科学团队转移到一个更大的团队,该团队需要实施项目并允许项目在整个组织中广泛使用。
显然,在这种情况下,能够将您的模型的实现与解决您的客户正在经历的真实世界的问题联系起来是至关重要的,并且真实世界的问题应该对客户很重要。在可能的情况下,你应该能够将解决特定问题与节省一定数量的钱联系起来。当你在内部展示一个模型时,你更有可能找到一个合理的价格。同时,如果您在早期的发现会议中取得了成功,您将会意识到您正在解决的问题对您的客户有多么重要。
购买模型可信度的关键是结果对客户有意义。这意味着,不仅你的模型需要显示出很好的结果,而且你的客户需要了解你是如何评估你的模型的,将你的评估与她的业务联系起来,并相信结果。
有许多可用的评估方法,它们的使用会在统计和数据挖掘社区中引发争议。经常使用的评估方法,如接收器工作特性可以在统计的基础上受到批评,提出了更为稳健但细致入微的(因此更难理解),然而即使这些简单但错误的方法对商业受众来说也很难理解。
还有一些方法,如提升或增益,与客户试图解决的业务问题紧密相关。在销售你的结果的演示中,这种类型的评估是理想的,其中数据和问题是合适的。例如,lift 与增加销售的营销目标明确相关。
如果不合适,开发一个适合问题的度量标准可能是一个前进的方向。在这两种情况下,最好的做法仍然是使用统计上稳健的方法进行评估,以确保正确评估模型的性能,而不必使用该方法来传达结果(我希望在接下来的几周内,在我的博客中比较两种分类器评估方法)。
现在,尽管在几分钟的闪光中,在不知道如何得出结论的情况下,产生一个非常精确的模型是可以的。当然,你仍然可以用这种模型赢得 Kaggle。然而,不幸的是,说服用户只相信一个有准确性分数的模型是非常困难的。一方面,许多用于评估模型的指标对于本身不是机器学习用户的人来说是不可访问的。另一方面,对许多人来说,准确性分数本身并不令人信服——这些人想知道,“它对下一批数据有用吗?”和“好得不像真的吗?”
为展示的模型选择一个客户能够理解的解释是确保客户相信你的模型的关键。它太重要了,不能在这里作为脚注,所以我把它留到下一期。
见我的 博客登陆页 本系列其他故事详情
了解黑盒模型:
原文:https://towardsdatascience.com/getting-to-know-a-black-box-model-374e180589ce?source=collection_archive---------4-----------------------
基于雅可比的对抗性攻击和基于雅可比的数据增强的二维示例
Mirror Lake and Lone Eagle Peak in Colorado 7/2018
随着对人工智能的大肆宣传,围绕对立例子的讨论也越来越多。一个对抗性的例子,也称为攻击,是一个被机器学习模型错误分类的输入。这些输入通常是高维输入,例如照片、音频样本、文本串,甚至是软件代码。
有几个精彩的博客从理论上和初级水平介绍了对抗性攻击和防御 。理解对立例子的关键之一是首先理解:
- 机器学习模型如何决策
- “数据流形”和高维空间
- 敌对的噪音或干扰
由于这些概念很难在高维空间中可视化,我们将通过一个简单的二维示例来演示对抗性攻击中使用的一些核心技术。这将有助于我们在更高的维度上更好地理解这些概念。
我们将构建一个逻辑回归分类器,它将充当我们打算攻击或欺骗的模型,或者我们的“受害者”模型。然后,我们将通过如何使用基于梯度的方法来攻击我们的受害者和我们的受害者的黑盒版本。(所有用来产生这篇文章的代码可以在这里看到)
建立受害者模型
让我们借用马丁·佩拉罗洛的例子从 iris 数据集的子集构建逻辑回归。为了简单起见,我们将把两个输入变量 X1 和 X2 以及类 0 和类 1 称为。
Subset of iris data set
我们在训练机器学习模型时的目标是确定这个二维空间中最好地分隔两个类别的线。幸运的是,这是一个简单的任务,因为这两个类是明显分开的,没有太多的重叠。为此,我们将拟合一个逻辑回归,该回归将创建属于类别 1 的数据点的概率分布。使用 sigmoid 函数(表示为 g)和一些参数θ,我们将使这个概率分布符合我们的数据。
Sigmoid function with parameters θ
通过改变矩阵θ中的参数,我们可以调整函数 g 以最佳地拟合我们的数据 x。
def sigmoid(X, theta):
return 1 / (1 + np.exp(-np.dot(X, theta[0])))
我们将使用二元交叉熵损失作为损失函数来确定模型的预测有多接近真实情况。
Binary Cross-entropy Loss
def loss(X, theta, y):
h = sigmoid(X, theta)
return (-y * np.log(h) - (1 - y) * np.log(1 - h)).mean()
损失函数对(w.r.t.) θ的偏导数告诉我们需要改变θ值的方向,以改变损失。在这种情况下,我们想尽量减少损失。
Partial derivative of the loss function w.r.t. θ
h = sigmoid(X, theta)
gradient_wrt_theta = np.dot(X.T, (h - y)) / y.shape[0]
一旦我们通过对θ进行定向更新来最小化损失函数,我们的受害者模型就被训练好了!
Victim model’s probability distribution for class 1
上图显示了该空间中属于类别 1 的任意点的模型概率分布,与类别 0 相反(1- P(y=1))。它还以我们的模型的概率阈值为 0.5 的决策边界为特征,如果一个点在线上,则它属于类别 1 的概率将低于 50%。由于模型“决定”在这个阈值,它将分配 0 作为它的标签预测。
攻击受害者模型
基于雅可比或梯度的攻击的目标,在 Goodfellow 等人的解释和利用对抗的例子中有描述。艾尔。就是在受害者模型的决策边界上移动一个点。在我们的例子中,我们将把一个通常分类为 0 类的点“推”过受害者模型的决策边界,分类为 1 类。当使用高维数据时,对原始点的这种改变也被称为扰动,因为我们对输入进行了非常小的改变。
‘Pushing’ a data point over the victim model’s decision boundary
您可能还记得,在训练逻辑回归时,我们使用了损失函数和损失函数 w.r.t. θ的导数来确定θ需要如何变化才能使损失最小化。作为攻击者,在完全了解受害者模型如何工作的情况下,我们可以通过改变函数的其他输入来确定如何改变损失。
Partial derivative of the loss function w.r.t. X
损失函数 w.r.t. X 的导数准确地告诉我们需要在哪个方向改变 X 的值来改变受害者模型的损失。
h = sigmoid(X, theta)
gradient_wrt_X = np.dot(np.expand_dims((h-y),1),theta)/y.shape[0]
既然要攻击模型,就要最大化它的损失。改变 X 的值实质上是在二维空间中移动 X。方向只是对抗性干扰中的一个组成部分。我们还需要考虑在该方向上移动多大的步长(表示为ε)才能越过决策边界。
#Normalizing gradient vectors to make sure step size is consistent
#necessary for our 2-d example, but not called for in the papergradient_magnitudes = np.expand_dims(np.asarray(list(map(lambda x: np.linalg.norm(x), gradient_wrt_X))),1)
grads_norm = gradient_wrt_X/gradient_magnitudes#Creating the adversarial perturbation
epsilon = 0.5 #The step size be adjusted
X_advs = X+grads_norm*epsilon
对手必须考虑使用哪些数据点或输入,以及成功推动一个点越过决策边界所需的最小ε。如果对手从非常远离 0 级空间的点开始,他们将需要更大和更明显的扰动来将其转换为敌对的例子。让我们转换一些最接近决策边界和来自类 0 的点。(注意:其他技术允许从随机噪声中创建对立的例子- 论文 & 文章)
‘Pushing’ several data points over the victim model’s decision boundary using epsilon = 0.5
我们已经成功地创造了一些对立的例子!
…嗯,你可能会想:
- “我们只是四处搬点东西。这些点只是现在的点不同而已……”
- “……我们之所以能够做到这一点,是因为我们对受害者模型了如指掌。如果我们不知道受害者模型是如何工作的呢?”
你是对的。我们会回到第一点,但是尼古拉斯·帕伯诺特等人的针对机器学习的实用黑盒攻击中的技术。艾尔。会帮助我们解决第二点。
攻击黑盒模型:
当我们了解一个模型的一切时,我们称它为“白盒”模型。相比之下,当我们对模型如何工作一无所知时,我们称之为“黑箱”。我们可以把黑盒模型想象成一个 API,我们通过发送输入和接收一些输出(标签、类号等)来 ping 它。理解黑盒攻击是至关重要的,因为它们证明隐藏在 API 后面的模型可能看起来是安全的,但实际上仍然容易受到攻击。
Papernot 的论文讨论了基于雅可比的数据集增强技术,该技术旨在训练另一个模型,称为替代模型,以共享与受害者模型非常相似的决策边界。一旦替代模型被训练成具有与受害者模型几乎相同的决策边界,被创建来将一个点移动到替代模型的决策边界上的对抗性扰动也将可能越过受害者模型的决策边界。他们通过探索受害者模型的决策空间周围的空间并确定受害者如何响应来实现这一点。
训练替代模型
这种技巧可以被描述为一个孩子在学习惹恼他们的父母。孩子一开始对什么会让他们的父母生气没有先入之见,但他们可以通过在一周内随机选择一组行为来测试他们的父母,并注意他们的父母对这些行为的反应。虽然父母可能会对其中的每一个表现出非二元反应,但让我们假设孩子的行为要么是坏的,要么是好的(两类)。在第一周之后,孩子已经了解了一些困扰他们父母的事情,并且有根据地猜测还有什么会困扰他们的父母。第二周,孩子记下成功的行动,并进一步采取不成功的行动。孩子每周重复这一过程,注意他们父母的反应,调整他们对什么会困扰父母的理解,直到他们确切知道什么会困扰他们,什么不会。
基于雅可比的数据集扩充的工作方式与获取初始数据的随机样本并用于训练非常差的替代模型的方式相同。对抗性示例是从数据集创建的(使用之前基于梯度的攻击)。这里,对立的例子是模型梯度方向上的一步,以确定黑盒模型是否会以与替代模型相同的方式对新数据点进行分类。
Substitute model’s decision boundary converges to that of the decision boundary
扩充的数据由黑盒模型标记,并用于训练更好的替代模型。就像孩子一样,替代模型对黑盒模型的决策边界在哪里有了更精确的理解。经过几次迭代后,替代模型与黑盒模型共享几乎完全相同的决策边界。
替代模型甚至不需要与黑盒模型是同一类型的 ML 模型。事实上,一个简单的多层感知器足以学习一个复杂的卷积神经网络足够接近的决策边界。最终,通过少量数据样本、几次数据扩充和标记迭代,可以成功攻击黑盒模型。
点积的诅咒:
现在,回到第一点:你是对的,我在二维空间中移动点。虽然这是为了保持示例的简单性,但对抗性攻击利用了神经网络放大信号的特性。安德烈·卡帕西在中解释了点积的效果,更多细节请点击。
The dot-product amplifies the signal from small adversarial perturbations
在我们的二维例子中,为了移动点穿过受害者模型的决策边界,我们需要以步长ε移动它。当神经网络的权重矩阵乘以正常输入时,每个权重和每个输入值的乘积被求和。然而,在对抗输入的情况下,对抗信号的附加求和放大了作为总输入维度的函数的信号。也就是说,为了实现跨越决策边界所需的步长,我们需要随着输入维度数量的增加,对每个 X 值进行较小的更改。输入维度越大,我们就越难注意到对抗性扰动——这种效应是为什么 MNIST 的对抗性例子比 ImageNet 的对抗性例子更明显的原因之一。
基于梯度的攻击已被证明是有效的技术,它们利用深度学习模型将高维输入处理成概率分布的方式。黑盒攻击表明,只要我们能够访问受害者模型的输入和输出,我们就可以创建一个足够好的模型副本用于攻击。然而,这些技术有弱点。要使用基于梯度的攻击,我们需要确切地知道输入是如何嵌入的(转换成机器可读的格式,如向量)。例如,图像通常表示为二维像素矩阵或三维矩阵,这是信息的一致表示。另一方面,可以使用一些秘密的预训练单词嵌入或学习嵌入来嵌入其他类型的非结构化数据,如文本。因为我们不能对一个单词求导,所以我们需要知道这个单词是如何表示的。训练替代模型需要一组可能可检测到的对黑盒模型的 pings。研究人员正在寻找越来越多的方法来保护他们的模型免受恶意攻击。无论如何,我们必须主动了解我们模型的弱点。
了解陨石
原文:https://towardsdatascience.com/getting-to-know-the-meteorites-ef4a6a04290c?source=collection_archive---------2-----------------------
陨石是从天空坠落并降落在地球上幸存下来的流星。今天我查看了 NASA 数据库中由陨石学会收集的陨石数据。在这次探索中,我想揭示的是陨石的分类和质量,以及着陆的地理位置。
在根据分类将 386 块陨石分成 3 个桶(铁、石头或混合物)的一些预处理后,我在时间轴上画出了陨石的大小和数量,按照其质量垂直展开,并标注了名称和质量(以吨为单位)。我们可以观察到:
- 到达地球的最大陨石主要是铁
- 1920 年着陆的 60 吨重的“霍巴”是迄今为止世界上最大的火箭
- 大多数是石质的,但相对较小。直觉上,这是有道理的,因为它们在进入地球大气层时更有可能因其材料而解体
- 从 20 世纪 80 年代开始,收集了大量的陨石数据
为了放大较小的陨石,我们可以转换 y 轴来显示质量的对数标度,这揭示了近几十年来记录的从几克到几千克的更多石质陨石的数据点。这是画在纯黑色的背景上,以获得更好的可视性。
接下来,我开始绘制登陆地图。当有太多点重叠时,热图比散点图提供了更好的视图。
Meteorite landings
我们可以在南极看到陨石回收活动。如果按陨石类型划分,似乎铁陨石不太经常从南极洲收集,这可能与铁陨石沉入冰下更深有关,而在白色大陆上更容易找到小石头陨石。BBC 文章对此有更多报道。
(Left) Iron meteorite landings; (Right) Stony meteorite landings
这是我关于数据科学和视觉故事的# 100 天项目的第 18 天。代码在 github 上。由于休假,我已经离开一个星期了🌠。
感谢您的阅读,欢迎您提出想法和建议。
为您的自然语言处理之旅准备好文本数据
原文:https://towardsdatascience.com/getting-your-text-data-ready-for-your-natural-language-processing-journey-744d52912867?source=collection_archive---------17-----------------------
Photo by Patrick Tomasso on Unsplash
在我们生活的各个方面,我们都被语言所包围。语言是我们存在的基础,是让我们成为我们自己的东西。语言使我们能够以如此简单的方式做事情,否则这是不可能的,比如交流思想,像指环王一样讲述巨大的故事,甚至深入了解我们的内心。
由于语言是我们生活和社会不可或缺的一部分,我们自然会被大量的文本所包围。我们可以从书籍、新闻文章、维基百科文章、推文以及许多其他形式的资源中获取文本。
这些大量的文本可能是我们所能处理的最大数量的数据。从书面文字中可以获得许多真知灼见,由此提取的信息可以产生非常有用的结果,可用于各种应用。但是,所有这些数据都有一个小缺陷,即文本是我们可用的最无结构的数据形式。这是纯粹的语言,没有任何数学含义。可悲的是,我们所有的机器学习和深度学习算法都是针对数字而不是文本的。
那么,我们该怎么办?
简单!我们需要清理这些文本,并将其转换为数学数据(向量),我们可以将这些数据提供给我们饥饿的算法,这样它们就可以为我们提供一些很好的见解。这被称为文本预处理。
文本预处理可以大致分为两个主要步骤:
- 文字清理
- 文本到矢量的转换
让我们深入了解他们的细节…
文字清理
为了避免占用我们的内存(自然语言处理是一个耗时耗内存的过程),在我们将文本转换成向量之前,文本必须尽可能的干净。以下是清理数据时可以遵循的几个步骤:
移除 HTML 标签:大多数可用的文本数据都是 web 废弃的,因此几乎总是包含 HTML 标签(例如:< br/ >、< p >、< h1 >等)。如果我们把它们转换成向量,它们只会占用内存空间,增加处理时间,而不会提供任何关于文本的有价值的信息。
去掉标点:标点没有用。与 HTML 标签相同。这些也需要清洗,原因和上面提到的一样。
去除停用词:像‘this’,‘there’,‘that’,‘is’等词。不能提供非常有用的信息,而且会在我们的记忆中制造一些无用的混乱。这种词被称为停用词。可以使用删除此类单词,但建议在这样做时要小心,因为像“not”这样的单词也被视为停用词(这对于情感分析等任务可能是危险的)。
词干:像‘有味道的’、‘有品味地’等词都是‘有味道的’这个词的变体。因此,如果我们的文本数据中有所有这些单词,当所有这些暗示(或多或少)相同的事情时,我们将最终为每个单词创建向量。为了避免这种情况,我们可以提取所有这些单词的词根,并为词根创建一个向量。提取出词根词的过程称为词干化。“雪球斯特梅尔”是最先进的词干分析器之一。
该代码片段给出了以下输出:
令人惊讶的是,tasty 的词根竟然是 tasti。
将所有内容转换为小写:在我们的数据中同时包含“饼干”和“饼干”是没有意义的,最好将所有内容转换为小写。此外,我们需要确保没有文字是字母数字。
实现上述所有过程的最终代码如下所示:
文本到矢量的转换
一旦我们完成了对数据的清理,就应该将清理后的文本转换为我们的机器学习/深度学习算法可以理解的向量。
有相当多的技术可供我们使用来实现这种转换。其中最简单的就是袋字。
文字袋—简短介绍
单词包基本上创建了一个‘d’单词的字典(这不是 python 字典),其中‘d’是我们的文本语料库中唯一单词的数量。然后,它为每个文档创建‘d’维向量(将其视为长度为‘d’的数组),每个维(单元格)的值等于相应单词在文档中出现的次数。
类似这样的-
credits
在上面的例子中,字典有八个单词(are,cat,dog,is,on,table,the)。问题中的句子(查询)有六个单词(The,dog,is,on,the,table)。显然,每个单元格都具有相应单词在查询中出现的次数的计数值。
在非常高维的向量中,零的数量将大大超过非零值的数量,因为每个向量将具有针对数据语料库中所有唯一单词的维度。这样的向量维数可以是几千、几万甚至更多,但是单个文档不会有这么多独特的单词。这种类型的向量(其中大多数元素为零)被称为稀疏向量。
它们看起来像这样-
visiting link
当这些稀疏向量相互叠加时,我们得到一个稀疏矩阵。
类似这样的-
Source
在这个图中,可以清楚地看到大多数值是零。该稀疏矩阵将我们的整个文本语料库表示为 n*d 矩阵,其中‘n’表示文本语料库中的文档数量,而‘d’表示其中唯一单词的数量(各个向量的维数)。
下面是获取单词包的代码片段:
获得的输出是:
因此,对于我们的每个文档(总共 525814 个—‘n’),我们得到一个 70780(‘d’)维向量!这是巨大的!
我希望这个数字能说明为什么我们需要在将数据转换成向量之前清理数据,因为如果我们不清理数据,数据的维数会比我们现有的维数大得多。
文本已经被转换成向量,我们现在已经准备好建立我们的 ML/DL 模型了!
更多关于单词袋方法的信息可以在这里找到。
其他更复杂的文本到矢量转换技术包括:
- Tfidf
- Word2Vec
这个项目的完整 Jupyter 笔记本可以在这里找到。
这里完成的预处理步骤是在 Kaggle 上可用的亚马逊美食评论数据集上执行的。执行所有步骤所依据的“文本”功能是指不同食品的审查(被视为文件)。
暂时就这样吧!感谢人们读到这里!
BBYE!!
马拉松入门 v0.5.0a
原文:https://towardsdatascience.com/gettingstartedwithmarathonenvs-v0-5-0a-c1054a0b540c?source=collection_archive---------8-----------------------
Marathon Environments for Unity ML-Agents
我花了两年时间学习强化学习。我创造了马拉松环境,以帮助探索机器人和运动研究在活跃的布娃娃和虚拟代理领域的视频游戏中的适用性。
Introduction to Marathon Environments. From Hopper to Backflips
关于本教程
本教程提供了马拉松环境的入门知识。在此,您将了解到:
- 如何设置你的开发环境 (Unity,MarthonEnvs+ML-Agents+TensorflowSharp)
- 如何让每个代理使用他们预先训练好的模型。
- 如何重新培训料斗代理并遵循 Tensorboard 中的培训。
- 如何修改漏斗奖励功能训练它跳。
关于马拉松环境
Marathon Environments 使用 ML-Agents 工具包重新实现了深度强化学习文献中常见的经典连续控制基准集,即 Unity environments。
Marathon Environments 与 Unity ML- Agents v0.5 一起发布,包括四个连续控制环境。基于 DeepMind 控制套件和 OpenAI Gym 中可用环境的沃克、霍普、人形和蚂蚁。
所有的环境都有一个单一的 ML-Agent 大脑,有连续的观察和连续的行动。没有视觉观察。每个动作都与一个电动关节轴相关。使用嵌套关节策略实现多轴关节。每个环境包含 16 个同时训练的代理。
马拉松环境主页是 https://github.com/Unity-Technologies/marathon-envs——如果您有任何问题或疑问,请提出 Github 问题。
设置您的开发库
安装 Unity 2017.4 或更高版本
从 Unity 商店下载 Unity
设置存储库
转到 GitHub MarathonEnvs 0.5.0a 版本并下载QuickStart_xxx.zip
。
快速入门在一个 zip 文件中包含以下内容:
- 马拉松-envs-0.5.0a
- 毫升-药剂-0.5-3.0a
- 张量流图
解压缩到您的开发文件夹。
设置 Python
跟随优秀的 ML-Agents 文档学习如何设置 python 开发环境。
运行预先训练的模型
打开 Unity 和您的项目:
Open Unity and Your Project
打开 DeepMindWalker 场景:
Open UnitySDK\Assets\MarathonEnvs\Environments\DeepMindWalker\Scenes\DeepMindWalker.unity
按下播放。这将运行预训练模型DeepMindWalker108-1m.bytes
DeepMind Walker — This model was trained using 16 agents over 1m simulation steps
步行者代理有 6 个关节/动作和 41 个观察值。奖励函数对于骨盆速度和骨盆垂直度具有正的奖励信号。对于当前动作状态的努力有一个负的奖励信号,如果身高低于 1.1 米则有一个惩罚。
人形,漏斗和蚂蚁
重复上述步骤运行其他环境:
DeepMind Humanoid
人形智能体有 21 个关节/动作,88 个观察值。奖励函数对于骨盆速度和直立度有一个正信号,对于当前动作状态的努力有一个负信号,如果身高低于 1.2m 则有一个惩罚。它还根据其腿部的相位周期增加额外的奖励。
DeepMind Hopper
料斗代理有 4 个关节/动作和 31 个观察值。奖励函数对于骨盆速度和骨盆垂直度具有正的奖励信号。同样,对于当前动作状态的努力有一个负的奖励信号,如果身高低于 1.1 米则有一个惩罚信号。
OpenAI Ant
蚂蚁智能体有 8 个关节/动作和 53 个观察值。奖励函数对于骨盆速度具有正的奖励信号,对于当前动作状态的努力具有负的奖励信号,并且如果关节处于它们的极限则具有负的信号。
培训绩效
这里是每个环境之间的训练性能比较,训练 16 个并发代理。
These results are using home PC. All environments where build and trained as executables.
训练料斗
到目前为止,我们已经运行了预训练的模型,然而,真正的乐趣开始于你自己训练和运行实验。首先,我们将重新训练料斗。稍后,我们将修改它的奖励函数来完全改变它的行为。
切换到训练模式
在 Unity 中,选择Academy -> DeepMindHopperBrain
。然后,在检查器中,选择Brain Type
下的External
。顾名思义;代理现在需要外部输入。
调用培训
打开终端或命令窗口,调用您的 python 环境:source activate ml-agents
。转到项目cd /Development/ml-agents-0.5a/
的根目录。
训练命令包含以下元素:
mlagents-learn <trainer-config-file> --train --run-id=<run-identifier>
mlagents-learn
-ml-代理脚本<trainer-config-file>
-路径和文件名。yaml 配置文件。我们将使用config/marathon_envs_config.yaml
--train
将 ml-agent 设置为训练模式--run-id=<run-identifier>
设置本次训练运行的唯一标识符。(在 Tensorboard 中使用的名称和训练模型文件名)
然后调用 ml-agents python 脚本:mlagents-learn config/marathon_envs_config.yaml --train --run-id=hopper001
最后切换回 Unity,按 play 开始训练。
专业提示:使用可执行文件构建和训练将减少训练时间。更多信息见 ML-Agents 培训文件。
使用 Tensorboard 监控训练
打开第二个终端或命令窗口,调用您的 python 环境:source activate ml-agents.
转到项目的根目录:cd /Development/ml-agents-0.5a/
。使用tensorboard --logdir=summaries
调用 Tensorboard。最后打开浏览器,指向 Tensorboard 输出:[http://yourPcName:6006](http://yourPcName:6006)
。
Tensorboard allows you to track training in real time
在 Unity 中运行训练好的模型
为了查看您新训练的模型,我们需要将训练好的模型文件models/hopper001-0/editor_Academy_hopper001-0.bytes
复制到模型文件夹.../DeepMindHopper/Models
然后,通过选择Academy -> DeepMindHopperBrain
将大脑设置回内部模式,然后在检查器中,选择Brain Type
下的Internal
。接下来,选择GraphModel
下的editor_Academy_hopper001-0
。
按“运行”查看您的训练模型:
Your newly trained model running in Unity
编辑奖励函数让 hopper 跳起来。
现在你明白了基本原理,让我们来玩一玩吧!
打开DeepMindHopperAgent.cs
你喜欢的代码编辑器。默认情况下,Unity 会安装 Visual Studio,但我更喜欢轻量级、响应性更好的 Visual Studio 代码。
找到StepRewardHopper101()
函数并添加下面一行:
var jumpReward = SensorIsInTouch[0] == 0 ? BodyParts["foot"].transform.position.y + .5f : 0f;
这在脚不接触地面时产生一个奖励信号,并根据脚的高度而增加。
专业提示:通常我们希望所有的观察和奖励保持在-1 到 1 之间的“正常”范围内。然而,ML-Agents 可以在训练期间正常化观察和奖励值,这允许我们稍微偷懒!
通过用jumpReward
替换velocity
来更新reward
。它应该是这样的:
var reward = jumpReward
+ uprightBonus
- effortPenality
- jointsAtLimitPenality;
确保您的 保存 DeepMindHopperAgent.cs
。然后,按照之前的培训步骤,重新培训代理。结果将如下所示:
Hopper is now trained to jump!
更深入
下面是一些关于使用和扩展马拉松环境的更多技术细节。
奖励、终止和观察功能受到 DeepMind 控制套件和 OpenAI.Roboschool 的影响,一个例外是人形机器人,它在奖励中实现了一个阶段功能,以提高训练速度。
每个环境都是一个独立的 Unity 场景,每个代理类型都有一个预置,并且包含一个或多个预先训练的 Tensorflow 模型。从 MarathonAgent.cs 继承的自定义代理类用于定义该代理的行为。对于每个环境,开发人员应该实现以下内容:
AgentReset()
用于初始化代理。它应该为 StepRewardFunction、TerminateFunction 和 ObservationsFunction 设置回调。开发人员应该将模型元素添加到 BodyParts 列表中,并调用SetupBodyParts()
来初始化 body parts。这使得回调能够利用助手函数;例如,GetForwardBonus("pelvis")
根据身体部位与前向向量的距离计算奖金。
StepReward()
返回一个float
,带有当前动作步骤的奖励。辅助函数包括以下:GetVelocity("pelvis")
返回指定身体部位的速度;GetEffort()
返回当前动作的总和(可以传递一个要忽略的身体部位列表);并且GetJointsAtLimitPenality()
返回对达到其极限的动作的惩罚。
如果满足终止条件,则TerminateFunction()
返回true
。终止功能通过减少代理暴露于无用的观察来帮助提高训练速度。辅助终止函数包括TerminateNever()
,它永远不会终止(总是返回false
)和TerminateOnNonFootHitTerrain()
,如果不是脚的身体部位与地形发生碰撞,它将返回true
。身体部位在功能OnTerrainCollision()
中定义。一些代理商要求小腿身体部位贴上"foot"
标签,因为它们从足部几何形状中突出来,造成假阳性终止。
包扎
在本教程中,我们学习了如何安装马拉松环境,运行预训练的 Tensorflow 模型,我们重新训练了 hopper,然后我们学习了如何修改奖励函数来奖励 Hopper 的跳跃。
这应该给你一个很好的基础,让你用强化学习来尝试马拉松。
P ro 提示:我强烈建议您阅读 ML-Agents 培训文档以了解有关使用 Unity ML-Agents 的更多详细信息。
你可以在下面的 Github 项目中关注我的一些研究。
- github.com/Sohojoe/ActiveRagdollStyleTransfer——对活动布娃娃运动方式转移的研究(来自动作捕捉数据)
- github.com/Sohojoe/ActiveRagdollAssaultCourse—训练突击课目研究
- github.com/Sohojoe/ActiveRagdollControllers—主动布娃娃控制器的研究
- github.com/Sohojoe/MarathonEnvsBaselines—实验性—开放式健身房/基线
如果您遇到任何问题或 bug,或者有任何疑问,请在该项目的 Github 页面https://github.com/Unity-Technologies/marathon-envs提出问题
雷达上的幽灵——为什么雷达图容易被误读
原文:https://towardsdatascience.com/ghosts-on-the-radar-why-radar-charts-are-easily-misread-dba00fc399ef?source=collection_archive---------9-----------------------
Mali Akmanalp 刚刚写了一篇有趣的文章,讲述他如何使用雷达图解决一个特殊的数据问题。虽然总体来说,我仍然认为雷达图很有问题——尽管看起来很性感——我想知道这些问题到底是什么。
我的疑虑与混合类别/数字数据无关,也与人脑难以旋转和比较坐标轴无关。相反,我的问题是,雷达图经常让虚假联系变得非常容易绘制,因为它们的形式暗示着某种数据编码在起作用,即使根本没有。
与更简单的图表相比
我可以通过与更简单的非放射状图表的比较来说明这个问题。假设你有一个跨越四个范畴的价值观:
这些简单图表的唯一缺点是,我们必须为条形选择一个任意的顺序,从左到右——观众可能会误认为这个顺序是有意义的。但那不太可能,所以我们照原样接受。
当我们用一条线将这些值连接起来时,情况就大不相同了:
我不认为我们大多数人会认为这是合法的。这条线强烈表明,这里有一个重要的顺序——即一个无形的 x 轴编码了另一个变量,在这个变量上,煤油比巧克力“更多”,洗发水处于中间位置。(我确信我们可以找到一个合理的基础来进行事后排序,但这与我们需要用这些数据讲述的故事没有任何关系。)
这种虚假的秩序暗示正是雷达图所要做的:
蓝色形状的突出和它在页面上的方向表明一些真实的东西正在被编码,而事实并非如此。这可能导致几种误读。
误读一:面积
通过在雷达图中绘制一个形状,我们还创建了一个区域。读者会怀疑它的重要性。但是区域的大小很大程度上取决于我们选择的排序。以下是用不同顺序绘制的完全相同的数据:
右边的数字显得更大,表明总价值更高。误读!
误读二:规律性
类似地,雷达的“尖峰”在视觉上非常突出,但可能完全取决于数据顺序。这里同样是两种排序的相同数据:
左边的图表可能看起来“不稳定”、“不稳定”或“不均衡”而正确的可能看起来只是有某些“优点和缺点”但是心理反应是我们产生的完全独立于真实数据的人工产物!这类似于 Tufte 所反对的在折线图中设置荒谬比例和起点的老把戏,让趋势看起来完全像设计师想要的那样极端。
误读三:方向性
我们不仅必须选择变量的相对顺序,还必须在页面上确定它们的方向(决定哪一个是“上”)。这可能暗示了比保证的更多的相似和对比。
当我们查看雷达图的网格时,有一点很突出,那就是它们具有相似的整体方向:有些上下运行,有些左右运行,有些两者都没有。
这使得“垂直”项似乎在一个类别中,与“水平”项截然不同。但是如果我们把变量重新排序,一个完全不同的分组就会出现。如果我们有一个合理的故事要讲,通过强调一些可变分组而不是其他分组,那么可能是好的。但是如果这只是一个任意的选择,我们又一次误导了读者。
合法使用
就像饱受诟病的饼图一样,雷达图肯定有其用途:这就是我们讨论的额外编码——面积、规律性、方向——实际上是我们想要使用的编码。在我的书里有两个条件:
- 可变类别可以是强有序的(至少以一种方式)。
- 排序是循环:最后一项与第一项相关。
第二项是雷达图比折线图更有意义的关键:那么,它的圆形就是一个优势。例子包括:
- 真实空间中的方向性:平均风速
- 色调(色轮)频率
- 周期时间:每月销售额
我仍然不一般主张雷达图,即使你满足这些条件。是否使用雷达图将取决于你需要展示什么,展示给谁,以及你有什么样的数据。寻找大幅下跌或上涨似乎是合理的。但是,如果您需要读取特定的值,折线图可能会更好。我还对展示一大块雷达图,并要求读者在它们很小的时候发现形状的差异感到犹豫:形状的确切含义通常不明显。但是如果数据是正确的,雷达可以工作。
对我来说,最重要的是:当你有无序变量要显示时,关掉你的雷达,去寻找其他工具。
Jasper McChesney 是一名高级数据分析师,拥有自然科学和数据可视化方面的背景。他曾在非营利组织、人力资源和高等教育部门工作过。目前在麻省大学教授 R 课程,Udemy 上 。
Mac 用户的 Git 设置
原文:https://towardsdatascience.com/git-mac-setup-be1d16162e79?source=collection_archive---------4-----------------------
Mac 用户,让我们以正确的方式设置 Git!
动机(个人,即):
几个月前,我偶然发现了 Medium——最初,我发现它的内容范围很广,材料也很注重质量——在博客和整体界面上已经有了显著的改进。有了这些,当我为实验室配置一台新的 iMac 时(例如,微笑实验室——稍后会详细介绍),我想我应该记录下安装和配置 Git 的过程。我打算把这作为我的第一篇博客;尽管如此,我认为这个简单的教程是一个“打破僵局”的好方法。我希望你喜欢它!
现在让我们转到一些不错的老式 Mac Git——我们将正确设置您的 Mac 机器。
目录
- 安装 Git
- 初始设置
- 终端中的 Git 样式
- Git 自动完成
- Git 忽略
- Git 别名
- Git 认证
- 桌面(GUI)应用
Git 安装
首先是安装。这很简单。有几种不同的方法可以做到这一点。为了安装 brew 包管理器,我推荐使用家酿。
通过自制 Git
打开终端,通过运行以下命令安装 Homebrew :
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
然后安装 git
brew install git
—或者—
Git for Mac 安装程序
在 Mac 上安装 Git 最简单的方法是通过独立的安装程序:
- 下载最新的 Git for Mac 安装程序。
- 按照提示安装 Git。
初始设置
- 打开终端,通过在终端中键入并运行以下命令来验证安装是否成功
git --version
2.使用以下命令配置您的 Git 用户名和电子邮件,用您自己的名字替换艾娃的名字。与您创建的任何提交相关联的这些详细信息:
git config --global user.name "Ava Paris"
git config --global user.email "aparis@domain.com"
3.(可选)为了在使用 HTTPS 存储库时记住您的 Git 用户名和密码,配置 git-credential-osxkeychain 助手。
终端中的 Git 样式
有许多风格可供展示。无论如何,让我们保持简单和整洁——设置 Git 配色方案和显示在终端中的分支信息。
颜色:
除非您是从单色显示器上阅读这篇文章,否则让我们利用 git 的一些彩色特性。最明确的是,Git 的特定组件最好用彩色显示,这样更容易识别不同的组件,因此阅读起来也更舒服。
从终端运行以下命令集(即,从任何文件夹):
git config --global color.status auto
git config --global color.branch auto
git config --global color.interactive auto
git config --global color.diff auto
Mac 终端可以配置为使用颜色来改善显示效果。为此,将以下内容复制并粘贴到文件~/.gitconfig
中。
[color]
branch = auto
diff = auto
status = auto
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[color "diff"]
meta = yellow bold
frag = magenta bold
old = red bold
new = green bold
[color "status"]
added = yellow
changed = green
untracked = cyan
回购及分行挂牌:
在我看来,Git 最好的定制之一是在终端中显示分支信息。
为此,只需将以下几行文本添加到~/.bash_profile
文件中:
parse_git_branch() {git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'}export PS1="$NO_COLOUR[\t] $BLUE\u$SSH_FLAG:$YELLOW\w$NO_COLOUR: \n$GREEN\$(parse_git_branch) $BLUE\\$ $NO_COLOUR"
现在,在当前的回购中,提示符看起来如下:
**[**jrobinso@blackhawk matlab **(**master**)]**$
Git 自动完成
通过 tab 键键自动完成可能是一个方便的特性。但是,MacOS 上不会自动设置自动完成功能。幸运的是,设置这个只需要几个简单的步骤。
首先,安装所需的 brew 软件包,如下所示:
brew install bash-completion
接下来,将下面的代码片段添加到~/.bash_profile
文件中。
source /usr/local/etc/bash_completion.d/git-completion.bash
要么打开一个新的终端或运行source ~/.bash_profile
和享受!
Git 忽略
某些文件或文件类型通常不会添加到 repo 中。因此,如果省略这些文件,“状态”显示打印输出会更清晰。为此需要做的就是创建~/.gitignore
并添加。首先,让我们创建一个包含以下内容的文件:
.DS_Store
注意,~/.gitexcludes
也适用于每个项目,在这种情况下,文件存在于 repo 的根目录中。尽管如此,按照上面的说明,应该全局忽略.DS_Store
。
Git 别名
别名,特别是对于 Git,通常是值得的!如果没有其他的,至少将这个特性添加到您的全局 Git 配置中。请注意,我将配置称为“全局的”——~/.gitconfig
是应用于系统范围的配置,而特定于项目的配置在位于存储库根的.gitconfig
中处理(即<repo>/.gitconfig
)。
对于别名,通常添加到全局配置中最有意义。如果以后需要,则为特定项目添加唯一的别名。也许值得注意的是,alias 或所有 Git 配置都是首先使用本地配置来设置的,如果没有在本地指定,则是全局设置。换句话说,假设您在本地和全局配置中定义了相同的别名,那么本地定义将用于该特定的回购。
不管是局部的还是全局的,但建议使用全局,将下面的【别名】块添加到.gitconfig
:
**[**alias**]**
st **=** status -uno
ci **=** commit
br **=** branch
co **=** checkout
df **=** diff
lg **=** log -p
lgg **=** log --graph --pretty**=**format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date**=**relative
f **=** fetch
现在尝试+添加额外的别名,只要看到合适的…就这么简单。
**[**jrobinso@blackhawk matlab **(**feature_branch**)]**$ git co master
Switched to branch 'master'
**[**jrobinso@blackhawk matlab **(**master**)]**$ git st
*# On branch master*
nothing to commit **(**use -u to show untracked files**)**
**[**jrobinso@blackhawk matlab **(**master**)]**$ git f *# <fetch output>*
Git 认证
通常认证需要一个 SSH 密钥。
为此,从终端生成一个密钥:
**[**jrobinso@blackhawk ~**]**$ ssh-keygen
按几次 return 键(即,将密码留空)。
接下来,通过以下方式将 SSH 密钥复制到剪贴板
**[**jrobinso@blackhawk ~**]**$ cat ~/.ssh/id_rsa.pub | pbcopy
最后,将密钥粘贴到存储库主机上的设置页面中。
桌面(GUI)应用程序
考虑到 Git 确实有一点点的学习曲线,即使克服这一点的最好方法是熟悉它的核心(即从终端),也许一些人会更喜欢 GUI。因此,我认为有必要提一下基于 GUI 的 Git 回购工具。为此,两个选项脱颖而出: SourceTree 和 Github 桌面 App 。
Source Tree: View of local projects.
Open session, i.e., git repo
Github Desktop App
SourceTree 的优势在于可以与来自各种主机(例如 Github、Bitbucket 等)的存储库协同工作。),而 Github 桌面 App 是 Github 特有的。
结论
在大多数项目中,正确地建立开发环境是首要的。花几分钟时间完成本教程,Git 版本控制现在已经在您的机器上正确地设置好了,可以增强和优化您的吞吐量。
对于那些刚接触 git 或者不习惯使用终端的人来说,也许桌面应用程序最适合你(例如 SourceTree 或者 GitHub 桌面应用)。这些在 GUI 中提供了许多特性、工具和可视化。无论如何,终端在某些情况下是必须的。另外,如果面对从终端使用 g it 带来的学习曲线,将会获得对 Git 和版本控制的更好理解。
无论如何,无论是专家还是初学者,您的系统现在都应该可以使用 Git 了。我希望你喜欢它!
如果有什么缺失或可以改进的地方,请在下面分享——是否有一个你离不开的 Git 别名,一个简洁的特性,或者一个可以改进或过时的方面。当然,也欢迎大家提问!
感谢你阅读我的第一篇博客——希望你会喜欢,请随时提供关于如何改进未来博客的反馈。
macOS 卡特琳娜 10 . 15 . 3博客 结账版本。
GitHub 假人用底漆
原文:https://towardsdatascience.com/github-primer-for-dummies-e8d307e52b6d?source=collection_archive---------12-----------------------
使用 GitHub 托管复杂代码的简单指南
Me vs. GitHub — Source: http://devhumor.com/media/git-push
介绍
GitHub 是全球程序员的重要工具,允许用户托管和共享代码,管理项目,以及与近 3000 万开发人员一起构建软件。GitHub 通过跟踪修订和修改使代码协作变得更加容易,允许任何人对存储库做出贡献。作为一个最近才开始编程的人,GitHub 已经无数次成为真正的救星,帮助我学习新的技能、技术和库。然而,有时 GitHub 上的一个简单任务,如创建一个新的存储库或推动新的变化,比训练一个多层神经网络更令人生畏。所以,我决定创建一个指南来帮助用户(阅读:我自己)充分利用 GitHub 的力量。
创建存储库
GitHub 存储库通常被称为“repo”,是 GitHub 上的一个虚拟位置,用户可以在这里存储项目的代码、数据集和相关文件。点击主页上的new repository
按钮,您将进入一个页面,在这里您可以创建一个 repo 并添加项目的名称和简要描述。有一个选项可以将您的存储库设为公共或私有,但是私有特性只对付费用户/公司可用。您还可以使用自述文件初始化存储库,该文件提供了项目的概述和描述。强烈建议将自述文件添加到您的存储库中,因为它通常是某人在查看您的存储库时看到的第一件东西,并且允许您编写有关您的项目的故事,并向查看者显示您认为最重要的内容。一份强有力的自述文件应该清楚地描述项目及其目标,展示项目的结果和成果,并展示其他人如何复制该过程。
Creating a repository on GitHub
不幸的是,点击create repository
只是这个过程的第一步(剧透:它实际上并没有创建你的回购)。下一步涉及到使用您的终端来初始化您的 Git 并推送您的第一次提交。Git 和 GitHub 不是一回事,虽然它们是有联系的。Git 是一个帮助管理源代码历史和编辑的修订控制系统,而 GitHub 是一个托管 Git 库的网站。通俗地说,Git 会在每次提交时为您的项目拍照,并存储一个对该状态的引用。要为您的项目初始化 Git,请使用终端输入您计算机上存储 Git 的目录,并在命令行中输入git init
。键入git add FILENAME
上传你的第一个文件。下一步是做你的第一次提交,或者修改。在命令行中输入git commit -m "your comment here"
。注释应该提供简短的细节,说明做了什么修改,这样你可以更容易地跟踪你的修改。提交会将更改添加到本地存储库中,但不会将编辑内容推送到远程服务器。下一步是在命令行中输入git remote add origin [https://project_repo_link.git](https://project_repo_link.git)
,在 GitHub 上创建一个远程服务器来托管你的工作。最后,输入git push -u origin master
将修改推送到远程服务器并保存您的工作。
Git data stored as snapshots of the project over time — Source: https://git-scm.com/book/en/v2/Getting-Started-Git-Basics
将文件添加到存储库
向 GitHub repo 添加更改的过程类似于初始化过程。您可以选择一次性添加项目目录中的所有文件,或者在进行编辑时单独添加每个文件。由于通过反复试验发现的众多原因,我强烈建议单独推送每个文件。首先,它将保持您的存储库整洁有序,这在 LinkedIn、简历或工作申请上提供您的 GitHub 个人资料/回购的链接时非常有用。其次,这将允许您单独跟踪每个文件的更改,而不是提交一个模糊的提交描述。第三,它将防止您意外地将不打算添加到您的回购文件中。这可能是包含个人信息(如 API 密钥)的文件,如果发布到公共域,这些文件可能是有害的。它还会阻止您上传超过 100mb 的数据集,这是免费帐户的大小限制。一旦文件被添加到存储库中,即使它尚未被推送或提交,也很难移除。凭经验来说,我曾经在许多场合下,在不小心上传了一个我不想要的文件之后,不得不删除一个存储库,所以我强调仔细选择上传哪些文件的重要性。
Vim interface
要添加一个新文件,通过终端进入你的项目目录,并在命令行输入git add FILENAME
。要进行提交,有两种选择:您可以遵循与创建 repo 相同的过程并键入git commit -m "commit description”
,或者使用 Vim,一个基于 unix 的文本编辑器来处理更改。Vim 是一个反直觉的文本编辑器,它只响应键盘(没有鼠标),但提供了多个可以重新配置的键盘快捷键,以及创建新的个性化快捷键的选项。要进入 Vim 文本编辑器,在命令行中键入git commit
,然后按 enter 键。这会将您带到 Vim 编辑器;要继续编写您的提交,键入i
进入 --INSERT--
模式,然后键入您的提交消息。完成后,按esc
退出 --INSERT--
模式,然后保存并退出 Vim,输入:wq
编写并退出文本编辑器。从那里,你需要做的就是在命令行中输入git push
来把你的修改推送到 GitHub。
Git 忽略
要在推送到 repo 时忽略某些文件,您可以创建一个.gitignore
文件,指定有意忽略未跟踪的文件。要创建该文件,请在您的存储库主页上单击new file
按钮,并将该文件命名为.gitignore
,或者使用提供的示例模板之一。有多种方法可以指定要忽略的文件或文件夹。第一种方法是简单地在.gitignore
文件中写入文件名。例如,如果您有一个名为AWS-API-KEY-DO-NOT-STEAL.py
的文件,您可以在.gitignore
文件中写入该文件的名称和扩展名。
Creating a .gitignore file on GitHub
要忽略带有特定扩展名的所有文件名,比如说。txt 文件,在.gitignore
文件中键入*.txt
。最后,您可以通过在文件中键入folder_name/
来忽略整个文件夹。一旦你添加了所有你想忽略的文件到.gitignore
文件,保存它并把它放到你的项目的根文件夹中。现在,如果您尝试将这些文件添加并推送到存储库中,它们将被忽略,不会包含在存储库中。然而,如果文件在添加到.gitignore
文件之前已经被添加到存储库中,那么它们在 Git 存储库中仍然是可见的。
叉子和树枝
如果你以前用过 GitHub,或者熟悉 GitHub 的行话,你可能已经见过 Fork、Branch 和 Merge 这三个术语。fork 本质上是一个克隆或存储库。派生其他人的存储库将在您的配置文件下创建一个完全独立于原始存储库的新副本。这在原始存储库被删除的情况下很有用——您的 fork 将与存储库及其所有内容一起保留。要派生存储库,只需访问 repo 页面并单击页面右上角的Fork
按钮。要用更新的存储库覆盖当前的分叉,用户可以在分叉修订的 repo 之前使用分叉目录中的git stash
命令。
分支提供了从存储库的主代码行中分离出来的另一种方式。对存储库进行分支会向保留原始存储库一部分的存储库添加另一个级别。分支对于长期项目或具有多个协作者的项目非常有用,这些协作者具有处于不同阶段的工作流的多个阶段。例如,如果你正在开发一个应用程序,你可能已经准备好了滑板和一个关键功能,但是还在开发另外两个功能,还没有准备好发布。您可以创建一个额外的分支,在主分支中只留下成品,而两个正在进行的特性可以在一个单独的分支中保持未部署状态。在与团队合作时,分支也很有用——每个成员都可以在不同的分支上工作,因此当他们推动更改时,不会覆盖其他团队成员正在工作的文件。这提供了一种简单的方法来保持每个人的工作是独立的,直到它准备好被合并和部署。
Microsoft rolls out automated GitHub support chatbot
只要本地保存了存储库的克隆版本,就可以从您的终端本地创建分支。要查看 repo 中的所有分支,请在项目目录中的命令行中键入git branch
。如果没有创建分支,输出应该是*master
,星号表示该分支当前是活动的。要创建一个新的分支,输入git branch <new_branch_name>
,然后输入git checkout <new_branch_name>
切换到新的分支,这样您就可以从它开始工作了。git checkout
命令允许用户在存储库的不同分支之间导航。将变更提交到分支的过程与提交到主分支的过程相同,只是要确保知道您正在哪个分支中工作。
Merging two branches — Source: Atlassian GitHub Docs
要将多个分支合并成一个统一的历史,您可以使用git merge <branch_name>
命令。一种类型的合并被称为三路合并,它包括将两个分叉的分支合并为一个。三向合并的名称来源于生成合并所需的提交次数——两个分支顶端和它们共同的祖先节点。调用 merge 命令将通过找到公共基础提交,然后创建将两个提交历史合并为一个的新的合并提交,来将当前分支与指定分支合并。如果每个分支中有一部分数据被更改,git 合并将会失败,需要用户干预。
3-way Merge — Source: Atlassian GitHub Docs
另一种类型的合并是快速前进合并,在目标分支和当前分支之间有线性路径的情况下使用。在这种情况下,merge 将当前分支顶端向前移动,直到它到达目标分支顶端,有效地将两个历史合并为一个。一般来说,开发人员更喜欢使用快速合并来修复 bug 或添加小的功能,从而节省了三路合并来集成运行时间更长的功能。
Fast Forward Merge — Source: Atlassian GitHub Docs
提示和技巧
这些都是成功使用 GitHub 的基本要素;然而,我想分享一些我认为有用的提示。:
- 固定存储库:一个免费帐户最多可以固定六个存储库,这些存储库将始终显示在用户资料的顶部。这是一个展示你所做的最重要的项目的好方法,而不需要有人去筛选杂乱的旧提交。
- 添加协作者:当与一组人一起工作时,最好让每个用户都成为存储库的协作者,这样他们就可以从他们的工作中获得荣誉。要添加一个协作者,单击存储库主页上的
settings
选项卡,并从左侧菜单中选择collaborator
。在那里,输入其他用户的 GitHub 名称或电子邮件来添加他们。 - 推送后从历史中删除敏感数据:
git filter-branch — force — index-filter ‘git rm — cached — ignore-unmatch <path-to-your-file>’ — prune-empty — tag-name-filter cat — — all && git push origin — force — all
- 显示所有保存的仓库列表:
- 查看作者和最后编辑时间,这样你就可以责怪他们搞砸了:
git blame <file-name>
- 缩短 GitHub 分享网址:https://git.io/
- 【https://pages.github.com/】GitHub Pages:你可以通过几个简单的终端命令很容易地把你的回购变成 GitHub 托管的网站
额外资源
[## 学习如何 Git:使用 GitIgnore 忽略文件和文件夹
有时,我们的项目不仅仅包含我们创建的代码。有一些文件是由我们的 IDE 生成的…
medium.com](https://medium.com/@haydar_ai/learning-how-to-git-ignoring-files-and-folders-using-gitignore-177556afdbe3) [## Git - Git 基础知识
Git 中的所有内容在存储之前都要进行校验和检查,然后通过该校验和进行引用。这意味着它是…
git-scm.com](https://git-scm.com/book/en/v2/Getting-Started-Git-Basics) [## Git - gitignore 文档
底层的 Git 管道工具,比如 git ls-files 和 git read-tree,读取 gitignore 指定的模式…
git-scm.com](https://git-scm.com/docs/gitignore) [## Git 分支|亚特兰大 Git 教程
Git 分支简介。用 git branch 创建,列出,重命名,删除分支。git checkout:选择哪一行…
www.atlassian.com](https://www.atlassian.com/git/tutorials/using-branches) [## 分支或分叉您的存储库- Atlassian 文档
随着 DVCS 主机的发展,术语 fork 也在发展。Bitbucket 软件增加了对 forks 的管理;派生存储库…
confluence.atlassian.com](https://confluence.atlassian.com/bitbucket/branch-or-fork-your-repository-221450630.html) [## 了解 GitHub 流程
当你在做一个项目时,在任何给定的时间,你都会有一堆不同的功能或想法在进行中…
guides.github.com](https://guides.github.com/introduction/flow/) [## git-提示/技巧
最常用的 git 技巧和窍门。在 GitHub 上创建一个帐户,为 git-tips/tips 开发做贡献。
github.com](https://github.com/git-tips/tips) [## 哦,妈的,饭桶!
Git 很难:搞砸很容易,弄清楚如何修复你的错误他妈的是不可能的。Git 文档…
ohshitgit.com](http://ohshitgit.com/)
给你的顾客一件东西,他们永远不会流失
原文:https://towardsdatascience.com/give-this-one-thing-to-your-customers-and-theyll-never-churn-4e4bd059633f?source=collection_archive---------6-----------------------
如何利用嵌入式分析从您的数据中获得更多价值
数据是当今组织对话的核心。组织渴望数据并受数据驱动。毕竟,现在是信息时代!
能够掌握、解锁、理解和利用其数据来支持自身、员工和产品的组织已经走上了成功之路。
对于这些组织来说,分析是关键,尤其是嵌入式分析。
充分利用数据
公司总是积累数据。即使以最古老的形式,他们也收集和贮藏它。社交媒体的繁荣给已经蓬勃发展的数据增加了混乱的真实世界数据集。大约十年的这种活动已经帮助将这些土堆扩展成不断增加的数据山。
在这些山上行走和导航是一项艰巨的任务。信息流不透明,部分原因是组织的数据架构不清晰。数据是孤立的、不完整的、非结构化的和不可访问的。数据支离破碎,分散在各个口袋里。而且,数据是不可验证的,不可靠的。
了解更多>
对于一个试图将所有数据点联系在一起以创建一个有凝聚力的故事情节的组织来说,数据需要分析的帮助——筛选数字以准确预测未来,报告、预测和开出路径,收集见解,以及解开数字中根深蒂固的故事和模式。
这是有分析的!
商业智能和分析诞生于组织对解密其数据告诉他们的信息的需求。自助毕走上舞台,吸引了所有人的目光。
这是每个组织都在经历转型和分析实现之旅的时期。IT 部门开始着手复杂(而且通常昂贵)的数据仓库集成和 BI 部署。每个人都在实现解决业务问题的单一观点的道路上。
这些商业智能工具的庞然大物很快就被交给了未经培训的员工。虽然分析的承诺仍然存在——使用户能够做出明智的决策,而不管他们的技术方向、资质或技能组合如何,但事实上,分析需要大量的支持。仪表盘和报告也只是显示了冻结数据的快照,而不是探索真实世界的数据。具有独立界面的 BI 应用程序迫使用户离开他们熟悉的应用程序,在屏幕、视图和仪表板之间切换,以便获得洞察力。
当然,扶持人民过去是,现在也是最重要的。但是单独的分析也许并不合适。事实上,能引起用户共鸣的解决方案被紧密集成到他们使用的系统中。
为他们执行的非常具体的任务带来额外的背景、意识和分析能力。
嵌入式分析如何真正有所帮助
嵌入式分析,或捆绑到商业应用中的分析功能,正在进行一次戏剧性的进军。将传统的探索性数据分析和移动可视化功能引入核心应用,如 CRM、HRMS、ERP 和 SCM 等。
需求是巨大的,越来越多的来自销售人员、招聘人员、人力资源经理、物流经理、供应商、库存管理员、医药代表等等。需要对他们在各自的业务部门中处理的数据进行及时、可视化和交互式的访问。人们期望分析能够无缝集成到核心应用套件中。
一般来说,这些集成分析功能不是内部开发的(尽管它们可以内部开发)。相反,Sisense 等 BI 供应商为业务应用程序供应商开发它们,然后这些供应商将分析打包到产品中。因此得名嵌入式分析。
很明显,嵌入式分析可以为组织带来诸多好处,从与传统 BI 部署相比降低总拥有成本,到使您的最终产品变得强大和可用。现有应用程序中的嵌入式报告和仪表板可以使其高度用户友好。给它一个竞争优势。该产品满足了您的客户的需求,他们无缝地接受了它。
Gartner 有话说 *:
“在选择新的业务应用程序时,公司应该将搜索重点放在提供嵌入式分析的解决方案上,或者在不久的将来提供嵌入式分析的清晰路线图上。从寻找补充您的 ERP 和 BI 平台投资的特定分析应用程序开始。从长远来看,审查供应商在面向服务的架构环境中支持可重用分析构件(即服务)的能力。”
( Gartner 客户可获得完整报告)*
未来:人工智能和嵌入式分析
人工智能正在增强嵌入式商业智能来分析企业范围内的数据。机器学习正在实现更快、更有效的数据挖掘、管理和分析。结合深度学习,公司正在建立分析更复杂、丰富和多样的数据的能力,以及处理更大数量的数据的能力。
自然语言处理的使用使得细节更加连贯。社交媒体评论可读性强;视频、图片和图像是可解释的;情绪是可以理解的。突然间,我们之前谈到的堆积如山的数据变得很容易克服。
所有这些都在您的数据环境中,集成在熟悉的应用程序中,简化了您的日常任务。
原载于 2018 年 5 月 23 日 www.sisense.com。
全球恐怖和 EDA 可视化兔子洞
原文:https://towardsdatascience.com/global-terror-and-the-eda-visualization-rabbit-hole-a953c998b7e9?source=collection_archive---------5-----------------------
数据科学家面临的最大挑战之一是知道何时继续前进。它可能会进行更多的探索性数据分析(EDA),它可能会调整您的模型参数以获得更好的分数,或者只是试图让您的笔记本看起来尽可能专业。无论主题是什么,都很容易忘记时间,陷入分析的兔子洞,但随着最后期限的临近,你必须面对现实,你必须跳出整体,确保项目的其他部分不会被忽略,因为如果你的项目只有一部分看起来很棒,而其他部分充其量看起来很平庸,那么你的客户会想“为什么他/她的其他分析和演示不如[插入兔子洞项目]。”从而降低你所做工作的价值和评价。
我最近经历了一个最好的例子,当我在 ed a 可视化中迷失时,我从一开始就提供了一个全球恐怖主义数据库。全球恐怖主义数据库(GTD)是一个关于 1970 年至 2016 年世界各地恐怖袭击的数据库,包含超过 150,000 条观察数据。国家联盟的研究人员维护着恐怖主义研究和应对恐怖主义数据库,总部设在马里兰大学。
我之前在大学学习过全球和世界历史,显然对这个主题有着浓厚的兴趣,因此很容易被诱惑去钻研 EDA。随着项目的完成,我现在可以给你我的可视化的全部范围,以及它们所呈现和不呈现的所有信息。这个项目的主要目的之一是深入研究围绕时间和它们所展示的东西生成可视化。它专注于 1970 年至 2016 年间的全球爆炸事件,其原因你将在下面看到为什么它是焦点的明确选择。
当最初查看数据时,你想回答的一个非常直接的问题是,在我们的数据集时间线内发生了多少事件,在这种情况下是恐怖袭击。第二,如果你关注一个地区,在我们的例子中是爆炸事件,你想看到事件数量随时间的变化,看看这两种趋势之间是否有任何明显的差异。
我们可以看到,从 1970 年到大约 1993 年,恐怖袭击开始缓慢增加,尽管发生了 2001 年 9 月 11 日这样的事件,但直到 2003 年,我们看到全球恐怖事件呈下降趋势。我们还可以在第二张图中看到,爆炸案的数量大致遵循相同的趋势,但在 90 年代初,爆炸案的数量急剧下降。
Global Terrorist Attack Incidents 1970–2016
Global Bombing Numbers 1970–2016
在这里,我们可以清楚地看到全球不同地区的总体攻击趋势是如何变化的。在 20 世纪 70 年代,我们可以看到大多数恐怖袭击发生在西欧,其次是 20 世纪 80 年代的拉丁美洲和南美洲,但在 20 世纪 90 年代中期至 2003 年期间,袭击次数总体下降。我们也可以看到,我们经历了同样的人数激增,并看到中东和北非以及南亚是受恐怖袭击最严重的地区。然而,同样重要的是要注意到,尽管总体趋势有所增加,但似乎无论在哪个地区,恐怖袭击的发生率都有所上升。
Terrorist Attacks by Region 1970–2016
在这里我们可以看到,在过去的 47 年里,恐怖分子最喜欢的袭击方式是爆炸,是武装袭击的两倍多。然而,应该指出的是,如果这两个事件单独或一起发生时有区别,我无法找到这样的数据澄清,所以这些数字可能是扭曲的,因为像孟买酒店和巴塔克兰袭击事件都涉及炸弹和武装袭击。有趣的是,尽管劫机在上世纪七八十年代盛行,但它却排在了最后。
Type of Terror Attacks
下面,我们看到一个 tableau 生成的图表,显示了“受打击最严重”的目标类型,按受伤人数和死亡人数排列,圆圈的大小表示发生的次数。我们可以看到,绝大多数情况下,最常见的目标是平民,因此他们在恐怖分子手中遭受的痛苦也最大。然而,这个图表可能会产生误导,因为像 9/11、1993 年 WTC 爆炸案和 Bishopsgate 这样的单一事件可能会扭曲这个数字,因为这三个事件要么记录了大量的死亡人数,要么记录了大量的受伤人数,或者两者都记录了。还应该注意的是,这是您应该更好地组织数据的一个主要示例,因为图中有几个点可以合并。例如平民可以包括村庄、市场、车辆、公共汽车,当然还有平民,而单个军事类别可以包括军事单位、士兵、检查站、巡逻队、车队、军官、单位和警察局。
由于恐怖行动通常是对目标政府或国家采取的行动的反应,我接下来想看看历史上相处不好的国家(说得好听点)之间的事件数量趋势是否有任何相似之处。
第一个比较是英国和爱尔兰,从下面的图表中我们可以看到,英国在所有的暴力事件中首当其冲。与这两个国家之间的冲突主要相关的高峰是 1970 年至 20 世纪 90 年代末,这包括了被称为“动乱的整个时期,在此期间有 3500 多人死亡,47500 多人受伤。这里需要注意的是,虽然很大一部分攻击似乎发生在英国,但大多数事件并没有发生在英国本土,而是发生在北爱尔兰,所以如果你要显示整个爱尔兰(爱尔兰和北爱尔兰)与英国的对比,我想数字会有所不同。
UK vs Ireland Incidents
接下来,我们看到两个国家自脱离英国独立以来经历了动荡的历史。然而,我们可以看到,除了 20 世纪 90 年代中期的一次激增之外,恐怖事件的数量每年都保持在 500 起以下,而且大多数发生在印度。然而,随着 2008 年孟买恐怖袭击,这一切开始改变。从那时起,巴基斯坦已经压倒性地比印度发生了更多的恐怖事件,但是在过去的一两年里,这个数字似乎已经开始急剧下降。然而,自 2008 年袭击以来,印度的数字急剧上升,自那以后,似乎是一个缓慢,但稳定的攻击增加。事实上,如果你放大图表的最末端,你可以看到印度在事故数量上超过了巴基斯坦。
India vs Pakistan
在过去的 46 年里,我们见过的另外两个锁头国家当然是美国和俄罗斯。而他们之间的战争要么是代理方式,要么是冷战(即制裁、间谍等。)它从未发展成一场可能会席卷全球的全面战争。然而,我们在这里可以看到,虽然美国经历了一些高调的恐怖袭击,如地下天气组织、蒂莫西·麦克维、尤那邦摩、基地组织、ISIS 和萨纳耶夫兄弟,但它经历的袭击次数远远少于俄罗斯。这在很大程度上是因为美国不像俄罗斯和前苏联的某些地区那样动荡,如达吉斯坦、车臣、乌克兰/俄罗斯边境以及俄罗斯与格鲁吉亚的冲突。这两个国家都遭受了损失,但是很明显,由于俄罗斯的国土面积和它与邻国之间的暴力冲突,它在恐怖分子手中遭受的损失最大。
United States vs Russian Federation/USSR
更令人高兴的是,也是我关注的这个个人项目的一大部分,自 1994 年以来,随着该国首次自由选举任命纳尔逊·曼德拉为总统,并非正式地结束了种族隔离,南非的局势有了显著改善。然而,随着曼德拉从监狱中被释放,种族隔离制度在 1991 年正式结束,选举直到三年后才举行。事实上,我们可以从下图中看到,1991 年至 1994 年是南非最暴力的时期之一,因为阿非利卡民族主义者采取了更暴力的手段来阻止 1994 年的选举,但没有成功,这当然会激起南非黑人的反击行动。幸运的是,我们可以看到,这些年来,我们有数据显示,在选举之后,事故数量大幅下降。可悲的是,这些数据似乎在 2000 年后开始消失,对于任何了解南非历史和政治的人来说,包括姆贝基总统和祖马总统,他们对国家的状况都不太透明。
虽然自 1994 年以来,这些数字确实出现了显著下降,但该图向我们展示了个人在处理所有数据时必须尽最大努力获得和/或管理的两件事。也就是获得尽可能多的关于数据的知识,以获得一些背景知识,并能够从数据中理解或推断出你必须为我们不知道的数据生成可能的数字。
基于贝叶斯推理的全球恐怖主义数据库
原文:https://towardsdatascience.com/global-terrorism-database-with-a-bayesian-inference-7d6e23ae5024?source=collection_archive---------9-----------------------
在大会的数据科学沉浸式课程中,我的一个项目是使用全球恐怖主义数据库,利用贝叶斯技术进行分析。该项目由三部分组成。第一部分是做一些 EDA(探索性数据分析)和可视化,这将帮助你更好地理解数据。第二部分是对我们选择的一部分数据进行贝叶斯推断。最后一部分是对 1993 年“爆炸/爆炸”类袭击的数量进行预测。
数据
全球恐怖主义数据库由国家研究恐怖主义和应对恐怖主义联合会创建和维护
(START)。它是在 2006 年编制的。它不包括 1993 年,因为缺乏该年的数据收集。全球恐怖主义数据库顾问委员会估计,他们只收集了那一年大约 15%的攻击数据。一些比较突出的栏目包括:日期栏,地区,县,攻击类型,目标类型和杀死的数量。你可以在http://start.umd.edu/gtd/downloads/Codebook.pdf的密码本上阅读更多关于数据收集过程和数据集的更详细信息。
第一部分
这个项目的第一部分是做一些 EDA 和熟悉数据集,以完成第二部分和第三部分。我首先浏览代码本,并尝试了解数据集中一些列的含义的背景信息。我看的第一个是“attacktype”。该数据集中有九种不同类型的攻击。我关注的一些类型还有爆炸、暗杀和武装袭击。这些特别重要,因为爆炸对第三部分很重要,在这个项目中,我想尝试用暗杀或武装袭击作为第二部分的推理主题。
有了所有的时间序列信息和地理信息,我知道理解这些数据的最好和最有趣的方法是使用可视化。我首先想看看数据集中包含的历年攻击类型。使用 Tableau,我能够创建一个信息丰富的图表,能够将每种攻击类型分开,以查看每年每种攻击的数量。然后,我可以给图表中的每个区域赋予自己的颜色,以给出一些地理背景。下面是爆炸/爆炸的截图但是请到我的 Tableau 公众号和图互动。
https://public.tableau.com/profile/cbjohnson30#!/vizhome/WorldTerror-T_S/Sheet2
我从这个图表中得到的一个重要信息是,当我试图预测 1993 年发生的爆炸事件的数量时,这个信息对这个项目的第三部分是有用的。只看这个图表,我就能猜出我要找的数字在 1000 到 1500 之间。
我创建的下一个可视化是关注数据集中多年来每次攻击的地理信息。再次使用 tableau,我能够在世界地图上按年份标出每次袭击的位置。下面是 1980 年的可视化设置的截图。
https://public.tableau.com/profile/cbjohnson30#!/vizhome/WorldTerror-T_S/Sheet1
通过在 Tableau 公众帐户上查看,您可以与可视化交互以更改显示的攻击年份。在 Tableau Desktop 上创建时,年份之间的过渡更加平滑,让您可以更清楚地看到世界各地的攻击活动。
第二部分
这个项目的第二部分是在这个数据集上创建一个贝叶斯推理。我问的问题是,美国和西欧“成功的”武装袭击造成的死亡人数是否有显著差异。要使一次袭击“成功”,必须至少有一人死亡。随着枪支暴力成为全世界的热门话题,我想深入探讨一下这类袭击。所有的贝叶斯推理都包括一个先验信念和一个后验信念。对于我的先验,我使用了西欧和北美袭击中的死亡人数,我比较的两个后验是西欧的死亡人数和美国的武装袭击死亡人数。第一步是找到先验的均值和标准差。西欧和北美袭击死亡人数的均值和标准差分别为 1.94 和 4.3。接下来,我绘制了 95%置信水平下两个后验概率的均值和标准差。以下是每一项的图表:
美国的真实平均值在 1.44 和 2.1 之间,在 95%的置信水平下,其标准偏差在 1.61 和 2.87 之间。西欧的真实平均值在 1.44 和 2.34 之间,其标准偏差在 4.81 和 5.46 之间,两者的置信度均为 95%。最后一步是绘制两个相互对立的后验概率。这可以从下面看出:
在这些图表中,绿线代表我正在查看的每个统计数据的西欧基线数字。Delta-mean 相对接近,意味着这些数字相当相似。Delta-STD 则相反,绿线并不靠近条形图。这是因为西欧的标准差比美国高得多。这意味着西欧在他们的袭击中有更大范围的死亡。鉴于这一数据的性质,这意味着西欧的武装袭击死亡人数高于美国。
第三部分
该项目的最后一部分是试图预测 1993 年爆炸袭击的数量。由于这个项目的性质,我想留在贝叶斯分析领域做这件事。在我的 EDA(第 1 部分)中,我找到了我所寻找的攻击数量的目标范围。我的目标数字在 1000 到 1500 之间。我的目标是创建一个爆炸袭击数量的散点图,并在图上画一条最佳拟合线。然后我会用 1993 年的那个时间点,作为我对攻击次数的估计。建议该课程在预测攻击数量之前将数据分成几个部分。我决定按地区来划分,因为我认为这是对世界和这个时间范围内可能发生的趋势的合理划分。为了得到更准确的数字,我还决定使用 1993 年前后 10 年的数据。我想这也能帮助我更好地了解每个地区的情况。一个很好的例子就是看看中东和北非的爆炸袭击数量。大约在 2004 年,由于该地区冲突和战争的增加,爆炸事件的数量开始急剧上升。我不希望这一攻击高峰影响我的预测。在对每个地区做出预测后,我将它们相加,得到 1993 年所有爆炸袭击的数字。结果这个数字是 1250。这是我刚开始写这一部分时正在寻找的产品系列的中间位置。
正如你在上面的图表中看到的,我的最佳拟合线确实有问题。对于每一个图,我的线实际上是水平的,即使它们应该有更多的斜率,只看标绘的点。每张图都估计了一个非极端的数字,总的估计值在我期望的范围内。我不知道为什么我对视觉化有这个问题。我的作品可以在我的 GitHub 上看到,(文章底部的链接)如果有人知道为什么会这样,请随时联系我。
我所有的代码都可以在我的 GitHub 上找到:https://github.com/CBJohnson30/Global-Terrorism
手套+有趣-无聊
原文:https://towardsdatascience.com/glove-fun-boring-664fe0717c4c?source=collection_archive---------3-----------------------
GloVe,源自GlobalVectors的首字母缩写,是一种将单词表示为向量的无监督学习方法。它对语料库的单词共现统计进行训练,目标函数是专门选择来编码单词向量之间有意义的差异。一个比较著名的例子是,“国王”+“女人”-“男人”的结果与“女王”的向量最为相似。学习者设法量化皇室和性别的概念,以便它们可以被分解和重新组合,从而得到与 king 类似的单词。
我想看看这些单词向量是否有助于创建一个更智能的词库。如今,如果你在搜索一个和另一个单词“x”意思相似的单词,你可以用谷歌搜索“x 的同义词”。更有效且有助于缩小搜索空间的方法是给出所需同义词的特定方向。例如,如果你在寻找一个表示“缺乏经验”但没有负面含义的词,你可能会更喜欢“新鲜的”或“新的”而不是“无能的”。为此,我下载了词向量,这些词向量在由 2014 年维基百科文章和 Gigaword 5 组成的数据集上进行了预训练。我发现单词与其他向量相加和相减得到的向量最相似(由余弦相似度定义)。以下是一些沿好坏轴的类比。如表所示,“方案”+“好”--“坏”≘“计划”,反其道而行之,“方案”--“好”+“坏”≘“骗局”,沿着好的光谱正确捕捉语义。
** + good - bad - good + bad**
scheme plan scam
intelligence knowledge spy
naive idealistic stupid
possibility potential consequences
dream wish nightmare
notion concept stereotype
bold courageous risky
有趣无聊轴上的一些类比很有趣。
**+ fun - boring - fun + boring**
presentation showcase powerpoint
woman girl housewife
acquaintance friend coworker
music pop orchestral
test challenge exam
premiere festival opera
这里有一些优雅-笨拙轴心的例子。
**+ elegant - clumsy - elegant + clumsy**
persuade convince pressuring
walked strolled stumbled
threw tossed hurled
placed adorned mishandled
stylish sleek uninspired
根据 Richard Socher 的讲座,没有数学证明可以保证这些类比脱离模型。实际上,有时类比似乎是正确的,但很多时候却不是。一个更智能的词库已经初露端倪,但它可能需要一种未来的方法来更好地捕捉语义关系。
数据解释中的萤火虫、热手和其他(所谓的)谬误。
原文:https://towardsdatascience.com/glowworms-hot-hand-and-other-alleged-fallacies-in-data-interpretation-80dfb8c6b220?source=collection_archive---------6-----------------------
很久以前,当我第一次学习认知心理学时,我被分配到了关于所谓“热手谬误”的著名论文。要点很简单:人们不擅长评估概率。他们认为罕见的事件更有可能发生,并倾向于将一些基本原理归因于没有任何特殊情况下出现的所谓随机序列(这一点在 Tversky 和 Kahneman 的整个职业生涯中不断出现)。
当然,最近在“热手”方面,事情已经发生了变化。虽然不是完全万无一失,但似乎有相当有力的证据表明,一旦你开始用精细的齿梳解析数据,毕竟可能有一只“温暖的”手。米勒和桑十郎的争论让我想起了关于萤火虫的一个更古老的观点,萤火虫是某些昆虫物种的幼虫,它们既能发光又能同类相食。关于萤火虫分布的争论是,虽然它看起来可能是随机的,但实际上是高度选择性过程的结果:它们倾向于等距分布,正是因为它们试图最大化与所有其他蠕虫的距离,因为它们互相捕食。米勒和桑十郎的观点在某种意义上是相反的:在真正随机的分布中,我们不应该像在现实生活数据中那样经常看到“团块”。因此,与其说这是一个支持“热手”的论点,不如说这是一个支持不自然的大量数据的论点——包括“热手”和“冷手”。思考这个问题的一种方式是,在“大数据”层面上,吉洛维奇很可能仍然是正确的(当然,还有其他人质疑这一点):如果你检查前一次射击成功的每一次射击,你可能会发现有条件的成功概率并不比无条件的高。但是,如果你检查每一个,比如说,100 个镜头序列——大数据的小子集,换句话说——你会发现成功和失败的条纹比完全随机抽签更长更频繁。
这是一个微妙的论点,具有潜在的广泛应用——如果人们仔细考虑小样本分布的性质的移动部分。你可能会注意到,这与我之前关于城市与农村的区别的推测有着直接的相似之处:在足够高的聚集水平上,城市地区通常比农村地区的单位面积人口密度更高(有明显的例外,例如在恒河流域),它们的特点是相邻“块”之间的密度存在高度的局部差异——非常密集的块紧挨着非常稀疏的块(与米勒和桑十郎的论点中代表冷热手的块数据不同)。)农村地区可能平均密度较低,聚集程度较高,但它们的密度变化也较小,分布均匀,与萤火虫没有什么不同。人们可以很容易地想到利用置换测试来解决这个问题的分析方法:假设样本量为 100,其中 60 个是 A 型,40 个是 B 型,如果序列是随机的,那么您找到一个具有相同类型邻居的元素的概率分布是什么,您在真实数据中找到的实际“邻居”是什么?当然,诀窍在于这是两个极端都不自然的情况:太多的睦邻友好表明存在某种形式的“吸引力”,以子集为条件,而太少的睦邻友好表明某种形式的“排斥力”,而这反过来又可以量化。
这引发了一些额外的问题:这些“排斥”和“吸引”力量出现的“自然分析单位”是什么?从某种意义上说,这是吉洛维奇似乎犯了一个错误:先验地假设没有“自然”子集可以找到这些聚集的“倾向”。由于“冷”条纹会消除“热”条纹,因此只在更高的聚合级别检查数据时,它们的结果为零也就不足为奇了。但同样诱人的是,假设数据中存在的所有簇,也许通过聚类分析识别,实际上是有意义的——这正是 Gilovich 等人首先指出的谬误。我们可以将简单的模式识别转化为实际的科学,Miller 和 Sanjuro 指出了前进的方向,即一旦问题得到充分考虑,我们就可以在纯粹随机机会的假设下构建和模拟反事实,并将其作为基线来估计/量化数据中的“聚集”在多大程度上是“不自然的”。
保罗·克鲁格曼(Paul Krugman)在一篇关于理论和经验的旧文章(在发展经济学的背景下)中指出,数据分析的伟大之处在于它迫使我们精确地知道我们知道什么和不知道什么。这是有代价的,有时代价很高:在许多不精确的真理中,隐藏着许多事实上是真实的东西,我们只是在给定现有数据(和模型)的情况下,无法足够精确地知道这些东西。因此,我们扔掉了乞力马扎罗山的雪,就像我们扔掉了热带的雪一样,不是因为它们“不真实”,而是因为我们对它们了解不够。这意味着,一旦我们有必要的手段在足够精细的分析水平上更精确地检验数据,我们可能不得不收回以前的“荒谬的废话”,如乞力马扎罗的雪,篮球中的热手,或者,事实上,甚至艾丁斯(如果需要的话)是“暂时真实的”,如果重新检验的数据表明它们可能事实上存在的可能性。
使用 Firebase 实现无服务器化
原文:https://towardsdatascience.com/go-serverless-with-firebase-5348dedb70e9?source=collection_archive---------6-----------------------
关于无服务器什么,为什么和如何?
什么是无服务器架构?
Firebase Cloud Function
简而言之,无服务器架构是一种编程范式,专注于直接为 web 端点编写函数,而不是经历设置服务器、路由请求、定义 REST 资源,然后创建 GET、POST 和 PUT 方法的整个过程。还在迷茫?用程序员的术语来说,我们只需要编写方法体,其他的都是由服务提供商现成提供的。
最常见的无服务器服务提供商是亚马逊,他们有的 AWS Lambda 服务。这是一种高度可扩展的解决方案,广泛用于企业级应用。这些服务大部分要么与亚马逊发电机一起使用,要么与 MongoDB Atlas 一起使用。从 AWS 开始并构建一个应用程序是相当麻烦的,尽管它有如此多的功能和酷的集成。所以让我们用 Firebase 做同样的事情吧!!😃
为什么选择无服务器架构?
除了简单性,无服务器架构几乎没有其他优势。由于您只对 web 服务的逻辑进行编程,可伸缩性将不再是一个问题。您将只为执行次数付费,这意味着未使用的功能不会收费。Firebase 通过其身份验证平台简化了身份验证方式。毕竟,这也有不好的一面。您可能不了解底层硬件,因此在某些情况下,您必须遵循它们提供的标准硬件 API。但是对于存储,谷歌提供谷歌存储,AWS 为此提供 S3 存储桶。
怎么会?
我觉得这是最有意思的事情。让我们使用 firebase 云函数制作一个简单的应用程序,这是他们对无服务器架构的称呼。
第一步
- 转到https://firebase.google.com/
- 转到控制台
- 添加项目,给一个名字,然后按下创建
- 选择“确定”后,您将被定向到 firebase 控制台
- 在开发部分,转到功能
第二步
现在您已经创建了一个应用程序,您将有一些 NPM 软件包要安装。
安装 Firebase CLI 工具
$ npm install -g firebase-tools
现在使用工具登录
$ firebase login
您将被要求通过打开浏览器登录。相应地登录。现在使用下面的命令启动项目。
$ firebase init
选择云函数并按回车键,然后选择创建的项目并按回车键。在同一个项目文件夹中,创建一个名为 functions 的文件夹,转到该文件夹并启动一个节点项目,如下所示。
$ npm init
$ npm install firebase-functions@latest firebase-admin@latest --save
现在创建一个 index.js 文件并创建函数,假设它是一个普通的节点 js 服务器端代码。示例代码如下。
如果您熟悉 Node JS,很明显这个函数会将查询参数和主体参数返回给用户。
第三步
您现在可以部署应用程序了。为此,我们可以使用以下命令。
$ firebase deploy --only functions
一旦部署结束,您将获得函数 URL。您可以将其粘贴到浏览器上并发送 GET 请求,或者通过 REST API 测试工具发送请求。
Firebase
工作量很大吗?一旦你将这些步骤分类,你就可以专注于编写函数了,上面的代码是我唯一需要自己编写的代码;-).您可以轻松地与 Firebase 数据库、存储或身份验证连接,构建一个完整的应用程序。另外,你可以用免费的配额做很多事情。
我希望你喜欢读这篇文章。启动你的下一个项目,干杯!!
文件:https://firebase.google.com/docs/functions/get-started
视频系列:https://www.youtube.com/watch?v=EvV9Vk9iOCQ
上帝不玩骰子,但我们玩
原文:https://towardsdatascience.com/god-doesnt-play-dice-but-we-do-how-we-learned-to-love-multi-armed-banditry-c88177d0158a?source=collection_archive---------9-----------------------
或者说,我们是如何学会爱上多种武器的土匪行为的
如今个性化无处不在。从网飞电影推荐到优化行动号召的字体大小,在有记载的历史中,从来没有像福克纳的小说那样投入如此多的存在主义的悲伤和精神能量,让人们点击闪烁的图标。每个人现在都在做 A/B 测试,从他们的电子商务前端到他们的电子邮件营销活动;你(或者你的 UX 设计师)可能也不例外。真正的问题是,你真的需要知道“家庭错误率”是什么(你应该知道),或者有其他方法吗?
有!如果传统的 A/B 测试可以描述为掷硬币,两组有不同的转换概率,那么多臂强盗(MAB)就像掷骰子。更重要的是,如果我们真的是为了乐趣和利润而玩,我们可以把正常的骰子换成有负荷或有偏见的骰子,某些方面比其他方面更有可能被掷出
We’re about to go from ashy to classy
在这种情况下,就像我们这些四处游荡的恶棍一样,我们在任何给定的时刻都在赌该选择哪个选项;就像我们这些聪明的流浪儿一样,随着时间的推移,我们试图通过选择期望值较高的选项来最大化我们的收益,而不是选择期望值较低的选项,并试图在我们学习新信息时调整相对频率。
MAB 的好处在于,它旨在平衡收集信息的需求和收集信息的成本。感兴趣的 KPI(例如点击率)可以在开始时直接优化。但是我们需要确定如何给骰子的每一面分配权重。有许多方法可以实现这一点,如ε贪婪或置信上限,但 Thompson 采样是一个特别优雅的解决方案(顺便提一下,这也是 WeWork 的首选 MAB 策略)。简而言之,这是一种基于某个选项是最佳选项的概率来选择选项的有效方法。
假设我们有三种类型的登录页面,每个页面都有不同的副本和千年美学,因此有不同但未知的引发转换事件的概率。我们需要在每个页面的可能转换率上定义一个概率分布(通常是一个 Beta 分布)。预期的转换以及我们估计的不确定性将被很好地编码到与其登录页面相关的每个发行版中。
通过汤普森抽样,我们将从每个登录页面的相关概率分布中随机抽取。然后,我们获取具有最大采样值的登录页面,简单地将其提供给用户,并记录结果。重复这个过程,直到你的产品经理满意或者宇宙的热寂,无论哪个更快。
Left: A state of maximum entropy. Right: Also a state of maximum entropy.
这一过程隐含地优化了登录页面,使其具有最大的预期转换率和最少的估计不确定性(在文献中称为“利用”),同时仍然允许选择具有较低预期转换率和较高不确定性的选项(“探索”)。随着时间的推移,每个页面被选择的频率将与该选项是最佳选项的概率一致。随着时间的推移,我们可以最大限度地提高转化的数量,从而最大限度地提高贵组织最终销售的产品数量(在我们的案例中,是桌子和潮人的产品)。
这里真正强大的是这些分布不是静态的。当我们观察用户如何响应登录页面时,我们可以获取这些信息并更新每个选项的底层分布,以反映新数据中的信息,如下所示。
事实上,如果您对每个登录页面的预期转换没有先入为主的概念,您可以从每个页面的相同分布开始,简单地“让数据自己说话”开始时,选择是随机的,然后随着收集到更多的数据来更新分布,开始倾向于最高性能的选项。在这个例子中,登录页面“C”逐渐成为明显的赢家。
Bandits 允许从探索到利用的平稳过渡,并且可以更快更有效,因为它们实时地将流量转移到获胜的变化,而不是强迫你等到测试期结束。如果自动化和持续优化是你的目标,它们是有用的工具。
也就是说,A/B 测试仍然有一席之地,特别是如果统计的严格性和不确定性估计很重要的话。真正的诀窍是在给定的情况下找到合适的工具,并理解其中的利弊。
临别赠言:我们建议你拿出一小部分流量,用于随机选择。这个调整对抗了数据收集过程中的偏见,并确保您有一个无偏见的随机基线来评估您的 bandit 的功效。它还可以抵御不可预见的外部或季节性变化的影响,这些变化可能会彻底改变分布的参数。
超越敏捷数据科学工作流
原文:https://towardsdatascience.com/going-beyond-with-agile-data-science-fcff5aaa9f0c?source=collection_archive---------6-----------------------
超越我的眼睛所看到的,是我应用于生活中每一个方面的东西。在本文中,我将展示敏捷数据科学工作流如何在这方面帮助我。
我们生活在一个复杂的世界,我们生活在一个文化的世界。这意味着我们不能选择成为没有文化的生物。我们出生了,就是这样,你已经在那里了。你无法选择你的身份,父母,城市等等。然后我们学习,从生活和学校,我们的朋友,我们的家庭。
这个过程创造了一种看待事物的方式,一种思考世界、思考我们自己和我们周围事物的方式。我们的感官向世界敞开我们的大门,我们听到,我们感觉到,我们品尝到,我们看到。当我提到“超越”或类似的东西时,我指的是我们所有感官的结合,即我们从各个角度所感知的东西。
我们从“外部世界”获得数据,我们的身体和大脑分析我们获得的原始数据,然后我们“解释”事物。
建模世界
这是什么“解读”?只是我们从所获得的信息中学到了如何反应、思考、感受和理解。当我们理解时,我们正在解码形成这个复杂事物的各个部分,并将我们一开始获得的原始数据转化为有用和简单的东西。
我们通过建模来做到这一点。这是理解“现实”,我们周围的世界,但创造一个更高层次的原型来描述我们所看到的,听到的和感觉到的东西的过程,但这是一个代表性的东西,而不是“实际”或“真实”的东西。
更进一步
我们不呆在那里。我们的世界模型,或者说过程,有另一部分。我们认为特定的事物意味着什么,以及我们对它的感受。
ME JUMPING TO CONCLUSIONS
当我年轻的时候,我对很多很多事情有很多偏见。在见到人和事之前就对他们下结论。我不认为我是一个人。
我们习惯于很快下结论,而不是分析事情的每一面。我们习惯于看到我们眼睛所看到的,并“相信我们的直觉”。
遗憾的是,在我们的文化中占主导地位的常识是亚里士多德式的和中世纪式的。这意味着直觉在试图理解世界时会失败很多次,而且这种“常识”有时会伴随着判断,这种判断会在我们看待事物的方式上产生偏见。
在这种情况下,向前看意味着向前迈一步,把你的判断、常识和直觉放在一边,真正分析一种情况。我们应该为我们周围发生的每一件事都这样做,问问我们自己你正在做的、思考的和感知的事情是否真的正确。这是非常接近笛卡尔的的东西。
为什么要超越数据科学?
在一个难以预测未来的世界里,商业成功构建系统的能力离不开能力。
那么数据科学和这些有什么关系呢?实际上,超越我们的常识和直觉是解决复杂商业问题的唯一途径。
在一个充满直观模型的世界里,颠覆和进步来自超越,用数据去理解肉眼或“专家的眼光”看不到的东西。
由 Russell Jurney 提出的敏捷数据科学工作流程是理解数据科学和敏捷如何以及为什么帮助我们以创造性的方式超越、看到更多和解决问题的一种令人惊讶的方式。
https://www.oreilly.com/ideas/a-manifesto-for-agile-data-science
敏捷数据科学宣言(我们应该把敏捷数据科学工作流程放在这里)引领我们走向这一点。一次又一次地重复,重新思考业务流程和需求,尝试很多,倾听数据要说什么,理解并鼓励业务部门理解数据的意见必须始终包含在产品讨论中,找到解决问题的关键路径然后组织团队完成问题,走得更远,让模型解决问题,当然使用我们的专业知识来帮助他们,但不要偏袒他们
从了解业务及其需求到部署解决方案,我们需要从上、下、侧面看更大的画面。清空我们头脑中的直觉,每个人都可以加入到解决方案中,相信我们的模型所说的过程,并理解它是如何解决问题的。
最后,我想记住并声明,每个模型都假设一些事情,在这里,模型可以表示一种理解世界如何工作的方式,以随机森林分类器来判断交易是否是欺诈性的。我们需要理解这些假设,它们可能在开始时并不清晰,但它们确实存在。在机器学习和深度学习中,更容易看到这些假设是什么,它们在提出算法的论文中,也在代码中,所以在使用 ML 或 DL 库导入模型之前,理解它从数据和过程中假设什么,这将使“调试”变得容易得多。
感谢你阅读这篇文章。希望你在这里发现了一些有趣的东西:)
如果你有问题,就在推特上加我
** [## 法维奥·巴斯克斯(@法维奥·巴斯克斯)|推特
Favio Vázquez 的最新推文(@FavioVaz)。数据科学家。物理学家和计算工程师。我有一个…
twitter.com](https://twitter.com/faviovaz)
还有 LinkedIn。
[## Favio Vázquez -首席数据科学家- OXXO | LinkedIn
查看 Favio Vázquez 在世界上最大的职业社区 LinkedIn 上的个人资料。Favio 有 15 个工作职位列在…
linkedin.com](http://linkedin.com/in/faviovazquez/)
那里见:)**
深入到对象检测
原文:https://towardsdatascience.com/going-deep-into-object-detection-bed442d92b34?source=collection_archive---------2-----------------------
随着基于深度学习的计算机视觉模型的最新进展,对象检测应用程序比以往任何时候都更容易开发。除了显著的性能改进,这些技术还利用了大量的图像数据集来减少对大型数据集的需求。此外,由于目前的方法侧重于完整的端到端管道,性能也有了显著提高,实现了实时用例。
类似于我写的关于不同图像分类架构的博客文章,我将介绍两种对象检测架构。我将讨论 SSD 和更快的 RCNN,它们目前都可以在 Tensorflow 检测 API 中使用。
首先,我将介绍对象检测中的一些关键概念,然后举例说明如何在 SSD 和更快的 RCNN 中实现这些概念。
图像分类与目标检测
人们经常混淆图像分类和对象检测场景。一般来说,如果你想把一幅图像归入某个类别,你就使用图像分类。另一方面,如果您的目标是识别图像中对象的位置,例如计算对象实例的数量,则可以使用对象检测。
Illustrating the difference between classification and object detection.
然而,这两种情况之间有一些重叠。如果您想要将图像分类到某个类别中,可能会出现执行分类所需的对象或特征相对于整个图像来说太小的情况。在这种情况下,即使您对对象的确切位置或数量不感兴趣,您也可以通过对象检测而不是图像分类获得更好的性能。
想象一下,你需要检查电路板,并将其分为缺陷或正确。虽然这本质上是一个分类问题,但缺陷可能太小,用图像分类模型无法察觉。构建对象检测数据集将花费更多的时间,但它很可能会产生更好的模型。
An example of an IC board with defects.
使用图像分类模型,您可以生成完整图像的图像特征(通过传统或深度学习方法)。这些特征是图像的集合。使用对象检测,您可以在更细粒度、更精细的图像区域级别上完成这项工作。在前一种情况下,您可能会失去对分类信号的跟踪,而在后一种情况下,信号可能会以更适合用例的方式保存下来。
数据要求
为了训练自定义模型,您需要带标签的数据。对象检测环境中的标记数据是具有相应边界框坐标和标记的图像,即左下和右上(x,y)坐标+类别。
The normalised bounding box coordinates for the dogs in the image are e.g. [0.1, 0.44, 0.34, 0.56] and [0.72, 0.57, 0.87, 0.77]
一个经常被问到的问题是这样的:为了在问题 X 上做物体检测,我需要多少张图片?相反,更重要的是正确理解模型将在哪些场景中部署。每个类别有大量(例如> 100 个,可能> 1000 个)代表性图像是至关重要的。在这种情况下,代表性意味着它们应该与模型将被使用的场景范围相对应。如果您正在构建一个将在汽车上运行的交通标志检测模型,您必须使用在不同天气、照明和相机条件下拍摄的图像。对象检测模型并不神奇,实际上相当愚蠢。如果模型没有足够的数据来学习一般模式,它在生产中就不会有很好的表现。
While the image on the left is clear and easy to detect, ultimately, you should train on data which better reflects the use case.
通用对象检测框架
通常,在对象检测框架中有三个步骤。
1。首先,使用模型或算法来生成感兴趣的区域或区域提议。这些区域提议是跨越整个图像的一大组边界框(即,对象定位组件)。
2。在第二步中,为每个边界框提取视觉特征,对它们进行评估,并基于视觉特征确定提议中是否存在以及存在哪些对象(即,对象分类组件)。
3。在最后的后处理步骤中,重叠的框被组合成单个边界框(即,非最大抑制)。
区域提议
有几种不同的方法可以生成区域建议。最初,“选择性搜索”算法用于生成对象建议。莉莉艾·翁在她的博客文章中对这个算法做了详尽的解释。简而言之,选择性搜索是一种基于聚类的方法,它试图对像素进行分组,并基于生成的聚类生成建议。
An example of selective search applied to an image. A threshold can be tuned in the SS algorithm to generate more or fewer proposals.
其他方法使用从图像中提取的更复杂的视觉特征来生成区域(例如,基于来自深度学习模型的特征)或者采用强力方法来生成区域。这些强力方法类似于应用于图像的滑动窗口,具有多种比率和比例。这些区域是自动生成的,不考虑图像特征。
An example of the sliding window approach. Each of the bounding boxes will be used as a region of interest (ROI).
区域提议生成的一个重要权衡是区域的数量与计算复杂度。生成的区域越多,找到该对象的可能性就越大。另一方面,如果您详尽地生成所有可能的建议,则不可能实时运行对象检测器。在某些情况下,可以使用问题特定信息来减少 ROI 的数量(例如,行人的比率通常约为 1.5,因此生成比率为 0.25 的 ROI 是没有用的)。
特征抽出
特征提取的目标是将可变尺寸的图像缩减为一组固定的视觉特征。图像分类模型通常使用强视觉特征提取方法来构建。它们是否基于传统的计算机视觉方法(例如,基于滤波器的方法、直方图方法等)。)或深度学习方法,它们都具有完全相同的目标:从输入图像中提取代表手头任务的特征,并使用这些特征来确定图像的类别。在对象检测框架中,人们通常使用预训练的图像分类模型来提取视觉特征,因为这些模型往往能够相当好地概括(例如,在 MS CoCo 数据集上训练的模型能够提取相当一般的特征)。然而,为了改进模型,建议试验不同的方法。我在博客上发表的关于迁移学习的文章清楚地区分了不同类型的迁移学习以及它们的优缺点(一般和应用)。
非最大抑制
非最大值抑制的一般思想是将一帧中的检测数量减少到存在的对象的实际数量。如果框架中的对象相当大,并且已经生成了 2000 个以上的对象提议,则很可能其中一些提议彼此之间以及与对象之间会有显著的重叠。观看 Coursera 上的这个视频,了解更多关于 NMS 的信息。NMS 技术通常是不同检测框架的标准,但这是一个重要的步骤,可能需要根据场景调整超参数。
An example of NMS in the context of face detection.
评估指标
在对象识别任务中使用的最常见的评估度量是“mAP”,它代表“平均精度”。它是一个从 0 到 100 的数字,通常值越高越好,但是它的值不同于分类中的精度度量。
每个边界框将有一个相关的分数(该框包含对象的可能性)。基于预测,通过改变分数阈值来计算每个类别的精确召回曲线(PR 曲线)。平均精度(AP)是 PR 曲线下的面积。首先计算每个类别的 AP,然后对不同类别进行平均。最终结果是地图。
注意,如果检测具有大于某个阈值(通常为 0.5)的与地面实况框的联合' (IoU 或重叠)的'交集,则该检测为真阳性。我们通常不使用 mAP,而是使用 mAP@0.5 或 mAP@0.25 来指代所使用的 IoU。
A visualisation of the definition of IoU.
张量流检测 API
Tensorflow 检测 API 在一个包中汇集了许多上述想法,允许您使用 Tensorflow 后端快速迭代不同的配置。通过 API,您可以使用配置文件定义对象检测模型,Tensorflow 检测 API 负责将所有必要的元素组织在一起。
普罗托斯
为了更好地理解不同的支持组件是什么,请看一下包含功能定义的' protos 文件夹。特别是,在微调模型时,train、eval、ssd、faster_rcnn 和预处理原型非常重要。
单次多盒探测器
概述
SSD 架构由谷歌的研究人员于 2016 年发布。它提出了一个目标检测模型使用单一的深度神经网络结合区域建议和特征提取。
使用不同纵横比和比例的一组默认框,并将其应用于特征地图。由于这些特征图是通过将图像通过图像分类网络来计算的,因此可以在单个步骤中提取边界框的特征提取。为每个默认边界框中的每个对象类别生成分数。为了更好地适应地面真值框,为每个框计算调整偏移量。
The SSD network leveraging feature maps from VGG-16
卷积网络中不同的特征图对应不同的感受野,用于自然处理不同尺度的对象。因为所有计算都封装在单个网络中,并且实现了相当高的计算速度(例如,对于 300 × 300 输入 59 FPS)。
用法 关于用法,我们将研究 SSD 的不同示例配置文件。在利用 SSD 架构时,有几个参数非常重要,我们将逐一介绍。
首先,不同的分类网络有不同的优势和劣势(见这篇博文的概述)。例如,Inceptionv3 网络经过训练,可以很好地检测不同尺度的物体,而 ResNet 架构总体上实现了非常高的精度。另一方面,Mobilenet 是一种经过训练的网络,可以最大限度地减少所需的计算资源。ImageNet 上的特征提取网络的性能、参数的数量以及对其进行训练的原始数据集是性能/速度折衷的良好代表。特征提取器在‘feature _ extractor’部分定义。
第二组明显的参数是默认框和纵横比的设置。根据问题的类型,分析标记数据的边界框的各种纵横比和比例是值得的。设置纵横比和比例将确保网络不会进行不必要的计算。您可以在“ssd_anchor_generator”部分对这些进行调整。请注意,增加更多的比例和纵横比会带来更好的性能,但通常回报会减少。
第三,在训练模型时,在“数据增强选项”和“图像大小调整”部分设置图像大小和数据增强选项是很重要的。较大图像尺寸将执行得更好,因为小的对象通常难以检测,但是它将具有显著的计算成本。数据扩充在 SSD 的环境中尤其重要,以便能够检测不同尺度的对象(甚至在训练数据中可能不存在的尺度)。
最后,调整“train_config ”,设置学习率和批量大小对于减少过度拟合是很重要的,并且将高度依赖于您拥有的数据集的大小。
更快的 R-CNN
概述
更快的 R-CNN 是由微软的研究人员开发的。它基于 R-CNN,使用多阶段方法进行目标检测。R-CNN 使用选择性搜索来确定地区建议,将这些建议通过分类网络,然后使用 SVM 对不同地区进行分类。
An overview of the R-CNN architecture. The NMS phase is not shown.
更快的 R-CNN,类似 SSD,是一种端到端的方式。更快的 R-CNN 没有使用默认的边界框,而是使用区域提议网络(RPN)来生成一组固定的区域。RPN 使用来自图像分类网络的卷积特征,实现几乎无成本的区域提议。RPN 被实现为预测每个位置的对象边界和对象性分数的完全卷积网络。
An overview of Faster-RCNN
请注意,RPN 的设置与 SSD 网络类似(即,它不会凭空预测边界框)。RPN 网络与跨特征地图的滑动窗口一起工作。在每个滑动窗口位置或锚,一组建议被计算出不同的比例和长宽比。与 SSD 类似,RPN 的结果是基于锚点的“调整”边界框。
不同的组件被组合在单个设置中,并且被端到端或分多个阶段训练(以提高稳定性)。对 RPN 的另一种解释是,它引导网络“关注”感兴趣的区域。
用法 更快的 R-CNN 的大部分使用细节与 SSD 的类似。在 raw mAP 方面,更快的 R-CNN 通常优于 SSD,但它需要更高的计算能力。
Fast-RCNN 检测器的一个重要部分是“第一阶段锚生成器”,它定义了由 RPN 生成的锚。本节中的步幅定义了滑动窗口的步幅。请注意,尤其是在尝试检测小物体时(如果步幅过大,您可能会错过它们)。
尽管 fast-RCNN 论文的作者没有使用广泛的数据扩充,但仍然建议在处理较小的数据集时使用它。
结论
还有几个对象检测架构,我还没有提到。尤其是在查看实时应用程序时,Yolov2 经常被杜撰为一种重要的架构(相当类似于 SSD)。每当这篇博文被添加到 Tensorflow 检测 API 时,我都会更新。
问题
如果你有任何问题,我很乐意在评论中阅读。如果你想收到我博客上的更新,请在 Medium 或 Twitter 上关注我!
各付各的:我如何利用数据科学和机器学习在阿姆斯特丹找到一间公寓——第一部分
原文:https://towardsdatascience.com/going-dutch-how-i-used-data-science-and-machine-learning-to-find-an-apartment-in-amsterdam-part-def30d6799e4?source=collection_archive---------2-----------------------
阿姆斯特丹的房地产市场正在经历一场难以置信的危机,自 2013 年以来,阿姆斯特丹的房价每年以两位数的速度飙升。虽然房主有很多理由笑,但对那些想买房或租房的人来说就不一样了。
作为一名前往旧大陆的数据科学家,这对我来说是一个有趣的话题。在阿姆斯特丹,据说房产租赁市场和房产购买市场一样疯狂。我决定利用一些工具( Python、Pandas、Matplotlib、leav、plot . ly和 SciKit-Learn )来仔细研究一下这个城市的租赁市场格局,以便尝试回答以下问题:
- 一般租赁价格分布是什么样的?
- 哪些是最热门的地区?
- 哪个地区开始狩猎会更有趣?
最后,但同样重要的是,蛋糕上的樱桃:
- 我们能够预测公寓租金价格吗?
我的方法分为以下几个步骤:
- 获取数据:使用 Python,我能够从一些网站上收集出租公寓的数据。
- 数据清理:这通常是任何数据分析过程中最长的部分。在这种情况下,为了正确处理数据格式、删除异常值等,清理数据是很重要的。
- EDA: 一些探索性的数据分析为了可视化,更好的理解我们的数据。
- 预测分析:在这一步,我创建了一个机器学习模型,用我得到的数据集对它进行了训练和测试,以预测阿姆斯特丹公寓的租金价格。
- 特征工程:通过调整我们的数据和添加地理特征,概念化一个更健壮的模型
所以…我们各付各的吧
“各付各的”可以理解为在餐馆或其他场合分摊账单。根据城市词典,荷兰人在金钱上有点吝啬是出了名的——这并非巧合,我完全认同这一点。这个表达来自几个世纪前;英国与荷兰的竞争,尤其是在英荷战争期间,催生了包括荷兰语在内的一些词汇,这些词汇宣扬了某些负面的刻板印象。
回到我们的分析,我们将各付各的,以便找到一些便宜货。
由于我们管道中的“获取我们的数据”步骤,我们能够以 CSV 格式获得包含截至 2018 年 2 月阿姆斯特丹 1182 套出租公寓的数据集。
我们首先从这些数据中创建一个熊猫数据框架。
我们已经知道我们正在处理一个包含 1182 个观察值的数据集。现在让我们来看看什么是我们的变量和它们的数据类型。
现在来看一些统计数据——让我们来看一些汇总和分散测量。
此时,我们能够在数据集上得出一些观察结果:
- 有一个“未命名:0”列,似乎没有保存重要信息。我们会放弃的。
- 我们有一些数据类型为“object”的变量。如果我们需要分析数字或字符串数据,这可能是一个问题。我们将把它转换成适当的数据类型。
- “卧室数量”的最小值是 2。同时,“公寓大小”的最小值是 10。把两间卧室放在 10 平方米的空间里听起来有点挑战,不是吗?事实证明,在荷兰,公寓的评估是基于房间的数量,而不是卧室的数量。因此,对于我们的数据集,当我们说卧室的最小数量是 2 时,我们实际上是指房间的最小数量是 2(一个卧室和一个客厅)。
- 一些列,如名称、提供商代码、开始日期和城市代码似乎没有为我们的分析增加多少价值,所以我们将删除它们。
- 我们有一些日期时间字段。但是,无法使用包含此数据类型的数据集创建预测模型。然后我们将这些字段转换成整数, Unix Epoch 编码。
- 平均公寓租金价格约为。【2225.13 欧元。公寓租金价格的标准偏差约为。【1148.40 欧元。因此,关于 normalized_price,我们的数据是过度分散的,因为分散指数(均值方差)约为 592.68。
一些基本的 EDA —探索性数据分析
除了做一些清理工作,作为数据科学家,我们的工作是向我们的数据提出一些问题。
我们已经看到了大多数变量的四分位数、最小值、最大值和平均值的一些信息。然而,我更喜欢视觉。所以让我们跳进去,生成一个 Plot.ly box plot,这样我们就可以看到我们数据的快照了。
看起来我们有很多异常值——特别是阿姆斯特丹市中心的公寓。我猜有很多人想住在运河和博物馆附近——这不能怪他们。
让我们通过创建我们的数据子集来减少离群值的数量——也许对 normalized_price 的一个好的限制是欧元 3K。
我们能够去除大部分异常值。初步分析来看,阿姆斯特丹 Zuidoost(T21)和阿姆斯特丹 Nieuw West(T23)看起来很适合我们找房子。
现在让我们看看数据的分布。
通过目测我们的分布,我们可以注意到它偏离了正态分布。
但不是偏态 ( 偏态约为 0.5915)也不是峰态 ( 峰度约为 0.2774)。
高偏度和峰值通常表示创建预测模型的问题,因为一些算法对具有(几乎)正态分布的训练数据做出一些假设。峰值可能会影响算法计算误差的方式,从而增加预测的偏差。
作为一名数据科学家,人们应该意识到这些可能的警告。幸运的是,我们没有这个问题。所以我们继续分析。我们将利用 seaborn 来生成一个 pairplot。配对图非常有用,因为它们为数据科学家提供了一种简单的方法来可视化特定数据集中变量之间的关系。
有趣的是,我们有一些近乎线性的关系。诚然,它们中的大多数一开始都有点琐碎,例如 normalized_price 对 apartment_size 。但我们也可以看到一些其他有趣的关系——例如,公寓大小与每米价格,这似乎是一种几乎线性的负相关关系。
让我们继续,借助 Seaborn 的 热图绘制每个变量之间的皮尔逊相关值。热图(或热图)是数据的图形矩阵表示,其中各个值用颜色表示。除了是一个新术语之外,“热图的概念已经存在了几个世纪,只是有不同的名称(例如阴影矩阵)。
一些有趣的发现:
- 正如最初从我们的配对图中注意到的,每平方米价格和公寓面积确实有相当大的负皮尔逊相关指数(-0.7)。也就是说,粗略地说,公寓越小,每平方米的价格越高——每平方米价格上涨的 70%左右可以由公寓面积的减少来解释。这可能是由很多因素造成的,但我个人的猜测是对小公寓的需求更高。阿姆斯特丹正在巩固自己作为来自欧盟和世界各地的年轻人的目的地的地位,这些年轻人通常是单身,或者已婚但没有孩子。此外,即使在有孩子的家庭中,每个家庭的孩子数量在过去几年也快速下降。最后,较小的地方对这类公众来说更实惠。这些言论既没有科学依据,也没有统计依据——只是单纯的观察和猜测。
- 标准化价格和公寓面积的皮尔逊相关指数为 0.54。这意味着它们是相关的,但没那么相关。这是意料之中的,因为租赁价格可能包含其他因素,如位置、公寓条件等。
- 有两条白线与 begin_date 变量相关。结果,对于每一次观察,这个变量的值等于 16/02/2018 。所以很明显,在开始日期和我们数据集中的其他变量之间没有线性关系。因此,我们将放弃这个变量。
- 经度和 normalized_price 的相关性可以忽略不计,几乎为零。对于经度和每米价格之间的相关性也可以这样说。
近距离观察
由于我们的 pairplot 和 heatmap,我们已经看到了一些变量之间的相关性。让我们放大这些关系,首先是规模与奖金,然后是规模与价格(对数标度)。我们还将调查价格和纬度(对数标度)之间的关系,因为我们有兴趣知道哪些是最热门的狩猎地区。此外,尽管在上一步中获得了相关性,我们还将调查大小和纬度(对数标度)之间的关系。难道古老的&黄金地产咒语T21【地段、地段、地段 对阿姆斯特丹适用吗?这句口头禅也会决定公寓的大小吗?
我们会找到答案的。
嗯,我们不能真的说这些变量之间有线性关系,至少目前没有。请注意,我们对一些图使用了对数标度,以尝试消除由于标度之间的差异而可能产生的失真。
这是这条线的终点吗?
尽头
我们对模型中变量之间的一些关系做了一些检查。我们无法想象标准化价格或每米价格与纬度、经度和经度之间的任何关系。
然而,我想对这些价格在地理上的表现有一个更直观的看法。如果我们能看到阿姆斯特丹的地图,描绘出哪些地区更贵/更便宜,会怎么样?
使用叶子,我能够创建下面的可视化。
- 圆圈尺寸根据公寓尺寸定义,使用 0-1 的标度,其中 1 =最大公寓尺寸,0 =最小公寓尺寸。
- 红圈代表高 价格与面积比的公寓
- 绿色圆圈代表相反的情况——价格与面积比低的公寓
- 每个圆圈在被点击时会显示一个文本框,其中包含以欧元为单位的月租金,以及以平方米为单位的公寓面积。
在视频的前几秒钟,我们可以看到运河之间的一些红点,靠近阿姆斯特丹中心。当我们离开这一地区,走近其他地区,如阿姆斯特丹祖伊德、阿姆斯特丹祖伊杜斯特、阿姆斯特丹西和阿姆斯特丹北时,我们能够看到这种模式的变化——大部分是由大绿圈组成的绿点。也许这些地方提供一些不错的交易。使用我们创建的地图,可以定义一条路径来开始寻找一个地方。
所以也许价格和位置终究是有关系的?
也许这就是线的终点了。也许这些变量之间没有线性关系。
走向绿色:随机森林
随机森林或随机决策森林是一种用于分类、回归等任务的集成学习方法,通过在训练时构建大量决策树并输出类(分类)或单个树的均值预测(回归)的模式的类来操作。随机决策树纠正了决策树的习惯,即过度适应到它们的训练集,并且在检测数据中的非线性关系时非常有用。
This.
随机森林是我最喜欢的机器学习算法之一,由于一些特征:
- 随机森林几乎不需要数据准备。由于它们的逻辑,随机森林不需要对数据进行缩放。这消除了清理和/或扩展数据的部分负担
- 随机森林可以训练的非常快。旨在使单个树多样化的随机特征子集同时也是一个很好的性能优化
- 随机森林很难出错。例如,与神经网络相反,它们对超参数不那么敏感。
这样的例子不胜枚举。我们将利用这种力量,尝试用我们目前掌握的数据来预测公寓租赁价格。我们的目标变量为我们的 R 随机森林回归变量,即我们将尝试预测的变量,将是 normalized_price 。
但在此之前,我们需要做一些功能工程。我们将使用 Scikit-learn 的随机森林实现,这需要我们对分类变量进行一些编码。在我们的例子中是地区 1 和地址。其次,我们还会去掉一些不重要的功能。最后,我们需要删除 price_per_meter,我们创建的一个变量,它是 normalized_price 的代理——否则我们将会有数据泄漏,因为我们的模型将能够“欺骗”并轻松猜测公寓价格。
培训和测试
How overfitting usually looks like.
过度拟合发生在模型捕捉到数据中的噪声和异常值以及潜在模式时。这些模型通常具有高方差和低偏差。这些模型通常很复杂,像决策树、SVM 或神经网络,容易过度拟合。这就像一个足球运动员,除了是一个非常好的前锋,他在其他位置上表现很差,比如中场或者防守。他太擅长达成目标了,然而在其他事情上却做得极其糟糕。
测试过度配合的一种常见方法是设置单独的训练和测试。在我们的例子中,我们将使用由数据集的 70%组成的训练集,使用剩余的 30%作为我们的测试集。如果在预测训练集的目标变量时,我们的模型得到了很高的分数,但在预测测试集时却得到了很低的分数,那么我们可能会过度拟合。
摊牌
在训练和测试我们的模型之后,我们能够得到下面的结果。
Predicted Values in Orange; Actual Values in Blue.
从图中我们可以看到,我们的模型在预测公寓租金价格方面做得不错。使用我们的模型,我们能够获得 0.70的分数,其中 1 代表可能的最佳分数,而-1 代表可能的最差分数。
请注意,这是我们的基线模型。在本系列的第二篇文章中,我将事情扩展了一点,以便在模型分数上获得大约 10%的提高。
你可能也会喜欢
**** [## 保持机器学习模型在正确的轨道上:MLflow 入门,第 1 部分
了解为什么模型跟踪和 MLflow 对于成功的机器学习项目至关重要
mlopshowto.com](https://mlopshowto.com/keeping-your-machine-learning-models-on-the-right-track-getting-started-with-mlflow-part-1-f8ca857b5971) [## 各付各的,第 2 部分:使用地理数据改进机器学习模型
一切开始的地方
towardsdatascience.com](/going-dutch-part-2-improving-a-machine-learning-model-using-geographical-data-a8492b67b885)****
各付各的,第 2 部分:使用地理数据改进机器学习模型
原文:https://towardsdatascience.com/going-dutch-part-2-improving-a-machine-learning-model-using-geographical-data-a8492b67b885?source=collection_archive---------5-----------------------
一切开始的地方
在我之前的帖子中,我描述了使用数据科学和机器学习在阿姆斯特丹寻找公寓的过程。使用从互联网上获得的公寓租金数据,我能够探索和可视化这些数据。作为可视化部分的一部分,我可以创建下面的地图:
最终,我能够使用这些数据来构建、训练和测试一个使用随机森林的预测模型。有可能达到 R2 得分 0.70,这对于基线模型来说是一个很好的衡量标准。测试集的预测值与实际值的对比结果如下图所示:
从这些数据中创建一个预测模型的想法是为了有一个好的参数,以便知道租赁列表是否有一个公平价格。这将允许我们找到一些便宜的或者扭曲的东西。这背后的推理是,如果我遇到任何一套公寓的租赁价格比我们的模型预测的低得多,这可能意味着一笔好交易。最终,这被证明是在阿姆斯特丹找房子的一种有效方式,因为我能够专注于特定的区域,发现一些好的交易,并在我来到这座城市的第一天找到一套公寓。****
After finding an apartment in AMS
现在回到我们的模型。作为一个基线模型,在预测质量方面有潜在的改进空间。下面的管道已经成为我最喜欢的处理数据问题的方法:
- 从基线模型开始
- 检查结果
- 改进模型
- 重复直到结果令人满意
所以我们现在到了第三步。我们需要改进我们的模型。在上一篇文章中,我列出了我如此喜欢随机森林的原因,其中之一是你不需要花很多时间调优超参数(例如神经网络就是这种情况)。虽然这是一件好事,但另一方面,为了改进我们的模型,它给我们施加了一些限制。我们几乎只剩下工作和改进我们的数据,而不是试图通过调整参数来改进我们的预测模型。
这就是数据科学的妙处之一。有时候这感觉像是一项调查工作:你需要寻找线索并把这些点联系起来。就好像真相就在那里。
Look! An empty apartment in Amsterdam!
所以现在我们知道,我们需要处理我们的数据,并使它变得更好。但是怎么做呢?
在我们的原始数据集中,我们能够应用一些特征工程来创建一些与公寓位置相关的变量。我们为一些分类特征创建了虚拟变量,例如地址和地区。这样,我们最终为每个地址和地区类别创建了一个变量,它们的值可以是 0 或 1。但是我们在分析中忽略了一个方面。
北方的威尼斯
阿姆斯特丹有一百多公里长的grachten(canals),大约 90 个岛屿和 1500 座桥梁。沿着主要运河有 1550 座纪念性建筑。17 世纪的运河圈地区,包括 Prinsengracht、Keizersgracht、Herengracht 和 Jordaan,在 2010 年被联合国教科文组织列为世界遗产T21,为阿姆斯特丹赢得了“北方威尼斯”的美誉。
阿姆斯特丹的地址通常包含一些信息,可以让人们知道一个地方是否坐落在运河前面——所谓的“运河房屋”。位于 Leidsegracht 的公寓最有可能看到运河的景色,而位于 Leidsestraat、的公寓就不一样了。也有建筑物位于广场内的情况,例如广场上的一些建筑物。
不用说,运河房子有额外的吸引力,因为它们提供了美丽的景色。在脸书群体中,可以看到运河房屋在挂牌后几个小时内就被出租。
Who wants to live in a Canal House?
我们将从公寓地址中提取这些信息,以创建另外三个变量: gracht 、 straat 和 plein ,可能的值为 0 和 1。为这些变量创建单独的变量,而不是仅创建一个具有不同可能值(如 1、2、3)的变量的原因是,在这种情况下,我们会将其视为一个连续变量,诱使我们的模型考虑这一重要性尺度。我们将有希望发现运河房屋是否真的如此受欢迎。
位置,位置,位置
通过观察我们的模型的特征重要性排名中的前 15 个最重要的特征,我们能够注意到,除了纬度和经度之外,许多与地址和地区相关的虚拟变量对于我们的模型是有价值的,以便正确地进行预测。所以我们可以说,位置数据肯定大有可为。
我们将详细阐述这一点。但问题是,怎么做?
Restaurants, bars and cafes near Leidseplein, Amsterdam.
走向社交
阿姆斯特丹除了拥有大约 80 万居民(对于西欧国家的首都来说,这个数字很小)之外,还遍布酒吧、咖啡馆和餐馆,拥有欧洲最好的公共交通系统之一。但是,重要的是要想清楚我们的目标主体:人。我们在这里的主要目的是了解人们在寻找公寓时的行为。我们需要将我们的目标分成不同的群体,这样我们就可以了解他们在住房和位置方面的需求。有人可能会说,靠近酒吧、咖啡馆和餐馆对某些人来说是有吸引力的。其他人可能愿意住在离公园和学校更近的地方,比如有小孩的夫妇。这两类人也可能对住在公共交通附近感兴趣,比如电车和公共汽车站。
Amsterdam Centraal Station
这给了我们一些建立假设的提示。靠近这些类型的地方会影响公寓租金价格吗?
为了测试这个假设,我们需要将这些数据输入到我们的模型中。
Yelp 是一个社交平台,它宣传自己的宗旨是“将人们与当地伟大的企业联系起来”。它列出了诸如酒吧、餐馆、学校和许多其他类型的兴趣点——世界各地的兴趣点,允许用户对这些地方写评论。2018 年,在 Q1,Yelp 每月平均有 3000 万独立访客通过 Yelp 应用程序访问 Yelp,7000 万独立访客通过移动网络访问 Yelp。通过 Yelp 的融合 API 可以很容易地提取 POI 信息,将纬度和经度作为参数。
Yelp 在其数据库中列出了一些地点类别(不幸的是,没有关于咖啡店的类别)。我们对以下内容感兴趣:
活跃的生活:公园、健身房、网球场、篮球场
酒吧:酒吧和酒馆
咖啡馆:不言自明
教育:幼儿园、高中和大学
酒店/旅游:酒店、汽车租赁店、旅游信息点
交通:电车/公共汽车站和地铁站
对于这些类别中的每一个,Yelp 都列出了包含其纬度和经度的 POI。
我们的方法是:
- 查询Yelp Fusion API以获取阿姆斯特丹上述类别的兴趣点数据
- 计算每个公寓和每个 POI 之间的米距离。
- 计算每个类别中有多少个 poi位于每个公寓的 250 米半径内。这些数字将成为我们数据集中的变量。
通过使用 Yelp 的 Fusion API,我们已经能够获取目标范围内每个类别的 50 个兴趣点的地理数据。
在我们开始计算每个 POI 和每个公寓之间的距离之前,请记住:纬度和经度是角度的度量。
纬度是指赤道以北或以南的度数。经度被测量为本初子午线线以东或以西的度数。这两个角度的组合可用于精确定位地球表面的确切位置。
如上图所示,地球表面两点之间最快的路径是"大圆路径",换句话说,这条路径包含了你可以在地球上画出的与两点相交的最长圆的一部分。并且,由于这是使用以角度表示的坐标的球体上的圆形路径,距离的所有属性将由三角公式给出。
Haversine Formula.
地球上两点之间的最短距离可以用哈弗辛公式计算出来。在 Python 中,它看起来像这样:
from math import sin, cos, sqrt, atan2, radians
# approximate radius of earth in km
R = 6373.0
lat1 = radians(52.2296756)
lon1 = radians(21.0122287)
lat2 = radians(52.406374)
lon2 = radians(16.9251681)
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
c = 2 * atan2(sqrt(a), sqrt(1 - a))
distance = R * c
现在我们知道了如何计算两点之间的距离,对于每个公寓,我们将计算每个类别中有多少个 POI 位于 250 米半径范围内。
将这些数据连接到我们之前的数据集中后,让我们看一下它的样子——注意右侧的最后几列:
把所有的放在一起
让我们看看添加这些变量后的数据集。
我们将从获得描述性统计的一些度量开始:
- 公寓在 250 米半径范围内平均有 0.7828 个酒吧。对于那些喜欢去喝一杯啤酒而不需要走太多路的人来说,这是个好消息。
- 咖啡馆似乎也遍布整个城市,平均每个公寓步行距离内有 0.6703 个 POI。
- 公寓 250 米内交通 POI 平均数量接近于零。
我们现在将为这些变量生成一些箱线图,看看它们如何影响 normalized_price 。
看起来这三个变量确实对 normalized_price 有重大影响。
那么 gracht 、 straat 和 plein 呢?
不出所料,运河别墅和广场公寓的价格都略高。对于位于普通街道的公寓,价格略低。
现在,我们将总结所有内容,并通过模型中引入的新变量和我们的目标变量 normalized_price 之间的 Pearson Correlation 矩阵生成热图。
不幸的是,我们的热图没有提供我们的新变量和 normalized_price 之间显著相关性的任何迹象。但是,这并不意味着它们之间没有任何关系,只是意味着没有显著的线性关系。
走向绿色,第 2 部分
既然我们丰富了我们的数据集,现在是时候用新数据训练我们的模型,看看它的表现如何。
How our new predictions perform. Predicted values in orange, actual values in blue.
考虑到我们的基准模型,我们能够将我们的 R2 得分从 0.70 提高到 0.75 — 大约 7.14% 。
上面的图描绘了我们获得的新预测值与实际值的比较。特别是在预测接近最高和最低价格的值时,可能会看到一个小的改进。
就特性的重要性而言,发生了一些有趣的事情。我们引入的一些新变量变得非常重要,从而降低了其他变量的重要性。注意由地址生成的虚拟变量变量是如何失去重要性的。就区变量而言,它们甚至不再是前 15 个最重要变量的一部分。如果我们想把这些变量从模型中去掉,我们的结果可能不会有太大的不同。
有趣的是,250 米半径范围内的交通 POI 数量不如该距离内的咖啡馆数量重要。一种可能的猜测是,交通更加均匀地分散在整个城市——大多数公寓靠近电车、公共汽车或地铁站,而咖啡馆可能集中在更中心的地区。
我们研究了大量可用的地理数据。也许让我们的模型变得更好的一个方法是获取诸如建筑建造日期、公寓条件和其他特征的信息。我们甚至可以利用地理数据,将变量建立在 POI 半径大于 250 米的范围内。也可以探索 Yelp 的其他类别,如商店、杂货店等,看看它们如何影响租赁价格。
关键要点
- 提高一个模型的预测能力不是一件小事,可能需要一点创造力来找到使我们的数据更丰富、更全面的方法
- 有时一个小的模型改进需要相当多的工作
- 在预测分析管道中,获取、理解、清理和丰富您的数据是一个关键步骤,但有时会被忽视;这也是最耗时的任务——在这种情况下,这也是最有趣的部分
这是两部分系列的第二部分。点击这里查看《T2》第一部:
[## 各付各的:我如何使用数据科学和机器学习在阿姆斯特丹找到一间公寓——部分…
阿姆斯特丹的房地产市场正在经历一场令人难以置信的危机,房地产价格以两位数的速度飙升…
towardsdatascience.com](/going-dutch-how-i-used-data-science-and-machine-learning-to-find-an-apartment-in-amsterdam-part-def30d6799e4)
如果你喜欢这篇文章,你可能也会喜欢:
[## 保持机器学习模型在正确的轨道上:MLflow 入门,第 1 部分
了解为什么模型跟踪和 MLflow 对于成功的机器学习项目至关重要
mlopshowto.com](https://mlopshowto.com/keeping-your-machine-learning-models-on-the-right-track-getting-started-with-mlflow-part-1-f8ca857b5971) [## 使用机器学习检测金融欺诈:赢得对不平衡数据的战争
机器学习和人工智能会在这场战斗中成为伟大的盟友吗?
towardsdatascience.com](/detecting-financial-fraud-using-machine-learning-three-ways-of-winning-the-war-against-imbalanced-a03f8815cce9)
走向规范——数据科学的真正超级力量
原文:https://towardsdatascience.com/going-prescriptive-the-real-super-power-of-data-science-66ebb79fb89c?source=collection_archive---------13-----------------------
Superhero Girl Speed by alan9187— CC0
在其核心,数据科学依赖于机器学习的方法。但是数据科学也不仅仅是预测谁会购买,谁会点击或者什么会坏掉。数据科学使用 ML 方法,并将其与其他方法相结合。在本文中,我们将讨论规范分析,这是一种将机器学习与优化相结合的技术。
说明性分析——做什么,不做什么
关于如何解释,我最喜欢的例子来自 Ingo Mierswa。假设你有一个预测明天会下雨的机器学习模型。不错——但这对你来说意味着什么呢?你开车去上班还是骑自行车去?在这种情况下,你不可能是唯一一个喜欢开车的人。结果可能是,你被堵在路上一个小时。尽管下雨,还是骑自行车会不会更好?
Depending on your forecasts for weather and traffic you might either take the car or the bike
对此的解决方案是定义一个定制的适应度函数。在给定天气预报、预期交通和个人偏好的情况下,你可以最大化这种适应性。这是说明性分析!这个想法不仅仅是预测将会发生什么,也是建议做什么。
在这个简单的例子中,我们有一个非常小的可操作选项的超空间:要不要骑自行车。这使得我们的优化很容易:评估两者并取其精华。在即将到来的现实世界的例子中,你可以看到这个超空间可能是巨大的,优化问题相当棘手。
预测定价
您可能会尝试使用直接预测模型进行价格计算。假设您有一个带有正确价格的数据集。你可以把这当作一个回归问题,用你最喜欢的 ML 方法来解决。由此产生的模型可以直接用于生产,以预测价格。
这里的大问题是有一个标签的奇迹。你从哪里得到的价格?在实践中,您使用人为生成的价格。你怎么知道这些是好的?实际上,这些标签的质量限制了建模的最高质量。当然,您可以通过使用 A/B 测试来引导自己摆脱这个问题。你有时会提供比人为价格更低或更高的价格来衡量成功。但是这是昂贵的并且不总是可行的。
指令性定价
解决这一问题的另一种方法是指令性定价。与 rain 示例类似,我们需要定义一个适应度函数来反映业务案例。在零售的例子中,你可以从需求价格关系开始。一个简单的健身功能看起来像这样:
fitness = gain = (Price — Cost)*demand
其中需求是机器学习模型的结果,该模型取决于日期、价格甚至其他因素。
如果你与保险公司合作,你的健康状况将会是这样的:
fitness = profitability = f(Premium,DefaultRisk,..)
在本例中,我们希望优化保费,以获得最大收益。其他因素也是从依赖于客户属性的机器学习模型中得出的。
在 RapidMiner 中实现
让我们看看如何实现这样一个系统。我受雇于 RapidMiner,因此我的首选工具当然是 RapidMiner 。当然,如果你愿意,你可以用 Python 或者 R 来构建类似的东西。
在我们的实现中,我们希望对客户是否会接受给定的报价进行评分。结果是取决于价格和其他元数据的接受置信度。这里需要注意的是,置信度不等于概率,即使在[0,1]中归一化。
在规定部分,我们将使用这个模型来定义我们的价格。我们会以这样的方式改变价格,每个客户有 0.75 的信心接受我们的报价。0.75 可能源自样本约束。例如,我们希望每个月至少有 1000 个被接受的报价。我们由此得出的适应度函数是:
fitness = price-if([confidence(accept)]<0.75,(0.75-[confidence(accept)])*1e6,0)
这意味着每当我们的信心下降到阈值以下时,我们就增加一个惩罚因子。
Example Implementation in RapidMiner. This trains a model and optimized the price for acceptance of offer. The fitness function is defined within Prescriptive Optimization
上面描述的示例过程首先是导出一个模型来预测。接下来,我们进入优化。优化采用我们想要优化的输入示例、设置默认边界的参考集和模型。在优化循环中,我们计算上面的适应度。由于优化是单变量的,我们可以使用网格。我们可以使用 CMA-ES、BYOBA 或进化优化。结果是这样的健身
Performance evaluation for one customer. The fitness gets better for higher prices until it hit the spot where confidence(accepted) < 0.75.
我们可以看到,适应度随着价格的增加而上升,然后下降,因为置信度低于 0.75。衍生价格为:976 欧元。
这里描述的过程可以在我的 github 档案中找到。
在神经网络中走向侧面
原文:https://towardsdatascience.com/going-sideways-in-neural-networks-7e15b3c4cc63?source=collection_archive---------2-----------------------
神经网络有几个致命的问题。其中最主要的是过度拟合——给定足够的训练时间,神经网络将准确预测训练数据,同时失去理解新数据的能力。它完全不能概括它所学到的东西。例如,一个图像分类器最终可以完美地预测它是否正在看一只猫的照片,在你已经手动分类的图像中。然而,这种特殊性使得对所有不完全像它所学习的图像的分类成为一场掷硬币的游戏。图像分类器已经学会记忆答案。
研究人员通过提前停止来避免过度适应。他们根据一组不存在于训练数据中的输入测试网络,这组输入被称为“保持”组。网络在保留集上的精确度是对网络在新数据上表现如何的估计。一旦这个坚持组的准确性变得更差,研究人员就停止训练网络。网络已经学习了足够的知识来进行归纳,任何额外的训练都会导致记忆(即过拟合训练数据)。**
从根本上说,我们不想要一个与我们的训练数据完全匹配的网络。提前停止是一种组装,一种补偿研究人员优化错误事物的方式。我们想要一个能够归纳的网络,这样它就可以预测不完全像它以前看到的事情。然而,我们优化了网络的成本函数,该网络仅准确预测了它所看到的。我们有错误的成本函数。
出路
想象成本函数的最小值是碗的中心。优化类似于把球滚下碗,直到它停在中间。然而,通过提前停止,我们希望我们的球滚到靠近中心的点,而不是正好在中心的点。当球滚下碗边时,它提高了预测的准确性。在接近底部的某个地方,网络对陌生输入的准确性开始恶化。网络开始记忆,而不是归纳。我们在某一点上停止了球,这就是提前停止。**
重要的是要认识到,如果我们多次滚动球,并找到我们提前停止的位置(没有记忆就概括的位置),所有这些提前停止的点形成一个围绕碗中心的连续环。我们甚至可以把碗切割成这个更小的环!每一个“好的概括”网络都将是碗唇上的,而任何进一步进入碗中的都将是一个“记忆陷阱”网络。对于这个更小的碗,我们不想再滚下——我们应该而不是*顺着斜坡的方向;我们不应该使用梯度下降!*****
相反,我们希望沿着这个碗的边缘迁移,停留在“良好概括”网络的边缘,永远不要偏离到所有“记忆陷阱”所在的碗的中心。重要的一点是,碗的某些面可能会很早就开始记忆,因为他们从一个糟糕的概括开始。我们想在碗的边缘走来走去,尝试不同的‘好的概括’,因为其中一些概括可能比其他的更好!沿着边缘行进是找到更好的概括的最好方法——远胜于将球滚向不同的方向数百次,摆弄初始化!****
横着走
从数学上来说,我们如何像那样沿着边缘滚动?
简单—我们垂直于梯度移动。梯度向量是我们碗中最陡下降的方向;碗的一些区域凸起或起皱,最陡的方向并不总是朝着中心。然而,无论最陡的方向是什么,边缘总是垂直于它!在更高维度中,那个边缘仍然是垂直的,尽管有许多垂直的方向。轮圈为子空间。并且,通过测量网络在保留输入上的准确性,我们有了在这个子空间中进行优化的度量。
因此,当你第一次训练网络并在泛化时提前停止时,你然后运行新的优化:最小化子空间边缘上的损失函数,该损失函数与梯度正交,其中损失是网络在保持集上的不准确性。在每一步,你都要测量训练集的倾斜度,就像常规的 SGD 一样,但是你要移动垂直于那个倾斜度*。高维空间中有许多垂直方向,因此您为保持输入* 选择梯度最大的方向!你实际上是在说“我不想记住我的训练数据;我只想改进这个新数据。”******
那不会导致对隐藏数据的记忆吗?没错。该子空间边缘遭受相同的过度配合问题。沿篮筐移动,你保证不会记住旧的训练数据,但你沿篮筐的移动可以记住保持数据 。轮辋需要自己的早停,创造自己的碗轮辋!你的新的边缘是一个更小的子空间,它被约束为与训练数据的梯度和与保持数据的梯度正交。有了许多坚持的设定,这可能会永远继续下去…这实际上是计划!****
抵制的层次
假设你有一百万张图片,一半是猫,一半是其他的东西,都有正确的标签。你可以给你的神经网络 80 万张这样的图片用于训练,保留 10 万张作为确定提前停止的保留集,另外 10 万张作为测量预期真实世界准确度的验证集。那是正常的做事方式。
然而,有了对碗状边缘和提前停止的这种认识,一种不同的方法出现了:将图像分块到箱中,每个箱有 100k 张图像;在第一个 100k 图像上训练您的网络,使用第二个 100k 作为确定提前停止的保留;当撑出精度开始下降时,及早停止;将*垂直于训练数据的坡度,并在保持数据的坡度的方向上移动,从而移动轮辋;使用第三个 100k 作为支撑,以确定这一新梯度的早期停止。*****
重复这一过程,仔细消化 10 万批新数据,而不去记忆旧数据。通过沿着每个连续箱的边缘移动,我们正在搜索一个越来越小的子空间。每个箱子都有自己的限制,说“不要沿着我的梯度移动——那只会导致记忆”。结合所有这些限制,我们沿着碗的边缘缩小了可用的方向,使得搜索更容易。(但是,当我们沿着边缘移动一步时,我们仍然需要检查我们的新位置是否对应于一个提前停止点。这意味着我们检查训练数据的梯度,并查看在该方向上的移动是否会导致保持精度下降。)
一切都是坚持
在具有一百万个图像的示例中,我们形成了 100k 个图像的连续箱,并且迭代梯度下降、提前停止和正交子空间。如果我们把这些箱子做得更小,每个箱子只有 100 张图片,会怎么样?或者,如果每个图像都是自己的 bin,并且可以随时添加新的图像,会怎么样?这就是在线学习——当每个新图像到达时,网络执行额外的训练,而不牺牲先前的归纳!传统的网络是在实验室中训练出来的,不能从新的经验中学习。通过迭代正交梯度技巧,我们的“rim”网络可以在操作期间继续学习。(DARPA 正在资助对人工智能的研究,这种研究可以边进行边学习,所以这可能很重要。)
这可能有助于拟人化这个正交的把戏,它在“滚下碗”和“沿着边缘滚”之间摆动。网络在碗的梯度方向(最陡的方向)上滚动一小段距离,询问“如果我以这种方式改变一点,我对新信息的准确性会不会降低?”如果精度提高,网络向那个方向移动,这是普通的梯度下降。然而,如果新信息的准确性下降,网络会对自己说“如果我从碗的最陡部分往下走,我会失去一般性,并开始记忆;沿着边缘的哪个方向,垂直于最陡方向,反而会提高拒绝数据的准确性?”在每一步之后,该过程重复进行。****
因此,每个输入都是一个拒绝集合,我们将向下移动到拒绝的梯度的分量,该分量与所有先前输入的梯度正交,遍历碗的边缘。一旦我们沿着那个边缘走了一步,我们也检查沿着的一步是否所有先前输入的梯度会降低保持精度(这决定我们是否已经‘远离边缘’了)。如果保持精度会增加,那么网络不在“边缘上”,所以我们沿着所有先前输入的梯度移动一步;如果精度会降低,我们将搜索限制在该梯度的正交子空间,而不是沿着保持的梯度移动。每一个新的输入都会触发这一过程,学习新的数据而不失一般性。
我希望这有助于我们寻找一种真正的可以终生学习的普遍智能。有诱人的证据表明,我们的大脑使用一种学习技术,这种技术相当于梯度下降的反向传播(在 19:30 这里是)——如果我们自己的大脑也使用类似于我上面描述的“边缘”搜索的方法来避免过度拟合,我不会感到惊讶。
足够好的数据科学
原文:https://towardsdatascience.com/good-enough-data-science-e2e9adc26daf?source=collection_archive---------6-----------------------
围绕数据科学的炒作的一个症状是,我们作为从业者需要实践它。归咎于营销、销售、博客作者甚至投资者很容易,但我们同样有责任让我们所做的事情变得不必要的复杂。
如果你在一个标题为“数据科学”、“机器学习”或(上帝保佑你)“人工智能”的部门工作了 1 周以上,你就会感受到这种压力,并完全明白我的意思。如果你没有听过,这里有一些你可能听过的问题和短语——按照恐慌发作的递增顺序排列。
- “这个新功能利用了机器学习吗?”
- “我们为什么不用更多的人工智能?”
- “我邀请了 IBM 的销售代表。沃森毕竟有助于治疗疾病,他们肯定能帮助你建立一个更好的推荐系统。”
并不是说机器学习,AI 或者沃森都是不好的东西。而是我们已经到了一个地步,数据科学/AI/ML 的炒作已经把解决方案放在了问题之前。假设是,如果你没有使用最复杂或最前沿的方法,你就不是真正的数据科学家。
现在回头看看这三个引起恐慌的短语。你自己团队中的某个人可以像销售副总裁一样轻松地说出这些话。相信我,我有时也有罪。我们的理由不同,但最终的结果是一样的。销售想要告诉客户驱动产品的复杂人工智能。高管团队想要吹嘘公司的数据科学能力。当然,数据科学团队希望学习如何使用最酷的工具,创建真正改变游戏规则的功能或产品。
改变叙述——一个例子
与其从解决方案开始,不如回到问题本身。假设您的公司以高于预期的速度带来新客户,客户支持团队不堪重负。电子邮件是主要的客户支持渠道,团队的平均响应时间从 4 小时缩短到了 3 天。客户不满意,团队精疲力竭,有人说简单地雇佣更多的人不是一个可扩展的解决方案。
值得庆幸的是,你是一个有能力的数据科学团队的一员,你随时准备提供帮助。现在是做两件事的时候了:
- 设定期望值
- 从简单的方法开始
首先,要积极主动,对任何可能向客户推销你未来解决方案的人设定期望值。不要让它变成“我们正在开发一个先进的人工智能解决方案来自动化客户支持”。您仍然不知道要部署什么,而且考虑到产生影响的迫切需要,您的初始解决方案根本不可能非常先进。在您的团队内部以及客户支持团队中设定相同的期望。你怎么能现在就想出一个简单的第一个版本来帮助他们,而不是 6 个月后?
现在是时候开始了。忘记你最近阅读的深度学习论文,想想你可以获得增量收益的方法。与其构建一个“智能”机器人来响应客户请求,不如对电子邮件进行优先排序和分类,这样团队就可以更有效率?
您与客户支持团队坐下来,发现如果他们知道哪些电子邮件最重要,他们可以将这些邮件分配给高级团队成员,让他们集中精力。此外,如果他们知道其余电子邮件*的一般类别,他们可以将它们批量分配给销售代表,这样他们就可以通过避免在工具和任务之间切换来节省时间。
你可能会问为什么不直接向顾客询问这些名称和类别。首先,你可以但不要期望一致性。其次,许多客户反对通过网络提交请求,而不是发送到电子邮件地址。
所以我们的目标是:
- 将电子邮件分为“关键”和“非关键”
- 将“非关键”桶中的电子邮件进一步分类,以便客户支持团队能够更有效地处理它们。
如果您能确保他们及时处理最关键的问题,并对其余问题进行分类,以便销售代表能够批量处理,您将会让很多人感到满意。更重要的是,这是一个你可以卖给越来越不耐烦的顾客的故事。
Serve your customer, not yourself
开始
您的第一项任务是浏览之前已经解决的电子邮件,并根据问题类型和严重性对其进行标记。大多数客户支持系统要求代表标记这样的属性,但您可能需要做一些清理工作,并与支持团队坐在一起,了解他们如何对这些东西进行分类。众所周知,花在数据准备上的时间在以后会有很大的回报,但这通常很无聊。无论如何都要做。
现在,将数据集分成训练/测试/验证集,并开始使用一些简单的分类器。试试线性回归,随机森林,甚至老朋友朴素贝叶斯。回去获取更多的数据,清理干净,必要时继续调整。注意你所花费的时间。
事情是这样的。你不需要一个完美的解决方案,你只需要让事情变得更好。这个例子的关键是知道在哪个方向上你错了会更好。在将电子邮件标记为“关键”时,你能忍受一些误报吗?当然可以!销售代表会给它贴上这样的标签,你和你的模型下次会变得更好。总比错过一个关键的好。
非关键电子邮件类别也是如此。尽你所能,但是如果负责登录问题的代表偶尔收到关于其他事情的电子邮件,你也可以忍受。让这成为期望设定的一部分。确保他们在收到邮件时正确标记邮件,您将利用这一点来改进您的模型。
部署
既然您已经有了一个足够好的模型(基于构建它的时间和减少支持团队的痛苦之间的权衡),那么就把它拿出来。在这里,您可以进行一些进一步的权衡,这可能会让数据科学宣传机器尖叫起来。在您的笔记本电脑甚至是开发服务器上构建和运行模型是一回事。投产是另一个。
你使用的库对于一个处理邮件的系统来说可能太慢了。你让他们建立和批量处理吗?设计实时运行的模型?如果它崩溃了,你停止了所有的电子邮件支持,会发生什么?
在这个阶段,您有几个选择。
- 简化您的模型,并与一些习惯于生产级软件的工程师合作,以实现批处理作业。请记住,处理过程中的任何延迟都将影响对客户的响应时间。
- (喘息!)利用您从模型中学到的知识,在生产中实施基于规则的实时方法。
- 回过头来改进模型的运行时。
这些都不是完美的,但请记住这种情况。上市时间至关重要,因此第三点已经过时。选项 2 并不总是可行的,但我确实看到过这样的例子,您从分类器中学到了足够多的东西来构建和部署基于规则的作业,并转移到选项 3,同时让支持团队松一口气。
然而,选项 1 非常常见。代价是一个缓慢的模型,不能实时处理电子邮件。您可能不得不每 15 分钟运行一次,这样会消耗您的响应时间。尽管如此,还是不要把它算在内。这个模型并不完美,但是你可以在生产工程师的一点帮助下部署它,然后回到实验室研究 V2。它也比基于规则的选项更容易更新。
当然,您的选择将取决于许多因素,但关键是等待您在会议上自豪地展示的模型很少是最适合业务的。如果你得到了“足够好”的结果,你可以为自己赢得更多的时间来改进模型,但即使这样,也要小心优化是否超过了有价值的增量值。会不会有优雅的模特走到一起的时候?当然,这些是你最想与其他数据科学家谈论的话题。然而,我敢打赌“足够好”的模型是拯救世界的模型。
感谢阅读!你可以联系我或者在我的网站上阅读我的其他博客文章。
好的统计数据是坏的,或者更糟的是误导。
原文:https://towardsdatascience.com/good-statistics-that-are-bad-or-worse-misleading-8e67b816821a?source=collection_archive---------0-----------------------
托尔斯泰有句名言:所有幸福的家庭都是相似的,但不幸的家庭却各不相同。当然,大多数家庭都相当幸福,这可能是真的。因此,一个预测不幸福的看似“好”的算法,如果事实上是真的,可能只是非常可靠地预测一个家庭是否幸福,并报告说不幸福的家庭只是奇怪的,无法准确预测,但这并不重要,因为它们并不多。
这可能看起来很傻,但这是在各种环境中使用统计数据时的一个常见问题。举个(修辞)例子,考虑谷歌翻译。它运行的前提是,翻译算法实际上不需要“理解”语言如何工作的机制,只需要识别模式。为了学习这些模式,它从翻译的文档中吸收大量数据——这些文档必然会包括更大比例的旨在高度可靠和忠实地翻译的文档(例如,来自欧盟或联合国等国际组织的内部文档),并将它“学习”的模式应用于其他情况。这至少有点粗糙,但这始终击败了以前在计算机化翻译算法方面的尝试,因为人类语言整体上对于完全“理性”的翻译方案来说太怪异和不规则了,但奇怪的不规则往往出现得太不频繁,不会对普通文档的熟练翻译造成严重问题。如果你愿意的话,以前的翻译尝试由于过于关注少数不幸福的家庭而使事情变得复杂,而谷歌翻译发现大多数家庭都是幸福的,如果你的工作是为大多数家庭服务,无论幸福还是不幸福,那么最好关注那些既相似又非常多的家庭——只是将不幸福的家庭视为可以被视为(统计)错误的罕见异常。众所周知,尤金·奥涅金是很难翻译的,至少我是这么听说的,但是诗歌在要翻译的文件中只占很小一部分,而且它们提供的许多不规则之处,大概会被归入(总体上很小的)一组错误中。
问题是,在许多情况下,我们对那些为我们提供大量数据的幸福家庭不感兴趣。他们是可预测的,你不需要特别的专业知识就能看出他们快乐,以及是什么让他们快乐。对我们来说,有趣的问题来自相对较少的不快乐的案例,而来自快乐家庭的数据,尽管可能很丰富,却只是污染了这个问题的样本。政治为我们提供了大量这方面的例子:DW-Nominate 引起了轰动,因为它表明绝大多数国会投票可以根据一维预测器进行预测,我认为这已经被贴上了非常误导的标签,即“意识形态”,但这一切都令人震惊吗?国会议员有时可能会投票支持钢铁、糖或玉米,而不是意识形态,但钢铁核心小组的成员不会一直投票支持钢铁——这不是一个经常出现的问题。另外,反正钢铁核心小组的成员也不多。因此,只有相对较小比例的国会议员出人意料地在很小的一部分选票上投票。因为他们都是各自政党的成员,所以他们会在其他时间——也就是绝大多数时间——投票给民主党或共和党。所以这就是托尔斯泰式的幸福家庭,他们可能构成了绝大部分的数据,但对于我们可能感兴趣的问题完全没用——如果我们对这样的问题感兴趣的话。这个问题变得更加复杂,因为尽管 DW-Nominate 算法可能很简单(因为第一维的重要性),但与一个更简单的算法相比,它相当复杂:假设国会成员投票给政党。随着时间的推移,如果你比较简单的“投票党”算法与一维 DW-Nominate 算法的预测准确性,就会出现一个有趣的问题:DW-Nominate 相对于“投票党”算法的(预测)附加值在过去几十年中一直在急剧下降,当时它的倡导者一直在吹嘘它在预测国会投票方面有多好。与“投票党”算法相比,DW-Nominate 的潜在附加值在于,它可以预测,在国会议员不投票党的情况下——这是一个相对罕见的事件——谁将倒戈。按照这种有条件的衡量标准,情况从来就没那么好,而且变得更糟了,尽管部分原因是叛逃并不经常发生。
可能不幸福的人,除了人数少,也没那么有趣,不值得研究?如果样本中没有不快乐的人(也就是说,没有人超越党派界限),也许研究不快乐或检查相关数据是没有意义的。这似乎是我们已经走了一段时间的趋势。但 2016 年选举应该提醒我们,这可能会严重误导我们。像国会议员一样,大多数人投票给政党,但有一小部分人不投。在这样一个选民群体中,党派选民(根据各州的分布情况进行调整)大致势均力敌,只要有百分之几的“不开心”的人就能让一切变得不同。当数据收集和分析工作被鼓励专注于容易产生良好预测能力的“可靠”数据时,这变得越来越严重——换句话说,就是“快乐的人”。不快乐的人从一开始就很少,但他们最终被更精确地欠采样(在技术上正确和不正确的意义上),因为检查他们不会产生太多的回报。当然,试图对“不快乐”的人进行过度采样可能会导致意外情况被过度重视的错误——当 DW-Nominate 首次出现时,它让国会专家如此惊讶的原因是,人们普遍认为国会政治中不成比例的份额是在钢铁、玉米和糖上,而且如此压倒性的投票比例可以简单地通过政党投票来解释(这就是 DW-Nominate 真正所说的一切——它在很大程度上并不是真正的“意识形态”)是出乎意料的。
我认为,分析学的未来在于认识到它在抽样过程中的局限性,其中很大一部分是它在提供大量数据的“简单”问题上做得非常好(当然,这正是 Landon 被期望以压倒性优势击败 FDR 的原因)。这并不是贬低它的潜在贡献:大多数问题都是常规问题,只需要“显而易见”的解决方案。但是“重要的”问题往往不是那么常规的——毕竟,这将是相当重要且相当罕见的投票,因为钢铁党团的人被收买去反对他们的党派关系。这些不寻常的例子什么时候会出现,根据这些例子(假设这是一个该法案的支持者购买钢铁而不是糖的例子——需要能够区分它们)中非常少的数据点将是可用的,你可以获得多少统计杠杆?
谷歌人工智能的新物体探测竞赛
原文:https://towardsdatascience.com/google-ais-new-object-detection-competition-6dde25cf099d?source=collection_archive---------7-----------------------
我为学习者写了一份名为《强大的知识》的时事通讯。每一期都包含链接和最佳内容的关键课程,包括引文、书籍、文章、播客和视频。每一个人都是为了学习如何过上更明智、更快乐、更充实的生活而被挑选出来的。 在这里报名 。
就在几天前,谷歌人工智能在 Kaggle 上发起了一项名为开放图像挑战的物体检测比赛。很高兴看到计算机视觉社区已经有一段时间没有这么大规模的竞争了。
几年来,ImageNet 一直是计算机视觉领域的“黄金标准”竞赛。许多团队每年都在竞争 ImageNet 数据集上的最低错误率。由于深度学习,我们最近看到了图像识别任务的巨大进步,甚至超过了人类水平的准确性。在下面的图表中,我们可以看到像 ImageNet 这样大规模的竞争如何帮助加速该领域的研究,特别是在 2012 年开始的最初几年。
Error rate history on ImageNet (showing best result per team and up to 10 entries per year)
ImageNet 是一个巨大的竞争,有 1000 个不同的类和 120 万个训练图像!庞大的数据规模是 ImageNet 如此具有挑战性的真正原因。我们从如此大规模的竞赛中获得的一个非常重要的东西(当然除了学习如何很好地对图像进行分类)是我们可以用于其他任务的特征提取器。在 ImageNet 上预先训练的特征提取网络用于许多其他计算机视觉任务,包括对象检测、分割和跟踪。此外,网络的一般风格或设计通常用于这些其他任务。例如,快捷连接最初用于 2015 年获奖的 ImageNet 条目,此后一直用于计算机视觉中的绝大多数 CNN!这是一件很棒的事情,当我们可以在一个简单的任务上工作时,它会对更复杂但相关的任务产生巨大的影响。
谷歌人工智能在 Kaggle 上举办的新物体检测比赛是朝着这个积极方向迈出的一步。到目前为止,COCO 检测一直是物体检测的最大挑战。但是,与 ImageNet 相比,它非常小。COCO 只有 80 个类别,330K 图片。它远没有你在现实世界中看到的那么复杂。许多从业者经常发现在野外进行物体检测极具挑战性。至少 ImageNet 有足够大的数据集和足够多的类,这对于预训练和使用网络进行迁移学习非常有用。也许有了足够大的数据集,我们的物体检测器就能同样适用于迁移学习。
这就是新的竞争的由来! Google AI 已经公开发布了开放图像数据集。Open Images 沿袭了 PASCAL VOC、ImageNet 和 COCO 的传统,如今规模空前。
开放图像挑战赛基于开放图像数据集。挑战赛的训练集包含:
- 1.7 米训练图像上 500 个对象类别的 12 米包围盒注释
- 具有多个对象的复杂场景的图像–平均每幅图像 7 个盒子
- 各种各样的图像,包含全新的对象,如“软呢帽”和“雪人”
- 反映打开图像类之间关系的类层次结构
除了对象检测轨迹,比赛还包括视觉关系检测轨迹,以检测特定关系中的对象对,例如“弹吉他的女人”、“桌子上的啤酒”、“车内的狗”、“拿咖啡的男人”等。你可以在这里找到更多关于数据集的信息。这个数据集令人惊叹的地方在于它的多样性。数据集中的所有 600 个类在这里有一个很好的可视化,在这里你可以看到类的分解和层次结构;真的挺多样化的。我们还可以观察到有一个非常宽的类频率范围。这意味着我们不能天真地平等对待所有的职业;我们被迫考虑职业分布,更真实的风格!这个数据集的健壮性无疑让我们更接近于创建对野外部署更有用的模型。
如果你喜欢奖品,还有 30,000 美元的奖金池!此外,挑战的结果将在 2018 年欧洲计算机视觉会议的研讨会上公布。它正在德国慕尼黑举行,这肯定会是一次不错的旅行!
也很高兴看到比赛在 Kaggle 上举行。挑战的核心往往是通过看到竞争对手的许多不同方法而获得的巨大知识来源。如此大规模和复杂的挑战将有望带来最好的研究和新的想法,可以应用于整个计算机视觉领域,就像 ImageNet 所做的那样!
Google 联合实验室—简化数据科学工作流程
原文:https://towardsdatascience.com/google-colaboratory-simplifying-data-science-workflow-c70059386323?source=collection_archive---------1-----------------------
谷歌最近公开了其数据科学和机器学习工作流的内部工具,名为合作实验室。虽然它非常类似于 Jupyter Notebook,但真正的价值来自这项服务目前提供的免费计算能力。协作功能,类似于 Google Docs,允许小团队紧密合作,快速构建小型原型。总的来说,这个工具与谷歌成为“人工智能第一”公司的愿景紧密相连。
Example Notebook (Source)
这个工具对于初学者来说也是非常强大的,因为它附带了 Python 2.7 环境和所有主要的 Python 库。他们不再需要首先经历各种安装过程,而是可以立即开始编写代码。
例如,我使用 OpenCV 创建了一个简短的关于人脸识别的公共合作笔记本,这是以机器学习为核心的计算机视觉的主题之一。为了运行笔记本,建议用户将笔记本复制到他们自己的实验室,从那里他们将能够运行代码。
要开始使用笔记本,运行所有现有的单元以加载库和底层数据是很重要的。然后,您可以在新的代码单元格中执行新版本的findfaces('<---IMAGE_URL--->')
函数,将<---IMAGE_URL--->
替换为网络上任何图像的 URL,例如http://epilepsyu.com/wp-content/uploads/2014/01/happy-people-1050x600.jpg
。这将使用新的 URL 获取图像,并在代码单元格下生成已识别图像的输出。如果照片包含由 OpenCV 算法拾取的人脸,那么将提供这些人脸的总数以及显示图像上识别的人脸位置的方块。
Example Output (Source)
我相信,对于那些刚刚开始编码的人来说,使用 Google 协作工具可以真正改变游戏规则。它允许我们快速开始执行脚本,而不用担心底层架构。上面提到的笔记本就是一个很好的例子,因为它的用户只需要插入一个新的功能。如果他或她对底层代码感兴趣,他们也可以看一看,并按照他们感兴趣的方式进行调整。
因此,最近引入的脚本更改的影响可以被快速识别,从而缩短开发反馈周期。笔记本也非常容易共享,并支持评论,允许从社区的不同成员那里收集反馈。
你还在等什么?试试看这里。
[谷歌]连续可微分指数线性单位与互动代码[手动反推与 TF ]
原文:https://towardsdatascience.com/google-continuously-differentiable-exponential-linear-units-with-interactive-code-manual-back-fcbe7f84e79?source=collection_archive---------10-----------------------
Image from this website
Jonathan T. Barron 是谷歌的一名研究人员,他提出了 CELU(),意为“ ”连续可微的指数线性单位 ”。简言之,这个新的激活函数在任何地方都是可微的。(对于一般的 ELU,当α值不为 1 时,它不是处处可微的。)
由于我最近报道了“ 【通过指数线性单元(ELUs) ”快速准确的深度网络学习”(请单击此处阅读博文),接下来报道这篇文章自然是有意义的。最后,为了好玩,让我们用不同的优化方法来训练我们的网络。
情况 a)用 ADAM 优化器自动微分(【MNIST】数据集)
情况 b)用 ADAM 优化器自动微分(cifar 10数据集)
情况 c)用AMSGrad 优化器膨胀背 Pro p 带AMSGrad 优化器(cifar 10数据集
连续可微的指数线性单位
左图→CELU 方程式()
右图→ELU 方程式()
以上是 CELU()的方程式,我们已经可以看出它与 ELU()的原始方程式并无多大不同。只有一个区别,当 x 小于零时,用α除 x 值。现在让我们看看这个激活函数是怎样的。
左图→CELU()和它的导数绘制时的样子
右图→ELU()和它的导数绘制时的样子
在最右边的图像(ELU()的导数)上,我们可以观察到函数不是连续的,然而对于 CELU()的导数,我们可以观察到函数在任何地方都是连续的。现在让我们看看如何实现 CELU()及其衍生物。
首先让我们看看 CELU()对输入 x 的导数
当用 python ( Tensorflow )实现时,它看起来像上面的东西,请注意我已经将 alpha 值设置为 2。
网络架构
红色矩形 →输入图像(32323)
黑色矩形 →与 CELU 卷积()有/无均值合并
橙色矩形 → Softmax 进行分类
我要使用的网络是七层网络,采用平均池操作。由于我们将使用 MNIST 数据集以及 CIFAR 10 数据集,因此对平均池的数量进行了相应的调整,以适应图像尺寸。
案例 1)结果:用 ADAM 优化器自动微分(MNIST 数据集)
左图 →一段时间内的训练精度/成本
右图 →一段时间内的测试精度/成本
对于 MNIST 数据集,测试图像和训练图像的准确率都达到了 95%以上。我对训练/测试图像的超时成本进行了标准化,以使图形看起来更漂亮。
测试和训练图像的最终准确度都是 98+%。
情况 2)结果:用 ADAM 优化器自动微分(cifar 10数据集)
左图 →一段时间内的训练精度/成本
右图 →一段时间内的测试精度/成本
现在我们可以观察到模型开始遭受过度拟合。特别是使用 Adam optimizer,测试图像的准确率停滞在 74%。
测试图像的最终准确率为 74%,而训练图像的最终准确率为 99%,这表明我们的模型过度拟合。
案例 3)结果:手动回柱带 AMSGrad 优化器(cifar 10数据集)
左图 →一段时间内的训练精度/成本
右图 →一段时间内的测试精度/成本
对于这个实验,AMSGrad 比常规的 Adam 优化器做得更好。尽管测试图像的准确性不能超过 80%,并且模型仍然存在过度拟合的问题,但给出的结果比 Adam 好 4%。
测试图像的最终精度为 78%,表明该模型仍然过拟合,但比使用没有任何正则化技术的常规 Adam 的结果好 4%,还不错。
案例 4)结果: 扩背 Pro p 带 AMSGrad 优化器(cifar 10数据集)
紫色箭头 →反向传播的常规梯度流
黑色弯箭头 →增大梯度流的扩张后支柱
记住这个架构,让我们看看我们的网络在测试图像上的表现。
左图 →一段时间内的训练精度/成本
右图 →一段时间内的测试精度/成本
同样,它比常规的 Adam 优化器做得更好,但是它不能在测试图像上达到 80%的准确率。(仍然)
测试图像的最终准确率为 77%,比 AMSGrad 的常规反向传播低 1%,但比常规 Adam 好 3%。
交互代码
对于 Google Colab,你需要一个 Google 帐户来查看代码,而且你不能在 Google Colab 中运行只读脚本,所以在你的操场上做一个副本。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!同样为了透明,我在训练期间上传了所有的日志。
要访问案例 a 的代码,请点击这里,要访问日志,请点击这里。
访问案例 b 的代码请点击此处,访问日志请点击此处。
访问案例 c 的代码请点击此处,访问日志请点击此处。
要访问案例 d 的代码,请点击此处,要访问日志,请点击此处。
最后的话
有趣的是,根据训练方式的不同,每个网络的表现也各不相同。CELU()似乎比 ELU()的激活函数表现得更好(至少对我来说是这样)。
如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你希望看到我所有写作的列表,请在这里查看我的网站。
与此同时,在我的 twitter 上关注我这里,访问我的网站,或者我的 Youtube 频道了解更多内容。我还实现了广残网,请点击这里查看博文 pos t。
参考
- 乔恩·巴伦。(2018).Jon Barron . info . 2018 年 5 月 8 日检索,来自https://jonbarron.info/
- j . t . Barron(2017 年)。连续可微指数线性单位。arXiv 预印本 arXiv:1704.07483。
- [ICLR 2016]通过指数线性单元(ELUs)进行快速准确的深度网络学习,具有…(2018).走向数据科学。2018 年 5 月 8 日检索,来自https://towards data science . com/iclr-2016-fast-and-accurate-deep-networks-learning-by-index-linear-units-elus-with-c 0 cdbb 71 bb 02
- 克利夫特博士、安特辛纳、t .和霍克雷特博士(2015 年)。通过指数线性单元(ELUs)进行快速准确的深度网络学习。Arxiv.org。检索于 2018 年 5 月 8 日,来自 https://arxiv.org/abs/1511.07289
- 张量流。(2018).张量流。检索于 2018 年 5 月 9 日,来自 https://www.tensorflow.org/
- CIFAR-10 和 CIFAR-100 数据集。(2018).Cs.toronto.edu。检索于 2018 年 5 月 9 日,来自https://www.cs.toronto.edu/~kriz/cifar.html
- MNIST 手写数字数据库,Yann LeCun,Corinna Cortes 和 Chris Burges。(2018).Yann.lecun.com。检索于 2018 年 5 月 9 日,来自http://yann.lecun.com/exdb/mnist/
[ Google DeepMind ] —利用交互式代码进行医学图像分割的深度学习
原文:https://towardsdatascience.com/google-deepmind-deep-learning-for-medical-image-segmentation-with-interactive-code-4634b6fd6a3a?source=collection_archive---------5-----------------------
Gif from this website
Matthew Lai 是 Deep Mind 的研究工程师,也是“ 长颈鹿,利用深度强化学习下棋 的创造者。但是他的硕士 Msc 项目是在 MRI 图像上,也就是“ 医学图像分割的深度学习 ”,所以我想深入看看他的项目。
因为这不是一篇传统的会议论文,而是一个主要项目,我会用不同的方式来处理这个问题。我会做一个论文总结(对我不知道的东西做笔记)和实施。
请注意,在原始论文中,Matthew 使用了 ADNI 老年痴呆症 MRI 数据集,不幸的是,我无法获得这些数据,所以我将使用“ 驱动:用于血管提取的数字视网膜图像 ”数据集。还请注意,由于使用了不同的数据集,以及硬件限制,网络架构与原始论文的差异很小,但是我试图保持总体结构相似。
2.2 网络节点和激活功能
在这里我了解到激活功能必须满足三个标准。(我只认识其中两个。)并且它们是差分的、非线性的和单调的。(我不知道单调。)
微分 →执行反向传播
非线性 →赋予模型计算非线性函数的能力
单调 →防止产生更多的局部最小值
Image from Wiki
左图 →单调递增的函数
中图 →单调递减的函数
右图 →非单调的函数
2.3 训练神经网络
在这里,我了解到 Rprop 反向传播的存在,这种反向传播方法只考虑偏导数的符号,而不考虑大小。如果您想了解更多信息,请点击此处。
3.1 为什么要建立深度网络?
在这里,我了解到我们需要使用深度神经网络的确切原因。我学到了几件事…
- 从理论上讲,用两层模型来模拟任何功能都是可能的,这意味着我们真的不需要一个比两层更深的模型。
- 但是使用深度神经网络的好处其实是节点效率。当我们有一个更小但更深的神经网络时,用更高的精度逼近复杂函数是可能的。
本质上,更小更深的神经网络更有效,因为(每个节点)完成的冗余工作量减少了。
3.2 消失渐变
在这里,我学到了三种解决消失梯度问题的方法。我已经知道了辍学和 ReLU,但我从来不知道 ReLU 激活功能是用来克服消失梯度。我也不知道分层预训练。
3.2.1 方案一:分层预训练
这个想法非常有趣,因为我们将首先以无人监督的方式训练每一层,然后一起使用它。
3.2.2 解决方案 2:整流线性激活单元
虽然 ReLU()激活可能在两个方面存在问题,因为
a.0 处没有导数。
b .正区域内没有边界。
然而,它仍然可以使用,因为它们在进行反向传播时不会降低梯度(导数为 1)。我不知道 ReLU()激活层是用来克服渐变消失问题的。
3.3 辍学
通过丢弃某些节点的值,我们可以使每个节点独立地从另一个节点进化,这使得网络更加健壮。
3.5 使深网变浅
在这里,我学到了一种提高网络性能的方法,这种方法非常有趣。来自论文“ 深网真的需要深吗? “我们可以看到一个深度 NN 被训练来指导一个较浅网络的情况。并且这种引导的浅层网络比用给定数据直接训练的浅层网络表现得更好。
网络架构(描述形式)
红框 →网络架构描述
因为其他两个网络与这个非常相似,所以我们只实现第一个。我从未真正使用全连接网络进行过分段,但我认为这会非常有趣。此外,请注意,由于使用不同的数据集,我将增加一个层,只是为了适应我们的数据。然而,网络的一般结构是相似的。
网络架构(图形形式)
黑色矩形 →输入图像
蓝色矩形 →卷积层
红色矩形 →全连通层(输入图像矢量化)
橙色矩形 →软 max 层
网络本身很简单,现在让我们来看看 OOP 的形式。此外,为了克服消失梯度,让我们使用 ReLU()激活功能,并 tanh()激活在完全连接的层。
注意由于硬件限制,我不得不将两个卷积层的滤波器大小减半,以及批量大小(2)。
红线 →添加图层
整个网络(由于其深度)可以在一个屏幕截图中查看。最后,我们将使用随机梯度下降优化器。
结果
右图 →原图
中图 →二值掩码
地面真相左图 →从网络生成二值掩码
网络给出的结果很差,但是我相信这是由于我使用了不同的数据集。我没有 ADNI 老年痴呆症的核磁共振数据集,但我相信网络的最终输出不是图像的矢量化版本。可能是海马体所在位置的坐标等等…
GIF 格式的结果
显示图像的顺序 → 1。原图→ 2。地面真实二进制掩码→ 3。生成的二进制掩码→ 4。原始图像上的地面真实遮罩叠加→ 5。原始图像上生成的蒙版覆盖。
如上所述,随着训练的继续,我们可以看到所生成的滤波器变得更加清晰,但是所生成的掩模不会从一幅图像改变到另一幅图像,并且在正确分割图像方面表现不佳。
互动代码/透明度
对于 Google Colab,你需要一个 Google 帐户来查看代码,而且你不能在 Google Colab 中运行只读脚本,所以在你的操场上复制一份。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!
要访问 Google Colab 上的代码,请点击这里。
- *注**:我不想在 github 上存放私人医疗数据,因为我可能会违反他们的数据使用政策。所以这段代码不能直接在线运行。
- 为了让这个实验更加透明,我上传了我所有的命令输出到我的 Github,如果你想看,请点击这里。
最后的话
这篇硕士论文在英语和内容方面都写得非常好,我希望在我做硕士论文时能写出类似的内容。
如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有写作的列表,请点击这里查看我的网站。
同时,在我的推特这里关注我,访问我的网站,或者我的 Youtube 频道了解更多内容。如果你感兴趣,我还在这里做了解耦神经网络的比较。
参考
- 赖,男(2015)。长颈鹿:利用深度强化学习下棋。Arxiv.org。检索于 2018 年 4 月 8 日,来自https://arxiv.org/abs/1509.01549
- 赖,男(2015)。用于医学图像分割的深度学习。Arxiv.org。检索于 2018 年 4 月 8 日,来自https://arxiv.org/abs/1505.02000
- 单调函数。(2018).En.wikipedia.org。检索于 2018 年 4 月 8 日,来自https://en.wikipedia.org/wiki/Monotonic_function
- Rprop。(2018).En.wikipedia.org。检索于 2018 年 4 月 8 日,来自https://en.wikipedia.org/wiki/Rprop
- 驱动:用于血管提取的数字视网膜图像。(2018).isi . uu . nl . 2018 年 4 月 8 日检索,来自https://www.isi.uu.nl/Research/Databases/DRIVE/
- ADNI |阿尔茨海默病神经影像倡议。(2018).Adni.loni.usc.edu。检索于 2018 年 4 月 8 日,来自http://adni.loni.usc.edu/
- 导数双曲线。(2018).Math.com。2018 年 4 月 8 日检索,来自http://www.math.com/tables/derivatives/more/hyperbolics.htm
- j . brown lee(2017 年)。深度学习的 Adam 优化算法的温和介绍-机器学习掌握。机器学习精通。检索于 2018 年 4 月 8 日,来自https://machine learning mastery . com/Adam-optimization-algorithm-for-deep-learning/
【谷歌/ ICLR 2017 /论文摘要】反事实的梯度
原文:https://towardsdatascience.com/google-iclr-2017-paper-summary-gradients-of-counterfactuals-6306510935f2?source=collection_archive---------6-----------------------
GIF from this website
Mukund Sundararajan ,是论文“神经元有多重要?”的作者之一(我也做了论文总结这里)。但是今天我想看看他之前的论文“反事实的梯度”。
请注意,这篇帖子是为了我未来的自己复习这篇论文上的材料,而不是从头再看一遍。
Paper from this website
摘要
执行分类时,梯度可用于识别哪些要素对网络很重要。然而,在深度神经网络中,不仅神经元,而且整个网络都可能遭受饱和。且导致给出小梯度值,即使对于非常重要的特征也是如此。
在这项工作中,作者提出了内部梯度,这是反事实输入的梯度。(缩小原始输入)。该方法不仅易于实现,而且能更好地捕捉特征的重要性。
简介
同样,梯度可以用来确定哪些特征是重要的。然而,由于网络内的饱和,重要特征可能具有非常小的梯度。以前有过克服这个问题的工作,但是它们需要开发者做大量的工作。相比之下,内部渐变非常容易实现,只需要最小的变化。(仅输入值)
我们(作者)的手法
作者首先从调查梯度如何用于测量特征重要性开始,他们决定使用 GoogleNet。如上所述,当我们直接可视化与原始图像重叠的归一化梯度时,我们不能准确地说出为什么网络将该图像分类为相机。
凭直觉,我们应该期望镜头区域和相机整体的渐变比左上区域更亮。因此,作者从原始图像中裁剪掉了左边部分,然而,即使这样做了,我们也可以观察到图像中最奇怪的部分梯度最强。
饱和度
从上面的实验中,我们已经知道,由于网络中的饱和,梯度有可能表现出奇怪的行为。为了捕捉网络中饱和度的分布范围,作者提出了反事实输入。并且这些输入可以通过将α值乘以原始图像来获得。
通过大量的实验,作者发现饱和度在谷歌网络中广泛分布。(更具体地说,甚至在中间层以及最终软最大层和预软最大层中。)此外,作者还注意到,当输入值乘以低 alpha 值时,网络中会有更多的活动。(如 0.02)。
最后,众所周知的事实是,梯度的饱和会阻止模型收敛到高质量的最小值,如果发生这种情况,网络的性能会受到严重影响。然而,当网络中仍然存在饱和时,GoogleNet 具有很好的性能测量,因此作者做出了以下假设。
我们的假设是,重要特征的梯度在训练过程的早期没有饱和。梯度仅在特征已经被充分学习之后饱和,即,输入远离决策边界。
内部梯度
在本节中,作者描述了如何创建反事实输入,并指出这样一个事实,即我们可以通过在颜色维度上对它们求和来聚合所有的最终渐变。当我们在每个比例因子α下可视化这些梯度时,我们得到如下结果。
我们可以观察到,随着比例因子的降低,网络将该图像归类为相机的原因变得更有意义。当我们绘制最终梯度的绝对幅度时,我们得到如下图。
这表明随着α值的增加,最终梯度的值由于饱和而减小。
累积内部渐变
在本节中,作者通过将不同 alpha 值的所有梯度值相加来扩展内部梯度。他们用一种非常聪明的方式做到了这一点,他们不是有多个α值,比如说 100,而是取α从 0 到 1 的所有可能值的积分。最后,他们用黎曼和来逼近积分梯度。
左图 →积分梯度的原始方程
右图 →用黎曼和近似积分
这个方法最好的部分就是简单地说,我们只是一遍又一遍地计算梯度。但是使用了缩小版本的输入,所以实现起来非常简单和自然。当我们将得到的积分梯度可视化时,我们会得到如下结果。
评估/调试网络/讨论
总之,在本节中,作者进行了额外的实验来评估积分梯度。(例如像素烧蚀或比较最高有效梯度的边界框)并且当与纯梯度相比时,积分梯度给出了更好的结果。(如果您希望查看更多示例,请点击此处。)
在精度要求较高的环境中,例如医疗诊断,了解网络中的情况非常重要。并且更准确地知道哪些特征贡献给哪些类,积分梯度可以用作获得更多洞察的工具。
最后,作者讨论了这种方法的局限性。
a .无法捕获特征交互 →模型可以执行一些操作,将某些特征组合在一起。重要的分数没有办法代表这些组合。
b .特征相关性→ 如果相似的特征出现多次,模型可以为其中任何一个分配权重。(或者两者都有)。但是这些重量可能不是人类能够理解的。
相关工作
在本节中,作者讨论了不同研究人员提出的其他方法,希望揭开神经网络内部工作的神秘面纱。
基于梯度的方法 →使用纯梯度或内部/整体梯度
基于分数反向传播的方法 → 深度提升、逐层相关传播、反卷积网络、导向反向传播
基于模型近似的方法 → 我为什么要相信你?
应用于其他网络
我不会深入每个实验的细节,但简而言之作者已经进行了两次实验。(一个与药物有关,另一个与语言建模有关。)通过使用积分梯度,他们能够确定哪些特征对模型做出预测起着最重要的作用。让他们更深入地了解模型在做什么。
结论
总之,作者提供了一种新的和简单的方法来衡量特征的重要性。并提供了广泛的实验,表明内部/积分梯度如何优于传统的梯度方法。
遗言
我真的相信这篇论文打开了研究神经网络的大门。总的来说,这是一篇相当长的论文,所以我没有包括很多内容和细节,如果你有时间,我强烈推荐你阅读这篇论文。
如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你希望看到我所有写作的列表,请在这里查看我的网站。
同时,在我的推特这里关注我,并访问我的网站,或我的 Youtube 频道了解更多内容。我也实现了广残网,请点击这里查看博文 pos t。
参考
- Sundararajan,m .,Taly,a .,和 Yan,Q. (2016 年)。反事实的梯度。Arxiv.org。检索于 2018 年 6 月 15 日,来自https://arxiv.org/abs/1611.02639
- Dhamdhere,m . Sundararajan 和 q . Yan(2018 年)。一个神经元有多重要?。Arxiv.org。检索于 2018 年 6 月 15 日,来自https://arxiv.org/abs/1805.12233
- 【NIPS2018/ Google /论文摘要】一个神经元有多重要?。(2018).走向数据科学。检索于 2018 年 6 月 15 日,来自https://towards data science . com/nips 2018-Google-paper-summary-how-importance-is-a-neuron-3d E4 b 085 EB 03
- ankurtaly/集成渐变。(2018).GitHub。检索于 2018 年 6 月 15 日,来自https://github.com/ankurtaly/Integrated-Gradients
- 斯普林根贝格,j .,多索维茨基,a .,布罗克斯,t .,&里德米勒,M. (2014)。追求简单:全卷积网。Arxiv.org。检索于 2018 年 6 月 15 日,来自https://arxiv.org/abs/1412.6806
- m .泽勒和 r .弗格斯(2013 年)。可视化和理解卷积网络。Arxiv.org。检索于 2018 年 6 月 15 日,来自https://arxiv.org/abs/1311.2901
- 宾德,a .,蒙塔冯,g .,巴赫,s .,M:ller,k .,& Samek,W. (2016 年)。具有局部重正化层的神经网络的逐层相关性传播。Arxiv.org。检索于 2018 年 6 月 15 日,来自 https://arxiv.org/abs/1604.00825
- Shrikumar,a .,Greenside,p .,和 Kundaje,A. (2017 年)。通过传播激活差异学习重要特征。Arxiv.org。检索于 2018 年 6 月 15 日,来自 https://arxiv.org/abs/1704.02685
- (2018).Kdd.org。检索于 2018 年 6 月 15 日,来自http://www . KDD . org/KDD 2016/papers/files/RFP 0573-ribeiroa . pdf
Photo by Dollar Gill on Unsplash
[谷歌/ICML/论文摘要]使用大规模无监督学习构建高级特征
原文:https://towardsdatascience.com/google-icml-paper-summary-building-high-level-features-using-large-scale-unsupervised-fa1ae8fb8678?source=collection_archive---------16-----------------------
GIF from this website
我们如何构建更高级的特征检测器?我们能通过无监督学习做到吗?
请注意,这篇帖子是给未来的自己看的,回顾这篇论文上的材料,而不是从头再看一遍。
Paper from this website
摘要
这篇论文的作者感兴趣的是从未标记的数据中制作类特定特征检测器。(例如,从未标记的人脸图像中制作人脸检测器。)为了实现这一点,作者在大数据集上训练了 9 层稀疏自动编码器。与普遍的看法相反,有可能在没有任何标签数据的情况下建立一个人脸检测器,而且在 ImageNet 数据上的表现优于现有技术水平。(2012 年)。
简介
本文的目的是仅从未标记的图像中构建类别特定的特征检测器,这是由神经科学的猜想所激发的,即在人脑中存在高度类别特定的神经元,通常和非正式地称为“祖母神经元”。在传统的计算机视觉中,大多数研究人员使用标记数据来获取这些过滤器,然而获取大量数据可能是困难的。这个实验的成功将提供两件事情,一个是从未标记的数据中学习高级特征的方法,另一个是是否可以从未标记的数据中学习大母神经元的可能性。这些方法中的大多数,例如稀疏自动编码器,仅学习低级特征,例如边缘或斑点。作者假设,深度学习之所以需要这么长时间,是因为缺乏高级特征,例如,图像的大小被调整得更小,这些减少破坏了高级特征的学习。作者没有缩小图像,也使用了大量的计算能力。在所有这些之后,它显示了从未标记的数据中学习更高水平的特征是肯定可能的。最后,使用学习过的过滤器,他们能够在 ImageNet 数据集上超越最先进的性能。(2012 年)。
训练集构造/算法
如上所述,从 1000 万个 YouTube 视频中随机选择了补丁,使用 OpenCV 人脸检测器,他们能够得出结论,在 100,000 个采样的补丁中,人脸不到 3%。并且所使用的算法受到不同类型的无监督学习算法的成功的启发。(RBM、稀疏自动编码器等)。作者的目的是学习更高层次的特征,而不仅仅是低层次的。
如上所述,作者使用的架构可以被认为是深度稀疏自动编码器,有一些扭曲,它们是局部感受域,池化和局部对比度归一化。(他们使用 L2 池)。堆叠一系列统一模块的方式,在选择性和耐受性层之间切换,被认为是大脑采用的架构。需要注意的一个重要事实是,尽管网络使用局部感受野,但它们不是卷积的(参数不在图像的不同位置共享。),这在生物学上更说得通。
学习和优化
在学习期间,第二子层被固定为统一的权重,并且编码器和解码器中的所有其他权重通过上面看到的成本函数来训练。优化问题也称为重构拓扑独立分量分析,基本上第一项确保表示编码了关于数据的重要信息,第二项鼓励汇集要素以将相似的要素组合在一起以实现方差。本文作者实现了异步随机梯度下降,并使用 1000 台机器对网络进行了三天的训练。
人脸实验
测试图像由来自 Wild 数据集和 ImageNet 数据集的标记人脸的 37,000 幅图像组成。训练后,作者使用测试集来测量每个神经元识别人脸的性能。令人惊讶的是,最好的神经元能够以 81.7%的准确率识别人脸。并且在没有局部对比度标准化层的情况下,准确度已经下降到 78.5%。
当他们创建激活值的直方图时,他们能够上图,很明显,即使没有标记数据,也有可能训练人脸检测器。
当作者通过使用两种技术可视化神经元的最佳刺激时。(可视化测试集中最具响应性的刺激,并进行数值优化以找到最佳刺激)。他们能够证实神经元确实在寻找一张脸。并且通过额外的实验,表明学习的权重对于不同的方差是鲁棒的,例如平面外旋转和缩放。
猫和人体探测器
作者还想知道该网络是否能够学习高级功能,如猫和人体。如上所述,网络中的一些神经元能够检测到形状像猫或人体的高级特征。在他们自己的数据集上进行测试,在猫和人体上分别达到了 74.8%和 76.7%。
使用 ImageNet 进行物体识别
在经过训练的权重之上添加一对一对所有逻辑分类器之后,他们重新训练网络,(这种方法也称为无监督预训练。)在 ImageNet 数据集上。他们能够超越最先进的基线(2012 年)。在包含 22K 个类别的 ImageNet 上,它比其他最高的结果取得了 70%的相对改善。所有的性能都可以在上表中看到。
结论
总之,使用大量的数据以及巨大的计算能力,可以仅使用未标记的数据来学习高级特征,如人脸和人体。此外,该方法在 ImageNet 数据集上的表现优于 2012 年的最先进水平。
最后的话
这是一个非常酷的实验,然而所需的数据量太大了(以及计算能力),也许这就是它没有起飞的原因。
如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你希望看到我所有写作的列表,请在这里查看我的网站。
同时,在我的 twitter 这里关注我,并访问我的网站,或我的 Youtube 频道了解更多内容。我也实现了广残网,请点击这里查看博文 pos t。
参考
- Le,q .、Ranzato,m .、Monga,r .、Devin,m .、Chen,k .、和 Corrado,g .等人(2011 年)。使用大规模无监督学习构建高级特征。Arxiv.org。检索于 2018 年 8 月 15 日,来自https://arxiv.org/abs/1112.6209
谷歌知道如何教学
原文:https://towardsdatascience.com/google-knows-how-to-teach-45e531ab3ada?source=collection_archive---------8-----------------------
Google’s Machine Learning Crash Course
足够了!我受够了!”我脑袋里面的声音就是这样在磨了几个小时几天的学习机学习之后对我吼的。虽然我已经习惯了,但这次听起来很严肃。真的很严重!“嗯,好吧。那你想做什么?”我相当礼貌地问道。我刚说完这句话,就得到回应,“抓点数据。运行一些代码。做一些分析。给我看一些图,图表”。从这些话中可以明显看出,我的内在自我并不厌倦机器学习。它受够了过多的学习和研究,却很少尝试和实施。所以我浏览了保存的内核、笔记本、GitHub repos 和博客帖子的列表,做了一些实践,我选择了这个——幽灵作者认证!
在接下来的大约两个小时里,我们忙于解决那个卡格尔问题。事实上,我在我跟随的 Kaggle 中发现了一个非常有用的笔记本( 这里 ) 。我喜欢文字云,在看完这本笔记本后,我开始知道如何制作一个!
The Raven word-cloud, with font size varying according to the frequency of the words
当我看着那些巧妙的文字云感到高兴时,我的手机发出嗡嗡声,要求一些 Twitter 通知。这是我在转发中发现的:
接下来的一秒钟,我上了博客,从那里我进入了速成班( 这里 )。接下来发生了三件事:第一,我注意到视频没有播放。我重新加载,尝试了不同的模块,然后从 Chrome 切换到另一个浏览器,它工作了。问题出在 Chrome 浏览器的广告拦截扩展上。当它被禁用时,视频工作正常。我使用“反馈”按钮让他们了解这个问题。第二,左边的主题列表涵盖了许多重要的 ML 主题,我的注意力开始增长。第三,我内心愤怒的声音又回来了,“减少损失、一般化、逻辑回归、神经网络……再来一句理论,我就要把你大脑里的神经元烧掉,我是认真的”。然而这一次,我做出了不同的回应,“我现在不想听你说!”当两个你爱的东西走到一起(ML 和 Google),你无法阻止自己用双手去抓住它。接下来的几个小时,我忙着看视频,看笔记,跑步练习,完成了速成班的一半。你猜怎么着,粘在上面的不仅仅是我。我的抱怨,叫喊,愤怒的内心声音也加入进来。
谷歌的机器学习速成班现在将在我的机器学习推荐资源列表中。尽管它自称为速成课程,但任何完成包括视频、笔记、练习和游戏任务在内的所有课程内容的人都会意识到,这不仅仅是一门速成课程。它不仅让我更好地了解了许多事情,还帮助我理解了一些我以前不知道的方法和概念。
“Dude, this is what convex means! You heard about it in all those courses and wondered what it is” — my inner voice after it joined me and got glued to this course.
这不是我从谷歌找到的第一个对机器学习真正有帮助的资源。Jason Mayes 机器学习 101 课程有非常生动的幻灯片,很好地解释了 ML 的概念。它有 101 张很好的机器学习内容的幻灯片,有很好的设计和很好的例子。
例子让理解更容易。这正是 Martin Gorner 在他关于深度学习的几个小时会议中所做的。虽然这不像神经网络上的任何 MOOC 那么大,但 Martin 通过分解神经网络并展示其各个部分的功能,很好地解释了神经网络是如何工作的。在几个小时的时间里,你将了解数据是如何输入网络的,权重和偏差是如何添加的,为什么我们需要激活函数,如何通过正则化、剔除和许多其他有用的技术来提高精度。这也有助于我理解 TensforFlow 是如何工作的。
[## 学 TensorFlow 和深度学习,没有博士| Google Cloud 大数据和机器学习…
这个 3 小时的课程为开发人员提供了深度学习基础知识的快速介绍
cloud.google.com](https://cloud.google.com/blog/big-data/2017/01/learn-tensorflow-and-deep-learning-without-a-phd)
除了所有这些资源之外,当我浏览谷歌的一些网站时,还会不时地发现许多其他资源。Google 的Tech Dev Guide和Learn With Google AI都有非常好的资源,无论是学习还是准备面试。在博客文章 机器学习的规则 ,中,作者列出了 43 条规则,每一条都用一个例子解释了它是如何在 Google Play、Google Plus 等谷歌产品中实现或使用的。Google code labs是另一个非常有用的资源,有一系列 Google 产品和技术的简单教程。谷歌的博客页面(像 这个 和 这个 ) 也是找到一些非常有趣的文章和更新的好来源。
通过 MOOCs、Youtube、博客和许多来自大学、学者、研究人员、学生和博客作者的其他途径,可以获得数百门课程,拥有一些来自科技公司的学习资源也很好。谷歌似乎在这方面做得很好。我希望谷歌和其他科技公司为任何愿意学习的人提供更多这样的开放资源。
虽然这里列出的大部分资源都是关于机器学习的,这也是我一直生活的地方,但在过去的一年里,我也遇到了许多其他技术和产品的资源。探索谷歌开发人员和其他谷歌网站将会带来宝贵的学习和实践资源。
你觉得这篇文章有用吗?欢迎留下任何反馈/意见。感谢阅读!!
连接: 领英推特 和我的 博客 。
谷歌无所不知——第一部分——Chrome 浏览模式
原文:https://towardsdatascience.com/google-knows-it-all-part-1-chrome-browsing-patterns-979d0f1c7ebd?source=collection_archive---------6-----------------------
剑桥分析公司和脸书事件引起了关于数据隐私和安全的轩然大波。虽然只有脸书在社交媒体上成为攻击目标,但你的数据正被互联网上每一个你与之互动的实体所收集。而且通常收集是为了让你的体验更好。当你真的很饿的时候,谁不喜欢一个应用程序上的食物推荐。它让你变得懒惰,但也节省了你的时间。
我请求谷歌给我发送我的数据,为此他们花了大约一个日。我对数据的粒度感到震惊。从我一年前访问的 URL(在 leaf 处),到我每次给任何应用程序我的位置许可时我的位置数据(关于我的高度、速度、方向、垂直精度等等的数据),它都有。基本上,他们已经把我在谷歌应用程序中搜索过的所有东西都储存起来了。
我想用我的浏览数据,看看我是否能从中获得一些有用的东西。我用的是 python 3.6,所有的计算都是在熊猫 3.6 中完成的。 Json、datetime、tldextract 和 regex 是我导入来清理数据的主要包。我特别崇拜《海底世界》中的调色板,并把它用在我的想象中。
简要地;我提取了 json 文件,清理了它,从 URL 数据中提取了域、子域、安全等,并将不同的域分为这 7 类;
一、学习——从 coursera 到 stack overflow 到 piazza 的一切
二。娱乐 —网飞,脸书,…
三。沟通 — Whatsapp,Messenger,GroupMe,Gmail,…
四。找工作——是的,我必须把它写进去,因为我开始在这上面花了很多时间
动词 (verb 的缩写)常规——从普通的谷歌搜索到预订机票到点餐,无所不包
不及物动词新闻——自从我加入科技公司后,就没怎么看了。
七。未分类的——所有其他的东西
上述分类是基于提取的域名完成的。
背景 : 我有 2017 年 3 月到 2018 年 2 月的数据。2017 年 6 月,我辞去了分析顾问的工作,并于 2018 年 8 月加入佐治亚理工学院。这可能有助于下面图表的上下文
自从加入 Tech,我发现我的互联网使用量明显增加。
被访问的安全网页的数量有所增加,而对不安全网页的访问基本保持不变。12 月份也可以看到下降。(寒假!)
下面的热图可以告诉你我是什么时候开始在 Tech 读硕士的。从 2017 年 8 月开始,学习网站突然增加,12 月略有下降。‘求职’2018 年一二月也变得更黑了。‘娱乐’秋季学期最后两个月也降了,所以我知道 2018 年三四月该期待什么了!
深入挖掘一周水平的分析,我总是在一周开始时学习,但随着时间的推移它会下降。真的可以在这里责怪自己。另一方面,随着时间的推移,“娱乐”会略有增加。随着时间的推移,“求职”再次下降。也许是周日晚上的负罪感引发了周一学习和求职的突然增加。****
注意:在我加入 GeorgiaTech 后,我将下图的数据限制为日期。
深入研究一个小时的分析,你会发现大部分的学习在上午 9 点左右开始,也就是课程开始的时候,在下午 3-4 点左右达到高峰。娱乐活动也在那段时间达到高峰,这要归功于欧洲足球比赛。你可以从凌晨 2 点到 8 点的干燥区域推断出我的睡眠模式。
另一个有趣的分析是在日时 T21 水平上进行的。在周日(第六天)下午 4-6 点左右有一个特殊的下降。这是由于日常杂货店访问目标/Publix。不出所料,星期五(第 4 天)比其他时间早结束,星期六比其他时间晚开始。
这最后的视觉化就是看看我在这些独立的类别中工作时有多有效。
很明显,在找工作的时候,我的沟通能力下降了。求职和娱乐的相关性也很低(或不太高),这很好。学习和娱乐不太相关,当娱乐节目开始时,交流增加。
同样的代码可以在这里找到:https://github . com/jehlokhande 93/BrowsingHistoryVisualization
**** [## Jeh Lokhande -数据科学家实习生- Cox Communications | LinkedIn
查看全球最大的职业社区 LinkedIn 上 Jeh Lokhande 的个人资料。Jeh 列出了 6 项工作…
www.linkedin.com](https://www.linkedin.com/in/jehlokhande/)****
使用迁移学习的 Google 地标识别
原文:https://towardsdatascience.com/google-landmark-recognition-using-transfer-learning-dde35cc760e1?source=collection_archive---------8-----------------------
Picture by Kevin Widholm
我法师分类用 15k 职业!
项目由凯瑟琳·麦克纳布、阿努拉格·莫希勒、 阿瓦尼·夏尔马 、埃文·大卫、阿尼莎·加尔格
D 处理大量的类,而在许多类中只有很少的图像,这使得这项任务非常具有挑战性!
问题来自一个著名的 Kaggle 比赛,谷歌地标识别挑战赛。训练集包含超过 120 万张图像,分布在 14,951 类地标、中,每类图像从一张到数千张不等。随着深度学习的发展,这种极端分类的问题在今天的数据科学社区中非常普遍。关于这个数据集需要注意的一件重要事情是,给定的测试集包括许多根本不是地标的图像,我们称之为“垃圾”图像。
这种数据集的巨大学习潜力促使我们的团队将其作为高级预测建模的课程项目。这篇博客将详细介绍我们在谷歌地标识别挑战中的尝试。我们将讨论所使用的平台、我们解决问题的方法、数据处理、尝试过的模型、我们的结果以及我们在此过程中面临的一些挑战。
按照此 github repo 获取代码。
方法概述
首先,我们首先在本地系统上处理 100 个类的数据样本,以设置整个过程。
这次试运行的一个教训是,使用较小分辨率的图像,模型训练的速度提高了 6 倍。
不同分辨率图像的下载时间大致相同(主要时间花在打开 url 链接上)。出于时间的考虑,我们决定在我们的项目中使用分辨率为 96x96 的图像,而不是全分辨率。最终的结果产生于 2000 个具有调整图像大小的类的数据样本。
接下来,我们需要选择一个平台,在一个巨大的数据集上运行如此密集的代码。一般选项有亚马逊网络服务(AWS)、谷歌云平台(GCP)或任何其他大数据处理平台。我们选择使用 GCP,因为帐户启动时有 300 美元的免费信贷。这个博客是一个很好的资源,可以一步一步的指导你在 GCP 创建图像识别的虚拟实例,特别是 CNN。我们最终使用了 1 个 GPU——NVIDIA Tesla K80,8 个 CPU,50GB RAM 和 500 GB 磁盘空间。
为了图像分类的目的,我们需要从一般的数据预处理开始,然后才能从 Keras 实现 CNN。我们需要在训练集和验证集中对图像进行分类标记,因此我们建立了相应的数据集。
在数据预处理之后,我们的方法包括对数据使用 VGG16 预训练模型以及 DeLF 来处理困难的测试图像。DELF 匹配图像中的局部特征,我们将在后半部分详细讨论这一点。最后,我们使用来自训练数据的样本测试集来检索准确度分数,并且我们的模型能够达到高达 83%的准确度(鼓掌!/喘息声!) .
I .获取图像数据
数据以 CSV 的形式出现,带有图像 URL 和地标 id。我们的 2000 个类样本包含从“1000”到“2999”的类标签(地标 id)。本项目的数据预处理大致分为以下几个步骤:
a)Train-validation-holdout data:由于 test 文件夹中的文件大部分是垃圾文件,不包含任何地标,我们不得不从 training.csv 创建自己的 holdout set 来测试我们的最终模型。我们从每个类中抽取 1%的图像来制作维持数据集。接下来是对剩余 99%数据的训练验证分割。来自每个类别的 20%的图像被标记为验证集,剩余的 80%用于训练。在这一步的最后,这就是数据分布
测试集有 1183 行。验证数据有 31,651 行,训练数据有 130,551 行。
b)获取图像文件:准备好图像 URL 和唯一 id 后,下一步是将图像下载到适当的文件夹中。创建了三个单独的文件夹,每个文件夹对应一个训练集、验证集和维持集。调整大小后的图像(96x96)被下载到各自的文件夹(在 GCP)中,大约花了 9 个小时才完成。
c)制作目录结构:训练和验证数据必须采用特定的目录格式,这样我们才能使用 Keras 功能。我们将数据转换成这种结构,其中每个类都是 Train/Validation 文件夹中的一个子文件夹。该子文件夹包含属于该类别的所有图像文件。
二。数据预处理
数据清理
某些 URL 链接已断开,下载的文件已损坏。在将文件移动到特定目录之前,使用文件大小大于 1000 字节的过滤器删除了所有此类文件。接下来,我们发现一些类在验证文件夹中丢失了。这是因为 80-20 的比例。所有具有 4 个或更少图像的类对验证集没有任何贡献(因为 4 的 20%小于 1)。验证数据中缺少文件夹导致模型训练出现问题。创建空白文件夹就是为了解决这个问题。
图像增强
我们的数据中的图像是在不同的角度、水平位移、变焦等情况下拍摄的。预计在测试数据中也会发现类似的变化。为了说明这些变化,我们对高度和宽度偏移、缩放、亮度、旋转和剪切进行了非零值的图像增强。我们没有将增强图像存储在我们的系统中,而是将它们直接用作模型的输入。通过目测图像来选择要使用的参数类型,并根据模型训练获得的精度来确定这些参数的具体值。
三。模特培训
在 Keras 库中可以找到不同的 CNN 架构,例如 VGG16、VGG19、Inception 等。虽然 VGG19 和 Inception 是更重的架构(需要训练的参数数量),但在我们拥有的时间范围内,训练 VGG16 是可行的。
An image classified as triumphal_arch using ImageNet
从简单开始,我们使用在 Google ImageNet 数据集上预先训练的 VGG16 来预测地标。我们观察到 ImageNet 权重能够成功地从我们的图像中捕获一般特征。这使得 VGG16(带有 ImageNet 权重)成为我们在迁移学习过程中的首选模型。
我们的方法是使用 VGG16 的瓶颈层作为特征提取器,并训练顶部 3 层使用更具体的特征对地标进行分类。在阅读了一些关于迁移学习的最佳实践的博客之后,我们加入了一个额外的步骤,在对整个网络进行训练之前,初始化前三层的权重。
所以我们最后的过程看起来像这样:
- 在 VGG16 的瓶颈层上使用 ImageNet 权重将图像(96x96)转换为矢量。
- 初始化最上面三层的权重。为此,训练了仅具有三个密集层(2 个 ReLU 激活,1 个 softmax)的模型。输入是上一步获得的图像向量。这样得到的重量被保存起来以备后用。
- 现在,整个 VGG16 模型已经编译完成——上一步中的前三个初始化层被添加到 VGG16 底层之上。我们选择只冻结底部的 16 层,而不是 19 层,这样网络可以更好地学习 ImageNet 图像之外的图像。这给了我们一个很好的准确性跳跃。
Step 1: Yellow, Step 2: Blue, Step 3: Red
我们探索的编译模型中的可变性是——要训练的层数、优化器的类型、所选优化器的超参数、图像增强的参数、批量大小和时期数。这些细节将在下面讨论。损失函数被固定为“分类交叉熵”。
IIIa。要训练的层数
我们只采用 VGG16 架构直到最后一个卷积层,并在顶部添加全连接层作为顺序层。这很重要,因为从 VGG16 中选择完全连接的层迫使我们对模型使用固定的输入大小(224 X 224,原始的 ImageNet 格式)。通过只保留卷积模块,我们的模型可以适应任意的输入大小。在我们的例子中,它是 96 X 96(图像高度 X 图像宽度)
借助新编译的 VGG16 架构,我们在对数据进行训练的同时,改变了冻结权重的层数。在中间运行中,我们还试验了添加的脱落层来测试我们模型的结果。对于验证和训练数据集来说,精度会随着丢失层而下降,因此被移除。
仅使用三个密集层(2 个 ReLU 激活,1 个 softmax)和冻结在底部 16 层的来自 ImageNet 的权重,就可以实现最佳精度。
IIIb。优化者
我们使用了各种优化工具,包括 momentum SGD、Adam 和 Adagrad。超参数首先以标准范围给出,然后朝着提高精度的方向变化。没有一个特定的学习率对所有优化者都有效。我们观察到,训练时间随着数据量的增加而线性增长,同样的学习速度也适用于更大的数据。我们调整的超参数是这些优化器的学习速率、动量和衰减。在用一些自适应学习率梯度下降算法进行试验后,我们观察到 Adam 对我们的问题是最好的。本文对超参数调优过程有很大帮助。
IIIc。图像增强
在观察了每个参数对图像的影响后,我们观察了每个参数对模型结果的累积影响。这些范围证实了我们目测照片的观察结果,这些照片有时是参观纪念碑的人拍摄的自拍照,例如 15-30°的角度会产生良好的精确度。
IIId。批量
有两个批量大小的实例要使用。
一个是在将图像转换为特征向量(使用 VGG16 瓶颈层)时应用图像增强,其中图像是成批拍摄的。这意味着训练和验证图像的数量应该是该批量大小的倍数。我们的最终模型的批量为 240。
其次是在模特培训期间。增加批量大小是增加训练时间和增加模型准确性之间的折衷。批量大小为 1 将基本上进行随机梯度下降,一次进行一次观察。对于如此庞大的数据集,在决定批量大小时,必须牢记我们系统的内存限制。我们能够以合理的准确度和运行时间达到 240 的批量。
IIIe。时代数
一旦上述超参数的特定设置达到了良好的精度水平,我们就将时期从 15 增加到 24 或 30,这将产生更好的模型结果。在 GCP 上使用单个 Nvidia Tesla K80 GPU 和 8 个 CPU(批量大小为 240)时,每个历元大约需要 15 分钟,因此历元的增量是选择性的。
最终模型
我们用 VGG16 架构训练的模型在验证集上可以给我们 78.60%的准确度,在转移到其他模型如 Inception 和 Resnet 之前,我们竭尽全力提高准确度,查看不同参数的影响。对于我们的最终模型,在 30 个历元之后,精度饱和到接近的值范围。最终模型的参数如下所示:
现在模型已经训练好了,我们得到了 78.6%的验证准确率,接下来呢??让我们继续对测试图像进行预测。但是…
测试数据主要由不相关的图像组成,这些图像甚至不是地标
这是一个问题,因为深度神经网络很容易被欺骗,也就是说,即使是不相关的图像,也会被有把握地归类为一类。那么,我们如何判断神经网络的预测是否正确呢?
四。深度局部特征
为了解决这个问题,我们利用一种称为 DeLF 的局部特征描述符进行大规模图像检索。它从图像中提取局部特征并进行匹配。我们使用它将测试图像的局部特征与已知的地标图像进行匹配。
DeLF 是 Google 最近开发的,详细内容可以在这篇论文中找到。
DeLF Pipeline
DeLF 架构是这样的,它选择具有最高分数的特征,然后查询图像通过,并且在经过几何验证之后,其特征与数据库图像的特征相匹配。特征的匹配是通过 Ransac(随机样本一致性)完成的,并且内联体的数量被用于做出决定。
内联体数量的这个阈值(进行‘标志’—‘无标志’分类)由我们决定,并且可以根据图像的分辨率直观地改变。分辨率越高,可用于匹配的局部特征的数量越多。然后通过 DELF 发送从深度网络获得的预测,并将测试图像与来自预测类的数据库图像进行比较。
有 3 种可能的匹配情况:
第一种情况具有最多的内联体,第二种情况具有较少的内联体,并且在没有界标的情况下,没有到只有几个内联体(同样,实际数量取决于我们决定处理的图像的分辨率)。
因此,设置适当的阈值,我们能够决定测试图像实际上是否是地标。
动词 (verb 的缩写)结果
Test set is the holdout set that was kept aside in the beginning
为了更好地理解模型行为,我们检查了一些错误分类的图像,并收集了一些有趣的观察结果。几个错误分类的测试图像看起来相似,并被合理地分类到错误的类别。
Images that confused our model
不及物动词结论
摘要
我们试图训练 CNN 在谷歌地标识别挑战中获得良好的准确性。为此,谷歌云平台被用来使用具有所需功能的机器。首先,训练图像数据集被分成训练、验证和测试图像,并且图像在下载之前被调整大小以使挑战更易处理。对于模型训练,VGG 16 神经网络与来自 ImageNet 的迁移学习一起使用。我们尝试了#层、优化器、超参数、图像增强、批量大小和#时期的变化,以提高验证准确性。最后,我们使用 DeLF 来处理主要由不相关图像组成的实际测试数据集。
后续步骤
对于这个项目,由于时间短和可用的计算机资源,我们面临许多限制。明确的下一步将是尝试更重的模型,如 Inception Net(它一直在我们配置的系统中抛出 OOM 错误),增加批量大小,并在更大的样本(或整个数据集)上工作。我们还尝试将图像分辨率增加到 224x224,但这将一个时期的训练时间增加到 90 分钟。如果有更多的时间,我们肯定会探索图像分辨率对准确性的影响。
改进或发展我们当前工作的其他可能步骤包括:
- 为测试图像创建 DeLF 和 CNN 的管道,以确保只有有效的界标被馈送到 CNN 进行分类。
- 一旦更多的 CNN 像 Inception Net 和 ResNet 被训练,尝试这些模型的集合。
七。从过程中学习
回顾过去,我们的团队从整个过程中学到了很多东西。在这里,我们记下几个关键的要点,我们希望在开始项目之前就知道。
- 利用预先构建的磁盘映像进行映像识别。试图通过安装所有依赖项来配置自己的系统是一场噩梦!
- 检查tensor flow 是否确实在使用 GPU 加速,然后等待几个小时等待您的纪元运行。
- 总是在较小的数据集上对整个过程进行试运行(从最开始到结束)。
非常感谢我们的教授 Joydeep Ghosh 博士,他在这个旅程中给了我们很大的帮助。如果您有任何意见或建议,请告诉我们。希望这个博客能帮助你设计你自己的图像分类项目!
谷歌新闻和列夫·托尔斯泰:使用 t-SNE 可视化 Word2Vec 单词嵌入
原文:https://towardsdatascience.com/google-news-and-leo-tolstoy-visualizing-word2vec-word-embeddings-with-t-sne-11558d8bd4d?source=collection_archive---------0-----------------------
每个人都以独特的方式感知文本,不管这个人是在网上看新闻,还是看世界知名的经典小说。这也适用于各种算法和机器学习技术,它们以更数学的方式理解文本,即使用高维向量空间。
本文致力于使用 t-SNE 可视化高维 Word2Vec 单词嵌入。可视化有助于理解 Word2Vec 如何工作,以及如何在神经网络或其他机器学习算法中使用它们之前解释从文本中捕获的向量之间的关系。作为训练数据,我们将使用来自谷歌新闻的文章和俄罗斯作家列夫·托尔斯泰的经典文学作品,托尔斯泰被认为是有史以来最伟大的作家之一。
我们通过 t-SNE 算法的简要概述,然后使用 Word2Vec 进行单词嵌入计算,最后,在 2D 和 3D 空间中使用 t-SNE 进行单词向量可视化。我们将使用 Jupyter Notebook 用 Python 编写我们的脚本。
t 分布随机邻居嵌入
T-SNE 是一种用于数据可视化的机器学习算法,它基于非线性降维技术。t-SNE 的基本思想是在保持点之间相对成对距离的情况下降低维度空间。换句话说,该算法将多维数据映射到两个或更多维,其中最初彼此远离的点也位于远处,并且靠近的点也转换成靠近的点。可以说,t-SNE 正在寻找一种新的数据表示方法,在这种方法中,相邻关系被保留。t-SNE 整个逻辑的详细描述可以在原始文章[1]中找到。
Word2Vec 模型
首先,我们应该获得单词的矢量表示。为此,我选择了 Word2vec [2],这是一个计算效率高的预测模型,用于从原始文本数据中学习多维单词嵌入。Word2Vec 的关键概念是定位在训练语料库中共享共同上下文的单词,这些单词在向量空间中与其他单词相比非常接近。
作为可视化的输入数据,我们将使用来自谷歌新闻的文章和列夫·托尔斯泰的几部小说。在谷歌新闻数据集(大约 1000 亿字)的一部分上训练的预训练向量是由谷歌在官方页面发布的,所以我们将使用它。
除了预训练的模型,我们将使用 Gensim [3]库在托尔斯泰的小说上训练另一个模型。Word2Vec 将句子作为输入数据,产生单词向量作为输出。首先,需要下载预先训练的 Punkt 句子标记器,它将一个文本分成一系列句子,考虑缩写词,搭配和词,这些词可能指示句子的开始或结束。默认情况下,NLTK 数据包不包括预先训练的俄语 Punkt 分词器,所以我们将来自https://github.com/mhq/train_punkt的第三方模型。
在 Word2Vec 训练阶段,使用了以下超参数:
- 特征向量的维数是 200。
- 句子中被分析单词之间的最大距离是 5。
- 忽略每个语料库中总频率低于 5 的所有单词。
使用 t-SNE 可视化单词嵌入
在需要可视化位于多维空间中的对象之间的相似性的情况下,T-SNE 非常有用。对于大型数据集,制作易读的 t-SNE 图变得越来越困难,因此常见的做法是可视化最相似单词的组。
让我们从预先训练的 Google 新闻模型的词汇表中选择几个词,并准备词向量用于可视化。
The effect of various perplexity values on the shape of words clusters
接下来,我们进入本文最吸引人的部分,SNE 霸王龙的构型。在这一节中,我们应该注意下面的超参数。
- 部件的数量,即输出空间的尺寸。
- 困惑值,其在 t-SNE 的上下文中可以被视为有效邻居数量的平滑测量。它与许多其他流形学习者中使用的最近邻的数量有关(见上图)。根据[1],建议在 5 到 50 之间选择一个值。
- 嵌入的初始初始化类型。
值得一提的是,t-SNE 有一个非凸的目标函数,使用随机初始化的梯度下降优化将其最小化,因此不同的运行会产生略有不同的结果。
下面是使用 Matplotlib 创建 2D 散点图的脚本,Matplotlib 是 Python 中最流行的数据可视化库之一。
Clusters of similar words from Google News (preplexity=15)
在某些情况下,为了看到全貌,一次绘制所有单词向量可能是有用的。现在让我们来分析《安娜·卡列尼娜》,这是一部充满激情、阴谋、悲剧和救赎的史诗小说。
Visualization of the Word2Vec model trained on Anna Karenina
如果我们在 3D 空间中映射初始嵌入,则整个画面可以提供更多信息。这一次让我们来看看《战争与和平》,它是世界文学的核心小说之一,也是托尔斯泰最伟大的文学成就之一。
Visualization of the Word2Vec model trained on War and Peace
结果呢
这是从 Word2Vec 和 t-SNE 的角度看文本的样子。我们为谷歌新闻中的相似词汇绘制了一个信息量很大的图表,并为托尔斯泰的小说绘制了两个图表。还有一件事,GIFs!gif 很牛逼,但是绘制 gif 和绘制常规图形几乎是一样的。所以,我决定不在文章中提及它们,但是您可以在源代码中找到生成动画的代码。
Github 提供了源代码。
[## sismetanin/word2vec-tsne
谷歌新闻和列夫托尔斯泰:使用 t-SNE 可视化 Word2Vec 单词嵌入。
github.com](https://github.com/sismetanin/word2vec-tsne)
参考
- 长度 Maate 和 G. Hinton,“使用 t-SNE 可视化数据”,《机器学习研究杂志》,第 9 卷,第 2579-2605 页,2008 年。
- T.Mikolov,I. Sutskever,K. Chen,G. Corrado 和 J. Dean,“单词和短语的分布式表示及其组合性”,神经信息处理系统进展,第 3111–3119 页,2013 年。
- R.Rehurek 和 P. Sojka,“大型语料库主题建模的软件框架”,LREC 2010 年自然语言处理框架新挑战研讨会论文集,2010 年。
谷歌对象检测 API 检测品牌标志第 1 部分
原文:https://towardsdatascience.com/google-object-detection-api-to-detect-brand-logos-fd9e113725d8?source=collection_archive---------3-----------------------
Brand Logos Object Detection
Google 已经分享了它的 Object Detecion API 和非常好的文档来帮助我们在自己的数据集上训练一个新的模型。文档可在使用云机器学习引擎训练对象检测器获得。指南解释得很清楚,只要按照步骤做一些改动就可以了。我试图训练检测品牌标志的模型,并发现结果适合这篇博文。
数据集
我使用的是 Flick-27 logo 数据集,它是公开可用的,有从 Flickr 下载的 27 个品牌的图片。它为每个类有 30 张图片。总共 810 幅图像用于训练。虽然它对于深度学习问题来说是一个非常小的数据集,但是使用数据扩充技术,它可以膨胀到适合于训练对象检测模型的更大的数据集。
一个大的数据集 flickr-32 也有更多的例子。对于训练数据集的 32 个类别中的每一个,它具有 70 个图像,而对于测试和验证数据集,它对于每个类别具有 10 个图像。它还有 6000 张没有标识的图片。但是它没有注释(图像中徽标周围的边框)。这就是为什么它更适合于标识(对象)识别而不是标识(对象)检测。
数据增强
因为 flick-27 是一个非常小的数据集,只有 810 张图像,所以数据扩充是训练前非常重要的一部分。为了增加数据,我从给定的图像中裁剪出每一个标志,并进行一些变换,如水平翻转、垂直翻转、添加噪声、旋转、模糊等。然后将每个转换后的图像粘贴到一些随机位置上没有徽标的图像上,并记录位置坐标,这些坐标将作为以后训练的注释。在这之后,我从仅仅 810 张图片中得到了大约 15000 个例子。我使用视觉对象类挑战 2012 数据集作为无徽标数据集。
Augmented data
迁移学习
迁移学习是深度学习的一个重要概念。在迁移学习中,我们通过将输入作为自己的数据集来重新训练已经训练好的模型。这样我们可以减少训练所需的数据量和训练时间。训练利用来自已经训练的模型的权重,并开始学习新的权重来学习分类新的数据。这是一种非常有效的技术。
我使用了在牛津 Pet 数据集上训练的 SSD Mobilenet 模型作为基础模型,而在同一牛津 Pet 数据集上训练的更快的 RCNN 被用于使用例如云机器学习引擎训练对象检测器。与 RCNN 或更快的 RCNN 等更大的模型相比,使用 SSD mobilenet 作为模型更小、更快。模型训练的大小只有 22MB。
更多经过训练的迁移学习模型可以在检测模型动物园找到。
培养
由于训练步骤已经在原帖使用云机器学习引擎训练物体检测器中做了很好的解释,我就不在这里解释了。然而,更多的帖子会有所帮助
如何用 TensorFlow 的物体检测器 API 训练自己的物体检测器
用 Tensorflow 和 OpenCV 构建实时物体识别 App
结论
我尝试使用 Flickr-27 数据集为品牌标志检测的对象检测进行训练,我发现了一些好的结果和大量的学习。
我观察到,它在高清晰度图像上工作得非常好,而在图像中的较小对象上不太准确。这是 SSD mobilenet 模型的一个折衷。但 SSD mobilenet 可以与高清摄像头一起实时使用,以获得更高的准确性,与 GPU 一起使用,以实现更快的实时检测。
下一个
我计划将来用更多的图片在 Flickr-47 数据集上训练它,以获得更好的准确性。
用高清摄像头和 GPU 在实时视频流上测试它。
尝试 SSD Inception 模型,而不是 Mobilenet,以便在较小的对象上获得更好的准确性。
第二部分:https://medium . com/forward-data-science/Google-object-detection-API-to-detect-brand-logos-Part-2-384055 e4e 109
检测品牌标志的 Google 对象检测 API 第 2 部分
原文:https://towardsdatascience.com/google-object-detection-api-to-detect-brand-logos-part-2-384055e4e109?source=collection_archive---------3-----------------------
我对 Logo 检测的痴迷从第一部就开始了。所以这次我尝试用一个更大的数据集和一些其他模型来使用迁移学习进行训练。结果优于第一部分。我能够检测尺寸较小的徽标,并且通过对检测代码进行一些更改,我也能够提高检测速度。
新数据集— Flickr Belga 徽标
在我之前的尝试中,我使用了更小的 flickr-27 徽标数据集——只有 27 个徽标类别的 810 幅训练图像。因此,面临的挑战是找到一个更好的数据集,用更多数量的图像进行训练。很难找到带有可用于对象的注释的图像数据集。
幸运的是,我偶然发现了 flickrBelgaLogos 数据集,它是 Belga 徽标数据集的扩展。Belga 徽标数据集包含 37 个徽标类别的 10k 幅图像。然而,在评估后,只有 2695 个被认为适合检测。flickrBelgaLogos 创建了一个新的合成数据集,方法是将 Belga 徽标中裁剪的徽标剪切并粘贴到从 Flickr 抓取的图像数据集中。
每个徽标类别的徽标分布可以从他们的网站上看到。我删除了一些图像样本数量较少的徽标类别。最后,我为总共 2406 张图片的 20 个标志类别创建了一个数据集。(我还复制了 flickr-27 数据集中的图片,以增加样本量)。
虽然这不是一个庞大的数据集,但显然比我之前的数据集有所改进。而且性能提高了许多倍。
训练不同的模型
有了数据集和注释之后,很容易得到注释 XML。然而,有一些重要的观点
1-总是以类别名称开头,后跟下划线“_”。此外,XML 的命名应该与图像名称相同。
2-label _ map . Pb txt 文件中的类别名称应以 1 开头,而不是 0。否则,将跳过类别 0 进行培训。
3-同样在训练时,如果你得到一个错误,很可能你的注释文件不正确,注释文件中的对象位置超出了图像边界。
创建”后。记录“来自图像数据集的文件我使用转移学习训练了 3 个模型— Faster_Rcnn_restnet101、SSD Inception V2 和 SSD Mobilenet 。我的意图是获得更快和更好的检测。这些是我在上述模型上训练和测试时的一些观察结果
1-更快的 RCNN 在检测中是最好的,而在检测中稍慢。然而,它们并不太慢。我设法实现了每秒 3.6 帧的视频检测,而没有并行性。我用的是 GeForce GTX 1060 6GB 机。
2- SSD Inception 和 Mobilenet 的检测速度非常快,但检测精度非常低。也许它们可以在大量训练数据集上表现得更好,但更快的 RCNN 仍然是我检测的选择。
3-我对上述模型进行了大约 100,000 次迭代的训练。但是更多的迭代使得模型更容易检测到假阳性。我不知道原因,但这是我观察到的。使用在更快的 RCNN restnet 上训练的. 99 阈值检测 obove 视频,迭代 110k】。
检测更小的物体
检测更小的物体是我从一开始就关心的问题,为了实现这一点,我尝试使用图像中更小的物体来训练模型。这在直觉上看起来是正确的,而我通过长时间训练模型实现了较小物体的检测。但是模型能探测到多小的物体是有限制的。
标注的较小对象上的训练模型可能会增加假阳性检测,而非常小的对象上的训练甚至可能不训练。
检测速度
由于 Priya Dwivedi 发布了“https://medium . com/forward-data-science/is-Google-tensor flow-object-detection-API-the-easy-way-to-implementing-image-recognition-A8 BD 1 f 500 ea 0”,我能够轻松地对视频进行检测,因为 OpenCV for Videos 非常令人头痛,而 moviepy 则容易得多。
对于一个 30 秒的剪辑(更快的 RCNN restnet 模型),我能够将时间提高到大约 3 分钟的检测时间,如上文提到的 1920x1080 视频剪辑的 3.6 FPS。在独立图像上,它在 0.28 秒内探测到物体。
谷歌智能写作、机器偏见、种族主义人工智能——总结一个疯狂阅读博客的夜晚
原文:https://towardsdatascience.com/google-smart-compose-machine-bias-racist-ai-summarising-one-night-of-binge-reading-from-blogs-19a033953013?source=collection_archive---------6-----------------------
Pic Credit
在桑德尔·皮帅上台并开始他的谷歌 I/O 2018 主题演讲后,我开始记下正在宣布和演示的有趣的事情。有一些非常有趣的演示和公告,特别是对于那些对深度学习感兴趣的人。我对 Gmail 的 Smart Compose 和 Google Duplex 以及其他东西很好奇,这两个都是自然语言处理的用例。Google Duplex 得到了很多关注,这并不奇怪,因为 Google Assistant 与真人的对话听起来天衣无缝,也很像人。如果你对深度学习感兴趣,你肯定想知道至少一点关于这些是如何完成的,谷歌的研究博客是一个了解更多的好地方。以防你不知道,ai.googleblog.com 是谷歌新的研究博客!
我们都熟悉在手机上完成单词的建议。但是为什么要把这个功能限制在只有单词补全呢?智能撰写是 Gmail 的新功能,它可以在我们撰写电子邮件时提供建议,从而帮助我们完成句子。这也像许多最近的进步和功能,利用神经网络。在典型的单词完成任务中,提示性单词取决于标记/单词的前缀序列。根据前面的单词,建议接下来可能出现的语义最接近的单词。在智能撰写的情况下,除了前缀序列之外,电子邮件标题以及先前的电子邮件正文(如果在当前邮件是对先前邮件的回复的情况下存在)也被认为是输入,以提供句子完成的建议。
Pic Credit
延迟、可伸缩性和隐私是三个已确定的挑战,要使该功能高效、可访问且安全,就必须解决这三个挑战。为了使句子完成建议有效,等待时间应该更短,这样用户就不会注意到任何延迟。考虑到有超过 10 亿人使用 Gmail,很难想象每封邮件的内容会有多么不同。该模型应该足够复杂和可伸缩,以容纳尽可能多的用户。当涉及任何类型的数据时,到处都可以听到对隐私的呼喊。只有少数事情比我们的电子邮件更需要隐私。因此,模型不应该以任何方式暴露用户的数据。
谷歌在 Smart Compose 上的博客引用了一些研究论文,这些论文有助于构建这一新 Gmail 功能背后的神经网络架构。还有一篇在博客中分享的论文 语义从语言语料库中自动导出必然包含人类偏见 。这是一篇非常有趣的论文,它引导我写了一系列博客。即使你不是人工智能研究人员,也不是机器学习专家,你也一定听说过这些领域的进步极大地改变了我们生活的许多方面。隐私和偏见是围绕从数据中学习的应用程序或程序的使用的两个大问题。虽然隐私问题已经被关注了很长一段时间,但偏见似乎也在蔓延。任何利用机器学习来解决问题的程序都需要数据作为输入。根据手头的问题或任务,这些输入数据可以是文本、图像、音频等。不管输入数据是什么类型/形式,它都是通过某种人类行为生成的。这意味着存在于人类行为和思想中的偏见和成见是学习模型中最重要的部分——输入。
当哈佛大学的拉坦娅·斯威尼在谷歌上搜索自己的名字时,令她惊讶的是,搜索结果中还有一条广告显示,“拉坦娅·斯威尼被捕了?”这让她对谷歌搜索结果进行了研究,从中她得出结论,与黑人联系更紧密的名字更有可能出现这样的搜索结果或广告。她在对 2000 多个真实姓名进行搜索后发现,与黑人相关的名字显示此类犯罪广告的可能性高达 25%。谷歌搜索在这里是种族歧视吗?这是来自谷歌的回应——“AdWords 不进行任何种族定性。我们也有一个“反”和暴力政策,声明我们将不允许宣传反对某个组织、个人或群体的广告。由个体广告客户决定他们希望选择哪些关键词来触发他们的广告。”
Pic Credit
2016 年,一位互联网用户在 Twitter 上发帖,讲述了他使用谷歌图片搜索的经历之一。当他搜索“三个白人少年”时,他发现的结果是微笑、快乐的白人少年的图像。当用“三个黑人少年”进行类似的搜索时,结果大相径庭。虽然这些结果也有一些正常和普通的图像,但许多其他结果是被监禁的青少年的。这篇文章发布后很快就火了,这并不奇怪。这背后的原因是什么?图像搜索背后的算法是编程来做这个的吗?情况肯定不是这样。谷歌也解释了这种情况——“我们的图片搜索结果是整个网络内容的反映,包括各类图片出现的频率以及它们在网上的描述方式”。
问题似乎只出在可以访问大量数据的大型科技公司的应用程序/算法上吗?美国的许多法院使用一种软件给被告/被指控者一个风险分数。这个分数代表这个人犯罪的可能性。软件从哪里获得数据来执行分析并给出风险分数?据 ProPublica 的博客称,开发这种风险评估软件的 Northpointe 公司使用了 137 个问题的答案作为数据。这些答案要么直接通过询问被告获得,要么取自过去的犯罪记录。
Pic Credit
在这种情况下,数据可能不多,但这并不意味着该程序没有偏见。当 Brisha Borden 骑着一辆不属于她的自行车被逮捕时,风险评估程序给她打了高分,认为她将来可能会犯下更多的罪行。同一个节目给了弗农·彼得一个较低的分数,他过去曾因持械抢劫入狱 5 年。然而,在两年的时间里,得分高的布里沙没有犯任何罪行,而得分低的弗农却因为另一次抢劫而再次入狱。数据也是这个风险评估项目最关键的组成部分。
这些不仅仅是为了解释偏见问题而精心挑选的一些事件。几年前有一个事件,惠普的面部跟踪网络摄像头在白人身上工作正常,但却无法识别深色皮肤的人。谷歌照片将黑人归类为大猩猩。所有这些的根本原因是偏见是被使用的数据的很大一部分。当生成的数据存在偏差时,以及当收集的用于训练模型的数据不具有代表性时,都会发生这种情况。当手机或网站上的一些应用程序将他们或朋友归类为某种动物时,并非所有人都会一笑置之。没有一家研究基于数据的算法和应用的公司会希望它们表现出偏见。我们许多人都很清楚,用于这些目的的算法远非完美。然而,当人们经历这些偏见时,他们的反应会是自发的,就好像他们受到了同伴的影响一样。
Pic Credit
拉坦娅·斯威尼事件发生在 2013 年。同样,提到的其他事件发生在 2014 年和 2016 年的某个时候,而惠普的面部跟踪问题发生在 2009 年。鉴于我们正在谈论的事件发生在几年前,这些偏见的问题现在可能已经解决了,不是吗?不。谷歌通过阻止应用程序中的任何图片被归类为大猩猩、黑猩猩等,修复了照片应用程序的问题。听起来更像是一种变通办法,而不是解决办法?但是我们的问题是这些是偏见,而不是错误。它们不存在于代码中。它们存在于数据中,这使得这个问题很难解决。
学习模型并不完美。开发和建造这些设备的公司也没有假装它们是。谷歌毫不犹豫地承认,即使是其最先进的算法也容易受到数据偏差的影响。它不断努力使这些算法变得更好。苹果已经从以前的人脸识别软件面临的所有缺陷和问题中吸取了教训。它确保使用神经网络构建的人脸识别程序是根据适当的代表性数据进行训练的——这些数据包括年龄、性别、种族、族裔等所有多样性。领先的科技公司和许多其他公司正在朝着改进这些算法的方向迈进,这些算法肯定有很大的潜力,比如疾病的早期检测和诊断,帮助不同能力的人,教育,使计算机和技术更好地执行类似人类的任务等。
尽管这些进步在过去几年里发生得很快,但像算法偏差这样的问题仍然存在。由于学习模型在对其进行训练的数据中存在偏差时是无能为力的,因此开发不仅学习关联模式而且学习在偏差存在时隐式处理偏差的学习模型将是一个巨大的进步。我们人类是如此受思想驱动。然而,即使有偏见的想法,如果我们愿意,我们也有能力采取不带偏见的行动。学习模型能学会这样做吗?如果不完全是,至少在某种程度上是?
致谢:
Google 研究团队在 Google Smart Compose 上的博客— 链接
语义从包含类人偏见的语言语料库中自动导出研究论文— 链接
ProPublica 在机器偏见上的博客— 链接
你觉得这个帖子有用吗?鼓掌是让我知道它做到了的一种方式。感谢阅读!!
要连接: LinkedIn 、 Twitter 和我的博客。
谷歌的 AutoML 将改变企业使用机器学习的方式
原文:https://towardsdatascience.com/googles-automl-will-change-how-businesses-use-machine-learning-c7d72257aba9?source=collection_archive---------4-----------------------
想获得灵感?快来加入我的 超级行情快讯 。😎
Google 的 AutoML 是一个新兴的(alpha 阶段)机器学习工具云软件套件。它基于谷歌在图像识别领域的最新研究,名为神经架构搜索 (NAS)。NAS 基本上是一种算法,在给定特定数据集的情况下,它会搜索最佳神经网络来对该数据集执行特定任务。AutoML 是一套机器学习工具,允许人们轻松训练高性能的深度网络,而不需要用户拥有任何深度学习或人工智能的知识;你需要的只是标签数据!Google 将使用 NAS 为您的特定数据集和任务找到最佳网络。他们已经展示了他们的方法如何能够实现比手工设计的网络更好的性能。
AutoML 完全改变了整个机器学习游戏,因为对于许多应用程序来说,不需要专业技能和知识。很多公司只需要深度网络来完成更简单的任务,比如图像分类。在这一点上,他们不需要雇佣 5 个机器学习博士;他们只需要有人能够处理移动和组织他们的数据。
毫无疑问,企业如何使用“人工智能”的这种转变将带来变化。但是我们看到的是什么样的变化呢?这种变化对谁有利?所有进入机器学习领域的人会发生什么?在这篇文章中,我们将分析谷歌的 AutoML,以及总体上向软件 2.0 的转变,对机器学习领域的企业和开发者意味着什么。
更多的开发,更少的商业研究
人工智能领域的很多企业,尤其是初创企业,正在深度学习的背景下做相对简单的事情。他们的大部分价值来自于他们最终组装的产品。例如,大多数计算机视觉初创公司都在使用某种图像分类网络,这实际上将是 AutoML 在套件中的第一个工具。事实上,谷歌的 NASNet,在图像分类方面达到了目前的最先进水平,已经在 TensorFlow 中公开可用了!企业现在可以跳过产品管道中复杂的实验研究部分,直接使用迁移学习来完成任务。因为实验研究减少了,更多的商业资源可以花在产品设计、开发和所有重要的数据上。
说到这个…
它变得更加关注产品
从第一点连接,由于更多的时间花在产品设计和开发上,公司会有更快的产品迭代。公司的主要价值将不再是他们的研究有多伟大和前沿,而是他们的产品/技术设计得有多好。设计的好吗?好用吗?他们的数据管道是否以这样一种方式建立,即他们可以快速方便地改进他们的模型?这些将是新的关键问题,以优化他们的产品,并能够比竞争对手更快地迭代。尖端研究也将不再是提高技术性能的主要驱动力。
现在更像是…
数据和资源变得至关重要
既然研究是等式中不太重要的部分,公司如何脱颖而出?你如何在竞争中领先?当然,销售、营销以及我们刚刚讨论过的产品设计都非常重要。但是这些深度学习技术性能的巨大驱动力是你的数据和资源。你的数据越清晰、多样且有任务针对性(即质量和数量),你就越能使用 AutoML 等软件工具改进你的模型。这意味着获取和处理数据需要大量资源。所有这些都部分表明我们正在远离编写大量代码的本质。
它变得更加…
软件 2.0:深度学习成为大多数人工具箱中的另一个工具
使用谷歌的 AutoML 你所要做的就是上传你的标签数据,然后嘣,你就搞定了!对于那些没有深入(哈哈,双关语)这个领域,只想利用技术力量的人来说,这是一个大问题。深度学习的应用变得更加触手可及。编码更少,更多地使用工具套件。事实上,对于大多数人来说,深度学习只是他们工具箱中的另一个工具。Andrej Karpathy 写了一篇关于软件 2.0 的伟大文章,讲述了我们如何从编写大量代码转向更多的设计和使用工具,然后让人工智能完成剩下的工作。
但是,考虑到所有这些…
创造性科学和研究仍有空间
即使我们有这些易于使用的工具,旅程也不会就此结束!当汽车被发明出来的时候,我们并没有停止改进它们,即使现在它们很容易使用。仍然有许多改进可以用来改进当前的人工智能技术。人工智能仍然不是很有创造力,也不能推理或处理复杂的任务。它需要大量的标签数据,获取这些数据既昂贵又耗时。训练仍然需要很长时间才能达到最高的准确度。深度学习模型的性能对于一些简单的任务来说是不错的,比如分类,但在本地化等事情上只能做得相当好,有时甚至很差(取决于任务的复杂性)。我们甚至还没有完全理解内部的深层网络。
所有这些都为科学和研究提供了机会,特别是推进当前的人工智能技术。在商业方面,一些公司,特别是科技巨头(如谷歌、微软、脸书、苹果、亚马逊)需要通过科学和研究来创新过去的现有工具,以便竞争。他们都可以获得大量的数据和资源,设计出色的产品,进行大量的销售和营销等。他们真的可以使用更多的东西来使他们与众不同,这可以来自尖端创新。
这留给我们最后一个问题…
这一切是好是坏?
总的来说,我认为我们创造人工智能技术的这种转变是一件好事。大多数企业将利用现有的机器学习工具,而不是创建新的工具,因为他们不需要它。许多人都可以接触到接近尖端的人工智能,这意味着对所有人来说都是更好的技术。人工智能也是一个相当“开放”的领域,像吴恩达这样的主要人物创建了非常受欢迎的课程来教授人们这一重要的新技术。让事物变得更容易接近有助于人们适应快节奏的技术领域。
这样的转变以前发生过很多次。编程计算机是从汇编级编码开始的!我们后来转向了 C 之类的东西。今天许多人认为 C 太复杂了,所以他们使用 C++。很多时候,我们甚至不需要像 C++这样复杂的东西,所以我们只是使用 Python 或 R 这样的超高级语言!我们使用手边最合适的工具。如果你不需要一些超低级的东西,那么你就不必使用它(例如 C 代码优化,从零开始的深度网络的 R&D),可以简单地使用一些更高级的内置的东西(例如 Python,迁移学习,人工智能工具)。
与此同时,在人工智能技术的科学和研究方面的持续努力至关重要。通过设计新的基于人工智能的产品,我们肯定可以为世界增加巨大的价值。但是有一点需要新的科学来推进。人类的创造力永远是有价值的。
结论
感谢阅读!我希望你喜欢这篇文章,并从人工智能技术的当前趋势中学到一些新的有用的东西!这是一篇部分自以为是的文章,所以我很想听听你在下面的回应!
喜欢学习?
在 twitter 上关注我,我会在这里发布所有最新最棒的人工智能、技术和科学!
谷歌在 Keras 的使用
原文:https://towardsdatascience.com/googles-use-in-keras-22fef48e2dfa?source=collection_archive---------11-----------------------
如何使用谷歌的通用句子编码器进行垃圾邮件分类
这是我放在一起的一个小视频,关于如何在 Keras 模型中使用谷歌的通用句子编码器。在此视频中,我们训练了一个模型来区分真实和垃圾短信。
如果您有任何问题或反馈,请告诉我!
我的网站上有代码:http://hunterheidenreich . com/blog/Google-universal-sentence-encoder-in-keras/
垃圾邮件数据集原文可以在这里找到:https://www . ka ggle . com/UC IML/SMS-spam-collection-dataset/version/1 # _ = _
JavaScript 中的 GPU 加速神经网络
原文:https://towardsdatascience.com/gpu-accelerated-neural-networks-in-javascript-195d6f8e69ef?source=collection_archive---------3-----------------------
据 Octoverse 2017 报道,JavaScript 是 Github 上最受欢迎的语言。用 pull 请求的数量来衡量,JavaScript 的活跃程度可以与 Python、Java 和 Go 的总和相媲美。
JavaScript 已经征服了网络,并在服务器、手机、桌面和其他平台上取得了进展。
与此同时,GPU 加速的使用已经远远超出了计算机图形学的范围,现在已经成为机器学习不可或缺的一部分。
用深度架构训练神经网络是一个计算密集型过程,已经在机器智能的许多重要领域产生了最先进的结果。
本文着眼于这些趋势的持续融合,并概述了将 GPU 加速的神经网络引入 JavaScript 世界的项目。
Community logo for JavaScript
概述
下面列出的所有项目都得到积极维护,在 Github 上有数千颗星,并通过 NPM 或 CDNs 分发。
它们都通过 WebGL 在浏览器中实现 GPU 加速,如果没有合适的显卡,则退回到 CPU。
旨在运行现有模型的库(尤其是那些用 Python 框架训练的)不包括在本概述中。
最终,有四个项目成功上榜。
虽然 deeplearn.js 的功能集面向神经网络,但它可以被描述为一个通用的机器学习框架。Propel 是一个科学计算库,提供自动微分。Gpu.js 提供了一种在 Gpu 上运行 JavaScript 函数的便捷方式。Brain.js 是一个更老的神经网络库的延续,使用 gpu.js 进行硬件加速。
我打算保留这篇文章,并将其扩展成一个 Github 库。如果你看到相关消息,请告诉我。
Deeplearn.js
Deeplearn.js 是四个项目中最受欢迎的,被描述为“机器智能的硬件加速 JavaScript 库”。它得到了谷歌大脑团队和一个由 50 多名贡献者组成的社区的支持。两位主要作者是丹尼尔·斯米尔科夫和尼基尔·苏拉特。
Definition of a convolutional layer in deeplearn.js
deeplearn.js 以 TypeScript 编写,并模仿 Tensorflow,支持 Google Brain 旗舰开源项目中提供的越来越多的功能子集。API 本质上有三个部分。
第一部分涵盖了用于创建、初始化和转换张量的函数,张量是保存数据的类似数组的结构。
API 的下一部分提供了在张量上执行的操作。这包括基本的数学运算、归约、归一化和卷积。在这一点上,对递归神经网络的支持是初步的,但确实包括长短期记忆网络单元的堆栈。
第三部分围绕模型训练展开。所有流行的优化器,从随机梯度下降到亚当,都包括在内。另一方面,交叉熵损失是参考文献中提到的唯一损失函数。
API 的其余部分用于设置环境和管理资源。
node.js 中的实验性 GPU 加速可以通过 headless-gl 实现(参见第 49 期)。
该项目网站有许多令人难忘的演示。这些包括通过递归神经网络进行的钢琴演奏,建立模型的视觉界面和基于 SqueezeNet(一种参数数量相对较少的图像分类器)的网络摄像头应用程序。
推进
Propel 被描述为“JavaScript 的差异化编程”。两位主要作者瑞安·达尔和伯特·贝尔德的工作得到了 11 位撰稿人的补充。
A feed-forward neural network with three layers trained with Propel on the MNIST data set
自动微分(AD)是这个项目的核心,让我们不再需要手动指定导数。对于用支持的张量运算定义的给定函数 f(x) ,梯度函数可以用 grad 得到。多变量箱由多 grad 覆盖。
除了 AD,这个项目的走向似乎并不完全明朗。虽然网站上提到“类似 numpy 的基础设施”是一个目标,但该 API 在“重度开发”下,包括与神经网络和计算机视觉相关的功能。使用 load 函数,npy 文件的内容可以被解析并作为张量使用。
在浏览器环境中,Propel 利用 deeplearn.js 中的 WebGL 功能。对于 Node 中的 GPU 加速,该项目使用 TensorFlow 的 C API。
gpu.js
虽然我的大部分经验是使用 CUDA 而不是 WebGL,但我可以证明 GPU 编程的耗时本质。因此,当我看到 gpu.js 时,我感到惊喜。该项目在 Github 上有大约 5700 颗星,其受欢迎程度可与 deeplearn.js 媲美,并有 18 名贡献者。随着时间的推移,一些个人做出了重大贡献。罗伯特·普卢默是主要作者。
Matrix multiplication with gpu.js: The Hello World equivalent in GPU programming
在当前的上下文中,内核是在 GPU 而不是 CPU 上执行的功能。有了 gpu.js,内核可以用 JavaScript 的子集来编写。代码然后被编译并在 GPU 上运行。节点。通过 OpenCL 的 JS 支持已经在几周前添加了。
多达三维的数字和数字数组被用作输入和输出。除了基本数学运算,gpu.js 还支持局部变量、循环和 if/else 语句。
为了实现代码重用和更模块化的设计,可以注册定制函数然后在内核代码中使用。
在内核的 JavaScript 定义中, this 对象提供了线程标识符,并保存了在实际内核内部为常量但在外部为动态的值。
该项目专门研究加速的 JavaScript 函数,并不试图提供一个神经网络框架。为此,我们可以求助于依赖于 gpu.js 的库。
Brain.js
Brain.js 是 harthur/brain 的继任者,这是一个历史可以追溯到 2010 年古代的存储库。
总共有近 30 人对这两个资料库作出了贡献。
对 GPU 加速神经网络的支持基于 gpu.js,可以说是该项目最近历史上最重要的发展。
除了前馈网络,Brain.js 还包括三种重要类型的递归神经网络的实现:经典的 Elman 网络、长短期记忆网络和最近的带门控递归单元的网络。
资源库中包含的演示还处于早期阶段。主页上显示了学习色彩对比度偏好的神经网络。另外两个演示,一个涉及对用 ASCII 符号绘制的字符的检测,可以在源代码中找到。
用于机器学习的加速 JavaScript 库的出现有几个有趣的含义。
在线课程可以将与机器学习或 GPU 计算相关的练习直接集成到 web 应用程序中。学生不必跨不同的操作系统和软件版本建立单独的开发环境。
许多基于神经网络的演示可以更容易地部署,不再需要服务器端 API。
对机器学习感兴趣的 JavaScript 开发者可以充分利用他们的专业技能,在集成问题上花费更少的时间。
此外,可以更有效地利用客户端可用的计算资源。毕竟,并不是所有的显卡都一直被用于虚拟现实和加密货币挖掘。
明确地说,在这一点上,我不提倡将本文中提到的库用于任务关键型神经网络。Python 生态系统仍然是大多数应用程序的首选。
然而,看到过去 12 个月取得的进展令人鼓舞。一年前,deeplearn.js 和 Propel 都不存在。gpu.js 存储库中的活动水平相对较低,Brain.js 不支持 gpu 加速。
随着时间的推移,这些项目将在某些方面与已建立的框架竞争,并启用 JavaScript 独一无二适合的全新应用程序。
感谢您的阅读!如果你喜欢这篇文章,请点击拍手按钮并关注我,以获得更多关于机器学习最新发展的信息。
关于这个话题的介绍,可以看看我的机器从头学习系列。
GPU 优化的动态编程
原文:https://towardsdatascience.com/gpu-optimized-dynamic-programming-8d5ba3d7064f?source=collection_archive---------4-----------------------
利用 GPU 计算能力开发动态编程的并行性。
Source: link
我们来考虑一下 路径和:项目欧拉问题 81 中的两路(环节)。探索解的动态编程范式和 GPU 优化是我们感兴趣的问题。
Project Euler: 81
您需要通过向右或向下移动矩阵中具有最小单元聚合和的单元,从左上向右下遍历。所以在左边的图中,红色区域展示了满足给定条件的路径。
动态程序建模
对于上述任务,我们可以如下对动态程序建模。
Dynamic Approach
我们可以从原点 O 开始遍历,并向右或向下移动。如果我们移动到 B 的成本是 成本(O + B) ,移动到 A 给出 成本(O + A) 。我们在拐角处没有选择的余地。考虑移动到 x 点,我们有两个选择。因此,现在正确的值是 min(Cost(A + X),Cost(B + X)) 。同样,我们可以遍历整个矩阵,更新从其 顶部 和 左侧 双亲到特定单元的最小范围。这需要 O(mn) 的迭代次数,在我们的例子中我们考虑 80 x 80 导致我们6400次迭代。现在让我们从 GPU 的角度来考虑这个问题。在 GPU 中,所有的单元都是同时计算的。
GPU Computation
如所展示的,尽管在整个矩阵的初始迭代中立刻计算了所有单元,但是只有具有标记 1 的单元将被计算为具有正确的值。仅仅一次迭代之后,带有标记 2 的单元将不会计算出正确的值,因为此时带有标记 1 的单元不具有正确的值。同样,我们必须多次运行程序,以获得单元格中的正确数字。在图中,标有相同数字的单元可以并行计算,这是动态程序中可用的并行度。我们对 GPU 所要做的就是虚线所示的正确的行刷次数,但是有多少呢?它显然是行数和列数的总和。因此,时间复杂度是 O(m+n) 在我们的例子中是 160。这是一个巨大的收获。然而,由于我们一次又一次地计算整个矩阵,我们需要存储原始矩阵,从而增加了程序的空间复杂度。
示例代码
pom.xml 和 DynamicProgramming.java
用这种方法可以很快地得到非常大的矩阵的结果。迭代次数的上限是行数和列数之和,而不是乘积。我在代码中使用的数据集可以在项目欧拉问题 81 的网页上找到。
链接:https://projecteuler.net/problem=81
使用随机森林的梯度推进在纽约出租车费用预测挑战中的应用
原文:https://towardsdatascience.com/gradient-boosting-using-random-forests-for-application-on-the-new-york-taxi-fare-prediction-f6101c592bf9?source=collection_archive---------15-----------------------
在这篇短文中,我将描述使用随机森林的梯度推进在 Kaggle 上的纽约出租车费用预测挑战中的应用。我还将比较两个最流行的软件包:微软的 LightGBM 和 Yandex 的 CatBoost 。
首先我将简要地谈论随机森林。随机森林基本上是决策树的集合,通常通过 bagging 方法训练,其中最大样本数设置为训练集的大小。在构建树的同时,每次都有一个分裂,并且从完整的 p 预测值集中选择随机样本的 m 预测值作为分裂候选值。这些 m 个预测值中只有一个被选择。在每次分裂时选择 m 个预测值的新样本。通常情况下,m√p:每次分割时考虑的预测值数量大约等于预测值总数的根。这具有以下效果:
- 将树彼此去相关
- 交易较高的偏差和较低的方差
随机森林有助于快速了解哪些特征很重要,尤其是在特征选择方面。
Boosting 是一种将几个弱学习者组合成一个强学习者的技术。您按顺序训练预测器,每次都试图纠正前一个预测器。不涉及 bagging(减少统计学习方法方差的通用程序)。每棵树都适合原始数据集的修改版本。
在我们谈论梯度增强之前,我们必须了解一下 Adaboost。自适应增强关注前一个欠适应的训练实例。增加错误分类的训练实例的相对权重,然后使用更新的权重训练第二分类器,等等。
类似于梯度下降,但不是改变单个预测参数来最小化成本函数,Adaboost 将预测器添加到集成中,逐渐使其更好。一旦训练了所有预测器,集成就像装袋一样进行预测,只是预测器具有不同的权重。然而,这种技术不能并行化,并且与装袋和粘贴相比不能很好地扩展。
渐变增强,和 Adaboost 一样也是一种序列技术。然而,在每次迭代中,新的预测器被拟合到由前一个预测器产生的残差,而不是使用实例权重。
整体算法如下:
- 使决策树回归器适合训练集
- 根据 1 产生的残差训练第二个决策树回归器。
- 根据 2 产生的剩余误差训练第三个回归变量。
- 通过将所有树的预测相加,使用这三棵树的集合对新实例进行预测。
Schematic of how gradient boosting works.
现在说说代码:这个代码大量借用了 Kaggle 上的 Sylas。评估指标是 RMSE(均方根误差)。首先,您需要导入库,然后从 csv 文件输入数据。我们将使用 LightGBM。注意 nrows 参数。你做得越高,你应该得到的分数就越好,但是跑的时间就越长。
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
import lightgbm as lgbm
import gc# Reading Data
train_df = pd.read_csv('train.csv', nrows = 800000)
#Drop rows with null values
train_df = train_df.dropna(how = 'any', axis = 'rows')def clean_df(df):
return df[(df.fare_amount > 0) & (df.fare_amount <= 500) &
# (df.passenger_count >= 0) & (df.passenger_count <= 8) &
((df.pickup_longitude != 0) & (df.pickup_latitude != 0) & (df.dropoff_longitude != 0) & (df.dropoff_latitude != 0) )]train_df = clean_df(train_df)
Train_df 基本上包含纽约出租车的所有信息,包括上下车地点、乘客、日期和时间以及票价本身。
How train_df looks like
现在我们需要定义几个要调用的函数。
# To Compute Haversine distance
def sphere_dist(pickup_lat, pickup_lon, dropoff_lat, dropoff_lon):
"""
Return distance along great radius between pickup and dropoff coordinates.
"""
#Define earth radius (km)
R_earth = 6371
#Convert degrees to radians
pickup_lat, pickup_lon, dropoff_lat, dropoff_lon = map(np.radians,
[pickup_lat, pickup_lon,
dropoff_lat, dropoff_lon])
#Compute distances along lat, lon dimensions
dlat = dropoff_lat - pickup_lat
dlon = dropoff_lon - pickup_lon
#Compute haversine distance
a = np.sin(dlat/2.0)**2 + np.cos(pickup_lat) * np.cos(dropoff_lat) * np.sin(dlon/2.0)**2
return 2 * R_earth * np.arcsin(np.sqrt(a))def sphere_dist_bear(pickup_lat, pickup_lon, dropoff_lat, dropoff_lon):
"""
Return distance along great radius between pickup and dropoff coordinates.
"""
#Define earth radius (km)
R_earth = 6371
#Convert degrees to radians
pickup_lat, pickup_lon, dropoff_lat, dropoff_lon = map(np.radians,
[pickup_lat, pickup_lon,
dropoff_lat, dropoff_lon])
#Compute distances along lat, lon dimensions
dlat = dropoff_lat - pickup_lat
dlon = pickup_lon - dropoff_lon
#Compute bearing distance
a = np.arctan2(np.sin(dlon * np.cos(dropoff_lat)),np.cos(pickup_lat) * np.sin(dropoff_lat) - np.sin(pickup_lat) * np.cos(dropoff_lat) * np.cos(dlon))
return adef radian_conv(degree):
"""
Return radian.
"""
return np.radians(degree)def add_airport_dist(dataset):
"""
Return minumum distance from pickup or dropoff coordinates to each airport.
JFK: John F. Kennedy International Airport
EWR: Newark Liberty International Airport
LGA: LaGuardia Airport
SOL: Statue of Liberty
NYC: Newyork Central
"""
jfk_coord = (40.639722, -73.778889)
ewr_coord = (40.6925, -74.168611)
lga_coord = (40.77725, -73.872611)
sol_coord = (40.6892,-74.0445) # Statue of Liberty
nyc_coord = (40.7141667,-74.0063889)
pickup_lat = dataset['pickup_latitude']
dropoff_lat = dataset['dropoff_latitude']
pickup_lon = dataset['pickup_longitude']
dropoff_lon = dataset['dropoff_longitude']
pickup_jfk = sphere_dist(pickup_lat, pickup_lon, jfk_coord[0], jfk_coord[1])
dropoff_jfk = sphere_dist(jfk_coord[0], jfk_coord[1], dropoff_lat, dropoff_lon)
pickup_ewr = sphere_dist(pickup_lat, pickup_lon, ewr_coord[0], ewr_coord[1])
dropoff_ewr = sphere_dist(ewr_coord[0], ewr_coord[1], dropoff_lat, dropoff_lon)
pickup_lga = sphere_dist(pickup_lat, pickup_lon, lga_coord[0], lga_coord[1])
dropoff_lga = sphere_dist(lga_coord[0], lga_coord[1], dropoff_lat, dropoff_lon)
pickup_sol = sphere_dist(pickup_lat, pickup_lon, sol_coord[0], sol_coord[1])
dropoff_sol = sphere_dist(sol_coord[0], sol_coord[1], dropoff_lat, dropoff_lon)
pickup_nyc = sphere_dist(pickup_lat, pickup_lon, nyc_coord[0], nyc_coord[1])
dropoff_nyc = sphere_dist(nyc_coord[0], nyc_coord[1], dropoff_lat, dropoff_lon)
dataset['jfk_dist'] = pickup_jfk + dropoff_jfk
dataset['ewr_dist'] = pickup_ewr + dropoff_ewr
dataset['lga_dist'] = pickup_lga + dropoff_lga
dataset['sol_dist'] = pickup_sol + dropoff_sol
dataset['nyc_dist'] = pickup_nyc + dropoff_nyc
return dataset
def add_datetime_info(dataset):
#Convert to datetime format
dataset['pickup_datetime'] = pd.to_datetime(dataset['pickup_datetime'],format="%Y-%m-%d %H:%M:%S UTC")
dataset['hour'] = dataset.pickup_datetime.dt.hour
dataset['day'] = dataset.pickup_datetime.dt.day
dataset['month'] = dataset.pickup_datetime.dt.month
dataset['weekday'] = dataset.pickup_datetime.dt.weekday
dataset['year'] = dataset.pickup_datetime.dt.year
return dataset
上面的代码主要计算哈弗线距离,它计算两个纬度经度点之间的距离。我们还希望以合适的日期和时间格式获得到机场的距离以及旅程的持续时间,以便稍后进行处理。
现在让我们修改 train_df,使这些附加属性从上面的函数中计算出来。
train_df = add_datetime_info(train_df)
train_df = add_airport_dist(train_df)
train_df['distance'] = sphere_dist(train_df['pickup_latitude'], train_df['pickup_longitude'],
train_df['dropoff_latitude'] , train_df['dropoff_longitude'])train_df['bearing'] = sphere_dist_bear(train_df['pickup_latitude'], train_df['pickup_longitude'],
train_df['dropoff_latitude'] , train_df['dropoff_longitude'])
train_df['pickup_latitude'] = radian_conv(train_df['pickup_latitude'])
train_df['pickup_longitude'] = radian_conv(train_df['pickup_longitude'])
train_df['dropoff_latitude'] = radian_conv(train_df['dropoff_latitude'])
train_df['dropoff_longitude'] = radian_conv(train_df['dropoff_longitude'])train_df.drop(columns=['key', 'pickup_datetime'], inplace=True)y = train_df['fare_amount']
train_df = train_df.drop(columns=['fare_amount'])print(train_df.head())x_train,x_test,y_train,y_test = train_test_split(train_df,y,random_state=123,test_size=0.10)
Train_df 现在有了这些附加列:
train_df with the additional columns after data processing.
我们可以去掉 train_df,因为我们现在已经将数据分为 x_train 和 x_test 以及 y_train 和 y_test。
del train_df
del y
gc.collect()
现在的关键部分是设置用于 LightGBM 的参数。我调整的关键参数是 max_bin,learning_rate,num_leaves。另一个重要参数是升压类型。在这里,我尝试了 dart(droppets meet Multiple Additive Regression Trees),因为它应该有助于实现更高的准确性。
params = {
'boosting_type':'dart',
'objective': 'regression',
'nthread': 4,
'num_leaves': 31,
'learning_rate': 0.05,
'max_depth': -1,
'subsample': 0.8,
'bagging_fraction' : 1,
'max_bin' : 5000 ,
'bagging_freq': 20,
'colsample_bytree': 0.6,
'metric': 'rmse',
'min_split_gain': 0.5,
'min_child_weight': 1,
'min_child_samples': 10,
'scale_pos_weight':1,
'zero_as_missing': True,
'seed':0,
'num_rounds':50000
}
现在我们开始使用 LightGBM,并将这些参数输入模型。我们删除最后不需要的数据帧以节省内存。
train_set = lgbm.Dataset(x_train, y_train, silent=False,categorical_feature=['year','month','day','weekday'])
valid_set = lgbm.Dataset(x_test, y_test, silent=False,categorical_feature=['year','month','day','weekday'])
model = lgbm.train(params, train_set = train_set, num_boost_round=10000,early_stopping_rounds=500,verbose_eval=500, valid_sets=valid_set)
del x_train
del y_train
del x_test
del y_test
gc.collect()
我们现在可以测试模型并将结果输入到 test_df 数据帧中。
test_df = pd.read_csv('test.csv')
print(test_df.head())
test_df = add_datetime_info(test_df)
test_df = add_airport_dist(test_df)
test_df['distance'] = sphere_dist(test_df['pickup_latitude'], test_df['pickup_longitude'],
test_df['dropoff_latitude'] , test_df['dropoff_longitude'])test_df['bearing'] = sphere_dist_bear(test_df['pickup_latitude'], test_df['pickup_longitude'],
test_df['dropoff_latitude'] , test_df['dropoff_longitude'])
test_df['pickup_latitude'] = radian_conv(test_df['pickup_latitude'])
test_df['pickup_longitude'] = radian_conv(test_df['pickup_longitude'])
test_df['dropoff_latitude'] = radian_conv(test_df['dropoff_latitude'])
test_df['dropoff_longitude'] = radian_conv(test_df['dropoff_longitude'])test_key = test_df['key']
test_df = test_df.drop(columns=['key', 'pickup_datetime'])
最后输出模型预测,并输入到 Kaggle 的提交文件中!
prediction = model.predict(test_df, num_iteration = model.best_iteration)
submission = pd.DataFrame({
"key": test_key,
"fare_amount": prediction
})submission.to_csv('taxi_fare_submission_800k.csv',index=False)
我使用 dart boosting 方法在整个 22m 行中取得的最好成绩是 2.88。我在总共 1488 支队伍中取得了第 79 名。
现在让我们来看看 Yandex 的 Catboost。因为我们已经有了所需格式的数据,所以使用 CatBoost 只需要几行代码。
from catboost import Pool, CatBoostRegressortrain_pool = Pool(x_train, y_train, cat_features=[5,6,7,8])
test_pool = Pool(x_test, y_test, cat_features=[5,6,7,8])
model = CatBoostRegressor(iterations=4000, depth=10, learning_rate=1, loss_function='RMSE')
model.fit(train_pool)
preds2 = model.predict(test_df)
print(preds2)submission = pd.DataFrame({
"key": test_key,
"fare_amount": prediction
})submission.to_csv('taxi_fare_submission_800k_cat_boost_it4k_depth10.csv',index=False)
使用 Catboost,我使用全部 22m 行只处理了 3.13。
为了优化模型的参数,以及正确地比较 LightGBM 和 CatBoost,我们需要进行更多的实验,并很好地了解决策树和随机森林的作用。
看看其他人用类似的方法用 LightGBM 和 CatBooost 实现了什么会很有趣。
带自由单子的梯度下降
原文:https://towardsdatascience.com/gradient-descend-with-free-monads-ebf9a23bece5?source=collection_archive---------5-----------------------
最近,我在 Scala 中玩自由单子,发现这可能是在函数式编程风格中进行梯度计算的完美方式。显然,从性能的角度来看,使用自由单子计算梯度并不是最好的主意,但它对于教育和实验目的非常有用。如果您有办法在 dispose 中计算任意表达式的梯度,那么开始构建简单的神经网络并不是什么大事。
Free Monad 是构建任何一种表示计算的抽象语法树 (AST ),同时保持计算 AST 与它的解释方式分离的完美方式。
我的目标是演示如何使用自由单子构建一个简单的梯度计算引擎。首先,我们将为 AST 表示定义一个域模型。然后,可以定义一个表示计算的自由单子。最后,我们将能够使用不同的解释器分析和数值计算梯度,并比较结果(应该相等)。此外,我们将能够定义一个简单的梯度下降优化器,能够解决一个简单的方程定义的计算自由单子。这里是回购,代码在这里演示。
计算 AST 表示
我们需要一种将计算表示为 AST 的方法。我们可以把它表示为一个图,其中边是进出由运算表示的顶点的张量。有两种边:变量和常数:
以及几种表示 AST 图顶点的操作:
定义了计算图的边(张量)和顶点(操作)之后,我们可以用一组预定义的基本操作来表示任意的计算。
我在这里使用术语张量。它只是一组不同形状的值的数学抽象。标量是一个 0 维张量。向量是一维张量。矩阵是二维张量。而任何具有更高维度的事物,都被简单地称为 n 维张量。在这个例子中,我使用的是 0 维张量,也就是标量。
此外,定义两个额外的类型也很方便:
计算自由单子
下一步是定义一个计算自由单子。我在这里使用的是 cats Scala 库:
我不会在这里深入探讨什么是自由单子。这里有牛逼的文章这里有。本质上,仅仅通过 Op[A]我们就可以使用自由单子将它提升到单子上下文中。这样一来,我们就有办法把 Op[A]组合成一元式了。这种一元组合是这样构建的,它是栈安全的,可以从定义它的地方单独解释。这意味着,反过来,我们可以对同一个计算表达式应用多个解释器。
现在可以使用 Scala for-comprehension 语法,根据计算自由单子定义计算:
上面的函数获取一个映射,其中键是变量或常量名称,值是变量/常量本身。该表达式接受三个变量(x1、x2 和 x3)和一个常数(c1)。
以下是计算的可视化表示:
((x1 -x2) + x3)c1((x1 -x2) + x3)*c1
数值梯度解释器
这里的数字梯度是在维基百科文章中描述的意义上使用的。当我们有一个依赖于多个输入变量的计算表达式时,就可以计算每个输入变量的偏导数。计算这种偏导数的最简单的方法是简单地将初始的一组值输入到计算中并得到输出结果,然后输入相同的初始的一组值,但是对于我们正在计算导数的变量,该值增加了一些小的增量。计算出两个输出值后,我们可以将它们相减,然后除以上一步中使用的增量。根据定义,这是一个偏导数。
我们可以立即尝试一个简单的表达式:
这看起来工作得很好,但是从性能的角度来看并不是很好。如果我们有大量的输入张量,那么我们必须对张量中的每个标量(项)进行两次解释。如果我们能够首先解析地计算导数,然后通过使用矢量化张量运算在一次运行中计算导数,那将会好得多(关于此的更多细节在此)。
分析梯度解释器
似乎我们可以将链规则应用于计算图,并在单个解释器运行中计算所有输入变量的偏导数(在神经网络应用中称为反向传播)。这是解释器正在做的事情:
正如你所看到的,它有更复杂的实现,但它能够在一次解释运行中计算所有的偏导数。让我们尝试一下,看看它是否与 6 个不同的数值解释器执行计算的结果相匹配:
如您所见,不仅结果与使用数值梯度解释器获得的结果相匹配,而且精度更高,并且是在单次解释器运行中计算的。
梯度下降优化器
在我们的 dispose 中有了梯度计算解释器,我们可以很容易地创建一个优化器,它使用梯度下降来最小化函数值。对于给定的成本函数,这在求解方程或训练机器学习模型时非常有用。
让我们立即对同一个表达式进行尝试,看看它是否有效:
如您所见,optimizer 找到了这样一组输入变量,因此表达式值几乎为零,这是非负定义表达式的最小可能值。
结论
我希望你也觉得玩偏导数和梯度下降很有趣,用自由单子以函数的方式表达。我曾经用 Python 实现过同样的方法,但是实现起来更麻烦。
梯度下降——初学者指南
原文:https://towardsdatascience.com/gradient-descent-a-beginners-guide-fa0b5d0a1db8?source=collection_archive---------6-----------------------
简介:
最近,在我的课程中,我对整个科学领域的进步感到敬畏。在仅仅十年的时间里,我们已经彻底改变了我们看待机器能力的方式,我们构建软件的方式等等。十年前看似不可能的任务现在变得触手可及,不费吹灰之力。长话短说,我们让机器思考了!!听起来很酷,不是吗?
人工智能已经真正进入主流意识。这些天来,每个人在日常生活中都听到或读到过“机器学习”这两个神奇的词。但是我们中的任何人对人工智能到底是什么理解得有多清楚呢?虽然,让机器思考和学习的想法听起来很吸引人,而且势不可挡,对于像我这样有抱负的数据科学家来说,让我们的头脑转起来;很少有人理解或知道一些导致机器学习的基本概念。在这篇博客文章中,我只是简单地把我对最重要和最基本的技术之一的理解放在许多机器学习算法的核心——梯度下降。
任何机器学习算法最关键的部分之一就是优化。如何让自己的学习算法学得更快?梯度下降是机器学习中最有效的优化算法之一。我们很多人都非常熟悉什么是梯度下降,但当谈到理解它时,我们所有人都经历过看到可怕的数学方程和图形的过程,看起来像是
Source: Google
Source: Google
别担心,比看起来容易!
正如克里斯·派恩所说,“有时候你唯一能控制的就是视角。你无法控制自己的处境。但你可以选择如何看待它。”
现在,让我们换个角度来看上面的图,就像这样-
现在,为了理解梯度下降,让我们想象这条河从山顶开始的路径。梯度下降的工作正是河流的目标;到达山的最底部。现在,正如我们所知,地球上有一个重力,因此河流将继续向下流动,直到它到达山脚。在这里,我们会做一些假设,说这座山的形状将会是这样的,河流不会在任何地方停留,而是直接到达山脚。在机器学习中,这是我们渴望的理想情况,你可以说我们已经实现了我们的“全局最小值”(在这个类比中,这意味着我们已经到达了“山脚”)。).然而,在现实生活中,情况并非如此。从山的角度来看,河流在向下流动的过程中可能会遇到很多坑,水有可能被困在坑里而无法向下流动。在机器学习术语中,这被称为“局部最小值”,这对我们的任何学习算法都是有害的。梯度下降容易达到这样的局部最小值,并且不能收敛。然而,当山区地形以这样一种特殊的方式设计时,即碗形(在机器学习中,我们将这种函数称为凸函数),那么我们保证会到达全局最小值(foothill)。现在,当谈到梯度下降时,有两个要点:初始值和学习率。为了给出一个大概的概念,我们知道,根据河流最初的源头,它会沿着不同的路径到达山麓丘陵。此外,根据河流的速度(学习速度),你可能会以不同的方式到达山脚。这些值对于决定你是到达山脚(全局最小值)还是被困在坑里(局部最小值)很重要。
如上所述,地球引力是促使河水向下流动的主要原因之一。可悲的是,在编码/数学中,我们没有利用地球引力的杠杆作用!!因此,为了克服这一点,我们需要转向数学,需要知道两种方法来帮助我们走向山脚。我们通过计算 1)给出坡度方向的梯度和 2)计算我们的步长(即河流在特定方向上需要移动多少单位)
现在,让我们考虑梯度下降的公式:
从上面的公式来看,有两件事是我们可以自行设定的;α和ɵ.的当前位置这里我们唯一需要学习的是,如何计算梯度?为了计算一个函数对于一个点ɵ的梯度,我们必须对这个函数关于ɵ.求导一次让我们通过一个例子来理解如何做到这一点:
考虑一个函数:
f(x,y) = x + y
-我们设置 x = 2 和 y = 6 的初始值
-函数的输出是 8
-这里的问题是,如何调整输入值以减少输出?让我们从对上述函数的输入进行微分开始;x 和 y:
这些导数可以被认为是每个输入上的力,因为我们希望将输出拉得尽可能小;力告诉我们 x 和 y 想要如何改变来减少输出。
让我们看看更新规则在上面的计算中是如何工作的(假设α= 0.001)
这直觉上是有道理的!为了减少函数的输出,我们需要用一个大小为 1 的正力来调整输入 x 和 y。例如,将 x 的值从 2 更改为 1.999 将得到小于 8 的输出 7.99,同样,将 y 的值从 6 更改为 5.999 将得到小于 8 的输出 7.998!!梯度下降算法的下一个重要特征是它是一个迭代算法!意思是,我们重复上述步骤,直到收敛。
因此,如果我们重复上述过程 4000 次,我们将得到 x = -2 和 y = 2.0 的值,从而得出函数 f(x,y) = 0 的输出。所以我们得到了 x 和 y 的期望值,这使得我们的函数给出最小值 0。这是梯度下降算法背后的直觉——一种“最成功”的优化技术,是大多数机器学习算法的核心。我告诉过你,这比看起来容易,只是为了让事情变得简单,我们用了一个简单的低维例子。在现实中,我们将处理非线性、高维函数,在这些函数中不可能通过手动分析来解决任何问题。然而,这种方法在那里是完全一样的!
这有意义吗?是吗?没有吗?虽然这篇文章的目的是帮助初学者获得梯度下降背后的工作直觉,但它绝不是一个全面的概述。在那之前,保持冷静,不断创新!
最后,正如我的朋友戈苏丁所说的“吉特·k·阿恩吉!”(会赢)
梯度下降算法及其变体
原文:https://towardsdatascience.com/gradient-descent-algorithm-and-its-variants-10f652806a3?source=collection_archive---------0-----------------------
Figure 1: Trajectory towards local minimum
优化是指最小化/最大化一个由 x 参数化的目标函数 f(x) 的任务。在机器/深度学习术语中,它的任务是最小化由模型参数 w ∈ R^d.优化算法(在最小化的情况下)参数化的成本/损失函数 J(w) 具有以下目标之一:
- 找到目标函数的全局最小值。如果目标函数是凸的,即任何局部最小值都是全局最小值,这是可行的。
- 找到目标函数在其邻域内的最低可能值。如果目标函数不像大多数深度学习问题那样是凸的,通常就是这种情况。
有三种优化算法:
- 非迭代优化算法,仅求解一个点。
- 本质上是迭代的优化算法,并且收敛到可接受的解决方案,而不管参数初始化,例如应用于逻辑回归的梯度下降。
- 本质上是迭代的优化算法,应用于一组具有非凸成本函数的问题,如神经网络。因此,参数的初始化对于加快收敛速度和降低错误率起着至关重要的作用。
梯度下降是机器学习和深度学习中最常见的优化算法。它是一种一阶优化算法。这意味着在对参数进行更新时,它只考虑一阶导数。在每次迭代中,我们在目标函数 J(w) w.r.t 的梯度的相反方向上更新参数,其中梯度给出最陡上升的方向。我们在每次迭代中达到局部最小值的步长由学习速率α决定。因此,我们沿着斜坡的方向下山,直到我们到达一个局部最小值。
在本文中,我们将介绍梯度下降算法及其变体:批量梯度下降、小批量梯度下降和随机梯度下降。
让我们先看看梯度下降是如何对逻辑回归起作用的,然后再详细讨论它的变体。为了简单起见,我们假设 logistic 回归模型只有两个参数:权重 w 和偏差 b 。
1.将重量 w 和偏差 b 初始化为任意随机数。
2.为学习率α选择一个值。学习率决定了每次迭代的步长。
- 如果α非常小,则需要很长时间才能收敛,并且计算量很大。
- 如果α很大,它可能无法收敛并超过最小值。
因此,针对不同的α值绘制成本函数,并选择恰好在第一个不收敛的值之前的α值,这样我们就有了一个收敛的非常快速的学习算法(见图 2)。
Figure 2: Gradient descent with different learning rates. Source
- 最常用的费率有: 0.001,0.003,0.01,0.03,0.1,0.3 。
3.如果数据的比例非常不同,请确保对数据进行缩放。如果我们不缩放数据,水平曲线(等高线)会更窄更高,这意味着需要更长的时间来收敛(见图 3)。
Figure 3: Gradient descent: normalized versus unnormalized level curves.
调整数据,使μ = 0,σ = 1。下面是每个示例的缩放公式:
4.在每次迭代中,取成本函数 J(w) w.r.t 每个参数(梯度)的偏导数:
更新方程是:
- 为了便于说明,我们假设我们没有偏见。如果 w 的当前值的斜率为> 0 ,这意味着我们处于最优 w* 的右边。因此,更新将是负的,并将开始接近最佳值 w *。然而,如果它是负的,更新将是正的,并将增加当前值 w 以收敛到最优值 w *(见图 4):
Figure 4: Gradient descent. An illustration of how gradient descent algorithm uses the first derivative of the loss function to follow downhill it’s minimum.
- 继续该过程,直到成本函数收敛。也就是说,直到误差曲线变得平坦不变。
- 此外,在每次迭代中,步长将位于产生最大变化的方向,因为它垂直于每步的高程曲线。
现在让我们讨论梯度下降算法的三种变体。它们之间的主要区别是我们在计算每个学习步骤的梯度时使用的数据量。它们之间的权衡是梯度的精度与执行每个参数更新(学习步骤)的时间复杂度。
批量梯度下降
批量梯度下降是指在对参数进行更新时,我们对每次迭代的所有示例进行求和。因此,对于每次更新,我们必须总结所有示例:
for i in range(num_epochs):
grad = compute_gradient(data, params)
params = params — learning_rate * grad
主要优势:
- 我们可以在训练时使用固定的学习率,而不用担心学习率衰减。
- 它具有朝向最小值的直线轨迹,并且如果损失函数是凸的,它保证在理论上收敛到全局最小值,并且如果损失函数不是凸的,它保证收敛到局部最小值。
- 它对梯度有无偏估计。例子越多,标准误差越低。
主要缺点:
- 即使我们可以使用矢量化实现,浏览所有示例仍然会很慢,尤其是当我们有大型数据集时。
- 学习的每一步都是在看完所有的例子之后进行的,有些例子可能是多余的,对更新没有太大帮助。
小批量梯度下降
小批量梯度下降法不是遍历所有样品,而是根据批量大小对少量样品进行汇总。因此,学习发生在每个小批量的 b 示例上:
- 打乱训练数据集以避免预先存在的示例顺序。
- 根据批量大小将训练数据集划分为 b 个小批量。如果训练集大小不能被批大小整除,则剩余的将是它自己的批。
for i in range(num_epochs):
np.random.shuffle(data)
for batch in radom_minibatches(data, batch_size=32):
grad = compute_gradient(batch, params)
params = params — learning_rate * grad
批量大小是我们可以调整的。通常选择 2 的幂,如 32、64、128、256、512 等。其背后的原因是因为一些硬件,如 GPU,在普通批量大小如 2 的幂的情况下,可以实现更好的运行时间。
主要优势:
- 比批处理版本快,因为它经历的例子比批处理(所有例子)少得多。
- 随机选择例子将有助于避免多余的例子或非常相似的例子,对学习没有太大帮助。
- 利用批量大小< size of training set, it adds noise to the learning process that helps improving generalization error.
- Even though with more examples the estimate would have lower standard error, the return is less than linear compared to the computational burden we incur.
The main disadvantages:
- It won’t converge. On each iteration, the learning step may go back and forth due to the noise. Therefore, it wanders around the minimum region but never converges.
- Due to the noise, the learning steps have more oscillations (see figure 4) and requires adding learning-decay to decrease the learning rate as we become closer to the minimum.
Figure 5: Gradient descent: batch versus mini-batch loss function
With large training datasets, we don’t usually need more than 2–10 passes over all training examples (epochs). Note: with batch size b = m (训练样本数),我们得到批量梯度下降。
随机梯度下降
随机梯度下降(SGD)不是遍历所有示例,而是对每个示例(xi,yi).)执行参数更新因此,学习发生在每一个例子上:
- 打乱训练数据集以避免预先存在的示例顺序。
- 将训练数据集划分为 m 个示例。
for i in range(num_epochs):
np.random.shuffle(data)
for example in data:
grad = compute_gradient(example, params)
params = params — learning_rate * grad
它分享了小批量版本的大部分优点和缺点。以下是特定于 SGD 的选项:
- 与有助于改善泛化误差的小批量相比,它给学习过程添加了更多的噪声。然而,这将增加运行时间。
- 我们不能在 1 个例子上使用矢量化,速度变得非常慢。此外,由于我们在每个学习步骤中仅使用一个示例,因此差异变得很大。
下图显示了梯度下降的变量及其朝向最小值的方向:
Figure 6: Gradient descent variants’ trajectory towards minimum
如上图所示,与小批量相比,SGD 方向噪音很大。
挑战
以下是关于梯度下降算法及其变体(主要是批处理和小批处理)的一些挑战:
- 梯度下降是一种一阶优化算法,这意味着它不考虑成本函数的二阶导数。然而,函数的曲率影响每个学习步骤的大小。梯度测量曲线的陡度,而二阶导数测量曲线的曲率。因此,如果:
- 二阶导数= 0→曲率呈线性。因此,步长=学习率α。
- 二阶导数> 0 →曲率向上。因此,步长< the learning rate α and may lead to divergence.
- Second derivative < 0 → the curvature is going downward. Therefore, the step size >即学习速率α。
结果,看起来对梯度有希望的方向可能不是这样,并且可能导致学习过程变慢或者甚至发散。
- 如果 Hessian 矩阵具有较差的条件数,即最大曲率的方向比最小曲率的方向具有更大的曲率。这将导致代价函数在某些方向上非常敏感,而在另一些方向上不敏感。因此,它会使梯度变得更难,因为看起来对梯度有希望的方向可能不会导致成本函数的大变化(见图 7)。
Figure 7: Gradient descent fails to exploit the curvature information contained in the Hessian matrix. Source
- 梯度 gTg 的范数应该随着每个学习步骤缓慢降低,因为曲线变得越来越平坦,并且曲线的陡度将降低。然而,我们看到,由于曲线的曲率,梯度的范数在增加。尽管如此,即使梯度的标准在增加,我们也能够实现非常低的错误率(见图 8)。
Figure 8: Gradient norm. Source
- 在小维度中,局部极小是常见的;然而,在大尺寸中,鞍点更常见。鞍点是指函数在某些方向上向上弯曲,在其他方向上向下弯曲。换句话说,鞍点从一个方向看起来像最小值,从另一个方向看起来像最大值(见图 9)。当 hessian 矩阵的至少一个特征值为负,而其余特征值为正时,会发生这种情况。
Figure 9: Saddle point
- 如前所述,选择一个合适的学习速度是很难的。此外,对于小批量梯度下降,我们必须在训练过程中调整学习速率,以确保它收敛到局部最小值,而不是在它周围徘徊。计算学习率的衰减率也很困难,并且随着不同的数据集而变化。
- 所有参数更新具有相同的学习率;然而,我们可能希望对一些参数进行更大的更新,这些参数的方向导数比其他参数更符合朝向最小值的轨迹。
原载于 2017 年 12 月 21 日imaddabbura . github . io。
梯度下降算法和自适应学习率调整方法
原文:https://towardsdatascience.com/gradient-descent-algorithms-and-adaptive-learning-rate-adjustment-methods-79c701b086be?source=collection_archive---------0-----------------------
这里有一个快速简明的总结供参考。更多详细解释请阅读:http://ruder.io/optimizing-gradient-descent/
批量梯度下降
普通梯度下降,也称为批量梯度下降,计算整个训练数据集的成本函数相对于参数θ的梯度。
随机梯度下降
相反,随机梯度下降(SGD)对每个训练示例 x(i)和标签 y(i)的执行参数更新
小批量梯度下降
小批量梯度下降最终取两者之长,对 n 个训练样本的每一个小批量进行更新。
挑战
然而,普通的小批量梯度下降并不能保证良好的收敛性,但也带来了一些需要解决的挑战:
- 选择一个合适的学习速度可能很困难。学习率太小会导致收敛速度非常慢,而学习率太大会阻碍收敛,并导致损失函数在最小值附近波动,甚至发散。
- 学习率时间表[ 11 ]尝试通过例如退火来调整训练期间的学习率,即根据预定义的时间表或当各时期之间的目标变化低于阈值时降低学习率。然而,这些时间表和阈值必须提前定义,因此无法适应数据集的特征[ 10 ]。
- 此外,相同的学习率适用于所有参数更新。如果我们的数据很稀疏,并且我们的要素具有非常不同的频率,我们可能不希望将所有要素更新到相同的程度,而是对很少出现的要素执行更大的更新。
- 最小化神经网络常见的高度非凸误差函数的另一个关键挑战是避免陷入其众多次优局部最小值。Dauphin 等人[ 19 ]认为,困难实际上不是来自局部最小值,而是来自鞍点,即一个维度向上倾斜而另一个维度向下倾斜的点。这些鞍点通常被相同误差的平台所包围,这使得 SGD 很难逃脱,因为梯度在所有维度上都接近于零。
梯度下降优化算法
动力
SGD 在穿越峡谷时有困难,峡谷是指表面在一个维度上比另一个维度上弯曲得更陡峭的区域,这在局部最优解附近很常见。在这些场景中,SGD 在峡谷的斜坡上振荡,同时沿着底部朝着局部最优值缓慢前进,如下图所示。这有助于在相关方向上加速 SGD 并抑制振荡
SGD without momentum (left) v/s SGD with momentum
内斯特罗夫加速梯度
Momentum 首先计算当前梯度(图 4 中的蓝色小向量),然后在更新的累积梯度(蓝色大向量)的方向上进行大跳跃,NAG 首先在先前累积梯度(棕色向量)的方向上进行大跳跃,测量梯度,然后进行校正(红色向量),这导致完整的 NAG 更新(绿色向量)。这种预先更新防止我们走得太快,并提高了响应能力,从而显著提高了 RNNs 在许多任务上的性能
图 4:内斯特罗夫更新(来源: G .辛顿的讲座 6c
阿达格拉德
上述方法使更新适应我们的误差函数的斜率,并依次加速 SGD。Adagrad 根据每个参数的重要性调整更新,以执行更大或更小的更新。
我们将 g(t,I)设为目标函数 w.r.t .在时间步长 t 对参数θi 的梯度:
Adagrad 的一个主要好处是,它消除了手动调整学习速率的需要。大多数实现使用默认值 0.01,并保持不变。
Adagrad 的主要缺点是它在分母中累积平方梯度:因为每个增加的项都是正的,所以累积和在训练期间保持增长。这进而导致学习速率收缩,并最终变得无穷小,此时算法不再能够获得额外的知识。
阿达德尔塔
Adadelta [ 6 ]是 Adagrad 的一个扩展,旨在降低其激进的、单调递减的学习速率。不是累积所有过去的平方梯度,而是将累积的过去梯度的窗口限制到某个固定大小的 ww。
RMSprop
RMSprop 和 Adadelta 都是在同一时间独立开发的,因为需要解决 Adagrad 的学习率急剧下降的问题。RMSprop 将学习率除以梯度平方的指数衰减平均值。
圣经》和《古兰经》传统中)亚当(人类第一人的名字
自适应矩估计是当今最流行的方法。
ADAM 计算每个参数的自适应学习率。除了存储像 Adadelta 和 RMSprop 这样的过去平方梯度 vt 的指数衰减平均值之外,Adam 还保持过去梯度 mt 的指数衰减平均值,类似于动量
那达慕
Adam 可以被视为 RMSprop 和 momentum 的组合。我们也看到内斯特罗夫加速梯度(NAG)优于普通动量。因此,Nadam(内斯特罗夫加速自适应矩估计)[ 24 ]结合了 adam 和 NAG。
演职员表:塞巴斯蒂安·鲁德(2016)。梯度下降优化算法综述。arXiv 预印本 arXiv:1609.04747。
梯度下降和加密货币
原文:https://towardsdatascience.com/gradient-descent-and-cryptocurrency-995693ddae6b?source=collection_archive---------7-----------------------
Photo by Pierpaolo Lanfrancotti on Unsplash
我一直在想一个有趣的方式来谈谈我通过 fast.ai 课程学到的一些早期的东西。我几乎要用一篇快速的文章来重新开始随机梯度下降(SGD)的概念,但是我确实喜欢使用类比的文章。类比是看待一个概念的另一种方式,并进一步巩固它在你大脑中的位置。
因此,今天,我将为大家提供一个关于新加坡元的转折和对那些狂热分子来说加密货币美妙世界的一个方面之间的良好联系。
重启的随机梯度下降
在《走向数据科学》中有几篇关于 SGD 的很棒的文章,那些不熟悉它或需要快速回顾的人,我建议搜索并阅读这些文章。我发现这里有几个,这里有几个。
总体想法是改变你的神经网络中权重的值,以便达到局部最小值。这个最小值由一个函数定义,您的目标是优化。学习率是你向那个最小点移动的速度。如果你学得太快,你可能会错过最小值。如果学得太慢,解题的时间可能会太长。数据科学就是要权衡取舍。
在 fast.ai 课程中,我们很早就学习了带重启的 SGD。这种技术有助于模型在第一轮中找到最佳路径。您可以将“重启”方法视为一种在搜索空间中寻找比第一次绕行更好的路径的方法。这里有一张图片可以帮助你想象这一点。
Fig. 1. From fast.ai Lesson 1
在左图中,模型正在经历一次 SGD 过程。在这一旅程中,模型找到了发挥其最大能力和约束的最佳解决方案。在右图中,重启功能通过多次运行 SGD 来利用它。如您所见,有更多的机会达到更好的局部最小值。
这种改进可能是模型中 99%和 99.5%准确性之间的差异!另外,该课程使这个功能非常容易使用,所以我建议检查一下。
现在来看看密码世界。
类比
你们中的一些人认为这是一个延伸的类比,但我真的很喜欢将想法融合在一起。因此,在我开车回家的路上,我一直在听这个关于一家名为 Multicoin Capital 的公司的播客。他们投资于加密团队,他们有很多关于空间现状的有趣的事情要说。
提出的一个话题是他们在考察采用不同智能合同协议的公司时使用的框架。智能合约协议这几个词在这个讨论中无关紧要,所以不要太担心。他们强调了他们的论点,他们认为智能合同领域将有多个赢家,因为有几个维度可能存在局部最大值。他们认为,目前,世界上只有一个地方最大值是以太坊,肯定会发现更多。
为了进一步分析,想想上面的图片(或者向上滚动到它)。这一职能的地形非常崎岖不平——有很深的低谷,也有很高的顶点。在投资的情况下,目标是找到高峰(而不是当我们考虑 ML 时的局部低谷)。
因此,在他们的世界里,他们在这片奇异的土地上搜寻,试图找到那些利用不同特性和技术的公司,从而实现新的局部最优。这些投资者是“重新启动的新币”,试图通过该函数找到本地最大值(即最有机会获胜的公司)。
带重新启动的 SGD 是一种不同的方式来看待如何探索函数空间,以获得 ML 问题的最低错误。在投资领域,人们发现自己也在从事类似的事情——尽管他们寻求的是最高回报。正是通过这种反复试验,我们为自己(和我们有趣的算法)设定了最高的成功概率。
感谢阅读。
梯度下降、反向推进和导数
原文:https://towardsdatascience.com/gradient-descent-back-prop-and-derivatives-5b286bb8d8b5?source=collection_archive---------3-----------------------
我收到了很多人关于梯度下降和反向传播的问题——这里是我对这些概念的 简化解释 ,给你一些关于神经网络是如何训练的直觉!
在训练神经网络时,我们使用梯度下降来降低我们的网络犯的错误总数。梯度下降是一种希尔下降算法。这座山和我们网络预测的“总错误数”一样高。
我们从运行一个循环开始,在每个循环迭代中,我们的目标是减少我们的净错误总数。这就是我们如何计算网络的训练准确度分数。
在正向推进的最后,通过比较我们的预测结果和真实结果,我们知道我们的网络所产生的“总误差量”。(Y 减去 Yhat)。
但是只有在反推步骤中,我们才能看到总误差中有多少是由每个神经元 T21 引起的。在每个神经元犯下的所有小错误之后,加起来成为整个网络的“总错误”。
微分学是我们用来观察事物如何变化的方法:它们变化快吗?慢慢改变?他们到底有没有改变?
当我们对(山坡)进行微分以获得成本函数的导数时,我们确定了我们所处位置的梯度/斜率。我们得到的梯度告诉我们我们在误差山的每个方向上倾斜了多少。这帮助我们小心翼翼地走下错误之山,一步一步地到达谷底,在我们的循环中,我们找到救赎!
我刚刚谷歌了一下,发现了这个很棒的视频…制作得很好,很直观!
可视化梯度下降
原文:https://towardsdatascience.com/gradient-descent-d3a58eb72404?source=collection_archive---------13-----------------------
梯度下降是一种非常强大的算法,是许多现代机器学习算法的基础。我们将涵盖对什么是梯度下降的直观理解,它如何连接到微积分,以及我们如何在数据科学中使用它。
目标
- 使用汽车数据集预测 MPG
- 理解术语残差的含义以及它如何定义我们的成本函数
- 对误差函数求微分以找到最小值
要求
- 以前有机器学习和微积分的经验
入门:下载数据
对于本教程,我们必须做的第一件事是下载我们在示例中使用的数据集。我发现了一个数据集,其中有汽车的 mpg,我将在教程中使用。这里是下载数据集的链接,请跟随。否则,你可以只是跟着视觉。如果您想在本教程的任何一个步骤上得到帮助,请在这里与我预约时间!
下载完成后,我们先来找一个与汽车 MPG 关联度高的变量。正如你在下图中看到的,汽车的重量与汽车每加仑行驶的英里数有很高的(负)相关性。
Weight is in tons
看着这幅图,你可以想象一条线,它能很好地表现数据。让我们在没有机器帮助的情况下做几次尝试来想出一条线。
对我来说,它看起来像是有一个截距与 y 轴大约 45 英里/加仑。同样,看起来它与 x 轴在 5°左右相交。利用这一点,我可以用这个工具画出一条线来表示这些数据。
这又给了我一个方程式 y = -34/5 * x + 45 || 让我们画出这个图,看看它是什么样子:
正如你所看到的,我们的线条很好地表现了数据,但它并不完美…因此,让我们尝试找出一种方法来衡量它与数据的吻合程度…
我们将定义一个叫做残差的东西,它是从我们的直线到我们的点的距离。在这种情况下,我们可以想象,我们想要最小化从每个点到我们的线的距离,然后最后,我们想要选择总体上最接近所有点的线。
Residuals in Red
这里我们可以看到残差是每个点到预测线的距离。我们可以对所有残差的绝对值求和,然后用这个来看看我们的模型表现如何。在这条线的例子中,代表这条线与数据拟合程度的单一值是 115.75。让我们开始玩我们的线,以更好地了解如何尽量减少这种残留。
首先,我们将保持斜率不变,并改变截距。我们可以想象这是如何改变情节的,图例告诉我们剩余分数,这样我们就可以将其与我们的第一行进行比较!
在此图中,您可以看到,只要改变截距,我们的剩余分数就会根据直线的拟合程度而增加或减少!我们可以仔细看看,实际上画出每条线的残差,开始了解最大值或最小值出现在哪里。事实上,我们将把每条线的残差称为损失函数。想通了这一点,我所说的开始变得有意义了。
您可以在这里看到,根据我们改变 y 轴截距的程度,我们会得到不同的残值。而且损失函数有最小值。这意味着我们可以用数值方法找到函数的最小值,这个最小值就是最佳拟合线。
最佳拟合线是最小化所有参数的残差的线
让我们回到之前的等式。它的形式是 *y = m x + b 或者如果你在做线性回归,它会是下面的形式:
我们一直在看,当β_ 1 系数改变时会发生什么。在另一个世界里,我们可以看到β_ 0 是如何改变残差的。在这种情况下,我们会查看改变斜率的残差,并将其最小化。
在一个不同的例子中,你可以假设我们可以从许多不同的变量预测 MPG。然后,可以对这些变量中的每一个进行调整,以最小化残差,从而为所有参数创建最准确的预测。不过,要做到这一点,我们需要非常清楚地定义一个残差函数,以便我们知道我们在测量什么。在我们的二维例子中,这看起来像下面这样(但是记住我们总是可以推广到一个更高维的空间)
既然我们已经清楚地定义了误差函数,我们可以对β_ 0 和β_ 1 进行微分。这将允许我们建立我们的最小化问题,然后利用微积分找到最小残差。
我们现在可以从任意的 B_0 和 B_1 开始,每次把它插入到我们的部分函数中,然后根据我们的部分函数选择一个新的猜测。
每次我们都会根据偏方程是正还是负来选择一个新的猜测。这个跳跃的大小被称为学习率。
这是优化许多机器学习技术的基础,并且表现非常好。为了实现,我会使用一个内置的库,但理解底层的数学总是一个加分。
本教程只是触及了这个主题的表面,但是为了更深入一点,这里有一些我们没有真正谈论过的主题:
凸性——在我们的线性回归问题中,只有一个最小值。我们的误差面是凸。不管我们从哪里开始,我们最终都会达到绝对最小值。一般来说,情况不必如此。梯度搜索可能会陷入局部极小值。有几种方法可以减轻这种情况(例如,随机梯度搜索)。
收敛 —我们没有讨论如何确定搜索何时找到解。这通常是通过寻找迭代间误差的微小变化来实现的(例如,梯度接近零的地方)。
梯度下降——去神秘化
原文:https://towardsdatascience.com/gradient-descent-demystified-bc30b26e432a?source=collection_archive---------2-----------------------
Types of Gradient Descent Algorithms
在本文中,我将详细讨论梯度下降,解释除标准梯度下降算法之外的不同优化算法。
为了讨论各种梯度下降算法,我将使用逻辑回归的损失函数作为要优化的“”函数。
对于那些不知道逻辑回归的人来说,
逻辑回归是一种统计技术,将输入变量(自变量或回归变量)作为连续变量,将输出变量(因变量或回归变量)作为二元变量。就效果而言,输入变量的单位变化会使输出变量的几率乘以一个常数因子。
逻辑回归作为一种分类技术被广泛使用。让我们考虑下面的回归方程,其中响应变量 y 是具有两类的分类变量。
Logistic Regression Equation
为了对对象进行分类,我们将获得对象属于类别“1”的概率。为了预测概率,我们将使用线性模型和逻辑函数的输出:
Finding probability of an example belonging to a class
梯度下降的目的是找出优化给定函数的最佳参数。在逻辑回归算法中,通过最小化以下损失函数找到最佳参数 θ :
Loss function of Logistic Regression (m: number of training examples)
最小化上述函数的最基本和广泛使用的优化技术是 梯度下降。 它是一种求函数最小值的迭代优化算法。为了使用梯度下降找到局部最小值,采取与函数在当前点的梯度的负值成比例的步骤。如果取正方向,算法找到局部最大值,这个过程称为 梯度上升。
Illustration of each iteration of Gradient Descent [Source: Wikipedia]
梯度下降是基于这样的观察:如果多变量函数 F 在点 x 的邻域中被定义并且是可微分的,那么如果从点 x 沿着点 x 处的 F 的负梯度方向前进,函数 F 下降最快。
对于上面定义的损失函数 J ,点 j 处的梯度定义为:
Gradient at a point — ΔJ
上述等式的推导如下所示,[Credits: Avitus
Derivation of Gradient at a point
标准梯度下降算法
标准梯度下降算法定义如下,其中 η 是学习率。
Gradient Descent Algorithm
在最后一次迭代之后,上述算法给出了函数 J 最小的 θ 的最佳值。该算法的缺点在于,在每次迭代中,必须根据 m 个训练示例来计算 m 个梯度。如果训练集非常大,上述算法将是内存低效的,并且如果训练集不适合内存,可能会崩溃。在这种情况下,随机梯度下降算法会很有帮助。
随机梯度下降
与计算真实梯度的传统算法不同,在随机梯度下降算法的迭代中,梯度是针对单个随机选择的训练样本计算的。该算法定义如下。
Stochastic Gradient Descent Algorithm
在每次迭代中,在 1 和 m(训练样本数)之间选择一个随机索引,并且只针对所选索引处的训练样本计算梯度。可以对训练集进行多次遍历,直到算法收敛。如果做到了这一点,就可以在每次传递时打乱数据以防止循环。
当然,这种方法有其优点和局限性。
- 有噪声的更新导致波动(有噪声的近似)。
- 每一步只需要一个例子。
- 可用于在线设置。
- 学习率 η 要慎重选择。
在计算批次梯度和单个示例的梯度之间的折衷是在每个步骤针对多个训练示例(称为“小批次”)计算梯度。
小批量梯度下降
在小批量梯度下降中,在每次迭代中,在 1 和 m 之间选择 z 个随机指数,并在这些随机指数下对训练样本计算梯度。该算法定义如下。
Mini Batch Gradient Descent Algorithm
这比所描述的随机梯度下降法的性能要好得多,因为代码可以利用矢量化库,而不是单独计算每一步。它还可以导致更平滑的收敛,因为在每一步计算的梯度是在更多训练样本上平均的。
动量梯度下降
在这里,我将讨论随机梯度下降算法的一个简单补充,称为动量,它通常比随机梯度下降算法工作得更好更快。动量或带动量的随机梯度下降是一种有助于在正确方向上加速梯度向量的方法(如下所示),从而导致更快的收敛。这是最流行的优化算法之一,许多最先进的模型都是用它来训练的。在深入数学之前,让我们探索动量梯度下降算法背后的思想
SGD without momentum (Source: Genevieve B. Orr)
SGD with momentum (Source: Genevieve B. Orr)
指数加权平均值处理的是数字序列。假设,我们有一些有噪声的序列。对于这个例子,我绘制了余弦函数,并添加了一些高斯噪声。看起来是这样的:
Credits: Vitaly Bushaev
请注意,尽管这些点看起来非常接近,但它们都不共享 x 坐标。对于每个点来说,这是一个唯一的数字。这个数字定义了序列中每个点的索引。
我们想对这些数据做的是,不是使用它,而是想要某种“移动”平均值,这将对数据进行“去噪”,并使其更接近原始函数。指数加权平均值可以给我们一个看起来像这样的图片:
Credits: Vitaly Bushaev
如你所见,这是一个非常好的结果。我们得到的不是有很多噪音的数据,而是更平滑的线,比我们得到的数据更接近原始函数。指数加权平均值用下面的等式定义了新的序列 V:
序列 V 就是上面标为黄色的那个。 β 是另一个超参数,取值从 0 到 1。我用的是 beta = 0.9 以上。这是一个很好的值,最常用于带动量的 SGD。直观上,你可以把 β 想成如下。我们对序列的最后 1 / (1- β) 个点进行近似平均。让我们看看 β 的选择如何影响我们的新序列 v。
如您所见,β值越小,新序列的波动越大,因为我们对更小数量的样本求平均值,因此更接近噪声数据。β值越大,如β =0.98 ,我们得到的曲线越平滑,但它稍微向右偏移了一点,因为我们对大量示例进行了平均(β =0.98 时约为 50)。β = 0.9 在这两个极端之间提供了良好的平衡。
动量梯度下降算法定义如下。
Momentum gradient descent algorithm
内斯特罗夫动量梯度下降算法
内斯特罗夫动量是动量更新的一个略有不同的版本,最近越来越受欢迎。在这个版本中,我们首先看当前动量指向的点,并从该点计算梯度。当你看这幅画时,它变得清晰多了。
内斯特罗夫动量算法定义如下。
Nesterov momentum algorithm formulas
结论
我希望这篇文章能帮助你学习不同类型的关于逻辑回归的梯度下降算法。动量梯度下降实际上是深度学习中最流行的优化算法之一,比更高级的算法使用得更频繁。
我将发表另一篇文章描述先进的梯度下降算法,如 Ada Grad,RMS Prop,Adam 梯度下降等。
请在下面的评论中发表你对这篇文章的看法。
参考
- Coursera 上的高级机器学习课程
- 蒸馏,为什么动量真的起作用
- 走向数据科学
Photo by Toa Heftiba on Unsplash
Python 中的梯度下降
原文:https://towardsdatascience.com/gradient-descent-in-python-a0d07285742f?source=collection_archive---------0-----------------------
当你冒险进入机器学习时,你学习的一个基本方面将是理解“梯度下降”。梯度下降是机器学习算法的支柱。在这篇文章中,我将尝试使用 python 代码来解释梯度下降的基本原理。一旦你掌握了梯度下降法,事情就开始变得更加清晰,并且很容易理解不同的算法。关于这个话题已经写了很多,所以它不会是一个突破性的话题。为了跟随并建立你自己的梯度下降,你需要一些基本的 python 包。要可视化的 numpy 和 matplotlib。
让我们从一些数据开始,更好的是让我们创造一些数据。我们将创建一个带有随机高斯噪声的线性数据。
X = 2 * np.random.rand(100,1)
y = 4+3 * X+NP . random . randn(100,1)
接下来让我们将数据可视化
很明显,Y 和 x 有很好的线性关系。这个数据非常简单,只有一个自变量 x。
你可能在大学学过,一条线可以表达为
Slope of line
然后你可以求解 b 和 m 的方程如下:
Analytical method
这就是所谓的解方程的解析方法。这没有错,但是记住机器学习是关于矩阵编程的。为了机器学习,我可以用一种不同的方式,用机器学习来表达一条直线的方程。我会称 y 为我的假设,表示为 J(θ),称 b 为θ0,m 为θ1。我可以写出相同的等式:
Machine learning way
为了求解θ0 和θ1 的解析方法,我必须编写以下程序:
theta _ best = NP . linalg . inv(X . t . dot(X))。点(X.T)。点(y)
请记住,我在 X 上增加了一个偏差单位,对于 X 上的每个向量都是 1,这是为了便于矩阵乘法求解θ。
你可以看到,如果 X 中的特征数量开始增加,那么 CPU/GPU 执行矩阵乘法的负载就会开始增加,如果特征数量非常大,比如有一百万个特征,那么你的计算机几乎不可能解决这个问题。这就是梯度下降的救援之处。
简单解释一下梯度下降,想象你在一座山上,被蒙上眼睛,你的任务是在没有帮助的情况下从山上下来到平地。你唯一的助手是一个能告诉你离海平面高度的小装置。你的方法是什么?你会开始向某个随机的方向下降,然后问这个小工具现在的高度是多少。如果这个小工具告诉你这个高度,并且它大于初始高度,那么你知道你开始的方向是错误的。你改变方向,重复这个过程。这样反复多次,最后你成功地下来了。
这是机器学习术语的类比:
向任何方向迈出的步伐=学习速度
小工具告诉你身高=成本函数
你脚步的方向=梯度
看起来很简单,但是从数学上来说,我们如何表示它呢?数学是这样的:
其中 m =观察次数
我举一个线性回归的例子。你从一个随机的θ向量开始,预测 h(θ),然后使用上面代表均方误差(MSE)的等式推导出成本。请记住,你试图将成本降至最低,你需要知道你的下一步(或θ)。偏导数有助于找到下一次迭代的θ。
但是等等,现在我们需要计算θ0 和θ1,如何计算,如果我们有多个特征,那么我们会有多个θ。别担心,这里有一个计算θ的通用形式:
其中α=学习率
好了,我们都准备好写我们自己的梯度下降了,虽然一开始看起来很难,但相信我,用矩阵编程只是小菜一碟。
我们需要什么,一个计算成本的成本函数,一个计算新θ向量的梯度下降函数,就是这样,真的就是这样。
让我们从成本函数开始,代码如下:
Cost function
我会在这篇文章的最后分享我的 GitHub 要点,这样你就可以下载并运行代码,但是现在让我们理解一下成本函数。它需要θ,X 和 y,其中θ是一个向量,X 是行向量,y 是向量。你的数据通常是这样的 X 是一个行向量的矩阵,而 y 是一个向量。
记住,你不需要显式调用这个函数,我们的梯度下降方法会在内部调用它,所以让我们来看看梯度下降函数。
Gradient Descend function
它需要三个强制输入 X,y 和θ。你可以调整学习速度和迭代次数。正如我之前说过的,我们从 gradient_descent 函数调用 cal_cost。
让我们试着用梯度下降法来解决我们之前定义的问题。
我们需要找到θ0 和θ1,但是我们需要在梯度下降中传递一些θ向量。我们可以从高斯分布的θ的随机值开始,并且可以是 1000 次迭代和 0.01 的学习率。代码片段是不言自明的。
我们得到θ0 = 4.11 和θ1 = 2.899,分别非常接近于θ0 和θ1 的实际值 4 和 3。但是我们需要迭代 1000 次,用 0.01 的学习率吗?为了回答这个问题,我们需要看看成本是如何随着迭代而变化的,所以让我们针对迭代绘制 cost_history。
看这个图,很明显,在大约 180 次迭代之后,成本没有降低,这意味着我们只能使用 200 次迭代。如果我们放大图表,我们可以注意到这一点。
我们还可以注意到,成本最初下降得更快,然后下降得更慢。
你可以尝试不同的学习率和迭代组合。
如果能看到梯度下降在不同的学习速率和迭代次数下实际上是如何收敛到解的,那就太好了。如果我们能一次看到所有的东西,这将更有意义。
那么为什么要等呢让我们开始吧,让我们画出四种迭代和学习率组合的收敛和成本与迭代的图表
it_lr =[(2000,0.001),(500,0.01),(200,0.05),(100,0.1)]
为了简洁起见,我没有在这里粘贴代码,而只是粘贴图表,请随时查看我的 GitHub 链接上的完整代码。
检查学习率小的情况下收敛到解需要多长时间,而学习率大的情况下收敛得更快。
需要注意的是,你的问题的实际学习速度将取决于数据,没有一个通用的公式来设置它。然而,有一些复杂的优化算法,它们以较大的学习率开始,然后随着我们接近解决方案而慢慢降低学习率,例如 Adam optimizer。
随机梯度下降
你可能听说过这个术语,可能想知道这是什么。理解这一点很简单,在我们的梯度下降算法中,我们对每个观测值逐个进行梯度计算,在随机梯度下降算法中,我们可以随机选择随机观测值。它被称为随机,因为样本是随机选择的(或混洗的),而不是作为一个单独的组(如在标准梯度下降中)或按照它们在训练集中出现的顺序。
小批量梯度下降
在实际操作中,我们使用一种叫做小批量梯度下降的方法。这种方法使用随机样本,但分批进行。这意味着我们不是为每个观察值计算梯度,而是为一组观察值计算梯度,这导致了更快的优化。一种简单的实现方法是混洗观察值,然后创建批次,然后使用批次进行梯度下降。
我们为线性回归实现了梯度下降,但是您也可以为逻辑回归或任何其他算法实现梯度下降。改变的是成本函数和计算梯度的方式。所以我们需要定义我们的成本函数和梯度计算。
这是对梯度下降的简化解释,但实际上你不需要写你自己的梯度下降。有许多复杂的算法可用。
这里是 GITHUB 要点的链接
如果你想看一个运行的例子,请查看谷歌实验室这里
[## 谷歌联合实验室
编辑描述
colab.research.google.com](https://colab.research.google.com/gist/sagarmainkar/5cfa33898a303f895da5100472371d91/notebook.ipynb)
梯度下降:简单解释?
原文:https://towardsdatascience.com/gradient-descent-simply-explained-1d2baa65c757?source=collection_archive---------2-----------------------
This is how the 2D cost function can look when plotted with two 2 independent variables.
我经常被问到这两个问题,那就是“你能解释一下梯度下降吗?”以及“梯度下降在机器学习中是如何体现的?”。
通过我多年的训练,我想我会在这篇博文中分享什么是梯度下降,以及为什么它是机器学习的“基本成分”。
现在我在这里做一个非常重要的假设,那就是读者理解微积分,尤其是 2 阶的微分。
成本函数
对于那些正在学习或已经学习机器学习的人来说,你知道每个机器学习模型都有一个成本函数。简单来说,这是一种确定机器学习模型在给定每个参数的不同值的情况下表现如何的方法。
例如,线性回归模型,参数将是两个系数,β1 和β2。
Linear Regression Model
成本函数将是最小二乘法的总和。
由于成本函数是参数β1 和β2 的函数,我们可以用每个β值绘制成本函数。(即给定每个系数的值,我们可以参考成本函数来了解机器学习模型的表现有多好。)
鉴于有许多参数,你可以想象一旦成本函数确定, 一个多维平面的轮廓被布置出来。 (类似于三维空间中的山区)。
注:这就是很多混乱的地方。基本上我见过很多人被横轴弄糊涂了。他们认为横轴实际上是 Xs,或者独立变量,但这不是真的,因为Xs 将在整个训练阶段保持不变。请记住,在训练阶段,我们的重点是选择参数的“最佳”值(即系数)。
当我们训练模型时,我们试图找到系数的值(对于线性回归的情况,是β),这将使我们的成本最低。换句话说,对于线性回归的情况,我们正在寻找系数的值,该值将把成本降低到最小值,也就是山区的最低点。
“梯度”下降
现在让我们来看看模型的训练阶段。
现在,假设我们将一个代理放入这个多维平面(还记得山区),起始位置是随机给定的(即,为每个系数随机分配一个值)。这个随机分配的起始位置在机器学习界被称为“初始化”,一共是一整个研究领域。
这个代理只能看到一个东西,那就是它所站的点的梯度,也就是给定系数单位变化的成本变化率。梯度的这种直觉是从微积分中的一阶微分得到的。这解释了梯度下降的“梯度”。
渐变“下降”
如果你学习了任何关于梯度下降的材料,你会遇到另一个专业术语,叫做学习率。学习率实际上指的是代理人在“山区”旅行时迈出了多大的一步,意味着我们正在采取的参数的变化有多大。所以如果在站立点坡度很陡,你迈出一大步,你会看到成本大幅下降。
或者,如果梯度小(梯度接近于零),那么即使采取大的步长,假定梯度小,成本的变化也将小。
把所有的放在一起
因此,在梯度下降中,在代理所处的每个点,代理只知道梯度(对于每个参数)和要采取的步长。考虑到梯度和步长,每个参数的当前值将被更新。使用参数的新值,再次重新计算梯度,并与步长一起计算参数的新值。这样不断重复,直到我们达到收敛(我们将在稍后讨论)。给定许多重复的步骤,代理将慢慢下降到山区的最低点。
现在你可能会问为什么代理将移动到最低点,而不是做一个上升。我将留给读者去发现更多,但让我提供一些研究方向。这与成本函数是凸函数以及参数值如何更新有关。
收敛
一旦代理人在许多步骤后意识到成本并没有提高很多,而是停留在非常接近某个特定点(最小值)的位置,从技术上来说,这就是所谓的收敛。最后一步的参数值称为“最佳”参数集(在线性回归模型中,我们有两个 Betas 的“最佳”值)。我们有一个训练有素的模特。
总之,梯度下降是我们计算相关参数的最佳值集的一种方法。
步骤如下:
1-给定梯度,计算参数相对于步长的变化。
2-使用参数的新值,计算新的梯度。
3 —返回步骤 1。
一旦我们达到收敛,这一系列的步骤就会停止。我希望这有助于你理解梯度下降。
所以,让我欢迎你来到梯度下降的世界,如果你足够冒险(我希望你在这篇博客文章之后会这么做),一定要看看 Sebastian Ruder 的这篇博客文章,它讲述了梯度下降算法的其他变体。
希望这篇博文有用。祝您的数据科学学习之旅愉快,请访问我的其他博客文章和 LinkedIn 个人资料。
注:考虑注册我的时事通讯或前往我的网站获取最新消息。
梯度下降,最简单的方法
原文:https://towardsdatascience.com/gradient-descent-the-easy-way-5240ca9a08da?source=collection_archive---------6-----------------------
理解梯度下降的温和而直观的方法。
梯度下降是所有深度学习的核心。这篇文章用简单的细节解释了这种方法的技术细节。
更新:学习和练习强化学习的最好方式是去 http://rl-lab.com
考虑一个系统,它接受一个输入,然后根据给定的参数进行一些计算,然后输出结果。
然后将输出与一些预期结果进行比较,我们希望看到的是输出尽可能接近那些预期结果。
以旧电视机或收音机为例,当有信号时,您可以使用一个按钮来微调设备,以获得最佳的音频/视频,几乎没有或没有噪音。
那么如何用数学方法做到这一点呢?
输出和预期结果之间的差异由我们称之为损失函数的函数来描述(𝓛).
为简单起见,我们将假设系统的损失函数是抛物线形式的:
𝓛 = a𝜃 + b
其中𝜃是微调参数,a 和 b 是一些值。
该损失函数如下图所示:
上图给出了基于参数𝜃.的输出误差量
目的是最小化误差,从图中很容易看出最小误差在曲线的底部(点:𝜃 = 0,𝓛 = 1)。
怎么求误差最小?
通常,解析解是可能的,但当损失函数变得复杂时,这并不总是容易的,因此我们退回到迭代解。
我们进行的方式相当直观,我们改变𝜃,看看𝓛是否减少。我们一直这样做,直到找到𝓛最小值的𝜃值。
我们可以看到,当𝜃从-2 移动到-1.4 时,𝓛下降,这意味着𝜃正朝着正确的方向移动。另一方面,当𝜃从+1.5 移动到+2 时,𝓛增加,这意味着𝜃在向错误的方向移动,它必须向箭头所示的相反方向移动。
现在的问题是如何找到最小化𝓛的𝜃?
显然,我们需要改变𝜃,但改变多少,向哪个方向改变?
正如我们在上面看到的,当我们将𝜃从最低值变化到最高值时(例如:-∞到﹢∞),我们跟踪了𝓛.的变化如果𝓛继续减少,我们继续增加𝜃,否则,如果𝓛开始增加,我们开始减少𝜃,直到我们找到正确的值。这解决了方向问题,但是𝜃应该变化的量呢?
一个简单的解决办法是取𝓛的一小部分变异,我们称之为𝛂.
将所有这些特征混合在一起,我们得到以下公式:
𝜃𝑛₊₁ = 𝜃𝑛 -𝛂 . ∆𝓛
这个公式清楚地表明,𝜃的下一个值,是以前一个值减去𝓛.变化的一个分数为基础的如果𝓛在减少,那么∆𝓛将是 0,-𝛂也是。∆𝓛 > 0 所以𝜃会增加。如果𝓛在增加,那么∆𝓛将会是 0,-𝛂也是。∆𝓛 < 0 所以𝜃会减少。
如何计算∆𝓛?
当然,最直接的方法是∆𝓛 = 𝓛(end) — 𝓛(start),但这需要一些管理。一个更好的方法是计算导数,这将给出𝓛在每一点的变化。
例如,𝓛 = a𝜃 + b 的导数变成了 d𝓛/d𝜃 = 2a𝜃,因此通过插入𝜃的值,我们得到了 d𝓛.对于某个𝜃.,当 d𝓛为零时,𝓛最小
目标现在变成找到给出 d𝓛 = 0 的𝜃
如何选择𝛂?
𝛂通常由经验决定,应该尝试几个值来找到使转换更快的值,但这里仍然有一个问题,即参数的常数(稍后将详细介绍)。
例子
假设𝛂= 0.9,𝓛 = 𝜃,ɛ= 0.00001,这个值告诉我们∆𝓛应该变得多小才能被认为是零。
迭代梯度下降公式后(𝜃𝑛₊₁ = 𝜃𝑛 -𝛂。∆𝓛)我们得到下表。
我们可以看到,为了使∆𝓛小于 0.00001,并且能够找到可接受的𝜃.值,需要 77 次迭代它有点长,这是因为我们有一个恒定的𝛂!
原因是,即使接近最小值时,我们也在走同一步,而事实上,我们应该用更小的步来重新调整下降。
示意性地,梯度下降类似于下图(PS。这不是准确的表示,但它给出了一种直觉)
然而,真正需要的是,当我们接近最小值时,我们必须调整我们的步骤,以确定最小值,并避免绕过它。因此,我们需要类似下面这样的东西:
实现这一点的一种方式是随着我们的继续减少𝛂,例如,随着每次迭代 i 计算因子 f = 1 + (i/10) 然后在梯度下降公式中将𝛂除以 f :
𝜃𝑛₊₁ = 𝜃𝑛 -𝛂/ f 。∆𝓛
这一修改将产生更好的结果,我们只需 8 次迭代就能得到解决方案,如下表所示:
最后,这里有一个 python 代码,它将计算任何损失函数的梯度下降,只要函数 dF(x)中给定了右导数
结论
梯度下降是一种寻找损失函数最小值的便捷工具,在深度学习领域非常有用。
梯度下降与神经进化
原文:https://towardsdatascience.com/gradient-descent-vs-neuroevolution-f907dace010f?source=collection_archive---------3-----------------------
2017 年 3 月,OpenAI 发布了一篇关于进化策略的博文,这是一种已经存在了几十年的优化技术。他们论文的新颖性在于,他们成功地将该技术应用于强化学习(RL)问题背景下的深度神经网络。在此之前,深度学习 RL 模型(通常有数百万个参数)的优化通常是通过反向传播实现的。使用进化策略进行深度神经网络(DNN)优化似乎为深度学习研究人员打开了一个令人兴奋的新工具箱。
本周,优步人工智能研究所发布了一套五篇论文,都聚焦于“神经进化”。术语神经进化指的是通过进化算法优化神经网络。研究人员假设遗传算法是一种训练深度神经网络以解决强化学习问题的有效方法,并且在某些领域优于传统的 RL 方法。
Neuroevolution relates to natural evolution as an airplane relates to a bird. Neuroevolution has borrowed some fundamental concepts from nature, similarly as neural networks, planes, etc.
概观
那么这意味着什么呢?在不久的将来,所有的 DNN,从有监督的到无监督的以及 RL 应用,都会使用神经进化进行优化吗?神经进化是深度学习的未来吗?神经进化到底是什么?在这篇博文中,我将尝试介绍神经进化,并将其与传统的反向传播算法进行比较。我也将尝试回答上述问题,并把神经进化技术放在更大的 DL 图像中。
首先,我将从框架优化问题开始,这是反向传播和神经进化试图解决的核心问题。我还将尝试明确区分监督学习和强化学习之间的区别。
接下来,我将讨论反向传播,并解释它与神经进化的关系。鉴于 OpenAI 和优步人工智能研究所都刚刚发表了关于这项技术的论文,我有很多课题要解决。幸运的是,由于深度学习神经进化处于研究的早期阶段,神经进化的机制仍然是相当容易理解的。
最优化问题
正如在我之前的博文中所讨论的,机器学习模型本质上是函数逼近器。无论是分类、回归还是强化学习,最终目标几乎都是找到一个将输入数据映射到输出数据的函数。您可以使用训练数据来推断参数和超参数,并使用测试数据来验证近似函数在看不见的数据上是否表现良好。
输入可以是手动定义的特征或原始数据(图像、文本等)。)并且输出是分类中的类或标签、回归中的真实值以及强化学习中的动作。在这篇博文中,我们将把函数逼近器的类型限制在深度学习网络中,但同样的讨论也适用于其他模型。因此,需要推断的参数对应于网络中的权重和偏差。“在训练和测试数据上表现良好”通过客观测量来表达,例如分类的对数损失、回归的均方误差(MSE)和强化学习的回报。
因此,核心问题是找到导致最低损失或最高回报的参数设置。简单!给定需要作为网络参数的函数进行优化的优化目标,即损失或回报,目标因此是以优化目标最小化或最大化的方式来调整参数。
为了使这个形象化,让我们用两个例子。在这两种情况下,我们都制定了优化目标。在抛物线的图像中,x 轴代表模型的单个参数,y 轴代表优化目标(如测试数据)。
在下图中,x 轴和 y 轴代表模型的两个参数,z 轴代表优化目标(如测试数据)。
事实上,由于参数的数量以及它们在深度学习网络中的非线性组合,不可能绘制出“优化表面”。然而,同样的想法也适用,优化表面通常是高维的和复杂的,有许多山丘、摇篮、山谷等。
现在的目标是找到一种优化技术,允许我们在优化面上爬行,找到最小值或最大值。请注意,这些曲面的大小和形状与参数的数量有关,无论我们使用的是连续参数还是离散参数,探索所有选项都是不可行的。现在问题变成了如下:给定优化面中的一个随机起点,找到绝对最小值或最大值。
深度神经网络是很好的函数逼近器(甚至在一定程度上是通用函数逼近器),但它们也很难优化。在这种情况下,难以优化意味着很难在“优化面”上找到全局最大值或最小值。在接下来的章节中,我将讨论如何使用梯度下降和神经进化来寻找好的解决方案。
梯度下降
梯度下降(反向传播)的一般思想已经存在了几十年。由于大量的数据、计算能力和新颖的创新,它已经成为优化深度学习模型参数的主要技术。
梯度下降的大致思路是这样的:
-假设你在法国巴黎,你需要到达德国柏林。在这种情况下,欧洲是优化面,巴黎是随机起点,柏林是绝对最小值或最大值。由于你没有地图,你向随机的陌生人询问去柏林的方向。一些随机的陌生人知道柏林在哪里,但其他人不知道,所以虽然大多数时候,你走在正确的方向,但也有可能你会走错方向。只要陌生人是正确的而不是错误的,它就应该是可行的(例如,随机梯度下降,或带有小批次的梯度下降)。
——你朝陌生人给你指的方向走 5 英里(步长或学习速度)。这个过程一直重复,直到你相信你离德国足够近。结果可能是你刚进入德国,离柏林(当地的 optima)很远。没有办法验证你是否达到了你的最终目标,你只能根据你周围的环境(测试损失或奖励)来估计。
Gradient descent: walking around in Europe without a map.
回到两个可视化的例子,你可以想象在抛物线和更复杂的表面的情况下梯度下降是如何工作的。本质上,使用梯度下降,您是在优化曲面上行走。在抛物线的例子中,这很简单,因为你只需要走下斜坡。如果学习率太高,你可能永远无法达到绝对最小值。
The importance of a proper stepsize (image taken from the Cornell course)
在第二个例子中,情况更加复杂。为了达到绝对最小值,你必须克服几座山和几个谷。几个梯度下降变量,试图模仿物理行为,如一个有动量的球滚下表面(如亚当),以避免陷入局部最优。
An example path that gradient descent might take. Notice that depending on the hyperparameters you might get stuck in the initial local minima.
我强烈推荐这篇关于梯度下降变体的博文。它清楚地解释和说明了不同变体之间的差异,以及它们如何解决梯度下降所面临的不同问题。在这个优化问题中经常有几个局部最优解、障碍和不同的路径,不同的梯度下降法通常试图解决一些(或所有这些)问题。如今,亚当乐观主义者似乎是最有影响力的一个。
梯度下降的本质是计算适当的梯度,推动你走向一个好的解决方案。在监督学习中,有可能通过标记数据集相对容易地获得“高质量梯度”。然而,在强化学习中,你只能得到很少的回报,因为随机的初始行为不会带来很高的回报。此外,这种奖励只发生在几次行动之后。虽然分类和回归中的损失是你试图逼近的函数的相对较好的代理,但是强化学习中的回报通常不是你想要学习的行为或函数的非常好的代理。
鉴于强化学习中的梯度并不总是高质量的,进化算法最近被优步和 OpenAI 用于改善学习。
神经进化
神经进化、遗传算法、进化策略都围绕着遗传进化的概念。
当你在 DNN 优化的背景下进行遗传优化时,你从模型的初始群体开始。典型地,模型被随机初始化,并且基于该初始模型导出几个后代。在 DNN 的情况下,你初始化一个模型(就像你平常做的那样),然后你添加小的随机向量,从一个简单的高斯分布中取样,到参数中。这导致模型的云,它们都驻留在优化表面的某个地方。请注意,这是梯度下降的第一个重要区别。您开始(并继续工作)一群模型,而不是一个单一的(点)模型。
从这个原始种群开始,基因优化周期开始。接下来,我将在进化策略的背景下描述遗传优化。进化策略、遗传算法等。关于如何进行遗传优化,所有的方法都略有不同。
Overview of genetic optimisation.
首先,执行健康评估。适应性评估对应于检查模型在优化表面中的位置,并确定哪个模型表现最好(例如,最适合)。有些型号的性能会比其他型号好,这仅仅是因为它们的初始化方式。
接下来,基于健康评估执行选择。在进化策略中,(伪)子代被简化为一个单一的模型,通过适应度评估进行加权。对 DNN 来说,适应度被定义为损失或回报。本质上,你就这样在优化面上走来走去,并利用后代朝着正确的方向前进。请注意,这是梯度下降的第二个主要区别。你不是计算梯度,而是设置多个“天线”,并朝着看起来最好的方向移动。在某种程度上,这类似于“结构化随机”搜索。选择阶段的最终结果是你有一个单一的模型。
接下来,执行再现和组合。具体地,重复与初始阶段相同的过程。基于新选择的‘主要’模型,导出一组新的后代。然后这个过程在这个后代身上继续。
通常,在遗传优化中,突变也被执行以改善后代的多样性。突变的一个例子是改变如何产生不同的后代(即不同参数的不同噪声水平)。
es 的优点之一是可以在不同的核上计算群体中不同模型的适合度评估(核外计算)。适应性评估后需要共享的唯一信息是它们的性能(标量值)以及用于生成模型的随机种子值。因此,不再需要与所有机器共享整个网络。OpenAI 和优步都使用了成千上万的机器来做实验。随着云计算的兴起,运行这些实验变得非常可扩展,并且只受计算能力的限制。
下图展示了 es 和梯度下降之间的两个主要区别。使用多个模型来移动,并且不计算梯度,而是基于它们的性能对不同的模型进行平均。正如优步的研究所示,对群体而不是单一模型进行优化会产生更高的稳健性,并显示出与 DNN 优化的贝叶斯方法的相似性。
Neuroevolution: walking around Europe in a group.
我强烈推荐看看优步博客文章中的精彩插图。这些说明了如何使用 ES 来规避梯度下降面临的一些问题(例如,陷入局部最优)。本质上,进化策略执行梯度近似。虽然当真实梯度可用时,使用真实梯度更好,但当真实梯度只有相对较差的近似可用时,以及当需要探索优化表面时,例如在强化学习场景中,该方法确实显示出前景。
结论
OpenAI 和优步的研究人员能够表明,进化策略的“梯度近似”导致监督学习场景中令人满意的(但不一定是新的最先进的)解决方案。另一方面,他们能够在强化学习场景中展示其方法的高性能(在某些领域可与最先进的技术相媲美)。
神经进化会是深度学习的未来吗?可能不会,但我相信它对困难的优化问题有很好的前景,比如在强化学习场景中。此外,我相信神经进化和梯度下降方法的结合将导致 RL 性能的显著改善。神经进化的一个缺点是训练这些系统需要大量的计算能力,这可能会限制这些技术的民主化。
鉴于著名的研究小组正在关注这些问题,我仍然很高兴看到未来会发生什么!
基于图形的亚马逊产品推荐引擎
原文:https://towardsdatascience.com/graph-based-recommendation-engine-for-amazon-products-1a373e639263?source=collection_archive---------2-----------------------
在我攻读硕士学位期间,我和我的同事为大数据课程做了一个很酷的项目。我们发现了一个最近发布的包含亚马逊产品和评论的数据集,因此我们决定基于这些产品构建一个推荐引擎。我们最初看到了协同过滤论文,它是亚马逊和网飞等多家大公司推荐引擎的基础。然而,我们决定采用另一种方法,在一个大图中表示产品,并在图的边缘捕捉产品交互。在这篇文章中,我将描述我们使用的数据,我们如何建立图表,我们如何评估我们的系统,以及我们的引擎失败的不同情况,以及如何潜在地改进它。
数据
我们在这个项目中使用了两个数据集。你可以从这里下载。第一个数据集包含从 1996 年 5 月到 2014 年 7 月在亚马逊上销售的产品的客户评论。每条评论都有一段用户体验的文字描述,一个有问题的产品的评级,以及一个有用性投票,它代表了这条评论对其他客户的帮助程度。原始数据有 1.428 亿条评论,但是,我们使用了该数据的子集,这样每个产品至少有 5 条评论。我们的子集数据有 4113 万条评论。
Product review sample
- reviewerID —审阅者的 ID,例如 A2SUAM1J3GNN3B
- asin —产品的 ID,例如 0000013714
- 审阅者姓名—审阅者的姓名
- 有帮助性—评价的帮助性等级,例如 2/3
- 审阅文本—审阅的文本
- 总体—产品评级
- 摘要—审核的摘要
- unixReviewTime —查看的时间(unix 时间)
- 审阅时间—审阅的时间(原始)
第二个数据集是产品元数据。它包括产品描述,价格,销售排名,品牌信息和共同购买链接。共同购买链接的划分如下
- 也查看:客户在查看此产品后查看的其他产品
- also _ built:客户购买该产品后购买的其他产品
- buyed _ together:客户与目标产品一起购买(一揽子交易)的其他产品。
Product metadata sample
- asin —产品的 ID,例如 0000031852
- 标题—产品的名称
- 价格—以美元为单位的价格(爬行时)
- imUrl —产品图像的 Url
- 相关—相关产品(也购买、也查看、一起购买、查看后购买)
- 销售等级-销售等级信息
- 品牌——品牌名称
- 类别—产品所属类别的列表。
构建图表
使用上述数据,我们构建了一个图,其中每个节点是一个产品,每个边是两个产品之间的关系。图中的每个节点都有一个权重,用于计算图的边权重。
产品得分
我们使用第一个数据集来计算这个分数。对于一个目标产品,我们得到该产品的所有评论,对于每个评论,我们提取有用性投票和总得分。思维过程如下:总得分越高,产品越好。此外,有用性越高,购买该产品时考虑该评论的人就越多。因此,我们需要建立一个与总体分数和有用性投票成正比的产品分数。两个模型出现了:
- 乘法模型:得分=有用性*总体
- 加法模型:得分= alpha*有用性+ (1-alpha) *总体
我们考虑这两个模型进行评估,看看哪一个表现更好。
图形边缘
使用第二个数据集,我们创建产品之间的边。使用共同购买的链接,我们在目标产品和每个共同购买的产品之间构建边,如下所示:
- 对于 buy _ together 产品,权重=1 的边
- 对于同时购买的产品,权重=2 的边
- 对于同时查看的产品,权重=3 的边
在创建初始边权重之后,我们基于每个节点的乘积分数和初始边权重来计算新的权重。产品 P1 和产品 P2 之间边 E 的新得分如下:
E(P1,P2) =初始边权重(1-产品得分 P1)(1-产品得分 P2)
这样,具有较高产品分数和较好初始交互的产品在图中更接近。
这样,我们构建了一个包含 150 万个节点和 5200 万条边的图。
搜索 K-最近产品
为了找到每个目标产品的推荐,我们搜索 k 个最接近的产品,并将它们返回给用户。
- 首先将产品 A 的所有直接连接添加到候选列表中
- 对于候选列表中的每个项目:
-如果候选列表中没有 K 个项目,则添加它
-否则,只有到产品 A 的距离小于列表中所有产品的最大距离时,才添加它 - 对候选人排序
- 返回前 K 个作为推荐
估价
这就是我们最初陷入困境的地方,不知道如何评估我们的模型。这不是我们训练一个模型并在子集数据上测试它的情况。经过研究,我们发现推荐系统通常用行业中的 A/B 测试来测试,其中业务相关的指标(例如总销售额)在用户的统计代表性样本上被跟踪。我们决定做一个迷你版。我们随机选择了 10 种产品,并考虑了这 4 种型号的建议:
- 乘法模型
- alpha=0.25 的加法模型
- alpha=0.5 的加法模型
- alpha=0.75 的加法模型
- 以 Amazon.com 的亚马逊推荐为基准
我们将这些建议提供给 5 名参与者,并要求他们报告每个目标产品中哪些项目是相关的建议。从那里,我们能够计算相关性分数,作为来自全部样本的全部相关推荐的比率。
Relevancy scores
正如所料,亚马逊的推荐是最相关的(否则我们会成为亿万富翁)。对于我们的模型,加法模型比乘法模型表现更好。经过一些调查,我们发现许多评论的有用性得分为 0,因此无论总得分是多少,产品得分都是 0。
至于相加模型,我们发现,与其中一个参数占主导地位的情况相比,对产品总体得分和有用性赋予相同的权重会产生略好的结果。
个案研究
在我们用于评估的 10 个产品中,我们有一个案例,我们的系统比亚马逊提供了更好的推荐。目标产品是儿童相关产品,我们的模型给出了 4 个儿童相关产品,而亚马逊给出了 2 个儿童相关产品和 3 部手机。
在另一个案例中,目标产品是迈克尔·杰克逊的音乐专辑。亚马逊推荐了同一位艺术家的其他音乐专辑。我们的系统确实推荐了其他音乐专辑,但它们来自不同的艺术家。
此外,有一次我们的系统没有给出任何建议。这是因为选择的产品与任何其他产品都没有优势,因此搜索无法找到任何可推荐的产品。
进一步改进
如果有更多的时间在这个项目上工作,我们有几个想法要进一步实施。其中之一是对评论文本执行 NLP,以从每个评论中提取情感。我们会根据评论的积极或消极程度来打分。这将导致我们计算不同的产品得分函数。我们可以通过使用元数据数据集中给出的产品在其类别中的排名来进一步提高产品得分。
另一种可能性是为每个产品添加一个类别特性。通过介绍类别是如何相似的,我们确保没有产品是没有边连接的,因为这将在相似类别的产品之间创建新的边。
评估方面,我们可以添加更多的参与者和更多的产品,以更好地评估我们产品的相关性。这将通过创建一个为用户提供选择建议的应用程序来简化。
这种方法的优点是只需要构建一次图。之后,只需向其他产品添加节点和边,就可以非常容易地向其中添加产品。此外,搜索算法是在线功能,在返回推荐方面速度很快。
谢谢你。
这篇文章最初发表在我的博客
图形嵌入——综述
原文:https://towardsdatascience.com/graph-embeddings-the-summary-cc6075aba007?source=collection_archive---------2-----------------------
本文介绍了什么是图嵌入,它们的用途,以及最常用的图嵌入方法的比较。
Pixabay — geralt
raphs 通常用于不同的实际应用中。社交网络是人们相互追随的大型图表,生物学家使用蛋白质相互作用的图表,而交流网络本身就是图表。他们在文本挖掘领域使用单词共现图。对在图上执行机器学习的兴趣正在增长。他们试图预测社交媒体中的新友谊,而生物学家则预测蛋白质的功能标签。对图表的数学和统计操作是有限的,并且将机器学习方法直接应用于图表是具有挑战性的。在这种情况下,嵌入似乎是一种合理的解决方案。
什么是图嵌入?
图嵌入是属性图到一个向量或一组向量的变换。嵌入应该捕获图的拓扑、顶点到顶点的关系,以及关于图、子图和顶点的其他相关信息。嵌入器编码的属性越多,在以后的任务中可以检索的结果越好。我们可以大致将嵌入分为两组:
- 顶点嵌入:我们用它自己的矢量表示对每个顶点(节点)进行编码。当我们想要在顶点级别上执行可视化或预测时,例如 2D 平面中的顶点的可视化,或者基于顶点相似性的新连接的预测,我们将使用这种嵌入。
- 图嵌入:这里我们用一个向量来表示整个图。当我们想要在图表水平上进行预测时,以及当我们想要比较或可视化整个图表时,例如化学结构的比较时,使用这些嵌入。
稍后,我们将介绍第一组中的一些常用方法(DeepWalk、node2vec、SDNE ),以及第二组中的 graph2vec 方法。
为什么我们使用图嵌入?
图形是一种有意义且易于理解的数据表示形式,但是需要图形嵌入有几个原因:
- 图上的机器学习是有限的。图由边和节点组成。那些网络关系只能使用数学、统计学和机器学习的特定子集,而向量空间有更丰富的方法工具集。
- 嵌入是压缩的表示。邻接矩阵描述了图中节点之间的连接。它是一个|V| x |V|矩阵,其中|V|是图中节点的数量。矩阵中的每一列和每一行代表一个节点。矩阵中的非零值表示两个节点相连接。使用邻接矩阵作为大型图的特征空间几乎是不可能的。想象一个有 1M 个节点和 1M×1M 的邻接矩阵的图。嵌入比邻接矩阵更实用,因为它们将节点属性打包在一个维数更小的向量中。
- 向量运算比图形上的可比运算更简单更快。
挑战
嵌入方法需要满足更多的要求。这里我们描述了嵌入方法面临的诸多挑战中的三个:
- 我们需要确保嵌入很好地描述了图的属性。它们需要表示图形拓扑、节点连接和节点邻域。预测或可视化的性能取决于嵌入的质量。
- 网络的大小不应该降低嵌入过程的速度。图通常很大。想象一下拥有数百万人的社交网络。一个好的嵌入方法需要在大型图上是有效的。
- 一个重要的挑战是决定嵌入维度。较长的嵌入比排序嵌入保留了更多的信息,但也带来了更高的时间和空间复杂度。用户需要根据需求做出取舍。在文章中,他们通常报告说 128 到 256 之间的嵌入大小对于大多数任务来说是足够的。在方法 Word2vec 中,他们选择了嵌入长度 300。
Word2vec
在我们介绍嵌入图的方法之前,我将讨论 Word2vec 方法和 skip-gram 神经网络。它们是图形嵌入方法的基础。如果想更好的理解,建议查看这个优秀教程或者这个视频。
Word2vec 是一种将单词转换成嵌入向量的嵌入方法。相似的词应该有相似的嵌入。Word2vec 使用 skip-gram 网络,这是一种具有一个隐藏层的神经网络。跳跃语法被训练来预测句子中的相邻单词。这个任务被称为假任务,因为它只是在训练阶段使用。网络在输入端接受该单词,并进行优化,使其能够以很高的概率预测句子中的相邻单词。下图显示了输入单词(标有绿色)和预测单词的示例。通过这个任务,作者实现了两个相似的单词具有相似的嵌入,因为具有相似含义的两个单词很可能具有相似的邻近单词。
The word colored with green is given to the network. It is optimized to predict the word in the neighborhood with higher probability. In this example, we consider words that are the most two places away from the selected words.
下图所示的 skip-gram 神经网络具有输入层、一个隐藏层和输出层。网络接受独热编码字。独热编码是长度与单词字典相同的向量,并且除了 1 之外全是 0。第一个是编码单词在字典中出现的位置。隐藏层没有激活功能,其输出呈现单词的嵌入。输出层是预测邻域单词的 softmax 分类器。关于 skip-gram 的更多细节可以在之前提到的教程 I 中找到。
Skip-gram neural network
我将介绍四种图形嵌入方法。其中三个嵌入节点,而一个用一个向量嵌入整个图。他们在三种方法中使用了 Word2vec 的嵌入原理。
顶点嵌入方法
我将介绍三种在图中嵌入节点的方法。选择它们是因为它们通常在实践中使用并且通常提供最好的结果。在我们开始之前,我可能会提到节点嵌入的方法可以分为三大类:因式分解方法、随机漫步方法和深度方法。
深度行走使用随机行走产生嵌入。随机游走从一个选定的节点开始,然后我们从当前节点移动到随机邻居,移动了定义的步数。
该方法基本上包括三个步骤:
- 采样:用随机漫步对一个图进行采样。很少从每个节点进行随机行走。作者表明,从每个节点进行 32 到 64 次随机行走就足够了。他们还表明,好的随机漫步有大约 40 步的长度。
- 训练 skip-gram: 随机游走与 word2vec 方法中的句子相当。skip-gram 网络接受随机行走中的一个节点作为独热向量作为输入,并最大化预测邻居节点的概率。它通常被训练来预测大约 20 个邻居节点——左侧 10 个节点和右侧 10 个节点。
- 计算嵌入:嵌入是网络的一个隐层的输出。DeepWalk 计算图中每个节点的嵌入。
Phases of DeepWalk approach
深度行走方法随机地执行随机行走,这意味着嵌入不能很好地保持节点的局部邻域。Node2vec 方法解决了这个问题。
Node2vec 是 DeepWalk 的修改版,与随机漫步的区别很小。它有参数 P 和 Q。参数 Q 定义随机行走发现图中未发现部分的可能性,而参数 P 定义随机行走返回前一个节点的可能性。参数 P 控制节点周围微观视图的发现。参数 Q 控制更大邻域的发现。它推断社区和复杂的依赖关系。
The figure shows probabilities of a random walk step in Node2vec. We just made a step from the red to the green node. The probability to go back to the red node is 1/P, while the probability to go the node not connected with the previous (red) node 1/Q. The probability to go to the red node’s neighbor is 1.
嵌入的其他步骤与 DeepWalk 方法相同。
结构化深度网络嵌入(SDNE) 与前两种方法没有任何共同之处,因为它不执行随机行走。我之所以提到它,是因为它在不同任务上的表现非常稳定。
它被设计成使得嵌入保持一阶和二阶近似。一阶近似是由边链接的节点之间的局部成对相似性。它描述了本地网络结构的特征。如果网络中的两个节点与边相连,则它们是相似的。当一篇论文引用另一篇论文时,意味着它们涉及相似的主题。二阶接近度表示节点邻域结构的相似性。它捕捉全球网络结构。如果两个节点共享许多邻居,它们往往是相似的。
作者提出了一个自动编码器神经网络,它有两个部分—见下图。自动编码器(左和右网络)接受节点邻接向量,并被训练来重建节点邻接。这些自动编码器被称为普通自动编码器,它们学习二阶近似。邻接向量(邻接矩阵中的一行)在表示连接到所选节点的节点的位置上具有正值。
网络中还有一个被监督的部分——左翼和右翼之间的联系。它计算从左侧和右侧嵌入之间的距离,并将其包括在网络的公共损耗中。训练网络,使得左和右自动编码器得到通过输入上的边连接的所有节点对。距离部分的损失有助于保持一阶近似。
网络的总损耗计算为左右自动编码器的损耗与中间部分的损耗之和。
图形嵌入方法
最后一种方法嵌入整个图形。它计算一个描述图形的向量。我选择了 graph2vec 方法,因为这是我所知道的最好的图形嵌入方法。
Graph2vec 基于使用跳格网络的 doc2vec 方法的思想。它从输入中获得文档的 ID,并被训练以最大化从文档中预测随机单词的概率。
Graph2vec 方法包括三个步骤:
- 从图中采样并重新标记所有子图。子图是出现在所选节点周围的一组节点。子图中的节点距离所选边数不超过。
- 训练跳格模型。图表类似于文档。因为文档是一组单词,所以图是一组子图。在这个阶段,训练跳格模型。它被训练成最大化预测输入图上存在的子图的概率。输入图作为一个热点向量提供。
- 计算嵌入,在输入端提供一个图 ID 作为一个热点向量。嵌入是隐藏层的结果。
由于任务是预测子图,所以具有相似子图和相似结构的图具有相似的嵌入。
其他嵌入方法
我提出了四种基于常用文献的方法。由于这个主题目前非常流行,所以有更多的方法可用。在这里,我列出了其他可用的方法:
- 顶点嵌入方法: LLE,拉普拉斯特征映射,图分解,GraRep,HOPE,DNGR,GCN,线
- 图嵌入方法: Patchy-san、sub2vec(嵌入子图)、WL 核和深度 WL 核
参考
[1] C. Manning,R. Socher,第二讲|词向量表示法:word2vec (2017), YouTube 。
[2] B. Perozzi,R. Al-Rfou,S. Skiena,DeepWalk:社会表征的在线学习(2014),arXiv:1403.6652。
[3]麦考密克。 Word2Vec 教程—跳格模型(2016)http://mccormickml.com。
[4] T. Mikolov,K. Chen,G. Corrado,J. Dean,向量空间中词表征的高效估计(2013),arXiv:1301.3781。
[5] A .纳拉亚南,m .钱德拉莫汉,r .文卡特桑,l .陈,y .刘,s .贾伊斯瓦尔,graph2vec:学习图的分布式表示(2017), arXiv:1707.05005。
[6] P. Goyal,E. Ferrara,图嵌入技术、应用和性能:一项调查(2018), 基于知识的系统 。
[7] D .王,p .崔,w .朱,结构化深度网络嵌入(2016), 第 22 届 ACM SIGKDD 知识发现与数据挖掘国际会议论文集。
[8] A. Grover,J. Leskovec,node2vec:面向网络的可扩展特征学习(2016), 第 22 届 ACM SIGKDD 知识发现与数据挖掘国际会议论文集。
平面测试的 Hopcroft-Tarjan 图的平面性和路径加法
原文:https://towardsdatascience.com/graph-planarity-and-path-addition-method-of-hopcroft-tarjan-for-planarity-testing-c56d2df2b0b3?source=collection_archive---------3-----------------------
给定一个无向图,平面性测试问题是确定是否存在围绕每个顶点的顺时针边序,使得该图可以在没有任何交叉边的平面上绘制。
平面图形在计算几何的许多问题中扮演着核心角色。如果化学结构是平面的,确定化学结构的同构就简单了。另一个例子是当工程师希望在芯片上嵌入组件网络时。元件由导线表示,任何两根导线交叉都会造成短路。这个问题可以通过把网络看作一个图并找到它的平面嵌入来解决。
下面是一些需要的基本概念。一个图 G=(V,E) 是 平面 如果可以把它画在一个平面上,使得除了端点之外没有边相交。这样的图叫做平面嵌入。平面图的一个例子是 K4 ,4 个顶点的完整图形(图 1)。
Figure 1: K4 (left) and its planar embedding (right).
并非所有的图形都是平面的。图 2 给出了两个非平面图的例子。它们被称为 K5 ,五个顶点上的完全图,以及 K_{3,3} ,两个大小为 3 的集合上的完全二部图。无论选择哪种复杂的曲线来表示边,当最后一条边无法在不与其他边交叉的情况下插入时,嵌入它们的尝试总是会失败,如图所示。
Figure 2: K5, the complete graph of 5 vertices, and K_{3, 3}, the complete bipartite graph on two sets of size 3
连接 u 和 v 的连续边序列被称为从 u 到 v 的 G 的路径。如果一条路所有顶点都是不同的,那么这条路是最简单的。从顶点到自身的路径是一条封闭路径。从 v 到 v 带有一条或多条边的闭合路径是一个循环,如果它的所有边都是不同的并且唯一出现两次的顶点是 v 。我们用p:u*** v来表示 p 是 G 中从 u 到 v 的一条路径。
(有向、有根)树 T 是具有一个根 r 的有向图,使得 T 中的每个顶点都可以从 r 到达,没有边进入 r ,并且恰好有一条边进入 T 中的每个其他顶点。关系“ (v,w)是 T 中的一条边”用 v → w 表示。用 v → ** w* 表示关系“T中有一条从 v 到 w 的路径”。如果 v → w , v 是 w 的父, w 是 v 的子。如果 v → ** w* , v 是 w 的祖先, w 是 v 的后代。每个顶点都是自己的祖先和后代。如果 G 是有向图,一棵树 T 是 G 的生成树如果 T 是 G 的子图包含 G 的所有顶点。
一个图的边 (x,y) 的细分是通过创建一个新的节点 z ,并用新的边 (x,z)**(z,y) 替换 (x,y) 得到的。一个图的细分是通过一系列细分操作可以从中获得的任何图。
由于 K5 和 K_{3,3} 是非平面的,显然这些图的细分也是非平面的。因此,有一个子图是 K5 或 K_{3,3} 的子图的图一定是非平面的。这样一个子图被称为对一个 K_{3,3} 或一个 K5 的同胚。图论中的一个著名结果是 Kuratowski 定理,该定理指出,没有一个 K5 或一个 K_{3,3} 的细分也足以证明一个图是平面的。
一般来说,图算法需要一种探索图的系统方法。平面性测试算法使用的最重要和最常用的技术是深度优先搜索。
深度优先搜索 (DFS) 是以特定的方式访问一个图的所有顶点 G 的方法。它从任意选择的顶点 G 作为根节点开始,并继续从当前顶点移动到未探索的相邻顶点。当当前顶点没有未探索的相邻顶点时,遍历回溯到具有未探索的相邻顶点的第一个顶点。请看下图中的 DFS 示例。
Figure 3: An example of graph G and its palm tree T
DFS 到达 G 顶点所使用的边形成了 G 的一棵生成树 T ,称为棕榈树,或 DFS 树。所以这个搜索以某种方式将 G 转换成一个有向图。 T 的根是访问开始的顶点。 T 的边称为树边,而 G 的其余边称为背边,在棕榈树中用虚线表示。深度优先搜索很重要,因为棕榈树中的路径结构非常简单。
如果对于每对顶点 u 和 v , G 包含一条从 u 到 v 的路径,则无向图 G 是连通的。图的连通分支是最大连通子图。
图中的关节顶点是删除后断开图的顶点。如果一个图没有连接顶点,那么它就是双连通的。图的双连通分支是最大双连通子图。
库拉托夫斯基子图是一个子图,它有 K5 或 K_{3,3}的细分。
库拉托夫斯基定理 (库拉托夫斯基【Ku30】)有限图是平面的当且仅当它不包含库拉托夫斯基子图。
狄拉克和舒斯特(1954)对这个定理的证明可以在[BM76]中找到。证明相当冗长,其中两个主要引理和定理的主要证明都使用了矛盾。对顶点数使用归纳法的另一个证明是由于汤姆森(1980) [GT87]。虽然这个证明不是最短或最容易的,但它很有启发性,因为它还产生了关于平面嵌入的其他结果。一个结果是单纯图的平面嵌入的边可以选择为直线的 Fary 定理(其他的是 Tutte 定理和 Whitney 定理)。此外,汤姆森的证明很容易转换成一个平面算法,这是多项式的顶点数。
平面性测试的朴素算法
有人可能会想,上面的 Kuratowski 的优雅定理是否可以用一种简单的方式作为测试图形平面性的标准。答案是肯定的,基于这个定理的朴素算法有指数级的运行时间,如下图。
顶点的度或价是该顶点的关联边数。设 u 为图 G=(V,E) 中度数为 2 的顶点,设 e1 和 e2 为 u 上的边,设 e1=(u,V),e2=(u,w) 。通过“在 u 处平滑”得到的图形,其顶点集合为 V / {u} ,其边集合为 E / {e1,e2} ,加上一条在 v 和 w 之间的新边。细分这个新边将反转 u 处的平滑操作。然后我们有以下结果,这是库拉托夫斯基定理的一个结果:
设 G 为图。对于 E 的每个子集,其移除仅留下一个非平凡分量 H ,通过连续平滑 H 中的价 2 的每个顶点来构建“平滑图” H^{smooth} ,如果 H 是一个循环,则可能除了最后一个顶点之外。如果某个 H^{smooth} 同构于 K5 或 K_{3,3} 那么这个图是非平面的,否则, G 是平面的。
因为有 2^{|E|} 边子集要考虑,这个朴素算法有指数运行时间。
hop croft 和 Tarjan 的路径添加算法
解决平面性问题的最好方法似乎是试图构造给定图的平面嵌入的表示。如果这样的表示能够完成,那么该图是平面的;如果不是,那么这个图是非平面的。一个这样的算法是 Hopcroft 和 Tarjan [HT74]的路径添加方法。他们首先表明平面度测试可以在线性时间内完成。
在给出算法的草图之前,我们可以做一些注释来限制所考虑的图 G 的类别。很明显,一个图是平面的当且仅当它的所有连通分量都是平面的。因此,我们可以假设 G 是连通的。
一个图是平面的当且仅当它的所有双连通分支都是平面的([Be64])。此外,铰接顶点可以在线性时间内找到([HT73],[Ta72]),因此单独嵌入每个双连接组件,然后通过它们的邻接铰接顶点连接它们就足够了。因此,我们可以假设 G 是双连通的。
下面的结果是著名的欧拉定理:
(欧拉 1750)设 G 是一个连通的平面图,设 n,m,f 分别表示 G 的顶点数、边数和面数。然后 n-m+f=2 。
这个定理可以通过对边数 m 的归纳来证明。我们需要的是以下推论:
如果 G 是一个有 n (≥ 3) 个顶点和 m 条边的平面图,那么 m ≤ 3n - 6 。
现在我们准备给出路径加法的概要。
算法示意图
- 统计边数,如果 |E| > 3 |V|- 6 那么它是非平面的(利用上面的推论去掉边太多的图)。
- 应用 DFS,将图形转换成棕榈树 T,并对顶点进行编号。
- 在树中找到一个循环并删除它,留下一组不相连的片段(使用 Auslander,Parter,Goldstein 的算法,[AP61],[Go63])。
- 检查每个零件加上原始循环的平面度(通过递归应用算法)。
- 确定各部分的嵌入是否可以组合,以给出整个图的嵌入。
对算法的每次递归调用都需要找到一个循环,并一次添加一条简单的路径。每一条这样的新路径通过新的边和顶点连接两个旧的顶点(有时整块被翻转过来,围绕着某条线;为了做到这一点,我们需要利用众所周知的 乔丹曲线定理 的一个推论:一条简单的闭合曲线将平面恰好分成两个连通的区域)。这解释了“路径添加方法”的名称。这也解释了使用 DFS 将图形分成简单路径的重要性,这些路径可以组合成平面性测试所需的循环。我将以上面图 3 中的图 G 和图 DFS 树 T 为例进行说明。
Figure 4: First cycle c and disconnected pieces s1 and s2
现在考虑第一个周期 c 。它将由一系列树边组成,后面是 T 中的一个后沿。顶点的编号是这样的,顶点沿着循环按编号顺序排列。所以在这个例子中周期 c 是1→2→3→4→5→8→1。当 c 被拆下后, G 会分成几个相连的块。不属于循环的每个片段将由单个后边缘 (v,w) (本例中的片段 s1 )或树边缘 (v,w) 加上带有根 w 的子树,加上从子树引出的所有后边缘(本例中的片段 s2 )组成。根据乔丹曲线定理,每一个棋子可以走“内”或“外” c 。当我们添加一个部分时,某些其他部分必须从内部移动或“翻转”到外部,或者如果必要的话反之亦然(以保持平面性),直到一个部分不能被添加或者整个图形被嵌入到平面中。该示例没有显示“翻转”情况,但是可以参考文章中的图 4 和图 5 进行说明。对 DFS 的修改将有助于生成路径的顺序,使得一个片段中的所有路径都在任何其他片段中的路径之前生成(在这种情况下 s1 有一个路径,而 s2 有三个路径),并且按照 v 的递减顺序浏览这些片段,其中 v 是路径的起点,如上所述。
Figure 5: Piece s2 after transformation
根据 Jordan 曲线定理,一块必须完全嵌入在 c 的一边。为了嵌入一个片段(比如说 s2 ,我们在其中找到一条路径 p 。我们选择一面,比如左边,在上面嵌入 p 。我们将 p 与之前嵌入的后沿进行比较,以确定 p 是否可以嵌入。如果没有,我们从左向右移动后边缘阻挡 p 的棋子。如果移动棋子后 p 可以嵌入,我们就嵌入。然而,如果我们将棋子从左边移到右边,我们可能必须将其他棋子从右边移到左边。因此可能无法嵌入 p 。如果是这样,我们声明这个图是非平面的。如果 p 可以嵌入,我们尝试通过递归使用算法来嵌入剩余的片段( s2 )。然后我们试着嵌入下一块。在本例中,需要将棋子 s2 转换为棋子S2’,如图 5 所示。
尽管算法的内部工作是基于对输入图的平面表示的搜索,但是没有描述如何实际产生它的平面嵌入。二十年后,Mehlhorn 和 Mutzel 填补了这一空白,描述了如何在测试阶段收集构建平面嵌入所需的信息,这些信息被隐含地用于显示平面性[MM96]。
结论
平面图形和平面性测试在计算几何中的各种问题中起着重要作用,包括地理信息系统、点定位。例如,集成电路的设计需要知道电路何时可以嵌入到平面中。
在 1974 中,Hopcroft 和 Tarjan【H提出了第一个线性时间平面性测试算法。该算法也称为路径添加算法,从一个循环开始,一次添加一条路径。然而,该算法是如此复杂和难以实现,以至于其他几个贡献跟随他们的突破。例如,在[HT74]之后大约二十年,Mehlhorn 和 Mutzel [MM96]发表了一篇论文,阐明了如何构造通过原始 Hopcroft 和 Tarjan 算法发现是平面的图的嵌入。
参考
[AP61] Auslander,l .和 Parter,S. V .,关于平面中的嵌入图,数学杂志。还有械甲怪。10, 517–523, 1961.
图的理论及其应用。伦敦梅图恩,1964 年。
J. A. Bondy,U. S. R. Murty,图论及其应用,北荷兰,1982 年。
[Go63] Goldstein,A. J .,一个测试一个图是否可以嵌入一个平面的有效的和构造性的算法,图论和组合学会议。,合同编号 1858-(21),1963 年。
[GT87]乔纳森·l·格罗斯,托马斯·w·塔克,拓扑图论,威利-Interscience,1987。
【Hhop croft,j .和 Tarjan,r .图操纵的有效算法,Comm. ACM 16,372–378,1973。
[HT74]约翰·霍普克罗夫特;Tarjan,Robert E .,有效的平面性测试,《计算机械协会杂志》21(4):549–568,1974 年。
[Ku30] Kuratowski,c .,关于地形学中的 corbes gauches 问题,数学基础 15,271–283,1930 年。
[MM96]库尔特·梅尔霍恩和佩特拉·穆策尔。,关于 Hopcroft 和 Tarjan 平面性测试算法的嵌入阶段。《算法》,16:233–242,1996 年。
[Ta72] Tarjan,r .,深度优先搜索和线性图算法,SIAM J. Comput。1, 2 146–159, 1972.
图形表示学习
原文:https://towardsdatascience.com/graph-representation-learning-dd64106c9763?source=collection_archive---------3-----------------------
Graph captured on the Floating Piers study conducted in our data science lab.
在使用复杂信息的任何科学和工业领域,图模型普遍用于描述信息。
在图中需要解决的经典问题有:节点分类、链接预测、社区检测等等。
当网络庞大时,分析它们会变得很有挑战性。一般来说,机器学习技术在网络上效果不佳。
因此,考虑到实际的网络结构,要点变成学习网络中节点的特征。这些被称为特征表示或嵌入。因此,任何节点都被描述为一个向量。
目标是将每个节点映射到一个低维空间,同时保留大部分网络信息。
基于这种低维表示,我可以进行任何下游分析。
主要的挑战是,如果与图像、音频或文本相比,网络的结构非常不规则。图像可以被看作是刚性的图形网格。运行机器学习更容易。
相反,图是非欧几里得的:节点的数量是任意的,它们的连接也是任意的。例如,如何将它输入神经网络?这就是为什么我们需要图形嵌入。
node2vec:无监督特征学习
主要思想是找到保持相似性的维度为 d 的节点的嵌入。目标也是嵌入使得附近的节点靠得很近。我需要计算一个节点的邻域,然后运行一个最大化问题,以一种 f(u) 预测邻域 N(u) 的方式计算节点 u 的特征学习。这可以通过 softmax 函数来实现,假设节点的因式分解(独立性)。
邻域的定义可以基于 BFS(宽度优先)或 DFS(深度优先)策略。BFS 提供网络的局部微观视图,而 DFS 提供网络的宏观视图。一个聪明的解决方案是 BFS 和 DFS 的插值。这是一个二阶随机游走,因为我们记得最后访问的节点,并且在每一步我们都要决定是返回最后访问的节点还是继续前往新的节点。本质上,在每一步,我都有三个选择:
- 节点回到更靠近原节点的位置 u
- 与当前节点距离相同的节点相对于 u
- 距离节点更远的节点 u
我可以设置概率 p (返回)和 q (离开)来决定每一步是离 u 远还是近。然后我可以运行随机梯度下降(线性时间复杂度)算法来寻找最佳路径。
基于我如何设置 p 和 q 的值,我可以得到对网络完全不同的解释:随着更大的 q ,我倾向于检测节点的“角色”,随着更小的 q ,我倾向于检测节点的“接近度”。
这是一种独立于任务的特征学习方法,在某种意义上,它不依赖于你对结果的使用。复杂度是线性的。网络的规模。
GraphSAGE:监督特征学习
相反,这种方法是受卷积神经网络的启发,通过将它们从简单网格(图像网格)的处理推广到一般图形。但是如何推广卷积呢?
您可以将图像视为一个图表,其中每个像素都连接(并以某种方式影响)附近的像素。
一种选择是使用图的邻接矩阵(加上节点的可能特征),并将其输入神经网络。问题:输入的数量与网络的规模成线性关系(巨大)。
一个改进是使用子图(例如,定义节点邻域的一片邻近节点)。这个邻域定义了一个计算图,我用它来传播和转换所考虑节点的所有邻居的信息(即属性)。本质上,对于每个节点,计算图是一个不同的神经网络,我可以运行它来学习参数。我有许多神经网络,它们使用相同的一组参数,所以这就像在进行监督学习。
如下所述,整个框架可以方便地以 MapReduce 方式执行,因为这自动避免了计算任务的重复。
本质上,我们定义了图的卷积网络概念。
在 Pinterest 中的实验已经成功地在 3 个 BLN 节点和 17 个 BLN 边上运行。
Graph captured on the Floating Piers study conducted in our data science lab.
这篇报道是关于 2017 年 12 月在波士顿举行的第四届 IEEE BigData 会议上由 Jure Leskovec (与斯坦福大学和 Pinterest)发表的主题演讲。
演讲的完整幻灯片可以在 Jure 的主页上找到:
http://I . Stanford . edu/~ jure/pub/talks 2/graph sage-IEEE _ big data-dec 17a . pdf
图论——基本性质
原文:https://towardsdatascience.com/graph-theory-basic-properties-955fe2f61914?source=collection_archive---------15-----------------------
第三部分——从简单的图表开始
让我们后退一步,以便在图论的基础知识中更进一步。本系列的前一篇文章主要围绕着解释&标注一个简单图形。我们现在将返回来强调一个简单图形的属性,以便为本文的其余部分提供一个熟悉的起点。
simple graph — part I & II example
在之前的文章中,我们将我们的图定义为简单由于四个关键性质: 边是无向的&未加权的;该图不包括多条边&有向回路 。这绝不是所有图形属性的详尽列表,但是,这足以让我们继续我们的旅程。本文将通过介绍关键的图属性,把我们从简单的图带到更复杂的(但相当常见的)图。
常见图表属性
图形,就像它们所代表的物体的动态系统一样,呈现出难以估量的形状和大小;因此,创建一组属性有助于指定唯一的图形属性。让我们检查一下简单图形示例的定义属性:
- 无向边
- 未加权的边
- 排除多条边和循环
无向图与有向图
上例中的边除了连接两个顶点外,没有其他特征。他们明显缺乏方向。
最清晰和最大的图分类形式始于图中的类型的边 。存在两种主要类型的边缘:有方向的和没有方向的。无向图,如示例简单图,是由无向边组成的图。在一个有向图中,或者一个有向图,每个顶点至少有一个输入边&和一个输出边——表示每个边相对于它的两个连接顶点的严格方向。
未加权与加权图形
类似地,加权边仅仅是具有相关数字或值的边,或者称为 权重 (通常以非负整数的形式)。权重值允许对更复杂的问题进行建模,从而通过图形更准确地表示现实生活中的系统。在许多实际应用中,边的权重通常也称为边的成本;图中边权重的实际例子包括测量路径的长度、电缆的容量或穿过特定路径所需的能量。下图为我们的示例图提供了一个快速的视觉向导,如果它包含加权边,该图看起来会是什么样子:
多重边缘和循环
我们的示例图中突出显示的第三个简单属性引入了两个独立的图关系,它们都基于相同的属性:基于顶点关系的图的简单性。
在我们的示例图中,每个顶点有条边连接到另一个顶点——没有顶点通过多条边连接到另一个顶点。此外,没有顶点循环回自身。一个图,如果包含其中一个或两个,多条边&自循环,称为多重图。**
下图通过右图突出了这两个区别:
循环-非循环与循环图
我们之前没有列出这个属性,因为非循环图和循环图都可以算作简单图,但是,图的循环属性是一种重要的分类形式,值得一提。在图论中,一个 圈 是一条由边&个顶点组成的路径,其中一个顶点可以从自身到达;换句话说,如果一个人可以从一个顶点回到自身,而不沿着路径重复(折回)一个边或顶点,那么这个循环就存在。
包含至少一个循环的图称为循环图。没有单圈的图称为无圈图。在下面的示例中,我们将在简单的图表中突出显示多个循环中的一个,同时在右侧展示一个非循环图表:
来源
图论介绍
图论
现在已经对与图相关的关键属性有了基本的了解,是时候跳到一个非常激动人心的图论主题了:网络!在下一篇文章 &中,我们将开始在更深层次上构建对网络的理解——最终将这些原则应用于网络分析。
图论帮助英国变得不那么臭了
原文:https://towardsdatascience.com/graph-theory-helped-the-british-become-less-stinky-de4b439a7784?source=collection_archive---------12-----------------------
这是为那些可能在数据科学环境中使用图论的人解释图论原理的系列文章中的第二篇。第一篇文章,主要讲图论的起源和图的基本性质,这里可以找到。
19 世纪中期的一个 7 月的早晨,伦敦人醒来时闻到一股令人作呕的恶臭。他们不能离开家而不生病。更富裕的人在手帕上涂上香水,走来走去,永远遮住他们的脸。许多穷人离开城镇去农村找工作,因为他们实在无法忍受。毫无疑问,这是英国历史上最卑鄙的事件。
这就是后来被称为 1858 年大恶臭的开始。泰晤士河,被中世纪木制下水道系统直接倾倒的人类排泄物填满了几个世纪,终于得到了它的报复。霍乱肆虐的淤泥被冲上河岸,在异常炎热的夏季温度下晒成了一股恶臭,方圆数英里都无法逃脱。
伦敦金融城公司(City of London Corporation)当时并不以在公共卫生方面特别积极而闻名,该公司意识到适可而止,并邀请提交该市新污水排放计划的设计方案。约瑟夫·巴扎格特的计划被接受了,他现在被认为是伦敦历史上主要的市民英雄之一。作为一名才华横溢的土木工程师,他监督了一个巨大的公共工程项目,该项目改变了伦敦的卫生水平和生活质量。Bazalgette 的下水道网络被广泛认为是创建现代城市的第一步,也是伦敦霍乱终结的开始。
The Great Stink of 1858 was solved with the help of graph theory.
Bazalgette 的下水道网络仍然运行良好,将数百万人的废物向东运送到泰晤士河口的处理设施。作为一个工程项目,这是人类努力的一个令人震惊的例子:22,000 公里的下水道,3.18 亿块砖,270 万立方米的挖掘土。
Bazalgette 以他自己的努力工作而闻名。他想尽一切办法让这项巨大的努力经得起未来的考验。确保水流的重力和坡度,隧道的直径,所有这些都是他非常关心的细节。但是有两个问题从一开始就必须回答,以使项目可管理和可持续:第一,我们如何将网络中任何两点之间的污水路线最小化,第二,哪一个是最重要的连接点?
Bazalgette 的工程壮举是图论新兴领域的一些最初用途的一个例子,并说明了我们今天一直在关注的与网络有关的两个概念的重要性:顶点之间的距离和顶点的重要性。
测量图形中的距离
距离在图论中是一个相当简单的概念,但在实践中非常有用。回想一下本系列的上一篇文章,图由一组顶点和一组连接成对顶点的边组成。给定任意两个顶点,它们之间的距离定义为它们之间最短路径的边数。这有时也被称为“测地线距离”,如果顶点之间不存在路径,则按照惯例被描述为“无穷大”。例如,在上面的简单图形中,顶点 2 和顶点 6 之间的距离是 3(有两条这样长度的路径可以到达那里)。
距离是一个非常有用的概念,因为我们经常想要优化它。在复杂的工程网络中,最小化距离是一个非常常见的要求。在对人的研究中,最小距离也是一个常见的利益问题。六度分离问题认为世界上的任何两个人可以通过最多六个中间顶点或七条边相互连接,这是一个图网络中的最小距离问题。最近对脸书的研究显示,该网络中个人之间的平均最小距离为 4.57。
但是最大距离也可能是有趣的,因为它意味着不熟悉和不同。例如,可以使用某些公司数据来开发一个表示员工之间过去协作的图表。然后,在公司活动中,你将人们组织成讨论组,如果你想最大限度地形成新的联系和观点的多样性,你可以问这样的问题:我们如何将这 100 人分成 10 组,每组 10 人,这样这些组有最大的平均距离,因此最不可能以前彼此合作过?以这种方式使用,图论可以对组织内的人们的体验产生有意义的影响。
测量图中顶点的重要性
在任何图中,有些节点更重要。例如,在 Bazalgette 的下水道网络中,将会有一些需要更多监控的连接点,因为任何故障或泄漏都会对整个网络产生更大的影响。同样,在一个人的网络中,某些个人由于其相对于网络中其他人的定位和连接性而具有更大的影响力。
衡量重要性的一个简单方法是顶点的价数 T2。这是连接到顶点的不同边的数量。以脸书为例,你的价就是你拥有的联系数量。但这并没有完全掌握影响力或重要性的概念,不是吗?并不是每个拥有大量人脉的人都在网络中扮演着真正重要的角色。
根据我的经验,衡量网络重要性的最佳标准是中间中心度。简单地说,给定顶点的介数中心性是该顶点在网络中两个其他顶点之间的最短路径上出现的次数。具有高度介数中心性的顶点在更大程度上影响信息的传播,并且它们从网络中的损失往往对其整体连通性具有更显著的影响。在上图中,红色顶点的中间中心度最小,而蓝色顶点的中间中心度最大。
理解中间中心性在人际网络中非常重要。它可以帮助确定投资于哪些个人,以确保某个信息尽可能广泛地传播。通过介绍给合适的人,它可以帮助你结交新朋友。它有助于确定你应该对从网络中失去一个人及其对其他人的潜在影响有多担心。
中间中心性很难测量,因为你需要计算网络中所有顶点对之间的路径。对于大型网络,这可能是高度计算密集型的。然而,有一些优秀的数据科学软件包可以用来计算网络特征,包括介数中心性。在我工作的 R 生态系统中,igraph
包特别方便。
下一次,我们将看看信息是如何在网络中流动的,这对谣言和趋势的研究有着非常有趣的应用。 这里读一下 。
最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在LinkedIn或者在Twitter上找我。**
图论——历史和概述
原文:https://towardsdatascience.com/graph-theory-history-overview-f89a3efc0478?source=collection_archive---------4-----------------------
第一部分——什么是图论&为什么它与今天相关?
Originally Published On https://www.setzeus.com/
图表,尤其是网络图,引起我的注意。
也许这是一种直觉,用图来分析系统会增加我对分散式和集中式网络的理解。我这个数学家看到了明确的网络分析是如何极大地有利于激励驱动系统的研究的。或者可能是我这个设计师很大程度上被上图这种与生俱来的艺术魅力所吸引——视觉上很吸引人,但最终还是信息丰富的。
不管出于什么原因,在软件开发中遇到了作为树的图,在区块链研究中遇到了作为网络的图,或者在 r/databasebeable click-bait 中遇到了作为诱饵的图之后,我决定深入图论的世界&它是网络理论的一个分支。
Article Originally Published On https://www.setzeus.com/
数学领域是 大 。它的知识之树分支到越来越多的子领域。对描述一组分支的&进行细分的最高级别方法之一是通过给定问题中号的类型。问题中的数字既可以是 离散的 ,如固定的、可终止的数值如自然数 1、2、3、4。或者它们可以是 连续的 ,这些数字更准确地将我们的现实映射为动态的、不断变化的数值比如物体的速度。
离散数字对于老式数字钟就像连续数字对于现代模拟时钟(一种滑动而非滴答的时钟)一样。在前者中,上午 11:32 和下一分钟 11:33 之间不存在任何数字。在后一种情况下,秒针持续移动,这意味着当秒针从一秒滑动到下一秒时,模拟时钟在技术上每一个瞬间都显示不同的值。包含离散数字的数学分支的最好例子是组合学,研究对象的有限集合。基于连续数的数学分支的最好例子是微积分,它研究事物如何变化。**
图论是离散数学的一个分支,是对事物之间联系的最高层次的研究。这些事物,更正式地被称为顶点,顶点或者节点节点,而连接本身被称为边。**
图论的历史
图的基本概念是由瑞士数学家莱昂哈德·欧拉在 18 世纪首先提出的。他对著名的柯尼斯堡桥问题的尝试和最终解决方案(如下所示)通常被引用为图论的起源:
Article Originally Published On https://www.setzeus.com/
德国城市柯尼斯堡(今俄罗斯加里宁格勒)坐落在普雷戈利亚河畔。地理布局由四个陆地主体共七座桥梁连接而成。向欧拉提出的问题很简单:有没有可能步行穿过城镇,穿过每座桥一次,而且只穿过一次(被称为欧拉步行)?**
欧拉认识到相关的约束条件是四块陆地&七座桥,他画出了第一张现代图形的可视表示。如右下方的图像 C 所示,现代图形由一组称为 v 顶点或节点的点表示,这些点由一组称为 e dges 的连接线连接。
Article Originally Published On https://www.setzeus.com/
通过首先尝试在上图中绘制路径,然后用顶点和边数交替变化的多个理论图进行实验,他最终推断出一条一般规则:
为了能够走欧拉路径(又名不重复边),一个图可以没有或者有两个奇数个节点?
从那以后,被称为图论的数学分支潜伏了几十年。然而,在现代,它的应用终于爆炸了。
图论的应用
图论*归根结底是对关系**的研究。给定一组节点&连接,它们可以抽象出从城市规划到计算机数据的任何东西,图论提供了一个有用的工具来量化&简化动态系统的许多移动部分。通过一个框架来研究图形为许多排列、网络、优化、匹配和操作问题提供了答案。*
随着我们继续学习图形集和矩阵符号的基础知识 (2) ,通过介绍一些应用来激发我们自学的动机不会有什么坏处——一窥图论的应用:
在软件工程中,它们被认为是一种相当常见的数据结构,被恰当地命名为决策树。在电气工程领域,整个学科都围绕着多部分电路的创建、计算和维护,这些电路通常按照图论原理绘制。与此同时,在分子生物学领域,科学家们推断预测模型来跟踪疾病的传播或繁殖模式。最后,在充满争议的社交媒体网络分析领域,我们见证了图论被用来创建现在的标准功能,如 LinkedIn 的分离度&脸书的朋友推荐功能。让我们进入下一篇文章,熟悉常见的图形符号。**
原载于
https://www.setzeus.com/
来源
图论介绍
图论
图论——网络理论
原文:https://towardsdatascience.com/graph-theory-on-to-network-theory-379b390fb19b?source=collection_archive---------13-----------------------
第四部分——网络理论的基础
Originally Published On https://www.setzeus.com/
最后,我们在这一系列图论文章中的路径把我们带到了图论的一个新兴分支的核心:网络理论。
网络理论是图论原理在复杂、动态互动系统研究中的应用
当提供额外的相关信息时,它为进一步分析相互作用的代理的结构提供技术。网络理论的应用,正如这篇文章之前的文章中所说的 (3) ,是深远的&行业不可知论。从计算机科学,到电子工程,到博弈论&社会媒体分析,网络理论的基础提供了一个强大的心智模型来增加我们对现代系统的理解。
在不破坏太多未来文章的情况下,提供一个网络理论通常用来解决的类问题的快速概述可能是有意义的。其中,有几个经典网络理论问题的例子:
- 最短路径问题——图中任意两个节点之间的最短(成本方面)路径是什么?
- 网络流量—有向路径是否有足够的容量来承载沿途每个节点接收到的“流量”?
- 匹配问题——一个图是否包含一对或多对匹配的独立边集?
- 关键路径分析——在一个相互依赖的活动系统中,哪一条路径最长?
一目了然——社交媒体网络
通过图论原理研究主流社交媒体的异同,我们可以加深对这些日常实体的理解和欣赏。让我们通过类似迷你图的表示来分解《媒介与脸书》的结构。
中等
代表 Medium(这个站点)的图表看起来像什么?从划分用户之间的关系开始。在介质上,用户可以跟随另一个用户,而第二个用户不一定要跟随第一个用户回来——这意味着介质图上的每条边都有方向。因此,Medium 的网络采用了有向图的形式。例如,如下图所示,我的一个朋友托尼·斯塔克(Tony Stark)既可以追随朱莉·卓(Julie Zhuo)(我追随 IRL 的一位才华横溢的脸书产品设计师&多产媒体作家);然而,由于她没有兴趣看我们写的东西,她没有跟着我们回去——从朱莉到托尼我自己没有回去的路。这在下面的例子中直观地表达出来:
Article Originally Published On https://www.setzeus.com/
脸谱网
现在让我们比较一下上面的媒介代表和蓝色的有争议的有罪快感,脸书。除了相对较新的“关注”功能,脸书用户已经成为朋友,以便共享对彼此内容的访问。一个脸书用户请求第二个脸书用户成为的朋友。然而,一旦请求被接受,谁向谁发送请求就不再重要了。方向性不再存在:双方用户将在各自的时间轴上看到对方的内容。让我们继续看看影响者 Julie 的例子,我自己也有两个普通用户& Tony Stark。在脸书,托尼很可能是我的朋友;然而,我们俩都不是朱莉的朋友:
Article Originally Published On https://www.setzeus.com/
我们已经对主流社交媒体进行了两次思维实验,以直观地理解它们各自的图形结构。让我们来看看加密货币这个激动人心的世界,以便浏览另外两个例子。
加密货币一览
我们现在将分析另一个类似图表的现代奇迹:加密货币。下面,我们将分析比特币的闪电网络和 IOTA 的纠结共识机制的支持网络的文字截图,而不是通过例子来思考。
闪电网络
Article Originally Published On https://www.setzeus.com/
上图是 Lightning Network 的截图,这是一个用于比特币的 p2p、链外结算层,是最有希望实现即时、近乎免费的比特币交易的扩展解决方案之一。闪电网是由个节点&个支付通道(又名边缘)组成的网络。支付通道严格由两个终端节点组成,通过发送初始金额来打开支付通道,这使得两个连接节点之间的比特币交易速度极快。为了加入 Lightning 网络,一个节点需要与另一个节点至少有一个支付通道。
节点& 支付渠道,如上所述,组合成一个图形结构的典型例子。一旦支付通道打开,两个用户都可以无休止地将交易发送回&——方向是双向的,这意味着闪电网络代表了一个无向图。
一丝纠结
Article Originally Published On https://www.setzeus.com/
另一方面,IOTA 项目基于 DAG — 有向无环图,为他们的区块链版本推出了一种特殊的共识机制。
在上面显示的纠结中,每个交易都被表示为图中的一个顶点。当一个新的事务加入这个纠结时,它选择两个先前未确认的事务进行确认,向图中添加两个新的边&节点。一旦确认,已确认的交易不能再被进来的未确认交易确认;但是最近加入未确认交易的&很可能会被下一个确认的传入,未确认交易。因此,根据交易是已确认还是未确认,导致图形中的方向性。通过上面的观察,我们可以通过注意到图形底部附近的大多数奇异顶点有两条边&顶点悬挂在它们上面来验证这一点(等待确认的未确认事务)。
最后
从图论历史的最基础开始,从哥尼斯堡的七座桥开始,我们现在一直前进到网络理论的中心。然而,这只是实际图形和网络理论应用的启动平台,下一步是使用许多制作精良的图形和网络可视化和分析工具,如下面链接的工具:
[## 免费的开源社交网络分析工具
社会网络分析:社会网络可视化(SocNetV)是一个用户友好的免费软件工具,为社会…
socnetv.org](https://socnetv.org/) [## ge phi——开放图形平台
Gephi 是各种图形和网络的领先可视化和探索软件。Gephi 是开源的…
gephi.org](https://gephi.org/) [## 免费在线网络可视化工具。在浏览器中创建交互式网络。不需要编码。
面向非开发人员的在线交互式可视化工具。
rhumbl.com](https://rhumbl.com/)
最初发表于
https://www.setzeus.com/
来源
图论介绍
图论
图论——集合和矩阵符号
原文:https://towardsdatascience.com/graph-theory-set-matrix-notation-7dfb04b8ed24?source=collection_archive---------12-----------------------
第二部分——图论符号的基础
Article Originally Published On https://www.setzeus.com/
一个图 G 由两组项组成:顶点( V ) &边( E )。换句话说,一个图 G = < V,E >。
简单图形—集合符号
在本文中,与本系列的第一篇相比,我们将通过图表示例来工作。我们要查看的第一个示例图包含了将其归类为 简单图的特定属性。 简单图是指其顶点未加权、无向、&不含多条边&自向环的图。不理解前面的术语没关系,因为我们将在下面的文章中广泛讨论图形属性。现在,让我们从下面的可视化示例开始:
Article Originally Published On https://www.setzeus.com/
如上图所示,可视化图形表示包含大量有用的信息;然而,为了以一种可操作的方式揭示这些数据,我们需要一种不同的方式来描述图表。首先,为了更好地理解开头的 G = < V,E > 公式,让我们继续记下上面的例图。为了开始标注,因为我们的顶点缺少标签,我们继续&分配任何随机节点标签“A”——然后遍历图形,用比前一个大的字母数字字符标记每个节点。还没有什么新奇的东西,我们所做的只是给上图中的顶点分配一个代表性的角色:
Article Originally Published On https://www.setzeus.com/
现在,让我们继续&通过创建两个数字集合来构造图形的数字符号:顶点&边。示例图的第一组顶点相当简单:它是一组字符 A-F(包括 A-F)。但是我们的优势呢?简单。回想一下,边是连接两个节点的。因此,一条边可以用它所连接的两个节点来表示;这意味着边集合包含一系列类似坐标的顶点。例如,顶点 A &和顶点 B 之间的第一条边最好表示为 AB 。让我们继续&写出图表其余部分的集合表示:
updated thanks to Simon Dedman
如上图所示,我们的图 G 的标准符号可以用两个独立的集合来完美地描述,一个表示顶点,&一个表示边。**
然而,这是进行数学和分析运算的最好方法吗?把它喂给电脑处理怎么样?事实证明,矩阵提供了一个强有力的工具来为一个更加计算机友好的数据集转录图形。让我们回顾一下这两种主要的方法&相应地标注我们的示例图。
简单图形—矩阵符号
计算机更擅长处理数字,而不是识别图片。这也是为什么以矩阵形式向计算机传达图形规格更为常见的原因之一。两种主要类型的矩阵设置是行业惯例:邻接矩阵&关联矩阵。**
邻接矩阵
相连的顶点被称为邻居,或者彼此相邻的。一个邻接矩阵因此描述两个顶点是邻接(1) 还是非(0) 。邻接矩阵中的每一项都是简单的描述连通性的布尔值。**
在邻接矩阵中,具有顶点集合 V 和边集合 E 的图 G 转化为大小为 V 的矩阵。在矩阵内部,我们发现 0 或 1——1 表示在行&中标记的顶点与列中标记的顶点是相连的,或者用更恰当的术语来说,它们是相邻的。因此,邻接矩阵是表示为矩阵的图,其中相邻的顶点是唯一的焦点。让我们继续&将我们的示例图转录为下面的邻接矩阵:
Article Originally Published On https://www.setzeus.com/
关联矩阵
将图形转换成矩阵的第二种常见语法是通过关联矩阵。在关联矩阵中,具有顶点集合 V &和边集合 E 的图 G 转化为大小为 V 乘以 E 的矩阵。行&列分别在顶点&边后标注。在矩阵内部,我们再次发现所有的项目都被标记为 0 或 1——更多的布尔值。然而这次,1 表示行&中标注的 顶点 与列中标注的 边 相连。
关联矩阵的一个有趣的性质是:将一个列中的每一项相加总会得到两个。这在直觉上是有意义的,因为简单图中的任何&每条边都只有两个顶点与之相连。让我们继续&将我们的示例图写成关联矩阵:
Article Originally Published On https://www.setzeus.com/
比较这两种矩阵符号,我们可以推出一些区别。首先,由于边总是比顶点多,因此邻接矩阵的列数比关联矩阵少。相应地,关联矩阵更稀疏(0 到 1),因此每个矩阵项的信息量可能更少。最后,邻接矩阵总是遵循正方形矩阵模式,而关联矩阵更可能代表矩形。
关键区别在于,前者的行&列代表顶点,而后者的行&列分别代表顶点&边。
过去简单图形
现在基本符号已经过时了,是时候继续研究基本的图形属性了,这些属性通常用于描述不同类型的图形。回想一下,我们的示例图早先被定义为简单的图;我在下一篇文章中,我们将在跳到图论中最激动人心的话题:网络理论之前探索一些图。
原载于
https://www.setzeus.com/
来源
图论介绍
图论
Jupyter 中的 GraphFrames:实用指南
原文:https://towardsdatascience.com/graphframes-in-jupyter-a-practical-guide-9b3b346cebc5?source=collection_archive---------0-----------------------
最初用于计算生物学的图分析已经成为社交网络分析(社区挖掘和建模作者类型)和推荐系统中越来越重要的数据分析技术。一个简单而直观的例子是曾经非常著名的脸书朋友聚类图,它可视化了你的脸书网络的隐藏结构。
有一段时间,权力图分析一直是学术界、脸书或 Twitter 内部人士的一门学科。但是自从 GraphX 和 Graphframes 之类的软件包发布以来,每个拥有一点数据和一个 Jupyter 笔记本的人都可以很容易地在迷人的图形世界中玩耍。
lostcircles.com
在这篇文章中,我提供了一个关于 Jupyter 笔记本中 Graphframes API 的大范围的玩笑。首先,我们通过设置 Jupyter 笔记本环境来使用 GraphFrames 包(在 Windows 机器上)。然后,我们将了解基本功能以及如何将数据导入框架,最后解释一些常用的高级功能。请注意,本文假设您对 Spark 和 Spark 数据帧有基本的了解。
GraphX 对于 rdd 就像 GraphFrames 对于 DataFrames 一样。
GraphFrames 和 GraphX 的功能基本相同,唯一的区别是 GraphFrames 基于 Spark 数据帧,而不是 rdd。如果你习惯使用 GraphX,那么浏览一下 API 文档,Graphframes 应该很容易学会。
设置环境
在继续之前,首先要检查的是确保 Spark 和 pyspark 正确安装在您的机器上。为了简单起见,在本教程中,我们将在本地模式下运行 spark。检查这一点最简单的方法是在 Python 发行版的外壳中输入 pyspark 。如果两者都安装正确,您应该会看到如下内容:
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/__ / .__/\_,_/_/ /_/\_\ version 2.xx.xx
/_/
Using Python version 3.xx.xx
关于设置 Apache Spark 和 pyspark 的更多信息,我推荐本教程和官方文档。
接下来,您希望在 Jupyter 笔记本中设置环境变量来运行 pyspark(而不是 shell)。这可以通过添加两个环境变量来轻松实现:
set PYSPARK_DRIVER_PYTHON=jupyter
set PYSPARK_DRIVER_PYTHON_OPTS=notebook
然后导航到您想要存储新笔记本的位置,并在您的 shell 中再次运行 pyspark ,但是添加一个 packages 标志并指示您想要使用 GraphFrames 包。这里使用的是最新版本,但是任何旧版本都可以通过更改参数的最后一部分来使用:
pyspark --packages graphframes:graphframes:0.5.0-spark2.1-s_2.11
创建新笔记本,并确保您可以成功运行:
from graphframes import *
入门指南
令人惊讶的是,这个包的核心类是 GraphFrame。GraphFrame 总是从顶点数据帧(例如用户)和边数据帧(例如用户之间的关系)创建的。两个数据帧的模式都有一些强制列。顶点数据帧必须包含一个名为 id 的列,用于存储唯一的顶点 id。edges DataFrame 必须包含一个名为 src 的列,用于存储 edge 的源,以及一个名为 dst 的列,用于存储 edge 的目的地。所有其他列都是可选的,可以根据需要添加。
一个简单的例子是:
from pyspark import *
from pyspark.sql import *spark = SparkSession.builder.appName('fun').getOrCreate()vertices = spark.createDataFrame([('1', 'Carter', 'Derrick', 50),
('2', 'May', 'Derrick', 26),
('3', 'Mills', 'Jeff', 80),
('4', 'Hood', 'Robert', 65),
('5', 'Banks', 'Mike', 93),
('98', 'Berg', 'Tim', 28),
('99', 'Page', 'Allan', 16)],
['id', 'name', 'firstname', 'age'])
edges = spark.createDataFrame([('1', '2', 'friend'),
('2', '1', 'friend'),
('3', '1', 'friend'),
('1', '3', 'friend'),
('2', '3', 'follows'),
('3', '4', 'friend'),
('4', '3', 'friend'),
('5', '3', 'friend'),
('3', '5', 'friend'),
('4', '5', 'follows'),
('98', '99', 'friend'),
('99', '98', 'friend')],
['src', 'dst', 'type'])g = GraphFrame(vertices, edges)## Take a look at the DataFrames
g.vertices.show()
g.edges.show()## Check the number of edges of each vertex
g.degrees.show()
你当然希望使用真实的数据。您可以将从简单的 csv 文件到拼花文件的任何内容导入到数据帧中。然后适当地命名您的列,过滤(如果需要)并从那里继续前进。关于将数据导入 Spark 数据帧的更多信息可在文档中找到。
我们刚刚创建的 GraphFrame 是一个有向图,可以如下图所示:
有向边与无向边
无向图的边没有方向。这些边表示双向关系,因为每个边都可以在两个方向上遍历。如果数据帧仅由双向有向边组成,您可能会对分析无向边感兴趣。如果 src ≥ dst (或者相反),您可以通过在 edges 数据帧上映射一个函数来转换您的图形,该函数会删除该行。在 GraphX 中,您可以使用 to_undirected() 来创建一个深度的、无方向的图形副本,不幸的是 GraphFrames 不支持这个功能。
在下面的代码片段中可以找到一个简单的例子来解决这个缺失的功能。请注意,“跟随”边在无向图中没有实际意义,因为它不代表双向关系。
copy = edgesfrom pyspark.sql.functions import udf[@udf](http://twitter.com/udf)("string")def to_undir(src, dst):
if src >= dst:
return 'Delete'
else :
return 'Keep'copy.withColumn('undir', to_undir(copy.src, copy.dst))\
.filter('undir == "Keep"').drop('undir').show()## for efficiency, it's better to avoid udf functions where possible ## and use built-in pyspark.sql.functions instead.
过滤和连接组件
GraphFrame 本身不能被过滤,但是从 Graph 中推导出的 DataFrames 可以。因此,filter-函数(或任何其他函数)可以像使用数据帧一样使用。唯一的陷阱可能是引号的正确使用:整个条件应该被引用。下面的例子应该可以澄清这一点。
g.vertices.filter("age > 30").show()g.inDegrees.filter("inDegree >= 2").sort("inDegree", ascending=False).show()g.edges.filter('type == "friend"')
图的连通分支是这样的子图,其中任意两个顶点通过一条或多条边相互连接,并且在超图中不连接任何额外的顶点。在下面的(无向)示例中,有三个相连的组件。连通分量检测对于聚类很有意义,而且可以使计算更有效。
Source: Wikipedia
实际上,GraphFrames 要求您设置一个目录来保存检查点。在您的工作目录中创建这样一个文件夹,并在 Jupyter 中放置下面一行(其中 graphframes_cps 是您的新文件夹)来设置检查点目录。
sc.setCheckpointDir('graphframes_cps')
然后,可以用 connectedComponents 函数很容易地计算出连通分量。
g.connectedComponents().show()
我们的迷你图有两个相连的组件,在组件列中对每个顶点进行了描述。
+---+------+---------+---+------------+
| id| name|firstname|age| component|
+---+------+---------+---+------------+
| 1|Carter| Derrick| 50|154618822656|
| 2| May| Derrick| 26|154618822656|
| 3| Mills| Jeff| 80|154618822656|
| 4| Hood| Robert| 65|154618822656|
| 5| Banks| Mike| 93|154618822656|
| 98| Berg| Tim| 28|317827579904|
| 99| Page| Allan| 16|317827579904|
+---+------+---------+---+------------+
主题发现
寻找主题有助于执行查询以发现图形中的结构模式。网络主题是图形中重复出现的模式,代表顶点之间的关系。GraphFrames motif finding 使用声明性领域特定语言(DSL)来表达结构化查询。
可以通过使用find-函数调用查询,其中 motif(在引号中)被表示为函数的第一个参数。
下面的例子将搜索由边e连接的顶点对 a 、 b 和由边 e2 连接的顶点对 b 、 c 。它将返回图形中所有此类结构的数据帧,其中包含主题中每个命名元素(顶点或边)的列。
g.find("(a)-[e]->(b); (b)-[e2]->(a)").show()
如果边和/或顶点是匿名的,它们将不会显示在结果数据帧中。主题可以用分号连接,也可以用感叹号否定。关于领域特定语言的更多细节可以在文档中找到。
例如,我们可以尝试为任何一对用户 a 和 c 找到共同的朋友。为了成为共同的朋友 b , b 必须是既有 a 又有 c 的朋友(而不仅仅是后面跟着 c 之类的)。
mutualFriends =
g.find("(a)-[]->(b); (b)-[]->(c); (c)-[]->(b); (b)-[]->(a)")\
.dropDuplicates()
要查询 2 和 3 之间的所有共同好友,我们可以过滤数据帧。
mutualFriends.filter('a.id == 2 and c.id == 3').show()
b-列将显示所有共同的朋友(在本例中只有一个)。
+--------------------+--------------------+--------------------+
| a| b| c|
+--------------------+--------------------+--------------------+
|[2, May, Derrick,...|[1, Carter, Derri...|[3, Mills, Jeff, 80]|
+--------------------+--------------------+--------------------+
三角形计数和 PageRank
最后,我们将发现两个额外的内置算法。TriangleCount 计算通过此图中每个顶点的三角形数量。三角形可以定义为一组相互关联的三个顶点,即 a 有一条边到 b , b 有一条边到 c ,以及 c 有一条边到 a 。下面的例子显示了一个有两个三角形的图形。
geeksforgeeks.org
在 GraphFrames 包中,你可以通过调用triangle count-函数来计算通过每个顶点的三角形数量。请注意,我们的简单示例总共只有两个三角形。三角形用于现实网络中的各种任务,包括社区发现、链接预测和垃圾邮件过滤。
g.triangleCount().show()
我们讨论的最后一个函数是 PageRank。PageRank 的工作原理是通过计算一个页面的链接数量和质量来粗略估计该网站的重要性。潜在的假设是,更重要的网站可能会从其他网站收到更多的链接。
PageRank 算法认为,一个假想的随机点击链接的冲浪者最终会停止点击。在任何一步,这个人继续下去的概率是一个阻尼因子。阻尼系数可以通过改变重置概率参数来设置。其他重要的参数是公差( tol )和最大迭代次数( maxIter )。
pr = g.pageRank(resetProbability=0.15, tol=0.01)## look at the pagerank score for every vertex
pr.vertices.show()## look at the weight of every edge
pr.edges.show()
我找到“真命天子”的几率
原文:https://towardsdatascience.com/graphic-novel-what-are-my-odds-of-finding-the-one-3e5983a5153f?source=collection_archive---------4-----------------------
你有没有想过,“我约会的对象对吗?他/她是那个人吗?我是不是太早安定下来了?当我们不以一种方式做事时,我们会以另一种方式做事。如果我不安定下来,他/她会成为“逃脱的那个”吗?"
我决定用一点数据就能解决这个问题。
在你说“你不能对爱下定义”之前,我会说我完全同意。如果你说,“你的女朋友一定很生你的气,因为你把她物化了”,让我说她很好奇,但也很不安。最后,让我说这部漫画小说有一个快乐的结局。
该方法
世界上有固定数量的人,我有一些基本要求。是的,爱情是盲目的,我知道,但让我们找点乐子,假设一些品质是真正的交易破坏者。你可能对年龄、教育程度、智力、吸引力、兴趣、性别、身高、语言等有所要求。我将详细说明我的要求,您可以通过复制这张谷歌表单来遵循您自己的偏好。你会发现找到你生命中的那个人的可能性有多大。
打开电子表格并跟随:-)
年龄和性别
世界上男性略多于女性。我感兴趣的是年龄在 25 岁到 34 岁之间的女性,大约占总人口的 7%,或者所有女性的 14%。
世界上 70 亿* 7% = 4.9 亿女性年龄大致合适
在印度,老年人很少,随着医疗保健的改善,他们的人口将快速增长。在中国,人口结构是相当不稳定的,因为有很多贫困时期和独生子女政策。
语言
我只能和说英语(或者可能说西班牙语)的人交往,所以那大约是 11 亿/70 亿=15%。这是为第一或第二语言使用者准备的。
70 亿7%15%
宗教
我对我伴侣的信仰有点挑剔。无神论者,不可知论者或精神工作对我来说。克里斯蒂安不行。只有 16%的女性符合我的标准。这对非宗教人士来说实在是太多了。
70 亿7%15%*16%
吸引力
好吧,这个因素有点不确定。显然,你想被和你在一起的人吸引,但是给某人加一个号码会触发很多人。我发现了一项对几十个快速约会事件进行的研究,其中男性和女性在事件后按照 1 到 10 的等级对他们的约会对象进行评级(也就是说,他们不仅根据外表进行评级,还根据化学成分进行评级)。[注意:在图表中,你可以看到女性比男性更挑剔,男性的评分也比男性低!]男人声称 5%的女人是 10 岁。
70 亿* 7% * 15% * 16% * 5%…对于那些正在记录分数的人来说。
https://www0.gsb.columbia.edu/mygsb/faculty/research/pubfiles/867/datingFULL-EK1.pdf
有趣的是,快速约会研究中的每一个人都至少获得了一个高于平均水平的评级和一个低于平均水平的评级,这表明,事实上,吸引力是主观的,“每个人都有自己的人”与此同时,收视率分布并不均匀。有些人的平均得分比其他人高得多,所以对“吸引力”也有一些共识。
根据我的计算,我只包括 10 个。你可能会说“7 还不够好吗?为什么需要 10 分?”首先,我的 10 分和你的 10 分不一样,所以我们不是在竞争同一个人。第二,我不想处于这样一种境地:我必须向我的伴侣撒谎,说他们是我见过的最有魅力的人——我以前也有过这种经历。
为了进一步支持人们会被非常不同的人吸引的论点,正如你在 OkCupid 的下图中看到的,平均水平高并不意味着低。虽然右边的女性平均水平较高(3.4 比 3.3),但她收到的消息是左边女性的三分之一(是网站平均水平的 0.8 倍,是网站平均水平的 2.3 倍)。这怎么可能?事实证明,平均水平会说谎;更有趣的是分布。左边的女人比右边的女人获得了更多的 1 分。但这并不重要。重要的是有多少人给你打 5 分。所以老话“做你自己”真的适用于现实生活。虽然照片中的两个女人可能都很特别,但左边的那个看起来更独特,因此也更两极分化。
From “Mathematics of Beauty” OkCupid blog post in 2011 (blog taken down, now available the book by the CEO of OkCupid called Dataclysm — Amazon link).
智力
我忘记了来源,但我读到过,如果夫妻之间的智商在 10 分以内,他们成功的可能性会大得多(我找到后会添加这项研究,或者如果你记得请贴上链接)。我想找一个智商 125+的女人。是的,我知道智商并不是衡量智力的完美标准,如果你有更好的衡量标准,请告诉我!
70 亿7%15%16%5%*5%
https://www.us.mensa.org/join/testing/scoreevaluation/
高度
我比男性平均身高(6 英尺 3 英寸)高出两个标准差,我发现很难和身高低于 5 英尺 3 英寸的女性跳舞,这是女性的平均身高,50%的女性高于平均身高。
70 亿7%15%16%5%5%50%
https://tall.life/height-percentile-calculator-age-country/
其他特征
此外,我的“另一半”需要目前单身( 47%的 25-34 岁女性单身)、想要孩子(显然只有 2/3 的千禧一代想要孩子)、不吸烟( 85% )、多面手( 4.5% )并且愿意骑摩托车穿越拉丁美洲 3000 英里(我估计只有 5%的女性愿意,尽管我不能
70 亿* 7% * 15% * 16% * 5% * 5% 50% * 47% * 66% * 85% * 4.5% * 5%…
Percent of women who are single by age. This photo highlights that 29 percent of 34-year-old women are single. I averaged the single rate for women 25–34. You can see the full data at: https://www.thrillist.com/news/nation/overflow-data-shows-percentage-of-people-your-age-are-married
免费奖金图表:D
如果以下任何一个恋物癖对你很重要,这里有一个关于这个话题的研究。或者也许你和我一样,性恋物癖不是一个必要条件,但发现这个图表很迷人…
https://www.reddit.com/r/dataisbeautiful/comments/6l8doh/the_tabooness_and_popularity_of_sexual_fetishes/
计算一下
我找到真命天子的几率有多大?世界上有 70 多亿人居住在 200 多个国家的数十万个城镇中。肯定有很多女性符合我的标准…
在世界上所有的人当中,只有 9 个女人符合上述要求。这对我来说是一个令人震惊的结果。我要见 9 亿人才能找到一个这样的女人。当然,我没见过那么多人。我一生中最多见过一万个人。
得出这个惊人的结论后,我兴奋地打电话给我的女朋友,并解释了我们相遇的低得荒谬的概率。我认为电话那头她的沉默意味着她被深深打动了。就像中了彩票一样。我甚至受到启发,给她写了一两封情书;-)然后她告诉我她不觉得好笑,而且世界上肯定没有其他 8 个女人像她一样。
那么你如何筛选 70 亿粒沙子呢?
两年前,在我搬到旧金山之前,我回顾了自己的约会史。我在寻找一种数据驱动的方法。认识女人最有效的方法是什么?哪种认识他们的方式会带来最好的关系?我应该在 Tinder 上搜索还是去参加速配活动?
结果也不是。
Analyzing my own dates and relationships.
通过朋友认识女性是认识可能成为你的另一半的女性的最有效的方式。朋友是一个伟大的过滤器。做了这项研究后,我开始意识到为什么人际关系网如此重要。我无法筛选世界上数百万可能的生活或商业伙伴。但是如果我利用我的朋友和我的关系网,他们可以为我筛选大部分的机会。
这与其他研究非常吻合。大多数异性恋夫妇通过朋友认识,然而网上约会正成为一种流行的认识伴侣的方式。
https://web.stanford.edu/~mrosenfe/Rosenfeld_How_Couples_Meet_Working_Paper.pdf mrosenfe@stanford.edu Searching for a Mate: The Rise of the Internet as a Social Intermediary Michael J. Rosenfeld, Stanford University* and Reuben J. Thomas, The City College of New York Published in the American Sociological Review 77(4): 523–547 ©2012
机会对我们不利,但事实证明很少有女人适合我。我相信有一些女人/男人适合你。现在你知道了:
- 如何确定找到梦中情人的几率
- 如何在世界上数十亿人中搜寻找到他/她。
你喜欢吗?请在这里创建您自己的谷歌表单,确定您找到那一个的机会,并在下面评论您的结果。
如果你喜欢,可以考虑注册我的时事通讯,玩玩创意。
感谢我的女朋友编辑了这个。
GraphQL 模式用例及功能
原文:https://towardsdatascience.com/graphql-schema-use-case-and-functions-731ec4a39061?source=collection_archive---------25-----------------------
使用 graphql-tools 复制、混合和定制现有的 API
在本文中,我介绍了 GraphQL API 的一些用例。对于新 API 的创建,有用的功能有“远程模式”、“模式拼接”、“模式转换”。它们能够复制、混合和定制现有的 API 模式。
用例
One API service called “Gian” is created from existing APIs called “Nobita” and “Suneo”
有时我们使用现有的 API 来创建新的 API。有人会从别人的 API 中复制 API 模式。其他人会将一个 API 模式与另一个 API 模式混合在一起。
“Gian” web service frontend utilizing API “manga” originated in “Nobita” API
如果您在 REST API 世界中
这是一个 web 服务“Gian”的用例。这个服务有一些 API(REST API)。大多数 API 源自其他服务“Nobita”和“Suneo”。
- “漫画”API 是从一个服务大雄复制而来,“游戏”API 是从一个服务 Suneo】复制而来
- 服务巨人融合了服务大雄和服务太阳
- orenomanga 的 API 是原创的,但它的内容来自“漫画”API。服务 Gian 修改 API 的内容。(例如。添加新字段或重命名现有字段。)
您可以使用 API 网关工具,但是管理许多 API 是一件困难的事情。
有用的功能:在 GraphQL 世界中复制、混合和定制模式
GraphQL 和一些工具为复制、混合和定制 API 准备了有用的函数。
- [初步]模式自省
- API 复制的远程模式
- 用于 API 混合的模式拼接
- 用于 API 复制和定制的模式委托
- 用于 API 定制(修改)的模式转换
初步知识:GraphQL 中的模式检查
在 GraphQL 中,你只用 GraphQL Schema 语言定义数据类型,然后 GraphQL 服务器自动提供 API 和文档并发布。例如,服务 Nobita 定义了以下数据类型。
GraphQL 模式语言包括数据名称、类型和描述。这些信息被重组为 API 规范文档的格式,称为自省。您可以通过特殊查询__schema.
向 GraphQL 服务器请求这些信息
GraphQL schema creates API and document (__schema) automatically.
自省使 GraphQL 服务器和客户机能够共享模式并验证查询。
功能 1(复制一个 API)“远程模式”
远程模式从远程 GraphQL 服务器获取 API 模式🤔。
Remote schema enables Gian to copy Nobita’s API schema and reproduce it.
当大雄 web 服务正在发布其 API 文档时,graphql-tools makeRemoteExecutableSchema
(→ref) 可以获取 API 文档并复制 API。此函数接收远程 GraphQL 服务器 URL 作为参数。introspectSchema
在通常情况下连用。
Web service Gian. (gian.ts)
graphql-tools
中的makeRemoteExecutableSchema
获取大雄的 API 文档(__schema)并在该服务器中生成可执行的 API 和自己的文档。😲
这个 web 服务器从下面几行开始😜
Starting web service Gian
功能 2(混合 API)“模式拼接”
融合大雄的 API 和 Suneo 的 API(模式拼接)🤔
graphql-tools
的mergeSchemas
(→ref)作为模式拼接工具非常好用。
过程
- 使用远程模式获取 Nobita 和 Suneo 的模式(上一节)
- 将模式数组传递给
mergeSchemas
参数schemas
现在我们有了一个新的服务,包括现有的多个 API😀
功能 3(复制和定制 API)“模式委托”
当您想要复制 API 模式并进行一些定制时(例如重命名查询字段),可以使用Schema Delegation
的(→ref)graphql-tools.
的
你可以在 query resolver
中使用delegateToSchema
,然后你让你的服务器上的任何请求转移到指定的服务器并进行查询。
以下示例显示了将原始的manga
查询重命名为另一个名称orenomanga
😳
功能 4(修改 API)“模式转换”
当你想定制一个现有的 API(例如删除查询字段),你可以使用Schema Transforms
(→ref)graphql-tools.
的
以下示例暗示原始查询manga
被 Gian 移除😱
transformSchema
的第二个参数是转换类型。在本例中,它被设置为FilterRootFields
,这意味着“场移除”。
其他转换
- 过滤器类型 /移除类型/有时使用
- 有时重命名类型/使用
- TransformRootFields,RootField / 修改查询、变异、订阅/很少使用之一
- FilterRootFields / 删除字段/使用大部分
- 重命名根字段 /重命名字段/常用
- ExtractField / 换路径/不太懂……
- WrapQuery /也许全能/不太懂…
摘要
GraphQL 和graphql-tools
是优秀的工具🍺
- 复制/
makeRemoteExecutableSchema,
introspectSchema
/ 这么有用 - 迸/
mergeSchemas
/ 有用的 - 定制/
transformSchema
/也许有用
我没有提到模式指令。您可以通过身份验证来限制访问。
遗留问题
如果重用 API,可能会遇到新的问题。
- N+1 problem⌛️
有时候,会出现性能问题。模式拼接可能会从一个请求带来 N+1 个请求的结果。用于批处理查询的数据加载器对于这类问题是有效的。数据加载器由来自脸书的 GraphQL 联合开发者 Lee Byron 开发。 - 版权问题👁
当您使用任何其他人的 API 时,您必须遵守规则。例如,当重用的 API 需要 creative commons cc-by 时,必须说明作者的姓名。您可以向 GraphQL 响应添加元数据,并使用中间件进行定制。
摘要
GraphQL 工具(远程模式和模式拼接)支持复制、混合和定制 API。很简单。
图形和 ML:线性回归
原文:https://towardsdatascience.com/graphs-and-linear-regression-734d1446e9cd?source=collection_archive---------5-----------------------
为了启动机器学习的一系列 Neo4j 扩展,我实现了一组 用户定义的过程 ,在图形数据库中创建线性回归模型。在这篇文章中,我演示了在 Neo4j 浏览器中使用线性回归来建议德克萨斯州奥斯汀的短期租赁价格。让我们来看看用例:
Photo from Yelp user Benigno A. (https://www.yelp.com/user_details?userid=GS2R_auCwoSzfQccLJIY6Q)
德克萨斯州奥斯汀最受欢迎的地区是通过邮政编码的最后两位数字“04”来识别的。这里有最时尚的俱乐部、餐馆、商店和公园,“04”是游客经常去的地方。假设你是一个将要去度假的奥斯汀当地人。你想趁你不在的时候,通过出租你的房子来利用你的邻居的声望。然而,你在每晚收费多少上有点卡住了。
此处 William Lyon 使用 Neo4j 对德克萨斯州奥斯汀的现有短期房屋租赁进行建模。除了每晚的价格,每个Listing
节点还包含诸如卧室数量、浴室数量、容纳的客人数量和可用性等属性。你家有四间卧室,两间浴室,可以住五个客人。我们如何使用存储在 Will 图表中的住房数据来为您的列表预测合适的每夜房价?
Will’s data model demonstrates that the data set is well suited for Neo4j
我们必须以某种方式量化未知变量(价格)和已知变量(卧室、浴室和可容纳的客人数量)之间的关系。住房市场中的许多价格预测者使用房间总数来预测住房价格。他们假设价格和房间数量之间的关系是线性的。我们将把这一理念扩展到短期租赁市场。线性回归是一种用于分析变量之间关系的工具,在这里,它可以用于量化每晚租金与列表中总房间数之间的关系。
一些背景:
回归是建模两个变量之间关系的线性方法。因变量、 y ,是我们希望预测的数量(在本例中是租赁价格)。我们使用独立变量的已知值,“ x ”来预测因变量。简单线性回归的目标是创建一个以自变量为输入并输出因变量预测值的函数。记得代数课吗?由于模型是一条线,所以以*y* = **a** + **b****x*
的形式写出来,可以让它用两个参数唯一表示:
斜率( b )和截距( a )。
https://en.wikipedia.org/wiki/Linear_regression
目测有几个( x , y )数据点的图。简单的线性回归找出通过点的直线,这些点与数据最“符合”。为了确定最佳拟合线,我们使用最小二乘法的方法找到系数 a 和 b ,这些系数根据线性模型*y* = **a** + **b****x*
最小化每个观察值的实际 y 值与其预测 y 值之间的平方差之和。
有几种测量方法试图量化模型的成功,或它与数据的“拟合”程度。例如,决定系数(R ) 是从自变量中可预测的因变量方差的比例。系数 R = 1 表示因变量的方差完全可以从自变量中预测出来(因此模型是完美的)。
线性回归是统计学中最流行的工具之一,它经常被用作机器学习的预测器。
等等,这是图的问题吗?
最小二乘法可以追溯到 19 世纪早期。它不依赖于数据可能存储在图中的事实。如果不是图形问题,为什么要在 Neo4j 中实现线性回归?因为在我们的例子中,我们感兴趣的数据已经存在于一个图表中了!
图表是租赁数据模型的合理选择,因为短期租赁数据固有的关联特性,建模为
(:User)-[:WRITES]->(:Review)-[:REVIEWS]->(:Listing)
以及列表、用户和评论的持续更新。线性回归可能不是图的问题,但数据集总体上肯定是。价格预测只是我们想要做的整体分析的一部分。在 Neo4j 中实现回归程序可以让我们避免将数据导出到另一个软件中的麻烦。通过这种方式,我们可以利用图形数据库的独特功能,同时也不会忘记更传统的统计方法,如线性回归。我们还创建了另一个构建模块,用于在我们的图形数据上运行更复杂的分析管道。
关于这些用户自定义过程的实现细节,请查看我的下一篇文章。在这里,我们将在创建过程之后进行分析。
我们开始吧
安装程序
在 Neo4j 桌面中创建项目和数据库。从最新的线性回归版本下载 jar 文件。将 JAR 文件放到数据库的 plugins 文件夹中。将regression
包的内容添加到管理- >设置底部的已识别程序中。如果你已经安装了 APOC 和图形算法,它看起来会像这样:
dbms.security.procedures.whitelist=algo.*,apoc.*,regression.*
How to add to a Neo4j Desktop Database
重新启动数据库。奔跑
CALL dbms.procedures() YIELD name WHERE name CONTAINS 'regr' RETURN *
检查regression.linear.*
程序是否可以使用。
导入数据
打开 Neo4j 浏览器。从 Neo4j 浏览器运行:play http://guides.neo4j.com/listings
,按照导入查询创建威尔的短期租赁列表。
Neo4j Browser Guide (Slides) for the Rental Listings
添加我们的列表
创建一个新的Listing
节点,代表我们希望添加到“04”短期租赁市场的房屋。在图中,每个Neighborhood
都可以通过存储在属性neighborhood_id
中的邮政编码来识别。
MATCH (hood:Neighborhood {neighborhood_id:'78704'})
CREATE (list:Listing
{listing_id:'12345', bedrooms:4, bathrooms:2, accommodates:5})
MERGE (list)-[:IN_NEIGHBORHOOD]->(hood)
分割训练和测试数据
我们应该使用哪个房屋数据子集来创建模型?房价因位置而异,所以让我们只使用位于“04”附近的列表来创建一个模型。列表节点包含bedrooms
和bathrooms
属性,所以我们将这两个值的和作为房间总数的近似值。因此,我们的数据集是“04”邻域中具有有效的price
、bedrooms
和bathrooms
属性的所有列表。
我们可以使用整个数据集来训练模型,但这样我们就无法在看不见的数据上测试模型的性能。因此,我们将数据集分成 75:25(训练:测试)的样本。从所有合格的列表节点中收集节点 id,并使用regression.linear.split
函数随机选择 75%的数据集。用Train
标记这个子集。
MATCH (list:Listing)-[:IN_NEIGHBORHOOD]->(:Neighborhood {neighborhood_id:'78704'})
WHERE exists(list.bedrooms) AND exists(list.bathrooms)
AND exists(list.price)
WITH regression.linear.split(collect(id(list)), 0.75) AS trainingIDs
MATCH (list:Listing) WHERE id(list) in trainingIDs
SET list:Train
将:Test
标签添加到数据集中剩余的列表节点。
MATCH (list:Listing)-[n:IN_NEIGHBORHOOD]->(hood:Neighborhood {neighborhood_id:'78704'})
WHERE exists(list.bedrooms) AND exists(list.bathrooms)
AND exists(list.price) AND NOT list:Train SET list:Test
初始化模型
查看我们的create
程序,它有这样的签名:
create('model-name', 'model-type' = 'Simple',
constantTerm? = true, noOfIndependentVars = 1)
为了给将来使用相同的create
程序实施多元线性回归创造灵活性,您必须输入模型类型'Simple'
。create 过程还将模型是否应该包含常数项和独立变量的数量作为参数。这些默认设置分别等于true
和1
。如果您知道您的数据在其整个域上遵循一个线性关系,并且必须经过原点,则仅使用false
排除常数项。****
CALL regression.linear.create('rental prices', 'Simple', true, 1)
添加培训数据
找到所有标有Train
的Listing
节点,添加每个对应的(bedrooms
、price
)数据点。如果我们不小心多次添加来自同一个列表的数据,我们的模型将会不太准确。作为额外的预防措施,让我们用标签Seen
来标记Listing
节点,以表明训练数据已经被添加到模型中:
MATCH (list:Listing:Train) WHERE NOT list:Seen
CALL regression.linear.add('rental prices',
[list.bedrooms+list.bathrooms], list.price)
SET list:Seen
注意,
regression.linear.add
程序采用List<Double>
类型的独立变量,即使这是简单的线性回归。这保留了将来创建多元线性回归(具有多个独立变量)并继续使用相同程序的灵活性。
检查模型
注意在的任何一点,你都可以调用info
程序。它将总是返回关于模型的信息流,并且如果模型的状态表明这些字段是有效的,它将使用关于训练和测试数据的统计来填充trainInfo
和testInfo
映射。
CALL regression.linear.info('rental prices')
添加测试数据
既然我们已经训练了模型,我们需要在看不见的数据上测试它的性能。添加测试数据:
MATCH (list:Listing:Test) WHERE NOT list:Seen
CALL regression.linear.add('rental prices',
[list.bedrooms + list.bathrooms], list.price, **'test'**)
SET list:Seen
注意,为了添加测试数据,我们使用相同的
add
过程,但是将数据类型(采用默认值'train'
)设置为'test'
。
执行测试计算
一旦我们最终确定了测试数据,调用test
程序来分析模型。
CALL regression.linear.test('rental prices')
在这种情况下,训练** R = 0.363,测试 R = 0.456。该模型预测测试数据中出现的方差比训练中出现的方差比例更大!虽然这两个值都比我们希望的要低一点(理想情况下,R 为 0.6 或更大),但这些数字表明模型在看不见的数据上表现相似。为了直观的理解,您可以看到测试数据比训练数据更接近趋势线。这是因为采样的测试数据点较少:**
做出并存储预测
这些线性回归过程是用来自 Commons Math 库的SimpleRegression
构建的。虽然过程regression.linear.train
确实存在,并且将用于具有多个独立变量的未来线性模型,但是对于简单回归,不需要调用train
过程(如果调用,它将只返回关于模型的信息)。只要模型中有两个或更多数据点,模型就能够做出预测。作为用户,您可以决定是否在进行预测之前对模型进行测试。
既然我们已经测试了模型,我们可以做出明智的价格预测。我们可以使用用户定义的函数** regression.linear.predict
来预测您在“04”中列出的 4 卧室、2 浴室(总共大约 6 个房间)的价格:**
RETURN regression.linear.predict('rental prices', [6])
或者在图表中为每个价格未知的“04”列表进行预测并存储预测:
MATCH (list:Listing)-[:IN_NEIGHBORHOOD]->
(:Neighborhood {neighborhood_id:'78704'})
WHERE exists(list.bedrooms)and exists(list.bathrooms)
AND **NOT exists(list.price)**WITH list, list.bedrooms + list.bathrooms as rooms
SET list.predicted_price =
regression.linear.predict('rental prices', [rooms])
RETURN DISTINCT rooms, list.predicted_price AS predictedPrice
ORDER BY rooms
现在,所有“04”列表都存储了推荐价格,可以提供给主机,以帮助他们做出明智的价格选择。
编辑测试/培训数据
我们对数据集一无所知,只知道所有列表都位于“04”中,并且包含有效的bedrooms
、bathrooms
和price
数据。让我们通过排除不受欢迎的列表来改进我们的模型。我们将只列出属于(:Review)-[:REVIEWS]->(:Listing)
关系的数据点,这表明该列表至少有一个审查。希望这将消除来自新上市房源的数据(潜在的不可靠定价)。
首先,通过从“租赁价格”模型中复制培训数据来创建一个新模型。
CALL regression.linear.create('popular rental prices', 'Simple')
CALL regression.linear.copy('rental prices',
'popular rental prices')
然后通过从没有评论的列表中删除数据来编辑模型。
MATCH (list:Listing:Train)
WHERE **NOT (:Review)-[:REVIEWS]->(list)**
CALL regression.linear.**remove**('popular rental prices',
[list.bedrooms+list.bathrooms], list.price)
REMOVE list:Train, list:Seen
现在,我们必须从没有审查的列表中删除测试数据。随着测试数据被添加到模型中,使用在训练期间创建的模型参数来执行计算。因此,如果任何训练数据被更新,则模型改变,并且所有测试计算无效。更改训练数据会自动使测试数据无效。因此,我们必须从没有评论的列表中删除Test
标签,然后重新添加所有剩余的测试数据。
请注意,如果在模型测试期间,您希望更新测试数据,您可以调用
regression.linear.add
或regression.linear.remove
而无需重新添加所有测试数据。只要训练数据保持不变,这就会起作用。
MATCH (list:Listing:Test) WHERE NOT (:Review)-[:REVIEWS]->(list) REMOVE list:Test
MATCH (list:Listing:Test)
CALL regression.linear.add('popular rental prices',
[list.bedrooms + list.bathrooms], list.price, 'test')
RETURN count(list)
CALL regression.linear.test('popular rental prices')
哇,消除“不受欢迎”的列表数据提高了我们模型的拟合度!现在,训练 R = 0.500,测试 R = 0.561。两者都增加了,而且测试 R 再次高于训练。这表明我们的模型更好地解释了价格数据中的差异,并在看不见的数据上表现良好。让我们更新图表中的预测价格:
MATCH (list:Listing)-[:IN_NEIGHBORHOOD]->
(:Neighborhood {neighborhood_id:’78704'})
WHERE exists(list.bedrooms)and exists(list.bathrooms)
AND NOT exists(list.price)WITH list, list.bedrooms + list.bathrooms AS rooms
SET list.predicted_price =
regression.linear.predict('popular rental prices', [rooms])RETURN DISTINCT rooms, list.predicted_price AS predictedPrice
ORDER BY rooms
存储、删除和重新加载模型
我们完成了今天的分析!让我们保存刚刚创建的模型。SimpleRegression
的每个命名实例都作为静态变量存储在用户定义的过程中。只要数据库关闭,这些变量就会被清除。确保在关闭数据库之前,您存储了您想要在图中或外部保留的任何模型的序列化版本:
MERGE (m:ModelNode {model: 'popular rental prices'})
SET m.data = regression.linear.data('popular rental prices')
删除模型:
CALL regression.linear.delete('popular rental prices')
当您重新启动数据库时,将模型从图中加载回过程中:
MATCH (m:ModelNode {model: 'popular rental prices'})
CALL regression.linear.load(m.model, m.data, 'Simple')
YIELD model, framework, hasConstant, numVars, state, nTrain, nTest, trainInfo, testInfo
RETURN *
现在,模型已经准备好进行额外的数据更改、测试和预测了!注意,新加载的简单回归不包含任何测试数据。
附加功能
请注意,以下程序存在,但不在本文讨论范围内:
regression.linear.clear
-默认情况下清除模型中的所有数据,或者只清除带有附加参数的测试数据'test'
regression.linear.addM
-从输入/输出数据列表中添加相应的数据点。如果从外部来源(如 CSV 文件)添加数据,会很有帮助regression.linear.removeM
-从输入/输出数据列表中删除相应的数据点
有问题吗?评论?你是更新测试数据回归平方和(SSR)计算公式的专家吗(我需要一些帮助)?请联系 LinkedIn 或 @ML_auren
特别感谢格蕾丝·特诺里奥对这个项目的帮助。查看她的博客或在推特上与她交谈
图形和 ML:多元线性回归
原文:https://towardsdatascience.com/graphs-and-ml-multiple-linear-regression-c6920a1f2e70?source=collection_archive---------4-----------------------
上一次 ,我用 简单的 线性回归从 Neo4j 浏览器创建了一个德克萨斯州奥斯汀的短期租房的模型。在这篇文章中,我演示了如何通过一些小的调整,同一套 用户定义的过程 可以创建一个带有多个 独立变量的线性回归模型。这被称为多元线性回归。
Nightlife in Austin, TX (https://www.nestvr.com/)
我们之前使用短期租赁列表中的房间总数来预测每晚的价格。然而,显然还有其他因素可能会影响价格。例如,一个列表接近热门旅游区可能会极大地影响其价值。让我们再来看看 Will 的数据模型,看看还有哪些额外的信息可以用来预测租赁价格。
Will Lyon’s rental listing data model with node properties
因为我们没有地址,所以很难分析一个列表相对于奥斯汀最受欢迎的目的地的位置。相反,考虑一下(:Review)-[:REVIEWS]->(:Listing)
关系。在我之前的文章中,我限制我的数据集只包括至少有一个评论的列表。我这样做是为了剔除定价可能不可靠的新上市商品,这大大提高了我的模型的拟合度。现在,让我们更深入一点,除了房间数量之外,使用一个列表的评论数量来预测每晚的价格。
请注意,我只是玩玩,并没有真正的统计理由来假设评论数量影响上市价格。我这样做主要是为了演示如何创建一个有多个自变量的模型。接下来分析评论并以某种方式量化文本的正面/负面反馈会很有趣。
一些背景
在我们回到奥斯汀租赁市场之前,我将回顾一下多元线性回归的重要细节。请记住,在简单线性回归中,我们希望使用单个独立变量“ x ”的值来预测因变量、 y 的值。不同的是,在多元线性回归中,我们用多个自变量( x1,x2,…,xp )来预测 y 而不是只有一个。
对多元线性回归的直观理解有点复杂,取决于自变量的数量( p) 。如果 p = 1,这只是简单线性回归的一个实例,并且( x1,y )数据点位于标准的二维坐标系中(具有 x 和 y 轴)。线性回归通过最“适合”数据的点找到线。
Visual for p = 1 (https://en.wikipedia.org/wiki/Linear_regression)
如果 p = 2,这些( x1,x2,y) 数据点位于三维坐标系中(具有 x,y,和 z 轴),多元线性回归找到最适合数据点的平面。
Visual for p = 2 (https://www.mathworks.com/help/stats/regress.html)
对于更多数量的独立变量,视觉理解更抽象。对于 p 自变量,数据点( x1,x2,x3 …,xp,y )存在于一个 p + 1 维空间中。真正重要的是,线性模型(是 p 维)可以用 p + 1 系数β0 , β1 ,…, βp 来表示,这样 y 就可以用公式*y =* **β0** + **β1****x1* + **β2****x2* + … + **βp****xp*
来近似。
小心!
多元线性回归有两种:普通最小二乘法(OLS) 和广义最小二乘法(GLS) 。两者之间的主要区别在于,OLS 假设任何两个独立变量之间都有很强的相关性。GLS 通过转换数据来处理相关的独立变量,然后使用 OLS 用转换后的数据建立模型。
这些程序使用 OLS 的方法。因此,要建立一个成功的模型,你应该首先考虑你的变量之间的关系。将bedrooms
和accommodates
作为两个独立变量可能不是一个好主意,因为客房数量和入住的客人数量可能有很强的正相关性。另一方面,评论数量和房间数量之间没有明确的逻辑关系。为了进行更定量的分析,挑选独立变量,使每一对变量的皮尔逊相关系数接近于零(见下文)。
多个 LR 在工作
好了,让我们来看一组在 Neo4j 中构建多元线性回归模型的查询。
建立
从最新的线性回归版本下载并安装 jar 文件。从 Neo4j 浏览器运行:play http://guides.neo4j.com/listings
,按照导入查询创建威尔的短期租赁列表。请参阅我之前的文章以获得安装 g 线性回归程序和导入奥斯汀租赁数据集的更全面的指南。
分割训练和测试数据
导入数据集并安装程序后,我们将数据集分成 75:25(训练:测试)的样本。让我们从上次的最终模型开始,再次只考虑至少有一个评论的列表。用:Train
标注 75%。
MATCH (list:Listing)-[:IN_NEIGHBORHOOD]->(:Neighborhood {neighborhood_id:'78704'})
WHERE exists(list.bedrooms)
AND exists(list.bathrooms)
AND exists(list.price)
**AND (:Review)-[:REVIEWS]->(list)** WITH regression.linear.split(collect(id(list)), 0.75) AS trainingIDs
MATCH (list:Listing) WHERE id(list) in trainingIDs
SET list:Train
并给剩下的 25%加上:Test
的标签。
MATCH (list:Listing)-[n:IN_NEIGHBORHOOD]->(hood:Neighborhood {neighborhood_id:'78704'})
WHERE exists(list.bedrooms)
AND exists(list.bathrooms)
AND exists(list.price)
**AND (:Review)-[:REVIEWS]->(list)**
AND NOT list:Train
SET list:Test
量化相关性
如果您想知道自变量之间的皮尔逊相关性,请使用函数regression.linear.correlation(List<Double> first, List<Double> second)
。此函数的一个List<Double>
输入包含来自许多列表的聚合“评论数”数据,并且每个“评论数”是通过聚合来自每个列表的关系来计算的。我们不能在同一个查询中执行两个级别的聚合(collect(count(r))
)。因此,我们必须执行两个查询。
首先在数据集列表上存储一个num_reviews
属性。
MATCH (:Review)-[r:REVIEWS]->(list)
WHERE list:Train OR list:Test
WITH list, count(r) AS num_reviews
SET list.num_reviews = num_reviews
然后从所有列表中收集(num_reviews,rooms)数据并计算相关性。
MATCH (list)
WHERE list:Test OR list:Train
WITH collect(list.num_reviews) as reviews,
collect(list.bedrooms + list.bathrooms) as rooms
RETURN regression.linear.correlation(reviews, rooms)
皮尔逊相关系数在[-1,1]范围内,0 表示不相关,1 表示完全正相关,而-1 表示完全负相关。评论数量和房间数量具有相关性-0.125,这表明非常弱的负相关性。对于这种小相关性,OLS 是一种可接受的方法,因此我们可以继续使用该模型。阅读更多关于解释相关系数的信息。
初始化模型
我们调用相同的create
过程,但是现在我们的模型框架是'Multiple'
而不是'Simple'
,独立变量的数量是2
而不是1
。
CALL regression.linear.create(
'mlr rental prices', **'Multiple'**, true, **2**)
添加培训数据
以与简单线性回归相同的格式添加已知数据。只需在自变量列表中添加另一个条目(评论数量)即可。
MATCH (list:Train)
WHERE NOT list:Seen
CALL regression.linear.add(
'mlr rental prices',
[list.bedrooms + list.bathrooms**, list.num_reviews**],
list.price)
SET list:Seen RETURN count(list)
训练模型
我们必须训练模型,使线参数(βi)、决定系数(R)等。是在接受测试数据或做出预测之前计算出来的。如果您忘记了这一步,然后尝试添加测试数据或进行预测,您的模型将会自动首先接受训练。
CALL regression.linear.train('mlr rental prices')
注意,在调用
train
过程后,您仍然可以添加更多的训练数据。你只需要在测试新型号之前再打一个电话给train
!
添加测试数据
根据看不见的数据分析模型的性能。请记住,当您添加测试数据时,需要一个额外的参数'test'
作为过程regression.linear.add
的输入。
MATCH (list:Test)
WHERE NOT list:Seen
CALL regression.linear.add(
'mlr rental prices',
[list.bedrooms + list.bathrooms, list.num_reviews],
list.price,
**'test'**)
SET list:Seen
RETURN count(list)
测试模型
现在所有的测试数据都已添加,调用test
过程来计算测量值(在下面的testInfo
中),以便我们分析模型的性能。
CALL regression.linear.test('mlr rental prices')
您也可以通过调用info
过程随时返回关于模型的信息。
CALL regression.linear.info('mlr rental prices')
再来看调整后的 R 。这个值类似于我们在上一篇文章中考虑的 R,但它被调整了,这样,随着独立变量被添加到模型中,调整后的 R 不会增加,除非模型被改进得比它偶然得到的更多。因此,当将我们的多元线性回归模型(有两个独立变量)与之前的模型(只有一个独立变量)进行比较时,调整后的 R 是更好的成功衡量标准。
我们通常寻找大于 0.6 的 R 值,但是更接近 1 的值表示更好的线性拟合。这里,训练调整 R = 0.517,测试调整
R = 0.556。上次我们训练和测试的 R 值分别是 0.500 和 0.559。使用多元线性回归创建的模型在训练数据上比上次的简单回归模型表现得好一点,在测试数据上表现得差不多。能不能找到更好的自变量,改进我的工作?
后退一步
在 Neo4j,我和我的同事们目前面临着这样一个问题:机器学习和人工智能在图数据库中处于什么位置?这个问题有几个答案,但没有一个是“正确”的。在我以前的帖子中,我演示了如何根据图中的数据建立一个简单的机器学习模型,以避免导出到另一个软件。在这篇文章中,另一个有趣的方面出现了:用存储在图的结构中的数据构建模型的能力。我们能够通过计算每个列表上的(:Review)-[:REVIEWS]->(:Listing)
关系的数量来轻松检索“评论数量”数据。在这方面,图形数据库增加了我们可以轻松访问的数据类型,以便建立机器学习模型。
展望未来,我很想探索机器学习模型如何更有效地利用数据集的图结构来学习和做出预测。
摘要
下面是使用多元线性回归的regression.linear.*
过程时必须做出的调整的快速列表:
- 在
regression.linear.create
期间指定型号“Multiple”
- 在
regression.linear.create
期间指定独立变量的数量 - 没有或
regression.linear.remove
方法用于测试或训练数据 - 你不能用
regression.linear.copy
将训练数据从一个模型复制到另一个模型 - 在测试、分析或预测之前,您应该通过调用
regression.linear.train
来训练模型 - 查看
adjusted R²
以更准确地比较具有不同数量独立变量的模型 regression.linear.data
返回模型的参数,不将其字节【序列化】。所以不能用regression.linear.load
。(我想解决这个问题)
这个项目是实验性的,所以我真的很感谢任何反馈。检查程序存储库并联系 LinkedIn 或 @ML_auren 。
对我来说,是时候离开这个线性建模的世界,转而使用逻辑回归构建分类器了。敬请关注新的一组程序和新的数据集!
模型调整的网格搜索
原文:https://towardsdatascience.com/grid-search-for-model-tuning-3319b259367e?source=collection_archive---------0-----------------------
模型 超参数 是模型外部的模型特征,其值无法从数据中估计。必须在学习过程开始之前设置超参数的值。比如支持向量机中的 c ,k-最近邻中的 k ,神经网络中的隐层数。
相反, 参数 是模型的内部特性,其值可以从数据中估计。例如,线性/逻辑回归的β系数或支持向量机中的支持向量。
网格搜索用于寻找模型的最佳超参数,从而产生最“准确”的预测。
让我们通过在乳腺癌数据集上建立分类模型来看看网格搜索。
1.导入数据集并查看前 10 行。
输出:
数据集中的每一行都有两个可能的类别:良性(用 2 表示)和恶性(用 4 表示)。此外,该数据集中有 10 个属性(如上所示)将用于预测,除了作为 id 号的样本代码号。
2.清理数据,并将类值重命名为 0/1,用于建模(其中 1 表示恶性病例)。还有,我们来观察一下班级的分布。
输出:
良性病例 444 例,恶性病例 239 例。
3.在构建分类模型之前,让我们构建一个虚拟分类器来确定“基线”性能。这就回答了这个问题——“如果只是猜测,这个模型的成功率会是多少?”我们使用的虚拟分类器将简单地预测多数类。
输出:
从输出中,我们可以观察到测试数据集中有 68 个恶性和 103 个良性案例。然而,我们的分类器预测所有病例都是良性的(因为它是多数类)。
4.计算此模型的评估指标。
输出:
模型的准确性为 60.2%,但这是准确性可能不是评估模型的最佳度量的情况。那么,让我们来看看其他评估指标。
上图是混淆矩阵,添加了标签和颜色以便更直观(生成该矩阵的代码可以在这里找到)。总结一下混淆矩阵:真阳性(TP)= 0,真阴性(TN)= 103,假阳性(FP)= 0,假阴性(FN)= 68。评估指标的公式如下:
由于该模型没有对任何恶性病例进行正确分类,因此召回率和精确度指标为 0。
5.现在我们已经有了基线精度,让我们用默认参数建立一个逻辑回归模型并评估这个模型。
输出:
通过用默认参数拟合逻辑回归模型,我们得到了一个“更好”的模型。准确率为 94.7%,同时精度更是惊人的 98.3%。现在,让我们再次看一下该模型结果的混淆矩阵:
查看错误分类的实例,我们可以观察到 8 个恶性病例被错误地分类为良性(假阴性) 。此外,只有一个良性病例被归类为恶性(假阳性)。
假阴性更严重,因为疾病被忽略了,这可能导致患者死亡。同时,假阳性会导致不必要的治疗——产生额外的费用。
让我们通过使用网格搜索来寻找最佳参数,从而尽量减少假阴性。网格搜索可用于改进任何特定的评估指标。
我们需要关注的减少假阴性的指标是召回。
6.网格搜索最大化回忆
输出:
我们调整的超参数是:
- 惩罚 : l1 或 l2,指定惩罚中使用的标准。
- C :正则化强度的倒数——C 值越小,正则化越强。
此外,在网格搜索功能中,我们有一个评分参数,可以指定评估模型的指标(我们选择了 recall 作为指标)。从下面的混淆矩阵中,我们可以看到假阴性的数量减少了,然而,这是以假阳性增加为代价的。网格搜索后的召回率从 88.2%上升到 91.1%,而准确率从 98.3%下降到 87.3%。
通过使用“f1”分数作为评估指标,您可以进一步调整模型,以在精确度和召回率之间取得平衡。查看这篇文章,更好地理解评估指标。
网格搜索为指定的每个超参数组合建立一个模型,并评估每个模型。一种更有效的超参数调整技术是随机搜索,其中超参数的随机组合用于寻找最佳解决方案。
连接 LinkedIn和 Github查看完整的笔记本。
[## rohanjoseph 93/用于数据科学的 Python
用 Python 学习数据科学。通过创建帐户,为 rohanjoseph 93/Python-for-data-science 开发做出贡献…
github.com](https://github.com/rohanjoseph93/Python-for-data-science/blob/master/Grid Search - Breast Cancer.ipynb)
基本事实与偏见
原文:https://towardsdatascience.com/ground-truth-versus-bias-99f68e5e16b?source=collection_archive---------9-----------------------
Photo by David Kovalenko on Unsplash
机器学习的主要目标是在给定一组输入的情况下预测结果。在人工智能社区取得的惊人进展中,这个目标一直保持不变。几十年前的这些进步引导我们研究今天有趣的社会含义。具体来说,在我们的算法技术中嵌入的基本事实和偏见之间有一种独特而敏感的相互作用。
相互影响
基础事实是我们的模型用来训练和测试自己的标记结果。通过有监督的机器学习方法,我们的模型试图将输入与这一事实联系起来。也就是说,当我们命令脚本进行拟合和预测时,我们会做出一些假设。我们说,我们相信有一种关系存在,这些变量有一些预测能力,这些结束标签是最终的真相。
最后一点可能会有点模糊。
我们怎么知道末端标签是真实的呢?好吧,如果我们谈论的是试图预测温度,我们可以相当肯定的是,这些数字中有很多是真实的。也就是说,现在的温度传感技术既精确又准确。然而,如果我们预测某个人是否会得到贷款,或者某个人是否是 x 公司的合适人选呢?
这就是有趣的地方。在这些情况下,我们引入了偏见——人为的偏见,隐含的和未知的偏见。这些混杂的变量可以成就或破坏一个实验,这就是为什么人们大声疾呼在我们的算法中包含多样性。
我同意这个观点。然而,我也相信我们的算法是工具,不管数据集如何多样化,垃圾进垃圾出的概念仍然盛行。
也就是说,这是良好的第一步。我相信,提高算法可推广性的下一步是始终回到最初的、潜在的假设,并作为数据科学家批判性地评估它们。
我们真正要求算法做的是什么?有没有可以减轻偏差的来源
这些问题至关重要,尤其是当我们使用这些模型来筛选一组从事特定任务的人时。也许我们会在此期间发现一些关于我们自己的有趣的事情。
感谢阅读。
分组卷积—并行卷积
原文:https://towardsdatascience.com/grouped-convolutions-convolutions-in-parallel-3b8cc847e851?source=collection_archive---------2-----------------------
通常,卷积滤波器被逐层应用于图像以获得最终的输出特征图。我们增加每层内核的数量来学习更多的中间特征,从而增加下一层的通道数量。但是为了了解更多的特征,我们也可以创建两个或更多的模型,并行地训练和反向传播。在同一幅图像上使用不同组卷积滤波器组的过程称为分组卷积。简而言之,创建一个具有一定数量层的深层网络,然后复制它,以便在一个图像上有不止一个卷积路径。这种分组卷积思想的第一次使用可以在 Alexnet 中看到,如下所示。
Grouped convolutions in ALexnet
Alexnet 中使用了分组卷积,以便深度神经网络可以在当时可用内存较小的功能较弱的 GPU 上进行训练。为了理解分组卷积的重要性,让我们想象一个没有分组卷积的世界,以及我们可能面临的问题:
- 我们构建每层多个内核的深度网络,从而在每层产生多个通道输出。基于我们的网络学习各种各样的低级和高级特征的希望,这将导致更宽的网络。
- 每个核滤波器对在前一层获得的所有特征图进行卷积,导致大量卷积,其中一些可能是冗余的。
- 训练更深层次的模型将是一场噩梦,因为在单个 GPU 上拟合这些模型并不容易。即使这是可能的,我们可能不得不使用较小的批量,这将使整体收敛困难。
我们可以开始看到分组卷积对于训练深度网络是多么重要。下图显示了如何理解 ResNext 体系结构中的分组卷积:
Grouped convolutions in ResNext
通过使用分组卷积,让我们逐一解决上述问题:
- 通过分组卷积,我们可以构建任意宽的网络。取一个过滤器组模块并复制它们。
- 现在,每个滤波器只对从其滤波器组中的核滤波器获得的一些特征图进行卷积,我们大大减少了获得输出特征图的计算量。当然,你可以说我们复制了过滤器组,导致了更多的计算。但是为了客观地看待问题,如果我们将所有的内核过滤器都放在分组卷积中,并且不使用分组卷积的概念,那么计算的数量将呈指数增长。
- 我们可以通过两种方式并行培训:
- —数据并行性:我们将数据集分成块,然后在每个块上进行训练。直观上,每个块可以被理解为在小批量梯度下降中使用的小批量。块越小,我们可以从中挤出更多的数据并行性。然而,更小的组块也意味着我们在训练中更像随机而不是批量梯度下降。这将导致收敛速度变慢,有时收敛效果更差。
- —模型并行性:在这里,我们尝试将模型并行化,以便我们可以接收尽可能多的数据。分组卷积实现了高效的模型并行,以至于 Alexnet 在只有 3GB RAM 的 GPU 上进行了训练。
Grouped convolutions’ performance nos
除了解决上述问题之外,分组卷积似乎可以更好地表示数据。本质上,不同过滤器组的内核过滤器之间的相关性通常很小,这意味着每个过滤器组正在学习数据的唯一表示。这在传统的神经网络中是不容易实现的,因为核通常是相互关联的。事实上,上图显示了增加组数对模型整体准确性的影响。最棒的是,所有的精度都来自降低的计算成本。
这篇文章的灵感来自雅尼·若安努的另一篇精彩文章,标题为滤波器组(分组卷积)教程,提供了更详细的分析。
使用内容分组对内容进行分组
原文:https://towardsdatascience.com/grouping-content-with-content-groupings-a8d01493b7a?source=collection_archive---------2-----------------------
本周,我有幸在纽约州布法罗市的 WPCampus 举办了一场关于谷歌分析的研讨会。我在会议期间演示的一个功能是使用内容分组,以便能够更好地理解作为比较单位的网站的各个部分。在与其他人交谈后,我认为有必要对这个特性和一些例子进行更深入的讨论。所以,给你!
你可能会问,什么是内容分组?这个设置非常自我描述——它是 Google Analytics 的视图管理中的一个功能,可以让你将网站某个部分的内容定义为属于某种类别。谷歌的文档使用了一个商店示例,展示了如何根据产品使用的方面命名法将产品集合分组在一起。
Initial Content Groupings Panel
我将演示的例子使用了来自我的演示站点的虚拟课程目录的课程部分级别。正如您在上面看到的,我设置了三个内容分组(其中两个我已经弃用)。类似于目标,一旦你进行了分组,你实际上就无法摆脱它。你只需要关掉它或者改变它的用途。同样值得注意的是,您最多只能有 5 个分组类别,所以如果您认为您可能会大量使用该功能,请花一些时间提前计划,以便以提供最大实用价值的方式创建顶级分组。
Making a new Content Grouping via tracking code
在 g 中创建一个内容组就像点击新内容分组按钮并给它命名一样简单。这是第一步。这是您在分析报告中使用内容分组功能时将看到的名称。在那里,您将看到三种方法来确定将与该选择一起出现的组。第一种方法是启用跟踪代码。这意味着你告诉 Google,你将在你的站点上使用 JavaScript 代码动态地提供名称(或者你将在标签管理器中使用标签,见最后一节)。
如果您使用跟踪代码方法,请记下适合您的分析实现的代码版本(此时最像通用分析)。您需要将它复制到页面上与您告诉 Google 的所属组相匹配的某个 JavaScript 中。所以在我的例子中,我的内容分组是名称课程,我将要使用的组名称将是 100 级课程和 200 级课程。在我的例子中,我不打算使用这种方法,但是如果我这样做了,大一学生的课程页面上的代码将看起来像这样:
ga('set', 'contentGroup1', '100 Level Courses');
创建组名的第二个选项是使用提取规则。这允许您使用 regex 来定义页面路径、页面标题或应用程序屏幕名称的一部分,以按照约定提供组名。根据我的例子给出的页面结构,看起来应该是这样的:
Using page path to determine the content group name.
这很好,也很有效,但是这意味着我的内容组名称会有点难看。在我的例子中,根据我的 URL,这些名字可能是 1xx 或 2xx 。可用,但不美观。页面标题提取可以提供更好的可读性,但是在我的例子中,页面标题不包括文本数据,这很好地满足了这个目的。值得一提的是,在这个和下一个选项中,如果与您的群组匹配的内容出现在网站的不同部分,您可以设置多个提取。这些规则将按照您列出它们的顺序应用,就像过滤器在视图上的应用一样。一旦有匹配的提取,它就停止检查。
最后一个选项是我最喜欢的,它提供了很大的灵活性,而不需要太多额外的努力。它基本上是提取选项的一个稍微高级的版本。这是组使用的规则定义。
My catalog rule definitions.
在这里,您可以看到我已经创建了两个组名,每个组名都基于我创建的目录的各个部分。显然,一个真正的内容分组可以有更多,但这只是一个演示案例。所以你有两个。规则定义基本上类似于自定义命名的提取,使用您提供的名称,而不是由提取产生的匹配。因此,如果我们看一个,我们会看到一个类似的匹配设置,如上例。
Rule to match all 100 level courses.
有了这些规则,Google Analytics 将开始跟踪与我的正则表达式匹配的页面,这样我就可以在我的内容报告中看到它们。这对于比较整体区域或不同类型的内容非常有用。因此,如果我想查看我的目录中不同类别的流量比较,我可以查看我的行为>网站内容>所有页面报告,并查看您的主维度的选项,您现在可以选择将内容分组更改为您选择的组,在我的情况下是课程。
Viewing a content report with content groupings enabled.
现在我可以看到,在我想象的目录中查看 200 门水平课程的用户的退出率大大高于 100 门水平课程(注意:我使用数据表正上方右侧的按钮将该报告切换到了对比视图),并且远远高于其他所有课程。每当你在你的内容分组维度中看到(未设置)值时,这表示你的站点上的内容在内容分组下没有被分配任何组名。它基本上是给你一个基线,让你可以和你的团队进行比较。
考虑到这一点,你可以开始考虑将它应用到大学网站或其他地方的所有方法,将所有大区域的内容聚集在一起,在那里你有许多不同的部分,你想与他人进行比较。一些想法可能是(格式遵循内容组>组名结构):
- 学术部门>部门名称
- 学院>学院名称
- 新闻>新闻类别
- 运动>运动名称
- 学生生活>服务类型
- 事件>事件类别
- 位置>位置类型
- 专业>专业名称
这样做,如果你的物理系有 87%的退出率,你可以将它与通信系的 32%的退出率进行比较,并意识到可能是你网站的物理系出现了问题,导致人们离开。它消除了使用 Data Studio 或其他工具进行更复杂的计算或定制报告来确定这些块如何比较的需要。
我要提到的另一个技术要点是,您也可以使用 Google Tag Manager 来确定类别组名称。正如我在开始时提到的,您可以使用跟踪代码作为名称的传输机制。Simo Ahava 有一个关于如何使用标签管理器的教程。它有点旧(你现在会使用谷歌分析设置变量,但它仍然会给你一些基本的东西。
Content Groups in Google Tag Manager
他的例子使用多个标签来实现这个目的。在上面的截图中,我使用了单个 pageview 标签中的变量,它可以使用一个 JavaScript 变量或 dataLayer 变量来检查页面的路径,并确定它应该指向的内容组索引,以及它应该如何基于此获得名称。这减轻了您创建决定这一切的代码的责任,但这也使它成为最灵活的方法,并且比在站点模板使用的原始 JavaScript 文件中做同样的事情更容易维护。
这就是在谷歌分析中使用内容分组的优缺点。想一想你可能如何应用它们,或者在下面的评论中分享你当前的实现,让其他人看到。
原载于 2017 年 7 月 15 日fienen.com。
GSoC 2017:神功文档的 Eclipse 插件
原文:https://towardsdatascience.com/gsoc-2017-eclipse-plugin-for-siddhi-documentation-c4d82e8089cb?source=collection_archive---------11-----------------------
WSO2 复杂事件处理器(WSO2 CEP)是一个实时复杂事件处理引擎,在识别传入的事件流/大型数据馈送中的模式时具有快速的响应时间,并且存储空间最小。WSO2 CEP 的核心是 Siddhi,这是一种类似 SQL 的查询语言,用于模式和序列检测等复杂查询,几乎解决了复杂事件处理中抑制应用程序性能指标的所有问题。
除了组织给出的项目目标之外,还完成了从 Antlr 到 Xtext 的语法文件转换,并修复了神功语法中的歧义。
迄今为止所做的工作如下。
- 神功语法文件的 Antlr 到 Xtext 转换
- 修正神功语法中的歧义
- 语法和语义突出显示
- 内容辅助
- 错误报告
Antlr 到 Xtext 神功语法文件转换
原始神功语法文件是用 Antlr 写的。因为 Xtext 被确定在这个项目中使用,所以将 Antlr 语法文件转换成 Xtext 是必要的。Xtext 框架是在 Antlr LL(*)解析器生成器之上开发的。尽管 Antlr 和 Xtext 的语法大致相似,但在 Siddhi 语法中处理左递归是我在转换语法文件时面临的一个挑战,因为 Xtext 处理它的方式不同。因为 LL 解析器是一个自顶向下的解析器,并且输入是从左到右传递的,所以需要小心处理左递归。EveryPatternSourceChain、PatternSourceChain、LeftAbsentPatternSource、RightAbsentPatternSource、LeftAbsentSequenceSource、RightAbsentSequenceSource、SequenceSourceChain 和 MathOperation 是为 Xtext 解析器生成器设置了左递归调用图的规则。下面描述一个例子。
神功最初的 EveryPatternSourceChain 和 PatternSourceChain 规则如下。
every_pattern_source_chain :
'('every_pattern_source_chain')' within_time?
| EVERY '('pattern_source_chain ')' within_time?
| every_pattern_source_chain '->' every_pattern_source_chain
| pattern_source_chain
| EVERY pattern_source within_time? ; pattern_source_chain :
'('pattern_source_chain')' within_time?
| pattern_source_chain '->' pattern_source_chain
| pattern_source within_time? ;
规则 every_pattern_source_chain 在“every _ pattern_source_chain”->“every _ pattern _ source _ chain”替代元素中留下了递归,并且规则 pattern _ source _ chain 在“pattern _ source _ chain”->“pattern _ source _ chain”替代元素中留下了递归,因为最左边的符号是规则本身。这些被转换成 Xtext 语法,如下所示。
EveryPatternSourceChain:
EveryPatternSourceChain1 =>({EveryPatternSourceChain.left=current} op= ‘->’ right=EveryPatternSourceChain1)*;EveryPatternSourceChain1 returns EveryPatternSourceChain:
=>(OPEN_PAR eps=EveryPatternSourceChain CLOSE_PAR wt=WithinTime?)
|psc=PatternSourceChain
|every=EVERY psc=PatternSourceChain1;PatternSourceChain:
PatternSourceChain1 -> ({PatternSourceChain.left=current} op=’->’ right=PatternSourceChain1)*;PatternSourceChain1 returns PatternSourceChain:
=>(OPEN_PAR psc_2=PatternSourceChain CLOSE_PAR wt=WithinTime?)
|ps=PatternSource wt=WithinTime?;
移除 MathOperation 规则中的左递归是一项不同的任务,因为它需要考虑语法的运算符优先级。运算符优先级越高,规则调用得越晚。例如,下面解释规则的一部分。
原始 MathOperation 规则的一部分如下。
math_operation :
'('math_operation')'
|null_check
|NOT math_operation
|math_operation (multiply='*'|devide='/'|mod='%') math_operation
|math_operation (add='+'|substract='-') math_operation
|function_operation
|constant_value
|attribute_reference;
这里“math _ operation(multiply = ' * ' | devide = '/' | mod = ' % ')math _ operation”和“math _ operation(add = '+' | subtract = '-')math _ operation”是左递归规则。由于乘法的运算符优先级高于加法,所以应该在 Xtext 中首先调用与加法相关的规则,如下所示。
MathOperation:
MathAddsubOperation;MathAddsubOperation returns MathOperation:
MathDivmulOperation =>({MathAddsubOperation.left=current} (add='+'|substract='-') right=MathDivmulOperation)*;MathDivmulOperation returns MathOperation:
MathOtherOperations =>({MathDivmulOperation.left=current} (multiply='*'|devide='/'|mod='%') right=MathOtherOperations)*;MathOtherOperations returns MathOperation:
=>({NotOperation} not=NOT op=MathOperation)
|OPEN_PAR op=MathOperation CLOSE_PAR
|=>NullCheck
|mathOtherOperations1=MathOtherOperations1;MathOtherOperations1:
const_val=ConstantValue
|fo=FunctionOperation
|attrRef=AttributeReference;
其他 Antlr 至 Xtext 转换可在此处找到。
修正语法中的歧义
语法中的模糊性会导致特定输入有几个解析树,而解析器无法确定它应该遍历的确切路径。特别是在 Xtext 中,歧义可以通过使用句法谓词、左因子分解和在工作流中启用回溯来解决。启用回溯并不是一个好的选择,因为它隐藏了由模糊语法引起的大问题。
我使用了 Antlrworks 调试工具来识别语法中的歧义,以及输入如何通过解析器进行解析。也就是说,它显示了在解析树表示中为特定用户输入解析了哪些规则。Antlrworks 以如下所示的典型方式显示语法规则中的歧义。两个彩色箭头显示了导致特定模糊性的两个可选路径。
Xtext 中有两种类型的语法谓词运算符,即“->”和“= >”。“-->”是第一个标记谓词,表示如果您处于决策点,无法做出决策,请查看第一个标记并做出决策。" = > "表示如果你正处于一个决定点,难以做出决定,检查语法的特定部分并做出决定。
例如,LogicalStatefulSource 规则中的歧义是使用如下的句法谓词解决的。
LogicalStatefulSource:
=>(stdSource+=StandardStatefulSource and=AND)stdSource+=StandardStatefulSource
|=>(stdSource+=StandardStatefulSource or=OR) stdSource+=StandardStatefulSource;
这意味着,如果解析器处于 LogicalStatefulSource,需要做出决定,请考虑“(STD source+= StandardStatefulSource AND = AND)”或“= >(STD source+= StandardStatefulSource OR = OR)”来决定选择哪个备选项。
另一个例子是 ExecutionPlan 的歧义修复,如下所示。
最初的规则是,
siddhi_app :
(app_annotation|error)* ( (definition_stream|definition_table|definition_trigger|definition_function|definition_window|definition_aggregation|error) (';' (definition_stream|definition_table|definition_trigger|definition_function|definition_window|definition_aggregation|error))* ';'? || (execution_element|error) (';' (execution_element|error))* ';'? || (definition_stream|definition_table|definition_trigger|definition_function|definition_window|definition_aggregation|error) (';' (definition_stream|definition_table|definition_trigger|definition_function|definition_window|definition_aggregation|error))* (';' (execution_element|error))* ';'? ) ;
这里第一个和第三个替代元素是不明确的。Xtext 中的模糊固定规则是,
ExecutionPlan:
(appAnn+=AppAnnotation)*( (=>defStream+=DefinitionStream|=>defTable+=DefinitionTable| =>def_window+=DefinitionWindow| =>defTrigger+=DefinitionTrigger|=>defFunction+=DefinitionFunction|=>defAgrregation+=DefinitionAggregation)=>(';' (=>defStream+=DefinitionStream|=>defTable+=DefinitionTable| =>def_window+=DefinitionWindow| =>defTrigger+=DefinitionTrigger|=>defFunction+=DefinitionFunction|=>defAgrregation+=DefinitionAggregation))* =>(';'(exElement+=ExecutionElement))* ';'?);
更多歧义固定可以在这里找到。
语法突出显示
句法突显由词汇突显和语义突显两部分组成。对关键词、数字和标点符号进行词汇突出显示。语义突出显示在变量名上,如流名、表名、触发器名、窗口名、函数名和紫色事件名。如下图所示,实现了词汇和语义突出显示。
Lexical and Semantic highlighting for Siddhi
代码自动完成
内容辅助在任何编辑器中都是一个非常重要的特性。在这个插件中,根据如下所示的语法为关键字和标点符号提供了内容帮助。
代码自动完成是针对执行计划中不同位置使用的流名、表名、窗口名、属性名和事件名完成的。这主要是通过使用 Xtext 中的局部作用域和交叉引用来实现的,因为它只需要提出属于一个执行计划的变量。交叉引用的一个例子将在下面解释。
Source:
strId=[Source1|IdNew];Source1:
inner='#'? name=IdNew;DefinitionStream:
{DefinitionStream}(ann += Annotation)* DEFINE (STREAM|TABLE) src=Source1 OPEN_PAR (feature += Features )(',' feature += Features )* CLOSE_PAR;StandardStream:
MainSource =>((postWindowHandlers = BasicSourceStreamHandlers)?);MainSource:
src=Source basicSSh=BasicSourceStreamHandlers1;
此处,源规则具有对 IdNew 类型(标识符)的 Source1 的交叉引用。因此,在流定义中定义的流名称可以在查询输入规则的 StandardStream 元素中访问。在语法文件中还使用了其他几个交叉引用,如 SourceOrEventReference、FeaturesOrOutAttrReference 和 AttributeNameReference。
查询输入中实现的代码完成如下所示。当所需变量的字母作为建议给出时,建议变量名。
为查询部分实现的代码完成如下。
定义了查询部分功能操作的一般方案,方便了用户的使用。当键入“,”或“:”时触发。
该建议可以定制如下。
错误报告
语法错误由 Xtext 框架本身捕获,并显示在编辑器中。逻辑错误,比如把错误的变量放在错误的地方,是在对流名、表名等进行了局部作用域之后捕获的。
语法错误显示在编辑器中,如下所示。
逻辑错误显示给用户,如下所示。
github 中共享代码的链接:https://github.com/udeshika-sewwandi/siddhi_editor
已实现特性的 Eclipse 编辑器插件链接:https://drive . Google . com/drive/folders/0 B3 tawrcyox 59 C1 pxa 2 vdammzuu?usp =共享
如何安装插件?
要在 Eclipse 中安装插件,需要遵循以下步骤。
- 下载并安装 Eclipse IDE(例如 Mars 2 可以在这里下载)
按照下面的过程在 Eclipse 中安装 Xtext。
- 点击帮助菜单->安装新软件
- 将http://download . eclipse . org/modeling/tmf/xtext/updates/composite/releases/放入与字段一起安装 Xtext
- 获取后,从列表中的 Xtext 类别中选择 Xtext complete SDK 并安装 Xtext
- 一段时间后,Xtext 将被安装并完成安装
- 重启 Eclipse
然后安装神功插件
- 在这里下载中的插件文件夹。
- 点击帮助->安装新软件
- 点击“添加”按钮
- 点击“本地”按钮,选择主插件文件夹,然后点击“确定”
- 为“名称”字段命名,然后单击“确定”
- 从列表中选中该功能,取消选中“按类别分组项目”,然后单击“下一步”
- 经过一些下载过程后,插件将安装到 Eclipse IDE 中
- 重启 Eclipse
安装两个插件后,按照下面的步骤创建一个. siddhi 文件。
- 点击文件->新建->项目
- 选择常规->项目
- 右键单击创建的项目并选择新建->文件
- 将文件名命名为 file_name.siddhi
- 点击完成
- Eclipse 将询问“您想将项目转换成 Xtext 项目吗?”->单击是
- 然后创建了。神功文件可以如下图所示使用
未来的工作
实现 Siddhi Eclipse 编辑器的运行和调试功能需要在将来完成,以便使用该插件。运行功能可以通过使用 Xtext 框架提供的代码生成器存根为特定于领域的语言定制来提供。
确认
这是我在大学生活中第一次参加 2017 年谷歌代码之夏,为 WSO2 的一个项目做贡献,WSO2 是一家开源的知名公司。Sriskandarajah Suhothayan 和 Nirmal Fernando 是我在 WSO2 的导师。虽然这是我第一次为 WSO2 做贡献,但是导师们真的很有帮助,在整个夏天都在这个项目上指导我。非常感谢导师和 WSO2 给我机会,指导我确定项目目标。我真的很高兴在 GSoC 2017 中为 WSO2 做出贡献,我也愿意在这款产品以及其他产品上为 WSO2 做出贡献。
GSoC 是一个鼓励大学生为开发自由和开源软件做出贡献的项目。我很高兴成为 2017 年 GSoC 的一员,我非常感谢谷歌每年组织这个项目,这为学生提供了一个在虚拟工作环境中工作来提高许多技能的大好机会。
如果需要任何澄清,请通过sewwandikaus . 13 @ CSE . mrt . AC . lk联系我。
关于 Xtext 的进一步阅读
[1]https://eclipse . org/Xtext/documentation/102 _ domainmodelwalk . html
[2]https://eclipse . org/Xtext/documentation/301 _ grammar language . html
[3]https://eclipse . org/Xtext/documentation/307 _ special _ languages . html
https://github.com/MartijnDwars/Xtext/wiki/Expressions
GSoC-2017:在 HSF 欧洲核子研究中心从事异常检测工作
原文:https://towardsdatascience.com/gsoc-2017-working-on-anomaly-detection-at-cern-hsf-49766ba6a812?source=collection_archive---------4-----------------------
Error function a 200,000 points long Time-Series
今年是我第一次作为学生参加谷歌的代码之夏项目。我被 CERN-HSF 组织接受,在 ATLAS 子组织下从事一个异常检测项目。这篇文章的目的是总结我在这个巨大的夏天所做的努力,包括成就和失败。
我要感谢我的导师 Mario、Alessandro 和 Tomas,他们来自 HSF 欧洲粒子物理研究所,在这段旅程中为我提供了指导。!
深度异常— 使命宣言
ATLAS Open Analytics 是一个平台,用于收集多个参与异构计算中心之间各种计算操作生成的数据。
我与欧洲粒子物理研究所-HSF 的项目都是关于使用机器学习来识别这个时间序列数据中的异常。
其想法是设计、构建和部署一个框架,该框架能够对这种实时 ATLAS 分布式计算数据中的异常行为进行监控、分类和聚类,然后根据这些信息自主采取行动。
目标
建立一个自动管道来触发异常,然后分析它们以预测其根本原因以及一些潜在的解决方案。
这个想法是让系统从历史和实时数据中学习,并对这种异常事件做出准确的预测。
数据探索
Recurring Trends for “transfer-done” events within a single day’s index
大多数 ADC 数据存储在两个不同的 ElasticSearch 实例中。对于像我这样不熟悉这个非常棒的工具的人来说,ElasticSearch 是一个分布式的 RESTful 搜索和分析引擎。ElasticSearch 最棒的地方在于它非常快,几乎是实时的。它允许你以一种非常方便的方式存储、索引和分发你的数据。结合一些真正灵活和直观的可视化工具,如 Kibana,它变得非常有吸引力,特别是如果你有大量的数据。
我个人使用 python 的两个 elasticsearch 库来处理 elasticsearch 实例: elasticsearch-py 和 elasticsearch-dsl 。
在任何给定的时间点,CERN ES 主实例包含 31 个" atlas-rucio-events-* "索引,过去 31 天中的每一天都有一个索引。由于可获得的数据确实非常庞大且种类繁多,我的导师 Mario 建议我只从这些“ atlas-rucio-events ”指数中的“ transfer-done ”事件开始。
我首先查询“transfer-done”类型的事件,并将它们保存到本地数据帧中。通常,每个索引包含 1,000,000–2,000,000 个此类事件,每个此类事件有 26 个子字段,包含有关特定传输的各种信息,如其来源、目的地、正在传输的文件大小等。
这是我对数据的第一次观察,下面是我在探索和提取数据时绘制的一些重要图表
File sizes for transfers in bytes
Actual durations for the transfers to finish(not including the time spent in queue)
Time that a file spent in queue before it actually got transferred
有些文件排了整整一周的队是很常见的!!(1 周~=600000 秒)
除了这些连续变量,还有很多分类变量需要我去处理。下面是一些直方图,描述了它们在单个索引中的分布频率:
在不冒任何风险的情况下,我选择了所有可以有意义地解析为任何模型的输入的变量,这些变量可能对决定转移的持续时间有影响。我总共得出了 10 个变量,它们将作为我未来模型的训练数据。
用于异常检测的机器学习
在理解了数据中不同变量的实际含义后,我开始实际识别这些转移中的异常。直到现在,我都不知道“大海捞针”到底意味着什么。
作为我的社区结合期的一部分,我对特定于时间序列数据的 ML 算法做了相当多的研究。科学家在各种研究论文和文章中使用的大多数模型都采用了某种“监督学习方法”来解决这样的问题。但这里的情况略有不同。在这些巨大的转会事件数据框架中,没有标签将异常转会与正常转会分开。无人监管的方法可能是前进的方向,我在我最初的提案中也提到过这一点。
ML 型号的选择:
神经网络
对我来说,我们正在做的一件事是,有数百万个数据点可供我训练机器学习模型!!我还被可靠地告知,发生异常的百分比非常低,大约为 1 / 1000 。有了这些知识,我开始在 Keras 中实现各种前馈架构,试图预测特定传输的传输持续时间,并取得不同的成功。
我尝试过的几乎所有前馈架构,更深、更广、不同/高级激活……都表现出了相似的性能。该模型学习了一段时间,然后稳定在一个不太好的水平上。我尝试了不同的缩放选项,看看是否有什么不同,但没有任何明显的改善。
递归神经网络-长短期记忆网络
在前馈网络上做了一些实验后,我终于到达了 RNNs。鉴于我的数据的时间序列性质,它们是我最理想的选择,我对它们持乐观态度。
我从简单的 LSTM 网络和一个 LSTM 开始,并开始训练他们在 10 个事件上的时间转移步骤。它们比以前的架构稍微好一点,但也好不了多少。经过与多个堆叠层、每层更多的 lstm/GRU 单元以及用数据训练网络(其中每个数据点都追溯到其历史)的争论,我最终得出了以下架构:
该模型以 100 个事件的时间步长为输入,即,为了预测每个单次转移的持续时间,它考虑了该转移的详细信息+在该转移之前的 99 次转移的详细信息。这些传输中的每一个都有 9 个输入—文件大小、队列中的时间、源、目的地、活动、协议、传输端点、src 类型、dst 类型。
对于 dim (100,9)的输入,网络输出单个值(输入中第 100 次传输的传输持续时间)。我们在数百万个这样的事件的数据集上训练这个网络,并且每个事件的迭代不超过 2 次。这样做是为了确保模型不会学习映射数据集中的任何异常事件。以下是对 200,000 次前所未见的传输进行评估后的网络性能图:
error distribution
这是迄今为止我得到的性能最好的型号。
使用的阈值:
- 为了区分异常和正常事件,我使用了 600 秒的阈值。实际传输持续时间比预测时间长 600 秒以上的传输事件被标记为异常。
分析检测到的异常
在构建了检测异常的网络之后,下一步是验证它们并确定它们的根本原因。这被证明是相当具有挑战性的,因为检测到的异常数量仍然太大。正是在这个时候,我开始与托马斯合作。由于没有潜在的资源来实际验证检测到的异常,调查其原因更加困难。
correlation plot b/w predicted and actual durations
经过一段时间的探索、研究我的结果以及与托马斯的多次讨论,我们得出了以下结论:
- 我需要一个更好的标签标准来标记异常事件;比单个错误阈值更强大的东西。
- 发现的异常数量需要降低到一个更易于管理的数量。
使用“性能声纳”数据
这个项目的最终目的是修复导致系统中检测到的异常的问题。这只能通过修复发生传输异常的特定源-目的地链路来完成。
欧洲核子研究中心有一个系统,它测量关于这种源-目的地对链路性能的一些核心统计数据。这些统计数据包括“吞吐量”、“延迟”和“数据包丢失率”等信息。我相信这些数据可以作为一个更好的异常触发系统的基础,用于检测基于 LSTM 模型预测的异常。
比如说-
- 在具有异常高的分组丢失率的 src-dst 链路上传输的、与预测传输持续时间具有高偏差值的传输事件更有可能是异常。
- 类似地,吞吐量度量可用于对通过同一 src-dst 链路传输的异常进行分组。
这就是我的努力所达到的状态。写这篇文章的时候,我还在纠结性能声纳数据。道路是艰难的,但我相信我的工作已经成功地证明了检测和修复异常的系统肯定是可行的。
失败和缺点:
这个项目是我第一次体验专业编码。我从未参与过如此规模、如此复杂的项目。尽管我为自己取得的进步感到自豪,但直到现在,我发现自己还存在一些不足:
- 实现一个实时触发器——这样做的目的是同时提取实时索引的数据,对其进行预处理,在模型中运行,并检测其中的异常。由于我缺乏使用多任务脚本的经验,我无法成功实现它。
- 当前模型有时不能捕捉具有较大传输大小的一些非异常传输的高尖峰。
虽然我的正式工作期间,我想继续这个项目的工作,并看到它通过它的完成和部署!!
Git 仓库— 深度异常
用 R 从婴儿的名字中猜出你出生的年份
原文:https://towardsdatascience.com/guessing-the-year-you-were-born-from-baby-names-using-r-17c8cbb8d0a5?source=collection_archive---------12-----------------------
一个简单的问题展示了数据科学的痛苦
最近,推特上流传着一篇关于“希瑟”这个名字兴衰的文章在 20 世纪 70 年代和 80 年代,希瑟是一个非常受欢迎的婴儿名字,但这个名字很快就变得模糊不清了。 JD Long ,一位在保险行业工作的著名数据科学家,发了一条关于此事的推文:
读了这条推文,以及数据科学家珍妮·汤普森的回应,让我想知道当时我认为是一个简单的问题:
哪一组四个婴儿名字最能代表你出生的年份?
在 JD 的例子中,他认为他出生年份的四个婴儿名字是 Chad、Clay、Jennifer 和 Lori。对于生于 80 年代中期的我来说,我猜我出生年份的四个名字是马修、迈克尔、劳拉和伊丽莎白。但是什么才是最好的名字呢?我们如何用数据来展示它呢?
这类问题正是数据科学家一直在处理的。当你读它的时候,它听起来像是一个你能很快回答的非常精确的问题。一旦你开始思考这个问题,它就变得很难理解。很快你就会意识到,你处理问题的方式会极大地改变答案,而且没有唯一正确的方法。最后,我尝试了三种不同的方法来解决这个问题,得到了一些有趣而独特的结果。
尝试 1:使用统计上最有可能来自该年的名字。
对我来说,“最能表明”这个词的意思是,如果你告诉某人这四个名字,他们就会知道你出生的确切年份。这个定义启发了我把它变成一个统计问题的第一种方法:如果从一年中随机抽取四个名字,那么这四个名字最有可能是从这一年中抽取的?
换句话说,假设我有一堆粗麻布袋子,每个袋子上都写着一年。在每个袋子里,我都有一些大理石,上面写着那一年出生的每个人的名字。如果我在袋子里选了四颗弹珠,然后递给你,我应该选哪四颗,让你猜猜是哪一年?
This is a super weird metaphor but like, aren’t most statistical and combinatorial framings?
从贝叶斯定理开始的一点点数学,原来我们想找到最大化的四个名字: P(name|year)/P(name) 。或者取我们关心的年份拉名字的概率,除以跨所有年份拉名字的概率(我假设年份的概率相等)。
让我们在 R 里做这个!谢天谢地,哈德利·威克姆利用政府数据制作了一个婴儿名字分析包。不幸的是,这只是使用了美国的数据,没有办法将结果推广到其他国家。首先,让我们加载我们需要的库:
library(babynames) # to get the baby name data
library(dplyr)
library(tidyr)
library(ggplot2)
babynames 包包含一个数据集babynames
,其中有一行是每年、婴儿姓名和出生时分配的性别(错误地标记为“性别”)。它记录了这个名字出现的次数,以及那一年出生的婴儿中使用这个名字和性别的百分比。只包括一年中至少出现五次的姓名和性别对。
> babynames
# A tibble: 1,858,689 x 5
year sex name n prop
<dbl> <chr> <chr> <int> <dbl>
1 1880 F Mary 7065 0.0724
2 1880 F Anna 2604 0.0267
3 1880 F Emma 2003 0.0205
4 1880 F Elizabeth 1939 0.0199
首先,让我们计算总概率,作为每个名字分数的分子。以下代码创建了一个数据框,其中为每个分配的性别和姓名对各占一行:
total_props <-
babynames %>%
complete(year,nesting(sex,name),fill=list(n=0,prop=0)) %>%
group_by(sex,name) %>%
summarize(total_prop = mean(prop)) %>%
ungroup()
代码获取表babynames
,用 0 填充缺失的行,然后获取每个名字和指定性别对的平均概率。
然后,我们计算一年中每个名字和指定性别的概率,并将其加入到前面的表中。我们计算这个比率,看看每年的前四名:
most_informative_ratio <-
babynames %>%
inner_join(total_props,by=c("sex","name")) %>%
mutate(value = prop/total_prop) %>%
group_by(year) %>%
filter(row_number(desc(value)) <= 4) %>%
ungroup() %>%
arrange(year,desc(value))
我们来看结果!以下是 1980 年最具参考价值的名字:
> most_informative_ratio %>% filter(year == 1980)
# A tibble: 4 x 7
year sex name n prop total_prop value
<dbl> <chr> <chr> <int> <dbl> <dbl> <dbl>
1 1980 F Nykeba 26 0.0000146 0.000000107 136
2 1980 F Sumeka 14 0.00000786 0.0000000578 136
3 1980 F Renorda 11 0.00000618 0.0000000454 136
4 1980 F Shanndolyn 11 0.00000618 0.0000000454 136
这些是什么鬼名字!?雷诺达?Shanndolyn?原来这四个名字只在 1980 年的数据中出现过。所以这些名字非常晦涩,很少使用。因此,如果我说表示 1980 年生日的四个名字是“Nykeba、Sumeka、Renorda 和 Shanndolyn”,那么是的,这些名字只在 1980 年使用,因此我表示年份。然而,这个问题隐含着这样一个假设:与我交谈的人以前听过这些名字。我对这个问题的统计公式没有考虑到一些从未说过但确实有必要的东西。因此,如果我们想考虑到与你交谈的人必须听说过这些名字,我们需要一种新的方法
尝试 2:用高于平均水平的名字来表示年份。
第一次尝试的问题是它没有考虑名字的受欢迎程度,只考虑了名字的信息力量。使用名字的平均受欢迎程度和一年内的受欢迎程度的想法似乎仍然有希望,那么如果我们把它改为两个数字之间的差异会怎么样呢?
这给出了公式二:在给定的一年中,哪一组四个名字的使用从它们的平均值增加最多?因此,如果多年平均下来,男性迈克尔斯的可能性是 1%,如果在某一年,男性迈克尔斯是儿童的 5%,那么我们会给出 4%的值?哪些名字的价值最高?
所以再次使用之前的总概率表,让我们计算一个新的最具信息量的表。现在的值是当年的概率和总概率之差。
most_informative_diff <-
babynames %>%
inner_join(total_props,by=c("sex","name")) %>%
mutate(value = prop - total_prop) %>%
group_by(year) %>%
filter(row_number(desc(value)) <= 4) %>%
ungroup() %>%
arrange(year,desc(value))
让我们看看 1980 年的表格:
> most_informative_diff %>% filter(year == 1980)
# A tibble: 4 x 7
year sex name n prop total_prop value
<dbl> <chr> <chr> <int> <dbl> <dbl> <dbl>
1 1980 F Jennifer 58381 0.0328 0.00609 0.0267
2 1980 M Jason 48173 0.0260 0.00413 0.0218
3 1980 M Michael 68673 0.0370 0.0178 0.0192
4 1980 M Christopher 49088 0.0265 0.00785 0.0186
太好了!这些看起来像 1980 年的流行名字!如果你看看不同的年份,这些名字似乎与当时流行的名字一致。不幸的是,现在这些年往往会混在一起。让我们看看 1978-1982 这四个名字。在这里,我添加了姓名在年份中的排名,并创建了一个name_gender
变量来制作表格。我使用 tidyr spread 函数,这样我们可以一次看到所有这些数据
most_informative_diff %>%
group_by(year) %>%
mutate(rank = paste0("rank_",row_number())) %>%
ungroup() %>%
mutate(name_gender = paste0(name,"-",sex)) %>%
select(year,rank,name_gender) %>%
spread(rank,name_gender) %>%
filter(year >= 1978, year <= 1982)
结果是:
# A tibble: 5 x 5
year rank_1 rank_2 rank_3 rank_4
<dbl> <chr> <chr> <chr> <chr>
1 1978 Jennifer-F Jason-M Michael-M Christopher-M
2 1979 Jennifer-F Jason-M Christopher-M Michael-M
3 1980 Jennifer-F Jason-M Michael-M Christopher-M
4 1981 Jennifer-F Jessica-F Michael-M Christopher-M
5 1982 Jennifer-F Christopher-M Jessica-F Michael-M
如果你看一下,五年间名字的唯一区别是杰森在 1981 年被杰西卡取代。这对我们用名字猜测年份的目标来说并不太好。这是 1980 年以来这四个名字出现的概率图。您可以看到,虽然它们都在那段时间达到峰值,但也有相当数量的其他年份处于高位:
most_informative_diff %>%
filter(year == 1980) %>%
semi_join(babynames, ., by = c("name","sex")) %>%
mutate(name_gender = paste0(name,"-",sex)) %>%
ggplot(aes(x=year,y=prop,group=name_gender, color = name_gender))+
geom_line(size=3) +
theme_minimal(20)+
labs(x="Birth year",y="Probability",color = "Name and assigned gender")
尝试 3:去他妈的,让我们做一个很酷的交互可视化来让人们惊叹。
虽然我可以多花十个小时来精确地找出这个问题的最佳统计框架,但我想尝试一些不同的东西。如果目标是从数据中传达一些意义,通常最好是制作一些有趣的东西,让人们对此进行更深入的思考。有时你只是有喜欢玩东西的业务主管。无论你的情况如何,交互式可视化都是很棒的。
我决定用 R 包 shiny 创建一个随机样本教室。这是一个很好的方法来看看如果你出生在某一年,你周围的人的名字会是什么样的。它传达了流行的名字,加上不流行的是什么样的。 自己试试吧! 如果你想玩很短的代码,在 GitHub 上有。
The my-classroom tool showing a class from the year 2000. You can tell the year by the three Jacobs and two Alex…es(?). Click the picture to try it for yourself!
这个小项目极大地提醒了我,简单的问题可能不容易用数据科学来解决。即使你在一个表格中拥有了你可能需要的所有数据,想出一个将问题转化为分析的方法也可能是一个阻碍。虽然这是一个有趣的小项目,但同样的事情也可能发生在诸如“哪些客户拥有最高的保留率?”或者“本季度我们生产了多少产品?”在这种情况下,你能为自己和同事做的最好的事情就是,在花费大量时间进行交互式可视化之前,立即解决问题的框架,并获得认同。
机器学习工作流的 GUI 化:快速发现可行的流水线
原文:https://towardsdatascience.com/gui-fying-the-machine-learning-workflow-towards-rapid-discovery-of-viable-pipelines-cab2552c909f?source=collection_archive---------3-----------------------
前言
软件开发的一个原则是尽可能自动化。这就是 DevOps 的思维模式,在这种模式下,致力于自动化有助于团队不断地推出特性,同时确保最佳实践得到尊重。当团队优先考虑自动化时,他们的开发人员关注的是为产品带来新特性所需的最少代码。这对现实世界的软件项目有 3 大好处:
- 代码库中少了人类错误;
- 发展更快;
- 更多变异。
虽然前两点是显而易见的,但最后一点却不太受重视。变化随着自动化而增加,因为当需要编写的代码更少时,尝试更容易。在产品发现的早期阶段,变化是一个关键因素。通过尝试更多的选项,我们减少了对前期假设的依赖,转而探索可能结果的空间。
传统软件(没有机器学习)选项很多。无论是添加按钮,创建登录屏幕,还是连接警报,传统软件都有大量选项可供选择。如果可以用计算机代码来表达,这是可以做到的。
Figure 1 With traditional software, product discovery operates under the assumption all features are options.
但是机器学习产品没有这样的保证。有了机器学习,产品特征不再是选项,而是可能性。只有当我们确认正确的数据存在时,我们才能称之为一种可能性。
Figure 2 Machine learning software cannot enter product discovery until it has been determined which product features are actual options.
这对产品发现有影响。产品发现假设选项是给定的;挑战在于发现这些选项中的哪一个会带来最好的产品。但是在机器学习中,我们不能开始这个过程,除非我们已经暴露了哪些选项是可用的,给定了数据。
有了机器学习,产品功能只有在数据允许的情况下才是可能的。
传统软件在“产品发现”期间开始发现过程,而机器学习应用依赖于该过程之前的发现。这意味着自动化的变化方面,促进发现,必须在开发开始之前发生。换句话说,自动化必须发生在机器学习工作流程中。
工作流与管道
数据科学家通过机器学习工作流程探索数据并验证模型,如下所示:
Figure 3 The Machine Learning Workflow
这是一个反复的过程,包括收集可用数据、清理/准备这些数据、构建模型、验证预测和部署结果。这导致了需要做出关于什么进入数据管道的战略决策的那种发现。数据管道是上述“扁平”布局的工作流程,负责将上述工作流程迭代中发现的最佳部分投入生产:
Figure 4 The Data Pipeline
尽管数据管道受益于传统软件中的自动化类型(测试、持续集成、构建、持续部署),但机器学习工作流需要不同类型的自动化。
我们如何自动化机器学习工作流程?
这个问题看似显而易见的答案是,某个库尝试了许多不同的模型,并自动验证哪一个模型导致最高的准确性。这些库是存在的,比如谷歌的 AutoML , auto-sklearn , tpot , MLBox ,还有很多其他。虽然这些努力有助于减少找到像样的模型所花的时间,但他们认为有产品价值的模型可以通过最少的人工干预来获得。这大大简化了将原始数据转化为真正可行的机器学习产品的过程。
机器学习实践者转动多个旋钮(超参数)来帮助推动学习算法走向更好的结果。我们最好的数据科学家称这一过程为艺术的原因是,知道转动什么旋钮,以及转动多少,是无法编纂的。它包括经验、与领域专家的交谈,以及最重要的试错。
可能结果的空间来自数据属性、模型和参数的复杂交互。真正自动化的机器学习将不得不做比旋转旋钮更多的事情,直到达到一定的准确度。它必须改变数据量,尝试各种数据集,尝试多种数据准备,设计新功能,运行验证指标的 gammit,并在不同的环境中部署结果;更不用说将特定领域的知识融入到这些步骤中了。
这代表了一种“组合爆炸”数据,科学家在寻找建立可行的机器学习产品时必须控制这种数据。
Figure 5 The right mix of tasks to effectively convert raw data to product-worthy outputs exists in a space of near-infinite possibilities.
有效地将原始数据转换为有价值的产品的正确任务组合存在于一个几乎无限可能的空间中。
经验丰富的数据科学家的标志是他们能够通过缩小可能的组合来控制这种复杂性。通过探索和推理,数据科学家将统计技术与经验结合起来,开辟出一条从无数可能性到少数可行选项的道路。
要真正实现机器学习工作流程的自动化,我们需要的不仅仅是自动化的旋钮转动。我们需要能够执行各种常见的机器学习任务,同时仍然允许人类干预,以探索和推理数据告诉我们的东西。
我认为这种自动化只有通过机器学习工作流程的 GUI 化才有可能。GUI 化就是通过图形用户界面来展示功能。当从业者按下按钮执行普通任务时,这使他们能够快速尝试许多选项,导致发现可行管道所需的大量变化。
这为数据科学提供了一个更加完整的devo PS 理念。虽然我们的管道需要传统的测试和构建实践,但我们也需要工作流程阶段的自动化,因此产品发现可以从一组可行的机器学习选项开始。
将机器学习工作流程图形化似乎太具挑战性了。毕竟,每当我们在机器学习任务中指向一个新的数据集时,事情似乎都会发生变化。但是理解事情出错时的场景正是我们走向自动化的方式。我认为自动化是经验丰富的从业者的责任。作为最终的抽象,自动化确保我们的工作只关注挑战中的新事物。当我们能够快速探索可能性的空间时,我们就能提高数据密集型项目的投资回报率。
自动化是经验丰富的从业者的责任。
随着时间的推移,GUI 化会在机器学习工作流程的每个步骤中产生一组健壮的机器学习能力。最终,这种能力可以作为服务公开,其目的是使团队能够在构思的早期阶段快速评估组织/客户的数据状态。
随着团队继续从事项目,他们会增加这些服务,公开更多的机器学习功能,并在寻求构建机器学习产品时更快地发现存在的选项。
Figure 6 Using a GUI-Service for machine learning. This enables rapid assessment of an organization’s data, laying the foundation for better product discovery.
值得注意的是,GUI 化并不意味着取代手工编码。当我们必须改进从数据中提取价值的过程时,没有什么可以替代深入研究代码。但是编码永远不应该是我们对数据集的第一次尝试。这样做是抽象的失败,自动化的失败,并不代表构建机器学习产品的精益方法。我们应该只在没有遇到问题的时候接触代码。
我们应该只在没有遇到问题的时候接触代码。
为机器学习构建 GUI 服务
机器学习工作流程的 GUI 化有两个部分。在后端上,我们需要将机器学习功能公开为 REST 服务,因此可以使用前端调用常见任务。在前端,我们需要轻松地可视化和管理我们选择运行的任务之间的数据流。
我将列出重要的要求,然后讨论每一点:
技术要求
- 公开R 和 Python 的功能;
- 允许在不重新启动服务的情况下更改代码;
- 允许适当的代码组织和版本控制;
- 间歇数据应可由 R 和 Python 访问;
- 利用本地 R 和 Python 可视化;
- r 和 Python 应该是分开的服务;
- 自动跟踪和管理数据依赖关系;
- 请等到后端完成处理后,再在前端显示结果。
讨论
公开 R 和 Python 的功能:我认为同时支持R 和 Python 是很重要的。这是因为正如本文开头所讨论的,变化是关键。当我们从语言中抽象出来时,唯一重要的是能力,允许机器学习的全部广度和深度用于应对我们的挑战。
允许在不重启服务的情况下更改代码:数据科学依赖于 REPL 式的环境,当我们更改代码时,这些环境会显示结果。如果我们的服务包含在 Docker 运行时中,我们将不得不重新构建/运行映像来显示新的变化。另一个选择是 Jupyter 笔记本,它支持 REPL 风格的编码,和可以使用 Jupyter 内核网关公开为 REST 服务。但是同样,如果不重启网关,代码更改是不会暴露的。
Node.js 中的 子进程 允许我们通过 Node.js 调用R 和 Python 函数。当与 web 框架 Express 结合时,就有可能创建一个 REST API,向前端公开 R 和 Python 功能。另外,这种类型的服务不需要重启就可以暴露子进程中的变化。
允许适当的代码组织和版本控制:笔记本在组织代码* 和进行适当的版本控制方面也有缺点。笔记本不是有组织的代码,笔记本之间的版本控制只是对我们工作的 JSON 表示进行版本控制。这对于现实世界的软件开发来说是不可估量的。我们的服务应该允许 R 和 Python 脚本作为适当的文件存在,可以像任何其他应用程序一样进行组织和版本控制。*
R 和 Python 都应该能够访问间歇数据:服务还应该允许 R 和 Python 在工作流的任何阶段访问间歇数据。例如,用户应该能够用 R 准备数据,用 Python 构建模型,在各种语言之间无缝切换。JSON 是一个很好的选择。**
JSON 很容易被 R 和 Python 读写。JSON 也很容易存储嵌套的数据。这对于机器学习非常有用,因为我们经常在一次调用中保存多个数据集,例如将数据分成训练集和测试集:
*[{
"**X_train**": [{
"feature_a": 100,
"feature_b": 150,
"feature_c": 40
}],
"**X_test**": [{
"feature_a": 200,
"feature_b": 250,
"feature_c": 140
}],
"**y_train**": [{
"feature_d": 170
}],
"**y_test**": [{
"feature_d": 270
}]
}]*
利用原生 R 和 Python 可视化:大多数前端应用程序选择交互式的、基于 JS 的可视化。虽然交互式图表有很多好处,但是它们缺少本地 R 和 Python 图表的多样性。例如,我们可以使用代码的 1 行在 R 中创建以下影响图:
复制这个需要多少定制的 JavaScript?原生视觉是数据科学家探索和验证其工作的方式;我们不应该妨碍那件事。
R 和 Python 应该是独立的服务:GUI 服务应该使用微服务架构,以便 R 和 Python 保持独立。仅仅用调用 R 和 Python 的脚本来包装服务并不是一个好的设计选择。当然,这必须与立即暴露代码变更的需求相平衡,正如以上关于 Docker 运行时的观点。
自动跟踪和管理数据依赖关系:执行的每个任务都将依赖于一些先前的数据集,无论是原始数据集还是转换后的数据集。GUI 需要自动跟踪和管理数据集之间的依赖关系,以保留工作流。这可以通过让前端管理跨节点的读写路径来实现,如下图所示:
例如,在节点上运行选择的函数将启动以下步骤:
等待后端完成处理,然后在前端显示结果:由于工作流将涉及运行计算密集型任务,前端必须等待后端处理完成,然后再尝试显示结果。只要我们调用 REST 端点,这就相当简单。比如 jQuery 的 $中的 Promise 接口。ajax 方法确保我们可以推迟执行额外的 JavaScript,直到请求完成。
介绍机器流程
我创建了机器流程来展示本文中讨论的哲学。Machine Flow 包含上述技术要求,并允许数据科学家和数据团队将他们的工作流程 GUI 化。
机器流支持机器学习工作流的可视化执行和跟踪。用户动态创建依赖图,每个节点负责执行一个任务并显示结果。
机器流程提供开发模式和服务模式。开发模式用于主动向我们的服务添加新的 R 和/或 Python 代码。对 R 或 Python 的任何添加/更改都会被它们各自的 REST 端点立即公开,从而允许数据科学家快速构建他们的 GUI 服务。
**服务模式在数据科学家的 GUI 服务中已经添加了大量机器学习功能时使用。在这种情况下,不太需要在后端和前端之间来回移动。服务模式背后的想法是提供一个容器化的运行时,团队成员可以用来构建机器学习工作流,而不必编写代码。
开发模式
我们将从开发模式开始,因为这使我们启动并运行,并且是大多数数据科学家使用机器流的方式。
克隆机器流程
您可以通过在 GitHub 上探索项目来查看自述文件。下载机器流程最简单的方法是打开终端并运行下面的命令:
*git clone https://github.com/WorldofDataScience/machine_flow.git*
这将把机器流带入你的目录。键入 ls 查看内容:
***machine_flow**
├── README.md
├── **app**
├── **data**
├── docker-compose.yml
├── **python_ml**
├── **r_ml***
4 个子目录是最重要的:
- app 包含前端应用;
- 数据保存数据集和日志文件;
- python_ml 保存我们的 python 脚本;
- r_ml 保存我们的 R 脚本。
打开机器流程 GUI
首先,让我们运行机器流的前端。我们可以启动一个简单的 Python web 服务器,在终端中运行以下命令:
*python3 -m http.server*
我们现在在端口 8000 上提供 HTTP 服务。在浏览器中打开以下链接:
http://localhost:8000/app/machine _ flow . html
您应该看到带有空白工作流程的机器流程应用程序。
启动 R 和 Python 服务
我们的前端通过 REST 端点向后端发送函数来运行 R 和 Python 代码。因此,我们需要在后端启动我们的 R 和 Python 服务。
在“终端”中打开 2 个新标签。在第一个新选项卡中,切换到 r_ml 目录,运行以下命令启动 R 服务:
*node connect.js*
在另一个新选项卡中,切换到 python_ml 目录下和运行相同的命令来启动 Python 服务:
*node connect.js*
每个选项卡都应显示其各自准备好的服务:
> R 机器学习端口:9191
> Python 机器学习端口:8181
添加数据
我们使用的任何数据集都必须添加到数据文件夹中。你可以随意添加;唯一真正的要求是所有数据都是 JSON 格式。
让我们添加来自 GitHub 的波士顿住房数据集:
https://raw . githubusercontent . com/selva 86/datasets/master/Boston housing . CSV
在“终端”中打开一个新标签页(确定您在 machine_flow 目录中),并通过键入 R + enter 启动一个 R 会话。我们通过运行以下命令将数据以 JSON 格式添加到我们的数据文件夹中:
*library(jsonlite)
df <- read.csv('https://url_to_boston_data.csv')
df_json <- toJSON(df)
write(df_json, file='data/boston.json')*
我们可以在 Python 中使用相同的方法,通过启动 Python 会话并运行以下命令:
*import pandas as pd
import jsondf = pd.read_csv('https://url_to_boston_data.csv')with open('data/boston.json', 'w') as f:
f.write(df.to_json(orient='records'))*
在任一种情况下,JSON 输出都有下面的格式,其中每个观察都包含在自己的对象中:
*[{
"feature_a" : "100",
"feature_b" : "150",
"feature_c" : "40"
}, {
"feature_a" : "720",
"feature_b" : "14",
"feature_c" : "431"
},
....
}]*
添加后端功能
为了让我们的前端对我们的数据做任何有用的事情,我们必须向后端添加 R 和/或 Python 函数。在编写我们的第一个后端函数之前,我们需要回顾一些需求,以使后端函数与机器流程一起工作。
每个后端函数必须有前两个参数作为读路径和写路径。函数使用这些来读取正确的数据集并将结果写入正确的路径。这些路径是由机器流自动管理的,所以我们只需要确保在我们的后端函数中使用它们。**
Back-end function for Machine Flow.
正如我们在上图中看到的,我们函数需要的任何额外参数都在 read_path 和 write_path 之后。**
我们还确保每个函数都以一个return(‘done’)语句结束。这告诉节点层 R/Python 已经执行完了它的函数。
添加我们的第一个后端函数
**必须提供的第一个后端函数是 list_data 函数。机器流程要求我们将这个函数命名为 list_data。所有其他功能都可以随意命名。
我们当然可以使用 R 或 Python 来编写 list_data 函数。我将如下使用 R:
*list_data <- **function**(read_path, write_path) {
res <- toJSON(list.files(read_path, pattern = **".json"**))
write(res, file=write_path)
return(**'**done**'**)
}*
这使用 R 的本机 list.files 函数来列出所提供路径中的所有文件。注意,我添加了 read_path 和 write_path 作为参数,并根据需要在我的函数中使用它们。
我们把这个函数放在哪里?
我们将后端函数添加到 Machine Flow 的 r_ml 和 python_ml 目录中的适当脚本中。
***machine_flow**
**r_ml**
├── R_Scripts
└── data_gathering.R
└── data_preparation.R
└── model_building.R
└── model_validation.R*
此时打开一个 IDE 比只打开终端更有意义,因为我们将管理多个脚本。我用 PyCharm 你可以用最适合你的。
因为我们用 R 编写了 list_data 函数,所以我们把它添加到了 R_Scripts 中。导航到 r_ml 目录内的 R_Scripts 并打开其内容。打开 utility_functions.R。您将看到已经添加了 list_data 函数的 Machine Flow,以及一些其他函数。因为它已经在那里,我们不需要添加它。如果您使用 Python 列出文件,您可以将 list_data 函数添加到 python_ml 目录下的 utility_functions.py 中。**
添加端点
由于我们已经有了后端功能,我们可以打开机器流程 GUI,并在端点下添加此功能:
点击端点打开功能覆盖图。这是我们告诉机器流 GUI 我们的机器学习服务提供了哪些后端功能的地方。
我们需要添加我们的 list_data 函数。默认端点设置为端口 9191,这是我们的 R 服务的端口,所以我们不会更改它。我们将添加 list_data 作为函数名,选择 data 作为预期输出,然后单击 add:
Adding endpoint and function in Machine Flow
我们需要指定我们想要向机器流 GUI 公开的任何后端功能的预期输出。这确保了机器流知道在运行函数时要显示什么样的结果。
关闭功能覆盖图,并单击工作流程的第一个节点。按回车键添加一个新节点。第一层中的任何节点都是数据节点。这些节点在我们的工作流上开始了一个新的分支。
Choosing raw dataset in Machine Flow
单击“添加数据”会弹出打开模式,并显示一个下拉列表,列出我们添加到数据文件夹的任何数据集。我们可以看到我们添加的波士顿数据集,以及机器流附带的虹膜数据集。
从列表中选择 boston.json 以显示数据集。这就是我们如何将数据加载到 GUI 中来开始一个新的分支。如果我们想添加另一个数据集,我们可以单击根节点并按 enter 键,选择不同的数据集进行操作。
添加任务
在第一层之后添加的任何节点都是任务节点。这就是我们如何通过添加和运行从起始数据节点分支的任务来构建我们的工作流。
点击 boston 节点上的并点击 enter,然后点击 ADD TASK。我们添加到端点的任何功能都将出现在此下拉列表中。因为我们还没有添加任何函数(这里没有列出 list_data ),所以现在我们可以这样做了。
Machine Flow 附带了一些 R 和 Python 中的函数来运行本教程。我们可以想象这些是由我们编写或由我们的数据科学团队公开的端点。
机器流程附带的功能如下:
- 【T4 列表 _ 数据(9191)(数据)
- show_outliers (9191)(图片)( 特征 )
- show_distribution (9191)(图片)(feature)
- show_missing (8181)(图片)
- 规格化 _ 数据(9191)(数据)
- remove_features (9191)(数据)(features)
- split_data (8181)(数据)( 目标 _ 特征,split _ percentage*)*
- 运行 _ 线性 _ 回归(8181)(数据)
- 实际 _ vs _ 预测(8181)(图片)
- show_mse (8181)(图片)
- show_r_squared (8181)(图片)
第一个括号中显示了端口。预期输出显示在第二个括号中。如果需要,参数显示在第三个括号中。
让我们用这些来实验波士顿数据集。打开端点并添加每个函数及其预期输出。根据功能检查以确保端点上的端口号正确:
Adding endpoints in Machine Flow
其中一些功能也需要参数。我们可以通过单击相应功能的参数图标来添加这些参数:
Adding parameters in Machine Flow
当我们稍后保存我们的工作流时,这些端点、函数和参数被保存,因此我们不需要重新添加它们。
构建工作流
一切就绪,可以开始使用我们的波士顿数据集构建工作流了。点击添加任务并检查下拉列表。您现在应该可以看到我们添加的所有功能。让我们开始探索数据。从下拉菜单中选择 show_outliers :
Choosing a function in Machine Flow
当我们选择一个函数时,我们会看到任何预期的特性的输入字段,以及一个函数调用,它是被调用的后端函数。前两个参数是传递给我们后端函数的 read_path 和 write_path 。这些是由机器流程自动设置的,所以我们可以不去管它们。当我们输入参数时,它会被动态添加到函数调用中。
这个特定的函数接受一个 ALL 参数作为特性参数传递,这在想要发现异常值时非常有用。在输入框中输入 ALL 并点击 RUN :
Looking for outliers in Machine Flow
我们可以看到,一旦后端代码完成,就会返回结果。正如在上面的需求中所讨论的,所产生的视觉效果是原生的 R 视觉效果。我还在模态顶部添加了一个名字并关闭它。任何时候我点击这个节点,任务的结果就会显示出来。
机器流程使用了许多检查来确保不违反数据相关性:
- 除非父节点已经运行了任务,否则无法运行任务;
- 一旦创建了第一个层节点的子节点,就不能在其上更改数据集;
- 如果前一个节点是图像,机器流将搜索路径,直到找到最近的数据集。
注:一个分支包含所有共享同一个第一层节点的节点。一条路径*包含所有直接相互连接的节点。*
让我们继续构建工作流。由于异常值对于特征 crim 、 zn 和 b 最为极端,我将从数据集中移除这些特征。让我们选择移除 _ 特征功能。我们可以在后端看到,该函数被编写为接受以逗号分隔的要素名称字符串,用于从数据集中移除要素:
*remove_features <- **function**(read_path, write_path, features) {
res <- read_json(read_path)
rem_vec <- unlist(strsplit(features, **', '**))
res <- res[,!(names(res) %in% rem_vec)]
res_json <- toJSON(res)
write(res_json, file=write_path)
return(**'done'**)
}*
因此,我们知道如何为这个函数调用添加参数:
Removing features in Machine Flow.
我们可以理解为什么我们在添加端点时必须提供预期的输出。第一个示例生成了一个图像,而本示例显示了结果数据集。
我现在将分割数据,训练一个线性回归模型,并显示预测值与实际值的对比图:
Stepping through splitting, building and validating in Machine Flow.
我可以从这个分支中分离出多种类型的验证,因为它指向由模型训练的数据。由于这是回归,我将检查 r 平方值和均方误差:
Spinning off multiple validations in Machine Flow
机器流程的一个主要好处是能够快速尝试许多选项。例如,我开始了一个新分支,其中我将数据归一化,仅删除的b 特征,并选择 0.4 的分割百分比。然后,我像上次一样训练并验证了一个回归模型。
我还创建了一个新的节点,它位于前一个分支的中途,在数据被标准化并删除了 b 特征之后,我选择了一个不同的分割百分比 0.5。
最后,我在原始数据集之外创建了另一个节点,并探索了它的一些分布而不是离群值。
这是我的工作流程的样子:
Building out workflow in Machine Flow
Bring 能够在任何分支的任何点添加新节点,这更符合数据科学工作的进展。
突出显示路径
机器流程的另一个重要特征是能够突出显示通向最终结果的路径。当工作流变得庞大而复杂时,这很有用。例如,我可能想快速查看哪些步骤导致我的最佳 R 平方值为 0.688。我可以弹出包含该结果的节点,并单击显示路径图标:
Highlighting a path in Machine Flow
保存工作流
机器流在浏览器中自动保存所有工作。这意味着您可以刷新甚至删除缓存,并且您的工作流仍然可用。当然,我们可能希望创建多个工作流,所以单击 SAVE 按钮将下载一个 JSON 文件,其中包含所有节点、端点、函数和参数,以及附加到每个节点的读写路径。
加载已保存的工作流就像点击 LOAD 并上传 JSON 文件一样简单。
注意:您可以与团队中的其他成员共享工作流文件*,只要他们的 GUI 可以访问相同的数据文件夹。*
预检方式
如上所述,服务模式是我们努力的目标;一个容器化的运行时,为一群数据科学家提供通用的机器学习任务。这是一种“内部产品化”,我们创建一个应用程序在我们的组织内部使用。
我们可以想象数据团队积极地向服务添加新任务。构建定制 GUI 服务的好处是服务对于组织来说是独一无二的。没有任何供应商工具能够捕捉到适合您组织的产品需求的细致入微的建模和验证。建立一个内部服务,能够快速评估新的数据集和可行的管道,为我们提供富有成效的产品发现。
Service Mode in Machine Flow. Service mode is a containerized runtime of commonly-encountered machine learning tasks, allowing teams to rapidly assess new datasets and discover viable pipelines.
访问容器外部的数据
机器流程使用 Docker 卷来保存数据。正如 Docker 文档,中所述,卷是保存 Docker 容器生成和使用的数据的首选机制。卷的一个伟大之处在于,它们允许数据在主机和 Docker 容器之间进行实时通信。这很重要,因为我们应该能够在不重启服务的情况下添加新数据集。
Machine Flow 使用 Docker Compose 在一次调用中启动 R 和 Python 服务。Docker Compose 是一个定义和运行多容器 Docker 应用程序的工具。
如果我们在机器流程中查看 docker-compose.yml ,我们可以看到卷安装在哪里。我们需要将 volumes 下的路径设置为我们机器的根目录:
***version: '3'
services:
r_ml:** *# builds R_ML Dockerfile* **build:** ./r_ml
**ports:** - **"9191:9191"
volumes:** - /path_to_directory/data:/app/data
**python_ml:** *# builds Python_ML Dockerfile* **build:** ./python_ml
**ports:** - **"8181:8181"
volumes:** - /path_to_directory/data:/app/data*
挂载卷所需的完整路径是我们在控制台中键入 pwd 时看到的路径(在 machine_flow 目录中)。
例如,在我的本地机器上,我在卷下的 :/app/data 前添加了以下行:
***volumes:** -/Users/seanmcclure/PycharmProjects/machine_flow/data:/app/data*
确保对 yml 文件的 r_ml 和 python_ml 部分都执行此操作。
添加库
尽管开发模式可以根据需要通过简单地导入库来使用它们,但是容器化的服务必须将这些库放入 Dockerfile 中。
为 R 服务添加库:
*FROM r-base
# install R packages
RUN R -e "**install.packages(c('dplyr', 'tidyr')**, repos = 'http://cran.us.r-project.org', dependencies=TRUE)"
# install node
RUN apt-get update
RUN apt-get install -y nodejs
RUN apt-get install -y npm
ADD . /app
# install node dependencies
RUN cd /app; npm install
WORKDIR /app
EXPOSE 9191
CMD node connect.js*
在这种情况下,我们只需在 RUN 命令中列出它们。以上,我正在安装 dyplr 和 tidyr。
为 Python 服务添加库:
*FROM nikolaik/python-nodejs
# install Python modules
**RUN pip3 install -U numpy
RUN pip3 install -U scipy
RUN pip3 install -U scikit-learn**
ADD . /app
WORKDIR /app
EXPOSE 8181
CMD node connect.js*
对于我们的 Python 服务,我们使用 pip3 install 安装库。注意用于绕过提示的-U 标志。
众所周知,库安装并不总是按计划进行。记住,机器流有 R 和 Python 的日志文件。要查看容器中的日志文件,只需“执行”容器。例如,进入 r_ml 容器我们可以运行:
*sudo docker exec -i -t machine_flow_r_ml_1 /bin/bash*
…并且查看 R 的 r_log.log 文件,Python 的 py_log.log ,数据目录内的:
*vi data/r_log.log*
更改读取、写入和结果路径
在服务模式下,我们需要更改机器流程使用的路径。首先,点击顶部的齿轮图标:
并将路径更改为:
同样,打开中的 connect.js 两个* r_ml 和 python_ml 目录,更改:*
*fs.appendFileSync(**"../data/r_log.log"**, data)*
到
*fs.appendFileSync(**"data/r_log.log"**, data)*
构建图像和运行服务
我们通过运行以下命令,使用 docker-compose 构建r _ ml 和 python_ml 映像:
*docker-compose build*
然后运行我们的容器,通过运行:
*docker-compose up*
您应该看到以下内容,以确认服务已经启动并正在运行:
*Attaching to machine_flow_r_ml_1, machine_flow_python_ml_1r_ml_1 | R Machine Learning on port: 9191python_ml_1 | Python Machine Learning on port: 8181*
注意:如果你和开发模式在同一台机器上,在运行 docker-compose up 之前,一定要停止在端口 9191 和 8181 上运行的节点服务。
摘要
无论你是想从机器流程开始,还是想建立自己的 GUI 服务,我认为数据科学朝着这个方向发展是很重要的。通过自动化产品发现之前的必要探索,将机器学习工作流程 GUI 化形成了一个完整的开发职责。机器学习没有选项,它有可能性。通过快速评估我们数据的就绪性,并揭示从原始数据到验证模型的可行路径,我们为自己在机器学习项目上取得更多成功做好了准备。
和往常一样,如果你遇到问题,请在评论区提问。
如果你喜欢这篇文章,你可能也会喜欢:
* [## 学习建立机器学习服务,原型真实的应用程序,并部署您的工作…
在这篇文章中,我将向读者展示如何将他们的机器学习模型公开为 RESTful web 服务,原型真实…
towardsdatascience.com](/learn-to-build-machine-learning-services-prototype-real-applications-and-deploy-your-work-to-aa97b2b09e0c) [## 用 D3.js 从玩具视觉过渡到真实应用
我们经常孤立地学习技术和方法,与数据科学的真正目标脱节;至…
towardsdatascience.com](/combining-d3-with-kedion-graduating-from-toy-visuals-to-real-applications-92bf7c3cc713) [## 创建 R 和 Python 库的分步指南(在 JupyterLab 中)
r 和 Python 是当今机器学习语言的支柱。r 提供了强大的统计数据和快速…
towardsdatascience.com](/step-by-step-guide-to-creating-r-and-python-libraries-e81bbea87911)*
[指南]使用 React、NodeJS 和 MySQL 构建数据科学 Web 应用程序
原文:https://towardsdatascience.com/guide-building-data-science-web-application-with-react-nodejs-and-mysql-1c55416ff0fb?source=collection_archive---------3-----------------------
数据科学是任何企业的强大工具。然而,为了将数据科学应用到业务中,我们必须开发一种工具,普通用户可以轻松地使用它来从查看数据中获益。
Tableau 或 PowerBI 等数据可视化工具是数据探索工具如何为任何业务增加巨大价值的绝佳例子。
最近,我有机会为股票市场数据从头开始开发另一个数据探索工具。由于我必须处理从服务器到开发 API 和前端应用程序的所有事情,我觉得这些知识和经验可能对其他希望开发数据科学 web 应用程序的人有所帮助。
在这篇博文中,我将带您了解构建我几周前构建的 web 应用程序的过程和开发。如果你有兴趣看代码,请随时通过 Twitter ( @woraperth )告诉我。以后我可能会考虑在我的 Github 上开源代码。[由于许多请求,我已经清理了代码并将其发布在 Github 库上]
股票分析器 Web 应用程序
这是我在 1 周内构建的 web 应用程序。它不是最漂亮的,但我希望界面足够简单,让用户看得懂。
我们为什么需要这个应用程序?
分析师想要分析股票市场中可能成为他们潜在客户的公司。逐一查看每家公司会花很多时间。他们需要易于使用的工具来帮助他们加快这个过程。
“股票分析器”的目标是利用股票市场数据并构建简单的界面来帮助分析师找到合适的客户。
我们有哪些数据,在哪里可以找到这些数据?
数据由每个股票市场中每只股票每天的股价组成。
股票市场数据可以从财经网站获得,如 Yahoo!金融。它允许您指定日期范围,并下载每只股票历史数据的 CSV 文件。
项目架构:React & NodeJS & MySQL
(Image by author)
最重要的部分是计划我需要什么技术,以及我如何将它们联系在一起。我决定通过使用 NodeJS 构建 API 并将数据发送到 React 前端来挑战自己。这是我第一次编写 NodeJS 代码,也是我第一次以现代方式构建 web 应用程序(将后端与前端分离)。
我看到很多现代网站都是这样发展的,而且他们的网站都很快。我知道我可能很难开发它,因为我以前没有这样做过,但从长远来看,了解它是如何工作的会让我受益匪浅。
下面是这个应用程序如何在幕后工作:(请按照上面的架构图像,从左到右&从上到下)
- 用户访问一个网站,看到由 React 构建的前端
- 当用户请求数据时,前端会连接 NodeJS 构建的 API 端点请求数据
- NodeJS 将从 MySQL 数据库中查询数据,然后将结果发送回前端
- MySQL 数据库会将文本文件中的数据加载到数据库中,每隔一段固定的时间,例如每天。
项目准备和组织:数字海洋和 Git
(Image by author)
因为我计划将后端和前端分离,所以我可以在不同的服务器上设置后端和前端,没有任何问题。
对于后端,我选择在 DigitalOcean 上安装云服务器(类似于 AWS 的服务,但使用起来简单得多)。我喜欢 DigitalOcean,因为它易于安装,支持团队提供了许多关于如何在他们的云服务器上安装不同软件的有用文章。
下面是我用来安装 NodeJS、Nginx 和 MySQL 的文章列表:
- NodeJS 安装教程(这也将教你使用 PM2,它有助于在后台服务 NodeJS 应用程序。因此我们不必保持终端窗口打开):https://www . digital ocean . com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-Ubuntu-16-04
- Nginx 安装教程(为了暴露 NodeJS 端口,我们需要 Nginx 做反向代理。我们必须首先启用防火墙,然后允许 SSH。否则我们将被锁在服务器之外):https://www . digital ocean . com/community/tutorials/how-to-install-nginx-on-Ubuntu-16-04
- MySQL 安装教程:https://www . digital ocean . com/community/tutorials/how-to-install-MySQL-on-Ubuntu-16-04
对于上面的 Nginx 部分,确保运行这个命令来允许 SSH:
sudo ufw enable
sudo ufw allow ssh
对于前端,我可以使用任何可以提供 HTML 页面的 web 服务器。
开发流程和技术堆栈
(Image by author)
为了开发这个应用程序,我首先按照上面提到的教程设置了 git 存储库和服务器环境。然后我开始开发 API 端点。测试完 API 后,我开发了前端应用程序来连接 API。
我用的技术是数据库用的 MySQL ,后端 API 用的 NodeJS ,前端用的 React 。选择这些技术是有原因的:
为什么选择 MySQL
(Image by author)
- 因为股票数据存储在结构化数据文件(CSV)中,所以它可以轻松地存储在关系数据库(如 MySQL)中
- MySQL 是开源的,受欢迎的,并且支持标准的 SQL 命令。对我们来说,转换到任何支持 SQL 的数据库软件都很容易
- 通过在 NodeJS 中使用“mysql”模块,可以自动对输入进行转义以防止 sql 注入
为什么 NodeJS
(Image by author)
- 另一种流行的开发后端的编程语言。用于 LinkedIn 和易贝等大公司
- 快速运行并支持并行查询
- 使用 Express 构建 API 很简单
- 使用 JavaScript 语法,这使得代码和知识可以与前端共享
- 最重要的是,我以前没有用过它,想学习如何使用它
为什么要反应
(Image by author)
- 易于维护、扩展、重用网页上的组件
- 庞大的第三方组件库,可以即插即用
- 良好的用户体验,因为它非常快
- JSX 太棒了
数据管道:使用 NodeJS 调度数据加载
Screenshot from Node-schedule project at GitHub
我使用 NodeJS 包节点调度器来安排在每天凌晨 1 点将数据加载到 MySQL 数据库中。语法与设置 cronjob 相同。因此,我们可以使用在线工具来帮助编写 cron,如 crontab 。
注意,我是数据工程领域的新手。因此,这可能不是计划任务的最有效方式。我还发现,通过 NodeJS 加载数据比用 MySQL 命令行直接加载数据需要更多的 RAM。
用 NodeJS 记录日志
(Image by author)
日志记录非常有用,尤其是当我们在后台运行进程时,例如数据加载。我们可以随时打开日志文件,看看在我们睡觉的时候是否出了什么问题。
我使用 NodeJS 包 winston 来管理日志。winston 允许我将错误从警告信息中分离出来,这非常方便。
这个项目中有两个日志文件:
- logs/error.log — SQL 错误
- logs/combined.log —警告&信息
额外的功能:股票比较
股票分析器的第一个版本可以一次看到一只股票的表现:
(Image by author)
“数据点只有在与其他数据点进行比较并在它们之间建立联系时才能获得价值。我不相信一个组织可以在没有标杆的情况下存在。”
——Jan-Patrick Cap,引自《外部观察》(2017)
我觉得一次只显示一只股票很枯燥。它也没有给将要使用这个工具的分析师带来多少价值。
最近,我读了一本名为《外部洞察力》的好书,书中谈到了我们如何利用外部数据的力量。有一个关于标杆管理的话题让我很感兴趣。
我决定进一步开发这个应用程序,增加比较多只股票的功能。这样,分析师可以看到这些公司在市场上的实际表现。在某些情况下,我们可能会发现,与其他公司相比,业绩非常好的公司可能收益很小。
(Image by author)
我从这个项目中学到了什么
这是一个伟大的项目,我学会了使用新技术和新方法将不同的技术联系在一起。与 CMS 后端的传统网站相比,我发现 NodeJS API 的反应非常快,而且成本很低(我每月为云支付 5 美元)。然而,当交通拥挤时,速度可能会很慢。
将来,我可以改进数据工程过程,以达到行业标准。因为我以前没有这方面的经验,所以我有兴趣学习更多关于数据工程的知识。也很难找到实用指南。如果你知道研究这个的好地方,请随意分享:)
我还想探索其他数据库软件,看看哪一个性能最好。我在考虑使用 Postgres,或者像 MongoDB 这样越来越受欢迎的 NoSQL,或者像 BigQuery 这样的云数据存储也可能是一个不错的选择,因为这个应用程序更像 OLAP 而不是 OLTP。
我希望这个博客对正在寻找开发数据科学 web 应用程序的人有用。如有任何问题,请随时在 Twitter @woraperth 上联系我。
附录
这是我从这个项目中学到的有用的东西。如果您想使用相同的技术栈来开发项目,它会派上用场。
常见问题
- 运行“npm start”后出现错误“listen EADDRINUSE 8080”
运行“killall -9 node”通常可以修复该问题。阅读更多关于 StackOverflow 的信息。 - 要求等待许多任务完成后再做下一部分
我们可以用 Promise 来处理异步。很久以前,我用样本代码写了一个博客,但它仍然运行得很好(除了 2018 年我们不再需要 polyfill) - 试图通过 NodeJS API 端点
加载数据时没有足够的 RAM 如果浏览器标签失效,也没关系,因为这是由于浏览器超时造成的。如果节点失效,请将 droplet 的内存增加到 2GB 或 4GB,然后再试一次。 - 服务器时间不在墨尔本时间
运行此命令设置时区:sudo dpkg-reconfigure tzdata
检查当前服务器时间:timedatectl - 如何检查 mysql 是否正在运行
运行此命令检查 MySQL 状态:system CTL status MySQL . service
如果 MySQL 没有运行,运行此命令启动 MySQL: sudo systemctl start mysql
最初发表于 沃拉特纳珀斯 。
学术研究论文阅读指南
原文:https://towardsdatascience.com/guide-to-reading-academic-research-papers-c69c21619de6?source=collection_archive---------2-----------------------
学会用系统的方法处理这个费力的过程!
My desk full of papers. Slightly shuffled around for dramatic purposes of course.
在数据科学和机器学习领域工作是一个令人兴奋和具有挑战性的领域。新的技术和工具在不断渗透,老实说,这种感觉让人无法抗拒。许多这些新发展都是在学术研究文章中发现并首次披露的。从这些文章中提取知识是困难的,因为这些论文的预期读者往往是其他研究人员。然而,为了跟上时代潮流,阅读论文是一项基本技能——幸运的是,这项技能可以通过勤奋和练习来提高。
在研究生院,你很擅长(应该会很擅长…)阅读论文和吸收研究成果。不是每个人都会接受这方面的培训,但这并不意味着你不能从这些文章中获益。公共税收是这项研究的大部分资金来源。这里的目标是使学术界民主化,只是一点点,并为你在浏览论文时提供一个应用的脚手架。
我阅读论文的方式并不特别独特,但它很有效,对我很有帮助。请记住,这不是唯一的方法,有很多技巧,随着你阅读的越来越多,我相信你会找到自己独特的风格。
本指南细分如下:
- 学习这个技能会帮到你!我保证
- 我听说读论文很难。为什么?
- 论文通常是如何组织的?
- 我阅读论文的“防弹法
- 帮助您完成工作的工具
为什么要学看论文?
阅读报纸当然可以培养性格,因为这通常要花很多时间,而且不能保证你能看完整个故事。这并不是贬低你,而仅仅是为了公开透明。阅读论文是困难的,这是毫无疑问的。机器学习、深度学习、数据科学、数据库和数据工程等领域的进步通常以学术研究的形式出现,其语言是学术论文。想想你可能会用到的一些技术:卷积神经网络、 PCA 、 AdaBoost (甚至深度增强!).这些都来自研究,是的,他们都有论文。此外,考虑到有许多关于这些技术的应用和使用的论文,当您试图解决一个特定的问题时,这些论文可能是至关重要的。除了跟上当前的研究之外,回到过去读一读旧论文也是值得的。你会学到很多东西。我保证。
纵观深度学习领域,似乎每隔几天或几周就会有一篇新的批判性论文问世。掌握它的唯一方法是拿起报纸读一读。
哪里出现困难…
这是哈伯德和邓巴 2017 年发表的一篇科学论文中的一个数字,关于阅读科学论文。科学论文盗梦空间!
Fig 2. Different sections of scientific papers are considered easy to read and important at different stages of academic careers.
答:参与者认为某一部分容易阅读(表现为“有些容易”、“容易”、“非常容易”的组合)的比例,作为职业阶段的函数。卡方检验的结果显示在左侧。 B: 作为职业阶段函数的部门平均重要性等级。为清楚起见,省略了单个点的误差线,唯一的灰色误差线表示任何数据点的最大 95%置信区间。数据点上方的星号表示与之前的职业阶段相比,响应有显著差异,这由 Mann-Whitney 事后测试确定。
一个不足为奇的结果表明,学术上的进展越深入,他们就越容易阅读论文的每一部分。有趣的一点是,各个职业阶段如何看待每个部分的重要性。方法、结果和数字似乎非常重要,表面上是因为作为的学者他们在自己的领域有更高的技能,这使得他们可以对论文的方法提出批评。这也意味着他们非常了解自己的领域,因此,引言和摘要就不那么重要了。早期阶段的博士生发现这些方法、结果和数字很难理解。这非常有意义,因为这些领域是论文中最需要某个领域知识的部分。你很可能有类似的经历。
到底是什么让这个过程如此困难和耗时?
- 作者倾向于假设读者的重要背景知识
- 学术语法非常密集,因此读者很难分析
- 数学表达式通常被压缩,为了简洁,方程被重新排序,经常跳过推导的步骤
- 如果读者阅读了被引用的论文,大量的知识空白就被填补了(有点像——你需要经验才能得到工作,但需要工作才能得到经验!)
- 不是所有的结论都是正确的。小样本量和功效、糟糕的研究设计、研究者偏见和选择性报告确保了你必须成为批判性读者!
显然,阅读论文时需要考虑很多问题。害怕吗?是时候放松一下了。这里有一篇有趣的文章,由科学的亚当·鲁本博士写的关于阅读论文的恐惧。这表明,即使是科学家也同意,论文很难阅读,而且考虑到它们的密度,会让你保持规律。
想想看,你读的论文越多,你学到的就越多,这个阅读的过程就变得越快。趋势开始浮现在眼前,你开始洞察科学方法,了解某些作者和团体正在做什么,并对你正在学习的领域形成一种欣赏。随着时间的推移,所有这些知识和技能都会让你更快、更有效、更成功地阅读论文。学习读报类似于学习吃饭。一开始很乱,你的调色盘也不是很发达。但是随着时间的推移,你的饮食经验会增加,你会更多地了解你喜欢什么和不喜欢什么,以及厨师的饭菜是好是差。
论文是如何组织的
这里有好消息。绝大多数论文或多或少遵循相同的组织惯例:
- 标题:希望朗朗上口,可能性感!包括关于作者和他们的机构的附加信息
- 摘要:高度概括
- 引言:该领域的背景信息和导致本文的相关研究
- 方法:非常详细的部分研究进行,它是如何设置的,使用的任何工具,最后,过程和工作流程
- 结果:作者谈论的是创造或收集的数据,它应该被理解为对所发生的事情的无偏见的描述
- 讨论:作者在这里解释结果,并说服读者他们的发现和假设
- 参考资料:在正文中引用的任何其他作品都会在这里显示
- 附录:更多的数字,相关数学的额外处理,或者额外感兴趣的项目可以在附录中找到它们的方式
开发系统方法
当你坐下来阅读时,制定一个计划是很重要的。仅仅从第一页开始阅读到最后一页可能对你没有好处。除了保留有限的信息之外,你会精疲力尽,而且付出巨大的努力却收获甚微。这是很多人止步的地方。
做好计划,从花 3-6 个小时真正消化一篇论文,记住它们非常密集!准备好并愿意让通过论文几次,每次都希望提取不同的信息和理解。请帮你自己一个忙,不要在你第一遍的时候从头到尾读完这篇论文。
下面是两个列表。我在阅读论文时或多或少采取的系统方法。)我在浏览论文时试图回答的一系列问题。我通常会根据论文增加更具体的问题。
我们开始吧!
- 试着找一个安静的地方呆几个小时,拿上你最喜欢的饮料(可能是咖啡、茶,或者任何其他东西)。现在我经常发现自己在华丽的咖啡店里工作。
- 从阅读标题和摘要开始。旨在获得论文的高水平概述。作者的主要目标和高水平的结果是什么。摘要通常为论文的目的提供一些线索。把摘要想象成广告。
- 花大约 15 分钟略读这篇论文。快速浏览图表,并注意阅读文本时要注意的关键词。试着对报纸的布局和东西的位置有个概念。稍后,你将在不同的部分和页面之间来回引用,这有助于了解资料的位置。试着不要花时间做笔记或强调/强调任何事情。
- 把注意力转向简介。我对论文/领域越不熟悉,我花在介绍上的时间就越长。作者倾向于做好巩固背景信息和提供大量参考资料的工作。这一部分通常是最容易阅读的,感觉就像你在读教科书一样。记下你不知道或不想进一步研究的其他参考资料和背景信息。
- 这部分极其关键。仔细浏览每一个图形,试着感受它们告诉你的东西。当我还是本科生的时候,我的神经科学导师给了我一些很好的建议。转述:“图包含了论文中一些最重要的信息。作者花了大量的时间创建它们,并认为它们包含的信息足够重要,可以通过视觉传达给读者。请特别注意它们。“第一次浏览时,你不会很好地理解所有的数字,但你会对作者认为最重要的东西有所了解,而且你还会透露出阅读其他部分时需要注意的有价值的信息。
- 到目前为止,你可能已经花了大约一个小时。休息一下。散散步,享受羊角面包!
- 现在你已经准备好第一次通过纸张了。这次你应该开始做一些高水平的笔记。你会遇到对你来说陌生的词汇和想法。不要觉得你需要在每一件没有意义的事情上停下来,你可以简单地标记它,然后继续前进。目标是花大约一个半小时。你不想陷入所有血淋淋的细节。第一遍的目标是熟悉论文。就像第一次约会。你要了解报纸,问一些好问题,也许会让它发笑。但你不会想深入每一个细节。那是粗鲁的。从摘要开始,快速浏览简介,给方法部分一个勤奋的通行证。请注意整体设置,方法部分包括大量的细节,此时您不需要仔细检查每个部分。最后,阅读结果和讨论部分,了解关键发现以及这些发现是如何确定的。请记住,作者试图说服你,读者,他们工作的价值和发现。
- 被铃声救了。休息一下,做一些跳跃运动,让血液流动起来。除非你在咖啡店里。那就别这么做。
- 现在你已经对论文有了一个很好的概述,你将进入数字的本质。在阅读了方法、结果和讨论部分之后,你应该能够从这些数字中提炼出更多的精华。找到那些宝石。目标是再花 30 分钟到 1 小时在这些数字上。
- 你应该对第二次全面通过试卷充满信心。这一次你将会以批判的眼光阅读。这个过程可能需要一两个小时,你也可以把它留到当天晚些时候,或者第二天。特别注意你标记为难以理解的地方。不要留下未定义的单词,并确保你理解每个句子。这一关你是在尝试真正的学习论文。浏览你有信心的领域(摘要、介绍、结果)。重点应该是巩固你以前不理解的内容,掌握方法部分,最后成为讨论部分的批判性读者。在讨论部分,你可以考虑作者的推理/理性,并把你从阅读论文中学到的东西与论文中提供的证据进行权衡。这一部分应该会引发一些有趣的问题,让你问你的朋友或同事。你甚至可以给论文作者发电子邮件,提出一个有见地的问题!他们可能需要一段时间才能给你回复,但是作者确实喜欢就他们的研究进行对话,并且通常非常乐意回答读者的问题。
- 在这一点上,你应该有信心与同事谈论这篇论文,批判性地思考结果,并能够将这项工作与该领域的其他研究进行比较(如果你读过其他论文)。为了保留和强化你所学到的东西,我建议你写关于论文的内容。它可以简单地是几段关于你学到了什么和结果的意义。当你通读这篇论文时,你可以参考你所回答的问题列表。
如上所述,这里有一个通用的问题列表来帮助指导你。如果你能回答这些问题,你就对这篇论文有了很好的理解,至少你能就此与他人进行明智的交流。
1\. What previous research and ideas were cited that this paper is building off of? (this info tends to live in the introduction)
2\. Was there reasoning for performing this research, if so what was it? (introduction section)
3\. Clearly list out the objectives of the study
4\. Was any equipment/software used? (methods section)
5\. What variables were measured during experimentation? (methods)
6\. Were any statistical tests used? What were their results? (methods/results section)
7\. What are the main findings? (results section)
8\. How do these results fit into the context of other research and their 'field'? (discussion section)
9\. Explain each figure and discuss their significance.
10\. Can the results be reproduced and is there any code available?
11\. Name the authors, year, and title of the paper!
12\. Are any of the authors familiar, do you know their previous work?
13\. What key terms and concepts do I not know and need to look up in a dictionary, textbook, or ask someone?
14\. What are your thoughts on the results? Do they seem valid?
我建议亲自或在网上找人来讨论这篇论文。建立一个日志俱乐部,目标是每月完成 1-2 篇论文。通过与朋友讨论论文,我获得了巨大的额外洞察力。纪念..唯一比独自忍受论文的痛苦更好的事情,就是和朋友一起忍受它!
另外,Keshav 写了一篇关于如何阅读论文的好文章。他介绍并探索了一种三阶段方法,您可能会感兴趣。也读一读吧!
帮助您完成工作的工具
您可以从以下几个来源找到论文:
- 一个 rXiv :是一个开放存取的知识库(维护在康乃尔),在这里你可以免费下载和阅读许多定量领域的预印研究论文。这里是更多关于 arXiv 的一般信息。你在网上找到的许多论文都会链接到 arXiv 论文。
- PubMed :他们说得最好:“ PubMed Central (PMC)是美国国立卫生研究院国家医学图书馆(NIH/NLM)的生物医学和生命科学期刊文献的免费全文档案。如果你正在寻找医学或生命科学相关的论文,PubMed 有一个强大的搜索功能。
- 谷歌学术:我会像使用谷歌一样使用谷歌学者。只需搜索一个主题、作者或论文,谷歌就会代表你开始工作。正如谷歌所说的“”谷歌学术提供了一种广泛搜索学术文献的简单方法。从一个地方,你可以搜索许多学科和来源:文章,论文,书籍,摘要和法院意见,从学术出版商,专业协会,在线仓库,大学和其他网站。谷歌学术帮助你在学术研究领域找到相关的工作。
- 社交媒体:我通过跟踪和保持与几个积极发表文章的人的联系,发现了很多新论文。附加奖金..他们通常会推送他们感兴趣的、你可能想了解或阅读的其他论文。
- 朋友和同事:找到和你兴趣相同的人,和他们一起读论文,互相学习。我从朋友那里得到好论文的推荐。它们是很好的过滤器。
- 大学:去你当地的学院或大学(如果附近有)可以让你接触图书馆,图书馆员(非常有用的搜索向导!)和许多期刊,在那里你可以找到并阅读在线付费墙后面的文章。
当你开始阅读更多的文件时,你会想把它们存放在某个地方。将 pdf 文件放入你硬盘上的一个文件夹中固然很好,但是缺少了一些物质享受。大多数研究人员和研究生使用一个咨询经理。 Zotero 和门德利很受欢迎,我喜欢 Zotero。最近一直在用纸堆。我喜欢 PaperPile,因为它是轻量级的,存在于我的浏览器中,并使用 Google Drive 来备份和存储我所有的 pdf。它有一个简单的,令人耳目一新的用户界面,它有一个非常好的标签和文件夹层次系统。我还可以在我的浏览器中注释 pdf,并在写作时建立引用列表。几乎任何参考资料管理器都有很多这样的功能,但我碰巧最喜欢 PaperPile。
随着你收集和阅读越来越多的论文,推荐人将很快成为你最好的朋友。
感谢您通读这篇文章。我希望它对你有所帮助,并且在你处理下一篇论文时给你一些好的想法。大多数人在看论文的时候都有自己独特的流程。我相信你会及时开发你自己的调整,希望这是一个很好的模板让你开始。
现在只需要相信过程。
我也希望我们能从读者那里得到一些好的反馈和评论,以及其他的提示和技巧。
干杯,
狭海峡
联系我:datasci@kmshannon.com
linkedin.com/in/kmshannon/
twitter.com/ButFirstData
[1]哈伯德,K. E .,&邓巴,S. D. (2017)。对科研文献的看法和阅读论文的策略取决于学术生涯阶段。 PloS one , 12 (12),e0189753。
[2]在 CoffeeCycle 向克里斯大喊!简直是圣地亚哥最好的咖啡。
[3]凯沙夫,S. (2007 年)。如何阅读一篇论文? ACM SIGCOMM 计算机通信评论, 37 (3),83–84。
NIPS 2018 竞赛赛道指南以及如何参与
原文:https://towardsdatascience.com/guide-to-the-nips-2018-competition-track-and-how-you-can-participate-6e75f992ea3b?source=collection_archive---------25-----------------------
今年是国家实施计划的第二个年度“竞赛轨道”。在竞赛跑道上,有许多有趣的比赛项目可供参加。所有的活动都很容易参加,并跨越 ML 的许多领域。竞赛适用于广泛的行业,包括汽车、安全、医疗保健和物理。
终身机器学习 AutoML(截止日期 10 月 26 日)
这场比赛的重点是建立一种算法,可以在没有任何人工干预的情况下,自动为后续任务创建预测模型。竞赛分为两个阶段:反馈阶段和测试阶段。在反馈阶段,组织者提供了五个与最终测试数据集性质相似的数据集。在第二阶段,上传的模型代码将在五个测试集上进行盲评估。这种竞争具有挑战性,因为分布将随着时间的推移以及各种特征类型(即分类、时间、二元等)的变化而缓慢变化。所有必要的数据和说明都可以在官方网站上找到。
对抗性视觉挑战(最终提交日期 11 月 1 日)
这项挑战的重点是制造鲁棒的视觉计算机视觉算法,对敌对的干扰有抵抗力。这对于保护计算机视觉模型免受恶意用户的攻击以及创建更加健壮的模型非常重要。首先,你可以转到 GitLab 库,然后按照指示进行操作。
对话智能挑战 2(convai 2)(9 月 30 日提交截止日期)
这是一个旨在开发非目标导向聊天机器人的竞赛。为了比赛,他们提供了一个有趣的新数据集,这个数据集是通过将众包工人配对在一起,给他们一个简单的角色并让他们聊天而制作的。评估将分三步完成:通过自动化评估指标(困惑、F1 和点击率),对机械土耳其人的评估,以及志愿者与机器人聊天的“野生”评估。
你可以在这里找到基线模型的源代码。首先,你需要创建一个私有的 Github 库,并与组织者共享。更多信息请访问官方网站。
追踪机器学习挑战
这是一个与物理学相关的挑战,涉及使用机器学习来检测粒子在碰撞后的路径。由于需要非常快速地对粒子碰撞数据进行分类,这项竞赛非常重要。目前,预计算法不会随着来自 LHC 的数据量的增加而扩展。比赛正在进行,包括几个不同的部分。第一阶段始于 5 月,将于 8 月结束,重点是重建粒子轨迹的准确性。第二阶段(NIPs 竞赛的焦点)关注模型在测试时的速度。
关于项目动机的 PDF 幻灯片
Kaggle 比赛(已完成)
(截止日期 11 月 26 日)
这项比赛的重点是训练一队 AI 智能体,在 Bomberman 的策略游戏的变种 Pommerman 的游戏中与另一队 AI 智能体的玩家进行比赛。这个竞赛是一个有趣的多智能体学习实验,在互补和对抗两个层面上。更多信息请参见 Github 或上面的官方网站链接。
包容性图片(截止日期 11 月 9 日)
NIPs 2018 赛道的又一场比赛。该竞赛旨在解决数据失真的问题。“具体来说,在这场比赛中,研究人员将在开放图像【2】上进行训练,这是一个大型、多标签、公开可用的图像分类数据集,已被发现表现出地理倾斜。”
AI 驾驶奥林匹克(截止日期 11 月 30 日)
这个你可能已经很熟悉了,因为它已经在 Reddit 和其他网站上流传,但如果你不熟悉,我会描述一下。“人工智能驾驶奥运会”于 10 月正式开始,将由两部分组成,第一部分于 12 月在 NIPS 举行,第二部分于 5 月在 ICRA 举行。比赛由三个独立的任务组成:车道跟踪,动态车辆的车道跟踪,以及动态障碍物的导航。你可以去他们的官方网站了解更多信息。
人工智能假肢挑战赛
最后但同样重要的是人工智能假肢挑战赛。这项挑战旨在使用 RL 来学习最佳策略,以帮助装有假肢的人跑步。这个挑战是 RL 在现实世界问题中的有趣应用。这是“学习跑步”在 NIPs 的第二年,有相当多的文章让你开始。最后,你可以在 GitHub 库上找到所有的额外信息和更多挑战信息。
正如你所看到的,今年在 NIPs 有一系列真正有趣的挑战,跨越了许多行业和机器学习领域。希望你能找到一个你感兴趣的并参与竞争。祝你好运!
用数据科学指导你在非洲的下一笔房地产投资
原文:https://towardsdatascience.com/guide-your-next-property-investment-in-africa-with-data-science-5a9fd623bb52?source=collection_archive---------5-----------------------
信息:该分析最初由余晚晚发表。点击此处查看原始代码和内容。
这里的目标是在选定的非洲国家( 【加纳】 , 肯尼亚 和 尼日利亚 )中确定利润最高和利润最低的国家/地区,以便用数据科学技术指导您的房地产投资决策。
投资房地产的理想社区应该有
- 高租金
- 低价出售。因此,租金将高于每月的按揭付款,以赚取利润。
为此,我们需要一种方法来比较租赁价格和销售价格。对于每个街区,我们计算了两件事:
- 租赁价格的每平方英尺单价和销售价格的每平方英尺单价
- 假设 20%的首付、19.67%的年利率(选定国家的平均值)和 30 年的抵押贷款期限,平均每月抵押贷款额。
在我们开始比较租赁价格和销售价格之前,先看一下数据集是很重要的。
我注意到一些社区很少有甚至没有挂牌。列表数量少可能会带来不稳定性并导致错误的结果。因此,我删除了等于或少于 5 个列表的邻域,以确保数据的质量。
Data showing distribution by number of property listings by region
以下是一些拥有 3 个以上房源的小区的例子。例如,在尼日利亚阿布贾的一平方英尺租金为 4.53 美元,购买价格为 344 美元,而在大阿克拉地区的一平方英尺租金为 1.68 美元,购买价格为 165 美元。肯尼亚内罗毕——租金 2.47 美元,房价 203 美元。
评估盈利能力
为了衡量一个地区的利润,我们计算了租金单价与销售单价的比率。这意味着:单位租售比越高,该地区的利润越低。见下图:
Profitability Ratio Distribution
根据我们的盈利能力评估,下面的图表显示了所有选定国家中房地产投资盈利最多和最少的地区。
Top Profitable Regions by Ratio
Least Profitable Regions by Ratio
最后
这种分析可能并不完美,因为这些国家之间没有标准的汇率。因此,价格可能会有变化(尼日利亚本身至少有四种不同的美元汇率)。此外,数据源(web scraped from House Jumia)可能不包含所有列出的属性,因此有点偏。
然而,这并没有放弃应用于该分析的技术。
我想听听你对分析的反馈。请留言或发送推文@ elesinOlalekan
我们希望这能对你的房地产投资决策有所帮助。
感谢 余晚晚 让我重现她的分析
使用 KNIME 分析平台的引导式分析
原文:https://towardsdatascience.com/guided-analytics-using-knime-analytics-platform-b6543ebab7e2?source=collection_archive---------11-----------------------
Guided Analytics KNIME workflow
什么是引导式分析?
虽然“引导式分析”这个词会让你的思维进入一种复杂的状态,但它仅仅意味着自动化数据科学。引导式分析允许数据科学专业知识较少的人浏览流程,并看到隐藏在现有数据中的新见解。例如,学校的 IT 管理员可以跟踪这一过程,并预测未来的结果,如特定班级的学生在特定科目上的表现。
什么是 KNIME?
KNIME Analytics platform 是数据科学中最受欢迎的开源平台之一,用于自动化数据科学流程。KNIME 的节点库中有数千个节点,这允许您将节点拖放到 KNIME 工作台中。相关节点的集合创建了一个工作流,在将工作流部署到 KNIME 服务器之后,该工作流既可以在本地执行,也可以在 KNIME web 门户中执行。KNIME 通过帮助自动化过程,帮助在 KNIME 平台中创建作为工作流的引导分析过程。
数据科学生命周期
Data science lifecycle
上图描绘了从数据清理到模型评估的递归数据科学生命周期。在向 Cinglevue 的 Virtuoso 平台引入引导式分析时,我们基本上专注于为 Virtuoso 最终用户提供灵活性和用户友好性。我们开发的引导式分析流程的范围从功能选择到模型评估,假设用户已经清理了数据。最上面的图说明了 KNIME 引导的分析工作流,该工作流用于实现前面提到的从特征选择到模型评估的过程。当您在 KNIME server 中部署这个工作流时,您可以通过 web 门户访问它,并获得用户友好的向导。基本上,它允许用户将数据集上传为 csv 文件,如下所示。
File upload wizard
然后将这些特征以表格的形式列出,其中包含使用正向特征选择方法获得的精度值。基本上,前向特征选择所做的是,它一次迭代地向模型添加一个特征,并在添加特定特征后找到模型的准确度分数。用户可以浏览列表,并通过考虑准确性来选择他认为将在模型中工作的一些特征。
Feature Selection wizard
下一个屏幕要求用户选择目标变量,如下图所示。
Target variable selection wizard
第四个屏幕显示了用户可以用来训练数据集的分类算法列表。
ML Algorithm selection wizard
在下一个屏幕中,用户可以通过 ROC 曲线和条形图查看所选算法中哪个算法执行得最好,以便于理解。下图描述了这种情况。
Graphical model comparison
最后一步允许用户下载 PMML 格式的最佳模型,它允许在任何企业应用程序中使用。
架构
High level architecture
上图描述了所采用的引导式分析流程的高级架构。分析服务包装在 KNIME 服务器上,它允许列出并执行已部署的 KNIME 工作流。Virtuoso 平台直接与分析服务对话,并执行与特征选择和建模相关的工作流。预测服务在开放评分引擎之上实现。Virtuoso 平台直接与预测服务对话,并利用 openscoring 的模型部署和模型评估功能。
cing levu 是如何在 Virtuoso 平台中引入导向分析的?
为了将引导式分析引入 Virtuoso 平台,我们必须将最上面的图中描述的 KNIME 工作流分解为针对分类和回归类型问题的特征选择和模型训练。
数据源访问本身是在前端完成的。重要的是,任何 csv 格式的数据集都可以利用这一工作流程获得新的见解。上传数据集后不久,用户需要选择目标变量。选择目标变量后,其余提取的特征列在可用特征列表框中,用户可以选择他认为会影响结果的任何特征。所选择的特征通过分析服务被发送到 KNIME 服务器,以运行工作流并发送回所获得的评估度量(准确性)。使用前向特征选择方法通过迭代添加特征来获得准确度值。如下图所示,所获得的精度值显示在所选特征下。
我们使用准确度作为分类类型问题的前向特征选择标准,而使用 R 作为回归类型问题的前向特征选择标准。如前所述,主引导分析工作流已被分解为几个子工作流,特征选择是一个子工作流。我们在后台使用的工作流程如下图所示。
Feature Selection KNIME workflow
对于分类类型问题,我们在前向特征选择元节点中使用朴素贝叶斯算法来预测添加特征的精度值,如下图所示。
Forward feature selection using Naive Bayes algorithm
对于回归类型的问题,我们在正向特征选择元节点中使用线性回归算法来预测添加特征的 R 值,如下图所示。
Forward feature selection using Linear Regression algorithm
然后下一步是根据在机器学习方法选择下选择的挖掘函数来选择列出的机器学习算法。如果选择了分类方法,则会列出分类算法;如果选择了回归方法,则会在算法选择下列出回归算法。所选算法以及数据集和所选要素被发送到 KNIME 服务器,以 PMML 格式返回所选算法的精度或性能 R 值以及最佳模型。结果显示为条形图,如下图所示。
Algorithm Selection for a classification type problem
Algorithm Selection for a regression type problem
下图显示了用于分类和回归类型问题的模型训练的后端 KNIME 工作流。模型训练元节点内部使用的 ML 算法根据挖掘功能的性质(分类或回归)而变化。
在这个阶段,我们已经完成了特征选择和模型训练这两个步骤。然后是模型部署和模型评估。Virtuoso 平台利用 Openscoring 引擎的功能来实现这两个目的。
我们获得的最佳模型的 PMML 文件使用用户给定的模型 id 部署到 Openscoring 引擎中。部署的模型如下图所示。
Deployed ML model list
一旦用户点击特定模型的评估按钮,与该模型相关的输入字段将与有效边界一起列出,如下图所示。
Input fields for model features
下一步是使用这个接口评估模型的不可见数据,如下图所示。
下一步将是验证获得的结果,并将新数据输入到重新训练模型中,以获得更好的预测。将会带来另一篇有趣的博文,讲述如何通过继续数据科学生命周期来重新训练模型。
如果您需要任何澄清,请通过udeshika.sewwandi@cinglevue.com联系我。非常感谢您对这种自动化数据科学流程的方法的宝贵意见。
延伸阅读
[1]https://www.knime.com/blog/principles-of-guided-analytics
[2]https://www . knime . com/knime-software/knime-analytics-platform
[3]https://en.wikipedia.org/wiki/Data_science
[4]https://en.wikipedia.org/wiki/Machine_learning
[5]https://en.wikipedia.org/wiki/Automated_machine_learning
用 Python 分析黑客新闻书籍建议
原文:https://towardsdatascience.com/hacker-news-book-suggestions-64b88099947?source=collection_archive---------9-----------------------
一个黑客新闻线程的分析,使用 Python,黑客新闻 API 和 Goodreads API,以及权威的前 20 名书籍建议列表!
几天前,传统的“你今年读了什么书”主题出现在黑客新闻上。线程充满了非常好的书籍建议。我试图为明年做一份阅读清单,我认为收集数据并分析它会很有趣。在接下来的文章中,我将展示我如何使用 Hacker News 的 API 来收集文章内容,我如何选择最常见的标题并对照 Goodreads API 进行检查,最后我如何得出最值得推荐的 20 本书。和往常一样,处理文本数据一点也不简单。不过最后的结果还是挺满意的!
抓取线程:黑客新闻 API
第一步是获取数据。幸运的是,黑客新闻提供了一个非常好的 API 来免费抓取它的所有内容。API 有帖子、用户、热门帖子和其他一些的端点。对于本文,我们将使用一个帖子。用起来很简单,下面是基本语法:v0/item/{id}/.json
其中 id 是我们感兴趣的项目。在这种情况下,线程的 id 是 18661546.json()) ,因此这里有一个关于如何获取主页面数据的示例:
import requests
main _page = requests.request(‘GET’, ‘[https://hackernews.firebaseio.com/v0/item/18661546.json').json()](https://hacker-news.firebaseio.com/v0/item/18661546.json').json()))
相同的 API 调用也用于线程或帖子的子帖子,其 id 可以在父帖子的kids
键中找到。在孩子们身上循环,我们可以得到线程中每个帖子的文本。
清理数据
现在我们有了文本数据,我们想从中提取书名。一种可能的方法是寻找文章中所有的 Amazon 或 Goodreads 链接,并按此分组。这是一种干净的方法,因为它不依赖于任何文本处理。然而,只要快速浏览一下这个帖子,就可以清楚地看到,绝大多数建议都没有任何关联。所以我决定走一条更难的路:将 n gram 分组,并将这些 n gram 与可能的书籍匹配。
因此,在从文本中剔除特殊字符后,我将二元模型、三元模型、四元模型和五元模型组合在一起,并计算出现的次数。这是一个计算二元模型的例子:
import re
from collections import Counter
import operator# clean special characters
text_clean = [re.sub(r"[^a-zA-Z0-9]+", ' ', k) for t in text for k in t.split("\n")]# count occurrences of bigrams in different posts
countsb = Counter()
words = re.compile(r'\w+')
for t in text_clean:
w = words.findall(t.lower())
countsb.update(zip(w,w[1:]))# sort results
bigrams = sorted(
countsb.items(),
key=operator.itemgetter(1),
reverse=True
)
通常在文本应用中,处理数据时首先要做的事情之一是消除停用词,即一种语言中最常见的词,如冠词和介词。在我们的例子中,我们还没有从我们的文本中删除停用词,因此这些 ngrams 中的大多数几乎都是由停用词组成的。事实上,下面是我们数据中最常见的 10 个二元模型的输出示例:
[((u'of', u'the'), 147),
((u'in', u'the'), 76),
((u'it', u's'), 67),
((u'this', u'book'), 52),
((u'this', u'year'), 49),
((u'if', u'you'), 45),
((u'and', u'the'), 44),
((u'i', u've'), 44),
((u'to', u'the'), 40),
((u'i', u'read'), 37)]
在我们的数据中有停用词是好的,大多数标题书中都会有停用词,所以我们希望保留这些停用词。然而,为了避免查找太多的组合,我们排除了仅由停用词组成的 ngrams,保留了所有其他的。
检查书名:Goodreads API
现在我们有了一个可能的 n gram 列表,我们将使用 Goodreads API 来检查这些 n gram 是否对应于书名。如果有多个匹配项可供搜索,我决定将最近的出版物作为搜索结果。这是假设最近出版的书最有可能与这种环境相匹配。这当然是一个可能导致错误的假设。
Goodreads API 使用起来没有 Hacker News 那么简单,因为它以 XML 格式返回结果,比 JSON 格式更不友好。在这个分析中,我使用了xmltodict
python 包将 XML 转换成 JSON。我们需要的 API 方法是[search.books](https://www.goodreads.com/api/index#search.books)
,它允许通过标题、作者或 ISBN 来搜索书籍。以下是获取最近发布的搜索结果的书名和作者的代码示例:
import xmltodictres = requests.get("[https://www.goodreads.com/search/index.xml](https://www.goodreads.com/search/index.xml)" , params={"key": grkey, "q":'some book title'})xpars = xmltodict.parse(res.text)
json1 = json.dumps(xpars)
d = json.loads(json1)lst = d['GoodreadsResponse']['search']['results']['work']
ys = [int(lst[j]['original_publication_year']['#text']) for j in range(len(lst))]title = lst[np.argmax(ys)]['best_book']['title']
author = lst[np.argmax(ys)]['best_book']['author']['name']
这个方法允许我们将 ngrams 与可能的书籍关联起来。我们用 Goodreads API 对照全文数据检查匹配所有 ngrams 的图书列表。在进行实际检查之前,我们删除了书名,去掉了标点符号(尤其是半栏)和副标题。我们只考虑主标题,假设大部分时间只使用标题的这一部分(列表中的一些完整标题实际上很长!).根据线程中出现的次数对我们得到的结果进行排序,我们得到以下列表:
Books with more than 3 counts in the thread
所以《坏血》看起来是帖子里最受推荐的书。检查其他结果大部分似乎是有意义的,并与线程匹配,包括计数。我能在列表中发现的唯一一个大错误是在第二位,这本书被列为魔法师而不是列夫·格罗斯曼的《魔术师 T2》。后者在文中确实被引用了 7 次。这个错误是由于我们假设 Goodreads API 的结果中考虑了最新的书。至于原始数据上的结果,没有出现在列表中,除了三体,我找不到任何明显的结果。这本书或同一三部曲中的其他书在文中被多次引用,但因为它们被不同的名称或不同的标点符号引用,所以没有被这种方法提取出来。解决这个问题的一个方法是在这个步骤中使用模糊匹配。
结论
在本文的结论中,我展示了如何从黑客新闻中提取数据,解析数据以提取书名,使用 Goodreads API 检查书名,并将最终列表与原文进行匹配。这个任务被证明是相当复杂的,因为它需要几个假设和处理两个不同的 API。而且最终的结果还是有一些不正确的结果。
尽管如此,我设法得到了一个好的最终结果。以下是《黑客新闻》推荐的前 20 本书的名单:
- 《恶感:硅谷的秘密和谎言》约翰·卡瑞鲁
- 我们为什么睡觉:释放睡眠的力量,马修·沃克著
- 列夫·格罗斯曼的《魔术师》
- 鞋狗:耐克创始人菲尔·奈特回忆录
- 迈克尔·波伦《如何改变你的想法》
- 真实:汉斯·罗斯林的《我们看错世界的十个理由》
- 维克多·e·弗兰克尔《人类对意义的探索》
- 卡尔·纽波特的深入研究
- 《德乌斯人:明日简史》尤瓦尔·诺亚·哈拉里著
- D.M .凯恩的凤凰计划
- 尤瓦尔·诺亚·哈拉里的《21 世纪的 21 课》
- 系统中的思考:多内拉·h·梅多斯的初级读本
- 沃尔特·伊萨克森的达芬奇
- 克里斯·沃斯的《永不分裂》
- Jocko Willink 的极端所有权
- 吉姆·赫夫龙的线性代数
- 生活的 12 条规则:混乱的解毒剂
- 蒂姆·马歇尔的《地理囚犯》
- 纳西姆·尼古拉斯·塔勒布的《游戏中的皮肤》
- 詹姆斯·克利尔的原子习惯
源码可以在Github上查看。任何形式的评论或批评都将不胜感激。
人工智能基因组黑客马拉松上的黑客数据艺术
原文:https://towardsdatascience.com/hacking-data-art-at-an-ai-genomic-hackathon-62e16efb49ce?source=collection_archive---------3-----------------------
不久前,我注意到一个有趣的黑客马拉松即将到来。人工智能基因组学黑客马拉松聚焦于一种罕见的疾病()。是的,我曾向自己保证不再参加任何黑客马拉松,但这太难以抗拒了。它结合了我最喜欢的两件事:编程和科学。此外,找到一种罕见疾病的治疗方法的可能性非常有吸引力。所以我填好申请表,点击“发送”,然后等着听我是否被录用。
我在去度假前不久发现我被录取了。我乘喷气式飞机离开,完全忘记了黑客马拉松。几个星期以来,我漫步于伦敦、威尼斯和佛罗伦萨,欣赏艺术、建筑、旧地图和科学仪器。
在黑客马拉松的前几天,我精神焕发地回到家,准备继续编码和解决问题。但是说实话,我也有点时差。
黑客马拉松于周五晚上开始, Onno Faber 与 NF2 分享了他的个人故事。他谈到了为什么他把自己的基因组数据给了这个项目,以及他希望我们可以用它来帮助找到治疗方法。晚上剩下的时间充满了关于 NF2 周围的科学和我们在项目中可以使用的各种工具的有趣的谈话。
这不是黑客马拉松吗?我为什么做艺术?
最初,我计划在黑客马拉松上做一些生物信息学。或者对医疗日志进行一些自然语言处理。但是在活动的前几天,一些组织者看了我的作品集,Onno 问我是否可以用基因组数据创作一些艺术作品。
一个周末的黑客马拉松时间不多,尤其是对于创建数据艺术来说。但它有足够的时间来开始和发挥一些想法。艺术可能需要很长时间,但我喜欢在黑客马拉松上开始一个项目的想法……熟悉一些数据,更好地理解科学。
什么是 NF2?
NF2 基因与肿瘤抑制有关,当突变破坏蛋白质时,疾病就会发展,肿瘤就会沿着听神经生长。除了寻找治疗 NF2 的方法,研究 NF2 基因的一个动机是该基因可能以某种方式与其他癌症有关。
Python (Biopython + PIL)
Python 是这个项目的合理选择,因为我要处理基因组数据。我很快选择了图书馆,因为我知道我可以以后再换。毕竟,这只是一个周末项目。
我知道有些数据是 FASTA 格式的,所以我查找了可以处理 FASTA 文件的库。Biopython 看起来记录良好且易于使用。
对于视觉草图,我保持简单并使用 Python 图像库(PIL/枕头),它可以写入各种图像文件格式。我以前用过它,所以我可以很快上手,而不需要学习新的库。
我的黑客马拉松
当大多数参与者组成小组并提出项目计划时,我在独自工作。我对我想要创造的东西有一些想法,但保持它们相当流畅,因为这将是一次创造性的探索。这与我以前在黑客马拉松中经历的任何事情都非常不同。在黑客马拉松期间,我发了几个帖子,上面有正在进行的工作的截图。
入门指南
对我来说,任何涉及数据的项目的第一步都是获取数据,并将数据打印到控制台或终端。
这是我的第一张草图。这是人类骨 gla 蛋白的 DNA 序列,我用 Biopython 从 FASTA 文件中提取的。这一步的全部目的是确保我从文件中获得了正确的数据段。在这种情况下,是第一串碱基(ATGC)编码了基因。FASTA 文件可以包含几个序列。
First Step: output data to terminal.
我还想更好地了解 Biopython 库,它有打开 FASTA 文件和从中提取数据的便利功能。
注意:出于隐私考虑,当我从代码和数据中创建图像时,我使用公开可用的基因组数据作为我的“快照”。
Creating an image file from the data.
一旦我将数据打印到终端,我就开始创建图像并将它们保存到我的本地文件系统。我的目标是解析数据,并根据数据中的值生成图像。在这种情况下,它是一串核苷酸(DNA)。
这个迭代的代码仍然有很多问题,但是它确实生成了一个新的图像,并且数据被用来创建这个图像。
Mosaic of images
我已经编写了 python 脚本来创建一个使用随机起始颜色的图像,所以每次运行脚本时都会创建一个新的调色板。当我看到我的图像渲染时,我惊讶地发现它们多么像彩色马赛克中的瓷砖。
一些形式的 NF2 不是种系,而是镶嵌或“自发”突变:这一事实激发了这幅早期草图。黑客马拉松第一天晚上的演讲开始激励我。
Getting transparency working with individual layers with PIL
下一个比我预期的要长一点。对我来说,棘手的部分是弄清楚如何让 python 图像库用一些透明度来绘制每个“点”,这样我就可以得到这种混合的视觉效果。
之前,我已经将序列字符串中的每个字母处理并呈现为一个中间图像,然后将其写入最终图像。但是为了获得透明度,每个点都必须单独写入最终图像。这需要大量的图像渲染。
第一稿代码很慢,效率很低…我需要优化,只将点的面积写入图像,而不是整个图像的面积…但在返回优化之前,我一直在玩视觉效果。让自己继续前进并不容易。我不得不不断提醒自己这是一次黑客马拉松,时间很短。
Starting to hint at the Codons in the sequence.
在这次迭代中,我想让这些点重叠,就一点点。我已经解决了透明度问题,结果不那么抽象,密码子作为三联体更加明显。在遗传学中,一个基因中的密码子就像一个句子中的单词;每个都有特定的含义。它们有三个核苷酸长,编码特定的氨基酸。例如,AUG 是一个“起始密码子”。它位于起始处,编码 Met 氨基酸。
Sleek
只是为了好玩,我尝试了不同的背景颜色。我很高兴黑色的背景让它看起来如此时尚。语境决定一切。小的改变可以带来大的不同。
Digging deeper into Biopython: translating Codons to Amino Acids
所以,我选择 Biopython 库不仅仅是因为它能够打开和读取 FASTA 文件。它也使得将 DNA 序列的密码子翻译成氨基酸序列变得容易。在这个阶段,我已经知道如何用 Biopython 翻译密码子,并将 DNA 和氨基酸序列输出到终端。
虽然我知道自己想要什么,但此时我还没有一个清晰的“愿景”。为了加快渲染速度,我限制了序列的绘制量,因为我尝试了视觉创意。
Amino Acid for each Codon
给 DNA 序列中的每个密码子加上氨基酸,就产生了一个令人愉快的模式。但在这一点上,我想打破网格布局。
Pretty Bug
编写代码来创建图像的一个好处是,有时你犯了一个错误(bug ),结果看起来还不错……或者至少很有趣。这里有一个完美的例子。虽然这不是我想要的视觉效果,但我真的很喜欢它的样子。所以我留着它。当我有更多的时间玩它的时候,我可能会回来。
What’s next?
黑客马拉松已经结束了。但这并不意味着我会停止处理这些数据。我仅仅触及了我能用 Biopython 库做的事情的表面,所以我当然想探索更多。我还想更多地玩视觉游戏,探索不同的想法和模式。
- 想了解更多关于黑客马拉松的信息,请查看官方的活动网站。
- 要查看我在黑客马拉松期间的原创帖子,请查看 my Patreon 。
黑客 Scikit-Learn 的矢量器
原文:https://towardsdatascience.com/hacking-scikit-learns-vectorizers-9ef26a7170af?source=collection_archive---------2-----------------------
自然语言处理是一个令人着迷的领域。由于所有的预测因子都是从文本中提取的,因此数据清理、预处理和特征工程对模型的性能有着更加重要的影响。
在我自己的一个涉及 NLP 的机器学习项目中工作了几个月之后,我已经了解了关于 Scikit-Learn 的矢量器的一两件事,我想与大家分享一下。希望在这篇文章结束时,你会有一些新的想法用在你的下一个项目中。
关于 Scikit-Learn 的矢量器
如你所知,尽管机器可能很先进,但它们不能像人类一样理解单词和句子。为了使文档的语料库更适合计算机,它们必须首先被转换成某种数字结构。有一些技术可以实现这一点,但在这篇文章中,我将重点关注向量空间模型,也称为 词汇袋 (BoW)模型。
****词汇袋是解决该问题的一种非常直观的方法,该方法包括:
- 按照某种模式将文档分割成令牌。
- 给每个标记分配一个与它在文档和/或语料库中出现的频率成比例的权重。
- 创建文档术语矩阵,每行代表一个文档,每列寻址一个标记。
Scikit-Learn 提供的矢量器对象开箱即用,非常可靠,它们允许我们一次有效地执行上述所有步骤,甚至可以应用预处理和关于标记数量和频率的规则。最重要的是,它们有三种不同的风格(还有其他版本,如 DictVectorizers,但它们并不常见):
- ****计数矢量器:最简单的一个,它计算一个标记在文档中出现的次数,并使用这个值作为它的权重。
- ****哈希矢量器:这个设计是为了尽可能的提高内存效率。矢量器不是将记号存储为字符串,而是应用散列技巧将它们编码为数字索引。这种方法的缺点是,一旦矢量化,就无法再检索要素的名称。
- TF-IDF 矢量器 : TF-IDF 代表“术语频率-逆文档频率”,这意味着分配给每个标记的权重不仅取决于它在文档中的频率,还取决于该术语在整个语料库中的出现频率。更多关于这里。
下面是一个计数矢量器的例子。
出局:
要更深入地了解每个步骤,请查看我写的这段代码。它实现了 Sklearn 的 CountVectorizer 的一个简化版本,该版本被分解成一些小函数,使其更具可解释性。
定制矢量器
矢量器本身非常强大,可以轻松地执行一些令人惊讶的复杂操作。也就是说,通过修改这些结构,可以将 Scikit-Learn 本身不支持的转换合并到单词包模型中。
创建自定义矢量器时主要使用两种方法:使用 Sklearn 默认分析器的修改版本实例化矢量器,以及创建从 CountVectorizer 继承的类。
修改默认分析器
在幕后,Sklearn 的矢量器调用一系列函数将一组文档转换成文档术语矩阵。其中,三种方法最为突出:
- build_preprocessor :返回一个 callable,用于在标记化之前对输入文本进行预处理。
- build_tokenizer :创建一个函数,能够将文档的语料库拆分成标记。
- build_analyzer :构建一个应用预处理、标记化、移除 停用词 并创建 n-grams 的分析器函数。
简而言之,这些方法负责创建默认的分析器、预处理器和标记器,然后用于转换文档。通过用正确的参数实例化矢量器,我们可以轻松地绕过这些方法,创建一个定制的矢量器。让我们看一个如何实现的例子。
让我们模拟一个场景,我们从 web 上删除了一些文本。使用默认设置:
出局:
现在,让我们通过创建一个矢量器来稍微清理一下文档集,该矢量器在预处理步骤中删除了 HTML 实体 ,并在文档被标记化时删除了 词汇😗***
出局:
看看“x00021”和“x0002e”是如何被人类可读的“!”替换的和“.”而“跳跃”被简化为引理?另外,如果你以前从未使用过 spaCy ,我建议你看一下它的文档。SpaCy 是一个高度优化的模块,能够同时执行多个复杂的 NLP 任务,它可以是一个救命稻草。
如果由于某种原因,您不能将转换分成预处理和标记化阶段(这种方式可能效率不高),那么您可以选择创建一个定制的分析器来同时执行这两个步骤。
自定义矢量器类
尽管用户定义的分析器可能会派上用场,但它们会阻止矢量器执行一些操作,如提取 n 元语法和删除停用词。引用 Scikit-Learn 的文档:
“默认分析器都调用预处理器和标记器,但是定制分析器将跳过这一步。N-gram 提取和停用词过滤发生在分析器级别,因此自定义分析器可能需要重复这些步骤。
例如,当使用预处理器+记号赋予器组合时:
矢量器创建单字、双字并删除停用词如“The”:
另一方面,当尝试使用自定义分析器执行相同的操作时:
输出不显示二元模型,包含停止字:
发生这种情况是因为当使用用户定义的分析器时,build_analyzer
方法不调用_word_ngrams
,T1 负责移除停止字并提取 n 元语法。
避免这种情况的一种方法是创建定制的矢量器类。这个概念非常简单,只需创建一个从基础矢量器继承的新类,并根据需要覆盖build_preprocessor
、build_tokenizer
和/或build_analyzer
方法。
所以,让我们再试一次,但是这次创建一个自定义矢量器类:
出局:
非常管用!尽管很耗时,但这种方法让分析器知道在矢量器实例化期间使用的任何参数,从而允许自定义函数与矢量器的其余部分无缝集成。
最后的想法
考虑到创建定制矢量器的不同方法,我的建议是总是首先尝试使用最简单的方法。这样你就减少了错误发生的几率,避免了许多不必要的麻烦。
此外,值得指出的是,这篇文章中讨论的结构本身非常通用,但只有在与 管道 中的其他变压器结合使用时,它们的真正潜力才会显现出来。你可以在这里了解更多关于这个的信息。
我希望这篇文章给你一套新工具,用在你的下一个项目上!
破解你的图像识别模型
原文:https://towardsdatascience.com/hacking-your-image-recognition-model-909ad4176247?source=collection_archive---------5-----------------------
Staircase to 99% Classification Accuracy
一旦您找到/创建了一个数据集,构建了一个卷积网络,并训练了模型,您就有了您的性能指标。很有可能,一开始你可能对你的模型的性能不太满意。以下是提高图像识别模型性能指标的一些最常用策略:
根据实施的难易程度/耗时程度,它们被分为两组。
黑客集群#1:易于实现
一、添加更多数据:改善你的图像识别模型的一个最简单的办法就是给它添加更多数据!如果你已经建立了一个很深的网络,或者你没有太多的训练实例,这是非常有用的。如果你有一个小的数据集,比如每个类中有 50 张图片,这可能就是你需要的。如果你对为什么添加更多数据会产生更好的模型感到好奇,我推荐这篇著名的文章。
二。添加更多的层:如果你有一个复杂的数据集,你应该利用深度神经网络的能力,在你的架构上添加更多的层。这些附加图层将允许您的网络学习更复杂的分类函数,从而提高分类性能。
Add more layers!
三。增大/减小图像尺寸:当您为训练和评估对图像进行预处理时,需要对图像尺寸进行大量实验。如果您选择的图像尺寸太小,您的模型将无法识别有助于图像识别的显著特征。如果您的图像太大,您可能没有足够的数据,或者您的模型可能不够复杂,无法处理它们。
一五、更多的训练时间:喝杯咖啡,用更多的纪元增量训练模型。以+25、+50、+100,..看看额外的训练是否提高了你的分类器性能。但是,您的模型将达到一个点,在这个点上,额外的训练时间不会提高准确性。在实验的同时,你也可以了解更多关于你的学习率参数。记得在每次实验迭代中加载并保存你的模型。
五、颜色通道:这里有很多选项可以选择 RGB、YUV、灰度,甚至灰度图像中的进一步处理像素值,所以它们只能取 X 数量的值,例如,[0,64,128,255]。颜色通道越复杂,数据集就越复杂,训练模型所需的时间就越长,但是,如果您有一个深度模型,这可能是一个很好的解决方案。
黑客集群#2:更难实现
六。迁移学习:避免让你的卷积神经网络学习边缘和线条等特征,相信聪明人已经用他们的 ResNet 做了很好的工作。将模型下载并加载到您的工作流中,然后更改完全连接的图层以适应您的问题。这篇文章声称迁移学习帮助他从 71%提高到 96%的准确率。
七世。数据扩充:尝试通过翻转图像、添加噪声或任何其他您认为不会破坏数据集的失真,将合成数据添加到您的数据集。如果你是一个强大的机器学习工程师,你也可以尝试用 GANs 进行数据增强。
VIII。改变内核大小,激活函数:这种技术带有一个“我希望你知道你在做什么”的警告,因为有一些数学涉及到确保你在每个卷积层正确地转换数据。然而,如果你是一名机器学习研究人员,这可能是一个很好的解决方案。
这些是提高分类器性能、训练更长时间、添加更多数据、添加合成数据、改变图像大小、改变颜色通道、转移学习、添加层以及改变内核大小和激活函数的一些解决方案。这些解决方案中的任何一个都可以帮助您获得额外的 5%的图像识别准确性,这一点至关重要。感谢阅读,请留下一些掌声!
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对软件经济学、深度学习和软件工程感兴趣。
今天的头发,明天就没了
原文:https://towardsdatascience.com/hair-today-gone-tomorrow-cfcaa7c31f3b?source=collection_archive---------7-----------------------
自从我上次剪头发以来已经有相当长的时间了。它现在已经过了我的肩膀,在过去的几年里它一直留在那里。
尽管它还在生长,但它不再长了,因为它也脱落了。它已经达到了一个动态平衡,头发生长的速度等于头发脱落的速度。
为了更好地理解这个过程,我查阅了一些关于头发生长的事实。头发以每月大约 0.5 英寸的速度生长。人的头上大约有 100,000 根头发,其中每天大约有 100 根脱落。这相当于每月 3%的头发脱落。头发还有其他细微差别,但我简化了模型,以假设生长是恒定的,所有头发都有相同的脱落机会。
我在 R 中模拟了这种动态,并绘制了一个图表来观察头发长度如何随时间变化。它开始没有头发(想象一个寸头),收敛到大约 16 英寸的稳定状态长度。将 y 轴反转,使图本身看起来像悬挂的几缕头发。
假设 T 是一个随机变量,代表一缕头发脱落前的时间,或者一根头发的年龄。在统计学中,风险率是某个事件(如失败或死亡)发生的瞬时率,假设它尚未发生。
hazard rate
通过应用条件概率的定义,
而取极限为 dt → 0,危险率就是概率密度函数(pdf)与 1 的比值——累积密度函数(cdf)。危险率唯一地表征了一个分布,反之亦然。常数风险率是指数分布的独特性质。
这里的危险率是. 03/月,所以 T ~ Exp (率= . 03/月)。头发年龄呈指数分布,平均年龄为 1/.03 = 33 个月。由于长度随年龄线性增长,头发长度~ Exp (比率= . 06/英寸),平均长度为 16.7 英寸。这与模拟中收敛的平均毛发长度一致。Q-Q 图将模拟的最后一个时间步长的头发长度与随机生成的指数进行比较,并确认它们具有相同的分布。
汉密尔顿:联邦党人文集的文本分析
原文:https://towardsdatascience.com/hamilton-a-text-analysis-of-the-federalist-papers-e64cb1764fbf?source=collection_archive---------3-----------------------
用潜在语义分析探索汉密尔顿、麦迪逊和杰伊在联邦党人文集里的写作风格
此处代码实现
Photo by Ryan Quintal on Unsplash
在这一点上,你可能已经听说过这部戏剧,汉密尔顿,这是席卷百老汇电路和复兴国家利益的“十美元无父开国元勋”。
这是一部极具娱乐性的引人入胜的故事,并且具有历史真实性(带有一些创作自由)。联邦制当然有了性感的改变。
在其中一首歌曲《马不停蹄》中,艾伦·伯尔的角色让我们来回顾一下这段关于《联邦党人文集》写作的令人难忘的台词:
“约翰·杰伊在写完第五部后生病了。麦迪逊写了二十九个。汉密尔顿写了另外 51 个。”
This line really resonated with people. [Source: altarandwitchinghour]
这是令人振奋的一句话,它激励我看一看《联邦党人文集》,看看在这个国家结束其 240 周年纪念日之际,这些政治巨人给美国人留下了什么样的遗产。这些文件打破了有利于批准宪法的政治平衡,为我们今天所珍视的民主奠定了基础。我想回答这样一个问题:现代文本分析是否能对这些有影响力的作品提供任何高层次的见解。
使用 Python 的 NLP
注意:这一部分技术含量很高,所以如果你不喜欢 NLP,可以直接跳到结果部分。
首先,下载 85 份联邦党人文集的文本。幸运的是,古腾堡计划是一个免费的在线电子书库,保存着联邦党人文集(以及大量其他书籍!)向公众提供。我下载了 1.2 MB 的 txt 文件,并将其加载到 Jupyter 笔记本中。
立刻,我可以看到文本必须被清理。古登堡计划许可证和 HTML 格式弄乱了文本,每篇论文都必须从单个文件中解析出来。我清理了格式,构建了一个文本刮刀,按照作者将每篇论文分离出来,并加载到一个包含作者、标题和语料库的 Pandas 数据框架中。到目前为止一切顺利!
接下来,我必须弄清楚如何对单词进行定量建模以便可视化。我最终使用了 sci-kit learn 的 Tf-idf 矢量化(术语频率-逆文档频率),这是自然语言处理的标准技术之一。归结到基本术语,这种技术跟踪一个单词在单个文档中出现的频率,如果它在所有其他文档中也频繁出现,则惩罚该分数。这是衡量一个词的重要性和独特性的标准。
对每个单词都这样做,就可以为每篇联邦党人论文创建一个定量向量。在过滤掉常见的英语单词如“of”和“they”后,我们最终得到了 558,669 个独特的单词 n-grams。我们对 Tf-idf 分数高于某个阈值的短语进行优先排序,以便在论文中找到可能的关键词。
尽管如此,我们仍然处于困境。这给了我们一个(85 x 558669)向量——在我们当前的现实中是不可能用图表示的。我们正在尝试做的是一种叫做潜在语义分析(LSA)的东西,它试图通过对文本内容中的潜在模式进行建模来定义文档之间的关系。
信息时代是仁慈的,幸运的是,LSA 算法有开源实现,比如奇异值分解(SVD)。该算法降低了文本向量的维数,同时使我们能够保留数据中的模式。完美地满足了我们将数据降低到二维的可视化需求!
结果:奇怪的预示
The Federalist Papers, visualized. [Image By Author]
整洁的图表。这意味着什么?
每个点代表一份联邦党人文件,由作者用颜色编码。这两个轴代表转换后的数据—它们本身没有任何意义,但是它们作为相互比较的点是有价值的。你可以看到汉密尔顿和麦迪逊的论文倾向于占据图表上不同的空间——这表明他们在文章中优先考虑不同的语言。这可能是在论文中写不同主题的副产品。尽管如此,每个人选择写的主题仍然可以揭示意识形态。
鉴于詹姆斯·麦迪逊和亚历山大·汉密尔顿在 18 世纪 90 年代后期的分裂,《联邦党人文集》中的词汇差异获得了新的意义。约翰·杰伊广泛参与外交事务,是美国第一任首席大法官,他的著作主要论述了外国影响的危险以及联邦制度防范其他国家的必要性。
从高层次来看,这很棒,但是单词本身呢?我们可以对每篇联邦党人论文的前 10 个 Tf-idf 分数进行排序,看看哪些短语最有特色。下面我列出了两篇论文的输出示例。鉴于联邦党人论文 10(防范政治派别)和联邦党人论文 11(联邦主义对经济贸易的有益影响)的主题,关键短语似乎非常相关。
Paper 10 | madison
faction 0.0806265359389276
majority 0.05308879709884898
number citizens 0.05002710059542178
small republic 0.04879259622492929
parties 0.048153279676380355
other 0.045091031288949604
interests 0.04313049392358246
passion interest 0.04168925049618481
republic 0.041154310712061014
number 0.040803681072543126
Paper 11 | hamilton
trade 0.08024350997462926
markets 0.06991189047603769
navigation 0.0674719898424911
navy 0.0562800477401255
commerce 0.05284120721585442
ships 0.04681698985492806
commercial 0.03619823151914739
america 0.03323133785132385
maritime 0.03230134296600752
naval 0.03230134296600752
对每位作者最常用的 10 个单词进行统计后发现:
Most common words for James Madison:[('government', 12),
('states', 12),
('state', 9),
('people', 6),
('other', 4),
('representatives', 4),
('governments', 3),
('all', 3),
('knowledge', 3),
('powers', 3)]
即使在《联邦党人文集》中,詹姆斯·麦迪逊也表现出对州与联邦政府之间的关系、代表政党的作用以及人民意愿等主题的偏好。
相比之下:
Most common words for Alexander Hamilton:[('government', 8),
('president', 8),
('states', 8),
('power', 7),
('executive', 6),
('senate', 6),
('state', 6),
('national', 6),
('union', 5),
('court', 5)]
亚历山大·汉密尔顿通过关于联邦政府各部门的语言以及对强调各州联合的术语的偏好,表明了他强烈的联邦主义立场。虽然没有迹象表明汉密尔顿和麦迪逊在《联邦党人文集》中的意识形态分歧,但有趣的是,考虑到两者之间的词汇选择肯定反映了不同的优先事项。
Most common words for John Jay:[('government', 3),
('nations', 2),
('people', 2),
('congress', 1),
('navigation fleet let', 1),
('national government', 1),
('efficiency government', 1),
('senate', 1),
('navigation', 1),
('militia obeyed', 1)]
对于约翰·杰伊来说,他的作品更有限,因为他只写了五篇论文。他们都讨论了外国利益对美国的影响,以及如何需要一个强大的联盟来对抗其他国家。文本分析很好地反映了这些主题——讨论民兵、舰队和效率。
非常感谢 NLTK、sci-kit learn、numpy 和 pandas 的开发者。还要感谢托马斯·休斯教授的文本分析 tf-ifd 可视化教程(https://github.com/tmhughes81/dap)。
欢迎在 LinkedIn 、 Twitter 、 Github 或 Medium 上与我联系!
深度学习中不平衡数据集的处理
原文:https://towardsdatascience.com/handling-imbalanced-datasets-in-deep-learning-f48407a0e758?source=collection_archive---------1-----------------------
给原力带来平衡!
Bring balance to the force!
想获得灵感?快来加入我的 超级行情快讯 。😎
并非所有的数据都是完美的。事实上,如果你能得到一个完美平衡的真实世界数据集,你将会非常幸运。大多数情况下,您的数据会有某种程度的类不平衡,这是因为您的每个类都有不同数量的示例。
为什么我们希望我们的数据是平衡的?
在将时间投入到深度学习项目中任何潜在的漫长任务之前,理解为什么我们应该这样做是很重要的,这样我们才能确定这是一项有价值的投资。只有当我们真正关心少数类时,类平衡技术才是真正必要的。
例如,假设我们正试图根据当前的市场状况、房子的属性和我们的预算来预测我们是否应该买房子。在这种情况下,非常重要的是,如果我们购买,那么这是正确的决定,因为这是如此巨大的投资。同时,如果我们的模型在我们应该买的时候说不要买,这也没什么大不了的。如果我们错过了一所房子,总会有其他房子可以买,但在如此巨大的资产上进行错误的投资将是非常糟糕的。
在这个例子中,我们绝对需要我们的少数“购买”类非常准确,而对于我们的“不购买”类来说,这没什么大不了的。然而,在实际情况下,由于在我们的数据中,购买比不购买要少得多,我们的模型将偏向于很好地学习“不购买”类,因为它拥有最多的数据,可能在“购买”类上表现不佳。这就需要平衡我们的数据,这样我们就可以更加重视正确的“买入”预测!
如果我们真的不关心少数阶级呢?例如,假设我们正在进行影像分类,您的类别分布如下所示:
乍一看,平衡我们的数据似乎会有所帮助。但也许我们对那些少数民族阶层不太感兴趣。也许我们的主要目标是获得最高可能的百分比精度。在这种情况下,做任何平衡都是没有意义的,因为我们大部分的百分比准确度都来自有更多训练例子的职业。第二,即使数据集不平衡,当目标是最高百分比准确度时,分类交叉熵损失往往表现得相当好。总之,我们的少数阶级对实现我们的主要目标没有多大贡献,所以平衡是不必要的。
综上所述,当我们遇到需要平衡数据的情况时,有两种方法可以帮助我们。
(1)重量平衡
重量平衡通过改变每个训练示例在计算损失时携带的重量来平衡我们的数据。通常,我们的损失函数中的每个示例和类别将具有相同的权重,即 1.0。但是有时我们可能希望某些类或者某些训练例子更重要。再次参考我们购买房子的例子,因为“购买”类的准确性对我们来说是最重要的,所以该类中的训练例子应该对损失函数有显著的影响。
我们可以简单地通过将每个例子的损失乘以取决于它们的类别的某个因子来给这些类别加权。在喀拉斯,我们可以这样做:
我们创建了一个字典,基本上说我们的“购买”类应该为损失函数保留 75%的权重,因为“不购买”类更重要,我们相应地将它设置为 25%。当然,可以很容易地调整这些值,为您的应用找到最佳设置。如果我们的一个类比另一个类有更多的例子,我们也可以使用这种平衡方法。与其花费时间和资源试图为少数阶级收集更多,我们可以尝试使用重量平衡,使所有阶级平等地为我们的损失做出贡献。
我们可以使用的另一种平衡训练示例权重的方法是下面显示的。主要思想是:在我们的数据集中,我们自然会有一些比其他人更容易分类的训练示例。在训练期间,这些示例将以 99%的准确率进行分类,而其他更具挑战性的示例可能仍然表现不佳。问题是那些容易分类的训练例子仍然是造成损失的原因。当有其他更具挑战性的数据点,如果正确分类,可以对我们的整体准确性做出更大贡献时,为什么我们仍然给予它们同等的权重?!
这正是焦点损失可以解决的问题!焦点损失不是对所有训练样本赋予相等的权重,而是降低分类良好的样本的权重。这实际上是将更多的训练重点放在难以分类的数据上!在我们有数据不平衡的实际设置中,我们的多数类将很快变得分类良好,因为我们有更多的数据。因此,为了确保我们也在我们的少数类上实现高准确度,我们可以在训练期间使用焦点损失来给予那些少数类样本更多的相对权重。聚焦损耗可作为自定义损耗函数在 Keras 中轻松实现:
(2)过采样和欠采样
选择合适的类权重有时会很复杂。做一个简单的逆频率可能不总是工作得很好。焦点丢失可能会有所帮助,但即使这样也会使所有分类良好的样本的权重下降。因此,平衡我们数据的另一种方法是通过抽样直接进行。请看下面的插图。**
Under and and Over Sampling
在上图的左侧和右侧,我们的蓝色类比橙色类有更多的样本。在这种情况下,我们有 2 个预处理选项,可以帮助训练我们的机器学习模型。
欠采样意味着我们将只从多数类中选择一些数据,只使用和少数类一样多的例子。应该进行这种选择以保持类的概率分布。那很容易!我们只是通过减少样本来平衡数据集!
过采样意味着我们将创建少数类的副本,以便拥有与多数类相同数量的实例。复制时将保持少数民族的分布。我们只是在没有获得更多数据的情况下平衡了数据集!如果您发现很难有效地设置类权重,那么采样是类平衡的一个很好的替代方法。
喜欢学习?
在 twitter 上关注我,我会在这里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上与我联系!
绝对初学者使用 XArray 处理 NetCDF 文件
原文:https://towardsdatascience.com/handling-netcdf-files-using-xarray-for-absolute-beginners-111a8ab4463f?source=collection_archive---------2-----------------------
探索 Python 中与气候相关的数据操作工具
Photo by Alberto Restifo on Unsplash
N etCDF 是一种独立于机器的、面向数组的、多维的、自描述的、可移植的数据格式,被各种科学团体所使用。它的文件扩展名是。nc 或。cdf (虽然据信两者之间有细微差别)。不像里的文件。csv 或。xlsx ,NetCDF 格式无法使用电子表格软件直接访问和查看。
即使你可以,你也不会用一堆元数据来处理一个四维数据。
我将以美国 大气辐射测量气候研究机构 (ARM)和欧洲 欧洲中期天气预报中心 (ECMWF)的气候数据为例。
目录
- 先决条件
- 替代品
- 数据预览
- 术语
- 使用 XArray 编码
- 备注
原载于我的博客edenau . github . io。
先决条件
我们将使用 Python 中的[xarray](http://xarray.pydata.org/en/stable/)
库进行数据处理。长话短说,它建立在numpy
(和dask
)库的基础上,并利用了pandas
的能力,但是你可能不需要了解它。正如您可能知道的,包依赖是 Python 中的一个难点。这就是为什么安装所有东西最方便的方法是使用以下命令:
$ conda install xarray dask netCDF4 bottleneck
建议有经验的 Python 程序员查看相关的文档了解更多细节。如果你是初学者,不用担心。我列出了你需要检查的依赖项:
- Python2.7/3.5+必需
- numpy 1.12+ 必填
- 熊猫 0.19.2+ 必填
- 为插补特征
- 瓶颈 加速跳 NaN
- *****netCDF 4-python*用于基本的 netCDF 读/写等操作
- dask-array0.16+与 dask 进行并行计算
如果您想要可视化您的数据集,您可能需要这些:
- matplotlib1.5+用于绘图
- cartopy 为地图
- seaborn 更好的调色板
对于绝对的初学者,您可以通过以下方式检查您的默认 Python 版本
**$ python --version
Python 2.7.5**
您还可以通过以下方式检查 Python3 是否已安装
**$ python3 --version
Python 3.4.9**
要检查软件包的版本,使用pip freeze
或conda list
。如果你通过conda
安装xarray
的话,事情应该没问题。
可供选择的事物
[iris](https://scitools.org.uk/iris/docs/latest/)
是xarray
的替代品,但需要做一些工作才能让它在 Windows 上工作,在 Mac OS 上效果不好。Iris 也是一个英文单词,所以谷歌‘iris’会给你很多不相关的结果。使用iris
对我来说是一种痛苦。
数据预览
“预览”和“了解”您的数据、其元数据和数据结构总是一个好主意。假设您已经安装了netCDF4-python
,您只需要两个命令ncdump
和ncview
。前者给出了 netCDF 数据集的文本表示(基本上是元数据和数据本身),而后者是一个非常强大的图形界面,用于即时数据可视化。
ncdump
转到数据集的目录并尝试
**$ ncdump -h twparmbeatmC1.c1.20050101.000000.cdf**
由于此时我们不需要查看每个数据条目的值,-h
确保只显示标题(元数据)。你会得到
**netcdf twparmbeatmC1.c1.20050101.000000 {
dimensions:
time = UNLIMITED ; // (8760 currently)
range = 2 ;
p = 37 ;
z = 512 ;
variables:
double base_time ;
base_time:long_name = "Base time in Epoch" ;
base_time:units = "seconds since 1970-1-1 0:00:00 0:00" ;
base_time:string = "2005-01-01 00.00, GMT" ;
base_time:ancillary_variables = "time_offset" ;
float prec_sfc(time) ;
prec_sfc:long_name = "Precipitation Rate" ;
prec_sfc:standard_name = "lwe_precipitation_rate" ;
prec_sfc:units = "mm/hour" ;
prec_sfc:missing_value = -9999.f ;
prec_sfc:_FillValue = -9999.f ;
prec_sfc:source = "twpsmet60sC1.b1" ;
float T_p(time, p) ;
T_p:long_name = "Dry Bulb Temperature, from sounding in p coordinate" ;
T_p:standard_name = "air_temperature" ;
T_p:units = "K" ;
T_p:missing_value = -9999.f ;
T_p:_FillValue = -9999.f ;
T_p:source = "twpsondewnpnC1.b1:tdry" ;// global attributes:
***< OTHER METADATA >***
}**
您可以看到维度、变量和其他不言自明的元数据。全局属性(上面没有打印)告诉我们如何收集和预处理数据。在本例中,它们是 ARM 在巴布亚新几内亚马努斯 147.4E 2.1S 处获取的测量数据。
当我们查看变量列表:1-dim prec_sfc
和 2-dim T_p
时,我们意识到它们具有不同的维度(!).降水率在每次都是标量测量,而温度在每次都是柱形(这次是在不同气压水平而不是海拔高度水平测量)。在气候科学中,四维数据是很常见的——纬度、经度、海拔/气压水平、时间。
ncview
试试下面的命令,它会给你一个图形界面,列出数据集中的所有变量,非常简单。
**$ ncview twparmbeatmC1.c1.20050101.000000.cdf**
The graphical interface in Linux using ncview
术语
Data structures of xarray
数据阵列
xarray.DataArray
是一个带标签的多维数组的实现,用于单个变量,如降雨量、温度等..它具有以下关键属性:
values
:保存数组值的numpy.ndarray
dims
:各轴的尺寸名称(如('lat', 'lon', 'z', 'time')
)coords
:一个类似 dict 的数组(坐标)容器,用于标记每个点(例如,一维数字数组、日期时间对象或字符串)attrs
:保存任意元数据(属性)的OrderedDict
资料组
xarray.DataSet
是 DataArrays 的集合。每个 NetCDF 文件都包含一个数据集。
使用 XArray 编码
数据导入
在你阅读数据之前,你不能摆弄它。使用open_dataset
或open_mfdataset
读取单个或多个 NetCDF 文件,并将其存储在名为DS
的数据集中。
**import xarray as xr# single file
dataDIR = '../data/ARM/twparmbeatmC1.c1.20050101.000000.cdf'
DS = xr.open_dataset(dataDIR)# OR multiple files
mfdataDIR = '../data/ARM/twparmbeatmC1.c1.*.000000.cdf'
DS = xr.open_mfdataset(mfdataDIR)**
数据检查
还记得数据数组的 4 个关键属性吗?您可以使用DS.values
、DS.var
、DS.dims
、DS.coords
和DS.attrs
进行数据检查。这在交互式 Python 中将变得非常方便。它们的功能非常明显,留给读者作为练习。).
数据阵列提取
从数据集DS
中提取数据数组非常简单,因为DS.<var_name>
就足够了。您可以考虑用dropna()
删除 NaN 条目,并用sel()
选择数据。sel()
中的method
参数允许我们通过使用'pad'
、'backfill'
或'nearest'
方法来启用最近邻(不精确)查找。要指定范围,使用slice()
。
您可以通过da.values
将xr.DataArray
转换为numpy.ndarray
。
**# Extract Dry Bulb Temperature in z-coordinate (T_z)
# Select the altitude nearest to 500m above surface
# Drop NaN, convert to Celcius
da = DS.T_z.sel(z=500,method='nearest').dropna(dim='time') - 273.15 # or .ffill(dim='time')# Select data in 2000s
da = da.sel(time=slice('2000-01-01', '2009-12-31'))
da_numpy = da.values**
按照惯例,DataSet 用大写字母DS
命名,DataArray 用小写字母da
命名。
日期时间操作
假设 DataArray da
有一个 DateTime 格式的维度time
,我们可以通过da.time.dt.<year/month/day/...>
提取出年 / 月 / 日 / 日 / 日。注意,输出仍然在 DataArray 中。
以下示例进一步尝试计算每个月任何变量的平均值/总和。我们先用assign_coords()
定义一个新的坐标系。为什么?尝试观察年和月在日期时间中的表现。如果我们需要系统知道 2000 年 1 月和 2001 年 1 月之间的差异,我们需要年和月来定义一个新坐标,我们称之为year_month
。
然后,我们可以根据新定义的坐标系,通过groupby('year_month')
对数据进行分组,然后进行mean()
或sum()
操作。
**# Contract the DataArray by taking mean for each Year-Month
def mean_in_year_month(da):
# Index of Year-Month starts at Jan 1991
month_cnt_1991 = (da.time.dt.year.to_index() - 1991) * 12 + da.time.dt.month.to_index()
# Assign newly defined Year-Month to coordinates, then group by it, then take the mean
return da.assign_coords(year_month = month_cnt_1991).groupby('year_month').mean()da_1 = mean_in_year_month(da1)**
数据数组合并
我们可以使用xr.merge()
合并多个数据数组。如果试图合并两个同名但不同值的变量,将引发xr.MergeError
。这确保了xr.merge()
是非破坏性的。
**DS_new = xr.merge([da_1,da_2,da_3]).dropna(dim='year_month')**
测绘
您可以简单地将数据数组作为matplotlib.pyplot
方法的参数。对于绝对的初学者,尝试使用plt.plot()
或plt.scatter()
绘制线图或散点图。记住通过plt.show()
显示数字,或者通过plt.savefig()
保存数字。
如果你需要地图,cartopy
库可以轻松生成一张。
**import cartopy.crs as ccrs
import matplotlib.pyplot as pltda = DS.t_sfc# Draw coastlines of the Earth
ax = plt.axes(projection=ccrs.PlateCarree())
ax.coastlines()
da.plot()
plt.show()**
通过几行额外的代码,您可以生成如下内容:
Plots generated by cartopy
数据导出
如前所述,您可以将 DataArray 转换为numpy.ndarray
,或者将 DataSet 或 DataArray 转换为pandas.DataFrame
,如下图所示。
**df = DS.to_dataframe()**
还可以通过以下方式将 DataArray 或 DataSet 导出到 NetCDF 文件
**dataDIR = '../data/new.nc'
DS.to_netcdf(dataDIR)**
评论
如果您对 Python 或编程感兴趣,以下文章可能会有所帮助:
** [## 我希望我能早点知道的 5 个 Python 特性
超越 lambda、map 和 filter 的 Python 技巧
towardsdatascience.com](/5-python-features-i-wish-i-had-known-earlier-bc16e4a13bf4) [## 使用交互式地图和动画可视化伦敦的自行车移动性
探索 Python 中的数据可视化工具
towardsdatascience.com](/visualizing-bike-mobility-in-london-using-interactive-maps-for-absolute-beginners-3b9f55ccb59)
本教程是为教学目的而写的,只包括xarray
的基础知识。希望这有所帮助!
原载于我的博客edenau . github . io。
参考
- https://www . unidata . ucar . edu/software/netcdf/netcdf-4/new docs/netcdf/NC dump . html
- http://xarray.pydata.org/en/stable/
- https://scitools . org . uk/cartopy/docs/v 0.15/matplotlib/intro . html
- http://earthpy.org/cartopy_backgroung.html**
处理深度学习模型中的过拟合
原文:https://towardsdatascience.com/handling-overfitting-in-deep-learning-models-c760ee047c6e?source=collection_archive---------2-----------------------
当您在训练数据上实现了模型的良好拟合,而在新的、看不见的数据上没有很好地概括时,就会发生过度拟合。换句话说,模型学习了特定于训练数据的模式,而这些模式在其他数据中是不相关的。
我们可以通过查看验证指标(如损失或准确性)来识别过度拟合。通常,验证度量在一定数量的时期后停止提高,之后开始下降。训练指标不断改进,因为模型试图找到最适合训练数据的方法。
有几种方式可以减少深度学习模型中的过度拟合。最好的选择是 获取更多的训练数据 。不幸的是,在现实世界中,由于时间、预算或技术限制,您通常没有这种可能性。
另一种减少过拟合的方法是 降低模型记忆训练数据的容量 。因此,模型将需要关注训练数据中的相关模式,这将导致更好的泛化。在本帖中,我们将讨论实现这一目标的三个选项。
项目的建立
我们首先导入必要的包并配置一些参数。我们将使用 Keras 来拟合深度学习模型。训练数据是来自 Kaggle 的 Twitter 美国航空公司情绪数据集。
# Basic packages
import pandas as pd
import numpy as np
import re
import collections
import matplotlib.pyplot as plt
from pathlib import Path# Packages for data preparation
from sklearn.model_selection import train_test_split
from nltk.corpus import stopwords
from keras.preprocessing.text import Tokenizer
from keras.utils.np_utils import to_categorical
from sklearn.preprocessing import LabelEncoder# Packages for modeling
from keras import models
from keras import layers
from keras import regularizersNB_WORDS = 10000 # Parameter indicating the number of words we'll put in the dictionary
NB_START_EPOCHS = 20 # Number of epochs we usually start to train with
BATCH_SIZE = 512 # Size of the batches used in the mini-batch gradient descent
MAX_LEN = 20 # Maximum number of words in a sequenceroot = Path('../')
input_path = root / 'input/'
ouput_path = root / 'output/'
source_path = root / 'source/'
一些助手功能
在本文中,我们将使用一些助手函数。
def deep_model(model, X_train, y_train, X_valid, y_valid):
'''
Function to train a multi-class model. The number of epochs and
batch_size are set by the constants at the top of the
notebook.
Parameters:
model : model with the chosen architecture
X_train : training features
y_train : training target
X_valid : validation features
Y_valid : validation target
Output:
model training history
'''
model.compile(optimizer='rmsprop'
, loss='categorical_crossentropy'
, metrics=['accuracy'])
history = model.fit(X_train
, y_train
, epochs=NB_START_EPOCHS
, batch_size=BATCH_SIZE
, validation_data=(X_valid, y_valid)
, verbose=0)
return history def eval_metric(model, history, metric_name):
'''
Function to evaluate a trained model on a chosen metric.
Training and validation metric are plotted in a
line chart for each epoch.
Parameters:
history : model training history
metric_name : loss or accuracy
Output:
line chart with epochs of x-axis and metric on
y-axis
'''
metric = history.history[metric_name]
val_metric = history.history['val_' + metric_name] e = range(1, NB_START_EPOCHS + 1) plt.plot(e, metric, 'bo', label='Train ' + metric_name)
plt.plot(e, val_metric, 'b', label='Validation ' + metric_name)
plt.xlabel('Epoch number')
plt.ylabel(metric_name)
plt.title('Comparing training and validation ' + metric_name + ' for ' + model.name)
plt.legend()
plt.show()def test_model(model, X_train, y_train, X_test, y_test, epoch_stop):
'''
Function to test the model on new data after training it
on the full training data with the optimal number of epochs.
Parameters:
model : trained model
X_train : training features
y_train : training target
X_test : test features
y_test : test target
epochs : optimal number of epochs
Output:
test accuracy and test loss
'''
model.fit(X_train
, y_train
, epochs=epoch_stop
, batch_size=BATCH_SIZE
, verbose=0)
results = model.evaluate(X_test, y_test)
print()
print('Test accuracy: {0:.2f}%'.format(results[1]*100))
return results def remove_stopwords(input_text):
'''
Function to remove English stopwords from a Pandas Series.
Parameters:
input_text : text to clean
Output:
cleaned Pandas Series
'''
stopwords_list = stopwords.words('english')
# Some words which might indicate a certain sentiment are kept via a whitelist
whitelist = ["n't", "not", "no"]
words = input_text.split()
clean_words = [word for word in words if (word not in stopwords_list or word in whitelist) and len(word) > 1]
return " ".join(clean_words)
def remove_mentions(input_text):
'''
Function to remove mentions, preceded by @, in a Pandas Series
Parameters:
input_text : text to clean
Output:
cleaned Pandas Series
'''
return re.sub(r'@\w+', '', input_text) def compare_models_by_metric(model_1, model_2, model_hist_1, model_hist_2, metric):
'''
Function to compare a metric between two models
Parameters:
model_hist_1 : training history of model 1
model_hist_2 : training history of model 2
metrix : metric to compare, loss, acc, val_loss or val_acc
Output:
plot of metrics of both models
'''
metric_model_1 = model_hist_1.history[metric]
metric_model_2 = model_hist_2.history[metric] e = range(1, NB_START_EPOCHS + 1)
metrics_dict = {
'acc' : 'Training Accuracy',
'loss' : 'Training Loss',
'val_acc' : 'Validation accuracy',
'val_loss' : 'Validation loss'
}
metric_label = metrics_dict[metric] plt.plot(e, metric_model_1, 'bo', label=model_1.name)
plt.plot(e, metric_model_2, 'b', label=model_2.name)
plt.xlabel('Epoch number')
plt.ylabel(metric_label)
plt.title('Comparing ' + metric_label + ' between models')
plt.legend()
plt.show()
def optimal_epoch(model_hist):
'''
Function to return the epoch number where the validation loss is
at its minimum
Parameters:
model_hist : training history of model Output:
epoch number with minimum validation loss
'''
min_epoch = np.argmin(model_hist.history['val_loss']) + 1
print("Minimum validation loss reached in epoch {}".format(min_epoch))
return min_epoch
数据准备
数据清理
我们用 tweets 加载 CSV 并执行随机洗牌。在分割训练集和测试集之前,对数据进行洗牌是一个很好的做法。这样,情感类别在训练集和测试集中平均分布。我们只将 文本 列作为输入,将 航空公司 _ 情绪 列作为目标。
接下来我们要做的是 去除停用词 。停用词对于预测情绪没有任何价值。此外,由于我们希望建立一个同样适用于其他航空公司的模型,我们 删除了提到的 。
df = pd.read_csv(input_path / 'Tweets.csv')
df = df.reindex(np.random.permutation(df.index))
df = df[['text', 'airline_sentiment']]
df.text = df.text.apply(remove_stopwords).apply(remove_mentions)
列车测试分离
模型性能的评估需要在单独的测试集上完成。因此,我们可以估计模型的概括程度。这是通过 scikit-learn 的train _ test _ split方法完成的。
X_train, X_test, y_train, y_test = train_test_split(df.text, df.airline_sentiment, test_size=0.1, random_state=37)
将单词转换成数字
要使用文本作为模型的输入,我们首先需要将单词转换成记号,这仅仅意味着将单词转换成引用字典中索引的整数。这里我们将只保留训练集中最常用的单词。
我们通过应用 滤镜 将文字整理成 小写 。单词由空格分隔。
tk = Tokenizer(num_words=NB_WORDS,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{"}~\t\n',
lower=True,
char_level=False,
split=' ')
tk.fit_on_texts(X_train)
创建字典后,我们可以将 tweet 的文本转换为带有 NB_WORDS 值的向量。用 mode=binary 表示,它包含了一个指示词是否出现在推文中。这是通过记号赋予器的texts _ to _ matrix方法完成的。
X_train_oh = tk.texts_to_matrix(X_train, mode='binary')
X_test_oh = tk.texts_to_matrix(X_test, mode='binary')
将目标类转换为数字
我们还需要将目标类转换成数字,然后用 Keras 中的to _ categorial方法对数字进行一次性编码
le = LabelEncoder()
y_train_le = le.fit_transform(y_train)
y_test_le = le.transform(y_test)
y_train_oh = to_categorical(y_train_le)
y_test_oh = to_categorical(y_test_le)
分离验证集
现在我们的数据已经准备好了,我们分离出一个验证集。当我们调整模型的参数时,这个验证集将用于评估模型的性能。
X_train_rest, X_valid, y_train_rest, y_valid = train_test_split(X_train_oh, y_train_oh, test_size=0.1, random_state=37)
深度学习
创建一个过度拟合的模型
我们从一个过度拟合的模型开始。它有两层紧密相连的 64 个元素。第一层的 input_shape 等于我们保存在字典中的单词数,我们为其创建了一个热编码特征。
因为我们需要预测 3 个不同的情感类别,所以最后一层有 3 个元素。 softmax 激活功能确保三个概率总和为 1。
要训练的参数数量计算为 (nb 输入 x 隐藏层中的 nb 元素)+ nb 偏差项 。第一层的输入数量等于我们语料库中的单词数量。后续层将前一层的输出数量作为输入。因此每层的参数数量为:
- 第一层:(10000 x 64) + 64 = 640064
- 第二层:(64 x 64) + 64 = 4160
- 最后一层:(64 x 3) + 3 = 195
base_model = models.Sequential()
base_model.add(layers.Dense(64, activation='relu', input_shape=(NB_WORDS,)))
base_model.add(layers.Dense(64, activation='relu'))
base_model.add(layers.Dense(3, activation='softmax'))
base_model.name = 'Baseline model'
因为这个项目是多类单标签预测,所以我们用categorial _ cross entropy作为损失函数,用 softmax 作为最终激活函数。我们在训练数据上拟合模型,并在验证集上验证。我们运行预定数量的历元,并观察模型何时开始过度拟合。
base_history = deep_model(base_model, X_train_rest, y_train_rest, X_valid, y_valid)
base_min = optimal_epoch(base_history)eval_metric(base_model, base_history, 'loss')
开始时, 验证损失 下降。但是在时期 3,这停止并且验证损失开始快速增加。这是模型开始过度拟合的时候。
训练损耗 继续下降,在纪元 20 几乎归零。这是正常的,因为模型被训练为尽可能好地拟合训练数据。
处理过拟合
现在,我们可以试着做一些关于过度拟合的事情。有不同的方法可以做到这一点。
- 通过移除图层或减少隐藏图层中的元素数量来减少网络容量
- 应用 正则化 ,这归结于为大权重的损失函数增加了一个成本
- 使用 脱落层 ,将某些特征设置为零,随机删除
降低网络容量
我们的第一个模型有大量可训练的参数。这个数字越高,模型就越容易记住每个训练样本的目标类。显然,这对于新数据的推广并不理想。
通过降低网络容量,您迫使它学习重要的模式或将损失降至最低。另一方面,过多地减少网络的容量会导致 配不上 。该模型将无法学习列车数据中的相关模式。
我们通过移除一个隐藏层并将剩余层中的元素数量减少到 16 个来减少网络容量。
reduced_model = models.Sequential()
reduced_model.add(layers.Dense(16, activation='relu', input_shape=(NB_WORDS,)))
reduced_model.add(layers.Dense(3, activation='softmax'))
reduced_model.name = 'Reduced model'reduced_history = deep_model(reduced_model, X_train_rest, y_train_rest, X_valid, y_valid)
reduced_min = optimal_epoch(reduced_history)eval_metric(reduced_model, reduced_history, 'loss')
我们可以看到,在简化模型开始过度拟合之前,需要更多的时期。验证损失也比我们的第一个模型上升得慢。
compare_models_by_metric(base_model, reduced_model, base_history, reduced_history, 'val_loss')
当我们比较基线模型的验证损失时,很明显,简化模型在以后开始过度拟合。验证损失低于基线模型的时间要长得多。
应用正则化
为了解决过拟合问题,我们可以对模型应用权重正则化。对于较大的权重(或参数值),这将增加网络损耗函数的成本。因此,您会得到一个更简单的模型,它将被迫只学习列车数据中的相关模式。
有 L1 正则化和L2 正则化。
- L1 正则化将会增加一个关于 参数的绝对值 的费用。这将导致一些权重等于零。
- L2 正则化将增加参数 的 平方值的成本。这将导致较小的重量。
让我们试试 L2 正则化。
reg_model = models.Sequential()
reg_model.add(layers.Dense(64, kernel_regularizer=regularizers.l2(0.001), activation='relu', input_shape=(NB_WORDS,)))
reg_model.add(layers.Dense(64, kernel_regularizer=regularizers.l2(0.001), activation='relu'))
reg_model.add(layers.Dense(3, activation='softmax'))
reg_model.name = 'L2 Regularization model'reg_history = deep_model(reg_model, X_train_rest, y_train_rest, X_valid, y_valid)
reg_min = optimal_epoch(reg_history)
对于正则化模型,我们注意到它在与基线模型相同的时期开始过拟合。然而,随后的损失增加速度要慢得多。
eval_metric(reg_model, reg_history, 'loss')
compare_models_by_metric(base_model, reg_model, base_history, reg_history, 'val_loss')
添加脱落层
我们尝试的最后一个选项是添加脱落层。脱落图层会将图层的输出要素随机设置为零。
drop_model = models.Sequential()
drop_model.add(layers.Dense(64, activation='relu', input_shape=(NB_WORDS,)))
drop_model.add(layers.Dropout(0.5))
drop_model.add(layers.Dense(64, activation='relu'))
drop_model.add(layers.Dropout(0.5))
drop_model.add(layers.Dense(3, activation='softmax'))
drop_model.name = 'Dropout layers model'drop_history = deep_model(drop_model, X_train_rest, y_train_rest, X_valid, y_valid)
drop_min = optimal_epoch(drop_history)eval_metric(drop_model, drop_history, 'loss')
具有脱落层的模型比基线模型晚开始过度拟合。损耗的增加也比基线模型慢。
compare_models_by_metric(base_model, drop_model, base_history, drop_history, 'val_loss')
具有脱落层的模型稍后开始过度拟合。与基线模型相比,损耗也保持低得多。
全训练数据的训练和测试数据的评估
乍一看,简化的模型似乎是最好的泛化模型。但是让我们在测试集上检查一下。
base_results = test_model(base_model, X_train_oh, y_train_oh, X_test_oh, y_test_oh, base_min)
reduced_results = test_model(reduced_model, X_train_oh, y_train_oh, X_test_oh, y_test_oh, reduced_min)
reg_results = test_model(reg_model, X_train_oh, y_train_oh, X_test_oh, y_test_oh, reg_min)
drop_results = test_model(drop_model, X_train_oh, y_train_oh, X_test_oh, y_test_oh, drop_min)
结论
如上所示,所有三个选项都有助于减少过度拟合。我们设法大幅提高测试数据的准确性。在这三个选项中,具有脱落层的模型在测试数据上表现最好。
你可以在 GitHub 上找到笔记本。好好享受吧!欢迎任何反馈。
处理稀疏矩阵——压缩稀疏行(CSR)矩阵背后的概念
原文:https://towardsdatascience.com/handling-sparse-matrix-concept-behind-compressed-sparse-row-csr-matrix-4fe6abe58a7a?source=collection_archive---------3-----------------------
Source: https://www.loginworks.com/web-scraping-blogs/text-mining/
有两种常见的矩阵——密集矩阵和稀疏矩阵
稀疏矩阵的大部分元素为零,而密集矩阵的大部分元素不为零。对于大矩阵,通常大部分元素为零。因此,只使用非零值来执行运算是有意义的,因为零乘以任何值都将始终等于零。
Source: https://www.coin-or.org/Ipopt/documentation/node38.html
Scipy 提供了各种只存储非零元素的稀疏矩阵函数。通过这样做,可以最小化数据存储所需的存储器。机器学习过程通常需要数据帧在内存中。它分解数据帧以适合 RAM。通过压缩,数据可以很容易地放入 RAM。仅使用稀疏矩阵的非零值来执行操作可以大大提高算法的执行速度。
压缩稀疏行(CSR)算法是 Scipy 提供的类型之一。下面是它的工作原理。
样本文本文档
短句
这不是一个短句
没有下雨。是吗?
第一步——步进
给单词编号。如果单词重复,分配相同的数字。通过这一步,我们知道整个文档中有多少单词。
索引从 0 开始。第一个单词是“short ”,它被索引为“0 ”,同样,每个唯一单词都将被索引。单词“Short”出现两次,因此它每次在文档中出现时都获得相同的索引值“0”。
步骤 2——文档的矢量表示
对于文档中的每一行,创建向量表示。计算唯一索引的数量。在这种情况下,我们有从 0 到 7 的 8 个索引,因此每个文档(行)使用 8 个值来表示,每个值表示对应于该索引的特定单词出现的次数。
(索引,单词)——(0,短,(1,句子),(2,这个,(3,是),(4,不是),(5,a),(6,它),(7,下雨)
01234567
[11000000]
[11111100]
[00021021]
这里,第一个向量的第一个位置中的值 1 表示索引为“0”的单词在文档中出现 1 次。第三个向量的第四个位置的值 2 表示索引为“3”的单词在该文档中出现了两次。
步骤 3——为每个文档创建稀疏向量
下面是每个文档的稀疏矩阵表示。它删除所有零值,只存储非零值。
文档 1: <0 1, 1 1>
第一个文档只在前两个位置有值,所以只表示它们。(0 1)表示第 0 个位置的值为 1,而(1 1)表示第 1 个位置的值为 1。在<0 1, 1 1>的(0-1)中,0 对应于索引,而 1 对应于特定索引在文档中出现的次数(值)
文件 2: <0 1, 1 1, 2 1, 3 1, 4 1, 5 1>
文件 3: < 3 2, 4 1, 6 2, 7 1>
CSR 矩阵表示需要三个数组——索引、值和指针。
索引
Ind — [0,1,0,1,2,3,4,5,3,4,6,7]
从上述步骤中获得的每个文档的索引被合并为一个。索引的大小是文档中非零值的个数。
值
瓦尔-[1,1,1,1,1,1,1,1,2,1,2,1]
值数组包含与从每个文档中获得的每个索引相对应的值。索引的大小是文档中非零值的个数。
指针
现在,我们已经组合了文档中所有行的索引和值。指针有助于在索引和值数组中标识完整文本文档中每个文档(行)的开头和结尾。
ptr -[0,2,8,12]
0 表示文档 1(行 1)的开始,它在开始后两个位置结束。从第三个位置开始,文档 2(行 2)开始并在第八个位置结束。从第 9 个位置开始,文档 3(第 3 行)开始并在第 12 个位置结束。这适用于索引数组和值数组。指针有助于理解索引和值数组。给定一个索引和指针数组,就可以知道每个文档的开始和结束。
传递这些数组将给出 CSR 矩阵,这就是 scipy 中 csr_matrix 函数的工作方式。
代码
来自 scipy.sparse import *
来自 scipy import *
ind = [0,1,0,1,2,3,4,5,3,4,6,7]
val = [1,1,1,1,1,1,1,1,2,1,2,1]
ptr = [0,2,8,12]
csr_matrix( (val,ind,ptr))
输出:< 3x8 sparse matrix of type ‘
具有压缩稀疏行格式的 12 个存储元素>
处理文本文档时,CSR 矩阵就是这样创建的。
……未完待续
灵感来自我的数据挖掘课。
放手键盘战士:有毒评论的文本挖掘
原文:https://towardsdatascience.com/hands-off-keyboard-warrior-text-mining-with-toxic-comments-6603ee3bc12e?source=collection_archive---------15-----------------------
从整齐的文本数据到 R 模型拟合的 NLP 初学者终极指南
通过互联网与人交流和接触是很神奇的。我们可以听到一些人的想法,如果没有这些想法,他们永远也不可能见面。可能是住在地球对面的人,或者是我们永远没有机会聊天的人。我们甚至可以和他们成为朋友,这就是为什么我们在这个年龄说“超级联系”。
然而,也有很多勇士威胁着这个令人敬畏的空间。键盘战士。他们没有基本的礼节,只是躲在他们的显示器后面,抛出他们的仇恨言论。这种评论不仅伤害了他人的感情,也破坏了网上交流的可能性。我们不能用数据科学来解决这个问题吗?我们能不能用机器学习建立一个有毒评论的检测器,让在线交流更健康?
今天我带来了另一个检测有毒评论的 NLP 项目。这是一项最初在卡格尔举行的比赛。我们面临的挑战是建立一个能够检测评论毒性的多头模型。有 6 种不同类型的毒性,即毒性、严重毒性、淫秽、威胁、侮辱和基于身份的仇恨。我来解释一下 NLP 的基本步骤。你可以从 Kaggle 下载数据集,完整代码可以在我的 Github 上找到。
加载数据集
我们先来看看数据集。我们有comment_text
栏和 6 种不同类型的毒性。
# Reading the dataset
train = read_csv('train.csv')
test = read_csv('test.csv')
这 6 个变量是我们的目标变量,有一个二进制值。拟合模型来一次预测 6 个变量将是这个项目的一个有趣的部分,你可以在这篇文章的结尾查看。在进入模型拟合之前,让我们先做一些挖掘comment_text
。
整理文本数据
为了处理文本变量,我将把它们标记成整齐的文本格式。但什么是记号化或记号化呢?
标记是一个有意义的文本单元,比如一个单词,我们有兴趣用于分析,而标记化是将文本拆分成标记的过程。
在大多数的自然语言处理工作中,我们基本上是在一个单词单元中处理文本数据。如果你需要一个 unigram 或 one-hot-encoding 的基本概念,请查看我之前的文章。
# Tokenize the comment_text column
tr_token = train %>%
unnest_tokens(output = word, input = comment_text) %>%
anti_join(stop_words, by = 'word')
函数unnest_tokens()
将文本变量分割成单个单词,并以每行一个标记的结构返回它们。这是处理文本数据的一种更简单的方式。记号不一定总是一个单词。它们可以是一个 N-gram,一个句子,甚至一个段落,这取决于你的目的。我个人很喜欢这个功能,因为它感觉就像我在开始烹饪之前切完所有的蔬菜和肉类一样。
因此,在对文本数据进行标记后,我们得到了如上所示的数据帧。我们来统计一下每个词的出现频率,并把它们形象化。
# Count frequency of each word
freq_n = tr_token %>%
group_by(word) %>%
count() %>%
arrange(-n)# words frequency bar plot
freq_n[1:15, ] %>%
ggplot(aes(x = reorder(word, n), y = n)) +
geom_col(fill = 'lightseagreen') +
geom_text(aes(x = word, y = 1, label = paste0('(', n, ')')),
hjust = 0, vjust = .3, fontface = 'bold', size = 4) +
coord_flip() +
labs(x = NULL, y = NULL, title = 'Top 15 most Frequent Words') +
theme_bw()
文章、页面、维基百科、talk、 和 来源 是评论中使用频率最高的。那大概是因为我们通常会留下评论新闻 文章 或观点 章节 和 谈论 关于我们的想法或附加 信息 来自其他 来源 。
术语频率-逆文档频率
的确,这些词是最常见的术语。但是对于我们的分析来说,很难说它们是“重要”的词。有时出现频率很高的词可能是不太重要的词,比如停用词。想想我们有 20 条评论,一个单词,比如“states”,出现在所有的评论中。或者‘医疗’这个词只出现在 3 条评论里怎么办?哪个更重要?这就是 TF-IDF 的由来。
统计数据 tf-idf 旨在衡量一个单词对文档集合(或语料库)中的文档有多重要,例如,对小说集合中的一部小说或网站集合中的一个网站。
词频 (tf)就和我们上面统计的一样。一个单词在文档中出现的频率(在这种情况下是一个注释)。逆文档频率 (idf)是包含该单词的文档数量的倒数。所以我们通过将这两个概念相乘来赋予这个词权重。你不必害怕数学,因为bind_tf_idf()
会为你计算所有这些。
那么数据集中有多少文档呢?因为有 6 种不同类型的毒性,并且我们要检查每种毒性的重要单词,所以我们有 41 种不同的毒性组合。这意味着有 41 个不同的文档。
tr_token_n = tr_token %>%
group_by(toxic, severe_toxic, obscene, threat, insult, identity_hate) %>%
count()head(tr_token_n)
# -> 41 different combinations of ‘toxic comment’ documents
tr_token_n$document = 1:41tr_tfidf = tr_token %>%
left_join(tr_token_n) %>%
bind_tf_idf(term = word, document = document, n = n) %>%
arrange(desc(tf_idf))
有了tf
、idf
和tf_idf
,我们现在可以得到真正重要的单词了。让我们在柱状图中标出重要的“有毒”单词。结果将与我们上面看到的大不相同。
# toxic important word
tr_tfidf %>%
filter(toxic == 1) %>%
top_n(20) %>%
ggplot(aes(x = reorder(word, tf_idf), y = tf_idf)) +
geom_col(fill = 'coral2') +
coord_flip() +
theme_bw() +
labs(x = NULL, y = 'TF_IDF', title = 'Top 20 Important \"Toxic\" Words')
让我们回顾一下到目前为止我们所讨论的内容。对于文本数据,我们用unnest_tokens()
对它们进行标记,使它们成为整齐的格式,并以可视化的方式统计单词的频率。
语料库和文档术语矩阵
为了建立机器学习,我们必须将数据转换成 dtm。什么是 dtm?它只是一个简单的矩阵。但是我们在前面附加了‘文档-术语’,以指定它在行中包含文档,在列中包含术语(所以文档-术语矩阵)。tdm 则相反。它的行中有术语,列中有文档。看你选择用 dtm 还是 tdm。
所以从现在开始,我们将把整个数据集转换成 dtm 并拟合一个模型。你注意到了吗,到目前为止我们一直在用训练集工作?测试集从未被接触过。因此,我将对整个数据集进行标记,但这一次是以不同的方式。还有一种方法可以处理文本数据,那就是通过tm
包把它们做成语料库。
# combining train and test dataset
full = rbind(train, test)
target = full[, 3:8]
part = 1:nrow(train)# transforming comment_text into corpus
corpus = full$comment_text %>%
str_trim() %>%
tolower() %>%
VectorSource() %>%
VCorpus()corpus = tm_map(corpus, removePunctuation)
corpus = tm_map(corpus, stripWhitespace)
corpus = tm_map(corpus, removeNumbers)
corpus = tm_map(corpus, removeWords, stopwords('en'))
corpus = tm_map(corpus, stemDocument)# casting into dtm and data frame
term_dtm = DocumentTermMatrix(corpus)
term_m = removeSparseTerms(term_dtm, sparse = 0.97) %>% as.matrix()
经过降低大写字母、删除标点、空格、数字和单词等几个步骤的处理,我得到了数据框。它看起来怎么样?
每行对应于id
,所有列变量都是单词或术语(记住文档-术语矩阵!).大部分都填了 0。它看起来像有很多洞的瑞士奶酪。由于这个漏洞,我们通常通过removeSparseTerms()
来降低稀疏度,以缩减数据。
拟合模型
终于到了建模的时候了!我将使用 glmnet 来拟合模型。我们有 6 个需要预测的目标变量。是不是意味着我们要一个一个的造 6 个模型?绝对不行。我们可以简单地使用 for 循环,迭代相同的算法 6 次,如下所示。
tr_x = term_m[part, ]
tr_y = target[part, ]te_x = term_m[-part, ]
te_y = target[-part, ]pred_glmnet = tibble()
for(x in names(target)){
y = tr_y[[x]]
model_glmnet = cv.glmnet(x = tr_x, y = factor(y),
family = 'binomial',
type.measure = 'auc',
nfolds = 5,
alpha = 0)
pred = predict(model_glmnet, newx = te_x,
s = 'lambda.min', type = 'response')
pred = ifelse(pred < .5, 0, 1)
pred_glmnet[, x] = pred
}
摘要
哇!我们今天经历了很多事情。让我们用一个更大的图表再回顾一遍。
我们首先遵循图片中间的步骤。然后我们在底部也尝试了不同的步骤。利用tm
软件包,我们制作了语料库,将其转换成 dtm 并拟合出模型。
我们最终让检测器能够对仇恨者的评论进行分类。厉害!对我来说,数据科学最大的乐趣就是帮助解决问题,让世界变得更美好。你也可以使用情感分析或主题建模,获得更复杂的模型。如果你想深入文本挖掘的世界,这里的是很好的教程。如果你不喜欢用课本学习,你也可以从 Datacamp 获得这个在线课程。
参考
- 用 R:https://www.tidytextmining.com/进行文本挖掘
- 维基百科:【https://en.wikipedia.org/wiki/Tf–idf
感谢您的阅读,希望这篇文章对您有所帮助。如果你想鼓励一个有抱负的数据科学家,请给一个或两个或三个掌声!我会很感激任何反馈,所以请在下面分享你的想法,或者在 LinkedIn 上联系我。我会回来讲另一个有趣的故事。在那之前,机器学习快乐:-)
Apache Beam 实践,用 Python 构建数据管道
原文:https://towardsdatascience.com/hands-on-apache-beam-building-data-pipelines-in-python-6548898b66a5?source=collection_archive---------3-----------------------
Apache Beam 是一个开源 SDK,它允许您从基于批处理或流的集成中构建多个数据管道,并以直接或分布式的方式运行它。您可以在每个管道中添加各种转换。但是 Beam 的真正强大之处在于它不基于特定的计算引擎,因此是平台无关的。您声明您想要使用哪个“跑步者”来计算您的变换。默认情况下,它使用您的本地计算资源,但是您可以指定一个 Spark 引擎或云数据流…
在本文中,我将创建一个接收 csv 文件的管道,计算历史 S&P500 数据集的打开和关闭列的平均值。这里的目标不是给出一个关于 Beam 特性的详细教程,而是给你一个总体的概念,告诉你可以用它做什么,以及它是否值得你更深入地使用 Beam 构建定制管道。虽然我只写批处理,但是流管道是 Beam 的一个强大特性!
Beam 的 SDK 可以用于各种语言,Java,Python…但是在本文中我将重点介绍 Python。
装置
在本文发表时,Apache Beam (2.8.1)只与 Python 2.7 兼容,但是 Python 3 版本应该很快就会推出。如果你安装了 python-snappy,Beam 可能会崩溃。这个问题是已知的,将在 Beam 2.9 中修复。
pip install apache-beam
创建接收 CSV 的基本管道
数据
在本例中,我们将使用包含标准普尔 500 历史值的 csv。数据看起来是这样的:
Date,Open,High,Low,Close,Volume
03–01–00,1469.25,1478,1438.359985,1455.219971,931800000
04–01–00,1455.219971,1455.219971,1397.430054,1399.420044,1009000000
基本管道
要创建管道,我们需要实例化管道对象,最终传递一些选项,并声明管道的步骤/转换。
import apache_beam as beam
from apache_beam.options.pipeline_options import PipelineOptionsoptions = PipelineOptions()
p = beam.Pipeline(options=options)
根据梁文档:
使用管道选项来配置管道的不同方面,例如将执行管道的管道流道,以及所选流道所需的任何特定于流道的配置。您的管道选项可能包括诸如项目 ID 或文件存储位置等信息。
上面的 PipelineOptions()方法是一个命令行解析器,它将读取通过以下方式传递的任何标准选项:
--<option>=<value>
自定义选项
您还可以构建自己的自定义选项。在这个例子中,我为我的管道设置了一个输入和一个输出文件夹:
**class** **MyOptions**(PipelineOptions):@classmethod
**def** **_add_argparse_args**(cls, parser):
parser**.**add_argument('--input',
help**=**'Input for the pipeline',
default**=**'./data/')
parser**.**add_argument('--output',
help**=**'Output for the pipeline',
default**=**'./output/')
转变原则
在 Beam 中,数据被表示为一个p 集合 对象。因此,为了开始接收数据,我们需要从 csv 中读取并将其存储为一个p 集合 ,然后我们可以对其应用转换。读取操作被视为一种转换,并遵循所有转换的语法:
[Output PCollection] **=** [Input PCollection] **|** [Transform]
这些转换可以像这样链接起来:
[Final Output PCollection] **=** ([Initial Input PCollection] **|** [First Transform] **|** [Second Transform] **|** [Third Transform])
该管道相当于一个应用方法。
输入和输出 p 集合以及每个中间 p 集合都被视为单独的数据容器。这允许对同一 PCollection 应用多个转换,因为初始 PCollection 是不可变的。例如:
[Output PCollection 1] **=** [Input PCollection] **|** [Transform 1]
[Output PCollection 2] **=** [Input PCollection] **|** [Transform 2]
读取输入数据和写入输出数据
因此,让我们首先使用提供的一个阅读器来阅读我们的 csv,不要忘记跳过标题行:
csv_lines = (p | ReadFromText(input_filename, skip_header_lines=1) | ...
在管道的另一端,我们希望输出一个文本文件。所以让我们使用标准编写器:
... **|** beam**.**io**.**WriteToText(output_filename)
转换
现在我们想对用 Reader 函数创建的 PCollection 应用一些转换。变换分别应用于 PCollection 的每个元素。
根据您选择的工作者,您的转换可以是分布式的。然后在每个节点上执行转换的实例。
运行在每个 worker 上的用户代码生成输出元素,这些元素最终被添加到转换生成的最终输出
*PCollection*
中。
Beam 有核心方法(ParDo,Combine ),允许应用自定义转换,但也有预写的转换,称为复合转换。在我们的例子中,我们将使用 ParDo 变换来应用我们自己的函数。
我们已经将 csv 读入到一个p 集合 中,所以让我们将其拆分,以便我们可以访问日期并关闭项目:
… beam.ParDo(Split()) …
并定义我们的 split 函数,这样我们只保留日期,然后关闭并将其作为 dictionnary 返回:
class Split(beam.DoFn):
def process(self, element):
Date,Open,High,Low,Close,Volume = element.split(“,”)
return [{
‘Open’: float(Open),
‘Close’: float(Close),
}]
现在我们有了需要的数据,我们可以使用一个标准组合器来计算整个 p 集合的平均值。
要做的第一件事是将数据表示为一个元组,这样我们就可以按键分组,然后将组合值与它所期望的相结合。为此,我们使用一个自定义函数“CollectOpen()”,它返回一个包含(1,<open_value>)的元组列表。</open_value>
class CollectOpen(beam.DoFn):
def process(self, element):
# Returns a list of tuples containing Date and Open value
result = [(1, element[‘Open’])]
return result
元组的第一个参数是固定的,因为我们想要计算整个数据集的平均值,但是您可以使它动态地只在由该键定义的子集上执行下一个转换。
GroupByKey 函数允许创建所有元素的 PCollection,对于这些元素,键(即元组的左侧)是相同的。
mean_open = (
csv_lines | beam.ParDo(CollectOpen()) |
"Grouping keys Open" >> beam.GroupByKey() |
"Calculating mean for Open" >> beam.CombineValues(
beam.combiners.MeanCombineFn()
)
)
当你给一个转换分配一个标签时,确保它是唯一的,否则 Beam 将抛出一个错误。
如果我们想链接所有东西,我们的最终管道可能是这样的:
csv_lines = (
p | beam.io.ReadFromText(input_filename) |
beam.ParDo(Split()) |
beam.ParDo(CollectOpen()) |
"Grouping keys Open" >> beam.GroupByKey() |
"Calculating mean" >> beam.CombineValues(
beam.combiners.MeanCombineFn()
) | beam**.**io**.**WriteToText(output_filename)
)
但是我们也可以用一种允许在 splitted PCollection 上添加未来变换的方式来编写它(例如像 close 的平均值):
csv_lines = (
p | beam.io.ReadFromText(input_filename) |
beam.ParDo(Split())
)mean_open = (
csv_lines | beam.ParDo(CollectOpen()) |
"Grouping keys Open" >> beam.GroupByKey() |
"Calculating mean for Open" >> beam.CombineValues(
beam.combiners.MeanCombineFn()
)
)output = (
mean_open | beam**.**io**.**WriteToText(output_filename)
)
同一 PCollection 上的多个转换
如果我想在 csv_lines PCollection 上添加另一个转换操作,我将获得第二个“转换的 PCollection”。Beam 以“分支”变换的形式很好地代表了它:
要应用不同的变换,我们需要:
csv_lines = (
p | beam.io.ReadFromText(input_filename) |
beam.ParDo(Split())
)mean_open = (
csv_lines | beam.ParDo(CollectOpen()) |
"Grouping keys Open" >> beam.GroupByKey() |
"Calculating mean for Open" >> beam.CombineValues(
beam.combiners.MeanCombineFn()
)
)mean_close = (
csv_lines | beam.ParDo(CollectClose()) |
"Grouping keys Close" >> beam.GroupByKey() |
"Calculating mean for Close" >> beam.CombineValues(
beam.combiners.MeanCombineFn()
)
)
但是现在我们有两个 PCollections: mean_open 和 mean_close,作为转换的结果。我们需要合并/连接这些结果,以获得一个可以用 writer 写入文件的集合。Beam 的CoGroupByKey
就是这么做的。我们的输出将如下所示:
output= (
{
‘Mean Open’: mean_open,
‘Mean Close’: mean_close
} |
apache_beam.CoGroupByKey() |
WriteToText(output_filename))
)
我们现在已经定义了端到端的管道。您可以使用我们之前定义的自定义参数通过命令行运行它:
python test_beam.py **--**input ./data/sp500.csv **--**output ./output/result.txt
文件中的最终结果如下所示:
(1, {‘Mean Close’: [1482.764536822227], ‘Mean Open’: [1482.5682959997862]})
光束读取器和写入器
在这个例子中,我们只使用了 csv 阅读器和文本编写器,但是 Beam 有更多的连接器(不幸的是,大多数连接器都适用于 Java 平台,但是还有一些 Python 连接器正在开发中)。您可以在以下位置找到可用连接器的列表及其文档:
[## 内置 I/O 转换
Apache Beam 是一个开源、统一的模型和一组特定于语言的 SDK,用于定义和执行数据…
beam.apache.org](https://beam.apache.org/documentation/io/built-in/)
如果你足够勇敢,你也可以找到一个指南来编写你自己的连接器:
[## 创作 I/O 转换-概述
Apache Beam 是一个开源、统一的模型和一组特定于语言的 SDK,用于定义和执行数据…
beam.apache.org](https://beam.apache.org/documentation/io/authoring-overview/)
创建数据管道时的一般逻辑
每当需要实现数据管道时,我们都希望清楚管道/转换的需求和最终目标。在 Beam 文档中,我找到了这个小摘录,我认为它是开始用 Beam 构建管道时应该如何推理的核心:
你输入的数据储存在哪里?你有几组输入数据?这将决定您需要在管道的开始应用哪种类型的
Read
转换。您的数据是什么样的?它可能是明文、格式化的日志文件或数据库表中的行。一些波束转换专门作用于键/值对的
PCollection
;您需要确定您的数据是否以及如何被键控,以及如何在您的管道的PCollection
中最好地表示它。您希望如何处理您的数据?Beam SDK 中的核心转换是通用的。了解您需要如何更改或操作您的数据将决定您如何构建核心转换,如 ParDo ,或者您何时使用 Beam SDKs 中包含的预先编写的转换。
你的输出数据是什么样的,应该放在哪里?这将决定你需要在你的管道末端应用什么类型的
Write
转换。
使用分布式转轮
如前所述,您可以使用 Spark 之类的分布式计算引擎,而不是使用本地计算能力(DirectRunner)。您可以通过为管道选项设置以下选项来实现这一点(在命令行参数或选项列表中):
--runner SparkRunner --sparkMaster spark://host:port
更多选项可用这里,但这两个是基本的。
结论
在编写定制转换时,Beam 是非常低级的,它提供了用户可能需要的灵活性。它速度很快,可以处理云/分布式环境。如果你看一个更高级的 API/SDK,一些像 tf.transform 这样的库实际上是建立在 Beam 之上的,在编码更少的情况下为你提供强大的功能。权衡在于您所寻求的灵活性。
这篇文章的代码可以在 GitHub 这里找到。
我希望你喜欢这篇文章。如果你看到了,欢迎鼓掌或关注我:)
Tensorflow 数据验证实践
原文:https://towardsdatascience.com/hands-on-tensorflow-data-validation-61e552f123d7?source=collection_archive---------4-----------------------
谷歌刚刚发布了他们的端到端大数据平台新产品 TFDV!数据科学中的一大难题是处理数据质量问题,即数据验证。让我们看看 google 是如何发布第一个版本的,以及这个新库有多有用。
1.装置
通过 pip 进行相当标准的安装过程,但是要确保你已经预先安装了一些依赖项,以确保它编译没有问题。就我而言,在 Ubuntu 16.04 上,我缺少 python-dev 和 python-snappy 来获得更快的性能。如果你开始使用 TFX 图书馆,Bazel 也是不错的选择。
sudo apt-get install python-dev python-snappy
pip install tensorflow-data-validation
这个 TFDV 是一个相当新的库,文档非常漂亮…所以我强烈建议您克隆库,看看您使用的每个函数接受什么参数。
2.加载数据和生成统计数据:
这里没有火箭科学,我们首先导入库,数据集分析/验证的第一步是在数据集上生成统计数据。我将在这里加载一个 csv 并指定一个分隔符,但是您也可以加载一个 TFRecords。为方便起见,下面是两个函数定义头:
import tensorflow_data_validation as tfdv**def generate_statistics_from_csv(** data_location,
column_names = None,
delimiter = ‘,’,
output_path = None,
stats_options = stats_api.StatsOptions(),
pipeline_options = None,):...**def generate_statistics_from_tfrecord(** data_location,
output_path = None,
stats_options = stats_api.StatsOptions(),
pipeline_options = None,):
让我们加载并生成我们的统计数据:
BASE_DIR = os.getcwd()
DATA_DIR = os.path.join(BASE_DIR, 'data')
TRAIN_DATA = os.path.join(DATA_DIR, 'train.csv')train_stats = tfdv.generate_statistics_from_csv(TRAIN_DATA, delimiter=';')
首先要注意的是,该操作非常占用内存。我的数据集只有一个 86Mb 的 csv 文件,但是内存使用量增加了近 1Gb,所以请确保您有大量的可用内存!
3.可视化统计数据:
统计数据生成后,您有两个选项来实现它们。您可以使用Facets Overview,根据您的平台,安装起来可能会很棘手,或者您可以使用内置的 TFDV 可视化功能,它提供的信息与 Facets 完全相同:
tfdv.visualize_statistics(stats)
如果您有大量缺失数据、高标准偏差等,立即发现是非常有用的。然而,我真的很喜欢 Dive 模块的方面,它让你以一种非常直观的方式探索你的数据集是什么样子的。
到目前为止,没有什么革命性的…但是大事来了…
4.描述您的数据集以供将来验证
TFDV 的主要特征是“图式”的概念。这基本上是对您的数据的描述,因此您可以将此描述与新的数据进行匹配,并验证它们…或者不验证。
它描述了数据的标准特征,如列数据类型、数据的存在/缺失、预期的值范围。
您可以在被视为参考数据集的数据集上创建模式,并可以重用它来验证具有相同结构的其他数据集。
一个更有趣的特性是,您可以在 TFTransform 中重用这个模式来自动声明您的数据集结构。
这就是事情变得容易的地方…要做到这一点,只有一行代码就足够了:
schema = tfdv.infer_schema(train_stats)
然而,正如它看起来那样简单,Tensorflow 团队提出了一个警告:
通常,TFDV 使用保守的试探法从统计数据中推断稳定的数据属性,以避免模式过度适应特定的数据集。强烈建议检查推断出的模式,并根据需要对其进行提炼,以获取 TFDV 的启发式算法可能遗漏的任何有关数据的领域知识。
为了存储您的模式,TFDV 使用 protobuf 库,它正在成为操作静态数据(数据结构、转换方案、冻结模型……)的统一方法。
如果有一点我们可能都同意,那就是没有一个数据集是完美的。当涉及到验证您的数据时,领域知识是必不可少的,这就是为什么自动化工具是一种独角兽!为了考虑到这一点,TFDV 附带了帮助函数,所以您需要手动硬编码不应从数据集派生的规则。
每个特性都有一组你可以访问和修改的属性。例如,假设我们希望在至少 50%的示例中填充特性 f1,这是通过以下代码行实现的:
tfdv.get_feature(schema, 'f1').presence.min_fraction = 0.5
每个特征由以下部分组成:
特征名称,类型,存在性,化合价,域
然后每个组件得到它自己的子组件子集。我不会在这里列出它们,但我能给你的最好建议是解析模式 protobuf,你会发现类似这样的东西:
num_examples:1000000000000000
weighted_num_examples: 1000000000000000
features {
name: “one_in_a_quadrillion”
type:INT
num_stats: {
common_stats: {
num_missing: 1
num_non_missing: 1000000000000000
min_num_values: 1
max_num_values: 1
weighted_common_stats {
num_non_missing: 1000000000000000
num_missing: 1
}
}
min: 0.0
max: 10.0
}
您也可以像这样简单地在笔记本上显示它:
tfdv.display_schema(schema)
5.验证更新的数据
你的“完美的”训练集现在已经描述过了,但是你每天都在不断地获取新的数据到 ETL,并且寻找一种方法来验证新的训练集,这是 TFDV 的核心。使用前面描述的模式/域…它将解析您的新集合并报告异常值、缺失或错误的数据。
我认为教程中的图片很好地展示了一个好的管道数据验证链应该是什么样子:
当您试图为您的模型将数据摄取管道产品化时,这基本上是您试图实现的目标。
让我们获取一个新的 CSV 文件,加载它,生成统计数据,并使用之前生成的模式解析它以进行验证:
NEW_DATA = os.path.join(DATA_DIR, 'test.csv')new_csv_stats = tfdv.generate_statistics_from_csv(NEW_DATA, delimiter=';')
anomalies = tfdv.validate_statistics(statistics=new_csv_stats, schema=schema)
然后,您可以通过以下方式显示这些异常:
tfdv.display_anomalies(anomalies)
您将获得一个列表,其中包含以下一条或多条错误消息,这些消息描述了新数据集未满足的条件(已知模式中的预期条件):
Integer larger than 1
BYTES type when expected INT type
BYTES type when expected STRING type
FLOAT type when expected INT type
FLOAT type when expected STRING type
INT type when expected STRING type
Integer smaller than 1
STRING type when expected INT type
Expected a string, but not the string seen
BYTES type when expected STRING type
FLOAT type when expected STRING type
INT type when expected STRING type
Invalid UTF8 string observed
Unexpected string values
The number of values in a given example is too large
The fraction of examples containing a feature is too small
The number of examples containing a feature is too small
The number of values in a given example is too small
No examples contain the value
The feature is present as an empty list
The feature is repeated in an example, but was expected to be a singleton
There is a float value that is too high
The type is not FLOAT
There is a float value that is too low
The feature is supposed to be floats encoded as strings, but there is a string that is not a float
The feature is supposed to be floats encoded as strings, but it was some other type (INT, BYTES, FLOAT)
The type is completely unknown
There is an unexpectedly large integer
The type was supposed to be INT, but it was not.
The feature is supposed to be ints encoded as strings, but some string was not an int.
The type was supposed to be STRING, but it was not.
There is an unexpectedly small integer
The feature is supposed to be ints encoded as strings, but it was some other type (INT, BYTES, FLOAT)
Unknown type in stats proto
There are no stats for a column at all
There is a new column that is not in the schema.
Training serving skew issue
Expected STRING type, but it was FLOAT.
Expected STRING type, but it was INT.
Control data is missing (either training data or previous day).
Treatment data is missing (either scoring data or current day).
L infinity between treatment and control is high.
No examples in the span.
我不得不说我对这里的结果感到有点失望…我知道我们只是在谈论数据验证,但是指向一个错误而不返回包含这些错误的子集感觉有点像未完成的工作。我也知道这个功能是相当昂贵的,如果你从 Talend 或 Alooma 这样的包中获得年度许可,价格在 1 万到 8 万美元之间,你会得到一个很好的流来处理你的缺陷,但我相信 TF 迟早会走这条路!
在“异常长描述”一栏中,您还有一些更多的细节,因此您应该对您所拥有的内容的可解释性感到满意。
更好的是,如果您认为与模式的偏差是意料之中的,您可以很容易地修改原始模式:
tfdv.get_domain(schema, 'f2').value.append('new_unique_value')
6.适应不同的数据集配置:
您可能希望使用模式定义来验证您的集合,但是根据上下文(在教程示例中,我们采用训练和预测,即标签/无标签),您可能需要忽略一些条件。这可以通过以下方式实现:
# All features are by default in both TRAINING and SERVING environments.schema.default_environment.append('TRAINING')
schema.default_environment.append('SERVING')
# Specify that labels column is not in SERVING environment.
tfdv.get_feature(schema, 'labels').not_in_environment.append('SERVING')
serving_anomalies_with_env = tfdv.validate_statistics(
serving_stats, schema, environment='SERVING')
7.在可视化工具中比较不同的集合
一张图片说明了一切:
你可以在一个比较可视化中获得以上所有的好处。但是,您只能购买 2 套:
tfdv.visualize_statistics(lhs_statistics=train_stats, rhs_statistics=test_stats, lhs_name=’TRAIN’, rhs_name=’TEST’)
8.我们在 TF 转换中使用您的模式
如前所述,您生成的模式将避免您手动描述您的要素类型。它可以通过以下方式加载到 TFTransform 中:
feature_spec = schema_utils.schema_as_feature_spec(schema).feature_specschema = dataset_schema.from_feature_spec(feature_spec)
9.最后一个音符
我将跳过偏斜和漂移比较器,因为它们是前面解释的逻辑的扩展,您可能希望在 git 中更深入地了解如何在 TFDV 中使用这些特性。两者都很有用!
总之,TFDV 正是它所代表的,一个数据验证工具,不多不少,与 Tensorflow 生态系统完美集成,为 TFTransform 提供更多自动化,并完成谷歌试图为机器学习从业者提供的端到端框架。它仍然感觉缺陷处理缺失,但是考虑到已经提供给我们的不同的库来减轻我们的痛点,我相信这很快就会到来!Google 计划的下一个版本是数据摄取模块,然后是作业管理、编排、监控…如下图顶部所示。
您可以在此找到完整的官方 TFDV 教程:
**[## Tensorflow 数据验证入门| TFX | TensorFlow
简而言之,模式描述了对“正确”数据的期望,因此可以用来检测数据中的错误…
www.tensorflow.org](https://www.tensorflow.org/tfx/data_validation/get_started)**
使用 Tensorflow 和 Keras 的手写识别
原文:https://towardsdatascience.com/handwriting-recognition-using-tensorflow-and-keras-819b36148fe5?source=collection_archive---------3-----------------------
由于个人书写风格的巨大差异,手写识别(也称为按书写者对每个手写文档进行分类)是一个具有挑战性的问题。解决这一问题的传统方法是提取语言相关特征,如不同字母的曲率、b/w 字母的间距等。然后用 SVM 这样的分类器来区分作家。在博客中,我想展示一种基于深度学习的方法来识别这些特征。我们将把小块手写图像传递给 CNN,并用 softmax 分类损失进行训练。
为了证明这种技术的有效性,让我们用它来对英文手写文本进行分类。
你可以在我的 Github repo 上找到完整的代码
获取我们的数据
IAM 手写数据库是最大的英文手写图像数据库。它有 1539 页由 600 多位作者撰写的扫描文本。出于本演示的目的,我们将选取拥有最多数据量的前 50 名作家。对于每个作家来说,数据库是他们写的单个句子的集合。请参见以下一个 writer 的示例:
Sample sentences
神经网络不需要对原始数据进行太多的预处理。因此,我们不会对这些图像进行任何修改,然而,我们不是将完整的图像传递给神经网络,而是传递小块的文本。
生成补丁数据
我们希望神经网络能够理解个人作家的写作风格,我们更希望这个神经网络是文本独立的(可以在任何语言上工作)。因此,我们不是传递单个的句子或单词,而是传递随机的文本块。这是通过从每个句子中随机裁剪 113×113 大小的补丁来完成的。下图是 8 个这样的补丁的拼贴画。
Collage of 8 patches
我们可以编写一个生成器函数来移动每个句子,并从中生成随机的图像块。对于每个图像,我们将把补丁的数量限制为可以生成的总补丁的 30%。关于如何编写这个生成器函数的更多信息,请查看我的 Github repo 。
模型和结果
为此,我们在 Keras 中使用 Tensorflow backend 构建了一个卷积神经网络(CNN)。我们将使用具有多个卷积和 maxpool 层、几个密集层和一个具有 softmax 激活的最终输出层的标准 CNN。在卷积层和致密层之间使用 RELU 激活,并使用 Adam 优化器优化模型。
模型的大小需要与数据的大小成比例。对于这个问题,三个卷积最大池层块和几个密集层就足够了。请参见下面的模型摘要:
CNN Model Summary
经过一点超参数调整后,我们在测试数据集上损失了 94% ,而该模型从未接触过该数据集。
见下面两个补丁,模型归类为同一作家。“t”的形状看起来非常相似,因此也可以直观地感觉到它们属于同一个作者。
总结
使用深度学习的手写识别是一种非常强大的技术,原因如下:
- 它会自动识别深层的强大功能
- 我们提供随机补丁的方法使模型文本独立
- 高预测精度使得在实际应用中使用它成为可能
参考
- 深度作家为文字独立作家鉴定
- IAM 手写数据库
SpringML 是谷歌云平台的首要合作伙伴,专注于机器学习和大数据分析。我们已经在多家财富 500 强企业中实施了预测和分析解决方案。请联系了解更多:info@springml.com,www.springml.com
使用 Keras 在 iOS 上使用 MNIST 进行手写数字识别
原文:https://towardsdatascience.com/handwritten-digit-recognition-with-mnist-on-ios-with-keras-e85e194f9fa5?source=collection_archive---------1-----------------------
或者:如何在 iOS 中使用一个 Keras 深度学习神经网络?
本教程展示了在 Tensorflow 上使用 Keras 构建和训练的卷积神经网络模型的使用。我将展示如何将该模型集成到 iOS 中,并通过 apple 为 iOS11 引入的新 CoreML 和 Vision Api 在代码中访问该模型(本教程中为 Objective-C)。我在 mnist 数据集上训练了这个模型,以便创建一个可以识别手写数字的应用程序。
对于那些 TL;博士:我感觉你- > 下面是代码!
对于那些不熟悉 Tensorflow 和 Keras 的人,我建议从那里开始尝试一些教程和代码,然后再回到这里。
对于那些对深度学习主题完全陌生的人,我肯定会推荐你去看看 Sentdex 、 Siraj 来自 Machine Learning Mastery 或 deepschool.io 的家伙们的一些不错的 Keras 教程,然后再回到这里。
在我们开始之前:这里有一些关于我如何为这个教程设置我的工作站的提示。在继续学习本教程之前,请确保您的计算机上已经运行了所有这些程序。安装过程可能需要一些时间,所以请确保你没有和你的另一半计划冲突😉
本教程的先决条件:
- Tensorflow(版本 1.2.1)
- Python 2.7
- Keras 2(版本 2.0.6)
- coremltools(版本 0.5.1)
- MacOS Sierra 10.12.4+
- Xcode 9 Beta(开发者帐户可用)
- iOS 11 测试版(如果你想在 iPhone 上测试,可以选择。模拟器完全足够)
好吧,如果你做到了这一点,有些东西你会很熟悉,这真的很好!
KERAS + MNIST 数据集
如何在 Keras 中加载和训练 MNIST 数据集?
Keras 框架已经提供了一个可以下载的 MNIST 数据集。它包含 60,000 张手写图像,可用于训练神经网络。请参见 MNIST 数据集中手写数字的一些示例。
Handwritten Digits from the MNIST dataset
您可以自由选择构建您自己的模型,并实现您自己的卷积网络或您在 Keras 中构建的任何其他网络或模型。但是为了加快速度,下载Keras github 仓库中的卷积网络 mnist 示例。这是一个完全可行的例子,可以用来玩和学习。它下载 mnist 数据集并重塑矩阵,以适应神经网络。我在我的 Mac 上训练了这个模型,花了将近一个小时,因为我没有安装带 GPU 支持的 TensorFlow。
如果您下载了 cnn_example_mnist.py ,请确保进行以下更改:
1.检查输入形状
数据的 input_shape 应该定义为channels _ last。这将确保 CoreML 能够识别模型的输入数据,从而能够将 CIImages 传递给模型。否则你需要知道如何将一个 UIImage 转换成一个 MLMultiarray 来将你的图像传递给模型。
由于模型将在 28x28 大小的图像上训练,请记住,我们将在稍后的应用程序代码中采用该大小的图像。
2.保存模型
如何在 Keras 中保存我训练好的 mnist 模型?
在您训练您的模型之前,请确保它将在完成训练后自动保存。在代码的最后添加这一行。
Keras 提供这个调用来保存训练好的模型。如果你已经完成了,你就可以运行这个脚本了。它将下载,训练和保存您的新模型在同一个目录中。
KERAS + coremltools
如何将我训练好的 keras .h5 模型转换成 CoreML?mlmodel?
幸运的是,苹果支持用 Keras 构建的机器学习模型。然而,本教程发布时的 coremltools 版本并不正式支持 Keras 2.0.6。但它仍然有效!我面临的唯一问题是将输出 _ 描述定义为与 输出 1 不同的东西。
如果你知道如何解决这个问题,请写在评论中,我会更新代码
谈论模型的输出:模型将输出一个独热数组,其槽数与我们拥有的类数一样多。在 iOS 中,输出将是一个 MLMultiArray,它相当于 Numpy 数组。
复制这段代码并编辑作者字段。coreml_model 使得向模型中添加一些元信息成为可能,这样如果你分享你的模型,那些支持你的模型的人就知道如何使用它。稍后我们将看到这将如何在我们的 Xcode 项目中显示。
如果您在转换由某些字段引起的模型时遇到问题,您也可以省去它们,只使用coreml _ model . save(' keras _ mnist _ CNN . ml model ')
此时你应该已经转换了。您目录中的 mlmodel。如果有,就好好享受,休息一下。
。mlmodel + Xcode
- 现在开始一个新的 Xcode 项目,选择单视图应用
- 想怎么命名就怎么命名,并确保语言设置为目标-C
- 现在在你的项目导航器左侧点击你的项目。在 General 下向下滚动到链接的框架和库。这是您添加 CoreML 框架和 Vision 框架的地方。
4.点击 cmd+b 来测试你的项目是否设置正确,是否可以正确构建。如果成功,只需拖动新创建的。mlmodel 到项目中。Xcode 9 能够将其识别为 mlmodel。如果您在项目导航器中单击它,它将如下所示:
看到我们在 coremltools 脚本中传递的信息了吗?很酷吧?
注意:如果您的 Xcode 无法识别型号,并向您显示类似这张图片的内容,那么您可能没有使用 Xcode 9
如果你的模型的输入是一个多阵列而不是一个图像,那么你应该仔细检查你的模型的输入形状是否真的被设置到通道最后,如上所述。
您还应该确保在转换脚本中正确初始化了 coremlmodel,并正确设置了 input_names=['image'] 和image _ input _ names = ' image '。
Xcode 应该自动生成 mlmodel 的 Objective-C 模型类。如果不是:
为什么 Xcode 没有生成我的 Objective-C 模型类?
我还不知道,可能是个 bug。但是要修复它,只需点击右边的复选框,将模型添加到目标中。这将触发构建过程并生成模型类。
绘图应用程序
你可以选择在 github 上下载我的代码,然后摆弄这些代码,或者参考位于 raywenderlich.com的旧的黄金绘图应用教程,然后完全自己构建它(这是我一直推荐的)。
在这一点上,你应该通过检查我的代码或自己构建应用程序来理解如何用手指在嵌入在 UIImageView 中的 UIImage 上书写。
图像预测
对于下一步,我们首先从清单开始:
- 您已经在 Xcode 项目中正确设置了模型
- 模型输入是 28x28 灰度图像
- 模型输出是一个大小为 10 倍的多阵列
- 如上所述,您已经将 CoreML 框架和 Vision 框架导入到您的项目中
- 您有一个 UIImageView,可以用手指在上面进行绘制
预测过程如下:导入 CoreML.h 和 Vision.h 的头文件以及自动生成的模型类的头文件:
当我测试应用程序时,我发现如果我们在将图像传递到视觉框架之前,自己将图像缩小到 28x28,我们会获得更好的预测结果。尽管框架会自动为我们进行缩放。您可以使用这个助手方法无缝地将 UIImage 缩放到所需的大小:
在我们缩放了 UIImage 之后,它需要被转换成 CIImage 这是我们需要的格式,以便将其传递给视觉框架。
在缩放和转换图像之后,我们使用 MLModel 类来初始化我们自己创建的模型,作为它的 MLModel 版本。这将被传递给我们的 VNCoreMLModel ,它将被 Vision 框架使用。
既然我们已经创建了图像和模型,我们需要构建预测请求。我们将使用 VNCoreMLRequest 并用我们新构建的 VNCoreMLModel 初始化它。该请求用 completition handler 初始化,该处理器接收我们的深度学习模型的预测结果。
现在棘手的是:
如何从 CoreML Vision framework 获得一个热门的多阵列预测结果?
当任务完成时,completition 处理程序中的 VNRequest 在其结果数组属性中携带结果。在大多数情况下,数组中的每个结果都是所谓的VNCoreMLFeatureValueObservation。这就是我们要找的东西。这个观察类包含一个 MLFeature ,我们可以通过观察 featureValue 属性检索它。而那个特征值的多数组值就是我们想要的 10 长度双多数组输出 1。
瞧!🎉
由于在我们的多阵列中有 10 个从 0 到 9 的神经元,与其他神经元相比,激发最多的神经元也具有最高的 double 值。该神经元在多阵列中的位置表示模型预测的数量。因此,如果最高值在索引 8 处,则预测数也是 8,以此类推。
One-Hot Array Values
现在,我们已经准备好了请求,也知道了如何获得结果,我们已经准备好了图像,我们可以组合所有内容并开始执行请求。
我们初始化一个 VNImageRequestHandler ,它接受我们之前创建的 CIImage 和一个包含图像选项的字典(我创建字典是为了将它传递给处理程序,但将它留空,因为我认为这里不需要选项)。
我们现在可以在新创建的请求处理器上调用 performRequests ,并将放入数组中的请求传递给它。
就是这样!VNImageHandler 将启动请求并调用 completition 处理程序,让我们知道我们的模型在想什么。
下面是完整的 predictDigit 方法:
现在,如果我们测试应用程序,它可能会检测到至少一些我们在屏幕上绘制的数字,但不是所有的数字。请随意改进模型或使用更好的模型。请在评论中告诉我们。
为了测试问题,我添加了原始 mnist 数据集的两个图像。它们总是被正确预测。
为什么要用黑色背景和白色来画画?
这纯粹是为了改进预测。mnist 数据集主要是深色背景上的白色数字。即使输入图像被转换成灰度,我们对训练集的输入越熟悉,得到的结果就越好。但是,如果我们只是在另一个训练集上训练我们的模型,使它独立于颜色,这可以得到改善。但就目前而言,我认为在 iOS 上尝试深度学习是一个良好的开端。
下一步是什么?
尝试示例应用程序。使用 Keras 构建您自己的模型,并将其传递给示例应用程序。你现在已经有了解决几个机器学习问题的工具。关于核心 ML 的更多信息和一个将 caffemodel 集成到 iOS 的例子,我强烈推荐gal Foppolo的教程。
另一个类似的项目可以在这里找到。这个程序使用从 UIImage 到 MLMultiarray 的转换作为输入,并使用这里的相同模型接收可比较的结果,所以也去看看这个程序吧!
希望这篇教程对 iOS 上刚接触深度学习和神经网络的人有所帮助。现在继续制作你自己的机器学习应用程序吧!
[## boaerosuke/digitre cognition _ IOs
digitrecognition_ios -使用 Tensorflow/Keras 的深度学习:基于 mnist-dataset 和卷积的数字识别…
github.com](https://github.com/boaerosuke/digitrecognition_ios)
HandySpark:让熊猫般的能力点燃数据框架
原文:https://towardsdatascience.com/handyspark-bringing-pandas-like-capabilities-to-spark-dataframes-5f1bcea9039e?source=collection_archive---------5-----------------------
“Panda statues on gray concrete stairs during daytime” by chuttersnap on Unsplash
TLDR;
HandySpark 是一个新的 Python 包,旨在改善 PySpark 的用户体验,特别是当涉及到探索性数据分析时,包括可视化功能。
更新(2019 年 3 月 9 日):版本 0.2.0 今天发布,包括分层操作的性能改进和 BinaryClassificationMetrics 的扩展版本——更多详细信息,请查看发布说明此处。
使用 Google Colab 亲自尝试一下:
[## 谷歌联合实验室
使用 HandySpark 探索泰坦尼克号
colab.research.google.com](https://colab.research.google.com/github/dvgodoy/handyspark/blob/master/notebooks/Exploring_Titanic.ipynb)
检查存储库:
[## dvgodoy/handyspark
HandySpark -带来熊猫般的能力来激发数据帧
github.com](https://github.com/dvgodoy/handyspark)
介绍
Apache Spark 是最流行的集群计算框架。约有 30%的工作清单 ( 链接)将其列为必备技能。
大多数数据科学家使用 Python 和熊猫、事实上的标准来操作数据。因此,他们想要使用py Spark——Spark Python API,当然还有 Spark DataFrames ,这是合乎逻辑的。
但是,从熊猫到星火数据帧的过渡可能不像人们希望的那样顺利…
动机
两年来,我一直在数据科学务虚会上使用 Apache Spark 向 100 多名学生教授应用机器学习。
我的学生经常对 PySpark 的一些怪癖感到困惑,还有一些时候,在使用传统的 Pandas/Scikit-Learn 组合时,对缺少一些科学家认为理所当然的功能数据感到困惑。
我决定通过开发一个 Python 包来解决这些问题,这个包将使PySpark中的探索性数据分析变得更加容易……
HandySpark 简介
HandySpark 非常容易安装并集成到您的 PySpark 工作流程中。只需 3 个步骤就能让你的数据框成为手办框:
- 使用
pip install handyspark
安装手动停车 - 用
from handyspark import *
导入手动停车 - 用
hdf = df.toHandy()
将你的数据框变成手持框
导入 HandySpark 后,方法toHandy
作为扩展被添加到 Spark 的数据框架中,所以你可以直接调用它。
让我们快速浏览一下你可以用 HandySpark 😃
1.获取数据
不再需要从Row
对象中进行繁琐的列选择、收集和手动提取!
现在你可以像在熊猫身上一样获取数据,使用**cols**
:
hdf.cols['Name'][:5]
0 Braund, Mr. Owen Harris
1 Cumings, Mrs. John Bradley (Florence Briggs Th...
2 Heikkinen, Miss. Laina
3 Futrelle, Mrs. Jacques Heath (Lily May Peel)
4 Allen, Mr. William Henry
Name: Name, dtype: object
简单多了,对吧?结果就是一个熊猫系列!
请记住,由于 Spark 中数据的分布式性质,只可能获取任何给定 HandyFrame 的顶部行——所以,不,您仍然不能做类似于
[3:5]
或[-1]
等等的事情…只有[:N]
。
还有其他类似熊猫的方法:
hdf.cols['Embarked'].value_counts(dropna=False)
S 644
C 168
Q 77
NaN 2
Name: Embarked, dtype: int64
如果你还没有猜到,上面的例子(以及这篇文章中的所有其他例子)是使用著名的泰坦尼克号数据集构建的:-)
2.绘图数据
缺乏一种简单的可视化数据的方法总是困扰着我的学生。而且,当人们在网上搜索使用 PySpark 绘制数据的例子时,更糟糕的是T42:许多许多教程只是简单地将整个数据集转换成熊猫然后以传统方式绘制。
求求你,千万别这么做!它肯定可以处理玩具数据集,但如果用于真正大的数据集(如果您使用 Spark,很可能会处理这些数据集),它会失败得很惨。
HandySpark 通过使用 Spark 的分布式计算能力正确计算统计数据,然后将结果转化为图表,从而解决了这个问题。然后,事情变得很简单:
fig, axs = plt.subplots(1, 4, figsize=(12, 4))
hdf.cols['Embarked'].hist(ax=axs[0])
hdf.cols['Age'].boxplot(ax=axs[1])
hdf.cols['Fare'].boxplot(ax=axs[2])
hdf.cols[['Fare', 'Age']].scatterplot(ax=axs[3])
Plotting with HandySpark!
是的,甚至还有散点图!这怎么可能呢?! HandySpark 将两个特征分别分成 30 个箱,计算 900 个组合中每一个的频率,并绘制相应大小的圆。
3.分层
如果您想使用分割-应用-组合方法执行分层操作,该怎么办?可能想到的第一个想法是使用 groupby 操作…但是 groupby 操作会在 Spark 中触发可怕的数据洗牌,所以应该避免使用。
HandySpark 通过相应地过滤行,对数据的每个子集执行计算,然后组合结果来处理这个问题。例如:
hdf.stratify(['Pclass']).cols['Embarked'].value_counts()Pclass Embarked
1 C 85
Q 2
S 127
2 C 17
Q 3
S 164
3 C 66
Q 72
S 353
Name: value_counts, dtype: int64
您还可以通过利用桶或分位数对象,用非分类列对其进行分层。然后在分层图中使用它:
hdf.stratify(['Sex', Bucket('Age', 2)]).cols['Embarked'].hist()
Stratified histogram
4.输入缺失值
“你应该估算缺失的值”
不过,首先要做的是。有多少缺失值?
hdf.isnull(ratio=True)PassengerId 0.000000
Survived 0.000000
Pclass 0.000000
Name 0.000000
Sex 0.000000
Age 0.198653
SibSp 0.000000
Parch 0.000000
Ticket 0.000000
Fare 0.000000
Cabin 0.771044
Embarked 0.002245
Name: missing(ratio), dtype: float64
好了,现在我们知道有 3 列缺少值。让我们去掉Cabin
(毕竟,它的 77%的值都丢失了),把注意力放在另外两列值的插补上:Age
和Embarked.
在版本 2.2.0 发布插补器转换器之前,缺失值的插补无法集成到 Spark 管道中。但是它仍然不能处理分类变量(如
Embarked
),更不用说分层插补了…
让我们看看 HandySpark 如何帮助我们完成这项任务:
hdf_filled = hdf.fill(categorical=['Embarked'])
hdf_filled = (hdf_filled.stratify(['Pclass', 'Sex'])
.fill(continuous=['Age'], strategy=['mean']))
首先,它使用最常见的值来填充分类列中缺失的值。然后,根据Pclass
和Sex
对数据集进行分层,以计算Age
的平均值,该平均值将用于插补。
它使用了哪些值进行插补?
hdf_filled.statistics_{'Age': {'Pclass == "1" and Sex == "female"': 34.61176470588235,
'Pclass == "1" and Sex == "male"': 41.28138613861386,
'Pclass == "2" and Sex == "female"': 28.722972972972972,
'Pclass == "2" and Sex == "male"': 30.74070707070707,
'Pclass == "3" and Sex == "female"': 21.75,
'Pclass == "3" and Sex == "male"': 26.507588932806325},
'Embarked': 'S'}
到目前为止,一切顺利!是时候将整合到一个火花管道中,生成一个自定义变压器与**transformers**
:
imputer = hdf_filled.transformers.imputer()
估算器对象现在是一个成熟的可序列化 PySpark 转换器!那是什么意思?你可以随意在你的管道和保存/加载中使用:-)
5.检测异常值
“你不能通过!”
我们不应该让多少异常值通过?
hdf_filled.outliers(method='tukey', k=3.)PassengerId 0.0
Survived 0.0
Pclass 0.0
Age 1.0
SibSp 12.0
Parch 213.0
Fare 53.0
dtype: float64
目前只有 Tukey 的 方法可用(我正在做 Mahalanobis 距离!).该方法采用可选的 k 参数,您可以将其设置为更大的值(如 3)以允许更宽松的检测。
以Fare
列为例。根据 Tukey 的方法,有 53 个异常值。咱们栅栏他们!
hdf_fenced = hdf_filled.fence(['Fare'])
下和上栅栏值是多少?
hdf_fenced.fences_{'Fare': [-26.7605, 65.6563]}
记住,如果你愿意,你也可以进行分层击剑 😃
您可能已经猜到了,您也可以将这一步集成到您的管道中,生成相应的转换器:
fencer = hdf_fenced.transformers.fencer()
6.熊猫功能
在 Spark 2.3 中,熊猫 UDF发布了!这对我们 PySpark 用户来说是一个重大改进,因为我们终于可以克服传统用户定义函数(UDF)带来的性能瓶颈。牛逼!
HandySpark 更进一步,为你做所有繁重的工作:-)你只需要使用它的**pandas**
对象和voilà——熊猫的许多功能立即可用!
例如,让我们使用[isin](https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.isin.html)
,就像你使用普通的熊猫系列一样:
some_ports = hdf_fenced.pandas['Embarked'].isin(values=['C', 'Q'])
some_portsColumn<b'udf(Embarked) AS `<lambda>(Embarked,)`'>
但是,记住 Spark 有懒评,所以结果是一个列表达式,它利用了熊猫 UDF的力量。剩下唯一要做的就是实际上将结果分配到一个新列,对吗?
hdf_fenced = hdf_fenced.assign(is_c_or_q=some_ports)
# What's in there?
hdf_fenced.cols['is_c_or_q'][:5]0 True
1 False
2 False
3 True
4 True
Name: is_c_or_q, dtype: bool
你说得对! HandyFrame 有一个非常方便的赋值方法,就像在熊猫里一样!
而且这还不是全部!来自熊猫的特殊化**str**
和**dt**
物品同样可用!例如,如果一个给定的字符串包含另一个子字符串,您希望查找该怎么办?
col_mrs = hdf_fenced.pandas['Name'].str.find(sub='Mrs.')
hdf_fenced = hdf_fenced.assign(is_mrs=col_mrs > 0)
有关所有支持功能的完整列表,请查看库。
7.您自己的 UDF
天空才是极限!您可以创建常规 Python 函数并使用赋值创建新列:-),它们将为您变成熊猫 UDF!
您的函数(或lambda
)的参数应该有您想要使用的列的名称。比如说Fare
的log
:
import numpy as np
hdf_fenced = hdf_fenced.assign(logFare=lambda Fare: np.log(Fare + 1))
您也可以使用接受多列作为参数的函数。请记住,默认的返回类型,即新列的数据类型,将与使用的第一列相同(在示例中为Fare
)。
也可以指定不同的返回类型——请查看库中的示例。
8.更好的例外
Spark 异常是 loooong …无论什么时候出现故障,错误都会通过看似无限的层冒出!
我总是建议我的学生将一直向下滚动到,然后向上滚动,试图找出问题的根源……但是,不再是了!
HandySpark 将解析错误,并在顶部 :-)向您显示一个漂亮而醒目的红色摘要,它可能不完美,但肯定会有所帮助!
Handy Exception
9.安全第一
一些数据帧操作,如collect
或toPandas
将触发检索数据帧的所有行!
为了防止这些动作的不良副作用, HandySpark 实现了一个安全机制!它将自动限制输出为 1000 行:
Safety mechanism in action!
当然,你可以用**set_safety_limit**
指定一个不同的极限或者豁出去告诉你的手柄到忽略安全使用**safety_off**
。关闭安全机制对单次动作有好处,因为它会在返回请求的无限结果后返回。
最后的想法
我的目标是改善 PySpark 用户体验并允许从熊猫到 Spark 数据帧的更平滑的 过渡,使得执行探索性数据分析和可视化数据更加容易。不用说,这是一项正在进行的工作,我已经计划了更多的改进。
如果你是使用 PySpark 的数据科学家,我希望你尝试一下 HandySpark 并让我知道你对它的想法:-)
[## dvgodoy/handyspark
HandySpark -带来熊猫般的能力来激发数据帧
github.com](https://github.com/dvgodoy/handyspark)
如果你有什么想法、评论或者问题,请在下方留言或者联系我 推特 。
人工智能产品来之不易的建议
原文:https://towardsdatascience.com/hard-earned-advice-for-ai-products-c320d900862e?source=collection_archive---------4-----------------------
AI 产品比较硬。它们需要解决人类思维无法理解的问题,同时还要在预算有限、挑剔、有时不稳定的基础设施上运营。它们需要组织来自网络上的无数无上下文的数据片段,并强制压缩遥远相关的见解,以形成更大的概括,而这些见解各自都在尽一切努力保持现状。
如果一个产品克服了这些挑战,它必须学会如何在一个开放的市场中保护自己,这个市场充满了成熟的非人工智能竞争对手,以及几家年轻的智能创业公司,这些公司充满了来自斯坦福和谷歌的所有热门新技术。每一个人工智能产品都希望市场认为他们拥有最大的价值——最好的数据,最准确的模型——但当两个解决方案不一致或使用未经实践验证的方法时,市场就会变得混乱。(事实上,人工智能产品在实践中经常失败,这要感谢它们易犯错误的创造者)。即使当其他一切都顺利运行时,行业可能已经有了一个工作解决方案,但没有通过机器学习得到显著改善,或者市场还没有为人工智能解决方案做好准备。然后,产品必须转移并深入挖掘核心行业问题,直到发现目前被复杂性隐藏的新价值。这些转变可能需要在产品的支持组织中进行大的、深远的改变,并且不是所有的团队都有能力执行或幸存一个支点。
也就是说,这是一个令人兴奋的领域,似乎有无限的机会。我永远不会声称自己知道所有的答案,但这里是我在过去的一年半时间里作为 IdealSpot 的产品总监所学到的一些经验。
- AI 没有内在价值。事实上,即使考虑到效率的提高,人工智能也比人力更难推销。与任何其他产品一样,模型没有任何意义,除非您将它们放入您的业务领域的上下文中。你遇到的大多数经理、主管和客户都不知道你在描述什么,或者为什么它很重要,除非你能用简单的英语描述你的产品如何帮助他们的底线。在销售产品时,你可能永远不会提到底层的模型或技术,这没关系。记住你工作的整个背景,用愚蠢简单的术语解释你的价值。
- 了解你的领域,知道你的极限。你不会走进一个你一无所知的几十年历史的行业,然后用你一起破解的一些出色的机器学习应用程序在一夜之间彻底改变它。你不会的。事情不是这样的。尤其是在老行业,复杂性已经变得看不见了,即使它一直存在。当人类有完成手头任务的过程时,他们在用无知掩饰复杂性方面训练有素。一旦这些过程建立起来,他们就会变得不信任任何可能出现的新解决方案。不要提供一个新的过程来解决旧的问题,而是提供一个新的工具来帮助旧的过程自动化。让生活变得更容易,但不要假设代理或优势。你必须赢得机会,用你新的思维方式来改变世界。
- 投机取巧。如果支持你产品的团队在你的目标领域没有经验或稳固的网络,你需要愿意通过中间人的角色采取一小步,直到你最终能得到合适的工作。如果你保持警觉,不断向目标前进,你可以从任何地方开始。
- 封装整个堆栈——不仅仅是机器学习人才,还包括现代数据库、抓取和足够多的分布式系统,以便从头开始设置和扩展您的产品。数据尤其重要。如果你的核心没有一套独特的多样化数据,你将很难达到产品生存所需的质量或灵活性。数据驱动产品化。
- 魔术不卖。在大多数情况下,模型很容易,但证明价值却极其困难。即使你建立了优秀的模型,为世界上最难的商业问题提供了最佳的答案,客户也不会信任你,除非你已经在大规模上得到充分的测试和证明。如果这是你选择走的路,你就错过了所有不需要完美,甚至不需要复杂程度就能实现采纳的唾手可得的果实。
- 尽管有这些喧嚣,人工智能行业还没有进化到足以赢得对其功能的内在信任。现在有一整类人工智能应用程序正在艰难地学习计算机仍然没有人类聪明,还有整整一代消费者正在学习不信任人工智能应用程序,因为简单问题的解决方案失败或困难。
- 使用机器学习更有效地创造产品价值。我发现现在机器学习非常适合 UX——尽可能做你的用户会在你的应用中做的猜测和模糊推理。填写适当的默认值和设置,插入缺失的信息,预测操作,发现交互数据中的趋势,以提供更好的用户体验。建模用户,而不是领域。
- 把你的产品想象成一个人工智能,即使它几乎没有智能组件。你的目标是让你的用户和你的产品进行流畅的交互,就像他们和人说话一样。请记住,交流不需要语音或文本,只需要一致的模式语言
深度学习的硬件
原文:https://towardsdatascience.com/hardware-for-deep-learning-8d9b03df41a?source=collection_archive---------3-----------------------
我喜欢深度学习…
深度学习最近的成功是不可阻挡的。从对图像和语音识别中的对象进行分类,到为图像添加字幕,理解视觉场景,总结视频,翻译语言,绘画,甚至制作图像,语音,声音和音乐!
…我想跑得更快!
结果是惊人的,因此需求将会上升。想象你是谷歌或脸书或 Twitter:在你找到一种方法来“阅读”图像和视频的内容,以更好地了解你的用户,他们喜欢什么,他们谈论什么,他们推荐什么,他们分享什么之后。你会怎么做?你可能会想做更多!
也许你运行了一个版本的 ResNet / Xception / denseNet,把用户图片分成上千个类别。如果你是互联网巨头之一,你有很多服务器和服务器场,所以理想情况下你想在这个现有的基础设施上运行深度学习算法。它可以工作一段时间…直到你意识到你用来解析文本的服务器,现在要做的操作是以前对单个图像进行分类的一百万倍以上。来自使用的数据越来越快。现实生活每一分钟 300 小时视频!。
服务器农场消耗大量电力如果我们需要使用 100 万个以上的基础设施来处理图像和视频,我们将需要建立大量的发电厂,或者使用更有效的方法在云中进行深度学习。权力来之不易,所以我们最好走效率路线前进。
但数据中心只是我们需要更优化的微芯片和硬件来实现深度学习解决方案的领域之一。在自动驾驶汽车中,放置 1000 瓦的计算系统可能是可以的(尽管也将使用电池/燃料),但在许多其他应用中,功率是一个硬限制。想想无人机、机器人、手机、平板电脑和其他移动设备。这些都需要在几瓦的功率预算下运行,如果不低于 1 W 的话。
还有许多消费产品,如智能相机、增强现实护目镜和设备,也需要消耗很少的电力,并且可能不想使用云计算解决方案来解决隐私问题。
随着我们的家庭变得越来越智能,人们可以看到许多设备将需要使用深度学习应用程序,持续收集和处理数据。
所以…你需要新的硬件,啊?
因此,我们需要新的硬件,比基于英特尔至强处理器的服务器更高效的硬件。一个英特尔服务器 CPU 可能消耗 100–150 W 的功率,并且可能需要一个带冷却功能的大型系统来支持性能。
其他选择是什么?
- 图形处理器,GPU
- 现场可编程逻辑器件
- 定制微芯片、专用集成电路、专用集成电路或片上系统
- 数字信号处理器
- 我们可能从未来、外星人或晦涩难懂的新物理定律中获得的一些其他技术
绘图处理器
GPU 是设计用于生成基于多边形的计算机图形的处理器。近年来,考虑到最近的计算机游戏和图形引擎的复杂性和对真实性的需求,GPU 已经积累了巨大的处理能力。NVIDIA 在这一领域处于领先地位,它生产的处理器拥有几千个内核,计算效率几乎达到 100%。事实证明,这些处理器也非常适合执行神经网络的计算,矩阵乘法。请注意,矩阵向量乘法被认为是“令人尴尬的并行”,因为它们可以通过简单的算法扩展来并行化(它们没有分支,因此几乎没有缓存未命中)。
泰坦 X 是一种最受欢迎的训练深度学习模型的工具。凭借超过 3500 个内核,它可以提供超过 11 万亿次触发器。有关测试性能的更多信息,请点击查看。
英特尔 CPU 和 NVIDIA GPUs 之间的竞争有利于后者,因为 GPU 的核心数量巨大(英特尔至强处理器的核心数量约为 3500 个,至强处理器的核心数量为 16 个,至强处理器的核心数量为 32 个),抵消了 CPU 时钟速度快 2 到 3 倍的影响。GPU 核心是更复杂的(分支预测和流水线)CPU 核心的简化版本,但是拥有如此多的 GPU 核心可以实现更高水平的并行性,从而提高性能。
目前,GPU 是训练深度学习系统的标准,无论是卷积/ CNN 还是递归神经网络/ RNN。他们可以在几毫秒内一次对 128 或 256 幅图像的大批量图像进行训练。但它们的功耗约为 250 W,并且需要一台完整的 PC 来支持它们,还需要额外的 150 W 功率。不低于 400 W 可能进入高性能 GPU 系统。
这不是增强现实护目镜、无人机、手机、移动设备和小型机器人的选项。即使在未来的消费级自动驾驶汽车中,这种功率预算也是不可接受的。
NVIDIA 正在努力开发更节能的设备,如 Tegra TX1 和 TX2 (12 W 和大约 100 G-flops/s TX1 在深度神经网络上的性能,更多的是 TX2)和更强大的 Drive PX (250 W,像 Titan X)。
还要注意的是,在自动驾驶汽车和智能摄像机的情况下,实时视频是必要的,图像批处理是不可能的,因为视频必须实时处理才能及时响应。
一般来说,GPU 每瓦功率可提供约 5 G-flops/s 的性能。如果我们希望移动系统部署深度学习解决方案,我们需要做得更好!
现场可编程门阵列 (Field Programmable Gata Array 的缩写)
现代 FPGA 设备,如 Xilinx 公司的产品是电子产品的乐高积木。人们可以用他们的电路作为构建模块来构建完整的定制微处理器和复杂的异构系统。近年来,FPGA 开始支持越来越多的乘累加计算模块。这些 DSP 模块可以执行乘法运算,并且可以排列在一起并行执行许多运算。
10 多年来,我们一直致力于将 FPGA 用于神经网络。我们的工作始于 NYU Yann le Cun 团队最初的开拓性工作,特别是 Clement Farabet 。我们的合作产生了用于运行神经网络的复杂数据流处理器。
在 2011 年至 2015 年初期间,我们完善了一个名为 nn-X 的全新设计。这项工作由 Berin Martini 和 Vinayak Gokhale(来自我们实验室)领导。该系统在 4 W 的预算下提供了高达 200 G-ops/s 的速度,实际上是 50 G-ops/s/W,几乎是 GPU 的 10 倍。
但是 nn-X 遇到了两个主要问题:
- 不使用固定卷积引擎时利用率低
- 高内存带宽第一个问题是由于 nn-X 采用 10x10 的固定卷积引擎,当执行 3x3 卷积时,只有 9%的 DSP 单元得到有效利用。后来,通过将 12x12 的网格划分为 4x4 的 3x3 卷积器单元,这种情况得到了改善。不幸的是,该系统还需要高内存带宽,因为它没有使用数据缓存,并且需要从内存中获取输入并将结果直接保存到内存中。因此,nn-X 无法扩展,其 DPS 单元的利用率从未超过 75–80%。
具有类似设计约束的系统在性能上也会受到限制。
所需要的是具有数据高速缓存的系统,该系统可以使用任意组的 DPS 单元来有效地使用接近 100%的资源。一个这样的系统是微软的 Catapult 和我们自己的雪花加速器,利用率接近 100%。
微软使用 Altera 设备在执行深度神经网络方面实现了创纪录的性能。不幸的是,这不是一个商业系统,而是微软数据中心的资产之一,因此还没有向公众开放。中国互联网巨头百度也走了这条路线。
定制 SoC
高通、AMD、ARM、Intel、NVIDIA 都在努力将定制微芯片集成到他们现有的解决方案中。Nervana 和 Movidius(现在都在英特尔公司工作)已经或正在开发集成解决方案。在相同的技术节点上,SoC 可以提供比 FPGA 系统好~ 10 倍的性能,在某些特定的架构上甚至更多。随着 SoC 和处理器的功耗越来越低,这种差异将来自新的集成内存系统,以及对外部存储器带宽的有效利用。在这一领域,集成为系统级封装的 3D 内存是将功耗降低至少 10 倍的一种方法。
死后无子女。
DSP 已经存在很长时间了,它生来就是用来执行矩阵运算的。但是到目前为止,还没有一个 DSP 真正提供任何有用的性能或可以与 GPU 竞争的设备。这是为什么呢?主要原因是内核数量。DSP 主要用于电信系统,不需要超过 16 或 32 个内核。他们的工作量不需要它。相反,GPU 工作负载在最近 10-15 年间持续增长,因此需要越来越多的内核。最后,自 2006 年左右,NVIDIA GPUs 在性能上优于 DSP。
德州仪器继续开发它们,但我们还没有看到它们的任何竞争性能。许多 DSP 也已经被 FPGAs 取代。
高通在他们的 SoC 中使用了 DSP,它们提供了加速,但是目前还没有足够的细节将它们与其他解决方案进行比较。
今后
是我们要做的。保持兴趣、专注和活跃!
关于作者
我在硬件和软件方面都有将近 20 年的神经网络经验(一个罕见的组合)。在这里看关于我:传媒、网页、学者、 LinkedIn 等等…
假观点!用于机器学习的合成医学图像
原文:https://towardsdatascience.com/harnessing-infinitely-creative-machine-imagination-6801a9fb4ca9?source=collection_archive---------9-----------------------
Image taken from High-Resolution Mammogram Synthesis using Progressive Generative Adversarial Networks, Korkinof et al. (Kheiron Medical Technologies) https://arxiv.org/abs/1807.03401
没有数据,人工智能什么都不是。就像一个人被锁在一个白色无声的房间里努力理解外部世界一样,没有某种输入,人工智能是不可能实现的。即使是业内最优秀的机器学习工程师,也无法在没有任何数据的情况下做出一个函数式算法。
人类大脑不断受到数据的轰炸——视觉、听觉、触觉、嗅觉、情感等——并进化出高级过滤器来整理这些冲击,只允许有意义的输入通过。如果我们要实现真正的人工智能,那么关键在于数据,以及对数据的大量过滤和处理。然而,现在,当谈到医学应用的训练模型时,似乎没有足够高质量的数据可供研究人员使用。
当前用于训练放射学人工智能系统的框架在很大程度上依赖于监督和半监督学习,其中使用了包含专业标记图像的大型数据集。研究人员在获得好东西时面临三大障碍——医疗数据的数量、质量和伦理使用。除了这些障碍之外,攀登医学成像数据准备度(MIDaR)等级以将 D 级数据(医院内的实时未匿名临床数据)转换为 A 级数据(用于培训的去识别、标记、干净的数据)所需的时间和成本可能是几个月、工时和数千美元的事情。即使获得了 A 级数据,尽管尽了最大努力来创建完美的数据集,它也常常是有偏差和不平衡的。罕见的疾病将被低估,各种奇怪而奇妙的正常变异将比比皆是。
很少有公开的高质量医学成像数据集可用于研究,也没有全球标准化的数据集用于验证放射学人工智能模型的准确性。这个问题在成像部门最为明显,例如,与电子健康记录分析相反,在电子健康记录分析中,数据主要是表格和字母数字。这种类型的数据可以很容易地扩充,只需为日期生成随机数,或者使用更复杂的技术来生成虚假的患者资料。
在医学成像中,翻转、裁剪、缩放和倾斜图像等数据增强技术只能到此为止。毕竟,改变图像的方法只有这么多,即使这样,实际上也没有添加新数据。
不幸的是,你不能生成无限的合成医学图像来进行训练。还是可以?
制造逼真的赝品
全球各地的机器学习团队现在正把注意力转向创建合成医学成像数据,使用一种相对新的网络形式(由 Goodfellow 等人首次推出)。2014 年)称为生成性对抗网络(GAN)。这种趋势正在加速,关于医学图像生成的论文越来越多。
你可能已经在其他领域看到过 GANs。例如,他们以创造假名人的图像而闻名,也有像职业舞者一样跳舞的假视频。
Examples of generated realistic high-resolution images of fake celebrities
那么什么是 gan,它们是如何工作的?
gan 由两个网络组成,一个是生成网络(G ),另一个是鉴别网络(D)。我喜欢把他们分别想象成学生和老师。它们相互对抗(因此有对抗性这个术语),学生试图通过考试,老师给考试打分。测试恰好是学生是否能创造出逼真的合成图像。只有当学生给出正确答案时,老师才会奖励学生。重要的是,老师和学生都很少或根本不知道教学大纲。教师必须从真实图像中反复学习,并给学生“打分”,学生必须在多次反复中猜测答案可能是什么,这是更困难的任务!通过这种方式,学生以无人监督的方式学习——没有被明确地教授任何东西,只得到关于对错的反馈。
医学图像的生成器必须使用随机噪声向量输入来创建看起来足够真实的合成图像,以便鉴别器将它们识别为属于定义手边任务的分布式特征(或潜在)空间。将一组图像中的潜在空间概念化是很棘手的,因为它本质上是一个多维的抽象实体。事实上,为了缩小这一特征,空间研究人员通常将其限制在多维超球面上。
多维超球面
A multi-dimensional hypersphere with discrete points relating to the feature space within images
想象一个 3D 空间(x,y,z)中的球体和位于其表面上的离散点。每个点代表一个合成图像,随着生成器根据鉴别器的反馈进行训练,球体上的点逐渐编码越来越多的关于真实世界医学图像中发现的特征的信息。例如,球体上的某些方向可能具有语义含义,在乳房 x 线照相术的情况下,这可能涉及密度或实质模式。假设一个训练有素的生成器,每个点将代表在真实世界医学图像中发现的综合构建它们所必需的整套特征。在现实中,这个空间实际上不是三维的,而是多维的(超球),然而它的维度比图像小得多(更紧凑),图像可以由数百万像素组成。
鉴别器网络(D)将图像编码成它自己的高维表示,类似于但不一定与发生器(G)对齐。它吸收关于给定训练数据集的特征空间的内容和边界的知识,而生成器网络(G)试图生成新的合成点以适应相同的空间。如果生成的图像不符合特征空间边界,鉴别器将拒绝它们。通过多次迭代,生成器网络学习创建开始匹配的图像,并且这样做的准确性和完整性越来越高。结果是一个充满无限离散合成数据点的特征空间,所有数据点都符合原始数据集的特征/潜在空间。更重要的是,可能没有一个合成图像与任何原始训练集相同。它们只是在特征空间中共享相同的分布。
Saturating hyperspheric feature space with synthetic data points
简单!
如果这很难理解(我试了几次),想象一个更简单的任务——教孩子画胡萝卜。首先你给他们看一根胡萝卜,让他们画出来。他们很可能会画出一些模糊地类似于你给他们看的胡萝卜的东西。他们下意识地做的是“学习”成为胡萝卜的特征空间——顶部有绿叶的橙色尖状物。现在想象给孩子看十种不同的胡萝卜,然后让他们画一张新的胡萝卜图片。他们将能够抽象并画出一个全新的胡萝卜,一个不同于你给他们看的所有图片的胡萝卜,但仍然是一个完全可识别的胡萝卜。人类特别擅长这种富有想象力和创造性的任务。
这就是为什么 GANs 如此有趣——它们让我们离复制人类大脑的实际工作方式更近了一步。我们人类能够进行抽象和有趣的思考,我们不仅仅是通过鹦鹉学舌来学习。人类以一种无人监督的方式学习,当我们还是孩子的时候,我们通过实验和玩耍来了解我们的环境,接受不断的反馈。在某种程度上,我们通过在潜意识中创造合成现实和在头脑中测试场景来学习。甘人本质上也能做同样的事情。通过创造抽象概念,并确保它们符合某些预先定义的参数,可以有效地让机器产生幻觉,在幻觉中保持现实的界限。它是视觉表达、创造和抽象,可能是解锁真正人工智能机器视觉的巨大进步。
那么为什么甘有用呢?
对于合成医学成像数据,有几个提议的用例。我不会涵盖所有内容,但我强烈建议感兴趣的读者参考 Kazeminia 等人的这篇优秀评论文章,以获得更完整的技术见解。图像合成仍然是研究最多的应用。例如,麻省总医院的团队发表了他们在生成合成核磁共振脑扫描方面的工作,其他人已经生成了逼真的视网膜图像。在图像去噪(提高低剂量 CT 分辨率)、从稀疏采集的数据进行图像重建(更快的 MR 序列)以及改进分割和弹性配准算法方面也有非常有趣的研究。
A pie chart. I hate pie charts. But this one does serve a purpose at least.
由于计算和处理能力的限制,创建非常高分辨率的图像存在技术障碍,目前大多数研究产生的图像介于 124 x 124 和 512 x 512 之间。这部分是因为 gan 是出了名的脆弱,当网络中的层变得过于拥挤时,经常会坍塌并产生垃圾。
在 Kheiron,我们最近发表了我们关于使用所谓的渐进式 GAN(或 pGAN)生成高分辨率乳房 x 线照片的工作。通过对来自我们数据库的大约 50 万张真实乳房照片训练鉴别器网络,我们绘制了构成乳房照片的整个特征空间,然后训练生成器在相同的特征空间内合成高分辨率合成图像。这是逐步完成的(见页首图片),以非常低的分辨率启动鉴别器和发生器,并在每次迭代中逐渐将图像大小加倍。据我们所知,我们超过了迄今为止发布的合成 2D 医学图像的最高分辨率,成功创建了像素比为 1280 x 1024 的极其逼真的乳房 x 光照片。(随着分辨率加倍,特征空间变得几乎呈指数级复杂!).此外,我们已经能够同时生成每个乳房的两个标准视图(头尾和内侧斜),这意味着我们可以创建任何形状、大小或密度的乳房的完整合成患者病例,而不仅仅是不相关的单个图像。此外,只要生成的图像保持在经过训练的特征空间内,我们就能够生成无限多的图像。下面的视频很好地展示了这些合成图像看起来有多真实,以及整个特征空间是如何通过的。
这是早期的工作,完整的结果还不知道。并非所有生成的图像看起来都绝对真实——肯定有一些奇怪的情况限制了有用性!我们将研究逼真的合成图像是否可以用于增强数据集,以便进行下游分类器训练。值得注意的是,尽管合成图像的数量是无限的,但它们并不代表原始数据集潜在空间边界之外的“新”数据,因此不能替代高质量真实世界数据的训练。然而,在对注释良好的真实数据进行微调之前,通过使用合成数据作为弱标记数据进行训练,可能会获得相当大的好处。鉴别器可用作超出正常特征空间分布的真实图像的检测器。还有工作要做,以评估这些模型是否可以帮助域转移,特别是对不同供应商硬件拍摄的乳房 x 光片的外观进行标准化。
因此,尽管还不完全是“免费的无限数据”,但通过让人工智能获得无限的创造力,我们肯定已经朝着实现这一目标迈出了一步。毕竟我们人类就是这么学习的。
如果你和我一样对人工智能在医疗保健中的未来感到兴奋,并想讨论这些想法,请联系我们。我在推特上 @drhughharvey
如果你喜欢这篇文章,点击推荐并分享它会很有帮助。
关于作者:
Harvey 博士是一名委员会认证的放射科医师和临床学者,在英国国民医疗服务体系和欧洲领先的癌症研究机构 ICR 接受过培训,并两次获得年度科学作家奖。他曾在 Babylon Health 工作,领导监管事务团队,现在是放射科顾问、皇家放射科医师学会信息学委员会成员、人工智能初创公司(包括 Algomedica 和 Smart Reporting)的顾问,并且是 Kheiron Medical 的临床总监,khe iron Medical 是第一家获得放射学深度学习应用 CE 标志的英国公司。
哈佛判例法系统访问项目数据
原文:https://towardsdatascience.com/harvard-caselaw-access-project-data-by-the-numbers-4f95f5b2b30a?source=collection_archive---------20-----------------------
2018 年 10 月 31 日,哈佛法学院图书馆的图书馆创新实验室将近 650 万份美国法院案例免费在线提供。这为法律技术领域的初创企业、老牌公司和研究人员提供了一个前所未有的机会,将机器学习方法应用于大量法律文档。
这篇文章提供了数据集中所有案例的案例摘要统计。统计数据基于截至 2018 年 11 月 15 日所有辖区的手动批量下载。正如哈佛判例法团队所确认的那样,一些批量文件不包括最新的 2018 年数据,并将很快更新——我将及时更新这篇帖子。
总共有 6,454,632 个案例,分布在 61 个司法管辖区,包括“美国”(即联邦案例)和一些没有数据的司法管辖区(“美洲原住民”和“地区”)。
“美国”管辖区有超过 170 万起案件,其次是纽约州近 110 万起,路易斯安那州略多于 30 万起。按辖区划分的案件数量分布如下图所示。
Distribution of the number of cases by jurisdiction.
相对于 2017 年的州人口,路易斯安那州的人均病例数最高,其次是纽约和哥伦比亚特区。
Cases per capita and jurisdiction.
大多数案件发生在 1990 年以后,这意味着它们的相关裁决日期大约在 1990 年或更近。在此之前,数据相当稀少,可以追溯到马里兰州的一个案件,判决日期为 1659 年。达科他州包括 1885 年到 1889 年之间的案例——该州实际上从 1861 年到 1889 年就存在了。关岛的领土包括 1955 年到 1980 年的案件,1969 年到今天的纳瓦霍部落和 1979 年到 1999 年的北马里亚纳群岛。按管辖区和判决日期年份划分的案件分布如下图所示。
Cases by jurisdiction and decision date year.
案件通常包含意见,意见是由一名法官(或一组法官)作出的书面解释,描述了裁决的理性和法律原则。意见根据手头的案例解释法律,因此为法律学者提供了一个有趣的机会。马里兰州和加利福尼亚州的法官倾向于撰写最长的意见,平均每份意见超过 5000 个标记。按管辖区降序排列的单一意见中包含的标记的平均数和中位数如下图所示。
Average and median number of tokens contained in a single opinion by jurisdiction in decreasing order.
最后,每个案件的律师人数一般为 2 人,每方一人。不过,新墨西哥州和加利福尼亚州的案件平均有超过 2.5 组律师,而路易斯安那州、华盛顿、波多黎各和纽约的案件平均只有不到一名律师。注意,每组代理人可能由任意数量的代理人组成,我在这里没有画出。每个案件和司法管辖区的平均和中位数律师人数如下图所示。
Average and median number of sets of attorneys per case and jurisdiction.
特别是哈佛案例数据库的“观点”部分为有趣的发现提供了更多的机会。这篇文章提供了对这个丰富的法律数据集的第一手见解。它有望为计划使用这些数据的数据科学家提供一个开端。
你将使用哈佛判例法数据做什么?
数据已经成为新的金牛犊了吗?
原文:https://towardsdatascience.com/has-data-become-the-new-golden-calf-8a199e386642?source=collection_archive---------14-----------------------
犹太人塔纳赫的一个广为人知的故事讲述了希伯来领袖摩西从上帝那里接受了著名的十诫。然后,神命令摩西将这些诫命教导给希伯来人。在那里,讨论一般会停止;然而,当摩西与上帝交谈时,希伯来人做了什么却没有被经常讨论。
虽然希伯来人的上帝安排他们从另一个国家的奴役中解放出来,但希伯来人敦促摩西的兄弟亚伦在摩西不在的时候让他们成为神来崇拜。在他们的要求下,亚伦用希伯来人给他的黄金和宝石为他们做了一个金牛犊。从那里开始,在没有摩西领导的情况下,希伯来社会围绕着享乐主义的狂欢。上帝将希伯来人从奴役中解救出来——现在,希伯来人心甘情愿地将自己重新置于他们先前逃离的神的奴役之下[1]。
我想继续这一讨论,因为我认为它非常尖锐地表明了一个令人震惊的结论,这是我在当今的许多技术进步中观察到的:如果我们不小心,我们将失去我们的自由和自由,不是因为它被强行窃取和夺走,而是因为自由地给予。
从历史上看,许多当代发达国家都保障其公民拥有土地、投票、竞选公职等权利。这些权利在整个人类历史上来之不易——无论是通过外交还是暴力手段(我们不需要把目光放得比过去三个世纪更远就能找到明显的例子)。然而现在,我感觉到保护这些权利的重大需要,因为它们受到了威胁——不是因为公然的暴力或审查,而是因为我们对自由的微小让步。
是我们自愿制造的。
为了举例说明,2018 年 1 月下旬,澳大利亚国际安全学院学生内森·鲁瑟(Nathan Ruser)分析了健身公司 Strava [2]公开发布的一份热图。该热图显示了不确定的 Strava 地理用户数据,显示了用户日常跑步、骑车或步行的地点。然而,这张热图也使用了从驻扎在敏感地区的美军人员那里收集的数据;当 Strava 发布这张热图时,它确定了军事地点——甚至是士兵的慢跑路径。Ruser 发现的这个巨大的安全漏洞将数千名员工置于危险之中。此外,可以利用它来针对在动荡环境中工作的非政府组织
Strava released their global heatmap. 13 trillion GPS points from their users (turning off data sharing is an option). https://medium.com/strava-engineering/the-global-heatmap-now-6x-hotter-23fc01d301de … … It looks very pretty, but not amazing for Op-Sec. US Bases are clearly identifiable and mappable [3]
值得称赞的是,Strava 的首席执行官在公司的博客中迅速对这一安全暴露做出了回应,目前正在与军方、政府和非政府组织合作解决这一缺陷[4]。虽然这一事件并非恶意,但它确实提出了一个重要问题:在这个由计算创新爆炸定义的历史时代,如何保护一个人的隐私和权利?
在与普林斯顿大学计算机科学家 Arvind Narayanan 的一次采访中,他讨论了 Strava 安全缺陷,认为这是一个更严重的潜在问题的特有问题。
“有几十家公司(像 Strava)拥有这种关于数百万人的精细定位数据[……]Strava 可以被视为一个更大问题的症状,即拥有我们不愿意公开看到的敏感数据的公司数量。”
纳拉亚南甚至认为,去识别数据的流行概念是失败的,即公司或研究小组从个人那里收集数据,并删除所有可用于追溯到数据收集人的标记。
“事实上,每个人的行为都会对其他人的隐私产生影响[……]一旦我们开始将隐私视为一个集体问题,那种‘你的数据是匿名的,所以你不会受到任何伤害’的说法就不攻自破了[……]正确的教训是,我们需要对隐私的含义有一个更细致的理解[……]它不能简单地归结为匿名,或者让用户去搞清楚……[P]隐私需要真正整合为核心部分
正如纳拉亚南所说,公司和开发者不仅需要考虑他们产品的最终用户,还需要考虑他们的隐私——而不仅仅是收集数据的匿名化。我们已经到了一个关键时刻,我们需要把人——我们脑海中能想到的真实的人,我们关心的人,有名字的人——放在数据收集和隐私的中心。这就把我们带到了 21 世纪最激动人心的发展和复杂问题的特殊领域——人工智能。
人工智能已经开始复兴。现在每天都有文章高呼“机器学习”或“人工智能代理”,人工智能已经不可磨灭地影响了世界。人工智能的存在使得谷歌首席执行官桑德尔·皮帅说“[人工智能]是人类正在努力的最重要的事情之一。它比,我不知道,电或火更深刻。”[6]尽管人工智能已经取得了很大进展,但它仍处于初级阶段。正是此时此地,在接下来的几年里,在可预见的未来,人工智能的使用将很有可能成形。
人工智能的发展之所以能够在进步方面看似突飞猛进——从人工智能能够比传统的放射科医生更好地检测肺炎[7]到像 Google Home 或 Amazon Echo 这样的数字家庭助理迅速普及——是因为开发人员可以使用人们通过互联网使用产生的大量数据。谷歌、脸书、亚马逊、百度、微软、政府组织——所有这些公司和组织都可以使用互联网收集一个人的任何信息。再加上技术在世界大部分地区的无所不在,你就有了无限的数据供应。
从事人工智能研究的计算机科学家利用这些丰富的信息——无论是在企业还是以研究为基础的群体中——来训练数学算法,这些算法可以对给定的用户活动做出各种预测。例如,这可能就像亚马逊注意到你喜欢在它的网站上购买特定的产品。稍后,您可以看到类似或相关产品的推荐弹出。这很方便。它帮助我们更有效率。酪在我们没有意识到的情况下,我们的整个体验可以在瞬间被人工智能支持的技术改变。
已经有很多关于人工智能主体可以做出什么样的结论的讨论,因为,总的来说,我们并不确切知道他们是如何得出这些结论的。为了获得谷歌或亚马逊等公司使用的有意义的结果,用户数据经常通过许多数学手段进行转换,即使是最有经验的计算机科学家也难以理解——这篇鹦鹉螺文章和技术评论文章更多地讨论了这种现象(尽管是用更专业的术语)——并在学术界引起了很大的不安[8,9]。
正如维贾伊·潘德在《纽约时报》上发表的一篇文章所言,人工智能的不可预测性没有什么可怕的——至少就其本身而言。他们举了一个医生诊断的例子。医生可以根据经验、信息和观察做出诊断,但从来不要求她解释整个过程。潘德认为应该对人工智能采取类似的方法[10]。双方之所以如此激烈地争论这个问题,是因为谁处于这些事态发展的中心:我们。
全世界的每一个人都被人工智能的思想所吸引。斯坦福大学人工智能实验室主任兼谷歌云首席科学家费-李非博士强调,要让人工智能更加成功,需要把人放在它的中心。这需要收集更多的人的数据来建立更好的背景[11]。这个问题让我们回到了我在开始时提出的最初论点——权利因为我们无休止的小让步而受到损害。Strava 是数据收集和发布出错的一个明显例子——然而,只会有更多的数据被生成、收集、筛选,并以近乎神出鬼没的方式检查更多的意义和结果。
现在,作为一个身处一些创造这些惊人变化的巨人身边的人,我实际上相当乐观。我可以看到这种技术可以产生的惊人的好处——事实上,我工作的实验室发表了关于医院败血症预测的文献[12]。我觉得这太不可思议了,很兴奋地想看看会发生什么。
然而,作为一个站在所有这些进步的界面上工作的人,我能感觉到一些巨大的变化正在到来。我很难讲清楚我所说的变化是什么意思,但学术界的时代精神非常活跃。无论将要发生什么,都将很快发生,它将彻底改变这个世界——“无论即将发生什么,我们都仅仅处于石器时代”[13]。
我谦卑地恳求你,无论你是学者还是职场人士,年轻人还是老年人,都要认真考虑你做出的每一个决定。继续在我所讨论的问题上教育你们自己,不要放弃我们所拥有的自由。考虑你所做的项目或工作的所有可能影响,因为现在发生的事情会影响未来的生活。技术在道德上是模棱两可的——但是我们用它做什么却不是。
来源:
[1]出埃及记第 32 章(圣经)
[2]葵,I. (2018 年 1 月 30 日)。他在暑假做了什么:暴露了一个全球安全漏洞。纽约时报。检索自 https://www.nytimes.com/2018/01/30/world/Australia/strava-heat-map-student . html?smid=tw-nytimes & smtyp=cur
[3]内森·鲁塞尔。【nrg 8000】(2018 年 1 月 27 日)。Strava 发布了他们的全球热图。来自他们用户的 13 万亿 GPS 点(关闭数据共享是一个选项)。https://medium . com/strava-engineering/the-global-heat map-now-6x-hotter-23 fc 01d 301 de……看起来很漂亮,但对于 Op-Sec 来说并不惊艳。美国的军事基地清晰可辨,可绘制地图。检索自https://twitter.com/Nrg8000/状态/957318498102865920
[4]夸尔斯法官(未注明日期)。给斯特拉发社区的信。检索于 2018 年 2 月 4 日,来自https://blog . strava . com/press/a-letter-to-the-strava-community/
[5]杨。与诺拉·杨擦出火花。从 http://www.cbc.ca/radio/获得spark/383-危险数据库-更多-1.4516637/exercise-app-shows-why-anonymous-data-can-still-be-dangerous-1.4516664631
[6]古德,L. (2018 年 1 月 19 日)。谷歌首席执行官桑德尔·皮帅将人工智能的影响比作电和火。边缘。检索自【https://www.theverge.com/2018/1/19/】16911354/Google-CEO-sundar-pichai-ai-人工智能-火-电-乔布斯-癌症
[7] Rajpurkar,p .,Irvin,j .,朱,k .,杨,b .,梅塔,h .,段,t .,… Ng,A. (2017)。CheXNet:通过深度学习对胸部 X 射线进行放射科医生级别的肺炎检测。更正,abs/1711/05225。从 http://arxiv.org/abs/1711.05225取回
[8]博恩施泰因,A. (2016 年 9 月 1 日)。人工智能是不是永远高深莫测?鹦鹉螺号。检索自http://nautil . us/issue/40/learning/is-人工智能-永久-高深莫测?
[9]奈特,W. (2017 年 4 月 11 日)。人工智能核心的黑暗秘密。麻省理工科技评论。检索自https://www . technology review . com/s/604087/the-dark-secret-at-the-heart-of-ai/
[10 ]潘德五世(2018 年 1 月 25 日)。人工智能的“黑匣子”没什么可怕的。纽约时报。检索自https://www . nytimes . com/2018/01/25/opinion/artificial-intelligence-black-box . html
[11]奈特,W. (2017 年 10 月 9 日)。把人类放在 AI 的中心。麻省理工科技评论。检索自https://www . technology review . com/s/609060/put-humans-at-the-center-of-ai/
[12]马约、路易&塔拉先科、利奥纳尔&安娜、吉拉里&克利福德、加里。(2013).心率复杂性对严重脓毒症患者病情严重程度的预测能力。重症监护杂志。28.e37。10.1016/j.jcrc
[13]阿贝尔,A. (2018 年 1 月 17 日)。奥威尔的《老大哥》已经走进了数百万个家庭。她叫阿利克夏。麦克林的。检索自http://www . macleans . ca/society/technology/Amazon-Alexa-Google-home-privacy-surveillance/
我如何用 Python 和 Tkinter 构建我自己的梅西烟火秀
原文:https://towardsdatascience.com/having-your-own-fun-how-to-build-your-own-macys-firework-show-with-python-and-tkinter-79cc31631b44?source=collection_archive---------4-----------------------
用一些数学印章和几行代码
Image source: Pixabay
故事(或缺少故事):
我要坦白一件事。
我没有看梅西百货 7 月 4 日的烟火秀。
“什么?但是你确实住在曼哈顿”
事实上,独立日那天我根本没有走出我的公寓。你看,从我还是个孩子的时候起,我就从来没有热衷过假日公共活动。人群中喇叭的声音和人们的尖叫,成千上万人的香水和体味的不洁聚集!!!我有没有提到在活动结束后,你和其他 100 个人一起坐在地铁车厢里的痛苦?就我个人而言,我度过了一个非常棒的 7 月 4 日假期——在我的空调房里看了《布鲁克林 99》的第二季,还看了一些好书。
“哈哈,随你怎么说,老兄!这太令人难过了”
总之,有一次,我开始觉得无聊了。所以我想,与其千里迢迢跑到皇后区或布鲁克林去欣赏焰火(或者把自己塞进东河沿岸成千上万的人群中),我真的可以通过制作一些焰火模拟来增加我一天的情趣。应该是个有趣的项目,有点高中物理概念(“抛体运动和重力,有人吗?”),一些仔细的可视化规划,以及一点点玩 Python 代码的乐趣。
At the end of this tutorial, you will be able to code up a simple firework show such as this. Imaged modified by Python code from original vector from 4vector.
规划概念:
首先,说实话。我不是专业的平面设计师,也没有工具可以制作出《变形金刚》《复仇者联盟》《复仇者联盟》的 CG 效果。所以,请原谅我,如果你期待一个全面的设计效果教程,如霓虹灯风车,旋转喷泉或跳动的心脏。
然而,我们实际上将创建一个烟火表演,尽管是一个简单的表演,用不到 100 行 Python 代码。
这个想法相对简单
在这里,我通过从屏幕上的一个点发送一个 x 数量的粒子来模拟爆炸。粒子将“膨胀”,这意味着它们将以恒定的速度运动,同时保持彼此之间的均匀角度。这使得我们可以将爆炸模拟成一个不断扩大的圆圈。经过一段时间后,粒子将进入“脱落”阶段,在重力的作用下,它们将开始落到地面上。
用 Python 和 Tkinter 设计:基础
不要一次扔掉所有的数学印章,让我们同时一路构建我们的代码。首先,确保您已经安装并导入了 Tkinter 。Tkinter 是 Python 标准 GUI 的首选,它广泛用于各种不同的应用程序和项目开发。
除了 Tkinter 之外,我还导入了 PIL 来执行一些图像处理(如果你喜欢界面的漂亮背景的话),以及其他一些包,如时间、随机和数学。它们将使我们控制烟火粒子行为的工作变得容易得多。
应用程序的基本设置如下所示:
为了初始化 Tkinter ,我们必须创建一个 Tk() root 小部件,这是一个带有标题栏和窗口管理器提供的其他装饰的窗口。必须在创建任何其他小部件之前创建根小部件,并且只能有一个根小部件。
这行代码包含标签小部件。Label 调用的第一个参数是父窗口的名称,在我们的例子中是“root”。关键字参数“text”指定要显示的文本。还有其他可以调用的小部件:按钮、画布等。
接下来的两行代码很重要。pack 方法告诉 Tkinter 让窗口的大小适合给定的小部件。进入 Tkinter 事件循环,由 root.mainloop() 调用,该窗口才会出现。我们的脚本将保留在事件循环中,直到我们关闭窗口。
将爆炸转化为代码:
现在,我们设计一个对象来表示 fireworks 事件中的每个粒子。我确保每个粒子都有一些重要的属性来控制它的外观和运动:大小、颜色、位置和速度等等。
到目前为止一切顺利。如果我们回到最初的想法,我们必须确保每次爆炸中的每个粒子都必须经历 3 个不同的阶段(“膨胀”、“脱落”和“消失”)。因此,我们可以将额外的运动函数添加到粒子类中,如下所示:
I use some pretty straightforward projectile motion formula to calculate motion of each particle
当然,这也意味着我们要定义一个粒子应该活多久,应该“自由落体”多久。在找到视觉效果最好的一个之前,我只是尝试了一系列的值。
用 Tkinter 模拟
现在,这对于概念化一个粒子的运动是很好的。但是显然,一个烟花不仅仅是由一个粒子组成的,一场烟花表演也不仅仅是由一次爆炸组成的。我们的下一步是指示 Python 和 Tkinter 以可控的方式连续拍摄我们的粒子。
从 1 个粒子开始,现在我们需要将我们的想法扩展到每个烟花多个粒子,以及屏幕上的多个烟花
这是我的解决方案:我们创建一个 list 列表,其中每个子列表是一个焰火,它本身包含一个粒子列表。列表中的每一个粒子都应该有相同的 x,y 坐标,大小,颜色,初始速度。
我们的下一步是确保我们的粒子属性定期更新。在这里,我决定让粒子每 0.01 秒更新一次状态,1.8 秒后停止更新。(这意味着一个寿命为 1.6 秒的粒子将有 1.2 秒的“膨胀”,0.4 秒的脱落,以及 0.2 秒的休眠,然后 Tkinter 将其完全移除)
We go through every explosion points and update every particles coming from that point
现在,我们只需要将最后 2 个 gists 组合成一个函数,这个函数可以被 Tkinter 调用。姑且称之为模拟()。该功能将显示所有项目,并在我们指定的时间内更新每个项目的属性。在我们的主代码中,我们将在()之后使用警报处理程序调用这个函数,它将等待一段特定的时间,然后调用这个函数。
I ask Tkinter to wait 100 units of time (1 second) before calling simulate()
给你,我们刚刚编码了我们自己的烟火表演
一旦你更熟悉 Tkinter,你可以通过添加更多的颜色,用一个好的背景图像使我们的表演有层次感等等来添加你自己的风格。
我所有的代码都在我的 Github 页面上。你可以在https://github.com/tuangauss找到我的其他项目
查看我的其他媒体文章:
- 用 Python 和 Networkx 可视化网络
- 贝叶斯统计如何说服我去健身房
从混淆矩阵中消除混淆——夏威夷假导弹警报
原文:https://towardsdatascience.com/hawaii-false-missile-alert-removing-confusion-from-confusion-matrix-75b53f8caab9?source=collection_archive---------8-----------------------
“导弹接近,每个人都跑去找掩护”。人们向他们所爱的人发送最后的告别信息。家庭成员聚在一起祈祷。母亲紧抓着孩子,而父亲赶紧带着全家人安全逃到地下室。想象一下,当每个夏威夷人在 2018 年 1 月 13 日收到接近的弹道导弹警报时,他们会面临的混乱和混乱状态。
谈天堂里的烦恼!!
鉴于目前特朗普总统称朝鲜独裁者为“火箭人”的推特威胁,许多夏威夷人有所有合理的理由相信这一警告。谢天谢地,“火箭人”没有按下小小的核按钮,可能是因为特朗普有一个更大的按钮!!
Source : Pantip
谢天谢地,结果证明是一场“虚惊”。除了轻微的车祸,一个人不幸心脏病发作,更不用说pornhub 浏览量的急剧下降和 porn hub 浏览量的突然飙升(川普的说法是“比以往任何时候都强”),没有太大的损失。
如果导弹警报是真的呢?光是想想就够吓人的了。
在第二次世界大战期间,英国和盟国每天都经历着同样的困惑和恐惧。需要做点什么。
英国开发了 ROC 曲线作为链家项目的一部分。目标是辨别哪一架是飞来的敌机,哪一架是海鸥或鹅。
受试者工作曲线(ROC)是一个图形,描述了具有不同阈值的二元分类系统的诊断能力。这是真阳性率对假阳性率的曲线图。
Image Source : Statsitcs how to
我知道术语“误报率”和“真报率”现在可能会让一些人感到困惑,但我购买 ROC 图片的原因是因为它将有助于在文章的后面讲述一些关于导弹警报 UI 设计的有趣内容。
混淆矩阵中的混淆是什么原因造成的?
在我看来,当我们把预测类放在左边,实际类放在上面时,混乱就产生了,如下图所示。
Source : Wikipedia
我们的人类大脑会进入“与下面的“T9”相匹配”的模式,并由于纯粹的认知负担而变得混乱。
如何消除困惑?
我必须承认,在建立和解释各种分类模型时,我也曾经在假阳性和假阴性之间感到困惑,直到我开发了自己的技术来终生记住它。这对我有用,也许对你也有用。
获得正确的 TP、TN、FP、FN 是至关重要的,因为它们被证明在计算 TPR(又名敏感性)、TNR(又名特异性)和许多其他方面是至关重要的。我可能会写一篇文章,用真实的例子来说明如何计算这些比率而不被弄糊涂。
但是首先要做的是,消除困惑的步骤。
第一步:永远记住“预测”这个词
第二步:从右往左读(阿拉伯人和波斯人可能会觉得更容易)
第三步:如果单词是 FP,你要把它读成预测正但假
同样,假设单词是 FN,你会把它读作预测为负但为假
我不想深究 TP(真阳性)和 TN(真阴性),因为它们是不言自明的。
夏威夷导弹预警系统设计错误吗?
许多文章已经写了关于用户界面有多糟糕以及任何人都很容易犯这个错误。选项以下拉列表的形式出现
Source : Imgur
- “试射导弹警报”
- “导弹警报”
系统设计的很差吗?
带着数据科学家的帽子,我的答案是不。
原因如下:
UI 被设计成一场真阳性(TP)和假阳性(FP)的战斗
还记得我之前说过的 ROC 曲线吗?在生死关头,你需要时刻保持警惕。在真阳性和假阳性的较量中,赢家永远是你。想想吧。最坏的情况是什么。
只有两种可能:
- 真正的肯定:一枚真正的导弹正在靠近,你躲起来
- 误报:没有导弹接近,但是系统说是,你躲避
无论哪种情况,你都要躲起来。你安全了!!
如果这场战斗是假阴性(FN)和真阴性(TN)之间的较量呢
这是一场你想永远支持真正的否定的战斗。为什么?
再来两种可能:
- 假阴性:一枚真正的导弹正在接近,然而系统显示天空中没有一点点。你不采取庇护和……..(永恒的沉默)
- 没有导弹接近,也没有警报。你安全了!!
所以不管是谁设计的 UI 都做得很好。这将拯救更多的生命。
底线:生命或死亡情况警报系统应该总是设计有真阳性(TP) 和假阳性(FP) 选项。
如果你喜欢我的文章,给它几个掌声,你也可以通过下面的评论让我知道你对这篇文章的想法。
您可以通过以下方式联系我:
LinkedinTwitter我的博客:分析洛卡
HCDE 210 冲刺 4 —可视化
原文:https://towardsdatascience.com/hcde-210-sprint-4-visualization-60a969acbcd9?source=collection_archive---------5-----------------------
2015 年 12 月 7 日
Graph of Incident Reports by District: “Where are the safest neighborhoods to raise my kids?”view here
Tableau 是一个用户友好的程序,允许用户创建流体数据表示。我们在第节中介绍了它的基础知识,使用西雅图自行车架上的数据以有效的方式将定性和定量结合起来。一旦我们对 Tableau 的理解充满信心,我们就可以继续处理 sprint 数据、西雅图警方 911 事件响应数据。我将我的用户群定义为在西雅图寻找好社区的准房主。
Graph of Incident Reports by Hour of Day: “When do crimes peak in Seattle?”
我认为大多数人都想住在犯罪率相对较低的地区,并且会将低事故报告与更安全的社区联系起来。此外,我认为每个购房者对某些犯罪都有自己的敏感程度。根据这些假设,我确定数据集最重要的部分是地区/部门、事故数量和事故类型。
Graph of House-related Reports by District: “How safe is my house if I choose to buy a house in Seattle?”
当我进行多次迭代时,我意识到有很多方法可以传递相同的数据。事实上,似乎另一个用户群也可以使用相同的图表来满足他们自己的需求(例如:企业、投资者、业主)。这种灵活性让我怀疑我是否没有为我的用户组创建足够具体的可视化。另一方面,我想知道可视化是否应该对每个人开放。也许有些用户群会有更具体的需求,但也许其他用户群可能在他们想看和想知道的方面有所重叠。这引发了几个问题:我们应该创造只有特定群体才能理解的可视化吗?或者可视化应该对所有人开放,甚至是指定用户组之外的人?尽管如此,撇开问题不谈,因为 sprint 涉及到一个用户组,我认为保持它与该组相关是很重要的。如果我回到这个项目,我认为基于用户组中的角色(例如:“家庭”、“大学生”、“年轻的工作成年人”、“退休人员”)创建过滤器会很有趣
这项任务有什么挑战性?
这项任务最具挑战性的部分是找到一种方法来清晰地表示大量的数据。我必须对每个图形进行多次迭代,然后才能决定它应该是什么类型的图形(线条、条形图等),以及 x 轴和 y 轴上应该有什么属性以及其他哪些属性应该作为细节添加。意识到与识别和传达关键属性相关的挑战,我真的开始欣赏文章和信息图中呈现的信息和简洁的可视化。
可以从这些数据中受益的另一个用户群是什么?
好奇某个城市如何随时间变化的城市规划者,可能是另一个对了解城市如何随时间变化感兴趣的用户群体。他们可能会问类似“人们通常住在哪里?市区?农村?郊区?,”“人口有什么变化?目前的人口统计是什么?、“人们是如何与周围环境互动的?商店?交通?公共空间?”例如,对于研究西雅图的城市规划者来说,这个 sprint 中可视化的数据可能特别有趣。他们可能想比较 10 年、20 年、50 年前到现在的 911 事件数量,以评估西雅图的城市化如何影响其公民的心理健康和/或查看城市化与犯罪率之间是否有任何其他关系。此外,他们可以按地区过滤事件报告的数量,并使用这些数据来分析西雅图的哪些社区在遏制犯罪方面成功或不太成功。城市规划者将需要一个广泛的事件报告数据库,但这样的可视化将有助于他们更好地了解我们日益发展的文明世界的城市趋势。利用他们对世界的更好的理解,他们可以为规划高效和充满活力的城市做出贡献。
最初发表于【hcde-tiffany.tumblr.com】。
走向数据奇点
原文:https://towardsdatascience.com/heading-towards-the-data-singularity-829bfd82b3a0?source=collection_archive---------7-----------------------
首席产品官 Anjali Arora, Rocket Software
你们当中熟悉未来学家和作家雷·库兹韦尔的人无疑听说过他所描述的奇点——人和机器的融合,这是一个开创性的转折点,机器人变得有意识,可以在平等的水平上与人类互动和回应。虽然这个话题在科学家和哲学家中引起了广泛的争论,但实际上我们几乎肯定会走向另一个奇点。基于当前数据、机器学习和人工智能之间的集成程度,我们正处于数据奇点的非常早期的阶段。
直到最近,这些学科都是截然不同且互不关联的。上个世纪的企业数据范围广泛,从马尼拉文件夹中传递的行政备忘录到使用 VisiCalc 或Lotus 1–2–3来获取与企业运营方式相关的数字的电子表格。在 20 世纪的企业环境中,也就是所谓的“小数据”时代,关于业务运营的信息要少得多,有效获取或操纵这些信息的方法也少得多。
直到最近,人工智能也同样被排除在实际问题之外。1956 年夏天,约翰·麦卡锡在达特茅斯学院开办了一个工作室,在此之前,“人工智能”一词主要用于科幻小说或漫画中。但即使在那个形成阶段之后,缺乏强大的软件和硬件也将人工智能归入了尘土飞扬的学术界,直到几年前它还在那里萎靡不振。快进到 2018 年,我们现在有了可以在扑克上击败人类和围棋的机器,并且能够在四个小时内自学下棋达到大师级别。
毫无疑问,今天是一个不同的世界,但它对商业创新有着令人兴奋的影响。随着数据海啸继续扩大并席卷我们,人工智能和机器学习领域的力量和能力正在同时增长。目前的想法是,我们每年平均生成 16.3 zb 的数据。但是数据洪流只会继续增长。你的衣服在发出信号。您的汽车正在获取其他车辆的状态数据。我们不仅在智能手机和笔记本电脑上生成信息,而且新兴的物联网(IoT)也在继续降低数据的粘度。随着传感器和致动器出现在从你的鞋子到你的电器的所有东西上,我们产生的信息量将继续呈指数级增长。
随着机器学习能力变得越来越强大,信息生成的速度和步伐加快,人工智能、数据科学和机器学习的即将到来的融合为每个企业提供了许多令人兴奋的可能性。我认为数据奇点为准备好加入并利用这种新模式的公司提供了巨大的机会。想象一下,能够轻松地将供应链中的数据与市场分析数据联系起来,并利用这些数据做出有关产品开发的战略决策。每天,越来越多的将各种商业数据与人工智能驱动的分析相连接的应用程序上线,让我们离现实越来越近。
这种融合最令人兴奋的是,它对商业创新有着巨大而广泛的影响。聪明的公司正在利用潜力来实现明智、实时的战略决策,以推动业务成功。促成的决策范围很广。我们如何经营我们的业务?我们如何发展业务?我们与谁合作?我们卖给谁?我们向谁购买?
我鼓励你利用这个令人兴奋和破坏性的交叉。在探索数据奇点的威力时,以下是一些需要牢记的一般性指导:
从小处着手。
确定与数据捕获和分析相关的业务问题。
对可用的人工智能和机器学习解决方案进行尽职调查:它们的范围从图像处理等利基能力到大型工具库。
利用你现有的数据。从 FigureEight 租一些来填。
基于业务目标构建并测试 AI 实例/机器学习模型。
迭代!
您不必注册 IBM Watson 来利用数据奇点,但是您绝对应该现在就开始。已经有各种各样的解决方案,每天都有更多的出现。同样,它们包括提供相对简单的利基功能(如图像识别或语音合成)的人工智能实例,以及使用基于云的 API 和数据来提供强大的人工智能驱动的分析的应用程序。如果你雄心勃勃,并且能够访问大型数据集和大量技术资源,你可以探索更强大的选项,如谷歌的 TensorFlow 。
这对商业来说是激动人心的时刻。在数据、机器学习和人工智能的交叉领域,一场新的强大的融合正在进行。组织现在可以用全新的方式捕获、管理、组织和合理化大量信息。这种新方法将为愿意大胆反思其商业模式并投资于利用数据奇点的资源和前沿技术的公司提供巨大的竞争优势。所以开始探索吧:这是一个勇敢的新世界,有很多令人兴奋的机会。现在就开始建立你的模型。没有人想在网飞世界一鸣惊人。
Anjali Arora 是 SVP 和 Rocket Software的首席产品官,Rocket Software 是一家专注于现代化和优化的全球技术提供商,她负责监管产品战略和研发。在加入 Rocket 之前,她曾在甲骨文健康科学全球业务部门担任了三年的软件工程全球副总裁。
健康应用:从拯救生命到威胁生命
原文:https://towardsdatascience.com/health-apps-from-lifesaving-to-life-threatening-859493e711c?source=collection_archive---------4-----------------------
电子健康在这里。如果你曾经通过电话咨询过你的医生,检查过你每天用可穿戴设备走了多少步,或者在候诊室使用过那些自己动手的体重、身高和血压检查器,那么你已经是革命的一部分了。
这是一场我们需要的革命。对卫生服务的需求超过了供给,随着人口继续膨胀,这种需求将面临进一步的压力。收集和连接地理疾病数据的技术有可能防止埃博拉和寨卡等流行病,并跟踪抗生素耐药性日益增长的威胁。应用程序和严肃游戏可以缓解精神健康危机。利用传感器和远程在线服务,可以更有效地照顾老龄化的世界人口。
当健康应用出错时
广义而言,电子医疗指的是由电子流程或通信促进的医疗保健中的任何事物。世界卫生组织强调,电子医疗的主要目标应该是利用技术减少不平等。当然,言下之意是,创造利润不应该是首要目标。还记得马丁,“美国最讨厌的人”,他将一种广泛使用的艾滋病和癌症药物的价格从每片 13.5 美元提高到 750 美元?或者在美国,救生 EpiPens 的价格在 7 年内上涨了 508%?
新的危险是不受监管的应用。有些做出相对无害的承诺,比如用你手机的光来治疗痤疮(提示:它不会)。但其他人声称,你可以通过将手机麦克风贴在胸前并将手指放在摄像头上来正确测量血压。在由约翰·霍普斯金大学医学院 批准的一项研究中进行测试时,该应用程序在 80%的真实病例中未能检测到高血压。更可怕的是,当匹兹堡大学检查 4 个皮肤癌检测应用程序的准确性时,即使是最可靠的算法也表明 30%合法诊断的黑色素瘤是“低风险”的。
虽然做出虚假营销声明的应用程序可能会被处以巨额罚款,但涵盖医疗过失或医疗事故的法规出现的时间却更长。苹果等公司的开发者指南也没有提供多少保护。苹果表示,“可能提供不准确数据或信息,或者可能用于诊断或治疗患者的医疗应用程序”可能会受到更严格的审查。但是仍然有很多可用的。
2013 年,美国食品和药物管理局出台了针对医疗器械或其附件的法规。今年 5 月,欧洲监管机构更进一步。欧盟“医疗设备法规”将记录和注册数据用于医疗目的的应用程序归类为医疗设备。这意味着,如果一个应用程序为你的饮食和总体健康状况提供建议,它仍然只是一个应用程序。但如果它使用相同的数据来管理威胁生命的疾病,如糖尿病,它就是一种医疗设备,因此受到严格的控制和风险评估。随着新规则的实施,我们现在可以期待非常高质量和相对便宜的应用程序将出现在管理慢性病、改善医生和患者之间的沟通、提供早期诊断以及为临床研究收集可靠数据。
一些应用程序仍在寻找漏洞以进入健康应用程序市场。最常见的是在小字上加上“娱乐目的”。因此,目前来说,消费者应该研究他们下载的应用程序,检查它们是否得到监管机构的批准,并记住移动设备或应用程序不应被用来替代认证医生的测试。尽管 iPhone 很贵,但你的设备不太可能配备进行皮肤癌活检所需的设备。
当健康应用可以改变生活
心理健康
精神健康服务通常资金不足,而且经常受到指责,因此需要改革。提供安全访问匿名电子咨询或与医疗保健专业人员视频聊天的应用程序被证明是非常有益的。
“大白墙”是一项匿名数字服务,由训练有素的“墙向导”提供服务。它全天候支持经历常见心理健康问题(如抑郁和焦虑)的人。成员们可以用图像、图画和文字来发表文章——和其他人、工作人员交流。在一些地区,有机会通过网络摄像头、音频或即时消息与经验丰富的顾问进行一对一的现场治疗。对于近一半的用户来说,大白墙是他们第一次分享问题,也是他们获得心理健康支持的第一步。67%的会员表示使用该服务后幸福感有所提高。
支持自我保健
可穿戴设备是一种越来越受欢迎的跟踪锻炼和心率的工具。任何可以收集精确数据的类似远程患者监护工具,如起搏器和血糖监测仪,也将有助于临床医生根据您的需求提供更具体的治疗。
2016 年 11 月, Eli5 因我们的创新理念' 【马蒂 ' '获得 IBM 和凯捷颁发的 Bluemix 大奖;基于人工智能(AI)的治疗应用。马蒂担任人工智能治疗师,通过使用音乐和过去的照片来帮助痴呆症患者恢复记忆。痴呆症患者与马蒂互动,可以根据之前的对话、他们的情绪和讨论的主题来观看图片和听音乐。该工具将 IBM 的 Watson 用于语音和对话元素。
菲律宾医科学生乔尔·亚历杭德罗(Joel Alejandro)最近开发了一款名为“Sali”的心肺复苏应用。在一个贫困公民缺乏基本医疗保健服务、紧急情况下难以到达农村地区和繁忙城市的国家,具备实施 CPR 能力的人口将拯救生命。该应用程序是执行 CPR 的指南,也是连接用户和其他救生员的网络,以获得额外的支持。
信用:大白墙
我应该担心分享我的医疗数据吗?
为了让电子医疗发挥作用,你必须从数据开始。没有患者的医疗信息,就没有证据来构建电子健康产品。
电子健康产品中的人工智能可以为你理解原始数据,并从中学习,以便在未来更好地帮助你。想想活动追踪器 Fitbit 的 2320 万活跃用户。如果没有一个简单的界面,用平均值、图表和图形来交流他们的健身结果,而不是小时、天、月的数字和小数点,人们就会完全放弃这个产品。
像 Pacmed 这样的软件展示了共享数据的普遍好处。Pacmed 是一个结合了大数据、机器学习和医疗专业知识的决策支持工具。基于对匿名常规护理数据的分析,医生可以快速检查不同治疗方案的预期效果,并确定哪种方案最适合患者。上周,该公司的所有者赢得了 Vintura 医疗保健影响力奖,为产品开发获得了更多资金。
医疗数据将如何得到保护
许多人对数据共享感到不安,解决之道也在于技术。首先,对于一般研究和分析(例如,监测 1000 名接受新肺癌治疗的患者),将使用数据匿名。这包括加密信息或删除所有个人身份信息。
第二部分是分享个人健康信息,为了您自己的健康,这些信息需要归属于您。一个想法是实施区块链技术。健康公司 PokitDok 正在与芯片开发商英特尔和 IBM Watson 合作,创建一个“Dokchain”,特别是用于共享医疗记录。通过将区块链技术移动到芯片级别,它将提供“前所未有的安全水平,这对于医疗保健来说是必不可少的”(如果你想了解更多关于这是如何工作的,请参见我上一篇 医疗保健博客 )。
为了实现医疗数据的数字化交换,我们还需要对技术和记录内容进行标准化。目前,关于你健康的数据可能会存储在你的医生、医院、保险公司甚至你的健身房里。没有一个输入数据的通用结构,也没有一个共享数据的统一的国家协议——尽管一些国家正在努力实现这一目标。你目前使用的全科医生软件是行不通的,它的记录中使用了“流感”这样的口语术语,试图与医院中使用“流感”这样的科学术语记录信息的不同软件进行交流。
荷兰的 MedMij 是一个旨在使患者能够控制其医疗信息的项目。一旦在 MedMij 的规则下有了这样做的安全通道,公民就可以同意与电子医疗应用程序共享他们的数据,这可以为他们提供创新和改进的医疗解决方案。MedMij 令人兴奋的事情是来自保险公司、荷兰政府和荷兰患者联合会的高调支持。通过这种认可,MedMij 已经为€筹集了 300 万英镑,用于为他们定义为“个人健康环境”的结构创建概念验证。
所以我们开发了一个电子健康应用。这是我们学到的东西。
当我们开发移动应用 Blik 时,我们优先考虑与提供服务的志愿者和我们应用的最终用户建立密切的关系。我们为荷兰 Laurentien 公主殿下创立的读写基金会创建了 Blik,以帮助荷兰 130 万低文化水平的公民理解他们在日常生活中遇到的文件,从公用事业账单到投票登记表。
1)限制流程
我们有两组用户。那些需要破译文件的人和提供解释的基金会志愿者。该应用程序需要简单、快速和直观,但也需要定制以满足每个人的需求。所以我们把这个过程限制在用户仅仅用他们的智能手机拍下文档的照片,然后志愿者发回音频描述。用户无需阅读,志愿者可轻松获得音频响应,因此无需安排预约或打电话来讨论文件,从而节省了时间和金钱。音频可以保存,并在需要时随时重播。
2)有道德标准
我们很高兴能制造出一种数字产品,这种产品有可能将成千上万的人从身体障碍中拯救出来,同时也能消除文盲带来的一些不安和耻辱。在 Eli5,我们很幸运我们的团队中有一位了解相关道德规范的医疗专家。如果一个公司想要创造电子健康产品,他们必须对用户的安全负责。这其中的一部分就是诚实地面对预期用途和局限性。有了 Blik,我们确保了如果给出的解释第一次没有帮助,可以选择请求回电。志愿者由基金会审查,以确保达到技能和保密标准。作为开发人员,我们也意识到通过互联网交换潜在敏感文档和信息时的安全需求。
带 Spark 的医疗数据集
原文:https://towardsdatascience.com/healthcare-dataset-with-spark-6bf48019892b?source=collection_archive---------5-----------------------
Spark 是来自 Apache 的开源项目。它也是大数据和机器学习最常用的分析引擎。
这篇文章将重点介绍如何快速开始使用 Spark 开发预测算法。
我选择了来自 kaggle.com 的“医疗保健数据集中风数据”数据集,这是世界上最大的数据科学家和机器学习社区。
内容:
根据世界卫生组织,缺血性心脏病和中风是世界上最大的杀手。
来自官方网站的信息:http://www . who . int/news-room/fact-sheets/detail/the-top-10-causes of death
我们需要做的是利用患者给定的信息来预测中风概率。这是一个分类问题,我们将尝试预测某个观察值属于某个类别的概率(在我们的案例中是中风的概率)。
有很多算法来解决分类问题,我将使用决策树算法。
设置火花并获取数据
**from** **pyspark.sql** **import** SparkSession
**import** **pyspark.sql** **as** **sparksql**
spark = SparkSession.builder.appName('stroke').getOrCreate()train = spark.read.csv('train_2v.csv', inferSchema=**True**,header=**True**)
探索数据
导入数据后要执行的第一个操作是获取数据外观的一些信息。可以使用以下命令:
- df.printSchema()
- df.describe()
- df.dtypes
train.groupBy('stroke').count().show()+------+-----+
|stroke|count|
+------+-----+
| 1| 783|
| 0|42617|
+------+-----+
从这个观察可以看出。这是一个不平衡数据集,其中属于一个类的观测值数量明显低于属于其他类的观测值数量。在这种情况下,预测模型可能会有偏差且不准确。有不同的策略来处理不平衡的数据集,因此这超出了本文的范围,我将重点讨论 Spark。要查找有关不平衡数据集的更多信息:
https://www . analyticsvidhya . com/blog/2017/03/不平衡-分类-问题/
这里我们有许多病人的临床测量数据(如高血压、心脏病、年龄、家族病史),以及每个病人是否患过中风的信息。在实践中,我们希望这种方法能够根据临床测量结果准确预测未来患者的中风风险。
分析
使用基本操作进行简要分析。有几种方法可以做到:
- 数据帧为结构化数据操作提供了特定于领域的语言,可以通过属性或索引来访问数据帧的列。
- 以编程方式运行 SQL 查询并将结果作为数据帧返回
例如,要了解哪种类型的工作有更多的中风病例,我们可以做以下工作:
*# create DataFrame as a temporary view*
train.createOrReplaceTempView('table')
SQL 查询
spark.sql("SELECT work_type, count(work_type) as work_type_count FROM table WHERE stroke == 1 GROUP BY work_type ORDER BY work_type_count DESC").show()+-------------+---------------+
| work_type|work_type_count|
+-------------+---------------+
| Private| 441|
|Self-employed| 251|
| Govt_job| 89|
| children| 2|
+-------------+---------------+
看来私活是这个数据集中最危险的工种。
让我们找出谁参与了这次临床测量。
spark.sql("SELECT gender, count(gender) as count_gender, count(gender)*100/sum(count(gender)) over() as percent FROM table GROUP BY gender").show()+------+------------+-------------------+
|gender|count_gender| percent|
+------+------------+-------------------+
|Female| 25665| 59.13594470046083|
| Other| 11|0.02534562211981567|
| Male| 17724| 40.83870967741935|
+------+------------+-------------------+
所有参与中风研究的人中,59%是女性,只有 40%是男性。
根据该信息,有可能检索关于多少女性/男性患有中风信息:
spark.sql("SELECT gender, count(gender), (COUNT(gender) * 100.0) /(SELECT count(gender) FROM table WHERE gender == 'Male') as percentage FROM table WHERE stroke = '1' and gender = 'Male' GROUP BY gender").show()+------+-------------+--------------------+
|gender|count(gender)| percentage|
+------+-------------+--------------------+
| Male| 352|1.986007673211464...|
+------+-------------+--------------------+ spark.sql("SELECT gender, count(gender), (COUNT(gender) * 100.0) /(SELECT count(gender) FROM table WHERE gender == 'Female') as percentage FROM table WHERE stroke = '1' and gender = 'Female' GROUP BY gender").show()+------+-------------+--------------------+
|gender|count(gender)| percentage|
+------+-------------+--------------------+
|Female| 431|1.679329826612117...|
+------+-------------+--------------------+
1.68%的女性和近 2%的男性曾患过中风。
我们还可以看到年龄是否对中风有影响,以及年龄带来的风险。
spark.sql("SELECT age, count(age) as age_count FROM table WHERE stroke == 1 GROUP BY age ORDER BY age_count DESC").show()+----+---------+
| age|age_count|
+----+---------+
|79.0| 70|
|78.0| 57|
|80.0| 49|
|81.0| 43|
|82.0| 36|
|70.0| 25|
|77.0| 24|
|74.0| 24|
|76.0| 24|
|67.0| 23|
|75.0| 23|
|72.0| 21|
|68.0| 20|
|59.0| 20|
|69.0| 20|
|71.0| 19|
|57.0| 19|
|63.0| 18|
|65.0| 18|
|66.0| 17|
+----+---------+
only showing top 20 rows
我可以用过滤运算,计算出 50 年后人们的中风病例数。
train.filter((train['stroke'] == 1) & (train['age'] > '50')).count()result: 708
我们可以看到年龄是发生中风的一个重要风险因素。
清洗数据
探索的下一步是处理分类值和缺失值。smoking_status 和 bmi 参数缺少值。
我将用“无信息”的值填写 smoking_status ,用平均值填写 bmi 参数。
*# fill in missing values*
train_f = train.na.fill('No Info', subset=['smoking_status'])*# fill in miss values with mean*
**from** **pyspark.sql.functions** **import** mean
mean = train_f.select(mean(train_f['bmi'])).collect()
mean_bmi = mean[0][0]
train_f = train_f.na.fill(mean_bmi,['bmi'])
大多数 ML 算法不能直接处理分类数据。编码允许期望连续特征的算法使用分类特征。
string indexer-> onehotencode-> vector assembler
**from** **pyspark.ml.feature** **import** (VectorAssembler,OneHotEncoder,
StringIndexer)
它不需要事先知道一个特性中有多少类别,由 StringIndexer 和 OneHotEncoder 的组合来处理。
下一步是创建一个组装器,它将给定的列列表组合成一个向量列来训练 ML 模型。我将使用在 one_hot_encoding 之后得到的向量列。
assembler = VectorAssembler(inputCols=['genderVec',
'age',
'hypertension',
'heart_disease',
'ever_marriedVec',
'work_typeVec',
'Residence_typeVec',
'avg_glucose_level',
'bmi',
'smoking_statusVec'],outputCol='features')
然后我们将创建一个决策树对象。为此,我们需要导入决策树分类器。
**from** **pyspark.ml.classification** **import** DecisionTreeClassifierdtc = DecisionTreeClassifier(labelCol='stroke',featuresCol='features')
到目前为止,我们有一个包含许多阶段的复杂任务,需要执行这些阶段来处理数据。为了包装所有火花,ML 表示这样一个工作流,作为一个管道,它由一系列按照特定顺序运行的管道阶段组成。
**from** **pyspark.ml** **import** Pipelinepipeline = Pipeline(stages=[gender_indexer, ever_married_indexer, work_type_indexer, Residence_type_indexer,
smoking_status_indexer, gender_encoder, ever_married_encoder, work_type_encoder,
Residence_type_encoder, smoking_status_encoder, assembler, dtc])
下一步是拆分数据集进行训练和测试。
train_data,test_data = train_f.randomSplit([0.7,0.3])
我现在要做的是拟合模型。为此,我将使用创建的管道和 train_data
model = pipeline.fit(train_data)
之后,转换测试数据。
dtc_predictions = model.transform(test_data)
现在是时候评估一个模型了
**from** **pyspark.ml.evaluation** **import** MulticlassClassificationEvaluator*# Select (prediction, true label) and compute test error*
acc_evaluator = MulticlassClassificationEvaluator(labelCol="stroke", predictionCol="prediction", metricName="accuracy")dtc_acc = acc_evaluator.evaluate(dtc_predictions)print('A Decision Tree algorithm had an accuracy of: **{0:2.2f}**%'.format(dtc_acc*100))
决策树算法的准确率为 98.08%
正如在开始时所定义的,不平衡数据集的预测模型可能具有误导性的准确性。
结论
Apache Spark 是一个开源框架,它非常简洁易用。
分手和谷歌趋势搜索数据
原文:https://towardsdatascience.com/heartbreak-monday-blues-and-pytrends-f1a398591a79?source=collection_archive---------4-----------------------
周一忧郁症的病例?周末结束时打破高峰的兴趣。
Photo by Elizabeth Tsung on Unsplash
有过糟糕的周末吗?这是否导致你想要离开你的关系?为什么人们不在周一凌晨 2-4 点睡觉?
根据谷歌趋势数据,在美国,分手的相对兴趣在周一凌晨 3 点达到峰值。好像周一的忧郁还不够忧郁!
Visualization by Shelby Temple; Data Source Google Trends; Made with PyTrends and Tableau
分手具有周期性
“什么东西一年上升两次,一次在复活节,另一次在圣诞节前两周,在每周一有一个小高峰,然后在整个夏天变平?”
David McCandless 在他的 TED 演讲中向他的听众提出了这个问题,数据可视化之美。
根据脸书的状态更新,答案是分手高峰期。
根据 10,000 个报废的脸书状态,他们发现春假有一个清仓,第二个分手高峰将导致寒假。出现的另一种模式是每周一的周期性高峰。
受此启发,我决定使用谷歌趋势数据来探索人们在哪天和什么时间搜索分手细节。
谷歌趋势
我们生活在一个美好的新时代,在这个时代,我们不再需要仅仅依赖于调查产生的数据集。我们现在可以通过观察人们在互联网上做什么来衡量他们的行为。
谷歌趋势是一个伟大的公共工具,可以看到人们在互联网上做什么。在 Google Trends 网站上,你可以根据时间或地理来衡量人们对某个搜索主题的兴趣。您还可以比较多达五个不同的搜索主题。
然而,这个数据有一个关键的细微差别。它并不衡量总体查询量。它衡量的是在同一时间和地点,一个主题的谷歌搜索相对于所有其他搜索的标准化相对份额。关于如何收集、处理和解释这些数据的更多细节,这里有两个有用的链接:
什么是谷歌趋势数据,它意味着什么?
趋势数据如何调整
PyTrends
由 General Mills 为您带来的(没错,就是为您带来 Cheerios 和 Lucky Charms 的同一批人)PyTrends 是 Python 中的一个非官方伪 API 包,它可以轻松创建新的 Google Trend 数据集,并将它们直接放入一个表格中。
“非官方-相扑-API-什么-现在?”不用担心,我会把这个分解。
从互联网上获取数据的两种最令人兴奋的方式是通过网络抓取或网络应用编程接口。API 有一个更广泛的定义,但是在本文中,让我们将它们定义为:一种预期的数据推送方式,就像你可以浏览互联网一样。
Web APIs 始终是首选方法,因为它们被设计为在通话结束时将数据推送给您。他们有大量的文档和任何变化的更新。
网络抓取本质上是应该有一个 API,但公司不想构建它。您直接从发送到 web 浏览器的 html 代码中提取数据。这是不太可取的,因为如果网站改变了网页抓取代码可以很容易地打破,你不会知道为什么。网络抓取是一种意想不到的获取数据的方式。网站的建立并没有考虑到这一点。
显然,玛丽莎·梅耶尔和谷歌确实打算在 2007 年为 Trends 开发一个 API——但显然,“即将到来”在这个上下文中意味着“永远不会”。
PyTrends 是非官方的。这意味着它没有得到谷歌的认可。这是一个伪 API,意味着它的行为与 API Python 包完全一样,然而它实际上是幕后的网络抓取。
如果您有兴趣使用或了解关于该软件包的更多信息,请点击以下链接:
通用磨坊 PyTrends GitHub
看看吧!我用 6 行代码创建了一个谷歌趋势数据集,涵盖 2017 年全年,按天按小时搜索包含“如何分手”的内容。
谷歌趋势给你一个搜索兴趣指数。这是一个从 0 到 100 的分数,100 是最高的搜索兴趣。
在这种情况下,我将地理限制在美国。
解读结果
Visualization by Shelby Temple; Data Source Google Trends; Made with PyTrends and Tableau
Visualization by Shelby Temple; Data Source Google Trends; Made with PyTrends and Tableau
为了创建这些重点表格,我采用了 2017 年全年每小时和每天的平均兴趣。
如前所述,Google Trends 数据并没有显示成交量的变化。它衡量给定时间和地点的所有搜索的份额变化。不能得出分手搜索最多的是发生在周一凌晨 3 点。一个更准确的结论是,如果有人在周一凌晨 3 点搜索,那么这个搜索很有可能是关于分手的。
“那么搜索查询量呢?”
谷歌在谷歌广告中有一个不同的工具叫做关键词规划器。这是一款商业产品,面向希望开展付费搜索营销活动的企业。他们也有谷歌广告的官方 API。不幸的是,这不是一个像谷歌趋势的公共工具。
标准化是一个细微的差别,但它是由设计。数量经常根据人口数量或在谷歌上的搜索次数而上下浮动。谷歌的数据编辑西蒙·罗杰斯在这篇媒体文章中写道:
“这种标准化真的很重要:在谷歌上搜索的人数不断变化——2004 年的搜索量比现在小得多,所以原始的搜索数字无法让你比较当时和现在的搜索。通过标准化我们的数据,我们可以获得更深入的见解:比较不同的日期、不同的国家或不同的城市。”
下次你有一个有趣的问题或想法想要探索。我建议从 Google Trends 和它提供的搜索数据入手。此外,记得这个周末对你的另一半格外友好。如果你想成为一个混蛋,那就等到周五上午 11 点。
TensorFlow 中的 Hello World
原文:https://towardsdatascience.com/hello-world-in-tensorflow-973e6c38e8ed?source=collection_archive---------6-----------------------
TensorFlow 是 Google 开发的用于机器学习的开源软件库。它能够在所有 Linux、Windows 和 MacOS 平台的 CPU 和 GPU 上运行。Tensorflow 可用于设计、实现和训练深度学习模型,这些模型的灵感来自大脑的结构和功能。
在这篇文章中,我将给出一个使用 TensorFlow 实现一个简单的神经网络的分步指南。著名的 Iris flower 数据集用于训练,然后将给定的花分类到正确的类型。
Iris 数据集包含 3 种类型的花,如“Setosa”、“Versicolor”和“Virginica”。为了识别每种花的类型,给出了花的 4 个特性,即萼片长度、萼片宽度、花瓣长度和花瓣宽度。我们将使用这些因素实现一个神经网络来识别正确的类型。
首先,我们将使用训练数据集来训练我们的模型,然后我们将使用测试数据集来测试它的准确性。你可以从这里下载训练数据集,从这里下载测试数据集。
第一步
首先,我们需要读入数据。csv 文件并导入它们。熊猫图书馆可以用来轻松处理这一点。
Importing data
Pandas 中的 read_csv()函数将读取文件并将内容加载到指定的变量中。作为函数的参数,我们需要指定文件的路径,names 参数可用于指定每个文件的列名。
第二步
在数据集中,每种类型的花被编码为 0、1 和 2。我们需要使用一个热方法将它们编码为[1,0,0]、[0,1,0]和[0,0,1]。这将使得训练和优化网络变得容易,因为来自网络的输出也以一种热格式生成。
然后我们需要定义训练集的 x,y 和测试集的 x,y
Encoding classes and data separation
第三步
然后是定义输入(X)、输出(Y)的占位符以及定义网络的权重和偏差的时候了。这里我们有 4 列输入,因为数据集有 4 个特征和 3 列输出,以映射 3 种类型的花。占位符的形状应该满足这一点。此外,权重矩阵的形状必须是 4x3,偏差必须是 3 的向量,以将输入映射到输出(无隐藏层)。
Defining weights, bias and placeholders
第四步
然后,我们需要通过激活函数发送输出,这里我使用了 tensorflow 中可用的 soft-max 函数。为了训练模型,我们需要计算成本,即模型产生的输出中有多少误差。在这里,我们计算其均方误差。然后,我们可以使用 AdamOptimizer 来训练模型,从而降低成本。
Training tensor definition
第五步
经过训练以检查我们的模型有多准确后,我们需要将我们的模型预测与实际结果进行比较。然后我们可以通过计算我们得到了多少正确的结果来计算我们的模型的准确性。
Calculate accuracy
这里我们检查由我们的模型生成的输出是否等于实际结果(Y)。该模型将为每种类型的花计算一个值,该值可以被认为是每种类型的概率。我们选择最有可能的类型。 argmax 函数将返回最大值的索引。请记住,结果是一个热格式,这种方法将很容易让我们检查正确性。
在这之后,我们必须开始训练模型。在此之前,我们需要首先初始化所有的全局变量,而global _ variables _ initializer函数就是为此服务的。
第六步
现在让我们训练我们的模型。每个张量执行都必须在 tensorflow 的一个会话中完成。因此,在培训之前,我们需要创建一个会话,在完成所有工作后,我们需要关闭该会话。
Training model
添加上述代码块是为了创建 tensorflow 会话,该代码块中的所有内容都将拥有该会话。此外,该代码块能够在一切完成时自动关闭会话。
首先,执行变量初始化张量,然后训练模型 1000 次。当训练时,我们需要将训练数据集指定为 X,将相应的结果指定为 Y,因为训练张量期望它们执行。在这里,当传递 Y 时,我已经迭代并创建了一个新的数组,以确保它具有与我们上面定义的相同的形状。在每次迭代中,跟踪成本以绘制图表来查看实际的训练。
最后一步
最后,当训练过程结束时,绘制成本变化图,并通过测试数据集检验模型的准确性。
Plot graph and check accuracy
经过 1000 次训练迭代后,有可能获得 96.67% 的准确度,这确实令人印象深刻,成本变化图显示了通过降低每次迭代的成本,模型得到了显著发展。
Cost reduction due to training
以下是程序的完整代码
这篇文章将有助于 tensorflow 的新手通过这个简单的例子理解它的概念,并将成为潜入海洋的开始。
继续读
干杯!
高精度跟踪自动驾驶汽车
原文:https://towardsdatascience.com/helping-a-self-driving-car-localize-itself-88705f419e4a?source=collection_archive---------2-----------------------
第六章:用数据做酷事!
定位,或者知道“我在哪里”对于自动驾驶汽车来说至关重要。每时每刻它都需要知道自己在世界的哪个角落。当我们开车时,我们使用 GPS 和地图应用程序来知道我们的车在哪里。但是 GPS 的精度是 1-3 米,有时更高。这不适用于自动驾驶汽车,因为这是车道的宽度。汽车可能偏离车道,这是很危险的。自动驾驶汽车需要更高的精度——小于 10 厘米。在这里,我们将讨论一种称为粒子过滤器的技术,它可以用来帮助汽车在地图中定位自己。
我实现了一个粒子过滤器,可以跟踪一辆平均 x 误差和 y 误差小于 0.07 的汽车。我已经用 C++分享了我的 GitHub 的链接和完整代码。
下面是一个视频,展示了粒子过滤器在模拟环境中跟踪汽车的过程。圆形点是地图上的地标,绿线是从汽车到这些地标的激光传感器。蓝色圆圈是追踪汽车的最近的粒子。请注意粒子与实际汽车的轨迹有多接近。
粒子过滤器是如何工作的。首先,我们有一张世界地图。该地图具有地标,可以是房屋、建筑物、灯柱等。我们知道这些地标在地图上的位置
- 我们用随机放置在地图周围的 N 个粒子初始化我们的地图。把这些微粒想象成汽车可能的位置。开始时,我们不知道汽车在地图上的位置,所以所有粒子被赋予相同的权重,这意味着它们有相同的概率来表示汽车的真实位置
- 在每个时间步,汽车移动。我们的传感器告诉我们汽车行驶的速度和角度。我们将每个粒子移动与汽车相同的距离和方向。这被称为预测步骤
- 现在进入测量步骤。使用激光雷达,我们测量汽车到地图上已知地标的距离。
激光雷达使用激光进行测量,并生成周围世界的点云,为汽车提供相当准确的 x 位置和 y 位置值。然而,激光雷达在恶劣的天气条件下或传感器变脏时不是很准确。
下面是激光雷达点云的图像
LIDAR point cloud
现在到了关键的一步。对于每个粒子,我们计算该粒子和地图中已知地标之间的距离。我们比较这个距离与来自汽车的激光雷达测量值的接近程度,并使用它来分配粒子的权重。更接近实际汽车的粒子将被赋予更高的权重。
应用激光雷达测量时需要注意几个实际问题:
I)数据关联-多个激光雷达测量可以与每个地标相关联。如果是这种情况,我们使用最近邻选择距离地标最近的激光雷达读数作为激光雷达读数,如下图所示
Data Association
ii)变换-当从汽车上进行激光雷达测量时,它们的 x 和 y 位置将参考汽车,这被称为汽车的局部坐标。这些需要通过考虑汽车/粒子的位置来转换成全局“地图”坐标
4.我们对粒子进行重新采样,使得具有较高权重的粒子(因此更有可能接近汽车的真实位置)被挑选出来,而具有较低权重的粒子被丢弃。
然后我们回到步骤 2,重复这个过程。
这项技术可以很快帮助我们定位汽车。
这里有个有趣的问题?—我们如何将这项技术用于行驶在城市 A 和城市 B 之间的真正自动驾驶汽车?粒子滤波器假设我们有一张世界地图,上面有许多地标的已知位置。我们如何确定数百个地标的位置并将其输入汽车?
谷歌汽车使用的一种方法是将汽车摄像头的图像与谷歌地图街景的图像进行匹配。这被用来生成地标和定位汽车。一些供应商也在用这些信息制作详细的世界地图
总的来说,建立我的第一个粒子过滤器并用它来定位是一次很棒的经历。
PS:我住在多伦多,我希望将职业生涯转向深度学习。如果你喜欢我的帖子,并能把我联系到任何人,我将不胜感激:)。我的电子邮件是 priya.toronto3@gmail.com
其他著述:【https://medium.com/@priya.dwivedi/】T2
参考文献:
Udacity 无人驾驶汽车 Nano Degree——我感谢 Udacity 和巴斯蒂安·特龙给我机会成为他们新的无人驾驶汽车项目的一部分。这是一次非常有趣的旅程。我使用的大部分代码都是在课堂讲课中建议的。这里的图片和视频参考也在讲座中分享
用神经网络帮助治疗宫颈癌
原文:https://towardsdatascience.com/helping-treat-cervical-cancer-with-neural-networks-d41c964327f1?source=collection_archive---------8-----------------------
我们即将结束大会数据科学沉浸式项目的最后一周。为了毕业,我们需要完成一个我们选择的课题的期末项目。我有政治竞选背景,但有兴趣学习更多关于医疗保健分析的知识,并发现计算机视觉很有趣,这就是我参加 Kaggle 的宫颈癌比赛的原因。
我们得到了 1000 多张子宫颈照片,必须训练一个模型如何根据这些照片正确识别子宫颈类型。什么类型的子宫颈取决于转化区的位置,转化区是一个可能发生癌症的区域。这是很重要的,因为在他们没有资源做巴氏涂片的地方,他们用苦味酸对转化区进行目视检查,以识别癌性病变。如果宫颈为 3 型,且部分转化区不可见,则医务人员需要在此过程中考虑这一点。让这个问题变得困难的是,用未经训练的眼睛很难区分子宫颈类型,这就是 Kaggle 举办这场比赛的原因。
Cervix Types
要参与,您需要通过您的模型运行 Kaggle 的测试照片集,并输出每张照片是 1 型、2 型或 3 型子宫颈的概率。根据测试集上的最低对数损失来判断比赛,这比不确定性对错误的惩罚更大。Kaggle 的基线提交具有 1.00575 的对数损失。
Kaggle Baseline Submission
我选择的工具是卷积神经网络(CNN),这是一种神经网络,它扫描图像,识别与目标相关的模式。这篇博客不会成为我如何使用 CNN 的成功故事。相反,它是集中在我的错误,这样你就不会陷入同样的陷阱时,做自己的图像识别问题。
第一课——确保你能区分班级
我说你作为你作为一个人,你作为一个人。我这样说是因为许多图像识别挑战是我们人类可以轻松完成的。比如 Kaggle 的狗对猫比赛或者硅谷的热狗 App 。有了这些更简单的问题,你就可以更容易地应用预处理技术来帮助你的算法(比如 canny 边缘检测)。
Canny Edge Detection on Type 1 Cervixes. The algorithm was able to outline the cervix of the top photo, but not of the bottom photo.
这与子宫颈图像挑战相比,在子宫颈图像挑战中,照片非常相似,只有细微的差别来区分阶级。我不打算张贴照片,因为我不知道媒体对医学图像的政策,但只是信任。这就是问题的核心所在——如果人类很容易区分这些子宫颈类型,那么我们就不需要计算机视觉的帮助。由于这个障碍,我认为这个挑战更适合计算机视觉专家或有机器学习经验的医生,而不是像我这样的人。
第 2 课—使用自然损失函数
我用 Keras 建立我的网络,当我开始时,我注意到他们没有 logloss 作为损失函数。文件确实说 Tensorflow 损失函数是兼容的,所以我用了 Tensorflow 的 logloss 函数。在我最初的模型中,我的验证损失一直低于我的 Kaggle 损失。这很糟糕,因为我的验证失败并没有反映我的模型在现实世界中的表现,而是给出了一个更加乐观的图景。
Validation Loss versus Kaggle Loss for Several Models
在某种程度上,我决定需要看看其他内核,看看发生了什么,我看到其他 Kaggle 用户正在使用 Keras 的本地分类交叉熵作为他们的损失函数。
显然,对数损失和交叉熵是同一个概念。所以我把我的损失转换成分类交叉熵,我的验证损失更接近地反映了我在 Kaggle 上的损失。
第 3 课——神经网络容易过度拟合
在我用我的损失函数解决了这个问题之后,我不断地遇到我的网络超载的问题。我添加的时代越多,我的训练损失和测试损失就越偏离,这表明我的架构不能很好地概括。即使我只训练了几个时期,我也不会取得超过基线的成绩。我试着用各种方式改变我的模型:增加 dropout,减少我的卷积步幅,裁剪和灰度化我的图像。无论我如何改变我的架构或者我运行了多少个纪元(无论是高还是低),我都不能打败基线。
Divergent Train and Test Losses
我真的需要帮助,所以我决定看看人们在 Kaggle 上做什么,并看到了 Owl1 的内核。我最初使用的架构是斯坦福大学教授安德烈·卡帕西推荐的用于拾取更复杂特性的框架(输入->【conv->Relu->conv->Relu->池】 3->【FC->Relu】* 2->FC)。Owl1 的内核就简单多了,类似 Karpathy 建议的另一个框架(输入->【conv->Relu->池】* 2->FC->Relu->FC】)*。Owl1 也有 0.89 的 logloss,比我得到的任何分数都好。
Owl1’s Architecture
我不想完全复制 Owl1,但我想学习他的模型。我反复修改了我的模型,使它更接近他的模型,方法如下:
- 使用了更简单的架构(输入->【conv->Relu->池】 2->FC->Relu->FC])*
- 使用较少的过滤器
- 用 tanh 替换了最后一次 relu 激活
- 将优化器从 rmsprop 更改为 adamax
- 使用照片的 RGB 版本,而不是灰度版本
- 在 FC 后增加了辍学
不幸的是,这些改变都不能让我超越基线。在这一点上,我复制了 Owl1 的模型,看看我是否能复制他的结果。我想考虑的另一个选择是使用 Keras 的一个预建模型,看看它的性能如何。
最后一课——神经网络很难,而且需要很多时间
在这个项目结束时,我有:
- 花了 11 天做模型
- 制作了 30 个神经网络
- 创造了 16 个独特的建筑
- 训练超过 607 个纪元
- 花了超过 150 美元的谷歌云信用
这导致零个神经网络超过了 Kaggle 的基线。最接近的一个是我制作的第一个神经网络,logloss 为 1.00616,只有 2 个时期在其上训练。
许多人已经证明神经网络是一个强大的工具,我知道我还有很多要学。最终,神经网络需要花费大量的时间和精力,并且不一定总能给出你想要的结果。
主成分分析和 SVM 组合
我确实通过另一种方法越过了 Kaggle 的底线。我使用了图像的灰度/裁剪版本,并通过主成分分析(PCA)运行它们。PCA 是一种降维技术,它使用线性代数来组合特征(参见我的老师 Matt Brem 的帖子了解更多信息)。每张 100 x 100 的照片由 10,000 个变量表示,每个变量表示一个像素有多亮或多暗。在通过 PCA 运行照片后,我从 1036 个结果成分(或组合特征)中选择了 61 个,这些成分解释了像素亮度/暗度差异的 90%。
然后我用默认参数将结果输入到 scikitlearn 的支持向量分类器(grid search 导致更差的分数)。在提交我的结果后,我勉强跳过了 Kaggle 的基线提交,logloss 为 1.00574。
The Results from my PCA/SVM Combo
来源:
手机 https://www.youtube.com/watch?v=N8OGrykSgy0 ODT 视频:&t = 543s
斯坦福 CNN 课程:http://cs231n.github.io/
keras Docs:https://keras.io/
Keras 博客:https://Blog . keras . io/building-powerful-image-class ification-models-using-very-little-data . html
Owl1 的内核:https://www . ka ggle . com/1 owl/artificial-intelligence-for-cc-screening
这里有 9 封关于数据的电子邮件简讯…我想你至少会喜欢其中的 4 封
原文:https://towardsdatascience.com/here-are-9-email-newsletters-about-data-i-think-youll-like-at-least-4-of-them-20fb8412d803?source=collection_archive---------3-----------------------
这是 首次发表在网络新闻博客 上
Sophie Warnes doesn’t just round up data journalism in her emails, she **does* data journalism about her emails*
随着第一批 MA 数据新闻学学生本月开始他们的课程,我一直在推荐他们应该关注的领域的一些电子邮件简讯——我想我也应该在这里分享一下。
这里有 9 封关于数据的电子邮件简讯——如果我错过了,请告诉我。
1.索菲·沃恩斯的合理警告
Sophie Warnes 是一名数据记者(也是我以前的学生),曾为各种头衔工作过,最近在英国国家统计局任职。自二月份以来,她的时事通讯《公平警告》一直在提供英国和国际数据新闻的每周综述,这引起了她的注意。
她还分享了她在媒体上发布电子邮件简讯的经历,其中简讯是交叉发布的。
2.杰里米·辛格·文:数据是复数
Each issue of the Data Is Plural newsletter is recorded in a Google spreadsheet
近两年来,BuzzFeed News 的数据编辑 Jeremy Singer-Vine一直在发布他的每周时事通讯——突出有用/好奇的数据集(主要集中在美国)。所有电子邮件的列表可以作为电子表格获得。订阅这里。
3.朱塞佩·索拉索:其他新闻
朱塞佩·索拉索 称自己是一个“开放数据、标准&透明政策的书呆子”,但他也是伦敦大学圣乔治学院的学者,也是一系列令人印象深刻的作品的创造者数据新闻 作品。
自 2014 年以来,他的简讯 In Other News 一直在收集数据极客感兴趣的各种链接。
4.安迪·迪金森:媒体工厂公报
安迪·迪金森的兴趣领域是开放数据和超本地数据新闻的使用。媒体工厂公报涵盖这两个领域,以及国家和国际数据工作和学术研究。
5.杨彼得:1801 年
Peter Yeung’s newsletters feature lots of gifs — such as this one on a piece of Indian data journalism about dowries
《泰晤士报》(英国)数据记者彼得·杨(Peter Yeung)在 7 月份发布了自己的电子邮件简讯,重点报道了世界各地一些最有趣的数据新闻。像索菲·沃恩斯一样,他也在媒体上出版每一期。
你可以在这里阅读第一期,在这里订阅邮件。
6.开放知识国际通讯
开放知识基金会(OKFN)已经在开放数据领域工作了一段时间,他们的时事通讯利用全球合作伙伴和项目网络来提供事件、计划、报告和工具的更新。
7.数据面:“数据和鸡蛋”
data face 将自己描述为“一群对体育、政治、音乐、环境以及两者之间的一切都感兴趣的数据迷。”他们制作了一份时事通讯,报道他们“前一周最喜欢的数据驱动的故事……依靠丰富的可视化和交互性来启发读者。”
8.约翰·霍普金斯数据科学实验室:周一早上的数据科学
The latest newsletter from The Johns Hopkins Data Science Lab features discussion about AI and a review of R tools
对于真正的数据极客,约翰·霍普金斯数据科学实验室的周一早间数据科学提供了与数据科学、统计相关的博客帖子、播客和视频的定期链接
9.希瑟·克劳斯:数据助理
Heather Krause 是“打造数据故事”和“数据探索和讲故事:通过探索性分析和可视化在数据中寻找故事”的讲师,也是 Datassist 的创始人和首席数据科学家。这并不容易找到,但在的底部,Datassist 主页是一个订阅他们每月时事通讯的链接,重点是实用技巧和有用的链接。
数据分析在石油行业中的作用
原文:https://towardsdatascience.com/here-is-how-big-data-is-changing-the-oil-industry-13c752e58a5a?source=collection_archive---------3-----------------------
2006 年,营销评论员麦可尔·柏默在博客中写道
数据就像原油一样。它很有价值,但如果不提炼,就不能真正使用。
答九年后,这句话仍然适用于任何依赖大量数据的行业。的确,除非数据不被分解和分析,否则它没有什么价值。
随着世界越来越接受大数据的优势,石油行业似乎也不远了。如果大量的数据只是被存储,那么它就没有什么价值,因此,为了使其有用,必须对其进行识别、汇总、存储、分析和完善。访问大型数据集并从中获取丰富见解的能力可以使石油行业更加有利可图和高效。一家成功的石油公司会快速预测潜在信息,并保持低成本以实现其成功,而不会丢失数据集评估中的任何差异。
石油运动和大数据的流行在一段时间内逐渐引起了轰动。长期以来,石油供求的变化与石油价格的波动有关。随着油价下跌,石油和天然气行业正在慢慢找到走向大数据的道路,以便管理和降低风险,从而增加公司的整体收入。全球油价正变得越来越有竞争力,随着产油经济体争夺全球石油市场份额,大数据分析可以帮助他们确定需要大幅改善的领域。
在石油行业采用大数据的优势
曼哈顿研究所(Manhattan Institute)高级研究员马克·p·米尔斯(Mark P. Mills)表示,“将分析应用于页岩地质、地球物理、增产和作业的复杂性以优化生产过程,可能会使有效阶段的数量增加一倍,从而使每口井的产量增加一倍,并将石油成本降低一半。”
一个技术驱动的油田预计将开采 1250 亿桶石油,这一趋势可能会影响与石油业务相关的 2 万家公司。因此,为了获得竞争优势,几乎所有这些公司都需要数据分析,以便在整个石油和天然气生命周期中集成技术。
1.实时和高成本效益
石油行业的数据量快速增长,高效处理大量数据变得非常重要。石油公司每天都在以非常高的速度产生大量的数据。传统上,对于石油和天然气生产商来说,大量数据可能非常昂贵。如此巨大的成本会严重影响公司的财务表现。
借助大数据,企业不仅可以削减成本,还可以实时获取大数据。这种分析方法有助于提高产量 6%-8%。然而,大数据在石油和天然气行业的作用不仅仅是提高效率和实时分析大量数据。近实时可视化、大数据集存储和近实时警报被认为是大数据分析中最重要的优势。
2.降低风险并做出更好的决策
从地理上讲,不同地区的岩石层有所不同,尽管它们在结构上可能是相似的。通常从一个地区学到的经验可以应用到类似的地区。传统上,非结构化数据存储在不同的数据库或任何存储设施中,这需要大量的时间和精力。数据科学有助于降低风险,并有助于更多地了解每个子系统,从而提高决策的准确性。
3.钻井方法和石油勘探的高精度
由于石油依赖于钻井和油田勘探,在这一领域使用大数据分析被认为是一种恩惠。米勒写道,“大数据分析已经可以优化最佳钻井位置的地下测绘;指出如何以及在哪里操纵钻头;逐段确定刺激页岩的最佳方式;并确保精确的卡车和铁路运营。”
寻找新的碳氢化合物矿藏需要大量的材料、人力和后勤。钻一口深水油井通常要花费 1 亿多美元,没人想找错地方。为了避免这个问题,壳牌公司使用光缆(与惠普公司为这些传感器建立了特殊的合作关系),然后数据被传输到其私人服务器,由亚马逊网络服务(AWS)维护。这给工程师们提供了一个更准确的关于地下有什么的想法,并节省了大量的时间和精力。
新的石油钻探地点和刺激页岩油的新方法只是在石油行业应用大数据分析的部分好处。地震软件、数据可视化和普适计算设备是石油公司目前采用的一些现代分析工具。
4.确保机器的高效运行
石油钻探是一个连续的过程,机器必须在恶劣的温度和条件下长时间工作。大数据用于确保机器正常工作,不会因故障或失效而受损。机器装有传感器,收集有关其性能的数据。然后将这些数据与汇总数据进行比较,确保以高效的方式更换部件,并最大限度地减少停机时间,从而进一步降低额外费用。
在埃森哲和微软最近的一项调查中,石油公司和支持行业的公司确定,86%至 90%的受访者表示,提高他们的分析能力、在现场使用移动技术以及更多地依靠工业物联网将增加他们的业务价值。根据调查,在未来 3-5 年内,大数据和自动化的投资预计将分别从 56%增加到 61%和 53%增加到 65%。以经济合理和环境友好的方式,以更低的成本发现和生产更多的碳氢化合物,不仅可以增加数据的价值,而且有助于准确的决策。
在石油行业应用大数据工具时的注意事项
随着越来越多的数据意识,大数据在各行各业的受欢迎程度越来越高。良好的分析有助于经理们更熟练地管理不同种类的数据。这些不同的数据可以包括地震、钻井记录、诸如钻头转速和钻压的操作参数、压裂性能数据和生产率。由于每个功能都会产生大量的可变数据,因此需要将正确的数据交给正确的人,以优化性能。
就像其他行业一样,石油和天然气行业需要了解如何以最佳方式使用大数据,以及有哪些可能的应用。由于并非所有数据都有价值,存储相关信息的知识变得很重要。随着全球石油供需平衡的改变,越来越多的统计数据需要绘制出来。地点和技术也需要经常重组,这需要专业人员不仅知道如何有效地使用大数据,而且能够从中获取价值。挑战还在于数据处理的效率(从不重要的东西中筛选出重要的)。
雇佣的专家需要知道何时需要技术升级,因为石油和天然气行业是基于不断波动的需求和供应。他们应该了解开源模型、云技术、普适计算和迭代开发方法。壳牌有大约 70 名全职员工在数据分析部门工作,另外还有数百名分布在世界各地的员工临时参与其中。
对于许多石油公司来说,逐步过渡到大数据实施可能并不容易,因为许多公司缺乏人力和能力来雇佣能够处理大数据的必要人员。各行业中只有约 4%的公司拥有从分析中获取切实商业价值所需的人才和技能。
个人和网络安全也需要关注,因为这仍然是实现大数据分析价值的一个明显障碍。大数据实时分析无疑为建立更高效的石油生产、降低成本和风险、提高安全性、提高法规合规性和改善决策提供了创新机会。在使用大数据工具时,良好的专业知识和战略审慎不仅能确保成功,还能减少误差。
为转载联系 作者
以下是分析如何重塑人力资源
原文:https://towardsdatascience.com/heres-how-analytics-is-reinventing-human-resources-1ad283fe7014?source=collection_archive---------6-----------------------
Photo by JehyunSung on Unsplash
使用真实世界的洞察力展示 ace 人才分析的 3 个步骤
您知道旧金山和纽约拥有美国最丰富的 JavaScript 人才库吗?根据公开的 Github 数据,西雅图是 C#程序员的首选之地?
在印度,班加罗尔是顶尖的编码人才中心,其中 Java 拥有最多的 Github 库。这与美国大多数城市的模式形成鲜明对比,在美国,Java 排在第四位,在 Javascript、Python 和 Ruby 之后。
这些都是对 HR 人才团队有用的见解。员工敬业度有哪些有趣的发现?
一家领先的亚洲零售银行发现,员工股票期权(ESOP)是年度评估中对员工绩效影响最大的因素,特别是在某些业务部门。该银行还发现,参与企业社会责任活动的员工流失风险最小。
数据驱动的人才管理
诸如此类的见解表明,数据有助于揭示表面上看不见、但更强大的人类行为潜流。
数据分析可以成为更好地了解员工及其参与度的有力工具。它可以改变人力资源职能的长度和宽度。它可以派上用场,以减少招聘偏见,改善员工关系,找到性能的驱动因素,并帮助管理自然减员。
人力资源流程捕获大量数据。它们始于最初的接触,并在员工不再积极参与后延续很久。这些数据可以提供特别有价值的可操作见解。如果有合适的外部资源,它可以变成一座金矿。
关于更智能的人力资源职能的三条建议
以下是迈向更聪明的人才管理之旅的 3 个成功步骤。为了说明每一点,我使用了来自真实世界商业案例研究的数据故事,这些数据故事来自我们在 Gramener 的工作。
1。数据从来都不是限制,发挥你的数据源的创造力
缺乏数据或精选来源是组织中的常见抱怨。这通常被认为是人力资源更加数据化的缓慢进展的原因。人们引用 excel 表格是如何驱动整个功能的。或者说,尽管数字化已经进行了几十年,但整合一个员工的观点是多么困难。
在每一个这样的情况下,我们都看到,如果一个人变得有创造力,解决方案是存在的。org 系统生成了大量的数据踪迹。想象一下生物识别、闭路电视监控、内部网日志或支持传感器的智能办公室。所有这些数据都可以在不侵犯隐私或道德的情况下获得。
一家领先的全球咨询公司努力在其部门内共享最佳实践。对电子邮件收件人列表的分析(不使用任何内容)显示了清晰的模式。与其他部门不同,美国和欧洲的零售团队很少互动。其中一项行动是成立跨区域团队,促进交流。
Network traffic showing the exchange of emails amongst global teams in a Consulting firm
2.使用完整的数据科学工具箱,而不仅仅是高级分析
分析领域的对话总是从人工智能驱动的算法开始。人们谈论预测行为,甚至在理解他们的员工想要什么之前。在金字塔底部,甚至在分析工具箱中,也有一个与财富的概念相似的概念。
为了获得最大的业务影响,重要的是从简单开始,发现“发生了什么”和“为什么会发生”。一个人可以像水晶球一样凝视未来,去发现将会发生什么或者它将如何被影响。利用自下而上的全分析光谱是有价值的。
Classes of analytical techniques and the questions of interest
将近十年前,在 Gramener,我们对在哪里建立产品团队感到困惑。我们转向 Github 寻求一个简单的、数据驱动的解决方案,并且吃我们自己的狗粮。分析显示,与班加罗尔相比,大多数印度城市都相形见绌。
这座城市为高度网络化的 Python/Javascript 极客提供了一个充满活力的生态系统。有大量的人才,有足够的空间供将来推荐。那就是我们去的地方。
Github network of coders in Bangalore. Check full demo on the Gramener website
3。工具并不重要,重要的是方法
在开始分析计划时,组织会争先恐后地决定合适的工具。这通常是一个经典的分析案例——瘫痪优化工具的选择。假设是工具决定了可以创造的魔法的范围。一些好消息和坏消息。
好消息是,你不需要花哨的工具或昂贵的投资。坏消息是方法的质量决定了分析的真正价值。因此,它更加主观和依赖于人。正确的过程可能是一个推动者,但很大程度上取决于你的团队的质量。
与数据科学的任何应用一样,人力资源分析的价值在于解决方案。算法需要尽可能多的上下文和计算能力。例如,在构建预测员工流失的模型时,从所有可用的因素开始。然后,人们必须通过调查相关性和关系来仔细删减列表。
Decision tree model to predict employee churn at a Financial organization
以一家大型零售银行为例,该银行希望建立一个客户流失模型来管理员工流失。虽然决策树更容易解释,但逻辑回归的准确性更高。考虑到可解释性的需要,我们建议银行远离黑箱模型。
通过展示每个因素及其减少损耗的可能性,使解决方案变得可行。从下表可以明显看出,“参与 CSR 活动”是人员流失的最大影响因素之一。这因业务部门而异,其中“首选银行”的影响最大。
Factors that influenced attrition in a Bank, higher percentage indicates bigger impact
摘要
人力资源分析可以为组织带来巨大的价值。要充分利用这种力量并实现优势,您必须:
- 创造性地识别新的情报数据来源
- 利用完整的分析工具箱,从描述性见解开始
- 将业务背景和方法放在中心位置,以推动计划
为了确保这些建议真正被公开,要保持模型的可解释性和分析结果的可解释性。这是赢得决策者信心的关键。它还可以帮助人力资源利益相关者熟悉领导洞察驱动的干预。
这是我最近在纽约的 机器人& AI Meet 上 talk 的数据故事摘录。
以下是智能自动化如何帮助您的企业发展
原文:https://towardsdatascience.com/heres-how-intelligent-automation-can-help-your-business-grow-ebac81f67c25?source=collection_archive---------7-----------------------
在职业领域,重要的是放弃不再适合你的工具和传统。每个商业领袖都知道,为了在他们的特定行业保持相关性和盈利性,他们的公司适应不断变化的实践、技术和商业模式是非常重要的。
随着开发人员近年来在人工智能领域取得令人难以置信的进步,公司不断寻找最新的尖端软件,以帮助他们保持行业领导者的地位。或者,它可以通过智能自动化平台领先于竞争对手,以低成本在短时间内解决各种问题,从而帮助新兴公司达到竞争对手的高度。
这里有几个方法智能自动化可以帮助你的业务增长,使用能够提高投资回报率和增加公司运营规模的工具。
1)生产率更高,错误更少
智能自动化可以通过自动化枯燥、重复的任务并将脑力劳动留给人类工人来提高工作场所的生产率。零售商从这项技术中受益匪浅,因为一旦实施了机器人流程自动化(RPA)工具,他们的员工将不再需要花费大量时间来检查订单和校准数据。让这些技术发挥作用可以确保员工坚持创造性任务,在工作场所营造竞争氛围,最终提高生产力。
正确的软件还可以消除因花费数小时反复重复同一任务而产生的人为错误,这些错误会造成疲劳并降低工作成果的准确性。一个看似微不足道的错误可以成就或摧毁一家公司,给公司的软件工程师和会计服务带来噩梦。同时,智能自动化可以通过以高度准确的方式立即处理和分析订单和流程来简化操作,减少质量控制员工的工作量。
WorkFusion 提供了一个智能 RPA 系统,帮助公司实现他们的目标,该系统由执行重复任务的机器人组成。
2)优化您的营销工具
知道何时何地推销特定的产品或服务是企业成功的关键因素。营销一家公司的产品有很多方式,包括电子邮件活动、在线广告、网站设计和网络。智能自动化可以通过分析大量数据和优化营销活动,帮助需要推动的公司找到理想的营销解决方案。这项技术可以通过查看某个行业在特定类型的产品上的成功率来进行选择。
例如,人工智能可以帮助你以一种吸引消费者的方式改造网站,以正确的方式提供正确的内容,根据客户留下的数字足迹向他们推送信息。人工智能甚至可以自动创建内容,以极具吸引力的散文形式吸引消费者的兴趣。另外,你可以随时以任何你认为合适的方式干预和改变内容。
3)关注需要改进的地方
为了通过智能自动化提高您的投资回报率,您的公司必须确定您的弱点或最耗时的部分是什么。人工智能开发人员可以通过检查您的能力和进行差距分析来修复需要改进的关键领域。在某些情况下,现有的系统和流程将不得不被改变或剥离,以纳入人工智能。将旧数据库与新的人工智能系统集成可能需要一段时间,但一旦你做到了,你的生产率和投资回报率将呈指数级增长。
值得迈出的一大步
将尖端技术应用到您的业务中可能会在将旧数据转移到新数据的过程中引起一些剧变,但这是一个值得冒的险。通过成倍地减少您的人力工作量,提高您的营销技能并扩展您的业务计划中的薄弱领域,智能自动化将为您提供一系列解决方案,这些解决方案将提高您的底线并使您的员工专注于高价值的工作。
WorkFusion 为寻求升级软件的公司提供一系列商业产品,包括银行和金融服务、保险和商业解决方案。
以下是你如何在业务中利用深度学习的方法
原文:https://towardsdatascience.com/heres-how-to-leverage-deep-learning-in-your-startup-9204666a3272?source=collection_archive---------4-----------------------
深度学习是镇上的热门话题,这是理所当然的!它使许多新的创新成为可能,并赋予我们解决许多现实世界问题的能力。解决人们的问题为他们提供价值,并向客户提供良好的价值,这正是强大、盈利的企业的基础。
我们知道深度学习非常适合各种任务:语音识别、图像分类、聊天机器人和许多其他任务!但是我们如何利用 T2 的力量呢?你如何在你的业务中使用 it?在我指导您如何做到这一点时,我们将使用下面的流程图来直观地展示这一过程。
步骤#1: 获取您的数据
将深度学习集成到您的业务中的第一步是获取非常重要的数据!使深度学习能够如此好地解决有价值问题的主要来源是数据。最好的深度学习模型是基于 s 监督学习的,即它们需要大量的标记数据来实现如此高的性能。简而言之:如果我们想让我们的深度学习机器工作,我们需要给它大量的燃料;那个燃料是数据。
我有一些好消息要告诉你:大多数时候,这些数据都是现成的!已经有许多公开 可用标记的数据集,收集用于深度学习模型的训练,以应用于常见应用。有大量的数据用于分类图像,翻译语言,聊天机器人,无人驾驶汽车,以及更多可以用于您的应用程序的数据!这里有一个关于一些流行的深度学习数据集的快速资源:http://bit.do/Deep-Learning-Datasets
现在,如果在极少数情况下,您有一个真正特定的定制 应用程序,但没有大型公共数据集,该怎么办呢?…那我们就自己做吧!数据收集不再像以前那样具有挑战性。网 - 刮工具在这种情况下会非常好用。阿德里安·罗斯布鲁克有一个很棒的教程,教你如何自动抓取谷歌图片来构建你自己的数据集http://bit.do/Scrape-Your-Dataset。要标注大量数据,你可以像亚马逊的机械土耳其人一样使用crowd****sourcing!这里的目标是获得足够的数据来构建你的最小 可行 产品(MVP) 。
您可能想知道需要多少数据。衡量你需要多少数据的一个好方法是看一个类似的任务,看看别人用了多少数据来解决这个问题。那会给你一个很好的大概数字。除此之外,越多通常越好(只要你没有得到递减的回报!)!
第二步:构建你的深度学习产品
现在你已经有了你的标签数据,你可以完全构建你的产品。使用这些数据,你可以训练你的深度学习模型来执行一项任务,这项任务最终会为你的客户提供价值。深度学习模型在倾向于展示大量模式的重复性任务上最有效。因此,将重点放在自动化任务上,这些任务在所需的知识和执行上都非常重复,但通常也需要大量的人力或特定的技能。这样,你就最大化了价值你给了你的客户一些东西,如果没有你的深度学习驱动的产品,他们就不会拥有这些东西。
步骤#3:客户驱动的正反馈循环
在这个阶段,你已经完成了在业务中利用深度学习的几个关键步骤。你已经收集了你的数据,并用它来训练深度学习模型。然后,您使用该模型来推动您的产品,实现出色的性能并提供价值。现在进入过程中最强大的部分:正向****反馈 循环。****
你开始向顾客交付你的产品。有的喜欢,有的讨厌,都是一个学习的过程!非常重要的是,你的新客户现在也是一个新的数据来源,可以进一步改进你的深度学习模型和它们支持的产品!这里的关键是高效 采集新** 数据。******
当您第一次构建您的 MVP 时,您可能已经使用了公开可用的数据集,或者为您的定制产品收集了您自己的数据集。在这两种情况下,你的数据足以构建一个 MVP,但可能不足以优化 你的 产品。如果您使用公共数据集,该数据可能不够具体。也许你正在为你的家建造一个人脸识别安全系统,只有当系统识别出这个人的脸时,它才会开门。如果你使用的数据集只包含清晰的面部图片,那么它可能会在雨天或夜间失效;你让你的顾客被困在雨中!在另一种情况下,您已经收集了自己的数据集,您的目标是获得足够的数据来构建 MVP。在这两种情况下,你的模型都可能受益于拥有远 多 数据;一次又一次的研究证明,多 数据 有助于 提高 深度 学习 车型:https://arxiv.org/abs/1707.02968v2。
现在你的产品在付费客户手中,他们是你新数据的最佳 来源!您的客户会定期使用您的产品,通过这种使用,您可以获得更多的数据。还记得那次在雨中失败的人脸识别吗?为什么不利用这些失败来帮助训练你的深度学习模型表现得更好呢!你可以收集那些失败的案例,比如在下雨和晚上的时候,给它们贴上标签,然后使用新的数据来微调你的模型!每次你的系统犯了一个错误,它都会给你提供一个很好的机会:获取新的数据,标记它,然后训练你的模型从错误中学习。你甚至可以在成功的案例中这样做,收集数据并强化模型在这些情况下的表现。
这整个过程创造了一个积极 反馈 循环,你的客户是驱动它的人。更多的数据让你得到更好的产品,更好的产品让你得到更多的客户,而这些客户让你得到如此宝贵的数据来推动你的深度学习产品!
最后的话
所以你有它!通过这个过程,你可以建立一个支持防御业务的产品。一个由持续的数据循环推动的产品。由深度学习驱动的产品,为您的客户提供巨大价值。
以下是如何使用 Python 将数据预处理速度提高 2-6 倍的方法
原文:https://towardsdatascience.com/heres-how-you-can-get-a-2-6x-speed-up-on-your-data-pre-processing-with-python-847887e63be5?source=collection_archive---------5-----------------------
使用这 3 行代码,您的预处理速度提高了 2-6 倍!
想获得灵感?快来加入我的 超级行情快讯 。😎
Python 是所有机器学习的首选编程语言。它易于使用,有许多奇妙的库,使处理数据变得轻而易举!但是,当我们处理大量数据时,事情就变得更加棘手了。
如今,“大数据”一词通常指的是至少有几十万甚至百万个数据点的数据集!在这样的规模下,每一个小的计算都会累积起来,我们在对流水线的每一步进行编码时都需要考虑效率。当考虑我们的机器学习系统的效率时,一个经常被忽略的关键步骤是预处理阶段,在这里我们必须对我们所有的数据点应用某种操作。
默认情况下,Python 程序使用单个 CPU 作为单个进程执行。大多数为机器学习而制造的现代机器都有至少 2 个 CPU 内核。这意味着,以 2 个 CPU 内核为例,当您运行预处理时,默认情况下 50%或更多的计算机处理能力不会做任何事情!当您使用 4 核(现代英特尔 i5)或 6 核(现代英特尔 i7)时,情况会变得更糟。
但是值得庆幸的是,在一个内置的 Python 库中有一个隐藏的特性,让我们可以利用我们所有的 CPU 内核!多亏了 Python 的concurrent.futures
模块,只需要 3 行代码就可以将一个普通的程序变成一个可以跨 CPU 内核并行处理数据的程序。
标准方法
让我们举一个简单的例子,我们在一个文件夹中有一个图像数据集;也许我们甚至有成千上万张这样的图片!为了缩短处理时间,我们这里使用 1000。我们希望在将图像传递到我们的深度神经网络之前,将所有图像的大小调整为 600x600。这是你在 GitHub 上经常看到的一些非常标准的 Python 代码的样子。
这个程序遵循一个您在数据处理脚本中经常看到的简单模式:
- 您从想要处理的文件(或其他数据)列表开始。
- 使用一个
for
循环一次处理一条数据,然后在每次循环迭代中运行预处理
让我们在一个有 1000 个 jpeg 文件的文件夹上测试这个程序,看看它需要运行多长时间:
time python standard_res_conversion.py
我的 i7–8700k 有 6 个 CPU 内核,运行时间为 7.9864 秒!对于这么高端的 CPU 来说似乎有点慢。让我们看看我们能做些什么来加快速度。
最快的方法
为了理解我们希望 Python 如何并行处理事物,直观地思考并行处理本身是有帮助的。假设我们必须执行同样的任务,将钉子敲进一块木头,我们的桶里有 1000 颗钉子。如果我们说每个钉子需要 1 秒钟,那么用一个人我们可以在 1000 秒内完成这项工作。但是如果我们团队有 4 个人,我们会把桶分成 4 个相等的堆,然后团队中的每个人都会处理他们自己的钉子堆。用这种方法,我们只需 250 秒就能完成!
在我们有 1000 张图片的例子中,我们可以让 Python 为我们做类似的事情:
- 将 jpg 文件列表分成 4 个小组。
- 运行 Python 解释器的 4 个独立实例。
- 让 Python 的每个实例处理 4 组较小数据中的一组。
- 综合 4 个过程的结果,得到最终的结果列表
最棒的是 Python 为我们处理了所有困难的工作。我们只需告诉它我们想要运行哪个函数,以及要使用多少 Python 实例,然后它会完成所有其他的工作!我们只需要修改 3 行代码。
从上面的代码可以看出:
**with** concurrent.futures.ProcessPoolExecutor() **as** executor:
启动的 Python 进程和 CPU 内核一样多,在我的例子中是 6 个。实际的处理线是这样的:
executor.map(load_and_resize, image_files)
executor.map() 将您想要运行的函数和一个列表作为输入,其中列表的每个元素都是函数的一个单个输入。由于我们有 6 个内核,我们将同时处理列表中的 6 个项目!
如果我们再次运行我们的程序,使用:
time python fast_res_conversion.py
我们得到了 1.14265 秒的运行时间,接近 x6 的加速!
注意:产生更多的 Python 进程和在它们之间移动数据会有一些开销,所以你不会总是获得这么大的速度提升。但总的来说,你的速度提升通常会非常显著
总是超级快吗?
当您有一系列要处理的数据,并且要对每个数据点执行类似的计算时,使用 Python 并行池是一个很好的解决方案。但是,它并不总是完美的解决方案。并行池处理的数据不会以任何可预测的顺序进行处理。如果您需要将处理的结果按照特定的顺序排列,那么这种方法可能不适合您。
您正在处理的数据也需要是 Python 知道如何“处理”的类型。幸运的是,这些很常见。来自官方 Python 文档:
None
、True
和False
- 整数、浮点数、复数
- 字符串,字节,字节数组
- 仅包含可选择对象的元组、列表、集合和字典
- 在模块顶层定义的函数(使用
[def](https://docs.python.org/3/reference/compound_stmts.html#def)
,而不是[lambda](https://docs.python.org/3/reference/expressions.html#lambda)
- 在模块顶层定义的内置函数
- 在模块顶层定义的类
- 此类类的实例,其
[__dict__](https://docs.python.org/3/library/stdtypes.html#object.__dict__)
或调用[__getstate__()](https://docs.python.org/3/library/pickle.html#object.__getstate__)
的结果是可 picklable 的(详见章节 pick Class Instances)。
喜欢学习?
在推特上关注我,我会在这里发布所有最新最棒的人工智能、技术和科学!也请在 LinkedIn上与我联系!
以下是我从编写、编码和设计我自己的长篇数据驱动专题故事中学到的东西
原文:https://towardsdatascience.com/heres-what-i-learned-from-writing-coding-and-designing-my-own-longform-data-driven-feature-story-e8500ff10b43?source=collection_archive---------6-----------------------
“不择手段。”这个短语在历史上有了新的含义,从第一次出现在让-保罗·萨特的戏剧中,到出现在马尔科姆·Ⅹ关于民权运动的演讲中。
当我想到这个短语时,它是在一个完全不同的环境中。去年 9 月,我走进伦敦大学金史密斯校区,开始了我数字新闻硕士课程的第一天。在接下来的一年里,我和我的同学将学习如何使用数据可视化、多媒体视频和网络应用程序为网络创作身临其境的故事。我们的计算机教授告诉我们,如果我们坚持一个原则,我们永远不会走远:
不择手段。
加长版?从你想要结束的地方开始,然后用你自己的方式进行破解、测试、实验和编码(即使会变得很乱)。这就是我们学会的。
三个月前,我开始将我在课程中学到的一切汇编成一个故事:一篇长篇数据驱动的专题文章,从头开始编码(没有模板)。
最终结果来自于数小时的研究、采访、清理数据集、搜索 d3.js 示例、在代码不起作用时拔掉头发、喝几升咖啡和工作许多个深夜。
我的文章《一生的网络》讲述了美国网络中立性的变化,以及这些法规如何影响消费者使用互联网。我开始创作一个故事,其中包括整个作品的数据分析和可视化,滚动是主要的用户交互。
我不知道完成后会有什么感觉:我努力了这么久的东西,突然变得“完成”并到达终点。
现在,几个星期后,完成这个大型项目的压力已经消失了。我想分享一些我一路走来学到的最重要的东西。对于这种项目,新闻编辑室通常会让多个人来做这项工作:一名记者、一名数据记者、一名网站开发人员,也许还有一名文字编辑。这篇文章是关于我通过必须同时成为所有这些人而学到的东西。
用一个总计划提前规划你的计划
我知道这个项目需要我同时做很多不同的事情。大型项目有许多阶段和任务——计划和组织是必不可少的。所以在我开始写作或编码的几周前,我给自己制定了一个总体计划。这是草图,作为我的项目进度监视器。
我把每项任务分成一个类别,然后在截止日期前的几周内把它们分开。然后,在每个星期的开始,我会看到我想在那一周完成什么,以及哪一天我可以开始工作。
显然,这并不总是完美的……一些任务最终花费了比预期长得多的时间,而另一些则通过在网上找到一个快速的解决方案来检查。但是估计每项任务需要的时间是管理整个项目的关键。如果某项任务花费的时间比我预计的时间长得多,就需要做出一个艰难的决定:要么坚持到底,要么找一个更简单的方法来完成它。
尽早测试,经常测试
在这个项目开始的时候,我认为这个作品的创作过程大概是这样的:
除了我的总体规划之外,事情本该如此发展。但事实上,最终的重叠比我预期的要多得多。新闻不会为任何人停止。在我的最后一周,我仍然在研究关于网络中立的最新文章,这导致了故事中某些段落的添加或删除。我一边写代码,一边创建数据可视化,一边记录采访等。这是混乱的,并且不像上面的图表那样线性。
但更重要的是,在测试代码的最后两周,采用这种方法让我陷入了困境。由于我把大部分代码留到了最后,我发现自己在过去几天里忙着在不同的设备和浏览器上测试我的网页。
这导致了一个巨大的难题,如何让所有不同的图形和数据在移动设备上看起来清晰。回过头来看,我应该在创建网站的时候就开始测试,使用不同的设备,从移动布局优先的方法开始,而不是调整桌面来适应移动设备。
总是从情绪板开始
在这个项目的早期,我就开始拼凑一个情绪影响板来塑造页面的外观和感觉。这是我从在创意设计机构工作的人那里学到的一种做法。我粘贴了 NYT、FiveThirtyEight 和 Quartz 等出版商提供的我最喜欢的互动故事的链接和截图,以保存一些灵感。
从这个情绪板上,我将这些影响正式化,以创建适用于整个网页的规则。我的情绪板包括字体选项、一套调色板、笔画粗细、数据可视化示例和摄影风格。
这些预设也让我开始为我的设计选择赋予意义。例如,因为我有一个设置好的调色板,所以我可以将某些颜色定义为网页中图表的强调色,或者将某种字体仅用作注释。
值得注意的是,这个过程发生在我开始为这个网站写任何代码之前。一旦我开始编码,CSS 样式很容易开始应用,因为我已经在情绪板上决定了。这也确保了我的文本、图像和图形在整个故事中的一致性。
有意识地进行互动
交互性是我反复思考了很久的一个问题。这是新闻媒体正在进行的辩论,尤其是在数据可视化方面。但在阅读了该领域一些最聪明的人的言论后,我决定基于英国《金融时报》互动新闻主管马丁·斯塔贝(尽管最初是由布莱恩·博耶在推特上发布的)采纳的一条箴言,实施一种极简主义的互动方法。
如果一个图表不能从交互中获益,我就用 Tableau 构建它,用 Adobe Illustrator 添加注释来讲述故事。它可能不是华而不实的,但它加载速度快,显示数据有效,只是简单地完成工作。对我来说,问题变成了:用户能从悬停/点击/缩放中真正受益多少?如果回答不多,我把互动元素剪掉了。
也就是说,并不是所有的图表都是静态的。例如,我创建了一个大型散点图,显示 34 个不同国家的互联网价格和速度。交互性在这里似乎更有意义,这样用户就可以在他们感兴趣的国家的价值观上徘徊。所以这个我用了 d3.js。但由于焦点是美国泡沫的价值,我添加了一个注释来展示这些。
NYT 的图形编辑阿奇·谢(Archie Tse)对采用这种方法来注释数据中的要点有一个很好的引用。
如果你做了一个工具提示或者鼠标经过,假设没有人会看到它。—阿奇·谢
如果没有人看到其他泡沫的确切数值,这张图表仍然能传达我的信息。
我尝试实现的另一种交互形式是滚动。现在,这还没有达到像布丁或 NYT 图形团队这样的人制作的滚动故事的规模。但是因为用户自然会向下滚动页面,所以我尝试用这种方式在图形和页面元素之间转换。
给语境和意义提供机会
因为我正在讨论一个技术性很强的话题,所以我知道某些术语和话题需要解释。但与此同时,我不想用我文章的一半来解释零评级服务和内容分发网络等术语的含义。
我不得不假设一些人对网络中立的话题很熟悉,而另一些人对这场辩论还很陌生。所以我决定借鉴出版商最近使用的策略,在整个故事中提供额外的背景。一个很好的例子是《华盛顿邮报》的“知识地图”功能,它突出显示某些文本,当点击时,会打开一个包含相关背景信息的框。
在我自己的文章中,我采用了类似的方法,对用户可能想了解更多信息的人、术语或问题使用亮色。为了与常规链接区分开来,我还在高亮部分添加了一个小的报纸图标,以此来表示这将在网页中显示额外的信息。由于我为我的站点使用了 Uikit 框架,所以我通过滑动画布外 div 在页面上显示了这些上下文框。
Screenshot of context feature
无情地对待你的先入之见
在我开始这个项目之前,我对最终的故事有一个很大的计划。我在网上收藏并保存了一些精彩的故事,作为我的基准。这将是有史以来最伟大、最好、最惊人的视觉数据故事。
但现实是:我不是一名职业开发人员。大约一年半前,我才开始做一些简单的编码工作。我也不是设计师。我是一名数据记者,在我的工具箱里有几项关键技能来创作一个具有视觉冲击力的故事。所以我兜了一圈,回到我的课程口号:
不择手段。
当我开始构建我的故事时,我调整了我的志向以适应我的时间表和能力。这并不意味着当事情变得困难时我就放弃了;我花了大量的时间调试和搜索堆栈溢出来解决我的编码问题。有时我会取得重大突破。
但其他时候,我不得不无情地对待自己,并找到一种不那么“令人印象深刻”的方式来建立一些东西。我学会了挑战自己,学习新的技能和语言,同时也知道何时放弃,寻找不同的方式来实现我的目标。最后,故事总是要占据中心舞台,而不是华而不实的技术元素。
这最后一点可能是我学到的最重要的一点,但这篇文章绝不是详尽无遗的。在创建这个功能的整个过程中,我学到了很多关于时间管理、调试代码和为 web 编写长格式功能的知识。
但我知道我并不孤单。视觉新闻和用数据讲故事正在媒体中兴起,这些技能正迅速从可选变为推荐。我希望我在黑进一个数字专题故事的过程中所学到的这些经验可以帮助那些需要做同样事情的人。
终生的网络是使用以下工具/资源创建的:
- Uikit
- 卷轴魔法
- jQuery
- D3.js
- C3.js
- (舞台上由人扮的)静态画面
- Adobe Illustrator
好奇更多?取得联系。
原载于 2017 年 7 月 28 日Benjamin cooley . me。
“英雄”:IT 基础设施的未来
原文:https://towardsdatascience.com/heroes-the-future-of-it-infrastructure-a426b69090a7?source=collection_archive---------11-----------------------
Logo de la série Heroes
预计未来几年的变化是巨大的、无情的、快速的。未来五年将比过去 50 年带来更多变化。随着传统企业适应新机器时代的现实——令人窒息的上市时间、智能增强的一切、有意义和个性化的体验——这对 IT 的影响是深远的。毫不夸张地说,当今成功企业的核心优势在于其 It 基础设施的就绪性,而不灵活、迟缓、低效的基础设施比任何有独创性的初创企业或破坏性的市场力量都构成更大的竞争威胁。
虽然服务器、数据库和电缆等传统 IT 行业仍然重要,但它本质上已经成为一种公用事业,让位于对敏捷、灵活和可快速扩展的技术基础的需求,以推动业务发展。因此,采用遗留技术架构的公司面临着一个两难的境地:在 IT 基础设施的当前和未来状态之间取得平衡。为了达到这种平衡,首先要抛弃的是 IT 传统上对削减成本的痴迷。一个简单的事实是,一个成本较低但完全不相关的主干网会让你在任何市场中亏损。在一个初创企业可以在几周或几个月内颠覆整个行业的时代,一家公司的技术骨干应该——事实上,必须——赋予它立即适应的能力(和敏捷性),或者更好的是,设定节奏。
根据我们在的最新研究,在新机器时代,重要的是优先考虑网络安全、创新、上市时间和客户体验,而不是削减成本。在接下来的 24 到 36 个月中,我们将看到 IT 组织发展到一个新的阶段,在这个阶段中,他们将采用一套与以往完全不同的指标进行衡量。IT 任务将超越我们熟悉的满足客户和员工、与企业协作和降低成本的领域,扩展到巩固客户关系、发现新的业务价值、实现业务灵活性和创新,同时确保安全性。
我们开发了一个被称为“英雄的框架,帮助首席信息官系统地转向新的 IT 工作方式,并最大化其 IT 投资的战略价值。该框架涉及五个领域的变革:混合云架构、边缘计算、机器人流程自动化(RPA)、旧 IT 的淘汰和企业安全。英雄框架的所有五个领域都将受到人工智能(AI)技术日益增长的影响,这将“升级”现有的 IT 基础设施,并为未来奠定基础。事实上, 61%的高管认为人工智能将在未来五年内从根本上改变他们的 IT 基础设施采购和消费模式。简而言之,人工智能将成为新 IT 基础设施的核心。
从明天开始:我们可以成为“英雄”
IT 部门只负责基础架构和运营,并坚持不懈地致力于降低成本的日子已经一去不复返了。那些认为 IT 是昂贵的开销而不是竞争能力的企业将很难在新机器时代取得成功。对于首席信息官来说,改变 IT 部门的这种思维模式,然后将这种想法推销给公司的其他部门,既是挑战也是机遇。
正如平板电脑、智能手机和应用商店引领了 IT 的消费化一样,我们的英雄框架,辅之以人工智能,可以帮助企业找到通往未来的道路。抓住这一变革时刻的业务和技术领导者将在未来 IT 价值的转变中占据前排位置。
查看我们的新报告IT 基础设施的未来,深入了解领导者在其组织的技术基础设施中正在进行的变革,以及 IT 工作、运营、绩效指标和工作的转变性质,以重新适应数字时代。
Manish 领导 Cognizant 亚太和中东未来工作中心。作为一名受人尊敬的演说家和思想家,Manish 用他发人深省的研究和咨询技巧引导许多财富 500 强公司走向工作的未来。他可以在manish.bahl@cognizant.com| @ mbahl |https://www.linkedin.com/in/manishbahl/
嘿谷歌,我的宠物在哪里?张量流对象检测贡献
原文:https://towardsdatascience.com/hey-google-where-is-my-pet-tensorflow-object-detection-contribution-9c1d1fdd0443?source=collection_archive---------8-----------------------
使用谷歌助手 /Google Home 是每天让我的家居生活更加灵活的东西。
我们还知道,计算机视觉学科为家庭安全领域提供了越来越多的支持。除了手动/半手动监控的传统元素之外,安全摄像机还有许多使用案例。借此机会,我想分享一个我家安全系统的经验。
挑战
我想与我的 Google Assistant/Google Home 系统交互以给出指令…并使用我的 cam 安全系统和 TensorFlow 的功能创建一些东西来定位我的宠物。
这个提议
所以,让我们使用谷歌助手动作,TensorFlow,计算机分析的力量,与相机系统的集成和云处理的力量。用这个…减少问题,只说一句话。
嘿谷歌,我的宠物在哪里?
example architecture
*作为摄像系统,我使用了爱洛。[顺便说一下非常好的硬件,具有灵活的硬件和非常稳定。].在混凝土阿洛 Pro 2。
此实施的预计步骤顺序如下:
- 通过 Google Assistant 【跨 Google Home 或通过电话】进入服务。在家庭环境中灵活使用语音指令非常方便[ Article 关于此组件的更多信息。].该实现将与组件ArloCamService的 webhook 连接。[ Github ]
- “ArloCamService”服务负责定位可用的相机,拍摄照片并发送给TensorPhotoXRayGithub。*在该组件中,我们分析图像并提取检测中最有把握的对象。
- 然后只剩下确定是否存在与所寻找的项目的匹配,并将该消息返回给用户。
让我们看看示例实现是如何工作的:
testing implementation using Google Assistant
ArloCamService 会发生什么?
该组件与爱洛相机系统连接,在本例中,我们仅使用照片。
*在这个组件上还有很多工作要做,但是对于我们的例子来说,它是功能性的。【 Github 】。文章提供了关于该组件的更多信息。
张量光电射线会发生什么?
该组件接收照片,用通用模型或个性化模型对其进行分析。
这是一个直观的例子:
然后它提供一个标签列表和它们的信任值,这里有一个例子。
[{ "人":97}、{ "椅子":95}、{ "人":95}、{ "沙发":92}、{ "椅子":82}、{ "电视":81}、{ "电视":81}、{ "椅子":79}、{ "狗":76}、{ "书":65}]
*在这个组件上还有很多工作要做,但是对于我们的例子来说,它是功能性的。[ Github ]
很多时候,我们有非常好的技术,或者非常好的技术,但是这些技术本身缺乏区别意义。添加一些元素并混合,我们可以为每天都在寻找更智能解决方案的用户创造出一些令人惊叹的东西。
这种实现将计算机视觉与在家庭环境中做出不同贡献的目标相结合。你能想到其他的用例吗?我希望你和我一样喜欢这个实施方案。
隐藏在文本之下:马云退休信与埃隆·马斯克私有化信分析
原文:https://towardsdatascience.com/hidden-beneath-texts-analytics-of-jack-ma-retirement-letter-and-elon-musk-s-privatization-letter-85ec2af4a2db?source=collection_archive---------9-----------------------
9 月 10 日对于中国互联网行业来说是一个非常重要的日子。首富、阿里巴巴董事局主席马云发出了他的退休信,宣告中国最大互联网帝国的新时代即将到来。
一个月前,特斯拉首席执行官埃隆·马斯克(Elon Musk)也发出了一封震惊股市的信。在信中,他表达了将特斯拉私了的意图。最终私有化计划没有做成,但还是在商业圈引起了一些涟漪。
我刚刚想到,这两封信对股市造成了如此大的影响,它们被不同的媒体广泛报道。我只是想知道我是否可以尝试破解这两封信的文本数据。通过一些简单有趣的文本分析和我在夏天学到的技巧,我想在文本下面提供一些发现。这两位伟大的首席执行官是正面还是负面看待他们的帝国?从这两封信中可以看出对阿里巴巴和特斯拉的主要关注点和愿景是什么?这些想法真的很吸引我。所以我只是在网上找到文本,开始破解数据,看看我是否能从中挖掘出一些黄金。
阿里巴巴马云退休信:【https://www.bloomberg.com/technology】T2
特斯拉埃隆马斯克私有化函:http://fortune . com/2018/08/07/Tesla-Elon-Musk-Letter-to-employees-Tesla-stock-tsla/
步骤 0:加载所需的包
准备步骤是加载一些包。我使用 python 包 NLTK 进行文本分析,使用 WordCloud 制作一些可视化的图形。
import pandas as pd
import nltk
from nltk.tokenize import RegexpTokenizer
from nltk.sentiment.vader import SentimentIntensityAnalyzer
from wordcloud import WordCloud, STOPWORDS
import matplotlib.pyplot as plt
步骤 1:加载数据和文本字典
对于文本情感分析,我使用了两种方法进行分析。第一个是 Loughran 和 McDonald 正面和负面词典(LMD),它广泛用于商业演讲、文档或公告的情感分析。另一个是 NLTK 包中内置的 SentimentIntensityAnalyzer。
下面的代码是我如何在 LMD 加载。(词典文本文件很容易在网上找到)
# Positive Words Dictionary
with open('LM_pos_words.txt', 'r') as f:
pos = f.read().replace('\n',',')
tokenizer = RegexpTokenizer(r'\w+')
pos_token = tokenizer.tokenize(pos)
pos_token = [word.lower() for word in pos_token]# Negative Words Dictionary
with open('LM_neg_words.txt', 'r') as f:
neg = f.read().replace('\n',',')
tokenizer = RegexpTokenizer(r'\w+')
neg_token = tokenizer.tokenize(neg)
neg_token = [word.lower() for word in neg_token]
在加载了所需的文本字典后,马云和埃隆马斯克的信件文本也需要加载。我们用记号赋予器来看你,两个字母里有很多单词。
## Load in Jack Ma's retirement Letter
with open('Jack Ma_retire.txt', 'r',encoding="cp1252") as f:
lines = f.read().replace('\n', '')tokenizer = RegexpTokenizer(r'\w+')
tokens = tokenizer.tokenize(lines)
len(tokens)
# It contains 1036 words## Load in Elon Musk's Privatization Letter
with open('Elon_private.txt', 'r',encoding="cp1252") as f:
lines_17 = f.read().replace('\n', '')
tokenizer = RegexpTokenizer(r'\w+')
tokens17 = tokenizer.tokenize(lines_17)
len(tokens17)
# It contains 634 words
第二步:信件中的信息
我决定为字母绘制一些简单的单词云。从词云可以突出一些信息。它可能揭示了一个领导者对自己公司的一些看法和想法。
首先,我们需要设置停用词,这有助于消除文本中的一些噪音。
stopwords = set(STOPWORDS)
然后我们为马云的退休信和埃隆马斯克的信构建词云。
# Jack Ma's letter
wordcloud_ma = WordCloud(width = 600, height = 600,
background_color ='white',
stopwords = stopwords,
min_font_size = 10).generate(lines)plt.figure(figsize = (8, 8), facecolor = None)
plt.imshow(wordcloud_ma)
plt.axis("off")
plt.tight_layout(pad = 0)
plt.show()# Elon Musk's letter
wordcloud_elon = WordCloud(width = 600, height = 600,
background_color ='white',
stopwords = stopwords,
min_font_size = 10).generate(lines_17)plt.figure(figsize = (8, 8), facecolor = None)
plt.imshow(wordcloud_elon)
plt.axis("off")
plt.tight_layout(pad = 0)
plt.show()
图表如下所示:
Jack Ma’s letter- Word Clouds
Elon Musk’s letter-Word Cloud
在这两个图表中,两家公司的名称都被突出显示。对于不同的部分,我们可以看到,杰克强调了一些词,如“文化”、“人才”、“使命”、“合作伙伴”和“人”,而埃隆·马斯克更强调“股东”、“员工”、“结构”、“股票”、“私有”和“保留”
我们可以看到这封信与目标读者的巨大不同。尽管这两封信都是公开的,但不知何故,杰克更多地瞄准了阿里巴巴的内部人才和外部合作伙伴。他非常强调未来的使命,这可能预示着阿里巴巴将继续在互联网行业的使命和火炬。
然而,埃隆·马斯克主要是先针对股东,然后才是员工。在信中,他似乎被动地说服利益相关者,他可能会为他们做一些最好的建议,一切将保持不变(T2 )( T4 )()的结构(T5)。
第三步:LMD 的情感分析
然后我开始对 LMD 进行情感分析。开始时,我试图去掉停用词和数字文本。
# Clean the stop word and number of Jack Ma's letter
fdist = nltk.FreqDist(tokens)
stop_word = []
for word, freqency in fdist.most_common(10):
stop_word.append(word)
tokens_n_s = [word for word in tokens if word not in stop_word]
tokens_n_s = [word for word in tokens_n_s if not word.isnumeric()]
tokens_n_s = [word.lower() for word in tokens_n_s]
然后,我们可以开始计算字母的积极和消极的话。
token_pos_ma = [word for word in tokens_n_s if word in pos_token]
token_neg_ma = [word for word in tokens_n_s if word in neg_token]len(tokens_n_s) # 758
len(token_pos_ma) # 31
len(token_neg_ma) # 7
情感计算如下所示:
Sentiment%: (# of Positive - # of Negative) / # of text(cleaned)
Negative%: # of Negative / # of text(cleaned)
我应用了与埃隆·马斯克的信相似的代码,并绘制了下面的结果。
从图表中,我们可以看出,有了 LMD 文本词典。马云信中的积极情绪远远高于埃隆·马斯克。负面情绪颇为相似。
我们可以通过信件查阅。杰克对公司的未来发展非常乐观;然而,埃隆·马斯克可能对特斯拉有一些负面和悲观的看法。
步骤 4:使用 NLTK 情感分析器进行情感分析
为了给出一个更具可比性的视角,我决定用 NLTK 内置的分析器进行情感分析,以掌握两封信的积极和消极情感。
sid = SentimentIntensityAnalyzer()# Jack Ma's letter
scores = sid.polarity_scores(lines)
for key in sorted(scores):
print('{0}: {1}, '.format(key, scores[key]), end='')## compound: 0.9997, neg: 0.007, neu: 0.771, pos: 0.221,# Elon Musk's letter
scores_elon = sid.polarity_scores(lines_17)
for key in sorted(scores_elon):
print('{0}: {1}, '.format(key, scores_elon[key]), end='')## compound: 0.9975, neg: 0.039, neu: 0.812, pos: 0.149,
结果如下所示:
反差巨大。对马云信的正面情绪高于埃隆马斯克,负面情绪低于埃隆马斯克。从这两个使用不同方法的图表中,我们可以从文本和分析中得出结论。在这封信发布的时候,特斯拉可能会遇到一些问题,而阿里巴巴仍在朝着良好的方向发展。
一些反映
将这两个文本进行比较是一个随机的想法,对我来说令人惊讶的是,分析展示了一些有趣的发现。希望你喜欢阅读,这些文章给你一些不同的视角来看这些公告。有时候,信不仅仅是信。它可能会给你公司未来的一些提示。
If you like the article, feel free to give me 5+ claps
If you want to read more articles like this, give me 10+ claps
If you want to read articles with different topics, give me 15+ claps and leave the comment hereThank for the reading
用于时间序列分类的隐马尔可夫模型——基本概述
原文:https://towardsdatascience.com/hidden-markov-models-for-time-series-classification-basic-overview-a59b74e5e65b?source=collection_archive---------0-----------------------
注:需要 HMMs 的基础知识。
最近,我一直在努力理解 HMMs 训练和识别特别有趣的时间序列数据集(美国手语)背后的魔力。在这篇文章中,我想对这个过程中的步骤做一个高层次的概述,经过详细的研究,我终于掌握了这个过程。
首先让我们看看数据。单个数据点(ASL 中的单个单词)由分散在离散时间帧中的值组成。
假设我们想要建立一本单词书的模型。我们查看数据集,注意到有三个时间序列对应于图书。我们将 HMM 建立在这三个例子的基础上。
训练前要做的一个重要步骤是决定状态的数量。我们可以凭经验做到。如果我们观察单词书的一个数据点的图,我们可以得出结论,说话者的手通过三个序列进行转换。
因此,我们的隐马尔可夫模型应该包含三个状态。稍后,我们可以用不同数量的状态训练另一个图书模型,比较它们(例如,使用 BIC 惩罚复杂性并防止过度拟合)并选择最佳的一个。现在我们只关注三态 HMM。
每个状态都有两种可能性(都有一定的概率):我们要么保持当前状态,要么进行转换。下面的箭头说明了这个概念。
我们稍后将回到这一点。现在我们将分配适当的高斯分布,它最适合给定状态下的数据。让我们假设来自训练集的单词书的三个示例在离散时间帧上的以下值:
先说一个叫维特比对齐的方法。它开始于将所有的例子大致相等地划分成 3 个群(3 个状态)。
接下来,我们计算每个聚类段的正态分布参数(平均值和标准偏差)。
基于 Z 值,我们稍后查看相邻值,考虑它们对给定分布的适合度,并在必要时更改红色边界。
在反复运行这个方法后,我们得到了对值分布的良好估计。然而,我们可以使用期望最大化算法做得更好,该算法根据正确分布的概率为每个值分配一个权重(P(平均值,标准偏差|值))。我们可以使用贝叶斯定理和给定特定分布(P(value | mean,standard deviation))的值的概率公式来推导。如果我们幸运的话,以下是我们到目前为止可以实现的目标:
以下是具有适当边界的聚类值:
现在让我们再次考虑第一个完整片段。我们可以注意到,在每个序列中有一个值,在这个值之后,我们转换到下一个状态。
如果我们把第一段的所有值都扔进一个盒子里,并试着从三个值中抽取一个,导致转换到下一个状态,我们有多大的机会?概率有多大?实际上很容易计算:3/20 = 0.15 (20 是段中值的总数)。抽取任何其他值(导致停留在第一状态)的概率是互补的(1–0.15 = 0.85)。你猜怎么着?我们刚刚计算了我们的转移和停留概率!让我们将它们添加到模型中。
恭喜你!我们刚刚为单词书训练了三态 HMM。下一步是检查测试时间序列的可能性,比如说:
为此,我们将模型分解为维特比路径,这些路径表示测试时间序列中所有可能的运动(包括转换和停留)。请注意,在下图中,概率仍然保持不变,我们忽略了无法到达最后状态的路径:
在最终计算之前,我们需要添加基于我们之前为每个状态导出的正态分布的时间序列值的概率:
最后一步是计算测试时间序列符合我们的图书模型的可能性。为此,我们将路径上的所有概率相乘,并选择最有可能的一个(具有最大概率)。这些概率往往很小,所以你经常会看到这种计算的对数版本。
所选路径的概率:
0.8 * 0.85 * 0.8 * 0.15 * 0.5 *0.3 * 0.4 * 0.375 = 0.0002754
识别过程基于从不同模型中比较给定时间序列的最佳路径可能性,并选择最高的一个。
层次聚类及其应用
原文:https://towardsdatascience.com/hierarchical-clustering-and-its-applications-41c1ad4441a6?source=collection_archive---------3-----------------------
聚类是数据科学中最著名的技术之一。从客户细分到异常值检测,它有着广泛的用途,以及适合不同用例的不同技术。在这篇博文中,我们将看看层次聚类,这是聚类技术的层次化应用。
使聚集
用一句话来说,聚类就是提取相似数据对象的自然分组。
Republican and Democrat clusters of senators
关于集群,有几个常见的想法:
- 聚类应该自然地出现在数据中。
- 聚类应该发现数据中隐藏的模式。
- 聚类中的数据点应该是相似的。
- 两个不同聚类中的数据点不应相似。
用于聚类的常见算法包括 K 均值、DBSCAN 和高斯混合模型。
分层聚类
如前所述,层次聚类依赖于使用这些聚类技术来寻找聚类的层次结构,其中该层次结构类似于树结构,称为树状图。
层次聚类是基于组相似性的数据的层次分解
查找分层聚类
有两种顶级方法可以找到这些层次聚类:
- 聚集聚类使用自下而上的方法,其中每个数据点从自己的聚类开始。然后,通过将两个最相似的聚类放在一起并合并,贪婪地将这些聚类结合在一起。
- 分裂式聚类使用一种自顶向下的方法,其中所有数据点都在同一个聚类中开始。然后,您可以使用 K-Means 之类的参数聚类算法将该分类分成两个分类。对于每个集群,您进一步将它分成两个集群,直到达到所需的集群数量。
这两种方法都依赖于在所有数据点之间构建相似性矩阵,这通常通过余弦或 Jaccard 距离来计算。
层次聚类的应用
1)美国参议员通过 Twitter 聚集
我们能通过 Twitter 找到政党路线吗?
继有争议的“Twitter 情绪预测股市”论文之后,研究人员一直将 Twitter 视为极具价值的数据来源。在这个例子中,我们使用 Twitter 将美国参议员分组到他们各自的党派中。
我们的数据很简单:我们只看哪个参议员跟着哪个参议员。它定义了一个图结构,以参议员为节点,以随从为边。
在这个图中,我们使用了由 Pons 等人提出的 Walktrap 算法,该算法在图中进行随机遍历,并通过从一个参议员开始到某个参议员的次数来估计参议员相似度。
在获得这些相似性之后,我们可以使用凝聚聚类来找到树状图。
Reds are Republicans, Blues are Democrats, Blacks are independent
为了衡量我们的聚类效果如何,我们可以用聚会的颜色来给结果着色。正如你所看到的,民主党人和共和党人从顶部非常明显地分裂,显示了这种方法的成功。
你可能也注意到了两条黑线,代表独立参议员。这些都是有点棘手的评估,但参议员伯尼·桑德斯和参议员安格斯金党团与民主党,这意味着这是自然的,他们在民主党的分支树。
2)通过系统进化树绘制进化图
我们如何将不同的物种联系在一起?
在 DNA 测序可靠之前的几十年里,科学家们努力回答一个看似简单的问题:大熊猫更接近熊还是浣熊?
如今,我们可以利用 DNA 测序和系统聚类来寻找动物进化的进化树:
- 生成 DNA 序列
- 计算所有序列之间的编辑距离。
- 基于编辑距离计算 DNA 相似性。
- 构建系统进化树。
这项实验的结果是,研究人员能够把大熊猫放在离熊更近的地方。
3)通过系统发生树追踪病毒
我们能找到病毒爆发的源头吗?
追踪病毒爆发及其来源是一项重大的健康挑战。追踪这些疫情的源头可以为科学家提供更多的数据,说明疫情开始的原因和方式,从而有可能挽救生命。
像艾滋病毒这样的病毒具有很高的突变率,这意味着同一种病毒的 DNA 序列的相似性取决于它传播的时间。这可以用来追踪传播途径。
这种方法在一个法庭案例中被用作证据,在该案例中,与对照组相比,发现受害者的艾滋病毒链与被告患者的更相似。
V1–3 are victim’s strands, P1–3 are accused patient’s, and LA1–12 are the control group
一项类似的研究也是为了寻找给人类带来 SARS 病毒的动物:
所以人类从果子狸身上感染了 SARS 病毒…对吗?
image source
“有了手头的数据,我们可以看到病毒是如何利用不同的宿主的,按照这个顺序,从蝙蝠到人类再到果子狸。所以果子狸实际上是从人类那里感染了非典——科学日报
结论
分层聚类是一种强大的技术,它允许您从数据相似性中构建树结构。现在,您可以看到不同的子分类之间的关系,以及数据点之间的距离。请记住,这些相似性并不意味着因果关系,就像棕榈果子狸的例子一样,您将拥有另一个工具。
参考
- Anasse Bari 博士的大数据科学(NYU)讲座幻灯片
- 生物信息学(Bogazici 大学)Arzucan Ozgur 博士的讲稿