免费使用 ngrok 从 Google Colab 快速共享 ML WebApps
互联网上有一个笑话,讲的是大多数机器学习模型最终如何出现在 Powerpoint 演示文稿中。如果你是一名数据科学家,你可能无法否认这个事实。但是事情已经开始改变,特别是像 Voila,Streamlit,Dash by Plotly 这样的解决方案。这些是 ML 和数据科学社区内利基的一部分,使数据科学家和机器学习工程师——他们不是 Web 开发人员——能够开发和部署机器学习应用程序(作为 Web 应用程序——如 SaaS)。
78%的数据营折扣
ML Web 应用程序
他们的主要观点是,你可以简单地用你熟悉的 Python 语法编写 web 应用程序(这意味着,不需要javascript
)。随着这种 ML Web 应用程序开发的开始,许多数据科学家仍然习惯并喜欢在 Jupyter 笔记本上编写代码,而不像 Web 开发人员/软件工程师那样更喜欢像 VSCode 或 Sublime Text 这样的成熟 IDE。使用 Google Colab 开发这种机器学习 Web 应用原型的爱好者也是如此——要么作为爱好项目,要么作为潜在工作机会的任务。具有讽刺意味的是,大多数时候,这些东西是以 Jupyter 笔记本或截图的形式分享的,或者有人不得不费力地将它们部署在pythonanywhere
或Heroku
ngrok
如果你处于这种情况,这种方法将会非常方便,因为你可以使用公共 URL 与世界上的任何人(暂时)共享你的 ML Web 应用程序。这个黑客使用了一个非常流行的安全隧道解决方案ngrok
你可以在这里阅读更多关于 ngrok 是什么和它做什么的信息。
基本上,ngrok 获取你的localhost
上的可用/托管的东西,并通过一个临时的公共 URL 将其公开到互联网上(注意:你可以通过他们的付费服务获得一个永久的 ngrok URL)。所有这一切都以安全的方式进行。为了进一步进行这项工作,你需要一个 ngrok(免费也可以)账户和你的仪表板上的authtoken
账户。
视频教程—https://www.youtube.com/watch?v=AkEnjJ5yWV0
如何在 Google Colab 上做到这一点?
虽然很有可能在 Google Colab 上安装ngrok
然后继续前进,但我选择了一条最短的路径,使用一个名为pyngrok
的 Python 包装器,它为我们做了很多基本的设置,还让我们可以在命令行/shell 中访问ngrok
。这意味着你可以通过!ngrok
在 Google Colab cell 上使用ngrok
命令(就像你如何访问系统命令一样)
平洛克—https://github.com/alexdlaird/pyngrok
- 在您的 Google Colab 会话上安装 pyngrok python 包
!pip install pyngrok
- 设置您的 ngrok Authtoken
!ngrok authtoken xxxxxxxxxxxxx
我们的示例 Web 应用程序
对于这个用例,让我们考虑一个使用jupyterdash
构建的示例 web 应用程序
!pip install jupyter-dashimport plotly.express as px
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output# Load Datadf = px.data.tips()# Build App
app = JupyterDash(__name__)
app.layout = html.Div([
html.H1("1littlecoder deploy ML App Colab ngrok Demo"),
dcc.Graph(id='graph'),
html.Label([
"colorscale",
dcc.Dropdown(
id='colorscale-dropdown', clearable=False,
value='plasma', options=[
{'label': c, 'value': c}
for c in px.colors.named_colorscales()
])
]),
])# Define callback to update graph
@app.callback(
Output('graph', 'figure'),
[Input("colorscale-dropdown", "value")]
)
def update_figure(colorscale):
return px.scatter(
df, x="total_bill", y="tip", color="size",
color_continuous_scale=colorscale,
render_mode="webgl", title="Tips"
)# Run app and display result inline in the notebook
- 运行 web 应用程序(在
external
模式下,我们可以获得本地主机端口的详细信息)
app.run_server(mode='external')
- 在我的例子中,web 应用程序运行在本地主机端口 8050 上
- 从 Python 调用 ngrok 并开始隧道/连接
from pyngrok import ngrok# Open a HTTP tunnel on the default port 80
public_url = ngrok.connect(port = '8050')
- 打印
public_url
(对象)以获取 web 应用程序正在隧道化的实际公共 URL
public_url
- 瞧啊。您的 Web 应用程序现在可以在互联网上使用——运行在 Google Colab 上,并在 ngrok 的帮助下显示 URL!
- 是时候与您的朋友/同事或在社交媒体上分享您的 URL,并获得对您的 ML Web 应用程序的反馈了!
结束了
本教程的目标是帮助机器学习工程师和数据科学家与世界分享他们的 Web 应用程序开发(暂时),而没有太多麻烦——实际上,只需要几行 Python 代码和最小的依赖性。请注意,这不是一个生产解决方案,在这种情况下,您可能想知道比简单的隧道更多的东西。但是,嘿,这是开始 ML Web 应用程序开发和分享之旅的良好开端! 让我知道你的想法!
参考文献
- 这里用的 Jupyter 笔记本—https://github . com/amrrs/YouTube-r-snippets/blob/master/temporary _ deploy _ ML _ web app _ with _ Google _ Colab _ and _ ngrok . ipynb
- 平罗克—https://github.com/alexdlaird/pyngrok
- 恩罗克——https://ngrok.com/
快速比较多个模型
如何高效地训练和评估多个模型
介绍
所有数据科学家在从事任何机器学习项目时都必须面对的一个问题是…
哪种模型架构最适合我的数据?
有几个理论问题需要考虑。例如,如果您的要素显示出与因变量(目标)的强线性关系,那么线性模型可能最适用。如果关系是非线性的,那么 SVM 或基于实例的分类器(如 K-最近邻)可能是最好的。如果可解释性是至关重要的,基于树的模型可能是正确的选择。此外,还有几个你应该考虑的实际问题。
出于本文的目的,我将假设您已经知道您是否正在处理一个监督的与非监督的问题,以及您是否需要分类或回归。
不幸的是,对于哪种模式是最好的这个问题,没有明确的答案。当面对不确定性时,我心中的科学家总是诉诸人类最严谨、最可靠的知识发现方法:实验!
在本文中,我将向您展示如何在您的数据集上快速测试多个模型,以找到哪些模型可能提供最佳性能,从而使您能够专注于微调和优化您的模型。
数据准备
在我们开始任何实验之前,我们需要一个数据集。我将假设我们的问题是一个监督二进制分类任务。让我们从 sklearn 载入乳腺癌数据集开始吧。
from sklearn.datasets import load_breast_cancer
X, y = data = load_breast_cancer(return_X_y=True)
接下来,我们需要将数据分成训练集和测试集。我选择了 75/25 的比例。
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=8675309)
我们现在准备运行一些实验!
进行实验
我们将快速测试 6 个不同模型对该数据集的拟合度。我选择了测试:
- 逻辑回归:基本线性分类器(好到基线)
- 随机森林:集合装袋分类器
- k 近邻:基于实例的分类器
- 支持向量机:最大间隔分类器
- 高斯朴素贝叶斯:概率分类器
- XGBoost:合奏(极限!)提升分类器
为了运行初始实验,我使用了每个模型的默认参数。为了更准确地表示每个模型的拟合程度,需要调整默认参数;然而,出于本文的目的,不调整每个模型会使总体思路更加清晰。
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.naive_bayes import GaussianNB
from xgboost import XGBClassifier
from sklearn import model_selection
from sklearn.utils import class_weight
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
import numpy as np
import pandas as pddef run_exps(X_train: pd.DataFrame , y_train: pd.DataFrame, X_test: pd.DataFrame, y_test: pd.DataFrame) -> pd.DataFrame:
'''
Lightweight script to test many models and find winners:param X_train: training split
:param y_train: training target vector
:param X_test: test split
:param y_test: test target vector
:return: DataFrame of predictions
'''
dfs = []models = [
('LogReg', LogisticRegression()),
('RF', RandomForestClassifier()),
('KNN', KNeighborsClassifier()),
('SVM', SVC()),
('GNB', GaussianNB()),
('XGB', XGBClassifier())
]results = []
names = []
scoring = ['accuracy', 'precision_weighted', 'recall_weighted', 'f1_weighted', 'roc_auc']
target_names = ['malignant', 'benign']for name, model in models:
kfold = model_selection.KFold(n_splits=5, shuffle=True, random_state=90210)
cv_results = model_selection.cross_validate(model, X_train, y_train, cv=kfold, scoring=scoring)
clf = model.fit(X_train, y_train)
y_pred = clf.predict(X_test)
print(name)
print(classification_report(y_test, y_pred, target_names=target_names))results.append(cv_results)
names.append(name)this_df = pd.DataFrame(cv_results)
this_df['model'] = name
dfs.append(this_df)final = pd.concat(dfs, ignore_index=True)return final
这个脚本中有很多东西需要解开。首先,我们创建一个变量dfs
来保存所有数据集,这些数据集将通过对训练集应用 5 重交叉验证来创建。
接下来,models
在一个元组列表中,保存每个要测试的分类器的名称和类。在这之后,我们循环遍历这个列表并运行 5 重交叉验证。每次运行的结果都记录在熊猫数据帧中,我们将其添加到dfs
列表中。必须注意,这里记录的指标是两个类别的加权平均值指标。这对于任何不平衡的数据集都不适用,因为多数类的性能会盖过少数类。您可能希望调整下面的脚本,只记录感兴趣的类的指标!
为了进一步帮助评估,测试集上的分类报告被打印到屏幕上。最后,我们连接并返回所有结果。
脚本的示例输出
评估结果
为了总结我们的分析,我们将分析从run_exps()
脚本返回的final
数据帧中的数据。
为了从每个模型中获得更好的度量分布估计,我在 30 个样本上运行了经验自举。此外,我将数据分为两类:性能指标和适合时间指标。下面的代码块实现了这一点。
bootstraps = []
for model in list(set(final.model.values)):
model_df = final.loc[final.model == model]
bootstrap = model_df.sample(n=30, replace=True)
bootstraps.append(bootstrap)
bootstrap_df = pd.concat(bootstraps, ignore_index=True)
results_long = pd.melt(bootstrap_df,id_vars=['model'],var_name='metrics', value_name='values')time_metrics = ['fit_time','score_time'] # fit time metrics## PERFORMANCE METRICS
results_long_nofit = results_long.loc[~results_long['metrics'].isin(time_metrics)] # get df without fit data
results_long_nofit = results_long_nofit.sort_values(by='values')## TIME METRICS
results_long_fit = results_long.loc[results_long['metrics'].isin(time_metrics)] # df with fit data
results_long_fit = results_long_fit.sort_values(by='values')
我们现在有一些可靠的数据来绘制和分析。首先,让我们从五重交叉验证中绘制我们的性能指标。
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(20, 12))
sns.set(font_scale=2.5)
g = sns.boxplot(x="model", y="values", hue="metrics", data=results_long_nofit, palette="Set3")
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.title('Comparison of Model by Classification Metric')
plt.savefig('./benchmark_models_performance.png',dpi=300)
按模型和指标的箱线图
很明显,支持向量机在所有指标上对我们的数据拟合得很差,而集合决策树模型(Random Forest 和 XGBoost)对数据拟合得很好。
训练和得分时间怎么样?
plt.figure(figsize=(20, 12))
sns.set(font_scale=2.5)
g = sns.boxplot(x="model", y="values", hue="metrics", data=results_long_fit, palette="Set3")
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.title('Comparison of Model by Fit and Score Time')
plt.savefig('./benchmark_models_time.png',dpi=300)
按型号划分的培训和评分时间
哇,SVM 就是不能休息一下!表现最差的车型和训练/评分慢!
有趣的是,XGBoost 无疑是训练最慢的;然而,这是最好的表现。我们通常会在性能和训练时间方面进行权衡。考虑需要大量数据和时间来训练的神经网络,但是一般来说表现得非常好。
RandomForest 和 GNB 的 KNN 相比速度相对较慢,而 LogReg 的表现排名第二。如果我继续改进模型,我可能会把大部分精力放在 RandomForest 上,因为它的表现几乎与 XGBoost ( )相同,它们的 95%置信区间可能会重叠!)但是训练速度快了差不多 4 倍!
如果您希望对这些模型进行更多分析(例如,计算每个指标的置信区间),您将需要访问每个指标的均值和标准差。你可以在这里找到这些信息。
metrics = list(set(results_long_nofit.metrics.values))
bootstrap_df.groupby(['model'])[metrics].agg([np.std, np.mean])
每个指标的平均值和标准差
time_metrics = list(set(results_long_fit.metrics.values))
bootstrap_df.groupby(['model'])[time_metrics].agg([np.std, np.mean])
时间的平均值和标准差
结论
现在,您已经有了工具,可以在您的数据上快速测试许多不同的模型,并查看哪些架构可能最适合您。
这种比较并不详尽,这一点我怎么强调也不为过!
以上分析只考虑了意味着精度、召回率等。在你的实际问题中,你不太可能关心所有类的平均精度,相反,你可能特别关注一个类的精度!此外,必须调整每个模型的超参数,以真正评估它们与数据的拟合程度。
参考
python 中用于统计计算的数据结构,McKinney,第 9 届科学中的 Python 会议录,第 445 卷,2010 年。
@software{reback2020pandas,
author = {The pandas development team},
title = {pandas-dev/pandas: Pandas},
month = feb,
year = 2020,
publisher = {Zenodo},
version = {latest},
doi = {10.5281/zenodo.3509134},
url = {https://doi.org/10.5281/zenodo.3509134}
}
Harris,C.R .,Millman,K.J .,van der Walt,S.J .等人用 NumPy 进行数组编程。自然 585,357–362(2020)。DOI:10.1038/s 41586–020–2649–2。
sci kit-learn:Python 中的机器学习,Pedregosa 等人,JMLR 12,第 2825–2830 页,2011 年。
J. D. Hunter,“Matplotlib:2D 图形环境”,科学计算&工程,第 9 卷,第 3 期,第 90–95 页,2007 年。
瓦斯科姆,法学硕士,(2021 年)。seaborn:统计数据可视化。《开源软件杂志》,6 卷(60 期),3021 页,https://doi.org/10.21105/joss.03021
陈,t .,& Guestrin,C. (2016)。XGBoost:一个可扩展的树提升系统。第 22 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集(第 785–794 页)。美国纽约州纽约市:ACM。https://doi.org/10.1145/2939672.2939785
用 Python 快速而不下流地绘图
使用 Excel 最常见的借口之一是什么:“它有利于快速’ n '肮脏的阴谋”。如果您对 Excel 可视化数据感到满意,那就没问题。然而,这篇文章是关于用 Python 绘制数据的一种更快更脏的方法:)
绘制 x 与 y 数据的简单代码如下:
这个片段中的数据文件是一个两列文本文件。
这相对简单:我们导入相关模块,加载数据并绘制它。当我们定制细节时,代码的行数会增加。但现在这不重要,因为这是关于快速’ n '肮脏!虽然上面的代码并不复杂,但是许多人会发现每次都要输入代码是一件痛苦的事情。
将来你可以做两件事来节省时间和精力:
- 保留一份拷贝。将文件复制到某个特殊的地方,并在每次需要的时候复制它,这样你只需要改变文件名。
- 制作你自己的绘图库,这样你就可以为特定的数据文件提供绘图功能。这将需要一些时间和经验来建立,但从长远来看会使事情更有效率。
这两种方法中的第二种更适合快速绘制,但是你们中的一些人仍然会觉得为每个新的绘图输入任何东西很烦人。然而,还有的另一种 方法,它需要以下步骤(在 Windows 机器上):
- 创建一个包含以下代码的 python 文件,并将其保存在您喜欢的任何地方(但最好是容易记住的地方)。
找出与前面代码的不同之处
- 在包含以下代码的同一文件夹中创建一个. cmd 文件。确保编辑步骤 1 中 python 文件的路径(橙色)。
- 创建一个快捷方式。cmd 文件。右键单击快捷方式,选择属性,并在运行选项中选择最小化(这将在每次运行时最小化终端)。
- 打开一个文件资源管理器窗口,输入“shell:sendto”或只输入“sendto”。通过快捷方式复制。cmd 文件复制到“SendTo”文件夹。
全部完成!现在,当您右键单击数据文件时,可以将鼠标悬停在上下文菜单中的“发送到”上,然后单击。cmd 文件。在这个例子中,数据文件只有两列 x,y 数据。您可能需要对忽略文本进行一些调整,例如skip prows 参数。
现在,您有了一个非常好的快速而不麻烦的方法来可视化数据。使用 matplotlib 绘制它允许您放大特定区域进行检查,并且您可以快速保存一个看起来不错的图以供共享。您可以通过执行简单的“for 循环”来编辑用于绘制多个文件的代码。从这里,您可以随心所欲地绘制带有图例的多个轴,以跟踪您打开了哪些文件。
您可以针对特定的数据文件格式对代码进行进一步的调整。熊猫图书馆非常适合加载和检查。csv 文件。您还可以在“发送到”文件夹中为不同的文件类型或绘图方法设置一些不同的选项。
现在,在这一点上,你可能会想,我们正在通过快速’ n ‘脏,进入缓慢’ n '干净…但你需要记住,你只需要创建这些代码一次。在这之后,一切都是点击!像这样的工具一开始可能需要一点时间来制作,但是从长远来看,它们将会为您节省很多时间,并使可视化数据变得更加容易和灵活。尽情享受吧!
快速推进,反向传播的替代方案
斯科特·法尔曼加速梯度下降的想法
由于 20 世纪 80/90 年代的普通反向传播算法收敛缓慢,Scott Fahlman 发明了一种学习算法,称为 Quickprop [1],它大致基于牛顿法。在“N-M-N 编码器”任务等问题领域,他的简单想法优于反向传播(经过各种调整),即训练一个具有 N 个输入、M 个隐藏单元和 N 个输出的解码器/编码器网络。【Quickprop 专门解决的问题之一是找到特定领域的最佳学习速率,或者说:一种动态适当调整它的算法。
在本文中,我们将看看 Quickprop 背后的简单数学思想。我们将用 Python 和 PyTorch 实现基本算法和法尔曼建议的一些改进。
Giuseppe Bonaccorso 在发表的这篇有用的博客文章中已经介绍了算法的粗略实现和一些背景知识。我们将在理论和代码方面对此进行扩展,但如果有疑问,可以看看 Giuseppe 是如何解释的。
研究 Quickprop 的动机来自于撰写我上一篇关于“级联相关学习架构”的文章[2]。在那里,我用它来训练神经网络的输出和隐藏神经元,这是一个我后来才意识到的错误,我们也将在这里进行研究。
要继续阅读本文,您应该熟悉如何使用损耗梯度的反向传播来训练神经网络(截至 2020 年,这是一种广泛使用的方法)。也就是说,您应该了解梯度通常是如何计算的,并应用于网络的参数,以尝试迭代实现损耗收敛到全局最小值。
概观
我们将从 Quickprop 背后的数学开始,然后看看如何一步一步地实现和改进它。
为了使后续工作更容易,所有使用的方程和完成的推理步骤都比原始论文中解释得更详细。
快速推进背后的数学
通常用于神经网络的反向传播学习方法是基于这样的思想,即通过在其梯度的反方向上采取短的步骤,迭代地“向下”函数的斜率。
这些“短步骤”是这里的症结所在。它们的长度通常取决于一个学习率因子,并且故意保持很小以不超过潜在的最小值。
回到法尔曼开发 Quickprop 的时候,选择一个好的学习速率是一个大问题。正如他在他的论文中提到的,在性能最好的算法中,科学家“通过眼睛”(即手动和基于经验)选择学习速率。[1]
面对这种情况,法尔曼提出了一个不同的想法:解决一个更简单的问题。
最小化损失函数**【L】**,特别是对于深度神经网络,在分析上(即,在整个域上以一般方式)会变得极其困难。
例如,在反向传播中,我们只是逐点计算,然后在正确的方向上迈出小步。如果我们知道函数的“地形”通常是什么样子,我们就可以直接“跳到”最小值。
但是,如果我们可以用一个更简单的,我们知道它的地形的形式来代替损失函数,会怎么样呢?这正是 Fahlmans 在 Quickprop 中采用的假设:他假定 L 可以用一个简单的正方向开口的抛物线来近似。这样,计算(抛物线的)最小值就像找到一条线与 x 轴的交点一样简单。
如果该点还不是损失函数的最小值,那么下一条抛物线可以从该点开始近似计算,如下图所示。
抛物线拟合到原始函数,并向其最小值前进一步。从那里开始,拟合下一条抛物线,然后进行下一步。两条虚线是抛物线的当前点和前一个驻点。(图片由作者提供)
那么…我们究竟怎样才能近似 L ?简单——使用泰勒级数和一个小技巧。
注意,对于下面的等式,我们认为权重向量 w 的分量是要独立训练的,所以 w 的意思是看做标量。但是我们仍然可以利用 GPU 的 SIMD 架构,使用组件式计算。
我们从 L 的二阶泰勒展开开始,给出一条抛物线(没有误差项):
(要了解这是如何创建的,请查看上面链接的关于泰勒级数的维基百科文章——这很简单,只需将 L 输入到一般泰勒公式中,直到第二项,然后放弃其余部分。)
我们现在可以根据重量差异定义重量的更新规则,并将其输入到😗*
Quickprop 现在使用差商进一步线性逼近(这就是上面提到的小技巧):**
利用这一点,我们可以将泰勒多项式改写为“快速推进”调整版本,并构建其梯度:
最后一个方程可以用来计算抛物线的驻点:
****就是这样!现在,为了综合考虑,给定以前的重量、以前的重量差以及以前和当前重量下的损耗斜率,Quickprop 只需通过以下方式计算新的重量:
把它编成代码
在开始实际的 Quickprop 实现之前,让我们导入一些基础库:
有了前面数学等式的最后两行,我们可以从 Quickprop 开始!如果您阅读了关于级联相关的第一篇文章,您可能已经熟悉了这一点——在这里,我们将首先关注算法的基本部分,并在最后将它们放在一起。
注意,我们使用 PyTorch 为我们进行自动梯度计算。我们还假设已经预先定义了激活和损失函数。
这是一个学习时期最简单的快速推进版本。要真正利用它,我们必须运行几次,看看损失是否收敛(我们稍后会谈到这一点)。
但是,这种实现在几个方面存在缺陷,我们将在下面几节中研究并解决这些问题:
- 我们实际上没有初始化任何
..._prev
变量——在上一篇文章中,我用 1 静态地初始化了它们,但这也不是一个好主意(见下一点) - 权重增量变量可能会停留在零值上,因为它在自己的更新步骤中被用作一个因子
- 如果梯度“爆炸”,实现可能会过冲或通常无法收敛
- 如果梯度在一次迭代中不变,它将导致除以零
改进:通过梯度下降初始化
我们可以应用的第一个简单的修正是使用梯度下降(具有非常小的学习率)来准备dw_prev
和dL_prev
变量。这将使我们对损失函数地形有一个很好的初步了解,并在正确的方向上启动 Quickprop。
再次使用 pytorch 很容易实现梯度下降——我们还将利用这个机会对上面的代码进行一点重构:
改进:有条件的渐变添加
有时,当使用快速推进抛物线法时,重量增量变得非常小。为了防止梯度不为零时发生这种情况,法尔曼建议有条件地将斜率添加到权重增量中。
这个想法可以这样描述:无论如何如果你一直朝着那个方向前进,那就走得更远,但是如果你之前的更新把你送到了相反的方向,就不要再往前推了(防止振荡)。
通过一小段 decider 代码,这可以很容易地实现:
有了这个,我们就可以把它全部放进一个小函数里:
改进:最大生长因子
第二步,我们将修复一些函数特征附近的爆炸权重增量问题(例如,奇点附近)。
为此,Fahlman 建议,如果权重更新大于上次权重更新乘以最大增长因子,则截取权重更新:
改进:防止被零除
在某些情况下,先前和当前计算的斜率可以相同。结果是,我们将尝试在权重更新规则中被零除,并且之后将不得不继续使用NaN
的,这显然破坏了训练。
这里简单的解决方法是做一个梯度下降步骤。
遵守两个更新规则:
除了最后一个因素,他们看起来很相似,不是吗?
这意味着我们可以再次无分支(即,为我们节省一些 if 子句),保持元素方式,并将所有内容打包在一个公式中:
细心的读者可能注意到了我们上面使用的“学习率”因素——一个我们认为可以去掉的参数…
嗯,实际上我们多少去掉了,或者至少我们确实去掉了在培训过程中必须调整学习率的问题。快速推进学习率可以在整个过程中保持固定。开始时,每个域只需调整一次。实际的动态步长通过抛物线跳跃来选择,而抛物线跳跃又严重依赖于当前和最后计算的斜率。
如果你认为这听起来非常熟悉反向传播学习率优化器的工作方式(想想:动量),那你就对了。本质上,Quickprop 实现了与它们非常相似的东西——只是它的核心没有使用反向传播。
回到代码上来:由于我们之前已经实现了梯度下降,我们可以在此基础上构建并尽可能多地重用:
把所有的放在一起
有了所有这些功能,我们可以把它们放在一起。仍然需要的样板代码只是进行初始化和检查每个时期平均损失的收敛。
警告
Quickprop 有一个大大降低其实用性的主要警告:我们使用的数学“技巧”,即损失函数的二阶导数与简单差商的近似依赖于该二阶导数是连续函数的假设。
这不适用于激活功能,例如整流线性单元,简称 ReLU。二阶导数是不连续的,并且算法的行为可能变得不可靠(例如,它可能发散)。
回顾一下我之前的文章关于级联相关的实现,我们使用 Quickprop 训练网络的隐藏单元,并使用协方差函数作为一种方法来估计该过程中的损失。然而,协方差(如那里实现的)被包装在绝对值函数中。即它的二阶导数是不连续的,因此不应使用 Quickprop。仔细阅读 Fahlman 等人的级联相关论文[2]的读者可能已经注意到,他们实际上是使用梯度上升来计算这个最大协方差。
除此之外,Quickprop 似乎在某些领域比其他领域提供了更好的结果。Brust 等人的有趣总结表明,与基于反向传播的技术相比,它在一些简单的图像分类任务(对基本形状进行分类)上取得了更好的训练结果,而同时在更现实的图像分类任务上表现较差[3]。
我没有在这方面做过任何研究,但我想知道这是否意味着 Quickprop 可能在更少模糊和更结构化的数据上工作得更好(想想商业环境中使用的数据框架/表格)。这肯定是一个有趣的研究。
摘要
本文介绍了 Scott Fahlman 改进反向传播的想法。我们看了一下数学基础和可能的实现。
现在开始在你自己的项目中尝试吧——我很想看看 Quickprop 能有什么用途!
如果你想看看 Quickprop 的变体,请查看我的关于级联相关学习架构的系列文章。
该系列的所有成品笔记本和代码也在 Github 上可用。请留下反馈并提出改进建议。
最后,如果你想支持这篇和类似精彩文章的创作,你可以注册一个中级会员和/或关注我的账户。
[1] S. E. Fahlman,反向传播网络学习速度的实证研究 (1988),卡内基梅隆大学计算机科学系
[2] S. E. Fahlman 和 C. Lebiere,级联相关学习架构 (1990),神经信息处理系统的进展(第 524-532 页)
[3] C. A. Brust,S. Sickert,M. Simon,E. Rodner 和 J. Denzler,《既不快速也不恰当——学习深度神经网络的 QuickProp 评估》 (2016),arXiv 预印本 arXiv:1606.04333
Python 中的快速排序
Python 中“快速排序”的介绍
排序算法是计算机科学中最重要的算法之一。排序涉及对列表或数组中的元素进行排序的任务。排序最常见的用法是数字排序和字典排序。在这篇文章中,我们将讨论如何在 python 中实现一个“快速排序”算法,我们将使用它对列表进行数字排序。
我们开始吧!
“快速排序”算法的基本过程是划分。分区的工作方式是首先选择一个枢轴。枢轴选项包括:
- 第一元素
- 最后一个元素
- 随机元素
- 中间分子
在选择枢轴后,我们根据枢轴值划分数组的元素。也就是说,对于一个输入数组和 pivot,我们将所有小于 pivot 的元素放在 pivot 之前,将所有大于 pivot 的元素放在 pivot 之后。为了看到这一点,让我们考虑下面的列表:
让我们选择最后一个元素“3”作为我们的轴心:
接下来,我们创建两个子列表,左边的列表包含小于主元的值,右边的子列表包含大于子列表的值:
然后,我们找到子列表的中枢,并重复划分过程。左侧子列表的枢轴是 1,右侧子列表的枢轴是 6:
接下来,我们围绕它们的支点划分子列表:
最后,让我们为最后一组子列表选择枢轴,左边 6 个,右边 8 个:
让我们完成最后一个分区:
我们最终得到了下面的排序列表:
让我们看看如何用 python 实现这个算法。首先,让我们定义我们的配分函数。我们的函数将接受一个列表,一个“低”变量和一个“高”变量。“低”是较小元素的索引(我们将在列表中从这里开始),而“高”是透视的索引,这将是最后一个元素。我们将最小元素的索引初始化为“低”-1,并将轴心定义为最后一个元素的值:
def partition(list,low,high):
i = (low - 1)
pivot = array[high]
接下来,我们将编写一个从“低”到“高”迭代的“for-loop”:
def partition(list,low,high):
i = (low - 1)
pivot = array[high]
for j in range(low, high):
接下来,我们检查“for-loop”中当前索引处的值是否小于或等于 pivot。如果当前值小于轴心值,我们将递增较小元素的索引:
def partition(input_list,low,high):
i = (low - 1)
pivot = input_list[high]
for j in range(low, high):
if input_list[j] <= pivot:
i = i + 1
input_list[i], input_list[j] = input_list[j], input_list[i]
否则,如果当前值大于中枢,我们将较大的值与中枢交换。我们还返回索引:
def partition(input_list,low,high):
i = (low - 1)
pivot = input_list[high]
for j in range(low, high):
if input_list[j] <= pivot:
i = i + 1
input_list[i], input_list[j] = input_list[j], input_list[i]
input_list[i+1],input_list[high] = input_list[high],input_list[i+1]
return (i+1)
接下来,让我们定义我们的“快速排序”函数。我们首先检查“低”的值是否小于“高”,如果条件为真,我们定义分区索引:
def quickSort(input_list, low, high):
if low < high:
partition_index = partition(input_list,low,high)
然后我们递归调用“快速排序”并在分区前对元素进行排序:
def quickSort(input_list, low, high):
if low < high:
partition_index = partition(input_list,low,high)
quickSort(input_list, low, partition_index - 1)
并对分区后的元素进行排序:
def quickSort(input_list, low, high):
if low < high:
partition_index = partition(input_list,low,high)
quickSort(input_list, low, partition_index - 1)
quickSort(input_list, partition_index + 1, high)
我们现在可以测试我们的“快速排序”功能。让我们用我们在最初的例子中使用的列表来测试它:
input_l = [9, -3, 5, 2, 6, 8, -6, 1, 3]
让我们定义我们的“高”变量,它将是列表的长度:
list_length = len(input_l)
“低”变量将是 0,因为在 python 中列表是零索引的。现在让我们用我们的列表、我们的“低”值(0)和“list _ length”-1 来调用“快速排序”方法:
quickSort(input_l, 0, list_length -1)
现在我们的数组应该排序了。让我们打印我们的数组:
print(input_l)
我们看到我们的函数成功地对列表进行了排序。我就讲到这里,但是我鼓励你自己去研究代码。
结论
总之,在这篇文章中,我们讨论了快速排序算法,并展示了如何用 python 实现它。如果你有兴趣学习更多关于排序算法的知识,我鼓励你去探索一下 realpython.com,它涉及到其他排序算法,比如“合并排序”、“插入排序”和“冒泡排序”。我希望你觉得这篇文章有用/有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!
快速入门:Kubernetes 上的 Apache Spark
使用 Kubernetes 的本地 Apache Spark 操作器,让您的大负载平稳运行
介绍
Kubernetes 的 Apache Spark 操作员
自 2014 年由谷歌推出以来,Kubernetes 与 Docker 本身一起获得了很大的人气,自 2016 年以来,它已成为事实上的容器编排者,并成为市场标准。在所有主要云中提供云管理版本。【1】【2】【3】(包括数字海洋阿里巴巴)。
随着这种流行,出现了 orchestrator 的各种实现和用例,其中包括使用容器的有状态应用和数据库的执行。
托管编排数据库的动机是什么?这是一个很好的问题。但是让我们关注一下在 Kubernetes 上运行工作负载的 Spark 操作符。
一个本地 Spark 运营商的想法在 2016 年出现,在此之前你不能本地运行 Spark 作业,除非是一些的 hacky 替代品,比如在 Kubernetes 内部运行 Apache Zeppelin 或者在 Kubernetes 内部创建你的 Apache Spark 集群(来自 GitHub 上的官方 Kubernetes 组织)引用独立模式下的Spark workers。
然而,本地执行更有意思的是利用负责分配资源的 Kubernetes 调度器,提供弹性和更简单的接口来管理 Apache Spark 工作负载。
考虑到这一点, Apache Spark Operator 开发得到关注,合并发布为 Spark 版本 2.3.0 于 2018 年2 月推出。
如果你渴望阅读更多关于 Apache Spark 提案的内容,你可以前往 Google Docs 上发布的设计文档。
为什么是 Kubernetes?
由于公司目前正在寻求通过广为流传的数字化转型来重塑自己,以提高竞争力,最重要的是,在日益活跃的市场中生存下来,因此常见的方法包括大数据、人工智能和云计算【1】【2】【3】。
关于在大数据环境中使用云计算而不是本地服务器的优势的有趣对比,可以在 Databricks 博客上阅读,该博客是由 Apache Spark 的创建者创建的公司。
随着我们看到云计算的广泛采用(即使是那些能够负担得起硬件并在本地运行的公司),我们注意到大多数云实施都没有 Apache Hadoop ,因为数据团队(BI/数据科学/分析)越来越多地选择使用像 Google BigQuery 或 AWS Redshift 这样的工具。因此,仅仅为了使用 YARN 作为资源管理器而加速运行 Hadoop 是没有意义的。
另一种方法是使用 Hadoop 集群提供者,如 Google DataProc 或 AWS EMR 来创建临时集群。仅举几个例子。
为了更好地理解 Spark Operator 的设计,GitHub 上来自 GCP 的 doc 是显而易见的。
让我们动手吧!
预热发动机
既然话已经传开了,那就让我们把它弄到手,展示一下发动机的运转吧。为此,让我们使用:
一旦安装了必要的工具,就有必要在PATH
环境变量中包含 Apache Spark path,以简化 Apache Spark 可执行文件的调用。只需运行:
export PATH=${PATH}:/path/to/apache-spark-X.Y.Z/bin
创建 Minikube“集群”
最后,为了拥有一个 Kubernetes“集群”,我们将启动一个minikube
,目的是运行一个来自 Spark 库的示例,名为SparkPi
,作为演示。
minikube start --cpus=2 \
--memory=4g
建立码头工人形象
让我们使用 Minikube Docker 守护进程来不依赖于外部注册表(并且只在 VM 上生成 Docker 映像层,便于以后的垃圾处理)。Minikube 有一个让我们生活更轻松的包装:
eval $(minikube docker-env)
配置完守护进程环境变量后,我们需要一个 Docker 映像来运行作业。Spark 仓库中有一个 shell 脚本来帮助解决这个问题。考虑到我们的PATH
已经正确配置,只需运行:
docker-image-tool.sh -m -t latest build
*参考消息:*这里的-m
参数表示一个迷你库的构建。
让我们快速执行 SparkPi,使用与 Hadoop Spark 集群 spark-submit 相同的命令。
然而,Spark Operator 支持使用 CRD 、用“Kubernetes 方言”定义作业,下面是一些例子——稍后介绍。
向洞里开火!
中间是 Scala 版本和的差距。jar 当您使用 Apache Spark 版本进行参数化时:
spark-submit --master k8s://https://$(minikube ip):8443 \
--deploy-mode cluster \
--name spark-pi \
--class org.apache.spark.examples.SparkPi \
--conf spark.executor.instances=2 \
--executor-memory 1024m \
--conf spark.kubernetes.container.image=spark:latest \
local:///opt/spark/examples/jars/spark-examples_2.11-X.Y.Z.jar # here
新的是:
--master
:在 URL 中接受前缀k8s://
,用于 Kubernetes 主 API 端点,由命令https://$(minikube ip):8443
公开。BTW,万一你想知道,这是一个 shell 命令替换;--conf spark.kubernetes.container.image=
:配置 Docker 镜像在 Kubernetes 中运行。
样本输出:
...19/08/22 11:59:09 INFO LoggingPodStatusWatcherImpl: State changed,
new state: pod name: spark-pi-1566485909677-driver namespace: default
labels: spark-app-selector -> spark-20477e803e7648a59e9bcd37394f7f60,
spark-role -> driver pod uid: c789c4d2-27c4-45ce-ba10-539940cccb8d
creation time: 2019-08-22T14:58:30Z service account name: default
volumes: spark-local-dir-1, spark-conf-volume, default-token-tj7jn
node name: minikube start time: 2019-08-22T14:58:30Z container
images: spark:docker phase: Succeeded status:
[ContainerStatus(containerID=docker://e044d944d2ebee2855cd2b993c62025d
6406258ef247648a5902bf6ac09801cc, image=spark:docker,
imageID=docker://sha256:86649110778a10aa5d6997d1e3d556b35454e9657978f3
a87de32c21787ff82f, lastState=ContainerState(running=null,
terminated=null, waiting=null, additionalProperties={}),
name=spark-kubernetes-driver, ready=false, restartCount=0,
state=ContainerState(running=null,
terminated=ContainerStateTerminated(containerID=docker://e044d944d2ebe
e2855cd2b993c62025d6406258ef247648a5902bf6ac09801cc, exitCode=0,
finishedAt=2019-08-22T14:59:08Z, message=null, reason=Completed,
signal=null, startedAt=2019-08-22T14:58:32Z,
additionalProperties={}), waiting=null, additionalProperties={}),
additionalProperties={})]19/08/22 11:59:09 INFO LoggingPodStatusWatcherImpl: Container final
statuses: Container name: spark-kubernetes-driver Container image:
spark:docker Container state: Terminated Exit code: 0
为了查看作业结果(以及整个执行过程),我们可以运行一个kubectl logs
,将驱动程序 pod 的名称作为参数传递:
kubectl logs $(kubectl get pods | grep 'spark-pi.*-driver')
这将产生输出(省略了一些条目),类似于:
...
19/08/22 14:59:08 INFO TaskSetManager: Finished task 1.0 in stage 0.0
(TID 1) in 52 ms on 172.17.0.7 (executor 1) (2/2)
19/08/22 14:59:08 INFO TaskSchedulerImpl: Removed TaskSet 0.0, whose
tasks have all completed, from pool19/08/22 14:59:08 INFO
DAGScheduler: ResultStage 0 (reduce at SparkPi.scala:38) finished in
0.957 s
19/08/22 14:59:08 INFO DAGScheduler: Job 0 finished: reduce at
SparkPi.scala:38, took 1.040608 s Pi is roughly 3.138915694578473
19/08/22 14:59:08 INFO SparkUI: Stopped Spark web UI at
[http://spark-pi-1566485909677-driver-svc.default.svc:4040](http://spark-pi-1566485909677-driver-svc.default.svc:4040)
19/08/22 14:59:08 INFO KubernetesClusterSchedulerBackend: Shutting
down all executors
19/08/22 14:59:08 INFO
KubernetesClusterSchedulerBackend$KubernetesDriverEndpoint: Asking
each executor to shut down
19/08/22 14:59:08 WARN ExecutorPodsWatchSnapshotSource: Kubernetes
client has been closed (this is expected if the application is
shutting down.)
19/08/22 14:59:08 INFO MapOutputTrackerMasterEndpoint:
MapOutputTrackerMasterEndpoint stopped!
19/08/22 14:59:08 INFO MemoryStore: MemoryStore cleared
19/08/22 14:59:08 INFO BlockManager: BlockManager stopped
19/08/22 14:59:08 INFO BlockManagerMaster: BlockManagerMaster stopped
19/08/22 14:59:08 INFO
OutputCommitCoordinator$OutputCommitCoordinatorEndpoint:
OutputCommitCoordinator stopped!
19/08/22 14:59:08 INFO SparkContext: Successfully stopped SparkContext
19/08/22 14:59:08 INFO ShutdownHookManager: Shutdown hook called
19/08/22 14:59:08 INFO ShutdownHookManager: Deleting directory
/tmp/spark-aeadc6ba-36aa-4b7e-8c74-53aa48c3c9b2
19/08/22 14:59:08 INFO ShutdownHookManager: Deleting directory
/var/data/spark-084e8326-c8ce-4042-a2ed-75c1eb80414a/spark-ef8117bf-90
d0-4a0d-9cab-f36a7bb18910
...
结果出现在:
19/08/22 14:59:08 INFO DAGScheduler: Job 0 finished: reduce at SparkPi.scala:38, took 1.040608 s Pi is roughly 3.138915694578473
最后,让我们删除 Minikube 生成的 VM,以清理环境(除非您想继续玩它):
minikube delete
临终遗言
我希望您的好奇心得到了的激发,并且为您的大数据工作负载提出了一些进一步开发的想法。如果你有任何疑问或建议,请在评论区分享。
原载于 2020 年 5 月 21 日https://ma Cunha . me。
快速启动:AWS Lambda 上的空间在 10 分钟内启动并运行
使用 spaCy 进行无服务器计算的简单方法
让我们信守承诺,先把事情做好。如果您想进一步阅读,快速入门部分将提供进一步的讨论。我希望这种安排能节省你的时间。
快速入门:循序渐进
I .为空间设置 Lambda 层
- 登录 AWS 帐户。创建新的 Lambda 函数。选择 Python 3.8,并使用默认设置。
- 进入λ*【配置】【设计器】,点击图层*。然后点击下方面板上的*【添加图层】*。
图一。AWS Lambda 设计器(截图)|作者图片
- 选择*【指定 ARN】。使用下面的 ARN 作为空位,然后点击【添加】*
arn:aws:lambda:us-west-1:770693421928:layer:Klayers-python38-spacy:30
图二。Lambda ->添加图层(截图)|作者图片
- 重复上述步骤,并添加语言模型层,使用以下 ARN。
arn:aws:lambda:us-west-1:770693421928:layer:Klayers-python38-spacy_model_en_small:1
- 图层完成后应该是这样的。
图三。空间的 AWS Lambda 图层(截图)|作者图片
二。调整和运行 Lambda
- 为 Lambda 中的空间分配更多内存。为内存选择 512 MB,为超时选择 10 秒。
图 4。AWS Lambda 调优(截图)|图片作者
- 将空间导入 Lambda。让我们编写一个 Hello World 函数来测试我们的层是否正常工作。
import json
**import spacy**def lambda_handler(event, context):
**nlp = spacy.load("/opt/en_core_web_sm-2.2.5/en_core_web_sm/en_core_web_sm-2.2.5")**
doc = nlp("Hello World from spaCy") return {
'statusCode': 200,
'body': json.dumps(doc.text)
}
- 结果应该是这样的。您可能会注意到,默认的 128 MB 内存分配是不够的,因为 Hello World 程序使用了 200 MB。
图五。AWS Lambda 执行结果(截图)|图片作者
恭喜你!现在 spaCy 已经可以使用了。如果你已经得到了你所需要的,请随意回到你忙碌的日子。
如果你有时间,我想分享一下我在 NLP(自然语言处理)方面的经验。
我为什么选择空间
其实我第一次用 TextBlob 开始 NLP(自然语言处理),感觉像是在一个阳光明媚的下午也能学到东西。TextBlob 有一个方便的名词短语提取器,它可以轻松地进行情感分析。我在一个数据可视化项目中使用了 TextBlob,很快就能得到一些结果,这很有趣。
从四月份开始,我开始从事一个计算诗歌项目,它需要对复杂的文学作品进行深入的分析。我发现 TextBlob 不够复杂,无法处理长而复杂的结构。就在那时,我转到了西班牙。
spaCy 旨在帮助您做真正的工作——构建真正的产品,或收集真正的见解。图书馆尊重你的时间,并尽量避免浪费时间。它易于安装,其 API 简单且高效。我们喜欢把 spaCy 看作是自然语言处理轨道上的 Ruby。— spacy.io
我不确定 Ruby on Rails 的类比是否仍然有意义,但是 spaCy 对我来说工作得很好。看看太空宇宙,印象相当深刻。
图六。spaCy Universe |图片来自 spaCy.io
AWS Lambda & spaCy
我的目标是开发一个基于云的应用程序,所以我需要在云上运行 spaCy。Lambda 是 AWS 上最具成本效益的选择,因为它只对请求进入的时间计费。AWS 上的虚拟机将对其所有正常运行时间收费。作为一个强大的软件包,spaCy 非常大,它的默认发行版超过了 Lambda 要求的 250 MB 的限制。
人们已经付出了额外的努力来减小 spaCy 的大小,也有 DIY 说明来将 spaCy 放入 Lambda,但如果你决心要实现它,这需要一些认真的努力。
幸运的是, Keith Rozario 做了一个 ARN 准备用作 AWS 层。这是您在本文的快速入门部分看到的内容。如果你真的用秒表计时,你的结果可能会低于 10 分钟。
干杯!
古怪的 Keras:R 中 Keras 的定制和非对称损失函数
实践教程
[图片由蒙提洛夫在 unsplash 上拍摄]
TL;DR——本教程向您展示如何使用包装器函数来构建自定义损失函数,该函数采用除 y_pred 和 y_true 之外的参数用于 r 中的 Keras。请参见线性指数误差(LINEXE)和加权最小二乘误差(WLSE)的示例代码。
背景
在统计学习中,损失函数是将非正式的哲学建模目标翻译成正式的数学语言(Hennig & Kutlukaya,2007)。因此,估算中损失函数的选择有些主观,取决于模型的具体应用或使用时的决策。以下是一些需要考虑的损失函数:
对称损失
- 均方误差(MSE) 是简单最小二乘回归中常见的目标函数,它是一个凸函数,通过平方误差来强调远离大部分数据的点。MSE 对较大误差的惩罚大于较小误差;该函数在尾部比在中部更陡。
- 对于较小的 x,对数双曲余弦(LOGCOSH) 或 log(cosh(x))近似为 1/2(x^2,对于较大的 x,【abs(x) — log(2)】。因此,LOGCOSH 的工作方式与 MSE 非常相似,但受偶然的非常不正确的预测的影响较小,在这方面,它类似于平均绝对误差(MAE) 。当较大值的估计误差不需要像 MSE 中那样通过平方来惩罚时,LOGCOSH 和 MAE 是有用的。
- 均方百分比误差(MSPE) 在相对误差更令人感兴趣的问题中很有用(例如,10/100 的误差比 10/100,000 的误差更令人感兴趣)。然而,MSPE 偏向于较低的预测值,不适合于数据为正偏差的问题(例如,流量总是> =0)。
这是为 MSPE 编写的自定义代码。注意,函数只取 y_true 和 y_pred。
不对称损失
当低估和高估相同的绝对误差时,对称函数产生相同的损失。然而,不对称损失函数对不同的损失方向应用不同的惩罚。例如,在水文预测中,不对称的损失函数会迫使模型在洪水时高估流量,而在干旱时低估流量,而不是相反。这种方法导致水资源管理者做出更保守的决策,因为模型预测了更多的极端洪水和干旱。
首先,需要一个简单的分类模型将观测值标记为洪水(洪水1)和干旱(洪水0)。对于每个流域,整个记录的平均降水量可以指定为一个硬阈值;如果某个月的降雨量低于这个数值,这种现象被称为“干旱”,如果高于这个数值,则被称为“洪水”给定这个名称,现在,不同的损失可以应用于数据中不同位置的预测误差。
Keras 不对称损失:用包装器向损失函数传递附加参数
让我们从 WLSE(等式 1)开始,其中α和β对于标记为洪水和干旱的观测值具有不同的值。因此,我们将αd、βd、αf 和βf 作为损失函数的输入。
情商。一
现在,快克;Keras 中的损失只能接受两个参数:y_true 和 y_pred,它们分别是目标张量和模型输出张量。然而,如果我们希望损失依赖于其他张量,如α和β向量,我们需要使用函数闭包。这里,wlse loss 函数接受我们想要的任何参数,包装函数返回仅依赖于 y_true 和 y_pred 的函数。
这是与 LINEXE 相同的概念:
LINEXE(等式 2)取决于 phi,对于标记为洪水和干旱的观测值,phi 具有不同的值。因此,我们将 phid 和 phif 作为损失函数的输入。
情商。2
…包装材料:
现在,继续建模。首先,我们定义神经网络模型的架构:
*“trainsetpv”是训练集预测变量。
接下来,我们必须编译并拟合模型。对于对称损耗,我们有:
*“trainsetrv”是训练集响应变量。
…对于对称损耗,我们的工作已经完成!
在不对称损失中,由于我们现在已经标记了观测值(洪水或干旱),我们需要这种指定来正确地与每个 y_true 和 y_pred 对齐。因此,我们不能再使用在不改变加扰算法以适应标签的情况下对数据进行加扰的迷你批次训练方法。迷你批次的大小由验证分割(例如,0.2)决定,并且仅帮助加速模型训练。为了在没有迷你批次的情况下仍然做出准确的预测,我们可以简单地增加训练时段,并且通过设置 shuffle=FALSE,我们不再有洪水和干旱标签与数据不一致的问题。
现在,预测可以来自:
*“testsetpvs”是测试集预测变量。
示例结果
图 1 显示了加利福尼亚州一个河流流域的流量预测,即北福克坝的美国河(White,E. 2020)。我们可以看到 WLSE 和 LINEXE 的不对称损失,预测总是高估洪水而低估干旱!这是我们希望发生的。这样我们可以做出更保守的决定,并为更极端的情况做好准备。
图一。North Fork 大坝美国河流流量的神经网络预测[图片由作者用 ggplot2 制作]。
结论
Keras 中的损失只能接受两个参数:y_true 和 y_pred,它们分别是目标张量和模型输出张量。然而,如果我们希望损失依赖于其他张量——如不对称损失的情况——我们需要使用函数闭包。这里,loss 函数接受我们想要的任何参数,并返回仅依赖于 y_true 和 y_pred 的函数。因此,命名为包装器。
一般来说,选择损失函数的灵活性在基于风险的决策中特别有用,在这种情况下,建模的目的是准确预测概率分布,特别是在可能发生高成本后果的尾部。不对称损失函数在这方面证明是有用的。
参考资料:
C.关于损失函数设计的一些想法(2007)。REVSTAT–统计杂志,5 (1),19–39。
E.White,无资料流域未受损流量预测的统计学习 (2020)。博士论文。
不要试图预测市场
为什么 99.99%的机器学习算法从未真正发挥作用
我经常在我的 Medium Daily Digest 电子邮件中收到相同类型的文章,标题有趣,声称可以用机器学习来预测股市。通常,他们以近乎完美的准确性结束一些极其精确的模型。我承认,这是非常令人兴奋的,也是一个了解这些模型如何工作的好机会,但是在现实世界中使用这些模型是自找麻烦。
特斯拉公司的机器学习模型接近完美的准确性。
为了理解为什么这些模型在市场上如此不准确,我将首先解释为什么,然后用 Python 研究一些 LSTM 张量流模型来进一步解释我的推理。
为什么市场如此难以预测?
为了回答这个问题,我们先从基础说起。股票市场本质上是投资者的市场,由供求关系驱动。不管听起来多么简单,实际上有无数的因素在起作用。这就是为什么几乎所有能想到的资料都显示,买入并持有策略远比试图把握时机或预测市场更省时、更有利可图。
现在,有了这个说法,你可以从技术上创建一个模型,将所有已知的影响市场的因素考虑在内。然而,绝大多数市场因素实际上是不可能事先知道的,比如自然灾害、流行病和政治动向。哦,还有,市场有时完全是不理性的,所以祝你好运,努力跟上它。
但是你看,即使你能够成功地预测或准确地把握市场时机,其他人也会模仿你的策略,最终导致市场以不同于你预测的方式做出反应。这可能有点令人困惑,所以我将在这里打破它。
假设你有一个预测 XYZ 公司未来股票价格的模型,那么你会用这些知识做什么呢?你很可能会试图用它来赚取大量的利润,促使你在实际市场中创造无限量的买卖信号。所有能接触到这个模型的人也一样。所有这些交易的结果是什么?它会以一种你的模型无法预测的方式影响 XYZ 股票的价格,无论它是暴涨还是暴跌;因此,本质上这里的悖论是,即使使用模型的预测,你也在直接影响未来,以这样或那样的方式使预测过时。
有机会,你可以预测或更确切地说,预测市场的一些趋势,以获得更高的市场成功机会,因为这基本上是市场研究人员和分析师所做的,但这些预测更接近于有根据的猜测,而不是 99%准确的精确预测。此外,市场未来将如何变化的置信区间太大,甚至无法做出简明的预测。
用 Python 中的 TensorFlow 创建 LSTM 模型
虽然在市场上使用这样的模型是不明智的,但创建机器学习模型是一种学习和熟悉模型如何工作以及它们潜在能力的好方法。遵循本文的其余部分,不仅要创建一个神经网络来“预测”TSLA 的价格,而且要理解它的缺点在哪里。
导入模块并设置参数
首先,您需要导入依赖项,并设置程序其余部分所需的参数。我们将对 LSTM 模型和 Scikit-Learn 使用 TensorFlow 来测试其准确性。
获取数据并对其进行整形以在模型中工作!
首先,我们必须使用 pandas_datareader 从 Yahoo Finance 读入数据。接下来,为了让 LSTM 模型工作,必须以正确的方式对数据进行预处理。我们可以使用 Scikit-Learn 中的 MinMaxScaler 和模块 NumPy 来实现这一点。我们还必须创建 x_train 和 y_train 数据列表,以发送到下一部分中的模型。
拟合模型并获得预测。
在这里,我们必须构建、编译和训练 LSTM 模型,以便获得最终的预测。幸运的是,TensorFlow 和 Scikit-Learn 让这变得非常简单。模型生成后,我们可以在测试数据上测试它,以获得我们的最终预测,看看它有多准确。对于这个特定的模型,我将 epochs 设置为 5,但是您可以更改它来查看它如何影响模型的输出。
使用预测来实际测试模型。
现在有趣的部分来了。我们成功地使用 LSTM 模型来“预测”股票价格,并最终找到了我们的准确性。在代码的这一部分,我们绘制了训练数据、测试数据和预测,并收到了一系列其他指标,如预测日常运动的准确性、下一个交易日的预测价格以及模型的均方根误差和测试均方误差。
TSLA 的 LSTM 模式
乍一看,这个模型似乎非常好。它甚至预测了 2020 年前所未有的冠状病毒大崩溃!
但是,当你进一步滚动时,你会看到模型只是跟踪最后一天的收盘价,因为它已经决定简单地跟踪昨天的收盘价是预测明天价格的“最好”方法。
LSTM 模型的特写视图
如果你回头看看我们之前找到的统计数据,你可以证实这一点(我在下面附上了一个截图)。预测每日走势的准确率为 48.19%,甚至低于抛硬币的准确率!!
LSTM 模型的结果
这个故事的寓意是:尽你所能预测股市,但千万不要在现实生活中使用它。非常感谢你的阅读,我希望你喜欢!
免责声明:本文材料纯属教育性质,不应作为专业投资建议。自行决定投资。
如果你喜欢这篇文章,看看我下面的其他文章吧!
了解如何在不到 3 分钟的时间内解析顶级分析师的数千条建议!
towardsdatascience.com](/parse-thousands-of-stock-recommendations-in-minutes-with-python-6e3e562f156d) [## 用 Python 制作股票筛选程序!
学习如何用 Python 制作一个基于 Mark Minervini 的趋势模板的强大的股票筛选工具。
towardsdatascience.com](/making-a-stock-screener-with-python-4f591b198261) [## 在 3 分钟内创建一个财务 Web 应用程序!
了解如何使用 Python 中的 Streamlit 创建技术分析应用程序!
towardsdatascience.com](/creating-a-finance-web-app-in-3-minutes-8273d56a39f8)
Quora 问题对:使用暹罗网络检测文本相似性。
Quora 相似问题:使用暹罗网络检测文本相似性。
E ver 想知道如何使用深度学习计算文本相似度?我们的目标是开发一个模型来检测文本之间的文本相似性。我们将使用 Quora 问题对数据集。
【https://unsplash.com/photos/askpr0s66Rg
要求
- Python 3.8
- sci kit-学习
- 张量流
- 天才论
- NLTK
资料组
让我们首先从探索数据集开始。我们的数据集包括:
- id: 一对训练集的 id
- qid1,qid2 :问题的唯一 id
- 问题 1 :问题 1 的文本
- 问题 2 :问题 2 的文本
- is _ duplicate:1如果问题 1 和问题 2 含义相同,否则 0
我们数据集的预览
数据预处理
像任何机器学习项目一样,我们将从预处理数据开始。让我们首先加载数据,并将问题 1 和问题 2 组合起来形成词汇表。
def load_data(df):
question1 = df['"question1"'].astype(str).values
question2 = df['"question2"'].astype(str).values
# combined: to get the tokens
df['combined'] = df['"question1"'] + df['"question2"']
labels = df['"is_duplicate"'].values
return question1, question2, labelsquestion1, question2, labels = load_data(df)
question1 = list(question1)
question2 = list(question2)
combined = question1 + question2df.head()
我们修改过的数据框
我们也将清理文本一点。
**# Remove Non ASCII characters from the dataset.**def cleanAscii(text): return ''.join(i for i in text if ord(i) < 128)
单词嵌入
每个前馈神经网络都将词汇作为输入,并将它们作为向量嵌入到低维空间,然后通过反向传播进行微调,必然会产生作为第一层权重的单词嵌入,这通常被称为嵌入层(Ruder,2016)
图片来自[3]
W ord embedding 学习文本的句法和语义方面(Almeida 等人,2019)。由于我们的问题与文本的语义相关,我们将使用单词嵌入作为我们的暹罗网络的第一层。
为此,我们将使用流行的 GloVe(单词表示的全局向量)嵌入模型。我们将获得预训练的模型(https://nlp.stanford.edu/projects/glove/)并将其作为我们的第一层作为嵌入层加载。
由于手套的最近邻方法(或余弦相似度),它能够捕获语义相似的单词。在我们的模型中,我们将使用使用手套权重开发的嵌入矩阵,并为我们的每个句子获取单词向量。
首先,我们用所有的词汇构建一个标记器。
max_words = 10000
tok = Tokenizer(num_words=max_words, oov_token="<OOV>")
tok.fit_on_texts(combined)# Padding sequences to a max embedding length of 100 dim and max len of the sequence to 300sequences = tok.texts_to_sequences(combined)sequences = pad_sequences(sequences, maxlen=300, padding='post')
现在假设,我们已经从这里下载了手套预训练向量,我们用嵌入矩阵初始化我们的嵌入层。
max_words = 10000
word_index = len(tok.word_index) + 1
glove_dir = ''
embeddings_index = {}
f = open(os.path.join(glove_dir, 'glove.6B.100d.txt'))for line in f:values = line.split()word = values[0]coefs = np.asarray(values[1:], dtype='float32')embeddings_index[word] = coefsf.close()print('Found %s word vectors.' % len(embeddings_index))print(word_index)# matrixembedding_dim = 100embedding_matrix = np.zeros((max_words, embedding_dim))for word, i in tok.word_index.items():if i < max_words:embedding_vector = embeddings_index.get(word)if embedding_vector is not None:embedding_matrix[i] = embedding_vector
输出的屏幕截图
模型
图片来自[4]
现在我们已经创建了我们的嵌入矩阵,我们也不会开始建立我们的模型。
模型摘要
lstm_layer = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(lstm_units, dropout=0.2, recurrent_dropout=0.2))# loading our matrix
emb = tf.keras.layers.Embedding(max_words, embedding_dim, input_length=300, weights=[embedding_matrix],trainable=False)input1 = tf.keras.Input(shape=(300,))
e1 = emb(input1)
x1 = lstm_layer(e1)input2 = tf.keras.Input(shape=(300,))
e2 = emb(input2)
x2 = lstm_layer(e2)mhd = lambda x: tf.keras.backend.abs(x[0] - x[1])
merged = tf.keras.layers.Lambda(function=mhd, output_shape=lambda x: x[0],
name='L1_distance')([x1, x2])
preds = tf.keras.layers.Dense(1, activation='sigmoid')(merged)
model = tf.keras.Model(inputs=[input1, input2], outputs=preds)
model.compile(loss='mse', optimizer='adam')
我们使用一个 LSTM 层来编码我们的 100 暗字嵌入。然后,我们计算曼哈顿距离(也称为 L1 距离),然后激活 sigmoid,将输出压缩在 0 和 1 之间。(1 表示最大相似度,0 表示最小相似度)。我们使用 MSE 作为损失函数和 Adam 优化器。
我们的模型结构
培养
我们将我们的 train.csv 分割为训练、测试和验证集,以测试我们的模型。
def create_data():
features, labels = df_train.drop(columns=['id', 'qid1', 'qid2', 'is_duplicate']).values, df_train['is_duplicate'].values
x_train, x_test, y_train, y_test = train_test_split(features, labels, test_size=0.2, random_state=42)
x_train, x_val, y_train, y_val = train_test_split(x_train, y_train, test_size=0.25, random_state=42)
return x_train, x_test, y_train, y_test, x_val, y_val
问题 1 和问题 2
为了训练我们的模型,我们简单地调用 fit 函数,后跟输入。
history = model.fit([x_train[:,0], x_train[:,1]], y_train, epochs=100, validation_data=([x_val[:,0], x_val[:,1]], y_val))
参考
- [1]https://arxiv.org/abs/1901.09069
- [2]https://nlp.stanford.edu/pubs/glove.pdf
- https://ruder.io/word-embeddings-1/
- [4]https://www . aaai . org/OCS/index . PHP/AAAI/aaai 16/paper/download/12195/12023
R 或 R——何时使用什么
平方皮尔逊相关系数和决定系数的图形解释,帮助您发现统计谎言
皮尔逊相关系数和决定系数的区别。图片作者。
想象一下,你是一名股票分析师,负责预测沃尔玛季度收益报告前的股价。当你正在努力工作时,你的数据科学家走进来说,他们发现了一个鲜为人知的数据流,提供沃尔玛每天的停车场占用率,这似乎与沃尔玛的历史收入有很好的相关性。你兴奋是可以理解的。你让他们在机器学习模型中使用停车场数据和其他标准指标来预测沃尔玛的股价。
到目前为止一切顺利。
几个小时后,数据科学家回来了,声称经过对模型的仔细验证,它的预测与真实的股票价格有很强的相关性。你接受这个模型而不做进一步的调查吗?
我希望不会。
C orrelations 有利于识别数据中的模式,但对于量化模型的性能几乎没有意义,尤其是对于复杂的模型(比如机器学习模型)。这是因为**相关性只告诉我们两个事物是否跟随(例如,停车场占用率和沃尔玛的股票),而不告诉我们它们如何匹配(例如,预测和实际的股票价格)。**为此,像决定系数®这样的模型性能指标会有所帮助。
在本文中,我们将了解:
- 什么是相关系数( r) 及其平方( r )?
- 什么是决定系数( R )?
- 什么时候使用上面的每一个?
1.相关系数:“这个预测器有多好?”
蓝线总和越短,相关系数越接近+1。图片作者。
相关系数有助于量化两个事物之间的相互关系或联系。一些众所周知的相关量是人的体重和身高、房屋价值和面积,以及我们在上面的例子中看到的商店收入和停车场占用率。
最广泛使用的相关系数之一是皮尔逊相关系数(通常表示为 r) 。从图形上看,这可以理解为“数据离最佳拟合线有多近?”
r 的范围为 1 至+1。灰线是最符合数据的线。图片作者。
- 如果这些点非常远, r 接近于 0
- 如果点非常靠近直线,并且直线向上倾斜, r 接近+1
- 如果点非常靠近直线,并且直线向下倾斜, r 接近 1
注意上图中的坐标轴上有缺失的数字吗?这是因为皮尔逊相关系数与数字的大小无关;它只对相对变化敏感。这种特性通常是可取的,因为变量很少具有相同的大小。例如,沃尔玛的股票价格是几十美元,而停在商店门口的汽车数以千计。
然而,由于皮尔逊相关系数对实际大小的不敏感性,当两个事物确实被期望具有相同的大小时,皮尔逊相关系数可能被滥用来给出错误的置信度。
更糟糕的是,一些人将皮尔逊相关系数的平方带到 0 和+1 之间,并将其称为 r 。但这不要与下面解释的决定系数®相混淆。
2.决定系数:“这个模型有多好?”
橙色线条的总和越长,决定系数越低。图片作者。
与皮尔逊相关系数不同,决定系数测量预测值与(而不仅仅是遵循)观察值的匹配程度。它取决于点和 1:1 线(不是最佳拟合线)之间的距离,如上所示。数据越接近 1:1 线,决定系数越高。
决定系数通常用 R 表示。然而,它不是任何东西的平方。它的范围可以是从任何负数到+1。
r 的范围可以从负无穷大到+1。灰线是两个轴上的量相等的线(也称为 1:1 线)。图片作者。
- R = +1 表示预测与观测完全匹配
- R = 0 表示预测与观察值平均值附近的随机猜测一样好
- 负 R 表示预测比随机预测差
因为 R 表示点与 1:1 线的距离,所以与取决于数字的大小(与 r 不同)。
3.什么时候用什么?
皮尔逊相关系数( r) 用于识别事物的模式,而决定系数®用于识别模型的强度。
通过对 *r,*取平方,你得到皮尔逊相关系数的平方( r ),它与决定系数®完全不同,除非在线性回归的非常的特定情况下(当来自上述数字的两条灰色线合并,使得蓝色和橙色线相等)。
因此,皮尔逊相关系数或其平方很少用于评估模型的性能。下图用 3 个例子对此进行了解释。
沃尔玛股票价格的 3 个不同模型的预测。图片作者。
- 模型 1: R = 0.99 表明它几乎完美地预测了股票价格。
- 模型 2: R = 0.59 表明它对股票价格的预测很差。然而,如果你只看 r 的话,你可能过于乐观了。这种有偏差的预测在机器学习模型中极为常见。因此,更重要的是将你的预测可视化,而不仅仅是用统计数据来总结它们。
- 模型 3:R = 0.98 表示比随机猜测 50 美元左右的股价更差。但是,如果你只是看了一眼,你可能会失去所有的钱!附注:信不信由你,与实际趋势相反的股票预测很常见。这也催生了一个全新的领域,叫做反向投资。
概述
- 相关性对于发现数据中的模式和关系是有用的,但是对于评估预测是无用的。
- 要评估预测,请使用诸如决定系数之类的度量标准,决定系数反映了预测与观测的匹配程度,或者预测解释了观测数据中的多少变化。
- 皮尔逊相关系数的平方通常不等于决定系数(或 r ≠ R)
如果你想要一个关于 R 和 R 之间区别的数学解释,看看迪帕克·汉德尔瓦尔的这篇优秀文章。
r 和传单来创建交互式 choropleth 地图。
地理可视化选举数据
照片由марьянблан| @ marjanblan在 Unsplash
在我开始之前,这里是 Github 页面上完整交互版主机的链接。
[## 用传单创建交互式地图
ejooco.github.io](https://ejooco.github.io/MapStats.github.io/)
我先说:这不是一篇关于冠状病毒的文章。
尽管新冠肺炎是世界上的一个大事件,它实际上对数据科学家来说是迷人的,特别是数据可视化。这可能激励了很多人进入这个行业。
在未来几十年,我想象大学和在线课程将使用新冠肺炎数据集来教授数据收集、辩论、可视化、建模等。
但在此之前,真正的数据之王可以说是政治,因此在这里我将向数据可视化的前任统治者致敬,并一步步地向您介绍如何使用 R Studio 和传单库构建交互式 choropleth 地图来显示选举结果。
让我们开始吧!
加载项目的库
**library**(rgeos)
**library**(maptools)
**library**(leaflet)
数据
我们需要两组不同的数据。一个用于映射几何图形,一个用于选举结果。
我使用的数据来自澳大利亚选举委员会,可以在这里找到:
虽然我们已尽力确保本产品中数据的准确性,但数据的所有者(包括…
aec.gov.au](https://aec.gov.au/Electorates/gis/gis_datadownload.htm) [## 部门结果
此表允许您按名称搜索分部。此表可通过选择列标题进行排序,您可以…
results.aec.gov.au](https://results.aec.gov.au/24310/Website/HouseDivisionalResults-24310.htm)
绘制形状文件
使用 maptools 包中的 readShapeSpatial(),我们将形状文件作为它自己需要的参数传入,并将其赋给一个变量。使用 plot()函数来查看它的外观。
vicmapdata <- readShapeSpatial(".\\vic-july-2018-esri\\E_AUGFN3_region.shp")
plot(vicmapdata)
读取选举数据并将其传递给一个变量
electiondata <- read.csv(".\\vic_elect_results.csv")
数据争论
首先,我们来看看数据的结构
summary(electiondata)## Division State Successful.Party TCP.Margin
## Aston : 1 VIC:38 Australian Labor Party:21 1,090 : 1
## Ballarat: 1 Independent : 1 10,934 : 1
## Bendigo : 1 Liberal :12 11,289 : 1
## Bruce : 1 The Greens : 1 11,326 : 1
## Calwell : 1 The Nationals : 3 12,134 : 1
## Casey : 1 12,453 : 1
## (Other) :32 (Other):32
首先,我不喜欢变量的名字。
colnames(electiondata) <- c("Divisions", "State", "Party", "Marginal Votes")summary(electiondata)## Divisions State Party Marginal Votes
## Aston : 1 VIC:38 Australian Labor Party:21 1,090 : 1
## Ballarat: 1 Independent : 1 10,934 : 1
## Bendigo : 1 Liberal :12 11,289 : 1
## Bruce : 1 The Greens : 1 11,326 : 1
## Calwell : 1 The Nationals : 3 12,134 : 1
## Casey : 1 12,453 : 1
## (Other) :32 (Other):32
这看起来更好接下来,我们将查看 shapefile 数据中的部门名称。这一点很重要,因为 electiondata 部分必须精确地映射到 shapefile 部分
summary(vicmapdata)## Object of class SpatialPolygonsDataFrame
## Coordinates:
## min max
## x 140.96168 149.97668
## y -39.15919 -33.98043
## Is projected: NA
## proj4string : [NA]
## Data attributes:
## E_div_numb ***Elect_div* ** Numccds Actual
## Min. : 1.00 **Aston : 1** Min. :267.0 Min. :100151
## 1st Qu.:10.25 **Ballarat: 1** 1st Qu.:337.5 1st Qu.:105494
## Median :19.50 **Bendigo : 1** Median :354.0 Median :107416
## Mean :19.50 **Bruce : 1** Mean :359.1 Mean :106954
## 3rd Qu.:28.75 **Calwell : 1** 3rd Qu.:387.0 3rd Qu.:109115
## Max. :38.00 **Casey : 1** Max. :467.0 Max. :112265
## (Other) :32
## Projected Total_Popu Australian Area_SqKm Sortname
## Min. :107381 Min. :0 Min. :0 Min. : 40.46 Aston : 1
## 1st Qu.:109070 1st Qu.:0 1st Qu.:0 1st Qu.: 80.59 Ballarat: 1
## Median :109986 Median :0 Median :0 Median : 170.28 Bendigo : 1
## Mean :110372 Mean :0 Mean :0 Mean : 5987.93 Bruce : 1
## 3rd Qu.:111484 3rd Qu.:0 3rd Qu.:0 3rd Qu.: 2619.61 Calwell : 1
## Max. :113924 Max. :0 Max. :0 Max. :81962.21 Casey : 1
## (Other) :32
看起来 shapefile 中的分区在变量 Elect_div 下
vicmapdata$Elect_div## [1] Aston Ballarat Bendigo Bruce Calwell Casey
## [7] Chisholm Cooper Corangamite Corio Deakin Dunkley
## [13] Flinders Fraser Gellibrand Gippsland Goldstein Gorton
## [19] Higgins Holt Hotham Indi Isaacs Jagajaga
## [25] Kooyong La Trobe Lalor Macnamara Mallee Maribyrnong
## [31] Mcewen Melbourne Menzies Monash Nicholls Scullin
## [37] Wannon Wills
## 38 Levels: Aston Ballarat Bendigo Bruce Calwell Casey Chisholm ... Wills
到目前为止一切顺利。election data$Divisions 和 vicmapdata$Elect _ div 都有 38 个级别,这是一个好的开始。我们可以在这种规模下手动检查它们,但如果我们检查整个国家,或者一个更大的国家呢?我们需要明智地做这件事,并让 R 为我们做这些繁重的工作。
两个数据集中的名称必须完全匹配,这样两个数据集才能正确映射。
setdiff(electiondata$Division, vicmapdata$Elect_div)## [1] "McEwen"
我们确实有矛盾。它告诉我们“McEwen”在第一个向量中,但不在第二个向量中。我们先找出第一个向量中“McEwen”的位置,看看第二个向量中对应的位置是什么。
which(electiondata$Division=="McEwen")## [1] 31
所以在 31 号位置。另一个向量的 31 号位置是什么?
vicmapdata$Elect_div[31]## [1] Mcewen
## 38 Levels: Aston Ballarat Bendigo Bruce Calwell Casey Chisholm ... Wills
好的,它很小,但是第一个向量有一个 E,第二个向量有一个 E。为了留在代码中,并且不必手动修复(记住这需要可伸缩),我们将把数据从一个向量映射到另一个向量(现在我们知道其他一切都是相同的)
vicmapdata$Elect_div <- electiondata$Divisions
现在,让我们像以前一样进行检查,以确保值匹配
setdiff(electiondata$Division, vicmapdata$Elect_div)## character(0)
那更好!
创造视觉效果
有趣的部分来了!我们将使用传单,而不是我们上面使用的绘图功能。我们会把我们的“受害者地图数据”传给它。当我们设置 stroke=True 时,addPolygons 将为我们绘制边界。我们将使用 1.5 粗细的白线
leaflet(vicmapdata) %>%
addPolygons(
stroke = TRUE,
color = 'White',
weight = 1.5,
)
(点击页面顶部的链接查看互动版)
此时,我们有两个数据变量。1 用于映射数据,我们刚才已经演示过了。现在,我们需要将我们的选举数据映射到绘图上。
首先,我们将创建标签。这意味着当我们将鼠标悬停在某个选民上时,它会告诉我们相关的统计数据。我们使用一些 HTML 工具来格式化渲染后的图形。
mylabels <- paste(
"Electorate: ", vicmapdata$Elect_div, "<br/>",
"Party: ", electiondata$Party, "<br/>",
"Margin(votes): ", electiondata$`Marginal Votes`
) %>%
lapply(htmltools::HTML)
现在,我们将把 mylabels 变量插入到之前的传单代码块中
leaflet(vicmapdata) %>%
addPolygons(
stroke = TRUE,
color = 'White',
weight = 1.5,
label = mylabels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "13px",
direction = "auto"
)
)
(点击页面顶部的链接查看互动版)
到目前为止一切顺利。现在我们将添加一些颜色。我创建了一个名为 factpal(因子调色板)的变量。我们使用传单库中的 colorFactor 函数。topo.colors(5)告诉该函数,我们需要 topo.colors 调色板中的 5 种颜色,unique()允许我们将一种颜色分配到特定级别。在这种情况下,我们希望同一个获胜政党的所有选民都被分配相同的颜色。
factpal <- colorFactor(topo.colors(5), unique(electiondata$Party))
现在我们将 factpal 函数插入到传单代码块中
leaflet(vicmapdata) %>%
addPolygons(
fillColor = ~factpal(electiondata$Party),
stroke = TRUE,
color = 'White',
weight = 1.5,
label = mylabels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "13px",
direction = "auto"
)
)
(点击页面顶部的链接查看互动版)
看起来更好了
从这里开始,我们只需要添加一些文本和一个图例。
文本:我们需要一个标题和一些数据的参考链接
图例:哪些颜色等同于哪个政党
下面是文本标签的代码。我们本质上只是在 HTML 中进食
htmltitle <- "<h5> How Victoria voted in the 2019 Federal Election | House of Representatives</h5>"references <- "<h5>References</h5><a target='_blank' href='https://results.aec.gov.au/24310/Website/HouseDivisionalResults-24310.htm'><h5>Election Data</h5></a><a target='_blank' href='https://aec.gov.au/Electorates/gis/gis_datadownload.htm'><h5>Geometric Data</h5></a>"
现在,我们只需插入上面的标题和参考数据,并在 addLegend 函数下添加图例,如下图所示。
leaflet(vicmapdata) %>%
addPolygons(
fillColor = ~factpal(electiondata$Party),
stroke = TRUE,
color = 'White',
weight = 1.5,
label = mylabels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "13px",
direction = "auto"
)
) %>%
addLegend( pal=factpal,
values=~electiondata$Party,
opacity=0.3,
title = "Political Party",
position = "bottomleft"
) %>%
addControl(html=htmltitle, position = "topright") %>%
addControl(html=references, position = "bottomright")
(点击页面顶部的链接查看互动版)
可能的延续
- 添加时间刻度以显示选举结果随时间的变化
- 创建另一个视觉效果来查看哪些选民易手了
- 扩大到整个澳大利亚
如果你正在读这封信,说明你已经看完了
感谢您的阅读。云中见。
埃蒙
推特@ejooco
https://github.com/ejooco
谷歌工作表中的 r 和 Python 绘图
使用自定义 Google Sheets 函数来改进绘图
卢卡斯·布拉塞克在 Unsplash 上的照片
上次
这是关于在 Google Sheets 公式中使用 R 和 Python 函数的 n 部分系列的第 2 部分。如果您还没有阅读第 1 部分,在 Google Sheets 公式中使用 R 和 Python,我建议您去看看所有对您有用的魔法。总之,通过在 Google Cloud Run 中设置一个简单的 API 并创建 Google Apps 脚本函数来调用您的 API,您可以使用 R 和 Python 代码来支持自定义 Google Sheets 单元格公式。在初始设置之后,在任何 Google Sheet 中使用 R 和 Python 都是快速而简单的。
以下是一些亮点。
作者图片
作者图片
技术上不在第 1 部分,但本着同样的精神。作者图片
在谷歌工作表中绘图(以及更多)
正如我之前所说的,我认为谷歌工作表是惊人的。我袖手旁观这一声明,并警告说,在谷歌工作表中绘图是非常糟糕的。它花费了最长的时间,甚至有一个合理的线性回归可用,图形选项是非常有限的。然而,现在您可以通过使用以前开发的技术,使用 R 和 Python 在 Google Sheets 中动态地创建漂亮的图形。事实上,许多生成图像文件的函数都可以在 Google Sheets 公式中使用,只需很少的额外设置。
这里有一些例子。
- 基地 R 标绘
作者图片
- ggplot2 绘图
作者图片
3.使用 matplotlib 进行 Python 绘图
作者图片
4.k-均值聚类图
作者图片
5.字云
作者图片
这是如何工作的?
Google Sheets 函数 IMAGE 将图像的 URL 作为参数,并将其显示在单元格内。基于第 1 部分中的技术,自定义 Google Apps 脚本函数 rplot 和 pyplot 对设置在 Google Cloud Run 上的 my /rplot 和/pyplot 端点进行 API 调用。这些 API 调用将 rscript 和 pyscript 参数作为代码运行,生成输出的 PNG,通过它们的 API 将 PNG 上传到imgur.com,并返回上传图像的 URL。
在 Google Sheets 中开始使用 rplot 或 pyplot 最简单的方法是克隆my rpyssheets GitHub repo并使用 GoogleCloudRunner R 包为RS Sheets _ plotting目录和 pysheets_plotting 目录部署一个 Google Cloud Run 服务。然后将 Google Cloud Run 服务 URL 复制并粘贴到这个 Google Sheets 模板中并播放。
googleCloudRunner::cr_deploy_run('{LocalPath}/rsheets_plotting/')googleCloudRunner::cr_deploy_run('{LocalPath}/pysheets_plotting/')
细节
参数 rscript 和 pyscript 是/rplot 和/pyplot 端点的工作平台,并且每个端点都有自己的端点。rscript 参数作为字符串读入,并使用 R 的 eval()函数运行,而 pyscript 则混合使用 Python 的 exec() 和 eval() 函数读入并运行。我知道允许不可信的来源将代码传递给 eval()或 exec()函数是很危险的。根据您的用例,我会考虑如何修改我编写的代码来保护这些功能。
传递给 rscript 和 pyscript 的每个变量都被标识并转换为具有列名、数组、向量或单个值的 dataframe。rscript 和 pyscript 可以修改这些变量,也可以访问内置值,但必须生成图像。因为 R 可以捕获 PNG 文件形式的情节,这是在幕后处理的,所以所有需要做的就是尝试一个情节。然而,据我所知,Python 并没有一种一致的方式将图形捕获到 PNG 中,pyscript 代码必须显式地将图形保存为 PNG 文件。在工作目录中找到的第一个 PNG 文件在后台被上传到 imgur.com。
**rplot Google Sheets Formula** =IMAGE(rplot("g <- ggplot(data = a, mapping = aes(x,y)) + geom_point() + geom_smooth(color = 'red') + ggtitle('Sample ggplot') + theme_minimal(); plot(g)", B2:C12))
作者图片
**pyplot Google Sheets Formula** =IMAGE(pyplot("import matplotlib.pyplot as plt; plot = a.plot(x = 0, y = 1, kind = 'scatter', title = 'Sample Python Scatterplot'); fig = plot.get_figure(); fig.savefig('output.png')", B2:C12))
作者图片
图像托管
对于/rplot 和/pyplot,我都使用了 imgur.com 的图像托管。如果你愿意,你可以使用不同的图片托管网站,但是要使用我上面所做的,你需要一个 imgur 客户端 ID。为了获得一个账户,创建一个 imgur 账户,然后添加一个客户到你的账户。一旦您有了客户端 ID,您就可以将它复制并粘贴到上面的脚本中,或者您也可以创建一个. creds 目录,其中的文件 imgur.json 以下面的方式定义。
{"clientID":"{YourImgurClientID}"}
我将我的客户机设置为授权类型“无用户授权的匿名使用”,并简单地上传公开可用的图像用于演示目的。您可以选择上传到私人相册。虽然每次更新谷歌表单上的图片都会为上传的图片生成一个唯一的 imgur URL,这是一种浪费,但每个客户每天可以上传多达 1250 张图片,这对我来说已经足够了。如果您在生产中使用它,您将希望在更新时修改图像,而不是每次上传不同的图像。请记住,如果你想用 imgur.com 赚钱,你有特殊的要求,它不是免费的。
资源
- 这是 Google Sheet 您可以简单地复制并使用为 pyscript、pyplot、rscript 和 rplot 预定义的自定义 Google Sheets 函数。所有你需要做的就是粘贴你的 R 和 Python Google Cloud 运行 URL,一旦它们被设置好。
- 这里是我的 GitHub repo 上面引用的 R 和 Python 代码。
尽情享受吧!
101 Munira 数据科学:R 和 RStudio 入门
桑尼·萨希尔在 Unsplash 上的照片
这是一个详细的指南,旨在帮助初学者轻松安装 R 和 Rstudio😃。
R 和 RStudio 有什么区别?
R 是数据科学世界中最流行的语言**。它是由统计学家开发的,作为数据分析的交互环境。**
RStudio 是一个集成开发环境(IDE ),帮助您更高效地使用 R。它不仅为我们创建和编辑 R 代码提供了编辑器,还提供了许多其他有用的工具,我们将在后面看到。
Rstudio 是一个交互式桌面环境,但它不是 R,也不包括你下载安装时的 R。
R 和 RStudio 都可以免费下载安装。
1.1 在 Windows 10 上下载 R
要使用 Rstudio,我们首先需要安装 r。
你可以从 CRAN 下载 R,CRAN 代表综合 R 档案网。只需访问 CRAN 下载页面,并按照下面 gif 中所示的步骤进行操作:
从 CRAN 网站下载 R
1.2 安装 R
下载完最新版本的 R 后,点击下载的文件开始安装。遵循下面 gif 中显示的步骤将帮助您通过选择所有默认选项来安装 R。
在 Windows 10 上安装 R
恭喜你!您已经安装了 r。
1.3 下载 RStudio
您可以按照以下步骤在 RStudio 网站下载 RStudio 的最新免费桌面版本:
下载 RStudio for Windows
1.4 安装 RStudio
运行下载的。exe 文件,并在安装过程中为所有默认设置选择“是”,然后按照下面的 gif:
别忘了 RStudio 要求预先安装 R。
在 Windows 10 上安装 RStudio
2.1 内部 R 与内部 RStudio
R 控制台
RStudio
通过查看上面的图片,您现在可能已经意识到为什么最好使用 RStudio IDE 了。
2.2 使用 RStudio 入门
您可以从开始菜单中打开 RStudio。如果 RStudio 没有出现,您可以像这样搜索它:
在 Windows 10 上启动 R studio
使用 R 的方式主要有两种:在 R 控制台或者脚本文件中编写代码(以. R 扩展名保存的纯文本文件)。
RStudio 窗格
首次启动 RStudio 时,您将看到三个窗格。左窗格显示 R 控制台。右侧顶部窗格包括环境和历史等选项卡,底部窗格显示五个选项卡:文件、绘图、包、帮助和查看器(这些选项卡在新版本中可能会有变化)。您可以单击每个选项卡来浏览不同的功能。
Rstudio 窗格
2.3 右侧控制台
交互式数据分析通常发生在 R 控制台窗口(在 RStudio 中,左下面板)中,当您在底部大于号旁边的光标处键入命令并按回车键时,命令将在该窗口中进行评估。
一旦会话关闭,直接写入控制台的命令将被遗忘。
下面是一个使用控制台进行一些算术计算的快速示例。
在 R 控制台中执行算术计算命令的例子
2.4 脚本文件
脚本文件是用保存的纯文本文件。R 扩展。为了完整地记录您所做的事情以备后用,最好将您的命令写在一个脚本文件中,并用。r 分机。
2.4.1 创建并保存新的脚本 R 文件
要开始一个新的脚本,你可以点击文件菜单,然后新建文件,然后 R 脚本。这将在 RStudio 的左上方打开一个新的窗格,在这里您可以开始编写脚本或 R 代码。
要保存新创建的脚本文件,您可以单击文件菜单,然后在键盘上保存(或按 Ctrl+S)并写入脚本名称。您可以省略。r 扩展名,RStudio 会为您添加。
如何创建和保存新的 R 脚本文件
2.4.2 在脚本文件中编写和运行命令
要一次运行一行而不是整个脚本,单击编辑窗格右上角的运行按钮或按键盘上的 Ctrl+Enter。
编辑完脚本后,不要忘记保存它。
要运行整个脚本,请按键盘上的 ctrl+shift+Enter。
2.5 安装 R 包
“Base R”是您第一次安装 R 后获得的内容。其他组件可通过软件包获得。然而,因为不是每个人都需要所有可用的功能,R 通过包提供不同的组件。
您可以安装的许多可用软件包中的一些是用于增强数据处理能力的 dplyr 或用于改进数据可视化的 ggplot2 。
使用 RStudio 安装 R 包有两种方法。第一个是在 R 控制台中执行以下代码行:
install.packages("ggplot2")
第二种方法是使用 RStudio 内置的图形界面,你可以从这个界面搜索和下载 CRAN 上的任何 R 包,以及通过 GitHub 等其他库共享的许多 R 包。
安装 R 包
装载 R 包
然后我们可以使用library
函数将已安装的包加载到我们的 R 会话中:
**library**(ggplot2)
您可以使用以下功能查看所有已安装的软件包:
**installed.packages**()
你一路赶到这里?!感谢阅读。😆
如果您有任何问题或意见,请在下面留下您的反馈,或者您可以随时通过 Twitter 联系我。在那之前,下一篇文章再见!✋.
参考
在我们的数据科学专业证书课程的第一个,这门课程将向您介绍 R…
www.edx.org](https://www.edx.org/course/data-science-r-basics)
用 R 探索电影中的彩色故事:调色板提取
如何使用颜色量化理论和无监督机器学习从电影帧中提取调色板
0.概述
在《T4》的第一部分中,我们探索了一些从著名电影中挑选出来的有趣的半音阶例子 ,试图猜测导演们选择背后的原因,并对通过 R 脚本可以做的事情略知一二。
一次丰富多彩、数据驱动的电影色彩世界之旅
towardsdatascience.com](/exploring-chromatic-storytelling-with-r-part-1-8e9ddf8d4187)
在第二部分 ,中,我们更加强调介绍 ChromaR 工具包的技术细节,这是一个 R 包,可以呈现之前在第一部分中显示的所有彩色可视化效果。
关于如何生成电影框架线和许多其他彩色数据的实用见解
towardsdatascience.com](/the-chromar-package-892b716ee2c9)
这部第三部的基石将是对单个画面的视觉检查,而不是关注整部电影的颜色和色彩模式序列。具体来说,我们的主要目标是从任何输入帧自动生成合适的调色板。
猫怪公主(吉卜力工作室)的调色板,用 ChromaR 提取
首先,让我们从一些颜色理论开始。
1.颜色量化
提取调色板都是关于颜色量化。在计算机图形中,颜色量化是减少图像中使用的不同颜色数量的过程。
色彩量化示例(鸣谢:柯达
这种技术通常用于在由于内存限制或风格选择而只能管理有限颜色的设备上显示多种颜色的图像。
在这些情况下,找到最有代表性的一组颜色 对于尽可能高保真地重建原始图片至关重要。
颜色量化过程可以分为两个步骤:
- 选择一个色彩空间(如 sRGB、HSL、CIELAB 等)。)以数学方式将颜色表示为数字元组。不同的色彩空间意味着不同的色彩组织策略。例如,CIELAB 是一个专门设计的颜色空间,包含普通人可以看到的所有颜色,而 sRGB 是为显示器和打印机设计的。
- 选择量化策略。对三维空间中的点进行分组的最简单的方法是 均匀量化 ,其中每个轴被独立处理并被分成 k 个大小相等的段,定义了空间的 k 个均匀区域。当然,这也是最弱的策略,因为像素/点在颜色空间中不是均匀分布的。
相反,大多数标准技术将颜色量化视为一个 聚类问题 ,其中每个像素都被视为颜色空间的一个 n 维点,并根据某种度量(通常是欧几里德距离)分配给一组相似的像素。
聚类算法的一个有效替代方法是 中值切割 ,它通过沿最长维度的中点递归切割每组数据来获得调色板。
sRGB 在文章顶部空间表现了幽灵公主的框架。视觉检查足以识别最主要的集群。
2.ChromaR 中调色板提取的实现
对于 ChromaR 包,选择通过 K-Means 聚类算法 ,使用 Lab 颜色空间 来实现调色板提取,其中欧几里德距离更符合感知差异。
色彩空间和度量
在该颜色空间中, L* 、 a* 和 b* 的非线性关系旨在模拟眼睛的非线性响应。
立方体 CIE 实验室颜色空间(鸣谢: 2018,Kulku
已经提出了不同的度量来量化适合人类感知的两种颜色之间的差异。这里我们使用了第一个也是最简单的一个, Delta E 76 ,这是一个标准的欧氏距离。
三角洲 E 76。不,那不是 埃隆马斯克的儿子的名字 。
几年来几次迭代改进了这个公式,得出了非常精确(和复杂)的度量标准,如Delta E 2000。
k-均值聚类算法
K-means 是一种聚类算法,使质心和聚类的其他点之间的距离平方和最小化(方差用作聚类分散的度量)。
簇的数量 k 代表我们调色板的期望大小,其中颜色由每个质心的 RGB/Lab 值决定。
为了简单起见,为 ChromaR 选择的距离度量是我们的 Delta E 76 又名欧几里德距离。
用 ChromaR 进行 K-means 聚类后猫怪公主框架的 sRGB 空间表示。每个聚类用其质心的颜色来标识,即其点的平均值。这些是用来生成调色板的颜色。
就像任何其他无监督的机器学习算法一样,K-Means 最终用标签标记我们帧的每个像素。这个标签可以假定的不同值将生成我们的调色板。
更进一步,我们可以使用这些标签用更少的颜色重建输入图像。
不同 k 值下的调色板提取和图像重建
k-意味着缺点和限制
尽管简单,K-Means 仍然可以产生有竞争力的结果。然而,它并不缺乏缺点和局限性。
K-Means 高度依赖于三个因素:
- 聚类数 : k 是一个输入参数,选择不当可能会产生不良结果
- 距离度量:我们决定测量点与点之间差异的方式会影响结果
- 初始点:算法不能保证收敛到全局最优,这意味着结果的质量可能取决于初始条件
为了减轻这些缺点的影响,ChromaR 实现了 K++算法 ,该算法限制了初始值选择引起的波动,并采用了基于人类感知的颜色空间。
《绝命毒师》(AMC)中的这个标志性场景清楚地表明了选择一个合适的 k 的重要性……绿色去哪里了?
使用 ChromaR 生成调色板
本文中显示的所有调色板都是使用运行以下脚本的 ChromaR 包生成的:
请注意,chromaR 包仍然是一个测试版,必须进行许多改进,以使其 100%可操作。因此,请报告您遇到的任何 bug 或问题!
结论
自动调色板提取工具确实是我们色彩探索的另一个有用的工具,但很难挑战人类评价的水平。事实上,人类设计的调色板通常显示一些高级结构(例如,颜色梯度、组合在一起的色调、颜色之间的高对比度等。)在自动创建的调色板中是完全没有的。
阿罗诺夫斯基的杰作《梦的安魂曲》中的一个资本场景。在这里,一个人造的 5 种颜色的调色板当然会包括从画面中心出现的鲜红色,正如导演自己所希望的那样。相反,机器驱动的聚类即使在 20 色调色板中也难以处理红色,因为衣服覆盖的像素区域非常有限。
然而,在这方面仍有很大的改进余地。例如,生成对抗网络(GANs)可能会帮助生成视觉上更可信的调色板,而像 Delta E 2000 这样更复杂的度量标准可能会在聚类中解开类似人类的感知。
即使没有我们温暖、神奇的人情味,我们仍然可以取得令人印象深刻的结果!
ChromaR 是一个实验性的 R 工具包,用于分析和探索电影或任何其他视频中的彩色故事…
github.com](https://github.com/detsutut/chroma) [## Tommaso Buonocore —作者—走向数据科学| LinkedIn
查看世界上最大的职业社区 LinkedIn 上 Tommaso Buonocore 的个人资料。托马索列出了 5 项工作…
www.linkedin.com](https://www.linkedin.com/in/tbuonocore/)
R 中的新冠肺炎数据采集
跨政府来源收集数据,检索政策措施,与世界银行公开数据、谷歌和苹果移动报告接口。
编者注: 走向数据科学 是一份以研究数据科学和机器学习为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
KOBU 机构在 Unsplash 上拍摄的照片
新冠肺炎数据中心由 R 构建,支持任何语言,提供了一个全球范围的、细粒度的、统一的数据集,有助于更好地了解新冠肺炎。用户可以立即从多个官方来源下载最新的结构化历史每日数据。这些数据每小时被处理一次,并以 csv 格式保存在云存储中,以便于从 Excel、R、Python…和任何其他软件中访问。所有的资料来源都有适当的记录,连同他们的引用。
在本教程中,我们将探索与新冠肺炎数据中心的接口。
快速入门
# install the package
install.packages("COVID19")
# load the package
library("COVID19")
# additional packages to replicate the examples
library("ggplot2")
library("directlabels")
数据
使用covid19
功能检索数据。默认情况下,它按国家下载全球数据,并打印相应的数据源。
x <- covid19()
使用verbose = FALSE
隐藏数据源
x <- covid19(verbose = FALSE)
返回一个包含几列的表格:累计确诊病例数、检测数、恢复数、死亡数、每日住院数、强化治疗数、需要通气的患者数、政策措施、地理信息、人口数和外部标识符,以便使用其他来源轻松扩展数据集。更多细节请参考文件。
干净的数据
默认情况下,通过用NA
值填充缺失的日期来清除原始数据。这确保了所有地点共享相同的日期网格,并且没有一天被跳过。然后,NA
值被替换为之前的非NA
值或0
。
例:按国家绘制确诊病例。
ggplot(data = x, aes(x = date, y = confirmed)) +
geom_line(aes(color = id)) +
geom_dl(aes(label = administrative_area_level_1), method = list("last.points", cex = .75, hjust = 1, vjust = 0)) +
scale_y_continuous(trans = 'log10') +
theme(legend.position = "none") +
ggtitle("Confirmed cases (log scale)")
例:按国家绘制确诊病例占总人口的比例。
ggplot(data = x, aes(x = date, y = confirmed/population)) +
geom_line(aes(color = id)) +
geom_dl(aes(label = administrative_area_level_1), method = list("last.points", cex = .75, hjust = 1, vjust = 0)) +
scale_y_continuous(trans = 'log10') +
theme(legend.position = "none") +
ggtitle("Confirmed cases - Fraction of total population (log scale)")
原始数据
并不总是建议用以前的非缺失数据填充数据,尤其是在计算比率或处理除数据可视化之外的更复杂的分析时。raw
参数允许跳过数据清理,按原样检索原始数据,无需任何预处理。
x <- covid19(raw = TRUE, verbose = FALSE)
该包依赖于来自多个来源的公开可用数据,但这些数据并不总是一致的,例如,确诊病例数大于检测数、累计计数减少等。新冠肺炎数据中心可以发现数据源之间的不一致,并自动通知当局可能的错误。所有日志都可以在这里获得。
例:按国家绘制确诊病例,作为检测的一部分。
ggplot(data = x, aes(x = date, y = confirmed/tests)) +
geom_line(aes(color = id)) +
geom_dl(aes(label = administrative_area_level_1), method = list("last.points", cex = .75, hjust = 1, vjust = 0)) +
scale_y_continuous(trans = 'log10') +
theme(legend.position = "none") +
ggtitle("Confirmed cases - Fraction of tests (log scale)")
示例:按国家绘制死亡率。
ggplot(data = x, aes(x = date, y = deaths/confirmed)) +
geom_line(aes(color = id)) +
geom_dl(aes(label = administrative_area_level_1), method = list("last.points", cex = .75, hjust = 1, vjust = 0)) +
scale_y_continuous(trans = 'log10') +
theme(legend.position = "none") +
ggtitle("Mortality rate (log scale)")
复古数据
检索在end
日期生成的数据集快照,而不是使用最新版本。此选项确保结果的可重复性,并跟踪数据提供者可能做出的更改。示例:检索 2020-06-02 的年份数据。
# retrieve vintage data on 2020-06-02
x <- covid19(end = "2020-06-02", vintage = TRUE, verbose = FALSE)
例子:与英国的最新数据比较。
# retrieve latest data
y <- covid19(verbose = FALSE)
# add type
x$type <- "vintage"
y$type <- "latest"
# bind and filter
x <- rbind(x, y)
x <- x[x$iso_alpha_3=="GBR",]
# plot
ggplot(data = x, aes(x = date, y = deaths)) +
geom_line(aes(color = type)) +
theme(legend.position = "right") +
ggtitle("UK fatalities")
行政区域
参数country
指定要检索的不区分大小写的国家名称或 ISO 代码 (alpha-2,alpha-3,数字)的向量。
# load data for United States, Italy, and Switzerland
x <- covid19(c("United States", "ITA", "ch"), verbose = FALSE)
例:绘制死亡率。
ggplot(data = x, aes(x = date, y = deaths/confirmed)) +
geom_line(aes(color = id)) +
geom_dl(aes(label = administrative_area_level_1), method = list("last.points", cex = .75, hjust = 1, vjust = 0)) +
scale_y_continuous(trans = 'log10') +
theme(legend.position = "none") +
ggtitle("Mortality rate (log scale)")
数据在不同的粒度级别上可用:行政区级别 1(顶级行政区,通常是国家),行政区级别 2(通常是州、地区、县),行政区级别 3(通常是城市、自治市)。数据的粒度由参数level
指定。示例:检索意大利地区的数据并绘制死亡率。
# italy admin area level 2
x <- covid19("ITA", level = 2, verbose = FALSE)
# plot
ggplot(data = x, aes(x = date, y = deaths/confirmed)) +
geom_line(aes(color = id)) +
geom_dl(aes(label = administrative_area_level_2), method = list("last.points", cex = .75, hjust = 1, vjust = 0)) +
scale_y_continuous(trans = 'log10') +
theme(legend.position = "none") +
ggtitle("Mortality rate by region (log scale)")
该软件包允许跨国比较。示例:绘制意大利地区和瑞士各州的死亡率。根据国家的不同,还支持城市级数据(3 级)。
# italy and switzerland admin area level 2
x <- covid19(c("ITA","CHE"), level = 2, verbose = FALSE)
# plot
ggplot(data = x, aes(x = date, y = deaths/confirmed)) +
geom_line(aes(color = administrative_area_level_1, group = administrative_area_level_2)) +
geom_dl(aes(label = administrative_area_level_2), method = list("last.points", cex = .75, hjust = 1, vjust = 0)) +
scale_y_continuous(trans = 'log10') +
theme(legend.position = "top", legend.title = element_blank()) +
ggtitle("Mortality rate by region (log scale)")
政策措施
国家层面的政策由牛津新冠肺炎政府响应跟踪系统获取。管理区域级别 2 和 3 的策略继承自国家级别的策略。详见文件。
示例:加载美国数据,检测测试政策的变化,并将其与死亡率一起绘制。
# US data
x <- covid19("USA", verbose = FALSE)
# detect changes in testing policy
testing_policy_dates <- x$date[diff(x$testing_policy)!=0]
# plot mortality rate and changes in testing policy
ggplot(data = x, aes(x = date, y = deaths/confirmed)) +
geom_line(aes(color = id)) +
geom_dl(aes(label = administrative_area_level_1), method = list("last.points", cex = .75, hjust = 1, vjust = 0)) +
geom_vline(xintercept = testing_policy_dates, linetype = 4) +
scale_y_continuous(trans = 'log10') +
theme(legend.position = "none") +
ggtitle("US mortality rate and changes in testing policy")
世界银行公开数据
数据集可以通过参数wb
使用世界银行公开数据进行扩展,参数wb
是指标代码的字符向量。可以通过检查相应的 URL 找到代码。例如,这里可用的 GDP 指标的代码是NY.GDP.MKTP.CD
。
例:用世界银行指标NY.GDP.MKTP.CD
(GDP)和SH.MED.BEDS.ZS
(每千人医院床位)扩展数据集。
# download worldwide data + GDP + hospital beds (per 1,000 people)
wb <- c("gdp" = "NY.GDP.MKTP.CD", "hosp_beds" = "SH.MED.BEDS.ZS")
x <- covid19(wb = wb, raw = TRUE, verbose = FALSE)
例子:绘制死亡率与医院病床数量的函数关系图。
ggplot(data = x, aes(x = hosp_beds, y = deaths/confirmed)) +
geom_line(aes(color = id)) +
geom_dl(aes(label = administrative_area_level_1), method = list("last.points", cex = .75, hjust = 1, vjust = 0)) +
scale_y_continuous(trans = 'log10') +
xlab("Hospital beds per 1,000 people") +
theme(legend.position = "none") +
ggtitle("Worldwide mortality rates (log scale) and number of hospital beds")
谷歌移动报告
数据集可以通过参数gmr
(Google CSV 文件的 url)用 Google Mobility Reports 扩展。
# at the time of writing, the CSV is available at:
gmr <- "https://www.gstatic.com/covid19/mobility/Global_Mobility_Report.csv"
x <- covid19("ITA", gmr = gmr, raw = TRUE, verbose = FALSE)
示例:检测意大利交通政策的变化,并将其与死亡率、确诊病例百分比和谷歌移动指标一起绘制。根据国家/地区,还支持地区或城市级别的移动数据。
# detect changes in transport policy
transport_dates <- x$date[diff(x$transport_closing)!=0]
# plot
ggplot(x, aes(x = date)) +
geom_line(aes(y = confirmed/tests*100, color = "Confirmed/Tested"), size = 1.2) +
geom_line(aes(y = deaths/confirmed*100, color = "Deaths/Confirmed"), size = 1.2) +
geom_line(aes(y = residential_percent_change_from_baseline, color = "Residential")) +
geom_line(aes(y = workplaces_percent_change_from_baseline, color = "Workplaces")) +
geom_line(aes(y = transit_stations_percent_change_from_baseline, color = "Transit Stations")) +
geom_line(aes(y = parks_percent_change_from_baseline, color = "Parks")) +
geom_line(aes(y = grocery_and_pharmacy_percent_change_from_baseline, color = "Grocery and Pharmacy")) +
geom_line(aes(y = retail_and_recreation_percent_change_from_baseline, color = "Retail and Recreation")) +
geom_vline(xintercept = transport_dates, linetype = 4) +
ylab("") +
theme(legend.position = "bottom", legend.title = element_blank()) +
ggtitle("ITA - Google mobility and transport policy")
苹果移动报告
数据集可以用 Apple Mobility Reports 通过参数amr
扩展,这是 Apple CSV 文件的 url。根据国家/地区,还支持地区或城市级别的移动数据。
# at the time of writing, the CSV is available at:
amr <- "https://covid19-static.cdn-apple.com/covid19-mobility-data/2009HotfixDev19/v3/en-us/applemobilitytrends-2020-06-03.csv"
x <- covid19("ITA", amr = amr, raw = TRUE, verbose = FALSE)
示例:检测意大利交通政策的变化,并将其与死亡率、确诊病例百分比和苹果移动性指标一起绘制。
# detect changes in transport policy
transport_dates <- x$date[diff(x$transport_closing)!=0]
# plot
ggplot(x, aes(x = date)) +
geom_line(aes(y = confirmed/tests*100, color = "Confirmed/Tested"), size = 1.2) +
geom_line(aes(y = deaths/confirmed*100, color = "Deaths/Confirmed"), size = 1.2) +
geom_line(aes(y = driving-100, color = "Driving")) +
geom_line(aes(y = walking-100, color = "Walking")) +
geom_line(aes(y = transit-100, color = "Transit")) +
geom_vline(xintercept = transport_dates, linetype = 4) +
ylab("") +
theme(legend.position = "bottom", legend.title = element_blank()) +
ggtitle("ITA - Apple mobility and transport policy")
规模分析
通过使用dplyr
包,数据集的结构使得复制多个国家、州和城市的分析变得容易。
library("dplyr")
加载数据。
x <- covid19(raw = TRUE, verbose = FALSE)
定义应用于每个组(如国家)的函数,必须返回一个数据帧。例如,该函数可以计算每个国家或地区的 R0。为了简单起见,下面的示例仅限于提取每组的最新死亡人数。
f <- function(x, key){
# x: the subset of rows for the given group
# key: row with one column per grouping variable
# code here...
example <- tail(x$deaths, 1)
# return data.frame
data.frame(id = key$id, example = example)
}
定义组,将函数应用于每个组,并绑定结果。
y <- x %>%
group_by(id) %>% # group by location id
group_map(f) %>% # apply the function to each group
bind_rows() # bind the results
打印第一行。
head(y, 5)## id example
## 1 AFG 309
## 2 AGO 4
## 3 ALB 33
## 4 AND 51
## 5 ARE 274
闪亮的应用程序
covid19
功能使用内部内存缓存系统,因此数据不会被下载两次。这特别适合交互式框架,比如 Shiny。参见如何在 5 分钟内构建新冠肺炎数据驱动的闪亮应用。
新冠肺炎数据中心是免费软件,没有任何担保。请确保同意使用条款。
[1]吉多蒂,即阿尔迪亚,d .(2020)。新冠肺炎数据中心,《开源软件杂志》,5(51):2376