TowardsDataScience-博客中文翻译-2020-六十二-
TowardsDataScience 博客中文翻译 2020(六十二)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
如何在 Jupyter 中创建交互式下拉列表
原文:https://towardsdatascience.com/how-to-create-an-interactive-dropdown-in-jupyter-322277f58a68?source=collection_archive---------15-----------------------
用下拉菜单更新图表
杰瑞米·托马斯在 Unsplash 上拍照
**Table of Contents**[**Introduction**](#b6ac)1\. [Libraries](#0ba4)
2\. [Data Setup for the Dropdown](#9ef9)
3\. [Multiple Plot Function](#bd3b)
4\. [Interactive Dropdown Menu](#b2ef)
5\. [All the Code](#14d0)
6\. [Using for Other Datasets](#6829)[**Conclusion**](#08ef)
介绍
在上一篇文章的中,我写了如何使用 Plotly.express 和 Mapbox 创建气泡图。气泡图可以在一张地图上显示不同大小的所有数据。
在这篇文章中,我将写一个使用下拉菜单的交互式图表。
当您有一系列数据集并希望将一个数据集与其他数据集分开时,此方法非常有用。
我在这篇文章中使用的是 CSSEGISandData 的新冠肺炎 Github repo。
图书馆
import pandas as pd
import numpy as np
import plotly.graph_objects as go
pandas 是一个快速、强大、灵活且易于使用的开源数据分析和操作工具。Numpy 是用 Python 进行科学计算的基础包。 Plotly 是一个交互式的开源 Python 图形库。
下拉列表的数据设置
让我们开始准备数据集。我们将使用时间序列数据,你可以在这里找到原始数据。
创建一个变量confirmed_global
,使用 Panda 的 read_csv 将数据存储到covid19_confirmed
中。我们将索引列设置为国家/地区,并显示数据帧。
# confirmed_global
confirmed_global='https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv'covid19_confirmed=pd.read_csv(confirmed_global,index_col='Country/Region')display(covid19_confirmed)
(图 1)covid 19 _ 已确认。作者图片
有 266 行。这在索引中有Country/Region
,在标签上有Lat
、Long
和日期。
我们将从数据帧中提取最新的日期。我们转置数据集,covid19_confirmed(图 1),使用T
并显示最后 5 行。Pandas 的转置通过将行写成列来反映数据帧的主对角线,反之亦然。
display(covid19_confirmed.T.tail())
(图 2)covid 19 _ 已确认。T.tail()。作者图片
转置的数据帧在索引中有日期,在标签中有国家名称。
我们在索引栏的末尾找到了最新的日期。我们可以使用index.values[-1]
提取最新的日期。
confirmed_latest = covid19_confirmed.T.index.values[-1]
display(confirmed_latest)
输出:“2010 年 6 月 9 日”
有多行具有相同的Country/Region
。
(图 3)covid 19 _ 已确认。作者图片
我们可以在上面的图 3 中找到澳大利亚的 8 行。
我们通过Country/Region
将它们分组在一起,并计算总和。
df_grouped_conf=covid19_confirmed.groupby('Country/Region').sum()display(df_grouped_conf.head(10))
这是前 10 行。
(图 4) df_grouped_conf。作者图片
以前我们有 266 行,现在我们有 142 行。澳大利亚有一排。
df_grouped_conf
(图 4)的末尾是最新的日期(本例中为 6/9/20)。
(图 5) df_grouped_conf。作者图片
我们将使用ascending=False
按照这个值confirmed_latest
对数据帧进行排序。我们使用head(10)
选择前 10 个国家,并删除Lat
和Long
列。我们在最后使用T
转置数据帧。
df_confirmed=df_grouped_conf.sort_values(confirmed_latest,ascending=False).head(10).drop(['Lat', 'Long'],axis=1).T
(图 6)df _ 确认。作者图片
[## 如何在 Docker 上运行 Jupyter 笔记本
不再有 Python 环境和包更新
towardsdatascience.com](/how-to-run-jupyter-notebook-on-docker-7c9748ed209f) [## 如何在 Jupyter 中创建一个有吸引力的气泡图
从 Github repo 抓取数据的分步指南
towardsdatascience.com](/how-to-create-an-attractive-bubble-map-5cf452c244e9)
多重绘图功能
我们可以在这里找到其他情节性的下拉示例。
我们创建了一个名为 multi_plot 的函数。这需要两个变量:
df
:以国家为列,以行为日期的数据框addAll
:布尔型。True 在下拉按钮中显示全部。全部一次显示所有国家。我们设置默认的True
。
我们创建一个plotly.graph_objects
的人物的实例。
我们使用 for 循环来迭代通过df.columns.to_list()
获得的县名。
df.columns.to_list()
返回一个列表,['美国','巴西','俄罗斯',…]。
在迭代中,我们向图中添加一个轨迹。您可以使用plotly.graph_objects.Scatter
或plotly.graph_objects.Bar
进行跟踪,我们将使用Scatter
。
我们定义了x
、y
和name
。name
参数设置一个trace name
。trace name
显示为图例项并处于悬停状态。
def multi_plot(df, title, addAll = True):
fig = go.Figure() for column in df.columns.to_list():
fig.add_trace(
go.Scatter(
x = df.index,
y = df[column],
name = column
)
)
// continue
我们定义一个字典button_all
和函数create_layout_button
,在[update_layout](https://plotly.com/python-api-reference/generated/plotly.graph_objects.Figure.html?highlight=update_layout#plotly.graph_objects.Figure.update_layout)
中使用。update_layout
更新图形布局的属性并返回图形对象。
在fig.update_layout()
方法中,我们使用updatemenus
,它是plotly.graph_objects.layout.Updatemenu
实例的元组。
我们还将yaxis_type="log"
设置为在 y 轴上显示对数刻度,并将height
设置为 400px。
// continue
button_all = dict(label = 'All',
method = 'update',
args = [{'visible': df.columns.isin(df.columns),
'title': 'All',
'showlegend':True}]) def create_layout_button(column):
return dict(label = column,
method = 'update',
args = [{'visible': df.columns.isin([column]),
'title': column,
'showlegend': True}]) fig.update_layout(
updatemenus=[go.layout.Updatemenu(
active = 0,
buttons = ([button_all] * addAll) + list(df.columns.map(lambda column: create_layout_button(column)))
)
],
yaxis_type="log"
)
# Update remaining layout properties
fig.update_layout(
title_text=title,
height=800
)
fig.show()
交互式下拉菜单
最后一部分是使用 multi_plot 函数。
multi_plot(df_confirmed, title="Logarithmic COVID-19 time series total confirmed by country")
交互式下拉菜单
所有的代码
用于其他数据集
CSSEGISandData 的新冠肺炎 Github repo 还有两个数据集。您可以使用相同的代码创建其他图形。
你可以在这里看到现场直播。
[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv')
Covid19 时间序列全球死亡
[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv')
Covid19 时序全球复苏
结论
你可能会发现 Plotly 有太多的参数,有时令人困惑。但是示例代码提供了各种示例,您可以将其用于您的数据科学项目。
通过 成为 会员,可以完全访问媒体上的每一个故事。
https://blog.codewithshin.com/subscribe
[## 如何用 Python 中的 Plotly Express 创建分组条形图
Python melt 函数将数据帧从宽到长格式化
towardsdatascience.com](/how-to-create-a-grouped-bar-chart-with-plotly-express-in-python-e2b64ed4abd7) [## 如何用不到 15 行代码创建一个动画的 Choropleth 地图
在 Jupyter 上使用 Python 中的 Plotly Express
towardsdatascience.com](/how-to-create-an-animated-choropleth-map-with-less-than-15-lines-of-code-2ff04921c60b) [## 如何在 Jupyter 中创建动画条形图
使用 Plotly Python 显示最新美国失业率的数据可视化
towardsdatascience.com](/how-to-create-an-animated-bar-chart-in-jupyter-9ee1de8d0e80)
如何用 Python 创建一个交互式创业成长计算器
原文:https://towardsdatascience.com/how-to-create-an-interactive-startup-growth-calculator-with-python-d224816f29d5?source=collection_archive---------44-----------------------
使用 Python 为您的创业构建实用的度量
泰勒·弗兰塔在 Unsplash 上拍摄的照片
动机
如果你正计划创建一家创业公司或者已经有了一家,对你的跑道和你需要达到的增长率有一个现实的预期将帮助你调整你的方法,以防止你的创业公司耗尽资金。作为一个数据爱好者,你可以使用 Python 创建一个简单的计算器来实现这个目标。
从上图中可以看出:
- 蓝色区域是剩余的现金
- 紫色线是月收入
- 橙色线是所有收入的累计总和
如果你的增长率是每月 0%,你的初创公司将在 2021 年 6 月耗尽现金。如果增长率是每月 30%,你的创业公司将在 2021 年 8 月耗尽现金。
如果您想创建一个类似于 this 的计算器,只需克隆这个 repo 。有关安装、设置和代码解释的说明,请参见下文。
为计算器设置
要创建这个计算器,你只需要一些基本的信息和简单的工具来创建一个创业成长计算器:
参数:
- 你在银行里有多少现金
forecast_length_years
:图表上显示的年数weekly_growth
:你目前的周增长率initial_revenue
:初始收入monthly_burn
:每月费用cash_injection
:现金注入(即 R & D,筹资)(可选)cash_injection_offset
(可选)
工具:
- Altair:Python 的可视化库工具,可以快速构建漂亮的可视化效果
- Datapane :一个 Python 库,可以轻松部署您的可视化脚本
要安装上面的两个库,只需使用
pip3 install datapane
就是这样。现在我们已经准备好创建我们的创业成长计算器了!
制造计算器
导入参数
从导入相关库开始
import pandas as pd
import requests
import datetime
import numpy as np
import altair as alt
import datapane as dp
参数的输入值
然后我们根据周增长率计算月增长率。
假设没有增长,创建数据框架
在创建基于增长率变化的图形之前,让我们简化问题,先创建没有增长率的图形。
这将创建一个如下所示的表格
用 Altair 可视化
在创建图表之前,让我们考虑一下我们希望图表做什么:
- 收入根据创业公司所处的时期和每月的增长而变化。
- 当月的累计金额根据上月的收入总额而变化
- 每月的现金总额根据收入和收入前的现金总额而变化。
这给了我们一个想法来创建这样一个脚本:
使用数据面板部署计算器
厉害!我们为计算器创建了一个表格和一个图表。剩下的步骤就是部署这个计算器。有了 Datapane,这个任务再简单不过了!
从在 Datapane 的网站上注册一分钟开始。登录后,您将获得您帐户的 API 令牌。复制并粘贴到您的终端登录,然后重新启动您的 Jupyter 笔记本。
datapane login --server=[https://datapane.com/](https://datapane.com/) --token='yourtoken'
或者,你可以像这样把它添加到你的 Jupyter 笔记本的开头
!datapane login --server=[https://datapane.com/](https://datapane.com/) --token='yourtoken'
将我们的表格和图表部署为报告就像这样简单!
这样的网站会自动为你创建!https://data pane . com/khu yen/reports/startup _ finance _ report _ 22717 d80/
在分享您刚刚创建的令人惊叹的计算器之前,让我们添加一些描述,让您的读者或用户更好地了解这个计算器是关于什么的。这可以用dp.Markdown
轻松完成!
现在我们有了一个优雅的网站,供你的创业计算器使用,随时准备与你的队友分享!
结论
恭喜你!你刚刚学会了如何用牵牛星和数据面板为你的创业成长创建一个计算器。这是基于简单的概念、创建图表的少量代码以及部署表格和图表的最少代码完成的!我鼓励你看看这两个神奇的工具,以了解更多的方法来创建类似的图表和报告。
简单地分叉这个 repo 来玩代码并根据需要调整参数。
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 T2 Twitter 上与我联系。
星这个回购如果你想检查我写的所有文章的代码。在 Medium 上关注我,了解我的最新数据科学文章,例如:
[## 如何用 Altair 创建交互式剧情
在 5 行简单的 Python 代码中利用您的数据分析
towardsdatascience.com](/how-to-create-interactive-and-elegant-plot-with-altair-8dd87a890f2a) [## 凸包:包装数据的创新方法
如何利用包装算法实现数据可视化
towardsdatascience.com](/convex-hull-an-innovative-approach-to-gift-wrap-your-data-899992881efc) [## 如何用图论可视化社交网络
找出《权力的游戏》中的影响者
towardsdatascience.com](/how-to-visualize-social-network-with-graph-theory-4b2dc0c8a99f) [## 如何为你最喜欢的可视化工具创建下拉菜单和滑动条
使用 Python Widget,您可以用 3 行代码升级可视化
towardsdatascience.com](/how-to-create-a-drop-down-menu-and-a-slide-bar-for-your-favorite-visualization-tool-3a50b7c9ea01) [## 如何找到和 Python 很好的搭配
给定个人偏好,如何匹配使得总偏好最大化?
towardsdatascience.com](/how-to-match-two-people-with-python-7583b51ff3f9) [## 如何用 Github 组织你的数据科学文章
被新信息淹没?现在,您可以轻松地跟踪文章并为其创建自定义注释
towardsdatascience.com](/how-to-organize-your-data-science-articles-with-github-b5b9427dad37)
如何用 Python 创建一个美化的维恩图
原文:https://towardsdatascience.com/how-to-create-and-beautify-venn-diagrams-in-python-331129bd4ed3?source=collection_archive---------12-----------------------
由 matplotlib-venn 授权
维恩图是科研文章中最常见的图,可以用来表示多个数据集之间的关系。从维恩图中,你可以很容易地发现这些数据集之间的共性和差异。本教程将向你展示用 Python 创建维恩图的三种不同方法,以及如何美化这些图。
第一部分:如何创建维恩图
- 步骤 1:您需要安装名为 matplotlib-venn 的库。
pip install matplotlib-venn
- 步骤 2:导入库
#Import libraries
from matplotlib_venn import venn2, venn2_circles, venn2_unweighted
from matplotlib_venn import venn3, venn3_circles
from matplotlib import pyplot as plt
%matplotlib inline
- 步骤 3:为数据可视化创建数据集
每个数据集中的字母代表学生姓名,我们希望直观显示每门课程有多少学生注册,其中有多少学生注册了两门和三门课程。
Course1=[‘A’,’B’,’C’,’E’,’F’,’G’,’I’,’P’,’Q’]
Course2=[‘B’,’E’,’F’,’H’,’K’,’Q’,’R’,’S’,’T’,’U’,’V’,’Z’]
Course3=[‘C’,’E’,’G’,’H’,’J’,’K’,’O’,’Q’,’Z’]
- 第四步:可视化维恩图
让我们开始画一张有两组的文氏图。
使用 matplotlib 库制作维恩图有 3 种主要方法,可以得到相同的结果。
方法 1 是最直接的方法。直接放两个数据集。
#Method1: put two datasets directly
venn2([set(Course1), set(Course2)])
plt.show()
你会得到这样的文氏图:
文氏图 1
对于方法 2,你需要先知道下面的数字。
- Ab =包含在 中的左组 (此处表示为 A),但 不是右组 (此处表示为 B)
- aB =包含在 右组 中的 B,但 不是左组 中的 A
- ab = a⋂b;包含在两组中。
子集参数是一个 3 元素列表,其中数字 5、8、4 对应于 aB、AB、Ab。
#Method 2:
venn2(subsets = (5, 8, 4))
plt.show()
你会得到和文氏图 1 一样的图。Matplotlib 自动将 A 和 B 赋给维恩图。
对于方法 3,您需要向参数子集传递一个字典。
#Method 3:
venn2(subsets = {‘10’: 5, ‘01’: 8, ‘11’: 4})
plt.show()
关键是二进制编码方法。所以这三个键必须是“10”、“01”和“11”,键后的每个值代表对应区域的大小。
第二部分:美化维恩图
- 更改标签
venn2([set(Course1), set(Course2)],set_labels=(‘Course1’, ‘Course2’))
plt.show()
2.设置颜色和不透明度
venn2([set(Course1), set(Course2)],set_labels=(‘Course1’, ‘Course2’),set_colors=(‘orange’, ‘darkgrey’), alpha = 0.8)
plt.show()
3.改变圈子
venn2([set(Course1), set(Course2)],set_labels=(‘Course1’, ‘Course2’),set_colors=(‘orange’, ‘darkgrey’), alpha = 0.8)
venn2_circles([set(dataset1), set(dataset2)], linestyle=’-.’, linewidth=2, color=’black’)
plt.show()
Matplotlib 提供了各种不同的线型。更多关于 linestyle 的信息可以在 Matplotlib 网站上找到。
4.更改标签和数字的大小
vd2=venn2([set(Course1), set(Course2)],set_labels=(‘Course1’, ‘Course2’),set_colors=(‘orange’, ‘darkgrey’), alpha = 0.8)
venn2_circles([set(Course1), set(Course2)], linestyle=’-.’, linewidth=2, color=’black’)
**for text in vd2.set_labels: #change label size
text.set_fontsize(16);
for text in vd2.subset_labels: #change number size
text.set_fontsize(16)**
plt.show()
5.向图表添加标题
要完成文氏图,必须添加标题。
vd2=venn2([set(Course1), set(Course2)],set_labels=(‘Course1’, ‘Course2’),set_colors=(‘orange’, ‘darkgrey’), alpha = 0.8)
venn2_circles([set(Course1), set(Course2)], linestyle=’-.’, linewidth=2, color=’black’)for text in vd2.set_labels:
text.set_fontsize(16);
for text in vd2.subset_labels:
text.set_fontsize(16)plt.title(‘Venn Diagram for Course1 and Course2’,fontname=’Times New Roman’,fontweight=’bold’,fontsize=20,pad=30,backgroundcolor=’#cbe7e3',color=’black’,style=’italic’);
plt.show()
画一个有 3 组的维恩图和生成一个有 2 组的维恩图没有明显的区别。
vd3=venn3([set(Course1),set(Course2),set(Course3)],
set_labels=(‘Course1’, ‘Course2’,’Course3'),
set_colors=(‘#c4e6ff’, ‘#F4ACB7’,’#9D8189'),
alpha = 0.8)
venn3_circles([set(Course1), set(Course2),set(Course3)], linestyle=’-.’, linewidth=2, color=’grey’)
for text in vd3.set_labels:
text.set_fontsize(16);
for text in vd3.subset_labels:
text.set_fontsize(16)
plt.title(‘Venn Diagram for 3 courses’,fontname=’Times New Roman’,fontweight=’bold’,fontsize=20,
pad=30,backgroundcolor=’#cbe7e3',color=’black’,style=’italic’);
plt.show()
Matplotlib 允许我们单独定制每个圆。让我们自定义左上角的圆圈。
vd3=venn3([set(Course1),set(Course2),set(Course3)],
set_labels=(‘Course1’, ‘Course2’,’Course3'),
set_colors=(‘#c4e6ff’, ‘#F4ACB7’,’#9D8189'),
alpha = 0.8)
c=venn3_circles([set(Course1), set(Course2),set(Course3)], linestyle=’-.’, linewidth=2, color=’grey’)
for text in vd3.set_labels:
text.set_fontsize(16);
for text in vd3.subset_labels:
text.set_fontsize(16)
plt.title(‘Venn Diagram for 3 courses’,fontname=’Times New Roman’,fontweight=’bold’,fontsize=20,
pad=30,backgroundcolor=’#cbe7e3',color=’black’,style=’italic’);
**c[0].set_lw(3.0) #customize upper left circle
c[0].set_ls(‘:’)**
plt.show()
圆圈的颜色也可以定制。但是,如果我们给圆分配一个新的颜色,它将覆盖我们在 venn3 函数中通过参数 set_colors 设置的颜色。
vd3=venn3([set(Course1),set(Course2),set(Course3)],
set_labels=(‘Course1’, ‘Course2’,’Course3'),
set_colors=(‘#c4e6ff’, ‘#F4ACB7’,’#9D8189'),
alpha = 0.8)
c=venn3_circles([set(Course1), set(Course2),set(Course3)], linestyle=’-.’, linewidth=2, color=’grey’)
for text in vd3.set_labels:
text.set_fontsize(16);
for text in vd3.subset_labels:
text.set_fontsize(16)
plt.title(‘Venn Diagram for 3 courses’,fontname=’Times New Roman’,fontweight=’bold’,fontsize=20,
pad=30,backgroundcolor=’#cbe7e3',color=’black’,style=’italic’);
c[0].set_lw(7.0)
c[0].set_ls(‘:’)
c[0].set_color(‘#c4e6ff’)
plt.show()
享受维恩图表!
如何用 Python 创建和定制维恩图
原文:https://towardsdatascience.com/how-to-create-and-customize-venn-diagrams-in-python-263555527305?source=collection_archive---------1-----------------------
用 2 组或 3 组自定义维恩图
维恩图非常适合用来说明两个或三个群体之间的关系;你可以很容易地看到共同点和不同点。本文将向您展示如何用 Python 创建维恩图,以及如何根据您的喜好定制这些图。
如何创建维恩图
首先,你必须把这个库安装到你的电脑上。在您的终端中使用以下命令。
pip install matplotlib-venn
一旦你安装好了,我们就可以开始编码了。我们将导入以下库。
#Import libraries
from matplotlib_venn import venn2, venn2_circles, venn2_unweighted
from matplotlib_venn import venn3, venn3_circles
from matplotlib import pyplot as plt
%matplotlib inline
有两组的文氏图
要创建两个组的文氏图,请使用文 n2。
venn2(subsets = (30, 10, 5), set_labels = ('Group A', 'Group B'))
子集参数是一个 3 元素列表,其中数字 30、10、5 对应于 aB、AB、Ab。
- Ab =包含在 A 组,但不包含在 B 组
- aB =包含在 B 组中,但不是 A 组
- AB =包含在 A 组和 B 组中
set_labels 参数允许您在维恩图中标记您的两个组。
定制维恩图
圆圈的默认颜色是红色和绿色,但好消息是你可以自定义颜色!添加 set_colors 参数来设置组的颜色。此外,您可以使用 alpha 参数来控制透明度。
venn2(subsets = (30, 10, 5), set_labels = ('Group A', 'Group B'), set_colors=('purple', 'skyblue'), alpha = 0.7);
维恩图最酷的一点是,它会根据圆圈内的项目数量自动确定圆圈的大小。然而,如果你不希望圆被加权,你可以使用未加权的文氏图。
尽管 A 组比 b 组大,但现在这两个组的大小相同。
venn2_unweighted(subsets = (30, 10, 5), set_labels = ('Group A', 'Group B'), set_colors=('r', 'g'), alpha = 0.5);
您可以通过在原始的圆周上覆盖一个轮廓来进一步定制您的维恩图。请注意,这仅适用于加权文氏图。
venn2(subsets = (30, 10, 5), set_labels = ('Group A', 'Group B'), set_colors=('r', 'g'), alpha = 0.5);venn2_circles(subsets = (30, 10, 5));
如果您不喜欢实线,可以使用 line style 参数更改为不同的线条样式。您也可以设置线条宽度。
venn2(subsets = (30, 10, 5), set_labels = ('Group A', 'Group B'), set_colors=('r', 'g'), alpha = 0.5);venn2_circles(subsets = (30, 10, 5), linestyle='dashed', linewidth=2, color='k');
最后,让我们给图表一个标题!
plt.title(“I made a Venn Diagram!”);
三组维恩图
为了创建具有 3 组而不是 2 组的文氏图,我们从文 n2 切换到文 n3。
venn3(subsets = (20, 10, 12, 10, 9, 4, 3), set_labels = ('Group A', 'Group B', 'Group C'), alpha = 0.5);
您可以使用 get_patch_by_id 方法定制图表中每个区域的颜色。请注意,三个圆重叠的中间区域现在是橙色的。
v.get_patch_by_id('111').set_color('orange')
请参见下图,了解每个区域的呼叫 id。
来源:https://en.wikipedia.org/wiki/Venn_diagram
最后,我想告诉你的是如何改变每个单独的圆圈的线条宽度。如果我将维恩图圆设置为变量 c,我可以调用每个单独的圆 c[0]、c[1]或 c[2]并设置线条宽度。
c = venn3_circles(subsets = (20, 10, 12, 10, 9, 4, 3), linestyle='dashed', linewidth=1, color=”grey”)c[0].set_lw(5.0)
c[1].set_lw(8.0)
c[2].set_lw(2.0)
如果你想跟随我的 Jupyter 笔记本,你可以在这里找到它。
最后,如果你正在处理超过 2 或 3 个集合,查看扰乱图库(https://pypi.org/project/UpSetPlot/)。感谢 Renato Bellotti 让我注意到这一点。
快乐的维恩图解!干杯。
如何使用 AWS CLI 创建和运行 EMR 集群
原文:https://towardsdatascience.com/how-to-create-and-run-an-emr-cluster-using-aws-cli-3a78977dc7f0?source=collection_archive---------7-----------------------
技术提示
为初学者编写的清晰易懂的教程
简介
简单介绍一下 Apache Spark 和 AWS EMR 上的 Spark 集群
Apache Spark 是用于大规模数据处理的统一分析引擎。Spark 被认为是“‘大数据’丛林之王 ”,在数据分析、机器学习、流和图形分析等方面有着多种应用。有 4 种不同的 Spark 模式:(1) 本地模式 :笔记本电脑等单机上的 Spark,用于学习语法和项目原型化;另外 3 种模式是集群管理器模式:(2) 单机模式 用于在私有集群上工作;(3) 纱 和(4) Mesos 模式 在与团队共享集群时使用。在独立模式下,Spark 部署在私有集群上,比如 Amazon Web Service AWS 上的 EC2。一个火花簇包括多个机器。要在每台机器上使用 Spark 代码,Spark 及其依赖项需要手动下载和安装。有了 弹性地图还原服务,EMR ,来自 AWS,一切都是现成可用,无需任何手动安装。因此,我们不使用 EC2,而是使用 EMR 服务来建立 Spark 集群。
本教程的动机
我确实花了很多时间使用 AWS 命令行界面、AWS CLI 在 EMR 上创建、设置和运行 Spark 集群。虽然我找到了一些关于这个任务的教程,或者是通过课程提供的,但是大部分都很难理解。有的不够清晰;有些人错过了一些关键步骤;或者假设学习者知道一些关于 AWS、CLI 配置等的先验知识。成功设置并运行集群后,我才知道这个任务 其实没那么复杂;我们应该轻松地完成它。我不想再看到人们为此而挣扎。 因此,我决定做这个教程。
本文假设您已经对 Spark、PySpark、命令行环境和 AWS 有了一定的了解。具体来说, 这篇文章是写给知道为什么需要创建 Spark 集群的读者的:)。 更多关于 Spark 的内容,请在这里阅读参考文献。
这是一个很长很详细的教程。简而言之,所有步骤包括:
- 创建一个 AWS 账户
- 创建一个 IAM 用户
- 在 EC2 中设置凭证
- 创建一个 S3 存储桶来存储集群产生的日志文件
- 安装 AWS CLI 包
[awscli](#6df6)
- 设置 AWS CLI 环境(创建凭证和配置文件)
- 创建一个 EMR 集群
- 允许 SSH 访问
- 创建与集群主节点的 SSH 连接
- 开始使用 EMR 集群
请随意跳过任何你已经知道的步骤。本教程的 Jupyter 笔记本版本,以及关于 Spark 的其他教程和更多数据科学教程可以在 my Github 上找到。现在,让我们开始吧!
我很高兴你们中的许多人发现这个教程很有用。我很荣幸能和大家一起讨论你在电子病历创建过程中遇到的任何问题。基于我们的一些讨论, 下面是对本教程 的一些更新。
一些注意事项:
1.对于本教程,应该使用 AWS 常规帐户而不是 AWS 教育帐户。AWS 常规帐户为用户提供对 AWS 资源和 IAM 角色的完全访问权限;而教育帐户具有一些有限访问权限。
2.您有责任监控您使用的 AWS 帐户的使用费。每次完成工作时,请记住终止集群和其他相关资源。我已经多次实现了 EMR 集群;本教程在 AWS 上应该没有成本或成本低于 0.5 美元。
3.AWS 控制台和 Udacity 的内容会随着时间的推移而变化/升级,因此我建议您搜索 AWS 网站和 Udacity 的课程,以获取任何更新的教程/指南。本教程根据 2020 年 7 月的 AWS 控制台生成。
4.本教程是用 Chrome 和 Mac OS X 制作的,在 Windows 平台上应该不会有太大区别。
参考
- 一些材料来自 Udacity 上的数据工程师纳米学位项目。
- 一些想法和问题是从 Knowledge-uda city 问答平台和学生中心-uda city 聊天平台收集的。
在 AWS CLI 上创建、设置和运行 EMR 集群的具体步骤
第一步:创建一个 AWS 账户
- 如果您还没有 AWS 帐户,请创建一个。该说明在 AWS 网站上非常容易理解。
- 登录你的 AWS 账户。
- (可选)为了提高 AWS 资源的安全性,您可以根据此处的简易 AWS 指南配置并启用虚拟多因素身份验证(MFA) 设备。
步骤 2:创建 IAM 用户
从 AWS 控制台,点击Service
,输入‘IAM’进入 IAM 控制台:
= >选择User
=>=Add user
=>输入用户名如‘EMR _ user’,选择Access type
为程序化访问,然后选择Next: Permissions
。
点击Attach existence policies directly
页面,输入并设置权限为Administrator Access
,然后选择Next: Tags
。
跳过此标签页,选择Next: Review
= >选择Create user
= >保存用户名、访问密钥和秘密访问密钥。
我们将使用这个 IAM 用户和访问密钥,通过 AWS CLI 设置和访问 AWS。
步骤 3:在 EC2 中设置凭证
在 AWS 控制台中,单击“服务”,键入“EC2”进入 EC2 控制台
在网络中选择Key Pairs
在左侧面板上选择&安全=>选择Create key pair
键入密钥对的名称,例如“emr-cluster”,文件格式:pem = >选择Create key pair
。完成此步骤后,将自动下载一个. pem 文件,在这种情况下,文件名为emr_cluster.pem
。我们将在步骤 6 中使用这个文件。
步骤 4(可选):创建一个 S3 存储桶来存储集群生成的日志文件
- 这将是 AWS 存储桶,用于存储我们将创建和设置的集群所生成的日志文件。如果我们没有指定 S3 存储桶,那么在创建和运行 EMR 集群时,会自动为我们创建一个 S3 存储桶。
- 从 AWS 控制台,点击
Service
,键入“S3”并转到 S3 控制台= >选择Create bucket
= >输入存储桶的名称,如“s3-for-emr-cluster”,选择您的首选地区,如“美国西部(俄勒冈州)”。保持其他选项的默认设置,以创建一个存储桶。
- 请注意,为了获得最佳性能并避免任何错误,请记住对您的所有工作(S3、EC2、EMR 等)使用相同的 AWS 区域/子区域。)
第五步:安装 awscli 包
- 在终端上,使用命令
pip install awscli
安装awscli
- 键入
aws help
检查安装是否正确。如果输出如下所示,安装应该会成功:
步骤 6:设置 AWS CLI 环境(创建凭证和配置文件)
这一步将帮助我们使用在上面第 2 步中获得的用户凭证自动访问 awscli 环境中的 AWS。
这种设置有两种方法:手动创建凭证和配置文件(方法 1)或使用aws
命令创建这些文件(方法 2)。你可以使用任何一个。
方法 1:
在终端上创建 ***credentials***
文件如下(您可以使用 ***nano***
或您选择的任何其他文本编辑器):
- 在终端上,导航到所需的文件夹,通常是根目录,并创建一个隐藏目录,如
aws
:
$mkdir .aws
(句点表示隐藏目录)
- 转到目录
$cd .aws
- 使用 nano 创建一个
credentials
文件:$nano credentials
按如下方式键入credentials
文件的内容(用步骤 2 中为用户‘EMR-user’生成的密钥替换密钥‘EXAMPLE _ ID’和密钥‘EXAMPLE _ Key’):
- 使用
Ctrl + X
,然后使用Y
保存文件并退出 nano。
创建配置文件:
$nano config
按如下方式键入config
文件的内容(我们使用的区域与我们在步骤 4 中创建 S3 存储桶时使用的区域相同):
[default]
region=us-west-2
- 使用
Ctrl + X
,然后使用Y
保存文件并退出 nano。
方法 2:
在终端上,键入$aws configure
,并按如下方式输入所需信息:
AWS Access Key ID [None]: (Enter your access key from the user 'emr-user' created in Step 2)
AWS Secret Access Key [None]: (Enter your secret key from the user 'emr-user' created in Step 2)
Default region name [None]: us-west-2 (The same region used in Step 4)
Default output format [None]:
这两个文件将在隐藏文件夹中自动创建。aws 通常位于根目录下,如下所示:
$cd ~/.aws
- 键入
$ls
以验证这两个文件是否存在。信息应该与方法 1 中的相同,我们可以通过键入以下命令来检查内容: $cat credentials
$cat config
准备好。步骤 3 中生成的 pem 文件
为了连接到集群,我们需要。在步骤 3 中创建的 pem 文件。移动。我们在步骤 3 中下载的 pem 文件保存到项目所需的位置。对我来说,我把它放在与隐藏文件夹中的凭证和配置文件相同的位置。位于根目录~/.aws/emr-cluster.pem
的 aws)
$ mv ~/Downloads/emr-cluster.pem .
- 用这个的时候。pem 文件来设置 ssh,如果。pem 文件太开放。警告的一个例子是:“对“~/”的权限 0644。“aws/emr-cluster.pem”太开放。要求您的私钥文件不能被其他人访问。该私钥将被忽略。
- 在这种情况下,我们需要为此更改权限。pem 文件使用命令:
sudo chmod 600 ~/.aws/emr-cluster.pem
验证我们是否成功安装了 awscli 包并设置了凭据
要验证我们是否成功安装了 awscli 并设置了凭据,请键入一些 aws 命令,如
- 列出所有 IAM 用户:
$aws iam list-users
- 列出 s3 中的所有存储桶:
$aws s3 ls
该命令将列出 AWS 中的所有 s3 存储桶:
步骤 7:创建一个 EMR 集群
现在我们准备在终端上创建 EMR 集群。在终端上,键入命令:
aws emr create-cluster --name test-emr-cluster --use-default-roles --release-label emr-5.28.0 --instance-count 3 --instance-type m5.xlarge --applications Name=JupyterHub Name=Spark Name=Hadoop --ec2-attributes KeyName=emr-cluster --log-uri s3://s3-for-emr-cluster/
电子病历脚本组件说明:
--name
:在这种情况下,集群的名称为‘test-EMR-cluster’--use-default-roles
:使用默认服务角色(EMR_DefaultRole)和实例配置文件(EMR_EC2_DefaultRole)获得访问其他 AWS 服务的权限--release-label emr-5.28.0
:使用 EMR 版本 5.28.0 构建集群--instance-count 3
和--instance-type m5.xlarge
:构建 1 个主节点和 2 个 m5.xlarge 类型的核心节点--applications Name=JupyterHub Name=Spark Name=Hadoop
:在这个集群上安装 JupyterHub、Spark 和 Hadoop--ec2-attributes KeyName=emr-cluster
:配置 Amazon EC2 实例配置,KeyName 是我们在步骤 3 中设置的 EC2 实例名称(Set up credentials in EC2
)并获取。pem 文件)。在这种情况下,名称为emr-cluster
。--log-uri s3://s3-for-emr-cluster/
:指定要存储日志文件的 S3 桶。在这种情况下,S3 存储桶是“s3-for-emr-cluster”。该字段是可选的(如步骤 4 中所述)。- 由于 EMR 集群的成本很高,我们可以设置选项
--auto-terminate
在集群上的所有操作完成后自动终止集群。为此,我们还需要使用--bootstrap-actions Path="s3://bootstrap.sh"
在命令中指定引导动作。当您使用自动终止时,群集将启动,运行您指定的任何引导操作,然后执行通常输入数据、处理数据,然后生成并保存输出的步骤。当这些步骤完成时,Amazon EMR 自动终止集群 Amazon EC2 实例。 如果我们不放任何自举动作,我们应该去掉这个字段。 可在 AWS 网站上找到关于引导的详细参考。
我们创建 EMR 集群后的期望输出将是:
使用以下命令,使用 ClusterId 检查集群的状态和信息(j- EXAMPLECLUSTERID
):
aws emr describe-cluster --cluster-id j-EXAMPLECLUSTERID
我们应该等待几分钟,让群集可用(状态变为“可用”),然后再继续下一步。
*** * 更新 1:* 如果您在创建 Amazon EMR 集群时遇到了"EMR_DefaultRole is invalid" or "EMR_EC2_DefaultRole is invalid" error
的问题,您可能需要删除角色和实例概要文件;然后按照本指令重新创建角色。感谢 Trevor S .讨论这个问题。
*** 更新 2: 为了使群集可用于 EMR 上的笔记本,我们可能需要在—ec2—属性中包含子网 id:
aws emr create-cluster --name test-emr-cluster --use-default-roles --release-label emr-5.28.0 --instance-count 3 --instance-type m5.xlarge --applications Name=JupyterHub Name=Spark Name=Hadoop --ec2-attributes ***SubnetIds=subnet-YOURSUBNET,***KeyName=emr-cluster --log-uri s3://s3-for-emr-cluster/
(感谢 Saverio G .和我讨论这个问题。)
如何查找子网 id?
点击 EMR 控制台上的 VPCSubnets 选项卡,从列表中进行选择。
对于初学者来说,另一个安全的方法是:使用 AWS 控制台创建一个类似的 EMR 集群。然后查看该群集的摘要页面上的“网络和硬件”会话,以查看子网 ID:
您可以通过 AWS 上的 VPC 仪表板访问子网。关于子网和 VPC 的更多信息可以在 AWS 网站上找到。
步骤 8:允许 SSH 访问
从 AWS 控制台,点击Service
,输入 EMR,并转到 EMR 控制台。
= >选择Clusters
= >选择列表中集群的名称,在本例中,是test-emr-cluster
在Summary
选项卡上,向下滚动查看零件Security and access
,选择Security groups for Master
链接
选择Security group ID
为ElasticMapReduce-master
向下滚动Inbound rules
,Edit inbound rules
= >为了安全起见,删除任何 SSH 规则(如果有),然后选择Add Rule
= >选择类型:SSH,TCP 用于协议,22 用于端口范围= >用于源,选择我的 IP = >选择Save
。
步骤 9:创建与集群主节点的 SSH 连接
方法 1:
- 在终端上,使用命令检查集群的 id
aws emr list-clusters
- 使用此命令连接到集群。记住要指定。pem 文件:
aws emr ssh --cluster-id j-EXAMPLECLUSTERID --key-pair-file ~/.aws/emr-cluster.pem
如果我们看到如下带有 EMR 字母的屏幕,恭喜您,您使用 AWS CLI 成功创建、设置并连接到 EMR 集群!!!!
使用命令$logout
关闭与集群的连接。
方法 2:
- 从 AWS 控制台,点击
Service
,输入 EMR,并转到 EMR 控制台。 - 选择
Clusters
= >单击列表中的集群名称,在本例中,在 Summary 选项卡上,单击链接使用 SSH 连接到主节点。
- 复制弹出窗口中显示的命令,并粘贴到终端上。
- 记得用私钥文件的位置和文件名替换~/emr-cluster.pem。pem)我们已经建立了。例如
ssh -i ~/.aws/emr-cluster.pem hadoop@ec2-xx-xxx-xx-xx.us-west-2.compute.amazonaws.com
如果我们看到带有 EMR 字母的屏幕,恭喜您,您使用 AWS CLI 成功创建、设置并连接到 EMR 集群!!!!
现在您可以开始使用 EMR 集群了
创建一个简单的 Spark 任务,例如,创建一个 Spark 数据帧,其中包含字符串类型的时间,然后将该列转换为不同的格式。
在集群终端上,创建文件test_emr.py
$nano test_emr.py
将该脚本复制并粘贴到 test_emr.py
### Content of the file 'test_emr.py'from pyspark.sql import SparkSession, functions as Fif __name__ == "__main__":
"""
example of script submited to spark cluster
"""
spark = SparkSession.builder.getOrCreate()
df = spark.createDataFrame([('01/Jul/1995:00:00:01 -0400', ),('01/Jul/1995:00:00:11 -0400',),('26/Jul/1995:17$
('19/Jul/1995:01:56:43 -0400',), ('11/Jul/1995:12:50:18 -0400',)], ['TIME'])
df = df.withColumn("date", F.unix_timestamp(F.col('TIME'), 'dd/MMM/yyyy:HH:mm:ss Z').cast('timestamp'))
# show the dataframe
df.show()
#### stop the spark, otherwise the program will be hanged
spark.stop()
文件的内容如nano
文本编辑器所示:
使用以下命令在集群终端上提交脚本:
$spark-submit --master yarn ./test_emr.py
当任务运行时,它可能会被终端上的任何信息淹没,这在 Spark 中是正常的。可以在信息日志中找到输出:
恭喜你!你做到了!
当不再使用集群时,记得将其终止。
键入logout
退出集群。然后使用以下命令终止集群:
$aws emr terminate-clusters --cluster-id j-EXAMPLECLUSTERID
请注意, 我们可以使用 AWS CLI 命令轻松地再次创建具有相同配置的集群 ,当我们在 emr 控制台上选择终止的集群“test-emr-cluster”时,单击AWS CLI export
选项卡可以找到该命令:
我希望没有人再需要使用 AWS CLI 在 EMR 上创建、设置和运行 Spark 集群。如果您对本教程有任何问题或发现任何错误,请告诉我。
本教程的 Jupyter 笔记本版本,以及 Spark 上的其他教程和更多数据科学教程可以在my Github上找到。 请欣赏!
如何创建和使用自定义 Matplotlib 样式表
原文:https://towardsdatascience.com/how-to-create-and-use-custom-matplotlib-style-sheet-9393f498063?source=collection_archive---------10-----------------------
为什么要使用样式表?
数据可视化的美感非常重要。我经常认为这是“漂亮的数据应该得到漂亮的展示”——过分讲究图表样式是不被鼓励的,但是适当的润色会大有帮助。
然而,对于我们通常用 matplotlib 或 seaborn 制作的静态图,默认的美学通常需要调整。这就是定制样式表派上用场的地方,至少有两个原因:
- 使我们的工作流程符合不重复(DRY)原则:我们不需要每次都重复输入相同的样式代码。相反,我们用一行代码来应用样式表
- 风格一致性很容易实现,这可能是个人、团队和组织的隐含特征
如何设置和使用自定义样式表
从内置示例开始
我们大多数人可能已经在日常工作中使用了一些内置的风格。例如,快速运行
# This code snippet mimics command usages in ipython consoleIn [1]: import matplotlib.pyplot as pltOut [1]: plt.style.available
将返回样式表的完整列表,我们可以在 matplotlib 的文档中找到它们效果的图库视图。
在引擎盖下,我们可以找到这些内置的样式表并看一看:
# This code snippet mimics command usages in ipython consoleIn [2]: import matplotlib# Locate path to matplotlib by checking where config file is
# To learn more about the function below,
# type ?matplotlib.matplotlib_fnameIn [3]: matplotlib.matplotlib_fname()
Out [3]: '/Users/sdou/opt/miniconda3/lib/python3.8/site-packages/matplotlib/mpl-data/matplotlibrc'
路径/Users/.../mpl-data
是我们想要去的地方,并且定位样式表:
In [4]: !ls /Users/sdou/opt/miniconda3/lib/python3.8/site-packages/matplotlib/mpl-data/
fonts images matplotlibrc stylelib
感兴趣的文件夹是stylelib
。现在让我们来看看这个文件夹:
In [5]: !ls -1 /Users/sdou/opt/miniconda3/lib/python3.8/site-packages/matplotlib/mpl-data/stylelib/
Solarize_Light2.mplstyle
_classic_test_patch.mplstyle
bmh.mplstyle
classic.mplstyle
dark_background.mplstyle
fast.mplstyle
fivethirtyeight.mplstyle
ggplot.mplstyle
grayscale.mplstyle
seaborn-bright.mplstyle
seaborn-colorblind.mplstyle
seaborn-dark-palette.mplstyle
seaborn-dark.mplstyle
seaborn-darkgrid.mplstyle
seaborn-deep.mplstyle
seaborn-muted.mplstyle
seaborn-notebook.mplstyle
seaborn-paper.mplstyle
seaborn-pastel.mplstyle
seaborn-poster.mplstyle
seaborn-talk.mplstyle
seaborn-ticks.mplstyle
seaborn-white.mplstyle
seaborn-whitegrid.mplstyle
seaborn.mplstyle
tableau-colorblind10.mplstyle
让我们检查一份.mplstyle
文件。这里我们以classic.mplstyle
为例,显示文件的前 37 行:
图 classic.mplstyle”文件的前 37 行(37 行是任意选择)
我们可以看到 matplotlib 参数设置及其默认值的综合列表,参数被组织成lines
、markers
、patch
、text
等组。
打造定制。mplstyle 文件
极简主义的例子
下面是一个建立在内置样式表seaborn-colorblind.mplstyle
之上的极简示例(名为signature.mplstyle
如何调用自定义样式表
- 如果我们对上述路径
stylelib
有写权限,我们可以将自定义样式表放入同一个文件夹,并使用
# Scenario 1: Apply globally to a jupyter notebook
plt.style.use(“signature”)# Scenario 2: Apply locally with context manager
with plt.style.context("signature"):
plt.plot([1, 2, 3, 4])
- 如果我们没有写权限,我们需要做的唯一额外的事情就是包含自定义样式表的完整路径。这里我们使用一个简单的例子,将样式表直接存储在主目录下:
# Scenario 1: Apply globally to a jupyter notebook
plt.style.use(“/home/signature.mplstyle”)# Scenario 2: Apply locally with context manager
with plt.style.context("/home/signature.mplstyle"):
plt.plot([1, 2, 3, 4])
如何恢复默认
有些情况下,我们希望恢复默认样式。有两种方法可以恢复默认设置:
- 通过
rcParams.update
复位
import matplotlib as mpl
mpl.rcParams.update(mpl.rcParamsDefault)
2.用默认样式表重置
plt.style.use('default')
数据即例子:样式表在行动
这里我们以企鹅数据集为例来演示自定义样式表signaure.mplstyle
的效果。
import matplotlib.pyplot as plt
import seaborn as sns# Load the penguins dataset
penguins = sns.load_dataset("penguins")
- 使用默认样式
plt.style.use("default")
# Show the joint distribution using kernel density estimation
g = sns.jointplot(
data=penguins,
x="bill_length_mm",
y="bill_depth_mm",
hue="species",
kind="kde",
)
g.fig.suptitle("Styled With Default Style Sheet", y=1.01)
plt.show()
图 matplotlib 默认样式的效果
2.使用signature.mplstyle
中的自定义样式集
plt.style.use("signature")
# Show the joint distribution using kernel density estimation
g = sns.jointplot(
data=penguins,
x="bill_length_mm",
y="bill_depth_mm",
hue="species",
kind="kde",
)
g.fig.suptitle("Styled With Custom Style Sheet", y=1.01)
plt.show()
图 3:定制样式表“signature.mpl”的效果
关键要点
- 漂亮的数据值得漂亮的展示。但是,与其重复输入大量的样式代码,不如花一点前期时间建立我们自己的定制样式表(文件扩展名
.mplstyle
)既能节省时间,又能确保样式的一致性 - 要构建定制样式表,我们可以从内置样式表开始,并根据我们的喜好进一步定制它们。关键的一步是在
matplotlib.matplotlib_fname()
的帮助下找到这些样式表
参考
4.11 定制 Matplotlib:配置和样式表:Jake Vander plas 的《数据科学手册》
如何在命令行上创建和查看交互式备忘单
原文:https://towardsdatascience.com/how-to-create-and-view-interactive-cheatsheets-on-the-command-line-6578641039ff?source=collection_archive---------33-----------------------
停止搜索命令行。用作弊来节省时间
与 Raj 在 Unsplash 的公路旅行照片
为什么是命令行?
如果您还没有使用过命令行,那么您应该开始学习一些基本的命令行工具。以下是原因:
-
命令行对数据科学家很有用。有了命令行,你通常做的许多事情,比如移动文件、复制文件、解压文件、创建新文件,都可以更快地完成。
-
您甚至可以使用命令行来浏览您的数据!这里有一个很好的资源。Jupyter notebook 通常用于此任务,但有时,当您为项目编写脚本时,使用命令行会更有好处。
-
您可以创建一个 bash 脚本来自动化您已经重复完成的任务。例如,我创建了一个 bash 脚本来重构我的 Django 项目文件。我不需要到处移动文件、创建虚拟环境、安装所需的包,我只需要调用
createapp.sh
,一切都在一秒钟内为我设置好了! -
您希望确定为什么代码需要很长时间才能执行。这时,拥有一个正在运行的系统的动态实时视图来确定您使用了多少 CPU 和内存是很有帮助的。
top
是完成这项任务的最强大的命令行工具之一
基于以上原因,不可否认命令行是有用的。然而,记住所有的命令是不可能的。这就是为什么在记忆命令方面,谷歌是我的朋友。
但是谷歌搜索需要时间,因为你需要:打开浏览器,在所有的网站中搜索,比如 StackOverflow 来找到命令。有比这更快的方法吗?
欺骗
是的,有一个比谷歌搜索更快的方法,它涉及作弊(不是欺骗)。 Cheat 允许你在命令行上创建和查看交互式备忘单。这是什么意思?意思是当你在终端上输入这个的时候
cheat mv
这是你将会看到的
# To move a file from one place to another:
mv <src> <dest># To move a file from one place to another and automatically overwrite if the destination file exists:
# (This will override any previous -i or -n args)
mv -f <src> <dest># To move a file from one place to another but ask before overwriting an existing file:
# (This will override any previous -f or -n args)
mv -i <src> <dest># To move a file from one place to another but never overwrite anything:
# (This will override any previous -f or -i args)
mv -n <src> <dest># To move listed file(s) to a directory
mv -t <dest> <file>...
相当酷!mv
命令的很多选项都有描述!
尽管这个存储库很有用,但是在存储库中并不清楚如何设置它。感谢 StackOverFlow 上的这个回答,我终于想出办法了。在这篇文章中,我将向你展示如何设置和使用作弊更详细的说明。
设置
- 从发布页面下载可执行文件
- 提取 zip 文件
- 使其可执行。没有这个命令,您将无法执行下载的文件
chmod +x <downloaded_file> # No gzip extension this time
- 在您的路径中查找目录
echo $PATH | tr ":" "\n"
这是我屏幕上显示的内容
- 将下载的文件复制到上述目录之一。任何一个都可以。在我的例子中,我复制了
/usr/local/bin
中的文件
cp <downloaded_file> /usr/local/bin/cheat
目录末尾的cheat
表示您将用来调用文件的名称
- 将配置文件放入
./config
文件
cheat --init > ~/.config/cheat/conf.yml
- 通过编辑
.bash_profile
将/.config/cheat/conf.yml
永久放置在路径中
nano ~/.bash_profile
在.bash_profile
中,在文件底部添加下面两行
export CHEAT_CONFIG_PATH="~/config/cheat/conf.yml"export EDITOR="/usr/bin/nano"
保存您的更改
source ~/.bash_profile
厉害!现在你可以使用作弊了!
使用
只需在终端上键入cheat
,您将看到使用作弊的不同选项
使用cheat.
非常容易,如果你想查看像tar
这样的备忘单,你可以使用
cheat tar
命令tar
的所有选项和描述都会显示在终端上。使用 cheat -l 查看所有可用的备忘单。
如果你想编辑或创建一个新的备忘单,你可以使用cheat -e <cheatsheet_name>
。例如,我想为fuser,
保存备忘单,这是一个用于定位进程的强大命令行实用程序,我将像这样将fuser
添加到我的备忘单中
cheat -e fuser
将打开fuser
的编辑器。你所需要做的就是写下描述和命令
#View port
fuser <portnumber>/tcp#Kill port
fuser -k <portnumber>/tcp
然后键入' ESC '和':wq '来编写并退出编辑器。
现在当你输入cheat fuser
的时候,你会看到你刚刚写的描述和命令!从现在开始,你再也不需要在谷歌上搜索这个命令了。多方便啊!
问题解答
如果下次使用cheat
时出现如下错误
failed to load config: failed to resolve symlink: /home/khuyentran/.config/cheat/cheatsheets/community: lstat /home/khuyentran/.config/cheat/cheatsheets: no such file or directory
只需输入source ~/.bash_profile
来设置.bash_profile
中指定的环境变量。
结论
恭喜你!您刚刚学习了如何在命令行上创建和查看交互式备忘单。这个工具将为你节省大量的谷歌搜索时间,所以如果你还没有这样做的话,试试吧。
如果你想查看我写的所有文章的代码,请点击这里。
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以通过 LinkedIn 和 Twitter 与我联系。在 Medium 上关注我或注册我的简讯以了解我的最新数据科学文章,例如:
[## VSCode 中数据科学家的 4 大代码查看器
让 YAML、JSON、CSV 和 Jupyter Notebook 为你工作,而不是与你作对
towardsdatascience.com](/top-4-code-viewers-for-data-scientist-in-vscode-e275e492350d) [## 如何用 Github 组织你的数据科学文章
被新信息淹没?现在,您可以轻松地跟踪文章并为其创建自定义注释
towardsdatascience.com](/how-to-organize-your-data-science-articles-with-github-b5b9427dad37) [## 如何在数据科学项目中利用 Visual Studio 代码
直到发现一种新的有效方法,我们才意识到我们是多么低效
towardsdatascience.com](/how-to-leverage-visual-studio-code-for-your-data-science-projects-7078b70a72f0) [## 高效 Python 代码的计时
如何比较列表、集合和其他方法的性能
towardsdatascience.com](/timing-the-performance-to-choose-the-right-python-object-for-your-data-science-project-670db6f11b8e) [## 使用 Python 最大化您的生产力
你创建了一个待办事项清单来提高效率,但最终却把时间浪费在了不重要的任务上。如果你能创造…
towardsdatascience.com](/maximize-your-productivity-with-python-6110004b45f7)
如何使用 Plotly 和 Dash 创建出色的动画散点图
原文:https://towardsdatascience.com/how-to-create-animated-scatter-maps-with-plotly-and-dash-f10bb82d357a?source=collection_archive---------15-----------------------
Plotly 中的动画地图可能很难配置。在本教程中,您将学习如何一步一步地实现一个散点图,日复一日地跟随 Covid 疫情走遍世界。
仪表板中的地图
Dash 是构建在 Flask 和 Plotly 之上的 Python 框架,旨在制作数据驱动的 web 应用。由于 Plotly,它提供了一些基本的图表,如直方图和饼状图,它还带有大量高度可定制的控件,如下拉菜单,复选框,日期滑块,等等。
要构建应用程序,您可以在一个或多个选项卡中组合所有这些控件和图表。但是当涉及到地图绘制时,就变得棘手了。Plotly 有一些基本的内置地图绘图:足以显示数据,但不如 2020 年 web 地图应该的那样好。为了解决这一弱点,Plotly 与 Mapbox 建立了合作关系。他们一起提供了很好的服务。
带有默认 plotly 贴图的散点图示例(相当难看)
今天,我们将了解如何在 dash 应用程序中使用 Mapbox 和 Plotly,以及如何创建动画散点图。
带有地图框地图的散点图示例(非常好)
由于这篇文章写于 2020 年 4 月冠状病毒疫情期间,我建议与新冠肺炎开放数据合作,以发现散点图。
注册到地图框
一些地图框表示需要一个令牌,散点图就是其中的一部分。别担心,这个简单又自由。
前往www.mapbox.com创建一个账户。对于这一步,你只需要一个电子邮件帐户验证。完成后,您可以在“令牌”页面上获得令牌,然后单击“创建令牌”按钮。
有了这个令牌,你可以免费绘制 50000 张地图/月。在本文的结尾,我们将看到如何存储地图并最小化所需的请求数量。
地图盒子网站截图
通常将这些信息存储在与脚本不同的文件中。通常的做法是使用 *。ini 文件进行存储,然后 python 内置的configparser
模块对其进行访问。
config.ini
[mapbox]
secret_token=your-token
any_file_needing_token.py
import configparser
config = configparser.read('config.ini')
mapbox_token = config['mapbox']['secret_token']
创建散点图
加载数据
如前所述,我们将使用 Covid 疫情数据。我们将使用霍普金斯大学的数据集,该数据集在危机期间每天更新。在 opendatasoft 上可用。
原始数据集的头部
数据非常容易理解:它包含许多国家关于 covid 的日常信息,关于死亡、确诊、或康复人员,以及 GPS 信息。
处理数据
必须转换该数据集以适应地图框输入。让我们明确所需的输入。
散点图的目的是在地图上绘制气泡,气泡的大小和颜色都是可变的。在今天的例子中,我们希望:
- 每个国家一个泡沫
- 气泡纬度:指定国家的纬度
- 气泡经度:指定国家的经度
- 气泡大小:确诊病例数
- 气泡颜色:获救人员比例
- 泡沫徘徊:国家形势概述
让我们在不同的栏目中获取这些信息。
- 第一步:将
Location
列提取为经纬度 - 第二步:将单个
category
列每键 3 行(date
&zone
)拆分为三列:confirmed
、deaths
&recovered.
,得到一个整洁的数据集 - 第三步:旋转表格时,我们丢失了位置信息。我们现在将它们合并回来,这多亏了
country_position
数据集。 - 第四步:定义每个气泡的大小
- 第五步:定义每个气泡的颜色
转换数据集的头
这里有一个多索引的全数据框:date
& zone
,过滤非常方便。
例如,要提取某一天的信息,我们需要:
day = '2020-05-01'
df_day = df.xs(day)
这对于我们的散点图和之后的地图动画来说非常方便!
地图
这里我们用所有必要的参数定义一个图形,然后用 Mapbox 信息更新它的 layout 属性:令牌、地图的中心位置以及我们想要放大多少。我们使用 1 的缩放比例,因为我们想看到整个地球。要放大,你只需要增加这个值。
2020 年 5 月 1 日的 Covid 案例
微小的改进
我们的散点图很好,但缺乏信息。在深入动画部分之前,我们先做一些基本的修改,提升贴图的质量。
- 添加色彩映射表。
在上图中,我们看到橙色、紫色和黄色的盒子,但不知道它们的意思。让我们添加一个色彩映射表来说明这一点。要添加色彩映射表,将showscale = True
添加到标记参数中。然后使用colorbar
属性,您可以添加更多的规范,比如标题、颜色条的大小或者任何其他关于记号的信息。
现在可以清楚地看到,黄色气泡与康复率最高的国家有关。气泡越暗,回收率越小。
2.添加自定义悬停信息
除了颜色理解之外,当用户用鼠标悬停在气泡上时显示数字也会很有趣。为此,我们可以向go.Scattermapbox()
添加一个text
参数,指定显示哪一列信息。但是这里我们想要显示多个信息,所以我们将使用hovertemplate
和customdata.
,后者允许我们将数据存储到控件中,并显示原始数据集中任何列的值。因此,我们将必要的列存储到np.stack()
中的customdata
中,并从hovertemplate
中定义的 Html 模板中访问它。
注意:
<extra></extra>
用于覆盖悬停框中写有跟踪名(trace0)的原始部分。跟踪是我们存储图形数据的对象。
2020 年 5 月 1 日的 Covid 案例,带有颜色图和悬停信息
这是我们之前修改的结果。看起来很棒,不是吗?
制作动画
现在,我们能够在地图上绘制特定日期的数据。让我们把它做成动画,日复一日地观察世界局势。
作为参考,有两种方法可以用 Plotly 和 Dash 制作地图动画:
- 创建一个多帧的动画地图(解释如下)
- 创建具有可更新轨迹的单个 Plotly 地图,通过 dash 回调进行更新,由时间滑块进行监控。这在技术上是可行的,但是由于在每一步都需要修改地图数据,因此要复杂得多并且计算量很大。(而绘制的动画地图只计算一次,然后优化帧间导航。)
框架
为了创建一个情节性的动画,我们将为该图形提供多个帧,而不是像之前在go.Figure()
语句中那样只提供一条轨迹。帧基本上是一个go.Scattermapbox()
的内容,但是存储在一个列表中。
注:
*days*
为可用天数列表:df.index.levels[0].tolist()
滑块
然后,为了浏览这个框架,我们将创建一个slider
。每个slider
被定义为一个字典,并存储在sliders
列表中。我们这里只有一个。
一个slider
由它的特性定义(如x
、y
、len
等)。),其初始状态(currentvalue
)及其steps
。为了将一个步骤链接到一个特定的帧,我们需要在帧name
和steps[i]['args'][0][0]
中有相同的值。steps[i]
作为步骤之一,i in [0 ; nb_frame]
。不是最容易的猜测,但工作。
工作按钮
一旦我们有了一个漂亮的滑块,添加一个“播放按钮”会是一个好主意,它会一个接一个地运行所有的迭代。以下是我们的做法。
放在一起
现在我们有了所有的部分,我们可以组装拼图,并最终创建我们的交互式地图。
就是这样!下面是结果!一个漂亮的交互式散点图!让我们希望气泡不会变大,我们很快就会在这个图中看到很多黄色的气泡。
结论
你已经学习了如何用 Plotly 绘制散点图以及如何制作动画。现在你可以用你自己的数据,颜色图,滑块绘制你自己的交互式地图,并通过一个播放按钮让他们活起来。我希望你喜欢它!
在我的下一篇文章中,我将把这个地图嵌入到 Dash 应用程序中,您将会发现如何在 Heroku 上部署 Python web 应用程序。你将设法进入这个散点图现场版!敬请期待!
(更新——你可以在那里查看)
[## 在 Heroku 上部署 Dash 或 Flask web 应用程序。简易 CI/CD。
在笔记本电脑上开发 python web 应用非常棒。让每个人都能接触到它更令人满意。让我们…
towardsdatascience.com](/deploying-dash-or-flask-web-application-on-heroku-easy-ci-cd-4111da3170b8)
如果你喜欢散点图版本,你可能也会喜欢 Choropleth 地图的故事😉
[## 如何使用 Plotly 和 Dash 创建出色的自定义 choropleth 地图🌎
使用 GeoJSON 文件迈出第一步&了解如何在地球上的任何地方构建 choropleth 地图。用…举例说明
towardsdatascience.com](/how-to-create-outstanding-custom-choropleth-maps-with-plotly-and-dash-49ac918a5f05)
为了发现更多关于 Plotly 以及如何展示你的 ML 项目和成果,我推荐你这篇来自 Neptune.ai 的好文章
[## 面向机器学习专家的 Plotly Python 教程- neptune.ai
Plotly 是一个开源的 Python 图形库,非常适合构建漂亮的交互式可视化…
海王星. ai](https://neptune.ai/blog/plotly-python-tutorial-for-machine-learning-specialists)
再见🤠
如何用 Plotly 创建动画可视化
原文:https://towardsdatascience.com/how-to-create-animated-visualizations-with-plotly-c54b9c97b133?source=collection_archive---------52-----------------------
让你的数据技能更上一层楼。
张家瑜在 Unsplash 上拍照
我们生活在大数据时代。我们可以收集大量数据,从而推断出有意义的结果,做出明智的商业决策。然而,随着数据量的增加,分析和探索数据变得更加困难。当有效和恰当地使用时,可视化是探索性数据分析的伟大工具。可视化也有助于向你的观众传递信息,或者告诉他们你的发现。没有一种通用的可视化方法,因此某些任务需要不同类型的可视化。近年来,动画可视化越来越受欢迎,因为它们使“告诉”比统计可视化更多的东西成为可能。动画可视化非常擅长展示事物如何随着时间的推移而变化。
我们将介绍如何使用 Plotly Python (plotly.py)创建动画可视化,这是一个基于 plotly javascript (plotly.js)构建的开源绘图库。我喜欢 plotly.py 的一点是,它提供了一个高级 API ( plotly express )和一个低级 API ( graph objects )来创建可视化。使用 plotly express,我们可以用很少的代码行创建一个很好的情节。另一方面,我们需要用图形对象编写更多的代码,但是对我们创建的内容有更多的控制。
在本帖中,我们将使用 plotly express API。我将写另一篇文章来介绍图形对象的动画可视化。
我们将合并两个不同的数据集。一个是肥胖率数据集,可在 kaggle 上的这里获得。原始数据集需要清理和重新格式化。如果你想经历数据清理的步骤,请随意访问我的帖子:
[## 数据清理实用指南:肥胖率数据集
如何清理和重新格式化原始数据集。
towardsdatascience.com](/a-practical-guide-for-data-cleaning-obesity-rate-dataset-aff9d12390c8)
以下是清理后的数据帧的前五行:
我们将使用的另一个数据集不区分性别。因此,我们需要通过按“国家”和“年份”分组并取“肥胖率”的平均值来消除该数据集中的性别:
import numpy as np
import pandas as pd# fixing data tytpes
obesity_cleaned = df2.astype({'obesity_rate': 'float32', 'year': 'int32'})# eliminating gender
obesity_cleaned = obesity_cleaned.groupby(['country','year']).mean().reset_index()obesity_cleaned.head()
另一个数据集可用作 plotly express 的内置数据集。它被称为 gapminder,包括 142 个国家从 1952 年到 2007 年的预期寿命、人均 gdp 和人口(以 5 年为增量)。我们首先导入 plotly express 和数据集:
import plotly.express as pxdf_gdp = px.data.gapminder()df_gdp.head()
我们可以使用 pandas 的 merge 功能来合并这两个数据帧。共享列是国家和年份,因此我们将它们传递给参数上的:
df_merge = pd.merge(df_gdp, obesity_cleaned,
on=['country','year'])df_merge.head()
我们现在可以创建我们的第一个动画可视化。下面是生成动画散点图的代码。我会解释每一个参数,然后显示图。
px.scatter(df_merge, x="obesity_rate", y="gdpPercap",
animation_frame="year",
size="pop", color="continent", hover_name="country",
size_max = 50,
range_x=[0.1, 50], range_y=[100,60000],
log_x=True, log_y=True)fig.show()
我们首先在数据帧的名称上加右键,并指定 x 轴和 y 轴。因此,我们的动画散点图将显示人均 gdp 和肥胖率如何随时间变化。为了使情节动画,我们使用动画 _ 帧参数。我们使用“年”作为动画帧,因此值将根据年份而变化。我们将人口分配给大小参数,因此散点图中点的大小与国家人口成比例。对于 color 参数,我们使用大陆列,这样我们可以大致了解每个大陆。 Size_max 参数允许调整散点图中点的大小。如果不指定,点可能看起来太小,人眼看不出来。 Range_x 和 range_y 参数用于指定范围,使所有点在动画期间保持可见。最后,log_x 和 log_y 参数调整对数标度上的轴范围。如果数值相差很大,最好使用对数标度,使绘图看起来更好。
可视化是传递信息的好工具。动画情节甚至更强大,因为它们也考虑了时间。通过我们刚刚创建的图,我们获得了以下信息:
- 国家人口
- 各国人均国内生产总值
- 各国肥胖率
- 这些值如何随时间变化
- 根据这些标准,各大洲是如何不同的
- 如果这些度量之间存在相关性
让我们看看我们创建的动画散点图:
- 欧洲国家的人均 gdp 和总体肥胖率都很高。
- 总的来说,非洲和亚洲国家在人均 gpd 和肥胖率方面都远远落后。
- 这些年来,亚洲国家的人均国内生产总值已经超过了非洲国家。
- 肥胖率和人均 gdp 之间似乎存在正相关关系(当然,我们需要更多的数据来证实)
- 尽管由于人口规模非常小,这一点很难引起注意,但科威特一直是肥胖率最高的国家,人均国内生产总值排名前三。
我们还可以创建一个动画条形图。例如,肥胖率如何随时间变化可以用柱状图来表示。让我们选择 5 个国家(每个洲一个)在图上显示。
countries = ['China', 'Germany', 'Senegal', 'Brazil', 'New Zealand']df5 = obesity_cleaned[obesity_cleaned.country.isin(countries)].reset_index(drop=True)
我们这次也加个标题。以下是使用 plotly express 创建动画条形图的代码:
fig = px.bar(df5, x="country", y="obesity_rate",
color="country",
animation_frame="year", animation_group="country",
range_y=[0.1, 50],
title='Obesity Rate from 1975 to 2016')fig.show()
不幸的是,全世界的肥胖率一直在上升。
我们已经介绍了如何使用 plotly express 创建一些基本的动画情节。当然,这只是这个神奇图书馆的一小部分功能。我们可以使用 plotly 动态创建许多其他绘图类型。我还将讲述如何使用 plotly.py 的图形对象创建动画图。语法稍微复杂一点,但它提供了更多的灵活性。最好熟悉这两种 API,选择最适合自己需求的一种。
就像任何其他主题一样,熟悉 plotly 的最好方法就是实践。因此,我建议创造大量的情节来提高你的技能。
感谢您的阅读。如果您有任何反馈,请告诉我。
如何使用地理空间数据在 Python 中创建气泡图
原文:https://towardsdatascience.com/how-to-create-bubble-maps-in-python-with-geospatial-data-e51118c3d767?source=collection_archive---------19-----------------------
初学者指南和教程。
Marc Sendra Martorell 在 Unsplash 拍摄的照片
想过如何用 Python 和地理空间数据创建气泡图吗?我将向您展示如何轻松地以静态格式和交互式格式制作气泡图。
A
bubble map
使用 size 作为编码变量。圆圈的大小代表一个地理区域的数值。
气泡图
我们经常使用 Choropleth 地图来显示区域,在这种情况下,我们使用颜色编码。Choropleth 地图有一个固有的大面积偏差问题。相比之下,气泡图使用圆形来表示区域或区域的数值。
用 Python 创建泡泡图看起来很复杂,也有点高级,但事实并非如此。这就像创建带有纬度和经度列的气泡图。让我们首先导入我们需要的库。
import pandas as pd
import numpy as npimport geopandas as gpdimport matplotlib.pyplot as plt
import plotly_express as px
我们可以用 Geopandas 读取数据。使用 Geopandas,您可以读取大多数地理数据格式,如 Shapefile、Geojson、Geo package 等..在本例中,我们使用的是瑞典莫尔蒙市的人口数据。
gdf = gpd.read_file(“data/malmo-pop.shp”)
gdf.head()
这是数据集的第一行。对于每个行政单位(Deso ),我们有许多人口细分栏(5 岁至 80 岁及以上)。
我们通常使用 choropleth 地图和颜色编码。正如我们将要看到的,我们可以用 Geopandas 非常容易地创建一个 choropleth 地图。请注意,我们首先通过细分总人口来标准化数据(年龄 80_w)。
gdf["Age_80_norm"] = (gdf["Age80_w"] / gdf["Total"]) * 100fig, ax = plt.subplots(figsize=(16,16))
gdf.plot(ax=ax, column="Age_80_norm", cmap="Blues",edgecolor="grey", linewidth=0.4, legend=True)
ax.axis("off")
plt.axis('equal')
plt.show()
气泡图
或者,我们可以使用气泡图,避免 choropleth 图的一些缺陷。例如,我们不需要对数据进行归一化,我们可以使用总体细分。但是,我们需要对数据进行一些转换,以便能够创建气泡图。
正如你所看到的,我们使用的数据是多边形,如果我们想创建气泡图,我们需要点。然而,这是使用 Geopandas 的一个简单过程。我们只需要改变几何列,在这种情况下,多边形为点几何。
gdf_points = gdf.copy()
gdf_points[‘geometry’] = gdf_points[‘geometry’].centroid
我们首先将具有面几何的地理数据框架复制到新的地理数据框架中。因为我们希望气泡位于区域的中心,我们可以使用 Geopandas 中的质心函数来实现这一点。
现在,我们有了具有不同几何列的相同地理数据框架,即点几何。让我们绘制一个气泡图,因为我们现在有了点数据集。
fig, ax = plt.subplots(figsize=(16,16))
gdf.plot(ax=ax, color=”lightgray”, edgecolor=”grey”, linewidth=0.4)
gdf_points.plot(ax=ax,color=”#07424A”, markersize=”Age80_w”,alpha=0.7, categorical=False, legend=True )ax.axis(“off”)
plt.axis(‘equal’)
plt.show()
下面的地图显示了瑞典莫尔蒙一个较小行政区域内 80 岁及以上人口的气泡图。每个圆圈代表基于 80 岁及以上人口小计的不同大小。要构建气泡图,您需要为您想要映射的列提供 markersize ,在本例中是 Age80_w。
正如你所看到的,这是一个静态贴图,气泡贴图的一个常见问题是点圆的重叠。我们可以避免这种情况的一种方法是创建交互式地图,允许用户与感兴趣的区域进行交互和放大。在下一节中,我们将看到如何创建一个交互式气泡图。
交互式气泡地图
有不同的 Python 库用于绘制交互式气泡图。为了构建一个交互式气泡图,我们使用 Plotly Express。我们只需要转换到另一个投影,用 Plotly Express 显示地图。Plotly Express 具有 scatter_mapbox()函数,该函数可以获取地理数据框和要用于气泡图的列。
gdf_points_4326 = gdf_points.to_crs(“EPSG:4326”)fig = px.scatter_mapbox(
gdf_points_4326,
lat=gdf_points_4326.geometry.y,
lon=gdf_points_4326.geometry.x,
size=”Age80_w”,
color=”Total”,
hover_name = “Age80_w”,
color_continuous_scale=px.colors.colorbrewer.Reds,
size_max=15,
zoom=10
)
fig.show()
使用 Plotly Express,我们可以通过创建交互式气泡图来避免气泡图的重叠问题。见下图 GIF。
气泡图可以是显示具有不同气泡大小的数值变量的替代图,而不是最常用的 choropleth 图。如果您有一个带有值(即年龄细分)的区域(即行政区)列表,气泡图可以代替 Choropleth 图。气泡图没有 choropleth 图固有的大面积偏差。
结论
在本教程中,我们已经看到了如何使用 Python 创建静态和交互式气泡图。静态气泡图存在重叠问题。为了避免这种情况,您可以创建允许放大/缩小的交互式地图,或者增加静态地图圆圈的透明度。
本教程的代码可以在这个 Github 存储库中找到。
[## shakasom/esda
permalink dissolve GitHub 是 4000 多万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/shakasom/esda/blob/master/Bubble Maps Medium.ipynb)
如何在深度学习中创建定制的实时图
原文:https://towardsdatascience.com/how-to-create-custom-real-time-plots-in-deep-learning-ecbdb3e7922f?source=collection_archive---------20-----------------------
如何在使用 Keras 回调训练深度学习模型的同时,生成自定义指标的实时可视化。
图片来源:pix abay
我们所说的实时图是什么意思?
用大型数据集训练复杂的深度学习模型可能非常耗时。随着时代的流逝,大量的数字在你的屏幕上闪现。你的眼睛(和大脑)会疲劳。
那个令人兴奋的不断更新你进度的精确度图在哪里?如何知道模型是否在学习有用的东西?还有,到底有多快?
一个 实时视觉更新 会很棒吧?
人类毕竟是视觉生物。
[## 人类是视觉动物
在这里,我们收集了一些有趣的事实来强调为什么在科学交流中使用视觉辅助工具是如此重要…
www.seyens.com](https://www.seyens.com/humans-are-visual-creatures/)
我说的视觉,并不是指当你打开模型的冗长时,所有的数字分数都倾泻在你的屏幕上。
不是这个。
我们希望如此。
让我们看看怎样才能到达那里。
那个令人兴奋的不断更新你进度的精确度图在哪里?如何知道模型是否在学习有用的东西?还有,到底有多快?
我们所说的自定义地块是什么意思?
常规工作有既定的工具。但是很多时候,我们需要定制的输出。
Tensorboard 很酷,但可能无法满足所有需求
如果你正在使用 TensorFlow/Keras 进行深度学习任务,那么你很有可能听说过或使用过 Tensorboard。这是一个神奇的仪表板实用程序,你可以传递训练日志,并可以获得精彩的视觉更新。
[## TensorBoard | TensorFlow 入门
在机器学习中,为了改进某些东西,你通常需要能够测量它。TensorBoard 是一款提供…
www.tensorflow.org](https://www.tensorflow.org/tensorboard/get_started)
图片来源: 张量板
用 Tensorboard 可以很容易地得到标准损耗、精度图。如果您只想监控这些,而不是 DL 模型中的其他内容,您可以停止阅读本文,直接使用 Tensorboard。
但是,当您有一个高度不平衡的数据集要处理,并且您想要绘制精度、召回和 F1 分数时,该怎么办呢?或者,另一个不那么标榜分类的度量标准像 马太系数 ?如果您只关心真阴性和假阴性的比率,并想创建自己的度量标准,那该怎么办?
随着您培训的进展,您如何看待这些非标准指标的实时更新?
Keras 内置了计算混淆矩阵的功能
幸运的是,Keras 提供了对应于混淆矩阵的四个基本量的基本对数——真阳性(TP)、假阳性(FP)、真阴性(TN)和假阴性(FN)。它们来自 Keras 指标模块。
[## 模块:TF . keras . metrics | tensor flow Core v 2 . 3 . 0
内置指标。
www.tensorflow.org](https://www.tensorflow.org/api_docs/python/tf/keras/metrics)
我们可以简单地在您的模型的训练日志中定义一个我们想要的度量列表,并在编译模型时传递该列表。
**metrics** = [
tf.keras.metrics.TruePositives(name="tp"),
tf.keras.metrics.TrueNegatives(name="tn"),
tf.keras.metrics.FalseNegatives(name="fn"),
tf.keras.metrics.FalsePositives(name="fp"),
]
然后,
model.compile(
optimizer=tf.keras.optimizers.Adam(lr=learning_rate),
loss=tf.keras.losses.BinaryCrossentropy(),
** metrics=metrics**,
)
因此,我们可以将这些度量(尽管它们是在训练数据集上计算的)作为训练日志的一部分。一旦我们得到了它们,我们就可以根据第一性原理的定义,为分类任务计算出我们想要的任何自定义指标。例如,这里我们展示了一些非标准指标的公式,
图片来源:维基百科
但是,我们如何从这些计算值中创建定制的实时图呢?
我们当然使用回调!
随着您培训的进展,您如何看待这些非标准指标的实时更新?
实时可视化的自定义回调
回调是一类非常有用的工具,可以在你训练的某些时候(或者你喜欢的话,在每个时期)调用。简而言之,它们可用于在培训过程中实时处理数据(与模型性能或算法相关)。
这是 Keras 回调的 TensorFlow 官方页面。但是为了我们的目的,我们必须编写一个自定义的绘图类从基本回调类派生而来。
[## 模块:TF . keras . callbacks | tensor flow Core v 2 . 3 . 0
回调:在模型训练期间的某些点调用的实用程序。
www.tensorflow.org](https://www.tensorflow.org/api_docs/python/tf/keras/callbacks)
演示 Jupyter 笔记本
演示版 Jupyter 笔记本是 位于我的 Github repo 上的 这里。 这个资源库 包含了很多其他有用的深度学习教程式的笔记本。所以,请随意星或叉。
不平衡的数据集
图片来源: Pixabay
我们为演示中的二进制分类任务创建了一个具有不平衡类别频率(负数比正数多得多)的合成数据集。这种情况在实际的数据分析项目中很常见,它强调需要有一个可视化的仪表板来定制分类指标,而准确性不是一个好的指标。
下面的代码创建了一个数据集,其中包含 90%的阴性样本和 10%的阳性样本。
from sklearn.datasets import make_classificationn_features = 15
n_informative = n_featuresd = make_classification(n_samples=10000,
n_features=n_features,
n_informative=n_informative,
n_redundant=0,
n_classes=2,
**weights=[0.9,0.1]**,
flip_y=0.05,
class_sep=0.7)
下面的配对图显示了两个类的样本数据分布。请注意内核密度图中的不平衡。
合成数据集的分类数据分布
回调是一类非常有用的工具,可以在你训练的某些时候(或者你喜欢的话,在每个时期)调用。
自定义回调类
自定义回调类主要完成以下工作,
- 启动一组列表来存储值
- 在每个时期结束时从模型中提取指标
- 从这些提取中计算分类度量
- 并将它们存储在这些列表中
- 创建多个地块
下面是初始化,
这里是提取,
这里是计算,
这里是仓库,
而且,我不会用标准的 Matplotlib 代码来让你厌烦,除了下面的位,它在每次迭代时刷新你的 Jupyter 笔记本绘图。
from IPython.display import clear_output# Clear the previous plot
clear_output(wait=True)
此外,您不必绘制每个时期的图,因为这可能会加重显示器或机器的负担并降低其速度。你可以选择绘制,比如说,每 5 个纪元。只要把整个绘图代码放在一个条件下(这里epoch
是你从训练日志中得到的纪元编号)
# Plots every 5th epoch
if epoch > 0 and epoch%5==0:
不要担心所有这些如何协同工作,因为 演示笔记本仍然为您准备 。
结果
这是一个典型的结果,以简单的仪表板样式显示损失和精确度/召回/F1 分数。请注意,对于这个不平衡的数据集,召回是如何从一个高值开始的,但是精度和 F1 值却很低。这些是您可以通过这种回调实时计算和监控的指标!
更多结果—概率分布!
在每个时期结束时,您可以对模型(在该点训练)进行任何想要的计算,并可视化结果。例如,我们可以预测输出概率,并绘制它们的分布。
def on_epoch_end(self, epoch, logs={}):
# Other stuff
m = self.model
preds = m.predict(X_train)
plt.hist(preds, bins=50,edgecolor='k')
请注意,在开始时很少给出高概率,慢慢地模型开始学习数据的真实分布。
摘要
我们展示了如何使用简单的代码片段创建深度学习模型性能的生动可视化仪表板。按照这里概述的方法,你不必依赖 Tensorboard 或任何第三方软件。您可以创建自己的计算和绘图,根据您的需要进行最大程度的定制。
请注意,上述方法仅适用于 Jupyter 笔记本。您必须针对独立的 Python 脚本对其进行不同的调整。
关于这一点,有另一篇关于这个主题的精彩文章,你可以在这里查看。
[## 如何在 Keras 中绘制模型训练——使用自定义回调函数和 TensorBoard
我开始探索不同的方法来形象化训练过程,同时致力于狗的品种识别…
medium.com](https://medium.com/@kapilvarshney/how-to-plot-the-model-training-in-keras-using-custom-callback-function-and-using-tensorboard-41e4ce3cb401)
你可能也喜欢…
如果你喜欢这篇文章,你可能也会喜欢我下面的深度学习文章,
[## 你在你的 Keras 深度学习模型中使用了“Scikit-learn wrapper”吗?
如何使用 Keras 的特殊包装类进行超参数调优?
towardsdatascience.com](/are-you-using-the-scikit-learn-wrapper-in-your-keras-deep-learning-model-a3005696ff38) [## 用几行代码实现深度学习模型的激活图
我们演示了如何用几行代码显示深度 CNN 模型中各层的激活图
towardsdatascience.com](/activation-maps-for-deep-learning-models-in-a-few-lines-of-code-ed9ced1e8d21) [## 使用 Keras 简化影像分类的单一功能
我们展示了如何构建一个单一的、通用的、实用的函数来从一个目录中自动提取图像…
towardsdatascience.com](/a-single-function-to-streamline-image-classification-with-keras-bd04f5cfe6df)
Y 你可以查看作者的 GitHub 知识库获取机器学习和数据科学方面的代码、思想和资源。如果你和我一样,对人工智能/机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
[## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…
通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和…
www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)
如何打造数据流物联网管道——谷歌云平台
原文:https://towardsdatascience.com/how-to-create-dataflow-iot-pipeline-in-google-cloud-platform-c08caeca13bb?source=collection_archive---------11-----------------------
来自谷歌云平台参考架构的数据管道架构
介绍
在本文中,我们将了解如何在谷歌云平台上配置完整的端到端物联网管道。你会知道-
如何在云物联网核心中创建设备注册表
如何创建主题和订阅
如何使用 GCP Python 物联网客户端向设备发送消息
如何设置发布订阅
如何建立从 PubSub 到 BigQuery 的云数据流管道
如何使用设备注册表和发布订阅设置云物联网核心
前往https://console.cloud.google.com/,使用您的凭证登录并搜索物联网核心。
选择物联网核心后,其主界面页面会打开如下图。
我们首先需要创建注册表来注册设备。
点击创建注册表。创建注册表的新页面打开如下
根据需要为您的注册表命名。您可以看到显示的命名规则。
选择要存储数据的区域。最好让注册表区域靠近设备源
然后您会注意到,它要求命名主题名为 pub-sub,以路由来自注册中心中注册的设备的消息。
所以我们取一个小的散度。转到发布订阅并创建主题和订阅。
在新标签页转到 https://console.cloud.google.com/的并搜索发布订阅
它将打开发布-订阅登录页面,如下所示
由于我已经创建了一个主题,它显示在列表中。
点击创建主题。将打开一个新的创建主题配置页面,如下所示
给一个你想要的话题 ID。它将自动创建一个主题名称,并添加到您的项目路径中。
点击创建主题。完成后,您将看到在主题登录页面中创建的主题。
主题将消息从发布者设备转发到订阅者。任何订阅的消费者都可以使用这些消息。
因此,让我们创建一个订阅,并将其与我们创建的主题相关联。
为此,请在发布订阅的登录页面上单击订阅。它将打开订阅窗格。
点击创建订阅。这将打开订阅配置窗格。
给出你选择的 ID。它将自动创建一个带有项目名称的订阅名称。
将您的订阅与刚刚创建的主题名称链接起来。
保留其余的默认设置,然后单击 Create。
这将创建如图所示的订阅
现在,让我们回到“物联网核心”选项卡,将注册表与我们在“创建注册表配置”窗格中创建的主题相关联。
单击“创建”来创建注册表。
创建注册中心后,物联网核心登录页面将如下所示
点击注册表创建。它将打开如下注册表页面。
我们现在需要创建一个设备实例,并将其与我们创建的注册表相关联。这将完成设备创建、注册表创建、主题订阅创建的路径。然后,我们可以从 GCP 客户端向这些设备发送消息。消息将通过订阅路由到主题。然后,可以用 API 提取消息。
点击设备,然后创建设备选项卡
这将打开设备配置页面。给出一个设备 ID,保留其余的设置,然后点击 create。这将创建一个与注册表相关联的设备实例。
创建 GCP 客户端,通过 MQTT 协议发送消息
下载用于谷歌云平台实施的 Python 脚本@
【https://github.com/GoogleCloudPlatform/python-docs-samples】
转到tree/master/IOT/API-client/end _ to _ end _ example/cloud IOT _ pubsub _ example _ mqtt _ device . py
此客户端依赖于以下 python 库。
argparse,datetime,json,os,ssl,time,jwt,paho MQTT 客户端 。如果需要,可以使用 pip install 将相关的库安装到 python 包中。
客户端文件生成虚拟温度数据消息,并将遥测数据发送到我们在物联网核心上创建的设备。该消息被进一步路由到发布-订阅主题。我们可以在发布订阅中看到消息,也可以订阅和提取消息。
请注意,这是一个基线脚本。您可以根据您的消息要求进行更改。
执行代码
python cloud IOT _ pubsub _ example _ mqtt _ device _ lift PDM . py—project _ id = your project name—registry _ id = your registry id—device _ id = your device id—private _ key _ file = RSApemfile—algorithm = RS 256
您可以使用 openSSL 通过以下命令生成 RSA pem 文件,如下所示-
OpenSSL gen pkey-算法 RSA-out RSA _ private . PEM-pkeyopt RSA _ keygen _ bits:2048
OpenSSL RSA-in RSA _ private . PEM-pub out-out RSA _ public . PEM
当我发布不同的数据时,你会看到不同的信息。但是消息将被确认。
现在让我们去 PubSub 看看消息。
点击您创建的主题 ID
点击查看消息。您将选择订阅。从我们刚刚创建的下拉列表中单击 subscription。
数据流管道
现在让我们来看看如何创建从 PubSub 到 BigQuery 的数据流管道
去 console.cloud.google.com/dataflow。登录页面如下所示
点击从模板创建工作。
给出所需的作业名称、区域端点。从数据流模板中选择 Pub-Sub 到 Bigquery 管道,如下所示。以 project:dataset:tablename 格式命名我们创建的订阅和表名。您还需要在 Google 云存储中指定临时存储位置,如下所示。
你可以在 big query @中寻找更多关于表创建的细节
【https://cloud.google.com/bigquery/docs/schemas】T5T6
您可以在云存储@中了解更多关于桶存储创建的详细信息**
****
单击运行作业选项卡,作业面板将如下所示
现在让我们转到大查询,检查数据是否流入我们的表。
注意 — GCP 不允许启动/停止数据流作业。每次想要停止时,您都必须重新创建一个作业。一定要停止这项工作,因为它会消耗大量资源并给你带来巨额账单。
数据流入数据集 liftpdm_2 的表 acc8。
一旦数据存储在 BigQuery 中,您就可以用于进一步的下游应用程序,如可视化、机器学习等,并将计算出的数据存储回 BigQuery。
结论
我们研究了 step 来创建物联网核心设备和注册表,并将它们与主题相关联。
如何创建发布-订阅主题和订阅?
如何通过物联网 Python 客户端向 PubSub 发送消息?
如何创建从发布订阅到大查询的数据流管道?
下一步怎么样
我们将研究如何利用一些可操作的参数创建与设备的闭环通信。
参考文献
https://cloud.google.com/iot/docs/samples/end-to-end-sample
https://cloud . Google . com/data flow/docs/guides/templates/provided-streaming。
** [## 谷歌云平台/专业服务
这个报告包含了数据流 python API 的几个例子。这些示例是我们看到的常见用例的解决方案…
github.com](https://github.com/GoogleCloudPlatform/professional-services/tree/master/examples/dataflow-python-examples)**
如何使用 Plotly 创建动态 3D 散点图
原文:https://towardsdatascience.com/how-to-create-dynamic-3d-scatter-plots-with-plotly-6371adafd14?source=collection_archive---------28-----------------------
让你的数据技能更上一层楼。
杰森 CS 陈在 Unsplash 上的照片
可视化比纯文本或数字更容易让人记住。可视化的信息力量是纯文本难以达到的。因此,可视化被广泛应用于数据科学领域。可视化的信息能力取决于它的结构。例如,3D 动态图比 2D 图更能说明问题。随着结构变得越来越复杂,我们可以用可视化来表示更多的信息。在将模型应用于数据之前,探索和理解原始数据中的结构是非常重要的。可视化是加速探索数据和帮助建立一个健壮的数据分析过程的很好的工具。
在本帖中,我们将创建动态 3D 散点图,并将它们与 2D 散点图进行比较。我们将使用 Plotly Python (plotly.py),这是一个基于 plotly javascript (plotly.js)构建的开源绘图库。我喜欢 plotly.py 的一点是,它提供了一个高级 API ( plotly express )和一个低级 API ( graph objects )来创建可视化。使用 plotly express,我们可以用很少的代码行创建一个很好的情节。另一方面,我们需要用图形对象编写更多的代码,但是对我们创建的内容有更多的控制权。
让我们首先使用 numpy 和 pandas 创建一个合成数据集。我们从导入库开始。
import numpy as np
import pandas as pdimport plotly.express as px
我们创建了一个数据框架,其中包含属于两个不同类别的一些观察值的 3 个不同的数字特征。我们使用 numpy 数组来表示数字特征,使用 python 列表来创建类别列。
数字特征:
x = np.random.random(size=60)*7 + 1
y = np.random.random(size=60)*7 + 1
z = np.random.random(size=60)
z[-30:] = z[-30:]*5 + 2
分类特征:
categories = "A "*30 + "B "*30
categories = categories.split(" ")
categories.pop(60)
首先创建一个包含 30 个 a 和 30 个 b(中间有空格)的字符串,然后用空格分割该字符串以创建一个包含 30 个条目的列表。由于字符串末尾有一个空格,所以列表的最后一个元素是一个空格(“”)。我们使用pop
方法移除它。
使用这 4 个数组,我们可以创建一个熊猫数据帧。
df = pd.DataFrame({
'cat':categories, 'col_x':x, 'col_y':y, 'col_z':z
})df.head()
让我们创建一个基于 x 列和 y 列的 2D 散点图
fig = px.scatter(df, x='col_x', y='col_y', color='cat',
width=700, height=500,
title="2D Scatter Plot")fig.show()
我们传递 dataframe 的名称、用作 x 轴和 y 轴的列。可选的颜色参数代表数据点的类别。
正如我们所看到的,类别 A 和 b 中的数据点之间没有明显的区别。在某些情况下,在可视化中增加一个特性就能说明很多问题。我们以这样一种方式创建数据帧,即“col_z”具有信息能力。
现在,让我们使用所有功能创建一个 3D 散点图。
fig = px.scatter_3d(df, x='col_x', y='col_y', z='col_z',
color='cat',
title="3D Scatter Plot")fig.show()
col_z 中的值清楚地区分了类别 A 和类别 b。当然,我们可以在 x 轴或 y 轴上使用 col_z,并通过 2D 散点图获得类似的结果。但是,在某些情况下,所有列都包含我们需要的有价值的信息。
让我们构建一个更复杂的数据框架,每个特征对分类都很重要。
特点:
x = np.random.random(size=100)*5
x[-30:] = x[-30:] + 6
x = x + np.random.random(size=100)*8y = np.random.random(size=100)*5
y[:30] = y[:30]*4 + 8
y = y + np.random.random(size=100)*3
y[-30:] = y[-30:] + 4z = np.random.random(size=100)*5
z[30:70] = z[30:70] - np.arange(1,41) / 40
z = z + np.random.random(size=100)*5categories = "A "*30 + "B "*40 + "C "*30
categories = categories.split(" ")
categories.pop(100)
数据帧:
df = pd.DataFrame({
'cat':categories, 'col_x':x, 'col_y':y, 'col_z':x
})df.head()
基于新功能的散点图:
px.scatter_3d
的另一个重要参数是size.
到目前为止,我们创建的图中的点具有相同的大小。然而,我们也可以给size
参数分配一个特性。然后,数据点的大小根据该特征中的值而改变。
我们给color
参数分配了一个分类变量,因此数据点用不同的颜色表示。Plotly 还提供了对color
参数使用数字特征的选项。在这种情况下,点的颜色会根据比例发生变化。
让我们使用size
参数再创建一个 3D 散点图。我们将使用著名的“iris”数据集,它是 plotly 库中的内置数据集。
df_iris = px.data.iris()
df_iris.head()
fig = px.scatter_3d(
df_iris, x='sepal_length', y='sepal_width', z='petal_width', color='petal_length',
size='petal_length', size_max=20
)fig.show()
还有一个参数增加了动态 3D 散点图的信息量,这就是symbol
。它只接受一个分类变量,代表数据点的符号根据类别而变化。例如,类别 A 可以用正方形表示,而类别 B 可以用圆形表示。
一个动态的 3D 图承载了大量的信息。如果“一张图胜过千言万语”,这些 3D 动态图有可能达到 100 万字:)
感谢阅读。如果您有任何反馈,请告诉我。
如何用 Faker 创建假数据
原文:https://towardsdatascience.com/how-to-create-fake-data-with-faker-a835e5b7a9d9?source=collection_archive---------15-----------------------
您可以收集数据或创建自己的数据
由paweczerwi ski在 Unsplash 上拍摄的照片
动机
假设您想要创建具有特殊特征(名称、地址、颜色、电子邮件、电话号码、位置)的特定数据类型(bool、float、text、integers)的数据,以测试一些 Python 库或特定实现。但是找到那种特定的数据需要时间。你想知道:有没有一种快速的方法可以创建你自己的数据?
如果有一个软件包可以让您在一行代码中创建假数据,比如:
fake.profile()
这可以用 Faker 来完成,这是一个 Python 包,它为您生成假数据,范围从特定数据类型到该数据的特定特征,以及数据的来源或语言。让我们来看看如何使用 Faker 来创建假数据。
Faker 的基础
从安装包开始
pip install Faker
进口冒牌货
from faker import Fakerfake = Faker()
Faker 的一些基本方法:
>>> fake.color_name()
'SeaGreen'>>> fake.name()
'Vanessa Schroeder'>>> fake.address()
'3138 Jennings Shore\nPort Anthony, MT 90833'>>> fake.job()
'Buyer, industrial'>>> fake.date_of_birth(minimum_age=30)
datetime.date(1906, 9, 18)>>> fake.city()
'Rebeccastad'
假设你是一本小说的作者,想创造一个角色,但发现想出一个真实的名字和信息既困难又费时。你可以写作
>>> name = fake.name()>>> color = fake.color_name()>>> city = fake.city()>>> job = fake.job()>>> print('Her name is {}. She lives in {}. Her favorite color is {}. She works as a {}'.format(name, city,color, job))
结果:
Her name is Natalie Gamble. She lives in East Tammyborough. Her favorite color is Magenta. She works as a Metallurgist
有了 Faker,你可以瞬间生成一个有说服力的例子!
但是如果我需要特定于一个位置的信息呢?
幸运的是,我们还可以指定我们想要伪造的数据的位置。也许你想创造的角色来自意大利。您还想创建她的朋友的实例。因为你来自美国,所以你很难生成那个地方的相关信息。这可以通过在类Faker
中添加location
参数来轻松解决
fake = Faker('it_IT')for _ in range(10): print(fake.name())
结果:
Lando Bertoli-Bulzoni Danilo Gianvecchio Dott. Margherita Veneziano Bianca Morabito Alfredo Rossetti Claudia Chechi Dott. Gastone Loredan Dott. Fulvio Russo Camilla Crisafulli-Gentileschi Agnolo Gioberti
或者从多个位置创建信息
fake = Faker(['ja_JP','zh_CN','es_ES','en_US','fr_FR'])for _ in range(10): print(fake.city())
结果:
Ceuta
Juanhaven
佳市
East Sarah
山武郡横芝光町
川崎市宮前区
Blondel-sur-Pottier
West Christine
Lake Amandahaven
Weekshaven
如果你来自这些特定的国家,我希望你能认出这个地方。如果您对您可以指定的其他位置感到好奇,请查看此处的文档。
创建文本
创建随机文本
我们可以创建随机文本
>>> fake.text()'Lay industry reach move candidate from local spring. Wind someone really but. One rock fund different down own.'
试试日语
>>> fake = Faker('ja_JP')>>> fake.text()'普通の器官証言する仕上げ鉱山癌。カラム索引障害自体今ブラケット創傷。細かい見出し見出し目的自体持っていました。\nピックバケツリンク自体。職人サワーカラム人形自体。癌ブランチ普通のデフォルト同行ヘア不自然な。\nあった偏差〜偏差今特徴敵。バストスパン拡張助けて。\nスマッシュ彼女ボトル隠す品質隠すサンプル。ヘアパイオニアスマッシュ風景。\nパン発生する装置尊敬する。偏差省略自体。'
从选定的单词创建文本
或者我们也可以从单词列表中创建文本
fake = Faker()my_information = ['dog','swimming', '21', 'slow', 'girl', 'coffee', 'flower','pink']fake.sentence(ext_word_list=my_information)
首次运行:
'Girl slow slow girl flower flower girl.'
第二轮
'Flower 21 flower coffee flower dog.'
创建快速配置文件数据
我们可以通过以下方式快速创建配置文件:
fake = Faker()fake.profile()
正如我们所看到的,关于一个人的大多数相关信息都是很容易创建的,甚至包括邮件、ssn、用户名和网站。
更有用的是,我们可以创建一个由来自不同国家的 100 名用户组成的数据框架
import pandas as pdfake = Faker(['it_IT','ja_JP', 'zh_CN', 'de_DE','en_US'])profiles = [fake.profile() for i in range(100)]pd.DataFrame(profiles).head()
或者创建自定义配置文件
创建随机 Python 数据类型
如果我们只关心数据的类型,而不太关心信息,我们很容易生成随机的数据类型,例如:
布尔代数学体系的
>>> fake.pybool()False
具有不同数据类型的 5 个元素的列表
>>> fake.pylist(nb_elements=5, variable_nb_elements=True)['TiZaWQDCzVIgSALOSKJD', 8100, 'hZTFGZpYVwJUcGZUoauG', Decimal('-3512.1951'), 37442800222.8852, 'XIxdbnwYMfOJDsZlaowZ']
一个有 5 个左数字和 6 个右数字的小数(在.
之后)
>>> fake.pydecimal(left_digits=5, right_digits=6, positive=False, min_value=None, max_value=None)Decimal('92511.722977')
你可以在这里找到更多关于你可以创建的其他 Python 数据类型的信息
结论
我希望你发现 Faker 是一个有效创建数据的有用工具。你可能会发现这个工具对你正在做的事情有用,也可能目前没用。但是知道有一个工具可以让您轻松地为您的特定需求(比如测试)生成数据是很有帮助的。
在这个 Github repo 中,您可以随意使用这篇文章的代码,或者在这里查看关于 Faker 的更多信息。
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。
如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:
[## 凸包:包装数据的创新方法
如何利用包装算法实现数据可视化
towardsdatascience.com](/convex-hull-an-innovative-approach-to-gift-wrap-your-data-899992881efc) [## 字典作为 If-Else 的替代
使用字典创建一个更清晰的 If-Else 函数代码
towardsdatascience.com](/dictionary-as-an-alternative-to-if-else-76fe57a1e4af) [## 跟踪数据的 Python 技巧
如何用列表、字典计数器和命名元组来跟踪信息
towardsdatascience.com](/python-tricks-for-keeping-track-of-your-data-aef3dc817a4e) [## 高效 Python 代码的计时
如何比较列表、集合和其他方法的性能
towardsdatascience.com](/timing-the-performance-to-choose-the-right-python-object-for-your-data-science-project-670db6f11b8e) [## cy thon——Python 函数的加速工具
当调整你的算法得到小的改进时,你可能想用 Cython 获得额外的速度,一个…
towardsdatascience.com](/cython-a-speed-up-tool-for-your-python-function-9bab64364bfd)
如何用 Altair 创建交互式剧情
原文:https://towardsdatascience.com/how-to-create-interactive-and-elegant-plot-with-altair-8dd87a890f2a?source=collection_archive---------14-----------------------
在 5 行简单的 Python 代码中利用您的数据分析
牛郎星是什么?
您是否曾经想要通过放大来仔细查看您的数据,突出显示感兴趣的点,或者使用滚动条来查看数据如何随时间变化?通过对静态图有更多的控制,你会发现你可以对数据有更多的了解。
但是你可以想象创造一个互动的情节一定很有挑战性。所以你决定不参与互动部分。如果有一个 python 库可以让你用几行 Python 代码就能做到这一点,那会怎么样呢?
上图是用 Altair 创建的。 Altair 是 Python 的统计可视化库,基于 Vega 和 Vega-Lite。Altair 提供了强大而简洁的可视化语法,用于快速构建各种各样的统计图形。您只需要声明数据字段、颜色、大小等之间的链接,而让其余的绘图细节自动处理。有了 Altair,你可以花更多的时间 理解你的数据和它的意义,而不是找出代码。
开始
安装 Altair
$ pip install altair
Altair 可以和示例数据集一起安装在 vega_datasets 中:
$ pip install altair vega_datasets
在 Jupyter 笔记本上导入 Altair
import altair as alt
import pandas as pd
Altair 中的一些数据集是围绕熊猫数据框架建立的。这是什么意思?这意味着你可以在 Altair 中操作数据,就像你处理熊猫数据帧一样。
我们将使用 vega_data 中的 gapminder 数据来显示一些国家 1995 年至 2005 年期间的全球健康和人口数据。
from vega_datasets import data as vega_data
gap = pd.read_json(vega_data.gapminder.url)gap.head(10)
找出此数据中有多少独特的年份:
>>> gap.year.unique()array([1955, 1960, 1965, 1970, 1975, 1980, 1985, 1990, 1995, 2000, 2005])
既然我们最感兴趣的是最新的数据,那就让我们看看 2005 年的数据吧。
gap2005 = gap.loc[gap['year'] == 2005]
形象化
指定 X 轴和 Y 轴
我们对生育率和预期寿命之间的相关性很好奇。所以我们指定了我们想要用mark_point()
绘制的图的类型,以点的形式显示数据。我们还可以使用mark_*
以其他几何形状呈现数据
alt.Chart(gap2005).mark_point().encode(
alt.X('fertility'),
alt.Y('life_expect')
)
看起来数据不在图表的中心。通常我们需要用matplotlib
来指定比例,但是用牛郎星,你只需要用scale
的方法
调整比例
不错!但是如果我们想知道人口数量与生育率和预期寿命的关系呢?我们可以利用另一个维度:大小
太棒了。左侧的图例给出了每个圆圈大小的含义。我们能增加另一个维度吗?绝对的!x 轴,y 轴,尺寸,我们遗漏了什么?颜色!
添加颜色维度并指定数据类型
正如您在上面看到的,我们还可以指定数据的类型:N-名义(类别名称)、Q-数量(数字数据)、O-序数(有序数据)或 T-时间(时间点或时间间隔)。在上面的代码中,因为我想将聚类解释为类别数据,所以我使用了:N
为了让我们的圆圈看起来更好,我们用filled=True.
填充颜色,用alt.OpacityValue(0.5)
添加一些不透明度来看大点后面的小点
显示每个点的信息
但是图中有很多点。有没有一种方法,当我们点击每一个点来显示关于国家、生育率和预期寿命的信息?是的,当然。这可以通过添加Tooltip
来完成
能够看到每个点上的信息是很好的。但是如果我们想一次看到多个点的信息呢?不用再等了,让我们直接跳到如何用 Altair 创造一个互动的剧情!
互动情节
选择单点
Selection_single()
使我们能够点击一个点来突出显示它。当我们单击该点时,我们希望其他点变得与灰色无关。这可以通过alt.condition()
完成
现在,我们可以查看感兴趣点的信息,而不会被其他点分散注意力
选择多个点
但是我们可能同时对几个点感兴趣。或者更好,到选择一个区间的点。两者都可以用selection_multi()
和selection_interval()
来完成
因为我们想一次尝试不同的选择工具,所以让我们创建一个函数来完成它。
现在使用alt.hconcat()
尝试不同的选择,并连接这些选择的图形
时间间隔
我们已经看到了 2005 年的数据。如果我们想看到数据随时间的变化呢?通过为alt.selection_single
添加更多的条件,例如name=’select’, fields = [‘year’]
、初始年份init={‘year’: 1955}
和范围bind=alt.binding_range(min=1955, max=2005, step=5)
,可以很容易地做到这一点
不错!现在,通过在select-year
栏上拖动鼠标,我们可以很容易地看到数据随时间的变化
保存情节
创建图形后,我们希望从图形中得到的最后一个函数是什么?保存我们的图表以展示我们的网站或社交媒体!这可以通过点击图表左上角的按钮轻松完成。
结论
恭喜你!您已经学习了如何利用 Altair 进行高效的数据分析。这篇文章并没有详尽地涵盖你可以用 Altair 做的所有事情,比如创建一个堆叠条形图、热图、面积图、地图或其他交互功能。你可以在这里找到更多关于牛郎星图书馆的信息,或者关注 Github 教程。我最希望你从这篇文章中得到的是:用 Python 创建一个有趣而漂亮的图形可以是难以置信的简单和有趣!
在这个 Github repo 中,您可以随意使用本文的代码。
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。
如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:
[## 当生活不给你喘息的机会,如何学习数据科学
我努力为数据科学贡献时间。但是发现新的策略使我能够提高我的学习速度和…
towardsdatascience.com](/how-to-learn-data-science-when-life-does-not-give-you-a-break-a26a6ea328fd) [## 什么是卓越的图形以及如何创建它
作为一名数据科学家,了解如何制作重要的图表至关重要
towardsdatascience.com](/what-graphical-excellence-is-and-how-to-create-it-db02043e0b37) [## 字典作为 If-Else 的替代
使用字典创建一个更清晰的 If-Else 函数代码
towardsdatascience.com](/dictionary-as-an-alternative-to-if-else-76fe57a1e4af) [## 使用 Python 最大化您的生产力
你创建了一个待办事项清单来提高效率,但最终却把时间浪费在了不重要的任务上。如果你能创造…
towardsdatascience.com](/maximize-your-productivity-with-python-6110004b45f7) [## 跟踪数据的 Python 技巧
如何用列表、字典计数器和命名元组来跟踪信息
towardsdatascience.com](/python-tricks-for-keeping-track-of-your-data-aef3dc817a4e)
参考
赫尔,杰佛里。github:https://github.com/uwdata/visualization-curriculum。2017 年 1 月。
如何用 Python 创建交互式可视化
原文:https://towardsdatascience.com/how-to-create-interactive-visualisations-in-python-4af42cf83ba4?source=collection_archive---------23-----------------------
Plotly express 简介
在这个博客中,我们将学习如何用 Python 创建交互式可视化。在探索添加更多的交互式控件之前,我们将从仅仅用不同的格式绘制数据开始。
如果你已经关注我一段时间了,你会注意到这是数据可视化系列的第三篇文章。我们首先介绍了使用默认 python 可视化库 matplotlib 的数据可视化。然后我们学习了如何使用同一个库创建一个时间序列的动画可视化。
[## 了解如何用 Python 创建动画图形
动画数据可视化的基础
towardsdatascience.com](/learn-how-to-create-animated-graphs-in-python-fce780421afe)
今天,我们将学习如何使用 Plotly express。Plotly 允许用户在开箱即用的可视化界面上进行交互,并且更容易与网络内容集成。
plotly express 简介
Plotly express 是 plotly wrapper,它允许更简单的语法。
受 Seaborn 和 ggplot2 的启发,它专门设计了一个简洁、一致和易于学习的 API:只需一个导入,只需一个函数调用就可以制作丰富的交互式绘图,包括分面、地图、动画和趋势线。
如果你想了解更多,可以去 Plotly 的官方媒体岗位看看。
只需两行代码,你就可以拥有一个看起来很酷的交互式图形。这很简单,因为:
import plotly.express as pxfig = px.line(x='x data set', y= 'y data set')fig.show()
获取和准备数据
就像我们在 Python 中的数据可视化系列的前几篇文章中所做的一样,我们将使用新冠肺炎数据。虽然在这篇博客中,我们不会涉及熊猫的运作,这些运作引导我们去获取和格式化我们的数据,如果你想进一步了解它,请阅读这篇文章。
我们将使用以下数据代码来获取和格式化我们的数据:
import plotly.express as px
import numpy as np
import pandas as pdurl = '[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv'](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv')
df = pd.read_csv(url, delimiter=',', header='infer')
df_interest = df.loc[
df['Country/Region'].isin(['United Kingdom', 'US', 'Italy', 'Brazil', 'India'])
& df['Province/State'].isna()]
df_interest.rename(
index=lambda x: df_interest.at[x, 'Country/Region'], inplace=True)
df1 = df_interest.transpose()
df1 = df1.drop(['Province/State', 'Country/Region', 'Lat', 'Long'])
df1 = df1.loc[(df1 != 0).any(1)]
df1.index = pd.to_datetime(df1.index)df1 = df1.diff() #day on day changes
创建图表
线形图
要在图上添加一行,我们实际上需要两行代码:
fig = px.line(x=df1.index, y= df1[df1.columns[0]],title = 'Daily Deaths due to COVID-19', name = df1.columns[0])fig.show()
简单线图
要添加更多的行,我们需要。add_scatter()属性。使用一个循环,我们可以添加范围内的所有国家。
fig = px.line()for i,n in enumerate(df1.columns):
fig.add_scatter(x=df1.index, y= df1[df1.columns[i]], name= df1.columns[i])
多线绘图
最后,我们可以考虑给我们的图表增加一些细节。我个人喜欢在图中突出显示不同的数据点。
fig.update_traces(mode='markers+lines')
带标记的图表
最后但同样重要的是,添加相关的轴标签,设置字体大小并替换默认模板。
fig.update_layout(
title = 'Daily Deaths due to COVID-19'
,xaxis_title = 'Dates'
,yaxis_title = 'Number of Deaths'
,font = dict(size = 25)
,template = 'plotly_dark' #"plotly", "plotly_white", "plotly_dark", "ggplot2", "seaborn", "simple_white", "none"
)
条形图
与我们之前看到的方式非常相似,条形图可以很快地组合在一起:
fig = px.bar()for i,n in enumerate(df1.columns):
fig.add_bar(x=df1.index, y= df1[df1.columns[i]], name= df1.columns[i])fig.update_layout(
title = 'Daily Deaths due to COVID-19'
,xaxis_title = 'Dates'
,yaxis_title = 'Number of Deaths'
,font = dict(size = 25)
,template = 'plotly_dark' #"plotly", "plotly_white", "plotly_dark", "ggplot2", "seaborn", "simple_white", "none"
)fig.show()
饼图
和以前一样,唯一的不同是我们将只显示时间序列中最近的一天。
df1 = df1.tail(1).transpose()
fig = px.pie(df1, values = str(df1.columns[0]), names = df1.index)
fig.update_traces(textposition='inside', textinfo = 'percent+label')ddate = str(df1.columns[0])[:10] #chop timestampfig.update_layout(
title = f'Deaths on {ddate} due to COVID-19'
,xaxis_title = 'Dates'
,yaxis_title = 'Number of Deaths'
,font = dict(size = 25)
,template = 'seaborn' #"plotly", "plotly_white", "plotly_dark", "ggplot2", "seaborn", "simple_white", "none"
)fig.show()
交互式控件
既然我们已经看到了如何快速地将不同类型的观想放在一起,现在是我们用交互控制来增强我们的观想的时候了!
范围滑块
首先,用一行代码,我们将添加一个范围滑块——一个漂亮的控件,允许用户关注时间序列的特定部分。
fig.update_xaxes(rangeslider_visible=True)
距离焦点
如果我们的用户总是关注时间序列中的某些片段,那该怎么办?然后我们就可以直接构建那些控件了!
fig.update_xaxes(
rangeslider_visible=True,
rangeselector=dict(
buttons=list([
dict(count=7, label="1w", step="day", stepmode="backward"),
dict(count=1, label="1m", step="month", stepmode="backward"),
dict(count=2, label="2m", step="month", stepmode="backward"),
dict(step="all")
]),
font = dict( color='#008000', size = 11),
)
)
自定义按钮
体验过前面一组关于焦点范围的功能后,很容易想象构建自定义按钮。Plotly express 以一种简单的方式迎合了这一点。让我们来看一下自定义按钮,这些按钮允许我们关注各个国家。
fig.update_layout(
updatemenus=[
dict(
type="buttons",
direction="right",
active=0,
x=0.5,
y=1.03,
buttons=list([
dict(label=df1.columns[0],
method="update",
args=[ {"visible": [True, False, False, False, False]},
{'showlegend' : True}
]),
dict(label=df1.columns[1],
method="update",
args=[ {"visible": [False, True, False, False, False]},
{'showlegend' : True}
]),
dict(label=df1.columns[2],
method="update",
args=[ {"visible": [False, False, True, False, False]},
{'showlegend' : True}
]),
dict(label=df1.columns[3],
method="update",
args=[ {"visible": [False, False, False, True, False]},
{'showlegend' : True}
]),
dict(label=df1.columns[4],
method="update",
args=[ {"visible": [False, False, False, False, True]},
{'showlegend' : True}
]),
dict(label='All',
method="update",
args=[ {"visible": [True, True, True, True, True]},
{'showlegend' : True}
]),
]),
)
]
)
下拉菜单
获得下拉菜单就像注释掉上一节中的一行一样简单。你所需要做的就是注释掉“type='buttons '”,给你:
结论
Plotly express 绝对是一个非常棒的数据可视化工具,它非常容易上手,使用起来也非常 pythonic 化。在这篇博客中,我们仅仅触及了它所提供的一些皮毛。我非常鼓励你进一步探索这个库,因为可能性真的是无穷无尽的!
如果您觉得这篇文章很有趣,您可能也会喜欢:
[## Python 数据可视化基础
在这篇博客中,我们将学习如何获取、转换并最终吸引人地呈现数据。我们要去工作了…
towardsdatascience.com](/the-basics-of-data-visualisation-with-python-23188aa9fc1a?source=your_stories_page---------------------------) [## 构建用于比较数据的 Python UI
如何快速让您的非技术团队能够比较数据
towardsdatascience.com](/building-a-python-ui-for-comparing-data-13c10693d9e4) [## 估算一个软件的最后期限真的很难——让我们来谈谈为什么
规划时你需要知道的 5 条法则
medium.com](https://medium.com/better-programming/estimating-a-software-deadline-is-really-hard-lets-talk-about-why-44687a6baf9d)
如何使用 Plotly Express 创建交互式可视化
原文:https://towardsdatascience.com/how-to-create-interactive-visualizations-with-plotly-express-a43bd4c6231b?source=collection_archive---------59-----------------------
有许多例子的实用指南
Plotly Python (plotly.py)是一个基于 plotly javascript (plotly.js)构建的开源绘图库。Plotly express 是 plotly.py 的一个高级接口,它允许我们创建许多交互式和信息可视化。
在这篇文章中,我们将一步一步地增加复杂程度,同时浏览许多例子。我们将探究添加到可视化中的每个特征/结构的效果。
如果您的工作环境中没有安装 plotly.py,您可以使用 pip 或 conda 进行安装:
$ pip install plotly==4.8.0$ conda install -c plotly plotly=4.8.0
先来导入 plotly express:
import plotly.express as px
对于示例,我们将使用两个不同的数据集。一个是 kaggle 上的“电信客户流失”数据集。另一个是 gapminder 数据集,可在 plotly 库中找到。plotly 的这些内置数据集对于练习来说很方便。
流失预测是机器学习领域的一个常见用例。如果你不熟悉这个术语,churn 的意思是“离开公司”。对于一个企业来说,了解客户可能流失的原因和时间是非常重要的。拥有一个强大而准确的客户流失预测模型有助于企业采取措施防止客户离开公司。我们将尝试探索数据集,并了解数据集的底层结构。原始数据集包含 7043 个客户的 20 个特征(自变量)和 1 个目标(因变量)。在这篇文章中,我们将只使用 7 个特性和目标变量。
churn = pd.read_csv("Telco-Customer-Churn.csv")churn = churn[['gender', 'Partner', 'tenure', 'PhoneService', 'InternetService', 'Contract', 'MonthlyCharges','Churn']]
churn.head()churn.head()
我们从一个基本的箱线图开始,根据合同类型检查每月费用的分布:
fig = px.box(churn, x="Contract", y="MonthlyCharges")fig.show()
箱线图越高,数值越分散。该图告诉我们,长期合同的月费用范围更大。我们可以通过将鼠标悬停在最小值、第一个四分位数、中值、第三个四分位数和最大值的可视化图形上来查看箱形图的临界值。
我们可以通过颜色参数对不同的组使用不同的颜色,还可以添加一个额外的变量用于比较 facet_col 参数。
fig = px.box(churn, x="Contract", y="MonthlyCharges",
color="Contract", facet_col='Partner')fig.show()
看起来有一个合作伙伴并没有显著改变合同类型。
散点图也常用于理解变量之间的关系。为了演示清楚,我将采用数据集的前 200 行。
churn_filtered = churn.iloc[:200,:]
我们可以检查任期和月费之间的关系,以及这种关系如何根据合同类型和是否有合作伙伴而变化。保有权变量是客户成为客户的月数。
fig = px.scatter(churn_filtered,
x="tenure", y="MonthlyCharges",
color='Partner',
facet_col="Contract", facet_col_wrap=3)
fig.show()
基于指定的变量创建支线剧情。 Facet_col_wrap 参数调整支线剧情的排列。
这个图告诉我们的是,没有合作伙伴的客户倾向于按月签约。此外,有合作伙伴的客户在公司停留的时间更长(任期更长)。这是原始数据集的子集,但是根据这 200 行,公司销售的逐月合同比一年或两年合同多。图中的每个点代表一个客户,我们可以通过悬停在该点上来查看数据。
我们也可以通过使用 groupby 函数检查平均值来确认我们的直觉:
churn_filtered[['Contract','Partner','tenure']].groupby(['Contract','Partner']).mean()
对于每种合同类型,有合作伙伴的客户的任期更长。此外,没有合作伙伴的客户数量在逐月合同细分市场中更多。
让我们来看看每月费用、合同类型和任期方面的流失率。我们还为情节添加了一个标题:
fig = px.scatter(churn_filtered, x="tenure", y="MonthlyCharges",
color='Churn',
facet_col="Contract", facet_col_wrap=3,
title= "Churn Rate Analysis")fig.show()
正如我们在上面的图表中看到的,拥有长期合同的客户不太可能流失(即离开公司)。如果公司想留住客户,首要任务应该是签订长期合同。
我们还可以使用 marginal_x 和 marginal_y 参数向散点图添加分布指示。这次让我们绘制整个数据集,并检查我们的 200 行样本是否真正很好地代表了整体:
fig = px.scatter(churn,
x="tenure", y="MonthlyCharges",
color="Churn",
marginal_y="rug", marginal_x="histogram")fig.show()
我们先来评价一下 x 轴。对于少于 10 个月的任期,red points(流失=是)占主导地位。随着任期的不断延长,蓝点(流失=无)正在成为主导类别。我们还可以在散点图上方的直方图中看到这一点。它显示了红点和蓝点的分布如何根据 x 轴上的位置而变化。大多数流失的客户任期不到 10 个月。
y 轴表示每月费用。散点图中红点的密度随着 y 轴的上升而增加(即每月费用增加)。这也可以在散点图右侧的地毯图上看到。水平线的密度在上部更密集。除了底部之外,蓝点的密度比红点更均匀。
Ploty express 提供了许多数据集来练习。我们可以很容易地将这些数据集加载到熊猫数据框架中。例如, gapminder 数据集包括 142 个国家 12 年的人均 gdp(不连续)。该数据集还包含这些年各国的预期寿命和人口。
gap_df = px.data.gapminder()gap_df.head()
我们来绘制一下 1952 年的人均寿命和人均 gdp。Plotly express 允许在使用查询方法创建绘图时过滤数据帧:
fig = px.scatter(gap_df.query("year==1952"),
x="gdpPercap", y="lifeExp",
hover_name="country",
color="continent", log_x=True
title="GDP vs Life Expectancy in 1952")
fig.show()
通过将 hover_name 参数设置为“country ”,我们能够在点上看到国家的名称。
总的来说,非洲国家的人均国内生产总值较低,欧洲国家的人均国内生产总值处于最高区域。科威特是个异数,人均 gdp 超过 10 万。你可能已经注意到了 x 轴上的对数刻度。我们通过将 log_x 参数设置为 True 来实现它,这使得绘图看起来更好。如果没有 log_x 参数,该图将如下所示:
我们也可以使用大小参数来表示图中的另一个变量。例如,如果我们设置 size="pop ",那么点数的大小就与国家的人口数成比例。
fig = px.scatter(gap_df.query("year==1952"),
x="gdpPercap", y="lifeExp",
hover_name="country",
color="continent", log_x=True,
size="pop", size_max=50,
title="GDP vs Life Expectancy in 1952")
fig.show()
我们已经用 plotly express 介绍了一些基本的可视化类型。当然,这只是这个神奇的图书馆的一小部分功能。我们可以使用 plotly 动态创建许多其他绘图类型。它的语法也很容易理解。在接下来的帖子中,我会尝试涵盖更复杂的情节。你也可以查看 plotly 文档,我认为它有很多不同的例子。就像任何其他主题一样,熟悉 plotly 的最好方法就是实践。因此,我建议创造大量的情节来提高你的技能。
感谢您的阅读。如果您有任何反馈,请告诉我。
如何使用 Spotipy 创建大型音乐数据集
原文:https://towardsdatascience.com/how-to-create-large-music-datasets-using-spotipy-40e7242cc6a6?source=collection_archive---------10-----------------------
为机器学习获取音乐相关数据的最快、最干净的方法
由吉纳罗·塞文和皮克斯拜拍摄的图像
什么是 Spotipy,你能用它做什么?
你是音乐爱好者还是程序员?很有可能,你们都是,就像我一样!当我开始使用 Spotipy 时,我几乎没有编程经验,想探索计算音频分析。现在,随着我深入编程和数据科学,我开始欣赏 Spotipy 为我的数据科学项目创建了令人惊叹的数据集。
这个图书馆非常适合你,如果
- 你是一名数据科学家或程序员,想要为机器学习生成有趣的数据集
- 你是一名音乐家/音乐学家想要学习编程或数据分析
Spotipy 是一个 Python 库,用户可以更容易地访问 Spotify Web API,并从中检索各种音乐数据。当我开始使用 Spotipy 时,这是我第一次接触 API。因此,如果您从未使用过 API,请不要担心。你能做到的!
你可以用 Spotipy 做这些事情
- 使用您自己的用户数据(创建或编辑您的播放列表,查找您最喜欢的曲目等。)
- 获取 Spotify 上每个曲目、专辑和艺术家的数据
在本指南中,我们将探索后一种应用的可能性。我将向您展示如何使用这些数据为统计分析或机器学习项目创建令人惊叹的数据集。
以下是您应该使用 Spotipy 创建数据集的两个主要原因:
- 由于 Spotify 拥有超过 5000 万首歌曲,创建大型数据集的可能性是无限的。最重要的是,一旦您设置好了基础,您将能够非常快速地检索数据。
- 在音乐领域,机器学习有如此多令人惊叹的应用,你可以探索。预测泰坦尼克号幸存者变得无聊了吗?不如你建立一个流派分类器,一个推荐系统,或者一个热门歌曲预测器?在我听来,那听起来更酷。
引起了你的兴趣?太好了!读完这个故事后,你就可以创建你的第一个大样本音乐数据集了(1k,10k,100k?你决定!).为了让你更容易做到这一点,我将通过你需要采取的三个步骤来指导你。
三步指南。1.注册和授权,请按 2。选择要分析的音乐,3。分析曲目并导出数据。
第一步:注册并授权
登记
这是最难的部分,但是坚持住。我们很快就要编码了!为了使用 Spotify Web API,你需要在 https://developer.spotify.com/注册一个应用程序。不管你实际上是在构建一个应用程序还是仅仅在探索 API。这是你走向成功的三个步骤:
- 用你的 Spotify 账户登录 https://developer.spotify.com/dashboard/login的 o r 免费注册一个
- 转到您的仪表板,然后单击“创建客户端 ID”
在这里,您提出了一个应用程序名称(您如何称呼它并不重要)和对它的描述。当我创建我的应用程序时,我只是诚实地写道,我只是想用我的应用程序探索 API。对我很有效。
3.打开你的应用视图,点击“编辑设置”。在重定向 URL 字段中输入 http://localhost/ 。
4.回到你的应用程序视图,点击你的客户端 ID 下的“显示客户端密码”。
5.将客户端 ID 和客户端秘密 ID 存储在文本文件或其他文件中,以便以后快速访问。我们需要他们的授权。
如果我的解释方式对你没有帮助,我建议你查看这部分的不同资源。一个很棒的介绍就是 Max Tingle 的这篇文章。
批准
万一最后一部分对你来说有点混乱或烦人,确保你只用几行代码就能完成无聊的部分。
- 首先,您需要进行两次导入。如果您还没有安装 spotipy,请先使用命令“pip install spotipy”来安装它。
import spotipy
import spotipy.util as util
2.接下来,将您的客户端和秘密 ID 分配给变量。
CLIENT_ID = "YourClientID"
CLIENT_SECRET = "YourSecretID"
3.下面几行代码我就不细说了。我建议你复制粘贴它们,以后再学习。
token = util.oauth2.SpotifyClientCredentials(client_id=CLIENT_ID, client_secret=CLIENT_SECRET)
cache_token = token.get_access_token()
sp = spotipy.Spotify(cache_token)
太好了!现在,您将在步骤 2 中开始分析一些实际的音乐。
第二步:选择要分析的音乐
现在 Spotify API 就在你的脚下,你打算用它做什么呢?如前所述,分析大量的轨迹会产生大量的数据集。然而,手动选择每一首曲目是很痛苦的。你需要一些曲目的集合或列表。以我的个人经验来看,有两个选项非常有用,那就是按播放列表或艺术家来搜索曲目。两者各有利弊,在我们进入真正的分析之前,我将很快介绍一下。
通过播放列表选择音乐
用户 Oscar Lallier 在 Spotify 上的“史上最长播放列表”
播放列表有多大?上面的这个美女有 10,000 首歌曲,这似乎是 Spotify 允许的最大播放列表大小。也许你也想使用包含 5000 首歌曲的“有史以来最大的播放列表”播放列表。环顾四周,你会发现许多这样的大型播放列表,可以用来快速建立一个大型数据集。然而,你必须问问自己,你真正的研究兴趣是什么。这 15000 的集合对任何人都有用吗?也许你想用这样的数据集来调查 Spotify 上的一些音频功能是如何分布的?
另一种方法是根据主题选择播放列表。您可以获取标题中带有“睡眠”一词的播放列表的前 20 个搜索结果。也许你想将“睡眠”播放列表中的歌曲与“专注”播放列表中的歌曲进行比较,找出它们的不同之处。我以前用这种方法分析过浪漫和心碎的歌曲在音乐上是否不同(令人惊讶的是,它们并没有不同)。
如果您选择了您感兴趣的播放列表,请确保存储它们的创建者用户名以及播放列表 id。您可以从 url 中检索 ID,如下所示。
按艺术家选择音乐
另一种选择音乐的方式是通过他们的艺术家。我以前使用过这种方法来建立一个机器学习模型,该模型将新发布的工具专辑“恐惧接种体”中的音乐分配给 6 个进步金属/摇滚乐队中的正确乐队。然而,在这种情况下,你面对的是小样本。很少有艺术家有几百首歌曲,更不用说几千首了。然而,Spotify 有一个“推荐艺术家”功能。您可能想要使用它来增加样本大小,同时仍然使用类似的音乐。
为德国乐队“拉姆斯坦”推荐艺术家:“林德曼”、“魅力”、“移民”、“玛丽莲·曼森”。
一旦你选择了几个艺术家,就像你之前存储播放列表 id 一样存储他们的艺术家 ID。
对于第三步,我将向你展示如何从播放列表中分析音乐。我们鼓励你自己通过 artist 来尝试如何做到这一点。也可以随时问我任何问题。
步骤 3:分析轨迹并导出数据
3.1 分析单个播放列表
让我们进入一些实际的编码。检索播放列表中每个曲目信息的基本 Spotipy 函数是:
sp.user_playlist_tracks("username", "playlist_id")
让我们以 Spotify 的“Warum Fuzzy Feeling”播放列表为例。
Spotify 的“温暖模糊的感觉”播放列表
从 url 中获取 ID,我们现在可以应用该函数。
sp.user_playlist_tracks("spotify", "37i9dQZF1DX5IDTimEWoTd")
输出是势不可挡的,乍一看,对于不习惯处理 API 的人来说完全无法理解。这是一些输出。
sp.user_playlist_tracks 函数的输出
虽然我非常鼓励您自己探索输出,但我不会在这里深入讨论,而只是简单地向您展示您想要的特性以及在哪里可以找到它们。如果您确实想自己探索输出,将它视为多个相互嵌套的字典的集合是很有用的。
这些是我们可以从输出中提取的特征。
- 元信息(艺术家、专辑、曲目名称、曲目 ID)
- 声学参数(响度、音调、模式、速度)
- 心理声学参数(可跳舞性、能量、乐器性、活性、效价)
Spotify 有一些很棒的资源,可以让我们找到更多可以提取的特征(见下图)。点击了解更多。
Spotify 解释他们的“可跳舞性”参数。
因为这是一篇介绍性的文章,所以我将向您展示提取函数,并简要解释它是如何工作的。
- 创建一个包含所有相关列的空数据框架
- 将 sp . user _ playlist _ tracks(" username "," playlist_id ")存储到" playlist "变量中
- 循环播放列表中的每个曲目
- 创建一个空字典来填充音轨信息
- 直接提取元数据
- 通过 sp.audio_features(track_id)提取音频特征
- 将 track_dict 连接到现有的数据帧上
- 返回最终数据帧
这是作为纯代码的函数。你可以在这个 github 库 中以更吸引人的格式找到本教程的全部代码。
def analyze_playlist(creator, playlist_id):
# Create empty dataframe
playlist_features_list = ["artist","album","track_name", "track_id","danceability","energy","key","loudness","mode", "speechiness","instrumentalness","liveness","valence","tempo", "duration_ms","time_signature"]
playlist_df = pd.DataFrame(columns = playlist_features_list)
# Loop through every track in the playlist, extract features and append the features to the playlist df
playlist = sp.user_playlist_tracks(creator, playlist_id)["items"]
for track in playlist: # Create empty dict
playlist_features = {} # Get metadata
playlist_features["artist"] = track["track"]["album"]["artists"][0]["name"]
playlist_features["album"] = track["track"]["album"]["name"]
playlist_features["track_name"] = track["track"]["name"]
playlist_features["track_id"] = track["track"]["id"]
# Get audio features
audio_features = sp.audio_features(playlist_features["track_id"])[0]
for feature in playlist_features_list[4:]:
playlist_features[feature] = audio_features[feature]
# Concat the dfs
track_df = pd.DataFrame(playlist_features, index = [0])
playlist_df = pd.concat([playlist_df, track_df], ignore_index = True)
return playlist_df
此时,您可以复制我的函数,编辑它,或者自己探索 API。在任何情况下,上面的函数都返回一个 dataframe,它可以很容易地转换成您想要的任何数据格式。
输出数据帧
# csv
df.to_csv("dataframe.csv", index = False)
# excel
df.to_excel("dataframe.xlsx", index = False)
3.2 分析多个播放列表
最后,我将向您展示如何创建包含多个播放列表的数据帧。
您可以使用以下函数来完成此任务。它分析每一个播放列表,添加一个带有播放列表名称的“播放列表”列。最后,该函数连接新旧数据帧。
def analyze_playlist_dict(playlist_dict):
# Loop through every playlist in the dict and analyze it
for i, (key, val) in enumerate(playlist_dict.items()):
playlist_df = analyze_playlist(*val)
# Add a playlist column so that we can see which playlist a track belongs too
playlist_df["playlist"] = key
# Create or concat df
if i == 0:
playlist_dict_df = playlist_df
else:
playlist_dict_df = pd.concat([playlist_dict_df, playlist_df], ignore_index = True)
return playlist_dict_df
然而,你需要以特定的格式组织你的播放列表,以使该功能正常工作。正如您在下面看到的,您需要将播放列表存储在一个字典中,将播放列表名称作为键,将它们的创建者和播放列表 id 作为元组形式的值。
playlist_dict = {
“warm_fuzzy_feeling” : (“spotify”, “37i9dQZF1DX5IDTimEWoTd”),
“love_songs_heart” : (“indiemono”, “5KbTzqKBqxQRD8OBtJTZrS”),
“romance_songs” : (“Susan Doles”, “7sAUK3XK8NHH1s5vGcTBkF”)
}
让我们看看运行这个函数会发生什么。
multiple_playlist_df = analyze_playlist_dict(playlist_dict)
multiple_playlist_df["playlist"].value_counts()
输出:
love_songs_heart 100
romance_songs 77
warm_fuzzy_feeling 70
Name: playlist, dtype: int64
如您所见,使用这种方法,您可以轻松地分析 20 个大型播放列表,并获得数千个曲目分析。但是,请记住,您需要进行一些数据清理。特别是,检查重复将是一个重要的步骤。
后续步骤
现在你已经有了第一个音乐数据集,但是下一步做什么呢?以下是一些想法:
- 分析不同流派、情绪或活动的播放列表。将每组播放列表(例如“悲伤”与“快乐”)存储在单独的数据帧中。然后,使用逻辑回归、决策树或深度学习方法(如神经网络或随机森林)来构建分类算法。
- 根据不同的艺术家而不是播放列表来分析音乐。您会发现以下两个函数对此很有用:
sp.audio_analysis(track_id)
sp.audio_features(track_id)
- 构建一个推荐系统,根据流派、情绪或活动输入向用户推荐音乐。
感谢您阅读这篇文章!如果有什么东西不见了或者对你不起作用,请随时给我发信息。
如何直接从 Python 代码创建 Latex 表
原文:https://towardsdatascience.com/how-to-create-latex-tables-directly-from-python-code-5228c5cea09a?source=collection_archive---------7-----------------------
将控制台中的结果表复制到 Latex 报告中是一件单调乏味且充满错误的事情——那么为什么不实现自动化呢?
制作桌子要简单优雅(图片由罗曼·博日科在 Unsplash 上拍摄)。
创建结果表在交流数据科学的实验结果方面起着重要作用。在 Python 中生成表格并在控制台输出中绘制它们有各种解决方案,但是如何将它们转换成书面报告呢?通常,这需要一些耗时和令人麻木的复制和粘贴,但有一些更好的解决方案。
用 Python 制作表格
Python 有几个库允许你绘制表格。在这篇文章中,我将特别关注两个:制表和文本表格。它们都实现了相同的目标——以尽可能少的麻烦生成格式良好的表格。制表是更受欢迎的图书馆,上个月下载量超过 1000 万次。相比之下,texttable 的用户量不到 200 万(根据 2020 年 6 月底的 PyPi 统计数据):
table 和 texttable 的下载比较( PyPi Stats 30/06/2020)
这两个库都允许您以特定的样式格式化表格。Texttable 在选择表格设计方面给予用户完全的自主权;可以定制列对齐、标题对齐、表格装饰、列类型,甚至是用于在行列之间画线的字符。制表选择关注预先设计的格式,但是用户仍然可以选择覆盖这些格式。
我个人的偏好是使用 texttable。十有八九,我使用它是因为它是我遇到的第一个创建表的库,但是它还没有让我失望。
导出到 Latex
制表格式主要是为了在其他平台上使用或模仿它们的设计,例如 github、html、psql。其中一种格式允许创建 latex 代码,为您提供可以直接复制并粘贴到 Latex 文档中的文本。工作完成了——这很容易。
比制表更轻量级的 Texttable 没有提供这样的解决方案。然而,作为一个个人的业余项目,我把我的第一个 Python 库放在一起,作为 texttable 的包装器来创建 Latex 表。我创造性地将其命名为 latextable ,目前它已经在 PyPi 上可用。它提供了与制表 Latex 格式类似的输出,并提供了额外的功能,如匹配 texttable 控制台输出的格式,并允许用户添加表格标题和标签。
使用任何一个库都非常简单;它们都做了它们的设计用途,并且有非常相似的用法。对于包含表数据的行列表,表是这样创建的:
print('Tabulate Table:')
print(tabulate(rows, headers='firstrow'))table = Texttable()
table.set_cols_align(["c"] * 4)
table.set_deco(Texttable.HEADER | Texttable.VLINES)
print('\nTexttable Table:')
print(table.draw())
输出 Latex 代码同样简单:
print(‘\nTabulate Latex:’)
print(tabulate(rows, headers=’firstrow’, tablefmt=’latex’))
print(‘\nTexttable Latex:’)
print(latextable.draw_latex(table, caption=”A comparison of rocket features.”))
它给出了下面的 Latex 代码:
两种 Latex 输出都可以直接复制到 Latex 文档中,latextable 输出具有自动缩进的优点。控制台输出与渲染 Latex 的比较如下所示:
比较控制台输出(左)和渲染 Latex 输出(右)的制表(上)和 texttable/latextable(下)。
我已经在的 Colab 笔记本中提供了这个例子的完整源代码。很可能您仍然需要对 Latex 代码进行一些修改,以得到您想要的样子,但是通过使用这些工具中的一个,您至少不必浪费时间来复制和粘贴东西。这样做的好处是,你在抄写时不会犯任何错误!
如何在 Plotly 中创建非美国位置的地图
原文:https://towardsdatascience.com/how-to-create-maps-in-plotly-with-non-us-locations-ca974c3bc997?source=collection_archive---------17-----------------------
美国人永远不会知道我们的痛苦。
安妮·斯普拉特在 Unsplash 上的照片
Plotly 使在交互式 choropleth 地图中显示地理空间数据变得非常容易,尤其是当您的数据与美国相关时。不幸的是,如果你的数据位置在美国以外,并且比国家一级的数据更细,事情就会变得有点模糊。当您在堆栈溢出和 GitHub 问题中寻找实现映射目标的线索时,您可能会觉得自己像一个可怜的表亲。我在这里说我也经历过,我感受到你的痛苦,也有解决的办法。让我们跳进来吧!
步骤 1:获取一些数据进行绘图
在本教程中,我将显示澳大利亚维多利亚州的失业数据。我从澳大利亚统计局的统计门户网站得到了我的数据。该门户允许您选择数据的地理空间粒度。我选择下载“2016 年人口普查,G43 按年龄和性别分列的劳动力状况(LGA)”,其中 LGA 指的是地方政府区域,这是数据的空间粒度。让我们把它放进去,稍微改变一下形状:
“LGA 2016”一栏指的是每个地方政府区域(LGA)的 ID 或代码。通过旋转数据,我们为每个 LGA 创建了一行,从而创建了一个失业率。这一点很重要,因为当我们创建地图时,我们需要为每个显示的地理空间区域指定一个值。
步骤 2:获取与数据相对应的几何图形
使用美国以外的数据创建 Plotly choropleth 的关键是拥有一个 GeoJSON,其几何图形与您的数据相对应。虽然有时您可能已经有了一个 GeoJSON,但更有可能的是您必须创建一个,对于我来说就是这种情况。
我再次使用澳大利亚统计局,通过此链接访问 ESRI Shapefile 格式的我的数据的几何图形(我下载了“ESRI Shapefile 格式的 ASGS 地方政府区域 Ed 2020 数字边界”)。可以使用 Geopandas 将这种格式加载到 Python 中,方法是将它指向。“shp”文件:
现在我们可以看到,两个数据框都有一列包含每个 LGA 的代码,这就是我们将要加入的内容。每行还有一个“几何”值,即 LGA 的地理空间轮廓。
附注:对于澳大利亚数据的绘图,ABS 将是您获取形状文件的最佳选择。我不太精通其他国家的数据(如果你知道有网站提供你国家的地理数据,请留下评论),但如果你被困住了,http://www.diva-gis.org/gdata 的包含大多数国家的形状文件,可以免费下载。
步骤 3:合并数据和几何图形(可选:使用 Geopandas 显示)
如果您的两个数据框都有像我这样的匹配键,那么在该列上连接它们并删除所需列中没有数据的行就很简单了。
我还喜欢在此时使用 Geopandas 显示我的数据框,作为一种健全性检查,并了解我的 plotly 地图最终应该是什么样子。
澳大利亚维多利亚州的失业率,使用 Geopandas 绘制。
注意:合并数据帧对于绘图中的几何图形来说并不是绝对必要的,但它确实可以将几何图形与要绘制的数据对齐。如果不执行此合并步骤,您将需要确保包含数据的数据框和包含几何的 shapefile/geoJSON 具有对应且排序相同的行。
步骤 4:将数据框转换为 GeoJSON
现在我们有了一个地理数据框架,其中包含了我们需要使用 Plotly 绘制的所有信息。除了一个小细节:Plotly 想要 GeoJSON 格式的。幸运的是,Geopandas 可以轻松地从数据框转换为 GeoJSON,如下所示。不过首先,你要确保你的几何图形是纬度/经度格式(EPSG:4236),这正是 Plotly 所期望的。
您的 GeoJSON 应如下所示:
{'type': 'FeatureCollection',
'features': [{'id': '20110',
'type': 'Feature',
'properties': {'LGA_2016': '20110',
'LGA_CODE20': '20110',
'LGA_NAME20': 'Alpine (S)',
'percent_unemployed': 0.037868162692847124},
'geometry': {'type': 'Polygon',
'coordinates': (((146.67057224400003, -36.56828108499997),
(146.670555271, -36.568038086999934),
(146.67051924600003, -36.567766081999935),
(146.67051924600003, -36.56750909899995),
(146.6704312810001, -36.56723709299996),
...
您可以看到该字典包含一个名为“features”的嵌套字典,其中每个数据框行的索引都存储为“id”。如果您没有使用此方法创建 geoJSON,请确保您的 geo JSON 具有类似的格式。
第五步:剧情!
在下面的代码中有一些需要注意的地方。
首先是,你需要一个 Mapbox 访问令牌。你可以通过在这里创建一个地图箱账户来得到这个。对于个人使用级别,访问 API 将是免费的。
其次,我们为地图分配数据,将 geoJSON 用于几何图形,将合并的数据框用于颜色和文本。
最后,我们设置一些参数来定义地图的布局,包括标题、中心经纬度、缩放级别。
这将生成一个漂亮的交互式地图,显示维多利亚的失业率。不错!
澳大利亚维多利亚州的 Plotly choropleth 显示失业率。
您可以使用自己的数据和 shapefiles 自定义本教程。要在 GitHub 上查看代码,请点击这里。
如何使用 pyRDF2Vec 创建知识图中实体的表示
原文:https://towardsdatascience.com/how-to-create-representations-of-entities-in-a-knowledge-graph-using-pyrdf2vec-82e44dad1a0?source=collection_archive---------12-----------------------
实践教程
关于如何处理知识图中表示的数据的下游 ML 任务的教程。
目录
- 用知识图表示数据
- 运行实例:DBpedia 中的国家
- 用 RDF2Vec 创建实体嵌入
- pyrdf 2 vec 简介
- 有偏差的行走或采样策略
- 行走修改和变换
- 用 pyRDF2Vec 装载 kg
- 创建我们的第一个嵌入
- 调节超参数
- 尝试不同的行走策略
- 采样深度行走
- rdf 2 vec 的缺点和研究挑战
- 代码和数据可用性
用知识图表示数据
图是用来表示无处不在的现象的数据结构,比如社交网络、化学分子和推荐系统。它们的优势之一在于,它们明确地对各个单元(即节点)之间的关系(即边)进行建模,这为数据增加了额外的维度。
我们可以使用 Cora 引用网络来说明这种数据丰富的附加值。该数据集包含数百篇论文的词袋表示以及这些论文之间的引用关系。如果我们应用降维(t-SNE)来创建单词袋表示的 2D 图(图 1,左侧),我们可以看到集群(根据其研究主题进行着色)出现,但它们重叠。如果我们产生一个嵌入的图形网络(图 1,右),考虑到引用信息,我们可以看到集群被更好地分离。
图 1: 左图:每篇论文的词袋表示的 t-SNE 嵌入。右:图网络产生的嵌入,考虑了论文之间的引用。来源:“深度图 Infomax”,Velickovic 等人
知识图 (KG)是一种特定类型的图。它们是多关系(即不同类型的关系有不同的边)和有向(即关系有主语和宾语)。这些属性允许以统一的格式表示来自不同来源的信息。我们可以将知识图转换成规则的有向图,这有助于进一步的分析,如图 2 所示。
图 2: 转换一个正则有向图中的多关系有向 KG。图片作者。
运行示例:DBpedia 中的国家
在这篇文章中,我们将使用一个运行的例子。让我们首先关注为世界各地随机选择的几个国家创建表示。我们将从 DBpedia 中提取每个国家的信息,DBpedia 是从 Wikipedia 中创建的大型通用 KG。
让我们来看看 KG 在一个特定的国家附近是什么样子的:🇧🇪比利时🇧🇪.这个过程类似于转到其对应的 DBpedia 页面,然后递归地点击该页面上的所有链接。我们在下面的图 3 中对此进行了描述。我们注意到,迭代地扩展这个邻域会使事情变得很快复杂,即使我们通过删除一些部分引入了一些简化。尽管如此,我们看到 DBpedia 包含了一些关于比利时的有用信息(例如,它的国歌、最大的城市、货币……)。
我们通过使用 DBpedia SPARQL 端点创建了一个包含国家信息的定制数据集。我们从曼海姆的大学的“机器学习语义网”存储库中检索了一个国家列表。每个国家都包含有关其通货膨胀和学术产出的信息。这些信息被二进制化为“高”和“低”(因此两个二进制分类任务)。此外,对于每个国家,我们检索了他们的大陆(欧洲、亚洲、美洲、非洲或大洋洲),这给了我们一个 5 级分类任务。包含这些国家信息的 KG 是 DBpedia 的一个子集:对于每个国家,我们通过将 KG 扩展三次来检索所有信息。这个过程与图 3 中描述的完全一致。由于 SPARQL 端点的速率限制,深度为 3 的节点及其父节点最多只能包含 10000 个。KG(Turtle 语法)可以在这里下载,带有国家及其标签列表的 CSV 文件可以在这里下载。
图 3: 递归扩展知识图让事情变得复杂得很快。图片作者。
用 RDF2Vec 创建实体嵌入
RDF2vec 代表资源描述框架 To Vector。这是一种无监督的、任务不可知的算法,以数字形式表示 KG 中的节点,允许它们用于进一步的(下游)机器学习任务。RDF2Vec 建立在现有的自然语言处理技术之上:它结合了来自 DeepWalk 和 Word2Vec 的见解。Word2Vec 能够为提供的句子集合(通常称为语料库)中的每个单词生成嵌入。为了生成一个 KG 的语料库,我们提取行走。提取 walks 类似于访问一个实体的 DBpedia 页面并点击链接。你点击的次数相当于一次散步的跳数。这种步行的一个例子,对于比利时来说,将是:比利时->-dbo:首都->-布鲁塞尔市->-dbo:市长->-Yvan Mayeur。注意,我们在遍历中没有区分谓词/属性(例如,dbo:capital 和 dbo:mayor)和实体(例如,比利时、布鲁塞尔、Yvan Mayeur 等等),如图 2 所示。现在,每一步都可以被视为一个句子,该步中的每一跳都对应于一个句子的标记(单词)。一旦我们提取了大量植根于我们想要为其创建嵌入的实体的遍历,我们就可以将其作为语料库提供给 Word2Vec。Word2Vec 将学习每个唯一跳的嵌入,然后可以用于 ML 任务。
pyRDF2Vec 简介
pyRDF2Vec 是一个存储库,包含了 RDF2Vec 算法的 Python 实现。在原始算法的基础上,还实现了不同的扩展。
在本教程中,我将解释我们如何使用 pyRDF2Vec 在 KG 中生成实体的嵌入。此外,我将简要解释 RDF2Vec 的一些扩展,以及如何在 pyRDF2Vec 中使用这些扩展。
图片取自我们的知识库。
有偏向的行走或采样策略
现在,从图 3 中可以注意到,我们可以提取的可能行走的数量随着深度呈指数增长。当我们使用像 DBpedia 这样的大 kg 时,这就成了问题。在最初的 RDF2Vec 论文中,行走只是从图中随机抽样,但是科切兹等人提出了几个度量来偏向行走。这些走步当时被称为有偏走步,但是我们将它们称为符合 pyRDF2Vec 术语的采样策略。一个可能的采样策略示例如图 4 所示。
图 4: 对行走中的下一跳进行采样的一种可能方式是根据外出边的数量来缩放权重。这只是一个例子,有许多不同的指标(基于频率,PageRank,度,…)。图片作者。
行走修改和变换
到目前为止,我们将行走算法解释为从节点的邻居连续采样,直到达到某个深度。但是,我们可以对该算法进行修改(提取算法),或者我们可以对行走进行后处理以包含额外的信息(转换算法)。这是我们在 IDLab 一直在研究的内容。这些策略应用于一个简单的例子,如图 5 所示。
图 5: 从图中提取行走(深度 2)的不同策略。在这个图中,A 和 F 是我们想要从中提取行走的根。c 和 H 属于同一个社区(社区检测)。来源:“知识图中 RDF2Vec 节点嵌入的行走提取策略”,Vandewiele 等人(博客作者)。
既然我们已经介绍了这些改进的行走策略,我们现在讨论 RDF2Vec 算法的三个主要构建模块:(I)一个行走策略 , (ii)一个采样策略,( iii)一个嵌入算法 (NLP)。正如我们将进一步讨论的,这些构建块中的每一个都可以在 pyRDF2Vec 中配置。
用 pyRDF2Vec 加载 kg
知识通常以资源描述框架(RDF)格式表示。pyRDF2Vec 可以通过包装 rdflib 轻松加载不同 RDF 语法的文件。这将把整个 KG 加载到 RAM 存储器中。然而,当 KG 大于可用的 RAM 内存时,这就成问题了。因此,我们也支持与端点的交互:KG 可以托管在某个服务器上,我们的 KG 对象将在任何需要的时候与那个端点进行交互。这大大减少了所需的 RAM 内存,但代价是延迟更长。
用 pyRDF2Vec 加载元数据和知识图
创建我们的第一个嵌入
现在我们已经将 KG 加载到内存中,我们可以开始创建嵌入了!为了做到这一点,我们创建一个RDF2VecTransformer
,然后用新加载的 KG 和一个实体列表调用fit()
函数。一旦模型被拟合,我们可以通过transform()
函数检索它们的嵌入。与常规的 scikit-learn 流程(我们在训练数据上调用fit()
,在测试数据上调用predict()
或transform()
)不同的一点是,训练和测试实体都必须提供给fit()
函数(类似于 t-SNE 在 scikit-learn 中的工作方式)。由于 RDF2Vec 在无人监督的情况下工作,这不会引入标签泄漏。
用默认的超参数创建我们的初始嵌入。我们为每个提供的实体获得 100 维的嵌入。
上面的代码片段会给我们一个列表列表。对于向转换方法提供的每个实体,将返回 100 维的嵌入。现在,为了用肉眼检查这些嵌入,我们需要进一步降低维数。一个很好的方法是使用 t-SNE。我们可以使用下面的代码片段来做到这一点:
用 t-SNE 进一步降低我们嵌入的维数,从 100D 到 2D,以便可视化它们。
这给了我们如图 6 所示的结果。
图 6: 我们初始嵌入的 t-SNE 图。我们可以开始看到国家集群的出现。图片作者。
现在让我们来看看这些嵌入有多好,以便解决我们已经讨论过的三个 ML 任务:两个二元分类任务(高/低通货膨胀和高/低学术产出)和一个多类分类任务(预测大陆)。应该注意的是,由于 RDF2Vec 是无监督的,在创建这些嵌入的过程中,从来没有使用过这个标签信息!RDF2Vec 是任务不可知的,从我们的节点到嵌入的投影不是为特定的任务定制的,嵌入可以用于多个不同的下游任务。让我们创建一个效用函数,它将生成的嵌入作为输入,然后对所有三个任务执行分类:
为三个不同任务的嵌入装配分类器。
现在让我们调用classify(walk_embeddings)
来看看我们基线嵌入的性能:
**Research Rating**
Accuracy = 0.765625
[[26 8]
[ 7 23]]
**Inflation Rating**
Accuracy = 0.5882352941176471
[[14 16]
[12 26]]
**Continent**
Accuracy = 0.6716417910447762
[[13 3 1 1 0]
[ 4 11 0 1 0]
[ 0 1 7 3 0]
[ 1 3 1 14 0]
[ 0 1 0 2 0]]
研究评级、通货膨胀和大陆分类的准确率分别为 76.56%、58.82%和 67.16%。虽然这些准确性远非完美,但它确实显示了所有这些任务的一些信息存在于生成的嵌入中。这些较低精确度的一个可能原因是,由于 DBpedia 的公共 API 的速率限制,只使用了 DBpedia 数据的一个子集。此外,我们只使用默认的超参数来生成我们的嵌入。
调整超参数
如前所述,RDF2Vec 算法的三个构建模块(行走算法、采样策略和嵌入技术)都是可配置的。现在,让我们尝试提取更深层次的遍历并生成更大的嵌入:
设置不同的行走深度和嵌入大小。
我们指定我们想要使用随机行走策略来提取深度为 3 的行走,这对应于从某个 DBpedia 页面跟随 3 个链接,或者在我们转换的 KG 中采取 6 次跳跃(参见图 1)。我们还指定我们想要为每个实体详尽地提取深度为 3 的所有可能的遍历,由None
参数指示。我们没有指定任何采样策略,但是指定了我们想要使用 Word2Vec 嵌入技术来产生大小为 500 的嵌入。这种超参数配置为我们提供了以下精度:
**Research Rating**
Accuracy = 0.78125
[[25 9]
[ 5 25]]
**Inflation Rating**
Accuracy = 0.6470588235294118
[[14 16]
[ 8 30]]
**Continent**
Accuracy = 0.6865671641791045
[[15 0 0 3 0]
[ 6 9 0 1 0]
[ 1 2 6 2 0]
[ 0 3 0 16 0]
[ 0 0 0 3 0]]
如我们所见,三项任务中有两项的准确性有所提高,而第三项任务(通货膨胀分类)的准确性保持不变。
尝试不同的行走策略
pyRDF2Vec 允许我们使用不同的行走策略,不同策略的概述如图 5 所示。此外,我们可以组合不同的策略:pyRDF2Vec 将提取每个策略的遍历,并在提供给嵌入技术之前将提取的遍历连接在一起。让我们试着结合几种行走策略:
我们现在得到的精度是:
**Research Rating**
Accuracy = 0.71875
[[24 10]
[ 8 22]]
**Inflation Rating**
Accuracy = 0.6764705882352942
[[14 16]
[ 6 32]]
**Continent**
Accuracy = 0.7910447761194029
[[15 0 0 3 0]
[ 5 11 0 0 0]
[ 2 0 9 0 0]
[ 0 1 0 18 0]
[ 0 1 0 2 0]]
因此,通胀评级和大陆任务有所改善,但研究评级的表现有所下降。
采样更深的行走
现在,如果我们想要提取更深的行走,我们很快就会遇到内存问题,因为行走的次数会随着行走的深度呈指数增长。这就是抽样策略发挥作用的地方。作为最后一个实验,让我们使用上一节中的行走策略对深度为 6 的 5000 次行走进行采样:
总共提取了 854901 次行走。这为我们提供了以下精度:
**Research Rating**
Accuracy = 0.671875
[[30 4]
[17 13]]
**Inflation Rating**
Accuracy = 0.5
[[14 16]
[18 20]]
**Continent**
Accuracy = 0.8059701492537313
[[17 0 0 1 0]
[ 4 10 0 2 0]
[ 0 2 9 0 0]
[ 0 1 0 18 0]
[ 0 3 0 0 0]]
因此,只有一个大陆分类的改进和其他两个任务的显著恶化。当然,人们可以调整 RDF2VecTransformer 的许多超参数(行走和采样策略及其相应的超参数)和随机森林(或任何其他分类技术)来获得最佳精度,但我们将此作为练习留给读者!
RDF2Vec 的缺点和研究挑战
当前版本的 RDF2Vec 存在一些缺点,需要进一步研究来解决这些缺点:
–最初的 RDF2Vec 实现没有结合 NLP 领域的最新见解:自 2017 年 RDF2Vec 问世以来,NLP 领域已经取得了许多进展。我们目前正在致力于将不同的 NLP 嵌入技术(比如 BERT)实现到 pyRDF2Vec 中。
–随机游走产生的嵌入的表达能力是有限的:游走只是单链,它们捕捉的信息有些有限。行走策略试图缓解这一缺点,但需要在这一方向进行进一步的研究。此外,我们或许可以将不同策略生成的行走组合在一起。
–RDF2Vec 无法扩展到大型 kg:由于可以提取的可能行走的数量随深度呈指数增长,rdf 2 vec 无法很好地扩展到具有大量节点的 kg,尤其是当它包含许多高度连接的节点时。采样策略提高了可伸缩性,但是还可以做更多的研究。
–rdf 2 vec 不能很好地处理 KG 中的数值:目前,遍历中的所有跳,对应于 KG 中的节点,都被作为分类数据处理。这对于有序数据(例如,居民人数和国家大小)来说是次优的。
–rdf 2 vec 不能处理易变数据:如前所述,训练和测试数据都需要提供给我们的fit()
方法。但是如果我们的一些测试数据还不可用呢?这里有一些技术可以提供帮助,比如在线和渐进式学习。
我们希望,通过发布 pyRDF2Vec,提供一个工具包,可以促进解决这些挑战的研究。
代码和数据可用性
pyRDF2Vec 库可以在 Github 上找到。如果你喜欢这个知识库,请给我们一颗星,我们将不胜感激!此外,我们欢迎各种贡献。
这篇博文中使用的自定义数据集可以下载: KG 和 CSV 。我们还在一个 Google Colab 笔记本中提供了所有的代码,这样你就可以从你的浏览器中交互地运行它了!
如何创建可重用的命令行
原文:https://towardsdatascience.com/how-to-create-reusable-command-line-f9a2bb356bc9?source=collection_archive---------41-----------------------
你能把你的多个有用的命令行打包成一个文件以便快速执行吗?
照片由 Joshua Lam 在 Unsplash 上拍摄
动机
作为一个数据科学家,知道一些基本的有用的命令行是很方便的。您可能有一些喜欢的命令行命令,您会一遍又一遍地使用它们。
例如,您想要创建一个 Django 应用程序,这个库使得用 Python 创建 web 应用程序变得容易。要为 Django 应用程序设置文件夹和环境,您需要执行以下操作:
# Create the folder for the app
mkdir newapp# Go to the directory
cd newapp# Create the virtual environment
python -m venv venv# Activate the environment
source venv/bin/activate# Upgrade pip and install Django
pip install --upgrade pip
pip install Django# Create Django project
django-admin startproject myapp# Make the structure cleaner
mv myapp/manage.py ./
mv myapp/myapp/* myapp
rm -r myapp/myapp/
既然我们想在将来使用相同的命令行命令来创建一个新的应用程序,如果我们能够将这些命令保存在某个地方,然后在我们想创建一个新的应用程序时使用它,是不是很好?
像这样简单的事情
./createapp.sh
而设置一个 app 的每一个基本步骤都要照顾到?本文将向您展示如何使您的命令更加可重用和更快地执行。
可重用的命令行
首先,我们用touch
创建一个文件,并使用。sh 表示 shell 脚本。
touch createapp.sh
使用nano
编辑文件
nano createapp.sh
我们应该能够在这里插入所有的命令
用 Control + X 关闭文件(或用 Mac 用 Command + X)。键入 y 保存更改。使用回车键退出文件。
现在用 Bash 运行这个文件
bash createapp.sh
app 应该设置好了,随时可以使用!但是为什么要 bash 呢?Bash 是 shell,即命令语言解释器。有没有办法不用 bash 直接运行文件?试着跑
./createapp.sh
我们会得到这个错误:
bash: ./createapp.sh: Permission denied
这里发生了什么事?使用以下命令查看该文件的权限
ls -l createapp.sh
我们会看到类似这样的东西
-rw-r--r-- 1 khuyentran khuyentran 229 May 14 22:58 createapp.sh
如果我们看一下第一个— ,
后面的字符rw
,我们可以看到拥有该文件的用户可以读r
和写w
,但是不能执行x.
,所以我们只需要使用
chmod u+x createapp.sh
u
代表用户,+
代表添加权限,x
代表执行。现在我们应该可以不用 bash 来运行我们的文件了!
轻轻一点,让你的命令变得可携带
我们发现这个文件非常方便,所以我们决定与我们的朋友分享或在另一台计算机上运行它。我们可能需要意识到环境中可能发生的变化。
默认情况下,我们使用的 Bash shell 在这个目录 /bin/sh 中执行。其他 shells 可能有不同的缺省值。所以为了确保这个文件总是正常工作(当在另一台计算机上使用时),我们应该添加这个添加到我们的createapp.sh
文件的开头
#!/usr/bin/env bash
但是如果我们想要另一个变量呢?
我们已经成功地用 bash 文件创建了一个应用程序。但是如果我们想为我们的下一个应用程序取另一个名字呢?我们可以编辑文件或者使用更快的方法,在我们的脚本中将名称作为变量!
#!/usr/bin/env bash
APPNAME="$1"
mkdir $APPNAME
cd $APPNAME
python -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install Django
django-admin startproject $APPNAME
mv $APPNAME/manage.py ./
mv $APPNAME/$APPNAME/* $APPNAME
rm -r $APPNAME/$APPNAME/
用一个变量替换newapp
,在本例中是 APPNAME。使用$1
指示在运行脚本时获取第一个参数。将每个appname
替换为$APPNAME.
现在快跑
./createapp.sh someapp
另一个新名字的应用程序被创建了!
最后一步:从任何地方运行你的脚本
我们已经成功地从当前目录执行了我们的应用程序。如果我们可以从计算机上的任何目录执行这个脚本,不是更方便吗?
为了使我们的文件能够从任何地方运行,我们将把这个文件添加到 PATH 中,PATH 是一个环境变量,它告诉 shell 在哪个目录中搜索可执行文件。
在 PATH 下找到一个目录列表。
echo $PATH | tr ":" "\n"
选择一个目录,并将文件移动到该目录中。假设我选择/usr/local/bin 作为保存所有工具的目录
sudo mv createapp.sh /usr/local/bin/
就是这样!将来,您可以在计算机的任何目录中使用
createapp.sh someapp
而不需要记住每一步。
结论
恭喜你!您已经学习了如何使您的命令行可重用。如果您尚未使用此工具,您应该考虑将此工具添加到您的工作流程中。你工作流程中的一个小小的改变可能会在未来增加大量的时间。
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上联系我。
如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:
[## 使用这两个工具在您的机器学习项目中实现可重复性
你能打包你的机器学习模型,并根据你的需要挑选一个最好的吗?
towardsdatascience.com](/achieve-reproducibility-in-machine-learning-with-these-two-tools-7bb20609cbb8) [## 如何有效地微调你的机器学习模型
发现为您的 ML 模型寻找最佳参数非常耗时?用这三招
towardsdatascience.com](/how-to-fine-tune-your-machine-learning-models-with-ease-8ca62d1217b1) [## 如何用 Github 组织你的数据科学文章
被新信息淹没?现在,您可以轻松地跟踪文章并为其创建自定义注释
towardsdatascience.com](/how-to-organize-your-data-science-articles-with-github-b5b9427dad37) [## 如何用 Ngrok 用 3 行代码分享你的 Jupyter 笔记本
想象一下,让你的朋友在远程机器上使用你的本地 Jupyter 笔记本
towardsdatascience.com](/how-to-share-your-jupyter-notebook-in-3-lines-of-code-with-ngrok-bfe1495a9c0c) [## 如何使用 HyperDash 远程监控和记录您的机器学习实验
培训需要很长时间才能完成,但你需要去洗手间休息一下…
towardsdatascience.com](/how-to-monitor-and-log-your-machine-learning-experiment-remotely-with-hyperdash-aa7106b15509)
如何使用 Python 从头开始创建简单的新闻摘要
原文:https://towardsdatascience.com/how-to-create-simple-news-summarization-from-scratch-using-python-83adc33a409c?source=collection_archive---------26-----------------------
新闻摘要入门
照片由 Aaron Burden 在 Unsplash
如果你是机器学习领域的新手,特别是自然语言处理(NLP ),你听说过自动新闻摘要,并且对它感兴趣。你一定在想,比如“如何做出一个好的模型?”,“我该学什么?”以及“我应该从哪里开始?”。
然后你开始搜索哪些方法有利于自动摘要,并找到诸如****,的方法,然后你尝试预先训练的模型,并对其结果留下深刻印象。那么你有兴趣为你的母语训练模型。但有一个问题,你生活在第三世界国家,没有预先训练好的模型可用,或者你没有任何超级计算机可以运行,或者你甚至没有找到你的语言的数据集,你也懒得单独给它贴上标签。
所以在这篇文章中,我会给你一个简单的方法来制作简单的新闻摘要。首先,让我们谈谈新闻摘要的方法。
一般来说,新闻摘要方法分为两种,即提取的和抽象的。提取摘要意味着识别文本的重要部分,并使其从原始文本中逐字产生句子的子集;而抽象概括在使用先进的自然语言技术解释和检查文本之后,以新的方式再现重要的材料,以产生新的、更短的文本,该文本传达来自原始文本的最关键的信息。
因为我们最初的目标是做一个简单的摘要,这里我们将使用提取摘要的方法。开始吧,如果想看这篇文章的完整代码,请访问我的 github 。
首先,导入将要使用的包
import numpy as np
import nltk
import re
这里我们使用了 NumPy , nltk ,以及 re 库。NumPy 是用于数值计算的库,nltk 是广泛用于 NLP 的库,re 是用于正则表达式的库。
之后,我们定义将要执行的预处理功能。它旨在集中单词并消除不需要的字符。这里有 3 个预处理功能,即:
- 大小写折叠:将所有字母改为小写
- 清除:删除所有标点和数字,仅保留字母字符
- 标记化:将句子转换成标记
下面是预处理过程的代码
def casefolding(sentence):
return sentence.lower()def cleaning(sentence):
return re.sub(r'[^a-z]', ' ', re.sub("’", '', sentence))def tokenization(sentence):
return sentence.split()
此外,您还可以添加其他功能,如停用词移除、词干提取或词汇化。但是,因为每种语言的用法可能不同,所以本文将不解释该功能,但我提供的 Github 链接中有一个示例。
接下来,我们还需要一个函数将整个故事转换成句子的集合
def sentence_split(paragraph):
return nltk.sent_tokenize(paragraph)
接下来,我们将定义一个函数来计算文档中每个单词的数量。执行这个过程是为了给单词加权,目的是确定该单词是否有效果。以下是该过程的代码
def word_freq(data):
w = []
for sentence in data:
for words in sentence:
w.append(words)
bag = list(set(w))
res = {}
for word in bag:
res[word] = w.count(word)
return res
然后,我们会做一个函数来计算每个句子的权重。这个过程是为了确定哪一个句子被认为最能代表整个故事。
def sentence_weight(data):
weights = []
for words in data:
temp = 0
for word in words:
temp += wordfreq[word]
weights.append(temp)
return weights
现在,我们将使用的所有函数都已定义。我们举个案例吧。例如,我将使用一篇来自的文章,标题为“《纽约时报》向一群愤怒的暴民投降了”。新闻业将会因此而遭殃。****
我们将从手动复制粘贴将网站上的新闻插入变量开始。如果你不想做复制粘贴,对网页抓取感兴趣,可以看我之前的文章《用 Python 做 4 行的 网页抓取新闻》。
**** [## 用 Python 实现 4 行新闻的网络抓取
抓取网站的简单方法
towardsdatascience.com](/scraping-a-website-with-4-lines-using-python-200d5c858bb1)
news = """
IIn a time in which even a virus has become the subject of partisan disinformation and myth-making, it’s essential that mainstream journalistic institutions reaffirm their bona fides as disinterested purveyors of fact and honest brokers of controversy. In this regard, a recent course of action by the New York Times is cause for alarm.On December 27, 2019, the Times published a column by their opinion journalist Bret Stephens, “The Secrets of Jewish Genius,” and the ensuing controversy led to an extraordinary response by the editors.Stephens took up the question of why Ashkenazi Jews are statistically overrepresented in intellectual and creative fields. This disparity has been documented for many years, such as in the 1995 book Jews and the New American Scene by the eminent sociologists Seymour Martin Lipset and Earl Raab. In his Times column, Stephens cited statistics from a more recent peer-reviewed academic paper, coauthored by an elected member of the National Academy of Sciences. Though the authors of that paper advanced a genetic hypothesis for the overrepresentation, arguing that Ashkenazi Jews have the highest average IQ of any ethnic group because of inherited traits, Stephens did not take up that argument. In fact, his essay quickly set it aside and argued that the real roots of Jewish achievement are culturally and historically engendered habits of mind.Nonetheless, the column incited a furious and ad hominem response. Detractors discovered that one of the authors of the paper Stephens had cited went on to express racist views, and falsely claimed that Stephens himself had advanced ideas that were “genetic” (he did not), “racist” (he made no remarks about any race) and “eugenicist” (alluding to the discredited political movement to improve the human species by selective breeding, which was not remotely related to anything Stephens wrote).It would have been appropriate for the New York Times to acknowledge the controversy, to publish one or more replies, and to allow Stephens and his critics to clarify the issues. Instead, the editors deleted parts of the column—not because anything in it had been shown to be factually incorrect but because it had become controversial.Worse, the explanation for the deletions in the Editors’ Note was not accurate about the edits the paper made after publication. The editors did not just remove “reference to the study.” They expurgated the article’s original subtitle (which explicitly stated “It’s not about having higher IQs”), two mentions of Jewish IQs, and a list of statistics about Jewish accomplishment: “During the 20th century, [Ashkenazi Jews] made up about 3 percent of the U.S. population but won 27 percent of the U.S. Nobel science prizes and 25 percent of the ACM Turing awards. They account for more than half of world chess champions.” These statistics about Jewish accomplishments were quoted directly from the study, but they originated in other studies. So, even if the Times editors wanted to disavow the paper Stephens referenced, the newspaper could have replaced the passage with quotes from the original sources.The Times’ handling of this column sets three pernicious precedents for American journalism.First, while we cannot know what drove the editors’ decision, the outward appearance is that they surrendered to an outrage mob, in the process giving an imprimatur of legitimacy to the false and ad hominem attacks against Stephens. The Editors’ Note explains that Stephens “was not endorsing the study or its authors’ views,” and that it was not his intent to “leave an impression with many readers that [he] was arguing that Jews are genetically superior.” The combination of the explanation and the post-publication revision implied that such an impression was reasonable. It was not.Unless the Times reverses course, we can expect to see more such mobs, more retractions, and also preemptive rejections from editors fearful of having to make such retractions. Newspapers risk forfeiting decisions to air controversial or unorthodox ideas to outrage mobs, which are driven by the passions of their most ideological police rather than the health of the intellectual commons.Second, the Times redacted a published essay based on concerns about retroactive moral pollution, not about accuracy. While it is true that an author of the paper Stephens mentioned, the late anthropologist Henry Harpending, made some deplorable racist remarks, that does not mean that every point in every paper he ever coauthored must be deemed radioactive. Facts and arguments must be evaluated on their content. Will the Times and other newspapers now monitor the speech of scientists and scholars and censor articles that cite any of them who, years later, say something offensive? Will it crowdsource that job to Twitter and then redact its online editions whenever anyone quoted in the Times is later “canceled”?Third, for the Times to “disappear” passages of a published article into an inaccessible memory hole is an Orwellian act that, thanks to the newspaper’s actions, might now be seen as acceptable journalistic practice. It is all the worse when the editors’ published account of what they deleted is itself inaccurate. This does a disservice to readers, historians and journalists, who are left unable to determine for themselves what the controversy was about, and to Stephens, who is left unable to defend himself against readers’ worst suspicions.We strongly oppose racism, anti-Semitism and all forms of bigotry. And we believe that the best means of combating them is the open exchange of ideas. The Times’ retroactive censoring of passages of a published article appears to endorse a different view. And in doing so, it hands ammunition to the cynics and obfuscators who claim that every news source is merely an organ for its political coalition."""
之后,我们将通过把新闻切割成句子的形式来处理它,然后使用我们上面定义的函数对每个句子进行预处理。
sentence_list = sentence_split(news)
data = []
for sentence in sentence_list:
data.append(tokenization(cleaning(casefolding(sentence))))
data = (list(filter(None, data)))
之后,我们将从我们定义的函数中统计文档中每个单词的数量。
wordfreq = word_freq(data)
然后,从单词计算的结果我们只需要计算每个句子的权重。
rank = sentence_rank(data)
之后,我们决定要输出多少个主要句子来表示新闻。例如,我将输出 2 个句子,所以这里我用 2 填充 n。然后,系统将选择权重最高的前两个句子。要看你选择多少个句子出现。
n = 2
result = ''
sort_list = np.argsort(ranking)[::-1][:n]
for i in range(n):
result += '{} '.format(sentence_list[sort_list[i]])
要显示结果,请使用以下代码
print(result)
所以结果会是这样的。
The editors did not just remove “reference to the study.” They expurgated the article’s original subtitle (which explicitly stated “It’s not about having higher IQs”), two mentions of Jewish IQs, and a list of statistics about Jewish accomplishment: “During the 20th century, [Ashkenazi Jews] made up about 3 percent of the U.S. population but won 27 percent of the U.S. Nobel science prizes and 25 percent of the ACM Turing awards. Detractors discovered that one of the authors of the paper Stephens had cited went on to express racist views, and falsely claimed that Stephens himself had advanced ideas that were “genetic” (he did not), “racist” (he made no remarks about any race) and “eugenicist” (alluding to the discredited political movement to improve the human species by selective breeding, which was not remotely related to anything Stephens wrote).
不错吧?虽然它可能不如我们使用最先进的方法,但我们可以很好地理解我们简短新闻的本质。根据我的提示,通过使用这种方法,您可以生成自己的数据集,尽管它仍然有局限性,因为获得的结果并不总是您想要的方式。
祝你好运!****
如果你喜欢这个帖子,我想推荐一篇启发了我 的 文章。
使用快照和数据工厂备份您的 Azure 存储
原文:https://towardsdatascience.com/how-to-create-snapshots-and-backups-of-your-azure-storage-e72bef58e0aa?source=collection_archive---------21-----------------------
了解如何使用 blob 快照和数据工厂增量备份来自动备份您的数据湖
完整的数据湖恢复解决方案请看我的后续博客:https://towards data science . com/how-to-recover-your-azure-data-lake-5b 5e 53 f 3736 f
1.Azure 存储备份-简介
Azure 存储总是存储您数据的多个副本。当使用地理冗余存储(GRS)时,它也被复制到配对区域。这样,GRS 可以防止数据在灾难发生时丢失。但是,当应用程序错误损坏数据时,GRS 无法防止数据丢失。然后,损坏的数据会被复制到其他区域/地区。在这种情况下,需要一个备份来恢复你的数据。两种备份策略如下:
- 快照创建:在添加或修改 blob 的情况下,从当前情况创建快照。由于 blob 的性质,这是一个高效的 O(1)运算。快照可以快速恢复,但是,恢复并不总是能够完成(例如,已删除的 blobs),请参见下一个策略。
- 增量备份:在添加或修改 blob 的情况下,会在另一个存储帐户中创建增量备份。复制 blobs 是一个开销很大的 O(N)操作,但是可以使用 Azure Data Factory 异步完成。恢复可以通过复制 blobs 来完成。
在这篇博客中,讨论了如何从存储帐户创建快照和增量备份,另请参见下面的概述。
1.数据湖备份—高级概述
为了支持您的存储帐户的自动快照和增量备份的创建,在本博客的剩余部分将使用和讨论三种类型的脚本:
- 生产者触发的基于事件的脚本,用于在接收/修改数据后创建快照和增量备份请求
- 使用 ADFv2 创建增量备份的队列触发器脚本
- 管理员触发的基于时间的脚本,用于协调丢失的快照/增量备份
请注意, blob 快照仅在常规存储帐户中受支持,在 ADLSgen2 中尚不受支持(但预计在 ADLSgen2 中也会可用)。因此,脚本基于常规存储帐户,下面提供了脚本的详细说明。另请注意,脚本处理快照/备份的创建,而不是恢复。
2.基于事件触发的快照/增量备份请求
在数据湖中,数据通常由生产者使用 Azure Data Factory 获取。要创建基于事件的触发快照/增量备份,应部署以下内容:
- 将下面的脚本部署为 Python 中的 Azure 函数。见此链接如何用 Python 创建 Azure 函数。参见我的另一篇博客如何保护 Azure 函数。
- 将 Azure 函数作为链接服务添加到 Azure 数据工厂实例中,并将 Azure 函数作为最后一步添加到摄取管道中。
- 创建两个存储帐户作为源存储和备份存储。还要创建一个存储队列来处理备份请求消息。
现在,每次使用 ADFv2 接收新数据时,都会调用一个 Azure 函数来创建快照,并为新的/已更改的 blobs 发送增量备份请求,另请参见下文。
2.基于事件触发的快照/增量备份请求
脚本 HttpSnapshotIncBackupContainerProducer的内部工作原理可以解释如下:
- 0.初始化快照/备份脚本通过将 blob 的 ETag 与之前的快照(如果有)进行比较,来检查存储帐户的容器中的已修改/新 blob。在它检测到修改的/新的斑点的情况下,完成以下 2 个步骤:
- 1a。从修改的/新的 blob 创建快照
- 1b。向存储队列发送增量备份请求消息。备份请求消息仅包含已修改 blob 的元数据。
脚本的核心如下:
**# Get all blobs in container** prev_blob_name = ""
prev_blob_etag = ""
blob_list = container.list_blobs(include=['snapshots']) for blob in blob_list: if blob.snapshot == None:
**# Blob that is not snapshot
** if prev_blob_name != blob.name:
**# New blob without snapshot, create snapshot/backup**
create_snapshot_backup(blob.name, blob.etag)
elif prev_blob_etag != blob.etag:
**# Existing blob that has changed, create snapshot/backup** create_snapshot_backup(blob.name, blob.etag) prev_blob_name = blob.name
prev_blob_etag = blob.etag
请注意,只有生产者 ADFv2 托管身份和此 Azure 函数托管身份对此容器具有写访问权限。Blob 触发器在这种情况下不起作用,因为修改 blob 时不会触发任何事件。
异步增量备份创建将在下一章讨论。
3.增量备份创建
一旦新的增量备份请求被添加到存储队列,该消息将被处理,从而创建增量备份。在这种情况下,应部署以下内容:
- 将下面的脚本部署为 Python 中队列触发的 Azure 函数。可以使用与步骤 2 中相同的应用服务计划
- 确保正确填写所有必需的应用程序设置,参见此处
- 部署 ADFv2 管道,通过将 blobs 从源存储帐户复制到备份存储帐户来创建增量备份
- 确保您为 Azure 函数分配了一个托管身份,并且 Azure 函数拥有 RBAC 角色“contributor”来运行它
现在,每次在存储队列上接收到新的增量备份请求消息时,都会触发一个 Azure 函数,该函数调用创建增量备份的 ADFv2 管道,另请参见下文。
3.增量备份创建
脚本 queuecreateblobbackupadfv 2的工作原理可以解释如下:
- 2a。存储队列收到 blob 的新备份请求消息。请注意,消息可以并行处理
- 2b。Azure 函数从存储队列中提取消息,并检查备份请求是否过期。然后,它使用 REST API 和 Azure Function 托管身份触发 ADFv2 管道
- 2c。ADFv2 通过将 blob 从源存储帐户复制到备份存储帐户来启动复制活动
在步骤 2b 中,还可以决定运行 blob_lease 模式,该模式排他地锁定文件并保证文件的正确版本被添加到备份存储帐户。是否使用 blob 租约取决于许多因素(例如,允许的最大租约时间、文件大小、作业数量、不变性)。
脚本的核心如下:
USING_BLOB_LEASE = True **# check if source blob has not changed in the meantime** if source_blob_changed(blob_name, blob_etag) == True:
return**# Start copying using ADFv2** try:
if not USING_BLOB_LEASE:
**# Copy without locking the file
** copy_adf_blob_source_backup(blob_name, blob_etag)
else:
**# Copy with blob lease locks the file
** copy_with_lease(blob_name, blob_etag) except:
logging.info("copy failed")
在前两章中,我们讨论了当生产者使用 ADFv2 向数据湖添加新数据时,如何创建快照和增量备份。但是,也可能需要触发基于时间的快照/增量备份。这将在下一章讨论。
4.基于时间的触发快照/增量备份请求
在第 2 章中,讨论了生产者如何创建基于事件的快照/增量备份请求。然而,还需要能够创建丢失快照和/或丢失备份的协调脚本。当生产者忘记将 Azure 功能添加到其摄取管道和/或脚本无法运行时,会发生这种情况。为了创建基于时间的功能,应部署以下内容:
- 将下面的脚本部署为 Python 中的 Azure 函数。可以使用与步骤 2 中相同的应用服务计划。
- 确保正确填写所有必需的应用程序设置,参见此处
现在,管理员可以将协调脚本配置为定期运行,以便创建快照并发送增量备份请求,另请参见下文。
4.基于时间的触发快照/增量备份请求
脚本 httpsnapshotincbackupstoragereconcing的内部工作原理可以解释如下:
- 0.基于初始化快照/备份时间的脚本通过将 blob 的 ETag 与以前的快照(如果有)进行比较,来检查存储帐户中修改的/新的 blob。在它检测到修改的/新的斑点的情况下,完成以下 2 个步骤:
- 1a。如果它检测到还没有快照的修改的/新的 blob,则创建新的快照:
- 1b。如果它检测到还没有增量备份的修改的/新的 blob,则发送新的备份请求消息
脚本的核心如下:
**# Get all containers in storage account**
container_list = client_source.list_containers()
for container in container_list:
**# Get all blobs in container
** prev_blob_name = ""
prev_blob_etag = ""
blob_list = container.list_blobs(include=['snapshots'])
for blob in blob_list:
if blob.snapshot == None:
**# Blob that is not snapshot
# 1\. Check if snapshot needs to be created
** if prev_blob_name != blob.name:
**# New blob without snapshot, create snapshot**
create_snapshot(blob.name, blob.etag)
elif prev_blob_etag != blob.etag:
**# Existing blob that has changed, create snapshot** create_snapshot(blob.name, blob.etag) **# 2\. Check if incremental backup needs to be created**
**# Check if blob exists in backup** blob_exists = check_blob_exists(blob.name, blob.etag)
if blob_exists == False:
**# Not in backup, put backup request message on queue**
queue_json = "{" + "\"container\":\"{}\",
\"blob_name\":\"{}\", \"etag\":\"{}\""
.format(container.name, blob.name, blob.etag) + "}"
queue_service.put_message(queue, queue_json)
prev_blob_name = blob.name
prev_blob_etag = blob.etag
5.结论
Azure 存储始终存储您的数据的多个副本,地理冗余存储(GRS)在成对的区域中额外存储副本。但是,GRS 存储不能保护因应用程序错误而损坏的数据。然后,损坏的数据会被复制到其他分区和区域。可以防止数据损坏的两种方法如下:
- 快照创建:一旦添加或修改了 blob,就会为当前情况创建一个快照。
- 增量备份:一旦添加或修改了一个 blob,就会创建该 blob 到另一个存储帐户的增量备份。
在这篇博客中,我们讨论了如何使用 github 中的脚本创建同步快照和异步增量备份。另请参见下文描述的扩展高级概述。
1.数据湖备份—高级概述扩展
如何创建 Tableau 数据警报
原文:https://towardsdatascience.com/how-to-create-tableau-data-alerts-3e7f508555ec?source=collection_archive---------43-----------------------
在你的老板接到你客户的电话之前得到关于数据异常的通知
图片由苏·曼斯菲尔德从皮克斯拜拍摄
当你有一套自动化的报告提供给你的商业伙伴时,你最终会收到可怕的电话或电子邮件。“我本打算在与客户会面时使用这些数据,但它看起来不太对。”要么是数据出了问题,要么是管道坏了,要么就是出现了可以解释的异常现象。当问题是由于你的一个中断的过程引起时,接到电话是令人尴尬的。最好在你的用户看到它之前得到通知。我将回顾如何在 Tableau 中设置通知。第一个知道。
有时候你需要设置一个主动预警。没什么问题,但是…但是你需要提前通知,这样你就可以密切关注整个过程。
如果你关注我的文章,你就会知道我尽量不去烦无聊的业务 KPI(当呼叫等待时间超过 2 分钟时提醒我,诸如此类)。让我们为一些有趣的事情设置一个提醒。假设你有一个连续测量你的万圣节糖果碗。不给糖就捣蛋的人来了,你购买了各种糖果,另一个家庭成员正在分发。私底下,你真的很想在士力架吃完之前吃一块。你还需要知道你什么时候会没有糖果,因为你可能需要在食品室里找一些应急储备(有人要吃吗?).
设置
我试图在 Tableau Public 上做这个演示,但是我现在找不到任何可以在 Tableau Public 上设置警报的地方。我不得不切换到 Tableau 服务器。如果您的公司使用 Tableau,您很可能可以在已发布的工作表上设置预警。
来自 Pixabay 的 pixel1 的图像
数据
实时数据会有当前的日期和时间,如下表所示。我开始时每个人有 40 块糖果,数字逐渐减少,代表所有的小公主和忍者都来拿他们的糖果。因为我今晚要运行这个,所以我必须相应地调整日期/时间。
糖果碗算数——作者截图
工作簿
要在数据达到警报阈值时得到通知,您需要在过滤器架上将日期和/或时间设置为相对日期或时间。
Tableau Public 上的工作簿设置—作者截图
警报
工作簿发布后,任何具有访问权限的人都可以设置通知。首先,突出显示您想要监控的数据元素。在这种情况下,我希望在士力架用完时得到提醒。我还可以在 Bowl 泳道中设置总数警报。
在已发布的工作簿上设置警告—作者截屏
当满足警报条件时,您会收到一封电子邮件。
有人提醒我跑去拿最后一块士力架!—作者截图
多甜啊?
结论
不要让数据的变化让你吃惊。设置警报只需一分钟。第一个知道!如果有问题,您可以在任何人注意到之前解决它。
参考:
[## 从 Tableau Online 或 Tableau Server 发送数据驱动的警报
当数据达到您业务的重要阈值时,数据驱动的警报会自动向以下人员发送电子邮件通知…
help.tableau.com。](https://help.tableau.com/current/pro/desktop/en-us/data_alerts.htm)
如何使用 Atom 为数据科学创建最棒的开发环境?
原文:https://towardsdatascience.com/how-to-create-the-most-awesome-development-setup-for-data-science-using-atom-261113b46be8?source=collection_archive---------8-----------------------
令人敬畏的 Atom 功能使其成为 Python 的优秀编辑器
Github + Markdown +堆栈溢出+自动完成+ Jupyter
在我开始这篇文章之前,我只想说我喜欢 iPython 笔记本,Atom 在任何方面都不是 Jupyter 的替代品。笔记本为我提供了一个界面,在这里我不得不一次思考编码一个代码块,我喜欢这样称呼它,它帮助我更清晰地思考,同时帮助我使我的代码更加模块化。**
然而,Jupyter 目前的形式并不适合某些任务。最突出的是当我不得不处理.py
文件的时候。一个需要合作的人。py 文件,每当他们想把你的代码推向生产或改变别人的代码。所以,直到现在,我用 sublime text 编辑 Python 文件,我发现它非常优秀。但是最近,当我查看 Atom 编辑器时,当我看到它提供的多个开箱即用选项时,我的忠诚度似乎发生了转变。
现在,Atom 的真正力量来自您可以安装的各种包。在这篇文章中,我将讨论帮助 Atom 成为有史以来最易被黑客攻击和最健康的开发环境的包。
安装 Atom 和一些开始的调整
在我们开始之前,我们需要安装 Atom。你可以在主网站这里做。无论您的平台是什么,安装过程都非常简单。对于 Linux,我只是下载了.deb
文件,双击它。一旦你安装了 Atom,你可以看看做一些调整:
- 使用
Ctrl+Shift+P
打开 Atom 中的核心设置,并在其中键入设置。这个Ctrl+Shift+P
命令将成为 Atom 中最重要的命令之一,因为它允许您导航和运行许多命令。
使用 Ctrl+Shift+P 访问设置窗口
- 现在进入
Editor
菜单,取消勾选Soft Tabs
。这样做是为了使TAB
键注册为TAB
而不是两个空格。如果需要,您也可以激活“Soft Wrap
”,如果文本超出窗口宽度,它会自动换行。
我首选的软包装和软标签设置。
现在,我们已经安装了 Atom,我们可以看看它提供的一些最棒的包。而其中最重要的是 GitHub。
1.不离开编辑器提交到 Github
您是否厌倦了每次向 Github 提交时都离开文本编辑器使用终端?如果您的答案是肯定的,Atom 通过让您无需离开文本编辑器窗口就可以提交来解决这个问题。
这是将我从崇高文本推向 Atom 的主要特征之一。我喜欢 Atom 预装的这一功能,并且设置它不需要太多时间。
要开始使用它,请点击 Atom 屏幕右下方的 Github 链接,Atom 屏幕会提示您登录您的 GitHub 以提供访问。这是一次性的设置,一旦您登录并将生成的令牌交给 Atom,您将能够从 Atom 屏幕本身推送您的提交,而无需导航到终端窗口。
****
点击 GitHub,然后登录
推送提交的过程是:
- 更改任何文件或多个文件。
- 点击右下角的 Git。
- 上演变革
- 编写提交消息。
- 点击右下角的推送。
- 我们完成了:)
下面,我将一个非常简单的提交推送到 Github,在这里我将一个标题添加到我的 Markdown 文件中。这是一个 GIF 文件,所以可能需要一些时间来加载。
在 Atom 中提交
2.用实时预览写减价
每当我为自己的网站写博客时,我总是在媒体编辑和 Markdown 之间左右为难。首先,当我不得不在帖子中使用数学符号或使用自定义 HTML 时,我更喜欢使用 Markdown。但是,我也喜欢媒体编辑器,因为它是所见即所得(所见即所得)。有了 Atom,我终于找到了完美的 markdown 编辑器,它为我提供了 Markdown 和 WYSIWYG。现在它已经成为我为 GitHub 创建任何 README.md 文件的默认选项。
在 Atom 中使用 Markdown 也是小菜一碟,默认情况下是激活的。要在 Atom 中查看 Markdown 的实时预览:
- 使用
Ctrl+Shift+M
打开降价预览窗格。 - 您在文档中所做的任何更改都将近乎实时地反映在预览窗口中。
降价分屏编辑器
3.小地图——大型代码文件的导航地图
到目前为止,我们还没有给 Atom 安装任何新的包,所以让我们安装一个基础包作为我们的第一个包。这个包被称为小地图,它是我在崇高的文字时代喜欢拥有的东西。它让你有一个侧面板,你可以点击并到达代码的任何部分。对于大文件非常有用。
要安装软件包,你可以去设置,然后点击安装软件包。Ctrl_Shift+P > Settings > + Install > Minimap> Install
安装小地图或任何软件包
一旦你安装了这个包,你就可以在你的屏幕上看到这个小地图。
侧边栏轻松导航大文件
4.在文本编辑器中使用函数定义的 Python 自动完成
一个编辑器永远不会真正完整,除非它为你提供一些你喜欢的语言的自动完成选项。Atom 与 Kite 集成得很好,Kite 尝试集成 AI 和 autocomplete。
因此,要启用 Kite 的自动完成功能,我们可以在 Atom 中使用名为[autocomplete-python](https://atom.io/packages/autocomplete-python)
的包。安装步骤与之前相同。即Ctrl+Shift+P > Settings > + Install > autocomplete-python> Install
。你也会看到使用风筝的选项。我通常最终使用 Kite 而不是 Jedi(另一个自动完成选项)。这是使用 Kite 自动完成功能处理 Python 文档时的样子。
使用 Kite 的自动完成功能也可以让你看到函数定义。
5.Hydrogen —在 Jupyter 环境中运行 Python 代码
想在带有 Jupyter 内核的 Atom 编辑器中运行 Python 吗?这也有办法。我们只需要用和以前一样的方法安装氢气。安装氢气后,您可以通过以下方式使用它:
- 使用
Ctrl+Enter
运行光标所在的命令。 - 从内核选择屏幕中选择任意内核。我从列表中选择
pyt
内核。 - 现在我可以继续在
pyt
内核中工作了。
使用 Ctrl+Enter 运行命令会询问您使用哪个环境。
有时,您可能在 Atom 中看不到环境/内核。在这种情况下,您可以安装 ipykernel,使该内核对 Jupyter 和 Atom 可见。
下面是如何在 Jupyter/Atom 中创建一个新内核并使其可见的方法:
**conda create -n exampleenv python=3.7
conda activate exampleenv
conda install -c anaconda ipykernel
python -m ipykernel install --user --name=exampleenv**
一旦您运行这些命令,您的内核将被安装。现在,您可以使用以下命令更新 Atom 的内核列表:
Ctrl+Shift+P >Hydrogen: Update Kernels
您的内核现在应该可以在 Atom 编辑器中使用了。
6.文本编辑器中的搜索堆栈溢出
堆栈溢出是任何开发人员生活中不可或缺的一部分。但你知道麻烦是什么吗?离开编码环境,去 Chrome 搜索你需要做的每一件简单的事情。结果我们一整天都在这样做。那么,如果我们可以从 Atom 访问堆栈溢出呢?你可以通过"ask-stack"包准确地做到这一点,它让你在 SO 上搜索问题。我们可以使用Ctrl+Alt+A
来访问它
使用 Ctrl+Alt+A 访问 Atom 中的堆栈溢出。
您可以使用的其他一些值得尊敬的软件包有:
- 电传 : 做配对编码。
- Linter: 检查代码的风格和编程错误。要在 Python 中启用林挺,可以使用“ linter ”和“Python-linters”。
- 高亮显示选中的 : 通过双击或用光标选择文本来高亮显示文本的所有出现。
- 原子-文件-图标 :在左侧树形视图中提供文件图标。看起来比以前好多了,对吧?
文件图标
结论
在这篇文章中,我谈到了如何在 Python 开发流程中使用 Atom。
Atom 中还有很多您可能喜欢的其他包,您可以看看它们,让您的环境更加可定制。或者一个甚至可以像 Atom 一样编写自己的包的人被称为 【最可黑客攻击的编辑器】 。
如果你想学习 Python,但又不完全是 Python 编辑器,我想向你推荐密歇根大学的一门优秀的中级 Python 课程。一定要去看看。还有,这里是我的课程推荐2020 年成为数据科学家。
将来我也会写更多初学者友好的帖子。在 媒体 关注我,或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系到我。
此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。
如何使用 GANs 创建独特的神奇宝贝
原文:https://towardsdatascience.com/how-to-create-unique-pokémon-using-gans-ea1cb6b6a5c2?source=collection_archive---------18-----------------------
以及如何让它变得更好的想法
我儿子真的很喜欢口袋妖怪。我不明白,但我想这是题外话。不过,我确实开始想知道,我是否可以利用深度学习自动为他创建新的口袋妖怪卡片。
我最终成功地使用生成对抗网络(GANs)生成了类似口袋妖怪的图像,我想其他人可能会喜欢看到这个过程。
生成对抗网络
来源
我不想花太多时间讨论什么是 gan,但上面的图像是对过程的一个非常简单的解释。
你训练两个网络——一个鉴别器和一个生成器。生成器学习如何接受随机噪声并生成看起来像来自训练数据的图像的图像。它通过将其生成的图像馈送到鉴别器网络来做到这一点,该鉴别器网络被训练来辨别真实图像和生成的图像。
生成器被优化以越来越好地欺骗鉴别器,而鉴别器被优化以越来越好地检测生成的图像。因此,两者共同提高。
如果你想了解更多,你可以通过谷歌找到许多令人惊叹的文章、书籍和 YouTube 视频。
所以——我的假设是,我可以用真实的口袋妖怪图像作为我的训练集来训练 GAN。结果将是一个发电机,然后将能够创造新的口袋妖怪!太棒了。
数据
我的第一个挑战是寻找口袋妖怪的图像。幸运的是,Kaggle 数据集拯救了我们!
有人已经想到了一个类似的想法,虽然听起来他在生成新的口袋妖怪图像方面没有太大的成功,但是因为他花了时间收集 800 多张图像,他决定将它们上传到 Kaggle 数据集。
这节省了我大量的时间。
我还了解到,实际上只有大约 800 个口袋妖怪,所以不可能用额外的口袋妖怪来扩展这个数据集。
以下是其中一幅图像的示例(256 x 256):
该算法
现在我有了数据,我必须选择我想要使用的 GAN 类型。可能存在数百种不同的 GAN,但我在过去使用 DCGAN 时看到了很好的结果。
DCGAN 从神经网络中消除任何完全连接的层,使用转置卷积进行上采样,并用卷积步长(以及其他)替换最大池。
我喜欢 DCGANs,因为与我尝试过的其他 gan 相比,它们似乎更健壮,因此更容易训练,而无需对超参数进行重大调整。
事实上,DCGAN 是如此受欢迎,以至于 PyTorch 有一个非常好的实现作为它的例子之一。最棒的是,他们的例子可以直接从文件夹中读取输入。因此,通过下面的命令,我可以开始训练我的 GAN:
python main.py --dataset folder --dataroot ~/Downloads/pokemon/ --cuda --niter 10000 --workers 8
这个命令从~/Downloads/pokemon 文件夹中读取图像,在我的 GPU 上运行,有 8 个工人加载数据,并运行 10,000 次迭代。
事实证明 10,000 次迭代对这个问题来说太多了,但是我想看看我能把它推进多远。我们来看看吧!
结果呢
第一步从一无所知的网络开始,所以产生的都是噪音:
每个盒子是一个 64 x 64 像素的图像,并试图从我们的生成器生成一个口袋妖怪。由于我们的网格是 8 x 8,我们有 64 个不同的口袋妖怪试图生成。我将图像缩小到 64 x 64,因为当试图生成更大的图像时,这种算法变得不稳定(或者至少对我来说是这样)。
50 个纪元后,我们开始看到一些生命:
150 年后,事情变得更清楚了:
3700 后,你有一些中途体面的 64 x 64 尝试口袋妖怪。在这之后,它开始转向更坏的结果:
现在——我知道你在想什么,那些看起来一点也不像口袋妖怪!
我想请你把浏览器缩小到 25%左右,再看一遍。从远处看,它们和真正的口袋妖怪惊人地相似。
问题是,由于我们是在 64 x 64 的图像上进行训练,鉴别器很容易被形状和颜色都像口袋妖怪的图像所欺骗,因此生成器不需要改进。
后续步骤
在我看来,显而易见的下一步是训练更高分辨率的 GAN。事实上,我已经在这方面做了一些尝试。
我的第一次尝试是重写 PyTorch 代码,以缩放到 256 x 256 的图像。代码起作用了,但是 DCGAN 坏了,我无法稳定训练。我相信这主要是因为我只有大约 800 张图片。虽然我做了一些数据扩充,但这不足以训练更高分辨率的 DCGAN。
然后,我尝试使用一个相对论 GAN ,它已经成功地用小数据集对高分辨率数据进行了训练,但也无法正常工作。
我将继续尝试一些其他的想法来生成更高分辨率的口袋妖怪,如果我得到一些工作,我会张贴我使用的技术。
别的不说,也许我们可以把这些生成的口袋妖怪叫做烟雾型口袋妖怪?
你也可以在这里找到这个故事。
有兴趣了解有关 Python 数据分析和可视化的更多信息吗?查看我的课程。
如何在 Python 中创建用户定义的函数
原文:https://towardsdatascience.com/how-to-create-user-defined-functions-in-python-e5a529386534?source=collection_archive---------2-----------------------
通过定义您自己的函数来提升您的 Python 游戏
拉杆脚轮
你有没有想过,“我希望 Python 有一个做 ________ 的函数。”填空。如果是这样,我有个好消息!Python 让您能够创建自己的自定义函数。有几件事你需要明白,但这并不难做到。所以让我们开始吧。
自定义函数是很好地打包可重用代码块的好方法。在最基本的层面上,自定义函数只需要五个组件:
- 使用 def 关键字开始函数定义。
- 说出你的函数。
- 提供一个或多个参数。实际上参数是可选的,但是括号不是。后跟冒号。
- 输入代码行,让你的函数做任何事情。输入代码,此处的 #逻辑如下面的示例代码所示。
- 在函数末尾使用 return 关键字返回输出。这也是可选的。如果省略,该函数将返回 None。
如您所见,函数的基本框架很简单。让我们停止玩理论思维,创建一个实际的功能。
函数名
每个函数都需要一个名字。否则,当您需要使用它时,就无法在代码中引用它。给你的函数起一个直观的名字。如果您的函数的目的是对您通过参数列表发送给它的所有数字求和,请将其命名为 add_nums() 或 sum_the_numbers() 。不要将其命名为 s() 或 function1()。最后两个是糟糕的选择。记住,代码是由人类阅读的。
此外,函数名后面必须跟一组括号。如果你不需要任何参数,括号将是空的,但它们必须存在。然后用冒号结束定义行。冒号表示该行下面的任何缩进行都是函数的一部分。
因素
一旦命名了函数,就要决定所需的参数。参数或自变量用于将相关数据传递给函数。这个函数能把多少个数字加在一起?如果没有提供参数,将使用默认值吗?论点的顺序是什么?
参数被插入到函数名后面的括号中。它们由逗号分隔。同样,使用直观的名称,这样您可以很容易地回忆起每个参数的用途。
如果我们的函数只将两个数相加,我们可以创建两个参数, num1 和 num2 。如果我们改变函数来添加三个数字,我们可以添加第三个参数, num3 。
如果您选择为参数分配默认值,只需将当前参数名称替换为 num1=0 和 num2=0 。0 应该替换为您想要分配的任何默认值。
通常,当你执行一个函数时,你会使用一行类似于 sum_the_numbers (5,3) 的代码来调用它。通过提供默认值,您可以从代码的执行行中省略一个或多个参数,函数仍然会运行,只使用默认值。
逻辑
现在让我们给函数添加一些逻辑。这就是函数将数字相加的原因。如果您正在执行一个简单的任务,例如将两个数字相加,这一部分可能会很短。或者,对于更复杂的任务,这一部分可能有数百行代码。记住,作为函数一部分的所有代码行都必须像下面的 total = num1 + num2 行一样缩进。
返回值
既然您的代码已经完成了规定的工作,您可能需要也可能不需要向调用您的函数的进程返回值。如果不需要返回值,可以省略 return 语句。然而,在这个示例函数中,我们需要返回总和。该行是返回总计。
return 语句将存储在 total 中的值发送回执行该函数的代码段。通常会有一个变量来存储返回值。例如,求和= sum_the_numbers (5,3) 。该函数返回的值将存储在求和变量中。现在我们已经拥有了成功实现函数的所有必要组件,让我们看看如何在代码段中执行它。
执行功能
每当我们执行一个用户定义的函数时,我们使用带有任何必需参数的函数名。如果函数返回值,我们通常会对它的输出做一些事情。我们可以把它打印出来,存储在一个变量中,或者发送到另一个函数中。假设我们要将输出存储在一个变量中,我们的函数执行可能类似于下面的代码。
如果我们选择将返回值直接打印到屏幕上,我们可以使用下面的代码。
请记住,当您调用您的函数时,参数必须按照您在函数定义中列出的顺序提供, num1 后跟 num2 。但是,如果您忘记了顺序,只要在执行函数时指定参数关键字,就可以更改顺序。当使用参数关键字时,该命令将类似于 sum_the_numbers (num2=5,num1=10) 。
不确定数量的参数
我相信你已经看出我们设计的问题了。每次我们希望添加更多的数字时,我们都需要添加另一个参数。但是有一种方法可以处理函数中无限多的参数。使用*args 技术,而不是在函数定义的括号中列出每个参数名。
当一个*跟在一个参数名后面时,它表示可以向该函数传递任意数量的参数。这将创建一个参数值列表。您只需在函数中解包 args 列表。我们功能上的这一小小变化使它变得更加灵活。
把所有的放在一起
通常,用户定义的函数和执行它的代码在同一个 Python 脚本中。在我们的例子中,整个脚本看起来像这样。
标准的用户定义函数使用起来很简单,但是对于开发人员来说是一个非常强大的工具。当然,用户定义的函数不会因为这种标准方法而停止。如果你在网上或者从深夜的电视购物节目中买东西,你会期望花 19.95 美元得到更多。用户定义的函数也是如此。
匿名函数
如果你喜欢标准的用户定义函数,你会喜欢匿名的用户定义函数。这些函数是在您需要的地方内联编写的,没有名称,也没有适当的定义语法。这些函数也被称为理解函数或λ函数。
对于这个例子,假设我们的场景和上面一样。我们需要一个能将两个数相加的函数。我们可以使用 lambda 函数来代替 sum_the_numbers 函数。
Lambda 是用来定义这些函数的 Python 关键字,而不是 def 。因此,它们通常被称为λ函数。
在这个 lambda 函数的例子中,我们将变量 answers 定义为函数本身。然后,当我们引用变量名时,我们只需传入所需的参数。结果是一个伪装成动态变量的匿名函数。
简而言之,匿名函数的语法是lambda argument _ list:expression。
让我们的例子更进一步,假设这个场景从一个数字列表开始。我们需要通过平方第一个列表中的每个数字来创建一个新的数字列表。我们可以像上面那样创建一个标准的用户定义函数来完成这个任务。但是,我们决定使用匿名函数。
为了遍历列表,我们使用 Python 的 map 函数。map 函数有两个参数。第一个是函数。在这种情况下,它将是一个匿名函数。第二个参数是一些可迭代的数据,比如我们要平方的数字列表。map 函数将获取 iterable 中的每一项,通过指定的函数运行它,并将输出附加到一个新的 iterable 数据结构中。
这段代码中的 list() 函数将 map 函数的默认可迭代输出(map 对象)转换为 Python 列表。列表在我们代码的其余部分更容易使用。
同样,你可以看到,与下面使用的标准方法相比,我们的 lambda 代码相对较短。
结论
投入必要的时间来学习如何用 Python 实现用户定义的函数。他们很强大。他们创建可重用的代码块。他们帮助组织你的代码。如果您开始使用面向对象编程技术,它们是绝对必要的。用户自定义函数是现代开发人员必备的工具。
如何在 Python 中使用地理空间数据创建 Voronoi 区域
原文:https://towardsdatascience.com/how-to-create-voronoi-regions-with-geospatial-data-in-python-adbb6c5f2134?source=collection_archive---------7-----------------------
地理数据科学
在 Python 中创建和绘制 Voronoi 图的逐步指南
安迪·福尔摩斯在 Unsplash 上的照片
假设你打算步行去车站取一辆小型摩托车。附近有很多车站。你应该去哪家取滑板车骑?
最近的车站,对!
但是,你怎么知道离你家最近的车站呢?
输入 Voronoi 图。
Voronoi 图是多边形的集合,所有点都在最接近单个对象的平面上。
换句话说,每个多边形分区都与一个对象相关联,并且包含与该对象最近的所有点。
应用程序
Voronoi 图的应用很多,通常包括确定哪个特征最接近任何给定点。例如,确定在邻近区域的给定点上哪所学校最近。或者哪个手机发射塔离我手机最近才能打电话。
据说,1854 年约翰·斯诺绘制的霍乱爆发图在五天内导致 500 人死亡,该图在一张图表上绘制了水泵数据,并有效地构建了伦敦内部街区的 Voronoi 图。
我们不能在这里列出 Voronoi 图所有可能的用例。尽管如此,它的应用是深远的,包括人类学和考古学,统计学和数据分析,市场营销和气象学。这里有一长串它的应用。
用 Python 创建 Voronoi 区域
在本教程中,我们使用幼儿园数据集创建一个 Voronoi 图。该数据集包含瑞典乌普萨拉县的所有幼儿园。为了创建 Voronoi 图,我们将使用几个库,包括 Geopandas 和 Geovoronoi 。
让我们先导入库并读取数据。
import numpy as np
import geopandas as gpd
import contextily as ctx
import matplotlib.pyplot as pltfrom shapely.ops import cascaded_unionfrom geovoronoi.plotting import subplot_for_map, plot_voronoi_polys_with_points_in_area
from geovoronoi import voronoi_regions_from_coords, points_to_coordsgdf = gpd.read_file("data/preschools.shp")
gdf.head()
如数据的前几行所示,我们有一个几何列,其中包含点和一些其他属性,如县、邮政地址等..
学前教育数据
我们可以绘制点数据。为了给出一些背景,我们还读取了县的边界,并在其上绘制了点。
boundary = gpd.read_file(“data/uppsala.shp”)fig, ax = plt.subplots(figsize=(12, 10))
boundary.plot(ax=ax, color=”gray”)
gdf.plot(ax=ax, markersize=3.5, color=”black”)
ax.axis(“off”)
plt.axis(‘equal’)
plt.show()
输出是显示瑞典乌普萨拉县所有幼儿园(黑点)的地图。
乌普萨拉的幼儿园
在我们计算 Voronoi 区域之前,我们需要确定两件事。首先,我们需要检查数据的投影,然后将其转换为 Web 墨卡托投影(epsg=339599。
boundary = boundary.to_crs(epsg=3395)
gdf_proj = gdf.to_crs(boundary.crs)
其次,我们需要将数据准备成 Geovoronoi 库可以使用的格式。这里,我们将边界几何转换为多边形的并集。我们还将 Geopandas 点对象的地理序列转换为 NumPy 坐标数组。
boundary_shape = cascaded_union(boundary.geometry)coords = points_to_coords(gdf_proj.geometry)
计算 Voronoi 区域
现在,我们已经准备好了数据,我们可以简单地使用 Geovoronoi 的方法 voronoi_regions_from_coords()来计算 Voronoi 区域。
# Calculate Voronoi Regions
poly_shapes, pts, poly_to_pt_assignments = voronoi_regions_from_coords(coords, boundary_shape)
输出包含形状、点以及两者之间的标识链接。
绘制 Voronoi 图
为了绘制 Voronoi 图,我们还使用了 geo Voronoi—plot _ Voronoi _ polys _ with _ points _ in _ area()的功能。这里,我们提供了上述 Voronoi 计算的所有输出和边界形状。
fig, ax = subplot_for_map()plot_voronoi_polys_with_points_in_area(ax, boundary_shape, poly_shapes, pts, poly_to_pt_assignments)ax.set_title('Voronoi regions of Schools in Uppsala')plt.tight_layout()
plt.show()
输出是一个 Voronoi 图,它将学校点划分为离每个位置最近的区域。
Voronoi 图
上面的地图很小,但好处是我们可以使用熟悉的 Matplotlib 接口来调整它。让我们先看看 plot _ Voronoi _ polys _ with _ points _ in _ area()函数的参数和文档。
plot_voronoi_polys_with_points_in_area**(
** ax**,
** area_shape**,
** poly_shapes**,
** points**,
** poly_to_pt_assignments**=None,
** area_color**='white',
** area_edgecolor**='black',
** voronoi_and_points_cmap**='tab20',
** voronoi_color**=None,
** voronoi_edgecolor**=None,
** points_color**=None,
** points_markersize**=5,
** points_marker**='o',
** voronoi_labels**=None,
** voronoi_label_fontsize**=10,
** voronoi_label_color**=None,
** point_labels**=None,
** point_label_fontsize**=7,
** point_label_color**=None,
** plot_area_opts**=None,
** plot_voronoi_opts**=None,
** plot_points_opts**=None,
)**
**Docstring:**
All-in-one function to plot Voronoi region polygons `poly_shapes` and the respective points `points` inside a
geographic area `area_shape` on a matplotlib Axes object `ax`. By default, the regions will be blue and the points
black. Optionally pass `poly_to_pt_assignments` to show Voronoi regions and their respective points with the same
color (which is randomly drawn from color map `voronoi_and_points_cmap`). Labels for Voronoi regions can be passed
as `voronoi_labels`. Labels for points can be passed as `point_labels`. Use style options to customize the plot.
Pass additional (matplotlib) parameters to the individual plotting steps as `plot_area_opts`, `plot_voronoi_opts` or
`plot_points_opts` respectively.
如您所见,我们可以使用许多参数来格式化可视化。文档也非常清晰和有用。
我们可以增加点的图形大小和标记大小。我们也可以使用 Matplotlib Colormap 改变颜色。这只是一种方式,还有其他方式可以调整,我留给你。
fig, ax = plt.subplots(figsize=(14,12))plot_voronoi_polys_with_points_in_area(ax, boundary_shape, poly_shapes, pts, poly_to_pt_assignments,
voronoi_and_points_cmap=’tab20c’,
points_markersize=20)ax.set_title(‘Upssalla Preschools — Voronoi Regions’)
ax.axis(“off”)
plt.tight_layout()
plt.show()
现在的输出贴图与之前的默认贴图相比要好得多。
沃罗诺伊——乌普萨拉幼儿园
结论
Voronoi 图是有用的,并且在许多地理应用中广泛使用。在本教程中,我们已经介绍了如何使用 Python 创建 Voronoi 图。
本文的代码和数据可以在这个 Github 存储库中找到。
[## shakasom/voronoi
用 Python 制作 Voronoi 图。在 GitHub 上创建一个帐户,为 shakasom/voronoi 的发展做出贡献。
github.com](https://github.com/shakasom/voronoi)
如何创建你的第一个机器学习模型
原文:https://towardsdatascience.com/how-to-create-your-first-machine-learning-model-4c8f745e4b8c?source=collection_archive---------4-----------------------
凯尔西·奈特在 Unsplash 上的照片
用 Python 创建简单机器学习模型的指南
许多机器学习教程专注于机器学习工作流的特定元素,如数据清理、模型训练或算法优化。然而,如果你是机器学习的新手,没有完整简单的解释或演练,很难完全掌握基本的端到端工作流。
在下面的帖子中,我将提供一个非常简单的教程,用 python 开发一个有监督的机器学习模型。在这篇文章中,我将假设你只有非常基本的 python 编程知识,并且已经安装了一些常用的数据科学库。如果你首先需要一个关于数据科学的 python 介绍, Codeacademy 是一个不错的起点。我还将提供教程中包含的所有库的文档链接。
什么是机器学习?
机器学习是计算机能够学习一些输入(数据特征)和一些已知输出(数据标签)之间的映射而无需显式编程的能力。目标是,给定未知输出的新输入,机器可以正确预测标签。
"机器学习本质上是一种事物标签.", 卡西科兹尔科夫
这种输入到输出的映射由数学函数执行,主要来自线性代数和微积分领域,其执行速度和规模在没有大量计算能力的情况下是无法实现的。有许多不同的算法可以完成这项任务,从简单的基于回归的方法到更复杂的深度学习技术。
幸运的是,python 编程语言有一个非常活跃的开源开发者社区,他们构建了许多库,这些库抽象出了直接编写这些算法的需求。其中一个核心的机器学习库是 scikit-learn ,对于初学者来说非常容易访问。在本教程中,我将关注这个库。
数据
为了简单起见,我将使用机器学习来解决一个分类问题。我将使用 scikit-learn API 中的一个玩具数据集,该数据集包含三种类型的葡萄酒(标签或目标)的许多葡萄酒属性(特征),如酒精度和颜色。
要加载数据并将其转换为 pandas 数据框,请使用如下所示的代码。
from sklearn.datasets import load_wine
import pandas as pdwine = load_wine()
data = pd.DataFrame(data=wine['data'], columns = wine['feature_names'])
data['target'] = wine['target']
data.head()
因为机器学习算法是基于数学的,所以用于机器学习的数据本质上必须是数字。这个数据集完全是数字的,但是,如果我们有分类特征,我们将需要执行一些预处理来首先将它们转换成数字。我选择了这个数据集,这样我就可以展示开发模型的最简单的工作流,而不用引入更多关于数据预处理的高级概念。
测试列车分离
在开发机器学习模型时,重要的是能够评估它能够将输入映射到输出并做出准确预测的能力。但是,如果您使用模型已经看到的数据(例如,在训练期间)来评估性能,那么您将无法检测诸如过度拟合之类的问题。
过度拟合是指模型在训练数据中学习了过多的细节或噪音,而这些不一定存在于看不见的数据中。在这种情况下,模型在训练数据上表现良好,但在看不见的数据上表现不佳。这通常被称为模型不能很好地概括。
机器学习中的一个标准是,首先把你的训练数据分成一组用于训练,一组用于测试。对于要进行的精确大小划分没有规则,但是为训练保留更大的样本是明智的——典型的划分是 80%训练数据和 20%测试数据。
重要的是,数据也是随机分割的,这样您就可以很好地表示两组数据中存在的模式。Scikit-learn 有一个工具可以在一行代码中完成这个过程,这个工具叫做 test_train_split 。下面的代码将特性和目标数据传递给函数,并指定 20%的测试大小。
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(data.drop('target', axis=1), data['target'], test_size=0.20, random_state=0)
基线模型
接下来训练一个虚拟分类器以获得基线分数来为模型开发的进一步迭代设定基准是一个好主意。Scikit-learn 有一个功能,允许你训练一个模型,并根据简单的规则进行预测,比如随机预测。这有助于评估您的模型开发在您迭代后续步骤时是否有所改进。
在下面的代码中,我训练了一个虚拟分类器,它总是预测最频繁出现的类。然而,虚拟分类器对此有许多不同的方法。准确度分数是 0.44。完美的准确度分数应该是 1.0。现在进入下一阶段,我们将知道我们是否在这个基线上有所改进。
from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_scorebaseline = DummyClassifier(strategy='most_frequent', random_state=0).fit(X_train, y_train)
y_pred = baseline.predict(X_test)
print(round(accuracy_score(y_test, y_pred),4))
型号选择
现在我们有了一个训练好的基线模型,我们需要评估是否有另一种算法可以更好地处理我们的数据。Scikit-learn 有这个有用的备忘单,它将让你了解解决分类问题的不同算法。
下面的代码循环遍历一系列分类算法,并打印出结果分数。输出显示在代码下方。
from sklearn.metrics import accuracy_score, log_loss
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC, LinearSVC, NuSVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysisclassifiers = [
KNeighborsClassifier(3),
SVC(kernel="rbf", C=0.025, probability=True),
NuSVC(probability=True),
DecisionTreeClassifier(),
RandomForestClassifier(),
AdaBoostClassifier(),
GradientBoostingClassifier()
]for classifier in classifiers:
model = classifier.fit(X_train, y_train)
print(classifier)
print("model score: %.3f" % model.score(X_test, y_test))
我们可以看到,RandomForestClassifier 对于该模型表现最佳,因此我们将选择该算法来训练我们的最终模型。
超参数优化
每个机器学习算法都有大量的参数用于控制学习过程。这些参数可以更改,并且根据数据集可以提高模型的性能。为算法和数据集寻找最佳参数集的过程被称为超参数优化。
从上一节运行的代码中我们知道,随机森林分类器在我们使用的数据集上表现最好。如果你看一下这个模型的文档,你会发现这个算法有很多参数可以调整。
超参数优化的一种常用方法是网格搜索。Scikit-learn 提供了一个名为 GridSearchCV 的函数来执行这个任务。我们需要向这个函数传递一个 python 字典形式的网格,其中包含参数名和相应的参数列表。这就变成了函数将要搜索的参数空间。
然后,该函数将为给定分类器的每个参数组合建立一个模型。一旦完成,您将能够以最佳模型和最佳参数组合的形式获得结果。
为了简单起见,在下面的例子中,我选择只调整四个参数。它们如下:
n_estimators: 模型中树的数量。
max_depth: 树的最大深度。
min_samples_split: 节点被拆分前,节点中数据点的最小个数。
min_samples_leaf: 每片叶子中数据点的最小数量。
下面的代码执行超参数调整,并打印最佳模型得分和参数组合。
from sklearn.model_selection import GridSearchCVn_estimators = [100, 300, 500, 800, 1200]
max_depth = [5, 8, 15, 25, 30]
min_samples_split = [2, 5, 10, 15, 100]
min_samples_leaf = [1, 2, 5, 10]param_grid = dict(n_estimators = n_estimators, max_depth = max_depth,
min_samples_split = min_samples_split,
min_samples_leaf = min_samples_leaf)rf = RandomForestClassifier()grid_search = GridSearchCV(estimator=rf, param_grid=param_grid)
best_model = grid_search.fit(X_train, y_train)print(round(best_model.score(X_test, y_test),2))
print(best_model.best_params_)
最终评估
最后,我们使用最佳模型来预测测试集上的标签,并打印分类报告来详细评估其性能。我们可以看到,与基线模型相比,整体性能有了很大的提高。
from sklearn.metrics import classification_reporty_pred_best = best_model.predict(X_test)
print(classification_report(y_test, y_pred_best))
在本文中,我展示了开发机器学习模型所需的最简单的工作流程。开发一个模型通常需要更多的步骤,尤其是当您使用真实世界的数据集时。其中包括数据清理、特征工程和交叉验证等许多可能的步骤。一旦你掌握了这篇文章中的基本步骤,你就可以继续学习机器学习中涉及的其他元素。
在本文中,我只讨论了分类,但对于其他类型的机器学习的简要概述,请参见— 三种机器学习类型的初学者指南 。
如果你对学习数据科学感兴趣,可以在这里看到我的学习数据科学的完全免费资源列表— 如何免费学习数据科学 。
感谢阅读!
如何创建自己的聊天机器人
原文:https://towardsdatascience.com/how-to-create-your-own-chatbot-a70120b34b42?source=collection_archive---------48-----------------------
使用 Dialogflow 构建对话体验
沃洛季米尔·赫里先科在 Unsplash 上的照片
介绍
在新冠肺炎一级防范禁闭的情况下,你有没有发现自己时不时地自言自语?别担心,我会向你展示如何创建一个聊天机器人,这样你就可以和机器人版本的你说话了。
玩笑归玩笑,聊天机器人有相当多的用例:
- 改善客户服务体验——使用聊天机器人,用户可以根据需要获得客户服务,而不必排队。
- 简化购买订单流程—使用聊天机器人,用户可以轻松购买他们想要的东西(例如购买比萨饼),而不必拨打热线电话。
- 自动回复——对于重复的问题,如退款问题、运输问题或支付问题,聊天机器人可以根据知识库提供回复。
- 减少客户服务工作量——我们可以将普通任务外包给聊天机器人,只要求客户服务人员完成更复杂的任务。
- 或者甚至提高自己的工作效率——你甚至可以创建一个聊天机器人来帮助你点播物品,播放你最喜欢的视频或者在你的日历上写一个任务。
有很多聊天机器人服务,但这篇文章将集中在谷歌的对话流。这篇文章将带你为我的虚构业务——pizza eiou 创建一个聊天机器人。正如你可能猜到的,我们卖比萨饼。由于我们有现金流问题,我必须确保我的聊天机器人服务是免费的。当我们不再有现金流问题时,我就可以查看他们的定价方案来升级我的聊天机器人。
代理人
聊天机器人从代理开始。我将把我的代理人命名为代理人 1 ,因为我没有足够的创造力来想出一个名字。代理负责存储意图、实体、内容和履行。简而言之,代理就是你的聊天机器人。
在转到 Dialogflow 并使用我的个人 Gmail 帐户登录控制台后,我看到了以下页面:
让我们继续创建一个代理:
意图
一旦我创建了我的代理,我将会看到两个默认的意图:
意图就像主题。每当我的客户向代理 1 询问某个问题时,代理 1 会尝试将问题归类到一个意图/主题下。
如果问题对 agent_1 来说太复杂,该问题将属于回退意图,其中代理将为她不理解的所有问题提供标准化回答。
第二个默认意图是欢迎意图。是的,你是对的。欢迎意向为问候 agent_1 的客户提供默认回复。
快速注释:
在这篇文章中,我将定期测试我的聊天机器人。每当我们配置代理时,我们首先要保存代理。这将允许 Dialogflow 培训我们的代理。其次,我们可以在右边的聊天中键入任何我们想要的命令。然后,我们可以观察 agent_1 的输出。
披萨订单
让我们为比萨饼订单创建一个意向。在任何意图中,都有训练短语。这些是客户会键入的短语。记得使用各种各样的短语,以便我们的代理可以更聪明。
当然,对于问题,必须有回答(暂时忽略$符号,我们稍后会谈到):
在测试了 agent_1 之后,我们发现它是有效的!
实体
agent_1 能回复披萨订单真是太好了。但是,什么是披萨?什么是培根?什么是草莓奶昔?对于 agent_1 来说,这是一个非常陌生的术语。因此,让我们定义实体。实体有助于识别句子中的何人、何事、何地、何时。
让我们定义一个实体来帮助 agent_1 理解比萨饼配料:
在我的 pizza_topping 实体中,我指定了 Pizzaeiou 提供的所有浇头。通过勾选“定义同义词”框,我允许不同的单词到达同一个词根,如第三行 bacon 示例所示。
通过勾选第三个框“允许自动扩展”,我们可以允许 agent_1 学习新单词。例如,如果所有客户都要求将“apple”作为比萨饼配料,agent_1 会自动将 apple 包含到该实体中。当然,没有人会喜欢苹果作为披萨的配料..因此,我不会勾选这个框。
注释训练短语
定义了我们的实体后,让我们将它投入使用。让我们在披萨上标注我们的训练短语。订购意图:
- 双击单词“鸡”
2.搜索我们预定义的 pizza_topping 实体:
3.Agent_1 现在将鸡肉视为披萨的配料:
让你的实体更有创造力
几个实体可以定义或随时可用:
- 系统实体—时间、日期、数字都是预定义实体的例子。您不必为它们创建实体。Dialogflow 会自动将“现在”、“下午 4 点”、“十月”标记为日期或时间实体。
- 复合实体——假设披萨店也卖饮料。我们当然可以把“奶昔”定义为我们的饮料。然而,我们如何定义“大杯草莓奶昔”是我们的饮料呢?当然,我们不希望 agent_1 将“大草莓奶昔”理解为“大草莓”和“奶昔”,那将是灾难性的。因此,我们可以定义一个名为 drinks_composite 的实体,并指定不同类型的订单。切记不要勾选“定义同义词”
当然,我们必须具体说明我们提供的口味类型:
缝隙填充
“我的顾客总是点披萨。我怎么知道他们想要巧克力披萨还是鸡肉披萨?!他们什么时候想要?!他们想要个人披萨还是大披萨?!"—代理 _1
Agent_1 现在已经受够了。她很难完成订单。让我们帮助她,确保我们的顾客总是提供尺寸、时间和配料:
- 用实体注释我们的训练短语
2.创建动作和参数。勾选所需参数,并定义用户未能提供参数时的提示
3.修改我们的回答。包括带有“$”符号的参数。
让我们来测试一下!(记得先保存您的代理)
如您所见,通过一个模糊的请求,agent_1 开始询问我们的客户以获取更多信息。
上下文
由于 Pizzaeiou 正面临现金流问题,我们应该开始向那些想要披萨的人追加销售饮料。目前,对话将会这样进行:
顾客:我现在想要一个小蘑菇比萨饼
代理 1:当然,你想喝点什么吗?
顾客:好的
抱歉,那是什么?
在这种情况下,没有上下文。 Agent_1 无法理解对话的流程。因此,让我们创建一个追加销售 _ 饮料 _ 是意向和一个追加销售 _ 饮料 _ 否意向。在此之前,我们必须修改我们的 pizza.order 意图,以产生一个追加销售饮料上下文:
数字 5 表示该上下文将持续的交互次数。然后,我们可以将我们的 upsell_drinks_yes 和 upsell_drinks_no 意图的输入上下文设置为我们的 pizza.order 意图的输出,并指定一些示例训练短语:
让我们来测试一下!
实现
现在我们已经收到了一个订单,我们需要将其推送到一个数据存储,以便 Pizzaeiou 的厨房可以获得订单!这可以通过满足来实现。有两种履行方式:
- 内联编辑器:你可以通过你创建的云函数将你的订单推送到你的数据库中。这通常用于测试目的。您应该切换到 Webhook 进行部署。
- Webhook : Webhook 允许不同的应用程序通过 JSON 请求相互交流。订单完成后,厨房会立即收到订单详情通知。
导出代理 _1
让我们导出 agent_1,这样她就可以永远生活在云中:
结论
瞧啊。我们已经成功地为 Pizzaeiou 创建了一个聊天机器人。我们现在可以让我们的客户支持人员处理更复杂的问题,而不是接受订单。
为了使它完全发挥作用,考虑创造更多的意图、实体和环境,这样你的聊天机器人听起来会尽可能的人性化。也试着创建一个聊天机器人,用于介绍中提到的不同目的。
参考资料:
https://www . coursera . org/learn/conversation-experiences-dialog flow/
如何创建自己的自定义对象检测器
原文:https://towardsdatascience.com/how-to-create-your-own-custom-object-detector-766cb11ccd1c?source=collection_archive---------11-----------------------
目标检测
使用 YOLOv3 和 ImageAI 创建您的自定义对象检测器
伊利亚·巴甫洛夫在 Unsplash 上的照片
这篇文章旨在帮助那些想第一次开发自己的自定义对象检测器的初学者,指导他们通过所有的关键点来训练一个成功的模型。
所示的例子将用 ImageAI 进行训练,这是一个开源的 Python 库,它允许你用几行代码训练一个模型。
介绍
在本文中,我们将详细介绍创建自定义对象检测器的所有必要步骤,从收集数据到最终测试我们的模型。
整个过程的步骤是:
- 收集数据
- 标注数据集
- 数据扩充
- 培训模式
- 评估模型
数据采集
在我们训练我们的模型之前,我们需要收集大量的数据,在这种情况下,是图像。根据检测机的复杂程度,最少 200 张图像应该没问题。
如果我们希望我们的模型尽可能健壮,我们的图像应该在光照和背景方面彼此不同,这样模型才能更好地概括。
这些图像可以从你的手机上获取,也可以从互联网上获取。
在这里,您可以看到我的药丸探测器模型的一个子集:
收集数据后,我们需要调整图像的大小,因为有些图像可能会很大。更小的图像意味着我们的模型将训练得更快。
为此,我编写了以下脚本:
标签数据
这是最繁琐的一步,因为你需要在每张图像中标注出你希望模型检测到的每一个物体。
你可以用 LabelImg 库给你的数据加标签。运行以下命令从终端安装它。
pip3 install labelImg
安装完成后,我们可以通过运行以下命令开始标记数据集。
labelImg path_to_images/
然后,您必须为图像中的每个对象创建一个带有相应标签的矩形框。
一旦标记了图像中的所有对象,就必须将其保存为 PascalVOC 格式,生成一个. xml 文件。
数据扩充
拥有大型数据集对于我们深度学习模型的性能至关重要,因此我们可以使用 imgaug 库来扩充我们已经拥有的数据。
这个 github repo 解释并提供了关于如何在图像边界框旁边增加图像的代码。这个过程可以分为三个步骤:
- 转换。xml 文件合并成一个。csv 文件
- 应用数据增强管道
- 转换结果。csv 文件分成多个。xml 文件
首先,我们定义一个函数来转换我们的。xml 文件合并成一个。csv 文件:
然后我们定义另一个函数来做相反的过程:
然后,我们用 imgaug 定义一个数据增强管道,比如下面这个。
最后,我们将这个管道应用到我们的数据集,并保存增强图像及其增强标签。你还要定义 image_aug() 和 bbs_obj_to_df() 函数,在这个 github repo 里可以找到。
训练模型
在所有这些预处理之后,我们最终可以用 ImageAI 训练我们的模型。
首先,我们需要安装库。
pip3 install imageai
要使用迁移学习,可以在这里下载模型。
然后,我们需要将数据集分成训练和验证文件夹。
dataset
├─ train
│ └── images
│ └── annotations
└─ validation
├── images
├── annotations
我们可以通过下面几行代码做到这一点:
然后我们可以用下面的脚本进行训练。
评估模型
一旦我们训练了我们的检测器,我们就可以通过它的映射来评估每个模型检查点的执行情况。
输出应该类似于以下内容:
使用我们的模型进行检测
最后,我们可以在生产中使用我们的模型来检测单个图像中的对象。
您可以调整minimum _ percentage _ probability参数,以或多或少的置信度显示检测到的对象,获得如下结果。
现在我想听听你的意见,让我知道它是如何工作的!
感谢阅读!
参见
[## 对象检测算法和库- neptune.ai
对象检测在图像中找到并识别事物,这是深度学习的最大成就之一…
海王星. ai](https://neptune.ai/blog/object-detection-algorithms-and-libraries)
如何为深度学习创建自己的图像数据集
原文:https://towardsdatascience.com/how-to-create-your-own-image-dataset-for-deep-learning-b53f1c22c443?source=collection_archive---------6-----------------------
弥合入门学习和现实世界应用之间的差距
照片由比塔·拉图兹尼亚克在 Unsplash 拍摄
动机
有太多的 MOOCs 声称通过带你解决经典的 MNIST 问题,让你成为深度学习/计算机视觉专家。这基本上是说,我会成为一个懂得如何打字的专业程序员。真正的专业知识是用深度学习解决自己的问题来展示的。然而,构建您自己的影像数据集本身就是一项重要的任务,而且在大多数在线课程中对它的介绍还远远不够全面。
本文的目标是帮助您收集自己的原始图像数据集,然后您可以将其用于自己的图像分类/计算机视觉项目。
要求:
- Python :你需要在你的机器上安装一个 Python 的工作版本。(我用的是 3.7.4)
- Linux/Unix 终端:我们将从命令行运行映像下载程序。如果你使用的是 Mac 或 Linux,那么标准终端应该没问题。(我运行的是 Ubuntu 18.04)。对于 Windows,您可能需要为 Linux 设置 Windows 子系统或找到另一个第三方终端应用程序。
步伐
信不信由你,下载一堆图片只需几个简单的步骤。
一个:使用 pip 安装谷歌图片下载器:
pip install googleimagedownloader
两个:下载谷歌 Chrome 和 Chromedriver
- 你需要确保你得到的 Chromedriver 版本与你运行的 Google Chrome 版本一致。
- 要检查你机器上的 Chrome 版本:打开一个 Chrome 浏览器窗口,点击右上角的菜单按钮(三个堆叠的点),然后点击“帮助”>“关于谷歌 Chrome”。
一旦你下载了 Chromedriver,一定要记下“chromedriver”可执行文件的存储位置。下一步我们需要知道它的位置。
三:使用命令行批量下载图像
举个例子,假设我想建立一个可以区分蜥蜴和蛇的模型。这意味着我需要一个包含蜥蜴和蛇图像的数据集。我首先使用以下命令下载蜥蜴的图像:
$ googleimagesdownload -k "lizard" -s medium -l 500 -o dataset/train -i lizards -cd ~/chromedriver
该命令将使用关键字“蜥蜴”从谷歌图片中抓取 500 张图片。它会将这些图像输出到:dataset/train/lizards/
。-cd
参数指向我们之前下载的“chromedriver”可执行文件的位置。
(注意:运行 500 张图像需要几分钟时间,所以我建议先用 10-15 张图像进行测试,以确保它能按预期工作)
如果打开输出文件夹,您应该会看到类似这样的内容:
关于如何使用google_image_downloader
的更多细节,我强烈推荐查看文档。
现在,要获得一些蛇的图像,我可以简单地运行上面的命令,将关键字/图像目录参数中的“蜥蜴”替换为“蛇”。
$ googleimagesdownload -k "snake" -s medium -l 500 -o dataset/train -i snakes -cd ~/chromedriver
嘣!只需两个简单的命令,我们现在就有 1000 张图像来训练一个模型。多酷啊。!
然而,要制作一个好的数据集,我们真的需要挖掘得更深。也许我们可以尝试用关键词来描述特定种类的蜥蜴/蛇。我们只需要认识到我们试图解决的问题,并发挥创造力。
结论
在这一点上,我们几乎没有触及开始深度学习项目的表面。我们所做的只是收集一些原始图像。如果我们想要构建一个有用的模型,仍然需要做大量的数据清理/格式化工作。构建一个好的数据集需要时间,这一点我再怎么强调也不为过。我只是希望这篇文章能够为您提供工具,帮助您克服收集图像来构建自己的数据集的最初障碍。
我希望你喜欢这篇文章。如有任何意见、问题或反馈,请联系我。我会尽力及时回复。
如何解决数据信任问题
原文:https://towardsdatascience.com/how-to-cure-data-trust-issues-49d15b9149ac?source=collection_archive---------42-----------------------
如果你在数据部门工作了一年,你可能参加过这样的会议:
分析师:“数字是 X”
商人:“但是我的另一个仪表盘显示这个数字是 Y”
分析师:希望地震能结束她的痛苦
那么,哪里出了问题?许多信息源都有不同的编号。这是怎么发生的?
照片由 s 托克兰在 Unsplash
这是一个组织数据需求演变的例子。利益相关者需要一些关于应用程序用户的信息。因此,她与数据团队聊天。然后,数据工程师创建一些管道,分析师编写代码来生成可视化信息的仪表板。
每次创建像仪表板这样的数据产品时,都会使用一整套假设和业务逻辑规则。例如,我们是否将搅动的用户定义为“超过 70 天不活动的用户?”或者“用户 50 天不活动?”我们是否使用表 1,它没有计算未注册的用户?还是用大一点的桌子?许多决策是在创建数据产品的过程中做出的。
因此,假设我们创建了一些跟踪用户流失的仪表板。一个月过去了,一个不同的利益相关者进来要求另一个仪表板。现在,企业领导层已经决定,被搅动的用户被定义为“50 天不活动的用户”但是,之前创建的控制面板将大量用户定义为“70 天不活动的用户”除非每个人都密切关注正在发生的事情,否则将会有两个相互冲突的数字在组织中流传。
与信息冲突相关的问题是什么?首先,企业主很难做出正确的决定。由于决策失误,企业可能会遭受损失。此外,数据分析师开始显得无能,企业领导人对他们的工作失去了信任。
解决方案:真理的单一来源
我的团队一直朝着这个天堂般的理想努力。这种涅槃被称为“真理的唯一来源”在这种状态下,您的所有数据产品(例如:仪表板、模型)都使用相同的管道、相同的业务逻辑,并且所有数字都是一致的。当然,说起来容易做起来难。而且,这需要时间和金钱。但是,这是值得的。那么,我们如何执行它呢?
由路上车头拍摄
首先,停止仪表板和管道的扩散。有时候,我们向用户提供的信息越多,我们创造的价值就越多。不。这是不正确的。少即是多。拥有更少的仪表板会更好,这些仪表板相互集成并使用相同的业务逻辑。投入实际的努力来检查您创建的所有仪表板,无情地删除任何与业务规则和报告标准的当前状态不同步的内容。对数据工程管道做同样的事情。
此外,确保业务的分析和业务方面的每个人都始终相互交流。我知道我们都害怕召开更多的会议。它们看起来像是巨大的时间浪费。但是,如果做得好,会议和空闲时间更新可以让你避免很多困惑。
保持真理的单一来源是一个持续的、痛苦的但非常值得的过程。记住,没有你努力追求的完美状态。你只是想跑得快一点,跟上业务和业务报告的变化。我将引用《爱丽丝梦游仙境》中的一句话,红皇后角色说你必须奔跑才能停留在一个地方。你觉得这句话是激励人心还是相反,就看你自己了。我觉得两者都有。
“现在,在这里,你看,它需要所有你能做的运行,保持在同一个地方。如果你想去别的地方,你至少要跑两倍的速度!”
如何处理不平衡的分类,而不重新平衡数据
原文:https://towardsdatascience.com/how-to-deal-with-imbalanced-classification-without-re-balancing-the-data-8a3c02353fe3?source=collection_archive---------9-----------------------
在考虑对倾斜数据进行过采样之前,请尝试在 Python 中调整分类决策阈值
Elena Mozhvilo 在 Unsplash 上的照片
在机器学习中,当用一个类的实例比另一个类的实例多得多的数据建立分类模型时,初始的默认分类器通常不令人满意,因为它将几乎每个案例都分类为多数类。许多文章向您展示了如何使用过采样(例如 SMOTE )或有时使用欠采样或简单的基于类的样本加权来重新训练“重新平衡”数据的模型,但这并不总是必要的。在这里,我们的目的是展示在不使用平衡数据或重新训练模型的情况下可以做多少事情。
我们通过简单地调整阈值来做到这一点,当模型预测的类别 1 的概率在两类分类中高于它时,我们称之为“类别 1”,而不是天真地使用默认分类规则来选择哪个类别被预测为最有可能(概率阈值为 0.5)。我们将看到这是如何为您提供灵活性,在假阳性和假阴性分类之间进行任何所需的权衡,同时避免重新平衡数据所带来的问题。
我们将用 Kaggle 的信用卡欺诈识别数据集来说明。数据集的每一行代表一笔信用卡交易,目标变量 Class0 表示一笔合法交易,Class1 表示该交易结果是一笔欺诈。有 284,807 笔交易,其中只有 492 笔(0.173%)是欺诈——确实非常不平衡。
我们将使用一个梯度增强分类器,因为这些通常会给出好的结果。特别是 Scikit-Learn 的新 histgradientsboostingclassifier,因为当数据集像这样相对较大时,它比他们原来的 GradientBoostingClassifier 快得多。
首先让我们导入一些库并读入数据集。
import numpy as np
import pandas as pd
from sklearn import model_selection, metrics
from sklearn.experimental import enable_hist_gradient_boosting
from sklearn.ensemble import HistGradientBoostingClassifier
df=pd.read_csv('creditcard.csv')
df.info()
V1 到 V28(来自主成分分析)和交易金额是特征,它们都是数字并且没有缺失数据。因为我们只使用基于树的分类器,所以不需要标准化或规范化特征。
在将数据分成训练集和测试集之后,我们现在将训练模型。这在我的笔记本电脑上花了大约半分钟。如果验证子集的性能由于过度拟合而开始恶化,我们使用 n_iter_no_change 来提前停止训练。我单独做了一点超参数调整来选择 learning_rate 和 max_leaf_nodes,但这不是本文的重点。
Xtrain, Xtest, ytrain, ytest = model_selection.train_test_split(
df.loc[:,'V1':'Amount'], df.Class, stratify=df.Class,
test_size=0.3, random_state=42)
gbc=HistGradientBoostingClassifier(learning_rate=0.01,
max_iter=2000, max_leaf_nodes=6, validation_fraction=0.2,
n_iter_no_change=15, random_state=42).fit(Xtrain,ytrain)
现在,我们将这个模型作为默认的硬分类器应用于测试数据,预测每个事务为 0 或 1。我们将决策阈值 0.5 隐式应用于模型的连续概率预测,作为软分类器。当概率预测超过 0.5 时,我们称之为“1”,当低于 0.5 时,我们称之为“0”。
我们还为结果打印了混淆矩阵,按照惯例,认为类别 1(欺诈)是“正”类别,因为它是更罕见的类别。混淆矩阵显示了真阴性、假阳性、假阴性和真阳性的数量。标准化混淆矩阵比率(如 FNR =假阴性率)以百分比形式包含在括号中。
hardpredtst=gbc.predict(Xtest)
def conf_matrix(y,pred):
((tn, fp), (fn, tp)) = metrics.confusion_matrix(y, pred)
((tnr,fpr),(fnr,tpr))= metrics.confusion_matrix(y, pred,
normalize='true')
return pd.DataFrame([[f'TN = {tn} (TNR = {tnr:1.2%})',
f'FP = {fp} (FPR = {fpr:1.2%})'],
[f'FN = {fn} (FNR = {fnr:1.2%})',
f'TP = {tp} (TPR = {tpr:1.2%})']],
index=['True 0(Legit)', 'True 1(Fraud)'],
columns=['Pred 0(Approve as Legit)',
'Pred 1(Deny as Fraud)'])
conf_matrix(ytest,hardpredtst)
我们看到第 1 类的召回率(也称为敏感度或真阳性率,如上面的 TPR 所示)仅为 71.62%,这意味着 71.62%的真实欺诈被正确识别为欺诈并因此被拒绝。因此,28.38%的真实欺诈不幸被批准为合法。
特别是对于不平衡的数据(或者通常任何时候假阳性和假阴性可能具有不同的后果),重要的是不要限制我们自己使用默认的隐式分类决策阈值 0.5,就像我们在上面通过使用。预测()”。我们希望提高 1 类产品(TPR)的召回率,以减少我们的欺诈损失(减少假阴性)。为了做到这一点,当我们预测一个高于阈值的概率时,我们可以降低我们所说的“类 1”的阈值。通过这种方式,我们称“1 类”为更大范围的预测概率。这种策略被称为阈值移动。
最终,我们希望在多大程度上减少这些假阴性是一个商业决策,因为作为一种权衡,假阳性(作为欺诈被拒绝的真实合法交易)的数量将不可避免地增加,因为我们调整了应用于模型概率预测的阈值(从“获得”)。predict_proba()"而不是"。预测()”)。
为了阐明这种权衡并帮助我们选择阈值,我们绘制了假阳性率和假阴性率与阈值的关系图。这是接收器工作特性 (ROC)曲线的变体,但强调了阈值。
predtst=gbc.predict_proba(Xtest)[:,1]
fpr, tpr, thresholds = metrics.roc_curve(ytest, predtst)
dfplot=pd.DataFrame({'Threshold':thresholds,
'False Positive Rate':fpr,
'False Negative Rate': 1.-tpr})
ax=dfplot.plot(x='Threshold', y=['False Positive Rate',
'False Negative Rate'], figsize=(10,6))
ax.plot([0.00035,0.00035],[0,0.1]) #mark example thresh.
ax.set_xbound(0,0.0008); ax.set_ybound(0,0.3) #zoom in
虽然存在一些选择最佳阈值的经验法则或建议的度量标准,但最终它只取决于假阴性与假阳性的业务成本。例如,看上面的图,我们可以选择应用阈值 0.00035(垂直绿线已添加),如下所示。
hardpredtst_tuned_thresh = np.where(predtst >= 0.00035, 1, 0)
conf_matrix(ytest, hardpredtst_tuned_thresh)
我们已将假阴性率从 28.38%降至 9.46%(即识别并拒绝 90.54%的真实欺诈,作为我们新的召回或敏感度或真阳性率或 TPR),而我们的假阳性率(FPR)从 0.01%增至 5.75%(即仍批准 94.25%的合法交易)。为了只批准不到 10%的欺诈交易,拒绝大约 6%的合法交易对我们来说可能是值得的,当我们使用默认硬分类器(隐式分类决策阈值为 0.5)时,欺诈交易的比例为 28%,这是非常昂贵的。
不平衡不平衡数据的原因
避免“平衡”不平衡的训练数据的一个原因是,这种方法通过系统地增加模型对原始少数类的预测概率,偏向/扭曲了最终训练模型的概率预测,从而使这些预测成为误校准,并因此简化为仅仅是相对的序数判别分数或决策函数或置信度分数,而不是原始(“不平衡”)训练和测试集以及分类器可以对其进行预测的未来数据中潜在准确的预测类概率。如果训练的这种重新平衡是真正需要的,但是仍然需要数值精确的概率预测,那么人们将不得不重新校准具有原始/不平衡类别比例的数据集的预测概率,或者对来自平衡模型的预测概率应用适当的校正——参见此处的、此处的或此处的。
通过过采样来平衡数据的另一个问题(与没有这个问题的依赖于类的实例加权相反)是,它偏向于天真的交叉验证,潜在地导致在交叉验证中没有检测到的过度拟合。如果对整个训练集执行过采样,则在交叉验证中,每次数据被拆分到“折叠”子集时,一个折叠中可能会有与另一个折叠中的实例重复的实例,或者由另一个折叠中的实例生成的实例。因此,折叠并不像交叉验证假设的那样是真正独立的——存在数据“流失”或“泄漏”。例如,参见不平衡数据集的交叉验证,它描述了如何通过仅在每组训练折叠上执行过采样,在交叉验证循环内正确地重新实施交叉验证,如中所示,本例。或者,您可以在由 imb learn . pipeline . make _ pipeline()创建的管道中执行过采样,该管道通过将交叉验证循环中的过采样仅应用于训练折叠,而不应用于测试折叠来解决这一问题。在 scikit-learn 中,至少对于通过简单实例复制/重采样(不一定是 SMOTE 或 ADASYN)进行过采样的情况,该问题可以通过使用 model_selection 来解决。GroupKFold 用于交叉验证,它根据选定的组标识符对实例进行分组,该标识符对于给定实例的所有副本都具有相同的值——参见我对前述文章的回复。
结论
我们可以尝试使用原始模型(在原始“不平衡”数据集上训练),并简单地绘制假阳性和假阴性之间的权衡,以选择可能产生理想业务结果的阈值,而不是天真地或隐含地应用默认阈值 0.5,或使用重新平衡的训练数据立即重新训练。
编辑:即使唯一真正的“问题”是默认的 0.5 阈值不合适,为什么重新平衡你的训练数据“有效”?
由您的模型产生的平均概率预测将近似为类 1 的定型实例的比例,因为这是目标类变量的平均实际值(其值为 0 和 1)。回归也是如此:目标变量的平均预测值有望逼近目标变量的平均实际值。当数据高度不平衡并且类别 1 是少数类别时,该平均概率预测将远小于 0.5,并且类别 1 的概率的绝大多数预测将小于 0.5,因此被分类为类别 0(多数类别)。如果您重新平衡训练数据,平均预测概率会增加到 0.5,因此许多实例会高于默认阈值 0.5 的以及低于默认阈值 0.5 的,预测的类会更加平衡。因此,重新平衡不是降低阈值以使概率预测更经常地高于阈值并给出类 1(少数类),而是增加预测的概率以使概率预测更经常地高于默认阈值 0.5 并给出类 1。
如果您想要获得与重新平衡类似(不完全相同)的结果,而不实际重新平衡或重新加权数据,您可以尝试简单地将阈值设置为等于模型预测的类 1 概率的平均值或中值。当然,这并不一定是针对您的特定业务问题在误报和漏报之间提供最佳平衡的阈值,重新平衡您的数据并使用 0.5 的阈值也不一定。
在某些情况和模型中,重新平衡数据可能会大大改进模型,而不仅仅是将平均预测概率移动到等于默认阈值 0.5。但是,当使用默认阈值 0.5 时,模型在绝大多数情况下选择多数类这一事实本身并不支持这样一种说法,即重新平衡数据除了使平均概率预测等于阈值之外,还能完成任何事情。如果您希望平均概率预测等于阈值,您可以简单地将阈值设置为等于平均概率预测,而无需为了扭曲概率预测而修改或重新加权训练数据。
编辑:关于置信度得分与概率预测的注释
如果您的分类器没有 predict_proba 方法,例如支持向量分类器,您也可以使用它的 decision_function 方法来代替它,产生一个序数判别得分或置信度得分模型输出,即使它是而不是可解释为 0 和 1 之间的概率预测,也可以用相同的方式设定阈值。根据特定分类器模型如何计算两个类别的置信度得分,有时可能需要而不是将阈值直接应用于类别 1 的置信度得分(我们在上面将其作为类别 1 的预测概率,因为类别 0 的预测概率只是 1 减去 1),或者将阈值应用于类别 0 和类别 1 的置信度得分之间的差, 对于假设假阳性的成本与假阴性的成本相同的情况,默认阈值为 0。 本文假设了一个两类分类问题。
如何处理不平衡数据
原文:https://towardsdatascience.com/how-to-deal-with-imbalanced-data-34ab7db9b100?source=collection_archive---------8-----------------------
Python 中处理不平衡数据集的分步指南
作者照片
具有不平衡类的数据集是常见的数据科学问题,也是常见的面试问题。在本文中,我提供了一个分步指南来改进您的模型并很好地处理不平衡的数据。您最常看到不平衡数据的领域是分类问题,如垃圾邮件过滤、欺诈检测和医疗诊断。
是什么让不平衡的数据成为问题?
几乎每个数据集都有不同的类表示。只要差异很小,这就不是问题。然而,当一个或多个类非常罕见时,许多模型在识别少数类时不太好用。在本文中,为了简单起见,我将假设一个两类问题(一个多数类和一个少数类),但是这些技术中的大多数也适用于多个数据集。
通常,我们会查看验证分割的准确性,以确定我们的模型是否表现良好。然而,当数据不平衡时,准确性可能会产生误导。例如,假设您有一个数据集,其中 92%的数据被标记为“非欺诈”,剩下的 8%是“欺诈”案例。数据明显不平衡。现在假设我们的模型最终将它看到的一切都归类为“非欺诈”。然而,如果我们着眼于准确性,这是一个惊人的 92%。但银行仍然关心那些“欺诈”案件。这就是它赔钱的地方。那么我们如何改进我们的模型呢?
为了克服不平衡数据集的问题,您可以执行以下一系列步骤和决策。
1。能收集更多数据吗
你可能会说,“好吧,网上的随便一个人,如果我能收集更多的数据,我就不会读这些了,不是吗?收集更多数据”。
通过 https://stopthatrightnow.github.io/生成的图像
但是听我说完。后退一步,考虑以下问题:
- 你收到的数据是否经过了筛选,以排除可能导致辅修课观察被忽略的情况。
- 你有多少年的历史,如果你回到一两年前,你会得到更多的数据仍然合理的次要类的实例。
- 如果是客户数据,我们能否使用不再订阅我们服务的客户,而不影响我们试图解决的参数。也许使用这些以前的客户记录,以及“当前客户”?(Y/N)"布尔变量会有所帮助。
- 你能把你的少数民族班合并成一个班吗?例如,如果您正在对一个人的心跳中的不同类型的异常进行分类,而不是试图对每种类型的异常进行分类,那么如果我们将它们都合并到一个单一的“异常心跳”类别中,该模型还会有用吗?
只是一些想法和一个提醒,总是考虑不同的可能性。
2。 更改绩效指标
如上所述,由于在处理不平衡数据集时,精确度不是一个好的衡量标准,所以让我们考虑更合适的衡量标准。
作者的混淆矩阵照片
基于混淆矩阵,我们可以测量以下内容:
- 精度:真阳性/所有预测阳性= TP / (TP+FP)。精度是对分类器准确性的度量。低精度表示大量的误报。
- 回忆:真阳性/所有实际阳性= TP / (TP + FN)。召回是对分类器完整性的一种度量。它也与敏感度或真实阳性率相同。低召回率表示大量的假阴性。
- F1 得分: 2TP/(2TP + FP + FN)精度和召回率的加权平均值。如果我们想在精确度和召回率之间取得平衡,那么我们应该看看 F1 的分数。
注意:这里我假设少数类在混淆矩阵中被标记为正类。
查看此维基百科页面,获取绩效指标公式列表。
我们还可以看一看:
- 灵敏度/特异性ROC 曲线:灵敏度与回忆基本一致,告诉我们真实的阳性率。
- Kappa(或 科恩的 kappa ) :分类精度由数据中类别的不平衡性归一化。
在这种情况下,我们希望寻找高回忆/灵敏度和 f1 分数,而不是准确性,以查看我们的模型在预测辅修课程方面的表现。
Jason Brownlee 在这里了解更多关于选择不同绩效指标的信息。
3。 尝试不同的算法
与大多数数据科学问题一样,对数据尝试几种不同的合适算法始终是一种好的做法。
有两种主要类型的算法似乎对不平衡数据集问题有效。
决策树
决策树似乎在不平衡数据集上表现得很好。因为他们在拆分的每个阶段都提出了条件/规则,所以他们最终把两个类都考虑进去了。
我们可以尝试一些不同的决策树算法,如随机森林、CART、C4.5。
处罚车型:
惩罚学习模型(代价敏感训练)对模型强加了额外的代价,用于在训练期间对少数类进行分类错误。这迫使模型更多地关注少数类观察。
异常检测模型:
如果只是 2 个类,多数类和少数类,那么您可以考虑使用异常检测模型而不是分类模型。这些异常模型试图做的是为多数类创建一个配置文件。任何不符合这一特征的观察都被认为是异常或异常值,在我们的例子中是来自少数群体的观察。这类模型用于欺诈检测等情况。
异常检测图片来自维基百科 ( CC BY-SA 4.0 )
4。 对数据集进行重新采样
这一步可以在尝试上述不同的模型方法时完成。不同类型的重采样如下:
- 对多数类欠采样
- 对少数民族阶层进行过度采样
按作者对数据照片进行重采样
欠采样(下采样)多数类
欠采样随机移除多数类的观测值。这减少了在训练集中使用的多数类观察的数量,并且因此更好地平衡了两个类的观察的数量。当您的数据集中有大量观测值(> 10K 观测值)时,这非常适合。风险是你正在丢失信息,因此可能导致不适合。
Scikit-learn 提供了一种“重采样”方法,我们可以用它来进行欠采样。不平衡学习包还提供了更高级的功能。Python 代码示例如下所示:
由于多数类的许多观测值已被丢弃,因此产生的数据集现在要小得多。这两个班级的比例现在是 1:1。
注:我们不一定要使用 1:1 的比率,我们可以使用这种方法将多数类观察的数量减少到任何合理的比率。
过采样(上采样)少数类
过采样随机复制少数类的观测值,以使其信号更强。最简单的过采样形式是置换采样。当数据集中没有大量观测值(< 10K 观测值)时,过采样非常合适。风险在于,如果你重复了太多的观察,那么你就是过度拟合了。
我们可以使用相同的 scikit-learn“重采样”方法,但使用不同的参数。下面显示了一个代码示例:
这一次,我们使用替换进行采样,以便在最终的训练集中有更多的代表性。但正如我提到的,这可能会导致过度拟合。那么,怎样才能把事情做得更好,避免过度拟合呢?
5。 生成合成样本
为了减少上采样期间的过拟合,我们可以尝试创建合成样本。
重击
一个流行的算法是 SMOTE (合成少数过采样技术)。SMOTE 不是使用观测值的副本进行过采样,而是改变观测值的属性来创建新的合成样本。
你可以在这里找到 SMOTE 的例子。
增大
与 SMOTE 类似,如果您的数据是音频或图像之类的东西,那么您也可以对原始文件执行转换来创建新的样本。
6.结论
正如数据科学和机器学习算法中的大多数事情一样,没有每次都有效的确定的正确方法。根据数据集的性质、类的分布、预测器和模型,上述一些方法会比其他方法更好。这取决于你来找出最佳的组合。
需要记住的几点是:
- 在创建合成/增强样本之前,始终进行训练/测试分割。您希望根据原始数据观察来验证和测试您的模型
- 使用相同的衡量标准进行比较——每次你尝试新的东西时,记得正确地进行比较。不要只看一个型号的精度,另一个型号的灵敏度。
除了这些步骤之外,不要忘记您还必须做一些事情,例如数据清理、功能选择和超参数调整。
希望这有所帮助!
if_you_like(this_article):
please(CLAPS) # Do this :)
else:
initiate_sad_author() # Don't do this :(# Thanks :)
参考资料和进一步阅读
博伊尔塔拉。"处理不平衡数据的方法."中等。2019 年 2 月 04 日。2020 年 6 月 21 日访问。https://towards data science . com/methods-for-processing-unbalanced-data-5b 761 be 45 a 18。
布朗利,杰森。"在你的机器学习数据集中对抗不平衡类的 8 个策略."机器学习精通。2020 年 1 月 14 日。2020 年 6 月 21 日访问。https://machine learning mastery . com/tactics-to-combat-unbalanced-classes-in-your-machine-learning-dataset/。
"如何处理机器学习中不平衡的类."2020 年 5 月 23 日。https://elitedatascience.com/imbalanced-classes.
Python 中如何处理不平衡数据
原文:https://towardsdatascience.com/how-to-deal-with-imbalanced-data-in-python-f9b71aba53eb?source=collection_archive---------1-----------------------
平衡不平衡的 pythonic 解决方案
Photo by 青 晨 on Unsplash
不平衡数据在现实世界中是非常常见的,尤其是当决策系统的目标是一个罕见但重要的案例时。当未来的决策是基于对历史数据的洞察而做出时,这可能是一个问题。来自少数案例的不充分数据会妨碍正在做出的新决策的稳健性。
不平衡数据的情况几乎存在于任何实际应用中。例如,美国无线运营商的平均客户流失率在 1-6%之间。同样在市场营销中,的平均转化率也徘徊在个位数范围内。
那么,在机器学习(ML)中使用不平衡数据会出现什么问题呢?你如何处理不平衡的数据?本文将带您了解所有这些问题,并展示一些 Python 中的实际例子。
令人惊讶的是,我将在本文末尾提供“另一件事”,说明如何结合使用过采样和欠采样方法来选择最佳采样比。
什么是精确的不平衡数据?
不平衡数据集是分类问题的特例,其中类在类间的分布不均匀。通常,它们由两类组成:多数(消极)类和少数(积极)类【1】。****
通常少数类是我们希望 ML 模型能够正确预测的,因此被称为正类。例如,如果一个模型试图以 3%的转换率对一组 10,000 个客户数据进行训练,它可能没有足够的样本进行足够好的训练来预测未来正转换率的概率。
那么,我们如何准确定义不平衡数据的阈值呢?
根据谷歌开发者的说法,答案可以分为 3 个不平衡度——轻度(20–40%)、中度(1–20%)和极端(< 1%)。
为什么重要?
不平衡数据的影响是隐含的,即当您构建和运行模型时,它不会立即引发错误,但结果可能会令人迷惑。如果多数类的类不平衡程度是极端的,那么机器训练的分类器可以产生高的总体预测精度,因为该模型最有可能预测属于多数类的大多数样本。例如,在一个类分布为 90:10 的两类问题中,分类器在多数类示例上的性能是少数类示例的九倍。
如何处理不平衡的数据?
文献中已经提出了几种解决这个问题的方案,其中有:
- 数据级技术— 在数据级,解决方案通过应用重采样技术来平衡数据集。这可以通过对少数类进行过采样来实现,即从现有的实例中综合创建新的实例;或者对多数类进行欠采样,这消除了多数类中的一些实例。然而,这两种技术都有缺点。过采样新数据会导致分类器过拟合;而欠采样会丢弃重要信息。在专业文献中可以找到这两种技术与启发式方法的结合,结果非常好。
- 算法级技术— 算法级解决方案可以通过相应地调整加权成本来实现,以适应每一类中训练实例的数量。在像支持向量机这样的参数分类器中,可以应用网格搜索和交叉验证来优化 C 和 gamma 值。对于像决策树这样的非参数分类器,调整树叶处的概率估计可以提高性能。
- ****两者的结合——各种文献中也在不断探索一种混合方法,包括彭和姚提出的 AdaOUBoost (自适应过采样和欠采样增强)和利用 Japkowicz 提出的基于自动联想的分类方法概念的通过识别学习。
用 Python 处理不平衡数据
Python 中最流行的采样方法库之一就是不平衡学习包。它提供了多种过采样和欠采样方法,以及一些组合方法。在本教程中,我们将为这三种方法分别探索一个示例:
- 使用随机欠采样器进行随机欠采样
- 使用 SMOTE 进行过采样(合成少数过采样技术)
- 使用流水线的随机欠采样和过采样的组合
本教程中使用的数据集基于来自 UCI 回购的银行营销数据。这是一个分类问题,目标是预测客户是否会订阅定期存款。所有分类(文本)特征列都被编码成机器友好的数字形式。编码数据集托管在 Github 上。为了测试数据在重采样后的表现,我们在重采样数据上训练支持向量机模型,以检查模型的表现。完整的 Python 代码也可以在同一个 Github 库中找到。
之所以选择这个数据集,是因为它反映了日常应用中常见的不平衡数据集。正如预期的那样,数据非常不平衡,只有大约 13% [5,289/(5,289+39,922)]的联系客户实际上订阅了定期存款。在 Python 中,可以使用方法value_counts()
打印每个预测类的编号。
目标类的分布。0 表示未转换的多数负类 aka 客户,而 1 表示认购定期存款的少数正类 aka 客户。
- 随机欠采样
照片由帕特里克·福尔在 Unsplash 拍摄
顾名思义,随机欠采样将多数类的数量随机减少到相对于少数类的期望比率。这可能是最简单的欠采样方法,如果有许多彼此接近的多数类实例,这种方法实际上可以产生良好的结果。关于减少多数类的更统计的方法,你可以参考浓缩最近邻(又名。CNN,基于 Hart 算法), Tomek Links (对原始 CNN 技术的改进), NearMiss 等等,这里仅列举一个新的。幸运的是,所有提到的技术都可以在同一个不平衡学习包中获得,你可以很容易地导入并尝试它们。
代码片段分为两部分:第 1 部分向您展示随机欠采样多数类的代码;第 2 部分使用支持向量机训练重采样数据,并输出 ROC AUC 得分。
代码片段的输出:第 1 行显示原始数据分布;第二行显示欠采样分布;第三行显示了使用欠采样数据的模型性能
2。使用 SMOTE 进行过采样
SMOTE 使用 5 作为 k 个最近邻进行过采样的示例。作者自我图解。
对于过采样技术, SMOTE (合成少数过采样技术)被认为是 ML 和数据挖掘中最流行和最有影响力的数据采样算法之一。使用 SMOTE,少数类通过创建“合成”示例进行过采样,而不是通过替换进行过采样[2]。这些引入的合成示例基于沿着连接定义数量的 k 个少数类最近邻居的线段,其在imblearn
包中默认设置为五个。
代码片段分为两部分:第 1 部分展示了用 SMOTE 对 minority 类进行过采样的代码;第 2 部分使用支持向量机训练重采样数据,并输出 ROC AUC 得分。
代码片段的输出:第 1 行显示原始数据分布;第二行显示了过采样分布;第三行显示了使用过采样数据的模型性能
3。使用流水线的欠采样和过采样方法的组合
由在 Unsplash 上创意交流拍摄的照片
代码片段分为两部分:第 1 部分展示了创建管道的代码,使用欠采样和过采样方法对数据进行重采样;第 2 部分使用支持向量机训练重采样数据,并在交叉验证后输出平均 ROC AUC 分数。
使用组合抽样方法显示 ROC AUC 得分的代码片段的输出。
奖励—我如何知道哪个采样比是最好的?
乔恩·泰森在 Unsplash 拍摄的照片
在上面的教程中,我们对数据进行了欠采样或/和过采样,以使两个类的分布达到 50:50 的平衡。但是如果我们想根据模型性能找出最佳的采样率呢?我们可以通过在 Python 中实现一个for
循环来迭代一个可能的采样比率列表,并在交叉验证后根据平均 ROC AUC 得分(或选择的其他性能指标)来查看哪个组合具有最佳性能。
代码片段向您展示了使用欠采样和过采样方法创建管道以对数据进行重采样的代码。过采样的可能比率列表为[0.3,0.4,0.5]
,欠采样的可能比率列表为[0.7,0.6,0.5]
。这些比率是出于演示目的而随机选择的,并且可以在一些试验和错误之后用其他值替换。然后,在交叉验证后输出平均 ROC AUC 分数之前,用每个可能的比率组合对的重采样数据训练支持向量机。
每个可能的比率组合对的平均 ROC AUC 评分的代码片段输出。
如输出快照所示,本例中的最佳采样率为 0.5 的过采样率,其次是 0.7 的欠采样率,以获得 82.1%的最佳可能平均 ROC AUC 得分。
结论
对于欠采样还是过采样方法更适合不平衡数据的问题,没有简单的答案,尤其是在使用哪种精确采样技术(随机或 SMOTE)时。然而,大多数研究指出,欠采样在大多数情况下确实比过采样产生更好的结果。在行业实践中,据报道,像脸书和微软这样的科技巨头在对他们的广告表现进行分类时也倾向于使用欠采样方法。常见的论点是欠采样通常比过采样“更便宜”,并且由于感兴趣的类是少数正类,因此减少多数负类的一些信息是可以接受的。但是不能保证在你的情况下同样的事情总是能重复发生。
我的建议是,在处理不平衡数据时,根据你拥有的时间和资源来决定。如果您有有限的时间和资源来研究哪种方法最适合您,那么您可以从一开始就选择随机欠采样。然而,如果你有一点奢侈去尝试不同的采样方法和技术,我会强烈推荐后者。一旦你有了一个平衡的数据,你的模型就有可能学会更好地对不同的类进行分类,从而得到更可靠的预测。
处理不平衡数据后的下一步可能是为您的模型选择最佳特性,为此,欢迎您查看我在特性选择中的文章。
*免责声明:由于训练测试分割和交叉验证的随机性,您可能不会得到如图所示的准确输出。
参考:
[1] 不平衡数据集,龙骨 2018
[2] SMOTE:合成少数过采样技术
感谢阅读这篇文章。如果你喜欢我的工作,请考虑加入 Medium 来支持我。谢谢大家!😊
** [## 通过我的推荐链接-谭施敏加入媒体
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
jackyeetan.medium.com](https://jackyeetan.medium.com/membership)**
如何在 Python 中处理无穷大
原文:https://towardsdatascience.com/how-to-deal-with-infinity-in-python-ab041fc95546?source=collection_archive---------34-----------------------
介绍在 Python 中定义和使用无限值的方法
由鲁本·特奥在 Unsplash 拍摄的照片
我们只是追求绝对完美的无限探索者。—g·h·哈代
很多人认为无穷大只是一个非常大的数。但在现实中,无限是无限的概念,没有任何界限。
从早期开始,数学家们就在用这种永无止境的概念赌博。正如约翰·格林在他的书《我们星星中的错误》中所写的,
"在一个由其结局定义的宇宙中,无尽是一个非常奇怪的概念."
对于算法设计来说,无穷大有许多可取的特性。最受欢迎的是:
∀ x ∈ ℝ,-∞ < x < ∞
每个数都小于正无穷大,大于负无穷大。
在 Python 中,我们可以用多种方式表示无穷大。我们将在下面讨论三个最受欢迎的。
设置
本文编写的代码在 Python 3.6 上进行了测试。这里唯一需要的非标准库是 numpy 。您可以使用以下命令非常简单地安装它:
pip install numpy
使用 float('inf ')
我们将创建两个变量并用正负无穷大初始化它们。
输出:
Positive Infinity: inf
Negative Infinity: -inf
使用数学模块(math.inf)
另一种表示无穷大的流行方法是使用 Python 的数学模块。看一看:
输出:
Positive Infinity: inf
Negative Infinity: -inf
使用 Numpy 模块(numpy.inf)
Numpy 对于无穷大的值也有自己的定义。我们也可以创建用无穷大值填充的数组。代码如下所示:
输出:
Positive Infinity: inf
Negative Infinity: -inf
Infinity Array: [inf inf inf inf inf inf inf inf inf inf]
在 Python 中检查一个数是否是无限的
math 模块提供了一个isinf()
方法,允许我们轻松地检查 Python 中的无限值。它返回一个布尔值。看一看:
输出:
For First Infinity: True
For Second Infinity: True
For Third Infinity: True
For Large Number: False
无限算术
大多数无穷数的算术运算都会产生其他无穷数。无限零悖论成为一个非常有趣的晚餐话题。至少我希望如此。我还没试过。
输出:
Addition : inf
Subtraction : inf
Multiplication : inf
Division : inf
Multiplication by Zero: nan
结束语
在最优化问题中经常用到无穷大。例如,在最短路径算法中,我们需要将当前距离与迄今为止的最佳或最小距离进行比较。
我们用正无穷大初始化未知距离。无论你在程序中输入什么距离,没有一个数能大于这个无穷大的表示。
我们讨论了在 Python 中表示无限值的多种方式。
我个人使用 math.inf
方法来定义一个无穷数。这是因为这种方法通常是三种方法中最快的。另外,math
是一个标准库,已经是我大部分代码的一部分。
%timeit np.inf
# 38.3 ns ± 0.208 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)%timeit float('inf')
# 198 ns ± 2.56 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)%timeit math.inf
# 37.5 ns ± 0.0933 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
但是像往常一样,当我们开始处理数组时,Numpy 变得更快:
%timeit [math.inf for _ in range(10000)]
# 585 µs ± 8.29 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)%timeit np.full(10000, np.inf)
# 10.4 µs ± 49.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
希望你觉得这个教程有用!你可以在这里找到我的其他故事。
如何在 Python 中处理缺失数据
原文:https://towardsdatascience.com/how-to-deal-with-missing-data-in-python-1f74a9112d93?source=collection_archive---------1-----------------------
使用 Pandas 和 NumPy 处理数据集中的缺失值
弗兰基·查马基在 Unsplash 上拍摄的照片
L 去年,我在做一个处理 Twitter 数据 的项目。我们的数据库中有大约 10 亿条推文。我需要清理我们的数据,这样我们就可以在上面运行一些机器学习模型。
以下是数据集的快照:
来源:作者
奇怪的 Unicode 字符(表情符号),标识符变化的随机缺失值等。我仍然会做那个项目的噩梦。
但是,现实世界的数据集就是这样。您会得到缺失值、随机字符、错误的数据类型等。根据一些统计, 数据科学家最终要花费 80%的时间来组织和清理数据 。
数据集中常见的情况是 缺失值 。这可能是由多种原因造成的,如未记录的观察结果或数据损坏。
在本教程中,我们将通过使用 熊猫库 来了解在 Python 中处理缺失值的许多不同方式。
熊猫库为标记这些腐败的价值观提供了多种功能。我们将研究如何去除或估算这些值。
来源: Giphy
设置
本教程中的所有例子都在运行 Python 3.7 的 Jupyter 笔记本上测试过。我们将在本教程中使用 NumPy 和 熊猫 。
这里有一个附带的 Jupyter 笔记本。
我强烈推荐建立一个虚拟环境,里面有测试所需的所有库。这是你可以做到的。
$ virtualenv missing_data
$ source ./missing_data/bin/activate
$ pip3 install pandas numpy
员工数据集
在本教程中,我们将使用小型员工数据集。
从我的 Github repo 中下载 CSV 格式的数据集,并存储在您当前的工作目录:employees . CSV
让我们将这个数据集导入 Python 并查看一下。
输出:
来源:作者
我们将 CSV 文件读入一个 熊猫数据帧 。[.head()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.head.html)
方法返回数据帧的前五行。
该数据集有 1000 个观察值,其中六个变量如下所示:
数据集中的所有变量。来源:作者
如何将无效/损坏的值标记为缺失
每个数据集中有两种类型的缺失值:
- 可见错误:空白单元格、特殊符号如 NA (不可用)、 NaN (不是数字)等。
- 模糊错误:未损坏但无效值。例如,负薪金或姓名的数字。
注意:对于埃隆的儿子 X?A-12,命名规则可能需要一些修改。
雇员数据集有多个缺失值。让我们仔细看看:
数据集的前 10 行。来源:作者
你会注意到像 NA , NaN ,这样的值?和空白单元格。这些代表我们数据集中缺失的值。
让我们打印'薪金'列的前 10 行。
print(df['Salary'].head(10))
我们在下面的图片中描绘了数据集的快照和上述语句的输出。
左:数据集中的薪金列。右图:熊猫进口时的工资栏。来源:作者
Pandas 会自动将空白值或带 NA 的值标记为 NaN(缺失值)。
Pandas 还为每一行分配一个索引值。包含 NaN 的值在 mean、sum 等运算中被忽略。
虽然这适用于 na 和空白行,但熊猫无法识别其他符号,如 NA?,不适用,不适用。这可以在'性别'栏中看到:
左:数据集中的性别列。右图:熊猫进口时的性别栏。来源:作者
如前所述,Pandas 处理空白值并将其转换为 NaN。但对于第 6 行中的不适用,它无法这样做。
当多个用户手动将数据输入数据库时,这是一个常见的问题。我们可以将 **.read_csv()**
方法 中的所有这些符号作为一个列表来传递,以允许熊猫识别它们为腐败值。看一看:
现在,n.a .也转为 NaN。来源:作者
处理无效数据类型
到目前为止,我们丢失的值都有唯一的标识符,这使得它们很容易被发现。但是当我们得到一个无效的数据类型时会发生什么呢?
例如,如果我们期望一个数值,但是,用户输入一个字符串,如' No' 表示薪水。从技术上讲,这也是一个缺失值。
我设计了一个函数,允许我检查列中的无效数据类型。假设我希望确保' Salary' 列中的所有值都是类型int
。我将使用以下内容:
此后,在出现无效条目的地方,薪金列中的值将是带有 NaN 的类型 int
。
使用 isnull 和 notnull 标记缺失值
在 Pandas 中,我们有两个用于标记缺失值的函数:
[isnull()](https://www.geeksforgeeks.org/python-pandas-series-isnull/)
:将数据集中的所有 NaN 值标记为真[notnull()](https://pandas.pydata.org/pandas-docs/version/0.23.4/generated/pandas.notnull.html)
:将数据集中的所有 NaN 值标记为 False。
看看下面的代码:
# NaN values are marked True
print(df[‘Gender’].isnull().head(10))# NaN values are marked False
print(df[‘Gender’].notnull().head(10))
左:原始性别栏,中:isnull()
函数输出,右:notnull()
函数输出
我们可以使用
isnull
和notnull
功能的输出进行过滤。
让我们打印所有没有性别遗漏的行。
# notnull will return False for all NaN values
null_filter = df['Gender'].notnull()# prints only those rows where null_filter is True
print(df[null_filter])
缺失值统计
isnull
和notnull
也可以用来汇总缺失值。
检查我们的数据帧中是否有任何缺失值:
print(df.isnull().values.any())# Output
True
每列缺失值的总数:
print(df.isnull().sum())# Output
First Name 70
Gender 149
Salary 5
Bonus % 4
Senior Management 71
Team 48
如何删除缺少值的行
既然我们已经将数据集中所有缺失的值标记为 NaN,我们需要决定如何处理它们。
最基本的策略是删除所有包含缺失值的行,或者在极端情况下,删除包含缺失值的整列。
Pandas 库提供了
[dropna()](https://pandas.pydata.org/pandas-docs/version/0.21.1/generated/pandas.DataFrame.dropna.html)
函数,可以用来删除丢失数据的列或行。
在下面的例子中,我们使用dropna()
删除所有丢失数据的行:
# drop all rows with NaN values
df.dropna(axis=0,inplace=True)
[inplace=True](https://pandas.pydata.org/pandas-docs/version/0.21.1/generated/pandas.DataFrame.dropna.html)
使所有更改发生在同一个数据框中,而不是返回一个新的数据框。
要删除列,我们需要设置 axis = 1。
我们也可以使用[how](https://pandas.pydata.org/pandas-docs/version/0.21.1/generated/pandas.DataFrame.dropna.html)
参数。
**how = 'any’**
:至少有一个值必须为空。how = 'all’
:所有值必须为空。
使用how
参数的一些代码示例:
输入数据集中缺失的值
当缺少值的情况很少时,删除行是一个很好的选择。但是这并不总是可行的。我们需要用聪明的猜测来代替这些 NaNs。
替换缺失值时,有许多选项可供选择:
- 单个预先确定的常数值,如 0。
- 从另一个随机选择的样本中取值。
- 列的平均值、中值或众数。
- 使用预测模型插值。
为了填补数据集中缺失的值,Pandas 库为我们提供了
[fillna()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.fillna.html)
、[replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html)
和[interpolate()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.interpolate.html)
、、函数。
让我们用例子一个一个地看这些函数。
用单个常数值替换 NaNs
我们将使用fillna()
将“薪金”列中缺失的值替换为 0。
df['Salary'].fillna(0, inplace=True)# To check changes call
# print(df['Salary'].head(10))
我们也可以对像'性别'这样的分类变量做同样的事情。
df['Gender'].fillna('No Gender', inplace=True)
用前一行或下一行的值替换 NaNs
这是填充图像数据中缺失值的常用方法。我们使用method = 'pad’
从前一行中取值。
df['Salary'].fillna(method='pad', inplace=True)
我们使用method = 'bfill’
从下一行的中取值。
df['Salary'].fillna(method='bfill', inplace=True)
来源:作者
使用列的中间值/平均值替换 NaNs
常见的合理方法。
# using median
df['Salary'].fillna(df['Salary'].median(), inplace=True)#using mean
df['Salary'].fillna(int(df['Salary'].mean()), inplace=True)
注意:关于
fillna
的其他选项的信息可在处获得。
使用替换方法
[replace](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html)
方法是fillna
方法的一种更通用的形式。这里,我们指定了要替换的值和替换值。
# will replace NaN value in Salary with value 0
df['Salary'].replace(to_replace = np.nan, value = 0,inplace=True)
使用内插法
interpolate()
函数用于使用各种插值技术填充 NaN 值。点击阅读更多关于插值方法的信息。
让我们使用 线性插值法 对缺失值进行插值。
df['Salary'].interpolate(method='linear', direction = 'forward', inplace=True)
print(df['Salary'].head(10))
使用线性插值后的输出。来源:作者
结束语
不管我们喜欢与否,现实世界的数据都是杂乱无章的。 数据清洗 是每个数据科学项目的主要部分。
在本教程中,我们回顾了检测、标记和替换缺失值的技术。
数据经常由于随机原因丢失,如数据损坏、信号错误等。但有些时候,这种数据缺失还有更深层次的原因。
虽然我们讨论了使用平均值、中值、插值等进行替换,但缺失值通常与我们的数据有一种更复杂的统计关系。我建议浏览本指南的了解更多详情。
希望看完这篇教程,你少花点时间清理数据,多花点时间探索建模。很高兴在下面的评论中回答你的所有问题。
相关材料
- Python 熊猫—缺失数据
- DataCamp 课程:用 Python 处理丢失的数据
- 机器学习掌握——如何用 Python 处理缺失数据
Chaitanya Baweja 渴望用工程解决方案解决现实世界的问题。在 Twitter 和 Linkedin 上关注他的旅程。
作为有抱负的数据科学家如何应对拒绝
原文:https://towardsdatascience.com/how-to-deal-with-rejection-as-aspiring-data-scientist-2b781d2b800a?source=collection_archive---------11-----------------------
在工作过程中跌倒后重新站起来的 12 条建议。
别担心,总有一天你会到达那里的。
你一直在申请数据科学的职位。但几个月来,你收到的唯一回复是这样开始的:“我很抱歉地通知你……”当你收到另一封来自一家公司的信时,你畏缩了,泪流满面,这家公司不会给你机会展示你所拥有的所有技能。
或者你过得更好。你获得了这家公司的第四次也是最后一次面试机会,而这家公司正是你真正想为之工作的。你对公司做了功课,为技术面试做了准备,并向正确的神祈祷。
但是当你认为你已经掌握了面试的机会时,你失败了。在决定命运的那一天,你太紧张了,以至于你不能发挥出 100%的水平。或者也许你 100%的努力还不够。
你被一家公司拒绝了。又来了。
对于那些处于这种情况的人,作为一名有抱负的数据科学家,这里有 12 条关于如何在精神和情感层面上处理拒绝的个人建议。我希望这些提示可以指导和重新激励你不懈的努力,在数据科学领域获得梦想的工作。
1.我们都经历过。
每一位在工业界工作的数据科学家都经历过和你现在一样艰难的工作流程。我们都以同样令人沮丧的方式失败了,但也以同样胜利的方式成功了。接下来的几个建议将深入探讨你如何处理你最低落的时刻。
第一个建议是假设你不是那种智商 167、资质完美、第一次尝试就拿到所有 FAANG offer 的人。像这样的地方很少。假设你不是那样的人,你是那 99%不懈努力实现梦想的人的一部分。
2.这是一个数字游戏。
如果你有一个数据科学伙伴可以把你的简历传给招聘经理,那就太好了。但是你们中的许多人正在转行,没有这种奢侈。这很好,因为冷申请无论如何都管用(我就是这样找到第一份工作的)。
从统计学的角度思考申请过程(作为未来的数据科学家)。假设你可以每隔 1~1.5 分钟发 1 个冷应用。所以每小时你会收到大约 40~60 份申请。如果每天花 3 个小时,那就是 120~180 个左右的应用。假设响应率的下限是 1%。那仍然是每 3 小时至少有一个响应。
相比之下,追求温暖的应用路线。你首先在 LinkedIn 上搜索一位前同事的朋友,他是一名数据科学家。你花每月的 LinkedIn premium 积分向熟人发送这样的直接消息,希望有人会回应你的咖啡聊天。一位数据科学家慷慨地同意了,然后你去了要求的位置。你尴尬地和那个人谈了大约一个小时,最后(紧张地)请求推荐。你得到了肯定的回答。万岁!。
整个过程需要多长时间?假设最初的搜索加上发送精心制作的消息花了 1 个小时。你花了一整天等待回应。也许一个感同身受的灵魂会在两天后当这个人有空的时候回应一次会面。直接会见数据科学家需要 30 分钟~ 1 小时,另外 1 小时用于咨询请求的对话。
两者都是有效的策略,但投资回报不同。如果统计结果正确,冰冷的电子邮件会导致招聘人员更多的回复。热情的方式让你离与招聘经理通话更近了一步。因此,了解这两种策略的优点和缺点。
我的战术侧重于掌握冷应用策略。通过试验和失败,我最终达到了每个公司每个应用程序 1~1.5 分钟的效率水平。当我现在的公司在我提交申请 3 天后联系我时,我已经完全忘记了他们实际上做了什么,因为那时我已经申请了 300 多个其他地点。
3。完善你的简历和求职信。
如果你的简历和求职信不合格,最大的申请效率并不重要。招聘人员在每份简历上花大约 7 秒钟寻找关键词。有时候公司会用 AI 根据这些词筛选出简历。换句话说,请专业人士审核你的简历。
大多数申请都有附信选项。当我没有附上求职信时,我还没有收到公司的回复。确保你写的求职信足够通用,适用于大多数公司,但也足够具体,这样即使你要改变公司名称和职位要求,求职信仍然有意义。
4.永远不要把所有的鸡蛋放在一个篮子里。
即使你即将得到那份工作,也不要停止申请。相信我;有一次,一家小公司的首席技术官直接找到了我,他在阅读了我的一篇关于数据科学的热门帖子后找到了我。我为这个事实感到非常自豪,以至于我不再申请其他角色。
这种专注于一家公司以实现单一回报最大化的策略在当时是有道理的。这似乎也很有效,我进入了面试阶段,直到与首席执行官面对面。他认为我很适合。但是当我最后一次技术面试时,我没能解析嵌套字典,他们不得不拒绝我的提议。
我崩溃了,更糟糕的是,我没有面试机会了,因为我的申请渠道已经枯竭了。感觉我不得不从头开始,这是一个令人心碎的时刻,如果我有其他的面试机会,这一时刻是可以弥补的。永远不要让这种情况发生在你身上。一直坚持申请。
5.这应该是(非常)艰难的
有成百上千的人申请同一个职位,他们的资历即使不比你好,也和你一样好。会很难,非常难。如果这个过程很简单,那实际上应该被视为公司的一个危险信号。这是一个违反直觉的说法,但听起来往往是正确的。
大多数拥有合法且经验丰富的数据科学团队的公司都会严格制定面试程序,以仔细衡量候选人的分析和解决问题的能力。这些技能可以代表候选人在被聘用后作为数据科学家的潜在表现。这就是为什么面试时间很长,并夹杂着棘手的脑筋急转弯问题。精心设计艰难面试过程的另一个原因是为了在众多初级求职者中找到最好的申请人。
从相反的角度思考这个问题;如果整个数据科学面试过程只有 1 个小时,没有任何技术问题,您对一家公司有多少信心?作为一名申请人,你也在评估自己是否适合这家公司,你希望置身于这样一个环境中,通过受到队友和经理的挑战而积极成长。
6.面试不同于数据科学技能。
扩展以上观点,技术面试本质上是智力测试。在我的另一篇文章中,我分解了智力测试的组成部分:
[## 抱歉,项目不会给你带来工作
我们如何高估了数据科学项目在工作过程中的作用——以及实际上…
towardsdatascience.com](/sorry-projects-dont-get-you-jobs-3e5d8e74bfdc)
作为 TLDR,切记数据科学技能 != 面试技巧。两者是不同的野兽。这就像标准化能力倾向测试(或你所在国家的大学入学可比能力倾向测试)。SAT 代表你的“智力”和对基础知识的掌握程度。他们有自己的规则和程序,如果你想进入一所好的大学,你需要玩这个游戏。从同样的角度考虑技术面试。
7.学位不是阻止你的东西。
相信我,当我说你不需要一个编程或统计硕士/学士学位就能成为一名数据科学家。我的学士学位是英国文学。如果你认为你很糟糕,想想我自己经历了什么。
学位和背景只对接到招聘人员的第一个电话有影响。之后其实就是我上面说的智力测试了。学位之所以重要,首先是因为竞争。我说几百个有着相同资历的人都在申请同一个职位。
他们中的许多人——至少是加利福尼亚湾区的人——拥有与数据领域相关的硕士学位。与学士学位相比,进入美国名牌大学攻读硕士学位相对容易(我知道这一点,因为我自己也是从常春藤盟校获得硕士学位的)。
加上 OPT / H1B 签证的情况,每年有 1000 多名拥有令人印象深刻的美国学位的毕业生试图获得那些利润丰厚的入门级数据分析师和科学家职位。如果你没有硕士学位,你看起来已经不如那些有硕士学位的人有竞争力了。
如果这是你担心的,我会罩着你的。在TDS 独家采访中,我采访了 DoorDash 的 Jeffrey Li,他分享了他在没有软件或统计学位的情况下获得多个数据科学职位的 3 个重要策略。这些策略贯穿整个面试过程,从接到招聘人员的电话到赢得招聘经理的芳心。
8.你可以做好每一件事,但仍然会被拒绝。
也许你有合适的学位和证书。对于你现在面试的这家公司来说,你在技术挑战上一点也没有失误。事实上,公司里你见过的每个人都给你一种强烈的感觉;他们似乎很有兴趣和你一起工作。为了进一步巩固你的地位,你可以利用 Jeffrey Li 在 TDS 采访中谈到的公文包场景。
但是,只是但是,几天后你发现他们拒绝了你的工作邀请。你感到震惊,困惑,崩溃。你不停地问自己,“我做错了什么?”。
我是来告诉你也许做错事的不是你。也许有些力量超出了你的控制范围,就像另一位决赛者的简历上有一件比你更令人印象深刻的事情。类似于数据科学,不确定性是工作流程中的固有变量。你可以尽力而为,但运气并不总是对你有利。把这种情况理解为公司不适合你。也许这反而是他们的损失。
9.失败可能是(巨大的)塞翁失马焉知非福。
也许你注定要失败。通过失败和从失败中成长,你已经成为一个更有能力和竞争力的候选人。这种成长我见过很多次了。申请人在最初几次面试中失败,在面试中变得更好,再失败一些,到第 30 次失败时,他们已经非常擅长面试,现在他们可以接受顶级公司最严格的面试。
10.这可能需要很多很多个月,但没关系。
我花了大约 4 个月的时间才得到最终的工作机会。对其他人来说,需要 8 个月,有些超过一年。想到你可能会失业一年,真是令人心碎。我知道。这是一个难以接受的现实。但是请记住,每个人最终都会到达他们想要到达的目的地。从那以后只会变得更加容易。
11.你恢复得越快,你就能越快成功。
恢复时间是需要这么长时间才能得到梦想中的数据科学工作的部分原因。忍受和克服痛苦的节奏因人而异,因为有些人沉浸在悲伤中的时间比其他人长。
我不是告诉你停止悲伤;我告诉你,当生活击倒你时,要增强你的精神毅力,重新站起来。在我第一轮与首席技术官的面试失败后,我经历了整整 3 天的痛苦和消极。但是通过体育、音乐和朋友,我立即投入了战斗。
12.其他角色也存在。
最后一点,你也可以随意申请其他职位。你不必只申请数据科学家的职位。数据分析师、数据工程师、业务分析师、产品分析师也是在某种程度上使用数据的重要角色。如果真的到了那一步,向其他机会敞开心扉。
[## Haebichan Jung - Medium
阅读容格在媒介上的作品。“走向数据科学|芯片领域的数据科学家”项目负责人…
medium.com](https://medium.com/@haebichan)
如何调试 ML 模型:NLP 中的分步案例研究
原文:https://towardsdatascience.com/how-to-debug-an-ml-model-a-step-by-step-case-study-in-nlp-d79d384f7427?source=collection_archive---------45-----------------------
虽然有这么多文章介绍如何开始学习 NLP 或向您提供指导,但最难学习的课程之一是如何调试模型或任务实现。
模型/任务实施前的精神状态,通过 Pixabay (CC0)的 StockSnap
模型/任务实施后的精神状态,Free-Photovia pix abay(CC0)
不要担心!本文将介绍一系列相当微妙(和不那么微妙)的错误的调试过程,以及我们如何修复它们,并通过一个案例研究来引导您完成这些课程。如果你想看提示列表,向下滚动到最后!
为了做到这一点,让我带你回到几个月前,那时我们(我的研究合作者 Phu 和我)第一次将屏蔽语言建模实现到 jiant 中,这是一个开源的 NLP 框架,目标是在 RoBERTa 模型上进行多任务训练。如果这听起来像是一种陌生的语言,我建议你先看看这篇关于迁移学习和多任务学习的文章,和这篇关于罗伯塔模型的文章。
设置场景
屏蔽语言建模是 BERT、RoBERTa 和许多 BERT 风格变体的预训练目标之一。它由一个输入噪声目标组成,其中给定一个文本,该模型必须预测给定上下文的 15%的标记。更困难的是,这些预测的标记有 80%的时间被替换为“[MASK]”,10%被另一个随机标记替换,10%是正确的、未被替换的标记。
例如,该模型如下所示
为 MLM 培训更改的文本示例。这里,模型将学习预测当前被“[MASK]”占据的令牌的“tail”
设计初始实施
我们首先查看了其他人以前是否实现过 MLM,发现了 Google 的最初实现和 AllenNLP 的 Pytorch 实现。我们几乎使用了所有的 Huggingface 实现 n(它已经被移动了,因为它看起来像是以前在那里的文件已经不存在了)来实现转发功能。根据 RoBERTa 的论文,我们在每个时间步动态地屏蔽了批次。此外,Huggingface 在这里暴露了预训练的 MLM 头,我们使用如下。
因此,我们代码中的 MLM 流变成了下面这样:
加载 MLM 数据->预处理和索引数据->加载模型->在模型训练的每个步骤中,我们:
1.动态屏蔽批处理
2.计算每个屏蔽令牌的 NLL 损耗
jiant 框架主要使用 AllenNLP 进行词汇创建和索引,以及实例和数据集管理。
我们首先用一个包含 100 个数据集示例的玩具数据集进行测试,以确保 AllenNLP 的加载是正确的。在我们经历了一些非常明显的错误之后,比如一些标签类型与 AllenNLP 不匹配,我们遇到了一个更大的错误。
麻烦的最初迹象
在确保我们的预处理代码与 AllenNLP 一起工作后,我们发现了一个奇怪的 bug。
TypeError: ~ (operator.invert) is only implemented on byte tensors. Traceback (most recent call last):
这是因为我们从 Huggingface 复制粘贴的代码是用旧版本的 Python 编写的,并且是在您需要使用的 Pytorch 中。byte()而不是 bool()。
因此,我们简单地修改了一行,从
indices_replaced = torch.bernoulli(torch.full(labels.shape, 0.8)).bool() & masked_indices
到
bernoulli_mask = torch.bernoulli(torch.full(labels.shape, 0.8)).to( device=inputs.device, dtype=torch.uint8 )
麻烦来了
现在,我们终于能够运行一个正向函数而不出错了!庆祝了几分钟后,我们开始验证更微妙的错误。我们首先通过调用 model.eval()并通过 MLM 转发函数运行模型来测试我们实现的正确性。因为这个模型,在这个例子中是 RoBERTa-large,已经在 MLM 进行了预训练,我们希望它在 MLM 会有很好的表现。事实并非如此,我们损失惨重。
原因很明显:预测总是与黄金标签相差 2%。例如,如果标记“tail”被分配了索引 25,那么“狗看到零食时摆动它的[面具]”和“[面具]”的标签将是 25,但是预测将是 27。
我们是打了这个错误才发现的。
`/pytorch/aten/src/THCUNN/ClassNLLCriterion.cu:105: void cunn_ClassNLLCriterion_updateOutput_kernel(Dtype *, Dtype *, Dtype *, long *, Dtype *, int, int, int, int, long) [with Dtype = float, Acctype = float]: block: [0,0,0], thread: [19,0,0] Assertion `t >= 0 && t < n_classes` failed.`
这个错误意味着预测空间大于类的数量。
经过大量的 pdb 跟踪,我们意识到我们没有使用 AllenNLP 标记/标签名称空间。在 AllenNLP 中,您可以使用名称空间(如标签名称空间和输入名称空间)跟踪 AllenNLP 词汇对象中需要的所有词汇。我们发现 AllenNLP 词汇对象 a 自动插入 @@PADDING@@和@ @ UNKOWN @ @标记来索引除标签名称空间(所有以“_tag”或“_labels”结尾的名称空间)之外的所有名称空间的 0 和 1 因为我们没有使用标签名称空间,所以我们的索引向前移动了两个,预测空间(由标签词汇大小定义)大了两个!发现这一点后,我们重新命名了标签索引,这种特殊的威胁得到了遏制。
最后一个隐藏的 Bug 和一个支点
到目前为止,我们认为我们已经捕获了所有或者大部分的错误,并且 MLM 工作正常。然而,当模型现在变得越来越不困惑时,一周后,当与第三个人一起查看代码时,我们发现了另一个隐藏的 bug。
if self._unk_id is not None:
ids = (ids — 2) * valid_mask + self._pad_id * pad_mask + self._unk_id * unk_mask
else:
ids = (ids — 2) * valid_mask + self._pad_id * pad_mask
在我们几个月前编写的代码的某个单独部分,我们将任何基于 Transformer 的模型的输入向后移动了 2,因为 AllenNLP 将其向前移动了 2。因此,从本质上来说,模型看到的是胡言乱语,因为它看到的是距离正确输入索引两个索引的词汇标记。
我们是如何解决这个问题的?
我们结束了对以前的 bug 的修复,并且没有使用 label 名称空间作为输入,因为所有的东西都向后移动了 2。并且简单地确保动态生成的 mask_idx 在被馈送到模型中之前向前移位 2。为了修复之前预测和标签空间大小不匹配的错误,我们将标签的数量设为预训练模型的标记器的大小,因为这包括该模型预训练的所有词汇。
经过无数个小时的调试和初步实验,我们终于摆脱了 bug。唷!
因此,作为对我们所做的事情的回顾,以确保代码没有错误,也是为了回顾我们所看到的错误类型,这里有一个漂亮的列表。
调试模型的关键要点
- 从玩具数据集开始测试。对于本案例研究,预处理整个数据集需要大约 4 个小时。
- 如果可能,使用已经创建的基础设施。
- 请注意,如果您正在使用其他人的代码,请确保您确切地知道它如何适合您的代码,以及在将外部代码集成到您自己的代码中时可能出现的任何不兼容性,无论是微妙的还是不明显的。
- 如果您正在使用预训练的模型,并且如果有意义,请尝试加载一个训练过的模型,并确保它在任务中表现良好。
- 注意代码之间 Pytorch 版本(以及其他依赖版本)的差异。
- 索引时要非常小心。有时勾画出索引的流程是非常混乱的,会导致很多令人头疼的问题,为什么你的模型执行得不好。
- 让其他人也看看你的代码。
- 为了理解 bug 的来源,您可能需要更深入地了解这些杂草,并查看用于预处理的包的源代码(如 AllenNLP)。
- 创建单元测试来跟踪细微的错误,并确保您不会因为代码更改而依赖这些错误。
现在你有了它,一个调试案例研究和一些教训。我们都在一起进行更好的调试,我知道我远不是模型调试的专家,但是希望这篇文章对你有帮助!特别感谢 Phu Mon Htut 编辑这篇文章。
如果你想看最终的实现,点击这里查看!
如何调试机器学习模型以尽早发现问题
原文:https://towardsdatascience.com/how-to-debug-machine-learning-models-to-catch-issues-early-and-often-5663f2b4383b?source=collection_archive---------12-----------------------
通过更好的数据捕获、实时监控和及时干预,节省机器学习培训的时间和成本
Eek!我的神经网络有个 bug!
如果你从事软件开发,你会知道程序错误是生活中的事实。当你开始你的项目时,他们会在那里,当你把你的产品交付给客户时,他们也会在那里。在过去的几十年里,软件开发社区已经开发了大量的工具、ide、库和技术来帮助尽早地、经常地捕捉 bug,因此很少会出现在产品代码中。
不幸的是,机器学习开发人员和数据科学家并不享受传统软件可用的同样健壮的调试工具集。这就是为什么我们很多人在培训脚本中使用打印语句。在集群上运行分布式训练或大规模实验时,问题会变得更糟。您可以保存来自多个工作人员的日志,但是发现问题就像大海捞针一样困难。
在这篇博文中,我将讨论是什么让调试机器学习代码不同于传统软件,以及为什么它要困难得多。然后,我将展示如何使用更好的机制来捕获调试信息、实时监控培训期间的常见问题以及及时干预以防止不良工作浪费资源,从而应对这些挑战。
为了实现这些技术,我将使用 Amazon SageMaker 调试器——一个托管服务和一个用于调试机器学习模型的开源库。通过示例,我将展示如何使用 Amazon SageMaker 调试器和带有 TensorFlow、Keras 和 PyTorch 的 smdebug 开源库(也支持 MXNet 和 XGBoost)来收集训练期间的调试数据,设置规则来监控条件并实时或离线分析数据。
是什么让机器学习调试与众不同?
如果机器学习只是软件,那么只使用传统软件开发可用的相同调试工具不是很有意义吗?毕竟,今天你有很多工具。您可以:
- 使用您最喜欢的集成开发环境(IDE ),它允许您放置条件断点并检查中间变量,
- 利用特定于语言的编程结构进行异常处理和类型检查
- 使用静态代码分析工具来尽早发现错误,并检查是否符合标准
- 使用调试器库,如 gdb
- 使用记录器和精心选择的打印语句执行记录和跟踪
即使有了所有这些工具,仍然很难找到机器学习的错误,这有几个原因,我在下面描述。
(1)机器学习不仅仅是代码
传统软件代码与机器学习代码
让我们考虑一下典型的(简化的)数据科学问题——你有一个数据集和一个问题陈述,你必须建立一个模型来根据数据预测一些事情。然后你衡量它的准确性,如果满意就使用这个模型——例如,部署它,集成到一个更大的软件项目中,出售它等等。
与传统软件相比,机器学习代码有更多的活动部分。存在数据集、模型架构、在训练期间微调的模型权重、优化算法及其参数、在训练期间改变的梯度等等。
在某种意义上,机器学习代码在训练阶段是“动态的”。我的意思是,你的“源代码”本质上是随着你的模型训练而变化或发展的。在训练过程中,模型中的数百万个参数或权重在每一步都在变化。一旦训练完成,它就停止变化,此时您在训练中没有发现的错误现在是模型的一部分。与传统软件形成对比——代码中的逻辑和规则不会在每次运行时改变。可能会有条件分支,但代码仍然是“静态的”,因为不像机器学习训练那样有无限的结果。
调试这种动态的、不断发展的代码需要不同的工具。你需要的是一种方法,通过分析数百万个不断发展的变量来检查训练进度,并在满足某些条件时采取行动。您希望能够监控模型参数、优化参数和指标,以捕捉消失梯度、激活饱和度等问题。
在这个领域缺乏适当的工具是我们许多人使用打印报表和记录器来分析培训的原因。
(2)在机器学习训练期间的监控和干预是困难的
调试运行在集群上的代码比调试运行在笔记本电脑或 Amazon EC2 实例上的代码更难
大量的机器学习训练代码运行在集群上,或者至少运行在云中远离你的计算机上。这是因为在进行大规模培训时,短期租用大量具有 GPU 的强大机器更加高效和经济。
那么,如何在集群中运行的代码上设置条件断点呢?
当您的编程范式改变时,您的调试工具和方法也应该改变。当您在集群上运行一个分布式培训任务时,监控进度的主要方法是检测您的代码以生成日志,并将它们保存在一个中心位置以供分析。相反,您需要一种简单的方法来实时监控进度,并在满足特定条件时向您发出警报或采取一些措施。如果你不必修改你的训练脚本,那就更好了。这让我们面临下一个挑战。
(3)调试机器学习代码可能需要大量的重写或转换框架
在其核心,机器学习代码依赖于一系列用 C、C++和 CUDA 等语言编写的高度优化和微调的线性代数子程序。诸如 TensorFlow、PyTorch、MXNet 等更高级别的框架抽象出底层的复杂性,并为您提供一种简单方便的方法来设计和训练您的模型。当你隐藏了复杂性,你就为了易用性而牺牲了控制,调试就变得困难了。
机器学习框架遵循两种不同的哲学——(1)声明性方法,其中您将模型架构定义为图形,该图形被编译、优化,然后被执行(例如 TensorFlow) (2)命令性方法,其中您将模型架构定义为图形,并且它按照定义被执行(例如 PyTorch、TensorFlow eager mode)。在声明式方法中,您无法访问优化的图,因此调试会更加困难。在命令式方法中,调试更容易,但是需要努力在较低的级别检测代码以捕获调试数据,并且在某些情况下需要牺牲性能。
为了更好地调试,您必须编写额外的代码来检测您的训练脚本,或者重写您的代码来支持命令式风格或切换框架。或者更糟,在多个框架上维护相同的副本。所有这些选择都是更多错误的机会。
(4)错误会让您付出代价—基础架构成本,更重要的是,您的时间
机器学习会浪费计算和存储资源
大多数机器学习问题可以在训练过程的早期发现。一些常见的问题,比如初始化不好,渐变消失,激活函数饱和,可以而且应该尽早发现,以防止时间和资源的浪费。随着时间的推移,其他问题也会显现出来,比如过度适应或过度训练。早期和晚期发生的问题都会让你付出代价。
早期发生的问题是不可挽救的,并且由于训练运行产生垃圾,导致基础设施资源浪费。如果实践了良好的检查点,后期出现的问题是可以补救的。通过在问题发生时回退到检查点,您仍然可以获得一个好的模型。然而,在问题发生后用于培训的所有资源再次被浪费。
这种浪费会累积起来,耗费你的金钱和时间,尤其是当你有多个团队并行运行多个项目的时候。
尽早发现过度合身等问题,并采取措施减少浪费
在随附的图表中,您可以看到一个示例,当模型在 20k 步左右开始过度拟合时,应该停止训练。相反,培训一直持续到大约 40k,花费了您两倍的基础设施成本。诸如此类的问题很常见,因为我们指定了固定数量的时期来运行培训作业,然后出去吃午饭。
在机器学习调试器中寻找什么?
如果传统的软件开发调试工具对机器学习不起作用,你如何着手调试机器学习代码?
以下是一个好的机器学习调试器应该具备的显著特征:
- 捕获:调试器必须能够在训练期间捕获模型和优化器的特定信息。用户必须能够指定粒度(频率)和后处理(在张量上应用缩减)来管理调试数据。
- 反应:调试器必须能够监控捕获数据的变化并做出反应。用户必须能够指定满足条件时触发的断言规则,例如分解渐变或过度拟合。
- 分析:调试器必须允许你在训练期间实时分析捕获的数据。用户还必须能够对捕获的数据进行离线分析。
现在让我们看看如何使用 Amazon SageMaker 调试器来执行这些调试步骤。
使用 Amazon SageMaker 调试器进行调试
Amazon SageMaker Debugger 是 Amazon SageMaker 服务套件的一项新功能,使用它,您可以通过监控、记录和分析捕获训练作业状态的张量数据来全面了解模型训练。有两种方法可以使用它:
- Amazon SageMaker 托管训练:使用 Amazon SageMaker 训练模型时会自动启用调试器,您不需要对您的训练脚本进行任何更改。只需指定要监控的问题,它就会自动运行监控作业,可以捕捉许多条件,如消失的梯度,爆炸张量,过度拟合和训练期间的其他情况。它还会在训练期间捕捉张量,并将其保存在亚马逊 S3 中,以供实时或离线分析。
**smdebug**
开源库:对于 DIY 体验,你可以使用开源库对你用 TensorFlow、Keras、PyTorch、MXNet 或 XGBoost 编写的训练脚本进行插装,保存调试信息。然后,您可以在本地设置和运行监控。您可以使用它来调试 Amazon SageMaker 上的定制培训容器,或者在 Amazon SageMaker 上运行缩放之前,在您的笔记本电脑、台式机或 Amazon EC2 实例上本地调试框架。
让我们来看看亚马逊 SageMaker 调试器如何让您能够 (1) 捕获调试数据, (2)对特定调试条件做出反应,并为您提供工具来 (3)分析调试数据。
(1)使用调试器钩子捕获调试数据
机器学习训练期间的大部分繁重工作都发生在优化例程中。非常明确地说,我指的是数值优化例程,如随机梯度下降(SGD),而不是编译器优化。
这些例程负责将您的模型预测与实际值进行比较,计算梯度并更新权重以缩小预测损失的差距。这一步发生在机器学习框架的深处,并负责使用计算的梯度更新数百万个模型参数或权重和偏差。
钩子允许你捕获和保存模型和优化变量,如权重,偏差,梯度等。
为了在培训期间捕获这些信息,Amazon SageMaker 调试器可以自动将钩子插入到您的 TensorFlow、Keras、PyTorch、MXNet 或 XGBoost 代码中。当指定一个 SageMaker 调试器钩子时,你可以告诉它在训练期间需要保存什么信息。Amazon SageMaker 调试器支持一个预定义的张量列表,您可以要求它保存这些张量,其中包括权重、偏差、梯度、损失、度量、优化器变量等。如果想要在模型的特定层中捕获特定张量,也可以指定正则表达式字符串。
让我们来看看在使用(1) Amazon SageMaker 和(2) smdebug
开源库进行本地调试或在定制容器中使用时,如何指定一个钩子
在 Amazon SageMaker 上使用钩子
如果您使用 Amazon SageMaker 运行培训作业,Amazon SageMaker 调试器会在 TensorFlow、PyTorch、MXNet 和 XGBoost 培训作业容器中自动配置,您不必更改您的培训脚本。
当指定您的培训工作时,您需要做的就是指定一个挂钩配置,如下所示。
在这个例子中,钩子被指定为每save_interval
= 100 步节省(1)损失,(2)重量,(3)梯度和(4)偏差。如果您不想保存整个培训期间的信息,也可以提供开始和停止步骤。
当调用 SageMaker TensorFlow 估算器时,使用 Amazon SageMaker Python SDK 只需将钩子传递给debugger_hook_config
参数。
如果你是亚马逊 SageMaker 的新手,请观看这个介绍性的网络研讨会,了解如何在亚马逊 SageMaker 上开展培训工作。TL;DR-Amazon sage maker 为您的培训工作提供全面管理的体验。只需提供如上所示的培训脚本,它就会自动提供所需的资源并运行培训。亚马逊 SageMaker 网页上也有大量资源,包括培训、模型调整和部署。
您看到了在 Amazon SageMaker 上运行培训作业时如何使用调试器挂钩。接下来,我们将看到如何使用开源的smdebug
库,在你的笔记本电脑、台式机或亚马逊 EC2 机器上本地使用亚马逊 SageMaker 调试器。
通过开源 smdebug 库使用钩子
如果你想在你的训练脚本中加入钩子,你可以使用smdebug
库:
- 在您的笔记本电脑或台式机上运行您的培训脚本,亚马逊 SageMaker 无法自动为您提供帮助
- 运行在 Amazon SageMaker 上,但是您使用了一个定制的容器映像,Amazon SageMaker 不能自动为您放置钩子
如果你是这两种情况中的一种,你可以使用smdebug
库来放置钩子,只需要最小的代码修改。我在下面提供了 Keras 和 PyTorch 脚本的例子。
在 Keras 中放置挂钩
使用smdebug
库,首先创建一个KerasHook
,并指定钩子参数。在这个例子中,我要求KerasHook
在out_dir
保存张量值,在tensorboard_dir
保存张量板日志。我想保存的张量是梯度和偏差。我可以扩展这个列表来保存其他值,比如权重、optimizer_variables 等等。在后台KerasHook
将配置必要的回调函数来捕获数据。
将吊钩放入 PyTorch
使用smdebug
库,创建一个类似于上面 Keras 方法的钩子,然后在 net 变量中用神经网络注册这个钩子。您还可以使用损失函数注册挂钩,以在训练期间捕获损失值。
在你的训练循环中,使用钩子记录特定的张量值,使用hook.record_tensor_value
(2)使用调试器规则对调试数据中的变化做出反应
如果您不能在训练期间实时地对它们采取行动,那么使用钩子保存的调试数据就没有多大用处。这就是调试器规则的用武之地。规则是一段 Python 代码,用于在训练过程中检测特定条件。当规则状态改变时,会触发一个 Amazon CloudWatch 事件,您可以对该事件采取行动,例如停止训练,或者向您发送电子邮件或短信。
Amazon SageMaker 调试器为常见问题提供了几个内置规则,所以你不必为它们编写逻辑。这些包括:死 relu,爆炸张量,差权重初始化,饱和激活,消失梯度,全零,类不平衡,损失不减,过度拟合,过度训练和许多其他问题。如果您正在寻找的规则不在这里,那么您可以使用smdebug
库编写一个自定义规则,我们将在下面看到。
对于主动监控培训作业和捕捉问题的规则,它需要作为服务与您的培训作业同时运行。如果你正在使用 Amazon SageMaker 运行培训作业,一个规则容器会自动运行来监控你的培训作业,不需要你做任何操作。
或者,您也可以使用smdebug
库在您的笔记本电脑或台式机上本地运行规则。让我们来看看如何做到这两点。
对 Amazon SageMaker 培训工作使用规则
如果您使用 Amazon SageMaker 运行培训作业,一个规则作业将自动安排与培训作业一起运行。在训练期间,规则作业获取 Hook 保存的张量(来自 S3 ),并调用规则逻辑。
您可以拥有任意多的规则,系统会自动为您安排一个单独的规则作业。在附图中,我展示了两条规则:损失不减少和消失梯度。每个都将在 Amazon SageMaker 管理的独立容器中运行。
指定培训工作时,请指定挂钩配置,如下所示。
此示例显示了 3 个规则— 2 个内置规则(overtraining
、overfitting
)和 1 个自定义规则(CustomGradientRule
)
对于CustomGradientRule
,您应该指定您希望 SageMaker 使用什么资源来运行规则。在这个例子中,我指定了一个t2.medium
实例,它应该足以运行一个实现定制规则的简单 Python 脚本。
在您的 SageMaker 框架估计器函数(例如下面的 TensorFlow 估计器)中,您提供您的规则配置作为规则的参数。这将指示 Amazon SageMaker 不仅启动一个培训作业,还将规则作业,数量相当于您指定的规则数量。在本例中,有 3 条规则。
具有规则规范的培训作业将启动一个培训作业和监视该培训作业的规则作业
使用 smdebug 库的规则在本地运行它们
要在培训期间在你的笔记本电脑、台式机或 Amazon EC2 实例上本地运行规则,你需要使用smdebug
库指定一个规则。
在下面的例子中,我定义了一个名为CustomGradientRule
的规则。您可以通过从 Rule 类派生来定义自定义规则。核心逻辑在invoke_at_step
函数中。在这里,我检查梯度的绝对平均值是否大于某个阈值——如果没有指定阈值,则阈值为 10。
为了调用规则,创建一个自定义规则类的对象并调用invoke_rule
输出:
INFO rule_invoker.py:15] Started execution of rule CustomGradientRule at step 0
(3)在训练期间离线或实时分析和可视化调试数据
使用钩子,你可以导出数据,如体重,梯度和其他在训练中,规则让你检查条件,以便你可以采取行动。在某些情况下,您只想分析原始数据并绘制图表,以找到您还不了解的问题。当你这样做的时候,你可以把它转换成一个规则,这样你就可以在下一次训练中抓住它。
有两种可视化结果的方法:
- 在 Amazon SageMaker Studio 上使用内置的可视化工具
- 在本地笔记本电脑、台式机或 Amazon EC2 实例上进行定制分析和可视化
使用亚马逊 SageMaker Studio 可视化
Amazon SageMaker Studio 建立在熟悉的 Jupyter 笔记本体验的基础上,集成了跟踪实验、可视化训练期间的性能曲线以及比较实验中不同试验的结果的功能。您还可以通过选择由调试器挂钩保存的值来调出自定义图表。
关于如何使用 Amazon SageMaker Studio 图表和可视化以及 Amazon SageMaker 调试器的演示演练,请观看我的 NVIDIA GTC 2020 会议演讲视频:
GTC 2020:使用 Amazon SageMaker 调试器提高 ML 培训性能
GTC 2020:利用亚马逊 SageMaker 调试器提高人工智能训练性能
使用 smdebug 库进行本地分析和可视化
为了在本地分析您的数据,您需要使用smdebug
库创建一个试验。试用对象可用于查询张量名称、张量值等。
例如,如果您已经使用以下钩子训练了 PyTorch 模型来保存梯度和偏差:
hook = smd.Hook(out_dir=f'./smd_outputs/{job_name}',
save_config=smd.SaveConfig(save_interval=10),
include_collections=['gradients', 'biases'])
您可以在训练仍在运行时创建一个试验以进行实时分析:
import smdebug.pytorch as smd
trial = smd.create_trial(path=PATH_TO_S3_OR_LOCAL_DIR')
要查询保存了哪些张量,请运行:
trial.tensor_names()
因为我们要求保存梯度和偏差,所以当你调用 tensor_names 时,你会看到两者。
输出:
[2020-03-30 06:02:17.108 ip-172-31-28-67:31414 INFO local_trial.py:35] Loading trial pytorch-exp03-30-05-53-52 at path ./smd_outputs/pytorch-exp03-30-05-53-52
[8]:
['CrossEntropyLoss_output_0',
'Net_conv1.bias',
'Net_conv2.bias',
'Net_fc1.bias',
'Net_fc2.bias',
'Net_fc3.bias',
'gradient/Net_conv1.bias',
'gradient/Net_conv1.weight',
'gradient/Net_conv2.bias',
'gradient/Net_conv2.weight',
'gradient/Net_fc1.bias',
'gradient/Net_fc1.weight',
'gradient/Net_fc2.bias',
'gradient/Net_fc2.weight',
'gradient/Net_fc3.bias',
'gradient/Net_fc3.weight',
'loss_output_0']
检索和分析gradient/Net_conv1.bias
运行:
你会注意到渐变是每 10 步保存一次,这是我们在钩子中指定的。通过循环运行上述命令来查询最近的值,可以在训练期间检索张量。这样,您可以绘制性能曲线,或者随着训练的进行,可视化过滤器权重的变化。看看这个演示如何使用smdebug
在训练期间[实时监控课程激活](https://github.com/awslabs/amazon-sagemaker-examples/tree/master/sagemaker debugger/model_specific_realtime_analysis/cnn_class_activation_maps)
https://github . com/aw slabs/Amazon-sage maker-examples/tree/master/sage maker debugger/model _ specific _ real time _ analysis/CNN _ class _ activation _ maps
这一切是如何协同工作的
端到端 Amazon SageMaker 调试器工作流
让我们快速回顾一下 Amazon SageMaker 调试器如何与 Amazon SageMaker 的培训一起工作:
- 您使用 SageMaker Python SDK 和框架(TensorFlow、PyTorch 等)开始了一项 Amazon SageMaker 培训工作。)估计量。
- Amazon SageMaker 在指定数量的 CPU 或 GPU 实例上启动了一项培训工作。SageMaker 还将启动规则工作来监控培训工作。
- 使用调试钩子配置,Amazon SageMaker 将把权重、偏差和其他张量保存到指定的 S3 位置。
- 当挂钩数据可用时,嵌线作业开始运行指定的嵌线逻辑(过度拟合、渐层消失等)。)在他们身上。
- 当规则状态发生变化时,会生成一个 CloudWatch 事件,您可以指定一个 CouldWatch 规则来采取诸如停止训练或向您发送文本消息之类的操作。这里是一个当规则被触发时使用 AWS Lambda 停止训练的例子。
- 要对调试数据执行实时或离线分析,您可以使用
smdebug
库通过提供调试数据位置来创建一个试验对象。trail 对象可用于查询张量,您可以绘制它们来分析结果
摘要
调试很难,调试机器学习更难。在这篇文章中,我讨论了如何使用 Amazon SageMaker 调试器来减轻一些机器学习调试的痛苦。这里有 3 种方法可以将 Amazon SageMaker 调试器用于您的机器学习工作流:
- 在 Amazon SageMaker 上运行培训作业时,您可以将它作为一个完全托管的服务来使用,无需对您的培训脚本进行任何更改。调试规则作业是自动计划和运行的,以检查问题。
- 你可以使用开源的
smdebug
库在你的笔记本电脑、台式机或 Amazon EC2 实例上进行本地调试,通过检测你的代码来添加钩子和运行规则。 - 通过使用 Amazon SageMaker 进行训练,并在本地使用
smdebug
来运行规则和分析调试张量,您可以在混合设置中使用这两者
因为它非常灵活,还允许您使用自定义规则扩展其功能,并使用正则表达式查询自定义张量。这篇博文中讨论的所有例子,以及一些额外的例子都可以在这里找到:
https://github . com/shashankprasanna/sagemaker-debugger-examples
对于亚马逊 SageMaker 调试器以及亚马逊 SageMaker 工作室演示的视频演练,请查看我在 NVIDIA GTC 2020 上的演讲:
GTC 2020:用亚马逊 SageMaker 调试器提高 ML 训练性能
如果你对这篇文章有疑问,对如何改进它有建议或者对新帖子有想法,请在 twitter ( @shshnkp ), LinkedIn 联系我或者在下面留下评论。尽情享受吧!
如何决定学习速度
原文:https://towardsdatascience.com/how-to-decide-on-learning-rate-6b6996510c98?source=collection_archive---------9-----------------------
使用 PyTorch Lightning 为您的神经网络找到好的 LR
用 PyTorch Lightning 为你的神经网络寻找 LR(图片由作者提供)
在机器学习算法中使用的所有超参数中,学习率可能是你最先了解的一个参数。很有可能这也是你开始玩的第一个。通过一点超参数优化,有机会找到最佳值,但这需要大量的实验。那么,为什么不让您的工具来做这件事(更快)?
了解学习速度
对什么是学习率的最简短的解释是,它控制着你的网络(或任何算法)学习的速度。如果你还记得监督学习是如何工作的,你应该熟悉神经网络的概念,它根据监督人的反应来适应问题,例如:
- 错误类别——对于分类任务,
- 输出值过低/过高 —用于回归问题。
由于这一点,它可以迭代地给出越来越准确的答案。每当它收到来自主管的反馈时,它就会知道正确的答案应该是什么。而学习率控制了响应于最近的错误(反馈)而改变模型感知的程度。
好的学习率,差的学习率
如果存在我们所寻求的“好的学习率”,“坏的学习”是否也存在?这意味着什么?让我坚持监督学习的概念,讨论一个微不足道的例子:
- 我们在玩“猜数字”游戏,
- 每猜错一次,你都会得到一个回应:【太低】或者【太高】。
虽然这不是一个真正的神经网络的例子,让我们想象一下如何玩这个游戏,让我们假设这次不是纯粹的随机猜测。
每次你得到反馈时,你是愿意向正确答案迈出一小步还是一大步?虽然这个例子不是真正关于神经网络或机器学习,但这本质上是学习率如何工作的。
现在,想象一下,只迈出很小的一步,每一步都让你更接近正确的数字。这能行吗?当然了。然而,这真的需要一些时间,直到你到达那里。这是小学习率的情况。在机器学习的背景下,LR 太小的模型学习速度会很慢,并且需要更多的迭代来解决问题。有时你可能已经决定在训练结束前停止训练(或者玩猜数字游戏)。
你也可以选择一个太大的值。然后呢?例如,它可能会导致神经网络过多地(并且过于频繁地)改变它的想法。每一个新的样本都会对你的网络信仰产生巨大的影响。这样的训练会高度不稳定。它不再是一个学习缓慢的人,但它可能更糟糕:你的模型可能最终没有学到任何有用的东西。
学习率范围测试
Leslie N. Smith 在 2015 年撰写的论文 《训练神经网络的循环学习率》 引入了一个循环学习率的概念——在训练过程中轮流增加和减少。然而,论文中提到了一件重要的事情,即所谓的“LR 范围测试”(第 3.3 节)。
整个事情相对简单:我们运行一个短的(几个时期)训练会话,其中在两个边界值 min_lr
和max_lr
之间学习率增加(线性)。在开始时,学习率小,网络将开始慢慢收敛,导致损失值越来越低。在某些时候,学习率会变得太大,导致网络发散。
图一。lr_find 方法建议的学习率(图片由作者提供)
如果您绘制损失值与测试学习率的关系图(图 1。),你通常会在最陡下降损失曲线中间的某个地方寻找学习的最佳初始值——这仍然可以让你使用学习速率调度器减少一点 LR。在图 1 中。当损耗在 LR 0.001 和 0.1 之间开始显著下降时,红点表示 PyTorch Lightning 框架选择的最佳值。
在 PyTorch 闪电中寻找 LR
最近 PyTorch Lightning 成为我短期机器学习项目的首选工具。几个月前我第一次使用它,从那以后我一直在使用它。除了所有很酷的东西,它还提供了学习率查找器类,帮助我们找到一个好的学习率。
使用 LR Finder 无非是训练器类中的 auto_lr_find 参数:
现在,当你调用trainer.fit
方法时,它在下面执行学习率范围测试,找到一个好的初始学习率,然后直接训练(拟合)你的模型。因此,基本上这一切都是在fit
通话中自动发生的,你完全不用担心。
如文档中所述,有一种替代方法允许您手动使用 LR Finder 并检查其结果。这一次你必须创建一个默认值为auto_lr_find
(False)的Trainer
对象,并手动调用lr_find
方法:
仅此而已。这种方法的主要优点是,您可以更仔细地查看显示选择了哪个值的图(参见图 1。).
例如:时尚 MNIST 的 LR 搜索器
我决定在时尚 MNIST 数据集上训练一个相当简单的网络架构。我运行了四个独立的实验,它们的不同之处仅在于初始学习率值。其中三个是亲手挑选的(1e-5、1e-4、1e-1),最后一个是 Learning Rate Finder 建议的。整个实现和其他参数我就不描述了(自己看这里)。让我给你看看我的发现。
大概用了 12 秒(!)来找到最佳的初始学习率,对于我的网络和正在解决的问题,结果是 0.0363。看着 loss versusLR 图(完全是图 1 中的图),我很惊讶,因为建议的点并不完全是“最陡下坡的中途”(如论文中所述)。然而,我不知道这是好是坏,所以开始训练模型。
为了记录和可视化,我使用 TensorBoard 来记录训练和验证步骤中的损失和准确性。下面您可以看到四个实验中每个实验的指标历史。
图二。培训和验证。对于 4 个实验(图片由作者提供)
闪电(浅蓝色)建议的学习率似乎在训练和验证阶段都优于其他值。最后,它在验证集上达到 88,85%的准确率,这是所有实验的最高分(图 2 )。不仅如此,损失函数值显然是“find_lr”实验的最佳值。在最后一个验证步骤中,损失达到 0.3091,这是与图 3 中的其他曲线相比的最低值。
图三。4 个实验的训练和验证损失(图片由作者提供)
结论
在这个短暂的实验中,学习率查找器的表现超过了我亲手挑选的学习率。当然,有可能我会选择 0.0363 作为我最初的猜测,但是LR Finder 的整个要点是最小化所有的猜测(除非你是一个幸运的人)。
我认为使用这个功能是有用的,正如莱斯利·n·史密斯所写的:
每当一个人开始一个新的架构或数据集,一个单一的 LR 范围测试提供了良好的 LR 值和良好的范围。那么应该比较具有固定 LR 的运行和具有该范围的 CLR。无论哪一次获胜,都可以放心地用于余下的实验。
如果你不想使用不同的值来执行超参数搜索,这可能需要很长时间,你有两个选择:随机选择初始值(这可能会让你的性能和收敛性非常差,但如果你是一个幸运的人,可能会工作得很好)或使用你选择的机器学习框架中包含的学习率查找器。
你会选哪一个?
如何决定学习什么数据技能
原文:https://towardsdatascience.com/how-to-decide-what-data-skills-to-learn-e456be194137?source=collection_archive---------4-----------------------
获得就业市场上最有价值的技能
如果你用谷歌搜索“如何学习”,你可能会找到至少一门在线课程、youtube 教程、书籍或文章很好地涵盖了它。许多资源甚至是免费的。当决定在哪里学习一项技能时,有许多观点。持有这些观点的人没有尝试过每一个教育产品(甚至可能试图向你推销某些东西),所以很难说什么是最好的资源。说到挑选资源,我没有什么建议,除了到 不喜欢就不要坚持。几乎总是有更好的资源可供选择。这里真正的问题是。你打算在谷歌搜索中加入什么技能?
不要按照工作描述去做
好吧,这听起来违背直觉。如果你不知道求职申请上有什么,你将如何吸引雇主?我有两个理由认为求职申请不是一个好的晴雨表。首先,要求的顶级技能包括像 Excel 和 Tableau 这样的东西,对我来说,以这些为主要要求的工作不是真正的数据科学工作。当然,您可能偶尔会将他们用作数据科学家,但这更多是数据分析师、商业智能人员或商业分析师的工作。从本质上来说,各公司对数据科学家和数据分析师的定义并不相同,因此求职应用程序并不是一个有效的衡量标准。
我不使用职位描述的主要原因是,它们通常是由人力资源和/或招聘人员编写的,而不是由你的未来经理编写的。我见过要求 5 年 PyTorch 经验的工作,考虑到它只有 3 年左右的历史,这种经验很难找到。你真的应该排队向不从事数据科学工作的人学习什么吗?我不这么认为。知道什么是有价值的技能的人是其他数据科学家。此外,你很有可能会在某个时候接受一位资深数据科学家的面试。因为他们可能是最难通过的过滤器,你应该优化给数据科学家留下深刻印象,而不是招聘人员。
不要只是做其他数据科学家做的事情
但是我刚刚告诉你要这么做!我建议这些条件。你首先需要拥有每个人都拥有的核心技能。这实际上是指 Python,包括 matplotlib、pandas、sklearn 和 numpy。但是如果你正在读这篇文章,你可能已经知道了。从那以后,我会用下面的图来帮助决定接下来要学什么。该图的数据来自数据科学家的 KDnuggets 调查;询问他们拥有什么技能,想要什么。我在这里提出的观点是,你不能只是问数据科学家他们使用什么工具,然后也学习这些工具。你必须将自己与其他数据科学家区分开来。要做到这一点,你必须学习他们中很少人拥有的技能。更好的是从少数人拥有的技能中挑出最想要的技能。本质上,你需要在这张图的左上方获得技能。
KD 掘金投票
我将图的左上方分为 4 个部分,大致排列如下:
- 深度学习——学习理论,然后如何在 TensorFlow 或 PyTorch 中实现(选哪个不是超级重要)
- NLP——排名比下面两个高,因为工具时好时坏,但是无论你如何实现它,NLP 知识都是有用的
- 大数据工具—Hadoop 是利用大数据的一项很好的技能,但大数据绝不仅限于 Hadoop。
- 火花
同样,我不知道学习这些技能的最佳方法,我认为其他人也不知道(希望有人有一个令人兴奋的数据集,可以证明我是对的还是错的)。尽管我确实相信这是选择学什么的最佳框架。了解其他数据科学家不知道但希望他们知道的东西,在就业市场上是一个强大的优势。
如何在 Python 中定义自定义异常类
原文:https://towardsdatascience.com/how-to-define-custom-exception-classes-in-python-bfa346629bca?source=collection_archive---------4-----------------------
编写自己的错误类
图片由西格蒙德通过 Unsplash 提供
创建自定义错误类
在 Python 中,我们有能力创建自己的异常类。自定义异常类的构造可以丰富我们的类设计。自定义错误类可以记录错误,检查对象。异常类做什么由我们决定,尽管自定义类除了显示一条消息之外通常不会做更多的事情。
当然,类型的错误本身就很重要,我们经常创建自己的错误类型来指示 Python 通常不涵盖的特定情况。这样,遇到错误的类的用户将确切地知道发生了什么。
这篇教程由两部分组成。首先,将孤立地定义一个异常类。第二部分将展示我们如何将定制异常类集成到我们的 Python 程序中,并演示这如何增强我们设计的类的可用性。
自定义异常类 MyCustomError
引发异常时需要 init()和 str()方法
当我们引发一个异常时,我们实际上是在创建一个异常实例并同时打印它。让我们分析一下下面显示的定制异常类。
在上面的 MyCustomError 类中,有两个神奇的方法 init 和 str 会在异常处理过程中自动调用。Init 是创建实例时调用的方法,str 是打印实例时调用的神奇方法。因此,当出现异常时,它们通常会被连续调用。Python 中的 raise 语句将程序置于错误状态。
init 方法的参数列表中有个参数。args 是在函数和方法中使用的特殊模式匹配模式。它允许传递多个参数,并将传递的参数存储为一个元组,但也不允许传递任何参数。
在我们的例子中,我们说,如果有任何参数被传递给 MyCustomError 构造函数,我们将获取传递的第一个参数,并将其赋给对象 message 中的一个属性。如果没有传递任何参数,则不会将任何参数分配给消息属性。
在第一个示例中,在没有任何参数的情况下引发了 MyCustomError,因此不会将任何参数设置为对象中的 message 属性。str 方法将被调用,并将打印消息“MyCustomError 消息已引发”。
引发 MyCustomError 时,括号中没有任何参数。换句话说,它看起来不像一个标准的对象构造。这只是 Python 在您引发异常时添加的语法帮助
在第二个示例中,使用字符串参数“我们有问题”传递 MyCustomError。这被设置为对象中的消息属性,并在引发异常时打印在错误信息中。
MyCustomError 异常类的代码可以在这里找到。
CustomIntFloatDic 类
创建一个只能存储整数和浮点数作为其值的自定义字典
现在让我们继续,演示自定义错误类是如何轻松有效地集成到我们自己的程序中的。首先,我将创建一个略显做作的示例。在这个虚构的例子中,我将创建一个自定义字典,它只能接受整数或浮点数作为它的值。
如果用户试图将任何其他数据类型设置为该字典中的值,将会引发异常。引发的异常将有效地通知用户如何使用字典。在我们的例子中,一条消息明确通知用户在这个自定义字典中只有整数和浮点数可以被设置为值。
我们必须注意,当我们创建自定义字典时,有两个地方可以添加值。第一种是在 init 方法中构造对象时(对象可能已经被赋予了键和值),另一种是在字典中设置键和值时。在这两个地方,我们都需要编写代码来确保值只能是 int 或 float 类型。
首先,我定义了一个名为 CustomIntFloatDict 的类,它继承自内置的 Dict 类。dict 在类名 CustomIntFloatDict 后面括号中的参数列表中传递。
如果创建了 CustomIntFloatDict 的实例,并且没有参数传递给键和值参数,则它们将被设置为 None。if 表达式的计算结果是,如果键为 None 或值为 None,将对对象调用 get_dict()方法,该方法将返回对象的 empty_dict 属性,该属性指向一个空列表。请记住,类属性可用于该类的所有实例。
这个类的目的是让用户传递一个列表或元组,其中包含键和值。如果用户为键和值输入一个列表或元组,这两个 iterables 将使用 python zip 函数压缩在一起。指向 zip 对象的压缩变量可以被迭代,元组可以被解包。当我们遍历元组时,我检查 val 是 int 还是 float 类的实例。如果不是,我将引发一个自定义的 IntFloatValueError,并将 val 作为参数传递。
IntFloatValueError 异常类
当我们引发一个 IntFloatValueError 异常时,我们正在创建一个 IntFloatValueError 类的实例并同时打印它。这意味着 init 和 str 魔法方法将被调用。
导致引发异常的值在 IntFloatValueError 类中被设置为名为 value 的属性。当调用 str magic 方法时,会出现一条错误消息,通知用户传递给 CustomIntFloatDict 的 init 的值无效。用户现在将知道他们必须做什么来纠正这个错误。
IntFloatValueError 和 KeyValueConstructError 异常类
如果没有引发异常,也就是说,如果压缩对象中的每个 val 都是 int 或 float 类型,它们将在字典中使用 setitem()进行设置,dict 父类方法为我们完成这项工作,如下所示。
KeyValueConstructError 异常类
如果用户输入的类型不是带有键和值的列表或元组,会发生什么?
同样,这个例子有些做作,但是将展示如何使用定制的异常类。
如果用户没有将键和值指定为列表或元组,将引发 KeyValueConstructError 异常。该异常类的目的是通知用户,为了将键和值获取到 CustomIntFloatDict 对象中,必须为 CustomIntFloatDict 类中的 init 构造函数指定一个列表或元组。
在所示的示例中,一个集合作为第二个参数传递给了 init constrictor,这导致了自定义 KeyValueConstructError 异常的引发。有用的是,显示的错误消息通知用户键和值需要作为列表或元组传递。
当引发异常时,将再次创建 keyvalueconstructor 的实例,并将键和值作为参数传递给 keyvalueconstructor 构造函数。这些属性在 KeyValueConstructError 中被设置为键和值属性,并在 str 方法中用于在打印对象时产生有用的错误信息。
此外,我甚至包括了添加到 init 构造函数中的对象的数据类型,以增强清晰度。
在 CustomIntFloatDict 中设置键和值
CustomIntFloatDict 继承自 Dict。这意味着除了我们选择有选择地修改其行为的地方之外,它的行为将与字典完全一样。
setitem 是我们在字典中设置键和值时调用的神奇方法。在我们的 setitem 实现中,我们验证该值是 int 还是 float 类型,然后才能在字典中设置它。如果不是,我们可以再次使用 IntFloatValueError 异常类。在这里,我们可以看到,当我们试图将字符串' bad_value '设置为字典 test_4 中的一个值时,会引发一个异常。
本教程的代码在下面的 Github gist 中显示,可以在这里获得。
总结:
自定义异常增强了类的可用性。异常类应该有 init 和 str 魔法方法,在异常处理过程中会自动调用这些方法。我们希望我们的自定义错误类做什么完全取决于我们自己。显示的方法包括检查对象和打印有用的错误消息。在这两种情况下,异常类使得该类的用户在错误发生时更容易处理错误!
如何定义你在数据科学方面的学习路径
原文:https://towardsdatascience.com/how-to-define-your-learning-path-in-data-science-24e722895188?source=collection_archive---------25-----------------------
决定下一步学什么很难。
莎伦·麦卡琴在 Unsplash 上的照片
数据科学是一个蓬勃发展的领域,有越来越多的专业和角色需要填补。随着热潮的兴起,有更多的课程、书籍和文章旨在帮助数据科学家学习他们需要的技能,以便更好地工作(或找到工作)。要学的东西太多了。那么,决定你下一步该去哪里的最佳方式是什么呢?
基础
从基础开始写似乎是一件愚蠢的事情。不过,我刚刚开始进入数据科学的旅程。我知道深度学习看起来超级酷,超级性感。但这不是开始的地方。在你尝试学习任何疯狂的东西之前,确保你对基础数学、统计学和计算机编程有坚实的理解。
一旦你对构成我们称之为数据科学的基本概念有了坚实的理解,就有很多不同的选择来决定下一步要学什么。没有完美的方法,你可能选择的每条学习道路都有利弊。
选择 1:把你的学习集中在新的东西上
组织你的学习的一个方法是专注于跟上你所选择领域的最新发展。你可以通过阅读和学习如何实现新的研究论文来做到这一点。对许多人来说,这是最难学习的方法之一,因为它需要你在足够深的层次上阅读和理解研究,以便能够将其翻译成代码。
优点:
专注于最新研究的好处是,你总是知道许多难题的最佳解决方案。它让你有机会从事有趣的项目,并创造出其他人很少(如果有的话)在创造的东西。如果你感兴趣的话,它还会让你做自己的研究。
缺点:
首先,很难阅读研究论文。梳理一篇研究论文并理解研究人员所做的一切需要时间。也很难准确理解这项研究对你正在处理的这类问题有多大用处。我发现许多人不喜欢用这种方式学习,如果你不喜欢学习,你就不会花时间去学。
选择 2:专攻感兴趣的领域
如果你对数据科学的某个特定领域感兴趣,比如自然语言处理、计算机视觉、可解释的机器学习或计算高效的深度学习,那么你就可以一头扎进那个领域。成为你感兴趣的某个领域的专家是一种非常有效的学习方式,它让你很容易知道哪些东西值得学习。
优点:
这种学习方式的好处是你只学习你真正感兴趣的东西。如果你把你的研究集中在一个特定的领域,也更容易成为该领域的专家,让你成为一笔宝贵的财富。
缺点:
成为专家的好处就是成为专家的坏处。把你所有的学习都集中在一个领域会让你处于一个缺乏灵活性的位置。您可能会错过一些更通用的方法可以提供给您的其他有价值的技能。
选项 3:学习一些东西来完成一项工作或项目
专注于学习对你当前工作最有用的东西是决定学习什么的另一个好方法。如果你正在做一个时间序列建模很有价值的项目,你可以开始学习。一旦你完成了这个项目,你就会发现什么主题对你的下一个项目最有帮助。
优点:
这种学习方法帮助你对你所学的东西有一个目标。它给你的学习时间明确的方向和动力。最重要的是,你所学的大部分东西都有一个清晰、直接的回报。
缺点:
我发现在不同的主题之间跳跃往往会在知识上留下一些空白。例如,学习如何在运行中进行图像分类可能会导致您无法理解卷积是如何工作的。有时这些漏洞最终变得微不足道,但有时它们是重要的漏洞,你必须回头去填补。
选项 4:遵循课程
这可以是任何东西,从大学学位,到 MOOC,到一本书。任何一种安排学习内容并提供学习材料的结构化程序。
优点:
这样做的一个巨大好处是它的便利性。你被告知知道什么是重要的,并提供你需要的一切来精通这些技能。大多数情况下,我们会为您提供示例和练习,这样您也可以获得实践经验。
缺点:
不幸的是,并不是所有的课程都是平等的。如果你选择走这条路,你需要考虑你学习课程的地方是否有很好的声誉,是否会提供好的内容。这种方法的另一个缺点是它通常是最昂贵的选择。你可能还会发现,你学到的技能和技术并不总是像在课堂上那样容易应用于现实世界。
选项 5:增加你所提供的价值
这种决定学什么的方式实际上可能适合其他任何一种方式。从职业的角度来看,你正在学习那些能让你变得最有价值的东西。例如,如果你的公司(或你希望为之工作的公司)重视全栈数据科学家,统计学家可能会专注于开发运营方面的学习。
优点:
带着让自己变得更有价值的目的去学习,很可能会带来职业生涯中最大的飞跃。它也可以为新的事物打开许多不同的大门。
缺点:
这有时会导致你去研究你不感兴趣的话题。这使得学习和掌握新材料变得非常困难,并且不能激发继续学习。
结论
在您涵盖了基础知识之后,剩下的选项并不相互排斥。事实上,我认为最好的学习方法是将所有这些东西结合起来。归根结底,最好的学习方法是找到一种你喜欢的学习方法,并坚持下去。
如何在不到 5 分钟的时间内将机器学习模型部署到云中
原文:https://towardsdatascience.com/how-to-deploy-a-machine-learning-model-to-the-cloud-in-less-than-5-minutes-1811fb6aef3e?source=collection_archive---------22-----------------------
使用 Azure 机器学习和 Python 为训练好的 ML 模型创建一个 web 服务
西蒙·艾布拉姆斯在 Unsplash 上拍摄的照片
想象以下情况:
你是一名数据科学家,被要求创建一个预测模型。您执行数据探索和清理,选择一个模型,调整它,训练它。经过几次迭代和修复后,您运行了一些性能指标,结果非常好。您认为您在这里的工作已经完成了,但是接下来您被要求将您的模型投入生产。该模型在您的笔记本电脑上运行良好,但他们希望您创建一个用户可以消费的模型,对吗?
数据科学家有时面临的一个问题是,他们的工作似乎与其他人的工作脱节。他们独自工作,修补他们的模型,并产生一些可能与手头问题相关的结果。如果结果确实有用,涉众将希望最好的模型投入生产。然而,在这一点上,模型通常不适合生产。通常,数据、ML 和/或软件工程师团队必须将它们转换成可用的模型,以便进行部署,并可能与一些现有的应用程序或管道集成。
幸运的是,生产一个机器学习模型正变得越来越容易,越来越快,越来越容易被所有人接受。主要的云提供商提供开发机器学习解决方案的专用服务,如微软的 Azure 机器学习,亚马逊的 AWS SageMaker ,或谷歌云 AI 平台。这些服务通过实施面向机器学习的 DevOps(也称为 MLOps)在自动化管道中构建、训练和部署模型,实现了端到端机器学习生命周期的管理。它们都支持流行的框架和编程语言(如 Python、R、scikit-learn、XGBoost、Tensorflow 或 PyTorch),无论人们习惯使用哪种工具,都可以平稳地从本地工作过渡到本地工作。
如果数据科学家不熟悉工程任务,前面提到的数据科学和工程任务之间的脱节可能会有问题。但是随着这些云服务的易用性,这种情况不会再发生了。即使具备云基础设施的一些基础知识和使用这些工具的初步经验,数据科学家也已经能够更好地理解工程师的工作和决策,促进双方的沟通和合作,从而快速跟踪机器学习解决方案的生产。
放弃
对于本教程,我们将使用微软 Azure 及其机器学习服务,以及用于 Python 的 Azure ML SDK。
注意,本文的目的是展示 Azure 机器学习服务的易用性和速度,特别是对于模型部署。因此,在 Azure 中快速部署可以被其他应用程序和用户使用的工作模型所需的代码和解释被减少到最低限度。
然而,要为现实世界的应用程序生产机器学习模型,在部署期间需要考虑几个额外的方面。主要是,部署任务预计将包含在 CI/CD 管道中,但在 Azure 机器学习服务本身中还有进一步的考虑要做。一些例子是在 REST 端点上执行身份验证,或者如果我们希望服务是可伸缩的,则在计算集群而不是单个容器中部署模型。
此外,在信息支持,我们提倡在整个开发生命周期中使用 Azure 机器学习和类似的 MLOps 框架,而不仅仅是在部署期间。在本文中,我决定将重点放在后者上,假设在模型的构建和训练过程中遵循了良好的 MLOps 实践——希望这些可以在以后的文章中涉及到。
我真的可以在不到 5 分钟的时间内部署我的模型吗?
是的,真的。虽然有些操作可能需要几分钟的等待时间(即创建 Azure 机器学习工作区和 web 服务部署),但需要完成的实际工作可以在几分钟内完成。
为了证明这一点,我制作了下面的视频,其中涵盖了执行所有步骤的最快方法(从上传已经训练好的模型到使用已部署的 web 服务):
如果您想更深入地研究这些步骤,或者如果您更喜欢学习如何使用纯代码方法来执行每个步骤,请继续阅读。
我如何部署我的模型?
出发点
正如我前面提到的,我们假设我们已经成功地完成了部署之前的所有步骤:我们已经获得、探索和清理了数据;选择一个模型,并训练它,达到足够好的性能,开始在生产中使用这个模型。
为了便于演示,我们将以一个非常简单的解决方案开始本教程,该解决方案基于 scikit-learn 中直接提供的玩具数据集: 威斯康星州乳腺癌诊断数据库 。我们将建立一个决策树来尝试预测乳腺肿瘤是良性还是恶性的几率。
该数据集包含从其细胞图像中提取的乳房肿块的几个特征的测量值。我们将利用前 4 个可用特征,它们大致对应于乳房肿块的半径、纹理、周长和面积的平均值。
请再次注意,该模型用于演示目的,因此我们不关注算法选择或实际性能。我们的目标是获得任何经过训练的模型,以便在 Azure 机器学习中部署和测试它。
保存模型
假设我们已经在测试分割上运行了一些评估指标,我们对模型的性能感到满意。我们准备让其他用户或外部应用程序可以访问它。但是为了将我们的模型加载到云中,我们首先需要存储它。
经过训练的模型可以通过序列化来存储——也就是 Python 中通常所说的“酸洗”。pickle 一个模型意味着将它转换成一个二进制文件,这个文件可以被存储、复制、移动、传输和最终加载,以便检索原始模型。
这可以通过使用一个名为 pickle 的库来完成。但是,对于用 Python 序列化机器学习模型,经常推荐一个替代库: joblib 。该库支持有效存储和加载可能包含大型数据结构的 Python 对象,这可以从一些机器学习模型中预期。
继续我们之前的脚本,我们可以像这样轻松地序列化和存储我们训练好的模型:
对于文件名,。joblib 或者。bin 是支持的扩展的例子。也可以使用其他扩展(例如。z)用于进一步压缩,如果需要的话。
强烈建议记下用于创建存储模型的 Python 版本和依赖项的版本,因为可能需要它们来反序列化和使用它,同时确保完全兼容。在这种特定情况下,我们确实需要 Python 版本来匹配 Azure 机器学习当前支持的任何 Python 版本,以及在注册我们的模型时指示 scikit-learn 的版本。
安装 Azure ML SDK
可以只使用 Azure 机器学习门户 GUI 在 Azure 机器学习中部署一个已经训练好的模型,而不需要一行额外的代码。然而,在单个容器中部署 web 端点(这是部署模型的最快方式)只能通过代码或命令行来实现。
这就是为什么,在本教程中,我们将使用 Python 的 Azure ML SDK。除了通过 GUI(如果适用)解释程序之外,还将提供用于执行部署的每个步骤的代码片段。
为了安装带有默认包的 Azure ML SDK,我们在本地终端中运行以下命令:
pip install --upgrade azureml-sdk
注意,Azure Machine Learning 在用 Azure ML SDK 开发时使用了交互式 UI 认证。我们第一次使用带有订阅 ID 的 SDK 时,Azure 会提示我们登录我们的订阅帐户。
在 Azure 中创建工作区
我们在仓库里有一个功能模型,太好了!现在我们实际上可以开始钻研 Azure 机器学习了。
假设我们在 Azure 中已经有了一个帐户和一个有效的订阅,我们导航到 Azure 门户并搜索服务>机器学习。
Azure 门户中的机器学习服务搜索
我们为我们的新工作区命名,并选择我们想要使用的订阅。因为我们假设从头开始一个项目,所以我们将创建一个新的资源组。我们可以选择基础版工作空间版,因为它提供了我们教程所需的所有功能。
在 Azure 门户中创建机器学习工作区
也可以使用 Azure ML SDK 直接创建工作空间。使用来自 Workspace 类的 create() 方法,我们可以提供与通过 Azure 门户提供的参数相同的参数:
一旦创建了资源组和工作空间,我们就可以通过 Azure Machine Learning dashboard 在ml.azure.com访问后者。
现在,我们需要获得包含工作区和订阅细节的 JSON 文件。在 Azure ML 门户中,在右上角的导航栏上,我们单击更改订阅>下载配置文件,并将文件放在我们的项目目录中。这个配置文件也可以通过在 Azure 门户中导航到新创建的工作区并在概览页面中点击下载配置文件来下载。一旦这个文件位于我们的项目文件夹中,我们就可以直接从 Python IDE 中部署我们的模型。
可下载的 JSON 配置文件的位置
注册模型
要上传并注册我们已经训练好的模型,我们进入左侧菜单的模型部分,点击注册模型。我们命名我们的模型,指出我们用来训练它的框架(在这种情况下,scikit-learn),并可选地为附加元数据编写描述。我们浏览我们的机器,选择并上传我们的序列化模型文件,然后我们点击注册。
Azure ML 门户中的模型注册
使用 Python 脚本和 Azure ML SDK 也可以快速完成整个过程。我们首先需要使用 from_config() 方法连接到工作区,这将在项目的根目录中搜索我们的配置文件。然后,我们能够通过使用模型类来注册我们训练好的模型。我们可以定义与之前在 GUI 中指示的参数相同的参数:
运行这个脚本后,我们可以返回到 Azure 机器学习门户,并验证我们的模型已经在 Models 部分下注册。
Azure ML 门户中注册模型的列表
部署模型
一旦我们的模型被注册,我们就可以按原样部署它了。这意味着我们部署的 web 服务将接受与我们训练的模型相同的输入数据(在这种情况下,四个浮点数的数组表示我们选择的四个特征),并将输出预测(在这里,1 表示良性,0 表示恶性)。
为此,我们在工作区中定位我们注册的模型,并利用来自 Model 类的 deploy() 方法,为我们的 web 服务提供一个名称和指向模型的指针:
通过这样做,我们的模型将被部署在 ACI (Azure 容器实例)中。Azure 机器学习中的 ACI 旨在用于开发和测试目的,因为它们只支持 CPU 上的低规模工作负载。然而,他们可以利用高达 16GB 的 RAM 和 4 个 CPU,这可能足以进行概念验证,甚至足以生产原型模型,这取决于应用程序。
就是这样!我们的 web 服务现在将出现在 Azure 机器学习门户的端点部分下。在那里,我们可以获得其 REST 端点的 URI,并向 API 发送一些测试 POST 请求,以验证部署是否成功。该 web 服务期望的 JSON 格式的输入如下:
{
"data" : [ <feature-value1>, <feature-value2>, <feature-value3>, <feature-value4> ],
"method": "predict"
}
注意“数据键的值也可以是包含几个样本的 2D 数组,然后 web 服务将返回所有相应的预测。
使用方法参数,如果我们希望 web 服务输出预测的标签(0 或 1 ),我们可以指定值 predict ,或者如果我们希望获得每个标签的精确概率输出,我们可以指定值 predict_proba 。
当发送来自分割评估数据集的两个样本时(例如,通过 Postman ,我们看到我们获得了预期的预测(第一个样本对应于良性肿瘤,第二个对应于恶性肿瘤):
示例请求通过邮递员发送到我们的模型,部署为 web 服务
因此,我们部署的模型可以被外部应用程序使用。作为如何使用 Python 来使用它的示例,我们发送一个以前的数据示例:
使用自定义条目脚本的替代部署
我们已经看到按原样部署我们的模型是多么容易。然而,根据我们的模型或我们想要构建的应用程序的种类,它可能会受到限制。
当我们使用上面的脚本部署我们的模型时,我们实际上是在一个计算实例中部署它,该实例具有预定义的配置(单个 CPU 内核和 0.5 GB RAM 的 10%使用限制)和具有默认包和框架的环境(确切地说包括 scikit-learn)。
但是如果这个计算目标设置不能为我们的模型提供足够的计算能力呢?或者,如果我们使用默认环境中不包含的某些库,该怎么办?此外,我们可能希望更灵活地定义 web 服务如何与外部用户交互:例如,我们可能需要在将输入数据提供给模型之前对其执行额外的操作,比如规范化输入特性或以某种特定的方式处理缺失值。
我们可以通过两个额外的步骤来完成所有这些:指定一个推理配置(通过为我们的 web 服务和定制环境提供一个入口脚本)和一个部署配置。
参赛脚本(也称为评分脚本)必须包含以下两个功能:
- 【init():它在托管我们的 web 服务的 Docker 容器启动时运行一次,通常用于将我们注册的模型作为全局对象加载
- run(input _ data):每次 web 服务收到请求时运行,负责接收输入数据,发送给模型,返回模型的响应
我们模型的简单评分脚本示例如下:
我们的推理配置需要的另一个参数是执行环境。我们可以创建一个环境对象,给它一个名称,并指出我们想要安装的 Conda 或 pip 依赖项。请注意, azureml-defaults 包始终是模型作为 web 服务托管所必需的。
我们现在可以创建部署模型所需的推理配置:
最后,我们定义部署配置。例如,我们可以创建一个具有一个 CPU 内核和 2GB RAM 的计算实例:
我们将两个配置对象都提供给在默认部署期间已经使用的 deploy() 方法:
我们现在可以运行它来部署新的 web 服务,只需提供输入数据就可以向其发送请求:
示例请求通过邮递员发送到我们的客户 web 服务
搞定了。接下来呢?
我们的模型已经成功部署在 Azure 中。正如本文开头提到的,我的目标是展示我们使用 Azure 机器学习服务部署模型有多快多容易。然而,如果我们想在现实世界的应用中生产我们的模型,还有很多工作要做。
为了继续深入研究 Azure Machine Learning 必须提供什么,查看来自微软的这个资源库,在那里他们提供了几个关于如何使用 Azure ML SDK 的 Python 笔记本,以及 Azure Machine Learning 的官方文档。
此外,如果你对教程的某些步骤有任何疑问,或者如果你在执行代码时遇到任何问题,请随时在下面的评论中问我,或者通过 LinkedIn 问我。
如何用 5 个步骤在 Heroku 上部署机器学习 UI
原文:https://towardsdatascience.com/how-to-deploy-a-machine-learning-ui-on-heroku-in-5-steps-b8cd3c9208e6?source=collection_archive---------27-----------------------
Gradio 让你为你的机器学习模型建立一个 UI。Heroku 让你主持。以下是如何一起使用它们。
在本教程中,我将一步一步地向您展示如何在 Heroku 上创建和部署您的机器学习模型和 UI。我将使用我为 Inception Net 模型创建的这个拖放图像界面作为一个例子:
您可以在:https://arcane-tundra-83748.herokuapp.com/试用 GUI(dyno 启动可能需要一分钟)
格拉迪欧的作品
我假设你已经对 Gradio 库(https://github.com/gradio-app/gradio)有所了解。如果没有,这个 MNIST 教程是一个开始的好地方。快速概述是:Gradio 是一个 Python 库,它允许您通过指定三件事情来围绕您的机器学习模型创建 ui:Python 函数、输入组件和输出组件。
第一步:创建你的 Gradio 应用
我们将从一个脚本开始,该脚本围绕先启模型创建一个拖放图像界面。创建一个全新的目录,并将下面的代码复制粘贴到一个 python 文件中,我们称之为app.py
:
这个脚本中发生的事情是,我们正在使用 Tensorflow Keras 加载 Inception Net 图像分类器。由于这是一个图像分类模型,我们将使用Image
输入接口。我们将使用Label
输出接口输出一个标签字典和它们相应的置信度得分。(要部署您自己的模型,请用您自己的代码来替换它)。
第二步:编写你的 **requirements.txt**
文件
我们需要确保将所有需要的 Python 库指定为依赖项。所以在与**app.py**
相同的目录下创建一个**requirements.txt**
文件。对我来说,那就是:
让包版本在 Heroku 上工作可能有点棘手,但是上面的包和版本对我来说是有效的。重要提示: Heroku 将您的构建大小限制为 500 MB,考虑到 Tensorflow 包的大小,这很容易填满。我建议用 Tensorflow 2.0.0 库,比其他一些版本的库要小一些。
如果您想在本地测试脚本(您应该这样做!),从终端运行:pip install -r requirements.txt
安装依赖项,然后python app.py
启动 UI。此时,您应该看到您的界面正在localhost:7860
(或另一个端口)上运行,如果您在浏览器中导航到该端口,应该会显示您的 GUI!
此 URL 可在本地访问。我们如何与世界分享这些?Gradio 带有一个内置的share
参数,可以创建公共 URL,但这些 URL 会在一定时间后过期。为了创建永久的公共链接,我们将使用 Heroku!
Heroku 的作品
要在 Heroku 上部署您的 web 应用程序,您需要有一个 Heroku 帐户,拥有 Heroku CLI 也非常方便。因此,如果你还没有做的话,请继续创建一个 Heroku 帐户并下载 CLI 。
现在,开始部署!
第三步:创建一个 **setup.sh**
文件
为了在 Heroku 上正确部署我们的应用程序,我们需要确保它服务于正确的 URL 和端口。下面的命令可以做到这一点,所以把它们放在一个名为**setup.sh**
的文件中,这个文件和你的应用程序在同一个目录下。
这里发生的事情是,我们告诉 Gradio 在0.0.0.0
上提供 UI,特别是使用 Heroku dyno 让世界可见的端口。
第四步:创建一个
现在,我们要创建一个名为**Procfile**
的文件(就是它,这个文件没有扩展名!)它的工作是告诉 Heroku 运行什么命令来启动 Gradio 应用程序。只有两个命令:运行我们在上一步创建的 bash 脚本,然后启动我们的应用程序。所以我们的 Heroku **Procfile**
看起来是这样的:
web: source setup.sh && python app.py
如果你想知道为什么我们使用source
而不是sh
,那是因为我们需要在脚本执行完毕后保存环境变量。
第五步:部署!
此时,您的目录应该如下所示:
一个目录中只有 4 个文件——超级简单!
如果您还没有将这些文件添加到 git repo 中,请在您的终端中运行以下命令:
git init
git add -A
git commit -am "commit message here"
我们只需要把这个推到 Heroku dyno 上。首先,让我们通过运行以下命令为我们的应用程序分配一个 Heroku dyno:
heroku create
Heroku 会自动旋转并给你的应用程序分配一个随机的名字。现在,我们把我们的改变推给 Heroku:
git push heroku master
给它几分钟时间在你的 dyno 上安装所有的依赖项。这里可能会遇到依赖性问题,您可以通过阅读错误消息并安装每个库的正确版本来解决这个问题(参见我上面关于 Heroku 大小限制的注释)。如果您没有看到任何错误,那么您应该能够通过运行以下命令打开您的应用程序:
heroku ps:scale web=1
heroku open
最后一个命令将打开您的默认浏览器,并把您带到应用程序。您会注意到网址是自动生成的实例名加上 Heroku 域。
就是这样!您有一个可以与任何人分享的实时链接。是时候开始运行一些预测了:)
如何免费部署 Postgres 数据库
原文:https://towardsdatascience.com/how-to-deploy-a-postgres-database-for-free-95cf1d8387bf?source=collection_archive---------6-----------------------
凯文·Ku 在 Unsplash 上的图片
数据存储
使用流行的数据库管理系统获得实际经验
PostgreSQL 是世界上最流行的关系数据库管理系统之一,为一些最大的企业提供支持。如果你下载 Postgres,你可能会很恼火地发现你只能把它托管在你机器的 localhost 服务器上,除非你支付一笔经常性的费用把它托管在 AWS 或 Azure 这样的平台上。在本指南中,我将向您展示如何使用 Heroku 免费部署您的数据库,并使用 Python 向其写入数据。
先决条件:
安装最新版本的 Postgres ,安装 pgadmin4 ,安装 python3 ,pip3 安装 sqlalchemy 和 psycopg2
1:创建你的 Heroku 账户&创建你的第一个应用程序
部署我们免费 Postgres 数据库的第一步是在 Heroku 上创建一个免费账户。Heroku 是一个云平台,你可以在上面部署你的应用和数据库。创建您的帐户并登录后,您应该会看到类似以下内容的控制面板屏幕:
你的新帐户不会有我上面列出的任何应用程序。找到并点击“创建新应用”按钮,进入以下页面:
为尚未使用的应用程序选择一个名称并创建它。点击“创建应用程序”按钮后,您应该会看到以下页面:
你现在有了你的第一个 Heroku 应用程序,让我们添加一个数据库!
2:将 Postgres 数据库添加到您的应用程序中
从你的应用程序的 Heroku 页面点击“资源”标签,查看你的项目拥有的 Dynos 和附加组件的空列表。我们希望将 Heroku Postgres 附加组件附加到您的项目中,因此请单击下图右侧的紫色“查找更多附加组件”按钮:
进入 Heroku 附件页面后,在页面右上角的“搜索元素”栏中输入“Heroku Postgres ”:
你现在应该已经找到了 Heroku Postgres 的附件,如下图所示。从这里,点击右上角的紫色“安装 Heroku Postgres”按钮,这样我们就可以将其添加到您新创建的应用程序中。
在将 Heroku Postgres 附加组件附加到您的项目的最后一页,您可以选择要附加该附加组件的计划和项目。确保你选择了“业余爱好自由发展”计划,这样你就不用为任何事情付费了!之后,搜索您的项目名称,选择它,然后单击紫色的“Provision add-on”按钮。
让我们学习如何连接到您的新 Postgres 数据库!
3:在 pgadmin4 中连接到数据库
要连接到您的新数据库,请返回 Heroku 应用程序的“资源”页面。你应该看到附件“Heroku Postgres”。点击下图右下方的“Heroku Postgres”链接,进入数据库管理页面。
“数据库概览”页显示了有关数据库的高级信息。最初,您应该没有连接、行或表。数据大小从 7.9 兆字节开始,这说明了与您的数据库相关的程序文件,您永远不需要看到或担心。一旦您添加更多数据,该大小将会增加。在免费计划中,您的数据库中只允许有 20 个连接和 10,000 行数据——这对于个人项目和实验来说非常实用。
如果您转到“设置”选项卡,然后单击“查看凭据”按钮,您将能够看到用于连接到数据库的数据库凭据。不要分享这些信息!
注意:以上凭证均未激活
现在我们有了数据库凭证,可以连接到 pgadmin。打开您应该已经安装在计算机上的 pgadmin 应用程序,它应该在您的默认浏览器中打开一个窗口,如下所示:
在这里,您可以单击 pgadmin 仪表板上的“Add New Server”按钮,并在提示符下输入您的数据库凭据。您不需要角色或服务:
注意:以上凭证均不有效
一旦你正确地输入了所有的字段,你可以点击“保存”,应该会看到你的 Postgres 服务器如下所示。这是一个有许多数据库的共享服务器,您只能通过在列表中找到它来访问您的数据库:
您现在已经连接到 pgadmin 中的免费 Postgres 数据库了!
4:从数据库中写入和读取数据
在最后一步中,我们将编写 python 代码来创建一个表,并将数据添加到数据库中。我们将首先创建一个 config.py 文件来存储我们的数据库凭证。我们的数据库凭据应该存储在一个单独的文件中,这样我们就可以将该文件添加到我们的。gitignore 在 GitHub 上分享我们的代码,不用担心有人访问我们的数据库。
配置. py
**host** = ec2-34-200-42-57.compute-1.amazonaws.com
**port** = 5432
**database** = dfg5a7fake6perlms
**user** = fdpbgfakeggheshfbv
**password** = a7cb88511fakea656dd5bb175220caa9646defd4f79e62085486b
下面的脚本 create_table.py 与 config.py 位于同一个文件夹中。首先,我们导入所有的配置变量和 sqlalchemy。然后,我们创建一个引擎,它接受所有的配置变量,并使用“ engine.connect() ”将它们连接到数据库。一旦我们连接到数据库,我们就获取数据库的元数据,这样我们就可以在" metadata = MetaData() "行上修改模式。我们已经准备好创建我们的第一个表了!
创建第一个表格
from **sqlalchemy** import *
from **config** import **host**, **port**, **database**, **user**, **password****conn_str** = f"postgresql://{**user**}:{**password**}@{**host**}/{**database**}"
**engine** = create_engine(**conn_str**)
**connection** = **engine**.connect()
**metadata** = MetaData()**first_tb** = Table('first_table', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(255), nullable=False),
Column('isHappy', Boolean, nullable=False)
)**metadata**.create_all(**engine**)
**query** = insert(**first_tb**).values(id=1, name="Student", isHappy=True)
**ResultProxy** = connection.execute(**query**)
在以“ first_table ”开始的行上,我们通过传递表名、元数据和所有列来创建我们的表。对于每一列,我们可以设置名称、类型以及我们希望每一列具有的约束。最后,在“metadata . create _ all(engine)”行上,我们在数据库中创建新表。现在我们的表已经创建好了,我们可以使用 insert() sqlAlchemy 方法创建一个查询,并向它提供表和我们想要添加到该表中的值。最后,我们可以在最后一行执行查询。
回到 pgadmin,我们可以转到:" database _ name "-> " Schemas "-> " public "-> " Tables "。如果你右击“first_table”,你可以选择:“查看/编辑数据”->“所有行”。这将运行一个选择查询,并将我们添加的行返回给您——如下所示!
结论
感谢阅读!我很乐意听到你的反馈或回答你的任何问题,所以请在下面评论。如果任何图片或信息不再是最新的,请让我知道!
如何使用 OpenCV 和 Flask 部署预先训练好的 Keras 模型
原文:https://towardsdatascience.com/how-to-deploy-a-pre-trained-keras-model-with-opencv-and-flask-86c9dab76a9c?source=collection_archive---------11-----------------------
作者照片
在这篇文章中,我将分享如何使用 Flask、OpenCV 和 Keras 将预训练的模型部署到本地托管的计算机上。我最初使用 Flask、Keras 和 jquery 在 PythonAnywhere 上部署了这个模型。该应用程序是为要求学生或员工剃掉面部毛发的远程学校教室或工作场所设置而设计的。
该应用程序允许用户上传一张照片,然后点击一个按钮将带有编码图像数据的 post 请求发送到网站的后端。图像转换和分类在后端处理,结果在 html 响应中返回到前端。响应动态更新页面,如Shaved
或Unshaved
。
该应用程序的后端是在 Flask 中构建的,但我想允许一个实时视频流检测用户的面部,并在屏幕上标记分类。因为我已经有了一个模型和一个基本的 Flask 框架,所以我想在我的本地机器上使用 OpenCV 来完成剩下的工作。
如果你有一个模型,你可以遵循相同的格式,但如果你没有,我会推荐阅读我以前的博客文章(建立一个卷积神经网络来识别剃毛与未剃毛的脸 & 如何分割一个腌制的模型文件以绕过 PythonAnywhere 上的上传限制)。
OpenCV
OpenCV(开源计算机视觉库)是一个开源的计算机视觉和机器学习软件库。OpenCV 旨在为计算机视觉应用提供一个公共基础设施,并加速机器感知在商业产品中的应用。
https://opencv.org/about/
在阅读文档,观看 YouTube 视频和阅读博客帖子后,我发现了一篇非常有帮助的文章,新冠肺炎:使用 TensorFlow 和 OpenCV 的人脸面具检测,作者 Gurucharan M K 。虽然 Gurucharan 使用 OpenCV 来检测新冠肺炎的面具,但我想先使用类似的格式来检测 a 是否有脸,然后确定该脸是否被剃掉。
对我的难题最有帮助的部分是首先检测人脸,这是通过使用人脸检测程序 基于 Haar 特征的级联分类器 来检测人脸特征来完成的。
face_classifier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
Haar Cascade是一种 机器学习 对象检测算法,用于识别图像或视频中的对象,基于 Paul Viola 和 Michael Jones 在 2001 年发表的论文《使用简单特征的快速对象检测Cascade中提出的特征概念
http://www.willberger.org/cascade-haar-explained/
视频捕捉
video = cv2.VideoCapture(0)
停止视频
video.release()
显示视频
(rval, im) =video.read()
翻转视频
im = cv2.flip(im, 1, 1)
调整视频大小
mini = cv2.resize(im, (im.shape[1] // 4, im.shape[0] // 4))
检测人脸
faces = face_classifier.detectMultiScale(mini)
瓶
Flask 是一个用 Python 编写的微型 web 框架。它被归类为微框架,因为它不需要特殊的工具或库。它没有数据库抽象层、表单验证或任何其他组件,而现有的第三方库提供了通用功能。
安摩尔·贝尔有一篇写得很好的文章,题为“使用 Flask 和 OpenCV 的视频流”。根据这篇文章,我能够构建一个 html 网页模板,以及使用计算机内置摄像头将每帧预测的视频流传输到浏览器所需的路径。
html 页面类似于我之前构建的页面,没有 jquery。
下面是我用来显示主页的简单代码:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Shaved or Not_Shaved </title></head>
</head>
<body>
<center><h1>Shaved or Not_Shaved Streaming App Demo</h1></center>
<center><img id="bg" src="{{ url_for('video_feed') }}"></center>
<video id="video" autoplay>Video Stream not available.</video>
</body>
</html>
为了构建路线,我使用了以下代码来处理页面何时被加载,以及从我们的camera.py
文件中提取的摄像机图像,该文件在网站被加载时被初始化。
以下是我在main.py
文件中使用的烧瓶代码:
from flask import Flask, render_template, Response
from camera import VideoCameraimport os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
app = Flask(__name__)@app.route('/')
def index():
# rendering webpage
return render_template('index.html')def gen(camera):
while True:
#get camera frame
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')@app.route('/video_feed')
def video_feed():
return Response(gen(VideoCamera()),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
# defining server ip address and port
app.run(host='0.0.0.0',port='5000', debug=True)
克拉斯
Keras 是用 Python 编写的深度学习 API,运行在机器学习平台tensor flow之上。它的开发重点是支持快速实验。能够尽快从想法到结果是做好研究的关键。
【https://keras.io/about/】T5T6
由于 Keras 运行在 TensorFlow 之上,我们可以利用 TensorFlow 模块中的 Graph 和 Session 方法。虽然图和会话的细节超出了本文的范围,但是在部署您的模型以便在预定的会话期间可以访问时,您仍然可以使用下面的代码。
import pickle
from keras import backend as K
from tensorflow import Graph, Sessionglobal loaded_model
graph1 = Graph()
with graph1.as_default():
session1 = Session(graph=graph1)
with session1.as_default():
loaded_model = pickle.load(open('Combined_Model.p', 'rb'))
把这一切结合在一起。
最后一块是我们的camera.py
文件。在这个例子中,我们的文件将包含一个函数,将我们的分割模型合并到一个 pickle 文件中。当应用程序加载时,我们将使用一个类摄像机来初始化相机,并将人脸检测程序与我们预先训练的 Keras 模型相结合。
import cv2
import numpy as np
import pickle
from keras import backend as K
from tensorflow import Graph, Session# defining face detector
classifier=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')size = 4labels_dict={0:'shaved',1:'not_shaved'}color_dict={0:(0,255,0),1:(0,0,255)}global loaded_model
graph1 = Graph()
with graph1.as_default():
session1 = Session(graph=graph1)
with session1.as_default():
loaded_model = pickle.load(open('Combined_Model.p', 'rb'))class VideoCamera(object):
def __init__(self):
# capturing video
self.video = cv2.VideoCapture(0) def __del__(self):
# releasing camera
self.video.release() def get_frame(self):
# extracting frames
(rval, im) = self.video.read()
im = cv2.flip(im, 1, 1)
mini = cv2.resize(im, (im.shape[1] // size, im.shape[0] // size))
faces = classifier.detectMultiScale(mini)
for f in faces:
(x, y, w, h) = [v * size for v in f] #Scale the shapesize backup
#Save just the rectangle faces in SubRecFaces
face_img = im[y:y+h, x:x+w]
resized=cv2.resize(face_img,(300,300))
normalized=resized/255.0
reshaped=np.reshape(normalized,(1,300,300,3))
reshaped = np.vstack([reshaped])
K.set_session(session1)
with graph1.as_default():
results=loaded_model.predict(reshaped)
if results >.5:
result = np.array([[1]])
else:
result = np.array([[0]])
label = np.argmax(result)
cv2.rectangle(im,(x,y),(x+w,y+h),color_dict[result[label][0]],2)
cv2.rectangle(im,(x,y-40),(x+w,y),color_dict[result[label][0]],-1)
cv2.putText(im, labels_dict[result[label][0]], (x, y-10),cv2.FONT_HERSHEY_SIMPLEX,0.8,(255,255,255),2)
# encode OpenCV raw frame to jpg and displaying it
ret, jpeg = cv2.imencode('.jpg', im)
return jpeg.tobytes()
请注意,此应用程序仅限于您的本地计算机。希望这篇文章有帮助。我很乐意使用Node.js
、Tensorflow.js
和OpenCV.js
公开部署这个模型,但是这超出了本文的范围。如果我得到 100 条评论,我会把它作为我的下一篇文章!
以下是我的 GitHub 回购的链接:
https://github.com/cousinskeeta/shavedVnotShaved_opencv
资源:
新冠肺炎:Gurucharan M K使用 TensorFlow 和 OpenCV 的人脸面具检测
Anmol Behl使用 Flask 和 OpenCV 进行视频流传输
如何提取评论分类器模型以重用于实时分类
原文:https://towardsdatascience.com/how-to-deploy-a-review-classifier-in-any-application-c1c0e5a0e8ff?source=collection_archive---------25-----------------------
使分类器可重用简介
有很多教程和例子都是关于用大部分可用数据集训练一个评论分类器,并用剩余部分测试它,看看它的表现如何。
很高兴看到如何建立一个分类器,以及它是如何执行的,但是我们如何导出这个分类器,并在任何应用程序中安装、运行,以便我们可以进行实时检查分类呢?
在本帖中,首先我们将利用欧洲 515,000 条酒店评论数据构建一个评论分类器,并对其进行一些领域调整,使其更加通用,而不是针对特定酒店,然后我们将导出带有特征索引的分类器,以应用于我们选择的任何应用程序。
如果你只对我们如何在其他应用程序中提取和应用分类器感兴趣,你可以去我们有一个分类器,现在做什么?部分。
点击这里下载数据集。
酒店数据集调查
我们这里有一个庞大的酒店数据集,它有许多功能,酒店地址,评论日期,平均分数,正面评论,负面评论等等。数据集中的每个条目都来自一个特定酒店的用户。每个用户都被要求对他们住过的酒店提供正面和负面的评价。值得一提的是,在某些情况下,用户只能选择其中之一。当用户未分别提供正面和负面评价时,我们会看到以下特征值:
- 没有阳性
- 没有负面影响
在这篇文章中,我们将只关注正面评论和负面评论,而不管哪个用户写了哪个酒店。
预处理
我们需要对数据集做一些预处理。首先,我们将创建一个新的数据集,只获取 1%的原始数据集的正面和负面评论。(在本文中,我们将只使用 5K 个数据条目,但是您可以稍后尝试使用整个数据集进行构建)。然后,我们将清除遗漏的评论(无负面、正面、无等等)。
删除空洞和无价的评论
让我们为项目创建一个文件夹,在该文件夹中找到数据集,然后创建一个新的 python 文件进行预处理。我把它命名为 hotel_review_pre_processor。
首先,我们将导入 pandas 和 numpy,然后加载原始数据集的 1%。
import pandas as pd
import numpy as np# load data
reviews_df = pd.read_csv("Hotel_Reviews.csv")#only get 1 percent of data. because the data is huge
reviews_df = reviews_df.sample(frac = 0.01, replace = False, random_state=42)
然后,让我们创建一个新的空数据框架,其中包含点评和 is_positive 特征,稍后我们将使用酒店数据集中的点评填充这些特征。
df = pd.DataFrame(columns=('review', 'is_positive'))
现在,我们将用空字符串替换数据集中的非正值和非负值,然后用 NaN 替换它们,最后删除它们:
#replace missing review info with empty strings
reviews_df = reviews_df.replace(['No Negative', 'No Positive'], ['', ''])#replace empty strings with NaN value (null) and then drop them.
reviews_df = reviews_df.replace(r'^\s*$', np.nan, regex=True)
reviews_df = reviews_df.dropna()
然后,我们将执行以下操作:
- 仅从数据集中获取负面评论和正面评论列。
- 为它们中的每一个创建单独的数据框
- 对于每个数据框中的每个条目,使用 review 和相应的 is_positive 值(0 表示负面评论,1 表示正面评论)向我们的新数据框(df)添加一个新条目。
- 然后,我们会将新的数据框保存为 reviews.csv。
#only get reviews.
reviews_df = reviews_df[["Negative_Review", "Positive_Review"]]#separate them
negative_reviews_df = reviews_df[["Negative_Review"]]
positive_reviews_df = reviews_df[["Positive_Review"]]#add all negative and positive reviews with related label 'is_positive' 0 for negative, 1 for positive.
for index, row in negative_reviews_df.iterrows():
if "nothing" in row["Negative_Review"]:
pass
elif "Nothing" in row["Negative_Review"]:
pass
else:
df = df.append({'review': row["Negative_Review"], 'is_positive': 0}, ignore_index=True)for index, row in positive_reviews_df.iterrows():
if "nothing" in row["Positive_Review"]:
pass
elif "Nothing" in row["Positive_Review"]:
pass
else:
df = df.append({'review': row["Positive_Review"], 'is_positive': 1}, ignore_index=True)#save the cleaned data as reviews.csv
endResult = df.to_csv('reviews.csv',index=False)
现在我们完成了预处理。我们将酒店数据集中的评论放入一个名为 reviews.csv 的新数据集中,该数据集中有 review 和 is_positive 功能。现在我们应该有大约 6500 条评论可供我们分析。正如我前面提到的,通过在下面一行中更改 frac 参数,您可以增加或减少您使用的数据集部分:
reviews_df = reviews_df.sample(frac = 0.01, replace = False, random_state=42)
使评论更加通用
现在我们已经处理了这些评论,并将它们重构为一个新的数据集,其中包含了我们感兴趣的特性,但是我们仍然有一个问题。由于原始数据集来自酒店评论,它们很可能包含酒店行业特有的词,如:酒店、床、淋浴、早餐等。如果我们想让我们的分类器以后变得通用,我们需要去掉这样的词。
但是首先,我们将去掉停用词(没有任何上下文含义的词,如:for、the、a、or、what 和 etc ),然后对评论中现有的词进行词干处理以删除重复的词。作为一个例子,当词干分析应用于下面的任何一个单词时,它们都将导致运行。
- (跑步,跑步,跑步)->跑步
继续创建一个名为 review_cleaner.py 的文件。
我们将把它创建为一个单独的类,因为我们稍后将从多个文件中再次需要这个方法:
import nltk
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmerclass ReviewCleaner:
[@staticmethod](http://twitter.com/staticmethod)
def clean_review(review):
review = review.lower()
review = review.split() ps = PorterStemmer() review = [ps.stem(word) for word in review
if not word in set(stopwords.words('english'))] review = ' '.join(review) return review
该方法将如下工作:
- 接受名为 review 的字符串参数
- 降低所有字符并拆分单词
- 对每个单词应用词干并删除任何停用词(如果存在)。
- 用带词干的单词创建一个名为 review 的新字符串并返回它
如果您曾经得到以下错误:“资源停用词没有找到”,即使您有 nltk 库。打开终端并执行以下命令:
- python3
-导入 nltk
- nltk.download('停用字词')
-这应该可以修复错误。
现在,让我们创建一个名为 review _ generifier.py 的文件,并添加以下代码块:
import pandas as pd
import numpy as np
from collections import Counter
from review_cleaner import ReviewCleaner as rcreviews_df = pd.read_csv("reviews.csv")for index, row in reviews_df.iterrows():
cleared_review = rc.clean_review(row['review'])
reviews_df.at[index, 'review'] = cleared_reviewmost_common_100_words = Counter(" ".join(reviews_df["review"]).split()).most_common(100)print(most_common_100_words)
请注意,根据您的机器,对数据集中的每个数据条目应用清除需要一段时间。
这里,我们将 ReviewCleaner 类中的 clean_review 方法应用于数据集中可用的每个评论。然后我们打印出出现次数最多的 100 个单词以及出现次数。(为简单起见,仅显示了 20 个):
[('room', 3067), ('staff', 1697), ('locat', 1596), ('hotel', 1499), ('breakfast', 1171), ('good', 1057), ('bed', 831), ('great', 771), ('help', 665), ('clean', 658), ('nice', 637), ('friendli', 636), ('comfort', 540), ('small', 513), ('stay', 478), ('excel', 469), ('bathroom', 393), ('love', 384), ('would', 382), ('could', 358)]
如你所见,有这样的词;房间、员工、酒店、早餐等(你可以在整个打印列表上看到更多)都是酒店行业特有的。如果我们想使它通用,我们不希望这样的词被输入到我们的分类器中。因此,我们现在要删除这些词。
现在,让我们创建一个要从评论中删除的单词列表:
unwanted_words = ['room', 'staff', 'locat', 'hotel', 'breakfast', 'bed', 'shower']
您还可以/应该尝试删除其他单词,看看它是否会影响您的分类器的准确性。
我们需要导入 re 来删除不需要的单词。使用其他导入在文件顶部导入 re,如下所示:
import re
现在,让我们从数据框中删除不需要的单词,如下所示:
reviews_df['review'] = reviews_df['review'].str.replace('|'.join(map(re.escape, unwanted_words)), '')
您可以获取常用单词并在更新数据框后再次打印它们,您应该会看到在 wanted_words 中声明的单词现在已经消失了。
现在,我们将把更新后的数据集保存为 cleared_reviews.csv ,并在末尾添加以下代码:
#save the cleaned data as cleared_reviews.csv
endResult = reviews_df.to_csv('cleared_reviews.csv')
从现在开始,我们将使用 cleared_reviews.csv 数据集:)
用随机森林分类器训练评论分类器
现在我们有了通用数据集,我们可以训练一个随机森林分类器(RFC)【1】模型作为我们的通用分类器。(请注意,审查分类器可以用许多不同的方法实现,我只想用 RFC)。
现在,让我们创建一个新文件 rf_classifier_training.py,并添加以下代码:
import pandas as pd
import numpy as np
import pickle
import jsondataset = pd.read_csv('cleared_reviews.csv')from sklearn.feature_extraction.text import CountVectorizer
cv = CountVectorizer(max_features = 1500)
X = cv.fit_transform(dataset["review"].values.astype('U')).toarray()
y = dataset["is_positive"]from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25)from sklearn.ensemble import RandomForestClassifiermodel = RandomForestClassifier(n_estimators = 501,
criterion = 'entropy')model.fit(X_train, y_train)
y_pred = model.predict(X_test)print('Score: ', model.score(X_test, y_test))
这里我们训练一个分类器如下:
- 初始化 CountVectorizer 以从我们的评论中获取 1500 个特征,这里每个特征对应一个词(它选择数据集中出现最多的 1500 个词)。
- 将数据集拆分为 75%和 25%,分别用于定型和预测。
- 创建一个 RFC 模型,包含 n 个估计量和标准参数(不同的参数值可以提高性能,如果你愿意可以试试)
- 训练模型,然后根据测试数据进行预测
- 最后打印出分类得分的分数。
打印分数应该在 0.90 左右,这意味着每 10 篇评论中,有 9 篇被成功归类为当前标签(正面或负面)。我认为这对 RFC 来说是相当好的,因为我们没有试图优化它的参数。
我们有了一个分类器,现在怎么办?
现在我们有了一个分类器,可以将评论分为正面或负面。但是我们如何提取它,以便在应用程序中对新数据进行分类呢?
为此,我们需要保存我们的模型。但这还不够。因为如果我们对特征(单词)一无所知,我们如何将新数据放入这个模型。更具体地说,我们不知道哪个词在特征空间中有什么索引。因此,我们还将为每个单词找到特征索引,并分别保存它们。
在 rf_classifier_training.py 中打印分数后,立即添加以下代码:
words = cv.vocabulary_
words_for_json = {}for k, v in words.items():
words_for_json[k] = int(v)pickle.dump(model, open('reviewClassifier.pkl','wb'))
with open('word_feature_space.json', 'w') as fp:
json.dump(words_for_json, fp)
[word: index]字典保存为 word_feature_space.json 下的 json 键值,分类器模型保存为 reviewClassifier.pkl。
现在再次运行 rf_classifier_training.py 来保存 json 和 pkl 文件。
这些文件不会包含在 github repo 中,因为模型的大小大约为 100 Mb。所以你必须运行 rf_classifier_training.py 来获取这些文件。
编写可以在任何应用程序中使用的分类器服务
现在我们有了模型和 json,我们可以编写一个服务来为任何给定的文本提供分类。
我们的服务如下:
- 清理收到的审核
- 用收到的评论创建一个向量
- 将这个向量拟合到模型中并进行预测
- 以二进制形式返回预测值(0 =负,1 =正)
让我们创建 review_classifier_service.py,如下所示:
ReviewClassifierService
值得从评论中给出关于向量创建的更多细节,我们检查评论中的每个词,如果它存在于我们的词空间(word_feature_space.json)中,我们将它添加到向量空间并增加字数,但是如果它不存在,我们就简单地丢弃它。
请求
现在,我们将向服务发出一个示例请求,以查看我们的分类器如何处理新数据,让我们创建 example_request.py:
from review_classifier_service import ReviewClassifierServiceservice = ReviewClassifierService()positive_sample = "It was great"
negative_sample = "It was horrible"
print(service.classify(positive_sample))
print(service.classify(negative_sample))
输出是:
{"outcome": 1}
{"outcome": 0}
如您所见,我们的分类器服务可以提供一个 json 响应,值 1 表示肯定,值 0 表示否定。为了简单起见,我在这里没有尝试不同的评论,但是它应该工作得很好,除非你提供一个棘手的评论(一个有许多正面和负面单词的评论=D)。请继续尝试不同的评论。
结论
在本文中,我们看到了如何处理数据以使其有用,如何使数据集更通用,如何构建评论分类器,更重要的是,如何提取该分类器模型并使其能够应用于我们想要的任何应用程序。您可以使用这些或类似的方法来获得您的分类器,然后将它们部署在您的后端,并为许多应用程序和客户端提供服务。
您可以在这里找到完整的存储库。
保重:)
在 AWS 上使用 Streamlit 和 Docker 部署机器学习应用程序
原文:https://towardsdatascience.com/how-to-deploy-a-semantic-search-engine-with-streamlit-and-docker-on-aws-elastic-beanstalk-42ddce0422f3?source=collection_archive---------17-----------------------
图片由 Kostas Stathoulopoulos 提供
在之前的博客中,我们讨论了如何用句子转换器和 Faiss 构建一个语义搜索引擎。这里,我们将创建一个 Streamlit 应用程序,并在本地和 AWS Elastic Beanstalk 上部署搜索引擎。
如果您想直接进入代码,请查看 GitHub repo!
简化应用程序
Streamlit 是一个开源的 Python 库,可以轻松创建用于机器学习和数据科学的应用程序。使用 Streamlit,您不需要学习 Flask 或任何前端开发,您可以专注于您的应用程序。
我们的应用程序将帮助用户搜索学术文章。用户将在搜索框中键入文本查询,并检索最相关的出版物及其元数据。他们还可以选择返回结果的数量,并根据论文引用数量和出版年份进行筛选。
在幕后,我们将使用句子蒸馏模型对搜索查询进行矢量化,并将其传递到预先构建的 Faiss 索引中进行相似性匹配。Faiss 将测量查询向量和索引纸张向量之间的 L2 距离,并返回与查询最接近的纸张 id 列表。
让我们看看这个应用程序会是什么样子,然后深入研究代码。
建立简化应用的原型
让我们导入所需的 Python 包。
接下来,我们将编写几个函数来加载数据、transformer 模型和 Faiss 索引。我们将使用 Streamlit 的 [@st.cache](https://docs.streamlit.io/en/stable/caching.html)
装饰器来缓存它们,以加速我们的应用程序。
最后,我们将创建应用程序的主体。
让我们一行一行地检查代码:
- 第 4–6 行:调用上面显示的函数,加载并缓存数据和模型。
- 第 8 行:设置我们应用的标题。
- 第 11 行:在页面主体上创建一个多行文本输入小部件。那是我们的搜索框!
- 第 14–17 行:创建搜索引擎过滤器,并将它们放在侧边栏上。
- 第 22 行:对给定的文本查询进行语义搜索,并返回最相关结果的论文 id。这些将基于它们与文本查询的相似性来排序。
- 第 24–28 行:根据发表年份和论文引用次数过滤数据。
- 第 30–34 行:对于第 22 行中检索到的每个纸张 ID,从过滤后的数据集中提取其元数据。
- 第 36–43 行:打印论文的元数据,即标题、引文、出版年份和摘要。
将申请归档
我们将使用 Docker 将应用程序及其所有依赖项打包到一个容器中。我们将创建一个Dockerfile
,它是一个包含命令(即指令)的文本文档,用来组合一个图像。如果你不熟悉 Docker,本指南提供了深入的介绍。
FROM python:3.8-slim-buster
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 8501
ENTRYPOINT ["streamlit","run"]
CMD ["app.py"]
让我们一行一行地解释这个 docker 文件将做什么:
- 第 1 行:取一个 Python 基图。
- 第二行:将这个 GitHub repo 的内容复制到一个名为
/app
的目录下 - 第 3 行:将工作目录更改为
/app
- 第四行 : Pip 安装
requirements.txt
文件。 - 第 5 行:让容器在运行时监听 8501 端口。
- 第 6 行:启动集装箱时执行
streamlit run
命令。 - 第 7 行:指定将提供给
ENTRYPOINT
的参数,在我们的例子中,是应用程序的文件名。
现在,假设 Docker 正在您的机器上运行,我们可以用下面的命令构建映像:
$ docker build -t <USERNAME>/<YOUR_IMAGE_NAME> .
构建命令将创建一个符合Dockerfile
规范的图像。现在,我们准备好部署我们的应用程序了!
部署应用程序
本地部署
在本地部署我们的语义搜索引擎非常简单。构建完映像后,我们将使用 run 命令在容器中旋转我们的应用程序。我们还将添加-p
参数,以在 8501 发布容器的端口。
$ docker run -p 8501:8501 <USERNAME>/<YOUR_IMAGE_NAME>
您可以通过以下地址访问该应用程序:
http://localhost:8501/
AWS 弹性豆茎展开
为了在 AWS 上部署我们的应用程序,我们需要将我们的图像发布到一个注册中心,云提供商可以访问这个注册中心。为了方便起见,我们还是用 Docker Hub 吧。如果您以前没有推送过图像,客户端可能会要求您登录。提供用于登录 Docker Hub 的相同凭据。请注意,这一步可能需要一段时间,因为我们的图像相当大!
$ docker push <USERNAME>/<YOUR_IMAGE_NAME> .
在公共注册表上发布您的映像并不是强制性的,但是,它通过跳过一些配置步骤简化了部署。
现在,我们几乎可以在 AWS Elastic Beanstalk (EB)上部署我们的映像了。让我们列出步骤:
- 登录 AWS 控制台,搜索弹性豆茎。
图片由 Kostas Stathoulopoulos 提供
- 点击创建应用按钮,并命名您的应用。
图片由 Kostas Stathoulopoulos 提供
- 选择 Docker 作为平台。现在,我们需要从本地文件上传我们的代码。因为我们的应用程序是 dockerized 的,所以我们只需要提供容器的细节。我们将通过点击选择文件按钮并上传
[Dockerrun.aws.json](https://github.com/kstathou/vector_engine/blob/master/Dockerrun.aws.json)
文件来完成此操作。这是一个特定于 AWS 的文件,它与 EB 共享我们的应用程序的详细信息和 docker 配置。在上传之前,请确保您已经将Dockerrun.aws.json
中的图像名称从kstathou/vector_engine
更改为您之前使用的<USERNAME>/<YOUR_IMAGE_NAME>
。上传文件后,点击配置更多选项。
图片由 Kostas Stathoulopoulos 提供
- 编辑实例和产能。从实例开始,将根卷类型更改为通用(SSD) 并将大小更改为 8GB。滚动到页面底部,点击保存。接下来,选择 Capacity 并将实例类型从 t2.micro 更改为 t3.medium。注意,我们选择的 EC2 实例不在空闲层中,您将因使用它而付费。请确保在使用完应用程序后关闭它!
图片由 Kostas Stathoulopoulos 提供
- 点击创建应用程序。EB 将需要几分钟来部署我们的应用程序。一旦完成,你将能够通过它的 URL 访问和分享语义搜索引擎!
图片由 Kostas Stathoulopoulos 提供
结论
在本教程中,我向您展示了如何使用 Streamlit 构建应用程序原型,以及如何使用 Docker 在本地和 AWS Elastic Beanstalk 上进行部署。如果你有任何问题,请在评论中告诉我。
代码可以在 GitHub 上找到!
如何免费使用 Heroku 部署电报机器人
原文:https://towardsdatascience.com/how-to-deploy-a-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-bot-using-heroku-for-free-9436f89575d2?source=collection_archive---------1-----------------------
使用 python-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-bot 库的完整指南
在本地运行你的电报机器人足以满足简单的应用。但是,如果您想要扩展您的 bot 并使其他人能够使用您的 bot,即使您没有在本地运行 bot,您将需要更进一步来部署 bot。
由伊恩·巴塔格利亚在 Unsplash 上拍摄
在本教程中,我将介绍如何使用 Heroku 的 python-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-bot 库部署您创建的电报机器人。更棒的是,我们可以完全免费地做到这一点!忘掉你从其他主机选项中产生的所有费用,Heroku 将很可能满足你的需求,你不用支付一分钱,也不用输入你的信用卡信息。
为此,我将使用一个取自 python-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-bot Github 存储库中示例的简单启动脚本,在该存储库中,bot 只是简单地回应用户发送的任何内容。您可能有不同的脚本,但是我将向您展示要修改哪些部分,以便使用 Heroku 部署 bot。
如果你想直接找到需要的文件,就去这个 Github 库下载吧!
这是我们的起点:
修改 python-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-bot 脚本
从轮询更改为 Webhooks
首先,我们将修改机器人获取新数据的方式。python-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-bot 脚本使用轮询而不是 webhooks 来获取新数据。对于简单的测试来说,轮询就足够了,因为它很容易实现。然而,轮询的缺点是效率低,而且它获取的数据总是旧的,从来不是实时的。这是因为轮询以预定的频率发送请求以检测数据中的任何变化,这意味着它不断检查数据是否被修改,而不是在数据发生变化时得到“通知”。
图片摘自https://community . Stuart . engineering/t/web hooks-vs-polling/257
另一方面,webhooks 的作用类似于推送通知。当数据被修改时,webhooks 被触发,而不是获取信息。这允许实时信息,也使它更有效,因为不需要不断地发送请求来检查数据。
图片取自https://community . Stuart . engineering/t/web hooks-vs-polling/257
我们首先导入 os,然后设置端口号来监听 webhook。
import os
PORT = int(os.environ.get('PORT', 5000))
接下来,我们修改下面的代码行
updater.start_polling()
到
updater.start_webhook(listen="0.0.0.0",
port=int(PORT),
url_path=TOKEN)
updater.bot.setWebhook('[https://yourherokuappname.herokuapp.com/'](https://yourherokuappname.herokuapp.com/') + TOKEN)
这样做的目的是将轮询方法更改为 webhook,使用上面用 port 变量指定的端口监听 0.0.0.0。令牌指的是你的电报机器人的 API 令牌,应该在代码的顶部定义。下一行是设置带有 heroku 应用程序链接的 Webhook,我们将在下一步讨论。
在对 python 文件进行了所有更改之后,它应该类似于下面这样(使用您自己的 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 bot 令牌):
创建 Heroku Webapp —设置目录
我们已经完成了 python-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-bot 脚本的编辑,除了更改 heroku 应用程序的名称之外,我们将很快进行更改。为了让 heroku 将以下内容识别为 python 应用程序,您需要将以下文件放在同一个目录中:
bot.py
Procfile
requirements.txt
python 代码应该在 bot.py 文件中,我将完成创建 Procfile 和 requirements.txt 的过程。
首先,将终端/命令提示符的目录更改为包含 python 脚本的目录。然后,创建包含以下行的 requirements.txt 文件:
python-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-bot==12.7
这需要告诉 heroku 需要安装哪些库来执行代码。假设你用的是上面的样例代码,你唯一需要的库是 python-丨t丨e丨l丨e丨g丨r丨a丨m丨s丨-bot,我们用的版本是 12.7。如果要导入其他库来运行 python 代码,请确保在 requirements.txt 文件中也包含其他库。
接下来,您需要一个 Procfile。procfile 以
web: python3 bot.py
确保 Procfile 没有任何文件扩展名,如。txt 在后面,因为行不通。
创建您的 Heroku Webapp
将这三个文件放在同一个目录中,我们现在将创建 Heroku Webapp。
- 登录/ 创建一个 Heroku 账号。
- 安装 Heroku CLI 。如果您没有安装 Git,请先安装 Git ,然后再继续使用 Heroku CLI。
- 安装后,您可以在终端/命令提示符下使用 heroku 命令。转到 python 文件所在的目录,然后输入:
heroku login
一个新的窗口将在你的浏览器中打开,提示你登录,所以只需点击按钮。
4.登录后,返回命令行。输入
heroku create
创建您的新 webapp。在这里,heroku 将为您的 webapp 分配一个名称以及指向您的 webapp 的链接,其格式应该是【https://yourherokuappname.herokuapp.com/.将 URL 粘贴到 bot.py 代码中
updater.bot.setWebhook('[https://yourherokuappname.herokuapp.com/'](https://yourherokuappname.herokuapp.com/') + TOKEN)
对您的 bot.py 文件进行所有更改后,它看起来应该类似于以下内容(当然,使用您自己的 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 bot 令牌和 heroku 应用程序名称):
5.接下来,在命令行中输入
git init
git add .
git commit -m "first commit"
heroku git:remote -a YourAppNamegit push heroku master
第一行创建了一个新的 Git 存储库。第二行告诉 Git,您希望在下一次提交中包含对特定文件的更新。然后第三行提交更改。在第四行中,将“YourAppName”更改为 heroku 应用程序的名称。最后,第五行将所有内容推送到服务器。
然后,您应该会看到以下消息:
特别是,它会说检测到一个 Python 应用程序,并使用 pip 在 requirements.txt 文件中安装所需的库。然后,它将读取指定要执行 bot.py 文件的 Procfile。
原来如此!一旦它完成执行,你可以简单地去电报和信息/开始你的机器人。它现在应该按照您期望的那样运行。
由于你在 heroku 上使用免费计划,机器人将在 30 分钟不活动后休眠。所以,如果你在使用它超过 30 分钟后才开始使用它,那么你要期待机器人会花几秒钟来响应你的/start。除此之外,机器人几乎会瞬间做出反应~
如果你的机器人停止响应该怎么办
我注意到,在大约 24 小时不活动后,机器人停止响应(因为我们使用的是 Heroku 的免费版本),所以如果您想“唤醒”机器人,一种方法是对其中一个文件进行更改(例如,将 procfile 中的 python3 更改为 python,反之亦然),然后用下面的代码行提交更改:
git add .
git commit -m "changing python3 to python in Procfile"
git push heroku master
您应该再次看到关于 Python 应用程序被检测到的消息,并且一旦它完成执行,您的 bot 现在应该恢复了!
如何在 AWS 上部署气流:最佳实践
原文:https://towardsdatascience.com/how-to-deploy-airflow-on-aws-best-practices-63778d6eab9e?source=collection_archive---------10-----------------------
在 AWS 上部署气流对于没有 DevOps 经验的人,也就是几乎所有从事数据工作的人来说,都是一个相当大的挑战。
TL;DR;
我创建了一个 repo,按照软件工程最佳实践在 AWS 上部署气流。如果你不想读这篇文章,你可以直接去那里。但我确实描述了一些你可能会觉得有用的东西。
荷兰 Zaandijk Zaanse Schans|照片由 Wim van 't Einde 在 Unsplash 上拍摄
运行 docker-compose 命令和 voíla,您就有了在本地环境中运行的 Airflow,并且您已经准备好开发一些 Dag 了。一段时间后,您已经为在生产环境中部署 Dag(和气流)做好了准备。然后你开始搜索如何在 AWS 上部署气流的说明。以下是您可能会发现的内容:
- 没有关于气流文件的说明。
- 有些帖子,像这个,教你如何在 AWS ECS 上部署。相当有趣的方法。问题是,整个教程都是基于通过在 AWS 控制台上点击来创建资源。相信我;您不希望在生产环境中部署时走这条路。想象一下创建三个不同的环境(开发、试运行和生产)并不得不重复该过程三次的噩梦。现在想象一下更新环境并使它们保持同步。想象一下,你可以很容易地花一整个星期来修复一个错误,这个错误是由一个被错误删除的资源引起的。
- 另一篇文章相对较新,采用了更好的方法,但它仍然使用 AWS CLI 创建资源(如 ECS 集群)。比控制台上的点击式稍好一点,但仍不能用于生产。
- 其他文章,可能会提到使用基础设施作为代码,这将解决上述问题。但是,它们在技术细节和实现上都非常肤浅。因此,尽管提供了很好的概述和最佳实践,但对于没有 DevOps 经验的人来说,它们并不实用。
- GitHub上的这个回购可能是你在遵循软件工程最佳实践的 AWS 上正确实现 Airflow 的最接近的方式。但它仍然缺乏一些基本的东西,如 web 服务器和工作人员的自动缩放,或者配置设置的方法,如 RDS 实例类型,而不必挖掘 Terraform 代码。
你可能会在你的谷歌搜索的第二页上看一下,但是如果一个好的结果没有出现在第一页上,那么这可能意味着它不存在。
入门指南
只需克隆 repo ,遵循一些说明并安装自述文件中描述的要求,然后运行:
make airflow-deploy
这将向您的 AWS 帐户部署一个 Airflow 实例!
搞定了。您将在启用自动缩放的 AWS ECS 上部署 Airflow。图片由作者提供,气流用户界面的打印屏幕。
它如何帮助您遵循最佳实践?
service.yml 文件
该回购使用 AWS Cloudformation 实现所有基础设施。在/cloud formation目录中,您将找到创建运行 Airflow 所需的基础设施的所有模板。好的一面是你不需要担心学习 Cloudformation 来做简单的部署,因为在根中有一个service . yml来帮助你。
假设您想要将特定 IP(如您的办公室 IP)列入白名单,以便访问 Airflow UI。您唯一需要做的事情就是修改 service.yml 中的几行代码:
添加要加入白名单的 IP 地址列表。默认情况下,所有服务将对所有 IP 开放(0.0.0.0/0)。
如果你想改变气流数据库实例类型,你也可以去 service.yml :
很容易改变你的气流的元数据数据库引擎版本,更新实例类型等。
你要的只是气流工作者的 CPU 和内存?微调自动缩放? service.yml 是一站式商店。
轻松微调气流服务的自动缩放规则。
在 AWS Secrets Manager 中管理密码
不要硬编码你的密码是软件工程 101。但是有时候,如果没有硬编码,很难在运行时自动部署和创建密码。在这个气流回购中,我们使用 AWS Secrets Manager 来帮助我们解决这个问题。
- 气流元数据数据库
我们的 Postgres 数据库将保存气流元数据,是需要管理员用户名和密码的资源之一。使用 AWS Secrets Manager,在部署时会创建一个强随机密码,并将其附加到集群。要获得密码值,您必须登录到您的 AWS 帐户,并转到 Secrets Manager。
Cloudformation 代码将为您创建一个强数据库密码。创建数据库时会引用用户名和密码。
也可以用 Secrets Manager 实现自动密码轮换,但是这个项目没有实现。
- 费尔内键
Airflow 使用 Fernet 密钥对保存在元数据数据库中的密码(如连接凭证)进行加密。该部署在部署时生成一个随机的 Fernet 密钥,并将其添加到 Secrets Manager 中。然后,它在气流容器中作为环境变量被引用。
自动缩放已启用
将气流投入生产的最大挑战之一是处理资源管理。如果出现使用高峰,如何避免 web 服务器崩溃?或者,如果某个特定的日常工作需要更多的 CPU/内存,该怎么办?
自动缩放为您解决了这些问题。在这个存储库中,您可以轻松地配置阈值,并且可以放心,您的基础架构将根据需求进行伸缩。
轻松部署到不同的环境
在生产设置中,您会希望将代码部署到不同的环境中。假设你需要:制作,舞台和开发。
这个 repo 允许您通过更改一个环境变量将相同的代码部署到不同的环境中,这可以在您的 CI/CD 管道上自动推断出来。要改变环境,请执行以下操作:
***export ENVIRONMENT=dev; # this will deploy airflow to dev environment
make airflow-deploy;***
更新 Dag 而不触及基础架构
Airflow 的美妙之处在于能够将工作流写成代码。这意味着您更改 DAGs 代码的频率要比更改基础设施的频率高得多。通过这种气流部署,您将向 Dag 提交更改,它不会尝试为您重新部署基础架构。
您唯一想做的事情是构建一个新的气流图像,将其推送到 ECR,然后更新您的 ECS 服务以加载最新的图像。为此,只需运行:
***make airflow-push-image;***
这里的情况并非如此,但是您甚至可以将 Dag 放在单独的存储库中。这将使基础设施与软件更加分离。
标记您的资源
标记资源将使我们能够轻松地创建自动警报、确定所有权和跟踪基础架构成本。这就是为什么这个气流储存库会标记所有资源。
当在云上运行多个服务时,标记资源是一个关键的实践。
你这边应该怎么做?
您应该将部署流程添加到 CI/CD 管道中。为了运行一些自动化测试,我使用 GitHub Actions(但是您的公司可能使用其他工具,如 CircleCI 或 Jenkins)。
您可以遵循类似的过程来自动化您的部署和测试。看看测试工作流程来获得一些灵感。
这要花多少钱?
在采用默认配置的 AWS 上运行气流(同时考虑到集群没有纵向扩展)每天应该花费 5 到 7 美元。这取决于您正在部署的区域。**
通过降低 service.yml 上的 CPU 和内存以及改变工人的最小数量,可以进一步降低成本。默认设置将允许气流在需要增加资源之前运行相当多的 Dag。微调并找到最适合您的用例的方法。
我希望这篇文章(和资源库)能帮助你轻松地生产气流。如果您有任何问题、建议或要求,请通过 LinkedIn 联系我,或在回购上打开问题。此外,欢迎您打开 PRs 并与该项目合作!
如何使用脸书先知机器学习模型将自动交易机器人部署到 AWS Lambda(无服务器)
原文:https://towardsdatascience.com/how-to-deploy-an-automated-trading-bot-using-the-facebook-prophet-machine-learning-model-to-aws-1182c603e280?source=collection_archive---------35-----------------------
AWS Lambda“设计者”这篇文章的算法概述
在这篇文章中,我将介绍我的无服务器投资算法,使用 AWS Lambda,脸书先知作为 ML 模型,以及我的自定义 Lambda 层。
我把这篇文章分为“我为什么要这么做”和“技术方法”两部分。如果你想跳过“为什么”的部分,可以直接跳到技术部分。
我为什么要在 AWS Lambda 中部署机器学习模型?
1。可靠性:算法将独立于其他系统、更新、…
2。性能效率:我可以在一个(小)系统上运行几个算法,彼此独立。
3。成本节约: AWS 允许每月320 万计算秒,基本上让我免费运行我所有的算法。
我一直在寻找一种方法,首先确保我的投资机器人肯定会执行,因为如果交易方向错误,没有及时取消,失败的执行可能会花费很多钱。此外,我想避免让我的计算机一直运行,并确保几个算法可以彼此相邻运行,而不会影响或延迟它们的执行。
此外,让一个投资算法运行而不用担心操作系统更新、硬件故障和断电等,这是一个很好的想法,这是无服务器技术的一般优势。
现在,我可以运行算法的几个变体来测试算法的变化,并且可以确定它将运行。另一件好事?AWS 提供了大约 100 万次免费的 Lambda 调用,这让我可以在其免费层中运行整个架构。
投资算法
我将在我的网站 www.datafortress.cloud 上的另一篇文章中更深入地解释该算法,但我的典型投资算法设置包括:
- 使用用 python 编写的开源回溯测试框架 Backtrader 测试算法
- 将成功的算法转换成包含 run()方法的单个 python 文件,该方法返回已经完成的投资
- 将 python 文件传输到 AWS Lambda,在这里我用 AWS Lambda 的 lambda_handler 函数调用 run()函数
在这个示例算法中,我根据当前价格是高于还是低于由脸书的先知模型预测的趋势线来做出投资决定。我从肖恩·凯利那里得到了灵感,他写了一个关于如何利用预言家和反向交易者的反向交易者设置。
在这个设置中,我的股票范围是通过从 SPY500 指数中选择在过去 X 个时间步中获得最高回报的前 20 只股票来计算的。
数据来源是雅虎财经,使用的是免费的 yfinance 库,作为我选择的算法经纪人,我选择了羊驼网。
在我的设置中,算法将在每天下午 3 点执行一次,或者在交易时间每 15 分钟执行一次。
将脸书先知部署到 AWS Lambda 时遇到的问题
AWS Lambda 预装了一些 python 库,但正如许多人可能知道的那样,这在默认情况下是非常有限的(这对 Lambda 的承诺来说是合理的)。尽管如此,Lambda 允许安装私有包,这对于较小的包来说非常容易(参见官方文档),但是如果处理大小超过 250 Mb 的包,就变得有点复杂了。不幸的是,脸书的 prophet 模型超出了这个界限,但幸运的是亚历山大·巴甫洛夫·马采诺夫通过减少包的大小解决了这个问题,而马克·梅斯处理了编译问题,使其可以在 AWS Lambda 上运行。
通过使用层,可以将非默认库添加到 AWS Lambda 中,层包含所有需要的包。如果导入了某个图层,您可以像在本地设置中一样,在 python 函数中导入包。
如何(技术)
最后,让我来解释一下你到底是如何做到这一点的。不耐烦的人可以看看这个 TLDR,或者下面更详细的版本。
TLDR;
- 你将需要一个 Lambda 层,上传我的(下载)包含先知,金融,…到一个 S3 桶(私人访问)
- 选择 AWS Lambda,创建一个函数,添加一个层,然后粘贴到您的 S3 对象 URL 中
- 将你的 lambda_function.py 粘贴到 lambda 编辑器中(或使用我的)
- 设置环境变量(可选)
- 要么通过单击“测试”手动运行它,要么前往 CloudWatch -> Rules -> Create Rule 并设置“计划执行”以在指定的时间间隔运行它
详解:
1.为 AWS Lambda 创建自定义层
你可以使用我的 Lambda 层,其中包含脸书先知、NumPy、熊猫、羊驼-交易-API 、yfinance ( GitHub )或者使用 Marc 给出的解释来编译你自己的层。
使用我的 Lambda 图层
- 从我的 Github repo 下载包含所有包的 zip 文件(链接)。
- 由于你只能直接上传层到 Lambda 直到 50 Mb 的大小,我们将首先需要上传文件到 AWS S3。
- 创建一个 bucket 并将下载的 zip 文件放入其中。访问可以保持私密,不需要公开!将 URL 复制到您的文件中(例如https://BUCKETNAME.s3.REGION.amazonaws.com/python.zip)。
- 登录 AWS,进入 Lambda-> Layers(EU central Link)。
- 点击“创建层”,给它一个匹配的名称,并选择“从亚马逊 S3 上传文件”,并复制第 3 步的代码到其中。运行时选择 Python 3.7。单击创建。
编译自己的 Lambda 图层
请遵循 Marc 的指示。
2.设置 AWS Lambda 函数
- 打开 Lambda 功能仪表板( EU central Link )并点击“创建功能”
- 保留“从头开始创作”复选框,并给它一个合适的名称。
- 在“运行时”中,选择 Python 3.7,其余保持不变,点击“创建函数”。
- 在“设计器”选项卡的概述中,您将看到 Lambda 函数的图形表示。点击它下面的“图层”框,点击“添加图层”。如果你正确地设置了层,你将能够在下面的对话框中选择它。最后,点击“添加”。
- 在“设计器”标签中,选择你的 Lambda 函数。如果向下滚动,您将看到一个名为“lambda_function.py”的文件中的默认 python 代码片段。如果你的代码结构和我的一样( Link ),你可以用 run()函数执行你的函数。如果一个 Lambda 函数被调用,它将执行 lambda_handler(事件,上下文)函数,你可以从这个函数调用 run()函数。当然,您可以重命名所有的文件和函数,但是为了这个项目的简单性,我让它保持原样。
- 请随意粘贴我的功能并测试它。
- 单击“Test”应该会成功执行,否则,它会在对话框中显示错误。
3.在 AWS Lambda 中使用环境变量
你不应该在你的代码中把你的用户和密码留为明文,这就是为什么你应该总是使用环境变量!幸运的是,Lambda 也使用它们,并且可以很容易地用 python os 包调用它们。例如,在我的脚本中,我使用 os.environ['ALPACAUSER']调用用户变量。当向下滚动到代码编辑器下方时,可以在 Lambda 函数主屏幕中设置环境变量。
4.在指定的时间间隔触发 AWS Lambda 函数
无服务器和 AWS Lambda 的概念是建立在当触发事件发生时执行一个功能的思想上的。在我的设置中,我希望在交易时间(周一至周五)每隔 15 分钟调用一次该函数。幸运的是,AWS 使用 CloudWatch 服务提供了一种无需运行服务器就能触发事件的方法。
- 前往 CloudWatch ( 欧盟中央联系)。
- 在左侧面板中,选择“事件”和“规则”。
- 点击“创建规则”,并选择“时间表”而不是“事件模式”。在这里,您可以使用简单的“固定比率”对话,或者创建一个 cron 表达式。我正在使用https://crontab.guru/(免费)来创建 cron 表达式。我对上述用例的 cron 表达式是“0/15 13–21?周一至周五"。
- 在右侧面板中,选择“添加目标”并选择您的 Lambda 函数。它将自动添加到 Lambda 中。
- 最后点击“配置细节”,给它一个名字,然后点击“创建规则”。
5.(可选)日志分析、错误搜索
如果你做到了这一步,你就应该完成了!但是如果你想检查一切是否正常,你可以使用 CloudWatch 来查看 Lambda 函数的输出。前往 cloud watch-> Logs-> Log groups(EU central Link)并选择您的 Lambda 函数。在这个概述中,您应该能够看到函数的输出。
如果你喜欢这篇文章,请留下评论或者到我的博客 www.datafortress.cloud 来激励我😊。
如何在 AWS 上部署带芹菜的阿帕奇气流
原文:https://towardsdatascience.com/how-to-deploy-apache-airflow-with-celery-on-aws-ce2518dbf631?source=collection_archive---------1-----------------------
完全指南
图片由在 Pixabay 上的免费照片提供
免责声明:本帖假设基本了解 气流 、 AWS ECS、 (安全组等)和Docker。我建议一种架构,在您的特定情况下, 可能不完美,也可能不是最好的 。在这种情况下,从这个讲座中得到你想要的。
一点背景
在我工作的地方,我们广泛使用阿帕奇气流。我们大约有 15 个 Dag,看起来可能不多,但其中一些有许多步骤(任务),包括下载大型 SQL 备份、使用 Python 转换一些值并将其重新上传到我们的仓库。
我们的气流仪表板截图
起初,我们开始使用顺序执行器(没有并行性,一次只运行一个任务),因为设置简单,而且没有很多 Dag。随着时间的推移,dag 不断增加,其中一些提供了利用并行性的机会,因此对于一些配置,我们开始使用本地执行器。
利用并行设置的 DAG 示例
你可能会问……为什么整件事不再有用了?
这两种情况都只在 AWS ECS 中部署了一个容器来做所有的事情:服务于 web UI、调度作业和执行它们的工作进程。这不是可扩展的,我们唯一的选择是垂直扩展(你知道,添加更多 vCPU、更多 RAM 等等)。没有其他选择。
此外,如果容器中的某个东西失败了,整个东西都失败了(没有高可用性)。同样,整个服务必须是公共的,以便通过互联网访问网络服务器。如果你想使某些组件私有(如调度器和工人)这在这里是不可能的。
为什么要创建这个指南?
没有任何指南谈论如何在 AWS 中部署气流,或者利用他们广泛提供的服务。使用docker-compose
在本地或 EC2 中部署整个系统很容易,但是这真的是您想要的吗?在同一个 VPC 中,完全隔离的节点如何相互通信?把需要保密的事情保密,把需要公开的事情公开?
建筑
用 Lucichart 制作的建筑图
乍一看,这整个图表可能很复杂,甚至可能会让感到害怕,但是不要担心。由此你要了解的大概只是以下几点:
- 一个人只能通过入口连接到 Airflow 的 web 服务器或 Flower(我们稍后会谈到 Flower)。没有从外部到调度器、工作器、Redis 甚至元数据数据库的访问点。你不会想从外面连接那里。
- 一切都在同一个 VPC 内,让事情变得更简单。每个对象都有自己的安全组,只允许来自正确服务的连接。
- 一切都是 AWS Fargate 的任务,同样,我们稍后将讨论 Fargate。
我们将使用什么服务?为什么?
主要来说, AWS ECS 和 Fargate 是其中的明星。
Amazon Elastic Container Service(Amazon ECS)是一个完全托管的容器编排服务[…]您可以选择使用 AWS Fargate 来运行您的 ECS 集群,这是一个针对容器的无服务器计算。Fargate 消除了供应和管理服务器的需要,允许您为每个应用程序指定和支付资源,并通过设计应用程序隔离来提高安全性。
关于无服务器计算的一个很好的类比是我在这篇酷帖中读到的:
无服务器计算就像无人驾驶汽车;还有一个司机,只是你看不到。你不需要问司机是饿了、累了、喝醉了还是需要停下来上厕所。如果我们让无人驾驶汽车在我们的道路上行驶,那将是因为我们不必关心司机,只是他们会带我们去我们想去的地方这个事实——玛丽·布兰斯科姆
我喜欢说 ECS 只是一个 chill Kubernetes,不需要太多的配置,它可以使用 Docker 映像和一些额外的设置来部署您的应用程序,例如您希望您的应用程序能够使用多少 CPU 或 RAM,如果您希望自动扩展,使用开箱即用的负载平衡器等等。
我们还应该建立一个元数据数据库,为此我们将使用方便的 RDS。
指南
在做任何事情之前,我们必须设置我们将使用哪个 Docker 图像,并将其设置为基础图像以在其上构建。为此,我使用了普克尔的气流。这张 docker 图片为你提供了在 3 个主要执行器中设置气流所需的一切。下载量超过 500 万,可以肯定地说这家伙做得很棒。
Dockerfile 文件
让我们创建我们的自定义 docker 文件。我使用了以下方法:
我添加了一个个人的airflow.cfg
(包含 s3 日志和 SMTP 服务器凭证的配置)、一个自定义的entrypoint.sh
和一个包含我所有 Dag 的dags
文件夹。在这种情况下,已经使用指令WORKDIR
在基础图像中将.
定义为/usr/local/airflow
。
我的切入点如下:
我去掉了基本图像的入口点中的一些行,这些行是为不同的执行者服务的条件,并且只为芹菜做了这些行,还去掉了一个烦人的不工作的wait_for_port
函数。
这整个事情首先做的是,设置有用的环境变量,然后,根据docker run
中给出的命令,跟随一个执行代码不同部分的开关。比方说,如果您正在启动一个worker
,它将安装您的 Python 需求,然后执行 worker 进程。如果是webserver
,它也会安装需求,但也会用airflow initdb
命令初始化数据库,然后打开 air flow UI 的 web 服务器。
本地测试
如果你想测试整个事情,并确保一切正常,你可以用 Puckel 的 docker-compose 芹菜 YAML 文件来做。
过一会儿,你应该能够访问localhost:8080
并看到气流的仪表板。你还不如访问localhost:5555
和看花。从这一点出发,运行一些示例 DAGs 甚至是您的示例——并亲自看看 web 服务器中的触发器是如何处理事情的,调度程序抓取任务并将其发送到队列,最后,工作人员拾取并运行它。
上传 docker 图像
对于本教程,我们将保持简单,使用 AWS ECR。ECR 只是一个 Docker 图像库。
ECR 与 ECS 集成,开箱即用。
来源: AWS ECR
要创建存储库,请进入 ECR 控制台,点击创建存储库,选择您认为合适的名称。提示:您可以有一个用于暂存气流的存储库,一个用于生产。请记住,所有的气流过程都将使用相同的图像,以避免冗余和干燥。
我的 AWS ECR 截图
现在进入新的存储库,点击查看推送命令。这将引导您将气流图像推向回购。如果在第一步中出现错误,比如unable to locate credentials
您可能还没有设置您的awscli
凭证,请查看这个。
一旦您推送图像并在 ECR 控制台中看到它,您就为下一步做好了准备!
在 ECS 上部署服务
让我们从创建 ECS 群集开始,转到“Services ”,然后选择“ECS”。
可能因为这是你第一次,你会看到一个向你展示服务的屏幕和一个简单的第一个集群按钮。这里您需要做的只是创建一个纯网络集群。
AWS ECS 中集群创建的屏幕截图
此时,您可能会看到一个类似这样的窗口。这是您自己的选择,是使用与其余实例相同的 VPC,还是专门为该集群创建另一个——我选择了后者。如果您选择这样做,我认为一个子网就足够了。
设置数据库(如果您还没有)
我们将建立一个 PostgreSQL 9.6 微实例数据库。如果您熟悉如何做到这一点,请随意操作并跳到下一步。
转到服务-> RDS。转到数据库部分和创建数据库。选择 PostgreSQL 徽标,转到版本 9.6.X,任何次要版本都可以。现在,我仍然在考虑是否我非常便宜或者气流元数据数据库真的不需要那么健壮,所以我选择了一个自由层微实例。如果你发现这对你来说还不够,以后很容易升级,所以不要担心。
接下来的配置由您决定,无论实例名称、用户名、密码是什么,只要确保它将创建在 ECS 使用的同一个群集中。
创建任务定义
太好了,我们现在有空的星团了。让我们创建我们的任务定义。
任务定义就像蓝图一样,它们定义了您的服务将如何执行——它将使用哪个容器,分配给它多少 CPU 和 RAM,映射哪些端口,它有哪些环境变量,等等。
转到左侧面板的任务定义,点击创建新的任务定义。
AWS ECS 截图
记住,我们想要 Fargate,所以选择它并点击下一步。
AWS ECS 截图
从现在开始,我们必须为 web 服务器、调度器和工作器创建一个任务定义。
我将向您介绍您必须为每项任务正确工作提供的所有必要配置。
任务定义名称:标识名称。选择一些描述性的东西,如 airflow-webserver、airflow-worker 等。
任务角色:任务将要注入到容器中的 IAM 角色。选择一个对你的任务必须做的事情有权限的人——从秘密管理器提取秘密,用awslogs
日志驱动程序记录日志,从 S3 查询存储桶。如果你不确定,就使用基本的ecsTaskExecutionRole
,如果下拉列表中没有,请在此处检查。
网络模式: awsvpc
既然我们用的是 Fargate。
任务执行角色:能够从 AWS ECR 提取图像并登录 Cloudwatch 的角色。ecsTaskExecutionRole
这两种政策都有。
任务大小:几乎完全取决于你。你的大部分资源将花在工人身上,因此他们会做所有的脏活。只是提供一个指南,这些是我的配置:
Webserver: 1GB, 0.5vCPU
Scheduler: 2GB, 0.5vCPU
Flower: 512MB, 0,25vCPU
Worker: 3GB, 1vCPU
Redis: 2GB, 1vCPU
现在点击添加容器。右侧面板将会弹出。
集装箱名称:集装箱的标识名。
图像:ECR 存储库的 URL。例:1234567890 . dkr . ECR . us-east-1 . Amazon AWS . com/air flow-celery:最新。对于 Redis,使用:docker.io/redis:5.0.5
T21端口映射:对于 webserver 写 8080。对于花,5555。对于工人,8793-访问日志。对于 Redis,6379。
在环境部分,在命令中,根据您正在创建的任务选择webserver
、flower
、worker
或scheduler
。
你也可以利用环境变量!您可以使用value
来硬编码 env,或者使用valueFrom
来使用秘密管理器或 AWS 参数存储库。但是请不要在没有安全措施的情况下注入秘密。更多信息这里。
对于除 flower 之外的所有服务,您必须设置POSTGRES_
变量,记得我们在entrypoint.sh
中提到的那些变量吗?如果没有这些,服务在尝试连接到一个不存在的数据库时将会悲惨地失败。
对于调度器和工作器的任务定义,需要设置REDIS_HOST
。您可以像我在这里一样设置 IP 或内部 DNS。我们没有设置用户和密码认证,我不认为这是必要的,因为服务本身是私人的。尽管如此,请随意。
我们正式完成了任务定义!坚持住,从现在开始事情会变得更容易。。
启动服务
转到您的 ECS 集群,在服务选项卡中单击创建。
- 选择相应的任务定义。
- 写服务的名字: webserver,scheduler,workers 等。
- 对于 webserver、Redis、flower 和 scheduler,我们应该总是有一个任务。对于工人,我们想要多少就有多少,还记得横向缩放吗?
- 点击下一步。选取您的群集的 VPC 以及您想要使用的任何子网。
- 对于安全组,只需确保将名称更改为更容易识别的名称。比如:气流-web server-安全-群组。我们稍后会弄乱这些。
- 公有 IP:还记得第一张架构图吗?嗯,除非你不想使用负载平衡器/入口,否则所有服务都应该是私有的。
- 对于 webserver 和 flower,我们可以添加一个应用负载均衡器,作为弹性 IPs 的替代。为什么不能用 EIPs?目前不可能。要在 AWS 中设置 LB,参考此处的。
- 确认并点击创建!
- 每隔一个服务重复一次。
过一会儿,所有的服务都应该是这样的。不要担心,如果一些服务不工作。我们将在下一节整理出它们之间的联系。
连接—安全组
我们现在应该做的是确保每个服务从相应的来源接收信息。我们要设置他们的安全组。
一个安全组充当您的实例的虚拟防火墙,控制入站和出站流量。在 VPC 中启动实例时,最多可以为该实例分配五个安全组。安全组在实例级起作用,而不是在子网级。因此,可以将 VPC 子网中的每个实例分配给不同的安全组。–AWS 文档
以下是气流芹菜架构的官方文档:
来源
我将借用 Airflow 文档中的一些语句:
Airflow consist of several components:
**Workers** - Execute the assigned tasks
**Scheduler** - Responsible for adding the necessary tasks to the queue
**Web server** - HTTP Server provides access to DAG/task status information
**Database** - Contains information about the status of tasks, DAGs, Variables, connections, etc.
**Celery** - Queue mechanismThe components communicate with each other in many places
**[1] Web server –> Workers** - Fetches task execution logs
**[2] Web server –> DAG files** - Reveal the DAG structure
**[3] Web server –> Database** - Fetch the status of the tasks
**[4] Workers –> DAG files** - Reveal the DAG structure and execute the tasks
**[5] Workers –> Database** - Gets and stores information about connection configuration, variables and XCOM.
**[6] Workers –> Celery’s result backend** - Saves the status of tasks
**[7] Workers –> Celery’s broker** - Stores commands for execution
**[8] Scheduler –> Database** - Store a DAG run and related tasks
**[9] Scheduler –> DAG files** - Reveal the DAG structure and execute the tasks
**[10] Scheduler –> Celery’s result backend** - Gets information about the status of completed tasks
**[11] Scheduler –> Celery’s broker** - Put the commands to be executed
上述内容应在安全组中得到反映。
进入 AWS 中的 VPC 服务,选择安全组。在设置所有服务时,我要求您用一个合适的名称来标识它们,这样您可以方便地过滤它们并提供配置。
我的气流安全组的屏幕截图
从这里,选择每个组并设置正确的入站规则。以雷迪斯为例:
Redis 服务器运行在端口 6379 上(我们在任务定义中启用的端口)。架构图向我们展示了工作人员和调度人员应该可以访问它。我们还包括 flower 来检查经纪人状态。因此,我们为那些实例的每个源安全组包含了行。
来源
请记住,按照图表并相应地设置所有服务的安全组。这确保了应该被允许的服务之间的每个连接。如您所见,数据库应该接受来自每个气流过程的连接。
测试整个事情
测试很容易,只需访问 web 服务器和 flower。启动一个示例 DAG,看看在执行任务时,活动计数器如何快速增加和减少。
不要担心,如果有什么不工作,去检查失败的容器任务的日志并做一些研究,解决方案应该很快出现。
如果你仍然失败,很可能是你忘记做什么了(或者是我忘记告诉你了,哈哈)。欢迎评论,我会尽力帮助你!
如果一切顺利…
恭喜你!你成功了!
就是这个!你的气流集群准备好了!我知道我知道…这很长,甚至有点混乱,但是嘿!你成功做到了!👏👏😄。
照片由阿里·叶海亚在 Unsplash
这对我来说是一次漫长的旅行,我在建立自己的集群时经历了许多问题、错误和异常。我真的希望我的这份指南能让你少一些头疼。
在那之前,谢谢你,再见!👋👋👋
如何将 Docker 容器部署到云中
原文:https://towardsdatascience.com/how-to-deploy-docker-containers-to-the-cloud-b4d89b2c6c31?source=collection_archive---------2-----------------------
Docker 和 GCP 让与世界分享你的作品变得容易
Zoltan·塔斯在 Unsplash 上的照片
ocker 容器是很棒的小东西。它们本质上是独立的应用程序,可以在任何操作系统上运行。
假设您有一个 Python 应用程序,您将它与运行它所需的一切捆绑到 Docker 容器中——该容器现在可以在任何 Windows、Linux 或 macOS 系统上运行,无需安装任何东西!
Docker 的另一个好处是对云平台上的容器的支持,比如我们将在本文中使用的 Google Cloud (GCP)。
我们可以快速构建一个应用程序,使用 Docker 将其打包到一个容器中,然后使用 GCP 在全球范围内部署它。
这就是我们在本文中要做的。我们将采用一个简单的 Python API,用 Docker 打包,用 GCP 部署,涵盖:
**> Project Setup****> Dockerfile**
- FROM
- WORKDIR and COPY
- RUN
- CMD**> Building the Docker Image****> Deploy with Google Cloud Platform**
- GCloud SDK
- Cloud Build and Container Registry
- Cloud Run
项目设置
我们不会仅仅关注 Python 代码,因为这不是本文的目的。相反,带上你自己的代码——或者,这是我之前做的一些东西。
我们的 gcp-api 目录应该是这样的。
我们将代码存储在一个名为gcp-api
(你可以随便叫它什么)的目录中,命名为app.py
。除了我们的脚本,我们还需要:
- aDocker file——Docker 的使用说明书
- requirements.txt —一组 Python 模块,供我们的 docker 文件安装
当然,我们用的是 Docker,所以;我们也需要码头工人。可以从这里安装。
如果您在安装 Docker 时遇到任何特定于操作系统的问题,此视频中的 1:46:21 标记说明了 Windows 安装,随后是 macOS 的 1:53:22 标记。
Dockerfile 文件
docker 文件是我们的容器构建蓝图。它确切地告诉 Docker 如何以一种产生自包含应用程序的方式重新排列我们的脚本和文件。
就像盖房子一样。
兰迪·法特在 Unsplash 拍摄的照片
我们的脚本和文件是原材料(木材、砖块等)。).我们创建了一套我们希望我们的房子是什么样子的说明(Dockerfile),然后我们把它交给我们的建筑师(Docker),他然后做所有的技术工作来产生一个房子蓝图(图像)。
稍后,我们还将把蓝图交给我们的建造者(Google Build),他将为我们建造房子(容器)——但现在还不是时候。
我们的档案。看起来是这样的:
FROM python:3.6-slim-busterWORKDIR /app
COPY . .RUN pip install -r requirements.txtCMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 app:app
最初,它可能看起来令人困惑,但它非常简单。
来自 python:3.6-slim-buster
Docker 文件的第一行用另一个预构建的 Docker 映像初始化我们的容器映像。
这个预构建的映像本质上就是一个包含 Python 3.6 的轻量级 Linux 操作系统。
但为什么是【瘦身达人】?嗯, buster 是 Debian(一个 Linux 发行版)所有版本 10 变体的代号。
至于他们为什么选择“buster”这个词——我想有人打开字典,选择了他们看到的第一个词。
另一方面,斯利姆确实有道理。正如你可能已经猜到的,它意味着 Debian 10 . x——但是被削减了,导致一个更小的包大小。
官方 Python 图片的完整列表可从这里获得。
Firestore (NoSQL 数据库)通过谷歌的 Firebase 平台提供。图像来源。
警告: 另外值得注意的是,我们这里用的是 Python 3.6 你不需要坚持这一点,除非你将使用 Google Firebase(我们不会在这里使用,但意识到这一点是很好的)。
如果您碰巧在 Python 中使用 Google Firebase,您可能会使用 *python-firebase*
模块,其中包含一个名为 *async*
的导入。
不幸的是,Python 3.7 引入了这个词作为关键字。我们坚持使用 Python 3.6 来避免由此产生的语法错误。
工作目录和副本
接下来是WORKDIR
和COPY
。
我们使用WORKDIR
将我们的映像(我们的容器的构造站点)中的活动目录设置为/app
。从现在开始,我们映像外部的.
是指我们当前的目录(例如/gcp-api
),我们映像内部的.
是指/app
。
在WORKDIR
之后,我们COPY
从本地目录/gcp-api
到内部活动目录/app
的所有内容。
我们在图像中复制app.py
到/app
的原因是因为这是我们的谷歌云实例所期望的结构。我们可以改变这一点,但这是我们将在这里使用的。
奔跑
现在,我们有了自己的pip install
指令。我们使用RUN
告诉 Docker 运行下面的命令。下面的命令是pip install -r requirements.txt
。
通过编写pip install -r requirements.txt
,我们告诉 Docker 对包含在requirements.txt
中的每一行递归运行pip install
。
那么requirements.txt
长什么样?
pandas==1.1.1
gunicorn==20.0.4
flask==1.1.2
flask-api==2.0
当它被输入到我们的递归pip install
指令中时,它被翻译成:
pip install pandas==1.1.1
pip install gunicorn==20.0.4
pip install flask==1.1.2
pip install flask-api==2.0
我相信每个人都知道这一点。
煤矿管理局
根据我们的应用程序,我们的最终指令不是必需的。在这种情况下,它使用gunicorn
Python 包来托管我们的 API。
尽管如此,CMD
指令相当于打开我们计算机的命令行界面 CLI 并键入我们提供的任何命令,在本例中为exec gunicorn — bind :$PORT --workers 1 --threads 8 --timeout 0 app:app
。
建立码头工人形象
在本文的前面,我们描述了 Docker 容器的房屋建筑隐喻。到目前为止,我们已经获得了原材料(脚本和文件),并编写了一套说明,解释我们希望我们的房子是什么样的(Dockerfile)。
现在,是时候创建我们的蓝图了 Docker 图像。
我们可以通过执行以下命令来创建它:
docker build -t gcp-api .
- 这里,Docker 映像构建命令是
docker build
- 接下来,我们使用
-t
标志来指定我们的图像名称—gcp-api
- 最后,我们告诉 Docker 用
.
包含当前目录中的所有内容
此时,我们已经有了蓝图,现在我们需要的是我们的构建者——云——所以让我们开始设置它。
使用谷歌云平台进行部署
要将容器部署到云中,我们需要采取三个步骤。首先我们:
- 下载 Google Cloud SDK,我们将使用它来—
- 用云构建构建我们的容器。
- 将集装箱上传到 GCP 的集装箱登记处。
- 使用云运行部署它。
GCloud SDK
我们可以在这里找到 SDK 安装程序。安装完成后,我们需要通过打开 CMD 提示符(或等效的 CLI)并键入以下命令来验证我们的 GCloud SDK:
gcloud auth login
这个命令打开我们的 web 浏览器,并允许我们像往常一样登录到 Google Cloud。我们将 Docker 配置为将我们的 GCP 凭据用于:
gcloud auth configure-docker
最后,将活动项目设置为您的项目 ID(我的是medium-286319
),使用:
gcloud config set project *medium-286319*
云构建和容器注册
Google 的容器注册(GCR)服务允许我们存储 Docker 容器,我们可以将其用作部署的发射台。
我们需要一个现有的项目来部署我们的容器。图片作者。
在我们可以使用 GCR(或任何其他 GCP 服务)之前,我们需要创建一个项目。我们可以通过在 GCP 控制台中导航到项目选择器页面并点击创建项目来实现。
建立一个新项目非常简单。图片作者。
我们需要做的就是给我们的项目起一个名字。我用的是介质。
如果这是我们第一次在项目中使用 GCR,我们将需要启用 GCR API。图片作者。
现在我们有了项目设置;我们应该能够访问容器注册表。在这里,我们应该能够在顶栏中看到我们新创建的项目的名称。
要使用 GCR,我们需要点击控制台窗口中央的Enable Container Registry API。
最后,我们可以通过将容器提交到 Cloud Build——构建 Docker 容器的 GCP 服务——来将容器上传到 GCR。
为此,我们在项目目录(gcp-api
)中打开 CLI,并键入:
gcloud builds submit --tag gcr.io/[PROJECT-ID]/gcp-api
gcloud builds submit
将附加到我们当前目录的 Docker 映像提交到 Cloud Build——它将被打包到一个容器中。
我们的容器注册位置被提供给--tag
标志,其中:
*gcr.io*
就是 GCR 主机名 。*[PROJECT-ID]*
是我们的项目 ID;我们在创建我们的项目时看到了这一点——对我来说,它是*medium-286319*
。*gcp-api*
是我们的形象名称。
我们的项目 gcp-api 在容器注册表中。图片作者。
如果我们回到我们的 GCR 窗口,我们应该能够看到我们新上传的 Docker 图像。如果它还没有出现,很可能还在构建过程中——这可以在我们的云构建仪表板中找到。
云运行
现在我们已经准备好了 Docker 容器;我们可以用云运行来部署它。
使用云运行部署容器的分步过程。图片作者。
在云运行界面中,我们通过以下方式进行部署:(1)单击创建服务,(2)配置我们的部署,(3–4)选择容器,以及(5)创建我们的部署!
云运行中正在进行的部署。图片作者。
我们将在云运行控制台中看到部署状态,这应该不会超过几分钟。
完成后,我们的部署名称和区域旁边会出现一个绿色勾号和 URL。图片作者。
完成后,我们会看到部署名称旁边有一个绿色勾号,旁边有我们的部署 URL。
完成了的
就是这样,我们已经把我们的 Python 应用程序打包到 Docker 容器中,并使用 Google Cloud 将其部署到 web 上!
多亏了一些出色的工具——即 Docker 和 GCP——这个过程没有痛苦,并且(通常)一次又一次地导致完美的部署。
现在,比人类历史上任何时候都多。我们可以将脑海中的想法和概念在现实世界中有形地呈现出来——这可以产生一些真正令人惊叹的创作。
我希望这篇文章能帮助你们中的一些人——如果你有任何问题、反馈或想法,请随时通过 Twitter 或在下面的评论中联系。感谢阅读!
有兴趣了解云上的 SQL 吗?试试 Google 出色的 MySQL、PostgreSQL 和 SQL Server 数据库服务:
[## 使用 Python 在云上运行 SQL
Google 云和 Python 上的 SQL 简明指南
towardsdatascience.com](/sql-on-the-cloud-with-python-c08a30807661)
如何在谷歌云平台上部署可解释模型
原文:https://towardsdatascience.com/how-to-deploy-interpretable-models-on-google-cloud-platform-8da93f2e131d?source=collection_archive---------24-----------------------
获取生产张量流模型的本地和全球解释
图片来源于 Pixabay 。
由 Chris Rawles,Michael Munn 和 Michael Abel 发布。
现代机器学习和人工智能已经证明了在解决非常复杂的问题方面令人印象深刻的结果。然而,更复杂的问题往往意味着更复杂的数据,这必然导致更复杂的模型。真正理解一个模型为什么做出某种预测,可以和原问题本身一样复杂!
这可能会有问题,因为许多这样的 ML 系统已经影响到医疗干预、自主运输、刑事司法、风险管理和许多其他社会领域的用例。在许多情况下,这些人工智能系统的有用性和公平性受到我们理解、解释和控制它们的能力的限制。因此,相当多的努力和研究已经进入了解开强大而复杂的 ML 模型的黑盒,如深度神经网络。
可解释的人工智能指的是方法和技术的集合,这些方法和技术使人类能够理解为什么一个模型会给出特定的结果。模型可解释性是我们在谷歌云的高级解决方案实验室教给客户的一个关键话题,在这篇文章中,我们将展示如何使用谷歌云的可解释人工智能来部署可解释和包容的机器学习模型。
这篇文章中使用的所有代码都可以在这里找到。
可解释方法的分类
(事后)模型可解释性方法的概述和不同技术的例子。
大多数可解释性方法可以沿着三个轴分开[ 来源 ]:
内在与事后。所谓内在,我们指的是内在可解释的模型。也就是说,它们在结构上足够简单,我们可以通过简单地查看模型本身来理解模型是如何进行预测的。例如,线性模型的学习权重或通过决策树学习的拆分可用于解释模型做出预测的原因。
事后方法包括使用经过训练的模型和数据来理解为什么做出某些预测。在某些情况下,事后方法也可以应用于具有内在可解释性的模型。
在这篇文章中,我们将关注后特设模型的可解释性,因为许多先进的方法,如梯度推进和神经网络,是最好的理解使用这些方法。
模型不可知与模型特定。模型不可知意味着可解释性方法可以应用于任何模型,而特定于模型的方法只能用于某些模型类型。例如,如果该方法只适用于神经网络,那么它将被认为是特定于模型的。相反,如果一个可解释性方法将训练好的模型视为一个黑盒,那么它将被认为是模型不可知的。
局部与全局:局部可解释性方法旨在解释单个数据点或预测,而全局方法试图提供模型整体表现的综合解释。通过使用局部结果的集合,所有局部方法都可以变成全局技术。
在谷歌云上部署可解释的模型
你可以使用可解释的人工智能在 GCP 部署可解释的模型,并使用gcloud beta ai-platform explain
命令进行预测。
使用解释进行训练和预测的步骤是
- 训练一个模型并将其部署在 GCP 上。
- 将一个包含基线特征值的 JSON 文件上传到一个云存储桶。
- 使用这个 JSON 文件创建模型的一个版本,并指定
explanation-method
。 - 致电
gcloud beta ai-platform explain
获取解释。
下面我们将更详细地展示这些步骤。
首先,你需要一个在谷歌云人工智能平台(CAIP)上训练和部署的模型。我们将查看纽约市出租车数据集。你可以看看这篇博文,看看如何在 CAIP 轻松训练一个模特。在撰写本文时,AI 解释仅支持 TensorFlow 1.x,因此无论您构建什么模型,请确保您使用 TensorFlow 1.x。一旦您将模型保存为 SavedModel 格式,我们将在 CAIP 上创建一个新模型:
gcloud ai-platform models create taxifare
在部署我们的模型之前,我们必须配置一个explanations_metadata.json
文件,并将其复制到模型目录中。在这个 JSON 文件中,我们需要告诉 AI 解释我们的模型所期望的输入和输出张量的名称。
此外,在这个文件中,我们需要设置input_baselines
,它告诉解释服务我们的模型的基线输入应该是什么。理解基线对于许多模型解释技术的有效使用是很重要的。两种支持的技术,采样 Shapley 和综合梯度,将预测与基线特征值和预测进行比较。选择合适的基线很重要,因为本质上您是在比较模型的预测与基线值的比较。要阅读更多关于基线的内容,请查看可解释的人工智能白皮书。
一般来说,对于数字数据,我们建议您选择一个简单的基线,如平均值或中值。对于本例,我们将使用每个要素的中值-这意味着此模型的基线预测将是我们的模型使用数据集中每个要素的中值预测的出租车费用。
我们可以将这个 Python 字典写出到一个 JSON 文件中:
# Write the json to a local file
with open(‘explanation_metadata.json’, ‘w’) as output_file:
json.dump(explanation_metadata, output_file)
# Copy the json to the model directory.
然后在 bash 中,我们使用gsutil.
将 JSON 文件复制到您的模型目录中
$ gsutil cp explanation_metadata.json $model_dir
现在我们已经创建了我们的explanations_metadata.json
文件,我们将部署模型的新版本。这段代码非常类似于使用gcloud
创建模型版本的通常过程,但是有一些额外的标志:
gcloud beta ai-platform versions create $VERSION_IG \
-- model $MODEL \
--origin $model_dir \
--runtime-version 1.15 \
--framework TENSORFLOW \
--python-version 3.5 \
--machine-type n1-standard-4 \
**--explanation-method ‘integrated-gradients’ \
--num-integral-steps 25**
使用**解释方法
**标志,您可以指定解释方法——目前支持[integrated-gradients](https://github.com/ankurtaly/Integrated-Gradients)
和[sampled-shapley](https://christophm.github.io/interpretable-ml-book/shapley.html)
。
注意:在综合渐变和采样 Shapley 之间做出决定时,我们引用了白皮书:
一般来说,对于神经网络和可微分模型,推荐使用积分梯度。它提供了计算优势,特别是对于大的输入特征空间(例如,具有数千个输入像素的图像)。对于不可微模型,建议使用采样 Shapley,这是由树和神经网络的集成组成的 AutoML 表模型的情况。
此外,对于那些想知道采样的 Shapley 方法与流行的【SHAP】库有何不同的人,我们还引用了白皮书:
应用 Shapley 值的方法有很多种,不同之处在于它们引用模型、定型数据和解释上下文的方式。这导致了用于解释模型预测的 Shapley 值的多样性,
考虑到 Shapley 的唯一性,这是有点不幸的。Mukund Sundararajan 和 Amir Najmi 的《模型解释的多个 Shapley 值》中对该主题进行了全面的讨论。我们的方法属于基线 Shapley 类别,并支持跨各种输入数据模态的多个同步基线。
现在我们的模型已经部署好了,我们可以从 Jupyter 笔记本中获得本地属性:
*resp_obj = !gcloud beta ai-platform explain — model $MODEL \
— version $VERSION_IG — json-instances=’taxi-data.txt’
response_IG = json.loads(resp_obj.s)# Analyze individual example.
explanations_IG = response_IG[‘explanations’][0][‘attributions_by_label’][0]*
我们可以将这些加载到 Pandas 数据框架中,并绘制各个示例的属性:
*df = pd.DataFrame(explanations_IG)
df.head()*
*row = df.iloc[0] # First example.
row.plot(kind=’barh’)*
最后,我们可以通过聚集局部属性来获得全局模型可解释性:
*df.mean(axis=0).plot(kind=’barh’, color=’orange’)*
有关使用采样 Shapley 全局属性的更多信息,请参考本文。
结论
就是这样!在这篇文章中,我们展示了如何使用可解释的人工智能在谷歌云平台上部署可解释的模型。可解释的人工智能工具允许用户从已部署的模型中获得本地解释。这些解释可以组合在一起,以提供全局可解释性。除了上述步骤,您还可以查看假设工具来检查和解释您的模型。
额外资源
- 用谷歌人工智能平台解释模型预测
- 欺诈检测和可解释人工智能
- 谷歌人工智能可解释性白皮书
- 克里斯多佛·莫尔纳尔的可解释 ML
如何使用 Flask + Gunicorn + Nginx + Docker 部署 ML 模型
原文:https://towardsdatascience.com/how-to-deploy-ml-models-using-flask-gunicorn-nginx-docker-9b32055b3d0?source=collection_archive---------2-----------------------
一个配置 Flask + Gunicorn + Nginx + Docker 的模板,并附有详细的解释,这应该会让你更接近使用微服务、构建 MVP 等等。
吴伯毅 via flickr
开发一个好的机器学习模型可能很棘手,但即使有人成功做到了,在你部署它以便其他人可以访问它之前,它仍然几乎没有用处。
部署模型有很多方法,我想谈谈一个非常简单的适用于基本 MVP 的解决方案——用 Flask 为您的模型编写一个 API,用 Gunicorn 为应用服务器编写 API,用 Nginx 为 web 服务器编写 API,用 Docker 包装它,这样就可以更容易地部署在其他机器上(特别是 AWS 和 GCP)。
完整代码可以在 GitHub repo 中找到。
设置服务器
我更喜欢在我专门租用的服务器上用新配置做实验,而不是使用我的个人或工作硬件。这样,如果你把什么东西弄坏了,也没什么大不了的。我推荐使用 Linode 来实现这些目的,因为我个人在我的实验中使用它们,它们的硬件工作得很好。但是你可以随意使用任何其他服务,只要是在 LTS Ubuntu 18.04 上。
曼努埃尔·盖辛格
如果你决定使用 Linode,那么这一部分就是为你准备的。导航至 Linodes 并点击“添加 Linode”。有几件事你应该填写。在发行版中,我建议选择 Ubuntu 18.04 LTS 映像、区域—任何离你更近的地方(我使用法兰克福,DE)、Linode 计划— Nanode(每月仅花费 5 美元,但对于我们的目的来说已经足够了)、root password —你的密码,然后单击“创建”。一段时间后(大约几分钟),你可以进入“网络”,在那里你可以找到通过 SSH 访问你的服务器的信息。
我建议做的下一件事是连接到服务器并创建具有 sudo 特权的非 root 用户。该操作背后的逻辑相当简单:您不希望以 root 用户身份运行任何东西来扰乱服务器,因为这样更容易破坏东西。
adduser usernameusermod -aG sudo username
最后,切换到您的新用户:
su — username
创建应用程序容器
整个系统配置分为两部分:应用容器(Flask + Gunicorn)和 web 容器(Nginx web 服务器)。先说第一个。
步骤 0 —安装 Docker 和 Docker Compose
Docker 和 docker-compose 安装非常容易。它们分别在 4 行和 2 行中完成。因此,我建议遵循以下页面:
码头工人安装
让 Docker 无根运行
码头工人作曲装置
步骤 1 —创建 Flask 应用程序和 WSGI 入口点
在主目录中创建 flask_app 目录,并将以下文件放在那里。
这是最基本的 Flask 应用程序,几乎没有任何功能。我们不加载任何模型,不添加任何 GET/POST 请求之类的东西。那是以后的事。目前,我们只有一个在主页上显示“hello world”的应用程序。
这是一个非常简单的部分——我们只需为 Gunicorn 创建一个单独的文件,让它在端口 8000 上运行。
步骤 2 —为 Flask 创建一个 Docker 映像
现在,我们需要创建一个 Dockerfile 来使用这些文件,并创建一个稍后可以运行的映像。
对于那些不熟悉 Docker 的人来说,这个脚本的作用如下:导入 Python 3.6.7 图像,为所有文件设置工作目录,复制包含 Flask、Gunicorn 和运行 Flask 应用程序所需的所有内容的需求文件。之后,通过 RUN 命令安装来自需求的所有包,最后我们将所有文件从 flask dir 复制到容器内的 usr/scr/flask_app 。
现在你只需要把这个文件放在同一个 flask_app 目录下,并添加 requirements.txt 。在这种特殊情况下,这是非常基本的:
附言记住,如果你对目录之类的东西有点困惑,可以在文章末尾查看完整的项目结构,或者访问 GitHub repo。
步骤 3 —创建 Nginx 文件
为了运行 Nginx,您需要进行一些配置。但是在我们继续之前,在您的主目录中创建 nginx 目录(与 flask_app 在同一层)。之后,我们需要的第一个文件是 nginx.conf ,它包含了所有基本的 nginx 信息和变量。一个非常基本的 Nginx 设置示例:
第二个文件—我们特定应用程序的配置。有两种流行的方法可以做到这一点。第一种是在/etc/nginx/sites-available/your _ project中创建一个配置文件,然后创建一个指向/etc/nginx/sites-enabled/your _ project的符号链接。第二种方法是在主 Nginx 目录中创建一个 project.conf 。我们将采用第二种方法。
有几件事你应该注意。首先看一下听 80。这个命令指定了你的应用程序将在哪个端口运行。作为默认端口,我们选择 80。其次,服务器名。你可以指定你从 Linode 得到的 IP 地址,或者你可以只使用你的 docker 镜像名称。最后但同样重要的是,代理传递命令,将您的 Nginx 配置指向 flask 项目。由于 flask 容器名为 flask_app(我们稍后会用到它),所以我们只使用容器的名称,以及我们在 flask 项目中指定的端口。
步骤 4 —为 Nginx 创建一个 Docker 映像
这个特定的 Docker 图像相当简单。和 Flask 的情况一样,它也只包含 5 行代码,只做了两件事:导入 nginx 图像,复制我们的文件,并用默认文件替换它们。
步骤 5-用 docker-compose 组合 docker 文件
所以,现在我们有两个 docker 文件:一个用于 Flask + Gunicorn,另一个用于 Nginx。是时候让他们互相交流,运行整个系统了。为了做到这一点,我们需要 docker-compose。
我们需要做的唯一基本更改是在主目录中创建 docker-compose.yml 文件。
为了理解它是如何工作的,我们应该解决几个重要的问题。首先, docker-compose 拆分成 2 个部分(2 个服务): flask_app 和 nginx 。从下面几行可以看出,flask_app 容器执行 Gunicorn,guni corn 运行 flask 应用程序,并使用 1 个 worker 将其转换为 8000 端口。而第二个容器只是在 80 端口上运行 Nginx。另外,注意依赖于部分。它告诉 docker-compose 首先启动 flask_app 容器,然后才启动 nginx 容器,因为它们相互依赖。
实际上,我们还应该添加一个东西,这样就可以更容易地运行这个 docker 设置。那就是 run_docker.sh 文件
它只是运行 docker-compose,但首先确保此时没有旧的 docker 进程处于活动状态。
第六步——把所有东西放在一起
好的,请记住,当前的项目结构应该是这样的:
.
├── flask_app
│ ├── app.py
│ ├── wsgi.py
│ └── Dockerfile
├── nginx
│ ├── nginx.conf
│ ├── project.conf
│ └── Dockerfile
├── docker-compose.yml
└── run_docker.sh
确保一切就绪后,就该运行 docker 了:
bash run_docker.sh
通过导航到您从 Linode 获得的 IP 地址,在浏览器中查看主页:
第 7 步—我什么也没得到。我该怎么办?
嗯,首先在 Linode 租一个服务器,安装 docker 和 docker-compose,然后克隆 git 库,运行 bash run_docker.sh. 在你确定运行成功后,开始改东西。玩玩 Flask、Dockerfiles 或 docker-compose,直到你打破一些东西。之后,试着找出问题所在并修复它。
此外,如果你不精通 Flask、Gunicorn、Nginx 或 Docker,我强烈推荐这些教程:
初学者 Docker
学烧瓶
烧瓶+ Gunicorn + Nginx
第八步——好吧,我明白了。下一步是什么?
接下来要添加的是 Flask App 中的 POST 请求支持。这样,您可以向您的模型发送请求,并获得响应。所以,我们需要两样东西。第一个是处理请求的模型。第二— POST 请求支持本身。
为了简单起见,本例中的模型只返回颜色列表的第 I 个元素。但是运行的是哪种模型并不重要,只需在所有方法之上创建模型的实例()就可以了,这里有 server = Flask(name) 。
现在,如果您导航到您的 IP 地址,您将看到一条消息"模型已启动并正在运行。发送 POST 请求”,因为只是去 IP 就有资格成为 GET 请求。然而,让我们试着发送一个包含模型索引的 json 文件的 POST 请求。就我个人而言,我使用 Postman,但您可以使用任何您喜欢的名称(即 Curl)。
嘿,成功了!现在,您可以添加能够接收 GET/POST 请求的附加路由。这个想法背后的原因是,您可以加载几个模型,并根据 URL 向特定的模型发送请求。
第九步——更进一步怎么样?
实际上还有一件大事要做。为了部署这个 docker 设置,将它部署在云中可能是个好主意。例如,我建议看一看将 Docker 部署到 Amazon ECS 的。这种方法的主要优点之一是 AWS 将负责集群管理基础设施。
结论
我们已经用 Gunicorn + Nginx + Docker 在 Flask 应用程序中运行了一个模型。请注意,如果您有任何问题,请随时在评论、GitHub 问题或我的电子邮件地址 ivan.panshin@protonmail.com 联系我
如何利用人工智能平台大规模部署模型
原文:https://towardsdatascience.com/how-to-deploy-models-at-scale-with-ai-platform-fd1badf449ea?source=collection_archive---------35-----------------------
将机器学习模型部署到云中,并将其作为 API 提供给世界其他地方。
马里乌斯·马萨拉尔在 Unsplash 上拍摄的照片由作者编辑。
通常,当我们都开始学习机器学习时,我们会发现大量关于如何建立模型的信息,这当然是主题的核心。但是在数据科学的学术世界中,ML 还有一个同样重要的方面很少被教授,那就是如何部署这些模型。我如何与世界上的其他人分享我做的这件有用的事情?因为,在一天结束的时候…这就是我们工作的目的,对吗?让人们的生活更轻松😊。
在本帖中,我们将学习如何将机器学习模型部署到云中,并将其作为 API 提供给世界其他地方。
工作流程
我们将首先将模型存储在 Firebase 存储中,以将其部署到 AI 平台,我们可以在生产中对其进行版本化和分析。最后,我们将通过具有 Firebase 云功能的 API 来提供我们的模型。
图片由作者提供。
AI 平台是什么?🧠
AI Platform 是谷歌云平台 (GCP)的一项服务,通过不必担心维护自己的基础设施,让你只为使用付费,可以轻松管理整个生产和部署过程。这将使您能够为快速增长的项目大规模扩展您的产品。
你可以利用 GCP 的 12 个月、300 美元的免费试用来免费尝试这个和更多的实验。
什么是 Firebase 云函数?🔥
本质上,对于本文的目的,云函数将作为一个 API 工作。我们将通过一个任何人都可以提出请求的链接来提供我们模型的预测,并实时接收我们模型的响应。
你需要什么
- 一个准备分享✔的模型
- 一个谷歌账户✔
是的,就这些
入门指南
为了简单起见,我假设这个模型是用 Python 开发的,并且存在于一个 Jupyter 笔记本中。但是当然,这些步骤可以适用于任何其他环境。
1.登录 Firebase
首先,用你的谷歌账户登录到 Firebase 控制台,创建一个新项目。现在你在 Firebase 仪表板里面,进入项目设置 > 服务账户 > Firebase 管理 SDK ,(在这种情况下)你选择 Python 选项并点击生成新私钥。这将给出您的服务帐户的 JSON 文件,您可以将其保存在笔记本的目录中。
然后,安装 Firebase Admin SDK 包:pip install firebase-admin
2.燃料库中的存储模型
一旦你训练和测试了你的模型,它就可以上传到人工智能平台了。但在此之前,我们需要先将模型导出并存储在 Firebase 存储中,这样 AI 平台才能访问它。
如果您使用笔记本,在末尾创建一个新的单元格,并添加以下脚本。这将启用您的 firebase 帐户:
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore# Use a service account
if (not len(firebase_admin._apps)):
cred = credentials.Certificate(r'service_account.json')
firebase_admin.initialize_app(cred)db = firestore.client()
现在,要运行下面的代码,您需要获取项目 ID,您可以在 Firebase 项目设置中再次找到它。
一旦我们有了我们的项目 ID,我们就通过运行下面的代码来上传模型(您应该首先用您的项目 ID 来更改它)。
from sklearn.externals import joblib
from firebase_admin import storagejoblib.dump(clf, 'model.joblib')
bucket = storage.bucket(name='[YOUR PROJECT ID HERE].appspot.com')
b = bucket.blob('model-v1/model.joblib')
b.upload_from_filename('model.joblib')
print('model uploaded!')
现在,我们可以通过检查指定目录(在我们的例子中是model-v1/
)中的 Firebase 存储来验证模型已经被正确上传。
3.在人工智能平台中部署模型
现在模型已经存储好了,可以接入 AI 平台了。
我们需要在谷歌云平台中启用几个 API。在左侧面板上,在库部分中,我们找到 API“AI 平台训练&预测 API”和“云构建 API”并启用它们。
现在,在左侧面板上,我们点击人工智能平台>模型,我们创建新模型并输入相应的信息。
一旦我们创建了模型,是时候创建它的一个版本了,它将指向。我们之前存储的 joblib 文件。我们点击型号 > 新版本并填写信息。重要的是,我们选择用于训练模型的相同 Python 版本。我们选择 scikit-learn 作为框架。当指定它的版本时,我们可以通过在笔记本中运行下面的代码来获得它。
import sklearn
print('The scikit-learn version is {}.'.format(sklearn.__version__))
在选择 ML 运行时版本时,您应该选择推荐的版本。机器类型可以暂时默认保留。
最后,我们指定我们的所在的文件夹。joblib 文件被定位。重要的是选择文件夹,而不是文件!其余字段可以保留默认并保存。那时,我们模型的一个实例将被部署在人工智能平台上。
现在,我们将能够从命令行或其他 Google APIs 进行预测,如 Cloud Function,我们将在接下来看到。此外,我们将能够获得模型的一些性能指标。
4.创建云函数
让我们看看如何实现该功能!
我们将在终端上运行一些命令,但为此,您需要确保您的计算机上安装了 Node.js 。以下命令特定于 Windows,但是您应该能够在 Unix 和 Mac OS 设备中使用它们,方法是在每个命令的开头添加sudo
。
让我们从安装 Firebase 客户端开始:$ npm install -g firebase-tools
我们进入谷歌账户:$ firebase login
初始化一个新的项目目录(确保你在你想要初始化它的目录中):$ firebase init
运行最后一个命令时,将会询问您几个问题。当询问您想要在目录中包含的 Firebase 项目时,您必须选择包含我们之前导出的 ML 模型的项目。选择 JavaScript 作为编程语言。我们不使用 ESLint,所以回答否。最后,用 npm 安装依赖项,回答是。
创建项目后,目录将具有以下结构:
在这个目录中,我们将只修改 index.js 和 package.json 文件。
我们安装 Google API 的包:$ npm i googleapis
现在,我们通过打开 package.json 文件来检查软件包是否已经正确安装。如果你想在你的代码中使用任何其他的外部包,你也应该把它和它相应的版本一起添加到这个文件中。
目前,它应该具有类似于以下的结构:
"dependencies": {
"firebase-admin": "~7.0.0",
"firebase-functions": "^2.3.0",
"googleapis": "^39.2.0"
}
我将简要说明它们的作用:
- firebase-admin :它是管理 SDK,允许从特权环境与 firebase 交互。
- firebase-functions:这是一个定义 firebase 中云函数的 SDK。
- Google APIs:是 Google API 使用的客户端库 Node.js。
现在让我们看看函数的实现(我们正在编辑 index.js 文件),你也可以在这个 GitHub 库中找到。作为一个例子,我将使用代码访问一个简单的假账户检测模型。
我们首先加载 firebase-functions 和 firebase-admin 模块。
const functions = require('firebase-functions');
const admin = require('firebase-admin');
我们加载 googleapis 模块,并添加对 ml 版本 1 的引用。
admin.initializeApp(functions.config().firebase);
const googleapis_1 = require("googleapis");
const ml = googleapis_1.google.ml('v1');
这些请求将被发送到一个 http 函数。
exports.predictSPAM = functions.https.onRequest(async(request,response)=>
{
我们指定函数的输入值。在这个例子中,我得到了一些关于社交媒体账户的数据,我的模型将使用这些数据来分类虚假与否。您应该指定您计划随后输入到模型中的字段。
const account_days_old = request.body.account_days_old;
const followers_count = request.body.followers_count;
const following_count = request.body.following_count;
const publications_count = request.body.publications_count;
之后,我们构建模型的输入,也就是我们将发送给模型以获得预测的输入参数。请注意,这些输入应遵循与模型训练时相同的结构(要素顺序)。
const instance =
[[account_days_old,followers_count,following_count,publications_count]]
现在,让我们向 Google API 发出请求,这个请求需要认证,这将把我们的 Firebase 凭证与 Google API 连接起来。
const model = "[HERE THE NAME OF YOUR MODEL]";
const { credential } = await
googleapis_1.google.auth.getApplicationDefault();
在一个变量中存储了我们的模型的名称之后(这个名称应该与您在 AI 平台控制台中给它的名称相同),我们通过发送我们的凭证、模型的名称和我们想要预测的实例来对 AI 平台进行预测调用。
const modelName = `projects/[YOUR PROJECT ID HERE]/models/${model}`;
const preds = await ml.projects.predict({
auth: credential,
name: modelName,
requestBody: {
instance
}
});
response.send(preds.data['predictions'][0]);
});
5.将云功能部署为 API
一旦我们创建了访问模型的云函数,我们只需要将它上传到 Firebase,将其作为 API 进行部署。
为了上传 Firebase 函数,我们在终端中运行以下命令:$ firebase deploy --only functions
一旦完成加载,将获得一个 URL,通过该 URL 可以访问该功能,这可以通过登录 Firestore,在功能部分,在请求下以较小的字体找到。
就这样,现在你的模型已经建立并运行了,可以开始分享了!🎉🎉🎉
你可以从一个移动应用程序、一个网站向这个 API 发出请求…它可以被集成到任何地方!
6.用失眠测试你的 API
当然,这是一个可选的步骤,如果您遵循了前面的指南,您的模型应该准备好接收请求。然而,作为一名程序员,我喜欢测试东西,以检查一切工作正常。
我最喜欢的测试 API 的方法是使用失眠。失眠症是一个 REST API 客户端,它让您可以轻松地测试您的 API。这款免费的桌面应用适用于 Windows、MacOS 和 Ubuntu。让我们检查一下我们新做的 API 是否工作正常!
安装桌面应用程序后,我们可以创建新的请求。
我们将编写请求名,并选择 POST 作为方法,JSON 作为其结构。
一旦我们创建了请求,我们就复制云函数的 URL,并将其粘贴到顶栏中。
我们现在将按照我们在函数中指定的格式编写请求,在我的例子中,它是这样的:
{
"account_days_old": 32,
"followers_count": 162,
"following_count": 152,
"publications_count": 45,
}
我们现在点击发送,我们将得到响应,以及响应时间和大小。如果有任何错误,您也应该收到错误代码,而不是200 OK
消息。
当然,您得到的响应会因您的型号而异。但是如果一切正常,那么恭喜你!您已经准备好与全世界分享您的模型了!🌍
如果你做到了这一步,感谢你的时间,我希望你能从这篇文章中得到一些价值😊
下一集再见!🚀
将张量流模型部署到 Web
原文:https://towardsdatascience.com/how-to-deploy-tensorflow-models-to-the-web-81da150f87f7?source=collection_archive---------15-----------------------
如何使用基本的 JavaScript 在浏览器中运行 Python 构建的模型
Avi Richards 在 Unsplash 上拍摄的照片
用 Python 开发机器学习模型会是一种美妙的体验。Python 对 ML 和数据科学的支持和社区是任何其他语言都无法比拟的。
尽管如此,与非 Python 用户共享这些模型的方法非常少——对于我们大多数人来说,这描述了我们的大多数同事和最终用户。
另一方面,世界上几乎每个拥有电脑的人都有一个互联网浏览器。
幸运的是,我们只需要一个网络浏览器。
在本文中,我们将使用 Python 和 TensorFlow 创建一个简单的模型。我们将导出它,并将其部署到使用 JavaScript 和 TensorFlow.js 的 web 浏览器中——我们将保持它非常简单。要做到这一点,您不需要了解 JavaScript。
Python 部分
我们将使用一个基本的神经网络来告诉我们 0-10 之间的数字是奇数还是偶数。当然,我们不需要一个神经网络来做到这一点,但这意味着我们保持这个例子非常简单——没有任何错误。
这个模型需要一个数字作为输入,并产生一个数字作为输出。奇数会产生一个1
甚至一个0
。
首先,我们创建训练数据:
x = []
y = []
for _ in range(10000):
num = np.random.randint(0, 101) *# generate random integer*
x.append(num)
y.append(num % 2)
**x** =[2, 7, 4, 1, 9, ..., 0]
**y** = [0, 1, 0, 1, 1, ..., 0]
现在我们有了数据,让我们建立模型:
事实证明,模函数的表达具有惊人的挑战性。因此,神经网络确实包含合理数量的参数——训练后偶尔会告诉我们 10 是一个奇数——但它在大多数情况下是有效的。
现在我们保存它:
model.save('model_py/model.h5')
这将我们的模型保存为一个HDF5
文件——准备转换为TensorFlow.js
web 格式。
要转换模型,我们首先需要pip install tensorflowjs
。安装完成后,我们从命令行运行tensorflowjs_converter
(Command Prompt
、Terminal
、Bash
等)。).
打开命令行并导航到我们的项目文件夹(Windows 上的cd <directory_path>
)。然后通过键入以下命令运行转换器:
tensorflowjs_converter \
--input_format=keras \
model_py/model.h5 \
model_js
这里,我们告诉tensorflowjs_converter
期待keras
模型格式。然后我们指定模型路径model_py/model.h5
。最后,我们告诉转换器将转换后的模型保存在model_js
目录中。
如果我们导航到model_js we
,会发现以下内容:
那个.json
文件是我们的支持 web 的模型,可以在 JavaScript 中使用。
JavaScript 部分
服务器设置
首先,我们需要建立一个本地 web 服务器。由此,我们可以模拟一个网页的行为,它将包含我们的模型和用户前端。
最简单的方法是使用 Chrome 网络服务器应用程序。这是超级轻量级的,易于使用。
安装完成后,导航至chrome://apps/
并点击网络服务器图标:
这将启动 web 服务器,但可能不在正确的目录中。点击CHOOSE FOLDER
并导航到包含我们项目的目录:
现在,输入localhost:8887
应该会显示 chrome 中的同一个目录:
这意味着我们的服务器设置正确。如果localhost:8887
不工作,服务器很可能被托管在另一个端口上。要找到正确的地址,请查看 Chrome Web 服务器窗口中的Web Server URL(s)
列表,并单击给定的 URL。
构建页面
接下来,我们需要一个网页。首先,创建名为index.html
的文件。在其中,我们创建了一个form
来为我们的模型提供输入,如下所示:
<input type="text"></input><button>Predict</button>
当然,这还没有做任何事情。我们需要添加一些 JavaScript。
我们将编写两个函数,一个用于加载模型,另一个用于进行预测:
该代码可以通过包装在<script>
标签中嵌入到index.html
中。我们还需要导入tensorflow.js
——同样可以使用<script>
标签来完成。
将所有这些都写入代码会给我们带来:
最后一步是将我们在<input>
框中输入的内容连接到我们的模型。
我们可以通过在调用predict
时获取<input>
元素来做到这一点。为此,我们给<input>
一个惟一的标识符id="userInput"
,然后用这个标识符将元素拉进我们的带有document.getElementByID('userInput')
的函数中——这给了我们整个元素,所以我们通过在末尾添加.value
来指定值。
现在我们已经将用户给定值连接到我们的predict
函数,我们只需要触发它。我们简单的把onclick="predict(model)"
加到<button>
上。所有这些给了我们完整的代码:
这就是我们的 NN,运行在一个世界上任何人都可以使用的浏览器中。当然,除了告诉我们一个数字是奇数还是偶数之外,我们可能还需要一些东西——但是我们都是从某个地方开始的。
后续步骤
在此基础上,您还可以做更多的事情。你已经知道最难的部分——教机器学习。在这之后,你需要的只是一点点时间,足够的激情,你就能创造出一些令人惊叹的东西。
实际上,像我们在本文中所做的那样快速而直接地编写东西并不是您处理真实项目的方式。为了学习和简洁,我们跳过了许多步骤和最佳实践。
使用 Angular 或 Node 之类的框架(Python 的替代方案包括 Django 和 Flask)可以轻松构建交互式、快速、可伸缩的 web 应用程序。Bootstrap 是另一个神奇的工具,它可以让我们看起来很糟糕的网站变得漂亮,而我们几乎不需要付出任何努力。
我不能代表所有人,但是以我个人的经验,学习 Angular ,用 Bootstrap 设计 web 应用程序,会产生很好的效果——而且可以很快上手。
如果这是你想进一步探索的东西,我强烈推荐这两个。
我希望你喜欢这篇文章——如果你有任何问题或建议,请告诉我!
感谢阅读!
如何使用 Azure 部署 Web 应用
原文:https://towardsdatascience.com/how-to-deploy-web-apps-with-azure-52ca340b41b9?source=collection_archive---------19-----------------------
利用 Angular 和 Azure 应用服务快速轻松地部署应用
照片由卡斯帕·卡米尔·鲁宾在 Unsplash 上拍摄
azure——或任何其他云服务——让分享我们创造性劳动的成果变得前所未有的容易。
我们可以用 Angular(一个非常容易上手的框架)构建一个应用程序,并以比制作咖啡更快的速度将其部署到世界各地。
对我来说,这真的是惊人的。我们开发和部署的容易程度和速度令人难以置信。它解放了我们的创新精神,让我们可以在几分钟内与世界分享。
这篇文章将带我们经历从孤独的 Angular app 到高度可用、高度连接的 Angular app 的步骤。
我们将使用的所有服务都是免费的(感谢微软),而且——老实说——非常容易使用。简而言之,我们将涵盖:
>准备我们的 App
>设置我们的 Azure 应用服务
>使用 Azure DevOps 创建我们的部署管道
尽情享受吧!
准备我们的应用
首先,我们需要一个应用程序——如果你没有,没问题——我们可以使用自然语言生成应用程序,你可以在 GitHub 这里找到。
应用程序编译
*The* ***App Compilation*** *step is repeated in our Azure pipeline. It can be skipped now — but it is useful to be aware of, and useful to confirm that our app compiles.*
Azure 需要一个dist/
目录——这是一个 Angular 构建的分发目录——包含我们已编译并准备好用于生产的整个应用程序。
为了构建dist/
,我们打开 Angular CLI 并导航到我们的 Angular 应用程序目录。然后我们告诉 Angular 使用生产配置 和ng build --prod
进行构建——然后应用程序将编译到dist/
目录中。
显示 ng 构建过程的屏幕截图。
检查输出
我们需要确保我们的ng build --prod
命令将我们的应用程序直接输出到dist/
目录中。默认情况下,Angular 将分配给dist/<app-name>/
——我们在angular.json
中对此进行了更改:
在 angular.json 中,我们从" outputPath "中删除了我们的 app-name,留下了 "outputPath": "dist" 。
现在,在dist/
目录中,我们应该能够看到index.html
——如果它不在那里,找到它在哪里,并相应地调整angular.json
中的"outputPath"
值。
设置我们的 Azure 应用服务
首先,我们需要前往 Azure 门户网站——Azure 云的首页。如果你需要注册,那就去吧,只需要几分钟。
[## Microsoft Azure 门户| Microsoft Azure
从微软和我们的合作伙伴提供的 3,000 多种服务中进行选择,其中许多是免费的。找到打开的…
azure.microsoft.com](https://azure.microsoft.com/en-us/features/azure-portal/)
既然我们已经登录到门户,我们应该欢迎进入门户屏幕。如果这是你第一次使用 Azure,你将需要注册一个免费试用版(我们将坚持使用免费版,因此我们不会使用任何点数!).
我们通过点击类似于“从 Azure 免费试用开始”的大方块来注册。
注册后,我们会创建一个应用服务实例,如下所示:
一旦我们注册了免费试用,我们就可以通过点击上面突出显示的图标来创建一个应用服务实例。
在这里,我们需要为我们的应用程序键入一些细节。这些选项中的大部分将特定于您正在构建的内容——但是对于运行时堆栈,请选择ASP.NET 4.7 版,当然还要选择离您最近的区域:
我们的 web 应用程序详细信息—注意运行时堆栈。接下来讨论我们的应用服务计划。
接下来,我们需要选择我们的 Windows 计划 —如果您还没有计划设置,我们需要创建一个。选择创建资源组,按开发/测试找到自由选项,如下图:
资源组规格。
现在我们已经创建了我们的应用服务资源!我们可以通过点击左上角的按钮(三条水平线)并点击 All Resources 来查看我们所有的资源。
资源列表应该是这样的——应用程序服务本身是中间项。
然后我们可以通过在浏览器中输入<app service name>.azurewebsites.net
来浏览我们的网页。我们将看到:
使用 Azure DevOps 创建我们的部署管道
现在我们需要设置我们的 Azure DevOps 项目。为此,请转到 Azure DevOps,使用您在 Azure 门户中使用的同一 Microsoft 帐户登录。
登录后,您应该会在屏幕的右上角看到创建一个新组织的选项,单击此处。
然后我们将看到另一个窗口,在这里我们命名我们的组织并为我们组织的项目分配一个地理位置。我常驻罗马,所以选择了西欧。
在下一个屏幕上,我们可以创建我们的项目:
现在我们有了项目设置,我们需要连接我们的 GitHub 库并建立一个生产构建管道。
连接到 GitHub
要连接到我们的 GitHub 存储库,使用右边的工具栏导航到 Pipelines 区域,并单击 Create Pipeline 。
我们将被带到一个新窗口,Azure 将询问我们的代码在哪里——我们正在拉入一个现有的 GitHub repo,因此我们单击 GitHub 。
然后,我们授权 AzurePipelines 在下一个窗口中访问我们的 GitHub 帐户。
下一步是选择我们想要使用的存储库,对我来说就是jamescalam/nlg-project
——你可以使用自己的 repo 或者简单地派生这个。
现在我们需要批准&为我们选择的存储库安装 Azure 管道。
下一步,我们配置我们的管道,使用带有 Angular 的 Node.js,这将生成以下 YAML 脚本:
在脚本中,我们可以看到管道 YAML 设置的步骤。首先,第 6 行是trigger
——设置为master
——这意味着每当我们的 GitHub repo 中的主分支被更新时,我们的 YAML 脚本就会被触发。
接下来——在第 10 行——我们可以看到这将在运行 Ubuntu 的虚拟机(VM)上运行。然后我们在第 13 行看到,该脚本将 Node.js 安装到我们的虚拟机上。
最后,我们的 YAML 脚本安装 Angular CLI,然后使用我们之前创建dist/
目录时使用的相同方法构建我们的应用程序——这执行相同的功能(我们也可以在早期跳过这一步,但这对于确认应用程序编译无误非常有用)。
但是我们缺少最后一步,部署到我们的 Azure 应用服务。
要添加这个,在右上角找到展示助手——点击这个。现在我们将看到可以添加到 YAML 脚本中的所有任务的列表;我们需要 Azure 应用服务部署:
点击后,会出现一个表格。我们需要做的就是添加我们的 Azure 订阅(我的是这个奇怪的俄语文本——我不知道为什么),我们的应用服务名称,最后将包或文件夹改为dist/
。
现在我们将把 Azure App Service deploy 代码添加到我们的 YAML 脚本中——确保这被添加到脚本的末尾。因此,我们的 YAML 脚本应该包括:
trigger
pool
steps
- task (install Node.js)
- script (npm install Angular CLI and build app)
**- task (deploy to Azure App Service)**
我们单击“save ”,将更改提交给我们的回购。最后点击运行。
YAML 管道将需要一分钟左右的时间来运行。如果似乎什么都没有发生,并且作业状态停留在 Queued 中,刷新页面并允许管道在提示时使用您的描述。
完成后,我们的作业状态将变为 Success ,现在我们可以使用之前使用的相同网址<app service name>.azurewebsites.net
导航到我们部署的 web 应用程序,对我来说,这是meditations-ai.azurewebsites.net
。
使用由 Azure App Services 托管的自然语言生成器 web 应用程序。
我们做到了!
仅此而已——我们现在知道如何用 Azure App Services 部署 Angular 应用了。有一些技能并不太难学,但对我们能构建的东西有着巨大的影响——这是其中之一。
能够使用我们内置的 Angular 应用程序,并以比制作咖啡更快的速度与世界分享,这是非常了不起的。
如果这还不够的话,我们不仅部署了一个应用程序,还将它直接挂在了我们的 GitHub 上。
所以现在,每次我们想把我们最新发布的网络应用推向世界,我们只需输入git push
——对我来说,这太不可思议了。
我希望这篇文章对你和对我一样有用。我很乐意听到你的想法、问题或评论——所以请随时通过 Twitter 或在下面的评论中联系我们。
感谢阅读!
对更有棱角感兴趣?请随意查看我写的这篇关于构建基于 TensorFlow 的 Angular 应用程序的基础知识的文章:
[## 如何使用 Angular 部署 TensorFlow Web 应用程序
在角度构建的 web 应用程序中使用 Python 构建的模型
towardsdatascience.com](/how-to-use-angular-to-deploy-tensorflow-web-apps-5675b5a042cc)
如何使用 Streamlit 和 Heroku 部署您的定制 ML 模型
原文:https://towardsdatascience.com/how-to-deploy-your-custom-ml-model-with-streamlit-and-heroku-53456cb054fb?source=collection_archive---------30-----------------------
我的互动模型!作者图片
数据科学
一步一步的指导来主持你的模型!
我一直想把我的一些数据科学项目放到网上,这样我的模型就可以是交互式的,有更大的影响力。YouTube 上的数据教授 (Chanin Nantasenamat)有一个关于 Streamlit 的很棒的教程系列,这是一个开源的交互式数据应用平台,似乎提供了我正在寻找的一切!
TLDR: 这是我的最后一页!
所以我回到了之前的项目,根据电子健康记录预测糖尿病患者的住院需求(EHR)。我的 GitHub repo 包含原始建模的所有代码,以及在 Heroku 上托管的必要附加内容。
但是!我遇到了一个问题。甚至当我把一系列简单应用的指南和教程拼凑在一起的时候,我仍然无法将最终的应用部署到 Heroku!所以这里有另一个指南,希望这个能帮助你跟随我的脚步。
步骤 0 —所有传统的 CRISP-DM 步骤!
本指南从最终模型到托管。因此,我假设您已经完成了开发模型的尽职调查,从数据和业务理解到清理和 EDA,再到建模和评估。
第一步——腌制你的模型
腌制它!瑞卡·比罗-霍瓦特打开 Unsplash
我使用 scikit-learn 的 LogisticRegressionCV 开发了一个多元逻辑回归模型。它被称为 logreg_nopoly ,因为它没有包含多项式或交互特性。
**import** **pickle**pickle.dump(logreg_nopoly, open('diabetes_model.pkl', 'wb'))
您的腌泡模型应该在根目录中。
步骤 2-创建 web_app.py 文件
这是链接到我的文件。我的模型有 19 个特征,混合了分类特征和连续特征,所以我需要清理我的数据,并对用户输入的数据执行相同的转换(特征工程和 get_dummies)。
Streamlit 允许简单的降价风格的标题和文本,以及嵌入图像和图表。为了将数据输入模型以获得预测,您应该创建一个函数,允许用户为您的每个要素定义一个值。
对于连续变量:
st.sidebar.slider('名称',最小值,最大值,默认值)
num_medications = st.sidebar.slider('Num of Medications', 1, 79, 16)
对于分类变量:
st.sidebar.selectbox('name ',(' option1 ',' option2 ',…),其中包含该功能中的所有类别
gender = st.sidebar.selectbox('Gender', ('Female', 'Male'))
如何在 Streamlit 中对滑块和框进行编码的示例。作者图片
该功能的前半部分将创建用户将在应用程序上与之交互的各种滑块和框。这些可以是任何顺序。我将一些最有影响力的特性放在栈顶,以使改变预测的体验更容易。
如何创建实际输入数据帧的示例。作者图片
函数的第二部分是创建数据集特征名(键)和我们在上面为相应特征(值)创建的变量的字典。然后将它加载到熊猫数据帧中。这个字典应该按照原始数据中列的顺序排列,这样当我们连接时,我们的 input_df 和原始 df 匹配。
您会注意到,为了确保所有分类变量都以相同的方式编码(以便我们的 get_dummies 编码特性中所有可能的条目),我们需要在这个文件中执行相同的数据清理和特性工程步骤,并且我们需要将这个用户输入连接到数据集。
以一些特征工程步骤为例——这里是要检查的完整文件。在这里,我创建了一些二元特征来确定患者是否接受了 HbA1c 测试,以及他们的药物治疗是否有所改变。
# Feature Engineering
df['A1C_test'] = np.where(df.A1Cresult == 'None', 0, 1)df.change = np.where(df.change == 'No', 0, 1)df['A1C_test_and_changed'] = np.where((df.change == 1) & (df.A1C_test == 1), 1, 0)
然后,我们删除目标特征(“重新接收”),并在编码前连接用户输入。
X = df.drop('readmitted', axis = 1) # drop target feature
df = pd.concat([input_df, X], axis=0) # add user input to dfencode = [categorical_variables]
for col in encode: # encode all categorical
dummy = pd.get_dummies(df[col], prefix=col)
df = pd.concat([df, dummy], axis=1)
del df[col]
df = df[:1] # first row is user input
现在我们将读入我们的 pickled 模型,以便对用户输入进行预测!st.write 方法接受要显示的字符串,但它也将以本机方式显示 pandas 数据帧和系列。
load_clf = pickle.load(open('diabetes_model.pkl', 'rb'))
prediction = load_clf.predict(df)
prediction_proba = load_clf.predict_proba(df)readmitted = np.array(['NO','<30','>30'])
st.write(readmitted[prediction]) # writes value from array
st.write(prediction_proba) # writes probability of each value
第三步——在本地改进 Steamlit 应用程序
一旦处理好建模,您就可以在本地托管 Streamlit,并添加必要的降价来构建应用程序。
在您的终端/CLI 中
这将安装 Streamlit(如果尚未安装)并打开演示页面。
$ pip install streamlit
$ streamlit hello
现在您已经准备好了一个 web_app.py 文件(或者足够接近),可以在本地打开它进行实时查看和编辑。你应该在应用程序的根目录。
$ streamlit run web_app.py
一旦打开,任何时候你更新和保存。py 文件,Streamlit 应用程序将检测到这些更改,并可以设置为自动更新应用程序。
步骤 4-创建 Heroku 依赖项
因此,您的应用程序已经准备就绪,正在本地运行!太棒了。所以现在我们需要在这个根目录下创建一些文件来馈送给 Heroku。本节大量参考了本之前的指南,但是我已经更改了 setup.sh 文件的内容,因为最初的指南对我不适用。
Procfile
在 Jupyter 中,创建一个名为 Procfile 的文件。将此作为唯一内容粘贴。这告诉 Heroku 运行我们将要创建的 setup.sh 文件,并运行我们之前运行的 Streamlit 命令来运行我们的应用程序。
web: sh setup.sh && streamlit run app.py
requirements.txt
在 Jupyter 中,创建一个名为 requirements.txt 的文件。在这里,您可以指定必要的包及其版本,以确保您的应用程序不会因进一步的更新而中断。这是我的版本(因为我正在使用的模型,所以我需要 sklearn)。
streamlit==0.71.0
scikit-learn==0.23.2
setup.sh
在 Jupyter 中,创建一个名为 setup.sh 的文件,这个文件创建一个目录,设置 Heroku 在托管你的 app 时使用的一些变量,并存储在 config.toml 文件中(一种开源的配置文件格式)。
mkdir -p ~/.streamlit echo "[server]
headless = true
port = $PORT
enableCORS = false
" > ~/.streamlit/config.toml
第五步——Heroku!
从这里你可以跟随[汉密尔顿·张的原版导游](http://streamlit0.71.0 scikit-learn0.23.2)!他可以指导您加载文件、运行应用程序和部署应用程序。我只补充一个方面…
如何更新 Git 远程路径
Heroku 给你一个随机生成的应用程序名称。重命名应用程序部署后,您必须更新 Git 远程路径,以便您可以继续更新应用程序并推送更改。
首先,删除原来的 heroku 路径。然后,添加新的远程路径。我将我的应用程序命名为糖尿病住院(也就是我对我部署的应用程序的命名)。
$ git remote rm heroku
$ heroku git:remote -a diabetes-hospitalization
然后,您可以更新应用程序,并将更改推送到您的回购中!
$ git push heroku master
结论
希望这个指南是有帮助的,是最新的(!).这些步骤使我能够将模型的交互式版本发布到 web 上,供用户进行交互!你可以在这里参观和游玩。拥有一个你的项目的工作演示是将你的项目扩展到雇主的一个很好的方法,它表明你可以部署一个工作/健壮的模型。虽然 Streamlit 不是最强大的工具,但它的易用性和开源特性使它非常适合初学者项目。
连接
我一直在寻找连接和探索其他项目!或者让我知道本指南中的某些内容是否可以扩展/不适用!
LinkedIn|Medium|GitHub
如何在 Heroku 上部署 Dash 应用程序
原文:https://towardsdatascience.com/how-to-deploy-your-dash-app-with-heroku-a4ecd25a6205?source=collection_archive---------21-----------------------
与世界分享您的应用程序的分步说明
来源:https://unsplash.com/photos/xrVDYZRGdw4
你刚刚花了几周时间开发你的 Dash 应用。它现在看起来很棒,你想让全世界都看到它?本教程将向您展示如何使用 Heroku 做到这一点。
Heroku 是一个云应用平台,允许你运行你的应用程序,完全免费。
你需要什么
对于本教程,您需要安装一些东西:
- Heroku 账号:https://id.heroku.com/login
- 饭桶痛击:https://git-scm.com/download/win
- Virtualenv ,可以安装 pip:
pip install virtualenv
。
你还应该下载 4 个文件,都在这里:https://github.com/francoisstamant/dash_heroku_deployment。
App.py
是包含 Dash 应用程序的文件。如果你想更新/改进应用程序,你应该更改这个文件。
requirements.txt
包含运行应用程序本身所需的 Python 依赖项。
循序渐进教程
好了,现在你已经得到了所有需要的东西,下面是一步一步的教程,它会让你部署你的 Dash 应用程序给其他人看!
- 打开 Git。在那里,键入以下代码为项目创建一个文件夹,并将该文件夹作为当前目录。
$mkdir dash_app_deployment
$cd dash_app_deployment
2.用一个空的 Git 存储库和$ git init
初始化文件夹。
3.用$ virtualenv venv
创建一个名为 venv 的虚拟环境。
4.如果您使用 Git Bash 来激活环境,那么首先需要将 Scripts 文件夹作为当前目录。然后,就可以激活环境了。以下是命令:
5.然后,在虚拟环境中安装 Dash 和 Gunicorn:
$ pip install dash
$ pip install gunicorn
只是提醒一下,安装 dash 可能需要一段时间(对我来说大约需要 4 分钟)。
5.然后,确保将目录改回存储库,在本例中使用$ cd ~/dash_app_deployment
。
6.现在,确保前面的 4 个文件确实被复制到当前位置,一旦它们被复制,通过逐个添加它们来初始化文件夹,就像这样:
$ git add app.py
$ git add Procfile
$ git add requirements.txt
$ git add .gitignore
7.现在你可以用你想要的名字创建 heroku 应用程序。该名称需要唯一。如果名字不可用,它会让你知道。然后,您可以将代码部署到 heroku。
$ heroku create francois-st-amant-app
$ git add .
$ git commit -m 'Initial app template'
$ git push heroku master
8.最后,通过做$ heroku ps:scale web=1
在一个 dyno 上运行应用程序。Dynos 是运行应用/代码的“容器”。假设你想保持所有东西都是免费的,你可以运行 2 个 dynos,每个都有 512MB 的内存。
在步骤 7 之后,您的应用程序的 URL 应该是可见的。基本上会是 https:// 你的应用名 .herokuapp.com 。
这是我的应用:https://francois-st-amant-app.herokuapp.com/
你会注意到,如果你现在登录 Heroku 账户,你会看到你的应用页面。在那里,您可以管理应用程序设置、添加合作者等。
更新应用程序
要更改应用程序,只需修改 app.py 文件。然后,以下 4 个命令将允许您将更改推送到 Heroku 应用程序。
我希望这有所帮助。如果您有任何问题,请随时联系我们。感谢阅读!
如何部署你的第一个机器学习模型——第二部分
原文:https://towardsdatascience.com/how-to-deploy-your-first-machine-learning-models-part-2-9e1d0fcfb68?source=collection_archive---------45-----------------------
使用带有较少命令的 CircleCI 管道将机器学习 API 部署到 Heroku
照片由 timJ 在 Unsplash 上拍摄
在之前的文章中,我给出了根据行业最佳实践开发机器学习管道所需步骤的高度概述。在这一部分中,我将继续构建可访问的 REST-API 端点,并使用 CI/CD 管道将其部署到 Heroku 平台。
这篇文章中的大部分代码已经在第一部分解释过了。
Github 的项目回购如果你想跟进的话。
目录
- 开发 REST-api 包
- 定义所需的 circleci 配置
- 部署到 Heroku 平台
- 测试一个端点。
我们一个一个的分解一下,了解一下结构。
什么是 REST API?
REST 代表表述性状态转移(REST ),这意味着服务器将向客户机传送所请求的资源状态的表示。API 代表应用编程接口;在本教程中,我们不会构建一个完整的 REST-API;我们将开发一种预测服务。这是因为本教程的范围是为 ML 模型开发一个 REST-API。
为了理解 API 结构,这里有一个很好的资源,可以从头开始学习 API 和的创建,本指南和在这里。
作为一个软件架构的思维模式,你会专注于做出设计决策,使其易于更改、可扩展性,当然还有更少的错误。这就是使用 MVC(模型、视图、控制器)架构的好处,它在应用程序中模块化不同的功能,提供三个组件的抽象。让我们简要总结一下这三个组成部分:
- 视图:终端用户在与应用程序交互时的体验——界面。
- 模型:数据驻留和更改的位置
- 控制器:模型和视图组件之间的通信器。
MVC 模式的好处是:
- 模块化:每个部分都是独特的、封装的,并且可以在不破坏应用程序其余部分的情况下进行替换。
- 语言不可知——可用于多种语言,不仅仅是 python。
- 简单快速的开发过程。
- 可伸缩和可扩展。
如果你想了解更多关于 MVC 模式和软件工程中的其他模式,查看本指南和本指南。
第 1 部分是通过在 Gemfury 上以私人包的形式发布回归模型而完成的。在这一部分中,我们将使用这个包来处理数据并部署到 Heroku 平台。
我们首先在包主目录下创建一个名为 ml_api 的新包。包框架将包括以下内容:
包目录结构
ml_package 有三个主目录和其他 python 脚本文件。
requirements.txt :包含运行包的所有需求。
ml_api 包的 requirements.txt
这里没有什么新的,我只是包括了我希望使用的 flask 版本。此外,包括我在 gemfury 上发布的 regression_model 包——我提供了 index-url 变量,因为它是私有包,还没有公开。如果您希望在本地使用这个包,只需添加您的路径而不是我的路径,然后取消注释即可。我包含了用于模式验证的 marshmallow,以及用于部署的 gunicorn。
重要的是每个单独的包都有自己的需求文件。
如果您克隆了 Github repo 并遵循以下步骤,请确保在 ml_api 包目录中安装所需的依赖项。
-
app.py :这个文件就像 flask 应用程序的工厂,它通过一系列命令来创建 flask 应用程序和蓝图。这个蓝图负责创建位于控制器中的端点。
-
controller.py :该文件作为浏览器后端代码和前端的接口。所以,这个控制器有三个端点,健康、版本、v1/预测/回归。保持 API 版本化是一个很好的实践。
controller.py
- run.py :这将是启动应用程序的入口点。负责调用 create_app() 方法来启动应用程序。
run.py
在这个阶段,您可以尝试检查浏览器上的 API 端点。我们可以通过告诉 flask 启动 API 的入口点来做到这一点。在终端中,运行以下命令
FLASK_APP=run.py
然后从终端运行python run.py
执行 run.py 文件;现在您可以看到服务器已经启动并运行在 /health 端点的端口 5000 上。
在端口 5000 成功运行服务器,端点健康
更好地了解 Flask 微框架的资源:
-
链接 Python 装饰初级读本:https://realpython.com/primer-on-python-decorators/
-
烧瓶入门:http://flask.pocoo.org/docs/1.0/quickstart/
-
Flask Mega 教程:https://blog . miguelgrinberg . com/post/the-flask-Mega-tutorial-part-I-hello-world
-
烧瓶设计图:http://flask.pocoo.org/docs/1.0/blueprints/
-
烧瓶源代码:https://github.com/pallets/flask(可读性很强!)
-
Flask Web 开发:用 Python 开发 Web 应用程序
-
config.py :如果你是从 part#1 跟进的话,跟regression _ model包的逻辑是一样的。我只添加了一些配置对象来设置特定的 flask 属性。除了微框架使用的其他几个不同的标志之外,还将 development 设置为 true。
配置. py
-
版本文件:将版本添加到
__init__.py
文件中,以便能够调用版本。 -
validation.py :这将负责验证模式;模式是数据的一种表示。在这里,它表示我们将接收到 API 的输入。关于模式优先 API 设计方法的争论越来越多。虽然有一种观点认为模式应该存在于模型包中,但是我们在这里使用它来定义 API 契约,这在这里是有意义的。
验证. py
我们实例化了模式,然后将输入数据转换成正确的格式。之后,加载输入数据并对模式进行检查,以确保没有错误。如果在验证检查过程中出现问题,它只会引发一个验证错误。
使用容器 Docker 映像进行部署
这些步骤如下:
- 安装 docker。
- 通过 Circleci 配置 Docker
- 通过 Circleci 将 docker 映像部署到 Heroku。
这看起来有点吓人,但是一旦你有了这个想法,这将是一个简单的任务。所以,让我们开始吧!
什么是容器?
容器是软件的标准单元,它将代码及其所有依赖项打包,以便应用程序能够从一个计算环境快速可靠地运行到另一个计算环境。
Docker 是什么?
Docker 是一个让创建、部署和运行容器变得简单的工具。Docker 容器是软件开发的标准化单元,包含软件应用程序运行所需的一切。这包括代码、运行时、系统工具、库、依赖等。
以上所有这些看起来都很好,很新奇,我为什么要使用它们呢?
容器自 2013 年发现以来变得如此受欢迎,因为它们提供了可再现性。这是一个巨大的好处,因为你确切地知道创建一个给定容器的步骤,容易跟踪错误。此外,它比虚拟机更快、更轻量级。易于与 CI/CD 管道一起使用。
1.安装 Docker
你可以导航到 docker 并按照步骤将其下载到你的本地机器上。
2.Dockerfile 文件设置
因此,我们想要创建的是一个基于 linux 的容器映像,这就是为什么大多数命令都是 linux 命令。
- Dockerfile:它拉下所需的 python 版本镜像,指定工作目录,安装需求,设置服务器端口。
Dockerfile 文件
- run.sh :这个 shell 脚本负责运行 guicorn 来启动 flask 应用程序。
run.sh
- dockerignore: 在构建映像后告诉 docker 忽略哪些文件。
。dockerignore
建立码头工人形象
现在我们已经准备好构建图像了;为此,如果您在 OSX/莱纳斯,我们需要在终端中运行以下命令:
prediction_app $ docker build --build-arg PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL} -t YOUR_APP_NAME:latest .
重要提示:如果您希望首先在本地机器上构建映像作为测试,您可以使用
.env
文件在本地定义 PIP_EXTRA_INDEX_URL。否则,下面的命令将抛出一个错误,即它无法获取所需的包,回归模型。
In the above command, just replace ${PIP_EXTRA_INDEX_URL} with yours if you wish to build locally before doing so through the circleci pipeline.
构建映像的快照
您可以通过在终端中使用docker images
来检查图像是否已成功构建。它将列出在您的本地机器上构建的所有 docker 映像。
一些有用的 docker 命令:
- 建造一个集装箱— 参考
docker build --build-arg PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL} -t YOUR_APP_NAME:latest .
2.运行 docker 镜像— 参考
docker run --name YOUR_APP_NAME -d -p 8000:5000 --rm YOUR_APP_NAME:latest
3.查看正在运行的容器:
docker ps
4.查看容器日志(通过运行docker ps
获得容器 ID)—引用
docker logs CONTAINER_ID — tail
和 docker 一起部署到 Heroku
Heroku 是一个基于云的平台即服务,允许开发人员完全在云中构建、运行和操作应用程序。
实现应用程序所需的步骤有:
- 如果您没有帐户,请浏览 heroku 网站并创建帐户。
- 导航至
New
菜单并创建新应用,填写应用名称并选择地区,然后点击创建应用。 - 安装 heroku-cli 工具,确保保留默认设置,以便 heroku 被添加到您的系统路径中。
- 安装后重新启动命令行工具。
- 通过
heroku login
使用 cli 工具登录 heroku 账户,输入你的邮箱和密码,你就可以登录 heroku 平台了。
Heroku 构型
为了能够部署,您需要将 PIP_EXTRA_INDEX_URL 变量添加到 heroku 项目设置中的 config vars 列表中。
为此,导航至应用程序设置→显示配置变量→
关键字:PIP_EXTRA_INDEX_URL
值:your_token@pypi.fury.io/user_name/→添加。
现在是时候配置部署管道了,以便在每次提交到远程时自动执行部署。
为此,我们将从以下方面着手:
- 根据 heroku 指令创建过程文件。这个文件负责运行应用程序和访问错误日志文件。
web: gunicorn --pythonpath packages/ml_api --access-logfile - --error-logfile - run:application
2.确保regression-model = = 1 . 0 . 0和 gunicorn==19.9.0 都被导入到 ml_api 目录下的需求文件中。
3.创建负责捕获主分支上最新变更的提交 id 的 Makefile,然后创建一个 remote,最后将工作推入 heroku。
生成文件
- config.py 将所需步骤添加到 circleci 配置文件——第 10 节和第 11 节。它基本上设置了部署所需的步骤,从重新安装需求到捕获新的依赖项,再到设置 heroku remote 并进行部署。最后,指定管道的工作流,在训练模型之后应该在哪里进行部署——逻辑步骤。
页(page 的缩写)n:在第 114 行,我设置了
docker_layer_caching: false
,因为在运行 circleci 时将它设置为 true 会出错。您需要升级您的飞机才能将此设置为真。
完整配置文件
现在,当您将更改提交到 github 时,应用程序应该会自动部署到 heroku 平台。
测试 API
你可以导航到 heroku dashboard 并从那里打开应用程序,或者使用像 postman 这样的工具来确保 API 正在工作。
使用 postman 测试 API,为 GET 动词返回 200 状态代码
工作应用 JSON
circleci 仪表板工作流程
注意,我们只有两个端点,健康和版本。一旦确认一切正常,就可以添加额外的端点。这种方法非常有用,从简单开始会更容易捕捉错误和 bug,从而在调试会话中花费更少的时间。
总结和结论
在这一部分中,我们探讨了许多关于 API 设计的概念,以及如何自动化这个过程以节省时间。这个项目为您提供了一些构建产品级应用程序的最佳实践。此外,它还让您领略了 SLCD 的实际工作流程——机器学习模型的软件生命周期开发。有问题就问吧;我很乐意帮忙!快乐学习!
如何在 Kubernetes 上部署你的机器学习模型
原文:https://towardsdatascience.com/how-to-deploy-your-machine-learning-models-on-kubernetes-36e260027ce1?source=collection_archive---------19-----------------------
使用 GCP 的 Kubernetes 和 Terraform 部署、扩展和管理您的机器学习服务。
Guillaume Bolduc 在 Unsplash 上拍摄的照片
Kubernetes 是一个生产级的容器编排系统,它自动化了容器化应用的部署、扩展和管理。该项目是开源的,并通过谷歌运行的关键任务应用程序进行了测试。
机器学习解决方案通常被分解成许多步骤,这些步骤可能与操作系统和框架无关。此外,数据科学项目通常遵循数据流编程范式,其中程序被设计为一个有向图,数据从一个操作移动到下一个操作。这些方法和抽象很容易用 Kubernetes 实现,将基础设施管理的负担留给了系统。
在这个故事中,我们将在 Kubernetes 上部署一个简单的图像分类器 web 服务。我们将在谷歌云平台(GCP)上工作,并利用他们的安全和管理的 Kubernetes 服务产品:GKE。我们将首先使用 Terraform 来供应和管理所需的基础设施,然后创建一个预训练 PyTorch 模型的简单部署。我们开始吧。
学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!
基础设施作为代码
为了建造所需的基础设施,我们将使用 Terraform。Terraform 将基础设施视为代码,以供应和管理任何云、基础设施或服务。Terraform 将使我们很容易创造我们需要的资源,并在我们完成后进行清理,以避免积累成本。要安装 Terraform,请遵循您的平台的说明。
预赛
要处理 GCP,我们首先需要创建一个项目资源。项目资源是一个逻辑组织实体,它是创建、启用和使用其他 Google 云服务的基础。有必要开始对 GCP 和容易建设一个或使用任何新的 GCP 帐户初始化默认项目的工作。
要创建一个新的,从侧面板转到IAM & Admin
并选择底部的Manage Resources
。按下Create Project
按钮,给出一个名字,你就可以开始了。
下一步是创建一个服务帐户,terraform 将使用它来创建我们需要的资源。服务帐户是一种特殊的帐户,由应用程序使用,而不是由个人使用。确保您正在使用您创建的项目,返回到IAM & Admin
选项并选择Service Accounts
。按下按钮Create Service Account
创建一个新的,将其命名为terraform
并按下 Create。下一步,授予服务帐户Project Editor
的角色,然后按 continue。最后,通过按下Create Key
按钮生成一个 JSON 密钥。该密钥将成为 Terraform 的身份验证方法。
地形结构
首先,我们需要配置 Terraform 使用 Google 存储桶来存储它需要的元数据。这是保持 Terraform 在自动化环境中运行的一个很好的方法。首先,让我们创建桶;创建一个名为main.tf
的新文件:
然后,我们需要为它使用的变量创建一个新文件。创建该文件并将其命名为variables.tf
:
这个文件告诉 Terraform 应该使用哪些变量,并提供了一些默认值。例如,我们第一个脚本中的location
变量现在有了一个默认值US
。还有其他变量,比如project_id
,我们需要自己提供值。为此,我们创建一个新的terraform.tfvars
文件:
确保用必要的信息填充terraform.tfvars
文件,然后运行terraform init
和terraform apply
。最后,转到 GCP 控制台,验证铲斗是否在那里。
改造您的 GKE 集群
我们现在准备剥离我们的 Kubernetes 集群。我们将在一个新目录中创建三个单独的文件:一个用于定义 Terraform 后端,一个用于云提供商,一个用于实际的集群。当然,我们需要两个额外的变量文件。让我们设置后端。创建一个terraform.tf
文件,并将以下内容复制到其中:
确保提供您之前创建的存储桶的名称。然后为云提供商创建一个provider.tf
文件:
最后,创建一个main.tf
文件来配置我们想要的 GKE 集群。对于这个例子,我们将把它保持在最低限度。
我们将改变的一件事是删除默认的节点池并创建一个我们自己的节点池,其中我们使用n1-standard-1
可抢占的机器。最后,创建variables.tf
和terraform.tfvars
文件,提供必要的变量。
和terraform.tfvars
文件:
将位置设置为区域格式将创建一个区域簇。谷歌为每个付费账户提供一个免费的区域集群,因此我们将利用这个折扣。像以前一样,运行terraform init
和terraform apply
,等待几分钟,您的集群将准备就绪。
图像分类器
对于这个例子,我们使用一个预先训练的 PyTorch 模型和 Flask ,来创建一个简单的机器学习 web 服务。接下来,我们将创建一个简单的 Kubernetes 部署来部署、管理和扩展 web 服务。
PyTorch +烧瓶
为了设计一个简单的图像分类器服务,我们使用了一个用于图像分类的 CNN 模型 AlexNet 的 PyTorch 实现。我们使用烧瓶微型框架来提供它。
首先,我们定义一个Predict
Flask 资源,它初始化模型并接受一个HTTP POST
请求。我们使用any-host
标识符(0.0.0.0
)将它与烧瓶一起提供。
Flask 的内置服务器不适合生产,因为它的伸缩性不好。对于我们的目的是好的,但是如果你想知道如何正确地部署 Flask 应用程序,请看这里的。
集装箱化
要在 Kubernetes 上部署它,我们首先需要将服务容器化。为此,我们定义如下Dockerfile
:
要从这个Dockerfile
构建一个映像,在同一个文件夹中创建一个requirements.txt
文件,包含以下内容:
flask
flask-restful
在同一个文件夹中下载包含 Imagenet 标签的 JSON 文件这里。我们现在准备建立我们的 docker 形象;运行以下命令:
docker build -t <your-dockerhub-username>/image-classifier:latest .
最后,您需要将映像推送到容器注册中心。例如,要在 docker hub 上推送它,创建一个帐户,配置 docker 并运行以下命令:
docker login --username usernamedocker push <your-dockerhub-username>/image-classifier:latest
为了简单起见,你可以用我为你准备的图像。可以从 docker hub 拉出来。
部署
最后一步是部署。为此,我们使用一个简单的YAML
配置文件。但是首先,我们需要安装kubectl
并获得连接到我们的集群的凭证。
要安装kubectl
,请遵循平台的说明。接下来,安装 gcloud
,GCP 的 CLI 工具。要获取 GKE 群集的凭据,请运行以下命令:
cloud container clusters get-credentials <the-name-of-your-cluster> --zone <the-zone-that-it-is-in>
例如:
cloud container clusters get-credentials my-gke-cluster --zone us-central1-a
该命令将创建一个配置文件,并指示kubectl
如何连接您的 GKE 集群。最后,定义图像分类器YAML
部署文件。
这个配置分为三部分:首先,我们定义一个名称空间,它为我们的资源名称提供了一个范围。然后,我们定义实际的部署,其中我们只使用服务的一个副本。你可以根据自己的需要调整这个数字。最后,我们用一个LoadBalancer
来公开我们的 web 服务。这将使我们的服务可以从互联网上访问。通过运行以下命令创建部署:
kubectl apply -f image-classifier.yaml
您现在已经准备好测试您的图像分类器 web 服务了。对于这个例子,我们使用curl
。
curl -X POST -d '{"url": "[https://i.imgur.com/jD2hDMc.jpg](https://l.messenger.com/l.php?u=https%3A%2F%2Fi.imgur.com%2FjD2hDMc.jpg&h=AT3BE3ChNWH0HYFPvWjWK_Aqtq08m0_DGLZpxfwEu_219IP625hqKCAjWzfap2ucsTFqtwk224-0Djl3nFCbpbxixNC4XgclqUkdsR9kOzTEkVVjazQJx395DGlzq3offB8i10LHlveiqg)"}' -H 'Content-Type: application/json' [http://<your-cluster's-ip>/predict](http://35.239.113.2/predict)
这个命令将使用一个小猫图片查询您的服务。你得到的是与某种自信相关的预测。您现在已经在 Kubernetes 上成功部署了一个机器学习模型!
清理
为了清理我们自己,我们将按相反的顺序进行:
- 删除命名空间、部署和负载平衡器:
kubectl delete -f image-classifier.yaml
2.销毁集群:
terraform destroy
从您在“改造您的 GKE 集群”步骤中创建的文件夹中运行此命令。
3.删除 Google 存储桶:
terraform destroy
从您在“地形配置”步骤中创建的文件夹中运行此命令。
结论
在这个故事中,我们看到了如何在 GKE 用地形创造资源。具体来说,我们创建了一个 GKE 集群,以利用 Google 云平台提供的托管 Kubernetes 解决方案。然后,我们创建了一个简单的图像分类 web 服务,用它构建了一个 docker 图像,并将其部署在 Kubernetes 上。最后,我们自己清理,销毁我们不再需要的资源,以避免额外的成本。
Kubernetes 是一个为生产部署机器学习模型的伟大平台。在后面的文章中,我们将探索 KubeflowKubernetes 的机器学习工具包。
我叫 Dimitris Poulopoulos,是希腊比雷埃夫斯大学BigDataStack和博士(c)的机器学习研究员。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲中央银行、经合组织和宜家等主要客户设计和实施人工智能和软件解决方案。如果你有兴趣阅读更多关于机器学习、深度学习和数据科学的帖子,请关注我关于 中 、LinkedIn或@ james2pl上
如何将您的 ML 模型部署到浏览器中
原文:https://towardsdatascience.com/how-to-deploy-your-ml-models-into-the-browser-f52ea62bfa60?source=collection_archive---------36-----------------------
来自 TensorFlow 的 jS 哥哥的嗨
以及如何有效地做到这一点。
当我刚开始学习 AI 和 ML 时,我经常会有这样的问题:我为什么要学习这个?在找到工作之前,我能有所作为吗?
这些问题出现是因为我知道如何训练模型,但不知道 如何部署 。因此,如果你正处于这个阶段,并且想学习如何使用模型,那么你来对地方了!
我是谁
我是 Dweep,一个充满热情的高中生,从各种课程和项目中获得了许多深度学习知识。
认识一下 TensorFlow 的哥哥 TensorFlow.jS
我们都知道 TensorFlow,以及如何在 TensorFlow 中制作模型(如果你不知道,那么我会推荐你阅读这篇博客,然后回到这里。)然而,它的 javaScript 兄弟却是相当的鲜为人知。但这并不意味着 TensorFlow.jS(也称为 tfjs)就没那么有用。大部分 TensorFlow 模型可以直接转向 tfjs 模型,tfjs 本身也有能力训练模型!
关于你下一步要做的事情
我深信代码是学习代码的最佳方式。因此,在本文的最后,您将在浏览器上实现一个 tfjs 系统。顺便说一下,我从 Coursera 上的数据和部署专业化的第一门课程中学到了大部分内容,我在这里回顾了一下。因为 tfjs 最常见的用例是迁移学习,所以您将实现它。
为了使尽可能与 tensor flow相关,我将首先解释 TensorFlow Keras 库和 tfjs 层库之间的关系。
代码风格的显著差异
就像 Keras 构建在 TensorFlow 库之上以提供高级功能一样,Layers 库也为 tfjs 做了同样的事情。
忘记下划线
所有的 jS 代码都在lower case中,这意味着所有的一切都应该有小写的第一个单词的第一个字母(像 l ),以及大写的第一个单词(像 C )。所有的函数和语法都遵循这个规则。因此,我们应该使用 inputShape 而不是 input_shape 。此外,所有语法都以分号结尾。
数据到张量
由于 javaScript 没有 NumPy,所有数据都需要转化为张量,供 tfjs 进行推理或训练模型。
使用{ }进行配置
另一个显著的区别是,与 Python 不同,所有的函数输入都在花括号内配置。一个例外是当你输入数据时,比如训练集。
还有一些差异,但我认为这些就足够了。
基本语法
下面列出了最常用的函数。要了解其中任何一个函数的更多信息,只需单击该函数的名称。我建议你对每一个都这样做,以便更好地理解。
- TF . tensor(data,shape)创建一个张量,tfjs 稍后可以使用它进行训练或推理,并将其保存在分配给该函数的变量中
- TF . sequential()创建由一系列层组成的模型。该模型保存到一个 const 或常量变量中。**
- TF . layers . dense({单位:_ _ _ _,激活:' _ _ _ _ _ _ '})创建一个 tfjs 图层,可以使用 model.add() 添加到模型中。注意,像 TensorFlow 一样,第一层有一个可选的附加输入,称为 inputShape ,它将进入模型第一层的配置内部。
- model . add()获取一个 tf.layers 图层,并将其添加到模型中现有的图层列表中。也可以使用 tf.layers.flatten 或 tf.layers.conv2d 。
- model . compile({优化器:' ___ ',损耗:' _ _ _ '})编译模型。优化器在 tf.train ,比如 tf.train.adam 和 tf.train.rmsprop 。
- model . fit(xs,ys,{epochs:_ _ _,回调:{_ _ _ _ _ _})拟合模型上 xs,ys 的数据集。
- . predict(【xs】)使用训练好的模型来预测标签。
语法已经过时了,我们现在可以开始编程了。
请注意,该程序是数据&部署专业化中 tfjs 课程中基于浏览器的模型的第 4 周示例的定制。
人脸识别
我们用 tfjs 中的迁移学习做一个人脸识别模型。该模型首先将三个人的图像作为输入,并将输出模型从网络摄像头中看到的人。如果你只是想看看演示,那么我在下面的一个网站上有。看看吧!
**[## 人脸识别 TFjS 演示
展示浏览器训练和推理能力的演示
djthegr8.github.io](https://djthegr8.github.io/)**
安装
- 从这里下载 Chrome 的 200 OK 网络服务器。它需要消除多个 HTTP 请求,并确保我们得到良好的上传。
- 可选地,如果你想编辑我的代码来玩 tfjs(我真的推荐这么做),你可以下载一个编辑器,比如括号,让你的工作更容易。
- 最后,所有的代码都可以在这个 GitHub 库中找到。请下载它,并将 Chrome Web 服务器的目标设置到该文件夹中。要运行,请打开服务器应用程序中的链接,然后打开 facerecgn.html 文件。
实际模型
让我们首先看一下 TensorFlow.jS 库的导入。这一行位于 HTML 页面的 head 部分。
**<script src="[https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest](https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest)"> </script>**
现在,我们将跳过 HTML 代码,在 index.jS 页面中查看 Tensorflow.jS 代码。
下面是加载 MobileNet 的代码,MobileNet 是一个经过预先训练的 tfjs 网络,它本身可以将图像分类到大约 1000 个类别。该函数通过声明一个新的模型来移除它的推理层,该模型采用倒数第二层的输出。
下面是代码中最重要的函数。我们正在展平 MobileNet 编码的三维输出(在 loadMobilenet() 函数中声明的模型的输出),然后通过一个小的 NN。损失是分类交叉熵,优化器是 adam。
我将展示的另一个函数是处理最终导致数据集创建的按钮按压的函数。这是不言自明的。
最后一个主要功能是 predict() ,它根据模型预测人。该函数查找预测概率并输出最高的概率。
完成后,rps-dataset.jS 就剩下了……与其描述代码,我将快速描述它的功能。它所做的只是创建一个可追加的数据集,并具有(一次性)标签。当然,代码在存储库中。
完成所有这些函数后,您可以查看最终的 index.jS 代码。
谢谢并评论
非常感谢你阅读这篇文章,如果你发现任何错误,请评论!
免费的任何疑问,项目帮助或任何合作机会!
给我发邮件到我的 Gmail 获取任何关于 TF、Keras、TFjS 或 Python 的帮助或合作!或者查看我的 Linkedin
如何服务您的 PyTorch 模型
原文:https://towardsdatascience.com/how-to-deploy-your-pytorch-models-with-torchserve-2452163871d3?source=collection_archive---------15-----------------------
TorchServe 的最新版本离 GA 又近了一步。
由 BENCE BOROS 在 Unsplash 上拍摄的照片
你已经收集了你的数据,处理了它们,训练了你的模型,微调了它,结果是有希望的。接下来去哪里?你如何让公众获得它?
嗯,如果你是一个 TensorFlow 用户,你可能想摆弄一下 TFX 。TFX 是一个优秀的工具集,帮助数据科学家创建和管理机器学习生产管道。但是如果你是 PyTorch 用户呢?嗯,你很幸运;截至 2020 年 4 月,你获得了torch serve。
学习率是我每周给那些对 AI 和 MLOps 世界好奇的人发的简讯。你会在每周五收到我关于最新人工智能新闻、研究、回购和书籍的更新和想法。在这里订阅!
火炬服务是什么
TorchServe 是一个灵活易用的工具,用于服务 PyTorch 模型。它没有 TFX 的复杂性,因此也没有提供那么多的功能。然而,这是完成工作的直接方法!
TorchServe 提供了一组必要的特性,比如服务器、模型归档工具、API 端点规范、日志记录、度量、批量推断和模型快照等等。它还提供了一系列高级特性,例如,支持定制推理服务、单元测试和通过 JMeter 收集基准数据的简单方法。目前,它还处于试验阶段,但它在大多数情况下都很有效。事实上,在本文的后面部分,我们将对它进行测试。
最新版本
TorchServe 在两天前(2020 年 6 月 10 日)发布了最新版本(0.1.1)。这是向 GA(全面上市)迈出的一步,包括一系列有希望的新功能。除其他外,TorchServe 的最新版本包括:
- 支持 HuggingFace ,这是一个深度学习库,其任务是为每个人推进和民主化 NLP,提供文档和示例
- 支持 Nvidia Waveglow ,一个基于流的语音合成生成网络,有文档和例子
- 与 Model Zoo 紧密集成,Model Zoo 是一个深度学习注册表,具有从流行的预训练模型创建的模型档案
- 支持 AWS 云形成,它提供了在 EC2 实例上运行服务器的能力,并提供了一个简单的配置文件(YAML 或 JSON)
- 支持通过 snakevize 分析器分析 TorchServe Python 执行,以获得详细的执行时间报告
- 具有清晰说明的重构文档
有关可用功能的详细列表,请阅读发行说明。
装置
安装 TorchServe 很简单。您可以使用文档中提供的说明,但是让我们使用 conda 在 Ubuntu 上安装它:
- 为您的 TorchServe 安装创建一个新环境(可选但推荐)。
conda create -n torch python=3.8
2.激活新环境。
conda activate torch
3.运行以下脚本来安装 TorchServe 及其依赖项。这个脚本在您的机器上安装 CPU 专用的 PyTorch、torchvision 和 torchtext 模块。如果你不需要的话,可以跳过这些。
conda install pytorch torchvision torchtext torchserve torch-model-archiver psutil future cpuonly -c pytorch -c powerai
您现在已经准备好开始使用 TorchServe,并通过 REST 端点使您的模型可用。
简单的例子
在这个例子中,我们部署了一个 MNIST 分类器。我们通过 TorchServe 文档中的代码示例来完成所需的步骤。
-
首先,我们需要定义一个 PyTorch 模型来解决 MNIST 挑战。下面的代码只是一种方法;将其复制并粘贴到一个名为
model.py
的文件中: -
然后,我们需要创建一个训练模型的脚本。将以下代码复制到一个名为
main.py
的文件中。你可以运行python main.py -h
来查看可用选项列表。训练新模型并保存(python main.py --save-model True
)或在此下载可用的预训练模型。不管怎样,把保存的模型移到一个名为artefacts
的新文件夹中。 -
接下来,我们需要编写一个定制的处理程序来在您的模型上运行推理。将以下代码复制并粘贴到一个名为 handler.py 的新文件中。该代码对灰度图像进行推理,就像 MNIST 图像一样:
-
接下来,我们需要使用 torch-model-archiver 实用程序创建 torch 模型归档。该命令将提供的模型(
artefacts/model.pt
)归档到一个.mar
文件中:
torch-model-archiver --model-name mnist --version 1.0 --model-file model.py --serialized-file artefacts/model.pt --handler handler.py
- 创建一个
model_store
文件夹,并将存档的模型移入其中:
mkdir model_store
mv mnist.mar model_store/
- 最后,启动服务器并向其查询答案。你可以在这里下载一些的测试数据。要使用它们,只需将它们放在一个名为
test_data
的新文件夹中:
torchserve --start --model-store model_store --models mnist=mnist.marcurl http://127.0.0.1:8080/predictions/mnist -T test_data/0.png
- 完成后,停止服务器:
torchserve --stop
结论
在这个故事中,我们介绍了 TorchServe,这是一个灵活易用的工具,用于服务 PyTorch 模型。我们看到了它是什么,它提供了什么,以及我们如何通过 REST 端点利用它的工具来服务 PyTorch 模型。最后,我们检查了它的最新版本(版本 0.1.1)和最新支持的特性,并用一个 MNIST 例子对它进行了测试。为了让您的手变脏,请阅读文档和官方示例。
学习率是我每周给那些对 AI 和 MLOps 世界好奇的人发的简讯。你会在每周五收到我关于最新人工智能新闻、研究、回购和书籍的更新和想法。在这里订阅!
我叫 Dimitris Poulopoulos,是希腊比雷埃夫斯大学BigDataStack和博士(c)的机器学习研究员。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲中央银行、经合组织和宜家等主要客户设计和实施人工智能和软件解决方案。如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和 DataOps 的帖子关注我上 中 、LinkedIn或@ James 2pl
如何设计一款流行的视频游戏:使用 NLP 和随机森林进行评分预测
原文:https://towardsdatascience.com/how-to-design-a-popular-video-game-rating-prediction-using-nlp-and-random-forest-d52a408bbadc?source=collection_archive---------67-----------------------
诚然,电子游戏行业现在是热点,其收入是电影的 4 倍,音乐的 7 倍。尤其是现在面对新冠肺炎,越来越多的人在虚拟的电子游戏世界中寻求社交联系和自我娱乐。毫无疑问,视频游戏行业前景广阔。
然而,在电子游戏行业成功容易吗?答案是否定的!尽管前景看好,但这仍是一项风险很大的业务。首先,有超过 100 万的视频游戏在行业内引发了激烈的竞争。第二,利润空间超级紧张。例如,playstation4 的利润率接近 5%。你猜怎么着,大部分成本来自研发。因此,在游戏设计上的准确投资可以产生巨大的差异。本文旨在使用随机森林和 NLP 技术来寻找能够极大地影响游戏评级的关键游戏设计特征。
作者来源
资料组
现有的亚马逊数据集包含元数据(包括视频游戏的基本产品信息)和评论数据(包括视频游戏的评论和评级)。这些表通过唯一的产品 ID (asin)链接在一起。下面是数据集的快照。虽然列出了许多特性,但没有一个与游戏设计特性直接相关。我们可能在哪里产生游戏设计特征?评论!接下来,我们将深入评论以提取特征。
元数据快照,按作者排序
作者来源的综述数据快照
特征工程
在这个项目中,我们将使用 IBM 自然语言理解包来实现特征工程。这个包中的一个嵌入功能是“keywords ”,它可以返回整个文本的关键字。此外,可以返回情感信息或情绪信息。我们从提取整个评论数据集中的关键词(合并所有评论)开始。然而,返回的不是一个词,而是一个阶段。正如在文本挖掘中经常出现的情况一样,关键字也因为不同形式的单词而变得非常混乱。
关键词示例,按作者来源
因此,我们应用了 PorterStemmer、word_tokenize、stopwords 来精简我们的关键字列表。最后,我们得到了如下所示的关键字列表。提到最多的关键词是“character”,是“character”的缩写。您可能已经注意到,如果我们将“character”输入到情感提取函数中,该函数无法检测到文本中相应的形式。下一步,我们检查了最常用的关键字形式,并给它们添加了内容。例如,打架可以是打架、打架和打架。
关键字列表的快照 1,按作者排序的来源
关键字列表快照 2,按作者排序的来源
现在我们已经有了最终的关键字列表。将所有功能放在一个篮子里可能会很混乱,也不太直观。让我们将它们归类到不同的篮子中,以进一步研究我们的关键字。关键词可以进一步分为 4 个篮子——游戏类型、系列、游戏元素和特征。
不同关键字组的 Wordcloud,按作者排序
最后,我们提取了每个产品在这些关键词上的情感得分。最终的特征矩阵是稀疏的,具有许多缺失值。考虑到许多关键词指向同一个游戏设计特征,如故事、情节和故事线,我们通过平均它们的情感分数来聚合相似的特征。
描述性分析
- 评分:平均评分约为 4.15,排名前 25%的产品评分超过 4.46。
评级分布,来源按作者
- 游戏类型:就平均收视率和波动性而言,rpg(角色扮演游戏)在所有游戏类型中脱颖而出,其次是冒险游戏和多人游戏。体育游戏和动作游戏在收视率上表现不佳。
不同游戏类型的分级,由作者提供
- 游戏系列:数码宝贝、口袋妖怪、金太阳平均评分最高,在 4.25 以上,而马登平均评分仅 3.88。
不同游戏系列的评分,由作者提供
- 游戏元素&特点:标尺是情绪得分。不同元素&特征之间的平均情感分数是一条乏味的直线,但情感分数的标准差确实形成了一些见解。在图形、新、易等方面,情感得分差异很大。与怪物相比。
游戏元素情感得分的标准差,来源于作者
机器学习和解释
现在我们为机器学习做好了准备。根据描述性分析中的发现,我们将评分降低到 4.4 分,形成一个高绩效组(30%)和一个低绩效组。功能是我们从评论中提取的,价格也是。游戏类型和游戏系列被编码为二进制变量,而其他的是连续的。
从个人经验来看,逻辑回归和随机森林在解释和预测准确性方面确实很突出。我们应用了这两种技术,并最终选择随机森林作为主要的解释器模型,因为它的性能稍好一些。采用的性能矩阵是 AUC 和准确性。
- 重采样:由于我们将产品分成不同组的方式,数据集有点倾斜。我们尝试了欠采样、过采样和 smote。为了更好的解释和准确性,我们最终利用欠采样。
- 特征选择:尝试了特征重要性技术和递归特征消除技术,但改进不大。
- 超参数调整:使用网格搜索调整 n_estimators、max_depth 和 min_sample_split。
最后,我们能够在验证集上实现 70%的准确性和 72%的 AUC。为了解释,我们使用排列重要性分数,因为我们有一些二元变量。我们也删除了游戏系列在解说剧情中的特征,因为它们对游戏设计贡献很少。
排列重要性分数,来源于作者
- 游戏类型(深蓝) : 体育游戏对区分高性能产品有很大影响。结合描述性分析中体育游戏对收视率产生负面影响的发现,我们通过进行逻辑回归进一步支持这一观点,逻辑回归也表明体育游戏对收视率产生显著的负面影响。
- 游戏元素(橙色) : 图形、关卡、控制对评分贡献最大。在描述性分析中,我们还发现图形在行业内具有最大的可变性。下面是评论中与“图形”或“级别”一起出现的词,它们可以为游戏设计提供很好的见解。产品设计的其他焦点可以是外观、声音和个性。
评论中的“图形”,来源于作者
评论中的“级别”,来源于作者
- 特征(浅蓝色) : 创新当然应该受到鼓励,因为“新”在重要性分数中排名第三。最常谈论的创新是“新功能”、“新武器”和“新风格”。
评论中的“新”,来源按作者
对于进一步的调查,可以做更多的工作。例如:
- 对于不同类型的电子游戏,不同功能的重要性分数会有很大差异吗?
- 图形是成本结构的一大部分。哪种类型/风格的图形对市场更有吸引力?
- 哪些创新会带来更高的回报?
- 难度等级设计如何选择合适的方法?
代码来源:https://github . com/JinPu-DuDu du/How-to-Design-a-Popular-Video-Game-Rating-Prediction-Using-NLP-and-Random-Forest
如何设计 Rust 中的恐慌恢复能力
原文:https://towardsdatascience.com/how-to-design-for-panic-resilience-in-rust-55d5fd2478b9?source=collection_archive---------26-----------------------
错误处理
不要慌!学会构建对错误有弹性的高质量软件。
照片:安德烈斯·达利蒙提 /Unsplash
试着想象使用一些软件和 WHAM,一堆文本,以及大脑无法忽略的视觉垃圾。或者更好的是,当你的用户同时按下两个按钮,飞机关闭时,他们正在驾驶一架商业客机。我们需要的是明确的反馈,并防止暂停执行。在这个故事中,我们讨论 Rust 应用程序中的恐慌恢复方法,以使高质量的软件用户可以依赖。
如果你认为你的软件是一辆时速 60 英里的汽车,恐慌就像撞上了一堵砖墙。
1990 年,一次软件更新导致美国电话电报公司全国 114 个电子交换系统全部瘫痪。当一座塔发生故障时,它会向邻近的塔发送一条信息,告知它正在停止交通。其他塔收到的信息导致它们进入类似的故障状态,通过整个美国电话电报公司长途网络使信息永久存在。
糟糕的逻辑是大多数有害软件错误的原因。C #中的错误可能更谨慎,因为被忽略的错误不会产生警告。Rust 本可以防止过去发生的一些讨厌的软件错误,但前提是软件开发人员利用了 Rust 语言提供的重要错误处理逻辑。
在 C 语言中,数值是表达“发生了错误”的惯用方法。函数调用返回一个表示错误代码的整数。如果代码为零,则没有错误发生。否则,可以将代码与值进行比较,以确定发生了什么故障。
C 中错误处理方法的问题是,忽略函数调用的返回值既不是错误,也不是警告。失败可能会被忽视和处理。
错误处理的首要目标是防止崩溃。
一些在 C 之后设计的新语言使用异常进行错误处理,这是对错误代码的高级抽象。调用一个可能失败并导致异常的函数需要一个try
和catch
块来执行可能导致异常的代码,并处理异常发出的错误信号。异常仍然不总是被显式处理,因此一些懒惰的程序员处理异常的方式与.unwrap()
在 Rust 中处理错误的方式相同——打印错误并失败。
在 Rust 中,错误显而易见。根据习语的说法,铁锈中的错误有Result
和Option
三种类型。因为错误是显而易见的,程序员厌倦了处理它们,最终更喜欢.unwrap()
每一个错误,这在恐慌恢复的名义下毫无用处。Unwrap 鼓励“最好的希望”,盲目地钻研可能存在的任何数据,如果在任何情况下都失败了,那就是严重的崩溃——恐慌。
错误处理的首要目标是防止崩溃。
让我们看看 Rust 中处理错误的三个关键部分:
- 什么时候恐慌,
- 处理错误,
- 和附加部分:库中的错误处理。
何时恐慌
带着错误代码退出总比惊慌失措好。在最好的情况下,你写的任何软件都不会死机。死机是一种可控制的崩溃,为了构建可靠的软件,必须避免死机。
崩溃从来都不是“恰当”的行为,但这总比让你的系统造成物理损坏要好。如果在任何时候,人们认为该软件可能会导致一些致命的、昂贵的或破坏性的事情发生,那么最好是将其关闭。
如果你认为你的软件是一辆时速 60 英里的汽车,恐慌就像撞上了一堵砖墙。
死机会解开调用堆栈,跳出每个函数调用并从程序执行中返回,在此过程中破坏对象。这不被认为是安全或干净的关闭。避免恐慌。
结束程序执行的最好方法是让它运行到最后一个大括号。以某种方式,为那种行为编程。它允许所有物体安全地自我毁灭。参见掉落特性。
处理错误
恐慌是最后的手段,而不是一个很好的内置工具,可以很容易地通过一个消息退出!
*Result*
、*Option*
、std::io::*Result*
等其他一些类型可以代表一次手术的成功。在惯用的 Rust 中,如果某个东西可能失败,它会返回一个*Result*
,该值编码了两个可能的值:要么是成功值(**Ok**
),要么是错误值(Err
)。*Result*<**T**, **E**>
其中T
是成功值类型,E
是错误值类型。
我们将我们的*Result*
与成功和错误值相匹配。如果这是一个成功,那么我们只是把我们的价值和进展,在我们的软件。但是,如果该值产生错误,我们必须基于以下问题制定有效的备份计划:
- 我们能再试一次吗?
- 数据是绝对强制进行的,还是可以生成、调整或假设的?
如果需要数据来继续,那么我们需要向调用者报告错误。除了 main 以外,我们绝对不能对任何功能感到恐慌。否则,你会得到自认为是上帝的东西的函数。适当的错误处理会尽其所能,当有疑问时,让调用者来处理问题。
下面的例子适用于第一个问题:我们可以再试一次吗?
**fn** open_config() -> *Result*<std::fs::File, std::io::Error> {
**use** std::fs::File;
**match** File::**open**("config.toml") {
**Ok**(f) => **Ok**(f),
// If not found, search in second location:
**Err**(e) => **match** File::**open**("data/config.toml") {
**Ok**(f) => **Ok**(f),
// Otherwise, bubble first error up to caller
_ => **Err**(e),
}
}
}**fn** main() {
**let mut** result = **open_config**();
**if** result.**is_err**() { // If failed the first time
// Try again in about 5 seconds ...
std::thread::**sleep**(std::time::Duration::**from_secs**(5));
// Reattempt
result = **open_config**();
} **match** result {
// Proceed as usual ...
**Ok**(cfg) => *println!*(**"Opened the config file"**),
// Print the cause to stderr, and DONT PANIC
**Err**(e) => *{
eprintln!*(**"File could not be opened: {:?}"**, e.**kind**());
std::process::**exit**(1); // Exit with code 1 (fail)
}
}
这段代码试图在“config.toml”中找到一个配置文件。如果失败,它会尝试在特定的子文件夹中查找相同的配置文件。只有当第二次尝试失败时,它才会将错误冒泡到调用者。调用者是 main,它愿意在暂停 5 秒钟后第一次重试失败。请注意,即使 main 也不会死机,因为虽然这是一个致命的错误,但是可以恢复正常的退出进程。带着错误代码退出总比惊慌失措好。
但是和恐慌一样,std::process:exit
可以防止物品的毁坏,所以只能在没有需要掉落的物品时使用。因此,恐慌是最后的手段,而不是一个漂亮的内置功能,可以很容易地通过一个消息退出!
最后一个例子适用于第二个问题:数据是否绝对必须继续?
/// Get the username from the config if it is present.
**fn** read_username_from_config() -> *Option*<*String*> {
// Implementation hidden
}/// Get the username if present. Otherwise returns the
/// default username "unnamed".
**fn** get_username() -> *String* {
**read_username_from_config**()
.**unwrap_or**(*String*::**from**(**"unnamed"**))
}**fn** main() {
**let** username = **get_username**();
*println!*(**"Username is: {}"**, username);
}
在上面的例子中,main 只请求一个用户名。get_username
返回String
,这意味着它没有失败的能力。它试图使用read_username_from_config
从配置文件中读取一个用户名,但是如果无法检索到,它将使用默认字符串“未命名”。
权衡你可能得不到的数据的价值是很重要的。考虑是否有可能返回到输入循环,或者带着警告继续。关注你的软件的可用性,以及它如何克服缺乏数据的问题。⁴
库中的错误处理
将错误值表示为代码时,可以使用枚举。
#[derive(Debug, PartialEq)] // Use derives
**enum** *SafeDivideError* { // Define a custom error type
**DivideByZero**,
}**fn** safe_divide(dividend: **i32**, divisor: **i32**) -> *Result*<**i32**, *SafeDivideError*> {
**if** divisor == 0 { // If the dividend is zero …
**Err**(*SafeDivideError*::***Divi*deByZero**) // Return the error value
} **else** { // Otherwise …
**Ok**(dividend / divisor) // Return the success value
}
}*assert_eq!*(safe_divide(4, 2), **Ok**(4/2));
*assert_eq!*(safe_divide(4, 0), **Err**(*SafeDivideError*::**DivideByZero**));
在上面的例子中,我们使用自定义枚举作为错误返回类型。这很容易看出我们产生错误的原因,但是在这种情况下,被零除是我们需要报告错误的唯一原因。因此,更好的型号可能是*Option*<**i32**>
。
创建自定义错误类型很有价值。当您使用空枚举作为错误类型时,数据足迹可能很小。这很重要,因为不管使用*Result*<**i32**, *String*>
的成功或错误值,例如,它消耗的内存和它的最大成员一样多。在这种情况下,是一个字符串,比堆栈上的一个**i32**
大 16 个字节。相反,SafeDivideError
枚举消耗“零”字节的内存。
*println!*(**"String: {}B"**, std::mem::size_of::<*String*>());
*println!*(**"SafeDivideError: {}B"**, std::mem::size_of::<*SafeDivideError*>());// String: 24B
// SafeDivideError: 0B
当使用两个或更多值时,它就变成了一个u8
的大小,在获得另一个字节之前,可以表示多达 256 个不同的错误值。将错误值表示为代码时,可以使用枚举。
利用文档注释来解释函数为什么会返回错误,尤其是不同的错误值意味着什么,这一点很重要。如果一个函数返回*Result*<**i32**, *String*>
,那么使用你的库的人肯定会想知道函数失败会返回什么不同的字符串。
旧的规则仍然适用于创建库:永远不要惊慌,只允许函数的调用者在您不能处理错误时处理错误——必要时冒泡错误。设计一个好的错误恢复库需要强调健壮的错误类型和它们的文档。从[std::io::Error](https://doc.rust-lang.org/std/io/struct.Error.html)
中汲取一些天才。
Rust 使任何人都能够构建高度健壮、可靠和高效的软件。所以不要慌!使用正确的方法编写可靠的 Rust 软件。
脚注
- 来源:http://www.phworld.org/history/attcrash.htm
- 这里有一个很好的列表:https://en.wikipedia.org/wiki/List_of_software_bugs
- 错误冒泡是指代码向上游传递错误,因为它肯定不会处理它。又名错误传播。
- 但是不要执行静默数据操作。
被遗忘的算法
原文:https://towardsdatascience.com/how-to-design-monte-carlo-simulation-138e9214910a?source=collection_archive---------4-----------------------
用 Streamlit 探索蒙特卡罗模拟
乔纳森·彼得森在 Unsplash 上拍摄的照片
TL;博士—当我们谈论机器学习时,我们经常会想到有监督和无监督的学习。在本文中,我想讨论一个经常被遗忘但同样强大的算法:蒙特卡罗模拟。我将分享一个通用的设计框架和一个交互式工具的营销应用程序。最后,你也可以在文末找到一个不错的模拟工具列表。
免责声明: 此非 Streamlit 赞助。我交替使用数据科学和机器学习。
喜欢读什么? 跟我上 中LinkedInTwitter。查看我的《 用机器学习影响 》指南。它有助于数据科学家更好地交流。**
不配的那个
在最近的机器学习(ML)兴起中,监督和非监督学习算法,如深度学习的分类和 KNN 的聚类,得到了大多数的关注。当这些算法从热情的社区获得谄媚的赞美时,同样强大而优雅的东西平静而安静地坐在黑暗的角落里。它的名字是蒙特卡洛——原子物理学、现代金融和生物医学研究以及赌博领域被遗忘且不配的英雄(或者是恶棍,取决于你对这些事情的看法)。
注:为了简洁起见,我将监督和非监督学习方法称为“ML 算法”,将蒙特卡罗方法称为“模拟”。
简短的历史
斯坦尼斯劳·乌拉姆、恩利克·费密和约翰·冯·诺依曼——洛斯阿拉莫斯的天才们——在 20 世纪 30 年代发明、改进并推广了蒙特卡罗方法,为了一个不那么高尚的事业(提示:这不是为了炸弹)。观看视频了解更多信息。
蒙特卡洛模拟简史(YouTube)
蒙特卡洛模拟是什么?
如果要我用一句话来总结蒙特卡洛模拟,那就是:假装十亿次,直到我们知道真实情况。****
吉菲
在技术(也是更严肃的)层面上,蒙特卡罗方法的目标是在给定各种输入、不确定性和系统动态的情况下,逼近对结果的** 期望。这个视频为感兴趣的人介绍了一些高级数学。**
蒙特卡洛近似, YouTube
为什么使用模拟?
如果我要强调模拟相对于 ML 算法的一个(过于简化的)优势,那就是:探索。我们用模拟来理解任何规模的任何系统的内部运作(例如,世界、社区、公司、团队、个人、车队、汽车、车轮、原子等。)
通过模拟虚拟地重新创建一个系统,我们可以计算和分析假设的结果,而无需实际改变世界或等待真实事件的发生。换句话说,模拟允许我们提出大胆的问题和制定策略来管理各种未来结果,而没有太多的风险和投资。
何时使用模拟,而不是 ML?
知名仿真专家 Benjamin Schumann 认为,仿真是过程驱动,而 ML 是以数据为中心。为了产生好的模拟,我们需要理解系统的过程和基本原理。相比之下,我们可以通过使用来自数据仓库的数据和一些现成的算法,使用 ML 创建相当好的预测。
换句话说,创建好的模拟通常在经济上和认知上更加昂贵。我们为什么要使用模拟?
好吧,考虑三个简单的问题:
- 您的数据仓库中有代表业务问题的数据吗?
- 你有足够的这些数据——数量上和质量上的——来建立一个好的 ML 模型吗?
- 预测比探索更重要吗(例如,提出假设问题并制定策略来支持业务决策)?
如果你的答案是否定的,那么你应该考虑使用模拟而不是最大似然算法。
如何设计一个蒙特卡罗模拟?
要创建蒙特卡洛模拟,至少需要遵循 3 个步骤:
模拟过程,作者的分析
如您所见,创建蒙特卡洛模拟仍然需要数据,更重要的是,需要对系统动态的一些理解(例如,销售量和价格之间的关系)。要获得这样的知识,通常需要与专家交谈、研究流程和观察真实的业务操作。
又一个模拟器
要了解基本概念是如何实现的,你可以去 另一个模拟器——这是我用 Streamlit 开发的一个交互工具。****
在欢迎页面上,您可以尝试各种输入设置,并观察结果如何根据您应用的功能而变化。
欢迎页又一个模拟器,作者的作品
除了基本示例,该工具还包括 4 个案例研究,讨论各种设计技术,如影响图、灵敏度分析、优化以及将 ML 与模拟相结合。
例如,在 CMO 的例子中,我讨论了如何使用影响图来帮助设计一个模拟来解决广告预算分配问题。
影响图,作者作品
最后,你将接替首席营销官(CMO)的数据科学家职位。你的目标是帮助 CMO 决定在广告上花多少钱,探索各种场景,并想出在不同的不确定性下最大化回报的策略。
广告预算分配,作者的工作
我希望这些例子能说明蒙特卡罗模拟是如何工作的,与最大似然算法相比,它在允许我们探索方面的优势,以及如何用不同的设计技术设计有用的模拟。
一些案例研究仍在积极进行中。在这里 注册 以便在他们准备好的时候得到通知。
综上
我希望这篇文章提供了对蒙特卡罗方法的另一种看法;在今天的 ML 讨论中,我们经常忘记这样一个有用的工具。模拟有许多传统 ML 算法无法提供的优势——例如,在巨大的不确定性下探索大问题的能力。
在即将发表的文章中,我将讨论如何在真实的商业环境中结合 ML 和模拟以获得两个世界的最佳效果,以及如何阐明不同模拟场景的含义。
敬请关注我上中 ,LinkedIn,或Twitter。****
直到下一次,
伊恩
吉菲
如果你喜欢这篇文章,你可能也会喜欢这些:
****** [## 最有用的 ML 工具 2020
每个懒惰的全栈数据科学家都应该使用的 5 套工具
towardsdatascience.com](/the-most-useful-ml-tools-2020-e41b54061c58) [## 12 小时 ML 挑战
如何使用 Streamlit 和 DevOps 工具构建和部署 ML 应用程序
towardsdatascience.com](/build-full-stack-ml-12-hours-50c310fedd51) [## ML 和敏捷注定的联姻
如何在 ML 项目中不应用敏捷
towardsdatascience.com](/a-doomed-marriage-of-ml-and-agile-b91b95b37e35) [## 数据科学很无聊
我如何应对部署机器学习的无聊日子
towardsdatascience.com](/data-science-is-boring-1d43473e353e) [## 抵御另一个人工智能冬天的最后一道防线
数字,五个战术解决方案,和一个快速调查
towardsdatascience.com](/the-last-defense-against-another-ai-winter-c589b48c561) [## 人工智能的最后一英里问题
许多数据科学家没有充分考虑的一件事是
towardsdatascience.com](/fixing-the-last-mile-problems-of-deploying-ai-systems-in-the-real-world-4f1aab0ea10) [## 我们创造了一个懒惰的人工智能
如何为现实世界设计和实现强化学习
towardsdatascience.com](/we-created-a-lazy-ai-5cea59a2a749)
流行工具
当我讨论模拟时,许多人询问关于工具的建议。这是我知道的工具列表,选择适合你的目的的。享受吧。
- AnyLogic (这大概是仿真专业人士的必备工具;免费增值)
- Simio (免费增值)
- 亚赛 (Excel 插件,免费)
- 甲骨文水晶球(免费增值)
- SimPy (Python 包,免费)
- Hash (在编写本报告时以秘密模式启动。相当坚实的创始团队。大概是免费增值)
参考
决策树的历史——http://pages . stat . wisc . edu/~ loh/Tree progs/guide/loh isi 14 . pdf
聚类历史—https://link . springer . com/chapter/10.1007/978-3-540-73560-1 _ 15
结婚时间模拟与 ML——https://www . Benjamin-Schumann . com/blog/2018/5/7/结婚时间模拟模型与机器学习
仿真分类—https://gamingthepast . net/theory-practice/Simulation-design-guide/
什么是蒙特卡洛,它是如何运作的——https://www.palisade.com/risk/monte_carlo_simulation.asp******
如何设计更丰富的可视化效果
原文:https://towardsdatascience.com/how-to-design-more-informative-visualizations-19f27fc8549a?source=collection_archive---------36-----------------------
用静态可视化更有效地向观众传播信息的 5 个技巧
数据可视化是成为数据科学家的必备技能。大多数时候,我们完全专注于学习如何使用可视化工具,我们没有停下来思考在制作可视化时我们应该遵循的设计原则和良好实践。可视化提供了一目了然的关键见解,它们比原始数据更有效地传达了一个想法。这主要是因为人脑无法同时处理大量数据。然而,仅仅向观众提供视觉效果是不够的,还必须进行适当的设计。可视化设计极大地影响了信息传达给观众的速度。出于这个原因,从布局到颜色、标签和背景的每个元素都必须经过挑选,以便于信息的传输。
本文简要解释了最重要的设计原则以及如何应用它们来使可视化更具知识性和更易于处理。我们将一步一步地重新设计视觉效果,这样你就可以了解这些原则是如何帮助你更有效地理解信息的。此外,我们提供了对 Github 库的访问,在那里你可以找到这篇文章中使用的代码。
顺便提一下,我想提一下,本文中解释的所有技术都是针对静态可视化的。这些可视化可以在印刷报纸、静态报告或公司演示中找到。它们只关注特定的数据故事,观众无法实时修改。相反,交互式可视化允许用户通过与数据交互来回答问题。因此,应该使用其他原则和工具来设计它们。
照片由absolute vision在 Unsplash 上拍摄
假设你是一名数据记者,你正在写一篇关于马竞自 2011 年 12 月迭戈·西蒙尼加盟以来的表现的文章。你想传达给观众的关键信息是马竞的防守比它的直接对手强得多。为此,您执行以下可视化操作,该操作描述了过去 10 个赛季西班牙顶级球队的进球情况。
在这里,你有一个特定的信息要传达给你的读者。然而,这种可视化并不能一目了然地传达这一信息。但是,你如何改进这种形象化,不仅更快而且更有效地向观众传达信息呢?接下来,我将向你展示 5 种技术,你可以将它们应用到你的可视化中,使它们更具知识性。我们开始吧!💜
“卓越的图形能够在最短的时间内,用最少的笔墨,在最小的空间里,向观众传达最多的思想。”
爱德华·塔夫特[1]
1.数据-油墨比
****数据-油墨比率是由爱德华·塔夫特在八十年代早期引入的概念,指的是显示实际数据的绘图油墨与可视化中使用的总油墨(数据-油墨+非数据油墨)的比例。
数据-油墨比率=数据-油墨/总油墨
根据 Tufte 的说法,设计可视化时的一个关键方面是获得高数据-墨水比率。为了实现这一目标,我们必须强调包含信息的元素(在这种情况下是剧情的线),并尽量减少那些没有给观众带来任何信息且专门用于装饰目的的元素。非数据墨水包括(1) 3D 和阴影效果,(2)框架,(3)网格线,(4)边框和(5)背景。当这些元素对可视化没有任何价值时,它们应该被删除,这样最重要的信息就突出来了。****
现在,是时候应用 Tufte 的设计原则和减少非数据墨水出现在我们的可视化中了。在这种特殊情况下,我们只需移除顶部和右边界。然而,如果您的可视化包含上述元素中的另一个,您应该认真考虑消除它。
2.颜色
误用颜色是制作可视化效果时的一个常见问题,因为它通常用于美学目的而非信息目的。色彩在讲故事中起着关键作用,可以战略性地用于指示观众往哪里看【2】。
在最初的情节中,所有的线条都有明亮的颜色,并且都在平等地争夺观众的注意力。为了克服这个缺点,上面的视觉效果被重新设计,除了我们想要强调的红色的之外,所有的线都使用了灰色,给观众一个在哪里看的提示。****
的颜色有的含义 与之相关的。因此,在设计可视化效果时,重要的是要记住颜色可以唤起某些情绪并相应地使用它们来避免误解【2】。红色通常与危险和谨慎的感觉联系在一起,并与消极的结果联系在一起。由于这个原因,当涉及到可视化时,必须谨慎使用它。然而,这种情况是一个例外,因为你可能知道,足球队也有代表性的颜色。任何熟悉西班牙足球联赛的读者都会将红色与马德里竞技联系在一起,因此,在这种情况下,使用另一种颜色(而不是红色)可能会产生误导。
此外,我们还可以将灰色用于次要元素,如标题、标签和轴,以使我们的数据更加突出。
3.行距
****前注意属性帮助我们快速识别视觉效果中的某个元素【3】,而无需我们有意识的行动。这是通过修改一个特定元素的外观来实现的,使它从其余的数据中突出出来。这些属性是有效的,因为我们的大脑能够立即注意到环境中的差异。在前面的部分中,我们只使用了颜色(红色对灰度)作为预先注意的属性来突出显示可视化的特定行;然而,你可以用更多的预先注意属性来吸引观众的注意力。
Colin Ware 将前注意属性分为 4 大类[5]:
- ****颜色:这个类别包括两个属性(1)颜色色相和(2)颜色强度。色调用于区分类别,而颜色强度可以携带数值[2]。
- 形式:我们可以改变一个元素的形式,比如它的大小、长度、曲率,或者方向,如果我们想要强调它。
- ****空间位置:该视觉编码包括 2D 定位、立体深度、凹凸定位【6】等属性。
- ****运动:这种前注意属性在交互式可视化中特别有用,可以吸引观众的注意力。
正如我之前提到的,前注意属性可以一起使用;例如,我们不仅可以改变元素的颜色,还可以改变元素的形状(线宽),以更有效地吸引查看者的注意力,如下图所示。
4。直接贴标
大多数可视化工具,如 Matplotlib 或 Seaborn,默认情况下都提供了一个图例来表示可视化中的数据序列。然而,使用图例有一个缺点。查看者必须不断地在图例和图表之间来回扫描,这是一个非常耗时的可视化过程。或者,对于线图,我们可以直接标记数据序列,而不是提供颜色编码的图例,如下所示。这样做,我们使图表更清晰,更容易理解。
现在,最后一次修改:标题:)
5.标题和副标题
我们可以有策略地使用标题来描述我们想要传达给读者的主要思想,而不仅仅是像我们最初做的那样给出一个无聊的数据描述。在这种特殊的情况下,我们希望观众不要认为马德里竞技队拥有西班牙联赛中最好的防守,因此我们将这一想法放在可视化的标题上,使读者一眼就能理解图形的主要信息。此外,我们提供与副标题上的数据相关的补充信息,以确保可视化的正确解释。最后,我们在左边对齐标题和副标题。通过这样做,我们可以确保读者首先关注这些信息。
瞧啊。现在,我们有了一个更引人注目的视觉效果,可以有效地传达一个特定的想法!看出区别了吗😉
以前
在...之后
Github 知识库
下面的 Github 库包含一个 Jupyter 笔记本,在这里你可以找到所有用于创建可视化的代码。
** [## amandaiglesiasmoreno/可视化
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/amandaiglesiasmoreno/visualizations)
好消息是,我没有使用复杂的工具来制作这些可视化效果。一切都是用 Matplotlib 完成的。💛
有趣的视频
在 Youtube 上观看了一系列关于数据可视化的视频后,我决定写这篇文章。这些视频让我认真地重新考虑了我到目前为止进行可视化的方式,并让我学会了许多有趣的数据可视化技术,我肯定会将这些技术应用到我未来的图表中。这些视频由谷歌数据分析师科尔·努斯鲍默解说,并基于她的书用数据讲故事:商业人士数据可视化指南。
它们只持续一个半小时,所以不要犹豫去看它们!💜
-
整理你的可视化数据
-
巧用色彩
-
你看到了吗?对比的力量
数据可视化清单
在写这篇文章的时候,我看到了斯蒂芬妮·常青树和安·k·埃莫里创建的一个非常有用的清单。您可以使用此列表作为开发高效数据可视化的指南💙。
参考
[1]爱德华·塔夫特。定量信息的可视化显示。第二版,美国图形出版社,1991 年。
[2]科尔·努斯鲍默。巧用色彩【视频文件】。2015 年 10 月 1 日【引自 2020 年 10 月 30 日】。可用从:https://www.youtube.com/watch?v=AiD6etOB6qI&t = 1200s。
[3] Udacity。atributos Pre-aten ao[视频文件]。2015 年 2 月 23 日【引用于 2020 年 10 月 30 日】。可用从:https://www.youtube.com/watch?v=AiD6etOB6qI&t = 1200s。**
[4]科尔·努斯鲍默。用数据讲故事:商业专家数据可视化指南。第一版,美国威利,2015。
[5]科林·韦尔。信息可视化:设计感知。第三版,爱思唯尔,1999 年。
[6]巴勃罗·埃尔南德斯。了解大脑是如何工作的!;2020 年 2 月 13 日[引用于 2020 年 10 月 31 日]。来自:https://www.diabetesaustralia.com.au/gestational-diabetes
感谢你阅读❤️
阿曼达·伊格莱西亚斯**
如何用 Python 设计专业的维恩图
原文:https://towardsdatascience.com/how-to-design-professional-venn-diagrams-in-python-693c9ed2c288?source=collection_archive---------19-----------------------
使用 matplotlib-venn 绘制时尚专业的维恩图的快速指南
两个都没有反应。来源:作者
上周,我为我的 Python 课程设计了一些阅读材料。讲座主题是 Python 集 。
为了说明一些功能,我想画出 维恩图 。是的,你经常在数据演示中发现的重叠圆形图。
来源:吉菲
我对用于设计专业外观维恩图的开源工具的搜索引导我找到了像 Canva、 元图表 和 Creately 这样的工具。虽然它们有吸引人的设计,但没有一个具备所需的优雅,而且很少可以定制。
在谷歌搜索深处的某个地方,我遇到了 matplotlib-venn ,并爱上了它。
matplotlib-Venn库允许你完全定制你的文氏图,从圆的大小到边框类型和线宽。这是使用该库生成的样本图。
由作者生成并清理。代码来源于图书馆主页。
在将这个库用于多个项目之后,我决定分享我通过本教程所学到的东西。我将解释如何使用matplotlib-Venn创建你自己的专业维恩图。
设置
本教程中的所有例子都是在运行 Python 3.7 的 Jupyter 笔记本上测试的。我们将在本教程中使用 matplotlib-venn。
本教程有一个附带的 Jupyter 笔记本这里 。
维恩图介绍
文氏图 是用来描绘不同组或集合之间的逻辑关系的图示。
每个组用一个圆来表示。每个圆圈的大小对应于群体的大小/重要性。
这些圆之间的重叠表示两个集合之间的交集。因此,这些图对于识别每个集合之间的共享元素特别有用。
让我们看一个例子来更好地说明。假设你有一群选修多门课程的学生。这些科目中有两门是英语和法语。
English = {**'John'**, 'Amy', 'Howard', 'Lucy', **'Alice'**, 'George', 'Jacob', 'Rajesh', 'Remy', 'Tom'}French = {'Arthur', 'Leonard', 'Karan', 'Debby', 'Bernadette', **'Alice'**, 'Ron', 'Penny', 'Sheldon', **'John'**}
两个科目各有十名学生。爱丽丝和约翰都学英语和法语。
文英语和法语课。来源:作者
现在,我们将使用维恩图来可视化这些集合。
两个圆圈一样大。这是因为这两个集合有相同数量的学生。
两个圆之间的重叠部分包含两个对象:爱丽丝和约翰。
现在,我们了解了什么是维恩图,让我们用 Python 来设计一些。
如何使用 Python 创建维恩图?
第一步,导入需要的库:matplotlib-Venn和 matplotlib 。然后,我们定义希望绘制的集合:
最后,我们将使用 matplotlib-venn 的[**venn2**](https://python-graph-gallery.com/170-basic-venn-diagram-with-2-groups/)
函数绘制我们的文氏图:
venn2([English,French])
输出:
Venn 由 venn2 函数绘制。来源:作者
该函数将两个集合的列表作为参数,并绘制所需的文氏图。
我们还可以给剧情和单个圈子添加标签。
输出:
三组维恩图
现在,让我们再考虑两个科目:数学和理科。
Math = {'Amy', 'Leo', 'Ash', 'Brandon', 'Sara', 'Alice', 'Ron', 'Annie', 'Jake', 'Zac'}
Science = {'Dexter', 'Geeta', 'James', 'Charles', 'Sammy', 'Brandon', 'Aayush', 'Josephy', 'Casey', 'Will'}
我们现在将绘制一个包含三组内容的维恩图:英语、法语和数学。我们使用[venn3](https://pypi.org/project/matplotlib-venn/)
函数来实现这一点:
输出:
正如所料,这三个集合之间存在重叠。所有布景都有共同的爱丽丝。
现在,让我们考虑用科学而不是数学作为第三套。
输出:
我们看到,科学是一个 不相交的集合 ,与其他圆圈没有任何重叠。
假设有一门叫做消防安全的必考科目,每个人都必须参加。我们可以通过取一个 集合所有科目的 来定义它。
输出:
使用组的大小
有时我们没有现成的定义。我们只知道这些集合的大小以及它们之间的重叠量。在这样的情况下,我们使用 子集参数 :
subsets
是一个包含三个值的元组:
- 包含在集合 A 中,但不包含在集合 B 中
- 包含在集合 B 中,但不包含在 A 中
- 集合 A 和 B 的交集
venn2(subsets = (50, 20, 10), set_labels = ('Set A', 'Set B'))
你可以在这里 找到更多使用子集 的细节和例子。
改变颜色和透明度
虽然默认颜色(红色和绿色)适合大多数情况,但是您可以根据自己的方便选择不同的颜色。
set_colors
参数允许我们设置组的颜色。
alpha
参数允许我们控制透明度。
venn2([English, French], set_labels = ('English Class', 'French Class'), set_colors=('darkblue', 'yellow'), alpha = 0.8);
输出:
使用设置颜色和阿尔法。来源:作者
添加自定义边框
我们还可以在维恩图中添加自定义边框。我们通过在原始轮廓上叠加定制轮廓来实现这一点。
我们使用**venn2_circles**
和**venn3_circles**
绘制这个轮廓。看一看:
图表周围的额外粗轮廓。来源:作者
我们还可以分别使用linewidth
和linestyle
参数选择边框的宽度和样式。
宽度为 3 且样式为虚线的轮廓。来源:作者
更多的例子可以在 这里找到 。
使用 Id 进行自定义
我们也可以使用它们的 id 访问维恩图的每个元素。
下图显示了 2 组和 3 组文氏图中每个区域的 id。
您可以使用**get_patch_by_id**
方法自定义图表中每个区域的颜色。我们还可以使用**get_label_by_id**
方法定制每个区域的文本。
看一看:
来源:作者
请注意,交叉区域现在是紫色的,左边的圆圈上写着“新文本”。
更多关于定制的细节可以在 这里 。
结论
matplotlib-Venn库允许你完全定制你的文氏图,从圆的大小到边框类型和线宽。它可以用来制作二组和三组维恩图。
建议不要设计超过三组的维恩图。这仍然是一个 打开的问题库里的 。
你可以在这本附带的 丘比特笔记本 中找到所有的片段。
希望你觉得这个教程有用。
Chaitanya Baweja 渴望用工程解决方案解决现实世界的问题。在 Twitter 和 Linkedin 上关注他的旅程。
使用 Python、SQL 和 Tableau 创建实时群组
原文:https://towardsdatascience.com/how-to-design-real-time-cohort-analysis-in-python-sql-tableau-1df527c19b7e?source=collection_archive---------31-----------------------
来源
队列是在选定时期内具有共同特征的一群人,如 2019 年 6 月毕业的硕士生或在美国出现首例新冠肺炎后报名参加网飞免费试用的用户。
有几个队列变异,但假设只有两个队列。在三月或四月注册网飞的用户。随着时间的推移,在分析群组中用户的行为之后,我们可以了解群组的“质量”,例如订阅、客户终身价值或每个用户每天观看的平均时间。
虽然《网飞》的下载和订阅数量因爆发而增加,但群组分析有助于我们进行比较,并提供更多关于用户“享受”或哪部电影有助于留住客户的见解。
群组分析对于理解几代人在特定时期的行为也很重要,比如像新冠肺炎这样的外部冲击。
在社会隔离时期,人们花更多的时间在社交媒体上。下面你会看到在互联网上消费内容时,不同代人(群体)之间的差异。
来源
在本文中,我们将分析一个来自 UCI 的著名在线零售数据集,并了解如何在离线(Python)和在线(SQL-Tableau stack)中设计群组分析。
【http://archive.ics.uci.edu/ml/datasets/Online+Retail/
Python 部分(离线)
数据集包含客户 id、国家、价格、数量等,但我们只需要 customer id 和 InvoiceDate 列。
首先,我们丢弃重复的值并删除缺失的值。然后,我们使用 transform 函数找到每个用户的第一个订单日期,并计算下一个订单日期之间的日期差。
我们将 999 设置为第一个订单日期的虚拟,因为这些订单不计入留存而计入流失。
我们可以很容易地使用数据透视表创建群组,并在右侧添加“总计”列。根据客户第一次购买或注册的时间对他们进行分组是很常见的。
(对于 Tableau 中的离线分析,我们将数据框保存为 excel 格式。)
478 名客户在 2011 年 11 月下了第一笔订单。其中 144 名用户在同一个月再次订购,13 名用户在下个月(2011-12 年)再次订购。
321%的顾客不再订购。这就是为什么我们把 999 作为第一批订单的虚拟订单。
我们根据用户数量来标准化群组表,因为更常见的是以百分比来分析群组。
SQL 部分(在线)
让我们假设 online_retail 模式下的“orders”表中的数据集和每个用户购买的一条记录。我们在 Python 部分中使用 SQL 中的 first_value 函数计算第一个订单日期。
然后,我们使用 datediff()函数计算订单日期之间的日期差,并使用 case when 为第一个订单设置 999。现在,我们准备连接到 Tableau 中的数据源,并在下面的 Tableau 视频之后分析群组。
画面部分(在线)
如果您有任何问题,可以通过 Twitter 或 LinkedIn 联系我。
越狱
原文:https://towardsdatascience.com/how-to-design-search-engines-24e9e2e7b7d0?source=collection_archive---------26-----------------------
我们应该如何设计推荐系统
照片由德鲁·比默在 Unsplash 上拍摄
TL;博士——我们被 YouTube 或亚马逊等公司设计的推荐算法所禁锢。这些算法产生了难以逃脱的回音室。我想要能带来刺激的东西,更重要的是,在不剥夺便利的同时还能掌控一切。在这篇文章中,我想介绍一下我用 Streamlit 构建的独立电影应用 YAME 。我用它作为例子来讨论为未来设计更好的机器学习系统的原则。
免责声明: 本文不是由 Streamlit 或我工作的任何公司赞助的。所有观点都是我自己的。
喜欢读什么? 跟我上 中LinkedIn,或者Twitter。**
仓鼠、飞轮和魔法
推荐系统驱动互联网。公司设计推荐算法来吸引你的注意力。这些算法推动你的手指滚动,就像一只仓鼠在飞轮上(或下面)。对仓鼠来说,这可能很有趣,但对人类来说,这似乎是个陷阱。
吉菲
当你看着屏幕时,你的头脑(或手指)释放出人类发明的最强大的魔法:股票价格。你的关注推高了设计飞轮的公司的价格,即脸书、亚马逊、网飞和谷歌(简称 F.A.N.G)。一切都很好,对吗?尤其是对那些拥有这些股票的人来说。今年圣诞节一切都变了。
截至 2020 年 1 月 20 日,雅虎财经
高度个性化的监狱
圣诞节期间,我重新看了一遍我最喜欢的电视节目《T2 越狱》,突然意识到:虽然我在身体上是自由的,但我被数字化囚禁了。我对我的社交媒体订阅源 — 显示的话题不再那么好奇,这些订阅源是根据我的兴趣定制的。真是讽刺。
对于《越狱》的主角迈克尔·斯科菲尔德来说,他的牢房是这样的:
吉菲
对我(和我们中的许多人)来说,当我去 YouTube 时,我的牢房看起来是这样的:
作者分析,2020 年 1 月 17 日— Youtube 登陆页面
好吧,我的牢房没有马天如的那么吓人。是的,我会收到基于我(和我妻子)感兴趣的高度个性化的内容。然而,还有两个问题。
首先,事情变得无聊。由于效用的急剧减少,我对相同的内容越看越不感兴趣。事实上,我经常花更多的时间寻找有趣的内容,而不是实际观看建议。
第二,用户不能轻易(也不能真正)探索。YouTube 或 Instagram 等平台确实提供探索功能,如 YouTube 的趋势和 Instagram 的探索订阅。但是,这些功能并没有提供简单的用户界面,无论是有意还是无意,以允许用户真正探索。具有讽刺意味的是,内容仍然主要取决于你的历史观和平台想要推广什么以获得更高的广告收入。
作者分析,2020 年 1 月 20 日——Youtube 趋势页面
作者分析,2020 年 1 月 20 日-Instagram Explore Feed
现在我们被困住了。社交平台用源源不断的个性化信息创造了美丽迷人的墙。但是当我们试图越过那堵墙窥视时,我们会意识到这是一个无边的陷阱。
和 YAME 一起越狱
我想出去!我想利用科技带来的便利探索更多。如果我愿意的话,我想选择呆在我的牢房里(不是每个人都想或需要一直满足他们的好奇心)。我想控制我所看到的东西。
但是,我知道我不是迈克尔·斯科菲尔德,我们也不是在电影里。所以,我们不要拆掉并重新设计 YouTube、网飞或 Instagram。相反,让我们通过专注于一个特定的用例来一次迈出一小步:找到一部好电影来看。这成了我持续的痛点。
考虑到这一点,我创建了一个名为 YAME 的小应用。它代表又一部电影探索者。YAME 是您在工作日、周末、约会夜或家庭聚会时寻找好电影的唯一应用程序。
YAME 有一个设计原则:通过在便利和控制之间取得平衡来为用户提供选择。所以,YAME 有三个特性:
- “今日精选”来自 58,000 多部电影,跨越时间和流派
- 根据年份和流派过滤
- 智能探索让用户决定
便利:登陆页面有五部系统推荐的电影。它每天更新。该算法跨年份、跨流派挑选电影;它试图做到不偏不倚。
特点一:今日精选
一些控制:如果你不喜欢你看到的或者只是想知道那里有什么,你可以使用左边的面板选择年份和流派。
特点 2:选择方便
更多控制而不牺牲便利:如果你真的想要别的东西,你可以基于探索你今天用一个简单的界面感受* 有多“冒险”。这个 UI 允许用户有一个 选项来选择 。用户可以决定他们想看什么,而不会认知超载。*
功能 3:智能探索:用户定义的探索
有兴趣或需要为这个周末挑选一部电影吗?这里 可以试试 YAME 。它对网络和手机都很友好。
有了 YAME,至少,我希望提供一个有用的和周到的工具,这样你就可以和你的朋友和家人(或独自)度过一段美好的时光。我希望这篇文章能让你更加意识到数字监狱对你好奇心和智力健康的影响。
超越亚美
从更大的角度来看,我想敦促设计和机器学习(ML)社区重新思考推荐系统如何更好地服务于用户,同时平衡与广告商或商家的利益。考虑到所有相互竞争的优先事项和利益,这是一个棘手的问题。
出于娱乐目的拥有不太理想的推荐系统相对来说是良性的,但是当这些系统被用来影响观点和社会运动时,后果就要严重得多了。今天, YouTube 推荐算法已经在分化和激进我们的社区。
我认为核心问题是推荐系统已经从你我这样的用户手中夺走了选择的权力。推荐算法和用户界面让我们很难选择我们想看的,很难选择我们想探索的,更重要的是,选择我们想的。**
我们需要重新平衡。尽管创建一个最大化每个人利益的解决方案是困难的,而且经常是不可能的,这里是给设计师和 ML 实践者的一个建议:让我们至少给用户提供可访问的选项来选择。这可以体现在用户体验、算法设计或两者之中。
同时,如果你喜欢并想支持 YAME,请查看我的Patreon页面。支持将用于支付运行和改进 YAME 的费用(如服务器、网站等)。).
祝你快乐,下次再见。你可以在中LinkedIn,或者Twitter*上找到我。*****
伊恩
吉菲
如果你喜欢这篇文章,你可能也会喜欢这些……
**** [## 最有用的 ML 工具 2020
每个懒惰的全栈数据科学家都应该使用的 5 套工具
towardsdatascience.com](/the-most-useful-ml-tools-2020-e41b54061c58) [## 数据科学很无聊
我如何应对部署机器学习的无聊日子
towardsdatascience.com](/data-science-is-boring-1d43473e353e) [## 被遗忘的算法
用 Streamlit 探索蒙特卡罗模拟
towardsdatascience.com](/how-to-design-monte-carlo-simulation-138e9214910a) [## 我们创造了一个懒惰的人工智能
如何为现实世界设计和实现强化学习
towardsdatascience.com](/we-created-a-lazy-ai-5cea59a2a749) [## ML 和敏捷注定的联姻
如何在 ML 项目中不应用敏捷
towardsdatascience.com](/a-doomed-marriage-of-ml-and-agile-b91b95b37e35) [## 你被解雇了
如何发展和管理一个快乐的数据科学团队
towardsdatascience.com](/i-fired-a-data-scientist-a137fca5b80e) [## 抵御另一个人工智能冬天的最后一道防线
数字,五个战术解决方案,和一个快速调查
towardsdatascience.com](/the-last-defense-against-another-ai-winter-c589b48c561) [## 人工智能的最后一英里问题
许多数据科学家没有充分考虑的一件事是
towardsdatascience.com](/fixing-the-last-mile-problems-of-deploying-ai-systems-in-the-real-world-4f1aab0ea10)****
如何摧毁 DeepMind 研究测验
原文:https://towardsdatascience.com/how-to-destroy-the-deepmind-research-quiz-90c9397c86db?source=collection_archive---------13-----------------------
DeepMind 是一家前沿的英国人工智能(AI)公司,旨在解决人工通用智能(AGI)。当他们的围棋程序 AlphaGo 击败了世界冠军 Lee Sedol 时,他们成了家喻户晓的名字。
在 Unsplash 上拍摄的 ThisisEngineering RAEng
小测验
注:我在 2019 年 6 月通过了研究小测验。从现在到那时,他们的采访内容可能已经改变了(不过我对此表示怀疑)。
DeepMind 的研究工程职位技术性很强。为了确保候选人有很强的技术背景,他们进行了一次两小时的测验。
测验由四部分组成:计算机科学、数学、统计和机器学习。问题的范围如此之广,这需要几乎包罗万象的知识。
准备小测验似乎让人不知所措。更糟糕的是,他们给出的准备材料清单包括两本教科书,三门在线课程,以及剑桥大学一年级数学和统计学课程的课堂笔记链接。
看两本厚厚的教材已经不现实了。在下面的部分,我会告诉你实际上需要做些什么来破坏这个测验。
准备
提交完学士论文后,我有一个月的时间准备小考。为了找出最有效的准备方式,我向在 DeepMind 工作的人和之前做过测试的人征求了意见。
我的大部分准备工作都集中在 Goodfellow 等人的深度学习书籍上。我还看了 David Silver 的强化学习(RL)课程,但这并不是必需的,因为测验的 RL 部分是可选的。
我创建了一个 Anki deck 来帮助我记忆面试所需的一切。创建和记忆这个套牌让我对深度学习的基础有了深刻的欣赏和理解。
要获得 DeepMind Anki deck 的副本,请从我的 Google Drive 下载。
我的 DeepMind Anki 卡组中的示例卡
计算机科学
对于计算机科学的问题,我会建议你复习计算机科学学位的标准内容。
测验的这一部分要求具备标准计算机科学学位主题的知识,如线程、数据结构、死锁、排序算法、编程范例和网络。还是那句话,你只需要知道如何定义事物。因此,没有必要阅读整个 CLRS 。
来自我的 DeepMind Anki Deck 的计算机科学卡示例
数学
数学问题侧重于线性代数、微积分和数值方法的概念。这一轮你还得手动微分或积分一个方程。所以,记得温习一下链条规则和零件整合。
为了复习代数、微积分规则、三角恒等式,我推荐阅读拉马尔大学的数学笔记并回答问题。笔记内容全面,制作精良。它们使得快速学习概念并付诸实践变得容易。
为了培养对线性代数概念的卓越直觉,我强烈推荐观看 3Blue1Brown 的《线性代数的本质》。有一个坚实的线性代数基础将使学习机器学习概念的数学变得容易得多。
来自我的 DeepMind Anki 卡组的线性代数卡
统计学和机器学习
我与一位前 DeepMind 研究工程师交谈过,他们告诉我阅读深度学习的书籍。
按照他的建议,我读了这本书,并在卡片上加了一张卡片,用来回答任何可以被称为“是什么”的问题。
这一部分的问题从定义一个特定的矩阵及其属性到解释不同的架构如何工作。
DeepMind Anki 牌组中的一张牌
结论
在我为小测验学习的一个月里,我学到了很多。当我通过测验时,我很高兴。但是知道我对我的领域有了全新的理解,感觉好多了。
不幸的是,我没能通过最后一次面试(现场前),但我在所有的面试中都有很好的经历。
我希望我的 Anki deck 或本文中的链接内容能帮助你在 DeepMind 的面试过程中取得成功。或者,任何其他基于机器学习的面试过程,你在未来的角色。
奥马尔·里德——你可以在 LinkedIn 和 T2 的 Twitter 上找到我。
Reddit 资源
来自 Reddit 用户的过去的问题
Reddit 上的一般讨论
如何检测和处理多重共线性
原文:https://towardsdatascience.com/how-to-detect-and-deal-with-multicollinearity-9e02b18695f1?source=collection_archive---------5-----------------------
关于识别和修复数值变量多重共线性的详细说明
照片由 Jaxon Lott 在 Unsplash 上拍摄
多重共线性是需要排除的主要假设之一,以获得任何回归模型的更好估计 ✌️
在本文中,我将通过一个示例数据集来介绍多重共线性的影响、如何识别以及何时解决这个问题。
👉什么是相关性?
两个变量之间的相关性可以用范围在-1 到 1 之间的相关系数来衡量。如果值为 0,则两个变量是独立的,没有相关性。如果测量值非常接近这些值中的一个,则表示线性关系,并且彼此高度相关。这意味着一个变量的变化与其他变量的显著变化相关联。
相关性可以用皮尔逊相关系数和斯皮尔曼秩序系数来计算。
👉什么是多重共线性?
当回归分析中的独立变量之间存在高度相关性时,会发生多重共线性,这会影响对结果的整体解释。它降低了系数的功效,削弱了统计测量以信任 p 值来识别显著的独立变量。因此,我们无法检验自变量对因变量的个别解释。
👉何时修复多重共线性?
好消息是修复多重共线性并不总是强制性的。这完全取决于回归模型的主要目标。
多重共线性的程度会极大地影响 p 值和系数,但不会影响预测和拟合优度检验。如果您的目标是执行预测,并且没有必要理解自变量的重要性,则没有必要解决多重共线性问题。
👉如何检验多重共线性?
- 相关矩阵/相关图
- 变动通货膨胀系数(VIF)
相关图可用于确定两个独立变量之间的相关性或双变量关系,而 VIF 用于确定一个独立变量与一组其他变量的相关性。因此,为了更好地理解,最好使用 VIF。
VIF = 1 →不相关
VIF = 1 比 5 →中度相关
VIF > 10 →高度相关
让我们从代码开始…..
这是数据集[ 房屋销售 ]的链接
数据集中的要素如下。销售价格是目标变量,其余为独立特征。
数据集的前几行
用数值变量识别多重共线性
现在我们将计算每个独立变量的 VIF 分数。
def vif_scores(df):
VIF_Scores = pd.DataFrame()
VIF_Scores["Independent Features"] = df.columns
VIF_Scores["VIF Scores"] = [variance_inflation_factor(df.values,i) for i in range(df.shape[1])]
return VIF_Scoresdf1 = df.iloc[:,:-1]
vif_scores(df1)
每个独立功能的 VIF
大多数变量的 VIF 分数都高于 10。如果我们使用此数据集构建回归模型,单个系数和 p 值将受到很大影响。我们将继续讨论如何解决这个问题。
修复多重共线性—丢弃变量
我们将考虑删除具有高 VIF 值的房间的特征室内(平方英尺)和 #,因为相同的信息被其他变量捕获。此外,它还有助于减少数据集中的冗余。
让我们比较一下去掉 VIF 值前后的 VIF 值。
突出显示的特征被移除并计算 VIF 分数
从上文中,我们可以注意到,在去掉高价值(室内(平方英尺)和房间数量)【VIF 特征】后,其他变量的 VIF 得分也降低了。
修复多重共线性—组合变量
接下来,我们可以观察到床的数量和洗澡的数量可以合并为一个变量,这有助于我们从这两个变量中获取更多信息。
*df5 = df4.copy()
df5['Total Rooms'] = df4.apply(lambda x: x['# of Bed'] + x['# of Bath'],axis=1)
X = df5.drop(['# of Bed','# of Bath'],axis=1)
vif_scores(X)*
床的数量和浴室的数量组合成一个单一的功能房间总数
从上面,我们可以注意到所有三个变量(公寓费、税和总房间数)都达到了令人满意的 VIF 值,我们可以进一步建立回归模型。
总结
在本文中,我们学习了如何识别和修复回归分析中数值的多重共线性问题。这是一个迭代过程,我们还需要领域知识来决定对哪些变量采取适当的行动。还有其他技术,如 PCA 和正则化方法也可以解决这个问题。
请访问我的 GitHub 链接获取完整的[ 代码
感谢阅读,快乐学习!🙂
如何检测人工智能中的偏差
原文:https://towardsdatascience.com/how-to-detect-bias-in-ai-872d04ce4efd?source=collection_archive---------17-----------------------
偏见
检测数据中常见的(认知)偏差
随着人工智能解决方案在我们的日常生活中变得更加根深蒂固,人工智能偏见在过去几年中一直是一个热门话题。作为一个转行做数据科学的心理学家,这个话题很贴近我的内心。
为了防止人工智能模型出现偏差,人们首先必须意识到各种偏差的存在。
在中,为了发现偏见,人们必须意识到它的存在。
为了做到这一点,本文将指导你在开发人工智能的不同阶段发现许多常见和不常见的偏见。这些阶段包括:
- 数据收集
- 数据预处理
- 数据分析
- 建模
希望了解你可能遇到的偏见将有助于你开发更少偏见的人工智能解决方案。
1.什么是偏见?
偏见被认为是对一个想法或事情的不成比例的倾向或偏见。偏见通常被认为是在人类的背景下,但它可以存在于许多不同的领域:
- 统计数据 —例如,统计数据的系统失真
- 研究—例如,偏向于发表某些有意义的实验结果
- 社会科学 —例如,对某些人群的偏见
在本文中,我们将结合(认知)偏见可能出现的几个领域,以了解偏见如何进入人工智能。
下面,我将介绍人工智能发展的常见阶段,并确定检测偏差的步骤。
2.数据收集
数据收集是你会发现偏见的第一个也是最常见的地方之一。最大的原因是数据通常是由人类收集或创建的,这使得错误、异常值和偏差很容易渗入数据中。
数据收集过程中发现的常见偏差:
**Selection Bias**
—以样本不代表总体的方式选择数据
例如,在许多社会调查研究中,研究人员利用学生作为参与者来测试他们的假设。学生显然不能代表一般人群,可能会使研究结果产生偏差。
选择偏差
**The Framing Effect**
—带有特定倾向的调查问题。
如下图所示,如果这个问题是正面的,人们更有可能拯救 200 条生命,相比之下有 33%的机会拯救所有人。
72%的参与者在积极的框架下选择了治疗 A(“拯救 200 条生命”),当同样的选择出现在消极的框架下(“400 人会死”)时,这一比例下降到了 22%。
**Systematic Bias**
—这是一个一致的、可重复的误差。
这通常是设备故障的结果。纠正这种错误很重要,因为错误很难检测。对机械或工艺的良好理解是必要的。
系统误差
**Response Bias**
— 参与者对问题回答不准确或错误的一系列偏差。
问卷中经常出现回答偏差。由于这些都是由参与者填写的,人类的偏见很容易在数据中找到自己的位置。例如,**Social Desirability Bias**
指出,人们很可能会在他们的反应中否认不受欢迎的特征。这可以通过强调好的行为或理解坏的行为来实现。类似地,**Question Order Bias**
指出人们可能会根据问题的顺序不同地回答问题。
了解您如何设计收集流程会对您将要收集的数据类型产生重大影响,这一点很重要。如果不小心,你的数据会强烈偏向某些群体。任何由此产生的分析都可能是有缺陷的!
3.数据预处理
处理数据时,可以采取许多步骤来为分析做准备:
**Outlier Detection**
您通常希望移除异常值,因为它们可能会对某些分析产生不相称的影响。在所有人都在 20 到 30 岁之间的数据集中,年龄为 110 岁的人很可能不太能代表数据。
**Missing Values**
如何处理某些变量的缺失值会引入偏差。如果您要用平均值填充所有缺失的值,那么您是有目的地将数据推向平均值。这可能会让你偏向某些行为更接近平均值的群体。
**Filtering Data**
我见过很多次这种情况,数据被过滤得太多,几乎不能代表目标人群。这就介绍了,在某种程度上,**Selection Bias**
到你的数据。
4.数据分析
当开发一个人工智能解决方案时,最终的产品可能是一个模型或算法。然而,在数据分析中也很容易发现偏差。通常,我们在数据分析中会看到以下偏差:
**Misleading Graphs**
—歪曲数据的扭曲图表,从而可能从中得出不正确的结论。
例如,在报告分析结果时,数据科学家可以选择从 0 开始绘制图表的 y 轴。虽然这不会在数据本身中引入偏差,但随着差异变得更加明显,可能会出现明显的**Framing**
(见下图)。
如果 Y 轴从 0%开始,作物产量的差异似乎很小。然而,简单地将其更改为从 70%开始会导致看似不同的观点,而结果实际上是相同的。
如果你想了解更多关于误导性图表的影响,强烈推荐《如何用统计数据撒谎》这本书!
**Confirmation Bias**
——倾向于关注证实自己先入之见的信息。
假设你相信癌症和喝酒有很大的关系。当你进行分析时,你只是通过不考虑任何混淆变量来确认这个假设。
确认偏差
这可能看起来像一个极端的例子,你永远不会做的事情。但现实是,人类天生就有偏见,很难改变这一点。这种事发生在我身上的次数比我愿意承认的次数还要多!
5.建模
当谈到人工智能中的偏见时,人们通常指的是以某种方式偏向某一群人的人工智能系统。一个很好的例子是亚马逊创建的雇佣算法 ,它显示了**Gender Bias**
的决策。他们用于该算法的数据主要由担任技术职务的男性组成,这导致该算法倾向于将男性作为高潜力候选人。
这是一个典型的**Garbage-in-Garbage-out Phenomenon**
的例子,你的人工智能解决方案和你使用的数据一样好。这就是为什么在开始数据建模之前检测数据中的偏差如此重要。
让我们来了解一下在创建预测模型时经常看到的几种偏见:
**Bias/Variance Trade-Off**
——在偏差(模型的基本假设)和方差(使用不同数据时预测的变化)之间的权衡。
具有高方差的模型将过于关注训练数据,并且不能很好地概括。高偏差,另一方面,假设数据总是以相同的方式运行,这很少是真的。当增加你的偏差时,你通常会降低你的方差,反之亦然。因此,我们经常寻求平衡偏差和方差。
展示了偏差和方差之间权衡的影响。
**Concept Drift**
—目标变量的统计特性随时间以不可预见的方式变化的现象。
假设您创建了一个模型,可以预测在线商店中客户的行为。这个模型开始时很棒,但是一年后它的性能就下降了。一年来,顾客的行为发生了变化。客户行为的概念已经改变,并对您的模型质量产生负面影响。
解决方案可以简单地是用新数据频繁地重新训练你的模型,以便与新的行为保持同步。然而,一个全新的模型可能是必要的。
随着时间的推移和新数据的添加,原始数据(左)与概念漂移(右)的对比。
**Class Imbalance**
——(目标)类别出现频率的极度不平衡。
假设你想分类一张图片是包含一只猫还是一只狗。如果你有 1000 张狗的图片,只有 10 张猫的图片,那么就有一个**Class Imbalance**
。
阶级不平衡的结果是模型可能偏向多数阶级。由于数据中的大多数图片都是狗的,因此模型只需要总是猜测“狗”就可以达到 99% 的准确性。现实中,模型还没有学会猫和狗图片的区别。这可以通过选择正确的验证措施来补救(例如,平衡准确度或 F1 分数代替准确度)。
6.下一步是什么?
在阅读了你的人工智能解决方案中的所有这些潜在偏见之后,你可能会想:
"但是我如何从我的解决方案中消除偏见呢?"—你
我认为要解决偏见,你需要了解它的来源。知道是成功的一半。之后,就要靠你自己想办法消除或处理这种特定的偏见了。例如,如果您发现问题源于数据中的选择偏差,那么最好添加额外的数据。如果类别不平衡使您的模型更偏向于多数群体,那么您可以研究重新采样的策略(例如,SMOTE)。
注:关于常见认知偏差的互动概述,请参见这一惊人的可视化。
如果你和我一样,对人工智能、数据科学或心理学充满热情,请随时在 LinkedIn 上添加我。
如何在 MLOps 监控中检测模型漂移
原文:https://towardsdatascience.com/how-to-detect-model-drift-in-mlops-monitoring-7a039c22eaf9?source=collection_archive---------3-----------------------
Adrià Tormo 在 Unsplash 上拍摄的照片
人工智能在各行各业的采用率都在迅速上升。随着新冠肺炎的出现,消费者和企业对数字技术的采用在 T4 的八周时间内已经向前跨越了五年。然而,部署 ML 的复杂性阻碍了 AI 系统的成功。MLOps,特别是 ML 模型的生产面临的挑战与 DevOps 监控出现之前困扰软件的挑战相似。
ML 中的运营挑战
与传统代码不同,ML 模型是独特的软件实体,由于部署后输入到模型中的数据的变化,其性能会随着时间而波动。因此,成功的人工智能部署需要持续的 ML 监控,以在持续的基础上重新验证其商业价值。
ML 团队可以使用模型性能指标,如 AUC、precision、recall 等。监控生产模型的实时性能。然而,这些指标需要这些实时预测的“基础事实”或标签。虽然标签在训练数据集中总是可用的,但是对于给定的用例,它们可能不总是在生产中可用。例如,当一个模型对贷款风险进行预测时,贷方将只知道贷款是否违约或在贷款期限内是否得到全额偿付。在没有这些输入的情况下,或者为了补充这些性能指标的可见性,监控生产特征和预测分布的变化可以用作性能问题的领先指标和故障排除工具。
已部署模型中的数据更改(图片由作者提供)
什么是漂移
漂移是实体相对于基线的变化。数据漂移是模型漂移的基础,被定义为数据分布的变化。在生产 ML 模型的情况下,这是实时生产数据和基准数据集(可能是训练集)之间的变化,基准数据集代表模型打算执行的任务。由于现实世界的变化,随着时间的推移,生产数据可能偏离或偏离基线数据。预测值的漂移是概念漂移或数据完整性问题的一个很好的代理,并且可以通知模型重新训练节奏
最大似然漂移的类型 根据所比较的数据分布,可能有四种类型的漂移
- 概念漂移或 P(Y|X)的变化是模型输入和输出之间实际关系的变化。概念漂移的一个例子是,当宏观经济因素使贷款风险更高,有资格获得贷款的标准更高。在这种情况下,以前被认为有信誉的收入水平不再有信誉。
- 预测漂移或 P(Y hat 预测|X)的变化是模型预测的偏移。例如,当你的产品在更富裕的地区推出时,有更大比例的值得信赖的应用程序。您的模型仍然有效,但是您的企业可能还没有为这种情况做好准备
- 标签漂移或 P(Y 地面真实值)的变化是模型输出或标签分布的变化
- 特征漂移或 P(X)的变化是模型输入数据分布的变化。例如,所有申请人的收入增加了 5%,但经济基本面是一样的。
概念漂移本质上是真实决策边界和学习决策边界之间的差异。需要重新学习数据,以保持先前状态的错误率和准确性。如果地面实况标签可用并且足够实时,性能漂移是这种情况的最强指示器。在缺乏实时地面实况的情况下,预测和特征分布的漂移通常预示着世界上的重要变化。然而,与性能漂移不同,这些量可能会相对于精确建模的决策边界漂移(下面称为“虚拟漂移”)。在这种情况下,模型性能将保持不变。
参考文献:概念漂移适应研究综述——Joao Gama 等
漂移的原因 生产模型中出现漂移有多种原因。
1.当外部性导致数据分布发生真正的变化时。这可能需要具有更新的代表性训练集的新模型。
- 基本事实或输入数据分布的变化,如由于疫情、在新市场推出产品等而改变客户偏好。
- 有一个观念的转变。例如,竞争对手推出了一项新服务
2.当存在数据完整性问题时。这需要进一步的人体调查。
- 正确的数据在源处输入,但由于错误的数据工程而被错误地修改。例如,债务收入比值和年龄值在模型输入中互换。
- 来源处输入的数据不正确。例如,由于前端问题,网站表单接受将字段留空。
如何计算数据漂移
测量漂移有两种技术
- 统计:这种方法使用统计指标。这种方法的一个关键优势是用户对这些指标的理解,这些指标已经在多个行业中使用,尤其是金融和银行业。它们还有一个额外的好处,就是实现起来更简单。
- 人口稳定指数 ,流行于金融服务业,是衡量两个人口样本之间人口稳定性的指标。
人口稳定指数(参考)
- kull back–lei bler(或 KL)散度是衡量一个概率分布与第二个,参考概率分布如何不同的指标。
参考:维基百科
- Jensen-Shannon(或 JS)散度是衡量两个概率分布之间相似性的一种方法。它基于 KL 散度,有一些显著的不同,包括它是对称的,并且它总是有一个有限的值。
参考:维基百科
- Kolmogorov-Smirnov 检验 (或 KS 检验)是连续(或不连续)一维概率分布相等的非参数检验,可用于比较样本与参考概率分布(单样本 K–S 检验),或比较两个样本(双样本 K–S 检验)
参考:维基百科
2.基于模型的:这种方法使用一个模型来确定给定点或点群与参考基线之间的相似性。虽然使用基于 ML 的技术可以给出更准确的漂移图像,但是解释该技术的基础对于形成直觉来说可能是一个挑战。
如何识别漂移的原因
没有正确的工具来监控预测和特征漂移可能是乏味的。负责维护生产模型的数据科学家或 ML 工程师必须使用上述技术之一,不断将选定的实时流量窗口与基线进行比较。
捕捉到模型输出中的漂移后,下一步是确定哪些特征导致了漂移。很多时候,输入要素可能会漂移很多,但它可能不会在模型输出中造成有意义的漂移(即伪漂移),因为该要素在模型中的重要性较低。识别漂移来源包括评估要素相对于其输入重要性的潜在漂移。
在 Fiddler,我们使用 JS-Divergence 和可解释的人工智能来帮助在几个步骤中识别和排除预测和特征漂移
确定数据漂移原因(作者截图)
- 步骤 1 :快速识别实时模型输出中的预测漂移,与训练或基线集进行比较,用您在生产数据漂移阈值方面的领域知识来补充 JS-Divergence。
- 步骤 2 :再次使用 JS-Divergence,向下钻取到所选的时间窗口,查看底层特征的漂移。使用可解释性查看漂移特征的特征重要性,并只关注那些有意义的影响,过滤掉虚假漂移。
- 第三步:比较数据分布,查看实际差异,围绕模型再训练的需要形成直觉。
- 步骤 4 :进一步分析受影响的流量切片,了解漂移的性能
总之,数据变化可能是模型衰退的主要指标,因为 ML 模型是概率性的,并使用历史示例为高性能而训练。监控 ML 模型中的数据漂移有助于 ML 团队在生产中的性能问题上保持领先,可解释的 AI 通过提供强大的诊断工具来补充这一点,只需点击一下鼠标就可以找到任何可疑的时间片。
用 Python 和 YOLO 进行对象检测
原文:https://towardsdatascience.com/how-to-detect-objects-with-your-webcam-82693c47bd8?source=collection_archive---------16-----------------------
使用网络摄像头的计算机视觉
摘要
在本文中,我将展示如何使用计算机视觉,并通过几行代码获得许多乐趣。
计算机视觉是人工智能领域,研究计算机如何从数字图像或视频中获得高层次的理解,以产生数字或符号信息。
计算机视觉的主要任务是图像分类和目标检测。第一种识别图像是关于什么的,并用标签对其进行分类。最好的例子是对狗和猫的照片进行分类。但是如果任务是数一张照片里有多少只狗和猫呢?这将是一个目标检测问题。对象检测处理在数字图像和视频中检测某类语义对象的实例。
(你只看一次)是最快的,因此也是使用最多的实时物体检测系统。基本上,它将单个神经网络应用于整个图像,将其划分为多个区域,然后网络预测每个区域的边界框和概率。在这篇文章中,我将使用一个预训练的 YOLO 模型来进行对象检测,因此,如果你想了解更多关于神经网络结构以及如何训练它,我建议阅读原始论文。
设置
有几种方法可以将预训练的模型用于计算机视觉,最流行的框架是 Tensorflow 和 Keras。不过我觉得 ImageAI 对于我这种懒程序员来说是最方便的工具。这个包促进了深度学习和计算机视觉的使用,因为它提供了非常强大和简单的功能来执行对象检测和图像分类。
首先,我会从这里下载预先训练好的 YOLO 的重量(文件“yolo.h5”),并将该文件存储在我电脑的某个文件夹中。
**modelpath = "mycomputer/myfolder/yolo.h5"**
然后,我可以使用 ImageAI 非常容易地加载模型:
**from **imageai** import Detectionyolo = Detection.**ObjectDetection**()
yolo.setModelTypeAsYOLOv3()
yolo.setModelPath(modelpath)
yolo.loadModel()**
现在模型已经可以进行预测了,我们只需要数据。我将使用来自我的网络摄像头的实时视频流来为模型提供真实世界的图像。
你可以用 OpenCV 包访问你的设备摄像头,它提供了一个视频捕捉对象,处理与打开和关闭网络摄像头相关的一切。
**import **cv2**cam = cv2.**VideoCapture**(0) #0=front-cam, 1=back-cam
cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1300)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 1500)**
预测
现在我们可以开始和 YOLO 一起玩了。该模型将用于逐帧预测摄像机捕捉到的图像,直到循环被中断。
**while True: **## read frames**
ret, img = cam.read() **## predict yolo**
img, preds = yolo.**detectCustomObjectsFromImage**(input_image=img,
custom_objects=None, input_type="array",
output_type="array",
minimum_percentage_probability=70,
display_percentage_probability=False,
display_object_name=True) **## display predictions**
cv2.imshow("", img) **## press q or Esc to quit**
if (cv2.waitKey(1) & 0xFF == ord("q")) or (cv2.waitKey(1)==27):
break**## close camera**
cam.release()
cv2.destroyAllWindows()**
好玩吧。这个模型也做得很好,尽管它把一个橙子识别为一个“运动球”。
我使用的最小百分比概率为 0.70,这意味着只有当模型至少有 70%的把握时,我们才能检测到物体。降低该值会显示更多的对象,而增加该值可确保检测到精度最高的对象。
********
我希望你喜欢它!如有问题和反馈,或者只是分享您感兴趣的项目,请随时联系我。
👉我们来连线👈
本文是 Python 系列 CV 的一部分,参见:
**** [## 用 Python 进行图像分类:CNN 与变形金刚
计算机视觉&用卷积神经网络、迁移学习、ViT、TensorFlow 和 HuggingFace 进行解释
pub.towardsai.net](https://pub.towardsai.net/image-classification-with-python-cnn-vs-transformers-fe509cbbc2d0) [## 使用 Python 和 OCR 进行文档解析
使用计算机视觉从任何类型的文档中检测和提取文本、图形、表格
towardsdatascience.com](/document-parsing-with-python-ocr-75543448e581)****
如何识别 R 回归模型上的异常观察值?
原文:https://towardsdatascience.com/how-to-detect-unusual-observations-on-your-regression-model-with-r-de0eaa38bc5b?source=collection_archive---------6-----------------------
兰迪·法特在 Unsplash 上的照片
在这篇文章中,我将讨论一些在回归分析中如何检测异常观察值的方法。作为一个分析师,你可能要考虑筛选不寻常的观察值,这将帮助你得到一个全面的回归模型。不寻常的观察结果需要进一步调查,要么是因为它们与其他观察结果不同,要么是因为它们对模型的结果产生了不成比例的影响。
我将回顾三种不同寻常的观察结果:
极端值
高杠杆观察
有影响的观察
为了便于说明,我将使用 R 样本数据(state.x77)。这个数据集为我们提供了美国 50 个州的人口数量、平均收入、文盲率、气温和谋杀率等信息。
来自 R 的 state.x77 样本数据
使用下面的代码,我想建立一个回归模型,该模型可以根据某些州的人口、收入、文盲率和温度来预测这些州的谋杀率。同样,我们将应用 汽车 包为我们的数据扯皮。
# How to Identify Unusual Observations in Regression?
# Created by Michaelino Mervisianoinstall.packages(“car”)
library(“car”)states <- as.data.frame(state.x77[,c(“Murder”, “Population”,”Illiteracy”, “Income”, “Frost”)])
View(states) fit <- lm(Murder ~ Population + Illiteracy + Income + Frost, data=states)
summary(fit)
从总结函数中,我们发现我们的模型确实是显著的,F 统计量的 p 值<为 0.05。从 t 检验中,我们还发现文盲率和人口规模对预测一个州的谋杀率有重要意义。接下来,我们将调查在我们的模型中是否有不寻常的观察
> summary(fit)Call:
lm(formula = Murder ~ Population + Illiteracy + Income + Frost,
data = states)Residuals:
Min 1Q Median 3Q Max
-4.7960 -1.6495 -0.0811 1.4815 7.6210Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.235e+00 3.866e+00 0.319 0.7510
Population 2.237e-04 9.052e-05 2.471 0.0173 *
Illiteracy 4.143e+00 8.744e-01 4.738 2.19e-05 ***
Income 6.442e-05 6.837e-04 0.094 0.9253
Frost 5.813e-04 1.005e-02 0.058 0.9541
— -
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.535 on 45 degrees of freedom
Multiple R-squared: 0.567, Adjusted R-squared: 0.5285
F-statistic: 14.73 on 4 and 45 DF, p-value: 9.133e-08
异常值
回归模型不能很好地预测异常值。它们要么有非常大的正残差,要么有非常大的负残差。如果模型低估了响应值,那么它将由正残差表示。另一方面,如果模型高估了响应值,那么它将由负残差指示。
从我们的回归模型示例中,我们可以通过使用 Q-Q 图开始研究异常值观察。下面的代码有助于您绘制和发现潜在的异常值。内华达州(第 28 次观察)和罗德岛州(第 39 次观察)被检测为潜在的异常值。
> qqPlot(fit,labels=row.names(states), id.method=”identify”,
simulate=TRUE, main=”Q-Q Plot”)
Nevada Rhode Island
28 39
应用 outlierTest 函数帮助我们确认潜在的异常值是否确实是异常值。统计检验表明,内华达州不可否认地被检测为异常值,p 值= 0.048。
> outlierTest(fit)
rstudent unadjusted p-value Bonferroni p
Nevada 3.542929 0.00095088 0.047544
Q-Q 图也证实了内华达有一个大的正残差。意味着我们的模型低估了这个州的谋杀率。你可以发现内华达州的谋杀率是 11.5%,而模型预测只有 3.9%。我们清楚地知道,与其他州相比,内华达州确实不同。
> states[“Nevada”,]
Murder Population Illiteracy Income Frost
Nevada 11.5 590 0.5 5149 188> fitted(fit)[“Nevada”]
Nevada
3.878958
因此,您可以删除这个观察结果,并重新运行测试来查看是否存在其他异常值。作为一名分析师,你可能想知道为什么内华达州的谋杀率很高。也许你可以把这个问题发到 Quora 上,让我知道你是否有答案😉
高杠杆点
当我们将其与其他预测值进行比较时,如果观察值类似于异常值,则它们将被视为高杠杆点。严格地说,它们具有不常见的预测值组合,而响应值对确定杠杆作用的影响较小。
您可以通过查看模型中估计的参数数量与样本大小的比率来计算高杠杆观察值。如果观察值的比率大于平均比率的 2 -3 倍,则该观察值被认为是高杠杆点。我个人喜欢用这个简单的函数来识别高杠杆的观测值。
highleverage <- function(fit) {
p <- length(coefficients(fit))
n <- length(fitted(fit))
ratio <-p/n
plot(hatvalues(fit), main=”Index Plot of Ratio”)
abline(h=c(2,3)*ratio, col=”red”, lty=2)
identify(1:n, hatvalues(fit), names(hatvalues(fit)))
}
highleverage(fit)
高杠杆点
上图显示阿拉斯加和加利福尼亚的比例最高。这意味着如果我们将这两种状态的预测值与其他状态进行比较,这两种状态是非常不寻常的。原因如下:
对于阿拉斯加来说,该州的收入比其他州高得多,但人口较少,气温较低。
对于加州来说,这个州的人口比其他州多得多,同时收入更高,气温也更高。
与其他 48 个州相比,这两个州确实很特别。有一点要记住,并非所有高杠杆的观察都是有影响力的观察。这将取决于他们是否是离群值。
有影响的观察
对模型参数值具有不成比例影响的观察值可以被认为是有影响的观察值。例如,如果您删除一个观察,那么它会显著地改变您模型。那个单一的观察一定是有影响力的观察。因此,检查我们的数据是否包含有影响的点是很重要的。
根据我的经验,有两种有效的方法来识别有影响的观察结果:
1。 厨师的距离
下面的代码提供了一种方法来计算截止值,并为我们的每次观察绘制库克距离。该图显示阿拉斯加、夏威夷和内华达是有影响的观察点。移除这 3 个状态将对我们的回归模型中的截距和斜率值产生重大影响。
cutoff <- 4/(nrow(states)-length(fit$coefficients)-2)
plot(fit, which=4, cook.levels=cutoff)
abline(h=cutoff, lty=2, col=”red”)
每次观察的库克距离图
我需要强调的是,上面的图确实有助于识别有影响的观察,但是它没有给出关于这些观察如何影响模型的额外信息。这就是为什么增加的变量图可以成为我们挖掘更多信息的一个选项。
2。 增加了可变地块
附加变量图的工作原理是绘制每个预测变量与响应变量和其他预测变量的关系图。可以使用 car 包中的 avPlots() 函数轻松创建。
library(car)
avPlots(fit, ask=FALSE, id.method=”identify”)
从下图中,每个图中的直线是该预测变量的实际回归系数。我们可以通过想象如果代表观察结果的点被移走,线会如何变化来观察有影响的观察结果的影响。
添加了变量图
现在,我们将把来自异常值、高杠杆和有影响的观察的所有信息合并到一个单一的信息图中。我个人发现 influencePlot() 是一个非常方便的函数来表示这些不寻常的观察问题。
library(car)
influencePlot(fit, id.method=”identify”, main=”Influence Plot”, sub=”Circle size is proportional to Cook’s distance”)
影响图
上图方便地总结了我们的最终裁决。这是:
内华达州和罗德岛州是异常值。
加利福尼亚、华盛顿、纽约和夏威夷是高杠杆观察点
阿拉斯加是有影响力的观测地
我希望你发现这篇文章是有用的,并与他人分享
干杯,
米夏里诺·梅尔维西亚诺
如何开发信用风险模型和记分卡
原文:https://towardsdatascience.com/how-to-develop-a-credit-risk-model-and-scorecard-91335fc01f03?source=collection_archive---------0-----------------------
使用 Python 进行统计信用风险建模、违约概率预测和信用记分卡开发的演练
照片由来自 Pexels 的 Lum3n 拍摄
我们都知道,并保持跟踪,我们的信用评分,不是吗?这个非常重要的数字从 20 世纪 50 年代就存在了,它决定了我们的信用度。我想我们都有一个基本的直觉,如何计算信用评分,或哪些因素影响它。参考我以前的文章,了解更多关于信用评分的细节。
在本文中,我们将详细介绍用 Python 开发数据驱动的信用风险模型的步骤,以预测违约概率(PD)并为现有或潜在的借款人分配信用评分。我们将使用高度可解释、易于理解和实施的记分卡来确定信用评分,使计算信用评分变得轻而易举。
在进行这个案例研究时,我将假设自己具备 Python 知识,并对某些统计和信用风险概念有基本的理解。
我们有很多要讲的,所以让我们开始吧。
初步数据探索和分割
我们将使用 Kaggle 上提供的一个与美国 P2P 贷款机构 Lending Club 发放的消费者贷款相关的数据集。原始数据包括 2007 年至 2014 年间发放的超过 45 万笔消费贷款的信息,其中有近 75 个特征,包括当前贷款状态以及与借款人及其支付行为相关的各种属性。参考数据字典了解每列的详细信息。
这里解释的概念和总体方法也适用于公司贷款组合。
最初的数据研究揭示了以下内容:
- 18 个要素的缺失值超过 80%。考虑到缺失值的高比例,任何估算它们的技术都很可能导致不准确的结果
- 某些与信用风险无关的静态特征,如
id
、member_id
、url
、title
- 其他预期仅在借款人违约时填充的前瞻性特征,如
recoveries
、collection_recovery_fee
。因为我们的目标是预测未来的违约概率,所以在我们的模型中包含这些特征是违反直觉的,因为这些特征在违约事件发生之前不会被观察到
我们将放弃上述所有功能。
识别目标变量
基于数据探索,我们的目标变量似乎是loan_status
。快速看一下它的独特价值和它们所占的比例也证实了这一点。
图 1:默认值的分布
基于领域知识,我们将具有以下loan_status
值的贷款归类为违约(或 0):
- 注销
- 默认
- 后期(31-120 天)
- 不符合信贷政策。状态:已关闭
所有其他值将被分类为好(或 1)。
数据分割
现在让我们将数据分成以下几组:训练(80%)和测试(20%)。我们将对训练测试执行重复的分层 k 折叠测试,以初步评估我们的模型,而测试集将保持不变,直到最终的模型评估。这种方法遵循最佳的模型评估实践。
上面的图 1 向我们展示了我们的数据,正如预期的那样,严重偏向于优质贷款。相应地,除了随机混合抽样之外,我们还将对训练/测试分割进行分层,以便测试集中的好贷款和坏贷款的分布与分割前数据中的分布相同。这是通过train_test_split
功能的stratify
参数实现的。
在任何数据清理或缺失值插补之前拆分我们的数据,可以防止任何数据从测试集泄漏到训练集,并导致更准确的模型评估。详情请参考我之前的文章。
到目前为止所做工作的代码片段如下:
数据清理
接下来是一些必要的数据清理任务,如下所示:
- 从
emp_length
列中删除文本(如年份)并将其转换为数字 - 对于所有带日期的列:将它们转换为 Python 的
datetime
格式,创建一个新列作为模型开发日期和相应日期特性之间的差异,然后删除原始特性 - 从
term
列中删除文本并将其转换为数字
我们将为上述每个任务定义助手函数,并将它们应用于训练数据集。拥有这些助手函数将帮助我们在测试数据集上再次执行这些相同的任务,而无需重复我们的代码。
特征选择
接下来,我们将执行特征选择,使用类别特征的卡方检验和数值特征的 ANOVA F 统计来确定最适合二元分类问题的特征。请参考我以前的文章,了解关于这些特征选择技术的更多细节,以及为什么不同的技术被应用于分类变量和数值变量。
根据我们对分类特征的卡方检验,p 值按升序排列如下:
图 2:卡方检验的 p 值
为了简单起见,我们将只保留前四个特性,而去掉其余的。
34 个数值特征的方差分析 F 统计显示了从 23,513 到 0.39 的大范围 F 值。我们将保留前 20 个特性,并可能回来选择更多特性,以防我们的模型评估结果不够合理。
接下来,我们将计算所选的前 20 个数字特征的成对相关性,以检测任何潜在的多重共线性变量。这些成对相关的热图将两个特征(out_prncp_inv
和total_pymnt_inv
)识别为高度相关。因此,对于我们的模型,我们也将删除它们。
图 3:成对相关
接下来,我们将简单地将所有要删除的特性保存在一个列表中,并定义一个函数来删除它们。这些特征选择技术的代码如下:
一键编码和更新测试数据集
接下来,我们将创建四个最终分类变量的虚拟变量,并通过迄今为止应用于训练数据集的所有函数来更新测试数据集。
关于我们创建虚拟变量的方式,请注意以下几点:
- 我们将对所有变量使用特定的命名约定:原始变量名、冒号、类别名
- 一般来说,为了避免多重共线性,通过
pd.get_dummies
的drop_first
参数去掉一个哑变量。但是,我们在这个阶段不会这样做,因为我们需要所有的虚拟变量来计算我们的类别的证据权重(WoE)和信息值(IV)——稍后会详细介绍。稍后,我们将为每个类别删除一个虚拟变量 - 我们也不会直接在我们的训练数据中创建虚拟变量,因为这样做会丢弃分类变量,这是我们进行 WoE 计算所需要的。因此,我们将创建虚拟变量的新数据框架,然后将其连接到原始训练/测试数据框架。
接下来,我们将通过传递到目前为止定义的所有函数来更新测试数据集。在创建虚拟变量之后,要特别注意重新索引更新的测试数据集。让我用一个实际的例子来解释一下。
考虑一个名为grade
的分类特征,其在预分割数据中具有以下唯一值:A、B、C 和 D。假设 D 的比例非常低,并且由于训练/测试分割的随机性,在测试集中没有选择在grade
类别中具有 D 的观测值。因此,grade
在训练数据中的虚拟变量将是等级:A、等级:B、等级:C 和等级:D,但是等级:D 不会被创建为测试集中的虚拟变量。我们将无法在测试集上应用拟合的模型来进行预测,因为缺少模型预期呈现的特征。因此,我们重新索引测试集,以确保它与训练数据具有相同的列,任何缺少的列都添加 0 值。0 值非常直观,因为在任何测试样本中都不会观察到该类别。
WoE 宁滨和特征工程
基于 WoE 为所有数字和分类变量创建新的分类特征是开发信用风险模型之前最关键的步骤之一,也是非常耗时的。GitHub 和其他地方提供了特定的定制 Python 包和函数来执行这个练习。然而,我更喜欢手动操作,因为它让我有更多的灵活性和对过程的控制。
但什么是悲哀和四?
证据权重(WoE)和信息价值(IV)用于特征工程和选择,并广泛用于信用评分领域。
WoE 是一种独立变量相对于目标变量的预测能力的度量。它衡量一个特定的特征在多大程度上可以区分目标类别,在我们的例子中,就是好客户和坏客户。
IV 根据我们的功能的相对重要性对它们进行排序。
根据 Baesens 等人和 Siddiqi 的研究,WOE 和 IV 分析使人们能够:
- 考虑每个变量对结果的独立贡献
- 检测线性和非线性关系
- 根据单变量预测强度对变量进行排序
- 可视化变量和二元结果之间的相关性
- 无缝比较连续变量和分类变量的强度,而不会产生虚拟变量
- 无缝处理缺失值,无需插补。(注意,我们到目前为止还没有估算任何缺失值,这就是原因。在 WoE 特征工程步骤中,缺失值将被指定为一个单独的类别)
- 评估缺失值的预测能力
证据权重
计算 WoE 公式如下:
正的 WoE 值意味着好客户的比例大于坏客户的比例,反之亦然。
WoE 特征工程的步骤
- 计算分类变量的每个唯一值(bin)的权重,例如 grad:A、grad:B、grad:C 等。
- 基于连续变量的分布和唯一观测值的数量,将连续变量归入离散的箱中,可能使用
pd.cut
(称为精细分类) - 计算连续变量的每个衍生箱的权重
- 一旦为分类特征和数值特征的每个箱计算了权重,就按照以下规则组合箱(称为粗分类)
与合并 WoE bins 相关的规则
- 每个箱应该具有至少 5%的观察值
- 对于好的和坏的贷款,每个箱应该是非零的
- 每个类别的悲哀应该是不同的。相似的组应该被聚集或组合在一起。这是因为有着相似悲哀的箱子有着几乎相同的好的或坏的贷款比例,意味着相同的预测能力
- WOE 应该是单调的,即随着仓的增加或减少
- 缺失值被单独入库
上述规则已被普遍接受,并在学术文献中有详细记载。
为什么离散化数字特征
数值特征的离散化或宁滨通常不推荐用于机器学习算法,因为它经常导致数据丢失。然而,我们的最终目标是最终基于信用评分模型创建一个记分卡。通过按照记分卡标准对新的未经训练的观察(例如,来自测试数据集的观察)进行分类来利用记分卡。
考虑到我们没有对连续变量进行分类,那么我们将只有一个具有相应系数/权重的收入类别,并且所有未来的潜在借款人将在该类别中被给予相同的分数,而不管他们的收入如何。但是,如果我们将收入类别离散化为离散的类别(每个类别具有不同的权重),从而产生多个类别,则潜在的新借款人将根据其收入被分类到其中一个收入类别中,并相应地进行评分。
自 20 世纪 60 年代 FICO 首次开发商业记分卡以来,连续变量的 WoE 宁滨已成为一种既定的行业实践,并有大量文献支持它。将文献中的连续特征离散化的一些其他理由是:
- 考虑到高昂的货币和非货币错误分类成本,法律上通常要求记分卡易于被外行人解读(这是巴塞尔协议、几乎所有央行和各种贷款实体提出的要求)。这很容易通过没有任何连续变量的记分卡来实现,所有变量都是离散化的。高分或低分的原因很容易理解并向第三方解释。与更复杂的模型相比,所有这些都使得记分卡更容易获得最终用户的“认可”
- 记分卡的另一个法律要求是,它们应该能够区分低风险和高风险 observations⁴.WoE 宁滨负责这一点,因为 WoE 正是基于这一概念
- 单调性。宁滨算法期望以这样一种方式在条柱上划分输入数据集,即如果你从一个条柱沿同一方向走到另一个条柱,信用风险指标会发生单调变化,即如果你的收入发生变化,信用评分不会突然增加。这源于一个潜在的假设,即在全球非单调 relationship⁵的情况下,预测变量可以将较高的风险与较低的风险分开
- 逻辑回归模型的一个基本假设是所有特征与目标变量的对数优势(logit)具有线性关系。收入 38000 美元的人和收入 39000 美元的人有区别吗?很有可能不是,但是把收入当作一个连续变量来做这个假设。通过基于 WoE 进行分类,我们可以让我们的模型决定是否存在统计差异;如果没有,它们可以合并在同一个类别中
- 缺失值和异常值可以单独分类,也可以与最大或最小的条柱组合在一起-因此,无需假设来估算缺失值或处理异常值
信息价值(四)
IV 计算如下:
根据 Siddiqi 的说法,按照惯例,信用评分中 IV 的值解释如下:
注意当使用二元逻辑回归模型时,IV 仅作为特征选择和重要性技术有用。
我们数据的特征工程和 IV 计算
理论讲够了,现在让我们为我们的训练数据计算 WoE 和 IV,并执行所需的特征工程。我们将定义如下三个函数,每个函数用于:
- 计算并显示分类变量的 WoE 和 IV 值
- 计算并显示数值变量的 WoE 和 IV 值
- 将权重值绘制在箱柜上,以帮助我们可视化权重和组合相似的权重箱柜
应用于分类特征grade
时,这两个函数的输出示例如下所示:
WoE 和 IV 值
悲哀情节
一旦我们计算并可视化了 WoE 和 IV 值,接下来是最繁琐的任务,即选择要组合的仓,以及是否丢弃给定 IV 的任何特征。到目前为止,我们剩下的入围功能将以下列方式之一进行处理:
- 给定离散和单调的 WoE 并且没有任何缺失值:
grade
、verification_status
、term
,不需要组合 WoE 箱或创建单独的缺失类别 - 将具有非常低观测值的 WoE 箱与相邻箱组合:
home_ownership
、purpose
- 将具有相似 WoE 值的 WoE 箱组合在一起,潜在地具有单独的缺失类别:
int_rate
、annual_inc
、dti
、inq_last_6mths
、revol_util
、out_prncp
、total_pymnt
、total_rec_int
、total_rev_hi_lim
、mths_since_earliest_cr_line
、mths_since_issue_d
、mths_since_last_credit_pull_d
- 忽略具有低或非常高 IV 值的特征:
emp_length
、total_acc
、last_pymnt_amnt
、tot_cur_bal
、mths_since_last_pymnt_d_factor
请注意,对于带有异常值的某些数字特征,我们将在排除它们后计算并绘制 WoE,这些特征将被分配到它们自己的单独类别中。
一旦我们探索了我们的特性并确定了要创建的类别,我们将使用 sci-kit learn 的[BaseEstimator](https://scikit-learn.org/stable/modules/generated/sklearn.base.BaseEstimator.html)
和[TransformerMixin](https://scikit-learn.org/stable/modules/generated/sklearn.base.TransformerMixin.html)
类定义一个自定义的“transformer”类。像其他 sci-kit learn 的 ML 模型一样,这个类可以根据我们的要求在数据集上进行转换。这个类的另一个显著优势是,它可以作为 sci-kit learn 的[Pipeline](https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html)
的一部分,使用重复分层 k-Fold 交叉验证来评估我们的训练数据。以这种结构化的方式使用管道将允许我们执行交叉验证,而不会在训练和测试折叠之间有任何潜在的数据泄漏。
请记住,到目前为止我们已经使用了所有的虚拟变量,因此我们还将使用自定义类为每个类别删除一个虚拟变量,以避免多重共线性。
与 WoE 和 IV 相关的三个函数和 transformer 类的代码如下:
模特培训
最后,我们来到了涉及一些实际机器学习的阶段。我们将在我们的训练集上拟合一个逻辑回归模型,并使用[RepeatedStratifiedKFold](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RepeatedStratifiedKFold.html)
对其进行评估。注意,我们已经将LogisticRegression
类的class_weight
参数定义为balanced
。这将迫使逻辑回归模型使用成本敏感学习来学习模型系数,即,在模型训练期间惩罚假阴性多于假阳性。成本敏感学习对于不平衡数据集是有用的,这通常是信用评分的情况。参考我以前的文章了解不平衡分类问题的更多细节。
我们的评估指标将是受试者操作特征曲线下面积(AUROC),这是一个广泛使用和接受的信用评分指标。RepeatedStratifiedKFold 将在保留类不平衡的同时拆分数据,并多次执行 k 倍验证。
在对我们的训练集执行 k-folds 验证并对 AUROC 感到满意后,我们将在整个训练集上拟合管道,并创建一个包含特征名称和从模型返回的系数的汇总表。
预测时间
这一切都归结为:应用我们训练的逻辑回归模型来预测测试集的违约概率,这种方法迄今为止还没有使用过(除了一般的数据清理和特征选择任务)。我们将把预测的违约概率与实际类别一起保存在一个单独的数据框架中。
接下来,我们将绘制 ROC 曲线,PR 曲线,并计算 AUROC 和 Gini。我们的 AUROC on 测试集得出 0.866,基尼系数为 0.732,两者都被认为是相当可接受的评估分数。我们的 ROC 和 PR 曲线大概是这样的:
测试集上预测和模型评估的代码是:
记分卡开发
我们的难题的最后一部分是创建一个简单、易于使用和实施的信用风险记分卡,它可以由任何外行人使用来计算个人的信用评分,给出关于他和他的信用历史的某些必需信息。
还记得在模型训练阶段创建的汇总表吗?我们将把我们从模型中遗漏的所有参考类别附加到它上面,系数值为 0,还有另一列用于原始特征名称(例如,grade
代表grade:A
、grade:B
等)。).
然后,我们将确定记分卡应该给出的最低和最高分数。作为起点,我们将使用与 FICO 相同的分数范围:从 300 到 850。
逻辑回归模型为每个特征类别返回的系数然后通过简单的算术被缩放到我们的信用评分范围。这里的一个额外步骤是通过进一步缩放来更新模型截距的信用评分,该评分将被用作每次评分计算的起点。
在此阶段,我们的记分卡将如下所示(分数-初步列是计算分数的简单舍入):
根据您的情况,您可能需要手动调整随机类别的分数,以确保任何给定情况下的最小和最大可能分数保持在 300 和 850 之间。这里会涉及到一些尝试和错误。
计算测试集的信用分数
一旦我们有了最终的记分卡,我们就可以为测试集中的所有观察计算信用分数了。请记住,我们的训练集和测试集是虚拟变量的简单集合,用 1 和 0 表示观察值是否属于特定的虚拟变量。例如,在下图中,观察值 395346 的等级为 C,拥有自己的家,其验证状态为源已验证。
因此,在对我们的测试集进行某些调整后,信用分数是通过测试集和每个类别的最终分数之间的简单矩阵点乘来计算的。考虑上述观察结果,以及我们记分卡中截距和等级类别的以下最终得分:
直观地说,观察 395346 将从截距得分 598 开始,并由于属于等级:C 类别而获得 15 个附加分。类似地,观察 3766583 将被分配 598 加 24 的分数,因为其属于等级:A 类。我们将使用矩阵点乘跨所有特征类别自动进行这些计算。最终信用分数是适用于观察的每个特征类别的单独分数的简单总和。
设置贷款审批截止时间
那么,我们如何确定应该批准和拒绝哪些贷款呢?什么是理想的信用评分分界点,即信用评分高于该分界点的潜在借款人将被接受,而低于该分界点的借款人将被拒绝?这个分界点还应该在预期的贷款批准率和拒绝率之间达到一个微妙的平衡。
为了找到这个临界值,我们需要回到 ROC 曲线的概率阈值。请记住,ROC 曲线绘制了 0 到 1 之间所有概率阈值的 FPR 和 TPR。因为我们的目标是最小化 FPR,同时最大化 TPR,所以曲线的左上角概率阈值就是我们要寻找的。这个理想的阈值是使用尤登 J 统计量计算出来的,这是 TPR 和 FPR 之间的一个简单差异。
在我们的例子中,理想的概率阈值是 0.187。所有预测概率高于此值的观察值都应归类为违约,反之亦然。起初,与更直观的概率阈值 0.5 相比,这个理想阈值似乎是违反直觉的。但是请记住,我们在拟合逻辑回归模型时使用了class_weight
参数,该模型对假阴性的惩罚多于假阳性。
然后,我们计算这个阈值点的标度分数。如下面的代码示例所示,我们还可以根据 ROC 曲线计算每个阈值的信用评分以及预期的批准和拒绝率。这可以帮助企业根据他们的需求进一步手动调整评分截止值。
与记分卡开发相关的所有代码如下:
结论
好了,现在你有了—一个完整的工作 PD 模型和信用记分卡!完整的笔记本可以在 GitHub 上的这里找到。如果需要澄清或有其他疑问,请随意使用它或发表评论。
一如既往,如果您想讨论任何与数据分析、机器学习、金融分析或财务分析相关的问题,请随时联系 me 。
下次见,摇滚起来!
参考
证据权重和信息价值说明
[1] Baesens,b .,Roesch,d .,和 Scheule,H. (2016 年)。信用风险分析:SAS 中的测量技术、应用和实例。约翰·威利父子公司。
[2]n . Siddiqi(2012 年)。信用风险记分卡:开发和实施智能信用评分。约翰·威利父子公司。
[3]托马斯、埃德尔曼和克鲁克(2002 年)。信用评分及其应用。
[4] Mays,E. (2001 年)。信用评分手册。格兰莱克出版公司。
[5] Mironchyk,p .和 Tchistiakov,V. (2017 年)。信用风险建模的单调最优宁滨算法。
如何用 Python 开发优化模型
原文:https://towardsdatascience.com/how-to-develop-optimization-models-in-python-1a03ef72f5b4?source=collection_archive---------7-----------------------
使用 Python 和 PuLP 的线性编程演练
来源
在给定的情况下,如稀缺资源的分配,确定如何以最佳方式设计和操作系统,通常需要在决策中利用定量方法。数学优化是在特定情况下决定最佳行动的主要方法之一。它包括通过从允许的集合中系统地选择输入值并计算目标函数值来最大化或最小化真实函数。
优化的一些使用案例包括:
- 产品计划和库存控制:计划订单的发放,同时避免缺货和超出产能限制
- 路线决策:确定最具成本效益的路线的过程
- 包装问题:在不超出容量的情况下,确定包装方式,同时最小化自由空间
- 资源计划:确定每个项目和所需资源的数量
- 排班:如排班工人的班次
- 选址问题:在保证需求的同时,将运输成本降至最低的设施布局。
在本文中,我将演示一些优化问题的解决方案,利用线性编程,并使用 Python 中的 PuLP 库。
线性规划处理在决策变量上服从线性等式/不等式约束的情况下优化线性目标函数(例如最大利润或最小成本)的问题。
线性规划有三个组成部分:
- 决策变量:决策者可以直接控制的变量。
- 目标函数:以数学方式表达最大化或最小化数量的线性函数。
- 约束:表示对决策变量的限制的等式或不等式的数学表达式。
让我们看一些例子。你可以查看我的 GitHub 上的 Jupyter 笔记本来获得完整的分析。
1.资源计划示例
面包店每天都做蛋糕和馅饼。它可以在一天内制作总共 30 个项目,至少必须为其计划的客户制作 5 个蛋糕和 10 个馅饼。每个蛋糕的利润是 1.5 美元,每个馅饼的利润是 2 美元。应该生产多少才能使利润最大化?
来源
这个例子很简单,意味着它不需要我们使用 PuLP 或 Python 的任何功能,但它是理解概念的一个很好的练习。
问题的目标函数是利润最大化:
最大利润= 1.5C + 2P
受以下限制:
C >= 5,P >= 10,
但是并不是所有的问题都像这个问题一样简单,如果我们想要计算复杂问题的每个决策变量的每个约束,我们可能会遇到严重的时间问题。😅
让我们看另一个例子:
面包店在一个月的每一天都制作蛋糕和馅饼。有:1 个烤箱,2 个面包机,1 个包装打包机,一个月只工作 22 天。蛋糕需要用烤箱烤 1 天,馅饼需要 0.5 天。每个面包师需要为蛋糕工作 0.5 天,为馅饼工作 2 天。包装工需要为蛋糕工作 1 天,为馅饼工作 0.5 天。每个蛋糕的利润是 15 美元,每个馅饼的利润是 12 美元。在给定的条件下,利润最大化应该生产多少?
为了解决这个问题使用纸浆,我们将遵循共同的建模过程。
1.导入纸浆并初始化模型:
在
LpProblem()
方法中,我们定义了问题名称和目标函数的含义,目标函数可以是“LpMaximize”或“LpMinimize”。
2.定义决策变量:
在LpVariable()
方法中,我们为变量定义了一个名字,下界和上界的值,以及可以是‘整数’、‘二进制’或‘连续’的类别类型。因为我们想要一个整数值来表示蛋糕和馅饼的数量,所以我们选择 integer。
3.定义目标函数:
import pulp
from pulp import *model = LpProblem('Maximize Bakery Profits', sense= LpMaximize)
使用+=
将目标函数添加到初始化的模型中
4.定义约束条件:
C = LpVariable('C', lowBound=0, upBound=None, cat='Integer')
P = LpVariable('P', lowBound=0, upBound=None, cat='Integer')
使用+=
将约束添加到初始化的模型中。注意,约束不同于目标函数,因为它们在右边有(不)等式。
5.求解模型
model += 15 * C + 12 * P
调用求解方法model.solve()
检查解决方案的状态LpStatus[model.status]
model += 1 * C + 0.5 * P <= 30
model += 0.5 * C + 2 * P <= 60
model += 1 * C + 0.5 * P <= 22
打印优化的决策变量C.varValue
- 打印优化的目标函数
value(model.objective))
- 2.调度示例
- 一家邮局正在招聘邮递员,要求连续工作 5 天,然后休息 2 天。目标是雇佣最少数量的工人,每天所需的邮递员数量估计为:星期一:25,星期二:32,星期三:22,星期四:18,星期五:24,星期六:12,星期日:14。雇佣邮递员的最低数量是多少?
- 为了解决这个问题,我们需要写下每天需要开始工作的工人数量的限制,例如:x_0 是星期一开始工作的工人数,x_1 是星期二开始工作的工人数,以此类推。这样做,我们可以从周一到周五存储 x_0,从周二到周六存储 x_1,因为他们需要连续工作 5 天。
#Results1
Optimal
Produce 8.0 Cake
Produce 28.0 Pie
456.0
模型约束的图示
状态:最优
工人 __0 = 7.0
工人 __1 = 7.0
工人 __2 = 0.0
工人 __3 = 0.0
工人 __4 = 10.0
工人 __5 = 0.0
工人 __6 = 8.0
正如解决方案所建议的,我们总共需要雇用 32 名邮递员,其中 7 名在星期一开始工作,另外 7 名在星期二,10 名在星期五,8 名在星期天。
3.位置问题示例
#Initialize model
model = LpProblem("Minimize Number of Workers", LpMinimize)#Define decision variables
days = list(range(7))
x = LpVariable.dicts('workers_', days, lowBound=0, upbound=None, cat='Integer')#Define model
model += lpSum([x[i] for i in days])# Define constraints
model += x[0] + x[3] + x[4] + x[5] + x[6] >= 25
model += x[0] + x[1] + x[4] + x[5] + x[6] >= 32
model += x[0] + x[1] + x[2] + x[5] + x[6] >= 22
model += x[0] + x[1] + x[2] + x[3] + x[6] >= 18
model += x[0] + x[1] + x[2] + x[3] + x[4] >= 24
model += x[1] + x[2] + x[3] + x[4] + x[5] >= 12
model += x[2] + x[3] + x[4] + x[5] + x[6] >= 14# Solve model
model.solve()#Print model status
print('Status:', LpStatus[model.status])#Print solution variables
for variable in model.variables():
print ('{} = {}'.format(variable.name, variable.varValue))
假设您需要优化一家制造公司在 5 个销售地点的供应链网络,以最低的成本满足各个地点的需求。您可以决定每个地点的工厂规模,选项有低容量和高容量。一种可能性是在每个地区建立一个工厂,其优点是运输成本低,缺点是生产计划的规模要满足当地需求,不能利用规模经济。另一种可能性是建立一些具有规模经济优势的制造工厂,但需要较高的运输成本。给定每个位置的估计需求、从一个工厂到另一个工厂的可变运输成本、拥有工厂的固定成本(基于工厂规模)以及基于工厂规模的生产能力(低产能为 500,高产能为 1500)。你会如何用最小的成本解决这个问题?
来源
需求栏显示每个地点的估计需求
列 A 到 E 显示了从索引中的位置到列中的每个位置的运输成本(即,从工厂 B 到工厂 D 的运输成本是 14)
“高 C”和“低 C”列显示了在每个位置拥有高容量和低容量工厂的固定成本(即,在位置 E 拥有低容量工厂的固定成本为 6500 美元)
- 为了解决这个问题,我们首先需要初始化我们的模型和决策变量。有两个决策变量;
- 在工厂 I 生产并运送到工厂 j 的生产数量(连续变量)
- 生产工厂的生产能力(二进制变量:如果生产能力为 s 的位置 I 的工厂开放,则为 1;如果工厂关闭,则为 0)
约束条件包括:
- 总产量必须等于总需求
- 总产量可以小于或等于总生产能力
#Initialize model
model = LpProblem('Facility Location Problem', LpMinimize)#Define decision variables
loc = ['A', 'B', 'C', 'D', 'E']
size = ['Low_C','High_C']x = LpVariable.dicts('production_', [(i,j) for i in loc for j in loc], lowBound=0, upBound=None, cat='Continuous')
y = LpVariable.dicts('plant_', [(i,s) for s in size for i in loc], lowBound=None, upBound=None, cat='Binary')#Define model
model += (lpSum([fix_cost.loc[i,s] * y[(i,s)] for s in size for i in loc]) + lpSum([var_cost.loc[i,j] * x[(i,j)] for i in loc for j in loc]))
因为 solve()方法返回 1,所以解是最优的,我们可以打印结果。
- 结果:
- 从结果中可以看出,该模型建议在地点 C 开设一个低产能工厂,在地点 A、D 和 e 开设高产能工厂。地点 B 的需求建议由地点 C 提供。这样做,我们可以实现最小成本$58850.9。
# Define constraints
for j in loc:
model += lpSum([x[(i, j)] for i in loc]) == demand.loc[j,'Demand']for i in loc:
model += lpSum([x[i, j] for j in loc]) <= lpSum([capacity.loc[i,s] * y[i,s] for s in size])
# Solve
model.solve()
对模型和解决方案进行健全性检查
# Results for production quantities
[{'prod':'{} to {}'.format(i,j), 'quantity':x[(i,j)].varValue}
for i in loc for j in loc]# Results for plant capacities based on location
[{'lowCap':y[(i,size[0])].varValue, 'highCap':y[(i,size[1])].varValue}
for i in loc]# Objective Value
print('Objective = ', value(model.objective))
工作流程图
prod quantity
A to A 145.4
A to B 0.0
A to C 0.0
A to D 0.0
A to E 1219.6
B to A 0.0
B to B 0.0
B to C 0.0
B to D 0.0
B to E 0.0
C to A 0.0
C to B 84.1
C to C 156.4
C to D 176.8
C to E 0.0
D to A 0.0
D to B 0.0
D to C 0.0
D to D 1500.0
D to E 0.0
E to A 0.0
E to B 0.0
E to C 0.0
E to D 0.0
E to E 1500.0 lowCap highCap
A 0.0 1.0
B 0.0 0.0
C 1.0 0.0
D 0.0 1.0
E 0.0 1.0Objective = 58850.9
一旦您调用了求解方法model.solve()
并打印了解的状态LpStatus[model.status]
,您可以收到以下结果。
最优:模型和约束运行良好,解决方案可行。您可以通过检查变量是否在预期范围内来继续。
不可行:没有可行的解。您可以回过头来查看约束条件。
无界:意味着目标函数是无界的,并且趋于无穷大。你可以回头回顾一下目标函数。
- 未定义:最优解可能存在,但可能没有找到。可以考虑复习一下模型。
- 未解决:解决问题前的状态。可以考虑复习一下模型。
- 如果模型状态为最佳,您可以继续并检查结果是否在预期范围内。如果是,那么模型就完成了。
- 高级主题:敏感性分析
- 如果您想要回答一些业务问题,例如如果需求增加一个单位,成本会增加多少,换句话说,需要多少利润来弥补这样的成本增加,您可以检查双值。如果您想了解约束条件是否有约束力,以及如果没有约束力,哪一个约束条件在未来需求增长的生产能力中有空间,您还可以检查每个约束条件的松弛度。
双值表示约束右侧每个单位变化的目标函数变化量。因此,如果地点 A 的需求增加 1 个单位,总成本将增加 8 美元,如果地点 B 的需求增加 1 个单位,总成本将增加 13 美元,依此类推。
每个限制的时差表示每个限制未使用的资源量。如果松弛值等于 0,则约束是绑定的,如果松弛值大于 0,则意味着它不是绑定的。在示例中,我们可以看到约束条件 C6 和 C8 没有约束力,这意味着它们没有充分利用其生产能力。在位置 A 有增加 135 产量的空间,在位置 C 有增加 82.7 产量的空间。
我希望您喜欢这些例子,并发现这篇文章对您的线性编程之旅很有用。
# Print Dual Value and Slack[{'name':name, 'dual value':c.pi, 'slack': c.slack}
for name, c in model.constraints.items()]name dual value slack
C1 8.0 -0.0
C2 13.0 -0.0
C3 8.0 -0.0
C4 10.0 -0.0
C5 12.0 -0.0
C6 0.0 135.0
C7 -7.0 -0.0
C8 0.0 82.7
C9 -7.0 -0.0
C10 -6.0 -0.0
如果你喜欢这篇文章,你可以 在这里阅读我的其他文章和* 关注我上媒*如果有任何问题或建议,请告诉我。✨
喜欢这篇文章吗? 成为会员求更!
I hope you enjoyed following the examples and found the article useful in your journey towards linear programming.
If you liked this article, you canread my other articles hereand follow me on Medium.Let me know if you have any questions or suggestions.✨**
Enjoy this article? Become a member for more!
如何用三个简单的步骤区分梯度下降目标函数
原文:https://towardsdatascience.com/how-to-differentiate-gradient-descent-objective-function-in-3-simple-steps-b9d58567d387?source=collection_archive---------26-----------------------
拿起笔和纸
在 Unsplash 上拍摄的 ThisisEngineering RAEng
如今,我们可以了解通常为学术团体保留的领域。从人工智能到量子物理学,我们可以浏览互联网上的大量信息并从中受益。
然而,信息的可用性有一些缺点。我们需要意识到大量未经证实的来源,充满了事实错误(这是一个完全不同的讨论主题)。更重要的是,我们可以习惯于通过谷歌搜索来轻松获得答案。因此,我们经常认为它们是理所当然的,并在没有更好理解的情况下使用它们。
我们自己发现事物的过程是学习的一个重要部分。让我们参加这样一个实验,计算一个线性回归的梯度下降算法背后的导数。
一点点介绍
线性回归是一种统计方法,可以用来模拟变量之间的关系[1,2]。它由一个线性方程描述:
线方程(图片由作者提供)。
我们有两个参数θ₀和θ₁和一个变量x。有了数据点,我们可以找到最佳的参数来拟合我们的数据集线。
将直线拟合到数据集(图片由作者提供)。
好,现在梯度下降[2,3]。它是一种迭代算法,广泛用于机器学习(有许多不同的风格)。我们可以用它来自动找到我们生产线的最佳参数。
为此,我们需要优化由以下公式定义的目标函数:
线性回归目标函数(图片由作者提供)。
在这个函数中,我们迭代数据集中的每个点 (xʲ,yʲ) 。然后我们为 xʲ 计算一个函数 f 的值,以及当前的θ参数(θ₀、θ₁)。我们取一个结果,然后减去 yʲ。最后,我们将它平方并加到总和中。
然后在梯度下降公式(每次迭代更新θ₀和θ₁)中,我们可以在方程的右边找到这些神秘的导数:
梯度下降公式(图片由作者提供)。
这些是目标函数Q(θ)的导数。有两个参数,需要计算两个导数,每个θ一个。让我们继续,用 3 个简单的步骤来计算它们。
第一步。链式法则
我们的目标函数是一个复合函数。我们可以认为它有一个【外层】功能和一个【内层】功能[1]。为了计算复合函数的导数,我们将遵循链式法则:
链式法则公式(图片由作者提供)。
在我们的例子中, "outer" 部分是关于将括号内的所有内容( "inner function" )提升到 2 次方。根据规则,我们需要将“外部函数”的导数乘以“内部函数”的导数。看起来是这样的:
将链式法则应用于目标函数(图片由作者提供)。
第二步。权力规则
下一步是计算幂函数的导数[1]。让我们回忆一下一个导数幂律公式:
幂律公式(图片由作者提供)。
我们的【外函数】只是一个二次幂的表达式。所以我们把 2 放在整个公式之前,剩下的就不做了( 2 -1 = 1 ,表达式的一次幂就是那个表达式)。
在第二步之后,我们有:
将幂法则应用于目标函数(图片由作者提供)。
我们还需要计算一个【内函数】(公式右侧)的导数。让我们进入第三步。
第三步。常数的导数
最后一条规则是最简单的。它用于确定常数的导数:
常数的导数(图片由作者提供)。
作为常数意味着,没有变化,常数的导数等于零[1]。例如f’(4)= 0。
记住这三条规则,让我们来分解一下“内在功能”:
内函数导数(图片由作者提供)。
我们的梯度下降目标函数的棘手之处在于 x 不是一个变量。 x 和 y 是来自数据设定点的常数。当我们寻找我们生产线的最佳参数时,θ₀和θ₁是变量。这就是为什么我们计算两个导数,一个关于θ₀,一个关于θ₁.
让我们开始计算相对于θ₀的导数。这意味着θ₁将被视为常量。
相对于θ₀的内部函数导数(图片由作者提供)。
你可以看到常数部分被设置为零。θ₀怎么了?因为它是一个一次幂的变量( a =a ),所以我们应用了幂法则。这导致θ₀被提升到零的幂。当我们将一个数提升到零的幂时,它等于 1 ( a⁰=1 )。就是这样!我们对θ₀的导数等于 1。
最后,我们得到了关于θ₀:的整体导数
关于θ₀的目标函数导数(图片由作者提供)。
现在是时候计算关于θ₁的导数了。这意味着我们把θ₀视为一个常数。
关于θ₁的内部函数导数
与前面的例子类似,θ₁被视为一个一次幂的变量。然后,我们应用了一个幂法则,它将θ₁减少到 1。然而θ₁乘以 x ,所以我们最终得到的导数等于x
关于θ₁的导数的最终形式如下:
关于θ₁的目标函数导数(图片由作者提供)。
完全梯度下降配方
我们计算了梯度下降算法所需的导数!让我们把它们放在它们该在的地方:
包含目标函数导数的梯度下降公式(图片由作者提供)。
通过做这个练习,我们对公式的起源有了更深的理解。我们并不把它当作我们在旧书中找到的魔咒,而是积极地经历分析它的过程。我们把这个方法分解成更小的部分,我们意识到我们可以自己完成计算,然后把它们放在一起。
时不时抓起笔和纸,解决一个问题。你可以找到一个你已经成功使用的公式或方法,并试图通过分解它来获得更深层次的洞察力。它会给你很大的满足感,激发你的创造力。
参考书目:
- K.a .斯特劳德,德克斯特 j .布斯,工程数学,ISBN:978–0831133276。
- Joel Grus,从头开始的数据科学,第二版,ISBN:978–1492041139
- 乔希·帕特森,亚当·吉布森,深度学习,ISBN:978–1491914250
抛弃 Excel!Python 入门
原文:https://towardsdatascience.com/how-to-ditch-excel-a-primer-to-python-c4a9c192e993?source=collection_archive---------27-----------------------
熊猫流行 excel 的一行程序
约瑟夫·陈(Joseph Chan)在 Unsplash 上拍摄的照片:Excel 是这位甜美的女士第一次实习时发明的
Excel 过去是,现在是,将来也永远是一个优秀的工具。它的精巧令人敬畏,优雅超越贝拉·哈迪德。自从 python 出现以来,人们很难忽视它提供的易用性和灵活性。该说的都说了,该做的都做了,继续前进仍然是最大的数据优势。因此,不管你是哪种类型的数据人,或者即使你只是偶尔使用它,习惯 python 也是值得的(它是免费的)。你会问为什么是 Python?
- 如果能够超越就像组装宜家家具,那么能够 python 就像做木匠。你可以创造更多的奇迹。
- 因为其他人都在这么做。
- 用乔治·马洛里的话说,因为它就在那里。
让我们从一些基本功能开始。为了简单起见,我们只谈熊猫图书馆。启动 python 并执行以下操作:
import pandas as pd
之后,将所有文件读入文件名变量:
file1 = pd.read_excel(‘path/to/your/file1.xlsx’)
Excel: VLOOKUP
熊猫等同:合并
使用 VLOOKUP,您可以尝试从另一个文件中的一个 excel 列中查找一个值。您将首先:
a.在所需的列上按字母顺序对两个文件进行排序
b.使用公式:
=VLOOKUP(A2, Area in columns, column to be returned,FALSE)
来获得输出。
熊猫的对等词是一个更简单、更容易理解的合并词。这与在所需的公共列上连接数据集是一样的。在将文件 1 和 2 作为文件 1 和文件 2 导入和读入后,它是一条语句:
file1 = file1.merge(file2[['columns', 'you', 'want', 'to' ,'return']], how=’left’,on=’common-column-to-look-for’)
瞧啊。
现在保存您的结果:
pd.to_excel('save/here/path/filename.xlsx')
COUNTIF
熊猫等值: value_counts()
通常,您会希望计算一个列中某个元素的出现次数。在 excel 中,您可以这样做:
=COUNTIF(area-to-search,value-to-search-for)(#and drag it down)
接下来,您将删除重复项以获取值计数。
在 pandas 中,您可以使用下面的一个命令行程序来实现这一点:
file1[‘Column which needs counting’].value_counts()
瞧啊。
value_counts()结果
整齐
pandas equivalent:str . strip()
在大多数文件中,看不见的空白是一种真正的痛苦。在 excel 中,我们创建一个新列并应用公式
= TRIM('cell which needs trimming') #and drag it down
对熊猫来说,这又是一句俏皮话:
file1.column_that_needs_stripping = file1.column_that_needs_stripping.str.strip()
删除所有空间
pandas equivalent:str . replace(" ","")
通常,修剪是不够的。整个列中都有不需要的空间。我习惯于在 excel 中选择列,搜索和替换空格。
Pandas 提供了一个简单的解决方案来替换列的所有字符串中的空格:
file1[‘column_to_delete_all_spaces’] = file1[‘column_to_delete_all_spaces’].str.replace(" ","")
串联
熊猫等值: +
字符串连接是 excel 中另一种流行的方法。假设您想要连接多个单元格,您可以在 excel 中这样做:
= CONCATENATE(Cell1,Cell2,Cell3,Cell4……)
找到每一个单元格并把它打下来真的很乏味。熊猫也为此提供了一个优雅的俏皮话,如下:
file1['new_column']= file1['first_col'] +’if_space_or_other_string_needed_here’+ file1['second_column']
CountA
熊猫当量:。notnull()。总和( )
Excel 的 CountA 对选定区域中所有非零单元格进行计数,并返回所有包含某些值的单元格。
= COUNTA(range)
计算非零值的 pandas 等价的一行程序如下:
file1[‘column_to_count’].notnull().sum()
相反,如果您想获得所有为 null 的列值,您可以将 notnull 更改为 isnull,瞧!
file1[‘column_to_count’].isnull().sum()
IFERROR
熊猫等同:菲尔娜( )
通过定义一个错误填充值,可以用 IFERROR 在 excel 中处理诸如零除法错误之类的错误。
= IFERROR(Formula that might have an error, “Value to return if error occurs”)
在 pandas 中,您可以通过使用 fillna()来完成这种错误处理
file1 = file1.fillna('Value_you_want_to_fill')
左/右
在 excel 中,您可以使用以下公式提取左侧 n 个数字或字母:
= LEFT(Cell, number of digits you want)
= RIGHT(Cell, number of digits you want)
与此相对应的熊猫如下。将“:”符号读作直到或从:
left_five_digits = file1['column'].str[:5]right_five_digits = file1['column'].str[-5:]
#the minus indicates 5 from the end, without minus, it means 5 from left
这些是我每天经常在 excel 中使用的函数,现在我经常在 python 中以惊人的速度使用它们。我希望这本书能激励你做出改变,因为每一秒都是值得的。
如何——抛弃 Ubuntu,转而使用 Arch Linux 作为深度学习工作站
原文:https://towardsdatascience.com/how-to-ditching-ubuntu-in-favor-of-arch-linux-for-a-deep-learning-workstation-c7ffae120f32?source=collection_archive---------13-----------------------
我为什么要抛弃 Ubuntu?
你们中的大多数人可能在他们的工作站上使用 Ubuntu,这对于没有经验的用户来说很好。我在使用 Ubuntu 和 Tensorflow/CUDA 时遇到的一个问题是,处理 CUDA、cudnn、Tensorflow 等不同的驱动程序和版本是一件非常困难的事情。我不知道你,但一旦我有了一个工作 Tensorflow 1.15 或 2.0 环境,我通常不会再碰它,因为害怕弄乱这个神圣的配置。
使用不同的程序,如果能像使用 Google Colab 一样,在两个最常用的 TensorFlow 版本 1.15 和 2.0 之间进行切换,那就太好了,但是安装不同的 TensorFlow 版本通常会再次搞乱我的系统。
此外,Arch 一直在我的任务清单上,因为它是你能得到的最“准系统”的 Linux 发行版,这意味着与 Ubuntu 这样的“更高抽象”相比,你更接近于硬件。用他们自己的话说,Ubuntu 是为了“开箱即用,让新用户的安装过程尽可能简单”而构建的,而 Arch Linux 的座右铭是“定制一切”。与 Ubuntu 相比,更接近硬件拱门的方式要快得多(比 Windows 领先几英里),代价是更多的终端使用。
当我在过去几周使用 Arch 时,RAM 的使用通常比 Ubuntu 少一半,安装机器学习包也很容易。我可以让 TensorFlow 1.15 和 2.0 一起工作,在 Anaconda 环境中切换版本。此外,该系统工作非常稳定,因为我使用的是 Linux 的 LTS(长期支持)内核,并且通常著名的 AUR(Arch 中的用户定制包)的更新比 Debian (Ubuntu)包提前一个月发布。
总而言之,我只能照原样推荐建立一个 Arch Linux 深度学习站:
- 更快,像包会装超级快,深度学习超级增压,…
- 更稳定
- 与 Ubuntu 相比,更容易在 TensorFlow 版本之间切换。
我将把操作方法分成两部分,第一部分是“如何安装 Arch Linux”,第二部分是“如何安装深度学习工作站包”。
对于一般的“如何安装 Arch Linux”,请阅读本文。
如果 Arch 目前太复杂,你可以试试 Manjaro ,它是 Arch 的一个用户友好版本,尽管我不能保证所有的包都一样工作,因为它们略有不同。总之,它应该是一样的。
我在考虑创建一个现成的安装映像(iso 或 img),如果有足够多的人感兴趣,请在下面留下评论或给我发消息!
在新的 Arch Linux 安装上安装深度学习(TensorFlow、CUDA、CUDNN、Anaconda)设置
一旦你完成了拱门的安装(唷!)让我们先更改一些设置,让我们的系统工作得更稳定。
1.切换到最快的镜像
软件从所谓的“镜像”下载,镜像是包含所有 Arch 库的服务器。如果没有自动完成,可能会出现您的服务器尚未优化的情况。因此,我们将安装一个名为“reflector”的小工具来查找并保存速度最快的服务器
安装反射器,使用
须藤 pacman -S 反射器
查找并下载最好的服务器
反射器–verbose-l 20-n 20–排序速率–save/etc/pacman . d/mirror list
检查输出是否有意义,例如,域是否靠近您的位置。如果没有,您可以添加国家标签以获得更精确的结果,例如德国和奥地利:
reflector -c "AT,DE "-verbose-l 20-n 20-sort rate-save/etc/pacman . d/mirror list
更新您的安装
须藤 pacman -Syyu
2.改变桌面环境
如果你正在使用 Manjaro 或者选择了 Ubuntu 上的“Gnome”桌面环境,考虑改变它可能是值得的,因为众所周知 Gnome 比 Chrome 消耗更多的 RAM,而且我们的深度学习设置肯定需要 RAM。
如果你喜欢 Gnome,可以跳过这一步。另外,我可以推荐 Xfce 桌面,因为它是轻量级和丰富功能的良好结合。
下载 Xfce
sudo pacman-S xfc E4 xfc E4-goodies lxdm
Lxdm 是一个显示管理器,允许您使用多个桌面。
注销当前会话,然后按 Alt + F2(如果无效,则按 Alt + F3)获得一个终端。首先禁用 Gnome,然后“激活”Xfce:
停用并卸载 gnome:
sudo systemctl 禁用 GDM
sudo pacman-R gnome-extras
激活 Xfce
sudo systemctl 使能 lxdm
sudo systemctl 启动 lxdm
如果新的 Xfce 桌面确实打开了,只需登录并浏览,如果没有,尝试重启(sudo 重启)。如果没有帮助,继续哭,在地板上打滚,然后给我发消息或评论。
3.安装 LTS(长期支持)Linux 内核以获得更好的稳定性
Arch 以非常接近当前的 Linux 内核而闻名,如果你总是想要最新的包和 Linux 特性,这是一个好主意,但如果你正在构建一个深度学习工作站,这是一个坏主意。
这就是为什么我转而使用 LTS 内核的原因,它基本上比新版的 Linux 内核获得了更多的支持,也更加稳定。
幸运的是,在 Arch 中切换内核非常容易。首先,我们将下载内核,然后告诉引导管理器选择哪个内核。
首先下载 LTS 内核:
sudo pacman-S Linux-lts Linux-lts-headers
看看您当前的内核版本:
ls -lsha /boot
一个内核应该被命名为 vmlinuz-linux.img 和 initramfs-linux.img(您当前的版本), LTS 的内核也是如此,末尾带有-lts。
如果您看到两个内核,现在可以删除旧的内核:
sudo pacman -R linux
现在一个更高级的部分是你需要告诉你的引导装载程序选择哪个内核。问题是你用的是哪个 bootloader,但大多数情况下是 Grub。如果你遵循我的 Arch 安装教程,你的引导程序是 systemd-boot。
我的建议是尝试 Grub 的说明,如果不工作,继续其他的。
更改 LTS linux 内核的 Grub 引导加载程序
grub-mkconfig-o/boot/grub/grub . CFG
如果您看到一个错误,继续下一个引导加载程序,否则重新启动(sudo 重新启动)。
更改 LTS linux 内核的 syslinux 引导加载程序
编辑配置文件:
sudo nano/boot/sys Linux/sys Linux . CFG
只需将"-lts "添加到 vmlinuz-linux.img 和 initramfs-linux.img 中,它们就是 vmlinuz-linux-lts.img 和 initramfs-linux-lts.img
更改 LTS linux 内核的 systemd-boot 引导加载程序
如果你来自我的 Arch 安装指南,这是你的引导程序。
编辑配置文件:
sudo nano/boot/loader/entries/arch . conf
只需将"-lts "添加到 vmlinuz-linux.img 和 initramfs-linux.img 中,它们就是 vmlinuz-linux-lts.img 和 initramfs-linux-lts.img
4.安装 yay,一个安装 AUR 软件包的简单方法
你应该更喜欢使用超快的 pacman 来安装大多数软件包,但是 Arch 的一个惊人之处在于用户创建了数百万个超级容易安装的自定义软件包。你基本上可以在这个回购里找到任何你能想到的方案。
安装 git SVC
sudo pacman-S git
mkdir ~/tmp
git 克隆https://aur.archlinux.org/yay-git.git~/tmp/yay
CD ~/tmp/yay
makepkg-si
现在你可以浏览 https://aur.archlinux.org/packages/所有的 AUR 套餐,或者直接输入:
yay -S【包装】
来安装它。
5.最后,运行 TensorFlow 1.15 和 2.0 的真实 cuda、cudnn、anaconda 安装
安装 Nvidia 驱动程序,cuda,cudnn 与一个简单的命令
sudo pacman-S NVIDIA NVIDIA-utils cuda cud nn
这需要一些时间,所以喝杯咖啡或者继续下一步
下载 Anaconda,我喜欢 Miniconda:
wgethttps://repo . anaconda . com/miniconda/miniconda 3-latest-Linux-x86 _ 64 . sh~/
使其可执行并安装
cd ~/
chmod +x ./Miniconda。sh
。/Miniconda。sh
一切都保持默认。
来源。/bash_profile
重启你的系统
sudo 重启
安装 tensorflow
现在是决定 TensorFlow 用于 CPU 还是 GPU 的时候了。我将继续使用 GPU 选项,但如果您想运行 CPU 版本,只需从包名中删除“-gpu”即可。
为 Tensorflow 2.0 创建一个 anaconda 环境
conda create–name TF 2.0
conda activate TF 2.0
conda install pip
conda install tensor flow-GPU pandas numpy
搞定了。现在用以下命令检查结果:
python
从 tensorflow.python.client 导入 device _ lib
device _ lib . list _ local _ devices()
如果结果显示这样的设备名称,您就完成了!
2018–05–01 05:25:25.929575:I tensor flow/core/common _ runtime/GPU/GPU _ device . cc:1356]找到具有属性的设备 0:名称:GeForce GTX 3080 10GB 主要:…
为 Tensorflow 1.15 创建一个 anaconda 环境
conda deactivate
conda create–name TF 1.15
conda activate TF 1.15
conda install pip python = = 3.7
conda install tensor flow-GPU = = 1.15
并再次检查是否一切正常,您的 gpu 是否被识别:
python
从 tensorflow.python.client 导入 device _ lib
device _ lib . list _ local _ devices()
6.在一台设备上切换 TensorFlow 1.15 和 TensorFlow 2.0!
只是梦想成真在我看来,只要选择 1.15 版本与
康达激活 tf1.15
和 TensorFlow 2.0 版本
康达激活 tf2.0
如何对熊猫数据帧进行自定义排序
原文:https://towardsdatascience.com/how-to-do-a-custom-sort-on-pandas-dataframe-ac18e7ea5320?source=collection_archive---------1-----------------------
你应该知道的一些最有用的熊猫把戏
照片由印尼 UX在 Unsplash 上拍摄
Pandas DataFrame 有一个内置的方法sort_values()
来根据给定的变量对值进行排序。该方法本身使用起来相当简单,但是它不适用于自定义排序,例如,
- t 恤尺码:
XS
、S
、M
、L
、XL
- 月份:
Jan
、Feb
、Mar
、Apr
、…。等等 - 星期几:
Mon
、Tue
、Wed
、Thu
、Fri
、Sat
和Sun
。
在这篇文章中,我们将看看如何对熊猫数据帧进行自定义排序。
请查看我的 Github repo 获取源代码
看看这个问题
假设我们有一个关于服装店的数据集:
df = pd.DataFrame({
'cloth_id': [1001, 1002, 1003, 1004, 1005, 1006],
**'size': ['S', 'XL', 'M', 'XS', 'L', 'S'],**
})
作者制作的数据
我们可以看到,每块布料都有一个 尺寸 值,数据应该按以下顺序排序:
XS
特大号S
用于小型M
为中等L
为大号XL
特大号
但是,调用sort_values('size')
时会得到如下输出。
输出不是我们想要的,但在技术上是正确的。在幕后,sort_values()
是按照数字数据的数字顺序或对象数据的字符字母顺序对值进行排序。
以下是两种常见的解决方案:
- 为自定义排序创建新列
- 使用
CategoricalDtype
将数据转换为有序的类别类型
为自定义排序创建新列。
在这个解决方案中,需要一个映射数据帧来表示自定义排序,然后根据映射创建一个新列,最后我们可以根据新列对数据进行排序。让我们借助一个例子来看看这是如何工作的。
首先,让我们创建一个映射数据帧来表示自定义排序。
df_mapping = pd.DataFrame({
**'size': ['XS', 'S', 'M', 'L', 'XL'],**
})sort_mapping = df_mapping.**reset_index().set_index('size')**
用于自定义排序的映射数据框架
之后,使用来自sort_mapping
的映射值创建一个新列 size_num 。
df['**size_num**'] = df['size'].**map(sort_mapping['index'])**
最后,按新列 size_num 对值进行排序。
df.sort_values('**size_num**')
使用排序映射数据框架进行自定义排序
这当然有助于我们的工作。但是它创建了一个备用列,在处理大型数据集时效率可能会降低。
我们可以使用CategoricalDtype
更有效地解决这个问题。
使用CategoricalDtype
将数据转换为有序的类别类型
CategoricalDtype
是一种具有类别和有序性的分类数据类型[1]。这对于创建自定义排序非常有用[2]。让我们借助一个例子来看看这是如何工作的。
首先,让我们进口CategoricalDtype
。
from pandas.api.types import **CategoricalDtype**
然后,创建一个定制的类别类型cat_size_order
,用
- 第一个参数设置为
['XS', 'S', 'M', 'L', 'XL']
为布料尺寸的唯一值。 - 这个变量的第二个参数
ordered=True
将被视为有序分类。
**cat_size_order** = CategoricalDtype(
**['XS', 'S', 'M', 'L', 'XL']**,
**ordered=True**
)
之后,调用astype(cat_size_order)
将尺寸数据转换为自定义类别类型。通过运行df['size']
,我们可以看到 大小 列已经被转换为带有顺序[XS < S < M < L < XL]
的类别类型。
>>> df['size'] = df['size']**.astype(cat_size_order)**
>>> df['size']0 S
1 XL
2 M
3 XS
4 L
5 S
Name: size, **dtype: category**
**Categories (5, object): [XS < S < M < L < XL]**
最后,我们可以调用相同的方法对值进行排序。
df.**sort_values('size')**
这个好用多了。让我们来看看在引擎盖下到底发生了什么。
用序列查看类别codes
属性。cat
访问器
现在 size 列已经被转换为 category 类型,我们可以使用[Series.cat](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.cat.html)
访问器来查看分类属性。在引擎盖下,它使用类别代码来表示有序分类中的位置。
让我们创建一个新列 代码 ,这样我们就可以并排比较 大小 和 代码 值。
df['codes'] = df['size']**.cat.codes**
df
我们可以看到XS
、S
、M
、L
、XL
分别有一个代码0
、1
、2
、3
、4
、5
。代码是实际值在类别类型中的位置。通过运行df.info()
,我们可以看到 代码 为 int8 。
>>> df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 cloth_id 6 non-null int64
1 size 6 non-null category
**2 codes 6 non-null int8 **
dtypes: category(1), int64(1), int8(1)
memory usage: 388.0 bytes
按多个变量排序
接下来,让我们把事情变得复杂一点。这里,我们将通过多个变量对数据帧进行排序。
df = pd.DataFrame({
'order_id': [1001, 1002, 1003, 1004, 1005, 1006, 1007],
'customer_id': [10, 12, 12, 12, 10, 10, 10],
'month': ['Feb', 'Jan', 'Jan', 'Feb', 'Feb', 'Jan', 'Feb'],
'day_of_week': ['Mon', 'Wed', 'Sun', 'Tue', 'Sat', 'Mon', 'Thu'],
})
类似地,让我们创建两个自定义类别类型cat_day_of_week
和cat_month
,并将它们传递给astype().
**cat_day_of_week** = CategoricalDtype(
['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
ordered=True
)**cat_month** = CategoricalDtype(
['Jan', 'Feb', 'Mar', 'Apr'],
ordered=True,
)df['day_of_week'] = df['day_of_week'].astype(**cat_day_of_week**)
df['month'] = df['month'].astype(**cat_month**)
要按多个变量排序,我们只需将一个列表传递给sort_values()
即可。例如,按 月 和 星期几 排序。
df.sort_values(**['month', 'day_of_week']**)
按 月 和 星期几 排序。
并按 客户 _ id月份 和 星期 _ 日 排序。
df.sort_values(**['customer_id', 'month', 'day_of_week']**)
按 customer_id 、 月 和 日 _ 周 _ 日 排序。
好了
感谢阅读。
请在我的 Github 上查看笔记本的源代码。
如果你对机器学习的实用方面感兴趣,请继续关注。
你可能会对我的其他一些熊猫文章感兴趣:
- 使用 Numpy select()和 where()方法在 Pandas 上创建条件列
- 何时使用 Pandas transform()函数
- Pandas 中应用()和转换()的区别
- 使用熊猫方法链接提高代码可读性
- 在熊猫数据帧中处理日期时间
- 熊猫阅读 _csv()你应该知道的招数
- 用 Pandas read_csv() 解析日期列应该知道的 4 个技巧
更多可以从我的 Github 中找到
参考
- 【1】熊猫。CategoricalDtype API
- [2] 熊猫分类分类类型教程
如何使用 Jupyter 笔记本、Kafka 和 NLTK 进行实时情感分析
原文:https://towardsdatascience.com/how-to-do-a-sentiment-analysis-in-realtime-using-the-jupyter-notebook-kafka-and-nltk-4470aa8c3c30?source=collection_archive---------25-----------------------
关于将 Kafka 的流数据处理到 Jupyter 笔记本的教程
在本文中,我们将讨论如何使用 Jupyter 笔记本对来自 Kafka 集群的数据进行情感分析。
我们将使用:
- kafka: 我们将使用 kafka 的融合版本作为我们的流媒体平台
- ksql: 这是一项来自 confluent 的技术,它让我们能够在 kafka 的基础上创建表,并使我们能够实时运行 sql 查询。很酷吧?
- jupyter 笔记本:我们运行分析的环境
- docker compose: 我们将使用它在本地创建我们自己的 kafka 集群
- NLTK: 使用 vader 算法的 python 情感分析库
TL;DR:整个项目代码在Github上。
Pexels.com
步骤 1:运行 docker compose
在第一步中,我们需要运行 docker compose 来创建我们的 kafka 集群。这将运行一堆 docker 容器,这些容器将创建集群的各种元素,如 zookeeper、brokers、topics、ksql。
现在简单地说,kafka 是一个分布式流媒体平台,能够处理大量的消息,这些消息被组织成主题。为了能够并行处理一个主题,必须将它分成多个分区,来自这些分区的数据存储在称为代理的独立机器中。最后,zookeeper 用于管理集群中代理的资源。这是卡夫卡经典版本中的元素。合流平台增加了 ksql 作为查询引擎。
在项目的根目录下运行docker-compose up
将会创建集群。如果一切运行成功,您应该会看到类似下图的内容。
服务将在端口8088
上运行,kafka 代理将在端口9092
上可用。我们需要这些信息从朱庇特联系到卡夫卡。当你完成集群上的工作时,你可以通过运行docker-compose down.
来停止所有的容器
步骤 2:安装附加的依赖项
我们正在使用一些以前可能没有用过的 python 包,因此我们需要安装它们。在项目的根,我们有一个requirements.txt
文件。要安装它,请在控制台中运行以下命令:
pip install -r requirements.txt
第三步:运行卡夫卡制作程序
为了能够实时消费数据,我们首先必须将一些消息写入 kafka。我们将使用 python 中的confluent_kafka
库来编写一个生产者:
我们将发送一些非常简单的JSON
消息{ 'data' : value }
,其中 value 是预定义列表中的一个句子。对于每条消息,我们写入队列,我们还需要分配一个键。我们将根据uuid
随机分配一个,以在集群中实现良好的分布。最后,我们还运行一个flush
命令来确保所有的消息都被发送出去。
一旦我们运行confluent_kafka_producer
,我们应该会收到一个日志,告诉我们数据已经正确发送:
we’ve sent 6 messages to 127.0.0.1:9092
步骤 4:创建 ksql 表
接下来,我们需要创建 ksql 客户端,它将帮助我们运行该接口的所有命令:
client = KSQLAPI(url='[http://localhost:8088'](http://localhost:8088'), timeout=60)
我们现在可以创建一个用于查询数据的表:
client.create_table(table_name='test_data',
columns_type=['data varchar'],
topic='test',
value_format='JSON',
key='data')
与我们的JSON
消息类似,该表只有一个名为 data 的字段,类型为varchar
,适合我们的字符串句子。
一旦我们运行了表创建命令,我们就可以通过检查我们有哪些可用的 ksql 表来检查一切是否运行成功:
client.ksql('show tables')
我们应该能够看到我们创建的那个:
[{'@type': 'tables',
'statementText': 'show tables;',
'tables': [{'format': 'JSON',
'isWindowed': False,
'name': 'TEST_DATA',
'topic': 'test',
'type': 'TABLE'}]}]
第五步:从卡夫卡那里获得一些结果,并应用情感分析
我们现在可以在 kafka 上运行SQL
查询。让我们从它那里得到最新的 5 条消息:
res = client.query('select * from test_data limit 5')
为了能够更容易地处理这些数据,我们对其进行解析,并将其存储到一个字典中:
def parse_results(res):
res = ''.join(res)
res = res.replace('\n', '')
res = res.replace('}{', '},{')
res = '[' + res + ']'
return json.loads(res)res_dict = parse_results(res)
最后,我们可以对这 5 个句子运行我们的情感分析算法。如前所述,我们将使用来自NLTK
的预训练vader
算法:
def apply_sent(res):
sent_res = []
for r in res:
sid = SentimentIntensityAnalyzer()
try:
sent_res.append(sid.polarity_scores(r['row']['columns'][2]))
except TypeError:
print('limit reached')
return sent_ressend_res = apply_sent(res_dict)
我们将TypeError
视为已经到达消息列表末尾的信号。我们可以想象结果:
[{'compound': 0.6369, 'neg': 0.0, 'neu': 0.323, 'pos': 0.677},
{'compound': 0.6249, 'neg': 0.0, 'neu': 0.423, 'pos': 0.577},
{'compound': -0.5423, 'neg': 0.467, 'neu': 0.533, 'pos': 0.0},
{'compound': 0.0, 'neg': 0.0, 'neu': 1.0, 'pos': 0.0},
{'compound': 0.4215, 'neg': 0.0, 'neu': 0.517, 'pos': 0.483}]
每行代表一个句子的结果,情绪可以是积极的、中性的或消极的。就是这个!我们可以看到,只需几个步骤,我们就可以在 Jupyter notebook 中处理和分析实时数据,这种环境对于数据科学家来说很容易使用。
如何在 R 中一次对多个变量进行 t 检验或方差分析
原文:https://towardsdatascience.com/how-to-do-a-t-test-or-anova-for-many-variables-at-once-in-r-and-communicate-the-results-in-a-6defaa712e5?source=collection_archive---------8-----------------------
了解如何在 R 中一次比较多个变量的样本,并以更好的方式交流结果
Teemu Paananen 拍摄的照片
介绍
作为我在比利时一所大学担任助教的一部分,学生们经常要求我帮助他们完成硕士论文的统计分析。
一个常见的问题是如何根据几个定量连续变量来比较各组患者。我们大多数人都知道:
- 要比较两组,应使用学生的 t 检验和 1
- 要比较三组或更多组,应进行 ANOVA
这两个测试是非常基本的,并且在网上和统计学教科书中有广泛的记载,所以困难不在于如何进行这些测试。
过去,我通常按照以下三个步骤进行分析:
- 绘制说明分组分布情况的箱线图(如果我想使用
[{ggplot2}](https://www.statsandr.com/blog/graphics-in-r-with-ggplot2/)
包,请使用boxplot()
函数或感谢[{esquisse}](https://www.statsandr.com/blog/rstudio-addins-or-how-to-make-your-coding-life-easier/#esquisse)
R Studio 插件 - 根据要比较的组数进行 t 检验或 ANOVA(分别使用
t.test()
和oneway.test()
功能进行 t 检验和 ANOVA) - 对每个变量重复步骤 1 和 2
只要只有几个变量需要测试,这是可行的。尽管如此,大多数学生来找我,要求不是对一两个变量进行这种测试,而是对多个变量进行测试。因此,当有不止一个变量需要测试时,我很快意识到我在浪费时间,必须有一种更有效的方法来完成这项工作。
注意 :您必须非常小心在执行多重测试时可能出现的 多重测试 (也称为多重性)的问题。简而言之,当进行大量的统计测试时,一些会有PP-值小于 0.05,这完全是偶然的,即使所有的零假设事实上都是真的。这就是所谓的多重测试。您可以通过使用 Bonferroni 校正等方法来解决这个问题。Bonferroni 校正是一种简单的方法,它允许进行许多 t 检验,同时仍然确保保持总体置信水平。为此,您可以使用 α = 0.05m 而不是使用标准阈值 α=5α=5 %作为显著性水平,其中 m 是 t 检验的次数。例如,如果您用期望的 α = 0.05 进行 20 次 t 检验,Bonferroni 修正意味着当PP-值小于 α = 0.05 / 20 = 0.0025 时,您将拒绝每个单独检验的零假设。
还要注意,没有普遍接受的方法来处理多重比较的问题。通常,你应该选择一个你的听众熟悉的或者你的研究领域中的p-价值调整措施。Bonferroni 校正易于实现。然而,如果您有大量的测试要执行,这是不合适的(假设您想要进行 10,000 次 t-测试,一个p-值必须小于 0.05 / 10000 = 0.000005 才是有效的)。更强大的方法也是使用 Benjamini-Hochberg 或 Holm 程序来调整错误发现率( McDonald 2014 )。
另一种选择是使用多变量方差分析(MANOVA)。当因变量相关时,这尤其有用。因变量之间的相关性为 MANOVA 提供了以下优势:
- 识别几个因变量之间的模式:自变量可以影响因变量之间的关系,而不是影响单个因变量。
- 解决多重测试的问题:使用 MANOVA,错误率等于显著性水平(不需要p-值调整方法)。
- 更大的统计功效:当因变量相关时,MANOVA 可以识别出 ANOVA 检测不到的太小的效应。
本文旨在从技术角度展示一种执行多重 t 检验和 ANOVA 的方法(如何在 R 中实现)。关于使用哪种调整方法或是否有更合适的模型来拟合数据的讨论超出了本文的范围(因此请务必理解使用下面的代码进行您自己的分析的含义)。在解释结果之前,确保测试方差分析的假设。
一次执行多项测试
因此,我写了一段代码,通过绘制箱线图并一次对几个变量进行测试来自动化这个过程。下面是我使用的代码,用iris
数据集说明了这个过程。Species
变量有 3 个级别,所以让我们删除一个,然后画一个箱线图,并对所有 4 个连续变量同时应用 t-test。注意,我们想要测试的连续变量是iris
数据集中的变量 1 到 4。
dat <- iris# remove one level to have only two groups
dat <- subset(dat, Species != "setosa")
dat$Species <- factor(dat$Species)# boxplots and t-tests for the 4 variables at once
for (i in 1:4) { # variables to compare are variables 1 to 4
boxplot(dat[, i] ~ dat$Species, # draw boxplots by group
ylab = names(dat[i]), # rename y-axis with variable's name
xlab = "Species"
)
print(t.test(dat[, i] ~ dat$Species)) # print results of t-test
}
##
## Welch Two Sample t-test
##
## data: dat[, i] by dat$Species
## t = -5.6292, df = 94.025, p-value = 1.866e-07
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -0.8819731 -0.4220269
## sample estimates:
## mean in group versicolor mean in group virginica
## 5.936 6.588
##
## Welch Two Sample t-test
##
## data: dat[, i] by dat$Species
## t = -3.2058, df = 97.927, p-value = 0.001819
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -0.33028364 -0.07771636
## sample estimates:
## mean in group versicolor mean in group virginica
## 2.770 2.974
##
## Welch Two Sample t-test
##
## data: dat[, i] by dat$Species
## t = -12.604, df = 95.57, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -1.49549 -1.08851
## sample estimates:
## mean in group versicolor mean in group virginica
## 4.260 5.552
##
## Welch Two Sample t-test
##
## data: dat[, i] by dat$Species
## t = -14.625, df = 89.043, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -0.7951002 -0.6048998
## sample estimates:
## mean in group versicolor mean in group virginica
## 1.326 2.026
正如您所看到的,上面的代码画了一个箱线图,然后一次性打印出每个连续变量的测试结果。
在过去的某个时候,我甚至编写代码来:
- 画一个箱线图
- 检验方差的相等性(感谢 Levene 的检验)
- 根据方差是相等还是不相等,应用适当的检验:如果方差不相等,则应用韦尔奇检验,如果方差相等,则应用学生的 t 检验(参见关于两个样本的不同版本的 t 检验的更多详细信息)
- 一次对所有连续变量应用步骤 1 至 3
我有一个类似的 ANOVA 代码,以防我需要比较两个以上的组。
代码相对来说做得不错。事实上,由于这段代码,我能够以自动化的方式测试几个变量,因为它可以一次比较所有变量的组。
从一个项目到另一个项目,我必须改变的唯一事情是,我需要修改分组变量的名称和要测试的连续变量的编号(上面代码中的Species
和1:4
)。
简明易懂的结果
t 检验
尽管它运行得很好,并且只需稍加修改就可以应用于不同的项目,但我仍然对另一点不满意。
精通统计学和 R 的人可以毫无困难地阅读和解释 t 检验的输出。然而,正如您在自己的统计项目中可能已经注意到的,大多数人不知道在结果中寻找什么,当他们在一个文档中看到如此多的图表、代码、输出、结果和数值时,有时会有点困惑。他们很容易被大量的信息淹没。
在我的旧 R 程序中,当我必须向我的学生解释 R 输出以便他们能够正确解释结果时,我通过自动化 t-tests 和 ANOVA 过程节省的时间就(部分)损失了。虽然大多数时候它只是简单地指出在输出中寻找什么(例如,p-值),但我仍然损失了相当多的时间,因为在我看来,这些输出对于大多数实际应用来说太详细了。换句话说,太多的信息似乎让许多人感到困惑,所以我仍然不相信这是向非科学家分享统计结果的最佳方式。
当然,他们向我寻求统计建议,所以他们期望得到这些结果,我需要给他们问题和假设的答案。尽管如此,我还是想找到一种更好的方法,用最少的信息将这些结果传达给这种类型的观众。不多也不少。
在网上花了很长时间试图找出一种以更简洁和可读的方式呈现结果的方法后,我发现了[{ggpubr}](https://cran.r-project.org/web/packages/ggpubr/index.html)
包。该软件包允许在基于 ggplot2 的图形上直接显示所使用的测试和测试的p-值。它还有助于为非高级统计受众创建可供出版的图表。
在对最初的代码(在这篇文章中可以找到)进行了许多改进和修改之后,我终于想出了一个相当稳定和健壮的过程,可以一次对多个变量进行 t 检验和 ANOVA,更重要的是,使结果简明易懂,任何人(无论是否是统计学家)都可以读懂。
一张图胜过千言万语,所以下面是与上一节完全相同的测试,但这次是用我新的 R 例程:
library(ggpubr)# Edit from here #
x <- which(names(dat) == "Species") # name of grouping variable
y <- which(names(dat) == "Sepal.Length" # names of variables to test
| names(dat) == "Sepal.Width"
| names(dat) == "Petal.Length"
| names(dat) == "Petal.Width")
method <- "t.test" # one of "wilcox.test" or "t.test"
paired <- FALSE # if paired make sure that in the dataframe you have first all individuals at T1, then all individuals again at T2
# Edit until here # Edit at your own risk
for (i in y) {
for (j in x) {
ifelse(paired == TRUE,
p <- ggpaired(dat,
x = colnames(dat[j]), y = colnames(dat[i]),
color = colnames(dat[j]), line.color = "gray", line.size = 0.4,
palette = "npg",
legend = "none",
xlab = colnames(dat[j]),
ylab = colnames(dat[i]),
add = "jitter"
),
p <- ggboxplot(dat,
x = colnames(dat[j]), y = colnames(dat[i]),
color = colnames(dat[j]),
palette = "npg",
legend = "none",
add = "jitter"
)
)
# Add p-value
print(p + stat_compare_means(aes(label = paste0(..method.., ", p-value = ", ..p.format..)),
method = method,
paired = paired,
# group.by = NULL,
ref.group = NULL
))
}
}
从上面的图表中可以看出,每个变量只显示了最重要的信息:
- 借助箱线图对各组进行直观比较
- 统计测试的名称
- 测试的p-值
当然,专家可能对更高级的结果感兴趣。然而,这个简单而完整的图表,包括了测试的名称和 p 值,提供了所有必要的信息来回答这个问题:“组是不同的吗?”。
根据我的经验,我注意到学生和专业人士(尤其是那些来自科学背景不太好的人)对这些结果的理解要远远好于上一节中给出的结果。
对于您自己的项目,唯一需要修改的代码行是分组变量的名称(上面代码中的Species
)、您想要测试的变量的名称(Sepal.Length
、Sepal.Width
等)。)、 2 是否要应用 t 检验(t.test
)或 Wilcoxon 检验(wilcox.test
)以及样本是否配对(FALSE
如果样本独立,TRUE
如果配对)。
基于这些图表,即使对于非专家来说,也很容易解释结果并得出结论versicolor
和virginica
物种在所有 4 个变量方面存在显著差异(因为所有的p-值< 0.05/4 = 0.0125(请注意,Bonferroni 校正用于避免多重测试的问题,因此我们将通常的α水平除以 4,因为有 4 个 t 测试))。
其他 p 值校正方法
如果您想使用另一种p-值调整方法,您可以使用p.adjust()
功能。以下是上面找到的原始p-值,以及从主要调整方法中得出的p-值(以数据框形式显示):
raw_pvalue <- numeric(length = length(1:4))
for (i in (1:4)) {
raw_pvalue[i] <- t.test(dat[, i] ~ dat$Species,
paired = FALSE,
alternative = "two.sided"
)$p.value
}df <- data.frame(
Variable = names(dat[, 1:4]),
raw_pvalue = round(raw_pvalue, 3)
)df$Bonferroni <-
p.adjust(df$raw_pvalue,
method = "bonferroni"
)
df$BH <-
p.adjust(df$raw_pvalue,
method = "BH"
)
df$Holm <-
p.adjust(df$raw_pvalue,
method = "holm"
)
df$Hochberg <-
p.adjust(df$raw_pvalue,
method = "hochberg"
)
df$Hommel <-
p.adjust(df$raw_pvalue,
method = "hommel"
)
df$BY <-
round(p.adjust(df$raw_pvalue,
method = "BY"
), 3)
df## Variable raw_pvalue Bonferroni BH Holm Hochberg Hommel BY
## 1 Sepal.Length 0.000 0.000 0.000 0.000 0.000 0.000 0.000
## 2 Sepal.Width 0.002 0.008 0.002 0.002 0.002 0.002 0.004
## 3 Petal.Length 0.000 0.000 0.000 0.000 0.000 0.000 0.000
## 4 Petal.Width 0.000 0.000 0.000 0.000 0.000 0.000 0.000
无论p-值调整方法如何,这两个物种对于所有 4 个变量都是不同的。注意,调整方法应在查看结果之前选择,以避免根据结果选择方法。
下面的另一个功能允许一次执行多个学生 t 检验或 Wilcoxon 检验,并选择p-值调整方法。该函数还允许指定样本是否成对,以及方差是否相等。(代码改编自马克·怀特。)
t_table <- function(data, dvs, iv,
var_equal = TRUE,
p_adj = "none",
alpha = 0.05,
paired = FALSE,
wilcoxon = FALSE) {
if (!inherits(data, "data.frame")) {
stop("data must be a data.frame")
} if (!all(c(dvs, iv) %in% names(data))) {
stop("at least one column given in dvs and iv are not in the data")
} if (!all(sapply(data[, dvs], is.numeric))) {
stop("all dvs must be numeric")
} if (length(unique(na.omit(data[[iv]]))) != 2) {
stop("independent variable must only have two unique values")
} out <- lapply(dvs, function(x) {
if (paired == FALSE & wilcoxon == FALSE) {
tres <- t.test(data[[x]] ~ data[[iv]], var.equal = var_equal)
} else if (paired == FALSE & wilcoxon == TRUE) {
tres <- wilcox.test(data[[x]] ~ data[[iv]])
} else if (paired == TRUE & wilcoxon == FALSE) {
tres <- t.test(data[[x]] ~ data[[iv]],
var.equal = var_equal,
paired = TRUE
)
} else {
tres <- wilcox.test(data[[x]] ~ data[[iv]],
paired = TRUE
)
} c(
p_value = tres$p.value
)
}) out <- as.data.frame(do.call(rbind, out))
out <- cbind(variable = dvs, out)
names(out) <- gsub("[^0-9A-Za-z_]", "", names(out)) out$p_value <- ifelse(out$p_value < 0.001,
"<0.001",
round(p.adjust(out$p_value, p_adj), 3)
)
out$conclusion <- ifelse(out$p_value < alpha,
paste0("Reject H0 at ", alpha * 100, "%"),
paste0("Do not reject H0 at ", alpha * 100, "%")
) return(out)
}
应用于我们的数据集,没有针对 p 值的调整方法:
result <- t_table(
data = dat,
c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"),
"Species"
)result## variable p_value conclusion
## 1 Sepal.Length <0.001 Reject H0 at 5%
## 2 Sepal.Width 0.002 Reject H0 at 5%
## 3 Petal.Length <0.001 Reject H0 at 5%
## 4 Petal.Width <0.001 Reject H0 at 5%
使用霍尔姆(1979)的调整方法:
result <- t_table(
data = dat,
c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"),
"Species",
p_adj = "holm"
)result## variable p_value conclusion
## 1 Sepal.Length <0.001 Reject H0 at 5%
## 2 Sepal.Width 0.002 Reject H0 at 5%
## 3 Petal.Length <0.001 Reject H0 at 5%
## 4 Petal.Width <0.001 Reject H0 at 5%
同样,使用霍尔姆的调整方法,我们得出结论,在 5%的显著性水平上,这两个物种在所有 4 个变量方面彼此显著不同。
方差分析
下面同样的过程用一个方差分析。注意,这次我们重新加载数据集iris
以包括所有三个Species
:
dat <- iris# Edit from here
x <- which(names(dat) == "Species") # name of grouping variable
y <- which(names(dat) == "Sepal.Length" # names of variables to test
| names(dat) == "Sepal.Width"
| names(dat) == "Petal.Length"
| names(dat) == "Petal.Width")
method1 <- "anova" # one of "anova" or "kruskal.test"
method2 <- "t.test" # one of "wilcox.test" or "t.test"
my_comparisons <- list(c("setosa", "versicolor"), c("setosa", "virginica"), c("versicolor", "virginica")) # comparisons for post-hoc tests
# Edit until here # Edit at your own risk
for (i in y) {
for (j in x) {
p <- ggboxplot(dat,
x = colnames(dat[j]), y = colnames(dat[i]),
color = colnames(dat[j]),
legend = "none",
palette = "npg",
add = "jitter"
)
print(
p + stat_compare_means(aes(label = paste0(..method.., ", p-value = ", ..p.format..)),
method = method1, label.y = max(dat[, i], na.rm = TRUE)
)
+ stat_compare_means(comparisons = my_comparisons, method = method2, label = "p.format") # remove if p-value of ANOVA or Kruskal-Wallis test >= alpha
)
}
}
就像 t 检验的改进程序一样,我注意到学生和非专业人士理解以这种方式呈现的方差分析结果比默认的 R 输出要容易得多。
每个变量一张图,很容易看出所有物种在所有 4 个变量方面彼此不同。
如果您想对您的数据应用相同的自动化过程,您将需要修改分组变量的名称(Species
)、想要测试的变量的名称(Sepal.Length
等。),是否要执行 ANOVA ( anova
)或 Kruskal-Wallis 检验(kruskal.test
),并最终指定事后检验的比较。 3
更进一步
正如我们已经看到的,这两个改进的 R 例程允许:
- 对少量或大量的变量进行 t 检验和 ANOVA,只对代码进行微小的修改。我基本上只需要替换变量名和我想使用的测试名。测试一个或几个变量几乎需要相同的时间,因此与一次测试一个变量相比,这是一个很大的改进
- 以一种更恰当、更干净的方式分享测试结果。这是可能的,因为有一张图显示了各组的观察结果以及该图中包含的适当测试的 p 值。当向更广泛的受众或来自不同背景的人传达结果时,这一点尤为重要。
然而,就像我的大多数 R 例程一样,这两段代码仍然是一个正在进行的工作。以下是我一直在思考的一些附加功能,这些功能可以在未来添加,以使比较两个或更多组的过程更加优化:
- 增加通过数据框中的编号选择变量的可能性。目前,只有通过他们的名字才能做到。这将允许进一步自动化这个过程,因为我们可以简单地输入
4:25
(例如测试变量 4 到 25),而不是一个接一个地输入所有的变量名。 - 增加选择一种p-值调整方法的可能性。目前,原始的p-值显示在图表中,之后我会手动调整它们。
- 当比较两个以上的组时,目前只能应用 ANOVA 或 Kruskal-Wallis 检验。一个主要的改进将是增加执行重复测量 ANOVA 的可能性(即,当样本相关时的 ANOVA)。目前已经可以用两个配对的样本进行 t 检验,但还不能用两个以上的组进行同样的检验。
- 在比较 2 个以上组时,另一个不太重要(但仍然很好)的特征是仅在 ANOVA 或 Kruskal-Wallis 检验的无效假设被拒绝的情况下自动应用事后检验(因此,当至少有一个组与其他组不同时,因为如果相等组的无效假设没有被拒绝,我们不应用事后检验)。目前,我根据 ANOVA 或 Kruskal-Wallis 测试的全局 p 值,手动添加或删除显示事后测试的 p 值的代码。
我将在未来尝试添加这些功能,或者如果{ggpubr}包的作者在包含这些功能时需要帮助,我将很乐意提供帮助(我希望他会看到这篇文章!).
最后但同样重要的是,一些读者可能会对以下软件包感兴趣:
- 如果你想在图表上报告统计结果,我建议你检查
[{ggstatsplot}](https://indrajeetpatil.github.io/ggstatsplot/)
包,特别是[ggbetweenstats()](https://indrajeetpatil.github.io/ggstatsplot/articles/web_only/ggbetweenstats.html)
函数。该功能允许在多组或多种条件下比较连续变量。请注意,图表上显示了许多不同的统计结果,不仅仅是测试名称和 p 值。然而,为了结合可视化和可靠的统计分析的优点,在图表中包含测试结果仍然是非常方便的。 [{compareGroups}](https://cloud.r-project.org/web/packages/compareGroups/index.html)
包也提供了一个比较组的好方法。它配有一个真正完整的闪亮应用程序,可用于:
# install.packages("compareGroups")
library(compareGroups)
cGroupsWUI()
感谢阅读。我希望这篇文章能帮助你同时对多个变量进行 t 检验和方差分析,并使结果更容易被非科学家阅读和解释。了解更多有关比较两个样本的 t-test 或比较三个或更多样本的 ANOVA 的信息。
和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。
相关文章:
- 新冠肺炎冠状病毒前 7 名资源
- 如何手动执行单样本 t 检验,并对一个平均值进行 R:检验
- 每个数据科学家都应该知道的概率中的 9 个概念和公式
- 学生的 R 和手工 t 检验:如何在不同场景下比较两组
- R 中的相关图:如何突出显示数据集中最相关的变量
参考
霍尔姆,斯图。1979."一个简单的顺序拒绝多重测试程序."斯堪的纳维亚统计杂志。JSTOR,65–70 岁。
麦当劳,J.H. 2014。生物统计手册(第 3 版。).马里兰州巴尔的摩斯巴基出版社。
- 理论上,ANOVA 也可以用于比较两组,因为它与学生的 t 检验相比会给出相同的结果,但在实践中,我们使用学生的 t 检验来比较两个样本,ANOVA 来比较三个或更多样本。 ↩
- 不要忘记用
|
分隔你想要测试的变量。 ↩ - 事后检验只是用来指特定类型的统计检验的名称。事后测试包括 Tukey HSD 测试、Bonferroni 校正、Dunnett 测试等。即使 ANOVA 或 Kruskal-Wallis 测试可以确定是否至少有一个组与其他组不同,它也不允许我们得出哪些彼此不同的结论。为此,有一些事后测试,在对多重比较进行调整后,将所有组两两进行比较,以确定哪些组是不同的。具体来说,在 ANOVA 或 Kruskal-Wallis 检验显示至少有一个组不同之后,对每一对可能的组进行事后检验(因此这种检验的名称为“post”)。无效假设和替代假设以及对这些测试的解释类似于学生对两个样本的 t 检验。 ↩
原载于 2020 年 3 月 19 日【https://statsandr.com】。
如何在 Azure Cosmos DB 中对图形数据进行高级分析
原文:https://towardsdatascience.com/how-to-do-advanced-analytics-on-graph-databases-in-azure-cosmos-db-f0a83b4cb5c4?source=collection_archive---------32-----------------------
学习使用 Gremlin 在 Cosmos DB 中编写图形数据,然后使用 GraphFrames 读取/分析 Azure Databricks 中的数据。
0.介绍
Azure Cosmos DB 是一个完全托管的多数据库服务。它使您能够在全球范围内构建高度响应的应用程序。作为 Cosmos DB 的一部分,graph 数据库支持 Gremlin。由于 Cosmos DB 针对快速处理进行了优化( OLTP ),遍历限制可能适用于繁重的分析工作负载( OLAP )。在这种情况下,Azure Databricks 和 GraphFrames 可以用作高级分析的替代方法,参见下面的架构。
0.建筑(作者图片)
在博客的剩余部分,完成了以下工作:
- OLTP:使用 Gremlin API 和 Python 将图形数据写入 Cosmos DB
- OLAP:从 Cosmos DB 读取数据,分析 Azure Databricks 中的数据
最后,在最后一章中得出结论。
1.OLTP:使用 Gremlin API 将数据写入 Cosmos DB
在本章中,Gremlin API 和 Python 将用于向 Cosmos DB 写入数据。因为 Azure Databricks 将在下一章中用于 OLAP,所以 Azure Databricks 集群也用于使用 Gremlin API 将数据写入 Cosmos DB。然而,任何 Python3 环境都可以用来将数据写入 Cosmos DB,例如 Visual Code、PyCharm 或 Azure 函数。执行以下步骤:
- 1.1.安装必备组件
- 1.2.在 Azure 数据块中安装 Gremlin Python 库
- 1.3.获取并运行笔记本
另请参见下面的架构。
1.OLTP:使用 Gremlin API 将数据写入 Cosmos DB(图片由作者提供)
1.1.安装必备组件
需要安装以下先决条件:
- Azure 数据块
- 带 Gremlin API 的 Cosmos DB
在 Cosmos DB 中创建数据库和图形时,可以使用/name 作为分区键。将 PeopleDB 作为数据库的名称,将 friends 作为图形的名称,请参见下文。
1.1./name 作为朋友图和 PeopleDB 数据中的分区键(图片由作者提供)
1.2.在 Azure 数据块中安装 Gremlin Python 库
启动 Azure Databricks 工作区并转到群集。使用 Databricks 运行时版本 6.4 创建一个新集群,并且只有一个工作节点,另请参见下文。
1.2a .创建数据块集群(图片由作者提供)
随后,转到您的集群并单击安装库。然后选择 Pypi 并搜索 gremlinpython,然后单击 install,另见下文。
1.2b .在集群上安装 gremlinpython 库(图片由作者提供)
1.3.获取并运行笔记本
转到您的 Azure Databricks 工作区,右键单击,然后选择导入。在单选按钮中,选择使用 URL 导入以下笔记本:
[https://raw.githubusercontent.com/rebremer/cosmosdb-databricks-olap/master/insert_data_CosmosDB_OLTP_Python_Gremlin.py](https://raw.githubusercontent.com/rebremer/cosmosdb-databricks-olap/master/insert_data_CosmosDB_OLTP_Python_Gremlin.py)
笔记本导入后,您需要更改您的 Cosmos DB 端点的 URL 和您的 Cosmos DB 密钥,这可以在门户中找到,也请参见下文。
1.3a .使用 gremlin API 写入 Cosmos DB 的笔记本(图片由作者提供)
现在选择运行笔记本,数据将被写入 Cosmos DB。验证数据是否存在,另见下文。
1.3b . Cosmos DB 中的数据(图片由作者提供)
在本章中,使用 Gremlin API、Python 和 Azure Databricks 添加了图形数据。在下一章中,将对数据进行分析,其中重复使用了 Databricks 集群。
2.OLAP:获取数据,用 Azure Databricks 进行分析
在本章中,数据是从 Cosmos DB 中检索的,并在 Azure Databricks 中使用 GraphFrames 进行分析。在这种情况下,数据直接从 Azure Databricks 中的 Cosmos DB 读取。由于 Cosmos DB 通常用作 OLTP,因此可能需要首先在 ADLSgen2 中暂存数据,以最小化 Cosmos DB 上的负载,防止在需要大量数据加载时超时,并节省成本。然而,为了简单起见,在这篇博客中,数据直接从 Cosmos DB 读取到 Azure Databricks。执行以下步骤:
- 2.1.在 Azure 数据块中安装 Cosmos DB 和 GraphFrames 库
- 2.2.获取并运行笔记本
另请参见下面的架构。
2.OLAP:从 Cosmos DB 获取图形数据,并使用 GraphFrames 进行分析(图片由作者提供)
2.1.在 Azure 数据块中安装 Cosmos DB 和 GraphFrames 库
Cosmos DB 连接器和 GraphFrames 需要作为 jar 文件安装到上一章创建的集群中。使用此链接下载最新的 uber Cosmos DB 连接器到您的桌面。随后,转到 your Azure Databricks 集群并单击安装库。然后选择 jar 并放下 Jar 文件,也见下文。
2.1a .将 Cosmos DB 连接器安装到集群(图片由作者提供)
随后,使用这个链接下载最新的 GraphFreams,并将其安装在与 Cosmos DB 连接器相同的 was 中。验证所有库是否安装正确,另请参见下文。
2.1b .库安装正确(图片由作者提供)
2.2.获取并运行笔记本
转到您的 Azure Databricks 工作区,右键单击,然后选择导入。在单选按钮中,选择使用 URL 导入以下笔记本:
[https://raw.githubusercontent.com/rebremer/cosmosdb-databricks-olap/master/get_data_cosmosDB_OLAP_Scala_GraphFrames.scala](https://raw.githubusercontent.com/rebremer/cosmosdb-databricks-olap/master/get_data_cosmosDB_OLAP_Scala_GraphFrames.scala)
笔记本导入后,您需要更改您的 cosmos DB 端点的 URL 和您的 Cosmos DB 密钥,这可以在门户中找到,也请参见下文。最后你可以运行笔记本了。在最后一个单元格中,您可以找到标签传播算法的结果,这是在社区检测中使用的,也请参见下文。
2.2.Azure Databricks 中图形的更高级查询(图片由作者提供)
3.结论
Cosmos DB 是 Azure 中的多模型数据库服务,支持图形数据库。由于 Cosmos DB 针对 OLTP 进行了优化,因此遍历限制可能适用于繁重的 OLAP 工作负载。在这种情况下,Azure Databricks 和 GraphFrames 可以用作高级分析的替代方法,参见下面的架构。
3.建筑(作者图片)
2020 年如何做数据科学
原文:https://towardsdatascience.com/how-to-do-data-science-in-2020-e8f729cb65e3?source=collection_archive---------44-----------------------
数据科学项目创意
2020 年数据科学的嗡嗡声就像特斯拉股票;它每天都在增加。这个领域非常热门,从机械工程师到医生,每个人都想成为数据科学家。但是,您将如何进入数据科学领域?加入 DS 训练营?做两三门 MOOCs?参加 Kaggle 比赛?纲要是无止境的。我不是在反驳 MOOCs 甚至 Kaggle 竞赛的优势,它们是学习数据科学的绝佳地点。
然而,问题是每个人都在这么做!我们多久会在泰坦尼克号数据集上看到一些关于他们的 Coursera 专业化或 GitHub 机器学习档案的帖子?如果你不得不找一份数据科学家的工作,你必须完成一些没有人做的事情。从根本上说,你必须将自己与其他竞争者区分开来。做全栈(问题制定、数据收集、数据清理、EDA、ML、部署)数据科学项目将为你提供制高点,同时在你是试图闯入数据科学的新生的情况下明确会面。
https://cdn . pix abay . com/photo/2012/03/01/15/43/brain-20424 _ 1280 . jpg
我最近偶然发现了苏珊的博客,她在博客中解释了我们如何找到最好的数据科学工作。她建议我们应该试着在有识之士工作的地方找一份工作。因此,出于好奇,我最终浏览了 Insight 的网站,主要是为了找到他们工作的公司。但是随着我对他们同事的项目了解的越来越多,我感到惊讶。当然,他们有定量领域的博士学位,但他们的一些项目可以转化为产品。以下是我用的刮刀。
import requestsfrom bs4 import BeautifulSoupresult=requests.get("[https://www.insightdatascience.com/fellows](https://www.insightdatascience.com/fellows)")src=result.contentsoup=BeautifulSoup(src,'lxml')div=soup.divname=[]for row in soup.find_all('div',attrs={"class" : "tooltip_name"}):name.append(row.text)project=[]for row in soup.find_all('div',attrs={"class" : "tooltip_project"}):project.append(row.text)
title=[]for row in soup.find_all('div',attrs={"class" : "toottip_title"}):title.append(row.text)
company=[]for row in soup.find_all('div',attrs={"class" : "tooltip_company"}):company.append(row.text)
d={'Name':name,'Project':project,'Company':company,'Title':title }df=pd.DataFrame(d)
万一你需要做一些很酷的项目,不要停下来从这里获取动力或想法。不管你是否能复制或扩展这个项目,如果你能理解他们做了什么以及他们为什么这么做,这将是巨大的帮助。同样,这也将是面试中一个非同寻常的话题,让你从不同的竞争对手中脱颖而出。
如何进行探索性数据分析
原文:https://towardsdatascience.com/how-to-do-exploratory-data-analysis-e8bfa7db69d9?source=collection_archive---------20-----------------------
从数据中获取洞察力的实用分步指南
探索性数据分析(EDA)通常是任何数据科学项目的第一步,在建立任何机器学习模型之前进行。它的目标是看一看我们获得的原始数据,探索它,并从中收集见解,这不仅可以帮助我们事后改进我们的模型,还可以提供从这些数据中得出的相关业务信息。
在这篇文章中,我们将在真实的数据集上进行广泛的 EDA,以了解可以做什么,如何做,并练习我们的技能。探索性数据分析主要是通过标绘不同的图表,从中推导出相关信息。虽然这看起来很容易,但是知道什么时候使用我们所掌握的每一个可视化工具,以及显示可用信息的最佳实践是很重要的。
同样重要的是,我们要学会如何深入了解我们的数据,这样我们就可以用它来讲述一个故事,吸引我们的听众,并提供有价值的、有用的信息。
为此,我们将使用真实的公共数据集,并涵盖我们将用于对其进行初步数据分析的所有不同步骤,同时解释我们使用的每个绘图工具的优势和劣势。我们走吧!
数据:UCI 银行营销数据集
与平面图标不一致
我们将使用的数据集是公开可用的 ' 银行营销数据集',来自 UCI 机器学习资源库,它是机器学习社区用来测试其算法的数据库、领域理论和数据生成器的集合。
该数据与一家葡萄牙银行机构的直接营销活动相关。这些营销活动是基于电话。在前面的存储库中,您可以找到所有变量的描述。让我们使用三个简单的 pandas 函数快速查看数据包含的内容:
- Head: 使用 head pandas 方法可以让我们看到数据的前 5 行。通过这样做,我们可以快速地看到我们拥有的变量,它们的一些可能的值,以及它们是否是数字的。
给定数据集上 pandas.head()函数的输出
- Info 方法是另一种快速获取相关信息的方法。使用它,我们可以看到我们有多少数据点和特征,以及这些特征的数据类型,以及它们是否有任何缺失值。
给定数据集上 pandas.info()函数的输出
- Describe:Describe 函数主要用于获取数据集的数值变量的信息。您可以看到这些变量的平均值、最大值和最小值,以及它们的标准偏差。从这里已经可以了解到一些很酷的信息。
给定数据集上 pandas.describe()函数的输出
好了,现在我们已经做了一个快速的描述性分析,让我们继续我们来这里的目的:剧情,如何用它们讲故事并获得相关信息。
探索性数据分析:地块和更多地块
来自平板图标的图标
在对 Pandas 进行快速分析以查看数据点的数量和我们拥有的要素的数量,以及它们的类型和缺失值的数量之后,我们很快就了解了我们正在处理的数据的大小、其复杂性以及我们需要完成的填充这些缺失值的工作。现在,我们将开始分析的可视化部分。
在下面的分析中,我们将一步一步地铺平道路,从最初对数据的无知到对数据的深入了解,形成足以回答最相关问题的理解。沿着这条路,我们将使用不同种类的图,每一种都将使用一个具体的例子来解释,涵盖了使用每一种图的最佳实践。
我们将从分析目标变量开始。在我们的数据的情况下,这个变量被清楚地定义,并且因为它是一个二元分类任务,我们已经有了它应该看起来像什么的想法。我们将使用条形图来完成这项工作。让我们来看看!
条形图:可视化与不同类别相关的数量
来自平面图标的图标
条形图表示一个轴上的数值和另一个轴上的不同类别。它们通常用于比较不同组或类别之间的单个数值。在下面的例子中,我们比较了不同类别的目标变量的样本比例。
显示目标变量分布的条形图
从前面的图中我们可以看到,超过 85%的样本具有“否的目标值,大约 12%的样本具有“是的值。这个初始图让我们了解了客户对我们的营销活动的反应(大多数人拒绝),也告诉我们,如果我们计划在使用它之后训练一个机器学习模型,我们可能需要重新平衡数据集。一个情节和两条非常有价值的信息。
让我们继续看看条形图和良好实践的其他用途。如果我们探索一个具有更多类别的变量,例如'教育'变量,我们会得到如下图:
“教育”变量类别的样本数量垂直条形图
从这幅图中我们可以看出,大多数目标人物都有大学学位,很少有人是文盲。当创建这样的图时,它有助于从最高值到最低值排列类别,因为它使可视化更加清晰。在本例中,我们也包括了 N 个样本的绝对值,而不是之前目标变量示例中的百分比。如果我们知道数据点的数量(在这种情况下是联系的人),那么包括百分比值是最有帮助的。如果没有,最好包含绝对的。
从上图中可以注意到一件事,那就是阅读变量不同类别的名称并不容易。为了解决这个问题,我们可以将这些标签旋转 45 度,或者切换到水平条形图,如下图所示。
“教育”变量类别的样本数量的水平条形图
现在我们可以很容易地阅读标签。还要注意给图加一个小标题是多么重要,这样我们就可以很容易地看到我们在谈论什么,也可以适当地给轴命名。在第一个教育变量的例子中,标有“ education ”的轴实际上显示了该变量的不同类别。在水平条形图中,该标签已被正确修改为“教育类别”。
让我们看完与' job '变量对应的一些条形图,它告诉我们受影响的客户所属的工作类别。
工作变量的条形图
左边的柱状图代表了每个工作类别的平均年龄。从中我们可以看到一些显而易见的东西:退休人员的平均年龄最高,而学生的平均年龄最低。
然而,右边的图表更有趣。它反映了每个工作类别相对于我们的目标变量的行为。正如我们之前看到的,对于我们抛出的营销活动,大约 12%是我们的平均接受率。这在图上用水平黑线表示。每列的高度代表被评估变量的每个类别的平均接受率。正如我们所见,学生是最有可能接受我们活动的客户,因为他们的接受率是标准接受率的两倍以上。相反,蓝领工人是最不可能接受的,只有平均接受率的一半。我们是否应该调整我们的活动来增加这类客户的数量?
下图显示了代表目标人员婚姻状况的婚姻变量的相同曲线:
婚姻变量目标分析条形图
正如我们所见,单身人士比已婚或离异人士更有可能对我们的营销活动做出积极反应。这可能是因为他们更年轻,属于学生类别,正如我们之前看到的那样,他们的录取率也很高。我将把这个进一步的调查留给最好奇的读者。
条形图概要: 条形图最常用于比较不同类别或组之间的单个变量值。当使用条形图比较不同的类别时,避免显示很长的类别列表,按高度对列进行排序,当 x 标签很长时,考虑使用水平条形图。
我们现在不会太担心颜色,但它们对于区分不同的类别和使情节更加清晰也很重要。
散点图:数值变量之间的关系
来自平面图标的图标
散点图用于确定两个数值变量之间的关系。它们可以帮助查看两个变量之间是否存在直接关系(例如,正线性关系或负线性关系)。此外,它们可以帮助我们检测我们的数据是否有异常值。如果变量不遵循任何类型的关系,我们可以考虑对它们中的一个进行转换,比如将其转换为对数。
如果数据没有任何直接关系,可视化散点图可以帮助我们看到一些信息,否则会被隐藏。让我们看看下面的例子,它绘制了变量年龄和持续时间的散点图。
年龄与持续时间散点图
从这个图中我们可以看到各种各样的事情:首先,很少有客户保持通话超过 2000 秒。此外,似乎随着年龄的增长,人们的耐心越来越差,挂电话的速度也越来越快。
不幸的是,在这个数据集中没有很多连续的数值,所以我们看不到散点图的更多真实例子。然而,假设我们有一个数据集,包含人们的体重、身高、年龄、性别、职业等特征。如果我们绘制一个身高与体重的散点图,我们可能会看到如下关系
自制身高体重散点图
正如我们所见,这两个变量之间的关系是线性的,正如我们可能预期的那样:个子高的人体重也更重。这再次强调了散点图在寻找两个数值变量之间的关系时非常有用。
在散点图的最后,让我们看看一些好的实践。首先,只有当数值变量是连续的或者可能的值范围很大时,创建数值变量的散点图才有意义。让我们通过下面的例子来看看为什么会这样:
年龄与就业变化率的散点图
它显示了年龄变量与就业变化率的散点图,即就业变化率。尽管这个变量是数字,但它只有 10 个可能的值,所以我们可以看到这个图并不是很有说明性。
散点图总结: 散点图是一种很好的方式来可视化两个连续数值变量之间的关系。当变量尽管是数字,但值的范围非常有限时,请避免使用它们。
箱线图:平均值、方差和异常值
来自平面图标的方框图图标
箱线图是从数值变量中获取信息的另一种方式。具体来说,它们允许我们查看中值、标准差和方差,还可以探索给定变量的值是否有异常值。让我们先看看箱线图给我们的信息,然后从我们的数据集中找到具体的例子。
箱线图向我们展示了我们正在研究的数据变量的中值,它代表了中间数据点的位置。上下四分位数分别代表数据的 75%和 25%。上限和下限显示了数据的最大值和最小值。最后,它也代表离群值。下图显示了一个标准的箱线图。
箱线图
让我们看看这些图表能告诉我们关于我们的数据集的两个真实的数字变量,年龄和持续时间。
数据集的年龄(左)和持续时间(右)变量的箱线图
上图向我们展示了几件事。首先,从右边的一个(持续时间变量)我们可以看到,通话时间通常很短,是大约 300 秒持续时间的中间观察值。我们还可以看到,上四分位数和下四分位数接近中值,异常值会传播到非常高的持续时间长度。
从左边的一个(年龄变量)我们可以看到,我们拥有的所有异常值(超出变量的可接受或正常值范围的值)都超过了顶部:我们不时地接触不寻常的老年人。这可能符合我们的营销策略,也可能是我们必须检查的事情。如果我们想获得没有任何年龄异常值的数据视图,我们可以使用年龄变量进行过滤,并保持任何低于 Q3(大约 70 岁)的数据,然后分析我们得到的结果。
箱线图总结: 箱线图可以让我们快速看到我们数值变量的统计值,无缝检测是否有异常值,而不需要执行复杂的算法。
直方图:数值变量的条形图
来自平面图标的直方图图标
直方图向我们展示了一个数字变量的频率分布。它为此类变量的值构建不同的范围组,称为箱,并告诉我们每个箱内的数据量。核密度估计图是从直方图构建的,正如我们在将仓的数量设置为非常高的值时可以看到的。因此,直方图可用于查看变量是否遵循正态分布,如果遵循正态分布,其偏斜程度如何。我们可以在下图中看到这一点。
年龄和持续时间变量的直方图具有不同数量的条柱。
年龄值的直方图告诉我们,它可能遵循一个正态分布,有点偏左,同样的情况可能发生在持续时间上。正如你所看到的,我们包括的箱越多,我们的图看起来就越像一个适当的分布。如果我们增加年龄变量的箱数,我们会得到如下结果:
年龄变量的 50 格直方图。
现在,我们可以更清楚地看到分布的形状,右边是一条长尾巴。
变量不必遵循特定的分布,就像我们在下面的示例中看到的那样,使用 euribor3m 变量,它表示 3 个月的 euribor 利率。
euribor3m 变量的直方图和箱线图。
从直方图中我们可以看到,变量并不遵循特定的分布,但大多数样本的值都接近 5,这可以从箱线图中提取的中值得到证实。
直方图总结: 直方图就像是数值变量的条形图,其中变量的值被划分在一系列称为 bin 的范围内。它们允许我们看到某个变量的分布,并且当我们增加箱的数量时,它们更好地逼近这个分布。
热图:作为可视化工具的颜色
热图获取一个数据网格(例如矩阵或表格),并使用不同的色阶来显示网格或表格中每个单元格的值。作为一种可视化工具,他们使用颜色就像条形图使用宽度和高度一样。
在数据分析中,它们可用于显示变量数值之间的相关性,如下图所示。
使用热图可视化我们数据的关联矩阵
使用这个矩阵,我们可以看到是否有任何相关的变量,发现我们可能想要深入研究的两者之间的有趣关系,或者我们可以使用它作为一种方法来删除变量,这些变量不会为我们的数据添加任何额外的信息来构建机器学习模型,作为一个特征选择步骤。
在图表上,每个单元格代表两个变量之间的相关性,值从深棕色(强负相关)到深蓝/绿色(强正相关),中间较浅的颜色代表较弱的相关性。这给了我们一个快速发现相关变量的方法。
从上图中我们可以看到 euribor3m 和 nr.employed 变量具有非常高的相关性。我们可以通过绘制两者的散点图来证实这一点:
就业人数与欧洲银行同业拆放利率的散点图
看起来这些变量确实有很强的线性关系,应该做进一步的调查以了解为什么会这样。
结论
至此,我们已经解释完了 EDA 上这篇帖子的所有情节。还有其他像折线图和饼图这样的图,可以添加,但是,它们非常简单,我们大多数人都知道它们是如何工作的,不需要解释。
使用所涵盖的可视化工具来分析我们的数据的不同变量及其关系,可以获得许多有用的信息,这些信息对于最初的业务观点和建模后的观点都是有用的。
我们还总结了一些绘图的最佳实践:重要的是,我们知道何时使用我们所掌握的每一个可视化工具,以及如何仔细优化我们在这些图中显示的内容。
最后,不仅仅要有绘图能力也很重要:我们必须能够阅读这些图并从中提取有用的信息;从中得不到任何东西的阴谋对任何人都没有帮助。
如果你想要这篇文章中任何情节的代码,请随时留下评论,我会发给你。
额外资源
如果你想更深入地挖掘和发展对 EDAR 更深刻的实践和理论知识,请查阅以下资源。
- 自然语言处理的探索性数据分析。
- 评《Python 用于数据分析》一书
- 为自己的数据分析项目设置数据集。
就这些,我希望你喜欢这个帖子。请随时在 Twitter 上关注我。还有,你可以在这里 看看我关于数据科学、统计学、机器学习的帖子。好好读!此外,要获得关于数据科学和机器学习的更多资源,请查看这个包含书籍、课程和教程的令人敬畏的资源库。
干杯!
如何用更少的数据做更多的事?—主动学习
原文:https://towardsdatascience.com/how-to-do-more-with-less-data-active-learning-240ffe1f7cb9?source=collection_archive---------39-----------------------
照片由 Unsplash 上的 Prateek Katyal 拍摄
如果机器学习项目是冰山,那么水下的部分就是项目中的标签和其他数据工作。好消息是像迁移学习和主动学习这样的技术可以帮助减少这种努力。
主动学习已经成为 ML 行业从业者工具箱的一部分有一段时间了,但很少在任何数据科学/ ML 课程中涉及。阅读罗伯特·芒罗的书人类在回路中的机器学习,帮助我将一些(并帮助我学习了许多)主动学习概念正式化,这些概念我一直在我的 ML 项目中直观地使用。
本文的目的是向您介绍一种简单的主动学习方法,称为“熵的不确定性采样”,并通过一个例子展示它的实用性。为了进行演示,我使用了主动学习,仅利用实际训练数据集的23%(ATIS 意图分类数据集)来获得与在 100%的数据集上进行训练相同的结果。
太好奇了?直接跳到演示。想先了解一下它的工作原理?请继续阅读。
什么是主动学习?
主动学习——模型从失败的预测中学到的比正确的预测多。图片提供— giphy
主动学习是指优先根据标签上的例子训练我们的模型,这些例子可以给我们带来最大的收益,而不是根据“学习信号”很少的例子。一个示例的学习信号的估计是使用来自模型的反馈来完成的。
这类似于老师问学生她不清楚的概念,并优先考虑那些概念,而不是教授所有的课程。
由于主动学习是一个迭代的过程,你必须经历多轮培训。主动学习的步骤包括:
主动学习过程
1。识别并标记您的评估数据集。
不言而喻,选择评估集是任何机器学习过程中最重要的一步。当涉及到主动学习时,这变得更加重要,因为这将是我们在迭代标记过程中模型性能改善程度的衡量标准。此外,它还帮助我们决定何时停止迭代。
直接的方法是随机分割未标记的数据集,并从分割的数据集中选取您的评估集。但是基于复杂性或业务需求,拥有多个评估集也是好的。例如,如果您的业务需要表明情绪分析模型应该能够很好地处理讽刺,您可以有两个独立的评估集—一个用于一般的情绪分析,另一个用于讽刺特定的样本。
2.识别并标记你的初始训练数据集。
现在选取 X%的未标记数据集作为初始训练数据集。X 的值可以根据模型和方法的复杂性而变化。选择一个对于多次迭代来说足够快的值,并且对于模型的初始训练来说足够大的值。如果您采用迁移学习方法,并且数据集的分布接近基础模型的预训练数据集,那么较低的 X 值足以启动该过程。
避免初始训练数据集中的类别不平衡也是一个很好的实践。如果是 NLP 问题,您可以考虑基于关键字的搜索来识别来自特定类别的样本,以标记和维护类别平衡。
3.训练迭代
现在我们已经有了初始的训练和评估数据集,我们可以继续进行第一次训练迭代。通常,人们不能通过评估第一个模型来推断太多。但是这一步的结果可以帮助我们看到预测在迭代过程中是如何改进的。使用该模型来预测剩余未标记样本的标签。
4.选择上一步中要标记的样本子集。
这是一个至关重要的步骤,在这一步中,您可以选择具有最多学习信号的样本进行标记过程。有几种方法可以着手做这件事(如书中所解释的)。为了简洁起见,我们将看到我认为最直观的方法——基于熵的不确定性采样。
基于熵的不确定性采样:
不确定性采样是一种挑选模型最不确定/混淆的样本的策略。有几种方法可以计算不确定度。最常见的方法是使用神经网络最后一层的分类概率(softmax)值。
如果没有明确的赢家(即所有的概率几乎相同),这意味着模型对样本是不确定的。熵正好给了我们一个度量。如果所有类别之间有联系,则分布的熵将会很高,如果类别中有明显的赢家,则分布的熵将会很低。
根据模型对未标记数据集的预测,我们应该按照熵的降序对样本进行排序,并挑选大约 Y%的顶级样本进行注释。
5。冲洗&重复:
我们需要将本次迭代中的训练数据集附加上我们标记的新样本,并重复步骤 3 中的过程,直到我们在评估集上达到所需的性能或我们的评估性能稳定水平。
演示
为了实验和演示,我们将使用 ATIS 意图分类数据集。让我们认为训练数据集是未标记的。我们从随机抽取 5%的带标签的训练数据集进行第一次迭代开始。在每次迭代结束时,我们使用基于熵的不确定性采样来挑选前 10%的样本,并在下一次迭代中使用它们的标签(模拟真实世界中的标注过程)进行训练。
为了在主动学习的每次迭代中评估我们的模型,我们还从数据集中提取测试集,因为测试集中的数据已经被标记。
演示和代码可在下面的笔记本中找到:
[## 谷歌联合实验室
colab.research.google.com](https://colab.research.google.com/drive/1BsTuFK8HcXS5WWlOCS1QHgvHRf2FK6aD?usp=sharing)
参考文献:
- 戴维·刘易斯和威廉·盖尔。1994.一种训练文本分类器的顺序算法。94 年,https://arxiv.org/pdf/cmp-lg/9407020.pdf
- 人类在回路中的机器学习由罗伯特·芒罗
感谢 Sriram Pasupathi 付出了比我写这篇文章更多的努力来校对这篇文章🙏
附:我非常高兴听到您对这篇文章的反馈,这也将推动我撰写“如何用更少的数据做更多的事”系列的其他文章,请评论您的反馈或在@ logesh _ umapathi给我发 DM。👋
如何手动进行安全测试:12 种有效方法
原文:https://towardsdatascience.com/how-to-do-security-testing-manually-12-effective-ways-1278bcb251a0?source=collection_archive---------18-----------------------
在 Unsplash 上拍摄的 ThisisEngineering RAEng
对于世界各地的企业来说,网络安全攻击正变得越来越突出。随着攻击的不断发展,大约 68%的商业领袖感到他们的网络安全风险在增加。
不能再忽视安全测试的需要。
虽然一些公司依靠少量的自动化安全测试工具和流程来维护安全合规性,但其他公司利用自动化测试和手动安全测试来确保他们的软件经过全面测试并且安全。
有许多方法可以手动进行安全测试,以测试应用程序的安全状态。在我们深入研究它们之前,让我们仔细看看为什么您应该手动进行安全性测试。
为什么您应该手动进行安全测试?
即使自动化技术发展迅速,仍然有许多因素需要人工注意来验证或准确确定应用程序中潜在的 web 安全漏洞。
一些潜在的漏洞,如业务逻辑问题或加密问题,需要人工来验证漏洞。
这就是为什么您需要手动进行安全性测试。
手动安全测试人员通常使用精选的安全测试软件和工具的组合,这些软件和工具最适合评估他们的应用程序。这些可能包括定制脚本和自动扫描工具。
手动进行安全测试的高级技术包括精确的测试用例,如检查用户控制、评估加密功能,以及彻底分析以发现应用程序中的嵌套漏洞。
手动进行安全测试并不意味着您不能使用自动化。相反,安全专家可以利用自动化技术来寻找模式或其他线索,这些模式或线索可能揭示关于应用程序漏洞的重要信息。
手动安全测试的主要目标是发现应用程序中的弱点和潜在漏洞,这些弱点和漏洞可能无法被自动化安全测试完全理解或发现。
不管使用多少自动化测试软件和工具,手动分析软件行为以确保其完整性、机密性和可用性原则不被违反是至关重要的。
帮助您手动进行安全测试的技术
当应用程序安全性中的任何弱点需要真正的人类判断时,您可以手动进行安全性测试。有一系列手动安全测试技术可以帮助您评估您的应用程序和系统,以确保它们是安全的。
以下是一些关于如何手动进行安全性测试的最有效的方法:
1.监控访问控制管理
无论是 web 应用程序还是计算机,访问控制都是帮助保护您的应用程序安全或系统不被攻击者或内部威胁利用的一个重要方面。
访问控制管理可以分为两个部分:
- 认证—你是谁?
- 授权—您能做什么?您能访问哪些信息?
例如,员工应该只能访问完成其工作所需的信息。
通过实施访问控制,您可以确保只有经过授权的用户才能访问数据或系统。
为了手动测试,测试人员应该创建几个具有不同角色的用户帐户。
然后,测试人员应该尝试使用这些帐户访问应用程序或系统,并验证每个用户帐户只能访问自己的表单、屏幕、帐户、菜单和模块。然后,测试人员可以在不同用户/角色的会话中测试一个用户/角色发出的请求。
如果测试人员能够使用禁用的帐户登录应用程序,他/她就可以记录应用程序的安全性问题。
还有呢?
具有受限或较低访问权限的用户不应该能够访问敏感信息或高权限数据。
您还应该手动测试密码质量规则、默认登录、密码恢复、密码更改、web 安全问题/答案、注销功能等。
类似地,授权测试还应该包括对水平访问控制问题、授权缺失、路径逆转等的测试。
2.动态分析(渗透测试)
渗透测试或 pen 测试,是一种软件测试技术,它使用受控的网络攻击来瞄准正在运行的系统,以确定可能被攻击者利用的漏洞。
运行系统的手动渗透测试包括以下步骤:
- 数据收集 —手动渗透测试的第一步是收集数据,如表名、数据库、第三方插件信息、软件配置等。可以手动完成,也可以使用在线免费提供的测试工具(如网页源代码分析)来完成。
- 漏洞评估 —一旦收集到数据,软件渗透测试团队将对其进行评估,以确定可能使系统面临安全攻击风险的安全风险或漏洞。
- 发起模拟攻击 —渗透测试团队对目标系统发起受控攻击,以探索更多漏洞,并了解他们如何阻止攻击。
- 报告准备 —在针对潜在的漏洞对系统进行了全面的定位和评估之后,软件测试团队创建一份报告,概述测试的发现,以及保护系统所需的措施。
当您想要手动进行渗透测试以增强系统的安全性时,这是您需要遵循的过程。
3.静态分析(静态代码分析)
另一种流行的手工安全测试方法是静态代码分析。它通常作为白盒测试的一部分来执行,也称为代码审查,执行它是为了突出“静态”(非运行)源代码中的潜在漏洞。
静态代码分析使用技术,如数据流分析和污点分析,来确定与系统相关的漏洞。
它是由了解应用程序运行的操作环境和使用应用程序的用户的手动测试人员进行的。这些测试人员知道应用程序的总体目的以及单个功能的目的。
他们将这些知识应用到静态分析工具中,这些工具检查源代码、文档甚至是可执行文件,从而在不实际运行代码的情况下找到漏洞。
静态分析工具在目的和范围上有很大的不同,从代码样式强制到编译器级别的逻辑错误检查等等。
简单地说,静态代码分析帮助您维护安全的代码,而不必实际运行代码。
4.检查服务器访问控制
Web 应用程序有多个用户访问点,它们提供足够的访问来满足用户的请求,但是它们必须维护安全性以避免数据泄露或攻击。
测试人员如何检查服务器访问控制?
测试人员应确保应用程序的所有网络内和网络间接入点都是由预期的机器(IP)、应用程序和用户提供的,并且所有访问都受到严格控制。
为了验证开放的访问点是否受到足够的限制,测试人员应该尝试从具有不可信和可信 IP 地址的各种机器上访问这些点。
此外,应该批量执行各种实时事务,以检查应用程序在负载条件下的性能。
在手动进行安全测试时,测试人员还应该检查应用程序中开放的访问点是否允许用户以安全的方式进行特定的操作。
例如,测试人员可能会上传超过最大允许文件大小的文件,尝试上传受限文件类型,或者从受限站点下载数据,以检查应用程序是否允许此类操作。
检查服务器访问控制的目的是确保当用户能够使用应用程序时,应用程序不会受到潜在的攻击。
5.入口/出口/入口点
测试人员经常检查入口和出口网络点,以确保没有未经授权的网络可以向主机网络发送流量或信息,反之亦然。
什么是入口点和出口点?
入口流量由源自外部网络的所有网络流量和数据通信组成,这些流量和数据通信指向主机网络中的一个节点。另一方面,出口流量由源自网络内部并以外部网络为目标的所有流量组成。
可以通过手动安全测试方法轻松检查网络中的这些入口点,例如尝试将数据从受限网络发送到主机网络,并检查它是否允许流量和接受数据。
测试人员甚至可以将敏感数据或机密信息从主机网络发送到授权的外部网络,以检查出口点是否安全。
入口和出口过滤允许网络彼此交互,同时保持安全标准,并限制未经授权的网络共享敏感数据。
6.会话管理
当您手动进行安全测试时,您应该执行会话管理测试,以检查应用程序是否正确处理会话。
为了确保您的应用程序具有正确的会话管理,请检查特定空闲时间后的会话过期时间、登录和注销后的会话终止时间、最大生存期后的会话终止时间、检查会话持续时间和会话 cookie 范围等。
7.密码管理
在手动测试时,您可以使用的最有效的安全测试技术之一是密码管理。这是指用于发现密码和访问用户帐户或系统的各种方法。
如何测试密码管理?
如果 web 应用程序或系统没有实施严格的密码策略(例如,使用数字、特殊字符或密码短语),就很容易暴力破解密码并访问帐户。
此外,不是以加密格式存储的密码更容易被窃取和直接使用。攻击者可以使用不同的方法来窃取存储在数据库中的信息,例如 SQL 注入。
即使密码以哈希格式存储,一旦被检索,也可以使用 Brutus、RainbowCrack 等密码破解工具或通过手动猜测用户名/密码组合来破解。
8.暴力攻击
另一种手动进行安全测试的方法是使用暴力攻击。
暴力攻击依靠猜测目标密码的不同组合,直到发现正确的密码。
攻击者使用暴力攻击来获取个人识别号、密码、口令或用户名等敏感信息,从而实施身份盗窃、将域重定向到包含恶意内容的站点或其他恶意活动。
应用程序安全测试人员也广泛使用这种方法来测试应用程序的安全性,更具体地说,就是评估应用程序的加密强度。
例如,测试人员应该尝试使用无效密码登录帐户,理想情况下,系统应该在有限次数的多次登录尝试失败后阻止用户。
此外,如果登录尝试是从未知设备或可疑网络进行的,应用程序应该要求进行多因素身份验证,这可能包括发送到用户已验证的电子邮件地址或联系号码的一次性密码,或者用户设置的安全问题。
9.SQL 注入(SQLi)
SQL 注入是一种代码注入技术,用于将恶意 SQL 语句注入到应用程序中,以修改或提取存储在数据库中的数据。
这是最危险、最频繁、最古老的 web 应用程序漏洞之一。它会影响任何使用 SQL 数据库的 web 应用程序,如 Oracle、SQL Server、MySQL 或其他。
如何防止 SQL 注入攻击?
手动测试人员检查 SQL 注入入口点,以确定它是否会被 SQL 注入攻击利用。他们通过接受某些用户输入来识别和测试在数据库上执行直接 MySQL 查询的数据库代码。
例如,应用程序应该能够在输入字段中接受单引号(')。但是如果应用程序向测试人员抛出一个数据库错误,这意味着用户输入已经被插入到数据库的某个查询中,并且已经被执行。
浏览器上显示的 SQL 查询错误消息可能会导致攻击者使整个应用程序崩溃,或者帮助他们提取用户名、密码、信用卡号等数据。
10.跨站点脚本(XSS)
除了 SQL 注入攻击,测试人员还在手动安全测试中检查 web 应用程序的跨站点脚本(即 XSS)。这是一种客户端注入攻击,攻击者的目标是在受害者的浏览器中执行恶意脚本。
这些恶意脚本可以执行各种功能,例如向攻击者发送受害者的登录凭据或会话令牌、记录他们的击键或代表受害者执行任意操作。
在手动测试期间,测试人员必须确保输入字段不信任未经验证的用户输入,并且如果这些字段的输出包含在服务器响应中,则必须对它们进行正确的编码。
此外,保护应用程序免受 XSS 注入攻击的主要方法是应用适当的输入和输出编码。
11.URL 操作
URL 操作是攻击者利用应用程序的另一种技术。它是攻击者出于恶意目的修改统一资源定位器(URL)参数的过程。
如何保护您的应用程序免受 URL 操纵?
手动测试人员应该验证应用程序是否允许在查询字符串中包含敏感信息。当应用程序使用 HTTP GET 方法在服务器和客户端之间传输信息时,就会发生这些类型的攻击。
当向应用程序提供基于 URL 的输入时,它通过查询字符串中的参数传递该信息。测试人员可以改变查询字符串中的参数值,以验证服务器是否接受该值。
用户信息通过 HTTP GET 请求传递给服务器,以获取数据或发出请求。如果测试人员能够操纵通过 GET 请求传递给服务器的输入变量,他们就可以访问未经授权的信息。
12.指定高风险功能
企业每天都要处理大量数据。有数以千计的业务功能需要文件上传/下载、向员工授予用户访问权限、与第三方承包商共享数据以及许多其他可能存在潜在漏洞的活动。
您需要识别高风险功能,以确保为特定活动实施更好的安全措施,例如限制不需要的或恶意的文件上传/下载。
如果您的应用程序处理任何敏感数据,您应该手动检查应用程序的注入漏洞、密码猜测、缓冲区溢出、不安全的加密存储等。
使用这些方法手动进行安全性测试
虽然自动化安全测试有很多好处,但它不足以确保应用程序完全安全。
企业必须进行手动安全测试,以确保应用程序中没有可能被攻击者利用的潜在弱点或漏洞。
通过手动进行适当的安全测试,公司可以检测到业务缺陷和注入漏洞,这些缺陷和漏洞在自动安全测试中可能不明显。
准备好开始了吗?在手动进行安全测试时,您可以使用上面有效的手动安全测试技术。
关于作者:
Steve Kosten 是 Cypress Data Defense 的首席安全顾问,也是 Java/JEE 的 SANS DEV541 安全编码:开发可防御应用程序课程的讲师。
如何在 BigQuery 中进行文本相似性搜索和文档聚类
原文:https://towardsdatascience.com/how-to-do-text-similarity-search-and-document-clustering-in-bigquery-75eb8f45ab65?source=collection_archive---------9-----------------------
在 BigQuery 中使用文档嵌入进行文档相似性和聚类任务
BigQuery 提供了加载 TensorFlow SavedModel 并执行预测的能力。这个功能是在数据仓库上添加基于文本的相似性和聚类的一个很好的方式。
接着从 GitHub 中的 my notebook 复制粘贴查询。你可以在 BigQuery 控制台或人工智能平台 Jupyter 笔记本中尝试这些查询。
文本嵌入对于文档相似性和聚类任务是有用的。图片来自 Pixabay 的 kerttu
风暴报告数据
作为一个例子,我将使用一个由“风暴观察者”打电话到国家气象局的风报告组成的数据集。这是 BigQuery 中的公共数据集,可以按如下方式查询:
SELECT
EXTRACT(DAYOFYEAR from timestamp) AS julian_day,
ST_GeogPoint(longitude, latitude) AS location,
comments
FROM `bigquery-public-data.noaa_preliminary_severe_storms.wind_reports`
WHERE EXTRACT(YEAR from timestamp) = 2019
LIMIT 10
结果看起来像这样:
假设我们想要构建一个 SQL 查询来搜索看起来像“一个家庭的电源线断了”的评论。
步骤:
- 加载一个机器学习模型,创建一些文本的嵌入(本质上是一个紧凑的数字表示)。
- 使用该模型来生成我们的搜索词的嵌入。
- 使用该模型生成风报表中每个注释的嵌入。
- 寻找两个嵌入彼此接近的行。
将文本嵌入模型加载到 BigQuery
TensorFlow Hub 有很多文本嵌入模型。为了获得最佳结果,您应该使用一个模型,该模型已根据与您的数据集相似的数据进行了训练,并且具有足够数量的维度以捕捉文本的细微差别。
对于这个演示,我将使用在 Google News 上训练过的有 20 个维度的旋转嵌入(也就是说,它相当粗糙)。这对我们需要做的事情来说已经足够了。
Swivel 嵌入层已经以 TensorFlow SavedModel 格式提供,因此我们只需下载它,从 tarred、gzipped 文件中提取它,并将其上传到 Google 云存储:
FILE=swivel.tar.gz
wget --quiet -O tmp/swivel.tar.gz [https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1?tf-hub-format=compressed](https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1?tf-hub-format=compressed)
cd tmp
tar xvfz swivel.tar.gz
cd ..
mv tmp swivel
gsutil -m cp -R swivel gs://${BUCKET}/swivel
一旦模型文件在 GCS 上,我们可以将它作为 ML 模型加载到 BigQuery 中:
CREATE OR REPLACE MODEL advdata.swivel_text_embed
OPTIONS(model_type='tensorflow', model_path='gs://BUCKET/swivel/*')
尝试在 BigQuery 中嵌入模型
要在 BigQuery 中试用这个模型,我们需要知道它的输入和输出模式。这些将是导出时 Keras 层的名称。我们可以通过转到 BigQuery 控制台并查看模型的“Schema”选项卡来获得它们:
让我们通过获得一个著名的 August 演讲的嵌入来尝试这个模型,将输入文本作为句子调用,并且知道我们将获得一个名为 output_0 的输出列:
SELECT **output_0** FROM
ML.PREDICT(MODEL advdata.swivel_text_embed,(
SELECT "Long years ago, we made a tryst with destiny; and now the time comes when we shall redeem our pledge, not wholly or in full measure, but very substantially." AS **sentences**))
结果有 20 个数字,如下所示:
文档相似性搜索
定义一个函数来计算一对嵌入之间的欧几里德平方距离:
CREATE TEMPORARY FUNCTION td(a ARRAY<FLOAT64>, b ARRAY<FLOAT64>, idx INT64) AS (
(a[OFFSET(idx)] - b[OFFSET(idx)]) * (a[OFFSET(idx)] - b[OFFSET(idx)])
);CREATE TEMPORARY FUNCTION term_distance(a ARRAY<FLOAT64>, b ARRAY<FLOAT64>) AS ((
SELECT SQRT(SUM( td(a, b, idx))) FROM UNNEST(GENERATE_ARRAY(0, 19)) idx
));
然后,计算我们的搜索词的嵌入:
WITH search_term AS (
SELECT output_0 AS term_embedding FROM ML.PREDICT(MODEL advdata.swivel_text_embed,(SELECT "power line down on a home" AS sentences))
)
并计算每个评论的嵌入和搜索词的 term_embedding 之间的距离(如上):
SELECT
term_distance(term_embedding, output_0) AS termdist,
comments
FROM ML.PREDICT(MODEL advdata.swivel_text_embed,(
SELECT comments, LOWER(comments) AS sentences
FROM `bigquery-public-data.noaa_preliminary_severe_storms.wind_reports`
WHERE EXTRACT(YEAR from timestamp) = 2019
)), search_term
ORDER By termdist ASC
LIMIT 10
结果是:
还记得我们搜索了“家里的电线坏了”吗?请注意,最上面的两个结果是“house 上的 power line down”——文本嵌入有助于识别 home 和 house 在此上下文中是相似的。下一组最佳匹配都是关于电力线的,这是我们搜索词中最独特的一对词。
文档聚类
文档聚类包括使用嵌入作为聚类算法(如 K-Means)的输入。我们可以在 BigQuery 中实现这一点,为了让事情变得更有趣,我们将使用位置和日期作为聚类算法的附加输入。
CREATE OR REPLACE MODEL advdata.storm_reports_clustering
OPTIONS(model_type='kmeans', NUM_CLUSTERS=10) ASSELECT
arr_to_input_20(output_0) AS comments_embed,
EXTRACT(DAYOFYEAR from timestamp) AS julian_day,
longitude, latitude
FROM ML.PREDICT(MODEL advdata.swivel_text_embed,(
SELECT timestamp, longitude, latitude, LOWER(comments) AS sentences
FROM `bigquery-public-data.noaa_preliminary_severe_storms.wind_reports`
WHERE EXTRACT(YEAR from timestamp) = 2019
))
嵌入(output_0)是一个数组,但 BigQuery ML 当前需要命名输入。解决方法是将数组转换为结构:
CREATE TEMPORARY FUNCTION arr_to_input_20(arr ARRAY<FLOAT64>)
RETURNS
STRUCT<p1 FLOAT64, p2 FLOAT64, p3 FLOAT64, p4 FLOAT64,
p5 FLOAT64, p6 FLOAT64, p7 FLOAT64, p8 FLOAT64,
p9 FLOAT64, p10 FLOAT64, p11 FLOAT64, p12 FLOAT64,
p13 FLOAT64, p14 FLOAT64, p15 FLOAT64, p16 FLOAT64,
p17 FLOAT64, p18 FLOAT64, p19 FLOAT64, p20 FLOAT64>AS (
STRUCT(
arr[OFFSET(0)]
, arr[OFFSET(1)]
, arr[OFFSET(2)]
, arr[OFFSET(3)]
, arr[OFFSET(4)]
, arr[OFFSET(5)]
, arr[OFFSET(6)]
, arr[OFFSET(7)]
, arr[OFFSET(8)]
, arr[OFFSET(9)]
, arr[OFFSET(10)]
, arr[OFFSET(11)]
, arr[OFFSET(12)]
, arr[OFFSET(13)]
, arr[OFFSET(14)]
, arr[OFFSET(15)]
, arr[OFFSET(16)]
, arr[OFFSET(17)]
, arr[OFFSET(18)]
, arr[OFFSET(19)]
));
生成的十个集群可以在 BigQuery 控制台中可视化:
集群#1 中的评论看起来像什么?该查询是:
SELECT sentences
FROM ML.PREDICT(MODEL `ai-analytics-solutions.advdata.storm_reports_clustering`,
(
SELECT
sentences,
arr_to_input_20(output_0) AS comments_embed,
EXTRACT(DAYOFYEAR from timestamp) AS julian_day,
longitude, latitude
FROM ML.PREDICT(MODEL advdata.swivel_text_embed,(
SELECT timestamp, longitude, latitude, LOWER(comments) AS sentences
FROM `bigquery-public-data.noaa_preliminary_severe_storms.wind_reports`
WHERE EXTRACT(YEAR from timestamp) = 2019
))))
WHERE centroid_id = 1
结果显示,这些大多是简短的、没有信息的评论:
第三组怎么样?这些报道大部分好像都和雷达验证有关!!!
尽情享受吧!
链接
TensorFlow Hub 有几种文本嵌入模型。你不必使用旋转,虽然旋转是一个很好的通用选择。
完整的问题在 GitHub 上的我的笔记本里。你可以在 BigQuery 控制台或人工智能平台 Jupyter 笔记本中尝试这些查询。
如何在 BigQuery 中进行时间序列预测
原文:https://towardsdatascience.com/how-to-do-time-series-forecasting-in-bigquery-af9eb6be8159?source=collection_archive---------21-----------------------
使用 BigQuery ML 中的 ARIMA 模型进行需求预测
让我们根据过去的六周,对海德公园的一个自行车站开始的自行车租赁数量进行两周预测。
收集培训数据
与任何机器学习问题一样,第一步是收集训练数据并探索它。假设我们有截至 2015 年 6 月中旬的租赁数据,我们希望预测这个月的剩余时间。我们可以使用以下工具收集过去 6 周的数据:
SELECT
CAST(EXTRACT(date from start_date) AS TIMESTAMP) AS date
, COUNT(*) AS numrentals
FROM
`bigquery-public-data`.london_bicycles.cycle_hire
WHERE start_station_name LIKE '%Hyde%' -- all stations in Hyde Park
GROUP BY date
HAVING date BETWEEN '2015-05-01' AND '2015-06-15'
ORDER BY date
绘制该图时,我们看到一种每周趋势,即周末租金上涨:
史料
火车 ARIMA 模型
我们可以使用这些数据来训练 ARIMA 模型,告诉 BigQuery 哪一列是数据列,哪一列是时间戳列:
CREATE OR REPLACE MODEL ch09eu.numrentals_forecastOPTIONS(model_type='ARIMA',
time_series_data_col='numrentals',
time_series_timestamp_col='date') ASSELECT
CAST(EXTRACT(date from start_date) AS TIMESTAMP) AS date
, COUNT(*) AS numrentals
FROM
`bigquery-public-data`.london_bicycles.cycle_hire
WHERE start_station_name LIKE '%Hyde%' -- all stations in Hyde Park
GROUP BY date
HAVING date BETWEEN '2015-05-01' AND '2015-06-15'
一旦模型被训练,我们就可以使用 ML 来评估它。评估()并使用 ML 查看 ARIMA 系数。ARIMA 系数()。
预测
我们可以预测未来 14 天每天的租赁数量,并使用以下公式获得第 90 个百分位数的置信界限:
SELECT * FROM ML.FORECAST(MODEL ch09eu.numrentals_forecast,
STRUCT(14 AS horizon, 0.9 AS confidence_level))
历史、预测和置信界限可以用以下公式绘制:
import matplotlib.pyplot as plt
import pandas as pd
def plot_historical_and_forecast(input_timeseries, forecast_output, timestamp_col_name, data_col_name):
plt.figure(figsize=(20,6))
plt.plot(input_timeseries[timestamp_col_name], input_timeseries[data_col_name], label = 'Historical')
plt.xlabel(timestamp_col_name)
plt.ylabel(data_col_name)forecast_output['forecast_timestamp'] = pd.to_datetime(forecast_output['forecast_timestamp'])
x_data = forecast_output['forecast_timestamp']
y_data = forecast_output['forecast_value']
confidence_level = forecast_output['confidence_level'].iloc[0] * 100
low_CI = forecast_output['confidence_interval_lower_bound']
upper_CI = forecast_output['confidence_interval_upper_bound']# Plot the data, set the linewidth, color and transparency of the
# line, provide a label for the legend
plt.plot(x_data, y_data, alpha = 1, label = 'Forecast', linestyle='--')
# Shade the confidence interval
plt.fill_between(x_data, low_CI, upper_CI, color = '#539caf', alpha = 0.4, label = str(confidence_level) + '% confidence interval')
# Display legend
plt.legend(loc = 'upper center', prop={'size': 16})plot_historical_and_forecast(df, fcst, 'date', 'numrentals')
这会产生:
历史数据和预测数据
但这与 6 月下旬实际发生的情况相比有多好呢?我们可以提取这些天的数据,并与预测时间序列进行比较:
历史、预测和实际发生的情况。
很酷,是吧?
预测一系列
到目前为止,我一直在预测海德公园所有自行车站的总出租量。我们如何预测每个加油站的租赁量?使用时间序列标识列:
CREATE OR REPLACE MODEL ch09eu.numrentals_forecast
OPTIONS(model_type='ARIMA',
time_series_data_col='numrentals',
time_series_timestamp_col='date',
**time_series_id_col='start_station_name'**) AS
SELECT
**start_station_name**
, CAST(EXTRACT(date from start_date) AS TIMESTAMP) AS date
, COUNT(*) AS numrentals
FROM
`bigquery-public-data`.london_bicycles.cycle_hire
WHERE start_station_name LIKE '%Hyde%' -- all stations in Hyde Park
GROUP BY start_station_name, date
HAVING date BETWEEN **'2015-01-01'** AND '2015-06-15'
请注意,我现在不是在 45 天内(5 月 1 日至 6 月 15 日)进行系列训练,而是在更长的时间内进行训练。这是因为总体时间序列比单个站点的时间序列更平滑,也更容易预测。因此,我们必须向模型展示一条更长的趋势线。
现在,这个模型不是一个 ARIMA 模型,而是一个独立的 ARIMA 模型。的确,在做:
SELECT *
FROM ML.ARIMA_COEFFICIENTS(MODEL ch09eu.numrentals_forecast)
ORDER BY start_station_name
为每个起点站名称提供一组单独的系数:
注意一些有趣的事情——每个站点都有不同复杂度的 ARIMA 模型!在引擎盖下,BigQuery ML 进行自动超参数调优。虽然该模型被称为“ARIMA”,但底层算法实际上包括相当多的华而不实的功能,包括异常检测、假日效应建模(用户需要指定假日区域)、季节性检测/建模和趋势建模。另外,不同的时间序列是并行训练的。
当我们进行预测时,我们将获得每个站和时间戳的预测:
SELECT
start_station_name,
forecast_timestamp, forecast_value
FROM ML.FORECAST(MODEL ch09eu.numrentals_forecast,
STRUCT(3 AS horizon, 0.9 AS confidence_level))
ORDER By start_station_name, forecast_timestamp
为每个站点生成一个时间序列预测:
GitHub 上的满满的笔记本里有各站的预报图。
模型评估可能有助于您预测哪个站的模型更好(季节性校正方差越低,预测就越容易,因此,模型应该越好-此处不能使用 AIC,因为不同时间序列的 AIC 不具有可比性):
SELECT * FROM ML.EVALUATE(MODEL ch09eu.numrentals_forecast)
ORDER BY **variance** DESC
基于这些结果,我们预计海德公园角的预测是最差的,骑士桥是最好的:
尽情享受吧!
后续步骤
- 在 GitHub 上浏览完整笔记本。
- 要了解更多关于 BigQuery ML 的内容,请阅读 BigQuery:权威指南的第 9 章。这本书会定期更新这些博客文章,这样它就保持了权威性。
感谢 Xi·程和阿米尔·霍玛蒂的有益建议
如何使用 python 从头开始创建令人惊叹的可视化效果
原文:https://towardsdatascience.com/how-to-do-visualization-using-python-from-scratch-651304b5ee7a?source=collection_archive---------1-----------------------
实践教程
使用 Matplotlib 和 Seaborn 库的分步指南
由卢克·切瑟在 Unsplash 上拍摄的照片
可视化是数据科学家的一项重要技能。良好的可视化有助于清晰地传达分析中确定的见解,也是更好地理解数据集的好方法。与基于阅读或其他方式提取细节相比,我们的大脑在某种程度上更容易从视觉数据中提取模式或趋势。
在本文中,我将从使用 python 的基础开始讲述可视化概念。下面是从基础开始学习可视化的步骤,
- 第一步:导入数据
- 步骤 2:使用 Matplotlib 的基本可视化
- 步骤 3:更高级的可视化,仍然使用 Matplotlib
- 步骤 4:使用 Seaborn 为数据分析构建快速可视化效果
- 第五步:构建互动图表
在这个旅程结束时,你将具备构建可视化所需的一切。虽然我们不会涵盖可以构建的每一个可视化,但您将学习构建图表背后的概念,因此您可以轻松构建本文中没有涵盖的任何新图表。
本文中使用的脚本和数据也可以在 git 资源库这里中找到。本文中使用的所有数据都可以在上述 git 存储库中的“data”文件夹中找到,脚本可以在文件夹“Day23、Day 24 和 Day25”中找到。
导入数据
第一步是读取所需的数据集。我们可以用熊猫来读取数据。下面是一个简单的命令,可用于从 CSV 文件中读取数据
在读取数据集时,重要的是对其进行转换,并使其适合我们将应用的可视化。例如,假设我们有客户级别的销售详细信息,如果我们想要构建一个图表来显示一天的销售趋势,则需要在一天的级别对数据进行分组和汇总,然后使用趋势图。
使用 Matplotlib 的基本可视化
让我们从一些基本的可视化开始。最好使用代码' fig,ax=plt.subplots()',其中' plt.subplots()'是一个函数,它将返回一个带有 fig 和 axes 对象的元组,并分别分配给变量' fig '和' ax '。如果不使用它,你也可以打印一个图表,但是通过使用它,你可以对 figure 进行修改,就像你可以根据它的外观重新调整图表的大小一样,还可以保存图表。类似地,这里的“ax”变量可以用来给轴提供标签。下面是一个简单的例子,我将数据作为数组传递,并直接打印成图表
在上面的代码中,首先导入所需的库,然后使用' plt.subplots()'函数生成图形和轴对象,然后将数据作为数组直接传递给轴对象以打印图表。在第二个图表中,轴变量“ax”接受特定于 x 轴、y 轴和标题的标签的输入。
趋势图表
现在,让我们开始使用一些真实的数据,并了解如何构建有趣的图表以及如何定制它们以使其更加直观。如前所述,在大多数真实的用例中,数据需要进行一些转换才能用于图表。下面是一个例子,我使用了网飞的数据,但对数据进行了转换,以合并每年的电影和电视节目数量。然后,我使用了“plt.subplots()”函数,但我也添加了一些额外的细节,使图表更加直观,不言自明。
还可以对上面的图表进行一些定制,比如创建一个双轴。在上面的例子中,电影和电视节目的数量之间没有太大的差异,因此数据看起来不错,如果它们之间有很大的差异,那么图表将不是很清楚。在这些情况下,我们可以利用双轴,以便具有较小值的属性也将与另一个属性一致。
散点图
我们还可以利用散点图,显示我们正在绘制的变量之间的任何关系。该图有助于显示变量之间的相关性,例如当一个属性增加/减少时,另一个属性会发生什么。
更高级的可视化,仍然使用 Matplotlib
一旦你熟悉了我们到目前为止介绍的简单趋势图,你就可以开始使用稍微高级一点的图表和功能来更好地定制你的可视化
条形图
条形图通过并排绘制来帮助我们同时比较多个值。有不同种类的条形图,
- 垂直条形图
- 水平条形图
- 堆积条形图
下面是一个条形图的例子,有一些自定义添加到这个图。他们是,
- 添加了轴标签和标题
- 已提供字体大小
- 还提供了图形大小(默认的图表看起来会小得多,也很杂乱)
- 使用一个函数来生成值并将其添加到每个条形的顶部,以帮助查看者获得实际的细节
水平和堆积条形图
垂直条形图是最常见的,但我们也可以使用水平条形图,特别是当数据标签有一个很长的名称,很难将它们打印在垂直条形图下方时。在堆积条形图的情况下,一个类别中的条形图将一个堆叠在另一个之上。下面是实现水平和堆叠条形图的示例。下面的代码还包括对图表颜色的定制。
饼图和圆环图
饼图有助于显示数据中不同类别的比例,并且这些饼图可以很容易地修改为圆环图,方法是用一个圆覆盖饼图的中心部分,并重新对齐文本/值以适应圆环图。下面是一个简单的例子,我实现了饼图,后来又把它修改成了圆环图
为什么学习 Matplotlib 很重要?
Matplotlib 是 python 中非常重要的可视化库,因为 python 中的许多其他可视化库都依赖于 matplotlib。学习 matplotib 的一些优势/好处是,
- 这很容易学
- 它是高效的
- 它允许大量的定制,因此可以构建几乎任何类型的视觉效果
- 像 Seaborn 这样的库是建立在 Matpotlib 之上的
我只讲述了 Matplotlib 中最基本的可视化,但重要的是通过练习这些图表,你将获得构建更多可视化的知识。Matplotlib 支持许多可视化功能,这里的是所有受支持图表图库的链接。
使用 Seaborn 构建数据分析的快速可视化
我们已经介绍了使用 Matplotlib 库的各种可视化。我不知道您是否注意到了,尽管 matplotlib 提供了高度的定制,但它涉及大量的编码,因此可能会非常耗时,尤其是当您正在进行探索性分析,并且想要快速绘制一些图表以更好地理解数据并更快地做出决策时。这正是 seaborn 库所提供的,下面是使用 Seaborn 库的一些好处,
- 默认主题仍然很有吸引力
- 简单快速地构建可视化效果,尤其适用于数据分析
- 它的声明式 API 允许我们只关注图表的关键元素
也有一些缺点,比如它没有提供太多的定制,并且它可能会导致内存问题,特别是当我们处理大型数据集时。但仍然是利大于弊。
只有一行代码的可视化
下面是一些使用 seaborn 库只用一段代码实现的简单可视化。
如上面的快照所示,可视化效果只用一行代码就创建好了,看起来也很不错。Seaborn 库被广泛用于数据分析阶段,因为我们可以轻松快速地构建图表,并且对图表的可展示性影响最小/没有影响。可视化是数据分析的关键,因为它们有助于揭示数据中的模式,而 seaborn 库正好适合这一目的。
热图
热图是另一种有趣的可视化方式,广泛用于时间序列数据,以显示数据集中的季节性和其他模式。然而,要构建热图,我们需要将数据转换成特定的格式,以支持热图绘制。下面是一个示例代码,用于转换数据以适应热图和用于构建热图的 seaborn 库
结对图——我最喜欢的 Seaborn 功能
我认为结对图是 seaborn 库最好的特性之一。它有助于将数据集中的每个属性与其他每个属性通过可视化方式进行比较,同样也是在一行代码中。下面是构建配对图的示例代码。当我们正在处理的数据集包含大量列时,使用配对图可能不可行。在这些情况下,配对图可用于单独分析一组特定属性之间的关系。
构建互动图表
在从事数据科学项目时,有时需要与业务团队共享一些可视化内容。仪表板工具广泛用于此目的,但是假设您在执行数据分析时注意到了一个有趣的模式,并希望与业务用户分享。如果将它们作为图像共享,业务用户可能没有太多可做的,但是如果将它们作为交互式图表共享,则业务用户可以通过放大或缩小或使用其他功能与图表交互来查看粒度细节。下面是一个例子,我们正在创建一个 HTML 文件作为输出,其中包括可视化,可以与任何其他用户共享,他们可以简单地在 web 浏览器中打开。
如果你热衷于学习使用 python 可视化,请查看下面我的播放列表。它包括三个视频,总教程长度只有一个多小时。
关于我
我是一名拥有超过 10 年经验的数据科学专业人员,我已经撰写了 2 本数据科学方面的书籍,它们在这里有售。我有一个 YouTube 频道,在那里我教授和谈论各种数据科学概念。如果有兴趣,可以订阅我下面的频道。
[## 莎兰的数据科学
我是一名数据科学专业人员,在高级分析和应用机器领域拥有十多年的经验…
www.youtube.com](https://www.youtube.com/c/DataSciencewithSharan)
如何为你的计算机科学研究项目“Docker”?
原文:https://towardsdatascience.com/how-to-docker-for-your-computer-science-research-project-the-minimal-guide-for-using-docker-2ecd3e9280ac?source=collection_archive---------29-----------------------
docker 使用指南。
当所有人都在讨论 dockers,谈论你的项目 dockerize 有多好的时候,因为它就像一个隔离的环境,人们可以直接运行你的 docker 映像,而不需要设置依赖关系。
我目前正在进行深度学习研究,我的老板让我将我的研究项目放入 docker。所以我花了一些时间去理解 docker 是什么,以及如何在最小理解的情况下使用它。
这是一个最低限度的理解,因此它可能不是使用 docker 的正确方式,但我发现它适合我作为一名研究人员的用法,所以我决定分享它!
什么是码头工人?
我是以我的经验来解释,而不是从谷歌的定义来解释。如果你知道什么是虚拟机,它就像你当前电脑中另一台电脑(如 ubuntu)的模拟器。Docker 就像一个类似的,只是它是一个更快更好的虚拟机(内心深处是相当不同和复杂的)。这是一个孤立的环境,一台新电脑!
如何安装?
这个网站对于在你的 Ubuntuhttps://phoenix nap . com/kb/how-to-install-docker-on-Ubuntu-18-04中安装 docker 有非常明确的说明。安装后,尝试运行“docker - version ”,如果显示输出,则说明您已成功安装!
我想在不安装任何包的情况下使用 docker!
我在所有项目中使用 docker 的原因是,我不需要在新电脑中设置 CUDA(如你所知,CUDA 非常复杂,我曾几次搞砸我的 ubuntu)。当然,有些时候我懒得安装依赖项,docker 最适合我!
如果你现在正在研究深度学习,你很可能会使用 PyTorch 或 Tensorflow。
没有 docker,可能需要安装 Anaconda3,python3,new ubuntu,设置 CUDA,pip install,conda install。但是用 docker,你需要做的只是两个命令。
docker pull pytorch/pytorch:最新#将下载“镜像”,或者您可以在安装环境时获得它
docker run-it-RM-GPU all py torch/py torch bash
如果面临“权限错误”,就用 sudo 运行,因为我已经设置了不带 sudo 的 running docker。
这是运行命令后的界面(我用名称“pt1.4”标记了原始图像)
现在你已经进入了“虚拟机”(它被称为“容器”,每当我谈到“容器”,它意味着我在谈论这个“虚拟机”),注意到你是这个容器中的“root”,稍后我将谈论如何摆脱“root”。
在这个“虚拟机”里,你可以像正常的 ubuntu 环境一样做任何事情。
其他版本的 pytorch 可以参考 Dockerhub 中的 pytorch 资源库:https://hub.docker.com/r/pytorch/pytorch
如果想要 tensorflow 版本(也可能是特定库版本),只需尝试谷歌“dockerhub tensorflow”或“docker pull tensorflow”,或者在 dockerhub 中搜索即可。
如果你想知道那是什么-it 和- rm,“-i”是交互的,“-t”是 TTY(类似于显示实时标准输出,你可以查看 docker 文档了解实际含义),“- rm”是它会在你退出 docker 后删除“容器”(就像从存储中删除你的虚拟机,如果你已经熟悉 docker,你可以不用这个命令运行)。
最新的 docker 非常方便,你不必设置英伟达的东西。“-GPU ALL”是告诉 docker 你想把所有的 GPU 设备都映射到这个容器。如果您只想将 GPU 0 和 GPU 1 映射到这个容器中,您可以使用“-GPU \ " device = 0,1”运行,请注意,我使用" \ "是因为它是单个设备的 docker 语法。
如果你想知道为什么 GPU 内存用了 7GB 却看不到其他进程,那是因为那些进程不在这个容器里。该容器在您的原始计算机中是独立的,并与其他容器隔离
将文件夹装入 Docker 容器
docker run-it-RM-GPU all-v/path/to/my/code:/path/in/docker-v/datasets:/data mypytorch bash
对于您想要“挂载”到容器中的每个文件夹,您需要在上面的命令中添加“-v”和“/pathA:/pathB”。然后你的文件夹“/A”将被挂载(或映射)到容器中的“/B”中
DeepIPR 是我的项目之一【https://kamwoh.github.io/DeepIPR/
正如您从上面看到的,原始文件夹路径是“/data/Projects……”,然后我用命令“-v”将它挂载到容器中。在容器中,我挂载的文件夹在“/workspace/DeepIPR”中。注意:在挂载的文件夹中创建的所有文件都将出现在原始文件夹中。
记住用-u \((id -u):\)(id -g)运行
在我知道这个命令之前,我通常只是运行 docker,将我的文件夹映射到容器的文件夹中,如下所示
docker run-it-RM-v/path/to/my/code:/path/in/docker-u \((id-u):\)(id-g)mypytorch bash
如果不使用“-u”运行也没关系,但是由/path/to/my/code 中的容器创建的新文件夹将成为“根”访问。完成这一步后,在容器中挂载的文件夹中创建的新文件夹将再次成为您自己的用户名。你会看到“我没有名字”,不过没关系,不会影响任何用法,忽略就是因为我们没有设置好 docker(更高级的部分)
请注意,6001 和 6000 是原始计算机环境的用户和组 id
直接运行您的代码
我的 DevOps 朋友告诉我,我使用 docker 的方式不对,使用“bash”命令有点难看(所有程序员都喜欢处理他们代码的优雅方式)。
在图像名称后的参数之后是将在容器中运行的命令。所以你可以像这样跑
docker run-it-RM-v/path/to/my/code:/path/in/docker-GPU all mypy torch python/path/in/docker/xxxx . py
简单 Dockerfile 文件
如果您需要安装一个原始 docker 映像没有的额外的包。
比如你拉的 PyTorch 图片,不包含“jupyter notebook”。您可以创建自己的 docker 文件。(您会注意到一些“dockerized”的 github 项目有一个名为“Dockerfile”的文件)
这个 Dockerfile 基本上就像一个设置你的映像的设置脚本(映像就像 ISO 文件,容器就像我们用 ISO 文件运行的内容)。比如你如何设置你的新 ubuntu 环境。
记得把你的文件存为“Dockerfile”!!
从 xxxxx 开始,它是您要在其上构建的基础映像。
运行 xxxxx,它在映像构建期间运行命令。对于 apt-get,你必须小心,如果你想在安装其他包之前更新 apt-get,你必须运行&就像我上面显示的那样,否则 docker 会在你用这个 docker 文件构建的第秒跳过它。
ENV xxxxx,用于设置环境变量
你会注意到,每当我进入容器时,我都在“/workspace”中,这就是 WORKDIR 的作用。为您设置默认位置。
你会觉得奇怪,为什么我要为 jupyter 设置 chmod 777,这是我面临的权限错误,希望这个技巧可以帮助解决你面临的问题。(当然不是优雅的方式)
而且可以用自己的名字打造自己的 docker。
DOCKER_BUILDKIT=1 docker 构建标记 imagename。
" DOCKER_BUILDKIT=1 "使 DOCKER 以更快的方式构建图像(可能是关于缓存的东西),"- tag "后面的参数是图像名称,不要忘记那个点。",表示当前目录中的“Dockerfile”。
建立自己的图像后,您可以使用“docker 图像”来检查它
结论
如果你想在这篇文章中更多地了解 docker
在这篇文章中,我实际上也跳过了许多有用的 docker 快捷方式,但我认为这些在这篇文章中相当复杂(至少在我第一次使用 docker 时是如此)。你可能会觉得设置 docker 很麻烦,但是相信我,麻烦只有一次。Docker 相当方便,因为你不需要在新电脑上重新设置。如果你真的需要了解更多关于 docker 或者真正优雅的使用 ocker 的方法,你应该谷歌一下 docker cheatsheet 或者别的什么。这篇文章是关于 docker 用法的最基本的理解。感谢阅读!!
额外收获:你可以参考的备忘单
我想在这篇文章之后,你应该有一个直观的认识,阅读下面的小抄对你来说应该不再是一个问题了!!
- https://www.docker.com/sites/default/files/d8/2019-09/docker-cheat-sheet.pdf
- https://github.com/wsargent/docker-cheat-sheet
- http://dockerlabs.collabnix.com/docker/cheatsheet/
- https://phoenixnap.com/kb/list-of-docker-commands-cheat-sheet
如何对任何机器学习应用进行分类
原文:https://towardsdatascience.com/how-to-dockerize-any-machine-learning-application-f78db654c601?source=collection_archive---------20-----------------------
实践教程
我用这三个简单的步骤反复做这件事。
用集装箱装运,模特们!(图片由安迪李在 Unsplash 上拍摄)
一个月后,作为一名刚毕业的大学生,我们人工智能创业公司的创始人走到我面前,问我,“Arunn,我想让你成为 Docker 方面的专家。你需要多长时间?” 。不确定 Docker 是什么,但又无法闪避问题,最终我回复了, “两周,1 次冲刺”。
我的经理也在附近,他试图打断我来救我,但我已经造成了伤害,我所能做的就是接下来的两个星期。
回想起来,我从来都不是专家(现在也不是!但是我学到了足够做需要做的事情。在这篇文章中,我将告诉你什么才足以对任何机器学习 web 应用程序进行 dockerize。
Docker 是什么?
Docker 是一个通过使用容器来创建、部署和运行应用程序的工具。一个容器是一个标准化的软件单元,简单来说——除了打包的应用程序代码、必需的库和其他依赖项之外,什么都没有。一个 Docker 镜像是一个可执行的软件包,包括运行一个应用程序所需的一切,并在运行时成为一个容器。
当我试图理解 Docker 时,它是许多新的技术术语。但这个想法其实很简单。
想象一下你得到了一台新的迷你 Ubuntu 机器。然后你在它上面安装一些包。然后在其上添加一些代码。最后,您执行代码来创建应用程序。所有这一切都发生在你现有的装有你所选择的操作系统的机器上。你所需要的就是在里面安装 Docker。
如果您的机器上没有安装 Docker,请在此处找到说明来设置 Docker 。
为什么 Docker 面向数据科学家?
我明白了。你在数据科学领域。你觉得 DevOps 的人能搞定 Docker 吗?你老板没让你成为专家(不像我!)。
你觉得其实不需要了解 Docker。
那不是真的,让我告诉你为什么。
“不知道为什么它不能在你的机器上工作,但它能在我的机器上工作。要不要我看看?”
在你的工作场所听过这些话吗?一旦你(和你的团队)理解了 Docker,没有人会再说出那些话。事实上,你的代码可以在 Ubuntu、Windows、AWS、Azure、Google Cloud 或任何地方流畅运行。
你构建的应用程序在任何地方都是可复制的。
您将更快地启动环境,并以正确的方式分发您的应用程序,并且您将节省大量时间。你将(最终)成为一名拥有软件工程最佳实践的数据科学家。
三个简单的步骤
正如我所承诺的,我已经将这个过程简化为 3 个简单的步骤。这里让我们使用一个糖尿病预测应用程序的用例,它可以根据诊断方法预测糖尿病的发作。这将让您了解我们如何在真实的用例场景中实现容器化。
我强烈推荐您阅读这篇文章,在这篇文章中,我们使用 Streamlit 一步一步地从头开始构建这个机器学习应用程序。
作者制作的糖尿病预测应用的截屏
请看一下这个 GitHub 库,以及完整的实现和示例。现在我们知道了背景,让我们开始我们的 3 个步骤吧!
1.定义环境
第一步是确保应用程序正常运行所需的确切环境。有许多方法可以做到这一点,但最简单的一个想法是为项目定义requirements.txt
文件。
请查看您的代码中使用的所有库,并在名为requirements.txt
的文本文件中列出它们。列出库的确切版本是一个很好的做法,当您在环境的终端上运行pip freeze
时就可以找到。我的糖尿病预测示例的需求文件如下所示,
joblib==0.16.0
numpy==1.19.1
pandas==1.1.0
pandas-profiling==2.8.0
scikit-learn==0.23.2
streamlit==0.64.0
2.编写 Dockerfile 文件
这里的想法是我们试图创建一个名为Dockerfile
的文件,它可以用来构建我们的应用程序运行所需的虚拟环境。请将它视为我们在任何系统之上构建所需环境的指导手册!
让我们为手头的例子编写 docker 文件,
FROM python:3.7
EXPOSE 8501
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD streamlit run app.py
就是这样。6 行代码。一切按顺序进行。每一行都建立在前一行之上。我们来剖析一下台词。
- 每个 Dockerfile 都必须从 命令的 开始。从 跟随 的必须是已经存在的映像(或者在您的机器上,或者来自docker hub 库)。因为我们的环境是基于 python 的,所以我们使用
python:3.7
作为我们的基本映像,并最终使用这个 docker 文件创建一个新映像。 - Streamlit 在默认端口 8501 上运行。因此,为了让应用程序运行,公开特定的端口非常重要。为此我们使用 曝光 命令。
- 工作目录 设置应用程序的工作目录。其余的命令将从此路径执行。
- 这里的 复制 命令将所有的文件从你的 Docker 客户端的当前目录复制到镜像的工作目录。
- 运行 命令确保我们在
requirements.txt
中定义的库被正确安装。 - CMD 指定启动时在容器内运行什么命令。因此
streamlit run app.py
确保了容器一启动,Streamlit 应用就会运行。
编写 Docker 文件需要一些练习,除非你花很多时间使用 Docker,否则你不可能掌握所有可用的命令。我建议熟悉一些基本命令,并参考 docker 的官方文档了解其他信息。
3.建立形象
既然我们已经定义了 Dockerfile,那么是时候构建它并创建一个映像了。这个想法是,我们创建的这个图像是与底层系统无关的可再生环境。
docker build --tag app:1.0 .
顾名思义build
命令按照 Dockerfile 中的定义一层一层地构建图像。用名称和版本号将图像标记为<name>:version.number
是一个很好的做法。末尾的点表示 Dockerfile 的路径,即当前目录。
等等,我建立了图像,但是我该怎么做呢?根据需求,你可以在 DockerHub 上共享构建好的映像或者在云上部署它们等等。但是首先,现在您运行图像来获取容器。
顾名思义,run
命令在主机上运行指定的容器。--publish 8501:8501
让容器的端口 8501 映射到主机的端口 8501,而-it
是运行交互进程(比如 shell/terminal)所需要的。
docker run --publish 8501:8501 -it app:1.0
现在按照你的终端上提示的链接,自己去看魔术吧!;)
你做到了!(照片由伊亚勒在 Unsplash 拍摄)
在你走之前
This article is a part of my series on **Machine Learning in Production**:
- [How I Build Machine Learning Apps in Hours](https://medium.com/towards-artificial-intelligence/how-i-build-machine-learning-apps-in-hours-a1b1eaa642ed)
- [How to Dockerize Any Machine Learning Application](/how-to-dockerize-any-machine-learning-application-f78db654c601)
- [Deploying Your Machine Learning Apps in 2021](/deploying-your-machine-learning-apps-in-2021-a3471c049507)
谢谢你读到这里。我希望这篇文章为您增加一些价值,并帮助您开始使用 Docker for data science。尽管我已经用了好几年了,但我并不认为自己是专家。但是我觉得我知道的足够多了,我想和大家分享我所知道的一点点。我迫不及待地想看到你们都开始扮演码头工人。我写了很多我在数据科学方面的经历 ,非常感谢您的反馈。
想保持联系? 加入我的私人邮箱好友列表 。
如何从 Google 电子表格中按名称下载特定的工作表作为 CSV 文件
原文:https://towardsdatascience.com/how-to-download-a-specific-sheet-by-name-from-a-google-spreadsheet-as-a-csv-file-e8c7b4b79f39?source=collection_archive---------9-----------------------
安迪·凯利在 Unsplash 上的照片
概观
在过去的两篇关于使用 Python 的 Google Drive API 的教程中,我们已经介绍了如何在这里获取凭证以及在这里通过名称在 Google Drive 中搜索特定文件。
在本教程中,我们将学习如何从 Google 电子表格中按名称下载特定的工作表到 csv 文件中。一个用例:您需要生成一个报告,该报告的数据存储在一个 Google 电子表格中,该表格有许多工作表,但您只需要其中的一两张。因此,不用下载整个谷歌电子表格,你可以自己挑选你需要的表格。
为什么叫它的名字?因为我从我的工作经验中了解到,人们倾向于坚持命名,并且通常用它的名字来称呼它。例如,一个人可能会这样问他或他的同事:“你能从收入表中提取数据吗?。
不管怎样,你知道我在说什么。💩我们开始吧,好吗?
TLDR;从 Github 下载项目回购。
以 csv 格式下载特定的工作表
我们当前的 Python 脚本能够根据文件名搜索特定的文件。让我们修改脚本,这样它就能够引用 Google 电子表格中的特定工作表,并将其下载为 csv 文件。
在本教程的最后,我们将得到一个 Python 脚本,它可以从命令行执行,并带有两个输入参数:
- Google 电子表格的名称
- 要以 csv 格式下载的工作表名称
要跟进,请查看回购的这个提交。
启用工作表 API
我们需要做的第一件事是启用 Google Sheets API。现在,打开你的浏览器,进入https://console.developers.google.com/apis/dashboard。然后,确保你是在正确的项目上,如果不是,从下拉列表中选择正确的项目。
谷歌开发者控制台
接下来,转到“库”选项卡,在搜索栏中键入“图纸”。
谷歌开发者库
继续点击它。一旦你登陆到 Google Sheets API 页面,点击 ENABLE 按钮来启用这个 API。
启用 Google 工作表 API
在那之后,如果你只是去凭证选项卡,你会看到它说我们的凭证,我们早些时候为 Google Drive API 设置的是与 Sheets API 兼容的。这意味着我们可以使用已经拥有并为我们的脚本设置的凭证。🙂
Google Sheets API 证书
添加一个功能来下载一个 csv 格式的谷歌表单
为了能够使用 Sheets API,我们需要如下初始化一个 Sheets 服务实例。
sheets = discovery.build('sheets', 'v4', credentials=credentials)
现在,让我们将上面的代码添加到我们现有的connect_to_google_drive.py
文件中(我们稍后将重构它)。
既然我们缩小了脚本的功能,我们可以在现有的retrieve_all_files
中添加一个过滤器,只查找 Google 电子表格类型的文件。为此,我们只需要添加一个参数q
,如下所示。
# define a function to retrieve all files
def retrieve_all_files(api_service, filename_to_search):
results = []
page_token = None
while True:
try:
param = {'q': 'mimeType="application/vnd.google-apps.spreadsheet"'}
if page_token:
param['pageToken'] = page_token
files = api_service.files().list(**param).execute()
...
...
...
通过添加mimeType="application/vnd.google-apps.spreadsheet"
,它告诉 Google Drive API 的list()
方法只返回文件的 mime 类型是 Google 电子表格的结果。
最后,让我们编写一个函数,该函数将使用工作表 API 的values()
方法从特定的工作表中获取单元格值,并将它们写入一个 csv 文件。
# define a function to export sheet to csv
def download_sheet_to_csv(spreadsheet_id, sheet_name):
result = sheets.spreadsheets().values().get(spreadsheetId=spreadsheet_id, range=sheet_name).execute()
output_file = f'{sheet_name}.csv'
with open(output_file, 'w') as f:
writer = csv.writer(f)
writer.writerows(result.get('values'))
f.close()
print(f'Successfully downloaded {sheet_name}.csv')
让我们在脚本的最后调用这个新函数,就像这样。
# call the function
filename_to_search = 'Christmas Plan'
all_files, search_file = retrieve_all_files(drive, filename_to_search)
download_sheet_to_csv(search_file.get('id'), 'Sheet2')
对于这个例子,Sheet2 的内容是这样的。
工作表 2
酷毙了。现在继续从终端运行这个脚本。记得在运行脚本之前激活您的虚拟环境。🙂这是脚本完成后您将在控制台中看到的内容。
$ python connect_to_google_drive.py{'kind': 'drive#file', 'id': '1GyIz1NqCg6Bkr0Z_3Craem0BAwG0195usRswduCtKab', 'name': 'Christmas Plan', 'mimeType': 'application/vnd.google-apps.spreadsheet'}Successfully downloaded Sheet2.csv
让我们通过查看其内容来验证下载的文件。
$ cat Sheet2.csvNo,Code,Name
1,123,Apple
2,234,Watermelon
3,345,Banana
4,456,Blueberry
5,567,Dragonfruit
6,678,Cherry
7,789,Strawberry
8,890,Kiwi
9,901,Avocado
好吧。看起来我们的脚本像预期的那样工作。快乐的日子😃
重构代码并允许它接受命令行参数
正如所承诺的,我们现在将重构代码并转换它,以便它将从命令行接受两个输入参数。
为了区分开来,我们将把connect_to_google_drive.py
中的所有函数提取到单独的 Python 文件中。让我们创建一个文件夹,命名为google_api_functions
。
首先,让我们将初始化我们的 drive 和 sheets 实例的代码行提取到一个新文件中,并将其命名为get_api_services.py
。
get_api_services.py
接下来,我们将重构retrieve_all_files
函数。现在,我们从这个函数中需要的唯一信息是 Google 电子表格的id
。所以,让我们删除不必要的行,最后,将其提取到一个名为get_spreadsheet_id.py
的新 Python 文件中。
get _ 电子表格 _id.py
最后要提取出来的函数是download_sheet_to_csv
函数。让我们将它提取到一个名为download_sheet_to_csv.py
的新文件中。
下载 _ 工作表 _ 到 _csv.py
现在,我们将把我们的connect_to_google_drive.py
文件重命名为main.py
。这是我们将从命令行调用的 Python 文件。
我们将在这个文件中添加一个函数,它将解析通过命令行传递的参数,这些参数将是电子表格名称和工作表名称。
def parse_args():
parser = argparse.ArgumentParser(description="Function to download a specific sheet from a Google Spreadsheet")
parser.add_argument("--spreadsheet-name", required=True, help="The name of the Google Spreadsheet")
parser.add_argument("--sheet-name", required=True, help="The name of the sheet in spreadsheet to download as csv")
return parser.parse_args()
最后,让我们编写当从命令行调用脚本main.py
时将被执行的代码行。
if __name__ == '__main__':
args = parse_args()
spreadsheet_name = args.spreadsheet_name
sheet_name = args.sheet_name
drive, sheets = get_api_services()
spreadsheet_id = get_spreadsheet_id(drive, spreadsheet_name)
download_sheet_to_csv(sheets, spreadsheet_id, sheet_name)
不错!现在,我们的代码变得更加清晰和易于遵循。🙂
有了这个新的main.py
脚本,我们可以从命令行调用它的方式如下。
$ python main.py --spreadsheet-name "Christmas Plan" --sheet-name Sheet2Successfully downloaded Sheet2.csv
就是这样。😺
包裹
在过去的三个教程中,我们讨论了以下内容:
- 设置凭证以使用 Google Drive API — 链接
- 在 Google Drive 中搜索文件— 链接
- 以 csv 格式下载特定的工作表
现在,我们应该都熟悉 Google Drive 和 Sheets API 了。我们还可以使用 API 做很多其他的事情,因此,我鼓励大家进一步探索它,并构建一些自动化脚本来帮助您的工作或生活。🙏
照片由 Anastasia Taioglou 在 Unsplash 上拍摄
如何使用 Python 下载图像
原文:https://towardsdatascience.com/how-to-download-an-image-using-python-38a75cfa21c?source=collection_archive---------1-----------------------
了解如何使用 Python 模块(如 request、urllib 和 wget)下载图像文件。
来源: Giphy
最近,我在用一个远程系统工作,需要下载一些我的代码最终会处理的图像。
我可以在我的终端上使用 curl 或者 wget 来下载文件。但是,我希望最终用户的整个过程是自动化的。
这让我想到了一个问题:
如何使用 Python 下载图像?
在本教程中,我将介绍几个可用于下载 Python 文件(特别是图像)的模块。涵盖的模块有: 请求 、 wget 、 urllib 。
免责声明:不要下载或使用任何违反其版权条款的图像。
设置
本教程中使用的代码是在安装了 Python 3.6.9 的 Ubuntu 系统上测试的。
我强烈推荐建立一个虚拟环境,其中包含所有测试所需的库。这是你可以做到的。
$ virtualenv image_download
$ source ./image_download/bin/activate
$ pip3 install requests wget
我们将在教程中使用的图像位于这里。是 免费用于商业用途,不需要任何归属 。
图片来自 Pixabay 的肖恩·韦林
我们将用于下载的图像 URL 将是:
[https://cdn.pixabay.com/photo/2020/02/06/09/39/summer-4823612_960_720.jpg](https://cdn.pixabay.com/photo/2020/02/06/09/39/summer-4823612_960_720.jpg)
我们将创建一个简短的脚本来从给定的 URL 下载图像。
脚本将下载与脚本文件相邻的图像,并且可选地,保留原始文件名。
请求模块
请求 是 Python 中一个整洁且用户友好的 HTTP 库。它使得发送 HTTP/1.1 请求变得非常简单。
这似乎是使用 Python 下载任何类型文件的最稳定和推荐的方法。
来源: Giphy
这是完整的代码。
来源:作者
不要担心。让我们一行一行地分解它。
我们将从导入必要的模块开始,还将设置图像 URL。
import requests # to get image from the web
import shutil # to save it locallyimage_url = "[https://cdn.pixabay.com/photo/2020/02/06/09/39/summer-4823612_960_720.jpg](https://cdn.pixabay.com/photo/2020/02/06/09/39/summer-4823612_960_720.jpg)"
我们使用切片符号将文件名从图像链接中分离出来。我们使用正斜杠(/
)分割图像 URL,然后使用[-1]
分割最后一段。
filename = image_url.split("/")[-1]
来自请求模块的get()
方法将用于检索图像。
r = requests.get(image_url, stream = True)
使用
stream = True
来保证没有中断。
现在,我们将以二进制写入模式在本地创建文件,并使用copyfileobj()
方法将我们的映像写入文件。
# Set decode_content value to True, otherwise the downloaded image file's size will be zero.
r.raw.decode_content = True# Open a local file with wb ( write binary ) permission.
with open(filename,'wb') as f:
shutil.copyfileobj(r.raw, f)
我们还可以使用 请求的状态代码 添加某些条件来检查图像是否被成功检索。
我们还可以在下载大文件或者大量文件时通过 增加进度条 来进一步改进。这里的就是一个很好的例子。
Requests 是使用 Python 下载任何类型文件的最稳定和推荐的方法。
Wget 模块
除了 python 请求模块,我们还可以使用 python wget 模块 进行下载。
这是 python 中相当于 GNU wget 的。
使用起来相当简单。
来源:作者
Urllib 模块
通过你的程序访问网站的标准 Python 库是 urllib 。请求模块也使用它。
通过 urllib,我们可以做多种事情:访问网站,下载数据,解析数据,发送 GET 和,POST 请求。
我们可以使用几行代码下载我们的图像:
我们使用了 urlretrieve 方法将所需的 web 资源复制到本地文件中。
需要注意的是,在一些系统和很多网站上,上面的代码会导致一个错误:HTTP Error:HTTP Error 403:Forbidden。
这是因为很多网站不喜欢随机程序访问他们的数据。一些程序可以通过发送大量请求来攻击服务器。这将阻止服务器运行。
这就是为什么这些网站可以:
- 屏蔽你你会收到 HTTP 错误 403 。
- 向您发送不同的数据或空数据。
我们可以通过修改用户代理来克服这个问题,这是一个随我们的请求一起发送的变量。默认情况下,这个变量告诉网站访问者是一个 python 程序。
通过修改这个变量,我们可以像普通用户在标准的 web 浏览器上访问网站一样。
你可以在这里阅读更多关于它的。
结论
请求 已经成为 Python 中事实上的下载东西的方式。
甚至 urllib 文档页面 都推荐请求更高级别的 HTTP 客户端接口。
如果你想在你的程序中有更少的依赖项,你应该选择 urllib。它是标准库的一部分。所以,没必要下载。
希望你觉得这个教程有用。
重要链接
- StackOverflow —通过 Urllib 下载图像并请求
- 请求库
- wget 库
- urllib 库
如何使用 Python 下载文件
原文:https://towardsdatascience.com/how-to-download-files-using-python-ffbca63beb5c?source=collection_archive---------4-----------------------
émile Perron 未喷涂的图像
权威指南
了解如何使用 python 下载 web 抓取项目中的文件
P ython 非常适合在互联网上抓取网页,但在从我想做的网站上抓取一些标题或链接后,我的首要任务之一就是下载文件。我需要一种方法来自动化这个过程!
这里我们将概述如何做到这一点。
到本文结束时,您将
- 注意 python 中 HTTP 处理包的选择
2.详细了解请求包
2.知道如何使用请求包下载文件
3.如何用请求包处理大文件?
4.如何下载使用请求包重定向的文件。
python 中有很多处理互联网的包。你没有必要知道所有这些,但是让你知道为什么人们会选择其中一个。
下面是处理 HTTP 请求的不同包。
- 内置包:urllib 和 urllib2、urllib3
- 请求(基于 urllib3 包)
- grequests(扩展请求以处理异步 HTTP 请求)
- aiohttp(另一个处理异步 http 的包)
你可能会问同步请求和异步请求有什么区别?为什么这很重要?
同步请求阻塞客户端(浏览器),直到操作完成。这意味着有时 CPU 什么也不做,会浪费计算时间。在我看来效率很高!
异步请求不会阻塞浏览器,这允许客户端同时执行其他任务。这允许轻松扩展 1000 个请求。
url-lib 和 url-lib2 包有许多样板文件,有时可能有点难以阅读。我使用 requests 包,因为它是可读的,并且能够管理您无论如何都需要发出的大多数 HTTP 请求。
当您有大量 HTTP 请求时,异步包非常有用。这是一个复杂的话题,但是可以提高 python 脚本的效率。我会在后面的文章中回到这一点!
请求包介绍
要使用请求包,我们必须导入请求模块。然后,我们可以使用一系列方法与互联网互动。使用请求包的最常见方式是使用 requests.get 方法。在幕后,它对选择的 URL 执行 HTTP GET 请求。
首先,我们创建一个发送到服务器的请求对象,然后服务器发回一个响应。这个对象携带关于请求的所有数据。
import requestsurl = 'PLEASE INSERT URL LINK'
html = requests.get(url)
要访问这个对象,我们可以调用 text 方法。这将允许我们看到字符串形式的响应。请求根据从服务器返回的数据进行编码。
我们收到的信息有两部分,头和主体。标题为我们提供了关于响应的信息。可以把邮件头想象成将邮件发送到计算机所需的所有信息。
请看下面一个来自媒体标题的例子!有很多信息告诉我们关于反应。
{'Date': 'Thu, 30 Jan 2020 17:06:12 GMT',
'Content-Type': 'text/html; charset=utf-8',
'Transfer-Encoding': 'chunked',
'Connection': 'keep-alive',
'Set-Cookie': 'uid=lo_NHI3i4bLD514; Expires=Fri, 29-Jan-21 17:06:12 GMT; Domain=.medium.com; Path=/; Secure; HttpOnly,
optimizelyEndUserId=lo_NHI3i4bLD514; path=/; expires=Fri, 29 Jan 2021 17:06:12 GMT; domain=.medium.com; samesite=none; secure,
sid=1:Hu5pQRgkgEyZr7Iq5hNn6Sns/FKPUZaBJBtDCMI+nmsU48zG2lXM+dtrtlefPkfv; path=/; expires=Fri, 29 Jan 2021 17:06:12 GMT; domain=.medium.com; samesite=none; secure; httponly',
'Sepia-Upstream': 'production',
'x-frame-options': 'allow-from medium.com',
'cache-control': 'no-cache,
no-store, max-age=0, must-revalidate',
'medium-fulfilled-by': 'lite/master-20200129-184608-2156addefa, rito/master-20200129-204844-eee64d76ba, tutu/medium-39848', 'etag': 'W/"179e9-KtF+IBtxWFdtJWnZeOZBkcF8rX8"',
'vary': 'Accept-Encoding',
'content-encoding': 'gzip',
'x-envoy-upstream-service-time': '162',
'Strict-Transport-Security': 'max-age=15552000; includeSubDomains; preload',
'CF-Cache-Status': 'DYNAMIC',
'Expect-CT': 'max-age=604800,
report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"', 'Alt-Svc': 'h3-24=":443"; ma=86400, h3-23=":443"; ma=86400', 'X-Content-Type-Options': 'nosniff',
'Server': 'cloudflare',
'CF-RAY': '55d508f64e9234c2-LHR'}
request package get 方法下载响应的正文,而不要求许可。这将与下一节相关!
为了下载文件,我们希望以字节而不是字符串的形式获取请求对象。为此,我们调用 response.content 方法,这样可以确保我们接收的数据是字节格式的。
现在要写一个文件,我们可以使用一个 open 函数,它是 python 内置函数的样板文件。我们指定文件名,而“wb”指的是写入字节。Python 3 需要明确地知道数据是否是二进制的,这就是我们定义它的原因!
然后,我们使用 write 方法写入 get 请求的已定义二进制内容。
with open('filename.txt', 'wb') as r:
r.write(html.content)
with 语句打开了所谓的上下文管理器。这很有用,因为它将关闭 open 函数,而不需要额外的代码。否则,我们将不得不请求关闭 open 函数。我们不必使用 with 语句。
根据请求下载大文件
我们已经讨论了使用请求包下载的基本方法。get 方法参数帮助定义我们如何从服务器请求信息。我们可以用许多方法改变请求。请参阅请求文档以了解更多详细信息。
我们说过请求下载二进制文件的主体,除非另有说明。这可以通过定义流参数来覆盖。这在请求文档中的标题“正文内容工作流”下。见此处了解详情。这是一种控制何时下载二进制文件主体的方法。
request.get(url, stream=True)
在脚本的这一点上,只有二进制文件的头被下载。现在,我们可以通过一个名为 request.iter_content 的方法来控制如何下载文件。这个方法将整个文件停止在内存(缓存)中。
在后台,iter_content 方法迭代响应对象。然后,您可以指定 chunk_size,这是我们定义要放入内存的大小。这意味着在所有数据传输完成之前,连接不会关闭。
详情见此处。
r = requests.get(url, Stream=True)
with open("filename.pdf",'wb') as Pypdf:
for chunk in r.iter_content(chunk_size=1024)
if chunk:
pypdf.write(ch)
因此,这里我们使用一个请求 get 方法来获取内容。我们使用 with 语句作为上下文管理器,并调用 r.iter_content。我们使用 for 循环并定义变量 chunk,这个 chunk 变量将包含由 chunk_size 定义的每 1024 个字节。
我们将 chunk_size 设置为 1024 字节,如果需要,可以是任何值。
我们在将数据块放入内存的同时写入数据块。我们使用 if 语句查找是否有块要写,如果有,我们使用 write 方法来完成。这使得我们不会用尽所有的缓存,并以零碎的方式下载较大的文件。
下载重定向的文件
有时候你想下载一个文件,但网站重定向到检索该文件。请求包可以轻松处理这个问题。
import requests
url = 'insert url'
response = requests.get(url, allow_redirects=True)
with open('filename.pdf') as Pypdf:
pypdf.write(response.content)
这里我们在 get 方法中使用 allow_redirects=True 参数。我们像前面一样使用 with 语句来编写文件。
本文到此为止!敬请期待下一部分。我们将看看验证下载,恢复下载和编码进度条!
在后面的文章中,我们将讨论异步技术。这些可以扩大下载更大的文件集!
关于作者
我是一名医学博士,对教学、python、技术和医疗保健有浓厚的兴趣。我在英国,我教在线临床教育以及运行 www.coding-medics.com网站。
您可以通过 asmith53@ed.ac.uk 或 twitter 这里联系我,欢迎所有意见和建议!如果你想谈论任何项目或合作,这将是伟大的。
更多技术/编码相关内容,请点击这里注册我的简讯。
[## 关于 Enumerate()您需要知道的一切
使用 python 的枚举函数永远改变你的循环方式
medium.com](https://medium.com/analytics-vidhya/everything-you-need-to-know-about-enumerate-a49a7fd0d756)
超越 python 中请求包的基础
原文:https://towardsdatascience.com/how-to-download-files-using-python-part-2-19b95be4cdb5?source=collection_archive---------6-----------------------
émile PerronUnsplash 图像
了解如何在 python 中使用进度条、恢复部分下载的文件和验证文件
当您习惯了 requests python 包后,在命令行应用程序中考虑验证文件、恢复未完成的 get 请求和使用进度条的方法会很有用。这些超出了请求包的基本用途。我们将通过简单的方法使用请求包来实现这一点。
在本文中,您将了解到
- 如何恢复下载不完整的二进制文件
- 如何创建一个简单的下载验证程序来传输文件/备份数据。
- 如何显示简单的命令行进度条?
恢复下载
下载大文件时,可能会因为各种原因而中断。我们有时需要一种能够在最后一个字节恢复的方法来重新建立连接。
作为来自服务器的 HTTP get 请求的一部分,我们将获得数据头和数据体。二进制文件的 HTTP 头返回了我们请求的文件的大量信息!根据请求被发送到的服务器,我们有时会得到的部分之一是accept-ranges
头。这允许客户端下载部分下载的数据。
下面是一个接受下载部分文件的二进制文件头的例子。
{'Server': 'VK',
'Date': 'Wed, 29 Jan 2020 11:47:20 GMT',
'Content-Type': 'application/pdf',
'**Content-Length**': '9713036',
'Connection': 'keep-alive',
'Last-Modified': 'Mon, 20 Jan 2020 13:01:17 GMT',
'ETag': '"5e25a49d-94358c"',
**'Accept-Ranges': 'bytes',**
'Expires': 'Wed, 05 Feb 2020 11:47:20 GMT',
'Cache-Control': 'max-age=604800',
'X-Frontend': 'front632904',
'Access-Control-Expose-Headers': 'X-Frontend',
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
'Access-Control-Allow-Origin': '*',
'Strict-Transport-Security': 'max-age=15768000'}
有了这种能力,我们还可以向服务器指定我们请求下载的文件的位置。然后,我们可以在该特定位置开始请求二进制数据,并从那里继续下载。
现在,要下载二进制文件的一小部分,我们必须能够用 request get HTTP 方法发送文件头。请求包使我们能够轻松地做到这一点。我们只想获得一定量的字节,我们通过发送一个range
头来指定要接收多少字节。然后,我们可以将它放入一个变量,并通过 get 请求传递它。
resume_headers = {'Range':'bytes=0-2000000'}
r = request.get(url, stream=True, headers=resume_header)
with open('filename.zip','wb') as f:
for chunk in r.iter_content(chunk-size=1024)
f.write(chunk)
笔记
1.我们在请求获取方法中指定了stream = True
。这允许我们控制何时下载二进制响应的主体。
2.我们在requests.get()
方法中使用 headers 参数来定义从 0 到 2000000 的字节位置。范围标题的边界是包含的。这意味着将下载字节位置 0 到 2000000。
4.我们使用一个 with 语句来写文件 filename . zip。r.iter_content
方法允许我们通过以字节为单位定义chunk-size
来指定要下载的数据的大小。在这种情况下,它被设置为 1024 字节。
我们下载了部分文件。这对我们恢复部分下载文件的实际目标有什么帮助?
当我们想要恢复部分下载的文件时,我们在文件头中指定文件大小。这是需要下载的下一个字节。这就是 python 中能够恢复下载的症结所在。
我们需要知道部分下载的文件大小。python 中有一系列的包可以做到这一点,pathlib 是这个用例的一个很好的包。请参见这里的获取使用 pathlib 的指导。
我们首先要导入 pathlib 包
import pathlib
方法path.stat()
返回关于路径的信息(类似于 os.stat,如果你熟悉 os 包的话)。现在我们调用path.stat()
方法的st_size
属性来获取文件的大小(也类似于 OS 包)。
现在我们准备将它投入使用
resume_header = {'Range':f'bytes= {path('filename.zip').stat().st_size}**-**'}
现在,这个需要打开包装。字符串前的 f 是一个 f 字符串,这是一个格式化字符串的好方法。作为一个用例,这里花括号中的{path.stat().st_size}
是一个表达式。我们正在创建的字符串被花括号中表达式的含义所修改。这可能是一个变量,但在这种情况下,我们得到的是我们下载的部分文件的大小。f 字符串解释{}中的任何内容,然后将结果显示为字符串。在这种情况下,它为我们打印文件大小。
字符串中{path.stat().st_size}
后面的粗体连字符表示我们从部分文件大小的字节开始抓取数据,直到文件的末尾。
既然我们理解了这一点,我们就可以将所有这些放在下面的代码中
resume_header = {'Range':f'bytes={path('filename.zip').stat().st_size}-'}
r = requests.get(url,stream=True, headers=resume_header)with open ('filename.zip','ab') as f:
for chunk in r.iter_content(chunk-size=1024):
f.write(chunk)
笔记
- “打开”功能中的“ab”模式将新内容添加到文件中。我们不想覆盖现有的内容,这是代替' wb '
验证文件
我们有时需要能够验证下载的文件。如果您恢复了文件下载,或者如果这是您想要与其他人共享的重要研究数据。有一个 python 模块叫做 hashlib 模块,它创建一个散列函数。哈希函数获取数据,并将其转换为唯一的数字和字母字符串。我们称之为哈希对象。这个字符串的计算是通过我们可以指定为模块的一部分的算法来完成的。
让我们开始讨论如何验证下载的文件。我们需要知道哈希值应该是什么才能验证它。我们将读取二进制文件并生成散列,然后可以将它与文件的已知散列值进行比较。由于散列文件是唯一的,我们将能够确认它们是相同的文件。
要创建哈希值,我们需要指定创建它的算法。有很多选择,但在这个例子中,我们使用sha256()
。现在,为了创建一个哈希值,我们使用 hashlib update()
方法,该方法只接受“类似字节”的数据,比如字节。为了访问哈希值,我们调用了hexdigest()
方法。hexdigest()
接受 hash 对象,并为我们提供一串仅十六进制的数字。这个字符串由我们之前指定的算法定义。
一旦创建了哈希值,就不能反向获得原始的二进制数据。它只有一种方式。我们可以通过唯一的哈希值来比较两个文件,并使其在传输给其他人时更加安全。
import hashlibwith open('research.zip', 'rb') **as** f:
content = f.read()
sha = hashlib.sha256()
sha.update(content)
print(sha.hexdigest())
输出:
42e53ea0f2fdc03e035eb2e967998da5cb8e2b1235dd2630ffc59e31af866372
笔记
- hashlib 模块被导入
- 我们使用 with 语句读取文件:这确保了我们不必使用 close 语句。
- 我们调用
read()
方法来读取二进制数据的所有内容 - 创建变量 sha,并使用 SHA 256 算法创建散列对象来创建散列值。
- 使用
update()
方法,我们将二进制数据传递给散列对象。通过这样做,我们得到一个哈希值。 - 使用
hexdigest()
方法,我们可以打印出哈希值,即二进制文件特有的固定字符串。
所以现在无论何时你想验证一个文件,我们都有一个哈希值。如果你不得不再次下载或者把数据传输给同事。你只需要比较你创建的哈希值。如果恢复的下载完成并且具有正确的哈希值,那么我们知道它是相同的数据。
让我们创建一个小脚本来确认您的朋友传输给您的一个文件。例如,您需要输入哈希值。
user_hash = input('Please input hash please: ')sha = hashlib.sha256()with open('file.zip' as 'rb') as f:
chunk = f.read()
if not chunk:
break
sha.update(chunk)
try:
assert sha.hexdigest() == user_hashexcept AssertionError:
print('File is corrupt, delete it and restart program'else:
print('File is validated')
笔记
- 我们要求用户输入一个散列值,该值被赋予变量 user-hash。
- 当我们指定算法时,会创建变量 sha 和散列对象
- 我们使用 with 语句打开想要验证的文件。我们定义变量 chunk,并使用 read 方法为它分配二进制数据。
4.我们使用 hashlib update()
方法为这个块创建一个散列对象。
5.我们使用sha.hexdigest()
为这个块创建一个哈希值。
6.我们使用 assert 关键字,它计算表达式的真值。在这种情况下,根据输入的哈希值评估下载数据的哈希值。
7.我们指定一个异常AssertionError
。当 assert 语句为 false 并指定错误消息时,将调用此函数。
8.在 else 语句中,如果user_hash
变量与文件的哈希值相同,我们打印出该文件已经过验证。
所以这里我们为下载的文件创建了一个非常简单的验证工具。
进度条
有许多软件包可以显示您的编程代码的进度。这里我们就来说一个下载文件时添加进度条的简单方法!如果您正在批量下载,并希望在下载过程中看到进度,这可能会很有用。进度条在很多方面都很有用,不仅仅是下载文件。
Tqdm 是一个第三方 python 包,可以处理进度条。对我来说,这是思考 python 的最好方式,从尽可能少的代码开始,得到你想要的。
首先,您需要使用 pip 安装 tqdm。
pip install tqdm
然后我们会想要导入 tqdm。现在是我们要用 tqdm 方法来显示数据的进度。tqdm 模块可以解释每个块并显示文件的进度。
将进度条合并到下载文件中。首先,我们必须创建一些变量,最重要的是文件的大小。我们可以使用请求包来做到这一点。我们获取二进制头和“内容长度”。向上滚动到另一部分的二进制文件头。它的相关值是我们从服务器请求了多少字节的数据。响应是一个字符串,当在进度条中使用它时,我们必须将它转换成数字格式
另一个重要的部分是文件名。我们可以将 URL 拆分成一个列表,然后非常简单地选择最后一项。
一旦设置好所有变量,我们就可以指定 tqdm 模块。
with 语句意味着一旦操作完成并且 open 函数写入数据,它就关闭。然后,我们使用 tqdm 方法并指定参数来显示正在下载的数据。请注意,论点是非常详细的!让我们一个一个地看。
total
参数是我们定义的文件大小。unit
参数是我们指定的字符串,用于定义数据块的每次迭代的单元。在这种情况下,我们指定 B 为字节。desc
参数显示文件名initial
参数指定了进度条从哪里开始,在本例中为 0。ascii
参数是指定我们用什么来填充进度条。如果设置为 false,它将采用 unicode 来填充进度条。
既然我们已经解释了我们在做什么,现在让我们来看看代码:
from tqdm import tqdmurl = "insert here"
file = url.split('/')[-1]r = requests.get(url, stream=True, allow_redirects=True)
total_size = int(r.headers.get('content-length'))
initial_pos = 0with open(file,'wb') as f:
with tqdm(total=total_size, unit=B,
unit_scale=True, desc=file,initial=initial_pos, ascii=True) as pbar: for ch in r.iter_content(chunk_size=1024),
if ch:
f.write(ch)
pbar.update(len(ch))
输出:
filename.zip 100%|#################################################| 3.71M/3.71M [00:26<00:00, 254kB/s]
笔记
- 我们从 tqdm 模块中导入 tqdm 方法。
- 定义了变量 url。
- 定义了文件变量,我们使用拆分字符串的方法将 url 拆分成一个列表。('/')参数告诉 split 方法在 url 的/'之间拆分字符串。这里,我们想要得到列表的最后一个索引,因为这将是我们想要的文件名。
- 变量 r 用于指定一个 HTTP get 请求,我们允许它有一个开放的数据流并允许重定向。
- 定义了
total_size
变量,并使用请求包获取二进制头。使用 get 方法,我们得到了二进制文件大小的‘content-length’
值。现在,它返回一个字符串,我们用 int()把它变成一个数字。 - 变量
initial_pos
被赋值为 0,这对于 tqdm 方法的指定很重要。 - 我们使用 with 语句访问 tqdm 方法。我们在参数中指定了几项。
r.iter_content
将数据分割成块。我们将 ch 定义为一个 1024 字节的块,如果该块可用,我们将该块写入文件。- 我们调用 tqdm 方法的 update 属性将该块更新到进度条并显示出来。
所以在那之后,你应该对如何处理进度条、验证文件和超越请求包的基础有了更好的了解。
感谢阅读!
关于作者
我是一名医学博士,对教学、python、技术和医疗保健有浓厚的兴趣。我在英国,我教在线临床教育以及运行网站www.coding-medics.com。
您可以通过 asmith53@ed.ac.uk 或 twitter here 联系我,欢迎所有意见和建议!如果你想谈论任何项目或合作,这将是伟大的。
如需更多技术/编码相关内容,请在此注册我的简讯。
如何用 Python 下载上市公司的收益日历
原文:https://towardsdatascience.com/how-to-download-the-public-companies-earnings-calendar-with-python-9241dd3d15d?source=collection_archive---------23-----------------------
威廉·艾文在 Unsplash 上的照片
用几行代码了解公司的最新收益
在撰写本文时,我们目前正接近 Q1 2020 财报季的尾声。对于许多投资者和量化金融爱好者来说,这是一个特别有趣的时期,有许多短期投资机会。这就是为什么在本文中,我想简要介绍收益季节的概念,并展示如何使用 Python 轻松提取所有重要信息。
什么是收益季节?
术语财报季指的是一年中大多数上市公司向公众发布季度公司财报的时间段。收益季节发生在每个财政季度结束后的几个月,因此这将对应于 1 月、4 月、7 月和 10 月。通常,收益季节持续约 6 周,之后报告的收益补贴数量为淡季频率(仍有一些公司报告淡季,因为它们的财务日历可能与大多数略有不同)。
为什么财报季对潜在投资者来说是一个重要时刻?仅仅是因为在给定公司发布收益的日期前后(主要是在当天),人们可以预期股票会有一些重大的价格变动。这是因为上市公司报告其财务和一般情况:上一季度的利润/亏损、组织的任何重大变化等。金融分析师利用这些信息评估股票的内在价值——以确定其当前市场价格是高估还是低估。这反过来又是投资者买入/卖出/持有股票的潜在信号。
大多数公司都在网站上为潜在/当前投资者开辟了一个专用部分,让他们可以访问收益报告以及即将发布的收益报告的日期。自然,从单个网站获取信息是不可行的(或者至少这不是一次愉快的经历)。这就是为什么我们将参考流行的金融数据来源——雅虎!金融。下面你可以看到一张来自当前收益日历的图片。
雅虎截图!财务收益日历
在我之前的一篇文章中,我展示了如何利用一些流行的 Python 库来轻松下载与股票价格相关的信息(以及一些关于公司本身的附加信息)。在本文中,我用一个名为yahoo-earnings-calendar
的新库来扩展这个工具包(是的,这个名字是不言自明的)。与前面描述的解决方案相比,它确实有一些优势,您将在下面看到。
使用 Python 下载收入日历
除了标准库,我们需要通过在终端中运行下面一行代码来安装yahoo_earnings_calendar
:
pip install yahoo_earnings_calendar
完成后,我们导入本文中使用的所有库:
下面,我们将介绍下载收入日历的三种可用方法。
下载特定日期的收入
我们探索的第一种方法用于下载特定日期的收入。为了下载数据,我们首先使用datetime
库定义日期。在本例中,我们使用当天(2020 年 5 月 15 日)。然后,我们实例化一个YahooEarningsCalendar
类的对象。使用earnings_on
方法,我们以字典列表的形式下载数据。最后,我们将下载的数据存储在一个pandas.DataFrame
中。
运行代码会生成DataFrame
的预览。
startdatetimetype
列包含有关收益电话会议时间的信息。传统上,收益(以及关于公司状况的任何其他重要信息)是在与感兴趣的投资者召开的收益电话会议上宣布的。综上所述,这是向公众公布收益的时候。
startdatetimetype
栏的图例:
- 蒙特利尔银行——开市前
- AMC——收市后
- TAS/TNS —时间未指定
通过运行df_earnings.shape
,我们看到DataFrame
有 119 行,这与上面的截图一致。以这种方式下载日历的一个潜在缺点是,我们只能获得美国公司的收益数据。
Yahoo!财务收益日历
这是雅虎上使用的过滤器的默认设置。财经网站。下载非美国公司信息最简单、最可靠的方法是使用股票代码。我们将在下面讨论这种方法。
下载一系列日期的收入
下载一系列日期的日历与我们已经描述过的非常相似。这一次,我们使用earnings_between
方法并提供感兴趣的时间段的开始和结束日期。对于下面的例子,我们下载未来 7 天的收益日期。
这次earnings_df
包含 312 个位置。
处理收入数据时要考虑的一个重要因素是日历会随着时间的推移而变化。因此,在提前几周/几个月下载收益的情况下,您可能希望不时刷新下载,以确保数据仍然有效。
下载特定产品的收益
最后,我们下载特定产品的收益日期,在本例中是 Twitter。我们通过使用get_earnings_of
方法并提供股票代码来做到这一点。这次不同的是,请求将返回过去和未来收入的列表。这就是为什么我们从时间戳字符串中提取日期(它以 ISO-8601 格式存储)并使用between
方法只过滤掉未来 180 天的收益。
代码返回下表,其中包含 Twitter 在未来 180 天内的两个收益发布日期。
结论
在这篇文章中,我解释了什么是收益季节,以及如何从 Yahoo!金融。
有了可以在 Python 中使用的数据,我可以想到一些潜在的用例:
- 建立一个自动的电子邮件/Slack 机器人通知你相关的收益发布。
- 在用于预测股票价格的 ML 模型中包含收益发布日期。例如,你可以在脸书的预言中指出收益日期作为转折点。
就代码行而言,yahoo-earnings-calendar
库相当紧凑,所以我强烈建议检查代码,以了解数据实际上是如何从 Yahoo!金融。这可能是特别重要的,因为雅虎!倾向于频繁更改网站,这可能导致库变得不可用,至少在修复之前是如此。这就是为什么在将基于它的任何代码投入生产时都应该小心谨慎。此外,熟悉用于抓取数据的方法无疑是有意义的,因此您可以在作者修复任何问题之前修复它们。并且您可以随时使用该更新进行拉取请求:)
你可以在我的 GitHub 上找到本文使用的代码。一如既往,我们欢迎任何建设性的反馈。你可以在推特或评论中联系我。
不久前,我出版了一本关于使用 Python 解决金融领域实际任务的书。如果你感兴趣,我在贴了一篇文章介绍这本书的内容。你可以在亚马逊或者 Packt 的网站上买到这本书。
参考
[1]雅虎!收益日历刮刀— GitHub
如何用 python 为你的科学论文绘制条形图
原文:https://towardsdatascience.com/how-to-draw-a-bar-graph-for-your-scientific-paper-with-python-a6c2a5e6bcd7?source=collection_archive---------24-----------------------
照片由特雷·赫尔利拍摄
条形图📊(也称为条形图或条形图)是一种可视化工具,读者可以使用它来比较不同类别的条形图所显示的数据。在这个故事中,我试图介绍如何用 python 绘制清晰的条形图。
作为一名学生或研究人员,你必须在科学论文中发表你的努力和成果,研究数据应该易于阅读和获取。共享研究数据是我们越来越鼓励,甚至强制要求的事情。同时,这也是我热衷的事情😘。
首先让我们重新认识一下这位朋友,条形图是谁(什么)?
条形图或条形图是一种图表或图形,用矩形条表示分类数据,矩形条的高度或长度与它们所代表的值成比例。条形图可以垂直或水平绘制。垂直条形图有时被称为柱形图。由维基百科提供。
第一个例子
我做了一个简单的例子,用竖条图直观的展示了一个学生 X 的各科成绩。
所有分数的条形图
这是由一个非常简单的 Matplotlib 代码实现的:
import matplotlib.pyplot as pltfig = plt.figure(figsize=(7,5))ax = fig.add_axes([0,0,1,1])subjects = ['Math', 'Physik', 'English', 'Chemistry', 'History']scores = [90,80,85,72,66]ax.bar(subjects,scores)ax.set_ylabel('scores',fontsize= 12)ax.set_xlabel('subjects',fontsize= 12)ax.set_title('all scores of student X')for i, v in enumerate(scores):ax.text( i ,v + 1, str(v), color='black', fontweight='bold')plt.savefig('barplot_1.png',dpi=200, format='png', bbox_inches='tight')plt.show()
数据分析中的真实案例
对于少量的结果数据,我们可以定义一个列表来保存整个数据,就像前面的例子一样。但有时数据太多,如果我们已经将相同的数据保存在 excel 文件中,那么再次将每个数据输入到一个列表中是低效的。
如果我们通过导入一个 excel 文件或其他文件来开始绘制条形图的过程,这将非常方便。因此,我们需要一个数据框架,它是二维的、大小可变的、潜在异构的表格数据,包括带标签的轴(行和列)。
在我在论文中写的这个真实案例中,我需要准确地比较不同模型的性能。准确度(ACC)是测量值与特定值的接近程度,这是评估分类模型的一个度量标准。从形式上看,准确性有以下定义:
准确度=正确预测的数量/方向总数
此外,通常在多分类模型中使用的前 N 名准确性意味着正确的类出现在前 N 名概率中,从而被认为是“正确的”。在论文中,我采用了前 1 名、前 3 名和前 5 名的准确度来评估预测。我已经在一个名为“model_accs.xlsx”的 excel 文件中输入了所有前 N 名 ACC。
数据,保存在 excel 表格(b)和熊猫数据框(c)中
有了 pandas,我们可以用 python 从 excel 文件中读取数据。Pandas 是一个开源的、BSD 许可的库,为 Python 编程语言提供了高性能、易于使用的数据结构和数据分析工具。
import pandas as pd
df= pd.read_excel("model_accs.xlsx",header=0) # read excel file
通过函数 pd.read_excel(),我们可以读取我们的结果 excel 文件。如果数据保存在。csv 文件,那么我们可以使用 pd.read_csv(),类似于 pd.read_excel()。
import numpy as nptop_1 = df.iloc[:,3]top_3 = df.iloc[:,2]top_5 = df.iloc[:,1]xlabels = df.iloc[:,0]N =5ind = np.arange(N) # the x locations for the groupswidth = 0.2 # the width of the barsfig, ax = plt.subplots(figsize=(12,8))rects1 = ax.bar(ind, top_1, width, color='b')rects2 = ax.bar(ind + width, top_3, width, color='orange')rects3 = ax.bar(ind + 2*width, top_5, width, color='g')ax.set_xticks(ind + width)ax.set_xticklabels(xlabels,fontsize=10)ax.set_xlabel("models", fontsize=12)ax.set_ylabel("Top-N ACC/%", fontsize=12)ax.set_title('Top-N ACC for 5 different models')ax.legend((rects1[0], rects2[0],rects3[0]),('top-1 acc', 'top-3 acc','top-5 acc'),bbox_to_anchor=(1.13, 1.01))def labelvalue(rects):for rect in rects:height = rect.get_height()ax.text(rect.get_x() + rect.get_width()/2., 1.01*height,'%d' % int(height),ha='center', va='bottom')labelvalue(rects1)labelvalue(rects2)labelvalue(rects3)plt.savefig('barplot_2.png',dpi=200, format='png', bbox_inches='tight')plt.show()
使用上述代码,我们为 5 款车型的 top-N ACC 保存了一个漂亮的条形图,如下所示:
5 款车型的前 N 名 ACC 条形图
进步
但是,我们对这个条形图不太满意,因为条形图太多了。我们能简化显示数据吗🤔?例如,我们将前 1 名、前 3 名和前 5 名 acc 合并到一个条形图中,这意味着我们只需要 5 个条形图来显示 5 个型号的前 N 名 acc。情节中的信息要压缩。在这里,我们可以通过以下预处理输入数据来实现,其中我们减去前 5 名 acc 和前 3 名 acc 以获得差异,对前 3 名 acc 和前 1 名 acc 重复相同的操作。
我们用下面的代码绘制了一个新的条形图:
ax = df[['top-1 acc','top-3 acc','top-5 acc']].plot(kind='bar', title ="Top-N ACC for 5 different models", figsize=(12, 8), legend=True, fontsize=12,stacked=True)top_1 = df.iloc[:,3]top_3 = df.iloc[:,2]top_5 = df.iloc[:,1]xlabels = df.iloc[:,0]ax.set_xticklabels(xlabels,fontsize=10)ax.set_xlabel("models", fontsize=12)ax.set_ylabel("Top-N ACC/%", fontsize=12)for i, v in enumerate(top_1):ax.text( i ,v - 2, str(v), color='black')for i, v in enumerate(top_3):ax.text( i ,v - 3, str(v), color='black')for i, v in enumerate(top_5):ax.text( i ,v + 1, str(v), color='black')plt.savefig('barplot_2.png',dpi=200, format='png', bbox_inches='tight')plt.show()
运行代码后,我们得到一个简单的条形图,它将前 1 名 acc、前 3 名 acc 和前 5 名 acc 集成到一个条形图中。
更直观的 5 款车型前 N 名 ACC 条形图
最后一个条形图看起来非常直观和明显,尽管它包含的信息与倒数第二个有 15 个条形的条形图相同。此外,最后一个条形图的代码比倒数第二个条形图的代码短。因此,我选择在我的论文中使用新的条形图📜。
结论
在这个故事中,我根据自己的经验介绍了用 Python 绘制条形图的方法。对于学生和研究人员来说,掌握如何直观地展示他们的研究数据的技能是很重要的。条形图是科学论文中最好和最常用的插图之一。我希望我的故事对你了解 it⛳️.有所帮助
链接到 GitHub 库:【https://github.com/Kopfgeldjaeger/Bar_graph_with_Matplotlib
参考
这里有两个对 pandas 和 Matplotlib 有用的文档。
[## pandas 文档- pandas 1.1.2 文档
在文档中看到了一个错别字?想要改进现有功能?投稿指南将指导您…
pandas.pydata.org](https://pandas.pydata.org/pandas-docs/stable/index.html) [## Matplotlib . py plot . bar-Matplotlib 3 . 3 . 2 文档
制作条形图。这些条按照给定的对齐方式定位在 x 处。它们的尺寸由高度和宽度给出…
matplotlib.org](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.bar.html)
如何用 Wolfram 语言画一只猫和其他愚蠢的东西
原文:https://towardsdatascience.com/how-to-draw-a-cat-and-other-silly-things-with-the-wolfram-language-9bf33ac7101f?source=collection_archive---------44-----------------------
用草图-RNN 神经网络生成手绘草图
图片由作者根据春蕾居在 Unsplash 上的照片制作
你不能教一只老狗新把戏,但也许你可以教一个神经网络画一只猫的画?前几天,当我在仔细阅读总是很有趣的 Wolfram 神经网络库时,我发现了一个小珍品。一个名为 Sketch-RNN 的神经网络自称能够画出猫、狗、长号、风车和许多其他动物和物体。这个,我不得不试试!
为了画一个草图,这个草图-RNN 页面提示我复制并粘贴一大块 Wolfram 语言代码。这工作得非常好,但我想有一个单一的函数来隐藏所有的复杂性。所以我写了一个简单的 ResourceFunction 来做这件事。
这些资源函数非常棒,因为它们基本上是从 web 上自动下载的代码块:
DrawSketch = ResourceFunction[
"user:arnoudb/DeployedResources/Function/DrawSketch"
]
有了这个资源函数,我就可以试着画出我的第一只动物:
(图片由作者和人工“智能”提供)
好吧,所以结果更像是毕加索的作品,而不是伦勃朗的,但很明显,它得到了猫的本质。据推测,随着神经网络的改进和更先进的训练数据,这有可能走得更远。
所有的草图都有随机生成元素,所以你可以画 25 只猫,它们看起来都是独一无二的!
(图片由作者和人工“创造”)
使用这个漂亮的函数,你可以画出总共 114 种动物和物体。我决定尝试一下。许多物品一眼就能认出来,而其他一些则有点神秘:
(图片由作者和我们的人工“助手”提供)
您可以通过修改原始的 DrawSketch 函数并添加随机颜色和线条粗细来获得更多乐趣。这是我用菠萝做的一个例子:
(图片由作者在菠萝的帮助下提供)
这里的可能性是无限的,尝试所有的可能性是非常有趣的。我看不出这有什么实际的应用,除了通过提供给他们很多很多的例子让他们临摹来启发学龄前儿童画某些物体。我希望你喜欢这个愚蠢的小故事,如果你有兴趣了解更多关于 Wolfram 语言的知识,可以看看我最近发表的题为“学习 Wolfram,从零到英雄”的文章。它有一套很棒的指向这种编程语言学习资源的指针!😻🍍
- 基于草图——RNN 根据来自 Wolfram 神经网络库的 QuickDraw 数据进行训练
- 参考:D. Ha,D. Eck,“草图的神经表示”,arXiv:1704.03477 (2017)可从https://github . com/tensor flow/magenta-demos/tree/master/Sketch-rnn-js获得
如何使用 Python 和 Word2vec 绘制地图
原文:https://towardsdatascience.com/how-to-draw-a-map-using-python-and-word2vec-e9627b4eae34?source=collection_archive---------27-----------------------
从欧洲首都的 Word2vec 向量创建的主要组件的二维可视化表示,也称为地图。
雅各布·布朗在 Unsplash上的照片
到目前为止,Word2vec 绝对是我在自然语言处理研究中遇到的最有趣的概念。想象一下,一种算法可以真正成功地模仿理解单词的含义及其在语言中的功能,可以沿着数百个不同的主题测量单词的接近程度,可以回答更复杂的问题,如“谁对文学来说就像贝多芬对音乐来说”。
我认为直观地表示 word2vec 向量会很有趣:本质上,我们可以获取国家或城市的向量,应用主成分分析来降低维度,并将其放在二维图表上。然后,我们可以观察我们离实际的地理地图有多近。
在这篇文章中,我们将:
- 广义地讨论 word2vec 理论;
- 下载原始预训练向量;
- 看看一些有趣的应用:从列表中找出奇怪的一个,或者对单词进行算术运算,比如著名的
king — man + woman = queen
例子; - 看看我们仅仅基于 word2vec 向量就能多精确地画出欧洲的首都。
最初的 word2vec 研究论文和预训练模型来自 2013 年,考虑到 NLP 文献的扩展速度,它在这一点上是旧技术。更新的方法包括 GloVe (更快的训练,不同的算法,可以在更小的语料库上训练)和 fastText (能够处理字符 n-grams)。我现在坚持原始算法的结果。
快速 Word2Vec 简介
自然语言处理的核心概念之一是我们如何量化单词和表达式,以便能够在模型设置中使用它们。这种语言元素到数字表示的映射被称为单词嵌入。
Word2vec 是一个单词嵌入过程。这个概念相对简单:它一句接一句地在语料库中循环,并符合一个模型,该模型根据来自预定义大小窗口的相邻单词来预测单词。为此,它使用神经网络,但实际上并不使用预测,一旦模型被保存,它只保存第一层的权重。在最初的模型中,我们将要使用的模型,有 300 个权重,所以每个单词都由一个 300 维的向量表示。
请注意,两个单词不一定要彼此接近才能被视为相似。如果两个单词从未出现在同一个句子中,但它们通常被相同的单词所包围,则可以有把握地假设它们具有相似的意思。
word2vec 中有两种建模方法:跳跃式语法和连续式词汇袋,这两种方法都有各自的优点,并且对某些超参数很敏感……但是你知道吗?我们不会去适应我们自己的模型,所以我不打算在这上面花更多的时间,你可以在这篇文章或维基站点中阅读更多关于不同方法和参数的内容。
自然,你得到的单词向量依赖于你训练你的模型的语料库。一般来说,你确实需要一个巨大的语料库,有在维基百科上训练过的版本,或者各种来源的新闻文章。我们将要使用的结果是在谷歌新闻上训练出来的。
如何下载和安装
首先,您需要下载预先训练好的 word2vec 矢量。您可以从针对不同类型文档的各种模型中进行选择。我用的是最初的模型,在谷歌新闻上受过训练,你可以从很多来源下载,只需搜索“谷歌新闻向量负 300 ”。比如这个 GitHub 链接就是一个方便的方法:https://github.com/mmihaltz/word2vec-GoogleNews-vectors。
请注意,该文件有 1.66 GB,但在其辩护中,它包含了 30 亿个单词的 300 维表示。
当谈到在 Python 中使用 word2vec 时,同样,您有许多包可供选择,我们将使用gensim
库。假设您已经将文件保存在word2vec_pretrained
文件夹中,您可以像这样用 Python 加载它:
from gensim.models.keyedvectors import KeyedVectorsword_vectors = KeyedVectors.load_word2vec_format(\
'./word2vec_pretrained/GoogleNews-vectors-negative300.bin.gz', \
binary = True, limit = 1000000)
limit 参数定义了你要输入多少单词,一百万对我来说已经足够了。
玩文字游戏
现在我们已经有了 word2vec 向量,我们可以检查它的一些应用程序。
首先,你实际上可以检查任何单词的矢量表示:
word_vectors['dog']
正如我们所料,结果是一个 300 维的向量,很难解释。但这是整个概念的基础,我们通过将这些向量相加和相减来对它们进行计算,然后我们计算余弦相似度来找到最匹配的单词。
您可以使用most_similar
函数查找同义词,topn
参数定义了您希望列出多少个单词:
word_vectors.most_similar(positive = ['nice'], topn = 5)
结果是
[('good', 0.6836092472076416),
('lovely', 0.6676311492919922),
('neat', 0.6616737246513367),
('fantastic', 0.6569241285324097),
('wonderful', 0.6561347246170044)]
现在,你可能认为用类似的方法,你也可以找到反义词,你只需要输入单词' nice '作为一个negative
,对吗?不完全是,结果是这样的:
[('J.Gordon_###-###', 0.38660115003585815),
('M.Kenseth_###-###', 0.35581791400909424),
('D.Earnhardt_Jr._###-###', 0.34227001667022705),
('G.Biffle_###-###', 0.3420777916908264),
('HuMax_TAC_TM', 0.3141660690307617)]
这些单词与单词“ nice ”相距甚远,表明它并不总是如你所愿。
您可以使用doesnt_match
功能找出奇数:
word_vectors.doesnt_match(
['Hitler', 'Churchill', 'Stalin', 'Beethoven'])
返回Beethoven
。我想这很方便。
最后,让我们来看几个例子,这些例子通过给算法一种错误的智能感而使它出名。如果我们想要组合字向量father
和woman
的值,但是减去分配给字向量man
的值:
word_vectors.most_similar(
positive = ['father', 'woman'], negative = ['man'], topn = 1)
我们得到:
[('mother', 0.8462507128715515)]
首先,要理解这个手术有点困难,我认为把这个问题表述成“父亲对于男人来说,对于女人来说是什么?“其实没那么有用。想象我们只有两个维度:父母和性别。单词'女人'可以用这个向量来表示:[0, 1]
,'男人是[0, -1]
,'父亲是[1, -1]
,而'母亲是[1, 1]
。现在,如果我们用向量做同样的运算,我们会得到同样的结果。当然,不同之处在于我们有 300 个维度,而不是例子中的 2 个,维度的意义几乎无法解释。
当谈到 word2vec 操作时,有一个著名的性别偏见例子,单词' doctor' (我们知道,这是一个中性词)的女性版本曾经被计算为' nurse' 。我尝试复制它,但没有得到相同的结果:
word_vectors.most_similar(
positive = ['doctor', 'woman'], negative = ['man'], topn = 1) [('gynecologist', 0.7093892097473145)]
我猜是进步了吧?
好了,现在我们检查了一些基本的可能性,让我们在我们的地图上工作!
映射函数
首先,我们需要一个我们希望我们的映射函数做什么的计划。假设我们有一个想要可视化的字符串列表和一个单词向量对象,我们想要:
- 找到列表中每个单词的单词向量表示;
- 使用主成分分析将维度减少到 2;
- 创建散点图,将单词作为标签添加到每个数据点;
- 作为一个额外的奖励,可以通过任何维度“翻转”结果-主成分分析的向量具有任意方向,当我们绘制地理单词以更好地与现实世界的方向保持一致时,我们可能希望改变这一点。
我们将需要以下库:
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.decomposition import PCAimport adjustText
列表中一个不常用的库是 adjustText ,这是一个非常方便的包,它使得在散点图中编写图例变得简单,而且不会重叠。对我来说,找到这个解决方案出奇的困难,而且据我所知,在 matplotlib 或 seaborn 中没有办法做到这一点。
事不宜迟,这个函数正是我们所需要的:
def plot_2d_representation_of_words(
word_list,
word_vectors,
flip_x_axis = False,
flip_y_axis = False,
label_x_axis = "x",
label_y_axis = "y",
label_label = "city"):
pca = PCA(n_components = 2)
word_plus_coordinates=[]
for word in word_list:
current_row = []
current_row.append(word)
current_row.extend(word_vectors[word]) word_plus_coordinates.append(current_row)
word_plus_coordinates = pd.DataFrame(word_plus_coordinates)
coordinates_2d = pca.fit_transform(
word_plus_coordinates.iloc[:,1:300])
coordinates_2d = pd.DataFrame(
coordinates_2d, columns=[label_x_axis, label_y_axis])
coordinates_2d[label_label] = word_plus_coordinates.iloc[:,0] if flip_x_axis:
coordinates_2d[label_x_axis] = \
coordinates_2d[label_x_axis] * (-1) if flip_y_axis:
coordinates_2d[label_y_axis] = \
coordinates_2d[label_y_axis] * (-1)
plt.figure(figsize = (15,10)) p1=sns.scatterplot(
data=coordinates_2d, x=label_x_axis, y=label_y_axis)
x = coordinates_2d[label_x_axis]
y = coordinates_2d[label_y_axis]
label = coordinates_2d[label_label]
texts = [plt.text(x[i], y[i], label[i]) for i in range(len(x))] adjustText.adjust_text(texts)
现在该测试功能了。我绘制了欧洲国家的首都,但是你可以使用任何列表,总统或其他历史人物的名字,汽车品牌,烹饪原料,摇滚乐队,等等,只要在word_list
参数中传递它。我从中得到一些乐趣,有趣的是看到集群形成并试图在两个轴后面找到一个意义。
如果你想重现结果,这里有一些城市:
capitals = [
'Amsterdam', 'Athens', 'Belgrade', 'Berlin', 'Bern',
'Bratislava', 'Brussels', 'Bucharest', 'Budapest',
'Chisinau', 'Copenhagen','Dublin', 'Helsinki', 'Kiev',
'Lisbon', 'Ljubljana', 'London', 'Luxembourg','Madrid',
'Minsk', 'Monaco', 'Moscow', 'Nicosia', 'Nuuk', 'Oslo',
'Paris','Podgorica', 'Prague', 'Reykjavik', 'Riga',
'Rome', 'San_Marino', 'Sarajevo','Skopje', 'Sofia',
'Stockholm', 'Tallinn', 'Tirana', 'Vaduz', 'Valletta',
'Vatican', 'Vienna', 'Vilnius', 'Warsaw', 'Zagreb']
(安道尔的首都安道尔城不在列表中,无法找到 word2vec 识别的格式。我们会接受的。)
假设您仍然拥有我们在上一节中创建的word_vectors
对象,您可以像这样调用该函数:
plot_2d_representation_of_words(
word_list = capitals,
word_vectors = word_vectors,
flip_y_axis = True)
(y 轴被翻转,以便创建更类似于真实地图的表示。)
结果是:
Word2vec 欧洲地图
我不知道你的感受,当我第一次看到这张地图的时候,我简直不敢相信它的效果是如此之好!是的,当然,你观察的时间越长,你发现的“错误”就越多,一个不祥的结果是莫斯科并不像它应该的那样远离东方……然而,东方和西方几乎完全分开,斯堪的纳维亚和波罗的海国家很好地组合在一起,意大利周围的首都也是如此,这样的例子不胜枚举。
需要强调的是,这绝不意味着纯粹的地理位置,例如,雅典在西边很远,但这是有原因的。让我们回顾一下上面的地图是如何得出的,这样我们就可以充分欣赏它了:
- 谷歌的一组研究人员训练了一个巨大的神经网络,它可以根据上下文预测单词;
- 他们将每个单词的权重保存在一个 300 维的向量表示中;
- 我们取了欧洲各国首都的向量。
- 通过主成分分析将维数降低到 2;
- 将计算出的组件放在图表上。
我觉得这很棒!
参考
霍布森、科尔和汉尼斯(2019 年)。自然语言处理实践:理解、分析和用 Python 生成文本。曼宁出版,2019。
[## Word2vec
Word2vec 是一种自然语言处理技术。word2vec 算法使用神经网络模型来学习…
en.wikipedia.org](https://en.wikipedia.org/wiki/Word2vec) [## 欢迎阅读 adjustText 的文档!- adjustText 0.7 文档
adjustText 是一个小的库,帮助您调整 matplotlib 图上的文本位置,以删除或最小化与…的重叠
adjusttext.readthedocs.io](https://adjusttext.readthedocs.io/en/latest/)
如何在 Jupyter 上画维恩图
原文:https://towardsdatascience.com/how-to-draw-venn-diagrams-on-jupyter-75c604b093ac?source=collection_archive---------45-----------------------
使用 Matplotlib-Venn 的所有基本逻辑文氏图
freepik 创建的业务向量—www.freepik.com
**Table of Contents**[**Introduction**](#8858)1\. [A, B](#53bd)
2\. [TRUE, FALSE](#3ba9)
3\. [A AND B, A NAND B](#3e55)
4\. [A OR B, A NOR B](#ea60)
5\. [A XOR B, A XNOR B](#7811)
6\. [NOT A, NOT B](#296f)
7\. [A NOT B, B NOT A](#f0f1)
8\. [Implication A → B, B → A](#b2c4)
9\. [Mutually exclusive](#76e9)
10\. [Complement](#6b3d)
11\. [Subset](#b30b)[**Conclusion**](#a953)
介绍
在这篇文章中,你会发现如何在 Jupyter 上绘制基本维恩图。为此,我们将使用matplotlib-Venn。matplotlib-venn 用于绘制面积加权的二圆和三圆 venn 图。对于大多数的文氏图,我们将使用双圆文氏图。
(更新:我根据这些代码创建了一个 Python 包。请阅读本。)
让我们开始吧。
** [## 如何在 Docker 上运行 Jupyter 笔记本
不再有 Python 环境和包更新
towardsdatascience.com](/how-to-run-jupyter-notebook-on-docker-7c9748ed209f) [## 介绍基本的维恩图 Python 包:Vennfig
在 Jupyter 或 Terminal 上用一行代码画一个维恩图
towardsdatascience.com](/introducing-basic-venn-diagram-python-package-vennfig-fa3f8e4dcb36)
甲,乙
文氏图
我们将导入venn2
和venn2-circles
并创建一行两列的支线剧情。本文中的大多数图都是我使用的这种设置。
如果你需要所有维恩图都没有支线剧情的代码,可以在 这个链接 找到。
与使用set-edgecolor
相比,venn2-circles
能让你更好地控制边缘线,所以我们同时使用venn2
和venn2-circles
。
我们用相同的子集值为v1
和c1
设置ax=ax1
,这样两者会很好地重叠。
我们使用for
循环遍历每个区域。您可以在下面找到区域 id。
两个圆形区域的 id。图片由作者提供。
在for
循环中,我们设置颜色。我们可以使用其中一个字符{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}
,它是蓝色、绿色、红色、青色、品红色、黄色、黑色和白色的缩写。此外,您可以使用十六进制 RGB 或 RGBA 字符串(例如,'#4287f5'
或'#4287f580'
)。
对于区域 A,我们在区域 ID 10
和11.
中设置颜色
对于区域 B,我们在区域 ID 11
和01
中设置颜色。
我们用get_patch_by_id
到set_color
和set_alpha
。如果不使用set_alpha
,如果区域重叠,区域的颜色将是混合色。
我们需要删除数字,所以我们使用下面的代码来完成这项工作。
txt = v1.get_label_by_id(area)
if txt: txt.set_text('')
我们用set_axis_on
设置一个矩形边界,用set_facecolor
设置矩形的颜色。
我们使用set_title
来设置标题和字体大小。
我们需要在底部留出一些空间,所以我们使用下面的代码来完成这项工作。
ymin, ymax = ax1.get_ylim()
ax1.set_ylim(ymin - 0.1, ymax)
真,假
真假文氏图
对于“真实的”文氏图,我们为for
循环中的所有区域设置颜色skyblue
。
类似地,对于“假”文氏图,我们为for
循环中的所有区域设置颜色white
。
A 和 B,A 和 B
A 和 B,A 和 B 维恩图
对于“A 和 B”文氏图,我们为区域11
设置颜色skyblue
。
对于“A 与 B”维恩图,我们将颜色skyblue
设置为包括facecolor
在内的所有区域,除了区域11
。
A 或 B,A 也不是 B
A 或 B,A 或非 B 文氏图
对于“A 或 B”文氏图,我们为所有区域设置颜色skyblue
、10
、11
、01
,并将颜色white
设置为facecolor
。
对于“A 或非 B”文氏图,我们将颜色white
设置为所有区域,将skyblue
设置为facecolor
。
一个异或 B,一个 XNOR B
一个 XOR B,一个 XNOR B 维恩图
对于“A XOR B”文氏图,我们为区域10
和01
设置颜色skyblue
。
对于“A XNOR B”文氏图,我们将颜色skyblue
设置为区域11
和facecolor
。
不是 A,不是 B
不是 A,不是 B 文氏图
对于“非 A”文氏图,我们为区域01
和facecolor
设置颜色skyblue
,否则,我们为区域10
和11
设置颜色white
。
对于“非 B”文氏图,我们为区域01
和11
设置颜色white
,为区域10
和facecolor
设置颜色skyblue
。
A 不是 B,B 不是 A
A 不是 B,B 不是维恩图
对于“A 不是 B”的文氏图,我们将颜色skyblue
设置为区域10
,否则,我们将颜色white
设置为所有其他区域。
对于“B 非 A”文氏图,我们将颜色skyblue
设置为区域01
,否则,我们将颜色white
设置为所有其他区域。
蕴涵 A → B,B → A
A → B,B → A 文氏图
对于隐含的“A → B”文氏图,我们将颜色white
设置为区域10
,否则,我们将颜色white
设置为所有其他区域。
对于隐含的“B → A”文氏图,我们将颜色white
设置为区域01
,否则,我们将颜色white
设置为所有其他区域。
互斥的
互斥文氏图
对于互斥的文氏图,我们将颜色skyblue
设置为区域10
和01
。
补充
互补文氏图
你可以用一个圆形补丁和一个矩形补丁画一个圆形,但是我们将使用venn3
和venn3_circles
。我们画了三个圆,但我们将通过设置颜色white
来隐藏两个圆,这与facecolor
相同。
通过使用三圈标识,我们可以修改它的属性。
三个圆形区域的 id。图片由作者提供。
我们还通过使用text
添加了U
。
ax1.text(-1, 0.2, r'U', fontsize=15)
v.get_label_by_id()
返回一个对象,该对象是 matplotlib.text.Text 的实例。在这个例子中,我想向您展示如何通过使用set_fontsize
、set_color
、set_rotation
方法来改变它的属性。
子集
子集文氏图
我们可以使用venn2
和venn2_c
来创建一个子集文氏图。我们将区域01
设置为 0。
结论
matplotlib-venn 包用于绘制面积加权的二圆和三圆的维恩图,但是使用您的创造性思维,您也可以创建一个单圆的维恩图。
请继续关注下一篇文章。
通过 成为 会员,可以完全访问媒体上的每一个故事。
https://blog.codewithshin.com/subscribe**
如何用人工智能钻黑洞
原文:https://towardsdatascience.com/how-to-drill-a-black-hole-with-ai-bc96ac04bb71?source=collection_archive---------47-----------------------
黑洞是天空的奥秘。杰西·陈在 Unsplash 上的照片
如果爱因斯坦能做到,你也能。
我 今天是星期天,我们要在你的房间里安装一个新架子。“你能帮我一下吗,”你问。我无法把那颗螺丝拧进墙里。'
“你得先钻个洞,”我回答道,然后拿起螺丝刀。给你。
谢谢你,爱因斯坦!你大声喊道,脸上带着灿烂的笑容。
我傻笑。我敢肯定爱因斯坦在外太空钻的洞比他的墙还多…
“对不起,什么?”你越狱了。
我是说,太空中也有洞。“黑洞!”
在我们银河系的中心有一个黑洞。由马赫凯奥在 Unsplash 上拍摄的照片
你放下螺丝刀,哼了一声笑了。“是啊,爱因斯坦钻了它们,”
“所以他没有钻黑洞,但他告诉我们它们是如何工作的,”你总结道,擦去脸上笑出的泪水。它们是如何工作的?它们像暗物质一样吗?
嗯,不。他们是黑人,不是黑人!“那不一样,”我回答。他们基本上是大胖明星的尸体。
尸体呢。“到底怎么回事……”你说。
是的,尸体!“在它的一生中,恒星是一个巨大的氢球,逐渐燃烧成氦,然后变成更重的元素,”我开始说道。但当氢耗尽时,它就会崩溃。
为什么会崩溃?“它再也没有氢了,这是不是很可悲,”你又笑了。
“我不知道明星是否有感情,”我傻笑着回答。但是只要恒星燃烧氢,它就会发光。光的发射抵消了重力。这颗恒星会因为自身的引力而坍缩,但光的发射使它保持稳定。
“当恒星耗尽氢时,它不会发光,就会坍缩,”你问。
“一点不错,”我确认道。它因自身重力而坍塌。但只要它发光,它就稳定而有活力。
[## 明星
恒星是如何形成和演化的?恒星是最广为人知的天体,代表着最重要的…
science.nasa.gov](https://science.nasa.gov/astrophysics/focus-areas/how-do-stars-form-and-evolve)
“明白了,”你回答。我不确定你指的是星星还是你同时成功钻的洞。你转向我。所以当一颗恒星坍缩时,它基本上就死亡了。然后它就变成了一个黑洞,”
“如果它够重的话,”我澄清道。一颗恒星的终结基本上有三种方式。
埋葬、火葬和僵尸!”你大声喊道,脸上带着灿烂的笑容。
我笑了。不完全是。根据恒星的质量,它最终会成为白矮星、中子星或黑洞。例如,太阳的质量相当低。它最终会变成一颗白矮星。
“太阳会变成僵尸,”你断言,仍然咧着嘴笑。
“好吧,所以轻量级变成僵尸,”我同意。或者,正如天文学家所说的,白矮星
较重的星星呢?你戳。
黑洞是超大质量恒星的尸体
如果恒星的质量是太阳的十倍左右,一旦氢耗尽,就会发生超新星爆炸。“超新星爆发后,坍缩的物质变成了一颗中子星,”我回答道。
什么是中子星?你问。
中子星基本上是一堆中子。当恒星的质量足够大时,引力是如此之强,以至于质子和电子被挤压成中子。“现在你有了一个超高密度的中子球——中子星!”
好了,对我来说就是火葬了。“就像有些人死后被压成钻石,那些恒星被压成中子堆,”你宣布。
“这是个好主意,”我一边回答,一边把一个螺丝拧进了墙上的洞。现在有些恒星质量太大,无法成为中子星。它们被万有引力挤压,我们最终形成了一个黑洞!
当恒星耗尽燃烧所需的氢时,它就会死亡。威尔·斯图尔特在 Unsplash 上拍摄的照片
“好吧,那么黑洞是超大质量的死星?”你问吧。
“一点不错,”我确认道。它们是如此巨大,以至于没有任何东西可以稳定它们,所以所有的东西都会在其中坍塌。如果另一个物体离它太近,它就会像吸尘器一样被吸进去。
[## 一个人掉进黑洞的奇怪命运
它可能发生在任何人身上。也许你正在努力寻找一个新的适合人类居住的星球,或者你正在…
www.bbc.com](http://www.bbc.com/earth/story/20150525-a-black-hole-would-clone-you)
哇哦。“黑洞是埋藏的恒星尸体和巨大的真空吸尘器!”你惊呼。“我们能看看它们吗,”
不完全是。黑洞会吸走一切,甚至光。“反正天空很暗,我们什么也看不见,”我解释道。
但是我看到了一张黑洞的图片你插嘴。
“嗯,是的,”我承认。但是你在图片上真正看到的并不是黑洞本身。它是黑洞边缘的热物质。天文学家称之为事件视界。我们看不到视界后面,但我们可以看到它周围即将被吸入的非常热的物质。
显然拍那张照片真的很难。“为什么这么难,”你问。
“黑洞离我们真的很远,”我解释道。最近的黑洞距离地球如此之远,以至于在月球上看起来就像一个橘子那么大!所以我们需要一个非常大的望远镜来捕捉它。物体越小,我们需要的望远镜就越大。
黑红色抽象,类似黑洞。约翰·保罗·萨默斯在 Unsplash 上的照片
但是我们有非常大的望远镜,对吗?你问吧。
“是的,”我肯定地说。但是为了看到这个黑洞,我们需要一个地球大小的望远镜。
“哦,”你说。
好消息是,我们可以使用世界上不同的望远镜,把它们拼凑成一个大的。然后我们猜测在所有没有望远镜的地方,望远镜会看到什么。
我们猜?那幅著名的画是猜的吗?你哭了。
“嗯,这是一个非常聪明的猜测,”我回答道。“科学家们用人工智能来重建图像,他们是如何做到的非常令人惊讶。”
“哦,好的,”你笑着回答。看来人工智能是钻黑洞的螺丝刀!
我笑了。是的,你可以这么看。想想人工智能也习惯于发现我们从未见过的黑洞。或者它如何被用来探测引力波,引力波通常来自两个合并的黑洞
AI 摇滚!你惊呼。这就是为什么我们用它来研究黑洞,”
“是的,”当我们把你的架子抬到墙上的新位置时,我回答道。不过,我们还是用普通的洞和螺丝起子来钉墙吧,好吗?
“好吧,爱因斯坦,”你傻笑。但是我会在书架旁边挂一张黑洞的海报,不管有没有 AI!’
如何为你的人工智能应用程序轻松下载谷歌的开放图像数据集
原文:https://towardsdatascience.com/how-to-easily-download-googles-open-images-dataset-for-your-ai-apps-db552a82fc6?source=collection_archive---------16-----------------------
由作者通过 Canva 创作,图片列在( CC BY 2.0 许可下)
你是那种想要建立一个自定义图像分类器,但不知道如何从 Google 的 OpenImages 数据集中只下载“图像”而不是标签的书呆子吗?
GIF 承接自 G iphy
你是那种想要建立一个自定义对象检测器,但不知道如何从谷歌的 OpenImages 数据集的 600 个对象类中下载选定的类的人吗?
好吧,我的朋友,你并不孤单,我也曾经有过同样的问题,直到几周前我偶然发现了这个包裹。
但是在学习使用这个包之前,让我们深入了解一下关于 Google 的 OpenImages 数据集的基本事实。
谷歌的开放图像数据集:拨乱反正的举措
开放图像数据集被称为现有计算机视觉数据集中的巨人。它有大约 900 万张图像,标注有图像级标签、对象边界框、对象分段遮罩、视觉关系和本地化叙述。它包含 1.9M 图像上 600 个对象类的总共 16M 的边界框,使其成为具有对象位置注释的最大的现有数据集。
由作者通过 Canva 创建,图像通过像素拍摄
据说一张图片胜过千言万语,上面的图片展示了如果你不使用开放的图像数据集,你的应用程序可能会变成另一个物体检测器或另一个图像分类器。但是,如果你利用谷歌开放图像数据集的力量,你可能会把你的人工智能应用程序变成一个通用的可扩展的解决方案,可能服务于许多人或一个社区的需求。[难道这不是我们在不同的屋檐下努力工作的原因吗,通过人工智能来帮助那些无法帮助自己的人,这取决于你]。
开发者模式:是时候做一些安装了
背景故事:
几周前,当我在为我的定制麸质/非麸质食品分类器寻找一个更好的解决方案来下载谷歌的开放图像数据集时,我坚持不懈的搜索将我带到了最近在 2 月份发布的名为“ openimages 的 Python 包。
因此,在博文的这一部分,我将分享我将 python 包安装到我的 Linux 系统中的步骤,以及我如何使用 python 包中的模块来下载数据集中可用的几个类的图像。与此同时,我将分享下载任何类标签的图像和注释所需的命令。
包装说明:
openimages 包附带了一个“ download ”模块,该模块提供了一个具有两个下载功能的 API 和一个相应的 CLI(命令行界面),其中包括可用于从 OpenImages 数据集下载图像和相应注释的脚本入口点。
安装程序:
创建虚拟环境:
作为一个最佳实践,始终使用 Python " 虚拟环境"来为任何特定的应用程序安装 Python 包,因为最好在一个隔离的位置安装包或库,而不是全局安装。
对于 Linux 用户,键入以下命令
virtualenv <DIR>
source <DIR>/bin/activate
如果您是 window 用户,请使用
virtualenv <DIR>
<DIR>\Scripts\activate
当 virtualenv 处于活动状态时,您的 shell 提示符会以 < DIR > 为前缀。
现在,在不影响主机系统设置的情况下,开始在虚拟环境中安装软件包。让我们从升级pip
开始:
<DIR>:~$ pip install --upgrade pip
openimages 包适用于 Python 3.6+版本。所以,一定要确保你有一个支持 openimages 的版本。现在,在活动的虚拟环境中,键入。
<DIR>:~$ pip install openimages
该命令将下载一些库,这些库对于从 Google 的 OpenImages 数据集中下载图像和相应的注释非常重要。
下面列出了将要安装的库:
ImageHash-4.1.0
absl-py-0.9.0
astunparse-1.6.3
boto3–1.13.16
botocore-1.16.16
cachetools-4.1.0
cvdata-0.0.7
docutils-0.15.2
gast-0.3.3
google-auth-1.15.0
google-auth-oauthlib-0.4.1
google-pasta-0.2.0
grpcio-1.29.0
jmespath-0.10.0
keras-preprocessing-1.1.2
markdown-3.2.2
oauthlib-3.1.0
opencv-python-4.2.0.34
openimages-0.0.1
opt-einsum-3.2.1
protobuf-3.12.1
pyasn1–0.4.8
pyasn1-modules-0.2.8
requests-oauthlib-1.3.0
rsa-4.0
s3transfer-0.3.3
tensorboard-2.2.1
tensorboard-plugin-wit-1.6.0.post3
tensorflow-cpu-2.2.0
tensorflow-estimator-2.2.0
termcolor-1.1.0
这是软件包安装完成后输出的样子[open_images_second_trial]只是一个虚拟环境名。
截图由作者拍摄
与这些包一起,两个 python 入口点也被安装在环境中,对应于下面描述的公共 API 函数oi_download_dataset
和oi_download_images
:
openimages.download.download_images
仅用于下载图像openimages.download.download_dataset
用于下载图像和相应的注释。
入口点+ CLI == "您下载数据集的途径"
在这一节中,我将通过使用提供的入口点,向您介绍下载数据集的图像和注释所需的命令行参数。请务必参考下图来加深理解。
由作者至 Canva 创建
在了解了命令行参数[CLI]之后,是时候使用它进行进一步的操作了,任何猜测,是的,你是正确的,下载图像和它们的标签。
I:为类标签下载图像和 PASCAL 格式注释的使用示例
<DIR>:~$ oi_download_dataset --csv_dir ~/<dir_A> --base_dir ~/<dir_A> --labels Zebra Binoculars --format pascal --limit 200
最好将 CSV 目录和基本目录保存在同一个位置,限制完全取决于你想下载多少带有类别标签的图像。
一旦你运行这个命令,去喝热水或啤酒,因为它需要时间将数据下载到您的计算机存储。
II:为类标签下载图像的用法示例
<DIR>:~$ oi_download_images --csv_dir ~/<dir_A> --base_dir ~/<dir_A> --labels Surfboard --limit 200
如果您多次运行这个脚本,那么它将从~/ <dir_a>中读取 CSV 文件,而不是再次下载文件。</dir_a>
截图由作者拍摄
一旦您的课程下载完成,不要忘记退出您的虚拟环境,只需输入:
<DIR>:~$ deactivate
:~$
这标志着整个过程的结束。我希望当你在读这几行的时候,你的数据下载过程一定已经开始了,你一定已经在计划使用哪种模型或者保持什么样的学习速度等等。
资源:
- Openimage 0.0.1:从 Google 的 OpenImages 数据集下载图像和相应注释的工具。
- OpenImages 数据集 Github repo 。
- OIDv4 工具包:下载图像和标签用于物体检测和图像分类任务的实用工具。
- 打开图像的快速图像下载器 V4 。
感谢您的关注
亲教会媒体在 Unsplash 上拍摄的照片
你用你的时间阅读我的作品对我来说意味着一切。我完全是这个意思。
此外,如果你愿意,可以在 Medium、LinkedIn 或 Twitter 上关注我!我很乐意。
[## 纳文·曼瓦尼培养基
阅读纳文·曼瓦尼在媒介上的作品。一个机器学习工程师,一个深度学习爱好者|Mentor @ Coursera…
medium.com](https://medium.com/@naveenmanwani) [## Naveen Manwani -机器学习工程师- AIMonk Labs Private Ltd | LinkedIn
查看纳文·曼瓦尼在全球最大的职业社区 LinkedIn 上的个人资料。Naveen 有一份工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/naveen-manwani-65491678/) [## 纳文·曼瓦尼
纳文·曼瓦尼的最新推文(@纳文·曼瓦尼 17)。机器学习工程师@ AIMONK Labs Pvt ltd,深…
twitter.com](https://twitter.com/NaveenManwani17)
如何在 Python 中轻松集成来自 Google Sheets、Dropbox 和你的桌面的电子表格
原文:https://towardsdatascience.com/how-to-easily-integrate-spreadsheets-from-google-sheets-dropbox-and-your-desktop-in-python-9f4065135449?source=collection_archive---------48-----------------------
告别电子表格集成难题
免责声明:这篇文章使用了我做的一个产品, API 电子表格 ,我相信这确实是最简单的方法。你可以自己去看看。
当你从事数据科学或分析项目时,通常到处都存储着大量的电子表格。
如果你和我一样,你可能会这样做:
- 下载你的谷歌工作表作为电子表格
- 下载你的 Dropbox 电子表格
- 把它们和你的桌面文件放在同一个文件夹里
- 使用熊猫读取所有文件
这是一个不错的工作流程。但是营销部门的史蒂夫改变了谷歌表单中的一些数据。
“不要担心”,您在重新下载表单并重新运行工作流程时回复。
现在,人力资源部的卡玛拉又给 Dropbox 添加了两个电子表格。
“我明白了”,你一边慢慢冷静一边说。
然后你的老板告诉你把你所有的电子表格用电子邮件发给她,这样她就可以对你的数据进行三次检查。“哦,顺便说一句”,她说,“不要忘了使用我们副总裁力推的样式来更改所有电子表格的名称”
你正式失去理智了。
照片由诺亚·布舍尔在 Unsplash 上拍摄
更简单的方法
我将向您展示如何使用 API 电子表格和 Python 轻松地将所有这些来源的数据整合在一起。并保持更新和同步。这样你就能保持冷静和快乐!
我们将使用 1 个谷歌表,1 个本地文件和 1 个 Dropbox 文件。每个文件将包含来自一个唯一美国州的 Covid 数据:TX、NJ 或 CA。数据将按县在每行上分解,如下所示:
来自 NJ 文件的样本数据。每个文件中的标题都是相同的
我们开始吧!
步骤 0:创建一个空的 Python 文件
创建一个名为spread sheet _ integration . py的空 Python 文件,并将其保存在某个地方。
该文件的最终代码如下。我们将在这篇文章中介绍如何到达那里。
最终文件代码
步骤 1:创建一个 API 电子表格免费帐户
前往www.apispreadsheets.com点击注册创建一个免费账户
第二步:连接到你的谷歌表单
点击谷歌表单上传框
点击 Google Sheets 上传框开始连接
选择您想要连接的 Google 表单
选择要连接的文件
从 Read 选项卡中复制 Python 代码并粘贴到您的 Python 文件中
您的 Python 文件现在将包含以下代码
import requestsr = requests.get("[https://api.apispreadsheets.com/data/581/](https://api.apispreadsheets.com/data/581/)")if r.status_code == 200:
# SUCCESS
data = r.json()
else:
# ERROR
data=None
我们现在要改变代码中的两件事,使数据更容易处理
- 我们将从 r.json()对象的数据键中访问数据
- 我们将导入熊猫并将数据转换成熊猫数据框架
我们的代码现在将如下所示
import requests
import pandas as pdr = requests.get("[https://api.apispreadsheets.com/data/581/](https://api.apispreadsheets.com/data/581/)")if r.status_code == 200:
data = pd.DataFrame(r.json()["data"])
else:
data = None
这篇文章中的所有 API 链接都是公开的,所以请随意使用这些链接进行测试!
步骤 3:连接到你的 Dropbox 文件
点击 Dropbox 上传框。第一次点击会要求您进行身份验证,或者如果您的帐户已经在标签中打开,它会刷新页面。这是 Dropbox 身份验证的预期行为。
点击 Dropbox 上传框开始流程
现在再次点击 Dropbox 上传框,你会看到一个文件选择器。选择您的文件。
按照与上面相同的步骤在文件中复制 Python 代码。
但是,我们现在将更改请求和数据的名称,以便于识别
import requests
import pandas as pdgoogle_sheet_request = requests.get("[https://api.apispreadsheets.com/data/581/](https://api.apispreadsheets.com/data/581/)")dropbox_request = requests.get("[https://api.apispreadsheets.com/data/582/](https://api.apispreadsheets.com/data/582/)")if google_sheet_request.status_code == 200:
google_sheet_data = pd.DataFrame(google_sheet_request.json()["data"])
else:
google_sheet_data = Noneif dropbox_request.status_code == 200:
dropbox_data = pd.DataFrame(dropbox_request.json()["data"])
else:
dropbox_data = None
步骤 4:从桌面上传文件
现在,我们将从您的桌面上传文件。
我们不会再用这个过程来烦你了。只需点击上传或删除文件框,上传您的文件。
按照与上面相同的步骤获取 python 代码,并将其插入到 Python 文件中。然后更改变量名,这样就有意义了。
这将引导我们找到最终的代码
原谅 local_data 上的缩进
就是这样!这就是集成各种来源的电子表格数据有多容易。
最棒的是,如果底层的 Google Sheet 或 Dropbox 文件数据发生变化,那么你的数据会自动更新。
如果你想和别人分享你的数据,你只需要给他们发送 API 链接。
祝你整合之旅好运,如果你遇到任何麻烦或有任何问题,请随时给我在 adhaar@lovespreadsheets.com 留言。
如何使用 TensorFlow 在您的 GPU 上轻松处理音频
原文:https://towardsdatascience.com/how-to-easily-process-audio-on-your-gpu-with-tensorflow-2d9d91360f06?source=collection_archive---------4-----------------------
使用 TensorFlow 的信号处理模块,充分利用您的 GPU 处理音频数据的能力
由沙哈达特拉赫曼在 Unsplash 上拍摄的照片
对音频数据的深度学习通常需要繁重的预处理步骤。
虽然有些模型运行在原始音频信号上,但其他模型期望将时频表示作为输入。在模型训练之前,预处理通常作为一个单独的步骤来完成,使用像[librosa](https://librosa.github.io/librosa/)
或[Essentia](https://essentia.upf.edu/)
这样的工具。
但是,当您开始处理更大的数据集时,此工作流会带来挑战。
任何时候改变参数,比如采样率或 FFT 大小,都需要再次处理整个数据集,然后才能继续训练。
这意味着等待。😴
即使在可用的 CPU 内核上并行化,预处理也需要很长时间。另外,您需要考虑如何存储和访问不同参数的文件。这无疑会浪费磁盘空间和精神资源,并且很快会变得令人头痛。
这些听起来熟悉吗?
厌倦了这种繁琐的两步走的过程,我开始问自己是不是没有更好的办法。
“没有更好的办法了吗?”
我最近建立了一个高效的音频数据管道,它使我能够按需将音频从文件路径加载到模型中。
[## 如何使用 TensorFlow 2.0 构建高效的音频数据管道
使用 TensorFlow 的数据集 API 消除培训工作流程中的瓶颈
towardsdatascience.com](/how-to-build-efficient-audio-data-pipelines-with-tensorflow-2-0-b3133474c3c1)
我还想对基于声谱图的模型使用相同的数据管道。
在这篇文章中,我想和你分享:
- 如何利用 GPU 的能力来完成信号处理任务。
- 如何构建自定义预处理层以用于任何神经网络。
- 最后还有一点奖金。😲
请继续阅读,了解更多信息。
如何用 5 个简单的步骤预处理您的音频数据
深度学习应用中跨音频域的流行特征表示是 mel-spectrogram 。
mel 谱图是信号频谱随时间变化的直观表示。与标准声谱图的主要区别在于,频率被投射到 mel 音阶 上,其中音高的感知距离等于 mel 频率的距离。这是受我们如何听的启发。
同样,梅尔频谱图的幅度通常是对数标度的,因为这更接近于我们如何感知响度的变化。因此,更精确的术语应该是对数级 mel 标度频谱图。但因为这相当拗口,所以大多数人简称它为对数-梅尔-光谱图或梅尔-光谱图。值得指出的是,尽管 mel 指的是频率等级,但是 log 描述的是震级的等级。
那么,如何将原始音频信号转换成 mel 频谱图呢?
- 计算音频信号的短时傅立叶变换
- 计算大小
- 实例化 mel 滤波器组
- 将线性标度的星等谱图弯曲到 mel 标度
- 将幅度转换为对数标度
让我们详细看看每一步。
这是我们将要学习的声音示例
1.计算短时傅立叶变换
短时傅立叶变换(STFT)将长信号分成较短的片段,通常称为帧,并计算每帧的频谱。帧通常会重叠,以尽量减少边缘的数据丢失。将每一帧的光谱结合起来就产生了光谱图。
要使用 TensorFlow 计算 STFT,请使用[tf.signal.stft(signals)](https://www.tensorflow.org/api_docs/python/tf/signal/stft)
,其中signals
是包含音频信号的张量。
您需要设置的一些参数是:
frame_length
:样本中每一帧的长度。这通常被称为窗口长度或窗口大小。窗口大小以时间分辨率(短窗口)换取频率分辨率(长窗口)。frame_step
:帧间样本数。这通常被称为跳长或跳大小。fft_length
:要应用的 FFT 的大小。这通常称为 FFT 大小,与frame_length
相匹配。它默认为可以包含一个框架的最小 2 次方。因此,如果frame_length
是 2 的幂,并且你没有显式地设置fft_length
,它取相同的值。
spectrograms = tf.signal.stft(signals,
frame_length=1024,
frame_step=512)
2.计算大小
上一步中的 STFT 返回一个复数值张量。使用[tf.abs()](https://www.tensorflow.org/api_docs/python/tf/math/abs)
计算震级。
magnitude_spectrograms = tf.abs(spectrograms)
我们现在可以画出星等谱图。
不过,请注意,在正确缩放数量级之前,您不会看到太多。第二个支线剧情用librosa.amplitude_to_db()
缩放。所以,从技术上讲,这是一个对数级的功率谱。
在第 5 步中会有更多的介绍。
上图:星等谱图。是全黑吗?不。如果你仔细看,你可以在较低的频率上看到一点能量。下图:对数幅度谱图。当量值用对数标度时,你可以在几个频带中看到能量。
3.实例化 Mel-滤波器组
将标准频谱图转换为 mel 频谱图包括将频率扭曲到 mel 标度,并将 FFT 仓组合到 mel 频率仓。
TensorFlow 使这种转变变得容易。
您可以使用[tf.signal.linear_to_mel_weight_matrix()](https://www.tensorflow.org/api_docs/python/tf/signal/linear_to_mel_weight_matrix)
创建一个 mel-filterbank,将线性标度光谱图扭曲到 mel 标度。
您只需要设置几个参数:
num_mel_bins
:生成的 mel 谱图中 mel 频段的数量。num_spectrogram_bins
:源谱图中唯一谱图仓的数量,等于fft_length // 2 + 1
。sample_rate
:输入信号每秒的样本数。lower_edge_hertz
:包含在 mel 标度中的最低频率,单位为赫兹。upper_edge_hertz
:包含在 mel 标度中的最高频率,单位为赫兹。
具有 16 个梅尔槽的梅尔滤波器组
4.将线性标度的星等谱图弯曲到 mel 标度
将平方的星等谱图乘以 mel 滤波器组,就可以得到 mel 标度的功率谱图。
mel_power_specgrams = tf.matmul(tf.square(magnitude_spectrograms),
mel_filterbank)
5.将幅度转换为对数标度
我们以对数方式感知响度的变化。所以,在这最后一步,我们也想用对数来表示 mel 光谱图的幅度。
做到这一点的一个方法是获取梅尔光谱图的log
。但是这可能会给你带来麻烦,因为log(0)
没有定义。相反,您希望以数值稳定的方式将幅度转换为分贝 (dB)单位。
log_magnitude_mel_spectrograms = power_to_db(mel_power_spectrograms)
下面是如何在基于[librosa.power_to_db](https://librosa.github.io/librosa/_modules/librosa/core/spectrum.html#power_to_db)
的 TensorFlow 中做到这一点。
将功率谱转换为张量流中的分贝单位
转换成对数标度后,光谱图的最大值为零,最小值为负top_db
。
“电子琴”的 mel 频谱图,具有 64 个 Mel 频段、16 kHz 采样率、1024 个样本 FFT 大小和 512 个样本跳数大小
现在有趣的部分来了。
准备好立即获得更大的灵活性了吗?
将各个步骤组合到一个自定义的预处理层中,允许您将原始音频馈送到网络,并在 GPU 上动态计算 Mel-spectro gram。
为了创建你的 mel-spectrogram 层(或任何自定义层),你从[tf.keras.layers.Layer](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer)
和子类实现三个方法:
__init__()
:将层的配置保存在成员变量中。build()
:定义你的体重。call()
:执行将图层应用到输入张量的逻辑。这是你将音频输入张量转换成梅尔频谱图的地方。
下面是我实现的一个自定义 Keras 层,它将原始音频转换为 log-Mel-spectrogram:
使用此自定义 Keras 层将原始音频转换为 log-Mel-spectrogram
一旦定义好,你就可以在一行代码中添加音频预处理到你的神经网络中。
一个神经网络的例子,它使用了我们上面定义的自定义 LogMelSpectrogram-layer
现在,您可能想知道,将相同的音频信号一次又一次地转换成频谱图,效率会不会低得令人难以置信。
这是一个很好的观点。
在写这篇文章的时候,我遇到了一个“用于音频和音乐信号预处理的 Keras 层”库。作者,Choi 等人,展示了一个基准,它显示,他们的预处理层增加了大约 20%的开销。
所以,这是一个权衡。就像生活中的任何事情一样。
在这种情况下,您用存储空间换取了稍长的计算时间。但不仅如此。您还可以摆脱繁琐的两步过程,并立即获得在音频数据上训练深度学习模型的更大灵活性。
尝试不同的预处理参数现在就像用不同的参数重新开始你的训练程序一样简单。
- 不需要维护单独的预处理脚本。
- 无需记住在多个地方更改参数。
- 在继续训练之前,无需处理整个数据集。
值得开销吗?
你自己决定。
这里有些东西可以帮你做到这一点
所有代码和示例都可以在这个 Colab 笔记本中找到:
[## Google Colab:如何使用 TensorFlow 在 GPU 上处理音频
免费笔记本,互动体验这篇文章。
colab.research.google.com](https://bit.ly/2QEBKEJ)
现在轮到你了。
你简化了(或喜欢简化)的工作流程中有哪一个给了你更多的灵活性和思维空间,尽管它稍微贵了一点?
参考
- 【1】h . Purwins 等,音频信号处理的深度学习(2019),IEEE 信号处理精选期刊 13.2:206–219
- [ 2 ] K. Choi 等人,Kapre:快速实现深度神经网络模型的 GPU 上音频预处理层,Keras (2017) arXiv 预印本
如何在 Keras 模型中轻松使用梯度累积
原文:https://towardsdatascience.com/how-to-easily-use-gradient-accumulation-in-keras-models-fa02c0342b60?source=collection_archive---------11-----------------------
实现通用梯度累积机制的分步指南
照片由法比安·格罗斯在 Unsplash 上拍摄
在的另一篇文章中,我们讨论了什么是深度学习中的梯度累积,以及它如何解决运行大批量神经网络时的问题。
在本文中,我们将首先看到如何轻松使用我们在 Run:AI 中实现和使用的通用渐变累积工具。然后,我们将深入研究 Keras 优化器以及我们实现这种通用工具的方式。
代码可以从 GitHub上获得,同时还有示例可以开箱即用。
在您自己的模型中使用渐变累积
向 Keras 模型添加渐变累积支持非常简单。首先,使用命令安装 Run:AI Python 库:
pip install runai
然后,将渐变累积包导入到 Python 代码中:
import runai.ga
现在,你可以从两个选项中选择一个。您可以用通用的梯度累积包装器包装现有的优化器,或者创建任何内置优化器的梯度累积版本。这两个选项需要指定您想要累积梯度的步数(在下面的示例中作为STEPS
传递)。
使用下一行包装一个现有的优化器(其中optimizer
是您的优化器):
optimizer = runai.ga.keras.optimizers.Optimizer(
optimizer, steps=STEPS)
或者,使用下一行创建任何内置优化器的渐变累积版本(下一个示例中使用了“Adam”):
optimizer = runai.ga.keras.optimizers.Adam(steps=STEPS)
就是这样!您已经成功地向 Keras 模型添加了梯度累积支持。
Keras 优化器概述
在了解了它的易用性之后,现在让我们来看看它到底是怎么回事。首先,我们将研究 Keras 中优化器的概念,并讨论它们的责任和实现。然后,我们将深入探讨我们是如何实现这样一个通用机制的。
哲学
Keras 中的优化器负责实现优化算法——负责最小化损失函数的数学公式。它们接收所有模型参数(权重和偏差)作为输入,计算它们的梯度,并使用它们来生成模型参数的更新。模型参数的更新不是梯度本身,而是使用梯度以及其他参数来计算的。
每个优化算法都有参数。有些优化器有相似的参数(如“epsilon”、“beta_1”、“beta_2”等…),有些可能有独特的(如 Adam 中的“amsgrad”),它们都支持“学习率”(以及学习率衰减)。
在构建模型时,Keras 将调用优化器并传递两个参数。第一个参数将是模型的所有可训练变量——权重和偏差。第二个参数是损失值。注意,可训练变量和损失是张量,而不是张量的实际值。
然后,优化器获取这些输入张量,并将优化算法添加到模型中。它首先计算可训练变量相对于损失的梯度(通过调用tf.gradients()
),然后生成代表数学公式的张量。
然后,Keras 将评估这些张量——由优化器生成——每一步。通过评估这些张量,将计算梯度,然后计算变量更新并将其分配给模型变量,即权重和偏差。
履行
Keras 优化器是 Python 类,它们都继承了一个叫做Optimizer
的基类(这里可以看到)。基类实现了一些方法,并声明了必须在子类中实现的其他(虚拟)方法。让我们简单地检查一下Optimizer
中的方法:
__init__(self, **kwargs)
:初始化常用成员和配置参数。get_updates(self, loss, params)
:没有在基类中实现的虚方法,必须在子类中定义,实现优化器的数学公式。get_gradients(self, loss, params)
:相对于params
(技术上是tf.gradients()
的一个包装器)简化loss
的梯度计算的实用方法。set_weights(self, weights)
:设置优化器的权重值。get_weights(self)
:获取优化器的权重值。get_config(self)
:获取常用配置值。
我们将关注get_updates()
。此方法仅在基类中声明(虚拟的);它不在 it 中实现,必须在所有子类中实现。它的实现是不同优化器之间的主要区别。
正如我们所说,Keras 将调用get_updates()
作为构建模型的一部分。该方法接收两个参数:loss
和params
,它们都是张量。并返回一个张量列表,它们是“赋值”操作——在求值时实际赋值变量更新的张量。
SGD 实现的简化版本
SGD 优化器的算法
让我们检查 SGD 的get_updates()
实现的简化版本。请注意,这是一个简化版本,而不是 Keras 中的实际代码:
SGD 的 get_updates()的简化版本
首先,在第 2 行,优化器通过调用self.get_gradients()
来计算loss
相对于params
的梯度。
然后,在第 4–6 行,优化器遍历模型的所有可训练变量,以及它们各自的计算梯度。对于每个参数,它使用梯度和学习率计算(第 5 行)变量的新值(self.lr
是在__init__()
中初始化的张量)。然后,它创建一个张量,该张量将分配变量的新值(K.update(p, new_p)
),并将其添加到此类张量的列表中(self.updates
)。
最后,在第 8 行,优化器返回“赋值”张量的列表(self.updates
),Keras 将在每一步对其进行评估。
在构建模型时,该方法只被调用一次。这可能需要一些时间来消化,但一定要理解,参数和结果是张量对象,而不是实际的张量值。请注意,第 5 行可能会引起误解,看起来它计算的是实际值,但事实并非如此,它只是张量对象上的语法糖(TensorFlow 的操作符重载)。
现实中更复杂一点
在检查了简化版本之后,是时候弄清楚现实中会发生什么了。
除了它们的简单算法之外,大多数优化器支持学习率衰减,这意味着它们在模型的整个训练过程中修改学习率,而不是为它提供一个常量值。为了支持随时间修改学习率,应该定义时间的概念。正如预期的那样,学习率不是作为自训练阶段开始以来已经过去的实际时间的函数来修改的,而是作为步数的函数来修改的,并且为了支持这一点,优化器计算步数(在它们的实现中称为iterations
)。
此外,Keras 中的 SGD 支持动量和内斯特罗夫动量算法,这使事情变得更加复杂。让我们来看看 SGD 的get_updates()
的实际实现(在 GitHub 上也可以看到):
SGD 的 get_updates()
让我们检查一下我们之前检查过的简化版本的附加内容。
在第 3 行,优化器创建了一个“赋值”张量,在每一步中把self.iterations
增加 1。self.iterations
是步数计数器(张量对象),在__init__()
中创建,初始值为 0。
在第 5–7 行中,我们可以看到学习率衰减公式是步进计数器(self.iterations
)和衰减值(创建时传递给优化器的参数,并设置为self.decay
)的函数。
在第 11 行,它创造了动量的变量。它为每个可训练变量声明另一个具有相同形状的变量,并将其初始化为 0(调用K.zeros(shape)
)。
然后,在可训练变量的迭代中,它计算每个动量的新值(第 14 行),并创建一个“赋值”张量以用新值更新动量(第 15 行)。
然后,在第 17–20 行,它计算参数的新值——取决于是否配置为应用内斯特罗夫动量——并在第 23–24 行对参数应用必要的约束(如果有的话)。
其余的行类似于之前的简化版本。
你可以逛逛optimizer . py并阅读 Keras 不同优化器的实现。
实施梯度累积机制
现在,在深入研究了什么是 Keras 优化器以及它们是如何实现的之后,我们准备讨论梯度累积机制的不同实现方案。
每个优化器特定的实现
可以重写任何优化器来支持梯度累积。梯度应该在几个步骤中累积,然后优化器才应该使用它们来更新模型参数。这不是最佳的,因为梯度累积是一种通用的方法,应该是独立于优化器的,并且这种方法有几个缺陷:
- 每个优化器都有不同的公式来实现不同的优化算法,因此对于相应的梯度累积版本将需要不同的实现。
- 这是特定于版本的,每次原始实现发生变化或添加新的优化器时,都需要修改代码。
- 它会导致代码重复,而且不够优雅。
一种更可取的方法是设计梯度累积模型,使其能够包装任何 Keras 优化器,而不管其优化算法如何。
Keras 优化器的通用包装器
通过具有通用的梯度累积机制,原始优化器中的变化将不需要代码更新。
为了设计和实现通用的梯度累积机制,需要考虑一些事情。
为什么我们需要一个复杂的解决方案?
在每个小批量上运行优化算法不会导致模型参数的相同更新。换句话说,我们不能只在每一步评估优化算法——在每一个小批量上。否则,没有必要进行梯度累积,我们可以使用较小的批量。
如果我们使用全局批次,所有梯度都将使用相同的模型参数值(权重和偏差)进行计算。当将全局批量分成几个小批量时,评估每个步骤的优化算法将导致在每个小批量之后更新模型参数。这意味着不会使用相同的权重和偏差值来计算所有小批量的梯度。
此外,优化器使用各种参数作为其公式的一部分,并且这些参数作为优化算法评估的一部分被更新。在每个小批量之后,每步更新这些参数将导致不同小批量之间优化算法的状态变化。
那我们该怎么办?
我们的包装器是一个继承了 Keras 的基类Optimizer
的 Python 类。我们在创建时接收原始优化器作为参数(在__init__()
中),以及我们想要累积梯度的步骤数。
我们定义优化器公开的所有方法(即get_gradients()
、set_weights()
、get_weights()
等……),并透明地调用原始优化器各自的方法。正如所料,主要逻辑位于get_updates()
中。
让我们开始研究get_updates()
(也可以在 GitHub 上看到),并深入研究算法和实现:
渐变累积包装的 get_updates()
计算梯度
第一行(2)应该看起来很熟悉,我们用和其他优化器一样的方法计算梯度。注意grads
将保存每个小批量的梯度值。
声明辅助张量
在第 5 行中,我们声明了一个步长计数器,名为iterations
,初始值为 0(与其他优化器非常相似)。我们使用步数计数器来判断我们是处于累积的第一步还是最后一步。为此,我们声明两个张量:first
和last
(第 6–7 行)。
first
将被设置为True
每次我们正好经过self.steps
步。从技术上讲,此时iterations % self.steps
将等于 0。例如,如果我们在五个步骤上进行累积,那么在第一个步骤(索引为 0)、第六个步骤(索引为 5)、第十一个步骤(索引为 10)等都是这种情况。在这些情况下,在步骤开始时,我们希望将累积的梯度重置为 0,并再次开始累积。
last
将被设置为True
每一步我们要更新的变量。从技术上讲,此时iterations % self.steps
将等于self.steps — 1
。继续前面的例子,这将是第五步(索引 4)、第十步(索引 9)等的情况
累积的梯度
在第 10 行中,我们声明变量来保存步骤之间的累积梯度值。我们用参数的形状和类型为每个模型参数——为每个可训练的权重或偏差——声明这样一个变量,并用零初始化它们。
使用这些变量,在第 13 行我们声明了张量——agrads
——来保存每一步中累积的梯度值。我们使用first
来告诉我们是否应该从现在开始累积梯度或者使用在前面步骤中累积的梯度。如果first
是True
——意味着我们从现在开始累积——我们单独使用当前小批量的梯度。如果first
是False
——意味着我们应该使用在过去步骤中累积的梯度——我们将当前小批量的梯度加到vagrads
。使用K.switch()
将该控制流(检查first
的值)生成到模型中。
好的,那太好了,但是优化算法本身呢?
作为一个通用包装器,我们不实现任何优化算法。最初的优化器对此负责。正如我们所介绍的,每个优化器都在get_updates()
中实现它的数学公式。在这里,优化器管理并使用公式所需的所有参数(例如,步数计数器、学习率、动量等)。优化器将参数值存储在专用变量中,每次需要更新参数时,它都会将新值赋给专用变量。
方法get_updates()
被调用一次,生成将在每一步中评估的“赋值”张量。其中一些是模型参数的更新,另一些是优化器参数的更新。
只要我们在累积梯度,我们不希望任何这些更新发生。我们不希望更新模型参数,以使所有小批量从完全相同的点开始,在权重和偏差方面具有相同的值。我们不希望优化器参数被更新,以便优化器以好像在全局批处理上运行的速度前进。例如,我们希望步骤计数器仅在所有小批量通过后才增加,因此学习速率将以正确的速率修改。
我们希望所有的更新都在所有的小批量通过之后才发生。从技术上讲,这意味着我们希望更新发生在累加的最后一步——当last
为True
时。
因此,如果我们可以调用最初的优化器的get_updates()
,同时(1)使它使用累积的梯度,并且(2)使所有的变量更新只发生在累积的最后一步,我们将会实现我们想要的。
幸运的是,在 Python 中替换(挂钩)方法真的很容易,通过用不同的实现替换一些方法,我们可以很容易地做到这一点。
优化器从get_updates()
调用它们的get_gradients()
来计算参数相对于损失的梯度。因此,我们将优化器的get_gradients()
替换为一个只返回累积梯度的函数(agrads
—我们在第 13 行生成的张量)。这将导致原始优化器在其算法中引用累积的梯度,并将求解(1)。让我们来看看这种替换方法的简化实现:
get_gradients()替换的简化版本
关于(2),Keras 中的变量可以用三种方法赋值:K.update()
、K.update_add()
和K.update_sub()
。优化器将这些方法用于所有更新——模型参数和优化器参数。我们把他们三个都换掉(可以在 GitHub 上看到)。我们希望使用这些方法创建的所有张量只在最后一个小批量中赋值,否则不做任何事情。因此,在我们的方法中——取代了这三个方法——我们用一个条件开关包装每个被赋值的值,并将这个开关传递给相应的方法。如果这是最后一个小批量(last
是True
),我们将实际值赋给变量,否则,我们赋一个不影响变量的值。对于K.update_add()
和K.update_sub()
,我们赋零,导致变量实际上没有增加或减少。对于K.update()
,我们分配变量的当前值,使变量保持其当前值。让我们来看看这种替换方法的简化实现:
替代赋值方法的简化版本
回到我们的get_updates()
,在第 15–18 行,我们实际上替换了所有这些方法。我们使用助手类——runai.utils.Hook
的子类——来实现这一点。
在第 19 行,我们调用原始优化器的get_updates()
。替换所有这些方法后,我们(1)使其引用累积的梯度,以及(2)使所有更新(“分配”操作)仅在last
为True
时发生。
更新我们的参数
在每一步的最后,我们还有两件事要做。
首先,我们必须更新我们的变量来保存累积梯度的当前值。这是在第 33 行完成的。
其次,我们必须推进我们的步计数器— self.iterations
(第 36 行)。为了确保这发生在步骤的最后,我们在所有其他“赋值”操作的控制依赖下生成张量。这导致步数计数器更新仅在所有其他更新已经发生之后才发生。
结论
这篇文章和之前的文章旨在详细描述一些事情:
- 训练神经网络时可能遇到的批量调整问题以及受 GPU 内存限制的问题。
- 为什么以及如何梯度积累可能有助于解决这些问题。
- 深入探讨 Keras 优化器以及在构建梯度累积机制时需要考虑的事项。
- 如何使用 Run:AI Python 库,轻松为你的 Keras 模型添加渐变累积支持。
我们希望我们能够阐明这些主题,并帮助您更好地理解它们。
后续步骤
在 GitHub 上有一个开源的渐变累积工具,以及使用示例和更多资源。
如果你觉得这很有趣并且对运行你自己的神经网络有帮助,请与我们分享!
如何有效地定义和验证 AI/ML 用例
原文:https://towardsdatascience.com/how-to-effectively-define-and-validate-use-cases-932c284837fe?source=collection_archive---------19-----------------------
大多数数据专业人员努力定义转化为数据科学的用例& AI/ML 解决方案带来真正的价值
来源:链接
你可能想知道为什么?
理论上,提出想法、收集反馈和原型以获得演示和验证概念应该很简单。
然而,在现实中,大多数数据科学和机器学习专业人员在该过程的每一步都失败了,结果是交付的解决方案很少达到生产阶段或发布后,并且没有任何价值(没有增加生产力、收入或根本没有娱乐性)。
每 10 个数据科学项目中只有一个能够真正投入生产。 ( 来源 )
有人可能会说,数据科学和机器学习项目只是研究性质的,因此很明显,它们中的大多数将会失败。
当然这是真的,但是如何构建用例定义和验证的过程以减少时间和成本并增加成功率呢?建立一个原型通常是一项重大的投资,需要努力和时间,其中一些需要几个月的时间……船上有一大群 ML 工程师。
此外,由于新冠肺炎限制的存在,一些组织在远程协作和生产力方面举步维艰(尽管一些组织被证明比以前更加有效!).
作者图片
毫无疑问,这里没有金科玉律,不同的公司有不同的流程。然而,本文旨在为数据科学和 ML 专业人员提供指导和技术,帮助他们在障碍之间导航,并使他们能够推出满足用户期望并为公司带来好处(收入、效率、敏捷性)的生产解决方案。
无论用例验证的过程是如何构建的,它都将包含以下两个主要阶段:
● 构思 —用例定义和原型制作准备
● 验证 —建造原型并测量结果
如何定义一个用例?
用例是对如何应用人工智能/人工智能解决特定问题的描述/机会。
一切都始于一个想法,这种想法可能来自不同的来源,有时甚至是不寻常的。也许一位副总裁在 LinkedIn 上看到一篇帖子并受到启发,一位数据科学家可能读过一篇有趣的论文,或者一位 ML 工程师偶然发现了一种新算法并想探索它的潜力。
用例通常来自产品管理、UX 团队或硬件团队,他们刚刚制作了新传感器的原型,或者希望为产品带来令人惊叹的新功能。
上面的每个例子都可能产生有趣的用例,但同时也可能只会导致壮观而昂贵的失败。例如,一个常见的错误是将冷静、复杂的深度学习算法(需要大量不可用的数据)应用于每个问题,即使是那些可以通过启发式或简单的“传统”模型成功解决的问题。
好,怎么开始?
投资创意&研究!
最好的开始方式是组织一次跨团队头脑风暴会议,不仅包括您的数据科学/机器学习团队,还包括来自产品管理、用户体验、硬件等团队的其他利益相关者,以及任何其他可能对用例定义和后续验证做出贡献的人。
这种不同观点+创造力的融合是成功的关键!
数据科学是关于创造力和从数据字节中构建有意义的解决方案,让我们的世界变得更美好!
来源:链接
通过发送有趣的用例示例(论文、视频等),可以激发创造力。)在会前发给所涉缔约方。
通过研究竞争对手及其产品、其他行业的使用案例以及适用的研究论文来促进研究。
当前的疫情和远程协作需求也是一个挑战。务必注重适当的引导,并为所有参与者提供充分的机会来分享他们的想法并提供反馈。
列出会议期间出现的所有想法。选择 10 个左右最有趣的用例,让团队使用以下问题列表检查每个用例,以确定用例的优先级,并选择最有希望进行原型制作的用例:
- 问题 —如何用数据科学和机器学习解决?
- 影响 —用户将如何从建议的解决方案中受益?
- 价值/利益 —有形&无形;成本降低、有效性、敏捷性或其他?
- 创新 —这个想法有多独特/新颖?涉及多少研究?有类似的吗?任何组件都可以重复使用吗?
- 数据 —数据是否可用,或者是否需要为原型制作生成/收集数据?
- 验证 —验证有多容易?
- 复杂性 —构建一个解决方案有多困难,需要多长时间才能为用户发布解决方案?
此时,没有必要关心答案的绝对准确性,因为它们只是支持用例优先级的粗略估计。上面的列表只是重要问题的一个例子,当然可以根据你的具体需求进行调整/扩展。
然而,保持简短。尽可能应用预定义的答案。这样的答案可以进一步用于应用权重和实现评分算法。
上述练习的最终结果应该是为下一阶段列出的三个用例。
来源:链接
从有形的商业利益、对用户的影响和上市时间方面选择最有希望的一个(将首先制作原型)来进行简化的可行性研究。
结果应该是一个简短的总结,概述下一阶段(验证)的工作范围,至少包括以下 6 个方面:1)目标,2)商业机会,3)技术,4)验证方法,5)数据,6)团队,7)进度,8)风险。
如何验证一个用例?
答案是快速成型。
不要在概念验证上花费时间,因为你的主要目标不应该是从技术角度验证构建一个解决方案是否可行。答案永远是肯定的(好吧,几乎总是…)。在大多数合理的情况下,这归结为数据可用性和选择正确算法的问题。
然而,你的验证目标不仅仅是技术可行性,更重要的是构建一个原型来评估产品化解决方案的潜在影响、有用性和好处。此外,评估与开发最终解决方案相关的工作、资源、时间表和风险。
来源:链接
我个人对快速原型的一些建议:
- 明确定义并获得团队对目标、范围、产出和验证标准的理解!
- 在每周冲刺中组织工作(最多 4-5 个,更长可能导致范围蔓延和失败)。
- 逐步构建原型,从基本模型(甚至启发式)开始,然后通过额外的改进来增强,切换到更高级的方法。
- 小型敏捷跨职能团队(1-2 名数据科学家,1-2 名 SME,+领导)。将许多 ML 工程师(一种常见的做法)分配给同一个用例是走向失败的路线图。
- 包括能够验证用例(UX/硬件/产品管理或其他)的中小型企业。
- 寻找最简单的方法,神经网络需要大量你可能没有的数据,并且通常使用经典算法可以获得相同的结果,甚至简单的线性回归或统计模型和试探法的组合。
- 尝试不同的算法 —不要拘泥于一种,针对同一问题尝试其他算法来评估性能。
- 投入时间进行研究 —重用可用的架构、模型和软件包。
- 确保数据质量并应用必要的数据清理。
- 确定您的主要利益相关方并确保持续沟通。
在分布式团队的情况下,特别是考虑到当前的疫情限制,协作可能是困难的,因为快速原型在并置的团队中执行是最有效的。然而,有许多不同的技术和技巧可以应用,从任务管理工具、看板板,到通过视频和即席消息来赶上进度。我不会在这里推广任何特定的工具,因为每个公司都使用他们自己的一套工具,可以有效地应用于预期的目的。
验证,最重要的部分!
来源:链接
显然,我们的目标不是验证模型(这仍然很重要),而是确保构建的原型/演示符合我们定义的用例,有可能对用户产生影响,并且能够产生切实的商业价值。
在这一阶段,您应该在项目开始之前,根据您与团队和利益相关者定义的定量和定性成功标准来验证原型。
量化标准可以是模型必须达到的误差阈值(MSE、召回或任何其他相关的)。它也可以是与模型或原型的性能相关的不同度量的组合。
这部分很容易。
最具挑战性的部分是定性的,在这里你无法衡量一些方面,比如原型可能为用户带来的价值和好处。当然,你可以运行一个焦点小组或者可用性研究,但是,这样的技术需要时间和大量的成本投入。因此,让他们进入下一阶段,暂时依靠您的中小企业——UX 和产品管理的专业知识。也让你公司的其他团队参与进来,分享原型并收集反馈。
然而,请记住——归根结底,这一切都是为了钱……
如果你想让你的商业利益相关者相信你的演示是有价值的,并且可能带来财务利润,你应该进行成本效益分析。首先列出所有直接的、间接的以及无形的成本和收益,包括那些与绩效提高和客户满意度相关的成本和收益。对所有头寸进行货币计量、汇总和比较。如果你很难展示收益,那就和你的团队一起确定并量化它们。
我应该什么时候开始验证?
答案是——一旦你开始快速成型。这应该是一个持续的过程,目的是验证用例的有用性。
在快速原型制作过程中,将结果传达给利益相关者,以获得他们的认同和对后续步骤的同意。这可以是一个简短的周会和/或每日更新的形式。
不管验证的结果如何,总结发现。
摘要可以是文档或演示文稿,不仅应该包括结果,还应该包括与产品化相关的方面,例如在进入下一阶段和开发解决方案时需要考虑的已确定的问题和风险。
当项目由于在特定时间缺乏能力或其他公司优先事项而被搁置时,摘要文档也是有用的。这样的总结可以作为一个很好的起点,甚至对于其他考虑开发的类似用例也是如此。
如果验证后的特定用例没有计划进一步的开发,回顾你的积压工作,挑选下一个并再次启动原型。
来源:链接
最终,你将永远不会达到你所有的用例都通过验证并被安排产品化的地步。
坦率地说,你不应该指望他们。为什么?
因为原型设计和验证是研究的一部分,旨在确保只有最有希望的用例被转化为解决方案,并避免失败。
希望这篇文章能为你提供一些经过验证的技巧和指导,告诉你如何构建你的用例定义、原型和验证过程,从而最大化你的成功率。但一如既往,如何在自己的公司内组织和应用这些建议的指导方针,并将其嵌入到已经到位的流程和工具中,这取决于您。
祝你成功!🙂
感谢阅读。请随时联系 LinkedIn 或发表评论。
如果你管理或想要建立一个数据科学或 AI/ML 团队,你可能会发现我的另一篇文章很有趣:
[## 我如何建立一个数据科学实验室并休假
了解如何有效地开发数据科学单元并避免常见陷阱
towardsdatascience.com](/how-to-build-data-science-unit-f84ee3de63f5)
如何有效地学习和掌握 Python,用于数据科学、人工智能或机器学习。
原文:https://towardsdatascience.com/how-to-effectively-learn-and-master-python-for-data-science-artificial-intelligence-or-machine-8d88a4fb03a3?source=collection_archive---------22-----------------------
学习如何重新编码或学习一门新的编程语言可能会非常困难。大多数情况下,我们发现这是因为我们学习的方法不对。
丹尼斯·简斯在 Unsplash 拍摄的照片
如果你正在读这篇文章,那可能是因为你已经迈出了大胆的一步,在数据科学、人工智能或 ML 的众多选择中学习 python。我不会用冗长的演讲来烦你,比如 python 是什么,为什么对于任何想涉足数据科学、人工智能或机器学习领域的人来说,python 是一种很好的语言选择。相反,我将与您分享一些技巧,告诉您如何有效地学习 python 编程语言,踏上精通这门语言的旅程。
Python 是一门真正奇妙的语言。当有人想出一个好主意时,只需要 1 分钟和 5 行代码就可以完成你想要的事情。然后只需要一个小时就可以将脚本扩展到 300 行,之后它仍然几乎做你想做的事情。—杰克·詹森
保持一致
无论你用什么方法或途径学习 python,都要坚持下去。学习,总的来说,没有一个公式。这就是说,许多人可以通过许多不同的方式学习一些东西,并且仍然可以实现他们的目标。然而,找到适合自己的方法取决于每个人。建立一个学习计划。这个计划不能一概而论。你的学习计划应该考虑到你的工作、学校和健康计划。不要对自己太严格。当这一切都完成后,一定要坚持你的学习计划。养成学习的习惯,热爱你所学的东西。通过这样做,你会对你所学的东西产生渴望,并且每天都期待着学习。
写下你学到的东西
写笔记是学习 python 和任何其他编程语言的一个极好的方法。当我们从书本、讲座或辅导视频中学习时,我们不能把所有的东西都记在脑子里。我们必须对重要的观点和话题做笔记,这样我们就可以试着在我们所写的观点上更进一步。通过写笔记,我们可以通过阅读我们写在笔记上的几行来尝试重现我们所学的内容。这对记忆概念和原则以及训练我们的大脑记住我们所学的重要东西非常有帮助。你也可以养成写博客的习惯,在博客上你可以和世界上的其他人分享你的进步,以帮助激励代码新手。写作很有趣,从一个尝试写作并且不想停下来的程序员身上可以看出这一点😄,你可以学习专业写作或只是作为一种爱好,仅仅写你喜欢做的事情就能赚很多钱。
享受乐趣,尝试尝试
让你所学的东西变得有趣和愉快。Python 是一门非常有趣的语言,因此,在学习这门语言的时候,尽你所能享受其中的乐趣。你可以通过写一些关于你所学主题的小脚本来做到这一点。你可以建立迷你项目,这样你就可以实际了解你学到了什么。对代码做大量的实验,找到新的做事方法,如果你找到了使事情变得更简单或修复 bug 的方法,就贡献给你使用的公共库和包。你可以和志同道合的人一起编写你的包或库。
Python 是可执行的伪代码。—布鲁斯·埃凯尔
休息,不要把自己累坏了
编码会变得非常上瘾,个人需要知道什么时候休息。你必须知道什么时候休息,这样你才不会筋疲力尽。倦怠并不是与长时间或过度编码相关的唯一问题,还有严重的健康风险。因此,你需要经常休息。放松,呼吸新鲜空气,偶尔散散步,照顾好自己——看起来整洁健康。不要剥夺自己的休息时间,以至于你看起来像电影中典型的程序员的刻板形象,看起来不修边幅,病怏怏的,脸色苍白。作为程序员要学会把自己,自己的身心健康放在一切之上。
给自己找个搭档
有一个一起学习如何编码的伙伴是非常有趣的,你们可以从对方身上学到很多东西。个人编写代码的方式是独一无二的,通过成对编程,你可以学习编写代码或做其他你不知道的事情的方法。你们可以分享新的资源,举行模拟面试来锻炼自己,甚至一起向专业人士寻求指导。有一个伙伴有助于填补孤独的空虚感,这种空虚感在那些一天花很多时间独自写代码,没有人可以聊天或放松或做其他事情的人身上很常见。
斯科特·格雷厄姆在 Unsplash 上拍照
编写 Python 代码的乐趣应该在于看到短小、简洁、易读的类,这些类用少量清晰的代码表达了大量的动作,而不是大量让读者厌烦得要死的琐碎代码。
—吉多·范·罗苏姆
我相信我在这篇文章中分享的一切对寻求进入该领域的初学者和学习进展不顺的中级程序员都有帮助。这些技巧是我从业内专业人士那里学到的,比如德里克·德贝杜伊
我已经策划了几本书来帮助你学习和欣赏 python 编程语言,理解一般编程的核心原理,学习数据科学、人工智能和 ML,享受😀
感谢您抽出时间阅读这个故事。我希望你学到了一些东西,这对你有所帮助。欢迎您在回复部分分享您的想法和观点,您可以直接在 Twitter 或 LinkedIn 上联系我。黑客快乐!
非常感谢 安娜·阿依库 为我校对并纠正我写这篇文章时犯的许多错误。
如何有效预测 Python 中的不平衡类
原文:https://towardsdatascience.com/how-to-effectively-predict-imbalanced-classes-in-python-e8cd3b5720c4?source=collection_archive---------5-----------------------
处理不平衡机器学习分类问题所需的所有细节
图片由 Eneida Nieves 在 Unsplash 拍摄
奇怪的是,我花在分类问题上的时间比花在回归问题上的时间要多得多。幸运的是,我经常处理不平衡的数据集。也许这是因为我的日常工作包括预测和分析信用风险、违约概率和其他欺诈风险!
在通常的情况下,一个人经常遇到付款违约、付款延迟和欺诈事件是不常见的。这就是说,与按时付款或正常的非欺诈活动相比,这类事件的比例通常很低。
这是不平衡数据集的一个非常简单的说明,其中一组(或一类)活动(如违约付款)在样本中的活动(如违约和正常付款)总数中所占的比例非常低。
现在,让我们看看为什么我们在面对不平衡的分类问题时需要小心,以及如何处理这些问题。该员额的其余部分结构如下:
- 介绍
- 模型评估指标
- 成本敏感学习
- 取样方法
介绍
当处理不平衡分类问题时,我们通常更关心正确预测少数类别(也称为肯定类别),例如欺诈事件、支付违约、垃圾邮件等。换句话说,与误报(例如,将正常电子邮件分类为垃圾邮件)相比,减少误报(例如,将欺诈性交易分类为非欺诈性交易)的数量对我们来说更加重要。
直觉上,给定较小的样本大小和偏斜的类分布,ML 模型正确地学习少数类的所有特征要困难得多。一个简单的模型可以通过简单地预测所有情况下的多数类来获得合理的准确性。
模型评估指标
评估指标只是评估特定模型在做出正确预测方面的效率和准确性。对于分类问题,评估度量将模型预测的类别标签(或其概率)与实际的类别标签进行比较,并给出预测的准确性。有几个标准评估指标在平衡的分类问题(例如,准确性)上工作得非常好,但是在倾斜的数据集上却失败得很惨。
因此,我们应该利用某些更适合不平衡分类问题的特定度量。
在继续之前,让我们回顾一下由 Cesar Ferri 等人分类的各种类型的评估指标:
- 阈值度量,基于对误差的阈值或定性理解:准确度、灵敏度/召回率、特异性、精确度、 F 值、灵敏度和特异性的几何平均值 Kappa 统计量。
- 分级标准基于模型对类别(可分离性的概念)的分级程度:在接收器操作特性曲线下的面积( AUROC )和在精度-召回曲线下的面积(PR AUC)。
- 概率度量测量与真实类别概率的偏差: LogLoss 和 Brier Score 。请注意,在使用这些指标之前,需要校准预测的概率。
准确性悖论
尽管它是分类问题中使用最广泛、最容易解释的度量标准,但请不要犯在不平衡数据集的情况下使用准确性度量标准来评估您的分类模型的新手错误。
精度计算如下:
或者,就混淆矩阵而言:
考虑一个具有 1:100 类不平衡的高度偏斜数据集-对于少数类(正)的每个实例,有 100 个多数类(负)的样本。一个简单的分类器(或者,甚至一个人)可以通过对每个测试样本默认预测多数类来实现 99%的预测准确性,而不需要任何实际的机器学习。然而,这并没有描绘真实的画面,因为可能正确预测少数类在上下文中更重要,例如在欺诈检测或垃圾邮件过滤算法中。
不平衡分类问题的评价指标
好的,那么我们应该用什么度量来评估我们的分类器呢?现在让我们来看一些适合不平衡分类的度量标准。
精度
精度是真阳性与分类器预测的总阳性的比率。请记住,在不平衡分类问题的背景下,阳性是指少数类。根据混淆矩阵计算如下:
精度值介于 0 和 1 之间。由于 Precision 本身不涉及假阴性,并且旨在最小化假阳性的数量,因此 Precision 并不真正代表我们也涉及最小化假阴性的全部情况(例如,预测交易为非欺诈性的,而实际上它是欺诈性的)。
Scikit-learn 的[precision_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_score.html)
函数计算二元和多类分类问题的精度:
from sklearn.metrics import precision_score# calculate precision for binary classification problem
precision = precision_score(y_true, y_pred, average='binary')# calculate precision for multi-class classification problem
precision = precision_score(y_true, y_pred, labels=[1,2], average='micro')
# labels is a list of all possible class labels
召回
召回率也称为敏感度和真阳性率(TPR),是样本中真阳性与真实阳性的比率。与 Precision 不同,Recall 还考虑了未被归类为阳性(少数)病例的数量。根据混淆矩阵计算如下:
召回值范围在 0 和 1 之间。召回与误报的数量无关,而是旨在最小化误报的数量。
Scikit-learn 的[recall_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.recall_score.html)
函数以与precision_score
完全相同的方式计算二元和多类分类问题的召回率。
F 分数
当我们更关心最小化假阳性时,精确度是合适的,而当假阴性的数量更关键时,召回是合适的。
但是,如果我们想同时最大化精确度和召回率,以最小的假阳性和假阴性准确地预测阳性类别呢?例如,在欺诈检测算法中,我们希望准确预测所有欺诈案例,同时不将非欺诈案例预测为欺诈案例。同时最大化精确度和召回率是一个很好的平衡行为,这就是 F 值的作用。
F-Score 提供了一个衡量精确度和召回率的单一分数。因此,最大化 F-Score 将意味着我们将最大化精确度和召回率。F-Score 是精度和召回率的简单调和平均值,并且广泛用于不平衡分类问题。
同样,F 值介于 0 和 1 之间。就像 Precision 和 Recall 一样,scikit-learn 的[f1_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html)
函数以完全相同的方式和语法计算二进制和多类问题的 F 分数。
受试者工作特性曲线下面积(AUROC)
ROC 曲线在 x 轴上绘制二元分类器的假阳性率(FPR ),在 y 轴上绘制真阳性率(TPR,召回),所有可能的概率阈值在 0 和 1 之间。TPR 计算如下:
任何分类器的默认概率阈值通常为 0.5,也就是说,如果样本的预测概率大于 0.5,则将该样本分类为属于阳性类别。然而,这个默认的假设不应该用于不平衡的数据集,稍后会有更多的介绍。
完美的分类器应该能够将 TPR 最大化为 1,将 FPR 最小化为 0,因此完美的分类器将在 ROC 曲线的左上象限(坐标 0,1)中一样高。ROC 并不特别偏向多数或少数类,因此,它是平衡和不平衡分类问题的普遍选择。
比较两个分类器的一种简便方法是计算 ROC 曲线下的面积 AUROC,它给出了一个分类器在所有概率阈值上的单一得分。AUROC 的范围在 0 到 1 之间,1 是一个非常熟练的分类器的分数。
使用 scikit-learn 的[roc_curve](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_curve.html)
和[roc_auc_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_auc_score.html)
函数绘制 ROC 曲线和计算 AUROC 的完整示例如下:
输出将类似于这样:
针对不平衡分类的 ROC 阈值移动
如上所述,在不平衡分类问题的情况下,使用默认概率阈值 0.5 来预测类别标签将可能导致较差的模型性能。幸运的是,在 ROC 曲线的情况下,确定最佳概率阈值非常简单。直观上,这个最佳阈值最接近 ROC 曲线的左上角,并且可以使用 Youden 的 J 统计很容易地确定。
为由roc_curve
返回的每个阈值计算 J 统计,最大的 J 值是最佳阈值。最简单的 J 统计量计算公式为:
一旦我们调用了roc_curve
函数,使用 J 统计量确定最佳阈值就非常简单了:
#import the required library
from numpy import argmax# calculate inputs for the roc curve
fpr, tpr, thresholds = roc_curve(test_y, yhat_positive)# get the best threshold
J = tpr - fpr
ix = argmax(J)
best_thresh = thresholds[ix]
print('Best Threshold: %f' % (best_thresh))
所有预测概率(yhat
)大于该阈值的样本应被分配到阳性类别。
精确召回曲线下面积(PR AUC)
对于所有可能的概率阈值,PR 曲线在 x 轴上绘制召回,在 y 轴上绘制精度。与 ROC 曲线相反,一个非常熟练的模型向坐标为(1,1)的右上轴弯曲。由于精度和召回率都与真阳性(少数类)有关,这使得它成为不平衡分类问题的有效工具。
比较两个分类器的一种简便方法是计算 PR 曲线下的面积 PR AUC,它给出了一个分类器在所有概率阈值上的单一得分。PR AUC 的范围在 0 和 1 之间,1 是一个完全熟练的分类器的分数。
使用 scikit-learn 的[precision_recall_curve](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_recall_curve.html)
和[auc](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.auc.html)
函数绘制 PR 曲线和计算 PR AUC 的完整示例如下:
输出将类似于这样:
不平衡分类的 PR 曲线阈值移动
类似于 ROC 曲线,在 PR 曲线的情况下,确定最佳概率阈值是足够简单的。直观地说,这个最佳阈值最接近 PR 曲线的右上角,可以使用 F 值轻松确定。
一旦我们调用了precision_recall_curve
函数,使用 F 值的最佳阈值确定如下:
#import the required library
from numpy import argmax# calculate inputs for the roc curve
precision, recall, thresholds = precision_recall_curve(test_y, yhat_positive)# Calculate F-Scores and find the index of ideal score
fscore = (2 * precision * recall) / (precision + recall)
ix = argmax(fscore)
best_thresh = thresholds[ix]
print('Best Threshold: %f' % (best_thresh))
预测概率(yhat
)大于该阈值的所有样本应被分配到阳性类别。
日志损失分数
Log Loss Score 是一种基于概率的评估指标,与预测的分类标签无关。相反,它用于评估预测的校准的概率。一些模型预测校准概率作为训练过程的一部分(例如,逻辑回归),
但是许多模型不预测,并且在使用 LogLoss 或 Brier 分数之前需要校准(例如,支持向量机、决策树和神经网络)。使用 scikit-learn 的[CalibratedClassifierCV](https://scikit-learn.org/stable/modules/generated/sklearn.calibration.CalibratedClassifierCV.html)
类可以很容易地校准概率。
可能的最佳对数损失分数为 0,范围从 0 到无穷大,分数越高越差。它被定义为基于地面真实类别标签(y
)预测概率(yhat
)的分类器的负对数似然性:
Scikit-learn 的[log_loss](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.log_loss.html)
函数使我们在获得如下预测类概率后计算对数损失分数变得容易:
from sklearn.metrics import log_loss# fit a model
model = LogisticRegression()
model.fit(train_X, train_y)# predict probabilities
yhat = model.predict_proba(test_X)# calculate and print Log Loss Score
logloss = log_loss(test_y, yhat)
print('Log Loss Score: %.3f' % (logloss))
欧石南得分
以 Glenn Brier 命名的 Brier Score 计算预测概率和它们各自的正类值之间的均方误差。Brier Score 通常仅适用于二元分类问题,并评估阳性类别的概率。Brier 和 Log Loss 得分之间的关键区别在于 Brier 得分中只考虑了阳性类别的预测概率。
与对数损失分数相反,Brier 分数的范围在 0 到 1 之间,0 是一个非常熟练的分类器的分数。其计算如下,其中yhat
是正类的预测概率,而y
是正类的基本事实标签:
Scikit-learn 的[brier_score_loss](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.brier_score_loss.html)
函数使得一旦我们有了如下预测的正类概率,就可以很容易地计算 Brier 分数:
from sklearn.metrics import brier_score_loss# fit a model
model = LogisticRegression()
model.fit(train_X, train_y)# predict probabilities
yhat = model.predict_proba(test_X)
# retrieve the probabilities for the positive class
yhat_positive = yhat[:, 1]# calculate and print Brier Score
brier = brier_score_loss(test_y, yhat_positive)
print('Brier Score: %.3f' % (brier))
不平衡数据集的交叉验证
k 倍 交叉验证技术在评估平衡甚至轻微偏斜数据集的分类器时非常高效和有效。然而,它在不平衡数据集的情况下失败,因为训练数据通常被分成假设均匀概率分布的折叠。在不平衡数据的情况下,这有可能导致某些折叠完全遗漏在阳性(少数)类别中,或者只有很少的样本。因此,这很可能导致误导性的模型评估。
一种改进的 k-fold 交叉验证,称为分层 k-fold 交叉验证,更适合不平衡分类问题。分层 k-fold 或重复分层 k-fold 保留了每个 fold 中不平衡的类分布。这些 k 倍技术中的任何一种都可以与[cross_val_score](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.cross_val_score.html)
结合使用来预测和评估每个折叠。前面解释的所有评估指标都可以用作cross_val_score
中的scoring
参数。在此参考完整列表。成本敏感学习一节稍后将提供实际演示。
成本敏感学习
在不平衡分类问题的情况下,分类器的误分类错误的感知成本通常是不同的。也就是说,缺失一个正(少数)类的代价通常比负(多数)类的错误分类更关键。换句话说,假阴性比假阳性更关键。
例如,拒绝给一个好客户贷款,并不像给一个可能永远不会还款的坏客户贷款那样糟糕。或者,诊断一个健康的癌症患者并进行更多的医学测试比让一个实际患有癌症的患者出院更好。
成本敏感性学习是 ML 的一个子领域,它考虑了各种错误的成本(包括误分类成本),同时在模型训练期间最小化模型误差。
用于不平衡分类的成本敏感学习集中于首先将不同的成本分配给可能产生的错误分类错误的类型,然后使用专门的方法将这些成本考虑在内。
但是如何将这些成本分配给错误分类,具体来说,是误报和漏报?真阳性和真阴性通常被赋予零成本。由于假阴性通常更重要,假阴性比假阳性的成本更高。在某些情况下,领域知识可以帮助我们。在保险索赔场景中,误报的成本可能是客户跟踪的潜在货币成本,而误报的成本可能是潜在的保险索赔成本。
然而,在所有情况下,分配错误分类成本可能并不简单。在这种情况下,一个有效的起点是将类别分布比率的倒数分配给假阳性和假阴性。例如,如果我们有一个 1:100 类平衡的数据集,假阴性的成本为 100,而假阳性的成本为 1。这是假设在现实生活中进行预测时,相同的类别分布也将成立。
现在,让我们通过某些 ML 模型,看看这种成本敏感的学习可以被纳入其中。
成本敏感的逻辑回归
Scikit-learns 的标准逻辑回归模型可通过class_weight
参数轻松修改,以考虑阶级不平衡。该参数对于来自多数类的示例中出现的错误对模型的惩罚较小,而对于来自少数类的示例中出现的错误对模型的惩罚较大。
class_weight
参数包含所有可能的分类标签及其相关权重/成本的字典,以便在模型拟合过程中加以考虑。同样,这些类权重可以由领域专家通过网格搜索、行业最佳实践或使用前面解释的类分布的逆来确定。
上面最后一个使用逆类分布作为权重的选项是通过将balanced
作为输入传递给class_weight
参数来指定的,而不是手动计算分布。
使用类别加权逻辑回归模型和使用重复分层 k 倍进行评估的完整示例如下:
成本敏感决策树
通过在确定每个节点的分裂点时考虑每个类别的重要性,在决策树中考虑类别不平衡。
就像逻辑回归一样,scikit-learn 的DecisionTreeClassifier
类有一个class_weight
参数,其功能与逻辑回归中的完全一样。
使用类别加权决策树并使用重复分层 k-fold 对其进行评估的完整示例如下:
对成本敏感的 XGBoost
XGBoost 是多个决策树的集合,是随机梯度推进的高效实现。它被广泛用于分类和回归问题,并被发现在几个具有挑战性的机器学习问题中非常有效。
[XGBoostClassifier](https://xgboost.readthedocs.io/en/latest/python/python_api.html#xgboost.XGBClassifier)
的scale_pos_weight
参数用于训练不平衡数据的类加权 XGBoost 分类器。XGBoost 的文档提供了一种估算scale_pos_weight
理想值的便捷方法,如下所示:
使用类加权 XGBoostClassifier 并使用重复分层 k-fold 对其进行评估的完整示例如下:
取样方法
一般来说,我不太喜欢使用各种过采样和欠采样方法来处理训练数据集中的类不平衡。我倾向于在尝试以下任何一种采样方法来纠正类别不平衡之前,对成本敏感的 ML 算法使用适当的评估指标。
首先,让我们确定三种主要类型的抽样方法来补救类别不平衡:
- 过采样包括复制或合成来自少数类的新样本
- 欠采样包括从多数类中删除或只选择一个样本
- 综合方法结合了过采样和欠采样
我通常不喜欢抽样方法而不喜欢成本敏感学习的原因:
- 然而,过采样情况下的潜在过拟合,后面解释的一些高级技术试图解决这个问题
- 采样不足导致有用数据丢失
- 过采样后学习和处理时间增加
如果你决定采用抽样方法,那么在实施时要非常小心。应该仅对训练数据集执行采样。它不会在整个数据集、维持集或验证数据集上执行。原因在于,其目的不是从数据中消除类别偏差,而是继续评估生产中真实和预期的数据的结果模型,以及实际现实问题的代表。
过采样方法
现在,让我们简要了解一些主要的过采样方法。请注意,我不会讨论随机过采样技术([RandomOverSampler](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.over_sampling.RandomOverSampler.html#imblearn-over-sampling-randomoversampler)
),因为我认为它更容易过拟合。
合成少数过采样技术(SMOTE)
SMOTE 合成来自阳性(少数)类的新数据样本,没有随机复制,并由 Nitesh Chawla 等人在其 2002 年的论文中介绍。来自该论文:“通过获取每个少数类样本并沿着连接任意/所有 k 个少数类最近邻居的线段引入合成样本,对少数类进行过采样。”。
Python 的不平衡学习库包含了 SMOTE 的一个实现,这个实现的类名副其实:[SMOTE](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.over_sampling.SMOTE.html?#imblearn-over-sampling-smote)
(以及这里描述的许多其他采样方法)。与 scikit-learn 中的任何其他数据转换对象一样,实现了SMOTE
类:它必须被定义和配置,适合数据集,然后被应用来创建数据集的新转换版本。
边界线-SMOTE
韩晖等人在 2005 年提出的边界 SMOTE 是对 SMOTE 的扩展,它使用 k 近邻算法识别并合成少数类的边界实例。imblearn
库的类实现了类似于 SMOTE 的边界 SMOTE。
濒临崩溃的 SVM
边界线-SMOTE SVM 与边界线-SMOTE 相同,但用于识别边界线情况的技术不同,其中使用 SVM 算法而不是 KNN 算法来识别错误分类的边界线情况。这是由 Hien Nguyen 等人在 2011 年的 paper⁴.中提出的imblearn
库的类实现了类似于 SMOTE 的边界 SMOTE SVM。
自适应合成采样(ADASYN)
ADASYN 是由 al.⁵的何海波等人在他们 2008 年的论文中提出的。来自该论文:“ADASYN 基于根据分布自适应地生成少数数据样本的思想:与那些更容易学习的少数样本相比,为更难学习的少数类样本生成更多的合成数据。”。imblearn
库的[ADASYN](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.over_sampling.ADASYN.html#imblearn-over-sampling-adasyn)
类实现了类似于 SMOTE 的 ADASYN。
实际演示
下面是使用RepeatedStratifiedKFold
的Pipeline
中的DecisionTreeClassifier
使用上述四种过采样技术的完整实践演示(注意,这些类别的某些参数可以调整):
欠采样方法
现在,让我们简要了解一些主要的欠采样方法。注意,我不会讨论随机欠采样([RandomUnderSampler](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.under_sampling.RandomUnderSampler.html#imblearn-under-sampling-randomundersampler)
)技术,因为我认为它更有可能导致有用数据的丢失。
欠采样未遂
接近失败指的是三种欠采样方法的集合,这些方法基于多数类实例和少数类实例之间的距离来选择样本。这些方法是由张建平和因德吉特·马尼在他们 2003 年的 paper⁶.中提出的这三种方法是:
- NearMiss-1 仅对那些与预定数量的最近少数类实例具有最小平均距离的多数类实例进行欠采样
- NearMiss-2 仅对那些与预定数量的最远少数类实例具有最小平均距离的多数类实例进行欠采样
- NearMiss-3 仅对那些与每个少数类实例具有最小距离的多数类实例进行欠采样
imblearn
库的[NearMiss](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.under_sampling.NearMiss.html#imblearn-under-sampling-nearmiss)
类实现了与 SMOTE 相似的 NearMiss 的所有三个版本。
其他欠采样方法
下面的imblearn
库中包含了其他几种欠采样方法,它们以类似的方式实现:
- 浓缩近邻 Rule⁷ —
[CondensedNearestNeighbour](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.under_sampling.CondensedNearestNeighbour.html#imblearn-under-sampling-condensednearestneighbour)
- CNN⁸的两次修改—
[TomekLinks](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.under_sampling.TomekLinks.html#imblearn-under-sampling-tomeklinks)
- 一面倒的 Selection⁹ —
[OneSidedSelection](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.under_sampling.OneSidedSelection.html#imblearn-under-sampling-onesidedselection)
- 已编辑最近邻⁰ —
[EditedNearestNeighbors](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.under_sampling.EditedNearestNeighbours.html#imblearn-under-sampling-editednearestneighbours)
- 邻域清理规则—
[NeighborhoodCleaningRule](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.under_sampling.NeighbourhoodCleaningRule.html#imblearn-under-sampling-neighbourhoodcleaningrule)
合成方法
有时将过采样和欠采样方法结合起来会更有效。就像上面用一个Pipeline
演示 SMOTE 一样,类似的流水线也可以用来创建一个多采样方法序列,最后用一个分类器。然后,该管道与RepeatedStratifiedKFold
和cross_val_score
一起用于评估预测。
在流水线中结合 SMOTE 和随机过采样的简单示例如下:
# import required libraries
from imblearn.pipeline import Pipeline
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.tree import DecisionTreeClassifier# define model
model = DecisionTreeClassifier()# define pipeline
oversample = SMOTE(sampling_strategy=0.1)
undersample = RandomUnderSampler(sampling_strategy=0.5)
steps = [('o', oversample), ('u', undersample), ('m', model)]
pipeline = Pipeline(steps=steps)# define cross-validation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)# evaluate model
scores = cross_val_score(pipeline, X, y, scoring='roc_auc', cv=cv, n_jobs=-1)
然而,代替这些手动组合,imblearn
有如下几个标准的合成实现:
- SMOTE 和 Tomek 链接—
[SMOTETomek](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.combine.SMOTETomek.html#imblearn-combine-smotetomek)
# import required libraries
from imblearn.pipeline import Pipeline
from imblearn.combine import SMOTETomek
from imblearn.under_sampling import TomekLinks
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.tree import DecisionTreeClassifier# define model
model = DecisionTreeClassifier()# define sampling strategy
resample = SMOTETomek(tomek=TomekLinks(sampling_strategy='majority'))# define pipeline
pipeline = Pipeline(steps=[('r', resample), ('m', model)])# define cross-validation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)# evaluate model
scores = cross_val_score(pipeline, X, y, scoring='roc_auc', cv=cv, n_jobs=-1)
- SMOTE 和编辑最近邻—
[SMOTEENN](https://imbalanced-learn.readthedocs.io/en/stable/generated/imblearn.combine.SMOTEENN.html#imblearn-combine-smoteenn)
# import required libraries
from imblearn.pipeline import Pipeline
from imblearn.combine import SMOTEENN
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.tree import DecisionTreeClassifier# define model
model = DecisionTreeClassifier()# define pipeline
pipeline = Pipeline(steps=[('r', SMOTEENN()), ('m', model)])# define cross-validation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)# evaluate model
scores = cross_val_score(pipeline, X, y, scoring='roc_auc', cv=cv, n_jobs=-1)
结论
我希望上面关于不平衡数据集分类问题的讨论对你有用,就像对我一样。
欢迎联系 me 讨论任何与机器学习或数据和金融分析相关的问题。
继续学习!
参考
来自机器学习大师的杰森·布朗利博士的灵感和功劳,他在我的人工智能之旅中发挥了重要作用
[1] Ferri,c .,Hernández-Orallo,j .,& Modroiu,R. (2009 年)。分类性能测量的实验比较。模式识别。列特。, 30, 27–38.
[2]乔拉、鲍耶、霍尔和凯格尔迈耶(2002 年)。SMOTE:合成少数过采样技术。j .阿提夫。智能。已获授权(JAIR)。16.321–357.10.1613/杰尔 953
[3]韩,黄,王,魏。,&毛,BH。(2005) Borderline-SMOTE:不平衡数据集学习中的一种新的过采样方法。在:黄 DS。,张晓萍。,黄 GB。智能计算的进展。ICIC 2005。
[4] Nguyen,h .,Cooper,e .和 Kamei,K. (2011 年)。不平衡数据分类的边界过采样。国际知识工程和软数据范例杂志。3.4–21.10.1504/IJKESDP
[5]海波,杨,b,加西亚,E. A. &李,S. (2008)。“ADASYN:用于不平衡学习的自适应合成采样方法”,2008 年 IEEE 神经网络国际联合会议(IEEE 计算智能世界大会),香港,2008,第 1322–1328 页,doi:10.1109/ij CNN . 2008 . 20020386306
[6]张,j .和 Mani,I. (2003).不平衡数据分布的 KNN 方法:涉及信息提取的案例研究。ICML 2003 年不平衡数据集学习研讨会会议录。
[7] Hart,p .,“压缩最近邻规则”,载于《信息论》,IEEE 会刊,第 14 卷(3),第 515-516 页,1968 年。
[8] Tomek,I .,“CNN 的两次修改”,载于《系统、人和控制论》,IEEE 汇刊,第 6 卷,第 769-772 页,2010 年。
[9]m . Kubat 和 s . Matwin,“解决不平衡训练集的诅咒:片面选择”,载于《ICML》,第 97 卷,第 179-186 页,1997 年。
[10]Wilson d,“使用编辑数据的最近邻规则的渐近性质”,载于 IEEE 系统、人类和控制论汇刊,第 2 卷(3),第 408-421 页,1972 年。
[11] Laurikkala,j .,“通过平衡班级分布改进困难小班的识别”Springer Berlin Heidelberg,2001 年。
如何有效利用你的计算机视觉项目!
原文:https://towardsdatascience.com/how-to-effectively-utilize-your-computer-vision-projects-3a90439eb3b2?source=collection_archive---------46-----------------------
如何最好地利用你为计算机视觉构建的模型和项目,并举例说明以便更好地理解。
照片由思想目录在 Unsplash 上拍摄
计算机视觉是人工智能的一个领域,通过处理图像和图片来解决现实生活中的视觉问题。计算机识别、理解和识别数字图像或视频以自动化任务的能力是计算机视觉任务寻求成功完成和执行的主要目标。
构建计算机视觉项目是最有趣的体验之一。然而,你为计算机视觉建立的机器学习或深度学习模型需要精确地建立,并有效地用于产生更好的结果。
本文的主要目的是提供一个坚实的基础,告诉您如何使用 python 或您喜欢的任何编程语言提供的模块来有效地构建您的计算机视觉项目。以及如何在更小或更大的平台规模上有效地实现它们。
让我们从简单了解计算机视觉开始,然后继续了解如何构建这些模型,最后,我们如何才能最好地利用它们。
所以,事不宜迟,让我们开始吧!
对计算机视觉的简要理解:
照片由米米·蒂安在 Unsplash 上拍摄
人类识别周围的物体和环境没有问题。然而,对于计算机来说,识别和区分环境中的各种模式、视觉、图像和物体并不容易。
出现这种困难的原因是因为人脑和眼睛的解释能力不同于计算机,计算机解释大部分输出是 0 或 1,即二进制。
图像经常被转换成由红色、蓝色、绿色组成的三维阵列。它们的取值范围是从 0 到 255,使用这种传统的数组方法,我们可以编写代码来识别图像。
随着机器学习、深度学习和计算机视觉方面的技术进步,现代计算机视觉项目可以解决复杂的任务,如图像分割和分类、对象检测、人脸识别等等。
计算机视觉可能是人工智能中最有趣、最迷人的概念。计算机视觉是一个跨学科的领域,研究计算机或任何软件如何学习对周围环境可视化的高级理解。获得这个概念透视图后,自动化任务或执行所需的操作会很有用。
如何有效构建计算机视觉项目?
布鲁斯·马斯在 Unsplash 上的照片
对于每个特定的计算机视觉任务,可以相应地使用各种机器学习或深度学习算法来处理您手头的任务。
你可以通过支持向量机(SVMs)等机器学习算法的深度学习来执行人脸识别任务,或者通过深度学习和卷积神经网络构建一个模型来执行相同的任务。
试验和尝试各种模型和想法是为这些复杂任务获得合适结果的最佳方式。让我们以人类情感和手势识别项目为例来理解这一点。
这个项目使用计算机视觉和深度学习来检测各种面孔,并对特定面孔的情绪进行分类。这些模型不仅对情绪进行分类,而且还相应地对所识别的手指的不同手势进行检测和分类。
在区分人的情绪或姿势之后,由训练的模型分别提供对人的情绪或姿势的准确预测的声音响应。这个项目最好的部分是你可以选择的广泛的数据集。
关于这个项目的更多细节可以通过下面的链接获得。如需更详细的解释,请随时查看。
[## 使用深度学习的人类情感和手势检测器:第 1 部分
了解如何从零开始构建具有深度学习的人类情感和手势检测器。
towardsdatascience.com](/human-emotion-and-gesture-detector-using-deep-learning-part-1-d0023008d0eb)
你可以看到我设计了各种模型来寻找一个合适的例子来解决这个复杂的问题。只有用试凑法,你才能达到最好的结果。构建的项目可以有效区分各种情绪和手势。然而,它无论如何都不是完美的,仍然有很大的改进空间。
在下一节中,我们将了解在有效性和效率方面可以做出的改进。
你如何有效地利用你的计算机视觉模型和项目?
布鲁斯·马斯在 Unsplash 上的照片
任何计算机视觉项目的最重要的方面是有效地利用它们来高效地工作并产生结果,而不管它们正在执行的任务的质量和它们工作的设备。
训练后分析有时也称为事后分析,在模型优化中起着重要作用。构建和训练的业务模型需要优化,以便在低端设备和嵌入式系统(如 raspberry pi)上有效工作。
构建和评估模型的主要组件之一是检查模型的预测能力和性能质量。一个更重要的概念是理解你的机器学习或深度学习模型的局限性。
克服这些限制是成功模式的关键。在计算机视觉领域,特别是在执行实时和现实生活时,以更高的精度和准确度完成这些任务变得非常重要。
这方面的一个例子是使用深度学习和计算机视觉构建的人脸识别模型。查看下面的文章,了解从头开始实施类似项目的更多细节。
[## 智能面部锁定系统
建立高精度人脸识别模型
towardsdatascience.com](/smart-face-lock-system-6c5a77aa5d30)
让我们来了解一下,为了获得更有效的性能,可以分别对这个模型的实现进行哪些改进和修复。
- 可以使用一次性学习和训练方法来减少每个面部的训练时间。由于当前模型只识别一张脸,如果我们想添加更多的脸,我们需要重新训练整个模型。因此,需要考虑一次性学习等方法来提高模型的质量和性能。
- 可以找到 haarcascade _ frontal face _ default . XML 的替代方案来提高在任何特定角度检测面部的准确性。另一种方法是为正面和侧面创建一个定制的 XML 文件。
- 为了使其在嵌入式设备上运行,可以对内存约束进行更改,如转换为 tf.float(32 ),也可以通过考虑使用 tflite 对模型进行更改。
这个例子是为了让观众对完成复杂任务时可以持续不断地进行的巨大改进以及如何有效地利用计算机视觉项目有一个基本的了解。
由 Unsplash 上的 Karsten Winegeart 拍摄
结论:
就这样,我们来到了这篇文章的结尾。我希望这个指南对你们所有人有所帮助,帮助你们巩固基础知识,理解计算机视觉项目实施的重要方面。
理解事物的内部工作方式在计算机视觉中至关重要,因为这有助于你弄清楚计算机究竟是如何分析和处理数据的,以及欣赏其方法背后的美。
如果您有任何疑问、问题或与此相关的问题,请随时打电话给我,让我知道您不明白的地方。我会尽力给你解释,帮你从概念上解决。
看看我的其他一些文章,你可能会喜欢读!
[## 揭秘人工智能!
打破人工智能领域和它的未来。
towardsdatascience.com](/demystifying-artificial-intelligence-d2887879aaf1) [## 用代码和例子简化函数的 args 和 kwargs!
理解 python 编程和机器学习的args 和kwargs 的完整概念。
towardsdatascience.com](/simplifying-args-and-kwargs-for-functions-with-codes-and-examples-b785a289c2c2) [## 简单有趣的万圣节 Python 项目!
这是一个有趣的“不给糖就捣蛋”的游戏,让你在万圣节愉快地学习 python 编程
towardsdatascience.com](/simple-fun-python-project-for-halloween-ff93bbd072ad) [## 用代码和例子理解 Python 中的高级函数!
详细了解 python 中的匿名函数和高级函数及其实际应用…
towardsdatascience.com](/understanding-advanced-functions-in-python-with-codes-and-examples-2e68bbb04094)
谢谢你们坚持到最后。我希望你们都喜欢这篇文章。祝大家有美好的一天!
加快 PySpark 和 Pandas 数据帧之间的转换
原文:https://towardsdatascience.com/how-to-efficiently-convert-a-pyspark-dataframe-to-pandas-8bda2c3875c3?source=collection_archive---------8-----------------------
将大型 Spark 数据帧转换为熊猫时节省时间
诺亚·博加德在unsplash.com拍摄的照片
由于使用了toPandas()
方法,将 PySpark 数据帧转换成 Pandas 非常简单。然而,这可能是成本最高的操作之一,必须谨慎使用,尤其是在处理大量数据时。
为什么这么贵?
Pandas 数据帧存储在内存中,这意味着对它们的操作执行起来更快,然而,它们的大小受到单台机器内存的限制。
另一方面,Spark 数据帧分布在由至少一台机器组成的 Spark 集群的节点上,因此数据帧的大小受到集群大小的限制。当需要存储更多数据时,只需通过添加更多节点(和/或向节点添加更多内存)来扩展集群。
重要的是要理解,当在 Spark 数据帧上执行toPandas()
方法时,分布在集群的节点上的所有行将被收集到驱动程序中,该驱动程序需要有足够的内存来容纳数据。
用 PyArrow 加速转换
Apache Arrow 是一种独立于语言的内存列格式,当使用toPandas()
或createDataFrame()
时,可用于优化 Spark 和 Pandas 数据帧之间的转换。
首先,我们需要确保安装兼容的PyArrow
和pandas
版本。前者为 0.15.1 ,后者为 0.24.2 。最近的版本也可能兼容,但目前 Spark 不提供任何保证,所以这很大程度上取决于用户测试和验证兼容性。有关所需版本和兼容性的更多详细信息,请参考 Spark 的官方文档。
默认情况下,基于箭头的列数据传输是禁用的,因此我们必须稍微修改我们的配置,以便利用这种优化。为此,应启用spark.sql.execution.arrow.pyspark.enabled
。
import numpy as np
import pandas as pd
# Enable Arrow-based columnar data spark.conf.set("spark.sql.execution.arrow.pyspark.enabled", "true")# Create a dummy Spark DataFrame
test_sdf = spark.range(0, 1000000)# Create a pandas DataFrame from the Spark DataFrame using Arrow
pdf = test_sdf.toPandas()# Convert the pandas DataFrame back to Spark DF using Arrow
sdf = spark.createDataFrame(pdf)
如果在实际计算之前出现错误,PyArrow 优化将被禁用。如果我们想避免潜在的非箭头优化,我们还需要启用以下配置:
spark.conf.set(
"spark.sql.execution.arrow.pyspark.fallback.enabled", "true"
)
PyArrow 的局限性
目前,基于箭头的优化转换不支持某些 Spark SQL 数据类型。这些类型是:
MapType
TimestampType
中的ArrayType
- 嵌套
StructType
结论
正如我们已经讨论过的,toPandas()
是一个开销很大的操作,应该小心使用,以尽量减少对 Spark 应用程序的性能影响。在需要这样做的情况下,尤其是当数据帧相当大时,在将 Spark 转换为 Pandas 数据帧时,需要考虑 PyArrow 优化(反之亦然)。
成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。
如何高效地设计机器学习系统
原文:https://towardsdatascience.com/how-to-efficiently-design-machine-learning-system-caef9e05d5fb?source=collection_archive---------61-----------------------
吴恩达对机器学习设计的重要见解
在 Unsplash 上由 Rohan Makhecha 拍摄的照片
比方说,你正在设计一个机器学习系统,你已经使用你最喜欢的模型用默认参数对你的数据进行了训练,但它的性能不够好。
从那以后,你可能会在黑暗中摸索,到处尝试,没有一个真正的计划,也不能保证你所做的会提高你的模型的性能。
幸运的是,机器学习之父吴恩达给了我们一种有效调整机器学习模型的方法。在这里。
- 尽快实现数据管道
- 诊断高偏差和/或高方差,并采取相应措施
- 手动分析未分类记录并寻找模式
使用选定的评估指标不断测试和学习
1.尽快实现数据管道
您的数据管道应该执行以下步骤:
- 清除不需要的值(异常值)
- 填充或删除空值
- 规范化数字特征
- 对分类特征进行编码
- 将数据分成 3 组训练(70%) /交叉验证(15%) /测试(15%)(非大数据应用的组大小)
- 使用您最喜欢的模型进行拟合和预测
- 使用您选择的指标(F1、精度、召回率、MAE 等)评估训练/交叉验证集上的模型性能
Andrew 对此的建议是,尽可能快地编写与上述每个步骤相对应的代码,不要太担心前两个步骤。它们会很快变得很耗时,最好在第一次实现时就做出强有力的假设,然后再重复这些假设。
2.诊断高偏差或/和高方差
诊断偏差和/或方差的方法有很多,Andrew 提出了两种方法:
学习曲线
学习曲线被定义为交叉验证和测试集的梯度下降迭代次数的成本演变的表示。
遗憾的是,根据定义,它只与使用梯度下降或优化 it 参数的变体的算法相关。
通过观察它们,你可以快速诊断高偏差和高方差。下图不言自明。
比较交叉验证准确性、训练准确性和人的表现
贝叶斯误差:针对特定问题的最优(不可达)误差率。通常使用最佳可用人类表现来近似。
高方差:训练误差非常接近贝叶斯误差,交叉验证误差比两者都更差。
高偏差:训练误差非常接近交叉验证误差,并且两者都比贝叶斯误差更差。
高偏差和高方差:训练误差比交叉验证误差好得多,但都比贝叶斯误差差得多。
我使用了“相当”一词来强调这样一个事实,即没有经验法则来定义交叉验证误差、训练误差和贝叶斯误差的差异应该有多大或多小。
基于诊断采取措施
根据偏差/方差诊断,您可以采取的措施因型号而异。
在这篇文章中,我将只提出逻辑和线性回归和神经网络,但你可以找到基于树的模型,KNN 和 SVM 的快速谷歌搜索相应的行动。
这里的关键见解是,您应该尽快诊断您的问题类型(高偏差或高方差)。
高偏置:
- 增加梯度下降迭代次数(全部)
- 添加多项式要素(线性和逻辑回归)
- 特征工程(全部)
- 增加层数/每层的单元数(神经网络)
高方差:
- 添加正则化:L1 范数(所有),退出正则化(神经网络)
- 添加更多数据(全部)
3.误差分析
误差分析包括在分类问题的情况下从测试集中收集未分类记录的随机样本,或者在回归问题的情况下收集预测误差高的记录的随机样本。然后你应该分析样本在不同类别中的分布。
在上面的错误分析输出表中,您可以看到该方法在 cat 检测器算法中的实际示例。
从该表中可以得出的主要见解是,61%的模糊图像和 43%的未分类记录是未分类的。基于这些结果,花一些时间来提高算法在大 Cat 和模糊图像上的性能似乎是值得的。
数据集可能包含也可能不包含关于其记录的详细信息。这就是为什么手动查看记录可以帮助您根据您的观察创建类别。
在上面的例子中,只有通过手动查看和分类图像,才能发现关于如何提高性能的重要见解。
使用您的评估标准不断测试和学习
在第二步和第三步中,使用步骤 1 中构建的评估设置来跟踪算法性能的改善。
您还应该使用此设置来测试不同的超参数/模型,并测试填充空值和过滤异常值的不同方法。
如果你觉得我错过了什么,请让我知道!
一切归功于吴恩达,也就是机器学习的教皇。
如何有效实现精确召回曲线下面积(PR-AUC)
原文:https://towardsdatascience.com/how-to-efficiently-implement-area-under-precision-recall-curve-pr-auc-a85872fd7f14?source=collection_archive---------20-----------------------
有几行代码能产生真正的魔力
这篇文章基于脸书人工智能研究所在 Detectron 项目范围内发布的 PR-AUC 的实现。我花了一段时间才理解为什么只有几行代码能够执行如此复杂的任务。我来分享一下我的见解。
在上一篇帖子中,我们介绍了 PR-AUC 的理论背景。在本帖中,我们将通过剖析一个高效的 PR-AUC 实现来加深我们的理解。如果你还不完全熟悉精度、回忆、TP、FP 等概念。请重温上一篇帖子。
我们将再次使用一个仅包含 10 个样本的过于简化的示例。对于每个样本,我们计算神经网络的输出(预测置信度),并将其与相应的基础事实标签放在一个表格中,见表 1。1.然后,我们根据预测的置信度对条目进行排序,如表 1 所示。2.
**Python code**:
predictions = np.array([0.65,0.1,0.15,0.43,0.97,0.24,0.82,0.7,0.32,0.84])
labels = np.array([0, 0, 1, 0, 1, 1, 0, 1, 1, 1])# sort the entries according to the predicted confidence
id = np.argsort(predictions)[::-1]
predictions = predictions[id]
labels = labels[id]
如果我们将阈值选择在第一个和第二个条目之间(0.84
使用基本事实标签,我们可以很容易地推导出所选阈值的 TP、FP、TN 和 FN。要得到 TP,只需计算“标签”列(左表)的绿色行中出现了多少个 1。让 TN 计算“标签”列红色行中的 0,等等。
接下来,我们选择第二个和第三个条目之间的阈值(0.84
我们可以对表中的所有行执行这个简单的过程。如果现在还不完全清楚这个过程是如何工作的,让我们再举一个例子。我们选择阈值位于第 8 和第 9 个条目之间(0.15
首先请注意,上表中每一行的 TP 值对应于该行(包括该行)以上所有 1 的总和。在 Python 中,这可以很容易地通过累加和来实现。
此外,请注意,上面右表中 TP 和 FP 的总和与左表中的秩条目相同。这并不奇怪,因为在上一篇文章中,我们展示了 TP+FP 是给定阈值的正面预测总数。这是个好消息,因为这意味着对于精度的计算,我们实际上不需要计算 FP(!).因此,通过将列“标签”的累积和除以列“等级”的条目,可以从上面的表中获得精度。
同样,请注意上表中 TP 和 FN 的总和始终为 6。这也不奇怪,因为 TP+FN 是数据集中实际阳性样本的总数。该数字等于标签列中所有条目的总和。因此,为了计算召回率,我们既不需要计算 TN 也不需要计算 FN(!).
接下来,让我们将获得的配方应用于上表的所有条目:
**Python code**:
cumsum = np.cumsum(labels)
rank = np.arange(len(cumsum)) + 1
Num = cumsum[-1]prec = cumsum / rank
rec = cumsum / Num
当我们绘制精度与回忆的关系图时,我们观察到一个曲折的模式:
接下来是更高级的部分,我将解释之字形图案的来源。在本节结束时,你应该能够通过查看(已排序的)“标签”栏来定性地绘制精度-召回曲线。这是一个很好的技巧,可以让你对精确回忆曲线有更直观的理解。你自己试几个例子就好了。但是,如果您只对 PR-AUC 的有效实施感兴趣,您可以安全地跳过这一部分。
之字形模式有以下根本原因:每次我们在列“Label”中遇到一个或多个零,列“TP”中的累积和与前一行中的值相同。
因为召回是 TP 除以一个常数,所以召回的值也保持不变。然而,当向下移动一行时,“Rank”列中的值总是增加 1。因为精度是 TP 除以秩,所以精度必须变小。这解释了精确召回曲线的暴跌。
相比之下,每当我们在列“标签”中遇到一个或多个 1 时,当前进到下一行时,列“TP”中的累积和就增加 1。因为召回是 TP 除以一个常数,所以召回的值也必须增加。
我们可以很容易地证明,在这些情况下,精度的值要么增加,要么保持不变。我们因此想证明下面的表达式:
其中 i = Rank 就是该行的索引。上述表达式相当于:
请注意,我们只考虑“标签”列中当前条目(行 i )的值为 1 的情况:
或者
将这个表达式代入上式,我们得到:
最后:
这种说法总是成立的,从下表中可以看出:
请注意,上面公式中的等式只有在“标签”列中没有出现零时才成立。因此,只要没有遇到零,精度也保持不变(值为 1.0)。
前哨值
正如我们将很快看到的那样,Sentinel value 使 PR-AUC 的实施非常有效。
让我们先来看看上面例子中的一个特点。当列“标签”中的第一个条目是 1 时,第一个召回值大于 0。
请再看一下上面的图表来验证这一说法。这是不好的,因为当我们在精度-召回曲线上进行积分以获得 PR-AUC 时,我们必须从召回值零开始。
请注意,如果上面示例中的第一个标签是零,我们将获得下图:
这一次我们从召回值零开始,但是,相应的精度值也是零。因此,我们得到了精确回忆曲线的原点。请进一步注意,如果列“标签”的前 2 个条目为零,我们将在精确召回曲线的原点得到两个重叠点,依此类推。
因此,如果我们在表中添加一个 sentinel 值(precision=0.0,recall=0.0)作为额外的第 0 行,也没有什么坏处。
为了完整起见,我们还将在表的末尾添加一个标记值(precision=0.0,recall=1.0)。请注意,根据定义,最后一行中的 recall 值必须始终为 1.0。
**Python code**:
mrec = np.concatenate(([0.], rec, [1.]))
mpre = np.concatenate(([0.], prec, [0.]))
为了消除锯齿模式并校正第一个标记值,我们将计算精度的包络。使用我们的表格很容易得到信封。对于每一行,我们计算该行下面所有精度值的最大值,包括该行本身的值。
**Python code**:
# compute the precision envelope
for i in range(mpre.size - 1, 0, -1):
mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
为了计算面积和精确召回曲线,我们将使用矩形划分图形(请注意,矩形的宽度不一定相同)。
在我们的例子中,只需要 6 个矩形来描述该区域,然而,我们有 12 个点来定义精度-召回曲线。我们如何找到有用的点?请注意,我们只需要位于每个矩形左上角的那些点。幸运的是,所有其他点都有一个属性,即它们后面(表中的下一行)有一个具有相同召回值的点,查看上图中不带小箭头的红色点即可获得该点。因此,在我们的表中,我们必须寻找与下面的行具有不同召回值的行。
**Python code**:
i = np.where(mrec[1:] != mrec[:-1])[0]
请注意,原点中的重复点(前面提到过)也会被该方法过滤掉。只有原点中的最后一点会被保留。
最后,我们必须计算所有矩形的面积,并将它们相加。矩形的宽度由两个相邻的召回值定义。
**Python code:** pr_auc = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
更多阅读
https://neptune.ai/blog/f1-score-accuracy-roc-auc-pr-auc
参考
脸书研究 Detectron
图(平均平均精度)用于物体检测
如何有效地从字符串中删除标点符号
原文:https://towardsdatascience.com/how-to-efficiently-remove-punctuations-from-a-string-899ad4a059fb?source=collection_archive---------12-----------------------
Python 中清理字符串的 8 种不同方法
由 Murat Onder 在 Unsplash 拍摄的照片
最近,我发现自己花了很多时间试图弄懂杂乱的文本数据,并决定回顾一些相关的预处理。有许多不同的方法来实现简单的清洁步骤。今天,我将回顾几种不同的方法来删除字符串中的标点符号,并比较它们的性能。
使用翻译
string translate 方法是一次性将多个字符更改为不同值的便捷方法。 Translate 需要一个表作为字典来映射字符串。maketrans 为您完成这项工作。
maketrans 语法的工作方式类似于str.maketrans('abcd', '0123', 'xyz')
。它将创建一个表格,告诉 translate 将所有 a 更改为 0, b 更改为 1, c 更改为 2,以此类推。,并移除 x、y、 z、
使用翻译删除标点符号和数字的完整语法如下。
# importing a string of punctuation and digits to remove
**import** string
exclist = **string**.punctuation + **string**.digits# remove punctuations and digits from oldtext
table_ = **str.maketrans**('', '', exclist)
newtext = oldtext.translate(table_)
这种方法将完全删除字符串中的任何字符。标点符号和字符串 .digits. 包括!" #$% & '()+,-。/:;< = >?@[\]^_`{|}~'* 和所有数字。
使用翻译+连接
但有时,我们可能希望添加一个空格来代替这些特殊字符,而不是完全删除它们。我们可以通过告诉一个表将特殊字符改为空格而不是排除它们来做到这一点。
table_ = **str.maketrans**(exclist, ' '*len(exclist))
此外,我们可以简单地用分割和连接来确保这个操作不会导致单词之间出现多个空格。
newtext = ' '.**join**(oldtext.**translate**(table_).**split**())
使用连接+字符串
我们也可以只使用 join 而不是 translate,从我们上面制作的字符串包中取出相同的排除列表。
# using exclist from above
newtext = ''.**join**(x **for** x **in** oldtext **if** x **not in** exclist)
使用 Join + isalpha
我们可以放弃排除列表,只使用字符串方法来调用字母。
newtext = ''.**join**(x **for** x **in** oldtext **if** x.**isalpha**())
这种方法只会保留字母表。因此,它还会消除单词之间的空格。
使用联接+过滤器
代替列表理解,我们可以使用过滤器做同样的事情。这比使用列表理解稍微更有效,但是以相同的方式输出新的文本。
newtext = ''.**join**(**filter**(str.**isalpha**, oldtext))
使用替换
另一种删除标点符号(或任何选定字符)的方法是遍历每个特殊字符,一次删除一个。我们可以通过使用替换的方法来做到这一点。
# using exclist from above
**for** s **in** exclist:
text = text.**replace**(s, '')
使用正则表达式
根据确切的目标,使用 regex 有许多方法可以完成类似的事情。一种方法是用空格替换不是字母的字符。
**import** re
newtext = re.**sub**(r'[^A-Za-z]+', ' ', oldtext)
【^a-za-z]+】选择符合方括号( [] )内规则的任意字符,即而非( ^ )在大写字母( A-Z )或小写字母( a-z )中至少有一个字母( + )。然后 regex sub 用空格替换旧文本中的这些字符。
另一种方法是使用元字符 \W. 选择所有非单词。该元字符不包括下划线(-)和数字。
newtext = re.**sub**(r'\W+', ' ', oldtext)
照片由凯勒·琼斯在 Unsplash 上拍摄
表演
我们回顾了一些方法,但是哪一个是最好的呢?我使用了 timeit 模块来测量每种方法处理大约 1kb 的字符串数据 10000 次需要多长时间。
测试表明,与其他方法相比,使用翻译花费的时间要少得多!另一方面,在列表理解中使用连接似乎是清理选择字符最低效的方式。 Translate 是当今所有评测中最通用、最快速的选项。
如果你有任何其他方法,请留下评论,我会将测试结果添加到帖子中!
如何将 Spark ML 模型作为 Kafka 实时流应用程序嵌入到生产部署中
原文:https://towardsdatascience.com/how-to-embed-a-spark-ml-model-as-a-kafka-real-time-streaming-application-for-production-deployment-933aecb79f3f?source=collection_archive---------11-----------------------
[OC]
用于生产评分的 2 种模型部署
今天的数据科学家可以依靠丰富的高质量开源工具、框架和库来训练模型。训练模型从未如此简单,只需几行 Python 代码即可完成。
然而,模型的生产部署仍然是数据科学中最棘手的问题,也是许多数据科学项目难以适应业务并产生影响的原因。Gartner 2019 等行业调查发现,多达 80%的数据科学项目失败。数据科学的成功受到一些通常称为“最后一英里问题”的困扰。
你可以在我之前关于模型开发最佳实践如何缩小数据科学和生产环境之间差距的博客文章中读到:
[## 用 Mlflow 为非傻瓜完成数据科学项目模板。
数据科学项目最佳实践,适用于在本地或云中工作的每个人,从刚起步的忍者到大…
towardsdatascience.com](/complete-data-science-project-template-with-mlflow-for-non-dummies-d082165559eb)
模型开发的最佳工具不一定是大规模生产中模型评分或模型推断的正确选择。为生产中的模型评分和模型推断选择最佳框架,并理解这对模型开发本身的约束和要求是很重要的。虽然最佳开发实践使模型更接近生产环境,但数据科学家仍然必须将模型与最合适的模型服务和评分框架相结合,以实现成功的生产部署。
用于模型服务和评分的框架和平台的选择越来越多,与所有最新的创新和发布保持同步会让人感到势不可挡。幸运的是,所有的解决方案都分为两大类。了解哪种类型最适合您的业务问题将大大简化选择最佳可用选项的过程。
[OC]
模型部署的两个高级类型是(1)嵌入式模型或(2)模型推理服务器。
在嵌入式模型的情况下,模型作为数据处理基础结构的一部分被托管和管理。当模型性能至关重要时,这种部署类型是理想的,因为嵌入式模型速度更快,延迟最低。如果您希望在设备或 edge 上支持离线推理,而不依赖于将数据发送到通常位于云中的独立模型推理服务器,那么也需要嵌入您的模型。嵌入式模型还继承了数据处理框架的优势和能力,例如,将模型嵌入到 Kafka 中可以保证只有一次语义而没有副作用。嵌入模型的目标基础设施的正确选择是
- Kafka:
使用无状态模型和类似于精确一次语义的保证对事件数据流进行实时评分。 - Spark:
针对大量现有数据对模型进行分布式批量评分
或对具有宽松实时要求的模型进行小批量评分,但先进的 ELT 步骤和功能工程受益于 SparkSQL - 数据库内:
有状态模型对不断变化的数据记录进行评分,比如需要高性能数据库的用户配置文件。选项有 RedisAI、ksqlDB 和 SQL Server。
在专用的模型推理服务器上部署模型也有它的优势:首先,它是最灵活的部署,对模型开发的约束最少。其次,通过 API 和 gRPC 调用与现有的遗留基础设施集成推理服务器和建模微服务也更简单,允许额外的中间层或集成层。但最重要的是,大多数专用的模型推理服务器都带有现成的功能,用于管理和监控生产中的模型。生产中的典型数据科学模型是动态的,具有复杂的生命周期。
[OC]
一个成功的数据科学团队将开发许多不同的现任和挑战者模型,并要求在不断变化的环境中通过持续的基准测试、监控和生产移交来重新培训这些模型。专用的模型推理服务器可以更轻松地实现复杂数据科学模型生命周期的端到端自动化。例如,专用推理服务器和模型微服务的选项有:
- 张量流服务
- ONNX 运行时
- 模型微服务,例如通过 AWS Sagemaker
- 会合建筑
卡夫卡的嵌入式模型
建立模型似乎是大多数数据科学项目中最容易的部分。然而,由于企业生产系统的需求,将模型部署到生产中是一个挑战。模型的部署必须解决伸缩和负载平衡问题,以满足不同需求的 SLA,并需要与上游数据系统和下游模型消费者集成。虽然这是一项极其复杂的工程任务
- 为了管理分布式模型,
- 对数据进行实时评分
- 保证每个请求只获得一次分数
- 包括容错和恢复
这些要求在企业部署中很常见。
通过将我们的模型嵌入到 Kafka Streams 应用程序中,我们只需继承 Kafka 的企业特性,就可以满足所有这些需求。
Kafka 是分布式流媒体应用程序的代理,Kafka 可以
- 将数据作为消息在应用程序之间传递,作为一个 KStream 和
- 将分布式应用程序的状态作为一个表进行全局管理。
在商业数据科学家的日常工作中,构建和训练模型的要求与部署用于评分的模型非常不同。模型通常使用 Spark 对大量历史数据进行批量训练,然后部署在生产中进行实时评分。
以下示例显示了如何将在 Spark 中构建和训练的数据科学模型作为 Kafka 流应用程序嵌入到实时评分中。
[OC]
创建模型
为了将 Spark 管道部署为 Kafka 流应用程序,我们使用 Mleap 项目来序列化我们的 Spark 管道,而不需要任何 Spark 上下文。
我们将 mleap 包与 pip 或 conda 一起安装在我们的 Jupyter 笔记本中使用,或者将 Python 脚本作为我们的 Spark 驱动程序脚本:
pip install mleap
下面的代码将 Mleap 添加到我们的 Spark 会话中:
from pyspark.sql import SparkSessionspark = (
SparkSession.builder
.config('spark.jars.packages', 'ml.combust.mleap:mleap-spark-base_2.11:0.14.0,ml.combust.mleap:mleap-spark_2.11:0.14.0')
.getOrCreate()
)
然后像平常一样使用 Spark,并使用 PySpark ML 包训练一个模型:
from pyspark.ml import Pipeline
from pyspark.ml.classification import RandomForestClassifier
from pyspark.ml.feature import IndexToString, StringIndexer, VectorAssembleriris.show(1)
# +---------------+--------------+---------------+--------------+---------------+
# |sepal_length_cm|sepal_width_cm|petal_length_cm|petal_width_cm| class|
# +---------------+--------------+---------------+--------------+---------------+
# | 7.0| 3.2| 4.7| 1.4|Iris-versicolor|
# +---------------+--------------+---------------+--------------+---------------+labelIndexer = StringIndexer(inputCol="class", outputCol="indexedLabel").fit(iris)
assembler = VectorAssembler(
inputCols=["sepal_length_cm", "sepal_width_cm", "petal_length_cm", "petal_width_cm"],
outputCol="features"
)
labelConverter = IndexToString(
inputCol="prediction", outputCol="predictedLabel",
labels=labelIndexer.labels
)
rf = RandomForestClassifier(labelCol="indexedLabel", featuresCol="features", numTrees=10)
pipeline = Pipeline(stages=[labelIndexer, assembler, rf, labelConverter])model = pipeline.fit(iris)model.transform(iris.select('sepal_length_cm', 'sepal_width_cm', 'petal_length_cm', 'petal_width_cm')).show(1)# +---------------+--------------+---------------+--------------+-----------------+--------------+-------------+----------+--------------+
# |sepal_length_cm|sepal_width_cm|petal_length_cm|petal_width_cm| features| rawPrediction| probability|prediction|predictedLabel|
# +---------------+--------------+---------------+--------------+-----------------+--------------+-------------+----------+--------------+
# | 5.1| 3.5| 1.4| 0.2|[5.1,3.5,1.4,0.2]|[10.0,0.0,0.0]|[1.0,0.0,0.0]| 0.0| Iris-setosa|
在真实的项目中,我们至少会使用测试数据集来验证我们的模型,并使用交叉验证来调整参数。在模型构建和训练的最后,我们有一个拟合的 Spark 管道模型,在上面的代码中称为 model,我们可以使用它来转换数据,以在 Spark 中批量获得预测。
为了将我们的模型从 Spark 中释放出来,并将其移动到 Kafka 流应用程序中进行实时评分,我们使用以下简单代码将其序列化为 Mleap 包:
import mleap.pyspark
from mleap.pyspark.spark_support import SimpleSparkSerializermodel.serializeToBundle(
"file:/home/jovyan/notebooks/model",
model.transform(iris)
)
它在名为 model:
创建 Kafka 流应用程序
通过将我们的模型序列化为 Mleap 包,我们可以创建 Kafka 流应用程序来将我们的模型嵌入到 Kafka 中。我们必须为此创建一个简单的 Scala 应用程序,最重要的是将带有 Mleap 包的模型文件夹移动到 Scala 项目的资源文件夹中。
您可以在我的 Git 存储库中找到完整的代码和项目设置:
[## Jan Teichmann / kafka-mleap-iris 分类器
借助 Mleap 嵌入 Spark ML 管道的 Kafka Streams 应用程序
gitlab.com](https://gitlab.com/jan-teichmann/kafka-mleap-iris-classifier)
下面的 Scala 代码将我们的 Mleap 捆绑包分解成一个 Mleap 管道模型,并创建一个名为 score()的简单函数,接受 iris 输入数据进行评分。你可以看到 Mleap 非常接近 Spark API。这段代码与 Kafka 无关,只是如何用 Scala 从一个包中加载任何 Mleap 模型。你可以在这里找到关于 Mleap 运行时的扩展文档。
object IrisModel {val schema: StructType = StructType(
StructField("sepal_length_cm", ScalarType.Double),
StructField("sepal_width_cm", ScalarType.Double),
StructField("petal_length_cm", ScalarType.Double),
StructField("petal_width_cm", ScalarType.Double),
StructField("class", ScalarType.String)
).getval modelpath = getClass.getResource("/model").getPathval model = (
for(bundle <- managed(BundleFile(s"jar:$modelpath"))) yield {
bundle.loadMleapBundle().get
}
).tried.get.rootdef score(
sepal_length_cm: Double, sepal_width_cm: Double,
petal_length_cm: Double, petal_width_cm: Double
): String = {model.transform(
DefaultLeapFrame(
schema,
Seq(Row(sepal_length_cm, sepal_width_cm, petal_length_cm, petal_width_cm, "Iris-setosa"))
)
).get.select("predictedLabel").get.dataset.map(_.getString(0)).head
}}
我们可以使用如下简单的单元测试来测试我们的模型是否如预期的那样工作:
class IrisSpec extends FlatSpec with Matchers {
"An Iris Classifier" should "return the class Iris-setosa" in {
val prediction = IrisModel.score(5.1, 3.5, 1.4, 0.2)
prediction should be ("Iris-setosa")
}
it should "return the class Iris-versicolor" in {
val prediction = IrisModel.score(6.2, 2.2, 4.5, 1.5)
prediction should be ("Iris-versicolor")
}
it should "return the class Iris-virginica" in {
val prediction = IrisModel.score(6.1, 2.6, 5.6, 1.4)
prediction should be ("Iris-virginica")
}
}
下一步,我们创建 Kafka 流应用程序并嵌入我们的模型:
object IrisStreamClassifier extends App {import org.apache.kafka.streams.scala.Serdes._
import org.apache.kafka.streams.scala.ImplicitConversions._val config: Properties = {
val p = new Properties()
p.put(StreamsConfig.APPLICATION_ID_CONFIG, "iris-classifier")
val bootstrapServers = if (args.length > 0) args(0) else "kafka:9092"
p.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers)
p
}def irisStreamClassifier(
inputTopic: String, outputTopic: String
): Topology = {val builder: StreamsBuilder = new StreamsBuilder()
val irisInput = builder.stream[String, String](inputTopic)
val irisScore: KStream[String, String] = irisInput.map(
(_, value) => {
val iris_values = value.split(",").map(_.toDouble)
(null, Seq(value, IrisModel.score(iris_values(0), iris_values(1), iris_values(2), iris_values(3))).mkString(","))
}
)
irisScore.to(outputTopic)
builder.build()
}val streams: KafkaStreams = new KafkaStreams(
irisStreamClassifier(
"iris-classifier-input",
"iris-classifier-output"
), config
)
streams.start()sys.ShutdownHookThread {
streams.close(Duration.ofSeconds(10))
}}
在 irisStreamClassifier 函数中,我们创建了流拓扑,它接收作为 csv 字符串的 iris 数据流,并通过将分类器应用于每个消息来映射该流。我们将流处理拓扑封装到一个新的 Kafka 流中,以将该拓扑转变为我们使用 streams.start()运行的应用程序
我们可以使用 Kafka 的 TopologyTestDriver 对我们的流应用程序进行单元测试:
class IrisClassifierSpec extends FlatSpec with Matchers with BeforeAndAfterAll {
val config: Properties = {
val p = new Properties()
p.put(StreamsConfig.APPLICATION_ID_CONFIG, "integration-test")
p.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "dummy config")
p
}val driver = new TopologyTestDriver(
IrisStreamClassifier.irisStreamClassifier("input-topic", "output-topic"), config)val recordFactory = new ConsumerRecordFactory("input-topic", new StringSerializer(), new StringSerializer())override def afterAll() {
driver.close()
}
"Iris Stream Classifier" should "return the class Iris-setosa" in {
driver.pipeInput(recordFactory.create("5.1,3.5,1.4,0.2"))
val record: ProducerRecord[String, String] = driver.readOutput("output-topic", new StringDeserializer(), new StringDeserializer())
record.value() should be("5.1,3.5,1.4,0.2,Iris-setosa")
}
it should "return the class Iris-versicolor" in {
driver.pipeInput(recordFactory.create("6.2,2.2,4.5,1.5"))
val record: ProducerRecord[String, String] = driver.readOutput("output-topic", new StringDeserializer(), new StringDeserializer())
record.value() should be("6.2,2.2,4.5,1.5,Iris-versicolor")
}
it should "return the class Iris-virginica" in {
driver.pipeInput(recordFactory.create("6.1,2.6,5.6,1.4"))
val record: ProducerRecord[String, String] = driver.readOutput("output-topic", new StringDeserializer(), new StringDeserializer())
record.value() should be("6.1,2.6,5.6,1.4,Iris-virginica")
}
}
为了构建我们的应用程序,我们将使用 SBT 并如下定义我们的 build.sbt 项目:
name := "iris-classifier-streams"
version := "1.0.0"
scalaVersion := "2.12.10"
exportJars := truelazy val iris = (project in file("."))
.settings(
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "3.1.0" % Test,
"org.apache.kafka" % "kafka-streams-test-utils" % "2.4.0" % Test,
"org.apache.kafka" %% "kafka-streams-scala" % "2.4.0",
"ml.combust.bundle" %% "bundle-ml" % "0.14.0",
"ml.combust.mleap" %% "mleap-runtime" % "0.14.0",
"com.jsuereth" %% "scala-arm" % "2.0",),
assemblyMergeStrategy in assembly := {
case PathList("org", "apache", "spark", "unused", "UnusedStubClass.class") => MergeStrategy.first
case "module-info.class" => MergeStrategy.discard
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
}
)
这包括汇编插件的合并策略,以处理一些依赖关系抛出的重复数据删除错误。我们使用一个名为 scala-sbt 的 Docker 映像,它提供了 scala 和 sbt 来编译和打包我们的应用程序,作为一个汇编超级 Jar:
ocker build \
--build-arg BASE_IMAGE_TAG="8u242-jdk-stretch" \
--build-arg SBT_VERSION="1.3.5" \
--build-arg SCALA_VERSION="2.12.10" \
-t scala-sbt github.com/hseeberger/scala-sbt.git#:debiandocker run -it --rm -w /home/sbtuser \
--mount type=bind,source="$(PWD)/src",target=/home/sbtuser/src \
--mount type=bind,source="$(PWD)/build.sbt",target=/home/sbtuser/build.sbt \
--mount type=bind,source="$(PWD)/project",target=/home/sbtuser/project \
--mount type=bind,source="$(PWD)/target",target=/home/sbtuser/target \
scala-sbt sbt assembly
在本地运行 Kafka 流应用程序
要将我们的新 Iris 分类器作为 Kafka 流应用程序运行,我们可以使用以下 docker-compose.yml 在我们的笔记本电脑上运行 Kafka broker:
version: '2'services:
zookeeper:
image: 'bitnami/zookeeper:3'
ports:
- '2181:2181'
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka:
image: 'bitnami/kafka:2'
ports:
- '9092:9092'
- '29092:29092'
environment:
KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper:2181
ALLOW_PLAINTEXT_LISTENER: "yes"
KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_CFG_LISTENERS: PLAINTEXT://:9092,PLAINTEXT_HOST://:29092
KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: "true"
depends_on:
- zookeeper
docker-compose up 将开始我们的单一卡夫卡经纪人
docker-compose up kafka
然后为我们的应用程序创建 Kafka 主题:
docker-compose exec kafka kafka-topics.sh --create --bootstrap-server kafka:9092 --replication-factor 1 --partitions 1 --topic iris-classifier-input
docker-compose exec kafka kafka-topics.sh --create --bootstrap-server kafka:9092 --replication-factor 1 --partitions 1 --topic iris-classifier-output
然后,我们使用以下命令启动我们的流应用程序:
java -classpath target/scala-2.12/iris-classifier-streams-assembly-1.0.0.jar kafka.iris.IrisStreamClassifier localhost:29092
我们启动一个控制台监听器,等待关于应用程序输出主题的消息:
docker-compose exec kafka kafka-console-consumer.sh --bootstrap-server kafka:9092 --topic iris-classifier-output --from-beginning --max-messages 1
最后,我们用下面的命令向模型的输入主题发送一条消息:
docker-compose exec kafka bash -c "echo 5.1,3.5,1.4,0.2 | kafka-console-producer.sh --broker-list kafka:9092 --topic iris-classifier-input && echo"
由于我们的努力,我们获得了模型输出主题上的消息,该消息由控制台消费者实时流式传输并打印到我们的终端:
在我的 GitLab 上找到这个例子的所有代码
[## Jan Teichmann / kafka-mleap-iris 分类器
借助 Mleap 嵌入 Spark ML 管道的 Kafka Streams 应用程序
gitlab.com](https://gitlab.com/jan-teichmann/kafka-mleap-iris-classifier)
[OC]
如果你有兴趣了解更多关于在 Kafka 上构建实时数据产品的信息,可以看看我写的关于 Trainline.com 实时数据产品团队的博客
[## 认识克罗诺斯:Trainline 的实时数据产品平台和团队
让我们的数据按时运行
engineering.thetrainline.com](https://engineering.thetrainline.com/meet-kronos-trainlines-real-time-data-product-platform-and-team-f4b3dbe663ec)
Jan 是公司数据转型方面的成功思想领袖和顾问,拥有将数据科学大规模应用于商业生产的记录。他最近被 dataIQ 评为英国 100 位最具影响力的数据和分析从业者之一。
在 LinkedIn 上连接:【https://www.linkedin.com/in/janteichmann/】
阅读其他文章:https://medium.com/@jan.teichmann