TowardsDataScience-博客中文翻译-2020-九十八-
TowardsDataScience 博客中文翻译 2020(九十八)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
快速简单的深度学习 WebApp
原文:https://towardsdatascience.com/quick-and-easy-deep-learning-webapp-762f92f19f46?source=collection_archive---------49-----------------------
使用 fastai 和 streamlit 训练和部署深度学习图像分类模型
锡德·巴拉钱德朗在 Unsplash 上拍摄的照片
你有没有想过在一个项目中使用深度学习,并以互动的方式展示你的成果?你想开始你的深度学习之旅,并作为一个工作应用快速看到你的结果吗?让我告诉你怎么做。
使用 Python 部署小型数据驱动或机器学习应用程序的最简单方法之一是 streamlit。Streamlit 允许您只使用几行代码创建具有大量功能的 web 应用程序,我将在一分钟后演示。
[## Streamlit -创建数据应用程序的最快方式
Streamlit 是一个面向机器学习和数据科学团队的开源应用框架。在…中创建漂亮的数据应用程序
www.streamlit.io](https://www.streamlit.io/)
现在涵盖了部署部分,但机器或深度学习呢?如果你想深入学习,fast.ai 是一个很好的起点。他们的 MOOC,现在也是他们的书,特别是 fastai 图书馆,为你提供了开始深度学习之旅所需的一切。
[## 主页
2020 年 10 月 20 日更新:NumFOCUS 已经向我道歉了。我接受他们的道歉。我不接受他们的断言,即“在…
www.fast.ai](https://www.fast.ai/)
我想向您展示,使用最先进的深度学习模型,构建一个交互式分类 WebApp 有多快多容易。为此,我将从 Kaggle 获得 225 个鸟类物种数据集,
在其上训练一个深度学习模型,然后在 streamlit 应用程序中使用该模型。
由 Dulcey Lima 在 Unsplash 上拍摄的照片
现在我意识到,从技术上来说,对这么多鸟类进行分类并不是一件容易的事情,而且这个模型也远非完美,如果你想得到真正好的结果,你就必须更深入地研究。我只想给你提供一个分类应用教程,不使用 MNIST,时尚 MNIST,CIFAR-10 或 fastai MOOC 已经使用的任何东西。本教程不是告诉你如何在 Kaggle 排行榜上获得鸟类图像分类的榜首。我更愿意向您展示如何以初学者友好的方式构建端到端的东西。
第一步是下载数据。
数据集包含 4 个名为“合并”、“测试”、“训练”和“有效”的文件夹。在每个文件夹中,我们可以找到 225 个子文件夹,每个物种一个。文件夹名称稍后将提供标签。“合并”文件夹包含所有图像,所以对我们来说用处有限。
让我们把重点放在我们任务的培训和验证文件夹上。
数据准备和模型培训
下一步是加载我们的数据,预处理它并训练我们的模型。如果你是一个初学者,这听起来可能很多,可能令人不知所措,但是 fastai 让它变得出奇的简单。
我们首先导入 fastai.vision.all 包。请注意,我这里用的是import *
。我知道这可能产生的问题,我不建议将它用于 jupyter 笔记本之外的任何探索和实验。一旦我们探索、训练并保存了模型,我们将不会在 WebApp 文件中再次使用这种导入。
from fastai.vision.all import *#set the path where our data can be found
path = Path("D:/datasets/birds/archive (2)")#check if the path is working by extracting one image
im = Image.open(path / "train/CROW/001.jpg")
im.to_thumb(224,224) #this should display your image
现在,我们可以构建一个数据块和数据加载器,以我们的模型可以处理的方式加载数据。在 fastai 中,这是通过 DataBlock 类和 dataloaders 完成的。GrandparentSplitter()
告诉数据块对训练集使用“train”中的所有文件,对验证集使用“valid”中的所有文件。
birds = DataBlock(
blocks = (ImageBlock,CategoryBlock),
get_items = get_image_files,
splitter = GrandparentSplitter(train_name = "train", valid_name = "valid"),
get_y = parent_label, #get labels from folder names
item_tfms = Resize(224) #resize images to 224x224
)#use a dataloader to get the images
dls = birds.dataloaders(path)
这将是检查一切是否如预期进行的好时机。我们将查看验证和训练数据的前 10 张图片,看看是否所有内容都已正确加载。
dls.valid.show_batch(max_n = 10, nrows = 2)dls.train.show_batch(max_n = 10, nrows = 2)
您的输出应该如下所示:
图片作者。
注意,训练数据已经被混洗用于训练,而验证数据没有,也不需要被混洗。
我们的分类器将不得不在真实环境中处理的大多数图片都不会是配得上国家地理特征的完美图像(例如,当有人想使用你的应用程序来找出他们拍了哪只鸟的照片时)。因此,我们应该对数据进行一些转换。使用birds.new()
,我们可以添加新的图像或转换后的图像。使用RandomResizedCrop
我们可以添加从原始图片中随机裁剪的图片,使用batch_tfms = aug_transforms()
我们可以为整批图片添加变换,这些变换是一些有用的标准图像增强,如改变亮度、倾斜、拉伸和挤压图片。
birds = birds.new(
item_tfms = RandomResizedCrop(224, min_scale = 0.5),
batch_tfms = aug_transforms())#we again load the data
#I set num_workers = 0 in order to run the torch code on my local #machine, this may not be necessary for you
dls = birds.dataloaders(path, num_workers = 0)#look at some of the transformations
dls.train.show_batch(max_n = 15, nrows = 3, unique = True)
其中一些图片可能看起来有点奇怪,但你也可以找到一些“还可以,但远非理想”的图片,这些图片可能类似于你的 WebApp 用户稍后上传的内容。
好了,我们有了数据,我们对它进行了一些预处理。是时候选择一个模型并训练它了。
Fastai 非常强调使用预训练的模型并对其进行微调。这通常比从头开始训练更好更快地得到结果。这里我们将使用在 ImageNet 数据集上预先训练的 ResNet34。因此,我们的模型已经“看到”了图片,也“知道”了一只鸟的样子。我们可以利用这一点,对模型进行微调,对不同种类的鸟类进行分类。
learn = cnn_learner(dls, resnet34, metrics=error_rate).to_fp16()
#to_fp16() works well for my local system, might not be necessary for you#lets train and tune the model for 5 epochs
learn.fine_tune(5)
有关fine_tune()
方法的深入解释,请参见 fastai 文档。
一旦模型被训练,我们可以检查它犯了哪种错误,查看它在训练时间内的损失,当然也可以使用测试集来查看它在新数据上的表现。你绝对应该做所有这些事情。如果你不知道怎么做,可以查看 fast.ai 教程或 MOOC。
然而,我在这里不讨论这些步骤,因为主要的焦点不是模型训练和评估,而是展示如何创建一个工作的应用程序。
这个模型做得很好。对我来说,错误率(在验证集上)是 0.02,这相当于 98%的准确率。请注意,准确性并不总是最好的指标,如果你想训练一个模型,你应该研究更多的指标。
是时候保存我们的模型并进入下一个阶段了:构建 WebApp。
learn.export(fname = "first_model.pkl")
您可能应该找到一个更有意义的名称,尤其是如果您有多个模型的话。
Streamlit 应用
我们将使用如上所述的 streamlit。要在本地托管您的应用程序,请打开您的终端或命令/anaconda 提示符,导航到您的 Python 文件所在的目录并键入streamlit run {your_file_name}.py
。
该应用程序应该在 localhost:8501 下可用。
我们将需要 streamlit,numpy,PIL 和 fastai.vision 来运行一切。
import streamlit as st
import numpy as np
from PIL import Image
from fastai.vision.all import load_learner, Path
我们的应用程序的开始应该有标题。在 streamlit 中,这就像输入st.title("Your chosen title")
一样简单
我们的应用程序的下一部分是文件上传,这是快速和方便的:uploaded_file = st.file_uploader("Choose an image...", type="jpg")
st.title("Upload + Classification Example")uploaded_file = st.file_uploader("Choose an image...", type="jpg") #file upload
我们现在基本上已经完成了应用程序的第一个状态,如下所示:
作者图片
为了整合我们的分类,我们首先需要加载模型。
learn_inf = load_learner(Path("first_model.pkl"))#load trained model
现在让我们对图像进行分类,并创建一些输出。
代码检查是否有上传的文件,一旦是,图像文件被转换,以便让我们的模型使用.predict()
方法预测它的标签。
一旦我们有了一个预测,我们就用使用标准降价格式的st.write()
为我们的用户创建一些输出。我还添加了一个小的 if 语句,以获得更好的语法。
#classification
if uploaded_file is not None:
#image transformation and prediciton
img = Image.open(uploaded_file)
st.image(img, caption='Your Image.', use_column_width=True)
image = np.asarray(img)
label = learn_inf.predict(image)
#label[0] accesses the actual label string
#output display
st.write("")
st.write("Classifying...")
#check for vowels in the names for correct grammar
if label[0][0] in "AEIOU":
st.write("## This looks like an")
else:
st.write("## This looks like a")
#our labels are in capital letters only
st.title(label[0].lower().title())
上传图片后,WebApp 看起来应该是这样的:
太好了!现在我们有了一个使用我们深度学习模型的正常运行的本地 WebApp!比用笔记本阅读要酷多了!
你可以部署它,但是你可能需要做一些改变,关于 GPU 的使用等等。
这是应用程序的完整代码:
###imports
import streamlit as st
import numpy as np
from PIL import Image
from fastai.vision.all import load_learner, Path## You may need these to deploy your model on e.g. heroku if you are coming from a windows machine
#import pathlib
#temp = pathlib.WindowsPath
#pathlib.WindowsPath = pathlib.PosixPath###App
##file upload and model loading
st.title("Upload + Classification Example")uploaded_file = st.file_uploader("Choose an image...", type="jpg") #file uploadlearn_inf = load_learner(Path("first_model.pkl"))#load trained model#learn_inf.model.cpu() # use this if you want to deploy the model somewhere without using a GPU, you may need pytorch cpu##classification
if uploaded_file is not None:
#image transformation and prediction
img = Image.open(uploaded_file)
st.image(img, caption='Your Image.', use_column_width=True)
image = np.asarray(img)
label = learn_inf.predict(image)
#label[0] accesses the actual label string
#output display
st.write("")
st.write("Classifying...")
#check for vowels in the names for correct grammar
if label[0][0] in "AEIOU":
st.write("## This looks like an")
else:
st.write("## This looks like a")
#our labels are in capital letters only
st.title(label[0].lower().title())
你现在知道如何构建一个基于深度学习的图像分类 App 了吧!
Streamlit 提供了许多功能,您可以添加更多功能或显示更多数据,或者稍微改变布局,进行实验和探索。Fastai 还提供了大量的功能,我建议您也去探索一下。
我希望这篇文章对您有所帮助,现在我请求您:
探索、实验、构建您自己的应用并展示您所学到的知识!
-梅林
快速简单地解释逻辑回归
原文:https://towardsdatascience.com/quick-and-easy-explanation-of-logistics-regression-709df5cc3f1e?source=collection_archive---------5-----------------------
对逻辑回归的简单解释,我们为什么需要它,如何评估它的性能,以及在 python 中使用逻辑回归构建多类分类
资料来源:Muskaan Arshad
逻辑回归
它是一种使用自变量预测因变量的预测算法,就像线性回归一样,但不同之处在于因变量应该是分类变量。
自变量可以是数字或分类变量,但因变量总是分类的
逻辑回归是一种统计模型,它使用逻辑函数来模拟条件概率。
对于二元回归,给定自变量 X,我们计算因变量 Y 的条件概率
可以写成 P(Y=1|X)或者 P(Y=0|X)
这读作 Y=1,给定 X 的条件概率或者 Y=0,给定 X 的条件概率
P(Y |X)近似为应用于输入特征的线性组合的 sigmoid 函数
逻辑回归的一个例子是发现一个人是否会拖欠他们的信用卡付款。一个人拖欠信用卡付款的概率可以基于未决的信用卡余额和收入等。
于是,我们可以写出【P(默认=是|余额)
当【P(default = yes)≥0.5, 那么我们就说这个人会拖欠自己的货款。
当P(default = yes)<0.4 时,那么我们就说这个人不会拖欠他们的付款。
概率总是在 0 和 1 之间。在二元分类的情况下,拖欠付款和不拖欠付款的概率总和为 1
Logistic 回归可用于二元分类或多类分类。
二元分类是指当我们有两种可能的结果时,比如一个人感染了新冠肺炎或者没有感染新冠肺炎。在多类分类中,我们有多种结果,比如一个人可能患了流感或过敏,或者感冒或新冠肺炎。
逻辑回归的假设
- 数据中没有异常值。异常值可以通过分析独立变量来识别
- 独立变量之间没有相关性(多重共线性)。
逻辑回归函数
Logistic 回归使用 logit 函数,也称为 log-odds;它是几率的对数。比值比是存在事件 B 时事件 A 的比值和不存在事件 B 时事件 A 的比值。
logit 或逻辑函数
- p 是事件 Y 发生的概率。P(Y=1)
- P/(1-P)是优势比
- θ是一个长度为 m 的参数
Logit 函数估计 0 到 1 之间的概率,因此逻辑回归是一种非线性变换,看起来像下面显示的 S 函数。
逻辑回归函数
可以使用最大似然估计(MLE)框架来估计逻辑函数的参数“θ”。MLE 搜索与独立变量 x 的联合概率最匹配的参数。
MLE 将为我们提供参数“θ”的值,该值将使拖欠付款的人的概率最大化,接近 1,使所有不拖欠付款的人的概率最大化,接近 0。
评价二元分类性能的混淆矩阵
混淆矩阵是一个表格,它告诉我们模型预测的不同类别存在多少实际值和预测值。也被称为误差矩阵。
混淆矩阵或误差矩阵以及不同的度量标准
解释关键术语
真阳性:当一个女性怀孕了,而我们预测她怀孕了
真否定:当一个男性没有怀孕,而我们预测他没有怀孕
假阴性:当女性怀孕,但我们预测她没有怀孕。又称2 型错误。
假阳性:男性不可能怀孕,但我们预测他怀孕了。也称为类型 1 错误
在 Iris 数据集上实现逻辑回归
数据可以从这里下载
导入所需的库
**import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split****%matplotlib inline**
读取数据
从[链接](http://from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split)下载数据,保存在 CSV 文件中,并添加标题。
**dataset=pd.read_csv("iris.csv")**
dataset.info()
显示数据集中的几行
dataset.head(5)
使用可视化进行数据分析
将数据可视化,以便更好地理解自变量和因变量
sns.boxplot(x="class",y="petal length",data=dataset)
plt.show()
使用花瓣长度和花瓣宽度的不同种类鸢尾的散点图
sns.scatterplot(x='petal length', y='petal width', hue="class", data=dataset)
利用萼片长度和萼片宽度绘制不同种类鸢尾的散点图
sns.scatterplot(x='sepal length', y='sepal width', hue="class", data=dataset)
E
将虹膜的类别从分类编码为数值
目标变量是代表鸢尾植物类别的字符串。我们将分类字符串数据编码成数值,以便模型理解
**from sklearn.preprocessing import LabelEncoder
le= LabelEncoder()
y_encoded=le.fit_transform(y)**
打印目标变量的编码值。
y_encoded
我们有一个多类分类问题,因为鸢尾植物 类有三个不同的值
将数据集分为训练和测试数据集
**from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test= train_test_split(X,y_encoded,test_size=0.2)**
使用逻辑回归训练数据集
我们正在使用逻辑回归为多类分类训练数据集
**from sklearn.linear_model import LogisticRegression
clf = LogisticRegression(random_state=0).fit(X_train, y_train)**
预测测试数据的虹膜类别
**y_pred=clf.predict(X_test)**
评估逻辑回归模型的性能
使用混淆矩阵来评估多类分类的性能
**from sklearn.metrics import confusion_matrix
cnf_matrix=confusion_matrix(y_test, y_pred, labels=[0,1,2])
cnf_matrix**
混淆矩阵
这个输出没有太大帮助,所以我们将数字目标变量反向转换回原来的类名
**y_pred_orig= le.inverse_transform(y_pred)**
我们还编写了一个函数,以更易读的格式显示混淆矩阵
**def plot_confusion_matrix(cm, classes,
title='Confusion Matrix',
cmap=plt.cm.Greens)**:
import itertools
print('Confusion Matrix')
plt.imshow(cm, interpolation='nearest', cmap=cmap)
plt.title(title)
tick_marks = np.arange(len(classes))
plt.xticks(tick_marks, classes, rotation=90)
plt.yticks(tick_marks, classes)
fmt = '.2f'
thresh = cm.max() / 2.
for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
plt.text(j, i, format(cm[i, j], fmt),
horizontalalignment="center",
color="white" if cm[i, j] > thresh else "black")plt.ylabel('Actual label')
plt.xlabel('Predicted label')
plt.tight_layout()
显示混淆矩阵
**plt.figure()
plot_confusion_matrix(cnf_matrix, classes=le.classes_,
title='Confusion matrixfor Iris test data')**
结论:
逻辑回归用于二元或多类分类,目标变量必须是分类变量。
参考资料:
https://web . Stanford . edu/class/archive/cs/cs 109/cs 109.1178/讲师讲义/220-logistic-regression . pdf
使用 Yellowbrick 进行快速简单的模型评估
原文:https://towardsdatascience.com/quick-and-easy-model-evaluation-with-yellowbrick-295cb0752bce?source=collection_archive---------26-----------------------
回顾一下机器学习工作流程的便捷工具
JR 克里奇摄,2016。
我偶尔会遇到一个 Python 包,它有可能简化我经常做的一项任务。当这种情况发生时,我总是很兴奋地尝试它,如果它很棒,就分享我的新知识。
几个月前,我在浏览 Twitter 时,看到了一条关于模型可视化包 Yellowbrick 的推文。我试过,喜欢,现在把它纳入我的机器学习工作流程。在这篇文章中,我将向你展示它能做什么的几个例子(你也可以随时去查看文档)。
快速事实
关于 Yellowbrick 的一些快速事实:
- 其目的是模型可视化,即帮助您直观地了解给定模型如何处理您的数据,以便您可以就是否选择该模型或如何调整它做出明智的选择。
- 它的界面很像 scikit-learn 的界面。如果您熟悉实例化模型、使其适合训练数据、然后在一行代码中进行评分或预测的工作流程,那么您将很快学会 Yellowbrick。
- Yellowbrick 包含基于 Matplotlib 的“visualizers”(一个特定于该包的类),用于主要类型的建模应用,包括回归、分类、聚类、时间序列建模等。,因此可能有一个可以帮助您处理大多数日常建模情况。
总体意见
总的来说,我喜欢使用 Yellowbrick,因为它为我节省了一些日常任务的时间。例如,我有自己的代码来可视化特性的重要性或生成一个颜色比例的混淆矩阵,我从一个项目复制到另一个项目,但是 Yellowbrick 让我可以用更少的代码行快速轻松地生成一个有吸引力的图。
当然,这种简单实现的缺点是,您无法像自己编码那样控制图形的外观。如果视觉化只是为了你的利益,很好;但是,如果您需要以任何方式操纵情节,请准备好钻研文档。当然,这是一个公平的交易,但是在你开始之前要考虑你的地块的最终用户,这样你就不用做两次了(一次在 Yellowbrick,一次在 Matplotlib/Seaborn/等等)。).
说到做事两次,我们来看看 Yellowbrick v. Matplotlib 中同样的可视化套路。
Yellowbrick 诉 Matplotlib 的特征重要性
对于这个小案例研究,我将为 UCI 葡萄酒数据集拟合一个随机森林分类器,然后使用一个柱状图来可视化每个特征对于预测的重要性。数据集很小(178 行,13 列),分类的目的是基于各种特征预测一种葡萄酒包含三种栽培品种中的哪一种。
首先,基础知识:
# Import basic packages
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# In Jupyter Notebook, run this to display plots inline
%matplotlib inline
# Get the dataset from sklearn
from sklearn.datasets import load_wine
data = load_wine()
# Prep features and target for use
X = data.data
X = pd.DataFrame(X)
X.columns = [x.capitalize() for x in data.feature_names]
y = data.target
在上面的代码中,我使用 sklearn 的内置 load_wine()类获取数据,并将其分成特性(X)和目标(y)。请注意,我采取了额外的步骤,将 X 转换为 DataFrame,并给列起了漂亮的大写名称。这将使我的生活更容易的时候,建立情节。
先来看看 Yellowbrick 的套路。我将实例化一个 RandomForestClassifier()和一个 FeatureImportances()可视化工具,然后调整可视化工具并显示绘图。
# Import model and visualizer
from yellowbrick.model_selection import FeatureImportances
from sklearn.ensemble import RandomForestClassifier# Instantiate model and visualizer
model = RandomForestClassifier(n_estimators=10, random_state=1)
visualizer = FeatureImportances(model)# Fit and display visualizer
visualizer.fit(X, y)
visualizer.show();
这就是你得到的:
在四行代码中(不包括导入语句),我得到了一个看起来不错的特性重要性图。我一眼就可以看出,脯氨酸对于识别品种非常重要,而苹果酸和灰分的碱度则不重要。
一些小小的抱怨:
- 颜色不能传达任何真实的信息,所以如果我手工编写代码,我会让所有的条形保持相同的颜色。
- x 轴已被重新标记,以最重要功能的重要性百分比来表示每个功能的相对重要性。所以脯氨酸,最重要的特征,在 100%,灰分的碱度在 5%左右。我更愿意看到由随机森林模型计算出的要素重要性值,因为即使是最重要的要素也只能解释数据中很小一部分的差异。黄砖图掩盖了绝对特征的重要性,有利于呈现相对重要性,我们可以从图中条形的长度推断出相对重要性!
现在,让我向您展示如何在 Matplotlib 中手工构建完全相同的图。我将从拟合 RandomForestClassifier()开始:
# Fit a RandomForestClassifier
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=10, random_state=1)
model.fit(X, y)
注意,我用与上面相同数量的估计器和随机状态实例化了模型,所以特性重要性值应该完全相同。
下面是我在绘制特性重要性时通常使用的基本代码:
# Plot feature importances
n_features = X.shape[1]
plt.figure(figsize=(8,6))
plt.barh(range(n_features), model.feature_importances_, align='center')
plt.yticks(np.arange(n_features), X.columns)
plt.xlabel("relative importance")
plt.title('Feature Importances of 13 Features Using RandomForestClassifier')
plt.show();
情节是这样的:
请注意,默认情况下,所有的条形都是相同的颜色,x 轴代表实际的要素重要性值,这是我喜欢的。不幸的是,这些条没有按照我喜欢的从最宽到最窄的顺序排列。例如,看着当前的图,我很难判断非类黄酮酚或镁更重要。
让我们看看如何在 Matplotlib 中精确地再现 Yellowbrick 图。首先,我要按照重要性对特性进行排序。这很棘手,因为 model.feature_importances_ 只是返回一个没有标签的值数组,其顺序与数据帧中要素的顺序相同。为了对它们进行排序,我需要将值与特性名称相关联,排序,然后将它们分割回来传递给 Matplotlib。
# Zip and sort feature importance labels and values
# (Note that reverse=False by default, but I included it for emphasis)
feat_imp_data = sorted(list(zip(X.columns, model.feature_importances_)), key=lambda datum: datum[1], reverse=False)
# Unzip the values and labels
widths = [x[1] for x in feat_imp_data]
yticks = [x[0] for x in feat_imp_data]
n_features = X.shape[1]
# Build the figure
plt.figure(figsize=(8,6))
plt.barh(range(n_features), widths, align='center')
plt.yticks(np.arange(n_features), yticks)
plt.xlabel("relative importance")
plt.title('Feature Importances of 13 Features Using RandomForestClassifier')
plt.show();
一个快速但重要的提示:看到我是如何按照升序排列特性重要性的了吗?这是因为 Matplotlib 会从底部开始绘制它们。相信我,因为我学到了一个艰难的方法:如果你想以降序顺序(从上到下)显示值,将它们以升序顺序传递给 Matplotlib。
那就好读多了!现在,如果我真的想要复制 Matplotlib 中的 Yellowbrick 图,我还需要提供颜色和 x-tick 标签,并删除水平网格线。
# First set up colors, ticks, labels, etc.
colors = ['steelblue', 'yellowgreen', 'crimson', 'mediumvioletred', 'khaki', 'skyblue']
widths = [x[1] for x in feat_imp_data]
xticks = list(np.linspace(0.00, widths[-1], 6)) + [0.25]
x_tick_labels = ['0', '20', '40', '60', '80', '100', '']
yticks = [x[0] for x in feat_imp_data]
n_features = len(widths)# Now build the figure
plt.figure(figsize=(8,6))
plt.barh(range(n_features), widths, align='center', color=colors)
plt.xticks(xticks, x_tick_labels)
plt.yticks(np.arange(n_features), yticks)
plt.grid(b=False, axis='y')
plt.xlabel("relative importance")
plt.title('Feature Importances of 13 Features Using RandomForestClassifier')
plt.show();
如果你想知道,我花了大约一个小时的时间在 Matplotlib 重建 Yellowbrick 地块。这包括从最大到最小对条形进行排序,猜测颜色并努力按正确的顺序排列,将 x 轴刻度和标签重置为 100%刻度,并删除水平网格线。
这个故事的寓意:如果一个黄砖地块能满足你的需求,那么这是一个比通过 Matplotlib 更快的方法。当然,在控制粒度方面,你永远也不会胜过普通的 Matplotlib。
黄砖带来更多乐趣
使用 Yellowbrick,您可以做更多的事情来可视化您的机器学习模型;请务必查阅文档。以下是几个简单的例子:
例 1 :一个颜色编码的混淆矩阵(使用与上面相同的葡萄酒数据和随机森林模型)。
# Import what we need
from sklearn.model_selection import train_test_split
from yellowbrick.classifier import ConfusionMatrix# Split the data for validation
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)# Instantiate model and visualizer
model = RandomForestClassifier(n_estimators=10, random_state=1)
matrix = ConfusionMatrix(model, classes=['class_0', 'class_1', 'class_2'])# Fit, score, and display the visualizer
matrix.fit(X_train, y_train)
matrix.score(X_test, y_test)
matrix.show();
这是我在最近的机器学习项目中使用的代码来自己构建类似的东西。注意,我的函数获取真实值和预测值,我必须事先计算这些值,而 Yellowbrick 从。score()方法。
# Define a function to visualize a confusion matrix
def pretty_confusion(y_true, y_pred, model_name):
'''Display normalized confusion matrix with color scale.
Edit the class_names variable to include appropriate classes.
Keyword arguments:
y_true: ground-truth labels
y_pred: predicted labels
model_name: name to print in the plot title
Dependencies:
numpy aliased as np
sklearn.metrics.confusion_matrix
matplotlib.pyplot aliased as plt
seaborn aliased as sns
'''
# Calculate the confusion matrix
matrix = confusion_matrix(y_true, y_pred)
matrix = matrix.astype('float') / matrix.sum(axis=1)[:, np.newaxis]
# Build the plot
plt.figure(figsize=(16,7))
sns.set(font_scale=1.4)
sns.heatmap(matrix, annot=True, annot_kws={'size':10}, cmap=plt.cm.Greens, linewidths=0.2)
# Add labels to the plot
class_names = ['Spruce/Fir', 'Lodgepole Pine', 'Ponderosa Pine', 'Cottonwood/Willow', 'Aspen', 'Douglas-fir', 'Krummholz']
tick_marks = np.arange(len(class_names))
tick_marks2 = tick_marks + 0.5
plt.xticks(tick_marks, class_names, rotation=25)
plt.yticks(tick_marks2, class_names, rotation=0)
plt.xlabel('Predicted label')
plt.ylabel('True label')
plt.title('Confusion Matrix for {}'.format(model_name))
plt.tight_layout()
plt.show();# Plot the confusion matrix
pretty_confusion(y_true, y_pred, 'Random Forest Model')
例 2 :显示两类文本如何重叠的 t-SNE 图。关于数据和模型我就不在这里赘述了,不过你可以在我的 GitHub 上查看相关项目。
# Import needed packages
from sklearn.feature_extraction.text import TfidfVectorizer
from yellowbrick.text import TSNEVisualizer# Prepare the data
tfidf = TfidfVectorizer()
X = tfidf.fit_transform(data.text)
y = data.target# Plot t-SNE
tsne = TSNEVisualizer()
tsne.fit(X, y)
tsne.show();
我甚至不知道这在 Matplotlib 中会有多难,因为我从未尝试过。我从 Yellowbrick 得到的结果足以回答我的问题,我能够获得这些信息并迅速继续前进。
我希望你能抽出时间来试验一下黄砖。在使用它的过程中,我获得了乐趣并学到了一些新的模型可视化技术,我打赌您也会这样。
跨贴自【jrkreiger.net】。
快速偏差/方差权衡
原文:https://towardsdatascience.com/quick-bias-variance-trade-off-d4895b126b08?source=collection_archive---------22-----------------------
偏差/方差的权衡很容易解释
这篇文章将解释机器学习中最常见的问题之一:偏差/方差权衡。我们将看到它是什么,为什么在建立机器学习模型时考虑它是重要的,我们将直观地解释它,并且不需要数学。
图片来自 Unsplash
偏差/方差的权衡是什么?
如上所述, 偏差/方差权衡 是在构建将使用监督机器学习模型进行预测的应用时必须解决的最常见问题之一。
这是一个与我们的模型的误差以及它们的灵活性有关的问题。总的问题表示为权衡,因为通常不可能同时改善我们模型的偏差和方差:通常当一个下降时,另一个上升,反之亦然。
为什么偏差/方差权衡很重要?
我们希望我们的机器学习模型在投入生产时尽可能准确。这意味着减少它可能犯的错误是很重要的,这种错误有三个主要方面:
来源: Codecogs
这个公式的含义如下:我们模型的整体误差可以分为三项;方差误差,偏差误差和不可约误差。最后一个是不能通过玩我们的模型或数据来减少的误差,它通常是由于数据中的噪声或因为模型的性能不能再进一步提高(即,它已经达到了与特定任务的顶级人类专家相同的性能)。
知道了这一点,很明显,我们有两种方法来减少总误差:由于我们不能减少不可约误差,我们必须减少来自方差或偏差的误差。
查看这些错误的另一种方式如下:在某些任务上人类水平的表现(由标记数据的人类产生的错误)和我们的模型在该训练数据上产生的错误之间的差异是由于我们的模型的偏差而产生的错误。我们的训练误差和测试数据误差之间的误差差是我们的模型由于方差而产生的误差。
人为误差和训练误差之间的差异是偏差误差,训练误差和测试误差之间的差异是方差误差。自制人物。
让我们看看这些误差来自哪里,我们如何减少它们,以及它们之间的权衡。
直观地解释了偏差/方差权衡
好了,我们已经简要描述了偏差/方差权衡,让我们看看这些术语的含义,然后深入描述这个问题:
- 偏差: 我们模型的偏差与它对数据所做的假设有关,与它在被训练时对数据的拟合程度有关。具有高偏差的模型不能很好地拟合训练数据,具有有限的灵活性,或者对于我们所拥有的数据来说极其简单,通常导致高训练误差。
偏差告诉我们我们的模型有多接近现实。
- 方差: 我们的模型的方差与它如何根据它用于训练的数据样本改变其结果有关。具有高方差的模型可以很好地拟合特定的数据,因此它难以推广到看不见的数据,从而导致较高的测试误差。
方差告诉我们我们的模型对训练数据有多敏感。
下图通常用于说明什么是方差和偏差:
偏差/方差靶心的图示。来自平面图标的图标。
对这个图的解释如下:每个镖靶给我们一个我们的模型表现如何的想法;红叉代表预测,越靠近靶心(棋盘的中心)越好。
- 当我们有高方差和高偏差时,我们的预测会非常分散,不会靠近中心。我们的模型没有对任何数据样本做出好的预测。
- 当我们有高方差和低偏差时,我们的预测是分散的,但围绕着棋盘的中心,所以它们中的一些击中了靶心,而另一些没有。在某些数据上,我们的模型预测得很好,但在其他数据样本上却不是这样。
- 高偏差和低方差意味着我们的预测很接近,但不在棋盘的中心。一般来说,我们的模型预测不好,尽管它对不同的样本做出了类似的预测。
- 低方差和低偏差意味着我们的预测接近且集中:这是最好的情况,我们的模型对各种数据都预测得很好。
现在让我们看一个真实世界应用程序的例子,以获得对问题的直觉。
想象一下,我们正在构建一个识别图像中的猫的应用程序,如果我们用高偏差训练一个模型,它会非常糟糕地预测猫的图像,独立于你用来训练它的猫数据样本。
我们的第一个模型,有很高的偏差,会预测这只狗是一只猫。原始图像来自 Unsplash 。
具有高方差的模型可以很好地预测特定的猫物种(例如),但当面对与之前训练的猫图像不太接近的猫图像时,它会出错。这对新来的猫来说太笼统了。
我们的第二个模型具有很高的方差,可以很好地预测某些种类的猫(上图),但对其他种类的猫(下图)预测很差。原始图片来自 Unsplash 。
最后,具有低方差和低偏差的模型将很好地独立预测它所训练的数据样本;在我们的例子中,它将足够概括地解释动物是猫还是狗,而不会被不同的猫物种所欺骗。
我们的最后一个低方差模型很好地分类了不同种类的猫。来自 Unsplash 的原图。
高偏差/方差模型示例
现在我们知道了什么是偏差和方差,它们之间的关系,以及直觉,让我们看看一些具有高方差/偏差的模型的例子。
正如我们所说的,具有高偏差的模型不能很好地拟合训练数据。可能遭受该问题的模型例如是线性模型,因为它们假设特征和目标变量之间的线性关系并不总是存在。
如果您不熟悉线性回归,您可以在这里了解它:
[## 线性回归解释
[ —线性回归简单解释— ]
towardsdatascience.com](/linear-regression-explained-d0a1068accb9)
在下图中,我们可以看到一个线性回归模型拟合的数据,显然没有线性相关性:因此,我们的模型将有很大的偏差,不会表现得很好。
适合非线性数据线性模型。自创形象。
具有高方差的模型是决策树例如:它们为训练数据的样本创建特定的分支和分裂,这些分支和分裂是特定于该数据的。此外,如果我们让决策树永远增长,它将增长与数据样本一样多的叶子节点,为每个数据点创建特定的路径。这意味着,当它找到一个新样本时,如果它与训练数据的任何样本的特征值都不完全匹配,它将不会很好地对其进行分类。
您可以在以下文章中找到对决策树的简单解释:
[## 决策树解释
学习机器学习决策树的所有知识
towardsdatascience.com](/decision-trees-explained-3ec41632ceb6)
这是决策树总是有某种停止条件(N 个离开节点、离开节点上的最小样本、最大深度……)的主要原因。通过这样做,我们使我们的树在新的数据点上更好地一般化。
如何解决偏差/方差问题
正如我们已经看到的,将训练数据拟合得太好会导致高方差但低偏差。没有很好地拟合训练数据会导致高偏差和低方差。我们如何解决高偏差或高方差的问题?
如果我们有一个高偏差(高训练误差),我们可以做以下事情来尝试解决这个问题:
- 改变我们模型的优化算法。
- 做好超参数调谐。(运行粗网格搜索,然后围绕第一个搜索的最佳结果运行更具体的搜索)。
- 切换型号类型
如果我们有高方差(高测试误差),我们可以尝试以下一些解决方案:
- 正则化我们的算法使用 L1 或 L2 正则化、删除、树修剪等…
- 获取更多数据进行训练,或尝试数据扩充技术。
- 也可以试试不同型号的。
结论和其他资源
我们已经看到了什么是偏差/方差权衡,它如何与我们的机器学习模型相关联,各种示例,以及如何解决它。如果您想更深入地了解它,请查看以下资源:
[## WTF 是偏差-方差权衡?(资料图)
课后无意中听到:“偏差-方差权衡听起来是不是像历史纪录片中一个条约的名字?”…
elitedatascience.com](https://elitedatascience.com/bias-variance-tradeoff) [## 机器学习中偏差-方差权衡的温和介绍——机器学习掌握
监督机器学习算法可以通过偏差-方差权衡的透镜得到最好的理解。在这个…
machinelearningmastery.com](https://machinelearningmastery.com/gentle-introduction-to-the-bias-variance-trade-off-in-machine-learning/)
就这些,我希望你喜欢这个帖子。请随时在推特上关注我。还有,你可以看看我在数据科学和机器学习上的帖子这里 。好好读!
快速代码:导出 Matplotlib 动画
原文:https://towardsdatascience.com/quick-code-exporting-matplotlib-animations-49cd0ecf32ba?source=collection_archive---------11-----------------------
如何将动画 Matplotlib 图形导出为 GIF 文件
Matplotlib 的一个经常被忽略的特性。动画在数据可视化方面开辟了一个全新的世界。让我们能够显著提高我们工作的影响力。
上图是使用以下代码创建的:
如果您尝试在 Python 中运行它,您可能会得到下面的ValueError: unknown file extension: .gif
。这是因为 Matplotlib 本身不支持 gif。
幸运的是,这个问题的解决方案非常简单。
循序渐进
我们首先从这里为 Windows 用户下载 ImageMagick (其他操作系统可以在同一网站找到)。这将用于把我们的动画人物转换成 gif。
像安装其他程序一样运行可执行文件并安装,记下它的安装位置。对我来说,这是C:\Program Files\ImageMagick-7.0.9-Q16
。
现在,我们需要更新 Matplotlib 的配置文件来使用 ImageMagick 进行 GIF 导出。要查找该文件位置,请切换到 Python 并键入:
import matplotlib
matplotlib.matplotlib_fname()
这将给你配置文件matplotlibrc
的位置。用文本编辑器打开它。现在,要启用 GIF 支持,找到这一行:
#animation.convert_path: convert
现在用 ImageMagick 的convert.exe
文件的路径替换convert
。这存储在 ImageMagick 目录的顶层。对我来说,这一行变成了:
animation.convert_path: C:\Program Files\ImageMagick-7.0.9-Q16\convert.exe
- 注意,您必须取消对该行的注释,否则它将被忽略。
现在,您可以在 Python 代码中将 Matplotlib 动画anim
保存为 GIF 格式,只需:
anim.save('animation.gif', writer='imagemagick')
现在我们可以分享精彩的动画 Matplotlib 情节!看看这些例子:
正弦波
表面旋转
我希望这个快速教程已经有用,让我知道你是否有任何问题!
有用链接
我为那些想了解 Matplotlib 中可用的动画工具的人提供了一些有用的链接。
动画文档:
https://matplotlib.org/3.1.1/api/animation_api.html
动画教程:
https://jakevdp . github . io/blog/2012/08/18/matplotlib-animation-tutorial/
Matplotlib 中关于动画的优秀文章:
[## Matplotlib 动画
动画是展示一种现象的有趣方式。我们人类总是被动画和…
towardsdatascience.com](/animations-with-matplotlib-d96375c5442c)
用脸书预言家进行快速预测——只需 10 行代码
原文:https://towardsdatascience.com/quick-forecasting-with-facebook-prophet-under-10-lines-of-code-4b23df30e517?source=collection_archive---------51-----------------------
照片由萨曼莎·加德斯在 Unsplash 上拍摄
Python 和 R 程序员的预测
我以前用的是 Rob J Hyndman 的 [fpp2](https://cran.r-project.org/web/packages/fpp2/index.html)
预测包。相当多。它仍然是我的首选预测库。我如此喜欢它的原因是它广泛覆盖了预测技术,并且是一本无价的开放书籍,里面有所有预测理论。时间序列学术研究所需的几乎所有东西都在那里。
但这也是软件包的缺点,它对初学者不友好。谁想造一辆车只是为了在路上开?
然后脸书先知出现了。
预言家对预测练习做了令人难以置信的简化。你可以开箱即用,而不需要理解很多理论,正如你将在下面看到的。
该软件包使用起来非常直观,对于业务预测尤其强大。您甚至可以指定影响业务活动的周末、特殊日子和事件(例如超级碗)。
Cherry 在上面,Prophet 有 python 和 R 编程语言两种版本!
让我们快速演示一下。
1.安装软件包
我是用 Python 做的,所以你所需要的只是用于操作数据的pandas
包。
当然还有Prophet
。
# improt libraries
import pandas as pd
from fbprophet import Prophet
2.导入和格式化数据
我要使用的数据集是一个时间序列,由 1981 年到 1990 年之间的 10 年中记录的每日最低温度组成。
# import data
df = pd.read_csv("[https://bit.ly/3hJwIm0](https://bit.ly/3hJwIm0)")# check out first few rows
df.head()
如您所见,datarame 只有两列,一列在时间维度上,另一列在观察值上。
需要一些数据格式化。Prophet
要求日期时间列命名为“ds”,观察列命名为“y”。
让我们重命名这两列。
# data formating
df = df.rename(columns = {"Date": "ds", "Temp": "y"})
3.模型结构
与 Scikit Learn 算法类似,Prophet
遵循简单的“实例化→拟合→预测”工作流程进行预测。
# instantiate model
m = Prophet()# fit model to data
m.fit(df)
您可以使用参数,但是要构建您的第一个开箱即用的预测模型,就像这两行代码一样简单。
4.预测
现在您已经有了模型,可以做预测了。
就像建立模型一样,预测也是两行代码。在第一行中,创建一个空的数据框架来存储预测值。在第二行中,您将空数据帧传入模型,模型将使用预测值填充行。
# make a forecast dataframe
future = m.make_future_dataframe(periods = 365)# make a forecast
forecast = m.predict(future)
预测已经完成,现在可以在数据框架中查看预测值。
# check out forecast values
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()
列名很直观—
- ds:预测时间步长;
- yhat:预测值
- yhat_lower & yhat_upper:置信区间
预测数据框架
5.测绘
最好是将数据和预测值可视化,看看它们是否吻合。
同样,这只是一行代码。
# plot
fig1 = m.plot(forecast)
在下图中,每个黑点代表原始观测值,深绿色线代表预测模型,浅绿色线代表置信区间。
历史和预测值
那里!你用 10 行代码就做出了一个真正的预测模型!
下一步是什么?
在这篇文章中,我并不打算深入研究这个模型,而是想让人们相信,即使你对理论知之甚少,建立一个预测模型也并不复杂。
下一步,你可以探索其他功能——它们有一个非常容易理解的文档。我特别鼓励人们去探索特殊的日子和事件是如何影响天气预报的(当然不是温度!而是商业活动)。
正如我所说的,您可以在 Python 和 R 编程环境中实现这个包,这给了您一些额外的自由。
欢迎在推特或 LinkedIn 上关注我。
AWS Sagemaker 中的文档化培训快速指南(带代码示例)
原文:https://towardsdatascience.com/quick-guide-to-dockerized-training-in-aws-sagemaker-with-code-example-94909c17556c?source=collection_archive---------50-----------------------
理解大数据
带上您自己的代码,只需几个步骤就可以利用云计算的强大功能!
由 Guillaume Bolduc 在 Unsplash 上拍摄的照片
训练一个模型是乏味的,尤其是当训练脚本耗尽了你所有的计算机能力,你除了等待什么也做不了的时候。这种情况总是发生在我身上——无论是在我开始模型构建过程时,还是在我通过参数调整最终确定模型时。幸运的是,大型云供应商提供了在云中培训和部署您的模型的解决方案,而不必使用您的本地容量。AWS、Azure 和 GCP 都有类似的产品,我在这里使用 AWS Sagemaker 来展示如何使用自己的容器化 docker 来训练云中的模型。
谈到配置,云培训通常是我的噩梦。不同的云供应商有不同的存储、实例和 API 结构,这意味着我们必须通读手册和开发指南才能正常工作。我开始用 Sagemaker 的时候也有这种感觉。但是,我发现 Sagemaker SDK 非常强大,而不是查看他们的控制台并试图在 UI 中找到解决方案。Sagemaker 的典型用法或宣传用法是通过它们的预建算法。但是除非你只是购买一个基线模型,否则你必须使用你自己的模型代码。当然,你可以研究他们的手册,学习如何调整或修改他们的算法 API,但我相信还有更有效的方法。
所以我创建了这个初学者指南来展示一种利用 Sagemaker 训练实例的方法,同时保持使用 docker 训练自己代码的能力。希望解决方案能帮助到有需要的人!
先决条件
这个练习需要一些先决条件。如果您以前使用过 Sagemaker SDK,可以跳过这一部分。否则,请仔细遵循设置。
- AWS CLI 安装&设置
检查此链接,根据您使用的系统按照说明下载并安装 AWS CLI。本教程中的示例是使用 Mac-OS。
如果您没有 AWS 帐户,您可以免费注册一个(注意:这将需要您的信用卡信息,并确保阅读 free-tier 优惠,以防产生任何费用)。
登录到控制台并导航到 IAM。创建一个用户并附加 SagemakerFullAccess 策略。另外,在安全凭证下创建一个访问密钥,并下载凭证。csv 文件。
AWS IAM 控制台
安装 AWS CLI 后,您可以使用凭据进行设置。您刚刚设置的 csv 文件。在终端中,键入以下内容:
aws configure
如果您的用户没有使用 MFA,只需填写从凭证文件中获得的信息,就可以了。否则,请在配置文件中添加您的 MFA 配置文件。
请检查您的配置。如果您的 CLI 设置正确,您应该会看到您的帐户下面列出了 bucket。
aws s3 ls
- Pipenv 设置
这一步是可选的,因为您可以针对您的环境使用其他方法。但是,我将简要介绍如何设置 Pipenv 环境,以便让您能够轻松地理解。
- 在这里克隆我的回购。
- 在您喜欢的 SDE 中打开项目。我正在使用 VSCode。
- 用 pip 安装 pipenv。
pip install pipenv
- 用 Python 解释器初始化 pipenv 环境。我使用的是 3.7 版本。使用
pipenv --python 3.7
进行初始化。 - 用
pipenv install
安装依赖项。
设置正确,它应该导致这样的事情。
模型结构
这个例子将使用房价:高级回归技术数据集,它包含 79 个变量来预测每套房子的最终价格。在比较了一堆模型之后,xgboost 回归器脱颖而出,我们的工作是在训练脚本中微调回归器。RMSE 将是模型选择的标准。
码头工作总结
如果您不熟悉 Docker,请查看 AWS 的本指南。我们在这里要做的是构建我们自己的 docker 映像,并将其推送到 AWS ECR。Elastic Container Registry 是 AWS 提供的托管服务,用于存储和管理 Docker 映像。为了与 Sagemaker SDK 一起使用,我们需要将 docker 映像推送到 ECR,以允许我们的训练实例从那里提取映像。
- Dockerfile
文档化培训工作流程(图片由作者提供)
上图说明了我们如何设置 Dockerfile 文件。建议在将 docker 映像推送到 ECR 之前,先在本地对其进行测试。
- 本地文档化培训
本例将使用 Sagemaker 训练 API 在上述 Docker 映像中测试执行本地训练。
- 将对接器推到 ECR
AWS ECR 提供了一个控制台,只需点击几下鼠标就可以设置 Docker 存储库。如果您想使用控制台,请检查此链接。或者,您可以使用 AWS CLI 通过命令行设置 Docker 存储库。
现在我们的图像设置好了,可以使用了。
在 Sagemaker 培训
一旦我们正确设置了前面的所有步骤,Sagemaker 中启动培训的工作流程就相对简单了。首先,我们需要将数据存储在指定的 S3 桶中。您可以在 AWS 控制台中创建一个并上传数据,或者使用 Sagemaker SDK。然后我们利用sagemaker.estimator
开始训练。
上面的脚本将使用指定的配置启动一个培训作业。检查自由层实例以避免费用。我使用的是“ ml.c4.xlarge ”,如果你的账户在两个月内开通,这应该是自由层实例。培训完成后,您可以在 Sagemaker 控制台中查看您的培训工作:
培训作业控制台视图
您还可以在同一个页面的输出下找到您的 s3 模型工件。通常,estimator
会为您创建一个新的存储桶来存储工件,除非您在output_path
中指定。检查此处的链接是否清晰。
这里需要注意的一点是,如果你想从 Docker 中导出你的模型或输出,只需将文件保存到opt/ml/model
,Sagemaker 会将你想要的输出打包到一个model.tar.gz
,并上传到输出桶。然后,您可以通过 S3 bucket 控制台或 Python SDK 下载并提取该文件。
一个完整的例子,检查我的回购这里。和平!🤗
梯度下降及其变体快速指南
原文:https://towardsdatascience.com/quick-guide-to-gradient-descent-and-its-variants-97a7afb33add?source=collection_archive---------42-----------------------
让我们来理解机器学习中最流行的优化算法,即梯度下降算法及其所有变体。
作者图片
在这篇文章中,我将讨论梯度下降算法。下一篇文章将是这篇文章的延续,我将讨论神经网络中的优化器。为了理解这些优化,深入理解梯度下降是很重要的。
内容-
- 梯度下降
- 学习速度的选择
- 批量梯度下降
- 随机梯度下降
- 小批量梯度下降
- 结论
- 信用
梯度下降-
梯度下降是一种一阶迭代优化算法,用于寻找可微函数的局部最小值。为了得到使我们的目标函数最小化的参数值,我们沿着该函数梯度的相反方向迭代移动,或者简单地说,在每次迭代中,我们沿着最陡下降的方向移动一步。每一步的大小由一个称为学习率的参数决定。梯度下降是一阶算法,因为它使用损失函数的一阶导数来寻找最小值。梯度下降适用于任何维数的空间。
图像来源
梯度下降的步骤-
- 随机初始化参数(权重和偏差)。
- 选择学习率('η')。
- 直到收敛重复这个-
作者图片
其中,'wₜ'是我们必须找到其值的参数,“η”是学习率,l 表示成本函数。
通过重复直到收敛,我们的意思是,重复直到旧的权重值不近似等于它的新值,即重复直到旧值和新值之间的差异非常小。
需要记住的另一件重要事情是,所有权重需要同时更新,因为在计算另一个参数之前更新一个特定参数会导致错误的实现。
一系列等级统计的梯度下降图(来源:维基百科)
学习率的选择(η)
选择一个合适的学习值是非常重要的,因为它有助于决定我们在每次迭代中下降多少。如果学习率太小,下降将会很小,因此将会延迟收敛或不收敛。另一方面,如果学习率太大,那么梯度下降将会超过最小点,最终无法收敛。
图片来源
为了检查这一点,最好的方法是在每次迭代时计算成本函数,然后根据迭代次数绘制成本函数。如果成本不断增加,我们需要降低学习率的值,如果成本以非常慢的速度下降,那么我们需要增加学习率的值。
图像来源
除了选择正确的学习速率值之外,优化梯度下降的另一个方法是将数据标准化到特定的范围。为此,我们可以使用任何类型的标准化技术,如最小-最大标准化、均值-方差标准化等。如果我们不对数据进行归一化,那么大比例的要素将占主导地位,梯度下降将采取许多不必要的步骤。
可能在你学数学的时候,你一定遇到过一个解决最优化问题的方法,通过计算导数,然后使它等于零,然后用二重导数来检查这个点是最小值点,最大值点,还是一个鞍点。一个问题出现在脑海中,为什么我们不在机器学习中使用该方法进行优化。这种方法的问题是它的时间复杂度非常高,如果我们的数据集很大,那么实现起来会非常慢。因此,梯度下降是首选。
梯度下降寻找一个函数的最小值。如果函数是凸的,那么它的局部极小值就是它的全局极小值。然而,如果函数不是凸的,在这种情况下,我们可能会到达一个鞍点。为了防止这种情况发生,我们可以对梯度下降进行一些优化。
梯度下降的局限性-
- 梯度下降时收敛速度慢。如果我们试图通过增加学习速率来加速它,那么我们可能会超过局部最小值。
- 如果我们对一个非凸函数应用梯度下降,我们可能会在局部最小值或鞍点结束。
- 对于大型数据集,内存消耗会非常高。
梯度下降是机器学习中最常用的优化技术。我们来讨论一下梯度下降的一些变体。
批量梯度下降-
批量梯度下降是梯度下降最常见的版本之一。当我们说梯度下降时,通常我们只谈论批量梯度下降。它通过获取数据集中所有可用的数据点来执行计算和更新梯度。对于凸函数来说,它工作得相当好,并且给出了到最小点的直线轨迹。然而,对于大型数据集来说,计算起来既慢又难。
优势-
- 给最小点一个稳定的轨迹。
- 小数据集的计算效率。
局限性-
- 对于大型数据集很慢。
随机梯度下降-
随机梯度下降是梯度下降的一种变体,它一次只考虑一个点来更新权重。我们不会一步计算所有数据的总误差,而是计算每个点的误差,并用它来更新权重。因此,基本上它增加了更新的次数,但每次更新所需的计算量会更少。它基于这样的假设,即每一点的误差都是可加的。因为我们一次只考虑一个例子,所以成本会波动,不一定在每一步都会降低,但从长远来看,成本会降低。随机梯度下降的步骤是
- 随机初始化权重并选择学习率。
- 重复直到获得近似最小值-
- 随机打乱数据集。
- 对于数据集中的每个点,即如果有 m 个点,那么-
作者图片
对整个数据集进行洗牌是为了减少方差,并确保模型保持通用,减少过度拟合。通过混排数据,我们确保每个数据点在模型上创建一个“独立的”变化,而不会受到它们之前的相同点的影响。
图像来源
从上面的图像中可以清楚地看到,SGD 将随着大量的波动而达到最小值,而 GD 将遵循一条直线轨迹。
优势-
- 因为一次只需要处理一个数据点,所以很容易放入内存。
- 与批量梯度下降相比,它更有规律地更新权重,因此它收敛得更快。
- 它在计算上比批量梯度下降更便宜。
- 它避免了非凸函数情况下的局部最小值,因为随机梯度下降引入的随机性或噪声允许我们避开局部最小值并达到更好的最小值。
缺点-
- SGD 可能永远不会达到局部最小值,并且可能由于每一步中的大量波动而在它周围振荡。
- SGD 的每一步都非常嘈杂,梯度下降在不同的方向波动。
因此,如上所述,在大数据集的情况下,SGD 是比批量 GD 更好的主意,但是在 SGD 中,我们必须在准确性上做出妥协。然而,SGD 有各种各样的变体,我将在下一篇博客中讨论,利用它们我们可以在很大程度上改进 SGD。
小批量梯度下降-
在小批量梯度下降中,我们不使用完整的数据集来计算梯度,而是只选择其中的一个小批量。批量的大小是一个超参数,通常选择为 32 的倍数,如 32、64、128、256 等。让我们看看它的方程式-
- 随机初始化权重并选择学习率。
- 重复直到收敛-
作者图片
这里的“b”是批量大小。
优势-
- 比批处理版本更快,因为它一次只考虑一小批数据来计算梯度。
- 计算效率高,易于存储。
- 不易因噪音而过度拟合。
- 像 SGD 一样,它在非凸函数的情况下避免局部最小值,因为由小批量梯度下降引入的随机性或噪声允许我们逃离局部最小值并达到更好的最小值。
- 它可以利用矢量化。
缺点-
- 像 SGD 一样,由于噪声,小批量梯度下降也可能不完全收敛于最小值,并可能在最小值附近振荡。
- 虽然计算小批量梯度下降中的每一步比批量梯度下降快,因为考虑了一小组点,但是从长远来看,由于噪声,需要更多的步骤来达到最小值。
我们可以说 SGD 也是一个小批量梯度算法,批量大小为 1。
如果我们特别比较小批量梯度下降和 SGD,那么很明显,与小批量梯度下降相比,SGD 噪声更大,因此它将波动更大以达到收敛。然而,它的计算成本更低,并且经过一些变化,它可以执行得更好。
结论-
在本文中,我们讨论了梯度下降及其变体和一些相关术语。在下一篇文章中,我们将讨论神经网络中的优化器。
作者图片
学分-
- https://towards data science . com/batch-mini-batch-random-gradient-descent-7a 62 ecba 642 a
- https://towards data science . com/difference-between-batch-gradient-descent-and-random-gradient-descent-1187 f 1291 aa 1
- https://medium . com/@ diva kar _ 239/random-vs-batch-gradient-descent-8820568 eada 1
- https://en.wikipedia.org/wiki/Stochastic_gradient_descent
- https://en.wikipedia.org/wiki/Gradient_descent
作者图片
那都是我这边的。感谢阅读这篇文章。使用的少数图片的来源被提及,其余的是我的创作。请随意发表评论,建议改正和改进。通过 Linkedin 与我联系,或者你可以给我发邮件到 sahdevkansal02@gmail.com。我期待听到您的反馈。查看更多这样的文章我的媒体简介。
随机森林:开始前你需要知道的
原文:https://towardsdatascience.com/quick-intro-to-random-forest-3cb5006868d8?source=collection_archive---------22-----------------------
机器学习
弗拉季斯拉夫·巴比延科在 Unsplash 上的照片
什么是随机森林?
根据官方文档::随机森林是一种元估计器,它在数据集的各个子样本上拟合多个决策树分类器,并使用平均来提高预测精度和控制过拟合。子样本大小始终与原始输入样本大小相同,但样本是用替换的抽取的。
换句话说,随机森林是一种强大但相对简单的数据挖掘和监督机器学习技术。它允许从极大的数据集中快速、自动地识别相关信息。算法最大的优点是依赖于很多预测(树)的集合,而不是信任单个。用随机森林你可以做到:
- C 分类(输入=分类数据),每棵树为最终预测投下一票。
- 回归(输入=连续数据),树的结果被平均以创建最终预测。
我们举个现实生活中的例子来解释一下。假设你正在犹豫下次去哪里度假。你决定向你的朋友拉斯姆斯寻求建议。拉斯莫斯会问你,你已经去过哪里,你做了什么,你是否喜欢它,以了解你喜欢做或看到什么样的事情。根据你的回答和他自己的经历,他会给你一些建议。 在这里,拉斯姆斯正在做一个决策树 来为你提供可能的最佳选择。于是,为了做出最准确的决定,你和“n”个其他朋友重复操作。他们像拉斯姆斯一样问你一些随机的问题,并给你提供不同的去处。每一个回答都像是为去的地方投了一票。有朋友推荐的一些常见的地方。你收集所有的投票并汇总。你决定去票数最多的地方。 在这里,你做的是随机森林。
换句话说,在做决定之前,你是想向一个人征求建议,还是想向许多不同的人征求意见,然后把他们的答案汇总起来再做决定?
这就是你在使用随机森林时所做的事情。通过累积各种树的预测,您正在授权您的分类/回归。
如何建立一个森林?
决策树是随机森林模型的基础。它们很容易理解,因为每个人都有意识或无意识地直观使用它们:
来源:https://www.canva.com/
在数据科学的世界里,决策树一步一步地将数据集分解成更小的子集。最终的结果是一棵有个决策节点和个叶节点的树。
来源:“Python 中的决策树分类。”,纳夫拉尼,阿维纳什。2018.
决策树的优势
- 因为直观所以容易理解。
- 易于解释和可视化,因为它产生了一组规则。
- 对数字和分类数据都开放
- 在大型数据集上表现相当好
- 与 KNN 和其他分类算法相比,以光速工作。
决策树的极限
决策树很简单,但相当不准确。选择下一个节点的一个失策,就可能把你推向完全不同的结果。此外,他们还面临着过度拟合的高风险。
记住: 过度拟合发生在我们的模型捕捉到数据中的噪声和潜在模式时。当我们在嘈杂的数据集上训练我们的模型时,就会发生这种情况。这些模型具有低偏差和高方差。
所以基本上,树越深→对你的数据集越具体→过度拟合的风险越高。
来源:数据挖掘博客——Philippe Fournier-Viger
团结则存,分裂则亡
随机森林算法不是创建一个单独的决策树,而是从随机选择的数据集子集创建许多单独的树。这些单独的树中的每一个生成数据子集内的对象的分类/回归。
它是如何工作的?
让我们考虑我们总共有 m 个特性。
- 随机选择 k 特征,其中 k < m.
- 在 k 特征中,使用最佳分割点计算节点。
- 使用最佳分割方法将节点分割成子节点。
- 重复前面的步骤 n 次。
- 你最终会拥有一片由 n 棵树组成的森林。
- 将决策树的结果组合在一起(即自举)。
随机森林=决策树的简单性*随机性带来的准确性
结论——为什么随机森林是这么酷的 ML 算法?
对异常值和非线性数据相当稳健
随机森林通过本质上的宁滨处理离群值。它对非线性特征也漠不关心。
很好地处理不平衡数据
让我们弄清楚,我们离欠采样、过采样或 SMOTE 方法还很远。随机森林所提供的是,根据类在数据集中的存在情况对它们进行反比例加权的可能性。换句话说,如果您有一个少数民族类和一个多数民族类,则少数民族类的权重将比多数民族类大得多(错误率大),以重新平衡其在数据集中代表性不足的事实。
降低过度拟合的风险
每个独立的引导数据集的分类/回归都可能略有错误。然而,由于该算法依赖于所有自举集的集合,它极大地限制了过拟合,而不会由于偏差而显著增加误差。让我们更详细地了解如何:
→对数据集的子样本进行训练: 每棵决策树的方差都很高,但偏差很低。但是因为我们平均所有的树,我们也平均方差,所以我们有较低的偏差和一个更温和的方差模型。
→对 特征的子样本进行训练
如果我们有 12 个特征,随机森林在每个模型中只会使用一定数量的那些特征。假设 4 乘树,那么 8 个潜在有用的特征被省略。但是由于 Random Forest 是决策树的集合,最终我们的许多或所有特征都会被表示出来。每个树中的特征是随机选择的,以便限制由偏差引起的误差和由方差引起的误差。
我们更有可能击中随机森林的目标
来源:“理解偏差-方差权衡”,2012 年 6 月,Scott Fortmann-Roe
感谢阅读!如果你喜欢这篇文章,就按住按钮鼓掌支持我的写作。我总是愿意聊天和喝杯“虚拟”咖啡,所以来关注我的Linkedin。
[## 通过我的推荐链接加入 Medium-aurélie Giraud
不要错过我的下一篇文章,阅读 Medium 上成千上万的其他作者的文章!我写的是如何使用数据科学…
agiraud.medium.com](https://agiraud.medium.com/membership)
情感分析快速入门
原文:https://towardsdatascience.com/quick-introduction-to-sentiment-analysis-74bd3dfb536c?source=collection_archive---------19-----------------------
什么是情绪分析,如何执行,以及它如何帮助你的业务。
来源: MonkeyLearn
情感分析是确定文本是否表达了对产品或主题的正面、负面或中性观点的自动化过程。通过使用情绪分析,公司不必花费大量时间来标记客户数据,如调查回复、评论、支持票和社交媒体评论。
情绪分析有助于公司监控其在社交媒体上的品牌声誉,从客户反馈中获得洞察力,等等!
在这篇文章中,我们将更详细地介绍什么是情绪分析,如何进行情绪分析,以及它如何帮助你的业务。
我们走吧!
情感分析是如何工作的?
情感分析使用自然语言处理(NLP)方法和算法,包括:
- 基于规则的系统:使用一组手工制作的规则
- 自动系统:依靠机器学习技术从数据中学习
- 混合系统:结合基于规则和自动化的方法
基于规则的情感分析系统:
为了识别极性,这种方法使用自然语言处理(NLP)技术(如标记化、词干化和解析)以及手工制作的规则定义了一组规则。
首先,你需要定义两个对立词的列表(例如,负面词如坏、最差、丑等,正面词如好、最好、漂亮等)。一旦一个基于规则的系统被输入这些预定义的列表,它就会计算文本中出现的正面和负面词的数量,如果正面词多于负面词,则返回正面情绪,反之亦然。
然而,这种方法没有考虑文本中的单词序列,例如,“UX 没那么好”。虽然“没那么好”表达的是消极,但基于规则的系统会检测到“很好”这个词,并将其添加到积极的列表中。
现在,作为一个基于规则的系统,您可以实现新的规则来考虑新的词汇和表达,但是系统可能会变得非常复杂,并且很难维护这么多的规则。因此,这些系统需要大量投资来微调和维护。
自动情感分析系统
这些系统不依赖于手工制作的规则,而是依赖于机器学习技术,如分类。用于情感分析的分类是一个自动系统,在返回类别之前,需要输入样本文本,例如正面、负面或中性。
实施自动化系统包括两个阶段:
- 培养
- 预言;预测;预告
在训练阶段,情感分析模型使用样本数据学习正确地将文本标记为负面的、中性的或正面的。然后,特征提取器将文本转换成特征向量,创建成对的特征向量和标签(例如,肯定的、否定的或中性的),这些特征向量和标签被馈送到机器学习算法中以生成模型。
在预测过程中,特征提取器用于将看不见的文本转换为特征向量,这些特征向量被提供给模型,使其能够进行情感预测。
来源: MonkeyLearn
混合情感分析系统
顾名思义,混合系统结合了基于规则的和自动化的技术,并且通常能够提供更准确的结果。
为什么情感分析很重要?
公司通过社交媒体、调查、在线评论、电子邮件和其他渠道获得的信息比以往任何时候都多。但是,您知道这些数据的 80%是非结构化的吗?因此,如果您想分析这些数据以了解客户的意见,您需要首先对其进行排序。
例如,假设您刚刚推出了一款新产品,并开展了一项调查来了解客户的想法。该调查非常成功,您收到了 1000 份开放式回复。很好,但是你的资源有限,所以要花很长时间去阅读和分析它们。
然而,在分析您的调查回答时,执行情感分析可以节省您的时间、精力和资源。它比手动排序数据更有效,因为它是完全自动化的,这意味着您的团队可以专注于更紧急和重要的任务。
让我们更详细地看看情绪分析的好处:
- 可扩展性
如今,企业接收海量信息— 每天产生超过 2.5 万亿字节的数据!这使得人工代理几乎不可能准确有效地手动分析这些数据。相反,用于情感分析的机器学习模型可以在几秒钟内自动标记你的文本,无论你收到 50 或 5000 条调查回复、评论或社交媒体评论。
- 实时分析
紧急问题会经常出现,它们需要被立即处理。例如,推特上的投诉如果像病毒一样传播开来,可能会迅速升级为公关危机。虽然你的团队可能很难在危机发生前识别危机,但机器学习工具很容易实时发现这些情况。
- 一致标准
假设您进行了一项客户满意度调查,收到了这样的回复:“支持代理速度很快,但非常粗鲁”。你会怎么标记它?正、负,还是空档?如你所见,手动识别文本的情感并不总是简单明了的。你的一些队友可能会根据他们的信仰和经验对文本进行不同的分类。如果他们感到无聊或疲倦,他们可能会犯错误,甚至随着时间的推移改变他们的标准!
另一方面,用于情感分析的机器学习模型在任何时候都应用一致的标准,而且它们永远不会感到累或无聊。
情感分析是用来做什么的?
让我们来看看情感分析是如何被使用的:
政治分析
情感分析可以用于政治分析。
2016 年,全球数百万人在推特上讨论美国大选。我们想了解公众对每位候选人的看法,于是对所有提及每位候选人的推文进行了情感分析,例如:
- “据@CBSNews #ClintonVsTrump 报道,@HillaryClinton 将在今晚的总统辩论中收到第一个问题”。
情绪:中立。 - “美国人信任@realDonaldTrump 让我们的经济再次伟大!”。
情绪:积极。 - “种族不和是由包括@realDonaldTrump 的父亲在内的美国人构想、培育、提炼和延续的。现实点吧!”。
情绪:消极。
以下是结果图表,显示了一段时间内推特用户对特朗普和克林顿的看法:
来源: MonkeyLearn
正如你所看到的,唐纳德·特朗普的被提及次数比克林顿多得多,这表明他在 Twitter 上的存在更多(特朗普每天被提及约 45 万次,而克林顿每天仅被提及 25 万次)。我们还发现,在所有这些推文中,特朗普比克林顿获得了更多的正面提及。
客户服务分析
您还可以分析与客户服务相关的情绪。例如,在线对话可以帮助企业了解客户对其品牌、响应时间、整体客户服务等的感受。
下面,我们分析了四家不同电信公司 (T-Mobile、AT & T、威瑞森和 Sprint)的推文情绪,并得出以下结果:
来源: MonkeyLearn
提及电信公司的正面推文百分比。
结果显示,T-Mobile 以近 20%的正面推文胜出,Sprint 以 15%的正面提及率位居第二。
当将 T-Mobile 的推文与其竞争对手的推文进行比较时,很明显,T-Mobile 在社交媒体上的个人方式会带来更积极的回应,这可能会鼓励其他公司在社交媒体上采用更非正式的个性。
客户反馈分析
您还可以使用情绪分析来分析客户反馈,从在线评论到 NPS 调查。
假设 Tripadvisor 希望对酒店评论进行情感分析,以探索整体情感。我们对超过 100 万条酒店评论进行了分析,发现了一些有趣的见解:
- 大多数评论是正面的:在分析的 400 万篇文本中,82%被标记为正面。
来源: MonkeyLearn
- 伦敦酒店的总体评价最差:伦敦酒店收到的负面评价比其他同等规模城市的酒店多,比如巴黎或马德里。
来源: MonkeyLearn
我们还将 Slack 对 Capterra 的评论分为正面、负面和中立三类,并得出以下结果:
来源: MonkeyLearn
如您所见,Slack 在整合、渠道和群组等类别中获得更多正面提及,但在定价、呼叫或搜索方面获得更多负面提及。这种类型的分析可以帮助企业获得关于如何改善其服务或产品的重要见解。
包裹
简而言之,情绪分析可以在许多方面改善你的业务,从防止公关危机到了解你的客户对你的产品或服务的感受。
手动分类不再适用于企业。他们需要快速、准确和高效的自动化系统,能够提供新的见解并为团队提供支持。
想马上开始情感分析吗?免费注册 MonkeyLearn ,开始使用预先训练的情绪分析模型,看看它如何将你的数据分类为积极、消极和中立。
快速 Python 技巧:隐藏已知异常,而不尝试 Except
原文:https://towardsdatascience.com/quick-python-tip-suppress-known-exception-without-try-except-a93ec34d3704?source=collection_archive---------5-----------------------
照片由凯尔·格伦在 Unsplash 上拍摄
用 Python 更优雅地处理已知异常。
在 Python 中使用try ... except ...
块处理异常是非常常见的。它使我们能够在出现问题时应用一些特殊操作。
然而,有一种特殊情况
- 我们知道这种例外可能会发生
- 我们不关心这个例外
- 如果发生了,什么也不做,直接忽略它
如果情况满足上述条件,就不必使用try ... except ...
来处理异常。相反,Python 内置库contextlib
提供了一个名为suppress
的函数来更优雅地处理这个问题。
定义问题
由 Romain Vignes 在 Unsplash 上拍摄的照片
假设我们有一个可能包含零的数字列表。我们想得到列表中每个数字的倒数,然后对它们求和。如果有零,就忽略它们。
首先,让我们使用随机库来生成这样一个列表。
import randomnums = [random.randint(-3, 3) for i in range(20)]
上面的代码生成了一个大小为 20 的介于(-3,3)之间的整数列表。请注意,您可以有一个没有任何零的列表。如果发生这种情况,只需生成另一个。在这个实验中,我们需要一些零。
现在,假设我们想得到列表中所有数字的倒数。注意数字零没有倒数。因此,如果我们编写如下代码而不处理异常,将会抛出一个ZeroDivisionError
。
results = [1/num for num in nums]
使用 Try Except
威尔·斯图尔特在 Unsplash 上拍摄的照片
解决这个问题最常见和直观的方法是用一个try ... except ...
块来捕捉ZeroDivisionError
异常并忽略它。
result = 0for num in nums:
try:
result += 1/num
except ZeroDivisionError:
passresult
在上面的代码中,我们捕获了ZeroDivisionError
异常,并使用pass
来忽略它。所以,当这个异常发生时,不会抛出任何东西,程序会忽略这个零,继续运行。
使用抑制功能
照片由费德里科·博托斯在 Unsplash 上拍摄
现在,我将向您介绍另一种方法,它使您的代码更加优雅。
在使用这种方法之前,我们需要先从contextlib
进口。
from contextlib import suppress
suppress
函数需要和with
语句一起使用,如下所示:
result = 0for num in nums:
with suppress(ZeroDivisionError):
result += 1/numresult
那不是更简洁直观吗?在我看来,它也更“Pythonic 化”。
因此,使用suppress
函数,作为参数传入的异常将被忽略。
为什么我们要用“压制”?
本节根据@Felix 回复中的一个问题进行了更新。
简短的回答是:不,你不必使用它。
在问题中,有人问我为什么不按如下方式修复它:
result = sum([1/x for x in nums if x != 0])
这是绝对正确的。在本文中,我只想创建一个可以演示 suppress 的场景。我的例子并不完美,因为通过上面的解决方案修复比使用 suppress 函数更好。但是我认为 suppress 函数的价值存在于其他场景中。例如,如果列表是这样的:
nums = [3, -1, -2, 1, 1, 0, 3, 1, -2, 1, 0, -1, -1, -1, 3, -2, -1, 3, '3', -1]
请注意,倒数第二个位置有一个字符串“3”。现在,我们有两个可能的例外。你也可以用上面的方法处理它:
result = sum([1/x for x in nums if x != 0 and type(x) == int])
或者,使用 suppress 函数,只需添加另一种异常类型:
for num in nums:
with suppress(ZeroDivisionError, TypeError):
result += 1/num
那么,如果有更多可能的例外呢?比起在列表理解中添加越来越多的条件,我相信使用 suppress 更优雅。
此外,如果您有两个以上的可能异常怎么办?或者,假设你不关心异常是什么,只想在它发生时绕过它。
for num in nums:
with suppress(Exception):
result += 1/num
所以,您抑制了任何类型的异常:)
限制
马库斯·斯皮斯克在 Unsplash 上拍摄的照片
但是suppress
功能是有限制的。也就是说,不能将 for 循环放在如下的suppress
with
语句中。
result = 0with suppress(ZeroDivisionError):
for num in nums:
result += 1/numresult
为什么我们会有不同的结果呢?这是因为一旦异常发生,for 循环就会被中断。尽管异常仍被忽略,但 0 之后的所有数字也将被忽略。
思想
照片由思想目录在 Unsplash
在本文中,我分享了一种替代方法,当你只是想捕捉异常并忽略它时,这就是来自 Python 中内置库contextlib
的suppress
函数。我认为,就编码风格而言,它更优雅。
然而,我也想提出我对此的一些想法
- 它有一个限制,我们不能在其中放置迭代,比如 for 循环
- 我们需要在使用前导入函数,所以当我们想在代码中的多个地方使用它时,可以使用它
每天我们都能学到一些东西。编码快乐!
[## 通过我的推荐链接加入 Medium 克里斯托弗·陶
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@qiuyujx/membership)
如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和数以千计的其他作者!(点击上面的链接)
使用 Lux 进行基于快速推荐的数据探索
原文:https://towardsdatascience.com/quick-recommendation-based-data-exploration-with-lux-f4d0ccb68133?source=collection_archive---------30-----------------------
通过基于一行建议的数据探索,轻松探索您的数据
作者创建的 GIF
作为一名数据科学家,数据探索或 EDA 是我们的日常工作,也是我们拿工资要做的事情。对于数据科学家来说,没有比数据探索技能更重要的技能了(在我看来)。虽然这很重要,但我们知道这个过程很麻烦,有时会浪费时间。此外,很多时候,我们不知道从哪里开始探索数据。
以下面的 mpg 数据集为例:
import pandas as pd
import seaborn as sns
mpg = sns.load_dataset('mpg')
mpg.head()
作者创建的图像
如果我们不是像我一样的汽车领域的专家,我们从哪里开始探索数据?在这种情况下,我们可以使用 lux 包来尝试基于推荐器的 EDA。
如果您想查看另一个开源 EDA 包,也可以在这里查看我的文章。
[## 数据框 EDA 软件包比较:Pandas Profiling、Sweetviz 和 PandasGUI
哪些熊猫数据框 EDA 包适合你?
towardsdatascience.com](/data-frame-eda-packages-comparison-pandas-profiling-sweetviz-and-pandasgui-bbab4841943b)
无论如何,让我们看看如何使用 lux 软件包来帮助我们探索我们的数据。
勒克斯
Lux 是 Python 中的一个开源包,旨在帮助我们根据他们的建议更智能地探索数据。该软件包的目标是那些在探索数据时不知道从哪里开始的人。
让我们从安装包开始。
pip install lux-api
当您安装完软件包后,我们需要在 jupyter 笔记本中启用 lux 小部件。
jupyter nbextension install --py luxwidget
jupyter nbextension enable --py luxwidget
现在,让我们尝试使用 Lux 包来研究我们的数据。首先,我们需要导入包,以便在我们的笔记本中自动设置小部件。
import lux
就像那样,我们已经设置了 Lux 包来与 Pandas 数据框集成。接下来,让我们尝试打开我们的任何一个数据框;让我们用之前用过的 mpg 数据集试试。
作者创造的形象
在 Lux 包中,我们可以看到一个名为“切换熊猫/Lux”的新按钮。试着按下那个按钮。
力士基本可视化
作者创建的图像
自动地,基于我们的数据集创建一组可视化。默认情况下,创建了三个可视化类别;相关、分布和发生。
相关性选项卡包含两个变量之间的所有数字关系,这些关系通过散点图可视化。可以看到上图的例子。
分布选项卡显示一个单数值变量,其中变量使用直方图可视化。你可以看到下图中的例子。
作者创造的形象
事件选项卡显示分类变量的计数图。它显示了分类变量中的每个类别频率,如下图所示。
作者创造的形象
基于 Lux 推荐的可视化
除了数据框可视化,我们还可以用 Lux 指定我们感兴趣的属性和值,以指导我们的数据探索的潜在后续步骤。
Ler 说我对' mpg '和'马力'属性都感兴趣,因为我知道它们是相关的。我们可以在 Lux 包中指定这两者来指导我们使用.intent
方法,就像下面的行一样。
mpg.intent = ['mpg', 'horsepower']
作者创造的形象
将意图设置到我们的数据框后,Lux 包为我们提供了可视化建议。我们可以看到三种不同的选择:增强、过滤、泛化。
增强选项卡通过向我们当前的意图添加额外的变量来显示可视化建议。本质上它显示了另一个变量如何影响我们感兴趣的变量。可以看到上图的例子。
滤镜选项卡为您设置的当前意图添加一个滤镜;这是在保持属性(在 X 和 Y 轴上)固定的情况下完成的。建议将向我们展示从另一个变量中筛选出来的变量之间的关系。从下图中可以看到,散点图是由 model_year 变量针对列中的每个类进行筛选的。
作者创造的形象
generalize 选项卡删除一个属性以显示更一般的趋势,显示属性的分布。目的是关注我们感兴趣的当前属性。
您也可以尝试数字和分类之间的可变组合。虽然意图的最大变量,你可以指定是三个变量。尽管如此,对您来说,轻松地浏览数据就足够了。
Lux 导出可视化
如果您想将一个可视化图表分离成另一个变量,您可以在 Lux 中完成。我们来看看下图。
作者创建的图像
我们只需要从上面的图像中点击我们想要的图表,直到它们显示出刻度线。之后,点击导出按钮(我给红圈的那个)。这样,我们已经成功地导出了图表。
那么,在哪里访问图表呢?导出的图表实际上存储在我们自己的数据框变量中。让我们试着进入它。
#The visualization is stored in the .exported attribute we could access any timevis = mpg.exported[0]
vis
作者创造的形象
这样,我们已经将我们的图存储到一个不同的变量中。
结论
Lux 是一个基于推荐的系统 EDA,可以帮助我们快速处理数据。这个包给了我们所有可能的数据组合,并根据我们自己的意图探索数据,从而帮助了我们。
如果你喜欢我的内容,并想获得更多关于数据或作为数据科学家的日常生活的深入知识,请考虑在这里订阅我的时事通讯。
如果您没有订阅为中等会员,请考虑通过我的推荐订阅。
使用暹罗伯特网络的快速语义搜索
原文:https://towardsdatascience.com/quick-semantic-search-using-siamese-bert-networks-1052e7b4df1?source=collection_archive---------8-----------------------
使用 Sentence-BERT 库创建适合在大型语料库上进行语义搜索的固定长度的句子嵌入。
图片由 PDPhotos 提供,并从 Pixabay 下载。
我一直在开发一个工具,需要嵌入基于 BERT 的语义搜索。想法很简单:获取语料库中每个句子的 BERT 编码,然后使用余弦相似度来匹配查询(一个单词或另一个短句)。根据语料库的大小,为每个句子返回一个 BERT 嵌入需要一段时间。我试图使用一个更简单的模型(如 ELMO 或伯特即服务),直到我看到尼尔斯·雷默斯和伊琳娜·古雷维奇的 2019 年 ACL 论文“句子-伯特:使用暹罗伯特网络的句子嵌入”。这篇论文的源代码可以从 Github 获得,并且 PyPi 已经准备好了要被 pip 安装的句子-BERT 库(如果你使用 Python 的话)。在这篇博文中,我将简要描述这篇论文解决的问题,并展示一个 Google Collab 笔记本,它展示了使用 SOTA 伯特模型实现语义搜索功能是多么容易。
为什么是连体和三联体网络结构?
BERT 使用交叉编码器网络,将两个句子作为变压器网络的输入,然后预测目标值。BERT 能够在语义文本相似性任务上实现 SOTA 性能,但是两个句子都必须通过完整的网络。在由 10000 个句子组成的语料库中,找到相似的句子对需要大约 5000 万次推理计算,大约需要 65 个小时(如果你有合适的计算能力,例如 V100 GPU)。令人印象深刻的是,BERT 可以在大约 5 秒钟内提供 10000 个句子的编码!!!
句子-BERT 使用连体和三元网络结构微调预训练的 BERT 网络,并向 BERT 的输出添加汇集操作,以导出固定大小的句子嵌入向量。所产生的嵌入向量更适合于向量空间内的句子相似性比较(即,可以使用余弦相似性进行比较)。
…为什么不是伯特即服务?
流行的 BERT-As-A-Service 库通过 BERT 运行一个句子,并通过对模型的输出进行平均来导出一个固定大小的向量。BERT-As-A-Service 也没有在生成有用的句子嵌入的上下文中进行评估。
用句子-BERT 库进行语义搜索
我创建了一个 Google Colab 笔记本来演示如何使用 Sentence-BERT 库创建一个语义搜索示例。Github 回购可从这里获得:SiameseBERT _ semantic search . ipynb
Collab 笔记本的要点版本如下所示:
使用 TF 在 AWS Sagemaker 上快速入门多 GPU 深度学习。分配
原文:https://towardsdatascience.com/quick-start-to-multi-gpu-deep-learning-on-aws-sagemaker-using-tf-distribute-9ee08bc9612b?source=collection_archive---------33-----------------------
向霍洛沃德说再见,向 TF 问好。分配
介绍
本文是使用 AWS Sagemaker 和 TensorFlow 2.2.0 tf.distribute 运行分布式多 GPU 深度学习的快速入门指南。
马库斯·斯皮斯克在 Unsplash 上的照片
密码
我所有与本文相关的代码都可以在我的 GitHub 资源库中找到,这里是。我的存储库中的代码是在 Kaggle 的数据上运行 BERT 版本的一个例子,具体来说就是 Jigsaw 多语言有毒评论分类竞赛。(我的很多代码都是采用了很棒的 顶级公共内核 。)
了解信息的需要
入门指南
首先,我们需要了解我们在 AWS Sagemaker 上运行深度学习的选项。
- 在笔记本实例中运行您的代码
- 在定制的 Sagemaker TensorFlow 容器中运行您的代码
在本文中,我们将重点放在选项#2 上,因为它更便宜,并且是 Sagemaker 的预期设计。
(选项#1 是一个很好的开始方式,但是它更贵,因为你要为笔记本实例运行的每一秒付费)。
运行 Sagemaker TensorFlow 容器
Sagemaker TensorFlow 容器有很大的灵活性,但我们将重点放在最基本的东西上。
照片由乌帕德克·马特米在 Unsplash 拍摄
首先,我们需要启动一个 Sagemaker 笔记本实例,并将我们的数据存储在 S3 上。如果你不知道如何做到这一点,我在我的博客上回顾了一些简单的选择。一旦我们在 S3 有了数据,我们就可以启动一个 Jupyter 笔记本(从我们的笔记本实例)并开始编码。该笔记本将负责启动您的培训工作,即您的 Sagemaker TensorFlow 容器。
同样,我们将把重点放在最基本的东西上。我们需要一个变量来指示数据的位置,然后我们需要将该位置添加到字典中。
data_s3 = 's3://<your-bucket>/'
inputs = {'data':data_s3}
很简单。现在我们需要创建一个 Sagemaker TensorFlow 容器对象。
我们的入口点是一个 Python 脚本(我们稍后会制作),它包含了我们所有的建模代码。我们还希望 script_mode =True,因为我们正在运行自己的训练脚本。
我们的 train_instance_type 是一个多 GPU Sagemaker 实例类型。您可以在这里找到 Sagemaker 实例类型的完整列表。注意一个 ml.p3.8xlarge 运行 4 个V100 NVIDIA GPU。由于我们将使用 MirroredStrategy (稍后将详细介绍)我们需要train _ instance _ count = 1。也就是说,1 台机器配有 4 台 V100s。
我们还需要将输出路径设置到 S3 的一个位置。这是 Sagemaker 将我们保存到路径“/opt/ml/model”中的所有内容自动存储到的地方。例如,如果我们将最终的模型保存到训练脚本中的容器路径“/opt/ml/model”中,那么当训练工作完成时,Sagemaker 会将模型加载到我们的 S3 位置。
其他的设置你可以暂时不管,或者根据需要进一步研究。综上所述,我们需要弄对的主要设置有入口 _ 点、脚本 _ 模式、训练 _ 实例 _ 类型、和输出 _ 路径。(然后对于 MirroredStrategy 我们需要 train_instance_count=1)。**
*# create estimator
estimator = TensorFlow(entry_point='jigsaw_DistilBert_SingleRun_v1_sm_tfdist0.py',
train_instance_type='ml.p3.8xlarge',
output_path="s3://<your-bucket>",
train_instance_count=1,
role=sagemaker.get_execution_role(),
framework_version='2.1.0',
py_version='py3',
script_mode=True)*
我们可以通过运行下面的代码来开始我们的培训工作。
*estimator.fit(inputs)*
注意,我们包含了我们的字典(包含我们在 S3 的位置)作为‘fit()’的输入。在运行这段代码之前,我们需要创建 Python 脚本,并将其分配给 entry_point (否则我们的容器将没有任何代码可以运行:-P) 。
创建培训脚本
我在 GitHub 上的训练脚本非常繁忙,因为我正在对 Kaggle 的一些数据运行 BERT 版本。我们唯一需要的是访问我们的数据,然后我们可以将任何结果保存到容器路径“/opt/ml/model”。
在 Unsplash 上由 Brooks Leibee 拍摄的照片
获取数据的最简单方法是在培训脚本中硬编码您在 S3 的位置。
我们还可以从“estimator.fit(inputs)”传递的值中获取 S3 位置。我们可以使用 argparse 来做到这一点。
*def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument(‘ — data’,
type=str,
default=os.environ.get(‘SM_CHANNEL_DATA’))
return parser.parse_known_args()args, _ = parse_args()*
如果我们想做的只是在 Sagemaker 容器中运行我们的培训工作,那基本上就是我们所需要的!现在,如果我们想使用 tf.distribute 运行多 GPU 训练,我们还需要一些东西。
和霍洛佛德说再见,和 TF 打招呼。分配
照片由泰勒维克在 Unsplash 上拍摄
首先,我们需要表明我们想要运行多 GPU 训练。我们可以用下面的代码很容易地做到这一点。
*strategy = tf.distribute.MirroredStrategy()*
有关 MirroredStrategy 的更多信息,我会查看 TensorFlow 文档。现在我们将在整个训练代码中使用我们的策略对象。接下来,我们需要通过包含以下行来调整多 GPU 训练的批量大小。
*BATCH_SIZE = 16 * strategy.num_replicas_in_sync*
我们将在后面的“model.fit()”调用中使用变量 BATCH_SIZE。
最后,在定义模型时,我们需要再次使用策略。
*with strategy.scope():
# define model here*
就是这样!然后,我们可以继续运行我们通常使用的“model.fit()”。
同样,与本文相关的完整代码可以在我的 GitHub 存储库中找到,这里是。
感谢您的阅读,并希望您发现这是有帮助的!
不想从初级职位开始的职业转换者的快速提示
原文:https://towardsdatascience.com/quick-tips-for-career-switchers-who-doesnt-want-to-start-from-a-junior-position-3640a13652ac?source=collection_archive---------70-----------------------
与刚毕业的学生相比,你应该做些什么
照片由Pexelsfaxels发自PexelsPexels
如果你是一个职业转换者,这意味着你已经有了大量的职业经验。我敢肯定,当你将职业生涯转向数据科学时,你不会希望从初级职位开始。这不是一个不合理的期望。你工作的这些年应该有所回报吧?
这就是为什么你需要突出你与那些想进入初级职位的应届毕业生的不同之处。
这里有一些在申请数据科学职位时要记住的快速提示。这些将帮助你传达你的价值,并确保你不会被认为是一个初学者的数据科学家,而是一个经验丰富的专业人士,将对组织做出重大贡献。
谈谈你在之前的工作中承担的责任。
具体来说,如果你管理过人员或项目。强调你在这些项目中面临的一些挑战,并在你的面试或求职信中提到它们。
无论你的专业经验与数据科学多么不相关,它都将使你与应届毕业生区分开来,并让你获得一个高于初级的职位。不要犹豫地谈论你以前的职位。谈谈你遇到的问题,你是如何克服的,这段经历教会了你什么,以及你现在如何在工作中应用这种新的理解。
数据科学主要是关于数据,而不是关于花哨的机器学习算法。
在你的面试中,不要谈论你是如何迫不及待地使用 ML 算法。对机器学习的过度兴奋往往会让人看起来很业余。这甚至是社区里一个非常常见的笑话。
领域知识很重要。
表明你知道这是至关重要的。这是一个真正的、公认的数据科学家的特质。确保你在与公司的通信中足够重视领域知识。
如果你在他们的领域有任何先验知识,让他们知道。
- 谈论一些你知道的在那个领域可能会出错的事情,或者那个行业的一般斗争。
- (即使您不知道具体的领域)花时间思考他们可能会遇到什么类型的数据问题。在你的求职信或面试中提到这些。
你的问题显示了你的水平
永远不要对面试官说你没有任何问题。在面试中问一些相关的问题,例如:
- 项目的类型
- 他们从哪里获得数据
- 他们如何部署他们的项目
- 是否有 ML 工程师的工作是部署或者你将部署代码
- 他们如何维护他们的模型
- (如果相关)他们如何存储数据以及如何处理隐私问题
- 你知道的其他问题形成了他们的特定领域
这将表明你了解总体流程,并且比一个没有专业经验的新毕业生处于更高的水平。
每一点都很重要
这可能不是每个人都能做到的,但是如果是这样的话,试着用你现在的角色的数据来做项目。可能小到可视化一些数据,也可能复杂到训练一个模型。如果你的作品能被你现在的公司使用,那就太好了。它将帮助你更好地理解现实生活中专业数据科学的斗争。但更重要的是,这将向你未来的雇主表明,你曾在专业环境中与数据打交道,你渴望提高自己。
当申请数据科学职位时,我们要传达的主要信息是:“我知道我以前没有做过数据科学家,但我有宝贵的专业经验,我有能力,我已经自学了很多数据科学知识。你应该雇用我,因为我会带来很多价值。”
如果你读过我的文章“初级和高级数据科学家之间不言而喻的差异”,你就会知道初级和高级数据科学家之间的一个关键差异是管理技能。毕竟,公司寻找的是能够应对现实生活中充满挑战的情况的人。有时甚至超过技术上的卓越。所以一定要让你的职业经历大放异彩!
如果你还有什么要补充的,请告诉我。我很想知道你申请高级数据科学职位的策略是什么。
👉对数据科学领域以及如何开始学习感到困惑? 免费参加数据科学入门迷你课程 !
快速教程:使用贝叶斯优化调整 PyTorch 中的超参数
原文:https://towardsdatascience.com/quick-tutorial-using-bayesian-optimization-to-tune-your-hyperparameters-in-pytorch-e9f74fc133c2?source=collection_archive---------11-----------------------
设计神经网络的更快方法
超参数调音就像调音吉他一样,因为我自己不会调音,所以更愿意使用应用程序。照片由阿迪·戈尔茨坦在 Unsplash
超参数是模型中决定模型架构、学习速度和范围以及正则化的参数。
寻找最佳超参数需要一些专业知识和耐心,您经常会发现人们使用网格搜索和随机搜索等令人疲惫的方法来寻找最适合他们问题的超参数。
快速教程
我将向您展示如何使用 Ax 在 PyTorch 中实现贝叶斯优化,以自动找到针对您的神经网络的最佳超参数集。
我们将使用迁移学习构建一个简单的 CIFAR-10 分类器。大部分代码来自 CIFAR-10 分类器的官方 PyTorch 初学者教程。
我不会深入贝叶斯优化的细节,但你可以在 Ax 网站上研究该算法,阅读原始论文或 2012 年关于其实际用途的论文。
首先,像往常一样
使用以下工具安装 Ax:
pip install ax-platform
导入所有必需的库:
下载数据集并构建数据加载器(我建议稍后将训练批量调整为 32 或 64):
让我们通过创建一些辅助函数来看看 CIFAR-10 数据集:
培训和评估职能
Ax 需要一个返回训练模型的函数,以及另一个评估模型并返回性能指标(如准确性或 F1 分数)的函数。我们在这里只构建训练函数,并使用 Ax 自己的evaluate
tutorial 函数来测试我们的模型性能,它返回准确性。如果你愿意,你可以看看他们的 API 来模仿他们的评估函数。
接下来,我们编写一个init_net()
函数,它初始化模型并返回网络准备训练。这里有很多超参数调优的机会。您会注意到parameterization
参数,它是一个包含超参数的字典。
最后,我们需要一个train_evaluate()
函数,贝叶斯优化器在每次运行时都会调用它。优化器在parameterization
中生成一组新的超参数,将其传递给这个函数,然后分析返回的评估结果。
优化!
现在,只需指定想要扫描的超参数,并将其传递给 Ax 的optimize()
函数:
这确实花了一些时间,但与对所有 3 个超参数进行简单的网格搜索相比,这算不了什么。让我们来看看结果:
results[INFO 09-23 09:30:44] ax.modelbridge.dispatch_utils: Using Bayesian Optimization generation strategy: GenerationStrategy(name='Sobol+GPEI', steps=[Sobol for 5 arms, GPEI for subsequent arms], generated 0 arm(s) so far). Iterations after 5 will take longer to generate due to model-fitting.
[INFO 09-23 09:30:44] ax.service.managed_loop: Started full optimization with 20 steps.
[INFO 09-23 09:30:44] ax.service.managed_loop: Running optimization trial 1...
[INFO 09-23 09:31:55] ax.service.managed_loop: Running optimization trial 2...
[INFO 09-23 09:32:56] ax.service.managed_loop: Running optimization trial 3......[INFO 09-23 09:52:19] ax.service.managed_loop: Running optimization trial 18...
[INFO 09-23 09:53:20] ax.service.managed_loop: Running optimization trial 19...
[INFO 09-23 09:54:23] ax.service.managed_loop: Running optimization trial 20...{'lr': 0.000237872310800664, 'batchsize': 117, 'momentum': 0.99}
{'accuracy': 0.4912998109307719}
{'accuracy': {'accuracy': 2.2924975426156455e-09}}
当动量为 0.99 且批量为 117 时,我们的最佳学习率似乎是 2.37e-4 。那很好。这里你看到的 49.1%的精度并不是模型的最终精度,不用担心!
我们可以更进一步,绘制一些图,显示每个时期的精度(随着参数化的改进而改进),以及优化器使用等高线图作为两个超参数的函数的估计精度。experiment
变量属于Experiment
类型,你一定要查看文档看看它提供的所有方法。
渲染的情节易于理解和互动。等高线图中的黑色方块表示实际采样的坐标。
最后,您可以通过简单地运行下面的脚本来获取具有最佳平均精度的参数集(Ax 称之为“arm”)。
Arm(name=’19_0', parameters={‘lr’: 0.00023787231080066353, ‘batchsize’: 117, ‘momentum’: 0.9914986635285268})
不要害怕调整你想要的任何东西,比如隐藏层数和大小、漏失、激活功能、解冻深度等等。
快乐优化!
COVID19 超额死亡率的快速不确定性估计
原文:https://towardsdatascience.com/quick-uncertainty-estimates-for-covid19-excess-mortality-1e39e6c94bd7?source=collection_archive---------55-----------------------
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
F 还是最近的一个故事 经济学家收集了大量的时间序列数据来进行每个国家的 COVID“超额死亡”分析。
使用的方法相当简单:
- 计算数据集中包含的 2020 年之前所有年份的每个国家的每周平均死亡人数
- 计算 COVID 爆发后实际每周死亡人数与“预测”平均每周死亡人数之间的差异
- 从疫情发病开始求和,以获得超额死亡总数。
- 与国家统计局报告的与 COVID 相关的死亡进行比较
根据《经济学人》的模型https://www . Economist . com/graphic-detail/2020/04/16/tracking-新冠肺炎-超额死亡-跨国家
虽然这是一个有趣的数据新闻,但从数据科学的角度来看,他们的方法有两个主要的问题:
- 任何试图建立基于历史观察的反事实结果的方法都将关键取决于模型的选择。我们怎么知道周均值模型是合理的?
- 我们如何知道观察到的差异不仅仅是由于采样误差?(碰巧)。或者更具体地说,我们如何更准确地确定超额死亡的全部后验分布?
因此,在接下来的内容中,我将尝试使用现成的预测工具来快速解决这些问题。幸运的是,《经济学人》已经在 github 上发布了本文使用的所有数据,所以我们可以马上开始。
描述性分析
对所提供数据的快速分析表明,在构建时间序列方面已经做了大量工作,但在将国家来源提供的数据统一到一个共同的每周汇总水平方面仍然存在明显的挑战:图 1 表明,我们缺少数据,而且各国的历史视野不同。
图 1:六个国家每周总死亡人数。start_date 表示各周的第一天。
虽然这可能会在未来提出一些建模挑战(例如,缺少数据,与 ARIMA 不太相符),但让我们首先评论一下整个过程的一般模式:首先,我们可以看到一个明显的年度模式,在冬季月份前后有年度高峰(德国在 3 月份左右)。其次,我们清楚地看到 2020 年第一季度的峰值,这与疫情的爆发相吻合。第三,更微妙的是,在人口增长和大致不变的死亡率的驱动下,死亡人数存在长期趋势。
为了激励我们的超额死亡数估计,让我们引入一个最小程度的形式主义。假设 y_{it}⁰表示第 t 周和国家 I 的每周死亡人数,如果 COVID19 没有实现,y_{it}表示实际死亡人数。假设 COVID 周期的开始时间为 t*(注意,这类似于回归不连续设计文献中研究的问题),则国家 I 的超额死亡率为:
假设 y_{it}可以准确无误地测量(如此盲目地相信国家统计局),我们仍然无法在不推理反事实数列 y_{it}⁰.的情况下计算上面的表达式为了这个练习的目的,我们采用 facebook 的 prophet package 中的假设:即我们假设 y_{it}⁰是由一个(贝叶斯) GAM 生成的:
而 g_i(t)包含国家特定的趋势成分,s_i(t)表示季节性因素,ε是一个特殊的误差项。Prophet 使用直接傅立叶分解来处理季节性成分,有关更多详细信息,请查看 my code 和 Prophet Paper (p11)。
为了确保我们对 y_{it}⁰的预测只反映前 COVID dgp,我估计了 2020 年前数据的 g_i(t)和 s_i(t)的参数。此外,我选择了一个线性时间趋势,加上季节性成分,分别具有季度和年度周期。使用 MCMC 和 1000 次复制完成参数估计。
随后,我们可以简单地使用估计后验样本来计算所需的增量。
其中 s 表示蒙特卡罗样本指数,t_i^{end}表示我们数据中国家 I 的最后一个现有时间指数,t*被设置为 2020 年 2 月 1 日。请注意,当然,为了捕捉长期影响,我们需要 y_{it}的更长时间序列,但是,基于当前数据,我们可以在官方 COVID 统计中可视化潜在的过度/不足归因。
最后,将所有的成分放在一起,我们得到了每个国家的估计 COVID 超额死亡率分布,加上一条红色的垂直线表示官方计数。(X 轴的刻度从 0 到 100k。)
图 2:不同国家超额死亡率的分布——注意德国的大部分概率位于零的左边。红色虚线表示特定国家报告的由 COVID 引起的死亡。
图 2 显示超额死亡率报告似乎与我们估计的分布大致一致。美国和德国的数据差异很大,有限的数据使得对意大利的精确估计颇具挑战性。请注意,红色垂直线和我们的分布模式之间的差异不一定表明 COVID 死亡的过度/不足归因:公共卫生服务压力的增加也可能增加不相关疾病的死亡。
德国怎么了?
从上面的直方图中可以明显看出,德国 2020 年春季的死亡人数比我们的模型预测的要低得多(因此出现了负的超额死亡人数)。然而,这似乎不是不合理的模型预测的结果,而是 2020 年 3 月和 4 月德国异常低的死亡率。这一时期是否有其他一些共同因素,或者数据来源是否有误,仍有待确定。
德国实际与预测的超额死亡
结论和进一步的工作
在这个小练习中,我试图将《经济学人》中的简单结果与更复杂的基于 ts 建模的方法进行对比,这种方法更适合处理季节性计数数据。贝叶斯实现还为我们提供了一种构建预测区间的简单方法。美国和德国报道的死亡人数和估计的死亡人数之间的负差异最大,而英国和意大利似乎略有低估。
尽管我认为贝叶斯 GAM 具有线性趋势和季度/年度季节性成分,可以合理地拟合不同国家,但上述结果取决于时间序列模型的质量(因此可以从进一步的敏感性分析中受益)。我敢肯定,许多研究希望弄清楚对 COVID 的实际影响,我们可以期待大量的论文阐明这个问题。我希望这篇文章和代码能让一些人入门,我期待着你的评论和建议。
代码:
https://github.com/citizenkeynes/CovidExcessDeath/
使用浏览器控制台快速提取网页中的所有链接
原文:https://towardsdatascience.com/quickly-extract-all-links-from-a-web-page-using-javascript-and-the-browser-console-49bb6f48127b?source=collection_archive---------0-----------------------
使用几行 JavaScript 提取网页上的所有超链接,不需要编码环境
使用控制台从网页中提取链接
从网站和文档中提取和清理数据是我的工作,我非常喜欢学习如何使用 Python 和 r 从多个网页甚至多个网站中系统地提取数据。但有时一个项目只需要少量数据,仅来自网站上的一个页面。
以前,当出现这种情况时,我仍然会启动 Python IDE 或 RStudio,编写并执行一个脚本来提取这些信息。这是用大锤砸坚果。常规的旧 JavaScript 足够强大,可以从单个网页中提取信息,并且有问题的 JavaScript 可以在浏览器的开发人员控制台中运行。
在这个例子中,我从一个网页中提取所有链接,因为这是我经常在网页上执行的任务。然而,这段代码同样适用于提取 HTML 文档中的任何其他文本元素类型,只需做一些小的修改。当这段代码运行时,它会在浏览器中打开一个新的选项卡,并输出一个包含每个超链接的文本和链接本身的表格,因此每个链接所指向的内容有一些上下文。
你将需要这个项目:
- 几乎所有过去 10 年生产的浏览器。
- 我将在页面的下方提供一些代码。
- 就是这样!
代码及其工作原理
打开你的浏览器(是的,如果你不怕惩罚的话,这在 Internet Explorer 中也能工作)并导航到你想要提取链接的页面。
2017 年议会的特别委员会质询
我用 2017 年议会页面的特别委员会询问列表作为例子——这是一个有大量链接的页面,作为一个分组,可能对很多人都有用。
现在我们只需要打开开发人员控制台并运行代码。要打开开发人员控制台,您可以按 F12 或者右键单击页面并选择“检查”或“检查元素”,这取决于您选择的浏览器。这将打开控制台,您可以在其中键入或复制并粘贴代码片段。
这是您需要放入控制台的代码片段:
var x = document.querySelectorAll("a");
var myarray = []
for (var i=0; i<x.length; i++){
var nametext = x[i].textContent;
var cleantext = nametext.replace(/\s+/g, ' ').trim();
var cleanlink = x[i].href;
myarray.push([cleantext,cleanlink]);
};
function make_table() {
var table = '<table><thead><th>Name</th><th>Links</th></thead><tbody>';
for (var i=0; i<myarray.length; i++) {
table += '<tr><td>'+ myarray[i][0] + '</td><td>'+myarray[i][1]+'</td></tr>';
};
var w = window.open("");
w.document.write(table);
}
make_table()
然后只需按下回车键(或 IE 中的运行按钮。但是说真的,你为什么用 IE?!).这将在您的浏览器中打开一个新的选项卡,其中包含您选择的网页中的所有链接文本和超链接。
代码运行后表格的显示方式。
然后,可以将该表复制并粘贴到电子表格或文档中,以便您随意使用。
代码在做什么?
下面是代码的分解和每个方面的作用。
var x = document.querySelectorAll("a");
var myarray = []
在这里,我们找到页面上的所有“a”元素(a 元素是链接),并将它们赋给变量 x。
for (var i=0; i<x.length; i++){
var nametext = x[i].textContent;
var cleantext = nametext.replace(/\s+/g, ' ').trim();
var cleanlink = x[i].href;
myarray.push([cleantext,cleanlink]);
};
然后我们遍历 x 中的所有“a”元素,对于每个元素,我们试图找到元素和链接的文本内容。
对于文本内容,我们用单个空格替换空白并修剪文本,因为可能有大量空白会使我们的表格不可读。
function make_table() {
var table = '<table><thead><th>Name</th><th>Links</th></thead><tbody>';
for (var i=0; i<myarray.length; i++) {
table += '<tr><td>'+ myarray[i][0] + '</td><td>'+myarray[i][1]+'</td></tr>';
};
var w = window.open("");
w.document.write(table);
}
make_table()
然后,我们使用函数“make_table()”制作表格。这将创建一个变量 table,它以 HTML 表格和表格标题开始。然后,我们使用 for 循环来添加包含链接文本和超链接的表格行。
然后,我们使用“window.open()”打开一个新窗口,并使用“document.write()”将 HTML 表写入该窗口。
但是……?
当前的代码有一个缺点——它需要一个页面上的所有链接。这意味着菜单中的所有链接,任何带你到当前页面不同点的跳转链接,联系人,条款和条件,页面底部的网站地图链接等等…
您可以更具体地在网页的某个区域中查找所有“a”元素。对于上面的委员会查询页面,我们只需更改第一行代码,让查询选择器查看页面的特定区域——可能只是页面中央的 a-z 列表。
为此,右键单击您想要获取链接的页面区域,然后单击“检查”。然后,您应该能够看到该页面元素的名称。在本例中,元素是一个“div ”,带有类“a-to-z-listing”。我们可以简单地更改第一行,在具有“a-to-z-listing”类的元素中查找所有“a”元素:
var x = document.querySelectorAll(".a-to-z-listing a");
在我的大部分 web 抓取活动中,我仍然会使用 Python 和 R,但是有一种快速简单的方法来从 web 页面中提取信息而不需要打开任何其他应用程序是很有帮助的。
你会用这个代码做什么?有没有更优雅的方法来构造这段代码?请在下面的回复中让我知道。
在 Jupyter 实验室中快速标记数据
原文:https://towardsdatascience.com/quickly-label-data-in-jupyter-lab-999e7e455e9e?source=collection_archive---------18-----------------------
使用 pigeonXT 来标记所有种类的数据
随便问一个人数据科学家是做什么的,他或她可能会回答说数据科学家使用最先进的算法提供数据驱动的解决方案。如果那个随机的人碰巧是(或认识)一个数据科学家,他或她很可能会用这个笑话来回应:80%的时间数据科学家在清理数据,20%的时间数据科学家抱怨不得不清理数据。玩笑归玩笑,数据科学家确实花了很多时间清理和调整数据集,并且通常总是在寻找改进过程。尤其是当一项任务不那么令人兴奋时,比如贴标签。
我发现数据标注的过程非常有益(甚至会上瘾)。每次我标记一个例子,我都觉得我的知识、经验和技能被转移到了模型中。“我真的无法理解数据科学家为什么抱怨被要求这么做,”安德里·布尔科夫
对于一个 NLP 项目,我们需要一个工具来将短文本分成一个或多个类别。在短短的五分钟“让我们自己写吧”之后,你很快就会得出结论,Python 社区中可能已经提供了一些东西。事实上,有许多像标签工作室或产品这样的解决方案,它们确实是很棒的解决方案,但在我们的品味中太过一般。稍微搜索了一下,我们找到了我们想要的工具:鸽子由 Anastasis Germanidis 创造。这非常简单:在 Jupyter 中,你向一个函数输入一个文本列表和一个标签列表,然后弹出一个小部件来遍历每个例子。结果再次以列表形式给出。唯一的缺点是它还不支持多标签。
在 Github 上共享代码最棒的一点是,每个人都可以分享代码并进行修改。不幸的是,Anastasis 没有回复讨论变化和拉请求的电子邮件。因此,我们决定将这些更改发布为 PigeonXT ,Pigeon 的扩展版本。
PigeonXT 目前支持以下注释任务:
- 二元/多类分类
- 多标签分类
- 回归任务
- 字幕任务
任何可以在 Jupyter 上显示的内容(文本、图像、音频、图表等。)可以通过提供适当的display_fn
参数由 pigeon 显示。
此外,定制挂钩可以附加到每个行更新(example_process_fn
),或者当注释任务完成时(final_process_fn
)。
装置
与最初的 Pigeon 一样,扩展的 PigeonXT 被上传到 Python 包索引,并且可以使用 pip 进行安装。在这篇 blob 帖子中,我们给出了几个例子。要运行这些,我建议首先创建一个新的环境。我们正在使用 Miniconda 管理环境,完整的程序在这里描述。要创建新环境并安装要求,请在 shell 中键入以下内容:
conda create --name pigeon python=3.7
conda activate pigeon
conda install nodejs
pip install numpy pandas jupyterlab ipywidgets
jupyter nbextension enable --py widgetsnbextension
jupyter labextension install [@jupyter](http://twitter.com/jupyter)-widgets/jupyterlab-manager**pip install pigeonXT-jupyter**
要启动 Jupyter Lab,只需在同一个 shell 中键入以下内容:
jupyter lab
例子
所有的例子也可以在我的 Github 页面的笔记本中找到。
二元或多类文本分类
多类分类或二元分类(如果只提供两个标签)非常简单:
多标签文本分类
将多个类标注到同一个示例中称为多标签标注,这与前面的示例几乎相同:
图像分类
可以与 Jupyter 交互的任何类型的结构(图像、音频、电影)的分类也可以同样容易地进行标记:
带有自定义挂钩的多标签文本分类
虽然自定义挂钩可能会再次增加复杂性,但这里有一个用例示例。当有一个包含 1000 个例子的数据框架要标记时,一次做的事情可能太多了。不仅是身体上的时间,也是为了防止无聊到发疯。在这里,您可以编写一个包装器来包装注释函数,以选择一部分并将该部分保存到磁盘。下一次,它检查输出,并在您停止的地方继续。这部分写在包装器和 final_processing 函数中。
作为一个基于行的钩子函数的例子,我们将标签改为它们的数字等价物,并用每一行更新数据帧。现在,您可以看到数据框中充满了每个步骤。
围捕
标注数据有许多有用的工具。我发现的大多数工具都非常完整,但也相对复杂。我们正在寻找一个简单的工具,可以直接从 Jupyter 使用。Pigeon 已经是一个很好的工具了,但是我们需要增加一些功能来满足我们的需求。我们也享受了创建/更改新的 Python 包并与社区共享的小小努力。如果您有任何问题或只是觉得有用,请告诉我。
免费使用 ngrok 从 Google Colab 快速共享 ML WebApps
原文:https://towardsdatascience.com/quickly-share-ml-webapps-from-google-colab-using-ngrok-for-free-ae899ca2661a?source=collection_archive---------14-----------------------
互联网上有一个笑话,讲的是大多数机器学习模型最终如何出现在 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/
快速比较多个模型
原文:https://towardsdatascience.com/quickly-test-multiple-models-a98477476f0?source=collection_archive---------5-----------------------
如何高效地训练和评估多个模型
介绍
所有数据科学家在从事任何机器学习项目时都必须面对的一个问题是…
哪种模型架构最适合我的数据?
有几个理论问题需要考虑。例如,如果您的要素显示出与因变量(目标)的强线性关系,那么线性模型可能最适用。如果关系是非线性的,那么 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 快速而不下流地绘图
原文:https://towardsdatascience.com/quickn-dirty-plotting-with-python-4a2c6e06d4f4?source=collection_archive---------50-----------------------
照片(背景)由米切尔罗在 Unsplash
使用 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 '干净…但你需要记住,你只需要创建这些代码一次。在这之后,一切都是点击!像这样的工具一开始可能需要一点时间来制作,但是从长远来看,它们将会为您节省很多时间,并使可视化数据变得更加容易和灵活。尽情享受吧!
快速推进,反向传播的替代方案
原文:https://towardsdatascience.com/quickprop-an-alternative-to-back-propagation-d9a78069e2a7?source=collection_archive---------29-----------------------
斯科特·法尔曼加速梯度下降的想法
由于 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 中的快速排序
原文:https://towardsdatascience.com/quicksort-in-python-dbefa7dcf9cc?source=collection_archive---------8-----------------------
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
原文:https://towardsdatascience.com/quickstart-apache-spark-on-kubernetes-18d01ea5df7d?source=collection_archive---------48-----------------------
使用 Kubernetes 的本地 Apache Spark 操作器,让您的大负载平稳运行
金赛在 Unsplash 上的照片
介绍
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 分钟内启动并运行
原文:https://towardsdatascience.com/quickstart-spacy-on-aws-lambda-up-and-running-in-10-minutes-e347037a0ef8?source=collection_archive---------27-----------------------
使用 spaCy 进行无服务器计算的简单方法
在 Unsplash 上由 QHUNG TA 拍摄的照片
让我们信守承诺,先把事情做好。如果您想进一步阅读,快速入门部分将提供进一步的讨论。我希望这种安排能节省你的时间。
快速入门:循序渐进
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 的定制和非对称损失函数
原文:https://towardsdatascience.com/quirky-keras-custom-and-asymmetric-loss-functions-for-keras-in-r-a8b5271171fe?source=collection_archive---------11-----------------------
实践教程
[图片由蒙提洛夫在 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)。博士论文。
不要试图预测市场
原文:https://towardsdatascience.com/quit-trying-to-predict-the-market-27d77149a709?source=collection_archive---------12-----------------------
为什么 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 模型的结果
这个故事的寓意是:尽你所能预测股市,但千万不要在现实生活中使用它。非常感谢你的阅读,我希望你喜欢!
免责声明:本文材料纯属教育性质,不应作为专业投资建议。自行决定投资。
如果你喜欢这篇文章,看看我下面的其他文章吧!
[## 使用 Python 在几分钟内解析数千份股票推荐!
了解如何在不到 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 问题对:使用暹罗网络检测文本相似性。
原文:https://towardsdatascience.com/quora-question-pairs-detecting-text-similarity-using-siamese-networks-a370f039731b?source=collection_archive---------17-----------------------
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——何时使用什么
原文:https://towardsdatascience.com/r²-or-r²-when-to-use-what-4968eee68ed3?source=collection_archive---------1-----------------------
平方皮尔逊相关系数和决定系数的图形解释,帮助您发现统计谎言
皮尔逊相关系数和决定系数的区别。图片作者。
想象一下,你是一名股票分析师,负责预测沃尔玛季度收益报告前的股价。当你正在努力工作时,你的数据科学家走进来说,他们发现了一个鲜为人知的数据流,提供沃尔玛每天的停车场占用率,这似乎与沃尔玛的历史收入有很好的相关性。你兴奋是可以理解的。你让他们在机器学习模型中使用停车场数据和其他标准指标来预测沃尔玛的股价。
到目前为止一切顺利。
几个小时后,数据科学家回来了,声称经过对模型的仔细验证,它的预测与真实的股票价格有很强的相关性。你接受这个模型而不做进一步的调查吗?
我希望不会。
C orrelations 有利于识别数据中的模式,但对于量化模型的性能几乎没有意义,尤其是对于复杂的模型(比如机器学习模型)。这是因为相关性只告诉我们两个事物是否跟随(例如,停车场占用率和沃尔玛的股票),而不告诉我们它们如何匹配(例如,预测和实际的股票价格)。为此,像决定系数(R)这样的模型性能指标会有所帮助。
在本文中,我们将了解:
- 什么是相关系数( r) 及其平方( r )?
- 什么是决定系数( R )?
- 什么时候使用上面的每一个?
1.相关系数:“这个预测器有多好?”
蓝线总和越短,相关系数越接近+1。图片作者。
相关系数有助于量化两个事物之间的相互关系或联系。一些众所周知的相关量是人的体重和身高、房屋价值和面积,以及我们在上面的例子中看到的商店收入和停车场占用率。
最广泛使用的相关系数之一是皮尔逊相关系数(通常表示为 r) 。从图形上看,这可以理解为“数据离最佳拟合线有多近?”
r 的范围为 1 至+1。灰线是最符合数据的线。图片作者。
- 如果这些点非常远, r 接近于 0
- 如果点非常靠近直线,并且直线向上倾斜, r 接近+1
- 如果点非常靠近直线,并且直线向下倾斜, r 接近 1
注意上图中的坐标轴上有缺失的数字吗?这是因为皮尔逊相关系数与数字的大小无关;它只对相对变化敏感。这种特性通常是可取的,因为变量很少具有相同的大小。例如,沃尔玛的股票价格是几十美元,而停在商店门口的汽车数以千计。
然而,由于皮尔逊相关系数对实际大小的不敏感性,当两个事物确实被期望具有相同的大小时,皮尔逊相关系数可能被滥用来给出错误的置信度。
更糟糕的是,一些人将皮尔逊相关系数的平方带到 0 和+1 之间,并将其称为 r 。但这不要与下面解释的决定系数(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,取平方,你得到皮尔逊相关系数的平方( r ),它与决定系数(R)完全不同,除非在线性回归的非常的特定情况下(当来自上述数字的两条灰色线合并,使得蓝色和橙色线相等)。
因此,皮尔逊相关系数或其平方很少用于评估模型的性能。下图用 3 个例子对此进行了解释。
沃尔玛股票价格的 3 个不同模型的预测。图片作者。
- 模型 1: R = 0.99 表明它几乎完美地预测了股票价格。
- 模型 2: R = 0.59 表明它对股票价格的预测很差。然而,如果你只看 r 的话,你可能过于乐观了。这种有偏差的预测在机器学习模型中极为常见。因此,更重要的是将你的预测可视化,而不仅仅是用统计数据来总结它们。
- 模型 3:R = 0.98 表示比随机猜测 50 美元左右的股价更差。但是,如果你只是看了一眼,你可能会失去所有的钱!附注:信不信由你,与实际趋势相反的股票预测很常见。这也催生了一个全新的领域,叫做反向投资。
概述
- 相关性对于发现数据中的模式和关系是有用的,但是对于评估预测是无用的。
- 要评估预测,请使用诸如决定系数之类的度量标准,决定系数反映了预测与观测的匹配程度,或者预测解释了观测数据中的多少变化。
- 皮尔逊相关系数的平方通常不等于决定系数(或 r ≠ R)
如果你想要一个关于 R 和 R 之间区别的数学解释,看看迪帕克·汉德尔瓦尔的这篇优秀文章。
r 和传单来创建交互式 choropleth 地图。
原文:https://towardsdatascience.com/r-and-leaflet-to-create-interactive-choropleth-maps-8515ef83e275?source=collection_archive---------33-----------------------
地理可视化选举数据
照片由марьянблан| @ 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 绘图
原文:https://towardsdatascience.com/r-and-python-plotting-in-google-sheets-255e974aed91?source=collection_archive---------38-----------------------
使用自定义 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 入门
原文:https://towardsdatascience.com/r-basics-getting-started-with-r-and-rstudio-b47664eb5baf?source=collection_archive---------91-----------------------
桑尼·萨希尔在 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 基础
在我们的数据科学专业证书课程的第一个,这门课程将向您介绍 R…
www.edx.org](https://www.edx.org/course/data-science-r-basics)
用 R 探索电影中的彩色故事:调色板提取
原文:https://towardsdatascience.com/r-color-palette-extraction-3850b3f56152?source=collection_archive---------28-----------------------
调色板提取示例(鸣谢:布莱恩·麦高恩上 Unsplash
如何使用颜色量化理论和无监督机器学习从电影帧中提取调色板
0.概述
在《T4》的第一部分中,我们探索了一些从著名电影中挑选出来的有趣的半音阶例子 ,试图猜测导演们选择背后的原因,并对通过 R 脚本可以做的事情略知一二。
[## 探索 R 电影中的彩色故事(上)
一次丰富多彩、数据驱动的电影色彩世界之旅
towardsdatascience.com](/exploring-chromatic-storytelling-with-r-part-1-8e9ddf8d4187)
在第二部分 ,中,我们更加强调介绍 ChromaR 工具包的技术细节,这是一个 R 包,可以呈现之前在第一部分中显示的所有彩色可视化效果。
[## 用 R 探索电影中的彩色故事:ChromaR 包
关于如何生成电影框架线和许多其他彩色数据的实用见解
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 中的新冠肺炎数据采集
原文:https://towardsdatascience.com/r-interface-to-covid-19-data-hub-244ae056af2c?source=collection_archive---------65-----------------------
跨政府来源收集数据,检索政策措施,与世界银行公开数据、谷歌和苹果移动报告接口。
编者注: 走向数据科学 是一份以研究数据科学和机器学习为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
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
r 闪亮认证(包括演示应用程序)
原文:https://towardsdatascience.com/r-shiny-authentication-incl-demo-app-a599b86c54f7?source=collection_archive---------2-----------------------
实践教程
为您的公司创建专业的 web 应用程序
用 R Shiny 构建企业级应用!—此处提供演示
序文
Shiny 非常强大,可以快速构建交互式 web 应用程序。这也是许多数据科学家的首选技术解决方案,因为它是 R-native。
由于并非所有的网络应用都是公开的,控制访问的能力应该是任何有抱负的数据科学家的知识的一部分。
本教程将向你介绍几个选项来通过认证层保护你的应用程序。
注意:为了从本教程中获得最大收益,感兴趣的读者应该已经熟悉了基本的 Shiny 原则(例如,反应性,如何使用模块),web 开发(例如,html 标签和 css),以及 RStudio 项目。
闪亮的应用伴侣
本教程附带一个 R Shiny 演示应用程序,你可以在这里访问。
完整代码也在我的 bitbucket 账号 上。
简单介绍一下 3 种提议的方法
本教程将介绍几种安全访问 R Shiny web 应用程序的方法。
- 首先,我将介绍身份验证的基础知识,构建我自己的登录表单,在用户提供正确凭证的情况下让应用程序出现(而登录表单消失)。
- 然后,我会把登录表单和对应的服务器逻辑打包成一个 模块 。这将增加应用程序的可读性和可维护性,并使您的登录表单易于跨多个应用程序重用。
- 第三步,我将利用shinyauthr包,这基本上是第二步的一个实现,增加了一些功能,包括密码散列(基于钠包)。
- 最后,我简单提一下两个其他方法。
注意:为了便于演示,我创建了一个表来直接存储来自 Shiny server 部分的用户名和密码。请记住,在应用程序部署在生产环境中的情况下,凭证应该加密并存储在数据库中(数据库连接不在本文讨论范围内)。
第一种方法—基础
在本节中,您将学习如何构建自己的登录表单,如下图所示:
访问配套的应用程序来测试它现场这里!
我将介绍登录表单的设计和相应的服务器逻辑。代码解释分为 3 个步骤:
- 加载所需的包并构建应用主干
- 构建您自己的完全可定制的登录表单
- 定义服务器端
步骤 1.1 —加载所需的包并构建应用主干
我用了以下 4 个包 : 闪亮、亮泽、亮泽和不亮泽
**# 1 - SET THE SCENE**# **load required packages**
library(shiny) # web app framework
library(shinyjs) # improve user experience with JavaScript
library(shinythemes) # themes for shiny
library(tidyverse) # data manipulation
然后我使用 navbarPage 设计了一个简单的应用主干:
**# 2 - UI PART****# app backbone**ui <- **navbarPage**(
title = "R Shiny advanced tips series",
collapsible = TRUE,
windowTitle = "R Shiny tips - TFI",
theme = shinytheme("readable"),
**tabPanel**(
title = "Demo",
useShinyjs() # Include shinyjs )
)**# 3 - SERVER PART**server <- function(input, output, session) {}**# 4 - RUN APP**shinyApp(ui = ui, server = server)
步骤 1.2 —构建您自己的完全可定制的登录表单
登录表单需要以下 3 个组件:
- 一个文本输入来捕获用户名
- 获取密码的密码输入(类似于文本输入,除了文本被隐藏)
- 一个动作按钮确认/弱化对应用程序的访问
这里有一个简单的代码块,您可以根据自己的喜好进行修改。在我的例子中,我主要使用基本的 bootstrap 类来使文本居中(文本居中),并给登录表单添加浅灰色背景(井)。
登录表单应该位于一个带有“类容器的专用 div 中。
还请注意:
- 应定义一个 id,以便在认证成功时,登录表单消失。该部分在步骤 1.3 中定义
- 使用 tagList() 函数在文本输入和密码输入标签旁边添加图标
**div**(
id = "**login-basic**",
style = "width: 500px; max-width: 100%; margin: 0 auto;",
**div**(
class = "**well**",
h4(class = "**text-center**", "Please login"),
p(class = "**text-center**",
tags$small("First approach login form")
),
**textInput**(
inputId = "ti_user_name_basic",
label = **tagList**(icon("user"),
"User Name"),
placeholder = "Enter user name"
),
**passwordInput**(
inputId = "ti_password_basic",
label = **tagList**(icon("unlock-alt"),
"Password"),
placeholder = "Enter password"
),
div(
class = "text-center",
**actionButton**(
inputId = "ab_login_button_basic",
label = "Log in",
class = "btn-primary"
)
)
)
)
步骤 1.3 —定义服务器端
服务器端是开发人员将智能注入应用程序、定义和控制预期行为的地方。
我首先构建了一个简单表来存储用户凭证。在这个例子中,我只授予一个用户(“user_basic_1”)访问权限,但是您当然可以定义任意多的 user x 密码组合。
# >> insert in server part**# create userbase**user_base_basic_tbl <- tibble(
user_name = "user_basic_1",
password = "pass_basic_1"
)
在第二步中,我使用了event reactive()函数根据有效凭证(存储在上述用户库中)检查用户的登录和密码。一旦用户单击登录按钮,就会相应地切换真/假布尔参数。
# >> insert in server part**# check credentials vs tibble**validate_password_basic <- **eventReactive**(input$ab_login_button_basic, {
validate <- **FALSE**
if (input$ti_user_name_basic == user_base_basic_tbl$user_name &&
input$ti_password_basic == user_base_basic_tbl$password {validate <- **TRUE**}})
基于这个布尔值:
- 登录表单会隐藏,使用shinyjs::hide()函数在一个observe event()内。这需要一个 id 来引用要隐藏的适当的 UI 部分,这就是我在步骤 1.2 中的注释。
- app 的安全部分会出现,采用经典的render ui()+ui output()组合
# >> insert in server part**# hide form** **observeEvent**(validate_password_basic(), {
**shinyjs::hide**(id = "login-basic")
})**# show app** output$display_content_basic <- **renderUI**({
req(validate_password_basic())
div(
class = "bg-success",
id = "success_basic",
h4("Access confirmed!"),
p("Welcome to your basically-secured application!")
)
})
uiOutput 应该插入到 ui 部件中
**# app** **uiOutput**(outputId = "display_content_basic")
如果到目前为止你已经能够理解并重现这个例子,那么恭喜你。您刚刚构建了第一个登录组件来保护您的 R Shiny 应用程序。
因为这个过程需要大量的代码,这使得你的应用程序很难长期维护,让我们把它打包成一个模块!
第二种方法——开发登录模块
既然您已经理解了身份验证的基本原理,并且已经构建了您的第一个登录表单,让我们使更健壮和更容易跨多个应用程序重用。这可以通过定义一个专用的 模块 来实现。
一个闪亮的模块是一个闪亮应用的一部分。不能直接运行,闪亮的 app 可以。相反,它是作为一个更大的应用程序的一部分(或者作为一个更大的闪亮模块的一部分——它们是可组合的)。—Wiston Chang—r studio 软件工程师
注意:本教程不会详细介绍如何创建一个模块,我假设读者对它的的关键概念有点熟悉。
简而言之,一个模块由两个函数组成,这两个函数代表 1)一段 UI,以及 2)使用该 UI 的服务器逻辑片段——类似于将闪亮的应用程序分为 UI 和服务器逻辑的方式。
查看下面的简短插图,了解第二种方法将会构建什么;如您所见,UI 部分看起来与我在第一种方法中构建的完全相同。然而,它在引擎盖下有所不同:
点击访问配套应用进行现场测试!
代码解释分为 4 个步骤:
- 构建模块
- 获取模块的源代码
- 在 UI 部分添加登录表单+应用程序的安全部分
- 定义服务器端
步骤 2.1 —构建模块
这个步骤主要是将我在前面的方法中实现的定制 UI 和相关的服务器逻辑整合到一个单独的 module_login 中。R 文件。
下面代码块中需要注意的关键方面:
UI 部分:
- NS() 的用法:创建模块时所有 UI 函数体都要以此行开头。它获取字符串 id 并创建一个名称空间函数。所有 id 名称必须封装在 ns() 中。感兴趣的读者可以在这里了解更多
- 该函数使用另一个变量 title ,以使易于定制登录页面标题,如果您需要在其他未来 R Shiny 应用程序的上下文中使用该模块的话
**# UI component**login_ui <- function(id, **title**) {
ns <- **NS**(id) # namespaced id
# define ui part
**div**(
id = **ns**("login"),
style = "width: 500px; max-width: 100%; margin: 0 auto;",
**div**(
class = "well",
h4(class = "text-center", **title**),
p(class = "text-center",
tags$small("Second approach login form")),
**textInput**(
inputId = **ns**("ti_user_name_module"),
label = tagList(icon("user"),
"User Name"),
placeholder = "Enter user name"
),
**passwordInput**(
inputId = **ns**("ti_password_module"),
label = tagList(
icon("unlock-alt"),
"Password"
),
placeholder = "Enter password"
),
**div**(
class = "text-center",
**actionButton**(
inputId = **ns**("ab_login_button_module"),
label = "Log in",
class = "btn-primary"
)
)
)
)
}
服务器部分:
- 使用 {{ }} 在函数中使用用户提供的表达式。更多关于这个的信息,请点击这里阅读
- 对shinyjs::hide()的调用嵌入在模块的服务器部分,因此不再需要像我在第一种方法中那样使用 observeEvent
**# SERVER component**validate_pwd <- function(input, output, session,
data, user_col, pwd_col) {
**# get user and pwd from data/ user_col/ pwd_col information**
user <- data %>% pull(**{{** user_col **}}**)
pwd <- data %>% pull(**{{** pwd_col **}}**)
**# check correctness**
**eventReactive**(input$ab_login_button_module, {
validate <- FALSE
if (input$ti_user_name_module == user &&
input$ti_password_module == pwd) {
validate <- TRUE
}
**# hide login form when user is confirmed**
if (validate) {
**shinyjs::hide**(id = "login")
}
validate
})
}
步骤 2.2 —源模块
在你的 R Shiny 应用程序中使用一个特定的模块之前,要注意对它进行适当的编译(参见我的 bitbucket account 以了解项目结构):
**# source module**
source("modules/module_login.R")
步骤 2.3 —在 UI 部分添加登录表单+应用程序的安全部分
登录表单和应用程序的安全部分现在都可以用两行代码在 UI 部分指定,这确保了应用程序的可读性和可维护性。
**# login form** as defined in the module
**login_ui**(id = "module_login", title = "Please login"),
**# app**
**uiOutput**(outputId = "display_content_module")
步骤 2.4 —定义服务器端
这与 1.3 节非常相似。
我首先构建了一个简单表来存储用户凭证。在这个例子中,我只授予一个用户访问权限,但是您当然可以定义任意多的用户 x 密码组合。
# >> insert in server part**# create userbase**user_base_module_tbl <- tibble(
user_name = "user_module_1",
password = "pass_module_1"
)
然后,我使用 callModule() 函数来访问我的模块的服务器端,并传递在哪里搜索登录和密码的信息(通过 data、user_col 和 pwd_col 参数来引用上面的 userbase):
**# check credentials vs tibble**
validate_password_module <- **callModule**(
module = validate_pwd,
id = "module_login",
data = user_base_module_tbl,
user_col = user_name,
pwd_col = password
)
最后,和第一种方法一样,我使用经典的render ui()+ui output()组合来显示应用程序的安全部分,只要上面定义的布尔validate _ password _ module()适当地切换:
**# app**
output$display_content_module <- **renderUI**({
req(validate_password_module())
div(
class = "bg-success",
id = "success_module",
h4("Access confirmed!"),
p("Welcome to your module-secured application!")
)
})
如果到目前为止你已经能够理解并重现这个例子,那么恭喜你。您已经能够将完全可定制的登录表单打包到一个模块中,您可以在未来的所有 web 应用程序中重用该模块。
在下一节中,我们将利用现有的认证模块,该模块在 shinyauthr 包中可用。与构建自己的模块相比,主要优势在于:
- 不需要你掌握建筑模块的艺术, shinyauthr 让你随时可以使用
- 能够通过钠包加密你的密码。钠使用哈希算法,这是专门设计来保护存储的密码免受暴力攻击
第三种方法——利用 SHINYAUTHR 包
Shinyauthr 是一个提供模块函数的 R 包,可以用来给你闪亮的应用添加一个认证层。如果到目前为止您已经成功地构建了自己的模块,那么第三种方法应该很容易遵循,并且我推荐您使用这个包来加速您未来的工作。
查看下面的简短插图,了解第三种方法将会构建什么;虽然它看起来非常类似于方法 1 和 2,但登录表单的可定制性稍差。
访问配套应用程序进行现场测试点击这里!
下面的代码解释将指定新的必需包,说明如何更新 ui 部分并详述服务器端。提醒一下,完整的代码可以在这里获得。
步骤 3.1 —加载所需的包
除了前面提到的包,您还需要加载 shinyauthr 和钠包。
library(shinyauthr) # shiny authentication modules
library(sodium) # crypto library
步骤 3.2 —在 UI 部分添加登录表单+应用程序的安全部分
登录表单和应用程序的安全部分现在都可以用两行代码在 UI 部分指定,这确保了应用程序的可读性和可维护性。
- shinyauthr 包中的 loginUI() 函数与您在第二种方法中构建的函数非常相似。标题(可以定制其他一些参数)
- 应用程序的安全部分通过 uiOutput() 函数显示
**# login form****shinyauthr::loginUI**(
id = "authr_login",
**title** = h4(class = "text-center", "Please login")
),
**# app** **uiOutput**(outputId = "display_content_authr"),
步骤 3.3 —定义服务器端
我首先构建了一个简单表来存储用户凭证。在这个例子中,我只授予一个用户访问权限,但是您当然可以定义任意多的用户 x 密码组合。
注意使用password _ store()函数从钠包中加密密码。
# >> insert in server part**# create userbase**uuser_base_authr_tbl <- tibble(
user_name = "user_authr_1",
password = **sodium::password_store**("pass_authr_1")
)
然后我调用了 shinyauthr 包中的两个模块(一个登录表单+一个注销表单)
# >> insert in server partlogout_init <- **callModule**(
module = **shinyauthr::logout**,
id = "authr_logout",
active = reactive(user_auth)
)
credentials <- **callModule**(
module = **shinyauthr::login**,
id = "authr_login",
data = user_base_authr_tbl,
user_col = user_name,
pwd_col = password,
sodium_hashed = TRUE,
log_out = reactive(logout_init())
)
当调用登录模块时,它返回包含 2 个元素的反应列表:
- user_auth (初始值为假)
- 信息(初始值为空)
我在服务器端创建了一个 reactive 对象来捕捉这些值的变化(特别是,如果用户提供了匹配的用户名和密码,user_auth 将变为 TRUE。)
# >> insert in server partuser_auth <- reactive({
credentials()$**user_auth**
})
user_data <- reactive({
credentials()$**info**
})
最后,我需要在 renderUI()函数中定义应用程序的安全部分,类似于前面的方法。
# >> insert in server partoutput$display_content_authr <- **renderUI**({
req(user_auth())
div(
class = "bg-success",
id = "success_module",
h4("Access confirmed!"),
p("Welcome to your shinyauthr-secured application!
Notice that password is encrypted.")
)
})
祝贺您如果您已经做到了这一步,那么您现在就拥有了一种快速、强大且简单的方法来保护您的应用程序!
其他方法
我通常实现上面 3 个详细方法中的一个。
但是,它们并不是唯一的选择,您可能有兴趣探索其他替代方案,例如:
- shinymanager (非常类似于 shinyauthr)
- 完善的一个非免费的解决方案,为您提供除身份验证之外的几个附加功能,例如:自定义登录页面、用户管理、单点登录或用户监控
结论
我希望你觉得这个教程有用,请随时留下评论来分享你的首选(也可能是替代)方法。
想了解更多?本文是我高级 R 闪亮小贴士系列的第二篇。第一篇文章是关于构建动态 UI 组件的。
资源
- shinymanager :单一 Shiny 应用的简单安全认证机制。
- shinyauthr : R 包提供模块函数,可用于为您的闪亮应用添加认证层
- 完美的:为您闪亮的应用程序添加身份验证
- 掌握 Shiny :这本书补充了 Shiny 的在线文档,旨在帮助应用程序作者更深入地了解 Shiny
- 商业科学 202A —使用 R 构建可扩展的应用程序:一门很棒的在线课程
R -统计编程语言
原文:https://towardsdatascience.com/r-statistical-programming-language-6adc8c0a6e3d?source=collection_archive---------2-----------------------
让我们不要让冠状病毒阻止我们学习新技能
如果可能的话,我们应该利用这段时间学习一项新技能。在过去的几周里,我一直在学习编程语言 R。
本文旨在概述 R 编程语言以及每个数据科学家都必须熟悉的所有主要概念
动机
数据科学和定量开发领域要求我们不断适应和学习新技能,因为它具有高度动态和高要求的性质。在数据科学家的职业生涯中,学习多种编程语言变得非常重要。随后,我选择了学习 r。
本文旨在概述所有关键的主要领域,并从基础开始解释一切。它假设读者不熟悉编程语言 r,或者对编程语言 r 只有初级的理解。
我强烈推荐 R,原因有很多,我将在本文中重点介绍
克里斯·迪诺托在 Unsplash 上拍摄的照片
r 越来越受欢迎,它是最流行的编程语言之一。r 是统计学家为统计学家写的。它可以很好地与其他编程语言如 C++,Java,SQL 集成。此外,R 主要被视为一种统计编程语言。因此,许多金融机构和大型量化组织在研发过程中使用 R 编程语言。
Python 是一种通用语言,R 可以看作是一种分析性编程语言。
1.文章目标
本文将解释关于 R 的以下关键领域:
- R 是什么?
- 如何安装 R?
- 在哪里编码 R?
- 什么是 R 包和 R 脚本?
- 有哪些不同的 R 数据类型?
- 如何在 R 中声明变量及其作用域?
- 怎么写评论?
- 什么是矢量?
- 什么是矩阵?
- 什么是列表?
- 什么是数据框?
- R 中不同的逻辑运算
- R 中的函数
- R 中的循环
- 读写 R 中的外部数据
- 在 R 中执行统计计算
- 在 R 中绘图
- R 语言中的面向对象编程
- 著名 R 图书馆
- 如何安装外部 R 库
- 在 R 中绘图
让我们开始…
我将从基础开始解释这种编程语言,以使这种语言更容易理解。说了这么多,编程进阶的关键是始终尽可能多的练习。
这篇文章应该为读者打下坚实的基础
2.R 是什么?
- r 是一种在 GNU 许可下的自由编程语言。简而言之,R 是一个统计环境。
- r 主要用于统计计算。它提供了一系列在机器学习领域广泛使用的算法,如时间序列分析、分类、聚类、线性建模等。
- r 也是一个环境,它包括一套软件包,可用于执行数值计算、图表绘制和数据操作。
- r 在统计研究项目中大量使用。
- r 非常类似于 S 编程语言。
- r 在 UNIX、Windows、MacOS、FreeBSD 和 Linux 平台上编译运行。
- r 有大量的数据结构、操作符和特性。它提供了从数组到矩阵,从循环到递归,以及与其他编程语言如 C、C++和 Fortran 的集成。
- 可以用 c 编程语言直接更新 R 对象。
- 可以实现新的 R 包来扩展。
- r 解释程序
- r 受到 S+的启发,因此如果你熟悉 S,那么学习 r 将是一项简单的任务。
R 的好处:
除了上面列出的好处,R 还包括:
- 简单易学
- 大量的统计、分析和图形软件包是开源和免费的
- 大量的学术论文及其在 R 中的实现都是可用的
- 世界顶级大学教授他们的学生 R 编程语言,因此,它现在已经成为一个公认的标准,因此,R 将继续增长。
- 与其他语言的集成能力
- 此外,还有大量的社区支持
R 的局限性:
也有一些限制:
- r 没有 C++快,而且安全性和内存管理也是个问题。
- r 有大量的名称空间,有时会显得太多。然而,情况正在好转。
- r 是一种统计语言,因此不像 Python 那样直观。创建 OOP 不像用 Python 那么简单。
让我们开始学习 R
现在,我将在快速跟进部分介绍 R 语言。
乔纳斯·雅各布森在 Unsplash 上拍摄的照片
3.如何安装 R?
您可以在以下位置安装 R:
- 乌布托
- 苹果个人计算机
- Windows 操作系统
- 一种男式软呢帽
- 一种自由操作系统
- SLES
- OpenSUSE
第一步是下载 R:
- 打开互联网浏览器
- 去 www.r-project.org 的。
- 写这篇文章时最新的 R 版本是 3.6.3(手持风向袋)。它于 2020 年 2 月 29 日发布。
这些是链接:
- 下载 R for Linux
- 下载适用于(Mac) OS X 的 R
- 下载 R for Windows
4.在哪里编码 R?
有多种图形界面可用。我强烈推荐 R-Studio
R-Studio 的截图
下载 RStudio 桌面:
- 从 https://rstudio.com/products/rstudio/download/下载 r studio
- RStudio 桌面开源许可是免费的
- 你可以在这里了解更多:【https://rstudio.com/products/rstudio/#rstudio-desktop】T4
- RStudio 需要 R 3.0.1+ 。
如果您使用的是 Windows,它通常会将 R Studio 安装在以下位置:
C:\Program Files\RStudio
5.什么是 R 包和 R 脚本?
R 包和 R 脚本是 R 的两个关键组件。
r 包
因为 R 是一种开源编程语言,所以理解什么是包是很重要的。包本质上是对代码和其他功能的分组和组织。包是一个可以包含大量文件的库。
数据科学家可以通过创建自己的包或增强他人的包来贡献并与他人共享他们的代码。包允许数据科学家重用代码并将其分发给其他人。
创建包是为了包含函数和数据集
数据科学家可以创建一个包来组织代码、文档、测试、数据集等。然后该包可以与其他人共享。
网上有上万个 R 包。这些包位于中央存储库中。有许多可用的存储库,如 CRAN、Bioconductor、Github 等。
一个值得一提的存储库是 CRAN。它是一个服务器网络,为 r 存储了大量版本的代码和文档。
一个包包含一个描述文件,其中包含日期、依赖项、作者以及包的版本等信息。描述文件帮助消费者获得关于包的有意义的信息。
要加载包,请键入:
*library(name of the package)*
要使用软件包的函数,请键入软件包的名称::函数的名称。
例如,如果我们想使用“carat”包的函数“AdBCDOne ”,那么我们可以:
library(carat)
carat::AdBCDOne()
r 脚本:
R script 是数据科学家编写统计代码的地方。它是一个带有扩展名的文本文件。我们可以称这个脚本为教程。稀有
我们可以在一个包中创建多个 R 脚本。
例如,如果您创建了两个 R 脚本:
- 博客。稀有
- 出版。稀有
如果你想调用出版的功能。r 在博客里。然后,您可以使用 source("target R script ")命令来导入发布。r 进入博客。R :
source("publication.R")
创建 R 脚本的 R 包
过程相对简单。简单地
- 创建描述文件
- 创建 R.scripts 并添加包所需的任何数据集、文档和测试
- 用 R 脚本编写你的功能
- 我们可以使用 devtools 和 roxygen2 通过使用以下命令来创建 R 包:
create_package("name of the package")
6.有哪些不同的 R 数据类型?
为了能够有效地使用 R 编程语言,理解 R 中不同的数据类型和结构是至关重要的。本节将阐述这些概念。
数据类型:
这些是 R 中的基本数据类型:
- 字符:如“abc”或“a”
- 整数:如 5L
- 数字:如 10.5
- 逻辑:真或假
- 复杂:如 5+4i
我们可以使用 typeof(变量)来查找变量的类型。
要查找元数据,如类型的属性,请使用 attributes(variable)命令。
数据结构:
r 中有许多数据结构,最重要的数据结构有:
- vector :最重要的数据结构,本质上是元素的集合。
- 矩阵:具有行和列的表状结构
- 数据框:用于执行统计操作的表格数据结构
- 列出了:可以保存数据类型组合的集合。
- 因子:表示分类数据
当我们开始构建基础时,我将在本文中解释所有这些数据类型和数据结构。
7.如何声明变量?
我们可以创建一个变量并给它赋值。变量可以是上面列出的任何数据类型和数据结构。也有其他可用的数据结构。此外,开发人员可以创建他们自己的自定义类。
变量用于存储可以在代码中更改的值。
作为理解的问题,记住 R 中的环境是什么是至关重要的。本质上,环境是存储变量的地方。它是对的集合,其中对的第一项是符号(变量),第二项是它的值。
环境是分层的(树形结构),因此一个环境可以有一个父环境和多个子环境。根环境是父环境为空的环境。
我们必须声明一个变量,并用→
x <- "my variable"
print(x)
这会将“我的变量”的值设置为变量 x,print()函数会输出 x 的值,也就是“我的变量”。
每当我们声明一个变量并调用它时,就在当前环境中搜索它,并在父环境中递归搜索,直到找到该符号。
要创建整数集合,我们可以这样做:
coll <- 1:5
print(coll)
1 是集合的第一个值,5 是集合的最后一个值。
这将打印 1 2 3 4 5
注意,R-Studio IDE 会跟踪变量:
R 工作室截图
*ls()*
函数可以用来显示当前环境中的变量和函数。**
8.怎么写评论?
代码中添加了注释,以帮助读者、其他数据科学家和您自己理解代码。
注意:始终确保注释不会污染您的脚本。
我们可以添加一行注释:
*#This is a single line comment*
我们可以使用双引号添加多行注释:
*"This is a
multi line comment
"*
注意:在 R-Studio 中,选择要注释的代码,然后按 Ctrl+Shift+C
它会自动为你评论代码。
9.什么是矢量?
向量是 r 中最重要的数据结构之一。本质上,向量是元素的集合,其中每个元素都需要具有相同的数据类型,例如逻辑(真/假)、数字、字符。
我们也可以创建一个空向量:
*x <- vector()*
默认情况下,向量的类型是逻辑的,例如 True/False。下面一行将逻辑打印为矢量类型:
*typeof(x)*
要使用元素创建向量,可以使用 concatenate 函数(c):
*x <- c("Farhad", "Malik", "FinTechExplained")
print(x)*
这将打印:
[1]《法尔哈德》
【2】《马利克》
【3】《fintech explained》
如果我们想求出一个向量的长度,我们可以使用 length()函数:
*length(x)*
这会打印出 3,因为向量中有三个元素。
要将元素添加到向量中,我们可以将元素与向量结合起来。
例如,在带有一个元素“hello”的 vector 的开头添加“world”:
*x <- c("hello")
x <- c("world", x)
print(x)*
这将打印“世界”“你好”
如果我们混合元素的类型,那么 R 也将适应向量的类型。向量的类型(模式)将变成它认为最适合向量的类型:
*another_vec <- c("test", TRUE)
print(typeof(another_vec))*
虽然第二个元素是一个逻辑值,但类型将被打印为“字符”。
运算也可以在向量上执行。
例如,将一个标量乘以一个向量:
*x <- c(1,2,3)
y <- x*2
print(y)*
这将打印 2,4,6
我们也可以将两个向量相加:
*x <- c(1,2,3)
y <- c(4,5,6)
z <- x+y
print(z)*
这将打印 5 7 9
如果向量是字符,我们想把它们加在一起:
*x <- c("F","A","C")
y <- c("G","E","D")
z <- x+y
print(z)*
它将输出:
x+y 错误:二元运算符的非数字参数
10.什么是矩阵?
矩阵也是 r 中最常见的数据结构之一。
它可以被认为是一个向量的延伸。矩阵可以有多行和多列。矩阵的所有元素必须具有相同的数据类型。
若要创建矩阵,请使用 matrix()构造函数并传入 nrow 和 ncol 来指示列和行:
*x <- matrix(nrow=4, ncol=4)*
这将创建一个名为 x 的矩阵变量,有 4 行 4 列。
通过在构造函数中传递矩阵,可以将向量转换为矩阵。生成的矩阵将按列填充:
*vector <- c(1, 2, 3)
x <- matrix(vector)
print(x)*
这将创建一个 1 列 3 行的矩阵(每个元素一行):
[,1]
【1,】1
【2,】2
【3,】3
如果我们想按行或列填充矩阵,那么我们可以显式地传入行数和列数以及 byrow 参数:
*vector <- c(1, 2, 3, 4)
x <- matrix(vector, nrow=2, ncol=2, byrow=TRUE)
print(x)*
上面的代码创建了一个 2 行 2 列的矩阵。矩阵按行填充。
[,1] [,2]
[1,] 1 2
[2,] 3 4
11.什么是列表和因子?
如果我们想创建一个可以包含不同类型元素的集合,那么我们可以创建一个列表。
列表:
列表是 r 中最重要的数据结构之一。要创建列表,请使用 list()构造函数:
*my_list <- list("hello", 1234, FALSE)*
上面的代码片段演示了如何用不同数据类型的三个元素创建一个列表。
我们可以通过使用索引来访问任何元素,例如:
*item_one = my_list[1]*
这将打印“你好”
我们也可以给每个元素起一个名字,例如
*my_named_list <- list(“A”=1, “B”=2)print(names(my_named_list))It prints “A” “B”print(my_named_list[‘A’])It prints 1*
因素:
因素是分类数据,例如是、否或男性、女性或红色、蓝色、绿色等。
可以创建因子数据类型来表示因子数据集:
*my_factor = factor(c(TRUE, FALSE, TRUE))
print(my_factor)*
因子也可以排序:
*my_factor = factor(c(TRUE, FALSE, TRUE), levels = c(TRUE, FALSE))
print(my_factor)*
我们还可以用表格的形式打印这些因子:
*my_factor = factor(c(TRUE, FALSE, TRUE), levels = c(TRUE, FALSE))
print(table(my_factor))*
这将打印:
*TRUE FALSE
2 1*
我们已经讨论了文章的一半。让我们继续学习更多的统计学知识
12.什么是数据框?
大多数(如果不是全部的话)数据科学项目需要表格格式的输入数据。数据框数据结构可以用来表示 r 中的表格数据。每一列可以包含一个元素列表,每一列可以是彼此不同的类型。
要创建 2 列 5 行的数据框,只需执行以下操作:
*my_data_frame <- data.frame(column_1 = 1:5, column_2 = c("A", "B", "C", "D", E"))
print(my_data_frame)column_1 column_2
1 1 A
2 2 B
3 3 C
4 4 D
5 5 E*
13.R 中的不同逻辑运算符
本节概述了常用运算符:
或者:一|二
这将检查一个或两个是否为真。
还有:一和二
这将检查一和二是否为真。
不是:!投入
如果输入为假,将返回真
我们也可以使用、>、isTRUE(输入)等。
14.R 和变量作用域中的函数
有时我们希望代码执行一组任务。这些任务可以按功能分组。函数本质上是 r 中的对象。
在 R 中,参数可以传递给函数,函数也可以返回一个对象。
r 附带了许多内置函数,如 length()、mean()等。
每次我们声明一个函数(或变量)并调用它时,在当前环境中搜索它,并在父环境中递归搜索,直到找到该符号。
一个函数有一个名字。这个存储在 R 环境中。函数体包含函数的语句。
一个函数可以返回值,并且可以选择接受一些参数。
要创建一个函数,我们需要以下语法:
*name_of_function <- function(argument1...argumentN) {
Body of the function}*
例如,我们可以创建一个接受两个整数并返回一个和的函数:
*my_function <- function(x, y) {
z <- x + y
return(z)
}*
要调用该函数,我们可以传入参数:
*z <- my_function(1,2)
print(z)*
这将打印 3。
我们还可以为参数设置默认值,以便在参数值未提供的情况下采用其值:
*my_function <- function(x, y=2) {
z <- x + y
return(z)
}
output <- my_function(1)
print(output)*
y 的缺省值是 2,因此,我们可以调用这个函数而不用传入 y 的值。
需要注意的关键是花括号{...}
让我们看一个复杂的例子,我们将使用逻辑运算符
假设我们想要创建一个接受以下参数的函数:模式、x 和 y。
- 如果模式为真,那么我们要把 x 和 y 相加。
- 如果模式为假,那么我们要减去 x 和 y。
*my_function <- function(mode, x, y) {
if (mode == TRUE)
{
z <- x + y
return(z)
}
else
{
z <- x - y
return(z)
}
}*
要调用函数将 x 和 y 的值相加,我们可以这样做:
*output <- my_function(TRUE, 1, 5)
print(output)*
这将打印 6
让我们回顾一下下面的代码。具体来说,请参见 print(z)的位置:
*my_function <- function(mode, x, y) {
if (mode == TRUE)
{
z <- x + y
return(z)
}
else
{
z <- x - y
return(z)
}
#what happens if we try to print z
print(z)
}*
需要注意的关键是,z 是在括号关闭后打印的。
变量 z 在那里可用吗?这就把我们带到了函数作用域的话题上!
一个函数可以在另一个函数中声明:
*some_func <- function() {
some_func_variable <- 456 another_func <- function() {
another_func_variable <- 123
}
}*
在上面的例子中,some_func 和 another_func 是两个函数。在 some_func 内部声明了另一个 _func。因此,另一个 _func()是 some_func()的私有函数。因此,它不能与外界接触。
如果我在 some_func 之外执行另一个 _func(),如下所示:
*another_func()*
我们将会遇到错误:
another _ func()中的错误:找不到函数“another _ func”
另一方面,我们可以在 some_func()中执行另一个 _func(),它将按预期工作。
现在考虑这段代码来理解 r 中作用域的工作原理。
- some_func_variable 可由 some_func 和 another_func 函数访问。
- 另一个函数变量只能由另一个函数访问
*some_func <- function() {
some_func_variable <- "DEF"
another_func <- function() {
another_func_variable <- "ABC"
print(some_func_variable)
print("Inside another func" + another_func_variable)
}
print(some_func_variable)
print("outside another func" + another_func_variable)
another_func()
}
some_func()*
运行上面的代码会在 R-Studio 中抛出一个异常:
>some _ func()
[1]“DEF”
打印错误("在另一个 func 之外"+另一个 _func_variable) :
找不到对象'另一个 _ func _ variable '
如错误所述,未找到另一个 _ func _ 变量。我们可以看到 DEF 被打印出来,这是赋给变量 some_func_variable 的值。**
如果我们想访问一个全局变量并给它赋值,使用< < -运算符。在父环境框架中搜索变量。如果找不到变量,则创建一个全局变量。
要添加未知数量的参数,请使用…
*my_func <- function(a, b, ...)
{
print(c)
}my_func(a=1,b=2,c=3)*
15.R 中的循环
r 也支持控制结构。数据科学家可以给 R 代码添加逻辑。本节重点介绍最重要的控制结构:
对于循环
有时候,我们想要迭代集合中的元素。语法是:
*for (i in some_collection) {
print(i)
}*
在上面的例子中,迭代器可以是列表、向量等。上面的代码片段将打印集合的元素。
我们还可以通过使用 seq_along()函数循环遍历一个集合。它接受一个集合并生成一个整数序列。
While 循环
有时,我们必须循环,直到满足一个条件。一旦条件为假,我们就可以退出循环。
我们可以使用 while 循环来实现所需的功能。
在下面的代码中,我们将 x 的值设置为 3,z 的值设置为 0。随后,我们将 z 的值每次递增 1,直到 z 的值等于或大于 x。
*x <- 3z <- 0
while(z < x) {
z <- z + 1}*
If Else(可选)
If Then Else 在编程中大量使用。
简而言之,条件是在 if 控制模块中评估的。如果为真,则执行其代码,否则执行下一个块。下一个块可以是 Else If 或 Else。
如果(条件为真){
#执行语句
}
我们还可以有一个可选的 else:
如果(条件为真){
#执行语句
}
else if(另一个条件为真){
#执行语句
}
否则{
#执行语句
}
*x <- 3
y <- 0if (x == 3) {
y <- 1}
else if (x<3) {
y <- 2}
else {
y <- 3}*
重复
如果我们想要重复一组语句未知的次数(可能直到满足一个条件或者用户输入一个值等等)。)然后我们可以重复/中断语句。休息可以结束迭代。
*repeat {
print("hello")
x <- random()
if (x > 0.5)
{
break; #exit the loop
}
}*
如果我们想跳过一次迭代,我们可以使用下面的语句:
*repeat {
print("hello")
x <- random()
if (x > 0.5)
{
next #iterate again
}
}*
16.读写 R 中的外部数据
r 提供了一系列的包,允许我们读写外部数据,比如 excel 文件或 SQL 表。本节说明了我们如何实现它。
16.1 读取 Excel 文件
*library(openxlsx)
path <-"C:/Users/farhadm/Documents/Blogs/R.xlsx"
res <- read.xlsx(path, 'Sheet1')
head(res)*
这将显示最上面的行:
显示 excel 文件内容的代码片段
16.2 写入 Excel 文件
*columnA <- runif(100,0.1,100)
columnB <- runif(100,5,1000)
df <- data.frame(columnA, columnB)
write.xlsx(df, file = path, sheetName="NewSheet", append=TRUE)*
它用名为 NewSheet 的工作表创建了一个新的 excel 文件:
显示 Excel 内容的代码片段
16.3 读取 SQL 表
我们可以从 SQL 表中读取数据
*library(RODBC)
db <- odbcDriverConnect('driver={SQL
Server};server=SERVERNAME;database=DATABASENAME;trusted_connection=true')
res <- sqlQuery(db, 'SQL QUERY')*
16.4 写入 SQL 表
我们可以写入 SQL 表
*sqlSave(odbcConnection, some data frame, tablename="TABLE", append=TRUE, rownames=FALSE)*
17.在 R 中执行统计计算
众所周知,r 是最流行的统计编程语言之一。理解 r 中的内置统计函数至关重要。本节将概述数据科学家执行的最常见的统计计算。
17.1 填充缺失值:
数据科学项目中最常见的任务之一是填充缺失值。我们可以使用 is.na()来查找空的元素(na 或 NAN):
*vec <- c("test", NA, "another test")
is.na(vec)*
这将打印 FALSE TRUE FALSE,表明 NA 中的第二个元素。
为了更好地理解它们,is.na()将返回所有为 na 的元素/对象。is.nan()将返回所有的 nan 对象。值得注意的是,南是安娜,但安娜不是南。
注意:许多统计函数,如均值、中值等,都有一个参数:na.rm,它表示我们是否要删除 na(缺失值)。
接下来的几次计算将基于以下两个向量:
*A <- c(1,2,5,6.4,6.7,7,7,7,8,9,3,4,1.5,0,10,5.1,2.4,3.4, 4.5, 6.7)
B <- c(4,4.1,0,1.4,2,1,6.7,7,5,5,8,9,3,2,2.5,0,10,5.1,4.3,5.7)print(length(A)) #20
print(length(B)) #20*
向量 A 和 B 都包含 20 个元素的数值。
17.2 平均值
平均值的计算方法是对集合中的值求和,然后除以值的总数:
*my_mean <- mean(A)
print(my_mean)*
17.3 中位数
Median 是排序集合中的中间值。如果有偶数个值,则是两个中间值的平均值:
*my_median <- median(A)
print(my_median)*
17.4 模式
众数是最常见的值。r 缺少计算模式的标准内置函数。但是,我们可以创建一个函数来计算它,如下所示。
*distinct_A <- unique(A)
matches <- match(A, distinct_A)
table_A <- tabulate(matches)
max_A <- which.max(table_A)
mode<-distinct_A[max_A]
print(mode)*
该函数执行以下步骤:
- 计算集合的不同值
- 然后,它找到每个项目的频率,并创建一个表格
- 最后,它找到出现次数最多的词的索引,并将其作为模式返回。
17.5 标准偏差
标准偏差是数值与平均值的偏差。
*sd <- sd(A)
print(sd)*
17.6 差异
方差是标准偏差的平方:
*var <- var(A)
print(var)*
17.7 相关性
相关性有助于我们了解集合之间是否存在关系,以及它们是否随着关系的强度一起移动:
*cor <- cor(A, B)
print(cor)*
我们可以传入特定的相关方法,如 Kendall 或 Spearman。皮尔逊是默认的相关方法。
在方法参数中传递相关方法。
17.8 协方差
协方差是用来告诉我们变量之间的关系的。
*covariance <- cov(A, B)
print(covariance)*
17.9 标准化和规范化数据集
我们经常需要标准化数据,例如使用最小-最大标准化或使用标准化机制计算 z 值。
标准化数据意味着数据集的均值= 0,标准差= 1。它需要从每个观察值中减去平均值,然后除以标准偏差。
我们可以使用比例函数。如果我们想从每个观察值中减去平均值,那么将其中心参数设置为真。
如果我们想要标准化数据,那么我们需要设置它的 scale 参数为 True。
*normal_A <- scale(A, center=TRUE, scale = FALSE)
print(normal_A)standard_A <- scale(A, center=TRUE, scale = TRUE)
print(standard_A)*
17.10 回归模型
回归模型由于其简单性和可解释性,在机器学习解决方案中越来越受欢迎。本质上,回归模型帮助我们理解不同变量之间的关系。
通常,计算一个或多个变量的系数。这些变量是回归变量。它们用于估计和预测另一个变量,即因变量。因变量也称为响应变量。
回归数据是通过抽样收集的,用于预测结果:
- b n 是线性模型可以估计的系数。
- x n 是自变量。我们将收集这些变量的数据并输入到模型中。
作为一个例子,让我们假设我们收集了温度数据集,并希望预测降雨量。我们可以使用如下所示的线性模型:
*Temperature <- c(1,2,5,6.4,6.7,7,7,7,8,9,3,4,1.5,0,10,5.1,2.4,3.4, 4.5, 6.7)
Rainfall <- c(4,4.1,0,1.4,2,1,6.7,7,5,5,8,9,3,2,2.5,0,10,5.1,4.3,5.7)model <- lm(Rainfall~Temperature)*
注意,如果有多个变量用于预测一个变量,例如使用湿度和温度来预测降雨量,我们可以使用 lm()函数,并将公式设置为:
*Temperature <- c(1,2,5,6.4,6.7,7,7,7,8,9,3,4,1.5,0,10,5.1,2.4,3.4, 4.5, 6.7)
Rainfall <- c(4,4.1,0,1.4,2,1,6.7,7,5,5,8,9,3,2,2.5,0,10,5.1,4.3,5.7)
Humidity <- c(4,4.1,0,1.4,2,1,6.7,7,5,5,8,9,3,2,2.5,0,10,5.1,4.3,5.7)model <- lm(Rainfall~Temperature+Humidity)*
然后我们可以打印出模型的概要。
r 将告诉我们关于残差、系数、它们的标准偏差误差、t 值、F 统计量等等:
*print(summary(model))*
它将打印以下统计数据:
*Call:
lm(formula = Rainfall ~ Temperature)Residuals:
Min 1Q Median 3Q Max
-4.2883 -2.2512 -0.2897 1.8661 5.4124Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.8639 1.3744 3.539 0.00235 **
Temperature -0.1151 0.2423 -0.475 0.64040
---
Signif. codes:
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1Residual standard error: 2.933 on 18 degrees of freedom
Multiple R-squared: 0.01239, Adjusted R-squared: -0.04248
F-statistic: 0.2258 on 1 and 18 DF, p-value: 0.6404*
*根据上面的例子,降雨量是-0.1151 温度+ 4.8639
如果我们想要使用模型来估计新值,我们可以使用 predict()函数,其中第一个参数是模型,第二个参数是我们想要预测降雨量的温度值:
*temperature_value <- data.frame(Temperature = 170)
rainfall_value <- predict(model,temperature_value)
print(rainfall_value)*
17.11 贝叶斯模型
贝叶斯模型使用概率来表示未知。目的是输入数据以估计未知参数。
举个例子,假设我们想确定一家公司的股票明天值多少钱。让我们也考虑一下,我们用公司销售额这个变量来估计股票价格。
在这种情况下,股票价格是未知的,我们将使用公司的销售额来计算股票的价格。
我们可以收集历史销售和股票价格的样本,并使用它来找到这两个变量之间的关系。在现实世界的项目中,我们会添加更多的变量来估计股票价格。
需要理解的关键概念是条件概率和贝叶斯定理。文章中解释了这些概念:
* [## 理解概率和统计:数据科学家的概率基础
为统计学家解释概率的关键概念
towardsdatascience.com](/understanding-probability-and-statistics-the-essentials-of-probability-for-data-scientists-459d61a8da44) [## 理解概率和统计:数据科学家的中心极限定理和收敛
本文是“理解概率与统计”系列文章的第二篇。它侧重于 CLT 和…
towardsdatascience.com](/understanding-probability-and-statistics-central-limit-theorem-and-convergence-for-data-scientists-653c53145400)
本质上,我们试图做的是使用股价的先验概率来预测使用似然数据和标准化常数的后验概率。
install.packages("BAS")
library(BAS)
StockPrice <- c(1,2,5,6.4,6.7,7,7,7,8,9,3,4,1.5,0,10,5.1,2.4,3.4, 4.5, 6.7)
Sales <- c(4,4.1,0,1.4,2,1,6.7,7,5,5,8,9,3,2,2.5,0,10,5.1,4.3,5.7) model <- bas.lm(StockPrice~Sales)
print(summary(model))
注意,我们安装了 BAS 包,然后使用了 BAS 库。然后显示结果:
P(B != 0 | Y) model 1 model 2
Intercept 1.00000000 1.0000 1.00000000
Temperature 0.08358294 0.0000 1.00000000
BF NA 1.0000 0.09120622
PostProbs NA 0.9164 0.08360000
R2 NA 0.0000 0.01240000
dim NA 1.0000 2.00000000
logmarg NA 0.0000 -2.39463218
可以使用参数prior
指定回归系数的不同先验分布,包括
- 《BIC》
- “AIC
- " g 优先"
- "超重力"
- “超 g 拉普拉斯”
- “超 g-n”
- 《JZS》
- " ZS-空"
- “ZS-完整”
- "电子商务本地"
- “e B-全球”
17.12 生成随机数
要在一个范围内生成随机数,请使用 runif 函数。这将打印 100 个介于 0.1 和 10.0 之间的随机数
random_number <- runif(100, 0.1, 10.0)
print(random_number)
我们还可以使用 sample()函数生成替换或不替换的项目和数字。
17.13 泊松分布
我们可以使用泊松分布,并使用家庭为泊松分布的 glm 模型:
output <-glm(formula = Temperature ~ Rainfall+Humidity,
family = poisson)
print(summary(output))
结果将被打印出来:
Deviance Residuals:
Min 1Q Median 3Q Max
-3.2343 -0.8547 -0.1792 0.8487 1.8781Coefficients: (1 not defined because of singularities)
Estimate Std. Error z value Pr(>|z|)
(Intercept) 1.69807 0.17939 9.466 <2e-16 ***
Rainfall -0.02179 0.03612 -0.603 0.546
Humidity NA NA NA NA
---
Signif. codes:
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1(Dispersion parameter for poisson family taken to be 1)Null deviance: 35.460 on 19 degrees of freedom
Residual deviance: 35.093 on 18 degrees of freedom
AIC: InfNumber of Fisher Scoring iterations: 5
17.14 正常分布
有几种方法可以生成正态分布的数据。最常见的方法是使用样本大小、平均值和标准差调用 rnorm 函数:
y <- rnorm(100, 0, 1)
17.15 远期替代
向前替换是用于求解线性方程组的常见过程:Lx = y
在这种情况下,L 是具有非零对角线元素的下三角系数矩阵 L。
有两个函数可以帮助我们向前和向后替换。
r 有 forwardsolve(A,b)用于下三角 A 上的前向替换,有 backsolve(A,b)用于上三角 A 上的后向替换。
具体来说,它们是:
backsolve(r, x, k = ncol(r), upper.tri = TRUE,
transpose = FALSE)
forwardsolve(l, x, k = ncol(l), upper.tri = FALSE,
transpose = FALSE)
r:上三角矩阵:R x = b
l:下三角矩阵:L x = b
这两个三角矩阵都给出了我们试图求解的系数。
x:这是矩阵,它的列给出了方程的右边。
k:这是要求我们使用的 r 的列数和 x 的行数。
upper.tri: TRUE 然后使用 r 的上三角形部分。
转置:如果为真,那么我们试图为 y 求解 r' * y = x
输出将与 x 的类型相同,因此,如果 x 是一个向量,那么输出将是一个向量,否则,如果 x 是一个矩阵,那么输出将是一个矩阵。
17.16 T 检验
t 测试可以通过使用 t.test()函数来执行。
例如,R 中的单样本 t 检验可以通过使用t.test(y, mu = 0)
来运行,其中 y 是我们想要检验的变量,而mu
是由零假设指定的平均值:
Humidity <- c(4,4.1,0,1.4,2,1,6.7,7,5,5,8,9,3,2,2.5,0,10,5.1,4.3,5.7)t.test(Humidity, mu = 5)
上面的代码测试湿度是否≤5 的平均值。这是无效假设。
结果是:
单一样本 t 检验
数据:湿度
t = -1.1052,df = 19,p 值= 0.2829
备选假设:真均值不等于 5
95%置信区间:
2.945439 5.634561
样本估计:
x 的均值
4.29
18.在 R 中绘图
这一节将解释在 r 中绘制图表是多么容易。
X-Y 散点图
我生成了以下数据:
x<-runif(200, 0.1, 10.0)
y<-runif(200, 0.15, 20.0)print(x)
print(y)
代码片段将绘制图表
plot(x, y, main='Line Chart')
XY 散点图
相关图
install.packages('ggcorrplot')library(ggcorrplot)
x<-runif(200, 0.1, 10.0)
y<-runif(200, 0.15, 20.0)
z<-runif(200, 0.15, 20.0)data <- data.frame(x,y,z)
corr <- round(cor(data), 1)ggcorrplot(corr)
柱状图
x<-runif(200, 0.1, 10.0)
hist(x)
19.R 语言中的面向对象编程
本节将概述 R 中面向对象编程的概念。理解 R 中如何创建对象是至关重要的,因为它可以帮助您以更简单的方式实现可伸缩的大型应用程序。
在 R 编程语言中需要理解的首要概念是一切都是对象。
函数也是一个对象,如函数部分所解释的。因此,我们必须定义一个函数来创建对象。关键是在对象上设置 class 属性。
r 支持面向对象的概念,比如继承。一个类可以是一个向量。
在 r 中有几种创建类的方法。我将围绕创建 S3 类演示最简单的形式。这包括创建一个属性列表。
在我解释如何构建一个完整的类之前,让我们以一种简化的方式回顾一下步骤:
- 第一步是创建一个命名列表,其中每个元素都有一个名称。每个元素的名称都是该类的一个属性。作为一个例子,这是我们如何在 R 中创建一个人类类:
farhad <- list(firstname="Farhad", lastname="Malik")
class(farhad) <- append(class(farhad), "Human")
- 我们创建了一个具有以下属性的人类类的实例:名字设置为法尔哈德,姓氏设置为马利克。
- 要打印 Human object 实例的 firstname 属性,我们可以这样做:
print(farhad$firstname)
- 现在,让我们转到另一个重要的概念。我们如何为对象创建一个实例方法?
关键是使用命令:UseMethod
这个命令通知 R 系统搜索一个函数。一个对象可以有多个类,UseMethod 使用实例的类来确定要执行哪个方法。
让我们创建 GetName 函数,该函数返回名和姓的连接字符串:
#This is how you create a new generic function
GetName <- function(instance)
{
UseMethod("GetName", instance)
}#This is how you provide a function its body
GetName.Human <- function(instance)
{
return(paste(instance$firstname,instance$lastname))
}GetName(farhad)
最后,让我们创建一个具有属性 firstname 和 lastname 的类 Human。它将有一个函数:GetName(),返回名字和姓氏。
技巧:创建一个返回列表的函数,并将属性作为参数传递给函数。然后使用 UseMethod 命令创建方法。
Human <- function(firstname, lastname)
{
instance <- list(firstname=firstname, lastname=lastname)
class(instance) <- append(class(instance), "Human")
return(instance)
}
GetName <- function(instance)
{
UseMethod("GetName", instance)
}
GetName.Human <- function(instance)
{
return(paste(instance$firstname,instance$lastname))
}
farhad <- Human(firstname="farhad", lastname="malik")
print(farhad)
name <- GetName(farhad)
print(name)
这将打印:
> print(farhad)
$firstname
[1] "Farhad"$lastname
[1] "Malik"attr(,"class")
[1] "list" "Human"
>
>
> name <- GetName(farhad)
> print(name)
[1] "Farhad Malik"
如果我们想创建一个新的类 OfficeWorker,它从 Human 类继承并为 GetName()方法提供不同的功能,该怎么办?
我们可以通过以下方式实现这一目标:
Human <- function(firstname, lastname)
{
instance <- list(firstname=firstname, lastname=lastname)
class(instance) <- append(class(instance), "Human")
return(instance)
}OfficeWorker <- function(firstname, lastname)
{
me <- Human(firstname, lastname)
# Add the class
class(me) <- append(class(me),"OfficeWorker")
return(me)
}
如果我们创建一个办公人员的实例并打印该实例,它将打印以下内容:
worker = OfficeWorker(firstname="some first name", lastname="some last name")
print(worker)> print(worker)
$firstname
[1] "some first name"$lastname
[1] "some last name"attr(,"class")
[1] "list" "Human" "OfficeWorker"
注意,实例的类是 list、Human 和 OfficeWorker
要为办公室工作人员创建不同的功能,我们可以覆盖它:
GetName <- function(instance)
{
UseMethod("GetName", instance)
}
GetName.Human <- function(instance)
{
return(paste(instance$firstname,instance$lastname))
}
GetName.OfficeWorker <- function(instance)
{
return(paste("Office Worker",instance$firstname,instance$lastname))
}
这将打印:
> GetName(worker)
[1] "some first name some last name"
20.如何安装外部 R 包
安装一个 R 包非常简单。
我们所要做的就是键入以下命令:
install.packages("name of package")
要安装多个软件包,我们可以向 install.packages 命令传递一个向量:
install.packages(c("package1","package2"))
例如,CARAT 是最流行的机器学习包之一。
R-Studio 使得安装包变得极其容易。要安装 CARAT,点击右下角的软件包标签,然后点击安装按钮。
输入“克拉”并点击安装
将出现对话框,指示正在安装软件包:
安装软件包后,您可以在控制台窗口中看到它:
The downloaded binary packages are in
C:\Users\AppData\Local\Temp\Rtmp8q8kcY\downloaded_packages
要删除软件包,请键入:
remove.packages("package name")
21.著名 R 图书馆
除了本文提到的 R 库和内置的 R 函数之外,我还推荐了大量有用的 R 包:
- 预言家:预测、数据科学和分析项目
- Plotly :用于图形
- 看门人:用于数据清理
- 插入符号:用于分类和回归训练
- Mlr :用于机器学习项目
- 润滑:用于时间序列数据
- Ggpolot2 :用于可视化
- Dplyr :用于操作和清除数据
- 预测:处理分类数据时
- Dplyr :用于数据操作
22.摘要
本文解释了关于 R 的以下关键领域:
- R 是什么?
- 如何安装 R?
- 在哪里编码 R?
- 什么是 R 包和 R 脚本?
- 有哪些不同的 R 数据类型?
- 如何在 R 中声明变量及其作用域?
- 怎么写评论?
- 什么是矢量?
- 什么是矩阵?
- 什么是列表?
- 什么是数据框?
- R 中不同的逻辑运算
- R 中的函数
- R 中的循环
- 读写 R 中的外部数据
- 在 R 中执行统计计算
- 在 R 中绘图
- R 语言中的面向对象编程
- 著名 R 图书馆
- 如何安装外部 R 库
- 在 R 中绘图
我以一种使语言更容易理解的方式从基础开始解释了编程语言 R。说了这么多,编程进阶的关键是始终尽可能多的练习。
如果您有任何反馈或意见,请告诉我。*
谷歌云上的 R Studio 服务器
原文:https://towardsdatascience.com/r-studio-server-on-google-cloud-dd69b8bff80b?source=collection_archive---------6-----------------------
萨法尔·萨法罗夫在 Unsplash 上拍摄的照片
目标:在 Google 云计算引擎的虚拟机实例上建立一个完全可运行的机器学习服务器。
在现实世界中,云计算和机器学习携手构建、转变和扩展预测建模项目。作为一个 Linux 服务器应用程序,R Studio server 是最好的解决方案之一,可以托管在 Google Cloud(或者 Amazon Web Service 或 Azure)上,以集中的方式自动处理 SQL/ R/ Python 中的大量数据。以下是如何在 Google Cloud 上配置全功能 R Studio 服务器的一步一步的方法:
- 在 Google Cloud 上配置一个虚拟机实例(Ubuntu OS)。
- 在虚拟机上安装 R and R 工作室服务器。
- 创建用户和组。
- 使用 cronR 包调度和运行 R 脚本。
第一步。在 Google Cloud 上配置一个虚拟机实例(Ubuntu OS):
步骤 1.1。创建 Google Cloud 项目:登录 Google Cloud 控制台 创建项目。
创建谷歌云项目(图片由作者提供)
第 1.2 步。创建防火墙规则:通过导航到“菜单”>“网络”下的“防火墙规则”,在 Google 云计算引擎中创建防火墙规则。配置以下设置:
创建防火墙规则(图片由作者提供)
第 1.3 步。创建虚拟机实例:通过导航到“菜单”>“计算引擎”下的“虚拟机实例”,在 Google Cloud 上设置一个新的虚拟机。
创建一个虚拟机实例(图片由作者提供)
第 1.4 步。虚拟机配置:为新的虚拟机实例命名(例如:“rstudio”),并选择一个靠近操作区域的区域,以减少网络延迟。因为 R 将所有的工作数据集存储在内存中,所以尽量给 VM 实例提供尽可能多的内存。在“操作系统映像”下,选择一个支持 OpenSSL 1.0 的最新版本的 Ubuntu。R Studio Server 总是通过不安全的 HTTP 连接进行连接。因此,在防火墙下,“允许 HTTP 流量”。最后,单击“Create”启动实例。
虚拟机配置(图片由作者提供)
第二步。在虚拟机上安装 R and R 工作室服务器:
第 2.1 步。SSH 连接:在 Google Compute Engine 的 VM instances 窗口中,单击新实例旁边的“SSH”。这将启动命令提示符。
SSH 连接(作者图片)
步骤 2.2。更新 apt:更新 apt 以确保我们有最新的软件包可以和 Ubuntu 一起使用。
sudo apt-get update
sudo apt-get upgrade
第 2.3 步。安装 R and R 工作室服务器:
sudo apt-get install r-base r-base-dev
在运行下面几行代码之前,检查一下最新版本的 RStudio 服务器 。安装所有支持包:
sudo apt-get install gdebi-core
wget [https://download2.rstudio.org/server/bionic/amd64/rstudio-server-1.2.5019-amd64.deb](https://download2.rstudio.org/server/bionic/amd64/rstudio-server-1.2.5019-amd64.deb)
sudo gdebi rstudio-server-1.2.5019-amd64.deb
sudo apt-get install libcurl4-openssl-dev libssl-dev libxml2-dev
第三步。创建用户和群组
使用 R studio server 的最大好处之一是,它为我们提供了一个在集中式云框架中与同行协作的窗口。向虚拟机实例添加用户,以便其他人可以同时使用 R Studio 服务器。
第 3.1 步。创建一个组:创建一个组(例如:“marketing”)将使管理团队共享的文件夹和文件变得更加容易。
sudo addgroup marketing
第 3.2 步。创建主用户:创建主用户背后的整个想法是,当同事和同事加入或离开我们时,“主用户”将仍然拥有所有的共享文件。
sudo adduser master
创建一个主用户(图片由作者提供)
第 3.3 步。创建共享文件夹:
cd /home/master
sudo mkdir shared_folder
sudo chown -R master:marketing shared_folder/
sudo chmod -R 770 shared_folder/
第 3.4 步。添加用户并将他们链接到一个共享文件夹:这里我将 Steve 作为一个例子添加到最近创建的“marketing”组中。Steve 的个人文件夹已链接到“主用户的共享文件夹”。
sudo adduser steve
sudo gpasswd -a steve marketing
su - steve
ln -s /home/master/shared_folder /home/steve/shared_folder
exit
添加用户并将他们链接到共享文件夹(图片由作者提供)
就是这样!我们在 Google Cloud 上使用 R Studio 服务器很好。为了在浏览器上打开 R studio 服务器,遵循 URL 语法: http://【外部IP】:8787。例如,如果新配置的虚拟机实例的外部 IP 是 35.185.161.49,那么我们的 R Studio 服务器 URL 将是:http://35.199.10.210:8787/
R Studio 服务器(图片由作者提供)
第四步。使用 cronR 包调度和运行 R 脚本:
安装 cronR 包以在 R Studio 服务器中生成任务调度器。使用该插件自动化虚拟机实例中的任何脚本。
install.packages("cronR")
install.packages("shinyFiles")
cronR 包(图片由作者提供)
第五步:下一步是什么?
我们刚刚在云中完成了机器学习框架的设置。以下是一些建议,说明我们可以做些什么来扩展这种数据建模和预测分析工作流:
1)从内部(CRM 数据库)或外部数据源(第三方供应商,如尼尔森评级或脸书和谷歌广告集)提取、转换和加载数据集到谷歌云计算引擎。
2)用 SQL、R 或 Python 构建数据模型(使用 Reticulate 和 sqldf 包将 python/SQL 脚本源化到 R studio 服务器中)。
3)在源自云的数据模型上构建监督的或无监督的或强化的机器学习算法。使用 cronR 包实现端到端工作流的生产化。将数据集存储在云数据库中。
4)最后,构建一个 BI 仪表板,可视化预测模型(可以是从预测下个月的销售额或流失率到使用无监督聚类模型对客户数据库进行分类的任何内容)。如果感兴趣,可以通过 REST API 将这个实时预测 BI 模型作为一个小部件嵌入到 web/移动应用程序中。
关于作者
[## Sreejith Sreedharan - Sree
数据爱好者。不多不少!你好!我是 Sreejith Sreedharan,又名 Sree 一个永远好奇的数据驱动的…
srees.org](https://srees.org/about)
如果您在理解上述配置方面需要任何帮助,请随时联系我。乐于分享我所知道的!希望这有所帮助:)
r 教程:分析新冠肺炎数据
原文:https://towardsdatascience.com/r-tutorial-analyzing-covid-19-data-12670cd664d6?source=collection_archive---------9-----------------------
在现实世界中使用 R 的介绍
来源
这学期我在耶鲁上计量经济学导论课,我们利用 R 和统计学来分析各种数据集。因此,当我在家与自己保持社交距离时,我认为将我在新冠肺炎数据集上学到的一些技术应用起来会很有趣。
我在 Kaggle 上使用了这个页面,发现了一个 CSV 数据集,你可以在这里获得。
让我们看一下数据:
我们有大约 1000 例新冠肺炎病例的数据。我们可以看到每个感染者的年龄,挡泥板,他们是否恢复或死亡,以及其他许多事情。对于本教程,我们将只看其中的几个专栏。让我们用这个 CSV 文件创建一个文件夹,并启动 RStudio。
在 RStudio 中,要导入数据集,我们将转到文件->导入数据集->从文本(基本)。找到您的 CSV 文件,然后单击“导入”您将在 RStudio 的控制台中看到这样一行:
我们将把这一行复制到我们的主 R 脚本中,我将把它保存为脚本。与我们的 CSV 文件放在同一个文件夹中。
为了方便起见,我将把数据框变量重命名为“data”我还将清除所有现有的变量,导入一个名为 Hmisc 的库,并使用它的 describe 函数来更好地理解我们的数据。
如果您运行这段代码,您将在控制台中看到大量信息。例如,我们有 1085 行。如果我们查看死亡部分,我们会看到有 14 个不同的值。这可能看起来有点奇怪,但是死亡一栏要么是 0(没有死亡),要么是 1(没有死亡),或者仅仅是患者的死亡日期。这很难做到,因为我们想要全是 0 和 1。
让我们通过向数据集添加一个 death_dummy 列来解决这个问题,它只包含值 0 和 1。
我们还计算了数据集的死亡率,运行后结果是 5.8%。在本教程的第一部分,我们将分析死亡和未死亡的人的年龄。
年龄
媒体声称新冠肺炎的老年人比年轻人更容易死亡。这是真的吗?让我们用数据集检查一下。首先,我们将我们的数据集分成活着的患者和已经去世的患者,并比较平均年龄。这段代码将为我们做这件事:
请注意,na.rm=TRUE 意味着跳过特定列(在本例中为 age)为 na(或没有值)的行。运行这个程序后,我们得到存活者的平均年龄是 48 岁,而死亡的平均年龄是 68.6 岁。
好的,所以数据确实显示在我们的样本中,那些死去的人年龄更大。但是这对于所有人来说都是真的吗?我们有多大把握这是真的?
我们可以使用 t.test 命令来衡量我们的信心,看看我们是否可以信任我们的方法。在这种情况下,我们将使用 95%的置信区间。
这个简单的命令非常强大。注意,我们给出了活着的病人和死去的病人的年龄。我们来分析一下输出。
查看置信区间,我们可以 95%肯定地说,已经死亡和没有死亡的患者之间的年龄差异是从 16.7 岁到 24.3 岁。现在,看看 p 值。快 0 了。这意味着,在零假设(即两组的年龄相等)下,我们有大约 0%的机会从这个样本中随机获得这样的极端结果。出于这个原因,我们可以合理地拒绝零假设(在 0.05 的常规显著性水平下),并说死于新冠肺炎病的人确实比没有死于该病的人更老。现在,我们来看看性别!
性别
这个会很像。我们想知道男性和女性的死亡率是否相似。让我们再次分割数据并进行 t 检验:
我们将原始数据分成两组。计算平均值后,我们看到数据集中男性的死亡率为 8.5%,而女性为 3.7%。这真是出乎意料。还是那句话,我们能相信这个数据吗?下面是 t.test 输出:
我们 95%的置信区间表明,平均死亡率将比女性高 1.7%至 7.8%。p 值为 0.002 意味着我们可以拒绝男性和女性死亡率相同的无效假设,因为 0.002 < 0.05.
There have been articles written that men indeed do have a higher coronavirus death rate. 这里的是其中之一,如果你感兴趣的话。
结论
正如您所看到的,R 帮助我们非常容易地对重要的数据集进行统计分析。感谢您的阅读!
伯特的种族偏见
原文:https://towardsdatascience.com/racial-bias-in-bert-c1c77da6b25a?source=collection_archive---------31-----------------------
BERT 嵌入向量中不公正偏差的理解和可视化
机器学习的公平性和偏见是一个越来越多地讨论的问题。随着迁移学习应用中使用的预训练语言模型的发展,理解预训练模型继承的不公正偏见至关重要。
在这篇文章中,我将重点关注英语 BERT [1],这是一个在多伦多图书语料库[2]和维基百科上训练的语言模型。为了检测模型中的偏见,我将使用 Sweeney 在谷歌搜索中显示种族偏见时使用的相同的一组黑人和白人、女性和男性的名字[3]。她作品中的名字基于 Bertran 等人[4]和 Fryer 和 Levitt [5]。这篇文章的灵感来自雷切尔·托马斯的实用数据伦理课程。
方法学
演示使用了拥抱脸变压器包和bert-base-cased
网络。下面的代码显示了网络的用法(基于 Transformers GitHub 页面的示例)。
使用 HuggingFace transformers 的 BERT 模型——基于 GitHub 示例
这个网络为句子中的每个标记产生 768 维向量。该研究测量如下:给定句子 s ,对于记号 t∈s 如果我们用掩蔽记号[MASK]
替换记号 t 两个记号的嵌入向量彼此有多接近,余弦 _ 相似度(f(t),f(*[MASK]*
)。
BERT 的训练步骤试图为屏蔽的令牌识别正确的令牌,因此,该测量提供了对模型认为给定令牌可以替代[MASK]
的可能性的洞察。为了能够比较这些标量值,该研究调查了成对的标记。例如在句子“艾米丽是个女人。”,单个令牌字女换成令牌【面具】和令牌男。通过计算这两个分数,这项研究寻求了一个问题的答案,“这个模型更可能把单词女还是男放在句子的末尾?”
m(p,q) = cosine_similarity(f(p),f(MASK))-cosine_similarity(f(q),f(MASK))
接下来,实验将名字列表放入两种类型的句子中:<NAME> is <ADJ>.
和<NAME> is a <NOUN>.
,其中标记对是某种类型的词对,如女人-男人、演员-女演员或富人-穷人。
每个名称的令牌数
虽然没有必要运行这个实验,但我认为完整的图片包括一个关于名称表示所需的标记数量的注释。
一方面,每个白人男性的名字用一个记号表示,而只有一个白人女性的名字用两个记号表示: Katelyn。另一方面,黑人男性姓名的平均标记数为 2.29,黑人女性姓名的平均标记数为 2.35。只有两个黑人女性的名字用一个 token 代表,而且两个名字都有不同的含义:肯尼亚和钻石。这不是由名字的长度引起的:Nia 这个名字只有两个字母,却用两个符号来表示!
如果一个人理解了 BERT 的 tokenizer 词块[6]背后的算法,她可以得出结论,这是数据集(书籍和维基百科)中黑人名字出现次数少的结果。这意味着
伯特患有针对黑人名字的“T21 偏见”。
为了评估实验结果,我们必须记住这一点。预训练的伯特可能没有足够的黑人名字样本来做我们将在下面看到的表示。
表象中想要的相似性
当研究人员发明单词的嵌入向量表示时,focus 的目标是建立一个向量空间,其中相似的单词彼此靠近。记住这一点,第一个实验包括象征性的男女和演员对。一个合理的假设是,模特更有可能选择男男和男演员作为男性名字,女女和女演员作为女性名字。第一对句子是<NAME> is a [MASK].
、<NAME> is a man.
和<NAME> is a woman.
,第二对句子是<NAME> is an [MASK].
、<NAME> is an actor.
和<NAME> is an actress.
。
男-女,男-女演员投影中的白人名字
在一个二维图形中表示白人的名字,我们可以沿着两个轴在视觉上将女性和男性的名字分开。由于所有的名字都在右上方的四分之一平面上,模型为每个名字确定了更靠近男主角和男主角的[MASK]
。因此,我建议在看数字时,应该分析相互比较的结果,而不是看原始数字。
这是一个很好的例子,它符合人们对模型的期望。让我们把黑人的名字放在桌子上!
男女演员投影中的所有名字
首先,我想指出的是,在投影中,黑人的名字比白人的名字更接近。其次,尽管有一些例外,但演员-演员轴和上一个差不多(不过,没有以前那么容易画门槛线了)。最后,原来在男女轴心上的分离完全消失了。
对白人名字的假设对黑人名字会失效。
不公正的偏见
虽然我们希望从模型中找到与性别相关的名词作为名字,但是在其他一些例子中,模型中的偏见是不必要的。比如用令牌对贫富和对错。
在下一个实验中,我举例说明了句子对“X 是一个演员。”——“X 是个女演员。”和“X 有钱。”——“X 差。”。请注意,有一个象征性的区别,单词“an”在新句子中缺失。让我们看看白人的名字!
贫富、男女演员投影中的白人名字
在这个图中,我沿着男演员-女演员轴展示了贫富轴。虽然人们可以沿着演员轴看到前一节中讨论的可能的分离,但人们不能沿着贫富轴看到同样的分离。我觉得不错,模型在这种新的情况下不能区分男女名字,穷富句对(一切都更接近于穷尾)。这是我们应该从公平模型中期待的。让我们看看其他的名字!
所有的名字都在贫富、男女演员的投影中
首先,我想指出,许多黑人的名字在投影上的位置与白人的名字相似。有趣的是,尽管我之前有所期待,黑人名字比白人名字更接近富人阶层。但最重要的是,这句话里有很大一部分黑人名字的表现和白人名字完全不同!在男女演员轴上,最大的差距不到 0.05,而在贫富轴上,拉坦亚和沙尼斯之间的差距大于 0.1。计算黑白女性-男性的平均值,人们可以得出这样的结论:在贫富句子中,该模型使黑白女性名字之间的差异是男演员-女演员句子中白人女性和男性名字之间的差异的 1.8 倍。
在伯特模型中,不公正的偏差大于期望的差异。
所有的名字在对错,演员演员投影
可能的解决方案
如果我们详述前面的例子,我们可以发现关于名字有许多异常。这可能导致基于预先训练的 BERT 网络的模型中的遗传偏差。为了发展一个更公平的网络,我建议考虑以下几点:
- 在输入预训练的 BERT 模型之前,使用命名实体识别过滤名称并用
[UNK]
标记替换它们。 - 用命名实体的特殊标记训练 BERT 模型,并将它们从原始文本中屏蔽掉。
我认为,如果想要使用预先训练好的模型建立一个公平的网络,理解 BERT 中的偏差是很重要的。我希望这个故事有助于实现这一目标。实验中使用的所有代码都在这里可用,我在下面附上了完整的名称表。
《伯特》中的黑白男女姓名表征
参考
[1] Devlin,j .,Chang,M. W .,Lee,k .,& Toutanova,K. (2018 年)。Bert:用于语言理解的深度双向转换器的预训练。 arXiv 预印本 arXiv:1810.04805 。
[2]朱、虞琨;基罗斯,瑞安;泽梅尔,有钱;萨拉赫胡季诺夫、鲁斯兰;乌尔塔松、拉克尔;安东尼奥·托雷巴;桑亚·菲德勒(2015 年)。“对齐书籍和电影:通过观看电影和阅读书籍实现故事般的视觉解释”。第 19-27 页。arXiv:1506.06724[cs。CV 。
[3]斯威尼,L. (2013 年)。在线广告投放中的歧视。队列, 11 (3),10–29。 arXiv:1301.6822
[4] Bertrand M 和 Mullainathan s . Emily 和 Greg 比 Lakisha 和 Jamal 更有就业能力吗?劳动力市场歧视的现场实验。NBER 工作底稿№9873。2003 年 7 月。http://www.nber.org/papers/w9873(截至 2013 年 1 月 9 日)。
[5] Fryer R 和 Levitt S .独特黑人姓名的原因和后果。经济学季刊。2004 年 8 月第 59 卷第 3 期。http://price theory . uchicago . edu/Levitt/Papers/fryerlevit 2004 . pdf(截至 2013 年 1 月 9 日)。
[6]吴,m .舒斯特,陈,z .乐,Q. V .,m .马切里,w .,… &克林纳,J. (2016)。谷歌的神经机器翻译系统:弥合人类和机器翻译之间的鸿沟。 arXiv 预印本 arXiv:1609.08144 。
警察拦截和搜查中的种族差异
原文:https://towardsdatascience.com/racial-disparities-in-police-stops-and-searches-e58319f278a2?source=collection_archive---------27-----------------------
变更数据
多年来警察拦截和搜查的统计分析,以确定警察是否对少数群体有偏见
由内森·杜姆劳在 Unsplash 上拍摄的照片
摘要
这份报告旨在调查与黑人或西班牙裔等少数民族相比,警察队伍是否对白人有种族偏见。我分析了斯坦福开放警务项目的数据,该项目收集了 2013 年至 2017 年间宾夕法尼亚州费城警察拦截的标准化数据。我评估了警察做出的有偏见的决定,其基础是检查警察搜查被拦下的司机的频率,以及这些搜查是否能成功找到违禁品。原始数据包含司机的年龄、性别、种族/民族、停车位置以及警察是否搜查过他们等信息。
介绍
几十年来,警察队伍中的种族偏见一直是一个有争议的话题。然而,最近警察拦截和搜查的消息导致了针对无辜美国黑人的暴力事件。例如,46 岁的手无寸铁的美国黑人乔治·弗洛伊德(George Floyd)因涉嫌使用假钞被一名警察杀害。由于警察对黑人的歧视,这一事件在世界范围内引发了抗议和愤怒。
对拦截和搜查率的数据进行评估,可以为是否存在针对少数群体的种族歧视提供证据。另一个策略是评估成功识别违禁品的搜索比例。如果成功搜查少数族裔的比例少于白人,这可能表明警察搜查少数族裔的证据不足。为了缩小分析范围,我将数据细分为 2017 年的车辆警察停车。
数据集解释
在这份数据中,2014 年 1 月 1 日至 2017 年 12 月 31 日期间,宾夕法尼亚州费城发生了 1,756,587 次警察拦截。2017 年,这些警察站中有 294,060 个是车辆警察站。
图 1
直方图(图 1)显示了司机的年龄分布。数据向右倾斜。这表明,与老年人相比,年轻人更容易被警察拦下。被停止的平均年龄约为 35 岁。
图 2
图 2 显示了驾驶员的种族/民族分布。黑人司机的比例过高,因为大约 69%的拦截都是针对黑人司机进行的。只有 17%的停车是对白人司机进行的,10%是对西班牙裔司机进行的。然而,这可能是因为费城的大部分人口是黑人。
被拦下的司机 70%是男性,30%是女性。
结果和数据分析
进行搜索
卡方检验分析
下面是卡方测试分析的代码块。这用于检查司机的种族/民族是否取决于警察是否会搜查司机。“假”表示未被搜索的驾驶员人数,“真”表示被搜索的驾驶员人数。
## Pearson's Chi-squared test
##
## data: search.conducted.table
## X-squared = 430.36, df = 4, **p-value < 2.2e-16****# Expected values for each race/ethnicity**chisq.test(search.conducted.table)$expected##
## white black hispanic
## FALSE 47745.775 190926.34 28194.879
## TRUE 2723.225 10889.66 1608.121**#Residual plot**chisq.test(search.conducted.table)$resid##
## white black hispanic
## FALSE 3.0764323 -2.4243816 0.6081798
## TRUE -10.3478119 10.1514171 -2.5465819
假设检验
H0:进行搜查的警察与司机的种族/民族之间没有联系
H1:进行搜查的警察与司机的种族/民族有关联
设α= 0.05。x 检验统计量的 p 值非常显著(卡方检验的 p < 2.2e-16). There is sufficient evidence to reject the null hypothesis and conclude that there is an association between the police conducting a search and the driver’s race/ethnicity.
Based on the residuals, more Black individuals than expected were searched. Less White individuals than expected were searched.
假设
满足卡方检验的假设。有理由相信样本是独立的,因为这些人是在费城的部分地区取样的。所有预期值都大于 10。
逻辑回归分析:进行搜索
下面是逻辑回归分析的代码块,用于预测司机被拦下后是否会被搜索。一个模型被用来估计警察搜查司机和司机的种族/民族之间的联系,调整混杂变量性别和年龄。
##
## Call:
## glm(formula = search_conducted ~ subject_race + subject_age +
## subject_sex, family = binomial(link = "logit"), data = stops.subset
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.5829 -0.4007 -0.2894 -0.2184 3.4213
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.9656439 0.0774345 -25.385 < 2e-16 ***
## subject_raceblack 0.7817956 0.0735729 10.626 < 2e-16 ***
## subject_racehispanic 0.5594270 0.0777094 7.199 6.07e-13 ***
## subject_raceother/unknown 0.2212841 0.1079140 2.051 0.0403 *
## subject_racewhite 0.4758386 0.0764091 6.228 4.74e-10 ***
## subject_age -0.0418716 0.0008089 -51.762 < 2e-16 ***
## subject_sexfemale -1.0650471 0.0234808 -45.358 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 123230 on 293539 degrees of freedom
## Residual deviance: 117002 on 293533 degrees of freedom
## (520 observations deleted due to missingness)
## AIC: 117016
##
## Number of Fisher Scoring iterations: 6
斜率系数和 P 值的解释
由于模型中包含了年龄,因此模型截距没有有意义的解释。模型截距表示警察搜索 0 岁男性和亚洲/太平洋岛民种族的预测对数概率。预测警察搜查新生儿的概率是不合理的。
黑人的斜率表明,在保持年龄和性别不变的情况下,警察搜查一名黑人的估计对数概率比搜查一名亚裔/太平洋岛民的概率高 0.78。
黑人和西班牙裔的斜率高于白人的斜率。例如,警察搜查一个黑人的对数概率是警察搜查一个白人的对数概率的 1.36 倍。如果双方都是 35 岁的男性。
这表明警察更可能搜查少数民族而不是白人。
每个种族/民族的斜率系数的 p 值小于α= 0.05。因此,这些数据提供了证据,证明警察搜查司机与司机的种族/族裔有显著关联。
搜查违禁品
双样本比例检验
下面是双样本比例测试的代码块。这用于确定拥有违禁品的白人个体的比例是否低于黑人个体。如果成功搜查黑人的比例低于白人,这表明警察搜查少数民族的证据不足。
#conduct test
prop.test(successes, n)##
## 2-sample test for equality of proportions with continuity correction
##
## data: successes out of n
## X-squared = 6.8023, df = 1, **p-value = 0.009104**
## alternative hypothesis: two.sided
**## 95 percent confidence interval:
## -0.046884129 -0.005958199**
## sample estimates:
**## prop 1 prop 2
## 0.2237007 0.2501219**
假设检验
p1 代表在被搜查的黑人个体中拥有违禁品的黑人个体的比例。
p2 表示在被搜查的白人个体中,拥有违禁品的白人个体的比例。
H0 : p1 = p2
哈:p1 不等于 p2
设α= 0.05。检验统计的 p 值显著(p= 0.009104)。有足够的证据拒绝零假设,并得出结论,两个种族群体之间的比例存在差异。
基于 p1 和 p2 的比较,拥有违禁品的白人个体的比例高于黑人个体。
置信区间
比例差异的 95%置信区间为(-0.047,-0.006)。在 95%的置信度下,白人个体相对于黑人个体拥有违禁品的比例的差异被区间(-0.047,-0.006)捕获。间隔不包含 0。这与差异的统计学显著证据一致。
比例测试的假设
下面是检查每个种族拥有违禁品的司机数量的代码块。“假”表示没有携带违禁品的驾驶员人数,“真”表示携带违禁品的驾驶员人数。
(table(searches$subject_race, searches$contraband_found))##
## FALSE TRUE
## asian/pacific islander 147 48
## black 9276 2673
## hispanic 1202 304
## other/unknown 137 29
## white 1538 513
满足成功-失败条件。对于置信区间和假设检验,每个种族/民族群体发现违禁品的预期成功和失败次数都超过 10 次。假设样本是独立的是合理的。
逻辑回归分析:识别违禁品
下面是逻辑回归分析的代码块,用于预测司机在被搜查后是否会持有违禁品。一个模型被用来估计警察识别违禁品和司机的种族/民族之间的关系,调整了性别和年龄这两个混淆变量。
##
## Call:
## glm(formula = contraband_found ~ subject_race + subject_age +
## subject_sex, family = binomial(link = "logit"), data = stops.subset)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -0.8486 -0.7355 -0.7030 -0.6152 2.0279
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -0.767719 0.177718 -4.320 1.56e-05 ***
## subject_raceblack -0.156001 0.168090 -0.928 0.353365
## subject_racehispanic -0.290847 0.178694 -1.628 0.103605
## subject_raceother/unknown -0.452432 0.263905 -1.714 0.086460 .
## subject_racewhite 0.074991 0.174405 0.430 0.667210
## subject_age -0.010238 0.001929 -5.308 1.11e-07 ***
## subject_sexfemale -0.215671 0.058023 -3.717 0.000202 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 16875 on 15827 degrees of freedom
## Residual deviance: 16816 on 15821 degrees of freedom
## (278232 observations deleted due to missingness)
## AIC: 16830
##
## Number of Fisher Scoring iterations: 4
解释斜率系数和 P 值
黑人的斜率表明,在保持年龄和性别不变的情况下,警察识别黑人违禁品的估计对数概率比亚裔/太平洋岛民低 0.156。
白人的斜率表明,在保持年龄和性别不变的情况下,白人警察识别违禁品的估计对数概率比亚洲/太平洋岛民高 0.075。
黑色人种的斜率为负,白色人种的斜率为正。这表明白人比黑人更有可能拥有违禁品。
每个种族/民族的斜率系数的 p 值大于α= 0.05。因此,没有足够的证据证明警察识别违禁品与司机的种族/民族有显著的联系。
结论
基于 2013 年至 2017 年宾夕法尼亚州费城 1756587 名被拦司机的数据,有证据表明,这些结果表明对黑人司机存在偏见。这项研究特别研究了司机的种族/民族是否取决于警察是否会搜查司机。与白人相比,黑人和西班牙人更有可能被搜查。该数据还评估了每个种族/民族中拥有违禁品的个人比例。结果显示,白人拥有违禁品的比例高于黑人。因此,根据较少的证据可以合理地得出结论,警察正在搜查少数民族。
严格地说,这个结果适用于居住在宾夕法尼亚州费城的人们。将这些结果推广到宾夕法尼亚州的其他地方也是合理的,因为该州的治安策略是相同的。由于被拦下的司机被搜查的速度不同,因此推广到所有其他州是不合适的。所以其他州的警察不一定对少数民族有偏见。
R 中的雷达图
原文:https://towardsdatascience.com/radar-chart-in-r-222c30866b1b?source=collection_archive---------17-----------------------
凯利·西克玛在 Unsplash 上的照片
如何使用 fmsb 库创建图表?
D 数据可视化对于从数据中获得洞察力非常重要。我们可以使用许多图表,例如条形图、直方图、折线图、雷达图等等。它的使用取决于我们想要达到的目的。
雷达图或蜘蛛图是一种在二维图表中显示多元数据的图表,其中每个变量都从同一点开始。
在本文中,我想向您展示如何构建雷达图,从准备数据开始,一直到数据的可视化。对于数据集,我们将使用 R4DS 学习社区在#TidyTuesday 使用的数据集。对于库,我们将使用 fmsb 和 tidyverse 库。最终的图表看起来会像这样,
数据描述
我先解释一下数据。这些数据来自#TidyTuesday 活动,该活动是为那些希望提高使用 R 的技能的人举办的,特别是在数据可视化和数据争论方面。它是基于向皇家防止虐待动物协会(RSPCA)的投诉,以及该协会自 1999 年以来做出的结果。它由 3 个数据集组成,例如它们是 animal_outcomes.csv、animal_complaints.csv 和 brisbane_complaints.csv。现在,我们只使用 animal_outcomes.csv 来创建雷达图。
该过程
要创建条形图,我们必须首先准备数据集。起初,数据集看起来像这样,
该数据集由 664 行和 12 列组成,其中每行包括年份、动物类型、状态,以及 RSPCA 照顾它们后的结果,无论是被回收还是目前被照顾。
我们想要这样的数据集,
为了让数据集看起来像这样,我们必须用这样的代码预处理数据,
下面是解释。首先,我们必须删除 total 列,该列描述了动物在每个州的每个条件的总和。然后,我们必须过滤只使用猫作为我们的动物类型。然后,我们必须将第 4 列旋转到第 11 列。然后,我们必须通过合计全年的数字来总结每个状态、结果和动物类型的数字。然后,我们扩展列以使数据集更长。最后,我们找出第一和第二列,并将州名设置为行名。
老实说,我们可以将数据作为雷达图的输入,但结果并没有那么好。它看起来像这样,
那不是我们想要的图表。为了解决这个问题,我们可以对每一列进行规范化,使其具有 0–1 的范围。我们可以使用最小-最大缩放,代码看起来像这样,
在我们缩放每一列之后,在使用 graph 函数之前,我们必须再做一个任务。我们必须将图表中每一列的最小值和最大值相加。我们可以将最小值设置为 0,将数据中的最大值设置为 1。代码看起来像这样,
完成后,我们可以使用这些数据来创建我们的图表。要构建它,我们可以使用 fmsb 库中的 radarchart 函数。该函数需要的参数是数据、基于我们的列的轴段的数量、颜色以及线条的宽度。代码看起来像这样,
结果将是这样的,
最后,我们已经完成了雷达图的构建。希望对你有用。如果你有一些问题或者一些建议,可以在下面评论下来。感谢您阅读我的文章。如果你想看我的其他文章,你可以看看下面,
[## R 中 ARIMA 模型的时间序列预测
从勘探到预测 1970 年至 2015 年的二氧化碳排放数据。
towardsdatascience.com](/time-series-forecasting-with-arima-model-in-r-77f4e2ae7abb) [## 使用 PyTorch 和 Flask 构建预测苹果叶部病害的 Web 应用程序
使用预先训练的模型(VGG-16、雷斯网-18 和 AlexNet 架构)构建图像分类器 web 应用。
towardsdatascience.com](/build-a-web-application-for-predicting-apple-leaf-diseases-using-pytorch-and-flask-413f9fa9276a) [## Python 中的客户细分
基于 K-均值聚类算法的图像分割。
towardsdatascience.com](/customer-segmentation-in-python-9c15acf6f945)
参考
https://www.r-graph-gallery.com/spider-or-radar-chart.html
径向基函数(RBF)核:定位核
原文:https://towardsdatascience.com/radial-basis-function-rbf-kernel-the-go-to-kernel-acf0d22c798a?source=collection_archive---------0-----------------------
你正在研究一种机器学习算法,比如针对非线性数据集的支持向量机,但你似乎无法找出正确的特征变换或正确的核来使用。嗯,害怕不是因为径向基函数(RBF)核是你的救星。
图一:别担心!RBF 帮你搞定了。【图片来源:Tenor (tenor.com)】
RBF 核是最普遍的核化形式,并且由于其与高斯分布的相似性,是最广泛使用的核之一。用于两点 X₁和 X₂的 RBF 核函数计算相似性或它们彼此有多接近。这个内核可以用数学方法表示如下:
哪里,1。σ'是方差,我们的超参数
2。|| X₁ - X₂|| 是 X₁和 X₂两点之间的欧几里德(l₂-范数)距离
设 d₁₂是 X₁和 X₂两点之间的距离,我们现在可以将 d₁₂表示如下:
图 2:空间两点间的距离【图片由作者提供】
内核等式可以重写如下:
径向基函数核的最大值可以是 1,并且当 d₁₂为 0 时出现,此时点是相同的,即 X₁ = X₂.
- 当这些点相同时,它们之间没有距离,因此它们非常相似
- 当这些点相距很远时,则核值小于 1 并接近 0,这意味着这些点是不相似的
距离可以被认为等同于相异,因为我们可以注意到,当两点之间的距离增加时,它们就不那么相似了。
图 3:相似度随着距离的增加而降低【图片由作者提供】
重要的是找到正确的“σ”值,以决定哪些点应被视为相似,这可以在个案的基础上证明。
a】σ= 1
当σ = 1 时,σ = 1,RBF 核的数学方程如下:
下面给出了该方程的曲线,我们可以注意到,随着距离的增加,RBF 核呈指数下降,并且对于大于 4 的距离为 0。
图 4:σ= 1 的 RBF 核【图片由作者提供】
- 我们可以注意到,当 d₁₂ = 0 时,相似性是 1,当 d₁₂增加超过 4 个单位时,相似性是 0
- 从图中我们看到,如果距离小于 4,这些点可以被认为是相似的,如果距离大于 4,则这些点是不相似的
b】σ= 0.1
当σ = 0.1 时,σ = 0.01,RBF 核的数学方程如下:
对于σ = 0.1,相似区域的宽度最小,因此,只有当点非常接近时,它们才被认为是相似的。
图 4:σ= 0.1 的 RBF 核【图片由作者提供】
- 我们看到该曲线非常陡峭,对于大于 0.2 的距离为 0
- 仅当距离小于或等于 0.2 时,这些点才被视为相似
b】σ= 10
当σ = 10,σ = 100 时,RBF 核的数学公式如下:
对于σ = 100,相似区域的宽度较大,因为这使得较远的点可以被认为是相似的。
图 5:σ= 10的 RBF 核【图片由作者提供】
- 曲线的宽度很大
- 对于 10 个单位以内的距离,这些点被认为是相似的,超过 10 个单位,它们就是不相似的
从以上情况明显看出,相似区域的宽度随着σT5 的变化而变化。
为给定数据集找到正确的σ非常重要,可以通过使用网格搜索交叉验证和随机搜索交叉验证等超参数调整技术来实现。
RBF 核因其与 K-最近邻算法的相似性而广受欢迎。它具有 K-NN 的优点,克服了 RBF 核支持向量机在训练时只需要存储支持向量而不是整个数据集的空间复杂度问题。
RBF 核支持向量机是在 scikit-learn 库中实现的,有两个相关的超参数,“C”代表 SVM,“γ”代表 RBF 核。这里,γ与σ成反比。
图 6:虹膜数据集的径向基函数核 SVM【图片来源:https://scikit-learn.org/】
从图中我们可以看出,随着γ的增加,即σ的减少,对于给定的 c 值,模型往往会过度拟合。
为了实现最佳偏置-方差权衡,找到正确的γ或σ以及 C 值至关重要。
参考文献:
- SVM 的 Scikit-Learn 实现:https://sci kit-Learn . org/stable/auto _ examples/SVM/plot _ RBF _ parameters . html
- 径向基函数核:https://en.wikipedia.org/wiki/Radial_basis_function_kernel
径向颜色直方图
原文:https://towardsdatascience.com/radial-color-histograms-a3ab0441516?source=collection_archive---------57-----------------------
当颜色、构图和计算对您的计算机视觉问题都很重要时——径向减少图像数据的表示
在 Unsplash 上由 Finn-E 拍摄的照片
假设您有一个计算机视觉问题,以下情况为真:
- 访问计算是一个限制,所以使用最新的艺术状态 CNN 架构不是一个选项。
- 颜色对于解决这个问题很重要,所以颜色直方图可以用于每个图像的低维表示。
- 但是合成也提供有用的信息,所以您需要一种方法在您的特征空间中保存这些信息。
对于这种情况,使用每个图像的径向颜色直方图表示可能是解决方案。
什么是径向颜色直方图?
它就像一个颜色直方图,但有一些关于图像组成的信息。在下图中;颜色直方图(顶部)给出了一个简单的表示,而径向颜色直方图(中间和底部)通过将图像分割成具有相同像素数的片段,保留了一些关于照片布局的信息。
照片由 Finn-E 在 Unsplash 上拍摄(直方图由作者提供)
特征空间
径向颜色直方图产生比颜色直方图更大的特征空间,如果你将图像分割成 X 个部分,那么它将是 X 倍大。
上面的基本示例中,每个通道使用 3 个面元(每个段提供 3 个面元),但对于实际应用,您可能需要每个通道 8 个面元的更高粒度(每个段提供 8 个面元)。当你把它分成 8 段时,你得到一个 8*8 = 4096 的特征空间。
与现代 CNN 的输入相比,这种表示仍然微不足道,现代 CNN 通常使用大约 2242243=150528 的特征空间。
应用程序
- 更简单的分类任务,您不希望在每幅图像中包含不必要的信息而加重模型的负担。
- 需要使用大型系综的复杂任务;径向颜色直方图模型可以是有用的齿轮,使用和再训练都很便宜。
履行
如果您想批量处理图像,或者只是玩玩用于创建上面图形的代码,请查看radialColorHistogram
库。
[## 高斯/径向颜色直方图
颜色直方图提供了颜色的表示,但不表示图像的组成。辐射状颜色直方图…
github.com](https://github.com/gmorinan/radialColorHistogram)
关于使用这种方法有效解决计算机视觉问题的例子,请查看我的文章迷因视觉:迷因分类的科学。
这与我在 机器医学科技 的工作无关。
放射科医生如何使用计算机视觉诊断新冠肺炎
原文:https://towardsdatascience.com/radiologists-computer-vision-diagnose-covid-cecbcdf96e8f?source=collection_archive---------52-----------------------
通过缩短 65%的评估时间,人工智能在抗击新冠肺炎病毒传播方面发挥了关键作用
图片由穆罕默德·哈桑拍摄,来自皮克斯拜
疫情冠状病毒已经蔓延到世界各地。逆转录-聚合酶链式反应(RT-PCR)测试通常用于筛查患者,使那些被感染的人能够快速接受治疗。
尽管被普遍使用,该检测试剂盒给出了 30%的假阴性结果。这意味着,每 10 个被新冠肺炎病毒感染的人中,就有 3 人被解除警报。专家建议阴性测试通常并不意味着这个人没有疾病。这需要注意不可靠测试带来的风险,因为错误的测试结果会导致错误的安全感。
专家说,即使你的新冠肺炎病毒检测呈阴性,也要假设你已经感染了
由于我们已经集体测试了数百万人,一些测试结果需要一个多星期。冠状病毒测试仍然是美国应对疫情最紧迫的问题之一。疑似新冠肺炎的患者迫切需要诊断和适当的治疗——这需要快速准确的冠状病毒诊断。因此,全球的科学家都在寻找更可靠的评估。
由于新冠肺炎是一种呼吸道疾病,它会导致一系列呼吸问题。这导致了肺部感染,肺泡发炎,医生可以在计算机断层扫描上看到呼吸道炎症的迹象。(CT)扫描。
CT 图像提供了我们肺部的高质量 3D 图像,有助于检测新冠肺炎的存在。由于大多数扫描只需几分钟,医护人员和研究人员可以获得大量高质量的图像。
3D CT 图像包含 200–400 个图像切片;专家可能需要很长时间才能做出诊断。由于新冠肺炎与其他类型的肺炎有相似的特征,一个非常有经验的医生至少需要 10 分钟来诊断一个病人。因此,非常需要使用计算机视觉的人工智能辅助诊断。
阿里巴巴集团建立了一个人工智能系统,能够根据 CT 扫描图像进行病毒诊断和分析。这个人工智能系统可以在不到 30 秒的时间内诊断 CT 图像,准确率为 96%。
图像分割— U-Net
图像分割是基于人工智能的新冠肺炎图像处理和分析的重要步骤。它有助于放射科医生准确识别肺部感染,并促进定量分析和诊断。图像分割突出了感兴趣的区域,例如 CT 图像中的感染区域,用于进一步的评估和量化。在 AI 评估的帮助下,放射科医生的阅读时间缩短了 65%。
U-Net 是医学图像分割的常用技术。Ronneberger 等人的这篇论文发表在 2015 MICCAI 上,在 2020 年 4 月被引用超过 13000 次。它有一个 U 形结构,带有一个扩展路径和一个收缩路径,这产生更精确的适合医学成像的分割。
Ronneberger 的 U-Net 架构
[## 生物医学图像分割:U-Net
使用非常少的训练图像,并产生更精确的分割。
towardsdatascience.com](/biomedical-image-segmentation-u-net-a787741837fa)
UNet++
基于 U-Net,周等人提出了 UNet++ ,旨在通过在编码器和解码器之间加入密集块和卷积层来提高分割精度。比 U-Net 稍微复杂一点;然而,它带来了 3 个好处。
- 重新设计的跳过路径使得语义相似的特征图的优化更加容易
- 密集跳跃连接提高了分割精度并改善了梯度流
- 深度监督允许模型复杂性调整,以平衡速度和性能优化
周建筑
[## 生物医学图像分割:UNet++
通过一系列嵌套、密集的跳过路径提高分段准确性
towardsdatascience.com](/biomedical-image-segmentation-unet-991d075a3a4b)
注意 U-Net
注意机制可以学习挑选出网络中特征的某些部分。Oktay 等人提出了一种注意力 U-Net ,旨在自动学习关注不同形状和大小的目标结构;因此这篇论文的名字叫“学习在哪里寻找胰腺”。它能够捕捉医学图像中的精细结构,因此适合新冠肺炎应用。
因为受感染的区域可能很小,具有各种形状和纹理,所以定位这些区域是一项具有挑战性的任务。整合到 U-Net 中的注意门提高了模型对前景像素的灵敏度和准确性,而不需要大量的计算开销。注意门可以逐渐抑制不相关背景区域的特征反应。
关注奥克泰的 U-Net 架构
[## 生物医学图像分割:注意力 U 网
通过在标准 U-Net 上附加注意门来提高模型的灵敏度和准确性
towardsdatascience.com](/biomedical-image-segmentation-attention-u-net-29b6f0827405)
图像分割在新冠肺炎中的应用
许多论文认为图像分割是分析医学图像的必要步骤。以下是冯等人收集的论文列表,这些论文将图像分割应用于研究。
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
愤怒退出癌症研究
原文:https://towardsdatascience.com/rage-quitting-cancer-research-5e79cb04801?source=collection_archive---------16-----------------------
为什么我从神经科学家变成了数据科学家
一张我为实验室拍摄的奇怪的宣传照片。剧透管子里什么都没有!
在我之前的故事中,我描述了如何从研究科学家转变为数据科学家,在这篇文章中,我将详细阐述为什么。我在脑瘤研究方面有着很有前途的职业生涯,并且已经研究了八年,那么我为什么要放弃这一切呢?
我完成了健康科学学位,但并不确定自己下一步想做什么。有一个新的放射摄影研究生学位,不幸的是它非常受欢迎,我没有进去。这让我不得不为新的一年已经开始的备份计划而忙碌。我联系了我最喜欢的本科讲师,看我是否有可能获得荣誉学位,尽管这个项目已经开始了。
通常这是不可能的。幸运的是,该系有一个项目,他们真的很想找人来做,但学生对这个项目不感兴趣。所以他们破例让我开始攻读解剖学和病理学的荣誉学位。
通常你的导师是你项目领域的专家,我作为第一个脑瘤研究者为实验室开辟了新天地。
在我获得荣誉的那一年结束时,我才刚刚开始对我模拟疾病的模型可能奏效抱有一线希望。
我不想让这个项目打败我,所以我继续用这个模型读博士。这听起来可能是一个奇怪的原因,要承诺至少 3 年的学习和研究,但我认为这可能比你想象的更常见。
就好像我是偶然成为神经科学家的。
2012 年,我完成了神经科学博士学位,下一步是去海外做博士后。我在 UCSF 获得了我的第一个博士后,那里是癌症研究的世界领导者。
- ✅健康科学学位
- ✅荣誉学位
- ✅博士
- 作为博士后的✅
那我为什么不开心呢?不知何故,我最终成为了一名科学家,却没有真正思考过我的余生想做什么。
我开始怀疑自己是否适合从事研究工作,我的老板是个恶霸。数据科学似乎可以很好地解决我的问题。这个故事是关于我从研究科学家到数据科学家的旅程。
我的旅程跨越了
- 在我的家乡南澳大利亚阿德莱德完成我的博士学位。
- 为了我的第一份工作——博士后,我搬到了美国旧金山。
- 回到阿德莱德接受再培训并申请数据科学工作。
- 经过大量的艰苦工作和坚持,我回到旧金山,在一家医疗创业公司工作。
对神经科学不再抱有幻想
在我博士后期间,我是 UCSF 海伦·迪勒癌症中心的一名脑肿瘤研究员。一些世界上最好、最先进的癌症研究正在那里进行,这应该是我梦寐以求的工作。但是我不想再待在那里了。我意识到我需要改变。有许多促成因素帮助我做出了那个决定。
我不擅长政治
政治在某种程度上存在于任何工作场所,但我很惊讶在科学中有这么多。我想,不知何故,学者们不会愿意为办公室里的讨价还价而自寻烦恼,伙计,我错了。研究科学家和任何其他行业的人一样充满竞争和不安全感,或许更甚。整天和那些在他们的特定研究领域是世界顶尖专家的人在一起,有助于培养冒名顶替综合症。
没有足够的工作或资金来分配,因此科学家们不得不与他们的同事竞争出版物的资助和著作权。它没有培养一个合作的环境。与其说是合作,不如说是割喉。“出版或灭亡”是学术口号。
你需要无限的耐心
在研究科学的世界里,尤其是在学术界,事情发生得很慢。这项工作是重复性的,在我所在的临床前研究领域,人们可能从我们所做的工作中受益的最快时间可能是 10 年左右。
这是一张我在实验室里的照片,一整天都在转动一个轮子(还在微笑)
科学不是精英管理
不幸的是,最好的科学并不总是得到最多的金钱或认可。对我来说,这听起来像是酸葡萄心理,可能有这样的因素,但我已经看到许多糟糕的科学得到了职业发展和资金的回报。我发现这很难处理,因为这似乎太不公平了。但我想生活往往是不公平的。
我是一个糟糕的说谎者,我没有能力让我的结果看起来比实际上更令人兴奋或更重要。要获得资助,你必须每次都让你的成果看起来具有突破性,即使它们并不具有突破性。这是你在研究中取得成功所需要玩的游戏。
我工作过度,报酬过低
我有没有提到我全职工作在赔钱?尽管我和男朋友合租了一套一居室的公寓,但我的工资还不够在旧金山生活下去。
我的老板是个恶霸
我与脑瘤研究分手的最后一根稻草是,我的一个老板是个真正的恶霸,他对我和我所有的同事进行微观管理。
我的一周通常是这样度过的…
周一我是实验室的明星。星期二,我会因为一些明显的缺点而被钉在十字架上。然后到了周三,就像前两天什么都没发生过一样。这是一次情感的大起大落,我总是紧张不安,想看看这一天会发生什么。这种对老板不可预测的反应的焦虑确实产生了影响。
当我的老板诉诸情感勒索时,我知道这不仅仅是我的想象。我告诉她,我正在考虑离开实验室,因为我再也无法应对压力了。她的回答是:
想想你的父母为了支持你读博士而牺牲的一切,你真的应该抛弃这一切吗?
事实上,我的父母已经鼓励我戒烟很长时间了,因为他们可以看出我很痛苦。
离开实验室后,我的许多实验室伙伴谈到了他们经历的创伤后压力的症状。不幸的是,通过与大学工会的交谈,我发现我们的实验室并不是唯一一个在暴君手下工作的实验室。
我辞职后
想谈谈压力吗?第二天我不得不离开这个国家
我持 J1 签证在美国工作,这是一种文化交流签证。由于我没有完成这个项目,当我辞职的时候,我不得不在第二天离开这个国家。谢天谢地,墨西哥只是一个快速的跳跃,跳过和跨越边境。我可以持旅游签证再次进入美国,在回澳大利亚之前收拾好我的公寓。
签证烂透了!
再训练
离开学术界后,我决定探索成为一名数据科学家。在科技行业工作的所有福利听起来都很吸引人。我知道我需要在多个领域大幅提高自己的技能。我所做的学术研究需要我生成自己的数据集,我只处理过非常小的数据集。
我在科学方法和实验设计方面有很好的基础,但我一生中从未编码过一天,只有统计分析的基本技能。
当我开始的时候,我不知道我不知道什么。因此,为了获得我需要的专业知识,我请了 6 个月的假来学习编码,并提高我对统计学和机器学习的理解。
为此,我参加了许多在线编码、统计和数据科学课程。我参加的课程和使用的工具的细节在我之前的一篇文章中有详细介绍。
得到我的第一份数据科学工作
寻找工作申请
我寻找工作机会的方法非常有针对性。我的男朋友和我想搬回旧金山,这样就缩小了我要找的公司的范围。湾区科技公司如此集中,所以我仍然有很多选择。
我尝试了所有正常的求职网站,但要筛选的内容太多了,所以我使用了更有针对性的方法。健康或生物公司是我一直在寻找的。
Rock Health 是一家投资数字健康公司的风险基金。通过查看 Rock Health 支持的健康创业公司列表,我找到了我的最佳匹配。我在他们的招聘板上搜寻适合我技能水平的职位,这些职位的使命与我产生了共鸣。
对于每家公司,我都做了功课,写了一封量身定制的求职信,告诉他们我有兴趣在那里工作的具体原因。我还试图突出我的技能,让我从其他求职者中脱颖而出。
从外国采访
我在 Skype 和 Google Hangouts 上做了所有的采访。被远程采访是一种奇怪而又伤脑筋的经历。
有一次采访让我记忆犹新。采访我的首席技术官的网络摄像头出了问题,所以当我和他谈话时,我只能看到他的 Skype 个人资料图片。这本来是完全正常的,除了他的个人资料照片是科米蛙。他开了个时区玩笑,说我从未来和他说话。那一刻,我知道我想在那里工作,我会融入那里。
https://gph.is/2d1ve5N
技术面试
远程面试的一个很大的好处是,我不必忍受任何白板编码面试。面试中在众人面前编程是我最讨厌的事情之一。不仅因为这让我不舒服,还因为这不是你在工作中编码的方式。然而,我承认会议中的白板架构和编写实际代码是有区别的。
我接受了编程技能测试。一些公司让我在我们交谈的时候提出 SQL 查询,一些公司让我在谷歌文档中进行结对编程,还有一些公司让我做带回家的作业。到目前为止,我更喜欢带回家的作业。
尽管它们占用了我更多的时间,但在我看来,它们最接近地复制了你在一家公司的实际工作方式。带回家的作业一石二鸟,同时测试编程和统计分析技能。我发现从负责批改我带回家作业的面试官那里得到反馈非常有帮助。
面试官通常不会在面试后提供反馈,但我会主动询问自己哪些地方可以做得更好,以便改进。即使当我很确定为什么我没有成功的时候,被证实了也是很棒的。当我在面试结束时跟进或询问时,我接触的所有人都非常坦诚,并向我提供了大量有价值的反馈。
我解决问题的能力被几家公司测试过。一些比另一些更有效。
我最喜欢的问题解决问题是数据科学团队最近处理的一个真实场景。我和我的面试官讨论了几种方法。我选定的方法与团队最终使用的方法相同。我发现这非常鼓舞人心,这是我第一次真正地认为‘我能做到!’。
相比之下,有几家公司用脑筋急转弯来测试我解决问题的能力。我真的不喜欢这种做法,它使人为难,而且与工作无关。我不明白为什么面试官会浪费时间问与工作无关的问题。有些人认为脑筋急转弯让你看到人们如何解决问题,这些人错了。
我的面试方法
面试时,我非常坦率地向招聘小组说明了我的局限性。我知道我资历极浅,需要指导和继续在职培训。这不是我试图隐瞒的事情,而是我对采访者说的。
我告诉他们,我最近才学会编码和分析大型数据集。然而,我强调我的学习能力和快速学习的能力。我告诉他们,如果他们要找的人是一位经验丰富的数据科学家,他已经知道所有的技能,我可能不是合适的人选。如果他们在寻找能够胜任这个职位的人,那么我就是最佳人选😉
为什么我更喜欢数据科学而不是脑瘤研究
我很高兴我完成了从研究科学家到数据科学家的转变。我从一个职位稀缺、工作时间长的领域,变成了一个吃香、待遇好得多的领域。此外,我挣的钱要多得多。
然而,当我成为一名数据科学家时,这些并不是让我更快乐的主要事情。
我有更好的工作生活平衡。我获得第一份数据科学工作的那家初创公司很关心员工。我们有无限假期和病假政策。相比之下,当我还是一名研究人员时,为了让实验时间框架发挥作用,我们整个周末都工作或者工作到晚上 10 点并不罕见。
作为一名数据科学家,我觉得我可以比一名脑瘤研究人员对世界产生更大、更快的积极影响。尽管我的研究是在寻找治疗和预防脑瘤的方法,但我觉得我对人们的影响受到了将新疗法转化为人类使用的缓慢速度的限制。理所当然,我不希望人们只是随意尝试新药。然而,让我感到沮丧的是,我的工作的影响被延迟了。
当我成为一名数据科学家时,我所开发的产品可能会在几周内送到用户手中。由于公司的使命反映了我的价值观,我觉得我可以给人们的生活带来真正积极的变化。我们还可以测试我们工作的影响,并从用户那里获得反馈。
作为一家小型医疗保健初创公司,我喜欢我们都朝着同一个目标努力的感觉。团队成员总是很慷慨,因为互相帮助而给予彼此信任。这与实验室内经常发生的论文作者竞争形成了对比。
这听起来可能很疯狂,但现在我是一名数据科学家,我不再做不小心让自己得了癌症的噩梦。我在实验室中使用的人类癌细胞和有害化学物质总是会引起背景水平的焦虑,这种焦虑经常会在非常奇怪的噩梦中出现。现在我在电脑前工作,我睡得更香了。
脑瘤研究和数据科学之间的相似性
我已经谈了很多关于我的新职业和旧职业之间的区别,但是研究科学和数据科学之间也有很多相似之处。顾名思义,科学是共同因素。
解决问题是两者的核心,也是我一直感到非常满足的事情。好的实验设计对于显而易见的研究来说也是极其重要的,但它对于从数据中获取最大价值也是不可或缺的。
统计分析在数据科学工作中更加突出,但作为研究科学的一部分也非常重要。在我看来,在基于实验室的研究中,适当的统计分析的重要性经常被忽视。统计方法经常被选择,因为它们是“这个领域的其他人是怎么做的”,而不是因为它们是最适合实验的方法。我认为更广泛的统计学培训应该作为研究学位的一部分来实施。
此外,这两个领域之间还有许多其他可转换的技能,我将在以后的帖子中进一步讨论。
谢谢
我非常感谢 Amino 的招聘委员会,他们给了我一个非常初级的数据科学家的机会,让我在工作中学习。我对我的新事业感到非常高兴,并感谢第一次机会。
除了数据,我的另一个爱好是绘画。你可以在 www.katemarielewis.com 找到我的野生动物艺术
如果您想了解更多关于我如何成为数据科学家的信息,请访问:
[## 我如何在 6 个月内从零编码技能成为数据科学家
我用来自学数据科学的 4 个工具没有花一美元
towardsdatascience.com](/how-i-went-from-zero-coding-skills-to-data-scientist-in-6-months-c2207b65f2f3) [## 让我获得第一份数据科学工作的面试策略
我是如何展示自己得到这份工作的
towardsdatascience.com](/interview-strategy-that-landed-me-my-first-data-science-job-bdd5e77bfb49)
降雨时间序列分析和预测
原文:https://towardsdatascience.com/rainfall-time-series-analysis-and-forecasting-87a29316494e?source=collection_archive---------10-----------------------
SHAH Shah 在 Unsplash 上拍摄的照片
印度尼西亚万丹省 2019-2020 年使用“R”语言的降雨量预测
预测是对未来事件的计算或估计,尤其是对金融趋势或未来天气的预测。直到今年,在面对任何事件之前,预测作为制定任何行动或政策的基础非常有帮助。例如,在一些国家一年只有两个季节(旱季和雨季)的热带地区,许多国家,尤其是非常依赖农业商品的国家,需要预测降雨,以决定开始种植产品和最大化收获的最佳时间。另一个例子是,预测可以被公司用来预测原材料价格的变动,并安排最佳策略以从中获取最大利润。
在本文中,我们将尝试对印度尼西亚万丹省(依赖农业商品的热带国家之一)的降雨量进行预测,我们有 2006-2018 年的历史降雨量数据,并将尝试使用“R”语言进行预测。
在此过程中将使用一个简单的工作流程:
图一。流程工作流
导入和选择数据
该数据集包含印度尼西亚万丹省从 2005 年 1 月到 2018 年 12 月的降雨历史数据。对于这一预测,我将放弃 2005 年,从 2006-2018 年开始,作为我们预测的基础。
#Import Necessary Library
library(lubridate)
library(ggplot2)
library(tidyverse)
library(dplyr)
library(astsa)
library(forecast)
library(readxl)
library(urca)
library(ggfortify)
library(tsutils)
#Import Data
hujan <- read_excel("../input/hujan-update/Hujan_Update.xlsx",
sheet = 'Sheet1')
hujan <- hujan %>% gather(key = "Tahun", value = "Curah_Hujan",
-Bulan)*#Converting To Time Series* hujan_ts <- ts(data = hujan[,3], frequency = 12, start = c(2005,1))
*#Selecting Data*
hujan_ts <- window(hujan_ts, start=c(2006,1))hujan_ts
运行完这些代码后,我们将获得以下时间序列数据:
图二。时间序列降雨数据
探索性时间序列数据分析
对任何时间序列数据进行探索性数据分析的第一步是可视化相对于时间的值。我们将使用以下代码将我们的降雨量数据可视化为时间序列图(折线图、值与时间的关系):
#Plot Time Series Dataautoplot(hujan_ts) + ylab("Rainfall (mm2)") + xlab("Datetime") +
scale_x_date(date_labels = '%b - %Y', breaks = '1 year', minor_breaks = '2 month') +
theme_bw() + ggtitle("Banten Rainfall 2006 - 2018")
图三。万丹降雨时间序列图
时间序列图显示降雨具有季节性模式,但没有出现任何趋势;降雨量将在年末达到最高值,直到 1 月(雨季),从 3 月到 8 月(旱季)开始减少。在 2006 年至 2018 年期间,这种模式每年都会重复。
我们将根据趋势、季节性和剩余部分将时间序列数据分解成更详细的内容。利用这一分解结果,我们希望更精确地了解 2006-2018 年期间的降雨行为。
将使用 stl() 函数进行分解,并将时间序列自动分成三个部分(趋势、季节性、余数)。
#Decomposition using stl()
decomp <- stl(hujan_ts[,1], s.window = 'periodic')#Plot decomposition
autoplot(decomp) + theme_bw() + scale_x_date(date_labels = '%b - %Y', breaks = '1 year', minor_breaks = '2 month') +
ggtitle("Remainder")
图 4。时间序列分解
趋势周期和季节图显示出现了季节波动,没有特定的趋势和相当随机的剩余/残差。
有一种计算方法可以衡量趋势和季节性强度:
Ft :趋势强度
图五。趋势强度公式
Fs :季节性强度
图六。季节性强度公式
趋势和季节性的强度在 0 和 1 之间,而 "1" 意味着有很强的趋势和季节性发生。
Tt <- trendcycle(decomp)
St <- seasonal(decomp)
Rt <- remainder(decomp)#Trend Strength Calculation
Ft <- round(max(0,1 - (var(Rt)/var(Tt + Rt))),1)#Seasonal Strength Calculation
Fs <- round(max(0,1 - (var(Rt)/var(St + Rt))),1)
data.frame('Trend Strength' = Ft , 'Seasonal Strength' = Fs)
图七。趋势/季节强度计算结果
通过使用测量趋势和季节强度的公式,我们证明了我们的数据具有季节性模式(季节强度:0.6),而没有出现趋势(趋势强度:0.2)。
季节性分析
我们知道我们的数据有季节性模式。因此,探索更多关于我们的降雨数据的季节性;季节图、季节-子系列图和季节箱线图将对我们的数据提供更深刻的解释。
#Seasonal Plot
seasonplot(hujan_ts, year.labels = TRUE, col = 1:13,
main = "Seasonal Plot", ylab= "Rainfall (mm2)")
图八。降雨时间序列季节图
季节图确实显示了每年发生的季节模式。尽管如此,由于在此期间几年的差异,我们无法仅使用此图来查看模式。进一步的探索将使用季节性箱线图和子系列图,从我们的数据中获得更深入的分析和见解。
#Seasonal Sub-Series Plot
seasplot(hujan_ts, outplot = 3, trend = FALSE,
main = "Seasonal Subseries Plot", ylab= "Rainfall (mm2)")#Seasonal Boxplot
seasplot(hujan_ts, outplot = 2, trend = FALSE,
main = "Seasonal Box Plot", ylab= "Rainfall (mm2)")
图九。季节性子系列图
图 10。季节性箱线图
使用季节性箱线图和子系列图,我们可以更清楚地看到数据模式。水平线表示按月分组的降雨量平均值,通过使用此信息,我们了解到降雨量将从 4 月开始减少,并在 8 月和 9 月达到最低点。降雨量将在 9 月后再次开始攀升,并在 1 月达到顶峰。
据此,我们可以将旱季安排在 4 月至 9 月,雨季安排在 10 月至 3 月。这对像印度尼西亚这样依赖农产品的国家来说是一个有益的启示。旱季和雨季预测可用于确定开始种植农业商品并使其产量最大化的正确时间。
此外,这些信息可以帮助政府制定任何政策,作为预防雨季暴雨引发洪水或旱季干旱的方法。
2019-2020 年降雨量预测
预测的第一步是选择正确的模型。为此,我们需要将时间序列数据集分为训练集和测试集。训练集将用于训练几个模型,而且,这个模型应该在测试集上进行测试。
分体列车/测试装置
训练集:我们将使用截至 2017 年 12 月的所有数据作为我们的训练集
测试集: 2018 年期间(1 月-12 月)将作为我们的测试集
*#Create Train Set*
hujan_train <- window(hujan_ts, end = c(2017,12))*#Create Test Set*
hujan_test <- window(hujan_ts, start = c(2018,1))
静止测试
在开始建立 ARIMA 模型之前,应检查列车组数据的平稳性。可以使用 URCA 包装的 科维亚特科夫斯基-菲利普-施密特-申恩试验(KPSS) 和 迪基-富勒试验(D-F 试验) 进行静态试验。
*#Kwiatkowski–Phillips–Schmidt–Shin Test*
summary(ur.kpss(hujan_train)) *#Dickey-Fuller Test* summary(ur.df(hujan_train)) #######################
# KPSS Unit Root Test #
#######################
Test is of type: mu with 4 lags.
Value of test-statistic is: 0.0531
Critical value for a significance level of:
10pct 5pct 2.5pct 1pct
critical values 0.347 0.463 0.574 0.739###############################################
# Augmented Dickey-Fuller Test Unit Root Test #
###############################################
Test regression none
Call:
lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)
Residuals:
Min 1Q Median 3Q Max
-176.15 -43.66 3.80 68.21 355.75
Coefficients:
Estimate Std. Error t value Pr(>|t|)
z.lag.1 -0.15081 0.05230 -2.883 0.004555 **
z.diff.lag -0.28241 0.08111 -3.482 0.000664 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 96.77 on 140 degrees of freedom
Multiple R-squared: 0.1755, Adjusted R-squared: 0.1637
F-statistic: 14.9 on 2 and 140 DF, p-value: 1.36e-06
Value of test-statistic is: -2.8835
Critical values for test statistics:
1pct 5pct 10pct
tau1 -2.58 -1.95 -1.62
使用 95%作为置信水平,两个测试的零假设(ho)定义为:
- KPSS 检验:数据是平稳的
- D-F 检验:数据是非平稳的
因此,对于 KPSS 测试,我们希望 p 值> 0.5,我们可以接受零假设,对于 D-F 测试,我们希望 p 值< 0.05 to reject its null hypothesis. Based on the test which been done before, 我们可以很舒服地说,我们的训练数据是平稳的。
型号分配
将使用 ARIMA 和 ETS 模型进行预测,这些模型之间的比较也将使用测试集的一些参数进行评估。
ARIMA 模式
建立 ARIMA 模型的第一步是创建平稳时间序列数据的自相关图。有时为了得到稳定的数据,我们需要做差分;对于我们的例子,我们已经有了一个固定的集合。因此,我们模型上的差异数(D,D)可以设置为零。
我们的数据集具有季节性,因此我们需要构建 ARIMA (p,D,q)(P,D,Q)m ,以获得(P,P,Q,Q)我们将看到自相关图(ACF/PACF)并从图中导出这些参数。
acf2(hujan_train)
图 11。ACF/PACF 绘图训练装置
ACF 图用于获得 MA 参数(Q,Q),在滞后 2 处有显著的尖峰,正弦曲线指示年度季节性(m = 12)。PACF 图用于获得 AR 参数(P,P),AR 参数在滞后 1 时有显著的尖峰。
这个 ACF/PACF 图表明,合适的模型可能是 ARIMA(1,0,2)(1,0,2) 。为了确定这个模型,我们将根据我们的建议设置其他模型,用 1 修改 (AR) 和 (MA) 组件。
- 模型-1 : ARIMA(1,0,2)(1,0,2)
- 模型二: ARIMA(2,0,2)(2,0,2)
- 模型 3 : ARIMA(1,0,1)(1,0,1)
- 模型 4 : ARIMA(2,0,1)(2,0,1)
- 模型-5 : ARIMA(0,0,2)(0,0,2)
- 模型 6 : auto.arima()
我们还将设置 auto.arima() 作为我们的模型的另一个比较,并期望找到更适合我们的时间序列。
fit1 <- Arima(hujan_train, order = c(1,0,2), seasonal = c(1,0,2))
fit2 <- Arima(hujan_train, order = c(2,0,2), seasonal = c(2,0,2))
fit3 <- Arima(hujan_train, order = c(1,0,1), seasonal = c(1,0,1))
fit4 <- Arima(hujan_train, order = c(2,0,1), seasonal = c(2,0,1))
fit5 <- Arima(hujan_train, order = c(0,0,2), seasonal = c(0,0,2))
fit6 <- auto.arima(hujan_train, stepwise = FALSE,
approximation = FALSE)
为了在所有 ARIMA 模型中选择最适合我们数据的模型,我们将比较这些模型的 AICc 值。具有最小 AICc 的模型通常是预测的最佳模型。
data.frame('Model-1' = fit1$aicc, 'Model-2' = fit2$aicc,
'Model-3' = fit3$aicc,
'Model-4' = fit4$aicc,
'Model-5' = fit5$aicc,'Auto.Arima'= fit6$aicc,
row.names = "AICc Value")
图 12。ARIMA 模型的 AICc 值
模型 1 的 AICc 值在其他模型中是最低的,这就是为什么我们选择这个模型作为我们预测的 ARIMA 模型。但是,我们还需要对该模型进行残差检查,以确保该模型适用于我们的时间序列预测。
checkresiduals(fit1) Ljung-Box test
data: Residuals from ARIMA(1,0,2)(1,0,2)[12] with non-zero mean
Q* = 10.187, df = 17, p-value = 0.8956
Model df: 7\. Total lags used: 24
图 13。ARIMA 模型的残差检验
基于模型残差的 Ljung-Box 检验和 ACF 图,我们可以得出结论,该模型适用于预测,因为其残差表现出白噪声行为,并且彼此不相关。
ETS 模型
我们将构建 ETS 模型,并将其与我们选择的 ARIMA 模型进行比较,以查看哪个模型更适合我们的测试集。
*#ETS Model*
fit_ets <- ets(hujan_train, damped =TRUE)
与 ARIMA 模型相似,我们也需要检查其残差行为,以确保该模型能够很好地进行预测。
checkresiduals(fit_ets)Ljung-Box test
data: Residuals from ETS(A,Ad,A)
Q* = 40.433, df = 7, p-value = 1.04e-06
Model df: 17\. Total lags used: 24
图 14。ETS 模型的残差检验
在残差检查之后,ACF 图显示 ETS 模型残差在几个滞后上相互之间的相关性很小,但是大多数残差仍然在限制范围内,我们将继续使用该模型作为与我们选择的 ARIMA 模型的比较。
测试集上的 ARIMA vs ETS 模型
可以使用测试集来检查我们的时间序列数据的更好模型。我们将使用 ARIMA 和 ETS 模型进行预测,并根据测试集(2018 年 1 月至 12 月)查看它们的准确性。
第一步,我们需要在 ARIMA 模型、ETS 模型和我们 2018 年的实际数据之间绘制可视化。但是由于 ggfortify 包不能很好地与其他包相适应,我们应该稍微修改一下代码来显示漂亮的可视化效果。
注意:如果没有加载 ggfortify 包,可以直接使用:autoplot(实际数据)+ autolayer(forecast_data),来做可视化。
#Modifying Data For ggplotmodel_1 <- forecast(fit1, h=12)
model_ets <- forecast(fit_ets, h=12)
model_1 <- as.data.frame(model_1$mean)
model_ets <- as.data.frame(model_ets$mean)
colnames(model_1) <- "Curah_Hujan"
colnames(model_ets) <- "Curah_Hujan"
hujan_train_df <- as.data.frame(hujan_train)
model_1_plot <- rbind(hujan_train_df,model_1)
model_ets_plot <- rbind(hujan_train_df, model_ets)
model_1_plot <- model_1_plot %>%
mutate('Date' = seq(from = as.Date("2006-01-01", '%Y-%m-%d'), to = as.Date("2018-12-31",'%Y-%m-%d'),by = 'month'))
model_ets_plot <- model_ets_plot %>%
mutate('Date' = seq(from = as.Date("2006-01-01", '%Y-%m-%d'), to = as.Date("2018-12-31",'%Y-%m-%d'),by = 'month'))
hujan_ts_df <- as.data.frame(hujan_ts)
hujan_ts_df <- hujan_ts_df %>%
mutate('Date' = seq(from = as.Date("2006-01-01", '%Y-%m-%d'), to = as.Date("2018-12-31",'%Y-%m-%d'),by = 'month'))
hujan_train_df <- hujan_train_df %>%
mutate('Date' = seq(from = as.Date("2006-01-01", '%Y-%m-%d'), to = as.Date("2017-12-31",'%Y-%m-%d'),by = 'month'))
colors <- c("ARIMA Model Forecast 2018" = "blue", "ETS Model Forecast 2018" = "red", "Actual Data" = "black")
#Creating Plotggplot() + geom_line(model_1_plot,
mapping = aes(x=Date, y=Curah_Hujan,
color= "ARIMA Model Forecast 2018"),lty = 2) +
geom_line(model_ets_plot,
mapping = aes(x=Date, y=Curah_Hujan,
color= "ETS Model Forecast 2018"),lty= 2) +
geom_line(hujan_ts_df,mapping = aes(x=Date, y=Curah_Hujan,
color= "Actual Data"), lty = 1, show.legend = TRUE) +
ylab("Rainfall (mm2)") + xlab("Datetime") +
scale_x_date(date_labels = '%b - %Y', breaks = '1 year',
minor_breaks = '2 month') +
theme_bw() + ggtitle("Banten Rainfall 2006 - 2018") +
scale_color_manual(values=colors)
图 15。实际数据与 ARIMA 和 ETS 预测
尽管 ARIMA 和 ETS 的模型并不完全符合实际数据的相同值,但可以肯定的是,他们都策划了一个非常相似的运动来反对它。
在 numbers 中,我们可以用实际数据计算这些模型之间的准确性,并决定哪一个模型最符合我们的数据:
#ARIMA Model Accuracy
accuracy(forecast(fit1, h=12), hujan_test)
图 16。ARIMA 模型精度
#ETS Model Accuracy
accuracy(forecast(fit_ets, h=12), hujan_test)
图 17。ETS 模型准确性
从准确性来看,ETS 模型在训练集和测试集上都优于 ARIMA 模型。
2019-2020 年降雨量预测
使用与使用我们的训练集创建的模型相同的参数,我们将预测 2019-2020 年的降雨量预测(h=24)。
预测和绘图:
*#Create Model*
ARIMA_Model <- Arima(hujan_ts, order = c(1,0,2),
seasonal = c(1,0,2))
ETS_Model <- ets(hujan_ts, damped = TRUE, model = "AAA")
*#ARIMA Model Forecast*
autoplot(forecast(ARIMA_Model, h=24)) + theme_bw() +
ylab("Rainfall (mm2)") + xlab("Datetime") +
scale_x_date(date_labels = '%b - %Y',
breaks = '1 year', minor_breaks = '2 month') +
theme_bw() + ggtitle("Banten Rainfall Forecast 2019-2020
ARIMA Model")
*#ETS Model Forecast*
autoplot(forecast(ETS_Model, h=24)) + theme_bw() +
ylab("Rainfall (mm2)") + xlab("Datetime") +
scale_x_date(date_labels = '%b - %Y', breaks = '1 year',
minor_breaks = '2 month') +
theme_bw() + ggtitle("Banten Rainfall Forecast 2019-2020
ETS Model")
图 18。ARIMA 模型预测 2019–2020
图 19。ETS 模型预测 2019–2020 年
使用这两个模型进行了预测,基于 2019 年和 2020 年 8 月降雨量最低值的绘图,它们共享相似的运动。
我们的预测对于想知道哪个月开始种植最好的农民是有用的,对于需要制定雨季防洪和旱季抗旱政策的政府也是有用的。最重要的是,这种预测仅基于历史趋势,更准确的预测必须结合使用气象数据和气候专家的一些专业知识。
[1] banten.bps.go.id 。于May,17th 2020
访问
[2]Hyndman,R.J .,& Athanasopoulos,G. (2018) 预测:原理与实践,第二版,OTexts:澳洲墨尔本。OTexts.com/fpp2.Accessed 在May,17th 2020
上。
兰博:排名度量黑盒优化
原文:https://towardsdatascience.com/rambo-ranking-metric-blackbox-optimization-36811a5f52dd?source=collection_archive---------36-----------------------
[3]
我们的论文在 2020 年 CVPR 大会上做了一次关于应用黑盒微分理论(代号#blackboxbackprop)来优化基于排名的指标的口头报告。事实证明,只要做一些简单的改变,一切都是可能的…
在我们的最新论文【1】中,我们通过直接优化基于排名的指标来处理深度神经网络的训练。我们的方法基于[ 2 ]中介绍的黑盒反投影理论。在 blackbox-backprop 论文(最新更新见 Twitter 上的 #blackboxbackprop 和附带的 blogpost )中,我们展示了如何通过神经网络中的组合解算器计算“有用的”梯度,而不损害解算器本身的最优性。该理论使我们能够利用组合 解算器作为复杂模型中的即插即用模块,我们可以用标准反向传播算法对其进行训练。
为了寻求该理论的实际应用,我们求助于计算机视觉。具体来说,我们表明,将 blackbox-backprop 应用于计算机视觉基准测试,以优化检索和检测任务的召回率和平均精度,可以持续提高底层架构的性能。顺便说一下,这是 ML 中的一个常见主题,总是希望为您真正关心的东西进行优化。如果 recall@K 是正确的性能度量,那么让端到端架构优化它是有意义的,而不是某种近似。召回率(更具体地说,召回率@K)和平均精度都是基于输入排序的度量,这实质上需要对它们的分数进行排序操作。在这方面,多种因素构成了挑战。首先,使用这些度量作为损失函数会导致不可分解的损失(即,我们不能基于输入的子集可靠地估计损失,但是我们需要整个输入集)。此外,用于计算指标的排名操作是不可微的。
尽管已经提出了许多竞争的方法,但是由于不同的原因,它们没有被从业者接受。它们在计算上过于昂贵,或者缺乏易于使用的实际实现。利用 blackbox-backprop 理论,我们将排序操作直接应用于输出的分数,这导致了低计算复杂度 O(n log n)(使用 torch.argsort 进行一般排序的复杂度)。我们需要回答的问题如下:
- 如何将排名问题投射到黑盒差异化框架中?
- 如何处理损失的不可分解性?
- 如何防止基于等级的损失崩溃?
将排名纳入黑盒区分框架
为了将排名转换到[2]中提出的框架中,我们需要在点积上进行 argmin 运算。我们首先定义分数的向量, y 。 y , rk(y) 的排序是在所有可能排列的集合上对向量 y 和排列 π,之间的点积进行 argmin 运算的结果:
前一个命题的证明很简单,并且基于众所周知的置换不等式,该不等式表示给定一个递减序列(向量 y ),对于任意整数 n:
直观地说,这意味着最大的分数被赋予了最小的权重,这发生在排列是排序排列的情况下。通过这个简单的改变,我们能够将 blackbox 框架应用于排名问题,这意味着我们可以简单地使用快速排序算法的有效实现(例如 PyTorch 中的 torch.argsort)来计算排名,并基于 blackbox-backprop 理论通过它进行区分。下图显示了应用黑盒反投影理论所产生的优化前景的示例:
得分保证金,以防止损失崩溃
基于等级的损失很难处理平局。为了说明它们的不稳定性,请考虑我们在整个数据集上得分相同的情况。我们可以在这种平局的小邻域中获得所有可能的排名,因为分数的最小变化完全改变了排名。这意味着应用基于等级的损失是非常不稳定的。我们通过引入裕量α 来缓解该问题,该裕量α【】在负标记分数上引起正偏移,在正标记分数上引起负偏移:
为更好的评估评分记忆
理想情况下,我们将有一个数据集范围的损失进行优化,因为基于排名的损失的不可分解性问题。因为这在计算上是难以处理的(例如,因为它受到 GPU 内存的限制),所以我们希望使用迷你批处理来训练我们的模型。我们通过用一定数量的先前批次的分数扩展当前批次的分数来考虑这一点,这减少了损失估计的偏差。
该算法
采用上述技术产生了一种方法,我们称之为排名度量黑盒优化(RaMBO) 。同样,额外的计算开销仅由排序操作 O(n log n) 的复杂性引入,当高效实现时,其速度极快。这使我们领先于大多数方法。该算法总结如下:
我们评估了我们的方法在对象检测(Pascal VOC)和几个图像检索基准(Cu B- 200–2011,店内服装,斯坦福在线产品)上的性能。在每个实验中,我们采用性能良好的架构,并用 RaMBO 对其进行修改。在这些基准测试中,该方法达到或超过了最先进的结果。
然而,我们应该承认,度量学习基线是一团乱麻,这是不同方向的大量快速研究的结果(改进网络架构、更好的目标函数等等)。这导致不可复制的结果、错误的结论和不公平的比较,对这些困难的分析可以在这里找到。
斯坦福产品检索数据集。
相关推文
参考
[1]rol nek,Michal 等人使用黑盒区分优化基于等级的指标,CVPR,2020 年
[2] Vlastelica,Marin 等人黑盒组合
解算器的微分,ICLR 2020
[3]图片取自 Pixabay
感谢
这是来自德国图宾根马普智能系统研究所的自主学习小组、图宾根大学和意大利费伦泽大学的联合研究成果。
随机森林和决策树
原文:https://towardsdatascience.com/random-forest-and-decision-trees-d8f7cd06803b?source=collection_archive---------44-----------------------
你已经听说过用于预测疾病、识别图形和面孔,甚至我们的行为的算法。但是你知道这些算法和它们是如何工作的吗?
@ugodly 在 Unsplash 上的照片
广泛用于解决数据科学问题的最流行(也是最强大)的算法之一是一种叫做随机森林的算法。不用说幕后有很多数学和计算机编程,但是让我们把它变得简单,这样即使你以前从未听说过它,你也能理解这个主题。
随机森林源自另一种被称为决策树的算法的思想,它基本上使用类似于树及其分支的结构来做出导致最终预测的决策。
但是这实际上是如何工作的呢?你需要知道的第一件事是没有魔法。训练算法时,必须有可用的历史数据。算法要学习的就是这些数据。假设我们想要创建一个模型,该模型能够识别给定了一些特定特征的对象,例如形状、颜色、高度、等等。
为了简化,让我们假设这些对象具体是三种不同的水果:香蕉、橙子和柠檬。决策树算法如何面对这个任务?
为了理解这个过程,让我们想象一下,我们的任务是教一个两岁的孩子区分三种相同的水果。第一个好方法是告诉孩子注意水果的形状:橙子和柠檬是圆形的,而香蕉是细长形的,这与其他两种水果明显不同。
然而,乍看之下,橙子和柠檬似乎更相似,我们必须考虑其他一些特征来完成我们的任务,教会孩子准确地识别这三种水果。
(上图)照片由肖恩·迈因杰斯在 Unsplash | ( 左下)照片由 Unsplash 伊莲娜·科切娃|(右下)照片由布雷特·乔丹在 Unsplash
区分柠檬和橙子的一个很好的参数可能是它们的颜色。假设柠檬通常是绿色的,而橙子通常是……橙色的,这将是一个很好的第二个参数,几乎总能引导我们聪明的孩子正确地识别水果。如果我们的橙子还没熟,还是绿色的,也许我们可以比较一下大小,如果它大于某个标准,我们就说它是橙子,否则,我们就把它归类为柠檬。
这可能看起来很傻,但这正是决策树算法的过程。在描述我们水果的所有可用特征中,它将深入数据,选择最重要的特征,最好地将一个类从其他类中分离出来,并对其余的特征遵循相同的逻辑,直到它找到一种方法来更好地确定它是哪种水果。
这就是决策树算法也可用作特征选择工具的原因,在本例中,它将识别对我们的识别更重要的特征,并排除对我们的主要目标贡献很小或没有贡献的特征。
例如,如果我们有谁购买了我们例子中的每一种水果的信息,那么对我们谈论的水果进行分类可能是不相关的信息,而这些树的结构在识别它方面非常好。
作者图片
如果我们能把不同的树放在一起,从几个不同的角度观察这些水果,以更好地了解它们如何区分彼此,会怎么样?这正是随机森林算法的思想。
它创建了一系列决策树,每一个都在寻找相同水果示例的略微不同的组成,并从不同的角度来看待它们:例如,一个决策树使用颜色作为第一个参数来构建,而另一个树使用高度。
只有当我们保证一棵树不等于另一棵树时,这才有意义,否则我们就不能从不同的“观点”中获益,并且创建一组树所需的计算能力也是不合理的。为了保证一组不同的树,一些参数是可以控制的(考虑到我们正在使用像Scikit-Learn这样的库中可用的框架,而不是从头开始构建它)。
首先,我们的算法将为每棵树选择一组不同的例子。因此,假设我们的原始数据有 1000 个可用的水果示例:该算法将为每棵树随机选择 1000 个示例,这意味着一些示例可能会在同一个集合中被选择多次,而其他示例可能会丢失。
除此之外,我们还可以控制参数,比如max_features
的数量。这个参数将设置一个数字,比如说 2,然后算法将为每棵树选择两个随机特征,并决定其中哪个最重要,以区分不同的果实。
这些随机因素实际上保证了所有的决策树都是不同的。另一个重要的参数是n_estimators
,它允许用户选择要创建的决策树的数量。
作者图片
直观地说,与单个决策结构相比,一系列协同工作的决策树会表现得更好,这说明了使用随机森林算法的强大之处。一旦我们建立了一个森林,我们如何让不同的决策树一起工作?
如果我们希望我们的模型预测哪种水果,给定一组新的特征,每棵树都将进行预测,并且该预测将与每类的一个概率相关联。例如,一棵树可以得出结论,给定的特征 80%可能是香蕉,12%可能是橙子,8%可能是柠檬,而其他树可能具有不同的关联概率。
最后,将对这些概率计算一个加权投票,得出最终结论。这将是一个分类任务的基本过程,就像我们的水果示例一样。
当我们想要预测一个连续的数字或度量时,如房子的价格或在某个特定时期将要出售的产品的数量,随机森林也可以用在回归任务中。在这种情况下,程序基本上是相同的,但是最终的预测不是像在分类任务中那样通过加权投票给出的,而是通过计算个体树预测的平均值来给出的。****
(左)照片由皮奥特·西霍斯在 Unsplash | ( 右)照片由路易·汉瑟@肖特·路易在 Unsplash
只是不要忘记,如果你向我们的水果模型分类器展示一个遥控器,它肯定会认为这是一个香蕉。这些模型准确地学习我们告诉它们学习的东西,它们预测的质量取决于我们给它们的例子的质量。
在本文中,我们更好地理解了最流行的机器学习算法之一是如何在幕后工作的。既然算法与机器控制一切的电影场景混合在一起的抽象概念已经离开了你的头脑,试着写下你的第一行代码怎么样?****
我知道大多数关于数据科学的文章都是用英语写的,所以我创建了一个名为 Tech4All-br 的项目,目的是用葡萄牙语创建内容。如果你想阅读葡萄牙语的材料,请访问此链接。
预测用随机森林
原文:https://towardsdatascience.com/random-forest-ca80e56224c1?source=collection_archive---------3-----------------------
利用随机森林预测汽车价格
这是一个在多个决策树之间操作的过程,通过选择其中的大多数作为最佳值来获得最佳结果。
有输出的多重决策树。(图片鸣谢:easydrawingguides.com,作者编辑)
请将上面的图像视为具有不同结果的多个决策树的代表。在 4 个决策树中,3 个的输出与 1 相同,而一个决策树的输出为 0。应用上面提到的定义,随机森林操作四个决策树,并且为了获得最佳结果,它选择大多数(即 3 个)决策树提供的结果。因此,在这种情况下,最佳结果将是 1。
对于决策树,您可以通过点击链接【https://towardsdatascience.com/decision-tree-ba64f977f7c3 访问更早的故事
用途
- 遥感:随机森林(RF)通常用于遥感,以预测数据的准确性/分类。
- 物体检测:射频在更短的时间内对物体检测起主要作用。
为什么?
- 因为我们在多个决策树上工作,所以过度拟合的可能性较小。
- 更高的准确性:因为它运行在更大的数据集上,所以准确性更高。
- 估计缺失数据:因为它运行在一个更大的数据集上,所以您也可以估计缺失值。
随机森林是如何工作的?
多重决策树(图片由作者提供)
在上图中,我们使用 3 个不同的决策树进行了相同的分类。树 1 使用颜色对数据进行分类,树 2 使用花瓣大小和颜色,树 3 使用花瓣寿命和颜色。
缺少颜色数据的花(图片来源:Vectorstock.com)
现在模特训练有素。考虑到我们有一朵缺少颜色数据的花。树 1 将无法识别此数据,因为它用颜色对所有东西进行了分类,所以它会将其归入郁金香花类别。
树 2:它作用于颜色和花瓣大小。根据花瓣的大小,它会变成假的,即不小,然后是颜色,即不是黄色。这是对它是一朵玫瑰的预测。
树 3:它对寿命和颜色有效。第一个分类将是一个错误的类别,随后是非黄色。正如预测的那样,这是一朵玫瑰。
让我们尝试使用 Python 随机森林。首先,我们将导入所需的 python 库。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
我们正在进口熊猫、NumPy 和 matplotlib。接下来,我们将消费数据并查看它。
作者图片
df.head()将给出每一列的前 5 行的详细信息。我们可以使用 df.tail()获得最后 5 行,使用类似的 df.head(10)获得前 10 行。
数据是关于汽车的,我们需要用上面的数据来预测汽车的价格
我们将使用随机森林来获得汽车的价格。
df.dtypessymboling int64
normalized-losses int64
make object
aspiration object
num-of-doors object
body-style object
drive-wheels object
engine-location object
wheel-base float64
length float64
width float64
height float64
curb-weight int64
engine-type object
num-of-cylinders object
engine-size int64
fuel-system object
bore float64
stroke float64
compression-ratio float64
horsepower float64
peak-rpm float64
city-mpg int64
highway-mpg int64
price float64
city-L/100km float64
horsepower-binned object
diesel int64
gas int64
dtype: object
dtypes 给出列的数据类型。
df.describe()
作者图片
在上面的数据框中,所有的列都不是数字。因此,我们将只考虑那些数值为数字的列,并使所有的数字都浮动。
df.dtypes
for x **in** df:
if df[x].dtypes == "int64":
df[x] = df[x].astype(float)
print (df[x].dtypes)
准备数据与分类任务一样,在本节中,我们将把数据划分为属性和标签,从而划分为训练集和测试集。我们将创建 2 个数据集,一个用于价格,另一个(df-price)。由于我们的数据框包含大量对象格式的数据,因此在本次分析中,我们将删除所有对象类型的列,对于所有 NaN 值,我们将删除该行。
df = df.select_dtypes(exclude=['object'])
df=df.fillna(df.mean())
X = df.drop('price',axis=1)
y = df['price']
这里,X 变量包含数据集中的所有列,除了标签“价格”列。y 变量包含“价格”列中的值,这意味着 X 变量包含属性集,y 变量包含相应的标签。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
为了训练树,我们将使用 Random Forest 类并用 fit 方法调用它。我们将有一个随机的 1000 棵决策树的森林。
from sklearn.ensemble import RandomForestRegressor
regressor = RandomForestRegressor(n_estimators = 1000, random_state = 42)
regressor.fit(X_train, y_train)
作者图片
我们来预测一下价格。
y_pred = regressor.predict(X_test)
让我们检查实际值和预测值之间的差异。
df=pd.DataFrame({'Actual':y_test, 'Predicted':y_pred})
df
from sklearn import metrics
print('Mean Absolute Error:', metrics.mean_absolute_error(y_test, y_pred))
print('Mean Squared Error:', metrics.mean_squared_error(y_test, y_pred))
print('Root Mean Squared Error:', np.sqrt(metrics.mean_squared_error(y_test, y_pred)))Mean Absolute Error: 1993.2901175839186
Mean Squared Error: 9668487.223350348
Root Mean Squared Error: 3109.4191134921566
我们算法的平均绝对误差是 1993.2901175839186,小于“价格”列中所有值平均值的 20%。这意味着我们的算法做出了预测,但还需要很多改进。
让我们检查一下我们预测的准确性。
*# Calculate the absolute errors*
errors = abs(y_pred - y_test)
*# Print out the mean absolute error (mae)*
print('Mean Absolute Error:', round(np.mean(errors), 2), 'degrees.')
*# Calculate mean absolute percentage error (MAPE)*
mape = 100 * (errors / y_test)
*# Calculate and display accuracy*
accuracy = 100 - np.mean(mape)
print('Accuracy:', round(accuracy, 2), '%.')Mean Absolute Error: 1993.29 degrees.
Accuracy: 87.87 %.
87.8%的准确率并不是一个很高的分数,还有很大的提升空间。
让我们画出实际值和预测值之间的差异。
import seaborn as sns
plt.figure(figsize=(5, 7))
ax = sns.distplot(y, hist=False, color="r", label="Actual Value")
sns.distplot(y_pred, hist=False, color="b", label="Fitted Values" , ax=ax)
plt.title('Actual vs Fitted Values for Price')
plt.show()
plt.close()
实际与预测(图片由作者提供)
以上是实际值和预测值之间的曲线图。让我们想象一下随机的森林树。
import pydot
*# Pull out one tree from the forest*
Tree = regressor.estimators_[5]
*# Export the image to a dot file*
from sklearn import tree
plt.figure(figsize=(25,15))
tree.plot_tree(Tree,filled=True,
rounded=True,
fontsize=14);
随机森林树(作者图片)
可以在https://www.kaggle.com/adityakumar529/random-forest处检查代码。
https://github . com/adityakumar 529/Coursera _ Capstone/blob/master/Random _ forest . ipynb
兰登森林解释道
原文:https://towardsdatascience.com/random-forest-explained-7eae084f3ebe?source=collection_archive---------3-----------------------
图片来自 Unsplash 。
[Random Forest 简单解释:训练、分类和回归的简单介绍]
在本帖中,我们将解释什么是随机森林模型,看看它的优点,它是如何构建的,以及它能用来做什么。
我们将通过随机森林 的理论和直觉,看到理解万物如何运作所必需的最少的数学量,而不深入最复杂的细节。
最后,在我们开始之前,这里有一些额外的资源可以让你的机器学习生涯突飞猛进:
*Awesome Machine Learning Resources:**- For* ***learning resources*** *go to* [***How to Learn Machine Learning***](https://howtolearnmachinelearning.com/books/machine-learning-books/)*!
- For* ***professional******resources*** *(jobs, events, skill tests) go to* [***AIgents.co — A career community for Data Scientists & Machine Learning Engineers***](https://aigents.co/)***.***
[## 订阅我的专属列表!
订阅我的专属列表!并获得所有你喜爱的新鲜文章<3! By signing up, you will create a Medium…
z-ai.medium.com](https://z-ai.medium.com/subscribe)
1. Introduction
In the Machine Learning world, Random Forest models are a kind of 非 参数模型既可用于回归又可用于分类。它们是最流行的集成方法之一,属于 Bagging 方法的特定类别。
en 集合方法包括使用多个学习者来单独提高其中任何一个人的表现。这些方法可以被描述为使用一群弱学习者 ( 那些平均成绩仅比随机模型稍好的人)在一起的技术,以便创建一个更强的、聚合的。
在我们的例子中,随机森林是许多独立决策树的集合。如果您不熟悉决策树,您可以在这里了解它们:
[## 决策树解释
学习机器学习决策树的所有知识
towardsdatascience.com](/decision-trees-explained-3ec41632ceb6)
决策树的一个主要缺点是它们很容易过度拟合:它们在训练数据上做得很好,但在对看不见的样本进行预测时却不够灵活。虽然有一些解决办法,比如修剪树木,但这降低了它们的预测能力。一般来说,它们是具有中等偏差和高方差的模型,但是它们简单且易于解释。
如果你对偏差和方差的区别不是很有信心,看看下面的帖子:
[## 快速偏差/方差权衡
偏差/方差的权衡很容易解释
towardsdatascience.com](/quick-bias-variance-trade-off-d4895b126b08)
随机森林模型结合了决策树 的简单性和集合模型的灵活性和强大功能。在树木的森林中,我们忘记了特定树木的高方差,更少关心每一个单独的元素,所以我们可以种植更好、更大的树,比修剪过的树具有更强的预测能力。
尽管随机森林模型提供的解释能力不如单棵树,但它们的性能要好得多,而且我们不必像处理单棵树那样担心如何完美地调整森林的参数。
好吧,我明白了,随机森林是一组独立的树。但为什么取这个名字随机呢?随机性在哪里?让我们通过学习如何构建随机森林模型来找出答案。
2.训练和建立随机森林
构建随机森林有 3 个主要阶段。我们将分解它们,并阐明每个概念和步骤。我们走吧!
2.1 为每棵树创建引导数据集
当我们构建一个单独的决策树时,我们使用一个训练数据集和所有的观察。这意味着,如果我们不小心,树可以很好地适应这种训练数据,并对新的、看不见的观察结果进行糟糕的概括。为了解决这个问题,我们阻止树变得非常大,通常是以降低其性能为代价。
为了建立一个随机森林,我们必须训练 N 棵决策树。我们是否一直使用相同的数据来训练这些树?我们使用整个数据集吗?没有。
这是第一个随机特征出现的地方。为了训练每一棵树,我们从整个数据集中随机抽取一个样本,如下图所示。
构建单独的数据集。图片作者。来自平面图标的图标。
从这个图可以推断出各种事情。首先,用于训练每棵树的数据的大小不一定是整个数据集的大小。此外,一个数据点可以在用于训练单个树的数据中出现多次(就像在树 n 2 中一样)。
这称为替换抽样或引导抽样:每个数据点都是从整个数据集中随机选取的,并且一个数据点可以被多次选取。
通过使用不同的数据样本来训练每棵树,我们减少了他们的一个主要问题:他们非常喜欢他们的训练数据。如果我们训练一个有很多树的森林,每棵树都用不同的数据训练过,我们就解决了这个问题。他们都很喜欢自己的训练数据,但森林不喜欢任何具体的数据点。这允许我们种植更大的单棵树,因为我们不再那么关心单棵树的过度生长。
如果我们使用整个数据集的很小一部分来训练每棵树,我们会增加森林的随机性(减少过度拟合),但通常是以较低的性能为代价的。
在实践中,默认情况下,大多数随机森林实现(如 Scikit-Learn 中的实现)选择用于每棵树的训练数据样本,其大小与原始数据集相同(但是它不是相同的数据集,请记住,我们选择的是随机样本)。
这通常提供了良好的偏差-方差折衷。
2.2 使用这些随机数据集训练森林树,并通过特征选择增加一点随机性
如果您记得不错,为了构建一个单独的决策树,我们在每个节点评估了某个指标(如基尼指数或信息增益),并选择数据的特征或变量放入最小化/最大化该指标的节点。
当只训练一棵树的时候,这种方法还不错,但是现在我们想要一整片树林!我们如何做到这一点?如果单个模型(在我们的例子中是单棵树)不相关,集合模型(如随机森林)效果最好。在随机森林中,这是通过在每个节点随机选择某些特征进行评估来实现的。
构建树 n 1 的随机特征选择。图片作者。来自平板图标的图标。
正如您在前面的图像中看到的,在每个节点上,我们只评估所有初始特征的子集。对于根节点,我们考虑 E、A 和 F(并且 F 获胜)。在节点 1 中,我们考虑 C、G 和 D(并且 G 获胜)。最后,在节点 2 中,我们只考虑 A、B 和 G(A 获胜)。我们将继续这样做,直到我们建立了整个树。
通过这样做,我们避免在每个树中包括具有非常高预测能力的特征,同时创建许多不相关的树。这是第二次随机扫描。在构建每棵树时,我们不仅使用随机数据,还使用随机特征。树的多样性越大越好:我们减少了方差,得到了一个性能更好的模型。
2.3 对 N 棵树重复上述步骤,创建我们的神奇森林。
太棒了,我们已经学会了如何建立一个单独的决策树。现在,我们将对 N 棵树重复这一过程,在每棵树的每个节点上随机选择哪些变量进入竞争,被选为分割的特征。
总之,整个过程如下:
- 为每棵树创建一个引导数据集。
- 使用相应的数据集创建决策树,但在每个节点使用变量或特征的随机子样本进行分割。
- 重复这三个步骤数百次,建立一个拥有各种各样树木的大森林。这种多样性使得随机森林比单一决策树好得多。
一旦我们建立了我们的森林,我们就准备用它来做令人敬畏的预测。让我们看看如何!
3.使用随机森林进行预测
用随机森林做预测非常容易。我们只需获得我们的每一棵树,通过它们传递我们想要进行预测的观察值,从每棵树获得一个预测值(总计 N 个预测值),然后获得一个整体的、聚合的预测值。
对数据进行自举,然后使用一个聚合来进行预测,这被称为 Bagging,如何进行预测取决于我们所面临的问题的类型。
对于回归问题,集合决策是每个决策树决策的平均值。对于分类问题,最终预测是森林所做的最频繁的预测。
使用随机森林的预测。图片作者。来自平面图标的图标。
上图展示了这个非常简单的过程。对于分类问题我们想预测某个病人是生病了还是健康了。为此,我们通过随机森林中的每棵树传递他的医疗记录和其他信息,并获得 N 个预测(在我们的例子中是 400 个)。在我们的例子中,355 棵树表示病人健康,45 棵树表示病人生病,因此森林判定病人健康。
对于回归问题我们想预测某个房子的价格。我们通过 N 棵树传递这个新房子的特征,从每棵树上得到一个数字预测。然后,我们计算这些预测的平均值,得到最终值 322.750 美元。
简单对吧?我们对每一棵树都进行预测,然后使用平均值或众数(最频繁值)汇总这些预测。
[## 订阅我的专属列表!
订阅我的专属列表!并获得所有你喜欢的新鲜文章<3! By signing up, you will create a Medium…
z-ai.medium.com](https://z-ai.medium.com/subscribe)
4. Conclusion and other resources
In this post we have seen what a Random Forest is, how it overcomes the main issues of Decision Trees, how they are trained, and used to make predictions. They are very flexible and powerful Machine Learning models that are highly used in commercial and industrial applications, along with Boosting 模型和人工神经网络。
在以后的文章中,我们将探索随机森林的技巧和诀窍,以及它们如何用于特征选择。此外,如果你想知道它们是如何建造的,可以看看 StatQuest 的视频,非常棒:
就是它!一如既往,我希望你 喜欢这个职位。
有关机器学习和数据科学的更多资源,请查看以下资源库: 如何学习机器学习 !有关职业资源(工作、事件、技能测试),请访问AIgents.co——数据科学家职业社区&机器学习工程师 。
非常感谢您的阅读,祝您愉快!
涡轮风扇发动机预测维修的随机森林
原文:https://towardsdatascience.com/random-forest-for-predictive-maintenance-of-turbofan-engines-5260597e7e8f?source=collection_archive---------13-----------------------
戴维·科瓦连科在 Unsplash 上拍摄的照片
探索美国宇航局的涡轮风扇数据集
FD003 的探索性数据分析和超参数调整
<免责声明:我的目的是展示模型开发过程中不同方法和选择的效果。这些影响经常使用测试集来显示,这被认为是(非常)不好的做法,但有助于教育目的。 >
欢迎来到“探索 NASA 的涡轮风扇数据集”系列的另一部分。在上一篇文章中,我们看了生存分析,并总结了我们对数据集 FD001 的分析。虽然最终的 RMSE 没有我们之前创建的模型好,但这是一个非常有趣的技术,因为它可以处理经过审查的数据。今天,我们将深入第三个数据集(FD003),其特征是发动机有两种可能的故障模式。
数据集元数据
我选择了交换在 FD002 和 FD003 上发布的顺序,因为在我看来,这个顺序会使复杂性逐渐增加。起初,我已经开始在 FD002 上安装随机森林(RF ),但结果并不理想。FD002 看起来确实需要更复杂的预处理和建模来处理各种操作条件。然而,在 FD003 上,我认为 RF 将表现得相当好,因为它自然能够区分故障模式。让我们一起来了解一下吧!
探索性数据分析
我们可以在 FD001 上重复 EDA 中的许多步骤。首先,让我们读入数据。
# returns
# (24720, 26)
train.head()的结果
看起来不错,接下来我们将考察一些描述性统计。
我们的数据集包括 24.7k 行和 26 列,第一个引擎在 145 个时间周期后失败,而最后一个引擎在 525 个时间周期后失败。接下来,我们将检查传感器描述符。
根据(几乎)为零的标准偏差来判断,传感器 1、5、16、18 和 19 没有保存有价值的信息。
在我们开始绘制数据之前,让我们计算一下列车组的剩余使用寿命(RUL)。
RUL 在击穿时可以认为是 0,我们天真地假设 RUL 是一个线性函数。意味着在击穿前的 10 个周期时 RUL 是 10,在击穿前的 50 个周期时是 50,等等。
既然已经添加了,我们将检查分布情况,以便获得比检查描述性表更好的理解。
RUL 的分布。
RUL 很明显是右斜的,左边根本没有尾巴。偏斜分布会对模型性能产生很大影响。EDA 完成后,我们会将计算的 RUL 限制在 125 的上限,用于模型训练,因为它更好地代表了我们对训练集[1,2]的 RUL 的了解。
标绘信号
接下来,我们将检查传感器值,看看我们是否可以直观地区分不同的故障模式,并确定在模型开发中要放弃的传感器。
S1 对 RUL 的曲线图
传感器 1、5、16、18 和 19 看起来都很相似。我们可以再次确认他们的排除,因为他们似乎没有任何信息。
S2 对 RUL 的曲线图
传感器 2、3、4、8、11、13 和 17 显示出类似的上升趋势,应包括在模型开发中。
S6 对 RUL 的图表
传感器 6 是一个有点奇怪的传感器,但在怀疑中受益。
七国集团对 RUL 的图表
传感器 7、12、15、20 和 21 清楚地显示了两种故障模式,并且应该明确地包括在模型中。
S9 对 RUL 的图表
传感器 9 和 14 显示了类似的趋势,但不能很好地区分故障模式。测试它们对模型性能的影响必须指出它们是否应该包含在内。
s_10 vs RUL 的图表
最后,传感器 10,也是一个奇怪的传感器,因为它似乎有上升趋势,所以被认为是有益的。EDA 完成后,是时候创建基线模型了。
基线模型
就像我们对 FD001 所做的一样,我喜欢从一个最简单的模型开始,一个没有额外预处理的回归模型。
# returns
# train set RMSE:19.33013490506061, R2:0.7736110804777467
# test set RMSE:22.31934448440365, R2:0.7092939799790338
基线模型的测试 RMSE 是 22.319,这将是我们要打破的分数。接下来是我们对随机森林回归器的第一次尝试。
随机森林
与单一决策树相比,随机森林(RF)的一个关键优势是它们能够生成不同的树。让我解释一下。创建单个决策树时,该算法会尝试基于单个要素(所有可用要素中的一个)创建一个决策节点,该要素可以最好地分割数据集。对于下一个节点,它将重新检查所有可用的特征,以创建以下最佳分割。如果你在这些条件下第二次拟合决策树,它会生成完全相同的树。然而,当创建分割时,RF 仅考虑所有特征的子集。这迫使算法生成不同的树,因为创建最佳分割的特征可能不可用。可能会产生比常规决策树的单个最佳分割更好的分割组合。
虽然上面的描述是我学习 RF 工作原理的方式,但检查您使用的工具是否也以同样的方式实现它也很重要。
scikit 的部分 RF 文档-了解 v0.22.2 [3]
scikit 的部分 RF 文档-了解 v0.22.2 [3]
检查 sklearns RandomForestRegressor 的文档显示,它默认考虑所有特性,本质上是一遍又一遍地创建同一个树。因此,我们将 max_features 指定为可用功能的平方根。此外,我们设置了 random_state,因此树总是以相同的方式生成。否则,随机树的生成将影响模型结果,使得很难判断一个模型是否因为我们改变了一些特征或由于随机性而表现得更好。
# returns
# train set RMSE:5.9199939580022525, R2:0.9787661901585051
# test set RMSE:21.05308450085165, R2:0.7413439613827657
虽然 RF 已经比我们的基线模型表现得好一点。根据训练集和测试集之间的 RMSE 和方差的差异来判断,该模型似乎非常适合。让我们检查一些树的特征来验证我的怀疑。
# returns
# 33
# array([15616, 11694, 7793, ..., 1, 1, 4], dtype=int64)
这棵树的最长路径由 33 个节点组成,是我们放入的特征数量的两倍多。当查看 n_nodes_samples 时,我们可以看到树的最后几片叶子每个都包含很少的样本。该树变得如此具体,它创建了分裂标准,直到大多数样本可以被区分,这对于泛化来说是非常糟糕的(因此在训练集上过度拟合)。我们可以通过设置 RF 的 max_depth 和 min_samples_leaf 来尝试解决这个问题。
# returns
# train set RMSE:15.706704198492831, R2:0.8505294865338602
# test set RMSE:20.994958823842456, R2:0.7427702419664686
尝试这些设置可以减少过度拟合,同时获得轻微的性能提升。在没有 s_6 和 s_10 的情况下拟合相同的模型表现更差,因此保留了这些传感器。我们将把这个模型作为进一步改进的基础。
可视化射频
我们可以将我们的树中的一棵形象化,试图找出改进点【4,5】。
决策树的一部分,请注意,此可视化仅代表 RF 的单个树
似乎有一些节点会导致非常不准确的预测(mse > 500)。还记得传感器 9 和 14 吗,它们不能很好地区分故障模式?它们在树的这一部分显示为分裂标准,但结果仍然黯淡无光。让我们尝试在没有这两个传感器的情况下安装一个 RF,并检查其性能。
重新运行粗略调整的 RF 返回:
# train set RMSE:17.598192835079978, R2:0.8123616776758054
# test set RMSE:22.186214762363356, R2:0.7127516253047333
不幸的是,性能变得相当糟糕,所以我们将保留传感器 9 和 14。
浅谈特征工程
对于这种特定的数据集-算法组合,没有太多的特征工程的可能性。随机森林天生擅长学习复杂的数据模式,并且对缩放或特征变换不变[6]。因为所有的特征都已经是数字了,所以我们没有更多的事情可做。
我试着用简单的移动平均数来平滑数据。理论上,这将使算法更容易正确地应用其分裂,并使其更容易区分故障,因为噪声已从信号中去除。但遗憾的是,性能并没有提升。平滑传感器信号的代码可以在笔记本上找到(文章底部的链接)。接下来,我们将深入研究超参数调优。
超参数
我们可以调整哪些参数?
# returns
{'bootstrap': True,
'ccp_alpha': 0.0,
'criterion': 'mse',
'max_depth': 8,
'max_features': 'sqrt',
'max_leaf_nodes': None,
'max_samples': None,
'min_impurity_decrease': 0.0,
'min_impurity_split': None,
'min_samples_leaf': 50,
'min_samples_split': 2,
'min_weight_fraction_leaf': 0.0,
'n_estimators': 100,
'n_jobs': None,
'oob_score': False,
'random_state': 42,
'verbose': 0,
'warm_start': False}
有关所有参数的完整描述,请参考官方文档[3]。拟合随机森林的最大挑战是过度拟合。参数 max_depth、min_samples_leaf、ccp_alpha 和 min _ infinity _ decrease 有助于减少过拟合并生成整体性能更好的模型。因此,我选择这些来进行模型调整。
最大深度和最小样本叶应该是不言自明的,但是 ccp 阿尔法和最小杂质减少需要更多的解释。
ccp 阿尔法
成本复杂性修剪α是用于修剪树的参数。修剪是在拟合后删除节点,因此本质上 CCP _ 阿尔法是使用最小 _ 样本 _ 叶子和最大 _ 深度来防止过度拟合的替代方法。
节点的成本复杂度可以从拟合树中检索。较低的 ccp 阿尔法值表示较高的成本复杂度。通过移除具有小 CCPα的节点,树被修剪,并且整体复杂性降低[7]。
为了指示超参数调谐使用的 CCPα的范围,最好将有效α与叶子的杂质可视化。注意,下面的分析来自 RF 的单个树。
总叶杂质与有效α的关系图
当有效 alpha 从大约 70 下降到稍微超过 20 时,树的成本复杂性确实增加了,但是对于较低的 alpha 值,成本复杂性对叶子杂质的影响很难确定,让我们放大一点。
总叶杂质与有效α的放大图
当有效阿尔法从 2 下降到 0 时(成本复杂性达到最大值),叶子杂质似乎减少了约 50 点,相当于约 7 个训练 RMSE。鉴于我们的第一个 RF 的极端过拟合,这似乎是超参数调谐的合适范围。
最小杂质减少量
最小杂质减少是一种测量方法,用于指示分离后误差的减少。杂质减少是一个加权值,计算如下:
计算杂质减少的公式[3]
杂质减少通常是为单个决策树计算的。所以,我们先提取单棵树所需的数据。
# returns shape (227, 5)
杂质结果 _df.head(10)
在查看前几行时,您应该注意到一些 child_id 的值为-1。这表明父节点是一个叶节点,因此没有进行进一步的分割。
利用数据帧中的所有数据,我们可以使用上述公式计算最小杂质减少量。
最好将结果可视化,以了解最小杂质减少的合适值。
杂质减少直方图
杂质减少非常右偏,这可以通过树的前几个节点对减少误差贡献很大来解释。检查描述符显示 25%的杂质减少值低于 14.59,这似乎是最小杂质减少参数的合适上限。
杂质减少的描述性统计和放大直方图
随机搜索
在研究完要优化的参数之后,我们现在可以设置合适的评估范围。
# returns
1571724
注意,如果我们想测试所有可能的组合,我们必须适应超过 150 万个模型。乏味的任务。幸运的是,通过随机挑选 60 个独特的组合来应用 Randomsearch 应该可以得到 95%的最优解[8]。
增加迭代次数会增加找到更好解决方案的可能性。除了使用 Randomsearch,我更喜欢保持较低的树数以加快训练时间。这种组合允许相对快速的搜索。
我已经执行了几次搜索,选择了性能最好的设置。在展示代码之前,还有一件事需要讨论:我们需要创建验证集来验证所选择的超参数。
确认
为该数据创建验证集需要考虑一个重要因素。包含在训练集中的引擎不能包含在验证集中,反之亦然。
通常,您会在数据中创建一个随机分割,其中 80 %属于定型集,20 %属于验证集。然而,如果我们随机分割而不考虑单元号,我们可能会在训练集和验证集中结束单个引擎的部分数据。然后,该模型可以学习在时间步长之间进行外推,并对验证集进行非常准确的预测。然而,对于真正的新数据,模型性能会受到影响。
为了防止这种形式的“数据泄漏”,我们必须确保将单个引擎的所有记录分配给训练集或验证集。为了实现这种形式的数据分割,我们将使用 GroupKFold。
随机搜索的打印进度
由于训练时间相对较短,我将迭代次数设置为 300 次。接下来,RandomizedSearchCV 用裸 RF、用于超参数调整的采样参数和 GroupKFold 实例化,其中组基于 unit_nr。随机搜索需要不到 15 分钟的时间,我们可以将结果转换成数据帧以供进一步检查。
随机搜索的结果
检查结果有助于了解哪些超参数表现良好,并有可能用于优化您的搜索空间(我们暂时不做讨论)。
不幸的是,结果是不可重复的,这意味着重新启动内核并再次运行笔记本不会产生相同的结果。我将在下一篇分析中尝试解决这个问题。执行了几次搜索后,我找到的性能最好的参数集是:
{'min_samples_leaf': 11, 'min_impurity_decrease': 0.0, 'max_depth': 15, 'ccp_alpha': 0.125}.
平均测试分数为-16.577。
最终模型
使用这些参数,我们可以训练我们的最终模型。
# returns:
# train set RMSE:13.95446880579081, R2:0.8820190156933622
# test set RMSE:20.61288923394374, R2:0.7520472702746352
现在你有了它,一个没有特征工程(只有一些特征选择)但仍然有很好结果的调整随机森林。20.612 的测试 RMSE 比我们的基线模型提高了 7.65%。这可能看起来不多,但就 RMSE 而言,这个 RF 优于我们之前在 FD001 上拟合的时间序列模型(其 RMSE 为 20.852),而 FD003 是一个更复杂的数据集!
完整的笔记本你可以在这里查看我的 github 页面。我要感谢迈克尔·格罗贝的意见和评论。下一次,我们将使用 Tensorflow 深入研究更加复杂的 FD002 和神经网络。有任何问题或意见吗?请在下面的评论中告诉我!
参考文献
【1】监督预测维护解决方案问题框架的重要性
【2】f . o . Heimes,“剩余使用寿命估计的递归神经网络”, 2008 年国际预测和健康管理会议,丹佛,CO,2008,第 1–6 页,doi:10.1109/PHM . 2008 . 4711422 .
【3】https://sci kit-https 评估机器学习模型。奥莱利媒体公司 2015
随机森林:超参数以及如何微调它们
原文:https://towardsdatascience.com/random-forest-hyperparameters-and-how-to-fine-tune-them-17aee785ee0d?source=collection_archive---------5-----------------------
图片来自来源。
如何优化最常用的机器学习模型之一
随机森林是一种很棒的机器学习模型。它们解决了单个决策树的许多问题,并且在构建某个应用程序时,它们总是最准确的候选模型。
如果你不知道什么是决策树或随机森林,不要担心;我给你准备了以下文章。快速看一眼,然后回到这里。
[## 决策树解释
学习机器学习决策树的所有知识
towardsdatascience.com](/decision-trees-explained-3ec41632ceb6) [## 兰登森林解释道
Random Forest 简单地解释了:训练、分类和回归的简单介绍
towardsdatascience.com](/random-forest-explained-7eae084f3ebe)
在这篇简短的文章中,我们将探索随机森林的一些基本优化,以及每个超参数是什么,哪些值得优化。
我们走吧!
[## 订阅我的专属列表!
订阅我的专属列表!并获得所有你喜欢的新鲜文章<3! By signing up, you will create a Medium…
z-ai.medium.com](https://z-ai.medium.com/subscribe)
Hyper-parameter considerations, tips and tricks
The most important hyper-parameters of a Random Forest that can be tuned are:
- 森林中决策树的 N 个(在 Scikit-learn 中这个参数被称为 n_estimators )
- 在每个节点上分割的标准(分类任务的基尼系数或熵,或回归的 MSE 或 MAE)
- 单棵树的最大深度。个体树越大,越有可能过度拟合训练数据,然而,由于在随机森林中我们有许多个体树,这不是一个大问题。
- 在树的内部节点上分割的最小样本。如果需要的话,我们可以用这个参数和前一个参数来调整单个的树。
- 叶节点的最大数量。在随机森林中,这并不重要,但是在单个决策树中,这也可以极大地帮助减少过度拟合,并且通过减少到叶节点的可能路径数量来帮助增加树的可解释性。了解如何使用决策树来构建可解释的 ML 模型在这里。
- 包括在每个分割节点的随机特征数量。
- 用来训练每个决策树的引导数据集的大小。
好了,现在我们知道应该在哪里优化和调整我们的随机森林,让我们看看触摸这些参数会做什么。
森林中的树木数量:
通过用大量的树(大量的估计量)建立森林,我们可以以更长的训练时间为代价,创建一个方差更小的更健壮的集合模型。大多数情况下,这里的秘密是评估您的数据:有多少数据可用,以及每个观察值有多少个特征。
由于随机森林的随机性,如果您有大量的要素和少量的树,一些具有高预测能力的要素可能会被排除在森林之外,无论如何都不会被使用,或者很少被使用。
这同样适用于数据:如果您有大量的观察值,并且您没有使用整个数据集来训练每棵树,如果您有少量的树,那么一些观察值可能会被忽略。
由于随机森林很少过度拟合,在实践中,您可以使用大量的树来避免这些问题,并遵循以下准则获得良好的结果:当所有其他超参数都固定时,增加树的数量通常会以更长的训练时间为代价来减少模型误差。
不过,不要被这种说法所迷惑,用 10K 树建造一个森林是一种疯狂而无用的方法:主要的收获是,随着你增加树的数量,你将减少模型方差,通常模型误差将接近最佳值。
随着我们增加树的数量和对具有 100000 棵树的 RF 的估计直方图,分类误差减少。来源。
结论 :微调树的数量是不必要的,只需将树的数量设置为一个大的、计算上可行的数字,就可以了。
在树的每个节点上拆分的标准
决策树通过计算哪个特征和该特征的哪个值最好地分割到该点的观察,在每个节点做出局部最优决策。
为了做到这一点,他们使用了一个特定的指标(基尼系数或熵值用于分类)和(MAE 或 MSE 用于回归)。对于回归,如果数据中没有很多异常值,一般规则是采用 MSE,因为它会严重惩罚那些远离平均值的观察值。
对于分类,事情有点棘手。我们必须用基尼系数或熵值来计算杂质,这有时会导致不同的分裂。以下面的问题为例,我们有两个类,A 和 B:
- 根据基尼系数和熵,仅具有 A 类观测值的节点是 100%纯的。
- 根据基尼系数和熵,具有 10 个 A 类观测值和 10 个 B 类观测值的节点是 100%不纯的。
- 具有 3 个 A 类观察值和 1 个 B 类观察值的节点是 75%或 81%不纯的,这取决于我们是否分别使用基尼或熵。
根据我们使用两者中的哪一个,我们的模型可以改变。这里没有一个真正的经验法则来知道该选择哪一个。不同的决策树算法使用不同的指标(CART 使用 Gini,而 ID3 使用熵)。
基尼系数和熵的公式。自制图像。
话虽如此,基尼系数通常计算成本较低,因为它不计算对数。RandomForestClassifier 的 Scikit-Learn 实现允许我们从两者中进行选择,因此尝试两种方法并查看哪种方法导致的错误更小可能是值得的。
结论 :微调分割标准可能会导致不同的森林,由于只有两个可能的值,我们建议对分类森林尝试这两个值。
单棵树的最大深度
增加单个树的深度会增加被考虑的特征/值组合的可能数量。树越深,它的分割就越多,它考虑的数据信息就越多。
在单个树中,这会导致过度拟合,但是在随机森林中,由于集合的构建方式,很难过度拟合,尽管对于较大的深度值仍有可能。
这个参数应该根据你的树的特征的数量设置一个合理的数量:不要建造树桩(非常浅的树)也不要建造大得吓人的树;将此参数设置为一个合理的值,如果需要的话可以稍微调整一下,但是合理值附近的变化不会对林的性能产生太大影响,所以如果您不需要,不必将它包括在像网格搜索这样的过程中。
结论 :不需要微调树的深度,取一个合理的值,继续其他超参数。
每次分割时要考虑的随机要素的数量
这是随机森林集合中最重要的超参数之一,所以请密切注意。
这个超参数的最佳值在没有实验的情况下很难选择,因此获得它的最佳方法是使用交叉验证的网格搜索,并考虑以下因素:
- 较小的值(在每个节点进行分割时考虑较少的特征)将减少集合的方差,代价是较高的个体树(可能还有集合)偏差。
- 该值应根据您拥有的信息量或质量要素的数量进行设置,并考虑到包含许多异常值的噪声要素。如果您的数据集具有非常干净、完美和高质量的要素,那么每个分割上的随机要素数量的值可能相对较小:所有考虑的要素都将是酷的。如果您有很多嘈杂的数据,那么这个值可能应该更高,以增加质量特征被包括在竞赛中的机会。
- 增加分割中考虑的随机要素的最大数量往往会降低模型的偏差,因为包含好要素的机会更大,但是这可能会以增加方差为代价。此外,当我们在每个节点包含更多要测试的特性时,训练速度会降低。
这里最实用的方法是交叉验证您的可能选项,并保留产生最佳结果的模型,同时考虑前面的考虑因素。您可以尝试在 Scikit-learn 的 RandomForestClassifier 的网格搜索空间中设置以下值。
- 无 :这将考虑你的数据的所有特征,从随机森林中取出一些随机性,并可能增加方差。
- sqrt :该选项将取单个每次分割的特征总数的平方根。如果我们的数据中有 25 个特征,那么它将在每个节点随机选取 5 个特征。这个选项通常适用于分类问题。
- 0.2(0 到 1 之间的十进制值):该选项允许随机森林在个体分割中取%的变量。在这个例子中,我们将选择 20%的特性,如果我们有许多特性,这是一个合理的数量。尝试 0.3、0.4 和 0.5,如果您有非常嘈杂的数据,甚至可能是更高的值。对于回归问题,0.33%是一个很好的起点。
引导数据集的大小
最后,我们将讨论增压数据集大小的重要性。这是用于训练每棵树的训练数据的百分比。
因为观察值是通过替换进行采样的,所以即使引导数据集的大小与整个训练集相同,两个数据集也会不同,所以很多时候该参数保持不变,并且每棵树都用具有相同初始训练数据大小的随机观察值集进行训练。
在 Sklearn 中,这由 max_samples 超参数控制,该参数默认采用初始数据集的大小。
在预期中,从大小为 N 的数据集中抽取 N 个替换样本将从原始集中选择大约 2/3 个唯一样本,留下 1/3 个样本(所谓的出袋或 OOB 数据,然后可用于评估森林)。
出于这些考虑,使用完整大小的训练数据没有坏处,因此大多数情况下,最好的办法是不要接触这个超参数。
** [## 订阅我的专属列表!
订阅我的专属列表!获得所有你喜欢的关于随机森林超参数调整的最新文章<3! By signing up, you will create a Medium…
z-ai.medium.com](https://z-ai.medium.com/subscribe)
Conclusion and further Resources.
In this post we have seen what the most important Hyper parameters of Random Forest are, how to set their values, and which of them are worth fine-tuning.
Like any ML problem, this is all dependent on your data, resources, and goal, so if you have time, do a sparse grid search first around the recommended values for each hyper-parameter and then a second, more specific search close to the optimal values found in the previous step.
The best parameter values should always be cross-validated if there is time for it, and at least a couple of combinations should be tried. For further information take a look at the following resources:
- 。
- 围绕这个问题的讨论令人敬畏。
有关机器学习和数据科学的更多资源,请查看以下资源库: 如何学习机器学习 !有关职业资源(工作、事件、技能测试),请访问AIgents.co——数据科学家职业社区&机器学习工程师 。
还有,你可以订阅我的邮箱列表在这里获取最新更新和独家内容:订阅邮箱列表。
非常感谢您的阅读,祝您愉快!**
GPU 上的随机森林:比 Apache Spark 快 2000 倍
原文:https://towardsdatascience.com/random-forest-on-gpus-2000x-faster-than-apache-spark-9561f13b00ae?source=collection_archive---------18-----------------------
闪电般的快速模型训练与急流
在 Unsplash 上由巴迪·阿巴斯拍摄的照片
声明:我是土星云的高级数据科学家——我们用 Python、Dask 和 RAPIDS 让企业数据科学变得快速而简单。
更喜欢看?点击查看视频演练。
随机森林是一种机器学习算法,因其鲁棒性、准确性和可扩展性而受到许多数据科学家的信任。该算法通过 bootstrap 聚合来训练许多决策树,然后通过聚合森林中树的输出来进行预测。由于其整体特性,随机森林是一种可以在分布式计算环境中实现的算法。可以跨集群中的进程和机器并行训练树,从而比使用单个进程显著缩短训练时间。
在本文中,我们探索了使用 Apache Spark 在 CPU 机器集群上实现分布式随机森林训练,并将其与使用 RAPIDS 和 Dask 在 GPU 机器集群上训练的性能进行比较。虽然 ML 世界中的 GPU 计算传统上是为深度学习应用程序保留的,但 RAPIDS 是一个在 GPU 上执行数据处理和非深度学习 ML 工作负载的库,与在 CPU 上执行相比,导致了巨大的性能加速。我们使用 3 亿个实例训练了一个随机森林模型: Spark 在 20 节点 CPU 集群上花费了 37 分钟,而 RAPIDS 在 20 节点 GPU 集群上花费了 1 秒。这比 GPU 快了 2000 多倍🤯!
曲速随机森林与 GPU 和急流!
实验概述
我们使用公开可用的纽约出租车数据集并训练一个随机森林回归器,该回归器可以使用与乘客接送相关的属性预测出租车的费用金额。将 2017 年、2018 年和 2019 年的出租车乘坐次数作为训练集,总计 300,700,143 个实例。
火花和急流代码可在 Jupyter 笔记本这里获得。
五金器具
Spark 集群使用亚马逊 EMR 管理,而 Dask/RAPIDS 集群使用土星云管理。
两个集群都有 20 个带有这些 AWS 实例类型的工作节点:
火花 : r5.2xlarge
- 8 个 CPU,64 GB 内存
- 按需价格:0.504 美元/小时
急流 : g4dn.xlarge
- 4 个 CPU,16 GB 内存
- 1 个 GPU,16 GB GPU 内存(英伟达 T4)
- 点播价格:0.526 美元/小时
土星云也可以使用 NVIDIA Tesla V100 GPUs 启动 Dask 集群,但我们选择了g4dn.xlarge
进行此次测试,以保持与 Spark 集群类似的每小时成本。
火花
Apache Spark 是一个开源的大数据处理引擎,内置于 Scala 中,带有一个 Python 接口,向下调用 Scala/JVM 代码。它是 Hadoop 处理生态系统中的一个主要部分,围绕 MapReduce 范式构建,具有数据帧接口和机器学习接口。
设置 Spark 集群超出了本文的范围,但是一旦集群准备好了,就可以在 Jupyter 笔记本中运行以下命令来初始化 Spark:
findspark
包检测 Spark 安装在您系统上的位置;如果火花包是可发现的,则不需要这样做。需要设置几个配置设置来获得高性能的 Spark 代码,这取决于您的集群设置和工作流。在这种情况下,我们设置spark.executor.memory
来确保我们不会遇到任何内存溢出或 Java 堆错误。
湍流
RAPIDS 是一个开源的 Python 框架,它在 GPU 而不是 CPU 上执行数据科学代码。这为数据科学工作带来了巨大的性能增益,类似于训练深度学习模型所看到的那些。RAPIDS 有数据帧、ML、图形分析等接口。RAPIDS 使用 Dask 来处理具有多个 GPU 的机器的并行化,以及每个具有一个或多个 GPU 的机器集群。
设置 GPU 机器可能有点棘手,但 Saturn Cloud 有用于启动 GPU 集群的预建映像,因此您只需几分钟就可以启动并运行!要初始化指向集群的 Dask 客户端,可以运行以下命令:
要自己设置 Dask 集群,请参考本文档页面。
数据加载
数据文件托管在一个公共的 S3 存储桶上,因此我们可以直接从那里读取 CSV。S3 存储桶将所有文件放在同一个目录中,所以我们使用s3fs
来选择我们想要的文件:
使用 Spark,我们需要单独读取每个 CSV 文件,然后将它们组合在一起:
使用 Dask+RAPIDS,我们可以一次性读入所有 CSV 文件:
特征工程
我们将根据拾取时间生成一些要素,然后缓存/保存数据帧。在这两个框架中,这会执行所有的 CSV 加载和预处理,并将结果存储在 RAM 中(在 RAPIDS 中是 GPU RAM)。我们将用于培训的功能有:
对于 Spark,我们需要将特性收集到一个Vector
类中:
对于 RAPIDS,我们将所有浮点值转换为 GPU 计算的float32
精度:
训练随机森林!
我们用几行代码为两个包初始化并训练随机森林。
火花:
急流:
结果
我们在 Spark (CPU)和 RAPIDS (GPU)集群上对纽约市出租车数据的 300,700,143 个实例训练了一个随机森林模型。两个集群都有 20 个工作节点,小时价格大致相同。以下是工作流程各部分的结果:
随机森林的火花与急流
Spark 是 37 分钟,而 RAPIDS 是 1 秒钟!
赢得胜利的 GPU!想想当你不需要为一个单次拟合等待超过 30 分钟时,你可以多快地迭代和改进你的模型。一旦您添加了超参数调整或测试不同的模型,每次迭代很容易增加到几个小时或几天。
需要看到才相信?你可以在这里找到笔记本,自己运行!
你需要更快的随机森林吗?
是啊!有了土星云,你可以在几秒钟内进入 Dask/RAPIDS 集群。Saturn 处理所有工具基础设施、安全性和部署方面的问题,让您立即开始使用 RAPIDS。点击在你的 AWS 账户中免费试用Saturn!
查看用 Dask 调节增压超参数
随机森林概述
原文:https://towardsdatascience.com/random-forest-overview-746e7983316?source=collection_archive---------14-----------------------
随机森林的概念概述
图 1:玛丽塔·卡韦拉什维利在 Unsplash 上的照片
由于 Keras、Tensorflow、Py-torch 和 Scikit-Learn 等令人惊叹的开源框架,机器学习和深度学习算法变得更加民主化,每个人都可以参与到下一代的建设中来。因此,我们不再需要用自己的代码从头开始构建任何算法,因为轮子已经发明出来了。然而,尽管我们现在可以实现算法,而不必深入了解幕后发生的事情,但我强烈认为,彻底了解我们的机器学习或深度学习算法在幕后做什么仍然是极其重要的,因为它使调试算法变得更加容易,这样我们就可以更好地解释模型的结果,并使用它来进行精心设计的实验,以找到我们可以用来优化模型的程序。
学习技术概念时可以采用的一个很好的框架被称为“自顶向下方法”。该领域的主要从业者/导师杰瑞米·霍华德和雷切尔·托马斯,fast . ai的创始人,不断地倡导这种方法,以至于我被激怒去读保罗·洛克哈特的书,书名为“数学家的哀叹”(他们经常用这本书来支持这种方法)。自上而下方法的思想是颠倒用于常规学习的传统方法(即在从事实际工作之前接受多年的理论教育),首先从事实际工作,然后再回来学习理论。
我发现这种方法有助于我建立一个关于特定技术方法的心智模型,因此当我访问关于该技术的理论时,我倾向于更加好奇为什么某些组件允许某些东西以这种方式工作。
在这篇博文中,我将分享对随机森林内部运作的概述。但是,我建议,如果您以前从未实现过随机森林,那么在阅读这篇概述文章之前,您可以这样做,并对超参数(训练前设置的参数)进行一些更改,以更好地了解它们如何影响算法的输出。
由于有大量非常广泛的资源覆盖随机森林,这将有助于开始,我没有准备自己的笔记本来浏览,尽管如果有人要求我这样做,我会这样做——在 kurtispykes@gmail.com 留下回复或给我发电子邮件。相反,我链接了一个资源,在我学习 Random forest 的时候,我发现这个资源非常有用。
在《Fast.ai 程序员机器学习入门》的第 1-rf 课是一门 MOOC,杰瑞米·霍华德使用 Kaggle Bluebook for 推土机数据集穿越随机森林。我相信克隆这个库并通过笔记本唤醒真的很有用(即使没有视频)。我的建议是改变算法中的东西,直到你破坏了它(一旦你破坏了它就试图修复它),这样你就可以直观地理解改变一个特征是如何影响模型预测的结果的。
附注:使用此链接下载用于此笔记本的数据集。
[## 法斯泰/法斯泰
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/fastai/fastai/tree/master/courses/ml1)
在随机森林的地基上推车
为了理解随机森林算法的内部工作原理,我们必须首先对决策树有一个直观的了解。决策树是一种高度可解释且重要的预测模型,能够执行分类和回归任务——决策树是最初用于算法的经典名称,但是在更现代的教科书和上下文中,决策树可能被称为 CART 算法,这是表示分类和回归树的首字母缩写词,因为该算法能够进行回归和分类。
虽然算法有看起来相当复杂的趋势,但手推车一直存在于我们的日常生活中。事实上,当人们了解手推车是如何工作的,并看到它与我们用来做决定的思维过程有多么相似时,他们仍然会感到惊讶。例如,如果我在考虑周末做什么活动,在对一项任务得出一些结论之前,我会考虑许多特征/变量。首先,我可能会考虑是否会下雨;如果周末下雨,我可能会决定呆在家里看书,但是如果不下雨,我会考虑切尔西俱乐部是否会在周末进行比赛。如果切尔西在比赛,我会问他们是在主场还是客场比赛;如果切尔西主场比赛,我会去看比赛,但是如果他们客场比赛,我会继续问问题,直到我决定周末做什么。
图 Titanic 数据集上使用的决策树。【来源:维基百科】
这种类似流程图的结构就是手推车的工作原理。从技术上来说,CARTs 试图通过提供最大信息增益的划分来划分协变量空间。因为我认为有时解释是不必要的复杂,所以我将其解释为,CARTs 试图将数据分割成子集(称为节点),树中的第一个节点称为根节点,进行二进制分割的节点称为内部节点,因此剩下的不进行分割的节点称为叶节点,它们最好地分离了结果。
为了在每个节点上进行二进制分割,该算法必须找到这样的特征(以及特征阈值,如果特征值不是二进制的话),该特征的分割最好地分离了类,因此命名为信息增益,因为我们获得了关于最终结果的最多信息。为了确定“最佳”分割,定义了一个成本函数,例如用于分类任务的基尼系数或熵(实际上,你决定优化哪一个并不重要)和用于回归任务的 RMSE (均方根误差),目的是在特征空间中找到使这些标准最小化的分割,从而在每一步产生最佳分割。此外,CARTs 也被称为贪婪算法,因为在树的每一步,该算法都试图进行最优分割,以便达到全局最优解。
图 sklearn 中使用的杂质公式。[ 来源:Stacey Ronaghan—sci kit 中的决策树、随机森林和特性重要性的数学-learn 和 Spark
没有正则化,更好地称为树结构中的修剪,树将在每个节点递归地分裂,直到每个节点,直到每个叶节点只剩下一个结果。虽然在我们决定周末应该做什么活动的场景中,这很好,因为我们总是会对我们应该做什么活动得出结论,但在应用机器学习中,这是一个主要问题,因为算法无法归纳(这是应用机器学习的全部目的)到看不见的实例,因为它只是记忆训练数据,这被称为过度拟合。
有各种剪枝方法来对抗 CARTs 泛化失败,但是这些技术经常导致训练期间的准确度降低和算法复杂度降低。使用多个决策树并取树的平均值(回归)或取多数投票(分类)很快成为解决这个问题的方法,并由此诞生了随机森林。目标是保持树的复杂性,同时保持训练数据的高准确性,并允许算法可以很好地推广到看不见的实例。
购物车的伪代码(无调整)
1) Define a cost function i.e. Gini index or Entropy (Classification) RMSE or MAE(Regression) 2) Perform binary split on the feature that minimise cost function 2) Repeat step 2 until you reach leaf node in all branches
随机森林概念
图 5:汤米·克兰巴赫在 Unsplash 上拍摄的照片
花点时间想想一片森林。一片森林是由许多独立的树木组成的。当我们将一组项目作为一个整体而不是一个个来识别时,我们称之为“集合”,因此森林是由大量单独的树组成的集合(当我们分解随机森林算法时,请记住这一点)。
随机森林是 Leo Breiman 在 2001 年开发的一种集成方法(它将多个决策树预测器分组)。在[2]中,Breiman 陈述了“树分类器森林的泛化误差取决于森林中个体树的强度以及它们之间的相关性”。也就是说,随机森林使用一种称为 bootstrap aggregation 的有效方法,以及随机子空间 method⁴来生长单个树,以实现非常强大的聚合预测器,能够进行分类和回归,比单个决策树具有更好的泛化误差。
引导汇总(打包)
Bootstrapaggregating*或者简单地说,Bagging,是一种用于生成预测器的多个版本并使用这些预测器来实现聚合预测器的方法[3]。通过制作 bootstrap 复制——通过替换从训练集中随机采样实例——并将此作为新的 bootstrap 数据作为训练集,随机性被引入到每个预测器中。请注意,当实例被随机采样到引导集时,它们将被替换回原始训练集,因此某些实例可能会在训练预测器的引导训练集中出现多次。此外,输入每个预测模型的每个引导样本具有相同的分布。*
在这种情况下,聚合预测器是我们的随机森林,当我们解决回归型问题时,它输出每个决策树预测的平均值,我们试图预测一个连续的结果,如房子的价格。另一方面,当我们在进行分类任务时——我们试图预测一些离散的标签,如一幅图像是否是一只猫——我们的随机森林输出每个模型的相对大多数预测。
图 6:装袋示例。【来源:叶达鑫·纳伊克 - 装袋:通过视觉进行机器学习。#1:什么是“打包”集成学习? ]
随机子空间方法
在[4]中,Kam Ho Tin 提出了随机子空间方法,通过降低集成中预测模型之间的相关性,在不牺牲训练数据准确性的情况下,提高决策树分类器的泛化准确性。这种方法在某种意义上类似于 bagging,即在具有替换的特征的随机样本上训练集成中的每个预测模型,而不是在所有特征上训练模型。该技术允许预测者不将其全部注意力集中在看起来比其他特征更具预测性的特征上。
改善泛化误差
上面提到的技术被引入到随机森林中,以降低每个预测器的相关性,用方差换取一些偏差。尽管每个单独的决策树本质上都是过度拟合的(每个树在训练数据上单独获得 100%的分数),但是用于构建每个树的训练数据和特征是不同的。先前调整的结果是决策树模型的相关性较低,并产生不同的错误,从而导致模型在正确性上互补。
改善随机森林的泛化误差的另一种方法是改善每个个体树的强度。通过构建具有强预测准确性的树(降低树的错误率),我们降低了随机森林的整体错误率。
减小 m 会降低相关性和强度。增加它会增加两者。介于两者之间的是 m 的“最佳”范围——通常相当宽。这是随机森林稍微敏感的唯一可调参数。
随机森林中一个非常有用的机制叫做 OOB 错误。这是一种用于评估模型中错误率的技术,该模型使用引导聚合(Bagging)来获得用于训练的引导样本。OOB 是通过仅使用未在构建树的引导示例中选择的实例进行预测而得到的。
图 7:米洛·米洛耶格在 Unsplash 拍摄的照片
随机森林的伪代码
1) For a training set of length N, sample N instances at random with replacement. 2) Grow a tree on the bootstrap training set using a specified number of random features 3) Repeat step 1 and 2 for the set number of estimators. 4) Average predictions or take majority vote (depending on type of task)
随机森林是一种非常强大集合方法。虽然他们可能不再赢得 Kaggle 比赛,但在现实世界中,0.0001 的额外准确性并不重要(在大多数情况下),随机森林是一个非常有效的开始实验的模型。
P.S. Kaggle 被认为是“数据科学之家”,平心而论,不难看出这是为什么。有一个很好的功能叫做笔记本,人们可以在里面分享他们的代码。如果你只是想运行一些算法,这是一个很好的开始。一个好主意是改变一些功能,并试图击败他们的分数,我发现这真的有助于学习。
基于你对随机森林了解,我推荐的其他帖子有:
- Eryk Lewinson - 以随机森林为例解释特征重要性
* [## 以随机森林为例解释特征的重要性
了解 Python 中最流行的确定要素重要性的方法
towardsdatascience.com](/explaining-feature-importance-by-example-of-a-random-forest-d9166011959e)
- 将科尔森 - 随机森林简单解说
[## 随机森林简单解释
用直观的例子理解随机森林
medium.com](https://medium.com/@williamkoehrsen/random-forest-simple-explanation-377895a60d2d)
- 饶彤彤 - 了解随机森林
[## 了解随机森林
该算法如何工作以及为什么如此有效
towardsdatascience.com](/understanding-random-forest-58381e0602d2)
- Stacey Ronaghan-sci kit-learn 和 Spart 中决策树、随机森林和特征重要性的数学运算
[## Scikit-learn 和 Spark 中决策树、随机森林和特征重要性的数学
介绍
towardsdatascience.com](/the-mathematics-of-decision-trees-random-forest-and-feature-importance-in-scikit-learn-and-spark-f2861df67e3)
- 叶达鑫·纳伊克 - 装袋:通过视觉进行机器学习。#1:什么是“打包”集成学习?
[## 装袋:通过视觉进行机器学习。#1:什么是“打包”集成学习?
作者叶达鑫·纳伊克和阿尔琼·乔哈里
medium.com](https://medium.com/machine-learning-through-visuals/machine-learning-through-visuals-part-1-what-is-bagging-ensemble-learning-432059568cc8)
- Jason Brownlee - 机器学习的分类和回归树
[## 机器学习的分类和回归树-机器学习掌握
决策树是预测建模机器学习的一种重要算法。经典的决策树…
machinelearningmastery.com](https://machinelearningmastery.com/classification-and-regression-trees-for-machine-learning/)
参考文献:
Breiman,l .,J. Friedman,R. Olshen 和 C. Stone。(1984):分类和回归树。
布雷曼,利奥。(2001).随机森林
布雷曼,利奥。(1996).打包预测值
何天锦,⁴(1995)。随机决策森林*
随机森林——决策树的集合
原文:https://towardsdatascience.com/random-forests-an-ensemble-of-decision-trees-37a003084c6c?source=collection_archive---------10-----------------------
这就是决策树组合成随机森林的方式
菲利普·兹恩泽维奇在 Unsplash 上的照片
随机森林 是当今最强大的机器学习算法之一。它是一种监督的机器学习算法,可用于分类(预测离散值输出,即一个类)和回归(预测连续值输出)任务。在本文中,我描述了如何使用流行的 Iris 数据集将它用于分类任务。
随机森林的动机
首先,我们讨论决策树算法的一些缺点。这将激励你使用随机森林。
- 对训练数据的微小更改会导致树结构的显著变化。
- 它可能会有过度拟合的问题(模型非常适合训练数据,但无法对新的输入数据进行推广),除非您调整 max_depth 的模型超参数。
因此,与其训练单个决策树,不如训练一组决策树,它们一起构成一个随机森林。
随机森林如何在幕后工作
随机森林背后的两个主要概念是:
- 群体的智慧——一大群人集体起来比单个专家更聪明
- 多元化——一组不相关的树
随机森林由一组单独的决策树组成。因此,该技术被称为集成学习。一大群不相关的决策树可以产生比任何单个决策树更准确和稳定的结果。
当您为分类任务训练随机森林时,您实际上训练了一组决策树。然后,您获得所有单个树的预测,并预测获得最多投票的类。尽管一些单独的树产生错误的预测,但是许多树可以产生准确的预测。作为一个群体,他们可以走向准确的预测。这就叫群众的智慧。下图显示了幕后实际发生的情况。
作者图片
为了保持单棵树之间的低相关性(高多样化),算法会自动考虑以下事项。
- 特征随机性
- 打包(引导汇总)
特征随机性
在一个普通的决策树中,当它想要分割一个节点时,该算法从所有特征中的中搜索最佳特征。相比之下,随机森林中的每棵树都从随机特征子集中搜索最佳特征。当在随机森林中种植树木时,这会产生额外的随机性。由于特征的随机性,随机森林中的决策树是不相关的。
作者图片
打包(引导汇总)
在随机森林中,每个决策树都在训练集的不同随机样本上进行训练。当用替换完成采样时,该方法被称为打包(自举聚集)。在统计学中,带替换的重采样被称为自举。bootstrap 方法减少了决策树之间的相关性。在决策树中,对训练数据的微小更改会导致树结构的显著变化。bootstrap 方法利用这一点来生成不相关的树。我们可以用下面的简单例子来演示自举方法。同样的事情也适用于随机森林。
假设我们有一个由 10 个观察值组成的训练集,从 1 到 10 进行编号。在这些观察结果中,我们使用 bootstrap 方法进行采样。我们想考虑:
- 样本大小 —在机器学习中,通常使用与训练集相同的样本大小。在本例中,样本量为 10。
- 样本数量 —等于随机森林中决策树的数量。
为了创建第一个样本,我们从训练集中随机选择一个观察值。假设这是第五次观察。这个观察结果被返回到训练数据集中,我们重复这个过程,直到我们得到整个样本。在整个过程之后,想象我们用下面的观察制作第一个样本。
样本 _1 = [5,4,6,6,5,1,3,2,10,9]
然后我们用这个样本训练一个决策树。由于替换,一些观察值可能在样本中出现更多次。另外,请注意,有些观察值在样本中至少不会出现一次。这些观察结果被称为【OOB】观察结果。第一个样本的 oob 观测值为:
oob_1 = [7,8]
样本 1 对应的决策树在训练过程中从来看不到那些 oob 的观测值。因此,这组 oob 观察值可以用作该决策树的验证集。我们可以通过平均每个决策树的 oob 评估来评估整个集合。这被称为 非现金评估 ,它是交叉验证的替代方案。
让我们创建另一个示例。
Sample_2 = [5,4,4,5,5,1,3,2,10,9]
OOB _ 2 =【6,7,8】
同样,我们创建的样本数量等于随机森林中决策树的数量。
作者图片
随机森林中的要素重要性
随机森林的另一个巨大优势是,它允许您根据在训练阶段计算的分数,了解每个特性的相对重要性。为此,he Scikit-learnRandomForestClassifier提供了一个名为feature _ importances _的属性。这将返回总和为 1 的值的数组。分数越高,特性越重要。分数是根据基尼系数计算的,基尼系数衡量的是分割的质量(基尼系数越低,分割越好)。基尼系数平均下降幅度较大的分割特征被认为更重要。
通过查看要素的重要性,您可以决定删除哪些要素,因为它们对构建模型的贡献不足。这很重要,原因如下。
- 移除最不重要的特征将增加模型的准确性。这是因为我们通过移除不必要的特征来移除噪声
- 通过删除不必要的功能,您将避免过度拟合的问题。
- 较少的功能也减少了训练时间。
理论够了!让我们动手编写一些 Python 代码,为 Iris 数据集训练一个随机森林。
关于虹膜数据集
Iris 数据集(此处下载)有 150 个观察值和 4 个数字属性。目标列(物种)由每个观察的类组成。有 3 类(0-setosa,1-versicolor,2-virginica)。
虹膜数据集的前 5 行(图片由作者提供)
数据集没有缺失值,所有要素都是数值型的。这意味着数据集无需任何预处理即可使用!
虹膜数据集信息(图片由作者提供)
为 Iris 数据集训练随机森林分类器
运行以下代码后,您将获得 0.97 的模型准确性分数。
我们的随机森林里有 100 棵树。这是因为我们设置了 n_estimators=100 。因此,自举样本的数量也是 100。
开箱(oob)评估
在随机森林中,每个决策树都是使用观察值的自举子集来训练的。因此,每棵树都有一个单独的子集【OOB】观察值。我们可以使用 oob 观察值作为验证集来评估我们的随机森林的性能。
该值接近模型准确度分数 0.97。
可视化特征重要性
通过查看特征重要性,我们可以决定删除 【萼片宽度(cm)】特征,因为它对制作模型的贡献不足。
最后的想法
决策树分类器和 RandomForestClassifier 等基于树的模型是分类任务中最常用的机器学习算法。如果要将模型解释为“为什么模型预测的是那种类”,最好使用普通的决策树算法,而不是随机森林。这是因为单个决策树很容易解释。但是请记住,正如我们前面讨论的,决策树算法有一些缺点。
使用随机森林算法时,请按照指定的顺序执行下列操作。
- 首先,通过处理缺失值并将分类值转换为数值来预处理数据。
- 然后,将数据集分为训练测试和测试测试,不要将相同的数据用于训练和测试。这样做可以让模型记住数据,而不是学习任何模式。
- 如下所述,在 RandomForestClassifier 中设置模型超参数。永远要考虑算法的性能和训练速度之间的平衡。例如,如果您在森林中包含更多的树,则性能较高,速度较慢。
- 然后训练您的模型并可视化特征重要性。
- 移除不太重要的特征(如果有),并使用所选特征重新训练模型。
- 使用测试集测试您的模型,并获得准确性分数。
选择模型超参数
- n_estimators: 森林中树木的数量。默认为 100。您可以使用与训练集中的观察次数相等的数字。
- max_depth: 树的最大深度。默认值为无。您可以首先训练一个决策树分类器,并为 max_depth 执行超参数调整。通过交叉验证和网格搜索获得最佳值后(我已经这样做了,并获得了值 3),可以将该值用于 RandomForestClassifier 的中的 max_depth 。
- bootstrap: 默认为真。使用此默认值执行引导抽样以获得不相关的树。
- oob_score: 默认为 False。如果您要执行袋外(oob)评估(交叉验证的替代方法),请将此项设置为 True。
要访问 RandomForestClassifier 的 Scikit-learn 官方文档,只需在从 sklearn . ensemble import RandomForestClassifier 导入类 后执行help(RandomForestClassifier)。
感谢阅读!
本教程由Rukshan Pramoditha,数据科学 365 博客作者设计创作。
本教程中使用的技术
- Python (高级编程语言)
- 熊猫 (Python 数据分析与操纵库)
- matplotlib (Python 数据可视化库)
- seaborn (Python 高级数据可视化库)
- Scikit-learn (Python 机器学习库)
- Jupyter 笔记本(集成开发环境)
本教程中使用的机器学习
- 随机森林分类器
2020–10–29
随机漫步、布朗运动和随机微分方程——直觉
原文:https://towardsdatascience.com/random-walk-brownian-motion-and-stochastic-differential-equations-the-intuition-3484413503e0?source=collection_archive---------8-----------------------
马库斯·温克勒在 Unsplash 上的照片
最近我一直在考虑将我的研究工作从常微分方程扩展到随机微分方程。最初我认为这两者不应该太不一样,但事实证明我错了。甚至使用的微积分也不一样。
在读了格雷戈里·s·奇里基安的《随机模型 、信息论和李群 这本书的几章后,我仍然无法理解其中的概念,因为毕竟我不是一个数学人。幸运的是,麻省理工学院开放式课程拯救了我,因为讲师 Choongbum Lee 很好地解释了用于处理 SDE 的数学背后的直觉。这篇博客文章不会是一个数学教程,而是一个从简单的随机漫步到随机微分方程的直观演练,借用麻省理工学院开放课程的见解和我自己的直觉。为了真正掌握这个主题,人们仍然需要通过推导和问题来工作,但我希望这篇文章能让人们有一个轻松的开始。
1.简单随机漫步
让我们从一个简单的离散时间的整数的 1D 随机漫步开始。
图 1:作者制作的 1D 随机漫步
让移动点在时间 t 的位置为 Xt 。由于点在离散时间内移动, t 只能取整数值(即 0,1,2,…)。整数行上一个点的随机游走从 X0 = 0 开始。在迈出每一步之前,为了决定向左还是向右移动,我们抛一枚公平硬币(两边落地的概率相等)。如果它给我们正面,那么点向右移动,否则,它向左移动。
形式上,我们可以把点在 t=k 的位置写成:
等式。1:随机漫步中的位置
其中易可视为第步到第步之前抛硬币的结果,只能取+1 或-1 的值。我们假设所有的抛硬币都是独立的事件。
我们感兴趣的是找到点在时间 t 的位置。很明显,不可能精确定位圆点的确切位置,因为每一次移动都是由概率事件决定的(圆点的轨迹是不确定的),因此使用概率分布来描述圆点在时间 t. 的位置更加自然
图 2:作者制作的随机漫步树
我们可以用一棵树来想象这个运动。图 2 中的树应该很容易解释,但如果不是这样,横轴是点移动的整数线,纵轴是离散时间线,每个红点下面的数字是点在特定位置和时间的概率。在 t= 0 点是 0,因此它的概率是 1。剩下的概率应该很容易算出来。不难看出,如果我们将每一行(每一时间步)上的概率的分母分解出来,剩下的数就形成了帕斯卡三角形,即对于 t= 0,我们有 1,对于 t =1,我们有 1,1,对于 t =2,我们有 1,2,1,对于 t =3,我们有 1,3,3,1,等等。并且由于帕斯卡三角形确定了二项式展开的系数,并且在每个时间步长上所有概率的总和是 1,所以应该直观的是,点的位置的概率分布应该在一定程度上遵循每个时间步长上的二项式分布。
数学上,对于 t=n ,点位于 X=k 的概率为:
这简化为:
等式。2:随机漫步的概率分布
其中第一个乘法项只是为了强调这样一个事实,即当 n 和 k 具有不同的奇偶性时,概率为零(这可以从图 2 中容易地验证。)
这实际上是二项分布的一种特殊情况,其形式为
等式。3:二项式分布
在我们的例子中,p = 0.5。我们的分布与一般二项式分布之间的唯一区别是:( 1)在从 n 中进行选择时,我们通过使用( n-k )/2 来加强围绕 k= 0 的对称性,以及(2)通过考虑奇偶性,总概率被“标准化”为 1。我用引号表示“正常化”,因为总概率为 1 是随机漫步的自然结果,而不是人为构造的。
我对 300 个时间步长的概率分布的演变进行了可视化:
图 3:作者制作的随机游走概率分布的演变
这一切都说得通。当 t =0 时,分布在位置 0 处只有概率 1。随着时间的推移,概率分布越来越分散。基于可视化,有几点需要注意:
(1) 很明显,这个点在任何时候最可能的位置还是在中心(如果 t 是偶数则为 0,如果 t 是奇数则为 1 和-1)。结合分布对称的事实,点在任意时刻的期望位置为 0。方程描述的典型二项式分布的方差。3 是 np(1-p) ,如果直接应用到我们的分布中,就会得到 n/4 。然而,这是不正确的,因为我们的分布是在区间[ -n,n ]上定义的,因此它被拉伸了 2 倍。因此它的方差是n。这非常重要,因为我们现在知道分布的方差等于点移动的时间。这种认识自然会引出下一个关于布朗运动的讨论。
(2) 这是而不是一种概率密度分布,因为状态空间(整数)是离散的而不是连续的。然而,这种概率分布的形状非常类似于高斯分布。我们很快就会看到,高斯分布实际上是二项式分布的“极限”。
(3) 如果进行点移动 n 步的实际实验(例如图 1 中的实验。是点移动 1000 步的位置)结果可能很难符合我们的概率分布。然而,如果相同的实验重复进行 m 次,其中 m 非常大,那么根据大数定律,点的位置的统计特性被我们的概率分布很好地捕获。
但是我仍然不认为我的解释是“直观的”,尽管有非严格的数学限制,但仍然不清楚简单的随机漫步意味着什么,所以我决定通过更好的可视化再尝试一次:
图 4:作者制作的随机漫步取样
概率分布在图 4 中显示为表面图(由于奇偶性,我没有去除 0 概率,因此表面看起来粗糙),红线是简单随机行走的轨迹。图 3 可以被认为是这些图在时间上切片的横截面,而图 1 可以被认为是只看整数线上的点而忽略其余部分。我模拟了四次,我们可以看到,概率分布总是以相同的方式随时间推移,但轨迹在所有四种情况下都是不同的。
这就是简单随机行走的酷之处,轨迹的统计属性总是及时保留,但要获得实际的轨迹,需要在每个时间步对某个位置进行采样。换句话说,当我们进行观察时,概率分布坍缩成一条单一的轨迹(我喜欢把这想象成宏观世界中海森堡的不确定性原理)。随着我们观察到越来越多的轨迹,根据大数定律,这些轨迹的统计特性将收敛到真实概率分布。
图 5:作者制作的图 4 的俯视图
如果我们从 z 轴俯视图 4,我们将看到图 5 中左侧的动画。右手边的动画绘制了概率的对数,这样更容易看到。所有空格的概率都是 0,很明显最大概率总是在整数行上的 0。
图 6:橙色线是标准差;白线是作者制作的方差
图 6 显示了另一个重要的含义。既然我们知道时间 t 的方差是 t ,那么时间 t 的标准差就是 sqrt(t) 。换句话说,我们知道轨迹不会偏离中心 1 个标准差太远,因为这个范围覆盖了大约 68.2%的可能轨迹。这在图 6 中是显而易见的,因为轨迹(红线)没有远离由标准偏差(橙线)包围的集合。这个例子展示了随机漫步模型预测能力的一个方面。
2.布朗运动
简单随机行走是一个离散空间(整数)和离散时间模型,而布朗运动是一个连续空间和连续时间模型,简单随机行走可以很好地激发布朗运动。我将解释空间和时间是如何从离散变为连续的,这基本上将简单的随机行走变成了布朗运动。前面描述的二项式分布 p(k,n) 会变成高斯分布,这个分布的时间演化会变成非常有趣的东西。
离散空间到连续空间
图 7。离散空间到连续空间,由作者制作
取整数行,将每个整数值 k 除以一个固定的数 N. ,然后我们将实数放入以每个 k/N、为中心的仓中,每个仓的宽度相等。随着 N 趋近于无穷大,离散概率分布 p(k,n) 变成了概率密度函数,任意时刻点的位置变成了连续的随机变量。换句话说,如果我们让点每次移动时都走很小的步,当它的步长接近 0 时,我们得到一个连续的概率分布(即,我们现在有一个与实数线上的所有点在合理的时间间隔内相关联的概率)。
此外,如果 n,点所走的总步数很大,则二项式分布可以很好地近似为均值和方差为 0 的正态分布 n/N 。分母 N 是将空间除以因子 N 的结果,这实质上减少了每移动一步的方差增加。这里是用斯特林公式的一个证明。事实上,当 n 接近无穷大时,正态分布是二项式分布的“极限”。在这个极限下,概率分布将被“压扁”(想象图 3 中有一个非常大的 t 。)密度函数将简单地变成范围[- n , n 内的均匀分布。
离散时间到连续时间
如果我们使用相同的技巧,将离散时间 n 除以固定的数 N ,将离散时间步长 n 替换为 t=n/N ,随着 N 接近无穷大,离散时间变成连续时间。正态分布的方差简单来说就是 t ,它是一个实数。
现在,希望从随机漫步到布朗运动的转变是有意义的。我解释了简单的随机行走如何在空间和时间上被无限分割成布朗运动,这也是大多数教科书的做法。
图 8:作者制作的随机行走时间表达式
然而,我也喜欢反过来想:如果我们无限放大布朗运动,我们看到的是随机行走。如果我们重新观察如图 8 所示的简单随机行走的时间进程,随着时间和空间尺度都变得非常大,人们可以很容易地将离散路径(显示为红线)想象为连续路径,因为每个增量都非常小,以至于当与整个时间和空间相比时,人们可以说在任何时间轨迹上的每个点都被定义在真实的线上。概率分布也会变得平滑。假设钟形离散分布变得平滑,这将给出高斯分布。
植物学家罗伯特·布朗于 1827 年首次描述了布朗运动。在显微镜下,他观察到浸入水中的花粉看似随机的运动。直到将近 80 年后,阿尔伯特·爱因斯坦发表了一篇论文,建立了布朗运动背后的理论。爱因斯坦将花粉描述为不断受到水分子的轰击。每一次撞击都发生在很短的时间内,并使花粉发生微小的移动。在这个意义上,花粉在分子尺度上的运动可以被认为是发生在离散时间(每次花粉被水分子击中)和离散空间(花粉每次被击中时移动一些微小的固定距离)。
版权所有远藤越修
形式化布朗运动
布朗运动,麻省理工学院开放式课程
定理 2.1 形式化了我们已经讨论过的关于布朗运动的内容:(I)表示点总是从 0 开始它的路径。(ii)表示给定点在时间 s 和 t,0≤s < t. 的两个位置,这两个位置之间的差的分布遵循均值和方差为 0 的正态分布 t-s. (iii)是不言自明的。
这个定义其实一点都不直观。通常“好的”函数是在确定性意义上定义的,或者可以说那些函数只定义了均值,均值由函数输入参数化,其方差假定为 0。但布朗运动有点相反:我们让均值为 0,只定义它的方差,它是随时间参数化的。因为布朗运动在时间上是连续的,所以我们可以在无限小的时间或空间片段上观察到它的行为。通过构造,这些微小的片段不是一个单一的值,而是一个概率分布。这种构造将赋予布朗运动许多有趣但怪异的事实和性质,其中许多是非常反直觉的。为此,我将向读者推荐麻省理工学院的开放式课程。我将只列出继续讨论 SDEs 所需的几个例子。
- 布朗运动 B(t) 是一个定义明确的连续函数,但它无处可微 ( 证明)。直觉上,这是因为布朗运动的任何样本路径都随时间变化太多,或者换句话说,对于该函数的任何无穷小的片段,其方差都不会收敛到 0。直接结果就是,我们不能在 B(t) 上使用经典微积分。dB(t)/dt 这样的表达式毫无意义!
麻省理工学院开放式课程的二次变异
- 布朗运动有二次变差。这一点非常重要,并促成了一种称为it——微积分的解决方法,用于对布朗运动进行微积分运算。直观地说,这意味着给定某个时间间隔[0, T ,如果我们把它分成许多不重叠的段。当最大的时间段接近 0 时,对应于这些时间段的路径增量的方差的极限是 T 。二次变分的一个重要结果是 (dB) = dt。这里有一些很好的证明。
等式。4:微积分中的微分
等式。5:微积分中的积分
- 伊藤清发明的微积分提供了一种用布朗运动做微积分的方法。微积分中的微分:将布朗运动包裹在另一个可微分的函数中,可以执行稍微修改的微积分版本。它是这样工作的:给定一个可微函数 f(x) ,如果它把 B(t) 作为它的输入 x ,那么我们可以根据方程写出 df 。4,这被称为 its 的引理(据称是历史上被引用最多的引理)。对于经典微积分,我们有 df = (∂f/∂x)dx ),所以它的引理实际上只有一项不同。这实际上是在泰勒级数展开中保留第 2 和第阶项的结果,以便说明布朗运动的高方差。最后一项 dt 其实是来自 (dB)。it \u Calculus 中的积分:关于 dB 的积分与经典微积分的不同之处在于,当写成黎曼和时,Itō integral 取每一段中最左边的值(如方程式中 Ht(i-1)所示)。5)而经典积分可以在每个区间内选择任意值。
我在这里的笔记是非常草书的,所以我强烈建议读者观看这个讲座来看看一些微积分的例子用法。
3.随机微分方程
现在有了微积分,我们可以解含有布朗运动的微分方程吗?
首先,有人可能会问这样一个微分方程看起来如何,因为表达式 dB(t)/dt 被禁止了。我们知道 ODEs 可能具有以下形式:
等式。6:颂歌
其中 X 的时间变化率由函数 f(.,.)。如果我们让布朗运动中的每个微小增量 dB 增加到沿着 X,的轨迹的微小变化 dX 上,我们可以得到:
我们可以通过将布朗运动乘以另一个函数来增加其复杂性:
等式 7。SDE
等式。7 给出了 SDEs 的形式。 dB 这里通常指的是高斯白噪声。使用符号 μ 和 σ 并不是没有原因的。 μ(t,X)dt 通常被称为漂移项,它可以被视为 X 在任意时刻的期望位置,而 σ(t,X)dB 通常被称为扩散项,它可以被视为 X 在任意时刻的位置的方差(随着时间的推移,这个项在所谓的扩散过程中展开了类似于图 3 的概率分布)。
- 如果 μ (。,.)始终为 0 且 σ (。,.)总是 1,那么 X 本身遵循布朗运动。
- 如果 σ (。,.)是 0,那么方程 7。成为方程中的颂歌。6.换句话说,没有添加布朗运动,X 只是根据其动态 μ 漂移,方差为 0。
ODEs 和 SDE 在很多方面都很相似,好在SDE 也有存在唯一性只要 μ (。,.)和 σ (。,.)是“好”的函数。
求解一个常微分方程意味着描述一个随时间变化的轨迹,而求解一个 SDE 意味着描述一个随时间变化的轨迹的统计特性。换句话说,前者仅求解方差始终为 0 的轨迹的期望值,而后者需要描述作为漂移结果的均值和作为扩散结果的方差。不幸的是,SDE 大多数时候没有解析解,就像(也许比)ODEs 一样。这里有两个求解解析解的 SDE 的例子。
更多的时候采用数值方法来求解随机微分方程。但是与数值求解微分方程的方式有一些主要的不同:
- 有限差分法 : 通过将时间离散成大小为 h 的小步长,将步长和 dX 的乘积依次加到初始条件上,可以近似得到 X 的轨迹。最简单的例子就是欧拉法。通过从一些初始条件近似一个轨迹,我们本质上是用 SDE 采样一个路径。
- 蒙特卡洛模拟 :由于 SDE 的概率性质,大多数时候只对其一条路径进行采样并不能告诉我们太多关于该系统的信息。利用蒙特卡罗模拟,我们从一些初始条件重复采样 SDE 的路径,并且根据大数定律,采样轨迹的统计特性(例如,均值和方差)将收敛到真实特性。蒙特卡罗模拟通常与有限差分法结合使用,后者模拟每次采样时的轨迹。
- 树形图:由于布朗运动是简单随机行走的极限。如果我们把布朗运动的时间分割成微小的片段,我们可以让这个点在每一个时间片段中以适当选择的步长做微小的随机行走。与前两种方法相比,这种方法的使用频率较低,但通常很容易通过手工操作来了解 SDE 的统计特性。
布朗运动导致许多反直觉的结果,常微分方程也是如此(例如,当混沌时,可以生成位于分形上的轨迹)。毫不奇怪,这两者的融合会产生更奇怪、更难以理解的东西。因此,更应该为这些概念建立直觉。浏览定义、引理、证明和命题是最重要的,但我个人认为直觉使它成为一个更快的过程。
附注:我仍在对一些 SDE 进行实验。如果我得到任何酷的东西,我会更新 GIFs 图片。
我的动画的所有代码可以在我的 GitHub 中找到。
参考文献
[1]麻省理工学院开放式课程。“数学中的主题及其在金融中的应用”https://OCW . MIT . edu/courses/Mathematics/18-s096-Topics-in-Mathematics-with-application-in-Finance-fall-2013/index . htm
[2]奇里基安,格雷戈里 S. 《随机模型,信息论和李群,第 1 卷》施普林格,2009
运动中的随机性
原文:https://towardsdatascience.com/randomness-in-sport-6e60c6132838?source=collection_archive---------58-----------------------
为什么赢得超级碗的球队比英超多?
有些人比其他人幸运。Izaac Crayton ( @icrayton )在 Unsplash 上的照片
被诅咒的
让我们从 2012 年元旦英超联赛的 Wearside 开始。桑德兰在对阵曼城的比赛中,大部分时间都在自己的禁区外安营扎寨,抵御曼城的猛烈进攻。与对手的 11 次射门相比,他们只有 3 次射门命中目标,并且在整个 90 分钟内控球率只有可怜的 41%。他们的后卫一直在追逐影子——要不是蓝军前锋埃丁·哲科挥霍无度,他们早就消失不见了。
然而,不知何故,比分一直保持到第 93 分钟。桑德兰从一次失败的城市进攻中夺回了控球权,他们的中场突破了中线,这似乎是比赛中的第一次。在这场可能是有史以来最慢的英超联赛反击中,夏羽·塞斯格农和智东元交换了几个快速传球,韩国前锋最终绕过守门员乔·哈特射门得分。在你的比赛中进球,最终比分 1-0 桑德兰。
不要介意创造的机会或投篮的缺乏。或者说,那座城市控制了控球权,与桑德兰的一个角球相差 10 个角球。蓝军空手而归,而桑德兰全取三分。
尽管赛后回放显示嵇的进球尽管越位但仍被误判。
由随机性推动
开篇描述了一个被所有运动爱好者又爱又恨的概念——随机性 。在体育运动中,没有什么是确定的——如果是,最好的球员和球队将赢得每一场比赛,它将很快失去作为奇观的吸引力。随机性是节目继续下去的动力。但这意味着什么呢?
简单来说,随机性是一种缺乏组织性或可预测性的状态或模式。一个例子是在一个高度危险的地区,也许是在一条有急转弯的路上,或者在一个繁忙的路口,对车祸数量进行抽样。你知道这些地区发生事故的比例比其他地区高,但是你知道下一次事故发生的确切时间吗?事故发生在每天早上 9 点 17 分,还是在钟敲 12 点的时候?谁也说不准。事故在随机发生。
同样,这种不可预测性导致全球数百万球迷收看并付费观看职业体育比赛。体育运动中的大多数得分事件都是随机的——NFL 触地得分是随机的。橄榄球中的尝试,或者足球和冰球中的进球也是如此。所有上述情况(以及许多其他情况)都是在比赛中发生的罕见事件,通常发生在个人技能、糟糕的决策甚至纯粹的运气之前。此外,这些随机事件在比赛中的任何时候都可能对某个球队不利或有利。
不间断的
尽管如此,足球中进球的随机性并不能阻止更好的球队比其他球队得分更多,赢得更多比赛。从长远来看,技术胜过运气。这就是为什么最好的球队几乎总能赢得联赛冠军——用一句流行的“足球人”的话来说,这种形式的比赛足够让运气“在一个赛季的过程中达到平衡”。基本上,如果你有世界上最多的钱和最好的球员,你更有可能在 30 场左右的比赛中积累最多的分数。
为了说明这一点,让我们来看看 2016-2020 年间欧洲五大联赛的独特联赛冠军数量:
2016-2020 年欧洲足球联赛顶级冠军。作者图片
你不需要成为火箭科学家就能推断出英超是唯一一个总共产生超过 2 个冠军的比赛(他们有 4 个)。法甲和西甲在 5 年内恰好有 2 个冠军,而德甲和意甲则完全由一支球队主宰。
现在让我们将这张表与北美体育的获胜者进行比较:
2015–2019 年北美体育冠军。作者图片
除了 NBA,所有其他运动在过去 5 年里都产生了 4 个或更多的冠军。事实上,MLB 和 NFL 有 5 个独特的赢家!
你觉得幸运吗,废物?
超级猫头鹰。Geronimo Giqueax(@ ggiqueaux)在 Unsplash 上的照片
那么,这是什么原因呢?足球和北美的其他运动有本质的不同吗?不太可能-我们已经建立了相似性,进球、触地得分和尝试都是随机事件。
北美体育产生更多赢家的原因之一是由于在常规赛结束后加入了季后赛的形式。除了增加比赛的刺激,季后赛本身就是随机的。当然,有时候常规赛表现最好的球员会在前几轮被淘汰,但他们要么必须在一次性比赛中击败其他球队,要么经过一系列比赛,才能进入下一轮并最终赢得比赛。
记住我们之前已经确立的事实——运气在短期内比在长期内起着更大的作用。糟糕的裁判决定,对手激发技巧的时刻,和/或错过的机会,在一场比赛中(或在季后赛中)对一支球队的伤害远远超过整个赛季。就这样,桑德兰 vs 曼城又来了!所有这些加在一起意味着“最好的”球队不一定比其他球队更容易成为冠军。
笔诛胜于剑伐
最后一件事——有没有想过为什么弱队在淘汰赛中对强队进行点球,让观众经历 120 分钟的无聊比赛?这又和随机性有关了。在比赛开始时,较弱的球队与较强的球队相比取得胜利的机会较小,但比赛进行得越久,比分保持不变的时间越长,点球就决定了结果。
除了在 Microsoft Excel 中创建一个随机数生成器来选择获胜者之外,点球可能是足球比赛中最接近 50/50 的决胜局。想想所有可能决定结果的随机事件——射门偏出,击中门柱,进入顶角,被守门员扑出。认为这是区分整场比赛不分胜负的两支球队的最佳方式是非常荒谬的,但在有人提出更好的想法之前,淘汰赛将继续因随机性而受到祝福和诅咒。
其他文章
[## 创造机会
英国博彩业繁荣简史,从贝叶斯到必发
towardsdatascience.com](/making-up-the-odds-73fbc509ee7f) [## 利物浦值得赢得英超冠军吗?
使用 Python、R 和预期目标的英超联赛 2019/20 回顾
towardsdatascience.com](/did-liverpool-deserve-to-win-the-premier-league-eda7a4e1b9ca)
排列你的东西…一个 AES 的故事
原文:https://towardsdatascience.com/rank-your-things-an-aes-story-1edf0e6d7ea8?source=collection_archive---------35-----------------------
自动论文评分(AES)是使用专门的计算机程序给在教育环境中撰写的论文打分。它的目标是将大量的文本实体分类到少量的离散类别中,对应于可能的等级。但是在这里,让我们从工业问题的角度来看。
来源:链接
你是篮球教练。你手下有 40 个想打球的孩子。你被要求选择一个由 5 个最高的孩子组成的团队。相当简单!你让他们按照身高的降序排列,然后你选出前 5 个。
现在说你是漫画作家。不是一个真正的作家,但你是那个能决定恶棍名字的人。你手下有很多实习生,他们为你创造反派角色的描述,并为你命名反派角色。他们为你的漫画创造了数百个这样的潜在反派角色,现在你必须在他们中选择你应该为你的漫画考虑的角色。棘手的是,你可能也想根据读者的喜好来选择。
从技术上来说,你要给你的每一个潜在的坏人打分,然后按照读者亲和力得分(或评级)的降序给他们排名。
(忽略你如何吸引读者的细节。假设漫画神给了你这些。)
所以,你有你所有的反派(最终进入漫画)和他们各自的读者亲和力得分。现在你的任务是利用这些信息(不知何故,咄),对你的实习生创造的未来恶棍进行排名或评分。
在文献中,这被称为 自动作文评分 或自动文本评分问题。
方法
这是一个在研究领域不断发展的领域。所以,你会找到很多解决方法。让我们专注于一个能完成工作的解决方案。
一种方法是将其视为一个预测问题,并尝试预测读者亲和力得分。但是有一个小问题,它可能无助于解决我们的问题。读者亲和力得分是针对整个漫画的,而不仅仅是针对反派。一个人喜欢剧情但讨厌反派还是可以给个好分数的。如果我们试图预测这个分数,我们将需要使用更多的信息(如漫画类别、发行月份、目标年龄组等),而不仅仅是反派信息(如名字、描述等)。
我们还要注意一个事实,一个反派的预测分数对我们来说并没有真正的用处,因为我们的工作是从一群反派中找出最好的反派。就个人而言,分数可能没有相对考虑时那么有意义。如果我们有 100 分,我们可以很容易地知道哪个恶棍可能比其他人表现得更好。
因此,我们仍然可以继续我们的预测逻辑,但不是客观地看预测的分数,我们只需要确保它们与实际分数相关。这意味着,如果一个反面角色 X 的得分高于反面角色 Y 的得分,不管我们的预测有多好或多坏,如果实际得分也遵循相同的顺序或等级,那么它就是赢了。
解决方案
来源:链接
直接找到一个解决方案(在许多解决方案中,就像我说的,文献资料非常丰富🔥),我们使用两种特定类型的模型。因为对文本进行评分是一项任务,所以我们需要某种文本嵌入技术来将我们的文本表示为向量。任何文本嵌入技术都可以选择,但我选择了 通用句子编码器 。
usemodel = **hub.Module**('models/sentence_encoder')**def** get_use_vectors**(list_text)**:
'''
Computing the USE vector representation of list of sentences
@param list_text : list of sentences
'''
messages = list_text
num_batches = **math.ceil**(len(messages) / BATCH_SIZE) message_embeddings = []
**with** tf.Session() **as** session:
session.**run**([tf.global_variables_initializer(),
tf.tables_initializer()])
**for** batch **in** range(num_batches):
**print**(batch * batch_size, batch * batch_size + batch_size)
batch_msgs = messages[batch * batch_size: batch * batch_size + batch_size]
message_embeddings_temp = session.run([model_use(batch_msgs)])
message_embeddings.append(message_embeddings_temp)
all_embedding = np.concatenate(tuple(message_embeddings))
**return** all_embedding1, all_embedding2
该模型用于将恶棍的名字和他们的描述转换成向量,并且我们在预测模型中使用这些向量作为特征(连同其他特征)。其他特征可以是分类特征,例如漫画的类别、作者姓名等,或者是顺序特征,例如购买数量、价格等。
这些可以是一个热编码,并附加到我们的功能列表。
预测模型是一个简单的 随机森林回归器 模型,直接取自 sklearn 教程部分。
**import** pickle
**from** sklearn.ensemble **import** RandomForestRegressor
params = {'n_estimators':[20, 50, 100], 'max_depth':[2, 4, 6, 8, None], 'min_samples_split': [2, 4, 6, 8],
'n_jobs': [10]}
rf = **RandomForestRegressor**(n_estimators = 250, random_state = 42)
grid = **GridSearchCV**(rf, params)
grid.**fit**(X_train, y_train)
predictions = grid.**predict**(X_test)
errors = abs(predictions - y_test)
**print**(grid.best_score_)
**print**(grid.best_estimator_)
这给了我们一个模型,这个模型是根据我们过去的历史数据训练出来的,可以预测一个恶棍的名字/描述会有多好。从技术上来说,这是一个用户亲和力得分预测器。但是,正如我们所讨论的,由于我们没有使用所有可能和可用的特征来预测这个分数,并且由于我们没有将它作为用户亲密度分数预测模型,所以我们得到的最终预测将是不准确的。但是如果分数给了我们两个或更多恶棍的表现的相对指示,它将帮助我们挑选出头号恶棍。
衡量标准
科恩的 Kappa 评分 通常被用作一种衡量标准,以确定我们的预测排名或排序与实际排序相比有多接近。但是,该指标假设预测是诸如分数(0 到 5)之类的类别。我们有一个更连续的预测,因此这个指标对我们来说不太适用。
为此,我们可以用简单的 斯皮尔曼 和 皮尔森 关联式。
绘制实际分数与预测分数的对比图可以很好地说明我们的预测是否符合正确的趋势。
对应于左侧预测的相关系数为:
皮尔森:0.65,p 值= 2.14 e-92 | 斯皮尔曼:0.60,p 值=8.13 e-123
因此,通过这种方法,你可以使用预测的分数来排列或排序你的恶棍,并选择顶部的 X ,前提是你的相关性和上面的情节看起来不错。别让实习生毁了你的漫画事业:)
排名算法—了解您的多标准决策解决技术!
原文:https://towardsdatascience.com/ranking-algorithms-know-your-multi-criteria-decision-solving-techniques-20949198f23e?source=collection_archive---------4-----------------------
让我们通过一些基本算法来解决受多个标准影响的复杂决策问题。我们将讨论为什么我们需要这样的技术,并在很酷的 skcriteria python 包中探索可用的算法
来自 Unsplash的 Joshua Golde 的照片
更新-2022 年 3 月:由于 scikit-criteria 最新版本中的代码破坏更改,建议对文中讨论的代码使用该包的 v0.2.11。这里的是的代码库。
介绍
假设你要做一个决定——比如买一栋房子,或者一辆车,甚至一把吉他。你不想随机选择或因某人的建议而产生偏见,而是想做出明智的决定。为此,您收集了一些关于您想要购买的实体的信息(假设是一辆汽车)。因此,您有一个包含价格信息的N
汽车列表。像往常一样,我们不会想花更多的钱,我们可以按照价格(升序)对汽车进行排序,然后选择最上面的一辆(价格最低),我们就大功告成了!这是一个只有一个标准的决策。但是,唉,如果生活是如此容易:)我们也希望汽车有良好的里程,更好的发动机,更快的加速度(如果你想比赛),等等。在这里,你要选择价格最小,但里程和加速最高的车,等等。这个问题不是简单排序就能这么容易解决的。输入多准则决策算法!
资料组
让我们选择一个数据集,以便更容易地可视化结果,了解幕后真正发生的事情,并最终建立直觉。为此,我选择了汽车数据集。对于每辆车,我们将关注属性的子集,并且只挑选 10 行(独特的车)来使我们的生活更容易。查看选中的数据,
汽车数据集中的 10 行
解释一些属性,
- mpg:衡量一辆汽车在油箱中加入一加仑汽油或柴油后能行驶多远的指标(里程)。
- 排量:发动机排量是活塞发动机所有活塞扫过的气缸容积的量度。更大的排量意味着更大的动力。
- 加速度:一个测量汽车从 0 加速到 1.5 公里所需时间的指标。加速度越高,赛车越适合飙车:)
这里请注意一些要点,
- 属性的单位和分布不一样。价格以千美元玩,加速以几十秒等。
描述所选数据的每个数字列(属性)
2.每个属性的最佳逻辑也各不相同。在这里,我们想找一款 mpg、排量、加速值都很高的车。同时,低价值的重量和价格。这种高和低的概念可以分别推断为最大化和最小化属性。
3.可能有一个额外的要求,我们不认为每个属性都是平等的。比如我想要一辆赛车,说我是亿万富翁赞助的,那我就不会那么在意 mpg 和价格了。我想要尽可能最快最轻的车。但是,如果我是一名学生(因此很可能预算严格)并且经常旅行,那么突然 mpg 和价格成为最重要的属性,我对排量一点也不在乎。这些重要属性的概念可以被推断为分配给每个属性的权重。比如说,价格 30%重要,排量只有 10%等等。
清楚了需求之后,让我们试着看看如何解决这类问题。
通用方法
大多数基本的多准则决策求解器都有一个通用的方法,
- 一次考虑一个属性,并尝试最大化或最小化它(根据要求)以生成优化的分数。
- 为每个属性引入权重以获得优化的加权分数。
- 合并(每个属性的)加权分数,以创建实体(此处为汽车)的最终分数。
在此之后,我们将需求转化为一个单一的数字属性(最终得分),并且像前面所做的那样,我们可以对其进行排序以获得最佳汽车(这一次我们通过降序排序,因为我们希望选择一个得分最高的汽车)。让我们用例子来探究每一步。
最大化和最小化
记住数据集部分的第一点,属性有非常不同的单位和分布,这是我们需要处理的。一种可能的解决方案是在相同的范围内对每个属性进行标准化。而我们也希望善的方向是相似的(不考虑逻辑)。因此,在标准化之后,接近范围最大值(比如 1)的值应该意味着汽车在该属性上是好的,较低值(比如接近 0)意味着它们是坏的。我们用下面的公式来做这件事,
用于最大化和最小化属性值的规范化逻辑
看看最大化的第一个等式,一个例子是通过除以所有汽车的 mpg 之和(总和归一化)来更新每辆汽车的 mpg。我们可以通过仅仅考虑 mpg 或其他公式本身的最大值来修改逻辑。目的是,在将此应用于每个属性之后,每个属性的范围将是相同的,并且我们可以推断值接近 1 意味着好。
最小化的公式与最大化的公式几乎相同,我们只是将其反转(1 除以最大化)或镜像(从 1 中减去它)以实际反转好的方向(否则 1 意味着坏,0 意味着好)。让我们看看它在实践中是怎样的,
原始数据的总和标准化热图示例。检查“福特都灵”的“mpg”值。最初是 17,但经过求和归一化后,应该是 17/156=0.109。同样,“价格”是 20k,反算后将是 1/(20k/287872) = 14.4
应用权重
我们只需要将权重叠加到优化的分数上,这可以通过将权重乘以优化的分数来轻松完成。这里我们也可以引入不同类型的标准化,
- 因为是:直接乘以权重得到优化分数
- 求和:通过求和逻辑(如上所述)归一化权重,然后相乘。
- max :用 max 逻辑归一化,然后相乘。
权重修改逻辑
合并分数
最后,我们将分数合并为一。这可以通过两种不同的逻辑来完成,
- 求和:将所有单项得分相加
- 乘积:将所有单项得分相乘。事实上,许多实现都是将数值的对数相加,而不是取乘积,这样做是为了在乘以小值时处理非常小的结果。
履行
有一个非常好的 python 包叫做 skcriteria ,它为多准则决策问题提供了许多算法。实际上,skcriteria.madm.simple
模块中有两个算法,
WeightedSum
—单项得分组合逻辑为总和WeightedProduct
—个人得分组合逻辑为乘积(对数之和)
这两种方法都采用两个参数作为输入,
mnorm
—定义值最大化规范化逻辑(最小化总是相同的最大化逻辑的逆)。wnorm
—定义权重标准化逻辑
为了对我们的数据进行排序,首先,我们需要通过,
将数据加载到数据对象
加载完数据后,我们需要做的就是用数据对象和参数设置调用适当的决策函数。输出中有一个额外的 rank 列,显示考虑了所有提到的标准后的最终排名。
值的和归一化的weightedSum
逻辑示例
我们甚至可以通过dec.e_.points
导出最终分数,通过dec.rank_
导出排名。
比较
让我们在数据集上比较不同决策算法(使用不同参数)的结果。为此,我使用了weightedSum
和weightedProduct
实现(一次使用max
,然后使用sum
值规范化)。我还实现了一个normalize_data
函数,默认情况下它执行最小最大和减去归一化。然后,我对输出进行求和合并。
5 种不同的多标准求解器
最后,我绘制了一个平行坐标图,其中每个轴(垂直线)表示一个解算器类型,值表示该解算器的汽车等级。每条线代表一辆车,从左到右,它显示了旅程——当你在不同的解算器之间切换时,一辆车的等级如何变化。
当我们切换决策求解器时汽车的旅程
有些点,
- 福特都灵在 4/5 的解决者中排名第一(得分最高的汽车)。明麦克斯青睐雪佛兰迈锐宝。
- 黑斑羚是普遍的低级动物:(
weightedProduct
的两个实现都给所有汽车相同的排名。这里没什么有趣的。- 两个
weightedSum
实现的排名差异很大。 - MinMax 给出了前 4 名男生最多样化的排名。
当改变归一化(从 sum 到 max)时,结果变化背后的主要原因是由于对原始数据进行的转换。这种转换改变了数据的范围(如缩放x
和y
之间的所有内容),并且在相反的情况下也修改了线性度(例如,原始数据中 1 的相等步长在转换后的数据中不一致)。这将通过以下结果变得更加清楚,
不同的标准化方法和转换后的数据
这里,输入数据由数字 1 至 9 组成(注意,任何两个连续数字之间的差值为 1,即步骤相同)。方法一(最小最大)在 0 和 1 之间转换数据,步长不变。现在看看方法 2 和 3 的最小化逻辑(_inverse
)。这里,在开始处(低原始值),步长几乎是最后一个元素的一半,但是在接近结束处(高原始值),步长非常小,即使在原始数据中,我们以相同的步长 1 移动。
因此,在最小化的情况下,“好”车(低值)甚至是少量杂质(当最小化时,高值=低分)会得到很高的分数,导致分数急剧下降。就好像我们很挑剔,要么你是最好的,要么你拿一半的分数:)另一方面,对于更高的数值,小杂质无所谓。如果这辆车的这个属性已经很差了,那么我们就不在乎它的值是 7 还是 8 还是 9,分数的减少也少得多!我们可以利用这种理解,根据我们的需要选择带有正确参数的正确决策求解器。
结论
这篇文章只是触及了多标准决策领域的表面。甚至在skcriteria
包中还有更多像 TOPSIS 和 MOORA 这样的算法,它们有完全不同的直觉来解决这些问题。但即便如此,善良的概念和处理个体属性最终将它们结合在一起的想法仍在许多书中使用。所以也许我们会在另一篇文章中探讨更多的算法。
但是这篇文章的主要收获应该是理解决策者的原因和目的。每个这样的决定都可以被多种标准所操纵。我们可能对每一个标准都有不同的善和重要性的概念。最后,我们有不同种类的解算器,可以通过逻辑和参数的排列来构建,几乎所有的解算器都会根据我们的需要给出不同的有趣的结果!
参考
[1] Skcriteria python 包
本文的代码和数据可在此处获得。
要阅读更多这样的文章,请在 LinkedIn 上关注我或访问我的网站。
干杯。
使用 Power BI 对类别进行排名
原文:https://towardsdatascience.com/ranking-categories-with-power-bi-846fbe88ced0?source=collection_archive---------5-----------------------
如何使用 MS Power BI 可视化前 n 个类别和其他类别
我最近开始更频繁地使用 Power BI,并且我已经从这个工具中学到了很多东西。
我原以为从一个更加面向代码的角度出发会让我更容易处理像 Power BI 这样的工具,但是无论如何,改变总是令人不舒服的。
插图来自达米安尼奥莱
如果你习惯于面向业务的解决方案,那么学习如何编码以及必须对你的可视化的几乎每个方面负责将是一件痛苦的事情。如果您来自代码领域,您将不得不习惯新工具的局限性,不得不适应最初的想法,并创建变通方法。
在本文中,我将分享我最近面临的一个挑战,以及我找到的表示分组和排序数据的解决方案。
如果你是 Power BI 的新手,我希望你能从我这里学到一些东西,如果你是这个工具的专家,也许你可以嘲笑我的错误,并为我的下一个项目提供一些指导。
请求
最初的任务听起来很简单。客户希望按类别查看计数。
问题是,他们有太多的类别,他们只想看到 n 个类,所有其他的值都归在一个类别中。
计算排名
对于这个例子,我将使用来自 Kaggle 的 Chipotle 位置数据集。由于它与我处理的数据集有相似的字段,我想我可以用它来说明我所面临的问题。
加载数据集后,我做的第一件事是获取计数,我将使用位置作为我们想要可视化的类别。
Count = COUNT(chipotle_stores[location])
用我的领域和措施,我得到了类似的东西。
因此,太多的类别在我们的数据集中只有一个外观。
接下来,我添加了一个对值进行排序的度量。
rank = RANKX(ALLSELECTED(chipotle_stores[location]),[Count],,DESC)
然后,我将新的度量作为工具提示添加到图表中,并能够控制使用过滤器显示多少类别。
太好了,我们可以可视化排名值,并在我们的 viz 中选择我们想要的前 n 个类别。
剩下要做的就是找出一种方法,将列表之外的所有内容进行分组,并显示为另一个条形。
情况
一旦我们有了排名的计算,我们可以添加一个条件。
所以我创建了下面的方法,想法是如果等级低于 n,它应该返回各自的名称,否则它应该带标题“其他类别”
top_n_others =var ranked = RANKX(ALLSELECTED(chipotle_stores[location]),[Count],,DESC)return if(ranked <= 10, SELECTEDVALUE(chipotle_stores[location]), "Other Categories")
厉害!问题是。
我们不能用度量作为条形图的轴——所以,是的——那是一种浪费。
如果我们使用计算列而不是度量值会怎么样?
那是我的下一次尝试。我创建了一个维度来保存该位置的不同值,并应用了与之前相同的计算。
top_n_others =var ranked = RANKX(ALL(location[location]),[Count],,DESC)return if(ranked <= 10, location[location], "Other Categories")
它起作用了,我们可以把它用在条形图上。
太好了,还有一件事。
我不得不添加更多的过滤器到我的可视化中;让我们看看当我们挑选一些州来测试它时会发生什么。
它不起作用。如果我们用过滤器移除一个状态,该状态中的顶部位置将会消失并且不会被替换。
这里发生的情况是,计算不再是动态的,因为我们直接以列的形式计算排名,所以结果对于整个列表是静态的。
无关表
好吧,我们需要重新考虑解决方案。
让我们尝试调整位置维度,这一次,我们将构建一个表,不仅保存位置的不同值,还保存“其他类别”的一行。
Unrelated location =
UNION(
VALUES('chipotle_stores'[location]),
ROW("location","Other Categories"))
现在让我们创建一个参数,这样我们就能够选择动态显示的类别数量。
我们参数的度量应该是这样的。
Top Value = SELECTEDVALUE('Top'[Top], 1)
最后,我们将创建一个对类别进行排名和分组的方法。
topn_others =var n = CALCULATETABLE(TOPN([Top Value],VALUES(chipotle_stores[location]),CALCULATE( [Count] )))var other = ROW("location", "Other Categories")var other_val = CALCULATE([Count], EXCEPT(VALUES(chipotle_stores[location]),n))var myUnion = UNION(n,other)returnSUMX( INTERSECT('Unrelated location',myUnion),
var currentIterator = 'Unrelated location'[location]
return
IF('Unrelated location'[location] <> "Other Categories",
CALCULATE([Count],
chipotle_stores[location] = currentIterator)
,other_val)
)
好吧,那上面的魔法会让我们的图表活起来。
这个想法是有一个“不相关”的表,它将使用主表中的值来填充它自己并计算它的度量。但是在其他表中没有创建实际的关系。
我发现并改编了这个解决方案,从 Power BI 社区、【大喊】到 TomMartens 来解决这个问题。
现在让我们看看它在图表中的样子。
条形图
斯莱伊萨
我们将使用“无关位置”作为轴,“topn_values”作为值,然后我们可以为刚刚构建的参数创建一个切片器。
哒哒!我们有图表。
现在,我们可以更改标题、x 和 y 标签,为“其他”赋予不同的颜色,并修正我们的情节的所有细节。
华盛顿州排名前五的位置
探索其他解决方案
很酷,在一些工具中可能很容易解决的问题在其他工具中可能很有挑战性。
当然,这个问题有很多解决方案,这只是其中之一。
最后,这将取决于你如何带来数据,你的模型是如何设计的,你能在多大程度上转换它,以及你在哪里这样做更舒服。
一位朋友发给我的另一个解决方案也是从创建一个包含所有类别的表格和一个包含其他类别的行开始的。
mylocation =UNION(VALUES('chipotle_stores'[location]),ROW("location","Other Categories"))
这种方法的不同之处在于创建了一个关系。
我们还需要一个衡量排名的标准,就像这样。
rank = RANKX(ALL(chipotle_stores[location]),[Count],,DESC)
以及用于计算顶级类别和其他类别的度量。
top with others =IF( [rank] <= 10,[Count],IF( SELECTEDVALUE(mylocation[location]) = "Others",SUMX( FILTER( ALL(mylocation[location]), [rank] > 10), [Count])))
结论
尽管这可能需要大量的工作,但是对类别进行分组可以让我们使用许多可视化工具,而这些工具在早期会有太多的干扰,在很多情况下是值得的。
感谢阅读我的文章。我希望你喜欢它。
根据法案通过的有效性对总统候选人进行排名
原文:https://towardsdatascience.com/ranking-presidential-candidates-by-effectiveness-at-getting-bills-enacted-54d306ba6014?source=collection_archive---------7-----------------------
我根据 1973 年以来所有参议员对最终成为法律的法案的支持程度对他们进行了排名,并根据历史时代的差异进行了调整。艾米·克洛布查尔在目前的总统候选人中排名最高,在 397 名参议员中排名第 60。伊丽莎白·沃伦排名第 216 位。尽管提出了最多的法案,乔·拜登在任期调整后排名第 222 位。伯尼·桑德斯排名第 351 位,对已颁布的法律影响相对较小。
原始数据
要量化各候选人对立法的影响,显而易见的是从他们发起或共同发起的法案的原始计数开始。为此,我调出了自 1973 年第 93 届国会开始以来参议院提出的所有 4321 项法案(这些法案都可以在 congress.gov 获得)。虽然有些法案总是比其他法案更有影响力,但我想把重点放在至少有点重要的法案上。因此,我排除了国会最喜欢的琐碎法案;以某人的名字命名某物的人。事实证明,基本上每个参议员和众议员都发起了一项法案,将命名为邮局、命名为联邦大楼、命名为一段高速公路等等。除去这些账单,我们还剩下 3722 张账单。
在这个集合中,我们可以统计出哪些候选人发起或共同发起的最多(包括以前的候选人以供比较)
乔·拜登的赞助和共同赞助远远多于其他人,而卡玛拉·哈里斯的赞助和共同赞助最少;这并不令人惊讶;乔·拜登在参议院呆了 36 年,而卡玛拉·哈里斯刚刚进入第四个任期。即使没有这种巨大的时间差异,比较其他人仍然很难。例如,科里·布克提出了两项法案,而希拉里只提出了一项,但她共同提出的法案几乎是他的两倍。我们需要一种方法来权衡这些因素。
赞助与联合赞助
虽然一项法案的提案人在通过该法案的过程中发挥了很大的作用,但每个共同提案人对该过程的重要性却不太清楚。一项法案由参议院的大多数人发起是很常见的,这表明任何特定的共同发起者的贡献都是最小的。例如, Pallone-Thune 电话 Robocall 滥用刑事执法和威慑法案是由 84 名参议员联合发起的,此外还有其发起人 John Thune 每个参议员都希望能够在阻止机器人电话方面获得一些荣誉。另一方面,有很多法案都有一小群集中的联署人,每个人都可能为法案的起草和通过做出贡献。
为了想出一个分配积分的启发式方法,我做了以下工作:
- 当只有一个赞助者而没有共同赞助者时,赞助者获得整个法案的信用。
- 当至少有一个共同发起人时,发起人获得一半的信用,剩余的信用在所有共同发起人之间平均分配。
因此,举例来说,在只有一个共同发起人的情况下,他们和发起人将各自获得 1/2 的赞助法案的信用。在上面的例子中,虽然有 84 个共同发起人,但每个共同发起人只得到 1/168 的赞助法案的信用,而约翰·图恩仍然得到 1/2 的赞助法案的信用。将所有法案中对每位参议员的总积分相加,将得到每位参议员的加权赞助分数。
虽然这并不严格,可能会低估一些重要的共同赞助者,而高估小团队中的其他人,但感觉大致合适。
时代很重要
为了恰当地比较卡玛拉·哈里斯和乔·拜登,我们需要做的不仅仅是调整他们在参议院的年数。我们还需要调整他们在参议院的具体年份。
为了了解这一点有多重要,我绘制了每次国会期间成为法律的法案数量,并根据提案人所属的政党进一步细分,如果提案至少由另一个政党的一名成员共同提案,则标记为两党共同提案:
从中可以看出几件事:
- 一些国会比其他国会通过更多的法案。
- 在过去的 20-25 年中,国会通过的法案比之前少了很多,这是一个很大的趋势。
- 尽管总是有大量的法案得到两党的支持,但国会之间通过党派立法的能力却大相径庭。例如,在 2005—2006 年的第 109 届国会中,当共和党控制了众议院和国会时,几乎没有任何立法是仅由民主党参议员提出的,也有一些是仅由共和党人提出的。在 2007 年至 2009 年的第 110 届国会中,在民主党翻转两院后,这一趋势发生了转变。
虽然乔·拜登发起和共同发起了许多成为法律的法案,但他也是在一个更为规范的时代这样做的。具体来说,从 1973 年到 1980 年,他参加的前四次国会都通过了比此后任何一次国会都多的法案,对民主党人来说尤其有成效。相比之下,卡玛拉·哈里斯参加的最近两次国会对一名民主党参议员来说并不是很有收获。
为了调整我们对每个参议员的期望,我计算了我上面描述的每个政党和国会所有参议员的加权支持得分的平均值。结果如下:
正如你所看到的,国会的赞助效率差异很大。例如,从第 109 届国会到第 110 届国会,共和党的平均赞助分数减半,而民主党的平均赞助分数翻倍。
这允许我们计算一个基线来比较每个参议员的赞助分数:我们将他们所在的政党在他们参加的所有国会中的平均赞助分数相加。
最终排名
做了以上所有的事情,我已经生成了候选人的最终排名。我已经计算了上面描述的加权赞助分数,然后计算了他们的分数与他们所参加的大会的预期分数之比。此外,我还提供了他们在我的数据集中包含的 397 名参议员中的排名。
- 正如已经叙述的那样,艾米·克洛布查尔作为参议员脱颖而出,她最有成效地使法案通过成为法律;在我们的数据库中,她在所有参议员中排名第 60 位,在现任参议员中排名第 16 位,在获得法案方面的生产率是平均水平的 1.4 倍。
- 乔·拜登和伊丽莎白·沃伦在调整了各自的任期后,被评为中等或中等以下的参议员。正如我们所预期的那样,他们两个都是 3/4 的富有成效的立法提案者。
- 卡玛拉·哈里斯排名最低,排在第 352 位,即使在一个对民主党参议员期望很低的时代也是如此
- 不过,伯尼·桑德斯在立法方面仅领先她一位,在 397 个国家中排名第 351 位,其生产率只有我们对民主党人预期的十分之三。诚然,他不是民主党人,但他与他们一起参加党团会议,目前正在争取他们的提名,所以这似乎是一个公平的比较。
这个数据集对于不竞选总统的参议员来说也很有趣。无论是现任参议员还是所有参议员,过去的和现在的都被计算在内。一些突出的例子:
- Kyrsten Sinema [D-AZ]在活跃的参议员中排名第一,仅从当前非常低效的国会获得的支持得分为 1.09。鉴于她在国会的时间,她获得的赞助分数是人们预期的 3.3 倍。
- Ben Sasse [R-NE]不仅仅是目前效率最低的参议员,基本上也是我们数据集中效率最低的。他在 397 人中排名第 393 位,赞助得分为 0.06,是我们预期的 1/50。他“超过”的 4 位历史上的参议员都是临时任命的,任期只有几个月。
- 帕特里克·莱希(D-VT)在参议院的 45 年中一直卓有成效,他的支持得分为 61.2,是我们预期的 1.9 倍,以此衡量,他在活跃的参议员中排名第八,在总产量中排名第一。
- 最近退休的奥林·哈奇(R-UT)在他 42 年的参议员生涯中获得了最高的赞助分数,高达 83.5 分,是我们预期的 2.7 倍,在我们的名单中排名第七。
- 兰德·保罗[R-KY]在通过法律方面效率很低,获得了 0.4 的赞助分数,是我们预期的十分之一,在我们名单上的 397 个国家中排名第 382 位。
- 令人惊讶的是,马尔科·卢比奥[R-FL]是第十位最活跃的参议员,他的支持得分为 6.7,是我们预期的 1.7 倍。
进一步的工作
这一分析忽略了对已颁布立法的一种重要影响,即修正案。即使一名参议员不支持一项已颁布的法案,如果他们提出并通过了对该法案的修正案,他们肯定会对最终结果做出贡献。尤其是伯尼对修正案相对积极,因此这一遗漏可能低估了他的贡献。
另一个感兴趣的领域是将更多的细微差别融入到每条法律的重要性中。虽然很难对 3722 项法案进行系统化的分析,但是很容易就能看出某个特定的参议员发起了什么,例如,这些由艾米·克洛布查尔发起的法案。
笔记
- 你可以在我的 GitHub 库中看到我的代码和数据。
- 我通过剔除标题中带有“指定”一词的法案来排除指名法案。这些账单非常公式化,所以这个简单的规则似乎奏效了,但是很有可能我漏掉了一些和/或过滤掉了一些我不应该有的账单。
- 为了设定一个底线,我指派了独立的参议员到他们参加党团会议的政党。因此,举例来说,伯尼·桑德斯被包括在民主党内,就像乔·利伯曼作为无党派人士时一样。我没有支持的一位参议员是迪安·巴克利,他是在保罗·威尔斯通死后由杰西·文图拉任命的,因为他似乎没有和任何一个主要政党进行过党团会议。
- 我对改变党派的参议员并不十分小心;他们大多被视为他们所属的最后一个政党的成员(或在无党派人士的情况下被分配到该政党)。总的来说,这种情况很少,但是从共和党转投民主党的阿尔伦·斯佩克特和从共和党转投民主党的吉姆·杰福兹这两个独立党团会议成员是处理最不恰当的。
使用谷歌移动数据,新冠肺炎第一波后美国各州排名恢复
原文:https://towardsdatascience.com/ranking-recovery-of-us-states-after-covid-19-first-wave-using-google-mobility-data-fec9df6f1864?source=collection_archive---------50-----------------------
可视化移动数据趋势萨克斯形状图
有传言说,新冠肺炎是一个展示你的数据科学/分析技能的好机会,你不必成为流行病学家,就可以与世界分享你的 2 美分。嗯…这是我的尝试。
从 2020 年 2 月 15 日开始,谷歌分享了新冠肺炎第一波之前、期间和之后世界各地日常流动性的公共数据集。我的版本有 6 种类型的移动性测量:
移动零售和娱乐
流动杂货店和药房
移动公园
移动中转站
移动工作场所
移动住宅
在这篇文章中,我关注的是美国 51 个州的整体水平分析。但是,数据源还包含州内几个地区以及其他国家/地区的信息。
分析目标:对流动性趋势第一次下降之间的状态恢复进行衡量和排序,直至恢复正常阶段(分析时)。
免责声明:以下分析的目的是演示数据可视化技术,分析推理,大部分是满足自己的好奇心。出于关注高层次洞察力的目的,可能已经采用了一些特定的快速启发式(假设)。当然,有多种可能的偏差可以更好地解释这些数据,这将在最后讨论。
数据:我真的不知道 Google 是如何测量移动性的,尽管如此,我也不知道他们的样本量、实验单位、数据收集程序和汇总以及验证。然而,从国家层面的流动性数据的时间序列趋势来看,似乎与明确的信号趋势非常一致。
图 1:每日移动数据趋势(平滑)。功劳:自己。
图 2:每日移动数据趋势(平滑)。功劳:自己。
人们很容易观察到零售和娱乐、公园、杂货店和药店、中转站和工作场所的流动性下降。然而,在住宅流动性方面却出现了相反的趋势。嗯……如果人们不再开车去某个地方,并且在大部分时间呆在家里之后,他们开始做一些别的事情……最有可能的是,在他们的房子周围走动,了解他们的邻居,否则他们很少说话。(至少以我 size =1 的经验)。
相关图图为上述 5 个流动性指标之间的相互关系,支持之前假设的正相关,以及与住宅流动性的负相关。偏离这种相关性趋势的州可能表明不同的行为,可能是天气季节性的强烈影响,或者是农村地区不同的人口密度。
图 3:WA 的相关图。功劳:自己。
图 4:每个州的工作场所流动性。功劳:自己。
公制定义:
第一个大降日期:流动性日期低于-10 的第一个日期。(垂直虚线)。
‘预降’期间的平均流动性:从 2020 年 2 月 15 日到上述日期的平均值。(左侧的水平全绿线)。假设没有其他季节性影响或其他趋势(绿色虚线),这也用作第一次下降后的假定“恢复正常”水平。
“恢复正常”期间的平均迁移率:2020 年 7 月 1 日至 2020 年 8 月 16 日之间的平均信号,最后一次收集信号时进行分析。(右侧的蓝色虚线)。
蓝线和绿线之间的间隙用于表示状态是否能够恢复到跌落前的移动性水平。
图 5:西澳大利亚州工作场所流动性数据,包括前后平均水平。第一滴是假期(总统日)。功劳:自己。
图 6:西澳大利亚州零售和娱乐流动性数据,以及前后平均水平。功劳:自己。
跨状态恢复比较:
计算每个州的上述情况,以下是基于工作场所流动性恢复差距的州排名。
也可以使用任何其他移动性指标,但是,为了避免地理天气或其他社会人口特征的可能偏差,我假设工作场所移动性是偏差最小的。
另一种选择是创建 6 个流动性指标的平均值(在逆转与住宅流动性的负相关性之后)。
图 7:基于工作场所流动性的状态恢复排名。功劳:自己。
受影响最大的州是 DC,其次是马里兰州、加利福尼亚州、亚利桑那州、德克萨斯州和纽约州。受影响最小的州是 me、SD、WY 和 AK,但仍有一些差距需要填补。
图 8:基于娱乐流动性的状态恢复等级。功劳:自己。
娱乐流动性与上述工作场所流动性的模式相似,但在底部,有几个州能够缩小差距,甚至达到比下降前更高的水平(怀俄明州、SD、AK、ME、MT)。
可能的偏差:
除了已经提到的问题之外,下面的问题可能更好处理。
时间序列:季节性,去除各州不平等的节假日。
可能的原因:社会人口特征,如农村与城市、失业水平、人口年龄、疫情/污染水平、人口密度、政治派别、病毒变异、卫生系统等等。
开放数据集也有额外的注释良好的信息,这些信息肯定会对上述内容有所帮助,但这超出了本文的范围。
下一步是什么?
嗯,除了一些简单的粗略假设来估计第一次重大下跌的日期之外,这种分析只是描述性的,即没有任何花哨的推断(预测)估计。
本系列的后续文章将尝试演示一些统计建模,如时间序列(预测)、机器学习和因果推理。敬请期待!
代码在哪里?
将很高兴应要求分享它。使用的 r 包有:tidyverse、 tidyverts 、jsonlite、 geofacet 、gt、GGally、 urbnmapr 、sf 和 rnaturalearthdata。
灵感来源于我朋友的博文。
查看我的其他博客文章和我的 GitHub 页面获得更多有趣的阅读。领英。
使用 VS 代码片段快速记录作者身份
原文:https://towardsdatascience.com/rapidly-document-authorship-with-vs-code-snippets-fa98a647085d?source=collection_archive---------51-----------------------
相信你的工作会得到好评。
记录作者身份
简介:
在一个版本控制的世界里,你是否应该在你的文件头部分记录作者信息还没有定论,但尽管如此,这就是我们今天要做的。
在我看来,记录你的作者身份是一件非常有价值的事情。如果你努力创造了一些东西,你的工作应该得到认可。记录作者身份可以让你为自己的成就打上商标,它告诉其他人你可能要承担责任,它让这个世界(你的社区)成为一个更有见识(更好)的地方。
毫无疑问,我们能够认可彼此的工作是很重要的,这样我们就可以更好地决定雇佣谁、与谁合作、支持谁等等
说白了,记录作者身份是好的。
问题:
所以,很好,记录作者身份是好的…
但是,我们如何避免在文件头中一遍又一遍地重复输入相同的作者信息的单调?
也许,我们使用文件模板?当然,文件模板在某些情况下可能是一个很好的解决方案,但是,在这种情况下,不,我们使用 VS 代码片段 和它们的模板能力。
解决方案是:
VS 代码片段,类似于文件模板,也有一个模板元素。然而,片段在本质上更加具体,在范围上更加动态。
对于那些使用过 智能感知 的人来说,你已经熟悉 snippet 的功能了。当 VS 代码检测到您已经输入了在 snippet-config 文件中定义的前缀词的开头时,snippet 通过建议文本插入来工作。
这些文本插入、前缀词和其他片段属性由一个 JSON 文件(snippet-config-file)定义,该文件可以通过以下步骤创建和修改【T14:
代码片段说明
生成的代码片段文件:
代码片段配置。文件
运行中的代码片段:
使用 VS 代码片段的快速文档
结论:
就这样,很简单,但是让我们反思一下我们在这里完成了什么。
- 熟悉 VS 代码片段(一个强大的开发工具)
- 确保我们有公平的机会获得工作上的荣誉
- 为我们未来的自己节省了一些时间
- 让我们对同事更加负责(通过记录责任)
所以,如果你今天什么也没做,你已经赢了。
Rasa 与 Dialogflow -Faceoff(开发者的视角)
原文:https://towardsdatascience.com/rasa-vs-dialogflow-faceoff-part-2-6a4692b25b71?source=collection_archive---------6-----------------------
独一无二的比较博客
诺德伍德主题公司在 Unsplash 上拍摄的照片
你是一个想知道在选择虚拟助手平台时如何比较和比较什么的开发者吗?那么你来对地方了。
在这篇博客中,我们将从开发者的角度来介绍平台的特性。以防万一,如果你错过了我们的第 1 部分 对话流与 Rasa,或者如果你是一个企业主,请检查一下。我们还讨论了在比较平台时需要考虑的核心组件,并深入探讨了企业所有者在选择平台之前需要考虑的特性。
3.开发商
基于关键字的 bot 构建(无 NLP):
当人工智能不在的时候,这是最古老的建立虚拟助手的方法。尽管这种方法不再是优选的。
是的,在基于关键字的 Dialogflow 中,有一些方法可以基于一个基于按钮的机器人来构建一个完全公正的流程。
在 Rasa 中,我们可以使用关键字意图分类器来构建。该分类器仅适用于小型项目或初学者。
机器人的类型:常见问题助手|上下文助手|个性化助手
FAQ assistant 是目前最常见的助手类型,可以用大多数 bot 框架轻松构建。
构建上下文助手需要真实的对话人工智能元素。即使在 FAQ 助手中,我们也可以通过多步骤的方法获得上下文。问题是——这会提供良好的对话体验吗?不,这只会增加开发者在管理意图和评估对话流方面的时间和精力。但要做到这一点,我们需要管理对话中的上下文,以确保我们处理任何事情和一切。根据我们对这两个平台的经验,与 Dialogflow 相比,Rasa 在为开发人员提供管理复杂对话中的上下文的灵活性方面占据优势。
如果开发人员必须通过 Dialogflow 上下文来更改或更新对话流,那么对话管理就更加棘手。带有流动可视化的工具会非常有帮助。
在 Rasa 中,对话由故事管理,再次浏览所有故事并直接在源文件中更新或更改更加棘手,因为它可能会破坏之前的工作行为(因为它是基于 ML 的实现)。但总的来说,Rasa 更擅长处理这种情况,因为它有其他功能来评估冗余检查。Rasa X 有一个功能,我们可以很容易地将正确的对话保存为测试,这样我们就不用自己写出来了。数据验证和测试都应该在一个连续的集成管道中运行,每当我们更新项目的范围时就会触发这个管道。
个性化助理是随着时间的推移了解你的东西。也许这种助手将在未来几年内成为现实。
Ref: 对话式人工智能:你的企业人工智能助手五级指南
定制:
我们认为没有一个平台是完美的,可以解决所有的业务需求,因此需要一些定制的功能来验证项目的平台。可能会有黑客攻击或解决方法,但平台必须提供这种灵活性。
Rasa 可以完全自由地配置 NLU、核心、集成、部署等。更多信息,请参考 Rasa 文档。
另一方面,Dialogflow 不允许对其代码进行任何定制,但您只能在实现中进行定制。
上下文管理:
因为我们的大多数对话都是上下文相关的,这就是虚拟助手对话由人工智能驱动的原因。上下文管理是对话管理模块的核心。
Rasa 和 Dialogflow 都使用槽来管理上下文。槽点不过是助理的回忆。Rasa 的基于 LSTM/变压器的核心采用插槽、当前意图和实体来预测机器人的下一步行动。在对话流管理中,上下文有点棘手,但一旦你掌握了它的工作原理,你就可以开发出很好的对话助手,但当你与上百个意图和实体进行复杂的对话时,管理它就变得很困难。
对话管理:
我们非常清楚,编写大量基于 if-else 语句的会话流是不可行的。因此,这个特性是至关重要的,同时要记住真正基于 ML 的虚拟助手。
Rasa 的对话是用个故事设计和训练的。这是有史以来第一个基于 ML 的对话管理方法与基于规则的方法相结合,包括使用定制的动作文件来创建对流程的更紧密的控制。Rasa 提供的交互式学习选项可以让故事的创作变得自然。与传统方式相比,这种方式构建聊天机器人更加自然。在这里阅读更多关于对话管理的信息:Rasa 核心对话引擎
Dialogflow 更多地使用基于规则的方法,并通过上下文本身管理对话。
SDK 和 API:
Rasa SDK 提供了用 python 编写定制逻辑所需的工具。
Dialogflow 有自己的不同语言的SDK。
4.易于开发、部署和调试
这是选择平台时的重要特征之一。因为每个人都想让自己的生活更轻松。尤其是开发者:P
发展
平台架构:
知道如何使用平台是一回事,但知道平台如何工作是另一回事。为了利用平台的功能,理解平台本身的架构是很重要的。
阅读以下资源,了解有关各自平台架构的更多信息。
Rasa: Rasa 文档和共同学习休息室 Rasa 教程
对话流:合作学习休息室对话流教程
易于学习:
大多数职场人士都有需要在昨天完成的事情的问题。获得更多的技能和更短的学习曲线是我们大多数时候更喜欢的。就功能而言,工具有多好并不重要,但对于我们开发人员来说,更重要的是拥有良好的资源,如平台文档和自助服务平台。
Rasa 文档易于理解和浏览,即使后端的架构可能很复杂。它的互动 ggetting 开始引导将轻松搭载新用户。如果你喜欢深入了解这个平台,你可以从 Rasa 大师班、算法白板和面向开发者的 NLP视频开始,这些视频是你深入了解的绝佳方式。
对于新手来说,通过大量可用的学习资源学习 Rasa 应该很容易,但考虑到 Rasa 的架构,与 Dialogflow 相比就不那么容易了。
Dialogflow 是在考虑编码人员和非编码人员的情况下构建的,因此与 Rasa 中的学习曲线相比,该平台的可用性非常容易。
易用性或开发的便利性:
开发时间和工作完全取决于项目需求、资源和平台专业知识。但是对平台的期望是,它们有助于减少端到端开发的时间,但不损害质量和最终产品。
因为 Rasa 主要是一个内部部署平台,开源意味着开发者可以完全控制工程。开始之前,需要对平台进行设置和了解。虽然 Rasa 非常积极地将新功能添加到 Rasa 堆栈中,但那些不受支持的功能需要额外的工程来设置。
与 Rasa 相比,Dialogflow 提供了一个易于使用的平台和几个通道的简单集成过程,从而减少了大部分开发时间。
设置和配置:
一个人能以多快的速度开始使用该平台进行开发工作对于一些人(如果不是很多人的话)来说也很重要。Dialogflow 没有任何安装步骤,因此除了通常需要一两分钟的 webhook 部分之外,不需要任何基础设施设置。主要的优点是你不需要使用服务器来部署 Dialogflow 或 webhooks。如果您熟悉 Firebase 函数/Lamdba 函数,那么您可以选择无服务器架构。
Rasa 确实需要安装,因为它是一个 python 库。此外,虚拟助手的开发需要必要的配置,通常需要 15-30 分钟或更长时间,这取决于您是否会面临任何依赖问题。但是在开始生产部署之前,请务必阅读 Rasa 部署指南。
内置支持:
拥有内置特性,如小型会谈、基本实体支持和后续机制,支持开发人员减少一些冗余和基本的活动。而 Dialoglow 内置了其中的大部分功能,其中一些功能和流程可以通过下载 JSON 格式的功能来重用。
在 Rasa 的例子中,没有像闲聊这样的内置意图,但是这样一组意图一旦定义,就可以很容易地在多个项目中重用。使用 Duckling 和 Spacy 的系统实体可以很容易地配置在 Rasa NLU 管道。Rasa 具有一种配置,其中如果意图分类和动作预测置信度低于指定阈值,则可以触发回退响应。Rasa 不像 Dialogflow 那样有任何内置的默认、欢迎和回退意图。
培训形式:
虚拟助手旨在模仿人类行为。正如我们人类通过对话和讨论随着时间的推移了解更多一样,对虚拟助手的期望也是一样的。平台需要足够先进,以协助开发人员更直观、更自然地训练机器人。在这种情况下,两个平台 NLU 都用自然用户话语进行训练,这些自然用户话语用如下所示的实体进行标记。
培训意图和实体
痛苦是当开发人员不得不开发对话流时。如上所述,Rasa 的方法比 Dialogflow 更自然,因为它是基于故事的方法。Rasa 的交互式学习让开发人员在开发对话流时变得轻松。
作为现有 Rasa 用户开始使用 Rasa X
配额和限额:
当我们的流程非常复杂和漫长时,这一点非常重要。由于配额和限制可能会给开发者造成障碍,因此对话设计者和语音助手开发者将不得不相应地合作理解平台和开发者的限制。
Dialogflow 在很多方面都有限制,涉及到意图、实体的数量,以及动作名称中允许的字符数量等等。Google 一定是在进行了基准测试并牢记最佳实践之后决定限制的。
由于 Rasa 没有这样的限制,但是,如果任何班级的人数相当多,它可能会导致训练/测试数据不平衡的问题。因此,像 Dialogflow 一样,如果任何类都达到了极限,那么就应该重新访问数据,并进行必要的更改来平衡类。
内置 bot 模板或市场:
为了让开发人员对工作流有一个基本的了解,并建立在现有流程的基础上,一些平台提供了聊天机器人模板和市场,如 Chatfuel。
因此,Rasa 没有专门的现成的机器人模板,但它有样本机器人开始。 Rasa 示例(GitHub)
Dialogflow 提供了一组模板,确切地说,它们提供了 45 个模板,帮助许多开发人员理解流程需要和设计,并使用它们来开始使用平台。
从其他平台迁移:
Rasa 支持从 Dialogflow、wit.ai、Luis、IBM Watson 等平台轻松迁移。
Dialogflow 只提供到两个平台的迁移,即亚马逊 Alexa 和谷歌动作(尽管谷歌助手作为 Dialogflow 本身的一部分工作),但它不允许或接受其他平台的直接集成。
模型评估:
因为 Rasa 提供的模型可由开发人员根据需求进行配置。当我们试验多种配置时,非常需要这个特性。
你可以在测试你的助手了解更多关于评估 NLU 和 Rasa 核心模型的信息。您还可以比较不同的配置选项,进一步优化您的助手。
尽管 Dialogflow 的后端模型是一个黑盒,但我们仍然可以调整 ML 分类阈值,并在混合模型(基于规则和基于 ML)和纯 ML 模型之间进行选择。
部署
对于许多客户来说,这是一个重要的决策因素,因为大多数客户不希望数据通过不受他们完全控制的外部实体传输。这无疑是 Rasa 的优势所在,因为 Rasa 可以在本地运营。它可以部署在内部和云上。有关如何部署的信息,请参考部署您的 Rasa 助手。因为它是在本地部署的,所以您拥有自己的数据。虽然开发虚拟助手不同于传统的软件开发。Rasa 遵循软件工程最佳实践。参见设置 CI/CD 和集成版本控制。Rasa 还支持 S3 、 GCS 和 Azure 存储来保存你的模型。参考云存储获取信息。
因为 Dialogflow 是 Google 云平台产品,因为它是基于 UI 的 bot 框架。整个项目和当然模型将被存储和部署在谷歌云中。我们只能灵活地在内部或其他云平台上实现后端业务逻辑。
排除故障
调试和开发一样重要,因为它会消耗大量时间。虽然大多数平台在提供开发特性方面表现出色,但是有必要验证它们是否也提供了大量的调试特性。调试虚拟助手不同于传统的软件调试,随着项目范围的扩大,由于基于 ML 的方法中数据的集体效应,调试失败变得更加棘手。因为你可以看到所有的东西和所有的代码,所以通过知道预测分数,你可以确切地知道你训练的模型表现如何。此外,上面提到的评估方法可以帮助决策。对于在两个平台中编写的定制逻辑,传统的软件调试是适用的。
去年,Rasa 可能会是一个明显的赢家,但去年年底 Dialogflow 引入了一个名为 Validation 的部分,该部分评估了每个意图,并指出有一个特定的意图需要更多的训练数据才能表现得更好。
而 Rasa X 提供治疗和微调能力。Rasa 还为我们提供了培训 NLU 以及对话的选项,而 Dialogflow 仅提供了 NLU 组件的培训选项。所以 Dialogflow 在这种情况下仍然不是赢家。此外,如果一个人有很多训练数据,而机器人在理解大多数输入方面有问题,那么在 Dialogflow 的训练部分进行这些纠正是一项非常乏味的任务。
Rasa X-YouTube
5.服务支持
开发人员在设计对话和实现对话时需要支持,并牢记最佳实践。Dialogflow 通过其 Google Group 、 Slack 和 StackOverflow 、提供社区支持。而 Rasa 则有自己的社区 论坛 和stack overflow。
我们希望您花的时间值得一读 Rasa Vs Dialogflow 平台之战。我们将不断更新这个博客,增加新的功能。
如果你仍然不确定哪个平台适合你,请在评论中告诉我们是什么让你犹豫不决?
如果你现在确定要为你的项目选择哪个平台,那么请告诉我们是哪个平台,是什么让你选择了这个平台?
如果您已经在使用其中一款,请告诉我们原因。
如果你正在使用任何其他机器人框架来构建虚拟助手,请在评论区告诉我们。我们很想探索它们。
我们想借此机会感谢艾玛·威格特曼、苏维克·戈什哈、尼基尔·萨瓦利亚、 德瓦希什·马姆加因 、 维斯瓦·纳特·贾、的深思熟虑和彻底的审查,没有他们,就不可能保持文章的高标准。
如果您喜欢您刚刚阅读的内容,请帮助其他人找到它。随便敲👏只要你认为这篇文章是值得的,就请鼓掌。
感谢 Akhil Misri 与❤️的合作
Raspberry Pi:托管 Jupyter 笔记本的虚拟教程,你可以在任何地方访问它
原文:https://towardsdatascience.com/raspberry-pi-tutorial-on-hosting-a-jupyter-notebook-that-you-can-access-anywhere-32191f882b1f?source=collection_archive---------10-----------------------
这个系列主要是关于用一个 Jupyter 笔记本服务器来设置你的 Raspberry Pi,你可以通过开放的互联网在任何地方访问它。我们已经到了最后一章。
在前面的会话中,我们已经介绍了如何设置端口转发或云代理服务器,以便您通过 SSH 安全地连接到 Raspberry Pi。在我的第一篇文章中,我还介绍了 TCP/IP 如何处理不同的传入流量。现在我们知道了如何打开我们的 Pi 并通过 SSH 访问它,我们实际上可以复制同样的想法。在一个简单的单行程序中,Jupyter Notebook 运行在 HTTP 上(这似乎很明显,因为我们都使用 web 浏览器来使用 Jupyter Notebook)。因此,我们需要做的只是为来自 Pi 的 HTTP 流量打开一个端口,并将其与 Jupyter Notebook 应用程序连接起来。
对于必要的先决条件,请查看下面介绍云代理服务器设置的文章。我假设您已经在 remote.in 注册了一个云代理服务器,并且能够通过 SSH 连接到您的 Pi。我想强调的是,许多云代理服务器提供商为您访问您的 Raspberry Pi 提供免费服务。因为你实际上并不租用任何服务器,而是托管自己的服务器,所以许多提供商的服务通常都很慷慨。所以一定要自己去看看其他的供应商!
[## Raspberry Pi:以最安全的方式连接到您的 Pi——云代理服务器的教程
这是我关于将 Raspberry Pi 设置为远程 jupyter 笔记本代码编辑器的系列文章的继续。在最后…
medium.com](https://medium.com/@jimip6c12/raspberry-pi-tutorial-on-the-most-secure-way-to-connect-to-your-pi-cloud-proxy-server-11867ddaac95)
我们希望以最安全的方式做到这一点。这就是为什么本章将把我们到目前为止学到的所有东西结合起来。我们不仅要在我们的 Raspberry Pi 上公开一个端口,我们还要将 port/Jupyter 笔记本应用程序连接到云代理服务器。从用户的角度来看,没有什么不同,他们只需要访问另一个 URL,而不是原来的 IP 地址。但是从服务器的角度来看,这给了你很大的安全性。这真的很重要,因为我假设你们大多数人都在家里设置 Pi,这意味着如果出现任何问题,你们的家庭网络都将受到攻击。
再说一遍,这只是为了好玩。Raspberry Pi 并没有提供很多计算能力。但是假设你有一个 NVIDIA 计算盒,那么设置远程访问可能是一个好主意。此外,在数据科学行业,使用 linux 服务器来做 ML 工作现在是一种规范。学习如何建立一个只是让你比别人更有优势和方便。
你肯定可以通过端口转发开放你的笔记本应用程序的公共访问。但是这样做真的很危险。由于 jupyter 笔记本通常启用“jupyter magic ”,它可以在您运行的操作系统上创建、更改和删除任何文件,任何有意访问您的 jupyter 笔记本的人都将面临相当于 SSH 访问的巨大风险。
随着所有的 BS 封面,这里是步骤列表。我们开始吧。
- 在树莓 pi 上安装 Jupyter 笔记本。
- 添加配置并设置密码。
- 在云代理服务器上安装一个应用程序,这样你就可以把你的 Jupyter 笔记本暴露在开放的互联网上。
在树莓 Pi 上安装 Jupyter 笔记本
当前的 Raspberry Pi 版本不包含 python3-pip。所以首先我们需要安装 pip3,然后是 jupyter。SSH 到您的树莓派,然后运行
# install pip
sudo apt -y install python3-pip# install jupyter
pip3 install jupyter# running pip freeze should show jupyter in the list of packages your installed
pip freeze
添加配置并设置密码
Jupyter 为我们处理设置过程提供了很多方便的工具。它包括这三个步骤。
1。创建一个密码并散列它。
托管公共笔记本服务器的一个良好做法是,每次用户访问笔记本时都要求输入密码。为此,首先,我们需要创建一个密码,并将其安全地存储在 web 服务器中(因此是散列部分)。
要创建密码,请运行jupyter notebook password
,
$ jupyter notebook password
Enter password: ****
Verify password: ****
[NotebookPasswordApp] Wrote hashed password to /Users/you/.jupyter/ jupyter_notebook_config.json
然后,使用任何编辑器打开 json,您应该看到有一个散列密码(从 sha1 开始,见下图),请现在复制它,因为我们稍后需要将它粘贴到配置文件中。
2。创建配置文件。
运行jupyter notebook --generate-config
,在/home/USERNAME/.jupyter/jupyter_notebook_config.py
下应该会产生一个jupyter_notebook_config.py
。
使用任何编辑器打开。py 文件,您应该看到所有设置都被注释了,所以我们可以简单地添加我们需要的任何配置,而不会与任何设置冲突。
3。添加配置参数。
在任一行中,添加以下配置。
c.NotebookApp.allow_password_change = True
c.NotebookApp.password = u'your_copied_hash_password'
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8888
c.NotebookApp.allow_remote_access = True
allow_password_change :允许您在成功使用密码登录笔记本服务器后更改密码。
密码:复制刚刚生成的密码,记得粘贴 sha 哈希密码,不要粘贴文字密码!
open_browser :将其设置为 false,以防止 web 服务器像我们通常在本地机器上所做的那样打开浏览器。
端口:笔记本服务器使用的端口号。您需要记住这一点,因为我们需要将它公开给云代理服务器。
完成后,保存文件,安装完成!让我们跑去jupyter notebook
主持一个树莓派的笔记本吧!
这里涉及的大部分内容都在官方文档上。
在云代理服务器上设置应用程序
简而言之,云代理服务器所做的就是监听你指向的端口,并托管一个你可以从开放互联网的任何地方访问的公共服务器。每当你访问那个公共服务器时,它唯一做的事情就是把你的请求转发给开放端口的应用程序。在这种情况下,jupyter notebook 运行在端口 8888 上,使用 HTTP 协议。这意味着当用户访问公共云代理服务器时,HTTP get 请求将在端口 8888 转发到您的 Pi,Pi 将笔记本网站返回给用户。
假设您在 remote.in 设置了一个远程服务器,我们可以通过访问http://find.remote.it/来添加一个 HTTP 应用程序。选择您的 Raspberry Pi 设备,您应该在仪表板中,转到设置并在那里选择您的 Pi。
如果你需要一些快速帮助来设置你的 Raspberry Pi 中的云代理服务器,最好的资源是官方 gitbook 中的快速入门指南,或者是我的上一篇关于设置的文章。
然后,点击Add Manually >
,填写新服务。您可以填写您喜欢的任何名称,将类型设置为 HTTP,将端口设置为 8888(或者您选择在 jupyter 配置中使用的任何端口)。
然后设置终于完成了!现在访问https://app.remote.it/,选择你的 Pi 设备,点击你刚刚创建的服务。
点击突出显示的部分,启动公共服务器!
它应该返回一个你可以访问的公共 URL。
访问这个网站,您将访问您的 jupyter 笔记本!这并不局限于同一个局域网,你现在可以从开放的互联网上的任何地方访问它!
需要您输入密码的登录页面
这就结束了整个系列。我们讲述了如何安装 Raspberry Pi 操作系统,设置 SSH,云代理服务器,最后是 Jupyter 笔记本服务器。同样的方法也适用于建立一个网站和其他 ide,如 visual studio 代码(从技术上讲,目前建立 visual studio 代码时存在编译问题,我们自己无法解决这个问题。但这在未来肯定是有可能的!).所以,一定要尝试不同的东西,谷歌一下,测试你的技能。
如果你有其他项目需要帮助,请在评论区告诉我。感谢您阅读本系列。
使用 Python 绘制栅格数据散点图
原文:https://towardsdatascience.com/raster-data-scatter-plot-using-python-4bcdc8286769?source=collection_archive---------17-----------------------
地理信息系统
在某些情况下,您可能需要查看两个栅格数据集之间的关系。在 GUI 应用程序中这样做可能会令人恼火,因为存在滞后、不一致等问题。处理大分辨率栅格时甚至更糟。使用 Python 编写脚本可能是一种替代解决方案,可以为您提供可靠、快速、自动化和一致的结果。本文将指导您使用基本和流行的 Python 库来显示两个栅格数据集的散点图。
介绍
栅格数据基本上是一种图像或矩阵。作为图像或矩阵,它由数组组成,可以形成数据框或电子表格。甚至可以在 Adobe Photoshop 或者 Ms. Excel 中可视化光栅数据!每个栅格像元包含一个数值,该数值可以表示任何内容,具体取决于上下文。该值可以是高程、土地覆盖指数、NDVI(归一化植被指数),具体取决于具体环境。
栅格数据(来源:作者,2020 年)
在某些情况下,我们可能想要查看栅格之间的关系。比如坡度对绿化有影响吗?NDVI 和 NDBI 是什么关系?与交通设施的距离是否与二氧化氮或其他污染气体相关?
虽然一些软件提供了显示两个栅格数据之间散点图的方法,但我总是觉得这很令人恼火。显示绘图需要大量的 ram 和 CPU 资源,因此经常会导致延迟。窗格需要时间来加载,更改内容或绘图属性也需要时间来加载。此外,有时,我们需要自动化我们的工作,而不必做繁琐的任务,如布局和美化我们的图表一次又一次。当我们处理需要更多 RAM 或 CPU 的高分辨率栅格时,情况会变得更糟!
幸运的是,Python 有一种方法来完成这样的任务,而不必做那些繁琐的事情。使用 Python,在显示散点图时也可以减少对 RAM 和 CPU 容量的需求,因为不需要 GUI,并且可以最小化显示。我想分享这个过程,因此,本文的主要目的是向您展示如何预处理栅格数据(使用 GIS) 并使用 Python 将它们显示在散点图中。
逻辑过程
散点图需要 2 个输入,并且两个输入都需要是一维的。栅格数据,就其本质而言,是二维数据,所以我们需要将数据重塑为一维。这种整形是通过拆纱完成。
在拆纱之前,在我们开始拆纱过程之前,必须满足一些标准。必须确保栅格的每个像元在空间上对齐。这确保了一维松散的数据是合乎逻辑的,并且类似于对应关系。如果两个栅格数据之间存在空间不匹配,则生成的散点图将绘制错误的绘图。此外,关于标准将在数据标准部分中解释。
总之,raveling 产生一个长度为列乘以行的一维数组。确保两个栅格数据具有相同的列和行意味着确保行进数据的长度精确。
栅格数据散点图的思维过程(来源:作者,2020)
先验知识和要求
如果你想继续,建议你理解
- GIS 分析的基础,做一些栅格掩蔽/提取
- 地理空间数据类型(栅格数据),了解栅格数据的属性
- 投影系统,转换栅格数据的空间度量。
- Python 。库: NumPy (处理数组) matplotlib (绘图和数据可视化),图像分析(使用 PIL(枕头))。嗯,我们只需要图像分析部分来读取光栅数据并将其转换为 NumPy 数组,因此只要您可以读取图像光栅数据,它就会进行检查。我推荐 PIL,因为 OpenCV 或 Matplotlib Imread 不能直接完成这项工作,因为我们将处理单波段图像。
数据标准
如果我们要将两个栅格绘制成散点图,则必须满足一些标准:
- 这两个栅格必须具有相同的维度。这意味着两个栅格必须具有相同数量的列和行,以及相同的像素大小。这个标准很重要,因为阵列之间的对应关系必须一致,这样每个单元都有一个到另一个单元的连接。绘图时,对于一个 X 输入会返回一个 Y 值,在只有 1 个 X 输入的情况下,如果返回 2 个 Y 值,会比较混乱;函数不是这样工作的,散点图就是一个函数。
- 这两个栅格必须在空间上对齐并重叠。一个散点图并不表示空间对齐和重叠,因此这一标准必须使用 GIS 进行独立评估。
- 这两个栅格必须具有相同的坐标参考。我不认为这很关键,只要列数和行数相同。应该首先满足这个标准,因为我们必须匹配像素大小和空间相邻性。
- 如果一个栅格中的像元为空值,则另一个栅格的对应像元应改为空值。还是那句话,标绘这样的数据不符合逻辑。例如,一个 X 输入返回一个空值…我们应该如何绘制?Null 不是 0,所以最好直接删除这个值。
利用地理信息系统进行数据预处理:符合标准
如果您的栅格数据不符合标准(通常不符合),则必须进行一些地理空间预处理。我将解释如何使用 ArcGIS 工具集,对于其他软件,如 QGis,甚至是 Python 包,如 RasterIO 或 Geopandas,应该有等效的工具。请原谅我…
假设我们有 2 个栅格:X 轴栅格和 Y 轴栅格。这两个栅格彼此重叠,我们想要概述这种关系。我们可以把 x 轴栅格想象成 NDVI 栅格,把 Y 轴栅格想象成高程数据 aster。由于来源和采集方法不同,这两种栅格具有不同的属性。因此,需要进行一些预处理。
预处理步骤 1/3:决定一个光栅数据参考(例如 X 轴光栅)
选择一个参考栅格。我更喜欢最低比例的栅格(最低分辨率;最小数量的列和行)。您可以在 GIS 软件中查看属性,并找到栅格的列、行和像素大小。在本例中,我的栅格参考(我将其命名为 X 轴栅格)有 203 列、210 列和 158(米)像素大小。
x 轴栅格属性(来源:作者)
预处理步骤 2/3Y 轴光栅概述
例如,Y 轴栅格具有不同的属性,如下图所示。我们必须对此 Y 轴栅格进行更改,使其具有与 X 轴栅格参考相同的属性。
预处理前的 y 轴(来源:作者)
预处理步骤 3/3:使用 GIS 对 Y 轴和 X 轴栅格进行空间处理
有 3 个主要过程。
- 将Y 轴光栅投影到与 X 轴光栅相同的坐标系中。如果 Y 轴光栅具有相同的坐标参考,则不需要该步骤。这保证了像素大小有相同的单位。在这种情况下,我的 Y 轴栅格具有非常小的像元大小,这是因为 Y 轴具有不同的投影参考。
- 重采样 投影后的 Y 轴:投影后,Y 轴光栅的像元大小应该与 X 轴光栅具有相同的度量,但它们可能大小不同。重采样聚合或插值 Y 轴值以调整 Y 轴分辨率,使其与 X 轴分辨率相同。所以…将 Y 轴栅格重采样到 X 轴栅格的分辨率。
- 双重 通过相互屏蔽 提取栅格:双重屏蔽确保消除与非空值重叠的空值。所以,首先用 X 轴屏蔽 Y 轴(返回屏蔽的 Y 轴),然后用屏蔽的 Y 轴提取 X 轴。现在您应该有 2 个符合条件的预处理栅格了!屏蔽的 Y 轴栅格和屏蔽的 X 轴栅格。
- 最后,将这些栅格导出为 TIFF 格式,32 位浮点像素类型,无数据值为-10(或任何其他数字!你必须注意这个没有数据值!)
导出栅格(来源:作者)
使用 Python 散点图绘制栅格
现在,资料都准备好了,该做饭了。步骤真的很简单!
- 定义拆纱功能。读取光栅、清理光栅和移动光栅。函数声明缩短了脚本。
- 将 每个光栅数据分解成一维数组(使用分解功能)
- 绘制每个散开的栅格!
我们将需要这些库:
- Numpy 负责整理和管理数组
- 枕读取光栅
- Matplotlib 可视化散点图
绘图,步骤 1/3:定义松散函数
正如我在逻辑部分解释的,我们必须遍历每个栅格。我们将使用下面的 fetch_data 函数遍历栅格。 fetch_data 函数读取并清理光栅数据。清理很重要,因为 TIF 图像包含应该为空的值,但还不为空。清理会将这些值转换为空值,以便以后删除。 fetch_data 返回松散的、干净的、准备绘制的光栅。
绘图,步骤 2/3:分析数据
定义函数后,我们使用 fetch_data 函数移动 X 轴栅格和 Y 轴栅格。现在我们有了 x_data 和 y_data。
#path to each raster data
x_data_path = "folder/x_raster.tif"
y_data_path = "folder/y_raster.tif"#raveling the data
y_data = fetch_data(y_data_path)
X_data = fetch_data(x_data_path)
绘制,步骤 3/3:绘制数据
这部分只是 matplotlib 可视化基础。您可以使用简单的分散代码,如下所示。
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "Times New Roman"#Declaring the figure, and hiding the ticks' labels
fig, ax = plt.subplots(figsize=(15,8))
ax.set_yticklabels([])
ax.set_xticklabels([])#Actually Plotting the data
plt.scatter(x_data,y_data, s=0.1, c='black')#Making the graph pretty and informative!
plt.title("Raster Data Scatter Plot", fontsize=28)
plt.xlabel("X-Axis Raster", fontsize=22)
plt.ylabel("Y-Axis Raster", fontsize=22)
plt.show()
结果呢
使用上面的代码,我们应该有这个绘图结果。你有它!两个栅格的散点图!
绘制栅格(来源:作者,2020 年)
结束语
绘图过程相当直接,但使用 GIS 的预处理是棘手的。在这种情况下,GIS 预处理需要人工监督,因此您必须充分了解并小心谨慎。
仅当栅格输入在空间上对齐时,松散才有效。这种空间排列可能是应该彻底检查的最重要的方面。这一步至关重要,因为只要维度相同,对数据进行分析和绘图总是会产生散点图。这种虚幻的散点图会产生误导,因为它没有任何空间对齐的指示,但本质上,它显示的是空间未对齐的信息。
例如,从技术上讲,34x78 维 10m 分辨率栅格可以用 78x34 维 10m 分辨率栅格进行绘制。拆开时,它们产生相同的一维长度,34x78=2652。您也可以从技术上绘制这些栅格,但它们没有任何意义。如果两个栅格不重叠,情况会更糟。
因此,请始终仔细检查栅格数据是否在相同的维度上,并且在空间上对齐。祝你好运!
Ratlab:一个用于研究空间选择性神经元的慢特征分析工具包
原文:https://towardsdatascience.com/ratlab-a-toolkit-for-studying-spatially-selective-neurons-with-slow-feature-analysis-fbc45f65a0c3?source=collection_archive---------52-----------------------
图片由vaun0815 上的 Unsplash
我最近开始在德国波鸿鲁尔大学攻读神经科学博士学位。我的导师是 Laurenz Wiskott 教授,他在计算神经科学和机器学习之间的广泛领域开展工作。该小组使用的主要方法之一是慢特征分析(SFA),这是一种从时态数据中提取慢变化特征的无监督技术。使用该算法获得的一个显著结果是,它能够生成与哺乳动物大脑中发现的神经元的空间编码相匹配的放电模式。rat lab(Fabian schn feld 2016—https://gitlab.com/fabschon/ratlab)是一款通过模拟大鼠的探索行为,并用分层 SFA 网络处理感官输入来探索这一特性的软件。我最近把这个软件从 Python 2 升级到 Python 3:https://github.com/wiskott-lab/Ratlabv3
我很喜欢使用这个软件,我相信它是理解 SFA 的一个有价值的工具,特别是在空间导航的应用中。此外,该软件不需要彻底的编程经验,这使得它成为神经科学领域工作人员非常容易使用的工具。在介绍 Ratlab 及其主要模块之前,我先对 SFA 做一个(简短的)概述,最后展示一些使用该软件可以获得的不同结果。我强烈建议您自己安装 Ratlab,并在阅读时和我一起探索它。我希望你喜欢学习这个有趣和多才多艺的工具包!
内容
- SFA 简介
- Ratlab 简介
- 模拟
- 培养
- 抽样
- 把这一切联系在一起
SFA 简介
SFA 的动机是慢度原则。这表明,在多维时间相关信号 x (t)中,该信号中更有意义的特征通常比不太有意义的特征在更慢的时间尺度上变化。作为一个例子,考虑这样一个事实,我们的视觉系统已经进化,以便为我们提供关于外部世界的行为相关信息。这些信息可以采取多种形式,包括我们周围的物体或其他动物的位置,以及它们的相对运动。典型地,这样的环境特征在秒的时间尺度上变化。然而,对于组成这种信息流的单个组件来说,情况就不一样了,例如视网膜中的单个受体(或者等效地,计算机视觉系统中的单个像素)接收的信号。后一种类型的信息在时间尺度上的变化比任何与动物相关的特征都要快得多。SFA 利用了这一观察结果,并试图通过仅考虑那些缓慢变化的特征来从 x (t)中提取有意义的信息。
关于 SFA 如何做到这一点的详细和数学描述,请参见我的同事 Hlynur David Hlynsson 写的这篇帖子(https://www . ini . rub . de/research/blog/a _ brief _ introduction _ to _ slow _ feature _ analysis/)。或者,对于那些对神经科学中 SFA 的更广泛范围感兴趣的读者来说,Scholarpedia 将它已经获得的各种结果进行了分类(http://www.scholarpedia.org/article/Slow_feature_analysis)
分级 SFA (HSFA)网络具有避免 SFA 非线性扩展可能遇到的“维数灾难”的优点。这种形式的网络已经应用于虚拟老鼠的原始视觉输入。al 2007) 。有趣的是,这个网络产生的慢速特征类似于在哺乳动物大脑中发现的几个空间选择性神经元的放电模式。根据虚拟大鼠的运动统计,这些慢特征采取位置细胞、头部方向细胞、空间视图细胞的形式,并且还再现了网格细胞的一些特性。
Ratlab 允许我们通过在虚拟大鼠上进行我们自己的模拟实验来探索其中的一些结果。在这个软件中,各种实验设置和控制参数都是可能的,这大大增加了它的范围。该软件使用由 3 层组成的前馈分层 SFA 网络,在虚拟大鼠探索时处理其视觉输入。在每一层中,过滤器接收来自前一层的输入,并对该输入执行 SFA 算法。这些滤波器的感受野大小随着网络的每一层而增加,使得第三 SFA 层仅是单个节点,并且具有覆盖虚拟 rat 的整个视觉输入的有效感受野大小。Ratlab 能够研究位置细胞和头部方向细胞的放电。因为在本文中已经表明,独立分量分析(ICA)对于将原始 SFA 输出转换成现场点火是必要的。al 2007 ),Ratlab 也提供了包括这一点的选项。Ratlab 的网络架构草图如下所示。
Ratlab 使用的网络架构—图片来自schn feld&Wiskott(2013)
Ratlab 简介
Ratlab 软件是用 Python 写的,最新版本用的是 Python 3(【https://github.com/wiskott-lab/Ratlabv3】T4)。在这篇文章中,我将尝试概述该软件的更广泛的范围,并展示其作为理解神经系统空间编码的工具的用途。
如果有兴趣,读者可以看看该软件早期版本的 Gitlab 页面(https://gitlab.com/fabschon/ratlab),其中也给出了一些软件语法和功能的例子。此外,schn feld&Wiskott(2013)在本文中正式引入了 Ratlab。
Ratlab 工具包由四个核心模块组成:
ratlab.py, convert.py, train.py, sample.py
这两个模块中的第一个处理实验的模拟阶段,并且生成随后可由第三模块 train.py 用于训练 HSFA 网络的数据。最后,最后一个模块采用训练阶段生成的慢速要素,并在整个环境中对其进行采样,以便您可以评估所实现的任何空间选择性。在任何这些模块之后输入 help 命令,提供了它们角色的详细描述以及它们需要的任何相关参数。
此外,该软件有自己的 GUI 来设置实验和选择模拟参数,如果想快速了解该软件的范围,这是一个很好的起点。从 Ratlab 主目录开始,通过运行以下命令打开 GUI:
python RatLabGUI.py
这会产生以下窗口:
Ratlab 的 GUI——使用 RatLabv3 生成的图像
左上角是可用的不同环境几何图形,以及用于输入相应尺寸和模拟记录限制的字段。在底部是用于指定人造大鼠的运动统计的其他字段。这两类信息在右侧的 ratlab.py. 中使用,训练参数在 train.py 中指定使用。
完成这些字段后,您可以点击“脚本!”在目录中生成一个 bash 脚本,这样就可以使用以下命令从头到尾运行实验:
./RatLabScript
一旦您开始实验,将会创建一个 /current_experiment 文件夹,该文件夹将存储您的实验的所有相关文件。
虽然 GUI 对于开始熟悉实验如何运行是有用的,但是 Ratlab 作为命令行工具工作得最好。在下面几节中,我将概述以这种方式运行 Ratlab 时可以使用的不同设置和计算。我鼓励读者在阅读时利用每个模块的帮助菜单。
模拟
环境
我真正喜欢这个软件的一点是它在设计环境时提供的灵活性。 ratlab.py 模块带有 4 种预定义的几何图形:矩形、星形迷宫、T 形迷宫和圆形。长方形和丁字迷宫如其名。星形迷宫由几条远离中心区域的走廊构成(走廊数量由用户指定)。圆形迷宫只是近似圆形,并且采用正 N 边多边形的形状(N 由用户固定)。
此外, custom_maze 选项允许您通过在文本文件中指定每面墙的纹理以及交叉点来手动设计您自己的迷宫(已经包括了一个自定义迷宫示例:工具/custom_example_world )。要使用它,必须先将其移动到当前实验文件夹中)
下面您可以看到每个环境设置的示例,以及生成它们的相应脚本。在每幅图像中,上面显示了鸟瞰图(白点= rat 以前的位置,红色箭头=当前航向),下面显示了 rat 的当前视图。图(a)显示了默认情况下激活的矩形几何图形(当没有调用其他参数时,其尺寸为 60(长)x40(宽)x10(高))。
Ratlab 中允许的不同环境类型:矩形、星形迷宫、t 形迷宫、圆形迷宫和自定义——使用 Ratlabv3 生成的图像
除了环境几何体,Ratlab 还允许你使用 box 和 dbox 命令将障碍物插入到环境中。
运动参数
一旦你选择了你的环境,你就可以决定(I)固定虚拟老鼠的导航点,或者(ii)让老鼠探索固定的移动统计数据。
(一)定点
此选项的一个好处是,您可以保证虚拟 rat 将探索环境的某些区域。它利用了路径命令,该命令要求。txt 文件来定义虚拟 rat 必须导航到的点。例如,尝试运行 /tools 文件夹中的 radial_points.py 文件,并将输出保存为 /current_experiment 文件夹中的‘path . txt’。这是为具有适当臂尺寸的五臂径向迷宫设计的路径。为了在所有这些都指定的情况下运行模拟,只需输入:
python ratlab.py star_maze 5 12 40 8 path path.txt
这将导致大鼠在返回迷宫中心之前依次探索每条手臂,如下图(a)所示:
使用 ratlab.py 中的“路径”命令——用 Ratlabv3 生成的图像
重要的是,路径要尊重环境的几何形状,否则老鼠会在实验室的墙壁间游荡!作为一个例子,如果你像以前一样调用相同的模拟,但使用较短的臂的星形迷宫,你会得到类似上面的图像(b)。
最后,额外的循环命令决定了虚拟 rat 到达最终节点时应该做什么。如果调用循环,它将使用结束和开始节点之间的最短路径导航,否则它将在到达最终节点后立即出现在第一个节点(如果您选择调用循环,请注意这也考虑到了环境几何)。否则,可能会出现如上图(c)所示的情况。
(二)自由探索
相反,如果你希望让老鼠自由探索,Ratlab 提供了各种控制参数来确定虚拟老鼠的运动统计数据。在这里,我简要概述了其中最重要的几个。
弧线:为了提供不规则的轨迹,虚拟大鼠的旋转是使用以大鼠当前航向为中心的高斯白噪声项生成的。由于较小的旋转(即< 20 度)比较大的旋转(即> 90 度)更有可能,因此这捕捉到了真实的探索。然而,由于我们不想产生完全随机的旋转,我们可能会进一步限制允许的角度范围。这个参数就是这样做的,并设置旋转的决定弧。默认值为 320。下图说明了弧线。
ratlab.py 中“arc”参数的示意图—图片由作者提供
mom: 这个术语描述了大鼠的有效动量。对于较大的值,可以将虚拟 rat 视为一个大质量粒子,其前进方向对噪声有很强的抵抗力。在这种情况下,生成的路径是平滑的。对于较低的值,由于噪波,老鼠的前进方向波动更大,产生的路径更加锯齿状。默认值为 0.55
(注意:一些极端值,如 arc =0 或 mom =1,会导致老鼠在撞墙时被卡住,所以要小心这一点!)
偏差:如果你想让虚拟老鼠有各向异性的运动统计,这是一个有用的参数。通过在 2D 空间中指定一个特殊的方向,老鼠在这个方向上的移动速度会比在正交方向上快。这种偏差的大小需要具体说明。
实验参数
现在你已经选择了你的环境和运动参数,你差不多准备好开始你的实验了!但是,在你这样做之前,你需要决定一些最终的细节。
limit: 这控制了您希望实验持续多长时间,以及最终您希望在多少数据上训练 SFA 网络。显然,较大的数据集可以提供更好的收敛性,但代价是计算时间。另一方面,太小的数据集可能会在 SFA 展开中产生奇异的协方差矩阵。我建议从几千个时间步开始。
图像颜色:默认情况下,训练图像以彩色保存,但 Ratlab 也允许你以灰度或两种颜色方案同时保存。
一旦你决定了这些,你可以通过加入最后的命令:记录来开始你所选择的选项的实验。我建议在你这样做之前清空 current_experiment 文件夹,这样新的训练图像就不会与之前实验的图像混淆。一个包括迄今为止所讨论的选项组合的示例可能是这样的:
python ratlab.py star_maze 5 12 40 8 mom 0.5 grey limit 5000 record
生成的训练数据将被保存在文件夹:current _ experiment/sequence 中。如果你想检查它是否被正确保存,看看这个文件夹,你会看到一堆。当老鼠在环境中移动时,从老鼠的视野中拍摄的 png 图像。图像数量应与参数的限制相同。此外,文件 exp_finish.png 将在模拟结束时保存,并让您看到虚拟大鼠的总轨迹。
最后一步,我们需要重新格式化数据,以便它可以被网络训练。我们通过以下方式实现这一点:
python convert.py
该步骤没有参数,训练数据编译到文件current _ experiment/sequence _ data中不会花费太长时间。
培养
现在你已经准备好训练你的网络,重要的是考虑你希望从这个具体的实验中获得什么。正如介绍中所解释的,Ratlab 能够研究位置细胞和头部方向细胞的放电频率。在放置单元格(即位置选择性)的情况下,需要额外的 ICA 节点,调用时使用:
python train.py ICA
在没有 ICA 的情况下,SFA 已经对磁头方向部分敏感,但是包括它增加了这种选择性的精度。在任何一种情况下,Ratlab 都允许您使用 add_ICA 命令追溯添加 ICA 节点,而无需再次训练整个网络,因此您还可以查看两者并比较结果(我强烈推荐)。
训练阶段的另一个有用选项是使用参数 noise 将噪声引入网络。如前一节所述,在小数据集上训练会导致协方差矩阵中的冗余。虽然解决这个问题的一个办法是使用更大的数据集,但也可以尝试在网络中加入噪声,以减少冗余。
Ratlab 将一层一层地更新你的训练过程,完成后将训练好的网络作为. tsn 文件保存在 current_experiment 文件夹中。
抽样
一旦你的网络被训练,你终于准备好想象它已经学会的慢特征。这是通过在环境中的多个位置和方向上对大鼠的视野进行采样,并记录网络的响应来实现的。与培训阶段一样,你在这里的选择应该反映出你想学什么。Ratlab 可以做的采样有两种:空间采样和方向采样。如你所料,前者适用于研究空间选择性(位置细胞),后者适用于方向选择性(头部方向细胞)。在这两种情况下,都必须指定要采样的慢速特征的数量。在 Ratlab 中,这被限制为 32,选择一个较小的数字可以大大减少计算时间。
空间采样:这种方法的工作原理是将虚拟鼠定位在环境中的周期性位置(形成网格)。用户可以使用周期参数指定这些采样点出现的频率。最后,也是最重要的一点,在不同的实验中对环境进行采样,每次老鼠都面向不同的方向。有 8 个方向(北,东北,东,东南等。)并且用户可以选择特定的选项或者使用所有选项。Ratlab 还会通过对用户选择的所有方向进行平均,自动产生一组额外的输出。通过比较各个方向和平均输出,我们可以检查网络输出是否依赖于方向。因为这应该而不是是 place 字段的情况,所以它充当了解释结果的有用的诊断工具。下图显示了空间采样输出的示例。这些发射模式在空间上是局部的,不同的方向与平均发射几乎没有差别,表明方向选择性很小。在这种情况下,Ratlab 生成了描述环境不同区域的 place 字段!
矩形迷宫上的空间采样慢速特征—使用 Ratlabv3 生成的图像
定向采样:第二种类型的采样工作方式是固定虚拟 rat 的头部方向,并在对这些位置进行平均之前,在环境中的位置网格上对网络进行采样。这是针对所有 360°整数角度进行的,结果图允许您可视化网络慢速功能的方向选择性。下面是取自schn feld&Wiskott 2013的图像,显示了使用定向采样的 10 个慢速特征的响应。在这种情况下,包括了额外的 ICA 层,并且结果显示了对某些方向的明显偏好(尽管一些低水平响应仍然出现在其他角度)。
Ratlab 生成的定向样本图示例—摘自schn feld&Wiskott(2013)
把这一切联系在一起
现在您已经熟悉了 Ratlab 的每个主要模块,您可以开始根据您的特定兴趣设计实验了。为了最大限度地利用该软件,很有必要在不同的环境和参数下进行大量的模拟,以便您首先对实验范围有一个大致的了解,并且能够更全面地了解 SFA 在不同场景下的表现。
一个很好的例子是弧和矩参数,它们分别控制老鼠运动的直线度和平滑度。如果您尝试在将这些参数设置为默认值的情况下运行模拟,您将会看到 rat 转动了很多,并且具有相当锯齿状的路径。因为 SFA 提取缓慢变化的特征,所以对于这些参数值,头部方向图显示几乎没有方向选择性就不足为奇了。或者,通过减少弧和/或增加力矩,可以减少每个时间步长的旋转大小,这意味着在轨迹过程中头部方向变化较慢。因此,如你所料,如果我们像以前一样运行相同的模拟,但做了这些更改,头部方向图现在显示出更好的方向选择性。下面描述了这两种情况,其中显示了两种参数规格下最慢 SFA 特征的 rat 轨迹(左)和头部方向图(右)。
“arc”和“mom”参数对头部方向选择性影响的比较——使用 Ratlabv3 生成的图像
偏差参数也会对结果产生明显的影响,特别是对于空间采样。直觉上,人们会认为定向运动偏差会降低任何位置场发射模式的对称性。这正是发生的情况,如下图所示。在这个实验中,大鼠探索了一个默认大小的矩形环境,并且除了偏差之外的所有参数都设置为默认值。我输入的偏移方向为 0±1(即环境中的垂直轴),缩放因子为 1,这意味着该方向的移动速度是水平轴的两倍。下图显示了生成的前 8 个慢速特征。垂直轴和水平轴之间的不对称清晰可见。在这种情况下,由于水平位置的变化比垂直位置慢,所产生的 SFA 输出对水平位置更敏感,即水平位置更局部化。
使用 ratlab.py 中的“偏置”参数生成的不对称位置细胞触发—使用 Ratlabv3 生成的图像
到目前为止,所有显示的结果都是在最终 SFA 层之后包括可选 ICA 节点的网络中获得的。将这些与没有 ICA 节点的网络进行比较,在空间采样的情况下会产生有趣的结果。这可以在下图中看到,在矩形环境中对 16 个慢速要素进行了采样(同样使用默认尺寸)。这些输出与在 Franzius et 中发现的没有 ICA 的输出相匹配。al 2007 ,具有部分类似于内嗅皮层网格细胞放电的周期性放电模式。在这篇早期的论文中,作者用理论论据解释了这一结果,证明了 SFA 发现的慢特征形成了傅立叶基础,每个特征的慢度与其频率相关。这确实可以在下面的结果中看到,它清楚地描绘了频率增加的谐波函数。
前 16 个输出是在没有 ICA 的矩形环境中使用默认运动统计生成的。输出按慢度排序,并显示递增的频率——用 Ratlabv3 生成的图像
由于要花很长时间才能完全说明您可以使用 Ratlab 做的所有事情,我鼓励您深入研究该软件,并尝试自己的设置和参数选择。
我希望你喜欢这个 Ratlab 的介绍,并希望你在自己的研究中使用这个软件。万事如意!
参考和链接
- franzius m .和 Wiskott l .(2007 年)。缓慢和稀疏导致位置、方向和空间视图单元。PLoS Comput。生物。3:e166。doi: 10.1371/journal.pcbi
- Schö nfeld 和 l . Wiskott(2013 年)。Ratlab:一个易于使用的位置代码模拟工具。前面。计算机。神经科学。7:104.doi: 10.3389/fncom
- Schö nfeld 和 l . Wiskott(2015 年)。用分层慢特征分析模拟场所现场活动。前面。计算机。神经科学。9:51.doi: 10.3389/fncom.2015.00051
- http://www.scholarpedia.org/article/Slow_feature_analysis
- 我的课题组网页:https://www . ini . rub . de/research/groups/theory _ of _ neural _ systems/
用于快速并行强化学习的 Ray 和 RLlib
原文:https://towardsdatascience.com/ray-and-rllib-for-fast-and-parallel-reinforcement-learning-6d31ee21c96c?source=collection_archive---------11-----------------------
使用 Ray 进行 RL 训练的介绍教程
照片由 Jean Gerber 在 Unsplash 上拍摄
Ray 不仅仅是一个用于多处理的库;Ray 的真正能力来自 RLlib 和 Tune 库,它们利用这种能力进行强化学习。它使您能够将培训扩展到大规模分布式服务器,或者只是利用并行化属性,使用您自己的笔记本电脑更高效地进行培训。选择权在你。
TL;速度三角形定位法(dead reckoning)
我们展示了如何使用 Ray 和 RLlib 来训练一个定制的强化学习环境,这个环境是在 OpenAI Gym 的基础上构建的。
一个温和的 RLlib 教程
一旦你用pip install ray[rllib]
安装了 Ray 和 RLlib,你就可以用命令行中的一个命令训练你的第一个 RL 代理了:
rllib train --run=A2C --env=CartPole-v0
这将告诉你的计算机使用CartPole
环境使用优势演员评论家算法(A2C) 进行训练。A2C 和许多其他算法已经内置到库中,这意味着你不必担心自己实现这些算法的细节。
这真的很棒,特别是如果你想用标准的环境和算法来训练的话。然而,如果你想做得更多,你必须挖掘得更深一点。
RLlib 代理
您可以通过ray.rllib.agents
访问各种算法。在这里,您可以找到 PyTorch 和 Tensorflow 中不同实现的长列表,并开始使用。
这些都是使用算法的训练器方法访问的。例如,如果您想要使用如上所示的 A2C,您可以运行:
import ray
from ray.rllib import agentsray.init()
trainer = agents.a3c.A2CTrainer(env='CartPole-v0')
如果您想尝试 DQN,您可以拨打:
trainer = agents.dqn.DQNTrainer(env='CartPole-v0') # Deep Q Network
所有算法都遵循相同的基本结构,从小写 algo 缩写到大写 algo 缩写,后跟“Trainer”
更改超参数就像将配置字典传递给config
参数一样简单。查看可用内容的一个快速方法是调用trainer.config
来打印出适用于您选择的算法的选项。一些例子包括:
fcnet_hiddens
控制隐藏单元和隐藏层的数量(作为一个名为model
的字典传递给config
,然后是一个列表,下面我会给出一个例子)。vf_share_layers
确定您是否拥有一个具有多个输出头的神经网络或独立的价值和策略网络。num_workers
设置并行化的处理器数量。num_gpus
设置您将使用的 GPU 数量。
从网络(通常位于model
字典中)到各种回调和多代理设置,还有许多其他的需要设置和定制。
示例:为CartPole
培训 PPO
我想转而展示一个快速的例子来让你开始,并向你展示这是如何在一个标准的开放的健身房环境中工作的。
选择您的 IDE 或文本编辑器,并尝试以下操作:
import ray
from ray.rllib import agents
ray.init() # Skip or set to ignore if already called
config = {'gamma': 0.9,
'lr': 1e-2,
'num_workers': 4,
'train_batch_size': 1000,
'model': {
'fcnet_hiddens': [128, 128]
}}
trainer = agents.ppo.PPOTrainer(env='CartPole-v0', config=config)
results = trainer.train()
config
字典更改了上述值的默认值。您可以看到我们如何通过在config
字典中嵌套一个名为model
的字典来影响网络的层数和节点数。一旦我们指定了我们的配置,在我们的trainer
对象上调用train()
方法将会把环境发送给工人并开始收集数据。一旦收集到足够的数据(根据我们上面的设置,有 1000 个样本),模型将更新并将输出发送到一个名为results
的新字典。
如果您想要运行多个更新,那么您可以设置一个训练循环来连续调用train()
方法,以达到给定的迭代次数,或者直到达到某个其他阈值。
定制您的 RL 环境
OpenAI Gym 和它的所有扩展都很棒,但是如果你正在寻找 RL 的新颖应用或者在你的公司使用它,你将需要一个定制的环境。
不幸的是,当前版本的 Ray (0.9) 明确声明与健身房注册表不兼容。幸运的是,整合一个助手函数来让定制的健身房环境与 Ray 一起工作并不太困难。
让我们假设您有一个名为MyEnv-v0
的环境,它已经被正确注册,这样您就可以像调用任何其他健身房环境一样使用gym.make('MyEnv-v0')
来调用它(如果您还没有,您可以在这里查看我关于设置环境的逐步过程)。
要从 Ray 调用定制环境,您需要将它封装在一个函数中,该函数将返回环境类,而不是一个实例化的对象。我发现做这件事的最好方法是使用一个create_env()
助手函数:
def env_creator(env_name):
if env_name == 'MyEnv-v0':
from custom_gym.envs.custom_env import CustomEnv0 as env
elif env_name == 'MyEnv-v1':
from custom_gym.envs.custom_env import CustomEnv1 as env
else:
raise NotImplementedError
return env
从这里,您可以设置您的代理,并在这个新环境中对它进行训练,只需对trainer
稍加修改。
env_name = 'MyEnv-v0'
config = {
# Whatever config settings you'd like...
}
trainer = agents.ppo.PPOTrainer(
env=env_creator(env_name),
config=config)
max_training_episodes = 10000
while True:
results = trainer.train()
# Enter whatever stopping criterion you like
if results['episodes_total'] >= max_training_episodes:
break
print('Mean Rewards:\t{:.1f}'.format(results['episode_reward_mean']))
注意,在上面,我们用env_creator
来称呼环境,其他一切保持不变。
使用自定义环境的提示
如果您习惯于从环境到网络和算法构建自己的模型,那么在使用 Ray 时,您需要了解一些特性。
首先,Ray 遵循 OpenAI Gym API ,这意味着您的环境需要有step()
和reset()
方法,以及精心指定的observation_space
和action_space
属性。对于最后两个,我总是有点懒惰,因为我可以简单地定义我的网络输入和输出维度,而不必考虑输入值的范围,例如,gym.spaces
方法所要求的。Ray 检查所有的输入以确保它们都在指定的范围内(我花了太多时间调试运行,才意识到我的gym.spaces.Box
上的low
值被设置为 0,但是环境返回了-1e-17 数量级的值并导致它崩溃)。
当建立你的行动和观察空间时,坚持Box
、Discrete
和Tuple
。MultiDiscrete
和MultiBinary
不工作(目前为),将导致运行崩溃。相反,在Tuple
函数中换行Box
或Discrete
空格。
尽可能利用定制预处理。Ray 对您的状态输入进行假设,这通常很好,但它也使您能够定制预处理步骤,这可能有助于您的训练。
超越 RLlib
Ray 可以大大加快训练速度,并使深度强化学习的开始变得容易得多。RLlib 并不是最终的结果(我们在这里只是触及了其功能的表面),它有一个强大的表亲,称为 Tune,它使您能够调整模型的超参数,并为您管理所有重要的数据收集和后端工作。请务必回来查看如何将此库引入您的工作流程的更新。
RCar |全民机器人!
原文:https://towardsdatascience.com/rcar-robots-for-all-71ca3df71749?source=collection_archive---------48-----------------------
3D 打印的遥控汽车和 Android 应用程序能够使用蓝牙连接控制其许多功能
RCar
故事
项目陈述
我们生活在一个快速变化的世界。人们现在比以往更加紧密地联系在一起。技术正变得越来越强大。尽管令人惊讶的是,民族之间仍然存在巨大的不平等,少数民族有时会停止追求他们的梦想。
RCar 项目不会解决这个问题,但它提醒了人们团结起来为一个公平的世界而战的重要性。我们认为这是向前迈出的一步。
Next lines 将让你意识到 Arduino 和 3D 打印是如何通过赋予人们权力和在全球传播科学来引领潮流的。#Science4All
意味着简单,意味着便宜,意味着让机器人大众化。打印 3D 零件,拿起 Arduino,下载应用程序并发挥创意!;)
视频 1 — RCar 项目[宣传片]
查看 RCar 网站(针对谷歌 Chrome 进行了优化)
汽车
遥控车
这种机器人在我们的社会中有广泛的用途。军队应用、儿童玩具、自动化项目和专业竞赛是我们可能会发现这种设备的一些场景。它们可以通过多种技术来控制,比如:有线、蓝牙、Wi-Fi 或 4G/3G 信号是一些最著名的技术。一般来说,它们可以由石油或电力驱动。根据它们的大小,通常会有一个比例因子。这是通过将它们与类似的真实模型进行比较来完成的。他们可以在许多类别中找到:街道,漂移,越野车,卡车和卡车(图 1)。
图 1 小车、街道、漂移、卡车、卡车(从左上至右下)
电子设备
“硬件组件”一节解释了每个组件的选择。注意所用驱动器( L298N 电机驱动器)的接线与图 2 中的略有不同。DC 3V 电机有一个指向相反方向的额外轴(两者同步移动)。
图 2 汽车电路示意图
设计
使用 CAD 软件 SolidWorks 对 RC 汽车的所有部件进行建模。完整的模型(图 3)被分成几个组件(这意味着要单独进行 3D 打印):车轮,底盘,L 形车轴,连杆和车身。最后一个结构的形状来自一个有趣的尝试,大致类似于联邦调查局的车辆(查看图 3,右图)。
图 3 遥控车模型立体图
一开始,第一个要建模的部分是后轮。从 GrabCad 获得了一个初始设计。然而,为了适应我们的模型,必须进行一些更改。由于这些轮子是要连接到电机上的(有一个双轴,一个指向右边,另一个指向左边),所以必须建造一个具有适当长度和内径的圆柱形轴。我们在图 4(右图)中看到,空心内圆筒的形状改变了,以匹配电机轴的形状,而不是原来设计中的六边形空腔(图 4,左图)。
图 4 黑色车轮——原始设计/修改设计(从左至右)
需要特别注意的是,车轮是固定在双轴上的,因此,这两个车轮以电机的速度移动。对于两个前轮来说,情况并非如此。
相同的原始设计被用在前轮上。然而,模拟的轴是完全不同的,因为这些轴意味着围绕一个垂直的假想轴旋转,与伺服机构的桨同步。这种移动被限制为每侧旋转 45°。两个车轮的车轴都设计成 L 形,一端为圆柱形,另一端为矩形。后者总是平行于伺服的桨,并有一个切口,在那里一个弹性被包裹和连接到桨(图 5)。
图 5 前轮 1 的剖视图。这里可以看到 L 形车轴的两个特征:松紧带缠绕的切口,以及车轴和车轮之间的连接
每根车轴的两端都用一根横杆连接起来,以保证车轮同时向两侧移动。此外,为了确保轮子以与伺服叶片相同的角度旋转,轴铰链中心和切口中心之间的距离等于叶片的长度(图 6)。
图 6 底盘仰视图。可以看到两个前轮车轴之间的连接
为了保证轮子的旋转,在轴的圆柱端增加了一个旋转切口,并在轮子上设计了一个互补的凸台(图 5)。为了使接头可拆卸,要保证内外半径相差 0.3 毫米。同样的原理也适用于两个轴上的铰链。因此,两个圆柱形结构建立在底盘的底面上,每个结构的末端都有一个旋转切口。每个轴角都有一个互补的结构,也有 0.3 毫米的差异。
至于汽车的底盘,除了已经提到的结构,还有另外两个特点值得一提。首先,在底盘上做了一个切口,以适应伺服系统,因为桨必须与轴处于相同的高度。第二,为了让轮子转动,必须在前面切割(图 7)。
图 7 底盘、车轮、车轴和伺服系统的等距视图
最后,虽然由于尺寸和附件的性质,这部分没有打印出来,但车身也是经过设计的。我们确保包括各个照明系统的切口,用于(背面和正面)注册板的位置,以及 4 个与机箱顶面上的支架互补的支架——紧密连接两个部分。它显示在完全组装好的模型的侧视图、前视图和后视图的下方(图 8)。
图 8 使用 Soliworks 建模的汽车原型的不同视图
这部分项目面临的最大挑战是前轮旋转系统的设计。这不得不重做几次,以允许伺服施加适当的运动。然而,这从来没有测试过,因为轴是要连接到一个弹性伺服的桨,这只能在印刷后完成。
此外,值得一提的是,为了实现最终设计,所有组件都必须重做多次,尤其是负责零件之间连接的切割和挤压。这确保了零件对齐并具有适当的尺寸。
建模后,就设计而言,主要目标是 3D 打印(使用 Ultimaker 2+扩展打印机—图 9)几个零件,并使用它们来构建模型。最后,所有的电子元件都被转移到了车上。
图 9 Ultimaker 2+扩展
值得一提的是,打印机有尺寸限制,不允许我们打印车身。印刷需要使用 2.85 毫米的 PLA 细丝。虽然模型的一些较小的细节没有被完美地复制,但是印刷是非常成功的。
关于底盘底部设计的两个圆柱形结构(以适应 L 形轴),它们最终稍微容易断裂。这是通过包装一些耐水龙头胶水解决的。此外,为了将车轴固定在底盘上,每侧都缠绕了两条松紧带,这有助于保持汽车的稳定性和所有部件的位置。换句话说,他们把两个部分推向对方。避免这些问题的一个方法是增加这些结构的尺寸。
前轮内部的旋转结构是为了配合车轴而设计的,填充了支撑材料(与汽车一起打印)。这需要精确的手工操作,以避免在拆卸时松开这些接头。虽然,后来,我们意识到由于 PLA 的膨胀,这两个部分不合适。这是通过刮胡子解决的。接下来遇到的问题是车轮不太安全,这导致它们随着汽车的运动而弯曲。解决方案是在每个前轮上粘一个铝环(在插入相应车轴的补充部分后),并在每个接头处缠绕一些金属丝。
按照最初的设计,两个轴通过一根杆(使用 2 个螺钉和相应的螺母作为接头)和一根松紧带连接在一起。最初,这种弹性应该连接到伺服的桨。在测试了汽车的侧向运动并确认杆如果直接连接到桨上可以更好地翻转车轴后,我们决定用一根细金属丝将两者连接起来。因此,松紧带(平行于杆)被丢弃。伺服保持在适当的位置,用胶水把它粘在底盘的孔上。
对于前轮和后轮,沿着它们的周边分布热胶以增加地面牵引力。由于增加的直径,胶水条纹加到前轮上,底盘的一部分必须被刮掉,以避免汽车在侧向运动中发生颠簸。
最后,前、后和转向信号灯被粘在汽车通常的位置上。试验板和全球定位系统安装在背面。和底盘底部的 DC 3V 电机。所有其他组件都用几个橡皮筋固定在适当的位置,以保证它们不会影响汽车的运动或断开电路。
总的来说,尽管设计在印刷后需要一些修改,但结果是成功的。汽车能够稳定地移动,有足够的牵引力,完美地支撑所有部件的重量。此外,印刷成本可以忽略不计
优化的蓝牙模块将提高可操作性的范围,并减少命令(与应用程序一起给出)和有效执行的动作之间的滞后;
- 市场上有很多不同的电池。更轻、更耐用的电池将对汽车的自主性产生积极影响;
- PCB(印刷电路板)将代替试验板,使汽车电路更耐用,更不容易发生短路或其他电气故障;
- 悬挂系统是另一种将来可以添加到项目中的结构。如果原型车打算在越野赛道上使用,这一特性就显得更为重要;
- 模型车身本可以更符合空气动力学。然而,由于这一部分没有与汽车的其余部分一起印刷(由于尺寸和时间的限制),这在设计中没有得到优先考虑;
- 给汽车安装摄像头可以让我们在看不见的地方控制它;
- 几个部分都是要用塑料印刷的。使用其他低成本材料,如用于车轮的橡胶和用于车轴/底盘的一些金属合金,将使我们能够创建一个增强且仍然便宜的模型。
- 应用
图 11 RCar 应用
在 Play Store 或 MIT App Inventor Gallery 查看 RCar 应用。
安卓应用
使用麻省理工学院应用程序 Inventor 2(图 12),我们开发了一个 Android 应用程序,它能够使用蓝牙连接控制 RC 汽车的许多功能。具体来说,后轮的角速度,前伺服的旋转角度,喇叭,音乐,灯光和 GPS 组件。
图 12a MIT App Inventor 2 标志
图 12b MIT App Inventor 2 编程界面
一旦应用程序有了许多控件(一个操纵杆和几个按钮),我们就需要清楚地定义 Arduino 接收的数据源。这尤其重要,因为我们只能向 BT 模块发送一种类型的值(字符串、字节或整数)。应用程序和 Arduino 之间的通信是使用 1 字节数字完成的。因此,每个命令都与一个从 0 到 255 的特定整数相关联。
GPS 模块的加入最终增加了应用程序的复杂性。原因是,在某些时候,应用程序发送值,而在其他时候,接收经度和纬度坐标。由于这些数字有大量的十进制数字(这是达到可接受的定位精度所必需的),所以传输它们并不特别容易。问题的根源是实时传输这两个值,并且不与先前接收的值重叠。
与 GPS 模块发生的情况类似,操纵杆动作不容易协调。同样,水平和垂直坐标的传输是通过在它们的传输之间包括一个小的延迟来完成的。这是经过仔细调整的,因此 Arduino 不会将 x 理解为 y,也不会将 y 理解为 x。同时,为了防止重叠的信号传输。此外,还避免了应用程序命令按钮中常见的一系列数字。
如上所述,单一通信信道的存在阻止了我们一次传输多个值。因此,在尝试发送新指令时,应小心禁用所有先前激活的定时器命令。
另一个我们无法控制的问题是麻省理工学院应用程序 Inventor 2 中仍然存在的大量错误。在项目开发过程中,我们在对蓝牙模块(HM-10)的最新版本进行编程时,遇到了大量意想不到的问题。麻省理工学院应用程序 Inventor 2 中的 BLE(蓝牙低能耗)库在其功能工具方面仍然非常有限。我们最后用了 HC-05。如果我们的目标是传输零星的开/关值,比如在一个按钮或一组按钮的情况下,这就可以了。但是,就目前而言,在非常短的时间间隔内发送许多值(如操纵杆为获得实时响应命令所请求的那样)会使仍处于 AI2 同伴模式的应用程序崩溃,或者在构建应用程序之后崩溃。
用户指南
为了使用该应用程序,第一步是进入智能手机的定义,并与汽车的蓝牙接收器配对,该接收器的名称为 HC-05。(默认)密码是 1234。完成此步骤后,打开应用程序,单击屏幕底端的蓝牙图标,并与模块建立连接。该应用程序控制的所有功能——前灯、转向灯、喇叭、音乐播放器和操纵杆——现在都可以使用了。GPS 的图标在蓝牙图标旁边,也可以访问(注意,它在室内不起作用)。在图 13 中,描述了应用程序的一些特性。
图 13RCar app 主要功能描述
未来改进
根据稳定性和内存要求开发改进的应用程序;
- 扩展跨移动设备的兼容性:创建 iOS 版本;
- 引入实时 FPV(第一人称视角)功能将允许我们控制汽车,而不用让它保持在我们的视野范围内。因此,允许一组全新的应用程序。
- 视频 2 — RCar 项目[DIY]
关于
在里斯本大学高级技术学院 Luís Sousa 教授的指导下,开发了一辆遥控汽车和相应的应用程序。
与本项目相关的所有应用程序、CAD 文件和装配图都是免费的。而且永远都是…
路易斯·丽塔&萨拉·弗雷塔斯
这个项目中使用的东西
硬件组件
Arduino Nano R3——使用 Arduino Nano,我们能够降低能耗并提高最终项目的可移植性。这是以牺牲一些计算能力为代价的。由于这个 Arduino 的模型只有 2 个串行连接(RX 和 TX-用于在蓝牙模块和 Android 应用程序之间传输数据),我们需要包括一个额外的串行端口来接收智能手机中 GPS 模块的位置值;
- DC 3V 电机-电机由 9V 电池供电,由 L298N 驱动器控制。它有两个轴(一个指向右边,另一个指向左边,同步移动);
- 在 Arduino 脚本中,SG90 微伺服电机伺服的旋转下限和上限分别为 45 度和 135 度。避免汽车车轮的过度旋转。我们首先在我们的项目中使用了一个旧的伺服系统,但是由于坏的润滑齿轮,它被一个新的取代了。这样,我们消除了抖动,大大提高了角度精度;
- 电阻 220 欧姆-我们包括几个电阻,以限制通过发光二极管的电流强度;
- led(红色、黄色和白色)-关于车辆中存在的不同灯,我们总是包括一个电阻,以限制通过二极管的电流强度。这是在(2)前,(2)后和(2)转向信号灯上完成的。这些灯完全由 RCar 应用程序控制,除了后面的那些在汽车向后加速时自动打开的灯;
- HC-05 蓝牙模块-蓝牙模块采用了类似的方法。虽然,在这种情况下,我们在电路中包括一个分压器,以便 HC-05 接收来自 5V Arduino 端口(TX)的一半电压(在 RX 端口)。然而,这是可有可无的。因此,它没有包括在电路图中(图 2);
- L298N 驱动器-L298N 驱动器是一个电气部件,其行为类似于 H 桥。根据闭合的断路器,电流将沿两个不同的方向流过 DC 电机。这样,通过始终向 Arduino 施加正电压,电机可以顺时针或逆时针旋转。此外,它还控制轴的旋转速度。这两组中断器由驱动器中的 IN1 和 IN2 引脚控制;
- GPS 模块(NEO-6M-0–001)-我们还决定在汽车中增加一个额外的功能— GPS。这可以以低于 3 米(半径)的显著精度(考虑到价格)检测位置。然后,带有红点的地图显示在应用程序中,位置正确。注意,由于 GPS 模块的限制,不可能在室内得到汽车的位置;
- 压电扬声器-电路中还增加了一个扬声器。每当点击应用程序的相应按钮时,就会发出声音信号。波形的持续时间和频率都是在 Arduino IDE 中定义的;
- 9V 电池-汽车由连接到 L298N 驱动器的 9V 电池供电。这既是对电机的供电,也是对 Arduino 的供电(因此,是对所有剩余电路的供电);
- 9V 电池适配器-带有开/关按钮,更容易切断电路的电源;
- 试验板——先前组件之间的所有连接都在试验板中可逆地进行;
- 跳线-公-公、公-母和母-母线确保所有电气元件之间的连接;
- M3x20 螺丝和螺母-这些是汽车的酒吧和每个 L 形轴之间的旋转接头;
- 橡皮筋- 2 个橡皮筋用于将 L 形轴压在底盘上,另外 5 个橡皮筋用于固定试验板顶部的所有非胶合部件;
- 金属环-每个前轮上有一个,以减少前轮和相应车轴的圆柱形部分之间的松动。事实上,这种结构是由 2×180 个环用热胶水粘合而成的。一旦环的内径需要与轴的最细部分具有大致相同的尺寸,这是安装两者的最简单的方法;
- 金属线-短而细的金属线用于连接汽车的酒吧和伺服的桨。这允许前轮转动;
- 热熔胶——我们用一管便宜但有效的热熔胶将大部分部件固定在汽车上。
- 软件应用和在线服务
Arduino IDE
- 麻省理工学院应用发明者 2
- Google Play
- GitHub
- 苹果 Final Cut Pro X
- SolidWorks
- GrabCAD
- 网络风暴
- 像素化器
- 烧结
- 草图制作
- 手工工具和加工机械
位于荷兰的 Ultimaker 2+Extended-Ultimaker-3D 打印机制造公司;
- Android 智能手机- RCar 应用程序,目前仅适用于 Android 用户。要求安卓 2.2 以上;
- 热胶枪-热胶水分配器。它会升温并向周围喷射。
- 定制零件和外壳
CAD 模型
“打包”一套 SolidWorks CAD 文件(SLDPRT 和 SLDASM)。换句话说,打印全车所需的一切。
下载
RCar
装配了所有 SolidWorks 零件的完整模型。仅供预览。这个文件包含在以前的包中。
三维模型
图表
电路
1.由于缺少与我们在项目中使用的电机驱动器(L298N 驱动器)类似的电机驱动器,我们用另一个少一个输入端口(定义电机轴的旋转方向)的型号代替了它;
2。DC 3V 电机有一个双轴,而不是。
密码
麻省理工学院应用程序发明者 2 (Java)
Android 应用程序就是用这段代码创建的。你将需要访问麻省理工学院 AI2 网站并导入文件进行可视化或编辑。
注意:MIT App Inventor 2 是一种基于 Java 的编程语言。
完成 MIT App Inventor 2 代码 ( 下载)
阿尔杜伊诺
Arduino Nano 中实现的整套指令。我们提醒您注意需要导入的库。
完成 Arduino 代码
Complete Arduino Code
重现历史
原文:https://towardsdatascience.com/re-animated-history-6b5eb1a85efa?source=collection_archive---------36-----------------------
正在使用的深度学习模型
历史形象,被#去理想化和# 3d 化
我们学习了各种奇妙的模型,由深度学习驱动。从长远来看,你可以称之为数据驱动的可视化复兴。但是,对于人工智能图像处理的所有这些多种方式,我们能做些什么呢?特别是如果我们结合各种 DL 方法。
你可以建造一台时间机器。
这里有一个有趣的例子,一个图像在激发团队合作中变得活跃的速度有多快。以及意想不到的事情是如何发生的。
这里是桑街、纽约市曼哈顿、曾经的心小意大利:
来源:(维基)
Jason Antic 是 DeOldify ( DL 驱动模型,允许给 B & W 照片上色)的开发者,他经常在他的 twitter 时间轴上展示他工作的最新成果:历史图像正在恢复它们的色彩和新鲜感。
昨天他上传了上面的图片,被#DeOldified:
注意细节的分辨率和调色板的丰富性!你可以没完没了地思考曼哈顿老街的复兴(在电影、书籍和电影中经常被提及):
例如,杰森发现了有趣的小细节(历史的人文因素在每一种形式中都令人着迷):
另一位推特用户发现了时光旅行的奥兰多·布鲁姆:
在这里,你可以看到另一个人生动的童年:
甚至这个:时光机。
整个构图几乎恳求虚拟化。
示意图片
所以我添加了由西蒙·尼克劳斯开发的 3D 本·伯恩斯方法:
或者,更好的质量:
3D 本·伯恩斯方法最适合这种清晰的消失点图像。图片被分成不同的空间层,层后的背景空白被内容敏感的修补填充。
上面这样的模拟跟踪拍摄,是有说服力的。然而,它仍然可以通过更多的动力得到改善。乔纳森飞做到了。他微调了 3D 本·伯恩斯相机的设置:
试验参数创造新的愿景:
然而,他甚至完美地夸大了设置,直到一个过高的质量:
你再也认不出最初的图像,但你会发现图像背后新的边界,是人工智能虚构出来的:
因此,在人们敏锐的思维和深度学习的结合下,历史镜头的交互式检查已经成为对现实极限的迷人探索。
深度学习不仅仅可以打开新的领域,它还可以开阔我们的思维。
角度反应事件和 Python 后端驱动的散景图
原文:https://towardsdatascience.com/reactive-event-and-python-backend-driven-bokeh-charts-in-angular-6fc23d608eeb?source=collection_archive---------22-----------------------
引用。:摘自http://infographics.quantecdc.es:8080/dashboard
如何克服 ajax 调用的缺点,让散景图更具反应性。
为什么通过 Ajax 方法进行数据轮询是一个死胡同
当谈到定期更新的数据视图时,来自 web 前端的 Ajax 调用似乎是准标准。但是 Ajax 调用使用轮询技术。这意味着客户端通过 http 调用在每个时间段向服务器端请求新数据,这有几个缺点:
- 降低视图的整体反应速度,尤其是当轮询时间低于 50 毫秒时
- 当你必须事先决定你想承认哪一个延迟时间时,轮询时间是至关重要的。如果您希望在数据更改事件上有短暂的时间延迟,轮询肯定不是最佳选择。
- 即使数据根本没有变化或者保持在非关键范围内,轮询也会永远进行下去,这是网络和服务器上的额外负载,尤其是当数据平台需要随着数据量和视图请求的增加而扩展时。
这也是为什么事件驱动的更新技术总是优于轮询技术的原因。我们将向您展示如何在角度散景设置中实现这一点。
角度事件
Angular 已经实现了一种内在的事件驱动机制,这就是为什么将 Python 的异步范例与 Angular 事件检测结合起来显然是非常有吸引力的。
在 Python 方面,处理异步的最成熟的 web 服务器是 aiohttp。它还提供了一种简单的可能性,即打开一个 websocket 服务器,Angular 客户机可以连接到这个服务器上。
在我们发表的关于 angular 和散景图结合的上一篇文章中,我们通过 websocket 连接将 json 格式的图表发送到 Angular。但是仍然依赖 ajax 调用来更新图表,因为 BokehJS API 主要提供了用于嵌入图表的黑盒嵌入方法。在深入研究了 Bokeh-API 之后,似乎不使用 embed 方法而是一步一步地进行嵌入是非常可行的。因此,我们能够提取 Bokeh 文档对象,并从该对象中访问数据源。
由于互联网上有很多可用的视图示例,我们决定就如何处理源对象以及如何使用它来将更新范例更改为事件驱动给出一点见解。
源对象更新
我们现在把重点放在有角的一面。在 item.doc 中接收到用 Python 以 json 格式生成的 chart-item 后,我们可以用
const doc = Bokeh.Document.from_json(item.doc);
可以通过调用从文档中提取源对象
const source = doc.get_model_by_name('my-tiles').data_source
其中在数据模型的后端也使用相同的名称“my-tiles”是很重要的。嵌入现在像这样工作
const roots: Roots = {[item.root_id]: el}; Bokeh.embed.add_document_standalone(doc, el, roots, false);
其中元素是 Http 元素,通常可以通过它的 id 获得。
const el = document.getElementById(id);
前一行的文档与散景文档无关,只是全局 app 文档钩子。既然我们已经访问了源代码,那么继续我们通常的事件驱动更新就不那么困难了。
public getNumberChartData(source: any) { const callbackId = 'numberChartData'; this.messageService.awaitMessage().pipe(filter(msg => msg.name === callbackId)) .subscribe( msg => { source.data.label[0] = msg.args.number; source.data.color = msg.args.color; source.change.emit(); }); }
每当相关的 websocket 消息到达 MessageService 时,就会调用 source change 事件,这将导致固有的图表更新。对于任何新源,该订阅必须只进行一次,并且应该确保当图表组件被移除时,订阅被取消订阅。
Python 方面:观察者和可观察对象
当谈到异步编程时,似乎仍然必须寻找最佳实践的例子。异步范式令人困惑,因为它打破了简单的未来,将异步编程有效地简化为三件事:异步、等待和循环浮动。由于大多数例子都是单一的、小的,所以首先似乎很难将整个项目设置为异步的,尤其是当人们试图将异步和非异步功能结合起来的时候。有时甚至不可能引入异步,例如常用的 init 函数。它只是不接受前面的异步。
同样令人吃惊的是,循环主要是作为一个持久的阻塞调用,循环内的所有东西都要被关注,而循环外的所有东西都将永远消失。这并不完全正确,但是根据我们的经验,当运行到完成时,如果一切都在循环内,这是最佳实践。
为了切换到一个完全事件驱动的范例,如果我们在模块 nucosObs 中引入一个观察者可观察的范例,设置起来会容易得多。因此,我们构建了一个简单而强大的观察者机制,它允许避免将每个方法引用分配到我们想要调用它的地方。另一方面,我们现在必须分配可观测量,这些可观测量为任何正在监听可观测量的观察者携带信息。此外,我们对可观测量内部数据的反应方式可以在事后很容易地单独调整。
所有的可观测数据都是在所谓的接口中输入的。例如,这可以是控制台或 websocket 服务器上的文本输入。在界面上,我们可能只关注如何从数据源获取数据,并将其输入到可观察对象中。这个任务与处理数据的任务是完全分离的。在遗留上下文中,回调通常连接到数据,但即使这样,在这里也不是必需的。
另一方面,观察器是在开始主循环调用之前设置的。但它们包含了所有固有的反应。它们监听可观察对象,并为任何目的解析数据,甚至通过调用后续方法。解析功能可以非常容易地个性化。
作为一个额外的奖励,观察员可以很容易地安排单一或定期的任务。
最初发表于【https://github.com】。
Heroku 上的 ReactJS + Python 烧瓶
原文:https://towardsdatascience.com/reactjs-python-flask-on-heroku-2a308272886a?source=collection_archive---------3-----------------------
为 API 开发和部署制定框架
马库斯·斯皮斯克在 Unsplash 上的照片
我真的很喜欢做东西,但我真的讨厌部署。我有一堆想法,放在我的本地机器上,只是积满灰尘,因为我懒得部署它们让全世界看到。在过去,我一直试图从零开始建立自己的服务器。这包括安装所有的 linux 包,处理 nginx 配置和所有我不喜欢的服务器管理工作。在我的开发生涯中,出于某种原因,我从未听说过 Heroku。Heroku 是我所需要的完美人选。它基本上允许你连接一个 git 存储库,当你把它推到他们的远程时,它会自动计算出你在运行什么(检测 flask 或 node.js 等),并自己完成构建。实际上只是将代码推向生产,没有服务器端的麻烦。
为了纪念我新发现的最好的朋友,我想展示如何构建一个简单的 ReactJs + Flask 框架,我将用它作为我今后开发 API 和 Web 应用程序的模板。这里的想法是让一些 可重用 ,这样我就可以克隆回购协议,开始做一些新的事情,而不需要重做任何步骤。
建立 Heroku
为此你所要做的就是去 www.heroku.com 注册一个账户。一旦一切就绪并登录,您应该会看到这样一个屏幕,显示您当前的应用程序:
我的 Heroku 仪表板
然后你所要做的就是点击右上角的新建按钮,创建你自己的新应用!是的,确实是这样。
据我所知,它基本上在他们的服务器上为我们建立了一个 git 存储库,它与我们的用户帐户相关联。这意味着我们现在可以在 heroku 上向这个应用程序推送代码。问题是如何做到这一点?这是你必须下载 Heroku CLI(命令行界面)的地方。这允许我们运行命令行命令来登录和推送代码等。CLI 可在此下载:
[## Heroku CLI
Heroku 命令行界面(CLI)使得直接从终端创建和管理您的 Heroku 应用程序变得非常容易…
devcenter.heroku.com](https://devcenter.heroku.com/articles/heroku-cli)
请确保为您的系统下载它。安装完成后,你可以打开一个终端并运行 heroku 登录,这会打开一个网页浏览器让你登录你的账户。
其他软件
你还需要一些其他的软件。我不打算详细说明如何安装它们,但我会在这里列出它们。
- Git:这是一个仓库管理系统
- Python:这当然是 Python。我会推荐 3.7.x,因为这是我正在使用的!
- NodeJS/NPM:用于反应堆开发部分
本地设置
现在,所有的软件都已安装,我们将设置我们的目录,并开始制作我们的 API 和客户端前端接口。首先,我们要创建一个新目录(注意:我用 datastuffplus 来命名我所有的东西):
mkdir datastuffplus
cd datastuffplus
git init **<--- This makes the current folder into a repo****# Links the repo to our heroku project!**
heroku git:remote -a datastuffplus
至此,我们所做的就是创建一个链接到 Heroku 项目库的目录。这意味着当我们添加代码并提交/推送时,它会被 Heroku 和 self 部署。接下来,我们可以使用 Flask 构建一个简单的 API。
构建 Flask API 和 Web 服务器
我们的 flask 服务器将做两件主要的事情。第一个是服务的网页文件,使我们的最终网页(前端)。第二个是充当 API 服务,完成一些 python 特定的任务,并将结果发送回前端网站。
首先为我们的 python 安装生成一个虚拟环境。这允许我们将这个环境从我们的系统中隔离出来。如果您需要在这个项目上安装某些版本的包,而在另一个项目上安装不同版本的包,这将非常有用。
python -m venv venv/
要使用这个环境,我们需要激活它。根据您的操作系统,它可能看起来有点不同,但在 Windows 上,我们运行:
cd ./venv/Scripts/
activate.bat
接下来,我们安装 python 包,并为部署到 Heroku 做好准备。请注意,因为我们在活动的 venv 中,所以软件包只安装在这个隔离目录中。太好了。
pip install flask flask-cors gunicorn boto3 matplotlib
上述 python 包适用于以下情况:
- 烧瓶:主服务器功能
- flask-cors :用于跨原点请求。基本上允许您在不违反安全性的情况下从不同的系统调用端点
- gunicorn :这是一个生产服务器包,Heroku 使用它来为站点提供服务
- boto3 :这个包用于访问 Amazons S3 存储桶(把它想象成一个基于云的目录来存储文件) NB :由于 Heroku 不能保证文件在停止运行后的持久性,所以使用这种云存储是非常重要的
- matplotlib :用于制作地块的包。这很重要,因为我们的测试 API 将使用它来生成一个饼图
在我们真正编写服务器代码之前,还有几个步骤。为了跟踪所有需要的包,Heroku 需要一个requirements . txt文件,它基本上列出了我们已经安装的所有 python 包。要做到这一点,我们只需运行:
pip freeze > requirements.txt
饼图 API
那么我们真正想要创造的是什么呢?我想要的一件事是一个漂亮的高分辨率饼图,用来展示我制作的一些图形。我通常使用 python matplotlib 来完成这项工作,但是如果我每次都需要实际运行 python,这就有点烦人了。所以,让我们把它变成一项服务,让我的生活更轻松,也让其他人可以使用它!奖金!
第一步是始终只定义完成工作的函数。下面我粘贴了制作饼状图并保存到本地的函数:
def GeneratePie():
**# Get the input data (Wedge is the distance between slices)** data = [60,40]
colors = ['#003049','#ffcdb2']
wedge = 0.05 **# Make a matplotlib (high res) pie chart!** fig1, ax1 = plt.subplots(figsize=(20,20))
patches, texts = ax1.pie(data,explode=[float(wedge) for w in
range(0,len(data))], colors = colors, startangle=90) **# Equal aspect ratio ensures that pie is drawn as a circle** ax1.axis('equal')
plt.tight_layout() **# Save the image temporary on the local machine** plt.savefig(os.getcwd() + '/test.png');
输出如下所示:
啊太好了!
所以我们现在有了我们想要的函数。下一步是将它包装在我们的 flask 服务器中。
在您的工作目录中创建一个名为 app.py 的新 python 文件。裸露的骨骼看起来是这样的(我们稍后会填充):
我们做的第一件事是导入我们需要运行的包
from flask import Flask,
render_template,send_from_directory,request, jsonify,
make_response
from flask_cors import CORS, cross_origin
import boto3
import os
接下来,我们将定义 flask app 对象,并设置静态文件夹和 URL:
app = Flask(__name__
,**static_folder**='client/build',**static_url_path**='')
cors = CORS(app)
在上面的例子中,当我们还想为前端网站提供服务时,静态文件夹和 url 是很重要的。 static_folder 将指向我们的 ReactJS 前端的构建版本,并且 static_url_path 需要被设置,否则构建将引用所有错误的位置。即。CSS 文件的路径将会是相对于位置的,如果你不指定它,它们将无法被找到!
[**@app**](http://twitter.com/app)**.route('/api')**
[@cross_origin](http://twitter.com/cross_origin)()
def Welcome():
return "Welcome to the API!!!"[**@app**](http://twitter.com/app)**.route('/api/justpie/')**
[@cross_origin](http://twitter.com/cross_origin)()
def GeneratePie():
....[**@app**](http://twitter.com/app)**.route('/')**
def serve():
return send_from_directory(app.static_folder, 'index.html')if __name__ == '__main__':
app.run(host='0.0.0.0')
在上面的框架代码中,我们看到了服务器的三条新路由。这些充当您可以通过 web 浏览器调用的端点。
- 【T6@ app****。route('/api'): 这是将作为 api 调用基础的路由。它现在所做的就是发回一个愉快的小信息!
- @ app。route('/api/justpie'): 这个端点完成了大部分工作。我们将在这里调用之前的饼图生成函数(做了一些修改,通过 get 请求接收用户输入,并将最终图像存储在 S3 桶中)
- @ app。route('/'): 这个根端点将指向 ReactJS 代码的构建版本,我们将在这里调用端点并在 web 浏览器中显示结果。
既然已经建立了框架,我们需要看看如何将独立的 python 函数修改成 flask 可调用函数。
修改功能
上面的 GeneratePie()函数有两个主要的变化。
- 我们需要通过 GET 请求接收来自客户端的输入
- 将最终文件存储到亚马逊 S3 存储桶中,这样它可以在 Heroku 重启后继续存在
为了进行第一次修改,我们替换以下代码
data = [60,40]
colors = ['#003049','#ffcdb2']
wedge = 0.05
随着
**# Get the input data from the request**
data = request.args.get('data')
colors = request.args.get('colors')
wedge = request.args.get('wedge')**# Turn it into a list**
data = [float(i) for i in data.split(',')]
colors = ['#'+i for i in colors.split(',')] **<-- Adding # to string**
数据传递的方式是通过 web URL。例如,为了模仿原始函数中的操作,您可以将 API 调用为:
http://localhost:5000/API/just pie/?data=10,10,80&colors=003049,ffcdb2,0fc9b2&wedge=0.02
你可以看到我们是如何传递参数的。
注意:颜色没有使用标签,因为它是一个特殊的字符,所以我们只是在把它变成一个列表的时候加上这个标签
第二个变化是替换代码:
**# Save the image temporary on the local machine** plt.savefig(os.getcwd() + '/test.png');
随着
**# Save the image temporary on the local machine**
plt.savefig(os.getcwd() + '/test.png');**# Connect to the S3 bucket and just drop it on there**
s3 = boto3.client('s3', aws_access_key_id=**ACCESS_KEY**,
aws_secret_access_key=**SECRET_KEY**)
s3.upload_file(os.getcwd() +
'/test.png',bucket,'test.png',**ExtraArgs={'ACL':'public-read'}**)**# The return will be a json where message contains the image path (URL)**
status = {};
status['status'] = 'DONE';
status['message'] = '[https://'+**bucket**+'.s3.ca-central-1.amazonaws.com/test.png'](https://'+bucket+'.s3.ca-central-1.amazonaws.com/test.png')return make_response(jsonify(status), 200)
在上面有几样东西可以看看:
- 我们仍然在本地保存文件,但是我们随后连接到 S3 存储桶来上传文件
- ACCESS_KEY 和 SECRET_KEY 来自你自己的亚马逊账户。我不会详细介绍如何设置它,因为有上百万篇文章,而且它非常无缝!extra args = { ' ACL ':' public-read ' }用于使文件公开。
- 最后,你可以看到我们发回了一个 json 响应,给出了我们的公共 S3 桶的上传位置 URL。这可以被前端用来向用户显示结果。
所以现在我们的 API 已经准备好了!现在我们所要做的就是得到一个前端网站来展示它!
与 CoreUI 的反应前端
对于前端,我使用 ReactJS 来制作一个简单的仪表板并与 API 交互。我不打算深入讨论仪表板样式本身的细节,但是会涉及它如何与 API 交互。我使用的模板来自
[## 免费 React.js 管理模板 CoreUI
时间是我们最宝贵的资产,因此我们希望通过创建简单、可定制、易于学习的工具来帮助您节约时间…
coreui.io](https://coreui.io/react/)
这是一个非常棒的免费管理面板,可以在 react 和许多其他框架中使用。我刚刚下载了它并解压了 zip 文件。只要你已经安装了 npm,你就可以运行安装程序来获得需要的包,然后用
mkdir client
cd ./client/
npm install
npm start
所有我决定放在 app.py 旁边的客户端/ 子目录中的文件。
我现在的目录结构的例子。请注意客户端子目录。
实际调用并显示结果的 ReactJS web 部分如下所示:
**# Define the function (functional components not classes)**
const JustPie = () => { **# Set up the state variables**
const [downloadLink, setDownloadLink] = useState(""); **# Image** **# Default settings for our form**
const [data, setData] = useState("40,60");
const [colors, setColors] = useState("003049,ffcdb2")
const [wedge, setWedge] = useState(0.05); **# NB: This URL will changed depending on your release!!!**
const api_base_url =
'[http://datastuffplus.herokuapp.com/api/justpie/'](http://justpie.herokuapp.com/api/v1/') **# Function to fetch the data from our API**
function fetchData(){ **# Set the image to be empty** setDownloadLink(''); **# Build up the endpoint to our API**
var url_req_string = api_base_url+ "?data=" + data + "&colors="
+ colors + "&wedge=" + wedge; **# Fetch the URL and parse the JSON response **
fetch(url_req_string)
.then(res => res.json())
.then(
(result) => { **# Set the image to be the API return "message"**
setDownloadLink(result.message);
}, (error) => {
console.log(error); }
);
};**# The rest of the code that runs the actual render**
return (<> </>)
上面简单地调用了一个对我们的 API 的获取,并更新了下载链接的状态,这是 S3 桶图像 URL。
最后,为了完整起见,页面呈现中出现的下一部分显示了状态变量如何连接到表单:
**# Update the data when the form changes**
<CInput type="text" id="hf-text" name="hf-text" placeholder="40,60" autoComplete=""
**value={data}**
**onChange={(event)=> setData(event.target.value)}**/>**# Call the API on a button press** <CButton type="submit" size="sm" color="primary"
**onClick={() => fetchData()}**>
就是这样!您可以通过运行以下命令来检查它的外观:
npm start
我的本地设置如下所示:
正如您所看到的,我们有输入表单以及输出结果部分!现在这一切都在本地运行,最后一步是将其部署到 Heroku。
部署到 Heroku
为部署做好准备还有最后几个步骤。我们需要为我们的服务器建立一个 Procfile 并构建 React 代码,这样我们的 flask 服务器就可以发送结果了。
Procfile
您所要做的就是创建一个名为 Procfile 的新文件,并在其中填入:
web: gunicorn app:app
反应生成
另一个简单的步骤是,一旦你进入/客户端/ 目录,你可以运行:
npm run build
这将生成一个名为 /client/build/ 的新目录,这是我们的 Flask 服务器在根路径上指向的位置。
注意:构建步骤可能需要一些时间,这取决于你的应用程序有多大
最后,我们可以将所有文件添加到 git 存储库中,如下所示:
git add .
git commit -am "All of teh codes"
git push heroku master
这也要花很多时间,所以去喝杯咖啡吧。一旦推送完成,你会看到 Heroku 自动检测到你正在推送一个 Flask 应用程序,它会为你的安装所有的包和服务器!如果你曾经尝试过自己做,这是疯狂的!
该版本在控制台中的外观
在所有这些艰苦的工作之后,我们可以看到我们创造了什么,并且可以与大众分享。看看这个视频,看看它是如何工作的!
最后这里是你可以自己尝试的链接!
http://labs . datastuff . plus
如果你有问题或需要有人就你的项目进行咨询,请给我发消息到 kyleanthonypastor@gmail.com,如果你在 instagram 上,请关注我@ datastuffplus。
数据科学中的“读取-评估-打印-循环”环境
原文:https://towardsdatascience.com/read-evaluate-print-loop-environment-in-data-science-e9668aadf98?source=collection_archive---------72-----------------------
这里有很多类似“为什么 Python 比 R 好,反之亦然”的文章。我们还需要另一个吗?所以,最近我花了几周时间将一个项目从 R 移植到 Python。我意识到有一个重要的特征在 99%的文章中被完全遗忘了。在这篇文章中,我将讨论这个话题,并分享我对在数据科学任务中实现强大的 REPL 环境的重要性的看法。
在此之前,让我们声明一件重要的事情:在这篇文章中,不会有人声称“R 优于…”。R 和 Python 都只是数据科学的工具。对于专业研究人员来说,应该根据他或她想要实现的目标来决定选择哪种工具。这不是平均利弊的总和。它是关于特定工具如何满足您在特定挑战中的需求。
我们还需要缩小一点我将在这里讨论的数据科学的范围。我只考虑表格数据和时间序列。显然,在计算机视觉和自然语言处理的两个选项中——R 或 Python——任何研究人员都会更喜欢 Python,只是因为它有可用的框架和最先进的算法。
另一个假设是,我将考虑更接近研究阶段而不是生产阶段的数据科学任务。这都是关于探索性数据分析,统计假设检验,建立模型和模型选择,数据可视化等。为了方便起见,我称之为统计分析,尽管这可能不是一个好的术语。
最后,介绍了这么久,让我们进入正题。什么是“阅读-评估-打印-循环”环境?我想专业的程序员会讨厌这样的定义,但是对于统计分析来说,REPL 意味着有机会单独执行一行或多行代码,并检查变量的当前状态(与执行整个脚本并查看最终结果形成对比)。
让我们来看看为什么 REPL 选项在所描述的数据科学领域非常重要。事实上,这是因为当我们探索我们的数据时,我们是一步一步地做的,下一步会是什么强烈地依赖于上一步的结果。在这种情况下,逐行添加和执行代码的机会只是反映了数据分析的过程。让我们想象一个非常基本的例子:你读取一个带有数据的源文件(假设它是几个预测值 X1,X2,X3 和目标变量 Y ),你将要拟合一个模型 Y=f(X) 。当然,可以写一个类似 read->normalize variables->fit model 的脚本。但这可能不是一个好主意。如果一个变量 Xn 看起来像这样会怎么样:
来源:作者
应用 Box-Cox 变换可能更准确,而不仅仅是归一化这些值。或者如果 Xn 是这样的呢:
来源:作者
我们可能想要根据 Xn 的原始值属于什么分布来引入一个新的分类变量。还有成吨的其他“如果”——如果 Xn 有很多遗漏怎么办,如果 Xn 方差接近于零怎么办等等。我们在数据分析中的下一步行动取决于上一步的发现。这就是为什么在你的 IDE 中拥有一个强大且用户友好的 REPL 环境是至关重要的。该选项使可视化当前步骤的结果成为可能,测试主脚本中的一些特殊假设并检查变量。
好吧,即使之前你没有想到 REPL 在你每天的数据分析活动中的影响,我希望现在我们在同一页上:它似乎非常有用。让我们看看将 REPL 与 Python 和 r 结合使用的机会。基本上,有两种选择——比方说“经典”IDE 或 Jupyter 笔记本。
好了,朱庇特笔记本。这绝对是一个很好的工具,可以用来交互展示结果,协同工作以及类似的事情。但是在我看来,在日常活动中有一些缺点是很烦人的。首先,当你检查和可视化你的数据很多的时候,笔记本变得太长,你总是需要上下滚动。那真的不方便。其次,要检查变量,你只能打印它。最后,我相信我们都喜欢代码自动完成,不需要按任何附加按钮。
转到 IDE,我假设这里最常用的两个是 Spyder 和 PyCharm(当然,这只是我的猜测)。
Spyder 提供了与 RStudio 几乎相同的功能来可视化和检查数据。事实上,当我开始写这篇文章的时候,我的机器上已经安装了 Spyder 3。我将提到控制台中的绘图和与 RStudio 相比 variable explorer 的有限功能。然后我将其更新到 Spyder 4,现在它有一个专用的绘图窗格。那真是太好了!对于变量资源管理器,我仍然认为 RStudio 比 Spyder 强,因为它在数据帧中显示列数据类型,在内存中显示对象大小。
来源:作者
尽管 PyCharm 为开发人员提供了令人惊叹的功能,但对于逐步可视化、运行特定分析和探索数据框架来说,它似乎不太友好。根据文档,它有“科学模式”,看起来像是为研究人员设计的。但是只有专业版才有。在免费版中,IPython 控制台可用,当然它支持 REPL 功能,但这不是我们在探索性数据分析、数据可视化等过程中需要的。
皮查姆的科学模式。来源:https://www.jetbrains.com/help/pycharm/
在我个人看来,R 与 RStudio 目前是数据科学中最强大和最友好的工具,这种数据科学在上面被称为统计分析。在 RStudio 中,您可以在编辑器和控制台中单独执行一行代码,您有绘图窗格,最后还有功能强大的环境窗格,它特别显示数据帧中列的数据类型和内存中对象的大小。那真的很有用,很友好,不是吗?!
来源:作者
好了,这就是我想分享的关于 REPL 和 ide 中用于数据分析的相关特性的全部内容。希望这篇文章对初学者或那些从未尝试过其他选择的人有帮助和兴趣。
如果你觉得有趣,可以看看我的博客。
不用离开熊猫就能抓取 HTML 表格
原文:https://towardsdatascience.com/read-html-54a942305c0f?source=collection_archive---------43-----------------------
如何从基于表格的网站中快速获取所需数据
网络搜集通常是一件痛苦的事。研究、查找和安装您需要的库可能非常耗时。在 HTML 中找到您需要的内容需要时间。让所有东西都工作起来可能很难。🙁
在本文中,我将向您展示如何使用 Python pandas 库用单行代码来抓取 HTML 表格!它并不是在所有情况下都有效,但是当你在网站上有 HTML 表格时,它会让你的生活变得更容易。😀
您将看到如何使用它从网站上获取关于足球和举重的数据。⚽️ 🏋
资料来源:pixabay.com
我们将使用[pd.read_html()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_html.html)
来抓取表格数据。根据我的经验,很多人不知道pd.read_html()
,尽管已经在出现了 7 年多。
本文原载于 Deepnote 。你可以在那里运行交互式笔记本。👍
设置
要获得必需的软件包及其依赖项的最新版本,请取消注释并运行以下代码一次。然后重启你的笔记本内核。
# !pip install pandas lxml beautifulsoup4 html5lib matplotlib -U
一般熊猫会尝试用 lxml 解析 HTML,因为它速度快。如果失败,它将使用 BeautifulSoup4 和 html5lib。你可以在熊猫文档中阅读更多关于解析器的内容。
让我们导入包并检查版本。我总是喜欢检查 Python 和密钥库的版本,以帮助诊断可能出现的问题。😉
import sys
import pandas as pd
print(f"Python version {sys.version}")
print(f"pandas version: {pd.__version__}")> Python version 3.7.3 (default, Jun 11 2019, 01:11:15)
> [GCC 6.3.0 20170516]
> pandas version: 1.0.5
如果你的 Python 版本低于 3.6,建议你更新一下。如果你的版本低于 1.0.5,熊猫也一样。要了解更多关于熊猫 1.0 的更新,请看我的指南这里。
示例 1:足球⚽️
让我们收集一些关于美国女子国家队的足球统计数据——这是世界上大多数地方的足球。⚽️
让我们使用美国足球网站:https://www.ussoccer.com/uswnt-stats。
在 Chrome 中,进入网站,右击数据,选择检查。
您应该会看到边栏出现。这向您展示了页面背后的 HTML,以及其他内容。寻找 HTML 标签、、或
| 。这些都表明你找到了一张桌子。如果你想了解 HTML 表格的基础知识,请参见w3schools.com。 |
我们将要使用的 pandas 函数要求我们找到 HTML 表。所以你刚刚挖到了金子!🎉
让我们从网页上抓取数据。要将每个表放入数据帧中,我们只需运行以下代码。
list_of_dfs = pd.read_html('https://www.ussoccer.com/uswnt-stats')
现在数据帧在一个列表中。
type(list_of_dfs)> list
让我们看看列表中有多少数据帧。
len(list_of_dfs)> 2
好的,让我们看看第一个数据框。👀
list_of_dfs[0]
看起来像是一堆球员的数据。很好,这符合我们在网站上看到的预期。
让我们看看第二个表格里有什么。
list_of_dfs[1]
看起来里面有守门员的数据。
在这两种情况下,如果我们将第一行作为列标题,将第一列作为索引来读取,效果会更好。
当您使用pd.read_html()
读取表格时,您可以使用许多与使用pd.read_csv()
相同的参数。这是大多数人更熟悉的熊猫方法。👍
让我们通过再次获取数据,将表列放在我们想要的位置。这次我们会通过header=0, index_col=0
。
list_of_dfs_nicer = pd.read_html('https://www.ussoccer.com/uswnt-stats', header=0, index_col=0)
list_of_dfs_nicer[0].head(2)
好多了。😀
要在 Jupyter 笔记本或 IDE 中查看更多可能的参数,请在函数中按住Shift
+ Tab
。或者直接去看文档。
我们继续拍吧。🧻
我们可以将每个数据帧保存为它自己的变量。让我们把所有不是守门员的人放在runners_df
里,把守门员放在goalies_df
里。根据互联网和我经常踢足球的女儿的说法,足球队中所有的非守门员都没有一个名字。我称他们为跑步者,因为他们经常这样做。🙂如果我遗漏了什么,请纠正我。
runners_df = list_of_dfs_nicer[0]
goalies_df = list_of_dfs_nicer[1]
我们希望排除 runners_df 中的最后三行和 goalies_df 中的最后两行。用.iloc[]
切片吧。如果你想了解更多关于切片数据帧和如何使用熊猫的知识,我谦恭地建议你看看我的令人难忘的熊猫书。
runners_df = runners_df.iloc[:-3]
runners_df.tail(2)
goalies_df = goalies_df.iloc[:-2]
goalies_df
让我们快速做一个可视化的展示,展示今年每个进球的球员的进球情况。
goal_scorers_df = runners_df[runners_df['G']>0]
goal_scorers_df['G'].sort_values().plot(kind='barh', title='2020 USWNT Goals');
看起来克里斯蒂安·普雷斯和林赛·霍兰在短暂的 2020 赛季中领先得分。🏅
好吧,我们可以做很多有趣的数据清理和可视化,但今天的重点是抓取和读取 HTML 表。让我们再看一个例子。
例子 2:举重🏋🏼♀️
维基百科有一个有趣的图表,显示不同的举重练习锻炼了哪些肌肉群。
检查后,我们看到这是一个 HTML 表。让我们抓住它。🚀
weightlifting_df_list = pd.read_html('https://en.wikipedia.org/wiki/List_of_weight_training_exercises', index_col=0)
len(weightlifting_df_list)2weightlifting_df_list[0]
这就是我们想要的!👍
资料来源:pixabay.com
让我们将第一个数据帧赋给一个变量。
exercises_df = weightlifting_df_list[0]
现在你可以对数据框做任何你想做的事情。也许你想过滤它,只显示锻炼你的腿筋。
hammies = exercises_df[(exercises_df['Ham-strings']=='Yes') | (exercises_df['Ham-strings']=='Some')]
hammies
让我们根据大量锻炼腿筋的练习对表格进行排序。
hammies.sort_values(by='Ham-strings', ascending=False)
看起来,如果我们想要更强壮的腿筋,我们应该做一些弓步、硬拉和腿部弯曲。我想是时候锻炼了!🏋️
包装
您已经看到了如何使用pd.read_html()
将数据从 HTML 表移动到熊猫数据帧列表中。pd.read_html()
并不是每一个网络抓取努力的正确工具,但当它是一个选择时,它是一个伟大的选择。👍
我希望这篇关于pd.read_html()
网络抓取的介绍对你有所帮助。如果你有,请在你最喜欢的社交媒体上分享,这样其他人也可以找到它。😀
如果你有问题或意见,请在 Twitter 或 LinkedIn 与我分享。
资料来源:pixabay.com
刮的开心!🚀
用 Python 读取 NetCDF 数据
原文:https://towardsdatascience.com/read-netcdf-data-with-python-901f7ff61648?source=collection_archive---------0-----------------------
访问一种有点混乱但功能强大的数据格式
由 Waldemar Brandt 在 Unsplash 上拍摄的照片
网络通用数据格式(NetCDF)通常用于存储多维地理数据。这些数据的一些例子是温度、降雨量和风速。存储在 NetCDF 中的变量经常在大面积(大陆)地区每天被测量多次。由于每天进行多次测量,数据值会快速积累,变得难以处理。当每个值还被分配给一个地理位置时,数据管理会变得更加复杂。NetCDF 为这些挑战提供了解决方案。本文将带您开始使用 Python 从 NetCDF 文件中读取数据。
装置
NetCDF 文件可以用一些不同的 Python 模块读取。最受欢迎的是netCDF4
和gdal
。对于这篇文章,我们将严格集中在netCDF4
上,因为这是我个人的偏好。
有关如何使用 xarray 和 rioxarray 在 Python 中读取和绘制 NetCDF 数据的信息,请查看本文。
安装很简单。我通常建议使用 anaconda Python 发行版来消除依赖关系和版本控制带来的混乱。要安装 anaconda (conda),只需输入conda install netCDF4
。或者,你可以用pip
安装。
为了确保您的netCDF4
模块安装正确,在终端中启动一个交互式会话(键入python
并按下‘Enter’)。然后import netCDF4 as nc
。
加载 NetCDF 数据集
加载数据集很简单,只需将一个 NetCDF 文件路径传递给netCDF4.Dataset()
。对于这篇文章,我使用了一个包含来自 Daymet 的气候数据的文件。
import netCDF4 as ncfn = '/path/to/file.nc4'
ds = nc.Dataset(fn)
通用文件结构
NetCDF 文件有三个基本部分:元数据、维度和变量。变量包含元数据和数据。netCDF4
允许我们访问与 NetCDF 文件相关的元数据和数据。
访问元数据
打印数据集ds
,为我们提供文件中包含的变量及其尺寸的信息。
print(ds)
和输出。。。
<class 'netCDF4._netCDF4.Dataset'>root group (NETCDF4_CLASSIC data model, file format HDF5):start_year: 1980source: Daymet Software Version 3.0Version_software: Daymet Software Version 3.0Version_data: Daymet Data Version 3.0Conventions: CF-1.6citation: Please see [http://daymet.ornl.gov/](http://daymet.ornl.gov/) for current Daymet data citation informationreferences: Please see [http://daymet.ornl.gov/](http://daymet.ornl.gov/) for current information on Daymet referencesdimensions(sizes): time(1), nv(2), y(8075), x(7814)variables(dimensions): float32 time_bnds(time,nv), int16 lambert_conformal_conic(), float32 lat(y,x), float32 lon(y,x), float32 prcp(time,y,x), float32 time(time), float32 x(x), float32 y(y)groups:
上面您可以看到文件格式、数据源、数据版本、引用、维度和变量的信息。我们感兴趣的变量是lat
、lon
、time
和prcp
(降水量)。有了这些变量,我们就能找到给定时间、给定地点的降雨量。该文件仅包含一个时间步长(时间维度为 1)。
元数据也可以作为 Python 字典访问,这(在我看来)更有用。
print(ds.__dict__)OrderedDict([('start_year', 1980), ('source', 'Daymet Software Version 3.0'), ('Version_software', 'Daymet Software Version 3.0'), ('Version_data', 'Daymet Data Version 3.0'), ('Conventions', 'CF-1.6'), ('citation', 'Please see [http://daymet.ornl.gov/](http://daymet.ornl.gov/) for current Daymet data citation information'), ('references', 'Please see [http://daymet.ornl.gov/](http://daymet.ornl.gov/) for current information on Daymet references')])
那么任何元数据项都可以用它的键来访问。例如:
print(ds.__dict__['start_year']1980
规模
对维度的访问类似于文件元数据。每个维度都存储为包含相关信息的维度类。可以通过遍历所有可用维度来访问所有维度的元数据,如下所示。
for dim in ds.dimensions.values():
print(dim)<class 'netCDF4._netCDF4.Dimension'> (unlimited): name = 'time', size = 1<class 'netCDF4._netCDF4.Dimension'>: name = 'nv', size = 2<class 'netCDF4._netCDF4.Dimension'>: name = 'y', size = 8075<class 'netCDF4._netCDF4.Dimension'>: name = 'x', size = 7814
单个维度是这样访问的:ds.dimensions['x']
。
可变元数据
访问变量元数据的方式与访问维度的方式相同。下面的代码展示了这是如何做到的。我放弃了输出,因为它很长。
for var in ds.variables.values():
print(var)
下面为prcp
(降水)演示了访问特定变量信息的程序。
print(ds['prcp'])
和输出。。。
<class 'netCDF4._netCDF4.Variable'>float32 prcp(time, y, x)_FillValue: -9999.0coordinates: lat longrid_mapping: lambert_conformal_conicmissing_value: -9999.0cell_methods: area: mean time: sum within days time: sum over daysunits: mmlong_name: annual total precipitationunlimited dimensions: timecurrent shape = (1, 8075, 7814)
访问数据值
通过数组索引访问实际的降水数据值,并返回一个numpy
数组。所有变量数据返回如下:
prcp = ds['prcp'][:]
或者可以返回一个子集。下面的代码返回一个 2D 子集。
prcp = ds['prcp'][0, 4000:4005, 4000:4005]
这是 2D 子集的结果。
[[341.0 347.0 336.0 329.0 353.0][336.0 339.0 341.0 332.0 349.0][337.0 340.0 334.0 336.0 348.0][342.0 344.0 332.0 338.0 350.0][350.0 351.0 342.0 346.0 348.0]]
结论
NetCDF 文件通常用于地理时间序列数据。最初,由于包含大量数据,并且与最常用的 csv 和光栅文件的格式不同,使用它们可能有点吓人。NetCDF 是记录地理数据的好方法,因为它内置了文档和元数据。这使得最终用户可以毫不含糊地准确理解数据所代表的内容。NetCDF 数据以 numpy 数组的形式访问,这为分析和整合到现有工具和工作流中提供了许多可能性。
阅读这本书,抓住你的第一份数据科学工作
原文:https://towardsdatascience.com/read-this-book-to-snag-your-first-data-science-job-553fd301d00a?source=collection_archive---------44-----------------------
这本书里的 5 个技巧改变了我研究数据科学的方式,并启发了我成为一名中型作家的旅程。
由 Rashtravardhan Kataria 在 Unsplash 拍摄的照片
让我们抛开这些事实:现在是一个怪异的活着时间。特别是对于求职者来说,当你也申请和面试工作时,可能很难专注于看似琐碎的事情,如再练习 10 个技术性面试问题、获得另一个在线认证或建立你的数据科学作品集(我相信中世纪国王没有将工作面试作为一种酷刑的唯一原因是因为他们还没有想到这一点)。
虽然屈服于集体低迷、一品脱一品脱地吃低热量冰淇淋、看《抖音》直到你的头脑融化可能很诱人,但我在这里是为了让你意识到更好的东西。老实说,当我读它的时候,我感觉好像找到了捷径。
仅在两个月前,Emily Robinson 和 Jacqueline Nolis 出版了在数据科学领域建立职业生涯,探索数据科学职业的方方面面。这本书有 281 页(加上 30 页的技术面试问题和解释),对任何刚入门的人来说,它是实践知识和灵感的彻底结合。
这是在我踏入数据科学行业的第一步时完全启发了我的 5 大技巧。如果你喜欢这些,请随意查看这本书(使用代码 buildbook40% 可享受 40%的折扣),并在 Twitter 上为作者的出色工作大声喊出来!
免责声明: 不知作者也没有靠这本书的销售赚钱。所有的想法和个人轶事都是我自己的。
1)✂️的问题不在于不够“前沿”
许多人被数据科学吓退了,因为它太宽泛了,学习所有的东西意味着一条不可能的学习曲线。没人能做到。因此,更重要的是深入钻研基础知识,而不是浪费精力过早地投入复杂的东西。
尤其是刚起步的时候,你确实而不是需要担心成为“数据科学独角兽”(也就是说,进入一家公司,可以执行交给他们的每一项模糊的数据科学相关任务的人)。在工作日的大部分时间里,数据科学家不是做那些花哨的高级任务,而是执行数据库查询和准备数据进行分析。出于这个原因,成为一名出色的数据科学家的方法是能够快速准确地执行简单的任务。
我最近阅读了一份统计数据,表明数据科学家一天中 80%的时间用于数据清理和组织,只有 20%的时间用于实际分析。再者,面试问题往往涉及编写 SQL 查询,对 Python 或 R 有基本了解,或者能够向面试官解释 p 值;不要担心复杂的东西,担心真正了解基本知识,真正好。
2)创建一个文件夹(作为一种学习策略)📝
当我获得经济学学位毕业时,我从未被告知在找工作时拥有一份投资组合的重要性。在接受了弗吉尼亚大学数据科学硕士项目的一个名额,并与美联储、特勤局和司法部(我个人对公共部门感兴趣)的潜在未来雇主交谈后,我反复听到一条建议:带一个作品集给我们看。
面试不是发现全明星员工的好方法。即使是技术面试,帮助也不大;您很少会将 SQL 查询写成白板,而不仅仅是键入一个。不记得怎么解 FizzBuzz 了?谷歌搜索只需要 0.2 秒——如果你在面试中回忆不起,那又有什么关系呢?
有了投资组合,你就完成了三件事:1)你的个人项目有一个清晰的开始、中间和结束,2)你让人们感觉到你的技能,3)你向人们宣传你是我们中的一员。数据科学家不断发布他们学到的交易技巧,因此通过创建投资组合,这表明你在获得数据科学家头衔之前很久就已经加入了社区。
3)宣传自己📰
当我在高中二年级的时候,我们做了一整节关于简爱的节目,以电影结尾(你不怀念以前学校有电影的时候吗?).简是一个相貌平平、文静的孤女,她在附近的一个庄园里找到了一份家庭教师的工作,这让她的朋友们大为吃惊。
“你是怎么做到的?他们问道,简回答道,“我登了广告。”
宣传自己是一件事。对我们许多人来说,这也是可怕和不可思议的。你看到它的工作效率只有百万分之一,并认为这种可能性对你来说太大了,所以你不能尝试。你没有人脉,没有互联网知识,或者在它流行起来之前就开始做媒体。
我不知道如何宣传自己,所以我采纳了这本书的建议,只关注高回报领域。首先,我花了三天时间创建了一个个人网站。然后我创建了一个 Twitter,开始分享我喜欢的数据科学博客。自然地,这种对博客的持续吸收将我引向了 Medium,过了一会儿,我屈服了,写下了我的第一篇关于 SQL 的博客文章(这是我三天前刚刚学到的)。
在 15 天内,我又写了 5 篇文章,我的文章有超过 2500 次的浏览量,有 100 多个追随者。一旦我把我的 LinkedIn 链接到我的媒介,我的 LinkedIn 页面浏览量也开始飙升。我收到了无数来自我所在领域的热门数据科学家的请求。
我不是边缘案例,给自己做广告不一定要吓人。从小处着手,你会在不知不觉中拥有一个强大的忠实追随者基础。
4)保持管道充满🚰
让我们面对它;只有一小部分约会会让你找到“那个人”,工作也是如此。有时候他们不喜欢你,有时候你不喜欢他们。有时你确实喜欢他们,但他们仍然挂念着另一个人,或者有你没有意识到的偏见(比如在内部雇佣某人,因为文书工作更容易)。
永远不要做“真正的”面试。通过把每一次面试都当作是下一次面试的练习,你就卸下了那份“独一无二”的工作所带来的压力,并且可以获得更多的乐趣。这些人想尽办法给你有趣的数据科学难题,他们可能会请你吃午饭,有什么不喜欢的呢?
面试官不仅在寻找合适的人,他们也在寻找一个有趣的同事。通过不断申请工作来保持你的渠道畅通,直到你有一份工作在手,这也将有助于减轻压力,让你感觉你不得不在任何一场面试中胜出。
Van Tay Media 在 Unsplash 上的照片
5)适用于您≥ 60% 所胜任的工作💼
逻辑很简单:对许多公司来说,列出的工作描述与其说是要求,不如说是愿望清单。我敢肯定,我们都希望能熟练掌握每一种编程语言,成为数据可视化的主沟通者,成为机器学习和自然语言处理的天才。总的来说,我们都想成为数据科学的独角兽(或者至少被视为独角兽)。
公司通常会列出比角色所需更多的技能,希望能吸引独角兽。出于这个原因,艾米丽·罗宾逊和杰奎琳·诺里斯建议申请那些你 60%或者更有资格的工作。如果你满足了 60%或更多的要求,你就已经为这份工作做好了准备。
我个人对这个建议非常兴奋,因为它消除了事情的猜测;我已经开始强调我在工作描述中“附带”的所有技能,然后将我的资格视为所列要点的一小部分。如果这个数字≥60%,我就要了!如果没有,对我们俩来说都不合适。
最后,不要出售你没有的技能也很重要,因为你认为它会让你更受欢迎;如果你交叉手指,他们没有问你简历上的 x、y 和 z 线,你应该认真考虑你是否应该有这些线。做真实的自己,专注于你所拥有的令人敬畏的技能:不多不少。
最后的想法🤔
你觉得这个建议怎么样?它是明显的还是新颖的?这会改变你的求职策略吗?我很乐意在下面的评论中听到你的想法!
谢谢,
阿曼达
读者使用条款和条件
原文:https://towardsdatascience.com/readers-terms-b5d780a700a4?source=collection_archive---------46-----------------------
最后更新于 2023 年 3 月
阅读我们的媒体出版物时你应该知道的事情
真诚媒体在 Unsplash 上拍摄的照片
走向数据科学公司是一家在加拿大注册的公司。通过使用 Medium,我们为成千上万的人提供了一个交流思想和扩展我们对数据科学的理解的平台。
由于 TDS 在过去几年中发展如此之快,我们决定整理一个术语列表,解释读者与 TDS 的关系( TDS 读者使用条款和条件—2023 年 3 月)。
这些条款绝不会改变、修改或取代您与 Medium 的关系,您与 Medium 的关系受 Medium 服务条款管辖。
如果您有任何问题,可以在这里联系我们。你也可以看看我们之前的版本:2022 年 8 月,以及2020 年 5 月。
用 Python 读取图像(不使用特殊的库)
原文:https://towardsdatascience.com/reading-an-image-in-python-without-using-special-libraries-534b57de7dd4?source=collection_archive---------11-----------------------
就告别 OpenCV,Matplotlib,PIL 除了 Numpy!
照片由克里斯蒂安娜·特斯顿在 Unsplash 拍摄
嗯,上面这张照片很棒,不是吗?。对我来说这是一部杰作。尽管如此,你有没有想过或者问过自己这个一百万美元的问题:
图像是由什么组成的?
现在,在阅读整个教程之前,我希望你们在评论区 回答这个问题 ,这样你们可以给大脑一些工作。无论如何,对于那些从未回答过问题或不知道答案的人,通过阅读这篇文章,你最终可以毫不犹豫地回答这个问题。炒作够了,我们开始吧!。顺便说一下,本教程的完整代码也可以在下面我的 GitHub 资源库 中找到:
[## 塔努-北帕布/Python
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/Tanu-N-Prabhu/Python/blob/master/Reading_An_Image_In_Python_(Without_Using_Special_Libraries).ipynb)
故事
照片由 Pixabay 从像素拍摄
我在图像处理课上(毕业时)有一个作业,我必须从一个文件中读取一个原始图像,使用单点重采样和加权平均重采样算法将图像调整到指定的尺寸。有人给了我一张纸条,上面写着“ 不要使用任何外部库 ”用于你的程序,尤其是读取和保存图像。只有选定的算法被允许使用,python 中的一个这样的算法是**numpy**
。这听起来很痛苦,但无论如何我不得不这么做,我做到了。在本教程中,我们将只专注于读取和保存图像,没有什么花哨的。
问题
编写一个程序,从文件中读取 raw 格式的灰度图像,并将新图像保存到 raw 格式的新文件中。(我只是把问题说得简短些,因为这是你今天要学的内容)。
图像源
下面是灰度 8 位图像的来源。我将使用 第 4 张 样图 芭芭拉,8 位灰度(512×512)。raw ”。其他样本图像的链接可以在 这里找到 。
图书馆的使用
正如我所说的,我不会使用任何特殊的 python 库。图像处理领域中一些最受欢迎和使用最广泛的库包括:
- Numpy
- OpenCV
- PIL
- Matplotlib
有趣的是,通过使用 OpenCV , PIL 和 Matplotlib 库,我们只需两行代码就可以读取图像并将其保存到文件中。但是这里的问题是不要使用特殊的库和特殊的方法。 Numpy 是唯一会被贯穿使用的标准库( 你就知道为什么 )。
密码
这是你们期待已久的时刻。
导入库
使用**numpy**
库的唯一原因是将 raw 图像转换为像素 的 数组。主要用于存储数组*中的值。*****
**# Necessary library used for this tutorial** import numpy as np
初始化图像的行和列值
图像的维度由行和列组成。
**# For example a particular image in this case would contain (512*512) rows and columns meaning 262,144 pixels** ROWS = 512
COLS = 512**# Different images have different dimensions. Change it accordingly**
打开输入图像文件(RAW 格式)
**# Opening the input image (RAW)** fin = open('barbara_gray.raw')
print(fin)
这将提示输出如下:
**<_io.TextIOWrapper name='barbara_gray.raw' mode='r' encoding='UTF-8'>**
现在,我们需要从原始数据(图像)构建一个 2D 数组。必须使用一种高效的方法来读取已知数据类型的二进制数据,这可以在**numpy**
库的帮助下完成。
加载输入图像
这是真正的乐趣开始的地方。感谢**numpy**
**# Loading the input image** print("... Load input image")
img = np.fromfile(fin, dtype = np.uint8, count = ROWS * COLS)
print("Dimension of the old image array: ", img.ndim)
print("Size of the old image array: ", img.size)
执行此操作后,您将获得
**... Load input image** Dimension of the old image array: **1**
Size of the old image array: **262144**
从 1D 到 2D 阵列的转换
有一种方法可以将 1D 阵列转换为 2D 阵列,例如用图像的行和列或列和列(任何一种都可以)来划分像素总数。这可以借助一个公式来写:
**img = tp // (cols, cols)**
tp =总像素; cols 代表图像的行和列。我们之所以使用地板除法而不是除法,是因为我们需要将数值四舍五入为整数。
**# Conversion from 1D to 2D array** img.shape = (img.size // COLS, COLS)
print("New dimension of the array:", img.ndim)
print("----------------------------------------------------")
print(" The 2D array of the original image is: \n", img)
print("----------------------------------------------------")
print("The shape of the original image array is: ", img.shape)
执行此操作后,您将获得
New dimension of the array: **2**
----------------------------------------------------
The 2D array of the original image is:
**[[240 240 240 ... 230 230 230]
[240 240 239 ... 230 229 229]
[240 239 238 ... 231 232 232]
...
[ 50 50 50 ... 50 50 50]
[ 50 50 50 ... 50 50 50]
[ 50 50 50 ... 50 50 50]]**
----------------------------------------------------
The shape of the original image array is: **(1000, 1600)**
将新图像以 raw 格式保存到新文件中
**# Save the output image** print("... Save the output image")
img.astype('int8').tofile('NewImage.raw')
print("... File successfully saved")
**# Closing the file** fin.close()
这就是你如何以 raw 格式保存新图像。这将保存在您的本地系统中。
... Save the output image
... File successfully saved
注意:进入图像的行和列时。例如,如果一幅图像的分辨率是 1600x1000 ,那么就意味着宽度是 1600 而高度是 1000 。类似地,在上面的程序中,行将是 1000 ,而列将是 1600 。
输出
成功执行上述代码后,您现在可以读取原始图像,然后保存原始图像。耶!!!。现在,如果你不相信我,你可以使用一些在线图像打开工具(或其他工具)打开保存的图像。我通常使用光电,这是我得到的。
塔努·南达·帕布摄
先提醒一下,上面是工具输出的截图,主要输出的图像是灰度的,叫做“ 【芭芭拉 ”(一个举起一只手的女人或者其他什么)。
结论
在离开之前,尝试阅读其他格式的图像,如 JPEG (JPG),PNG,看看你会得到什么价值。此外,尝试阅读彩色(RGB)图像。反正现在你可以轻松回答教程开头的上述问题了。让我再次提醒你。 图像是由什么组成的? ”。答案是大家都看到了,“ 图像是由一组像素值 ”组成的。值的数量取决于给定图像的行和列。
今天到此为止,希望大家喜欢阅读教程“ (不使用特殊库) ”的内容。正如承诺的那样,除了**numpy**
,我没有使用任何其他库。嗯,咄!你需要使用**numpy**
来处理数组。如果你们对教程有任何意见或担忧,请在下面的评论区告诉我。直到那时再见,保持安全:)
使用 Python 读取和可视化 GeoTiff |卫星图像
原文:https://towardsdatascience.com/reading-and-visualizing-geotiff-images-with-python-8dcca7a74510?source=collection_archive---------2-----------------------
用于处理 GeoTiff 或卫星影像的 python 库简介。
Unsplash 图像链接
在 python 中读取图像非常容易,因为有许多库可用于读取、编辑和可视化不同格式的图像。这些库的例子有 Matplotlib、OpenCV、Pillow 等。这些库可以很好地处理流行的图像格式,比如。png,。tiff,。jpg,。jpeg,等。但它们似乎对 GeoTiff 图像不起作用。
如果我们了解 GeoTiff 格式与其他图像格式的不同之处,就很容易猜到原因。下面给出了一个简单的定义。
GeoTIFF 是一种标准的
.tif
或图像文件格式,它包括嵌入在。tif 文件作为标签。
通过标签,这意味着它有一些额外的元数据,如空间范围、CRS、分辨率等。以及像素值。是卫星和航空 摄影 影像的一种流行分发格式。
本文讨论了使用 jupyter 笔记本通过 python 读取和可视化这些图像的不同方法。使用的库有 GDAL、rasterio、georaster 和 Matplotlib(用于可视化)。这些库将帮助我们将这些图像转换为简单的 numpy 数组格式,从那里我们还可以使用 numpy 或 TensorFlow 执行其他图像转换,尽管我在本文中没有讨论转换。
这些库的文档中提到了安装步骤,我在参考资料部分提供了它们的链接,请仔细阅读。
使用 RasterIO
RasterIO 由 Mapbox 实现,它提供了用于读取地理参考数据集的 python API。此外,文档中提到,与 GDAL python 绑定不同,它没有悬空 C 指针和其他可能导致程序崩溃的指针问题。
import rasterio
from rasterio.plot import showfp = r'GeoTiff_Image.tif'
img = rasterio.open(fp)
show(img)
不要把自己和 x 轴和 y 轴的刻度值混淆,它们只是经度和纬度值。如果你想读取单个波段,使用下面的代码。
fp = r'GeoTiff_Image.tif'
img = rasterio.open(fp) # mention band no. in read() method starting from 1 not 0
show(img.read(3))
使用 RasterIO 的图像相关数据
# No. of Bands and Image resolution
dataset.count, dataset.height, dataset.width# Coordinate Reference System
dataset.crs
使用 RasterIO 的图像相关数据
使用地理控制器
georaster 安装了 pip 的版本为 1.25。这个版本可能会给你带来一些问题,如果你遇到任何问题,先去你的 georaster 安装目录。下面的代码会告诉你安装目录路径。
import georaster
print(georaster.__file__)
现在,在那里找到 georaster.py 文件,并用这个 georaster 中的内容更改它的内容。py 文件。
下面是可视化具有多个波段(或通道)的图像的代码。
import georaster
import matplotlib.pyplot as plt# Use SingleBandRaster() if image has only one band
img = georaster.MultiBandRaster('GeoTiff_Image.tif')# img.r gives the raster in [height, width, band] format
# band no. starts from 0
plt.imshow(img.r[:,:,2])
不使用 matplotlib 打印图像
我们可以直接使用绘图方法,而不是选择和可视化单个波段。
地理绘图法
使用 GDAL
这是处理 GeoTiff 图像时最受欢迎的库,但有时很难安装,需要花费大量精力才能最终使用它。GDAL 的大部分方法和类都是用 C++实现的,我们在这里使用它的 python 绑定。像 georaster 这样的大多数库都利用 GDAL,并为它提供了一个漂亮而简单的 python 接口。
from osgeo import gdal
import matplotlib.pyplot as pltdataset = gdal.Open('GeoTiff_Image.tif', gdal.GA_ReadOnly) # Note GetRasterBand() takes band no. starting from 1 not 0
band = dataset.GetRasterBand(1)arr = band.ReadAsArray()
plt.imshow(arr)
使用 GDAL 的图像相关数据
# For no. of bands and resolution
img.RasterCount, img.RasterXSize, img.RasterYSize# stats about image
img.GetStatistics( True, True )
Jupyter 笔记本实现图像统计
参考
安装
- https://mothergeo-py . readthedocs . io/en/latest/development/how-to/gdal-Ubuntu-pkg . html
- https://github.com/GeoUtils/georaster
- https://rasterio.readthedocs.io/en/latest/installation.html
- https://pypi.org/project/GDAL/
单据
- https://geo raster . readthe docs . io/en/latest/API . html # multi band raster
- https://rasterio.readthedocs.io/en/latest/quickstart.html
- https://gdal.org/python/index.html
阅读色盲图表:深度学习和计算机视觉
原文:https://towardsdatascience.com/reading-color-blindness-charts-deep-learning-and-computer-vision-a8c824dd71cd?source=collection_archive---------13-----------------------
转换数据,使其与类似的数据集兼容
有很多在线教程,你可以学习训练一个神经网络,使用 MNIST 数据集对手写数字进行分类,或者区分猫和狗。我们人类总是非常擅长这些任务,可以轻松地匹配或击败训练有素的模型的性能。
情况并非总是如此。在这个项目中,我想探索一个我个人非常纠结的任务。我有轻度红绿色盲。所以,这样的图表对我来说通常很难看到,如果不是不可能的话:
这是一个 6(我想?)
有没有可能让我训练一个模型来帮我完成这项任务,而不用我眯着眼睛,不可避免地把问题弄错?
乍一看,这个任务似乎很简单。我们可以拍摄一些图像,将它们分成训练集和测试集,然后训练一个卷积神经网络。除了…没有数据集。在网上,我只能找到 54 个不同的图像,这对于一个训练集来说是不够的,因为有 9 个类别(数字 1-9)。
如何解决这个问题?我们仍然有包含单个手写数字图像的 MNIST 数据集。我们可以使用这个数据集来训练一个擅长分类单个数字的神经网络。通过一些 OpenCV 转换,我们可以让色盲图表看起来类似于 MNIST 图像,就像这样:
手写 5
我们开始吧!
在 MNIST 数据集上训练卷积神经网络
有很多关于这方面的教程,但我还是会给出一个关于这是如何完成的高层次概述。
首先,我们需要安装 Tensorflow,它可以通过 pip 获得。如果没有安装,请在终端中运行以下命令。
pip install tensorflow
或者如果你有一个图形处理器:
pip install tensorflow-gpu
现在,我们将创建一个 mnist.py 文件并获取我们的训练数据,由于 mnist 数据集的流行,这些数据内置于 tensorflow 中:
接下来,我们将建立我们的卷积神经网络。我不会详细介绍这些是如何在内部工作的,但是网上有很多资源可以阅读,比如这个。我们将使用一个 Conv2D 层,然后是 MaxPooling 和 Dropout。然后,我们的 2D 输出被展平并通过具有 128 个单元的密集层,接着是具有 10 个类(编号 0–9)的分类层。输出将是长度为 10 的向量,以指示预测。例如,2 会被预测成这样:
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
因为 1 在第二个索引中。以下是型号代码:
现在,我们编译模型,在训练数据上运行它,在测试数据上评估它,并将模型作为. h5 文件保存在我们的目录中:
当我们运行这段代码时,我们得到了大约 99%的训练准确率和 98%的测试集准确率:
还不错!现在,您应该在您的目录中看到一个 mnist.h5 文件。现在,让我们进入下一步。
OpenCV 图表处理
下一个目标是获取现有的图表,并将其转换为与 MNIST 数据尽可能相似的形式,我们保存的模型在分类方面非常出色。对于这一部分,我们还需要几个库:
pip install opencv-python
pip install imutils
pip install numpy
pip install sklearn
pip install scikit-image
我们的目标是这样的转变:
经过一些实验后,下面是我们需要做的处理:
- 增加对比度,使手指的颜色更明显。
- 应用中值和高斯模糊来平滑我们在原始图像中看到的小圆圈。
- 应用 K-均值颜色聚类获得一致的颜色斑点。
- 转换为灰度
- 应用阈值处理(这将是棘手的)来得到一个只用黑白的图像。
- 更多模糊和阈值处理
- 形态学开放、封闭、侵蚀
- 骨骼化
- 扩张
哇,太多了。让我们从对比开始。我从网上复制了一个函数,它接收一幅图像并应用定制的亮度和对比度变换。我把它放在一个文件 ContrastBrightness.py 中,并使它成为一个类:
在高水平上,增加亮度会将值添加到图像的 RGB 通道,而增加对比度会将值乘以某个常数。我们将只使用对比功能。
我们算法的另一个复杂部分是聚类。同样,我创建了一个文件 Clusterer.py,并将我在网上获得的必要代码放入其中:
这段代码将接受一个图像和一个数字作为输入。这个数字 K 将决定我们将使用多少颜色聚类。你可以在这里阅读更多关于 K-means 聚类的内容。现在,让我们创建最后一个文件 main.py。我们将从导入开始:
请注意,我们正在导入刚刚创建的两个类。现在,请从 my Github 下载图表目录中的图片。
这些都被分类(在没有色盲的人的帮助下)到适当的文件夹里。
现在,我们将遍历路径中的所有图像,并应用变换 1–4。我对我的代码做了大量的注释。
下面是一些转换后的图像:
这是一个明显的进步。数字都很清楚,连我都看得一清二楚。仍然存在两个问题:
- 它们看起来不是手写的,而且太厚了
- 它们在黑色背景上不是全白的
所以,我们将门槛。然而,由于图像的各种颜色,每一种都需要不同的阈值来工作。我们将自动搜索最佳阈值。我注意到,根据像素数,一个数字通常占整个图像的 10–28%。
因此,我们将尝试不同的阈值,直到白色百分比在 10–28%的范围内。首先,我们将定义一个函数,它告诉我们输入图像中白色所占的百分比。有更短的方法可以做到这一点,但我想明确地展示这是在做什么。我们正在计算所有值为 255 的像素(255 表示白色,0 表示黑色)。
现在,我们将从阈值 0 开始,以 10 为增量增加到 255,直到我们处于 0.1–0.28 区域(此代码进入 for 循环):
厉害!终点在望。现在我们得到这样的图像(如果我们使用我们找到的阈值):
大多数图像看起来都很不错!然而,有些是有问题的。结果是一些数字比背景暗,就像你看到的右上角的 9。因此,阈值处理使它们变黑,而不是变白!从未达到 0.1–0.28 区域。
我们可以通过变量值来检查我们的阈值是否成功。如果 threshold 变量的值是 260,这意味着 while 循环没有找到一个完美的阈值就结束了。对于这些图像,我们将有一个单独的过程。
本质上,我们会
- 反转图像,使内部比背景明亮
- 转换成黑白
- 创建一个圆形蒙版来遮盖背景(当我们反转时,背景从黑色变成白色)。
这是视觉过程:
最后一步是最难的,所以我在代码中对它进行了注释。这是我们的整个函数:
我们将调整代码以使用新函数,并执行步骤 6–7。这些都是内置的 OpenCV 转换,所以没什么好奇怪的:
让我们看看图像是什么样的!
厉害!清晰可辨。最初,我们预计精度约为 10%,因为模型输出大小为 10,并且其输出基本上是随机的,因为原始图像看起来一点也不像模型所训练的 MNIST 数据集。有了这些变换后的图像,该模型肯定比随机模型做得更好。如果我们停在这里,我们的准确率大约是 63%,比随机准确率高 6 倍!然而,我们可以做得更多一点。
我们将骨骼化和扩大我们的图像。这将使我们的宽度一致,整体看起来更加统一。让我们开始吧:
这段代码是我们放在大 for 循环中的最后一段代码。结果如下所示:
它们有点参差不齐,但笔迹也是。这些输入对神经网络来说应该不成问题。现在,我们只需重塑我们的列表,加载模型,并进行评估:
将这段代码放在 for 循环下面。概括地说,我们加载我们的模型,重塑数据,并在评估后打印准确性。
结果
运行代码后,打印出来的内容如下:
我们来看看吧!我们得到了…的总体精确度。78%!这比随机测试好 7-8 倍,比中度到重度色盲的人好得多。这是杰出的!
如果我们看看我们对数字的回忆(正确预测的正面观察与实际类别中所有观察的比率),我们会看到我们对 1-5 和 9 有很好的表现。我们在 8 分的时候表现还可以,我们的神经网络在 6 分和 7 分的时候真的很挣扎。
这种方法显然有局限性,并且我列出的变换并不适用于所有可能的色盲图像(实际上,在阈值化步骤之后,在数据集中有一个图像不适用)。试着打印所有处理过的 9,你会看到阈值步骤产生的比率在 0.1 和 0.28 之间,但那是因为背景变成了部分白色。我没有试图找到解决这个问题的方法,因为这只影响了一张图片。
结论
我希望本教程能够提供关于如何使用相似的数据集对不同的数据集进行预测的信息。另外,我希望本教程能帮助初学者更好地掌握 OpenCV、Tensorflow 和 Python。
要查看完整代码并下载图片和模型,请查看 my Github 。
参考
[1]数据科学栈交换(2020),链接
真正的人工智能:理解外推 vs 概括
原文:https://towardsdatascience.com/real-artificial-intelligence-understanding-extrapolation-vs-generalization-b8e8dcf5fd4b?source=collection_archive---------11-----------------------
来源。图片免费分享。
不要混淆这两者
机器学习模型不需要很智能——它们的大多数应用都需要执行像推荐 YouTube 视频或预测客户下一步行动这样的任务。理解外推法和一般化/内插法之间的区别很重要,这样才能理解模型智能的真正含义,并避免混淆这两者的常见问题,这通常是许多模型实现失败的根本原因。
泛化是机器学习的全部要点。该模型被训练来解决一个问题,试图利用从该任务中学到的模式来解决相同的任务,只是略有不同。打个比方,假设一个孩子正在学习如何进行一位数加法。概括是执行相同难度和性质的任务的行为。这也可以称为插值,虽然泛化是一个更常用和理解的术语。
由作者创建。
另一方面,外推是指模型能够从较低维度的训练中获得更高维度的洞察力。例如,考虑一个一年级学生,他被教授一位数加法,然后面临一个多位数加法问题。一年级学生想,“好的,所以当个位数加起来大于 10 时,有一个 10 的部分和一个 1 的部分。我会考虑到这一点,并在十位数上加 1。”当然,这是算术所基于的关键见解,如果你足够努力地思考加法意味着什么,并且理解了位置值,你就能弄明白它。然而,大多数一年级学生从来没有意识到这一点,很少发现如何独立完成学业。
由作者创建。
重要的是要认识到外推是困难的。甚至许多人都无法成功地进行外推——事实上,智力确实是一种能够进行外推的衡量标准,或者能够将在较低维度中解释的概念应用于较高维度(当然,维度是指复杂程度,而不是字面意义)。大多数智商测试都是基于这个前提:以只有真正的推断者才能理解的方式使用标准概念。
就机器学习而言,外推的一个例子可以被认为是在一定范围的数据上进行训练,并能够在不同范围的数据上进行预测。对于简单的模式,例如简单的正数/负数或在一个圆内/不在一个圆内的分类,这可能很容易。
由作者创建。
然而,传统的机器学习方法限制了模型推断更复杂模式的能力。例如,考虑棋盘问题,在这个问题中,二维平面上交替的正方形被着色为 0 或 1。对人类来说,这种关系是清楚的,只要给定一个更小的有限的 x 乘 x 棋盘的规则,就可以继续给一个无限的棋盘着色。虽然棋盘问题是由人类的一组规则定义的(没有两个共用一边的正方形可以是相同的颜色),但数学上它是这样定义的:
由作者创建。
这是一种非常不直观的思维方式,大多数模型都不认为会产生严格的数学推断定义。相反,常规算法本质上试图以几何方式分割特征空间,给定任务,这可能有效也可能无效。不幸的是,在这种情况下,他们不能外推至他们接受训练的坐标之外的坐标。甚至许多神经网络都无法完成这项任务。
KNN 和决策树在 20x20 棋盘上训练并被告知预测 40x40 空间时的结果。由作者创建。
然而,有时候,外推法与其说是为了识别复杂的关系,不如说是为了找到一个智能的、可外推法的解决方案来执行国外范围的任务。例如,棋盘问题可以通过画对角线来解决。例如,已经观察到用神经网络集成发现了这种解决方案。
神经网络来自“通过预测性能加权的竞争学习神经网络集成”。由作者创建。
在机器智能的辩论中,你会听到一个常见的论点,即“机器只能做好一件事。”这确实是插值或泛化的定义——在一套预定义的规则中执行任务。然而外推法需要对概念有如此坚实的理解,以至于它们可以被应用到额外的领域,或者在教授的领域之外。当前的机器学习模型很少能够可靠地进行推断;通常,那些有希望的人在几何学上更容易推断出一个问题,而在其他问题上失败。所有的人工智能方法本质上都是插值的,即使人工构建一个外推(“智能”)算法也是有争议的。
外推很少是建模或机器学习的目标,但它经常与泛化互换使用-最明显的当然是线性回归,在这种情况下,当有多个维度在起作用时,将其趋于无穷大的预测作为黄金更常见,也更不明显(多元回归)。
外推法的另一个例子是,比如说,公司将在无异常值的数据上训练一个模型,然后在现实生活中实现它,在现实生活中,异常值要丰富得多,不能简单地忽略。这在模型的实现中很常见,常常不被发现,但这可能是您的模型在现实生活中可能无法达到测试结果的一个重要原因。当模型的定型数据和模型的预测数据之间存在差异时,您可能会要求模型进行外推。
XKCD 。有时甚至人类也是糟糕的推断者。图片免费分享。
模型通常不能很好地外推,无论是在符号智能的测量中还是在实际应用中。确保您的模型没有面临外推任务非常重要-当前的算法,即使像神经网络一样复杂和强大,也不能很好地执行外推任务。检查外推任务的一个不错的方法是绘制出训练和测试集中每一列的分布,然后查看测试集是否与训练集明显不兼容。
在我们能够创建一种能够概括所有问题的机器学习算法之前,类似于神经网络(当然,具有一些不同的架构)的概念如何能够独自解决几乎任何概括问题,它们将永远不会真正能够“智能”并在它们接受培训的狭窄范围之外执行任务。
如果你喜欢的话,你可能会对外推-概括讨论的应用感兴趣,来解释 ReLU 是如何工作的:
[## 如果整流线性单元是线性的,它们如何增加非线性?
神经网络最喜欢的功能背后的直觉
medium.com](https://medium.com/analytics-vidhya/if-rectified-linear-units-are-linear-how-do-they-add-nonlinearity-40247d3e4792)
房地产咨询数据项目
原文:https://towardsdatascience.com/real-estate-consulting-data-project-44c904480290?source=collection_archive---------35-----------------------
使用 Zillow 数据为房地产投资公司提供建议
照片由晨酿在 Unsplash 拍摄
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
最近,我接受了一项任务,根据从 Zillow 获得的数据集获得的见解,为一家虚构的房地产投资公司提供关于前 5 个邮政编码的投资建议,该数据集包含 14,723 个邮政编码中每个邮政编码的平均房屋销售价格,时间窗口从 1996 年 4 月开始,到 2018 年 4 月结束。该项目的分析和建模是结合使用 Python 和 R Jupyter 笔记本完成的。数据和项目笔记本可在项目存储库中的这里获得。
由于该项目使用的数据于 2018 年 4 月结束,因此可以想象这是提供咨询的时间,因为世界上最近的发展对金融和房地产市场产生了广泛的影响,而且没有办法将项目数据与当前事件联系起来。可以说,重要的是要记住,宏观经济和社会政治问题会在市场上造成不可预见的冲击,任何预测都应考虑到这种冲击造成的波动集群。幸运的是,这些数据跨越了包括 2007 年至 2010 年金融和房地产市场崩溃在内的时间框架,提供了一个观察单个邮政编码如何经受住上次风暴的机会,让人们对那些有望显示出对未来不利经济和市场条件的弹性的邮政编码有所了解。许多邮政编码在数据库的时间段内没有完整的数据,这使得不可能将它们的行为与那些有完整数据的行为进行适当的比较,因此被排除在考虑范围之外。
投资建议基于两个主要标准:高预期资本增值率和低预期方差,以及在投资期限内在邮政编码范围内租赁物业的盈利能力。为了预测每个邮政编码的资本增值率,设计了一种方法来为每个邮政编码快速生成适当的 SARIMAX 模型,以便可以对投资期限内的预测平均回报率和波动率进行比较。为了比较每个邮政编码内租赁物业的盈利能力,从 2017 年 Zillow research 的一篇文章中获得了一个数据库,其中包含各个大都市地区的 P2R(房价与租金)比率。这些比率可以与全国平均水平进行比较,并给出一个在给定区域内多少年的租金支付可以付清房产价值的概念。
代码块将遵循本文中展示的工作流进行演示。对于所用方法的更深入的研究,请参见资源库中的 Jupyter 笔记本。本文将介绍一种在 Python 工作流中为时间序列数据生成良好拟合的 SARIMAX 模型的有效方法,该工作流足够快,允许对每个邮政编码单独建模,以便可以比较这些模型,找到具有最佳前景的邮政编码。该方法将 Python 和 R(分别为 statsmodels 和 forecast)的时间序列建模包的优势结合起来,通过使用 rpy2 包从 Python 工作流中调用 R 的 forecast 包中 auto.arima 函数的快速模型生成功能,以便为 SARIMAX 模型生成最佳阶数和系数,然后使用获得的值平滑 statsmodels SARIMAX 模型。我们发现,这种方法可以生成始终令人满意的模型,避免了使用循环进行网格搜索以获得最佳模型阶数的耗时过程,并且可以利用 statsmodels 的所有统计明确性和功能,以及在 Python 环境中工作。
请注意,本文的内容仅旨在演示与房地产环境中的时间序列数据分析和建模相关的数据科学工作流程和方法,不得作为任何形式的投资建议。除非另有说明,所有图片都是作者的财产。
加载数据和初始观测值
首先,我们需要导入所有要使用的库;我们将使用许多标准的 Python 数据科学包,尤其是 pandas 和 statsmodels。
现在用熊猫来读取数据:
查看原始数据,我们可以看到有两列用 5 位数来标识“区域”在谷歌上快速搜索几下,就会发现“地区名”一栏包含了邮政编码。另一栏对我们没用。我们还可以观察到,数据是所谓的“宽格式”,其中每个邮政编码的日期及其对应值包含在向右扩展数据框架的列中,这就是它有 273 列的原因。要将数据转换为长格式,可以使用 pandas 的 melt 方法。出于我们的目的,我们需要长格式的数据。测试发现 sizeRank 功能没有用。
该操作复制了在列中找到的每个日期的每个邮政编码,从而得到一个包含 3,901,595 行的数据帧。在这一点上,可以使用多索引数据框架来处理面板数据,但是这里我将使用 GroupBy 对象。首先,需要将“date”列转换为 datetime,并且我们需要检查是否缺少值。
最后一个操作显示在“值”列中有 156,891 个丢失的值,我们需要记住这些值。现在,让我们创建我们的 GroupBy 对象,并首先查看一些邮政编码。
首先看一些数据,我们可以看到各个邮政编码有许多不同之处。只看 14,723 个中的前 6 个,就能看出平均值和增长率的差异。我们还可以看到他们正在遵循一个总体趋势,价值不断上升,直到 2007 年至 2010 年间的次级抵押贷款危机导致市场崩溃,随后在 2013 年左右开始复苏。只看这 6 个,我们可以看到一些邮编比其他的更好地经受住了风暴,这对于那些意识到未来的低迷可能是由不可预见的宏观经济影响引起的投资者来说是一个有吸引力的特征。
我们现在有了一些想法,在确定向投资者推荐的“5 个最佳邮政编码”时,我们可能会寻找什么:增长率和对糟糕经济环境的适应能力;但是还有其他的要考虑。首先,如果预期的增长率与较低的预期波动性相辅相成,人们会对投资最有信心。第二,最好是在持有期间将自有物业出租给租户,这样资本就不会无所事事。这意味着我们应该推荐这样的邮政编码,它不仅具有强劲的预期增长、较低的预期方差和对恶劣经济条件的弹性,而且还具有高于平均水平的租赁盈利能力。为了确定这一点,我们可以求助于一个叫做房价租金比(P2R)的指标。这一比率让我们了解到在某一地区购买和拥有房产的价格与租房者每年愿意支付的金额之间的比例。贾米·安德森撰写的这篇 Zillow research 文章提供了房地产投资者在租赁房产的盈利能力方面应该考虑的更多问题,并提供了我们现在将要导入的数据。
我们可以看到,在这篇文章发表时(2017 年 6 月 19 日,方便地接近我们数据集的末尾),全国平均 P2R 为 11.44。根据这篇文章,大多数“主要市场”的大多数房屋都可以出租获利,因此有理由认为,在 P2R 低于全国平均水平的任何邮政编码进行房地产投资,不仅对业主来说租金是有利可图的,而且盈利能力也将好于全国平均水平。
另一个丰富的房地产投资建议来源于 Sam Dogen 写的这篇金融武士文章。在这篇文章中,多根建议投资者遵循他所谓的“关键房地产投资规则”:购买公用设施,租用奢侈品(伯尔)。多根解释说,豪华房产(尤其是在沿海城市)往往不像公用事业房屋(尤其是在中西部)那样通过租赁获得利润,而且通常根本没有租赁利润,租金无法覆盖每年的拥有成本。多根引用了上面 Zillow research 的文章,并使用 P2R 比率来区分奢侈品和效用,他将 P2R 低于 9.6 的所有东西都标记为效用,P2R 高于 13.3 的所有东西都标记为奢侈品。这意味着我们应该寻找 P2R 低于全国平均水平的邮政编码,如果可能的话,希望低于 9.6。显而易见,由于预期资本增值率是我们的标准之一,我们可能无法获得 P2R 低于 9.6 的所有邮政编码,因为预期增长率通常反映在资本价格中,但这为我们的竞争者提供了一个坚实的目标。同样可以肯定的是,被视为公用事业的住宅所在的邮政编码的平均销售价格不会超过 50 万美元,因此这也将有助于缩小我们的列表。
对单个邮政编码建模
在我们能够遍历所有的邮政编码并为每个邮政编码生成一个模型之前,我们需要一种好的方法来快速生成一个适合单个邮政编码的模型。Statsmodels 为我们提供了 SARIMAX 模型的强大功能,但它不包含确定这种模型的最佳阶数的方法。使用循环和比较 AIC 分数的网格搜索非常慢,特别是如果要考虑 AR 和 MA 项的滞后,比如说 5 或 6。幸运的是,R 的预测包有一个 auto.arima 函数,它可以快速找到给定时间序列的最佳阶数和系数。这样,我们可以选择采用建议的阶数并让 statsmodels 估计系数,或者用给定的系数平滑建议阶数的 statsmodels SARIMAX。在这项研究中发现,由 auto.arima 函数估计的系数始终比使用 statsmodels 估计的系数产生更低的 AIC 分数,因此我们将使用前者来制作我们的模型。为了了解我们将如何做到这一点,我们首先需要看看如何使用 rpy2 从 Python 中调用 R 函数。我们将从进口必要的商品开始。
我们现在可以在 Python 工作流中使用 forecast 包中的函数,但是要利用输出结果还需要一点修补。系数和它们的名字可以在附加到返回对象的 vectors 中获得,但是顺序并不是以这样一种方便的方式存储的。让我们看看 auto.arima 函数返回的打印输出是什么样的,使用测试数据集的第一个邮政编码。请注意,我们必须将时间序列转换为 FloatVector,以便它与 R 函数兼容。另外,请注意如何从 pandas GroubBy 对象访问时间序列,方法是通过名称(邮政编码)获取一个组,将日期列设置为索引,然后获取值列。还要注意,Python 去掉了这些“较低”邮政编码的第一个零,因为它们是数值,但我们知道它实际上是一个前面带零的 5 位数邮政编码。在金融时间序列分析中,通常的做法是对一个序列的收益建模,而不是对价格建模,因为这为我们提供了一个比较所有邮政编码的通用尺度。为了数学上的方便,对数回报通常比百分比增长更受青睐,因为它们可以随着时间的推移进行累积求和。这些是通过取一系列的差分对数值而产生的。这会在我们要删除的序列的第一天产生一个 NaN 值。此外,频率“MS”被分配给产生的返回序列,因为这告诉 pandas 数据是每月的。
这里我们可以看到第一个邮政编码的返回流。我们可以看到序列有趋势,方差不是常数,意味着它不是平稳的。趋势可以通过另一阶差分来消除,但异方差将会保留,不可避免地导致我们模型中的异方差误差。尽管残差将是异方差的,但是只要误差在时间上以零为中心,具有大致的正态分布,并且不是序列相关的,那么该模型将是最有效的。该模型将根据给定估计参数的数据的对数似然性来估计参数,因此受不一致波动性影响的将是该模型的 sigma2(方差)估计值,该模型将在早年的较低方差和 2009 年前后的较高方差之间找到一个合适的中间值。这在我们的预测考虑中非常重要,因为该模型将基于方差的估计值生成置信区间,该估计值在某种程度上偏向于方差较低的过时市场制度,导致置信区间比实际上可能合适的区间更窄。
然而,尽管预测置信区间存在这一问题,但当比较许多在崩溃期间和之后经历不同程度的方差波动的邮政编码的模型时,使用整个时间序列来估计模型参数是有优势的,即使存在异方差,因为崩溃期间更强烈的波动期将导致模型中更高的方差估计值,这些模型适合没有很好处理崩溃的邮政编码。这意味着,一旦所有的模型都生成了,那些对未来方差前景更乐观的人将是那些被提供了波动性没有那么大峰值的数据的人;换句话说,那些在危机中表现出弹性的模型,意味着模型的比较仍然有利于我们找到我们想要的东西。人们可以在事后对预测的有偏 sigma2 估计进行调整,在执行预测之前,仅将平滑步骤中的该参数更改为更能反映近年来的变化的值,但由于这是一个假设项目,已经涵盖了很多内容,因此我将省略它。
寻找 ARMA 模型阶次的传统方法是 Box-Jenkins 方法,它使用 ACF 和 PACF 直观地寻找自相关中的尖峰。我们将在 auto.arima 函数中使用更现代的方法,但看看 ACF 和 PACF 的第一个邮政编码以及建议的订单会很有意思。请记住,回报将需要一个差分顺序,因此我们在查看要建模的自相关之前应用该顺序,并删除前导 NaN 值。
我们可以看到序列中确实存在一些序列相关性,但是很难确切地说出什么样的顺序最适合模拟它。看起来每年的季节性在 12 个滞后时是明显的,在 5 个滞后时有很强的自相关性。让我们看看从 auto.arima 调用返回的对象是什么样子的。请注意,在 R 中使用 ts 函数创建时间序列对象时,频率被指定为 12,以表示每月的数据。
Series: structure(c(-0.00265604405811537, -0.00177462335836864, -0.00266785396119396, -0.00178253166628295, -0.00178571476023492, -0.000894054596880522, -0.000894854645842713, 0, 0.00178890924272324, 0.00178571476023492, 0.00178253166628295, 0.0017793599000786, 0.002663117419484, 0.0017714796483812, 0.0026513493216207, 0.00264433825308963, 0.00263736416608573, 0.00263042676877312, 0.00262352577238545, 0.00261666089117085, 0.0034782643763247, 0.00346620797648711, 0.0025917941074276, 0.00258509407210461, 0.00171969087952739, 0.00171673861905397, 0.000857265376119187, 0.000856531101616653, 0.000855798083895465, 0.0017094021256483, 0.00170648505575954, 0.00170357792478271, 0.00254993763327249, 0.004235499766855, 0.00337553063128126, 0.00336417474563255, 0.00335289501031077, 0.00417537141048108, 0.00332779009267448, 0.00414422474602638, 0.00330305832925681, 0.00329218404347742, 0.00328138112317689, 0.00408664238545242, 0.00407000968829685, 0.00567032706008774, 0.00483482005458313, 0.00401123682645377, 0.00399521106728784, 0.0039793128514809, 0.00396354066245586, 0.00473560474583401, 0.00392927813988919, 0.00469484430420763, 0.00544960476756629, 0.00464756839654612, 0.00616334770766791, 0.0068886609951857, 0.00608366895361456, 0.00604688161489264, 0.00526119214336163, 0.00523365680611043, 0.00520640819057405, 0.00444116199996714, 0.00515654917924557, 0.00513009553102961, 0.00510391191817661, 0.0065241260769433, 0.00719945514285492, 0.00857148105014005, 0.00849863472146239, 0.00842701616188002, 0.00835659459094273, 0.00828734024856992, 0.00958255108099593, 0.00949159668157051, 0.00873367996875452, 0.00932097294306367, 0.0112027530765531, 0.0123739774874423, 0.00902067972593201, 0.00575633185257551, 0.00572338605268641, 0.00632113356336994, 0.00753299230754578, 0.00747667034301891, 0.00680485149838539, 0.0067588582951057, 0.00610502506680355, 0.0072771697738947, 0.00782429510752891, 0.0077635504899245, 0.00711324872451868, 0.0076493459184892, 0.00817284175587396, 0.00925932541279728, 0.0097449897009394, 0.010780246243792, 0.0112234623698484, 0.011650617219976, 0.0120615497338186, 0.0119178008640368, 0.0101795682134629, 0.0100769879503577, 0.0110208410142789, 0.0119326967118454, 0.0128108336717592, 0.0146578312983845, 0.014940516954951, 0.0156942897625889, 0.0149725086303825, 0.01380645591966, 0.012685159527317, 0.0120651115518431, 0.0100964602510096, 0.00682596507039968, 0.0049762599862273, 0.00270392233240102, 0.00134922440076579, 0.000449337235149727, -0.000898876465017295, -0.0013498314760465, -0.00225377602725274, -0.00225886700972744, -0.00181077460070966, -0.000453206443289389, 0, 0.000453206443289389, 0.00181077460070966, 0.00225886700972744, 0.00180342699915137, 0.000900495333249651, -0.0013510472669811, -0.00270758288154482, -0.00452899324870693, -0.00500569873443624, -0.00503088186627743, -0.0045955963233375, -0.00415417167913823, -0.00463607691747825, -0.00605921219926842, -0.00703732672057633, -0.00756147270057639, -0.00809721023262, -0.00623652776946138, -0.00482393603085285, -0.00436152860052985, -0.00389294895540893, -0.00390816325475818, -0.00294117859081666, -0.0024576075284326, -0.00345082915773354, -0.00395844158642866, -0.00347653690108984, -0.00348866538730341, -0.0040020063418531, -0.00351494210744541, -0.00453744161395342, -0.00354341043998474, -0.000507228009860583, 0.00202737018250154, 0.00303336936332954, 0.00252079790656623, -0.00151171608532152, -0.00201918291723047, -0.000505433419908385, 0.00252461633713885, 0.00402617554439999, 0.00300902935161851, -0.00100200409185014, -0.00301205046999264, -0.00706360151874996, -0.00813425939068146, -0.0123268124806586, -0.0135277817381336, -0.00683314091078202, 0.00263365967346196, 0.000525900616906938, -0.00263227317032033, -0.00422610243350618, -0.00424403820047914, -0.00266169973486008, 0.00159786984729493, 0.00318810046864648, -0.00106157122495887, -0.0042575902526405, 0, 0.00159872136369721, -0.00320000273067222, -0.00535619920052355, -0.00215053846322988, -0.00269469308842396, -0.00704037568232785, -0.00873367996875452, -0.00660068403135128, -0.00442478598035656, 0, 0.00442478598035656, 0.00495459312468327, 0.00383667228648576, 0.00327690080231591, 0.00163443239871519, -0.00217983737542049, 0.00109051264896465, 0.00705949171296005, 0.0118344576470033, 0.0085197533447694, 0.00264760546505549, -0.00211752328990755, -0.00318471606752091, -0.00533050302693994, -0.00643433855264597, -0.00431267514794698, -0.00162206037186685, 0.00054097918549445, -0.0021656749124972, 0, 0.0032467560988696, 0.00377460680028641, 0.00322407587175277, 0.00267881221002675, 0.00267165534280522, 0.00266453661509658, 0.00477834729198179, 0.00528263246442684, 0.00525487283835879, 0.00366204960651473, 0.00364868791549178, 0.00104004169541305, -0.0015604684570949, -0.00312826115380993, -0.00261438057407126, 0.00104657257067053, 0.00573665197743445, 0.00673752224774127, 0.00515199490942919, 0.0035906681307285, 0.00306748706786131, 0, 0.00102040825180616, 0.00508648095637376, 0.00455581653586101, 0.00654419652421367, 0.00899106955985651, 0.00496032763096999, 0.000989119764124524, 0.00148184764088199, 0.000493461643371162, -0.000493461643371162, 0.00639608576582695, 0.0102464912091715, 0.0106229873912866, 0.0109864969415678, 0.00945633524203515, 0.00656662772389005, 0.00837993730674924, 0.0115235200038608, 0.00866991513344573, 0.00453309933098467, 0.00271002875886417, 0, 0, 0.00450045764105589, 0.00403316701762257), .Tsp = c(1, 22.9166666666667, 12), class = "ts")
ARIMA(3,1,1)(0,0,2)[12]
Coefficients:
ar1 ar2 ar3 ma1 sma1 sma2
-0.5119 0.0622 -0.3987 0.9257 -0.4116 -0.3586
s.e. 0.0611 0.0649 0.0578 0.0259 0.0666 0.0703
sigma^2 estimated as 2.524e-06: log likelihood=1320.17
AIC=-2626.35 AICc=-2625.91 BIC=-2601.34
我们可以看到这有点乱,但我们需要的一切都在那里。如前所述,参数估计值和它们的名称可以方便地作为易于访问的向量附加到对象上。但是,订单不方便存储,需要通过将输出转换成字符串并对其进行索引来提取所需的信息。下面是两个函数,一个可以提取参数,另一个可以从这个对象中提取订单。
现在我们有了助手函数来从 auto.arima 输出中提取我们想要的信息。还有一个问题需要处理,那就是当 auto.arima 输出有一个常量时,我们需要以一个向量的形式向 statsmodels SARIMAX 对象提供一个外部变量,系数将被分配给这个向量。此外,创建我们的 auto.arima 响应对象可能要简单得多。我们可以创建另一个助手函数,一步提供创建 statsmodels SARIMAX 模型所需的一切,而不是每次都生成这些函数,如下所示:
我们现在拥有了快速生成时间序列的适当模型所需的一切。让我们在我们的第一个邮政编码的日志返回中尝试一下,看看它是否有效:
我们可以看到这个模型有一些问题,但它是相当有效的。正如预期的那样,残差是异方差的,在滞后 5 的残差中有一些轻微的自相关,这不是理想的。然而,残差以零为中心,尽管尖峰值(过度峰度,指由波动性聚类引起的细长峰)导致正态分布残差的 JB 检验零假设被拒绝,但它们不会太远,具有合理的偏斜和峰度。在其他几个邮政编码上测试这一过程表明,生成的模型一般不具有自相关残差,接近但不是正态分布的残差,异方差遵循相同的随时间增加的波动性的一般模式,以及由此产生的稀疏性。有很多讨论集中在这样一个事实上,即具有适合金融时间序列的完美 SARIMAX 模型并不常见,考虑到这个领域,尤其是考虑到它们生成的速度,这些模型是相当可靠的。
比较所有邮政编码的型号
我们现在希望将这个建模过程应用于所有具有完整数据的邮政编码,以及最近平均销售价格低于 500,000 美元的邮政编码。每个模型都将用于预测 5 年内的情况,然后我们将取每个模型预测期内预测平均值和置信下限的平均值进行比较。这两个指标对于邮政编码比较来说是一个很好的组合,因为较高的预期回报均值告诉我们,该模型对未来的回报前景持乐观态度,当这与同一时期较高的置信下限均值配对时,这意味着邮政编码不仅对收益有积极的前景,而且具有相对紧密的置信区间,从而具有较低的预期方差。在金融危机期间经历了不太强烈的波动聚集的邮政编码将在其模型中具有较低的 sigma2 估计值,因此在其预测中具有更紧密的置信区间。这种方法应该会引导我们找到我们投资标准中 3 个最重要的邮政编码:高预期资本增值率,低预期波动性,以及在危机期间对恶劣经济条件的弹性。一旦我们有了竞争对手,我们就可以查看他们的 P2R 比率,找出那些也能满足我们租赁盈利能力需求的比率。
尽管我们有一种新颖高效的方法来生成模型,但 14,723 个邮政编码仍然很多,为每个邮政编码生成一个模型需要几个小时。以下代码将运行适当的循环来编译指标的数据帧,我们将使用该数据帧来选择我们的顶级邮政编码候选项。
0 - 1001
(3, 1, 1)(0, 0, 2, 12) model with no constant
1 - 1002
(0, 1, 3)(0, 0, 2, 12) model with no constant
2 - 1005
(2, 1, 1)(0, 0, 2, 12) model with no constant
3 - 1007
(4, 1, 3)(1, 0, 1, 12) model with no constant
4 - 1008
(0, 1, 3)(0, 0, 1, 12) model with no constant...and so on forever
非常好。短短几个小时后,我们有了一些不错的预测指标,可以引导我们找到更好的投资邮政编码。我们采用的信息量最大的指标是整个 5 年预测中置信下限的平均值。这个数字包含了很多信息,因为如果没有一段时间内的高平均预测回报率以及低预期方差,它就不可能很高。这意味着我们可以按照这个指标降序排列我们的结果,找到目前为止我们的最佳竞争者,然后包括 P2R,以最终确定我们投资的前 5 个邮政编码的列表。
选择前 5 位邮政编码
结果出来了,但我们需要一个更具描述性的数据框架,我们还需要 P2R 比率。之前,我们看到 P2R 数据帧在“区域名称”列中记录了位置,这是地铁的名称以及州的缩写。我们可以从原始数据帧中创建一个类似的列,将 metro 和 state 列组合起来,这样我们就可以合并这两个数据帧。让我们将结果限制在前 200 名,然后遍历索引并创建一个 info dataframe,然后将所有内容合并在一起。
现在我们在一个地方就有了我们需要的所有信息。我们可以看到,P2R 一栏中有缺失值,因此我们无法对这些邮政编码的租赁盈利能力进行评论,我们将专注于那些我们有 P2R 信息的项目。让我们将我们的结果过滤到 P2R 低于全国平均水平的所有东西,然后从那里开始。
现在我们的搜寻即将结束。接下来要做的是分别检查每个邮政编码的模型,为投资者找到最好的机会。为了节省一点空间,这个列表中的前两个邮政编码具有历史上较低的波动性,然后在最近一两个月出现了巨大的意想不到的增长率,这些因素的结合使得模型预测在短期内相当乐观。然而,最好是建议客户投资于近几个月回报率较高的邮政编码,所以我们继续往下看。圣安东尼奥有很高的 P2R 比率,接近多根推荐的 9.6。由于我们的目标 P2R 是 10 左右,让我们考虑一下这意味着什么:需要 10 年的租金支付才能还清拥有一套房产的成本。这意味着,如果投资者持有房产 10 年,并在此期间将其出租,他们将已经还清了初始投资,并且仍然可以以潜在的更高价值出售房产!这给了他们巨大的投资回报。让我们看看圣安东尼奥的模型,并对未来 10 年进行预测。
我们可以看到,除了该数据集中任何邮政编码预期的典型异方差性之外,该模型拟合得相当好。残差接近正态分布,并且残差不是自相关的。让我们看看样本内和样本外的 10 年预测。
这是一个 10 年的样本预测,带我们回到危机中期,那时事情最不确定。
我们可以看到,尽管我们的 sigma2 可能有点低估,但我们模型的置信带包含了 2008 年 4 月以后的所有情况,除了最近的增长峰值。让我们看看这个模型对未来 10 年的预测。
这看起来很不错。预测的平均值为每月 2%左右,置信区间大多在零线以上。阴影区域中低于零线的面积比零线以上的面积小得多,这让投资者相信他们在未来 10 年不太可能亏损。
在这一点上,选择前 5 个邮政编码是通过检查每个邮政编码的单个模型手工完成的。只需在最初的 get_group 调用中更改邮政编码,就可以调整上面的三个代码块来为任何邮政编码生成模型及其预测。在选择前 5 名时,避免选择同一城市的两个邮政编码,因为分散投资在资本投资中通常是一件好事,这样,如果某个地方的市场受到不利影响,投资组合就不会过度暴露。然而,达拉斯/沃斯堡地铁的两个邮政编码被选中,尽管在不同的地区,一个是郊区,一个是市区。最好的 5 个邮政编码是:
所有这些邮政编码都有很好的平均回报预测,较低的估计波动性,以及低于全国平均水平的 P2R 比率。根据 SARIMAX 模型,由于这些邮政编码在预测中也具有最高的平均置信区间下限,因此它们代表了最不可能在未来失去价值的区域。这些邮政编码区的房产可以通过大约 10 年的租金来偿还所有权成本,因此,假设房屋除了保持其价值之外什么也不做,投资者可以在这段时间内获得 100%的利润,房产的任何资本收益都将是额外的。考虑到这些邮政编码具有最低的贬值概率,它们对于房地产投资者来说是相当有吸引力的选择。让我们一起来看看它们的价格曲线。
这让我们很好地了解了这些邮政编码对市场崩溃的弹性,以及我们所期待的近期增长。让我们看看其余前 5 位邮政编码的型号。
钟形扣,TN:
德克萨斯州达拉斯:
马克尔,在:
德克萨斯州花丘:
结论
在这个项目中,一个虚构的房地产投资公司被告知要投资的前五个邮政编码。为了回答这个问题,将领域知识与为每个邮政编码的返回序列生成的 SARIMAX 模型的比较相结合。为了在合理的时间框架内生成如此大量的模型,使用 Python 演示了一种为大量时间序列生成良好拟合模型的有效方法。通过在 Python 环境中使用 R 的 forecast 包中的 auto.arima 函数,可以使用 Python 工作流和 statsmodels 功能,并快速生成适当的模型。邮政编码是由他们对资本增值的展望评估的,寻找低预期方差的强劲增长。然后,具有最佳前景的邮政编码的 P2R 比率被用于筛选结果,同时具有良好前景和高于平均租赁利润率的邮政编码被手动选择用于推荐。由于目标 P2R 约为 10 年,因此生成了 10 年预测,以了解持有期内模型预期是什么,在持有期内,所有者可以预期支付财产所有权的成本。由于所选的邮政编码(78210、37020、75228、46770 和 75028)是数据集中 14,723 个邮政编码中最不可能贬值的,因此它们是房地产投资者的最佳选择。
辨别人工智能的真实例子
原文:https://towardsdatascience.com/real-life-examples-of-discriminating-artificial-intelligence-cae395a90070?source=collection_archive---------0-----------------------
人工智能算法展示偏见和成见的真实例子
马库斯·斯皮斯克在 Unsplash 上的照片
目录
- 介绍
- 人工智能偏见的三个真实例子
- 我们能从这一切中学到什么?
介绍
人工智能。
有些人说这是一个没有什么实际意义的时髦词。其他人说这是人类灭亡的原因。
事实是,人工智能(AI)正在引发一场技术革命,尽管 AI 尚未接管世界,但我们已经遇到了一个更紧迫的问题:AI 偏见。
什么是 AI 偏见?
人工智能偏见是用于创建人工智能算法的数据中的潜在偏见,最终可能导致歧视和其他社会后果。
让我举一个简单的例子来阐明这个定义:假设我想创建一个算法来决定一个申请人是否被一所大学录取,而我的输入之一是地理位置。假设来说,如果一个人的位置与种族高度相关,那么我的算法将间接有利于某些种族。这是人工智能偏见的一个例子。
这是危险的。歧视破坏了平等机会,加剧了压迫。我可以肯定地说这一点,因为已经有几个例子表明人工智能偏见确实做到了这一点。
在这篇文章中,我将分享三个真实的例子,说明人工智能算法何时对他人表现出偏见和歧视。
人工智能偏见的三个真实例子
1.美国医疗保健中的种族主义
照片由金奎大·斯蒂文斯在 Unsplash 上拍摄
2019 年 10 月,研究人员发现,在美国医院对超过 2 亿人使用的一种算法预测哪些病人可能需要额外的医疗护理,这种算法严重倾向于白人病人而不是黑人病人。虽然种族本身不是这个算法中使用的变量,但另一个与种族高度相关的变量是,即医疗费用历史。基本原理是,成本总结了一个特定的人有多少医疗保健需求。出于各种原因,平均而言,在同样的情况下,黑人患者比白人患者花费的医疗费用要低。
令人欣慰的是,研究人员与 Optum 合作,将偏差水平降低了 80%。但是如果他们一开始没有被审问,人工智能偏见会继续严重歧视。
2.康派斯牌衬衫
比尔·牛津在 Unsplash 上的照片
可以说,人工智能偏见最显著的例子是 COMPAS(替代制裁的矫正罪犯管理概况)算法,该算法在美国法院系统中用于预测被告成为惯犯的可能性。
由于所使用的数据、所选择的模型以及创建算法的整个过程,模型预测黑人罪犯再犯的误报率(45%)是白人罪犯的两倍(23%) 。
3.亚马逊的招聘算法
布莱恩·安杰洛在 Unsplash 上拍摄的照片
亚马逊是世界上最大的科技巨头之一。因此,毫不奇怪,他们是机器学习和人工智能的大量用户。2015 年,亚马逊意识到他们用于雇用员工的算法被发现对女性有偏见。这是因为该算法是基于过去十年提交的简历数量,由于大多数申请人是男性,它被训练成更倾向于男性而不是女性。
我们能从这一切中学到什么?
很明显,制作无偏见的算法很难。为了创建无偏见的算法,使用的数据必须是无偏见的,创建这些算法的工程师需要确保他们没有泄露任何自己的偏见。也就是说,这里有一些小贴士可以减少偏见:
- 一个人使用的数据需要代表“应该是什么”而不是“是什么”。我的意思是,随机抽样的数据会有偏差,这是很自然的,因为我们生活在一个有偏差的世界,在那里平等的机会仍然是一个幻想。但是,我们必须主动确保我们使用的数据平等地代表每个人,并且不会对特定人群造成歧视。例如,对于亚马逊的招聘算法,如果男性和女性的数据量相等,该算法可能不会有这么大的区别。
- 应该强制实施某种数据治理。由于个人和公司都有某种社会责任,我们有义务规范我们的建模过程,以确保我们在实践中是道德的。这可能意味着几件事,比如雇佣一个内部合规团队对每个创建的算法进行某种审计,就像 Obermeyer 的团队所做的那样。
- 模型评估应包括社会团体的评估。从上面的例子中,我们应该努力确保在比较不同的社会群体(无论是性别、种族还是年龄)时,真实准确率和假阳性率等指标是一致的。
你们还觉得怎么样?每个人都应该采取哪些最佳做法来最大限度地减少人工智能偏差!留下评论,大家一起讨论!
感谢阅读!
特伦斯·申
创始人ShinTwin|我们来连线一下LinkedIn|项目组合这里是。
真实或虚假的关系:你约会的有魅力的人更令人讨厌
原文:https://towardsdatascience.com/real-or-spurious-correlations-attractive-people-you-date-are-nastier-fa44a30a9452?source=collection_archive---------28-----------------------
因果推理和虚假关联
使用 Python 模拟假相关性
照片由达雷尔·弗雷泽在 Unsplash 上拍摄
魅力-个性相关性
这里有一个普遍的直觉:你已经非常仔细地挑选了你的约会对象,基于他们看起来有多好,以及他们是否有很好的个性。但不知何故,在你约会过的人中,那些更有魅力的人往往性格更差。吸引力和个性之间有很强的负相关性。
在你断定有魅力的人一定是令人讨厌的之前,我们可以使用一些基本的数据科学技能来测试我们的直觉,看看是否有什么地方出了可怕的问题(剧透:是的,有什么地方出了问题)。
如果你喜欢像这样的因果推理问题和悖论,看看洛德悖论(另一个常见的推理问题):
[## 数据科学:因果推理和洛德悖论:改变分数还是协变量?
hausetutorials.netlify.app](https://hausetutorials.netlify.app/posts/2020-04-11-causal-inference-and-lords-paradox-change-score-or-covariate/)
模拟数据以获得洞察力
但是我们怎么知道吸引力和性格之间的负相关是真的呢?数据科学家定期处理相关性,获得更多关于数据的直觉和学习分析方法的好方法是通过模拟。所以我们模拟一些数据来检验我们的直觉。
Python 模拟
首先,我们导入常用的数据科学模块:numpy
、pandas
、seaborn
(用于可视化仿真结果)。
import numpy as np
import pandas as pd
import seaborn as sns
让我们指定几个模拟参数,模拟一些数据。我们将设置一个随机种子,以便您可以复制我的结果,但如果您愿意,可以跳过它。你的模拟也可以工作,但是你的结果不会和我的一样,但是会非常相似。
# set seed so you can replicate my results
np.random.seed(1)# let’s pretend you have 500 potential dates to choose from
n = 500# generate personality and attractiveness data
# assume data comes from normal distribution
data = {"personality": np.random.randn(n),
"attract": np.random.randn(n)}# store data in pandas dataframe
df = pd.DataFrame(data)
因为个性和吸引力是使用np.random.randn()
随机生成的,所以模拟值来自正态分布,这两种分布并不相关。
sns.jointplot('attract', 'personality', *data*=df, *kind*='reg')
在你的 500 个潜在约会对象中,吸引力和个性之间没有关联。
现在让我们具体说明你的约会标准。这个参数反映了你有多挑剔。我们将它设置为 0.80,这意味着你将只和那些在你的 500 个潜在约会对象中,综合吸引力和个性值排在前 20%的人约会。
quantile = 0.80 # dating criterion
现在让我们决定你实际上和谁约会。
# add personality and attract values
df['personality_attract'] = df['personality'] + df['attract']# determine the 0.80 quantile personality_attract cutoff value
cutoff = df['personality_attract'].quantile(quantile)# determine who to date/reject
# if higher than our cutoff value/criterion, date person
# else (lower than cutoff value/criterion, reject person
# save 'dated'/'rejected' in new 'outcome' column
df['outcome'] = np.where(df['personality_attract'] > cutoff, 'dated', 'rejected')
过滤数据,使其只包含你约会过的人。
# select only rows/people you chosen to date
dated = df.query('outcome == "dated"')
dated
数据帧有 100 行(可以用dated.shape
验证)。在你可能约会的 500 个人中,你和其中的 100 个人约会了(前 20%的人)。
可视化模拟结果
让我们画出你约会过的人的personality
和attract
特征之间的相关性。记住,你选择约会对象是基于他们看起来有多好(‘吸引’)和他们是否有伟大的个性(‘个性’)。
sns.regplot('attract', 'personality', *data*=dated)
假设你之前和我一样使用了相同的随机种子,attract
和personality
之间的相关性应该大约是–0.48,你可以使用 pandas .corr()
方法:dated.corr()
来验证
你约会过的有魅力的人显然个性更差。
另外,如果您经常在 Python 中使用统计模型,我强烈推荐 Pingouin 库。
[## 用于统计测试的新 Python 库—比 statsmodels 更简单,比 scipy.stats 更丰富
统计建模变得更简单
towardsdatascience.com](/new-python-library-for-statistical-tests-simpler-than-statsmodels-richer-than-scipy-stats-ff380d4673c0)
是不是偶然?运行更多模拟
优秀的数据科学家非常了解机会和概率。上面的负相关可能都是由于偶然,所以总是有必要运行多个模拟来看看我们是否能重复上面的结果。
定义模拟功能
为了避免重复代码(软件开发中的 DRY 原则——不要重复自己),让我们定义一个运行模拟的函数。我们基本上是把上面所有的代码放在一个函数里。
下面是我们新定义的simulate
函数的注意事项:
- 模拟参数现在是函数参数
simulations
参数让我们指定运行多少模拟simulate
函数返回所有模拟的相关值
# define function to run simulations
def simulate(*simulations*=1000, *n*=500, *quantile*=0.80):
# initialize array to store simulated correlations
correlations = np.zeros(simulations)
# loop
for i in range(simulations): # same code described above in the article
data = {"personality": np.random.randn(n),
"attract": np.random.randn(n)}
df = pd.DataFrame(data) # identify who you want to date
df['personality_attract'] = df['personality'] + \
df['attract']
cutoff = df['personality_attract'].quantile(quantile)
df['outcome'] = np.where(df['personality_attract'] > cutoff,
'dated', 'rejected')
dated = df.query('outcome == "dated"') # compute correlation between attract and personality
correlations[i] = dated.corr()['personality'][1] return correlations
运行并绘制 1000 次模拟的结果
np.random.seed(1) # set seed so you get same results as me
correlations = simulate()
sns.distplot(correlations).set_title('Histogram of correlations')
下面是来自 1000 次模拟的 1000 个相关值的直方图。直方图的中点约为–0.65,所有模拟的相关性都小于 0。也就是说,在所有 1000 个模拟中,相关性都是负面的:你约会过的有魅力的人性格更差!
吸引力和个性之间的负相关模拟。
用不同的参数再次模拟
如果负相关是因为我们的模拟参数呢?现在,让我们假设你有一个更小的可供选择的人群(300 人),你决定对你的约会标准更加宽松(0.7:你愿意和高于 0.7 分位数的人约会)。
np.random.seed(2) # set seed so you get same results as me
correlations = simulate(n=300, quantile=0.7)
sns.distplot(correlations).set_title('Histogram of correlations')
同样,我们所有的模拟在吸引力和个性之间有负相关(大约-0.60)。
吸引力和个性之间的负相关模拟。
在你下结论之前,多思考和模拟
你认为负相关是真实的还是虚假的?也就是说,有魅力的人真的倾向于性格更差吗,还是我们正在处理的数据的性质有问题?剧透:是后者,但我不会告诉你为什么(因为答案可以在数据中找到),除了告诉你这是一个因果推断问题。
在您结束之前,请试验并调整上面的代码,模拟更多的数据,并更改参数(甚至是代码本身)。至关重要的是,以不同的方式绘制模拟数据和结果,你可能会在数据中看到有趣的模式。
我期待着你的想法,评论,或回答如下。如果你喜欢这篇文章,请关注我的更多数据科学文章,我会在以后的文章中解释因果推理如何帮助我们解决这个(cor)关系问题!
如果您对提高数据科学技能感兴趣,以下文章可能会有所帮助:
[## 在 Python 中重塑 numpy 数组—一步一步的图形教程
本教程和备忘单提供了可视化效果,帮助您理解 numpy 如何重塑数组。
towardsdatascience.com](/reshaping-numpy-arrays-in-python-a-step-by-step-pictorial-tutorial-aed5f471cf0b) [## 在 Python 中更有效地循环的两种简单方法
使用枚举和压缩编写更好的 Python 循环
towardsdatascience.com](/two-simple-ways-to-loop-more-effectively-in-python-886526008a70) [## 使用终端多路复用器 tmux 提高编码和开发效率
简单的 tmux 命令来提高您的生产力
medium.com](https://medium.com/better-programming/code-and-develop-more-productively-with-terminal-multiplexer-tmux-eeac8763d273)
更多帖子, 订阅我的邮件列表 。
具有深度学习的实时 3D 人脸跟踪
原文:https://towardsdatascience.com/real-time-3d-face-tracking-with-deep-learning-963b91bb5ad4?source=collection_archive---------11-----------------------
我在尝试复制 Snapchat 镜头和抖音特效背后的人工智能技术时学到的东西
电脑眼中的我
napchat 通过在人们的头上戴上有趣的狗耳朵、交换面部表情和其他把戏变得流行起来,这些把戏不仅有趣,看起来也不可能,甚至还有的魔法。我在数字视觉特效行业工作,所以我对这种魔力很熟悉..以及了解它在幕后如何运作的渴望。
魔术背后
修改人脸是好莱坞视觉特效中的常规工作,这是一项当今广为人知的技术,但通常需要数十名数字艺术家才能实现逼真的人脸变换。我们如何实现自动化?
以下是这些艺术家遵循的步骤的简单分类:
- 追踪3D 中人脸相对于摄像机的位置、形状和运动
- 3D 模型的动画捕捉到被跟踪的人脸(如狗鼻子)
- 将 3D 模型的光照和渲染成 2D 图像
- 将渲染的 CGI 图像的与真人动作镜头合成
步骤 2 和 3 的自动化与视频游戏中发生的事情没有太大的不同,它相对简单。合成可以简化为 3D 前景超过现场背景,很容易。挑战在于追踪,一个程序如何“看到”人类头部的复杂运动?
用人工智能追踪人脸
计算机科学界长期以来一直试图自动跟踪人脸,但这很难。近年来,机器学习来拯救我们,每年都有许多关于深度学习的论文发表。我花了一段时间寻找“艺术状态”,并意识到实时做到这一点是非常困难的!这是一个尝试应对挑战的好理由(这将与我已经实现的 AR 美颜模式配合得很好)。
“试图追踪面孔..这很难..实时做这个很辛苦!”
我是这样做的。
设计网络
卷积神经网络常用于图像的视觉分析,并且通常用于诸如对象检测和图像识别的应用。
基本的卷积神经网络架构(来自本刊 ⁹)
对于要实时评估的深度神经网络(至少每秒 30 次),需要紧凑的网络。随着机器学习和智能手机的普及,每年都会发现新的模型,推动效率的极限——在计算精度和开销之间进行权衡。在这些模型中,MobileNet、SqueezeNet 和 ShuffleNet 由于其紧凑性而在移动设备上的应用中很受欢迎。
针对不同复杂程度的 ShuffleNet V2 架构(来自作者)
ShuttleNet V2 最近推出,提供最先进的表演,有各种尺寸,以平衡速度和准确性。它配有 PyTorch,这是选择该型号的又一个原因。
选择要学习的功能
面部标志(摘自本文)
现在我需要找到 CNN 应该学习的特性。一种常见的方法是为面部的不同关键部位定义一系列锚点,也称为“面部标志”。
这些点被编号并战略性地围绕着眼睛、眉毛、鼻子、嘴和下颌线。我想训练网络来识别每个点的坐标,以便稍后可以基于它们重建遮罩或几何网格。
构建训练数据集
因为我想用 3D 效果增强视频,所以我寻找了一个具有 3D 地标坐标的数据集。300W-LP 是少数几个带有 3D 位置的数据集之一,它非常大,并且作为一个额外的好处,它提供了很好的面部角度多样性。我想将我的解决方案与最先进的技术进行对比,最近的出版物在 aflw 2000–3D 上测试了他们的模型,因此我选择 300W-LP 进行训练,并在 aflw 2000–3D 上进行测试以进行比较。
来自数据集 300W-LP 的图像,以数学方式生成剖面图
关于这些数据集的说明,它们是为研究社区准备的,通常不会免费用于商业用途。
扩充数据集
数据集扩充通过向已有的集合添加更多变化来提高训练的准确性。我对每个图像和地标进行了如下的变换,以随机的数量创建新的图像和地标:围绕中心旋转-/+ 40 度,平移和缩放 10%,水平翻转。我在内存中对每张图片和每一个学习阶段(时期)应用不同的随机变换来进行额外的增强。
还需要将输入图像裁剪到界标的边界框附近,以便 CNN 识别界标的相对位置。这是为了节省训练期间从磁盘加载的时间而做的预处理。
设计损失函数
不同参数设置下的机翼损失函数图(图片来自出版物 ⁴)
典型地,L2 损失函数用于测量标志位置的预测误差。最近的出版物 ⁴描述了一个所谓的机翼损失函数,它在这个应用中表现更好,我可以验证。我按照作者的建议,用 w=10 和ε = 2 对其进行参数化,并对所有地标坐标的结果求和。
训练网络
训练深度神经网络是非常昂贵的操作,需要强大的计算机。实际上,使用我的笔记本电脑一个培训阶段要花费数周时间,而建立一个像样的系统要花费数千美元。我决定利用云,这样我就可以只为我需要的计算能力付费。
我选择了 Genesis Cloud ,它提供了极具竞争力的价格和 50 美元的免费积分。我用 GeForce GTX 1080 Ti 构建了一个 Linux 虚拟机,准备了一个操作系统和存储映像,在那里我安装了 PyTorch 并上传了我的代码和数据集,所有这些都是通过 ssh 完成的。一旦系统设置完毕,就可以根据需要启动和关闭,创建快照允许从我离开的地方继续工作。
每个历元的平均误差图
内部训练循环处理 32 个图像的小批量,以最大限度地提高 GPU 上的并行计算。一个学习过程(epoch)处理大约 60,000 个图像的整个集合,并且花费大约 4 分钟。训练集中在 70 个纪元左右,所以为了安全起见,我让它整夜运行 100 个纪元。
我使用流行的 Adam 优化器,它可以自动调整学习率,从 0.001 开始。我发现设置正确的初始学习率是至关重要的,如果它太小,训练过早地收敛于次优解。如果它太大,就很难收敛。我通过反复试验找到了价值,这很费时间..实际上,为每次使用支付云费用是非常昂贵的!
估价
所有这些努力都得到了回报,通过更大的网络洗牌网 V2 2x,我在 aflw 2000–3D 上获得了 2.796 的归一化平均误差(NME)。在该数据集上,这比最先进的模型 ⁵及其 3.07 的非市场经济性要好很多,尽管该模型要重得多!💪
预测的界标与地面真实情况的比较证实了理论结果,界标甚至在大角度下也能精确地找到它们的路径(尽管 aflw 2000–3D 包含我的模型失败的极端角度的挑战性案例)。
在 aflw 2000–3D 上评估我的模型,红色标记来自地面实况,绿色标记预测
我的 MacBook Pro 上没有大的 CUDA GPU 进行推理(对模型的评价)。为了最大限度地利用硬件资源,我将模型转换为可移植格式 ONNX,并使用微软的库 ONNX 运行时,它可以在我的机器上更有效地推断模型(是的,它在 OSX 上运行!).在 CPU 上,推理时间在 100 毫秒以下,这已经很不错了,尽管不是实时的。但是我要记住,我在这里使用最大版本的 ShuffleNet V2 (2x)以获得最大的精度,我可以选择较小的版本以提高速度(例如 1x 版本快 4 倍)。我也可以在 GPU 上运行更好的数字。
这一切都是为了一个强大的面部跟踪系统..至少我是这么认为的。
视频的局限性
我终于可以把训练好的网络接入视频流了。在使用单独的模型来检测面部边界框时需要一个额外的步骤,因此我们可以在接近地标的位置裁剪图像,就像在训练数据集中一样。经过大量的研究,我选择使用这款轻量级人脸检测器,它的评估速度非常快,而且非常精确(我也试过其他的)。
尽管我尽了一切努力,但非常遗憾的是,我发现视频上的结果一点也不稳定:标记抖动很大,随时间漂移,检测不到眨眼。😱
我做错了什么?
摇晃的马克笔
进一步挖掘后,我意识到这是什么。训练数据集仍然是照片,而不是视频帧!它似乎确实在剧照上工作得很好,但视频就不同了。它们代表了额外的挑战:时间一致性(和运动模糊)。
注释不精确(来自本刊 ⁶)
正如来自悉尼科技大学和 Facebook Reality Labs 的这项工作 ⁶所指出的,来自训练数据集的地面真相标记是在每张照片上手动标注的,这不是很精确。如上所示,不同的注释器将标记放置在稍微不同的位置。
我们的网络实际上学习了不精确的地标位置——这导致在预测期间在小区域内随机抖动,而不是精确的位置。
来自互动演示的 1€ 滤镜的图示
解决这个问题的常见方法是在事件发生后稳定预测的标记。为了达到这种效果,正如谷歌研究的另一个出版物 ⁷所建议的那样,我使用了1⁸的€滤波器来平滑运动噪声。我发现它比传统的卡尔曼 滤波器给出了更好的结果,并且更容易实现。我还用它来稳定面部检测器返回的盒子,因为它也抖动很多,这没有帮助。
运动过滤器有很大的不同。但它并不完美,特别是像我笔记本电脑那样的低质量网络摄像头会产生嘈杂的视频,这种模式似乎不太喜欢。
上面提到的来自 UTS 和脸书的论文建议基本上如下微调训练模型:
前向-后向通信方案(摘自本刊 ⁶)
- 通过计算跨帧的光流来预测地标位置(OpenCV 可以做到这一点)
- 从该结果反向计算光流
- 基于来自光流的预测和来自预训练模型的预测之间的距离来计算损失函数
我自己没有尝试过,但是演示视频看起来很有前景。
僵硬的眼睛和眉毛
经过训练的网络受到眼睛运动的影响,它看不到眨眼,也不能完全“关闭”眼睛标志。与他们正在跟踪的相比,眉毛界标在它们的运动中似乎也是僵硬的。
我的宽面角模型
我的模型变得非常擅长预测轮廓,因为数据集中有大量的轮廓(实际上在面部角度方面非常平衡),但没有那么好地学习眼睛。如果 CNN 学习的特征倾向于生活在一致的位置周围,它可以表现得更好,这就是为什么我们必须在推理之前检测人脸边界框,并在训练期间围绕地标进行裁剪:这使得人脸每次都处于中心。
随着脸部角度的变化,脸部内部的特征——眼睛、嘴巴和鼻子——在帧中的形状和位置会发生变化,甚至可以在广角下消失。这使得模型每次都很难识别它们。我试着增加极端眼部姿势(闭着眼,睁着眼)的数据集,但收效甚微。
后续步骤
这个项目很有趣,但耗费时间和金钱(除了最初的 50 美元免费信贷外,我还自掏腰包 15 美元)。这是一个很好的学习机会,但我不打算重新发明轮子。自从我开始这段旅程以来,谷歌已经开源了 MediaPipe ,提供了他们模型的跨平台实现。虽然 MediaPipe 的初始演示显示了一些漂移、僵硬和抖动,这验证了我的结果。
不过,我有一些想法来改进我的方法(从上面提到的基于光流的微调开始)。
3D 可变形人脸模型
4DFM 变形模型
为了能够构建像 Snapchat 这样的应用程序,我们实际上需要的不仅仅是几个 3D 点。一种常见的方法是使用 3D 可变形人脸模型(3DMM)并将其拟合在带注释的 3D 点上。数据集 300W-LP 其实就有这样的数据。网络可以学习 3D 模型的所有顶点,而不是少量的界标,这样 3D 人脸将由模型直接预测,并准备好用于一些 AR 乐趣!
多重网络
为了提高整体精度,前面提到的机翼损失论文,以及谷歌研究的工作,建议用第一个轻量级模型预测一些地标。由于初始信息,我们可以垂直裁剪和对齐面部,以帮助第二个模型处理较少的姿势变化。
我相信,我们可以将专业模型的概念进一步推广到多个网络。我们可以为特定的面部角度训练不同的 CNN,比如一个网络用于大角度(60 +),一个用于中间角度(30 到 60),一个用于正面角度(0 到 30),然后以某种方式将它们结合起来。
或者,不同的网络可以学习不同的面部部分,一个用于眼睛,一个用于嘴,等等..希望简化模型的工作能提高精确度。第一遍可以如上所述检测头部的粗略位置和方向,然后为相关的专家网络裁剪和对准感兴趣的区域。
结论
深度学习在人脸跟踪中的应用是一个活跃的研究领域,在过去几年中取得了很多进展。仍有改进的空间,尤其是在跟踪视频方面。预测的面部特征的时间一致性以及眼睛和嘴巴等关键区域的精度仍然是一个挑战。
我很期待看到这个话题的未来!
[1]: N .马等, ShuffleNet V2:高效 CNN 架构设计实用指南 (2018),
[2]: X .董等,风格聚合网络人脸标志点检测 (2018)
[3]: X .朱等,大姿态人脸对齐:一种 3D 解决方案 (2016),
[4]: Z. Feng 等,用卷积神经网络实现鲁棒的人脸标志点定位 (2018),
[5]: J. Guo 等人,使用双变压器的堆叠密集 U 形网实现鲁棒的人脸对齐 (2018),
[6]: X .董等,注册监督:一种提高人脸标志点检测器精度的无监督方法 (2018)
[7]: Y. Kartynnik 等人,基于移动 GPU 的单目视频实时人脸表面几何 (2019),CVPR
[8]: G. Casiez 等, 1 €滤波器:一种简单的基于速度的低通滤波器,用于交互系统中的噪声输入 (2012),迟
[9]: V.H. Phung 等人,一种用于小数据集上云图像斑块分类的卷积神经网络的高精度模型平均集成 (2019),应用科学
实时自定义对象检测
原文:https://towardsdatascience.com/real-time-custom-object-detection-a95d955cecda?source=collection_archive---------20-----------------------
创建自定义对象检测器指南—第 2 部分
亚采克·迪拉格在 Unsplash 上的照片
在这篇文章中,我们将测试我上一篇文章中定制的暗网模型
建议:视频输出可以通过彭博快带在 YouTube 上获得。一个窗口的图像是我的个人电脑的屏幕截图。输出图像来源取自 Kaggle 的开源数据集。非常感谢 Shauryasikt Jena
在我的上一篇文章中,我们看到了如何使用 darknet 创建一个自定义的蒙版检测器。如果能看到它的行动,那会更有趣,不是吗?)
因此,让我们使它工作,是的,这些步骤比训练模型要容易得多,因为如果您已经按照我以前的文章安装了所需的库(唷!).
如果没有,保持冷静:),可以上我的文章详细查一下。
这是我以前的文章—
[## 使用暗网的自定义对象检测
自定义暗网完全指南
medium.com](https://medium.com/@tejas.khare99/custom-object-detection-using-darknet-9779170faca2)
使用 CPU 执行整个代码。如果您正在编写视频输出,您不需要 GPU,视频是根据您首选的每秒帧数值编写的。要编写视频文件,请查看步骤 10。
内容
- 导入库
- 从培训中获取生成的文件
- 阅读网络
- 输入图像的一些预处理
- 置信度得分、类标识符、边界框的坐标
- 非最大抑制(NMS)
- 绘制边界框
- 使用
- 写入文件(可选)
好吧…让我们成功吧!请通读整篇文章,以免遗漏任何内容。谢谢:)
1.导入库
请导入这些库。
import tensorflow as tf
import numpy as np
import cv2
import pandas as pd
import time
import os
import matplotlib.pyplot as plt
from PIL import Image
N 注:你还需要 ffmpeg==4.2.2+ 来写视频输出文件。如果你有任何问题,请浏览我以前的文章。一旦你有了 ffmpeg,确保你在安装了 ffmpeg 的同一个 anaconda 环境中运行所有的东西。
这就是你所需要的,让我们进入重要的下一步!
2.从暗网和训练模型中收集文件
这是我们的目标探测器运行的非常关键的一步。我在下面列出这些文件,确保你有这些文件。
- 习俗。名称文件
- 习俗。cfg 文件
注:我们在培训前创建了这些文件,所以如果你错过了其中的任何一个,你的模型将会给你带来麻烦。这两个文件对于您的自定义对象检测器来说是非常特定的,我以前的文章将指导您可以进行哪些更改。你可以冷静下来!创建这些文件只需一分钟,如果遵循每个细节:)
3.习俗。权重文件
好吧…让我们在这里暂停一分钟来理解你是如何得到它的。
这个文件被称为重量文件,它通常是一个大文件,也取决于你的训练大小(对我来说是 256mb)。当你的训练完成后,你就会得到这个文件。在我的例子中,我使用的文件名是 yolov 3 _ custom _ train _ 3000 . weights。在这里,“3000”意味着文件是在完成 3000 个历元后生成的。如果你已经通过了。cfg 文件,您会发现纪元设置为 6000。
那么我为什么没有用‘yolov 3 _ custom _ train _ 6000 . weights’呢?
这是因为经过一些测试后,我发现 3000 个历元后生成的权重文件在实际生成的所有权重文件中具有最好的准确性,而不仅仅是“6000”的那个。
好。因此,更多的时代应该意味着更高的准确性,对不对?
不尽然:(
更多的历元也意味着过拟合,这会大大降低精度。我的训练数据可能有一些重复的图像,或者我可能将错误地标记为****(是的,我知道..这是一个乏味的任务,所以..你知道思想是如何偏离正确的),这确实对准确性有直接影响。
3。阅读网
现在..测试部分开始。我会尽我所能让它简单易懂,显然,理解并排:)
幸运的是,cv2 有一个内置函数。
net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)
ln = net.getLayerNames()
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
这些漂亮的功能通过直接读取存储在 Darknet 模型文件中的网络模型并为我们的探测器代码设置它们,使我们的日常工作变得更加容易。!).
有关该函数的更多信息—
** [## OpenCV:深度神经网络模块
cv::dnn::blobFromImage(input array image,double scalefactor=1.0,const Size &size= Size(),const Scalar & mean=…
docs.opencv.org](https://docs.opencv.org/3.4/d6/d0f/group__dnn.html#gafde362956af949cce087f3f25c6aff0d)
您还需要从“yolo.names”文件中获取标签..
LABELS = open(labelsPath).read().strip().split("\n")
N 注:configPath、weightsPath 和 labelsPath 包含各自文件的路径
4.输入图像的一些预处理
这些是我们需要为我们的模型做的一些步骤,以获得一些预处理的图像。预处理包括 均值减法和缩放 。
[## OpenCV:深度神经网络模块
cv::dnn::blobFromImage(input array image,double scalefactor=1.0,const Size &size= Size(),const Scalar & mean=…
docs.opencv.org](https://docs.opencv.org/3.4/d6/d0f/group__dnn.html#ga29f34df9376379a603acd8df581ac8d7)
(H, W) = image.shape[:2]
blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416),
swapRB=True, crop=False)
net.setInput(blob)
layerOutputs = net.forward(ln)# Initializing for getting box coordinates, confidences, classid boxes = []
confidences = []
classIDs = []
threshold = 0.15
5.获得一些自信
是的…实际上在这一步之后,我们会对我们的代码有一些信心,并且更好地理解我们已经做了什么,以及在这之后我们要做什么。
for output in layerOutputs:
for detection in output:
scores = detection[5:]
classID = np.argmax(scores)
confidence = scores[classID] if confidence > threshold:
box = detection[0:4] * np.array([W, H, W, H])
(centerX, centerY, width, height) = box.astype("int")
x = int(centerX - (width / 2))
y = int(centerY - (height / 2))
boxes.append([x, y, int(width), int(height)])
confidences.append(float(confidence))
classIDs.append(classID)
那么这段代码到底在做什么呢?
包含一个巨大的 2D 浮点数数组,从中我们需要“将要”绘制的边界框的坐标、classid 和每个预测的置信度得分,或者我们可以说是检测:)
6.非最大抑制(NMS)
对..最初,当我没有向它提供正确的输入数据类型时,这一步给了我很大的困难。我也试过 NMS 的一些预写功能,但是我的物体检测太慢了…
尼克·艾布拉姆斯在 Unsplash 上拍摄的照片
在撞了我的头一段时间后(不是字面上的..),我能够通过为这个超快救生功能编写上一步中给出的代码来获得正确的输入数据类型。
idxs = cv2.dnn.NMSBoxes(boxes, confidences, threshold, 0.1)
你可以在这里找到一些信息—
[## OpenCV:深度神经网络模块
cv::dnn::blobFromImage(input array image,double scalefactor=1.0,const Size &size= Size(),const Scalar & mean=…
docs.opencv.org](https://docs.opencv.org/master/d6/d0f/group__dnn.html#gaeec27cb32195e71e6d88032bda193162)
那么什么是 NMS 呢?
该模型返回多个预测,因此单个对象存在多个框。我们当然不希望这样。多亏了 NMS,它为该对象返回了一个单一的最佳包围盒。
为了深入了解 NMS 及其运作方式—
[## 非最大抑制(NMS)
一种消除目标检测中重复和误报的技术
towardsdatascience.com](/non-maximum-suppression-nms-93ce178e177c)
7.绘制边界框
Aahhaa..有趣的部分。现在让我们的探测器开始工作吧
mc = 0
nmc = 0if len(idxs) > 0:
for i in idxs.flatten():
(x, y) = (boxes[i][0], boxes[i][1])
(w, h) = (boxes[i][2], boxes[i][3]) if LABELS[classIDs[i]] == 'OBJECT_NAME_1'):
mc += 1
color = (0, 255, 0)
cv2.rectangle(image, (x, y), (x + w, y + h), color, 1)
text = "{}".format(LABELS[classIDs[i]])
cv2.putText(image, text, (x + w, y + h),
cv2.FONT_HERSHEY_SIMPLEX,0.5, color, 1)
if (LABELS[classIDs[i]] == 'OBJECT_NAME_2'):
nmc += 1
color = (0, 0, 255)
cv2.rectangle(image, (x, y), (x + w, y + h), color, 1)
text = "{}".format(LABELS[classIDs[i]])
cv2.putText(image, text, (x + w, y + h),
cv2.FONT_HERSHEY_SIMPLEX,0.5, color, 1)text1 = "No. of people wearing masks: " + str(mc)
text2 = "No. of people not wearing masks: " + str(nmc)
color1 = (0, 255, 0)
color2 = (0, 0, 255)cv2.putText(image, text1, (2, 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color1, 2)
cv2.putText(image, text2, (2, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color2, 2)
搞定了。!这段代码会给你一个包含你的边界框的图片/框架
N 注:请务必根据您的对象名称更改OBJECT_NAME_1
和OBJECT_NAME_2
。这将使你更好地理解你的代码;)
T ip:我建议你创建一个函数,在其中传递一个图像,因为以后你可以将这个函数用于视频以及图像输入;)
9.使用
上面的代码有两种用途—
- 实时,即将视频传递给探测器
这可以通过从视频中读取帧来完成,如果你愿意,你也可以调整它的大小,以便你的“cv2.imshow”以更快的速度显示输出帧,即每秒帧。用 cv2 阅读视频——
[## 视频入门- OpenCV-Python 教程 1 文档
学会看视频,显示视频,保存视频。学会从相机捕捉并显示它。你会学到这些…
opencv-python-tutro als . readthedocs . io](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_video_display/py_video_display.html)
注意:你不需要将获得的帧转换成灰度。
现在只需将框架传递给功能(在提示中提到)和吊杆..你有你的实时物体探测器准备好了!
输出视频—
以 20fps 写入的视频输出
N 注:上面的视频输出很流畅,因为我已经以每秒 20 帧(fps)的速度将这些帧写入了一个. mp4 文件
2.图像
你也可以通过传递一张图片来测试你的物体检测器。(是啊..没那么好玩)。用 cv2 来读取图像—
[## 图像入门- OpenCV-Python 教程 1 文档
cv2.waitKey()是一个键盘绑定函数。它的参数是以毫秒为单位的时间。该功能等待…
opencv-python-tutro als . readthedocs . io](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_image_display/py_image_display.html)
输出图像—
物体探测器的单图像输出
10.写入文件(可选)
你可能想知道我是如何让视频输出如此流畅的,对吗?这里有一个技巧,你可以用它来获得流畅的视频输出…
OpenCV 有一个函数叫做 cv2。VideoWriter(),您可以通过指定文件名、codecid、fps 和与输入字段相同的分辨率来编写帧。
[## OpenCV: cv::VideoWriter 类引用
视频编剧类。更大的...默认构造函数。构造函数初始化视频编写器。在 Linux FFMPEG 上…
docs.opencv.org](https://docs.opencv.org/3.4/dd/d9e/classcv_1_1VideoWriter.html)
在 while 循环之外定义变量out
,在该循环中读取视频的每一帧
out = cv2.VideoWriter('file_name.mp4', -1, fps,
(int(cap.get(3)),int(cap.get(4))))
注意:第二个参数'-1 '是要给出的 codecid,但是它在我的计算机上工作得很好。计算机上的 codecid 可能不同。请访问这个网站进行调试—
[## 无法使用 OpenCV 和 Python 编写和保存视频文件
感谢贡献一个堆栈溢出的答案!请务必回答问题。提供详细信息并分享…
stackoverflow.com](https://stackoverflow.com/questions/38397964/cant-write-and-save-a-video-file-using-opencv-and-python)
最后一个参数将帮助您获得输入视频的分辨率。之后,将下面的代码放入调用检测器函数的 while 循环中。
while True:
....
....
image = detector(frame)
out.write(image)
....
....
注意:你的探测器函数应该返回一个“图像”
ip:你也可以用“moviepy”将你的画面写入视频…
[## 电影
MoviePy 依赖于 Python 模块 Numpy、imageio、Decorator 和 tqdm,这些模块将在…
pypi.org](https://pypi.org/project/moviepy/)
pjreddie 暗网的推理时间图
原来如此!我希望你现在已经有了自己的自定义对象检测器。干杯!
感谢您通读整篇文章,希望您能从中受益。如果你有任何反馈,他们是最受欢迎的!**
使用 Azure 的 Power BI 中的实时数据流
原文:https://towardsdatascience.com/real-time-data-streaming-in-power-bi-with-azure-8650d3cbfddb?source=collection_archive---------20-----------------------
使用 Azure 创建无缝的实时 Power BI 仪表板
背景
Azure Event Hubs 是一个大数据流平台和事件摄取服务,每秒可以跟踪和处理数千个事件。来自活动中心的数据可以使用实时分析服务进行转换和存储。 Azure Stream Analytics 是一款实时分析服务,旨在帮助分析和处理可用于触发警报和行动的数据流。Power BI 是一项商业分析服务,提供交互式可视化。
目标
利用 Azure 数据接收/查询服务,如事件中心和流分析——成功创建自流式 Power BI 实时仪表板
设置 Azure
- 首先,访问 Azure 门户,通过以下链接设置您的 Azure 免费试用订阅:https://azure.microsoft.com/en-us/free/
- 一旦您的免费试用帐户被激活,请访问 azure 门户网站:https://portal.azure.com/#home.仔细检查右上角,确保您已使用您的免费试用 azure 帐户登录。如果不是,请确保登录,然后再执行后续步骤。
- 在左上角的标题下:“微软 Azure”,点击创建资源。
4.在“搜索市场”搜索栏中,键入“资源组”。点击标题为“资源组”的第一个结果,然后点击创建。
5.点击 create 后,您将转到一个页面,在该页面中您可以设置新资源组的设置。为您的新资源组键入任何名称,然后点击下面标题为“Review+Create”的蓝色按钮。要进入资源组,请单击位于门户右上角的通知图标。然后点击“转到资源组”。
6.现在,再次单击门户右上角的 create a new resource 按钮。
7.在搜索栏中,输入“活动中心”。点击标题为“活动中心”的第一个结果****
8.这将再次把您带到一个页面,您可以在这里设置新的活动中心的设置。为您的活动中心键入任何名称。将定价等级设置为标准。启用 Kafka,并确保“使该命名空间区域冗余”被关闭。订阅应设置为免费试用。选择您在之前步骤中创建的现有资源组。保持位置设置为美国西部,并将吞吐量单位设置为 4。同时启用自动充气。
8.点击“创建”后,需要几分钟时间来部署事件中心。单击右上角的通知图标,查看事件中心部署的状态。一旦部署成功,单击通知描述中的事件中心链接名称。
点击您的活动中心的名称。在我的例子中,我将点击文本 TestEventHub56
9.单击后,它会将您带到您的部署页面。只需单击转到该资源即可访问您的事件中心名称空间。****
10.进入 event hub 名称空间后,查看右侧列中的各种资源部分。在实体下查找标题为“事件中心”的部分。****
11.
转到活动中心页面后,单击单词活动中心旁边的+图标。点击后,您将进入活动中心创建设置页面。键入新事件中心的名称(不同于您的命名空间名称),并将分区计数和消息保留时间设置为 4。将捕获设置为关闭。然后点击创建。将立即创建事件中心,并且您将被转移回您的名称空间中的事件中心页面。要访问新的事件中心实例,单击其名称。
12.下一个设置是流分析作业。要进行设置,单击左上角的 create resource 按钮。然后,搜索上游分析作业。点击第一个结果,然后点击创建。您将再次转到流分析作业设置页面。在“设置”页面中,输入您的 ASA 作业名称,并选择您创建的资源组。保持托管环境**为云,并将流式单元移动到 4。**
13.部署您的 ASA(Azure Stream Analytics)作业需要几分钟时间。一旦部署成功,点击通知栏中的转到资源。
14.进入流分析作业后,单击右侧栏中作业拓扑下的输入。****
在输入页面中,点击页面顶部的新流输入。一旦点击,它将带来三个不同的流输入供您选择。点击“活动中心”。****
15. 1。点击活动中心后,将显示输入设置页面。为您的输入别名设置一个名称,并保持其他设置不变。确保将“事件序列化格式”**设置为 JSON。接下来,点击保存。这将自动开始测试与 ASA 和您的活动中心的连接。它将很快弹出一个通知,说你的连接是成功的。**
16.接下来,转到“作业拓扑”下的输出部分****
一旦你点击输出。选择页面顶部的添加按钮。向下滚动选择 Power BI 作为输出。在 Power BI 设置页面中,设置 Power BI 输出别名的名称。然后点击授权。登录您的 Power BI 个人/工作帐户。登录后,为数据集选择一个名称。运行流分析作业会在 Power BI 中自动创建流数据集。数据集名称将是该流式数据集的名称。还要选择一个表名。****
17.一旦您单击 save,它将自动开始测试到输出的连接。它应该说连接成功。
18.现在,回到您的事件中心名称空间。点击右上角“创建资源”下的主页图标。确保选择“事件中心名称空间”而不是实例。名称空间是您在本教程中创建的第二个资源。单击后,您将位于事件中心名称空间内。在右侧栏中,点击设置下的共享访问策略。
****
Python 设置
我们将使用 Python 向我们的 Azure 事件中心发布数据。请随意使用最适合您的 IDE。流行 Python ide:py charm,notepad++
我们将使用 pandas 读取 excel 文件中的数据,然后将数据值发布到 Azure Event Hub。
建立一个包含行和列的简单 Excel 表格。至少有 15-20 行数据供 Python 脚本读取。我的数据将包含产量、SKU、序列号、产品重量、皮带速度等列。
负载字典应该分别具有列名和行值数据类型的键值对。
确保安装所有必需的软件包,否则程序将无法运行。
现在您的 python 程序已经设置好了,可以运行了。
运行程序并确认您的结果没有任何错误。
流分析和 Power BI
- 现在继续你在 Azure 门户中的流分析工作。点击“职位拓扑”下的查询****
- 从这里,将以下代码复制到您的流分析查询中:
用您的列名替换 SKU、产量、BeltEfficiency 等。确保相应地调整数据类型。
流分析查询数据类型的完整列表可以在这里找到
3.现在点击你的输入名旁边的 3 个省略号。接下来,单击来自输入的样本数据。
4。等待您的输入被采样。采样完成后,您将会收到一个通知,告知您的样本已经成功。现在点击页面顶部的 test。
5.一旦测试成功,它应该会在查询的底部弹出您的结果。现在,单击 ASA 作业右侧的概述。然后点击开始。这将启动您的流式作业。
6.ASA 作业需要一段时间才能开始流式传输,但一旦开始,将会在 Power BI 工作区的数据集部分创建一个新的流式数据集。在这里,您可以创建一个新的仪表板,并使用您的流数据集创建视觉效果。****
联系人:
索希尔·巴蒂亚
使用 OpenCV 和 Dlib 的实时眼睛跟踪
原文:https://towardsdatascience.com/real-time-eye-tracking-using-opencv-and-dlib-b504ca724ac6?source=collection_archive---------3-----------------------
在本教程中,学习通过 python 中的网络摄像头创建一个实时凝视探测器。
第一步是下载所需的包。通过 pip 安装:
pip install opencv-python
pip install dlib
或者,如果您使用 Anaconda,那么使用 conda:
conda install -c conda-forge opencv
conda install -c menpo dlib
除此之外,我们需要一个面部关键点检测器,可以实时检测眼睛。为此,我们将使用 dlib 库中预先训练好的网络,该网络可以检测出本论文中提出的“68 个关键点”。所需的预训练模型可以从这里下载。使用 Dlib 是因为它可以实时给出预测,不像 CNN 模型,它对我来说非常重要,因为我正在为在线监督制作 AI。
Dlib 面部关键点。图片取自此处。
使用 Dlib 的眼睛检测
首先要做的是找到眼睛,然后我们才能继续进行图像处理,并找到我们需要找到一张脸的眼睛。面部关键点检测器将 dlib 模块的一个矩形对象作为输入,它只是一张脸的坐标。为了找到人脸,我们可以使用 dlib 内置的正面人脸检测器。您可以使用任何分类器来完成这项任务。如果你想要高精度和速度对你来说不是问题,那么我会建议你使用 CNN,因为它会提供更好的精度,特别是对于非正面人脸和部分遮挡的人脸,如下面链接的文章所示。
[## 用于遮挡倾斜面部的鲁棒面部标志
Dlib 提供了一个很好的面部标志检测器,但是当面部处于陡峭的角度时,它不能很好地工作。学习如何…
towardsdatascience.com](/robust-facial-landmarks-for-occluded-angled-faces-925e465cbf2e)
import cv2
import dlibimg = cv2.imread('image.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # convert to grayscale detector = dlib.get_frontal_face_detector()
rects = detector(gray, 1) # rects contains all the faces detected
这时我们有了矩形的人脸对象,我们可以把它传递给关键点检测器。
def shape_to_np(shape, dtype="int"):
coords = np.zeros((68, 2), dtype=dtype)
for i in range(0, 68):
coords[i] = (shape.part(i).x, shape.part(i).y)
return coordspredictor = dlib.shape_predictor('shape_68.dat')
for (i, rect) in enumerate(rects):
shape = predictor(gray, rect)
shape = shape_to_np(shape)
for (x, y) in shape:
cv2.circle(img, (x, y), 2, (0, 0, 255), -1)
获得输出。
关于 dlib 的更详细的描述可以在这篇很棒的文章中找到,这篇文章是我在做这个项目时参考的。
利用 OpenCV 寻找眼球中心
照片由 Anastase Maragos 在 Unsplash 拍摄
我们将通过网络摄像头获得现场直播。要打开网络摄像头,读取帧并显示它,您可以使用以下代码:
import cv2cap = cv2.VideoCapture(0)
while(True)
ret, img = cap.read()
cv2.imshow("Output", img)
if cv2.waitKey(1) & 0xFF == ord('q'): # escape when q is pressed
break
所以,现在我们如何从网络摄像头读取帧,是时候对他们进行工作,以达到我们的目标。我们创建一个新的黑色遮罩,使用与我们的摄像头框架相同尺寸的 NumPy。存储来自关键点阵列形状的左右眼点的(x,y)坐标,并使用cv2.fillConvexPoly
将其绘制在蒙版上。它接受一个图像,点作为一个 NumPy 数组,数据类型= np.int32
和颜色作为参数,并返回一个图像,这些点之间的区域用该颜色填充。
def eye_on_mask(mask, side):
points = [shape[i] for i in side]
points = np.array(points, dtype=np.int32)
mask = cv2.fillConvexPoly(mask, points, 255)
return maskleft = [36, 37, 38, 39, 40, 41] # keypoint indices for left eye
right = [42, 43, 44, 45, 46, 47] # keypoint indices for right eye
mask = np.zeros(img.shape[:2], dtype=np.uint8)
mask = eye_on_mask(mask, left)
mask = eye_on_mask(mask, right)
这样做之后,我们有了一个黑色的蒙版,眼睛区域是白色的。这个白色区域用一个形态学操作cv2.dilate
扩大了一点。使用cv2.bitwise_and
和我们的蒙版作为我们图像上的蒙版,我们可以分割出眼睛。将所有的(0,0,0)像素转换为(255,255,255),这样只有眼球是唯一剩下的黑暗部分。将结果转换为灰度,使图像为阈值处理做好准备。
kernel = np.ones((9, 9), np.uint8)
mask = cv2.dilate(mask, kernel, 5)
eyes = cv2.bitwise_and(img, img, mask=mask)
mask = (eyes == [0, 0, 0]).all(axis=2)
eyes[mask] = [255, 255, 255]
eyes_gray = cv2.cvtColor(eyes, cv2.COLOR_BGR2GRAY)
阈值处理用于创建二元掩模。因此,我们的任务是找到一个最佳阈值,根据这个阈值,我们可以从眼睛的其余部分中分割出眼球,然后我们需要找到它的中心。但是阈值对于不同的照明条件是不同的,所以我们可以制作一个可调节的跟踪条来控制阈值。平心而论,我从 Stepan Filonov 那里得到了这个想法,他也试图在这篇文章中解决这个凝视检测的问题,并使用了 Haar cascade 和 Blob 检测。阈值处理步骤,即腐蚀,膨胀和中值模糊也是从他那里得到的,但他的最终结果并不令人信服,所以我做了这个解决方案。
def nothing(x):
pass
cv2.namedWindow('image')
cv2.createTrackbar('threshold', 'image', 0, 255, nothing)
threshold = cv2.getTrackbarPos('threshold', 'image')
_, thresh = cv2.threshold(eyes_gray, threshold, 255, cv2.THRESH_BINARY)
thresh = cv2.erode(thresh, None, iterations=2)
thresh = cv2.dilate(thresh, None, iterations=4)
thresh = cv2.medianBlur(thresh, 3)
用跟踪条反转后显示阈值
我们已经到了项目的最后一步。眼球被分割出来,我们可以利用cv2.findContours
来找到它们。现在我们的背景是白色的,眼球是黑色的。但是在 OpenCV 的cv2.findContours()
方法中,要查找的对象应该是白色的,背景是黑色的。所以我们需要使用cv2.bitwise_not
来反转我们的阈值。现在我们可以找到轮廓。理论上,我们可以说,我们现在需要做的是找到两个最大的轮廓,这些应该是我们的眼球。然而,这为假阳性留下了一点空间,可以通过找到眼睛之间的中点并将图像除以该点来解决。然后我们在那些划分中找到最大的轮廓,应该是我们的眼球。关键点 40 和 43(在 Python 中是 39 和 42,因为 index 从零开始)用于寻找中点。用cv2.contourArea
排序,找到中点两边最大的等高线。我们可以利用cv2.moments
找到眼球的中心。
def contouring(thresh, mid, img, right=False):
cnts, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnt = max(cnts, key = cv2.contourArea) # finding contour with #maximum area
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
if right:
cx += mid # Adding value of mid to x coordinate of centre of #right eye to adjust for dividing into two parts
cv2.circle(img, (cx, cy), 4, (0, 0, 255), 2)# drawing over #eyeball with redmid = (shape[39][0] + shape[42][0]) // 2
contouring(thresh[:, 0:mid], mid, img)
contouring(thresh[:, mid:], mid, img, True)
在运行时,我们的代码会抛出几个类似于max() arg is an empty sequence
或division by zero
的错误,分别在没有找到轮廓或M['m00']
为零时抛出。要解决这个问题,请将轮廓绘制函数包含在 try 块中。如果只在没有检测到眼睛时才会出现错误,我们不需要做任何事情。新的轮廓绘制函数将如下所示:
def contouring(thresh, mid, img, right=False):
cnts, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
try:
cnt = max(cnts, key = cv2.contourArea)
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
if right:
cx += mid
cv2.circle(img, (cx, cy), 4, (0, 0, 255), 2)
except:
pass
一切都结束了。只需显示 img 和 thresh 并相应地设置阈值跟踪栏,就可以享受了。完整代码:
使用人工智能进行在线监督的完整代码可以在我的 Github 上找到。
使用 TensorFlow、Keras 和 OpenCV 的实时人脸检测器
原文:https://towardsdatascience.com/real-time-face-mask-detector-with-tensorflow-keras-and-opencv-38b552660b64?source=collection_archive---------13-----------------------
了解如何使用 Tensorflow、Keras 和 OpenCV 以及您的网络摄像头或移动摄像头创建实时面具检测器
澳门图片社在 Unsplash 上拍摄的照片
在本文中,我将使用由 Prajna Bhandary 创建的面具数据集。该数据集由属于with mask
和without mask
2 类的 1376 幅图像组成。
我们的主要焦点是检测一个人是否戴着面具,而不需要靠近他们。
概观
简而言之,首先,我们获得带有人脸的图像,并将其通过级联分类器。分类器将给出面部的感兴趣区域(高度和宽度)。其次,我们将把感兴趣区域的大小调整为一个100x100
,并将其传递给预先训练好的 CNN,它将把概率作为输出给我们。
步骤 1:数据预处理
我们使用的数据集由不同颜色、不同大小和不同方向的图像组成。因此,我们需要将所有图像转换为灰度,因为我们需要确保颜色不应该成为检测蒙版的临界点。之后,我们需要在将它应用到神经网络之前,使所有的图像都具有相同的大小(100x100
)。
数据预处理
第二步:训练 CNN
这包括 2 个卷积层(两个 Convo2D 100 @ 3x3)。首先,您必须从数据预处理加载数据集。然后你必须配置卷积架构。我已经包括了一个model.add(Dropout(0.5))
来消除过度拟合。由于我们有两个类别(带面具和不带面具),我们可以使用binary_crossentropy
。你从一个模型关卡开始训练 20 个纪元。
训练 CNN
请记住,您可以使用更多的卷积层或使用外部训练器,如 MobileNetV2 以获得更好的准确性。
您可以绘制图表来做出更好的验证决策。我已经把它放在我的知识库里了。请参考。
步骤 3:检测戴面具和不带面具的人脸
首先,您必须加载我们创建的模型。然后我们把想要的相机设置为默认。
可选—您可以将手机摄像头(Android/IOS)连接到 OpenCV。为您的手机和 PC 下载 DroidCam 应用程序。并更改代码
*source = cv2.VideoCapture(1)*
其次,我们需要标注两个概率(0 代表with_mask
,1 代表without_mask
)。之后,我们需要使用 RGB 值设置边框颜色。我给了红色和绿色两种颜色。
在一个无限循环中,我们将从相机中一帧一帧地读取,并将它们转换成灰度并检测人脸。并且它将通过一个for
循环来运行,以针对每张脸检测感兴趣的区域,调整其大小并将其重塑为 4D,因为训练网络期望 4D 输入。对于模型,我们将使用可用的最佳模型来获得结果。这个结果由带面具或不带面具的概率(result=[P1, P2]
)组成。之后会贴上标签。
检测遮罩
让我们看看演示,
演示
[## 面具检测器-谷歌驱动
编辑描述
drive.google.com](https://drive.google.com/open?id=1oLIPBOkCuhej-iNTre_qnlQ3b-fWZeEy) [## ravindu 9701/面罩检测器
在 GitHub 上创建一个帐户,为 ravindu 9701/面罩探测器的开发做出贡献。
github.com](https://github.com/ravindu9701/Face-Mask-Detector.git)
结论
如果使用 MobileNetV2 进行微调,可以提高精确度。我们也可以将这个模型部署到嵌入式系统中。如果我们正确部署它,我们可以帮助确保您和他人的安全。
文章到此为止。希望对某个人有用。谢谢,注意安全!
资源
- 般若的 Github 回购
- 阿德里安·罗斯布鲁克的文章
物体上的实时手指检测器—工作示例
原文:https://towardsdatascience.com/real-time-fingers-detector-over-an-object-a-working-example-73fd1cc84e91?source=collection_archive---------38-----------------------
普里西拉·杜·普里兹在 Unsplash 上的照片
介绍
最近,我有机会构建一个 PoC(概念验证——演示)来解决一个特定的计算机视觉问题,这是一个很酷的体验,为什么不分享一下呢?
演示的目标是实时检测,以摄像机的视频流作为输入,如果特定对象(假身份证)上有手指,覆盖的信息可以在帧完成后用于 OCR 任务。
换句话说,一个可以帮助自动捕获 id 文档的系统确信文档上的所有相关数据都是可见的。
不
不
好的
我们将涵盖的内容
简而言之,这些是我们将涉及的要点:
- 构建一个工作示例(即使不完美)来验证方法的重要性
- 如何使用一个标准框架——CRISP-DM——即使是在一个轻量级的版本中,也可以非常有用地指导项目的所有重要阶段
- 工作码
重要提示:在这个项目的制作过程中没有手指受伤:)
所以让我们开始吧!
构建一个工作示例
创建一个工作模型的目标是验证一种方法,看看第一个结果是否指向正确的方向,或者很快失败并尝试不同的东西。
PoC 是一个工作示例,既可以在开发期间内部使用,也可以向某人展示——猜猜是什么——证明方法的有效性。
但是在开始编码之前,理解问题、可用的数据和所有需要预先知道的东西是必要的。
为了做到这一点,使用结构化的方法会有所帮助,这里 CRISP-DM 开始发挥作用。
使用基于 CRISP-DM 的方法
CRISP-DM(数据挖掘的跨行业标准流程)是一个框架,用于在解决面向数据的问题时拥有一个精确且可重复的步骤和任务列表。
顾名思义,它用于自 1999 年就存在的数据挖掘项目——但也可以用于今天的 ML 项目,因为它们也是高度面向数据的。
在这里,您可以看到迭代过程的主要阶段,从业务问题到生产部署。
Kenneth Jensen —自己的工作基于:FTP://public . dhe . IBM . com/software/analytics/SPSS/documentation/modeler/18.0/en/modelercrispdm . pdf
因此,让我们按照它来描述在 PoC 中做了什么,跳过对演示没有用的步骤,如准备项目计划或评估成本/收益分析。
商业理解
业务需求是自动执行捕获文档的过程,并确保检索到的数据可用于进一步的用途:特别是,包含整个文档的图片,没有任何东西覆盖它的一部分。
由于该过程是使用相机完成的,而卡的所有者将文档放在它的前面,所以目标是确保我们可以用有用的数据来终止捕获会话。
作为一个在短短几天内开发出来的 PoC,引入了约束以保持其简单性:
- 固定捕捉区域,以避免跟踪对象和处理与相机的距离的必要性——我想这一限制也可以用于制作系统。在演示中,一个简单的蓝色方框将指示屏幕上感兴趣的区域
- 在这篇文章中,出于隐私的原因,使用了一个假文件,而不是一个真正的身份证
- 仅考虑了文档的侧面部分——稍后将详细介绍
- 不太关注焦点——使用了基于拉普拉斯方差的简单模糊阈值检查函数,但结果表明它非常依赖于光线条件,因此不能一概而论。作为高级预处理步骤,这一部分专用 ML 解决方案可能更有效
- 只有手指被认为是不需要的物体
- 有限的评估和训练数据集,使用特定的摄像头捕获—仅使用我的笔记本电脑来捕获和评估数据
的成功标准是,基于准确性度量(客观)和实例如何工作(经验)。
数据理解
输入数据是从使用笔记本电脑摄像头创建的视频流中获取的图像。
数据准备
捕获大量几乎相同的帧可能会令人烦恼,因此引入了一个参数来捕获或评估视频流中每 x 帧的一个帧。
作为输入,来自原始帧的两个子集被考虑用于捕获和评估,即左右边界和上下边界,通过选择和组合特定的图像部分来构建。
左+右捕捉
顶部+底部捕捉
没有做进一步的预处理。
除了彩色图像矩阵表示之外,没有添加其他特征。
注意:可能值得研究 hog 表示(基于边缘检测)是如何工作的
建模
显而易见的方法是考虑一个受监督的问题,并为训练建立四个不同的标记数据数据集(ok 上下图像、ko 上下图像、ok 左右图像、ko 左右图像)。
使用了两个简单的 CNNs 因为它是处理图像识别任务的事实上的标准——具有相同的架构但不同的输入形状,一个用于上下图像,一个用于左右图像。回想起来,一个更好的解决方案可以使用一个独特的图像,建立旋转的左帧和右帧,并用自上而下的一个进行组装,因此只能使用一个 CNN。
一旦捕获了足够的标记数据,CNN 就被训练和评估。如果在测试实况会话期间,一个主要的分类错误是明显的,则该图像被添加到正确的类,并且该网络用添加的新数据从头开始再次训练。
估价
该评估基于准确性,使用与训练和测试数据分离的维持(验证)集。
在我的例子中,由于严重的过度拟合,结果非常高——太高了,因为只使用了几百张图像。
除了数值之外,作为一个概念验证,甚至现场观看也是证明它可以工作的必要条件。
这是一个例子。让我们描述一下你所看到的:
- 主区域窗口,带有指示放置卡的位置的蓝色框
- 两个框架窗口—上下和左右图像—带有一个小的彩色框,指示在评估模式下图像是否正常(绿色)或不正常(红色)。这个想法是,如果上下和左右都可以,那么对于连续数量的帧来说,整个帧都可以
让我们看看它的实际表现(https://youtu.be/rzG7LHYfiho
手指探测器在工作
部署
PoC 在笔记本电脑上本地运行,但很容易将分类器想象为一个公开的 API,或者使用 TensorFlow Lite 等在本地部署到特定的目标设备。
这两种方法各有利弊,选择超出了 PoC 的范围,主要是因为需要更多多样化的数据来决定什么是最好的。
代码
该代码由以下文件组成:
- py:它处理视频流。可用于捕获帧,用于训练目的,或使用预测器实例评估帧以进行预测
- py:它包含用于预测的模型
- trainer _ CNN . py:CNN 及相关加载、训练、保存和评估方法
- properties.py:检测器和训练器使用的属性列表
- utils.py:处理缓存图像和处理文件的辅助方法
- 在捕获模式下启动程序
- main_predict.py:以评估模式启动程序
- py:从头开始训练和评估 cnn,并使用文件夹中所有可用的图像
代码可从 GitLab 的这里获得
它是如何工作的
1 —运行main _ capture . pyT5。它将创建必要的目录并启动相机。按“c”启动捕获阶段,将出现两个以上的窗口,显示上下和左右帧的捕获图像,这些图像将保存在 sample_left_right 和 sample_top_bottom 文件夹中。
再次按下“c”停止捕捉。改变位置,再次按“c”开始另一个记录会话。如果捕获了太多模糊图像,请提高 capture _ fuzzy _ threshold 属性值。
记录有效图像(没有手指,只有文档边框可见)和无效图像(手指可见)。完成后按“q”。**
2 —目视评估捕获的图像,并将它们移动到正确的文件夹中(ok_left_right 等)。重复步骤 1 和 2,直到有足够的数据可用
3 —运行main _ train _ CNN . py。它会将训练图像保存在磁盘缓存上以便更快地检索(此处未使用,因为从头开始构建),编译和训练 CNN 模型,使用维持集执行评估,打印结果并将模型保存在磁盘上。
4 —运行main _ predict . py。它将使用上一步中保存的模型创建一个预测器,并启动摄像机。按“e”开始评估。将出现另外两个窗口,显示上下和左右框架的分类结果。一旦达到一定数量的 ok 帧(均为绿色),将显示结果图像
结论
我在开发这个 PoC 的过程中得到了很多乐趣,甚至因为我以前从未使用过 OpenCV,所以我有机会在解决这个问题的同时学到了很多东西。
更一般地说,尝试解决一个真正的问题比只是看教程或看书更有用,所以找到问题,理解它们,然后实施可行的解决方案!
利用机器学习进行实时欺诈检测
原文:https://towardsdatascience.com/real-time-fraud-detection-with-machine-learning-485fa502087e?source=collection_archive---------12-----------------------
内部 AI
随着我们的生活和金融从物理世界转向数字世界,实时欺诈检测将占据中心位置。
Bermix 工作室在 Unsplash 拍摄的照片
与我们的父母和祖父母不同,我们生活和呼吸在数字世界中。最初是在线论坛上的讨论,然后是聊天和电子邮件,现在我们整个生活和金融交易的大部分都是以数字模式进行的。
随着风险越来越高,事后发现欺诈是不够的。想象一下,某人拥有一些关于您的银行或信用卡详细信息的机密信息,能够执行欺诈交易。银行和保险公司需要工具和技术来实时检测欺诈,以便采取适当的措施。
当我们超越三维空间时,我们人类失去了解释和观想的感觉。
如今,金融交易涉及数百个参数,如交易金额、过去的交易趋势、交易的 GPS 位置、交易时间、商户名称等。我们需要考虑许多参数来实时检测异常和欺诈。
Scikit-Learn 中实施的隔离森林算法有助于实时识别欺诈,避免经济损失。在这篇文章中,我将讨论一个带有机器学习的欺诈交易的一步一步的过程。
第一步:我们需要导入将要使用的包。我们将使用“make_blobs”来生成我们的测试数据,并将使用 accuracy_score 来测量拟合模型的准确性。
**from sklearn.datasets import make_blobs
from sklearn.metrics import accuracy_score
from sklearn.ensemble import IsolationForest**
第二步:在现实生活中,我们基于数百万和数十亿的过去交易和数百个参数来建立模型。在本文中,我们将考虑一百个样本和四个特性来理解核心概念和过程。
**X, y = make_blobs(n_samples=[4,96], centers=[[5,3,3,10],[9,3,6,11]], n_features=4, random_state=0, shuffle="True")**
数组 X 保存 100 条记录的四个参数的值,y 存储它是欺诈交易还是正常交易。
步骤 3: 我们将使用集合中的 300 个基本估计量(树)和来自数据集的 10 个样本来训练每个基本估计量。
**clf = IsolationForest(n_estimators=300,max_samples=10,
random_state=0,max_features=4,contamination=0.1).fit(X)**
此外,我们将为模型使用所有四个特征值(“max_feature”参数)。在项目中,通过特征工程,确定每个参数的重要性,并确定模型所基于的特征列表。我不会在本文中讨论特性工程的细节,我会在另一篇文章中讨论它。 IsolationForest 模型进一步拟合样本数据集。
我们基于历史数据中异常的比例和针对错误警报的丢失异常的风险来设置参数“污染”的值。假设历史数据集中欺诈交易的比例为 0.05 %,且这是一个非常高风险的交易。在这种情况下,我们可能希望将污染值设置为 0.25 到 0.35。将污染值设置为历史数据记录中异常比例的 5 到 7 倍将确保没有欺诈交易被错误地分类。事实上,与异常比例相比,设置较高的污染值也会导致错误警报的增加。在风险较低的情况下,我们可能会错过一些欺诈交易,但通过较低的污染值减少错误警报。
步骤 4: 在下面的代码中,fitted IsolationForest 模型预测交易是欺诈还是正常交易。IsolationForest 预测异常为“-1”,正常事务为“1”。在我们的样本测试数据集中,欺诈交易编码为“0”,正常交易编码为“1”。
**y_pred=clf.predict(X)
y_pred[y_pred == -1] = 0**
为了将模型预测准确性与样本数据集中的实际分类进行比较,我们将对预测的欺诈交易进行从“-1”到“0”的分类。
第五步:由于现在欺诈交易在样本和预测集中被标记为“0”,因此我们可以直接用 accuracy_score 函数比较模型的预测精度。
**fraud_accuracy_prediction= round(accuracy_score(y,y_pred),2)
print("The accuracy to detect fraud is {accuracy} %" .format (accuracy=fraud_accuracy_prediction*100))**
该模型似乎以 93%的准确率识别了欺诈交易。乍一看,该模型的预测准确性可能不够好,但请记住,由于风险更高,因此我们可以接受很少的假警报(假阳性)。这些假警报牺牲了预测的准确性,但它比错过一些欺诈交易更安全。
第 6 步:我们将使用混淆矩阵更深入地研究预测。
**from sklearn.metrics import confusion_matrix
print(confusion_matrix(y, y_pred))**
在样本数据集中的总共 100 笔交易中,该模型可以识别所有四笔真实的欺诈交易。
由于模型中污染(安全系数)参数为 0.1,模型将七个真实交易标记为欺诈(假警报)。我们将污染值设置为高于历史数据中欺诈交易的实际比例,因为在风险更高的情况下,安全比遗憾更好。
步骤 7: 我们已经编写了一个小函数来实时检测新交易是否是欺诈。它将新交易馈送的参数值输入到已训练的模型中,以检测交易的真实性。
**def frauddetection(trans):
transaction_type=(clf.predict([trans]))
if transaction_type[0] < 0:
print("Suspect fraud")
else:
print("Normal transaction")
return**
步骤 8: 在新交易时收集各种交易参数。
**frauddetection([7,4,3,8])
frauddetection([10,4,5,11])**
通过调用前面用事务参数定义的函数来确定事务的真实性。
我已经简化了一些事情,如交易中的特征数量,历史交易的数量以适应模型,特征工程等。来解释核心概念。我们已经看到隔离林算法如何帮助实时检测欺诈性交易。
如果您想知道我们如何利用探索性数据分析执行特征工程,请阅读关于探索性数据分析(EDA)的高级可视化的文章。
Python 中的实时头部姿态估计
原文:https://towardsdatascience.com/real-time-head-pose-estimation-in-python-e52db1bc606a?source=collection_archive---------6-----------------------
使用 Python 和 OpenCV 创建一个头部姿态估计器,它可以告诉你头部朝向的角度。
头部姿态估计器
头部姿态估计在计算机视觉中是一个具有挑战性的问题,因为需要各种步骤来解决它。首先,我们需要在帧中定位面部,然后定位各种面部标志。如今,识别人脸似乎是一件微不足道的事情,面对镜头的人脸也是如此。当面部有角度时,问题就出现了。此外,由于头部的运动,一些面部标志不可见。在这之后,我们需要将这些点转换到 3D 坐标来找到倾斜度。听起来工作量很大?不要担心,我们将一步一步来,并提到两个伟大的资源,这将使我们的工作容易得多。
目录
- 要求
- 人脸检测
- 面部标志检测
- 姿态估计
要求
对于这个项目,我们需要 OpenCV 和 Tensorflow,所以让我们安装它们。
#Using pip
pip install opencv-python
pip install tensorflow#Using conda
conda install -c conda-forge opencv
conda install -c conda-forge tensorflow
人脸检测
我们的第一步是在图像中找到面部标志。对于这个任务,我们将使用 OpenCV 的 DNN 模块的 Caffe 模型。如果你想知道它与其他模型如 Haar Cascades 或 Dlib 的正面人脸检测器相比表现如何,或者你想深入了解它,那么你可以参考这篇文章:
[## 人脸检测模型:使用哪一个,为什么?
一个关于用 Python 实现不同人脸检测模型的完整教程,通过比较,找出最好的…
towardsdatascience.com](/face-detection-models-which-to-use-and-why-d263e82c302c)
你可以从我的 GitHub 库下载需要的模型。
import cv2
import numpy as npmodelFile = "models/res10_300x300_ssd_iter_140000.caffemodel"
configFile = "models/deploy.prototxt.txt"
net = cv2.dnn.readNetFromCaffe(configFile, modelFile)img = cv2.imread('test.jpg')
h, w = img.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(img, (300, 300)), 1.0,
(300, 300), (104.0, 117.0, 123.0))
net.setInput(blob)
faces = net.forward()#to draw faces on image
for i in range(faces.shape[2]):
confidence = faces[0, 0, i, 2]
if confidence > 0.5:
box = faces[0, 0, i, 3:7] * np.array([w, h, w, h])
(x, y, x1, y1) = box.astype("int")
cv2.rectangle(img, (x, y), (x1, y1), (0, 0, 255), 2)
使用cv2.dnn.readNetFromCaffe
加载网络,并将模型的层和权重作为参数传递。它在大小调整为 300x300 的图像上表现最佳。
面部标志检测
最常用的一个是 Dlib 的面部标志检测,它给我们 68 个标志,但是,它没有给出很好的准确性。相反,我们将在这个 Github repo 中使用尹提供的面部标志检测器。它还提供了 68 个地标,这是一个在 5 个数据集上训练的 Tensorflow CNN!预先训练好的模型可以在这里找到。作者只写了一系列解释包括背景、数据集、预处理、模型架构、训练和部署的帖子,可以在这里找到。我在这里提供了一个非常简短的摘要,但是我强烈建议您阅读它们。
在第一个系列中,他描述了视频中面部标志的稳定性问题,然后列出了现有的解决方案,如 OpenFace 和 Dlib 的面部标志检测以及可用的数据集。第三篇文章是关于数据预处理和准备使用的。在接下来的两篇文章中,工作是提取人脸并在其上应用面部标志,以使其准备好训练 CNN 并将它们存储为 TFRecord 文件。在第六篇文章中,使用 Tensorflow 训练了一个模型。在本文中,我们可以看到损失函数在训练中有多重要,因为他首先使用了tf.losses.mean_pairwise_squared_error
,该函数在最小化损失时使用点之间的关系作为优化的基础,并且不能很好地概括。相比之下,当使用tf.losses.mean_squared_error
时,它工作得很好。在最后一篇文章中,模型被导出为 API,并展示了如何在 Python 中使用它。
该模型采用大小为 128x128 的正方形盒子,其中包含人脸并返回 68 个人脸标志。下面提供的代码取自这里,它也可以用来绘制 3D 注释框。该代码被修改以在所有的脸上绘制面部标志,而不像原始代码那样只在一张脸上绘制。
这个代码将在人脸上绘制面部标志。
绘制面部标志
使用draw_annotation_box()
,我们也可以绘制如下所示的注释框。
带注释框
姿态估计
这是一篇关于 Learn OpenCV 的很棒的文章,它解释了图像上的头部姿态检测,其中有很多关于将点转换到 3D 空间的数学知识,并使用cv2.solvePnP
来找到旋转和平移向量。快速通读这篇文章将有助于理解其内在的工作原理,因此我在这里只简单地写一下。
我们需要面部的六个点,即鼻尖、下巴、嘴唇的最左和最右点,以及左眼的左角和右眼的右角。我们采用这些面部标志的标准 3D 坐标,并尝试估计鼻尖处的合理和平移向量。现在,为了进行精确的估计,我们需要摄像机的固有参数,如焦距、光学中心和径向失真参数。我们可以估计前两个,并假设最后一个不存在,以使我们的工作更容易。获得所需的向量后,我们可以将这些 3D 点投影到 2D 表面上,这就是我们的图像。
如果我们只使用可用的代码,并找到与 x 轴的角度,我们可以获得如下所示的结果。
结果
它非常适合记录头部上下移动,而不是左右移动。那么如何做到这一点呢?嗯,上面我们已经看到了一个标注框的脸。如果我们能利用它来测量左右运动。
带注释框
我们可以找到两条深蓝色线中间的线作为我们的指针,找到与 y 轴的角度,找到运动的角度。
结果
把两者结合起来,我们就可以得到我们想要的结果。完整的代码也可以在我的 GitHub 库找到,还有在线监督解决方案的各种其他子模型。
在 i5 处理器上测试时,即使显示图像,我也能获得每秒 6.76 帧的健康帧,而面部标志检测模型只需 0.05 秒即可找到它们。
现在我们已经创建了一个头部姿势检测器,你可能想做一个眼睛凝视跟踪器,然后你可以看看这篇文章:
[## 使用 OpenCV 和 Dlib 的实时眼睛跟踪
在本教程中,学习通过 python 中的网络摄像头创建一个实时凝视探测器。
towardsdatascience.com](/real-time-eye-tracking-using-opencv-and-dlib-b504ca724ac6)
使用 YOLOv3 进行实时掩模检测
原文:https://towardsdatascience.com/real-time-mask-detection-with-yolov3-21ae0a1724b4?source=collection_archive---------22-----------------------
来源: cottonbro ,via Pexels
介绍
由于冠状病毒疫情,我们都知道 2020 年的灾难性开始。我们所知的生命已经停止。研究一直表明,基本卫生,如洗手和打喷嚏或咳嗽时捂住口鼻,会大有帮助。在这种场合, 在公共场所戴口罩是必不可少的。
在这篇文章中,我将谈论一个我使用 Darknet 训练的自定义对象检测器,它可以检测你是否戴了面具。Darknet 是一个用 C 和 CUDA 编写的开源神经网络框架,支持 CPU 和 GPU 计算。使用 Darknet,我训练了一个 YOLO(你只能看一次)物体探测器。
简单来说,YOLO 可以一次探测到图像中的所有物体。这篇文章不会讨论 YOLO 的细节。YOLO 的详细情况可以在这里和这里的文件中找到。
先决条件
首先,你需要一个运行 Linux 和 GPU 的系统,最好是。虽然你可以使用 AlexAB 的实现在 Windows 上设置 Darknet,但是我强烈建议你坚持使用 Linux ,因为这个过程要简单得多。好吧,我明白了,你用的是 Windows,你不想经历笔记本电脑双重启动的麻烦。不管你的选择是什么,这篇文章将帮助你的物体探测器启动并运行!除此之外,我将在 Python 3.7 中使用 OpenCV。请随意使用您已经安装的 Python 版本。确保还安装了 numpy 和 argparse python 库。
TLDR;如果你出于任何原因不想经历训练模型的麻烦,我会帮你搞定的!跳到最后一节。
安装暗网
对于 Linux
在 Linux 上安装 Darknet 非常简单。建议看官方指南这里。要开始,请打开您的终端并键入以下内容:
git clone https://github.com/pjreddie/darknet.git
cd darknet
make
如果你有 NVIDIA 支持的 GPU,你应该考虑安装 CUDA,因为它可以大大减少培训时间。这篇帖子让安装过程变得简单,将为您节省大量时间。用 CUDA 和 OpenCV 编译 Darknet,只需打开/darknet/Makefile
,编辑GPU=1
、CUDNN=1
、OPENCV=1
,用make
命令构建软件即可。
对于 Windows
对于 Windows,这个过程稍微复杂一些。首先,克隆 AlexAB 的存储库:
git clone [https://github.com/AlexeyAB/darknet.git](https://github.com/AlexeyAB/darknet.git)
完成后,转到存储库的需求页面:
https://github.com/AlexeyAB/darknet#requirements
在继续之前,确保您已经满足了所有要求,然后进入本节:
https://github . com/AlexeyAB/darknet #如何使用 cmake 在 windows 上编译
选择您想要用来构建软件的方法。我建议使用 CMake 方法(这也是作者推荐的方法),因为使用 vcpkg 可能会令人厌倦。
模特培训
继续克隆我的存储库:
git clone [https://github.com/rushad7/mask-detection.git](https://github.com/rushad7/mask-detection.git)
文件夹结构应该类似于:
.
├── annotations
├── cfg
├── class_names
├── data
│ ├── mask
│ └── no-mask
├── misc
├── results
├── weights
└── yolo
data
文件夹包含mask
和no-mask
文件夹,它们包含戴面具和不带面具的人的图像。annotations
文件夹包含data
文件夹中的所有图像,但带有各自的.txt
注释文件。
将/mask-detection/annotations
文件夹中的图像和.txt
文件复制到/darknet/obj/
文件夹中。如果您希望添加您的训练图像,也将它们添加到上面的文件夹中。为了给图像添加注释,我使用了 LabelImg ,这是一个免费且易于使用的标签工具,支持 Linux、Windows 和 Mac。在使用它的时候,只要确保你是以 YOLO 格式保存文件(可以通过点击保存按钮附近的按钮来设置)。同样,将/mask-detection/cfg/yolov3-custom.cfg
文件复制到/darknet/cfg/
文件夹,将/mask-detection/yolo/voc.data
文件复制到/darknet/cfg/
文件夹。
从终端运行/mask-detection/misc/test_train_split.py
python 脚本(检查脚本的用法),它将在/mask-detector/train_test/
文件夹中生成train.txt
和test.txt
文件。打开/mask-detection/yolo/voc.data
并用上述文件的路径编辑train
和test
变量。
另外,你可能需要修改路径,这取决于你在系统的什么地方使用了 Darknet 和 my repository。如果你使用的是 Windows 系统,你必须将路径改为 Windows ie。C:/Users/...
最后,从这里下载 darknet53 模型的卷积权重,并将其放在您的 darknet 目录中。
现在我们都准备好接受训练了!要开始训练模型,请转到您的 darknet 目录并键入:
./darknet detector train /cfg/voc.data cfg/yolov3-custom.cfg darknet53.conv.74
根据您训练的图像数量以及是在 CPU 还是 GPU 上,训练时间会有所不同。我在英伟达 GTX 1050 上训练了这个数据集,花了我大约 6 个小时。
附:如果你得到一个关于 CUDA 内存不足的错误,试着在yolov3-voc.cfg
文件中改变批量大小。
现在你要做的就是等待训练结束!Darknet 每 100 次迭代保存权重,直到第 1000 次迭代,然后每 10,000 次迭代保存在/darknet/backup/
文件夹中。
测试对象检测器
转到/darknet/backup
并将最后生成的.weights
文件复制到我的存储库中。
对于那些没有训练模型、的、克隆我的 GitHub 库的人,我已经把我训练的权重包含在里面了。
要运行实时屏蔽检测,只需从终端运行yolo-live-cv2.py
脚本,如下所示:
python yolo-live-cv2.py --yolo yolo
瞧啊。,你的 YOLO 面具探测器正在工作!检测器表现相当好,但大约 10 到 15 FPS。我注意到,模型的准确性可以通过增加数据的大小和质量来提高。我在 GitHub 上找到了这个数据集,可能会有帮助。
使用 SHAP、Streamlit 和 Docker 的实时模型可解释性 API
原文:https://towardsdatascience.com/real-time-model-interpretability-api-using-shap-streamlit-and-docker-e664d9797a9a?source=collection_archive---------24-----------------------
自助式 API 实时解释模型分数
礼貌: Pixabay
背景
作为一名数据科学家,您将一个业务问题转化为一个数据科学问题。接下来,您构建解决问题的解决方案/模型。您用测试和超时数据验证模型,以确保它没有偏差。最后,您在生产中部署模型,监控模型的性能,进行实验等等。除了这些任务之外,您还需要向业务涉众展示您的发现,有时还需要与他们一起工作来教育和有效地使用您的模型。你的工作完成了吗?还没有。
您的模型的最终用户可能会思考并提出类似这样的问题——“为什么您的模型预测这个客户是某某人?”或者“你能解释一下为什么我们会从你的模型中得到这个结果吗?”。即使你有一个合适的文档(假设你做了),它也不能解释你的模型预测。考虑一个场景,您构建了一个模型来对猫/狗进行分类。您的文档看起来像这样。
混淆矩阵
交叉熵
当最终用户问你“为什么你的模型预测这张图片是一只猫?”
礼貌: Pixabay
上面提供的文档不能回答这些类型的问题。当您有一个线性模型时,您可以使用参数估计来解释结果。然而,随着模型开始变得复杂(像神经网络这样的黑盒模型),解释结果变得更加困难。在这种情况下,你需要一个黑盒模型来获得更好的结果,但解释这些结果变得更加困难,这是一个讽刺。此外,当你被要求解释一个你过去开发的模型时,你需要一定的时间才能得到答案。SHAP 解决了这个根本的缺点。
你将从这篇文章中学到什么?
- 对模型进行分类以执行实时评分
- 使用 Streamlit 创建一个前端 API 来与您的模型通信并获得预测
- 使用 SHAP 解释模型预测
GitHub 资源库中提供了完整的代码。
* [## sundar 0989/模型-可解释性
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Sundar0989/model-interpretability)
在这个练习中,我使用了银行数据集来构建一个二元分类模型。 jupyter 笔记本将带你完成为 pickle 文件创建对象的步骤。在本练习中,我们在 pickle 文件中存储 4 个对象。
- d —标签编码器对象,用于将分类数据转换为数字数据
- features_selected —分类模型中使用的特征
- clf —随机森林分类模型
- 讲解人 — SHAP 讲解对象
一旦准备好 pickle 文件,就可以继续创建 API 了。
第一步:对你的模型进行分类,进行实时评分
helper.py
这个文件包含执行评分的帮助函数。当您获得原始数据时,需要对其进行处理,并为评分做好准备。这是通过transform _ categorial函数实现的。一旦数据被处理,我们可以使用 score_record 函数对数据进行评分。该函数返回概率和预测,稍后将在前端 API 中显示。
app.py
这个 flask 应用程序用于读取你的模型对象并产生分数。首先我们读取之前创建的 pickle 文件(score _ objects . pkl)并加载模型对象。第二,我们从 Streamlit 前端 API 以 json 格式获取数据。第三,我们使用助手函数来执行预处理并生成分数。最后,我们将分数发回 Streamlit 前端 API。
requirements.txt
该文件包含执行上述操作所需的包的列表。
Dockerfile 文件
这个文件用于为您的模型创建一个 docker,并将整个应用程序容器化。正如您所看到的,它获取了一个基础映像(python:3.7-stretch),并在映像内部创建了一个工作目录( /deploy/ )。我们把前面提到的文件( app.py,requirements.txt,helper.py 和 score_objects.pkl )复制到工作目录下。它在映像内部的 requirements.txt 文件中安装包(第 7 行),并将端口 5000 暴露给外部的 wold。当 flask 被执行时(第 9 行),它将使用这个端口与外部应用程序通信。如果需要使用不同的端口,那么在 app.py 文件中配置端口。
所有这些文件都驻留在一个名为 的目录中。
pythonapi 目录结构
注意:在创建 docker 容器之前,您可以通过单独运行 app.py 文件来测试您的应用程序。这将避免不必要的错误,并有助于代码调试。我推荐使用 Postman API 来完成这个任务。
使用 Postman API 调试应用程序
您需要确保按照步骤来设置 Postman API。
Postman API 应用步骤
启动终端/命令提示符,使用下面显示的命令执行 app.py 文件。
python app.py
应用程序启动后,使用下面的示例验证应用程序是否正确运行,没有任何错误。
您应该会得到如下所示的输出。
完成调试后,您可以进入下一步,创建前端 Streamlit API。
步骤 2:使用 Streamlit 创建一个前端 API
Streamlit 前端 API 位于自己的 docker 容器中。这样,前端应用程序就独立于模型 docker,并且可以随时更改。这是一个很好的行业惯例。streamlit 的目录结构如下所示。
streamlitapi 目录结构
webapp.py
该文件包含创建 Streamlit 应用程序的代码。使用 Streamlit 的最大好处是您可以在工作时交互式地构建前端,并且只需要最少的代码。您需要确保 Python API 端点指向之前创建的 pythonapi 目录。如果您使用了不同的目录名,您需要更改它才能工作。
要调试这个应用程序,您可以使用下面的代码。
streamlit run webapp.py
简化应用编程接口
最终的前端 API 看起来如上。在这个 API 中,您可以在左侧栏中提供输入数据,然后在主页面中获得实时预测和解释。
需求. py
Dockerfile 文件
我们在这个目录中还有score _ objects . pkl文件,也可以访问 SHAP 解释器对象。
现在,我们准备将 shapley 解释值合并到 API 中。
第三步:使用 SHAP 解释模型预测
SHAP 的代码已经包含在 webapp.py 中。下面的代码是摘自 webapp.py 的片段。
解释 _ 模型 _ 预测 函数产生解释结果所需的 shap 值。 st_shap 函数获取 force_plot 对象(p)生成的图形,并使其与 Streamlit API 兼容。最后,我们为每个预测添加了汇总图。
现在,我们已经准备好了各个组件,让我们将它们组合在一起,使我们的应用程序工作。我们将使用 docker-compose 来执行这项任务。代码如下。
这是使这个东西工作的整个目录的结构。
整个目录结构
导航到终端/命令提示符并执行以下命令。
docker-compose 构建
它将构建完整的图像,并在模型和 streamlit docker 之间建立必要的连接。一旦该步骤完成,您就可以执行下面的代码来运行应用程序。
docker-compose up
您将在 URL 中看到应用程序—http://localhost:8501/。要运行应用程序,为每个特性提供一些输入,并点击“获取预测”按钮。您应该得到如下所示的输出。
Streamlit API 输出 1
Streamlit API 输出 2
Streamlit API 输出 3
除了预测和概率,你还会得到一个很好的可解释的图表,解释为什么模型会做出这样的预测。一旦您使用完 API,您可以使用下面的代码关闭。
docker-compose down
就是这样。现在,您拥有了一个具有良好前端的实时模型评分和解释应用程序。您可以根据自己的目的/应用添加/修改/删除图。
玩得开心!*
实时目标检测[PyTorch]||[YOLO]
原文:https://towardsdatascience.com/real-time-object-detection-pytorch-yolo-f7fec35afb64?source=collection_archive---------34-----------------------
Python-PyTorch
用 PyTorch 在 Python 上实现的 YOLO 统一实时目标检测
亚历山大·奈特在 Unsplash 上拍照
计算机能理解它们看到的东西吗?他们能区分狗和猫、男人和女人或者汽车和自行车吗?让我们在这里找到它!
目标检测和识别是当今计算机视觉研究的前沿领域之一。研究人员正在寻找新的方法让计算机理解他们看到的东西。新的最先进的模式正在制定,以大幅度击败他们以前的模式。但是,计算机实际上还远远没有“看到”它们所看到的东西。
在这篇文章中,我将详细介绍 YOLO[你只看一次]——2016 年的一项研究工作,创下了实时对象检测的新高。这篇文章是对 YOLO 模型的简要描述和实现,让你开始进入计算机视觉和物体检测领域。
YOLO:简介
YOLO 将对象检测重新构建为一个单一的回归问题,直接从图像像素到边界框坐标和类别概率。YOLO 使用单个卷积层来同时预测多个边界框和这些框的类别概率。因此,YOLO 的一个主要优点是我们可以用它来检测帧的速度。即使在这样的速度下,YOLO 也设法达到了其他实时系统平均精度(mAP)的两倍多!
Mean Average precision 是每个类的平均精度的平均值。换句话说,平均精度是所有类的平均精度。
平均精度方程
侦查
YOLO 是一个统一的物体检测过程— 统一? YOLO 将涉及物体检测的几项任务统一到一个单一的神经网络中。网络在进行边界框预测时会考虑整个图像。因此,它能够在同一时间预测所有类的所有边界框。
首先,图像被分成一个 S x S 网格。如果网格的中心落在网格单元中,则网格单元应该能够检测到对象。那么,我们所说的检测是什么意思呢?准确地说,网格单元预测 B 边界框,每个框的置信度得分告诉我们模型对该框包含一个对象有多少置信度,以及该框在覆盖该对象方面有多准确。因此,这个框给了我们 5 个预测— x,y,w,h 和置信度得分。网格单元因此给了我们 B 这样的预测。
除了边界框上的预测,网格单元还给出了我们 C 个条件类概率。假定网格单元包含一个对象,这些基本上给出了类的概率。换句话说,假设一个对象存在,条件类概率给我们这个对象可能属于哪个类的概率。每个格网像元仅预测一组类别概率-无论存在多少个边界框
模型功能概述—【https://arxiv.org/abs/1506.02640
网络
该模型受 GoogleNet 图像分类模型的启发。它有 24 个卷积层,后面是 2 个全连接层。与 GoogLeNet 使用的 inception 模块不同,它使用 1 × 1 缩减层,然后是 3 × 3 卷积层。
模型架构概述—【https://arxiv.org/abs/1506.02640
交替的 1 × 1 卷积层减少了来自前面层的特征空间。整个网络以一半的分辨率针对 ImageNet 分类问题进行预训练,然后分辨率加倍用于检测。
丢失和激活
最后一层使用线性激活函数,而所有其他层使用泄漏-ReLU 激活函数。Leaky-ReLU 激活可以表示为:
漏流激活
损失函数是简单的误差平方和,写为—
平方和误差
然而,如果我们像这样定义损失函数,它将把分类和定位误差结合在一起,并且从模型的观点来看,将同等重视这两者。
为了防止这种情况发生,增加边界框坐标预测的损失,并减少不包含对象的框的置信度预测的损失。两个参数λcoord 和λnoobj 用于实现这一点——λcoord 设置为 5,λnoobj 设置为 0.5(参见损失函数方程中关于这些超参数的更多信息)
SSE 还带来了大小包围盒权重误差相等的问题。为了形象化这个问题,请看下面的图片—
狗和碗的图片(仅供参考)——谷歌图片
这里我们可以看到,狗和碗已经被注释为图像中的对象。狗的边框尺寸较大,碗的尺寸较小。现在,如果狗和碗的边界框减少相同的正方形像素,它会觉得碗与框相比具有更差的注释。这是为什么呢?因为在位移和尺寸方面的边界框精度应该与边界框尺寸而不是图像尺寸相比较。
现在,来看我们的损失函数,我们可以看到,损失函数并没有特别注意边界框的大小。它没有考虑到这一点。为了克服这个障碍,网络不预测边界框的高度和宽度,而是预测其平方根。这有助于将差异保持在最小。
考虑到所有这些因素,多部分损失函数可以写成—
网络的总损失函数—https://arxiv.org/abs/1506.02640
既然我们已经完成了 YOLO 物体检测模型的基础,让我们开始研究代码吧!
建造它!
YOLO 网络简单易建。问题在于边界框。绘制边界框和保存图像、编写置信度得分和标签以及配置整个训练代码会使本文变得不必要的长。因此,我将直接实现这个模型。自己承担责任,在这个周末作为一个项目完成代码,并在评论区告诉我结果!我将上传这篇文章的续集,以你的代码和你的结果为特色,并给予满分;)
YOLO 网络模块
这是一个关于 yolov 3(YOLO 的最新即兴版本)结果的短片—
YOLOv3
很兴奋吧。嗯,你应该是因为计算机视觉突飞猛进!现在是开始的时候了。如果你被 YOLO 的实现卡住了,请在评论区告诉我。来帮忙了:)
查看我的博客以获得更快的更新,并订阅优质内容:D
[## 卷积博客
克罗伊斯,吕底亚(小亚细亚)的国王,曾经问特尔斐的神谕,他是否应该对波斯开战…
www.theconvolvedblog.vision](https://www.theconvolvedblog.vision)
Hmrishav Bandyopadhyay 是印度 Jadavpur 大学电子与电信系的二年级学生。他的兴趣在于深度学习、计算机视觉和图像处理。可以在——hmrishavbandyopadhyay@gmail.com 找到他。
利用 YOLO 进行实时目标检测
原文:https://towardsdatascience.com/real-time-object-detection-with-yolo-9dc039a2596b?source=collection_archive---------25-----------------------
这是特斯拉的自动驾驶 Model S。
现在,除了直到最近无人驾驶汽车的想法还闻所未闻这一事实之外,人们不得不怀疑无人驾驶汽车实际上是如何工作的?我的意思是,我们把自己的生命——以及我们的朋友和家人的生命——托付给了一堆金属和电路。不幸的是,答案非常复杂,包括各种组件,如雷达、激光雷达、GPS 定位等。然而,自动驾驶汽车大脑的核心是 YOLO 物体检测。
在我的上一篇文章中,我谈到了卷积神经网络,以及它们如何让计算机对图像中的对象进行分类。然而,要像特斯拉的自动驾驶仪一样工作,汽车不仅需要识别它看到的图像,还需要知道这些物体的确切位置。对于这一点,分类器是不够的——这就是 YOLO 的用武之地。**
超快速、实时的物体检测
澄清一下,YOLO 物体检测并不代表“你只活一次”物体检测(我不想用那个软件上车),而是“你只看一次”物体检测。传统的分类器需要在图像上滑动窗口多次来检测不同的类别,而 YOLO——正如所料——只需要看一次。这是一种非常快速的实时方法,不仅可以识别物体,还可以定位物体,速度高达惊人的每秒 155 帧。
YOLO 物体探测在行动
边框和网格
YOLO 的工作原理是将一个单神经网络应用于完整的图像输入。网络将每个输入图像分成一个 S 乘 S 的网格,每个网格单元预测预定数量的边界框。这些框预测对象的 x 坐标、y 坐标、宽度和高度。这些框还包括一个置信度得分,以确定该对象属于所识别的类别。
YOLO 网格和边界框
交集超过联合模型评估
为了评估模型的性能,YOLO 使用了一种叫做交集超过并集** ( IoU),的东西,计算方法是将预测边界框和地面真实之间的重叠面积除以两者之间的并集面积。IoU 是一种衡量 YOLO 网络在识别物体时准确性的指标,它将网络的输出与手动标记的数据进行比较。**
非最大抑制
最终,每个网格单元最终给我们一个集合数量的边界框,每个边界框都有一个置信度得分和分类。这些边界框中的大多数往往是无用的或不相关的,因此只有那些高于某个置信度阈值的边界框被保留作为 YOLO 网络的最终输出。
YOLO 异议检测的优势
虽然在它之前有许多前辈,但在实时对象检测方面,没有任何计算机视觉算法像 YOLO 一样快速或有效。概括地说,YOLO 是:
1.极快
现在,在这一点上,你可能厌倦了我用 YOLO 真的真的很快这个事实来打击你,但是这一点我怎么强调都不为过。将人工智能应用于现实生活的主要障碍之一是,在大多数情况下,计算机在现实世界中花费的时间太长。我们根本不能让无人驾驶汽车到处游荡,如果每次他们都需要停下来思考几秒钟,不管他们面前是一个孩子还是一个塑料袋!在大多数情况下,计算机视觉总是准确的,但由于其速度,YOLO 允许计算机视觉在现实生活中更加适用和实用。
由卢卡斯·布拉塞克在 Unsplash 上拍摄
2.情境感知
在训练过程中,YOLO 也接受了完整图像的训练,这意味着它不会孤立地看特定的物体。它不仅编码了关于类外观的信息,还编码了关于它的上下文信息。这样,YOLO 网络几乎不会被误认为物体的潜在背景噪音所困扰。该网络知道汽车经常被其他汽车和路面包围——所以影子看起来有点像森林中的汽车?很可能不是车。
3.广义网络
最后,由于其架构和训练方式,YOLO 是一个高度通用的网络。YOLO 不仅学习如何识别孤立的物体,还学习它们的广义表示。当应用于意想不到的输入和不熟悉的情况时,它发生故障或失败的可能性要小得多——如果我必须说的话,这是无人驾驶汽车非常希望拥有的。
实时 Reddit VADER 情绪分析,用于“世界新闻”子编辑中的术语跟踪!
原文:https://towardsdatascience.com/real-time-reddit-vader-sentiment-analysis-for-term-tracking-in-worldnews-subreddit-bbd366d477c0?source=collection_archive---------40-----------------------
使用流式 Reddit API 和 Python 中的 PRAW、POSTGRESQL 和 Dash 收集 Reddit 数据。
在这个简短的教程中,我们将学习如何使用 Python 中的 Reddit API 从 Reddit 中提取实时 7 流数据,并应用情感分析。Reddit 拥有庞大的用户群(近 4.5 亿),其中最活跃的子编辑之一是“ worldnews ”。(近 2500 万用户)。能知道这个大平台上的人都在说什么,挺好的。
http://sentiment-reddit.herokuapp.com/
你可以在你的电脑上试试这个 代码 。
第一步:
第一件事就是在你的 Reddit 账户上设置一个应用程序。Felippe Rodrigues 有一个很好的教程教你如何去做。一旦掌握了以下信息,就可以直接转向 python 了。
reddit = praw.Reddit(client_id='PERSONAL_USE_SCRIPT_14_CHARS', \
client_secret='SECRET_KEY_27_CHARS ', \
user_agent='YOUR_APP_NAME', \
username='YOUR_REDDIT_USER_NAME', \
password='YOUR_REDDIT_LOGIN_PASSWORD')
第二步:
如果你想在本地电脑上运行这个应用,你不需要这一步。是时候建立一个数据库帐户了。自从 Heroku 对 PostgreSQL 有了很大的支持,我就开始用 PostgreSQL 了。在 Heroku 上创建一个应用程序,并设置数据库。格雷戈里在这方面有很好的指导。一旦你有了凭证,你就可以填写app.py
和reddit_stream.py
。
conn = psycopg2.connect(host = *****.compute-1.amazonaws.com, database = *********, password = ********)
第三步:
安装requirements.txt
中的所有要求
在app.py
和reddit_stream.py
中填入conn
和reddit
的值。在您的本地计算机上,在命令提示符下运行 Reddit 流应用程序,只需使用
python reddit_stream.py
上面的脚本从 Reddit 流直播线程,该线程的评论和回复,并使用 VADER 情绪分析器提供情绪得分。我们使用复合情感评分来存储和显示。
当脚本运行且数据库填满时,让我们现在显示我们的应用程序。为此,只需在服务器上运行应用程序。对此代码使用另一个命令提示符。
python app.py runserver
在应用程序中进行修改,以显示您想要的图表。Dash 有一些漂亮的图表、制作精良的文档和一个不错的社区来帮助你。
结论
我们从 Reddit 上搜集数据,对文本进行 VADER 情感分析。我们使用 PostgreSQL 保存数据,使用 Dash 应用程序显示和部署我们的应用程序。如果你认为你可以做得更好,请给它一个机会。
资源:
[## 实时 Reddit 监视器
编辑描述
sentiment-reddit.herokuapp.com](http://sentiment-reddit.herokuapp.com/) [## zero panda/Reddit-情绪
第一个命令 pmt 类型- python Reddit_Stream.py 第二个命令 pmt 类型-python app . py runserver Live-streaming 情操…
github.co](https://github.com/ZeroPanda/Reddit-Sentiment)
使用 TensorFlow.js 在浏览器中进行实时语义切分
原文:https://towardsdatascience.com/real-time-semantic-segmentation-in-the-browser-using-tensorflow-js-e2e00a185139?source=collection_archive---------30-----------------------
直接从浏览器执行语义分段。不需要复杂的库或强大的计算机。
语义分割是检测和描绘图像中出现的每个感兴趣对象的问题。目前,有几种方法可以解决这个问题并产生如下结果。
图 1:语义分割示例(来源
这种分割是预测图像中的每个像素,也称为密集预测。需要注意的是,同一个类的实例没有被分开,模型只关心像素的类别。如图 1,方法可以说某些位置有椅子,但不能区分。
这项技术的主要应用之一是在自动驾驶汽车中,汽车需要了解他们的环境。语义分割能够为场景赋予一种意义,并将汽车置于上下文中,指示车道位置,如果有一些障碍物,如倒下的树木或行人穿过道路,并识别其他汽车。
视频 1:自动驾驶的语义分段示例
因此,在城市街道场景中应用语义分割算法是当今计算机视觉的主要挑战之一。评估模型性能的一个流行数据集是城市景观。它包括来自 50 个不同城市的 30 个班级,根据季节和天气情况而变化。
图 2 显示了随着时间的推移,不同的算法如何在这个数据集中达到最先进的水平。
图 Cityscapes 数据集上的语义分割(来源)
在这个项目中,使用了一个中级模型,它可以提供合理的精度并实时运行。RefineNet [2]于 2016 年底首次从阿德莱德大学的研究中推出,并于 2018 年转换为轻量级模型[3],允许实时推理。
TensorFlow.js
TensorFlow 是一个开源库,广泛用于创建机器学习模型,主要在 python 项目中。Tensorflow.js 的出现使得同样的模型开发、训练和测试可以在浏览器中进行。
ML 在浏览器中运行意味着从用户的角度来看,不需要安装任何库或驱动程序。只要打开一个网页,程序就可以运行了。此外,它可以运行 GPU 加速。TensorFlow.js 自动支持 WebGL,在有 GPU 可用的情况下会在后台加速代码。用户也可以从移动设备打开你的网页,在这种情况下,你的模型可以利用传感器数据,比如来自陀螺仪或加速度计的数据。最后,所有数据都保留在客户端,这使得 TensorFlow.js 对于低延迟推理以及隐私保护应用程序非常有用[4]。
权重文件
TensorFlow.js layers 格式是一个目录,包含一个model.json
文件和一组二进制格式的分片权重文件。model.json
文件包含了模型拓扑(又名“架构”或“图形”:层的描述以及它们是如何连接的)和权重文件的清单[5]。
JSON 权重在轻量级 RefineNet 存储库中提供[6],但是也可以将 PyTorch 或 Keras 模型转换为 TensorFlow.js 格式[7]。
服务 TensorFlow.js 模型
Tensorflow.js 模型必须通过一个 URL 提供服务,并以 javascript 加载。如前所述,该模型基于一个主 JSON 文件和二进制格式的分片权重文件。想法是创建一个 HTTP 服务器,它将使模型在一个允许请求的 URL 中可用,并作为 REST API 被线程化。加载模型时,TensorFlow.js 将执行以下请求:
可以使用以下命令安装 http-server :
npm-install http-server -g
一旦安装了程序,您就可以进入您的 weights 文件夹并运行以下命令来服务您的模型:
http-server -c1 --cors .
然后,下面这段代码将加载 tensorflow.js 模型。
做预测
一旦模型加载完毕,进行预测的过程就相当简单了。你必须加载一个框架,并使用model.predict(frame)
命令从模型中获得预测。返回的是一个 PASCAL VOC 格式的帧,必须进行转换和渲染,可以在项目库中找到代码。
我决定创建一个简单的应用程序,从网络摄像头读取一帧,并生成语义分段,如下例所示:
图 3:细化网络——语义分割示例
为了在现实场景中测试该项目,我在手机上下载了一些图片来填充算法,下面的视频显示了应用程序在浏览器中实时运行:
视频 2:浏览器中的实时语义分割
该应用程序有一个小的延迟,主要是由于帧重建时间,但总体结果相当不错。TensorFlow.js 开启了许多可能性,允许需要强大计算机和复杂库的机器学习模型可以在浏览器中平稳运行,并使用少量计算资源。
运行项目的所有源代码和指令都可以在 GitHub 找到。如果您有任何问题或建议,可以通过 Linkedin 联系我。
感谢阅读:)
参考
[1] Romera-Paredes,Bernardino 和 Philip Hilaire Sean Torr。"循环实例分段."欧洲计算机视觉会议。施普林格,查姆,2016。
[2]林,,等.“Refinenet:面向高分辨率语义切分的多路径精化网络”IEEE 计算机视觉和模式识别会议论文集。2017.
[3]涅克拉索夫、弗拉迪米尔、沈春华和伊恩·里德。“轻量级 refinenet 用于实时语义分割。” arXiv 预印本 arXiv:1810.03272 (2018)。
[4]中等。2020.介绍 Tensorflow。js:Javascript 中的机器学习。【在线】可在:<https://medium . com/tensor flow/introducing-tensor flow-js-machine-learning-in-JavaScript-BF 3 eab 376 db>【2020 年 6 月 3 日访问】。
[5]https://www . tensor flow . org/js/tutorials/conversion/import _ keras
https://github.com/DrSleep/light-weight-refinenet
https://www.tensorflow.org/js/guide/conversion
通过电子推板进行实时情绪分析和可视化
原文:https://towardsdatascience.com/real-time-sentiment-analytics-and-visualization-via-electiontweetboard-43ff96d358d6?source=collection_archive---------29-----------------------
通过推特情感分析分析 2020 年总统选举
这篇文章将通过深入研究我最近开发的一个名为 election tweet board(https://www.electiontweetboard.com/)的产品,来探索数据分析、可视化以及机器学习的各种形式和考虑因素。
电子推特背后的“为什么”
每一个数据科学或者 AI 相关的项目,背后都需要强大的驱动力。出于真正的好奇心,我开发了 ElectionTweetBoard,以了解更多关于公众对即将到来的总统选举中的顶级候选人的看法,以及这些看法与媒体对候选人的报道有多相关。
由于 Twitter 是收集实时用户生成数据的一个非常好的来源,我决定设计一个自动化的工作流程来获取推文,然后分析这些推文的情绪。从这个最初的起点,该产品已经发展到还包括一个“快速链接”部分,自动策划最相关的文章对每个候选人。
经由候选卡的情感分布数据可视化
该网站仪表板的第一个突出的主要组件是个人候选人卡片,这些卡片总结了从当前一组推文中提取的当前情绪分布。绿色、蓝色和红色圆圈分别代表阳性、中性和阴性的百分比。
这里主要考虑的是让代表每一类情感的颜色有清晰的含义。绿色和红色是显而易见的选择,因为它们出现在成功和错误消息中,以及像交通灯这样的常见设备中。另一方面,浅蓝色是一种中性色,整体饱和度较低。我试图在整个应用程序中保持这种配色方案。
每个候选卡还有两个按钮,链接到两个独立的弹出模式。Tweets Info 模式旨在以定性和定量的方式显示正在进行的 tweet 情感分析的结果,而 Quick Links 模式为每个候选人挑选最相关的链接。下面让我们更深入地探讨这两个组件:
推特模式
Tweets 模式由三个部分组成,每个部分侧重于显示特定类别的数据:
- 样本推文
- 感情随时间推移
- 地理情感
通过样本推文进行定性数据分析
Tweets 模式的 Sample Tweets 选项卡显示了每个候选人最新的正面和负面 Tweets 的示例。这样做的目的是让用户更好地了解人们在特定时间点对特定候选人的评价。
通过随时间推移的情感的时间序列数据可视化
现在,示例 Tweets 选项卡侧重于提供最相关的实时定性数据,而随着时间推移的情绪选项卡深入显示不同时间段不同类别的情绪趋势。这种分析通常被称为时间序列分析。
通过将前面提到的通过样本推文进行的定性数据分析与上面的时间序列情绪分析相结合,人们可以开始更好地了解某些事件/决策如何与公众情绪相关联。
基于地理情感的地理数据可视化
Tweets 模型的第三个也是最后一个部分——按地理划分的情感,重点是提供基于州的情感分析。目前,颜色编码是基于每个给定州的推文中表达的积极或中性情绪的百分比。
进一步探索的起点
ElectionTweetBoard 背后的主要目的是通过公众情绪的视角增加对选举最新发展的实时了解,然而,它也是通过其快速链接部分进行进一步探索的宝贵起点。
Quicks Links 是一个实时新闻聚合器,它根据公众的意见提醒用户最新和最相关的新闻文章、视频和照片。
根据各种指标进行排序
ElectionTweetBoard 还提供了一个易于访问的下拉列表,可以根据各种指标对候选人进行排序。目前,候选卡可以根据积极、中立和消极情绪进行分类,使用户能够挑选他们希望重点分析的特定顺序。这也是一种有效的方式,为用户第一次进入网站时看到的默认的、开箱即用的排序提供替代。
结论
随着预选会议即将开始,竞选活动日益升温,现在是查看 https://www.electiontweetboard.com/选举推板的好时机。它将帮助您了解最新发生的事情,并通过上面强调的数据科学和机器学习功能进一步分析这些事情!
相关链接
链接到选举推板:【https://www.electiontweetboard.com/
基于实时模拟的分析服务
原文:https://towardsdatascience.com/real-time-simulation-based-analytics-services-3b1f722ebd14?source=collection_archive---------24-----------------------
在 AWS 上使用 SimPy 进行概念验证,英尺。Terraform 和本地堆栈
沃尔夫冈·哈塞尔曼的照片
在他最近发表的非常有趣的博士论文(德语)中,来自埃尔兰根-纽伦堡大学的 Toni Donhauser 给出了一个很好的例子,说明了生产同步数字双胞胎如何用于砖石工厂的自动化、基于模拟的订单调度。作为一项核心功能,开发的模拟允许初始化制造系统的在制品,以精确反映当前状态并创建准确的短期预测,作为在意外中断情况下比较替代方案和优化生产计划的基础。 Tecnomatix Plant Simulation(西门子)用于仿真模型的实现。
由于 Plant Simulation 以广泛的功能和广泛的许可费用而闻名,这篇博客文章将介绍这种生产同步数字双胞胎的替代实现,基于开源框架并建立在易于操作、按使用付费的 AWS 基础设施上。可以使用 Docker 、 Terraform 和 LocalStack 在本地部署和测试完整的设置(不需要 AWS 帐户)。
从 github 获取回购:https://github . com/fladdimir/CsA-simulation-based-sc-forecast
场景和范围
下图显示了一个虚构的简化订单处理流程,并将作为一个最小的示例来说明如何实现系统的数字孪生。
简单的订单处理流程
创建后,公司接收并接受订单(摄取-步骤),订购订单特定的原材料(订单 _ 材料),让订单等待,直到相应的材料到达(等待 _ 材料)。物料交付后,订单进入缓冲队列( wait_for_sop ),等待在产能受限的生产步骤中处理,该步骤一次只能处理一个订单。最终,完成的订单被交付给客户并离开系统。
每当请求订单的物料时,会分配一个初始预计到达时间(ETA)。然而,意外的供应商特定流程偏差或其他交付问题可能会在任何时间点引入延迟,因此在订单等待材料交付时,ETA 更新是可能的。由于生产步骤使用受能力限制的资源,并代表系统的一个可能的瓶颈,这里任何计划外的利用不足都可能延迟每个即将到来的订单,并减少系统吞吐量(取决于时间表看起来有多紧)。因此,一旦订单的任何 ETA 更新发生,就希望能够量化任何时间偏移的影响。
同步数字孪生:概念和实现
下图显示了一个简单的事件处理管道,能够接收定义的事件并保持系统状态(事件跟踪),这反过来又能够基于模拟创建对预期订单完成时间和延迟的预测(事件分析)。一个简单的网络仪表板将用于可视化的结果。
基于模拟的预测创建的处理流程(图标由 AWS 提供)
1.数据生产者的发布事件
在生产系统中处理订单的过程中,数据生产者发布进度信息,例如订单处理步骤的开始或结束。虽然这些事件实际上会在物理制造系统中发生,但在开发过程中可能会使用模拟模型来创建数字双胞胎的测试数据(参见虚拟调试 上的这篇帖子,了解物流模拟用例的另一个示例)。
2.使用 AWS Kinesis 捕获事件
Kinesis 是一个 AWS 服务,用于连续缓冲和实时处理流数据。Kinesis 流分离了数据生产者和消费者,由可配置数量的碎片组成,每个碎片每秒能够摄取高达 1 MB 或 1000 条记录的数据。每个记录根据其指定的分区键值放入一个碎片中,这变得很重要,因为记录的有序处理只在分区键级别上得到保证。
在所描述的场景中,有序处理对于订单的 ETA 更新变得至关重要,因为预期延迟的消息不能在任何更早提交的更新之前处理。
3.用 AWS Lambda 处理事件
Lambda 是 AWS 提供的功能即服务,允许按需运行代码,为调用次数和执行时间付费。Lambda 函数可以很容易地与其他服务耦合,比如 SQS 和 DynamoDB。由于 AWS 按需提供函数运行时,NodeJS 和 Python 的短冷启动时间使它们成为实现 lambdas 的流行选择。
为处理订单更新而实现的 lambda 很简单,只需用调用中提供的事件数据更新指定 DynamoDB 表中受影响订单的相应项目。
4.用 DynamoDB 保持系统状态
DynamoDB 用作快速、灵活和可管理的 NoSQL 数据库。虽然这种类型的数据库在设计上缺乏关系数据库的一些便利性(例如在数据库级别上实施引用完整性的适当方法,或者复杂 ORM 和模式管理工具的可用性),但它对于我们只涉及更新单个项目和基本查询的简单用例来说是很好的。DynamoDB 需要一个分区键和一个可选的范围键,两者结合使用可以唯一地标识一个存储项。对于订单,字符串 id 可用作分区键。DynamoDB 的一个很好的特性是启用流,自动提供表更新信息。这样,订单 ETA 更新可以触发新的预测。
5.模拟未来
AWS 允许使用 Lambda 函数作为 DynamoDB 流事件消费者,因此模拟运行可以预测每个状态变化的未来订单完成时间。对于每次运行,从 DynamoDB 中获取当前系统状态(这实际上可能需要多次请求,因为单次扫描只能返回一页最多 1 MB 的数据)。
基于注册的过程时间戳,可以识别每个订单的当前相关过程步骤。
使用 Casymda 从上图所示的流程图生成仿真模型。为了概念证明的简单性,处理时间被假定为确定性的。实施模型块是为了说明在制品实体在模拟开始时已经经过的处理时间(初始化在线模拟模型的可能性之一,在 Hanisch 和 Tolujew,2005 的经常引用的论文中讨论,并由 Hotz,2007 进一步探讨)。在执行过程中,以预测流程步骤完成时间的形式收集预测指标。
目前,AWS 允许 Lambda 函数的执行时间长达 15 分钟,因此即使复杂的模型也可以这样运行。然而,频繁且长时间运行的计算可能会使创建专用服务更有吸引力。
6.+ 7.预测持久性和可视化
在每次运行结束时,收集的结果被保存在第二个 DynamoDB 表中,仪表板应用程序可以从这个表中访问和可视化数据。
Plotly Dash 是一个流行的网络应用分析框架。只需编写 Python 代码,就可以快速创建动态仪表板。在引擎盖下,它使用烧瓶将带有图表的网站反应给浏览器。使用 Python 在后端完成数据查询和分析。实现的仪表板只包含一个简单的甘特图。使用 interval -callback 循环轮询数据库更新来实现自动仪表板刷新。dashboard 的 Docker 容器可以在 AWS 上运行(例如 ECS/Fargate,但是由于 LocalStack 的免费版本不包括这一点,所以它只是在本地运行以供演示)。
结果
要从克隆的存储库中本地运行设置,需要安装 Docker 和 Terraform。
尽管性能无法与实际的云服务相提并论, LocalStack 是在本地模拟众多 AWS 服务的绝佳选择,包括 Kinesis、Lambda 和 DynamoDB。LocalStack 可以在 Docker 容器中启动,根据需要生成更多的容器,例如用于执行 Lambdas:
docker-compose up localstack
在部署 Lambda 函数之前,需要打包函数代码及其依赖项:
docker-compose up package-ingest-lambda package-simulation-lambda
Terraform 是一个伟大而广泛使用的工具,它可以自动提供配置文件中描述的基础设施资源(但是,请看一下这篇文章中更细致的分析)。要创建所有需要的资源,需要在相应的目录中使用两个 terraform 命令:
cd terraform
terraform init # (only required once)
terraform apply
# (enter 'yes' when prompted to confirm the changes,
# or use -auto-approve)
cd ../ # return to project root
(为了防止在没有调用terraform destroy
的情况下重启 LocalStack 后调用apply
时出现 404 错误,首先删除main.tf
旁边的terraform.tfstate
文件。)
成功创建后,可以启动另外两个容器,一个服务于仪表板,另一个运行模拟模型来模拟真实的事件生成器:
docker-compose up dashboard emulation
在(重新)开始任何试运行之前,需要清除 DynamoDB 表:
docker-compose up truncate-tables
http://localhost:8050 现在应该显示空的仪表板,而 http://localhost:5001 应该显示 Casymda web canvas 动画控件。
样品流
开始模拟时,订单将在源位置创建,并流经定义的流程。同时,仪表板应稍有延迟地更新,并显示系统(y 轴)中当前所有订单的相关流程步骤的完成时间(x 轴)。图表中的垂直线表示模拟运行开始和预测创建的时间点。
仿真模型和预测仪表板的截屏
当订单-2 的预期未来物料交付延迟发生时,会产生一个有趣的情况(橙色):
订单 2 的预期物料交付延迟(橙色)对订单 3 的预测影响(红色)
由生产步骤的能力限制引起(最大。一个订单并发)订单-2 的延迟(橙色)预计也会延迟订单-3 的开始生产(红色)。
虽然给出的例子很简单,但是可以想象出很多扩展。从商业角度来看,研究一个更复杂的过程是很有意思的,例如包括原材料库存和不同的补充策略。类似地,可以评估随机或计划的机器维护间隔的影响。这可能还要求自动确定最佳决策备选方案,例如考虑订单特定的到期日或吞吐量目标。有趣的技术扩展可能包括对摄取的事件数据进行初步分析,使用流处理解决方案,如 AWS Kinesis 数据分析,以便识别相关模式并仅在关键流程偏差的情况下触发预测/优化运行。
使用 SpaCy、Kafka 和 Seldon 核心的大规模实时机器学习
原文:https://towardsdatascience.com/real-time-stream-processing-for-machine-learning-at-scale-with-spacy-kafka-seldon-core-6360f2fedbe?source=collection_archive---------14-----------------------
这是一个实践教程,讲述了如何使用 Reddit 评论审核数据集训练机器学习模型,并使用 Kafka 和 Seldon Core 将其部署在可扩展的基础架构中
使用 Seldon Core 进行流处理的模型部署(图片由作者提供)
在本帖中,我们将介绍如何为自动文本预测用例训练和部署利用可扩展流处理架构的机器学习模型。我们将使用 Sklearn 和 SpaCy 从 Reddit 内容审核数据集训练一个 ML 模型,我们将使用 Seldon Core 部署该模型,以实时处理来自 Kafka 实时流的文本数据。你还可以在这篇文章中找到视频形式的内容概述,在 NLP Summit 2020 上展示。
实时机器学习视频(NLP 峰会 2020)
您可以在以下链接中找到本文的完整代码:
- 谢顿模型集装箱化笔记本
- Reddit 数据集探索性数据分析笔记本
- 卡夫卡谢顿核心流处理部署笔记本
使用 SpaCy & Sklearn 进行模型训练
对于这个用例,我们将使用 Reddit /r/science 内容审核数据集。这个数据集由超过 200,000 条 reddit 评论组成,主要根据评论是否被版主删除来标记。我们的任务是训练一个 ML 模型,它能够预测 reddit 版主已经删除的评论。
SpaCy 是用于生产文本处理用例的最受欢迎和最活跃的 NLP 库之一,它提供了“工业级”功能,包括标记化、NER、深度学习集成以及跨广泛语言模型的更多功能。同样,Sklearn 是 Python 中最流行的机器学习工具包。我们将使用这两个框架进行探索性数据(和模型)分析,以及训练我们的机器学习模型。
探索性数据分析笔记本(图片由作者提供)
当涉及到构建机器学习模型时——特别是当它被部署到生产系统时——使用原则和最佳实践来确保其负责任的设计、开发和运营是很重要的。
算法对比图(图片由作者提供)
您将能够在模型培训笔记本中找到探索性数据分析的最佳实践和技术。这些包括特征工程、数据分布、数据不平衡、数据清理、算法性能比较、标记化方法、部分依赖图等。
这些技术使数据科学家和工程师能够为机器学习模型的培训、部署甚至生产监控确定特定领域的最佳实践。
基本 NLP 管道(图片由作者提供)
在本教程中,我们将使用 Sklearn 和 SpaCy 构建机器学习管道。如上图所示,我们在管道中使用了以下组件:
CleanTextTransformer
—通过删除相关字符、符号和重复短语来清除输入文本SpacyTokenTransformer
—使用 SpaCy 将输入文本转换为标记,并删除相关标记,如停用词TfidfVectorizer
—将令牌转换为模型可以处理的向量LogisticRegression
—在我们当前数据集上训练的逻辑回归模型
模型推理阶段(图片由作者提供)
为了更直观地了解我们的模型将如何处理数据,上图显示了文本数据输入实例在每个阶段是如何转换的。更具体地说,如果我们接收到一个短语,它将通过每个管道组件发送,直到我们能够接收到一个预测。
一旦我们训练了我们的模型,我们将能够使用用于管道的相同代码,并且我们将导出使用pickle
训练的模型的工件,这样我们可以在部署模型时加载它们。
具有谢顿核心的集装箱化模型
Seldon Core 可用于将我们的模型转换为可扩展的微服务,并使用 Seldon cloud 原生 kubernetes 操作员将其部署到 Kubernetes。使用 Seldon Core 部署的模型支持 REST 和 GRPC 接口,但从 1.3 版本开始,它还支持原生 kafka 接口,我们将在本文中使用。
采用塞尔顿核心的模型部署(图片由作者提供)
Seldon 提供了几种生产机器学习模型的方法。最常见的方法是使用现有的 预打包模型服务器 s 中的一个。然而,在这种情况下,我们将通过扩展默认的 sklearn 预打包服务器 来添加 SpaCy 及其各自的英语语言模型,从而构建我们自己的 定制模型服务器 。
为了用 Seldon 封装我们的模型,我们将使用 Python 语言包装器 遵循标准的 Seldon 核心工作流程。如下图所示,将模型装箱所需的标准步骤如下:
- 创建一个 Python 包装类来公开模型逻辑
- 通过
requirements.txt
文件添加 Python 依赖关系 - 添加协议、日志级别等环境参数
- 可选地添加任何带有 Dockerfile 扩展名的进一步依赖关系
集装箱模型所需的标准步骤(图片由作者提供)
在我们的例子中,我们只需要定义一个 Python 包装器,它由以下部分组成:
- 导入本文培训部分使用的 ML 管道的代码
- 一个加载模型工件的
__init__
方法 - 每次发送请求时被调用的
predict
方法
包装器的代码可以在下图中找到,或者你可以找到完整的 Jupyter 笔记本来训练、装箱和测试谢顿包装模型。
一旦有了包装器,我们就能够使用s2i
CLI 简单地运行 Seldon 实用程序,即:
s2i build . seldonio/seldon-core-s2i-python3:1.3.0 nlp-model:0.1
现在我们已经将我们的模型完全容器化为 image nlp-model:0.1
,我们将能够在下一节中为流处理部署它。
Kafka 流处理
谢顿模型支持 REST、GRPC 和 Kafka 协议——在本例中,我们将使用后者来支持流处理。
Kafka ML 处理架构(图片由作者提供)
您可以在示例中找到完整的 jupyter 笔记本,其中包括部署文件以及请求工作流。
我们有以下组件:
- Kubernetes 集群 —我们所有组件将部署到的 Kubernetes 集群
- Reddit 源 —以 Reddit 评论流的形式产生输入数据的组件
- Kafka 队列—Kafka 集群组件,将处理消费者和生产者提供的数据流
- Seldon ML 服务 —我们使用 Seldon 部署的容器化 reddit 分类器模型
- 卡夫卡
- 卡夫卡
**model_output**
主题 —其他应用程序可以从中消费的输出主题 - 其他应用程序 —在我们的例子中,这是一个单一用户应用程序,但是这可以包括任何其他想要使用
model_output
主题的应用程序
为了简单起见,我们将跳过设置 kubernetes 集群所需的步骤——包括设置 Kafka 代理和安装 Seldon Core——但是您可以在笔记本示例中找到完整的说明。
现在我们可以部署我们的模型了。为此,我们只需按照 SeldonDeployment 模式定义我们的部署配置文件:
SeldonDeployment Kafka 配置文件(图片由作者提供)
正如您在配置 YAML 中看到的,该结构包含以下要点:
- 型号名称
name: reddit-kafka
graph.name: classifier
是我们将部署的型号serverType: kafka
使用 kafka 接口启用部署的微服务(与 REST 或 GRPC 协议相反)KAFKA_BROKER
卡夫卡经纪人的服务器KAFKA_INPUT_TOPIC
输入消费主题的名称KAFKA_OUTPUT_TOPIC
要生成的输出主题的名称
我们现在可以使用 kubectl 命令创建模型:
kubectl apply -f sdep_reddit_kafka.yaml
一旦我们的模型被创建,我们现在可以将数据发送到输入主题中。我们可以通过使用kafka-console-producer.sh
实用程序来实现。
类似地,我们也可以监听模型产生的输出数据。
现在,当我们将输入数据发送到输入主题时:
{”data”: {”ndarray”: [”This is an input”]}}
因此,我们会在输出主题流中看到预测:
{“data”:{“names”:[“t:0”,”t:1"],”ndarray”: [[0.6758450844706712, 0.32415491552932885]]},”meta”:{}}
这样,我们现在有了一个部署在可扩展架构中的模型,用于实时机器学习处理——更具体地说,该架构允许每个相应组件的水平和垂直可扩展性。部署的模型可以扩展到可变数量的副本,以及基于 Kubernetes HPA 的自动扩展,后者可以根据资源使用情况进行水平扩展。类似地,Kafka 还可以通过代理的数量进行水平扩展,从而实现低延迟的大吞吐量。这可以在下图中更直观地看到。
缩放副本和代理(图片由作者提供)
下一步是什么?
现在,您已经对核心架构组件有了直觉和理解,您现在能够深入研究实际的细节了。为此,您可以通过以下链接访问代码和资源:
- 谢顿模型集装箱化笔记本
- Reddit 数据集探索性数据分析笔记本
- 卡夫卡谢顿核心流处理部署笔记本
如果您有兴趣进一步了解机器学习模型的可扩展部署策略示例,您可以查看:
- 利用 Argo 工作流程进行批处理
- 无服务器事件与 Knative
- AI 用不在场证明解释模式
实时时间序列异常检测
原文:https://towardsdatascience.com/real-time-time-series-anomaly-detection-981cf1e1ca13?source=collection_archive---------3-----------------------
入门
开发一个基于多个时间序列传感器的监控系统
在 Unsplash 上可爱的镜头拍摄的照片
尽管多年来从不同来源收集大量数据变得越来越容易,但公司需要确保他们收集的数据能够带来价值。为了帮助从数据中收集洞察力,机器学习和分析已经成为趋势工具。由于这些领域需要实时洞察,大量不受欢迎的数据可能会产生真正的问题。
在做出决定之前,关键的是,在采取行动之前,我们必须问:我们的数据中是否存在异常,可能会扭曲算法分析的结果?如果异常确实存在,我们自动检测并减轻它们的影响是至关重要的。这可以确保我们在采取行动之前获得最准确的结果。
在本帖中,我们将探索不同的异常检测方法,这些方法可以在大数据源上实时扩展。这个 tsmoothie 包可以帮助我们完成这个任务。 Tsmoothie 是一个用于时间序列平滑和离群点检测的 python 库,能够以矢量化的方式处理多个序列。它很有用,因为它可以提供我们需要的技术来监控传感器。
异常的类型
首先,让我们定义异常。它们可以是任何不同的或异常的,并且与样本中的其他数据或历史数据有很大偏差的数据。
异常通常分为点状异常和状异常。点异常是异常的单个实例,而模式异常代表异常的数据簇。
在大多数情况下,一些点异常可能看起来像是运气不好。取而代之的是模式异常,数据创建了一个看起来非常不同于正常的模式。模式异常更难检测,因为我们必须首先能够定义一个正常的模式,然后我们可能需要更多的数据来分类这种模式与历史活动相比是异常的。
下面我们给出了不同的模拟场景,其中我们应用了适合于异常检测的不同技术。它们的采用是与领域相关的,并且它们都基于简单的假设。这种简单性在我们缺少信息或存在少量数据的所有任务中都是基本的。
点异常
我们的目标是检测与其他数据偏离如此之大的数据点。这让人怀疑这些点是由不同的机制产生的。
使用两种不同的算法:卷积平滑器和指数平滑器。两者都使用滑动窗口方法平滑接收的信号。卷积方法使用离散线性卷积,而指数方法使用指数加权卷积。卷积是一种数学运算,可以描述为两个序列(原始信号和权重)乘积的积分。卷积平滑器使用预定义窗口函数生成的权重(线性、汉宁、汉明、巴特利特、布莱克曼)。在线性类型的情况下,权重都是相同的并且等于 1。这使得操作等于移动平均线。指数平滑器使用指数函数生成的权重。因此,在计算平滑度时,最近的观测值权重最大。
分别考虑了两种不同的数据结构:随机游走序列和无趋势的季节性序列。
随机游动中卷积平滑的点异常
无趋势的季节性数据中指数平滑的点异常
收集新值时,会计算平滑度。实际观测值和相应的平滑值之间的差异称为残差。我们用它们来定义异常值或异常值,即实际观测值超过残差置信带的点。
从模拟中,我们可以看到,我们的方法能够检测峰值和疯狂值,这些值可以归类为点异常。
模式异常
我们的目标是检测一组连续的数据点,这些数据点总体上是异常的,即使单个点可能是也可能不是异常点。当我们寻找模式异常时,潜在的假设是原始数据必须显示一个模式。例如,季节性时间序列就是这种情况。
时间序列中的季节性在很多数据中都可以观察到。研究季节性因素对于有效的异常检测至关重要。在这方面,一个关键的挑战是如何确定季节周期并将其从趋势中分离出来。季节趋势分解是检测季节和趋势分量的常用方法之一。卷积滤波、LOWESS 或自然三次样条是 tsmoothie 用来检测趋势分量的技术。而季节模式是使用周期中的平均集合来检测的。从提取的趋势和观察到的季节性的联合中,我们可以构建一个假设的平滑值的时间序列。
使用分解平滑器,将具有趋势的季节性序列考虑在内,以检测模式异常。在第一种情况下,我们的目标是检测到目前为止数据中不符合研究模式的观察结果。对大多数人来说,这是打破季节性模式的观察结果。在第二种情况下,我们在某些区间引入一个移位。我们想知道这是否被检测为可以改变趋势的剧烈变化,从而被指出为异常。
具有趋势的季节性数据中分解更平滑的模式异常
具有趋势和偏移的季节性数据中分解更平滑的模式异常
平滑机制和残差置信带的计算和以前一样工作。
从模拟中,我们可以看到我们的方法能够检测出不符合季节模式的峰值。我们还可以指出我们的传感器偏离过去观察中出现的假设模式的部分。在最后一种情况下,我们也试图提供理论信号的重建。
摘要
在这篇文章中,我们介绍了一些开发时序数据监控工具的标准技术。当我们想要检测异常,但是我们不处理关于底层系统的很多信息时,我们的方法看起来非常有用。所提出的方法也适用于同时处理多个时间序列。我们必须小心选择正确的一个,并进行一些参数调整。
查看我的 GITHUB 回购
保持联系: Linkedin
可定制的实时仪表板,以监控您的谷歌表单的反应
原文:https://towardsdatascience.com/real-time-visualization-of-google-form-responses-in-streamlit-1e7fd20c6574?source=collection_archive---------26-----------------------
在 Streamlit dashboard 中可视化实时 Google 表单响应的分步指南
比方说,你的谷歌表单是共享给公众的。
您希望在一个仪表板中监控响应的更新,该仪表板可以使用多个变量进行过滤,并显示在多变量图表中。
此外,您希望它是实时的,并且可以与您的任何利益相关者共享。
很明显,你的谷歌表单中的“回复”部分不是这个场景的答案。在本文中,我将一步一步地介绍如何在 Streamlit dashboard 中可视化实时 Google 表单响应,从在 google sheets 中导入响应开始,直到部署仪表板。如上图所示,总共有 8 个步骤。
在 Google API 控制台中创建凭证
为了能够生成凭证,首先您必须在您的 Google API 控制台中创建一个新项目。
图 1:创建一个新项目
单击“新建项目”后,您必须指定项目的名称。保留默认位置。然后,单击“创建”来创建您的新项目。
图 2:给你的项目命名
完成创建新项目后,您将看到显示项目信息、API 请求信息等的仪表板。在仪表板的顶部,有一个 API 和服务的搜索栏。在搜索栏中,搜索 Google Drive API 并选择它。
图 3:您新创建的项目的仪表板
然后,您必须启用该 API,以便我们可以从新创建的项目的 Google Drive 访问资源。
图 4: Google Drive API
启用 API 后,您将看到 API 仪表板,现在您需要做的是创建凭证。
图 5: Google Drive API 仪表板
然后,为第一个问题选择 Google Drive API 选项,为第二个问题选择 Web 服务器选项。第三,选择应用程序数据,最后为最后一个问题选择“不,我没有使用它们”。
图 6:指定您需要哪种凭证
下一步是给出一个服务帐户名称并选择编辑者角色。您可以在“项目”类别下找到编辑角色。选择 JSON 作为键类型。单击 Continue 后,将会下载 JSON 文件。
图 7:创建一个服务帐户
用你最喜欢的文本编辑器打开 JSON 文件。这里,我使用 Sublime Text 3 打开 JSON 文件。在该文件中,您可以找到“client_email”键。你必须复制那个键的值,然后我们才能进入下一部分。
图 8:下载的 JSON 文件
除了启用 Google Drive API,您还必须启用 Google Sheets API。搜索“Google Drive API”时,只需在同一搜索栏中搜索“Google Sheets API”,然后单击“启用”。
图 9: Google Sheets API
与客户电子邮件分享您的 Google 表单回复
一旦您已经从 JSON 文件中复制了“client_email”值,您就可以简单地共享该邮件的 Google 表单响应(Google Sheets)。
图 10:分享 Google 表单对客户邮件的响应
安装依赖项
关于 UI 的设置已经足够了。先说代码吧!首先,您必须安装用于导入 Google 表单响应的依赖项。需要安装的软件包有 6 个: gspread , OAuth2Client , pandas , time , streamlit ,以及 altair 。我在本教程中使用的是 Python 3.6.7。
pip install gspread==3.6.0 oauth2client==4.1.3 pandas==1.0.4 time streamlit==0.57.3 altair==4.1.0
环境设置
现在,您必须创建一个 python 脚本来将 google 表单响应数据导入到您的计算机中。在本教程中,我将 python 脚本命名为scrap_form_data.py
。请确保将下载的 JSON 文件移动到与 python 脚本相同的文件夹中。然后,您可以导入包并授权凭据。注意,您还必须根据您的文件名来更改 JSON 文件名。
导入 Google 表单响应数据
让我们假设你做了一项调查,以了解某人是否接受了新冠肺炎病毒测试。有两种类型的调查分布。第一种是询问是否使用聚合酶链式反应测试进行过测试,而第二种是使用快速测试。在本教程中,我为两种调查响应类型生成虚拟数据,并将其存储在 Google Sheets 中。下面是生成的虚拟数据片段和导入数据的脚本。
图 11:生成的虚拟数据
数据预处理
有时我们还必须在生成最终数据之前先做一些数据预处理。下面我给出一些可以做数据预处理的例子。
这里是scrap_form_data.py
脚本的完整代码。
简化仪表板构建
Streamlit 的开源应用框架是数据科学家和机器学习工程师在几个小时内创建漂亮、高性能应用的最简单方式!全是纯 Python。全部免费。
有许多很棒的文章([1][2][3])解释了如何使用 Streamlit 构建仪表板。我建议您在继续阅读本节之前,先阅读这些精彩的文章。在这里,我给出了仪表板的片段,以及构建仪表板的主要功能代码。你可以在本文最后附的回购中看到完整的代码。
部署
在本教程中,我使用 AWS EC2 来部署仪表板。要做到这一点,您可以简单地租用一个 AWS EC2 实例,并在tmux
中运行下面的命令,这样仪表板就会一直在线。
**streamlit run streamlit_dashboard.py**
然后,您可以复制“外部 URL”链接,并在您最喜欢的浏览器中打开它。这里有一篇很棒的文章解释了如何在 AWS EC2 Free 实例中部署 Streamlit Dashboard。
因为我们希望我们的仪表板是一个实时仪表板,所以我们也必须实时导入数据,或者在这种情况下,我们可以说是接近实时。您需要做的是在tmux
中运行这个 bash 脚本。它将每 10 分钟更新一次仪表板中的数据。
您可以在这里找到本文中使用的所有代码。
关于作者
Louis Owen 是一名数据科学爱好者,他总是渴望获得新知识。他在印度尼西亚顶尖大学Institut Teknologi Bandung攻读数学专业,并获得了最后一年的全额奖学金。
Louis 曾在多个行业领域担任分析/机器学习实习生,包括 OTA()、电子商务( Tokopedia )、FinTech ( Do-it )、智慧城市 App ( Qlue 智慧城市 ),目前在 世界银行 担任数据科学顾问。
去路易斯的网站了解更多关于他的信息吧!最后,如果您有任何疑问或需要讨论的话题,请通过 LinkedIn 联系 Louis。
参考
https://towards data science . com/access-Google-spread sheet-data-using-python-90 a5 BC 214 FD 2
现实世界的例子,网页刮硒和美丽的汤
原文:https://towardsdatascience.com/real-world-example-on-web-scraping-with-selenium-and-beautiful-soup-3e615dbc1fa1?source=collection_archive---------15-----------------------
美国宇航局在 Unsplash 拍摄的照片
53.9 亿。
这就是万维网的页数。
数据方面?
价值超过 1,200。
这相当于 1,200,000 TB 和 1,200,000,000 GB。
Giphy 的 GIF,2013 年 7 月 12 日(来源)
我想说的是,网络上有大量的非结构化数据。
只是坐在那里…
等待被刮擦和分析。😉
在这篇文章中,我将讲述如何用硒和美丽的汤来抓取网页的代码片段。
我将先介绍这些技术,然后再介绍一个真实的例子。
我也将提出我在这个刮擦项目中遇到的问题,这样你就知道如何在你自己的工作中减轻这些问题。
我们开始吧!
硒美汤简介
对于外行来说,让我们先简单介绍一下我们将要使用的技术。
硒
Selenium 诞生于 2004 年,是一个开源的自动化测试框架,用于验证跨不同浏览器和平台的 web 应用程序。
这些测试脚本可以使用不同的编程语言构建,如 Java、C#、PHP、Python、Ruby 和 Perl。
在本文中,我们将使用 Selenium Python 包( Selenium Web Driver )来创建测试脚本。
作为对其工作原理的快速介绍,这里有一张我在 Jupyter 笔记本上使用 Selenium 的 GIF 图片。
硒简介
在 GIF 中,我开始导入相关的包并初始化一个 chrome 浏览器。同时我告诉浏览器得到“http://www.google.com”。
接下来,我触发了一个命令,在退出之前在 Google 搜索栏中搜索“Selenium python API”。
如果你想尝试一下,那就开始使用你当地的 Jupyter 笔记本吧。
您需要做的第一件事是安装 selenium。
pip install selenium
你还需要在这里安装 chrome 驱动程序。
然后逐步运行下面的代码。
注意第 13 行,类名是“gLFyf.gsfi”?
我怎么知道谷歌搜索栏使用这个标签?
要找出一个 HTML 页面的不同标签,你需要做的就是右键点击页面,用“inspect”进入开发者模式。
如何从网页进入开发者模式
接下来,点击左上角的图标。这将使您能够选择页面上的元素。
用于选择页面上元素的图标
要查看搜索栏的标签,只需将鼠标悬停在搜索栏上。
如何找到相关标签的示例
一旦找到感兴趣的相关类标签,就可以告诉 Selenium 用代码获取它
elem = browser.find_element_by_class_name("gLFyf.gsfi")
不过,这里需要注意一点。
根据这个特殊的抓取项目的经验,我注意到了“find_element_by_class_name”函数中的一个错误。
如果类名太长,空格太多,该功能将无法工作。
我在谷歌上搜索了大量的解决方案。即使您将这些句点放在标记之间,即“gLFyf
这并不总是有效……
这方面很不靠谱。
过滤掉类标签的更好方法是使用 Beautiful Soup。
所以如果硒元素让我如此痛苦…
为什么是硒?
我不得不在这个项目中使用硒的原因是由于在美丽的汤方面的限制。
当 Beautiful Soup 解析一个 HTML 页面时,它不会解析页面中需要 java script 加载的部分。
有时,在加载网页的新部分之前,有些网页需要用户向下滚动——加载通常由 java 脚本完成。
因此,如果您的 web 页面要求您向下滚动来加载页面的片段,漂亮的 Soup 解析器将永远不会解析完整的 HTML。
为了缓解这个问题,您应该在解析整个 HTML 页面之前使用 Selenium 来自动化滚动过程。
这样,您可以灵活地使用硒或美丽的汤来开始您的信息提取过程。
我两个都用,因为他们每个人都有自己的优点,在一起,他们就像一对强大的夫妇。😃
美味的汤
创建于 2004 年的 Beautiful Soup 是一个用于无缝解析 HTML 和 XML 文件的 Python 库。
我这么说是什么意思?
好吧,让我们来看看他们的文档中的例子的修改版本。
我修改了这个例子,让事情变得更清楚一些。
首先要做的就是装美汤。
pip install beautifulsoup4
以下是代码:
正如你所看到的,美丽的汤是非常容易和直观的使用。
如果你有时间,我建议你亲自尝试一下。
那好吧。
既然介绍已经结束了,那么文章的核心部分就来了!
我们开始吧!
真正的网络抓取项目
照片由戴恩·托普金在 Unsplash 上拍摄
如果您已经完成了上面的介绍步骤,那么做得很好!
但是这就是网络抓取变得有点复杂的地方。
整个抓取项目是从 TDS 作者那里抓取文章标题。
我想分析 TDS 作者写的是什么主题,并通过每篇帖子获得的掌声数量来估计读者的兴趣。
我不会在这篇文章中讨论结果,但会在另一篇文章中讨论。
然而,我将介绍用于完成抓取任务的代码。
这花了我大约 2 天的时间让它工作,因为我一路上遇到了很多不同的 bug。
开始了。
用硒和美丽的汤刮网-两步过程
我分两步完成了这件事。
第一步——定义需要抓取的网页,并找到不同网页中使用的通用标签。
这一步需要一段时间,因为您需要找到所有相关的标签,并将它们与其他页面进行交叉引用,以确定它们是否指向您想要抓取的相同元素。
我通过打开不同页面的多个选项卡并进入开发者模式(即右键单击“Inspect”或按 F12)来手动完成此操作。
然后,我将鼠标悬停在我想要提取的元素上,并搜索所有这些元素使用的公共标签。
就拿我的简介来说吧。
要刮的东西的例子
我感兴趣的信息有:
- 发布者名称
- 发布日期
- 读出时间
- 职位名称
- 鼓掌次数
我要找的是“div”标签,它包含我想要提取的信息。
在这里,我找到了我需要的“div”标签,还注意到它有“class”标签!
完美!
注意上面有 7 个相同的“类”标签吗?
这是因为我的个人资料页面中的每个帖子都有相同的标签名称。
<div class = "gk gl gm gn go y c">...</div>
这是你想要寻找的东西。
但问题是,其他用户资料是否遵循相同的标签?
让我们把这一发现和另一份资料对照一下。
另一个概要文件的类标签示例
事实证明,并不尽然。
<div class = "gm gn go gp gq y c">...</div>
但是在看了另一个简介之后…
具有不同配置文件的另一个类标签的示例
有格局。
<div class = "go gp gp gr gs y c">...</div>
我需要的所有“div”标签的模式都遵循以下正则表达式模式:
re.compile(r'(..\s){5}y c')
在英语中,会有一个 2 字符后跟一个恰好出现 5 次的空格。在此旁边,将出现字符“y c”。
因此,这就是我在抓取过程中使用的正则表达式模式。
我不会去经历所有需要的模式,但你得到的想法。
网络抓取有点粗糙,充满了硬编码的标签。
无论如何,我冲洗和重复上述步骤,我需要提取的一切。
让我们进入下一步。
步骤 2——定义脚本将遵循的逻辑流程
回想一下,我们的目标是让获得所有 TDS 职位头衔。
从第一步我们知道我们想要提取什么,以及如何提取。
我们现在需要的是知道如何从所有作者简介页面中动态提取帖子标题。
这意味着加载每个编写者的档案并启动抓取过程。
关键字“各”。
我们该如何着手呢?
这是一个分为三步的过程:
- 我们首先运行一个抓取作业来提取所有 TDS writer 配置文件链接。
- 然后使用每个链接进入他们的个人资料页面,提取他们之前写的所有帖子标题。
- 作为(2)的子任务,对于每个 post“div ”,为基本数据帧创建一个新条目,并将该行追加到该条目。
下面是应用所有 3 个步骤后的代码。
让我们来分析一下你在上面的代码片段中看到了什么。
首先,我调用了一个定义“get_profile_urls(…)”,它接受指向所有 TDS 作者个人资料的链接。
所有 TDS 作者简介的链接示例
一旦定义抓取了每个作者的 URL 链接,它就返回一个它们的 python 列表。
url_list =['[https://medium.com/@kozyrkov','https://medium.com/@ssrosa','https://medium.com/@neha_mangal','https://medium.com/@parulnith'](https://medium.com/@kozyrkov','https://medium.com/@ssrosa','https://medium.com/@neha_mangal','https://medium.com/@parulnith'), ...]
这些链接中的每一个都被循环,并被用作另一个名为“extract_information(…)”的定义的输入。
在 gist 中,这个定义为每个 URL 初始化一个 Selenium 浏览器,并使用 Selenium 一直向下滚动到概要文件的末尾,然后启动两个子任务:“get_post(…)”和“get_writer_profile(…)”。
下面是 extract_information(…)的定义:
请注意第 21 行到第 37 行:
# Path to webdriver
browser = webdriver.Chrome(webdriver_path)# URL to scrape
browser.get(pub_url)
time.sleep(1)# Get body
elem = browser.find_element_by_tag_name("body")# No. of times to scroll
no_of_pagedowns = 100while no_of_pagedowns:
elem.send_keys(Keys.PAGE_DOWN)
time.sleep(0.5)
no_of_pagedowns-=1
这是 Selenium 为每个配置文件启动一个浏览器,定义页面的“主体”,每 0.5 秒向下滚动页面 100 次。
是的,100 是硬编码的。我以为你会在 100 卷内看完每一页。
如果没有,只要增加到 150 滚动,这应该做的把戏。
继续,请注意我是如何跟踪错误计数的。
说到网络抓取,会有很多意想不到的事情发生。
在这种情况下,我面临着以下问题:
- 没有掌声的帖子。因此,我必须说明这一点。
- 没有 H1 标题标签的帖子。
- 帖子 H4 标签在所有帖子中不相等。
- 还有更多…
对于所有这些小错误,我使用“try and except”来记录错误计数,并允许程序即使有错误也能继续运行。
如果帖子不符合数据框列,这将是一个错误,我记录了计数。
我总共刮了 5524 篇文章,其中有 435 个错误。
呀。
不过还好,我凑合用 5524。😏
现在让我们看看“get_posts(…)”和“get_writer_profiles(…)”是什么样子的。
“get_posts(…)”定义
该定义从每个帖子中提取所有相关信息,并为基本数据框创建一个新条目,并将该新条目附加到该数据框中。
此外,任何未通过提取过程的帖子都会被忽略,并保留一个错误计数器。
下面是代码的样子:
注意第 25 行和第 26 行:
ends_with_yc = re.compile(r'(..\s){5}y c')
for row in page_content.find_all('div', class_=ends_with_yc):
回想一下,我使用正则表达式匹配来查找每个帖子的位置。
我使用 Beautiful Soup 而不是 Selenium 进行提取的原因是因为类标签的匹配。
如前所述,Selenium 中似乎有一个 bug,即类标签的匹配没有正常工作。
在这个项目中,使用 class 标签来定位相关的“div”标签是至关重要的。
接下来我想提醒大家注意的是第 63 行:
dp_rt_tag = row.find_all('span')[3].find('div')
有时候找到一个父标签来搜索它的子标签真的很有帮助。
在第 63 行,父标签是“ span ”,子标签是“ div ”。
你看,网页本质上是有层次的,知道了父标签,有时候提取东西会更容易。
这里有一个我提到的等级的例子。
网页中的层次结构示例
在上图中,父标签可以是“部分,它有很多子标签——“div”、“图”、“ h1 ”、“ h2 ”等。
“get_writer_profiles(…)”定义
除了提取文章标题,我还随意提取了作者的名字,以及他们是否是顶级作家。
这就是这个定义的本质。相当直接。
我用硒来提取。
注意不同的语法。
注意,对于 Selenium,要找到一个标记,您需要运行:
match_tag = browser.find_element_by_tag_name("p")
OR
match_tag = browser.find_elements_by_tag_name("p")
单词“元素”与“元素”之间的细微差别。
在《美丽的汤》中,相当于:
match_tag = browser.find("p")
OR
match_tag = browser.find_all("p")
要在 Selenium 中找到一个类,您可以写:
match_tag = browser.find_element_by_class_name("go.gp.gp.gr.gs.y.c")
在美丽的汤里:
match_tag = browser.find('div', class_="go gp gp gr gs y c")
但是在 Selenium 中找到“class”标签并不总是有效的。
奇怪的是,它对某些类标签有效,但对其他类标签无效。😅
它对介绍中的 Google 示例有效,不是吗?
确实非常奇怪…
最终结果
运行您看到的代码后,最终提取的结果将如下所示:
我以出版商的身份过滤了 TDS。
抓取文章标题的结果
对于作者简介:
抓取作者个人资料的结果
偷偷摸摸的时刻
如果您一直在关注,请注意我是如何跳过一个定义的?😉
我没有提到任何关于“get_profile_url(…)”的定义。
我跳过了这个定义,所以你可以自己尝试一下。
与我分享的其他定义相比,这非常简单。
自己试一试,看看硒或美丽的汤是如何工作的!
如果所有这些都失败了,我的脚本和笔记本在下面的 GitHub 页面上。
一旦你亲自尝试了提取过程,你就可以检查它们。
这篇文章的 GitHub 链接:
[## timtan-github/Selenium-Web-刮刀
这个 Selenium web scraper 用于一个大型项目的数据收集阶段,以分析作者和读者…
github.com](https://github.com/timtan-github/Selenium-Web-Scraper)
结尾注释
嗯,就这样吧!
在这篇文章中,我已经向你介绍了硒和美丽的汤是如何通过简单的练习发挥作用的。
然后我给了你代码,让你在一组更真实的数据上尝试网络抓取。即 TDS 网页
注意,这个抓取器可以在任何出版物上工作,不仅仅是 TDS,在某种意义上,它可以是你得到的其他 web 抓取项目的基础。
希望这篇文章能让你对网络抓取有所了解。
说完了,下一篇帖子再见!
再见!
领英简介:谭震霆
在 Colab 上 5 分钟内实现真实的深度伪造
原文:https://towardsdatascience.com/realistic-deepfakes-colab-e13ef7b2bba7?source=collection_archive---------2-----------------------
以及为什么我们应该教育公众这种技术的存在
图片由来自 Pixabay 的斯蒂芬·凯勒拍摄
女士们先生们,Deepfake 视频非常容易制作,任何人都可以制作。你不需要博士学位,你也不需要花几个小时训练模型,你甚至不需要上一门关于生成对抗网络的课程。
你所要做的就是,录制一段你自己的视频,并选择一张你想模仿的人的照片。机器学习将按照你在视频中想要的方式给图片中的人添加动画。
用单个图像生成 Deepfakes
图像动画旨在生成视频序列,以便根据视频的运动来动画化源图像中的人。
这项技术属于计算机视觉领域,人工智能研究人员一直致力于制作更逼真的视频。它利用机器学习来操纵和生成视觉图像或视频,以他人代替一个人。
图像动画的一阶运动模型【作者阿利亚克山大
出于对科学的热爱,从研究的角度来看,阿利亚克山大的工作确实令人印象深刻。它已经发表在 NeurIPS 上,源代码可以在网上获得。
他的工作在所有基准上都超过了最先进的水平,并且可以在各种图像上工作(人脸、身体、卡通和机器人)。这个模型是如此的灵活,以至于你可以用一张目标物体的图片来创建高质量的 Deepfakes。
不需要事先信息
它学习面部动作的能力令人难以置信。你可以看到它可以识别脸上的关键点,并且它很好地跟随这些关键点到视频中的动作。
模型学习识别关键点[通过 Aliaksandr
在以前的工作中,我们需要额外的信息,如面部标志来绘制头部运动,姿势估计来绘制全身运动。
过去的工作需要面部标志和姿势估计
在这部作品中,它可以不使用任何注释或关于特定对象的先验信息来制作动画。一旦模型已经在面部上训练,模型可以将任何运动转移到任何面部上。
漂亮的头部运动
您可以录制自己的视频,并为照片中的人制作动画。是的,甚至还有一幅蒙娜丽莎的画像。
你可以抬头,转头。你会说话,嘴部动作看起来很棒。你可以转动你的眼睛,它将眼球运动很好地映射到目标视频上。
生成头部运动[由阿利亚克山大 ]
全身运动也是
它也适用于全身运动的视频!理论上,这意味着你可以拍下比莉·珍的视频,让唐纳德·特朗普像迈克尔·杰克逊一样跳太空步。
生成全身动作[由 Aliaksandr ]
它产生背景
由于人覆盖了图像的一部分,算法需要找出人背后的背景。在这个作品中,自动生成被移动的人覆盖的背景——绝对精彩。
它是如何工作的?
Aliaksandr 的工作包括运动提取器,它学习提取关键点及其局部仿射变换。有一个生成器网络,它对目标运动中的遮挡进行建模,并将从源图像中提取的外观和从驾驶视频中导出的运动进行组合。
一阶运动模型[来自论文
要了解它是如何工作的,我建议你访问 GitHub 页面并查看研究论文。你也可以看他的视频解释它是如何工作的。很酷的东西。
想自己做吗?看看这个 Colab 笔记本。
深度造假的负面后果
Deepfakes 因其在假新闻、欺诈、诈骗和许多其他非法活动中的使用而获得了广泛关注。
人们过去常常在 subreddit、 r/deepfakes 分享他们创作的 Deepfakes 视频。许多这样的视频将名人的脸,如盖尔·加朵和泰勒·斯威夫特,交换到色情表演者的身体上。
许多 Deepfakes 视频也被分享,描绘了政治家。它通过独裁政府传播虚假信息、仇恨和恐惧来影响政治。
这项技术已经引起了行业和政府的关注,以控制和限制 Deepfakes 的使用。2018 年 2 月, Reddit 因违反政策暂停 r/deepfakes 。2019 年 6 月,它引起了政府的关注,以通过限制 Deepfakes 视频更改技术来打击虚假信息的传播。
和我一起告知它的存在
知道世界上有人会滥用这项技术。你可能会问,我为什么要写这个?为什么我要传播这些知识?
由于在当今这个时代,任何人都可以很容易地制作假视频,这样的生成模型不再是科幻小说了。我的目标是教育公众,让人们知道这种技术的存在。通过了解它的存在,人们可以有所觉察,更加注重辨别真假。
假新闻是当今互联网结构的一部分,现在假新闻很容易被发现;这使得虚假信息达到了一个全新的水平。它通过传播虚假信息影响了政治。它导致人们被骗子利用,利用它在网上骗钱。
由于冠状病毒,世界现在已经一片混乱;我不确定在这种时候人们会如何滥用这项技术。Deepfakes,作为一种虚假信息,是危险的。我们需要对人们进行技术教育,人们需要辨别真相,而不仅仅是相信我们所看到的。
[## 从 Google 联合实验室看它的实际应用
一阶运动模型
colab.research.google.com](https://colab.research.google.com/github/AliaksandrSiarohin/first-order-model/blob/master/demo.ipynb) [## 数据科学家:21 世纪最肮脏的工作
40%的吸尘器,40%的看门人,20%的算命师。
towardsdatascience.com](/data-scientist-the-dirtiest-job-of-the-21st-century-7f0c8215e845) [## 人工智能和神经科学之间的迷人关系
他们如何相互激励、共同进步、相互受益
towardsdatascience.com](/the-fascinating-relationship-between-ai-and-neuroscience-89189218bb05)
图像动画的一阶运动模型。神经信息处理系统的进展。2019.
插图属于 阿利亚克山大 ,经允许使用。
使用 TensorFlow2.x 的实时多人 2D 姿态估计
原文:https://towardsdatascience.com/realtime-multiple-person-2d-pose-estimation-using-tensorflow2-x-93e4c156d45f?source=collection_archive---------4-----------------------
图片来源:左:BailarineEugenia Delgrossi—右: OpenPose — IEEE-2019
介绍
正如 Zhe Cao 在他的 2017 论文中所描述的,实时多人 2D 姿势估计对于让机器理解图像和视频中的人至关重要。
然而,什么是姿态估计呢?
顾名思义,它是一种用于估计一个人身体位置的技术,例如站、坐或躺。获得这种估计的一种方法是找到 18 个“身体的关节”,或者如人工智能领域中所命名的:“关键点”下图显示了我们的目标,即在图像中找到这些点:
图片来源:物理世界——爱因斯坦在牛津(1933)
关键点从点#0 (顶颈)向下到身体关节,回到头部,以点#17 (右耳)结束。
使用基于人工智能的方法出现的第一项重要工作是谷歌的 Toshev 和 Zegedy 在 2014 年发表的论文 DeepPose 。提出了一种基于深度神经网络(DNNs)的人体姿态估计方法,其中姿态估计被表述为一个基于 DNN 的针对身体关节的回归问题。
该模型由一个 AlexNet 后端(7 层)和一个输出 2k 关节坐标的额外最终层组成。这种方法的显著问题是,首先,必须检测单个人(经典的对象检测),随后是模型应用。因此,在图像上发现的每个人体必须分别处理,这大大增加了处理图像的时间。这种方法被称为“自上而下”,因为首先要找到身体,然后找到与之相关的关节。
姿态估计的挑战
有几个与姿态估计相关的问题,如:
- 每个图像可能包含未知数量的人,这些人可能出现在任何位置或比例。
- 由于接触、闭塞或肢体关节,人与人之间的交互会导致复杂的空间干扰,使各部分的关联变得困难。
- 运行时的复杂性往往会随着图像中人数的增加而增加,这使得实时性能成为一个挑战。
为了解决这些问题,一种更令人兴奋的方法(这就是这个项目使用的方法)是 OpenPose ,这是 ZheCao 和他来自卡内基梅隆大学机器人研究所的同事在 2016 年推出的。
开放姿势
提出的 OpenPose 方法使用非参数表示,称为部分亲和场(PAF ),以“连接”每个在图像上找到的身体关节,将它们与个人相关联。换句话说,OpenPose 与 DeepPose 相反,首先找到图像上的所有关节,然后“向上”寻找最有可能包含该关节的身体,而不使用任何人探测器(“自下而上”的方法)。OpenPose 查找图像上的关键点,而不管图像上有多少人。下面的图片是从 ILSVRC 和 COCO workshop 2016 上的 OpenPose 演示中获取的,让我们了解一下这个过程。
图片来源:ILSVRC 和 COCO workshop 2016 上的 OpenPose 演示
下图显示了用于训练的双分支多级 CNN 模型的架构。首先,前馈网络同时预测身体部位位置的一组 2D 置信图(S )(来自(dataset/COCO/annotations/)的关键点注释)和一组部位亲和力的 2D 矢量场(L ),其对部位之间的关联程度进行编码。在每个阶段之后,两个分支的预测以及图像特征被连接起来用于下一阶段。最后,通过贪婪推理来解析置信图和亲和域,以输出图像中所有人的 2D 关键点。
图片来源: 2017 OpenPose 论文
在项目的执行过程中,我们将回到这些概念中的一些来进行澄清。然而,强烈建议关注 OpenPose ILSVRC 和 COCO workshop 2016 演示和 CVPR 2017 的视频录制,以便更好地理解。
TensorFlow 2 开放姿态安装(tf 姿态估计)
最初的 OpenPose 是使用基于模型的 VGG 预训练网络和使用 Caffe 框架开发的。然而,对于这次安装,我们将遵循伊尔杜·金张量流方法,详见他的 tf 姿态估计 GitHub 。
什么是 tf 姿态估计?
tf-pose-estimation 是“Openpose”,一种使用 Tensorflow 实现的人体姿态估计算法。它还提供了几个变体,对网络结构进行了一些更改,以便在 CPU 或低功耗嵌入式设备上进行实时处理。
tf-pose-estimation GitHub 显示了使用不同模型的几个实验,如下所示:
- cmu: 原论文中描述的基于模型的 VGG 预训练网络,将 Caffe 格式的权重转换为 TensorFlow 中使用。
- dsconv :与 cmu 版本的架构相同,除了 mobilenet 的深度方向可分离卷积。
- mobilenet :基于 mobilenet V1 论文,使用 12 个卷积层作为特征提取层。
- mobilenet v2 :类似于 mobilenet,但是使用了它的改进版本。
本文中的研究是使用 mobilenet V1(“mobilenet _ thin”)完成的,它在计算预算和延迟方面的性能居中:
https://github . com/ildoonet/TF-pose-estimation/blob/master/ETCS/experiments . MD
第 1 部分—安装 tf 姿态估计
我们在这里跟随,优秀的 Gunjan Seth 文章用 TensorFlow 2.0 进行姿态估计。
- 转到终端并创建一个工作目录(例如,“Pose_Estimation”),移动到该目录:
mkdir Pose_Estimation
cd Pose_Estimation
- 创建一个虚拟环境(例如 Tf2_Py37)
conda create --name Tf2_Py37 python=3.7.6 -y
conda activate Tf2_Py37
- 安装 TF2
pip install --upgrade pip
pip install tensorflow
- 安装将在开发期间使用的基本包:
conda install -c anaconda numpy
conda install -c conda-forge matplotlib
conda install -c conda-forge opencv
- 克隆 tf 姿态估计库;
git clone https://github.com/gsethi2409/tf-pose-estimation.git
- 转到 tf-pose-estimation 文件夹并安装需求
cd tf-pose-estimation/
pip install -r requirements.txt
下一步,安装 SWIG ,这是一个接口编译器,将 C 和 C++编写的程序与 Python 等脚本语言连接起来。它的工作原理是获取 C/C++头文件中的声明,并使用它们来生成脚本语言访问底层 C/C++代码所需的包装器代码。
conda install swig
- 使用 Swig,构建 C++库进行后处理。
cd tf_pose/pafprocess
swig -python -c++ pafprocess.i && python3 setup.py build_ext --inplace
现在,安装 tf-slim 库,这是一个轻量级的库,用于定义、训练和评估 TensorFlow 中的复杂模型。
pip install git+https://github.com/adrianc-a/tf-slim.git@remove_contrib
就是这样!现在,有必要进行一个快速测试。以便返回到主 tf 姿态估计目录。
如果你按照顺序,你必须在 tf_pose/pafprocess 里面。否则,使用相应的命令来更改目录。
cd ../..
在 tf-pose-estimation 目录中有一个 python 脚本 run.py ,让我们运行它,参数为:
- model=mobilenet_thin
- resize=432x368(预处理时图像的大小)
- 图像=。/images/ski.jpg(图像目录中的示例图像)
python run.py --model=mobilenet_thin --resize=432x368 --image=./images/ski.jpg
请注意,在几秒钟内,什么也不会发生,但大约一分钟后,终端应该会显示类似下图的内容:
然而,更重要的是,图像将出现在一个独立的 OpenCV 窗口中:
太好了!这些图像证明了一切都已正确安装并运行良好!我们将在下一节详细介绍。然而,为了快速解释这四个图像的含义,左上角(“结果”)是以原始图像(在这种情况下,是 ski.jpg)作为背景绘制的姿态检测骨架。右上角的图像是“热图”,其中显示了“检测到的零件”(Ss),底部的两个图像显示了零件关联(Ls)。“结果”是将个人的 S 和 L 联系起来。
接下来的测试是现场视频:
如果计算机只安装了一个摄像头,请使用:camera=0
python run_webcam.py --model=mobilenet_thin --resize=432x368 --camera=1
如果一切顺利,将会出现一个窗口,显示真实的实时视频,如下图所示:
图片来源:PrintScreen 作者的网络摄像头
第 2 部分——深入研究图像中的姿态估计
在本节中,我们将更深入地研究 TensorFlow 姿态估计的实现。建议跟随文章,尝试重现 Jupyter 笔记本:10 _ Pose _ Estimation _ Images,可从 Project GitHub 下载。
作为参考,这个项目是 100%在 MacPro (2.9Hhz 四核 i7 16GB 2133Mhz RAM)上开发的。
导入库
import sys
import time
import logging
import numpy as np
import matplotlib.pyplot as plt
import cv2from tf_pose import common
from tf_pose.estimator import TfPoseEstimator
from tf_pose.networks import get_graph_path, model_wh
模型定义和目标估计器创建
可以使用位于模型/图形子目录中的模型,如 mobilenet_v2_large 或 cmu (VGG 预训练模型)。
对于 cmu,*。pb 文件在安装过程中没有下载,因为它们非常大。要使用它,运行位于/cmu 子目录中的 bash 脚本 download.sh 。
这个项目使用 mobilenet_thin (MobilenetV1),考虑到使用的所有图像都要整形为 432x368。
参数:
model='mobilenet_thin'
resize='432x368'
w, h = model_wh(resize)
创建评估者:
e = TfPoseEstimator(get_graph_path(model), target_size=(w, h))
为了便于分析,让我们加载一个简单的人类图像。OpenCV 用于读取图像。图像以 RGB 格式存储,但在内部,OpenCV 支持 BGR。使用 OpenCV 显示图像没有任何问题,因为在图像显示在特定的窗口之前,图像将从 BGR 转换为 RGB(如前一节中的 ski.jpg 所示)。
一旦在 Jupyter 单元格上绘制图像,将使用 Matplotlib 代替 OpenCV。因此,图像应该在显示前进行转换,如下所示:
image_path = ‘./images/human.png’
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)
plt.grid();
请注意,此图像的形状为 567x567。OpenCV 在读取图像时,自动将其转换为数组,其中每个值从 0 到 255,其中 0=白色,255=黑色。
一旦图像是一个数组,就很容易使用 shape 来验证它的大小:
image.shape
结果将是(567,567,3),其中形状是(宽度,高度,颜色通道)。
尽管可以使用 OpenCV 读取图像;我们将使用 tf_pose.common 库中的函数 read_imgfile(image_path)来防止颜色通道出现任何问题。
image = common.read_imgfile(image_path, None, None)
一旦我们将图像作为一个数组,我们就可以将方法推理应用于估计器(e),将图像数组作为输入(图像将使用原则上定义的参数 w 和 h 来调整大小)。
humans = e.inference(image, resize_to_default=(w > 0 and h > 0), upsample_size=4.0)
运行上述命令后,让我们检查数组 e.heatmap。该数组的形状为(184,216,19),其中 184 是 h/2,216 是 w/2,19 与特定像素属于 18 个关节之一的概率相关(0 到 17)+1(18:无)。例如,检查左上角的像素,应该会得到“无”的结果:
可以验证该数组的最后一个值
这是所有价值中最高的;可以理解的是,有 99.6%的几率,这个像素不属于 18 个关节中的任何一个。
让我们试着找到颈部的底部(两肩之间的中点)。它位于原始图片上大约半宽(0.5 *宽= 108)和大约 20%高的位置,从上/下开始(0.2 *高= 37)。因此,让我们检查这个特定的像素:
很容易实现位置 1 的最大值为 0.7059……(或者通过计算 e.heatMat[37][108】)。max() ),这意味着该特定像素有 70%的概率是“基颈”。下图显示了所有 18 个 COCO 关键点(或“身体关节”),显示“1”对应于“基础颈部”。
人体姿态骨骼的 COCO 关键点格式。
可以为每个像素绘制代表其最大值的颜色。这样,显示关键点的热图就会神奇地出现:
max_prob = np.amax(e.heatMat[:, :, :-1], axis=2)
plt.imshow(max_prob)
plt.grid();
现在,让我们在重塑的原始图像上绘制关键点:
plt.figure(figsize=(15,8))
bgimg = cv2.cvtColor(image.astype(np.uint8), cv2.COLOR_BGR2RGB)
bgimg = cv2.resize(bgimg, (e.heatMat.shape[1], e.heatMat.shape[0]), interpolation=cv2.INTER_AREA)
plt.imshow(bgimg, alpha=0.5)
plt.imshow(max_prob, alpha=0.5)
plt.colorbar()
plt.grid();
因此,可以在图像上看到关键点,颜色条上显示的值意味着黄色越多,可能性越大。
要获得关键点(或“关节”)之间最可能的连接(或“骨骼”),我们可以使用 e.pafMat 的结果数组。该数组的形状为(184,216,38),其中 38 (2 x 19)与该像素成为 18 个特定关节+ nones 之一的水平(x)或垂直(y)连接的一部分的概率相关。
绘制上述图形的函数在笔记本中。
使用 draw_human 方法绘制骨骼
使用列表 human ,e.inference()方法的结果,可以使用 draw_human 方法绘制骨架:
image = TfPoseEstimator.draw_humans(image, humans, imgcopy=False)
结果如下图所示:
如果需要的话,可以只绘制骨架,如下所示(让我们重新运行所有代码来回顾一下):
image = common.read_imgfile(image_path, None, None)
humans = e.inference(image, resize_to_default=(w > 0 and h > 0), upsample_size=4.0)
black_background = np.zeros(image.shape)
skeleton = TfPoseEstimator.draw_humans(black_background, humans, imgcopy=False)
plt.figure(figsize=(15,8))
plt.imshow(skeleton);
plt.grid();
plt.axis(‘off’);
获取关键点(关节)坐标
姿态估计可用于机器人、游戏或医学等一系列应用。为此,从图像中获取物理关键点坐标以供其他应用程序使用可能会很有趣。
查看 e.inference()产生的人类列表,可以验证这是一个只有一个元素的列表,一个字符串。在这个字符串中,每个关键点都以其相对坐标和关联概率出现。例如,对于目前使用的人类图像,我们有:
例如:
BodyPart:0-(0.49, 0.09) score=0.79
BodyPart:1-(0.49, 0.20) score=0.75
...
BodyPart:17-(0.53, 0.09) score=0.73
我们可以从这个列表中提取一个数组(大小为 18 ),其中包含与原始图像形状相关的实际坐标:
keypoints = str(str(str(humans[0]).split('BodyPart:')[1:]).split('-')).split(' score=')keypts_array = np.array(keypoints_list)
keypts_array = keypts_array*(image.shape[1],image.shape[0])
keypts_array = keypts_array.astype(int)
让我们在原始图像上绘制这个数组(因为数组的索引是关键点)。结果如下:
plt.figure(figsize=(10,10))
plt.axis([0, image.shape[1], 0, image.shape[0]])
plt.scatter(*zip(*keypts_array), s=200, color='orange', alpha=0.6)
img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(img)
ax=plt.gca()
ax.set_ylim(ax.get_ylim()[::-1])
ax.xaxis.tick_top()
plt.grid();for i, txt in enumerate(keypts_array):
ax.annotate(i, (keypts_array[i][0]-5, keypts_array[i][1]+5)
创建功能以快速再现对普通图像的研究:
笔记本显示了迄今为止开发的所有代码,“封装”成函数。例如,让我们看另一个图像:
image_path = '../images/einstein_oxford.jpg'
img, hum = get_human_pose(image_path)
keypoints = show_keypoints(img, hum, color='orange')
图片来源:物理世界——爱因斯坦在牛津(1933)
img, hum = get_human_pose(image_path, showBG=False)
keypoints = show_keypoints(img, hum, color='white', showBG=False)
与多人一起研究图像
到目前为止,只探索了包含一个人的图像。一旦算法被开发来同时从图像中捕获所有关节(S)和 PAFs ),寻找最可能的连接只是为了简单。所以,得到结果的代码是一样的;例如,只有当我们得到结果(“人类”)时,列表才会具有与图像中的人数相兼容的大小。
例如,让我们使用一个上面有五个人的“忙碌图像”:
image_path = './images/ski.jpg'
img, hum = get_human_pose(image_path)
plot_img(img, axis=False)
图片来源: OpenPose — IEEE-2019
该算法找到了将他们与这五个人相关联的所有 Ss 和 Ls。成绩优秀!
从读取图像路径到绘制结果,整个过程不到 0.5s,与图像中找到的人数无关。
让我们把它复杂化,看一个图像,当一对夫妇跳舞时,人们更加“混杂”:
image_path = '../images/figure-836178_1920.jpg
img, hum = get_human_pose(image_path)
plot_img(img, axis=False)
图片来源: Pixabay
结果似乎也很好。让我们只画关键点,每个人用不同的颜色:
plt.figure(figsize=(10,10))
plt.axis([0, img.shape[1], 0, img.shape[0]])
plt.scatter(*zip(*keypoints_1), s=200, color='green', alpha=0.6)
plt.scatter(*zip(*keypoints_2), s=200, color='yellow', alpha=0.6)
ax=plt.gca()
ax.set_ylim(ax.get_ylim()[::-1])
ax.xaxis.tick_top()
plt.title('Keypoints of all humans detected\n')
plt.grid();
第 3 部分:视频和现场摄像机中的姿态估计
在视频中获取姿态估计的过程与我们处理图像的过程相同,因为视频可以被视为一系列图像(帧)。建议跟着小节走,尽量重现 Jupyter 笔记本: 20_Pose_Estimation_Video 可从 Project GitHub 下载。
OpenCV 在处理视频方面做得非常出色。
因此,让我们获取一个. mp4 视频,并通知 OpenCV 我们将捕获它的帧:
video_path = '../videos/dance.mp4
cap = cv2.VideoCapture(video_path)
现在让我们创建一个捕捉每一帧的循环。有了框架,我们将应用 e.inference(),从结果中,我们将绘制骨架,就像我们对图像所做的一样。结尾包含了一段代码,用于在按下某个键(例如“q”)时停止播放视频。
下面是必要的代码:
fps_time = 0while True:
ret_val, image = cap.read() humans = e.inference(image,
resize_to_default=(w > 0 and h > 0),
upsample_size=4.0)
if not showBG:
image = np.zeros(image.shape)
image = TfPoseEstimator.draw_humans(image, humans, imgcopy=False) cv2.putText(image, "FPS: %f" % (1.0 / (time.time() - fps_time)), (10, 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
cv2.imshow('tf-pose-estimation result', image)
fps_time = time.time()
if cv2.waitKey(1) & 0xFF == ord('q'):
breakcap.release()
cv2.destroyAllWindows()
图片来源: tf-pose-estimation GitHub 上的视频截图
图片来源:截图自 tf-pose-estimation GitHub 上的视频样本
结果很棒,但是有点慢。最初大约 30 FPS(每秒帧数)的电影将在“慢速相机”中运行,大约 3 FPS。
这是另一个经历,电影放了两次,记录了有背景视频和没有背景视频的姿态估计骨架。视频是手动同步的,但如果结果不完美,那就太棒了。我剪掉了 1928 年卓别林电影《马戏团》的最后一个场景,流浪汉走路的方式很经典。
用现场摄像机测试
建议按照小节,尝试重现 Jupyter 笔记本:30 _ Pose _ Estimation _ Camera可从 Project GitHub 下载。
运行现场摄像机所需的代码与视频使用的代码几乎相同,只是 OpenCV videoCapture()方法将接收一个整数作为输入参数,该整数表示使用的是什么真实摄像机。例如,内置摄像头使用“0”,外置摄像头使用“1”。此外,相机应设置为捕捉模型使用的“432x368”帧。
参数初始化:
camera = 1
resize = '432x368' # resize images before they are processed
resize_out_ratio = 4.0 # resize heatmaps before they are post-processed
model = 'mobilenet_thin'
show_process = False
tensorrt = False # for tensorrt processcam = cv2.VideoCapture(camera)
cam.set(3, w)
cam.set(4, h)
代码的循环部分应该与视频中使用的非常相似:
while True:
ret_val, image = cam.read() humans = e.inference(image,
resize_to_default=(w > 0 and h > 0),
upsample_size=resize_out_ratio)
image = TfPoseEstimator.draw_humans(image, humans, imgcopy=False)
cv2.putText(image, "FPS: %f" % (1.0 / (time.time() - fps_time)), (10, 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
cv2.imshow('tf-pose-estimation result', image)
fps_time = time.time()
if cv2.waitKey(1) & 0xFF == ord('q'):
breakcam.release()
cv2.destroyAllWindows()
图片来源:PrintScreen 作者的网络摄像头
同样,当使用该算法时,30 FPS 的标准视频捕获减少到大约 10%。这里有一个完整的视频,可以更好地观察到延迟。然而结果却是极好的!
结论
一如既往,我希望这篇文章可以激励其他人在 AI 的奇幻世界中找到自己的路!
本文中使用的所有代码都可以从 GitHub 项目下载:TF2 _ 姿势 _ 估计
来自世界南方的问候!
我的下一篇文章再见!
谢谢你
马塞洛
重构传统的机器学习系统
原文:https://towardsdatascience.com/rearchitecting-legacy-machine-learning-systems-c1035e79ad98?source=collection_archive---------37-----------------------
活动讲座
阿米特·贾恩和罗纳尔多·费利佩| TMLS2019
来自多伦多机器学习峰会的演讲:【https://torontomachinelearning.com/
TradeRev 使用回归模型来预测汽车的拍卖价格。ML/development 的早期完全集中在产品成功上市的时间上,但是我们最终得到了一个有巨大技术债务的代码库(意大利面条代码、整体架构、手工创建的基础设施等等)。).
随着产品的扩展成为一个巨大的瓶颈,产品采用率的增加暴露了技术债务。演讲者将讨论他们如何从软件工程和数据科学的角度来应对重新构建整个 ML 产品的挑战。
他们将分享他们如何通过这一努力实现了许多里程碑:
- 提高模型准确性
- 微服务架构
- 可扩展的 ML 解决方案
- 持续集成和自动化部署
- 文档化软件解决方案- 80%以上的代码覆盖率
- 回归/性能测试
- 增强对评估指标的监控
- 基础设施即服务
【Youtube.com
与 Amit Jain 联系: LinkedIn | Twitter
金融情报推理
原文:https://towardsdatascience.com/reasoning-on-financial-intelligence-3e40db6c2b5?source=collection_archive---------40-----------------------
知识图表和推理
如何使用人工智能帮助打击有组织犯罪
梁杰森在 Unsplash 上的照片
严重犯罪的动机是利润,无论大小,大多数犯罪行为都会留下财务线索。金融情报是收集犯罪分子信息的过程,这些犯罪分子试图利用金融部门的弱点来掩盖非法资金。
在这里我们不是在谈论一些随机的庞氏骗局或者如何花费十一罗汉抢劫的赃物。它既不有趣也不迷人。在这里,我们谈论的是被摧毁的生命。一万亿美元的事件与各种卑鄙的潜在犯罪,命名的上游犯罪,如腐败,剥削儿童,奴役,贩毒,逃税,人口贩运,人口走私,有组织犯罪,等等。
金融情报的神经中枢由金融情报机构组成,这些独立机构分布在每个国家,打击洗钱和恐怖主义融资。金融情报机构的分析师与私营部门、执法部门和其他国家安全合作伙伴合作,识别、侦查和摧毁犯罪网络及其犯罪所得,以实现一个没有犯罪滥用的金融系统。他们接收可疑交易报告,并发布对参与者、金融交易和可疑犯罪的详细和一致的分析。
如果您想了解更多关于反洗钱系统的运作情况,您可以在此处获得信息:
[## 多花几美元
金融智能的业务是什么,为什么要关注?
medium.com](https://medium.com/discourse/for-a-few-dollars-more-4d25ceba2023)
无论你是金融分析师、人工智能极客还是研究人员,难道你不想通过使用知识图上的推理来帮忙吗?
让我们看看如何!
背景
在金融情报机构的日常调查职责中,必须完成许多任务。金融情报部门从私营部门以可疑交易报告 (STRs)的形式接收数千份可能的可疑金融数据,并调查复杂的洗钱案件,以揭露犯罪所得看似合法的来源。
在这样做的时候,金融情报机构应该评估可疑情况(计算出一个分数或一个评估等级的试探法),并使用某种分类来确定所涉及的罪行。在此过程中,管理大量数据(也来自其他政府机构)的金融情报机构需要执行基于风险的计划(例如,首先追查更多可疑案件或重大犯罪)。连接所有任务和子任务的点是重建过程,通常写一份报告,包括所有可能的假设和结论,包括所有的证据。
金融情报机构的反洗钱任务—按作者分类的图片
在一个犯罪具有跨国性的世界里,参与全球金融情报机构系统的所有行动者之间的合作至关重要。许多国际利益攸关方声称,大力和持续使用现代技术可以促进和维持金融情报机构之间以及金融情报机构与私营部门之间的良性合作。[1,5,6,7,8]
根据最近发表在“声明性人工智能 2020”的行业跟踪中的新兴的基于规则的反洗钱观点,我们可以将反洗钱任务和金融情报机构感兴趣的子任务设置为推理任务,涵盖反洗钱知识图(AML-KG) ,对所有相关领域对象和相互联系进行建模。
知识图是一种半结构化的数据模型,由三个部分组成:
- (基础)扩展组件( EDB,扩展数据库),具有构造,即事实,以图形或其概括的形式表示数据;
- 内涵组件( IDB,意向数据库),具有对基础外延组件的事实的推理规则;
- 一个派生的扩展组件,推理组件,在推理过程中产生,它在基础事实上应用规则。[4]
知识图上的推理涉及在回答查询时遍历它的不同方式,沿着不同的路径到达所有相互链接的相关实体,可能需要创建图的新部分:创建新知识。
反洗钱知识图表—图片由作者提供
在这幅图中,AML-KG在较高的抽象层次上得到体现。
特别是,在 AML-KG 中,可疑交易报告(str)、来自社交网络和媒体的事实、报纸或来自执法机关的后续反馈都被表示为 KG 的 EDB,以及来自企业知识系统的数据。对于中介,它们包括交易、企业和 KYC 数据。IDB 可用于以“RegTech”方式表示和实施官方法规,并对自定义标准进行编码,包括洗钱模式(例如,循环电汇、金字塔控制结构)、域规则和可疑行为,这些都是金融情报分析师广为人知的。
大多数洗钱模式、可疑行为和金融业务规则都可以用一种知识和推理表示语言 (KRR)进行有效描述,支持完全递归、本体推理、概率推理和机器学习模型。[1,4]
如果你想了解更多关于 KRR 人在知识图上进行推理的迫切需要,你可以看看最近这篇关于走向数据科学的文章。
在 AML-KG 中,推理规则应该由金融分析师和领域工程师来设计。事实上,在这个领域,精心制作的规则体现了无法从数据中归纳出来的有价值的领域知识。例如,合规性法规、洗钱模式的内部机制或财务跟踪混淆的策略对分析师来说可能是众所周知的,以至于从数据中得出结论会导致准确性和可解释性降低。另一方面,当规则嵌入参数化机器学习模型时,这些参数又可以从数据中推断出来,此外,从数据中学习规则可以敏感地加快普通规则设计过程。图片“AML 知识图”中的学习总线表示这种混合演绎/归纳方法。
编码将规则(KG IDB 的)应用于 EDB 的推理过程可以使用 KGMS(知识图管理系统)来执行,KGMS 是一种软件推理引擎,它对非常大量的数据执行复杂的基于规则的推理任务,此外,还提供用于数据分析和机器学习的方法和工具。[4]
在这种情况下,我使用牛津大学的 Vadalog 系统作为 KGM,但还有许多其他可用的系统,如 RDFox 、 LogicBlox 、 Ontotext 等。
触发器
让我们来看一下一个勾结和腐败的案例,其中涉及许多参与者和盘根错节的金融活动。在这种情况下,我们利用 AML-KG 的全面推理能力,以及金融情报单位在日常工作中可以利用的大部分信息。
这是一个来自真实金融情报机构的真实洗钱案例,我们现在可以通过推理方法有效地进行分析和处理。该案件已被匿名化,并因图形原因进行了部分简化,但案件中所有必要的和难以解决的元素都包括在内。我们当然会用图标和昵称来称呼个人和实体。
正如我们在前面的上下文部分所看到的,一个金融情报单位可以收到数千份可疑交易报告。
有些充满了细节,有些是假阳性,大多数是如此模糊和难以理解,以至于科学家和软件都无法单独得出任何结论。
让我们考虑一下银行发送给金融情报机构字符串。
AML-KG 案件的导火索。
一个有前科的人(图标为“坏人”)向 Acme 银行申请贷款。就是这样。没有其他线索。
Acme Bank 可能正在努力完成其合规责任,向其当地的金融情报机构报告任何哪怕是很小的可疑活动。但是…
关于 Acme Bank 的这份报告,金融情报机构应该对反洗钱活动得出什么结论?
金融情报机构应该拿出水晶球,给我们一个充分解释和合理的理由,说明是否有理由相信这项交易是异常的。或者,更典型的是,它应该依靠金融情报分析师的经验和专业知识。
这一过程始于漫长而痛苦的分析,可能包括其他私人实体、其他金融情报机构,更简单地说,是金融情报机构已经掌握并应试图用来解开这一谜题的所有信息。在这样做的时候,分析师应该跟着钱、直觉、经验走,更实际的是,开始查询所有可用的数据。这是一个危险的过程,在这一过程中,对众所周知的犯罪活动的模式和所有可能的变体进行概括是可以预见的,如果是这样的话,就要进行准确的考虑。
目标是了解该可疑交易报告是否导致与洗钱有关的事情,此处的主要活动是确定该可疑交易报告的可疑性,并因此评估可疑性评分。
现在让我们看看如何用基于规则的方法来实现它!
情况
我们可以开始探索一种基于资产最终受益所有人的隐瞒的典型洗钱模式。
在这种情况下,向银行申请贷款的人(他或她是该银行的最终受益所有人)可能打算通过该银行清洗不干净的钱。最终受益所有人是真正控制资产的实体。与此同时,我们需要指定所有可能的模式来隐藏资产的最终受益者,在本例中是 Acme Bank。
但是如何表达公司控制权的含义呢?我如何用计算机能在合理的时间内运行的“东西”来概括个人或另一家公司控制的所有可能路径?
就是这样!
这是一组用 Vadalog 编写的 5 个规则,vada log 是 Datalog 家族的一种语言,它用许多有用的功能扩展了 Datalog,如存在量化、聚合、分层否定、布尔条件、数学表达式、概率推理、嵌入式函数和任意机器学习模型,同时由于推理任务的 PTIME 数据复杂性而保证了可扩展性。[4]
有了这一套规则,我们就可以很容易地描述公司控制权的概念了。
让我们通过一组数据日志规则来描述公司控制的概念,如下所示:
规则 1 是谓词“控制”的自反属性。一般来说,一家公司(或一个人或一个家庭)x 控制一家公司 y,如果:
- (规则 2) x 直接拥有 y 超过 50%的股份
- 或者,(规则 3) x 控制一组公司,这些公司共同(即合计股份金额),并且可能与 x 一起,拥有 y 超过 50%的股份[2,3]
我们也可以假设一个公司的 CEO 对它有完全的控制权(规则 4)。这当然是一种简化,但适用于这种情况。在规则 5 中,我们看到了聚合函数,它将所有可能的所有权路径上的直接和间接所有权进行累加和求和。
如果我们在最先进的云机器和 Vadalog 系统上运行推理过程,利用 5 行数据日志,我们可以在几分钟内测试 AML- KG 中数百万公司之间的数千条路径控制。而不是试图通过查询或特别的程序或算法来寻找合理的路径。还要考虑到在图中表达未知的导航模式并不简单,并且涉及到求助于复杂的设备,比如递归,这超出了分析师的标准编程技能。
让我们更深入地了解一下在 FIU 数据上激活这简单的五条规则!
这是 AML-KG 结合 KG 的 IDB 和 EDB 的推理过程的部分结果。在黑色固体中,代表公司之间所有权级别的 EDB 的现有边缘,以及链接是 CeoAt。而我的银行和 Acme 银行之间的绿色虚线控制边已经通过推理推断出来了!所以这个绿色的链接属于衍生的 EDB 部分,推理部分,通过规则的应用来推断。
目前,我们发现我们的强盗没有控制 Acme 银行。我们只知道我的银行控制着 Acme 银行。
现在,在测试了隐藏资产最终受益者的非常常见的洗钱模式后,让我们更进一步。
有时,犯罪分子,特别是有组织犯罪中的犯罪分子,试图通过他们的附属机构,通常甚至是家庭成员或亲戚来隐藏对资产的控制,这在黑手党家族中是常见的。
因此,让我们添加一些规则来发现这种关系。
另一组规则的目标是将个人聚集到家庭中,这些家庭可以是真实的家庭,或者只是广义上的犯罪成员。特别地,规则 1 包含用于链路预测的专门的机器学习模型,由 #sim 嵌入式函数表示。它返回一个分数 p 来衡量两个人 i_1 和 1_2 成为配偶的可能性。注意到“::”符号偏离了标准的 Datalog 语法,表示一种“规则概率”。特别地,规则 1 产生配偶事实,其概率取决于 p。
规则 3 规定,每个人都属于一个家庭,他/她自己的家庭,规则 4 将家庭 f1 和 F2 合并,只要它们包含两个配偶,即 i1 和 I2。类似的规则可以合并拥有不同关系的个人的家庭。整体效果是聚类人的空间。
然后,我们可以将第一组规则与规则 5 中的第二组规则联系起来,在规则 5 中,我们可以合计不同家庭成员的所有权金额。
通过对现有数据的推理,这是我们最终可以揭示的:
运用第二组规则,我们找出“坏人”的家庭成员,特别是他的配偶 P1。这个家庭还包括 P2、P3,可能还有更多人。知道了家庭成员,我们就可以确定家庭 f 与 Acme Bank 的整体关系。为此,规则 5 汇总了来自不同家庭成员的所有权金额,这些家庭成员可能通过所有不同的贡献共同控制资产。
是的,这是我们的案子!
我们最终可以得出结论,“坏人”并没有控制 Acme 银行,但是他通过他的黑手党家族隐藏了对 Acme 银行的控制。P2 直接拥有我银行 0.34%的股份,P1 间接拥有我银行 0.21%的股份,由 1%0.93%0.23%衍生而来。总的来说,f 家族控制着我的银行,拥有 0.55%的股份。反过来,我的银行通过金字塔股权结构控制 Acme Bank holding 0.52%的股份,这可能是为了混淆两家公司之间的联系。
f 家族控制着 Acme 银行,而“坏人”试图通过他的家族隐藏对 Acme 银行的控制。因此,这起案件的导火索,最初的 STR 只包含“坏人”向他间接控制的银行 Acme Bank 申请贷款的交易,可能是试图通过用假贷款证明不干净的钱是合法的来洗钱。对这一结论的总体信心取决于个人关系存在的确定性、关联预测模型的输出以及洗钱模式的内在可靠性。
但是,怎么可能呢?
请记住,这里的目标是决定这个 STR 的可疑性,并因此评估可疑性的分数。要算这笔帐,我们可以用这条规则:
这条规则告诉我们,我们的个人并不是 Acme 银行的最终受益所有人,但他的家庭作为一个整体是。此外,如我们所见,规则左侧的“w”控制着激活规则的偏向。在某种意义上,这是对规则重要性的一种度量,因此控制了可疑的可能性。
以下是用于解释这种情况的 11 条完整规则:
结论
在一个包含金融情报单位可用性常规数据的 AML-KG 中,仅激活 11 条规则,即使像左边这样的触发器如此之小且模糊,我们也可以解决一个复杂的金融情报谜题,其中包括:许多相互关联的实体、犯罪模式的许多可能变体(隐藏资产的最终受益所有人)以及严重犯罪,如勾结、腐败和有组织犯罪。
虽然金融分析师可以考虑这些因素,但是变量的数量、数据量以及数据的具体性质(大量的相互联系、高度周期性等)都是不可忽视的因素。)表明这是极不可能的,至少在合理的时间内是如此。
[## 埃莉诺拉·劳伦扎—中等
阅读埃莉诺拉·劳伦扎在媒介上的作品。人工智能博士研究员富布赖特数字…
medium.com](https://medium.com/@eleonora.laurenza)
关注我的 Medium 了解更多信息。
让我们也在 Linkedin 上保持联系!
参考
[1] L. Bellomarini 等人;金融情报机构基于规则的反洗钱:经验与愿景(2020);RuleML+RR。
[2] S. Ceri 等人;逻辑编程与数据库(2012);斯普林格。
[3]小伯乐;《现代公司和私有财产》(1932);加德纳。
[4] L .贝洛马里尼等人;vada log 系统:基于 Datalog 的知识图推理(2018);PVLDB。
[5]欧盟委员会;委员会向欧洲议会和理事会提交的报告——评估金融情报机构之间的合作框架(2019);
[6]路孚特:创新与打击金融犯罪。https://www.refinitiv.com/en(2019)。
[7] J .卡萨拉;“更新反洗钱法律以打击洗钱和恐怖融资(2017 年)国会证词:捍卫民主基金会”;https://www . judiciary . Senate . gov/IMO/media/doc/Cassara % 20 testimmony . pdf
[8]金融行动特别工作组;评估 FATF 建议技术合规性和反洗钱/CFT 系统有效性的方法 (2019)。
使用模块化神经网络进行推理
原文:https://towardsdatascience.com/reasoning-using-modular-neural-networks-f003cb6109a2?source=collection_archive---------55-----------------------
一种解决人工智能问题的创新解决方案
模块化背后的基本思想是:应对复杂挑战的最佳方法不是执行一个巨大的任务,而是一个由独立且基本独立的子任务组成的系统,这些子任务朝着一个大目标共同工作。这个概念有一个生物学基础。大脑中有专门的功能区域,它们是不同认知过程的特定领域。外侧膝状体(LGN)位于大脑的丘脑部分,分为几层,分别处理颜色和对比度:这两个视觉的主要组成部分。模块化神经网络利用这种思想解决复杂 人工智能问题。几个独立的神经网络被同时训练用于特定的子任务,并且它们的结果在最后被组合以执行单个任务。模块化神经网络的优势包括:
- 简单
- 技术组合
- 可量测性
- 效率
众所周知,人工智能天生没有语言,所以我们的工作就是训练我们的模型对给定的文本进行推理。所谓推理,我们指的是算术、排序、比较和计数等任务。
图 1:视觉问答是回答关于图像的问题的任务,以表明系统理解图像。
图 2:阅读理解是回答关于一段文字的问题,以表明系统理解了这段文字。
假设我们要创建一个问答系统,图 1 和图 2 说明了 QA 模型是如何工作的!
考虑这个问题“交通灯旁边的标志说什么?”在图 1 中。回答这样一个问题需要多个推理步骤:找到图像中的所有“标志”,找到“红绿灯”,选择“红绿灯旁边”的标志,然后找到“它说的是什么”。或者图 2 中的问题:首先我们需要找出给定文本中所有的逃课率,挑出最高的一个,然后找出“并列哪个区域”。我们希望开发能够理解此类复杂问题的组合语义的模型,以便提供正确答案。
NMNs 能够提供这样的推理。使用给定的问题,模型组装一个具体的网络架构,然后执行组装的神经模块网络以输出答案,如图 3 和图 4 所示。
图 3:对于每个实例,模型首先预测布局,然后使用图像特征,它执行组装的神经模块网络来输出答案。
图 4:对于每个实例,模型首先预测布局,然后使用文本特征,它执行组装的神经模块网络来输出答案。
布局预测器
为了解决质量保证问题,制作了许多不同的模型布局。最近一篇关于这一主题的文献综述发现,他们中的大多数在特定形式的问题上表现突出。创建灵活布局组件是为了利用所有这些不同的模型。为了找到特定问题 q 的最佳布局 l ,需要先计算概率分布 p(l||q),然后使用波束搜索,最大概率布局将在后面定义。假设每一层都是一系列模块:
由于我们有一个序列形式的模块,注意 LSTM 模型可以用来寻找每个可能的布局的概率分布。首先,我们把问题特征 fQ(q)交给 LSTM 模型来生成一个隐藏状态:
输入问题单词的注意权重被预测为:
其中 e_ti 为对准模型,其定义为
其中 h_i 和 h_t 分别是编码器和解码器的 LSTM 输出。则上下文向量被计算为
该上下文向量将用于计算下一个模块的概率
最后, l 的概率分布定义如下
模块
创建模块是为了独立执行基本的推理任务。把它们想象成接受注意力向量、文本或图像特征的函数,它们有一些内部参数来执行某种计算。让我们来看一些例子:
查找[x]
VQA 的 模块将输入图像中的每个位置与一个权重向量进行卷积(对每个 x 都不同)以产生一个关注。
查找最大数量
给定一段话,这个模块首先计算一个数字记号分布 T ,然后用这个来计算每个数字记号是具有最大值的那个的概率。
和/或
和 和 或 模块以两幅图像注意力为输入,分别返回它们的交集或并集。
重新安置
重定位模块将输入图像映射改变为新的注意力映射,这对于空间关系是有用的。
端到端培训
像其他神经网络一样,在训练过程中,目标是最小化损失。但这里不同的是,模型共同学习****预测布局** p(l|q)和各个模块中的参数。**
参考资料:
Hu R,Andreas J,Rohrbach M,Darrell T,Saenko K .学习推理:用于视觉问题回答的端到端模块网络。IEEE 2017 年计算机视觉国际会议论文集(第 804–813 页)。
用于文本推理的神经模块网络。arXiv 预印本 arXiv:1912.049712019 年 12 月 10 日。
Andreas J,Rohrbach M,Darrell T,Klein D .神经模块网络。2016 年 IEEE 计算机视觉和模式识别会议论文集(第 39–48 页)。
Hubel DH,Livingstone MS .猕猴外侧膝状体和初级视皮层的颜色和对比敏感度。神经科学杂志。1990 年 7 月 1 日;10(7):2223–37.
选择 PyTorch 进行深度学习的理由
原文:https://towardsdatascience.com/reasons-to-choose-pytorch-for-deep-learning-c087e031eaca?source=collection_archive---------31-----------------------
PyTorch 可以为深度学习程序员提供很多东西
在过去的几年里,深度学习和机器学习一直是每个人最热门的词汇,对此有一个完美的解释。
机器学习使系统能够从经验中学习,而深度学习通过使用扩展的数据集将机器学习带到了更大的规模。ML 和 DL 中的这种提升导致了各种编程语言****s和库的出现,并使程序员****研究人员和数据科学家实现了不可想象的事情。最佳深度倾斜库的一些最强有力的竞争者是和 PyTorch 。现在,我们将更多地关注 PyTorch。****
PyTorch
脸书在 2016 发布了针对编程场景的 PyTorch ,基于 Lua 的 Torch 库。
PyTorch 是一个免费开源的机器学习库,目前是1.4。PyTorch 已经出局快三年了,已经经历了大量的改进,现在处于一个更好的位置。PyTorch 被创造出来是为了感觉比其他对手更快、更敏捷。还包括对 C、C++和张量计算的支持。
谷歌趋势— PyTorch 兴趣随时间变化
谷歌趋势(来源)
选择 PyTorch 进行深度学习的理由
在解释为什么不应该尝试 PyTorch 之前,下面是一些独特而令人兴奋的深度学习项目和库 PyTorch 已经帮助诞生了:
● CheXNet: 利用深度学习对胸部 x 光片进行放射科医生级别的肺炎检测。
● 地平线:应用强化学习(Applied RL)的平台
● PYRO : Pyro 是用 Python 编写的通用概率编程语言(PPL),后端由 PyTorch 支持。
● 高岭土由 NVIDIA 作为 PyTorch 库,用于加速 3D 深度学习
● TorchCV 用于在您的项目中实施计算机视觉
● PyDLT 作为一套深度学习的工具
● fastai 库优化您的神经网络训练过程
● 还有很多。
这是一些构建在 TensorFlow 和 PyTorch 之上的框架和项目。你可以在 Github 以及 TF 和 PyTorch 的官网上找到更多。
PyTorch:一个开源的 ML 框架
在一个张量流的世界里, PyTorch 凭借自己的优势能够独当一面。以下是一些亮点,解释了 PyTorch 为什么适合您的深度学习项目:
1。 PyTorch 更是蟒
PyTorch 是一个 go to 框架,它让我们以更python 式的方式编写代码。此外,它支持使用简单的 python 代码的那种动态性是显著的。****
与其他库相比,PyTorch 更倾向于 Python。这是因为 PyTorch 相对来说容易理解,而且感觉更自然,原生和符合 Python 代码。对于任何使用过 Python 的人来说,他们会对 PyTorch 的一切如鱼得水,比如损失函数、优化器、转换、数据加载器和更多的类。
每个 PyTorch 示例(Vision 和 NLP)的代码共享一个公共结构:
PyTorch 示例(来源)
PyTorch 示例(来源)
2。 好用
与 PyTorch 相比,TensorFlow 的学习曲线相对较陡。Python 程序员将需要更少的时间来适应 PyTorch,因为对他们来说,它更像是 Python 框架的扩展。简单的调试和一套简单的 API 在让程序员更容易掌握 PyTorch 的过程中起到了关键的作用。
塞斯·梅耶斯 Boom GIF By 深夜与塞斯·梅耶斯
3.有用的库
巨大的社区支持带来了对社区的巨大热情和贡献。使用 PyTorch,程序员们已经创建了一些项目,任何有兴趣的人都可以一睹为快。下面是这些项目在不同领域的综合列表,如计算机视觉、自然语言处理和生成库:
● pro_gan_pytorch 利用 ProGAN 功能
●使用贝叶斯优化的 BoTorch
● ParlAI 用于共享、培训和测试对话模型
● OpenNMT-py 用于实现神经机器翻译系统
● MUSE 用于多语言单词嵌入
● skorch 用于将 scikit-learn 代码与 PyTorch 融合
4.轻松的数据并行
PyTorch 中的数据并行是高效的,并允许您将数据分成批次,然后发送到多个 GPU 进行处理。使用这种技术,PyTorch 可以将大量工作负载从 CPU 转移到 GPU。对于数据并行,它使用 torch.nn.DataParallel 类。
分布式数据并行是 PyTorch 的一项功能,您可以将它与数据并行相结合,以处理需要大型数据集和模型的用例,这些数据集和模型对于单个 GPU 来说足够大。当 GPU 池中的所有任务都完成后,结果会被收集、合并并通过数据并行发送给您。
Pytorch 数据并行(来源)
5.优秀的研究人员
PyTorch 是研究人员的天赐之物,因为它被证明被至少 70%从事框架工作的研究人员所使用。尽管 TensorFlow 是开发应用程序的行业领先选择,但在这方面还没有赶上 PyTorch。这背后的一个原因可能是 PyTorch 必须提供更好的性能的简单易用性。
做得好竖起大拇指 GIF 由新希望俱乐部
6.移动就绪
从 v1.3 开始,PyTorch 增加了对 Android 和 iOS 设备上部署的支持。该特性将 PyTorch 的所有优势带到了边缘设备,以满足要求更低延迟的应用。PyTorch mobile 的目标是通过支持移动平台的基础 API 来缩短开发周期,消除导出到 Caffe2 等移动框架的需要。这可以显著减少设备占用空间。为了更好的控制,还增加了对构建脚本精确微调的支持。
【PyTorch 手机入门:
开始使用 Android
开始使用 iOS
**** [## PyTorch
随着应用继续要求更低的延迟,在边缘设备上运行 ML 变得越来越重要。这也是一个…
pytorch.org](https://pytorch.org/mobile/home/)
7.简单调试
PyTorch 很容易调试,因为你可以选择访问每一行,并在每一行之后打印。锦上添花的是 PyTorch 中的对象和操作包含了实际数据而不是符号引用,这使得程序员的生活更加轻松。PyTorch 的一些标准调试器是:
● ipdb
● pdb
● PyCharm
比如说你可以使用 pdb 的“pdb.set_trace()”函数在你的代码中放置断点,向下钻取错误的根源。此外,PyTorch 的动态计算图允许在代码执行时进行动态修改和快速调试。
使用 pdb 进行 PyTorch 调试(来源)
8.支持 ONNX
开放神经网络交换 作为人工智能的开源生态系统,为 AI 程序员提供了一个可互换地在各种框架、工具和库上工作的公共基础。ONNX 通过提供一种跨多种框架和硬件工作的标准文件格式来做到这一点。
说到 PyTorch,ONNX 自带了对 PyTorch 的内置支持,以及一系列其他框架,比如 Caffe2、MXNet、TensorFlow 等等。ONNX 使得人工智能程序员更容易将他们的 PyTorch 模型导出和迁移到其他框架可以集成的开放格式。
PyTorch 原生 ONNX 支持(来源)
9.支持动态计算图形
PyTorch 将每个模型视为有向无环图,提供了一种定义计算图的动态方法。虽然其他框架允许静态图定义,但是 PyTorch 支持创建一个动态计算图,您可以在其中自由地操作它。从 PyTorch 的动态特性中获益最多的一个元素是递归神经网络。
10.强大的社区支持
PyTorch 还提供出色的社区支持。PyTorch 的主页有关于它每个特性的详细文档。库的所有最新更新都有很好的解释。随着每一个新的加入, 支持性教程 以及相关资源也可以找到,以获得那种宝贵的动手感受。
PyTorch 论坛是一个非常棒的地方,强烈推荐新手发表他们的问题,老手与其他程序员分享他们的想法。每天有一百多个帖子,这个社区非常活跃,鼓励人们加入 PyTorch。
这里有一些 PyTorch 开发人员社区、资源和教程来贡献、学习和回答您的问题——
● PyTorch 讨论表
● PyTorch Slack 社区
● PyTorch 示例
● PyTorch Docs
● Github Pytorch 教程
● PyTorch 初学者备忘单
● PyTorch 发行说明
●py torch 深度学习:60 分钟闪电战
● 使用 Colab 中 Google Drive 的教程数据
● 中文文档和教程
● 韩语教程****
结论
PyTorch 为深度学习程序员提供了大量直观的功能,可以为各种技能水平的人提供很多东西。尽管 PyTorch 提供了一个简单的入口点,但也不能掉以轻心,因为它提供的特性不仅在某些方面提供了更好的性能,而且还提供了额外的独特特性。我们讨论了 PyTorch 的一些最常被谈论的特性,以帮助您实现向 PyTorch 的转变,而您对此一直持怀疑态度。
更多有趣的阅读—
我希望这篇文章对你有用!下面是一些有趣的读物,希望你也喜欢
** [## 机器学习和深度学习的最佳 Python 库
现代机器学习模型和项目的 Python 库
towardsdatascience.com](/best-python-libraries-for-machine-learning-and-deep-learning-b0bd40c7e8c) [## 面向所有人的顶级谷歌人工智能工具
使用谷歌人工智能中心将想法变为现实
towardsdatascience.com](/top-google-ai-tools-for-everyone-60346ab7e08) [## 2020 年人工智能工程师的顶级编程语言
从几种编程语言中,人工智能工程师和科学家可以挑选出适合他们需要的语言
towardsdatascience.com](/top-programming-languages-for-ai-engineers-in-2020-33a9f16a80b0) [## 哪个深度学习框架发展最快?
TensorFlow 与 PyTorch
towardsdatascience.com](/which-deep-learning-framework-is-growing-fastest-3f77f14aa318)
关于作者
克莱尔 D 。是Digitalogy—的内容制作者和营销人员,这是一个技术采购和定制匹配市场,根据全球各地的特定需求,将人们与预先筛选的&顶尖开发人员和设计师联系起来。在LinkedinTwitterinsta gram上连接 Digitalogy 。**
代理损失函数对机器学习中的分类至关重要的原因
原文:https://towardsdatascience.com/reasons-why-surrogate-loss-functions-are-pivotal-for-classification-in-machine-learning-e33974ce6d29?source=collection_archive---------30-----------------------
作者图片—巴西卡诺阿·克夫拉达
这篇文章将深入探究机器学习中分类的铰链损失、逻辑损失和二进制损失背后的概念和理论。我们将在 MATLAB 上实现感知器算法,看看如何基于代理损失函数选择最佳分类器。
在这篇文章结束时,你将知道如何使用感知器进行分类,以及每个损失函数的优缺点。
资料组
我们将使用 N = 200 个数据点的三维数据集。这个数据集最初是由 Ruth Urner 博士在她的一次机器学习课程作业中提出的。在下面的库中,你会发现两个 TXT 文件: fg_inputs.txt 和 fg_outputs.txt 。
[## jaimedantas/感知器-分类
感知器算法用于机器学习中的线性分类。感知器在 MATLAB 上实现…
github.com](https://github.com/jaimedantas/perceptron-classification)
这些文件包含输入和输出向量。使用 MATLAB,我们可以在 Home > Import Data 中导入它们。现在,让我们绘制这个数据集。
数据集 FG
感知器
感知器算法是最古老的机器学习算法之一,至今仍被广泛使用。它用于不同类型数据集的线性分类。感知器是用于二进制分类的许多算法之一,它非常容易理解。我推荐阅读这篇简短的文章,这样你可以详细了解它是如何工作的。如果你真的想学习背后的数学,这些讲座可能会帮助你。
长话短说,感知器的工作方式是通过分析 x 和 w 乘以其标签 t 之间的点积信号。
每次 h(x) 小于或等于 0 ,我们就用一个新值更新 w 。
说的够多了,还是在 MATLAB 上实现吧!我在 MATLAB 上创建了一个实现感知器算法的函数。它接收输入矩阵 x 和标签向量 t 。我做的第一件事是在x【4】中添加一列 1。
然后,我将 x 和 t 连接起来。这样做的原因是因为这样会更容易打乱数据。我使用了 MATLAB 的函数 randperm() 对数据集进行混洗。之后,我用零初始化了向量 w 。由于我们正在添加术语 b ,即 w0 ,我将用b = 0【2】进行初始化。
我还在变量更新中跟踪算法在数据集上运行的次数。最后,在算法的最后,我执行了向量w【3】的欧几里德归一化。算法如下所示。
为了运行我们的函数,我们必须在 MATLAB 的命令窗口中执行命令【w,updates】=感知器(输入,输出)。
感知器函数将返回标准化向量 w 和执行的更新次数。
替代损失函数分析
为了计算损失,我执行感知器函数 20 次,每次用存储向量。我还在矩阵中添加了一列 1
让我们首先计算预测值的经验二进制损失,并在向量二进制损失中对它们进行平均。这个损失函数由下面的等式给出[4]。
对铰链损失进行相同的处理。然而,这一次的损失由下式给出:
最后,我计算了物流损失。
为了分析这个数据集的训练损失,我创建了compare _ loss . m脚本来绘制 20 次执行的三次损失。
下图的左图显示了 20 次执行的损失。从那里,我们可以注意到,二进制损失是所有三个损失中最小的。此外,替代损失是一个更加明确的指标,现在我们的分类器的“好”。当我们看一看执行 i = 17 和 i = 18 时,我们就能明白其中的原因。虽然它们的二进制损失大致相同,但后者的铰链和逻辑损失明显小于前者。这是因为替代损失是分类器与其在两个类中最接近的数据点之间的距离的指示器。因此,位于错误一侧的数据点会造成很大的枢纽和逻辑损失。如果数据点被正确分类,但它非常接近线,则替代损失不像二进制损失一样为零。所以, i = 18 的分级机比 i = 17 的分级机好。
左边是感知器算法的 20 次执行的二进制损失、铰链损失和逻辑损失,以及感知器算法在 200 个数据点上的一次执行(w1)的二进制损失、铰链损失和逻辑损失。根据compare _ loss . m脚本绘制。
当我们观察点 i = 4 和 i = 5 时,可以进行另一个很好的比较。前者具有较小的二进制损失,而后者具有较小的铰链和逻辑损失。所以,从这个分析来看, i = 5 中的分类器可能比 i = 4 更好。这使我们得出结论,物流和铰链和损失是独立于和损失的。我们也可以说这两个替代损失是相互独立的。当我们观察他们在点 i = 12 和 i = 13 所采取的相反方向时,这一点可以得到证明。
转到上图的右图,我们可以看到,当我们对一个数据点进行错误分类时,后勤损失和枢纽损失都给了我们很大的损失,当我们正确分类时,后勤损失接近于零,枢纽损失接近于零(当 t⟨ w , x ⟩ ≥ 1 时)。另外,我们可以得出结论,当 t⟨ w , x ⟩在 0 和 1 之间时,铰链不为零。这是因为数据点太靠近分类这两类的线[5]。
另外,当数据点分类正确但离线太近时,铰链损耗给我们一个小值。类似地,当数据点被错误地分类并且它位于离线太远的位置时,铰链和逻辑损耗给我们一个非常大的值。事实上,对于 t⟨ w 、 x ⟩的大负值,两个损失都变成平行线[5]。
对于错误分类的数据点,逻辑损失遵循铰链损失的趋势。然而,对于正确分类的数据点来说,它永远不会为零,如上图右侧的图表所示。类似地,对于太靠近线的数据点,逻辑损失分配接近 1 的误差。
最后,铰链损耗是二元损耗的上界,它比二元损耗更能证明真实损耗。下面我们可以看到每种损失类型的最小损失值。
最小损失
结果显示,二进制损失确实是最小的损失,而且是在执行中发现的 i = 1 。然而,最小的铰链和后勤损失是在执行 18 中发现的。这突出了使用代理函数进行二元分类的重要性。因此,给我们最小二进制损失的分类器并不总是理想的分类器。
使用 MATLAB
出于好奇,我决定将我们的结果与 MATLAB 上的一个现成实现进行比较。我在 MATLAB 上运行这个数据集,并使用分类线性模块拟合一个具有 20 个交互的线性分类器。下图显示了学习者的分类错误。
MATLAB 在数据集 FG 中进行 20 次交互的线性分类的最小分类误差。
正如我们所见,MATLAB 拟合了一个误差为 0.135 的分类器,这恰好与运行我们的感知器算法相同。重要的是要记住,在 MATLAB 上进行比较时使用的学习算法不是感知器。我只是想说明我们的感知器实现为这个数据集估计了一个非常好的分类器。
结论
我们看到,与铰链和逻辑损失不同,当我们正确分类所有数据点时,二进制损失总是 0 。逻辑和枢纽损失表明预测者实际上“有多正确”或“有多错误”。这就是为什么最挑剔的数据点和分类器线之间的距离会影响整体损失。
因此,当选择最佳分类器时,分析替代函数被证明是最重要的,特别是当二元损失不是 0 时。
最后,我们看到了如何在 MATLAB 上实现 D+ 1 维空间的感知器算法。
关于我
我是约克大学的一名硕士研究生,骨子里是一名软件工程师。在过去的十年里,我一直在软件开发、云计算和系统工程等领域的几个行业工作。目前,我正在研究云计算和分布式系统。
如果你愿意,可以在我的网站上查看我的作品。
感谢阅读!
参考
[1]约西·凯舍特。多类分类。2014.网址:https://u . cs . biu . AC . il/~ JK eshet/teaching/AML 2016/multi class . pdf
[2]道林·耶戈。感知器:解释,实现和一个可视化的例子。2020.网址:[https://towardsdatascience . com/perceptron-explain-implementation-and-a-visual-example-3c 8e 76 B4 e 2d 1](https: //towardsdatascience.com/perceptron-explanation-implementation-and-a-visual-example- 3c8e76b4e2d1)
[3]玛丽娜·桑蒂尼。语言技术的机器学习第 9 讲:感知器。2014.网址:【http://santini.se/teaching/ml/2014/Lecture09_Perceptron.pdf
[4] Shai Shalev-Shwartz 和 Ben-David。理解机器学习:从理论到算法。剑桥大学出版社,2014 年。DOI: 10.1017/CBO9781107298019。网址:【https://www . cs . huji . AC . il/~ shais/understanding machine learning/understanding—机器学习—理论—algorithms.pdf。
[5]基利安·温伯格。经验风险最小化-康奈尔大学。2020.网址:https://www . cs . Cornell . edu/courses/cs 4780/2018 fa/lectures/lessons note 10 . html
数据科学项目的秘诀
原文:https://towardsdatascience.com/recipe-for-a-data-science-project-69ad5c5ecf29?source=collection_archive---------28-----------------------
数据科学项目是小菜一碟吗?看看我关于如何处理它的完整的 6 步指导。
照片由凯特琳娜·奥兹勒
根据我的经验,在下面的文章中,你会读到数据科学项目从开始到生产的阶段和活动。
阅读本文时,请记住以下两个信息:
- 下面的每个活动代表一组相似的活动,因此它们可以被视为任务组。
- 没有一个阶段可以一次通过。总会有迭代。
一个天真的想法是,数据科学项目主要由预测建模组成。当然不是,尤其是在企业公司。有许多你必须采取的步骤和你必须面对的困难。因此,创建了一些过程框架,以使数据科学项目更易于管理,并防止失败。数据科学项目最著名的流程之一是 CRISP-DM 。它将数据科学项目的过程分为以下 6 个阶段。
我更喜欢用非常相似但阶段略有不同的东西来描述整个过程:
- 评估价值:了解业务,评估是否值得继续,确定项目范围
- 数据准备:理解数据,准备必要的结构,数据传输,数据预处理,特征工程
- 建模:建模、模拟、评估结果
- 软件开发:开发 API、仪表盘、报告、通知、模拟&管理应用,部署&与现有产品的集成
- 监控 : A/B 测试,监控和评估试点阶段,推广
- 参与:让所有利益相关者相信项目的好处,并让他们参与进来
在讨论各个阶段之前,让我简单介绍一下总的完成时间。根据我在企业中的经验和观察,一个数据科学项目需要 3 到 6 个月。请记住,这只是一个简单的平均数,有些情况下需要一年以上的时间。
第一阶段:评估价值
- 我相信这是数据科学项目中最重要的部分。
- 它可能更短或更长,但我认为 2 周是这个阶段的平均持续时间。
- 产品所有者和数据翻译是关键角色。
该阶段的主要活动:
- 借助一些可视化的帮助来理解当前的状态。
- 在当前状态下找到一些难点或机会,并创建项目范围以从中获得价值。
- 定义目标变量。客户流失案例的一个例子是“如果客户关闭其账户,或者如果客户账户的总余额下降到 xxx 美元以下,并且每月交易次数低于 yyy。”。我们将这些客户标记为 1,将其他客户标记为 0。
第二阶段:数据准备
- 这个阶段消耗了项目中 60%到 80%的与数据相关的任务,任务真的不好玩。
- 可能需要 4 到 12 周。
- 数据工程师是关键角色。
该阶段的主要活动:
- 在源代码管理中创建项目的文件结构
- 决定项目中将使用哪些数据源,并创建数据字典的第一个版本
- 将数据从其源传输到分析环境
- 通过移除一些字段、将表连接在一起以及创建新要素来为建模准备数据集
第三阶段:建模
- 数据项目中最酷的部分。创建预测模型并评估其结果是一件令人愉快的事情。
- 它可能更短或更长,但我认为 2 周是这个阶段的平均持续时间。
- 数据科学家是关键角色。
阶段主要活动:
- 创建一个简单的基线模型,让每个人都开始谈论它
- 选择适当的模型来权衡性能和可解释性
- 深入研究数据,非常清楚地了解数据的每一部分
- 特征选择
- 交互效度分析
- 调谐
- 评估结果
阶段 4:软件开发
- 在这一部分,人们意识到几乎每个数据项目都是软件产品的一部分。
- 如果是最简单的情况,只发送一些报告就足够了,可能只需要 1 周。另一方面,如果你开发一个 api、仪表板、模拟和管理应用程序,那么它甚至需要 12 周。
- 软件开发人员是关键角色。
该阶段主要活动:
- 开发 API,将模型作为服务向世界开放
- 开发仪表板,以便在推出新模式后监控业务
- 创建报告以观察推出过程并评估新模型的生产寿命
- 实现模拟和管理应用程序,让业务利益相关者输入模型所需的参数,并进行模拟,以便能够进行假设分析。
- 部署组件并将其与现有产品集成
第五阶段:监控
- 这个项目最激动人心的部分是因为所有的参与者都开始观察模型在生产中的结果。
- 我经历的最短持续时间是 12 周,根据具体情况,可以延长到 1 年。
- 每个人都在船上。
该阶段的主要活动:
- 通过控制新型号的性能来观察其生产寿命。
- 通过观察和评估控制组和试验组的结果来执行 A/B 测试。
- 为接下来的推广步骤做出可行/不可行的决策。
第六阶段:参与
- 根据利益相关者的保守程度,这可能是项目中最具挑战性的部分。
- 它从第 0 天开始,在项目结束时团队被释放时结束。
- 产品所有者和数据翻译是关键角色。
该阶段的主要活动:
- 向所有利益相关者解释路线图。
- 让他们参与所有可能的工作。
- 帮助他们将当前的业务流程升级到基于人工智能的流程。
总之,
如果您让我说出三个关键要点来最大限度地降低数据科学项目的失败风险,我会说:
- 找到合适的案例/问题来解决(最重要的事情),
- 关注那些对人工智能有远见或者至少不反对人工智能的利益相关者的案例,
- 不要陷入忽视软件开发工作和部署复杂性的陷阱。
如果你有任何进一步的问题,请不要犹豫,写信给:haydarozler@gmail.com。
食谱大师,一个基于自然语言处理的食谱推荐网站
原文:https://towardsdatascience.com/recipe-guru-a-recipe-recommendation-web-app-based-on-nlp-a3290d79da2f?source=collection_archive---------35-----------------------
在这篇博文中,我将回顾一下我的食谱推荐网络应用“食谱大师”的流程和技术细节,以及一些代码片段。
贝卡·泰普特在 Unsplash 上拍摄的照片
“食谱大师”使用 NLP 技术来推荐人们可能喜欢的相似食谱,目前基于食谱 1M+中的 18000 个食谱。在引擎盖下,这个网络应用程序使用 Recipe 1M+数据和自然语言处理(NLP)模型,根据用户喜欢的食谱推荐食谱。
它使用相似性矩阵来记录基于标题、成分和说明的食谱之间的相似性。单词袋(BoW)、Doc2Vec 和 BERT(来自变压器的双向编码器表示)模型用于估计配方之间的相似度,并提供配方推荐。(这是我的中型博客文章,谈论 BERT 和其他最近的 NLP 技术,包括 XLNet。)
“食谱大师”的主页,基于三种 NLP 技术提供不同的厨师推荐选项。
关于数据集
对于这个项目,我使用了来自麻省理工学院研究人员的 Recipe 1M+数据集:一个新的大规模结构化语料库,包含超过 100 万份烹饪食谱和 1300 万张食物图片。数据集可用于 NLP 和 CV 项目。这里,我们将重点放在包含以下信息的文本菜谱(来自 JSON)上:菜谱 URL、标题、id、配料和说明。
预处理步骤将 1M+食谱中的每一个的标题、配料和指令组合成一个字符串,并且在干净的数据集上应用不同的自然语言处理技术来生成嵌入和余弦相似性矩阵。
余弦相似矩阵
由于余弦相似性矩阵的大小很大,我没有使用 sklearn 函数“metrics.pairwise_distances”和 scipy 的“spatial.distance.cosine”来获得成对余弦相似性,而是使用 TensorFlow 和 GPU 来加速余弦相似性矩阵计算,并尝试使用 Spark 分布式计算。
1。用张量流得到余弦相似矩阵:
关于存储大的余弦相似性矩阵(对于具有 20k 食谱信息的 20k * 20k 矩阵来说需要几个 GB),有效存储它的一种方式是通过将矩阵转换成稀疏矩阵来保持非零条目的索引。您可以在 SciPy 文档中查看更多关于处理稀疏矩阵的信息。
保存稀疏矩阵的一个例子
由于我将部署 web 应用程序以及腌余弦相似性矩阵,我担心大文件大小(1–2gb)。因此,在转换为 csr_matrix 之前,如果得分不在前 10 名,我将菜谱与目标菜谱的相似性得分设置为 0。那么我们只需要 pickle ~recipe_num * 10 个压缩稀疏行格式化矩阵中的元素。文件大小从 1.67 GB 到 2 MB 😄。顺便说一下,我今天在他处理大型 NLP 数据文件的旅程中遇到了这个中型帖子,希望它也可以帮助你,如果你正面临类似的部署问题。
sparse.csr_matrix(sim_matrix)
# <18000x18000 sparse matrix of type '<class 'numpy.float32'>' with 202073252 stored elements in Compressed Sparse Row format># Let's keep top 10 elements of each row whose indices are of the recipes to be recommended.for i in range(len(sim_matrix)): row = sim_matrix[i] # cos sim of top 10th element threshold = heapq.nlargest(10, row)[-1]
row[row < threshold] = 0sparse.csr_matrix(sim_matrix)
# <18000x18000 sparse matrix of type '<class 'numpy.float32'>' with 202070 stored elements in Compressed Sparse Row format>
2。使用 PySpark 计算余弦相似度:
在 Colab 中使用 PySpark 进行分布式计算,使用以下代码:
为了获得相似性矩阵,使用三种不同的 NLP 方法来表示配方:
- 一堆话。
- Doc2Vec。
- 伯特。
我们将在下一节讨论这三种方法。
首先,我们先来看看“食谱大师”的主要功能:
主应用首先提供从 Recipe 1M+数据集中随机选择的 10 个食谱。用户可以选择一个或多个食谱并要求推荐。他或她也可以要求其他食谱收藏,直到看到那些有趣的。
在这里,如果我们选择“红烧鸡肉”,单词包模型将为我们带来以下选择,您可以继续选择,基于这些,web 应用程序将推送新的食谱推荐。如你所见,建议的食谱与最初的选择相似。
基于词汇袋模型的建议
在下面的例子中,我将挑选 3 个我喜欢的食谱,看看我们会得到什么:
不错,推荐的食谱也大多是甜点。BoW 在使用 BoW 向量表示来测量来自不同食谱的短文本的相似性方面是简单且有效的。特别地,计数矢量器方法用于表示配方。然而,BoW 的一个缺点是它丢失了关于词序的信息。由于数据稀疏和高维数,我没有使用可以帮助捕获局部词序的 n-grams 模型的包。
Doc2Vec 是使用无监督学习来测量两个文档之间的相似性的另一个选项。它将每个文档表示为一个向量,并提供文本文档的数字表示。与表示单词概念的 word2vec 不同,doc2vec 为每个文档生成试图使用固定长度向量来表示文档概念的向量。这里,使用的配方 1M+数据子集不同于 Doc2Vec 使用的子集,也包括 18k 配方。该方法也相当简单。我使用 Gensim 的 Doc2Vec 类在数据集上训练并获得嵌入,训练期间隐藏层大小为 512。得到的矩阵具有 1028702 * 512 的维度。对于这个项目,我从矩阵中取出前 18k 行,作为 Doc2Vec 食谱推荐器中包含的食谱的嵌入。
不像 BoW 的推荐在菜谱名称中显示相似或相同的单词,Doc2Vec 的推荐更加多样化。这里有一个例子:
由 Doc2Vec 提供支持
以下是基于“火腿、羊乳酪和桃子沙拉”和“四种奶酪烤蔬菜”的推荐。我们可以在食谱上下文/语义方面找到更多的相似之处。
更多关于伯特来,而我正在完成应用程序:D..
工作流程的一些注意事项
下面的标准 Lang 类用于根据原始食谱创建单词字典。这在预处理配方语句数据时很有用。
对于这个项目,使用来自 Recipe 1M+的 Layer1.json 文件。初步探索性分析显示有 1029720 个食谱,下图显示了食谱字数的直方图。
为了便于分析,在下游处理中使用了 1029662 个小于 300 字的食谱。
“det_ingrs.json”提供了 51213 个食谱的营养信息,我将在 web 应用程序的下一步中加入这些信息,因此用户可以根据营养要求筛选食谱。
“食谱大师”网络应用程序是使用 Flask 构建的。
食谱推荐系统
原文:https://towardsdatascience.com/recommendation-system-for-cookbooks-439795005bab?source=collection_archive---------19-----------------------
来源
使用亚马逊书评的案例研究
1.介绍
自从我开始看《伟大的英国烘焙秀》后,我不断增加的烹饪书收藏中又增加了三本。我会烘焙吗?不,先生,我没有!至少不是很熟。我并不是唯一痴迷于烹饪节目和烹饪书的人。根据 NBCNews.com 的数据,2018 年大约售出了 1800 万本烹饪书,至少在过去两年中,烹饪书的年销售额增长了 21%或以上[1]、[2]、[3]。这些书的格式也发生了变化——更多的光面纸和图片,而不是记录食谱的冗长文本。
那么,我们如何找到我们的食谱呢?当然,我们从 Amazon.com 评论开始!结合我对烹饪书的迷恋和对数据科学的热情,我试图通过建立一个基于 Amazon.com 图书收藏和用户评级的推荐系统来帮助我的烹饪书爱好者朋友找到他们的下一次购买。我使用了自然语言处理(NLP)方法和无监督学习来将书籍聚集在一起,以找到主题和子主题。
还有谁会从这样的推荐系统中受益呢?希望通过向客户提供适当且相关的图书建议来增加在线销售的供应商。以及空间有限的小型商业书店,因此他们可以挑选与以前销售情况相似的书籍。
2.方法
我的方法包括建立一个混合推荐系统,它结合了:
- NLP 主题建模技术,分别使用书名和图书描述构建两个基于内容的推荐系统
- SVD 矩阵分解技术(类似于 Simon Funk 因 Netflix 奖而推广的方法),用于使用用户对烹饪书的评级来构建协作推荐系统。
2.1 数据集
来自 Amazon.com 的用户评级和产品信息的收集可从加州大学圣地亚哥分校计算机科学系获得[4]。这个数据集从 1996 年到 2018 年,被修剪成只包括烹饪书评论。这导致了大约 45,000 本烹饪书,其中 29,000 本(65%)没有用户评级,其余的大约 16,000 本烹饪书有 428,000 个评级。Amazon 数据集由两个 JSON 格式的独立数据文件组成:
- 用于菜谱 标题和描述 的产品表,以及
- 点评表用于提取 用户评分 。
请注意,此分析没有使用用户评论,只使用了用户评级。可以想象使用评论文本建立一个基于内容的推荐系统,也许这将是这个项目的扩展。
下图 1 展示了 Amazon.com 网站上用于分析的数据。
图 1:一个样本食谱数据点
2.2 建模步骤
数据处理和建模涉及多个步骤,每个步骤都有如下变化:
在降维步骤之后,测试了 K-means 聚类算法,但是后来确定它对食谱推荐系统不是太有益。在搜索空间中有大约 45,000 本烹饪书,如果有一百万个产品要通过 K-means 来查找,将有利于减少搜索空间。
产生最佳结果的模型(从质量上来说)是 TF-IDF 和 LSA 的结合。在执行这些步骤时使用了许多工具和技术,其中包括:
- 计算机编程语言
- Sci-kit 学习
- 熊猫
- 惊喜,Python 的推荐系统引擎
- 自然语言工具包
作为该项目的一部分构建的三个推荐系统如下所示。请注意,每个推荐系统都是不同的,并且不共享任何输入。这是为了最大化模型可以从每一个输入类别中学习到的东西。考虑的另一种方法是告知每一步前面的步骤学到了什么,但这使得该方法比这个项目的范围稍大,我希望在以后的日子里探索这一点。
图二:三个推荐系统
我很乐意仅仅使用烹饪书的标题来构建一个推荐系统。烹饪书的标题旨在吸引注意力,而且亚马逊上的标题往往包括副标题,甚至更多一点的描述,以便在搜索中可见。但是我不建议对其他类型的书籍使用标题。举个例子, 由 变成 米歇尔奥巴马 不会只根据标题找到它的邻居。
其他数据探索
为了更好地理解主题建模空间,通过将十维空间投影到两维空间上,对维度的一些选择组合进行了降维步骤的额外探索。
我的直觉是,书名承载着与书籍描述不同的“高质量信息”,因为书名应该简洁、吸引人、切中要害。烹饪书的标题由作者和出版商仔细审查、编辑和营销,比烹饪书的描述更有分量。另一方面,书籍描述承载了更多的“信息量”,因为它们使用了更多的词汇,并且更有可能将不同的概念联系起来。以下两个数字证实了这种直觉,因为 LSA 之后的书名的投影空间是清晰、干净和鲜明的。另一方面,LSA 之后书籍描述的投影空间扩展并具有交叉分支/斑点(图 4)。
图 3:LSA 之后的食谱标题的维度空间:从 10 维空间中选择投影(颜色基于 K-Means 算法,仅用于说明目的)
图 4:LSA 之后的食谱描述的维度空间:从 10 维空间中选择投影(颜色基于 K-Means 算法,仅用于说明目的)
3.模型结果
对于两个基于内容的推荐系统,模型结果以定性的形式呈现:阶段 1 和阶段 2。针对第三阶段基于模型的协同推荐系统,对两个“朴素”模型进行了定量比较。
对于这两个基于内容的推荐系统,一种方法是引入不在训练集中的新食谱,并检查推荐的“相关性”。相反,我采取了更具探索性的方法:
1.从训练数据中随机选择一本书,
2.找到基于余弦相似性确定的最近邻居,
3.显示这些邻居的书的封面,并从视觉上检查书籍类别/主题。
这种探索性的方法提供了一种发现推荐系统从食谱中学到了什么的方法。
至少可以说,结果相当令人着迷。我将尝试在这一节中直观地展示这些。正如图 3 和图 4 所预期的,这种探索性的方法也揭示了书名倾向于推荐“狭窄”范围的选项,而书籍描述提供了更广阔的视角。
基于内容的推荐系统经常遭受“信息限制区域”问题,其中相同的项目被重复地建议给用户。这个问题导致错过了帮助用户探索他们可能感兴趣并且可能已经导致购买的更多项目的机会。对食谱使用两种不同的推荐系统肯定会解决这个问题。
3.1 结果:使用书名的基于内容的推荐系统
该模型发现了烹饪书的许多主题和子主题。有许多类别,探索模型所学的所有内容是不切实际的!!一些突出的类别如下:
- 蛋糕
- 纸杯蛋糕
- 标题中有糖的甜点
- 糖果
- 葡萄园
- 葡萄酒和食物
- 啤酒
- 鸡尾酒
- 海味
- 高压锅
- 电炖烧锅
- 意大利的
- 沙无然食物(包括美国南方食物和意大利南方食物!)
- 柴&茶
图 5:使用书名的基于内容的推荐系统
3.2 结果:使用图书描述的基于内容的推荐系统
模型发现的几个类别是:
图 6:使用图书描述的基于内容的推荐系统
3.3 结果:使用图书用户评级的协作推荐系统
协同推荐系统是利用西蒙·芬克因网飞奖而推广的奇异值分解矩阵构造的。这一步使用了 Python 的推荐系统 machine Surprise。将结果与两个简单的解决方案进行比较:
- 向每个人推荐每本食谱。因为每个人都喜欢烹饪书!对于每一个用户,每一本烹饪书来说,这是一个 5 星级的评价
- 朴素模型#2 向每个用户推荐平均图书评级
模型结果只比上面两个简单的解决方案稍微好一点。各型号的 RMSE 如下所示:
- 模型 RMSE = 0.92
- 天真模型#1 RMSE = 1.13
- 简单模型#2 RMEE = 0.93
4.结论
构建上述推荐系统的主要结论是:
- 仅仅使用标题,主题建模就有惊人的效果!
- 与基于标题的推荐系统相比,使用书籍描述进行主题建模使主题多样化
- 拥有多个推荐系统(在上面的例子中使用 tiles & description)有助于使用户推荐多样化
- 大多数亚马逊对烹饪书的评价都很高——每个人都喜欢烹饪书。这意味着,一个协作推荐系统可能会过度适应更高的评级,并需要更先进/彻底/智能的方式来处理它。
5.参考
[1]米歇尔·梅纳德(Micheline Maynard),烹饪书销量激增,这对专营烹饪书的商店来说是个好消息(2019 年 3 月),福布斯。
[2] Ed Nawotka,美食书店喂饱本地人的胃口(2019 . 03 . 01)出版人周刊。
[3]玛莎·c·怀特(Martha C. White),成功的秘诀:烹饪书的销售在向数字媒体的转变中幸存(2018 年 8 月 14 日),NBCNews.com。
[4]朱利安·麦考利&简墨·尼,UCSD,亚马逊评论数据(2018) ,GitHub。
[5] Baptiste Rocca,推荐系统介绍,一些主要推荐算法概述。中/走向数据科学篇。
原载于https://mlbhanuyerra . github . io。
GitHub 回购:https://github.com/mlBhanuYerra/Metis_Prj4/tree/master/code
YouTube 上相似内容创建者的推荐系统
原文:https://towardsdatascience.com/recommendation-system-for-similar-content-creators-on-youtube-3fed96b3c783?source=collection_archive---------34-----------------------
使用无监督的机器学习算法为任何给定的 YouTube 频道推荐相似的内容创建者
照片由 今敏 上 下
YouTube 是任何有空闲时间的人都会去的网站之一。从观看随机视频到学习新事物,YouTube 在我的生活中发挥了非常大的作用。我喜欢 YouTube 的一个原因是它拥有种类繁多的内容创作者。从播客到 ASMR 视频,YouTube 应有尽有。
虽然 YouTube 有一个很棒的推荐系统,可以根据用户的历史和类似用户观看过的内容来推荐视频,但是,假设对于一个给定的 YouTube 频道名称,如果我们想知道其他 5 个类似的 YouTube 频道(根据它们创建的内容),那么没有任何平台可以让我找到这些(而不必观看 YouTube 上的每个视频)。例如,如果我们更喜欢一个上传旅游博客的用户,比如说我想知道其他 5 个上传旅游博客的类似内容创建者,那么我将不得不根据他们创建的内容建立一个推荐系统,而不是依赖 YouTube 在我的 feed 或“up next”部分自动推荐他们,并观看每一个视频。下面是我试图建立一个简单的推荐系统来做到这一点-
网上没有任何数据集包含你的土豆的名字和他们创造的内容。我们可以获得任何 YouTube 频道的视频内容细节的一种方法是抓取他们在视频中提供的字幕(因为他们在视频中输入的标签可能不会准确地了解视频中的内容,并且不是每个内容创作者都为他们的视频添加“标签”)。假设一个 YouTube 频道谈论或评论汽车,那么他们视频中的字幕将包含重复的关键词,如“马力”、“发动机”等。甚至像“大众”这样的品牌名称。对于这种方法,我们首先需要所有(或受欢迎的)YouTube 频道的名称,为了获得这些名称,我们可以使用这里的数据集。这个数据集包括几个月的 YouTube 每日趋势视频数据。数据分别来自美国、英国、德国、加拿大和法国(但我只使用了美国和加拿大,即 CAvideos.csv & USvideos.csv)。让我们用 python 导入这些 CSV 文件,并将它们附加到一个数据帧中
**import os
import pandas as pd
directory = os.getcwd()
df_1 = pd.read_csv(directory+"/USvideos.csv")
df_2 = pd.read_csv(directory+"/CAvideos.csv")
df= df_1.append(df_2)
df[["video_id","channel_title"]].head()**
我们数据集中的前 5 行(作者图片)
我们使用这个数据集只是为了获得 YouTube 频道的名称和那些出现在 YouTube 的趋势视频标签中的视频的视频 ID。一旦我们有了视频 ID 和 YouTube 频道名称,就可以使用YouTube-抄本-api ,我们可以创建一个函数来遍历数据集中的所有视频 ID。csv 文件),我们可以检索数据集中提到的所有视频 ID 的字幕,然后将它们存储在. csv 文件中。
**!pip install youtube_transcript_api # install youtube_transcript_api
import pandas as pd
import os
import re
import csv
import numpy as np
directory = os.getcwd()
from youtube_transcript_api import YouTubeTranscriptApi #this library that will retrieve the subtitles from a video in the form of list of dictionaries****#Creating a function that will iterate through the data-set and get the subtitles from each of the video ID's available
def converter(x):#function will take an input as a data-frame
array = x.to_numpy() #convert to array
for i in range(len(array)):
try:
video_id=str(array[i][0])
Channel_name = array[i][3]
subtitles_1 = YouTubeTranscriptApi.get_transcript(video_id,languages=['en']) #obtain the subtitles in the video
first=''
for g in range(len(subtitles_1)):
first += " "+str(next(iter(subtitles_1[g].values()))).replace("\n"," ")
subtitles_2= first #sanitize the subtitles
subtitles_3=' '.join([i for i in subtitles_2 if not i.isdigit()]) #remove numbers as they are not relevant
subtitles = re.sub('[^A-Za-z ]+','',subtitles_3)
print(subtitles)
except:
subtitles=''
Channel_name=''
subtitles_part_one = subtitles[0:20000]
subtitles_part_two = subtitles[20001:40000]
subtitles_part_three = subtitles[40001:len(subtitles)]
with open(directory+'/Subtitles.csv', 'a',encoding='utf-8') as newFile:
FileWriter = csv.writer(newFile)
FileWriter.writerow([Channel_name+"|"+subtitles_part_one+"|"+subtitles_part_two+"|"+subtitles_part_three])
converter(df)#pass the data frame to the function
#Note the above function takes around 10-12 hours to run completely**
一旦我们运行上面的代码,我们将得到。csv 文件,其中一列包含内容创建者的姓名,另外三列包含每个视频的字幕。现在让我们用 python 导入这个文件,并查看数据的前 5 行
**data=pd.read_csv(directory+'/Subtitles.csv',sep="|",skiprows=0,header=None)
data = data.replace(np.nan, '', regex=True)****data["Text"] = data.apply(lambda x: f'{x[1]} {x[2]} {x[3]}', axis=1) *#combining subtitles from three columns*****data=data.drop([1,2,3],axis=1)** **data =data.rename(columns={0:'Name'})****data.head()**
“名称”栏包含你的土豆名称,“文本”栏包含每个视频的字幕。(图片由作者提供)
正如您在上面的图像中看到的,文本列包含小写和大写的文本,还包含停用词。以上数据需要清理,以便我们获得一些关键的见解。
下面我们整理数据集-
***#Convert text to upper case*
data["Text"]=data["Text"].str.upper()*****#remove words of length less than 2 (as they will not be relevant)*
data["Text"]=data["Text"].apply(lambda x: ' '.join([word for word in x.split() if len(word)>2]))**
由于 one You Tuber 有多个视频,我们需要将多个视频的字幕连接起来,放在一行。下面是实现这一点的代码:
**grouped_df = data.groupby("Name")****grouped_lists = grouped_df["Text"].agg(lambda column: "".join(column))****grouped_lists = grouped_lists.reset_index()**
在下面的代码中,我们使用“TfidfVectorizer”来获得每个文档中每个单词的总权重,即我们的例子中的字幕。术语频率-逆文档频率是一种统计数据,它强调某个单词相对于文档集合中所有单词的重要性。使用“TfidfVectorizer ”,每个单词的值与计数成比例增加,但与语料库中单词的频率成反比。这种相反的文档频率将适应某些单词通常频繁出现的事实。例如,由于我们的数据基本上是每个视频的字幕,“the”、“we”和“you”等词的频率会经常出现,但是,它们并不能真正告诉我们视频中的内容。我们使用“TfidfVectorizer”来获取每个单词的权重,它将返回每个频道字幕中每个单词的 TF-IDF 值的稀疏矩阵。这将有助于我们找到那些使用类似词语如“播客”、“烹饪”等的人。(我们目前只采用单个单词,但是也可以通过改变下面代码中的“ngram_range”参数来使用单词的组合)
警告——在“min_df”中提供较小的值将增加稀疏矩阵的形状,导致内存负载,因此建议相应地调整“min_df”。
**from sklearn.feature_extraction.text import TfidfVectorizer****from nltk.tokenize import RegexpTokenizer*****#tokenizer to remove unwanted elements from out data like symbols and numbers*
token = RegexpTokenizer(r'[a-zA-Z0-9]+')*****#Convert the collection of subtitles to a matrix of TF-IDF features*
cv = TfidfVectorizer(analyzer='word',stop_words='english',tokenizer = token.tokenize,min_df =1,ngram_range = (1,1))****text_counts= cv.fit_transform(grouped_lists['Text'])****print('the shape of the sparse matrix is',text_counts.shape)**
下面是我们稀疏矩阵的形状-
作者图片
k-最近邻(KNN)
现在我们到了有趣的部分,即实际构建模型。为此,我们将使用 NearestNeighbors,这是一个用于实现邻居搜索的无监督学习器。下面是代码:
**from sklearn.neighbors import NearestNeighbors****model = NearestNeighbors(metric='cosine',algorithm='auto',n_neighbors=5)****model.fit(text_counts)**
就这样…我们完了!!
照片由 安布琳·哈桑 上 下
现在,为了返回给定的 YouTube 的 5 个相似的内容创建者,我们将创建一个函数,该函数将接受一个输入(即 YouTube 频道名称)并给出 5 个相似的 YouTube 频道及其距离
**#this function will take input x i.e. Name of the content creator
def get_recommends(x):
indices = pd.Series(grouped_lists.index, index=grouped_lists['Name'])*#this will allow us to map our input i.e. YouTube channel’s name for the model*
idx = indices[x]
distances, indices = model.kneighbors(text_counts.getrow(idx), n_neighbors = 6)#here we have kept n_neighbors = 6 because 0th neighbour will be x itself
names_similar = pd.Series(indices.flatten()).map(grouped_lists.reset_index()['Name'])
for i in range(0, len(distances.flatten())):
if i==0:
print('Similar Content creators like',names_similar[0],'are :-')
else:
print(" ",i,names_similar[i],'with distance - ',distances.flatten()[i])**
现在,我们将使用上面定义的函数,并为我们的推荐模型提供输入,以便为给定的 YouTube 频道名称提供相似的 You Tubers(邻居)。
**get_recommends("PewDiePie")*#"PewDiePie" is our Input***
类似的内容创建者,如“PewDiePie”以及它们的成对距离(图片由作者提供)
上面的输出首先打印我们的输入,即 PewDiePie,随后是五个不同的 YouTube 频道,内容相似,如“游戏”、“反应视频”等。以及它们的成对距离。
让我们试试其他渠道-
**get_recommends("Jimmy Kimmel Live")**
类似的内容创建者,如“吉米·基梅尔现场直播”以及他们的成对距离(图片由作者提供)
**get_recommends("MLG Highlights")**
类似的内容创建者,如“MLG 集锦”(图片由作者提供)
**get_recommends("NBC News")*#NBC News is our Input***
类似的内容创建者,如“NBC 新闻”(图片由作者提供)
摘要
对于那些熟悉我们上面测试的 YouTube 频道的人来说,会知道我们创建的推荐系统是有效的!!
我们在 TfidfVectorizer 函数中提供的参数可以进一步优化,以提供更精确的结果。
因此,这是一个创建简单推荐模型的尝试,在这个模型的帮助下,我们可以从 YouTube 上推荐类似的内容创作者。请分享你对这个实现和整个帖子的想法。
Python 中的推荐系统:LightFM
原文:https://towardsdatascience.com/recommendation-system-in-python-lightfm-61c85010ce17?source=collection_archive---------0-----------------------
https://www . needpix . com/photo/642084/needle-hay-大海捞针
深度解析
使用 LightFM 在 Python 中构建推荐系统的分步指南
推荐系统或推荐系统可以被认为是信息过滤系统的一个子类,该信息过滤系统寻求预测用户将给予项目的最佳“评级”或“偏好”,该最佳“评级”或“偏好”通常通过优化诸如总点击、总收入和总销售额之类的目标来获得。
推荐算法工作的基本原理是什么?
推荐的基本原则是,以用户为中心的活动和以项目为中心的活动之间存在显著的依赖关系。例如,对纽约市的酒店感兴趣的用户更可能对纽约市的其他酒店感兴趣,而不是波士顿。
介绍
尽管任何推荐系统的主要商业目标是为用户提供个性化的体验;从问题设置的角度来看,我们可以将推荐者大致分为两类:
- 预测问题:第一种方法是我们希望预测用户-项目组合的评级值,假设训练数据可用于指示用户对其他项目的偏好。设想 m × n 矩阵,其中 m 是用户数,n 是项目数,目标是预测缺失(或未观察到)的值。
图像来源
- 排名问题:其他时候,我们希望为特定用户推荐前 k 个项目,或者确定特定主题的前 k 个目标用户。这个问题也被称为 top-k 推荐问题,是推荐问题的排名提法。想想搜索引擎,取决于谁在搜索;您希望显示 top-k 项目,以根据他们过去的偏好和最近的活动提供个性化的结果。
图像来源
推荐建模方法的基础
概括地说,大多数推荐系统利用两种类型的数据:
- 交互数据,如评分和浏览行为,以及
- 归属信息,关于每个用户和物品
依赖于前者数据的建模方法一般称为Collaborative Filtering
方法,使用后者的方法称为Content Base Filtering
方法。还有另一类被称为Knowledge-Based
的推荐系统,它基于明确指定的用户需求。
当然,每种方法都有其优点和缺点,这取决于它们用于哪些应用程序以及可用的数据量。
Hybrid Systems
然后用于结合这些方法的优势,在各种应用中拥有一个健壮的执行系统。
- 协作过滤方法:这些类型的模型使用多个用户提供的评级的协作能力来进行推荐,并且主要依赖于利用项目间相关性或用户间交互来进行预测过程。直觉上,它依赖于一个潜在的概念,即对项目进行相似评级的两个用户很可能对其他项目具有相似的偏好。
- 有两种类型的方法常用于协同过滤:
基于记忆的方法也称为基于邻域的协同过滤算法,其中用户-项目组合的评级是基于它们的邻域来预测的。这些邻域可以进一步定义为(1)基于用户,和(2)基于项目
在基于模型的方法中,ML 技术用于在给定优化框架的上下文中学习模型参数
- 基于内容的过滤方法:在这些类型的系统中,使用项目/用户的描述性属性来进行推荐。术语“内容”指的是这些描述。在基于内容的方法中,用户的评级和交互行为与项目中可用的内容信息相结合。
- 混合方法:在许多情况下,有更多种类的输入可用;在这种情况下,存在许多混合的机会,来自不同类型系统的各个方面被结合起来,以实现所有世界的最佳。该方法与传统的集成分析方法相当,在传统的集成分析方法中,多种类型的机器学习算法的能力被组合以创建更鲁棒的模型。
还有更多不同类型的方法,以及每种方法的细微差别;如果你有兴趣了解更多,我强烈推荐 Deepak Agarwal 的《推荐系统的统计方法》一书。
LightFM 入门
有许多跨不同语言的开源推荐系统框架和库,可以帮助您开始首次实现推荐模型。
在本文中,我们将探索其中一个我在工作中发现的有价值的算法,并涵盖各种用例的各种底层算法,称为LighFM
LightFM 是针对隐式和显式反馈类型的几种流行推荐算法的 Python 实现。
重要的是,它允许您将项目和用户元数据合并到传统的矩阵分解算法中,从而可以推广到新项目(通过项目功能)和新用户(通过用户功能)。
要了解更多,你可以查看它的文档这里。
履行
完整的代码可以在 GitHub 的 Jupyter 笔记本上找到
- 加载数据
- 数据检查和准备
- 数据预处理
- 模特培训
- 前 n 条建议
加载数据
对于本教程,我们将使用 Goodreads 的书评数据。这些数据集是在 2017 年底从 goodreads.com 收集的,从用户的公共书架上收集数据,即每个人都可以在网上看到它,而无需登录。用户 id 和评论 id 是匿名的。
收集该数据集仅用于学术用途。请不要重新分发或用于商业目的。
有三组数据集:
- 书籍的元数据
- 用户-图书交互
- 用户的详细书评
这些数据集可以通过匹配图书/用户/评论 id 合并在一起。对于本教程,我们将只使用前两个。
您可以从这里下载本文中使用的数据集:
- 书籍元数据:https://drive.google.com/uc?id = 1 h6 xuv 48 D5 sa 2 usf _ BusW-ibj 7 pcqzts 1
- 用户与图书的互动:https://drive.google.com/uc?id = 17 G5 _ mes wuhynd 4 fgjmvkrsolbqccimxj
%%time
books_metadata = pd.read_json('./data/goodreads_books_poetry.json', lines=True)
interactions = pd.read_json('./data/goodreads_interactions_poetry.json', lines=True)
数据检查和准备
书籍元数据
让我们从检查书籍的元数据信息开始。为了开发一个可靠和稳健的 ML 模型,有必要对现有数据进行全面的理解。
作为第一步,让我们看看所有可用的字段和示例数据
books_metadata.sample(2)
书籍元数据(示例)
虽然所有可用的信息对于提取上下文信息以便能够训练更好的推荐系统是至关重要的,但是对于本例,我们将只关注需要最少操作的选定字段。
# Limit the books metadata to selected fields
books_metadata_selected = books_metadata[['book_id',
'average_rating', 'is_ebook', 'num_pages', 'publication_year',
'ratings_count', 'language_code']]
books_metadata_selected.sample(5)
过滤的图书元数据(示例)
现在我们已经有了包含所选字段的数据,接下来,我们将通过 pandas profiler 运行它来执行初步的探索性数据分析,以帮助我们更好地理解可用数据
import pandas_profiling
import numpy as np
# replace blank cells with NaN
books_metadata_selected.replace('', np.nan, inplace=True)
# not taking book_id into the profiler report
profile = \
pandas_profiling.ProfileReport(books_metadata_selected[['average_rating',
'is_ebook', 'num_pages', 'publication_year', 'ratings_count']])
profile.to_file('./results/profiler_books_metadata_1.html')
考虑到探查器的结果,我们将对数据集执行以下转换:
- 用另一个值替换分类值中缺少的值,以创建新的类别
- 将数值变量的 bin 值转换为离散区间
# using pandas cut method to convert fields into discrete intervals
books_metadata_selected['num_pages'].replace(np.nan, -1, inplace=True)
books_metadata_selected['num_pages'] = pd.to_numeric(books_metadata_selected['num_pages'])
books_metadata_selected['num_pages'] = pd.cut(books_metadata_selected['num_pages'], bins=25)
# rounding ratings to neares .5 score
books_metadata_selected['average_rating'] = books_metadata_selected['average_rating'].apply(lambda x: round(x*2)/2)
# using pandas qcut method to convert fields into quantile-based discrete intervals
books_metadata_selected['ratings_count'] = pd.qcut(books_metadata_selected['ratings_count'], 25)
# replacing missing values to year 2100
books_metadata_selected['publication_year'].replace(np.nan, 2100, inplace=True)
# replacing missing values to 'unknown'
books_metadata_selected['language_code'].replace(np.nan, 'unknown', inplace=True)
# convert is_ebook column into 1/0 where true=1 and false=0
books_metadata_selected['is_ebook'] = books_metadata_selected.is_ebook.map(
lambda x: 1.0*(x == 'true'))
profile = pandas_profiling.ProfileReport(books_metadata_selected[['average_rating', 'is_ebook', 'num_pages',
'publication_year', 'ratings_count']])
profile.to_file('./results/profiler_books_metadata_2.html')
交互数据
作为第一步,让我们看看所有可用的字段和示例数据
interactions.sample(5)
交互数据(示例)
将数据仅限于选定的字段
# Limit the books metadata to selected fields
interactions_selected = interactions[['user_id', 'book_id', 'is_read', 'rating']]
# mapping boolean to string
booleanDictionary = {True: 'true', False: 'false'}
interactions_selected['is_read'] = interactions_selected['is_read'].replace(booleanDictionary)
profile = pandas_profiling.ProfileReport(interactions_selected[['is_read', 'rating']])
profile.to_file('./results/profiler_interactions.html')
考虑到分析器的结果,我们将 is_read 列转换为 1/0
# convert is_read column into 1/0 where true=1 and false=0
interactions_selected['is_read'] = interactions_selected.is_read.map(
lambda x: 1.0*(x == 'true'))
因为我们有两个字段表示用户和书之间的交互,“is_read”和“rating”——让我们看看我们有多少数据点,用户没有读过这本书,但给出了评级。
interactions_selected.groupby(['rating', 'is_read']).size().reset_index().pivot(columns='rating', index='is_read', values=0)
从上面的结果,我们可以得出结论,评分> = 1 的用户都读过这本书。因此,我们将使用“评级”作为最终得分,删除“is_read”为假的交互,并限制随机 5000 个用户的交互,以限制进一步分析的数据大小
数据预处理
现在,让我们将可用的数据转换成可用于矩阵运算的 CSR 稀疏矩阵。我们将通过创建 books_metadata matrix 开始这个过程,它是 NP . float 64 CSR _ matrix of shape([n _ books,n_books_features]) —每一行都包含该书相对于功能的权重。然而,在我们创建一个稀疏矩阵之前,我们将首先创建一个条目字典用于将来的引用
item_dict ={}
df = books_metadata[['book_id', 'title']].sort_values('book_id').reset_index()
for i in range(df.shape[0]):
item_dict[(df.loc[i,'book_id'])] = df.loc[i,'title']
# dummify categorical features
books_metadata_selected_transformed = pd.get_dummies(books_metadata_selected, columns = ['average_rating', 'is_ebook', 'num_pages', 'publication_year', 'ratings_count', 'language_code'])
books_metadata_selected_transformed = books_metadata_selected_transformed.sort_values('book_id').reset_index().drop('index', axis=1)
books_metadata_selected_transformed.head(5)
# convert to csr matrix
books_metadata_csr = csr_matrix(books_metadata_selected_transformed.drop('book_id', axis=1).values)
接下来,我们将创建一个迭代矩阵,它是 NP . float 64 CSR _ matrix of shape([n _ users,n_books])。我们还将为未来的用例创建一个用户字典
user_book_interaction = pd.pivot_table(interactions_selected, index='user_id', columns='book_id', values='rating')
# fill missing values with 0
user_book_interaction = user_book_interaction.fillna(0)
user_id = list(user_book_interaction.index)
user_dict = {}
counter = 0
for i in user_id:
user_dict[i] = counter
counter += 1
# convert to csr matrix
user_book_interaction_csr = csr_matrix(user_book_interaction.values)
user_book_interaction_csr
模特培训
理想情况下,我们将为我们的推荐系统构建、训练和评估几个模型,以确定哪个模型最有希望进行进一步优化(超参数调整)。
然而,对于本教程,我们将使用随机选择的输入参数来训练基本模型。
model = LightFM(loss='warp',
random_state=2016,
learning_rate=0.90,
no_components=150,
user_alpha=0.000005)
model = model.fit(user_book_interaction_csr,
epochs=100,
num_threads=16, verbose=False)
前 n 条建议
为了找回前 n 名的推荐,我们将通过Aayush agr awalT2 重新使用代码
def sample_recommendation_user(model, interactions, user_id, user_dict,
item_dict,threshold = 0,nrec_items = 5, show = True):
n_users, n_items = interactions.shape
user_x = user_dict[user_id]
scores = pd.Series(model.predict(user_x,np.arange(n_items), item_features=books_metadata_csr))
scores.index = interactions.columns
scores = list(pd.Series(scores.sort_values(ascending=False).index))
known_items = list(pd.Series(interactions.loc[user_id,:] \
[interactions.loc[user_id,:] > threshold].index).sort_values(ascending=False))
scores = [x for x in scores if x not in known_items]
return_score_list = scores[0:nrec_items]
known_items = list(pd.Series(known_items).apply(lambda x: item_dict[x]))
scores = list(pd.Series(return_score_list).apply(lambda x: item_dict[x]))
if show == True:
print ("User: " + str(user_id))
print("Known Likes:")
counter = 1
for i in known_items:
print(str(counter) + '- ' + i)
counter+=1
print("\n Recommended Items:")
counter = 1
for i in scores:
print(str(counter) + '- ' + i)
counter+=1
让我们检查结果
sample_recommendation_user(model, user_book_interaction, 'ff52b7331f2ccab0582678644fed9d85', user_dict, item_dict)
结束语
在过去的十年中,机器学习变得越来越受欢迎,计算可用性的最新进展导致人们寻求新方法如何被结合以推进推荐系统领域的方法呈指数级增长。
通常,我们将推荐系统视为黑盒算法。尽管如此,希望这篇文章能够揭示底层的数学原理、背后的直觉,以及让你开始构建你的第一个推荐模型的高级代码。
在下一篇文章中,我们将更深入地了解如何评估这些模型的性能,调整其超参数以获得更直观和可靠的结果。
参考
[1]https://en.wikipedia.org/wiki/Recommender_system
[2]迪帕克·阿加瓦尔..推荐系统的统计方法。剑桥大学出版社。Kindle 版
[3] Charu,A. (1997 年)。推荐系统教科书。在美国计算机学会的通讯中(第 40 卷)
[4]万,朱利安·麦考利,【关于单调行为链的项目建议】,载于 RecSys'18
[5]万,里沙布·米斯拉,恩达帕·纳卡肖勒,朱利安·麦考利,“大规模评论语料库中的细粒度扰流板检测”,载于 ACL'19
[6]https://github . com/aayushmnit/cookbook/blob/master/rec sys . py
感谢阅读。如果你有任何反馈,请联系我,在LinkedIn给我发邮件(shmkapadia[at]gmail.com)
如果你喜欢这篇文章,请阅读我在 NLP 上的其他文章
[## Python 中的主题建模:潜在狄利克雷分配(LDA)
如何开始使用 Python 中的 LDA 进行主题建模
towardsdatascience.com](/end-to-end-topic-modeling-in-python-latent-dirichlet-allocation-lda-35ce4ed6b3e0) [## 评估主题模型:潜在狄利克雷分配(LDA)
构建可解释主题模型的分步指南
towardsdatascience.com](/evaluate-topic-model-in-python-latent-dirichlet-allocation-lda-7d57484bb5d0)
推荐系统——矩阵分解
原文:https://towardsdatascience.com/recommendation-system-matrix-factorization-d61978660b4b?source=collection_archive---------1-----------------------
照片由freepik.com拍摄
R ecommender 系统在亚马逊、UberEats、网飞和 Youtube 等多个领域得到应用。
协同过滤: 协同过滤是发现用户过去行为上的相似之处,并基于与其他用户相似的偏好对用户做出预测。该模型然后被用于预测用户可能感兴趣的项目(或项目的评级)。
基于内容的过滤: 基于内容的过滤用于根据项目的特征产生项目推荐。
在本文中,您将学习推荐系统的矩阵分解算法:
(1)矩阵分解的介绍
(2)矩阵分解的数学概念
(python 代码对矩阵分解的实践经验
矩阵分解导论
矩阵分解是两种不同实体相乘时生成潜在特征的一种方式。协同过滤是矩阵分解的应用,用于识别项目和用户实体之间的关系。通过输入用户对商店商品的评级,我们希望预测用户将如何对商品进行评级,以便用户可以基于预测获得推荐。
假设我们有 5 个用户和 5 部电影的客户评级表,评级是从 1 到 5 的整数,矩阵由下表提供。
表 1-用户对电影的评分表
因为不是每个用户都给所有电影评级,所以矩阵中有许多缺失值,这导致了稀疏矩阵。因此,用户没有给出的空值将用 0 填充,以便为乘法运算提供填充的值。例如,当电影由他们最喜欢的男演员和女演员表演或者电影类型是动作片时,两个用户给某个动作高的评价,等等。从上表中我们可以发现,用户 1 和用户 3 都给了《move2》和《movie3》很高的评价。因此,从矩阵分解中,我们能够发现这些潜在特征,以给出关于用户偏好和交互的相似性的评级预测。
给定一个场景,用户 4 没有给电影 4 评级。我们想知道用户 4 是否喜欢电影 4。该方法是通过获取对电影 4 具有相似偏好的用户给出的评级来发现与用户 4 具有相似偏好的其他用户,并预测用户 4 是否喜欢电影 4。
矩阵分解的数学概念
定义一组用户(U)、项目(D)、R 大小|U|和|D|。矩阵|U||D|包括用户给出的所有评级。目标是发现潜在的特征。给定两个矩阵 P (|U|k)和 Q (|D|*k)的输入,它将生成乘积结果 r。
矩阵 P 表示用户和特征之间的关联,而矩阵 Q 表示项目和特征之间的关联。通过计算 u_i 和 d_j 对应的两个向量的点积,我们可以得到对一个项目评分的预测。
为了获得 P 和 Q 的两个实体,我们需要初始化这两个矩阵,并计算名为矩阵 m 的乘积的差。接下来,我们通过迭代来最小化差。该方法被称为梯度下降,旨在找到差异的局部最小值。
为了使误差最小化,梯度能够使误差最小化,因此我们分别对上述方程的这两个变量进行微分。
根据梯度,可以更新 p_ik 和 q_kj 的数学公式。a 是计算梯度时达到最小值的步长,a 通常设置为小值。
根据上面的等式,p'_ik 和 q'_kj 都可以通过迭代更新,直到误差收敛到最小值。
矩阵分解的例子
用户和物品矩阵的点积可以生成评分矩阵,而用户矩阵是 k(用户)* f(特征)的形状,物品矩阵是 j(物品)* f(特征)的形状。从用户和项目的矩阵中,电影的特征可以是其类型、演员、情节等。有了分解矩阵的两个特征,让我们假设 F1 是“这部电影是不是喜剧?”F2 为“如果罗宾·威廉姆斯出演这部电影?”
用户矩阵:根据用户 1 的说法,如果这是一部喜剧电影,他会给它 4 分,如果罗宾·威廉姆斯是这部电影的演员,他会给它 3 分。
项目矩阵:项目矩阵中主要有二进制值,当满足上述特征的条件时为 1,否则为 0。通过执行用户矩阵和项目矩阵的点积,将生成评级矩阵。
当数学成本函数 RMSE 通过矩阵分解最小化时,可以生成用户和项目矩阵的矩阵分解。根据上述数学概念,梯度下降是通过每次迭代最小化 RMSE 的方法之一。
矩阵分解的实用 Python 代码
下面是执行梯度下降算法的 python 代码片段。我们用 6 个用户给出的 4 部电影设置了一个评级矩阵。如你所见,有些用户之前没有看一些电影,所以在评分中给出的评分为 0。
预测矩阵生成如下。如您所见,预测矩阵具有与真实值相似的输出,0 评级被基于相似用户对电影的偏好的预测所取代。
我们可以看到,对于现有的评级,我们有非常接近真实值的近似值,我们还可以获得一些未知值的“预测”。给定特征为 3 时,算法能够将用户和项目与三个不同的特征相关联,并且预测也遵循这些关联。我们可以发现,U2、U5 和 U6 对 M1 和 M2 给予低评级,而对 M3 给予高评级。即使 U5 没有看 M1,我们也会进一步推断 U5 可能不喜欢 M1。
在现实世界中,评级矩阵非常稀疏,因为每个用户都以不同的频率观看电影。但是,误差函数 RMSE 仅使用非空等级进行计算。评级矩阵中缺失的条目将由因素矩阵的点积代替。因此,我们知道如何根据预测向用户推荐未看过的电影。
总之:
- 矩阵分解是一种协同过滤方法,用于发现项目和用户实体之间的关系。潜在特征,即用户和电影矩阵之间的关联,被确定来寻找相似性并基于项目和用户实体进行预测
- 当数学成本函数 RMSE 通过矩阵分解被最小化时,可以生成用户和项目矩阵的矩阵分解。梯度下降是一种最小化成本函数的方法。
参考:
- 矩阵分解:http://www . quux labs . com/blog/2010/09/matrix-Factorization-a-simple-tutorial-and-implementation-in-python/
2.推荐系统:https://medium . com/sfu-cspmp/recommendation-Systems-collaborative-filtering-using-matrix-factorization-simplified-2118 F4 ef 2c D3
推荐系统系列第 6 部分:用于协同过滤的自动编码器的 6 种变体
原文:https://towardsdatascience.com/recommendation-system-series-part-6-the-6-variants-of-autoencoders-for-collaborative-filtering-bd7b9eae2ec7?source=collection_archive---------6-----------------------
RECSYS 系列
利用自动编码器提出建议
更新: 本文是我探索学术界和工业界推荐系统系列文章的一部分。查看完整系列: 第一部分 , 第二部分 , 第三部分 , 第四部分 , 第五部分 和
在过去的几年中,已经提出了许多推荐模型。然而,它们在处理数据稀疏和冷启动问题时都有其局限性。
- 如果用户和项目之间的交互非常稀疏,当推荐性能显著下降时,就会出现数据稀疏性。
- 冷启动问题发生在模型无法推荐新用户和新物品的时候。
为了解决这些问题,最近的方法已经利用了关于用户或项目的辅助信息。然而,由于这种模型在捕捉用户偏好和项目特征方面的限制,推荐性能的提高并不显著。
丽贝卡·海尔威尔——抖音的推荐有些奇怪(https://www . vox . com/recode/2020/2/25/21152585/tiktok-推荐-简介-长相相似 )
Auto-encoder 是一种适合无监督学习任务的神经网络,包括生成建模、维度缩减和高效编码。在许多领域,包括计算机视觉、语音识别和语言建模,它在学习潜在特征表示方面已经显示出它的优越性。鉴于这一点,新的推荐架构已经整合了 autoencoder,因此在重新创造用户体验以满足客户方面带来了更多机会。
- 传统模型只处理单一数据源(评级或文本),而基于自动编码器的模型可以处理异构数据源(评级、音频、视频、视频)。
- Auto-encoder 的更好地理解了用户需求和项目特征的,因此比传统模型具有更高的推荐准确度。
- 此外,自动编码器有助于推荐模型在多媒体场景中更具适应性,并且在处理输入噪声方面比传统模型更有效。
在这篇文章和接下来的文章中,我将介绍推荐系统的创建和训练,因为我目前正在做这个主题的硕士论文。
- 第 1 部分提供了关于推荐系统、如何构建推荐系统以及如何利用推荐系统改善各行业业务的高级概述。
- 第 2 部分提供了关于这些模型的优势和应用场景的正在进行的研究计划的仔细回顾。
- 第 3 部分提供了几个可能与推荐系统学者社区相关的研究方向。
- 第 4 部分提供了您可以构建的矩阵分解的 7 种变体的本质数学细节:从使用巧妙的辅助功能到应用贝叶斯方法。
- 第 5 部分提供了基于多层感知器的协同过滤模型的 5 个变体的架构设计,它们是能够以非线性方式解释特征的判别模型。
在第 6 部分中,我探索了使用自动编码器进行协同过滤。更具体地说,我将剖析六篇将自动编码器纳入其推荐架构的原则性论文。但是首先,让我们浏览一下关于自动编码器及其变体的初级读本。
自动编码器及其变体入门
如下图所示,标准自动编码器由输入层、隐藏层和输出层组成。输入数据被传递到输入层。输入层和隐藏层构成一个编码器。隐藏层和输出层构成解码器。输出数据来自输出层。
自动编码器架构
编码器用函数 f 将高维输入数据 x 编码成低维隐藏表示 h:
方程式 1
其中,s_f 是激活函数,W 是权重矩阵,b 是偏置向量。
解码器通过另一个函数 g 将隐藏表示 h 解码回重构 x ’:
等式 2
其中 s_g 是激活函数,W’是权重矩阵,b’是偏差向量。
s_f 和 s_g 的选择是非线性的,例如 Sigmoid、TanH 或 ReLU。这使得 auto-encoder 能够学习比其他无监督线性方法更有用的特征,比如主成分分析。
我可以训练自动编码器通过平方误差(对于回归任务)或交叉熵误差(对于分类任务)来最小化 x 和 x’之间的重建误差。
这是平方误差的公式:
等式 3
交叉熵误差的公式如下:
等式 4
最后,向自动编码器的最终重构误差添加一个正则项始终是一个好的做法:
等式 5
上面的重建误差函数可以通过随机梯度下降或替代的最小二乘法来优化。
目前在推荐系统中使用的自动编码器有很多种。四种最常见的是:
- 去噪自动编码器(DAE) 在将输入映射到隐藏表示之前破坏输入,然后从其破坏的版本重建原始输入。想法是迫使隐藏层获得更健壮的特征,并防止网络仅仅学习身份函数。
- 堆叠去噪自动编码器(SDAE) 堆叠多个去噪自动编码器,以获得输入的更高级表示。训练通常用贪婪算法逐层优化。这里明显的缺点是训练的高计算成本和缺乏对高维特征的可扩展性。
- 边缘化去噪自动编码器(MDAE) 通过边缘化随机特征破坏来避免 SDAE 的高计算成本。因此,它具有训练速度快、实现简单和对高维数据的可扩展性。
- 变分自动编码器(VAE) 是一个无监督的潜在变量模型,它从高维数据中学习深度表示。其思想是将输入编码为概率分布,而不是像普通自动编码器那样的点估计。然后,VAE 使用解码器通过使用来自该概率分布的样本来重建原始输入。
可变自动编码器架构
好了,是时候回顾一下不同的基于自动编码器的推荐框架了!
1 — AutoRec
从自动编码器的角度考虑协同过滤问题的最早的模型之一是来自 Suvash Sedhain、Aditya、Scott Sanner 和 Lexing Xie 的“自动编码器遇到协同过滤”的 AutoRec 。
在该论文的设置中,有 m 个用户,n 个项目,以及维数为 m×n 的部分填充的用户-项目交互/评级矩阵 r。每个用户 u 可以由部分填充的向量 rᵤ表示,每个项目 I 可以由部分填充的向量 rᵢ.表示 AutoRec 直接将用户评级向量 rᵤ或项目评级 rᵢ作为输入数据,并在输出层获得重建的评级。根据两种类型的输入,AutoRec 有两种变体:基于项目的 AutoRec ( I-AutoRec )和基于用户的 AutoRec ( U-AutoRec )。两者结构相同。
Suvesh Sedhain 等人——AutoRec:自动编码器满足协同过滤(https://dl.acm.org/doi/10.1145/2740908.2742726)
论文中的图 1 说明了 I-AutoRec 的结构。阴影节点对应于观察到的等级,实线连接对应于为输入 rᵢ.更新的权重
给定输入 rᵢ,重建为:
等式 6
其中 f 和 g 是激活函数,参数θ包括 W、V、mu 和 b
AutoRec 仅使用普通自动编码器结构。该模型的目标函数类似于自动编码器的损失函数:
等式 7
该函数可以通过弹性传播(收敛更快并产生可比较的结果)或 L-BFGS(有限内存 Broyden Fletcher Goldfarb Shanno 算法)进行优化。
以下是 AutoRec 的一些重要信息:
- I-AutoRec 的表现一般比 U-AutoRec 好。这是因为每个项目的平均评级数比每个用户给出的平均评级数多得多。
- 激活功能的不同组合会显著影响 AutoRec 的性能。
- 增加隐藏神经元的数量或层数可以提高模型性能。这是有意义的,因为扩展隐藏层的维度允许 AutoRec 有更多的能力来模拟输入要素。
- 添加更多的层来形成深层网络可以导致轻微的改善。
出于说明目的,AutoRec 模型类别的张量流代码如下所示:
对于我的 TensorFlow 实现,我用一个由 sigmoid 非线性函数激活的 500 个单元的隐藏层来训练 AutoRec 架构。其他超参数包括 0.001 的学习率、512 的批量大小、Adam 优化器和 1 的 lambda 正则化器。
2 — DeepRec
DeepRec 是由英伟达的 Oleisii Kuchaiev 和 Boris Ginsburg 创建的模型,参见“为协同过滤训练深度自动编码器”该模型受上述 AutoRec 模型的启发,有几个重要区别:
- 网络要深得多。
- 该模型使用“比例指数线性单位”(SELUs)。
- 辍学率很高。
- 作者在训练期间使用迭代输出再馈。
Oleisii Kuchaiev 和 Boris Ginsburg——为协同过滤训练深度自动编码器(https://arxiv.org/abs/1708.01715)
2.1 —型号
上图描述了一个典型的 4 层自动编码器网络。编码器有 2 层 E1 和 E2,而解码器有 2 层 D1 和 D2。它们在表示 z 上融合在一起。这些层被表示为 f(W * x + b),其中 f 是某个非线性激活函数。如果激活函数的范围小于数据的范围,则解码器的最后一层应该保持线性。作者发现隐藏层中的激活函数 f 包含非零负部分是非常重要的,并且在他们的大多数实验中使用 SELU 单位。
2.2 —损失函数
由于预测用户表示向量 x 中的零没有意义,作者优化了掩蔽均方误差损失:
等式 8
其中 r_i 是实际评级,y_i 是重构评级,m_i 是屏蔽函数,使得如果 r_i 不为 0,m_i = 1,否则 m_i = 0。
2.3 —密集再进给
在前向传递和推理传递期间,模型从训练集 x 中获取由其评级向量表示的用户。注意,x 非常稀疏,而解码器 f(x)的输出是密集的,并且包含对语料库中所有项目的评级预测。因此,为了明确实施定点约束并执行密集训练更新,作者用如下的迭代密集再反馈步骤来增加每个优化迭代:
- 在初始正向传递期间,给定稀疏输入 x,模型使用等式 8 计算密集输出 f(x)和 MMSE 损耗。
- 在最初的反向过程中,模型计算梯度并相应地更新权重。
- 在第二次向前传递期间,模型将 f(x)视为新的数据点,从而计算 f(f(x))。f(x)和 f(f(x))都变得稠密。MMSE 损失现在所有的 m 都是非零的。
- 在第二次反向传递期间,模型再次计算梯度并相应地更新权重。
为了便于说明,下面给出了 DeepRec 模型定义的张量流代码:
对于我的 TensorFlow 实现,我用以下架构训练了 DeepRec,512,512,1024,512,512,n]。所以 n 是用户给定的收视率数,编码器有 3 层大小(512,512,1034),瓶颈层有大小 1024,解码器有 3 层大小(512,512,n)。我用随机梯度下降来训练模型,动量为 0.9,学习率为 0.001,批量为 512,辍学率为 0.8。参数通过 Xavier 初始化方案进行初始化。
3 —协同去噪自动编码器
“Top-N 推荐系统的协同去噪自动编码器”作者、Christopher DuBois、Alice Zheng 和 Martin Ester 是一个具有一个隐藏层的神经网络。与 AutoRec 和 DeepRec 相比, CDAE 有以下不同之处:
- CDAE 的输入不是用户项目评分,而是部分观察到的隐含反馈 r(用户的项目偏好)。如果用户喜欢一部电影,对应的条目值为 1,否则为 0。
- 与用于评级预测的前两个模型不同,CDAE 主要用于排名预测(也称为前 N 名偏好推荐)。
https://dl.acm.org/doi/10.1145/2835776.2835837**)吴耀等人——前 N 名推荐系统的协同去噪自动编码器
3.1 —型号
上图显示了一个 CDAE 的样本结构,它由三层组成:输入层、隐藏层和输出层。
- 在输入层中总共有 I + 1 个节点。第一个 I 节点代表用户偏好,这些 I 节点的每个节点对应一个项目。最后一个节点是特定于用户的节点,在上图中用红色节点表示,这意味着不同的用户有不同的节点和相关的权重。
- 这里,yᵤ是用户 u 对 I 中所有项目的 I 维反馈向量。yᵤ是一个稀疏的二进制向量,只具有非零值:如果用户 u 对 I 评分,yᵤᵢ = 1,否则 yᵤᵢ = 0。
- 有 K(<< I) + 1 nodes in the hidden layer. The blue K nodes are fully connected to the nodes of the input layer. The pink additional node in the hidden layer captures the bias effects.
- In the output layer, there are I nodes which are the reconstructed output of the input yᵤ. They are fully connected to the nodes in the hidden layer.
The corrupted input CDAE 的 r_corr 是从一个条件高斯分布中得出的 p(r_corr | r) 。 r_corr 的重建公式如下:
等式 9
其中 W₁是对应于编码器的权重矩阵(从输入层到隐藏层),W₂是对应于解码器的权重矩阵(从隐藏层到输出层)。Vᵤ是红色用户节点的权重矩阵,而 b₁和 b₂都是偏置向量。
3.2 —损失函数
通过最小化平均重建误差来学习 CDAE 的参数,如下所示:
等式 10
上式中的损失函数 L (r_corr,h(r_corr)) 可以是平方损失,也可以是 logistic 损失。CDAE 使用平方 L2 范数来控制模型的复杂度。它还(1)应用随机梯度下降来学习模型的参数,以及(2)在学习过程中采用 AdaGrad 来自动调整训练步长。
作者还提出了负采样技术来从用户没有交互的项目中提取一个小子集,以在不降低排序质量的情况下显著降低时间复杂度。在推理时,CDAE 将用户的现有偏好集(没有损坏)作为输入,并向该用户推荐输出层上具有最大预测值的项目。
为了便于说明,下面给出了 CDAE 建筑等级的 PyTorch 代码:
对于我的 PyTorch 实现,我使用了一个 CDAE 架构,隐藏了 50 个单元。我使用随机梯度下降来训练模型,学习率为 0.01,批量为 512,损坏率为 0.5。
4 —多项式变分自动编码器
这次讨论中最有影响力的论文之一是来自网飞的 Dawen Liang、Rahul Krishnan、Matthew Hoffman 和 Tony Jebara 的“协作过滤的变分自动编码器”。它提出了一种 VAE 的变体,用于隐式数据的推荐。特别是,作者介绍了一种有原则的贝叶斯推理方法来估计模型参数,并显示出比常用的似然函数更好的结果。
本文使用 U 来索引所有用户,使用 I 来索引所有项目。用户逐项交互矩阵称为 X(维度为 U x I)。小写的 xᵤ是一个单词包向量,其中包含用户 u 对每个项目的点击次数。对于隐式反馈,该矩阵被二进制化为只有 0 和 1。
4.1 —型号
等式 11
模型的生成过程如等式 11 所示,细分如下:
- 对于每个用户 u,该模型从标准高斯先验中采样 k 维潜在表示 zᵤ。
- 然后,它通过非线性函数 f_θ变换 zᵤ,以产生 I 项π(zᵤ).上的概率分布
- f_θ是一个多层感知器,有参数θ和一个 softmax 激活函数。
- 给定来自用户 u 的点击总数,从具有概率π(zᵤ).的多项式分布中采样词袋向量 xᵤ
用户 u 的对数似然性(以潜在表示为条件)为:
等式 12
作者认为多项式分布适合这个协同过滤问题。具体而言,等式 11 中的交互作用矩阵的可能性奖励了将概率质量放在 xᵤ.的非零条目上的模型然而,考虑到π(zᵤ)的总和必须为 1,项目必须竞争有限的概率质量预算。因此,该模型应该将更多的概率质量分配给更有可能被点击的项目,使得它适合于在推荐系统的前 N 名排名评估度量中实现稳定的性能。
4.2 —变分推理
为了训练等式 11 中的生成模型,作者经由变分推理通过近似难以处理的后验分布 p(zᵤ | xᵤ)来估计θ。这种方法用一种更简单的变分分布 q(zᵤ(一种全对角高斯分布)来逼近真实的难处理的后验概率。变分推理的目标是优化自由变分参数{μᵤ,σᵤ }使得库尔贝克-莱伯散度kl(q(zᵤ)| |p(zᵤ|xᵤ)】最小化。
变分推断的问题在于,用于优化σᵤ{μᵤ的参数数量会随着数据集中用户和项目的数量而增长。VAE 通过用一个依赖于数据的函数代替单个变分参数来帮助解决这个问题:
等式 13
该函数由ϕ参数化,其中μ_{ϕ} (xᵤ)和σ_{ϕ} (xᵤ)都是 k 维向量。然后,变分分布设置如下:
等式 14
使用输入 xᵤ,推理模型返回相应的变分分布 q_{ϕ} (zᵤ|xᵤ).)的变分参数当被优化时,这种变分分布近似于难处理的后 p_{ϕ} (zᵤ | xᵤ).
变分渐变(【https://matsen.fredhutch.org/general/2019/08/24/vbpi.html】)
为了用变分推断学习潜变量模型,标准的方法是对数据的对数边际似然进行下界估计。用户 u 最大化的目标函数现在变成:
等式 15
这个目标的另一个术语是证据下限(ELBO)。直观上,我们应该能够通过对 zᵤ∞q_ϕ进行采样并使用随机梯度上升对其进行优化来获得 ELBO 的估计值。然而,我们不能对爱尔波求导以得到相对于ϕ.的梯度重新参数化技巧在这里派上了用场:
等式 16
本质上,我们隔离了采样过程中的随机性,因此相对于ϕ的梯度可以通过采样的 zᵤ.反向传播
从不同的角度来看,等式 15 的第一项可以解释为重构误差,等式 15 的第二项可以解释为正则化。因此,作者用一个附加参数β来扩展方程 15,以控制正则化的强度:
等式 17
该参数β在模型拟合数据的良好程度和学习期间近似后验与先验的接近程度之间进行权衡。作者通过 KL 退火调整β,这是一种常见的启发式方法,用于在担心模型未被充分利用时训练 VAEs。
4.3 —预测
给定用户的点击历史 x,该模型基于未归一化的预测多项式概率 f_ϕ (z)对所有项目进行排名。x 的潜在表示 z 就是变分分布 z = μ_ϕ (x)的平均值。
梁大文等——用于协同过滤的变分自动编码器(【https://arxiv.org/abs/1802.05814】)
该论文中的图 2 提供了自动编码器不同变体的统一视图。
- 2a 是普通的自动编码器架构,如 AutoRec 和 DeepRec 所示。
- 2b 是去噪自动编码器架构,如在 CDAE 看到的。这里,ϵ是注入到输入层的噪声。
- 2c 是 MultVAE 下的变分自动编码器架构,其使用由ϕ参数化的推理模型来产生近似变分分布的均值和方差,如上面详细解释的。
MultVAE 架构类的 PyTorch 代码如下所示,用于说明目的:
对于我的 PyTorch 实现,我保持生成模型 f 和推理模型 g 的架构对称,并使用一个带有 1 个隐藏层的 MLP。潜在表示 K 的维度被设置为 200,而其他隐藏层的维度被设置为 600。MultVAE 的整体架构现在变成[I->600->200->600->I],其中 I 是项目总数。其他模型细节包括 tanH 激活函数,概率为 0.5 的辍学率,Adam 优化器,批量为 512,学习率为 0.01。
5 —顺序变分自动编码器
在“用于协同过滤的序列变分自动编码器”中,诺维恩·萨克德瓦、朱塞佩·曼科、埃托雷·里塔克和维克拉姆·迪普通过探索过去偏好历史中存在的丰富信息,提出了对 MultVAE 的扩展。他们引入了 MultVAE 的递归版本,而不是传递整个历史的子集,而不管时间依赖性,他们通过递归神经网络传递消费序列子集。他们表明处理时间信息对于提高 VAE 的准确性至关重要。
5.1 —设置
问题设置与 MultVAE 论文中的设置完全相似:U 是一组用户,I 是一组项目,X 是维度为 U x I 的用户-项目偏好矩阵。主要区别在于 SVAE 考虑了矩阵 X 中的优先级和时间关系。
- x 归纳出评分矩阵中项目之间的自然排序关系:i x_{u,j}。
- 他们假设定时信息 T 的存在,其中 t_{u,i}项代表我被 u 选中的时间,那么我 t_{u,j}。
- 他们还在 xᵤ:的元素中引入了一个时间标记,x_{u(t)}表示
诺维恩·萨克德瓦等人——用于协同过滤的序列变分自动编码器(【https://arxiv.org/abs/1811.09975】)
5.2 —型号
论文中的上图显示了 MultVAE、SVAE 和另一个名为 RVAE 的模型之间的架构差异(我在这里不讨论它)。查看 SVAE 架构,我可以观察到 z_{u(t)}所依赖的层中出现的循环关系。SVAE 背后的基本思想是潜在变量建模应该能够表达时间动态 以及用户历史中偏好之间的因果关系和依赖性。
让我们复习一下数学。在这个 SVAE 框架内,作者通过将每个事件与之前的事件相联系来模拟时间依赖性。给定一个序列 x_{(1: T},那么它的概率是:
等式 18
这个概率表示 x_{(t+1)和 x_{(1:t)}之间的递归关系。因此,模型可以单独处理每个时间步长。
回想等式 11 中的生成过程,我们可以添加时间戳 t,如下所示:
等式 19
等式 19 得出联合似然性:
等式 20
等式 20 中的后验似然性可以用因式分解的建议分布来近似:
等式 21
其中右边是高斯分布,其参数μ和σ取决于当前历史 x_{u(1:t-1)},通过递归层 h_t:
等式 22
最后,SVAE 优化的损失函数为:
等式 23
5.3 —预测
在这个 SVAE 模型中,建议分布引入了来自递归层的潜在变量的依赖性,这允许我们从先前的历史中恢复信息。给定用户历史 x_{u(1:t-1)},我们可以使用等式 22 并设置 z = μ_{λ} (t),在此基础上,我们可以通过π(z)来设计 x_{u(t)}的概率。
为了便于说明,下面给出了 SVAE 架构类的 PyTorch 代码:
本文的另一个独特之处是评估协议的工作方式。作者将用户分为训练集、验证集和测试集;然后使用训练集中用户的全部历史来训练该模型。在评估过程中,对于验证/测试集中的每个用户,他们将按时间排序的用户历史分为两部分,即折叠和折叠拆分。
- 折叠分割学习必要的表示并推荐商品。
- 然后,使用精确度、召回率和标准化折扣累积收益等指标,使用用户历史的展开分割来评估这些项目。
对于我的 PyTorch 实现,我遵循作者提供的相同代码。
- SVAE 架构包括大小为 256 的嵌入层、具有 200 个单元的递归层(门控递归单元)、两个编码层(大小为 150 和 64)以及最后两个解码层(大小为 64 和 150)。
- VAE 的潜在因子的数量 K 被设置为 64。
- 该模型使用 Adam 进行优化,权重衰减设置为 0.01。
6 —令人尴尬的浅薄的自动编码器
Harald Steck 的“令人尴尬的浅薄的稀疏数据自动编码器”是一个很吸引人的东西,我想带进这个讨论。这里的动机是,根据他的文献综述,与仅具有一个、两个或三个隐藏层的“深度”模型相比,具有大量隐藏层的深度模型通常在协同过滤中获得排名准确度的显著提高 而不是 。这与 NLP 或计算机视觉等其他领域形成了鲜明的对比。
Harald Steck——令人尴尬的浅薄的稀疏数据自动编码器(https://arxiv.org/abs/1905.03375)
6.1 —型号
令人尴尬的浅薄的自动编码器 (ESAE)是一个没有隐藏层的线性模型。(二进制)输入向量 X 向量表示用户已经交互的项目,ESAE 的目标是在输出层预测推荐给用户的最佳项目(如上图所示)。对于隐式反馈,X 中的值 1 指示用户与项目交互,而 X 中的值 0 指示没有观察到交互。
项目-项目权重矩阵 B 表示 ESAE 的参数。这里,输入层中的项目与输出层中的项目的自相似性被忽略,因此 ESAE 可以在重建步骤中有效地进行概化。因此,该权重矩阵 B 的对角线被约束为 0 ( diag(B) = 0 )。
对于一个项目 j 和一个用户 u,我们想预测 S_{u,j},其中 X_{u,.}指的是 u 行和 B_{。,j}指的是 j 列:
等式 24
6.2 —目标函数
关于 diag(B) = 0, ESAE 具有以下用于学习权重 B 的凸目标:
等式 25
以下是关于这个凸目标的重要注释:
- ||.||表示 Frobenius 范数。数据 X 和预测得分 XB 之间的平方损失允许一个封闭形式的解决方案。
- 超参数λ是权重 b 的 L2 范数正则化
- 零对角线的约束有助于避免平凡解 B = I,其中 I 是单位矩阵。
在论文中,Harald 从等式 25 中的训练目标导出了一个封闭形式的解。他认为,传统的基于邻居的协同过滤方法是基于概念上不正确的项目-项目相似性矩阵,而 ESAE 框架利用了原则的邻居模型。我不会在这里重复数学推导,但是你应该看看论文的第 3.1 节来了解细节。
值得注意的是,ESAE 的相似性矩阵是基于给定数据矩阵的 逆 。结果,学习到的权重也可以是负的,因此模型可以学习项目之间的不相似性(除了相似性之外)。事实证明,这对于获得良好的分级准确性至关重要。此外,如果数据矩阵 X 中的用户数量足够大,则数据稀疏性问题(对于每个用户可能只有少量数据可用)不会影响估计权重矩阵 B 的不确定性。
6.3 —算法
上面给出了学习算法的 Python 代码。训练只需要项目-项目矩阵 G = X^T * X 作为输入,而不需要用户-项目矩阵 x。如果 g 的大小小于 x 的大小,这是非常有效的
对于我的 PyTorch 实现,我设置 L2 范数正则化超参数λ为 1000,学习率为 0.01,批量为 512。
模型评估
您可以查看我在这个存储库中构建的所有六个基于自动编码器的推荐模型:https://github . com/khanhnamle 1994/transfer-rec/tree/master/auto encoders-Experiments。
- 数据集是 MovieLens 1M ,类似于我之前用矩阵分解和多层感知器做过的两个实验。目标是预测用户对一部电影的评价,其中评价在 1 到 5 之间。
- 对于 AutoRec 和 DeepRec 模型,评估指标是评级预测(回归)设置中的掩蔽均方根误差(RMSE) 。
- 对于 CDAE、马尔特瓦、SVAE 和 ESAE 模型,评估指标是排名预测(分类)设置中的精度、召回和归一化贴现累积收益(NDCG) 。如以上部分所述,这些模型使用隐式反馈数据,其中评级被二进制化为 0(小于等于 3)和 1(大于 3)。
- 结果在 彗星 ML 中被捕获。对于那些不熟悉的人来说,它是一个非常棒的工具,可以跟踪模型实验,并在一个仪表板中记录所有必要的指标。
结果表在我的回购的自述的底部:
模型评估
对于评级预测:
- AutoRec 比 DeepRec 性能更好:RMSE 更低,运行时间更短。
- 这很令人惊讶,因为 DeepRec 是比 AutoRec 更深层次的架构。
对于排名预测:
- SVAE 模型显然具有最好的结果;但是,也需要一个数量级的时间来训练。
- 其余三个模型之间:CDAE 的精度最高@100,ESAE 的召回率最高@100,NDCG@100,MultVAE 的运行时间最短。
结论
在这篇文章中,我讨论了自动编码器的具体细节以及它们在协同过滤中的应用。我还浏览了 6 篇使用自动编码器作为推荐框架的不同论文:(1) AutoRec,(2) DeepRec,(3)协作去噪自动编码器,(4)多项式变分自动编码器,(5)顺序变分自动编码器,以及(6)令人尴尬的浅薄自动编码器。
这个领域出现了几个新兴的研究方向:
- 当面对不同的推荐需求时,重要的是融入辅助信息来帮助理解用户和项目,以进一步提高推荐的性能。自动编码器处理异构数据源的能力为推荐具有非结构化数据(如文本、图像、音频和视频特征)的不同项目带来了巨大的机会。
- 最近出现了许多基于自动编码器的有效的无监督学习技术:加权自动编码器、梯形变分自动编码器和离散变分自动编码器。使用这些新的自动编码器变体将有助于进一步提高推荐性能。
- 除了协作过滤之外,还可以将自动编码器范例与基于内容的过滤和基于知识的推荐方法相集成。这些基本上是未得到充分探索的领域,有取得进展的潜力。
请继续关注本系列未来的博文,这些博文将探索为协同过滤而设计的不同建模架构。
参考文献
- 自动编码器满足协同过滤 。Suvash Sedhain、Aditya、Scott Sanner 和 Lexing Xie。2015 年 5 月。
- 训练深度自动编码器进行协同过滤 。奥莱克西·库切耶夫和鲍里斯·金斯伯格。2017 年 8 月。
- Top-N 推荐系统的协同去噪自动编码器 。吴耀、克里斯托弗·杜布瓦、爱丽丝·郑和马丁·埃斯特。2016 年 2 月。
- 用于协同过滤的变分自动编码器 。Dawen Liang,Rahul G. Krishnan,Matthew D. Hoffman 和 Tony Jebara。2018 年 2 月。
- 用于协同过滤的序贯变分自动编码器 。诺维恩·萨克德瓦、朱塞佩·曼科、埃托雷·里塔克和维克拉姆·迪普。2018 年 11 月。
- 尴尬浅薄的稀疏数据自动编码器 。哈拉尔德·斯泰克。2019 年 5 月。
如果你想关注我在推荐系统、深度学习和数据科学新闻方面的工作,你可以查看我的 中的 和GitHub,以及 https://jameskle.com/*的其他项目。你也可以在* 推特 , 直接发邮件给我 ,或者 在 LinkedIn 上找我。 注册我的简讯 就在你的收件箱里接收我对机器学习研究和行业的最新想法吧!
推荐系统:综述
原文:https://towardsdatascience.com/recommendation-systems-a-review-d4592b6caf4b?source=collection_archive---------6-----------------------
日本北海道别市
推荐系统方法综述
一个 推荐系统 ,或一个 推荐系统 ,是 信息过滤系统 的一个子类,它试图预测用户对一个项目的“评分”或“偏好”。它们主要用于商业应用。
这类应用的例子包括在亚马逊上推荐产品,在 Spotify 上推荐音乐,当然还有在 Medium 上推荐故事。著名的Netflix 奖也是推荐系统背景下的竞争。
更正式地说,推荐者问题可以解释为确定映射( c,i ) → R 其中 c 表示用户, i 表示项目, R 是被推荐项目的用户的效用。然后,项目按实用程序排序,前 N 个项目作为推荐项目呈现给用户。
效用的抽象概念有时可以通过用户的后续行为来衡量,例如购买商品、点击“不感兴趣”或“不再显示”等。
排名与推荐
人们有时会混淆排名(或搜索排名)系统和推荐系统,有些人甚至认为它们是可以互换的。虽然这两种算法都试图以排序的方式呈现项目,但这两种算法之间存在一些关键差异:
- 排名算法依赖于用户提供的搜索查询,用户知道他们在寻找什么。另一方面,推荐系统没有用户的任何明确输入,旨在发现他们否则可能不会发现的东西。
- 排名算法通常将更相关的项目放在显示列表的顶部,而推荐系统有时试图避免过度专业化。一个好的推荐系统不应该推荐与用户之前看过的过于相似的项目,而应该使其推荐多样化。
- 推荐系统更加强调个性化,因此更容易受到数据稀疏性的影响。
推荐系统的类型
推荐系统通常分为以下几类:
- 基于内容的过滤
- 协同过滤
- 混合动力系统
根据模型是否从底层数据中学习,推荐系统也可以分为:
- 基于记忆的
- 模型库
基于内容过滤
基于内容的过滤方法基于项目的特征化(与用户相对)和用户效用的简档。它最适合于关于项目的已知数据(例如,主要演员、发行年份、电影类型)以及用户历史上如何与推荐系统交互的问题,但是缺少用户的个人信息。基于内容的推荐器本质上是一个用户特定的学习问题,用于量化用户的效用(喜欢和不喜欢,评级等)。)基于项目特征。
更正式地说,用户 c 的项目 i 的效用 u ( c , i )是根据同一用户 c 分配给之前看到的其他项目的效用来估算的。
让我们假设是项目 i 的特征向量,而 ω ᵥ 是用户 v 的简档向量。用户简档可以被解释为用户对之前看到的所有项目的效用的总结。
基于记忆的例子
让我们以评级系统为例,对用户简档向量建模的一种方式是通过评级加权平均值,即,
那么效用 u ( c , i )就变成了
效用函数在信息检索文献中通常用余弦相似性度量来表示
其中 K 是项目和用户简档向量的维度。
基于模型的示例
朴素贝叶斯分类器已经被广泛用作推荐系统的基于模型的方法。
我们以一个视频推荐系统为例,用一个推荐的视频是否被用户点击来衡量一个用户的效用。更正式地说,这个推荐问题可以被建模为估计点击的概率(或者某些文献中的点击率),即,
根据贝叶斯定理,
根据链式法则,
来自维基百科
现在,借助于“天真的”条件独立性假设,我们有了
这里 α 是一个归一化参数,以确保所得概率位于[0,1]内。然而,这对于一些推荐系统来说是不必要的,在这些推荐系统中,我们只关心所有项目之间的相对排名。
限制
- 数据稀疏、基于记忆或基于模型,它们都利用了用户与推荐系统的历史交互。所以对于不活跃的用户,推荐可能是非常不准确的。
- 新用户,这是非活动用户的极端情况,因此使得基于内容的过滤方法不适用。
协同过滤方法通过利用跨用户信息来解决上述限制。
协同过滤
协同过滤最适合于具有已知用户数据(年龄、性别、职业等)的问题,但是缺乏项目数据或者难以对感兴趣的项目进行特征提取。
与基于内容的方法不同,协同推荐系统试图根据其他用户以前对某个项目的效用来预测用户对该项目的效用。
基于记忆的例子
重新使用评级系统示例,基于记忆的方法本质上是试探法,其基于来自其他用户的对项目的评级集合来预测用户对项目的评级,即,
其中 C 是不包括感兴趣的用户 c 的用户集合。
聚合函数的几种实现是
(1)仅仅是所有其他用户对该项目的平均评级。(2)试图通过其他用户与用户 c 的接近程度来加权其他用户的评级,并且一种测量方式是两个用户的特征向量(年龄、性别、位置、职业等)之间的相似性函数。).(3)是为了解决用户对于他们“喜欢”的意思可能具有不同的评级尺度的问题,例如,一些用户可能更慷慨地对他们喜欢的项目给出最高评级。
基于模型的示例
与基于模型的基于内容的过滤类似,基于模型的协同过滤使用历史数据(来自其他用户)来学习模型。对于评分示例,基于模型的方法是分别为每个项目建立以用户简档为特征、评分为目标的线性回归模型。
限制
类似于基于内容的方法的限制,协同过滤方法也受到下面列出的一些约束
- 数据稀疏,对于评分少的冷门项目,协同算法很难做出准确的预测。
- 新项目,这是不太受欢迎项目的极端情况,因此使得协同过滤方法不适用。
混合方法
考虑到基于内容的方法和协作方法的局限性,并且它们都解决了另一种方法的一些局限性,自然要考虑将这两种方法结合起来,这就产生了混合方法。结合的方式包括:
- 分别实现基于内容的方法和协作方法,并结合它们的预测。这本质上是一种模型集合方法。
- 将基于内容的特征纳入协作方法。一种方法是利用用户简档来测量两个用户之间的相似性,并在协作方法的聚集步骤中使用该相似性作为权重。
- 将协作特征纳入基于内容的方法。做到这一点的一种方法是对一组用户简档应用降维技术,并将其呈现为感兴趣的用户的协作版本简档。
- 跨用户和跨项目模型。这就是建立一个既有物品特征又有用户特征作为输入的模型,比如线性回归模型、树形模型、神经网络模型等。
延长
一些推荐系统对时间非常敏感(例如新闻馈送)或者受季节性影响(旅游目的地推荐)。对于这些系统,我们可能需要考虑建立时间序列模型(如 ARIMA、RNN)。还有一些系统,其中推荐与用户最后观看的项目高度相关(例如,YouTube.com),在这种情况下,基于马尔可夫的模型可能更合适。
参考
班尼特,詹姆斯和斯坦·朗宁。“网飞奖。”KDD 杯及研讨会会议录。第 2007 卷。2007.
协同推荐系统。美国专利 8949899 号。2015 年 2 月 3 日。
《YouTube 视频推荐系统》第四届 ACM 推荐系统会议论文集。2010.
Adomavicius,Gediminas 和 Alexander Tuzhilin。“迈向下一代推荐系统:对最新技术和可能扩展的调查” IEEE 知识与数据工程汇刊17.6(2005):734–749。