TowardsDataScience-博客中文翻译-2021-十四-

龙哥盟 / 2024-10-22 / 原文

TowardsDataScience 博客中文翻译 2021(十四)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

线性回归导论

原文:https://towardsdatascience.com/an-introduction-to-linear-regression-9cbb64b52d23?source=collection_archive---------21-----------------------

回归主要用于预测或解释数字数据

回归|照片由王昊拍摄

这篇文章是上一篇讨论贝叶斯统计的系列文章的继续。

波动性是股票市场固有的,但也许“迷因股票”的兴起超出了传统的理解。这篇文章不是关于这种“股票”——这是一种讽刺性的股票拼写错误,概括了千禧一代中新的投资时代精神(广义而言)。相反,我在思考乘坐$GME 过山车的神话般的感觉,这是应用线性回归的一个及时的例子;人们可以对给定的股票应用线性回归模型来预测其未来的价格。本文和后续文章将详细阐述线性回归的概念和几种相关的方法,模型分析的相关误差以及残差。

但是什么是回归呢?回归的目标是生成一个模型,该模型代表某些观察数据的最佳拟合。一个更好、更具体的说法是,回归被用来预测或解释数字数据——比我聪明的人几十年来一直在将这种模型应用于金融数据(如$GME)。但是,如果你想预测某人是否会生病,或者某人是否会穿黑色衣服,或者某项资产是否会升值或贬值,这些都不是回归,而是分类。回归是数字数据的解释模型或预测模型。在大多数情况下,我们将处理可以描述一个函数的函数,这意味着一个输出,我们可以描述一个或多个输入变量和一个输出变量之间的关系(对于线性回归)。

历史

回归基于最小二乘法或最小均方误差法。围绕最小二乘或平均误差的想法已经发展了近三个世纪。已知的第一份“平均法”出版物是德国天文学家托拜厄斯·迈耶在 1750 年发表的。皮埃尔·西蒙·拉普拉斯在 1788 年发表了一个类似的方法。最小二乘法的第一个出版物是由法国数学家阿德里安-玛丽·勒让德在 1805 年发表的。

撇开历史不谈,德国物理学家和数学家卡尔·弗里德里希·高斯很可能早在 1795 年就发展了最小二乘法,但他直到 1809 年才发表了这一方法。勒让德坚决反对任何认为高斯在 1805 年出版日期之前就已经使用这种方法的观点。

查尔斯·达尔文的表兄弗朗西斯·高尔顿在 1886 年创造了回归这个术语。高尔顿感兴趣的是确定包括人类在内的动植物的哪些特征可以说是遗传的。虽然高尔顿发明了一种现代形式的回归,但却是卡尔·皮尔逊将回归和多元回归置于坚实的数学基础之上。他在 UCL 创建了世界上第一个大学统计系。皮尔逊 1898 年的出版物提出了我们今天所理解的回归方法。

卡尔·皮尔逊|来源维基百科

自皮尔森的关键论文发表以来的一个世纪里,许多其他人扩展了回归理论。值得注意的是,约瑟夫·伯克森在 1944 年发表了逻辑回归方法,这是最早的分类算法之一。近年来,对机器学习(ML)的兴趣激增,导致回归模型的数量和类型迅速增加。

回归的类型

有各种类型的回归,包括许多非线性的,与我要讲的内容完全无关的回归;它们用于预测数字结果,但使用不同的底层技术。一些常见的回归类型有:

  • 线性—最常见
  • 逻辑—二元结果(成功/失败)
  • 多项式-当直线不是最佳拟合时
  • 阶梯式脊线和套索(常见于 ML)

最小二乘线性回归

最小二乘回归是我今天要阐述的类型。注意,大多数人会把这和线性回归混为一谈。现在这两者不一定是相同的,但只是警告你,大多数人会把这两者混为一谈。线性回归仅仅意味着你将使用一个线性参数集合来做一些事情。还有各种其他方法来进行回归,这些方法不会使用这些参数的线性集合;其中每个参数与一个变量相关联。

线性回归|来源维基百科

我们有线性回归,它最常用于描述如上图所示的直线,但对于逻辑和多项式也是如此。并且可能也适用于阶梯式脊和套索的大多数情况。所以有两种关于线性的定义——这将会令人困惑。

线性的一个定义是穿过数据的线。换句话说,一条线适合你的数据。线性的另一个定义是当你有一个参数的线性集合,每个参数与一个变量相关联。换句话说:基于解释变量的相关(目标)值的线性可预测行为。****

这是一种奇特的说法:

参数的线性集合

在上面的示例中,参数 a、b、c 与输入变量 x1、x2 和 x3 具有线性关联,x0 是偏移量。当我说变量时,那意味着它们是回归的输入。

最小二乘线性回归是借助线性代数和一些微积分推导出来的。我相信理解线性模型是理解一大堆统计和 ML 模型行为的基础。事实上,我相信大约一半的机器学习模型会使用这种形式的线性回归,至少在它们的起点。

型号选择:11 点

模型 1 |一阶线性回归,最佳拟合的简单直线

对一些数据进行回归的一个非常合理且可接受的方法(比如上面的例子)就是盯着它,然后在上面画线。你想称之为倒退,那很好。我怀疑它还能被称为线性回归,但它肯定是一个回归。这是一个非常有效的方法。现在我们将讨论回归,我们可以展示从数据点到最佳拟合线的数学规则。

数学上定义上面的线

前面我定义了线性回归,现在我将展示一个二次方程的例子,它仍然是我们定义的线性方程:

模型 2 |二阶二次回归

等效地:

我们要做的或者我们能做的是,我们可以说,“好的”,y 不是接受一个变量,即 x1 的函数的输出,而是接受两个变量的函数的输出;第一个是 x1,第二个是 x1。事实上,我们可以称 x1 乘以 x1 为变量 x2。

通过将 x1 重新标记为 x2,我们恢复了线性回归

我们可以用非直线来拟合线性方程!从这里延伸,我们基本上可以得到任何多项式。下图具有与二次示例相同的数据,但最佳拟合线不同。

模型 3 |使用与二次示例相同的数据的高阶回归

唯一真正改变的是我们对他们的划分。在这两种情况下,我们都在使用我们所谓的线性关系——从事回归业务的人(数学家/物理学家)这样称呼它。他们非常清楚这不是一条直线。但是他们声称在更高维度中,这实际上是直的;称之为超平面而非直线。

超平面在那些维度上不是弯曲的。尺寸可能是:

也许需要一个四阶。

这是毗邻拓扑学的数学领域,与粒子物理学家和爱因斯坦的广义相对论非常相关,总的来说(哈哈)!物理学家会说棒球击球的轨迹是一条直线。在高中,我们学习了这条路径是一条抛物线但是在弯曲的时空中,路径是一条直线测地线(测地线是弯曲拓扑景观中的一条“直”线)。你可能熟悉的测地线包括地球上的纬线。

所以这里要问的相关问题是,这三个过程模型中哪一个是正确的?一阶线性的?二阶线性的那个?四阶线性的那个?好吧,更好的问题是这三个中哪一个更有用,这自然需要我们知道模型的用途。

一般规则是,这是一个非常重要的规则,模型越简单,它就越有用。记住这个启发!稍后我会写正则化,这只是一种使模型更简单的方法。当你简化你的线性模型(任何模型,但这里的上下文是线性模型)时,它不仅更容易理解,更重要的是,它们工作得更好!

没有完美的数据,误差永远存在。另一个需要记住的有用的启发是“所有的模型都是错误的,但有些是有用的!”事实是,上面的一些数据可能只是错误。上面的 11 个点是训练数据。当我们观察新数据时,可能会发现,或者可能会发现,它们不会遵循有趣的曲线,即我们的高阶模型。“超平面”模型很可能就是我们所说的过度拟合的一个例子。并且过拟合的逆过程或撤销过拟合的过程被称为正则化。因此,概率的平衡表明我们的第一个模型是进行进一步分析的最有用的模型。

术语

  • ****反应(因变量):主要感兴趣的变量,我们试图预测或解释的变量。就像上面 Jupyter 笔记本中的例子一样,答案在等号的左边——“y”依赖于等号右边的值
  • ****解释性(独立)变量:试图解释反应变量的观察结果的变量。在一个等式中,如果你改变“y”(因变量),你不会改变右边的“x”变量,因此它们与“y”的变化无关

线性模型中有两种类型的参数:

  • ****y 轴截距,以上称为偏移量
  • ****斜率,上升超过游程,y 的变化除以 x 的变化。如果有多个输入,那么我们有多个斜率(我们称之为部分斜率)

作为题外话,但是我想提一下,数据通常不是线性的,因此数据需要被转换以应用回归分析。一个重要的此类转换是在处理非线性数据时进行对数转换。

国家面积与人口|来源维基百科

这个原始数据不是线性的,但是,我们可以通过应用对数变化使它看起来是线性的,这里它将是以 10 为底的对数:

同样的数据,转换后|来源维基百科

进行对数转换的原因是因为现在你的错误可能会始终一致,这很可能会更好。可以用指数线拟合数据,进行非参数线拟合,但这样误差就不一致了,它们的规模也不一样,这使得下游分析更加困难。

错误术语

在解释最小二乘回归之前,我们需要了解误差是什么:

ε表示误差,I 表示它是哪个数据点(第一、第二等。)

E(误差)是每个点和回归线之间的距离。我们选择每个点和直线之间的平方差和最小的直线。

回归线和每个点的误差

上面的线非常适合上面的五个点,但它并不完美。我们想知道的是因变量的误差有多大。添加ε项是为了弥合我们的预测值(y_hat)和实际观察值之间的差距,预测值是红点跟随绿线并与回归线相交的位置。误差是预测变量和观察变量之间的差异。这将在下面的代码分析中进一步解释。

利用一点微积分和线性代数,我们试图找到所有可能的回归线的误差总和的最小值。这个总和就是最佳拟合线。这是非常费力的计算。相反,如果你说你想最小化这个值的平方,结果是有很好的解析解。这就是为什么我们做最小二乘拟合。所以我们并不试图最小化这些虚线,或者这些虚线的总和,而是试图最小化它们的平方和。那么平方和是多少呢?

回归线误差平方和的可视化

现在,平方相加。这些正方形的最小总面积就是我们认为的最佳拟合线。除了漂亮的解析解之外,这种方法的优点还在于它惩罚了较大的误差——惩罚了异常值。在上例中,假设最大误差比最小误差大 6 倍。在最小二乘回归中,误差是最小平方的 36(6×6)倍。

显式解决方案存在使用微积分

我们让计算机求解上面的方程,通过摆弄斜率和截距来找到最小二乘方的和。从实际(观察)值中减去预测(理论)值并求和。

Python 示例:回归模型

下面的代码可以在 Jupyter 笔记本中运行,以帮助获得最小二乘线性回归的感觉和可视化。

注意:我们使用合成数据,因为我们对发生的事情有很大的控制权。合成数据并不总是最好的。

# relevant imports
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline# synthetic data points between 0 and 10 with standard deviation of #the errors of 1 (std deviation of y should be around 3-the square #root of 10)
n_points = 80
x_start, x_end = 0, 10
y_start, y_end = 0, 10
y_sd = 1 # std deviation of the errors# data columns, the y values are the errors added to the x values
x_data = np.linspace(x_start, x_end, n_points)
y_error = np.random.normal(loc=0, scale=y_sd, size=n_points)
y_data = np.linspace(y_start, y_end, n_points) + y_error# create dataframe
syn_data = pd.DataFrame({‘x’:x_data, ‘y’:y_data})syn_data.head()

我们 80 个合成数据点的前五行

现在让我们将数据可视化—注意数据的强线性。记住这个练习的目的是回答这个问题“如果我们知道 X 的值,我们能预测 Y 的值吗?”我们相信,通过画出最佳拟合线,如果有人给我们一个 X,比如说一个我们还没有的 X,那么我们就能算出 Y 值是多少。

plt.plot(syn_data[‘x’], syn_data[‘y’], ‘ko’) # ko = black points
plt.grid(True)
plt.xlabel(‘x’)
plt.ylabel(‘y’)
plt.title(‘x vs y’)
plt.show()

我们的合成数据-在大多数情况下,x 值大约是 y 值

建立线性回归模型

按照一个简单的模板,我们可以建立我们的模型。您可能熟悉一个可以做到这一点的常见包:Sci-Kit Learn。sklearn 的一个怪癖是它最适合 NumPy 数组,这正是它所习惯的。以下模板为模型定型和评估重塑和转换数据:

# standard lin reg template# imports
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score# create numpy arrays for the x (independent) and y (dependent) #variables
x = syn_data.x.values.reshape(-1,1)
y = syn_data.y.values.reshape(-1,1)# model initialization
regression_model = LinearRegression()# train the model (fit data)
regression_model.fit(x, y)

y_predicted = regression_model.predict(x)# model evaluation
rmse = mean_squared_error(y, y_predicted)
r2 = r2_score(y, y_predicted)# printing values
print(‘Slope:’ ,regression_model.coef_)
print(‘Intercept:’, regression_model.intercept_)
print(‘Root mean squared error: ‘, rmse)
print(‘R2 score: ‘, r2)# plotting values
plt.scatter(x, y, s=10)
plt.xlabel(‘x’)
plt.ylabel(‘y’)plt.plot(x, y_predicted, color=’r’)
plt.show()

这条线很适合数据

当我们评估模型的性能时,下面将更详细地解释统计值。

绘制残差

以下是理解您的回归模型有多好的重要工具——残差图。正在发生的是,对于每个点,观测值和预测值之间的差异被绘制出来。

import seaborn as sns
sns.residplot(x, y)
plt.show()

预测 y 值与实际 y 值的差异

残差是误差,我们之前画过了。x 轴是 x 值。y 轴是实际 y 值和预测 y 值之间的差异,即误差。

from sklearn import linear_model
# from sklearn.linear_model import LinearRegression# initialize the model.
linear_model = linear_model.LinearRegression()# define x and y
x_input = syn_data['x'].values.reshape(n_points, 1)
y_output = syn_data['y'].values.reshape(n_points, 1)# fit the model to the existing data with lm.fit(x,y)
linear_model.fit(x_input, y_output)# fit model to make predictions
y_pred = linear_model.predict(x_input)# plot
plt.scatter(x_input, y_output)
plt.plot(x_input, y_pred, linewidth=2)
plt.grid(True)
plt.xlabel('x')
plt.ylabel('y')
plt.title('x vs y')
plt.show()# model parameters
print('Intercept: {0:.5f}'.format(linear_model.intercept_[0]))
print('Slope : {0:.5f}'.format(linear_model.coef_[0][0]))

统计模型包

另一个较老且较少使用的 Python 包是 Stats Model sm。下面的代码重复了 Sci-Kit 的学习工作。请注意两个 w/r 在输出显示方式上的细微差异。

注意:统计数据是相同的,但是软件包之间的表示和健壮性是不同的。sklearn 是这几天学习的首选套餐。

import statsmodels.formula.api as sm# ols = ordinary least squares
ols_model = sm.ols(formula = ‘y ~ x’, data=syn_data)# fit the model
results = ols_model.fit()print(‘Intercept: {0:.5f}’.format(results.params.Intercept))
print(‘Slope : {0:.5f}’.format(results.params.x))

# add predicted to dataframe
syn_data[‘predicted’] = y_pred# add residuals to dataframe
syn_data[‘resids’] = y_output — y_pred# verify data is as expected
syn_data.head()

# coefficients of line of best fit
m = linear_model.coef_[0]
b = linear_model.intercept_
print(‘m = {}’.format(m[0]))
print(‘b = {}’.format(b[0]))

解释参数

知道如何解释参数非常重要(由于创建数据时的随机种子,您的结果会有所不同)。

  • y 截距(b) :当 x 为零时,y 为-0.13…
  • slope (m) :当我们将 x 增加 1 时,我们预计 y 将增加 1.03…

很简单,我敢打赌大多数读者对这些基础知识都有很强的掌握,但重要的是要让每个人耳目一新,并建立在一个坚实而通用的基础上。

模型汇总统计

这就是 SM 的闪光点——漂亮的成果总结。目前,本地显示的数据比我们理解最小二乘回归所需的数据要多得多。残差也在 OLS 报告后绘制。

import statsmodels.formula.api as sm
import seaborn as snsols_model = sm.ols(formula = ‘y ~ x’, data=syn_data)results = ols_model.fit()# print slope (m) and y-intercept (b)
print(‘Intercept, Slope : {}’.format(results.params))print(‘\nSSE, SST, SSR, and RMSE:’)
mean_y = np.mean(y_output)
sst = np.sum((y_output — mean_y)**2)
ssr = np.sum((y_pred — y_output)**2)
sse = np.sum((y_pred — mean_y)**2)print(‘Sum of Squares Explained (SSE): {}’.format(sse))
print(‘Total Sum of Squares (SST): {}’.format(sst))
print(‘Sum of Squared Residuals (SSR): {}’.format(ssr))
print(‘RMSE: {}’.format(np.sqrt(results.mse_resid)))# print linear regression statistics
print(‘\n’, results.summary())

# plot histogram of the residuals
sns.distplot(results.resid, hist=True)
plt.xlabel(‘Residual’)
plt.ylabel(‘Frequency’)
plt.title(‘Residual Histogram’)
plt.show()

关于上面绘制的残差,首先要注意的是,它们大致是正态的。这是可以预料的,因为合成数据就是这样产生的,所以这有点像自我实现的预言。y 数据是从添加到随机生成的 x 数据的误差中创建的,y 数据具有+/-1 的标准偏差。

回归模型的评估

现在我们已经建立了一个回归模型,我们可以定量地评估我们的回归模型的性能。回归模型的评估是基于误差的测量。

如果我们想知道我们做得有多好,我们必须考虑什么是好的基准。一个常见的简单基准是看看我们是否能比仅仅预测目标变量的均值更好。****

我们定义了以下术语:

现在,我们需要定义以下误差指标:

  • 残差平方和(SSR) :这是最小二乘法能够用最佳拟合线最小化的值。回归的目标是最小化这个量。

回归的目标——最小化它

  • 总平方和(SST) :这是对目标均值预测有多差的度量

  • 解释的平方和(SSE) :这是(SST — SSR)的逐点差平方和。你也可以认为这是一种衡量,我们对变异的解释比均值好多少

请注意 SST = SSR + SSE

  • 只有在对训练数据进行回归时,该公式才成立!如果你在测试数据上这么做,这个公式就不再成立了。这个公式适用于你的决定系数(COD)与你的皮尔逊相关系数 R 相同的情况。他们不一样!它们有时可能是相同的,但仅在对训练数据进行最小二乘拟合的情况下,而不是在使用测试数据或不使用非最小二乘拟合的情况下。SSR 可以变得比 SST 大,导致 R 为负!

线性回归模型误差的可视化

我们现在可以谈论均方根误差(RMSE)** 。我们这样做的原因是“平方和误差”(也称为均方误差)的单位是 x 。要将误差转换为单位 x ,我们需要均方误差的平方根或残差平方和的平方根。这是 RMSE:**

记住回归的目标是最小化残差, SSR 。具体来说,我们希望用我们的模型尽可能解释原始数据中的最大方差。我们可以用决定系数(COD)来量化这个想法,也称为 R :

仅使用最小二乘拟合和测量训练数据进行校正

只要

****

****R 是模型解释的原始数据方差的分数。一个完美解释数据的模型,R = 1。一个完全不能解释数据的模型 R = 0。这意味着训练数据分布得如此均匀,以至于您无法通过它绘制任何最佳拟合线。你可以在数据中画一条线,但这条线不会是最佳拟合线。

然而,R 并不完美:

  • r 不针对自由度进行偏差调整
  • 更重要的是,模型参数的数量没有调整。随着模型参数数量的增加,SSR 一般会降低。没有调整,你会得到一个错误的模型性能

我们通过定义调整后的 R (R adj)** 来解决这个问题:**

****

在哪里

****

这使得 R adj 为:

在哪里

****

可以重写:

现在,我们有了一个随着更多参数的增加而减少的指标,奖励简单性——记住前面的内容,简单的模型比复杂的模型更受欢迎。

结论

到目前为止,我们已经介绍了许多回归概念:

  • 直线的单一回归方程为

  • 使用 Python 模型对象linear_model.LinearRegression()初始化模型
  • 使用fit方法使模型符合数据
  • 使用predict方法计算因变量(y)的分数(预测值)
  • coef拉模型参数——m(斜率)和 b(y 轴截距)——用intercept
  • 残差是 y 输出和 y 预测之间的差值
  • 使用statsmodelsseaborn库获取汇总统计数据并绘制诊断图
  • sklearn优于sm包,它使用起来更简单,也更健壮
  • 什么是残差,为什么我们要画它们

我们用summary方法评估了 OLS 回归结果

  • SSR (残差平方和)是与回归线的误差差(尽量最小化)
  • SST ( 总和的平方和)是目标平均值的差值
  • SSE (解释的平方和)是回归直线到平均值的变化
  • RMSE (均方根误差)是 SSR 的平方根
  • R 是由模型解释的原始数据的方差的分数,想要一个接近 1 的数字
  • SST = SSR + SSE 只适用于你的决定系数(COD)与你的皮尔逊相关系数 R 相同的情况。对于训练数据的最小二乘回归,是的。在这种情况之外,根据测试数据或当 SSR > SST 时,公式不成立

在我的下一篇文章中,我将介绍多元回归和用回归模型自举!

在 Linkedin 上找到我

物理学家兼数据科学家——适用于新机遇| SaaS |体育|初创企业|扩大规模

机器学习竞赛简介

原文:https://towardsdatascience.com/an-introduction-to-machine-learning-competitions-133cce76e219?source=collection_archive---------12-----------------------

通过这三个竞争平台进行竞争、练习和赢取

由 Serghei Trofimov 在 Unsplash 拍摄的照片

学习数据科学最重要的一个方面是将你的知识付诸实践。在我看来,数据科学是最好通过实践来学习的东西。

如果你在正规教育或工作经验之外学习数据科学,找到练习你所学技能的地方可能会很棘手。机器学习竞赛为数据科学技术的实际应用提供了一个非常有效的平台。

参加数据科学竞赛可以帮助你学习、赚钱,还可以提供项目组合,帮助你在该领域获得第一份工作。

作为初学者或更高级的从业者参加机器学习竞赛提供了一系列好处,包括:

  • 建立一个可以展示你技能的项目组合。
  • 将你的技能与该领域的其他人进行比较。
  • 利用您的技能解决接近真实世界的数据科学问题。
  • 学习新技能。
  • 潜在的收入,有些奖金高达 20 万美元。

有几个网站举办机器学习比赛。大多数都有类似的格式。这通常包括技能水平范围内的各种比赛的可用性,以及无奖励练习问题和附有经济奖励的比赛。

比赛本身通常会提供一个数据集和要解决的问题,以及一个排行榜,当你提交你的结果时,你会在那里。大多数比赛允许无限的条目,这意味着你可以不断完善你的模型,提高你的分数。

这是一个很好的学习方式,因为排行榜让您了解潜在的模型性能,并且您可以通过反复试验,很好地了解最适合改进模型以解决特定问题的技术和工具。

在本文的剩余部分,我将介绍三个我最喜欢的机器学习竞赛网站。这将包括每个网站的简要说明,谁最适合比赛,以及你可能获得的奖励水平的想法。

卡格尔

最适合: 从初学者到高级修炼者的所有人。

典型头奖: $10 万。

突出特点: 有一个很棒的社区为初学者提供支持。

Kaggle 比赛主页。图片作者。

Kaggle 可能是最广为人知的机器学习竞赛网站。它还建立了一个优秀的社区来支持人们学习数据科学。教程、课程、示例内核和一个论坛都提供支持,帮助初学者开始比赛。

Kaggle 竞赛有一些重要的奖励,最高奖金在 10 万美元左右。比赛的复杂程度和所需的技术水平也各不相同。这意味着,无论你是希望将所学付诸实践的初学者,还是希望进一步拓展技能的高级从业者,都有合适的挑战来竞争。

分析 Vidhya

最适合: 初学者。

典型头奖: 学习潜力。

脱颖而出特色: 竞赛涵盖的问题比较全面。

分析 Vidhya 竞赛页面。作者图片

Analytics Vidhya 是另一个出色的数据科学社区,也定期举办机器学习竞赛。然而,与 Kaggle 不同的是,大多数比赛纯粹是为了学习,而不是任何经济奖励。这样做的好处是,比赛通常更适合该领域的初学者,并提供了一个很好的机会来与其他也在学习的人对比你的技能。

总有一系列的竞赛,涵盖了数据科学的大多数关键领域,包括自然语言处理、图像识别、一般分类和回归以及预测。

驱动数据

最适合: 中级到高级武者。

典型头奖:20 万美元。

脱颖而出特色: 争夺头奖的机会,同时为解决社会问题做出贡献。

驱动数据竞赛页面。图片作者。

DrivenData 的目标是众包数据驱动的解决方案来解决一些世界上最大的社会问题。因此,这个网站上的比赛让你能够学习和竞争奖品,同时还有助于解决重要的社会挑战的额外奖励。

这些比赛通常相当具有挑战性,但会吸引一些非常大的经济回报。目前提供的头奖价值 20 万美元。除了这些更难的问题,还有一些初级水平的练习问题。虽然这些通常没有奖金。

在这篇文章中,我已经给出了三个机器学习竞赛网站的描述。然而,还有许多其他地方可以竞争,如 Innocentive 、 Codalab 和 CrowdANALYTIX 等等。数据科学竞赛提供了一种将您的技能付诸实践的有用方法,也是一个学习的好地方。

如果你是独立学习,这也是了解你的技能水平的一个很好的方法。如果你不像在正规教育中那样受益于同龄人或通过考试,就很难了解你的学习进展如何。参加机器学习比赛并了解自己能够在排行榜上获得多高的名次是实现这种了解的一个绝佳方式。

如果您目前正在学习数据科学,无论技能水平如何,请从今天开始参加竞赛。你越早开始在实践中应用你的技能,你就越早发现你不知道的地方和你需要改进的地方。这是迄今为止最快的学习方法。在你知道之前,你将在排行榜上名列前茅,并赢得那些 Kaggle 奖牌!

感谢阅读!

我每月发一份简讯,如果你想加入,请通过此链接注册。期待成为您学习旅程的一部分

面向生产/多任务生产的机器学习工程介绍——多任务生产中的阶段

原文:https://towardsdatascience.com/an-introduction-to-machine-learning-engineering-for-production-mlops-phases-in-mlops-43fd22567366?source=collection_archive---------21-----------------------

(图片作者来自 Canva )

关于机器学习模型生产阶段的讨论,即范围、数据、建模和部署。

欢迎回来!这将是 MLOps 系列的第二篇文章。之前,我们简要介绍了生产中面临的挑战以及应对这些挑战的一些简单解决方案。如果你没有机会看我以前的文章,你可以在这里查看。

现在,正如我们之前讨论的,生产部分可以大致分为 4 个阶段。在本文中,让我们探索这些阶段以及它们各自的真正含义。

1.辖域

简而言之,范围界定有助于确定问题的可行解决方案。让我们考虑一个例子,你正在为你的公司做一个手写识别项目。现在,解决这个问题的一些初始步骤可以是查看这个问题的基准论文/开源实现。通常,对于大多数项目来说,这是一个很好的起点,因为在你之前几乎总会有人试图解决相同的问题陈述。在此之后,您可以将您的数据提供给这个开源模型并对其进行微调,或者从开源模型中提取一些数据并制作您自己的模型。基本上,查看这些预先存在的解决方案可以让您对可达到的精度水平有一个基本的了解。这就是范围界定所需要的。范围界定中涉及的一些要点是-

  • 集思广益解决商业问题
  • 集思广益人工智能解决上述问题
  • 评估解决方案的可行性和潜力(我认为这非常重要)

这就是范围界定的本质。它帮助你或你的团队更好地了解手头的问题以及如何着手解决它。

2。数据

众所周知,数据在很大程度上统治着人工智能世界。我们的模型,至少在监督学习的情况下,只和我们的数据一样好。重要的是,尤其是在团队中工作时,要对你所拥有的数据保持一致。考虑我们前面定义的相同的手写识别任务。假设你和你的团队决定暂时丢弃点击不好的图片。现在,什么是点击不好的图像?对你的队友和你来说可能都不一样。在这种情况下,建立一套规则来定义什么是点击不好的图像是很重要的。也许如果你很难在一页上读到 5 个以上的单词,你会决定扔掉它。诸如此类的东西。即使在研究中,这也是极其重要的一步,因为数据和标签的模糊性只会给模型带来更多的混乱。

另一件需要考虑的重要事情是您正在处理的数据的类型,即结构化或非结构化。你如何处理你拥有的数据很大程度上取决于这个方面。非结构化数据包括图像、音频信号等,在这些情况下,您可以执行数据扩充来增加数据集的大小。然而,对于结构化数据,数据扩充是不可取的。标记也是一样——作为人类,我们发现非结构化数据比结构化数据更容易标记。

处理数据时要记住的一些要点是-

  • 干净的标签至关重要
  • 贴标机必须就贴标的标准程序达成一致,以确保一致性
  • 仅将人的水平的性能(我们将很快对此进行更多讨论)作为非结构化数据任务的基准
  • 确保您在收集数据时从容不迫,但同时也开始处理模型。让数据收集方法在本质上是迭代的。

3。建模

许多人可能认为这是最重要的阶段,然而,这是不正确的。我仍然认为数据阶段要重要得多。话虽如此,我承认建模也是一个重要的阶段。它围绕着微调,开发你的模型,并试图达到一定程度的准确性。不像简单的项目,在开发/测试集上做得好可能是模型做得好的指示,这不是 MLOps 的情况。这是因为部署时模型将与之交互的真实世界的数据可能会导致模型的行为方式与预期的不同,因此了解如何处理您的模型非常重要。

有一些关键的步骤来确保你得到正确的建模部分。大致可以总结如下-

  • 建立基线:一些经常被忽视的事情(个人犯了这个错误,请不要犯这个错误内心尖叫),建立基线非常重要,因为它有助于给你一个如何前进的想法。它基本上包括查阅相关领域的先前研究,或者看看做同样事情的其他公司的产品,看看他们的模型有多好。这再加上了解所需/可用的计算资源,可以帮助您复制一些最先进的(SOTA)结果。DL 社区的一个好处是 SOTA 的大部分论文都是开源的。这使得不仅建立基线变得容易,而且建立相似的或者在某些情况下甚至更好的模型也变得容易。对于非结构化数据,可以以人的水平的表现作为评判你的模型的标准。考虑前面给出的手写识别任务——如果一个开源模型能够以大约 20%的错误率阅读单词,那么这就是你的任务基线。如果你觉得你有办法复制 SOTA 的论文,那么你也可以用他们的结果来建立你的基线。都是主观的。
  • 以数据为中心的方法:以数据为中心的方法正在社区中迅速获得牵引力,它涉及到关注数据而不仅仅是模型。努力尝试并确保数据的高质量并得到保持。虽然这在研究中并不常见,但在我看来,以数据为中心的方法是改善模型结果的唯一确定的方法。确保您的数据覆盖重要的测试用例,被一致地定义,并且尽可能平均地分布,这些都是以数据为中心的方法的一部分。就我个人而言,在我参与的项目中,每当我尝试采用以数据为中心的方法时,我总能看到对看不见的数据的准确性略有提高。它可以是一些小事情,比如在将图像提供给模型之前修复图像中的光照条件等等。
  • 实验跟踪/版本控制:devo PS 中一个众所周知的步骤,版本控制帮助我们跟踪变化,并让我们在应用程序可能抛出错误的情况下恢复到以前的工作版本。在 MLOps 中,跟踪所用算法的代码超参数数据集(如果有的话)的变化,以及为某组超参数获得的结果的种类等非常重要。

4.部署

现在我们已经准备好了模型,下一步是什么?当然是部署!这包括在现实环境中发布您的模型,或者将其集成到为其开发的应用程序/边缘设备中。即使在部署中,也有某些类型的部署。这些是-

  • 影子部署(Shadow Deployment):在这种类型的部署中,模型被部署,但是最终的决定由人做出,不管模型预测什么。这样做通常是为了衡量模型做得有多好以及它在哪里失败了。
  • 金丝雀部署:在这种类型的部署中,模型只暴露给一小部分允许它做出决策的数据。例如,模型可能只暴露于每 1000 张图像中的 10 张。根据模型的表现,流量会逐渐增加,或者模型会被拉回并进行调整。
  • 蓝绿部署:在这种部署中,流量逐渐从旧版本或版本迁移到新版本或绿版本。这有助于防止任何类型的停机,并且在任何错误/错误的情况下,应用程序可以很容易地回滚到以前的稳定版本或蓝色版本。

接下来要看的是对我们部署的模型的监控。请记住,部署是一个迭代的过程。因此,总有改进的空间,唯一可以改进的方法是,即使在部署后也要监控他们的模型。有许多软件可以用来监控指标等。我可能会在以后的文章中谈到这些。现在,让我们关注一些关键点,以确保我们部署的模型能够顺利运行-

  • 考虑服务器负载的种类并对其进行监控
  • 检查所有可能的情况,在这些情况下你的模型可能会失败或者可能会出错,然后尝试纠正这些情况或者确保正确的错误处理
  • 和你的团队一起,决定几个关键指标来判断你的模型的性能
  • 不要固执于你的性能指标,对变化保持开放的态度,并且总是尝试和致力于确定最适合你的模型的指标
  • 确保不仅模型而且 ML 管道都受到监控。有时,由于预处理步骤中的一个小错误可能会导致错误,这可能会导致整个系统的崩溃(在那里,搞乱了输入形状,并试图通过只查看模型的代码来解决错误;-😉
  • 对于您正在处理的问题陈述,了解真实世界的数据可以/可能变化得有多快。

这就对了。关于 MLOps 的阶段,我要说的就是这些。如果你已经做到了这一步,并且想了解更多关于 MLOps 的知识,请随时查看我的 GitHub 库 。我会用相关的材料和 Jupyter 笔记本不断更新它!

参考文献

  1. https://www . red hat . com/en/topics/devo PS/what-is-blue-green-deployment
  2. https://www . coursera . org/learn/introduction-to-machine-learning-in-production
  3. https://cloud . Google . com/blog/products/ai-machine-learning/key-requirements-for-an-m lops-foundation
  4. https://blog.ml.cmu.edu/2020/08/31/3-baselines/
  5. https://blog . tensor flow . org/2021/01/ml-metadata-version-control-for-ml . html

面向生产/物流的机器学习工程导论——概念和数据漂移

原文:https://towardsdatascience.com/an-introduction-to-machine-learning-engineering-for-production-part-1-2247bbca8a61?source=collection_archive---------31-----------------------

(图片作者来自 Canva )

简要介绍数据漂移、概念漂移和 MLOps 中面临的挑战,以及解决这些问题的一些最佳实践。

可以肯定地说,我们大多数人从机器学习/深度学习开始,都能够轻松地开发基本模型,并取得不错的结果。然而,从个人经验来说,我们很少接触到我们模型的部署,特别是如果我们对 Flask、Django 等框架几乎没有经验的话。

许多机器学习课程都复习了解决某些类型问题所需的算法、代码片段和库的基础知识。然而,我还没有特别找到任何专门针对生产相关主题的课程。直到 DeepLearning.ai 就这个话题发布了他们的特殊化!这篇文章(或者可能是一系列文章)本质上是这个专业的第一门课所讲内容的总结,同时也混合了我对这个主题的看法。

每个 ML/DL 项目大致可以分为 4 个阶段——即范围界定数据建模部署。现在,在我们查看每个阶段(可能在后续文章中)和最佳实践之前,重要的是要理解在现实世界中生产可伸缩模型所面临的挑战。

ML 项目开发阶段(图片由作者提供)

模型部署后经常出现的两种情况是概念漂移数据漂移。

  • 概念漂移指的是在一段时间内输入数据‘x’和输出数据‘y’之间关系的变化。 Eg- 考虑一个房价预测模型。在像疫情这样的异常情况下,房地产价格会突然发生变化,因此模型可能不再做出准确的预测。在正常情况下,一个价值 500 万印度卢比的住宅现在可能要花费 750 万印度卢比才能获得同样数量的功能,如卧室、空调、平方英尺面积等。

概念漂移(图片作者提供)

  • 数据漂移是指输入特性的变化。从数学上来说,是变量分布的变化导致了它们意义的变化。考虑一个处理银行交易的模型。通常,必须有某种交易限制,超过某个阈值的任何交易都可能导致信用卡出于安全目的而被冻结。然而,再想想疫情的情况,那里由于必需品的有限供应而出现了支出增加(或囤积必需品)的情况。这将导致正常的 ML 模型阻塞每个人的卡以限制交易。因此,由于正常事务数量(输入特征)的变化,模型的性能不如预期。

数据漂移(图片由作者提供)

除了部署后面临的这些挑战之外,在部署您的模型之前需要问的一些关键问题是-

  • 该模型是否将被实时使用?
  • 部署模型的设备可以访问互联网吗?
  • 该模型将部署在边缘设备还是云上?
  • 需要哪种计算资源?

如果这些问题能够得到回答,那么作为一名机器学习工程师,你的生活会轻松很多,而且在项目中途进行更改时也不会浪费太多时间。令人惊讶的是,我还发现这些问题中的一些在开始任何以研究为导向的项目时很有用。

现在,因为我已经告诉了你们所面临的挑战,所以讨论解决这些挑战的可行方案是有意义的。这些可以大致概括如下-

  • 在发生变化/漂移之前和之后,使用所有可用的数据重新训练您的模型。
  • 微调模型超参数以尝试和调整模型可能遇到的新模式会有所帮助。此外,这比数据相关的方法相对容易。一个优势是模型部署不必是一次性的过程,而是本质上的迭代。每隔几周/几个月,你就可以推出你的模型的一个改进版本,而且几乎总是这样,因为现在你的模型对真实世界的数据有了更多的经验。
  • 最后,如果你觉得你已经获得了足够的新数据,丢弃旧数据。数据越新鲜,你就越容易训练你的模型来适应问题陈述(在大多数情况下)。

这就对了。这是对 MLOps 的简要介绍,还有很多内容要介绍,但我认为这是结束本文的好地方。在接下来的文章中,我们将更详细地讨论开发和部署模型的 4 个阶段,并进一步深入研究用于确保平稳操作的技术。

如果你已经做到这一步,并想了解更多关于 MLOps 的信息,请随时查看我的 GitHub 库 。我会用相关的材料和 Jupyter 笔记本不断更新它!

参考

  1. https://machinelingmastery . com/gentle-introduction-concept-drift-machine-learning/
  2. https://www . explori um . ai/blog/understanding-and-handling-data-and-concept-drift/
  3. https://towards data science . com/machine-learning-in-production-why-you-should-care-data-and-concept-drift-d 96d 0 BC 907 FB 0
  4. https://youtu.be/06-AZXmwHjo
  5. https://www . coursera . org/learn/introduction-to-machine-learning-in-production

非概率抽样方法介绍

原文:https://towardsdatascience.com/an-introduction-to-non-probability-sampling-methods-b74c76f7f710?source=collection_archive---------7-----------------------

探索数据科学的其他采样技术

克里斯汀娜·戈塔迪在 Unsplash 上的照片

本文是上一篇文章的续篇,介绍概率抽样方法。抽样方法不仅在统计学研究中有相关作用,而且在许多机器学习方法中也有相关作用,例如 K-fold 交叉验证和基于决策树的模型。为此,我决定对这些方法进行更多的研究。此外,它们可以主要分为两大类,概率方法和非概率方法。由于概率技术在上一篇文章中已经介绍过了,现在我们将学习另一类技术。

非概率抽样方法

在非概率抽样方法中,每个被选总体元素的概率是未知。这是与概率方法最明显的区别,在概率方法中,被选择的群体中的每个单元的概率是已知的并且可以被估计。非概率抽样方法的另一个重要方面是,研究者的角色在他/她所进行的研究中起着核心作用。参与者的选择取决于数据收集者的主观性。虽然它们提供了许多优势,如简单的组织、低成本和执行速度,但使用这些技术也有缺点,在进行任何市场或其他类型的研究之前必须考虑这些缺点:

  • 所选单位的选择依赖于研究者的判断,因此,样本中可能存在选择偏差
  • 样本不具有代表性,因此,对样本进行的结果不能扩展到所有总体
  • 不可能估计结果的精确度。

你可能会问自己为什么要使用这些方法,因为它们有很多缺点。这是因为概率抽样方法在金钱和时间上是昂贵的,并且不可能有一个完整的人口列表。因此,非概率方法提供了一种更简单、更便宜的收集数据的方法。

作为概率抽样方法,非概率抽样方法可以进一步分为四类。

非概率抽样方法:

  1. 配额抽样
  2. 判断取样
  3. 方便取样
  4. 雪球取样

1.定额抽样

作者插图

配额抽样可能与分层抽样相混淆,因为它们都是根据某些特征,如性别、年龄和教育程度,将人口分成不同的阶层。此外,团队需要内部同质,内部异质。

即使乍看起来相似,配额抽样在许多方面也不同于分层抽样:

  • 每个组由配额表示,配额是要调查的单元的数量
  • 为每个阶层选择单位时考虑了它在整个人口中的分布。
  • 在每个名额内,面试官可以自由选择面试的参与者。

例如,我们可以按性别研究 2020 年人口为 1 万的超级马里奥 Run 应用内支出者。如上表所示,我们计算每一组在总体中的百分比,然后,研究人员可以计算他需要每一组多少个样本来保持相同的比例。在这种情况下,我们抽取了 500 个单位的样本,其中研究者采访了 400 名男性和 100 名女性。

优点:

  • 这既省时又省钱,尤其是在分层抽样方面。

缺点:

  • 由于面试官的谨慎或不回答的偏见,结果可能会被扭曲
  • 配额样本会产生选择偏差

2.判断抽样

判断取样。作者插图。

判断性抽样,也称为目的性抽样,考虑了研究者的判断。对于调查研究,他/她选择参与者,因为他认为他们是人群的代表。一般来说,当只有有限数量的人具有特定的特质时,这是有用的。

例如,如果你想调查技术工作中的性别差距,样本不是随机选择的,而是为特定目的而选择的。应该有一些标准来选择受访者。我们可以只考虑来自美国、加拿大和英国的 35 岁以下的男性和女性。此外,参与者至少应完成科学领域的学士学位。

优点:

  • 又省时又划算
  • 它适合于研究某个文化领域,在那里需要专家的知识

缺点:

  • 研究人员的知识和人口的实际情况之间的差距越大,就可能导致较高的选择偏差

3.方便抽样

方便取样。作者插图

在方便抽样中,研究者选择任何对他“方便”的人,即可以立即回答问题的人,没有任何特定的标准。很多时候,参与的人都是志愿者。招募人员没有特定的策略:研究人员可以招募朋友、家人或社交媒体中的人。这种方法导致选择有偏差的样本,不能代表总体。

大多数时候,它构成了一个非常危险的数据来源,因为它会带来关于所研究现象的误导信息。一个典型的例子是,当你在网上点击一个选项,给出你对一个敏感话题的看法,比如政治。它会导致错误的结论,从而出现极端的观点。

优点:

  • 它既便宜又快捷

缺点:

  • 这导致样本不具有代表性

4.滚雪球抽样

滚雪球抽样。作者插图

在滚雪球抽样中,研究人员要求已经招募的人识别其他潜在的参与者,等等。因此,样本的单位像滚雪球一样增加。它特别适合于稀有人群,对于稀有人群,不可能有人群列表,并且很难在区域内定位结果,即使是很少的人。

例如,如果我们想对没有居住许可的移民的工作条件进行研究,收集数据可能会很困难。最快的方法是联系一个移民,让他联系其他他认识的人。

优点:

  • 这对于市场研究或关于敏感话题的研究很有用。

缺点:

  • 样本可能不具有代表性,因为它不是随机的,而是取决于研究者直接或间接接触的人
  • 这很费时间

最终想法:

在这篇文章中,我提供了非概率抽样方法的概述。总的来说,它们具有成本和时间效益,但同时,获取非代表性样本的风险也很高。它们应该在没有完整的人口名单和概率方法不能应用的情况下使用。与概率抽样方法不同,非概率抽样方法用于数据收集。希望这个故事和之前关于概率抽样方法的故事帮助你掌握了抽样方法。感谢阅读!祝你有愉快的一天。

你喜欢我的文章吗? 成为会员 每天无限获取数据科学新帖!这是一种间接的支持我的方式,不会给你带来任何额外的费用。如果您已经是会员, 订阅 每当我发布新的数据科学和 python 指南时,您都可以收到电子邮件!

Python 中 Matplotlib 绘图简介

原文:https://towardsdatascience.com/an-introduction-to-plotting-with-matplotlib-in-python-6d983b9ba081?source=collection_archive---------20-----------------------

UCL 数据科学协会工作坊 7:创建一个基本图形,在同一个图形上绘制不同的信息,并创建多个支线图形

尼古拉斯·卡佩罗在 Unsplash 上拍摄的照片

今年,作为 UCL 数据科学学会的科学负责人,该学会将在整个学年举办一系列 20 场研讨会,涵盖的主题包括数据科学家工具包 Python 和机器学习方法简介。每一篇文章的目标都是创建一系列的小博客,这些小博客将概述要点,并为任何希望跟进的人提供完整研讨会的链接。所有这些都可以在我们的 GitHub 资源库中找到,并将在全年更新新的研讨会和挑战。

本系列的第七个研讨会介绍了 matplotlib python 包,它是数据科学家工具包系列的一部分。在本次研讨会中,我们将介绍如何构建一个基本的绘图,在同一个图表上绘制不同的信息,以及跨多个轴绘制信息。虽然这里将分享一些亮点,但完整的研讨会(包括自测题)可以在这里找到。

如果您错过了我们之前的任何研讨会,您可以在以下链接中找到最后三场:

什么是 Matplotlib?

Matplotlib 是另一个应该包含在任何数据科学家工具包中的核心数据科学库,以及之前介绍的 Numpy 和 Pandas 库。这个库的主要目的是创建可视化,以便能够更好地理解您所拥有的数据,pandas 基于这个库构建了自己的功能。

在 Matplotlib 网站上描述为:

Matplotlib 是一个用于在 Python 中创建静态、动画和交互式可视化的综合库。

该库的目标和目的是使绘图尽可能简单,因为它还声明:

Matplotlib 让简单的事情变得简单,让困难的事情变得可能。

虽然 Python 中有许多其他可视化库,包括 seaborn 和 plotly ,但这通常是你学习的第一个可视化工具,因此这也是我们在一个研讨会中讨论它的原因。

创建您的第一个情节

在创建任何图之前,我们需要做的第一件事是实际创建我们将用于绘图的数据!因为我们已经了解了 Numpy 库及其丰富的功能,所以我们可以使用 Numpy 数组及其数学功能来创建我们可以绘制的数据。我们可以这样做:

# Creating an array with 100 values from 0 to 2pi
x = np.linspace(0,2*np.pi,100)# An array with the sine of all the values in array x
y = np.sin(x)

现在我们有了 x 和 y 的数据,我们可以开始创建我们的图了!

为此,我们可以从创建一个相当基本的图开始,其中我们将数据非常简单地显示为轴上的一条线,如下所示:

# Produces the figure
plt.figure()# Plots the sine function
plt.plot(x,y)

作者图片

简单来说,我们只使用了两行代码来创建我们的图表(您甚至可以删除第一行,它仍然可以工作!).那是多么美好和简单啊!

当然,这是一个相当基本的情节,所以我们可以开始改善它。我们注意到的第一件事是,我们不一定能看到数据在图上如何排列,因为没有网格来显示正弦波的波峰和波谷。因此,我们可以使用plt.grid将网格添加到我们的图中,如下所示:

# Produces the figure
plt.figure()# Adds a grid
plt.grid(True)# Plots the sine function
plt.plot(x,y)

作者图片

由此我们可以看到,y 值在 1 处达到峰值,在-1 处降至最低点,我们可以更准确地读取与 x 和 y 值相关的数据。

然后,我们可以开始定制情节的外观。例如,如果我们想将颜色从蓝色变为红色,我们可以指定颜色为r,如果我们想将线条样式从实线变为圆点,我们可以如下指定r.:

# Produces the figure
plt.figure()# Adds a grid
plt.grid(True)# Plots the sine function with red dots
plt.plot(x,y,'r.')

作者图片

其他方法也可以使用图的colorlinestyle参数来改变外观,包括各种颜色的线条和不同外观的线条样式。

当然,我们已经能够使我们的线条看起来更好、更清晰,但其他任何看这个情节的人可能不明白我们试图用情节本身来展示什么。因此,为此我们需要添加一个标题和标签来表明我们想要展示的内容。我们可以这样做:

# Produces the figure
plt.figure()# Adds a grid
plt.grid(True)# Adds a title
plt.title("Plot of a sine function",
         fontsize = 20,
         pad = 15)# Adds label for the x-axis
plt.xlabel("x",
          fontsize = 15,
          labelpad = 20)# Adds label for the y-axis
plt.ylabel("sin(x)",
          fontsize = 15,
          labelpad = 15)# Plots the sine function with red + signs
plt.plot(x,y,'r+')

作者图片

我们使用了plt.xlabelplt.ylabelplt.title函数将它们添加到图中。我们还指定了fontsize来指定标签上使用的字体大小,并指定了labelpadpad来将标签从轴上移开,以便于阅读。

由此,我们可以开始在我们的地块中添加更多的功能,并创建我们自己的风格,可以在我们创建的所有地块中使用。然而,Matplotlib 有丰富的内置样式表,我们可以使用plt.style.use(namedstyle)来访问。其中我最喜欢的一个是fivethirtyeight样式表,因为它能够产生漂亮清晰的视觉效果,以及干净容易识别的调色板。我们可以这样实现:

# Changing style to fivethityeight
plt.style.use('fivethirtyeight')# Produces the figure
plt.figure()# Adds a grid
plt.grid(True)# Adds a title
plt.title("Plot of a sine function",
         fontsize = 20,
         pad = 15)# Adds label for the x-axis
plt.xlabel("x",
          fontsize = 15,
          labelpad = 20)# Adds label for the y-axis
plt.ylabel("sin(x)",
          fontsize = 15,
          labelpad = 15)# Plots the sine function with red + signs
plt.plot(x,y, "+")

作者图片

现在看起来干净多了!更多这些,以及它们的样子的例子,可以在这里的链接找到。

同一轴上的多个图

虽然我们现在有了一个看起来不错的图,显示了我们想要的所有信息,但是如果我们想在同一个图中添加更多的信息呢?我们可以通过重用相同的轴并绘制新数据来简单地做到这一点。

在我们的例子中,由于我们已经创建了一个正弦波,我们也可以使用相同的 x 序列创建一个余弦波,以比较它们如何在相同的值上变化。我们可以这样做:

# Generates an array of cos(x) values
y1 = np.cos(x)# Produces the figure
plt.figure()# Adds a grid
plt.grid(True)# Adds a title
plt.title("Plot of a sine and cosine function")# Adds label for the x-axis
plt.xlabel("x")# Adds label for the y-axis
plt.ylabel("y")# Plots the sine function with red + signs
plt.plot(x,y,'r+')# Plots the cos function with green crosses
plt.plot(x,y1,'gx')

作者图片

太好了!我们可以看到,我们已经能够使用与之前相同的函数来添加网格和标签,但现在我们已经能够添加余弦函数以及绿色十字。现在唯一的问题是,除非我们看到正弦函数开启时的原始图(或者我们知道正弦函数应该是什么样子),否则我们不一定知道如何区分它们。这就是传说派上用场的地方!

为了给我们的图添加图例,我们需要为正弦和余弦函数的图指定一个标签,以便能够区分它们。这是通过向plt.plot函数添加一个额外的参数label=来实现的。这个标签需要被设置为我们想要标记图的字符串。然后我们添加一行额外的plt.legend来显示图例。这里的可选参数loc="best"经常被使用,它只是试图确保图例被放置在图中最合适的位置。我们可以这样尝试:

# Produces the figure
plt.figure()# Adds a grid
plt.grid(True)# Adds a title
plt.title("Plot of a sine and cosine function")# Adds label for the x-axis
plt.xlabel("x")# Adds label for the y-axis
plt.ylabel("y")# Plots the sine function with red + signs and defines a legend label
plt.plot(x,y,'r+',label="sin(x)")# Plots the cos function with green crosses and defines a legend label
plt.plot(x,y1,'gx',label="cos(x)")# Adds a legend in the best position
plt.legend(loc='best')

作者图片

现在我们可以清楚地分辨出哪个是正弦函数,哪个是余弦函数。唯一剩下的问题是,我们现在在绘图的两端都有一些空白空间,我们的行基本上在这里用完了。因此,我们可以尝试限制我们的轴,以便我们只显示使用plt.xlimplt.ylim函数实际绘制值的位置,如下所示:

# Produces the figure
plt.figure()# Adds a grid
plt.grid(True)# Adds a title
plt.title("Plot of a sine and cosine function")# Adds label for the x-axis
plt.xlabel("x")# Adds label for the y-axis
plt.ylabel("y")# Defines a region along the x-axis to be displayed
plt.xlim(0,2*np.pi)# Plots the sine function with red + signs and defines a legend label
plt.plot(x,y,'r+',label="sin(x)")# Plots the cos function with green crosses and defines a legend label
plt.plot(x,y1,'gx',label="cos(x)")# Adds a legend in the best position
plt.legend(loc='best')

作者图片

使用多轴

到目前为止,我们已经能够创建一个显示单个数据的图,然后我们能够创建一个显示多个数据的图。如果我们有两个独立的数据,我们想在多个图中显示,但我们不想创建两个独立的图呢?嗯,我们可以通过创建一个支线剧情数组来做到这一点!

有两种方法可以做到这一点。第一个是创建一个基础图形,就像我们已经做的那样,然后向原始图形添加支线剧情,我们可以向其中添加数据。为此,我们可以使用fig.add_subplot(1,2,1),其中前两个数字表示创建的数组的大小(这里是 1 行 2 列),而第三个数字表示这将是哪个子情节。我们可以将它赋回一个变量,将其创建为一个轴。我们之前所做的和现在所做的唯一区别是,我们现在有了一个轴,而不是使用fig.titlefig.xlabel,我们现在必须使用ax.set_titleax.set_xlabel。例如,我们可以像以前一样创建两个子轴来添加我们的图:

# Defines a variable for your array of subplots
fig = plt.figure(figsize=(10,5))# Adds a subplot to the array
ax1 = fig.add_subplot(1,2,1)# Plots the sine function on the first subplot
ax1.plot(x,y1,'r')
ax1.set_title("Sine function")
ax1.set_xlabel("x")
ax1.set_ylabel("y")
ax1.grid(True)# Plots the cosine function on the second subplot
ax2 = fig.add_subplot(1,2,2)
ax2.plot(x,y2,'g')
ax2.set_title("Cosine function")
ax2.set_xlabel("x")
ax2.set_ylabel("y")
ax2.grid(True)#to ensure no overlapping
plt.tight_layout()

作者图片

我们可以看到,现在我们已经创建了两个独立的轴,然后我们可以绘制我们的数据!

另一种方法是使用fig, ax = plt.subplots(1,2, figsize = (10,5))直接指定我们正在创建子情节,其中fig是我们的基轴,ax是一个轴数组,我们可以像访问列表或数组一样访问它。因此,我们可以绘制出与前面相同的信息,如下所示:

fig, ax = plt.subplots(1,2, figsize = (10,5))# Plots the sine function on the first subplot
ax[0].plot(x,y1,'r')
ax[0].set_title("Sine function")
ax[0].set_xlabel("x")
ax[0].set_ylabel("y")
ax[0].grid(True)# Plots the cosine function on the second subplot
ax[1].plot(x,y2,'g')
ax[1].set_title("Cosine function")
ax[1].set_xlabel("x")
ax[1].set_ylabel("y")
ax[1].grid(True)#to ensure no overlapping
plt.tight_layout()

作者图片

我们现在有完全相同的图,但是使用了稍微不同的符号!然后,我们可以使用这些来创建多个子情节数组,以在同一个整体情节中显示多种类型的数据!

为此,后一种创建支线剧情的方法更常用,因为你直接指定你正在创建几个子轴,而不是稍后指定。当您创建一个单轴(指定1,1)时,也经常使用它,因为它确保当您绘制多条信息时,所有内容都绘制在同一个轴上!

当然,Matplotlib 可以做的不仅仅是像这样绘制基本信息,我们还会在实际的研讨会中介绍如何创建矩阵图、choropleth 图、雷达图等等。Matplotlib 是一个非常广泛的库,它允许你用它做很多事情,包括箱线图、散点图、条形图和直方图等,但也有其他可视化库,如 seaborn 和 plotly。我建议你探索和练习绘图,包括尝试我们的问题工作表来挑战你!

完整的研讨会笔记,以及更多的例子和挑战,可以在 这里找到。如果您想了解我们协会的更多信息,请随时关注我们的社交网站:

https://www.facebook.com/ucldata 脸书

insta gram:https://www.instagram.com/ucl.datasci/

领英:https://www.linkedin.com/company/ucldata/

如果你想了解 UCL 数据科学协会和其他了不起的作者的故事,请随时使用我下面的推荐代码注册 medium。

https://philip-wilkinson.medium.com/membership [## scikit-learn 决策树分类器简介

towardsdatascience.com](/introduction-to-decision-tree-classifiers-from-scikit-learn-32cd5d23f4d)

多项式回归导论

原文:https://towardsdatascience.com/an-introduction-to-polynomial-regression-9aa6a8c0ce95?source=collection_archive---------15-----------------------

实践教程

R 语言中的数值例子及实现

图片来自像素

在介绍多项式回归之前,我们需要有一个概念,线性回归是做什么的。线性回归的主要思想是利用基函数的线性组合建立模型。为了引入这个概念,有一个问题需要回答。

「线性组合」是什么意思?它是几个项的组合,通过标量进行加法和乘法,形式如下

线性组合的定义。作者图片

其中 a₁、a₂,…是标量,x₁、x₂,…是项,或者用线性代数的语言来说,是向量。无论这些项是什么,模型都与参数成线性。

一个多项式回归模型可以被认为是几个单项式的线性组合并采取以下形式

多项式回归模型。作者图片

线性回归模型的变异

在线性回归领域,可能会遇到一些变化,有时很容易被看起来相似的术语搞混。

多元线性回归:试图用一个线性模型来描述一个因变量与两个或两个以上自变量之间的关系。在本文中,我们将关注多项式回归,它被认为是多元线性回归的一个特例。

简单线性回归 : 也是多元线性回归的特例,只涉及一个自变量。它使用一条直线来模拟数据,这条直线是一次多项式。

一般多元回归模型:它是几个多元线性回归同时写在一起的形式

一般多元回归模型。作者图片

其中 Y 是一个 n 乘 p 的矩阵,每列有 p 个因变量,每行有 n 个个体,X 是一个有观测数据的 n 乘 q 的已知矩阵,B 和 U 分别表示未知参数和噪声。

广义线性模型:应用 链接函数将因变量分布的参数链接到线性预测器(因变量的线性组合)。与其他线性模型不同,它允许因变量的误差项具有不同于正态分布的分布。

当连接函数为恒等式时,该模型退化为具有正态误差的普通线性模型。

拟合数据

要使用多项式找到合适的模型来拟合数据,需要完成两件事情:

  1. 我们需要知道它的是多少。
  2. 我们需要找到每个单项的系数

确定系数

上面描述的第一个任务实际上更困难,所以我们可以先看看第二个。为了说明线性回归的原理,让我们生成一些带有白噪声的数据

X <- seq(from=-10, to=10, by=1)
Y <- vector(mode = "double", length = length(X))
lenY <- length(Y)**for** (i **in** seq(from = 1, to = lenY)){
  noise <- runif(1, min=-1, max=1)[1]
  rangeNoise <- 25
  Y[i] <- X[i]^2 + 2*X[i] + 2 + noise*rangeNoise
}df <- data.frame(X, Y)

当然,拟合该数据的最佳模型是二次多项式。让我们试着拟合数据,看看它是什么样子的。这很简单,这就是我们需要做的

model <- lm(Y ~ I(X^2)+ I(X), df)

事实上,使用poly(X, 2)更好,因为它使用正交多项式,可以避免 X 和 X 之间的相关性引起的问题。然而,为了比较来自lm的结果和来自手动计算的结果,我们仍然使用Y ~ I(X^2) + I(X)

拟合数据的最佳多项式看起来是这样的(显然,线性模型不一定是一条线,因为它只是一些项的线性组合,项可以是任意的,线性模型看起来可以是任意的。但是它关于参数是线性的。)

拟合的结果。作者图片

其中灰色区域描述了置信区间。

lm函数使用了什么方法,我们获得了什么结果,如何解读?让我们用summary来看看吧

线性模型概述

首先让我们看一下Estimate Std.,那里的数字是我们模型的系数,也就是说得到的多项式是 f(x) = 1.0341x + 1.7416x-0.7320。计算系数的方法是最小化成本函数,在这种情况下,成本函数被选择为均方误差函数

MSE(均方差)函数。作者图片

其中,yᵢ是观测值,yᵢ哈特是预测值。由于 yᵢ是单项式 x,x,x,…和系数(我也将互换使用“权重”)w₁,w₂,…的函数,确定成本函数何时达到最小值给了我们关于 x 的 w 的表达式,x-es 是已知的,因此我们可以求解系数。这就是最小二乘法

系数也可以通过伪逆来计算。将输入数据、权重和观察值写入矩阵

输入数据、权重和观察值。作者图片

预测值将是 XW,我们希望 XW 尽可能接近 Y。权重可以通过以下方式获得

因此,损失函数为

损失函数。作者图片

这是我们计算重量的方法

使用伪逆计算权重。作者图片

现在我们要证明这是作为最小二乘法的东西,也就是说我们可以从(2.2)推导出(2.3)。

从(2.2) (a)推导出(2.3)。作者图片

然后我们对 f 对 w 求导

从(2.2) (b)推导出(2.3)。作者图片

在转置两边乘以(X^T X)的逆后,我们立即得到(2.3)。

为了验证这一点

存储在Wm中的结果对应于使用lm找到的系数。(此处截距为常数)。

[,1]
X^2  1.0340966
X    1.7415511
1   -0.7320286

拟合误差及评价

线性模型概述。作者图片

Std. Error标准 误差的估计参数。由于我们拥有的数据是来自总体的样本,因此整个总体的最优回归模型可能在一个范围内——我们获得的最优解是而不是(对于样本来说,它是最好的,但是对于整个总体来说,基本关系可能有点不同)。在统计学中,重要的是要知道,我们谈论的是什么数据,整个人口,还是只有样本数据。这些误差用于计算距离。那我们如何计算这些误差呢?

在表格中填写我们的模型

我们例子中的线性模型。作者图片

这意味着

。作者图片

其中εᵢ是误差项,它是观测值和预测值之间的差值。

根据这个,我们可以通过以下方式计算系数

估计系数误差的计算公式。作者图片

其中,变量上的帽子表示它们是估计值,σ(X)是 X 的标准差,X_hat 是 X 的平均值。[自由度](https://www.investopedia.com/terms/d/degrees-of-freedom.asp)是 n-3 (在本例中,n-3 = 21–3 = 18,我们在样本中有 21 个点)。s 就是Residual standard error,这里 s = 15.11。

在这个源中,符号似乎不是很常见和清晰,所以也参考了维基百科。在这两个来源中,仅给出了最简单模型(a 线 Y = aX + b)的公式,但是可以推导出我们的二次示例的公式。但是当然,鼓励读者尝试实现它们,并用一些数据验证它们。

线性模型概述。作者图片

Coefficients中的最后两列告诉我们模型中的一个组件是否重要。方法是计算一个 t 统计量,即t value。然后我们计算 p 值,即Pr(>|t|),这是反对零假设的证据(H₀: 模型中的成分在统计上不显著,我们在模型中不需要它)。如果 p 值足够小,我们可以拒绝零假设(值得注意的是,我们不能永远接受零假设,因为我们只有证据反对它)。

以 x 项为例,x 的系数为 w₁,t 值为 w₁

t 值。作者图片

t 遵循学生的 t 分布,自由度为 n-3。在这个例子的情况下,t 值简单地通过系数/标准误差来计算。

函数 lm 中 t 值是如何计算的?作者图片

而结果是3.197。为了找到 p 值,我们需要参考学生 t 分布临界值表。我们可以看到我们的 t 值在 2.878 到 3.610 之间。所以累积概率在 0.002 和 0.01 之间——结果是0.00499。总体中基本关系式(2.4)中参数的区间可由下式确定

总体参数的区间。作者图片

其中 t*ₙ₋₃是 tₙ₋₃分布的第(1-α/2)分位数,这个值也可以在这个表中找到。默认情况下,α = 0.05,置信区间为 1-α=0.95。如果 p 值小于α,我们可以拒绝零假设。因此,X 项在我们的例子中很重要。

这个预测将在最后一节讨论。在 R 中非常方便,我们只需要应用函数predict

比较和选择模型

这里我们回到第一个任务,我们要用什么样的线性模型?线性组合的项应该是什么?

当使用多元线性回归时,我们经常需要减少因变量的数量,因为如果一个更复杂的模型并不比一个更简单的模型好多少,我们应该使用更简单的模型。对于一个非常复杂的模型,我们可能会获得高性能,但它也更加难以解释。有时过度拟合也会发生。有几种简化的方法,例如,主成分分析就是一个有用的工具。

由于这里我们只处理多项式,PCA 不是很合适,逐步回归将是一个更好的方法,我们可以应用它来降低模型的阶数。但是减少多项式模型的次数的任务类似于减少任何多变量线性回归模型中的独立变量的数量。对于多项式回归模型,次数越高,多项式就能更好地拟合数据,但同时会包含更多的噪声,这将导致非常差的预测(过度拟合)。

我们可以对我们的数据使用一个 5 次多项式,当然这不是必须的,它也不利于预测。如果我们检查这个模型的摘要,我们会发现组件具有较大的 p 值—它们在统计上不显著。以下代码可用于进行逐步回归(需要库MASS)

fullModel <- lm(Y ~ I(X^5) + I(X^4) + I(X^3) + I(X^2) + I(X) + 1, df)
stepModel <- stepAIC(fullModel, direction = "backward", trace = FALSE)
summary(stepModel)

正如我们已经知道的,结果stepModel是一个二次多项式。

什么时候应该使用多项式回归,什么时候不应该?

1.速度和距离

使用的例子将是 R 中的内置数据集car,它记录了汽车的速度和停车时所经过的距离。多项式回归在这里是合适的。事实上,根据我们的物理知识,这是正确的答案。

图 3.1 速度和距离。使用此处的代码制作的图像。

我们将数据分为训练集和测试集,并用测试数据绘制线性模型。

图 3.2 拟合(75%随机选择的训练数据)和预测。作者图片

如果我们运行一个 R 测试,它会告诉我们这个模型解释了测试集中 80.089%的数据可变性。

2.油价

这里是我们不应该使用线性回归的时候。假设我们想根据历史数据预测油价(数据来源:【https://finance.yahoo.com/quote/OIL/history?p=OIL】)。

图 3.3 一年的每日油价。作者图片

我们用了一个三次多项式,这个图看起来不错。(index为天数指数,CloseP为每天收盘价)。但在测试数据上,这似乎并不可信

图 3.4 拟合(从数据集开始的 75%的数据),和预测。作者图片

事实上,在这个例子中,它永远不会工作,因为如果我们使用一个偶数阶的多项式,当指数变大时,曲线将上升,奇数阶的曲线将下降。但是很明显,这不是商品价格的变化方式。

为什么比第一个例子差那么多?图 3.1 看起来没有图 3.3 那么混乱和嘈杂。然而,在图 3.1 中有一个时间序列,距离与速度之间的关系和油价与时间之间的关系是完全不同的故事。更多的因素使价格变化变得复杂,例如,时滞、周期性等。

摘要

本文试图介绍多项式回归,并把它与一元线性回归和多元线性回归联系起来。它还简要描述了什么是线性回归和有什么变化。

在关注多项式回归的部分,首先,我们知道如何拟合数据和如何确定系数(使用 R 中的内置函数实现,但也可以手动实现)。然后介绍了模型和评估中的误差,主要是 t 值和 p 值的计算。此外,对统计推断也作了简要介绍。

最后,我们看了两个例子,多项式回归模型分别适用和不适用。

资源

[1] 线性组合 (2015), nLab

[2]米歇尔·莱西,多元线性回归

[3]肯特,J. T .,毕比,j .,&马迪亚,K. V. 多变量分析 (1979)。阿姆斯特丹:学术出版社

[4]内尔德,J. A .,,威德伯恩,R. W . 广义线性模型 (1972)。英国皇家统计学会杂志:A 辑(总论)135 (3),370–384。

[5] Jonathan Bartlett,线性回归的假设 (2013)

[6] Alboukadel Kassambara,R中的逐步回归要点(2018)

概率抽样方法介绍

原文:https://towardsdatascience.com/an-introduction-to-probability-sampling-methods-7a936e486b5?source=collection_archive---------6-----------------------

为什么采样方法是您的数据科学之旅的关键

作者插图

还在学习统计学的时候就接触到了抽样技术。我记得这是我更喜欢的话题之一,因为教授深入地解释了它们,让我明白它们是许多调查研究的基础,但在那段时间里,我充满了其他课程和其他想法,以至于我一通过考试就忘记了这些有用的概念。

但是在我读数据科学硕士期间,在我的实际研究工作中,我间接看到了很多机器学习模型中涉及到的采样方法,比如决策森林、随机森林、隔离森林等等。它们还用于解决数据集中的不平衡类分布等问题,并通过使用重采样过程(称为 K-fold 交叉验证)来改进模型性能的评估。

出于这个原因,我决定进一步研究这个惊人的主题,它在处理大量数据时具有关键作用。我将从定义什么是采样开始。一旦基本概念清楚了,下一步就是解释不同的抽样技术,重点是概率抽样方法。

介绍

在统计研究中,并不总是能够获得所有案例的数据。为此,最实用的方法是纳入总体的一部分,称为样本

在进行采样时,我们需要定义一些相关术语。首先,目标人群包括我们理论上感兴趣的所有项目。我们需要区分目标人群和研究人群,有时也称为样本人群,它是我们可以获得的目标人群的子集。

抽样本质上是从研究人群中选择样本的过程。一个重要的要求是,样本需要尽可能地代表总体,以便概括整个总体的特征。

这可以通过采用不同的采样方法来实现,这些方法可以分为两大类:

  • 概率抽样方法:被选择的群体中每个单元已知的概率。
  • 非概率抽样方法:总体中每个单元被选中的概率未知,与收集数据的研究者的主观性更相关。

在这篇文章中,我将重点介绍概率抽样方法。这种类型的方法可以进一步分为不同的类别,如下所示。

概率抽样方法:

  1. 简单随机抽样
  2. 系统采样
  3. 分层抽样
  4. 整群抽样
  5. 多级采样

1.简单随机抽样

简单随机抽样。作者插图

简单随机抽样(SRS)是对人口进行抽样的最简单的方法,人口只是项目的集合[1]。如果检查简单随机抽样的定义,你可能会在某处发现这一点:

简单的随机抽样确保了群体中的每个元素都有相等的选择概率

这并不完全错误,但这取决于提取过程的类型:

  • 具有替换的 SRS:群体中的所有单元将具有相同的被选择概率 1/N 。例如,让我们考虑一个装有 4 个红球和 2 个黑球的骨灰盒。在第一次抽取中,红球是从瓮中随机抽取的。所有的球总会有 1/6 的概率被抽样。
  • 无替换的 SRS:在第一次抽取时,每一个群体单元将有相等的选择概率 1/N 。在第二次提取时,剩余的 N-1 个单元将具有等于 1/(N-1) 的选择概率。在这个例子中,我们观察到选择概率在第二次提取中发生了变化。这违反了顶部显示的定义!

优势:

  • 它很简单,并且不使用关于人口的辅助信息
  • 选择是随机的,然后,任何单位都是受青睐的
  • 样本具有代表性

缺点:

  • 元素的选择是完全随机的
  • 需要一份完整的人口单位清单
  • 这既费时又费钱

2.系统抽样

系统抽样。作者插图

系统取样可以归纳为两个步骤:

  1. 计算采样间隔 k =N/n .在图示中,我们有 9 个微笑,我们想获得 3 个单位的样本,那么 N=9,n=3,k=9/3=3。
  2. 在 1 和 k 之间选择一个随机整数 r:1≤r≤k,例子中我随机选择 r=2,其中 1≤r≤3。
  3. 一旦选择了第一个单元,我们就取接下来的第 k 个项目来构建样本:r,r+k,r+2k,…,r+(n-1)k。

优点:

  • 随机选择仅应用于第一个项目,而选择的其余项目取决于第一个项目的位置和选择项目的固定间隔。

缺点:

  • 如果群体元素的列表呈现确定的顺序,则存在获得不具有代表性的样本的风险

3.分层抽样

分层抽样。作者插图

根据一些分类特征,如年龄、性别和教育程度,人口被分为亚人口,称为阶层。如果组内部同质,且组间异质,分层抽样是有效的。从每一层,我们提取一个简单的随机样本。这些样本的集合产生分层样本。

要计算地层样本大小,有两种常用的分配方法:

  • 比例分配是实践中最简单、应用最广泛的方案。它在每个地层 nₕ/Nₕ 内提供相同的采样分数,对应于全局采样分数n/n:fₕ=nₕ/nₕ=f=n/n。在插图中,我们根据水果的类型分为两组。阶层人口分别是 N₁=6 和 N₂=9.通过比例分配,我们选择总样本量为 n=5 的样本。根据理论,我们希望相同的采样分数等于 5/15=1/3。正如你所观察到的,这个标准得到了尊重:n₁/N₁ = 2/6=1/3 作为苹果组的样本分数,n₂/N₂ = 3/9=1/3 作为橙子组的样本分数。

  • 最优或奈曼分配基于每个地层中取样分数应该不同的想法,并假设地层取样大小 nₕ 与地层 S 的标准差成正比。当阶层差异不同时,这种分配比比例分配更有效、更精确。

优点:

  • 这比简单的随机抽样更有效
  • 获得非代表性样本的风险较小

缺点:

  • 它需要获得关于人口的辅助信息。
  • 对阶层有严格的条件,需要面面俱到,互相排斥。

4.巢式抽样法

整群抽样。作者插图。

整群抽样假设总体可以由基本单位的子集构成,这些子集称为群。显然,它可能看起来类似于分层抽样,但原理完全不同。

在分层抽样中,各组内部是同质的,相互之间是异质的与分层抽样不同,聚类之间 相似,每个聚类包含具有不同特征的元素

例如,如果我们有兴趣研究纽约的居民,我们可以考虑由属于同一城市的家庭的人构成的人口。一个家族是一个典型的集群,其中包含不同的成员。

整群抽样允许从群体中随机抽取一些群体,而不是从群体中抽取一些元素。如果我们考虑将人口分成家庭,我们可以随机抽取一些家庭,如图所示。

优点:

  • 当集群构成自然形成的子群时,这是有效的,因为我们不拥有群体的列表
  • 如果这些单位的特点是分散在整个地区,而且有必要进行直接接触,那么只研究某些集群比简单的随机抽样花费要少。

缺点:

  • 集群的条件并不总是被尊重。这些簇可以包含相似的元素。

5.多阶段取样

两阶段抽样。作者插图。

实际上,自然形成的人口子群集群,如果集群规模较小,并且集群是基于地域特征确定的,则可能包含类似的单元。

为每个集群分析一些单元可能更方便,而不是考虑所有的元素。这种设计叫做两阶段整群抽样。如果我们再次考虑居住在纽约的家庭,我们可以从已经选择的群中随机抽取两个人。

因此,多阶段抽样将大量人口分成“阶段”,以使抽样过程更有效。

优点:

  • 当集群之间同质而内部异质时,多阶段采样可能比集群采样更有效。
  • 抽样规模减小
  • 组织起来更简单,成本效益更高

缺点:

  • 在不考虑聚类条件的情况下,多阶段采样结果不如简单随机采样有效。

最终想法:

我希望这篇教程对你学习更多概率抽样方法有用。不看例子来研究这个话题是很有挑战性的。在机器学习领域,简单随机抽样和分层抽样是最广泛用于评估模型性能的方法。这里肯定还有我没有提到的其他采样方法。我的目标是关注最相关的技术。我将在下一篇文章中介绍非概率抽样方法。感谢阅读!祝你有愉快的一天。

[1]“调查抽样参考指南,样本设计和估计技术介绍”,欧盟统计局

你喜欢我的文章吗? 成为会员 每天无限获取数据科学新帖!这是一种间接的支持我的方式,不会给你带来任何额外的费用。如果您已经是会员, 订阅 每当我发布新的数据科学和 python 指南时,您都可以收到电子邮件!

回归不连续设计导论

原文:https://towardsdatascience.com/an-introduction-to-regression-discontinuity-design-f55075079def?source=collection_archive---------5-----------------------

纳丁·沙巴纳在 Unsplash 上拍摄的照片

用历史数据进行可靠的因果推断

与相关性不同,因果关系是两个变量之间更强的关系。尽管很难断言两者之间存在因果关系,但一旦被证实,它会提供有意义的见解和信息指导。在我之前的文章中,我已经讨论了关于因果推理的什么、为什么和如何:

正如文章中提到的,证明因果关系的最可靠的方法是通过随机试验,这也被称为实验。然而,进行随机试验并不总是可行的。在这种情况下,我们可以使用一些在经济研究中广泛应用的“技巧”,利用历史数据进行因果推断。当某些条件适用时,回归不连续设计(RDD)就是这些技巧之一。在本文中,我将向您展示什么是 RDD,以及使用 RDD 进行因果推理的一些应用。

为什么不实验?

随机分配对照组和治疗组可确保除治疗效果外两组间无显著差异,从而确定因果关系,无需担心混淆变量。进行实验是分析因果关系最可靠的方法,但它不是最常见的方法,主要原因有两个:

  • 进行实验的成本很高:进行随机试验不仅经济上很高,而且很耗时。如果没有项目投资的坚实预算,很难进行实地试验;
  • 并不总是适用于跑步实验:跑步实验不可行的原因有很多。例如,在一些医学治疗上进行实验是不道德的。此外,有时不可能在不担心两组之间的互动的情况下将受试者分为治疗组和对照组,尤其是在社交媒体上进行实验时。

如果不可能通过实验产生新的数据来进行因果推断,其他的解决方案是对历史数据应用特殊的方法。根据场景和假设,我们可以从回归不连续设计(RDD)、差异差异(DID)、工具变量(IV)、倾向得分匹配(PSM)等中进行选择。在本文中,我将详细阐述回归不连续设计的假设和应用。

什么是 RDD?

使用历史数据进行因果推断的一个挑战是,我们永远无法知道真实的反事实结果,这意味着我们永远不知道如果治疗组的受试者被分配到对照组会发生什么,反之亦然。因此,我们通过简单地比较治疗组和对照组观察到的结果差异并不是真正的治疗效果,而是可能被其他变量所偏倚。所有的因果推理方法都包括寻找可靠的方法来估计真实的反事实效应。对于随机试验,利用随机性,我们确保两组受试者除了接受或不接受治疗之外,在各方面都相同。在倾向分数匹配中,我们根据治疗组和对照组受试者在某些特征上的匹配分数来“匹配”他们之间的比较。

回归不连续设计在截止点测量治疗效果,因此我们只能在有明确的截止点将治疗组和对照组分开的情况下应用 RDD。这可以是一个自然的截止点,如地理边界,也可以是一个干预点,如合格奖学金的分数要求。仅通过比较接近临界值两侧的受试者,我们就可以估计平均治疗效果并确定因果关系。

RDD 背后的直觉是,虽然我们知道将受试者分配到不同的组会有偏差,但我们相信接近截止值的受试者是非常相似的,随机性是他们被分配到治疗组或对照组的唯一原因。它非常类似于随机试验,但只使用历史数据。

按作者

正如上图所示,在绘制我们感兴趣的结果变量 Y 和截止值前后的赋值变量 X(截止值变量)之间的回归时,存在一个不连续点。由于治疗组和对照组的受试者之间的治疗效果和其他预先存在的差异,这种不连续性是存在的。然而,我们认为,对于接近临界值 c 的受试者,如 A 和 B,他们的结果差异主要来自治疗,因为他们在 X 变量方面非常接近。

在 RDD 的应用

RDD 第一次被应用于评估奖学金项目的效果(蓟和坎贝尔 1960) 。如果我们想知道获得奖学金(待遇)对学生未来成绩(结果变量)的影响,简单地比较有奖学金和没有奖学金的学生的成绩会在估计中引入偏差。因为过去的成绩而获得奖学金的学生即使没有奖学金也可能比其他学生得分高!简单的比较会高估治疗效果。然而,如果我们只关注接近给予奖学金分数线的学生,即几乎获得奖学金的学生(略低于分数线)和勉强获得奖学金的学生(略高于分数线),我们可以估计他们未来的成绩差异并声称因果关系。由于这些学生过去的成绩如此接近,我们相信除了是否获得奖学金之外,他们在各方面都非常相似,这正是我们进行因果推断所需要的。

另一个有趣的应用是利用 RDD 利用历史交易数据估计优步客户的价格弹性和需求曲线( Cohen et al(2016) )。价格弹性描述了顾客购买的数量和他们面对的价格之间的因果关系。价格弹性高的客户对价格变化很敏感。简单地从历史交易数据中回归价格和购买数量会导致其他因素的偏差,这些因素也会影响客户的购买决策,如季节性、客户收入等。在这篇论文中,研究人员利用优步的“激增”定价算法,并进行回归不连续设计,以估计需求曲线上几个点的需求弹性。直觉是,在价格“暴涨”期间,该算法将根据当地市场供求状况、客户特征等内生生成一个暴涨乘数。尽管市场条件下的激增乘数是内生的,但有一些随机性水平可以用来估计价格弹性。激增乘数“1.244”和“1.246”之间的市场条件彼此非常相似,但是,由于激增乘数只有两位数,前者导致“1.24”,而后者导致“1.25”。由于接近截止点的客户的市场条件非常相似,通过估计接近截止点的客户的反应(交易)的差异,他们能够估计每个点的价格弹性和需求曲线。

虽然 RDD 是估计历史数据因果关系的好方法,但这并不意味着我们不能为了因果推断而利用它来创造新数据。正如优步的例子所展示的,在算法中加入一定程度的随机性可以帮助你以后分析因果关系。另外。有时这比进行野外实验要便宜得多。

警告

尽管 RDD 提供了一个估算因果关系的方便方法,我们仍然需要在进入分析之前仔细检查这些假设是否适用:

  • 受试者不应该影响他们是否可以接受治疗:在奖学金的例子中,学生不应该能够说服教授给他们奖学金,即使他们的成绩没有通过截止日期;
  • 临界值不应该被具有相同临界值的治疗方法所污染:例如,赌博的法定年龄也是 21 岁,这一事实可能会污染一项使用 RDD 和 21 岁临界值分析酒精影响的研究。

这就是本文的全部内容。感谢您的阅读。这是我所有博客帖子的列表。如果你感兴趣的话,可以去看看!

https://zzhu17.medium.com/my-blog-posts-gallery-ac6e01fe5cc3 https://zzhu17.medium.com/membership

参考

[1] 回归不连续设计百科

[2]李,大卫和托马斯·雷米尔。2010."经济学中的回归不连续设计."经济文献杂志,48(2):281–355。

[3]thislethwaite,d .和 D. Campbell。"回归-不连续分析:事后实验的替代方法."教育心理学杂志51(1960):309–317。

[4]科恩,p .,哈恩,r .,霍尔,j .,莱维特,s .,&梅特卡夫,R. (2016)。利用大数据估算消费者剩余:优步案例(第 w22627 号)。美国国家经济研究局。

强化学习导论

原文:https://towardsdatascience.com/an-introduction-to-reinforcement-learning-4ecc096ee80f?source=collection_archive---------43-----------------------

展示支持 RL 的关键概念

最近在强化学习的帮助下取得的成功被媒体广泛报道。人们可以想到 DeepMind 的 AlphaGo 算法:使用强化学习(和大量昂贵的硬件来训练它),AlphaGo 学会了玩围棋这一古老的游戏,甚至开发了自己的游戏风格。

OpenAI 展示了另一个例子,其研究人员教会了一只机器手解魔方。有趣的是,它是在虚拟环境中训练的;因为即使拿着一个立方体转动而不掉它也是相当困难的,这是令人惊奇的第一步。

我写这篇文章的目的是首先解释使这种成功成为可能的概念。我从介绍开始,然后逐步完善 RL 的定义。

由大卫·莱维克在 Unsplash 上拍摄的照片

介绍

强化学习是机器学习的一个领域。您可能已经使用过监督学习(数据被标记)和非监督学习(未标记的数据,例如,用于生成技术)。这两大领域由强化学习领域补充。两个关键区别在于,数据通常不是独立且相同地分布的(即,它可能非常杂乱,没有明显的结构),并且代理的行为决定了它遇到的未来数据。

用一句非正式的话来说,强化学习学习通过互动来达到一个目标。

让我们来看看机器学习这一分支背后的基本成分:

首先,我们有提到的代理。代理既是学习者又是决策者。现实生活中的类比就是你和我,都在做决策,都在不停地学习。第二,代理可以与之交互的一切都是环境(对我们来说是我们的正常环境:其他人、建筑物、汽车、狗、猫等等)。第三,这种环境可以通过互动来改变,这是代理人产生影响的唯一方式。在每一种可能的情况下,代理人可以决定一个行动,并依次获得奖励。这种奖励会影响学习过程。

MDP

这个描述相当模糊。为了给强化学习下一个更精确的定义,我们需要一种数学方法。这就是马尔可夫决策过程的用武之地,它是一种对状态之间的转换进行建模的数学方法。我们有一个五元组(s,a,r,p,p₀) [1,2]:

S 是状态空间,包含一个代理可能遇到的所有可能的状态。因此,每一个状态 s ∈ S。

a 是动作空间,包含代理可能的动作。同样,我们有每一个动作。

R 是奖励函数,它基于当前状态 sₜ、选择的动作 aₜ和结果状态 sₜ₊₁.,传递代理动作的奖励我们包括结果状态也是为了考虑状态之间的转换。如果没有它,在不同的时间步骤在相同的状态下行动会产生相同的回报——不考虑代理人可能已经学到了什么。换句话说,动作 a 在 tt+k 可以是相同的,但是可能导致不同的新状态。我们通过添加 sₜ₊₁.来考虑这一点奖励是一个实数,比如+1,-2.5 等等。

P 是将状态和动作映射到概率的函数。它决定了从 sₜ出发并选择 aₜ.行动时到达 sₜ₊₁州的概率我们的环境可能会受到我们无法控制的事件的影响。为此,我们有 P,它考虑了外部影响。如果我们没有这样的影响,我们简单地使用一个确定性的转变,也就是说,新的状态是保证达到的。

最后,我们有 p₀,这是初始状态的分布,也就是说,它包含了所有我们可以开始的状态。

Roméo A. 在 Unsplash 上拍摄的照片

你还记得手机游戏 DoodleJump 吗?还是任天堂设备上的马里奥游戏?让我们构建一个与这两个类似的设置:

我们的敌人从右侧进来(这是来自马里奥),我们向上跳一级就可以躲开他们(这是来自嘟嘟跳)。我们的状态空间 S 由两个状态组成,

在这两种状态下,我们有两种可能的动作,跳转等待,它们构成了动作空间 A

每次我们从低处跳到高处或者从高处跳到高处,我们都会得到+1 的奖励。当我们被敌人击中时,我们会下降一级,奖励是-1(注意,这里的奖励不是与一个动作相关联,例如跳跃或等待,而是与我们被外部影响击中的事实相关联)。等待的回报是 0。

现在到 P ,它决定了我们达到下一个水平的可能性有多大。这是 80 %,有 20 %我们保持在目前的水平。等待可能导致停留在当前水平或被敌人击中的概率相等;因此,两者的概率都是 50 %。最后,我们的 p ₀只包含状态

政策

到目前为止,我们已经讨论了动作和环境,但是没有讨论如何在给定的状态下确定适当的动作。因为我们有多个状态和多个时间步,我们需要一些进一步的算法来帮助我们。这是策略的任务π,从一个状态到一个动作的映射:π(aₜ|sₜ)是在状态 sₜ选择 aₜ的概率1,2。由此出发,我们可以从所有可能的动作中抽取动作,用 aₜπ表示。|sₜ).

该策略是可以由深度 RL 中的神经网络建模的部分[1]。

对于我们的示例,我们的策略由以下映射组成:(jump|low) = (jump|high) = 50 %。这意味着在低和高的状态中,我们以 50 %的概率选择动作跳转。(等待|低)和(等待|高)的概率各为 50 %。

奖励

到目前为止,我们已经介绍了政策,但还没有介绍奖励的形式和作用。开始时,我注意到我们希望代理实现一个目标。这个比较模糊。更正式地说,我们希望代理人最大化预期报酬。

让我们来看看这个:

从我们最初的状态,s₀和 a₀把我们带到 s₁.和 a₁一起我们去了 s₂.和 a₂一起,我们前进到 s₃.这种情况可能会持续无限长的时间。这种状态和动作的序列被称为轨迹,表示为τ。此外,我们还会在每个动作之后获得奖励,奖励 rₜ₊₁(因为奖励考虑了结果状态,所以奖励也会在下一个时间步支付, t+1 )。有了轨迹和奖励,我们可以通过对所有个人奖励求和来计算我们的最终回报,或累计奖励【1,2】

回到我们的例子,考虑这个轨迹:(低,跳,高,跳,高)。由低到高过渡的奖励是+1,由高到高的奖励也是+1。对于这个轨迹,回报是 2。

在有限的动作序列的情况下,这就是我们所需要的。但是当我们处理无休止运行的环境时,这就产生了一个问题:

每个奖励目前都具有相同的重要性,无论它发生在一个近时间点(因此可能更有形)还是无限的边缘(非常无形)。此外,这也是更重要的,我们的回报是没有界限的,它不会收敛到一个固定的值。这使得比较两个策略变得很困难:一个可能总是得到+1,-1,+1,-1,…,而另一个策略可能经常得到+10,+10,+10,只是后来犯了一个严重的错误,抵消了我们到目前为止所取得的一切。换句话说,当轨迹无穷无尽时,我们不知道从长远来看哪种政策会更好,因为一切都可能发生。

幸运的是,这可以通过使用折扣回报来解决,这是一种更通用的方法:我们用折扣乘以每个奖励,这量化了它的重要性(将折扣设置为 1 导致之前的未折扣回报)[1,2]:

因此,贴现回报迫使代理人“早赢比晚赢好”[3]。

为了最大化预期回报,我们需要我们的政策(检查),我们的轨迹(检查),和回报(检查)。配备了它们,我们开始:

让我解释一下这个等式:给定一个策略π,我们想知道我们得到一个特定的状态和动作序列的可能性有多大(这是轨迹,τ)。为此,我们取我们的初始状态 s₀的概率,然后乘以所有进一步的概率(这是∏部分)。对于我们到达的每一个后来的状态 sₜ₊₁,我们检查它到达这个状态(这是 P(sₜ₊₁|sₜ,aₜ)的可能性,并且将它乘以采取引导我们到达那里的行动的可能性(这是π(aₜ|sₜ)).)

在此基础上,我们写下预期回报是我们通过政策π获得的回报,然后根据它采取行动(这为我们提供了轨迹,即状态-行动序列的列表)。如上所述,对于每个这样的轨迹,我们都有一个回报。检查所有可能的轨迹(所有可能的状态-行动序列),并总结它们各自的回报,我们就有了预期的回报[1,2]:

让我更详细地描述这个方程:我们通过写出τ∞p(⋅|π).来取每个可能的轨迹正如我上面所写的,每个轨迹都有发生的概率,每个轨迹都有回报。通过将概率乘以回报(用 R(τ)来描述),我们根据可能性对结果进行加权。这遵循了计算期望值的正常方式:

对于我们的例子,我们有这两个轨迹:(低,跳,高,跳,高)(奖励为 2),以及轨迹(低,跳,高,等待,低)(奖励为 0: +1 表示前进,-1 表示等待并被敌人击中,从而下降一级)。

现在让我们计算第一个轨迹的概率:它是 1×0.8×0.5×0.8×0.5 = 0.16;1 是开始状态低的概率,0.8 × 0.5 是前进到下一个级别的概率,乘以选择动作跳转的概率。类似地,我们继续第二个轨迹:1 × 0.8 × 0.5 × 0.5 × 0.5 = 0.1,唯一的区别是 0.5 × 0.5。这里,我们取等待的概率为 0.5(也就是在这种情况下下降一级),并将其乘以成功率,0.5。

有了每条轨迹的回报和概率,我们现在可以按照上面的等式计算预期回报:0.16 × 2 + 0.1 × 0=0.32。因此我们的预期收益是 0.32。

这样,我们可以进一步形式化我们的 RL 定义:找到最大化期望回报的策略[1,2]

这是最佳策略。

价值函数

说了这么多,我们怎么知道一个动作是好的动作,或者一个状态是好的状态呢?我们可以通过价值函数和行动价值函数找到答案。简而言之,给定一个策略π,一个状态的值就是从这个状态得出的预期回报,并且此后总是按照π行事。使用数学符号,我们把它写成

类似地,对于行动价值函数,我们也需要策略π。与之前不同,我们现在将值分配给一对状态和动作[1,2]。同样,这个价值也是我们在 s₀开始与 a₀:合作时的预期回报

有了 Q ,我们就可以简单地选择一个状态的下一个动作,作为最大化期望回报的动作

同样,我们可以通过查询 V 来检查一个状态的值。

酷的是,有了最优政策,我们可以找到最优价值和最优行动价值函数。这个最优策略对于任何 MDP 都是存在的。挑战在于找到它。

参考

[1]乔希·阿奇姆,在《极深 RL》(2020),OpenAI

[2]萨顿,理查德 S 和巴尔托,安德鲁 G,《强化学习:导论》 (2018),麻省理工学院出版社

[3]迈克尔·l·利特曼,马尔可夫博弈作为多主体强化学习的框架 (1994),机器学习论文集

强化学习导论:K 臂强盗

原文:https://towardsdatascience.com/an-introduction-to-reinforcement-learning-the-k-armed-bandit-3399593e68e8?source=collection_archive---------31-----------------------

k 臂土匪问题引入了很多强化学习的思想。多读点了解一下。

亲爱的在 Unsplash 上的照片

最近有很多关于强化学习(RL)的宣传,这是理所当然的。自从 DeepMind 发表论文“用深度强化学习玩雅达利”以来,已经出现了许多有希望的结果,其中最著名的可能是 AlphaGo。然而,在我们能够理解这些模型如何工作之前,我们需要理解强化学习的一些基本原理。我认为对这些概念最好的介绍是通过一个简单得多的问题——所谓的“k 臂土匪问题”。

问题是

首先,我们来定义一下什么是 k 臂土匪问题。“k 臂强盗”这个词让人想起《星球大战》中波巴·费特和章鱼杂交的画面,但幸运的是事情没有那么疯狂。相反,你可以把强盗想象成一个老丨虎丨机,而 k 个手臂中的每一个都是一个杠杆。拉动 k 杆中的一个会给你一个正的回报。在大多数强化学习问题中,你的目标是最大化你的总回报,给定固定数量(比如 1000)的拉力。你唯一的先验信息是每个杠杆的平均回报不随时间变化。这里的最佳策略是什么?

如果我们知道每个杠杆的平均回报,这个问题就简单了。我们总是拉着平均回报最高的杠杆。所以一个可能的方法是首先使用一些拉力来计算出哪一个杠杆有最高的平均回报,然后只拉那个杠杆。

应该怎么搞清楚哪个杠杆最好?我们需要多次尝试所有的杠杆,因为即使每个杠杆的平均回报是固定的,每次拉动杠杆都会得到不同的回报。一旦我们多次尝试每个杠杆,我们可以取所有拉力的平均值作为真实回报的近似值。换句话说,一种可能的算法是:

算法 1

拉动每根杠杆 n 次,平均每根杠杆的 n 次回报。

平均值最高的杠杆就是最好的杠杆。从现在开始只拉那个。

这就有一个问题,就是我们不知道如何设置 n,比如说我们用 n = 3。对于其中一个杠杆,我们拉 3 次,我们得到 14、15 和 16 的回报,平均下来是 15。然而,那个杠杆的真实平均回报是 5——我们只是非常幸运地拉了三次。现在我们有麻烦了,因为我们总是假设这个杠杆比它实际上要好得多。我们可以使 n 变大,这将使我们更加确信我们的平均值是准确的。然而,由于我们的时间步数有限,我们不想浪费杠杆拉动。因此,设置大的 n 也有问题。

我们可以完全避免固定一个数字 n。相反,我们保留了每个杠杆的运行平均回报。另一种可能的算法是:

算法二

在做任何拉动之前,将每个杠杆的移动平均值设置为 0。

对于每个时间步长:

  • 选择运行平均值最高的杠杆。如果有平局,在平局的杠杆之间随机选择。
  • 拉动我们刚刚选择的杠杆,观察回报,并用回报修改该杠杆的运行平均值。

从理论上讲,这种算法的优势在于,它总是越来越接近每个杠杆的真实平均回报。没有每根杠杆 n 的拉动次数,在此之后我们停止学习。可惜行不通。在第一个时间步,这个算法将拉动一个随机杠杆,得到一个正的回报。然后,因为所有其他运行平均值都设置为 0,它将永远从第一个时间步长继续拉动杠杆。它永远不会碰到其他杠杆。

解决这个问题的一个办法是使用另一个参数 epsilon,它控制我们是拉具有最高运行平均值的杠杆,还是拉随机的杠杆。我们的算法变成了:

算法三

在做任何拉动之前,将每个杠杆的移动平均值设置为 0。

将 epsilon 设置为[0,1]中的一个数字。

对于每个时间步长:

  • 在[0,1]中得到一个随机数(来自均匀分布)x。
  • 如果 x >ε,选择运行平均值最高的杠杆。如果有平局,在平局的杠杆之间随机选择。
  • 如果 x
  • 拉动我们刚刚选择的杠杆,观察回报,并用回报修改该杠杆的运行平均值。

这个算法确实有效。通过 x 的随机性,最终我们将被迫尝试所有的杠杆足够的次数,以获得所有杠杆的精确运行平均值。然而,我们必须决定ε是什么。如果我们将 epsilon 设置得更接近 1,算法将更均匀地尝试杠杆,从而得到更好的估计,但总回报会更低。如果我们将 epsilon 设置得更接近 0,算法将更多地关注几个杠杆,导致不太准确的估计,但可能会有更高的回报。

RL 视角

现在让我们把所有这些放在强化学习的术语中。首先,我们注意到我们想要得到每个杠杆的真实平均回报的精确估计。我们称每个杠杆的真实平均回报为问题的行动价值函数。为什么叫这个?嗯,在我们的问题中,我们可以采取的可能的行动是拉动每个杠杆。每拉一次杠杆,就有一个真实的平均奖励值。更正式地说,动作值函数由 Q(a) 表示。 Q 是函数, a 代表可能的动作。我们不知道 Q ,所以我们试着估计一下,记为 Q* 。我们的希望是 Q*将接近 Q。

我们也想出了一些具体的算法来解决这个土匪问题。算法 1 有两个独立的部分。第一部分试图通过使用每个杠杆 n 次拉动的样本平均值来近似动作值函数(求 Q)。第二部分用 Q来决定拉哪个杠杆。在高层次上,算法的第一部分,寻找 Q,被称为探索。算法的第二部分,使用由 Q确定的最佳动作/拉动,称为利用。我们在设置该算法的参数 n 时遇到了一些问题。同样,我们很难决定如何在勘探和开采之间划分时间间隔。这是强化学习中的一个常见主题。

我们把总是利用贪婪算法的算法叫做。贪婪算法总是试图最大化每个时间步长的回报;它不探索。我们在算法 2 中看到了这个问题。因为没有进行探索,所以在短期内贪婪算法可能工作得很好,但从长期来看,它几乎肯定是次优的。

我们提出的另一个算法(算法 3)使用结合了参数ε的移动平均值。艾司隆有效地控制了勘探和开采之间的平衡。如果ε接近 0,大部分时间我们都会在做剥削,或者贪婪算法。正因为如此,这类算法被称为“ epsilon-greedy ”,因为 epsilon 控制着我们想要有多贪婪。ε-贪婪算法是非常常用的,包括在本文开头链接的 Atari 论文中。

让我们回顾一下我们已经讲过的内容。首先,我们解释了 k 臂土匪问题和几种可能的解决方案。我们注意到,逼近动作值函数是解决问题的重要一步。我们看到了平衡探索和利用的困难,这是强化学习问题中的一个常见主题。最后,我们讨论了贪婪ε贪婪算法,并讨论了它们如何绑定到探索/开发框架中。强化学习是一个相当广泛的话题,但是我希望这篇文章能够阐明一些基本概念。

使用 OpenAI Gym、RLlib 和 Google Colab 进行强化学习的介绍

原文:https://towardsdatascience.com/an-introduction-to-reinforcement-learning-with-openai-gym-rllib-and-google-colab-48fc1ddfb889?source=collection_archive---------15-----------------------

使用 OpenAI Gym、RLlib 和 Google Colab 进行强化学习的入门教程

本教程将使用强化学习(RL)来帮助平衡一个虚拟的横竿。上面来自 PilcoLearner 的视频展示了在现实生活中使用 RL 的结果。

作者 : 迈克尔·加拉尼克和斯文·米卡

强化学习(RL)的一个可能的定义是学习如何在与环境交互时最大化总回报的计算方法。虽然定义是有用的,但本教程旨在通过图像、代码和视频示例来说明什么是强化学习,同时介绍代理和环境等强化学习术语。

特别是,本教程探索了:

  • 什么是强化学习
  • 开放的健身房钢管环境
  • 代理在强化学习中的作用
  • 如何使用 Python 库 RLlib 训练代理
  • 如何使用 GPU 加速训练
  • 使用光线调节进行超参数调节

什么是强化学习

正如之前的一篇帖子提到的,人工智能的一个子领域机器学习(ML)使用神经网络或其他类型的数学模型来学习如何解释复杂的模式。ML 的两个领域由于其高度的成熟度而最近变得非常受欢迎,这两个领域是监督学习(SL)和强化学习(RL),在监督学习中,神经网络学习基于大量数据进行预测,在强化学习中,网络使用模拟器以试错的方式学习做出良好的行动决策。

作者图片

RL 是令人难以置信的成功背后的技术,例如 DeepMind 的 AlphaGo Zero 和《星际争霸 2》AI(alpha star)或 OpenAI 的 DOTA 2 AI(“open AI Five”)。请注意强化学习有许多令人印象深刻的用途,它在现实生活决策问题中如此强大和有前途的原因是因为 RL 能够持续学习——有时甚至在不断变化的环境中——从不知道要做出什么决定(随机行为)开始。

代理和环境

作者图片

上图显示了代理和环境之间的交互和通信。在强化学习中,一个或多个智能体在一个环境中相互作用,这个环境可以是本教程中类似 CartPole 的模拟,也可以是与真实世界传感器和执行器的连接。在每一步,代理接收一个观察(即环境的状态),采取一个行动,并且通常接收一个奖励(代理接收奖励的频率取决于给定的任务或问题)。代理人从重复的试验中学习,这些试验的序列被称为一个事件——从最初的观察到导致环境达到其“完成”状态的“成功”或“失败”的动作序列。RL 框架的学习部分训练关于哪些动作(即,顺序决策)导致代理最大化他们的长期累积回报的策略。

开放的健身房钢管环境

作者图片

我们试图解决的问题是试图保持一根柱子直立。具体来说,该杆通过一个非驱动关节连接到一个小车上,小车沿无摩擦轨道移动。钟摆开始直立,目标是通过增加和减少小车的速度来防止它倒下。

作者图片

本教程将使用 OpenAI Gym 而不是从头开始编写这个环境,OpenAI Gym 是一个工具包,它提供了各种各样的模拟环境(雅达利游戏、棋盘游戏、2D 和 3D 物理模拟,等等)。Gym 对您的代理的结构没有任何假设(在这个 cartpole 示例中,是什么推动小车向左或向右),并且与任何数值计算库兼容,比如 numpy。

下面的代码加载 CartPole 环境。

import gym
env = gym.make("CartPole-v0")

现在让我们通过观察动作空间来开始理解这个环境。

env.action_space

输出离散(2)意味着有两个动作。在 CartPole 中,0 对应“向左推车”,1 对应“向右推车”。请注意,在这个特定的例子中,静止不动不是一个选项。在强化学习中,代理产生一个动作输出,这个动作被发送到一个环境中,然后环境做出反应。环境会产生一个观察结果(以及奖励信号,此处未显示),我们可以在下面看到:

env.reset()

观察值是 dim=4 的向量,包含小车的 x 位置、小车的 x 速度、以弧度表示的极角(1 弧度= 57.295 度)以及极的角速度。上面显示的数字是开始新一集( env.reset())后的初步观察。随着每个时间步长(和动作),观察值将会改变,这取决于小车和杆子的状态。

培训代理

在强化学习中,代理的目标是随着时间的推移产生越来越聪明的行为。它通过一项政策做到了这一点。在深度强化学习中,这种策略用神经网络来表示。让我们首先在没有任何神经网络或机器学习算法的情况下与健身房环境进行交互。相反,我们将从随机运动(向左或向右)开始。这只是为了理解机制。

作者图片

下面的代码重置环境,需要 20 个步骤(20 个周期),总是采取随机操作并打印结果。

# returns an initial observation
env.reset()for i in range(20): # env.action_space.sample() produces either 0 (left) or 1 (right).
   observation,reward,done,info =env.step(env.action_space.sample()) print("step", i, observation, reward, done, info)env.close()

样本输出。在钢管舞中有多种终止情节的条件。在图像中,该集因超过 12 度(0.20944 rad)而终止。情节终止的其他条件是推车位置大于 2.4(推车的中心到达显示器的边缘),情节长度大于 200,或者当 100 次连续试验的平均回报大于或等于 195.0 时的解决要求。

上面的打印输出显示了以下内容:

  • 步骤(它在环境中循环了多少次)。在每个时间步中,代理选择一个动作,环境返回一个观察和一个奖励
  • 环境观察[x 推车位置、x 推车速度、杆角度(rad)、杆角速度]
  • 前一次行动获得的奖励。规模因环境而异,但目标始终是增加你的总回报。包括终止步骤在内,每一步的奖励是 1。之后为 0(图中的步骤 18 和 19)。
  • done 是一个布尔值。它指示是否该再次重置环境。大多数任务被划分为定义明确的情节,如果 done 为 True,则表明该情节已经终止。在推车杆中,可能是杆倾斜过远(超过 12 度/0.20944 弧度),位置超过 2.4 表示推车的中心到达显示器的边缘,情节长度大于 200,或者解决的要求是在 100 次连续试验中平均回报大于或等于 195.0。
  • info 是对调试有用的诊断信息。对于这种横向环境,它是空的。

虽然这些数字是有用的输出,但视频可能会更清晰。如果您在 Google Colab 中运行这段代码,需要注意的是,没有可用于生成视频的显示驱动程序。但是,可以安装一个虚拟显示驱动程序来让它工作。

# install dependencies needed for recording videos
!apt-get install -y xvfb x11-utils
!pip install pyvirtualdisplay==0.2.*

下一步是启动虚拟显示器的实例。

from pyvirtualdisplay import Display
display = Display(visible=False, size=(1400, 900))
_ = display.start()

OpenAI gym 有一个 VideoRecorder 包装器,可以录制 MP4 格式的跑步环境视频。下面的代码和前面的一样,除了它是 200 步,并且是录音。

from gym.wrappers.monitoring.video_recorder import VideoRecorderbefore_training = "before_training.mp4"video = VideoRecorder(env, before_training)# returns an initial observation
env.reset()for i in range(200):
   env.render()
   video.capture_frame() # env.action_space.sample() produces either 0 (left) or 1 (right).
   observation, reward, done, info = env.step(env.action_space.sample()) # Not printing this time
   # print("step", i, observation, reward, done, info)video.close()
env.close()

通常,当 done 为 1(真)时,您将结束模拟。上面的代码让环境在达到终止条件后继续运行。例如,在 CartPole 中,这可能是杆翻倒、杆脱离屏幕或达到其他终止条件的时候。

上面的代码将视频文件保存到 Colab 磁盘中。为了在笔记本中显示它,您需要一个助手函数。

**from** base64 **import** b64encode
**def** **render_mp4**(videopath: str) -> str:
  """
  Gets a string containing a b4-encoded version of the MP4 video
  at the specified path.
  """
  mp4 = open(videopath, 'rb').read()
  base64_encoded_mp4 = b64encode(mp4).decode()
  **return** f'<video width=400 controls><source src="data:video/mp4;' \
         f'base64,{base64_encoded_mp4}" type="video/mp4"></video>'

下面的代码呈现了结果。你应该得到一个类似于下面的视频。

**from** IPython.display **import** HTML
html = render_mp4(before_training)
HTML(html)

播放视频表明,随机选择一个动作并不是保持侧手翻直立的好策略。

如何使用 Ray 的 RLlib 训练代理

教程的前一部分让我们的代理做出随机的行为,而不考虑环境的观察和奖励。拥有一个代理的目标是随着时间的推移产生越来越聪明的行为,而随机的行为并不能实现这个目标。为了让代理人随着时间的推移做出更明智的行动,itl 需要一个更好的策略。在深度强化学习中,策略用神经网络来表示。

作者图片

本教程将使用 RLlib 库来训练一个更聪明的代理。RLlib 有许多优点,例如:

  • 极度的灵活性。它允许您定制 RL 周期的每个方面。例如,本节教程将使用 PyTorch 创建一个定制的神经网络策略(RLlib 也有对 TensorFlow 的本地支持)。
  • 可扩展性。强化学习应用程序可能是计算密集型的,并且通常需要扩展到一个集群以实现更快的训练。RLlib 不仅对 GPU 有一流的支持,而且它还建立在 Ray 之上,后者是并行和分布式 Python 的开源库。这使得将 Python 程序从笔记本电脑扩展到集群变得容易。
  • 统一的 API 和对离线、基于模型、无模型、多代理算法等的支持(本教程不探讨这些算法)。
  • 成为 Ray 项目生态系统的一部分。这样做的一个优点是,RLlib 可以与生态系统中的其他库一起运行,如Ray tuning,这是一个用于实验执行和任何规模的超参数调整的库(稍后将详细介绍)。

虽然有些功能在这篇文章中不会被完全利用,但是当你想做一些更复杂的事情和解决现实世界的问题时,它们是非常有用的。你可以在这里了解一些令人印象深刻的 RLlib 用例。

要开始使用 RLlib,您需要首先安装它。

!pip install 'ray[rllib]'==1.6

现在,您可以使用近似策略优化(PPO)算法来训练 PyTorch 模型。这是一个非常全面的,适合所有类型的算法,你可以在这里了解更多关于的信息。下面的代码使用了一个由 32 个神经元和线性激活函数组成的单一隐藏层的神经网络。

import ray
from ray.rllib.agents.ppo import PPOTrainerconfig = { "env": "CartPole-v0",

   # Change the following line to `“framework”: “tf”` to use tensorflow
   "framework": "torch",
   "model": {
      "fcnet_hiddens": [32],
      "fcnet_activation": "linear",
   },
}stop = {"episode_reward_mean": 195}ray.shutdown()ray.init(
   num_cpus=3,
   include_dashboard=False,
   ignore_reinit_error=True,
   log_to_driver=False,
)# execute training
analysis = ray.tune.run(
   "PPO",
   config=config,
   stop=stop,
   checkpoint_at_end=True,
)

这段代码应该会产生相当多的输出。最后一个条目应该是这样的:

条目显示,解决环境问题需要 35 次迭代,运行时间超过 258 秒。每次都不一样,但是每次迭代大概需要 7 秒(258 / 35 = 7.3)。注意,如果你想学习 Ray API,看看像 ray.shutdown 和 ray.init 这样的命令是做什么的,你可以看看这个教程。

如何使用 GPU 加速训练

虽然本教程的其余部分使用了 CPU,但需要注意的是,您可以通过在 Google Colab 中使用 GPU 来加速模型训练。这可以通过选择运行时>更改运行时类型并将硬件加速器设置为 GPU 来完成。然后选择运行时>重启并运行所有

请注意,虽然训练迭代的次数可能大致相同,但是每次迭代的时间已经显著减少(从 7 秒减少到 5.5 秒)。

创建训练模型的视频

RLlib 提供了一个 Trainer 类,它保存了一个环境交互策略。通过训练器界面,可以对策略进行训练、操作计算和检查。虽然之前从ray.tune.run返回的分析对象不包含任何训练器实例,但是它拥有从保存的检查点重建一个所需的所有信息,因为checkpoint_at_end=True是作为参数传递的。下面的代码显示了这一点。

# restore a trainer from the last checkpoint
trial = analysis.get_best_logdir("episode_reward_mean", "max")
checkpoint = analysis.get_best_checkpoint(trial,
   "training_iteration",
   "max",
)trainer = PPOTrainer(config=config)
trainer.restore(checkpoint)

现在让我们创建另一个视频,但这一次选择由经过训练的模型推荐的动作,而不是随机动作。

after_training = "after_training.mp4"
after_video = VideoRecorder(env, after_training)observation = env.reset()
done = False
while not done:
   env.render()
   after_video.capture_frame()
   action = trainer.compute_action(observation)
   observation, reward, done, info = env.step(action)
after_video.close()
env.close()# You should get a video similar to the one below.
html = render_mp4(after_training)
HTML(html)

这一次,杆子平衡得很好,这意味着代理已经解决了横竿环境!

使用光线调节进行超参数调节

射线生态系统(图片由作者提供)

RLlib 是一个强化学习库,是 Ray 生态系统的一部分。Ray 是一个高度可扩展的并行和分布式 python 通用框架。它非常通用,这种通用性对于支持其图书馆生态系统非常重要。这个生态系统涵盖了从培训,到生产服务,到数据处理等等。您可以一起使用多个库,并构建完成所有这些事情的应用程序。

教程的这一部分利用了 Ray Tune ,这是 Ray 生态系统中的另一个库。这是一个用于任何规模的实验执行和超参数调整的库。虽然本教程将只使用网格搜索,但请注意,光线调整还可以让您访问更有效的超参数调整算法,如基于群体的训练,BayesOptSearch 和 HyperBand/ASHA。

现在让我们试着找出能够在最少的时间内解决 CartPole 环境的超参数。

输入以下代码,并准备好它需要一段时间才能运行:

parameter_search_config = {
   "env": "CartPole-v0",
   "framework": "torch",# Hyperparameter tuning
"model": {
   "fcnet_hiddens": ray.tune.grid_search([[32], [64]]),
   "fcnet_activation": ray.tune.grid_search(["linear", "relu"]),
   },
   "lr": ray.tune.uniform(1e-7, 1e-2)
}# To explicitly stop or restart Ray, use the shutdown API.
ray.shutdown()ray.init(
   num_cpus=12,
   include_dashboard=False,
   ignore_reinit_error=True,
   log_to_driver=False,
)parameter_search_analysis = ray.tune.run(
   "PPO",
   config=parameter_search_config,
   stop=stop,
   num_samples=5,
   metric="timesteps_total",
   mode="min",
)print(
   "Best hyperparameters found:",
   parameter_search_analysis.best_config,
)

通过向 ray.init 传递 num_cpus=12 来请求 12 个 CPU 内核,可以在三个 CPU 上并行运行四次试验。如果这不起作用,也许谷歌已经改变了 Colab 上可用的虚拟机。任何大于或等于 3 的值都可以。如果 Colab 因内存不足而出错,你可能需要做运行时>工厂重置运行时,紧接着运行时>运行所有。请注意,在 Colab 笔记本的右上角有一个区域显示 RAM 和磁盘的使用情况。

指定 num_samples=5 意味着您将获得学习率的五个随机样本。对于其中的每一个,隐藏层的大小有两个值,激活函数有两个值。因此,将有 5 * 2 * 2 = 20 次试验,在计算运行时,在单元的输出中显示它们的状态。

注意,Ray 会打印当前的最佳配置。这包括所有已经设置的默认值,这是找到其他可以调整的参数的好地方。

运行此命令后,最终输出可能类似于以下输出:

INFO tune.py:549 —总运行时间:3658.24 秒(调优循环为 3657.45 秒)。

找到的最佳超参数:{'env': 'CartPole-v0 ',' framework': 'torch ',' model': {'fcnet_hiddens': [64],' fcnet_activation': 'relu'},' lr ':0.006733929096170726 };' ' ' '

因此,在二十组超参数中,具有 64 个神经元、ReLU 激活函数和大约 6.7e-3 的学习率的超参数表现最好。

结论

神经 MMO 是一个模拟大型多人在线游戏的环境——一种支持数百到数千个并发玩家的类型。你可以在这里了解 Ray 和 RLlib 如何帮助实现这个项目和其他项目的一些关键特性(图片由 Joseph Suarez 提供,经许可使用)

本教程通过介绍强化学习术语,展示代理和环境如何交互,并通过代码和视频示例演示这些概念,说明了什么是强化学习。如果你想了解更多关于强化学习的知识,请查看斯文·米卡的 RLlib 教程。这是了解 RLlib 的最佳实践、多代理算法以及更多内容的好方法。如果你想了解所有关于 RLlib 和 Ray 的最新消息,可以考虑关注 twitter 上的@ Ray distributed和注册 Ray 简讯。

原载于https://www.anyscale.com

数据科学家的 SQL 介绍

原文:https://towardsdatascience.com/an-introduction-to-sql-for-data-scientists-e3bb539decdf?source=collection_archive---------12-----------------------

UCL 数据科学学会工作坊 9:什么是 SQL,选择数据,查询数据,汇总统计,分组数据,连接数据

简·安东宁·科拉尔在 Unsplash 上拍摄的照片

今年,作为 UCL 数据科学协会的科学负责人,该协会将在整个学年举办一系列 20 场研讨会,主题包括 Python 简介、数据科学家工具包和机器学习方法等。每一篇文章的目标都是创建一系列的小博客,这些小博客将概述要点,并为任何希望跟进的人提供完整研讨会的链接。所有这些都可以在我们的 GitHub 资源库中找到,并将在全年更新新的研讨会和挑战。

本系列的第九个研讨会是 SQL 简介,是数据科学家工具包系列的最后一个研讨会。在本次研讨会中,我们将向您介绍在 SQL 中查询数据、从数据中提取汇总统计数据、对数据集进行分组和连接的基础知识。如果你想继续写代码,你可以在我们的 GitHub 这里找到完整的研讨会,其中包含了如何使用 docker 容器在你的系统上建立 MySQL 数据库,如何将数据推送到数据库以及如何与 MySQL workbench 交互的信息。

如果您错过了最近的任何研讨会,您可以在此找到它们:

什么是 SQL?

SQL(结构查询语言)是在关系数据库管理系统中处理数据库时使用最广泛的编程语言之一。它用于执行各种不同的操作,如选择数据、查询数据、分组数据和提取汇总度量,如下所示。在处理数据科学项目的数据时,它是一个在工业和学术界广泛使用的工具,因此理解 SQL 是任何数据科学家工具包中的一个关键工具。为此,我们向您介绍 SQL 中的一些基本命令,以及如何使用它们来操作和提取数据。

选择数据

我们想做的第一件事是能够从我们的数据库中选择数据,看看它看起来像什么。我们可以通过使用SELECT命令来做到这一点,然后使用FROM命令告诉我们想要这个信息的位置。在我们的例子中,我们有两个名为single_tabledouble_table的表,所以首先我们可以使用命令从第一个表中提取所有信息:

SELECT *
FROM single_table;

该命令将返回来自single_table的所有数据,因为我们使用*来表示我们想要所有列。

这将根据表的大小返回大量数据,因此我们可能只想查看几列,可能只查看前 100 行。我们可以通过修改我们的 SQL 语句来做到这一点,这样我们就不会使用*变量来选择所有的列,而是使用实际的名称,然后设置一个LIMIT来只返回前 100 行。我们可以使用以下命令来实现这一点:

SELECT `Air Date`, Category, `Value`
FROM single_table
LIMIT 100;

在这里,我们选择了 Air Date、Category 和 Value 列(第一列和第三列用''括起来,因为它们包含一个空格或者是关键字),我们将一个LIMIT设置为 100 行。为此,在末尾使用;分隔语句非常重要,否则 MySQL 不会将它们识别为单独的语句。

搜索条件

上述语句将返回所选列中的所有数据,但是我们可以创建更高级的搜索,以便在特定条件下进行匹配。当您仅从数据集中搜索特定信息以便缩小分析范围时,通常会出现这种情况。

在我们的例子中,我们有CategoryAir DateValue列,因此我们可以搜索属于HISTORY类别的所有问题。这是通过使用WHERE命令来指定我们希望数据匹配的条件,如下所示:

SELECT `Air Date`, Category, `Value`
from single_table
WHERE Category = "HISTORY"
LIMIT 100;

这个WHERE语句允许我们添加对数据进行子集化的条件,并允许我们使用任何想要的比较运算符,例如><==BETWEENLIKEIN。首先指定要应用条件的列,然后使用上述操作符设置条件本身。

我们还可以通过WHERE条件组合使用ANDORNOT的条件来进行更高级的搜索。例如,如果我们想将搜索范围缩小到类别为“历史”的问题,但该问题的价值也大于 200 美元,我们可以这样做:

SELECT `Air Date`, Category, `Value`
FROM single_table
WHERE Category = "HISTORY"
AND `Value` > 200
LIMIT 100;

汇总统计数据

除了提取信息以便稍后执行计算,SQL 还可以自己执行计算。这包括从列中提取所有不同值、计算数据集中值的数量或从数字列中提取平均值、最小值或最大值等功能。

例如,使用位于CATEGORY列中心的DISTINCTCOUNT命令从数据集中提取不同类别的数量。我们可以这样做:

SELECT COUNT(DISTINCT CATEGORY)FROM single_table;

这应该会返回一个单一的数字,我们有多少独特的类别。如果我们只想要一个唯一类别的列表,我们可以放下COUNT命令,我们将得到所有这些类别的列表。其他汇总统计包括MINMAXAVGSUM,就像我们在熊猫数据帧中预期的那样。

分组数据

对于数值,我们可以使用各自的命令从列中提取MAXMINAVG值,就像我们对COUNT所做的那样。但是,我们可能希望从不同的数据组中获取这些值,然后提取每组的信息。在这种情况下,我们可以将汇总统计数据与GROUP BY功能结合使用。

在这里,我们可以看到每个类别的平均值是多少,这样我们就可以尝试选择将为我们带来最大价值的问题。我们可以这样做:对我们想要获取统计数据的列调用 summary statistic 命令,并对我们想要按组提取信息的列使用GROUP BY命令。这可以通过以下方式实现:

SELECT Category, AVG(`Value`)FROM single_tableGROUP BY CategoryLIMIT 100;

在这个命令中,我们对 Category 列进行了分组,并提取了每个类别的平均值。

目前,这种方法的用处有限,因为顺序与类别出现的顺序一致,而不是与值一致。因此,我们可以结合使用GROUP BY命令和ORDER BY命令。为此,我们指定要排序的列,然后指定是按降序还是升序排序。这里我们希望数据以降序排列,这样我们可以先看到最高值。这可以通过以下方式实现:

SELECT Category, AVG(`Value`)FROM single_tableGROUP BY CategoryORDER BY AVG(`Value`) DESCLIMIT 10;

请注意,在按问题的平均值排序时,我们仍然需要指定在使用ORDER BY命令显示我们想要在被操作的列上执行聚合时在Value列上执行的聚合。

连接数据集

我们要介绍的最后一件事是JOIN功能,该功能可用于根据左表或右表中的值、两个表中的数据将两个或多个表连接在一起,或者将表与自身连接在一起。一个简单的例子是使用左连接,它使用左侧表中的所有信息,只使用右侧表中的连接信息。

在我们的例子中,我们可以使用一个INNER JOIN,在这里我们希望根据平均值连接每个表的分组类别上的single_tabledouble_table,以查看哪个数据集在每个类别中具有更高的值。为此,我们需要为第二个表指定INNER JOIN,并使用ON命令指定我们希望连接的列。我们可以这样做:

SELECT a.Category, AVG(a.`Value`) as single_value, 
b.Category, AVG(b.`Value`) as double_valueFROM single_table aINNER JOIN double_table bon a.Category = b.CategoryGROUP BY a.Category, b.CategoryLIMIT 100;

为此,需要注意的是,我们使用a.b.符号来访问每个数据集的相关列,并且在创建了INNER JOIN之后使用GROUP BY。在这样做的时候,我们还使用了GROUP BY功能在连接发生之前对每个表的类别列进行分组。虽然这可能不是最有效的方法,但它确实有效!

完整的研讨会笔记本,以及更多示例和挑战,可在的 处找到。如果您想了解我们协会的更多信息,请随时关注我们的社交网站:

https://www.facebook.com/ucldata脸书

insta gram:https://www.instagram.com/ucl.datasci/

领英:https://www.linkedin.com/company/ucldata/

如果你想了解 UCL 数据科学协会和其他了不起的作者的故事,请随时使用我下面的推荐代码注册 medium。

https://philip-wilkinson.medium.com/membership

或者看看我在 Medium 上的其他文章:

[## scikit-learn 决策树分类器简介

towardsdatascience.com](/introduction-to-decision-tree-classifiers-from-scikit-learn-32cd5d23f4d)

使用 FPL 数据的 SQL 简介

原文:https://towardsdatascience.com/an-introduction-to-sql-using-fpl-data-8314ec982308?source=collection_archive---------24-----------------------

使用梦幻超级联赛数据的 SQL 基础指南

内森·罗杰斯在 Unsplash 上拍摄的照片

对于任何与数据打交道的人来说,SQL 是一项非常有用的技能。这是一个教程,为那些想学习一些基础知识,并有兴趣这样做与幻想英超联赛数据。

数据

在本教程中,我使用来自 https://github.com/vaastav/Fantasy-Premier-League的数据。这是一个用于获取游戏周数据的 FPL 库。以前的比赛周可以在资源库中找到。我用的是一个叫 merged_gw 的文件。每个玩家的每个游戏都有一行。

工具

在本教程中,我使用数据库浏览器的 SQLite(https://sqlitebrowser.org/)。我选择了这个,通常也选择了 SQL Lite,因为设置非常简单。DB Browser for SQLite 将让我们创建数据库,添加数据,然后查询数据。

创建数据库和表

我们需要做的第一件事是创建一个数据库。在数据库浏览器中:

  1. 转到文件>新数据库
  2. 保存文件——我将其命名为 FPL.db

接下来,您将看到一个创建表的选项。在这里,我们只需单击 cancel,因为我们将利用 DB Browser 的功能,根据我们要导入的 CSV 来定义表,然后导入数据。

  1. 转到文件>从 CSV 导入>表。
  2. 选择文件并点击打开
  3. 给这张桌子起个名字——我把它命名为 Players_GWs
  4. 选中复选框,说明 CSV 中的第一行代表列名(这些将成为我们的表名列)。

这样做将创建表格。该应用程序还显示了用于创建表的查询。CREATE TABLE 后面是我们正在创建的表的名称,然后在括号中是每列的名称,后面是数据类型,每列名称用逗号分隔:

CREATE TABLE "Players_GWs" (
 "name" TEXT,
 "position" TEXT,
 "team" TEXT,
 "xP" REAL,
 "assists" INTEGER,
 "bonus" INTEGER,
 "bps" INTEGER,
.........

探索数据

要执行 SQL,我们转到执行 SQL 选项卡:

以下示例中的所有查询都是通过输入查询并单击工具栏中的“运行”按钮(或 CTRL + Enter)来执行的:

选择基础

我们使用 SELECT 来查询数据库。下面是一个从数据库中获取数据的基本 SELECT 语句。我们说我们想要从哪个表中选择哪些列。*表示我们选择所有列。

SELECT * FROM Players_GWs

限制

这将返回我们所有的行和列。不是很有用,因为有 20,700 行。如果我们想快速查看我们拥有的数据类型,我们可以运行上面的限制,只返回指定数量的行。这里我们返回 5 行:

SELECT * FROM Players_GWs LIMIT 5

选择特定列

所以我们有更少的行,但是通过使用我们仍然可以看到所有的列,这使得我们很难看到最有趣的列。我们可以用我们想要查看的特定列替换。让我们加上姓名,职位,团队,GW,总积分,值。

SELECT name, position, team, GW, total_points, value FROM Players_GWs LIMIT 5

同样值得注意的是,这些列可以按照我们选择的任何顺序排列。

SELECT position, GW, name, team, total_points, value FROM Players_GWs LIMIT 5

以...排序

到目前为止,我们有一个按名称字母顺序排列的记录列表(因为这就是 CSV 中的数据以及它保存到包中的方式)。更有趣的是根据某种度量标准来查看前 5 行。我们可以将 total_points 列添加到查询中,并根据它进行排序。这需要在限制前进行。

SELECT name, position, team, GW, total_points, value FROM Players_GWs ORDER BY total_points LIMIT 5

由 DESC 订购

如我们所见,数据从最小到最大。这是单场得分最低的五位选手。通过将 DESC 添加到我们的订单中,我们可以看到前五名。

在哪里

如果我们想查看某个特定团队的情况,我们可以使用 WHERE 来过滤团队。让我们看看马刺。所以就是[我们要匹配的列]=[我们要匹配的值]:

SELECT name, position, team, GW, total_points, value FROM Players_GWs WHERE team='Spurs' ORDER BY total_points DESC LIMIT 5

喜欢

“马刺队”寻找一个精确的匹配。我们也可以用 LIKE 来匹配一个模式。例如,假设我们想同时匹配曼城和曼联,我们可以用 LIKE 替换=并将' Man% '作为我们想要匹配的。这将查找所有以“Man”开头的团队。%是一个通配符,匹配其后任意数量的字符。

SELECT name, position, team, GW, total_points, value FROM Players_GWs WHERE team LIKE 'Man%' ORDER BY total_points DESC LIMIT 5

分组依据

到目前为止,我们一直返回单行(每一行代表一个游戏)。如果我们想要查看某个特定团队或玩家在所有游戏周的一些指标的总和,我们可以使用 GROUP BY 和对 total_points 执行的 SUM 函数。

SELECT name, team, SUM(total_points) FROM Players_GWs GROUP BY name

我们也可以按多列分组。比方说,我们希望先按团队再按球员进行细分。

SELECT team, name, SUM(total_points) AS 'overall points' FROM Players_GWs GROUP BY team, name

在第一组示例中,如果玩家在整个赛季中为不同的球队效力,球队栏将随机显示一个球队。但是第二组可以让我们看到每支球队的得分——因为我们是按球队和球员的名字分组的。

如同

代表所有游戏周中每个玩家点数的列的名称不是最具描述性的。它显示为我们对数据库中的 total_points 数据执行的函数。我们可以用 AS 给它起一个更好的名字。

SELECT name, team, SUM(total_points) AS 'overall points' FROM Players_GWs GROUP BY name

这些是 SQL 入门的一些基本查询类型。这里,我们只处理一个表中的数据,但是我们可以在另一个表中包含详细的团队信息,然后使用查询从两个表中获取数据。我将在以后的教程中研究这个和更复杂的查询。

如需进一步阅读,请查看位于 https://sqlite.org/docs.html 的 SQLite 文档

作者拍摄的所有截图。由内森·罗杰斯在 Unsplash 上做的介绍性图片。

机器学习的魔力介绍

原文:https://towardsdatascience.com/an-introduction-to-the-magic-of-machine-learning-6b213e88b54c?source=collection_archive---------1-----------------------

用数学代替代码

所有插图均由作者提供。

这些天我们经常听到机器学习,事实上它就在我们身边。这听起来可能有点神秘,甚至有点可怕,但事实证明,机器学习只是数学。为了证明这只是数学,我将用传统的方式写这篇文章,用手写的方程代替代码。如果你更喜欢通过听和看来学习,我在这里贴了一个涵盖本文内容的视频。否则,请继续阅读!

为了解释什么是机器学习以及数学是如何让它工作的,我们将全面演练一下逻辑回归,这是一个相当简单但基本的模型,从某种意义上说,它是神经网络等更复杂模型的构建模块。如果我必须选择一个机器学习模型来真正理解,这将是它。

最常见的情况是,我们将逻辑回归用于一个叫做二元分类的任务。在二进制分类中,我们想学习如何预测一个数据点是否属于两个组或中的一个,标记为 0 和 1。

为了进行这些预测,我们对给定数据点属于标记为 1 的类别的概率进行建模。

在这个设置中,我们将类标签的单个观察值写成小写的" y ",它可以取值 0 或 1,并将单个数据点写成小写的" x ",带下划线以表示它是一个向量。

更具体地说,它是一个由 m 个元素组成的向量,其中 m 是我们必须描述每个数据点的信息或特征的数量。一会儿就会明白,为什么我们把 1 作为每个向量的第一个元素。

现在我们需要决定如何对这个概率建模。逻辑回归通过以下假设做到了这一点。

我将回到这个“sigma”函数是什么,但是在这个函数内部,我们注意到我们的模型是基于数据点特征的加权和。

我们现在可以看到,通过将每个数据点向量的第一个元素设置为 1,我们获得了截距或偏差项。我们为什么要那样做,以后会变得很清楚。

因此,我们使用这些 m 特征来说明该数据点属于标记为 1 的类别的概率,并且我们可以通过改变θ参数的值来控制这些特征对该概率的贡献程度。在计算这个加权和之后,我们将它传递给这个 sigma 函数。

那么什么是西格玛呢?请注意,如果我们只是计算一个加权和,我们可以得到任何实际值,因为每个数据点的特征可能呈现任何实际值。但是我们想建立一个概率模型,这个概率在 0 到 1 之间。所以我们需要一个函数,将所有实数值映射到区间[0,1]。

其中一个函数叫做逻辑函数或 sigmoid 函数,看起来像这样。

正如我们所见,它接受任何实数值,并将其压缩在 0 和 1 之间。原来在机器学习中有很多情况是我们要这么做的,包括在神经网络中,所以 sigmoid 函数出现的很多。

好了,现在的问题是,这个θ矢量应该是什么?

这取决于我们的数据。为了有一个对一般数据点进行良好预测的模型,它可以采用各种特征的许多不同值,我们需要根据各种数据点及其相应的类别标签来选择θ参数。假设我们有 n 个数据点,称它们为我们的训练数据

这些训练数据允许我们学习最佳θ参数。最优是什么意思?一个合理且普遍的定义是,最优θ是最大化获取训练数据概率的一组参数。

这正是我们通过最大化所谓的似然函数得到的结果,它是θ的函数,定义为整个数据集(即我们所有的训练数据)的联合概率分布。假设我们的数据是独立的,我们可以把它写成每个数据点的所有个体概率分布的乘积。

但是我们如何表达一个普通数据点的概率分布,它可能属于标记为 0 或 1 的任何一类?利用我们只有两个类的事实,我们知道每个数据点属于一个类的概率就是一个减去它属于另一个类的概率。

利用指数定律,我们可以用下面的巧妙方法把这两个表达式结合起来。尝试将标签 0 和 1 插入下面的表达式,以说服自己它涵盖了这两种情况。

如果你学过概率,你可能会认识到这是一个伯努利随机变量的概率质量函数。

太好了。所以我们想最大化关于θ参数的似然函数。如果你记得一些微积分,你可能记得这将涉及到求导。很难找到这个乘积的导数,但是通过取它的对数,我们可以把这个乘积的对数重写为对数的和。我们可以这样做,因为 log 是一个单调函数,所以最大化对数似然性的θ值也会最大化似然性,我们真正关心的是这些最佳θ值。

这看起来更容易处理,但事实证明,如果我们试图找到它对θ参数的导数,我们将会没有封闭形式的解。这是机器学习中的一个常见问题,处理它的标准方法是应用类似梯度下降的迭代优化算法,这允许我们找到局部最小值。但是我们希望最大化对数似然,所以我们将该算法应用于对数似然,因为最小化负对数似然的θ参数也将最大化原始对数似然。

有很多很棒的视频解释梯度下降是如何工作的,包括 StatQuest 的这个,如果你是算法新手,你一定要看看。对于我们的问题,我们将通过迭代应用以下更新,使用它来计算每个mθ参数的最佳值:

为了应用这种算法,我们所需要的只是负对数似然相对于每个θ参数的偏导数。

为了使事情变得简单一点,我们可以首先在给定单个数据点而不是所有训练数据的情况下找到负对数似然的偏导数。因为和的导数等于导数的和,所以给定整个训练数据集,重写这些偏导数将是容易的。单个数据点的负对数似然性很简单:

但即使这样也很难区分,所以我们可以使用链式法则将导数分成更小的块(这也用于计算神经网络中的梯度,所以这是一个很好的实践)。

利用链式法则,不是直接对每个θ参数的负对数似然进行微分,而是可以对另一个我们称之为 p 的量进行微分,然后对 z 进行微分,进而可以对θ参数进行微分。这些衍生产品都很容易找到。将它们相乘,我们得到原始导数。

最后,在给定单个数据点的情况下,我们有负对数似然的导数,我们可以通过对所有训练示例求和来使用该表达式覆盖整个数据集。

好了,现在我们可以把这个导数直接代入我们的梯度下降公式,应用算法得到优化的或“拟合的”θ参数,我们把它放入一个叫做“θ帽”的向量中

这给了我们最终模型所需要的一切,它和我们开始时的一样,但是现在——关键的是——包括了“theta hat!”

这很有用,但是请记住,我们进行逻辑回归的最初目标是进行二元分类,并预测给定的数据点是属于标记为 1 还是 0 的类别。我们将这些类预测称为“ y hat”,并说如果数据点属于标记为 1 的类的估计概率大于 0.5,那么我们预测该数据点属于该类。否则,我们预测该数据点属于标记为 0 的类。

这个临界值 0.5 定义了所谓的决策边界,它是决定是否预测一个数据点属于标记为 1 或 0 的类之间的边界。

让我们看几个例子。如果我们只有一个特征,我们可以使用第二个轴来显示相应的类标签,0 和 1。由于我们的模型,我们对每个特征值的预测概率将描绘出一条 s 形曲线,决策边界将是对应于概率 0.5 的单个特征值。

如果我们的每个数据点都有两个特征,那么我们可以再次使用一个额外的轴来显示属于这两个类的点之间的间隔。在三维空间中思考,我们可以想象所有画成十字的点将位于通过 y 等于 1 的平面中,而所有画成圆的点将位于通过 y 等于 0 的平面中。这一次,两个特征的所有组合的预测概率将形成一种看起来像波浪的 s 形表面,并且决策边界将是穿过所有这些 0.5 概率值的直线。

在一维中,决策边界是一个点。在二维中,它是一条线。你能猜出它在三维空间会是什么样子吗?事实上,我们可以通过求解这个方程,用拟合的θ参数来表示这些决策边界。试试吧!

仅此而已。我们已经在不接触计算机的情况下完成了一个非常重要的机器学习模型的完整演练。当然,我们需要计算机的帮助来进行梯度下降和计算最佳θ参数,但我希望我已经说服了你,机器学习没有什么特别或神秘的,它真的只是数学。有问题请在评论里留下!

泊松整数 ARIMA 回归模型简介

原文:https://towardsdatascience.com/an-introduction-to-the-poisson-integer-arima-regression-model-b66d3ff2e6e5?source=collection_archive---------10-----------------------

图片由 Clker-Free-Vector-Images 来自 Pixabay ( Pixabay 许可)

以及如何使用 Python 和 statsmodels 实现泊松 INAR(1)回归模型的教程

整数 ARIMA 模型用于建模由整数计数组成的时间序列数据。

这些数据集带来了一些独特的挑战:

数据是自相关的:时间序列数据通常是自相关的。我们为这些数据建立的任何模型都需要考虑这些序列相关性。ARIMA(自回归综合移动平均)模型旨在捕捉时间序列数据中的自相关性。

数据仅由整数计数 0、1、2、3…等组成。: ARIMA 模型设计用于模拟实值时间序列数据,而不是基于计数的时间序列数据。基于计数的数据可以使用泊松和类泊松模型进行建模,例如负二项式和广义泊松模型。不幸的是,泊松和类泊松模型是静态模型,不是为处理相关时间序列数据而设计的。

泊松整数 ARIMA 模型弥补了时间序列数据的 ARIMA 模型与基于计数的数据集的泊松和类泊松模型之间的差距。

正如我们将在下面看到的,在结构上,泊松风险模型的构建与 ARIMA 或泊松模型非常不同。

在本文中,我们将重点关注 Brannas 在“AR(1)模型中的解释变量”中介绍的泊松 INAR(1) 模型(参见文章底部的论文链接)。INAR(1)是具有 1 阶自回归分量的整数 ARIMA 模型,即,它仅使用第一时间滞后分量, y_(t-1)。泊松 AR(1)使用泊松过程对误差分量建模。

让我们检查泊松整数 AR(1)模型的结构。我们将经常使用 Cameron A.C .和 P.K. Trivedi 的《计数数据的回归分析》一书中所遵循的符号约定,以及该主题的一些原始论文。文章最后提到了书和论文的链接。

泊松 INAR(1)模型的结构

通用整数 AR(1)模型表示如下:

通用整数 INAR(1)回归模型(图片由作者提供)

在 INAR(1)模型中,我们将时间序列在时间 t 的值 express y_t 表示为两个量的和:

ρ ○ y_(t-1): 这一项是时间序列在前一时间步 (t-1)的值的函数。

ε_t: 这是一个随机变量,代表隐藏的,因此也是未知的变量。我们将选择通过假设随机变量 ε_t. 的某种已知概率分布(如正态分布或泊松分布)来模拟潜在变量的影响

第一项,ρ○y _(t-1)值得补充说明。理解这个量的方法如下:

假设我们正在对一个电子商务网站每天的点击数进行建模。这是计数的时间序列数据,人们可以合理地预期第 t 天的点击次数与前几天的点击次数相关。

现在假设在某一天 t ,点击次数 y_t =1000 。再假设我们把这个数字 1000 看做 1000 个独立的,同分布的随机变量: b_1,b_2,b_3,…b_1000 。每个变量 b_i 遵循以下伯努利分布:

伯努利随机变量 b_i(图片由作者提供)

所以我们可以把 y_t=1000 的值看做 1000 次独立伯努利试验,每一次的成功概率为 ρ。如果一次试验‘成功’*,网站上就会记录一次点击。因此,一天 t 的预期点击数就是 ρ乘以 y _ t*

现在我们可以看到 INAR(1)方程是如何模拟在时间索引 t 的网站点击量的,即:

  • 在前一时间步 (t-1) 的预期网站点击数,以及
  • 由随机变量 ε_t. ε_t 的实现值提供的对该期望值的调整用于对一些潜在数据生成过程建模。**

泊松 INAR(1)模型

由于我们希望对整数计数的时间序列数据进行建模,因此假设基础(未知)数据生成过程是泊松过程是合适的。因此,εt是一个泊松分布的随机变量。

因此,泊松 INAR(1)模型可以表示如下:

泊松 INAR(1)模型

基本上,我们所说的是在时间 t 观察到的值是前一时间步的期望值和假设泊松比为μt的泊松分布计数的组合。

如何处理回归变量

假设 X 为回归变量的矩阵, β 为回归系数的向量,如下:

回归变量矩阵 X 和回归系数向量 β (图片由作者提供)

我们将泊松过程的平均发生率μt表示为下面的函数 X 和回归系数 β 如下:

泊松平均指数(图片由作者提供)

估计

估算包括估算 ρ和 β 该领域的各种研究提出了许多估计技术,如最大似然估计、条件最小二乘法、加权最小二乘法和广义矩法。在“AR(1)模型中的解释变量”中,Brannas 使用条件最小二乘法和条件广义矩方法技术进行参数估计。

在本文中,我们将探讨使用最大似然估计(MLE)方法来估计 ρ和β。* 我们对 MLE 的选择很大程度上取决于 statsmodels 库中GenericLikelihoodModel类的存在。GenericLikelihoodModel 类允许您指定您选择的自定义 MLE 函数,statsmodels 将很乐意为您最大化该函数。*

泊松 INAR(1)模型的极大似然估计

在最大似然法中,我们寻求将观察整个训练数据集的可能性最大化的值 ρ和【β】。具体来说,我们希望找到 ρ和 β ,这将最大化 t=1 到 n y_t 的联合出现概率的自然对数。 就符号而言,我们希望最大化以下对数似然函数:

对数似然函数(作者图片)

在实践中,我们通过使用以下规则将乘积的对数转换为各个概率的对数之和:

*ln(A * B * C * D ……)= ln(A)+ln(B)+ln(C)+ln(D)+……

最大化ℓ(⍴;β|y),我们需要构造条件概率分布 P(y_t|y_(t-1)) 。让我们看看如何做到这一点。

泊松 INAR(1)分布随机变量的概率质量函数

让我们来看看泊松 INAR(1)模型的方程:

泊松 INAR(1)模型

我们看到 y_t 由两部分组成:y_(t-1) 的期望值和一个泊松分布变量 ε_t 。因此,给定 y_(t-1) ,观察到 y_t 的概率可以表示为两个概率的乘积:

  1. y_(t-1) 个可能事件中观察到 j 个‘事件’的二项概率,接下来,
  2. 观察(y _ t—j)‘事件’的泊松概率。

由于我们不知道 j 是什么,所以我们允许 j 的范围从 0y_t(实际上是,从 0min(y_t,y_(t-1) ,但这是一个技术问题,所以一切仍然有意义)。对于 j 的每个值,我们在(1)和(2)中计算上述两个概率的乘积。最后,我们将所有单个产品总结如下:

泊松 INAR(1)分布随机变量的 PMF(图片由作者提供)

上面的等式所表示的是,在时间步长 t 观察到前一时间步长 y_(t-1)y_t 的概率,等于观察到 y_(t-1) 事件中的 0 事件的二项式概率和观察到 y_t 事件的泊松概率,或者说,观察到 1 事件中的二项式概率

让我们回忆一下,在上面的等式中,泊松过程的平均发生率 μ_t 是表示为回归变量* x_t 和回归系数 β 的如下函数:*

泊松平均指数(图片由作者提供)

让我们还记得 ρ 是二项概率,在做 MLE 时,我们不希望 ρ 出界。因此,我们定义另一个变量γ,使得:

逻辑函数(图片由作者提供)

上述逻辑函数确保当γ的范围从-∞到+∞时,伯努利概率 ρ 保持有界在 [0,1]内。

逻辑函数(图片由作者提供)

如何使用 Python 和 Statsmodels 构建和训练泊松 INAR(1)

我们将使用 STRIKES 数据集说明泊松 INAR(1)模型的使用过程:

制造业罢工数据集

为了说明模型拟合过程,我们将使用以下在回归建模文献中广泛使用的开源数据集:

制造业罢工(数据来源:美国 BLS 通过 R 数据集)

该数据集是一个月度时间序列,显示了从 1968 年到 1976 年每月开始的美国制造业活动与美国制造业合同罢工数量之间的关系。

STRIKES 数据集(来源: R 数据集)(图片由作者)

这个数据集在 R 中可用,可以使用 statsmodels 数据集包获取。

因变量 y

我们将从导入所有必需的包开始:

***import** math
**import** numpy **as** np
**import** statsmodels.api **as** sm
**from** statsmodels.base.model **import** GenericLikelihoodModel
**from** scipy.stats **import** poisson
**from** scipy.stats **import** binom
**from** patsy **import** dmatrices
**import** statsmodels.graphics.tsaplots **as** tsa
**from** matplotlib **import** pyplot **as** plt*

让我们使用 statsmodels 将数据集加载到内存中:

*strikes_dataset = sm.datasets.**get_rdataset**(dataname=**'StrikeNb'**, package=**'Ecdat'**)*

打印出数据集:

***print**(strikes_dataset.**data**)*

我们看到以下输出:

我们将前 92 个数据点视为训练集,其余 16 个数据点视为测试数据集:

*strikes_data = strikes_dataset.**data**.**copy**()
strikes_data_train = strikes_data.**query**(**'time<=92'**)strikes_data_test = strikes_data.**query**(**'time>92'**).**reset_index**().**drop**(**'index'**, **axis**=1)*

这是我们的回归表达式。罢工是因变量,产出是我们的解释变量。假设回归截距存在:

*expr = **'strikes ~ output'***

我们将使用 Patsy 来雕刻出 Xy 矩阵。Patsy 将自动添加一个回归截距列到 X :

*y_train, X_train = **dmatrices**(expr, strikes_data_train, **return_type**=**'**dataframe**'**)
**print**(y_train)
**print**(X_train)y_test, X_test = **dmatrices**(expr, strikes_data_test, **return_type**=**'**dataframe**'**)
**print**(y_test)
**print**(X_test)*

接下来,我们将扩展 GenericLikelihoodModel:

***class** INAR(GenericLikelihoodModel):
    **def** __init__(self, endog, exog, **kwds):
        super(INAR, self).__init__(endog, exog, **kwds)*

在我们的扩展中,我们将覆盖 nloglikeobs()fit() 方法。statsmodels 调用 nloglikeobs() 方法来获取每个观测值的对数似然值 y_t. 因此,我们之前描述的泊松 INAR(1)的似然函数进入该方法。该方法返回一个对数似然数组,由 statsmodels 提供的超类对该数组中的所有值求和,以获得由 statsmodels 的优化器优化的总对数似然值。

***class PoissonINAR**(GenericLikelihoodModel):
    **def** __init__(self, endog, exog, **kwds):
        super(INAR, self).__init__(endog, exog, **kwds)

    **def** nloglikeobs(self, params):
        ***#Fetch the parameters gamma and beta 
        #that we would be optimizing***gamma = params[-1]
        beta = params[:-1]

 ***#Set y and X***y = self.endog
        y = np.array(y)
        X = self.exog

 ***#Compute rho as a function of gamma***rho = 1.0/(1.0+math.exp(-gamma))

 ***#Compute the Poisson mean mu as a dot 
        #product of X and Beta***mu = np.exp(X.dot(beta))

 ***#Init the list of log-likelihhod values, 
        #one value for each y***ll = []

 ***#Compute all the log-likelihood values for 
        #the Poisson INAR(1) model*****for** t **in** range(len(y)-1,0,-1):
            prob_y_t = 0
            **for** j **in** range(int(min(y[t], y[t-1])+1)):
                prob_y_t += poisson.pmf((y[t]-j), mu[t]) *  
                            binom.pmf(j, y[t-1], rho)
            ll.append(math.log(prob_y_t))
        ll = np.array(ll) ***#return the negated array of log-likelihoods*****return** -ll*

让我们也实现一下 model.fit() 方法:

***def** fit(self, **start_params**=None, **maxiter**=1000, **maxfun**=5000, **kwds):
 ***#Add the gamma parameter to the list of 
    #exogneous variables that the model will optimize***self.exog_names.append(**'gamma'**) **if** start_params == **None**:
 ***#Start with some initial values of Beta and gamma***start_params = np.append(np.ones(self.exog.shape[1]), 1.0)***#Call super.fit() to start the training* ****return** super(**PoissonINAR**, self).fit(**start_params**=start_params,
               **maxiter**=maxiter, **maxfun**=maxfun, **kwds)*

让我们创建泊松 INAR(1)模型类的实例,并在训练数据集上对其进行训练:

*inar_model = **PoissonINAR**(y_train, X_train)
inar_model_results = inar_model.**fit**()*

打印模型培训总结:

***print**(inar_model_results.**summary**())*

我们看到以下输出:

泊松 INAR(1)模型的训练总结(图片由作者提供)

回归系数的显著性

输出变量和 gamma 的系数在 95%的置信区间都是显著的,正如它们的 p 值小于 0.05 所证明的。显著不同于零的回归截距也是如此:

回归系数的重要性(图片由作者提供)

回归系数的解释

系数的解释是而不是简单明了。伽马为-0.7039,对应于 1/(1+exp(0.7039)) = 0.33095 的 ρ

估算的 β 为 2.6215。

拟合模型的方程式为:

拟合泊松 INAR(1)回归模型的方程(图片由作者提供)

对于任意给定的 t ,0.33095(大约 33%)的 y_(t-1) 构成 y_t 。其余的来自泊松过程的估计平均值 μ_t ,它是时间 t 的输出和估计的 β 向量的函数。

测量产量变化对罢工频率的影响

从模型方程中,很容易看出,观察到的撞击次数随着制造产量的增加而增加。我们可能想通过它们增加了多少来衡量。

在训练数据集中,“输出”变量的标准偏差为 0.05654。通过打印以下内容可以看到这一点:

*strikes_data_train['output'].**std**()*

现在假设我们考虑 y_t 的两个假设值,即 y_t1y_t2 ,使得它们各自之前的值y _(T1–1)y _(T2–1)恰好相同。由于 β =2.6215 “输出”增加一个标准差,将导致泊松过程的估计均值波动 e^(2.62150.05654) = 1.15977,即大约 16%。因此,产量中一个标准差的增加会导致每月观察到的罢工次数增加 16%。*

泊松 INAR(1)模型的拟合优度

模型方程中的滞后项 y_(t-1) 使得拟合优度的确定变得复杂。泊松 INAR(1)模型的非线性排除了使用基于均方误差的测量,例如 R 平方。另一方面,由于 MLE 用于模型拟合,基于偏差的测量,例如卡方分布似然比(LR)测试 可用于判断拟合优度。然而,伪 r 平方和 LR 检验都需要计算零模型(也称为仅截距模型)的对数似然(LL)。在泊松 INAR(1)模型中,由于模型方程中滞后项 y_(t-1) 的存在,零模型的构成并不十分明显,还存在争议。

考虑到这些困难,人们可能希望通过间接方式判断拟合优度,特别是通过检查拟合模型参数的标准误差和相应的 95%置信区间。

在对“罢工”模型采用这种方法时,我们观察到以下情况:

ρ 的 95%置信区间范围为 1/(1+exp(1.174))=0.23613 至 1/(1+exp(0.233))=0.44201,与 1/(1+exp(0.7039)) = 0.33095 的 ρ 拟合值相当接近。

不幸的是,“输出”变量有一个相当大的标准误差 1.126 和相应的宽置信区间 0.415 到 4.828。正如我们在上一节所看到的,它对“打击”的影响很弱。这对模型的拟合优度有不利影响。

预言;预测;预告

该模型允许提前一步做出预测。预测包括在 X 矩阵和 y 的滞后值上运行拟合的模型。我们将在 X_testy 的滞后值上运行拟合的模型。为此,我们将在 statsmodels 中的 model.py 上实现 predict() 方法,如下所示:

*****def** predict(self, **params**, **exog**=None, ***args**, ****kwargs**):
 ***#Fetch the optimized values of parameters gamma and beta***fitted_gamma = params[-1]
    fitted_beta = params[:-1] ***#Compute rho as a function of gamma***rho = 1.0/(1.0+math.exp(-fitted_gamma)) ***#Get the Intercept and the regression variables,
    #Don't get the last column which contains the lagged y values***X = exog[:,:-1]
 ***#Fetch the lagged y values***y_lag_1 = exog[:,-1] ***#Compute the predicted y using the fitted Poisson INAR(1) 
    #model's equation***y_pred = rho * y_lag_1 + np.exp(X.dot(fitted_beta)) **return** y_pred***

让我们准备 X 矩阵进行预测

***X_test[**'y_lag_1'**] = y_test.**shift**(1)
X_test = X_test.**fillna**(0)***

根据测试数据集生成预测。由于我们对计数感兴趣,我们将对预测进行四舍五入。

***inar_predictions = np.**round**(inar_model_results.**predict**(**exog**=X_test))
**print**(inar_predictions)***

我们得到以下输出:

让我们为 y_test 绘制一步预测图:

***predicted_counts=inar_predictions
actual_counts = y_test[**'strikes'**]fig = plt.**figure**()
fig.suptitle(**'Predicted versus actual strike counts'**)predicted, = plt.**plot**(X_test.index, predicted_counts, 'go-', **label**='Predicted counts')actual, = plt.**plot**(X_test.index, actual_counts, 'ro-', **label**='Actual counts')plt.**legend**(**handles**=[predicted, actual])plt.**show**()***

我们看到的是:

泊松 IINAR(1)模型创建的一步预测罢工数量(图片由作者提供)

提前一步预测的质量证实了我们之前通过泊松 INAR(1)模型的拟合优度强调的问题。

以下是完整源代码的链接:

使用 Python 和 statsmodels 的泊松整数 ARIMA 模型

引用和版权

Cameron A. Colin,Trivedi Pravin K ., 计数数据回归分析 ,计量经济学会专论№30,剑桥大学出版社,1998 年。国际标准书号:0521635675

报纸

布朗恩斯,科特。(1995).AR(1)计数数据模型中的解释变量 PDF 下载链接

荣,罗伯特 c 和 a。整数时间序列的二项式稀疏模型。统计建模6(2006):81–96。,DOI:10.1191/1471082 x 06 ST 114 OAPDF 下载链接**

凯南 j ., 美国制造业的合同罢工持续时间,计量经济学杂志 ,第 28 卷,1985 年第 1 期,第 5-28 页,ISSN 0304-4076,https://doi . org/10.1016/0304-4076(85)90064-8。 PDF 下载链接

数据集

文章中使用的制造业罢工数据集是统计软件中可供公众使用和实验的几个数据集之一,最值得注意的是,这里的是 R 包。在 GPL v3 许可下, Vincent Arel-Bundock 通过vincentarelbundock.github.io/rdatasets已经可以使用 Python 访问数据集。

形象

本文中的所有图片版权归 CC-BY-NC-SA 所有,除非图片下面提到了不同的来源和版权。

相关文章

***

感谢阅读!如果您喜欢这篇文章,请 关注我 获取关于回归和时间序列分析的提示、操作方法和编程建议。***

worldfootballR 软件包介绍

原文:https://towardsdatascience.com/an-introduction-to-the-worldfootballr-r-package-8932b192065d?source=collection_archive---------28-----------------------

使用 worldfootballR 包提取英超联赛替补数据

照片由维也纳雷耶斯在 Unsplash 拍摄

随着[worldfootballR](https://github.com/JaseZiv/worldfootballR) R 包的创建;一个新的 R 包来帮助从 fbref.com 提取足球数据,我将试着强调这个包的使用方法。

发布的软件包目前是一个开发版本,仅在 GitHub 上可用,但一旦用户测试完成,将在 CRAN 上提供。

在这篇文章中,我将分析利物浦在过去三个赛季的英超联赛(EPL)中使用换人的情况,以了解当前赛季的行为是否发生了变化,以及在 2019-2020 赛季期间 COVID 爆发和随后暂停期间是否发生了变化。

数据是从过去两个半赛季中提取的,直到 2020/21 EPL 赛季第 17 轮比赛结束。

使用worldfootballR提取数据

该软件包有一个名为get_match_summary的功能,提取比赛 URL 的比赛摘要(进球,替补,红/黄牌)数据(以及其他关于比赛的元数据)。

要获取比赛 URL,可以使用另一个函数—get_match_urls—它接受国家代码(“ENG”代表英格兰)、性别和赛季结束年份,并返回一个比赛 URL 向量。

devtools::install_github("JaseZiv/worldfootballR")
library(worldfootballR)match_urls <- get_match_urls(country = "ENG", gender = "M", season_end_year = c(2019:2021))match_summaries <- get_match_summary(match_url = match_urls)

该函数的输出如下所示:

大量事件数据需要分析。来源:世界足球

制造第一艘潜艇的队伍

既然包装说明已经出来了,我们就把注意力转向英超联赛换人数据的分析,特别提出这个问题,利物浦的换人行为有变化吗?

这一分析大致是受 FiveThirtyEight 在联赛重启前后关于德甲球队替代者的一篇文章的启发。

用数据解释利物浦的换人

在分析的所有赛季中,利物浦在一个赛季中的替补人数略高于联盟平均水平,上赛季重新开始后,每个赛季的平均替补人数达到了 4.67 人。本赛季已经恢复到 COVID 之前的水平。

有趣的是,虽然利物浦的第一次替补出场时间通常略晚于联赛平均水平(56 分钟比 52 分钟),但红军在赛季重新开始后一直接近他们的第一次替补出场时间,而联赛平均水平已经恢复到 COVID 之前的水平,逆转了全联盟的趋势。

现在第一个小时更?

红军在 2019-20 赛季的第一个小时进行了 12%的换人(是 2018-19 赛季的两倍),本赛季在前 16 场比赛中这一比例再次翻倍。然而,联盟经历了这一趋势的直接逆转,在 19/20 赛季重新开始的部分期间飙升至 24%,并回落到前几个赛季的联盟平均水平。

看看这种趋势如何在本赛季的后半段继续下去将会很有趣。

数据来源于 worldfootballR。使用 gt 进行可视化

包裹

这是利用worldfootballR包中各种数据提取功能的一系列分析中的第一个。

在这里,我们看到利物浦比他们之前的趋势更早地进行了第一次换人,并且偏离了联赛平均水平。我将跟踪这一分析,看看这一趋势是否还在继续。

一如既往,任何关于作品或 R 包的问题/评论,请随时通过常规渠道联系。

加油红人!!

这篇文章的完整版本出现在 dontblamethedata.com 的这里

ARIMA 时间序列分析导论

原文:https://towardsdatascience.com/an-introduction-to-time-series-analysis-with-arima-a8b9c9a961fb?source=collection_archive---------9-----------------------

作者图片

时间序列预测侧重于分析等距时间间隔内的数据变化。时间序列分析广泛应用于各种领域,从计量经济学到地质学和地震预测;它也被用于几乎所有的应用科学和工程。时间序列数据的例子包括标准普尔 500 指数、发病率、死亡率、血压跟踪、全球气温。这篇文章将着眼于如何自回归综合移动平均(ARIMA)模型的工作,并适合时间序列数据。在继续之前,首先要考虑的是多变量预测和单变量预测之间的区别。前者仅使用以前的时间值来预测未来值。后者利用了不同的预测值,而不是序列本身。Jupyter 笔记本及相关数据请参考我的 GitHub repo。

白噪声及其重要性

根据定义,白噪声是随机数据。如果变量是独立的且同分布(i.i.d ),均值为零,则时间序列是白噪声(随机)。换句话说,时间序列有一个均值 μ = 0 和一个恒定的标准差 σ = c 。您可以使用 df.describe()函数来检查您的平均值:

作者图片

由于我们的平均值远高于零,我们可以放心,我们的数据不是白噪音。尽管我们不需要执行以下操作,但还是让我们将数据分成两部分,看看它们各自的标准偏差:

df_1 = df[:100]
df_2 = df[100:]print(df_1.describe())
print(df_2.describe())

作者图片

这里我们可以清楚地看到,我们的σ₁ ≠σ₂.下一张图将展示一个白噪声的例子。如下图所示,信号在平均值 0 附近振荡,不难发现标准偏差随时间保持不变。

图片来自维基百科

白噪声 y =噪声(t) = ϵₜ

由于白噪声的定义隐含着随机性,你不能对它建模并做出预测。一旦你看到白噪音,不要继续任何预测模型!

ARIMA 简介

Arima 是 Auto-Regressive Integrated Moving Average 的缩写,它是一种预测算法,基于以前的值携带固有信息的假设,可用于预测未来的值。我们可以开发一个预测模型,根据过去的值来预测 xₜ。,正式表示为:
p(xₜ | xₜ₋₁,… ,x₁)

为了理解 ARIMA,我们首先要把它分成几个基本成分:

  1. 阿肯色州
  2. 马萨诸塞州

ARIMA 模型包含三个参数:

  1. p 是 AR 项的阶数
  2. q 是 MA 项的顺序
  3. d 是差分的数目

自回归 AR 和移动平均 MA

AR 模型仅依赖于过去的值(滞后)来估计未来的值。让我们来看看 AR 模型的一般形式:

值“p”决定了预测中要考虑的过去值 p 的数量。模型的阶数越高,考虑的过去值就越多。为了简单起见,我们来看一个 AR(1)模型。

AR 模型可以简单地认为是 p 个过去值的线性组合。

另一方面,移动平均 MA 模型依赖于过去的预测误差来进行预测。让我们看看 MA 模型的一般形式:

MA 模型可以简单地认为是 q 个过去预测误差的线性组合。

现在,在进一步讨论之前,我们必须讨论平稳数据和非平稳数据之间的区别。

静止的

平稳数据是时间序列不依赖于时间变量的数据;为了开发仅依赖于过去值的预测模型,需要这种假设。没有稳定的数据会使您的预测不令人满意,因为您的模型会将时间变量考虑在内。直观上,平均值和方差等参数不会随时间而改变。下面的两个图表说明了平稳数据和非平稳数据之间的区别:

作者图片

如上所示,非平稳数据有明显的上升趋势。

现在让我们看一个非平稳数据的具体例子,并使用 Pandas 的 diff()函数来实现平稳性:

非平稳数据

#Calculates the difference of a Dataframe element compared with another element in the Dataframe (default is element in previous row = 1).df_1.diff(1).plot()

使用 Pandas Diff 函数后的静态数据

如上所述,我们通过计算连续行之间的差值实现了平稳性。

如果 d=0: yₜ = Yₜ

如果 d=1: yₜ = Yₜ — Yₜ₋₁

如果 d = 2:yₜ=(yₜ—yₜ-₁)-(yₜ-₁—yₜ-₂)

现在让我们考虑时间序列 x 的 ARIMA(1,1,1)。为了简洁起见,省略了常数项。

yₜ = yₜ — y_t₋₁

yₜ = ϕ₁yₜ₋₁ + ϵₜ — θ₁ ϵₜ₋₁

我们如何找到参数(p,d,q)

我们可以简单的使用 Auto。Arima 和交叉验证,以便找到模型的最佳参数。首先,让我们加载数据并绘制它。

df = pd.read_csv('passengers.csv', usecols=[1], engine='python')
plt.plot(df)

作者图片

如上所示,该数据具有明显的季节性上升趋势。现在我们将简单地利用汽车。Arima 来拟合数据并进行预测

y = df.values
train, test = train_test_split(y, train_size=100)# Fit model
model = pm.auto_arima(train, seasonal=True, m=12)forecasts = model.predict(test.shape[0])x = np.arange(y.shape[0])
plt.plot(x, y, c='blue' , label = 'expected')
plt.plot(x[100:], forecasts, c='green' , label = 'predicted')
plt.legend()
plt.show() 

作者图片

非常符合测试数据!

摘要

  1. Arima 是一个很好的时间序列分析工具,Auto Arima 软件包使微调过程变得更加容易
  2. 始终绘制您的数据并执行解释性数据分析 EDA,以便更好地理解数据。
  3. 了解不同预测模型背后的技术细节可以帮助你选择正确的模型。

参考

https://machine learning mastery . com/ARIMA-for-time-series-forecasting-with-python/

https://people.duke.edu/~rnau/411arim.htm

https://towards data science . com/understanding-ARIMA-time-series-modeling-d 99 CD 11 be 3 f 8

贝叶斯定理的直观方法

原文:https://towardsdatascience.com/an-intuitive-approach-to-bayes-theorem-f1af8a116375?source=collection_archive---------39-----------------------

区域类比

"剑桥自治大学霓虹灯下的数学."图片由马特·巴克在 flickr 上提供,经知识共享协议 BY-SA 2.0 授权。

这张照片很好地说明了一切:给定事件 B,事件 A 的概率等于给定事件 A,B 的概率,A 的概率,以及 B 的概率的倒数的乘积。实际上,我认为这张图片更好地总结了这一切。

这个公式来自于数学背景(相对于统计学),起初有点难以理解,如果你把这些条件概率过于字面地解释为分数,它就显得有些荒谬。这是一个很容易犯的错误——一个我很容易犯的错误——把这个公式理解成这样:

错误的贝叶斯。作者图片

这反过来又简化成了一句废话:

进一步错误的贝叶斯。作者图片

事件 A 的概率给定事件 B,不管这些事件是什么,都是确定无疑的——疯狂!显然,这不是对贝叶斯定理的正确解释,但是对于熟悉(可能过于熟悉)有理表达式的人来说,要不看到上面的分数解释可能有点困难。我承认,由于这种诱人但错误的分数转换,贝叶斯定理总是需要我做一些工作来抵制这种诱惑,并深入挖掘这一统计真理的直观而准确的解释。所以,为了让我为自己更好地记忆这个解释铺平道路,也为了给其他人带来一个有希望的直观解释,我想分享一下我对这个公式的更好的解释。为此,图像:

作者图片

假设在这个矩形内部,黄色区域 A(包括与 B 重叠的绿色部分)总共占矩形的 15%;蓝色区域 B(包括绿色重叠区域)总共占矩形的 20%;绿色重叠的地方占矩形的 5%。

问一下,如果你把你的笔悬停在这个长方形的盒子上并随机放下,你落在 A 区的概率是多少(写为 P(A))。它占了总面积的 15%,所以你有 15%的机会以黄色着陆是有道理的。降落在蓝区的概率呢,B (P(B))?它是矩形的 20%,所以有 20%的可能性。以及在 A 和 B 中落地的概率(P(A&B)也写成 P(A∩B),读作“A 相交 B 的概率”)?那是绿色区域,所以有 5%的可能性。到目前为止,还不错。

假设我们限制我们的笔只悬停在蓝色区域,b。让我们放大。

作者图片

我们在蓝区着陆的新概率是多少(P(B|B),读作“给定 B 的 B 的概率”)?现在,这是一个 100%的机会——我们已经将我们的笔移动限制在蓝色区域上!所以让我们来衡量我们的数字。蓝区原本只是总面积的 20%,现在是整个赛场:B=1.0 = 100%。至于绿色交叉区域,我们也需要扩大它。它占矩形的 5%,但它占 b 区的 0.05/0.2 = .25 =25%。

作者图片

有了这些重写的区域,就很容易知道我们的笔落在绿色重叠区域的概率是多少(P(A|B)): 25%。

让我们思考一下所有这些。为了找到单个事件的概率,例如降落在 A 或 B 或它们的相交区域的概率,我们只需查看该区域占整个矩形的比例。在绿色重叠区域中,有 15%的机会降落在 A 上,20%的机会降落在 B 上,5%的机会同时降落在两者上。

作者图片

但是,当我们限制我们的笔在蓝色区域盘旋时,B——我们可以说我们已经给定了我们将在 B 的某个地方着陆——我们通过除以 B 的面积(或者,不严格地说,除以 B 的概率)来重新计算我们的面积,以找到新的面积/在绿色 A-B 重叠区着陆的概率,或者给定我们将在 B (P(A|B))的某个地方着陆的概率,即 0.25,或者 25 在一个恰当的统计定义中,你会看到它是这样写的:

条件概率的定义。作者图片

给定事件 B 的事件 A 的概率等于 A 和 B 相交的概率(或者,在我们的面积类比中,绿色 A-B 重叠区的面积)除以 B 的概率(或者 B 的面积)。

停止追踪,关掉迪斯科球。如果我们想知道 B 给定 A 的概率是多少(P(B|A))呢?在我们上面的区域例子中,很容易放大黄色区域,再次缩放区域,看看绿色重叠区域的新区域是多少:0.3,或者说有 30%的机会降落在区域 B,假设我们要降落在 a 的某个地方。

作者图片

不幸的是,在现实生活中很难复制这一过程。通常,只有一个这样的条件概率是已知的(P(B|A)),而另一个是未知的(P(A|B))。这就是贝叶斯定理的力量。你不需要知道另一个概率,不需要去实验性地找到它。你可以先把它算掉。你可以把它想象成从放大的图片开始,然后回到完整的图片。

作者图片

我们从 P(A|B)开始,我们想到达 P(B|A)。看看我们所知道的。p(A | B)= . 25;P(B) = 0.2。让我们把它们放大。为了缩小它们,我们除以 B 的面积(0.2);把它们按比例缩小,乘以 B 的面积 P(A | B)* P(B)= 0.25 * 0.2 = 0.05 = P(A∩B)。让你回到这里:

作者图片

再次放大,这次是黄色区域 A:

作者图片

通过除以 A 的面积(0.15)来缩放面积。P(A∩B)/P(A)= 0.05/0.15 = 0.3 = P(B | A)。就是这样。你从 P(A|B)一路做到了 P(B|A ),而无需进行任何新的实验或任何更多的计数。我们现在也可以重温原来分数解释。只要稍加替换,一切都会迎刃而解:

表明贝叶斯定理产生了条件概率的定义。图片作者。

那么贝叶斯定理发生了什么?在分子中,你将 P(B|A)的条件概率(这是重叠区域,缩放到 A) 乘以 A (P(A)的大小,以查看重叠区域在“总体情况”中的价值。比如找到它的原始分数。然后,你把它缩小,这次是 B 的大小,用它除以 B 的面积(P(B))来看它值多少 B 区。那就是把你从 P(A|B)带到 P(B|A)的翻转。

当应用于一个例子时,这个东西听起来更酷。一个经典的例子是垃圾邮件。使用单词“money”的垃圾邮件的部分是 0.4(P(Money | Spam)= 0.4);所有电子邮件中垃圾邮件的比例为 0.1 (P(垃圾邮件)= 0.1);所有邮件中使用“钱”这个词的部分是 0.2 (P(Money)=0.2)。贝叶斯定理告诉你,带有“money”一词的邮件是垃圾邮件的部分或概率是 P(Spam | Money)= P(Money | Spam)* P(Spam)/P(Money)= 0.4 * 0.1/0.2 = 0.2。当一封带有“钱”字的邮件进来时,有 20%的可能是垃圾邮件。

请继续阅读这些链接,了解更多关于条件概率、贝叶斯定理及其应用的信息。

  • 集合论
  • 条件概率
  • 贝叶斯定理
  • 贝叶斯定理和条件概率(附有趣例子)
  • 朴素贝叶斯分类器
  • 多项式朴素贝叶斯解释

直观指南:熵如何与交叉熵相联系

原文:https://towardsdatascience.com/an-intuitive-guide-how-entropy-connects-to-cross-entropy-78b0713494a9?source=collection_archive---------28-----------------------

你好。

对于任何机器学习和数据科学的初学者来说,最重要的是你要清楚交叉熵的概念。它们无处不在,并作为构建树、奇特的维数缩减和图像分类的关键基础。

在这篇文章中,我将试着用信息论的视角带你了解熵的概念,当我第一次尝试掌握这个概念时,它变得非常有用。让我们看看进展如何。

照片由 Ave Calvar 在 Unsplash 上拍摄

第一步。什么是-log(p)?

信息论的主要关注点之一是量化编码和传输事件所需的总位数。直观上,罕见事件,即具有较低概率的事件,将需要更多的比特来表示,而频繁事件将不需要很多比特。

因此,我们可以从编码器和发射器的角度出发,将负对数(p) 定义为编码和传输遵循 p 概率分布的事件所需的总比特数,也称为信息、。很容易检查到小 p(罕见事件)导致大对数(p)(更多比特)。

现在,从事件观察者的角度来看,我们注意到 how -log(p)本质上是观察事件的'惊喜'。例如,如果掷硬币时 p(头)= 0.99,p(尾)= 0.01,那么如果掷的是一条尾巴,人们会惊讶得多。注意-log(p(tail)) = 6.644,远大于-log(p(head)) = 0.014。

你直观的看出-log(p)是什么意思了吧?

第二步。熵,意料中的惊喜

根据这一讨论,我们可以用概率分布 p(x)定义事件的预期惊喜,我们称之为熵。更正式地说,这是量化一个事件的可能结果中固有的不确定性水平。对于连续变量 x,熵可以写成:

熵,一个事件的预期惊喜

回到信息论,从编码器和发射器的角度来看,这量化了表示遵循概率分布 p(x)的随机选择事件所需的比特数。想象一个包含圆形和三角形的盒子,回忆化学课上熵的概念/感觉!一个偏斜的分布(许多圆和几个三角形)将意味着低熵,因为你的不确定性水平很低,这意味着,你有信心你选择的将是一个圆。

第三步。交叉熵,用于机器学习

现在换挡。让我们记住,机器学习的主要目标是找到并声明一个最佳模仿(近似)真实数据分布的概率分布。交叉熵提供了一种使用分布 q 量化遵循分布 P 编码数据所需的平均比特数的方法。

q(x)与 p(x)的交叉熵

值得注意的是,这个量可以通过下面的关系从熵中获得,其中的概念是:(原始比特)+(额外比特)=(总比特)。(额外比特)部分就是所谓的 KL-divergence ,统计学上常用来衡量两个分布之间的距离,也称为相对熵

从熵到交叉熵

在图像分类中,您会经常遇到交叉熵损失,对于 N 个类别,表示如下,其中 y_{i}和\hat{y_{i}}分别是实际标签和预测。想象 N = 2,然后你会意识到交叉熵损失如何简单地变成逻辑回归中使用的逻辑损失。

交叉熵损失

恭喜你。你已经走了很长的路。

总而言之,

  • -log(p)只是一种表达你对观察到概率为 p 的事件有多惊讶的奇特方式。罕见事件(低 p)导致高度惊讶。
  • 如果你对所有事件的惊喜进行积分,你会得到你预期的惊喜,我们称之为熵。如果你有高熵,这意味着一个事件的可能结果中固有的不确定性水平很高。
  • 交叉熵考虑了接近真实分布 P 的分布 Q,并使用分布 Q 来测量表示分布 P 之后的数据所需的比特量
  • 交叉熵损失是一种很好的方法,可以量化我们的机器学习模型对数据的真实分布(P)的逼近程度(Q)。注意,逻辑损失只是一个二元交叉熵损失。

你现在对熵是什么以及它如何与机器学习的交叉熵联系起来有了很好的理解。希望它能帮助你比以前更容易起飞。

不要犹豫留下你的想法!您的反馈和评论有助于丰富我们的社区。很高兴听到。感谢阅读:-)
DK

引导程序的直观指南

原文:https://towardsdatascience.com/an-intuitive-guide-to-the-bootstrap-9b1ebdec6975?source=collection_archive---------15-----------------------

入门

本文概述了如何在不做太多假设的情况下回答因果问题

对我来说,自举是 21 世纪最了不起的发明之一。这是一种非常强大的易于实现的重采样技术。这种技术被广泛应用于许多领域。

从测试因果断言到提高机器学习模型的预测准确性,bootstrap 已经极大地增强了任何人都可以对其数据提出的各种问题。为了充分理解它是如何工作的,我想通过一个有趣而简单的例子向大家展示一下。

想象一下,网飞正在宣传一部名为《好莱坞崛起》的虚构动作片。他们想最大化人们观看这部电影的时间。为此,他们希望优化用户登录网飞网站时看到的这部电影的艺术作品(缩略图)。

一部电影的艺术作品是用户与网飞网站互动的焦点。因此,没有吸引力的缩略图可能会阻止观众观看电影。因此,网飞的高管们热衷于使用吸引大部分用户群的缩略图。让我们假设下面的艺术品是正在考虑的两个选项之一。

照片由 Angela Ng 在 Unsplash 上拍摄。查看缩略图 A 的用户看好莱坞崛起的时间更长吗?

这些高管想知道他们的用户会对 缩略图 A 做出怎样的反应,然后再向所有人推广。为此,他们进行了一项实验。

首先,他们从用户群中随机选择 1000 名观众。然后向这些查看者显示缩略图 a。然后记录这些用户的每个查看时间。观看时间本质上是用户观看好莱坞崛起的时间。这些信息随后被用于计算网飞管理层感兴趣的各种汇总统计数据。

例如,他们可能对这个视图时间分布(MVT) 的 含义感兴趣。例如,假设他们观察到缩略图 A 的 MVT比缩略图 b 下的 MVT 高**

在 Unsplash 上由 Cameron Venti 拍摄的照片。网飞正考虑在《好莱坞崛起》首映期间展示其成员

一个简单的实验

网飞许多高管心中的一个问题是,这个数字有多可靠?他们应该用它来推动缩略图 A 超过 B 吗?他们能从某种程度上理解他们评估中潜在的不确定性吗?

让我们试着用一些模拟数据来回答这些问题。我从平均值为 50 分钟、方差为 15 分钟的正态分布中得出观察结果。

观看时间的所有 1000 名观众谁观看了设置后,显示。

使用这些参数值,我们可以观察到各种各样的视图时间行为。看起来好像有些用户几乎没有看这部电影(观看时间约 0 分钟),而他们中的少数人看完了这部电影(观看时间约 120 分钟)。所有这些场景都代表了合理的观看行为。我们还发现经验平均观看时间为 49.7 分钟。这是意料之中的,因为我是从 50 分钟的均值分布中提取的。

如何知道这个数字是异常低还是异常高?如何判断我的统计值是否只是随机的结果?也许我观察到了我所做的价值,因为我的样本中选择了特定的人,以及他们在进行这个样本的那天的特定心情?

要回答所有这些问题,我们需要测量统计数据的可变性。 也就是说,我们想知道如果我们选择不同的随机样本 ,我们的统计值会有多大的不同。那么我们该怎么做呢?

嗯,有两种大致的方法:

  1. 使用统计理论的方法
  2. 引导程序

统计理论

由于我们样本中的每个观察值都是独立的(随机抽取)且同分布的(都选自正态分布),统计理论给出了以下结果:

从统计理论中推导出样本平均值的标准误差(样本标准偏差)

我们现在可以使用这些等式来测量样本均值统计的可变性。嗯,那很简单!为什么我们不这样做呢?嗯,一个原因是这些好的封闭形式的公式只被开发用于一个被充分研究的分布的子集(想想泊松,正态)。因此,为了利用上面的简单公式,需要确保他们的数据符合每个分布的假设。

这不是一个吸引人的解决方案。像现实生活中的大多数事情一样,假设需要被检验。虽然它们有时可能是合理的,但它们最终会迫使分析师花费大量时间来验证这些假设,而不是研究手头的实际数据。

在我看来,这就是 无模型解决方案 的最终动机。我们能否在不对数据生成过程施加所有这些条件的情况下,以某种方式了解我们的估计器的行为?

有没有办法让我们用我们观测样本的经验分布作为我们的北极星;我们的指南针?

有,有!让我在下一节告诉你所有的事情

自举

我们知道我们的每个模拟观察都是独立的,并且是同分布的。因此,我们为什么不从我们的样本 中抽取样本呢?具体来说,我们为什么不用替换重新取样呢?

让我们考虑一下。我们 1000 次浏览的样本本质上是我们对网飞用户行为的唯一描述。如果这个抽样步骤执行正确 (即以分层随机的方式代表网飞用户群的分布),它应该是用户真实观看行为的相当准确的表示。

这是为什么呢?有趣的是,随机抽取的样本的 分布形状通常与从 抽取的人口相似。我知道这听起来有点奇怪。当我第一次听到这个消息时,我也对此表示怀疑。为了让我相信这一点,我进行了测试。然而,在我向你展示我的结果之前,我想请你注意另一个重要的问题。

这是否意味着我从人群中随机抽取的每个样本看起来都一样?不要!也不应该。你会注意到一些极端的例子,在这些例子中,同一个数字要么被抽取了很多次,要么根本没有被抽取。出现这种情况是因为我们用替换的 样品。 这样做可以确保:

  1. 每个抽屉都是相互独立的。
  2. 我们以反映数据生成过程的方式抽取样本。

在模拟反事实(假设)现实的背景下,这些指针再次变得非常有用。例如,假设你在最初的实验中观察到的观看时间天生就受到人们当天情绪的影响。有些人可能只是想拿些爆米花和他们的伴侣一起看一部精彩的动作惊悚片,而另一些人可能只是度过了艰难的一天,因此想看一些有趣和放松的东西。

因此,在这种情况下,您会发现视图时间分布有很大的偏差。可能会有一些小的视图持续时间和一些异常大的视图持续时间。

如果我们在大部分用户想看一部好的动作片的时候进行实验,或者相反,会怎么样呢?诸如此类的问题使得网飞很难通过单一实验的镜头准确推断观众想要什么。

那么,他们是否应该反复进行同样的实验呢?如果代价很高呢?如果这破坏了他们的用户体验怎么办?有替代方案吗?这是自举拯救世界的众多例子之一。

该引导程序描述如下:

  1. 随机选择一组网飞观众,给他们看。
  2. 记录他们的观看时间。
  3. 计算这个随机样本的平均观看时间(MVT)。
  4. *从步骤 1 中收集的样本中抽取另一个样本(随机替换)并记录其 MVT。把这个**叫做 T5【自举】MVT 叫做 ***
  5. 重复步骤 4 B 次(通常 B 被设置为 250 或 500 这样的大数字)。
  6. 计算 自举 MVT 的 B 值的样本标准差(标准差)。

我还附上了我用来用 Python 创建自己的引导示例的代码片段:

在 python 中模拟引导程序

要全面了解我用来生成下面这些图的代码,请查看我的GitHub repo。正如我所承诺的,这是我画的一些自举样本的照片:

**

一些显示引导样本的图像,这些引导样本是通过从观察样本中抽取 1000 个观察值而创建的

**

不出所料,尽管来自同一个分布,但我们在它们的每个形状上都看到了相当多的变化。你可能也想知道标准误差的自举估计是否与统计理论预测的一致?嗯,统计理论告诉我们这个数字是 0.4963 。我们的自举估计是 0.48694 。我认为数字说明了一切。

如上所示,bootstrapping 使我们能够从收集的数据中重新采样。因此,我们实质上可以模拟许多不同的现实。这些样本本质上允许我们假装在不同的时间点进行实验。

因此,通过模拟大量不同的似是而非的现实,我们可以在我们的估计器(在我们的例子中是平均观看时间)可以采用的不同值上形成一个分布。因此,通过这种分布,我们可以更好地了解估计量的不确定性。

限制

像所有的统计方法一样,bootstrap 也有它的缺点。例如,当样本量非常小时,它对手头数据的经验分布的依赖可能是错误的。我强烈建议读者查看 关于引导程序 的介绍,以获得关于这些限制的全面讨论。对于喜欢快速浏览的读者,请查看这个精彩的 栈溢出 答案。

结论

这就是它的全部!这个优雅的程序让我们可以做很多奇妙的事情。我们可以用它来衡量我们估计的不确定性。我们可以围绕我们的估计建立置信区间,并进行假设检验(例如,缩略图 A 下的查看时间是否高于缩略图 B)。我们还可以对复杂的统计数据做出推断性的陈述(例如,缩略图 A 下的平均观看时间的标准误差是多少?)不可能得到这么好的封闭形式的公式。

这些途径中的每一个都能让网飞更好地了解他们的实验结果。 它还能让他们在对数据做最少假设的情况下做出明智而有意义的决定

最后,对于那些关心这个过程的统计特性的人,不要担心。统计学家投入了大量的时间和精力来证明这一过程产生的估计值具有大量理想的统计特性(如无偏性)。

参考

[1] 布拉德利·埃夫隆和罗伯特·J·蒂布拉尼 ,《自举导论》(1994), CRC 出版社

[2] 用外行人的话解释自举是如何工作的 (2012),https://stats . stack exchange . com/questions/26088/Explaining-to-layer-why-bootstrapping-works

[3] 自举的利弊 (2017),https://stats . stack exchange . com/questions/280725/自举的利弊

F1 分数的直观指南

原文:https://towardsdatascience.com/an-intuitive-guide-to-the-f1-score-55fe8233c79e?source=collection_archive---------25-----------------------

揭秘一个非常流行的分类标准

安托万·道特里在 Unsplash 上拍摄的照片

作为一名数据科学家,我广泛使用了 F1 分数的概念,因为这是一种在澄清任务中同时考虑精确度和召回率的好方法。这是一个非常受欢迎的指标,也被称为索伦森-戴斯系数。但对我来说,这从来不是一个直观的平均值。

为了刷新我们的记忆,F1 分数的公式是 2m1m2/(m1+m2*),其中 m1m2 代表精度和召回分数。

在我看来,F1 的分数有两个关键属性:

  1. F1 分数在定义时位于 m1m2 之间。
  2. F1 分数从来不会大于 m1m2 的算术平均值,但往往会更小。(即 F1 分数向 m1m2 中较小的一个加权)。其实只有在 m1 = m2 时才等于算术平均值。

在我看来,这两个属性非常关键,因为如果没有第一个属性,它就不能被认为是一个平均值。如果没有第二个,就很难理解为什么要用 F1 分数来分类,而不是用典型的算术平均值来分类。有了这个属性,我们就可以强制要求一个分类算法在精确度和召回率上都是体面的。当使用 F1 分数时,该算法不能通过另一个中的优秀来弥补一个中的严重不足,因为分数倾向于两者中较低的一个。典型的算术平均数不是这种情况。

从 F1 分数的上述定义中,这两个重要的特性都没有突出出来。

如果其他人处于相同的位置,我想我会提供一个清晰,直观的指南来理解 F1 的分数。

我们从一个(看似)不相关的概念开始。

你可能听过一个常见的谜语,它是这样的:

你正在跑 10 公里。如果你以 10 公里/小时的速度跑完前 5 公里,然后以 15 公里/小时的速度跑完最后 5 公里,你在整个比赛中的平均速度是多少?

经过多年数学教育的磨练,典型的本能是脱口而出“12.5!”,这当然是错误的。这是算术平均值,如果比赛是根据时间而不是距离分成两部分,这将是正确的。

正确答案是 10/(5/10 + 5/15) = 12 公里/小时

很有意思。

答案小于 12.5 的原因是,我们实际上花了更多的时间以较慢的速度前进,这将平均速度向较慢的速度加权。(要把这一点说清楚,想想如果你以 0 公里每小时的速度跑完下半场会发生什么。您将永远跑完这场比赛,您的平均速度必须设置为 0。)这反映在正确的答案中。

让我们以两个任意的速度求解一个任意长度的比赛。

考虑一场长度为 x 的比赛,前半段距离(x/2)我们以 m1 的速度前进,后半段以 m2 的速度前进。在整个比赛中,我们的平均速度是多少?我们继续进行下图中的计算。

作者形象

在第 1 行,分子是所覆盖的总距离,分母是所用时间。我们进行到第 2 行,通过交叉乘法,将 2 移至分母。接下来,我们算出 x,并以取消 x 和重新排列结束。

也许你现在看到了这个常见谜语和 F1 成绩之间的联系。平均速度公式简化为精确的 F1 分数公式,其中 m1m2 表示精确和召回。

用我们可能称之为“两个一半的比赛”的故事来指导我们的直觉的优势在于,现在上面提到的 F1 成绩的两个关键属性自然出现了。在不借助抽象数学证明的情况下,这些性质从故事中直观地表现出来。事实上,他们不可能是其他人。

具体来说:

  1. F1 成绩不能大于准确率和召回率中的较大者,也不能小于两者中的较小者。因此,它确实是一种平均值。这显然是对的,因为你在整个比赛中的平均速度不能快于你在比赛中最快的瞬时速度,也不能慢于你最慢的瞬时速度。
  2. 如果两者确实不相等,F1 分数更接近精确度和召回率中的较小者,而不是较大者。因此,F1 分数不能大于算术平均值(且通常较小)。这是显而易见的,因为你花更多的时间在较慢的速度上,所以平均速度会朝着较慢的速度下降。当然,在两种速度相等的情况下,这一点没有意义。

诚然,这些属性可以直接从 F1 成绩的定义中得到正式证明,为了完整起见,我将在下面提供正式证明,但它们比故事中出现的更直观。

好了,该证明了。

深呼吸。

为了开始第一个性质的证明,我们注意到如果 m1m2 中恰好有一个是 0,那么 F1=0,性质 1 是非常正确的。如果 m1 和 m2 均为 0,则 F1 分数未定义。

现在我们只需要关注 m1 和 m2 都不是 0 的情况。

我们将用矛盾来证明性质 1:

不失一般性,让 m1m2 。因此,我们把 m2 作为两者中的较大者,如果确实存在较大者的话。

然后,我们假设,与我们试图证明的相反,F1 = 2m1m2/(m1+m2)>m2*。

既然我们知道 m2 不为零,那么我们可以将两边除以 m2 ,得到:2m1/(m1+m2)>1

将两边乘以( m1 + m2 )并组合相似项得到: m1 > m2 ,这与我们假设的 m1m2 相矛盾。

由此,我们得出 F1 ≦ m2 的结论。

通过几乎相同的论证,我们可以得出 F1 ≧ m1 的结论。我们假设 F1 < m1,两边除以 m1,两边乘以( m1 + m2 )并组合类似的项。这就产生了 m2 < m1 ,再次与我们的假设 m1m2 相矛盾。

因此,我们已经证明 F1 必须位于 m1 和 m2 之间,并且第一个性质被证明。

进一步,在 m1 = m2 的情况下,很明显 F1= m1 = m2 ,由于 F1 = 2m1m2/(m1+m2)= 2m1**

为了证明性质 2,我们再次使用矛盾的方法:

我们假设 F1 = 2m1m2/(m1+m2)>(m1+m2)/2,其中( m1 + m2 )/2 为算术平均值。*

这就简化为 4 个m1m2>(m1+m2)。如果我们乘出并组合类似的项,我们得到 0>m1+m2-2m1m2=(m1-m2)。

这是不可能的,因为一个数的平方不可能是负数。此外,等式仅在 m1 = m2 时成立。因此,我们已经表明,F1 等于算术平均值当且仅当 m1 = m2 ,(这符合事实,在这种情况下 F1 =m1=m2,如上所述),否则 F1 小于算术平均值,这是性质二。

虽然上述证明并不特别困难,但我相信你会同意我的观点,这个故事提供了非常需要的直觉。

所以下一次你遇到 F1 的分数时,把它想象成你在一场比赛中的平均速度,你以等于精确的速度跑到一半,以等于回忆的速度跑到另一半。

精确和回忆有好几个名字。精度也称为用户的准确度。召回也被称为敏感性和生产者的准确性。精确性和回忆性也与遗漏和犯错误的概念有关。这些概念的名称各不相同,这表明这些概念在多少学科中是至关重要的。

维基百科贡献者。(2021 年 9 月 28 日)。索伦森-骰子系数。在维基百科,免费百科。2021 年 10 月 10 日 16:58 从 https://en.wikipedia.org/w/index.php?检索 title = S % C3 % b 8 rensen % E2 % 80% 93 ice _ coefficient&oldid = 1047086456

https://deepai . org/machine-learning-glossary-andterms/f-score

无需数学的假设检验的直观介绍(几乎)

原文:https://towardsdatascience.com/an-intuitive-introduction-to-hypothesis-testing-210277ddf09?source=collection_archive---------12-----------------------

照片由 Testalize.me 在 Unsplash 上拍摄

在这篇文章中,我将做一个假设检验的基本演示。我会尽量避免使用数学,把重点放在让你对所涉及的概念有一个总体的概念上,并在假设检验上培养一些直觉。

好吧,那我们开始吧。

一个例子

我将向你们展示一个假设,这个假设是-

我们将忽略不同年龄组女性之间的潜在差异,保持简单。现在,虽然我们以正常的方式称之为假设,但在统计学中,假设有一个正式的含义,即可以被检验的东西。

所以让我们试着测试一下。假设我们选取 20 名女性作为样本,她们的平均身高为 168.6 厘米。

那么这个观察对于这个假设意味着什么呢?我想让你停下来思考几秒钟- 这对我们的假设产生了多大的怀疑?

我们一开始说平均值是 169 厘米,但现在我们有了这个样本,它比那个略小,但它真的对假设产生了很多疑问吗?

大概不会吧?我们随机选择了一个小样本,但由于随机变化,选择的女性可能略矮。所以我们的假设仍然是正确的,这并不是完全不可能的。

取不同的样本 现在让我们想象另一个场景,我们再次随机抽取 20 名女性 ,但这次她们的平均身高是 161 厘米 。这一次平均值比上一次稍远一些。

所以让我再问你一次,这给我们的假设带来了多大的怀疑。

你认为这次观察到的样本 的平均身高为 161 厘米会比上一个例子 更加令人怀疑吗,即使我们抽样的人数相同?

平均身高比 169 低很多,所以你要开始思考这个样本只是随机低于真实平均值的可能性有多大。

虽然我们还没有处理任何公式或数学,但你已经在这一点上完成了你的第一个假设检验。

现在让我们稍微形式化一下。更具体地说,我们将原始假设称为 零假设 ,并将其表示为【h₀】、 ,在这种情况下,零假设 是真实平均值为 169 cms 。然后我们得到了另一个叫做 的东西替代假说 通常被表示为 H₁. 在替代假设下,真实均值不是 169 cms。

无效假设和替代假设

所以问题是,我们的样本均值是否离 169 厘米足够远,以至于我们能够拒绝最初的假设?在第二个例子中,你认为——嗯,也许它离 169 足够远,也许现在对零假设有相当多的怀疑

形式化假设检验

让我们考虑这条代表样本均值可能值的数字线。我们通常用 x̅代表样本平均值,用𝝻.代表总体平均值如果你取一个样本,取它的平均值,你会期望它是 169,但是你也知道由于随机变化 ,它可能是 168 或 170。

假设检验所要做的就是设定这些关键的界限,超过这些界限,我们将开始拒绝零假设。所以当我们的样本变得太极端时,我们开始更加怀疑我们的零假设。在我们的示例中,样本平均值为 161 厘米,很可能离 169 太远,处于剔除区。

第二个例子

现在让我们试试另一个例子,另一个假设。我们的第二个假设是

像以前一样,我们要取一个样本来检验这个假设。这一次,虽然我们只取了五个人作为样本,但我们发现这五个人的平均体重只有 68 公斤。

同样,我们也要问自己同样的问题- 这对我们的假设 产生了多大的怀疑。所以停下来几秒钟,想一想

现在,即使权重之间的差异很大,你可能会认为这没关系,因为我们 只考虑 5 个样本 ,也许,只是也许我们选择了稍微轻一点的人,如果我们再选择 5 个样本,总样本的平均权重可能会上升。

现在让我提出一个稍微修改的场景。这一次我们抽样调查了 500 人,而不是 5 人。但是样本平均值仍然是 68 公斤。这给我们的假设带来了多大的质疑?

你会开始认为- 是的,这是铸造了很多疑问现在 。平均重量没有一点变化,但变化的是样本中的观察次数。所以我们现在在样本中有 500 个人。这意味着 我们对样本均值 更有信心,我想直觉上你可以看到这个工作。以亚马逊评论为例——一个产品在 5 个评分中获得 4.8 星,而另一个产品在 1200 个评分中获得 4.8 星。你会对第二种产品更有信心。

如果你有一个更大的样本,发现平均体重仍然是 68,你会开始想,我们现在几乎已经得到了整个城镇——真正的平均体重可能不再是 74 了。

我们这里的零假设是真实的总体均值是 74,我们的
替代假设是它不是 74。

无效假设和替代假设

因此,在我们的五人样本中,我们将在这里得出的决定我们是否拒绝零假设的临界值可能远离 74,但当我们的样本中有 500 人时,我们将拒绝零假设的临界值实际上非常接近 74。所以如果我们得到一个样本均值,比如说 71 或者 77,这就有足够的证据来否定零假设。

较大的样品扩大了剔除区

到目前为止,我们还没有做任何实际的计算,但是我们有办法计算这些精确的区域,来决定我们是否要拒绝这个无效假设。

通过这些我们很快就会看到的计算,我们真正想要回答的是这个问题— 如果零假设为真,我们的样本 有多极端?这确实是假设检验试图从数字上回答的核心问题。

虽然在文章的开始我提到我们将保持这种数学自由,我只是给你一个公式,并帮助巩固我们在这里发展的直觉。

样本的极值

这个 Z 是极值的度量 。因此,当 Z 接近于零时,这意味着我们的样本与零假设为真时我们的预期相符。如果你看看这个函数的分子,你可以看到,如果样本均值等于假设均值μ,那么我们会得到 0。和x̅和 mu 之间的差距越大,z 值越大 意味着我们的样本更极端,这意味着我们更有可能拒绝零假设,我们在第一个例子中看到了这种情况。

另外,你可能会注意到分母上有一个 n ,它代表样本大小。我们现在也明白了这是如何工作的,因为随着 n 的增加,Z 的值也会增加,这再次意味着我们更有可能拒绝空值。因此,随着样本量的增加,我们更有可能拒绝零,除非总体和样本均值之间的差异很小。

基于以上所见,我们知道当-
1 时,我们更有可能拒绝【h₀】。样本差异较大,如第一个示例和
2。当观察次数更多时,如第二个例子。

假设检验本质上包括三个步骤

假设检验过程

第一类和第二类错误

这就引出了本文的最后一个概念,即第一类和第二类错误。

第一类和第二类错误

当我们进行假设检验时,我们会根据手头的证据做出决定,而不是 100%有保证的证据。我们只是说,有足够的证据表明会有这样或那样的行为。统计学上永远如此!正因为如此,无论做出什么决定,我们都有可能犯错误。总有机会得到一个极端的样本,使你拒绝零假设或替代假设。

在前面的例子中,我们有拒绝区域,在那里我们要拒绝零假设。当我们拒绝事实上为真的零假设时,第一类错误就发生了。我们永远无法排除打字错误的可能性。

拒绝区域是任意的,由测试人员选择

类型 1 错误的概率称为显著性水平α(α)。事实上,你可以选择你的重要性水平。你可以选择拒绝零假设的决定有多严格。我们通常会使用 5%的级别,但这只是惯例。我们在这里画出的这些区域,我们要拒绝零假设,是完全任意的。我们只是根据我们称之为显著性水平(α)的严格程度来决定它们。

当您不拒绝事实上为假的零假设时,就会出现类型 2 错误,因此假设样本均值非常接近 169 cms,因此我们选择不拒绝该零假设。当然,真实的人口平均数仍有可能不同于 169。这可能是任何事情,在这种情况下,我们将犯第二类错误,这种犯第二类错误的可能性是我们无法完全减轻的。当我们进行假设检验时,总会有犯第二类错误的概率,在这种情况下,犯第二类错误的概率被称为β(β),一个负β被称为假设检验的功效(1- β )。

假设检验的介绍到此结束。

对费希尔信息的直观观察

原文:https://towardsdatascience.com/an-intuitive-look-at-fisher-information-2720c40867d8?source=collection_archive---------1-----------------------

思想和理论

它的含义,以及为什么它是这样计算的

Fisher information 提供了一种方法来衡量随机变量包含的关于随机变量的假设概率分布的某个参数 θ (如真实均值)的信息量。

我们将从费希尔信息的原始定义和公式开始。

费希尔信息的定义和公式

给定一个随机变量 y ,假设它遵循一个概率分布f(y);θ),其中 θ 为分布的参数(或参数向量),Fisher 信息计算为偏导数的方差w . r . t .θℓ(*θ*****

Fisher 信息为表示为偏导数的方差 θ* 对数似然函数ℓ(θ| y)(图片由作者提供)***

上面的公式可能看起来有点吓人。在本文中,我们将首先深入了解费希尔信息的概念,然后我们将了解为什么它是以这种方式计算的。**

先说个例子。

泊松过程的例子

让我们从下面的数据样本开始我们的旅程。这是一个泊松过程的模拟,模拟了医院急诊室每小时到达的病人数量。

模拟病人到达急诊室的泊松过程(图片由作者提供)

在这个数据样本中,随机变量(姑且称之为 y )是每小时到达的病人数。既然 y 是一个离散的随机变量,它必然服从某种 P 概率 M ass F 函数( PMF )。像这样的全编号事件类型数据通常可以通过泊松分布成功建模,如下所示:

泊松分布的离散随机变量 yP 概率 M ass F 函数(图片由作者提供)

此时,我们需要后退一步,注意以下两点:

  • 我们不知道(也永远不会知道)什么是 y 的真实概率分布。我们所拥有的只是几百个事件的数据样本。基于数据的性质(在我们的示例中,基于非负计数的事件数据),我们假设 y 是泊松分布的。
  • 其次,即使我们(正确地)假设 y 是泊松分布,我们也不会知道 y 值的总体的真实平均事件率 λ_0 的值。我们能做的最好的事情是使用样本平均速率 λ 来估计 λ_0

现在,假设你观察到一定数量的病人在特定的时间走进急诊室。假设,y= 20。如果能够知道 y 中包含多少关于 y 值总体的真实但未知的平均事件率 λ_0 的信息,那就太好了。而这正是费希尔信息让我们以数学特别擅长的量化方式来衡量的!

在我们理解如何度量随机变量 y 中包含的费希尔信息之前,让我们再一次看看泊松概率的公式:

泊松分布离散随机变量 yP 概率MasF函数(图片由作者提供)**

注意 f(y) 实际上是两个变量的函数:

  • 观察到的事件计数 y,
  • 平均速率λ。

因此,我们将 PMF 的等式写得稍微有些不同,如下所示:

PMF 表示为 y 和 λ(图片由作者提供)的函数

假设我们是某个无所不知的存在,他们知道真实的群体平均事件率 λ_0 是每单位时间 16 。利用 λ=λ_0=16,我们得到下面的图,用于f(y;λ) w.r.t. y:**

平均速率的泊松 PMFλ= 16(图片由作者提供)**

这幅yPMF 的图给了我们这个问题的答案:假设真实的平均发生率是 16,那么单位时间内观察到 0,1,2,3…事件的概率是多少?

毫不奇怪,概率f(y;λ=16) 峰值在 λ=16。**

泊松变量通常是整数(离散)值,但我们将它显示为一条平滑的曲线。严格来说,简单地将 PMF(离散概率函数)转化为平滑的概率曲线是非常不正确的,但是将其显示为平滑曲线将有助于我们使用单参数分布(如泊松分布)来说明 Fisher 信息背后的一些概念。这是上述分布的连续版本:

f(y;λ)w . r . t . y .λ= 16事件/单位时间(图片由作者提供)**

可能性的概念

现在,假设我们对 y=10 进行单次观察。我们将 y 固定为 10,并允许平均速率 λ 从 0 变化到∞。

这里我们提出的问题是:给定不同的平均速率 s λ值,在某个单位时间间隔内观察到 10 事件的概率是多少?****

这类问题是可能性函数概念的基础。

f(y;λ) w.r.t. λ 如下图,外形与上图相似。不同之处在于这两幅图的坐标轴所显示的内容。

在上图中,X 轴显示随机变量 y 的观察值,Y 轴显示概率(或连续YY情况下的概率密度)。**

在下图所示的第二个图中,图的 X 轴显示了参数 λ。y 轴描绘了所谓的 λ 的似然函数,用程式化的 L、表示,即: ℒ(λ|y) ,或者一般来说ℒ(θ|y)对于某些参数 θ 对于给定的随机变量 y 的观测值,它被读出为 θ 的可能性。**

y=10 的观测计数的 λ的似然函数(图片由作者提供)

我们观察到关于此图的以下三件事(用蓝色矩形突出显示):

似然函数上缓慢变化的似然区域(图片由作者提供)

  1. 对于(未知的)真实平均速率 λ 的值远离yT5【的观测值(本例中为 10),似然函数变化不大。这由曲线底部左侧和右侧(尤其是右侧)的蓝色矩形标记。****
  2. 类似地,当值 λ 非常接近观察值 y=10 时,可能性不会改变太多。这由可能性曲线顶部的平顶区域指示。
  3. 对于 λ 的其余值, λ 的每一个单位变化都会导致在任何给定的小时内观察到 10 事件的概率发生很大的变化。

通过检查似然变化率的绝对值的曲线图ℒ(λ|yw . r . t .λ,证实了上述三个直觉。****

似然变化率 w.r.t. θ

可能性ℒ(λ|y偏导数 w.r.t. λ的绝对值(图片作者提供)**

我们通过将 y 固定在特定小时内 10 个事件的观测值上来构建上述图表,我们绘制了以下值与平均速率的关系:

似然 ℒ(λ|y 的偏导数 w.r.t. λ的绝对值)(图片由作者提供)。

对数似然的概念

不是微分原始似然函数 ℒ(λ | y_i) ,而是微分似然函数的自然对数通常是方便的,原因如下:

  • 对目标函数凹性的需求:很多时候,我们希望找到能最大化观测整个训练数据集的联合概率的参数向量 θ 。换句话说,我们希望最大化训练数据集中所有观察到的 y_i 的可能性 ℒ(λ | y_i) 的乘积。这种优化技术被称为最大似然估计。如果被最大化的函数是一个向下凹的函数,则最大化起作用。许多概率分布函数只有在取对数时才是下凹的。**
  • 保存优化目标:x的对数函数是 x 的严格增函数。通俗地说, log(x)x 起伏。因此,无论我们对 x 有什么优化目标,采用 log(x) 将保持这些目标不变。
  • 易微分:几种概率分布f(y;θ) 包含指数运算和乘法项。泊松和正态概率分布函数是经典的例子。区分这样的功能会变得很乏味,有时甚至完全不可能。取自然对数具有“消除”指数运算的效果(即“ e 项)。对数运算符还将所有乘法转换成加法,使得求导工作变得容易得多。

对数似然函数用小格程式化的 l 表示,即ℓ( θ | y ,对于给定的随机变量y的观测值 y ,读作θ的对数似然****

采用泊松分布函数的自然对数可将其简化为以下函数:

泊松分布函数的自然对数(图片来自作者)

对数似然函数的偏导数

让我们保持 y 固定在某个观测值 y 并重写ln(f(λ;y)) 为对数似然函数ℓ(λ| y =y)。接下来,我们对ℓ(λ| y =y)求偏导数,得到如下函数:**

泊松分布对数似然函数的偏导数 w.r.t. λ(图片由作者提供)

让我们画出 λ 的非负值的偏导数:

ℓ(的偏导数 w . r . t .λλ| y= 10)对于 λ的非负值(图片由作者提供)**

上面的图揭示了以下特征:

  • 当真实平均速率 λ 等于每小时观察到的计数 y=10 时,对数似然函数的变化率下降到零。
  • 当真实平均速率 λ 与 y=10 的观测值相差很大时,对数似然的变化相对于真实平均速率 λ 迅速且渐进地稳定到恒定值-1。
  • 对于真实平均率 λ 的所有其他值,对数似然函数对于 λ中的每个单位变化变化非常迅速。

这里有一些有趣的事情:

对数似然的偏导数的方差

对数似然的偏导数就像 y 一样是一个随机变量。对数似然的偏导数也有均值和方差。

该函数的方差越小,观察值 yy 的概率分布的真实平均值匹配的可能性就越大。换句话说,随机变量 y 中包含的关于 y 的真实含义的信息越多。另一方面,ℓ(λ| y= y的偏导数的方差越大,包含在 y 中关于其真实均值的信息就越少。**

因此, y 所包含的关于【y的假定分布的某个参数 θ 的真值的信息,与对数似然函数的偏导数 w.r.t. θ 的方差成反比关系。这种相反的关系由 y 的分布的费希尔信息捕获如下:

费希尔信息(图片由作者提供)

上述等式的 R.H.S .可以通过使用下面的计算随机变量 X 的方差的公式来简化:

随机变量 X 的方差公式(图片由作者提供)

记住对数似然的偏导数本身是一个随机变量,具有平均值,即期望值(w.r.t. y )。因此,我们可以利用上述方差公式,如下所示:

费希尔信息(图片由作者提供)

期望值在费雪信息计算中的作用

上式中需要注意的一点是期望值,R.H.S 上的 E() 算子是 w.r.t .随机变量 y. 它们是不是w . R . t .y概率分布的参数 θ这是有意义的,因为对数似然函数的偏导数总是针对随机变量y= y的特定观测值来计算的。例如,在泊松的例子中,我们计算的是在某个小时的观察中的y= 10观察到的事件。因此,对于随机变量 y 的每个观察值,对数似然函数的偏导数可能呈现不同的值。因此,偏导数的期望值具有(粗略地说)“平滑”整个观察值范围内的方差的效果。**

简化费希尔信息方程的程序

对等式(1)的 R.H.S .的第一个期望可以用无意识统计学家(简称 LOTUS)的定律来简化,它是这样的:

  • 如果 X 是一个概率密度函数为f(X= X)的连续随机变量,并且**
  • g(X)X 的函数,那么,
  • g(X)的期望值,即E(g(X)可以用下面的公式计算:**

无意识统计学家的法则(LOTUS)(图片由作者提供)

我们可以如下使用 LOTUS 来求解等式(1)的 R.H.S .的两个期望中的第一个:

简化费希尔信息方程(图片由作者提供)

同样,我们可以使用 LOTUS 来求解等式(1)的第二个期望:

简化费希尔信息方程(图片由作者提供)

在上面的等式中,通过注意对数似然函数ℓ(θ| y= y)实际上是概率分布函数 y、f(θ;y)* 它是两个变量的函数, yθ。所以它的偏导数 w.r.t. θ 可以表示为:***

(图片由作者提供)

我们将把这个结果代入方程(1b)的 R.H.S .积分中。此外,由于在 R.H.S .上的积分是 w.r.t. y ,我们可以在这个积分之外求 w.r.t. θ 的偏导数,如下所示:

简化费雪信息方程中的方程(1b)

在上面的简化中,我们利用了这样的事实,因为 f(。)是 y 的假定概率分布,f(y=y)从-∞到+∞的积分将为 1,对常数值 1 的微分为零。因此,等式(1b)简化为零。

现在,让我们回忆一下等式(1)表示的费希尔信息的等式如下:

费希尔信息方程(图片由作者提供)

等式(1)由等式(1a)组成:

(图片由作者提供)

和方程 1b,我们评估为 0。

因此,我们有以下结果:

给定一个随机变量 y 假定服从一个概率分布f(y θ ),该分布的费希尔信息可以使用以下公式计算:**

费希尔信息的公式(图片由作者提供)

引用和版权

,【费希尔 R. A .】,(1922)论理论统计学的数学基础,伦敦皇家学会哲学汇刊。A 辑,包含数学或物理性质的论文。222309–368。http://doi.org/10.1098/rsta.1922.0009**

形象

本文中的所有图片版权所有 Sachin Date 在 CC-BY-NC-SA 下,除非图片下面提到了不同的来源和版权。

如果您喜欢这篇文章,请关注我的Sachin Date以获得关于回归、时间序列分析和预测主题的提示、操作方法和编程建议。**

对信息论基础的直观观察

原文:https://towardsdatascience.com/an-intuitive-look-at-the-basics-of-information-theory-2bf0d2fff85e?source=collection_archive---------22-----------------------

入门

数据压缩、熵、加密、Kolmogorov 复杂性以及它们为何重要的非技术之旅

随机像素的放大视图。图片由作者提供。

介绍

本文将着眼于信息理论,目标是为一些概念及其应用开发有用的直觉。它将远离技术细节,但底部有链接的参考资料供进一步阅读。首先,我想从一个简单的问题开始:

任何文件都可以压缩吗?

这个问题的答案是深刻的。不要只是陈述答案,让我们看看我们是否能推理出解决的方法。

  1. 假设任何文件都可以被压缩,导致文件变小。
  2. 因此,压缩文件的输出也可以总是被压缩。
  3. 如果这是真的,那么任何文件都可以被无限多次压缩。
  4. 因此,任何数量的信息都可以压缩成一位。
  5. 这显然是荒谬的,所以我们必须拒绝前提。

关键的一点是,冗余度较大(因此信息较少)的文件可以比冗余度较小(因此信息较多)的文件压缩得更多。一旦你压缩了一个文件,你就消除了冗余,使其信息更加密集。试图再次压缩它将产生收益递减。

通过创建一个包含随机生成的文本(没有模式或冗余)的文件,并尝试将其压缩成 ZIP 文件,您可以很容易地看到这一点。检查前后的文件大小,你会发现它们没有什么不同。同时,从维基百科上取一段,复制粘贴几十次到一个文件里,然后压缩。你会看到它缩小了很多。您还可以尝试使用zlib Python 库的compressdecompress函数,以编程方式进行压缩。

探索数据压缩涉及到信息论中一些最重要的观点:

  • 有一个基本的信息单位(比特)。
  • 并非所有的比特串都包含相同数量的信息——有些比特串可以比其他比特串压缩得更多。
  • 文件中的信息量与其随机性相关,与其可预测性负相关。

作者随机像素。由 Pauline Loroy 在 Unsplash 上拍摄的狗狗照片

关于随机性和信息的想法通常是违反直觉的。哪一个包含更多的信息,一个看起来有噪声的随机像素的图像,就像左边的图像,还是一张狗的照片(假设像素数量相同)?很多人可能会说,随机像素的图像包含的信息比狗狗照片少。对于我们的人眼来说,随机像素看起来是重复和多余的。但这是不正确的。当我们放大到像素级别时,我们看到随机像素表现出多样性、不可预测性和缺乏模式,而狗的照片则有模式和冗余。狗的照片可以压缩到原来大小的一小部分,而随机像素则不能。不信你自己试试!可解释性和对人类的意义并不等同于信息内容。

放大了上面两张图片(随机像素对狗)。作者图片。

加密和信息

加密意味着获取一条消息,让没有密钥的人无法阅读。早期的替换密码(如凯撒密码)只是简单地用字母互相替换,保留了语言的统计模式。如果消息在加密前是可压缩的,那么在加密后仍然是可压缩的。我用zlib进行了测试,在美国权利法案上得到了 70%的压缩率,不管是否应用了凯撒密码。看到我用的代码这里。通过使用字符频率的统计知识,这些替代密码很容易被破解。

现代安全加密使加密的消息看起来与随机位无法区分,消除了原始消息统计属性的任何泄漏。加密是基于位的,因此任何类型的信息都可以加密—文本、照片、音频、视频、可执行文件等。为了直观地了解加密是如何工作的,让我们考虑一下一次性密码本(OTP),它是加密的一个基本构造块。

要使用 OTP,双方需要共享一串秘密随机位(“pad”)。为了发送秘密消息,一方将消息转换成二进制,用填充符将其排列起来,并执行按位异或(XOR)运算。XOR 由带加号的圆圈表示,如果两位相同,则返回 0,如果两位不同,则返回 1。结果是一串看起来随机的比特,没有密码板是完全无法破译的。因为看起来是随机的,加密的信息几乎是不可压缩的。没有关于潜在消息的统计信息被泄露,它甚至不受暴力攻击的影响,因为当你尝试每一个可能的长度为 N 的 pad 时,你将简单地揭示长度为 N 的每一个可能的消息,没有办法区分正确的和不正确的。

使用一次性密码本的加密示意图。图片作者。

为了解密消息,接收方用他/她的 pad 排列接收到的消息,并再次执行逐位 XOR。这将反转加密并揭示原始消息。这是因为 XOR 函数的一些特性:(a XOR b) XOR b = a XOR (b XOR b) = a XOR 0 = a。实际上,交换真正随机的一次性密码本是不可行的。但是上面解释的思想也可以用于伪随机密码本,这意味着双方只需要交换用于生成伪随机密码本的相对较短的秘密密钥。

让我们试着把加密和信息密度的概念放在一起。考虑下面的思维实验:你是一名间谍,任务是寻找和解码敌人的信息。有一天,你截获了一个图像文件。你打开它,发现每个像素的 RGB 值都是(0,0,0)。图像完全是黑色的。你对这个截获的文件有什么看法?

你可以确信,无论你的对手使用什么样的加密方法,在黑色像素阵列中没有隐藏的秘密图像或秘密信息。为什么?因为它是非随机的,非常冗余,而且它不包含太多的信息。当然,信息内容不是零(可能已经有了预先的协议,如果场景 A 发生,对手将向他们的伙伴发送黑色图像,如果场景 B 发生,发送白色图像,等等。).但是加密不能删除消息中的信息,解密也不能恢复丢失的信息,所以如果加密后的消息是低信息量的,那么之前的消息一定也是。

两幅图像的像素数量相同。全黑图像的压缩率是随机图像的 1000 倍。注意:PNG 是一种无损压缩格式。图片作者。

另一方面,如果你收到的是一个随机像素的数组,就像上面的图像一样,它与加密后的有意义的图像没有什么区别。通过应用某种变换,图像中看似随机的 0 和 1 可以变得有意义。也许像素只是代表随机的比特,这对我们人类来说没有多大意义。如果没有额外的知识,我们无法区分,但无论哪种方式都有信息存在。意义和信息不是一回事。意义与我们对信息的主观理解有关,而信息则是一种客观指标。

事实上,低于预期的信息量可以暗示意义的存在。如果你是一名天体物理学家,正在接收来自深空的信号,在混乱的背景噪声之间,你突然探测到一串信息异常低的比特(即异常可压缩的序列),你可能会开始怀疑你正在接收一个外星人的传输。对于我们人类来说,信息中的非随机性和冗余性是一个强烈的意义信号——无论是语言的统计模式、玫瑰图像中的红色像素海洋,还是一段音乐的和声。无论假想的外星人与我们有多么不同,他们产生的信息无疑也包含冗余。

宏观状态和微观状态

我们刚刚讨论了将随机性与缺乏信息混为一谈,将有序性与信息混为一谈是错误的。我们可以用宏状态微状态来理解命令信息的关系。宏观状态是对系统的宏观描述,例如“画面全黑”或“画面有随机值的像素”。微观状态是系统在较小细节层次上的精确排列,例如图像中每个像素的实际 RGB 值。

的概念,通常翻译为“无序”,在热力学和信息论中都有出现。当一个给定的宏观状态有很多微观状态时,就会出现高熵。低熵是指给定的宏观状态只有很少的微观状态。更少的熵意味着更多的有序和更多的可预测性。更多的熵意味着更少的有序性、更多的随机性和更多的不确定性。

让我们考虑另一个日常例子:滚动一对骰子。任何垄断玩家都知道,并非所有的结果都是平等的。平均而言,每 36 卷中只有 1 卷会产生 12 个总数。但是 36 中的 6 将产生 7 的和。因此,宏状态“我掷了一个 12”只有一个对应的微状态,而“我掷了一个 7”有 6 个微状态。

掷出 7 有六种方法,但掷出 2 或 12 只有一种方法。图片作者。

在前面的全黑图像中,只有一个微观状态与宏观状态“图像全黑”匹配:每个像素必须具有 RGB = (0,0,0)。这意味着熵非常低,因此信息量低,因此可压缩性高。每个像素都符合前一个像素的模式,因此它不会提供任何令人惊讶或有价值的信息。

在随机像素图像中,有难以想象的大量微观状态对应于宏观状态“图像具有随机值的像素”。大约有 2 个⁰⁰⁰⁰⁰⁰可能的独特的 1200x800 RGB 图像,其中许多会导致一个看起来随机的图像。这意味着有非常高的熵,因此高信息量,因此低压缩性。每个像素的颜色完全独立于之前的颜色,因此每个像素都具有最大的惊喜和信息量。

熵也适用于许多物理系统。想象一下在房间的角落里爆开一个充满难闻气体的气球。有许多微观状态对应着“气体均匀地散布在整个房间里”,而远远更少的状态对应着“气体全部集中在房间的一个角落里”。或者想象一个放在室温下的冰块。水分子以液体形式四处弹跳的宏观状态比水分子被锁在高度有序的冰块中的宏观状态要多得多。根据热力学第二定律,一个系统的总熵不可避免地随时间增加,可能性较大的事件支配可能性较小的事件。结果,气体总是扩散,发生化学反应,冰块融化。完全不同的领域——信息论、化学和物理——都利用了熵的概念。

Kolmogorov 复杂性

一位名叫安德雷·柯尔莫哥洛夫的俄罗斯数学家在他的《复杂性理论》中正式提出了关于信息压缩的想法。根据 Kolmogorov 的说法,一个文件的复杂度是能够重现该文件的最短计算机程序的长度。因此,尽管圆周率的前十亿个二进制数字看起来是随机的,并且需要十亿位来存储它们的原始形式(并且可能不能被 ZIP 算法压缩太多),但是它们可以由相对较短的计算机程序生成(远少于十亿位),只要你有足够的时间和内存。你可以直接存储产生它们的程序,而不是直接存储十亿位。

在我大学时最喜欢的一个作业中,我们被给了一堆数据文件,并且必须编写脚本在运行时重新创建这些数据文件。分数是根据你的剧本有多小来分配的。全班都在看谁能写出最少的位来表示文件;我们试图尽可能接近真实的 Kolmogorov 复杂性。

假设您有一个如下所示的文件,存储一年中每天的天气数据:

01/01/2021: sunny, high of 8 C, low of 4 C
01/02/2021: partly cloudy, high of 3 C, low of -1 C
01/03/2021: rainy, high of 6 C, low of 2 C
...
12/31/2021: snow, high of -1 C, low of -5 C

文件中有很多冗余:日期遵循可预测的顺序,相同的天气词汇重复使用,每次都给出温度的单位,等等。通过为特定文件定制脚本,您通常可以胜过一般的压缩算法,有时甚至是显著的。

Kolmogorov 复杂性也被扩展到物理定律是宇宙状态的一种压缩算法。知道了力、质量和加速度之间的关系,就意味着可以用更少的变量来描述同一个系统。一个在弹道运动下遵循抛物线轨迹的物体可以用两个点来描述,而不是它实际通过的无限个点。科学作为压缩宇宙的一种方式的想法是深刻的,马库斯·赫特在莱克斯·弗里德曼的播客[5]中对此进行了探索。

语言学、音乐等等

作为一名语言学家,我对这些概念如何应用于人类语言很感兴趣。语言中存在统计模式和内置冗余,这使得所有人类语言都是可压缩的。几乎开创了信息论领域的克劳德·香农估计,书面英语有大约 50%的冗余率。

这是你第一次写英语作文。

语言必须平衡效率和冗余。语言不应该无谓地浪费宝贵的比特和音节。然而,信息密度太大,信息变得对噪音和讹误更加敏感。如果消息中的每一位都在做更多的工作,那么偶然翻转一位将会产生更灾难性的结果。语言中的冗余允许听者甚至从被破坏的信息中恢复意义(例如在嘈杂的房间中,使用糟糕的 FaceTime 连接,或者在阅读凌乱的手写内容时),就像在数字信息中添加纠错位允许从被破坏的信号中恢复一样。有趣的是,上面的“密集英语”的例子在像希伯来语这样的语言中不起作用,因为希伯来语已经是拼写密集的了(元音不是书面的)。语言的某些特征,比如同意标记(我吃 vs .她吃 s ),起初看起来是多余的,因为它们没有告诉你任何你无法从句子中的其他单词中找出的东西。但是考虑到通信容易受到噪音和干扰,内置冗余实际上很有意义。

研究甚至表明,压缩率可以代表一首音乐听起来有多好听。压缩性太大,而且太无聊(就像全黑的图像或者一段音乐一遍又一遍的演奏着同样简单的旋律)。密度太大,听起来不和谐,缺乏令人愉悦的模式。有一个可压缩性的黄金地带——音乐包含了模式和惊喜的恰当平衡。

关于信息论还有很多可以说的,所以看看下面的资料,感谢阅读!

参考

[1] 詹姆斯·格雷克的信息。

[2]https://en.wikipedia.org/wiki/Entropy

[3]尼古拉斯·哈德森。2008.音乐美与信息压缩。https://www . researchgate . net/publication/49770962 _ Musical _ beauty _ and _ information _ compression _ Complex _ to _ the _ ear _ but _ simple _ to _ the _ mind

https://en.wikipedia.org/wiki/Kolmogorov_complexity

[5]马库斯·哈特在莱克斯·弗里德曼的播客上。https://www.youtube.com/watch?v=E1AxVXt2Gv4

6 罗杰·利维。2008.不确定输入下理性人句子理解的噪声通道模型。http://www.mit.edu/~rplevy/papers/levy-2008-emnlp.pdf

联邦学习的研究

原文:https://towardsdatascience.com/an-investigation-into-federated-learning-4e466346e515?source=collection_archive---------61-----------------------

一种不共享原始数据的分散分布式机器学习技术

什么是联合学习?

联合学习也称为协作学习或分散学习,是一种机器学习技术,通过保持训练数据分散来训练模型。

多酷啊。

那么我们为什么需要联邦学习呢?

在我们开始之前,让我们快速浏览一下如何在传统的机器学习(ML)设置中训练一个模型。在传统的 ML 设置中,训练模型之前的第一步包括下载或存储您希望在本地存储库中使用的数据,并对数据应用一些机器学习算法来预测结果。这里要注意的关键点是,您将数据集中收集或存储到一个地方,从而集中训练模型。但是由于数据隐私相关的考虑,这一过程在未来可能不会继续进行。数据,无论来自哪个领域,通常都是私有或敏感的。由于隐私相关的问题,任何组织都不可能共享这些数据。由于行业竞争、隐私安全和复杂的行政程序,即使是同一家公司不同部门之间的数据整合也面临重重阻力。

现在让我们考虑卫生保健领域的一个例子。医疗数据是高度敏感的。出于监管方面的考虑,如美国的健康保险便携性和会计法案(HIPAA)或通用数据保护和法规(GDPR ),这些数据不能共享或提供给公众。

也就是说,改革传统的机器学习技术对于解决这些日益增长的监管问题是必要的。

那么,当您无法访问任何数据时,您将如何开始培训过程呢?如果您不能收集数据并存储到您的本地存储库中,您如何训练模型呢?

每个问题都有三种解决方法:接受它,改变它,或者离开它。如果你不能接受,那就改变它。如果你不能改变它,那就离开它

谷歌在 2016 年首次推出了联邦学习。你可以在这篇文章中读到更多关于联合学习的内容。他们使用边缘设备(移动设备)中的联合学习来预测谷歌 Gboard 中的下一个关键词预测。

让我们简单地理解一下联合学习。

联合学习的主要概念是将模型发送到训练设备,而不是将数据收集或存储到一个地方来训练模型。

刘宇英在 Unsplash 上的照片

已经使用集中式机器学习设置训练的模型被发送到联合学习过程中的所有参与设备。每个设备都有自己的本地私有数据。每台设备都使用自己的设备数据进行训练,产生特定的本地更新。这些更新被发送到受信任的中央服务器,在那里服务器对所有设备更新进行加权平均。这个加权平均值成为下一轮训练的基础模型。这被重复 k 次,直到模型收敛。这样,通过分散训练数据来训练模型。

图片作者。该图显示了联合学习中的四个参与设备,每个工人都通过自己的数据接受培训,并将更新发送到服务器。服务器从这 4 台设备中获取加权平均值,并分配给所有工人,这将成为下一轮培训的基础模型。

但是,在联邦学习中有许多实际的挑战或限制。以下是其中的一些:

1.每个设备的系统要求(如内存)都不同

2.由于每个设备都必须向服务器发送模型更新,因此存在大量通信开销

3.每个设备的更新都可以逆转,以恢复原始数据

4.本地设备数据可以是异构的和非 IID 的。也就是说,设备数据可能不平衡,并且每个设备的样本数量可能不同

在我的下一篇文章中,我们将更多地讨论联合学习的类型、使用 Pytorch 的实现以及联合学习中可以采用的各种模型拓扑。这只是对联合学习的介绍。

敬请期待伙计们。在我的下一篇文章中再见。

关于我

我是 Manjari Ganapathy,拉斯维加斯内华达大学计算机科学专业的理学硕士。目前我正在 Mingon Kang 教授的指导下完成我的联邦学习硕士论文。

参考

[1].Brendan McMahan 等人,从分散数据进行深度网络的通信高效学习 (2017)

[2].彼得·凯鲁兹等人,联邦学习的进展和公开问题 (2019)

一个提高人工智能情感识别意识的在线游戏

原文:https://towardsdatascience.com/an-online-game-to-raise-awareness-on-ai-emotion-recognition-76bb2740dfa3?source=collection_archive---------34-----------------------

来源:作者截图自网站 Emojify.info

人工智能情感识别的应用概述和伦理问题

根据非语言行为线索识别某人的感受,甚至预测潜在的反应,不再是为敏感和机敏的人保留的问题。

随着情绪智能尖端技术的进步,这种能力随着机器出于各种目的识别人类情绪的能力而获得了新的维度。

复杂的面部检测算法现在已经强大到足以分析和测量现实世界中捕捉到的情绪。它们是如此强大,以至于我们正在达到一个点,一些伦理方面已经被提出。

情绪识别是如何工作的?

情绪识别基于面部表情识别,这是一种基于计算机的技术,采用算法来检测面部,对面部表情进行编码,并实时识别情绪状态。

它通过使用嵌入在笔记本电脑、手机和数字标牌系统中的计算机驱动的摄像头以及安装在计算机屏幕上的摄像头来分析图像或视频中的人脸来实现这一点。

一般来说,计算机驱动的摄像机用于面部分析分三步进行:

  1. 人脸识别:识别场景、图像或视频片段中的人脸。
  2. 面部标志的识别:从检测到的人脸中提取面部特征信息。例如,检测面部组件的形状,或者描述面部区域中的皮肤纹理。
  3. 情绪分类和面部表情:分析面部特征外观的运动和变化,并将该信息分类为表情解释类别,例如面部肌肉活动,例如微笑或皱眉;情绪类别,如快乐或愤怒;以及诸如(不)喜欢或矛盾心理的态度类别。

来源:https://github.com/gitliber/Facial_Emotion_Detector—图片由作者提供。

实际例子

前段时间,为了了解更多关于这项技术的信息,我实现了一个面部情感检测器,它能够使用带有 Keras CNN 模型和 OpenCV 的 fer2013/IMDB 数据集进行实时面部检测和情感/性别分类。

使用 IMDB 性别分类的系统对性别的准确率达到 96%,使用 fer2013 数据集进行情感分类测试的准确率达到 66%。

来源:https://github.com/gitliber/Facial_Emotion_Detector—图片由作者提供。

该系统基于一篇论文,该论文提出了由 B-IT-BOTS 机器人团队实现的用于设计实时 CNN(卷积神经网络)的通用框架,该 CNN 控制能够执行人脸检测、性别分类和情感分类的实时视觉系统。

详情请参考我的 GitHub 。

用游戏提高意识。

关于 AI 的情感识别伦理方面的讨论,有很多方法可以展开。

其中一项是允许人们在网络摄像头或智能手机上做鬼脸,通过使用情感识别的游戏来观看人工智能的运行。

最近,剑桥大学和 UCL 大学的一组研究人员创建了一个网站,旨在帮助人们了解计算机如何扫描面部表情来检测情绪,并开始讨论技术及其社会影响。

这个项目是由一群社会科学家、公民科学家和设计师创建的,他们希望开始一场关于情绪识别系统的对话,从技术背后的科学到其社会影响,以及这之间的一切。

当你访问该网站时,你可以在设备的摄像头前玩一个做鬼脸的游戏,让人工智能情感识别系统识别六种情绪:快乐,悲伤,恐惧,惊讶,厌恶和愤怒。

该项目允许人们与这些系统互动,并更好地了解它们有多强大,以及它们有多大缺陷。

如果你愿意,你也可以回答一系列可选问题来帮助研究人员,例如你以前是否使用过这项技术,你是否觉得它有用或令人担忧。

问题的可选答案将被用在一篇关于公民科学方法的学术论文中,以更好地理解情绪识别的社会含义。

情绪识别的伦理方面

一旦情感识别假定我们的面部表情完美地反映了我们的内心情感,它就不可靠。

每个曾经假笑过的人都知道,那通常不是真的。

这种倡议是一种引人入胜的方式,可以引发关于技术及其社会影响的讨论。

这个项目可能看起来是一个有趣的游戏。尽管如此,这也是一种令人兴奋的科学方法,让人们考虑这项技术的风险,考虑到它可能存在的令人担忧的歧视和监控潜力。

情感分析的应用

凭借强大的商业吸引力,企业可以使用这种技术来评估客户的总体情绪,从而确定营销策略。仅仅拥有一个社交媒体账户就能让你使用这个工具,了解人们对它的看法以及你的客户的行为。

这项技术也可以用于呼叫中心。使用人工智能,可以实时识别感觉,从而提供直接的护理。

情感分析范围广泛,可用于多种目的,包括:

  • 进行市场研究,捕捉公众表达的情感;
  • 沉浸式体验创造:根据用户传递的情绪改变虚拟现实环境的能力;
  • 用户评价;
  • 虚拟助手:可以根据用户的情绪定制语言。

在一些国家,如中国,人工智能情感识别技术已经用于许多领域,包括警察审讯和学校行为监控。

其他潜在应用包括:

  • 边境管制。
  • 求职面试中对候选人的评估。
  • 面向企业的客户洞察收集。

结论

复杂的面部检测算法现在已经强大到足以分析和测量现实世界中捕捉到的情绪。它们是如此强大,以至于我们正在达到一个点,一些伦理方面已经被提出。

因此,我们需要一种更加开放和民主的方法来决定如何使用这项技术,尤其是决定必须如何使用这项技术。

与信息安全相结合的用户体验有待加强。这不仅仅是实现机制。

越来越有必要让用户能够管理他们想要共享的数据和不想共享的数据。

参考

  • 一个展示人工智能情感风险的在线游戏。https://www . technology times . PK/2021/04/04/emojify-a-online-game-to-show-risks-of-ai-emotion-recognition/
  • 人脸分类与检测—【https://github.com/gitliber/Facial_Emotion_Detector
  • 测试人工智能情感识别技术。——【https://emojify.info/
  • 科学家创造了一个在线游戏来展示人工智能情感的风险。https://jerseyeveningpost . com/news/uk-news/2021/04/04/scientists-create-online-game-to-show-risks-of-ai-emotion-recognition/
  • 面部情感识别简介—https://algorithm ia . com/blog/introduction-to-Emotion-Recognition
  • 使用深度学习的面部情感识别:综述和见解—https://www . science direct . com/science/article/pii/s 1877050920318019
  • 人工智能的进步威胁到隐私。https://www.eurekalert.org/pub_releases/2019-01/uoc-aia010319.php
  • 用于情感和性别检测的实时卷积神经网络—https://github . com/git liber/face _ Emotion _ Detector/blob/master/report . pdf

致数据科学界的公开信

原文:https://towardsdatascience.com/an-open-letter-to-data-science-community-cc887d45a3d1?source=collection_archive---------21-----------------------

公平和偏见

人工智能伦理挑战:偏见和偏见,经济不平等和全球变暖

照片由吉安·沙汉在 Unsplash 上拍摄

在你开始阅读这篇文章之前,我希望你放下你的警惕。我们都知道人工智能的力量。在过去的 15 年里,我一直在这个领域学习和工作。所以,我显然不想在这封信中贬低艾;然而,我想简单地提倡更负责任地构建人工智能解决方案。

如果你关心经济不平等,你应该谨慎使用 GPT-3 等拥有 1750 亿个参数的巨大 ML 模型。当一个模型有那么多参数时,你需要强大的计算能力才能从中受益。这些模型不能用小数据集进行调优。因此,需要收集大量数据,以确保充分利用这些模型。现在的问题是,有多少人工智能专家能够以合理的成本获得所需的计算能力?或者说,有多少小企业有足够的资本以合理的成本进行大规模的数据收集?答案是几乎没有

这是一个永无止境的游戏,模型变得越来越大。这样做的后果是,只有大公司才有运行这些模型的计算能力,而小型创业公司将没有竞争机会。这不是我为人工智能设想的未来。我们不应该让巨型公司控制人工智能的命运。

这不是我想象的人工智能的未来。一个只有巨头公司才能进入人工智能美好世界的未来。

我记得有一段时间,创造力是人工智能发展的主要增长引擎。越有创意****的算法,模型越强大。我仍然相信创意可以在某种程度上击败大型模特的竞争。这肯定很难,但我保证这将是一个更令人兴奋的旅程。我在分析 BERT 和 Word2Vec 模型的时候证明给自己看;然而,我不确定 10 年后会发生什么。这还不是故事的结尾。

巨大的 ML 模型有大量的碳足迹。根据一些研究,自动驾驶汽车需要大约 2500 瓦才能在我们的街道上行驶。如果这项技术被部署在世界上的每辆汽车上,它将对全球变暖产生相当大的影响。如果你关心气候危机,你不应该不负责任地使用巨大的 ML 模型。站在历史正确的一边。

最后但同样重要的是,我们应该反对数据中存在的偏见。ML 模型可能固有地适应这些偏差。我们应该想办法限制它们的影响。我们知道当前的人脸识别算法对某些种族群体的效果有多差。我们知道当前的语音识别算法对于有明显口音的人来说效果有多差。由于许多不合理和不可接受的原因,我们的日常交往充满了偏见和成见。让我们防止 ML 模型从数据中继承这些偏差。

让我们推动道德人工智能的发展,在这里和那里。我们都相信美好的未来;而且,人工智能应该帮助我们更快地到达那里,而不是阻碍它。

总之,在使用巨大的 ML 模型之前,请三思。你应该负责任地使用这些模型来减少经济不平等,阻止全球变暖,帮助人们过上更幸福的生活。荣誉😊

感谢阅读!

如果你喜欢这个帖子,想支持我…

  • 跟我上
  • 亚马逊 上查看我的书!
  • 成为 中的一员
  • 连接上Linkedin**
  • 关注我的 推特

**https://pedram-ataee.medium.com/membership **

预测长期无家可归者的开源可解释机器学习方法

原文:https://towardsdatascience.com/an-open-source-interpretable-machine-learning-approach-to-prediction-of-chronic-homelessness-8215707aa572?source=collection_archive---------16-----------------------

加拿大伦敦市中心的景色。图片由妮可·奥斯本拍摄。

变更数据、行业备注

获得对未来 6 个月内面临长期无家可归风险的客户的可解释预测

Blake VanBerlo 是一名数据科学家,支持伦敦市的市政人工智能应用实验室。该实验室由信息技术服务部管理。布莱克关于我们开源人工智能项目的帖子。有关其他主要城市利益相关方的联系方式,请参见下面的“联系方式”部分。

摘要

加拿大伦敦市政府最近将机器学习应用于慢性无家可归问题的预测(见论文【1】及随附的源代码)。一个模型预测公民在未来 6 个月内是否处于长期无家可归的高风险中,并为每个预测获得解释。本文讨论了项目的路径,从研究到部署。

介绍

有人建议对慢性无家可归者进行预测性筛查,以此来标记那些可能从预防慢性无家可归的干预措施中受益的个人[2]。此外,研究表明,住房补贴、转移努力和基于社区的服务等预防性策略已被证明能有效降低未来长期无家可归的发生率[2]。人们可以想象,这些有限的支助资源中的一部分将优先用于那些面临长期无家可归最大风险的人。这就引出了一个问题:我们能可靠地识别出最有可能长期无家可归的人吗?

加拿大伦敦市政府致力于开发一个预测模型,在给定人口统计和服务使用信息的情况下,该模型可以准确估计个人在未来 6 个月内成为长期无家可归者的风险。伦敦市政人工智能应用实验室应用机器学习方法来研究这种模型。参与该项目的利益相关者包括伦敦无家可归者预防部门、城市信息技术服务部门以及来自伦敦各种无家可归者服务机构的各种利益相关者。

在本文中,我们将讨论(1)问题是如何发现的,(2)使用的数据,(3)寻找符合城市模型透明和负责任人工智能原则的有效模型的过程,(4)模型如何过渡到部署以供个案工作者使用,(5)未来工作的途径,以及(6)市政当局如何自己复制这项工作。

伦敦市中心的维多利亚公园。图片由妮可·奥斯本拍摄。

挑战

与利益攸关方进行了讨论,以确定该系统的具体目标。这些会谈中产生的问题陈述指导了后续的设计和部署需求。粗略地说,利益相关者想要预测一个客户(定义为获得无家可归者服务的个人)在未来是否有长期无家可归的风险。如果存在可靠的此类估计,个案工作者可以为该客户分配更多的无家可归预防资源(例如,住房补贴、负担得起的住房、个案管理)。

形式上的挑战是:给定一个人的人口统计和无家可归者服务利用记录,预测他们是否会在 6 个月后处于长期无家可归的状态。

如果在过去的一年中,一个客户至少有 180 天在无家可归者收容所度过了至少 15 分钟,那么他就被认为是长期无家可归者。

这个长期无家可归的定义改编自加拿大政府的无家可归战略指令[3]。然后基于该定义制定了二元预测任务。积极类的客户在预测日期后 6 个月符合慢性无家可归的定义,而消极类的客户则不符合。

分类任务有多种量化分类器性能的指标。我们检查的指标包括准确度、精确度、召回率、F1 分数和受试者操作曲线下面积(AUC)。利益相关者坚持认为召回是最重要的衡量标准。在我们的问题中, recall 指的是模型正确识别的实际上成为长期无家可归者的客户比例。另一方面,Precision 是模型确定为长期无家可归者的客户中实际上成为长期无家可归者的比例。理想情况下,分类器将最大限度地提高精确度和召回率;然而,这两者之间有一个权衡。给定选项,利益相关者更喜欢模型实现高召回,因为高召回最小化了假阴性预测的机会。错误地不对最终成为长期无家可归者的客户实施预防策略比错误地将预防资源分配给可能不需要它们的人要付出更高的代价(社会和经济代价)。值得注意的是,这种关系不能走极端,这意味着最小化假阴性是目标,然而过度服务假阳性的成本不能太高。这导致无家可归者预防部门使用修改的 F1 分数(考虑召回率和精确度)来确定生产的最佳模型性能。

数据和可行性

HIFIS 数据库

该项目的主要促成因素之一是现有数据库的可用性,该数据库包含有关全市无家可归者服务客户的人口统计和服务使用信息。伦敦是加拿大众多使用无家可归者个人和家庭信息系统(HIFIS)应用程序来管理向获得无家可归者服务的客户提供服务的城市之一。事实上,信息技术服务司的 HIFIS 数据库管理员最初想知道储存在 HIFIS 数据库中的信息是否可以用来预测长期无家可归的情况。此外,利用这些数据的可行性首先依赖于强大的数据治理基础。五年前,伦敦的 20 多个无家可归者服务组织通过强大的数据治理、隐私、同意和信息安全实践,将他们的数据整合到一个数据库架构下。这个丰富且维护良好的数据源是这个项目成功背后的核心促成因素。

在与伦敦的无家可归者服务机构互动时,如果客户同意收集,将为新客户收集人口统计和其他背景信息。向客户提供各种服务,如住宿、食物银行服务、个案管理、住房补贴、住房支助和个人物品储存。每当客户端访问这些服务时,都会在数据库中创建记录来捕获交互。

隐私和信息安全

在这一点上,谈论隐私、信息安全和负责任的人工智能很重要。该模型的基础数据包括来自伦敦最脆弱人群之一的敏感的个人身份信息。因此,我们竭尽全力保护数据和系统的隐私和信息安全。一些措施的例子如下:

  • 明确同意:数据收集程序和基础数据库是明确同意驱动的数据库,这意味着在数据收集之前,任何个人都给予明确同意。
  • 数据治理:所有使用 HIFIS 的组织都签署了数据共享协议,以便能够以非身份格式将这些信息用于这些目的。
  • 去除身份:即使在项目的最早原型和设计阶段提取的所有数据都会被去除身份,以保护系统中的个人信息。
  • 隐私设计:模型给出的风险预测与客户 ID 相关联,然后再映射回一个名字。这种重新识别过程只发生在 HIFIS 应用程序/数据库中,只允许那些已经访问过该识别数据的人查看命名的预测。这种一致的访问权限管理对于保护个人隐私和信息安全至关重要。
  • 安全性:利用企业网络和应用安全的最佳实践来保护数据库以及生产中的机器学习管道。
  • 系统隔离:机器学习管道只能访问去识别数据,这意味着任何正在进行的维护、模型的重新训练和模型性能的监控都不能提供对识别数据的任何访问。

负责任的 AI

上面提到的隐私和信息安全措施对于像这样的机器学习系统的运行至关重要。然而,在部署和维护负责任的人工智能系统时,还有其他考虑因素。通过与我们的隐私官和法律服务团队合作,我们决定将加拿大国库委员会秘书处关于自动决策的指令 [4】应用于该系统,尽管该系统是市政府实施的。该系统通过算法影响评估(AIA)工具运行,以确定系统的影响水平,并确定纳入系统的风险缓解措施。分析的结果是,该系统收到了 AIA 的 2 级调查结果,因此我们实施了以下风险缓解措施:

  • 同行评审:我们让第三方数据科学供应商评审模型、部署架构和安全架构,以确保其符合或超过最佳实践。此外,我们向 Elsevier Engineering Applications of Artificial Intelligence 提交了一篇学术论文供同行评审(发表于 2021 年 4 月),预印本可供评审( arXiv 预印本链接)。
  • 通知:关于该系统存在的通知和关于运行中的模型的详细文档可以在我们的公共代码库( GitHub 链接)上开源获得。该模型目前处于实施规划阶段,浅显易懂的语言解释将成为培训和持续实施的一部分。
  • 人在回路中决策:尽管 ADS 指令中的 2 级系统不需要人在回路中,但考虑到本项目的敏感性,人们决定这只能是决策辅助/协助,人将始终处于回路中。
  • 解释:我们利用局部可解释的模型不可知解释算法(LIME)来为机器学习系统生成的每个预测生成人类可解释的解释(下文对此有更多介绍)。这使得用户能够理解系统为什么做出这样的决定,建立对系统的信任,并监控系统的非预期偏差。
  • 测试:在生产之前,通过使用来自 LIME 算法的解释,我们能够标记出系统中是否有意外偏差,并使我们能够移除或修复任何不公平地影响结果或导致系统预测有问题的功能。
  • 监控:我们的支持模型有一个熟练的数据科学家来监控生产系统的性能指标。预测是每天生成的(与按需生成相反)。除此之外,在发布之前,我们进行了分析,发现只有当模型的训练数据超过大约 1.5 年时,性能指标才开始受到影响(即模型衰退)。因此,我们在支持模型中构建了机器学习模型,在将新训练的模型投入生产之前,该模型将接受年度再培训,并由业务部门签署绩效指标。
  • 培训:通过预印文章,以及上面链接的 GitHub repo 中的模型文档,我们能够提供关于模型功能的全面文档。实践标准和业务级别的未来实现也将被记录,以便根据模型做出明智的决策。
  • 审计:我们在系统中建立了一个记录,记录了生产系统曾经做出的所有历史预测,这些预测映射到系统的哪个版本做出了这些预测,这样就可以对所有决策进行审计。
  • 同意:我们在系统中实现了一个功能,以确保如果客户撤回对其数据进行处理的同意,他们的信息将不再被机器学习系统处理。如果在数据库级别撤销了明确的同意,这将自动发生,并且如果需要的话,可以在逐个客户端的基础上人工完成,也可以仅针对系统的机器学习方面来完成。这不是 AIA 的要求,而是我们在分析相关立法时建议的。例如,在欧洲联盟的 GDPRs 中,个人有权通过自动决策系统限制处理。
  • 利益相关者的参与和监督:在整个项目中,不仅与伦敦金融城的无家可归者预防部门,还与更广泛的利益相关者机构伦敦无家可归者预防网络(LHPN)进行了多次对话,设置了许多检查点和审批关口。LHPN 是一个包括所有伦敦收容所负责人和有生活经验的个人的机构,负责监督项目并继续指导实施。上述大部分措施既是自上而下负责任的 AI 立法审查所要求的,也是自下而上的利益主体参与 LHPN 所要求的,这让我们相信我们正在采取正确的方法。

时间序列公式

到目前为止,我们已经决定预测模型的功能可以包括人口统计和总服务使用情况(例如,使用服务的总天数或次数)。因此,在项目的第一阶段,我们考虑了为客户创建预测的模型,给出了他们的人口统计属性和当前服务使用总量。此后,我们将这些特征统称为静态特征。静态特征可以进一步分解为数字特征(如)。年龄】、单值分类变量(如公民身份)、多值分类特征(如健康问题)。

由于服务使用记录与一个日期相关联,我们假设,以一种捕获服务使用的时间分布密度的方式来重构模型输入可能是有益的。其原因是这样一个事实,即一个在过去几年中可能大量使用服务,但目前不是长期无家可归且住房已经稳定的客户,对于该模型来说,其静态特征与过去 6 个月内在收容所停留的人相同;这更预示着高风险个体。因此,我们决定在不同的日期为每个客户创建多个记录。这些示例将包括前面提到的静态特征和最近几个月每种服务类型的总服务使用量。因此,我们为特定的 30 天时间步长内的总服务使用量创建了特征,包括到示例日期为止的最后 6 个时间步长(即最后 6 个月)(针对每种服务类型)。即,给出本月、上个月、2 个月前等与每个服务的交互次数的一组特征。我们将这些时序服务使用特征称为动态特征。

单个时间序列示例中的特征分解。图片作者。

作为研究的一部分,我们比较了在仅包含静态特征(即每个客户 1 条记录)的数据集上训练的模型和在静态和动态特征(即每个客户不同日期的多条记录)的数据集上训练的模型。

模型搜索

可解释标准

自动算法工具在决策支持中的使用越来越多,这引起了人们对模型预测的不透明性和偏差传播可能性的关注。如上所述,在利益相关者参与时,部署模型所做的任何预测都要得到利益相关者满意的解释,这被认为是一项关键任务要求。

候选模型

我们在研究中考虑了各种潜在的建模技术。候选建模技术如下:

  • 逻辑回归
  • 随机森林
  • XGBoost
  • 多层感知器
  • 混合递归神经网络+多层感知器

所有上述模型类型都使用纯静态数据集和包含静态和动态特征的数据集进行训练,只有混合模型除外,我们将其缩写为“HIFIS-RNN-MLP”。论文中列出了每个模型使用的特定超参数,以及 HIFIS-RNN-MLP 的精确示意图[1]。

为了比较这些模型,根据数据集的类型进行了交叉验证。对于纯静态数据集,应用传统的 k 重交叉验证,其中 k=10 。对于时间序列数据集,应用了嵌套交叉验证方法(使用 10 倍)。性能指标记录为所有折叠的平均值。下图描述了这种时间序列交叉验证策略。

嵌套交叉验证策略中 fold k 的训练、验证和测试集。验证集和测试集包含可用于 fold k. Image by author 的最新记录。

在我们的实验中测试的模型架构不是计算密集型的,只需要几分钟的训练。

表演

下表总结了每个候选模型的性能。

候选模型的所有交叉验证的平均测试集性能的比较。使用分类阈值 0.5 计算精确度、召回率和 F1 值。图片作者。

上表中有很多内容。乍一看,似乎没有一种型号是明显的赢家。然而,显而易见的是,在时间序列数据集(包含静态和动态特征)上训练的模型往往比仅在静态特征上训练的模型表现更好。这将搜索范围缩小到在时间序列数据集上训练的模型。

回顾无家可归预防的主要目标是最大限度地回忆。虽然多层感知器(MLP)拥有最高的召回率(96%),但它的精度是在时间序列数据集上训练的模型中最低的。无家可归者预防组织不希望以牺牲精确性为代价来选择一个召回率稍高的模型。在召回率次高的两个模型(HIFIS-RNN-MLP 和逻辑回归)中,HIFIS-RNN-MLP 因其更高的精确度最终被选中。其他城市可能会有不同的选择。

请注意,逻辑回归是列表中唯一内在可解释的模型,其余的都是“黑盒”模型。如果不是 LIME 提供了令人满意的解释,由于前面概述的透明度标准,可能会选择逻辑回归。

可解释性

为了满足透明性标准,应用了一种称为局部可解释模型不可知解释的可解释性算法【5】。LIME 是模型不可知的,意味着它可以被应用于产生任何类型的黑盒模型的解释。

LIME 确定了对模型预测贡献最大的示例特征。对于每个特征值,LIME 输出一个权重列表。正权重表示该特征有助于正面预测(即长期无家可归),负权重表示该特征有助于负面预测(即不是长期无家可归)。权重的大小意味着指示贡献有多强。下图显示了数据集中匿名示例的时间预测权重。

一个简单的解释。绿色条和红色条分别表示某个特征有助于正面预测或负面预测。在这个例子中,客户在过去 30 天的时间里至少在避难所呆了 1 天的事实为长期无家可归的积极预测提供了强有力的支持。

上面的例子摘自论文,在论文中有更详细的描述[1]。当个案工作者为客户查看模型预测时,他们也会收到类似上图的解释。利益相关者认为 LIME 的解释对于理解为什么模型对特定客户做出预测是有价值的。

LIME 的另一个好处是,它提供了一种生成模型功能的全局(和近似)概要的方法。使用 LIME paper [5]中概述的子模型选择方法,我们为整个模型生成了一个全局解释,如下所示。

总结整个模型功能的简要说明。显示 30 个最有贡献的特征值。图片作者。

在全局解释中,我们首先注意到,最能预测 6 个月内长期无家可归者的特征是,在最近 30 天的时间步长内至少有 1 天住在收容所。第二个影响最大的特性是在第二个最近的 30 天时间步长中对客户端进行的 SPDAT 评估的数量。SPDAT(即服务优先决策辅助工具)是一种常用的无家可归者筛查工具,在全球多个司法辖区使用[6]。其他一些有助于预测长期无家可归者的有趣特征包括高龄、5 年前去过食物银行,以及从未接受过住房补贴。相反,一些有趣的特征与长期无家可归的预测相悖,包括年轻和在最近的时间步骤中没有接受 SPDAT。利益相关者认为这一数字非常有助于考虑哪些因素导致了伦敦无家可归人口的长期无家可归。特别有趣的是,大多数最有影响力的特性是时间序列服务使用特性。

顺便说一句,计算时间比获得预测时间长得多。原因是,LIME 在生成解释时使用该模型对虚构的相近示例进行了多次预测。更多信息请参考 LIME 论文。

加拿大伦敦市中心的考文特花园市场。图片由妮可·奥斯本拍摄。

部署和支持

一旦 HIFIS-RNN-MLP 被确定为首选模型,其性能指标得到无家可归者预防组织的批准,人们就开始努力部署该模型,供伦敦收容所的个案工作者实时使用。该模型在所有可用数据上被再次训练,并被保存用于部署。

云架构

微软 Azure 被选为云计算服务,以促进模型部署。部署功能被分成两个主要的工作流:模型再训练和模型预测(即“推理”)。 Azure ML 提供了开发机器学习“管道”来自动化这一工作流程的能力。每个管道都由一系列顺序执行的明确定义的步骤组成。管道产生的原始数据、预处理数据和工件存储在 Azure Blob 存储器中。每天都会自动运行一个 SQL 查询来从 HIFIS 数据库中检索所有客户端数据,该数据库被展平并作为 CSV 文件保存在 Blob 存储中。

训练管道训练新模型并产生全局解释(通过石灰子模型选择)。它将每年举办一次。它由以下步骤组成:

  1. 预处理原始数据集中的所有数据,创建由静态和动态要素组成的时间序列数据集。
  2. 在测试集上训练模型并保存性能指标。
  3. 运行石灰子模块选择以获得全局解释。
  4. 将此次运行中生成的所有工件保存到一个文件夹中。

推理管道为当前日期的数据集中所有同意的客户端生成预测。它每天运行。其步骤是:

  1. 预处理原始数据集中最近的记录,在当前日期为每个客户生成一个时间序列示例。
  2. 获得每个例子的预测和相应的时间解释。

PowerBI 仪表板会消耗最新的预测,使它们可以作为报告提供给个案工作者。为了确保每天为所有客户端做出预测,一个 Azure Logic 应用在每天的同一时间向 REST 端点发出一个经过身份验证的 HTTP POST 请求,该请求启动推理管道的执行。

描述模型部署云架构的示意图。图片作者。

支持和维护

利用一家精通数据科学和 Azure 云服务的供应商开发了一个支持模型,为管道提供支持和维护。他们的职责包括:

  • 确保推理管道每天无误运行
  • 调查和解决管道问题
  • 在绩效指标和全球解释获得批准后,适当运行培训管道并替换当前模型

后续步骤

已经确定了未来工作的多个可能方向。首先,有必要最终量化我们模型的影响。到目前为止,有一个收容所已经是该系统的早期采用者。当决定在预防性资源分配中优先考虑哪些客户时,个案工作者正在考虑模型的预测和解释。可以通过检查访问该庇护所的客户的结果数据来验证该模型的效用。如果这样一项研究表明,良好的客户结果更有可能在引入模型后,它将作为证明模型使用的部分证据。

如果这种方法可以应用于其他城市的数据,就有可能对其进行外部验证。任何使用 HIFIS 数据库的市政当局都是这种研究的理想候选人,因为他们可以利用我们的开源代码更容易地训练他们自己的模型。来自另一个城市的数据集可以像在伦敦一样进行预处理,然后进行交叉验证。可比的性能指标将增加对这种方法的信心。请注意,伦敦的训练模型不能直接应用于为来自其他城市的客户做出预测,因为数据集中存在特定于地区的特征(例如客户住过的避难所、服务提供的类型、行为标志),并且出于信息安全原因,我们的开源存储库不包括训练模型参数。除此之外,伦敦的人口统计数据肯定不同于其他城市,因此该模型可能会偏向伦敦人口。

我的城市如何使用这个?

如果你有兴趣在自己的城市尝试这种预测长期无家可归者的方法,这里有一些关于如何开始的建议。

为了效仿伦敦金融城采取的方法,您所在的城市需要拥有一定的员工和技术资源,包括:

  • IT 经理:管理和支持参与项目的所有员工;最好熟悉数据科学基础知识
  • 数据科学家:领导研发工作;应具备数据科学专业知识和经验;如果设想进行云部署,最好有云服务经验
  • 数据库经理:促进数据库支持,并告知数据科学团队数据库中包含的潜在功能;并协助处理数据争论
  • 无家可归者服务经理:在技术团队和最终将使用模型预测的工作人员之间牵线搭桥;对城市中无家可归者的情况和需要参与的利益相关者有深刻的理解

如果您所在的城市是 HIFIS 应用程序的用户,您可能会受益于伦敦金融城为此项目发布的代码,该代码可通过公共 GitHub 资源库获得。除了用于训练、预测和可解释性的代码之外,存储库还包括 HIFIS SQL 查询和将原始查询结果转换为预处理数据集的代码。如果您的城市使用不同的无家可归者信息管理系统,您仍然可以遵循我们论文中概述的方法,但是您必须开发自己的预处理功能。

请务必让您的数据科学团队阅读我们的论文 [1],因为它对我们的方法进行了比本文更深入的研究。

接触

马特·罗斯
伦敦市人工智能
信息技术服务
经理

Jonathan Rivard
无家可归预防经理
住房、社会服务& Dearness 之家
伦敦金融城
jrivard@london.ca

Blake van berloblake@vanberloconsulting.com
数据科学家
伦敦金融城市政人工智能应用实验室

加拿大伦敦的标志。图片由妮可·奥斯本拍摄。

参考

[1] B. VanBerlo,M. A. S. Ross,J. Rivard 和 R. Booker,预测长期无家可归现象的可解释机器学习方法 (2020 年),arXiv

[2] M. Shinn 和 R. Cohen,无家可归预防:文献综述 (2019),无家可归问题循证解决方案中心。

【3】“到达家:加拿大无家可归战略指令 (2020),加拿大政府。

[4] 自动化决策指令 (2019),加拿大政府。

[5] M. T .里贝罗,s .辛格和 C. Guestrin,“我为什么要相信你?”解释任何分类器的预测 (2016),arXiv

[6](2021),伴侣结束无家可归

开放式人工智能模型学习总结书籍

原文:https://towardsdatascience.com/an-openai-model-learns-to-summarize-books-91b2ec6480f1?source=collection_archive---------16-----------------------

这些机器学习模型有什么危害?

照片由张成浩在 Unsplash 上拍摄

M 任何大型科技公司都在竞相开发通用人工智能(AI)——让他们的模型接近并解决我们给他们的任何问题,无论多么耗时或具有挑战性。这被称为对准问题。

为了测试和扩展一个潜在的解决方案,OpenAI 团队最近训练了一个人工智能模型来递归地总结书籍。通过 GPT-3 使用自然语言处理可以让你得到任何长度的书的要点。

根据 OpenAI 团队的说法,该模型“在 5%的时间里阅读了该书的人获得了 6/7 的评分(类似于普通人写的摘要),在 15%的时间里获得了 5/7 的评分。”

使用递归任务分解,每个长文本被分解成越来越小的片段。然后对这些小片段或章节进行总结,然后这些章节总结本身也可以进行总结。然后,人们可以对这些评论提供反馈,以进一步改进模型。

人工智能驱动的摘要是许多未来应用的一个小测试案例,在这些应用中,有监督的机器学习可以扩展到许多困难的任务。

但显然存在一些限制,因为这些模型只能在 5%的时间内达到人类水平的精度。分解方法也可能会遗漏一本书各部分之间的重要联系。而源代码和训练集将不会公开(讽刺的是,鉴于开放的 AI 名称)。

有什么坏处呢

据 VentureBeat 报道,谷歌、微软和脸书都在开发类似的工具向用户提供文本摘要。虽然一些个人使用它来与人工智能合作和共同撰写小说,但它也可能导致更多的新闻聚合。谷歌、脸书和一些其他公司现在是互联网其余部分的守门人和仲裁者。

新闻与知识的贬值

为了获得广告收入,新闻公司需要根据算法调整他们的文章,确保人们会点击。为了节省成本,公司已经在使用自动化系统来收集和组织内容,或者建议头条新闻。这是记者富兰克林·福尔在他的著作《没有头脑的世界:大科技的生存威胁》中的部分论点

“杂志和报纸过去常常认为自己是某种连贯的东西——一个问题、一个版本、一个机构。不是作为每天在脸书、推特和谷歌上被贩卖的几十个独立作品的出版商。”

即使是有声望的媒体也需要生成可点击的故事来生存,并在社交媒体上获得吸引力。新闻正在向数字模式转变,年轻人更有可能通过谷歌或社交媒体获得在线新闻。在最近的一项调查中,42%的 18-29 岁的美国人回答说他们最常从社交媒体上获得新闻。

这些人工智能算法有可能成为总结一天中大量新闻的首选方式,这种风险是合理的。毕竟,这些模型可以被训练成包括一个可点击的标题和搜索引擎优化关键词。虽然这也可能为记者腾出时间从事更激动人心的项目,但这些项目需要更直接的监督和调查。

毕竟,许多潜在的自然语言处理模型是有偏见的,大规模实施这些总结算法可能会有意想不到的伤害。还有一些人担心,新闻采集过程的自动化可能会进一步损害媒体和新闻业的价值。

独家授权强大的工具

还有一个问题是微软拥有 GPT-3 的独家许可,垄断了本可以是开源工具的东西。当一家大公司实现这种垄断时,其他行业也开始依赖它。

以亚马逊为例,它推出了统一价格为 9.99 美元的电子书。然而,阿歇特图书集团进入了一场合同纠纷,因为他们不想随意降低他们所有电子书的成本。作为回应,亚马逊阻止顾客预购任何阿歇特书,损失了大量利润。

亚马逊可以利用这种不可思议的力量,因为他们已经有效地压制了所有的竞争,让许多出版商依赖他们来销售他们的产品。微软将能够通过其独家许可和它认为合适的算法使用来发挥类似的力量。

GPT-3 的问题

许多研究人员对像 GTP 3 这样的自然语言处理算法提出了合理的批评,指出它们倾向于种族主义和性别歧视。任何通用的人工智能模型,即使是那些用于总结书籍和信息的模型,在投入使用之前都需要仔细审核。

“我担心人工智能社区的群体思维、偏狭和傲慢,”前谷歌研究员蒂姆尼特·格布鲁博士写道。

学习从一套精选的书中总结文章是一个小的、有针对性的目标。但是一次又一次,将类似的语言处理模型运用到互联网上被证明是有问题的。不仅 GPT-3 倾向于种族主义和性别歧视,研究人员还发现这些模特随着年龄的增长变得越来越毒。

书籍、文件和其他任何输入 GPT 3 号的东西都不会被中性编码。许多负责评估算法准确性的人也会加入他们自己的错误和偏见。虽然许多科技公司都有部门来处理这个问题,但它们并不完美。

Timnit Gebru 博士为谷歌工作,研究人工智能的伦理及其偏见。她的工作重点是大型语言模型,包括 GPT-3 和谷歌自己的算法。然而,一群高管希望她在论文通过内部审查程序并提交给会议后收回论文。

在谷歌高管认为该研究不可接受,称其过于黯淡后,她被毫不客气地解雇了。我们如何相信公司会违背自己的财务利益,对他们的技术进行限制和昂贵的修复?我们可以看到,脸书和推特上仍然充斥着反疫苗言论和错误信息。

仅仅因为我们可以用人工智能做一些事情,并不意味着我们不应该事先考虑潜在的后果。在模型被实现并用于我们的日常生活之前,所有这些都要容易得多。向一家公司独家提供这项技术开创了一个有害的先例。

正如我们一次又一次看到的那样,大型科技公司在道德监督方面并不擅长,尤其是如果这损害了它们的财务利益。虽然这项技术本身令人难以置信,但我担心这些算法可能会继续走目前有问题的道路。

嗨!我曾经是一名研究生和记者,发表了多份科学论文https://scholar.google.ca/citations?user=CAQC6BEAAAAJ&hl=en研究神经科学和微生物组。如果你想在 Medium 上阅读更多的故事,你可以在这里用* 会员身份订阅 。你可以找到我关于媒介、大规模科学、未来主义和耐心的作品。如果你对我的写作感兴趣,你可以在这里阅读更多的http://linktr.ee/simonspichak或者在我的* 子专栏 上注册,获得我的故事的双周刊综述。**

Python 中组合回归估计量的一种新颖方法

原文:https://towardsdatascience.com/an-original-method-to-combine-regression-estimators-in-python-b9247141263?source=collection_archive---------33-----------------------

COBRA:一种非线性组合回归策略

来自 Pixabay 的 Clker-Free-Vector-Images 的图像。

现在数据科学家有很多精确的机器学习算法。但是,选择最佳模型是一项复杂的任务,集成学习已经在实践中证明了它的有效性。在以前的帖子里:“如何选择最好的模特?"和如何处理重叠规则?“我已经提出了专家的聚合理论。一种应该更多地用于集成学习而不是简单平均的理论。在这里,我想把重点放在 COBRA 方法上,在[1]中提出。这种方法对于估计量的组合有一种非常不同的和新颖的方法。为了简单起见,我不加区分地使用术语估计者、预测模型和专家。事实上,在回归设置中,回归函数的估计量可以用作预测模型,或者它可以用作对每个新观察值进行预测的专家。

首先,我回顾了专家聚集理论的主要框架。我们有一组专家,他们在每一次 t 给我们一个目标 yₜ.值的预测这个想法是聚集 k 位专家的预测来产生一个聚集预测ŷₜ.

COBRA (组合回归备选)。

用手解释。

通常,在专家聚集理论中,我们使用专家预测的凸组合来做出 ŷ.但是眼镜蛇却有着截然不同的做法。它基于与k-最近邻算法相似的思想。每次 t 我们都有一个新的观测值 xₜ ,我们计算 K 专家预测{p₁(xₜ】**p₂(xₜ】,…pₖ(xₜ)}。然后,想法是平均实现 y未使用来生成专家,这些专家在 {p₁(xₜ)p₂(xₜ) ,…, pₖ(xₜ)} 的相同邻域(在欧几里德意义上)具有预测。在这些邻域中搜索实现的步骤被称为共识步骤。下面的例子将用来说明这个概念。

两个预测因子的 COBRA 聚合。图片来自作者。

在这个例子中,我们有一个横坐标表示的特征 x ∈ Ry 的实现标记为黑色圆圈。我们有两个专家:第一个专家给出红色预测,第二个给出绿色预测。对于新的观测值 x = 11 ,我们有预测值 p ₜp ₜ 。对于每个预测,形成一个邻域,用彩色虚线表示。然后,对邻域中所有预测的所有实现(标记为蓝色圆圈)进行平均,以计算 ŷₜ (蓝色菱形)。

数学解释。

形式上,COBRA 估计量如下。设 Dₙ 为随机变量对(x,y)的 n 个独立同分布观测值的一个样本。样本分为两个独立的样本, DₗD ₘ.然后, Dₗ 用于生成一组专家 {p ₁, p ₂、…pₖ}D ₘ用于计算 ŷₜt41】的组合预测值,用于一次新的观测 xₜ 。我们有以下公式

其中随机重量 Wᵢ 采取的形式

ϵₘ 是平滑参数。ϵₘ越大,这个过程就越宽容。反之,如果 ϵₘ 太小,许多专家就被抛弃。因此,其校准是至关重要的一步。为了克服这一步,作者在[1]的第三部分提出了一种数据相关校准。

这些文字表达式表明,COBRA 与其他常用汇总方法的主要区别之一是,COBRA 相对于专家 {p ₁、 p ₂、…、 pₖ}.来说是一种非线性方法否则,从理论的角度来看,COBRA 也满足一个 oracle 界,该界表明,集合预测器的累积损失以专家组的最小累积损失为上界,直到一个向零衰减的残差项。

Pycobra 图书馆

Pycobra 是在[2]中引入的 Python 开源库。这个库不仅仅是 COBRA 聚合的一个实现。即便如此,用一种叫做 Python 的语言开发一种叫做 COBRA 的算法这一简单事实已经足够了。该库还包括[3]中详述的 EWA 算法(指数加权聚合),以及受[4]启发的用于分类设置的 COBRA 版本 ClassifierCobra 。这个包还包括一些可视化工具来衡量专家的表现。此外,一类诊断允许比较组成专家的不同组合和数据分割,以及其他基本参数。它允许更好的参数分析。最后,这个库可以在 GitHub 这里找到。

结论

COBRA 是一种新颖的非线性集成学习方法,具有理论保证。第一篇论文的主要作者仍在致力于开发一个更好的版本,正如最近介绍内核版本的论文所示[5]。此外,该算法在开源 Python 库中可用,因此没有理由不在您的下一个数据科学项目或 Kaggle 挑战赛中尝试一下。

关于我们

Advestis 是一家欧洲合同研究组织(CRO ),对统计学和可解释的机器学习技术有着深刻的理解和实践。Advestis 的专长包括复杂系统的建模和时间现象的预测分析。

领英:https://www.linkedin.com/company/advestis/

参考

[1] G.Biau,A.Fischer,B.Guedj & J.D.Malley COBRA:一种组合回归策略。多元分析杂志146(2016):18–28。

[2] B.Guedj 和 B.Srinivasa Desikan Pycobra:用于集成学习和可视化的 python 工具箱。机器学习研究杂志18.190(2018):1–5。

[3] A. S.Dalalyan 和 A.B.Tsybakov 通过指数加权和夏普甲骨文不等式进行聚合。计算学习理论国际会议(2007):97–111。

[4] M.Mojirsheibani 通过离散化组合分类器。美国统计协会杂志 94。446 (1999 年):600–609。

[5] B.Guedj 和 B . s . desikan .Python 中基于内核的集成学习。信息 11,2 号(2020): 63。

你应该选择 H2O 无人驾驶人工智能作为你的建模方案吗?

原文:https://towardsdatascience.com/an-overview-for-h2o-driverless-ai-ee1a4502f7e7?source=collection_archive---------29-----------------------

对 DAI 主要功能的全面概述,以及我对此 AutoML 工具的评论和建议

阿瑟尼·托古列夫在 Unsplash 上的照片

自动机器学习(AutoML)已经成为当今数据科学领域越来越热门的话题。许多人会对“自动构建模型”的概念着迷,在这种情况下,人们可以简单地将数据输入某个 AutoML 工具包,然后在几分钟内准备好 ML 模型进行部署。—但事实是这样吗?带着这个问题,我开始研究市场上可用的 AutoML 解决方案。

AutoML 领域有相当多的参与者,包括 Google 和 IBM 等大牌公司,以及各种正在提供其独特的 Auto ML 解决方案的初创公司。

在所有参与者中, H2O.ai 和 DataRobot 是其中最受欢迎的,因为它们的解决方案非常成熟,并且能够灵活地与客户现有的数据生态系统集成。

在这篇文章中,我对来自 H2O.ai 的 AutoML 解决方案进行了初步研究,名为无人驾驶 ai(戴),我很乐意分享我在这一过程中的一些学习。

戴的主要特征

H2O 戴提供了几个给用户带来好处的关键特性。

1。用户友好的图形用户界面

H2O 戴有一个非常用户友好的图形用户界面与基本和专家设置,使其既适用于一般的商业用户和有经验的数据科学家。

2。各种特征转换器和 ML 算法支持

H2O 戴支持各种特征转换器和 ML 算法。最重要的是,特征选择和模型超参数调整过程都是在流水线中自动完成的。

3。MLI(机器学习可解释性)功能

随着对可解释人工智能需求的增加,H2O 提供的 MLI 函数在某些用例中可能会有所帮助。H2O 戴提供了几个选项来增加复杂模型的透明度和问责制,包括留一个协变量(LOCO)局部特征重要性,部分依赖图,决策树代理模型等。关于 MLI 的更多细节,你可以参考本文档。

4。自定义配方支持

没有一个工具可以涵盖所有潜在的用例,因此定制的灵活性很重要。启用自定义配方功能后,用户可以自由地将自定义算法或计分器代码脚本上传到 H2O 戴,用于模型训练。

5。自动文档

对于严格监管环境下的模型应用而言,这是一个理想的特性,通常必须详细记录特性选择、参数调整步骤。有了 Auto-doc 功能,一些信息可以被自动捕获,从而为以后的文档工作节省了大量时间。

戴的特色和优点(图片由作者提供)

戴造型工作流程

H2O 戴的一般工作流程类似于常规的模型建立过程。下图显示了整体工作流程:

戴造型工作流程(图片由作者提供)

1。将数据导入 H2O :

首先,用户需要将数据导入到戴。数据导入实际上有很多选择,包括像亚马逊 S3 这样的云数据源,MySQL 和 MariaDB 这样的关系数据库连接,以及像 HDFS 这样的分布式文件系统。

另一方面,在将数据导入 H2O 之前,一定程度的特征工程工作可能仍然是必要的。虽然在进入建模步骤之前,戴会应用一些高级数据清理操作,但是做一些健全性检查仍然是有价值的。例如,您可能希望基于业务理解删除某些特性,或者您希望在将数据输入到 DAI 之前自己进行上采样或下采样,等等。

2。数据可视化:

将数据上传到 H2O 戴后,有几个选项可以帮助用户了解数据,包括自动可视化、数据汇总(每个要素的最小值、最大值、缺失值等指标)。这个特性也可以作为健全性检查

步骤来确认是否有丢失值百分比很高的要素,或者某些要素是否彼此高度相关。

3。自动模型优化:

在这一阶段,戴将基于实验设置(稍后有更多细节)对特征、特征变换器和 ML 模型的不同组合运行遗传算法,并最终记录下最佳执行模型。

4。模型文档和部署:

在戴完成建模过程后,将生成模型文档来记录关键的建模步骤。在模型部署方面,H2O 可以用 Java 和 Python 自动生成评分管道,部署在 REST API 框架下。也有将模型直接部署到云平台的选项,比如 Amazon Lambda。

H2O 实验配置

在戴建立良好模型的关键步骤之一是在实验配置页面下进行适当的选择。如下图所示,用户需要输入一些参数,包括训练/测试数据选择、目标变量选择等。在配置页面中有三个主要的调节旋钮,它们将在很大程度上决定最终模型是什么样的,它们是准确性、时间和可解释性。对于每个旋钮,用户可以从 1 到 10 中选择其值。

戴配置页面(图片来自和)

1.精确度:

调整精度旋钮值时,戴表演《进化》和《合奏》的方式也会随之调整。对于低精度值,用户通常期望单个模型作为最终输出,而对于较高精度,每个独立模型将独立发展,然后成为最终集合模型的一部分。与此同时,戴也将使用更高数量的折叠验证,以获得更好的模型概括。

2.时间:

顾名思义,它用于配置用户给戴运行优化的时间。为时间旋钮配置更高的值,将进行更多的训练和验证迭代。

3。可解释性

可解释性将在很大程度上决定最终模型的复杂性。在配置了较高的可解释性值的情况下,最终模型倾向于具有较低的级别或不进行集成,并且倾向于使用更基本的特征变换器和 ML 模型。

关于如何改变每个旋钮值的更多细节,你可以参考官方文件这里。需要注意的一点是,三个旋钮值并不是严格相互独立的。例如,准确性和可解释性旋钮值将决定最终模型中的整体效果。因此,这里没有关于如何选择最佳旋钮值的金科玉律——最有可能的是这里预期的一些尝试和错误。幸运的是,H2O 通过给出一个预览部分让这一步对用户来说更加直观(如前面的图表所示,“这些设置是什么意思?”在左手边)它将为用户提供一个更高层次的概述,当改变每个旋钮值时,最终模型中会出现什么。

4.专家设置

如果你想在使用什么特征转换器,或者为最终模型选择什么评分器方面有更多的灵活性,戴在“专家设置”页面下提供了选项。在这个页面中,用户可以更加定制地选择包含哪些特性的 transformers,使用哪些 ML 模型,甚至加载一些预先训练好的神经网络模型来完成 NLP 相关的任务。简而言之,如果用户以前在模型构建方面有一些经验,专家设置可能会更有用。

戴模型部署

获得模型后,下一步就是部署并在生产中投入使用。H2O 戴确实可以选择导出 Python 和 MOJO(优化的模型对象)形式的评分管道。

python 评分管道是 ML 模型的一个更直接的扩展,您可以选择在本地部署它以进行测试,也可以为其他语言和平台使用 TCP/HTTP 评分服务。

MOJO 评分管道利用了 MOJO,这是 POJO 的 H2O 优化版本。当处理更大的数据集和更复杂的模型时,MOJO 对象通常消耗更小的磁盘空间,具有更好的速度性能。可以在 Java 程序中自然使用,但用户也可以使用 R/Python 调用 MOJO 对象进行预测。

有了评分管道,就有了在云中部署模型的选项(AWS Lambda 是 H2O 推荐的选项),但更受欢迎的选项可能是使用 MOJO 部署 REST API。然而,可能仍然需要一些人工日来将模型集成到生产中——因此在某种意义上,模型部署部分还没有被戴完全自动化。

H2O 戴模型部署选项(图片由作者提供)

需要注意的事项

我曾经尝试用戴建立模型,并将其性能与手工建立的模型进行比较。一般来说,如果配置得当,H2O 戴在大多数使用案例中即使不能获得更好的性能,也能获得与之相当的性能。事实上,H2O 戴包括各种 ML 模型、特征转换器,并且可以运行通过特征、模型和超参数的如此多的不同组合,并且集合最佳执行模型以进一步提高模型分数。因此,从统计上看,在大多数情况下,戴确实显示出获得更好预测分数的优势。

话虽如此,但在考虑使用这个 AutoML 工具包进行生产时,仍有一些地方需要注意。仅举几个例子:

1。注意那些不自动化的事情:

虽然戴已经很好地自动化了许多耗时的建模过程,但仍有一些事情需要用户手动处理。

一个例子可能是特征工程部分,尽管在 H2O 有相当多的特征转换器,它们可能不会恰好覆盖你所需要的。因此,我相信类似于建立常规模型,

数据清理和特征工程仍然是重要的步骤,甚至与 H2O 戴。

2。当业务理解和可解释性很重要时:

当戴在内部进行计算时,优化纯粹是通过统计地改进得分函数来驱动的。可能会有这样的情况,一个特性转换器得到应用,并导致模型分数的整体提高,但是从业务角度来看,这可能没有多大意义。

例如,戴可能会选择对代表过去三个月客户交易计数的变量应用对数转换—从业务角度来看,该功能有意义吗?这个问题没有严格的正确或错误的答案,但是必须与相关的涉众保持一致,特别是对于那些通常对“自动过程”更加保守的模型评审者。

3。生产仍需额外努力:

模型部署和监控是 ML 建模生命周期中的另一个关键部分。正如我们前面提到的,虽然 H2O 戴可以自动生成评分管道,但仍有一些集成

在将它投入生产之前需要做的工作,比如使用评分管道设置 REST API,与本地数据库建立数据连接,设置跟踪系统以定期监控模型性能,等等。目前,所有这些步骤仍需要在戴以外的地方进行规划和测试。

话虽如此,戴却是一路快速进化。如果给一些时间,上述一些问题能够得到解决或显著改善,我不会感到惊讶。

有用的参考资料

戴官网是一个很好的入门工具。如果你想在购买许可证前亲自体验戴,一旦你注册,还提供 21 天的免费试用。

另一个对我帮助很大的文档是戴文档的 PDF 版本。它包含或多或少与在线用户手册相似的内容,但我觉得它在如何更系统地理解和学习 H2O 方面给出了一个更结构化的观点。

我希望这篇文章可以帮助那些对戴作为潜在的 AutoML 解决方案感兴趣的人。感谢阅读!

增强方法概述:CatBoost、XGBoost、AdaBoost、LightBoost、基于直方图的梯度增强

原文:https://towardsdatascience.com/an-overview-of-boosting-methods-catboost-xgboost-adaboost-lightboost-histogram-based-gradient-407447633ac1?source=collection_archive---------22-----------------------

用 python 实现在一个视图中编译所有 boosting 方法

***Table of Contents*****1\. Introduction
2\. AdaBoost
3\. Gradient Boost
3.1\. XGBoost
3.2\. Histogram-Based Gradient Boost
3.3\. LightBoost
3.4\. CatBoost
4\. Summary**

扎克·赖纳在 Unsplash 上的照片

1.介绍

在集成学习中,目标是用多种学习算法最成功地训练模型。在集成学习之一 Bagging 方法中,多个模型被并行应用于同一数据集的不同子样本。Boosting 是另一种方法,在实践中经常使用,它按顺序而不是并行建立,旨在训练算法和训练模型。弱算法训练模型,然后根据训练结果重新组织模型,使模型更容易学习。然后,这个修改后的模型被发送到下一个算法,第二个算法比第一个算法更容易学习。本文包含不同的增强方法,从不同的角度解释了这种顺序方法。

2。AdaBoost

自适应增强(Adaboost)是一种广泛使用的基于决策树桩的增强方法(决策树桩:分配阈值,根据阈值进行预测。)。但是这种方法在 Adaboost 中并不是盲目重复的。构建了多种算法,这些算法依次更新它们的权重,并在做出最准确的估计时扮演单独的角色。在每个算法中计算错误率。权重被更新,因此被引用到第二算法。第二种算法对模型进行分类,像第一种模型一样更新权重,并将其转移到第三种算法。这些过程一直持续到 n 个估计量或达到误差=0。在此过程中,该算法使分类更容易和更成功,因为权重由前一算法更新并发送到另一算法。让我们用一个例子来解释这个复杂的顺序算法过程:

假设有两个标签,红色蓝色。第一种算法(弱分类器 1)分离标签,结果是 2 个蓝色样本和 1 个红色样本被错误分类。增加这些错误分类的权重,之后降低正确分类的权重,发送到下一个模型学习。与以前的算法相比,新模型学习起来更容易,在新模型中,以前的模型错误分类的样本具有增加的偏差,而正确分类的样本具有减少的偏差。在接下来的步骤中重复相同的过程。总之,强分类是在弱分类的配合下发生的。因为它用于分类,所以也可以通过导入 AdaBoostRegressor 用于回归。

超参数

所有超参数均可在 sklearn 网站上获得。总结一下:

  • base _ estimators:一种顺序改进的算法(默认为决策树分类器)
  • n _ estimators:确定上述过程将采取的最大步骤数。(默认值=50)
  • 学习 _ 速率: 决定了权重的变化量。如果选择过小,n_estimators 值必须很高。如果选择得太大,它可能永远达不到最佳值。(默认值=1)

导入了将用于所有方法的数据集,现在让我们实现 Adaboost:

3.梯度增强

Adaboost 通过用决策树桩(1 个节点分成 2 片叶子)更新权重来改进自己。梯度增强,另一种顺序方法,通过创建 8 到 32 片叶子来优化损失,这意味着树在梯度增强中更大(损失:记住线性模型中的残差。(y_test-y_prediction)给出残差,每个数据点的平方和给出损失。为什么应用正方形?因为我们寻找的值是预测与实际结果的偏差。负值被平方,因为它们将使损失值变小,即使它偏离)。简而言之,通过使残差值更接近 0,残差值被转移到下一个算法,从而最小化损失值。

与 Adaboost 一样,梯度增强可通过导入 GradientBoostRegressor 用于回归。

OUT[0.22686585533221332,0.20713350861706786,0.1900682640534445,
 0.1761959477525979,0.16430532532798403,0.1540494010479854,
 0.14517117541343785,0.1375952312491854,0.130929810958826,
 0.12499605002264891,0.1193395594019215,0.11477096339545599,
 0.11067921343289967,0.10692446632551068,...................
 ...........................................................
 0.05488031632425609,0.05484366975329703,0.05480676108875857,
 0.054808073418709524,0.054740333154284,0.05460221966859833,
 0.05456647041868937,0.054489873127848434,0.054376259548495065,
 0.0542407250628274]

查看 Error_list,可以看到每一步损失值都在变小。[从 0.22 开始,到 0.05 结束]

3.1.XGBoost

XGBoost(代表极端梯度增强)最初是由陈天琦在 2014 年开发的,在梯度增强之前速度快得多,因此它是首选的增强方法。由于它包含超参数,可以进行许多调整,如正则化超参数,以防止过度拟合。

超参数

  • learning _ rate&eta:乘以权重值使用。其目的是通过安排特征权重使过程更保守。默认值=0.3,通常使用 0.01–0.3。
  • max_depth: 树的最大深度。如果该值增加,模型可能会过度拟合。默认值=6 且仅当growing_policy=lossguidemax_value=0时。请查看增长政策。
  • n _ estimators:集合树的数量
  • alpha: L1 正则化在权重上。鼓励小重量。默认值=1。
  • gamma: 正则化复杂度的超参数之一,在一片叶子中发生分裂所必需的最小损失。默认值=0,较大的灰度系数使模型更加保守。
  • λ:L2 正则化在权数上。鼓励小重量。默认值=1。
  • 子样本: 将训练多少个数据样本?默认值=1 表示 100%百分比,如果设置为 0.5,则随机选择 50%的数据。
  • col sample _ bytree:构造每棵树时列的子采样比。默认值=1。对于每个构建的树,进行一次子采样。
  • col sample _ by level:每个级别的列的子样本比率。默认值=1。对于树中达到的每个新的深度级别,进行一次子采样。从为当前树选择的列集中对列进行子采样。
  • col sample _ node:每个节点列的子样比率。每次评估新的分割时,进行一次子采样。从为当前级别选择的列集中对列进行子采样。
  • min _ child _ weight:用于控制过拟合。过高的值会导致拟合不足。默认值=1。
  • grow_policy: 控制新节点添加到树中的方式。在 LGBM 发布后,它被添加到 XGBoost 中。由于 LGBM 的高速度(由于 wise-leaf),它被添加到 XGBoost 与 wise-leaf 的工作中。为了激活它,grow_policy=lossguide,默认=depthwise
  • 目标: 指定学习任务。‘regsquarederror’:平方损失回归;‘reg logist’:logistic regression 等。
  • eval _ metric:test _ data(validation _ data)的评估度量。‘RMSE’:均方根误差;‘Mae’:平均绝对误差,‘mape’:平均绝对百分比误差。

更可在此 链接

3.2.基于直方图的梯度增强

用宁滨(离散化)对数据进行分组,这是一种数据预处理方法,这里****已经解释过了。例如,当给定‘年龄’列时,将这些数据分为 30–40、40–50、50–60 三组,然后将其转换为数值数据,这是一种非常有效的方法。当这种宁滨方法适用于决策树时,通过减少特征的数量,它加快了算法的速度。这种方法也可以通过用直方图对树进行分组而在每个树的构造中用作集成。scikit 学习库提供的方法:

3.3.光增强

LGBM(代表轻度梯度增强机器)最初由微软在 2017 年发布,是用户首选的另一种梯度增强方法,并且是基于决策树的。与其他方法的关键区别在于,它基于树叶对树进行拆分,即可以检测和停止点拍所需的单元(记住:其他的是基于深度或基于级别的)。由于 LGBM 是基于叶子的,如图 2 所示,LGBM 是一种非常有效的方法,可以减少误差,从而提高精度和速度。您可以使用特殊算法拆分分类数据,但是必须输入一个整数值,如 index,而不是列的字符串名称。

图二。基于层与基于叶,按作者排序的图像

3.4.CatBoost

CatBoost 是 Yandex 在 2017 年开发的。由于它通过一次热编码将所有分类特征转换为数字,因此其名称来自于CategoricalBoosting。应该输入索引值,而不是 but 列的字符串名称。它还处理缺失的数值。它也比 XGBoost 快得多。与其他增强方法不同,Catboost 与对称树不同,后者在每一层的节点中使用相同的分裂。

XGBoost 和 LGBM 计算每个数据点的残差,并将模型训练为具有残差目标值。它重复这个迭代次数,从而训练和降低残余误差,达到目标。由于这种方法应用于每个数据点,它可能在泛化方面较弱,并导致过拟合。

Catboost 还计算每个数据点的残差,并对用其他数据训练的模型执行此操作。以这种方式,为每个数据点获得不同的残差数据。将这些数据作为目标进行评估,并根据迭代次数训练通用模型。由于许多模型将通过定义来实现,这种计算复杂性看起来真的很昂贵,并且花费太多时间。但是在有序升压的情况下,它在更短的时间内完成。有序提升,而不是从第(n+1)个数据点计算的残差开始。就是指数据点的残差。为了计算第(n+2)个数据点,应用第(n+1)个数据点,等等。

超参数

  • l2_leaf_reg: L2 代价函数的正则化项。
  • 学习 _ 速率: 渐变步长。在过度拟合的情况下降低学习率。
  • 深度: 树的深度,大多用在 6-10 之间。
  • one _ hot _ max _ size:用小于或等于给定参数值的几个不同值对所有分类特征进行 one-hot 编码
  • grow_policy: 决定建筑类型的树。可以使用 SymmetricTree、Depthwise 或 Lossguide。

4.摘要

在这篇文章中,boosting 方法是通过决策树来实现的,但是通过改变相关的超参数,可以很容易地实现其他机器学习模型。此外,所有 boosting 方法都应用了基本版本(未调整任何超参数)来比较 boosting 方法的性能,上面应用的代码列表如下:

增强方法的比较,图片由作者提供

在以后的文章中,我们将通过优化超参数来更深入地探讨每种提升方法。

参考

  • https://stack overflow . com/questions/50087526/catboost 算法中对称树背后的直觉是什么
  • https://catboost . ai/docs/concepts/python-reference _ parameters-list . html
  • https://csiss.org/SPACE/workshops/2004/SAC/files/fisher.pdf
  • 【https://xgboost.readthedocs.io/en/latest/parameter.html 号

回到指引点击这里。

**https://ibrahimkovan.medium.com/machine-learning-guideline-959da5c6f73d **

使用 SequenceMatcher 和 spaCy 构建商家名称清理引擎概述

原文:https://towardsdatascience.com/an-overview-of-building-a-merchant-name-cleaning-engine-with-sequencematcher-and-spacy-9d8138b9aace?source=collection_archive---------10-----------------------

照片由米科拉·马赫莱在 Unsplash 上拍摄

问题陈述

商家名称清理可能是一个相当具有挑战性的问题。由于不同的银行提供不同质量的交易数据,没有一个非常成熟的方法来清理数据。通常,商家名称清理可以被分类为命名实体识别 (NER)任务,并且以与实体提取问题类似的方式来解决。

对于一家金融科技公司来说,商户名称清理步骤非常重要,因为开发人员需要利用这些从原始混乱的交易数据中清理出来的商户名称来生成正确的交易分类,以便在管理个人金融方面提供更好的客户体验。

我发现这个话题非常有趣,我已经搜索了几个星期的资源,用我自己的基本解决方案写了这个概述。因此,我希望我对这个话题的一些想法能够对读者有所帮助,以更好地解决这个商家名称清理问题。

如果你正在寻找更多关于这个主题的阅读资料,欢迎你查看本文末尾的参考书目

工程计划

对于一个基本的商家名称清洗引擎,我计划将其分为三层:

  • 第一层:删除特殊字符和数字,并转换大小写。
  • 第二层:根据相似性得分返回名称匹配。
  • 第三层:训练一个空间模型来检测模式和清理输入。

这个项目的工具包包括 python 中的正则表达式运算、FuzzyWuzzy/sequence matcher(库)以及 spaCy 模型算法中的一些知识。

随着阅读的进行,我也会分享一些我觉得有帮助的相关阅读。

第一层:预处理步骤

删除特殊字符和数字:

删除所有特殊字符和数字将是该项目的第一步。这很有用,因为当我们试图查找商家名称匹配和计算相似性分数时,特殊字符和数字通常会增加复杂性。完全删除所有特殊字符和数字可能有点激进。但是,考虑到有数千个原始商家名称的数据集,您可能会发现大多数特殊字符和数字都可以删除,而不会影响商家名称中的任何关键字。

借助 Python Re 库,可以高效地完成特殊字符和数字的删除。一些必备知识是 Python 中的正则表达式

*https://medium.com/better-programming/introduction-to-regex-8c18abdd4f70

案例转换

通过成功完成上述步骤,您现在拥有了一个仅包含字母的商家名称数据集。但是,您可能仍然会发现一些商家名称的大小写不同,例如“amazon”、“Amazon”或“AMAZON”。要转换案例,可以在以下文章中找到一些有用的字符串函数:

第二层:计算相似性得分表

对于这一层,我们的主要目标是计算一个相似性得分表,并返回具有前 3 个最大相似性得分的匹配名称。这是一个有用的方法来清理商家名称,假设你已经有一个匹配的名称目录,并且原始输入不是杂乱的。

相似性度量

FuzzyWuzzy 是一个 Python 库,它使用 Levenshtein 距离 来计算一个简单易用的包中序列之间的差异。

https://github.com/seatgeek/fuzzywuzzy

使用 FuzzyWuzzy 的一些实例如下:

  • 简单比率
>>> fuzz.ratio("this is a test", "this is a test!")
    97
  • 部分比率
>>> fuzz.partial_ratio("this is a test", "this is a test!")
    100
  • 令牌排序比率
>>> fuzz.ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
    91
>>> fuzz.token_sort_ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")
    100
  • 令牌集比率
>>> fuzz.token_sort_ratio("fuzzy was a bear", "fuzzy fuzzy was a bear")
    84
>>> fuzz.token_set_ratio("fuzzy was a bear", "fuzzy fuzzy was a bear")
    100

或者,sequence matcher也是一个常用于计算输入之间相似性的伟大工具。

基本思想是找到不包含“垃圾”元素的最长连续匹配子序列。然后,相同的思想被递归地应用于匹配子序列的左边和右边的序列片段。这不会产生最少的编辑序列,但会产生对人们来说“看起来正确”的匹配。

>>> s = SequenceMatcher(lambda x: x == " ", 
"private Thread currentThread;", 
"private volatile Thread currentThread;")  

>>> .ratio() returns a float in [0, 1], measuring the "similarity" of the sequences.  As a rule of thumb, a .ratio() value over 0.6 means the sequences are close matches>>> print(round(s.ratio(), 3))    
0.866

定制相似性函数&计算相似性表

对我来说,我选择 SequenceMatcher 作为评价相似性的度量。如果您选择 FuzzyWuzzy 库,过程将是相似的。

# define a function to calculate similarity between input sequences
def similarity_map(word1, word2):

    seq = difflib.SequenceMatcher(None,word1,word2) d = seq.ratio()

    return d

上面的定制函数将两个序列作为输入,并返回相似性得分的比值。

为了进一步计算相似性得分表,我制作了一个数据集,它将原始的商家名称作为行索引,将经过清理的商家名称目录作为列名。通过运行下面的代码单元格,它将为每对行索引和列名生成一个相似性得分表。

# prepare a sample dataset
df = pd.DataFrame(data, 
index =['amazon co com', 'www netflix com', 'paypal payment', 'apple com bill', 'google play', 'facebook ads'],
columns = ['amazon', 'netflix', 'paypal', 'apple', 'google', 'facebook']) 

# print the data 
dffrom tqdm import tqdmfor i in tqdm(range(6)):
    for j in range(6):
        df.loc[df.index[i], df.columns[j]] = similarity_map(str(df.index[i]), str(df.columns[j]))

df.head()

一旦您运行完上面的单元格,您应该有一个相似性得分表,如下所示:

相似性得分表

返回最佳匹配

基于上表,我们可以通过返回每行具有前 3 个最高相似性得分的商家名称来进一步分析洞察力。

编写一个函数top ,该函数将上述数据集作为输入,并返回一个包含前 3 名姓名及其相似性得分的数据集。

similarity = df.reset_index()
similarity.head()def top(x):
    x.set_index('index', inplace=True)
    df = pd.DataFrame({'Max1Name':[],'Max2Name':[],'Max3Name':[],'Max1Value':[],'Max2Value':[],'Max3Value':[]})
    df.index.name='index'
    df.loc[x.index.values[0],['Max1Name', 'Max2Name', 'Max3Name']] = x.sum().nlargest(3).index.tolist()
    df.loc[x.index.values[0],['Max1Value', 'Max2Value', 'Max3Value']] = x.sum().nlargest(3).values
    return dftest = similarity.groupby('index').apply(top).reset_index(level=1, drop=True).reset_index()
test.head()

https://stackoverflow.com/questions/29919306/find-the-column-name-which-has-the-maximum-value-for-each-row https://stackoverflow.com/questions/37494844/find-the-column-names-which-have-top-3-largest-values-for-each-row

通过成功实现上述代码单元,您应该得到如下所示的返回数据集:

每行前 3 个最相似的匹配项

尽管这只是对一个样本数据集的测试,但是如果我们有非杂乱的输入以及一个经过清理的商家名称目录,我们仍然会发现这种方法很有用。

然而,这种方法对于更复杂的商家输入可能表现不好。例如,booking.com 多伦多上一个名为 *paypal 卡支付的商家可能会返回一个关于 paypal 或 Booking 的低相似性分数(小于 0.5)。

在这种情况下,需要更先进的方法来检测我们想要的“真实”商家名称的位置。

第 3 层:用 spaCy 清理商户名称

通过完成前两层,我们能够通过简单地返回相似性得分表来解决一些商家名称清理问题,例如拼写错误、大小写不同、缺少字符/空格,甚至一些非杂乱的商家输入。

然而,我们实际上仍处于使用基于规则的清理引擎的阶段,这意味着迄今为止我们仍未从数据中学习。此外,即使通过使用典型的机器学习模型,训练阶段仍然需要大量的时间来执行特征工程以创建更多的信息特征。

…潜在的交易级信息特征,如金额和类别,同时还生成单词级自然语言特征,如标签内的单词位置(如第一、第二)、单词长度、元音比例、辅音和字母数字字符等。

CleanMachine:钱包的金融交易标签翻译。艾

因此,我研究了如何使用深度学习模型来创建清洁引擎。使用深度学习模型的优势在于,我们能够“跳过”特征工程步骤,让模型本身从输入中检测任何有见地的模式。

空间介绍

一个免费的短期空间课程可以找到如下:

https://course.spacy.io/en

根据 空间指南 :

spaCy 是 Python 和 Cython 中高级自然语言处理的库。它建立在最新研究的基础上,从第一天起就被设计用于真正的产品。spaCy 自带预训练的统计模型词向量,目前支持 60+语言的标记化。

它具有最先进的速度、卷积神经网络模型,用于标记、解析和命名实体识别以及轻松的深度学习集成。这是在麻省理工学院许可下发布的商业开源软件。

https://github.com/explosion/spaCy

由于商家名称清洗问题可以归入命名实体识别 (NER)的主题下,我相信通过输入一组有代表性的输入数据,spaCy 模型会有很好的表现。

训练空间的统计模型

https://spacy.io/usage/training#section-basics

为了训练一个空间模型,我们不仅仅希望它记住我们的例子——我们希望它提出一个理论,这个理论可以推广到其他例子

因此,训练数据应该总是代表我们想要处理的数据。对于我们的项目,我们可能希望从不同类型的商家名称中选择训练数据。最终,我们的培训数据将采用如下实体列表的形式:

TRAIN_DATA = 
[
('Amazon co ca', {'entities': [(0, 6, 'BRD')]}),
('AMZNMKTPLACE AMAZON CO', {'entities': [(13, 19, 'BRD')]}),
('APPLE COM BILL', {'entities': [(0, 5, 'BRD')]}),
('BOOKING COM New York City', {'entities': [(0, 7, 'BRD')]}),
('STARBUCKS Vancouver', {'entities': [(0, 9, 'BRD')]}),
('Uber BV', {'entities': [(0, 4, 'BRD')]}),
('Hotel on Booking com Toronto', {'entities': [(9, 16, 'BRD')]}),
('UBER com', {'entities': [(0, 4, 'BRD')]}),
('Netflix com', {'entities': [(0, 7, 'BRD')]})]
]

我选择的训练数据只是一个样本。该模型可以接受更复杂的输入。但是,注释一长串商家名称可能会有点无聊。我想推荐另一个数据标注工具 UBIAI 来完成这个任务,因为它支持 spaCy 格式甚至亚马逊理解格式的输出。

https://medium.com/@walidamamou/how-to-automate-job-searches-using-named-entity-recognition-part-1-16c150acafa0 https://medium.com/swlh/building-a-job-entity-recognizer-using-amazon-comprehend-5dd2c33faa82

可能需要一些如何选择代表数据输入的经验。随着你练习得越来越多,观察空间模型学习的方式,你会越来越清楚“代表”可能意味着“不同的位置”。这就是为什么我们需要在输入数据中提供一个实体 start & end 索引的原因,因为它可以帮助模型从不同的上下文中学习模式。

如果模型经常被训练为第一个单词的位置是商家名称(Amazon ca),那么它倾向于认为商家名称只位于输入的开头。这可能会导致偏见,并导致对输入(如“音乐 Spotify ”)的错误预测,因为“Spotify”恰好是第二个单词。

然而,在输入中包含各种商家名称也很重要。请注意,我们不希望我们的模型仅仅记住它们。

一旦完成了对训练数据的调优,剩下的过程几乎就会自动完成。

import spacy
import randomdef train_spacy(data,iterations):
    TRAIN_DATA = data
    nlp = spacy.blank('en')  # create blank Language class
    # create the built-in pipeline components and add them to the pipeline
    # nlp.create_pipe works for built-ins that are registered with spaCy
    if 'ner' not in nlp.pipe_names:
        ner = nlp.create_pipe('ner')
        nlp.add_pipe(ner, last=True)# add labels
    for _, annotations in TRAIN_DATA:
         for ent in annotations.get('entities'):
            ner.add_label(ent[2])# get names of other pipes to disable them during training
    other_pipes = [pipe for pipe in nlp.pipe_names if pipe != 'ner']
    with nlp.disable_pipes(*other_pipes):  # only train NER
        optimizer = nlp.begin_training()
        for itn in range(iterations):
            print("Statring iteration " + str(itn))
            random.shuffle(TRAIN_DATA)
            losses = {}
            for text, annotations in TRAIN_DATA:
                nlp.update(
                    [text],  # batch of texts
                    [annotations],  # batch of annotations
                    drop=0.2,  # dropout - make it harder to memorise data
                    sgd=optimizer,  # callable to update weights
                    losses=losses)
            print(losses)
    return nlpprdnlp = train_spacy(TRAIN_DATA, 20)# Save our trained Model
modelfile = input("Enter your Model Name: ")
prdnlp.to_disk(modelfile)#Test your text
test_text = input("Enter your testing text: ")
doc = prdnlp(test_text)
for ent in doc.ents:
    print(ent.text, ent.start_char, ent.end_char, ent.label_)

上面的代码来自下面的 Medium 文章,因为我发现它非常有帮助,并启发我测试 spaCy 的一个商家名称清洗问题。

https://manivannan-ai.medium.com/how-to-train-ner-with-custom-training-data-using-spacy-188e0e508c6 https://www.machinelearningplus.com/nlp/training-custom-ner-model-in-spacy/

评估空间模型

通过成功完成训练步骤,我们可以通过检查其损失值来监控模型进度。

Statring iteration 0
{'ner': 18.696674078702927}
Statring iteration 1
{'ner': 10.93641816265881}
Statring iteration 2
{'ner': 7.63046314753592}
Statring iteration 3
{'ner': 1.8599222962139454}
Statring iteration 4
{'ner': 0.29048295595632395}
Statring iteration 5
{'ner': 0.0009769084971516626}

然后向模型显示未标记的文本,并进行预测。因为我们知道正确的答案,所以我们可以以计算训练样本和预期输出之间的差异的损失函数误差梯度的形式给出关于其预测的模型反馈。差异越大,梯度和模型更新就越显著。

要测试您的模型,您可以运行下面的代码单元格:

#Test your text
test_text = input("Enter your testing text: ")
doc = prdnlp(test_text)
for ent in doc.ents:
    print(ent.text, ent.start_char, ent.end_char, ent.label_)

例如,我们可以使用“paypal payment”作为输入,并测试模型是否能检测出“paypal”是正确的品牌名称。

考虑到 PayPal 没有出现在训练输入中,该模型做得非常好。

这也结束了我的项目,建立一个商业名称与空间模型清洁引擎。

结论

首先,感谢您花时间阅读这篇长文,我真诚地希望它对您有所帮助~

  • 我首先介绍了为什么商户名称清理很重要。
  • 然后,我把清洁引擎分成三层。
  • 最后,对于每一层,我解释了输入和输出,以及为什么每一层都是必要的。

作为对这个挑战性问题的概述,我并不完全期望给出一个完美的解决方案。但是我相信分享我的想法和我在研究过程中发现的任何有用的读物会有所帮助。

因此,我希望你喜欢阅读这篇文章。同时,我在本文末尾添加了一个参考列表部分,以防您有兴趣了解关于这个主题的更多信息。

谢谢~

页(page 的缩写)s。

第一次更新:2021 年 2 月 5 日

对 spaCy 模型的训练结果进行了一点更新,大约有 1000 行输入数据。(1000 条注释)

我已经将模型设置为每轮训练 50 次迭代,并对其进行 10 轮训练,以查看训练损失如何变化。似乎如果我们以正确的方式预处理数据,我们应该能够通过 50 次迭代每次达到低且一致的训练损失,如下图所示:

10 轮训练,每轮 50 次迭代

第二次更新:2021 年 2 月 8 日

🤔但是,还有什么方法可以让我们的 spaCy 模型更具交互性呢?如果我们能把 spaCy model 和 Streamlit 集成到一个 web 界面中,会不会更加用户友好?

我受到了如下空间文档的启发:

https://spacy.io/usage/projects

似乎 spaCy 支持包括 Streamlit 在内的许多花哨的工具。因此,我决定尝试将 spaCy 和 Streamlit 整合到一个 web 应用程序中。

如果您想了解更多关于 Streamlit 的知识,下面这篇文章是一个好的开始。

由于之前我们已经将空间训练函数定义为 train_spacy ,剩下的工作将在 10 行代码之内。这也是我认为我应该在同一篇文章下给出一个更新的原因🤗

假设我们已经准备了之前 TRAIN_DATA 格式的输入注释列表。

Streamlit 中的 web 应用程序界面代码如下所示:

import pandas as pd
import numpy as np 
import random
import spacy
import re
import warnings
import streamlit as st 
warnings.filterwarnings('ignore') # ignore warnings nlp = train_spacy(TRAIN_DATA, 50) # number of iterations set as 50# Save our trained Model 
# Once you obtained a trained model, you can switch to load a model for merchant name cleaning
modelfile = input("Enter your Model Name: ")
nlp.to_disk(modelfile)# Load our saved Model 
# Load your model to clean a user input instead of training a new model once again when there is a new input
# nlp = spacy.load(modelfile/) # path to the saved file foldertext = 'Amazon/ca' # default text input on web interfacest.title('Merchant Names Cleaning App') # web app title nameuser_input = st.text_input("Text", text) # input text placedoc = nlp(user_input) for ent in doc.ents:

    st.write('Text:', ent.text) # display model output 
    st.write('Label:', ent.label_) # display model output

一个成功的 web 界面应该如下所示:

使用 Streamlit 的示例 web 界面

希望你喜欢阅读!

引用表

[1] 从 Reddit 上清理企业名称

[2] 利用机器学习改进您的交易数据分类

[3] 理清杂乱的银行数据

[4] 使用 Greenplum Hadoop 标准化金融服务领域的 1 . 13 亿多家商户名称

[5] 与 FuzzyWuzzy 匹配的字符串

[6] 用 Python 进行模糊字符串匹配的自然语言处理

【7】大规模模糊姓名匹配的集成方法

【8】混合模糊名称匹配

[9] CleanMachine:钱包的金融交易标签翻译。艾

【10】深度学习魔法:小企业类型

[11] 使用 Pytorch 检测商户名称

[12] 对银行交易数据进行分类

[13] 训练空间的统计模型

[14] 如何训练 spaCy 自动检测新实体(NER)【完全指南】

[15] 使用 Amazon comprehension构建自定义实体识别器

[16] 用亚马逊 SageMaker Ground Truth 和亚马逊 comprehension 开发 NER 模型

[17] UBIAI 文档

[18] 如何使用命名实体识别实现工作搜索自动化—第 1 部分

[19] 使用 Amazon understand 构建作业实体识别器

[20] Streamlit 和 spaCy:用最少的领域知识创建一个预测情感和单词相似度的应用*

AWS Lambda 的 CloudWatch 指标概述

原文:https://towardsdatascience.com/an-overview-of-cloudwatch-metrics-for-aws-lambda-41fc1f0e773?source=collection_archive---------34-----------------------

了解如何监控 AWS Lambda 函数的 CloudWatch 指标

图片来自 Pexels

在本文中,我将讨论如何使用 CloudWatch 指标来执行和监控 AWS Lambda。AWS Lambda 允许您在云上运行应用程序,而无需提供任何服务器。你所需要做的就是使用你喜欢的编程语言编写你的代码,并将你的代码部署到 AWS Lambda。然后,您可以使用 AWS 提供的资源直接运行您的程序。在撰写本文时,AWS Lambda 支持用 Java、NodeJS、C#、PowerShell、Python、Ruby 和 Go 编写的程序。

为什么要监控 Lambda 函数

我认为这是一个很好的起点。这可能是一个问题,如果 Lambda 是无服务器的,并且部署在云中,那么我们为什么要监控它呢?这是因为 Lambda 为每次触发的执行以及执行的持续时间计费。我们将在本文后面看到更多关于 Lambda 定价的内容。但是,总有改进代码的空间或范围,以便它可以用最少的资源和尽可能短的时间有效地执行。这将帮助你作为一个开发人员成长,并且逐渐地也将有助于组织的成长,因为你实际上是在构建一个有成本效益的系统。

在云计算的新时代,事情与传统的基于服务器的架构有些不同。AWS Lambda 是无服务器的,它有一个内置的日志记录和监控系统,可以在 AWS CloudWatch 中推送结果。在运行 AWS Lambda 函数时,了解可以测量哪些指标非常重要。下面是 CloudWatch 在执行 Lambda 函数期间捕获的一些指标。

图 AWS Lambda 的帐户级别指标—云观察指标

为了查看任何 Lambda 函数的性能指标,您可以按照如下步骤操作。打开要监控的 Lambda 函数。单击顶部的 Monitoring,将会显示 CloudWatch Metrics 选项卡。在此选项卡中,您可以看到如下多个指标。

图 2 —在 CloudWatch 指标中监控 Lambda 函数的执行细节

在该选项卡中,有近七个指标受到监控。我已经讨论了下面每个指标的含义。基本上,所有指标都可以分为三个部分——调用指标、性能指标和并发指标。让我们来详细了解一下每一项。

调用指标

调用 —这个指标是 lambda 函数的计费实际上所依赖的最重要的指标之一。每当 lambda 函数被触发时,Lambda 会为每次成功或失败的执行添加一个值 1。如果调用被抑制,那么它将不会在这个指标中被捕获。

错误—lambda 函数中可能存在错误,这可能导致 lambda 函数在执行后无法成功完成。这可能是由于 lambda 函数的代码或 lambda 运行时本身在内部引发了异常。lambda 环境引发错误的最常见原因是不正确的参数配置或由于执行时间较长而引发的超时问题。lambda 函数最多可以运行 15 分钟。

错误 比率 —错误率通过将错误数除以函数调用总数来计算。

Success****Rate—lambda 函数的成功率通过从调用中减去错误,然后除以调用总数来计算。

性能指标

性能指标告诉我们 lambda 函数单次执行的性能。

持续时间 —这个指标告诉我们 lambda 执行函数所需的持续时间。这也取决于分配给 lambda 的内存量。基于内存,AWS 也将计算能力分配给 lambda,该计算能力与内存分配成比例。当您的 lambda 用完所有已分配的内存时,您可以尝试这个设置来找到一个好的基准。

迭代器年龄 —这个度量帮助我们理解在流中收到消息和它实际被发送到函数之间的持续时间。此度量仅适用于事件源映射的 lambda 函数。lambda 函数的事件可以从各种 Amazon 服务发送,如 Simple Queue Service 或 Amazon Kinesis。

并发度量

在云上运行 lambda 函数为同时运行并发函数提供了额外的优势。当 lambda 函数被并行执行时,并发性指标被推送到 CloudWatch 指标中。

并发执行 —这个指标告诉我们对于任何给定的特定 lambda 函数,同时运行的并发执行的最大数量。

CloudWatch 日志洞察

每当执行 lambda 函数时,都会生成日志,这些日志会被存储起来,以后可以在任何时间点从 CloudWatch 查看。日志有助于我们分析 lambda 函数并排除故障,以防在函数执行过程中出现任何问题或错误。

图 3 — CloudWatch 在 lambda 函数中记录见解

CloudWatch Logs Insights 也是一个重要的部分,它为我们提供了关于 lambda 函数的每个执行的信息。这里有两个部分— 最近的调用最昂贵的调用。这些部分中提供的 CloudWatch 指标如下。

时间戳 —这通常是函数接收到开始执行的请求时的时间戳。它以 UTC 时区存储。

request id—request id 是一个 UUID 字段,为 lambda 函数的每次执行自动生成。这是一个唯一的标识符,可用于标识 lambda 函数的特定执行实例。

日志流 —日志流实际上包含了在生成 Lambda 函数期间生成的详细日志流。您可以单击每个单独的日志流,这将打开特定的日志流,您可以在其中详细查看日志。

DurationInMS —这个指标告诉我们 lambda 函数执行的持续时间,以毫秒为单位。

BilledDurationInMS —此指标是 DurationInMS 指标的四舍五入版本,用于计费目的。通常,这些值总是向上舍入到下一个更大的整数。

MemorySetInMB —这告诉我们在执行时我们已经分配给特定 Lambda 函数的内存。默认情况下,每个 lambda 函数都被设置为从 128 MB 内存开始。但是,根据您的应用程序的负载,建议您相应地更改它。

MemoryUsedInMB —这是最重要的 CloudWatch 指标之一,我个人经常使用它来了解我的应用程序消耗了多少内存。如果所有的内存集都被使用了,那么我们应该增加它,这样在执行之后还会剩下一些内存。这反过来也有助于减少执行时间。

BilledDurationInGBSeconds—这是一个计算指标,通过将分配的内存乘以计费持续时间来衡量。您最终将根据这一指标付费。

结论

在本文中,我们看到了如何捆绑应用程序并部署到 AWS Lambda。AWS Lambda 提供了一个在无服务器平台上运行应用程序的平台。这意味着您不需要维护或照顾 Lambda 使用的底层资源。然而,由于它是无服务器的,你需要监控这些功能的使用,这样你就不会被超额计费。Lambda 是基于执行次数和执行持续时间计费的。您可以使用默认提供的 CloudWatch 指标轻松监控 Lambda 函数的执行。

使用 R 中的 Tidyverse 库进行数据分析概述

原文:https://towardsdatascience.com/an-overview-of-data-analysis-with-the-tidyverse-library-in-r-e94c151bf7d1?source=collection_archive---------20-----------------------

马修·施瓦茨在 Unsplash 上的照片

很好的学习资源,也可以用作备忘单

R 中的“tidyverse”包对于 R 中的数据分析是一个非常有用的工具,因为它几乎涵盖了分析数据集所需的一切。它是几个大图书馆的组合,使它成为一个巨大的学习图书馆。在他的文章中,我将尝试对 tidyverse 库做一个很好的概述,它提供了足够的资源来很好地执行数据分析任务,也是进一步学习的一个很好的基础。它也可以用作备忘单。

如果一个人没有多年的经验,在你面前的一页上有一个操作或数据分析想法的列表会很有用。所以,我试着在这个页面上编译了相当多的常用操作来帮助我自己和你。

tidyverse 包中包含的日常数据分析包有:

ggplot2

dplyr

tidyr

readr

满意地说

蒂布尔

stringr

forcats

除了 tibble 之外,本文触及了所有这些包。如果你不知道 tibble 是什么,它也是一种数据框架。我在这里不赘述。我在这里的所有例子中使用了简单的数据框。

我会从一些简单的事情开始,慢慢走向一些更复杂的任务。

开始吧!

首先导入 tidyverse 库。

library(tidyverse)

我将从 stringr 库的一些简单函数开始,这些函数是不言自明的。所以,我就不多解释了。

将字符串转换为小写:

x = "Happy New Year 2022"
str_to_lower(x)

输出:

[1] "happy new year 2022"

将字符串转换为大写:

str_to_upper(x)

输出:

[1] "HAPPY NEW YEAR 2022"

将几个字符串组合成一个字符串:

str_c("I ", "am ", "very ", "happy")

输出:

[1] "I am very happy"

获取字符串列表的子集:

这里我将列出一个字符串列表,然后只取每个字符串的前三个字母:

x = c("Apple", "Tears", "Romkom")
str_sub(x, 1, 3)

输出:

[1] "App" "Tea" "Rom"

在接下来的演示中,我将使用一个名为 flight dataset 的数据集,它是 nycflights13 库的一部分。

library(nycflights13)

库被导入。现在,您已经准备好使用飞行数据集了。飞行数据集很大。这是一个很大的数据集。所以,这里不可能显示截图。以下是数据集的列:

names(flights)

输出:

[1] "year"           "month"          "day"            "dep_time"      
 [5] "sched_dep_time" "dep_delay"      "arr_time"       "sched_arr_time"
[9] "arr_delay"      "carrier"        "flight"         "tailnum"       
[13] "origin"         "dest"           "air_time"       "distance"      
[17] "hour"           "minute"         "time_hour"

我将从将两列组合在一起的“unite”函数开始。下面的代码块将 flight 和 carrier 列合并在一起,形成一个名为“flight_carr”的新列:

flights %>%
  unite_(.,"flight_carr", c("flight", "carrier"))

以下是显示新 flight_carr 列的数据集部分:

当我们有分类数据并且需要将它们用作级别时,因子函数非常有用。对于可视化和机器学习,有必要对分类数据使用因子函数来将它们存储为级别。

在这里,我对载体列进行因子分解,并打印独特的载体:

carr = factor(flights$carrier)
levels(carr)

输出:

[1] "9E" "AA" "AS" "B6" "DL" "EV" "F9" "FL" "HA" "MQ" "OO" "UA" "US"
[14] "VX" "WN" "YV"

让我们看看每个载体的数量:

fct_count(carr)

下一个是 purr 包中的 map_dbl 函数,它采用一个统计函数并返回结果。在这里,我将采用“距离”和“sched_arr_time”列,并找出这两个列的“平均值”:

map_dbl(flights[, c("distance", "sched_arr_time")], ~mean(.x))

输出:

distance sched_arr_time 
1039.913       1536.380

GGPLOT2 是一个巨大的可视化库,也附带了 tidyverse 包。这里有一个例子:

ggplot(data = flights) + 
  aes(x = distance) + 
  geom_density(adjust = 1, fill = "#0c4c8a") + 
  theme_minimal()

我有一个关于 ggplot2 的详细教程,你可以在里面找到一系列可视化技术:

我们来看看 lubridate 包的一些功能:

dates = c("January 18, 2020", "May 19, 2020", "July 20, 2020")
mdy(dates)

输出:

[1] "2020-01-18" "2020-05-19" "2020-07-20"

小时-分钟-秒数据:

x = c("11:03:07", "09:35:20", "09:18:32")
hms(x)

输出:

[1] "11H 3M 7S"  "9H 35M 20S" "9H 18M 32S"

让我们回到我们的航班数据集。航班数据集中有年、月、日数据。我们可以用它做一个日期栏,找出每个日期的航班数和平均距离。

flights %>% 
  group_by(date = make_date(year, month, day)) %>%
  summarise(number_of_flights = n(), mean_distance = mean(distance, na.rm = TRUE))

如何取一个数据帧的子集?

这个代码块从航班数据集中抽取了 15 行数据。

flights %>%
  slice_sample(n = 15)

以下代码块从航班数据集中抽取了 15%的数据样本:

flights %>%
  slice_sample(prop = 0.15)

从大型数据集中选择特定的列

这里,我从航班数据集中提取了始发地、目的地、承运人和航班列:

flights %>%
  select(origin, dest, carrier, flight)

如果从这个大的航班数据集中,我想要除 time_hour 和 tailnum 列之外的大多数列,该怎么办?

select(flights, -time_hour, -tailnum)

该代码块将选择航班数据集中除 time_hour 和 tailnum 列之外的所有列。

使用列名的一部分来选择列也很有帮助。

以下代码行选择所有以“air_”开头的列:

flights %>%
  select(starts_with("air_"))

只有一列以“air_”开头。

这些是以“延迟”结尾的列:

flights %>%
  select(ends_with("delay"))

以下各列包含“dep”部分。

flights %>%
  select(contains("dep"))

如何根据具体条件过滤行?

保留“dest”以“FL”开始的数据行,并过滤掉其余的数据:

flights %>%
  filter(dest %>% str_detect("^FL"))

以下是部分输出数据:

看看上面的“目的地”一栏。所有值都以“FL”开头。

这是另一个过滤函数的例子。保留 month = 2 的行,过滤其余的行。

filter(flights, month == 2)

这行代码将返回月份值为 2 的数据集。

使用筛选并选择同一行代码中的两个

选择距离值大于 650 的起点、目的地、距离和 arr_time 列:

select(filter(flights, distance > 650), origin, dest, distance, arr_time)

使用管道也可以做到同样的事情:

flights %>%
  filter(distance > 650) %>%
  select(origin, dest, distance, arr_time)

在下面的例子中,我从航班数据集中选择航班和距离,并在航班号为 1545 的地方取平均距离。

flights %>%
  select(flight, distance) %>%
  filter(flight == 1545) %>%
  summarise(avg_dist = mean(distance))

使用现有列创建新列

我正在创建两个新列 arr_time_new 和 arr_time_old,并使用 mutate 操作将 arr_time 列加上和减去 20。在此之前,我使用过滤器删除空值。

flights %>%
  filter(!is.na(arr_time)) %>%
  mutate(arr_time_new = arr_time + 20,
         arr_time_old = arr_time -20)

变异的最后一个例子。在这里,我们将长距离飞行定义为距离大于 1000,并根据该定义计算有多少次飞行是长距离的。

flights %>%
  mutate(long_distance = (distance >= 1000)) %>%
  count(long_distance)

拉斯韦加斯到达延迟和西雅图准时到达计数:

flights %>%
  mutate(dest = case_when(
    (dest == 'LAS') & arr_delay > 20 ~ "Las Vegas arriavl - Delayes",
    (dest == "SEA") & arr_delay <= 20 ~ "Seattle arrival - On time"
  )) %>%
  count(dest)

替换人名并计数

起源被表示为 EWR、LGA 和 JFK。我们将用它们的全名替换它们,计算航班数量,并按排序顺序显示它们:

flights %>%
  mutate(origin = str_replace_all(origin, c(
    "^EWR$" = "Newark International",
    "^LGA$" = "LaGuaria Airport",
    "^JFK$" = "John F. Kennedy International"
  ))) %>%
  count(origin)

使用 Group By 函数汇总数据

我想知道每个月所有航班的平均距离。在这种情况下,我将对 month 列使用 group_by 函数,并使用 summarise on distance 列找到平均距离:

flights %>%
  group_by(month)%>%
  summarize(mean_distance = mean(distance, na.rm = TRUE))

Group by 函数可用于多个变量,也可用于汇总函数之外的函数。

这里有一个例子。这里还使用了另一个名为“排列”的函数来获得按平均距离排序的数据集。

flights %>%
  filter(!is.na(distance))%>%
  group_by(year, month) %>%
  summarize(mean_distance = mean(distance),
            min_distance = min(distance)) %>%
  arrange(mean_distance)

看,数据集是按照平均距离升序排列的。

计数功能

让我们按航班号数一下航班:

flights %>%
  count(flight)

统计每个起点的航班数量,并根据航班数量进行排序:

flights %>%
  count(origin, sort = TRUE)

让我们看看每个始发地-目的地组合有多少个航班:

flights %>%
  count(origin, dest)

制作航线栏,显示起点->终点组合,并统计每条航线的航班数;

flights %>%
  count(flight_path = str_c(origin, "->", dest), sort = TRUE)

传播功能

为了演示传播函数,我们先准备点东西。我为每个始发地-目的地组合计算平均 dep_delay:

flg = flights %>%
  filter(!is.na(dep_delay)) %>%
  group_by(origin, dest) %>%
  summarize(mean_dep_delay = mean(dep_delay))flg

下面是 spread 的用法,其中键是原点,值是 mean_dep_delay:

flg %>%
  spread(key = origin, value=mean_dep_delay)

看起来起源是传播。该数据集中有三个原点,它们现在成为了该扩展数据集的列。此处显示了每个目的地从每个起点的平均 dep_delay。

但问题是这个输出数据集中有一些空值。我们可以使用以下代码用零填充它们:

flights_spread = flg %>%
  spread(origin, mean_dep_delay, fill=0)

请自行运行这段代码并查看结果。

聚集功能

使用聚集函数,我将从“EWR”列到“LGA”列的 mean_dep_delay 值中收集值:

flights_spread %>%
  gather(key = "origin", value = "mean_dep_delay", EWR:LGA)

这篇文章就这么多了!

结论

使用 tidyverse 包可以做更多的事情。我试图给出一个涉及不同领域很多事情的概述。希望你能用它来做一些有趣的工作。

欢迎在推特上关注我,查看我的新 YouTube 频道

更多阅读

数据预处理概述:特征浓缩、自动特征选择

原文:https://towardsdatascience.com/an-overview-of-data-preprocessing-features-enrichment-automatic-feature-selection-60b0c12d75ad?source=collection_archive---------13-----------------------

实践教程

在一个视图中使用 python 实现的有用的要素工程方法

数据集应该适用于机器学习中训练的数据和算法做出的预测,以产生更成功的结果。查看数据集,可以发现有些要素比其他要素更重要,也就是说,它们对输出的影响更大。例如,当用数据集的对数值或其他数学运算(如平方根、指数运算)进行替换时,可以获得更好的结果。这里要区分的是选择适合模型和项目的数据预处理方法。这篇文章包含了不同的角度来看待数据集,以使算法更容易学习数据集。使用 python 应用程序,所有研究都变得更容易理解。

Table of Contents (TOC)
1\. Binning
2\. Polynomial & Interaction Features
3\. Non-Linear Transform
3.1\. Log Transform
3.2\. Square Root Transform
3.3\. Exponential Transform
3.4\. Box-cox Transform
3.5\. Reciprocal Transform
4\. Automatic Feature Selection
4.1\. Analysis of Variance (ANOVA)
4.2\. Model-Based Feature Selection
4.3\. Iterative Feature Selection

塔玛拉·加克在 Unsplash 上的照片

1.扔掉

在上一篇文章中,解释了以算法可以处理的方式对分类数据进行数字化的方法。宁滨用于将数值数据转换为分类数据,从而使模型更加灵活。考虑到数字数据,创建了由用户确定的箱数。所有数据都被填入这些范围并被重命名。现在让我们将宁滨应用于数据集中的年龄列。

import numpy as np
import pandas as pd
import matplotlib.pyplot as pltIN[1]
data=pd.read_csv('toy_dataset.csv')
data[['Age']].describe()
**OUT[2]**
**count 150000.000000
mean 44.950200
std 11.572486
min 25.000000
25% 35.000000
50% 45.000000
75% 55.000000
max 65.000000**IN[2]
def binnings(col, number_of_bins,labels):
    min_val = col.min()
    max_val = col.max()
    space = (max_val-min_val)/number_of_bins
    bin_borders=[]
    for i in range(number_of_bins+1):
        bin_values = min_val+space*i
        bin_borders.append(bin_values)
    bin_borderss = pd.cut(col, bins=bin_borders,labels=labels,include_lowest=True)
    return bin_borders,bin_borderss
IN[3]
labels=["young_1","young_2","young_3","young_4","young_5","young_6","young_7","young_8","young_9","young_10"]
binnings(data['Age'],10,labels)
**OUT[3]
([25.0, 29.0, 33.0, 37.0, 41.0, 45.0, 49.0, 53.0, 57.0, 61.0, 65.0],
 0         young_4
 1         young_8
 2         young_5
 3         young_4
 4         young_6
            ...   
 149995    young_6
 149996    young_1
 149997    young_1
 149998    young_1
 149999    young_3
 Name: Age, Length: 150000, dtype: category**

通过将数据集中的年龄范围等间隔分成 11 个部分,创建了 10 个箱。每个范围都被赋予选定的标签(young_1…..young_10)并作为列添加到数据集中。现在,如果我们想向数据集添加一个新列:

IN[4]
data['binned_age']= binnings(data['Age'],10,labels)
data

图一。OUT[4],图片由作者提供

现在让我们看看算法精度对我们创建的数据集的影响。

IN[5]
x = np.random.rand(100, 1)
y = 100 + 5 * x + np.random.randn(100, 1)
plt.scatter(x,y)
plt.xlabel('input')
plt.ylabel('output')

图二。OUT[5],图片由作者提供

IN[6] *without bin*
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=2021)
lr = LinearRegression()
lr.fit(x_train,y_train)
print("score=",lr.score(x_test,y_test))
**OUT[6]
score= 0.7120200116547827**

现在,让我们创建条块,并用条块测试新数据集。

IN[7] *create bins*
bins=np.linspace(x.min()-0.01,x.max()+0.01,9)
print(bins)
datas_to_bins = np.digitize(x, bins=bins,right=False)
np.unique(datas_to_bins)
**OUT[7]
[-0.00374919  0.12264801  0.24904522  0.37544243  0.50183963  0.62823684 0.75463404  0.88103125  1.00742846]
array([1, 2, 3, 4, 5, 6, 7, 8], dtype=int64)**IN[8] *with bins*
from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder(sparse=False)
x_binned=encoder.fit_transform(datas_to_bins)
x_binned_train,x_binned_test,y_binned_train,y_binned_test=train_test_split(x_binned,y,test_size=0.2,random_state=2021)
lr.fit(x_binned_train,y_binned_train)
print("score=",lr.score(x_binned_test,y_binned_test))
**OUT[8]
score= 0.7433952534198586**

可以看出,当分成 9 个部分并分组为 8 个箱时,测试数据集中的成功率从 71 增加到 74。

宁滨不会影响基于树的算法,因为它们使用拆分日期来训练模型。另一方面,它对于线性模型相当有效。

2.多项式和交互特征

可以对数据集进行的另一项改进是添加交互要素和多项式要素。如果我们考虑上一节中创建的数据集和宁滨运算,可以创建各种数学配置来增强这一点。例如,让我们以宁滨数据为例,该数据从数值变量转换为分类变量,然后用 OneHotEncoder 转换回数值变量。我们使用宁滨对通过添加 0 和 1 之间的 100 个随机数据而创建的数据集进行了分组,现在让我们将入库数据集与正常数据集合并并创建一个新数据集,或将入库数据集与正常数据集相乘并将其添加到入库数据集,或将入库数据集划分为正常数据集并将其添加到入库数据集。让我们看看所有这些配置的线性回归和得分。

IN[9]
x_combined=np.hstack([x_binned,x*x_binned])
print(x_binned.shape)
print(x.shape)
print(x_combined.shape)
x_combined_train,x_combined_test,y_combined_train,y_combined_test=train_test_split(x_combined,y,test_size=0.2,random_state=2021)
lr.fit(x_combined_train,y_combined_train)
print("score=",lr.score(x_combined_test,y_combined_test))
**OUT[9]
(100, 3)
(100, 1)
(100, 6)
score= 0.7910475179261578**IN[10]
x_combined2=np.hstack([x_binned,x])
x_combined2_train,x_combined2_test,y_combined2_train,y_combined2_test=train_test_split(x_combined2,y,test_size=0.2,random_state=2021)
lr.fit(x_combined2_train,y_combined2_train)
print("score=",lr.score(x_combined2_test,y_combined2_test))
**OUT[10]
score= 0.7203969392138159**IN[11]
x_combined3=np.hstack([x_binned,x_binned/x])
x_combined3_train,x_combined3_test,y_combined3_train,y_combined3_test=train_test_split(x_combined3,y,test_size=0.2,random_state=2021)
lr.fit(x_combined3_train,y_combined3_train)
print("score=",lr.score(x_combined3_test,y_combined3_test))
**OUT[11]
score= 0.7019604516773869**

丰富数据集的另一种方法是使用多项式要素。通过对多项式要素列中的数据进行指定次数的幂运算来扩展数据集。例如,当在多边形特征预处理中设置 4 度时,它很容易与 sklearn 库一起使用,4 个新特征将被添加为 x,x,x,x⁴.现在,让我们通过在同一数据集中添加多项式要素来观察结果。

IN[12]
from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=4, include_bias=False)
x_poly=poly.fit_transform(x)
poly.get_feature_names()
**OUT[12]
['x0', 'x0^2', 'x0^3', 'x0^4']**IN[13]
x_poly_train,x_poly_test,y_poly_train,y_poly_test=train_test_split(x_poly,y,test_size=0.2,random_state=2021)
lr.fit(x_poly_train,y_poly_train)
print("score=",lr.score(x_poly_test,y_poly_test))
**OUT[13]
score= 0.7459793178415801**

使用多项式和交互功能无法获得良好结果的原因是,数据集是随机创建的。这些方法在实际项目中经常使用,效率很高。

3.非线性变换

数据集中的数值呈高斯分布这一事实非常有利于模型学习和进行预测。它可以通过一些数学运算将数据集转换为高斯分布。这就像从另一个角度看同一数据集,就像在同一信号的频率分析中使用傅立叶变换一样。相同的 mat 操作应用于该列中的所有数据。现在,在我们看一下这些方法之前,让我们准备一下我们将使用的列和 qq_plot。

IN[14]
data=pd.read_csv('CarPrice_Assignment.csv')
data.columns
**OUT[14]
Index(['car_ID', 'symboling', 'CarName', 'fueltype', 'aspiration',
       'doornumber', 'carbody', 'drivewheel', 'enginelocation', 'wheelbase', 'carlength', 'carwidth', 'carheight', 'curbweight', 'enginetype', 'cylindernumber', 'enginesize', 'fuelsystem', 'boreratio', 'stroke','compressionratio', 'horsepower', 'peakrpm', 'citympg', 'highwaympg', 'price'],
      dtype='object')**IN[15]   *column we will use*
data['price'].describe()
**OUT[15]
count      205.000000
mean     13276.710571
std       7988.852332
min       5118.000000
25%       7788.000000
50%      10295.000000
75%      16503.000000
max      45400.000000
Name: price, dtype: float64**IN[16] *create histogram and qq plot*
import scipy.stats as stat
import pylab
def qq_plot(data,feature):
    plt.figure(figsize=(12,4))
    plt.subplot(1,2,1)
    data[feature].hist()
    plt.title('histogram')
    plt.subplot(1,2,2)
    stat.probplot(data[feature],dist='norm',plot=pylab)
    plt.show()IN[17]
qq_plot(data,'price')

图 3。输出[17],直方图(左)和概率图(右),图片由作者提供

3.1.对数变换

列中所有数据的对数。

IN[18]
data['log'] = np.log(data['price'])
qq_plot(data,'log')
OUT[18]

图 4。输出[18],对数变换,直方图(左)和概率图(右),作者图片

3.2.平方根变换

列中所有数据的平方根。

IN[19]
data['squareroot'] = data.price**(1/2)
qq_plot(data,'squareroot')

图 5。输出[19],平方根变换,直方图(左)和概率图(右),图片作者

3.3.指数变换

列中所有数据的用户选择的指数。

IN[20]
data['exp'] = data.price**(1/1.5)
qq_plot(data,'exp')

图 6。OUT[20],指数变换,直方图(左)和概率图(右),作者图片

3.4.Boxcox 变换

它根据等式应用于列。

Box-cox 方程,来源

IN[21]
data['boxcox'],parameters = stat.boxcox(data['price'])
print(parameters)
qq_plot(data,'price')

图 7。OUT[21],box-cox 变换,直方图(左)和概率图(右),图片由作者提供

3.5.互易变换

列中的所有数据除以 1。

IN[22]
data['reciprocal'] = 1/data.price
qq_plot(data,'reciprocal')

图 8。OUT[22],倒数变换,直方图(左)和概率图(右),作者图片

4.自动特征选择

在上一节中,我们丰富了我们的特征并扩展了我们的数据集,但是由于这个操作将创建一个复杂的数据集,它可能会导致过度拟合。现在,让我们研究一下根据高维数据集或复杂数据集的要素重要性减少要素的方法。

4.1.方差分析——ANOVA

每个特征与目标的关系被单独分析,并且以用户选择的速率与目标具有较少关系的特征被排除。这种特征-目标关系是根据 p 值确定的。首先消除具有高 p 值的要素。现在让我们导入乳腺癌数据集,然后应用线性回归和决策树算法。

IN[22]
from sklearn.datasets import load_breast_cancer
data=load_breast_cancer()
x=data.data
y=data.targetIN[23]
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=2021)
lr = LinearRegression()
lr.fit(x_train,y_train)
print("score=",lr.score(x_test,y_test))
**OUT[23]
score= 0.7494572559981934**IN[24]
from sklearn.tree import DecisionTreeRegressor
dt = DecisionTreeRegressor(random_state=42)
dt.fit(x_train, y_train)
print("score on test set: ", dt.score(x_test, y_test))
**OUT[24]
score on test set:  0.8115079365079365**

添加决策树回归器是为了查看特征的重要性:

IN[25]
print(dt.feature_importances_)
**OUT[25]
[0\.         0.01755418 0\.         0\.         0.01690402 0.00845201
 0.01173891 0\.         0\.         0.00375645 0.00725021 0.01126935
 0.00907901 0.00991574 0.00223873 0\.         0\.         0.
 0\.         0\.         0.00782594 0.0397066  0\.         0.71559469
 0\.         0\.         0.01979559 0.11891856 0\.         0\.        ]**IN[26]
np.argsort(dt.feature_importances_)
**OUT[26]
array([ 0, 25, 24, 22, 19, 18, 17, 16, 15, 28, 29,  2,  3,  8,  7, 14,  9, 10, 20,  5, 12, 13, 11,  6,  4,  1, 26, 21, 27, 23], dtype=int64)**

现在让我们应用方差分析:

IN[27]
from sklearn.feature_selection import SelectPercentile
select = SelectPercentile(percentile=30)
select.fit(x_train, y_train)
# transform training set
x_train_selected = select.transform(x_train)
print("X_train.shape: {}".format(x_train.shape))
print("X_train_selected.shape: {}".format(x_train_selected.shape))
**OUT[27]
X_train.shape: (455, 30)
X_train_selected.shape: (455, 9)**

百分比设置为 30,以便选择 30%的特征(9)。

具有选定特征的线性回归:

IN[28]
x_test_selected = select.transform(x_test)
lr.fit(x_train_selected, y_train)
print("Score with only selected features: {:.3f}".format(
lr.score(x_test_selected, y_test)))
**OUT[28]
Score with only selected features: 0.712**

仅用 9 个特征获得 0.712,而用 30 个特征获得 0.749。现在让我们看看 SelectPercentile 选择了哪些功能:

IN[29]
mask = select.get_support()
print(mask)
**OUT[29]
[ True False  True  True False False  True  True False False False False False False False False False False False False  True False  True True False False False  True False False]**

4.2.基于模型的特征选择

它一次评估所有特性,并根据它们的相互作用选择特性。它根据用户设置的阈值选择重要性较高的内容。例如,如果选择阈值=中等,则选择 50%的特征。Sklearn 中阈值的默认值是均值。

IN[30]
from sklearn.feature_selection import SelectFromModel
selection = SelectFromModel(LinearRegression(), threshold="median")
selection.fit(x_train, y_train)
x_train_select = selection.transform(x_train)
print("X_train.shape:",x_train.shape)
print("X_train_l1.shape:",x_train_select.shape)
**OUT[30]
X_train.shape: (455, 30)
X_train_l1.shape: (455, 15)**IN[31]
mask = select.get_support()
print(mask)
**OUT[31]
[False False False False  True  True  True  True False  True False False False False  True  True  True  True  True  True False False False False True False False  True  True  True]**

具有选定特征的线性回归:

IN[32]
x_test_select = selection.transform(x_test)
print(lr.fit(x_train_select, y_train).score(x_test_select, y_test))
**OUT[32]
0.6919232554797755**

4.3.迭代特征选择

它根据某个阈值以 2 种方式工作:第一种从 0 个特征开始,根据其重要性继续添加特征,直到达到阈值。第二个选择所有特征并逐个消除它们,直到阈值。顾名思义,递归特征消除(RFE) 选择所有特征,消除特征,直到指定条件。

IN[33]
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
select = RFE(LogisticRegression(),
n_features_to_select=20)
select.fit(x_train, y_train)
# visualize the selected features:
mask = select.get_support()
print(mask)
**OUT[33]
[ True  True False False  True  True  True  True  True False  True  True True  True False False False False False False  True  True  True False True  True  True  True  True  True]**

条件设置为 20 个特征,从 30 个特征开始,一个接一个地消除特征,直到剩下 20 个特征。

IN[34]
x_train_rfe= select.transform(x_train)
x_test_rfe= select.transform(x_test)
lr.fit(x_train_rfe, y_train)
print("score:",lr.score(x_test_rfe, y_test))
**OUT[34]
score: 0.7140632795679898**

回到指引点击这里。

https://ibrahimkovan.medium.com/machine-learning-guideline-959da5c6f73d

深度学习概述——从历史到基础

原文:https://towardsdatascience.com/an-overview-of-deep-learning-from-history-to-fundamentals-f7117b2d0d37?source=collection_archive---------4-----------------------

世贸中心遗址

一本学习深度学习本质的剧本,重点是卷积神经网络

照片由雷蒙·克拉文斯在 Unsplash 拍摄

我最近为那些想成为数据科学家的人教授了一门关于机器学习 101 的迷你课程。其中一个模块是关于深度学习的。我发现许多新手对这个话题感到困惑,主要是因为它经常被教授许多复杂的内容。在这篇文章中,我的目标是描述它足够简单,但不要太简单。希望有帮助!

本文分为以下四个部分:

  • 什么是神经网络?
  • 什么是深度学习?
  • 如何搭建一个简单的深度学习架构?
  • 如何训练一个深度学习模型?

什么是神经网络?

神经网络是一种受生物神经网络启发的计算模型,它在人脑中处理信息。神经网络由一组按层(输入、隐藏和输出)组织的人工神经元组成。这些人工神经元由突触连接,这些突触只是加权值。

—构建模块是什么?

人工神经元是具有特定数学运算的计算元件。一个神经元接受它的输入(布尔或实数),并在对输入应用预定义的操作后,通过激活函数将结果传递给其他神经元。激活函数是每个节点的一部分,它将线性函数转换为非线性函数。基本上,它决定了一个神经元是否应该放电。激活函数可以是不同的数学函数,例如 Step、Sigmoid 和 ReLU。

图 1:生物神经元(上)和人工神经元(下)。该图像已获得 Shutterstock 的许可。

一个普通的神经元(也称为感知器神经元)接受包括偏差在内的输入,并将其乘以相关的权重,然后将总和传递给阶跃函数。

—如何训练一个神经网络?

训练神经网络是指计算(或找到)网络中的权重以最小化目标函数(或损失函数)的过程。您可以将神经网络中的权重视为多项式函数(如ax^2+b*x+c)中的参数,其中有两个主要区别。神经网络是具有高度和潜在非线性性能的多项式函数。在这里,高度意味着需要时参数的数量可以超过数百万。

有各种算法来训练神经网络,反向传播(backpropagation)是其中之一。简而言之,反向传播是一种在训练阶段使用梯度下降技术来计算神经网络中的权重的算法。在这种方法中,计算输出与期望值相比的误差,并成比例地(即,基于当前权重)反向传播以更新网络权重。网络权重基于学习速率迭代更新,直到收敛。

推荐看视频了解更多这种方法。YouTube 频道有一个描述这个话题的最好的可视化工具。

反向传播到底在做什么?—3 蓝色 1 棕色

要训练神经网络,您必须知道以下问题的答案。在开始实现一个示例项目之前,您可能不会理解它们的重要性。

  • 如何初始化权重?
  • 停止的标准是什么?
  • 算法不收敛怎么办?
  • 增加网络的复杂性有帮助吗?

最后一件事。如果你想了解学习率、激活函数或架构等配置参数如何影响神经网络的结果,我强烈建议查看 TensorFlow 创建的名为 Playground 的交互式演示。太美了,太有见地了!

https://playground.tensorflow.org/#activation=tanh&batchSize=10&dataset=circle&regDataset=reg-plane&learningRate=0.03&regularizationRate=0&noise=0&networkShape=4,2&seed=0.24016&showTestData=false&discretize=false&percTrainData=50&x=true&y=true&xTimesY=false&xSquared=false&ySquared=false&cosX=false&sinX=false&cosY=false&sinY=false&collectStats=false&problem=classification&initZero=false&hideText=false

什么是深度学习?

深度学习是一系列基于深度神经网络(具有许多隐藏层的神经网络)的特殊架构的机器学习方法,这些深度神经网络可以同时进行特征提取分类,并且只需很少的人力。这种特殊的结构比简单完全连接的神经网络中的层更高级。这些特殊的架构大多建立在一个名为“胶囊的概念之上。胶囊是每一层中的一组神经元,它们进行大量内部计算,并输出表示数据属性(如卷积)的压缩结果。你可以阅读更多关于卷积神经网络的内容

—一个成功的故事:AlphaGo

由 Deepmind 创建的 AlphaGo 项目是深度学习的成功案例之一。正如 Deepmind 所说:“AlphaGo 是第一个打败围棋世界冠军的计算机程序”。首先,我来描述一下围棋为什么特别。

围棋是人工智能瞄准的最具挑战性的经典游戏。为什么?主要是因为玩家可以选择的移动数量。按此篇、T3 在前 2 步棋后,围棋中大概有 13 万步棋。这个数字是国际象棋中 400 种可能的走法。你可以看到 Go 中的搜索空间是无可争议的广阔。当搜索空间极其广阔时,深度学习可能是一个不错的选择。****

深度学习是瞄准围棋的正确方法的另一个原因是植根于围棋的玩法。如果你问围棋手他们是如何决定一步棋的,他们通常会告诉你感觉很对。在这些你不能定义特征的场景中,你不能使用经典的机器学习算法。当确定有用的特征集不可行时,深度学习可能是一个不错的选择。

什么是卷积神经网络?

卷积神经网络(或 CNN)是一类深度学习架构,通常用于分析图像,如图像分类、对象检测和视频动作识别。一般来说,卷积神经网络被设计用于任何在其结构中具有某种空间不变性的数据,例如人脸或语音识别。空间不变性意味着,例如,图像左上角的猫耳与图像右下角的猫耳具有相同的特征。CNN 建立在下面描述的两个主要构件上。

  • 卷积 —细胞神经网络是空间不变的,因为它们建立在卷积算子之上。卷积是一种数学运算,它对两个函数(信号)的乘积进行积分,其中一个信号被翻转(如果需要)。例如,在过去,卷积运算符被用于计算两个信号之间的相关性或寻找信号中的模式。该操作符对于视觉数据中的特征提取非常有效。过去几年里,计算机视觉领域取得的许多进步,部分归功于卷积神经网络。
  • 池化—CNN 中的另一个构件是池化层。它的功能是逐渐减小数据的空间大小,以减小网络大小和算法对输入中要素精确位置的敏感度。网络规模转化为在训练阶段必须计算的权重数量。

有时,您还需要在输入图像的边界周围添加带有pixel_intensity=0 的额外像素,以增加有效尺寸。这有助于在应用卷积层后保持图像大小固定。这个过程叫做填充

图 2:Alex net——图片获得了 Shutterstock 的许可。

有哪些特殊的架构?

  • AlexNet — AlexNet 是卷积神经网络的成功实现,在 2012 年赢得了 ImageNet 大规模视觉识别挑战赛( ILSVRC )。该架构已由 Alex Krizhevsky、Ilya Sutskever、Geoffrey Hinton 在 NeurIPS 2012 上发表(图 2)。在这种架构中,输入是大小为 256×256 的 RGB 图像,这些图像被随机裁剪成大小为 224×224 的图像。该架构包含 65 万个神经元和 6000 万个参数。此外,在两个 GTX 580 3GB GPU 上训练需要 5-6 天。它由 5 个卷积层和 3 个全连接层组成。他们首次使用整流线性单元(ReLUs)作为激活函数。
  • VGG16 — 提高深度神经网络性能的标准方法是增加深度。VGG-16 是由牛津大学视觉几何小组的人发明的。该架构有 13 个卷积层和 3 个全连接层。他们还使用 ReLU 激活功能作为 AlexNet 的传统。与 AlexNet 相比,该网络堆叠了更多层,并使用了更小尺寸的过滤器(2×2 和 3×3)。它由 138M 参数组成。
  • ResNet50 — 随着网络深度的增加,精度会饱和,然后迅速下降,这主要是因为我们无法对其进行适当的训练。微软研究院用 ResNet50 解决了这个问题——使用跳过(或快捷方式)连接,同时构建更深层次的模型。更深的 CNN(高达 152 层)而不影响模型的泛化。这是一个好主意…

如何构建一个简单的深度学习架构

— Keras

Keras 是一个带有 Python 接口的高级神经网络库,可以在主要的科学计算框架上运行,如 TensorFlow(由 Google 创建)或 CNTK(由微软创建)。与 Pytorch 相比,工程师通常更喜欢提供快速开发的 Keras。您可以使用下面的 Kears 找到如何建立一个类似 VGG 的卷积神经网络。要了解更多关于如何使用 Keras 建立深度学习模型的信息,可以查看原始的文档。

**from** keras.models **import** Sequential
**from** keras.layers **import** Dense, Dropout, Flatten
**from** keras.layers **import** Conv2D, MaxPooling2D
**from** keras.optimizers **import** SGDmodel = **Sequential**()
model.add(**Conv2D**(32, (3, 3), **activation**='relu', **input_shape**=(100, 100, 3)))
model.add(**Conv2D**(32, (3, 3), **activation**='relu'))
model.add(**MaxPooling2D**(**pool_size**=(2, 2)))
model.add(**Dropout**(0.25))model.add(**Conv2D**(64, (3, 3), **activation**='relu'))
model.add(**Conv2D**(64, (3, 3), **activation**='relu'))
model.add(**MaxPooling2D**(**pool_size**=(2, 2)))
model.add(**Dropout**(0.25))model.add(**Flatten**())
model.add(**Dense**(256, **activation**='relu'))
model.add(**Dropout**(0.5))
model.add(**Dense**(10, **activation**='softmax'))**sgd** = **SGD**(**lr**=0.01, **decay**=1e-6, **momentum**=0.9, **nesterov**=True)
model.compile(**loss**='categorical_crossentropy', **optimizer**=sgd)model.fit(x_train, y_train, batch_size=32, epochs=10)

— PyTorch

PyTorch 是一个基于 python 的低级神经网络库,构建于脸书科学计算框架(Torch)之上。其工作流程类似于 Python 科学计算库(Numpy)。Pytorch 具有高度可配置性,与不需要复杂架构或特殊图层操作的开发者相比,更受研究人员的欢迎。您可以在下面找到如何使用 PyTorch 构建卷积神经网络。要了解更多关于如何使用 PyTorch 构建深度学习模型的信息,可以查看原始的文档。

**import** torch.nn **as** nn
**import** torch.nn.functional **as** F

**class** **Net(nn.Module):**
    **def** __init__**(**self**):**
        super**().**__init__**()**
        self**.conv1** **=** **nn.Conv2d(**3**,** 6**,** 5**)**
        self**.pool** **=** **nn.MaxPool2d(**2**,** 2**)**
        self**.conv2** **=** **nn.Conv2d(**6**,** 16**,** 5**)**
        self**.fc1** **=** **nn.Linear(**16 ***** 5 ***** 5**,** 120**)**
        self**.fc2** **=** **nn.Linear(**120**,** 84**)**
        self**.fc3** **=** **nn.Linear(**84**,** 10**)**

    **def** **forward(**self**,** **x):**
        **x** **=** self**.pool(F.relu(**self**.conv1(x)))**
        **x** **=** self**.pool(F.relu(**self**.conv2(x)))**
        **x** **=** **torch.flatten(x,** 1**)** 
        **x** **=** **F.relu(**self**.fc1(x))**
        **x** **=** **F.relu(**self**.fc2(x))**
        **x** **=** self**.fc3(x)**
        **return** **x**

**net** **=** **Net()**

如何训练一个深度学习模型?

在本文中不可能解释关于训练神经网络的所有内容。在这里,我想阐明一些最重要的话题。

—定义

如上所述,训练神经网络是指计算网络中的权重以最小化目标函数的过程。这是一个经典的优化问题,你必须搜索使损失函数最小化的最优权重(或参数)集。搜索方法的功效决定了训练过程的速度结果

思考的食粮— 在机器学习算法中,我们选择一个度量(例如,准确性)来评估模型;然而,我们优化了一个不同的目标函数,并“希望”最小化它的值将改进我们关心的度量。那么,我们能做些什么来确保达到预期的要求呢?

—实施

一般来说,要实现一个搜索方法,必须对以下问题有答案:(1)“如何确定搜索方向?”以及(2)“如何确定搜索步骤?”。

如上所述,梯度下降技术已被用于训练神经网络以指导搜索过程。搜索方向由梯度算子决定,搜索步长由超参数𝝺决定,也称为学习率。简而言之,梯度下降技术中的更新机制如下:xₘ=xₙ -𝝺* f(xₙ).经典的梯度下降技术不能简单地用于深度学习技术,在深度学习技术中通常存在大量的权重(参数)和大量的数据点。⛔

🚀随机梯度下降 (SGD)是梯度下降技术的一种变体,对深度学习模型更有效。与使用数据计算误差相反,该方法计算误差并更新训练数据集中每个数据点的模型。SGD 的搜索速度更快,并且提供更频繁的型号更新。另一方面,每次运行的 SGD 结果不同,与标准技术相比,它的收敛更慢

除了只使用当前步骤的梯度来指导搜索,我们可以使用过去步骤的梯度知道最近的步骤更重要。这在优化上下文中被称为动量。因此,我们可以,例如,使用梯度步骤的指数平均值来进行更有效的搜索过程。查看下面的文章,了解更多关于动量的信息。

https://distill.pub/2017/momentum/

SGD 不管用怎么办?

我们有其他技术来解决优化问题,如 AdaGradAdam (自适应矩估计)。这些方法是梯度下降优化的变体,其自适应地改变学习速率以确保具有更有效的搜索过程。简而言之,对于搜索空间中的每个方向以及在时间中的每个时刻,学习率或搜索步长可以不同。这里可以阅读更多。如果你想学习如何在现实世界中使用这些技术,可以看看 Keras 官方文档。

感谢阅读!

如果你喜欢这个帖子,想支持我…

  • 跟我上
  • 亚马逊 上查看我的书!
  • 成为 中的一员
  • 连接上Linkedin
  • 关注我 推特

https://pedram-ataee.medium.com/membership

Julia 算子概述

原文:https://towardsdatascience.com/an-overview-of-julias-operators-3db925db38d1?source=collection_archive---------27-----------------------

快速浏览 Julia 编程语言中的所有操作符及其用法

https://unsplash.com/photos/Mmk63saBhDM

介绍

对于那些对朱丽亚感兴趣的人来说,进入朱丽亚的世界可能会感到困惑和恐惧。这不仅适用于 Julia 通常使用的方法,利用不同的编程概念,如多重分派,而且适用于更基本的数学函数,如加法或减法。

当学习一门新的编程语言时,最重要的事情之一就是学习这门语言中的操作符。Julia 有一些非常独特的操作符,它们不一定在整个计算机编程范围内都是标准化的。记住这一点,让我们看看这些操作符,以及它们在语言中的作用。

算术运算符

Julia 中最重要和最基本的操作符是算术操作符。这些运算符用于 Julia 中的断言和数学表达式,执行与用于表示 Julia 中运算符的字符相关的精确运算。

断言操作符

断言操作符是大多数程序员可能都熟悉的一种操作符。这由=符号表示,通常用于将变量别名设置为某种类型。

一元加号

一元加号是加法运算符的典型用法,只放在一个变量上。这将执行标识操作。恒等运算是表示给定数量和另一数量的组合的运算,其中该数量保持不变。例如,加法恒等式是 0,因为 x + 0 = 0 + x = x。这在 Julia 中表示为一元运算符,这意味着它只用于一个参数。我们可以在变量调用之前使用+ char 来调用它,就像这样:

+x

一元减操作

一元减号运算符的表示方式与一元加号运算符相同。然而,这个操作符执行的是完全不同的运算。该运算符用于将值映射到它们的加法逆运算。这基本上意味着它否定了这个数。换句话说,在《朱莉娅》中,我们可以用一元减号来表示否定——我认为这很自然也很酷。这真的符合他们“就像在报纸上一样”的方法论,我认为这很酷。

-x

二进制加号

二进制加法执行普通加法。

x + y

二进制减

二进制减执行正常的减法。

x - y

时间运算符

乘以运算符用于执行普通乘法。

x * y

除法算符

谁能想到呢?除法运算符是用来执行除法的!

x / y

整数除法运算符

该运算符将执行除法,但将始终返回一个四舍五入的整数:

x ÷ y

我认为这个很没用,因为我不知道按什么 numpad 键来创建这个符号,你可以简单地使用 round()方法来将一个浮点数转换成一个整数。

反向除法

反向除法运算符将第二个参数除以第一个参数,而不是相反。

x \ y

力量

Julia 中的幂运算符是^,每当我使用 Python 并试图调用 Xor 运算符^,以为它会给我一个指数时,这总是让我感到困惑。

x ^ 2

剩余物

余数运算符将返回两个参数相除的余数。

x % y

布尔运算符

虽然不是很令人兴奋,布尔运算符也很重要。正如所料,这些操作符专门用于 bool 类型。坦率地说,我知道最有可能知道我们到目前为止所看到的所有运算符,但是要获得朱利安运算符的真正内容,我们必须首先通过相对基本的东西。

否认

否定运算符是另一个一元运算符,它将给定的布尔值改为相反的值。用一个解释点来表示。

!x

布尔 and 操作符是直接从 Julia 的 Bash 中提取出来的。它被表示为&&。

x && y

或者

另一个连接操作符是 or 操作符,用||表示。

按位运算符

在计算机程序设计中,按位操作是在位串、位数组或二进制数的单个位的层次上进行操作。这通常意味着操作符用于改变操作符中的单个位。

按位非

按位 not 运算符用~表示,是一元运算符。

~100

按位 and

按位 and 运算符用“与”符号表示,是一种二元运算符。

x & y

按位或

按位“或”运算符用一个管道表示,也是一个二元运算符。

x | y

按位异或

按位异或用⊻表示,但是你也可以使用 xor()方法,这是我通常做的。

x ⊻ y

逻辑右移

逻辑右移运算符用三个向右箭头表示,是一个二元运算符。

x >>> y

算术右移

算术右移只用两个右箭头表示,也是一个二元运算符。

x >> y

逻辑或算术左移

逻辑和算术左移组合成两个向左的箭头。这当然也是一个二元运算符。

x << y

更新运算符

Julia 语言中的每个二进制位或算术运算符都有一个更新的对应部分。这些运算符用于用新类型更新变量别名。我们刚刚讨论的操作符的更新版本是

+=  -=  *=  /=  \=  ÷=  %=  ^=  &=  |=  ⊻=  >>>=  >>=  <<=

矢量化运算符

基本运算符的最后一种形式是任何二进制算术运算的矢量化版本。这由操作符前面的点表示。这些当然意味着用在可迭代的向量或数组上。这些运算符的矢量化版本如下:

.+ .- .* ./ .\ .% .^

比较运算符

比较运算符用于根据某种条件从两个参数返回布尔类型。这个条件可以是数字、等式,甚至更多。

等式运算符

如果值相等,相等运算符返回 true。

x == y

不等式算子

如果值不相等,不等式运算符返回 true。

x != y

小于运算符

如果第一个参数小于第二个参数,则小于运算符返回 true。

x < y

大于运算符

如果第二个参数小于第一个参数,则大于运算符返回 true。

x > y

或等于运算符

我们可以通过简单地在运算符后添加一个等号,使小于和大于运算符都变成小于或等于和大于或等于运算符。

x >= y
y <= x

子类型运算符

不幸的是,这个列表中最令人兴奋的是子类型操作符。子类型运算符有两种用途。它是一个接受类型的二元运算符。该运算符用<:/>

abstract type AbstractTuber end
struct Potato <: AbstractTuber data::Array end

该运算符也可用于返回用于比较的布尔值,这也是它出现在本节中的原因:

x <: y

我们可以假设这个操作符的意思是“是的子类型。”如果您想了解更多关于 Julia 中子类型的一般概念,以及这个操作符在 Julia 类型层次结构中的用法,我写了一整篇文章,您可以在这里查看:

结论

我决定写这篇文章,因为 Julia 语言在它的领域中与许多其他竞争语言有一些显著的不同。当从一种语言切换到另一种语言并使用不同的操作符时,经常会感到困惑,此外,对于新程序员来说,了解他们语言中的所有操作符可能是件好事。虽然写起来很无聊,但我确实认为它可能对任何打算学习这门语言的人有所帮助。非常感谢你阅读我的文章,我很感激!

AWS 上的 ML 概述

原文:https://towardsdatascience.com/an-overview-of-ml-on-aws-d3c0ada16dac?source=collection_archive---------27-----------------------

从自动人工智能服务到构建定制深度学习模型的全面的 ML 产品资源集

图片来自 Unsplash

当你开始在本地笔记本或环境之外看待 ML 时,你就开始进入云计算的世界。像 AWS、Azure 和 GCP 这样的提供商正在他们各自的云中提供一套令人难以置信的 ML 服务,可以帮助你将 ML 带到生产级规模。更令人难以置信的是,对于所有程序员来说,ML 正在慢慢地民主化。随着人工智能的发展,算法背后的许多理论和知识都被抽象成了 AutoML 服务,使得没有人工智能经验的开发人员能够启动由尖端人工智能驱动的应用程序。这些 Auto-AI 服务涵盖了不同 ML 领域种类,例如 NLP计算机视觉时间序列预测、等等。尽管如此,仍然需要使用 TensorFlow、PyTorch、SKLearn 等框架的定制模型。AWS 提供各种各样的服务,这些服务都属于建筑风格。在本文中,我们将探索 AWS 中这两个不同领域提供的大量服务。我还将附上这些服务所有代码样本文档和其他资源

目录

1.基于 AutoML/API 的 ML(需要较低的 ML 理论知识)

  • 领悟
  • 重新认识
  • 个性化
  • 翻译
  • 转录
  • 预测
  • 其他

2.AWS SageMaker(更适合数据科学家/定制模型构建)

  • 简介
  • 管道
  • 亚马逊算法
  • SageMaker 上的定制型号

3.结论

1.基于自动人工智能/API 的 ML(需要较低的 ML 理论知识)

以下服务属于基于 AWS ML API 的服务。在这里,您不必像我们传统的做法那样构建定制的 ML 模型,而是可以通过一个 AWS SDKbot O3(Python SDK)以编程方式访问这些服务,以调用这些高级 API 的,并将它们集成到您的应用程序中。

包含

理解是亚马逊的主要自然语言处理服务,它自动化了许多流行的自然语言处理任务,如情感分析、命名实体识别和主题建模。understand 还在自定义分类中增加了另一层,您可以通过 ML powering understand 提供数据来训练自定义模型。理解医疗是理解的扩展,但是是为处理临床文本而定制的,例如医生笔记和测试结果。

资源:

  • Boto3 文档
  • 情感分析&实体提取示例
  • 医学 NER 的例子
  • Python 代码示例

重新认识

Rekognition 是亚马逊的主要自动计算机视觉服务。Rekognition 具有多种任务功能,例如:人脸检测、文本检测、自定义标签等。定制标签特别允许您为您正在尝试识别的特定用例/对象或项目提供/训练定制数据集。

资源:

  • Boto3 文档
  • 带认知的情感检测
  • Python 代码示例

使个性化

亚马逊个性化帮助用户建立实时个性化推荐。个性化使您可以带来一个自定义数据集,您可以像传统方式一样对其进行预处理和处理。您以个性化可以理解的特定格式提供模式和数据,它创建一个配方:个性化算法,提供基于常见用例的训练模型。创建配方后,Personalize 会创建一个解决方案,让您定制培训。在此之后部署您的个性化模型,您使用该解决方案创建一个称为个性化活动的东西,用于实时推荐。这些步骤被清晰地抽象出来,在构建模型之前,理解个性化的一般流程和术语是非常重要的。

资源:

  • Boto3 文档
  • 配方、解决方案、活动说明
  • Python 代码示例

翻译

亚马逊翻译是一款支持 71 种语言进行翻译的神经机器翻译工具。翻译还支持基于您的用例的实时和批量翻译。Translate 的另一个巧妙之处是可以附加的自定义术语。如果您需要翻译硬编码的特定单词或实体,您可以将它们插入一个自定义词典(例如:csv 文件), Translate 会将其添加到模型翻译中。

资源:

  • Boto3 文档
  • Python 代码示例

转录

Amazon Transcribe 使用自动语音识别(ASR)为他们的应用程序添加了语音到文本的功能。转录支持异步和实时转录。与“理解”类似,还有一个被称为亚马逊转录医疗的医疗扩展。转录医学符合 HIPAA 标准,您可以通过提供自定义医学词汇来提高转录准确性。

资源:

  • Boto3 文档
  • 实时流示例(Java)
  • Python 代码示例

预报

Amazon Forecast 使用 ML 来处理时间序列数据和其他功能来建立预测模型。您可以将任何历史数据与您拥有的其他相关数据集结合起来,并上传到 Forecast,Forecast 将自动分析这些数据以识别重要的属性,并选择合适的预测算法(也可以由您选择),它可以为您创建预测文件以集成到您的应用程序中。为了比较预测提供的算法,请点击这里查看文档。

资源:

  • Boto3 文档
  • Python 代码示例

其他人

总结一下自动人工智能的部分,有很多其他的自动人工智能服务,你也可以在你的空闲时间探索。我已经列出了 AWS 的一些其他产品以及它们的基本功能。

  • Amazon Textract :处理基于大量文本的文档数据以提取洞察力(例如:OCR)
  • 亚马逊肯德拉:搜索服务
  • 亚马逊波利:文本到语音服务
  • 亚马逊 Lex :聊天机器人服务(对话界面)
  • 其他服务

2.AWS SageMaker

介绍

SageMaker 是一个覆盖整个 ML 生命周期的巨大服务,所以在未来我会看到更多的文章和资源来深入研究它的每一个功能。在这篇文章中,我们将探索它对构建 ML 管道的特性的介绍,它涵盖了 SageMaker 的 MLOps 部分。我们将介绍提供的内置算法/模型,以及关于如何将定制模型引入框架(如 TensorFlow)的资源,涉及 SageMaker 的培训/托管部分。 SageMaker核心上工作的方式是通过 笔记本实例 ,它们是计算实例,让你在实例上的传统 Jupyter 笔记本/实验室设置中构建、训练和部署 ML 模型。

SageMaker 管道公司

ML 生命周期的很大一部分是创建和自动化端到端的管道。SageMaker Pipelines 是一个 CI/CD 服务,帮助创建和自动化 ML 工作流程从预处理到培训等等。在 Pipelines 中,您可以使用 SageMaker Python SDK 来定义您的工作流,以定义各个步骤。下面显示了一个来自管道示例的示例工作流。

管道示例工作流程(截图来自文档

在 Pipeline 中,您可以与各种其他 SageMaker 功能进行交互,例如功能存储、模型注册、培训和部署,从而帮助您完成 ML 端到端生命周期。

资源:

  • 管道车间
  • 管道示例
  • 使用 Python SDK 的 SageMaker 管道

亚马逊算法

对于实际的模型训练和部署,SageMaker 提供了一套自己开发的内置算法。这些内置算法虽然类似于我们讨论的 Auto-AI 服务,但为我们添加预处理代码或在您正在构建的整体模型中引入更多库/包提供了更多的灵活性。关于这些内置算法或您带来的任何自定义算法,需要注意的一个关键特性是,SageMaker 上的所有东西都是通过 Docker 容器化的 。为了访问这些内置算法,你需要提取它们的图像,如果是定制模型,你需要提供一个 Docker 图像。对于参考资料,我附上了内置算法及其功能的列表,以及 SageMaker 上的容器入门,以了解不同的部署选项。

资源

  • 内置算法
  • 带 SageMaker 的码头工人

SageMaker 上的定制模型

SageMaker 提供的最大灵活性是在你选择的框架** 中带来你自己的模型/容器。SageMaker 提供了内置的 Docker 图像,您可以为 TensorFlow、PyTorch 和 SkLearn 等流行的框架提取这些图像。您可以通过提供自己的定制训练/推理模型代码来构建这些图像。这种方法被称为自带模型/脚本模式。为了获得训练/推理的最大灵活性,有一种称为自带容器 的东西,如果您正在使用 AWS 不提供的框架,您可以在其中提供一个定制的 Docker 容器,其中包含您的模型的所有依赖项。SageMaker 中有各种不同的培训/托管选项,您可以根据自己的计算/模型需求进行选择。**

资源:

  • 脚本模式
  • 脚本模式样本
  • 自带容器
  • SageMaker 上的自定义 TensorFlow2 示例

结论

本文概述了 AWS 提供的一些 ML 功能。每个服务都有自己的大量资源和主题来帮助优化和构建令人难以置信的 ML 应用程序。您可以将其中许多与其他 AWS 服务结合使用,以复杂的方式解决极其复杂的问题。

我希望这篇文章对 AWS 必须提供的 ML 功能/服务的介绍和概述有所帮助。我计划在未来撰写并提供更多关于这些服务和 SageMaker 功能的深入/具体的例子,所以请确保继续关注媒体以跟上我的工作。如果你对 ML & AWS 感兴趣,请随时在评论中留下任何反馈或通过 Linkedln 与我联系。感谢您的阅读!

自然语言处理应用综述

原文:https://towardsdatascience.com/an-overview-of-natural-language-processing-caa471819e06?source=collection_archive---------52-----------------------

用深度学习处理文本的实用方法,已解释

自然语言处理(NLP)是人工智能的一个分支,包括一个广泛的软件领域,旨在推理和处理文本数据。NLP 技术正在快速发展,很难找出哪种 NLP 技术对行业影响最大。

在本帖中,我们将介绍和讨论自然语言处理技术,这种技术已经在现实生活中广泛采用和使用。

让我们开始吧。

自然语言处理简史

自然语言处理领域可以追溯到艾伦·图灵(Alan Turing)和图灵测试——能够如此有效地教会计算机用自然语言对话,以至于它会被误认为是人类吗?因此,NLP(以及计算机视觉)是现代人工智能研究的核心。

基于规则的自然语言处理

NLP 经历了两个不同的阶段。第一种通常被称为“优秀的老式人工智能”,其中算法被编写为使用逻辑规则解析语言。这些技术导致了 80 年代、90 年代和 2000 年代的一系列 NLP 技术,包括知识库、基于规则的推理机和语法分析器。

机器学习

最近,机器学习技术在 NLP 中的引入导致了新技术的寒武纪大爆发,其中使用大型训练语料库来监督深度学习模型,以创建围绕语言的灵活算法。本文将关注自然语言处理中的机器学习方法,包括:

  • 文本分类
  • 槽提取
  • 对话系统
  • 文本翻译

可以构建不属于这些更完善的技术的自定义 NLP 模型,但是考虑您的任务是否适合这些类别之一或者这些 NLP 技术的集合总是有用的,因为这将允许您为您的项目利用大量开源工作。

文本分类

自然语言处理中的许多任务归结为对文本进行分类的任务。在文本分类中,给机器学习算法一个类别选择,它可以放置一段给定的文本。

文本分类示例

一个示例文本分类预测

例如,如果我们正在训练一个机器人来对旅行社的用户请求进行分类,我们可以让机器人将短语“请为我在台北预订两晚的酒店住宿”放入“新预订”类别中。文本分类算法的任务是决定该分类优于其他可能的类别。

文本分类训练

为了训练一个文本分类器,你需要收集一个相似例子的数据集来展示你的机器学习算法。这个数据集将通过一个训练循环,反复通知模型它应该做出的决定。

文本分类知识库

我们最喜欢的文本分类库包括:

  • 用于分类的文本转换器的高级实现。
  • fastai.text — fastai 很好地实现了各种文本分类器。

槽提取

自然语言处理问题的另一个大子集属于槽提取(也称为信息提取或槽填充)的管辖范围。Slot extraction 查看一个句子并提取相关的信息,将它们传递到 Slot 类别中。

插槽提取示例

示例时隙提取预测

例如,在我们的 travel agent bot 示例中,我们可能需要文本分类所提供的额外信息,并且我们可能希望训练一个槽提取模型来提取相关细节以完成用户的请求,而不是必须通过算法来请求额外信息。

插槽提取训练

为了训练槽提取模型,您将需要收集训练数据集,就像分类一样。在这个数据集中,要提取的句子中的跨度应该突出显示,并用它们特定的槽标签进行标记。

插槽提取存储库

我们最喜欢的一些槽提取库包括:

  • JointBert —一个使用 Bert 进行插槽提取的非常好的实现
  • LSOIE —用于开放插槽提取的开放信息提取报告

对话系统

对话系统位于分类和填充槽的交叉点。在对话系统中,用户输入通过一个分类模型被分组为“意图”,然后通过一个槽填充模型进行调查,以寻找与用户请求相关的信息。对话系统可以在同一个模型中进行多次对话。

对话系统资源

你可以使用像 JointBert 这样的开源技术,或者使用 Rasa 或 Google 的 DialogueFlow 这样的聊天机器人服务来构建自己的对话系统。

文本翻译

文本翻译是 NLP 技术产生重大影响的另一个领域。文本翻译接受一种语言的文本输入,并依次预测目标语言的翻译序列。

文本翻译的一个例子

在我们的酒店预订示例中,我们可能希望将文本翻译成给定的目标语言,比如西班牙语。

与文本分类和槽填充不同,文本翻译不太具有可定制性,通常您将使用现成的模型,该模型已经过培训,可以在您选择的语言之间进行翻译。

结论

从事涉及自然语言处理的项目是一个令人兴奋的时刻,因为由机器学习驱动的自然语言处理技术正在迅速发展,并在行业中产生真正的影响。

在这篇文章中,我们回顾了自然语言处理中常用的一些关键技术,包括文本分类、槽提取、对话系统和文本翻译。

一如既往,快乐训练!

原载于 2021 年 1 月 6 日https://blog . apex advisors . ai

用 5 分钟概述熊猫系列

原文:https://towardsdatascience.com/an-overview-of-pandas-series-in-5-minutes-eb0186831e53?source=collection_archive---------39-----------------------

Python 熊猫教程—第 1 部分

掌握数据科学家最流行的 Python 数据结构之一

图一。还有什么图标可以更好地代表熊猫的数据帧?(照片由弗莱彻·普莱德在 Unsplash 上拍摄)

熊猫是我们一直认为理所当然的图书馆之一。当我们从事数据项目时,我们总是专注于使用最新、最酷的深度学习框架(如 TensorFlow 或 PyTorch)来构建最佳模型。Pandas 是我们每次都不可避免地在预处理中使用的库,并且很快就忘记了它。嗯,熊猫的力量恰恰来源于此:它的方便。在本帖中,我们将介绍我们在 pandas 库中看到的主要数据结构之一:Series

让我们简单介绍一下

熊猫是什么?

Pandas 是一个 Python 库,它提供了灵活且富于表现力的数据结构,适合执行快速数学运算。它是一个全面易用的数据分析库,旨在成为领先的开源语言中立的数据分析工具。你没听错:Pandas 开发团队的目标是将其功能扩展到 Python 之外。

由于 Pandas 扩展了 NumPy 的功能,并且是在 NumPy 的基础上构建的,所以它几乎是作为 NumPy 的扩展来运行的。Pandas 还提供了几种数据可视化方法,这对于从数据集中获得洞察力非常有用。在进入高级部分之前,在这篇文章中,我们将只关注两个主要对象类型中的第一个:熊猫系列对象。

熊猫系列

一维序列和二维数据帧是 pandas 中的两种主要数据结构。尽管您可以创建更高维度的数据帧,但熊猫数据帧对象通常是二维的。另一方面,熊猫系列总是一维的。以下是系列对象的基本可视化:

图二。熊猫系列物品的可视化

进口熊猫

因为我们将在这篇文章中编码,所以请确保用下面的代码行导入 Pandas 库(也请导入 NumPy 库):

import pandas as pd
import numpy as np

熊猫系列

Series 是一维数组,能够保存任何数据类型,如整数、字符串、NumPy 对象和其他 Python 对象。它们也被标记,这是相对于 NumPy 数组的一个扩展。这些标签在熊猫 API 中被称为index

创建系列对象

创作一个熊猫系列相当容易。你可以使用主熊猫 API 中的pandas.Series()函数,并将你想要转换的数据传递给熊猫系列对象,如下所示:

# The data and index variables must be defined # see below
s = pd.Series(data, index=index)

好吧,你能传递的数据可以很不一样。可以传递的一些合适的数据类型有:

  • 一只熊猫dictlist
  • Numpy 数组;
  • 像单个整数一样的标量值;
  • 甚至是一串。

为了充分利用这个系列,最好传递一个带有索引值的类似列表的对象。然而,正如你在上面看到的,熊猫 API 在创建一个系列对象时非常灵活。以下是熊猫系列对象的一个示例:

data = [1,2,3,4,5]
index = ["a","b","c","d","e"]s = pd.Series(data=data, index=index, name='series 1')
print(s)

图 3。由 1 到 5 的数字组成的 Series 对象示例(作者提供的数字)

属性

一旦创建了Series对象,就可以使用属性来查看关于系列对象的信息:

print("Index:", s.index)
print("Values:", s.values)
print("Data Type:", s.dtype)
print("Name of the Series:", s.name)
print("Length of the Series", len(s))
print("Descriptive statistics about the Series\n", s.describe())
print("Shape of the Series", s.shape)

图 4。可通过系列对象属性查看的信息(按作者分类)

您也可以使用Series.rename()功能重命名系列对象:

s = s.rename(“new name”)
print(“Name of the Series:”, s.name)

图 5。重命名系列对象(作者图)

随机访问值和设置新值

series 对象的行为类似于 dictionary 对象;因此,也可以通过索引标签访问随机值。此外,您还可以将索引值用作属性:

# Access a random value like in dictionary objects
print("The val. at 'a' is", s['a'])# Use index values as an attribute
print("The val. at 'b' is", s.b)# get() function for random access
print("The val. at 'c' is", s.get("c"))# get() function for missing valuesprint("The val. at 'f'", s.get("f", "does not exist"))

图 6。随机访问系列对象值(图由作者提供)

此外,您可以使用我们用于 list 对象和 NumPy 数组的相同方法来访问 Series 对象的切片:

print('The first two elements of the Series object are:\n', s[:2])

但是,这还不是全部!pandas API 还提供特定的属性来访问特定的值。我们有四个具体选项:Series.atSeries.iatSeries.locSeries.iloc。简而言之,下面是它们在一个句子中的作用:

  • **Series.iat** →使用索引位置访问单个值;
  • **Series.at** →使用索引名称访问单个值;
  • **Series.loc** →按索引名访问一组值(一个切片)。
  • **Series.iloc** →通过索引位置访问一组值(切片)。

因此,Series.locSeries.iloc 属性也可以用于一组值,而Series.atSeries.iat属性用于单值访问。

让我们用一个例子来看看它们:

print(‘Output of s.at[“a”]’)
print(s.at[“a”])print(‘Output of s.loc[“a”:”b”]’)
print(s.loc[“a”:”b”])print(‘Output of s.iat[0]’)
print(s.iat[0])print(‘Output of s.iloc[0:2]’)
print(s.iloc[0:2])

图 7 和图 8。访问系列对象的切片和单个值(作者图)

最后,我们可以使用所有这些属性为给定的片或单个元素设置新值,如下所示:

print(“Before\n”, s)# Setting values by label:
s.at[“a”] = 100# Setting values by position
s.iat[3] = 500# Setting by assigning with a list object:
s.loc[“b”:”c”] = [33, 44]# Setting by assigning with a NumPy array:
s.iloc[4:5] = np.array([111])print(“After\n”, print(s))

图 9 和图 10。为系列对象设置新值之前和之后(作者提供的图表)

矢量化运算

对序列执行矢量化运算也非常容易,几乎与对整数值执行操作一样容易。以下是我们进行加法、除法和指数运算的一些例子:

s + 3
s / 5
s * s

图 11。加法运算(图由作者提供)|图 12。除法运算(作者图)|图 13。指数运算(图由作者提供)

但是,你并不局限于这些基本操作。您可以使用Series.apply()函数来传递自定义函数或 lambda 函数。例如,我们可以用下面的代码将 Series 对象的值乘以 2:

s.apply(lambda x: x* 2)

图 14。Lambda 函数在系列对象中的应用(作者提供的图片)

由于这是一个介绍性的帖子,我将在这里完成它。现在你对熊猫系列物品有了更多的了解。在下一篇文章中,我们将深入研究 DataFrame 对象,这种二维数据结构对于数据科学任务非常有用。

订阅邮件列表获取完整代码

如果你喜欢这篇文章,想在 Google Colab 上获得我的教程文章的代码,并尽早获得我的最新内容,考虑订阅:✉️的邮件列表

订阅现在

如果你对深度学习感兴趣,也可以看看我的人工智能内容指南:

https://oyalcin.medium.com/a-guide-to-my-content-on-artificial-intelligence-c70c9b4a3b17

既然您正在阅读这篇文章,我相信我们有着相似的兴趣,并且现在/将来会从事相似的行业。那么我们就通过Linkedin来连线吧!请不要犹豫发送联系请求!Orhan g . Yal n—Linkedin

Python 中机器学习(分类)算法的性能评价指标综述

原文:https://towardsdatascience.com/an-overview-of-performance-evaluation-metrics-of-machine-learning-classification-algorithms-7a95783a762f?source=collection_archive---------19-----------------------

由 Unsplash 上的科坦·拉杰普特拍摄的照片

使用 Python 函数开发分类模型并计算所有流行的性能评估指标

在我看来,性能评估是机器学习中最重要的部分。因为机器学习本身已经变得相当容易,因为有了所有的库和包。任何人都可以在不太了解幕后发生的事情的情况下开发机器学习。那么绩效评估可能是一个挑战。你如何评价那个机器学习模型的性能?

像 Weka 这样的软件会在你建立模型的时候自动提供大量的性能评估参数。但是在 sklearn 或 R packages 等其他工具中,性能评估参数不会随模型自动提供。您必须选择评估模型性能的参数。

因此,我决定撰写这篇文章,总结分类模型的所有流行的性能评估指标。所以,它为你节省了一些时间。

在本文中,我将尝试使用公式、简单的解释以及使用实际示例的计算来简要解释分类模型的性能评估度量。我不会深入探究它们,因为这是一个概述或备忘单。

我们需要一个机器学习模型,在这个模型上我们将尝试所有的性能评估指标。因此,首先,我们将开发一个模型,然后逐个研究绩效评估指标。

这篇文章表现:

  1. 特征的选择
  2. 模型开发
  3. 绩效评估方法

我将使用这个关于关节炎的数据集。该数据集包含其他参数,我们将使用这些参数来预测一个人是否患有关节炎。请随意从以下链接下载数据集:

https://github.com/rashida048/Machine-Learning-BU/blob/main/arthritis.csv

让我们把重点放在模型开发上。但在此之前,我们需要选择功能。

特征选择

以下是该项目的数据集:

import pandas as pd
import numpy as npdf = pd.read_csv('arthritis.csv')

这个数据框太大了,我无法在这里显示截图。它总共有 108 列。这些是列:

df.columns

输出:

Index(['x.aidtst3', 'employ1', 'income2', 'weight2', 'height3', 'children', 'veteran3', 'blind', 'renthom1', 'sex1',
       ...
'x.denvst3', 'x.prace1', 'x.mrace1', 'x.exteth3', 'x.asthms1',
'x.michd', 'x.ltasth1', 'x.casthm1', 'x.state', 'havarth3'],
dtype='object', length=108)

最后一列“havarth3”是我们希望使用分类器预测的目标变量。这一栏告诉我们一个人是否有关节炎。它有两个价值。值 1 表示该人患有关节炎,值 2 表示该人没有关节炎。

其余的特征是输入参数。

X= df.drop(columns=["havarth3"])
y= df['havarth3']

使用 scikit-learn 库中的 train_test_split 方法,将数据集拆分为训练集和测试集:

from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.34, random_state = 35)

我们现在有了培训和测试集。但是我们需要所有的 108 个训练特征吗?也许不是。

我使用 sklearn 库中可用的 SelectKBest 函数从中选择了 9 个特性。

我没有随意选择 9 这个数字。我检查了不同的其他功能选择方法,并尝试了不同的数字,即使使用这种功能选择方法,最终选择了数字 9。

请随时查看我关于特性选择的文章。我在最后提供了链接。

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classifuni = SelectKBest(score_func = f_classif, k = 9)
fit = uni.fit(X, y)reduced_training = fit.transform(x_train)
reduced_test = uni.transform(x_test)

这些是通过上述特征选择方法选择的列:

x_train.columns[fit.get_support(indices=True)].tolist()

输出:

['employ1',
 'rmvteth4',
 'genhlth',
 'x.age.g',
 'x.age80',
 'x.ageg5yr',
 'x.age65yr',
 'x.phys14d',
 'x.hcvu651']

这 9 个特征将用于分类器。

模型开发

有这么多可用的分类器。我在这里选择一个随机的森林分类器。如果您使用 sklearn 库,这相当简单。只需导入分类器,传递超参数并使训练数据适合它。

from sklearn.ensemble import RandomForestClassifierclf = RandomForestClassifier(max_depth=6, random_state=0).fit(reduced_training, y_train)

分类器完成了!现在我们将转向我们做这一切的主要目的。那就是学习所有的绩效评估指标。

机器学习的性能评估指标

精度

任何人都很容易想到的第一个是准确率。对于这个特定的项目,我们想知道准确预测了多少有关节炎和没有关节炎的人。让我们先检查一下训练集。

clf.score(reduced_test, y_test)

输出:

0.7417447018235584

是 74.17%。还不错!我们保留测试集来测试模型。让我们来测试一下:

clf.score(reduced_training, y_train)

输出:

0.7466666666666667

74.67%的训练集和测试集的准确率非常接近。所以这里不存在过度拟合的问题。

困惑 _ 矩阵

很多时候我们需要处理非常敏感的数据。例如,如果我们正在处理一个诊断癌症患者的数据集。正确诊断非常重要。

请记住,在这些情况下,准确性度量可能具有欺骗性。因为数据集可能会非常倾斜。也许 98%或更多的数据是负面的。意味着 98%或更多的情况下,患者没有癌症并且是阴性的。只有少量的数据是肯定的。在这种情况下,如果我们的分类器准确率是 98%,这意味着什么?

这可能意味着它只能正确分类癌症阴性患者,而不能诊断任何癌症阳性患者。但准确率仍高达 98%。但是在这种情况下分类器有效吗?一点也不。

因此,知道正确分类的癌症阳性患者的百分比和正确分类的癌症阴性患者的百分比是重要的。

混淆矩阵是一个由四个数字组成的 2x2 矩阵,将结果细分为真阳性、假阳性、真阴性和假阴性。定义如下:

真阳性:真阳性是被正确预测为阳性的阳性数据的数量。

假阳性:假阳性显示实际上是阴性的数据量,但分类器将其归类为阳性。

真阴性:被正确预测为阴性的阴性数据的数量。

假阴性:假阴性是被分类器错误地预测为阴性的阳性数据的数量。

您可以比较实际标签和预测标签来找出所有这些。但是这里我将导入并使用 confuion_matrix 函数。

下面是使用混淆矩阵函数的函数,并使用字典将输出标记为 tp(真阳性)、“fp”(假阳性)、fn(假阴性)和“tn”(真阴性)。

def confusion_matrix_score(clf, X, y):
    y_pred = clf.predict(X)
    cm = confusion_matrix(y, y_pred)
    return {'tp': cm[0, 0], 'fn': cm[0, 1],
            'fp': cm[1, 0], 'tn': cm[1, 1]}

接下来,只需导入混淆矩阵函数并使用上面的函数:

from sklearn.metrics import confusion_matrix
cm = confusion_matrix_score(clf, reduced_test, y_test)
cm

输出:

{'tp': 692, 'fn': 651, 'fp': 397, 'tn': 2318}

这四个参数将用于查找其他几个绩效评估指标。

真阳性率(TPR)和假阳性率(FPR)

真阳性率是真阳性(TP)除以总阳性(P)。如果我们看混淆矩阵,真正已经在那里了。但是总的积极因素是什么呢?总阳性是真阳性和假阴性的总和。

真阳性率(TPR) =真阳性/(真阳性+假阴性)

真实阳性率也称为敏感度。

同样,假阳性率是假阳性除以假阳性和真阴性之和。

假阳性率(FPR) =假阳性/(假阳性+真阴性)

TPR 和 FPR 都是非常重要的指标。如果我们看这个项目,我们可以发现有多少关节炎的人被正确检测出来,有多少没有关节炎的人被错误地检测为关节炎患者。为了计算它们,让我们从上面计算的混淆矩阵‘cm’中提取 tn、fp、fn 和 tp。

tn, fp, fn, tp = cm['tn'], cm['fp'], cm['fn'], cm['tp']tpr = tn/(tn+fn)
fpr = fn/(fn+tp)(tpr, fpr)

输出:

(0.7807342539575615, 0.4847356664184661)

真阳性率为 78.07%,假阳性率为 48.47%。

ROC 曲线和曲线下面积(AUC)

ROC 曲线(受试者工作特征曲线)显示了真阳性率(TPR)和假阳性率(FPR)之间的权衡。针对不同的阈值计算 TRP 和 FPR。然后将这一系列的 TPR 和 FPR 绘制成 ROC 曲线。如果曲线下面积(AUC)更接近 1,则认为该模型是有技巧的。

所以,这里是如何找到 ROC 曲线和曲线下的面积

from sklearn import metrics
metrics.plot_roc_curve(clf, reduced_test, y_test)

该图显示曲线下面积(AUC)为 0.8。

精度和校准

如果我们考虑这个项目,precision 将计算分类器正确预测关节炎患者的比例。这个公式可以写成:

从公式中可以看出,精度越高意味着真阳性越高,假阳性越低。

另一方面,回忆代表所有关节炎患者中被检测为关节炎患者的比例。如果你是第一次看到这个,这个定义可能看起来很混乱。公式如下:

所以,更高的回忆意味着更高的真阳性和更低的假阴性。回忆也叫敏感。

让我们计算一下精度和回忆:

precision = tn/(tn+fn)
recall = tn/(tn+fp)(precision, recall)

输出:

(0.7807342539575615, 0.8537753222836095)

f 分数

如您所见,精确度意味着更低的误报率,召回意味着更低的误报率。当你将要优化一个机器学习模型的时候,你需要选择你想往哪个方向走:更低的误报率还是更低的漏报率?这取决于项目要求。

F1 分数是精确度和召回率的调和平均值。该公式如下所示:

注意公式。当精确度和召回率都达到完美时,f 值为 1。

f 分数的一个更通用的公式是:

当精确度或召回率需要比另一个更重要时,使用这个公式。β的三个常用值是 1、2 或 0.5。当精度和召回权重相同时使用 1,当召回权重高于精度时使用 2,当召回权重低于精度时使用 0.5。

在本次演示中,我将使用 1 和 2 的β值,并计算 f 1 和 f2 值:

f1_score = 2*precision*recall/(precision + recall)
f2_score = 5*precision*recall/(4*precision + recall)
(f1_score, f2_score)

输出:

(0.8156228008444757, 0.8380938607274568)

精确召回曲线

精确-召回曲线显示了精确和召回之间的权衡。精确度-召回率曲线下的高区域意味着高精确度和高召回率。为此,使用不同的阈值来计算精确度和召回率。

但是没问题。我们不必手动计算不同阈值的精度和召回率。我们可以简单地使用 sklearn 库中可用的函数,该函数将为我们提供曲线以及曲线下的面积。

from sklearn.metrics import auc, plot_precision_recall_curve
plot_precision_recall_curve(clf, reduced_test, y_test)

输出:

曲线显示平均精度(AP)为 0.89。

这是中国曲线下的面积:

auc(recall, precision)

输出:

0.6555667752074759

马修斯相关系数

MCC 是二进制分类的另一个很好的性能评估指标。它考虑了真阳性、假阳性和假阴性。它返回一个介于-1 和 1 之间的值。值 1 表示完美的分类器,0 表示不比随机猜测好,而-1 表示原始标签和预测标签之间完全不一致。公式如下:

使用 python 对本项目进行计算:

mcc = (tn*tp - fn*fp)/np.sqrt((tn+fn)*(tn+fp)*(tp+fn)*(tp+fp))
mcc

输出:

0.3919014959349731

也可以使用以下函数进行计算,该函数将预测 y 和原始 y 作为参数:

**from ** **sklearn.metrics ** **import** matthews_corrcoef 
matthews_corrcoef (y_test, y_pred)

输出:

0.3919014959349731

结论

所有指标都显示为二进制分类设置。但是相同的度量也可以用于多类分类问题。这种方法被称为一对一。说,你在计算精度。您将其中一个类设置为正类,将其余的类设置为负类。这样问题就变成二元的了。

希望这个关于绩效评估的讨论有所帮助。请随时在 Twitter 上关注我。

更多阅读

[## 文本数据的探索性数据分析,包括可视化和情感分析

towardsdatascience.com](/exploratory-data-analysis-of-text-data-including-visualization-and-sentiment-analysis-e46dda3dd260) https://pub.towardsai.net/dissecting-1-way-anova-and-ancova-with-examples-in-r-a3a7da83d742

文本挖掘软件选项概述

原文:https://towardsdatascience.com/an-overview-of-text-mining-software-options-e799382c7dc5?source=collection_archive---------36-----------------------

这些定性定量的软件工具需要在你的雷达上

介绍

在我的数据科学工作中,我经常向客户和合作伙伴推荐一系列软件,它们在定性和定量分析之间架起了一座桥梁。

https://adamrossnelson.medium.com/membership

由米卡·博斯韦尔在 Unsplash 上拍摄的照片

我们有时将这些软件包称为定性数据分析软件(QDAS)。他们人数众多。在我看来,定性这个名称是用词不当。对于许多这样的软件包来说,其内部都有一套强大的定量算法和功能。

我也是一个文字游戏爱好者,这些包很多都是用来给自己命名的!

如果没有这个软件家族,数据科学或分析社区将很难有效地处理像 Boswell 照片中显示的文本。

本文将确定其中的许多包,在哪里可以找到它们,并给出它们的优缺点。在适用的地方,我会提到关于它们与其他包的互操作性的信息。

按字母顺序。

ATLAS.ti

这个 QDAS 软件是可用时间最长的软件之一。该平台提供了可以与 SPSS(或任何其他可以读取 SPSS 的平台,如 R、Stata 和 Python 的 Pandas)一起工作的导出。你可以在 http://atlasti.com 找到更多——指定为商业和/或非开源。

AnSWR

AQUAD

有多种语言版本。主网站是德语的。下拉菜单提供英语和其他语言的访问。你可以在https://www.aquad.de/找到更多——这个工具值得了解,因为作者在他们的网站上维护了参考书目。

卡珊德拉

这个包的大部分文档都是法语的。对于那些寻求能够在所有主流操作系统(Mac、Windows 和 Linus)上运行良好的软件的人来说,这是值得一看的。更多在线尽在http://cassandre.ulg.ac.be/。

计算机辅助文本标记分析(CATMA)

现在,在其第六个主要版本中,该软件拥有高度的稳定性和成熟性,受到用户群的高度赞赏。适用于 Windows、Mac OS 和 Linus。汉堡大学的研究人员为人文学科的研究人员开发了这个平台。更多在线尽在https://catma.de/。

下一代纲要

原名纲要(现已退休)。该软件可通过其 GitHub repo 获得。它将自己描述为对“对话映射和思维映射”有用,并继续解释“但它的用途几乎是无限的。”遗留产品信息在线存档。更新后的下一代包在:【https://github.com/CompendiumNG/CompendiumNG】T4。

Dedoose

喜欢这个的拼写!Dedoose 提供了一个基于 web 的用户界面。加州大学洛杉矶分校的学者最初在威廉·格兰特基金会的支持下开发了这个平台。导致该平台流行的许多额外待遇和功能包括低成本、基于云的基础设施和有益的技术支持。更多在线尽在https://www.dedoose.com/。

发现文本

以前称为,编码分析工具包(CAT)。该软件提供了一个基于网络的用户界面。以前这个工具是免费和/或开源的。然而,情况不再如此。Discover Text 通过他们在 https://discovertext.com/的网站提供免费试用。

F4 分析

该平台提供了一系列与文本分析相关的服务和解决方案,而不仅仅是分析。例如,在与音频转录相关的特性和能力上与该平台相结合。该平台还支持多种语言。更多在线尽在https://www.audiotranskription.de/en/。

自由 QDA

这个项目的状况还不清楚。虽然它最后一次更新是在 2015 年,但它的代码仍然可以在:https://sourceforge.net/projects/freeqda/找到。

超研究

最初发布于 1991 年。该软件为研究人员和科学家提供了免费的有限试用版,他们可能会在您购买之前尝试一下。这个软件的一个优点是他们提供先进的技术支持。更多在线信息请访问 http://www.researchware.com/company.html。

夸利坦

这个软件的大部分文档都是德语的,有着聪明的文字游戏名称。更多在线尽在https://kwalitan.nl/。

libreQDA

这个工具来自乌拉圭,为说西班牙语的人提供了一个平台。现在由 https://tryolabs.com/的赞助和维护,关于这个包的更多信息在 Tryo 的博客上。作为 Tryo 实验室的一个项目,该项目为包括或将涉及机器学习和人工智能的项目提供支持。

语言民族志

这个包提供了对特定用例的支持。在它的网站上,这个包“表演语言民族志”。也就是说,给定代表某一现象的文档集合(例如,快乐博客;谎言;妇女撰写的文本;等等。),这些工具可以帮助分析集合并发现潜在的有趣模式。”更多在线信息,请访问 https://web . eecs . umich . edu/~ mihalcea/downloads . html # linge thn

MAXQDA

这个包的一些优点是对统计分析和数据可视化有强大的支持。这个软件包还提供了一个免费试用版。有三个级别,包括“标准”、“高级”和“专业分析”该软件包的网站提供了广泛的教育资源,对研究人员、科学家、分析师以及其他处于学习定性数据分析软件初级阶段的人非常有用。更多在线尽在https://www.maxqda.com/。

NVivo

QSR 国际公司维护和分发这一受欢迎的软件包。作为定性数据分析软件中的知名产品,该软件通常通过网站许可协议提供给许多基于大学的研究人员和科学家。此外,与 MAXQDA 类似,NVivo 网站提供广泛的教育资源,包括点播培训网络研讨会。更多在线信息请访问https://www . qsrinternational . com/nvivo-qualitative-data-analysis-software/home/。

QDA 矿工队(QDA 矿工队)

根据 Provalis 的研究,该软件可以很好地与其他软件包集成。Provalis 的这套软件的一个优点是高度模块化。配套软件包包括 WordStat 和 SimStat。从网站上看,“这些工具的互操作性允许研究人员将数字和文本数据集成到单个项目文件中,并在定量和定性数据分析之间无缝地来回移动。”更多在线尽在https://provalisresearch.com/。

夸鲁斯

又一个有趣的文字游戏。这个包赢得了荣誉,因为它最近退休了。更多在线信息请访问 http://www.ideaworks.com/qualrus/index.html(通过 Wayback 机器)。

奎尔科斯

最初由爱丁堡大学开发的基于英国的软件。许多领域的许多组织都使用这种软件,它主要支持那些对文本数据的定性分析感兴趣的人,通常是社会科学。这个软件包的特性列表包括许多有用的插图,包括展示其许多用途的动画。更多信息请访问 https://www.quirkos.com/index.html 的。

RQDA

对于流行的统计和数据科学编程语言 R 的用户来说,这个包值得一读。这个软件作为一个 R 包免费发布,带有 BSD 许可证。更多信息请访问 http://rqda.r-forge.r-project.org/的。

https://adamrossnelson.medium.com/membership

结论

本文列出了定性数据分析软件(QDAS)包以及在哪里可以找到它们。在适用的情况下,本文也给出了关于软件包优点和缺点的注释。

对于全方位服务的研究和分析工作,数据科学家和相关专业人员将从了解这些软件包中受益。我经常向客户和合作伙伴推荐这个连接定性和定量分析的软件家族。

感谢阅读

感谢阅读。把你的想法和主意发给我。你可以写信只是为了说声嗨。我期待着尽快聊天。推特:@ adamrossnelsonLinkedIn:亚当·罗斯·尼尔森在推特和脸书:亚当·罗斯·尼尔森在脸书。

scikit-learn 集群包概述

原文:https://towardsdatascience.com/an-overview-of-the-scikit-learn-clustering-package-d39a0499814?source=collection_archive---------23-----------------------

机器学习

scikit-learn 系列的第二集,解释了用于机器学习的著名 Python 库

作者图片

聚类是一种无监督的机器学习技术,其中既没有训练集,也没有预定义的类。当有许多记录时使用聚类,这些记录应该根据相似性标准(如距离)进行分组。

聚类算法将数据集作为输入,并返回标签列表作为输出,这些标签对应于相关的聚类。

聚类分析是一个迭代过程,其中,在每一步,当前迭代被评估,并被用于反馈到下一次迭代中对算法的改变,直到获得期望的结果。

scikit-learn 库提供了一个名为[sklearn.cluster](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.cluster)的子包,它提供了最常见的聚类算法。

在这篇文章中,我描述了:

  • sklearn.cluster提供的类和功能
  • 调谐参数
  • 聚类算法的评价指标

1 类和功能

sklearn.cluster子包定义了两种应用聚类算法的方式:类和函数。

1.1 类别

在类策略中,您应该通过指定类参数来创建所需聚类类算法的实例。然后用数据拟合算法,最后,可以使用拟合的模型来预测分类:

**from** **sklearn.cluster** **import** AffinityPropagationmodel = AffinityPropagation()
model.fit(X)
labels = model.predict(X)

1.2 功能

除了类定义之外,Scikit-learn 还提供了执行模型拟合的函数。关于类,当只有一个数据集时,可以使用函数,该数据集必须在一个点上只分析一次。

在这种情况下,调用函数就足够了,以便获得集群化的数据:

**from** **sklearn.cluster** **import** affinity_propagationresult = affinity_propagatiom(X)

2 个调谐参数

根据要调整的主要参数,聚类算法可以分为两大类:

  • 要在数据中发现的聚类数
  • 观测值之间的最小距离。

2.1 要发现的集群数量

通常,在这组聚类算法中,你至少要调优最大数量的聚类才能找到。在scikit-learn中,通常这个参数被称为n_clusters

sklearn.cluster包提供了以下属于该类别的聚类算法(为每个提供的算法显示了类和函数):

  • [**AgglomerativeClustering**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.AgglomerativeClustering.html#sklearn.cluster.AgglomerativeClustering)
  • [**Birch**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html#sklearn.cluster.Birch)
  • [**FeatureAgglomeration**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.FeatureAgglomeration.html#sklearn.cluster.FeatureAgglomeration)
  • [**KMeans**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans)/
  • [**MiniBatchKMeans**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.MiniBatchKMeans.html#sklearn.cluster.MiniBatchKMeans)
  • [**SpectralClustering**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.SpectralClustering.html#sklearn.cluster.SpectralClustering)/
  • [**SpectralBiclustering**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.SpectralBiclustering.html#sklearn.cluster.SpectralBiclustering)
  • [**SpectralCoclustering**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.SpectralCoclustering.html#sklearn.cluster.SpectralCoclustering)

对于这类算法,主要的问题是找到最佳的聚类数。可以使用不同的方法,例如弯头法。

在肘形法中,计算并绘制出数量不断增加的聚类的平方和(例如从 1 到 20)。最佳的聚类数对应于斜率像弯头一样变化的点。

存在许多其他技术来计算最佳聚类数。 Matt.0 在他的一篇非常有趣的文章中阐述了它们,这篇文章名为选择最佳聚类数的 10 个技巧。

2.2 观测值之间的最小距离

在这类聚类算法中,最重要的调整参数是距离。在 scikit-learn 中,与距离相关的参数名称取决于算法。因此,我建议阅读与所选算法相关的文档,以发现距离参数的确切名称。

sklearn.cluster包提供了以下属于这个类别的聚类算法(括号中是距离参数的名称):

  • [**AffinityPropagation**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.AffinityPropagation.html#sklearn.cluster.AffinityPropagation)**(damping)**/
  • [**DBSCAN**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html#sklearn.cluster.DBSCAN)**(eps)**/
  • [**MeanShift**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.MeanShift.html#sklearn.cluster.MeanShift)**(bandwidth)** / **mean_shift()**
  • [**OPTICS**](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.OPTICS.html#sklearn.cluster.OPTICS)**(max_eps)**/**cluster_optics_xi()**——**cluster_optics_dbscan()**

这类聚类算法的主要挑战是找到最佳距离值。一种可能的解决方案是用不同的距离值测试算法,并选择与最佳性能相关联的值。

3 项评估指标

[sklearn.metrics.cluster](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.metrics.cluster)子包包含了用于评估聚类分析的指标。

评估聚类算法的性能并不是一件容易的事情,因为它应该验证每条记录都被分配了正确的聚类 r,即每条记录与属于其聚类的记录的相似度要比与属于其他聚类的记录的相似度高得多。

关于集群评估的更多细节可以在这篇有趣的文章中找到。

有两种评价:

  • 基于监督的评估
  • 基于无监督的评估

3.1 基于监督的评估

基于监督的方法(也称为外在方法)利用基础事实来执行评估。其思想是将基本事实与聚类算法的结果进行比较,以计算得分。

Scikit-learn 提供以下基于监督的方法:

  • [**adjusted_mutual_info_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.adjusted_mutual_info_score.html#sklearn.metrics.adjusted_mutual_info_score)
  • [**adjusted_rand_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.adjusted_rand_score.html#sklearn.metrics.adjusted_rand_score)
  • [**completeness_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.completeness_score.html#sklearn.metrics.completeness_score)
  • [**fowlkes_mallows_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.fowlkes_mallows_score.html#sklearn.metrics.fowlkes_mallows_score)
  • [**homogeneity_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.homogeneity_score.html#sklearn.metrics.homogeneity_score)
  • [**mutual_info_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.mutual_info_score.html#sklearn.metrics.mutual_info_score)
  • [**normalized_mutual_info_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.normalized_mutual_info_score.html#sklearn.metrics.normalized_mutual_info_score)
  • [**rand_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.rand_score.html#sklearn.metrics.rand_score)

对于所有前面的函数,您应该至少提供两个参数:labels_true(地面真实类标签)和labels_pred(要评估的聚类标签)。

3.2 基于无监督的评估

基于非监督的方法(也称为内在方法)通过分析分类的分离程度和分类的紧密程度来评估聚类算法。

Scikit-learn 为聚类评估提供了以下固有方法:

  • [**calinski_harabasz_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.calinski_harabasz_score.html#sklearn.metrics.calinski_harabasz_score)
  • [**davies_bouldin_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.davies_bouldin_score.html#sklearn.metrics.davies_bouldin_score)
  • [**silhouette_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.silhouette_score.html#sklearn.metrics.silhouette_score)
  • [**v_measure_score**](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.v_measure_score.html#sklearn.metrics.v_measure_score)

这类函数至少接受两个参数作为输入:X(样本之间成对距离的数组)和labels(每个样本的标签值)。

摘要

在本文中,我描述了由 Scikit-learn 库提供的 sklearn.cluster 子包,以及用于评估集群算法质量的评估指标。

有关集群的更多信息,您可以阅读 Scikit-learn 官方文档。

如果你想发现 Scikit-learn 提供的其他类和函数,你可以关注我、订阅我的邮件列表,敬请关注。

如果你已经走了这么远来阅读,对我来说今天已经很多了。谢谢!你可以在这篇文章里读到更多关于我的内容。

相关文章

Scikit-learn 库概述—第 1 集预处理

原文:https://towardsdatascience.com/an-overview-of-the-scikit-learn-library-episode-1-preprocessing-9b17ab4dde4f?source=collection_archive---------27-----------------------

机器学习

著名的用于机器学习的 Python 库的剧集中的描述。第一集处理预处理子包。

作者图片

Scikit-learn 是一个非常流行的用于机器学习的 Python 库。最初由 David Cournapeau 于 2007 年开发,2010 年,当法国计算机科学和自动化研究所 INRIA 参与该项目时,它开始成长。2021 年 9 月,Scikit-learn 最新版本发布,即 1.0。

Scikit-learn 提供了机器学习过程中涉及的所有步骤,包括数据预处理、特征提取、模型选择、模型训练、模型评估和模型部署。

在这篇文章中,我开始了一系列的情节,每一集都描述了 Scikit-learn 提供的一个单独的子包。Scikit-learn 被组织成一个名为sklearn的主模块,这个主模块又被分成许多子模块。在本文中,我关注数据预处理。

用于数据预处理的所有类和函数都包含在子模块sklearn.preprocessing中,该子模块提供以下操作:

  • 特征缩放
  • 特征二值化
  • 特征编码
  • 非线性变换
  • 其他的

1 特征缩放

特征缩放涉及数据规范化和标准化。在这篇由 Baijayanta Roy 撰写的名为关于特性缩放的有趣文章中,你可以理解规范化和标准化之间的区别。

Scikit-learn 为功能缩放提供了许多类:

  • MaxAbsScaler() —给定一个特征值列表,将列表中的每个值转换为 0 到 1 之间的数字。新值的计算方法是当前值除以列的最大值。
  • MinMaxScaler() —新值计算为当前值和最小值之差除以特征值列表的范围。
  • RobustScaler() —移除中间值,并根据四分位范围缩放数据。该定标器对异常值具有鲁棒性
  • StandardScaler() —移除平均值并缩放至方差。这个定标器对应于经典的标准化过程。
  • Normalizer() —将每个值标准化为单位定额。

为了使用 whatever scaler,您应该首先实例化一个对象,例如:

scaler = StandardScaler()

然后你必须用所有可用的数据来拟合它:

scaler.fit(data)

最后,您可以将缩放器仅应用于感兴趣的数据(也可能包括所有数据)。数据集):

scaled_data = scaler.transform(subset_of_data)

或者,您可以用一个函数同时应用拟合和变换:

scaled_data = scaler.fit_transform(data)

你可以在我之前的文章中读到一个关于MinMaxScaler()MaxAbsScaler的实际例子,标题是使用 Python scikit 进行数据规范化-学习。

除了所描述的类之外,Scikit-learn 还提供了一些用于特征缩放的函数,这些函数可以直接在固定数组上使用,而无需拟合过程:

  • maxabs_scale()
  • [minmax_scale](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.minmax_scale.html#sklearn.preprocessing.minmax_scale)()
  • normalize()
  • robust_scale()
  • scale()

2 特征二值化

特征二值化阈值数字特征获取布尔值,存储为 0 或 1。

Scikit-learn 为二进制化提供了许多类:

  • Binarizer() —根据阈值将特征值设置为 0 或 1。大于阈值的值设置为 1,小于或等于阈值的值设置为 0。
  • LabelBinarizer() —对于每个输出标签,构建一个向量,其中元素的数量等于唯一标签的数量,然后根据向量的每个元素在哪个标签中,为其分配 1 或 0。这个类与OneHotEncoder()非常相似,区别在于LabelBinarizer()用于输出类,而 OneHotEncoder 用于输入特性。更多细节,你可以在 Stackoverflow 上阅读这个线程。
  • MultilabelBinarizer()LabelBinarizer()的扩展,支持多标签。

类似于缩放器,二进制化器也应该首先被实例化,然后被拟合,最后被应用于数据:

binarizer = Binarizer()
binarizer.fit(data)
binarized_data = binarizer.transform(new_data)

或者:

binarizer = Binarizer()
data = binarizer.fit_transform(data)

Scikit-learn 还为二进制化提供了有用的函数,当元素数量固定时可以使用:

  • binarize()
  • label_binarize()

正如已经说过的特征缩放,请提醒保存安装的二进制化器,因为它将在模型部署期间使用。

3 特征编码

在模型能够被拟合和评估之前,分类特征必须被转换成数字。特征编码就是这种转换。

Scikit-learn 为特征编码提供了不同的类:

  • LabelEncoder() —用介于 0 和类别总数减 1 之间的值对输出标签进行编码。
  • OneHotEncoder()-对于每个输入分类特征,构建一个向量,其中元素的数量等于唯一标签的数量,然后根据向量的每个元素在哪个标签中,为其分配 1 或 0。
  • OrdinalEncoder() —每个唯一的类别值被分配一个整数值。然后,每个输入分类特征值被转换成一个数字,对应于相对类别。比如,“苹果”是 1,“橘子”是 2,“甜瓜”是 3。

每个编码的使用与前面的操作非常相似。因此,实例化所选的编码器,然后用分类数据对其进行拟合和转换就足够了。

4 非线性变换

Scikit-learn 还为非线性转换提供了一些有趣的类:

  • PowerTransformer() —应用幂变换使特征更像高斯。这对于建模需要数据正态性的情况很有用。
  • QuantileTransformer()-变换特征以遵循均匀分布或正态分布。这是通过利用分位数信息来实现的。
  • SplineTransformer() —基于单变量 B 样条函数生成新的特征矩阵。
  • FunctionTransformer() —应用自定义变换。

每个转换器必须首先被实例化,然后用数据拟合,最后通过transform()函数使用。

如果元素的数量是固定的,也可以直接通过以下函数进行变换,而无需任何拟合:

  • quantile_transform()
  • power_transform()

5 其他

preprocessing包还包括以下类:

  • KBinsDiscretizer() —将连续数据归入区间。
  • KernelCenterer() —将内核矩阵居中。
  • PolynomialFeatures() —生成一个新的特征矩阵,该矩阵包含所有次数小于或等于指定次数的特征的多项式组合。

还有一个有趣的功能:

  • add_dummy_feature()-用虚拟输入特征扩充数据集。

摘要

在本文中,我描述了 Scikit-learn preprocessing包的概述。许多操作和变换可应用于数据集,包括输入要素和输出类,包括要素缩放、要素二值化、要素编码、非线性变换和其他操作。要了解更多信息,你可以阅读预处理包上的官方 Scikit-learn 文档。

如果你想发现 Scikit-learn 提供的其他类和函数,可以关注我,订阅我的邮件列表敬请关注。

如果你已经走了这么远来阅读,对我来说今天已经很多了。谢谢!你可以在这篇文章里读到更多关于我的内容。

你愿意支持我的研究吗?

你可以每月订阅几美元,解锁无限的文章。

奖金

提醒将拟合的预处理操作保存到一个外部文件,因为当您部署模型时,您需要将处理过程中使用的同一 scaler 应用到新数据:

from sklearn.externals import joblibjoblib.dump(prep, 'prep.pkl')

然后,要从文件中打开 scaler,您可以执行以下代码:

prep = joblib.load('prep.pkl')

相关文章

多功能数据工具包概述

原文:https://towardsdatascience.com/an-overview-of-versatile-data-kit-a812cfb26de7?source=collection_archive---------23-----------------------

数据工程

开始使用多功能数据工具包,这是一个使数据工程师工作更高效的框架

作者图片

数据工程师的工作需要多种技能,包括构建数据管道、评估数据库、设计模式和管理模式。简而言之,数据工程师加载、提取、操作和管理数据。这项工作通常需要大量的技能,如果流程没有实现自动化,数据工程师就有可能犯很多错误,并在解决意外事件时浪费大量时间。

最近,我测试了一个非常有趣的框架,它方便了数据工程师的工作:由 VMware 在 Github 上开源发布的通用数据工具包。

多功能数据工具包允许数据工程师半自动执行任务。实际上,他们只需要关注数据和框架的一般配置,比如数据库设置和 cron 任务调度,而不用担心手动部署、版本控制和类似的事情。

换句话说,多功能数据套件简化了数据工程师的生活,因为它允许以简单快速的方式管理数据,以及快速处理意外事件。

数据工程师只需三个步骤就可以构建完整的数据处理工作负载(数据作业,在通用数据工具包语言中):

  • 摄取数据
  • 过程数据
  • 发布数据

在本文中,我给出了通用数据工具包的概述,以及一个实际的用例,展示了它的潜力。欲了解更多信息,您可以阅读多功能数据套件完整文档。

1 概述

通用数据工具包是一个框架,使数据工程师能够开发、部署、运行和管理数据作业。一个数据作业就是数据处理工作量。

多功能数据套件由两个主要组件组成:

  • 一个数据 SDK,提供了所有用于数据提取、转换和加载的工具,以及一个插件框架,允许根据数据应用的特定需求扩展框架。
  • 一个控制服务,它允许在 Kubernetes 运行时环境中创建、部署、管理和执行数据作业。

多功能数据工具包管理三种类型的数据作业,如下图中的浅绿色所示:

作者图片

1.1 摄入工作

摄取作业包括将不同来源的数据推送到数据湖,这是原始数据的基本容器。数据可能以不同的格式提供,如 CSV、JSON、SQL 等。

摄取可以通过不同的步骤来定义,包括但不限于创建数据模式和将数据加载到表中的过程。所有这些步骤都可以通过编写数据作业(通常用 Python 或 SQL)或通过插件来指定。通用数据工具包提供了一些预打包的插件,例如用于 CSV 和 SQL 摄取,但是您可以实现自己的插件。

1.2 加工作业

处理作业允许从数据湖中包含的数据集创建精选数据集。通常,这些工作涉及数据操作,例如数据清理和数据聚合。产生的数据集存储在数据仓库中,这在概念上不同于数据湖,但在物理上可能与之一致。由于其高度可配置性,处理作业也可以与高级分析用例相关联。

通常处理作业是用 SQL 编写的,但是 Python 也可以用来实现这种类型的作业。

1.3 发布工作

发布作业包括即席查询或视图,可用于不同的目的,例如使用标准商业智能工具构建交互式仪表板,向其他应用程序发送通知或警报等。

发布作业依赖于特定的数据集,因此目前它们尚未包含在当前版本的通用数据工具包中。

2 用法示例

例如,我将开发一个本地数据湖,在这里我将摄取一个 CSV 文件,该文件包含世界城市数据库的基本版本,包含大约 41k 个位置:

作者图片

我将遵循以下步骤:

  • 多功能数据套件安装
  • 数据作业创建
  • 摄取作业
  • 加工作业

2.1 多功能数据套件安装

多功能数据套件可通过pip轻松安装,如下所示:

pip install -U pip setuptools wheel
pip install quickstart-vdk

由于我在本地部署了所有数据作业,因此不需要安装控制服务。但是,如果您想在 Kubernetes 运行时环境上部署数据作业,您可以遵循本指南。

2.2 数据工作创建

一旦安装完毕,我就可以使用vdk命令与多功能数据工具包进行交互。我可以通过以下命令创建新的数据作业:

vdk create -n world-cities-vdk -t my-team

其中-n指定数据作业名称,-t指定团队名称。关于每个vdk命令的更多细节,我可以运行以下命令:

vdk [command-name] --help

例如:

vdk create --help

作为create命令的结果,vdk创建了一个新目录,其中包含一些示例文件,每个文件对应于数据作业的一个步骤。

作者图片

步骤按字母顺序执行,因此,为了便于阅读,可以从 1 开始编号。关于数据作业目录结构的更多细节,可以查看官方文档。

2.3 环境设置

在开始使用多功能数据工具包之前,需要进行初步配置。这是通过配置两个文件实现的:

  • requirements.txt —该文件包含项目中开发的库的列表,每行一个;
  • config.ini —该文件允许配置一些基本信息,如团队名称和 cron 运行任务。

现在,我可以配置一些环境变量,包括数据库类型(在我的例子中是 sqlite)和名称(在我的例子中是vdk-cities.db)。我可以直接从我的终端配置这些变量:

export VDK_DB_DEFAULT_TYPE=SQLITE
export VDK_INGEST_METHOD_DEFAULT=sqlite
export VDK_INGEST_TARGET_DEFAULT=vdk-cities.db
export VDK_SQLITE_FILE=vdk-cities.db

这个vdk-cities.db文件将成为我的数据湖。

2.4 摄入工作

我已经准备好接收数据湖中的数据。首先,我在本地下载数据集,并将其放入名为source的目录中,该目录位于数据作业父目录中。

想法是将数据集摄取到名为cities的表中。这可以通过两种方式实现:

  • 编写数据作业
  • 使用vdk-csv插件。

2.4.1 写入数据作业

我定义了一个初步的数据作业步骤,它删除表cities,如果它存在的话,以确保总是有一个新版本的表:

DROP TABLE IF EXISTS cities;

我在数据作业目录中将这一步保存为10_drop_cities_table.sql。名称开头的10将确保首先执行该步骤。

现在我定义第二个数据作业步骤,它定义了表模式,数据集将被导入到这个表模式中。数据作业步骤对应于以下简单的 SQL 代码:

CREATE TABLE cities (city NVARCHAR,
city_ascii NVARCHAR,
lat REAL,
lng REAL,
country NVARCHAR,
iso2 NVARCHAR,
iso3 NVARCHAR,
admin_name NVARCHAR,
capital NVARCHAR,
population INTEGER,
id INTEGER
);

我将此步骤保存为20_create_cities_table.sql

最后,我可以将数据集上传到cities表中。我可以编写以下 Python 脚本,它将数据集作为 Pandas dataframe 加载,将其转换为 dict,然后通过多功能数据工具包提供的job_input.send_object_for_ingestion()函数将 dict 的每一项发送到数据湖:

import logging
from vdk.api.job_input import IJobInput
import pandas as pdlog = logging.getLogger(__name__)def run(job_input: IJobInput):
   log.info(f"Starting job step {__name__}")
   df = pd.read_csv('source/worldcities.csv') df_dict = df.to_dict(orient='records')
   for row in range(0, len(df_dict)):
       job_input.send_object_for_ingestion(
          payload=df_dict[row], destination_table="cities")

请注意,为了将 Python 脚本识别为数据作业 Python 步骤,需要使用run()函数。

现在,我已经准备好运行数据作业步骤了。我移动到数据作业父目录,并运行以下命令:

vdk run world-cities-vdk

数据库vdk-cities.db在当前目录中创建,并使用cities表填充。我可以通过vdk query命令或传统的sqlite命令查询数据库:

vdk sqlite-query -q 'SELECT * FROM cities'

2.4.2 使用 **vdk-csv** 插件

将数据集加载到数据湖的另一种方法是使用插件。在我的例子中,我将使用vdk-csv插件。我可以通过pip轻松安装:

pip install quickstart-vdk vdk-csv

然后,我可以通过以下命令接收数据集:

vdk ingest-csv -f source/worldcities.csv -t cities

2.5 加工作业

作为一项处理工作,我创建了一个只包含美国城市的cities表的视图。为此,我定义了两个处理作业:

  • 删除视图(如果存在)
  • 创建视图并将其保存在默认的数据湖中。

首先,我编写了另一个数据作业步骤,名为40_drop_usa_cities_view.sql:

DROP VIEW IF EXISTS usa_cities;

然后我创建了另一个数据作业步骤,它创建了视图:

CREATE VIEW usa_cities
AS
  SELECT *
  FROM cities
  WHERE country = 'United States';

我又运行了一遍所有的数据作业:

vdk run world-cities-vdk

视图被添加到数据湖中。

摘要

在这篇文章中,我描述了通用数据工具包的概述,这是一个非常强大的框架,允许以有效的方式管理数据。

此外,我还展示了该框架的一个初始用例,包括数据作业接收和处理。有关更多详细信息,您可以阅读通用数据工具包用户指南。

本教程的完整代码可以从我的 Github 资源库下载。

对于多功能数据工具包的问题或疑问,你可以直接加入他们的公共 slack 工作区或他们的邮件列表或在 Twitter 上关注他们。

如果你读到这里,对我来说,今天已经很多了。谢谢!你可以在这篇文章中读到更多关于我的内容。

你愿意支持我的研究吗?

你可以每月订阅几美元,并解锁无限的文章。

相关文章

免责声明 :此文非赞助文章。我与通用数据工具包或其作者没有任何关系。这篇文章展示了该工具包的一个公正的概述,旨在让更多的人可以使用数据科学工具。

用 Python 进行 RFM 分析

原文:https://towardsdatascience.com/an-rfm-customer-segmentation-with-python-cf7be647733d?source=collection_archive---------3-----------------------

以及如何从 it 中快速释放洞察力和商业价值

Dilyara Garifullina 在 Unsplash 上拍摄的照片

是时候重温一下我的 Python 技能了!👩🏻‍💻

本周,我想走技术路线,分享一个最近使用 RFM 框架的 Python 练习。这是一种通过三个方面来确定客户价值的方法:

  • 最近:用户最后一次采取行动(例如登录、下订单)是什么时候?
  • 频率:用户采取这个动作多少次?
  • 货币价值:这个用户一生的货币价值总和是多少?

我的工作受到了同一个数据集上许多有用帖子的极大启发,比如这个。在这篇文章中,我想分享我的 RFM 细分分析,并重点关注我发现的一些有用的提示,以快速从模型输出中带来商业价值。

  • 将绝对最近值、频率值和货币值转换为相对值,以减少与实际客户生命周期相关的偏差。
  • 生成简单、启发式的业务逻辑,以快速的方式交付业务价值。
  • 将这些细分市场与其他数据集结合起来,以更深入地了解您的客户群。

数据集描述和问题陈述

在我们深入细节之前,我想快速浏览一下我们的数据集是什么样子,以及我们的目标是解决什么问题。

我们的原始数据是包含以下字段的交易记录表:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 406829 entries, 0 to 541908
Data columns (total 8 columns):
 #   Column       Non-Null Count   Dtype  
---  ------       --------------   -----  
 0   InvoiceNo    406829 non-null  object 
 1   StockCode    406829 non-null  object 
 2   Description  406829 non-null  object 
 3   Quantity     406829 non-null  int64  
 4   InvoiceDate  406829 non-null  object 
 5   UnitPrice    406829 non-null  float64
 6   CustomerID   406829 non-null  float64
 7   Country      406829 non-null  object 
dtypes: float64(2), int64(1), object(5)
memory usage: 27.9+ MB

通常,我们会在客户层面上汇总数据。

作者图片

我们希望将 RFM 框架应用于该聚合数据集,并回答以下问题:

  1. 新近性、频率和货币价值之间有关联吗?
  2. 我们应该如何定义我们最有价值的客户(MVC)?我们的客户中有百分之多少是最有价值的客户?
  3. 我们是否能够创造独特的细分市场并据此设计 CRM 活动来提高客户参与度和/或盈利能力?

将绝对值转换为相对值,以减少客户寿命的偏差。

我在许多教程中注意到的一点是,计算中使用了绝对数字。换句话说,我们有以下内容:

  • 最近=最近一次操作和今天之间的时间间隔
  • 频率=从用户注册日期到今天的操作次数
  • 货币价值=用户一生中的总收入

在这一步之后,一个典型的方法是通过基于每个单独列的四分位数创建存储桶来计算最近/频率/货币得分。例如,在“频率”列上,我们执行以下操作:

customer_data["FrequencyScore"] = pd.cut(customer_data["Frequency"], 
                                       bins=[-1, 
                                         np.percentile(customer_data["Frequency"], 25), 
                                             np.percentile(customer_data["Frequency"], 50), 
                                             np.percentile(customer_data["Frequency"], 75), 
                                             customer_data["Frequency"].max()], 
                                       labels=[1, 2, 3, 4]).astype("int")

请注意,对于最近得分,我们需要给出相反的标签,因为客户越活跃,最近值就越低。😃

一旦我们获得了每个维度的分数,我们就可以通过将这三个分数相加来计算 RFM 的总分数。总体 RFM 得分越高(从 3 到 12),客户越有价值。

customer_data["RFM"] = customer_data["RecencyScore"] + customer_data["FrequencyScore"] + customer_data["MonetaryScore"]

这种方法很容易实现,但它容易与实际的客户生命周期产生偏差。例如,与过去 6 个月内注册的客户相比,12 个月前注册的客户自然具有更低的新近度(假设用户参与度在整个生命周期内普遍下降)、更高的频率和更高的货币价值(假设在用户活动和货币化方面同类)。因此,签约 12 个月的客户的 RFM 分数可能被高估了。

为了解释这种偏差,在计算个人得分之前,我会先将最近发生的事、发生的频率和货币价值标准化。例如,我会做相对频率=最近/一生。

customer_data["RelFrequency"] = customer_data["Frequency"] / customer_data["Lifetime"]

然后我会根据相对频率计算频率得分:

customer_data["FrequencyScore"] = pd.cut(customer_data["RelFrequency"], 
                                       bins=[-1, 
                                             np.percentile(customer_data["RelFrequency"], 25), 
                                             np.percentile(customer_data["RelFrequency"], 50), 
                                             np.percentile(customer_data["RelFrequency"], 75), 
                                             customer_data["RelFrequency"].max()], 
                                       labels=[1, 2, 3, 4]).astype("int")

在我的笔记本上,你可以找到使用绝对值的rfm_absRFM 分割和使用相对值的rfm_rel。在这里,我只附上在这两种方法下每个 RFM 细分市场的中值客户生命周期。正如我们所看到的,使用绝对值的 RFM 细分市场的客户生命周期有较大的差异,而使用相对值的 RFM 细分市场的客户生命周期相当稳定。更具体地说,对于第一种方法,我们看到那些 RFM 分数为 5 和 6(因此处于活动的下限)的人具有明显更短的寿命(因此是更近期的客户)。这种方法似乎“惩罚”了最近的客户,因为他们的频率和金额较低。

另一方面,我们的方法设法减少了 RFM 细分中与客户寿命相关的偏差!

作者图片

生成简单、启发式的业务逻辑,以快速的方式交付业务价值。

到目前为止一切顺利!

许多教程都以生成 RFM 分段标签(3–12)结束,包含以下汇总统计数据:

RFM 分割结果

这张表回答了我们的前两个问题:

  1. 在最近、频率和货币价值之间确实存在正相关关系。
  2. 我们的 MVC 是那些总 RFM 分数为 11 和 12 的人,即他们平均有 7 次以上的交易,在其一生中产生超过 2K 的交易,并且他们的最后一次交易是在过去 2 周内。这类客户约占我们总客户群的 16%。

然而,在现实生活中,这种输出可能不足以快速创造商业价值。一方面,我们得到的桶彼此差别不大,我们有机会合并一些部分。另一方面,逻辑本身相当复杂-如果我们想要严格遵循逻辑,我们需要将笔记本电脑部署到生产中,这需要大量的工程工作,并且产生大量商业价值的不确定性很高。

我们想快速行动。因此,我想根据上面的 RFM 分割结果生成一些简单的启发式逻辑,并将它们应用到生产中进行分析和操作。请注意,没有完美的逻辑——这里我只分享一组我认为最有区别的标准。

customer_data["last_order_within_l60d"] = customer_data["Recency"]<60 # Had transactions in the last 60 dayscustomer_data["more_than_two_orders"] = customer_data["Frequency"]>2 # Logged in more than twicecustomer_data["value_higher_than_2k"] = customer_data["MonetaryValue"]>2000 # Sum of value higher than 2Kcustomer_data.groupby(["last_order_within_l60d", "more_than_two_orders", "value_higher_than_2k"]).count()["Lifetime"]

作者图片

基于上面的分支,我定义了五个最终段(在括号中,您可以找到段的大小):

  1. 高参与度&高价值 (523)是最近 2 个月有最后一笔交易,成交 2 笔以上,平均贡献 2K 以上的人。
  2. 高参与度&低值 (876)是和 Group1 一样活跃,但贡献不到 2K 的人。
  3. 近期活动&低频 (811)是指最近 2 个月内有最后一笔交易但交易不超过 2 笔的人。这些客户的货币价值也较低。显然,这个群体中的大多数客户是最近获得的客户(他们的平均寿命只有 45 天)。
  4. 【老】活动&高频 (523)是最近 2 个月没有任何交易的人。然而,他们平均有 2 笔以上的交易。这些客户在旅程开始时非常活跃,但最近不那么活跃了。我们需要想办法让他们重新参与进来。
  5. 低参与度&低值 (1426)是最近 2 个月没有任何交易,交易不超过 2 笔,贡献收入最低的人。

作者图片

与其他数据集结合,释放更多洞察力和价值。

基于我们在上面获得的知识,有许多使用案例。这里我想详细阐述一下我在工作中用过的两个用例。

一种方法是将这个客户价值分数作为一个新的维度附加到 BI 数据集(用户资料、跟踪事件、购买记录等)。结合现有的指标和仪表板,这可以帮助您回答以下问题:

  • 我们的 MVC 的社会经济特征(收入、职业等)和人口统计学特征(年龄、性别、婚姻状况等)是什么?这为我们如何瞄准并获得更多这样的客户提供了启示。
  • 与其他群体相比,我们的 MVC 有明显不同的用户旅程吗?我们如何优化 MVC 的旅程体验?
  • 与其他集团相比,我们的 MVC 是否拥有重要的市场份额?这可能会给我们一些启发,以改善对他们的推荐。

另一个用例是将此标签发送到 CRM 工具,并将其用于定制的互动交流。以我上面生成的最终细分为例:对于第 2 组高参与度&低价值和第 3 组近期活动&低频率,我们应该通过个性化推荐关注货币化(例如订单数量、平均订单价值),而对于第 4 组老活动&高频率,我们应该尝试重新吸引他们,并让他们回到我们的网站/应用程序。结合其他数据集的特征,我们能够设计有针对性的内容和媒体,以接触到个人客户并最大限度地提高转化率。

就是这样。让我知道你的想法和反馈!

熊猫数据可视化的终极备忘单

原文:https://towardsdatascience.com/an-ultimate-cheat-sheet-for-data-visualization-in-pandas-f7bc239c9937?source=collection_archive---------15-----------------------

照片由马克俯身在 Unsplash

熊猫所有基本类型的可视化,以及一些非常有用和省时的高级可视化

我们使用 python 的 pandas 库主要是为了在数据分析中进行数据操作。但是我们也可以用熊猫来进行数据可视化。您甚至不需要为此导入 Matplotlib 库。Pandas 本身可以在后台使用 Matplotlib,为你渲染可视化。使用一个数据帧或一系列数据可以很容易地绘制图表。熊猫使用比 Matplotlib 更高级的 API。因此,它可以使用更少的代码行来绘制图表。

我将从使用随机数据的非常基本的图开始,然后转向使用真实数据集的更高级的图。

在本教程中,我将使用 Jupyter 笔记本环境。如果你没有安装,你可以简单地使用谷歌 Colab 笔记本电脑。你甚至不用在上面装熊猫。它已经为我们安装好了。

如果你想安装一台 Jupyter 笔记本,这也是一个好主意。请继续安装 anaconda 包。

对于数据科学家来说,这是一个非常棒的软件包,而且是免费的。

然后使用以下命令安装 pandas:

pip install pandas

或者在你的蟒蛇提示中

conda install pandas

你准备好摇滚了!

熊猫可视化

我们将从最基本的开始。

线条图

首次进口熊猫。那么,我们就在《熊猫》里做一个基础系列,做一个台词剧情吧。

import pandas as pd
a = pd.Series([40, 34, 30, 22, 28, 17, 19, 20, 13, 9, 15, 10, 7, 3])
a.plot()

最基本最简单的剧情都准备好了!看,多简单。我们可以稍微改进一下。

我要补充的是:

一个数字大小,使地块的大小更大,

要更改默认的蓝色,

上面的标题显示了这个情节的内容

和字体大小来更改坐标轴上这些数字的默认字体大小

a.plot(figsize=(8, 6), color='green', title = 'Line Plot', fontsize=12)

在本教程中,我们将学习更多的造型技巧。

区域地块

我将使用相同的系列“a ”,并在这里绘制一个面积图,

我可以用。plot()方法,并传递一个参数 kind 来指定我想要的绘图类型:

a.plot(kind='area')

或者我可以这样写

a.plot.area()

我上面提到的两种方法都会创建这个图:

当有几个变量时,面积图更有意义,看起来也更好。因此,我将制作几个系列,制作一个数据表格,并从中制作一个面积图。

b = pd.Series([45, 22, 12, 9, 20, 34, 28, 19, 26, 38, 41, 24, 14, 32])
c = pd.Series([25, 38, 33, 38, 23, 12, 30, 37, 34, 22, 16, 24, 12, 9])
d = pd.DataFrame({'a':a, 'b': b, 'c': c})

现在让我们把这个数据框画成面积图,

d.plot.area(figsize=(8, 6), title='Area Plot)

您不必接受这些默认颜色。让我们改变这些颜色,并添加一些更多的风格。

d.plot.area(alpha=0.4, color=['coral', 'purple', 'lightgreen'],figsize=(8, 6), title='Area Plot', fontsize=12)

可能参数α对你来说是新的。

“alpha”参数为绘图增加了一些半透明的外观。

当我们有重叠的面积图、直方图或密集散点图时,它显得非常有用。

这个。plot()函数可以制作十一种类型的图:

  1. 线条
  2. 区域
  3. 酒吧
  4. barh
  5. 馅饼
  6. 箱子
  7. 赫克宾
  8. kde
  9. 密度
  10. 分散

我想展示所有这些不同情节的用法。为此,我将使用美国疾病控制和预防中心的 NHANES 数据集。我下载了这个数据集,并把它保存在 Jupyter 笔记本所在的文件夹中。请随意下载数据集并跟随:

https://github.com/rashida048/Datasets/blob/master/nhanes_2015_2016.csv

在这里,我导入数据集:

df = pd.read_csv('nhanes_2015_2016.csv')
df.head()

这个数据集有 30 列和 5735 行。

在开始绘制图之前,检查数据集的列很重要:

df.columns

输出:

Index(['SEQN', 'ALQ101', 'ALQ110', 'ALQ130', 'SMQ020', 'RIAGENDR', 'RIDAGEYR', 'RIDRETH1', 'DMDCITZN', 'DMDEDUC2', 'DMDMARTL', 'DMDHHSIZ', 'WTINT2YR', 'SDMVPSU', 'SDMVSTRA', 'INDFMPIR', 'BPXSY1', 'BPXDI1', 'BPXSY2', 'BPXDI2', 'BMXWT', 'BMXHT', 'BMXBMI', 'BMXLEG', 'BMXARML', 'BMXARMC', 'BMXWAIST', 'HIQ210', 'DMDEDUC2x', 'DMDMARTLx'], dtype='object')

这些列的名称可能看起来很奇怪。但是不要担心这个。在我们进行的过程中,我会继续解释这些列的含义。我们不会使用所有的列。我们将使用其中一些来练习这些情节。

直方图

我会用人口的权重做一个基本的直方图。

df['BMXWT'].hist()

提醒一下,直方图提供了频率的分布。上图显示,约 1825 人体重 75。最大人数的权重范围为 49 到 99。

如果我想在一个图中放几个直方图呢?

我将使用体重、身高和身体质量指数(身体质量指数)在一张图中绘制三个直方图。

df[['BMXWT', 'BMXHT', 'BMXBMI']].plot.hist(stacked=True, bins=20, fontsize=12, figsize=(10, 8))

但是,如果您想要三个不同的直方图,也可以只使用一行代码,如下所示:

df[['BMXWT', 'BMXHT', 'BMXBMI']].hist(bins=20,figsize=(10, 8))

还可以更动感!

我们在“BPXSY1”列中有收缩压数据,在“DM deduct 2”列中有教育水平。如果我们想检查每个教育水平的人群中收缩压的分布,也只需一行代码即可完成。

但在此之前,我想用更有意义的字符串值替换“DM deduct 2”列的数值:

df["DMDEDUC2x"] = df.DMDEDUC2.replace({1: "less than 9", 2: "9-11", 3: "HS/GED", 4: "Some college/AA", 5: "College", 7: "Refused", 9: "Don't know"})

现在做直方图,

df[['DMDEDUC2x', 'BPXSY1']].hist(by='DMDEDUC2x', figsize=(18, 12))

看啊!我们仅用一行代码就获得了每个教育水平的收缩压水平分布!

柱状图

现在我们来看看收缩压是如何随婚姻状况变化的。这次我将制作一个条形图。像以前一样,我将用更有意义的字符串替换“DMDMARTL”列的数值。

df["DMDMARTLx"] = df.DMDMARTL.replace({1: "Married", 2: "Widowed", 3: "Divorced", 4: "Separated", 5: "Never married", 6: "Living w/partner", 77: "Refused"})

为了制作柱状图,我们需要对数据进行预处理。也就是把数据按不同的婚姻状况分组,取每组的平均值。在这里,我在同一行代码中处理数据和绘图。

df.groupby('DMDMARTLx')['BPXSY1'].mean().plot(kind='bar', rot=45, fontsize=10, figsize=(8, 6))

这里我们使用“rot”参数将 x 刻度旋转 45 度。否则,它们会太杂乱。

如果你愿意,你也可以把它做成水平的,

df.groupby('DMDEDUC2x')['BPXSY1'].mean().plot(kind='barh', rot=45, fontsize=10, figsize=(8, 6))

我想做一个多变量的柱状图。我们有一列包含人口的民族血统。看看人们的体重、身高和身体质量指数是否会随着种族的不同而变化,这将是一件有趣的事情。

为了绘制图表,我们需要将这三列(体重、身高和身体质量指数)按种族分组并取平均值。

df_bmx = df.groupby('RIDRETH1')['BMXWT', 'BMXHT', 'BMXBMI'].mean().reset_index()

这一次我没有更改民族血统数据。我保留了原来的数值。现在让我们制作柱状图,

df_bmx.plot(x = 'RIDRETH1', 
            y=['BMXWT', 'BMXHT', 'BMXBMI'], 
            kind = 'bar', 
            color = ['lightblue', 'red', 'yellow'], 
            fontsize=10)

看起来第四种族比其他种族高一点。但是都很接近。没有显著差异。

我们也可以将不同的参数(体重、身高和体重指数)相互叠加。

df_bmx.plot(x = 'RIDRETH1', 
            y=['BMXWT', 'BMXHT', 'BMXBMI'], 
            kind = 'bar', stacked=True,
            color = ['lightblue', 'red', 'yellow'], 
            fontsize=10)

派剧情

这里我想检查一下婚姻状况和教育是否有关系。

我需要按教育程度对婚姻状况进行分组,并按教育程度统计每个婚姻状况组中的人口。听起来太罗嗦了吧?让我们看看:

df_edu_marit = df.groupby('DMDEDUC2x')['DMDMARTL'].count()
pd.Series(df_edu_marit)

使用这个系列很容易做出一个饼图:

ax = pd.Series(df_edu_marit).plot.pie(subplots=True, label='',
     labels = ['College Education', 'high school', 
     'less than high school', 'Some college',
     'HS/GED', 'Unknown'],
     figsize = (8, 6),
     colors = ['lightgreen', 'violet', 'coral', 'skyblue', 'yellow', 'purple'], autopct = '%.2f')

这里我添加了一些样式参数。请随意尝试更多的样式参数。

箱线图

例如,我将使用体重指数、腿和臂长数据绘制一个方框图。

color = {'boxes': 'DarkBlue', 'whiskers': 'coral', 
         'medians': 'Black', 'caps': 'Green'}
df[['BMXBMI', 'BMXLEG', 'BMXARML']].plot.box(figsize=(8, 6),color=color)

散点图

对于一个简单的散点图,我想看看身体质量指数(“BMXBMI”)和收缩压(“BPXSY1”)之间是否有任何关系。

df.head(300).plot(x='BMXBMI', y= 'BPXSY1', kind = 'scatter')

这太简单了!我只使用了 300 个数据,因为如果我使用所有的数据,散点图会变得过于密集,难以理解。尽管你可以使用 alpha 参数使其半透明。在本教程中,我倾向于保持轻松。

现在,让我们用同一行代码检查一个高级散点图。

这次我将添加一些颜色阴影。我将绘制一个散点图,x 轴表示重量,y 轴表示高度。有一点曲折!

我还会加上腿的长度。但是腿的长度会显示在阴影中。如果腿的长度更长,颜色会更深,否则颜色会更浅。

df.head(500).plot.scatter(x= 'BMXWT', y = 'BMXHT', c ='BMXLEG', s=50, figsize=(8, 6))

它显示了体重和身高的关系。你可以看看腿的长度与身高和体重之间是否有关系。

另一种增加第三个参数的方法是增加粒子的大小。在这里,我把身高放在 x 轴,体重放在 y 轴,体重指数作为气泡大小的指标。

df.head(200).plot.scatter(x= 'BMXHT', y = 'BMXWT', 
                          s =df['BMXBMI'][:200] * 7, 
                          alpha=0.5, color='purple',
                         figsize=(8, 6))

这里,小点表示身体质量指数较低,大点表示身体质量指数较高。

Hexbin

另一种美丽的可视化形式,点是六角形的。当数据太密集时,将它们放在箱中是有用的。正如你所看到的,在前面的两个图中,我只使用了 500 和 200 个数据,因为如果我把所有的数据都放在数据集中,图会变得太密集,无法理解或从中获得任何信息。

在这种情况下,使用空间分布会非常有用。我用的是 hexbin,数据用六边形表示。每个六边形是一个箱,代表该箱的密度。这是一个最基本的六邻体蛋白的例子。

df.plot.hexbin(x='BMXARMC', y='BMXLEG', gridsize= 20)

这里,较深的颜色代表较高的数据密度,较浅的颜色代表较低的数据密度。

听起来像直方图吗?是的,对吗?它不是用线条,而是用颜色来表示。

如果我们增加一个额外的参数 C,分布就会改变。它将不再像一个直方图。

参数“C”指定每个(x,y)坐标的位置,对每个六边形面元进行累加,然后使用 reduce_C_function 进行缩减。如果没有指定 reduce_C_ function,默认使用 np。卑鄙。你可以把它指定为 np。意思是,np。马克斯,np。sum,np。std 等。

查看文档了解更多信息 这里

这里有一个例子:

df.plot.hexbin(x='BMXARMC', y='BMXLEG', C = 'BMXHT',
                         reduce_C_function=np.max,
                         gridsize=15,
                        figsize=(8,6))

这里六边形的深色表示 np。max 有一个更高的人口高度值(' BMXHT '),你可以看到我用了 np。max 作为 reduce_C_function。您可以使用色彩映射表来代替颜色阴影:

df.plot.hexbin(x='BMXARMC', y='BMXLEG', C = 'BMXHT',
                         reduce_C_function=np.max,
                         gridsize=15,
                        figsize=(8,6),
                        cmap = 'viridis')

看起来很漂亮,对吧?而且信息量也很大。

一些高级的可视化

我解释了一些人们在日常生活中处理数据时使用的基本绘图。但是数据科学家需要更多。熊猫图书馆也有一些更先进的可视化。这可以在一行代码中提供更多的信息。

散点 _ 矩阵

Scatter_matrix 非常有用。它在一个图中提供了大量的信息。它可以用于一般的数据分析或机器学习的特征工程。我们先来看一个例子。之后我会解释。

from pandas.plotting import scatter_matrixscatter_matrix(df[['BMXWT', 'BMXHT', 'BMXBMI', 'BMXLEG', 'BMXARML']], alpha = 0.2, figsize=(10, 8), diagonal = 'kde')

看那个!我在这里使用了五个特性。我得到了所有五个变量之间的关系。在对角线上,它给出了每个单独特征的密度图。我们将在下一个例子中讨论密度图。

KDE 或密度图

构建 KDE 图或核密度图是为了提供数据帧中一个系列或一列的概率分布。让我们来看看权重变量(' BMXWT ')的概率分布。

df['BMXWT'].plot.kde()

你可以在一张图中看到几种概率分布。在这里,我在同一张图中绘制了身高、体重和身体质量指数的概率分布:

df[['BMXWT', 'BMXHT', 'BMXBMI']].plot.kde(figsize = (8, 6))

您也可以使用我们之前描述的其他样式参数。我喜欢保持简单。

平行 _ 坐标

这是显示多维数据的好方法。它清楚地显示了集群(如果有的话)。例如,我想看看男性和女性在身高、体重和身体质量指数方面是否有差异。让我们检查一下。

from pandas.plotting import parallel_coordinatesparallel_coordinates(df[['BMXWT', 'BMXHT', 'BMXBMI', 'RIAGENDR']].dropna().head(200), 'RIAGENDR', color=['blue', 'violet'])

你可以看到男性和女性在体重、身高和身体质量指数方面的明显差异。在这里,1 是男性,2 是女性。

自举 _ 剧情

这对于研究和统计分析是非常重要的。会节省很多统计分析的时间。自举图用于评估给定数据集的不确定性。

该函数随机抽取指定大小的样本。然后计算该样本的平均值、中间值和中间值。这个过程重复指定的次数。

在这里,我使用身体质量指数数据创建了一个自举图:

from pandas.plotting import bootstrap_plotbootstrap_plot(df['BMXBMI'], size=100, samples=1000, color='skyblue')

这里,样本量为 100,样本数为 1000。因此,我们随机抽取了 100 个数据样本来计算平均值、中间值和中间值。这个过程重复 1000 次。

这是一个极其重要的过程,也是统计学家和研究人员节省时间的方法。

结论

我想为熊猫的数据可视化做一个备忘单。虽然如果你使用 matplotlib 和 seaborn,有更多的可视化选项或类型。但是如果我们处理数据,我们在日常生活中会用到这些基本的可视化类型。使用 pandas 进行可视化将使您的代码更加简单,并节省大量代码。

欢迎在推特上关注我,喜欢我的脸书页面。

更多阅读:

用 Python 的 Seaborn 库实现数据可视化的终极指南

原文:https://towardsdatascience.com/an-ultimate-cheatsheet-of-data-visualization-in-seaborn-be8ed13a3697?source=collection_archive---------14-----------------------

由 Unsplash 上的 CHUTTERSNAP 拍摄

一大堆情节

Seaborn 是一个基于 Matplotlib 的 python 数据可视化库。seaborn 有什么特别的?我们已经有了 Maplotlib,为什么还需要使用 seaborn?Matplotlib 可以满足您的需求。它具有执行数据故事项目所需的所有可视化功能。但是 seaborn 很特别,因为它有很多风格。样式已经内置了。与普通的 matplotlib 图相比,普通的 seaborn 图看起来要好得多!

此外,seaborn 库具有高级可视化功能,更具表现力,能够更有效地表达更多信息。

一点背景知识。如果您不熟悉 python 中的数据可视化,或者需要复习 Matplotlib,请看看这篇文章:

您也可以在 Pandas 中执行数据可视化。当你在 pandas 中调用 plot()函数时,它在后台使用 Matplotlib。

复习部分完成了。让我们现在潜入海底。

我将从基本的情节开始,然后慢慢转向一些更高级的。

我主要使用内置数据集。因此,安装了 seaborn 库的任何人都可以很容易地获得它们。

我将反复使用相同的变量,以节省寻找新数据集的时间。我的目标是为你展示可视化功能的选择。

首先导入必要的包和著名的 iris 数据集:

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as snsiris = sns.load_dataset('iris')
iris

从 Matplotlib 中非常基本的散点图开始,然后是 Seaborn,以显示相同图中基本部分的差异。Matplotlib 中萼片长度与萼片宽度的基本散点图:

plt.scatter(iris.sepal_length, iris.sepal_width)

这是《海波恩》中相同的基本情节:

sns.set()
plt.scatter(iris.sepal_length, iris.sepal_width)

您可以看到,它甚至没有编写太多额外的代码就添加了一种样式!

我会尽量保持精确。大部分代码几乎是不言自明的。如果你是为了学习而阅读这篇文章的话,请把代码拿到你自己的笔记本上运行,改变不同的选项,然后玩一玩。这是唯一的学习方法。

在前面的情节中你已经看到。set()函数可以在绘图中引入默认的 seaborn 样式。下面是 set_style()函数的一个例子。

sns.set_style('whitegrid')
plt.scatter(iris.sepal_length, iris.sepal_width)
plt.show()

set_style()函数有一些其他的样式选项:深色网格、深色、白色和刻度。请随意试用它们。

下一个图也将是萼片长度对萼片宽度。但是花瓣长度参数也将被添加到它。圆点的大小会根据花瓣的长度而改变。

sns.set_style('darkgrid')
sns.set_context('talk', font_scale=1.1)
plt.figure(figsize=(8, 6))
sns.scatterplot(iris.sepal_length, iris.sepal_width, data=iris)
plt.xlabel("Sepal Length")
plt.ylabel("Sepal Width")
plt.title("Sepal Length vs Sepal Width")
plt.show()

圆点越大,花瓣越长。

此图中还引入了另一个新功能。那就是 set_context() 。它控制线条、标签和其他类似参数的大小。在该图中使用了“talk”选项。set _ context()函数中还有“纸张”、“笔记本”和“海报”选项。请检查一下。

这里可以轻松地添加一个变量。我将在这块土地上增加花的种类。不同物种的圆点颜色会有所不同。

sns.set_context('talk', font_scale=1.1)
plt.figure(figsize=(8, 6))
sns.scatterplot(iris.sepal_length, iris.sepal_width, 
                size="petal_length", data=iris,
               sizes=(20, 500), hue="species", 
                alpha=0.6, palette="deep")
plt.xlabel("Sepal Length")
plt.ylabel("Sepal Width")
plt.title("Sepal Length vs Sepal Width")
plt.legend(bbox_to_anchor = (1.01, 1), borderaxespad=0)
plt.show()

重新绘图

relplot 函数既有趣又能提供信息。 Relplots 可以是折线图或散点图。这是一个折线图,每条线都显示置信区间。

如果不想要置信带,在 relplot 函数中添加“ci = None”。

我不会那么做的。因为我想要信心乐队。

sns.relplot(iris.sepal_length, iris.sepal_width, 
                data=iris, kind='line', hue='species')
plt.xlabel("Sepal Length")
plt.ylabel("Sepal Width")
plt.title("Sepal Length vs Sepal Width")
plt.show()

距离图

distplot 给出了直方图,一个连续变量的分布。这里有一个基本的。

plt.figure(figsize=(8, 6))
sns.distplot(iris.sepal_length)
plt.show()

如果您不想要密度曲线,在 distplot 函数中添加 kde = False 。下一个图是没有密度曲线的垂直直方图。

plt.figure(figsize=(8, 6))
sns.distplot(iris.sepal_length, vertical=True, kde=False, color='red')
plt.show()

直方图甚至可以提供更多信息。您可以用分类变量分隔连续变量的直方图。为了演示,我将使用不同的数据集。

tips = sns.load_dataset("tips")
tips.head()

该图将显示每个物种的鳍状肢长度,并按性别分类。

g = sns.displot(
    tips, x="total_bill", col="day", row="sex",
    binwidth=3, height=3, facet_kws=dict(margin_titles=True))
g.fig.set_size_inches(18, 10)
g.set_axis_labels("Total Bill", "Frequency")

因此,我们将账单总额的分布按照星期几和性别进行了划分。

也可以制作类似的重绘图。下面的 relplot 显示了按一周中的某一天和一天中的某个时间划分的账单总额与小费的散点图。

sns.set_context('paper', font_scale=1.8)
sns.relplot('total_bill', 'tip', data=tips, hue="time", col='day', col_wrap=2)

条形图

另一个广泛使用和流行的情节。在小费数据集中,我将在 x 轴上使用“大小”变量,总账单将在 y 轴上绘制。

总账单将按午餐和晚餐时间分开。

plt.figure(figsize=(8, 6))
sns.barplot(x='size', y= 'total_bill', hue='time', 
            palette = 'GnBu',
            data=tips, ci='sd',
           capsize=0.05,
           saturation=5,
           errcolor='lightblue',
           errwidth=2)
plt.xlabel("Size")
plt.ylabel("Total Bill")
plt.title("Total Bill Per Day of Week")
plt.show()

注意,我在这里使用调色板作为“GnBu”。seaborn 库中有几个不同的调色板。 页面 找到不同的调色板选项。

如果你对统计学感兴趣,你会喜欢这里的“ci”选项。否则,用' ci=None' 就可以避免。

计数图

计数图看起来也像条形图。但是它显示了每个类别的观察计数。

plt.figure(figsize=(8, 6))
sns.countplot(x='day', data=tips)
plt.xlabel("Day")
plt.title("Total Bill Per Day of Week")
plt.show()

该图显示了一周中每天有多少数据可用。“hue”参数在这里也可以用于通过另一个分类变量将其分离。我在考虑“时间”变量。

plt.figure(figsize=(8, 6))
sns.countplot(x = 'day', hue='time', 
            palette = 'GnBu',
            data=tips)
plt.xlabel("Day")
plt.title("Tip Per Day of Week")
plt.show()

群集图

该图确保数据不会重叠。剧情之后再多解释。

plt.figure(figsize=(8, 6))
sns.set_style('whitegrid')
sns.swarmplot(x='size', y='total_bill', data=tips)
plt.xlabel("Size")
plt.ylabel("Total Bill")
plt.title("Total bill per size of the table")
plt.show()

当大小为 1 时,只有三个点,它们在同一条线上,自然不会重叠。但是当大小为 2 时,在同一个点上有很多数据,所以默认情况下 swarmplot 稍微调整了点的位置,使它们不相互重叠。

这看起来不错,而且当数据集不太大时,还可以更好地了解每个点有多少数据。如果数据集太大,群集图就不能很好地缩放。

在下一个图中,我将添加一个“色调”参数,它将显示不同性别的不同颜色。

plt.figure(figsize=(10, 6))
sns.set_style('whitegrid')
sns.set(font_scale=1.5)
sns.swarmplot(x='size', y='total_bill', data=tips, hue="sex")
plt.xlabel("Day")
plt.ylabel("Total Bill")
plt.legend(title="Time", fontsize=14)
plt.show()

性别隔离也可以被分开,

plt.figure(figsize=(10, 6))
sns.set_style('whitegrid')
sns.set(font_scale=1.5)
sns.swarmplot(x='size', y='total_bill', data=tips, hue="sex", split=True)
plt.xlabel("Size")
plt.ylabel("Total Bill")
plt.legend(title="Time", fontsize=14)
plt.show()

在这片土地上,雄性和雌性有不同的群体。

还有另一种称为因子图的图,它与群集图相同,但它是面网格图。您可以添加多个变量并提供更多信息。

g = sns.factorplot(x='size', y="tip",
              data=tips, hue="time",
              col="day", kind="swarm",
              col_wrap=2, size=4)g.fig.set_size_inches(10, 10)
g.set_axis_labels("Size", "Tip")
plt.show()

该图显示了一周中每一天每份食物的小费金额,不同的颜色代表了用餐的不同时间。如此多的信息被压缩在一个情节中!

点图

点图可以提供很多信息,比条形图更有用。这是一个显示一周中每天小费金额的点图。情节之后我会再解释一些。

plt.figure(figsize=(8, 6))
sns.pointplot(x="day", y="tip", data=tips)
plt.xlabel("Day")
plt.ylabel("Tip")
plt.title("Tip Per Day of Week")
plt.show()

这里的点表示平均值,垂直线表示置信区间。有时候少即是多。简单而又丰富的情节。

可以在这里添加一个“色调”参数,通过另一个分类变量显示一周中每天的小费。我在这里用了性别。

plt.figure(figsize=(8, 6))
sns.pointplot(x="day", y="tip", hue="sex", data=tips, palette="Accent")
plt.xlabel("Day")
plt.ylabel("Tip")
plt.title("Tip Per Day of Week by Gender")
plt.show()

性别在小费金额上的差异如此明显!

Regplot

这实际上是一个散点图,增加了一条线性回归线和一个置信带。

plt.figure(figsize=(8, 6))
sns.set_style('whitegrid')
sns.regplot(x='total_bill', y='tip', data=tips)
plt.xlabel("Total Bill")
plt.ylabel("Tip")
plt.show()

接合图

联合绘图仅用一行代码在一个绘图中显示两种不同类型的绘图。默认情况下,散点图位于中心,x 和 y 变量的分布位于边缘。“hue”参数在这里是可选的。有需要就用。

sns.set_style('dark')
g = sns.jointplot(x='total_bill', y='tip', hue='time', data=tips)
g.fig.set_size_inches(8, 8)
g.set_axis_labels("Total Bill", "Tip")
plt.show()

该图是一个散点图,显示了账单总额与小费金额之间的关系,按“时间”进行划分。不同的颜色显示了用餐的不同时间。侧图显示了午餐和晚餐时间总账单和小费金额的分布。

如果您不喜欢默认选项,还有几个其他选项可用。这里我明确提到 regplot,它是一个散点图,带有一条线性回归线和置信带。

sns.set_style('darkgrid')
g = sns.jointplot(x='total_bill', y='tip', data=tips, kind='reg')
g.fig.set_size_inches(8, 8)
g.set_axis_labels("Total Bill", "Tip")
plt.show()

下一个图将不是散点图,而是 kde 图,

sns.set_style('darkgrid')
g = sns.jointplot(x='total_bill', y='tip', data=tips, kind='kde')
g.fig.set_size_inches(8, 8)
g.set_axis_labels("Total Bill", "Tip")
plt.show()

在这个 kde 图中可以随意使用“色调”参数,

sns.set_style('darkgrid')
g = sns.jointplot(x='total_bill', y='tip', hue='time', data=tips, kind='kde')
g.fig.set_size_inches(8, 8)
g.set_axis_labels("Total Bill", "Tip")
plt.show()

比起阴影线,kde 图总是更吸引我。下面有一个带阴影的 kde 图。

plt.figure(figsize=(8, 6))
sns.set_style('whitegrid')
g = sns.kdeplot(x='total_bill', y='tip', shade=True, data=tips)
plt.xlabel("Total Bill")
plt.ylabel("Tip")
plt.show()

阴影图显示了数据的密度。我觉得它更有表现力。

回到 jointplot,这里有一个 jointplot 中 hexplot 的例子。又一个美好的情节。

sns.set_style('dark')
g = sns.jointplot(x='total_bill', y='tip', data=tips, kind='hex')
g.fig.set_size_inches(8, 8)
g.set_axis_labels("Total Bill", "Tip")
plt.show()

当数据集太大时,Hexplot 特别有用。

抖动图

抖动图有点像之前展示的蜂群图。这一个也稍微调整了点的坐标以避免太多的混乱。但是有点不一样。在蜂群图中,没有一个点在另一个点的上面。但在抖动图中,它仅展开指定的量。下面是一个抖动图,指定抖动量为 0.2。此外,默认情况下,它添加了一个线性回归线和一个置信区间,这很好!

plt.figure(figsize=(8, 6))
sns.set_style('whitegrid')
sns.regplot(x='size', y='total_bill', data=tips, x_jitter=0.2)
plt.xlabel("Size")
plt.ylabel("Total Bill")
plt.show()

注意,这里的 x 轴包含一个分类变量。

lmplot

lmplot 是 regplot 和 facet grid 的组合。该图可以显示每个条件组的线性回归线和置信带。这听起来可能有点晦涩。请看这个情节。

sns.set(font_scale=1.5)
sns.lmplot(x='total_bill', y='tip', data = tips, 
           hue='time')
plt.gcf().set_size_inches(12, 8)
plt.ylabel("Total Bill")
plt.xlabel("Tip")
plt.show()

听着,午餐和晚餐时间都有回归线。

它甚至可以提供更多的信息。下面这张示意图显示的是每天的总账单和小费。

g = sns.lmplot(x='total_bill', y='tip', col="day", hue = "day", 
          data=tips, col_wrap=2, height=4)
g.fig.set_size_inches(11, 11)
g.set_axis_labels("Total Bill", "Tip")
plt.show()

箱线图

我不喜欢基本的箱线图。请看看我在开始提到的关于熊猫和 Matplotlib 的可视化教程,重温一下基本的情节。我喜欢箱线图,因为它能在同一个图中给出分布、中位数、IQR 和异常值的信息。下一个图将显示每个尺寸的总账单的箱线图。

sns.set(font_scale = 1.5)
sns.boxplot(x='size', y='total_bill', data=tips)
plt.gcf().set_size_inches(12, 8)
plt.xlabel("Size")
plt.ylabel("Total Bill")

如果您需要关于如何从箱线图中提取我之前提到的所有信息的提示,请阅读这篇文章:

紫罗兰花

这里是一个基本的小提琴情节。

ax = sns.violinplot(x=tips["total_bill"])

小提琴图显示了数据的分布。你可能会认为它就像一个直方图。可以,但是可以更高级。如下图所示,吸烟者和非吸烟者每天的总账单分配情况。

plt.figure(figsize=(10, 7))
sns.violinplot(x='day', y='total_bill', hue="smoker",
              data=tips, palette="muted")
plt.xlabel("Day")
plt.ylabel("Total Bill")
plt.title("Total Bill per Day of the Week")
plt.show()

吸烟者和不吸烟者的部分可以显示在一把小提琴的不同侧面上,而不是由两把小提琴分开。看这个情节。

plt.figure(figsize=(10, 7))
sns.violinplot(x='day', y='total_bill', hue="smoker",
              data=tips, palette="muted", split=True)
plt.xlabel("Day")
plt.ylabel("Total Bill")
plt.title("Total Bill per Day of the Week")
plt.show()

这里蓝色显示的是吸烟者总账单的分布,黄色代表不吸烟者。

小提琴情节可以与其他类型的情节结合。这是一个在小提琴图中显示蜂群图的例子。它看起来很好,并且给出了与这些分布相关的数据量的概念。

plt.figure(figsize=(10, 6))sns.violinplot(x='day', y='total_bill', inner=None,
              data=tips, palette="muted")sns.swarmplot(x='day', y='total_bill',
              data=tips, color="k", alpha=0.9)
plt.ylabel("Total Bill")
plt.xlabel("Day")
plt.title("Total Bill per Day")
plt.show()

热图

热图用于显示变量之间的相关性。热图在数据科学的许多领域非常有用。在数据故事项目中,这是一个受欢迎的元素,在机器学习中,它有助于选择特征。

这是一个基本的热图,显示了总账单和小费金额之间的关系。

sns.heatmap(tips[["total_bill", "tip"]].corr(), annot=True, 
            linewidths=0.9, linecolor="gray")
plt.show()

让我们回到虹膜数据集。看到萼片长度和宽度、花瓣长度和宽度之间的相互关系将会很有趣。

plt.figure(figsize=(8, 6))
sns.heatmap(iris.corr(), annot=True, linewidths=0.5, cmap='crest')
plt.show()

看色彩图。颜色越深,相关性越强。

facetgrid

我们以前处理过 facetgrid 样式的地块。但是没有直接使用函数 facet grid。以下是小平面网格函数的一个示例:

g = sns.FacetGrid(tips, col="time")
g.map(sns.scatterplot, "total_bill", "tip")
g.fig.set_size_inches(12, 8)
g.set_axis_labels("Total Bill", "Tip")
plt.show()

它还可以进一步被性别所分隔。

g = sns.FacetGrid(tips, col="time", row="sex")
g.map(sns.scatterplot, "total_bill", "tip")
g.fig.set_size_inches(12, 12)
g.set_axis_labels("Total Bill", "Tip")
plt.show()

配对图

又一个很有用的情节。你自己看个例子吧,之后我们会解释。

df = sns.load_dataset('iris')
sns.set_style('ticks')
sns.pairplot(df, hue="species", diag_kind='kde', kind='scatter', palette='husl')
plt.show()

该图显示了同一图中每对变量之间的关系。同时,给你每个连续变量的分布。我们在这里设置“色调=物种”来表示不同物种的不同颜色。这个图中包含了如此多的奇异图的信息。

本教程是不完整的,甚至没有显示一个时间序列热图。

我将在接下来的图中使用以下数据集:

https://github.com/rashida048/Datasets/blob/master/stock_data.csv

让我们导入数据集:

df = pd.read_csv("stock_data.csv", parse_dates=True, index_col = "Date")
df.head()

我们的目标是按月份和年份绘制“开放”数据的热图。为此,我们需要从“日期”中检索月份和年份,并分别列出“月份”和“年份”。

df['month'] = df.index.month
df['year'] = df.index.year

如果您重新检查数据集,您会发现其中有一个“月”和“年”列。使用 pandas pivot table 函数,创建月和年的数据集,其中月是索引,年是列,“开放”数据是值。

import calendar
all_month_year_df = pd.pivot_table(df, values="Open",
                                   index=["month"],
                                   columns=["year"],
                                   fill_value=0,
                                   margins=True)
named_index = [[calendar.month_abbr[i] if isinstance(i, int) else i for i in list(all_month_year_df.index)]] # name months
all_month_year_df = all_month_year_df.set_index(named_index)
all_month_year_df

数据集已准备好制作我们的热图!

plt.figure(figsize=(10,10))
ax = sns.heatmap(all_month_year_df, cmap='GnBu', robust=True, fmt='.2f', 
                 annot=True, linewidths=.5, annot_kws={'size':11}, 
                 cbar_kws={'shrink':.8, 'label':'Open'})                       

ax.set_yticklabels(ax.get_yticklabels(), rotation=0, fontsize=10)
ax.set_xticklabels(ax.get_xticklabels(), rotation=0, fontsize=10)
plt.title('Average Opening', fontdict={'fontsize':18},    pad=14)

聚类图

聚类图也类似于热图。它不显示数字。仅按颜色进行分层聚类。让我们看一个例子:

sns.clustermap(all_month_year_df, linewidths=.5, cmap = "coolwarm")

查看该图中的 x 和 y 刻度标签。它们遵循集群的层次结构。2017 年最高,2016 年最低。如果您希望按顺序排列年份,请将“col_cluster”设置为 False。

sns.clustermap(all_month_year_df, linewidths=.5, cmap = "coolwarm", col_cluster=False)

现在,年是有序的。您也可以通过将“row_cluster”设置为 False 来按顺序排列月份。请你自己试试。

请随意查看这篇文章,以找到各种时间序列数据可视化选项:

结论

恭喜你。如果你今天真的在所有这些地块上工作了,你走了很长的路!Seaborn 是一个巨大的图书馆。当然,这些还不是全部。但是这篇文章涵盖了很多!关于这个库还有很多需要了解的。我希望在将来的某个时候能制作更多关于更多情节的教程。但在此之前,请随意阅读下面“更多阅读”部分的 python 文章中的高级可视化。他们在 Matplotlib 和 Seaborn 收集了更多的高级地块。

欢迎在推特上关注我,并喜欢我的脸书页面。

更多阅读:

https://medium.com/illumination/a-practical-pathway-to-get-your-first-2000-followers-on-medium-42df26ce6571

Python 的终极(免费)数据可视化编译

原文:https://towardsdatascience.com/an-ultimate-data-visualization-course-in-python-for-free-12a5da0a517b?source=collection_archive---------22-----------------------

在 Unsplash 上由 nine koepfer 拍摄的照片

学习使用更多的可视化功能和技术

如果您以任何方式处理数据,数据可视化是必不可少的。我非常关注这一点。我以前写过几篇关于 Python 中数据可视化的文章。我意识到如果我在一个页面上编译它们,它可能会成为一个巨大的数据绘图技术的集合。您可以从这里学到的数据可视化的数量可能会与任何付费的可视化课程相媲美。

Matplotlib

这可以说是 Python 中最流行、最常用的可视化库。还有其他基于 Matplotlib 构建的高质量 python 库。即使您使用 python 的其他一些库,学习 Matplotlib 也是一个好主意。下面这篇文章是我们在日常生活中使用的 Matplotlib 中所有基本图形的备忘单,以及一些指向更高级图形的链接:

这里是其中一些图的视频版本,包含一些更多的样式技术和一些更高级的选项,特别是柱状图、柱状图、箱线图和支线图:

熊猫

熊猫图书馆以数据操作和数据清理而闻名。但是它也有一些可视化的功能。当你使用它们时,它会在后台调用 Matplotlib 并为你渲染图形。问题是为什么我们需要用熊猫呢?答案是,它为您节省了几行代码,而且运行速度很快。在这里你可以找到熊猫图书馆中所有主要的可视化技术:

有时,在一个包含大量信息的图中使用多个图会很有帮助。此外,它还可以生成仪表板样式的绘图,这在报告或演示文稿中非常有用。本文解释了如何在绘图数组中进行完全控制和定制形状绘图:

高级可视化

Seaborn

Seaborn 库建立在 Matplotlib 之上。它受欢迎的原因是,它有一些内置的风格。最基本的情节也已经有了一些风格。因此,它节省了一些造型工作。同时,Seaborn 库有很多高级的可视化功能。只需几行代码,你就可以创造出惊人的情节。以下文章从基本的 Seaborn 情节开始,涵盖了许多高级情节:

时间序列可视化

它不是一个单独的图书馆。使用 Matplotlib 和 Seaborn,您可以实现出色的时间序列数据可视化。但是对于时间序列数据,你需要处理一些格式化的任务。所以,它需要一些关注。这就是为什么他们有自己的形象。在这里,您可以找到完整的时间序列可视化教程:

收集一些高级剧情

如果您经常处理数据,您可能希望让您的图看起来更有趣。尤其是当您必须制作大型报表时,最好选择不同的可视化样式。我整理了一些更有趣的可视化样式,不同的外观可能包含更多信息:

结论

Python 有几个库。甚至我主要关注的 Matplotlib 和 Seaborn 也是具有大量可视化选项的大型库。没有人能记住所有这些,除非你是一个超人或者多年来每天都在处理数据可视化。学习它们是一个好主意,这样你就知道你能做什么。然后准备一些资源,在需要的时候可以随时查看。所有这些可视化教程都可以用来学习,也可以用来做备忘单。希望有帮助。

欢迎在推特上关注我,并喜欢我的脸书页面。

更多阅读

匹配和倾向评分匹配终极指南

原文:https://towardsdatascience.com/an-ultimate-guide-to-matching-and-propensity-score-matching-644395c46616?source=collection_archive---------3-----------------------

实践教程,使用观察数据进行因果推断

如何减少观察数据中混杂因素的影响

由拉尔夫·梅休在 Unsplash 上拍摄的照片

2021 年 8 月 15 日更新

介绍

随机对照试验(又名。A/B 测试)是确定干预和结果之间因果关系的黄金标准。RCT 的高效度源于其通过随机化过程对数据生成过程(DGP)的严密控制,使得实验组在很大程度上具有可比性。因此,我们可以将实验组之间最终指标的差异归因于干预。

它的缺点是,由于实际原因,RCT 在现实世界中并不总是可行的。公司没有实验基础设施来促进大规模测试。或者,高用户干扰会使个体水平随机化的任何结果无效。

在这种情况下,当 A/B 测试被搁置时,幸运的是我们有两种选择:准实验设计和观察设计。在几篇文章中,我介绍了几种准实验设计:差异中的差异、回归不连续设计、间断时间序列、和综合控制。

在今天的帖子中,我们转向观察性设计,重点关注两种观察方法——匹配和倾向得分匹配——并特别关注 PSM 的基本假设、限制和应用。

在未来的帖子中,我们将更深入地研究序列“使用观察数据的因果推断”,并讨论高级主题,如、倾向评分分层、治疗加权的逆概率和协变量调整。

对观测数据的一些抱怨

与具有清晰 DGP 的实验数据相反,研究人员不知道也不能控制治疗分配过程。我们只观察到一些受试者属于一个组(如治疗组),而其他受试者属于另一个组(如对照组),但不知道他们为什么会出现在那里。这两个群体之间的任何直接比较都是没有意义和误导性的。

为什么?

可能会有混杂变量影响分配过程和结果变量。

这是程序评估文献中的一个经典例子。比方说,我们正试图评估一个针对失业者的职业培训项目的有效性,这个项目是通过家庭年收入来衡量的。

由于道德约束,RCT 是不可能的。想想媒体的影响,如果公众意识到一部分人可以参加有益的社会项目,但不是所有人。

一个更好的选择是采用观察设计。

问题仍然是:我们能直接比较注册和未注册之间的目标度量来评估计划的有效性吗?

不要!

那些参与者可能比其他人更有动力和渴望找到工作。因此,结果指标的差异可能是由动机水平(一个混杂变量)而不是治疗状态(参与计划)引起的。换句话说,参与者即使不参加该计划也会做得更好(Gertler 等人,2011)。

我自己的截图

注:

  • 虚线表示变量之间没有因果关系
  • 实线表示因果关系

观察法的首要任务是找到一种方法来减少或消除选择偏差或混杂变量的影响。

选择可比反事实的三个条件

到一天结束时,因果推理是关于反事实的:如果没有干预,会发生什么?不幸的是,我们只能观察到两个潜在结果中的一个。从概念上来说,因果推理受到缺失数据问题的困扰,研究人员必须依靠标准程序来找到一个完美的克隆作为反事实。

由于随机化过程,这对于实验数据来说是一项简单的任务:我们可以在很大程度上相信治疗组和非治疗组之间的可比性。

然而,与实验方法相比,观察方法建立在更多的假设基础上,并做出仔细的推断。在选择控制案例时,我们必须牢记以下原则(Gertler 等人,2011 年):

宗旨 1:不要追求每个个体的相似性,而是群体水平的相似性。

原则 2:如果给予治疗,治疗组和对照组对治疗的反应应该相同。

原则 3:控制混杂因素。

宗旨 1 。无论你选择哪种估计量来估计,因果推断从来都不是关于每个个体单位的因果效应。相反,它是关于群体(总体)水平的治疗效果,平均

宗旨二 。如果被分配到治疗组,两组对干预的反应是一样的。否则,就不可能获得因果效应。

宗旨 3 。如何控制混杂因素?

如何控制混杂因素?

如果混杂变量是可观察到的,我们可以通过将每个治疗个体与一个或多个对照相匹配来减少或消除协变量偏倚。假设倾向得分包含了关于选择过程的所有信息,那么倾向得分匹配获得了最佳的效率和一致性(Rosenbaum 和 Rubin,1983)。

不应有任何未观察到的变量;否则,估计量将是有偏差的和不一致的。

匹配

匹配是一个统计过程,试图根据关键的观察协变量将治疗受试者与对照受试者配对。

对于具有大量潜在对照的小治疗组,匹配是理想的。

基于匹配比例(一对一匹配、多对一匹配)、匹配对象的替换(有或无替换)、算法(贪婪、遗传或最优/完全匹配),有各种匹配策略(Kim 和 Steiner,2016)。

不可能在一篇博文中检查所有这些子类别。如果可能的话,我会在后续文章中研究一些最重要的方法。

倾向评分匹配

如果我们认为有多个混杂变量,由于缺乏数据,匹配所有变量可能是不可能的。作为一个解决方案,我们构建了一个比例条件概率接受治疗分配给定的协变量向量。

只有在少数罕见的情况下,已知分配治疗的概率,如在 RCT,真实的倾向评分仍然未知的观察设计。相反,我们必须使用 logit 或 probit 来估计它。

倾向得分是一个平衡得分:根据倾向得分,观察到的基线协变量的分布在治疗/对照受试者之间足够相似。换句话说,倾向得分为使用观察数据的有效因果推断提供了足够好的反事实。

倾向评分匹配模拟了 RCT,我们在倾向评分匹配样本中比较了治疗和未治疗受试者的结果(Austin,2011)。

然而,这是一个有争议的过程。正如 King 和 Nielsen (2019)所说,PSM 试图近似一个完全随机的实验,而不是一个分块随机的实验。因此,PSM 无法消除可以通过阻塞消除的协变量不平衡。我不会详细阐述这场辩论,把它留给以后的帖子。此外,金教授推荐其他类型的倾向得分分析,如倾向得分分层。

警告

PSM 有以下警告(Gertler 等人,2011 年):

警告 1:常见的支持。待治疗的倾向的范围在已治疗和未治疗的病例之间是相同或相似的。

警告 2:仅使用不受干预影响的基线特征进行匹配。

警告 3:潜在的混杂变量是可观察的,没有不可观察的变量;否则,估计是有偏差的。

警告 4:匹配最相关的特征,不应该将每个变量都放入等式中。

告诫 1 。在计算了治疗组和非治疗组的倾向后,我们得到了下图。在两个极端,缺乏共同的支持。在最右边,有更高概率接受治疗的人找不到可比较的对照。在最左边,接受治疗的概率较低的人找不到可比较的治疗案例。

在中档中有一个共同的支持,在未注册者和注册者之间有重叠。因此,我们不得不把我们的因果发现缩小到当地的平均治疗效果(晚期)。

格特勒等人,2011 年

警告 2 。在估计倾向得分时,我们不应该包括任何可能被干预改变的特征;否则,估计可能会有偏差。

告诫 3。没有正式的方法来测试它,我们必须依靠深入的领域知识来假设。在这种情况下,一些基于设计的想法就派上用场了。

首先,我们可以交叉检查不受干预影响的结果(Shadish 等人,2002)。

第二,我们可以添加第二个但概念上不同的对照组,允许对未受影响的结果进行类似的测试(Rosenbaum,2002)。

**告诫 4。仅包含决定注册状态的变量而非所有变量可提高估计值的精度。我们对登记过程了解得越多,倾向评分在构建可比群体时就越准确。

使用 PSM 的步骤 (Jalan 和 Ravallion,2003):

  1. 计算所有单位的倾向得分
  2. 按照某种匹配策略将治疗组与对照组进行匹配
  3. **检查协变量平衡&如果不平衡,使用替代规格重复步骤 1 和 2
  4. 计算治疗组和对照组之间结果的平均差异

应用程序

在这一部分,我将重复两项研究的结果(LaLonde,1986;德赫贾和瓦赫巴,1997 年)。请查看诺亚·格里弗( 链接 )的这篇帖子,获取完整的 R 代码和演练。读诺亚的 ,我受益匪浅。

第 0 步:安装包并加载库

*#install.packages(“MatchIt”)
#install.packages(‘optmatch’)
library(“MatchIt”)
library(“optmatch”)
data(“lalonde”)
head(lalonde)*

我自己的截图

*Note: - The outcome variable is 1978 earnings ( ‘re78’)- The intervention: ‘treat’- 1974 earnings: re74- 1975 earnings: re75- and other control variables*

在这里,我们基于协变量(年龄、教育、种族、已婚、无学位、re74 和 re75)为每个观察构建了一个倾向得分,代表其加入该计划的倾向。

步骤 1:无匹配&比较协变量不平衡

*result_0 <- matchit(treat ~ age + educ + race + married +  nodegree + re74 + re75, data = lalonde, method = NULL, distance = 'glm')result_0*

我自己的截图

*summary(result_0)*

我自己的截图

总共有 185 个经处理的观察值和 429 个未经处理的观察值。

标准差和 eCDF 统计接近 0 或方差比接近 1 表示良好的平衡;否则,不平衡。

在没有应用匹配方法的情况下,治疗组和非治疗组之间存在严重的不平衡。它们在标准均值差(Std)方面看起来非常不同。平均差异。),方差比(Var。比率),以及经验累积密度函数(eCDF)。

协变量失衡表明治疗前的选择偏差,因此我们不能将差异归因于干预。

步骤 2.1:最近邻居

*result_1 <- matchit(treat ~ age + educ + race + married +  nodegree + re74 + re75, data = lalonde, method = “nearest”, distance = ‘glm’)result_1*

我自己的截图

我们应用最近的方法和 1:1 匹配最近的邻居。1:1 匹配意味着我们将一个治疗单位与一个具有最接近倾向得分的对照单位进行匹配。然后,这个控制单元将被从控制池中取出,并且不可用于其他情况(也称为。不更换)。对其余已处理的病例重复该过程。

*summary(result_1, un=FALSE)*

我自己的截图

*plot(result_1, type = “jitter”, interactive = FALSE)*

我自己的截图

*plot(result_1, type = “qq”, interactive = FALSE, which.xs = c(“age”, “married”, “re75”))*

我自己的截图

让我们检查三个变量的协变量的分布。远离实线对角线的点表示两组之间的协变量差异。两个变量,已婚和 re75,匹配后有更好的平衡,但对年龄没有改善。

在 1:1 匹配后,就 Std 而言,与不匹配相比,两组具有更好的平衡。平均差异。,Var。比率和 eCDF 统计。然而,仍然存在群体不平衡。让我们检查其他匹配方法并比较结果。

步骤 2.2:完全匹配和概率单位

*result_2 <- matchit(treat ~ age + educ + race + married + nodegree + re74 + re75, data = lalonde, method = “full”, distance = “glm”, link = “probit”)result_2*

我自己的截图

完全匹配将一个处理单元匹配到一个或多个控制单元(或一个控制单元匹配到一个或多个处理单元)()。此外,我们将链接函数从 logit 更改为 probit。

*summary(result_2, un = FALSE)*

我自己的截图

*plot(summary(result_2))*

我自己的截图

在应用完全匹配后,治疗组和非治疗组之间的协变量看起来更加平衡。

第三步:估计效果和标准误差

*m.data2 <- match.data(result_2)
m.data2*

我自己的截图

*library(‘lmtest’) 
library(‘sandwich’) fit2 <- lm(re78 ~ treat + age + educ + race + married + nodegree + 
 re74 + re75, data = m.data2, weights = weights)coeftest(fit2, vcov. = vcovCL, cluster = ~subclass)*

最后一步,我们估计治疗效果及其标准误差。对于成对集合,我们使用聚类稳健的标准误差(查看 Noah 的帖子以获得解释)。治疗的效果是 1980 美元,标准误差为 756,统计显著性为 0.001。

结论

使用实验数据的因果推断依赖于温和的假设,但观察方法提出了更多的要求,需要更多的假设。对于观察数据,倾向评分匹配旨在通过匹配治疗组和未治疗组来减少干预前存在的偏差。

Medium 最近进化出了它的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。

*https://leihua-ye.medium.com/membership *

参考

德赫贾和瓦赫巴(1999 年)。非实验研究中的因果效应:重新评估训练计划的评估。美国统计协会杂志 94:1053–1062。

Gertler,P.J .,Martinez,s .,Premand,p .,Rawlings,L.B .和 Vermeersch,C.M .,2016 年。实际影响评估。世界银行。

Kim,y .和 Steiner,p .,2016 年。因果推理的准实验设计。教育心理学家51(3–4),第 395–405 页。

拉隆德,R. (1986 年)。用实验数据评估训练计划的经济计量评估。美国经济评论 76:604–620。

格里弗,N .(2021 年)。MatchIt:入门

j .贾兰和 m .拉瓦里翁,2003 年。通过倾向得分匹配估计反贫困项目的受益发生率。商业杂志&经济统计21 (1),第 19–30 页。

相关阅读

*

喜欢读这本书吗?

请在 LinkedIn 和 Youtube 上找到我。

还有,看看我其他关于人工智能和机器学习的帖子。*

熊猫时间序列分析终极指南

原文:https://towardsdatascience.com/an-ultimate-guide-to-time-series-analysis-in-pandas-d511b8e80e81?source=collection_archive---------22-----------------------

桑德拉·维尔廷格在 Unsplash 上的照片

在 Pandas 中执行时间序列分析所需的所有 Pandas 功能。您也可以将此用作备忘单。

什么是时间序列分析?

正是对数据集的分析才有了一系列时间戳。随着对机器学习的日益重视,它变得越来越重要。现在,许多不同类型的行业使用时间序列数据进行时间序列预测、季节性分析、发现趋势以及做出重要的商业和研究决策。所以作为数据科学家或数据分析师,清楚地理解时间序列数据是非常重要的。

时间序列数据用于:

银行和金融机构

股票市场

社会化媒体

电力、天然气和石油工业

机械或化学过程中的周期性措施

以及更多的领域

这是不可避免的。所以,我们来学学吧。

我将从一些通用函数开始,并使用脸书股票价格数据集展示更多主题。

让我们开始吧!

使用正确的格式

时间序列数据可以有多种不同的格式。但并非所有这些格式都对 python 的熊猫库友好。最方便的格式是熊猫的时间戳格式。但是大多数时候时间序列数据都是字符串格式的。这里我有一个不同格式的时间序列数据的例子。

import pandas as pd
import numpy as npdates = ['2020-11-25 2:30:00 PM', 'Jan 5, 2020 18:45:00', '01/11/2020', '2020.01.11', '2020/01/11', '20201105']

上面的“日期”变量显示了五种不同格式的日期时间设置,并且都是正确的。但是我们需要这种特定的格式来方便地工作。因此,将这些日期转换成正确的格式。

pd.to_datetime(dates)

输出:

DatetimeIndex(['2020-11-25 14:30:00', '2020-01-05 18:45:00',
               '2020-01-11 00:00:00', '2020-01-11 00:00:00',
               '2020-01-11 00:00:00', '2020-11-05 00:00:00'],
              dtype='datetime64[ns]', freq=None)

世界上还有其他国家,他们首先使用天数。例如,在美式英语中,2002 年 6 月 1 日被写成“2020 年 6 月 1 日”。但是在英国,像印度、孟加拉国、巴基斯坦和世界其他一些地方的南亚国家把它写成“1/6/2020”。

如果你为来自世界其他地方的客户工作,以下是如何格式化日期。

pd.to_datetime(dates).strftime('%d-%m-%y')

输出:

Index(['25-11-20', '05-01-20', '11-01-20', '11-01-20', '11-01-20', '05-11-20'], dtype='object')

我只是在这里使用了“%d-%m-%y”作为格式。您可以根据需要更改顺序。

如果需要先放月或者先放年,只需要改变格式中的顺序即可。

现在,我将导入数据集,我们将使用该数据集来演示许多函数。我们的脸书股票数据。请随意在此下载数据集并跟随:

https://github.com/rashida048/Datasets/blob/master/FB_data.csv

你学习的唯一方法是通过实践。

如果你读这篇文章是为了学习,我强烈建议你边读边练。

df = pd.read_csv('FB_data.csv')
df.head()

这是一个原始数据集。看起来不坏!井井有条。但是我们需要像前面讨论的那样改变“日期”列的格式。我们将把它做成 DatetimeIndex 格式,并把它作为索引列。

因为当“日期”列是索引列时,我们将能够非常容易地对其进行重新采样。您将在后面的章节中看到这意味着什么。

这是导入数据的正确方法,我在导入时更改了日期的格式并将其设置为索引。

df = pd.read_csv('FB_data.csv', parse_dates=['Date'], index_col="Date")
df.head()

看,我们改变了“日期”栏的格式!

重采样

在这一节中,我将讨论如何对数据进行重采样。

为什么重采样很重要?

因为我们并不总是需要庞大数据集中的所有数据。例如,我们可能只需要 2019 年 6 月的数据。如果您的日期格式是 DatetimeIndex,那就非常简单了:

df["2019-06"]

我们只有八天的数据。求 2019 年 6 月开盘价均值。

df["2019-06"].Open.mean()

输出:

190.71000014285715

我们也可以得到单个日期的数据。

df.loc["2019-06-21"]

输出:

Open         1.887500e+02
High         1.920000e+02
Low          1.887500e+02
Close        1.911400e+02
Adj Close    1.911400e+02
Volume       2.275120e+07
Name: 2019-06-21 00:00:00, dtype: float64

比方说,我们需要 2019 年 6 月 27 日到 7 月 10 日两个星期的数据。

df.loc["2019-06-27": "2019-07-10"

你也可以按月重新取样。这给出了月平均值。例如,这里我将获得月平均收盘数据:

df.Close.resample('M').mean()

输出:

Date
2019-06-30    190.324286
2019-07-31    199.595454
2019-08-31    184.497726
2019-09-30    185.735000
2019-10-31    184.383912
2019-11-30    195.718500
2019-12-31    201.951904
2020-01-31    216.643333
2020-02-29    207.505263
2020-03-31    165.747727
2020-04-30    177.003335
2020-05-31    216.549001
2020-06-30    232.671332
Freq: M, Name: Close, dtype: float64

我们可以用一行代码计算月平均值并绘图:

df.Close.resample('M').mean().plot()

如果您想要周数据并绘制它,您可以通过以下代码获得它:

df.Close.resample('W').mean().plot()

使用 plot()函数中的“kind”参数,您可以获得总共 13 种类型的图,而不是简单的线形图。

我用这个柱状图命名了这 13 种类型的图。

我将绘制季度结算数据的柱状图。

df.Close.resample('Q').mean().plot(kind='bar')

上面的“种类”参数采用以下 13 种可视化类型:

  1. 线条
  2. 区域
  3. 酒吧
  4. barh
  5. 馅饼
  6. 箱子
  7. 赫克宾
  8. kde
  9. 密度
  10. 分散

变化

听起来,shift 函数将数据移动指定的次数。我们正在使用的 FB 数据集从 2019 年 6 月 20 日开始。现在,如果我们将数据移动 1,2019 年 6 月 20 日的数据将移动到 2019 年 6 月 21 日,2019 年 6 月 21 日的数据将移动到 2019 年 6 月 22 日,依此类推。

我稍后会解释为什么人们使用 shift

对于这个例子,我将只使用列。你会非常清楚地看到变化。我将创建一个名为“df1”的新数据帧,只包含开放数据。

df1 = pd.DataFrame(df['Open'])
df1.head()

将该数据移动 1。

df1.shift(1)

第一行的值为空。仅仅是因为第一行移到了第二行。但是第一行之前没有数据。

如果你在 shift 中使用了一个负值,结果正好相反。

df1.shift(-1)

我们为什么要使用 shift?

班次给你前一天的数据或者第二天的数据。这是一个使用案例。我将使用 shift 将今天的数据和前一天的数据并排放置。

df1['Prev Day Opening'] = df1['Open'].shift(1)
df1

有用吗!?

您还可以在另一列中获得 1 天数据的变化:

df1['1 day change'] = df1['Open'] - df1['Prev Day Opening']

以百分比计算 1 周的总数。为此,我们必须推迟 5 天。对吗?然后取今天和 5 天前数据的差值。乘以 100,然后除以今天的原始数据。让我们来看看,以便更好地理解它。

df1['One week total return'] = (df1['Open'] - df1['Open'].shift(5)) * 100/df1['Open'].shift(5)
df1.tail()

我要用 df.tail(),因为我们上了 5 天的班。所以前 5 行将为空。

时区

理解时区很重要。很可能,你在一个时区,而你的客户在另一个时区。熊猫有很强的适应不同时区的功能。

我们有两种类型的日期时间数据。不知道时区的简单日期时间和知道时区的时区感知日期时间。我们拥有的数据是朴素的日期时间。所以,我们需要使用 tz_localize 来转换这个 DateTime。

将脸书数据集的索引转换为“美国/东部”。

df.index = df.index.tz_localize(tz = 'US/Eastern')
df.index

输出:

DatetimeIndex(['2019-06-20 00:00:00-04:00', '2019-06-21 00:00:00-04:00', '2019-06-24 00:00:00-04:00', '2019-06-25 00:00:00-04:00', '2019-06-26 00:00:00-04:00', '2019-06-27 00:00:00-04:00', '2019-06-28 00:00:00-04:00', '2019-07-01 00:00:00-04:00', '2019-07-02 00:00:00-04:00', '2019-07-03 00:00:00-04:00',
               ...
               '2020-06-08 00:00:00-04:00', '2020-06-09 00:00:00-04:00', '2020-06-10 00:00:00-04:00', '2020-06-11 00:00:00-04:00', '2020-06-12 00:00:00-04:00', '2020-06-15 00:00:00-04:00', '2020-06-16 00:00:00-04:00', '2020-06-17 00:00:00-04:00', '2020-06-18 00:00:00-04:00', '2020-06-19 00:00:00-04:00'], dtype='datetime64[ns, US/Eastern]', name='Date', length=253, freq=None)

在每个日期,它显示负 4 小时。同样,如果我们将其转换为“欧洲/柏林”,它将增加 6 个小时。

df = df.tz_convert('Europe/Berlin')
df.index

输出:

DatetimeIndex(['2019-06-20 06:00:00+02:00', '2019-06-21 06:00:00+02:00', '2019-06-24 06:00:00+02:00', '2019-06-25 06:00:00+02:00', '2019-06-26 06:00:00+02:00', '2019-06-27 06:00:00+02:00', '2019-06-28 06:00:00+02:00', '2019-07-01 06:00:00+02:00', '2019-07-02 06:00:00+02:00', '2019-07-03 06:00:00+02:00',
               ...
               '2020-06-08 06:00:00+02:00', '2020-06-09 06:00:00+02:00', '2020-06-10 06:00:00+02:00', '2020-06-11 06:00:00+02:00', '2020-06-12 06:00:00+02:00', '2020-06-15 06:00:00+02:00', '2020-06-16 06:00:00+02:00', '2020-06-17 06:00:00+02:00', '2020-06-18 06:00:00+02:00', '2020-06-19 06:00:00+02:00'], dtype='datetime64[ns, Europe/Berlin]', name='Date', length=253, freq=None)

您可以找到世界上所有可用的时区,并以这种方式使用适合您的时区:

from pytz import all_timezones
print(all_timezones)

这是输出的一部分。满输出太大:

['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', 'Africa/Algiers', 'Africa/Asmara', 'Africa/Asmera', 'Africa/Bamako', 'Africa/Bangui', 'Africa/Banjul', 'Africa/Bissau', 'Africa/Blantyre', 'Africa/Brazzaville', 'Africa/Bujumbura', 'Africa/Cairo',.....

如何生成缺失日期

如果您有数据并且知道时间段,但是时间没有记录在数据集中,该怎么办?或者你有去年第二季度的数据,但没有今年的数据。而你今年需要用去年的数据。

在许多情况下,您可能需要生成一系列日期。熊猫 date_range 功能就派上用场了。让我们生成一个 10 天的时间段:

rng = pd.date_range(start='11/1/2020', periods=10)
rng

输出:

DatetimeIndex(['2020-11-01', '2020-11-02', '2020-11-03', '2020-11-04', '2020-11-05', '2020-11-06', '2020-11-07', '2020-11-08', '2020-11-09', '2020-11-10'], dtype='datetime64[ns]', freq='D')

如果我只需要工作日怎么办?

我只需要添加一个称为频率的额外参数,如下所示:

rng = pd.date_range(start='11/1/2020', periods=10, freq='B')
rng

输出:

DatetimeIndex(['2020-11-02', '2020-11-03', '2020-11-04', '2020-11-05', '2020-11-06', '2020-11-09', '2020-11-10', '2020-11-11', '2020-11-12', '2020-11-13'], dtype='datetime64[ns]', freq='B')

还有几个类似的选项和频率。请查看这篇文章,我只详细解释了 date_range 函数:

因此,我们可以生成一系列日期,并将它们添加到我们的数据集中!

旋转

rolling 函数聚合指定日期时间数的数据。这里我将取每三天的平均值。在完成这个例子后,我将进一步解释:

df[["High"]].rolling(3).mean()[:10]

这里到底发生了什么?我在滚动函数中传递了 3 作为参数,而聚合函数是 mean。因此,它取 6 月 20 日、21 日和 24 日“高”数据的平均值,放在 24 日。对第 21、24 和 25 个数据进行同样的操作,并放在第 25 个数据上,以此类推。很多时候,我们使用周平均值或三天平均值来做决定。

您还可以选择放置滚动数据的位置。这里有一个例子:

data_rol = df[['High', 'Low']].rolling(window = 7, center = True).mean()
data_rol

在这个滚动函数中,我传递了 window = 7。这意味着需要 7 天的平均时间。center = True 表示将平均值放在第 4 行而不是第 7 行。这就是为什么它的底部也有一些空值。

让我们在同一个图中绘制原始“高”数据和 7 天累计“高”数据:

%matplotlib inline
import matplotlib.ticker as ticker 
fig, ax = plt.subplots(figsize= (11, 4))
ax.plot(df['High'], marker = '.', markersize=4, color='0.4', linestyle='None', label='Daily')
ax.xaxis.set_major_locator(ticker.MultipleLocator(30))
ax.plot(data_rol['High'], linewidth=2, label='7-d rolling mean')
ax.set_xlabel('Month')

通常,这种类型的图用于观察数据中的任何趋势

在我们的数据中,有一个趋势是可以观察到的。2020 年 1 月后,价值开始下降,曲线变得陡峭。在时间序列分析中,我们有时会努力寻找趋势。但有时我们需要从数据中剔除趋势。尤其是当我们需要使用时间序列数据进行机器学习或预测时。

再次行军后,它有一个陡峭的上升。在下一节,我将告诉你如何摆脱这种趋势。

消除趋势的差异

如果数据中有任何趋势,这对于建模、预测或观察季节性都是不利的。为了提高模型性能,或者观察数据中的任何季节性或任何噪声,差分是一种常见的做法。它采用指定天数的数据差异。这里有一个例子:

df_first_order_diff = df[['High', 'Low']].diff()
df_first_order_diff

在这里,我没有指定。diff()函数。因此,默认情况下,只需要 1 天的差异。

您看到结果表中发生了什么吗?“高”和“低”数据是“20–06–19”是 21–06–19 和 20–06–19 的“高”和“低”数据的差值。故事发生在 2019 年 6 月 21 日。这就是为什么它在 20–06–19 中为空。因为在那之前没有数据可以减去。

这种差异过程被认为可以消除这种趋势。万一没有,尝试 3 天差异或 7 天差异。这是如何进行 3 天的差异:

df[['High', 'Low']].diff(3)

让我们绘制上面一阶差分的数据,看看我们在上一节观察到的趋势是否已经消除。

start = '20-06-19'fig, ax = plt.subplots(figsize = (11, 4))
ax.plot(df_first_order_diff.loc[start:, "High"], marker = 'o', 
        markersize = 4, linestyle = '-', label = 'First Order Differencing')
ax.xaxis.set_major_locator(ticker.MultipleLocator(30))

看那明显的趋势没了!如果你能在最后摆脱这种轻微的趋势,请随意检查我之前提到的 3 天差异。

重要时间特征提取

您可以从时间序列中提取非常有用的年、月、周或工作日。让我们从索引列“Date”中提取年份开始。

pd.DatetimeIndex(df.index).year

输出:

Int64Index([2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019,
            ...
            2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020], dtype='int64', name='Date', length=253)

现在,选取数据集的一个子集使其变小,并在单独的列中添加年份。

df3 = df[['High','Low', 'Volume']]
df3['Year'] = pd.DatetimeIndex(df3.index).year
df3

看到我们在最后加上了年份。同样,您可以提取月份和工作日。下面是代码:

pd.DatetimeIndex(df3.index).month

输出:

Int64Index([6, 6, 6, 6, 6, 6, 6, 7, 7, 7,
            ...
            6, 6, 6, 6, 6, 6, 6, 6, 6, 6], dtype='int64', name='Date', length=253)

以下是提取工作日的方法:

pd.DatetimeIndex(df3.index).weekday

输出:

Int64Index([3, 4, 0, 1, 2, 3, 4, 0, 1, 2,
            ...
            0, 1, 2, 3, 4, 0, 1, 2, 3, 4], dtype='int64', name='Date', length=253)

工作日出来就是数字。如果您需要周日、周一等工作日格式,该怎么办?那会更有用!

df3['Weekday'] = pd.DatetimeIndex(df3.index).to_series().dt.day_name()
df3.head()

让我们检查工作日是否对“高”、“低”和“量”数据有任何影响。

import seaborn as sns
fig, axes = plt.subplots(3, 1,figsize=(11, 10), sharex=True)for name, ax in zip(['High', 'Low', 'Volume'], axes):
    sns.boxplot(data=df3, x = 'Weekday', y = name, ax=ax)
    ax.set_title(name)

工作日对这些数据有影响,对吗?周三的“高”、“低”和“量”都在上涨。周一情况正好相反。箱线图在一个包中给出了很多信息。如果您需要复习如何从箱线图中提取所有数据,这里有一篇详细的文章:

周期和周期指数

另一个重要的 python 函数。我们将通过实践来学习。使用周期函数的最基本方法是:

y = pd.Period('2020')
y

输出:

Period('2020', 'A-DEC')

此输出表明,这一时期' 2020 年'将于 12 月结束。有道理,对吧?

以下是可从周期函数中提取的所有信息的目录:

dir(y)

这是输出的一部分。因为目录大!

.
.
.
.
.
'asfreq',
 'day',
 'dayofweek',
 'dayofyear',
 'days_in_month',
 'daysinmonth',
 'end_time',
 'freq',
 'freqstr',
 'hour',
 'is_leap_year',
 'minute',
 'month',
 'now',
 'ordinal',
 'quarter',
 'qyear',
 'second',
 'start_time',
 'strftime',
 'to_timestamp',
 'week',
 'weekday',
 'weekofyear',
 'year']

我将展示其中的一些。

y.start_time

输出:

Timestamp('2020-01-01 00:00:00')

输入:

y.end_time

输出:

Timestamp('2020-12-31 23:59:59.999999999')

如果我们使用频率作为月份:

month = pd.Period('2020-2', freq="M") 
month

输出:

Period('2020-02', 'M')

输入:

month.start_time

输出:

Timestamp('2020-02-01 00:00:00')

输入:

month.end_time

输出:

Timestamp('2020-02-29 23:59:59.999999999')

我们可以用这种类型的月数据做什么?

必要的话可以加减。例如,如果您有学生的年龄数据,并且需要更新年份或月份,您可以这样做:

month + 2

输出:

Period('2020-04', 'M')

同样的,你可以增加或减少天数。如果我们输入一个日期,默认情况下它会将频率作为日期。

d = pd.Period('2020-02-28')
d

输出:

Period('2020-02-28', 'D')

如果你增加一两天,它就会增加一两天。但是我这里写的日期是 2 月 28 日。这是不同的,对不对?闰年的二月有 29 天,其他年份的二月有 28 天。

让我们在上面的日期 d 的基础上增加两天:

d + 2

输出:

Period('2020-03-01', 'D')

2 月 28 日加 2 天,就得到 3 月 1 日。这意味着周期函数知道闰年。

同样,你可以添加年、小时、分钟甚至季度。

让我们来看一个 25 美分硬币的例子:

q = pd.Period('2020Q1')
q

输出:

Period('2020Q1', 'Q-DEC')

检查 q 的开始和结束月份。

q.asfreq('M', how='start')

输出:

Period('2020-01', 'M')

2020Q1 的第一个月是一月。这意味着默认情况下第一季度从一月份开始。检查什么时候结束。虽然我们知道它应该在三月结束。

q.asfreq('M', how='end')

输出:

Period('2020-03', 'M')

q 期始于一月,止于三月。任何地方的商业年度都不是从一月开始到三月结束。一会儿我会再谈一谈。

在 q 上加 1:

q + 1

输出:

Period('2020Q2', 'Q-DEC')

在这里,“Q-DEC”表示该季度在 12 月结束。一年有四个季度,最后一个季度在 12 月结束。但是有几个行业将一月作为第四季度末,或者将六月作为第四季度末。

我们可以使用“频率”参数来指定季度末。在下一个例子中,我将使用第四季度末作为一月份。

q1 = pd.Period('2020Q2', freq = 'Q-Jan')
q1

输出:

Period('2020Q2', 'Q-JAN')

看,这里我们把第四季度末改成了一月份!请随意查看第一季度的开始和结束月份。你会看到开始的月份是三月而不是四月。因为第一季度是从二月到四月。

按照我们之前生成 date_range 的方式,我们也可以生成期间范围:

idx = pd.period_range('2017', '2020', freq = 'Q')
idx

输出:

PeriodIndex(['2017Q1', '2017Q2', '2017Q3', '2017Q4', '2018Q1', '2018Q2', '2018Q3', '2018Q4', '2019Q1', '2019Q2', '2019Q3', '2019Q4', '2020Q1'], dtype='period[Q-DEC]', freq='Q-DEC')

默认情况下,从“2017Q1”开始。因为默认情况下,季度从一月开始,到十二月结束。但与之前一样,如果我们在 1 月份指定季度末,它将从 2017 年第四季度开始。

idx = pd.period_range('2017', '2020', freq = 'Q-Jan')
idx

输出:

PeriodIndex(['2017Q4', '2018Q1', '2018Q2', '2018Q3', '2018Q4', '2019Q1', '2019Q2', '2019Q3', '2019Q4', '2020Q1', '2020Q2', '2020Q3', '2020Q4'], dtype='period[Q-JAN]', freq='Q-JAN')

您可以将这些季度转换为时间戳:

idx = idx.to_timestamp()
idx

输出:

DatetimeIndex(['2016-11-01', '2017-02-01', '2017-05-01', '2017-08-01', '2017-11-01', '2018-02-01', '2018-05-01', '2018-08-01', '2018-11-01', '2019-02-01', '2019-05-01', '2019-08-01', '2019-11-01'], dtype='datetime64[ns]', freq='QS-NOV')

同样,当我们有时间戳时,我们可以使用 to_period()将其转换为季度。

idx.to_period()

输出:

PeriodIndex(['2016Q4', '2017Q1', '2017Q2', '2017Q3', '2017Q4', '2018Q1', '2018Q2', '2018Q3', '2018Q4', '2019Q1', '2019Q2', '2019Q3', '2019Q4'], dtype='period[Q-DEC]', freq='Q-DEC')

恭喜你!您现在刚刚学会了对任何数据集执行时间序列分析!

结论

我试图记录和解释大部分大熊猫的功能,用于时间序列分析。学习完这一整页后,您应该有足够的知识对任何时间序列数据执行有效的时间序列分析。但是请记住,要熟练使用所有这些功能需要大量的练习!编码快乐!

欢迎在推特上关注我,喜欢我的 T2 脸书页面。

更多阅读:

一个非常规但方便的 Matplotlib Broken_Barh 函数,当它特别有用时

原文:https://towardsdatascience.com/an-unconventional-yet-convenient-matplotlib-broken-barh-function-and-when-it-is-particularly-88887b76c127?source=collection_archive---------26-----------------------

它是什么,如何使用和定制,何时使用

作者图片

尽管对于 Python 中的某些数据可视化情况非常方便,但[broken_barh](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.broken_barh.html)是 matplotlib 中不太为人所知和被低估的方法之一。它用于绘制不同 x 范围的水平矩形序列,并且位于 y 范围定义的相同垂直位置。换句话说,它产生了一个“断开的”水平条形图,即一个有间隙的图。

语法非常简单:该函数主要接受两个参数,xrangesyrangexranges参数表示 2 项元组的列表或元组,其中每个元组的第一项xmin是相应矩形的最左侧 x 位置,第二项xwidth是该矩形的宽度。yrange参数是一个元组,表示所有矩形的 y 位置和高度。

一个基本的情节是这样的:

import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(8,2))
plt.broken_barh(xranges=[(1, 1), (3, 2)], yrange=(1, 1))
sns.despine()
plt.show()

作者图片

一些额外的不言自明的参数可以用来定制结果矩形的外观:coloralphaedgecolorlinewidthlinestyle(可以是'solid''dashed''dashdot''dotted')。hatch参数用于用图案填充矩形,可以取下列值之一或其组合作为字符串:/\\|-+xoO.*label参数设置将在图例中显示的标签。

这些参数中的每一个都可以是应用于所有矩形的单个自变量(浮点或字符串)(例如color='red')或自变量的列表/元组(例如color=('red','blue')),在该列表/元组上迭代以创建矩形的间歇序列:

plt.figure(figsize=(15,2))
x1 = (1, 1), (2.1, 2), (5, 2), (7.2, 1)
y1 = (1, 1)
plt.broken_barh(x1, y1, 
                color=['slateblue', 'orange'], alpha=0.7, 
                linewidth=4, 
                edgecolor=['black', 'brown', 'green', 'blue'], 
                linestyle='dashed', hatch='/')
sns.despine()
plt.show()

作者图片

我知道,上面的情节看起来有点让人不知所措🙂然而,它清楚地显示了附加参数是如何工作的。

broken_barh函数什么时候能在现实世界中派上用场?

1.要显示范围

使用这种方法,我们可以在同一个图上显示不同类别的范围,例如:

  • 不同种类动物的边界条件(比如温度),
  • 不同地理位置在一段时间内的降雨量,
  • 各种工作的工资范围。

让我们用虚拟数据来看看最后一种情况:

x_ranges = [[(3800, 600)], [(2000, 1000)], [(2700, 800)]]
y_start = 1
colors = ['deepskyblue', 'limegreen', 'magenta']
for i in range(len(x_ranges)):
    plt.broken_barh(x_ranges[i], (y_start+i, 0.5), color=colors[i])    
plt.title('Salary ranges by job ($)', fontsize=25)
plt.xticks(fontsize=14)
plt.yticks(ticks=[1.25, 2.25, 3.25], 
           labels=['Job1', 'Job2', 'Job3'], fontsize=16)
plt.tick_params(left=False)
sns.despine()
plt.show()

作者图片

在这种情况下,broken_barh方法实际上为每个类别绘制了一个矩形。

注意:当我们必须为一个类别只绘制一个矩形时,我们必须将相应的 2 项元组放在列表中,而不是放在元组中。

2.强调另一个图形上的某些音程

在强调其他图表上的某些特定区间时,broken_barh方法是一个不错的选择。例如:

  • 我们有一个地理区域在一段时间内温度波动的线图,我们希望显示温度高于某个值的时间间隔,
  • 货币汇率随着利息的变化而变化,
  • 当交通比平均水平更拥挤时,交通流量波动

下图准确地代表了最后一种情况:工作日从 06:00 到 19:00, I-94 州际公路上每小时的交通量波动(数据取自 this repository ,经过修改和略微修改)。我们应用了broken_barh方法来强调流量高于平均水平的时间范围:

import pandas as pd
cars_per_hr = pd.Series([4141, 4740, 4587, 4485, 4185, 4466, 4718, 4801, 4932, 5241, 5664, 5310, 4264, 3276])# Create a line plot
plt.figure(figsize=(10,5))
plt.plot(cars_per_hr, color="grey")# Create a broken horizontal bar plot
x = [(0.8, 0.95), (5.65, 6)]
y = (cars_per_hr.mean()-50, 100)
plt.broken_barh(x, y, color ='red')plt.title('Traffic volume from 06.00 till 19.00 on weekdays', 
          fontsize=25)
plt.xlabel('Time', fontsize=20)
plt.ylabel('Traffic volume, cars/hr', fontsize=20)
plt.xticks(ticks=list(range(14)), 
           labels=list(range(6,20)), fontsize=13)
plt.yticks(fontsize=13)
plt.xlim(0,13)
sns.despine()  
plt.show()

作者图片

我们看到有两个时间段的交通比平均水平更拥挤:大约从 6.45 到 7.40,以及从 11.40 到 17.40。

3.要创建甘特图

或许,broken_barh方法的最佳应用是创建简化的甘特图。甘特图是一种特殊类型的条形图,通常用于显示不同活动之间随时间变化的关系。这些活动可以包括:

  • 项目管理进度及其当前状态,
  • 要完成的任务及其截止日期,
  • 正在进行的事件,
  • 假期。

在 Python 中还有其他更复杂的创建甘特图的方法,比如使用 Plotly 或 python-gantt 库。然而,broken_barh matplotlib 函数也足以创建一个基本但信息丰富的图形。此外,它只需要几行代码就可以完成。

让我们以今年夏天的假期计划为例来说明这种方法是如何工作的。我们将为一个 5 人的部门使用虚拟数据:

plt.figure(figsize=(20,7))# Create broken horizontal bar plots for vacation ranges 
x_ranges = [[(0,3), (36,3), (69,12)], [(13,19), (55,5)], [(48,5), (76,12)], [(27,19)], [(0,4), (62,12), (86,2)]]
y_start = 0.75
colors = ['deepskyblue', 'indianred', 'limegreen', 'gold', 'violet']
for i in range(len(x_ranges)):
    plt.broken_barh(x_ranges[i], (y_start+i, 0.5), color=colors[i])# Create broken horizontal bar plots for weekends 
x_weekend = [(4,2), (11,2), (18,2), (25,2), (32,2), (39,2), (46,2), (53,2), (60,2), (67,2), (74,2), (81,2), (88,2)]
y_weekend = (0, 5.5)
plt.broken_barh(x_weekend, y_weekend, color='tomato', alpha=0.1)plt.title('Vacation schedule for June-August 2021', fontsize=35)
plt.xticks(ticks= [0, 4, 9, 14, 19, 24, 30, 34, 39, 44, 49, 54, 61, 65, 70, 75, 80, 85, 90],
           labels=['June', 5, 10, 15, 20, 25, 'July', 5, 10, 15, 20, 25, 'August', 5, 10, 15, 20, 25, 30], fontsize=20)
plt.yticks(ticks= [1, 2, 3, 4, 5], 
           labels=['Vladimir', 'Natalia', 'Michael', 'Peter', 'Elena'], fontsize=20)
plt.xlim(0, 92)
plt.ylim(0, 5.5)
plt.axvline(30, color='black')
plt.axvline(61, color='black')
plt.grid(axis='x')
plt.tick_params(left=False, bottom=False)
plt.show()

作者图片

即使不使用任何专门的库,上面的图看起来也很清楚:我们看到了雇员的姓名、每个雇员的假期数和假期范围、主要的时间标志(开始、5 日、10 日等等。每个月、所有的周末)、重叠假期的时段或者没有人休假的时段。

结论

在本文中,我们探索了一个很少使用但很方便的broken_barh matplotlib 方法的语法,定制结果图的方法,特别是该方法有特殊用途的情况,即在同一图上显示不同类别的范围(边界条件、工资范围),在另一个图上强调一些区间(汇率变化、交通量波动),以及创建甘特图(可视化计划,如项目步骤、任务或假期)。

感谢阅读!

相关主题:

https://medium.com/geekculture/creating-toyplots-in-python-49de0bb27ec1

15 分钟的大学水平的统计学入门课程

原文:https://towardsdatascience.com/an-undergraduate-level-introductory-statistics-course-in-15-minutes-51996bb7caf3?source=collection_archive---------8-----------------------

一个包含最基本的概念和公式的备忘单让你开始统计学。

照片由 Pexels 的 Meruyert Gonullu 拍摄

由于之前数学不及格,我怀着恐惧走进了我的第一门本科统计学课程。

不过,我害怕的不仅仅是数学。我担心,如果我连一门简单的统计学课程都学不会,我将会失去就业机会。沉迷于成为数据科学家的想法,我害怕无法建立所有数据科学家都需要的基本技能之一:理解和执行统计程序的能力。

不过,我本不必担心。尽管战战兢兢,我还是以 82%的成绩轻松通过了这门课(一个 A-),并以 92%的最终成绩杀进了期末考试。我今天与你分享的笔记正是那些帮助我取得成功的笔记。

在开始学习统计学之前,重要的是要知道统计学是一门非常“简单明了”的数学。简而言之,如果你知道公式,并能仔细阅读和理解问题,你就能回答任何摆在你面前的统计问题。统计问题通常会确切地告诉你他们在寻找什么作为答案的一部分(例如,计算平均值、确定标准差、完成双变量分析等)。).这就是为什么我今天与你分享的笔记非常“简单”,主要包含公式、一些词汇、显示概念之间关系的表格以及解决问题的逐步方法。

这些笔记假设理解一些概念,例如求和符号、寻找一组数字的范围、数据可视化(理解图表的类型)、基本概率和基本代数。这些注释确实省略了关于使用各种分布表的信息,因为这会大大增加本文的长度。相反,在这里分享的笔记突出了最重要的细节——其余的可以在其他地方填写。

介绍

关键术语

  • 描述性统计:通过使用表格、图表以及其他汇总和可视化措施来组织、显示和描述数据的方法。
  • 推断统计学:使用样本结果对总体进行决策或预测的方法。
  • 定量变量:可以用数字测量的变量。在定量变量上收集的数据称为定量数据。
  • 定性/分类变量:不能假定为数值,但可以归类为非数值类别的变量。在定性变量上收集的数据是定性数据。
  • 群体:由所有特征被研究的元素组成。
  • 样本:为研究选择的一部分人口。
  • 代表样本:代表总体特征的样本。
  • 随机抽样:抽取样本,使总体中的每个成员都有一定的机会被选中。
  • 非随机样本:抽取的样本,使得总体中的某些成员没有机会被选中。
  • 抽样误差:从抽样调查中获得的结果与如果整个人口都包括在调查中所获得的结果之间的差异。
  • 非抽样误差/偏差:数据收集、记录和制表过程中出现的误差。

桌子

表格中数据各个方面的实际例子。

非随机抽样的类型。

抽样和非抽样误差的类型。

随机抽样技术。

组织和绘制数据

公式

计算一个类别的相对频率。

计算百分比。

寻找班级宽度。

计算班级中点。

计算相对频率和百分比。

计算累积相对频率和累积百分比。

桌子

频率分布表中显示的分组数据。

数字描述性度量

关键术语

  • 均值/平均值:一个数据集的平均值。
  • 中位数:将按升序排列的数据集分成两半的值。如果数据集有奇数个值,则中值由数据集中中间项的值给出。如果数据集有偶数个值,则中位数由数据集中两个中间项的平均值给出。
  • 模式:数据集中出现频率最高的值。
  • 标准差:表示数据集的值围绕平均值聚集的紧密程度的值。标准差的较低值表示数据集分布在平均值附近的较小范围内。标准差的值越大,表明数据集分布在平均值附近的较大范围内。
  • 经验法则:对于钟形分布,(1) 68%的观察值位于均值的一个标准差内,(2) 95%的观察值位于均值的两个标准差内,(3) 99.7%的观察值位于均值的三个标准差内。
  • 四分位数:将已排序的数据集分成四等份的三个值。第二个四分位数与数据集的中位数相同。第一个四分位数是小于中位数的观察值的中位数。第三个四分位数是大于中位数的观察值的中位数。
  • 盒须图:使用数据集中的中间值、第一个四分位数、第三个四分位数以及最小和最大值来显示数据集的中心、分布和偏斜度的图。

公式

计算平均值。

未分组数据的计算平均值。

计算样本和总体的未分组数据的方差和标准差。

计算样本和总体分组数据的平均值。

计算样本和总体分组数据的方差和标准差。

计算四分位数间距(第三个四分位数和第一个四分位数之间的差值)。

计算百分点。

计算数值的百分位数等级。

概率

关键术语

  • 边际概率:不考虑任何其他事件的情况下,单个事件发生的概率。
  • 条件概率:假设一个事件已经发生,另一个事件将要发生的概率。如果 A 和 B 是两个事件,那么给定 B 的条件概率写成 P(A|B)。
  • 独立事件:一个事件的发生不影响另一个事件发生的概率。如果 P(A|B) = P(A)或 P(B|A) = P(B ),则 A 和 B 是独立事件。
  • 事件的交集:A 和 B 的交集表示 A 和 B 共有的所有结果的集合,用(A 和 B)表示。
  • 联合概率:两个事件相交的概率,记为 P(A 和 B)。
  • 互斥事件的联合概率:两个互斥事件的联合概率始终为 0。
  • 事件的并:属于 P(A 或 B)表示的 A 或 B 或 A 和 B 的所有结果的集合。
  • 阶乘: n!(读作“n 阶乘”)表示从 n 到 1 的所有整数的乘积。
  • 组合:给出从 n 个元素中选择 x 个元素的方法。
  • 排列:从 x 个元素中选择 x 个元素的总数。

公式

求概率的经典概率法则。

使用相对频率作为概率的近似值。

计算独立事件概率的乘法法则。

求两个相关事件的联合概率的乘法法则。

计算两个事件的条件概率。

求两个互不排斥的事件并的概率的加法法则。

求两个互斥事件并的概率的加法规则。

组合符号读作“一次选择 x 个 n 个元素的组合数”。

组合的数量。

排列符号读作“从 n 个元素中选择 x 个元素的排列数”

从 n 项中选择 x 项的排列数。

离散随机变量及其概率分布

关键术语

  • 随机变量:其值由随机实验结果决定的变量。
  • 离散随机变量:取可数数值的随机变量。
  • 连续型随机变量:可以取区间内任意值的随机变量。
  • 离散随机变量的概率分布:列出随机变量可能出现的所有值及其概率。

笔记

概率分布的两个特征。

二项式实验的条件:

  1. 有 n 个相同的试验。
  2. 每次试验只有两种可能的结果。审判分为两个相互排斥的事件。
  3. 这两种结果的概率保持不变。
  4. 轨迹是独立的。

公式

一个离散随机变量的平均值是指如果一个实验被重复了很多次,那么在每次重复中预期出现的值。也称为期望值,可以用 E(x)表示。

离散随机变量的标准差给出了其概率分布的范围。

二项式公式。

二项分布的均值和标准差。

连续随机变量和正态分布

关键术语

  • z 值/ z 得分:标在标准正态曲线横轴上的单位,以标准差的形式给出平均值与 z 所代表的点之间的距离。

笔记

正态概率分布:绘制时产生一条钟形曲线;

  1. 曲线下的总面积为 1.0。
  2. 这条曲线关于平均值是对称的。
  3. 曲线的两个尾部无限延伸。

公式

将 x 值转换为 z 值,其中 mu 和 sigma 是 x 的正态分布的平均值和标准差。

抽样分布

关键术语

  • 人口概率分布:人口数据的概率分布。
  • 条形 x 的抽样分布:给出其抽样分布的样本统计量的概率分布。
  • 样本比例的抽样分布:样本比例的概率分布(p hat)。
  • 样本比例的中心极限定理:陈述对于足够大的样本量,p hat 的抽样分布近似正态,使得 np > 5 和 nq > 5。

公式

当总体呈正态分布时,条形 x 的抽样分布均值。

当总体呈正态分布时,条形 x 的抽样分布的标准差。

z 值为条形 x 的值。

人口和样本比例。

样本比例的平均值。

样本比例的标准差。

p hat 值的 z 值。

均值和比例的估计

关键术语

  • 估计:根据样本统计值指定给总体参数的值。
  • 估计量:用于估计总体参数的样本统计量。
  • 点估计:用于估计总体参数的样本统计值。
  • 区间估计:围绕点估计构造的包含相应总体参数的区间。

笔记

评估程序包括:

  1. 选择一个样本。
  2. 从样本成员处收集所需信息。
  3. 计算样本统计值。
  4. 为相应的填充参数赋值。

公式

给定置信水平的置信区间。

置信区间的置信水平,表明我们对该区间包含真实总体参数有多大的把握。

mu 的点估计。

标准差已知时均值的置信区间。

标准差未知时均值的置信区间。

平均值估计的误差幅度。

均值估计的样本量。

大样本 p 的置信区间。

p 估计的误差范围。

p 估计的样本容量。

关于平均值和比例的假设检验

关键术语

  • 无效假设:关于一个总体参数的声明,该参数在被声明为假之前一直被假定为真。
  • 替代假设:关于总体参数的声明,如果零假设被声明为假,该参数将被声明为真。
  • 第一类错误:当真零假设被拒绝时发生。
  • 第二类错误:发生在错误的零假设没有被拒绝的时候。
  • 双尾检验:双尾都有拒绝区域。
  • 左尾检验:在分布曲线的左尾有拒绝区域。
  • 右尾检验:在分布曲线的右尾有拒绝域。
  • P 值:零假设被拒绝的最小显著性水平。

笔记

临界值方法:

  1. 陈述无效假设和替代假设。
  2. 选择要使用的分布。
  3. 确定拒绝和非拒绝区域。
  4. 计算检验统计的观察值。
  5. 做决定,写结论。

P 值法:

  1. 陈述无效假设和替代假设。
  2. 选择要使用的分布。
  3. 计算 p 值。
  4. 做个决定。

公式

当标准偏差已知时,检验关于平均值的假设。

关于平均值和标准差的假设检验是未知的。

大样本下 p 的假设检验。

桌子

假设检验的四种可能结果。

检验的零假设、替代假设和尾部的符号。

估计和假设检验:两个总体

关键术语

  • 独立样本:从两个总体中抽取的两个样本,其中从一个总体中选择一个样本不影响从第二个总体中选择第二个样本。
  • 相依样本:从两个总体中抽取的两个样本,其中从一个总体中选择一个样本会影响从第二个总体中选择第二个样本。
  • 成对/匹配样本:两个样本当从一个样本收集的每个数据值都有从第二个样本收集的相应数据值,并且这两个数据值都是从同一来源收集的。

公式

当两个标准差都已知时,使用正态分布对两个独立样本的均值 1 减去均值 2 的假设进行检验的检验统计量。

从两个具有相等但未知标准差的总体中抽取的两个独立样本的混合标准差。

x 条 1 减去 x 条 2 的标准差估计。

使用 t 分布的测试统计。

配对样本中 sub d 假设的检验。

p1 — p2 假设的检验。

卡方检验

关键术语

  • 卡方分布:只有一个参数(自由度)的分布。这种分布曲线的形状对于小自由度向右倾斜,对于大自由度变得对称。整个分布位于垂直轴的右侧。这个分布只假设非负值。
  • 观察频率:从实验中获得的频率,用 o 表示
  • 期望频率:如果零假设为真,我们期望获得的频率。由 E = np 获得。
  • 同质性检验:涉及检验两个或两个以上不同群体中具有某些特征的元素比例相同的原假设,以及这些比例不同的替代假设。

笔记

多项实验:具有以下特征的实验为多项实验:

  1. 这个实验由 n 个相同的试验组成。
  2. 每次试验都产生 k 种可能结果中的一种,其中 k > 2。
  3. 这些试验是独立的。
  4. 各种结果的概率在每次试验中保持不变。

公式

拟合优度检验。

用列联表检验独立性。

使用列联表的同质性检验。

方差分析

关键术语

  • ANOVA: 用于检验三个或三个以上总体均值相等的零假设的程序。
  • 样本间均方值(MSB): 从不同人群中抽取的样本的平均值的变化度量。
  • 样本内均方值(MSW): 对取自不同人群的所有样本的数据内变化的度量。
  • SSB: 样本间的平方和。
  • SST: 总平方和。
  • SSW: 样本内的平方和。

笔记

f 分布:

  1. f 分布是连续的并且向右倾斜。
  2. 分布有两个自由度:分子的 df 和分母的 df。
  3. f 分布的单位是非负的。

单因素方差分析的假设:

  1. 从中抽取样本的总体近似呈正态分布。
  2. 从中抽取样本的总体具有相同的方差或标准差。
  3. 从不同人群中抽取的样本是随机和独立的。
  4. 单向方差分析总是右尾的。

公式

单向 ANOVA 检验的方程式。

简单线性回归

关键术语

  • 简单回归:****模型,描述两个或更多变量之间的关系,只包括两个变量:一个自变量和一个因变量。
  • ****线性回归:给出两个变量之间直线关系的简单回归模型。
  • ****A 和 B 的最小二乘估计:利用样本数据计算出的 A 和 B 的值。
  • ****最小二乘法:通过散点图拟合回归线,使误差平方和最小的方法。
  • ****最小二乘回归线:用最小二乘法得到的回归线。
  • ****线性相关系数:衡量两个变量之间线性关系强度的指标。
  • ****多元回归模型:包含两个或多个自变量的回归模型。
  • ****两个变量之间的正关系:回归线中斜率的值和两个变量之间的相关系数都是正的。
  • ****两个变量之间的负关系:回归线中斜率的值和两个变量之间的相关系数都为负。
  • ****斜率:回归模型中 x 的系数,它给出了 x 变化一个单位时 y 的变化。
  • ****SSE(误差平方和):y 的实际值和预测值的平方差之和。
  • ****SSR(回归平方和):由回归模型解释的 SST 部分。
  • ****SST(总平方和):实际 y 值与 y 的平方差之和。
  • ****误差的标准偏差:随机误差扩散的度量。

公式

简单线性回归模型。

估计回归模型。

b 的置信区间。

关于 b 的假设检验。

****

线性相关系数。

****

决定系数。

最终想法和附加资源。

虽然这个备忘单是一个很好的起点,但是网上有大量的资源可以帮助你进一步加深对统计概念的理解。下面列出了一些我最喜欢的:

**https://www.khanacademy.org/math/statistics-probability </8-fundamental-statistical-concepts-for-data-science-9b4e8a0c6f1c> </10-statistical-concepts-you-should-know-for-data-science-interviews-373f417e7d11>

当学习统计学时,重复和一致性是关键。当你知道你在寻找什么以及如何寻找时,问题很少是难以解决的。通过熟悉寻找所需值的最重要的公式和程序,你将能够很快解决任何摆在你面前的统计问题。**

ROC 曲线和 AUC 以及为什么和何时使用它们的易懂指南?

原文:https://towardsdatascience.com/an-understandable-guide-to-roc-curves-and-auc-and-why-and-when-to-use-them-92020bc4c5c1?source=collection_archive---------6-----------------------

图片由皮克斯拜的 Gerd Altmann 提供

ROC 曲线是检查分类模型性能的最常见评估指标之一。本指南将帮助您真正理解 ROC 曲线和 AUC 是如何协同工作的

ROC 曲线或受试者操作特征曲线是检查分类模型性能的最常见评估指标之一。不幸的是,许多数据科学家经常只是看到 ROC 曲线,然后引用 AUC(ROC 曲线下面积的缩写)值,而没有真正理解 AUC 值的含义以及如何更有效地使用它们。

其他时候,他们不理解 ROC 曲线解决的各种问题以及 AUC 的多重属性,如阈值不变性和比例不变性,这必然意味着 AUC 度量不依赖于所选的阈值或概率比例。这些性质使得 AUC 对于评估二元分类器非常有价值,因为它为我们提供了一种在不关心分类阈值的情况下比较它们的方法。这就是为什么数据科学家更全面地了解 ROC 曲线和 AUC 非常重要。

那么,ROC 曲线/AUC 满足什么需要呢?

因此,在我们开始学习 ROC 曲线和 AUC 之前,我们想到的第一个问题是,为什么不使用一个相当简单的度量标准,如二进制分类任务的准确性?毕竟,准确性很容易理解,因为它只是计算模型正确预测的百分比。

答案是,准确度没有抓住概率分类器的全部本质,即,它既不是阈值不变的度量,也不是尺度不变的度量。我这么说是什么意思?最好用一些例子来解释。

1。为什么准确度不是阈值不变的?

假设逻辑回归分类器的阈值为 0.5,您认为该分类器的准确度是多少?

来源:作者图片

如果你说 50%,那恭喜你。我们会把两个零误归类为一。这个结果没那么好。但是我们的分类器真的那么差吗?基于准确性作为评价指标,似乎是这样的。但是如果我们把同一个例子中的阈值改成 0.75 呢?现在,我们的分类器变得 100%准确。这让我们不禁要问,我们如何才能提出一个不依赖于阈值的评估指标。也就是说,我们想要一个阈值不变的度量。

2。为什么精度不是尺度不变的?

现在,让我们再次做同样的练习,但是这次我们的分类器预测不同的概率,但是在相同的等级顺序。这意味着概率值会改变,但顺序保持不变。因此,在分类器 B 中,预测的等级保持不变,而分类器 C 在完全不同的尺度上进行预测。那么,以下哪一个是最好的?

来源:作者图片

在所有这些情况下,我们可以看到每个分类器在很大程度上是相同的。也就是说,如果分类器 A 的阈值为 0.75,分类器 B 的阈值为 0.7,分类器 C 的阈值为 68.5,那么我们对所有这些分类器都有 100%的准确性。

当等级顺序保持不变时,评估度量具有相同值的属性被称为尺度不变属性。在分类器预测分数而不是概率的情况下,这个属性确实可以帮助我们,从而允许我们比较两个不同的分类器,它们预测不同尺度上的值。

因此,最后,我们需要一个满足以下两个条件的评估指标:

  • 它是阈值不变量 ,即度量的值不依赖于选定的阈值。
  • 它是尺度不变的,即它衡量预测的排名,而不是它们的绝对值。

好消息是 AUC 满足上述两个条件。然而,在我们甚至可以看如何计算 AUC 之前,让我们更详细地理解 ROC 曲线。

ROC 曲线

关于 ROC 曲线的一个有趣的历史事实是,它们在第二次世界大战期间首次用于分析雷达信号。珍珠港事件后,美国军方想用他们的雷达信号探测日本飞机。ROC 曲线特别适合这项任务,因为它们让操作员选择阈值来区分阳性和阴性样本。

但是我们如何自己制作这些曲线呢?要理解这一点,我们需要先了解真阳性率 (TPR)和假阳性率 (FPR)。因此,假设我们有一个具有特定概率阈值的模型的以下样本混淆矩阵:

来源:作者图片

为了解释 TPR 和 FPR,我通常会举一个司法系统的例子。自然,任何司法系统都只想惩罚有罪的人,而不想指控一个无辜的人。现在让我们说,上面的模型是一个司法系统,它评估每个公民,并预测要么是零(无辜),要么是一(有罪)。

在这种情况下,TPR 是我们的模型能够捕获的有罪罪犯的比例。因此,分子是抓获的罪犯,分母是罪犯总数。这个比率也被称为回忆或敏感度。

**TPR(True Positive Rate)/Sensitivity/Recall**= TP/(TP+FN)

FPR 是我们错误预测为罪犯(误报)的无辜者的比例除以实际无辜公民的总数。因此,分子是被抓获的无辜者,分母是无辜者总数。

**FPR(False Positive Rate)**= FP/(TN+FP)

通常,我们会想要高 TPR(因为我们想抓住所有的罪犯)和低 FPR(因为我们不想抓住无辜的人)。

那么,我们如何使用 TPR 和 FPR 绘制 ROC 曲线呢?我们使用不同的阈值在 X 轴上绘制假阳性率(FPR ),在 Y 轴上绘制真阳性率(TPR)。当我们连接这些点时产生的曲线称为 ROC 曲线。

让我们通过一个简单的代码示例来理解如何在 Python 中实现这一点。下面,我们只是创建一个小样本分类数据集,并在数据上拟合一个逻辑回归模型。我们还从分类器中得到概率值。

from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve
from sklearn.metrics import roc_auc_score
import plotly.express as px
import pandas as pd# Random Classification dataset
X, y = make_classification(n_samples=1000, n_classes=2, random_state=1)model = LogisticRegression()
model.fit(X, y)# predict probabilities
preds = model.predict_proba(X)[:,1]

现在我们想评估我们的模型使用 ROC 曲线的效果。为此,我们需要找到不同阈值的 FPR 和 TPR。我们可以通过使用来自sklearn.metrics的函数roc_curve很容易地做到这一点,它为我们提供了不同阈值的 FPR 和 TPR,如下所示:

fpr, tpr, thresh = roc_curve(y, preds)roc_df = pd.DataFrame(zip(fpr, tpr, thresh),columns = ["FPR","TPR","Threshold"])

我们从获得不同阈值的 FPR 和 TPR 开始。来源:作者图片

现在剩下的就是使用上面的数据绘制曲线。我们可以通过使用任何图形库来做到这一点,但我更喜欢[plotly.express](https://mlwhiz.com/blog/2019/05/05/plotly_express/),因为它非常容易使用,甚至允许您在 plotly express 图形的基础上使用 plotly 构造。正如您在下图中看到的,我们绘制了不同阈值下的 FPR 与 TPR 的关系。

来源:作者图片

如何使用 ROC 曲线?

我们通常可以使用 ROC 曲线来决定阈值。阈值的选择也将取决于分类器打算如何使用。因此,如果上面的曲线用于癌症预测应用,您希望获取最大数量的阳性结果(即,具有较高的 TPR ),您可能会选择较低的阈值值,如 0.16,即使此时 FPR 非常高。

这是因为你真的不想为一个实际上得了癌症的人预测“没有癌症”。在这个例子中,假阴性的成本相当高。即使一个没有癌症的人测试呈阳性,你也没问题,因为假阳性的成本比假阴性的成本低。这实际上是许多临床医生和医院为这种重要测试所做的,也是为什么如果一个人测试呈阳性,许多临床医生会第二次做同样的测试。(你能想到为什么这样做有帮助吗?提示:贝叶斯法则)。

否则,在像前面例子中的罪犯分类器这样的情况下,我们不需要高 FPR,因为司法系统的原则之一是我们不希望捕获任何无辜的人。因此,在这种情况下,我们可以将阈值选择为 0.82,这样我们的召回率或 TPR 为 0.6。也就是说,我们可以抓获 60%的罪犯。

现在,什么是 AUC?

AUC 是 ROC 曲线下的面积。该区域始终表示为 0 到 1 之间的值(正如 TPR 和 FPR 的范围都可以从 0 到 1),我们本质上希望最大化该区域,以便我们可以在某个阈值下拥有最高的 TPR 和最低的 FPR。

Scikit 还提供了一个实用函数,如果我们有使用roc_auc_score(y, preds)的预测和实际 y 值,它可以让我们获得 AUC。

来源:维基百科

还可以从数学上证明,AUC 等于分类器将随机选择的阳性实例排序高于随机选择的阴性实例的概率。因此,AUC 为 0.5 意味着阳性实例排名高于阴性实例的概率为 0.5,因此是随机的。一个完美的分类器总是将一个阳性实例排在一个阴性实例之上,并且 AUC 为 1。

那么,AUC 是阈值不变和尺度不变的吗?

是的,AUC 是阈值不变的,因为我们不必设置阈值来计算 AUC。

为了检查标度不变性,我将做一个实验,在这个实验中,我将我们的预测乘以一个随机因子(标度),并对预测求幂,以检查即使它们的等级顺序不变,如果预测改变,AUC 是否改变。由于 AUC 是比例不变的,我希望有相同的 ROC 曲线和相同的 AUC 指标。在下面,你可以看到左边的比例和右边的指数排名顺序。

缩放(左)和取幂排序(右)

事实上这就是我得到的。只有阈值随着标度的变化而变化。曲线的形状以及 AUC 保持完全相同。

结论

创建任何机器学习管道的一个重要步骤是相互评估不同的模型。选择错误的评估指标或者不理解您的指标的真正含义可能会对您的整个系统造成严重破坏。我希望,通过这篇文章,我能够消除你对 ROC 曲线和 AUC 的一些困惑。

如果你想了解更多关于如何构建机器学习项目以及这样做的最佳实践,我会推荐 Coursera 深度学习专业化中名为“构建机器学习项目”的这个优秀的第三门课程。一定要去看看。它解决了陷阱和许多改进模型的基本思想。

我以后也会写更多这样的帖子。让我知道你对这个系列的看法。在 媒体 关注我,或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系到我

此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。

浅显易懂的 C 语言介绍

原文:https://towardsdatascience.com/an-understandable-introduction-to-c-e2cc12a52053?source=collection_archive---------14-----------------------

速成班

对 C 语法结构的有效观察,以及对 C 编程的介绍

(src =https://pixabay.com/images/id-1143863/

介绍

C 编程语言可能是计算机历史上最重要的编程语言之一。这种语言确实在很多方面让计算机世界变得更好,并且在今天的计算世界中仍然扮演着重要的角色。不管你目前是在什么系统上阅读这篇文章,除非你出于某种原因把它打印了出来,否则正如我们所说的,你正在使用 C 代码。也就是说,如果你在任何技术领域工作,学习 C 语言对你的领域有益是很容易理解的。这当然包括软件工程和数据科学,但我认为 C 编程语言应该涉及的不仅仅是这些学科。我还制作了一个视频,对某些人来说可能更容易理解。

如果您想通过 Github 访问本文中使用的代码,可以在这里查看:

https://github.com/emmettgb/C-CrashCourse/blob/main/1/christmas_tree.c

事不宜迟,现在让我们讨论更多关于 C 编程语言的内容,并开始我们对这种语言的第一印象吧!

为什么要学 C?

当然,每当学习一种新的编程语言的问题出现时,当然应该问学习一种给定的编程语言有什么好处。我将从人们可能想学习 C 语言的一些一般原因开始,然后我将继续讨论 C 语言编程可能给科学领域带来的具体好处。

我推荐学习 C 语言的第一个主要原因是它是通用的。正如我之前提到的,你用来阅读这篇文章的电脑、手机或平板电脑可能从头到尾都写满了 C 代码。C 无处不在,并且是通用的,这意味着当与 C 一起使用时,你的软件几乎可以在任何地方运行,这种通用性也体现在 C 与其他编程语言的集成中。由于大多数操作系统及其各自的头文件都是用 C 语言编写的,所以大多数脚本语言和其他高级语言都与 C 语言集成得非常好。如果不是这样,那么这种语言在广泛使用和与其他软件一起工作时可能会有一些问题。

对于一般的软件应用程序,我支持学习 C 的最后两点是,首先,C 可以成为学习 C++的一个很好的基础。像 C 一样,C++是一种非常通用的编程语言,需求量也很大,是一种非常值得了解的语言。考虑到这一点,那些想学习 C++的人可能想先学习 C,以便掌握一些基本的语法并更好地理解 C++,而没有这种语言的范例挡路。最后,C 是最快的高级语言。在我个人看来,没有比 C 更好的了。C 代码将是你在大多数情况下可能编写的最快速和最通用的代码——所以 C 是需要高级优化的应用程序的最佳选择。

如果你想了解更多关于这如何应用于数据科学的知识,我专门写了一整篇文章。因为有很多材料我想看完,而不是把这篇文章写成一本书,所以我在这本书上练习提取方法,那些感兴趣的人可以阅读更多。尤其是因为我已经写过这个话题,没有必要再重复同样的话:

[## 为什么 C 对于数据科学来说很方便

towardsdatascience.com](/why-c-comes-in-handy-for-data-science-76071206bb5)

C 语言的主要特点

获得 C 编程语言的基础将从理解编程语言的关键特性和方法开始。在我看来,和任何语言一样,人们应该了解的第一件事是 C 的范式。c 是一种经典的命令式编程语言。这意味着当我们用 C 语言编程时,我们可以与硬件紧密互动。我们能够直接管理计算机的组件,而不是以不干涉的声明方式来使用我们的计算机。

关于 C 应该知道的第二件事是,这种语言是静态类型的。这是这种编程语言的典型特征,需要注意的是,这当然与在键盘上打字无关。类型系统是编程语言处理定制数据结构的方式。类型还可以增加编程的继承性和范围,因此它们无疑是编程语言中的无价之宝。静态这个词,至少在这个意义上(我们不是在地毯上摩擦我们的袜子,)意味着它不变。就像我们用 Java 写public static void一样,这意味着我们描述的东西不会改变。记住,用 C 在我们的软件中声明的变量类型在运行时不会改变。这意味着编译停止后,开始执行,我们的类型被锁定,我们无法改变它们。

关于 C 你应该知道的另一件事是,它是一种相当低级的语言。当然,这只是与当今典型的语言相比,但一般来说,C 会让你写得更多,做得更少。然而,原因是 C 有一种通过汇编解释我们的代码的特定方法,这种方法通常被认为是非常快速的…代价是在某些情况下,语法可能比其他语言更难。这种语言也非常古老,使得许多已经用 C 语言编写的优秀软件非常容易被 C 程序员、许多库、优秀的文档等访问。

安装说明

现在我们已经讨论了为什么你应该使用 C,如果你决定尝试一下这种语言,那么你可能需要安装它。下面我列出了每个平台的说明。

Linux 操作系统

如果您使用的是 Linux,那么您的机器上可能已经安装了 GCC。为了检查该语句的有效性,您可以键入

gcc -v

进入你的终端。如果“gcc -v”不是一个已知的命令,那么您的软件包管理器可能会推断您想要安装 gcc。当然,无论哪种方式,您都可以使用您的软件包管理器来安装它

sudo dnf install gcc
sudo apt install gcc
sudo pacman -S gcc
sudo man install gcc

我们有这么多的包装经理,我相信你知道你的是什么。

马科斯

为了在 MacOS 上安装 GCC,您需要一个包管理器。这通常是 Brew 包管理器。因为我不是 Mac 用户,所以在这一点上,我建议我的 MacOS 朋友(类似 Unix 的兄弟/姐妹/非二进制 hood)参考另一篇提供此类信息的文章:

在您的机器上安装 Brew 之后,您可以简单地在您的终端上运行我们在 Linux 上运行的相同命令。如果您还没有更新您的软件包档案,那么您可能应该先这样做。

**brew update****brew install gcc**

https://www.digitalocean.com/community/tutorials/how-to-install-and-use-homebrew-on-macos

旁注——谢天谢地有人做了一个 MacOS 软件包管理器。我不明白没有包管理器人们怎么生活。

Windows 操作系统

对于我的 Windows 朋友来说,我相信 C 编译器的安装是非常典型的常规 Windows 安装。我会从下面的链接下载setupx86_64.exe,然后运行它:

https://www.mingw-w64.org/

编写我们的第一个程序

我们真的不需要做太多准备来开始创建我们的新 C 项目。我所做的基本上就是创建一个漂亮的工作目录,并在其中创建一个新文件——我最初将其命名为等腰. c,但后来将其重命名为 christmas.c,因为我开始这个项目时想制作一个三角形——

但是有点辣。(喜欢薄荷辣,不喜欢辣椒辣。)

因此,我们在新的 christmas.c 文件中要做的第一件事是编写一个主函数。在此之前,我想用一种智能的方法来编写一个函数。每当我去写一个函数时,我总是做的第一件事就是考虑我的输入和输出。首先,我需要什么来调用这个函数?其次,我希望从这个功能中达到的结果是什么?当我们写代码时,有一个清晰的方向,以及一条清晰的路径,无论何时我们编程都是绝对必要的。虽然有一些方法可以让我们在输出时“随波逐流”,但我们当然希望了解函数的作用——并为该指令恰当地命名所述函数。

考虑到这一点,这个建议对 C 也有一点帮助,因为参数是和返回的类型一起列出的。记住,C 中的打字是静态的,非常强。强静态类型意味着这个返回类型是不可变的和显式的。也就是说,我们的返回必须明确定义为我们放入该字段的类型。当我们写一个主函数时,返回的总是一个整数。这是因为我们的程序总是会返回一个退出代码。退出代码是编程中的一种通用方法,用来告诉计算机是否有什么地方出错了。基本上我们可以说误差=(我们的回报。)当然,如果没有错误,我们希望这是假的—或零。让我们考虑我们的第一个功能:

int main(){}

上面代码中的“int”是我们的返回类型。如上所述,这将是一个 0,因为我们没有任何错误,甚至错误处理目前。main()函数只是一个新的方法定义。请注意,每当运行 C 文件时,编译器都会寻找这个定义来执行。请记住,如果我们要编写另一个不是从我们的主函数调用的函数,这段代码将不会运行。最后,C 语言中打开和关闭函数的方法语法就是{}括号。这将包含这个新函数的内容。假设首先运行这个函数,我们不需要在我们的参数中放入任何东西,这些参数通常在 main()后面的括号内。这当然可以通过 CLA 来改变,我们将在这些演练的下一部分中讨论这一点。

最后,我们将返回我们的函数。我们可以简单地在这个函数中加入 return 0。我们还需要在这个表达式的末尾添加一个分号。每当我们在 C 语言中完成类似这样的语句时,我们都需要使用分号。这让 C 知道这是函数中这个特殊调用的结束,我们想继续下一个调用。

int main(){
    return 0;
}

现在让我们回到我们的终端或奇怪的 Windows 命令提示符的事情。随便想想,Windows 用户在编程时可能想考虑的一个选项是 WSL,即 Linux 的 Windows 子系统。我听说它非常耐用而且容易使用…并且可以让您更好地理解(即使使用真正的 GCC 编译器!)不管怎样,如果我们是 ls(或者对于 windows 用户是 dir),我们将看到我们的 christmas.c 文件:

lschristmas.c

现在我们将把它编译成一个二进制文件:

gcc christmas.c -o Christmas

这将为我们提供一个可执行文件,不需要 linker-dude(我对 ld 的昵称)或任何类似的特殊东西,我们可以简单地用。/适用于 MacOS/Linux 用户。我认为 Windows 用户需要双击输出文件。

./Christmas

现在你会“C”(懂了吗?)那什么都没发生。

标准输出

鉴于这仅仅是对 C 编程语言的一个基本而缓慢的介绍,并且我刚刚花了 20 分钟解释什么是 C 以及如何在各种操作系统上安装 C,今天我们将只讨论标准输出。然而,为了做到这一点,我们将需要利用一些依赖关系。我现在才意识到——我不知道如何在 Windows 上安装头文件——我强烈推荐 WSL,但是标准库和标准输入/输出包含在 GCC 中,所以我认为至少这篇文章不会有问题。

在我们开始写这个小 C 文件的其余部分之前,请允许我先解释一下为什么什么都没发生。每当我们运行下面的代码时,

int main(){
    return 0;
}

我们的编译器直接跳转到我们在这里定义的 main()函数。一旦它运行了上述函数中的语句,就会立即返回一个退出代码 0。因此,它没有错误地退出。为了从这个软件中获得一些输出,我们需要做的第一件事是包含两个头,stdlib.h 和 stdio.h。对于这个场景,我们不一定需要 stdlib.h,但它在将来肯定会派上用场,并且这是在大多数用 c 编写的软件的开头编写的。h 在这方面意味着这是一个头文件,它包含了一些我们的 C 软件将要依赖的数据。在 C 语言中包含文件的语法是使用#后跟 include。然后,我们用箭头<>将想要包含的标题括起来。

#include <stdlib.h>
#include <stdio.h>int main(){
    return 0;
}

现在我们可以开始向我们的函数添加输出。我不打算用我花了多长时间画一棵圣诞树来烦你,(我认为它花了太多时间。)所以请允许我将完整的代码粘贴在这里供您欣赏。这里唯一的信息是一些正则表达式,printf()方法,这是标准输出,以及如何使用引号""编写字符串。

#include <stdlib.h>#include <stdio.h>int main() {printf("    ★\n");printf("   /_\\\n");printf("  /_ _\\\n");printf(" /_  _ \\\n");printf("/       \\\n");printf("---------\n");printf("   | |\n");return 0;}

结论

我认为 C 语言仍然是程序员最有价值的学习经历之一。如果你不熟悉 C 编程语言,我强烈推荐你学习它,因为它很有趣,功能多样,而且它的命令性可以教会你很多东西。就我个人而言,我发现从软件的角度来了解硬件,尤其是我个人使用的硬件,是一件非常有趣的事情。

感谢您的阅读!祝你在进入可爱的 C 世界的旅途中好运!我将很快贴出这个快速简单速成课程的更多部分!

Python 中升级的营销组合建模

原文:https://towardsdatascience.com/an-upgraded-marketing-mix-modeling-in-python-5ebb3bddc1b6?source=collection_archive---------1-----------------------

营销分析

让我平庸的营销组合模式更加强大

照片由彼得·阮在 Unsplash 上拍摄

闪回

在我的上一篇文章中,我向您介绍了营销组合建模的世界。如果您尚未阅读,请在继续之前阅读。

在那里,我们创建了一个线性 回归模型,该模型能够根据几个广告渠道(如电视、广播和网络横幅广告)的原始广告支出来预测销售额。对于作为机器学习实践者的我来说,这样的模型本身就已经很好了。更好的是,它还让商界人士感到高兴,因为该模型让我们能够计算投资回报率,让我们能够判断每个渠道的表现如何。

然而,我们上次的简单线性回归模型有一些问题,我们将在本文中解决。让我给你解释一下:

  1. 我们第一款产品的性能可能会更好。
  2. 我们的第一个模型表现得不真实。将支出增加到无穷大也会将销售额增加到无穷大,这毫无意义,因为人们只能在我们的产品上花有限的钱。
  3. 优化变得琐碎、无用、不切实际。为了在给定固定预算的情况下最大化销售额,我们现在将把所有资金投入到线性回归系数最高的渠道中。

广告😉

我创建了一个小库,在这里我实现了本文其余部分的思想,甚至更多。通过pip install mamimo安装,并在此查看如何使用:

解决问题

为了规避这些问题,我们可以做一些聪明的特征工程,允许我们将一些营销领域的知识整合到模型中。不要担心,理解这些概念不需要营销经验,因为它们很自然,因此很容易理解。以下技术将提高性能,并使模型更加真实。

广告股票

我们要做的这个特色工程是一个至关重要的组件,叫做https://en.wikipedia.org/wiki/Advertising_adstock这是西蒙·布罗德本特发明的一个术语[1]。这是一个包含两个简单概念的奇特词汇:

  1. 我们假设你花在广告上的钱越多,你的销售额就越高。然而,我们花得越多,增长就越弱。例如,将电视支出从 0 €增加到 100,000 €会大大增加我们的销售额,但将它从 100,000,000 €增加到 100,100,000 €就没有那么多了。这叫做饱和效应收益递减效应** **
  2. 如果你在广告周花钱,人们通常不会立即购买你的产品,而是在几周之后。这是因为该产品可能很贵,人们希望仔细考虑它,或者将其与其他公司的类似产品进行比较。不管是什么原因,在第 T + x 周的销售部分是由你在第 T、周播放的广告引起的,所以它也应该得到一些积分。这被称为遗留滞后效应

我认为这两个事实都很容易理解,商界人士也很喜欢。

我们的新模型仍然是线性的,但是用 adstock 特性代替原始支出作为输入。这使得模型更加强大,同时保持其可解释性。

在 scikit-learn 中构建饱和度和结转效应

对我们来说不幸的是,scikit-learn 不包含这些转换,因为它们不是跨行业的兴趣。但是由于这两种转换都没有那么复杂,所以这是一个练习编写 scikit-learn 兼容估计器的好机会。

如果你以前从未这样做过,你可以看看我的另一篇关于这个话题的文章。这篇文章是关于回归变量而不是变压器的,但是方法并没有太大的不同。

**

所以,让我们从更简单的开始:饱和效应。

产生饱和效果

我们希望创建一个具有以下属性的变换(=数学函数):

  1. 如果支出为 0,则饱和支出也为 0。
  2. 该转换是单调递增的,即输入支出越高,饱和输出支出越高。
  3. 饱和值不会增长到无穷大。相反,它们的上限是某个数,比如说 1。

简而言之,我们想要这样的东西:

图片由作者提供。

有很多方法可以得到这样的函数,例如,在图片中你可以看到函数 1-exp(-0.7 x )。所以让我们使用这个函数模板,并将其推广到 1-exp(-ax)for somea>0。 a 是一个超参数,我们可以随后进行调整,因为通常我们不知道饱和函数的形状。

N ote: 还有许多更标准的饱和度函数,如AdbudgHill函数,但让我们坚持用 指数函数 函数

一个很好的副作用:我们最终能够输出饱和曲线,所以我们知道花更多的钱是否有意义,或者渠道是否已经饱和。比如从上图来看,投资 8 以上好像就没用了。

所以,我们来编码一下。事实上,就是这个简单的小类:

class ExponentialSaturation:
    def __init__(self, a=1.):
        self.a = a

    def transform(self, X):
        return 1 - np.exp(-self.a*X)

然而,我们将为输入添加一些健全性检查,以使其符合 scikit-learn。这增加了一点代码,但这是我们必须付出的相对较小的代价。

from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.utils.validation import check_is_fitted, check_array

class ExponentialSaturation(BaseEstimator, TransformerMixin):
    def __init__(self, a=1.):
        self.a = a

    def fit(self, X, y=None):
        X = check_array(X)
        self._check_n_features(X, reset=True) # from BaseEstimator
        return self

    def transform(self, X):
        check_is_fitted(self)
        X = check_array(X)
        self._check_n_features(X, reset=False) # from BaseEstimator
        return 1 - np.exp(-self.a*X)

它仍然不完美,因为我们还应该实现对大于零的 a 的检查,但这是你可以自己轻松完成的事情。使用ExponentialSaturation变压器,我们可以做到以下几点:

图片由作者提供。

这个不算太糟,对吧?现在让我们来看下一个效应。

产生遗留效应

这个稍微复杂一点。让我用一个例子来说明我们想要达到的目标。随着时间的推移,我们会有一系列的支出,例如

(16, 0, 0, 0, 0, 4, 8, 0, 0, 0),

这意味着我们在第一周花了 16 英镑,然后从第 2 周到第 5 周我们什么也没花,然后在第 6 周我们花了 4 英镑,等等。

我们现在希望一周的花费能以指数形式部分结转到下一周。这意味着:在第一周有 16 英镑的支出。那么我们携带超过 50%,意思是

  • 0.5 * 16 = 8 到第 2 周,
  • 0.5 * 16 = 4 到第 3 周,
  • 0.5 * 16 = 2 到第 4 周,

这引入了两个超参数:强度(有多少被结转?)和长度(多长时间结转?)的结转效应。如果我们使用 50%的强度和 2 的长度,则上面的支出顺序变为

(16, 8, 4, 0, 0, 4, 10, 5, 2, 0).

我相信你可以写一些循环来实现这个行为,一个好的快速的方法是使用卷积。我就不详细解释了,就拿代码当礼物吧。我再次强调了真正重要的线。

from scipy.signal import convolve2d
import numpy as np

class ExponentialCarryover(BaseEstimator, TransformerMixin):
    def __init__(self, strength=0.5, length=1):
        self.strength = strength
        self.length = length

    def fit(self, X, y=None):
        X = check_array(X)
        self._check_n_features(X, reset=True)
        self.sliding_window_ = (
            self.strength ** np.arange(self.length + 1)
        ).reshape(-1, 1)
        return self

    def transform(self, X: np.ndarray):
        check_is_fitted(self)
        X = check_array(X)
        self._check_n_features(X, reset=False)
        convolution = convolve2d(X, self.sliding_window_)
        if self.length > 0:
            convolution = convolution[: -self.length]
        return convolution

可以看到,上课是走强度和长度的。在拟合过程中,它会创建一个滑动窗口,由 convolve2d 函数使用,神奇地完成我们想要的工作。如果你知道 CNN 的卷积层,这就是这里发生的事情。从图形上看,它执行以下操作:

图片由作者提供。

N 注: 还有很多方法可以创建遗留问题。衰变不一定是指数的。也许广告效果的顶峰不是在花钱的那天,而是在下一周。您可以通过相应地更改滑动窗口来表达所有这些变化。

让我们结合饱和效应和结转效应来创建一个更现实的营销组合模型。

最终模型

我们将对每个渠道使用不同的饱和度和结转。这是有道理的,因为通常情况下,电视广告比你在网上看到的横幅广告在你脑海中停留的时间更长。从高层次的角度来看,该模型将如下所示:

图片由作者提供。

请注意,蓝色管道只是电视支出的函数,橙色管道是广播支出的函数,紫色管道是横幅广告支出的函数。我们可以使用ColumnTransformerPipeline类在 scikit-learn 中有效地实现这一点。ColumnTransformer允许我们对每个广告渠道使用不同的转换,而Pipeline允许我们对单个渠道进行连锁操作。花点时间理解下面的片段:

from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LinearRegression

adstock = ColumnTransformer(
    [
     ('tv_pipe', Pipeline([
                           ('carryover', ExponentialCarryover()),
                           ('saturation', ExponentialSaturation())
     ]), ['TV']),
     ('radio_pipe', Pipeline([
                           ('carryover', ExponentialCarryover()),
                           ('saturation', ExponentialSaturation())
     ]), ['Radio']),
     ('banners_pipe', Pipeline([
                           ('carryover', ExponentialCarryover()),
                           ('saturation', ExponentialSaturation())
     ]), ['Banners']),
    ],
    remainder='passthrough'
)

model = Pipeline([
                  ('adstock', adstock),
                  ('regression', LinearRegression())
])

最难的部分是ColumnTransformer,所以让我来解释一下如何阅读用粗体标记的电视块。它只是说:

将管道应用于“TV”列,并将此部分命名为“tv_pipe”。管道只是 adstock 转换。

那里没有更多的事情发生。最后,我们使用这个大的预处理步骤,并在末尾添加一个简单的LinearRegression来得到一个实际的回归变量。那么,让我们 再次加载数据 并做一些训练。

import pandas as pd
from sklearn.model_selection import cross_val_score, TimeSeriesSplit

data = pd.read_csv(
    'https://raw.githubusercontent.com/Garve/datasets/4576d323bf2b66c906d5130d686245ad205505cf/mmm.csv',
    parse_dates=['Date'],
    index_col='Date'
)

X = data.drop(columns=['Sales'])
y = data['Sales']

model.fit(X, y)

print(cross_val_score(model, X, y, cv=TimeSeriesSplit()).mean())

# Output: ~0.55

注: 我们这里不使用标准的 k -fold 交叉验证,因为我们处理的是时间序列数据。 *TimeSeriesSplit* 是比较合理的做法,这里 可以多了解一下

有用!然而,该模型仍然相当糟糕,交叉验证的 r 约为 0.55,而旧的、更简单的模型为 0.72。这是因为我们为每个通道使用了默认的非最佳参数,即饱和度的 a = 1,残留强度为 0.5,长度为 2。

因此,让我们调整所有的 adstock 参数!

超参数调谐

我将使用 Optuna ,一个用于优化任务的高级库。在许多其他的事情中,它提供了一个 scikit-learn 兼容的OptunaSearchCV类,你可以把它看作是 scikit-learn 的[GridSearchCV](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html)[RandomizedSearchCV](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html)的替代物。

简而言之,OptunaSearchCVRandomizedSearchCV的更智能版本。虽然RandomizedSearchCV只是随机走动,但是OptunaSearchCV首先随机走动,然后检查看起来最有希望的超参数组合。

查看与您习惯用 scikit 编写的代码非常接近的代码——了解:

from optuna.integration import OptunaSearchCV
from optuna.distributions import UniformDistribution, IntUniformDistribution

tuned_model = OptunaSearchCV(
    estimator=model,
    param_distributions={
        'adstock__tv_pipe__carryover__strength': UniformDistribution(0, 1),
        'adstock__tv_pipe__carryover__length': IntUniformDistribution(0, 6),
        'adstock__tv_pipe__saturation__a': UniformDistribution(0, 0.01),
        'adstock__radio_pipe__carryover__strength': UniformDistribution(0, 1),
        'adstock__radio_pipe__carryover__length': IntUniformDistribution(0, 6),
        'adstock__radio_pipe__saturation__a': UniformDistribution(0, 0.01),
        'adstock__banners_pipe__carryover__strength': UniformDistribution(0, 1),
        'adstock__banners_pipe__carryover__length': IntUniformDistribution(0, 6),
        'adstock__banners_pipe__saturation__a': UniformDistribution(0, 0.01),
    },
    n_trials=1000,
    cv=TimeSeriesSplit(),
    random_state=0
)

你告诉 Optuna 优化model。它通过使用您在param_distributions中指定的所有参数来实现。因为我们的模型是完全嵌套的,也就是说,列转换器中有管道,而列转换器本身又在管道中,所以我们必须准确地指定我们想要优化的超参数。这是通过诸如adstock__tv_pipe__carryover__strength这样的字符串来完成的,其中两个下划线分隔了完整模型的不同层次。你发现adstocktv_pipecarryover这几个字都在型号说明书里,而strengthExponentialCarryover变压器的一个参数。

然后,你找到一些分布。UniformDistribution(0, 1)表示应该在 0 和 1 之间寻找浮点参数。按照同样的逻辑,IntUniformDistribution(0, 6)搜索 0 到 6 之间的整数值(不是 5!),因此我们告诉模型只考虑结转长度小于或等于六周,这只是我们的一个选择。

我们尝试n_trials=1000不同的参数组合,并再次使用TimeSeriesSplit进行评估。通过设置random_state=0保持结果的可再现性。搞定!这应该足够理解代码了。

性能检查

让我们使用这个名为tuned_model的优化模型来检查性能。小心,这需要很长时间。你可以将n_trials减少到 100,以更快地得到一个更差的解。

print(cross_val_score(tuned_model, X, y, cv=TimeSeriesSplit()))

# Output: array([0.847353, 0.920507, 0.708728, 0.943805, 0.908159])

平均交叉验证的 r0.87,与未优化的模型(0.55)和我们上一篇文章中的旧平面线性模型(0.72)相比,这是一个很大的改进。让我们现在改装模型,看看它学到了什么。

tuned_model.fit(X, y)

最佳超参数如下:

print(tuned_model.best_params_)
print(tuned_model.best_estimator_.named_steps['regression'].coef_)
print(tuned_model.best_estimator_.named_steps['regression'].intercept_)

# Output:
# Hyperparameters = {
# 'adstock__tv_pipe__carryover__strength': 0.5248878517291329
# 'adstock__tv_pipe__carryover__length': 4
# 'adstock__tv_pipe__saturation__a': 1.4649722346562529e-05
# 'adstock__radio_pipe__carryover__strength': 0.45523455448406197
# 'adstock__radio_pipe__carryover__length': 0
# 'adstock__radio_pipe__saturation__a': 0.0001974038926379962
# 'adstock__banners_pipe__carryover__strength': 0.3340342963936898
# 'adstock__banners_pipe__carryover__length': 0
# 'adstock__banners_pipe__saturation__a': 0.007256873558015173
# }
#
# Coefficients = [27926.6810003   4114.46117033  2537.18883927]
# Intercept = 5348.966158957056

对新数据使用模型

如果您想为新的支出表创建预测,可以按如下方式进行:

X_new = pd.DataFrame({
    'TV': [10000, 0, 0],
    'Radio': [0, 3000, 0],
    'Banners': [1000, 1000, 1000]
})

tuned_model.predict(X_new)

请注意,预测总是以零库存开始,即模型不知道过去的任何结转,除非您将它放入预测数据框架。例如,如果您想知道第周到第周的销售额,并且您只输入第周到第周的支出,那么它不会考虑之前第周到第 -1 周、周到第 -2 周的结转。如果你想让模型建立一个库存,你也必须包括之前的几周,即使你只对最后一次观察的预测感兴趣。

你甚至可以用更多不花费的特性来扩展训练数据,所谓的控制变量。如果您没有在ColumnTransformer对象中指定任何预处理,原始值将直接传递给LinearRegression并被考虑用于训练和预测。

解释模型

使用上面的数据,我们可以创建一些漂亮的图片,帮助我们从模型中获得洞察力。

饱和效应

如果我们插入饱和变压器的值,我们会得到以下结果:

图片由作者提供。

  • 我们可以看到,该模型认为电视频道仍然非常不饱和——在这里花费更多可能有利于销售。注意,我们最大的电视支出大约是 15000 英镑。
  • 广播看起来有点饱和,但增加这方面的支出似乎还是合理的。该渠道最高消费约 7700。
  • 横幅看起来过饱和。这里最高消费 2500 左右,函数值已经接近 1 了。更高的支出似乎不会有太大的成效。

遗留效应

如果我们插入延续变压器的值,我们会得到以下结果:

图片由作者提供。

似乎电视广告在最初消费 4 周后仍然对销售有影响。这比广播和网络横幅广告在同一周内迅速消失的效果要长得多。

渠道贡献

和上一篇文章一样,我们可以计算每个渠道对每天销售额的贡献。代码比以前稍微复杂一些,因为模型也变得更复杂了。无论如何,这里有一个工作版本:

adstock_data = pd.DataFrame(
    tuned_model.best_estimator_.named_steps['adstock'].transform(X),
    columns=X.columns,
    index=X.index
)

weights = pd.Series(
    tuned_model.best_estimator_.named_steps['regression'].coef_,
    index=X.columns
)

base = tuned_model.best_estimator_.named_steps['regression'].intercept_

unadj_contributions = adstock_data.mul(weights).assign(Base=base)
adj_contributions = (unadj_contributions
                     .div(unadj_contributions.sum(axis=1), axis=0)
                     .mul(y, axis=0)
                    )

ax = (adj_contributions[['Base', 'Banners', 'Radio', 'TV']]
      .plot.area(
          figsize=(16, 10),
          linewidth=1,
          title='Predicted Sales and Breakdown',
          ylabel='Sales',
          xlabel='Date'
      )
     )

handles, labels = ax.get_legend_handles_labels()
ax.legend(
    handles[::-1], labels[::-1],
    title='Channels', loc="center left",
    bbox_to_anchor=(1.01, 0.5)
)

输出:

图片由作者提供。

与旧图相比,基线不再摇摆不定,因为该模型可以更好地解释给定渠道支出的销售情况。下面是老款的一款:

型号。图片由作者提供。

总结与展望

在本文中,我们采用了旧的简单线性模型,并通过不依赖原始渠道支出,而是依赖广告库存来改进它。广告库存是通过引入饱和效应和结转效应来更真实地反映现实世界的转换支出。

我们甚至对这两个概念做了简明的实现,可以在 scikit-learn 生态系统中以即插即用的方式使用。

我们做的最后一件事是调整模型,然后看看它已经了解了什么。我们以人们容易理解的图片形式获得了一些有趣的见解,使这个模型既准确又可解释。

然而,仍有一些未解决的问题:

  1. 我们已经讨论了优化支出,以及旧模式为何无法做到这一点。嗯,有了新的,但我不会在这里详细介绍。简而言之,对待我们的tuned_model函数,用你选择的程序优化它,例如 Optunascipy . optimize . minimize。为优化添加一些预算约束,例如总支出应少于 1,000,000。
  2. 非支出数据输入模型可能会进一步改善它。例如,以一周中的,或者甚至是我们想要销售的产品的价格为例。尤其是价格是销售的一个重要驱动力:一部售价 10000 €的普通 iPhone 不会产生多少销量,而一部售价 100 €的 iPhone 会在一眨眼的功夫就脱销。对于季节性产品(如粉丝或热巧克力)来说,月份等及时功能可能很有意思。或者像圣诞节这样的特殊日子。收集你的想法,并确保添加所有能够影响销售的内容!

参考

[1] S .布罗德本特,《电视广告的单向作用》(1979 年)。《市场研究学会杂志21 (3),第 139–166 页。**

我希望你今天学到了新的、有趣的、有用的东西。感谢阅读!

作为最后一点,如果你

  1. 想支持我多写点机器学习和
  2. 无论如何都要计划获得中等订阅量,

为什么不做 通过这个环节 ?这将对我帮助很大!😊

透明地说,给你的价格不变,但大约一半的订阅费直接归我。

非常感谢,如果你考虑支持我的话!

有问题就在LinkedIn上写我!**

写了一年的数据科学文章

原文:https://towardsdatascience.com/an-year-of-writing-data-science-articles-96c1e17b09ec?source=collection_archive---------36-----------------------

简短的背景故事、学习经历和关键要点!

照片由思想目录在 Unsplash 上拍摄

一年前,我欣喜若狂地发表了我的第一篇文章《走向数据科学》,这是我长期关注的最好的平台之一。

在写这篇文章的时候,我已经在这个平台上写了近百篇文章,聚集了大约 800 名追随者,并多次成为人工智能和生产力领域的顶级作家,同时也获得了这个平台上 1000 名顶级作家的荣誉。

虽然文章的统计数据和表现对我来说并不重要,但它仍然是一个压倒性的积极影响,从社区获得了大量的积极和爱。接触到广泛的受众并分享最好的知识,希望能够帮助所有有志于这门学科的人和爱好者,这是一种巨大的快乐。

我的文章的目标是接触到所有层次的研究人员和开发人员,并为大多数读者提供一些信息。由于我一直忙于我的全职工作,几个月来发表文章的速度略有下降。但是,我打算长期坚持写下去,把最好的资源分享给大家!

下面是我个人最喜欢的文章之一,我会推荐大多数数据科学初学者查看,以深入探索该主题的大多数复杂细节和方面。

</12-steps-for-beginner-to-pro-in-data-science-in-12-months-c6f6ba01f96e>

通过这篇文章,我希望分享我在一年多的时间里写数据科学和人工智能文章时积累的一些重要知识和经验。在我们深入讨论关键要点之前,我想分享一些关于我的背景的小细节,我被问了好几次。事不宜迟,让我们开始吧!

简短背景故事:

照片由大流士巴沙尔在 Unsplash

经过三年从众多资源中学习数据科学和人工智能,我开始构建一些很酷的项目。虽然我总是构建一些项目来将我的理解与特定的概念相关联,但我觉得我能够在那个学习阶段执行一些相当高水平的项目。因此,我认为分享我的想法和项目是一个很好的主意,这样可以帮助其他人,也可以在一个受欢迎的平台上传播我的想法。

在写我的第一篇文章的时候,我正在进行一个深度学习项目,在人类情感和手势检测的任务上使用迁移学习和定制模型。我以两部分系列的形式发表了这些关于迈向数据科学的文章,并由此开始了我的文章写作之旅。如果您有兴趣探索更多,请点击下面的链接。

最初的想法是写几篇文章,可能只是转移到我的其他爱好上。然而,在我早期的帖子中收到的爱和鼓励越来越多地激励我继续学习和写作。

在写了几个月的大量文章后,我不得不过渡到一个更平衡的系统,因为我在该国一家知名机构实习了三个月,现在我正全职从事深度学习的研发工作。

尽管我很忙,但我计划只要有时间就为我所有的读者写有用的文章,这样每个人都可以从中找到最好的效用!

我的经历和主要收获:

照片由UX在 Unsplash 上拍摄

现在我们有了一个简短的背景故事,我的许多观众都对它感兴趣,我将尝试探索我的一些主要经验和在这个平台上作为一名作家不断发展的主要学习。在这一部分,我将解释五个最重要的知识,它们对我帮助很大,增加了我对概念的理解和个性的全面发展。

1.增长的学习曲线:

虽然我最初开始写文章来展示我的工作和开发更多的项目,但随着我写更多的文章,我开始有每天学习新东西的冲动。写文章的时候,我的学习曲线总体上有所增长,因为我不断地理解更多的新概念,并在我已经简单了解的主题上磨练我的技能。

定期写文章的主要好处之一是,我可以不断地用新的现代技术和人工智能世界中不断发现的其他新技术来更新自己。在与其他了不起的读者分享它们的同时,我也有机会对每个主题有了更多的个人了解。

2.新的思想渠道:

虽然我通常在随意拖延和想一些最愚蠢的事情时得到大多数最好的想法,但我发现对我个人来说,写作帮助我将我的想法引向积极的方向。它使我能够思考不同的事情,并且不会忘记我在想什么,因为我把它写下来,然后对这个话题进行更多的探索。

这种方法可能不太适合大多数人,但对我来说非常有效,我建议试一试。你也可以写一些笔记来确保你的想法朝着正确的方向发展。每个不同的人都有不同的获取新概念和理解新思想的方法。

3.了解在线博客的复杂细节:

对我个人来说,最大的好处之一是理解了在线博客错综复杂的细节。在这一年中,我有过几次学习经历。作为一个完全不熟悉在线撰写数据科学文章的人,我意识到了在线遵循正确的程序以获得更有成效的结果。

TDS 的编辑团队在整个旅程中给予了我特别的支持,他们在几个方面帮助我提高了写作技巧,并从整体上提高了我的在线形象。他们有益的反馈有助于提高文章的质量以及我对这个主题的总体了解。

由于我获得了持续的知识,在许多其他项目或其他工作组织中工作对我来说也是一次奇妙的经历。有了一些学习经验,如图像版权声明、提供真实来源、抄袭规则和其他类似的规定,我对如何进行大多数任务有了清晰的理解。

4.支持性社区:

一般来说,学习人工智能、数据科学或 Python 编程的一个最好的方面就是从社区中获得大量的支持和鼓励。有几个网站、YouTube 视频、discord 频道、slack 频道、GitHub 和许多其他优秀的资源可供我们探索和利用。

除了这些资源丰富的材料之外,在这些领域中的每一个领域都有不断的更新,并且社区积极地致力于有效地完善每一个需求。如果你在某个问题上陷入困境,像 Stack Overflow 或 just friends online 这样的社区总是愿意提供帮助。利用这些机会,你可以建立令人敬畏的联系,共同繁荣!

5.终极满足感:

选择一个主题,研究特定的主题以获得额外的信息,写文章,反复检查和验证事实和信息,最后发表文章的整个过程是最愉快的经历之一。虽然有时工作可能会变得乏味,但分享新事物和学习新经验永远不会扼杀整体的兴奋感。

我从观众、读者、朋友和编辑团队那里得到了大量的鼓励,帮助我茁壮成长,并获得了巨大的满足感。因此,我将热爱在这个平台上长期从事以下写文章的爱好。

关键要点:

杰森·D在 Unsplash 上的照片

虽然我已经介绍了我想在本文中介绍的大部分主题,但我还是建议所有感兴趣的读者注意一些要点,这样他们就有希望从这些建议中受益。

  1. 数据科学的关键方面是要弄清楚,你花在学习这个主题上的时间越多,你获得的知识就越多。在这个广阔的领域没有捷径可走。
  2. 尝试利用你获得的知识,以某种方式对你的研究方法和风格有用和有成效。
  3. 如果你真的被数据科学的奇迹所鼓舞,继续追求你认为对你有意义的东西。
  4. 在构建任何数据科学项目时,在取得成功之前经历多次失败的情况应该被视为一个预先确定的结论。对于任何复杂的数据科学问题,第一次尝试就取得最佳结果几乎是不可能的。
  5. 对于任何对追求数据科学感兴趣的人来说,关键因素是你对学习该领域不断发生的新方面和发展的兴趣和持续的动力。

如果你仍然在选择数据科学的中途,还没有完全决定你在不久的将来想从事什么工作,我建议查看我以前的一篇文章,其中我谈到了成为数据科学家的十个错误理由。下面提供了链接。

</10-wrong-reasons-to-become-a-data-scientist-319531bb874e>

结论:

照片由达维德·扎维亚在 Unsplash 上拍摄

“如果你在做你真正关心的事情,你就不需要被逼。愿景拉着你。”史蒂夫·乔布斯

这篇文章与我平时写的文章大不相同。主要目标是涵盖我的观众想要回答的一些关于我的问题,我在一年的写作过程中所学到的主要经验,并给每个人一些关键的收获,以便他们最终能以某种方式从中受益。

总结我最后的想法,到目前为止这是一个神话般的旅程,我计划在未来继续撰写大量与人工智能和数据科学相关的文章。如果我的观众有什么具体的事情要讨论,请随时在下面的评论区联系我,或者在 LinkedIn 上联系我。

Medium 启动了一个新项目,让读者订阅他们最喜欢的作家的作品,以获得最快的更新。如果你喜欢我的内容,那么从下面的链接订阅,每当我发表文章时,你就会收到闪电般的通知!

https://bharath-k1297.medium.com/subscribe [## 当我发布时收到闪电般的速度通知!

bharath-k1297.medium.com](https://bharath-k1297.medium.com/subscribe)

如果你对这篇文章中提到的各点有任何疑问,请在下面的评论中告诉我。我会尽快给你回复。

看看我的其他一些文章,你可能会喜欢读!

</10-computer-vision-terms-everyone-must-know-about-687a98845fc8> </5-best-python-projects-with-codes-that-you-can-complete-within-an-hour-fb112e15ef44> </14-pandas-operations-that-every-data-scientist-must-know-cc326dc4e6ee> </7-best-ui-graphics-tools-for-python-developers-with-starter-codes-2e46c248b47c>

谢谢你们坚持到最后。我希望你们都喜欢这篇文章。祝大家有美好的一天!

用熊猫和 Plotly 分析 1993 年的米兰德比数据

原文:https://towardsdatascience.com/analyse-milan-derby-data-from-1993-with-pandas-and-plotly-b4648376c947?source=collection_archive---------37-----------------------

下一场米兰德比将于下周开始,为了向我的足球迷丈夫提供更多的信息和可视化,以及建立我的 python 学习,我从 Kaggle 获取了关于意甲和维基百科的数据,并试图开发一个基于证据的可视化。

Izuddin Helmi Adnan 在 Unsplash 上拍摄的照片

先决条件:

用于此分析的 Python 包:

import pandas as pd
import glob
import matplotlib.pyplot as plt
import numpy as np
import plotly.express as px

第一步:获取数据

当前分析中使用的数据来自 ka ggle(https://www.kaggle.com/massibelloni/serie-a-19932017),我从那里下载了 1993 年至 2017 年的所有意甲数据,并保存到本地文件夹中。

第二步:合并数据

从 Kaggle 下载的意甲数据是按年份呈现的。为了了解意甲的概况,我在过滤 AC 米兰/国际米兰的结果之前,先合并了所有的数据。

这里我使用了函数 glob :

##set up the path
path = r'.....SerieA'
all_files = glob.glob(path + "/*.csv")##read all files
tb = []
for filename in all_files:
    df = pd.read_csv(filename, index_col=None, header=0)
    tb.append(df)##combine all files
frame = pd.concat(tb, axis=0, ignore_index=True)

第三步:过滤掉 AC 米兰和国际米兰的所有比赛

根据数据框架,它有主队和客场队(见下图 1)。我们需要让 AC 米兰成为主队,国际米兰成为客场,反之亦然。

图 1 :车架头部(10)

首先,我试图找到 AC 米兰是主队,国际米兰是客队的比赛:

df1= frame[(frame['HomeTeam'] == 'Milan') & (frame['AwayTeam'] == 'Inter')]

然后,国际米兰是主队,AC 米兰是客场队:

df2 = frame[(frame['HomeTeam'] == 'Inter') & (frame['AwayTeam'] == 'Milan')]

要将这两个数据帧合并为一个数据帧:

ddff = [df2,df1]
result = pd.concat(ddff)

我们就要完成数据清理了!因为我只想知道数据的前几列,所以我省略了其余几列:

data = result.iloc[:, 0:7]

步骤 4:完成可视化数据集

为了使可视化更容易,我做了一些事情:1)添加 1997 年到 2020 年的比赛数据,因为这些数据在下载的文件中丢失了;2)获取比赛日期的“年份”;3)添加两列——一列为“冠军队”,另一列为每场比赛的“总目标”:

## add data from 1997 to 2020 - a bit messy method was used here:
new_row = {'Date': '15/10/17', 'HomeTeam':'Inter', 'AwayTeam':'Milan', 'FTHG':'3','FTAG':'2', 'FTR': 'H'} 
data = data.append(new_row, ignore_index = True)new_row = {'Date': '27/12/17', 'HomeTeam':'Milan', 'AwayTeam':'Inter', 'FTHG':'1','FTAG':'0', 'FTR': 'H'} 
data = data.append(new_row, ignore_index = True)new_row = {'Date': '04/04/18', 'HomeTeam':'Milan', 'AwayTeam':'Inter', 'FTHG':'0','FTAG':'0', 'FTR': 'D'} 
data = data.append(new_row, ignore_index = True)new_row = {'Date': '21/10/18', 'HomeTeam':'Inter', 'AwayTeam':'Milan', 'FTHG':'1','FTAG':'0', 'FTR': 'H'} 
data = data.append(new_row, ignore_index = True)new_row = {'Date': '17/03/19', 'HomeTeam':'Milan', 'AwayTeam':'Inter', 'FTHG':'2','FTAG':'3', 'FTR': 'A'} 
data = data.append(new_row, ignore_index = True)new_row = {'Date': '09/02/20', 'HomeTeam':'Inter', 'AwayTeam':'Milan', 'FTHG':'4','FTAG':'2', 'FTR': 'H'} 
data = data.append(new_row, ignore_index = True)new_row = {'Date': '18/10/20', 'HomeTeam':'Inter', 'AwayTeam':'Milan', 'FTHG':'1','FTAG':'2', 'FTR': 'A'} 
data = data.append(new_row, ignore_index = True)

为可视化准备色谱柱:

## Add the column - "Year" of each match
data['year'] = pd.DatetimeIndex(data['Date']).year
data = data.sort_values('year')## Add the column - "Winner" of each match
data['Winner'] = np.where(data['FTR'] == 'A', data['AwayTeam'], (np.where(data['FTR'] == 'H', data['HomeTeam'], 'Draw')))## Add the column - "TotalGoal" of each match
data["FTHG"] = pd.to_numeric(data["FTHG"])
data["FTAG"] = pd.to_numeric(data["FTAG"])
data['TotalGoal'] = data['FTHG'] + data['FTAG']

第五步:用 Plotly 可视化

在这里,我创建了两个图表:

气泡图:

显示“比赛日期”、“每场比赛的总进球数”和“比赛获胜者”之间关系的图表:

fig = px.scatter(data, x="year", y="TotalGoal",size="TotalGoal", color="Winner",
                 color_discrete_map={'Milan':'red',
                                 'Inter':'royalblue',
                                 'Draw':'lightgreen'},
                 hover_name="Winner", log_x=True, size_max=20)
fig.show()

图二:气泡图

饼图:

另一张图表是关于过去几年中获胜的比例。为了得到饼图,需要用 groupby 重新构造数据帧:

## Restructure the dataframe with groupby
counts = data['TotalGoal'].groupby(data['Winner']).count().reset_index(name="count")## Pie chart
fig1 = px.pie(counts, values ='count', names ='Winner', title='Milan Derby', color = 'Winner',
             color_discrete_map={'Milan':'red',
                                 'Inter':'royalblue',
                                 'Draw':'lightgreen'})
fig1.show()

图三:饼状图

思绪

通过看这两张图表,下面是对米兰德比的一些思考。

  1. 很明显,AC 米兰和国际米兰在赢得比赛方面没有太大的区别。国际米兰赢的比赛比 AC 米兰略多;
  2. AC 米兰在 2010 年之前的比赛中比国际米兰更有可能获胜,而国际米兰在 2010 年之后获得了更多的获胜机会;
  3. 当比赛的总进球数超过 4 个时,国际米兰似乎更有可能赢得比赛。

这些想法似乎与球队那些年的表现一致。我等不及要看下一场德比了!

使用 Python 和 Apple Health 分析您的健康状况

原文:https://towardsdatascience.com/analyse-your-health-with-python-and-apple-health-11c12894aae2?source=collection_archive---------6-----------------------

厌倦了用鸢尾花和海难学习数据科学?让我们试试你的健康数据。

Solen Feyissa 在 Unsplash 上拍摄的照片

眼下,描述手机对我们生活的影响感觉有些毫无意义。无论我们在哪里,我们形影不离的伙伴让我们打电话,写信息,浏览互联网,玩游戏等等。可能性的列表是无穷无尽的,并且每天都在增长。

另一个重要方面是,它们配备了各种硬件传感器(例如 GPS、加速度计、陀螺仪),结合软件,几乎可以跟踪我们生活的方方面面。此外,随着可穿戴设备的到来,他们的数据收集能力进一步扩展。

如果你是苹果用户,你大概知道苹果健康。它是 iOS 的一项功能,用于监控和组织与健康相关的数据。它整合了苹果生态系统和第三方设备和应用程序收集的数据。根据您的具体设置,它可以提供关于您的身体活动、身体测量、睡眠习惯、心率、听力、营养、血糖甚至月经周期的宝贵见解,仅举几个例子。虽然一些指标很简单,如步数,但其他指标更详细,如我们行走时的双支撑时间不对称的比率。

这些工具引发了隐私问题,因为它们利用并可能暴露敏感数据。即使用户同意,我们的记录有多安全?这些特征构成了自我意识的机会还是仅仅是另一种形式的虐待?我们如何利用它们进行科学研究?毫无疑问,这是一场引人入胜的辩论,但它超出了本文的范围。

在本文中,我们将下载并探索我们自己的健康记录。如果您正在使用其他人的,请负责任地行事,并确保在您继续之前得到他们的同意。从数据科学的角度来看,这些全面的数据集构成了研究和增加我们自我知识的黄金机会,也就是说,更好地了解我们的生活方式。如果你正在学习数据科学,还有另一个优势:这是来自你的实际数据。将你所学到的一切应用到真实数据中,并得出一个可以改善你自己生活的可行结论,这难道不是一件很棒的事情吗?不要误解我,那些流行的数据集(例如 Iris 、 Titanic )非常有教育意义,但它们并没有那么实用。相反,这些健康和生活日志数据源可以提供有趣的、激励性的和可操作的例子。值得给他们一试!

1.下载数据集

首先,我们正在下载数据集。它需要几个手动步骤:

  • 打开手机上的健康应用。
  • 触摸右上角的个人资料图片。
  • 触摸下一屏幕底部的导出所有健康数据
  • 您将看到几个选项来共享生成的 zip 文件。选择对你最方便的,比如给自己发邮件。
  • 在您的桌面上,解压缩附加的归档文件。

图片作者。有些区域是故意模糊的。

2.将 XML 处理成数据帧

从存档中的两个文件中,名为export.xml的文件包含我们需要的数据。只需几行代码和标准包,就可以很容易地将其改造成一个熊猫T1。不需要安装其他任何东西。所以,让我们打开一个 Jupyter 笔记本,运行这个:

上面的代码使用 xml 模块中的ElementTree解析 XML。文件结构非常简单,一系列带有一些属性的条目。首先,我们将 XML 转换成一个字典列表(每个条目对应一个属性)。其次,我们将它们转换成一个DataFrame,将列表映射到行,将字典映射到列。接下来,我们调整数据类型,这对于日期和度量尤其重要。最后,由于观察类型的标签相当大,我们通过仅保留标识符的尾部来缩短它们(例如 hkquantitytypeidentifierbodymasus被翻译成仅 BodyMass )。

完成了:我们有了一个整洁的DataFrame,里面有我们所有的长格式健康记录!要检查可用度量的范围,只需执行data.type.unique()来获得type列的不同值。这取决于你的情况,但通常你会得到诸如步数距离步行跑步或、飞行攀爬等标签。

3.透视和重新取样

为了方便地分析数据,最好切换到宽格式的表格。况且看到数据稀疏,也方便汇总成月。结果将是一个表,每月一行,度量以列表示。下面的示例代码只聚集了身体质量距离行走跑步。您需要的具体列取决于您的案例中可用的数据和您的特定研究问题。请注意,每个度量都需要自己的聚合策略。例如,我们应该将这段时间内的所有观察值相加,以计算每月的总步行距离。相反,为了计算平均重量,我们应该应用平均值(从 numpy 导入)而不是总和。

4.添加外部数据和合成变量

虽然我们可以单独使用 pivot 和 long 表完成许多事情,但是如果我们添加 Apple Health 外部的数据或创建合成变量,我们的分析会变得更加有趣:

如果变量不是通过直接测量获得的,则该变量是合成的。让我们来计算一下我体重的月差异(稍后会有更多的介绍)。作为外部数据,我包括三个虚拟变量,它们将标记我生活中的一些相关事件。在相关事件发生的月份,它们将被设置为 1,否则为零。例如, covid 表示我的国家第一次新冠肺炎封锁(当流动性显著降低时), phd 强调我的博士学位的持续时间,圣诞节强调寒假期间(即 12 月和 1 月)。因此,最终的表格如下所示:

2020 年的表格摘录。图片作者。

5.研究问题:什么因素影响我的体重?

现在到了有趣的部分,让我们把所有的部分组合在一起,并从数据中提取有价值的见解。作为解决问题的第一个方法,我们绘制了身体质量月时间序列:

图片作者。

这些年来,我的体重并没有保持不变。哪些因素可能会影响它?解释这些变化的简单数学模型如下:

图片作者。

等式的左侧是体重的每月变化(此后为增量)。右边是一个常数,一个因子的线性组合和一个误差项。哪些因素?在数据集中,我们有远程行走跑步和假人博士covid圣诞。让我们试试这些。

下图显示了体重月差异的时间序列,旁边是密度函数。

图片作者。

6.相关矩阵

相关矩阵是总结数据集中所有变量之间相关性的一种便捷方式。除了数字之外,我们还可以绘制一个热图,使其在视觉上更具吸引力。正相关的变量显示为蓝色,负相关的变量显示为红色。只需扫一眼就可以得出一些结论:

  • Delta 与步数、距离和 PhD 负相关。这些因素似乎降低了我的体重。前两个是因为体力活动,第三个最有可能是因为压力。然而,圣诞节似乎让我超重了。
  • 由于对移动性的相应限制,锁定会对距离和步数产生负面影响。
  • 步数和距离有很强的相关性。
  • 体重和体力活动呈正相关。尽管这似乎违反直觉,但实际上是有道理的:当我的体重高时,我会进行更多的身体活动来补偿和减肥。

图片作者。

7.配对图

另一种有效的表示是配对图。它将每个变量映射到双变量和单变量图网格中的列和行上。在这种情况下,对角线显示每个变量的密度,而上下三角形用散点图和一些核密度估计 (KDE)等高线描述变量之间的成对关系。让我们画出关系最密切的变量:

图片作者。

如果我们只关注第一行,δ是纵坐标,其他变量是横坐标。最左边的图是 Delta 的概率分布,我们之前已经展示过了。下面两个是 DeltaDistanceWalkingRunningchristmas 的关系。我们欣赏两个图表中清晰的斜率。

8.线性回归

情节是解决问题的很好的探索工具。然而,为了得出更有意义的结论,我们需要测量效果的强度和统计显著性。考虑到这个目标,我们正在计算一个普通最小二乘法 (OLS)回归:

图片作者。

结果包含了大量的图表,这些图表非常有助于更好地理解这个问题:

  • 决定系数,R 的平方,测量自变量预测的因变量的方差。越高越好。我们的 0.31 是合理的,但离最大值 1.0 还很远。随着解释变量数量的增加,调整后的版本解释了虚假结果。
  • 回归系数测量影响的数量和方向。例如,我在圣诞节期间每月增加约 0.911 公斤,或者如果我每天穿越 3 公里,我可能每月减少 1 公斤。
  • p 值回答了另一个有趣的问题:我们确定系数不为零吗?为了拒绝零假设,我们需要低于临界值的 p 值(T21)。在本例中,我们将其设置为 5%。因此,我们应该只考虑常量距离步行跑步圣诞节的值。
  • 95%的置信区间为每个系数提供了最可能的范围。

最后的话

如果你足够老,你肯定还记得电脑在处理能力和多功能性方面无法与今天的智能手机相提并论的时代。如今,这些设备伴随我们到任何地方,并记录我们的个人生活。虽然在这种情况下,隐私是一个合理的问题,但作为数据科学家,我们的职责是将可用数据转化为对个人、组织和整个社会有用的东西。在这个过程中,我们必须采取负责任的行动。

健康数据为了解一个人的生活提供了有价值的信息。在这篇文章中,我们学会了从手机中轻松检索数据,并(希望)得出一些有趣的结论。

可能性是无限的!另外,如果你是学生,这个教程可以让你在对你有意义的真实数据上练习技巧。极限是你的想象力。

期待您的评论,感谢您的阅读!

分析气候跟踪全球温室气体排放数据

原文:https://towardsdatascience.com/analysing-climate-trace-global-greenhouse-gas-emissions-data-part-1-fba426128e34?source=collection_archive---------20-----------------------

作者图片

使用 Python 的 Plotly 库的一系列交互式世界地图

随着至关重要的第 26 次联合国气候变化大会(COP26)的临近,来自各个领域的气候变化活动人士正在努力影响和施压将参加 2021 年 10 月 31 日至 11 月 12 日在格拉斯哥举行的气候谈判的政策制定者。

最引人注目和创新的举措之一来自排放跟踪联盟气候跟踪,该联盟最近发布了全球首个基于直接、独立观察的全球温室气体(GHG)排放综合核算,涵盖 2015 年至 2020 年期间。利用卫星技术、遥感、人工智能和机器学习的力量,该清单旨在提高 GHG 监测和报告的透明度,特别是在那些缺乏技术和资源来确保对排放数据进行合理核算的国家。

该清单可在 Climate Trace 网站上获得,提供了一个直观且用户友好的界面来可视化数据并按不同变量过滤信息。然而,除了条形图和折线图,我相信有地图来比较 GHG 在世界范围内的排放量也是很棒的。

这个职位(以及本系列即将上任的职位)有三重目的。首先,它旨在提高对当前 气候危机的认识。其次,它提供了一个分析迷人且改变游戏规则的气候痕量排放数据库的绝佳机会,从而使其更加可见和熟悉,以便其他研究人员、气候科学家和数据分析师可以使用它。最后,它为那些对使用 Python 进行数据分析和可视化感兴趣的人提供了一个编码教程。更准确地说,在本帖中,我们将关注如何使用强大的 Plotly Python 图形库制作世界地图。

这个项目的代码可以在我的 GitHub 库中找到。地图(两者都有。巴新和。html 格式)也可以在我的 GitHub 库和我的 Plotly 工作室账户中找到。请随意使用和分享:我们对气候危机、其原因和后果了解得越多,我们就越有准备去解决它。

注:根据 知识共享署名 4.0 国际许可(CC BY 4.0),排放数据已通过 Climate TRACE 提供。

免责声明:以下地图尺寸因嵌入略有变化。这种大小调整影响了标题、图例和源文本的位置。

数据

数据的主要来源是气候追踪排放数据库,你可以从气候追踪网站下载。此外,我还使用了来自世界银行的世界人口数据,因此我可以计算各国的人均排放量。

该清单涵盖 2015 年至 2020 年期间,提供了 250 个国家 10 个部门和 38 个分部门的 GHG 排放数据(以二氧化碳当量衡量)。下面你可以找到谁的数据看起来像:

作者图片

经过一些处理和一些预处理步骤后,我们可以将总量数据与排放数据合并:

结果如下:

作者图片

用 Plotly 创建世界地图

地图是理解分布和比较各国数据的绝佳视觉工具。 Plotly 的 Python 图形库提供了创建交互式、出版物质量的图形的工具,包括可以轻松嵌入网站的地图。关于如何在你的 Plotly Chart Studio 账户上上传 Plotly graphs 和在中型帖子上嵌入 Plotly graphs 的更多信息,请查看本教程。

本质上,创建 GHG 排放地图(以及一般意义上的地图),是一个子集化、过滤和分组操作的游戏。例如,我们可以绘制 2020 年按国家划分的 GHG 排放量地图,2017 年按国家划分的 GHG 人均排放量地图,以及计算 2015 年农业排放量的第三张地图。由于有许多选择,而不是写一段代码为每一个地图,我们可以创建函数,将创建一个特定的参数集的地图。

下图显示了 2020 年各个国家的 GHG 排放量:

作者图片

这张地图是三个以套娃方式工作的函数组合的结果(即我们只需调用一个函数,这个函数随后会调用另一个函数,依此类推)。在我们的例子中,我们必须调用函数 show_map (metric,year,map_format='img '),调用函数 df_metric (metric,year),调用函数 calculate_percentiles (df,metric)。

show_map() 主要处理可视化任务。它使用 Plotly 语法创建一个 choropleth map控制布局选项(地图框架、标题、悬停、图例和注释)美学属性(如颜色、字体和文本大小)配置选项(将文件保存在您的本地计算机或您的 Plotly Chart Studio 帐户中,以及 Plotly 按钮)。默认情况下,函数将文件保存在本地计算机的中。png 格式。PNG 文件是不允许交互的静态图像。要允许这个选项,我们只需将 map_format 参数改为【html】这样一个交互。将创建 htlm 映射,而不是在本地创建。

为了构建地图, show_map(metric,year,map_format='img') 依赖于由 df_metric(metric,year)创建的数据。根据我们想要计算的指标— GHG 排放量(【百万吨二氧化碳当量】)、人口数(【人口数】)或 GHG 人均排放量(【二氧化碳当量/人均排放量】 ) —以及所选年份,该函数将对数据框架执行不同的操作以选择正确的数据。最重要的任务之一是创建一个名为“range”的新列,它使用 pandas 函数 cut()对数据值进行分段和分类。此栏是用颜色区分国家的关键。我可以使用连续色标,我认为使用离散色标更有效,如地图图例所示。(有关这方面的更多示例,请查看世界银行数据网站上的地图可视化。)

但是如何分割数据,使地图上的颜色有意义呢?由于指标的价值和尺度不同(例如,GHG 的排放量是以百万吨二氧化碳当量来衡量的,而 GHG 的人均排放量是以每人多少吨二氧化碳当量来衡量的),我们需要摆弄数据,直到我们找到合理的分割值。这是通过函数 calculate_percentiles(df,metric)完成的。该函数返回两个列表:第一个是根据指标分割数据的百分比列表;第二个是将出现在地图图例中的标注列表。用于计算百分位数的值是在对每个指标中的数据分布进行了一些实验后选择的。

按部门绘制排放图

气候追踪数据中最酷的事情之一是,它提供了 GHG 按部门和子部门的排放分布。例如,“石油和天然气”部门由三个子部门组成:石油和天然气生产、炼油和固体燃料转化。在地图上标出这些信息也很有意义。我已经建立了第二组函数来创造奇迹: show_map_sector(sector,year,map_format='img')df_sector(sector,year)percentiles_sector (df,sector)。

函数的推理与上面解释的函数非常相似。唯一的特殊性是,对于每个部门,其分部门的排放信息可以在与每个国家相关的悬停框中找到。例如,您可以在下面找到 2020 年石油和天然气行业的世界排放地图。

作者图片

结论

我希望你喜欢这个教程。随意使用 Python 代码——即 show_map 函数——作为 Plotly 新世界地图可视化的模板。如前所述,不同指标和部门的地图可以在我的 GitHub 库以及我的 Plotly 工作室账户中找到。请注意,我只创建了最近一年(2020 年)的地图。如果您想创建前几年的地图,只需下载我的代码,安装所需的依赖项并更改 year 参数。

在本系列的后续文章中,我们将进一步挖掘气候跟踪数据库,提供新的数据分析和可视化,这可能有助于提高对我们这个时代最大挑战:气候变化的认识和理解。

分析与 SHAP 的互动

原文:https://towardsdatascience.com/analysing-interactions-with-shap-8c4a2bc11c2a?source=collection_archive---------2-----------------------

使用 SHAP Python 包来识别和可视化数据中的交互

来源:作者

SHAP 值用于解释模型做出的单个预测。它通过给出每个因素对最终预测的贡献来做到这一点。SHAP 相互作用值通过将贡献分解成它们的主效应和相互作用效应对此进行了扩展。我们可以用这些来突出和可视化数据中的交互。它也是了解模型如何做出预测的有用工具。

来源:作者

重点将放在应用 SHAP 方案和解释结果上。具体来说,我们首先解释什么是 SHAP 相互作用值,以及如何用它们来解释个人预测。然后,我们深入研究这些值的 3 种不同聚合,这有助于我们解释模型一般是如何进行预测的。这包括取所有相互作用值的绝对平均值,并使用 SHAP 汇总和相关图。我们会检查关键的代码片段,你可以在 GitHub 上找到完整的项目。

资料组

为了解释如何使用 SHAP 包,我们创建了一个包含 1000 个观测值的模拟数据集。在表 1 中,您可以看到该数据集中的要素。目标是使用剩余的 5 个特征来预测员工的年度奖金。我们设计了数据集,因此体验和程度之间以及业绩和销售之间存在互动。days_late 不与任何其他功能交互。你可以在 Kaggle 上找到这个数据集。

表 1:随机生成的数据集中的字段

本文假设您对数据交互有所了解。如果没有,下面的文章将是一个很好的阅读第一。在这里我们确切地解释什么是相互作用。使用与上面相同的数据集,我们还解释了可以用来分析它们的其他技术。这些可以是 SHAP 的一个很好的替代品。

包装

在下面的代码中,您可以看到我们将用来分析这些数据的包。在第 2 行到第 5 行,我们有一些用于管理和可视化数据的标准库。在第 7 行,我们导入 XGBoost,用于对目标变量建模。在第 9 行,我们导入 SHAP 包。在那之下,我们初始化允许你在一个笔记本里显示图表的包。确保你已经安装了所有这些。

系统模型化

要使用 SHAP 软件包,我们首先需要训练一个模型。在第 2–4 行,我们导入数据集并分配目标变量和特性。在第 7 行和第 8 行,我们定义并训练了 XGBoost 模型。为了简单起见,我们使用整个数据集来训练我们的模型。为了避免过度拟合,我们限制了模型中每棵树的最大深度为 3。

如果您将 SHAP 应用于现实世界的问题,您应该遵循最佳实践。具体来说,您应该确保您的模型在训练集和验证集上都表现良好。你的模型越好,你的结果就越可靠。作为对该模型的快速检查,我们在下面绘制了实际奖金与预测奖金的对比图。这个模型应该可以很好地展示 SHAP 一揽子计划。

图 1:实际奖金与预测奖金

解读 SHAP 互动价值观

现在我们有了模型,我们可以得到 SHAP 相互作用值。这些可以解释为类似于正常的 SHAP 值。如果你对解释这些不熟悉,下面的文章会很有帮助。这将使本文的其余部分更容易理解,因为所讨论的情节是相似的。

为了计算 SHAP 交互值,在第 2 行,我们通过将模型传递给 TreeExplainer 函数来定义一个 explainer。该函数用于解释系综树模型的输出。使用第 3 行的解释器,我们得到交互值。这将返回一个数组,【shap _ interaction】,它包含 X 特征矩阵中 1000 个观察值中每一个的记录。

为了理解的结构shap _ interaction我们可以使用下面的代码。第 2 行告诉我们数组的形状是(1000,5,5)。这意味着该阵列包含 1000 个 5x5 矩阵。我们将 5×5 矩阵称为贡献矩阵。它们包含了用于解释 1000 个预测的 SHAP 值。第 5 行给出了数据集中第一个雇员的贡献矩阵。我们可以在下面的图 2 中看到这个矩阵。

该矩阵告诉我们,与平均预测相比,每个因素对模型预测的贡献有多大。这是对标准 SHAP 值的类似解释,除了贡献被分解成主效应和交互效应。主要效应在对角线上给出。例如,该员工的经验水平使他们的预测奖金增加了 35.99 美元。相互作用效应在非对角线上给出。这些值减半,例如,performance.sales 交互将预测奖金减少了 8.76 美元(-$4.38 x 2)。

图 2:第一个员工的 SHAP 互动价值观

平均预测是所有 1000 名员工的平均预测奖金。如果您将贡献矩阵中的所有值相加,并添加平均预测值,您将获得该员工的模型实际预测值。在我们的例子中,平均预测奖金是 148.93 美元。矩阵中的所有值加起来是 59.98 美元。这为第一个雇员提供了 208.91 美元的预测奖金。您可以使用下面的代码确认这与模型的预测相同。

SHAP 交互图

查看单个贡献矩阵可以解释单个模型预测。但是如果我们想解释模型是如何做出一般预测的呢?为此,我们可以用几种不同的方式聚集贡献矩阵中的值。

绝对平均图

首先,我们将计算所有 1000 个矩阵中每个单元的绝对平均值。我们采用绝对值,因为我们不希望正负 SHAP 值相互抵消。因为相互作用的影响减半,我们也将非对角线乘以 2。然后我们将它显示为热图。您可以在下面的代码中看到这是如何实现的,输出如图 3 所示。

此图可用于突出重要的主效果和交互效果。例如,我们可以看到,平均主效应对于体验、程度、性能和销售都很大。这告诉我们,这些特点往往有很大的积极或消极的主要影响。换句话说,这些特征往往会对模型的预测产生重大影响。同样,我们可以看到,体验程度和绩效销售互动的影响是显著的。

图 3:主效应和交互效应的绝对平均值

汇总图

对于标准 SHAP 值,一个有用的图是蜂群图。这是 SHAP 一揽子计划中的一个情节。在下面的代码中,我们获得了 SHAP 值并显示了这个图。具体来说,这些是没有被分解成它们的主效应和交互效应的 SHAP 值。

关于如何解读这张图表,我们不会涉及太多细节。快速看一下图 4,您可以看到图表的颜色是由左轴给出的特性的特征值决定的。我们可以看到,学位、经验、绩效和销售的高价值都与更高的 SHAP 价值或更高的奖金相关联。

图 4: SHAP 蜂群图

有了 SHAP 相互作用值,我们可以通过使用下面代码中的摘要图来扩展这个图。输出如图 5 所示。这里主要效应的 SHAP 值在对角线上给出,非对角线给出了相互作用效应。对于这个情节,互动效果已经翻倍了。与蜂群图一样,颜色由 y 轴上的特征的特征值给出。

图 5: SHAP 汇总图

通过指出重要的主效应和交互效应,该图可以给出与绝对均值图相似的见解。具体来说,我们可以看到,在图 3 中,具有高 SHAP 值的细胞对应于具有高绝对平均值的相同细胞。摘要图通过可视化关系的性质提供了额外的洞察力。例如,我们可以看到,学位、经验、业绩和销售的主要影响都是积极的。

依赖图

在概要情节中有很多细节,即使有颜色,也很难解释交互作用的效果。我们可以使用依赖图来更好地理解交互的本质。下面,您可以看到用于为 experience.degree 交互创建依赖图的代码。

查看图 6 中的输出,我们可以看到,如果这个人有学位,那么随着经验的增加,experience.degree 交互效应也会增加。如果这个人没有学位,情况正好相反。我们应该记住,这只是相互作用的结果。应该根据经验和学位的主要影响来考虑这种关系。

图 6:体验度交互依赖图

图 7: SHAP 总结图(仅学位和经验)

回到我们的总结剧情,可以看到经验的主效应是正面的。所以假设一个有学位的人的经验增加了。主效应和交互效应将在同一个方向上起作用。这意味着随着经验的增加,他们的预期奖金也会增加。另一方面,如果一个人没有学位。那么主要的(积极的)和交互作用的(消极的)影响将在相反的方向上起作用。随着经验的增加,预测奖金可能增加、减少或保持稳定。

这与下面的散点图是一致的。这里我们绘制了原始数据值——没有 SHAP 值。我们可以看到,如果一个人有学位,那么他们的奖金往往会随着经验的增加而增加。如果他们没有学位,奖金在不同的经验水平上趋于稳定。我们还没有用 SHAP 值来展示,但稳定的奖金表明,当一名员工没有学位时,主效应和交互效应可能会完美地相互抵消。

图 8:体验度交互散点图

最后,在图 6 中,我们有业绩-销售互动的依赖图。这个情节可以用类似的方式来解释。我们应该记住,我们现在有一个更好的相互作用的两个连续变量,而像以前一样,我们有一个连续和分类变量。

图 9:绩效-销售互动依赖图

上面我们使用了 SHAP 相互作用值作为更多的探索性数据分析技术。也就是说,我们用它们来识别和可视化重要的相互作用。我们也可以使用这个包来帮助解释我们的模型。你可以用类似的方式使用它,除了我们的目标是理解我们的模型如何做出预测。我们将在下面的文章中详细解释为什么这很重要。

支持我成为我的 推荐会员 😃

https://conorosullyds.medium.com/membership

|Twitter|YouTube|时事通讯 —注册免费参加 Python SHAP 课程

图像来源

所有图片都是我自己的或从www.flaticon.com获得的。在后者的情况下,我拥有他们的保费计划中定义的“完全许可”。

参考

南伦德伯格, SHAP 蟒包 (2021) https://github.com/slundberg/shap

南 Lundberg,NHANES I Survival model . ipynb(2020)https://github . com/slund Berg/shap/blob/master/notebooks/tabular _ examples/tree _ based _ models/NHANES % 20I % 20 Survival % 20 model . ipynb

南伦德伯格和 s .李,解释模型预测的统一方法 (2017),https://arxiv.org/pdf/1705.07874.pdf

C.Molnar,可解释机器学习(2021)https://christophm . github . io/interaction-ml-book/html

用普罗特利分析 2020/21 赛季西甲联赛

原文:https://towardsdatascience.com/analysing-la-liga-2020-21-with-plotly-1f63c99073b4?source=collection_archive---------49-----------------------

用动画线形图描绘西甲比赛,用图表显示统计数据

"进攻为你赢得比赛,防守为你赢得冠军."

作为一个狂热的巴萨球迷,我不禁赞同弗格森爵士(前曼联主帅)的上述说法,尤其是在当前俱乐部足球的背景下。巴塞罗那足球俱乐部(FC Barcelona)曾在其黄金时代完全主宰国内联赛和欧洲足球。然而,俱乐部自 2015/16 赛季以来就没有打进过欧冠决赛。在上赛季输给劲敌皇家马德里之后,巴塞罗那在本赛季的倒数第二个比赛日输给了塞尔塔维戈,也被踢出了冠军争夺战。另一方面,马德里竞技队在去年夏天从巴塞罗那转会到马德里竞技队的首席射手路易斯·苏亚雷斯的激励下,获得了他们的第 11 个西甲冠军。

西甲联赛在很大程度上被认为是一场三足鼎立的比赛,尤其是在最近几年,因为在过去十年中,只有巴塞罗那、皇家马德里和马德里竞技赢得了联赛冠军或成为了联赛冠军的最大竞争者。在这篇文章中,我将使用一个动画情节的线图比赛和一个非常基本的仪表板来讨论这三个俱乐部在本赛季西甲的竞争和基本统计数据。代码和数据可以在这个 GitHub 资源库中获得。让我们开始吧。

西甲 2020/21 赛季动画剧情线路图

首先,我的目标是想象整个赛季前三名球队在西甲联赛中的表现。我首先导入三个必需的包,在本例中是 pandas、numpy 和 plotly.graph_objects。用于此目的的数据可在这个储存库中获得,这个储存库是我根据FcTables.com通过跟踪每个俱乐部每个比赛日的赢、输和平而创建的。dataframe 由每个比赛日之后西甲三支顶级球队的累计积分组成,如下图所示。

每个比赛日后包含累积积分的数据框(图片由作者提供)

plotly.graph_objects 包括显示图形的数据和布局元素。我从定义numOfFrames 开始,这相当于 dataframe 中的行数。我创建了一个名为initial_data 的散点图类型的轨迹,它表示数据帧的第一行中的数据。

为了获得动画折线图竞赛,在每个瞬时时间点捕获帧是一个先决条件,这样第一帧捕获第一行的数据,第二帧捕获第一和第二行的数据,依此类推。为此目的创建了嵌套 for 循环,使得frames 将每个current_frame 的实例附加到末尾。

通过传递用于数据的initial_data和用于布局的frames,我得到了一个描述联赛中前三名俱乐部每个比赛日总积分的动画线图,如下所示:

前三名俱乐部每个比赛日的积分(图片由作者提供)

分析

正如上面的 gif 图片所示,巴塞罗那在赛季开始的前十场比赛中表现不佳。这是他们这么多赛季以来最糟糕的开局之一,俱乐部在前八场比赛中仅积 11 分,在联赛中排名第 13 位。相比之下,马竞的开局要好得多。到 2021 年 1 月赛季中期,马竞在联赛中稳步上升,分别与皇家马德里和巴塞罗那拉开了 10 分和 13 分的差距。

前十场比赛后,巴塞罗那加快了速度,连续几场连胜,甚至在某些点上超过了皇家马德里,并缩小了与联赛领头羊的差距。另一方面,马德里竞技在赛季中期后下降了几分,并将领先优势从超过 11 分缩小到只有几分。在赛季的最后一个季度,巴塞罗那和皇家马德里都丢掉了几个关键分,甚至错过了登上榜首的机会。在本赛季的最后一个比赛日,三家俱乐部都赢得了比赛,然而,马德里竞技成为了西甲 2020/21 赛季的最终赢家。

Plotly 仪表盘

在本节中,我打算创建一个非常基本的交互式仪表盘,以可视化西甲 2020/21 的统计数据并进行讨论。我为此使用的包与上面的线图比赛使用的包是一样的。用于此目的的数据可在此处获得,可从fbref.com公开获得。数据帧如下所示:

西甲 2020/21 积分表(图片由作者提供)

接下来,我初始化该图,并创建一个我希望在仪表板中显示的指标的字典。在我的字典里,这些键代表着分数、进球、失球、净胜球、获胜的比赛、平局的比赛和失败的比赛。该字典的每个键都链接到原始数据集的相应子集。

#create a figure from the graph objects (not plotly express) library
fig=go.Figure()#Create dictionary for ease of access
df_dict={"points":df[["Squad","Pts"]],
        "goal_difference":df[["Squad","GD"]],
        "goals_scored":df[["Squad","GF"]],
        "goals_conceded":df[["Squad","GA"]],
        "matches_won":df[["Squad","W"]],
        "matches_drawn":df[["Squad","D"]],
        "matches_lost":df[["Squad","L"]]}

在这一步,我需要为下拉菜单创建一个按钮列表。为此,我初始化了一个名为dropdowns 的空列表和一个计数器i。使用 for 循环,我为每个指示器创建一个名为dropdown 的按钮对象。该按钮还包含一个名为args的布尔值(真/假)列表,它告诉根据真值显示哪个轨迹。

所有的按钮对象都被追加到dropdowns列表中。如下图所示,对于第一个字典,只有列表中的第一项在更新时可见。对于第二个字典,它是列表中可见的第二个项目,依此类推。

下拉列表 由每个指标组成的列表作为标签,“更新”作为方法,True/False 作为可见参数。(图片由作者提供)

最后,为了更新绘图的布局,我指定了(x,y)坐标,我想要的dropdowns按钮的位置,以及我想要菜单弹出的方向。

我得到了一个基本的交互式仪表板,如下所示。

带有西甲 2020/21 统计数据的仪表板

分析

在西甲 2020/21 赛季总共 38 场比赛之后,马竞以 86 分的成绩成为冠军。皇家马德里以 84 分接近第二,巴塞罗那以 79 分排名第三。排名前三的俱乐部分别赢得了 26 场、25 场和 24 场比赛。巴塞罗那以 85 个进球成为联赛中进球最多的球队,冠军和亚军各进 67 个球。然而,巴塞罗那也是三支球队中防守最差的,在同样多的比赛中丢了 38 个球。虽然巴塞罗那在三个俱乐部中净胜球最多,但输掉七场比赛和七场平局对俱乐部来说是非常昂贵的。

结论

在这篇文章中,一个简单的西甲比赛和基本统计数据的分析是在一个动画线图比赛和使用 Plotly 的仪表板的帮助下进行的。除了对数据有一个整体的了解之外,Plotly 的交互功能对于从图中获得准确的信息非常有用。交互式功能、地图、动画等。可以通过其开源图形库访问。

用 R 分析李氏对策

原文:https://towardsdatascience.com/analysing-lichess-games-with-r-c4f8b0bc512c?source=collection_archive---------20-----------------------

使用 ANOVA 和 Bootstrapping 揭示游戏洞察力

来源:图片来自 Pixabay 的 Devanath

国际象棋历史悠久,可以追溯到 1500 年前。然而,由于在线游戏的激增,这款游戏直到最近才成为数据分析的宝库。

玩家经常会有很多问题,比如随着时间的推移,一个人的评级可以提高到什么程度,什么样的开局与胜利最相关,等等。

然而,一个经常被争论的问题是,在任何特定的游戏中,白棋是否由于先走而比黑棋有优势。

也就是说,这个问题的答案并不明确,因为在任何特定游戏中的表现都取决于棋手的能力。一个 Elo 评分为 900 的玩家下白棋将很难击败一个 Elo 评分为 2000 的玩家下黑棋——即使前者有先发优势。

初步分析

为了获得关于这个问题的更多见解,我决定分析来自 database.lichess.org的数据,该公司根据知识共享 CC0 许可证提供其数据。

具体来说,我决定从 2013 年 2 月的数据库中抽取 650 个不同的样本(游戏),以更详细地分析每个游戏的结果和评分变化。

在所玩的一系列游戏中,Elo 评分在白人和黑人玩家中的分布或多或少遵循了我们倾向于在整体评分中看到的正态分布曲线。

来源:RStudio 输出

在这 650 场比赛中,我们看到白棋赢的比输的多,但只是很少:

资料来源:作者的计算

然而,更有趣的是每场比赛后玩家评分的波动。例如,如果输了一场比赛,输的玩家可能会失去 10 分,而赢的玩家可能会得到 15 分,等等。

一般来说,两个玩家之间的收视率差距越大,收视率变化就越深刻。例如,如果排名 1200 的玩家赢了排名 2000 的玩家,则随后的评级变化将比该玩家与类似级别的人比赛时高得多。

来源:RStudio 输出

从本次分析中使用的 650 个游戏样本中,我们可以看到,我们获得了在特定游戏中玩白棋和黑棋的玩家的总体评级,以及每个玩家的评级波动,这取决于他们在特定游戏中是赢是输。

查看一些收视率波动的汇总统计数据,会发现一些非常有趣的事情:

资料来源:作者的计算

在这 650 场比赛中,白人的平均收视率变化明显低于黑人。平均而言,白人每场比赛的收视率下降了 3.24,而黑人每场比赛的收视率上升了 0.55。

方差分析和自举

让我们更详细地探讨这一点。

首先,进行 ANOVA 测试,以确定玩白色游戏的人和玩黑色游戏的人之间的评分变化的均值差异是否显著。

>>> anova <- aov(df$blackratingdiff ~ df$whiteratingdiff)
>>> summary(anova) Df Sum Sq Mean Sq F value  Pr(>F)    
df$whiteratingdiff   1  77223   77223   65.99 2.3e-15 ***
Residuals          648 758311    1170                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

根据 ANOVA 检验,平均值的差异具有统计学意义。

假设我们的样本量是 650,我们假设这个样本代表了象棋游戏的总体。利用这一假设,我们希望使用 bootstrapping 生成评级波动的抽样分布,即带有替换的随机抽样。在这种情况下,替换意味着可以从样本中不止一次地选择一个观察值。

具体来说,我们将对 30,000 个 bootstraps 进行重新采样,以检查随着样本的增加,95%的置信区间会是什么样子。例如,bootstrap 样本将显示一个评级变化分布,我们可以 95%确信它包含总体均值。

这是针对白色和黑色评级波动而进行的。

使用随机抽样替换两组间的等级变化,生成了白色等级(称为 x )和黑色等级(称为 y )的样本。

x<-sample(df$whiteratingdiff, 650, replace = TRUE, prob = NULL)
xy<-sample(df$blackratingdiff, 650, replace = TRUE, prob = NULL)
y=

使用引导库,可以生成 30,000 个引导。

library(boot)boot_mean <- function(original_vector, resample_vector) {
  mean(original_vector[resample_vector])
}# R is number of replications
mean_results <- boot(x, boot_mean, R = 30000)
mean_results

白色等级分布

以下是为白色生成的自举置信区间。

BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 30000 bootstrap replicatesCALL : 
boot.ci(boot.out = mean_results)Intervals : 
Level      Normal              Basic         
95%   (-7.674, -0.569 )   (-7.445, -0.346 )Level     Percentile            BCa          
95%   (-7.875, -0.777 )   (-8.523, -1.157 )  
Calculations and Intervals on Original Scale

95%置信区间表示总体均值位于 -7.647-0.569 之间。这是分布的图示。

来源:RStudio 输出

黑色评级分布

以下是为 black 生成的 bootstrap 置信区间。

BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 30000 bootstrap replicatesCALL : 
boot.ci(boot.out = mean_results_2)Intervals : 
Level      Normal              Basic         
95%   (-2.3838,  3.4096 )   (-2.3830,  3.3846 )Level     Percentile            BCa          
95%   (-2.3354,  3.4323 )   (-2.2885,  3.4720 )  
Calculations and Intervals on Original Scale

95%的置信区间表示总体平均值位于 -2.383.4 之间。这是分布的图示。

来源:RStudio 输出

bootstrap 样本生成的分布非常有趣。平均而言,那些在任何特定游戏中扮演白人的人可能会看到他们的评分平均下降,而那些扮演黑人的人则会看到平均上升。

当然,我们必须注意这样一个事实,即平均值受到分布两端的极端评级变化的影响。当我们根据初步分析分析评分变化的汇总统计数据时,我们发现,虽然白人评分的平均变化为负,黑人评分的平均变化为正,但评分的中值变化却显示出相反的情况。

那么,我们能从这些发现中得出什么结论呢?如果假设白棋有先发优势,是否可以推断出能和黑棋一起赢的玩家(特别是在高等级游戏中)总体上更强?

从目前为止的数据来看,这并不一定是结论性的,这将保证一项单独的研究,即是否持续拥有较高黑棋胜率的玩家比拥有较高白棋胜率的玩家表现出更高的评级。

限制

虽然上述发现是有趣的,但当以这种方式分析国际象棋评级时,当然存在局限性。

首先,bootstrapping 技术假设选择的 650 个样本代表总体。虽然 650 是一个很大的样本量,但与历史上大量的国际象棋比赛相比,这只是沧海一粟。

虽然 bootstrap 是推断抽样分布特征的一种非常有用的工具——拥有人们可能认为的大样本量并不一定万无一失,如果收集的数据存在任何偏差,那么 bootstrap 抽样的结果也会如此。

此外,值得记住的是,在这个特定的数据集中,有许多一个玩家用两种颜色玩多种游戏的例子。如果一个球员特别有天赋,并且赢了所有他们穿黑白球衣的比赛,那么这更多的是一个强大球员的标志,而不是他们穿的颜色。

结论

希望你喜欢这篇文章!最近我又回到了国际象棋,我想这可能是一个利用统计分析收集更多关于游戏的见解的好机会。

这里有棋手希望提供任何评论或反馈吗?如果你对我的发现或如何改进分析有任何建议,我很乐意听到你的意见。

概括地说,本文涵盖了:

  • 如何用 R 来分析博弈
  • 方差分析在确定样本均值差异是否显著中的意义
  • 自举在估计统计量的抽样分布中的作用

非常感谢您的宝贵时间,再次感谢您的任何问题或意见。

参考

  • cran . r . project . org:Package ' boot '
  • 【lichess.org 开放数据库

免责声明:本文是在“原样”的基础上编写的,没有任何担保。它旨在提供数据科学概念的概述,不应被解释为专业建议。本文中的发现和解释是作者的发现和解释,不被本文中提到的任何第三方认可或隶属于任何第三方。作者与本文提及的任何第三方无任何关系。

利用在线评论评估文化旅游的质量

原文:https://towardsdatascience.com/analysing-online-reviews-for-evaluating-the-quality-of-cultural-tourism-services-2c9004d12123?source=collection_archive---------23-----------------------

思想与理论,社交媒体和网络评论能否超越一般的情绪?

意大利博物馆的经历

由米歇尔·比特托在 Unsplash 上拍摄的照片

在文化旅游领域,人们对采用数据驱动的方法越来越感兴趣,这些方法旨在通过在线评论衡量服务质量。在线评论长期以来一直是旅游领域数据分析的宝贵来源,但这些数据源主要是根据评论平台提供的数字评级进行研究的。

自顶向下与自底向上数据驱动的质量评估

在最近的一篇文章中,我们探讨了社交媒体和在线评论平台是否可以成为量化评估文化场所(如博物馆、剧院等)服务质量的良好来源。本文应用在线评论的自动分析,通过比较两种不同的自动分析方法来评估哪一种更适合评估质量维度。该分析涵盖了用户对意大利前 100 家博物馆的评论。

具体来说,我们比较两种方法:

  • 基于监督分类的“自上而下”方法,监督分类基于国家一级政策制定者指南所定义的战略选择;还有
  • 一种“自下而上”的方法,基于评论者在线词汇的无监督主题模型

我们比较了由此产生的博物馆质量维度,表明与通过“自上而下”方法获得的结果相比,“自下而上”方法揭示了额外的质量维度。

“自上而下”的战略研究和“自下而上”的数据驱动方法的结果不一致,凸显了数据科学如何为文化旅游的决策做出重要贡献。

关于质量维度的问题

该研究解决了以下三个问题:

  • 从战略的、集中的角度来看,哪些博物馆质量维度是按照“自上而下”的方法确定的?
  • 哪些博物馆质量维度是根据在线评论中“自下而上”的数据驱动方法确定的?
  • 这两种方法中的质量维度有什么不同?

在“自上而下”的方法中,由决策者(即国家一级的政策制定者)定义一组预定义的维度,我们使用基于关键字的分类器来分析在线评论文本中的预期维度。

在“自下而上”的方法中,潜在的质量维度已经通过依靠无监督的主题分析从游客体验的文本描述中直接导出,而没有强加一组预定义的质量维度。

决策者选择的质量维度可能与博物馆参观者感知的质量维度非常不同。

照片由塞巴斯蒂安·皮克勒在 Unsplash 上拍摄

数据集准备和探索

在线评论的数据是从意大利文化遗产、活动和旅游部确定的前 100 家意大利公共博物馆的猫途鹰网页上收集的。一旦收集,在线评论通过语言检测阶段得到丰富。最后,这两种分析方法都应用于 14,250 篇意大利评论的同一数据集。

2019 年 100 家意大利博物馆的评论和评级[图片由作者提供]

自上而下的方法

自上而下的方法是指决策者根据主观选择对要考虑的服务/产品的质量进行衡量。

在我们的实证背景下,决策者由政策制定者“意大利文化遗产和旅游部”代表,该部在 2018 年推出了一套公共博物馆的质量标准。基于该指南和对政策制定者的采访,我们确定了遵循“自上而下”观点的五个质量维度:票务和欢迎、空间、舒适度、活动、沟通。这些维度中的每一个都被认为是用户评论分类问题中的一类。自上而下的方法允许我们将每个评论标记为对这 5 个维度之一的描述。

分类已经被实现为机器学习分类问题和基于关键字的标记(即,每个维度与预期代表该维度的一组关键字相关联)。特别是,我们将基于关键字的分类器与来自 Transformers (BERT) 语言模型的双向编码器表示进行了比较。通过人工标记的 1,000 条评论来检查性能。基于关键词的方法在五类( 表 2 )中获得了 80%的平均准确率和 50%的召回率,而 BERT 方法获得了 88.2%的准确率和 58%的召回率。这种方法的缺点是数据在类间高度不平衡。

应用“自上而下”方法识别在线评论中博物馆质量维度的结果示例(多级软分类)。[图片由作者提供]

自下而上的方法

“自下而上”的方法利用在线评论,而没有关于访问维度的预定义预期;相反,它是基于直接从评论者的话语中获得体验的潜在维度,而没有任何预先定义的期望。

从分析的角度来看,“自下而上”的方法是通过无监督的主题建模方法实施的,即 LDA(潜在狄利克雷分配),在多达 30 个主题的范围内实施和调整。我们选择的最好的“自下而上”模型,确定了评论文本中的 13 个潜在维度。

为了获得更好的可解释性,我们将讨论的潜在主题手动分组为博物馆质量的三个主要“自下而上”的维度,我们将其解释为博物馆文化遗产、个人体验博物馆服务。

应用“自下而上”方法的结果示例。[图片由作者提供]

结果和比较

至于详细的结果,我想让读者阅读全文,这里我总结一下主要的发现。

游客的大部分注意力不是集中在服务上,而是博物馆的实际内容质量。

很大一部分评论内容无法归类到服务类别中。[图片由作者提供]

  • “自上而下”的方法(基于政策制定者发布的标准中定义的一组关键字)导致 63%的在线评论不符合任何预定义的质量维度;
  • “自下而上”的数据驱动方法通过使用评论者自己的话搜索感兴趣的方面来克服这一限制,甚至不知道有多少或哪些可能是博物馆的质量维度;
  • 特别是,当分析标记为其他方面的评论时,“自下而上”的分析以 21%的平均概率识别出博物馆服务。这意味着决策者也能够通过“自下而上”的方法发现与服务质量相关的其他方面;
  • 基于主题分析,我们看到博物馆评论更多地讨论博物馆的文化遗产方面(46%的平均概率)和个人经历(31%的平均概率),而不是博物馆提供的服务(23%的平均概率);
  • 这意味着游客的大部分注意力不是集中在服务上,而是博物馆的实际内容质量。

“自下而上”的博物馆质量维度在通过“自上而下”方法分类为“其他方面”的评论中的分布。[图片由作者提供]

TL;速度三角形定位法(dead reckoning)

在本研究的各种定量发现中,我认为最重要的一点是,决策者认为是质量维度的方面可能与博物馆游客认为是质量维度的方面有很大不同:在博物馆的特定环境中使用“自上而下”的方法,大多数评论(63%)与决策者定义的博物馆服务质量维度无关,因为博物馆游客不仅仅看重博物馆服务的质量维度(23%),而是更重视文化遗产(46%)和个人体验(31%)。

你可以通过阅读在线发表的开放获取的完整文章找到更多关于这个分析的信息。该论文的完整参考文献是:

阿戈斯蒂诺博士;布朗比拉,m。帕瓦内托;丽娃,p。在线评论对文化旅游产品质量评估的贡献:意大利博物馆的经验。持续性 202113 ,13340。https://doi.org/10.3390/su132313340

欧洲五大国内联赛传球分析

原文:https://towardsdatascience.com/analysing-passing-in-the-top-five-european-domestic-leagues-907f18231a20?source=collection_archive---------21-----------------------

使用 worldfootballR 软件包分析欧洲五大国内足球联赛中不同的传球行为

照片由埃德加·恰帕罗在 Unsplash 拍摄

足球经常被称为“美丽的运动”,因为不同国家之间错综复杂的比赛风格而变得更加美丽。

这篇文章旨在开始探索欧洲五大国内联赛比赛风格的一些差异。作为参考,当我们提到前五名时,我们指的是以下国内联赛:

  • 足球-德甲(德国)
  • 西甲(西班牙)
  • 法甲联赛(法国)
  • 英超联赛(英格兰)
  • 意甲(意大利)

具体来说,这篇文章将集中在传球上,并分析这些联盟中的球队如何在球场上运球是否有任何差异。

这一块的数据来自 fbref ,来自worldfootballR R 包。这个包目前可以从 GitHub 安装,这里的库是。

尝试和完成传球

首先,我们将注意力转向每 90 分钟足球比赛中传球次数最多的联赛。

除了意甲在 2017-18 赛季的传球尝试次数最高之外,德甲在传球尝试次数方面占据了最高地位,本赛季的传球尝试次数最高(514 次)。

法甲球队继续增加传球尝试,本赛季首次超过了 EPL 和意甲。有趣的是,在 2017–18 赛季,英甲和西甲同样是传球率最低的联赛,在短短的三年时间里,各自的联赛在传球尝试上出现了分化。

进一步深入分析联赛赛季中的各个球队,可以看出,尽管德甲和 EPL 的传球率最高,但它们的可变性也最高,每个联赛中传球率最高和最低的球队之间的差异最大(尽管西甲的可变性最大)。

完成率

尝试传球无疑对比赛很重要,但有人会说完成传球更重要。

下面的方框图显示,总的来说,每个联赛的球队在过去四年中都增加了传球完成率(尽管德甲有些停滞)。

意甲球队一直比其他联赛的球队有更高的传球准确性,而西甲则是所有联赛中完成率变化最大的球队——毫无疑问,这是由马德里队和巴萨以及联赛其他球队之间的巨大质量差异所驱动的。

为什么这很重要?

从下面可以看出,在一个赛季中尝试更多传球的球队往往会积累更多的联赛积分,变量之间有相当强的正相关性。以下数据不包括当季。

这对于 EPL 相关性(0.829)、德甲(0.805)和意甲(0.796)来说更是如此,而对于西甲和法甲来说,这种相关性并不那么强。

通行证往哪个方向走?

所以,我们已经看到了不同联盟之间在将球传给队友的频率和成功程度上存在一些差异。当他们传球时,球的行进方向是怎样的?

为此,我们可以查看已完成传球的渐进距离(以码为单位),并将其与所有已完成传球的总码数进行比较。fbref 将累进码定义为:

完成的传球朝向对方球门的总距离,以码为单位。注意:远离对手球门的传球被算作零码

得出的数字表明每完成一码传球,球前进了多少码。一个较高的数字表示一个队更直接地移动球,而一个较低的数字表示一个队更大比例的完成传球码不像对手的球门那样直接。

联赛传球不那么直接?

联赛已经逐渐远离更直接的传球路线,EPL 领先(每完成总码数 0.319 个累进码),而西甲最不直接,每完成总码数 0.339 个累进码。

就像联赛积分和传球尝试之间的相关性一样,在直接性和联赛积分之间似乎也有关系,然而这种关系是负面的,这意味着传球不太直接的球队也往往在赛季末获得更多的联赛积分。

此外,这种关系并不是所有的联盟都如此。这种关系在 EPL(相关系数为-0.711)和意甲(-0.706)中相当强,而在西甲中最弱(-0.402)。

我们也可以看看那些直接传球最多和最少的单个球队赛季。

下面列出了过去四个赛季中最不直接的 20 支球队,榜首由 EPL 俱乐部占据,特别是曼城,他们占据了前六名中的四个席位。

有趣的是,这份名单上的队伍似乎比排名靠后的队伍更接近榜首,这加强了我们上面的相关性。

同样,我们也可以看看最近四个赛季最直接传球的 20 支球队。

这些俱乐部的最终排名看起来更接近他们的积分榜底部(西甲 2018-19 赛季的赫塔菲和德甲 2018-19 赛季的莱比锡是明显的例外)。

卡迪夫城唯一的英超赛季是最直接的传球赛季,每完成传球码数 0.464 递进码。

虽然欧洲五大国内联赛之间的传球活动没有太大的差异,但仍然有一些差异,看看他们的联赛在未来几年如何演变将是有趣的。

一如既往,任何反馈或意见都将在评论区得到重视,或者随时在 Twitter@ jaseziv上联系。

这个完整的帖子最初出现在 dontblamethedata.com。这篇文章的代码可以在这里找到。

用 PyMC3 分析后验预测分布

原文:https://towardsdatascience.com/analysing-posterior-predictive-distributions-with-pymc3-5b6544398181?source=collection_archive---------20-----------------------

实践教程

使用 PyMC3 模拟后验分布

来源:图片来自 Pixabay

贝叶斯分析的主要目的是在给定不确定性的情况下对数据进行建模。

由于人们无法获得关于一个群体的所有数据来确定其精确的分布,因此经常会做出相同的假设。

例如,我可能会对某个国家人口的平均身高做一个假设。这是一个先验分布,或者是一个建立在先验信念基础上的分布,在此之前,我们先来看看可以证明或否定这个信念的数据。

在分析一组新数据(似然函数)时,可以将先验信念和似然函数结合起来形成后验分布。

来源:图片由作者创建

让我们看看如何使用 PyMC3 来模拟这样的分布。

用 PyMC3 分析身体质量指数数据

在本例中, Pima Indians 糖尿病数据集用于模拟大量患者(其中一些是糖尿病患者,一些不是)的体重指数数据。

在查看数据之前,需要建立一个关于该数据的均值和标准差的先验信念。鉴于数据集中相当多的患者是糖尿病患者,那么人们可以形成一种先验信念,即平均身体质量指数高于平均水平。

螺母(不掉头取样器)

在这方面,我们先假设平均身体质量指数为 30 ,相对较小的标准偏差为 2,表明我们不希望在个别情况下偏离平均值太多。

mu_prior=30
sigma_prior=2with pm.Model() as model:
    mu = pm.Normal("mu", mu=mu_prior, sigma=sigma_prior)
    sd = pm.HalfNormal("sd", sigma=sigma_prior)
    obs = pm.Normal("obs", mu=mu, sigma=sd, observed=data)
    idata = pm.sample(1000, tune=1500, return_inferencedata=True)

使用 3.1 版本。采样模板来自 PyMC3 通用 API 快速入门手册,NUTS(不掉头)采样器用于从每个链的后部抽取 1000 个样本,然后允许在额外的 1500 次迭代中进行重新调整。注意,在生成后验分布时,除了先验均值和标准差之外,模型还考虑了观察数据(观察=数据)

NUTS 是蒙特卡罗马尔可夫链(MCMC) 算法的一种形式,它绕过随机游走行为,允许更快地收敛到目标分布。这不仅具有速度优势,而且允许拟合复杂的模型,而不必使用关于这些拟合方法的理论的专业知识。

解释

使用 arviz,下面是生成的后验图:

来源:Jupyter 笔记本输出

还提供了分布的统计摘要:

来源:Jupyter 笔记本输出

请注意, 31.949 的平均值略高于之前的估计,而标准偏差在 7.823 处明显更高。

考虑到这些数据,事后看来,标准差高于最初的预期是有道理的。

毕竟,数据集中的许多患者都不是糖尿病患者。此外,尽管人们可能认为身体质量指数和糖尿病之间存在正相关,但这是基于先前的信念——如果不查看数据,我们没有确凿的证据证明这一点。

考虑到更新的平均值和标准偏差,下面是更新的后验分布:

来源:Jupyter 笔记本输出

我们可以看到,离差高于最初的预期。也就是说,如果数据本身并不总是十分准确呢?例如,没有人的身体质量指数可以为 0,但由于某种未知的原因,数据中存在许多 0 身体质量指数值。

然而,先验值的说明——以及数据中的大多数其他值——表明这种观察是极不可能的。在这方面,后验预测分布显著下降到 20 以下(数据中观察到的最低身体质量指数值为 18.2)。

重温先前的信念

当我们第一次形成对身体质量指数的先验信念时,估计的平均值与实际值相差不远。

然而,如果我们先前的信念完全偏离了目标呢?假设我们估计平均身体质量指数为 50,标准差为 2?

生成的后验分布如下:

来源:Jupyter 笔记本输出

即使存在不准确的先验信念,采样器也可以认识到这完全偏离了相对于实际观察到的数据的标记,并且相应地更新分布。

在新数据采用不同于先前模式的分布的情况下,这也非常有用。例如,一个公司的经理可能会根据经验假设某一年的产品销售倾向于显示某一平均值和标准偏差,但随后的数据与前几年的数据不同。在这方面,后验分布允许更新管理者的先前信念,以反映正在观察的新数据。

结论

后验分布允许在生成这种分布时通过考虑新的证据(或数据)来更新先前的信念。

在本例中,您已经学习了:

  • 先验分布和后验分布之间的差异
  • 如何用 PyMC3 模拟后验分布
  • 如何用阿尔维兹解读后验情节
  • 先验信念和似然函数在生成后验分布中的作用

非常感谢您的时间,任何问题或反馈都非常欢迎。你也可以在 michael-grogan.com 找到更多我的数据科学内容。

免责声明:本文是在“原样”的基础上编写的,没有担保。它旨在提供数据科学概念的概述,不应被解释为专业建议。本文中的发现和解释是作者的发现和解释,不被本文中提到的任何第三方认可或隶属于任何第三方。

参考

  • 盖尔曼和霍夫曼(2011)。不掉头采样器:在哈密尔顿蒙特卡罗中自适应地设置路径长度
  • Kaggle:皮马印第安人糖尿病数据库
  • PyMC3:通用 API 快速入门

用 R 分析幂律分布

原文:https://towardsdatascience.com/analysing-power-law-distributions-with-r-4312c7b4261b?source=collection_archive---------21-----------------------

用幂律检验幂律假设

资料来源:RStudio

幂律分布(如帕累托分布)描述了支配我们周围许多现象的 80/20 法则。

例如:

  • 一家公司 80%的销售额通常来自 20%的客户
  • 计算机 80%的存储空间通常被 20%的文件占用
  • 一个国家 80%的财富掌握在 20%的人手中

这些只是几个例子。虽然许多人认为大多数数据集倾向于遵循正态分布,但幂律分布往往比我们意识到的要普遍得多。在分析数据试图捕捉生产率差异的分布时,情况尤其如此。

也就是说,因为不可能获取所有的数据,比如销售数据,所以我们最终必须根据我们所拥有的数据生成一个概率分布。

在这点上,贝叶斯分析试图将先验分布(或研究者对分布形状的先验假设)与似然函数(代表观察到的样本数据的概率密度)相结合,以最终生成后验分布

来源:图片由作者创建

因此,贝叶斯分析的目的最终是用数据更新我们的先验信念。

例如,当谈到财富、销售和存储空间时,我做了声明来证明我的先验信念,即这些现象遵循幂律分布。

如果我们想从经验上证明事实是否如此呢?

幂律简介

科林·吉莱斯皮的幂律软件包在更详细地分析离散和连续幂律分布时非常有用。

例如,我决定使用美国人口普查局的销售数据-特别是 2019 年年度零售贸易调查-来确定不同零售行业的销售是否也遵循幂律分布-即只有少数几个行业占 2019 年记录的大部分销售?

当导航到名为销售(1992–2019)的数据集时,您将会看到,每个行业都分为不同零售公司的子组,如汽车经销商、家具店、服装店、等。

从最高到最低排列子组销售额时,我们可以看到存在一个广泛的幂律形状:

来源:RStudio 输出

然而,我们不能确定是否是这种情况,我们将使用上述软件包对幂律分布的存在进行经验测试。

离散分布与连续分布

当使用幂律包时,首先要决定的是数据是否遵循一个离散连续分布。

离散分布的值是特定的和有限的。例如,假设有人希望测量参加体育比赛的人数。明明一个人 0.5 都不能参加!因此,这种分布将是离散的。

但是,在销售数据的情况下,数量可能是连续的。例如,虽然此实例中的销售数据四舍五入到最接近的美元,但从技术上讲,总销售额可能是 100,000.50 美元。此外,考虑到我们正在处理该数据集中的大量数据,分布被建模为连续

模拟连续分布

首先,估计分布的下限(xmin ):

> sales<-sales$data
> library("poweRlaw")
> m_pl = conpl$new(sales)
> est = estimate_xmin(m_pl)
xmin search space truncated at 1e+05
        You have three options
                  1\. Increase xmax in estimate_xmins
                  2\. Specify xmins explicitly
                  3\. Ignore and hope for the best (which may be OK)
> est
$gof
[1] 0$xmin
[1] 96940$pars
[1] 1.832684$ntail
[1] 16$distance
[1] "ks"attr(,"class")
[1] "estimate_xmin"
> m_pl$setXmin(est)

xmin 标识为96940,表示为下限阈值。我们还注意到一条警告消息,说明“xmin 搜索空间在 1e+05 处被截断”

这意味着概率分布的下限限于 100,000。然而,当分析数据时,这似乎是合理的——因为数据集中大约 26%的值超过 100,000。

因此,在这种情况下,我判断 xmin 搜索空间足以继续进行引导过程。

拔靴带

自举指的是带替换的随机采样。这允许使用重采样数据来更好地估计总体分布,从而将样本本身视为总体。

在本例中,我们对 5,000 个具有两个内核的引导进行了采样。以下是输出和计算的标准偏差:

> bs = bootstrap(m_pl, no_of_sims = 5000, threads = 2)
xmin search space truncated at 1e+05
        You have three options
                     1\. Increase xmax in estimate_xmins
                     2\. Specify xmins explicitly
                     3\. Ignore and hope for the best (which may be OK)
Some of your data is larger than xmax. The xmax parameter is
            the upper bound of the xmin search space. You could try increasing
            it. If the estimated values are below xmax, it's probably OK not to
            worry about this.
Expected total run time for 5000 sims, using 2 threads is 160 seconds.
> bootstrap(m_pl)
xmin search space truncated at 1e+05
        You have three options
                  1\. Increase xmax in estimate_xmins
                  2\. Specify xmins explicitly
                  3\. Ignore and hope for the best (which may be OK)Some of your data is larger than xmax. The xmax parameter is
the upper bound of the xmin search space. You could try increasing
it. If the estimated values are below xmax, it's probably OK not to
worry about this.Expected total run time for 100 sims, using 1 threads is 7.45 seconds.
$gof
[1] 0$bootstraps
           gof  xmin     pars ntail
1   0.00000000 96940 1.745017    16
2   0.08522512 64208 2.044028    23
3   0.00000000 96940 1.752732    20
...
98  0.00000000 96940 1.650699    17
99  0.05581238 84703 2.013810    18
100 0.09645264 28837 1.730375    44$sim_time
[1] 0.04173159$seed
NULL$package_version
[1] ‘0.70.6’$distance
[1] "ks"attr(,"class")
[1] "bs_xmin"
> sd(bs$bootstraps[, 2])
[1] 15144.57
> sd(bs$bootstraps[, 3])
[1] 0.1633353

累积平均值和标准偏差的迭代结果如下:

来源:RStudio 输出

在绘制分布图时,显示了最后 90%的迭代。此外,在假设如下的情况下计算 p 值:

H0:数据是根据幂律分布生成的

H1:数据不是由幂律分布产生的

以下是结果输出:

> ## trim=0.1 only displays the final 90% of iterations
> plot(bs, trim = 0.1)
> 
> hist(bs$bootstraps[, 2])
> hist(bs$bootstraps[, 3])
> 
> # bs1 = bootstrap(m_ln)
> 
> bs_p = bootstrap_p(m_pl)
xmin search space truncated at 1e+05
        You have three options
                  1\. Increase xmax in estimate_xmins
                  2\. Specify xmins explicitly
                  3\. Ignore and hope for the best (which may be OK)Some of your data is larger than xmax. The xmax parameter is
the upper bound of the xmin search space. You could try increasing
it. If the estimated values are below xmax, it's probably OK not to
worry about this.Expected total run time for 100 sims, using 1 threads is 10.5 seconds.> bs_p$p
[1] 1
> plot(bs_p)

生成的 p 值为 1 ,非常高,在 5%的显著性水平上无法拒绝。这表明我们不能拒绝零假设,即所讨论的销售数据遵循幂律分布,即基于这个 p 值,我们非常确信它遵循

然而,由于这个值在这种情况下非常高,我们还将检查 p 值在迭代中的波动,以确定我们是否仍然可以拒绝零假设。

以下是累积平均值和标准差统计数据的生成图:

来源:RStudio 输出

我们可以看到,在 100 次迭代中,p 值的范围在 0.20.4 之间。虽然指示的 p 值 1 比这些范围高得多,但我们仍然可以相当有信心,在给定这些范围的 5%显著性水平下,我们不能拒绝零假设,我们可以推断这是数据遵循幂律分布的证据。

结论

poweRlaw 是一个特别有趣的包,我期待着进一步探索它。在这个例子中,我们看了如何使用这个包来模拟连续分布,特别是如何测试一个分布是否遵循幂律。

我们还了解了如何执行用于重采样目的的自举方法,这在样本大小低于预期的情况下非常有用。

此外,我们还看到了如何生成累积平均值和标准差统计数据的图表,以及如何推断迭代中的 p 值范围。

非常感谢您的宝贵时间,非常感谢您的任何问题或反馈。你也可以在 michael-grogan.com的找到更多我的数据科学内容。

免责声明:本文是在“原样”的基础上编写的,没有任何担保。它旨在提供数据科学概念的概述,不应被解释为专业建议。本文中的发现和解释是作者的发现和解释,不被本文中提到的任何第三方认可或隶属于任何第三方。

参考

  • 科林·s·吉莱斯皮:幂律包:示例
  • 美国人口普查局:2019 年年度零售贸易调查

用一个简单的统计数据分析 NFL 比赛的流程

原文:https://towardsdatascience.com/analysing-the-flow-of-nfl-games-with-one-simple-statistic-5bfca4e17dd4?source=collection_archive---------31-----------------------

如何发挥成功可以帮助您理解普通盒分数

蒂姆·米尔克在 Unsplash 上的照片

在周末对阵小马队的比赛中,比尔·乔希·艾伦投出了 26 次传球,35 次尝试,324 码,2 次达阵。比尔跑比赛也有 21 次 96 码的冲刺。

作为回应,小马队 QB 菲利普里弗斯在 46 次尝试中完成了 27 次 309 码,也有 2 次达阵。他们的跑垒有 29 次,共 163 码。

从这些数据中,我们知道艾伦在空中的表现稍微好一点。他的完成率更高了,他投了更远的距离。小马有一个相当好的运行游戏,他们比比尔尝试更多的运行发挥,并有更高的码数。

但是这些球队在比赛过程中各自的表现如何呢?我们知道比尔队最终打得更好,因为他们以 27 比 24 获胜,但了解比分是如何产生的很重要,这样我们才能有效地评估他们的表现。一个四分卫在井喷比赛的垃圾时间里投出了他 300 码中的大部分,因此不会与带领他的球队赢得胜利的表现相同。

本文的目的是介绍一种单一的度量标准,它采用标准的逐场比赛数据,并将它们转换成更好地描述游戏流程的图表。这只是体育分析的表面,但它有助于给数字带来一点生命和视觉化。

玩成功

对于任何不熟悉这项运动的人来说,美式足球的每一次进攻都是由一系列的下沉组成的。你有 4 个向下获得 10 码之前,你的向下重置。通常情况下,第三次倒地是你实际上可以跑位或传球的最后一次倒地,因为第四次通常是预留给把球踢给对手的,除非你有非常好的场上位置或者你在一场势均力敌的比赛中卷土重来。如果你在第四次击球时没有成功地打出 10 码,球将在最后一次击球的地方被传给对方。

那么我们如何定义一部戏剧是否成功呢?嗯,用最简单的话来说,如果你获得了所需的码数,那么这出戏就一定会成功,对吗?。但这引发了一个问题。如果你在第一和第十,并获得 8 码,这是一个相当稳定的发挥,但在我们的初始条件下不会被算作一个。

我们必须稍微调整我们的要求,我们通过设定固定的每羽绒所需码数百分比来做到这一点。标准共识使用以下规则:

如果一部戏剧达到了…就被认为是成功的

  • …第一次降落所需码数的 40%
  • …第二次击球所需码数的 60%
  • …第三次或第四次下降所需码数的 100%

所以这个指标帮助我们给那些在场上不断进攻的球员更多的信任。至少有 3 个 downs 可用于弥补 10 码,我们确保球队不会因为使用所有这些而受到处罚。

我们现在可以开始开发这一指标,并将其分为比赛过程中的传球和跑动。我们也可以引入防守成功,如果他们阻止了一场成功的进攻,那么这场比赛就被认为是成功的防守。

将每一次跑位分配为 0 或 1,传球和防守也是如此,这给了我们一组数值来绘制比赛过程。

我们可以把它直接绘制成成功游戏的累计次数。对于周末的海鹰@公羊比赛,看起来有点像这样。

作者图片

从这张图表中我们可以初步看出,公羊队似乎在这场比赛中赢得了奔跑和防守。这个图表中我们没有看到的是相对比较。例如,我们知道海鹰队有更多的传球和成功,但这和公羊队的成功相比又如何呢?

我们可以通过公式(成功播放次数/总播放次数)计算累计成功百分比。对于公羊海鹰队的比赛,我们的情节可能看起来像这样。

作者图片

这种视觉化帮助我们理解游戏的流程。我们看到一个球队的整体表现基于它周围的数据,这给了我们一个更清晰的关于西雅图传球比赛的画面。虽然他们确实投得更多,他们确实有更多成功的比赛,但总体百分比很低,只有 46.15%。此外,总的来说,他们的跑动和防守更差,我们开始理解为什么公羊队在这里赢得了胜利。

这种观想有一个明显的缺陷。一支球队越晚取得成功,它对他们的百分比的贡献就越小,这就是为什么同时看这两张图很重要。不过,这种观想确实能帮助我们理解游戏是如何结束的。如果我们在任何一条线的末端看到方向的剧烈变化,这真的会放大四分卫、跑卫或防守完成比赛的好坏。

这只是一个简单的例子,说明我们如何理解赛后得到的数字和比赛数据。这是一种有效而清晰的总结表现的方式,同时不会忘记游戏是如何进行的。

汽车销售的方差分析

原文:https://towardsdatascience.com/analysis-of-car-sales-with-anova-in-r-a62546d8fa41?source=collection_archive---------20-----------------------

确定各组之间的销售差异

来源:照片由奥斯卡琳拍摄,来自皮克斯拜

使用 ANOVA(方差分析)模型的主要目的是确定组间均值是否存在差异。

虽然 t 检验能够确定两个均值之间是否存在差异,但如果存在几个组,则需要进行更广泛的检验。

在本例中,我们将了解如何实现 ANOVA 模型来分析汽车销售数据。

背景

该分析是在 Kaggle 的汽车销售数据集上进行的。

该分析的目的是确定基于车型原产国的汽车组之间的发动机尺寸、马力和燃油效率等因素是否不同。

当只使用一个分类变量时,使用单向 ANOVA 来确定影响。

双向方差分析用于确定跨多个类别的影响(也称为因子方差分析),以及是否存在交互影响,即因素对因变量的综合影响,而不是单独考虑它们。

以下是数据集的概述:

来源:RStudio 输出

请注意,对于制造商列,数据集中提供了 50 个不同的类别(或因子)。为了减少因素的数量,增加了称为国家的第二个因素,制造商根据其原产国进行分组。例如,奥迪和大众生产的所有汽车都被归为德国制造,而现代和丰田生产的所有汽车都被归为日本制造,等等。

单向方差分析

如前所述,在这种情况下,将使用单向方差分析来确定以下变量在车辆类型和制造商所在国家之间是否存在显著的平均值差异:

  • 功率性能因数
  • 发动机尺寸
  • 马力
  • 燃料容量
  • 燃料效率

让我们运行 ANOVAs 并分析结果。

> one.way <- aov(Power_perf_factor ~ vehicle_type, data = mydata)
> summary(one.way)
              Df Sum Sq Mean Sq F value Pr(>F)
vehicle_type   1      0     0.1       0   0.99
Residuals    153  97352   636.3               
2 observations deleted due to missingness

> one.way <- aov(Engine_size ~ vehicle_type, data = mydata)
> summary(one.way)
              Df Sum Sq Mean Sq F value Pr(>F)   
vehicle_type   1  11.34  11.338   11.06 0.0011 **
Residuals    154 157.81   1.025                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
1 observation deleted due to missingness

> one.way <- aov(Horsepower ~ vehicle_type, data = mydata)
> summary(one.way)
              Df Sum Sq Mean Sq F value Pr(>F)
vehicle_type   1     11      11   0.003  0.954
Residuals    154 498303    3236               
1 observation deleted due to missingness

> one.way <- aov(Fuel_capacity ~ vehicle_type, data = mydata)
> summary(one.way)
              Df Sum Sq Mean Sq F value Pr(>F)    
vehicle_type   1  836.4   836.4   85.49 <2e-16 ***
Residuals    154 1506.6     9.8                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
1 observation deleted due to missingness

> one.way <- aov(Fuel_efficiency ~ vehicle_type, data = mydata)
> summary(one.way)
              Df Sum Sq Mean Sq F value   Pr(>F)    
vehicle_type   1    928   928.0    75.1 6.21e-15 ***
Residuals    152   1878    12.4                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
3 observations deleted due to missingness

我们可以看到,对于数据集中的车辆类型(指定为客车或轿车),结果对于马力功率性能系数并不重要,即这些变量的平均值并没有显示出统计上的显著差异,这取决于车辆是被分类为客车还是轿车

现在让我们来看看这些变量的平均值是否因国家而异。

> one.way <- aov(Power_perf_factor ~ Country, data = mydata)
> summary(one.way)
             Df Sum Sq Mean Sq F value Pr(>F)
Country       4   4851  1212.7   1.967  0.102
Residuals   150  92501   616.7               
2 observations deleted due to missingness

> one.way <- aov(Engine_size ~ Country, data = mydata)
> summary(one.way)
             Df Sum Sq Mean Sq F value  Pr(>F)   
Country       4  14.56   3.641   3.556 0.00838 **
Residuals   151 154.59   1.024                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
1 observation deleted due to missingness

> one.way <- aov(Horsepower ~ Country, data = mydata)
> summary(one.way)
             Df Sum Sq Mean Sq F value Pr(>F)
Country       4  14798    3699   1.155  0.333
Residuals   151 483516    3202               
1 observation deleted due to missingness

> one.way <- aov(Fuel_capacity ~ Country, data = mydata)
> summary(one.way)
             Df Sum Sq Mean Sq F value Pr(>F)
Country       4   10.7    2.67   0.173  0.952
Residuals   151 2332.3   15.45               
1 observation deleted due to missingness

> one.way <- aov(Fuel_efficiency ~ Country, data = mydata)
> summary(one.way)
             Df Sum Sq Mean Sq F value Pr(>F)
Country       4   11.3   2.826   0.151  0.962
Residuals   149 2795.0  18.758               
3 observations deleted due to missingness

我们可以看到,除了发动机尺寸之外,F 统计的 p 值对于所有发动机尺寸来说都是不显著的,这意味着根据制造商的国家不同,平均发动机尺寸在统计上存在显著差异。

值得注意的是,使用 ANOVA 的一个限制是,测试将仅表明组间的平均差异是否具有统计显著性——它们不会特别揭示哪个组对平均差异负责。

例如,我们可能会观察到不同国家的平均发动机尺寸不同,但是 ANOVA 本身无法告诉我们与其他国家的车辆相比,哪个国家的制造商的平均发动机尺寸更大。

双向方差分析

此外,单向方差分析的局限性在于它不能检验交互作用的影响。例如,车辆类型和制造国家可能不会单独影响车辆的马力,但是当这两个因素结合在一起时呢?

在这方面,双向方差分析用于 1)检验多个因素对因变量的影响,以及 2)组合这些因素的影响,即交互作用的影响。

以下是我们将运行的四个模型(包括交互效应):

model_1 = lm(Engine_size ~ vehicle_type + Country + vehicle_type*Country, data = mydata)model_2 = lm(Fuel_efficiency ~ vehicle_type + Country + vehicle_type*Country, data = mydata)model_3 = lm(Fuel_capacity ~ vehicle_type + Country + vehicle_type*Country, data = mydata)model_4 = lm(Sales_in_thousands ~ vehicle_type + Country + vehicle_type*Country, data = mydata)

对四个模型中的每一个进行双向 ANOVA 测试:

library(car)
Anova(model_1, type = "II")
Anova(model_2, type = "II")
Anova(model_3, type = "II")
Anova(model_4, type = "II")

结果如下:

> Anova(model_1, type = "II")
Note: model has aliased coefficients
      sums of squares computed by model comparison
Anova Table (Type II tests)Response: Engine_size
                      Sum Sq  Df F value   Pr(>F)   
vehicle_type          10.219   1 10.4870 0.001484 **
Country               13.444   4  3.4492 0.009989 **
vehicle_type:Country   0.159   2  0.0814 0.921836   
Residuals            144.211 148                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1> Anova(model_2, type = "II")
Note: model has aliased coefficients
      sums of squares computed by model comparison
Anova Table (Type II tests)Response: Fuel_efficiency
                      Sum Sq  Df F value    Pr(>F)    
vehicle_type          997.09   1 81.5442 9.305e-16 ***
Country                80.39   4  1.6436    0.1664    
vehicle_type:Country   12.65   2  0.5171    0.5973    
Residuals            1785.22 146                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 > Anova(model_3, type = "II")
Note: model has aliased coefficients
      sums of squares computed by model comparison
Anova Table (Type II tests)Response: Fuel_capacity
                      Sum Sq  Df  F value    Pr(>F)    
vehicle_type          888.24   1 104.4075 < 2.2e-16 ***
Country                62.56   4   1.8383    0.1245    
vehicle_type:Country  184.94   2  10.8693 3.941e-05 ***
Residuals            1259.10 148                       
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1> Anova(model_4, type = "II")
Note: model has aliased coefficients
      sums of squares computed by model comparison
Anova Table (Type II tests)Response: Sales_in_thousands
                     Sum Sq  Df F value   Pr(>F)   
vehicle_type          24865   1  6.3332 0.012909 * 
Country               49466   4  3.1497 0.016097 * 
vehicle_type:Country  45149   2  5.7497 0.003932 **
Residuals            585007 149                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

我们可以看到,对于车型 4车型国家之间的交互作用在统计上是显著的。

这表明销售价值受到车型和制造商所在国家的显著影响。而且,这两个变量也是相互作用的。

举一个假设的例子,我们可能会发现日本的乘用车销量较高,但德国的乘用车销量较低。换句话说,我们不能简单地得出结论,车辆类型和销售之间的关系在不同国家将保持不变——相互作用的存在表明它们可能不同。

使用 sjPlot 库,我们可以进一步查看交互效果。

library(sjPlot)
plot_model(model_4, type = "pred", terms = c("vehicle_type", "Country"))

来源:RStudio 输出

我们可以看到,不同车型的销售价值差异很大。例如,在德国,汽车的销售范围要比乘用车大得多。

同样,日本的乘用车销售价格中值高于轿车。

结论

总之,我们已经看到了如何使用单因素和双因素方差分析来分析均值之间的差异,在这种情况下,使用的是汽车销售数据集。

我们还看了一下:

  • 使用方差分析的局限性
  • 如何使用双向方差分析来检验变量之间的交互作用
  • 使用 sjPlot 库在视觉上检查交互效果

非常感谢您的宝贵时间,非常感谢您的任何问题或反馈。你也可以在 michael-grogan.com 的找到更多我的内容。

免责声明:本文是在“原样”的基础上编写的,没有担保。它旨在提供数据科学概念的概述,不应被解释为专业建议。本文中的发现和解释是作者的发现和解释,不被本文中提到的任何第三方认可或隶属于任何第三方。作者与本文提及的任何第三方无任何关系。

蒙特利尔咖啡店分析——街区分割和聚类

原文:https://towardsdatascience.com/analysis-of-coffee-shops-in-montreal-neighbourhood-segmentation-and-clustering-4e4f020c30d7?source=collection_archive---------25-----------------------

实践教程

如何使用 four square API k-means 聚类对蒙特利尔市的社区进行分类和聚类

图 1——由拍摄的自由照片在 Pixabay 上

介绍

蒙特利尔是加拿大人口第二多的城市,也是加拿大魁北克省人口最多的城市。

这座城市是一个旅游胜地,有几个娱乐区、历史古迹、众多的酒吧、餐馆和咖啡馆。一项既是游客也是居民的活动是喝咖啡。这项活动可以单独进行,也可以在朋友的陪同下,在这个城市的任何时间进行。

在世界上人均饮用咖啡量较高的 20 个国家中,加拿大人的人均消费量约为 6.5 公斤/年,高于美国和英国。

平均而言,72%的 18 至 79 岁的加拿大人每天都喝咖啡,但在经常喝咖啡的人中,平均消费量是每天 2.8 杯(加拿大咖啡协会)。

商业问题

这个项目的目标是分析和探索一个咖啡店的最佳位置。这份报告将针对那些想从零开始,购买现有企业的利益相关者,或者任何对加拿大蒙特利尔的好咖啡感兴趣的人。

由于蒙特利尔有很多咖啡店,我们将尝试检测那些还没有挤满咖啡店的位置。我们还对附近没有咖啡店的地区特别感兴趣。假设前两个条件都满足,我们也希望位置尽可能靠近市中心(麦吉尔大学附近)。

数据

对于蒙特利尔居民区的数据,维基百科上有一个页面,里面有我们探索和聚集城市居民区所需的所有信息。

为了获得蒙特利尔居民区和邮政编码的数据,维基百科页面被废弃了。用于此任务的库是 BeautifulSoup。通过刮擦,从 124 个邮政编码、地区和区域获得了数据。仍然需要添加每个邮政编码的纬度和经度,为此,我使用了 pgeocode 库。

在验证了一个邮政编码(HOP)没有关于它的邻居、地区的信息,因此既没有纬度也没有经度之后,执行了数据清理。我研究了蒙特娄的邮政编码,发现 H0 的前缀很奇怪。零表示交付农村地区,因此实际上是空的。(加拿大的邮政编码)。这样,那个邮政编码就被删除了。

通过邮政编码的箱线图图,观察到经纬度的异常值。该坐标不属于加拿大,因此已从数据集中移除。

图 2—按作者分类的图像—纬度箱线图中的异常值

之后,该数据框总共有 122 个邻域,并且它的存储方式可以读取到 pandas 数据框中,因此它是一种类似于魁北克蒙特利尔数据集的结构化格式。

图 3——作者的图片——蒙特利尔街区

方法学

在这一节中,将展示用于项目分析的方法。

首先,我们检查了候选社区。这是创造了经纬度坐标的质心,麦吉尔大学附近。

可视化库 叶子 被用来创建一个蒙特利尔的地图,上面叠加了街区,以及一个覆盖感兴趣区域的网格。20x20 公里,以麦吉尔大学附近为中心。

图 4—按作者分类的图像—候选人社区

为了探索蒙特利尔市的街区,使用了four squareAPI。该界面用于获取每个街区中最常见的位置类别(咖啡馆、餐馆、冰淇淋店、艺术画廊等),然后使用该功能对街区进行分组。必须在应用程序中创建一个帐户来获取您的客户端凭据。

首先,API 被用来获取半径为 2.5 公里的麦吉尔大学附近的前 100 个场馆。

第二,分析验证了蒙特利尔地区上空 280 个类别的频率,并且在咖啡店类别被过滤之后。

图 5——按作者分类的图片——每个类别的出现频率

图 6—按作者分类的图片—咖啡店类别频率

然后,执行 k-means 聚类算法以将邻域聚类成 4 个聚类。再次,叶图书馆被用来可视化城市的集群分布。根据咖啡店在每个区域的出现频率,按照本项目的要求(附近很少或没有咖啡店的区域),对每个集群进行检查和区分。

图 7—作者提供的图片— 群集

最后,计算出咖啡店很少或没有的街区到麦吉尔大学街区的距离,并将其添加到分析中。

图 8—作者提供的图片— 距离市中心最近的前 5 个街区,咖啡馆的出现频率很低

结果

这项工作分析了蒙特利尔的 122 个街区,目的是发现不再充满咖啡店的地方。

蒙特利尔自助餐厅密度最低的区域集中在分析区域的外围区域。这个区域与群集 0(地图上的红点)相关。在这个组群中,有 25 个居民区密度较低。

凡尔登南部是离麦吉尔大学最近的街区,咖啡店密度很低。距离中心坐标 1.97 公里。

还有更近的地方,没有拥挤的咖啡店:Plateau Mont-royal southeast(0.75 公里),Verdun North(1.36 公里),Place Desjardins,蒙特利尔市中心东北(都是 1.38 公里)。

结论和建议

项目要求包括检测尚未挤满咖啡馆的地方,或附近咖啡店密度较低的区域,并尽可能靠近市中心(麦吉尔大学)。建议以下五个方案满足项目要求:凡尔登南,距离麦吉尔大学最近的街区,咖啡店密度最低,距离中心坐标 1.97 公里;Plateau Mont-royal 东南(0.75 公里)Verdun North(1.36 公里)Place Desjardins(1.38 公里)蒙特利尔市区东北(1.38 公里)。

这个项目只考虑了附近咖啡店的频率。其他因素对最终决定自助餐厅的位置也很重要,如附近的其他企业(将是补充自助餐厅的其他相关类别)、附近的生活费用、安全区等。此外,所有分析都是使用免费 API 或其开放访问选项进行的。可以使用付费资源进行分析,以便获得更多的结果选项

这个分析的笔记本可以看这里。

纽约市机动车碰撞事故分析

原文:https://towardsdatascience.com/analysis-of-new-york-city-motor-vehicles-collisions-927da110dfc7?source=collection_archive---------19-----------------------

实践教程

使用 Google BigQuery 和 Tableau 的数据分析师访谈案例研究

在我的上一篇文章中,我谈到了我向数据分析的转变,以及我最近如何获得一份全职数据分析师的职位。整个 4 月 21 日,我在各种北美公司的面试中来去自如。对于其中一些公司,我必须参与 Excel、SQL 或 Python 测试,而其他一些公司则让我进行案例研究。在本文中,我将向您介绍我通过的一个这样的案例研究,以及我解决这个问题的方法。

照片由卢克·斯塔克波尔在 Unsplash 拍摄

任务

首先,案例研究是公司在考虑让你进入高级面试阶段之前测试核心技能的一种方式。在这个案例研究中,我的任务是分析 2014 年 1 月至 2017 年 12 月谷歌大查询中的纽约市机动车辆碰撞数据集,并提供建议以减少纽约布鲁克林区**的事故发生率。从 2012 年至今,整个数据集目前拥有超过 170 万条记录,可在此处访问。

附注:Google BigQuery 有几个定期更新的公共数据集,可以用来为你的投资组合构建项目。

我的方法

我的第一反应是在网上搜索与这项任务相关的文章,因为“太阳底下没有新东西”。我发现以前的文章对开发我的方法很有用。我的方法总结如下图所示。

我的案例研究方法(图片由作者提供)

第一步

这里有一些技巧和步骤,你可以用来进行未来的案例研究。

  • 理解任务: 这对于任何案例研究都是相关的,以确保你的分析不会跑题。重要的是,在多走一步之前,先按照指示去做。在本案例研究中,我差点错过了简报中要求我仅分析 2014-2017 年数据的地方。
  • 准备数据:在浏览数据集时,识别主键并检查重复值和空值应该是很容易的事情。还要寻找可能与您的分析相关的字段,这样您就不会将不相关的字段导入到您的商业智能工具中。这就是 SQL 派上用场的地方。

在 Google BigQuery 中检查重复项(P.S. Query 没有返回结果)在这种情况下是一件好事。)

深潜

为了分析数据集,我使用了 Tableau Public ,原因有二:我想创建一个交互式仪表盘,Tableau 是工作描述中提到的技能之一。通过研究数据集,我获得了对关键特性进行深入分析的想法。下面重点介绍了一些,而其他的可以在最终的控制面板中探索。

  • 碰撞分析:这样做是为了揭示导致碰撞和死亡的主要原因。我们可以看到,大多数死亡事故都是由驾驶员疏忽/分心造成的。

按死亡人数列出的 7 大碰撞促成因素(图片由作者使用表格提供)

  • **时间序列分析:揭示一天中的什么时间或一周中的哪一天碰撞最多。我们可以从下面的图表中看到,大多数碰撞发生在高峰时间(下午 4 点到 5 点)。在一天的早些时候,我们也能看到大量的数据。

碰撞时间序列分析(图片由作者使用 Tableau 提供)

  • **死亡分析:这表明,每当发生碰撞时,行人比其他道路使用者更容易死亡。

道路使用者每年死亡总数(作者使用表格提供图片)

将这一切结合在一起

利用从我的分析中收集的见解,我准备了一个幻灯片来提供建议。一个额外的建议是确保你提供的任何建议都是由你的分析支持的——而不是先前的知识。此外,大多数公司会给几个小时到 5 个工作日的时间来完成案例研究。如果你看到你有更多的时间,请尽量不要匆忙。

根据我的分析提供的建议(图片由作者提供)

此案例研究的最终提交是一个幻灯片组仪表盘。后者是一个附加物,因为这是一个主要的技术公司,他们喜欢它:)。交互式仪表板的预览如下所示。我在 Figma 设计了背景,剩下的魔术发生在 Tableau。

最终 Tableau 仪表板(图片由作者提供)

相关链接

  • 画面仪表盘
  • 最终幻灯片组
  • LinkedIn 个人资料

利用熊猫分析纽约市报告的犯罪数据

原文:https://towardsdatascience.com/analysis-of-nyc-reported-crime-data-using-pandas-821753cd7e22?source=collection_archive---------16-----------------------

安德烈·本茨在 Unsplash 上拍照

介绍

当我在 Python 中使用 Pandas 学习数据分析时,我决定分析关于纽约市的公开数据——美国最大和最有影响力的大都市。纽约市实际上是分散在该市五个区的许多街区的集合:曼哈顿、布鲁克林、布朗克斯、皇后区和斯塔滕岛。纽约是美国人口最多、最国际化的城市。

Pandas 是一个高级库,用于在 Python 中进行实际的、真实世界的数据分析。它是分析和操作数据的最强大、最灵活的开源工具之一。在这篇文章中,我的目标是探索熊猫视觉分析的广泛机会。

关于数据集

该数据集包括从 2006 年到 2019 年底向纽约市警察局(NYPD)报告的所有有效的重罪、轻罪和违规犯罪。原始数据集可以在 NYC 开放数据网站上找到。

导入库和数据

  • read_csv上面写着。csv 数据并返回熊猫数据帧。
  • 我做了。csv 数据集可在 Kaggle 获得供公众使用。
*#import pandas*
import pandas as pd *# data processing and manipulation*

*#import data*
df = pd.read_csv('NYPD_Complaint_Data_Historic.csv')
  • 检查是否成功获取数据。

df.head()

数据预处理

先看数据

首先,我们检查数据集中的行数,以了解我们正在处理的大小。为此,我们使用函数df.shape返回数组的形状。

  • 意见数量:6 983 207
  • 变量:35

在查看数据集的头部之后,我们已经能够注意到一些 NaN 值,因此我们需要在继续分析之前进一步检查缺失的值。

  • isna()函数向我们显示了每个变量的不存在值的百分比。
PARKS_NM              object             99.64%
STATION_NAME          object             97.75%
TRANSIT_DISTRICT     float64             97.75%
HADEVELOPT            object             95.04% 
HOUSING_PSA           object             92.31%
SUSP_AGE_GROUP        object             67.41%
SUSP_SEX              object             49.72%
SUSP_RACE             object             47.81%
CMPLNT_TO_DT          object             23.89%
CMPLNT_TO_TM          object             23.82%
VIC_AGE_GROUP         object             23.46%
LOC_OF_OCCUR_DESC     object             21.19%
PREM_TYP_DESC         object              0.56%
Y_COORD_CD           float64              0.34%
X_COORD_CD           float64              0.34%
Lat_Lon               object              0.34%
Latitude             float64              0.34%
Longitude            float64              0.34%
OFNS_DESC             object              0.26%
BORO_NM               object              0.15%
PATROL_BORO           object              0.09%
PD_DESC               object              0.08%
PD_CD                float64              0.08% 
JURISDICTION_CODE    float64              0.08%
ADDR_PCT_CD          float64              0.03%
CMPLNT_FR_DT          object              0.009%
VIC_RACE              object              0.004%
VIC_SEX               object              0.004%
CMPLNT_FR_TM          object              0.0006%
CRM_ATPT_CPTD_CD      object              0.0001%
JURIS_DESC            object              0.00%
LAW_CAT_CD            object              0.00%
KY_CD                  int64              0.00%
RPT_DT                object              0.00%
CMPLNT_NUM             int64              0.00%

处理缺失数据

因为一些列对于分析非常重要,所以我删除了缺少任何关键值的整行。为此,我在 Pandas 中使用了dropNA()函数。

我不想删除整行的列,我选择用“未知”值填充它们(这些值包括包含犯罪受害者信息的变量,如他们的年龄组、种族和性别)。为此我使用了fillNA()函数。

值得一提的是,一些特定的变量有很多 NaN 值,它们在这个分析中不一定有任何用处(比如 PARKS_NM 表示犯罪发生的附近的公园或公共场所,考虑到它们有很多缺失的数据,包含嫌疑人信息的列也不重要),所以我会用drop()函数完全删除这些列。

预处理关于犯罪类型的文本

好好看看这个数据,去掉 NaN 值,才知道犯罪类型数据真的很混乱。通过提取 OFNS_DESC 列(进攻描述)中的唯一值,我可以看到哪些描述不太直观,并重命名这些值,使它们更容易理解。

replace()方法返回一个子字符串被另一个子字符串替换后的副本。这样,我就能够将数据集copy()成一个名为‘df _ clean’的新数据集,并将一些犯罪描述重新命名(例如‘骚扰 2’改为‘骚扰’,‘关。从“违反公共秩序/行政管理”到“违反公共秩序/行政管理”。

探索性分析

1.犯罪类型

清理完数据后,我想知道纽约市有多少种犯罪类型。

  • 在熊猫身上用value_counts

value_counts方法有助于统计不同类型犯罪出现的次数,并按顺序排序。

以下是数据集中报告的 10 大犯罪。

df_clean.OFNS_DESC.value_counts().iloc[:10].sort_values().plot(kind="barh", title = "Types of Crimes")

在这里,我们可以看到纽约市发生最频繁的犯罪事件是“小盗窃”,这是一种盗窃行为,被盗财产的价值一般低于 50 美元。

在纽约州有三种级别的犯罪:违规、轻罪和重罪。

从下面的图表中,我可以看出轻罪是最受欢迎的犯罪级别,轻罪的刑期可能超过 15 天,但不超过一年。第二种常见的是重罪,是最严重的违法行为,第三种是违反,是较轻的违法行为,刑期不超过 15 天。

2.犯罪在时间上的分布

我还想知道纽约市犯罪事件的趋势。

第一张图显示了按年份、按月份、最后按一天的犯罪分布的犯罪事件。

df_clean['year'].value_counts().plot(kind="line", title = "Total Crime Events by Year")

总的来说,通过查看纽约市警方记录的犯罪数量,可以看出自 2006 年以来犯罪率一直在下降。

df_clean.groupby('month').size().plot(kind = 'bar', title ='Total Crime Events by Month', color = '#C0392B',rot=0)

犯罪在 7 月、8 月和 10 月最多,而 2 月、11 月和 12 月似乎更安全。根据这些信息,有可能假设温度和犯罪之间存在正相关关系。

df_clean.groupby('time').size().plot(kind = 'bar', title ='Total Crime Events by Day', color = '#E67E22', xlabel = 'hours',rot=0)

我们可以知道一天中最不容易发生犯罪的时间是早上 5 点,但更有可能发生在晚上 12 点到 6 点之间。

3.每个行政区的犯罪分布

df_clean['BORO_NM'].value_counts().sort_values().plot(kind="barh", color = '#1ABC9C', title = 'Total of Crime Events by Borough')

根据这一可视化,布鲁克林的犯罪事件总数最高,有超过 200 万份报告。

4.分析具体的犯罪

我想具体分析一下纽约市的性犯罪。为此,我将包含犯罪描述“性犯罪”和“强奸”的数据框部分放入另一个数据框,并将其命名为“性犯罪”

sex_crimes = df_clean[df.OFNS_DESC.str.contains('SEX CRIMES|RAPE')]
  • 新的数据集记录了纽约市总共 104.211 起性犯罪报告。

我们可能对这些年的数值分布感兴趣,所以我将按年份对数据进行分组,并绘制出结果。

  • 根据我计算的柱状图,与前几年相比,性犯罪在过去 3 年中发生得最多。
  • 平均而言,纽约市每年有 7443 名强奸和性侵犯受害者。

让我们看看报告的数量在一天内是如何变化的。

在这里,我们可以告诉你一天中最安全的时间是早上 6 点,这是纽约最不可能发生性犯罪的时间。然而,人们需要在午夜和凌晨 1 点之间更加小心。

分析受害者

性暴力影响了数百万人。性侵犯、家庭暴力、约会暴力或跟踪的影响可能会改变幸存者及其家人的生活。因此,我决定对纽约的性犯罪受害者做一个简要的分析。

FEMALE                   83.20%
MALE                     14.75%
UNKNOWN                   1.93%

<18      48.85%
25-44    22.43%
18-24    16.44%
45-64     4.69%
65+       0.53%

BLACK                             32.87%
WHITE HISPANIC                    28.59%
WHITE                             16.66%
UNKNOWN                           10.13%
ASIAN / PACIFIC ISLANDER           5.85%
BLACK HISPANIC                     5.60%
AMERICAN INDIAN/ALASKAN NATIVE     0.28%

通过对受害者的这种分析,我发现了以下几点感悟:

  • 83%的受害者是女性。女性成为强奸、强奸未遂或性侵犯受害者的可能性大约是男性的四倍。
  • 18 岁以下的人最容易遭到强奸/性侵犯。
  • 黑人和白人西班牙裔居民经历强奸/性侵犯的可能性是其他种族的两倍。

结论

通过使用 Pandas,我分析并可视化了纽约市犯罪事件报告的公开数据。这个库被证明是数据分析中一个强大的工具,是一个很好的开始。
在这之后,我对研究更多与犯罪相关的数据感兴趣,并尝试不同的图书馆进行数据可视化。

感谢您的阅读!请随意检查我的 Github 的完整代码。

布鲁纳·m

使用 Python 分析 Garmin Watch 中的跑步活动

原文:https://towardsdatascience.com/analysis-of-runing-activities-from-garmin-watch-using-python-99609f83314e?source=collection_archive---------15-----------------------

发现你的跑步模式

在疫情期间,我决定寻找一种新的活动,而不是当时关闭的健身房或游泳池。我从来不喜欢跑步,但对我来说,这显然是一个对 Covid 友好的选择,所以我决定尝试一下。我买了 Garmin Vivoactive 4 来跟踪我的进展,并开始了旅程。

Garmin Connect 应用程序确实提供了一些见解,如平均速度、一段时间内的心率等。但我很好奇,想自己摆弄数据,看看自己的进步。在最初几个月的跑步后,我还受过两次伤(先是左腿,然后右腿),所以想看看数据是否能揭示这些伤的根本原因。这个项目我用的是 Python 3.8 和 Jupiter Notebook。

数据收集

首先,我们需要得到数据。Garmin 提供了几种方式来访问你的数据。您可以将上传的活动导出为 CSV 文件或请求数据导出,Garmin 会将您所有的数据以 JSON 格式发送到您的电子邮件中(无论如何您都必须将其解析为 CSV 格式才能进行分析)。我通过“运行”类型过滤了我的活动,并将其导出:

作者图片

我也使用法定测量单位,所以所有的数据都是英里。如果您更喜欢 km,您可以更改 Garmin 设置并以公制单位导出所有内容,或者稍后修改数据框中的数据。

数据清理

我们先来看看数据。我们需要导入 pandas 库来处理数据框:

import pandas as pddf = pd.read_csv('garmin/Activities.csv')df.info()

作者图片

哇,32 列!我不需要全部,所以让我们先清理一下:

0.活动类型—这必须始终“运行”,以便我们能够安全地删除它。让我们做一个快速的理智检查:

df['Activity Type'].describe()

作者图片

是的,正如预测的那样,所有的活动都是“运行”类型的,删除这个列很好。

1.Date —我们肯定需要这个列,但是,数据类型是 object,而不是 datetime,所以我们将稍后修复它。

我也会用 4。距离,5。卡路里,6。时间,平均 7 小时,最大 8 小时,9 小时。平均跑步节奏,10。最大跑步步频,11。平均配速,12。最佳配速,平均步幅 15,耗时 29。

其中一些是对象类型,我们需要在以后将它们转换成 datetime 或 float64。

好了,让我们更新数据框,只保留我们要使用的列:

df = df[['Date', 'Distance','Calories','Avg HR','Avg Run Cadence', 'Avg Pace', 'Best Pace', 'Avg Stride Length', 'Elapsed Time']]

让我们将日期、平均配速、最佳配速、经过时间转换成日期时间,然后将时间转换成分钟数:

#convert 'Date', 'Avg Pace', 'Best Pace', 'Elapsed Time' objects to datetime formatdf['Date'] = pd.to_datetime(df['Date'])df['Avg Pace'] = pd.to_datetime(df['Avg Pace'], format='%M:%S')df['Best Pace'] = pd.to_datetime(df['Best Pace'], format='%M:%S')df['Elapsed Time'] = pd.to_datetime(df['Elapsed Time'])#convert 'Avg Pace', 'Best Pace', 'Elapced Time' objects to the number of minutesdf['Avg Pace'] = df['Avg Pace'].dt.hour*60 + df['Avg Pace'].dt.minute + df['Avg Pace'].dt.second/60df['Best Pace'] = df['Best Pace'].dt.hour*60 + df['Best Pace'].dt.minute + df['Best Pace'].dt.second/60df['Elapsed Time'] = df['Elapsed Time'].dt.hour*60 + df['Elapsed Time'].dt.minute + df['Elapsed Time'].dt.second/60

我更了解速度(英里/小时)而不是配速(分钟/英里),所以将增加 2 个新列:

#add 'Avg Speed' and 'Best Speed' columnsdf['Avg Speed'] = 60 / df['Avg Pace']df['Best Speed'] = 60 / df['Best Pace']

最后,让我们将对象类型的其余列转换为 float64:

s = df.select_dtypes(include=’object’).columnsdf[s] = df[s].astype(“float”)

总部,我有:

值错误:无法将字符串转换为浮点数:“—”

我没想到会看到这个。让我们找出我们在哪里有' ——:

df[df.isin(['--']).any(axis=1)]

作者图片

我的数据集中有 1 个虚拟运行会话。我们可以用 NaN 代替'—':

import numpy as npdf.replace({'--':np.nan},  inplace=True)

让我们再次尝试运行我们的小代码来将对象列转换为 float64:

#convert remaining columns of object type to float64s = df.select_dtypes(include='object').columnsdf[s] = df[s].astype("float")df.info()

作者图片

终于成功了!最后看一下数据:

作者图片

数据分析

我将使用 seaborn 和 Matplotlib Pyplot 库来可视化我的数据。让我们从心跳分布的简单直方图开始:

import seaborn as snsimport matplotlib.pyplot as pltplt.figure(figsize=(14,6))sns.histplot(data = df, x='Avg HR').set(title = 'Average HR Distribution')

作者图片

心跳分布在我看来很正常(:

塞巴斯蒂安·劳贝在 Unsplash 上的照片

运行期间最有可能的值是大约 135 BPM。

只有两种方法可以提高你的跑步速度:你可以增加你的步频(每分钟的步数)或者步幅。我们去看看。

首先是节奏:

sns.jointplot(x='Avg Speed',y='Avg Run Cadence', data=df.dropna(),kind='scatter')print("The correlation coefficient between cadence and speed:", df['Avg Speed'].corr(df['Avg Run Cadence']))

节奏与速度的相关系数:0.7879793392063

作者图片

对于步幅长度:

步幅与速度的相关系数:0.792976223204663

作者图片

节奏和步幅与速度有很强的相关性。我可以同时增加步频和步幅吗?让我们来看看:

步幅与跑步节奏的相关系数:0.4213359685994146

作者图片

在我的例子中,步频和步幅之间的相关性要弱得多。至少还是正面的。比较一年内的数据会很有趣。

让我们仔细看看速度。我想将它按月分组,并绘制每月的箱线图:

plt.figure(figsize=(14,6))#add extra column with month for every running sessiondf['Month'] = df['Date'].dt.strftime('%b') + " " + df['Date'].dt.strftime('%Y')#sort datataset by date in ascending orderdf.sort_values(by='Date', inplace=True)#plot boxplots grouped by monthsns.boxplot(x='Month',y='Avg Speed', palette=["m", "g"], data=df.dropna()).set(title = 'Avg Speed by Month')

作者图片

有意思。前 2 个月(2020 年 12 月和 2021 年 1 月)是我最快的几个月。我在二月份左腿受伤时放慢了速度,然后我想我恢复了,在四月份右腿受伤。五月和七月几乎没有跑步,七月我开始谨慎锻炼。我的中值速度仍然低于 1 月份,但你可以看到 9 月份我的最大速度的离群值(那是因为我参加了 5K 比赛)。

让我们用节奏和步幅做同样的练习:

作者图片

作者图片

这里有一些模式。受伤后,我在 7 月份开始慢慢增加步频,而我的步幅基本保持在同一水平。这正是我想要达到的目标:增加你的节奏是一种压力小得多的提高速度的方法,我现在想放松一下!

我还想知道现在我每周跑步的次数,以及它与我的平均速度之间的关系。

首先,让我们创建一个新的数据集,并按周对数据进行分组。我还将创建“计数”列来计算每周的会议次数:

df['Count'] = 1#aggregate data by weekdfW = df.groupby(pd.Grouper(key='Date',freq='W')).agg({'Count':'sum','Distance':'sum', 'Calories':'sum','Avg HR':'mean','Avg Run Cadence':'mean', 'Avg Speed':'mean','Best Speed':'mean', 'Avg Pace':'mean', 'Best Pace':'mean', 'Avg Stride Length':'mean', 'Elapsed Time':'mean'}).reset_index()dfM.head()

作者图片

现在,我将展示每周的会议次数与我的平均速度:

# create figure and axis objects with subplots()fig,ax = plt.subplots(figsize=(14,6))# make a barplotcount = ax.bar(dfW['Date'], dfW['Count'],width=10, color='red',label='Number of Runs')ax.bar_label(count)# set x-axis labelax.set_xlabel('Date')ax.legend(loc=2)# set y-axis labelax.set_ylabel('Number of Runs',color='red')# twin object for two different y-axis on the sample plotax2=ax.twinx()# make a plot with different y-axis using second axis objectax2.plot(dfW['Date'],dfW['Avg Speed'],color='blue',marker='o',label='Average Speed')ax2.set_ylabel('Average Speed',color='blue')ax2.legend()plt.show()

作者图片

我首先在一月份达到了每周训练次数和平均速度的最大值。我感到左腿有些不舒服。我试着减轻负荷,但是没有用,我停止了 3 周的训练。我试图在二月份以较慢的速度恢复训练,但是我的右腿受伤了,几乎完全停止了几个月。我能说什么,永远不要跳过 l̶e̶g̶休息日!

我们可以做同样的练习,但这次用步幅代替速度:

作者图片

这是有道理的,在我受伤的前几个月,我的平均步幅更高。

吸取经验教训,我现在通常每周训练 3 次,并试着专注于节奏而不是步幅。

如果你有兴趣玩代码,可以随意查看我的 GitHub 页面。

2020-21 英超赛季切尔西阵容分析

原文:https://towardsdatascience.com/analysis-of-the-chelsea-squad-for-the-2020-21-premier-league-season-a7b38176bd41?source=collection_archive---------39-----------------------

照片由 Pixabay 上的 ahundt 拍摄

随着新年的开始,我们已经到达了一个不同寻常的英超赛季的“中点”。当所有球队都打了 19 场比赛时,从技术上来说,这将被视为中点(在以前的赛季中,大多数球队在新年伊始就已经打了 19 场比赛)。然而,由于新冠肺炎的原因,赛季开始的晚些时候打破了通常的循环。因此,目前,我们只进行了 16 场比赛。

由于这个新的正常中点,这将是一个伟大的时间来分析赛季至今。因此,我将利用这篇文章,用数据科学的方法来分析我所支持的俱乐部,即切尔西的联赛赛季。我用于分析的数据只有 14 场比赛的统计数据。

由乔罗诺在 Pixabay 上拍摄的照片

在这篇文章中,我想回答三个问题

问:球队中表现最好和最差的射手是谁?

问:小队中哪些球员是最倒霉的创造者?

问:哪些球员的进球得分率最高?

数据取自名为fbref.com的网站。你可以在这里看一下数据。

关于数据的一些信息:有 30 名切尔西球员的信息,有 25 个特征或指标。一些指标是预期进球(xG)、预期助攻(xA)等的统计数据。

Jannik Skorna 在 Unsplash 上的照片

Q1。谁是球队中表现最好和最差的射手?

拉斯·博·尼尔森在 Unsplash 上的照片

对于这个问题,我们将查看预期目标统计(或 xG)。预期目标是一名球员应该进球的数量。该数值基于各种因素,例如离球门的距离、朝向球门的角度等。例如,与从 40 码外射门相比,罚球区内的机会将具有更高的 xG。简单来说,你更有可能或被期望得分的机会,被给予更高的 xG。对于这个例子,我们将从每个球员的 xG 中取得进球的差异,我们将它称为 XGDiff。如果球员表现过度,XGDiff 将为正,这表明球员的进球比预期的多。反之,负的 XGDiff 表示玩家的得分低于预期。大多数最佳射手的 XGDiff 都是正数,或者是略低于 0 的数字。在这个问题中,我们将考虑 90 后的目标,而不是目标。这个数字的计算方法是用进球数除以上场时间和 90 的商。每 90 分钟进球数表示球员每 90 分钟的进球数。这个统计更符合逻辑,因为它更容易比较一个打了 900 分钟的球员和一个只打了 300 分钟的球员的统计。这一指标带来了一个更加公平的竞争环境,对于我们的数据集尤其有用,我们有超过 1400 分钟和低于 300 分钟的球员。因此,我们将使用每 90 个目标和每 90 个 xG 指标。我们将两者相减以得到 XGDiff。

我们可以看到卡勒姆-哈德森-奥多伊以 0.38 的成绩是整个切尔西阵容中 XGDiff 最高的。这意味着每 90 分钟,他都比预期多进 0.38 个球。

我们还可以注意到,蒂莫·韦尔纳的 XGDiff 最低,为-0.18。这意味着沃纳每 90 分钟就要比预期少进 0.18 个球。

Q.2 阵容中最倒霉的创意球员是哪些?

由以赛亚·鲁斯塔德在 Unsplash 上拍摄的照片

对于这个问题,我们将关注预期助攻指标。和预期进球类似,预期助攻是球员在一场比赛中应该得到的助攻数。导致投篮的传球被算作预期助攻。导致罚球区射门的传球比导致 40 码外射门的传球具有更高的 xA。所以和 XGDiff 类似,XADiff 是助攻数和预期助攻数之差。然而,与 XGDiff 相反,负的 XADiff 被认为比正的 XADiff 更好。一个消极的 XADiff 暗示一个球员正在创造高质量的机会,而不是由前锋/前锋完成。另一方面,积极的 XADiff 表明球员可能得到了他们可能不应该得到的助攻。继续早期的类比,一名球员提供了一个基本的侧身传球,导致 40 码的尖叫,他将获得助攻,但他在该传球中的预期助攻得分较低,导致 XADiff 为正。另一方面,一名球员提供了一个防守分裂传球,但没有被前锋完成,他将不会得到助攻,但会因此得到一个高的预期助攻得分,导致一个负的 XADiff。因此,负的 XADiff 被认为是优越的。理想情况下,大多数伟大的创造者会有一个正的或接近零的 XADiff,因为不是所有的助攻都是突然传中或传球。然而,这个指标让我们可以衡量谁是真正创造高质量机会的球员,而不是纯粹由于外部因素如糟糕的射门或出色的防守而获得助攻的球员。xA 的统计数据允许球队从不太可能的球队中发现未经加工的钻石,这些球队创造了高质量的机会,但纯粹是因为他们无法控制的因素而失望。

和 xG 类似,我们也用过每 90 助攻和每 90 xA。

我们可以看到,克里斯蒂安·普利西奇的 XADiff 最低,为-0.15。这意味着在每 90 分钟里,普利西克应该比现在多 0.15 次助攻。

另一方面,我们可以看到哈基姆·齐耶什的 XADiff 最高。这意味着每 90 分钟,哈基姆·齐耶什都会比预期多 0.24 次助攻。哈基姆·齐耶什可以说是目前切尔西阵容中最有创造力的球员之一,这证明了我之前的观点,即最好的创造者不会总是有一个负面的沙迪夫。这个指标的目的是了解谁是最不幸的创造者,那就是克里斯蒂安·普利西奇。

当我们比较整个切尔西阵容的 XADiff 和 XGDiff 时,我们可以收集关于一名球员正在经历的赛季类型的深刻见解。我已经用 Power Bi 绘制了每个玩家的 XADiff vs XGDiff。

问题 3 .哪位球员的进球得分率最高?

由 Thomas Bormans 在 Unsplash 上拍摄

进球分钟比率是指球员进球所需的分钟数。这是一个非常有用的指标来计算前锋的效率。因此,大多数顶级前锋的上场时间与进球比率都很低。为了计算上场时间与进球的比率或每球上场时间,我们用上场时间除以进球得分。

因此,我们可以看到,塔米·亚伯拉罕的每球分钟数最好,其次是奥利维尔·吉鲁,分别为 138 分钟和 145 分钟。这意味着两名球员都能够在不到 2 场比赛或不到 180 分钟的时间内进球。这是一个很好的迹象,切尔西的两名前锋每球上场时间最少。然而,令人担忧的是蒂莫·韦尔纳,他每球出场时间高达 300 分钟,这表明他需要超过 3 场比赛才能进球。

然而,这些目标包括点球目标。为了真正理解前锋的致命性,我们需要考虑除了点球之外的进球。为了找到这一点,我们从目标中减去惩罚。

最后,我们用它除以分钟数,得到每个非点球进球的分钟数。

从上图中我们可以看到,数据没有太大变化,即塔米·亚伯拉罕和奥利维尔·吉鲁的每球上场时间仍然最低。然而,你会注意到若日尼奥不再被考虑,因为他所有的进球都是点球。

感谢您的阅读。我已经从fbref.com获取了我的数据,下面的链接指向这些数据

https://fbref.com/en/squads/cff3d9bb/Chelsea-Stats

如果你有兴趣了解我的分析方法,你可以看看我的 Github 资源库和这个项目的 Jupyter 笔记本。

https://github.com/samuelvarkey/Chelsea_Analysis

如果你有兴趣了解更多,我建议你阅读来自 https://fbref.com/en/的关于预期目标和助攻的文章。你可以在 LinkedIn 上联系我:

【https://www.linkedin.com/in/samuelvarkey】T4/

祝大家新年快乐。

情感数据分析:情感识别任务的数据集

原文:https://towardsdatascience.com/analysis-of-the-emotion-data-a-dataset-for-emotion-recognition-tasks-6b8c9a5dfe57?source=collection_archive---------9-----------------------

包含展示六种不同情绪的推文的数据集。

腾雅特在 Unsplash 上拍摄的照片

你永远不会知道…如此多的情感我选择不向你展示

情感识别是一种常见的分类任务。例如,给定一条推文,你创建一个模型来分类这条推文是正面的还是负面的。然而,人类的情感由无数情感组成,不能仅仅局限于这三类。相反,大多数可用于此目的的数据集只包含两种极性——积极的、消极的,有时是中性的。

然而,最近,我偶然发现了一个由 Twitter 数据构建的新数据集,它似乎填补了这一空白。这个数据集,又名情绪数据集,包含了代表六种基本情绪的英语推特信息——愤怒、厌恶、恐惧、快乐、悲伤和惊讶。在本文中,我们将了解数据收集的背景,并对其进行一些探索。

情感分类数据集

情感数据集来自 Saravia 等人的论文CARER:Contextualized effect Representations for Emotion Recognition。作者构建了一组标签,从 Twitter API 中收集独立的英语推文数据集,这些推文属于八种基本情感,包括愤怒、预期、厌恶、恐惧、快乐、悲伤、惊讶和信任。数据已经根据他们论文中描述的方法进行了预处理。数据集被存储为 pandas 数据帧,并准备在 NLP 管道中使用。下面提供了每种情绪的数据分布和标签示例列表。

来源:https://aclanthology.org/D18-1404/

访问数据集

我们已经看到了数据集。现在让我们看看如何访问它。我将演示加载和使用数据集的两种方法。

1.直接从数据源加载数据

数据集已经可以作为熊猫数据框架使用。有一个附带的笔记本展示了如何使用它来微调一个预先训练好的语言模型进行情感分类。可以通过以下方式轻松访问它:

我们来看几个数据的统计。

data.head()

数据集|图像的前几行(按作者)

我们可以找到包含 tweets 及其相应标签的数据集的前五行。从这里,我们可以将数据集分成测试集和验证集,并训练情感分类器。做一些探索性的文本分析来理解数据也是一个好主意。我们一会儿就会谈到这个问题,但在此之前,让我向您展示另一种加载数据集的方法。

2.从拥抱脸下载数据🤗数据集中枢。

拥抱脸数据集库提供 API 下载公共数据集和预处理很容易。你可以参考这个关于 Huggingface 数据集的视频来开始。

HuggingFace datasets Hub 主页 |来源:hugging face 网站

我们将首先下载数据集库并导入必要的模块

!pip install datasets
from datasets import load_dataset

emotion_dataset = load_dataset("emotion")

这将创建一个 emotion_dataset 对象。

emotion_dataset

情感 _ 数据集对象|作者图片

我们得到的是一个字典,每个键对应一个不同的拆分。让我们访问培训数据以查看其内容。

emotion_train = emotion_dataset['train']
print(emotion_train[0])
print(emotion_train.column_names)
print(emotion_train.features)

训练数据集|按作者分类的图像

训练数据集包括六个不同的类别——悲伤、快乐、爱、愤怒、恐惧和惊讶。

将情感数据集转换成熊猫数据帧

我们现在可以很容易地将上述数据集转换成熊猫数据框架,并对其进行进一步分析。

import pandas as pdemotion_dataset.set_format(type="pandas")
train = emotion_dataset["train"][:]
test = emotion_dataset["test"][:]
val = emotion_dataset["validation"][:]

让我们快速检查一下转换是否成功。

train.head()

训练数据集|作者图片的前几行

是的,的确!现在您知道如何从 Huggingface 数据集中心访问数据集了,这是您的数据科学技能的又一项提高。那么当你有了数据后你会怎么做呢?你探索它,这正是我们在下一节要做的。

情感数据集的探索性数据分析

我们将从导入必要的库和可视化数据开始。正如我们已经知道的,数据已经过预处理,所以这是一个额外的收获。我们通常会从数据集和推文长度的不平衡入手。除此之外,请随意深入研究。

笔记本跟随一起: 情感数据集的探索性数据分析

创建带有标签名称的列。

标签列当前有个整数。为了更容易理解,我们将创建一个名为description的新列,包含标签列中每个整数的描述。

作者图片

描述列的分析

现在,我们来分析一下description列是什么样子的。我只使用了训练数据集,但如果我们希望对测试数据集也这样做,过程将保持不变。

每种情绪的例子

让我们来看看每种情绪的例子。

按情绪分类的各种推文示例|按作者分类的图片

训练集中标签的分布

看看标签的分布会很有帮助。这也将让我们了解数据集中的不平衡,如果有的话。

train['description'].value_counts(normalize=True)

sns.countplot(train['description'],order = train['description'].value_counts(normalize=True).index)

数据集|图像中目标列的分布(按作者)

大约 33%的推文是快乐的,其次是悲伤和愤怒的推文。

分析文本统计

我们现在可以做一些统计分析来探索文本数据的基本特征。一些有用的分析如下:

  • 文本长度分析:计算文本的长度
  • 词频分析:计算单字、双字和三元字的字数。
train['text_length'] = train['text'].astype(str).apply(len)
train['text_word_count'] = train['text'].apply(lambda x: len(str(x).split()))

推文长度分析

sns.distplot(train['text_length'])
plt.xlim([0, 512]);
plt.xlabel('Text Length');

推文长度分析|作者图片

上面的直方图显示,推文的长度从 2 到 300 个字符不等。

推文字数分析

现在让我们来分析每类推文的词频。

sns.boxplot(x="description", y="text_word_count", data=train)

推文字数分析|作者图片

大部分推文平均 15 个字。此外,所有推文的长度似乎都差不多。因此,推文的长度并不是极性的有力指标。

顶级 n-grams 的分布

一个 n -gram 是来自给定文本或语音样本的 n 项的连续序列。查看各种 n 元语法来了解哪些单词主要一起出现也是一个好主意。例如,我们观察单字母词、双字母词和三字母词在各种情绪——悲伤、愤怒和爱——中的分布。

悲伤类推文|作者图片

愤怒类别的推文|作者图片

来自“爱情”类别的推文|作者图片

接下来呢?

既然我们已经对数据集做了一些初步的探索,接下来就是使用这个数据集来创建一个情感分类器。这可能是一个很好的项目,可以添加到你的简历中,你也可以与社区分享你训练过的模型。如果你想快速旋转笔记本来浏览数据,我现在已经在 Kaggle 上提供了。

https://www.kaggle.com/parulpandey/emotion-dataset

印度学校制度分析

原文:https://towardsdatascience.com/analysis-of-the-indian-education-system-388f7ad8c68f?source=collection_archive---------15-----------------------

教育空间中若干因素的不同状态比较

来源

背景

印度是文化、传统和价值观的大熔炉。这个拥有 10 多亿人口的次大陆拥有 36 个邦和联邦直辖区的公民。教育质量不仅受到不同教育委员会的影响,还受到不同的普遍社会经济因素的影响。

我在一个安静的小镇上一所美丽的基督教兄弟学校长大。完成学业后,我在印度的几个不同地方呆过,这让我接触到了不同的背景和不同的教育实践。

正如任何问题都可以通过在基层工作得到最有效的解决一样,我相信,一个国家可以通过改善未来领导人学习的学校来实现可持续和稳定的发展。

介绍

在这个项目中,我比较了各邦的以下因素,以了解印度教育系统中普遍存在的差距:

  • 女孩和男孩的辍学率
  • 学校不同部门的辍学率
  • 女孩和男孩的入学率
  • 学校不同部门的入学率
  • 学生与教师的比率
  • 存在不同的因素,如电力、男女厕所等。

小学:一至五年级
高级小学:六至八年级
中学:九至十年级
高级中学:XI 至十二年级

分析

辍学率和入学率

作者图片

观察:

  • 随着我们进入学校更高的部分,入学率下降,高中入学率从小学的 100%以上急剧下降到 60%。
  • 与其他邦相比,两个中央直辖区----拉克沙威和查谟-克什米尔----的早期教育入学率特别低。
  • 辍学率最高的是中学,而不是高中,因为入学率已经很低了。

85%的中学注册学生中约有 15%辍学。这导致只有 72%的学生留在 x 班。这成为他们的最高学历。

但是,把它看成点估计是不对的。相反,我们应该把它看作一个范围估计:它大多在 60%到 83%之间。它根据州的不同变化很大。

  • 我们还需要检查性别是否是入学和辍学的一个因素。

作者图片

观察:

  • 男孩的入学率较低,辍学率较高

在印度农村,父母一让他们的男孩到了可以挣钱的年龄就去工作,带些钱回家。这可能是男生辍学率略高的原因。还有,也许父母不愿意教育女孩,而是把她们嫁出去。值得注意的是,女孩的辍学率高于男孩。因此,即使男孩的辍学率更高,女孩的辍学率也会受到异常值的影响。

学校不同部门的学生与教师比例

观察:

  • 学生与教师的比例最高的是高中。
  • 中学也缺乏教师。合格教师的缺乏可能是因为学校无法用微薄的工资吸引合格的候选人。
  • 像北方邦、比哈尔邦、恰尔肯德邦和 WB 邦在这方面做得很差。

学生在中学受到的关注较少。这种情况在高中阶段更加严重。这些是导致初中和高中辍学率较高的重要因素。

总体情况

学校教育中的不同因素

观察:

  • 超过 50%的州至少有 92%的学校有饮用水
  • 与电力相比,更多的学校有饮用水
  • 拥有计算机设施的学校比例很低
  • 与男生厕所相比,有女生厕所的学校比例更高

学校各科不同因素对比:

出现在学校不同部分的特征的平均百分比:

观察:

从小学高年级到中学,厕所数量急剧减少,但饮用水供应却没有减少多少。也许学校没有建立卫生厕所的基础设施。厕所里没有水可能是一个原因。

同样令人惊讶的是,中学的电力供应最低。另外,请注意,在小学高年级和高中阶段,计算机的比例有所下降。

农村地区的大多数学校只有教到中学(十年级)的设施。在这些上层阶级中,学校缺乏良好的设施。学生辍学去找工作使情况更加恶化。因此,没有足够的需求来改善这些学校的中学部分的条件。

假设检验

我们对数据进行了探索性分析。通过假设检验,我们可以得到结论性的结果。

拒绝传统社会的人

我们进行 t 检验以获得:

t,p = (-0.9810354738258853,0.3282807268)

因此,我们不能拒绝 Ho。

女孩和男孩的辍学率没有什么不同。

学校的部门

我们进行 ANOVA 测试以获得:

f 统计=45.282,p=0.000

因此我们拒绝 Ho。

学校不同部门之间的辍学率有很大差异。

注册

我们进行 t 检验以获得:

t,p = (0.8775733057976992,0.384163598124)

因此,我们不能拒绝 Ho。

女孩和男孩的入学率没有差别。

学校的部门

我们进行方差分析测试以获得:

f 统计=58.335,p=0.000

因此我们拒绝 Ho。

学校不同部门的入学率有很大差异。

学生与教师的比率

我们进行方差分析测试以获得:

f 统计=12.850,p=0.000

因此我们拒绝 Ho。

学校不同部门的学生与教师的比例有很大差异。

其他因素

我们做了χ2 检验,以评估学校和不同因素的存在之间的独立性。

χ2 检验的结果:

在 12 个自由度上 p = 0.0054。

因此我们拒绝 Ho。

不同因素的存在取决于学校的区域。

假设检验概述

  • 男孩和女孩的辍学率和入学率没有差别。
  • 学校不同部门的辍学率和入学率不同。
  • 学生与教师的比例在学校的不同部门是不同的。
  • 不同因素的存在取决于学校的各个部门。

可视化状态性能

我们可以将数据可视化到 3D。我做了主成分分析来找出解释最大方差的成分。这样,我们可以缩小维度,同时合并来自更高维度的数据。

进行 PCA 的检验统计量:
KMO 统计量:0.61
p(Bartlett 球形度检验):0

让我们找到这些更广泛的特征。
三个主要成分的因子载荷:

观察结果:

  • PC1 解释了学校中不同因素的存在
  • PC2 解释了学校不同部门的师生比例
  • PC3 解释了学校不同部门的入学情况(以及间接的辍学情况)

这三个因素被用来创建非等级聚类。用 3 个聚类(这里 0=2)获得最大轮廓分数。

可视化集群:

不同聚类的平均值

解读

集群 0: 失败者
缺乏因素;生师比低,升学率高,这两点都值得称道。
这一组州具有最大的潜力,我们应该首先关注改善这一组中学校的因素。

集群 1: 特权阶层
要素存在率高,学生:教师比率最低。尽管有一些有利因素,这个群体的入学率并不是最高的。当我们看辍学与入学散点图时,这一点就变得很清楚了。这些州的辍学率远远高于平均水平。这可能是由于社会政治、文化和其他原因造成的,这些原因没有被学校系统的特点所解释。

群组 2: 缺席教师 在这个群组中,学生与教师的比率非常高,这反映在最低的入学率上。我们需要为这个集群中的学校配备教师。

结论

造成各州教育部门绩效差异的主要因素有:

  • 中学辍学者
  • 高中入学率
  • 学校里有电和电脑

进一步研究

下一个大的创业公司被认为是教育公司。我相信他们会改进现有的基础设施,而不是营销新产品。根据帕累托原则,80%的收益来自于关注 20%的问题。需要弥补中学阶段的差距。我们需要努力降低中学的辍学率。

行动呼吁

  • 第三集群各州人员配备合格教师:
    具体要求:
    1。政府必须缩小公立和私立学校之间的薪酬差距来吸引人才。
    2。应该允许教育部门中为资金不足的学校配备人员的主要非政府组织将其研究员/实习生转为长期职位。
    3。许多工程师失业了。他们学了很多数学和科学。他们可以被重新训练成为熟练的教师。
    可衡量的目标:

印度与世界的学生:教师比率

印度的学生与教师的比例在中学应该达到 19,在高中应该达到 23。

假设时间框架: 3 年。

  • 教师是确保学习成果的最重要的因素。教学质量需要评估。
    具体要求:
    如此处所述,必须按照全球标准建立新的指标。
    可衡量的目标:
    假设时间框架:3 年
  • 通过确保第一组的电力供应,改善学校设施。
    具体要求: 提高学校用电比例
    可衡量目标:

假设时间框架:3 年

这些任务并不简单,需要在城镇和农村地区的基层做大量的工作。

  • 通过与这些州(主要是东北部各州)的教师和家长进行有针对性的小组讨论,了解是什么导致了第二组的高辍学率。

数据

https://www.kaggle.com/aman139/indian-school-education-data

MHRD 数据:https://www . education . gov . in/sites/upload _ files/mhrd/files/statistics-new/ESAG-2018 . pdf

其他参考:

https://www . India today . in/education-today/news/story/15-initiatives-taked-by-central-government-to-improve-teaching-standards-in-India-HRD-minister-1556357-2019-06-26

全球基准:

https://data.worldbank.org/indicator/SE.SEC.ENRL.LO.TC.ZS https://data.worldbank.org/indicator/SE.SEC.ENRL.TC.ZS https://data.worldbank.org/indicator/SE.SEC.ENRL.UP.TC.ZS

用 Python 进行方差分析——ANOVA

原文:https://towardsdatascience.com/analysis-of-variance-anova-8dc889d2fc3a?source=collection_archive---------19-----------------------

用 Python 实现大学统计

介绍

在一系列的每周文章中,我将会涉及一些重要的统计学主题。

目标是使用 Python 来帮助我们获得对复杂概念的直觉,从经验上测试理论证明,或者从零开始构建算法。在本系列中,您将会看到涵盖随机变量、抽样分布、置信区间、显著性检验等主题的文章。

在每篇文章的最后,你可以找到练习来测试你的知识。解决方案将在下周的文章中分享。

迄今发表的文章:

  • 伯努利和二项随机变量与 Python
  • 用 Python 从二项式到几何和泊松随机变量
  • 用 Python 实现样本比例的抽样分布
  • Python 的置信区间
  • 使用 Python 进行显著性测试
  • 用 Python 进行组间差异的双样本推断
  • 分类数据的推断
  • 高级回归
  • 方差分析— ANOVA

像往常一样,代码可以在我的 GitHub 上找到。

逐步方差分析

我们再一次用数据科学家的薪水工作。在这种情况下,我们对基于一些独立特征预测工资不感兴趣。我们重点了解具有不同背景的 3 组数据科学家的平均工资是否存在差异:第一组是来自计算机科学专业毕业生的样本,第二组是经济学专业毕业生的样本,第三组是信息工程专业毕业生的样本(请注意,工资单位是 10,000€)。

图 1:数据科学是结合了领域专业知识、编程技能以及数学和统计知识的研究领域,用于从数据中提取有意义的见解;来源

import pandas as pd
import numpy as np
from scipy.stats import fdf = pd.DataFrame.from_dict({'g1': [5,9,10,12,8,8,9], 
                        'g2': [5,4, 4, 5,5,4,8], 
                        'g3': [9,8, 5, 6,7,7,6]})

df

表 1:不同背景的 3 组数据科学家的万人薪酬。

执行 ANOVA 测试的第一步是计算 SST(总平方和)、SSW(总内平方和)、SSB(总间平方和)以及相应的自由度。他们计算如下:

  • SST 是每个数据点和数据集平均值之间的平方距离之和。在这种情况下,自由度是组数 m 乘以每组中数据点数 n ,然后我们减去 1,即 mn-1。
  • SSW 是每个数据点和相应组平均值之间的平方距离之和。自由度是组数乘以数据点数减 1,即 m(n-1)。
  • SSB 是每个组平均值和每个数据点的数据集平均值之间的平方距离之和。自由度是组数减 1,即 m -1。
m = df.shape[1]
n = df.shape[0]SST = np.sum(np.sum((df - np.mean(np.mean(df)))**2))
SST98.57142857142858df_sst = m*n-1
df_sst20SSW = np.sum(np.sum((df - np.mean(df))**2))
SSW50.28571428571429df_ssw = m*(n-1)
df_ssw18SSB = np.sum(np.sum((np.tile(np.mean(df), (3,1)) - np.mean(np.mean(df)))**2))
SSB20.6938775510204df_ssb = m-1
df_ssb2

假设检验

让我们定义我们的假设检验。我们的零假设是背景没有影响的情况。相比之下,我们的另一个假设是,背景会影响数据科学家的薪酬。

像往常一样,我们将假设我们的零假设是正确的,并计算出得到一个极端统计数据或比我们从观察到的数据得到的数据更极端的概率。为此,我们将使用 F 统计量,它基本上是两个卡方统计量的比率。它实际上是上面计算的两个指标除以各自自由度的比率:

这个想法是,如果分子明显大于分母,这应该让我们相信,在真正的人口均值之间存在差异。相反,如果分母明显较大,则意味着与样本之间的差异相比,每个样本内的差异占总差异的百分比较大。因此,我们可以观察到的任何均值差异可能只是随机的结果。

F = (SSB/df_ssb)/(SSW/df_ssw)
F3.703733766233764f.ppf(0.95, dfn=df_ssb, dfd=df_ssw)3.554557145661787

现在,我们可以计算我们的 p 值。让我们使用 0.1 的显著性水平。

p_value = (1 - f.cdf(F, dfn=df_ssb, dfd=df_ssw))*2
p_value0.08991458167840971if p_value<0.1:
    print('Reject H_0')
else:
    print('Accept H_0')Reject H_0

我们看到 p 值小于显著性水平,这使我们拒绝零假设。有足够的证据来接受群体间均值的差异,这种差异并不仅仅来自于偶然或每个群体内的差异。说了这么多,我们可以得出结论,一个数据科学家的工资是不同的,取决于毕业背景。

结论

本文介绍了方差分析(ANOVA),这是一组比较不同组的多个平均值的方法。我们还引入了一个新的统计量,称为 F 统计量,我们用它来对我们组的均值差异进行假设检验。

这是“使用 Python 进行大学统计”系列的最后一篇文章我希望你喜欢它!

保持联系: LinkedIn

上周的答案

  1. Márcia 收集了便携式电脑随机样本的电池寿命和价格数据。根据下面提供的数据,总体斜率为 0 的零假设的检验统计量是什么?
data = {'Intercept': [200.312, 92.618],
             'Battery': [7.546,4.798]}df = pd.DataFrame.from_dict(data, columns=['Coef', 'SE Coef'], orient='index')
df

t = (df['Coef'][1]-0)/df['SE Coef'][1]
t1.5727386411004585

2.芮随机抽取了一些同事,注意到他们的年龄和他们昨天步行的公里数成正比。回归线斜率的 95%置信区间为(15.4,155.2)。芮想用这个区间在 5%的显著性水平上检验 H_0: β=0 vs. H_1: β ≠ 0。假设推断的所有条件都已满足。芮应该得出什么结论?

芮应该拒绝 H_0,即数据提示年龄和昨天走的公里数成线性关系。

“分析师 2.0”会是什么样子?

原文:https://towardsdatascience.com/analyst-2-0-3c10daf124c8?source=collection_archive---------3-----------------------

最新一代分析师将改变游戏规则。

分析师从一开始就一直是我们数据团队的稳定成员,但可悲的是,近年来他们的角色和声誉一直在下降。如果我们要在新的分析时代取得成功,在这个时代,我们被期望将我们的数据转化为行动,我们必须扭转方向,重新发现谦逊的分析师的角色。

今日分析师

当前分析师的化身诞生于“洞察时代”。向企业交付数据的主要方式是小心地将数据打包成仪表板、图表或报告之类的东西。这是分析师的领域,一切都很顺利……有一段时间。

首先,我们的行业经历了一个高度专业化的阶段。数据管道被分割,分配给新的职位,如数据工程师,或者最近的分析工程师。曾经享有大量管道的分析师们发现自己被四面八方排挤。

图片由伯爵提供。

随着专家数据角色成为标准,纯粹的分析师在数据社区和我们的业务合作伙伴眼中的地位下降了,实际上将分析师变成了初级角色。这使得曾经稳定的业务分析师合作关系变成了建立在任务和等级制度基础上的不稳定关系。

当我在一家大公司担任数据分析师时,我们非常强烈地感觉到我们的头衔在拖累我们,以至于有一天我们都被提升为数据科学家。这是在没有任何培训的情况下完成的,没有改变我们的期望或工作方式。这纯粹是为了在我们试图影响的更广泛的企业中赢得更多的尊重和信任。

这种耻辱超越了团队动力。2020 年,数据分析师每年获得的经验比他们的数据科学或数据工程同行少[1],消除了任何分析师对我们在这个行业中的价值的怀疑。

今天的分析师只剩下一个选择:专业化或者死亡

多年的编码经验与数据专业人员(标记为其他开发人员角色)的平均工资。圆圈大小表示调查对象的数量。(分析链接 ) ( 调查链接)

利害攸关的是什么?

值得停下来提醒我们自己为什么这是一个如此危险的最后通牒。答案是双重的:

  1. 只有当数据对业务清晰、有用且可操作时,数据堆栈才是成功的。
  2. 从本质上讲,分析师是他们所服务的组织理解、消费和使用数据的主要方式。

我们可能拥有一流的数据模型、超高性能的数据库,甚至是最先进的数据应用程序,但是如果没有一个分析师能够将这些信息整合到业务中,那就毫无意义。

削弱分析师的作用只会削弱数据在任何组织中的作用。

最后一英里

我们需要一个更大版本的分析师角色。

以前,我们认为数据堆栈的端点是输出(例如,图表、仪表板或报告)。我们越来越认识到这些媒介在更复杂的决策和解决问题中的局限性。我们必须超越“见解”,进入“行动”。

我们正在为分析工作流程的最后一步配音,从洞察到决策,“最后一英里”。如果分析师要继续成为数据堆栈向业务交付价值的方式,那么这就是他们必须称之为自己的空间。

图片由伯爵提供。

此外,如果他们想拥有这个空间,他们必须发展一套新的技能和习惯,以适应最后一英里的挑战。

分析师 2.0

分析师已经具备了最后一英里分析所需的许多特质,包括强大的数学基础和良好的数据沟通技能。然而,适应这片新土地需要一些关键技能:

1.专家翻译

在我看来,这是当今分析师最容易被忽视的技能。最成功的分析师能够无缝弥合数据和业务之间的差距。他们将数据带入业务问题的背景中,确保团队不仅能立即理解图表的内容,还能理解对他们的意义。他们可以轻松地将模糊的业务需求转化为上游数据需求,从而节省整个团队的返工时间。

在未来,这将不仅仅是一个天才分析师的“秘方”,而是所有分析师都认同和培养的技能。

2018 年,麦肯锡强调了这种翻译技能的必要性,建议它甚至应该成为自己的[专门]角色:

“在他们的角色中,[分析]翻译者帮助确保通过复杂的分析产生的深刻见解转化为对组织的大规模影响。麦肯锡全球研究所估计,到 2026 年,仅美国对翻译的需求就可能达到 200 万到 400 万。- 麦肯锡 (2018)

虽然我同意这种观点,但我认为未来的分析师将满足行业对有效翻译的需求。

2.决策促进

随着决策变得越来越复杂,我们需要越来越多的数据。查看数据来帮助决定我该做什么需要对我们的方法有更细致入微的理解。

看着 A/B 测试结果的仪表板,自信地说你的解释没有偏见,你不是在一个设计糟糕的实验中做决定,或者小样本量对任何人来说都几乎是不可能的,更不用说一个时间紧迫的高管了。(这篇网飞系列的文章是一个很好的例子,说明了这可能是如何工作的。)

分析师处于独特的地位,可以专业地帮助指导在这些复杂的决策中使用数据。这意味着他们将对组织内数据的使用负责任和合乎道德——目前这还是一个方便的无人区。

这些讨论不仅促进了数据使用的改进,还促进了数据使用的更加可信——如果数据要在我们的商业决策中发挥更大的作用,这是不可或缺的。

酷,但是接下来呢?

重新定义分析师的角色不会在一夜之间发生。这是一个渐进的变化,我相信它已经开始了。有了指标层,分析师和他们的业务合作伙伴将拥有比以往更大的自主权来使用数据推动决策,但他们将需要帮助来有效地做到这一点。

跨越最后一英里可能需要分析师学习新技能和采用新工具。我们还需要考虑我们的组织和团队如何适应新的工作方式。简而言之,在最后一英里,我们不缺少挑战,也不缺少机遇。

,我们正在为数据驱动的决策时代而建设。订阅了解更多关于 M 矿石而非数字 未来的挑战和机遇。

参考

[1] 2020 年开发者调查。斯塔科弗洛。https://insights.stackoverflow.com/survey/2020#overview

分析散列技术

原文:https://towardsdatascience.com/analytical-hashing-techniques-5a0393f3fc1c?source=collection_archive---------11-----------------------

Spark SQL 函数简化您的生活

图片来源:https://unsplash.com/@swimstaralex

在分析和机器学习领域工作的任何人最终都需要为他们正在处理的数据生成强大的复合分组键和幂等标识符。这些加密的强标识符有助于减少执行复杂的存储、重复数据删除和一系列其他重要任务所需的工作量。

我们将看看生成散列的两种方法:

  1. 使用 Base64 编码和字符串串联
  2. 使用杂音哈希和 Base64 编码

Spark SQL 函数

核心 spark sql 函数库是一个预构建的库,包含 300 多个常用 sql 函数。然而,查看函数索引并简单地列出事情并不像运行代码本身那样令人难忘。如果您有火花壳,那么您可以继续学习一些分析散列技术。

旋转火花

$SPARK_HOME/bin/spark-shell

上图:参考我的 Shell 环境

spark-shell 启动并运行后,您可以通过运行来执行下一步:在 shell 中粘贴来粘贴 multiline。 *(:粘贴,然后粘贴代码,然后 cmd+D 处理代码)

导入库和隐式

import org.apache.spark.sql._
import org.apache.spark.sql.functions._
import org.apache.spark.sql.types._
import spark.implicits._

创建数据框架

val schema = new StructType()
  .add(StructField("name", StringType, true))
  .add(StructField("emotion", StringType, true))
  .add(StructField("uuid", IntegerType, true))val df = spark
  .createDataFrame(
    spark.sparkContext.parallelize(
      Seq(
        Row("happy","smile", 1),Row("angry", "frown", 2))
      ),
      schema
    )

此时,您应该有了一个非常简单的数据框架,现在可以对其应用 Spark SQL 函数。使用 df.show() 显示其内容。

scala> df.show()+-----+-------+----+
| name|emotion|uuid|
+-----+-------+----+
|happy|  smile|   1|
|angry|  frown|   2|
+-----+-------+----+

现在我们有了一个简单的数据框。接下来,我们可以简单地通过使用 withColumn 函数并传入我们想要使用的 Spark SQL 函数,向数据帧添加一个 base64 编码器列。

哈希字符串

Base64 编码的字符串值

val hashed = df.withColumn(
  "hash", base64(
    concat_ws("-", $"name", $"emotion")
  )
)

这个转换的结果产生了一个新列,它是对来自列 nameemotion 的串联字符串值进行 base64 编码的结果。这被分解为以下流程。

df.withColumn("concat",
  concat_ws("-",$"name",$"emotion"))
  .select("concat")
  .show+-----------+
|     concat|
+-----------+
|happy-smile|
|angry-frown|
+-----------+

完整列表达式的最终结果如下。

scala> hashed.show()
+-----+-------+----+----------------+
| name|emotion|uuid|            hash|
+-----+-------+----+----------------+
|happy|  smile|   1|aGFwcHktc21pbGU=|
|angry|  frown|   2|YW5ncnktZnJvd24=|
+-----+-------+----+----------------+

很好。没错。

下一个。我们可以考虑一种更强的散列技术。这使用 Murmur3 哈希算法,并在输入 base64 编码器之前进行显式二进制转换。

杂音散列和二进制编码

有许多方法可以生成散列,散列的应用可以从分桶到图的遍历。当你想创建强散列码时,你可以依靠不同的散列技术,从循环冗余校验(CRC) ,到高效的杂音散列(v3) 。我们将在 Spark 中使用我们可以免费获得的东西,即 Murmur3。

hashed.withColumn("binhash",
  base64(bin(hash($"name",$"emotion")))
)
.select("uuid", "hash", "binhash")
.show(false)

这将基于相同的输入数据返回下面的行(比较两种散列方法)。

+----+----------------+--------------------------------------------+
|uuid|hash            |binhash                                     |
+----+----------------+--------------------------------------------+
|1   |aGFwcHktc21pbGU=|MTAxMTEwMDAxMTAwMDAwMTAwMDAwMDEwMTExMDAxMA==|
|2   |YW5ncnktZnJvd24=|MTEwMTAwMDEwMTExMTExMDEwMDAwMDExMDAxMTAxMA==|
+----+----------------+--------------------------------------------+

查看 Spark 代码生成

如果你想知道 Spark 在幕后是如何工作的,那么解释函数有一个很棒的新特性,可以让你查看 Spark 为你的转换生成(并优化)的代码。要查看这一点,您需要做的就是下面的事情。

hashed.withColumn("binhash",
  base64(bin(hash($"name",$"emotion")))
)
.select("binhash")
.explain("codegen")

这将输出 java 代码并解释更多关于计算的内容。

上图:查看 Spark 代码生成

这段代码是 Spark 的 Catalyst Optimizer 的一部分,幸运的是,你很有可能永远不会在这个较低的级别上工作,很有可能继续你的生活。但是,如果您正在编写定制的数据源读取器和写入器,那么这可能是您想要深入研究的内容。如果没有别的东西可以让你了解更多关于底层机制的知识,在上面的用例中,codegen 详细说明了正在使用的 brunh hash 库的用法。对于调试和那些只想在 360 度模型中学习的人来说,这是一个很好的工具。

摘要

现在,您还有两种技术可以用来创建强组合键,或者用作创建幂等键的跳板。我只是觉得分享这些技术会很有趣,因为它们很方便,并且可以重用 side Spark 附带的核心库。愉快的旅行。

作为决策过程基础的分析

原文:https://towardsdatascience.com/analytics-as-the-basis-of-the-decision-making-process-da3453c1637a?source=collection_archive---------26-----------------------

最聪明的管理方式

约翰·施诺布里奇在 Unsplash 上的照片

几乎所有的决定都是在面临不确定性的情况下做出的,因为很少情况下我们拥有所有的信息来做出毫无疑问的决定。我们都知道,不确定性是任何组织生活中的固有元素,它是威胁和机会的来源,可以破坏或创造价值。

然而,确定一个可接受的不确定性程度以最大化价值创造是所有时代的管理者必须面对的主要挑战之一。

基于数据分析的决策是一种“新”的管理形式,它使我们能够更有效地应对这些威胁和机遇,增加管理层的信心,并显著提高公司的价值创造能力。

要理解这种“分析”形式的管理是如何工作的,了解两个简单的定义很重要。

首先是模型的概念,模型可以有各种类型:业务模型、流程模型、预测模型……,但最终所有模型都有相同的目的,它们用于更好地理解问题和做出更好的决策。

照片由阿姆利·莫里雄在 Unsplash 拍摄

另一个要考虑的重要定义是决策分析(DA)。它是一种系统的、定量的和图形化的方法,通常用于评估多个有时是复杂的选项。

处理某些困难决策的一种方法是通过结合这两个先前的定义,这将我们带到众所周知的决策模型,这些模型结合了心理学、管理技术、统计学和经济学的各个方面来定义决策中的最佳选择。

请记住,模型并不代表现实。英国统计学家乔治·e·p·博克斯说:

“所有模型都是错的,但有些是有用的”。

这句格言是一个伟大的真理,因为最好的模型是现实的模糊近似,但它们对于理解问题和分析替代方案非常有用。

另一方面,任何决策模型的成功都必须有两个主要参与者,他们不一定是个人,但可以是工作团队。

一个是决策者,通常由公司的经理或董事代表,另一个是数据分析师或数据科学家,他们负责建立模型,并在整个决策过程中支持经理。

因此,数据分析师必须能够理解流程或业务模型,并将其与适当的定量方法相结合,以便尽可能地代表决策的本质。和往常一样,这应该在相对较短的时间内完成。

在 Unsplash 上由 Austin Distel 拍摄的照片

由于决策者和数据分析师之间的差异,在定义最适合决策的模型时经常会出现误解。

如果经理与分析专家密切合作,开发一个简单的模型,允许初步了解决策中涉及的主要因素,就可以避免这些缺点。在经理熟悉这个模型后,可以逐步添加更多的细节和更复杂的东西,直到达到期望的满意度。

一些最常见的因素使得有必要将更多的细节合并到一个模型中,这就是拥有多目标决策的事实。

当有两个或两个以上的目标时,很多时候它们会相互冲突,也就是说,一个战略对于一个目标来说可能是最优的,但对于其他目标来说可能是最差的选择。这种决策问题必须通过更复杂的分析模型来评估,例如“多目标优化”

照片由亚当·诺瓦克斯基在 Unsplash 上拍摄

这种类型的决策分析过去专门用于评估涉及多个变量或具有许多可能的结果或目标的困难决策,例如在采矿或石油和天然气项目中经常观察到的那些决策。幸运的是,新技术现在允许随时获得大量信息,以及多种分析方法的结合,这有助于在任何行业的任何类型的决策中使用这些技术。

不管决策的复杂性如何,涉及主要参与者的模型的渐进构建是敏捷和灵活的过程开发中最重要的因素,这种过程会导致成功的决策。

数据分析应被视为任何决策过程中不可或缺的一部分,在一些国家,这甚至开始逐渐被纳入公司的新法规中。如果公司的信息系统必须是完全可访问和可审计的,并且如果需要,必须向技术委员会提交一份包含项目细节的完整报告。

使用数据分析来支持决策不应被视为组织敏捷性的障碍,相反,这是改善业务控制、提高生产力和利润以及规划未来更成功战略的最有效管理形式。

分析工程师:最新的数据职业角色

原文:https://towardsdatascience.com/analytics-engineer-the-newest-data-career-role-b312a73d57d7?source=collection_archive---------4-----------------------

办公时间

是分析吗?是工科吗?这些人是做什么的?

由布鲁克·拉克在 Unsplash 拍摄的照片

几个月前,我决定正式开始转行,寻找一份新工作。在数周浏览 LinkedIn 上的招聘信息,试图找到一个让我最感兴趣的角色后,我一直注意到一个模式。

当我还是一名数据工程师时,我希望有更多的机会发挥创造力,并与业务团队密切合作。我的技能不太适合数据分析师,但我也不想扮演传统的数据工程师角色。

就在那时,我遇到了分析工程师。

所有吸引我的招聘信息都是这个角色的。我以前从未听说过它,但我很感兴趣。碰巧的是,这个职位完美地结合了我已经拥有的工程技能和我想要的商业经验。

这些技能看起来像什么?

  • 结构化查询语言
  • 计算机编程语言
  • dbt
  • 数据可视化
  • 强大的沟通能力

先说一个分析工程师的主要技术和工具。一名成功的分析工程师最重要的素质之一是强大的 SQL 技能。你需要编写大量的查询和数据模型,所以在面试这个角色之前,你必须练习,练习,练习所有类型的聚合和窗口函数。如果你在准备这些类型的编码面试时需要帮助,请查阅顶级技能,在每一次 SQL 面试中胜出。

同样重要的是,你有用 Python 写代码的经验。分析工程师通常比典型的数据分析师拥有更多的编码知识。他们可能不一定知道像 Javascript 和 C++这样的软件工程语言,但他们知道除了 SQL 之外的更高级的“数据”语言。Python 非常通用,用于分析工程师接触的大多数数据编排服务和数据科学模型。

下一个是一个大的。公司通常会寻找曾经使用过 dbt 工具的人。不确定这是什么?我写了一整篇帖子解释这个工具及其使用方法。创建 dbt 的公司本质上是塑造分析工程师角色的同一家公司!没有 dbt 就没有分析工程。它们携手并进。

像数据分析师一样,分析工程师也应该有创建有影响力的数据可视化的经验。重要的是,您可以将数据中的任何发现传达给业务团队。如果分析不容易理解和执行,那么它有什么用?没有一个工具比另一个突出,但是你必须熟悉不同的工具。

核心职责是什么?

你可以把分析工程师想象成管理公司数据堆栈的人。虽然根据公司的规模大小而有所不同,但许多职责包括以下内容。

  • 数据建模
  • 数据仓库管理
  • 数据编排
  • 设定最佳实践
  • 交叉协作

想想 ETL(提取、转换、加载)过程;这就是你作为一名分析工程师所能控制的。您将实现和管理一个数据仓库,如雪花,以摄取您的数据。您将决定将不同来源的数据接收到该仓库的最佳工具。您将对分析师使用的数据进行建模,并安排运行来简化这些模型。

数据建模是日常工作的一大部分。如果你不确定数据建模到底需要什么,看看我写的这篇文章的吧。

分析工程师做的很多事情都是从零开始构建一个全新的数据生态系统。如果你想掌控一个大型项目,并真正改变一家公司使用其数据的方式,这个角色非常适合你。

到目前为止我学到的是

我只做了 3 个月的分析工程师,已经学到了很多。我设计并实现了我们的雪花架构,它是我们所有数据的一站式商店。我在 dbt 中彻底检查并重建了我们的许多核心数据模型。现在我正在使用 AWS Fargate 和 Prefect 部署这些模型。

如果这些职责听起来对你有吸引力,我强烈建议你去看看分析工程师的招聘信息。不要让一个陌生的头衔吓跑了一个可能非常适合你的角色!

更多关于分析工程和现代数据堆栈的信息,订阅我的免费每周时事通讯。

数据科学的分析基础

原文:https://towardsdatascience.com/analytics-essentials-for-data-science-25da994f4bed?source=collection_archive---------17-----------------------

让数据变得有意义的基础

Robynne Hu 在 Unsplash 上的照片

虽然 Excel 的魔法可能适合许多分析任务,数据科学工作严重依赖编程的细微差别再现性可扩展性从只能在专门的 R 和 Python 库中使用的统计测试,到能够一步一步地展示模型是如何制定和生成预测的,再到能够通过几个按键从处理一个数据集到处理 1000 个数据集, 流畅的编程对于成为一名高效的数据科学家至关重要。

因此,我们将重点关注编程技能,这是有效操作和分析数据的关键。无论你在分析-工程光谱中处于什么位置,这些技能都应该是有用的。

虽然许多数据科学角色只依赖于 R,但这篇文章将展示 Python 的编码概念。Python 的多功能性使其成为一种“一体化”语言,适用于大量的数据科学应用,从数据帧处理到语音识别和计算机视觉 T21。即使你的角色需要在 R 中整天处理数字,也可以考虑学习一点 Python 来自动完成像将结果保存到你公司的 Dropbox 这样的步骤。

这篇文章假设你熟悉 Python 基础知识。如果没有,请查看真实 Python 和 Codecademy 中的重要资料。我们将涵盖以下概念:

  • 数据帧
  • 数组
  • 形象化
  • 描述统计学
  • 使用日期和时间
  • 机器学习

要深入了解统计,请查看我的“数据科学统计基础”帖子。

[## 数据科学统计基础

towardsdatascience.com](/stats-essentials-for-data-science-cfcdee17af68)

数据帧

数据框架是数据科学和分析的核心。它们本质上只是一个由行和列组成的表格,通常每行是一个 记录 ,每列是该记录的一个 属性 。例如,您可以有一个雇员表,其中每行是一个人,列是他们的姓名、家庭住址和职务。

因为数据框架在数据科学中起着核心作用,所以您需要掌握可视化和操作其中的数据。pandas这里是钥匙库。

基础知识包括能够加载、清理和写出 CSV 文件。清理数据可能涉及删除具有缺失值或重复信息的行,纠正错误值,以及将列重新格式化为不同的数据类型。

其他重要的数据操作包括矢量化和迭代数据转换。对于我们的数据框架中的列的简单的元素数学,pandas让我们把列当作奇异值。

对于更细微的操作,比如处理丢失的值,否则会导致列操作失败,您可以使用.apply。下面,我们使用一个λ将一个自定义函数safe_divide应用到每一行的col1col2字段。[1]

对于不容易传递到 lambda 中的逻辑,我们可以使用.itertuples遍历 dataframe 行。(能避免就不要用 [.iterrows](https://medium.com/swlh/why-pandas-itertuples-is-faster-than-iterrows-and-how-to-make-it-even-faster-bc50c0edd30d) !)

最后,我们需要能够组合来自多个数据帧的数据,并对数据运行聚合命令。在下面的代码中,我们合并了两个数据帧,通过指定它是一个左合并,确保不要删除df1中的任何行。然后我们创建一个新的 dataframe,df_agg,它对每个用户的每一列进行求和。由于user_id现在是我们的索引,我们可以使用.loc轻松显示特定用户在给定类别中的支出。

泰勒·伊斯顿在 Unsplash 上拍摄的照片

数组

pandas数据帧实际上是建立在 [numpy](https://stackoverflow.com/questions/11077023/what-are-the-differences-between-pandas-and-numpyscipy-in-python) 数组之上的,所以了解一些如何有效使用numpy的知识会很有帮助。例如,pandas.Series(行和列的类似数组的数据类型)上的许多操作与numpy.array操作相同。

numpy或 Numerical Python ,是一个专门为高效数学运算而构建的类库。R 用户会发现numpy数组很熟悉,因为它们与 R 的向量共享许多编码逻辑。

下面,我将强调 Python 内置的list类的一些区别。我遵循的一个典型经验法则是,只要有可能,最好使用 Python 的内置类,因为它们已经针对该语言进行了高度优化。然而,在数据科学中,numpy数组通常是更好的选择。[2]

首先,我们对向量进行简单的过滤。Python 的内置list要么需要列表理解,要么需要filter函数加上 lambda 和解包([*...])。与此同时,numpy只需要阵列本身。

第二个主要区别是数学运算。+操作符将列表连接起来。与此同时,numpy数组将+解释为元素相加。

为了对 Python 列表进行元素式的数学运算,您需要在两个列表上使用类似于带有zip的列表理解。对于numpy,只是普通的数学运算符。您仍然可以手动计算简单的聚合,如列表中的平均值,但是我们几乎已经到了使用列表没有意义的地步。

最后,如果您正在处理更高维度的数据,不要为列表的列表而烦恼——只需使用numpy。我仍然在挠头,试图弄清楚[*map(np.mean, zip(*l_2d))]到底是如何工作的,而arr_2d.mean(axis=1)清楚地表明我们取每列(轴 1)的平均值。

如果你最终从事计算机视觉工作,多维数组将是必不可少的,因为它们是存储图像像素亮度的默认数组。例如,您可能会遇到一个二维数组,其中包含每个像素的 RGB 值的元组,或者一个五维数组,其中维度 3、4 和 5 分别是红色、绿色和蓝色。

照片由莎伦·皮特韦在 Unsplash 拍摄

形象化

在数据帧和数组之后,下一个最重要的分析技能是数据可视化。可视化数据是分析的第一步也是最后一步:当 Python 向您传达数据时,以及当您向利益相关者传达数据时。

主要的 Python 数据可视化库是matplotlibseaborn。下面介绍如何在matplotlib中创建一个简单的双面板图。

作者图片

下面是一个简单的方法来绘制多组数据。label关键字非常方便,因为您可以简单地调用plt.legend并用每个组的信息自动填充图例。

作者图片

如果你想变得有趣,可以看看交互式仪表盘工具,比如散景或 Plotly 。这些工具允许用户与绘图进行交互,例如通过将鼠标悬停在某个点上来获取关于该点的更多信息,或者通过单击下拉菜单或拖动滑块来重新生成绘图中的数据。你甚至可以将简单的图嵌入到静态 HTML 中,就像下面的散景图。[3]

作者 Gif

由 Unsplash 上的 CHUTTERSNAP 拍照

描述统计学

虽然你可能已经迫不及待地想要开始机器学习,但我认为首先应该对描述统计学和推断统计学有一个扎实的理解。对于大多数数据科学应用程序来说,这些基础知识应该足够了。

与推断统计学不同,后者涉及将我们样本的数据转化为对更广泛人群的推断。数据是正态分布,单峰还是双峰,偏左还是偏右?什么是典型值,数据与该值相差多少?将描述性统计视为数据可视化的“硬数字”对。能够快速传达这些指标将为数据提供一种直觉,这有助于识别异常值,例如数据质量问题。

以下是我认为必须了解的主要指标:

  • 平均值:平均值,中位数,众数
  • 价差:标准差
  • 模态:单峰、双峰、多峰分布
  • 歪斜:左、右

照片由阿伦视觉在 Unsplash 上拍摄

使用日期和时间

至少有了数据分析,你很可能无法逃避与日期打交道。日期构成了时间序列分析的主干,这在像物联网这样有连续数据流的领域中无处不在。

内置的datetime库是 Python 的标准,在dateutil库中有扩展的方法。幸运的是,当索引设置为 datetime 时,pandas具有处理日期的优秀功能,这意味着您可以在pandas中进行有日期和无日期的分析。类似地,matplotlib让您传入dt.datetime值,就像它们是正常数字一样。

dt.datetimestr格式之间转换也很重要。这里的功能是:

  • dt.datetime.strptimestr - >为dt.datetime
  • dt.datetime.strftimedt.datetime - >为str

(注意:我始终记不住是字符串还是日期时间值先出现!我只是在旁边的 Jupyter 笔记本电池上试了一下,看看哪个能用。)

最后,Python 的time模块可以方便地计时分析中的步骤需要多长时间。time.time()将返回一个浮点数,表示自 1970 年 1 月 1 日午夜以来的秒数。(也称 Unix 纪元时间。)您可以在代码块之前保存该值,然后在代码之后将其与纪元时间进行比较。

安迪·凯利在 Unsplash 上的照片

机器学习

最后,我们有机器学习。在数据科学家做的所有事情中,机器学习最受关注,但可能是这份工作中最小的方面。

把成为一名数据科学家想象成建造一台钻孔机。

来自 Pexels 的雅罗斯拉夫·舒拉耶夫的原始照片

训练本身是引人注目的部分——花哨的统计和分析——秘诀是机器学习。钻尖因突破而获得所有荣誉,并且总是有新的和改进的钻尖出现,可以破碎更坚硬的材料。

但你的大部分时间可能会花在组装其余的机器——框架、杠杆、螺丝等。识别在哪里钻孔。(如果你在一个特别缺乏工程技术的组织中,你也可能最终构建前端:用户的控件!)

如果你只关心钻头而不是整个机器,你可能会发现自己对许多数据科学工作大失所望。但是,如果你在建造机器的整个过程中找到乐趣,并创造出真正帮助人们开拓创新的东西,那么你就会热爱你的工作。

无论如何,你需要一些机器学习的知识。虽然你需要了解你使用的任何算法在做什么——以及它是否是解决你所提问题的正确工具——,但你可能会惊讶地发现,研究完全相似的算法有何不同(例如随机森林与支持向量机与 XGBoost )所带来的商业收益是如此之少,除非你的工作是研究、教育或机器学习咨询。[4]

相反,如果你很好地理解了使用机器学习算法之前和之后的必要步骤,你会走得更远。因此,我将在这一节讨论有效使用机器学习的“之前和之后”部分。我认为,需要了解的主要概念是:

  1. 特征工程
  2. 训练数据与测试数据
  3. 评估模型拟合度

特征工程

我们的原始数据通常不足以建立一个强大的模型。比方说,我们试图预测在线商店每天售出的商品数量。

我们已经知道周末的销售额比平日高,所以我们希望我们的模型包含工作日/周末的区别,以便更加准确。我们的数据中没有明确的工作日/周末的区别,尽管我们只有销售发生的日期。

线性模型肯定不知道如何处理原始数据。也许一个复杂的深度学习模型可以获得与日期相关的销售循环模式,但这可能需要大量数据才能弄清楚。

一个简单得多的选择是设计一个is_weekend 特性,询问每笔销售是发生在周六还是周日,而不是一周的其他时间。is_weekend功能现在作为一个明确的标志,提醒我们的模型 a 在工作日和周末之间可能会有所不同。

类似地,也许用户购物车中商品的原始数量并不是一个有价值的预测指标,但是这些商品的平方根或对数实际上是。(我其实也不知道。如果电子商务领域的所有数据科学家都在使用某种转换,请给我发消息!)

最终,特征工程是一种将领域专业知识整合到模型中的方法,为模型提供了更有用的工具来理解数据。预计将花费大量时间来尝试为您的模型识别和设计最具信息性的功能。在精确的数据之后,相关特征是精确的机器学习模型的最重要的组成部分——远远超过所使用的精确算法或调整超参数所花费的时间。

训练数据与测试数据

当你建立一个预测模型的时候,知道它有多准确是很重要的。这就是训练数据对比测试数据的地方。主要的想法是将你的数据分成“训练”数据和“测试”数据,前者用于创建模型,后者用于评估模型的准确性。

一旦您的模型了解了输入和输出之间的关系,您就可以使用测试数据来查看模型的预测与真实输出的对比情况。【5】是终极考验!当我们确切知道答案应该是什么时,就没有多少解释的余地了。

Scikit-learn ( sklearn)是机器学习的首选 Python 库。它与pandasnumpy无缝集成,拥有准备、运行、评估和微调模型所需的一切。

评估模型拟合度

我们需要了解的最后一个机器学习理论是评估你的模型对你的数据描述得有多好……以及它对数据的描述是否也很好。

作者图片

模型是真实世界的简化表示。如果模型过于简单,那么它既不能代表训练数据,也不能代表真实世界(欠拟合)。另一方面,如果它太复杂,它将描述它所训练的数据,但不会推广到现实世界(overfit)。

将模型视为将输入转换为输出的底层“规则”。假设我们有一个模型,可以将学生 1)学习和 2)睡觉的时间转换成考试分数。如果我们开始包括像 3)学生是否吃早餐和 4)他们是否喜欢老师这样的特征,我们可以使模型更加准确。

但是我们拥有的特性越多,我们就需要越多的数据来精确地计算每个特性对输入和输出的贡献,特别是当特性不是完全独立的时候。事实上,研究人员已经估计过当我们有相关特征时,我们的模型不应该有超过我们模型中n 个特征的平方根(其中n是观察的数量)。除非你有几十或几百名学生的数据,否则这将大大减少你的模型应该具有的特征的数量。

当我们用相关特征包装我们的模型时,比如昨天的个小时的睡眠和两天前的个小时的睡眠,我们在描述我们的数据时挤出了一些额外的准确性,但我们也稳步地创建了一个像右上方这样的图片,其中我们的模型没有很好地转化为现实世界。为了解决这个问题,我们需要采用类似于特征选择、 k 重交叉验证、正则化和信息标准的技术。这些技术使我们能够仅基于最具信息性的特征来创建真实世界的最简洁的表示。

亚历山大·波辛汉姆在 Unsplash 上拍摄的照片

总结想法

这篇文章涵盖了我称之为数据科学的“分析”方面——当你操作和分析数据时你写的代码。这些技能通过从数据中提取洞察力来实现精确性、速度和可重复性。

从在pandas中重新排列数据,到在matplotlib中将其可视化,再到在sklearn中训练一个模型,我们现在已经掌握了一些处理任何数据的核心技能。通过留下代码的痕迹,我们写的任何分析都可以被他人更仔细地检查和重复——甚至是未来的我们自己。

下一篇文章将探讨数据科学的软件工程方面,包括你在实际处理数据的之外编写的代码。在我们的钻孔机例子中,除了钻孔机之外,工程技能是一切。结合这篇文章中的技能,你将为加入数据科学家团队做好充分的准备,并开始做出有意义的贡献。下期帖子再见!

最好,
马特

脚注

1.数据帧

numpydivide函数与我们的safe_divide函数非常相似,我通常会推荐使用已经编写并优化的代码。但是也许在这种情况下,假设我们在被零除的时候想要np.nan而不是Inf

此外,您可能会注意到,我们正在将一个预定义的函数safe_divide传递给一个 lambda,它应该是一个“匿名”函数。为什么不直接在.apply中使用safe_divide?我们需要一个额外的 lambda 层,因为.apply需要一个pd.Series,特别是您的 dataframe 行(axis=1)或列(axis=0)。我们的匿名函数是一个包装器,它接收一个pd.Series,然后将safe_divide应用于该系列的col1col2字段。

2.数组

在列表上使用numpy数组的规则的一个明显的例外是,如果您希望您的数组存储不同类型的值。numpy.arraypandas.Series有类型强制,这意味着所有元素必须是相同的类型,在创建数组时它们将被强制为相同的类型。

下面,our_list1numpy版本将12转换为浮动以匹配3.0。(整数被转换成浮点数,以保留浮点数中小数点后的信息。)对于our_list2,没有明确的整数或浮点版本的'a',所以将12.0转换为字符串。如果出于某种原因,您希望您的数组存储不同类型的数据,那么您最好坚持使用 Python 的list类。

3.形象化

如果你感兴趣,下面是生成散景图的代码。

4.机器学习

作为一个喜欢搞清楚事物如何工作的具体细节的人,我个人建议深入研究随机森林和 XGBoost 等算法之间的区别!我觉得这很有趣,这些知识让我更容易向模型输出的好奇消费者揭开机器学习的神秘面纱。但是总的来说,通过挖掘这些细节,我交付商业价值的能力并没有提高多少;真正的好处是理解细微差别的个人满足感。

5.训练数据与测试数据

请注意,这是针对监督学习问题的,其中每个输入都有一个“正确”的输出。对于无监督学习问题,评估模型准确性更加复杂,并且可能需要特定领域的专业知识。例如,我们可能会看到有四类客户支出,但需要有商业头脑的人才能看出只有三类与公司的市场相关。

没有问责制,分析毫无意义

原文:https://towardsdatascience.com/analytics-is-pointless-without-accountability-68d131ba15d3?source=collection_archive---------20-----------------------

分析更多的是关于决策而不是数据。

几年前,我为一家大型科技公司的营销团队做了一个分析咨询项目。我和我的团队进行了数据集成,将他们的营销平台数据与 Salesforce 结合在一起。这使得他的团队能够将营销活动和内容与已完成的销售和机会渠道联系起来。

客户印象非常深刻,希望我们飞到公司总部,向他的 SVP 展示我们的产品。

我们到达并展示了工具。大约进行到一半时,我们开始钻研一些销售数字。这位客户脸上带着灿烂的笑容——“他们建造的东西简直令人难以置信,”他说,希望他的老板也有类似的反应。作为回应,SVP 带着关切的表情说,“我不确定我们愿意受制于这些数字。”会议马上就没了气氛,从炫耀变成了辩护听证会。SVP 的最后一个问题:“你们能用声音分享做些什么吗?”

我们对此表示怀疑。我们建立了一个工具集,这是公司内部 50 多名员工的分析团队无法建立的,我们只用了几个月就完成了。但我们忽略了一个简单的事实——他们想要分析,而不是问责。

什么是分析?

“分析”这个术语经常被使用。人们用它来表示智慧。“善于分析”是市场上几乎所有公司工作的要求。但是什么是分析,真的吗?

维基百科将分析定义为“数据或统计的系统计算分析。”

当然,那是真的。

但这只是定义了它是什么,而不是它为你做了什么。

简单地说,分析是用于决策的信息

没有决策,分析只是屏幕上的数字。然而,成千上万的人认为分析是一种存在的东西,所以你拥有它,而不是你实际用来做决定的东西。

企业对所有“人工智能”和“人工智能”的痴迷反映了这一点。太多的商业领袖认为数据科学是摆脱决策的工具,而不是支持决策的工具。这是许多数据科学项目失败的一个原因。商业用户认为他们将得到托尼·斯塔克的贾维斯(一个非常智能的系统)。实际上,他们只是在仪表板和数据集中获得了稍微好一点的信息。

人还是要做决定的。

学会喜欢出错的时候

人类想推迟做决定,因为他们不想看起来很糟糕。我咨询过的 SVP 喜欢分析学的想法,但她实际上并不想要它。当她不喜欢她在屏幕上看到的内容时,她质疑这些信息。她询问了声音份额(一个衡量品牌知名度的指标),因为这是一个让她看起来不错的指标。那家特定的公司规模很大,知名度很高,这意味着默认的语音共享会让她看起来很好。

照片由来自佩克斯的马体·米罗什尼琴科拍摄

不幸的是,这是大多数人使用仪表板和数据的方式——作为一种工具来突出良好的表现,并告诉别人他们有多棒。这种思维方式的谬误是双重的:

  1. 当你只用数据来告诉人们你做得有多好的时候,如果有什么事情出错了,你会看起来像一个大笨蛋。这开创了“一切都好”的先例。通过把自己变成好消息记者,即使是最温和的坏消息也会看起来很糟糕。
  2. 如果你从不审视自己做错的事情,你就永远不会进步。你真的不能做任何决定,因为你不知道哪些决定不该做。没有决策,你就没有战略。

责任感有时很难接受,但是没有它,我们永远不会变得更好。分析是最终的问责工具,我们应该用它来帮助我们做出更好的决策。

将数据与决策联系起来

正如我上面所讨论的,分析更多的是关于决策,而不是数据。

如果你是一名分析师或数据科学家,重新规划你的问题。与其从数据开始,不如从企业想要做出的决策开始。

如果你是商业或营销领导者,不要为了拥有数据而要求数据。先弄清楚你想做的决定。然后,与您的数据团队合作,构建支持这些决策的工具。

将分析重新构建为决策制定练习,而不是数据采集练习。与其从数据开始,不如从问题开始:你将如何改进?你将如何做出更好的决定?我们需要知道什么来选择不做什么?

依赖于数字

当我开始我的数据职业生涯时,我认为分析就是获取数据。“大数据”的说法让我相信,你拥有的数据越多,你就会过得越好。如今,我更关心如何让数据变小。太多的信息,即使是有组织的,也很难消化——使决策变得具有挑战性。简单易懂的信息有助于决策。

但首先,你必须愿意接受这些数字。

这些年来,我意识到大多数人不想要问责制,他们只想说他们在做分析。

但是正如我们所探索的,没有问责制,分析是没有意义的。

更多关于分析、工作和商业的文章,请在 Twitter 上关注我。

你也可以看看我正在做的@ retrix.io

分析生命周期管理

原文:https://towardsdatascience.com/analytics-lifecycle-management-f391b3cbebad?source=collection_archive---------15-----------------------

行业笔记

从问题形成到解决方案日落的 7 个阶段

现在,将机器智能添加到我们的业务工作流中已经成为常态,越来越多的数据驱动预测分析正在开发并集成到现有的业务运营中,以帮助决策、提高效率、降低风险和增强员工体验。

然而,随着分析和人工智能模型的激增,我们面临着有效管理分析生命周期的挑战,以确保这些模型产生可靠的业务洞察力,从而做出最佳决策,确定机会和合理的行动。这是一项多方面的复杂任务。

下面是我对管理分析的整个生命周期的看法,它提供了一步一步的指导,通过制定业务问题,开发和部署分析,并最终淘汰分析的过程。请注意,虽然该过程是以顺序方式呈现的,但它本质上是一个迭代过程,可用于产生可重复且可靠的预测结果。

A .问题提法

任何分析或人工智能解决方案都始于业务问题或业务用例。只有清楚地了解了业务需求,才能设计和开发具有预期业务成果的分析解决方案。在这一阶段,还需要确保业务发起人承诺在提议的用例中使用开发的分析,以满足最初的设计目标。一个项目经常会陷入一个陷阱,那就是它的分析输出没有被任何潜在用户采用,从而浪费了所有的努力。因此,在项目的早期阶段,让业务发起人参与进来并与他们共同创造解决方案是非常重要的。

阐明问题的另外两个方面包括项目范围和成功度量的定义。这是询问关键问题的时候,例如:这个项目的范围是什么?它是包括所有员工,还是仅包括特定的业务部门、地区、国家和部门?我们如何定义成功?衡量成功的标准是什么?现在是什么状态,未来又会是什么状态?目标用户在未来状态下会是怎样的体验?澄清这些问题对于解决方案设计阶段至关重要。

B .方案设计

一旦问题得到很好的表述,下一步就是设计解决方案,包括

  • 了解该领域的当前形势或现有工作,尤其是公司内部的工作,以避免任何重复工作,并有可能建立在现有解决方案的基础上。如果在外部市场发现类似的解决方案,那么“购买还是建造”的问题可能需要与业务利益相关者讨论。此步骤还应包括可行性研究以及工作规模(如果业务发起人要求的话)
  • 确定解决方案所需的数据,并探索其可用性。这一步可能需要与数据工程师、数据科学家、赞助用户和业务利益相关者进行头脑风暴。在这里,让具有业务领域知识的人参与讨论是非常宝贵的。另一方面,数据收集往往是最耗时的步骤,尤其是当数据来自许多不同的来源,混合了数据库表、电子表格、平面文件和其他异构格式时。当大部分数据可以从一个集中的数据仓库中自动提取出来时,开发周期可以大大缩短
  • 清理、整合和探索数据。在这一步,团队将使用各种工具来搜索关系、趋势和模式,以更深入地了解数据,并确定有助于从分析角度解决业务问题的显著特征。在检查数据时,团队可能会发现需要添加、删除或组合特征来创建更精确的模型
  • 理解应用附加业务规则的需要。如果确实有这样的需要,那么在设计阶段就应该考虑到它们

C .解决方案开发

在此阶段,将对数据应用大量分析和机器学习建模算法,以找到数据中关系的最佳表示,这将有助于回答业务问题或解决第一阶段中确定的业务需求。将相应地进行广泛的模型构建、测试、验证和校准。此开发阶段的另一个关键领域是数据质量保证,它根据业务和分析要求,确保不同开发阶段的数据质量。

对于任何基于机器学习的解决方案来说,人工智能信任已经成为一个越来越重要的方面。在一天结束时,如果最终用户不信任人工智能解决方案产生的见解、预测或建议,他们就会忽略这些数据。因此,如何增加数据透明度,展示人工智能输出的公平性和健壮性,以及使人工智能决策可以解释,对于推动解决方案的采用变得非常关键。IBM Research 开发了一些工具来培养 AI 信任,包括 AI Factsheet 360(https://aifs360.mybluemix.net/)、AI Fairness 360(【http://aif360.mybluemix.net】T2)和 AI explability 360(http://aix360-dev.mybluemix.net)。在那里可以找到很多有用的信息。

这个阶段的最后一步是在业务环境中解释见解,与业务涉众分享和验证它们。从 AI 信任评估中收集的信息将在此类审查中非常有用。

D .解决方案部署

在这个阶段,我们采用开发的解决方案和衍生的见解,并使用可重复的自动化流程将它们付诸实施。针对目标用户群的活动和支持会议是提高解决方案认知度的好方法,最终推动解决方案的采用。另一方面,将解决方案集成到现有的运营流程中是另一个很好的、事实上也是更好的方法,可以推动其使用并实现业务成果。有时,一定程度的变更管理对于将分析结果纳入之前的流程是必要的,来自业务发起人和利益相关者的有力支持和认可将使该流程变得更容易和更快。

请注意,在开发之后可能需要一个解决方案试验阶段,以便在扩大规模之前在相对较小的范围内验证解决方案。一旦团队确认试点结果确实符合预定义的成功标准,并获得业务利益相关方的批准,就可以进入解决方案部署阶段。

解决方案部署并投入使用后,需要监控其性能、跟踪使用情况并收集反馈,以便支持未来任何潜在的解决方案调整和增强。另一方面,如果确实发现了严重的缺陷或严重的性能问题,那么团队可能需要回到解决方案开发阶段。

E .成功测量

一旦解决方案成功部署并持续跟踪其使用情况,就到了衡量成功的时候了。在问题形成阶段定义的成功标准将在这一阶段进行测量和报告。其他指标可能包括成本节约或收入产生方面的 ROI,以及基于反馈的 NPS。

F .解决方案维护&增强

一旦溶液处于稳定状态,就可以转换到 BAU 模式。这也是尽可能简化/自动化流程,以最少的维护或人工干预提高效率的时候了。在此阶段,还会定期刷新模型。

此外,通过基于标准化度量标准的模型性能的持续监控和测量,团队应该持续评估解决方案的有效性,以检查它是否仍然满足当前的业务需求。如果发现了差距,那么模型需要改进和重新校准。如果业务需求随着时间的推移发生了变化,现有数据源不再有效,或者有了新的数据,这可能会将周期带回到解决方案开发,甚至是解决方案设计。这最终使得生命周期管理成为一个迭代的过程。

G .解日落

如果最初的业务需求不再有效,新的解决方案已经开发出来并具有增强的功能,或者客户已经离开,那么现有的解决方案将不再需要,是时候淘汰该模型了。

回顾完端到端分析生命周期后,我想指出一些可能会使整个过程复杂化、变慢甚至脱轨的事情。

  • 所需的数据源可能分散在整个组织中,需要非常手动的收集和整合,或者由于其隐私和敏感性而具有非常严格的访问权限,甚至是机密的,因此无法共享
  • 人工智能信任在数据洞察中的建立滞后,目标用户对洞察的有效性和道德性有所担忧
  • 企业可能很难利用目标业务用例中的洞察力,或者目标用户不重视这样的洞察力,并选择在任何决策中忽略它们
  • 将分析集成到现有工作流中可能需要大量涉及不同用户角色的变更管理

为了避免或减轻上述一些陷阱,以下是一些建议:

  • 构建一个非常清晰的用例,并估算投资回报率
  • 获得业务发起人和利益相关者的大力支持
  • 通过设计思考会议与赞助用户共同创建解决方案,并在整个分析生命周期中让他们参与进来
  • 以敏捷的方式开发解决方案

祝您好运,并享受分析生命周期的管理!

使用 Python 和 Tableau 分析和绘制照片位置

原文:https://towardsdatascience.com/analyze-and-map-photo-locations-with-python-and-tableau-7b2a4af971eb?source=collection_archive---------11-----------------------

Python、数据分析、地理、摄影

使用 Python 从数字照片文件和 Tableau 中提取 GPS 坐标和其他元数据来绘制它们

在 Unsplash 上由米琳·特雷莫耶拍摄的照片。

"元数据解放了我们,解放了知识"大卫·温伯格

介绍

当胶片摄影卷土重来时,数码摄影提供了许多好处。首先,在相机、镜头、存储和附件的初始投资之后,没有胶片或处理的费用,除非进行打印。此外,摄影师可以在相机和现场预览图像。此外,各种元数据,包括曝光和镜头设置,日期和时间,有时甚至是 GPS 位置,都存储在每张照片的文件中。

本文描述了一个 Python 程序,它从图像文件中获取 GPS 坐标和其他元数据,并将它们写入 CSV 文件。然后,它会在一个 Tableau 公共仪表板中呈现元数据,该仪表板跟踪相机的使用和图像位置。介绍使用 Python 从图像文件中提取元数据,参见 如何使用 Python 和 Tableau 分析照片元数据

演示总结

以下是本文中描述的处理和可视化影像 GPS 和其他元数据的任务:

  1. 使用 Adobe Lightroom 或您喜欢的照片编辑器将小图像文件导出到文件夹中。确保导出设置包含 EXIF 数据。就我而言,我选择了 2021 年用 Z50、D750 和 iPhone 12 拍摄的所有照片。或者,您可以将从一台或多台相机导入的未经编辑的图像文件存储在电脑上的单个文件夹中。
  2. 运行 Python 图像元数据提取程序,将图像文件夹作为其输入。该程序创建一个 CSV 文件,每个图像包含一个元数据行。
  3. 将包含图像元数据的 CSV 文件导入 Tableau Public。
  4. 建立一个 Tableau 仪表板,按月显示相机使用情况和照片位置地图。

"摄影从时间中抽出一瞬间,通过静止不动来改变生活."多萝西娅·兰格

关于图像元数据

数码相机将有关图像的元数据存储在一个文件中,该文件还包含所捕获图像的表示。他们以一种叫做 EXIF 的标准格式保存数据。以下是 EXIF 定义的一些字段示例:

  • 图像制作 —相机制作
  • 图像模式 l —相机型号
  • EXIF 日期时间原件 —相机拍摄图像的日期和时间
  • EXIF 焦距 —镜头的焦距
  • EXIF 快门速度 —以秒为单位的快门速度
  • EXIF 光圈数—F 档
  • EXIF 曝光偏差值 —曝光偏差(低于或高于基准曝光时停止)
  • EXIF 白平衡 —相机的白平衡设置
  • EXIF ISO speedrating—ISO 传感器灵敏度设置
  • GPS 纬度 —以度、分、秒为单位的地理纬度
  • GPS 全球定位系统经度 —以度、分、秒为单位的地理经度

TsuruZoh Tachibanaya 描述了 EXIF 文件格式标准。此外,ExifTool 还记录了其相关的 GPS 标签。

Python ExifRead 模块

以下部分展示并描述了从影像中提取 EXIF 数据的 Python 程序。该程序利用了 ExifRead 模块。要使用该模块,请使用 Python pip 实用程序安装它。下面是一个 pip 使用示例:

$ pip 安装退出读取

Python 程序从图像文件中提取元数据

从图像文件中提取元数据并将值存储在 CSV 文件中的程序包括两个模块:一个作为程序入口点的控制器和一个从每个图像文件中读取元数据并将其写入 CSV 文件以供以后分析和可视化的类。下面介绍和描述了这些模块。

photo _ EXIF _ controller . py—该文件是程序的控制器模块和入口点。它只是打印一个开始消息,并用一组参数调用 c_photo_exif 类的构造函数。处理完成后,它会打印已处理的图像文件数量和完成消息。

控制器模块 photo_exif_controller.py .作者创建。

c_photo_exif.py —该文件中定义的 c_photo_exif 类执行以下步骤:

  1. 调用模块使用这些参数调用构造函数(init()):输入图像文件夹、输出 CSV 文件命名、程序将获取日出和日落时间的城市以及该城市的日落。
  2. init 函数在调用 init_csv_file()函数时格式化输出 CSV 文件的文件头。然后,它调用 process_photos()函数,逐个读取每个图像 JPEG 文件。
  3. 对于每个图像文件,process_photos()函数调用 process_photo()函数,从文件中提取元数据的子集。process_photo()函数又调用 calculate_coordinate()辅助函数将纬度和经度的 GPS 度数、分钟和秒钟值转换为单个数值十进制度数。
  4. 接下来,process_photos()函数调用 write_csv_file_row()将一个图像的元数据写入 csv 文件。
  5. 最后,控制器模块打印已处理图像文件的数量,并显示一条消息,说明已完成处理。

c_photo_exif.py 文件中的 c_photo_exif 类。由作者创作。

示例输出 CSV 文件

下面的截图显示了尼康 Z 50 和 iPhone 12 Pro Max 相机的两个元数据记录。如果图像文件包含 GPS 位置坐标,则程序会将经纬度(整数)、分钟和秒坐标值转换为小数。

CSV 文件中的 EXIF 元数据。图片由作者提供。

关于图像文件中相机和 GPS 元数据的注释

即使在今天,许多 DSLR 和无反光镜相机也不能直接捕捉照片位置的 GPS 坐标并存储在其图像文件中。然而,大多数(如果不是全部的话)当代智能手机都捕捉 GPS 坐标。

在这里显示的例子中,尼康 D750 没有捕捉 GPS 坐标。然而,尼康 Z50 只有在现场与 iPhone 上安装的尼康 SnapBridge 应用程序配对,并且 iPhone 获得 GPS 信号时,才会存储 GPS 坐标。另一方面,iPhone 12 只要接收到 GPS 信号,就会捕获 GPS 坐标。

可视化相机使用和照片位置与 Tableau 公共

为了分析相机使用和照片位置,我将 Tableau Public 连接到 Python 程序创建的 photo_exif.csv 文件。然后,我构建了一个可视化仪表板,其中包含两个工作表:一个按月记录相机使用情况,另一个在地图上显示我拍摄照片的位置。

Tableau 是领先的数据可视化和商业智能应用程序。其免费版本 Tableau Public 包含商业软件包的许多功能,但至少有两个明显的限制:

  1. Tableau Public 可以连接到有限数量的数据类型。例如,虽然它可以连接到 Excel 和文本文件,但它不能像商业产品那样直接链接到关系数据库。
  2. Tableau Public 仅将项目保存到 Tableau Public 服务器,供全世界查看。因此,如果您的 Tableau 可视化显示机密数据或不想与他人共享数据,Tableau Public 并不是一个很好的选择。相反,您可能希望选择另一种可视化产品,如 Tableau 或 Microsoft Power BI 的商业版本。

安装 Tableau Public

要在 Windows 或 Mac 电脑上安装 Tableau 公共桌面应用程序,请导航至https://public.tableau.com。然后,输入您的电子邮件地址,点击[下载应用程序],并按照安装提示进行操作。

Tableau 公共主页和安装表单。图片由作者提供。

创建相机使用和地图面板

下面列出的说明仅提供了构建相机使用和地图仪表板的基本步骤。要了解更多关于在 Tableau 中构建可视化工作表和仪表板的信息,请参见这些免费学习资源。

在您学习了如何使用 Tableau Public 之后,请按照以下步骤构建仪表板:

1 —打开 Tableau 公共应用程序。

2 —在连接窗口中,单击[文本文件]。然后,导航并选择包含 EXIF 数据的 CSV 文件。最后点击【打开】连接数据。

连接到影像 EXIF 元数据 CSV 文件。图片由作者提供。

3-在“数据源”窗口中查看影像 EXIF 记录。

数据源窗口中的示例图像 EXIF 数据。图片由作者提供。

4-构建一个“按月显示相机”工作表,其中包含一个条形图,显示按月显示的相机使用情况。

Tableau 公共桌面应用程序中的相机使用工作表。图片由作者提供。

5 —建立一个“照片地图”工作表。添加要应用于此工作表和相机使用工作表的过滤器。

Tableau 公共桌面应用程序中的照片地图工作表。图片由作者提供。

6-将“按月照相机”和“照片地图”工作表组合成“照相机使用”仪表板。

Tableau 公共桌面应用程序中的相机使用仪表板。图片由作者提供。

7-最后,如果你还没有创建一个免费的 Tableau 公共帐户,现在就创建一个。然后,将仪表板发布到 Tableau 公共网站。

Tableau 公共服务器上的摄像机使用仪表板。图片由作者提供。

你可以在这里查看仪表盘。

摘要

本文演示了如何使用 Python 从图像文件中访问关于数码照片的元数据。它还展示了如何转换数据,以便为可视化和分析做准备。最后,它演示了如何构建一个 Tableau Public,该 Tableau 使用图像元数据来可视化相机使用和图像捕获位置。

胶片相机仍然是捕捉我们周围世界图像的绝佳工具。但是现在,你可能会同意数码相机提供了额外的好处,以提高摄影过程和理解照片和模式。

"对我来说,相机是一本速写本,是直觉和自发性的工具."— 亨利·卡蒂埃·布列松

使用差异中差异模型分析因果关系

原文:https://towardsdatascience.com/analyze-causal-effect-using-diff-in-diff-model-85e07b17e7b7?source=collection_archive---------17-----------------------

对于真实世界的应用程序

作者图片

进行随机 AB 实验并不总是可行的,但如果我们有一个随时间产生观察数据(即面板数据)的近似实验,我们仍然可以恢复治疗的因果效应。我们可以使用的一个模型是差异中的差异(Diff-in-Diff,或 DiD)来估计观察数据的因果关系。

差异中的差异模型

当我们有两个现有的组(例如,两个区域 A 和 B)而不是像在随机 AB 试验中那样由我们随机分配,并且治疗发生在其中一个组时(例如,只有区域 A 发起促销),我们可以在治疗和控制之前对组间的差异建模,用于预先存在的差异,并且当我们假设治疗后的差异不是由于仅打击其中一个组的任何其他外部冲击而是由于治疗本身。

让我们用潜在结果模型的框架来研究一下数学。如果你需要快速回顾一下那是什么,你可以阅读我以前的文章。补充的是,现在我们使用具有时间维度的数据,因此将下标 t 添加到等式中。

yᵢₜ 为个体受试者在时间tI的潜在结果;y₀ᵢₜy₁ᵢₜ 为观察结果(我们只能观察其中一个,不能同时观察两个); Dᵢₜ 为治疗状态变量。DiD 的一个关键假设是,潜在结果 y₀ᵢₜ 可以建模为个体单位和时间固定效应的线性加法方程:

上面的第二个等式表明 Dᵢₜ 与协变量上的随机分配一样好。我们还假设因果效应是可加的和恒定的,我们推导出 y₁ᵢₜ为:

鉴于 yᵢₜ = (1-Dᵢₜ)y₀ᵢₜ + y₁ᵢₜ ,我们有:

这个等式表明,潜在的结果是由时间不变的个体固定效应和时间固定效应的总和决定的,时间固定效应在个体之间是常见的,并且是因果效应。

假设我们有面板数据,允许我们对治疗前后的组间差异进行建模。让我们将 t =0 表示为预处理周期,将 t =1 表示为后处理周期。只有当 D ᵢ=1(治疗组)和 t =1 时, Dᵢₜ =1。我们推导出差分中的差分如下:

对照组治疗前后的差异:

治疗组治疗前后的差异:

因此,治疗组和对照组之间的差异中的差异是平均治疗效果:

我们用回归的形式来写吧:

从回归中,我们得到:

一份申请

Card 和 Krueger (1994 年)估计了国家最低工资增加对就业的因果影响。1992 年 4 月 1 日,新泽西州将州最低工资从 4.25 美元提高到 5.05 美元,而宾夕法尼亚州的最低工资保持在 4.25 美元。卡德和克鲁格分别于 1992 年 2 月和 1992 年 11 月调查了新泽西州的快餐店。他们还从邻近的东宾夕法尼亚的快餐店收集了数据。

我从麻省理工学院经济学网站下载了 Card 和 Krueger (1994)使用的数据文件 public.dat。我用 Python 计算了新泽西州最低工资增长影响的简单 DiD 估计。本质上,我比较了从 2 月到 11 月期间新泽西州的就业变化和宾夕法尼亚州的就业变化。以下是代码:

以下是回归结果的摘要:

它说就业变化的差异是 2.76 个 FTE 雇员。似乎更高的最低工资并没有减少就业。然而,我的结果显示这种差异在统计学上并不显著。

提醒

Diff-in-Diff 估计有效的关键假设是共同趋势,这意味着,在上面的例子中,处理前两个州的就业趋势应该相同。治疗使治疗组的趋势偏离共同趋势。治疗组和对照组可以不同,因为这种差异意味着被未观察到的个体固定效应所捕获,但是它们需要共享一个共同的趋势。

为了检验这一共同趋势,我从 BLS 下载了 1991 年至 1993 年费城、宾夕法尼亚大都会区和新泽西“食品服务和饮料场所”行业的月度就业时间序列数据。我将 1992 年 4 月和 1992 年 11 月作为垂直虚线绘制在下面。就业价值指数是 1991 年 1 月确定的。下载的系列没有季节性调整。我看到很多波动。即使我们放大到 1992 年 1 月至 1992 年 4 月期间(治疗前),我也不确定 PA 是否与 NJ 相当。因此,在没有最低工资变化的情况下,PA 就业可能不是 NJ 就业的一个好的反事实测量。

使用 RStudio 分析医疗保险数据

原文:https://towardsdatascience.com/analyze-health-insurance-data-using-rstudio-85f1c1e37ec8?source=collection_archive---------7-----------------------

了解如何使用 RStudio 分析医疗保险数据

欧文·比尔德在 Unsplash 上的照片

数据分析在商业中很重要,可以了解任何领域的当前状态,以做出准确的决策,推动业务步入正轨。在这里,我们涵盖了一个实用的领域,可以帮助个人在他们选择的任何领域进行数据分析。让我们从健康保险领域开始。

假设您收到了一个样本数据集( medExpense.csv ),其中包含了 1340 个当前参加健康保险计划的受益人的示例,这些示例显示了被保险人的特征以及该日历年的医疗费用总额。假设您被赋予了分析、讨论和解释这些数据的任务。我们将指导您如何使用 RStudio 处理这种情况。我们将使用 RStudio 来执行我们的数据分析。

加载数据集

**Code Snippet****## Importing the dataset**
dataset <- read.csv(‘medExpense.csv’, stringsAsFactors = TRUE)

Image_1:在 Rstudio 中加载数据集

让我们从在 RStudio 中加载数据集开始。我们可以使用 read.csv 函数(Image_1)从 CSV 文件加载数据集。我们设置 stringsAsFactors = TRUE 来自动将字符数据转换成因子,因为我们不能在机器学习算法中直接使用字符数据。加载的数据集如 Image_2 所示。

image _ 2:r studio 中加载的数据集

数据探索

**Code Snippet****## Returns the first parts of the data frame**
head(dataset)**## Returns the latter parts of the data frame**
tail(dataset)**## Compactly display the internal structure of the data frame**
str(dataset)**## Summarize medical expenses**
summary(dataset$expenses)**## Histogram of medical expenses**
hist(dataset$expenses)**## Table of region**
table(dataset$region)

图 Rstudio 中的数据浏览

现在让我们探索一下我们的数据集(Image_1)。使用 head & str 函数对数据集进行初步探索。函数返回数据帧的第一部分(Image_4)。 tail 函数返回数据帧的后面部分(Image_5)。 str 函数简洁地显示了数据帧(Image_6)的内部结构。这里我们可以观察数据帧的结构。它包括 1340 行和 7 列。年龄列是 int 类型,性别列是具有两个级别“女性”&“男性”的因子,bmi 列是 num 类型,儿童列是 int 类型,吸烟者列是具有两个级别“否”、“是”的因子,地区列是具有四个级别“东北”、“西北”、“东南”、“西南”的因子,费用是 num 类型(Image_6)。从 CSV 文件中读取数据时,使用 stringsAsFactors = TRUE 将分类变量转换为因子。我们会用多元线性回归,机器学习算法不能直接对字符数据起作用。我们必须检测特征矩阵和因变量向量。由于我们对医疗费用感兴趣,所以我们选择费用列作为因变量,并对其进行更多的探索。汇总函数汇总医疗费用列的最小值、最大值、第 1 个&第 3 个四分位数、中值和平均值(Image_7)。医疗费用的频率分布通过直方图使用 hist 函数可视化(Image_8)。它表明大多数病例低于 10000。table 函数用于获取 region 列的每个因子级别组合的计数。它说 325 排落在东北地区,326 排在西北地区,364 排在东南地区,325 排在西南地区。

Image_4:数据帧的第一部分

图 5:数据帧的后半部分

Image_6:显示数据框的内部结构

图片 _7:医疗费用汇总

图片 _8:医疗费用柱状图

图 9:地区表

检查功能之间的关系

**Code Snippet****## Correlation**
cor(dataset$age, dataset$expenses)
cor(dataset$bmi, dataset$expenses)
cor(dataset$children, dataset$expenses)**## Correlation matrix**
cor(dataset[c(“age”, “bmi”, “children”, “expenses”)])

Image_10:检查 Rstudio 中各功能之间的关系

现在我们需要检查特性之间是否存在任何关系。我们可以使用 cor 函数(Image_10)检查特征之间的关系。在这里,我们试图解释有用的特征,这将有助于预测医疗费用。相关值为 1 表示这两个变量完全相关。在这里,我们分别比较了每个变量年龄、bmi、儿童栏与费用的相关性。然后,我们已经在一个函数调用中实现了所有这些。我们可以看到,年龄字段与医疗费用高度相关,相关值为 0.3009237 &儿童字段是最不相关的列,相关值为 0.0684989。Bmi 与 0.1934809 的值合理相关。我们已经在一个函数调用中比较了所有这些变量之间的相关性,如 Image_12 所示。

图 11:各变量年龄、bmi、子女栏与费用相关性的个别比较

Image_12:年龄、体重指数、子女、费用等所有变量的相关性比较

可视化特征之间的关系

**Code Snippet****## Scatterplot matrix**
pairs(dataset[c(“age”, “bmi”, “children”, “expenses”)])**## More informative Scatterplot matrix using psych package**
## install.packages(‘psych’)
library(psych)
pairs.panels(dataset[c(“age”, “bmi”, “children”, “expenses”)])

Image_13:在 Rstudio 中可视化功能之间的关系

我们使用 pairs 函数来可视化年龄、bmi、儿童特征的散点图矩阵(Image_14)。使用 psych package "pairs . panels "函数提供丰富的图表(Image_15)。在对角线上,我们可以看到每个特征的分布,无论是正态分布、右偏还是左偏等。年龄和 bmi 特征似乎呈正态分布(Image_15)。孩子和费用是右偏的,所以平均值正好落在峰值上。上半部分显示了这些特征之间的相关性(图 15)。年龄与费用高度相关,与其他特征的相关性较低。所以年龄是一个重要的特征。体重指数与其他特征的相关性较小,与费用的相关性也较小。儿童与其他特征的关联度较低,与费用的关联度也较低。下半部分显示了这些特征之间的相关椭圆(Image_15)。它被拉伸得越多,相关性就越强。如果是正圆,那就没有关联。似乎 bmi &儿童的相关性最小,因为它接近于圆形。由于椭圆拉伸,年龄和儿童是相关的。年龄和费用之间的椭圆最长,因此年龄在预测费用时很重要-用红色突出显示的黄土曲线表明年龄与费用呈线性关系(Image_15)。

图 14:将年龄、体重指数、儿童等特征的散点图矩阵可视化

图 15:使用“心理”软件包,用丰富的图表可视化年龄、体重指数、儿童的散点图矩阵

将数据集分成训练集和测试集

**Code snippet****# Splitting the dataset into training set and test set**
## install.packages(‘caTools’)
library(caTools)
set.seed(123)**## Obtain the training index**
training_index <- sample(seq_len(nrow(dataset)), size = floor(0.75 * nrow(dataset)))**## Partition the data**
training_set <- dataset[training_index, ]
test_set <- dataset[-training_index, ]

Image_16:在 Rstudio 中将数据集分为训练集和测试集

我们必须在数据集上构建模型,并在一个完全不同的新数据集上进行测试。所以我们需要两套。我们在其中建立机器学习模型的训练集和我们在其中测试机器学习模型的性能的测试集。测试集的性能不应该与训练集相差太多。这意味着机器学习模型已经很好地学习了相关性,因此它可以适应新的情况。我们使用 seed 设置一个随机状态来获得相同的结果。使用 sample 函数,我们从数据集中的所有行中随机抽取一个指定大小的样本(Image_16)。这里,我们从数据集中的所有行中获取 75%的训练索引。然后,我们使用整个数据集中的这些索引将数据集划分为 75%的训练集(Image_17)和 25%的测试集(Image_18)。

Image_17:分区后 75%的训练集

Image_18:分区后 25%的测试集

在训练集上训练数据(将多元线性回归拟合到训练集)

**Code Snippet****# Training the data on the training set****## Fit Multiple Linear Regression to the training set**
initial_model <- lm(expenses ~ ., data = training_set)

Image_19:在 Rstudio 的训练集上训练数据

这里,我们使用 lm 函数(Image_19)对训练集进行多元线性回归拟合。我们把医疗费用表示为所有自变量的线性组合,用“费用~ 表示。”在函数中。使用这个函数,我们在训练集上训练我们的初始模型。生成的模型如 Image_20 所示。

Image_20:训练后的初始模型

根据训练数据评估模型性能

**Code Snippet****# Evaluate the model performance on training data** summary(initial_model)**# Interpret on residuals, coefficients, statistical significance of predictors
# & overall model performance — Adjusted R-squared**

Image_21:评估 Rstudio 中训练数据的模型性能

这里我们已经使用 summary 函数获得了初始模型的概要。总结包括四个重要元素残差、系数、预测值的统计显著性&整体模型性能调整的 R 平方(Image_22)。

残差是误差。在低估的情况下,最大误差是 30029。这意味着实际费用高于预测费用。在高估的情况下,最高误差是 11439。这意味着我们收取的费用超过了实际费用。第一个四分位数代表第一个 25%分界点,第三个四分位数代表 75%分界点。第一个四分位数是高估 3060,第三个四分位数是低估 1445,这是可以接受的范围。

当我们查看系数部分时,我们看到 R 确实创建了伪变量&没有落入伪变量陷阱。它自动删除一个虚拟变量,以避免一些冗余的依赖关系。对于每个系数,我们有不同的信息—来自线性回归方程的系数、标准误差、t 值、p 值、显著性水平。对于模型,我们需要看看我们是否有足够的统计上的强变量。这是基于阈值的。一般来说,一个好的阈值是 5%。如果 P 值低于 5%,则自变量在统计上非常显著。它就越会大于 5%。它在统计学上不太重要。带星号的最后一列是解释系数的一种更快速的方法。在所有的独立变量中,年龄、体重指数、孩子和吸烟者是费用的强有力的统计预测因素。一些地区也是强有力的预测者。

调整后的 R 平方告诉我们因变量(医疗费用)的总可变性中有多少可以用模型(选定的自变量)来解释。这里我们得到了 0.7352,这是一个强模型。我们可以通过使用这个值来查看模型是否有所改进。

Image_22:训练数据的初始模型性能摘要

进一步改进和重新评估模型性能

**Code Snippet****## Add a higher order age term**
dataset$age2 <- dataset$age^2**## summary of the BMI column**
summary(dataset$bmi)**## Add an indicator for BMI**
dataset$bmi30 <- ifelse(dataset$bmi >= 30, 1, 0)**## Partition the data again with the additional columns but using the same index**
training_set_new <- dataset[training_index, ]
test_set_new <- dataset[-training_index, ]**## Create the final model**
final_model <- lm(expenses ~ sex + bmi + children + region + age2 + bmi30*smoker,data = training_set_new)**# Evaluate the model performance on the new training data**
summary(final_model)**# Interpret on residuals, coefficients, statistical significance of predictors
# & overall model performance — Adjusted R-squared**

Image_23:使用 Rstudio 中的附加 age^2 列评估训练数据的模型性能

Image_24:使用 Rstudio 中附加的 age^2 列和 bmi 指标列来评估模型在训练数据上的性能

图 25:使用 Rstudio 中的附加 age^2 列以及 bmi 指标列和吸烟者列的组合来评估模型在训练数据上的性能

为了优化我们的初始模型,我们可以做一些操作。引入互动栏目或特色是一种可能。当我们修改我们的初始模型及其性能时,我们用这些额外的列呈现新的训练数据。具有线性关系的年龄通过引入类似 age^新协议的附加列而被视为非线性关系。随着这一新列的添加,调整后的 R 平方值增加到 0.7389,从而提高了模型性能(Image_23 & 26)。此外,对于 Bmi,我们不是将其作为一个连续的值,而是将其作为一个健康与否的因素。我们用一个接近均值的值 30 来区分 bmi 值健康与否。随着这一新列的添加,调整后的 R 平方值增加到 0.7435,从而提高了模型性能(Image_24 & 28)。然后将具有最小 P 值的两列合并,这意味着具有高度的统计显著性。随着这一新列的添加,调整后的 R 平方值增加到 0.8565,从而提高了模型性能&,为我们提供了最佳模型(Image_25 & 29)。

这里我们已经使用 summary 函数获得了最终模型的概要。总结包括三个重要元素残差、系数、预测值的统计显著性和整体模型性能—调整后的 R 平方(Image_29)。

当考虑残差时,在低估的情况下,最高误差为 24059.4。这意味着实际费用高于预测费用。在高估的情况下,最高误差为 4567.1。这意味着我们收取的费用超过了实际费用。第一个四分位数是高估 1768.5,第三个四分位数是高估 747.6,这是可以接受的范围。

对于模型,我们需要看看我们是否有足够的统计上的强变量。这是基于阈值的。一般来说,一个好的阈值是 5%。如果 P 值低于 5%,则自变量在统计上非常显著。它就越会大于 5%。它在统计学上不太重要。带星号的最后一列是解释系数的一种更快速的方法。在所有的自变量中,统计上最强的预测因子是 bmi 指标&吸烟者的乘积,它具有最低的 P 值。高阶年龄&一些区域也是强有力的预测因子。性别和 bmi 列在费用预测中各自具有一定的意义。

调整后的 R 平方告诉我们因变量(医疗费用)的总可变性中有多少可以用模型(选定的自变量)来解释。这里我们得到了 0.8565,这是迄今为止我们得到的最高性能模型。该值比初始模型高得多。

Image_26:带有附加 age^2 列的训练数据的模型性能摘要

Image_27:身体质量指数专栏摘要

Image_28:具有附加 age^2 列和 bmi 指示列的训练数据的模型性能摘要

图 29:具有额外的 age^2 列以及 bmi 指标列和吸烟者列的组合的训练数据的最终模型性能摘要

用改进的模型预测测试集结果

**Code Snippet****# Predicting the test set results with the improved** modelmedicalExpensesPredicted = predict(final_model, newdata = test_set_new)cor(medicalExpensesPredicted, test_set_new$expenses)
plot(medicalExpensesPredicted, test_set_new$expenses)
abline(a = 0, b = 1, col = “red”, lwd = 3, lty = 2)

Image_30:使用 Rstudio 中的改进模型预测测试集结果

这里,我们使用预测函数(Image_30)通过改进的模型对新的测试数据(test_set_new)进行预测。我们使用 cor 函数比较测试集中预测医疗费用和实际医疗费用的相关性,得到的值为 0.9432327,这意味着它们高度相关,具有良好的准确性(Image_31)。这里我们绘制了预测与实际医疗费用的对比图(图 32)。很少有异常值,但该图表明在大多数情况下,实际结果和预期结果是一致的。你可以在这里下载上面例子的 R 脚本。

Image_31:改进模型的预测测试集结果

Image_32:绘制预测与实际医疗费用的对比图

现在你可能已经意识到,当你使用 RStudio 这样的工具时,数据分析并不是一个非常困难的过程。您可以将在本指南中获得的知识应用到任何其他感兴趣的领域。

使用 Julia 分析您的健康和健身数据

原文:https://towardsdatascience.com/analyze-your-health-and-fitness-data-using-julia-d6f4c3842b17?source=collection_archive---------17-----------------------

一个简单的数据科学项目,为您的编码周末增添趣味

阿图尔·尤奇卡在 Unsplash 拍摄的照片

我几乎每天都戴手表。我的习惯性合作伙伴是三星 Gear S3 Frontier,这是我在 2018 年生日时买的。除了手表的常见功能外,它还有一系列传感器来记录各种活动,如步数、距离、爬过的楼层和心率(通过光电容积描记图)。较新的银河系列手表还具有记录血氧和 EKG 的传感器。作为一个技术呆子,这自然让我兴奋!

这些传感器记录的数据被传递到三星健康应用程序,该应用程序已经很好地将它们总结成漂亮的视觉效果。然而,作为一名程序员,我一直渴望用它做更多的事情。幸运的是,三星允许我们下载原始数据。csv 文件)直接从应用程序。如果您是三星手表/手机用户,您可以按照本文文章中的说明下载您的健康数据。我想对于 Fitbit 和 Garmin 用户来说也有这样做的方法。如果你发现一些有用的东西,请在评论中告诉我。

在本指南中,我们将利用 Julia 生态系统中的各种软件包。我使用 Pluto.jl 做了这个练习,它允许我们创建交互式代码笔记本(此处可用)。也可以选择自己的编辑器比如 VS Code。

设置冥王星

如果你是 Julia 的新手,你首先需要从这里安装适合你的系统的二进制文件。一装好,打开朱丽亚·REPL。按“]”进入 Pkg (Julia 的内置包管理器)提示符。然后输入add Pluto。这将下载 Pluto 包并为您编译它。按 backspace 键返回 Julia 提示符。然后键入using Pluto,后面跟着Pluto.run()。应该会打开一个新的浏览器窗口,显示 Pluto 主页。您可以继续创建新笔记本。

如果你熟悉 Jupyter,你已经知道如何使用冥王星。但是,请记住以下特性:

  • 冥王星是一个反应式笔记本,这意味着细胞之间是相互联系的。当您更新一个单元格时,依赖于它的所有其他单元格也会更新。这也意味着你不能在两个地方使用相同的变量名,除非它们的作用域是局部的(比如在函数中)。
  • 当在一个代码单元中写多行时,需要在 begin-end 块中换行。当执行(shift + enter)这样一个程序块时,您将得到一个选项来自动完成这个操作。

要在您的工作环境中导入所有相关的包,请执行以下命令:

using PlutoUI, DataFrames, CSV, Query, VegaLite, Dates, HTTP, Statistics

获取输入数据

我们将使用 CSV.jl 直接从我的 GitHub 存储库中读取数据,并以数据帧的形式存储它们。为了可视化,我们将使用优秀的 VegaLite.jl 包。来自三星健康应用程序的数据以各种 csv 文件的形式提供,但是,我们将只使用以下三种文件:

  • com . Samsung . shea lth . tracker . pedometer _ day _ summary。。战斗支援车
  • com . Samsung . shea lth . tracker . heart _ rate。。战斗支援车
  • com . Samsung . health . floors _ clipped。。战斗支援车

文件名是不言自明的。我们可以将数据直接读入数据帧,如下所示。我们设置 header = 2,这样第二行用于命名列。

将 CSV 文件读入各自的数据帧

清洁和一些组织

让我们探索一下我们的数据帧实际包含了什么。

您也可以尝试以下方法:

create_time 列表示记录数据条目的时间,类型为“字符串”。我们需要将它转换成一个“DateTime”对象,这样以后就可以进行排序和更容易的绘图。此外,我们还可以将距离列转换为 km(从 m 开始),将活动时间转换为分钟。最后,我们通过删除重复条目来清理数据帧,并对 w.r.t. time 进行排序。

清洁和分类操作

我们计算累积距离,并将其添加到单独的列 cumul_distance 。为了以后的使用,将日子分类为“工作日”或“周末”,并将它们添加到单独的 day_type 列也很方便。对于新的列也是如此。

添加新列

基于时间的过滤

使用 PlutoUI.jl 包,我们可以通过添加按钮、滑块等来进一步增强交互体验。例如,要将日期时间值绑定到变量 start_date,执行以下操作。

插入交互式日期选择器

根据上面选择的时间范围过滤数据帧。 @filterQuery.jl 包提供的强大宏。我们筛选出创建时间位于开始日期结束日期之间的行,如下所示:

使用 Query.jl 进行过滤

现在我们准备开始可视化数据。

每日步骤

我们过滤后的数据帧 df_pedometer_filter 可以直接传递给 VegaLite.jl 包提供的 @vlplot 宏。其余的参数是特定于绘图类型的。查看 VegaLite.jl 教程了解更多信息。

用线梯度绘制每日步数

很明显,2020 年我走的步数少了很多。这可能是由于电晕爆发期间实施的封锁。很高兴看到我在 2021 年加快了步伐。相同的数据也可以可视化为堆叠直方图。

绘制每日步数的堆积直方图

每天的默认目标设置为 6000 步。我总是试图至少达到那里,因此三年的峰值都在那个值附近。对于 2020 年,有很多天我的活动量如预期的那样低。

每日距离

我喜欢每天去散步。除了步数,看看我通常走多远也是很有趣的。在我们的 DataFrame 中将色标设置为 distance 列,以与每个数据点的大小成比例的渐变来呈现条形。看起来相当酷!

将每日距离绘制成带颜色渐变的条形

累积距离

有趣的是,我还可以检查到目前为止我已经跑了多少公里。我猜达到 10,000 公里会是一个不错的目标。

将累积距离绘制成面积

有效时间

这是在任何活动(行走、跑步等)中花费的时间。)如手表所检测到的。如果您还记得的话,我们之前已经根据是工作日还是周末添加了一个 day_type 列。现在,我们可以利用它来相应地对我们的活动时间进行分组。

使用日类型分组的绘图活动时间

我们还可以简单地通过将参数列表中的color = :day参数更改为 @vlplot 宏来对每天的活动时间进行细分。

似乎我在周二和周三很活跃,周六最不活跃。这有意义吗?

步数和卡路里之间的相关性

绘制 2D 直方图,显示步数与卡路里的关系

您可以在 Pluto 中创建一个滑块(需要 PlutoUI.jl 包),并将其值绑定到 select_year 变量,如下所示:

正如所料,步数和消耗的总热量有直接的关系。该 2D 直方图散点图还显示了大小与总计数成比例的标记。步数越多,数据点越少。今年我应该试着更加积极。

步数与活动时间的热图

绘制步数与卡路里的热图

可视化心率数据

心率数据也可以使用类似的策略进行清理,如前所示。

使用圆形标记和与数值成比例的尺寸绘制心率数据

我的手表每隔 10 分钟测量一次心率。我几乎每天都穿。这意味着大多数数据点是在我坐在办公桌前工作时收集的。让我们看看分布是什么样的。

绘制心率分布图,色标设置为数值的大小

大多数数据似乎集中在每分钟 60-100 次(bpm)的静息心率范围,平均值约为 78-79 BPM。那就放心了!相当高的值可能是在运行会话期间测量的。

攀爬的楼层数

爬过的楼层数

这里没有什么太令人兴奋的,除了 2019 年 11 月的大幅飙升。在印度奈尼塔尔市的一次短途徒步旅行中,我戴着这只手表。9 英尺的高度变化被记录为一次楼层爬升。所以,65 层楼表明我在那段时间里一定爬了 585 英尺~ 178 米。唷!

结论

朱莉娅的生态系统正在迅速发展,有许多令人惊叹的绘图包,而 VegaLite.jl 恰好是其中之一。图形风格的优雅语法和与 DataFrames 的紧密集成使其成为任何类型的数据科学/分析项目的理想选择。我希望您喜欢阅读本指南。完整代码(冥王星笔记本)可以在这里找到。感谢您的宝贵时间!如果你想联系,这是我的 LinkedIn。

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

参考

  1. 分析三星健康步骤数据
  2. 从你的三星中提取健康数据
  3. VegaLite.jl

用 SQL 分析 120 年奥运历史

原文:https://towardsdatascience.com/analyzing-120-years-of-olympics-history-with-sql-11d4daace4d0?source=collection_archive---------19-----------------------

SQL 实践教程

马特·李在 Unsplash 上的照片

我在 Kaggle 上发现了一个很棒的数据集。它是在知识共享许可下共享的,所以我们可以公开使用和共享它。我认为了解奥运会的历史将是令人兴奋的。

有许多替代工具可用于对此数据集执行分析。我选择 SQL 没有特别的原因。在本文中,我们将在练习 SQL 的同时了解奥运会。

注意: SQL 被很多关系数据库管理系统使用,比如 MySQL、SQL Server、PostgreSQL 等等。尽管它们大多采用相同的 SQL 语法,但可能会有一些细微的差别。在本文中,我们将使用 PostgreSQL。

我选择了一些列,并将数据上传到一个 SQL 表中。让我们先来看看奥运表。

SELECT * FROM olympics LIMIT 5

(图片由作者提供)

我们有运动员的名字、性别、年龄和他们参加的运动。该表还包含游戏的详细信息。原始数据集包含 271116 行,但是我只上传了 200000 行到 olympics 表。如果对整个数据集进行相同的分析,结果可能会略有不同。

我想看看有多少不同的运动员参加了奥运会。我们可以数出不同的名字。

SELECT COUNT(DISTINCT(name)) FROM olympics99875

这张桌子上有近 10 万名不同的运动员。我想知道他们中有多少人获得了奖牌。

SELECT COUNT(DISTINCT(name)) FROM olympics
WHERE medal IS NOT NULL20560

我们刚刚使用 where 语句添加了一个条件。

让我们找出奖牌总数前 3 名的国家。

SELECT team, COUNT(medal) AS medal_won
FROM olympics
WHERE medal IS NOT NULL
GROUP BY team
ORDER BY medal_won DESC
LIMIT 3

(图片由作者提供)

上面的查询过滤了 medal 列没有空值的行。然后,根据团队列对行进行分组,并对行进行计数,这就给出了获得的奖牌数。最后,结果集按奖牌数降序排序,选择前三个。

了解获得奖牌的男女运动员的平均年龄是很有趣的。

SELECT sex, AVG(age) AS avg_age
FROM olympics
WHERE medal IS NOT NULL
GROUP BY sex

(图片由作者提供)

女运动员比男运动员小两岁。

我们还可以查看女运动员获得奖牌最多的前 5 项运动。

SELECT sport, COUNT(medal) AS medal_count 
FROM olympics
WHERE sex = 'F'
GROUP BY sport
ORDER BY medal_count DESC
LIMIT 5

(图片由作者提供)

考虑到我们对比赛年份感兴趣。该表没有单独的年份列,但可以从游戏列中提取。

SELECT LEFT(games, 4) AS year, games
FROM olympics
LIMIT 5

(图片由作者提供)

左边的函数允许从字符串中选择部分。它接受列名和要选择的字符数。right 函数做同样的事情,但是从右边开始计数。

下一个示例与其说是探索数据集,不如说是 SQL 实践。考虑到我们只需要 1950 年以后的数据。我们可以删除属于 1950 年或之前的游戏的行,或者用我们感兴趣的数据创建一个新表。

以下查询使用 olympics 表中的数据创建一个新表。

CREATE TABLE olympics_after_1950 AS
SELECT * FROM olympics
WHERE CAST(LEFT(games, 4) AS INTEGER) > 1950

让我们检查一下查询是否工作正常。

SELECT MIN(LEFT(games, 4)) FROM olympics_after_19501952

令人惊讶的是,create table 语句用于创建表😃。我们可以通过使用 select 语句和 create table 语句从不同的表中选择数据来填充新表。

我们还可以通过删除属于 1950 年或之前的奥运会的行来更新奥林匹克表。我想保持原来的桌子不变。我们可以在新表上练习 update 语句。

让我们删除新表中 1970 年之前的行,然后检查最小日期。

DELETE FROM olympics_after_1950
WHERE CAST(LEFT(games, 4) AS INTEGER) < 1970SELECT MIN(LEFT(games, 4)) FROM olympics_after_19501972

我们做了几个例子来深入了解奥林匹克的历史。我们还练习了基本的 SQL 语句和函数。

感谢您的阅读。如果您有任何反馈,请告诉我。

分析和解释评分表中的数据

原文:https://towardsdatascience.com/analyzing-and-interpreting-data-from-rating-scales-d169d66211db?source=collection_archive---------8-----------------------

使用学生/客户满意度调查数据的两部分指导性案例研究

注:本帖代码可在 这里 找到

仔细查看评分标准(图片由作者提供)

等级量表是衡量态度和观点的一种有效且受欢迎的方式。它们易于实现,广泛用于调查、反馈表和绩效评估。然而,误用和错误经常发生在这个看似直观的工具的实现和分析中。理解和综合评定等级信息的能力使我们能够在不断变化的环境中做出决策。这个由两部分组成的系列的目标是展示有效利用评定等级数据所需的基本概念以及关于常见陷阱的警告。在第一部分中,我们从定性考虑开始,这对于第二部分中讨论的定量分析的适当性具有重要意义。****

数据集介绍

在我们的案例研究中,我们将使用我从数据分析课上收集的每周调查结果。这些匿名调查要求所有学生每周进行。这些说明要求学生对以下每个因素进行 1(差)到 5(好)的评分,从“总体满意度”的总体评分开始。我们的目标是深入了解学生对整个课程的感受。

反馈形式问题

了解评定等级

每个评定等级都作为一个封闭式问题来实施,以获取信息。它要求回答者根据说明给被评对象赋值。正确使用时,等级量表可作为非物理属性的测量工具。不同于我们用来测量物理属性的科学仪器(例如测量温度的温度计和测量长度的尺子),等级量表可以用来测量本质上是认知的属性。因为它们是抽象的、无形的和复杂的,所以通常不能用一个问题来概括。相反,我们可以问一系列涉及主题不同方面(或因素)的相关问题,我们称之为“兴趣结构”。对这些个别但相关问题的回答更多的是基础陈述性。****

评级标准的类型

有 4 个基本级别的测量尺度用于采集数据。每个秤都是一个级增量级测量,即每个秤都实现前一个秤的功能。在分析数据时,首先理解变量代表什么是很重要的。

4 种测量尺度

附注:评级尺度分析的一个常见缺陷是假设选择之间的距离相等。

可用于名义秤的分析类型非常有限,因为它缺乏数字属性。它们很容易实现,但只对分类数据有用。更常见的评级尺度是序数或区间,其中的选择带有等级顺序属性。两者之间的差异可以是细微的,但是从分析的角度来看的含义是相当显著的。在决定实施/应该实施哪一项时,我们会考虑受访者是否认为(所有)选项是等距的。这种不足使使用参数统计数据进行序数标度的能力受到质疑,但有时可能是首选,因为它们相对容易使用。另一方面, Interval Scales 将选项设计为均匀间隔(即,不同选项之间的差异幅度相同),这可以通过将单词锚与序列号相关联来实现。这种方法利用了人们对数字线的直觉,支持使用均值标准差以及其他统计方法。我们正在分析的数据来自区间尺度;因此,受访者选择的幅度和差异是有意义的,尽管这并不意味着选择#4 的强度是选择#2 的两倍(对于比率等级来说是这样的)。

测量仪器具有可靠性和有效性

评级尺度衡量难以定义的缺乏验证标准的;因此很难知道他们什么时候按计划工作。评定量表的有效性可以通过可靠性有效性进行评估,定义如下:

  • 可靠性(意味着稳定性一致性** ) —如果重复使用,仪器会产生相同的结果。**
  • 有效性(意味着准确性** ) —仪器准确测量它应该测量的东西。**

Fido 教授可靠性和有效性

我们打个比方来强调信度和效度的重要性。假设我们相信一只叫 Fido 的狗已经被训练来警告危险的血糖事件。他们通过检测与这些血糖水平下的生物化学相关的气味来做到这一点。Fido 在许多方面起着测量工具的作用。在它们被认证为官方糖尿病警戒犬之前,我们必须首先评估它们的可靠性和有效性。出于可靠性考虑,我们希望确保它们能够持续向人类同伴发出警告信号。他们应该表现出对周围环境干扰的抵抗力,并且警告信号不是不稳定的。为了有效性,我们希望确保他们的警告信号是异常血糖事件的真实指示。他们的警告信号应该伴随着来自患者佩戴的 BGM(血糖监测器)的过高或过低的读数。

测量可靠性和有效性

对信度和效度进行定性评估和定量评估。为了获得对可靠性和有效性估计的信心,我们的数据应该有足够的样本量和一定的可变性(如下直方图所示)。重要的是要记住,我们计算的估计值主要用于评估研究方法的质量,而不一定对结果做出推断。********

调查中各因素的评分分布

可靠性

可靠性是指如果在相同的条件下再次使用评定量表,评定量表会给出相同结果的程度,即其稳定性 y 或一致性 c y。没有可靠性,我们就不能确定来自评定量表的数据是有意义的且不是(部分)随机的。我们可以通过观察两组(或更多组)测量值之间的相似性来量化可靠性,即一致度 e。实际上,有 4 种类型的可靠性可以比较来自相同等级量表的不同结果组,如下散点图所示:

不同类型的一致性

对于区间数据,使用相关性来估计可靠性是合适的,从广义上讲,它衡量两个变量之间的关系(而不是一致性)。可靠性可以显示一个评级尺度抵抗可能影响人们准确反应能力的外部因素的能力,例如不清楚的指示选择标签。很难给什么被认为是可靠的划定一个门槛;因此,检查 4 种可靠性类型中的每一种(视情况而定)来寻找和审查不可靠性的证据是合适的:

  • 重测信度考察的是同一受访者在一段时间内所取得结果的一致性。它用于评估评级尺度抵御外部因素(如受访者在调查时的情绪)的能力。它可以表示为在不同时间点进行的调查之间配对结果的相关性 ( 皮尔森),如图表 A)B) 所示。这也被称为班内可靠性,它假设学生每周都会有类似的反应,因为他们对班级的看法不会有实质性的改变。增加测试和重新测试之间的时间(以减少记忆效应)会随着时间的推移引入真正变化的前景,使观察可靠性变得更加困难。

重测信度(评分者内部信度)

B1) 中,我们对结果本身进行绘图,以产生完美的相关性。这是为了模拟两个时间点的结果是否相同且高度可靠。在 B2)B3) 中,数据被认为不太可靠,因为受访者选择了递增的不同评分,例如,第一次回答 4,第二次回答 3 或 5。这可能是由于对指令或选择的不同解释,导致了较低的相关性。我们数据的实际结果显示在 B4) 中,相关系数约为 0.65,这并不坏,因为我们确实期望观点会改变。值得注意的是,第 3 周和第 6 周之间的相关性下降(如 C) 所示),可能是由于寒假期间的时间差。

  • 内部一致性顾名思义,寻求旨在测量相同结构的项目结果的一致性。换句话说,调查中相关问题的结果是一致的还是相互矛盾的。首先是每个评级尺度之间的成对相关性 ( 皮尔森),如附件 A)B) 所示。

内部相容性

B) 中,我们用热图绘制了评级尺度之间的成对相关性。不出所料,所有个人因素都与全球“总体满意度”评级相关。这表明,这些因素中的高评级对应于“总体满意度”中的高评级,反之亦然。此外,与讲师相关的问题的结果(清晰度、知识和参与度)具有很高的相关性。相关性可以通过克朗巴赫的阿尔法来总结,对我们的数据来说是> 0.8。我们发现“课外应用学习”和“教师知识”之间的相关性较低,以及“课外应用学习”和“学术支持”之间的相关性较低,这是可以接受的,因为它们之间的相关性较小。

  • 评分者间可靠性着眼于不同人的结果的一致性。它用于评估主观性对受访者选择的影响程度。可以使用回答者之间的成对相关性 ( Pearson )进行计算,如附件 A)B) 所示。虽然单个受访者之间的相关性不太重要,但它们应该作为一个整体反映一些普遍的一致(如克朗巴赫的阿尔法等可靠性系数所总结的)。

评分者间信度

B) 中,我们用热图绘制了学生之间的两两关联。除了少数例外,大多数相关性都是> 0.6。只要大多数学生能够作出类似的回答,那么一小部分与他人相关性较低的受访者是可以接受的。

Pearson 相关性的使用仅适用于区间数据,在较小程度上适用于顺序数据,因为它保持了选择之间的顺序关系。对于名义数据,一致性可以用总体一致性百分比或 Fleiss/Cohen 的 Kappa 来衡量。

  • ****平行(或等效)形式可靠性要求相同的回答者接受不同版本的调查,这些调查被设计为等效的。或者,这可以通过创建一大组问题并将它们随机分成两组来实现。遗憾的是,我们没有使用可替换的调查问题。

有效期

有效性是指评定量表的结果在多大程度上代表了其预期目的,即准确性。当测量具有可靠性时,我们更加有信心认为结果代表了它们应该代表的东西;因此,有效性是基于可靠性的,但是可靠性本身是不够的——等级量表可以非常可靠,但是无效。确定测量有效性的最明显的方法是将其与基准进行比较。与基准可比的度量更有可能是有效的,但不幸的是它们并不总是存在。在这里,我们将基准称为 1) 一种用于测量感兴趣的构建体的成熟方法,或者 2) 一种与感兴趣的构建体相关的群体统计。即使基准不完全匹配,比较也有助于验证评级尺度。有效性有三种类型:

  • 表面有效性着眼于评定等级与被测概念的现有理论和知识的一致性。另一方面,内容有效性关注调查在多大程度上覆盖了感兴趣的结构的所有方面。它们都是定性评估,最好通过征求双方 专家参与者的反馈来实现。此外,对问题和选择的描述应该清晰、透彻、完整地阐述感兴趣的结构。根据我们的数据,我们咨询了教育领域的专家,以确保调查问题全面且与学生关心的问题密切相关。
  • ****标准有效性检验评级量表的结果与旨在衡量类似结构的不同方法的结果有多接近。我们比较的结果是标准,它通常来自一个已建立的或广泛使用的方法。这两者之间的高度相关性很好地表明,评级尺度是衡量什么是声称。我们希望在我们的调查中建立等级量表的有效性,因此我们寻找比较的方法。代替真正的“黄金标准”标准,我们可以使用开始时收集的全球“总体满意度”评级来评估其他因素的有效性。合理的假设是,个人因素的评级有所贡献,因此应该与满意度评级相关联。

并行有效性

综合指数(单个因素的总和)和加权综合指数都与总体满意度相关。这被称为并发有效性,因为它的总体满意度与其他问题同时进行。

预测效度

为了寻找更多有效性的证据,我们可以用学生每周作业中的数据来扩充我们的调查结果。我们发现“作业反馈评级”和评分者对学生作业提交的反馈中的字数有很高的相关性。此外,学业支持与作业成绩也有很高的相关性。这被称为预测有效性,因为这些变量是在稍后的时间点收集的。

准备信度和效度的方法

在调查进行之前,我们不会知道它有多可靠或有效。如果操作不当,即使是精心设计的评级标准也会遇到问题。以下是一些提高可靠性和有效性的技巧:

  • 彻底设计并采纳他人的意见——从明确定义的目的、目标甚至收集方法开始,需要进行大量规划以确保调查成功。应对促成感兴趣的构建的因素进行映射,以确保包括所有相关方面。
  • 考虑受访者的偏好/努力—容易回答的问题可确保高参与率。另一方面,难以使用或理解的评级标准会导致回答者变得沮丧和消极,从而降低他们回答的质量。
  • 避免偏差来源——以下是评定等级中常见的偏差来源:

偏差的不同来源

摘要

在本文中,我们对来自学生/客户满意度调查的评级尺度数据进行了定性评估。我们期望数据的可靠性和有效性,但要做到这两点还需要大量的工作。为了最大限度地利用评分量表,我们应该在可靠性、有效性、辨别能力和受访者偏好之间进行权衡分析。随着计算技术的进步,数据收集方法变得比以往更加灵活、适应性更强、效率更高。我乐观地认为,这类研究中的巨大机会将继续帮助组织满足其成员的需求。

接下来,我们将对相同的数据进行定量分析。如果你喜欢这篇文章,我邀请你跟我来,这样你就可以在第二部分得到通知。

分析和预测消费者参与度

原文:https://towardsdatascience.com/analyzing-and-predicting-consumer-engagement-8b3229f0cbad?source=collection_archive---------10-----------------------

我们将使用来自 Kaggle 的互联网新闻和消费者参与数据集来分析消费者数据,预测热门文章和受欢迎程度评分。

在 Unsplash 上视觉拍摄的照片

介绍

在这个项目中,我们将使用来自 Kaggle 的互联网新闻和消费者参与数据集来预测热门文章和受欢迎程度评分。我们将探索我们的数据,以发现模式,如相关性,分布,均值和时间序列分析。我们将使用文本回归和文本分类模型来预测参与度得分和基于标题的热门文章。

文本分类在我们日常使用的应用程序中很常见。例如,电子邮件提供商使用文本分类来过滤掉收件箱中的垃圾邮件。文本分类的另一个最常见的用途是在客户服务中,他们使用情感分析来区分差评和好评 ADDI AI 2050 。我们将在标题上训练我们的模型,以便它可以预测文章是否在顶部。文本回归是类似的,其中我们采用文本矢量化数据并预测十进制值的流行度得分。

我们的重点将放在文章标题以及它如何影响其他功能上。

资料组

该数据集(源)受知识共享— CC0 1.0 通用许可,有关更多信息,请查看此处的元数据信息。该数据集是关于 2019 年 9 月 3 日至 2019 年 10 月 4 日收集的新闻文章。随后,脸书参与度数据(如分享数、评论和反应)丰富了这一数据。

  • Source id 列值表示发布者的唯一标识符,通常表示为小写的 sourcename,空格替换为下划线符号。
  • Source_name 列值表示发布者名称。
  • 作者列值表示文章作者。一些出版商不共享他们的新闻作者的信息,在这种情况下,通常 source_name 会替换这些信息。
  • 标题列值表示文章的标题。
  • 描述列值表示通常在发布者网站的弹出窗口或推荐框中可见的短文描述。这个字段被缩短为几个句子的内容列。
  • Url 列值指示位于发布者网站上的文章的 URL(统一资源定位符)。
  • Url 图像列值表示与文章相关联的主图像的 Url。
  • Published_at 列值表示发布文章的确切日期和时间。日期和时间以 UTC (+000)时间格式显示。
  • 内容列值表示文章的无格式内容。该字段被截断为 260 个字符。
  • Top_article 列值表示文章在发布者网站上被列为热门文章。该字段只能有两个值,当文章包含在流行/热门文章组中时为 1,否则为 0。

安装所需的软件包

我们将安装用于情感分析的 vaderSentiment,显示最常用词的 wordcloud,用于机器学习模型的 lightgbm,以及用于不平衡分类的 imblearn。

加载所需的库

探索数据

在这一部分中,我们将探索我们的数据并可视化关键特征,以理解消费者参与度。

加载数据

经过初步审查的数据集包含 10437 条记录和 14 列。

我们将重点关注:

  • 文章标题
  • 来源名称
  • 作者
  • 热门文章
  • 用户参与特征。

缺少值

使用.isna().sum()我们可以检查每一列的缺失值。为了让它看起来更有趣,我们将我们的发现转换成一个带有NA percent和颜色渐变背景的表格。正如我们可以观察到的,大多数内容作者名称列都缺少值。

前十名作者和来源名称

使用 seaborn 条形图,我们显示了前 10 名作者和来源名称。我们可以看到有些作者的名字与 publication/sources 相似。前三大主要来源是路透社、BBC 新闻和爱尔兰时报。排名前三的作者分别是美联社、路透社和 CBS 新闻。

顶级文章

使用 matplotlib 饼图,我们可以看到有 12%的热门文章。

接合箱线图

很难分析参与度数据的分布,因为它们有极端的异常值。我们可以使用sns.kdeplotnp.log1p来分析每个参与列,但是有一个更好的方法是使用 boxplot,将 yscale 设置为Symlog

  • 接合反应计数有 1 个中值,但它有多个平均值在 0–60 之间的异常值。
  • 参与评论计数为 0 中等,但有多个平均值在 0-1 之间的异常值。
  • 参与份额计数为 10 中等,但有多个平均值在 0-50 之间的异常值。
  • 参与评论插件计数为 0 中等,但它有多个平均值为 0 的异常值。

评论插件

让我们看看评论插件,因为它有最奇怪的数据,平均值和中值都是 0。正如我们所看到的,99%的数据是零,其余的是 1-15 的异常值。

干净的标题

让我们清理标题,因为我们将在机器学习模型中使用它。我们的文本数据中有标点符号和大写单词,这将使我们的模型表现最差。

clean_title函数将清除括号、超链接、标点和包含数字的单词。

添加包含干净标题的新列

创造情感极性

使用 Vader 情绪强度分析器,我们将从干净的标题中提取分数,并将其分为 3 类:积极、消极和中性。

应用复合分数

运用情感

正如我们所看到的,我们已经在数据集中添加了 2 列,分别是情绪得分和基于得分的情感。

情感类别计数图

新闻标题多有中性情绪和负面情绪看新闻。

词云

我们将使用单词云库来显示标题和描述中最常用的单词。

最常见的单词是 say、new、said、will 和 Trump 。我们使用英语停用词来删除每个句子中的常用词。

时间序列

我们将在 2019 年 9 月 3 日至 2019 年 10 月 3 日期间策划消费者互动。

分割日期时间

我们将把日期拆分成星期、月份和年份,然后将它们添加到数据帧中。

一个月的雇佣次数

使用 seaborn 折线图显示一个月内的消费者参与模式。十月一日,消费者参与度出现高峰。可能是因为某个重大事件。除此之外,在 9 月 3 日、7 日和 12 日还有较小的反应高峰。

关联热图

反应、评论和分享参与度之间存在高度正相关。喜欢帖子的消费者最有可能分享和评论。约定和顶级文章之间没有其他显著的相关性,很明显,顶级文章的选择纯粹基于质量。

预处理

  • 替换丢失的标题
  • 将标题转换成矢量
  • 替换 top_article 中缺少的值
  • 使用 SMOTE 进行过采样
  • 创造人气 pcore

Tfidf 矢量器

我们的机器学习模型只理解数值,因此为了在文本数据上训练我们的模型,我们将把它转换成 TF-IDF 特征的矩阵。 SKlearn

过采样

我们的top_article数据是不平衡的,因为我们只有 12%的 1。为了使我们的模型性能更好,我们将使用过采样方法 SMOTE(合成少数过采样技术)。我也尝试过其他过采样和欠采样方法,但 SMOTE 表现更好。

受欢迎程度得分

我们将添加所有四个参与列,然后采取类似于np.log(X+1)np.log1p(X)。许多零约定将导致无穷大,因此将所有列加 1 将避免灾难。

我们可以清楚地看到大部分分布在 0-3 之间。

我们可以清楚地看到,最受欢迎的两家出版公司是《纽约时报》和 CNN。

测试分类器模型

让我们建立一个模型,该模型将获取标题并预测文章是否会成为热门。

  • x:标题
  • y:热门文章

建立模型

我们已经用 SGD 和随机森林分类器进行了实验,但是到目前为止,光照梯度增强模型表现得更好。在超参数调整之后,我们的模型就可以在数据集上训练了。

  • 分为训练和测试。
  • 将我们的置顶文章分层,使它们平均分布。
  • 使用 LGBMClassifier
  • 学习率=0.5,
  • max_depth=20,
  • num_leaves=50
  • n _ 估计值=120,
  • max_bin=2000
  • 交互效度分析
  • 培训和测试
  • 混淆矩阵

交互效度分析

在对我们的模型进行交叉验证后,我们可以观察到我们的 f1 分数相当稳定。0.9 是我们能达到的最高值。

训练/测试模型

在训练数据集上拟合我们的模型后,我们可以看到f1accuracy_scores在我们的测试数据集上都是+0.9。

保存模型

混淆矩阵

我们有一些假阳性和假阴性。总的来说,我们的 LGBM 模型表现得比预期的要好。

文本回归模型

  • x:标题
  • y:人气 _ 分数

我们将使用矢量化标题来预测受欢迎程度得分。我已经用逻辑回归和随机森林回归进行了实验,但是在我们的例子中,光梯度增强表现得很好。

  • 用 1 填充缺失值。
  • 训练和测试分割
  • LGBMRegressor
  • 学习率=0.01,
  • max_depth=20,
  • num_leaves=50
  • n _ 估计值=150
  • 交互效度分析
  • 培训和测试

列车测试分离

建立模型

验证分数

该模型表现良好,因为没有超参数调整和逻辑回归,得分为 8+ RMSE。

培训和测试

在训练数据集上拟合模型之后,似乎我们的模型在测试数据集上也表现得很好。现在,我们将使用这两个模型来构建标题评分函数。

保存模型

标题评分

title_score函数获取标题并输出流行度得分,对热门文章进行分类。全面参与,包括反应、分享和评论。我们可以使用这些功能为我们的博客创造最好的标题。

功能任务:

  • 清理文本
  • 将文本矢量化
  • 预测热门文章和受欢迎程度
  • 打印热门文章、受欢迎程度得分和总参与度。

测试

是时候测试我们的功能和预测模型了。我们将首先测试数据集内的随机值,然后使用今天新闻的标题来确定分数。

正如我们可以清楚地看到我们的功能和两个模型的工作。

最新消息

随机测试最新消息

热门新闻测试

正如我们所见,它得到了很高的受欢迎程度。

我们再次测试了新闻头条,正如我们所见,根据我们的模型,它是头条。

结论

我们在探索数据和玩不同的机器学习技术和模型中获得了乐趣。简而言之,我们探索了我们的数据,并提供了独特的信息,可以帮助新闻机构创造更好的内容,从消费者那里获得高牵引力。我们开发了机器学习模型,将帮助作家和博客写手写出更好的标题。我们还发现,高人气并不意味着这篇文章会成为头条。

对于未来的工作,我想探索数据中的多个聚类,并使用文章的图像创建一个模型来预测受欢迎程度得分。我已经试验了深度学习文本生成模型,但由于内存限制,我仅限于简单的表格模型。

为了学习更多关于数据分析、自然语言处理和机器学习的知识,我建议你参加一个令人惊叹的 DataCamp 课程,并自己练习。

密码

代码可从以下网址获得:

  • T3
  • Deepnote 项目
  • DataCamp 项目
  • Kaggle
  • GitHub
  • DAGsHub

作者

阿比德·阿里·阿万 ( @1abidaliawan )是一名认证数据科学家专业人士,热爱构建机器学习模型和研究最新的人工智能技术。目前在 PEC-PITC 测试人工智能产品,他们的工作后来获得批准用于人体试验,如乳腺癌分类器。

分析和可视化来自非结构化数据的情感

原文:https://towardsdatascience.com/analyzing-and-visualizing-sentiments-from-unstructured-raw-data-c263ba96cc2c?source=collection_archive---------37-----------------------

使用 Microsoft Azure 文本分析和 Power BI 集成

梅森·琼斯在 Unsplash 上拍摄的照片

情感分析

微软 Azure 认知服务和 Power BI 集成

全球创建、捕获、复制和消费的数据总量预计将快速增长,在 2021 年达到 74 兆字节(来源:Statista)。想象一下,这 74 个 zettabytes 的数据中有多少将是非结构化的和不受控制的,留下一个巨大的空白💣世界各地的数据科学家将如何分析、建模和消费这些庞大的数据。例如,亚马逊等电子商务网站上的产品评论,或者脸书和 Twitter 等社交媒体巨头的言论自由。

非结构化数据面临的主要挑战之一是如何衡量公众意见,进行细致入微的市场研究,监控品牌和产品声誉,以及了解客户体验。通俗地说,如何理解和分类情绪,或者对于数据科学家来说,如何进行情绪分析。情感分析是确定一篇文章是正面、负面还是中性的过程。

我们将讨论什么?

在本案例中,我们将对一组样本数据进行情感分析,并使用:

  1. Microsoft Azure 文本分析(用于执行情感分析)
  2. Power BI(用于集成和可视化)

以下是我们将使用的示例数据的链接: 示例数据

所需资源

  • Microsoft Azure 订阅(免费试用或付费)
  • 微软商务智能桌面(专业版许可)

你准备好了吗??我们开始吧🏄

第一步:Azure 文本分析

登录 Azure 门户:https://portal.azure.com/#home,搜索“文本分析

Azure 门户主屏幕搜索栏

通过选择订阅、创建资源组(只是绑定资源的容器)、位置和定价层来创建文本分析服务。一个免费的网络容器每月允许5000 笔免费交易 。点击“查看+创建”后,Azure 可能需要几分钟来创建资源。

创建文本分析服务

创建文本分析资源后,导航至“密钥和端点”,将密钥和端点详细信息复制到记事本中。

⚠️请注意,密钥和端点不应透露给未经授权的人,因为它们可能会影响你的 azure 消费成本。如果您不小心泄露了密钥,请重新生成密钥。

现在,您已经完成了 Azure 门户部分,可以导航到 Power BI。

密钥和端点在 Power BI 集成中发挥着重要作用,确保它们的安全

步骤 2:电源 BI 集成

打开 Power BI desktop 的一个新实例>>从 Excel 导入数据>>浏览样本数据文件> >宾果! 您在 Power BI 中导入了数据集,离可视化世界又近了一步。

功率 BI 的新实例

使用步骤 1 中的 APIKey 和 Endpoint 链接,并替换下面 M 查询脚本中的占位符,这基本上有助于执行对 Azure 的 API 调用。这里需要知道的另一个重要参数是语言:“en”,它可以调整为包括 20 多种语言(印地语、汉语、德语、法语等等)。

电源 BI 集成的 m 查询代码

现在继续并选择 Get data>>Blank query(这将导航到 Power Query editor)> >粘贴 M 查询代码(包含替换的 API 键和端点链接)

在 Microsoft Power BI 中创建空白查询

在超级查询编辑器中粘贴您的 M 查询

这将是一个🔦将" Query1" 重命名为类似于“情绪 API”的有意义的东西是个好主意。通过右键单击左侧窗格或直接在右侧窗格的名称字段中进行编辑。

现在,在 power query 编辑器中导航到数据集,在 Add Column section > >下选择“调用自定义函数”> > 添加列名=情绪,从下拉列表中选择函数 query,并将文本作为带有反馈的列“答案”> >按 OK。

在超级查询编辑器中配置自定义函数

这将调用 Azure API 并创建一个新列,展开列“情绪”,并将 3 个新创建的列(正、中、负)的数据类型更改为“整数”。虽然您可以保持十进制格式,但我建议将它们改为整数,因为这有助于更好地显示它们。现在你可以点击“保存&关闭”,让力量 BI 发挥它的魔力!🎉

积极、中立和消极情绪栏

在您最终进入可视化之前,创建一个新的计算列将是有用的,该列可用于提供切片器以便于过滤。您可以使用下面的 DAX 公式将所有内容整理成一列。

**Overall Sentiment = IF(Responses[Sentiment.positive]=1,"Positive",IF(Responses[Sentiment.neutral]=1,"Neutral",IF(Responses[Sentiment.negative]=1,"Negative","NA")))**

步骤 3: Power BI 可视化

现在你准备好想象了📊信息。我建议使用以下方法:

  1. 一个水平切片器,通过正向、负向和中性 来过滤情绪。
  2. 按周、月或年表示情绪趋势的条形图。
  3. 一些表情符号代表观众的感觉和情绪。
  4. 一个表格,提供所有要关联的原始数据字段和“导出到 Excel”
  5. 明确 AI 模型局限性的免责声明。

*作为一个预测性的人工智能模型,这可能不是 100%准确地表达情感,但它确实有助于提供可操作的见解和更快的决策,从而提供指示性的情感。#责任#透明度。

最后但同样重要的是,您还可以添加条件格式,以确保颜色模式与情感相匹配。

这里有一个 Power BI 模板示例,您可以将其用作起点。 情感分析 Azure + Power BI 集成 DEMO.pbix

Microsoft Power BI 中的情感分析可视化演示

输出

通过切分过滤器,你可以看到 Azure 文本分析资源在执行情感分析方面是多么有效。例如,类似于【良好会话】精彩事件】 的反馈被正确分类为正面😃类似的反馈如【很多问题】 被正确归类为负面😞。**

正面情绪的 Azure 文本分析输出

针对负面情绪的 Azure 文本分析输出

结论

我们学到了📘如何使用 Microsoft Azure Text Analytics 进行情感分析,以及如何在 Microsoft Power BI 中集成分析以开发可视化。

您可以使用其他数据集并定制代码,看看什么最适合您的用例!

发现了一种不同的情感分析方法?请放在评论里!

参考

[1]https://www . statista . com/statistics/871513/world wide-data-created/#:~:text = The % 20 total % 20 amount % 20 of % 20 data,ever-growth % 20 global % 20 data % 20 sphere。

[2]https://docs . Microsoft . com/en-us/azure/cognitive-services/text-analytics/tutorials/tutorials-power-bi-key-phrases

[3]数据来源:作者手工编制

深度学习在水产养殖中的应用分析

原文:https://towardsdatascience.com/analyzing-applications-of-deep-learning-in-aquaculture-7a273399553?source=collection_archive---------17-----------------------

深度计算机视觉保护海洋,可持续地养活人类

通过追踪水中的物体来解释进食行为— 礼貌潮汐

为什么要花时间让水产养殖变得更聪明?🤯

对鱼作为肉类来源的需求平均每年增长 6%,这使得鱼成为肉类行业增长最快的食品。自 21 世纪初以来,这一需求已经翻了一番,如果目前的增长率保持不变,到 2050 年将再翻一番。

养鱼业一直在扩大,通过增加设施内的鱼的数量来满足这种需求。然而,随着鱼群越来越密集,它们的生活质量会下降。

保持高质量的生活需要满足以下需求:

  • 低比率的海虱(鲑虱)感染
  • 低水平的压力荷尔蒙皮质醇
  • 食物的理想水平(以及定时送餐)
  • 合适的生物量大小
  • 维护良好的网状网将鱼围在里面(将捕食者挡在外面)
  • 谨慎的水质平衡
  • 低发病率

不幸的是,随着渔场枯竭,生活质量呈指数下降。这是因为这些因素与空间之间的关系(空间越小=越容易传播海虱、疾病等)。)

为什么这会使养鱼场受益?💰

  • 饲养成本占渔业收入的 60%。不合理的喂养可能是收入的一个重要因素 de Verdal 等人,2017
  • 手动选择特征是一种费力的启发式方法,其效果高度依赖于运气和经验(Mohanty 等人,2016 年)
  • DL 模型在弱光和高噪声等挑战性条件下表现出很强的稳定性,并且比传统的人工特征提取方法表现更好(Sun 等人,2018)

我们如何执行?🤔

大多数养鱼场几乎没有技术支持,预算也很紧张。因此,任何解决方案都必须易于安装且成本低廉。

我们的深度学习解决方案只需要一件设备——一台集成了测量仪器的相机。养鱼场中心的一个井位仪器可以收集和汇总监测上述七个生活质量指标所需的所有数据。当这些指标组合在一起时,还可以产生一个养鱼场的整体健康值,代表一个整体的一览式健康评级。

使用上述聚合数据和计算机视觉,我们可以开发以下深度学习应用:

  • 海虱检测
  • 鱼类的行为分析
  • 动态鱼食欲估计和递送
  • 生物量测量
  • 网格完整性监控
  • 水质监测和控制
  • 疾病识别和预防

深度学习流水线架构

为什么这种方法在✅行得通

在进入应用程序之前,让我们简要分析一下目前为止的所有情况:

  1. 我们可以在七个不同的应用中利用单个设备的汇总数据——每个应用都致力于鱼类生活质量的一个关键因素
  2. 每个应用程序都使用类似的深度学习技术,但会产生一个独特的报告值,养鱼者可以据此采取行动
  3. 七个输出可以组合在一个最终的深度学习应用中,该应用代表农场的整体健康状况

现在想象一下,这七个指标、相关测量值和整体健康评估通过一个漂亮的仪表板实时显示出来!📈

应用程序

1.海虱检测🐟

弗朗切斯科·温加罗在 Unsplash 上的照片

它解决的问题

全世界的渔场都遭受海虱的侵扰。这些寄生虫附着在鱼类宿主身上,以它们的皮肤/血液为食。渔场越密集,海虱就越容易传播。

它是如何解决问题的

苛刻的化学处理已经成为去除海虱最常见的方法。虽然化学处理能有效去除海虱,但对鱼有不良影响。它还可以防止鲑鱼在排毒的几周内被出售。

一种深度学习解决方案利用卷积神经网络(CNN)和计算机视觉在海虱传播到其他鱼类之前检测/识别它们,使农民能够采取行动,例如(什么,移动鱼群或暂时降低密度?)在海虱的临界种群水平引发一场彻底的化学冲刷之前。

摘要

海虱会对商业渔场造成灾难性的破坏。如果不加以控制,鱼会因寄生虫引起的病变而无法出售,在某些极端情况下,虱子也会导致鱼死亡。使用深度学习系统进行早期预防可以防止有害化学物质,并控制虱子数量。

2.鱼类的行为分析🦈

照片由德鲁·法威尔在 Unsplash 上拍摄

它解决的问题

微小的环境变化会迅速增加鱼类的压力水平,从而增加它们体内压力荷尔蒙皮质醇的数量。皮质醇会改变鱼的味道,并对消费者产生负面影响。

它是如何解决问题的

IdTracker.ai 模型利用两种不同的 CNN 来提供跟踪小型和大型群体中所有个体鱼类行为的能力——允许农民检测与皮质醇增加相关的行为异常。然而,挑战仍然是巨大的,因为跟踪单个鱼的行为涉及非刚性变形,低图像质量和频繁的遮挡。

赵等人(2018a)展示了另一种解决方案,该方案利用改进的运动影响图递归神经网络(RNNs) 系统地检测、定位和识别鱼群中的异常行为。

摘要

鱼类对其环境中最小的变化,如溶解氧、藻类、浮游植物等,反应迅速。如果鱼类受到压力,它们会产生皮质醇,影响鱼肉质量。分析行为和鱼类游泳模式有助于农民做出更明智的决定。

相关引用: Saberioon 等人,2017 , Papadakis 等人,2012 , Romero-Ferrero 等人,2019 ,赵等人,2018a

3.鱼类食欲检测🐡

它解决的问题

没有任何指标比养鱼更能反映生产效率和养殖成本。喂养占一般养鱼场运营预算的 60%。

喂食不足会大幅降低鱼类繁殖/生物量增长率,而过度喂食会造成成本浪费和周围水环境污染。

它是如何解决问题的

确定最佳的喂食时间和喂食量是一项挑战。传统上,农民使用简单的计时器和直观的经验来做出决定——这没有考虑重要的环境和营养因素。

包含视觉信息、水测量和关于鱼对过去喂食的反应的历史数据的汇总数据可以与 3D-CNN 和 RNN 模型相结合,以适应时间/空间数据流,从而大大提高喂食效率。Maloy 等人利用这种双重网络方法来选择最佳喂食时间,以说明喂食和非喂食行为。

摘要

很多水产养殖场的投饵时间都是随机的。一些农民凭直觉使用饲料。当这种情况发生时,鱼可能会吃得过多或过少。过度使用饲料会导致成本浪费和环境污染,并且喂养不足会降低生长速度。通过检测食欲,农民可以控制何时喂鱼。

相关引用:mloy 等(2019) ,陈等,2017

4.生物量估计🐠

它解决的问题

估算生物量是可持续管理养鱼场的基础,因为它能让农民了解当前鱼的数量、大小和重量。这些至关重要的数据点也推动了与喂养和行为管理相关的决策。

在没有人类干预的情况下,测量生物量可能具有挑战性,因为鱼类在光照和能见度条件无法控制的环境中自由移动。根据鱼的深度,需要考虑不同程度的遮挡和光线变化。

它是如何解决问题的

两种可能的解决方案可以结合起来精确估计生物量:

  1. 训练深度学习算法,理解声纳和光学图像之间的映射
  2. 分割单个鱼的图像,随着时间的推移跟踪它们,并使用帧内对象的深度通过鱼的变化连续估计体积和重量。

摘要

估计生物量有助于农民对鱼的大小、质量和重量做出更好的决定。目前,这一过程是手动完成的,并且是劳动/成本密集型的。自动化这一过程将节省农民的时间和金钱。

相关引用:寺山等人,2019 ,摩恩等人,2018 ,张等人,2020

5.网格完整性检测🐙

网格检测—由 Petrov 等人提供。

它解决的问题

特别设计的网状网将养殖的鱼围在一个封闭的区域内,确保它们的安全/健康。逃离农场的养殖鱼对农场和附近的生态系统将是灾难性的。

它是如何解决问题的

目前,潜水员执行“网完整性检查”,他们戴着水肺在农场周围检查网的节点是否有磨损的迹象。雇用专业潜水员或拥有潜水设备可能是一个艰巨/昂贵的过程。

被训练来识别网中的节点的深度学习神经网络可以容易地创建用于网状网的放置和监控的规则。

摘要

目前的峡湾和其他水产养殖网可以打破。如果发生这种情况,成千上万的鱼将逃到附近的环境中,破坏生态系统。潜水员目前例行检查网状网,但自动检测网破将节省农场很多钱,并拯救海洋免受进一步的伤害。

相关引文:奥迪等人,云鹏等人

6.预测水质🐋

它解决的问题

高水平的溶解氧(DO)和其他自然元素会降低压力和疾病水平,并提高繁殖水平。质量监测需要长期精确测量与水中元素相关的参数。

它是如何解决问题的

深度学习在短期和长期水质监测方面都取得了很大的成果,使用配备注意力的长短期记忆网络(LSTMs)和 RNNs 来捕获/预测与水元素相关的时间序列信息。

摘要

正如上面提到的那一段,鱼对最小的水质变化如溶解氧都会有反应。整个养殖场保持稳定的水质对于鱼类的长期健康至关重要。

【拉赫曼等人,2019 ,胡等人,2019 ,刘等人

7.缺陷鱼丸检测🐳

布兰登在 Unsplash 上的照片

它解决的问题

事实证明,食品缺陷的检测、识别和定位在食品生产中极具挑战性。对于鱼片来说,血斑有损品质,降低市场价值。人工分类方法已经不能满足现代工业的需要。现代工业需要一种稳健、快速、有效、自动化、非侵入性和低成本的方法来分类正常和有缺陷的鱼片。

它是如何解决问题的

米西米等人使用预先训练的 CNN 和 SVM 模型对血斑进行精确分割和定位,并对有缺陷的鳕鱼片进行分类。本研究提出了一种新的数据扩充方法,该方法降低了 CNN 对形状的敏感性,并且只关注颜色特征来区分正常和有缺陷的鱼片。3D 信息用于定位血斑并计算相关的抓取向量,作为机器人处理的输入。

摘要

鱼丸中的缺陷可能对它们的健康有害,并降低它们的市场价值。自动检测有缺陷的鱼颗粒的过程对鱼来说是健康的。

其他研究领域

  • 自动疾病识别和检测
  • 浮游植物和藻类水华检测
  • 温度预测
  • 用于公海自主探测的水下机器人
  • 叶绿素 A 含量预测
  • 海洋生态系统中的障碍和闭塞避免

月球快照摘要🌒

海洋是人类的宝贵资源。它覆盖了 70%的土地,为地球上大部分地区提供食物、氧气和生计。水产养殖只是改善海洋健康的一个方面。如果我们作为研究人员仅仅用一台照相机就可以做这么多来改善海洋,想象一下当我们把我们的大脑和研究用于海洋面临的其他问题时,我们可以取得什么样的成就?

“人们可以下定决心实现看似不可能的神奇想法,并通过科学和技术将其变为现实,然后激发其他人去做其他看似不可能的事情。”—天文泰勒

moon shot 在想什么?

使用 Twitter 分析抖音常用俚语

原文:https://towardsdatascience.com/analyzing-commonly-used-slang-words-on-tiktok-using-twitter-3b9043e32f93?source=collection_archive---------6-----------------------

我们如何在 Python & Tableau 上使用情感分析和主题建模来发现俚语的含义和用法

图片由作者提供— Tableau 仪表板

近年来,抖音在全球范围内一直呈上升趋势,特别是在 1997 年至 2015 年出生的 Z 世代人口中。像 LOL (笑出声来) ROFL (笑得在地上打滚) FOMO (害怕错过)这些俚语是我们大多数人都知道的,但是抖音的崛起带来了另一套俚语吗?事实上,根据 TheSmartLocal (新加坡领先的旅游和生活方式门户网站),有 9 个抖音俚语被认为是 Z 世代孩子常用的。平台上正在使用的 bussinno cap&sheesh等词汇是指什么?像 bestiefax 或者 slaps 这样的常见英文单词,意思还一样吗?

这篇文章解释了 9 个俚语的意思,以及如何在对话中使用它们。在本文中,我们将从数据科学的角度来分析这些俚语,我们将使用 Python 来进行一些自然语言处理(NLP)技术,如情感分析和主题建模。这将使我们更好地了解通常与俚语一起使用的一些关联单词,信息的情感,以及与这些单词一起讨论的话题。

资料组

我们将利用另一个社交媒体平台 Twitter,在一个月内,包含 9 个俚语中任何一个的推文将被捕获,这将形成我们的整个数据集。Python twitter上的 Twitter 公共 API 库允许我们在获得消费者密钥和访问令牌的身份验证后收集过去 7 天的 tweets。一旦我们初始化了与 Twitter 的连接,我们就设置了纬度、经度的最大区域范围,并将搜索查询设置为俚语词。由于我对提取新加坡用户的推文感兴趣,所以我将地理位置设置为新加坡。最喜爱的计数和转发计数也是从 Twitter 上收集的。

# import libraries
from twitter import *
import pandas as pd
from datetime import datetime# store the slang words in a list
slangs = ['fax', 'no cap', 'ceo of', 'stan', 'bussin', 'slaps', 'hits different', 'sheesh', 'bestie']# twitter authentication
consumer_key = '...'
consumer_secret = '...'
access_token = '...'
access_token_secret = '...'
twitter = Twitter(auth = OAuth(access_token, access_token_secret, consumer_key, consumer_secret))# set latitude & longitude to Singapore, maximum radius 20km
latitude = 1.3521    
longitude = 103.8198    
max_range = 20# loop through each of the slang
for each in slangs:
    # extract tweets with query containing the planning area; note max count for standard API is 100
    query = twitter.search.tweets(q = each, geocode = "%f,%f,%dkm" % (latitude, longitude, max_range),\
                                  lang = 'en', count = 100)
    # once done, loop through each tweet
    for i in range (0, len(query['statuses'])):
        # store the planning area, tweet, created time, retweet count & favorite count as a list variable
        temp_list = [each, query['statuses'][i]['text'],\
                     datetime.strptime(query['statuses'][i]['created_at'], '%a %b %d %H:%M:%S %z %Y').strftime('%Y-%m-%d'),\
                    query['statuses'][i]['retweet_count'], query['statuses'][i]['favorite_count']]
        # append list to tweets dataframe
        tweets.loc[len(tweets)] = temp_list

数据清理/令牌化

由于收集的推文是原始形式,包含用户名、表情符号和标点符号等单词,因此有必要进行数据清理以删除它们。我们将首先把所有的大小写转换成小写,过滤掉单个单词的回答,删除标点符号/网址/链接。

# function to clean column, tokenize & consolidate into corpus list
def column_cleaner(column, slang_word):
    # convert all to lower case and store in a list variable
    corpus = column.str.lower().tolist()
    # filter off single word responses, 'nil', 'nan'
    corpus = [x for x in corpus if len(x.split(' ')) > 1]
    corpus = [x for x in corpus if x != 'nan']
    corpus = [x for x in corpus if x != 'nil']
    # remove punctuations, links, urls
    for i in range (len(corpus)):
        x = corpus[i].replace('\n',' ') #cleaning newline “\n” from the tweets
        corpus[i] = html.unescape(x)
        corpus[i] = re.sub(r'(@[A-Za-z0–9_]+)|[^\w\s]|#|http\S+', '', corpus[i])

然后我们扩展上面的函数column_cleaner,将 tweets(来自RegexpTokenizer函数)标记为单个单词,移除停用词(来自nltk包)/数字,并使用词性(来自WordNetLemmatizer函数)执行词条化。

# empty list to store cleaned corpus
    cleaned_corpus = []
    # extend this slang into stopwords
    stopwords = nltk.corpus.stopwords.words("english")
    stopwords.extend([slang_word])
    # tokenise each tweet, remove stopwords & digits & punctuations and filter to len > 2, lemmatize using Part-of-speech
    for i in range (0, len(corpus)):
        words = [w for w in tokenizer.tokenize(corpus[i]) if w.lower() not in stopwords]
        cleaned_words = [x for x in words if len(x) > 2]
        lemmatized_words = [wordnet_lemmatizer.lemmatize(x, pos = 'v') for x in cleaned_words]
        cleaned_corpus.extend(lemmatized_words)
    return cleaned_corpus

整个功能将在我们收集的 tweets 数据集上运行,每条 tweets 将被标记化,然后我们将能够在我们的可视化软件(即 Tableau)上绘制出与俚语相关的前 n 个单词。

# loop through each slang word
for each in slangs:
    # filter dataframe to responses with regards to this slang word
    temp_pd = tweets.loc[tweets.slang == each, :]
    # save result in temp pandas dataframe for easy output
    temp_result = pd.DataFrame(columns = ['slang', 'word'])
    # run column_cleaner function on the tweets
    temp_result['word'] = column_cleaner(temp_pd['tweets'], each)
    # add slang to slang column
    temp_result['slang'] = each
    # append temp_result to result
    result = result.append(temp_result, ignore_index = True)

图片由作者提供—运行 column_cleaner 函数后的 excel 输出

情感分析/极性得分

我们可以利用 Python 包textblob进行简单的情感分析,其中如果极性得分> 0 ,我们会将每条推文标记为,如果极性得分< 0 ,则标记为,否则标记为中性。请注意,在我们进行情感分析之前,不需要运行上述函数column_cleaner,因为textblob包可以直接从原始推文中提取极性得分。

from textblob import TextBlob# empty list to store polarity score
polarity_score = []
# loop through all tweets
for i in range (0, len(tweets)):
    # run TextBlob on this tweet
    temp_blob = TextBlob(tweets.tweets[i])
    # obtain polarity score of this tweet and store in polarity_score list
    # if polarity score > 0, positive. else if < 0, negative. else if 0, neutral.
    if temp_blob.sentiment.polarity > 0:
        polarity_score.append('Positive')
    elif temp_blob.sentiment.polarity < 0:
        polarity_score.append('Negative')
    else:
        polarity_score.append('Neutral')

# create polarity_score column in tweets dataframe
tweets['polarity_score'] = polarity_score

作者提供的图片—进行情感分析后的 excel 输出

主题建模

接下来,我们编写一个函数,可以对我们的推文进行主题建模。主题建模是一种统计建模,用于发现文档集合中出现的抽象“主题”。我们将使用常见的潜在狄利克雷分配(LDA)算法,该算法用于将文档中的文本分类到特定主题,我们可以在sklearn库包中找到它。在我们的函数中,我们还将使用单个标记生成二元模型和三元模型,以及每个俚语词的前 3 个主题。

from sklearn.decomposition import LatentDirichletAllocation
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import make_pipeline# function to conduct topic modelling
def topic_modeller(column, no_topic, slang_word):
    # extend this slang into stopwords
    stopwords = nltk.corpus.stopwords.words("english")
    stopwords.extend([slang_word])
    # set up vectorizer that remove stopwords, generate bigrams/trigrams
    tfidf_vectorizer = TfidfVectorizer(stop_words = stopwords, ngram_range = (2, 3))
    # set the number of topics in lda model
    lda = LatentDirichletAllocation(n_components = no_topic)
    # create a pipeline that vectorise and then perform LDA
    pipe = make_pipeline(tfidf_vectorizer, lda)
    # run the pipe on the cleaned column
    pipe.fit(topic_column_cleaner(column, slang_word))
    # inner function to return the topics and associated words
    def print_top_words(model, feature_names, n_top_words):
        result = []
        for topic_idx, topic in enumerate(model.components_):
            message = [feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]]
            result.append(message)
        return result
    return print_top_words(lda, tfidf_vectorizer.get_feature_names(), n_top_words = 3)

图片由作者提供—进行主题建模后的 excel 输出

数据可视化/分析

一旦我们准备好数据集,我们就可以将我们的发现绘制到数据可视化软件上,即 Tableau。由于本文更多地关注收集数据和生成我们的见解所需的步骤,我将不讨论我是如何设法将我的发现绘制到 Tableau 上的。可以参考我的 Tableau 公众号上的 Tableau 仪表盘。

让我们以俚语单词 sheesh 为例,我们可以将 Tableau 仪表板过滤到该俚语,整个仪表板将被刷新。使用 iPhone 线框作为用户过滤器的想法是不是很酷?

图片由作者提供—文字过滤器的表格截图

2021 年 8 月期间,在新加坡共收集了 173 条推文,我们的极性得分显示,31.8%的推文是正面的,47.4%是中性的,20.8%是负面的。这似乎表明俚语 sheesh 更多地带有中性到积极的意思。

图片由作者提供—情绪分析的 Tableau 截图

在我们的 Python 代码中,我们对 tweet 进行了标记,这样我们就可以根据单词在所有包含俚语单词的 tweet 中的出现频率对它们进行排序。我们的视觉化显示,像 like、schmuck、sembab (在印尼语中是肿胀的意思)这样的词似乎暗示 sheesh 被用来进一步加剧某事的影响。

作者提供的图片—前 5 个关联单词的表格截图

查看 3 个建模的主题,我们的假设是被用来加剧某事的影响,这在渴望 murtabak、可爱女孩等主题中得到了进一步的暗示。**

图片由作者提供—主题建模的 Tableau 截图

事实上,根据 TheSmartLocal 的文章,单词 sheeshdamn 的用法相似,都是表示不相信或恼怒。如果我们看我们的一些推文,Sheesh渴求 murtabakSheesh【他是一个幸运的人】做暗示的意思。**

结尾注释

我希望这篇文章是有趣的,并给你们一些关于自然语言处理技术如情感分析和主题建模如何帮助我们更好地理解我们的一系列文档(即我们的推文)的想法。玩 Tableau 仪表板玩得开心,整理仪表板真的很有趣, 没有大写 sheesh

使用 Azure 机器学习和健康文本分析分析 COVID 医学论文

原文:https://towardsdatascience.com/analyzing-covid-medical-papers-with-azure-machine-learning-and-text-analytics-for-health-c87ab621a3d0?source=collection_archive---------21-----------------------

思想和理论

如何最大限度地利用人工智能,以便从海量文本语料库中提取见解

作者图片

自从 COVID 疫情开始以来,已经有超过 70 万篇关于这个主题的科学论文发表了。人类研究人员不可能熟悉如此庞大的文本语料库,因此非常需要人工智能的帮助。在这篇文章中,我们将展示如何从科学论文中提取一些知识,获得洞察力,并构建一个工具来帮助研究人员以有意义的方式浏览论文集。在这个过程中,我们还会遇到一些对数据科学家有用的云工具。

如果您想继续下去,自己做这个实验,您可以在这里找到所有源代码和分步说明:

http://github.com/CloudAdvocacy/AzurePaperExplorationWorkshop

如果要引用这段文字,请使用arXiv:2110.15453【cs。CL]

自动纸张分析

自动科学论文分析是快速发展的研究领域,并且由于 NLP 技术的最近改进,在最近几年中已经有了很大的改进。在本帖中,我们将向您展示如何从 COVID 论文中获得具体的见解,例如医学治疗随时间的变化,或使用几种药物的联合治疗策略。

我将在这篇文章中描述的主要方法是从文本中提取尽可能多的半结构化信息,然后将其存储到某个 NoSQL 数据库中以供进一步处理。将信息存储在数据库中将允许我们进行一些非常具体的查询来回答一些问题,以及为医学专家提供可视化探索工具以进行结构化搜索和洞察生成。提议系统的整体架构如下所示:

作者图片

我们将使用不同的 Azure 技术来深入了解纸质语料库,如 健康文本分析CosmosDBPowerBI 。现在,让我们关注该图的各个部分,并详细讨论它们。

如果你想自己尝试文本分析,你需要一个 Azure 账户。如果你没有免费试用版https://azure.microsoft.com/free/?OCID=AID3029145&WT.mc_id=aiml-20447-dmitryso,你可以随时获得。而且你可能还想为开发者查阅 其他 AI 技术

COVID 科学论文和 CORD 数据集

将自然语言处理方法应用于科学文献的想法似乎很自然。首先,科学文本已经是结构良好的了,它们包含关键词、摘要以及定义明确的术语。因此,在 COVID 疫情的最开始,一个 研究挑战已经在 Kaggle 上启动,以分析关于该主题的科学论文。这场比赛背后的数据集被称为CORD(publication),它包含了与 COVID 相关的主题中发布的所有内容的不断更新的语料库。

该数据集由以下部分组成:

  • 元数据文件 Metadata.csv 在一个地方包含所有出版物的最重要信息。该表中的每篇论文都有唯一的标识符cord_uid(事实上,一旦你真正开始使用数据集,它并不完全是唯一的)。这些信息包括:出版物名称、期刊、作者、摘要、出版日期、doi
  • ****全文论文document_parses目录下,用 JSON 格式的结构化文本表示,这大大简化了分析。
  • 预构建的文档嵌入,它将cord_uid映射到反映论文整体语义的浮点向量。

在本帖中,我们将关注论文摘要,因为它们包含了论文中最重要的信息。然而,对于数据集的完整分析,在全文上使用相同的方法肯定是有意义的。

AI 能用文字做什么?

近年来,自然语言处理领域取得了巨大的进步,已经训练出了非常强大的神经网络语言模型。在 NLP 领域,通常会考虑以下任务:

  • 文本分类/意图识别— 在这个任务中,我们需要将一段文本分成若干类别。这是一个典型的分类任务。
  • 情感分析— 我们需要返回一个数字,显示文本的积极或消极程度。这是一个典型的回归任务。
  • ****命名实体识别(NER)——在 NER,我们需要从文本中提取命名实体,并确定它们的类型。例如,我们可能在寻找药品名称或诊断。另一个类似于 NER 的任务是关键词提取
  • 文本摘要— 这里我们希望能够产生原始文本的简短版本,或者选择最重要的文本片段。
  • 问答— 在这个任务中,我们被给予一段文字和一个问题,我们的目标是从文字中找到这个问题的确切答案。
  • ****开放领域问答(ODQA)——与之前任务的主要区别在于,我们得到了一个大的文本语料库,我们需要在整个语料库的某个地方找到我们问题的答案。

在我之前的一篇文章 中,我描述了我们如何使用 ODQA 方法自动找到特定 COVID 问题的答案。然而,这种方法不适合严肃的研究。

要从文本中获得一些见解,NER 似乎是最突出的技巧。如果我们能够理解文本中存在的特定实体,我们就可以在文本中执行语义丰富的搜索,回答特定的问题,并获得不同实体共现的数据,找出我们感兴趣的特定场景。

为了训练 NER 模型以及任何其他神经语言模型,我们需要一个适当标记的相当大的数据集。找到这些数据集通常不是一件容易的事情,为新的问题领域生成数据集通常需要最初的人工努力来标记数据。

预先训练的语言模型

幸运的是,现代的 变压器语言模型 可以使用迁移学习以半监督的方式进行训练。首先,基础语言模型(例如, BERT )首先在大型文本语料库上训练,然后可以在较小的数据集上专门用于特定的任务,例如分类或 NER。

该迁移学习过程还可以包含额外的步骤——在特定领域数据集上进一步训练通用预训练模型。例如,在医学科学领域,微软研究院使用 PubMed 知识库中的文本,预先训练了一个名为PubMed Bert(publication)的模型。如果我们有一些专门的数据集可用,那么这个模型可以进一步用于不同的特定任务。

文本分析认知服务

然而,除了数据集之外,训练模型还需要大量的技能和计算能力。微软(以及其他一些大型云供应商)也通过 REST API 提供一些预先训练好的模型。这些服务被称为 认知服务 ,其中一个处理文本的服务被称为 文本分析 。它可以执行以下操作:

  • ****关键词提取和 NER 用于一些常见的实体类型,如人、组织、日期/时间等。
  • 情感分析
  • 语言检测
  • 实体链接,通过自动添加互联网链接到一些最常见的实体。这也执行了歧义消除**,例如火星既可以指行星也可以指巧克力棒,正确的链接将根据上下文使用。

例如,让我们来看看通过文本分析分析的一篇医学论文摘要:

作者图片

正如你所看到的,一些特定的实体(例如,HCQ,它是羟氯喹的缩写)根本没有被识别出来,而其他的则分类很差。幸运的是,微软提供了特别版的 健康文本分析

健康文本分析

面向健康的文本分析是一种认知服务,它公开了预训练的 PubMedBERT 模型以及一些附加功能。以下是使用健康文本分析从同一段文本中提取实体的结果:

作者图片

要执行分析,我们可以使用最新版本的 文本分析 Python SDK ,我们需要先安装:

pip install azure.ai.textanalytics

该服务可以分析一堆文本文档,一次最多 10 个。您可以传递文档列表或字典。假设我们在txt变量中有一个摘要文本,我们可以使用下面的代码来分析它:

poller **=** client.begin_analyze_healthcare_entities([txt])
res **=** list(poller.result())
**print**(res)

在进行这个调用之前,您需要创建TextAnalyticsClient对象,传递您的端点和访问键。你从认知服务/文本分析 Azure 资源中获得这些价值,你需要通过门户或命令行在你的 Azure 订阅中创建这些价值。

除了实体列表之外,我们还会得到以下内容:

  • 实体映射实体到标准医学本体,如https://www.nlm.nih.gov/research/umls/index.html
  • 文本内部实体之间的关系,如TimeOfCondition等。
  • 否定,表示实体用于否定语境,例如新冠肺炎诊断没有发生**

作者图片

除了使用 Python SDK,还可以直接使用 REST API 调用文本分析。如果您使用的编程语言没有相应的 SDK,或者如果您更喜欢接收 JSON 格式的文本分析结果以便进一步存储或处理,这将非常有用。在 Python 中,这可以通过使用requests库轻松完成:

**uri **=** f"{endpoint}/text/analytics/v3.1/entities/
         health/jobs?model-version=v3.1"
headers **=** { "Ocp-Apim-Subscription-Key" : key }
resp **=** requests.post(uri,headers**=**headers,data**=**doc)
res **=** resp.json()
**if** res['status'] **==** 'succeeded':
    result **=** t['results']
**else**:
    result **=** None**

生成的 JSON 文件将如下所示:

**{"id": "jk62qn0z",
 "entities": [
    {"offset": 24, "length": 28, "text": "coronavirus disease pandemic", 
     "category": "Diagnosis", "confidenceScore": 0.98, 
     "isNegated": **false**}, 
    {"offset": 54, "length": 8, "text": "COVID-19", 
     "category": "Diagnosis", "confidenceScore": 1.0, "isNegated": **false**, 
     "links": [
       {"dataSource": "UMLS", "id": "C5203670"}, 
       {"dataSource": "ICD10CM", "id": "U07.1"}, ... ]},
 "relations": [
    {"relationType": "Abbreviation", "bidirectional": **true**, 
     "source": "#/results/documents/2/entities/6", 
     "target": "#/results/documents/2/entities/7"}, ...],
}**

注意:在生产中,您可能希望包含一些代码,以便在服务返回错误时重试操作。有关正确实现认知服务 REST 客户端的更多指导,您可以 查看 Azure Python SDK 的源代码 ,或者使用 Swagger 生成客户端代码。

并行处理所有文件

由于数据集目前包含 80 万篇论文摘要,通过文本分析按顺序处理它们将非常耗时,可能需要几天时间。要并行运行这段代码,我们可以使用 Azure Batch 或者Azure Machine Learning等技术。它们都允许您创建一个相同虚拟机的集群,并在所有虚拟机上并行运行相同的代码。

作者图片

Azure 机器学习是一项旨在满足数据科学家所有需求的服务。它通常用于培训和部署模型和 ML 管道;但是,我们也可以使用它在一个计算集群上运行我们的并行扫描作业。为此,我们需要提交一个sweep_job实验。

有几种方法可以使用 Azure ML 并提交实验:

  • 通过 Azure 门户进行交互。这可能最适合初学者,但不容易复制或记录。
  • 使用Azure ML Python SDK。它允许你通过代码定义一个实验的所有属性,然而,Python 代码似乎有很多样板文件。
  • 命令行 ,使用 YAML 文件 来定义参数。这是目前推荐的方法。
  • 来自Visual Studio Code Azure ML Extension—它本质上与上面的方法非常相似,但是 VS Code 通过提供自动完成选项来帮助您简化所有配置文件的创作,它还可以为您提交命令。

首先,我们需要创建一个 Azure 机器学习工作区,以及一个运行实验的集群。这是通过 Azure CLI 完成的:

******$** az ml workspace create -w AzMLWorkspace -l westus -g MyGroup
**$** az ml compute create –n AzMLCompute --size Standard_NC 
      --max-node-count 8****

我们还需要将我们的 CORD 数据集上传到 Azure ML 中。我们首先用 YAML 文件data_metacord定义数据集:

****name: metacord
version: 1
local_path: Metadata.csv****

然后我们将数据集上传到云端:

******$** az ml data create -f data_metacord.yml****

我们还需要定义脚本运行的环境。环境本质上是一个容器,可以通过指定一个起始容器并在其上应用一些附加配置来定义。这里,我们在env.yml中定义一个环境:

****name: cognitive-env
version: 1
docker:
    image: mcr.microsoft.com/azureml/base:intelmpi2018.3-ubuntu16.04
conda_file: 
    file:./cognitive_conda.yml****

我们从一个标准的 Azure ML Ubuntu 容器开始,并在cognitive_conda.yml中指定额外的 Python 依赖项:

****channels:
  - conda
dependencies:
  - python=3.8
  - pip
  - pip:
    - azure-cosmos
    - azure.ai.textanalytics
    - requests****

我们通过跑步来创造环境

****az ml environment create -f env.yml****

为了定义一个清扫任务,我们将使用下面的 YAML 文件sweepexp.yml:

****experiment_name: sweep_experiment
algorithm: grid
type: sweep_job
search_space:
  number:
     type: choice
     values: [0,1,2,3,4,5,6,7]
trial:
   command: python process.py 
     --number {search_space.number} 
     --nodes 8
     --data {inputs.metacord}
   inputs:
      metacord:
        data: azureml:metacord:1
        mode: download
   code:
    local_path: .
   environment: azureml:cognitive-env:1
   compute:
      target: azureml:AzMLCompute
max_concurrent_trials: 8
timeout_minutes: 10000****

这里我们用整数参数number定义一个搜索空间,取值从 0 到 7。我们允许最多 8 个并发运行,每个运行将包括调用process.py脚本,向其传递数据集的命令行参数,并发运行的总数和单独运行--number,其范围从 0 到 7。

注意,我们还在这里指定了环境名和计算机名。如果您使用带有 Azure ML 扩展的 Visual Studio 代码来创建这些脚本,您可以使用自动完成(按 Ctrl-Space)来填充字段的名称和必需的值(如可用的计算名称、容器名称等)。)自动。

处理逻辑将编码在 Python 脚本中,大致如下:

****## process command-line arguments using ArgParse
…
df = pd.read_csv(args.data) # Get metadata.csv into Pandas DF## Connect to the database
coscli **=** azure.cosmos.CosmosClient(cosmos_uri, credential**=**cosmoskey)
cosdb **=** coscli.get_database_client("CORD")
cospapers **=** cosdb.get_container_client("Papers")## Process papers
**for** i,(id,x) **in** enumerate(df.iterrows()):
   if i%args.nodes == args.number: # process only portion of record
   # Process the record using REST call (see code above)
   # Store the JSON result in the database
   cospapers.upsert_item(json)****

为了简单起见,我们不会在这里展示完整的脚本

使用 CosmosDB 存储分析结果

使用上面的代码,我们获得了一个论文集合,每个论文都有许多实体和对应关系。这种结构本质上是分层的,存储和处理它的最佳方式是使用 NoSQL 方法进行数据存储。在 Azure 中, Cosmos DB 是一个通用数据库,可以存储和查询类似我们的 JSON 集合的半结构化数据,因此将所有 JSON 文件上传到 Cosmos DB 集合是有意义的。上面显示的代码演示了如何从并行运行的处理脚本中将 JSON 文档直接存储到 CosmosDB 数据库中。

作者图片

我们假设您已经创建了一个名为“CORD”的 Cosmos DB 数据库,并获得了进入cosmos_uricosmoskey变量所需的凭证。

运行完这段代码后,我们将以容器Papers结束所有元数据。我们现在可以在 Azure Portal 中使用这个容器,方法是转到数据浏览器:

作者图片

现在我们可以使用 Cosmos DB SQL 来查询我们的集合。例如,下面是我们如何获得语料库中所有药物的列表:

***-- unique medication names*
**SELECT** **DISTINCT** e.text 
**FROM** papers p 
**JOIN** e **IN** p.entities 
**WHERE** e.category**=**'MedicationName'**

使用 SQL,我们可以制定一些非常具体的查询。假设,一位医学专家想要找出一种特定药物的所有建议剂量(比如说羟氯喹),并查看所有提到这些剂量的论文。这可以使用以下查询来完成:

***-- dosage of specific drug with paper titles*
**SELECT** p.title, r.source.text
**FROM** papers p **JOIN** r **IN** p.relations 
**WHERE** r.relationType**=**'DosageOfMedication' 
**AND** r.target.text **LIKE** 'hydro%'**

更困难的任务是选择所有实体以及它们相应的本体 ID。这将是非常有用的,因为最终我们希望能够引用一个特定的实体(羟氯喹),而不管它在论文中被提及的方式(例如, HCQ 也指同一种药物)。我们将使用 UMLS 作为我们的主要本体。**

***--- get entities with UMLS IDs*
**SELECT** e.category, e.text, 
  ARRAY (**SELECT** VALUE l.id 
         **FROM** l **IN** e.links 
         **WHERE** l.dataSource**=**'UMLS')[0] **AS** umls_id 
**FROM** papers p **JOIN** e **IN** p.entities**

创建交互式仪表板

虽然能够使用 SQL 查询来获得一些特定问题的答案,如药物剂量,似乎是一个非常有用的工具——但对于没有很高 SQL 掌握水平的非 it 专业人员来说,这并不方便。为了使医疗专业人员能够访问元数据集合,我们可以使用 PowerBI 工具来创建一个用于实体/关系探索的交互式仪表板。

作者图片

在上面的例子中,您可以看到不同实体的仪表板。用户可以在左侧选择所需的实体类型(例如,本例中的药物名称,并在右侧观察该类型的所有实体及其数量。您还可以在表格中看到相关的 IDs in,并且从上面的例子中可以注意到几个实体可以引用同一个本体 ID ( 羟氯喹HCQ )。

要制作这个仪表盘,我们需要使用 PowerBI 桌面 。首先,我们需要导入 Cosmos DB 数据——这些工具支持从 Azure 直接导入数据。

作者图片

然后,我们提供 SQL 查询来获取具有相应 UMLS id 的所有实体——如上所示——以及另一个查询来显示所有唯一的类别。然后我们将这两个表拖到 PowerBI 画布上,得到上面显示的仪表板。该工具自动理解两个表由一个名为类别的字段链接,并支持基于第一个表中的选择过滤第二个表的功能。

同样,我们可以创建一个工具来查看关系:

作者图片

从这个工具中,我们可以进行类似于上面在 SQL 中进行的查询,以确定特定药物的剂量。为此,我们需要在左侧表格中选择药物剂量关系类型,然后根据我们想要的药物过滤右侧表格。还可以创建进一步的下钻表格,以显示提及选定药物剂量的特定论文,使该工具成为医学科学家的有用研究工具。

获得自动洞察

然而,故事最有趣的部分是从文本中得出一些自动的见解,例如随着时间的推移医疗策略的变化。为此,我们需要用 Python 编写更多的代码来进行适当的数据分析。最方便的方法是使用嵌入 Cosmos DB 的笔记本:

作者图片

那些笔记本支持嵌入式 SQL 查询;因此,我们能够执行 SQL 查询,然后将结果放入 Pandas DataFrame,这是 Python 固有的数据浏览方式:

****%%sql** *--database CORD --container Papers --output meds*
**SELECT** e.text, e.isNegated, p.title, p.publish_time,
       ARRAY (**SELECT** VALUE l.id **FROM** l 
              **IN** e.links 
              **WHERE** l.dataSource**=**'UMLS')[0] **AS** umls_id 
**FROM** papers p 
**JOIN** e **IN** p.entities
**WHERE** e.category **=** 'MedicationName'**

这里我们以meds数据框架结束,包含药物名称,以及相应的论文标题和出版日期。我们可以根据本体 ID 进一步分组,以获得不同药物的提及频率:

**unimeds **=** meds.groupby('umls_id') \
              .agg({'text' : **lambda** x : ','.join(x), 
                    'title' : 'count', 
                    'isNegated' : 'sum'})
unimeds['negativity'] **=** unimeds['isNegated'] **/** unimeds['title']
unimeds['name'] **=** unimeds['text'] \
                  .apply(**lambda** x: x **if** ',' **not** **in** x 
                                     **else** x[:x.find(',')])
unimeds.sort_values('title',ascending**=**False).drop('text',axis**=**1)**

这为我们提供了下表:

作者图片

从该表中,我们可以选择 15 种最常提及的药物:

**top **=** { 
    x[0] : x[1]['name'] **for** i,x **in** zip(range(15),
      unimeds.sort_values('title',ascending**=**False).iterrows())
}**

为了了解药物的提及频率如何随时间变化,我们可以计算每月提及次数的平均值:

***# First, get table with only top medications* imeds **=** meds[meds['umls_id'].apply(**lambda** x: x **in** top.keys())].copy()
imeds['name'] **=** imeds['umls_id'].apply(**lambda** x: top[x])*# Create a computable field with month* imeds['month'] **=** imeds['publish_time'].astype('datetime64[M]')*# Group by month* medhist **=** imeds.groupby(['month','name']) \
          .agg({'text' : 'count', 
                'isNegated' : [positive_count,negative_count] })**

这为我们提供了一个数据框架,其中包含每个月对药物的正面和负面提及次数。从那里,我们可以使用matplotlib绘制相应的图形:

**medh **=** medhist.reset_index()
fig,ax **=** plt.subplots(5,3)
**for** i,n **in** enumerate(top.keys()):
    medh[medh['name']**==**top[n]] \
    .set_index('month')['isNegated'] \
    .plot(title**=**top[n],ax**=**ax[i**//**3,i**%**3])
fig.tight_layout()**

作者图片

可视化术语共现

另一个有趣的发现是观察哪些术语经常一起出现。为了可视化这种依赖关系,有两种类型的图表:

  • 桑基图允许我们调查两类术语之间的关系,例如诊断和治疗
  • 弦图有助于可视化同类型术语的共现(例如,哪些药物被一起提及)

为了绘制这两个图,我们需要计算共现矩阵,该矩阵在行i和列j中包含术语ij在同一摘要中的共现次数(可以注意到这个矩阵是对称的)。我们计算的方法是为我们的本体手动选择相对少量的术语,如果需要,将一些术语组合在一起:

**treatment_ontology **=** {
 'C0042196': ('vaccination',1),
 'C0199176': ('prevention',2),
 'C0042210': ('vaccines',1), ... }diagnosis_ontology **=** {
 'C5203670': ('COVID-19',0),
 'C3714514': ('infection',1),
 'C0011065': ('death',2),
 'C0042769': ('viral infections',1),
 'C1175175': ('SARS',3),
 'C0009450': ('infectious disease',1), ...}**

然后,我们定义一个函数来计算由这些本体字典指定的两个类别的共现矩阵:

****def** **get_matrix**(cat1, cat2):
    d1 **=** {i:j[1] **for** i,j **in** cat1.items()}
    d2 **=** {i:j[1] **for** i,j **in** cat2.items()}
    s1 **=** set(cat1.keys())
    s2 **=** set(cat2.keys())
    a **=** np.zeros((len(cat1),len(cat2)))
    **for** i **in** all_papers:
        ent **=** get_entities(i)
        **for** j **in** ent **&** s1:
            **for** k **in** ent **&** s2 :
                a[d1[j],d2[k]] **+=** 1
    **return** a**

这里,get_entities函数返回论文中提到的所有实体的 UMLS id 列表,而all_papers是返回论文摘要元数据完整列表的生成器。

为了实际绘制桑基图,我们可以使用 Plotly 图形库。这个过程在 这里 有很好的描述,不再赘述。结果如下:

作者图片

作者图片

用 Plotly 绘制和弦图并不容易,但可以用一个不同的库— Chord 来完成。主要思想保持不变——我们使用上述相同的函数构建共现矩阵,传递相同的本体两次,然后将该矩阵传递给Chord:

****def** **chord**(cat):
    matrix **=** get_matrix(cat,cat)
    np.fill_diagonal(matrix,0)
    names **=** cat.keys()
    Chord(matrix.tolist(), names, font_size **=** "11px").to_html()**

治疗类型和药物的弦图结果如下:

************

作者图片****

右图显示了哪些药物被一起提及(在同一摘要中)。我们可以看到那些众所周知的组合,如羟氯喹+阿奇霉素,清晰可见。

结论

在这篇文章中,我们描述了一个用于从大型医学文本语料库中提取知识的概念验证系统的架构。我们使用 Text Analytics for Health 来执行从文本中提取实体和关系的主要任务,然后一些 Azure 服务一起为医学科学家构建查询并提取一些视觉洞察。这个帖子目前还是概念性的,可以通过在 PowerBI 模块中提供更详细的下钻功能,以及对提取的实体/关系集合进行更多的数据探索来进一步改进系统。切换到处理全文也会很有意思,在这种情况下,我们需要考虑术语共现的稍微不同的标准(例如,在同一段落与同一篇论文中)。

同样的方法可以应用于其他科学领域,但我们需要准备训练一个定制的神经网络模型来执行实体提取。这个任务已经在上面简要地描述过了(当我们谈到 BERT 的使用时),我将在我的下一篇文章中集中讨论它。同时,如果你正在做类似的研究,或者对代码和/或方法有任何具体的问题,请随时联系我。

分析熊猫的数据

原文:https://towardsdatascience.com/analyzing-data-in-pandas-7b7d500f6aed?source=collection_archive---------34-----------------------

当熊猫脱颖而出

斯科特·格雷厄姆在 Unsplash 上拍照

一年前,如果你问我是否认为有比使用 Excel 更好的方法来分析表格数据,我可能会摇头说“没有”,我职业生涯的前 8 年一直在提高我的 Excel 技能,从初级到高级,在公司财务部门担任各种角色。会计部门是一个很好的例子,说明微软 Excel 或谷歌 Sheets 在利用 Python 的 Pandas 软件包方面表现突出,因为它对非技术人员来说更加用户友好,并且易于创建报告,如账户对账。当你开始从一个更程序化的任务转向一个更深入的分析任务时——这就是我认为熊猫脱颖而出的地方。

探索数据

当你收到一个很大的 Excel 文件时,除非你有很多外部构建的 VBA 宏或其他插件,否则你需要大量的跑腿工作和 Excel 公式来熟悉这些数据。Pandas 用两行非常简单的代码解决了这个难题: df.info()df.describe()。

**#importing pandas**
import pandas as pd**#reading in tabular data of All-NBA teams**
df = pd.read_csv('../Data/YoY_Analysis.csv', index_col = 0)**#selecting needed columns**
df = df[['YEAR','All_NBA', 'PLAYER', 'TEAM', 'Age', 'PTS', 'AST', 'TRB']]**#showing the first 5 rows of data**
df.head()

数据帧图像

**#pandas code giving statistical information for all numerical columns**
df.describe()

数据框架统计信息

**#pandas code showing count of all columns and data types**
df.info()

数据帧信息

如前所述,导入数据后,仅用两行简单的代码,我们现在就有了所有数字数据的统计数据,包括 IQR 的和每列的数据类型。我们不需要编写公式来计算每一列的最小值/最大值/平均值等,并且 df.info 还向我们显示,我们的数据集中有一些缺失的信息,如 TRB 的 699 非空计数所示——总反弹。经过研究,这是由于 NBA 直到 1951 年才正式追踪篮板。

重塑

Excel 为它提供了一个非常有用的数据透视表工具和用户友好的 GUI,但是它不允许您改变数据的形状,除非您在完成数据透视表的构建后选择全部并对其进行硬编码。Pandas 提供了两个内置函数来帮助重塑/聚合你的数据集: Groupby & Pivot_Table。

几乎在我最初探索数据集的任何时候,我都倾向于使用 groupby ,因为它快速、简单,并且在你想要开始创建视觉效果时非常有用。让我们再来看看我们的数据集,但假设我们对 NBA 球队每年的平均数据感兴趣。

**#creating a new dataframe aggregating average stats per year**
annual_averages = df.groupby('YEAR')['PTS', 'AST','TRB'].mean()annual_averages.head()

分组数据帧

我们现在也可以很容易地绘制这些数据,显示平均值随时间的变化。这使我们能够快速识别 1999 年停摆缩短赛季,导致只有 50 场常规赛正在进行。

annual_averages.plot()

Groupbypivot_table 在熊猫身上的表现非常相似。主要区别在于 pivot_table 允许在行和列上进行聚合。让我们通过旋转数据,然后绘制图表,来看看所有 NBA 球队的统计平均值。

pivot = df.pivot_table(df[['AST', 'PTS', 'TRB']], **#selecting columns**
               index = 'All_NBA', **#selecting index**
               aggfunc = np.mean, **#selecting aggregate function** 
               margins = True ) **#column totals** pivot

数据框架数据透视表

pivot.plot(kind ='bar)

数据透视表绘图

结论

如上所示,在探索数据时,Pandas 是一个令人惊叹的工具。只需几行非常简单的代码,您就可以开始理解您正在处理的数据集。这个库还可以提供更多的东西,但是我希望这个快速浏览能够在下次您收到一个大的 Excel 文件并被要求提供分析见解时有所帮助。

分析巴黎迪士尼乐园游客对公园和酒店的评论—第一部分

原文:https://towardsdatascience.com/analyzing-disneyland-paris-visitors-reviews-for-parks-and-hotels-part-1-f3c2ced2a672?source=collection_archive---------33-----------------------

对超过 12 万篇猫途鹰评论的探索性数据分析和主题建模📝

我们对巴黎迪士尼乐园的所有英文评论的词频

介绍

巴黎迪斯尼乐园是世界上最著名的娱乐胜地之一。它有两个公园,里面有表演、特技和游行、特别活动、人物和游乐设施。它还有几家酒店和餐厅,在 Tripadvisor 上排名第三。

准备好享受巴黎迪士尼乐园的神奇时光吧!

是出现在该公司网站上的第一句话之一,总的来说,这种交流似乎旨在与家人或朋友一起享受一种独特的体验。

有了一点关于该公司的背景和大量来自猫途鹰的评论,让我们试着,没有特定的期望,一起发现留下评论的访问者对它说了些什么。

关于我们的数据集

在开始分析之前,我们需要了解一些关于数据的细节。我们的数据集由迪士尼乐园和酒店的 12 万条 Tripadvisor 点评组成。它们于 2021 年 3 月 12 日在被提取。

迪士尼乐园

  • 巴黎迪士尼乐园→ 41k 评论
  • 朴华特·迪士尼工作室→ 16k 评论

合并成一个 57,799 行(216 MB)的数据集

迪士尼乐园酒店

  • 迪士尼乐园酒店***** → 8k 评论
  • 迪士尼纽约酒店**** → 8k 评论
  • 迪士尼新港湾俱乐部**** → 8k 评论
  • 迪士尼的红杉小屋*** → 12k 评论
  • 迪士尼夏延酒店** → 11k 评论
  • 迪士尼的大卫·克洛科特牧场→ 7k 评论
  • 迪士尼圣达菲酒店** → 10k 点评

组合成一个 65,250 行(217 MB)的数据集

迪士尼乐园自然度假村

  • 巴黎自然村****→ 3k 点评

分析巴黎迪士尼乐园🎢

本文将只关注公园评论(巴黎迪士尼乐园和华特·迪士尼工作室)

为什么你会问?因为有更多的酒店(其中七家)和评论包含更多的领域,如子评级(清洁度、睡眠质量、房间、服务、价值),我们必须从某个地方开始!

欢迎留下任何评论和反馈,如果你喜欢这篇文章,我们可以在第二部分再写一篇关于酒店的文章😉。现在,我们将分两步来尝试从我们的评论数据集中获得最大的收益。

探索性数据分析(EDA)

我们首先探索我们的数据集,并试图得出有趣的见解,如:

  • 游客满意度
  • 情绪随时间变化
  • 响应时间和速率

文本分析和话题发现

我们有一堆像样的评论,我们希望了解访问者留下的文字内容(主要通过提取不同的话题或主题)。为此,我们将关注以下内容:

  • 评论长度、表情符号和语言
  • 词频和 N 元语法
  • 使用 LDA 和 NMF 进行主题建模

既然一切都准备好了,让我们开始吧!

探索性数据分析

每月有多少评论?

Tripadvisor 创建于 2000 年,巴黎迪士尼乐园创建于 1992 年。华特·迪士尼工作室公园在 2002 年晚些时候开放。

从下图中,我们可以看到访客真正开始分享和写评论是从 2010 年开始的。

2004 年至 2021 年每月审查次数

观察到大多数峰值对应于 6 月到 8 月这一段时间非常有趣,而且有明显的季节性。

从 2019 年初开始,我们观察到下降的趋势,自 2020 年 3 月新冠肺炎疫情开始以来,几乎没有评论留下。

此外,通过计算巴黎迪士尼乐园和工作室公园之间的 CORR()函数,我们看到两条线具有 97% 的相关性,这意味着它们具有相同的游客评论季节性和趋势。

我们可以问自己一些问题,为什么冬天没有季节性🎃或者圣诞节🎄)?或者,如何解释 2019 年评论的持续减少?

SQL 提示

Tripadvisor API 以字符串类型格式返回日期,如下所示 2016–03–17t 12:40:44–04:00。为了解析它,我们在 BigQuery 中使用 PARSE_TIMESTAMP()函数。

总体评分和一段时间内的平均评分

除了留下书面文字,访问者还可以从 0 到 5 颗星评价他们的体验,我们将其转换为可读的标签。

按评分分组的评论(1-5 星)

在我们所有的评论中,报道的都是总体而言的美好体验

对于这两个公园,游客的体验更有可能是优秀非常好

总的来说,游客似乎真的很享受这种体验,但这种体验会随着时间的推移而改善吗?

让我们使用一个季度的平均评分,可能从 2012 年开始,因为从今年开始,访问者开始留下很多评论。

平均评分和季度间的相对变化

不要让图表的比例产生误导。我们看到的平均评分在 3.7 到 4.3 星之间,这仍然是一个很小的区间。我们可以把这个图分成两部分,在 Q1 2018 年奥运会之前的 T36 和之后的 T38。

之前,似乎从 2012 年的到 2018 年的,平均评分正在超过的 4 星,其中最大的下降是从的 2016 年到 2016 年第三季度,平均评分从下降到的 3.95 星。

同样引人注目的是,从 2018 年第三季度到 2020 年 Q1持续下降,达到最低评级之一。

SQL 提示

为了获得季度,我们使用带有季度参数的 TIMESTAMP_TRUNC()函数。此外,我们正在利用 BigQuery 中 LAG()函数的功能计算相对变化。

让我们尝试一种不同的可视化方式,使用绿色-琥珀色-红色指示器(基本上将我们的评级转换为阴性-中性-阳性指示器)

红色-琥珀色-绿色指示器,用于季度评审

在 2021 年 Q1 奥运会上,只有 8 条评论,这甚至没有显示在我们的规模上,但正如我们在第一张图表上看到的(每月评论)我们从 2017 年底到 2021 年 3 月有下降趋势,这意味着正面评论的数量也在减少,占总评论的比例更小。

响应速度和响应时间

评论可以由猫途鹰页面所有者回答,在这种情况下,是巴黎迪士尼团队。我想到的一个指标是响应率和响应时间。

巴黎迪士尼团队于 2016 年底开始在 Tripadvisor 上为各公园解答问题。他们在回答大多数评论方面有一个很好的开始,至少三个季度的回答率在 40%到 60%之间,然后这个比率急剧下降。

总的来说,巴黎迪士尼乐园的平均回答率为 15%。这意味着 Tripadvisor 上剩下的 100 条点评中,只有 15 条会得到回复。

响应时间呢?

以天为单位的响应时间的百分比

中值为 3 天,16 天后得到答案的可能性较小。除了这张表,平均回答时间是 5,7 天。

SQL 提示

为了统计一个季度中的回答数量,我们将 owner_response 字段转换为布尔值 1 或 0。然后,我们可以使用 SUM()函数在单个查询中对其进行聚合。

文本分析和主题发现

我们分析的第二部分将更加关注我们的访问者在这些评论中表达了什么(我们将尽力找出答案👀 )

我们将使用不同的技术来帮助我们发现应该深入探究的话题、主题或问题。由于我们不知道这些评论中包含了什么,我们将使用大多数无人监管的方法来探索发现

评论长度、表情符号和语言

单纯出于好奇,我们来看看每次评论的字数有没有什么规律。为此,我们统计了一篇评论的字数,并在几个月和几年内进行平均。

一段时间内的平均审核长度

平均来说,我们的访问者每次评论使用 550 到 800 个字符。随着时间的推移,它看起来相当平坦,没有什么真正突出的。

表情符号能给我们一些有趣的暗示吗?这里需要注意的是,只有1.7%的评论包含表情符号,这在我们的评论数据集中所占的份额非常低。

查看不同评级中最常用的表情符号,我们可以看到 4-5 星的表情符号与爱、笑和幸福有关,1-2 星的表情符号与金钱、愤怒和困惑有关。

SQL 提示

表情符号是从每个评论中提取的。它们以字符串格式存储在 BigQuery 中,用两个方括号封装: [😎,🎉]

为了解析这个字段,我们使用 JSON_EXTRACT_STRING_ARRAY()将我们的字符串转换成一个单值数组。解析逗号分隔值列表非常有用。

来自世界各地的游客参观巴黎迪士尼乐园,因此,评论可能会用许多不同的语言编写。

在所有评论中,我们观察到五种主要语言。

大多数人的评论都是用英语写的。这可能代表美国、加拿大或英国等国家。

法国是第二大代表国家,紧随其后的是意大利和西班牙。

为了进行我们的主题分析,我们将只保留英文评论,这些评论仅占我们数据集的 41% ,这意味着我们将错过来自其他国家和语言的其他观点或想法。

字频率

词频是一种测量给定文本中最频繁出现的单词或概念的技术。然后,我们将它们显示为单词云,以帮助区分最具代表性的单词。

在我们的例子中,我们从评论中删除了一些词,如以及所有停用词(、【他们】、、【你的】、、【我们】、等)

我们对巴黎迪士尼乐园的所有英文评论的词频

例如,这里我们看到单词在我们的评论集中出现得最多。很难确切说出它暗示了什么,但值得注意。

让我们尝试应用相同的方法,但将其分为正面(4-5 星)负面(1-2 星)评论,看看我们是否能注意到每个子集中的特定单词。

正面评价在左边是绿色,负面评价在右边是红色

我们已经可以注意到,有些词是两个词云共有的,比如、【日】、。我们可以说它们适用于消极或积极的感觉。

因此,我们可以观察到大多数出现在一个或另一个子集中的单词。

  • “时间”、“人员”或“食物”大多出现在否定集中
  • “人物”、“游行”或“小鬼”大多出现在正面集合中

这很有趣,但如果脱离上下文,只解释一个词可能会有点困难。我们将试着看看搭配,看看哪些单词通常会出现在一起。

Python 提示

我们没有使用正方形图像格式显示 wordcloud,而是使用了自定义的。PNG 图像来显示米老鼠形状中的单词。wordcloud librairy 允许我们使用“mask”参数来使用任何自定义图像。

搭配/ n-grams

搭配有助于识别共同出现的单词。它有助于识别句子中隐藏的意思。

例如,我们看到“Rides”这个词被频繁提及。但也许它与其他有意义的词同时出现,如、【趣味骑行】。

再比如,在我们之前的文字云中,我们看到了【快速】**【通过】这几个字。在互联网上,我们发现巴黎迪士尼乐园提供了一张通行证,让游客在一些游乐设施上跑得更快。我们可以假设这些单词更有可能一起出现,而不是单独出现。

为了不使陷入过于复杂的分析,我们将看看 bi-gram(两个相邻的词,如“快传”)和 tri-gram(三个相邻的词,如“大雷山”)。

我们的 top 按频率找到了二元模型

两个相邻单词的前 20 次出现(双字母组)

有些联想似乎比其他联想更有可能发生,如、【巴黎迪士尼】、【快速通行证】、、【过山车】、

但也许更有趣的是,我们有“Go Back”【值得】的意思是游客可能愿意回来,因为他们的旅程值得。

另一个“游乐设施关闭”可能表示景点经常关闭,这是一个反复出现的话题。

我们的 top 按频率找到了三元组

前 20 个出现的三个相邻单词(三元组)

我们已经看到,这三个词的组合在我们的评论语料库中出现的频率大大降低了。

好像有几个是指向孩子年龄的,像【6 岁】**【3 岁】或者【4 岁】。

额外魔法时间”和“人物走动”可能是公园提供的有趣功能,值得一看。

三元语法的列表更长,但它们可能不太相关,因为它们出现在更少的评论中。

巨蟒提示

我们使用一个自定义的清理功能来词条化和删除停用词,然后降低和修复编码问题。然后,NLTK librairy 给了我们 ngrams()函数。最后,我们将结果转换成可以在 BigQuery 中接收的数据帧。

主题建模

我们的目标是按照主题自动组织文本。在我们的例子中,我们有一堆评论,我们想弄清楚所有这些评论会产生什么主题。

例如,以下评论可以在一个名为神奇的地方的主题中建模。

  • “我对这个神奇的地方爱得无以言表。”
  • “真正神奇的体验和物超所值只要你在去哪里吃饭上做足功课,我绝对会再去!”
  • “从《料理鼠王》和《海底总动员》这种独一无二的游乐设施来看,一切都很神奇。”

我们将使用两种算法, LDA (潜在狄利克雷分配)和 NMF (非负矩阵分解)来卧底这些话题。

这两种算法的工作原理是,根据评论包含的单词将评论分组,并注意它们之间的相关性。我们使用两种方法来比较发现的主题,即使它们不同,但它们应该会带来相似的结果。

LDA 发现的主题

使用 LDA 发现的主题

  • 第一个话题听起来是关于好玩的游乐设施,比如太空山和大雷山
  • 第二个话题是关于排队和等待时间。可能相关或由于封闭的游乐设施。
  • 第三个话题好像是关于员工抽烟和钱的。
  • 第四个主题描述了一次由于游行和迪斯尼人物而带来的神奇和令人惊奇的经历。
  • 第五个主题似乎是与酒店和货币价值有关,或者也与烟火和一天中的繁忙时间有关。

要找到对这些主题的清晰解释并不总是容易的,但至少它给出了指示,也许是进一步探索的主题。

NMF 发现的话题

使用 NMF 发现的主题

至于 LDA,这种方法的结果也是主题的形状。

  • 第一个话题可能是关于孩子们喜欢游行和见到迪斯尼人物。
  • 第二个主题是关于有趣的游乐设施,类似于我们的 LDA 主题,但有替代名称(碾压过山车、恐怖塔、料理鼠王)。
  • 第三个好像是关于快速通票和等待时间(小时或分钟之间)。
  • 第四个话题与工作人员/演职人员和人有关。
  • 第五个话题是关于酒店、餐厅、火车。

Python 提示

在这个例子中,我们使用 python Gensim librairy。LDA 函数提供了足够的参数进行调整,因此我们可以获得良好的结果。这里,提示可以是使用 Sparse2Corpus()函数来转换转换后的评论集。此外,我们使用两个工人来分配计算过程。

我们的下一步是什么?🐭

我们一直在分析关于两个巴黎迪士尼乐园的评论,但看看评论告诉我们关于酒店的什么也是很有趣的。

此外,我们只考虑了英语评论的文本分析部分。我们可以尝试使用不同的图书馆,以包括其他语言,如法语,西班牙语或意大利语的评论。

此外,我们可以针对不同的评级或情绪对文本进行详尽的分析。例如,对我们的正面和负面评论分别应用主题建模方法。

就是这样!我希望你喜欢这篇文章,了解更多关于文本分析的可能性,不要犹豫留下反馈或评论🤓

用 NLP 分析迪士尼乐园评论

原文:https://towardsdatascience.com/analyzing-disneyland-reviews-b916b6dcccf4?source=collection_archive---------28-----------------------

情感分析、情感检测、搭配和主题建模

与刘培、路畅、帕萨·塔玛塞比和马英凯(加州大学欧文分校 MSBA 分校 21 年级)合作

项目目标:使用情感分析、情感检测和 n-gram 联想,比较顾客对三个迪士尼乐园地点(阿纳海姆、巴黎和香港)景点的情感。使用主题建模识别关键词,帮助迪士尼确定游客痛点并改善公园体验。要查看我们的代码,请参考 GitHub 库这里。

数据集:我们使用了在 Kaggle 中找到的数据集,该数据集包含来自猫途鹰的 42,000 条关于三个迪士尼乐园分店的评论:加州、巴黎和香港。我们决定按分支位置分割数据,以便在计算上更容易分析较小的样本。关于阿纳海姆的评论有 19406 条,关于巴黎的有 13630 条,关于香港的有 9620 条。数据变量包括评论 ID、评级、年月、评论者位置、评论文本和迪士尼乐园分支。

探索性数据分析:首先,我们进行了探索性数据分析(EDA ),以了解所有地点的平均评分,我们的访问者来自哪里,以及评分如何随时间变化。

上图显示了公园所在地每年的平均评分。下图显示了每年针对每个地点撰写的评论数量。

显示了前 10 个国家的游客来自的频率。加州、巴黎和香港(从左至右)

一段时间内的评级频率。2019 年的下降可能是因为没有全年的数据。有些评论没有日期。

我们找到了每个公园的平均评分(满分 5 颗星):加州 4.41,巴黎 3.96,香港 4.20。游客的国籍取决于地理位置——例如,许多香港游客来自邻近国家(如澳大利亚、印度、菲律宾),大多数巴黎游客来自英国,许多加州游客来自美国。

单词云:我们生成了单词云,以便对游客在回顾他们的迪士尼乐园体验时谈论的内容有一个大致的了解。在我们的分析中,我们只对用英语写的评论感兴趣,并删除重复的评论。

为了创建单词云,我们对评论中的单词进行了标记,并删除了停用词。有许多方法可以自定义文字云的字体、背景颜色和轮廓。你可以参考这个网站来寻找 HTML 颜色或者这个来获得更多可以用来增强你的图表的颜色图选项。

tokenizer = RegexpTokenizer(r'\w+')
text = text.lower()
cleaned_text = re.sub('\W', ' ', text)
stopword = stopwords.words("english")
snowball_stemmer = SnowballStemmer("english")
word_tokens = nltk.word_tokenize(cleaned_text)
stemmed_word = [snowball_stemmer.stem(word) for word in word_tokens]
processed_text = [word for word in stemmed_word if word not in stopword]
text_string=(" ").join(processed_text)#make word cloud
mask = np.array(Image.open("m2.jpg"))
wordcloud = WordCloud(background_color="white", font_path='arial', mask = mask).generate(text_string)#applies colors from your image mask into your word cloud
image_colors = ImageColorGenerator(mask)
plt.figure(figsize=(15,8))
plt.imshow(wordcloud.recolor(color_func=image_colors), cmap=plt.cm.gray, interpolation="bilinear")
plt.axis("off")
plt.show()

生成关于所有公园位置的文字云。

从左至右:加州、巴黎、香港

总的来说,这三个地方的评论都提到了快速通道、排队、游客统计、乘车和景点。

情感分析:我们想更深入地了解评论揭示了访问者的情感。对于这一步,我们使用了三种方法来获得使用 TextBlob 和 Vader 的情感。

  1. 这种方法使用复合分数来分配情绪“积极”或“消极”。
#assign sentiment based on compound score
df['sentiment'] = np.where(df['vader_comp'] >= 0.05, 'positive', 'negative')

2.我们还尝试了其他方法来附加情感,通过使用不同的复合得分阈值来分类“正面”、“中性”和“负面”:

df['nltk_sentiment_type'] = ''
df.loc[df.nltk_compound > 0, 'nltk_sentiment_type'] = 'POSITIVE'
df.loc[df.nltk_compound == 0, 'nltk_sentiment_type'] = 'NEUTRAL'
df.loc[df.nltk_compound < 0, 'nltk_sentiment_type'] = 'NEGATIVE'

每个公园位置的情感频率。

3.另一种方法是基于评级来分配情感:

# assigning sentiment using rating
rating = df['Rating']
def label_func(rating):
    if rating >= 4:
        return "Positive"
    elif rating == 3:
            return "Neutral"
    else:
        return "Negative"

df['Sentiment'] = df['Rating'].apply(lambda x: label_func(x))

我们想知道情绪的两极性和主观性在多大程度上影响了游客对迪士尼乐园体验的评价。下面是一个例子,说明我们如何衡量使用“最幸福的地方”和“地球上最幸福的地方”这两个短语的关于香港的评论的极性和主观性

从上面的图表中,我们可以推断出,情绪积极、极性得分高的评论对他们的公园体验非常满意。主观正面评价比主观负面评价多。主观性衡量一篇评论有多固执己见,因此我们可以推断,那些持负面观点的人给出了更严厉的评论,因为他们的期望在访问期间没有得到满足。

情绪检测:我们使用 NRCLex 来分配情绪,NRC lex 基于文本来测量情绪影响。情绪影响包括:积极、消极、期待、信任、恐惧、惊讶、愤怒、悲伤、喜悦和厌恶。我们还尝试使用软件包 text2emotion ,它将情绪分为快乐、愤怒、悲伤、惊讶和恐惧。然而,text2emotion 的问题是它会给“恐惧”打高分(这对地球上最快乐的地方来说没有意义),所以我们选择使用 NRCLex 进行分析。

from nrclex import NRCLex#nrclex outputs a score for all 9 emotions, but we only want the emotion with the highest score (usually the first output)emotion = []
for i in range(len(df)):
    emotions = NRCLex(df['Review_Text'][i])
    emotion.append(emotions.top_emotions[0][0])
df['emotion'] = emotion

检测情绪后,我们为每个位置创建了可视化效果,以显示每种情绪的频率:

graph = sns.countplot(y = "emotion", data = df, palette = "flare")
graph.set(xlabel = 'Frequency', ylabel = 'Emotion', title = 'Emotion from reviews about Disneyland (CA)')
figure = graph.get_figure() 

在这三个地方中,香港是唯一一个没有感到“厌恶”的地方。

总的来说,这三个公园都有高频率的“积极”情绪。然而,我们必须仔细看看与负面情绪(愤怒、恐惧、消极、厌恶、悲伤)相关的评论,这样我们才能了解为什么有些游客有不愉快的公园经历。

我们发现了一些有趣的评论,其中情绪被分为“厌恶”或“负面”:

  1. 巴黎的顾客服务: “不要在欧洲迪斯尼浪费你的时间……那里的工作人员不友好,粗鲁,对顾客一点也不感兴趣!如果你不说法语,你就被忽视了!”
  2. 加州物价: “这无疑是一个传奇的地方,但我认为不值得为过度拥挤和过高的价格而花钱。迪士尼继续提高门票价格,每天的人潮都很荒谬。”
  3. 加州客服: “去过佛罗里达的迪士尼世界,加州迪士尼乐园让人大失所望。洗手间很脏。送餐员会转过身来挖鼻孔。”
  4. 酒店住宿,客户服务,公园可及性,香港的线路: “圣诞节假期去过。整个旅程都被令人恶心的服务和糟糕的经历所破坏…甚至对我的孩子来说也没有魔力。那里的员工大多在生闷气(可能是因为他们需要在假期工作)。回复主要是照着剧本念的,听起来像是破了的单调唱片。有两个亮点,我希望我会忘记.....为我的小宝贝租了一辆婴儿车。一位皱着眉头的工作人员接待了她,递给她一张 HKD 1000 美元的钞票,但找错了零钱(HKD 少了 500 美元)问她,她尖叫了一声!!然后她用广东话咒骂,坚持说她身上没有 HKD 1000 元的钞票,我真笨,给了一张 HKD 500 元的钞票。第二个亮点是当我们排队观看 3D 表演时,一群印度人插队到了队伍的前面。告知工作人员,他们坚决告知,没有排队的规定,并继续聊天。插队者反驳说他们是贵族,排在队伍前面是他们的权利。工作人员笑着点点头,继续他们之间的闲聊。史上最可怕的噩梦....永远不要去那里.....最好还是坚持东京或者我们。”

将情绪和情感结合起来使用可以帮助迪士尼找到客户不满意的地方以及他们不满意的原因。然后,这些信息可用于进行必要的适当更改,以增强游客体验。

搭配:我们希望找到评论中的常用短语,这样我们就可以识别访问者经常讨论的关键词或主题。通过这样做,迪士尼可以识别评论的上下文,而不必单独阅读每一篇评论。我们采取措施寻找搭配——由一个以上的单词组成的短语,通过 n 元语法关联共同出现。

二元联想 —识别两个频繁出现的词,以获得关于评论上下文的更多洞察。我们发现,只过滤形容词和名词更有意义:

def rightTypes(ngram):
    if '-pron-' in ngram or '' in ngram or ' 'in ngram or 't' in ngram:
        return False
    for word in ngram:
        if word in stop_words:
            return False
    acceptable_types = ('JJ', 'JJR', 'JJS', 'NN', 'NNS', 'NNP', 'NNPS')
    second_type = ('NN', 'NNS', 'NNP', 'NNPS')
    tags = nltk.pos_tag(ngram)
    if tags[0][1] in acceptable_types and tags[1][1] in second_type:
        return True
    else:
        return False

以下是每个公园位置的顶级二元模型:

从左至右:加州、巴黎、香港

最常见的二元模型包括热门景点、使用的门票类型(一日通票、公园票)、员工(演职人员)和等待时间。

三元组关联 —识别三个频繁出现的词,以获得对评论上下文的更多洞察。三元模型可以给我们更多关于游客在主题公园做什么的信息。我们也将只考虑形容词和名词给我们有意义的上下文。

从左至右:加州、巴黎、香港

似乎去加州的游客会鼓励其他人“使用快速通道”来缩短等待时间。这些评论还谈到加州冒险,比较他们的经验,佛罗里达州的华特·迪士尼世界,使用公园跳跃者,和受欢迎的公园景点。巴黎评论家还提到使用快速通道,受欢迎的景点,并与其他公园进行比较。关于香港的评论提到了热门景点和乘车等待时间。

我们可以使用通过搭配识别获得的结果,进一步分析游客对景点的情感。为此,我们将查找提到“太空山”或“超空间山”的评论,并比较这三个地方对该旅程的总体看法。我们只对游客使用的与游乐设施相关的词汇感兴趣,所以我们只考虑形容词。

从左到右:与太空山加州、巴黎和香港相关的前 100 个单词

总的来说,当我们可视化与太空山相关的评论时,来自所有三个地方的评论者使用相似的形容词。

主题建模:我们希望使用主题建模来提取评论中使用的关键词,以帮助迪士尼确定公园游客关注的具体问题。我们可以建立一个字典,并使用无监督学习算法 ld a(潜在狄利克雷分配)来训练我们的主题模型,以发现文本中的隐藏模式。这也将产生主题出现在我们的模型中的概率。在构建这个模型之前,我们删除了标点符号、停用词,并对文本进行了词条化。然后,我们找到了 k(主题数量)的最佳值,将其与 coherence score 进行对比。我们选择了一致性分数最大的理想 k 值。我们使用 gensim 包来完成这项任务。

def compute_coherence_values(dictionary, corpus, texts, start, stop):
    """
    Compute c_v coherence for various number of topics
    """
    coherence_values = []
    model_list = []
    for num_topics in range(start, stop):
        model = gensim.models.ldamodel.LdaModel(corpus=corpus, 
                                              num_topics=num_topics,
                                              id2word=id2word,
                                              random_state=90,
                                              alpha='auto',
                                              eta='auto',
                                              per_word_topics=True)
        model_list.append(model)
        coherencemodel = CoherenceModel(model=model, texts=texts,
                             dictionary=dictionary, coherence='c_v')
        coherence_values.append(coherencemodel.get_coherence())
    return model_list, coherence_values
start=4
stop=11
model_list, coherence_values = compute_coherence_values(dictionary=id2word, 
                                    corpus=corpus,
                                    texts=data_lemmatized,
                                    start=start, stop=stop)x = range(start, stop)
plt.figure(figsize=(10,7))
plt.style.use('ggplot')
plt.plot(x, coherence_values, color = "blue",marker=".")
plt.xlabel("Num Topics", size=14)
plt.ylabel("Coherence score", size=14)
plt.title('Number of Topics Based on The Coherence Score',size=18)
#plt.savefig("output/k_topic.jpg", bbox_inches='tight', dpi = 300)
plt.show()

对于加利福尼亚的位置,理想的主题数是 7。这给出了 0.35 的一致性分数和-6.94 的困惑分数。应用这个 k 值,我们获得每个主题中的热门单词:

[(0,
  '0.089*"year" + 0.078*"kid" + 0.052*"old" + 0.033*"child" + 0.032*"come" + '
  '0.031*"little" + 0.029*"character" + 0.018*"young" + 0.018*"daughter" + '
  '0.015*"adult"'),
 (1,
  '0.079*"wait" + 0.076*"line" + 0.066*"pass" + 0.050*"fast" + 0.043*"long" + '
  '0.038*"people" + 0.037*"hour" + 0.026*"minute" + 0.023*"ticket" + '
  '0.019*"get"'),
 (2,
  '0.051*"ride" + 0.049*"go" + 0.040*"time" + 0.040*"day" + 0.037*"park" + '
  '0.030*"get" + 0.018*"do" + 0.016*"good" + 0.014*"food" + 0.014*"take"'),
 (3,
  '0.087*"mountain" + 0.080*"space" + 0.041*"pirate" + 0.033*"detail" + '
  '0.028*"disneyworld" + 0.022*"haunted_mansion" + 0.022*"walt" + '
  '0.020*"matterhorn" + 0.019*"caribbean" + 0.018*"indiana_jone"'),
 (4,
  '0.020*"area" + 0.018*"tell" + 0.013*"give" + 0.013*"put" + 0.012*"re" + '
  '0.012*"parking" + 0.011*"patience" + 0.011*"gate" + 0.011*"leave" + '
  '0.010*"truely"'),
 (5,
  '0.078*"disneyland" + 0.051*"disney" + 0.038*"place" + 0.030*"great" + '
  '0.029*"love" + 0.027*"visit" + 0.025*"park" + 0.020*"world" + 0.019*"fun" + '
  '0.017*"well"'),
 (6,
  '0.034*"overprice" + 0.032*"halloween" + 0.030*"effort" + 0.022*"party" + '
  '0.021*"event" + 0.013*"group" + 0.013*"weekday" + 0.013*"local" + '
  '0.011*"trick" + 0.010*"sandwich"')]

为了在二维空间中可视化主题,我们将使用 gensim 的 pyLDAvis 并创建一个我们模型的交互式可视化。

从我们的主题模型中,我们能够获得每个主题的热门关键词:

  1. 42.5%的代币是关于乘车、表演和食物的。
  2. 24.4%的人认为家庭公园体验是积极有趣的。
  3. 12%的代币关于排队等候和使用快速通行证。
  4. 7.8%的游客与谁一起参观主题公园。
  5. 7.2%的代币关于停车和入口。
  6. 3.5%的热门游乐设施代币(太空山、加勒比海盗、鬼屋、马特宏峰、印第安纳琼斯、大雷山)。
  7. 2.5%的代币关于节假日(万圣节和圣诞节)。

我们应用同样的技术提取关于巴黎和香港的主题,发现了以下结果:

  • 对于巴黎迪士尼乐园,我们发现了 6 个主题:公园体验、景点、排队和快速通道、酒店住宿、天气和公园可达性。
  • 对于香港迪士尼乐园,我们提取了 7 个主题,涉及:公园体验、家庭娱乐、酒店和餐厅住宿、客户服务、假期和庆祝活动(万圣节、冬季、生日)、积极体验和游客建议。

通过寻找关键主题,迪士尼可以确定他们可以改善的具体领域,以提高游客体验。同样的技术可以用于分析情绪消极的评论,以便发现主题公园中出现的问题。

我们用这种方法分析了关于香港的负面评论,并找出了与负面情绪相关的话题:排队、价格、插队和餐馆。在谷歌上快速搜索一下,就会发现插队在香港已经存在多年了。香港迪士尼乐园还在他们的公园条例中增加了一条,游客应该“……在参观期间尊重公园的其他游客,注意不要撞到、推搡或超过其他排队的游客。”(参见本猫途鹰论坛上的问题)。

我们对巴黎的评论应用了同样的方法,发现这些话题与负面情绪有关:长队和人群、客户服务、预订和住宿、吸烟、游览时间和糟糕的公园体验。吸烟在法国很普遍;巴黎迪士尼乐园甚至在园区内有指定的吸烟区。一些评论抱怨这个问题,并声称它已经“摧毁了魔法。”(这里是一个关于这个问题的猫途鹰论坛)。游客们表示,他们的孩子呆在空气中飘散的烟雾周围是不安全的。

我们发现在加州常见的问题是:长队和人群,家庭体验,食物,可达性和婴儿车。这个地方的一个独特问题是婴儿车拥挤、出租、停车和盗窃。评论者提到,如果婴儿车挡住了道路,演职人员有时会移动婴儿车,或者在必要时切断他们的锁。这个动作会让公园的游客感到困惑,特别是如果他们不知道他们的婴儿车被移动到了哪里。(这里是一个关于这个问题的有趣论坛。这里的是一篇关于一个公园游客建议迪士尼应该解决这个问题的文章——根据婴儿车的尺寸向游客收费。)

分类建模:我们希望使用多种方法构建一个健壮的分类器,以便对未来数据进行分类。我们分别实现了随机森林逻辑回归,并在 unigrams 上使用单词包TF-IDF 作为集合模型。我们用于评估每个模型的指标是 F1 分数*。我们还使用了微平均方法用于集成分类器。

** F1-得分是精确度和召回率指标的加权平均值,您可以使用混淆矩阵计算每个指标。*

我们的分析结果如下:

  1. 袋字

香港

加州

巴黎

2。TF-IDF

香港

巴黎

加利福尼亚

进一步分析:通过按月对比评论,我们可以更深入地了解何时发生常见公园问题。我们还可以分析不同年份的评论,以告知我们每个分支机构是否试图做出改变来改善游客体验。

推荐:很多游客痛点源于排队和人潮的挫败感。大量时间花在排队上,这会激怒人们,并导致更负面的体验。另一个导致排长队问题的常见痛点是公园容量——更多的游客意味着等待景点和食物的时间更长。迪士尼应考虑以下一些建议,采取措施缓解负面公园体验的症状:

  • 迪士尼应该想办法优化他们的快速通行证系统。全天提供免费移动快速通行证。
  • 在旺季,尤其是夏天,设置最大的公园容量,这样就不会有太多的人排队。炎热的天气只会加剧游客的挫败感。
  • 让等待的队伍互动,或者在队伍附近设立小吃摊。让更多的角色在受欢迎的游乐设施周围走动——让该游乐设施中的一些角色与排队的游客互动,并与他们合影。
  • 鼓励演职人员执行公园规则,以便游客只在指定区域吸烟(巴黎),不插队(香港),并遵守推车政策(加州)。然而,我们意识到这些都是很难解决的问题,因为有些游客试图打破规则,如果他们没有任何后果的话。
  • 迪士尼应该在受欢迎的景点附近指定区域来停放或存放婴儿车。这可以减少人行道上的拥挤和盗窃/财产损失。

参考文献:

NRCLex:https://pypi.org/project/NRCLex/

https://pypi.org/project/vaderSentiment/

text blob:https://pypi.org/project/textblob/

基于复合得分的情感赋值:https://www . analyticsvidhya . com/blog/2021/01/opinion-analysis-Vader-or-text blob/

搭配:https://medium . com/@ nicha ruch/collocations-identifying-phrases-that-act-like-individual-words-in-NLP-f58 a 93 a2 f84 a

航空公司推特:https://medium . com/analytics-vid hya/airlines-on-Twitter-理解-客户-投诉-with-NLP-81278 F2 b 68 DC

分析德克萨斯海湾沿岸的能源消耗习惯

原文:https://towardsdatascience.com/analyzing-energy-consumption-habits-of-the-texas-gulf-coast-ea46a7dfbb9e?source=collection_archive---------36-----------------------

RStudio 中的多元回归、自举和方差分析

弗拉德·布苏约克在 Unsplash 上拍摄的照片

摘要

这项分析旨在综合 2010 年至 2016 年期间每年 6 月至 8 月三个月的夏季德克萨斯州墨西哥湾沿岸电力消耗数据。所用数据直接来自 ERCOT,该公司管理着该州约 90%的电力负荷,代表着超过 2600 万德州客户。所有计算均使用 R 和 RStudio 进行。

通过这一分析,我将试图回答两个主要问题:

1.在夏季,工作日与周末相比,白天的耗电量高或低多少?

2.平均而言,功耗如何随温度增加?这种关系在周末和工作日之间似乎有所不同吗?

关于数据

用于此分析的数据集包含 5,820 个关于德克萨斯州墨西哥湾沿岸地区功耗的单独条目。这包括休斯顿周围的地区,并延伸到马塔哥达湾以南。如果你想直观地了解这个地区,你可以在这里查看地图。该数据集中的列如下:

时间:每个数据点的日期和时间戳。每个点覆盖上午 9 点到下午 7 点之间的一个小时间隔,并从列出的时间戳开始。

COAST:指定时间内德克萨斯州整个沿海地区的峰值需求(以兆瓦为单位)。请参见上面的链接地图,进一步了解这一点。

Temp:休斯顿威廉·p·霍比国际机场气象站记录的所列一小时间隔内的平均温度。所有单位都是摄氏度。

Weekday:一个二元指示器,表示所讨论的那一天是否是工作日。在本分析中,1 =工作日,0 =周末。

接近

在直接处理任何问题之前,让我们先构建手头数据的可视化。通过执行以下代码块,创建一个简单的日间能耗散点图,作为温度的函数,并按日分类分面,可以很容易地做到这一点:

ggplot(data=load_summer, mapping=aes(x=temp, y=COAST)) +
  geom_jitter(width=0.5, alpha=0.2) +
  geom_smooth(se=F, method=lm) +
  facet_wrap(~weekdaytf) +
  labs(
    title = "Energy Consumption By Weekday/Weekend on Texas Gulf Coast",
    caption = "Data sourced from ERCOT",
    x = "Weekday vs. Weekend",
    y = "Peak Energy Demand (MW)"
  )

这产生了下面的图:

图片由作者使用 RStudio 制作

毫不奇怪,在峰值能源需求和测量温度之间可以看到一个积极的趋势。我们稍后将进一步研究这种关系。不过,现在让我们来解决第一个问题。

要回答工作日和周末之间的日间功耗变化程度,拟合一个简单的多元回归模型会很有用。这可以用 R 来构造,如下所示:

lm1 = lm(COAST ~ temp + weekday + temp:weekday, data=load_summer)
coef(lm1) %>%
  round(3)

正如您在这里看到的,我在这个模型中包含了三个主要的预测项:

  1. 温度的主要影响
  2. 日分类的主要作用
  3. 两种主要效应之间的相互作用项

在执行时,给出以下结果:

(Intercept)         temp      weekday temp:weekday 
    -569.919      512.214      962.098        0.461

这允许我们通过以下线性方程来表达这些变量之间的关系:

能量需求 = -569.919 + 512.214* 温度 + 962.098* 工作日 + 0.461* 温度:工作日

虽然这个模型对于简单的估计来说很好,但是它很容易产生很大的误差。为了克服这个问题,我使用了一个简单的 bootstrap 和重新采样的 load_summer 数据,并根据这些结果计算了每个参数的置信区间:

lm1_boot = do(10000)*lm(COAST ~ temp + weekday + temp:weekday, data=resample(load_summer))confint(lm1_boot) %>%
  mutate_if(is.numeric, round, 3)

*注意:当试图引导一个多元回归模型时,R 有时会很挑剔。如果在运行这段代码时收到奇怪的错误消息,可以直接在原始线性模型上运行 confint()函数。你的置信区间会宽一点,但是在同一个邻域内。

运行此命令后,我们可以在控制台中查看每个模型参数的 95%置信区间:

 name     lower    upper   level   method   estimate
1    Intercept -1013.626 -116.096  0.95 percentile -569.919
2         temp   496.896  527.219  0.95 percentile  512.214
3      weekday   422.334 1487.091  0.95 percentile  962.098
4 temp.weekday   -17.385   18.722  0.95 percentile    0.461
5        sigma  1136.468 1177.841  0.95 percentile 1157.655
6    r.squared     0.691    0.713  0.95 percentile    0.702
7            F  4333.136 4823.466  0.95 percentile 4571.931

如果您直接在非自举线性模型上运行 R 的 confint()函数,下面是输出。如前所述,这个简化方法的上限和下限会稍微偏离自举模型提供的估计值。然而,出于本分析的目的,这两种方法都适用:

 2.5 %   97.5 %
(Intercept)  -1043.794  -96.044
temp           495.783  528.646
weekday        398.141 1526.056
temp:weekday   -19.075   19.998

仅从这些结果来看,我们可以说,在工作日与周末相比,白天的功耗预计会从422 MW 增加到1487 MW——保持所有其他变量不变。鉴于该地区的地理位置和一年中的时间,这是有道理的。当这个国家的其他地区可能会在周末看到更高的能源需求,因为个人花更多的时间在家里,休斯顿是热的。办公室和家庭每个月都不得不在空调上花费大量金钱,因此,当全市的办公室试图为员工提供一些夏日阳光时,能源消耗会更高是有道理的。

但是,观测到的温度和能量消耗之间是否也有关联呢?如果是的话,这种关系在周末和工作日之间也有所不同吗?让我们把焦点转移到第二个问题上来,把这个问题搞清楚。

如果你看一下本分析开头的可视化,这两个变量之间的正相关是相当明显的。同样,这也是合乎逻辑的——由于室内气候控制系统的更多使用,能源消耗必然会随着温度的升高而增加。在再次查看了我们的自举置信区间的输出后,看起来平均而言,对于温度上升一度,峰值需求有望从 ~496.896 MW 增加到 527.219 MW。

评估这种关系在周末和工作日之间是否不同的最简单方法是进行简单的方差分析(ANOVA)。这可以在 R 中通过将 simple_anova()函数应用于我们的原始模型来完成:

simple_anova(lm1) %>%
  round(3)

执行此代码块将产生以下结果:

 Df  R2     R2_improve  sd     sd_improve  pval
Intercept       1 0.000             2120.9                 
temp            1 0.659      0.659  1238.4     882.52 0.000
weekday         1 0.702      0.043  1157.6      80.86 0.000
temp:weekday    1 0.702      0.000  1157.7      -0.10 0.963
Residuals    5816

注:方差分析表本身受制于其中变量的排序,也应如此解读。上面的方差分析表不是这个模型的方差分析表,而是它的一个单一版本。幸运的是,我们感兴趣的联合效应不会因为任何排序的变化而受到影响。然而,如果将来你发现自己在一个更复杂的回归模型上运行 ANOVA,一定要记住这一点。*

在回顾了这些结果之后,交互项的增加似乎对模型性能没有太大的改善(至少在小数点后三位没有可测量的 R2 改善)。这是相当明智的。温度对能量消耗的影响不会因天的分类而改变,所以很明显,前面引用的置信区间适用于周末和工作日。

关闭思路

这一分析为德克萨斯海湾地区的能源消耗模式提供了一些很好的见解。然而,我想指出一些缺点。首先,我构建的自举线性模型的置信区间相当宽。由于意外天气事件和电网中断导致能源消耗的巨大自然差异,这并不奇怪。因此,上述模型中引用的数字估计值应被视为估计值。要进一步精确,就需要将消费模式细分为更具体的类别。我个人认为将我们手头的数据与同一时间段的天气报告结合起来会很有趣。这将允许我们建立一个更实用的多元回归模型,因为墨西哥湾沿岸地区比该州的其他地区更容易发生剧烈的天气变化。

此外,用于此分析的数据集仅涵盖 6 月至 8 月的三个月夏季。这意味着从这些结果中得出的任何论断都只真正适用于夏季。从这里使用的数据得出任何关于 11 月或 12 月能源消耗习惯的结论都是不明智的。同样,从这一分析中得出国家整体消费习惯的结论也是不可取的。我们的数据受到地点和时间的限制,因此我们的结论也是如此。

尽管如此,在过去的一个学期中,这个分析是一个快速而有趣的谜题。该语言内置的 lm()函数使构建回归模型变得简单,只需编写几行代码,而 ggplot2 库允许快速轻松地生成清晰的可视化效果。现代计算能力使得以前复杂的分析变得足够简单,任何人都可以在几分钟内完成。我鼓励大家自己去看看 ERCOT 的数据,看看能做些什么——你可能会发现一些有趣的东西!

英超 VAR 足球决策分析

原文:https://towardsdatascience.com/analyzing-english-premier-league-var-football-decisions-c6d280061ebf?source=collection_archive---------17-----------------------

用 Python 回顾英国足球(EPL)中有争议的视频助理裁判的实现

图片由来自 Pixabay 的 chiraphat phaungmala 拍摄

比赛集锦

动笔:背景
前半段:数据采集与准备
后半段:分析与感悟
专职哨:结论

TL:DR

  • 孙香敏是最频繁卷入 VAR 倾覆事件的人
  • 风险值事件倾向于在每一半的中间出现峰值,在每一半的末尾出现峰值
  • VAR 决策没有明显偏向大 6 团队
  • 在两个 EPL 赛季都实施 VAR 的球队中,布莱顿拥有最高有利于他们的推翻判决的比例(67.9%),而西布罗姆维奇最低(25.0%)
  • 链接到这个项目的 GitHub 回购这里

我们现在已经准备好开始了,所以让我们继续阅读!

启动:背景&背景

乔纳森·沃德在 Unsplash 上拍摄的照片

2019 年英超联赛(EPL)引入了视频助理裁判( VAR )系统。它包括借助视频回放和音频耳机对裁判判决进行现场审查。

其目的是通过快速纠正明显的错误和严重的失误事件,减少人为错误对比赛结果的负面影响。尽管其意图如此,但由于其对比赛的破坏性影响,大量违反足球逻辑的有争议的规则,以及决策缺乏标准化,它已经受到了大量的抨击。

现在最近两个 EPL 季节已经结束,有足够的数据让我们回顾到目前为止的 VAR 决策。

上半年:数据采集和准备

由托马斯·塞勒在 Unsplash 上拍摄的照片

(一)数据来源

本次分析的数据来自 ESPN 足球网站,其分析师在该网站上维护了发生在 EPL 的每个风险值事件的最新公开记录。

以下是关于这些数据的一些重要事实:

  • 仅涉及被推翻的判决(例如,由现场裁判处理的处罚上诉不包括在内)
  • VAR 仅审核四种事件类型 : ( 1 )进球/无进球、( 2 )判罚/无判罚、( 3 )直接红牌(非第二张黄牌/警告)、( 4 )认错人(如裁判罚错球员)
  • 2019/20202020/2021 EPL 季节数据分析
  • 数据有两个方面: (1) 团队 VAR 事件汇总统计 (2) VAR 个人事件信息

(二)数据准备

虽然数据以清晰的表格格式出现,但是在进行探索性分析之前,仍然需要执行几个预处理步骤。以下是采取的一些关键步骤:

  • 对事件描述文本应用字符串操作和正则表达式,以提取裁判判决(即代表反对、中立)、事件类型、比赛时间以及所涉球员姓名等特征
  • 标准化足球队的名称,因为它们在不同的数据集中以不同的方式表示(例如,曼联和曼联、西布罗姆维奇和西布罗姆维奇、狼队和狼队等)。)
  • 删除重复的行,以防止重复计算每个事件,因为每个事件有一行代表团队的“决定”,另一行代表对手的“决定”。

两个重复行的示例,按作者表示同一 VAR 事件|图像

数据准备的代码和细节请参考 GitHub repo 。

下半年:分析和见解

由拍摄的混乱足球齿轮在 Unsplash 上

现在是时候通过从数据中收集有价值的见解来实现一些目标了。我发现通过首先提出业务问题,然后以问答的形式组织分析后的见解来构建分析是最理想的。

问题 1:哪些玩家最常卷入风险值事件?

使用 Python 的Counter子类及其most_common方法,我们可以识别在 VAR 事件中出现频率最高的足球运动员姓名(名和姓)。我们可以很容易地发现一些熟悉的名字,只要看看计数为 6 或以上的值。

经常参与 VAR 颠覆活动的玩家的名字/姓氏|图片由作者提供

可以看出,VAR 倾覆事件中最常涉及的前五名参与者(括号中显示的数字)是:

  • 孙香民 (10)
  • 萨迪奥·马内 (8)
  • 加布里埃尔·赫苏斯 (7)
  • 卡勒姆·威尔逊 (7)
  • 布鲁诺·费尔南德斯 (6)

自 2019/2020 赛季引入 VAR 以来,Son Heung-Min 是卷入 VAR 事件次数最多的球员|图片来源:http://www.soccer.ru/galery/940971.shtml(许可:维基共享,CC BY 3.0)

以上强调了领域知识在数据相关项目中的重要性,因为需要熟悉 EPL 足球运动员才能准确识别和解释这些名字。

问题 VAR 事件在比赛中最常发生在什么时候?

接下来,我们研究 VAR 推翻事件在比赛期间是如何分布的。我使用 Tableau 来创建可视化,而不是使用像seaborn这样的库,因为 Tableau 的 GUI 使得生成和编辑美观的图表更加有效。

90 分钟内 VAR 倾覆事件的分布。:上半场和下半场的补时已经分别包含在第 45 分钟和第 90 分钟的时间点|图片由作者提供

VAR 倾覆事件数量趋向于在每半场中间达到高峰(即上半场 24-25 分钟和下半场 76-77 分钟),在每半场结束达到高峰(即 45 和 90 分钟)。

每半场结束时大量的 VAR 事件可能反映了球队在试图赢得或挽救比赛时进攻(甚至抗议)方法的紧迫性和强度。

Qn 3:2020/2021 年的新风险值规则对事件类型的比例有何影响?

英超推出2020/2021 赛季新规则改善 VAR 实施,那么让我们看看它对 VAR 事件类型的影响。

就总数而言,与 2019/2020 赛季( 113 )相比,2020/2021 赛季( 128 )出现的 VAR 逆转略多。至于事件类型,最明显的区别是涉及处罚的事件比例更高(即+13.4%)。

VAR 倾覆事件类型对比(2019/2020 和 2020/2021 赛季)。事件% do 不等于到 100%,因为事件类型不与互斥|图片由作者提供

从表面上看,有人可能会认为新的处罚侵犯规则是这种增长的原因。然而,深入调查发现,与 2019/2020 年的4(36 起处罚事件)相比,只有3(58 起处罚事件)涉及侵占。这意味着这一较高的比例可能是由于偶然(或其他不确定的原因)。

新的越位规则也是最近的重大变化,但越位事件的比例仍然大致相同。总体而言,新规则似乎并未对风险值事件的概况造成重大变化

问题 4:“六大”团队是否有更多有利于他们的风险值决策?

欧洲超级联赛的溃败引起了很多争议,EPL 的“六大”球队想要脱离出来,组建他们自己的精英比赛。根据对“大 6”的定义,看看风险值决策是否对这些顶级团队有任何偏见将是很有吸引力的。

EPL 六大球队。俱乐部价值基于来自福布斯(2021 年 4 月)|作者图片

三个指标用于评估团队从 VAR 推翻决策中获得的收益:

  1. 净得分:支持决策的总数减去反对决策的总数
  2. 净目标分数:根据所有风险值决策授予团队的净目标数
  3. 主观净得分:主观判定“赞成”的数量(即场上裁判的判定)减去主观判定“反对”的数量

通过三个净指标比较大 6 和非大 6 团队的箱线图。分数越高,团队优势越大|作者图片

仅通过观察方框图,VAR outcomes 似乎更倾向于支持非大 6,而不是,主要是在净主观得分净得分

为了从统计上而不是从视觉上证实这一点, Welch 的 t 检验被用于在所有三个指标上比较两组。

使用 Python 的 SciPy 库运行 Welch 的 t-tests |作者图片

Welch 的 t 检验得出的所有 3 项指标的 p 值均大于 0.05(即大 6 和非大 6 之间的得分无统计显著差异)。这意味着没有明显的风险值决策倾向于(或反对)6 大团队,这是令人鼓舞的。

奖金洞察力:如果你想知道,在净进球得分净主观得分方框图中,大 6 的上部异常值实际上是曼联

Qn 5:哪个 EPL 团队的有利决策比率最高(或最低)?

因为我们看到没有明显偏向六大团队的情况,所以深入了解每个团队的“决策”比率将会很有意思。这将允许我们评估哪些团队拥有对他们有利的最高比例的 VAR 决策。

“支持决策”的百分比是通过将支持团队的决策数除以风险值推翻事件的总数获得的。

EPL 团队的决策比率(降序)|作者图片

看起来布莱顿的风险值推翻决定的比例最高(67.9%),而诺里奇的比例最低。然而,鉴于诺维奇在实施 VAR 的两个赛季中只有一个赛季在 EPL(他们随后被降级),更公平的说法是西布罗姆维奇在两个赛季都在 EPL 的球队中比例最低。

顺便提一下,布莱顿布莱顿从 VAR 推翻决定中受益最多(与曼联并列),这是基于对他们有利的决定的绝对数量(19)。

全职哨:结论

照片由 Jannes Glas 在 Unsplash 上拍摄

在这个激动人心的足球分析中,我们使用 Python 分析了公开的 EPL 风险值数据,以更深入地了解最近两个 EPL 赛季所做的风险值决策。

笔记本中有更多的见解,所以请在 GitHub repo 中查看。

在你走之前

欢迎您加入我的数据科学学习之旅!点击此媒体页面,查看我的 GitHub ,了解更多精彩的数据科学内容。同时,祝你自举愉快!

说完了,该回更衣室了,下一场比赛再见!

** 💔-steps-to-get-tableau-desktop-specialist-certified-in-2-weeks-abbef25778de> **

解析伊拉斯谟与熊猫的学习交流

原文:https://towardsdatascience.com/analyzing-erasmus-study-exchanges-with-pandas-e1da38896265?source=collection_archive---------51-----------------------

在 Erasmus 计划 2011–12 中进行的 200,000 次研究交流的数据集分析结果

由 Unsplash 上的窗口拍摄

自 1987 年以来,伊拉斯谟项目每年为成千上万的欧洲学生提供在另一个欧洲国家度过一个学期或一年的机会,为他们提供一个简单的交流过程以及经济支持。这是一次真正有价值的经历,它打开了他们的思想和心灵,让他们了解欧洲不同的民族、语言和文化。

我在奥地利的维也纳做了我的伊拉斯谟交换,那也是一次难忘的经历。我在那里上过一门课,我们必须做一个关于数据分析的项目, Hilke van Meurs 和我决定对 2011-12 学年的 Erasmus exchange 数据进行分析,这些数据可以在欧盟开放数据门户中找到。一年后的今天,我和你们分享这个项目。

设置

我们在这个任务中的主要需求是使用 JupyterLab 作为工作环境,使用 Python 作为编程语言,使用 Pandas 作为数据处理库。此外,我们必须使用 Matplotlib 来绘制一些图形,以及 Scipy 和 Numpy 来执行一些操作。

理解数据

从欧盟开放数据门户下载的数据集是一个 CSV 文件,其中每一行代表一名学生,每一列给出关于她交换的信息,比如她来自的国家和去的大学、学习领域、交换长度……

伊拉斯谟数据集的预览

有很多列,其中很多对这个项目没有用,所以现在不描述它们,我会在我们需要使用它们的时候解释它们的意思。另一个重要的事实是,这个数据集不仅提供了关于学习交流的信息,还提供了其他类型的伊拉斯谟实习的信息,如实习。因为这个项目只关注学习交流,其他的将会被取消,我们很快就会看到。

下载和清理数据

所以让我们开始工作吧!首先,让我们从在 JupyterLab 中创建一个新的笔记本开始,导入一些我们需要的基本库,并设置绘图样式:

然后,我们必须从欧盟数据门户服务器下载数据集,并将其转换为熊猫数据框架:

最后,由于该数据集涵盖了学习和实习交流,并且我们希望仅关注学习交流,因此我们将删除与职位安排相对应的行和列:

分析单变量

年龄、获得的资助和学分

现在,我们的数据已经准备好进行分析,让我们开始计算一些单一变量的最小、最大、平均和标准偏差,如学生的年龄、他们获得的助学金或他们学习的 ECTS(学分)数。为了更好地理解这些数据,我们还会将其绘制成直方图。

例如,让我们看看如何获得学生年龄的那些统计指标(列年龄):

2011-12 学年最年轻的伊拉斯谟学生只有 17 岁,太神奇了!但最令人惊讶的是,年龄最大的竟是 83 岁,真是难以置信。我们非常震惊,于是我们在数据集中搜索关于这个人的更多信息,出乎意料的是,不止一个,而是两个英国绅士决定参加这个交换项目。然而,平均年龄是 22 岁。

这同样适用于总计( STUDYGRANT )和每月(study grant/length study period)收到的资助和学分数(TOTALECTSCREDITS)–您可以在完整的笔记本中找到代码。

性别百分比

确定男女比例也是非常有趣的。这可以通过从数据帧中获取性别列并计算' F '(女性)和' M '(男性)的出现次数来实现:

很简单,对吧?看起来 60.59%的学生是女性,而男性只有 39.41%。然而,这个比率在不同的目的地大学之间变化很大,我们稍后会看到。

60.59%的学生是女性,39.41%是男性

发送和接收大学

你很好奇欧洲送留学生比较多的大学有哪些?然后,只需从 DataFrame 中获取列' HOMEINSTITUTION ',用 value_counts() 方法计算其唯一值和频率,并绘制成条形图:

发送机构前 10 名

如果你想获得接收机构的前 10 名,只需将' HOMEINSTITUTION '替换为' HOSTINSTITUTION '即可!不言而喻,前 10 个发送机构中有 8 个也是前 10 个接收机构。

语言

英语被认为是世界通用语言,但这并不意味着欧洲学生出国交流时会学习莎士比亚语言的课程。对于数据集中的每个学生,language teached列给出了他们接受课程时所用的语言,因此让我们为这些课程画出十种最流行的语言:

正如我们所料,英语是最受欢迎的,有 10.3 万名学生,其次是西班牙语,有 2.7 万名学生,几乎低 4 倍。

到目前为止,英语是教得最多的语言

那么,这是否意味着在英国和爱尔兰,伊拉斯谟的学生用英语授课的比例要比在西班牙用西班牙语、法语等授课的比例高得多?让我们去发现它!

伊拉斯谟学生用当地语言学习的前 10 个国家

一点也不!英国 91.9%的伊拉斯谟学生用英语学习(因此,尽管英语无所不能,但即使在英国也有外语课程),其次是爱尔兰的 86.8%。第三,西班牙 84.5%的伊拉斯谟学生用西班牙语上课,第四,法国 81.1%的学生用法语上课。第一名和第五名(英国和意大利)的差距只有 14%。

主题领域

另一个基本问题是伊拉斯谟学生最受欢迎和最不受欢迎的学科领域是什么。根据联合国教科文组织的 ISCED 分类,有九个学习领域:教育,人文&艺术,社会科学&商业&法律,科学,工程&制造业&建筑,农业,卫生&福利,服务。对于我们数据集的每一行,在列 SUBJECTAREA 中有一个代表学生学科领域的数字。然而,从那个字段我们只需要第一个数字,所以请注意代码,因为它有一个复杂的函数:

拥有超过 8 万名学生,目前最受欢迎的学习领域是社会科学、商业和法律。银牌和铜牌分别授予人文&艺术工程、制造&建筑,分别为 44.7k 和 30.8k 的学生。

分析多个变量

按接收大学分列的性别比例

有没有想过欧洲有没有「女子大学」或者「男子大学」?嗯,我们很惊讶地知道,有许多机构只接收男性或女性学生,你知道吗?我们可以很容易地对进入大学的女生比例排名前 30 名,对进入大学的男生比例排名前 30 名。

令人惊讶的是,在这两个排名中,男性或女性的百分比都是 100%。除非你列出前 123 所大学,否则你不会看到低于 100%的男性比例,除非你列出前 256 所大学,否则女性比例也不会低于 100%。

接收大学的平均年龄

想知道哪些大学接收最老的学生,哪些是最年轻的?

虽然在最年轻的排名中,差距很小,从 18 岁(即巴塞罗那的波布伦努,事实上,它不是一所大学,而是一所技术学院中心)到前 10 名中的 19.5 岁,但在最老的排名中,差距更大:德国的第 21 所大学为 45 岁,而第 10 名是法国的阿尔伯特·加缪中学,其新生的平均年龄为 32 岁。

每个国家的学生流入和流出比率

我出生的国家,西班牙,是欧洲学生最向往的出国目的地之一。然而,很多西班牙学生也参加了伊拉斯谟竞赛,就像我一样,所以比例相当均衡。然而,有些国家向海外输送了大量学生,却几乎没有接收任何学生,反之亦然。通过柱状图,我们可以很容易地看到每个国家的发送/接收比率。

分析变量之间的相关性

母国和东道国

母国和目的地国是分类变量,而不是数字变量,因此计算相关指数并不简单。出于这个原因,我们选择了更直观的东西,比如热图。

在上面的热图中,每行代表一个国家,每列代表一个目的地。每个国家的结果都是标准化的,这意味着颜色代表每个国家(行)选择每个目的地(列)的学生的百分比。从图表中可以看出,这两个变量的熵值非常低,这意味着对于一个特定的国家来说,哪一个是首选目的地是完全可以预测的。让我们为一个国家检查一下:

如果原籍国和目的地国之间没有相关性,那么对于每个原籍国,每个目的地国将接收 2.86%的学生。然而,从上面的热图和饼图来看,情况并非如此。例如,在饼图中,我们可以看到西班牙学生非常喜欢意大利(21.3%)、法国(12.4%)、德国(11.1%)、英国(9.4%)、葡萄牙(6.8%)和波兰(6.6%)。

目的地和主题区域

欧洲各地有非常著名的大学,但是很难找到一所在每个知识领域都出类拔萃的大学。因此,了解每个学科领域是否存在对某些机构的偏好会很有意思。因为我们再次处理分类变量,让我们应用和以前一样的技术。

如果学科领域和目的地大学之间的相关性为零,对于每个学科领域,每个目的地大学将接收 0.04%的学生。然而,对于大多数学科领域,接收更多学生的机构在 1%和 3.7%之间,表明这两个变量之间的熵并不高。然而,从这个意义上说,我们找不到任何一所大学比其他大学更突出。“普通”类别的百分比非常高,只有三所院校接收了几乎 50%的学生。

母国和东道国以及每月补助金

当我在 2019 年为我的 Erasmus exchange 做文书工作时,我记得西班牙政府根据生活成本设置了三组目的地国家,每个月给每个人不同的补助金。我一到那里,就惊讶地发现一些来自其他欧洲国家的朋友收到的钱比我多或少。那么,每月的补助取决于什么:你要去的国家,还是你来自的国家?让我们去发现它!

每个目的地国家每月补助的方框图

每个派遣国每月赠款的方框图

比较这两个图,排除大量的异常值,很明显,在学生收到的钱的数量上,母国比目的地国是一个更具决定性的因素。在第一张图中,看起来每个目的地国家的每月赠款的平均值相当同质,对于大多数目的地国家来说,方差非常高,从平均值的 50%到 150%不等,而在第二张图中,方差非常低,平均赠款非常异质。因此,正如我在做这个分析之前所想的,每月的补助金主要取决于你来自哪个国家。

我希望这封信对你来说不会太长。事实上,在这篇文章中,我跳过了我们的一些见解,以免写得太长,所以如果你感兴趣,这里有完整的笔记本。我还想再次对 Hilke van Meurs 为这个项目所做的工作表示感谢。当然,如果你有任何问题或建议,请在评论中告诉我。

参考

  • https://jupyter.org/install
  • 熊猫 data frame:https://pandas . pydata . org/pandas-docs/stable/reference/API/pandas。DataFrame.html
  • https://matplotlib.org/api/
  • 伊拉斯谟 2011-12 年数据集:https://data . Europa . eu/eu ODP/en/data/dataset/伊拉斯谟-移动性-统计-2011-12
  • GitHub 中的 Jupyter 笔记本:https://GitHub . com/gbarreiro/Erasmus-data-analysis/blob/main/Erasmus . ipynb

用 Python 分析金融数据

原文:https://towardsdatascience.com/analyzing-financial-data-in-python-ccf5c99f55e8?source=collection_archive---------10-----------------------

探索 Python 中的金融数据

照片由energepic.com在像素上拍摄

探索性数据分析(EDA)是每个数据科学家工作流程的重要组成部分。EDA 允许数据科学家总结他们正在处理的数据的最重要的特征。在金融数据分析中,这包括生成简单的汇总统计数据,如回报率和平均回报率的标准差,通过关联热图可视化股票之间的关系,生成股票价格时间序列图、箱线图等。

让我们来分析一下三只股票:亚马逊(Amazon)、谷歌(Google)和苹果(Apple)。我们将看到如何对这些股票进行简单的探索性数据分析,方法是生成汇总统计数据和可视化数据、风险和回报分析,以及生成滞后指标以了解股价趋势。对于想开始学习如何用 Python 分析金融数据的初学者来说,这应该是一个坚实的基础。在我们开始之前,这里有一些我们将使用的工具。

pandas-datareader 是一个 Python 库,允许用户轻松访问股票价格数据并执行统计分析任务,如计算回报、风险、移动平均线等。此外,matplotlib 和 seaborn 是 Python 中的库,进一步允许您创建数据可视化,如箱线图和时间序列图。这些库的组合使数据科学家能够用相对较少的代码行从金融数据中获得强大的洞察力。

股票风险分析对于理解股票价格波动的不确定性非常重要。这可以帮助投资者根据他们的风险承受能力选择他们想要投资的股票。我们可以使用移动平均线计算,通过描述股票价格运动的方向趋势,进一步为投资决策提供信息。

最后,布林线图是可视化价格波动的有用方法。布林线图和均线就是我们所说的滞后指标。这意味着它们基于长期变化,有助于我们理解长期趋势。这与用来预测未来价格变动的领先指标形成对比。

使用 Pandas-Datareader 访问财务数据

首先,我们需要在终端中使用以下命令安装 pandas-datareader 库:

pip 安装熊猫-datareader

接下来,让我们打开一个新的 Python 脚本。在脚本的顶部,让我们从 pandas_datareader.data 模块导入 web 对象。让我们也导入内置的 datetime 包,它将允许我们创建 Python datetime 对象:

import pandas_datareader.data as webimport datetime

现在让我们提取 Amazon 的股票价格数据,将其存储在一个名为 amzn 的变量中,并显示前五行数据:

amzn = web.DataReader(‘AMZN’,’yahoo’,start,end)print(amzn.head())

作者图片

我们看到数据框有高、低、开仓、收盘、成交量和调整收盘等列。这些值基于交易时段(通常是上午 9:30 到下午 4:00)的股票价格。让我们考虑一下这些列的含义:

  • 高价:股票在交易过程中的最高价格
  • 低价:股票在交易过程中的最低价格
  • 收盘价:股票在交易时段结束时的价格
  • 开盘价:股票在交易时段开始时的价格
  • 调整后收盘价:对股票分割和股息进行调整后的收盘价

接下来,我们应该使用 pandas to_csv 方法将这些数据保存到一个. csv 文件中:

amzn.to_csv(f’amzn_{start}_{end}.csv’, index=False)

现在我们已经有了 AMZN 的数据,让我们提取 GOOGL 和 AAPL 的数据。我们将从谷歌开始,然后转移到 AAPL。

googl = web.DataReader(‘GOOGL’,’yahoo’,start,end)print(googl.head())googl.to_csv(f”googl_{start}_{end}.csv”, index=False)

作者图片

接下来,我们来拉一下 AAPL:

aapl = web.DataReader(‘AAPL’,’yahoo’,start,end)print(aapl.head())aapl.to_csv(f”aapl_{start}_{end}.csv”, index=False)

我们现在应该有三个文件,包含 AMZN、GOOGL 和 AAPL 两年的股票价格数据。让我们把这些文件读入新的熊猫数据帧:

import pandas as pdamzn_df = pd.read_csv(f’amzn_{start}_{end}.csv’)googl_df = pd.read_csv(f’googl_{start}_{end}.csv’)aapl_df = pd.read_csv(f’aapl_{start}_{end}.csv’)

探索和可视化财务数据

接下来,我们可以生成一些简单的统计数据。理解股票价格变动的一个重要指标是回报率。回报的定义是开盘价减去收盘价除以开盘价(R =[开盘价-收盘价]/开盘价)。让我们计算每个股票的收益。让我们从计算 AMZN 的日回报率开始:

amzn_df[‘Returns’] = (amzn_df[‘Close’] — amzn_df[‘Open’])/amzn_df[‘Open’]

作者图片

我们可以创建一个简单的可视化图形,即 AMZN 股票价格的每日回报直方图。我们可以使用 seaborn 进行样式设计,使用 matplotlib 生成直方图:

import matplotlib.pyplot as pltimport seaborn as snsamzn_df[‘Returns’] = (amzn_df[‘Close’] — amzn_df[‘Open’])/amzn_df[‘Open’]amzn_df[‘Returns’].hist()plt.title(‘AMZN Stock Price Returns Distribution’)plt.show()

作者图片

我们可以对谷歌重复这一点:

googl_df[‘Returns’] = (googl_df[‘Close’] — googl_df[‘Open’])/googl_df[‘Open’]googl_df[‘Returns’].hist()plt.title(‘GOOGL Stock Price Returns Distribution’)plt.show()

作者图片

和 AAPL:

aapl_df[‘Returns’] = (aapl_df[‘Close’] — aapl_df[‘Open’])/aapl_df[‘Open’]aapl_df[‘Returns’].hist()plt.title(‘AAPL Stock Price Returns Distribution’)plt.show()

作者图片

我们还可以计算每只股票的平均回报率和回报率的标准差,并将它们显示在直方图的标题中。这些统计数据对投资者来说非常重要。平均回报率让我们了解股票投资的盈利能力。标准差是衡量回报波动程度的指标。在金融界,我们称之为风险。通常情况下,高风险伴随着高回报。让我们展示一个 AMZN 的例子。首先,我们将平均值和标准偏差存储在变量中,并使用 f 字符串来格式化标题:

mean_amnz_returns = np.round(amzn_df[‘Returns’].mean(), 5)std_amnz_returns = np.round(amzn_df[‘Returns’].std(), 2)plt.title(f’AMZN Stock Price Returns Distribution; Mean {mean_amnz_returns}, STD: {std_amnz_returns}’)plt.show()

作者图片

另一个有用的数据可视化是箱线图。类似于直方图,这是另一种可视化数据的均值、离散度和偏斜度的方法。在我们的财务数据的背景下,它可以帮助我们比较每只股票的平均回报、回报的离差和回报的偏度,这有助于为投资决策提供信息。首先,让我们将每只股票的回报合并到一个数据框架中:

amzn_df[‘Ticker’] = ‘AMZN’googl_df[‘Ticker’] = ‘GOOGL’aapl_df[‘Ticker’] = ‘AAPL’df = pd.concat([amzn_df, googl_df, aapl_df])df = df[[‘Ticker’, ‘Returns’]]print(df.head())

为了生成箱线图,我们使用以下代码:

sns.boxplot(x= df[‘Ticker’], y = df[‘Returns’])plt.title(‘Box Plot for AMZN, GOOGL and AAPL Returns’)plt.show()

作者图片

我们将讨论的最后一个可视化是退货的关联热图。这种可视化有助于我们理解股票价格回报之间是否存在线性关系。这很重要,因为它可以提供投资者投资组合中股票之间关系的见解,因此也有助于了解投资者如何构建投资组合。为了创建我们的热图,让我们首先创建一个新的数据框,其中包含每个 ticker 的一列:

df_corr = pd.DataFrame({‘AMZN’:amzn_df[‘Returns’], ‘GOOGL’:googl_df[‘Returns’], ‘AAPL’:aapl_df[‘Returns’]})

接下来让我们计算每只股票收益之间的相关性:

作者图片

这张热图显示,每只股票都有正的线性关系。这意味着,当 AMZN 的日收益增加时,AAPL 和谷歌也可能增加。反之亦然。如果 AMZN 收益减少,其他也可能减少。一个好的投资组合包含多样化的资产。在这种情况下,这意味着我们应该选择彼此相关性不强的股票,如 AAPL、AMZN 和 GOOGL。这是因为如果一只股票的回报下降,你的整个投资组合的回报也会减少。在股票互不相关的多元化投资组合中,一只股票的价格不一定会随着其他股票的价格一起上涨或下跌。

滞后指标

我们接下来要做的计算是两种不同的滞后指标,移动平均线和布林线图。移动平均线是分析师用来消除股价短期波动以了解价格方向趋势的常用技术。在这里,我们将绘制 AMZN、GOOGL 和 AAPL 的移动平均线。先说 AMZN。我们将绘制 AMZN 调整后收盘价的 10 天移动平均线,并考虑 2021 年 1 月 23 日之后的股价:

cutoff = datetime.datetime(2021,1,23)amzn_df[‘Date’] = pd.to_datetime(amzn_df[‘Date’], format=’%Y/%m/%d’)amzn_df = amzn_df[amzn_df[‘Date’] > cutoff]amzn_df[‘SMA_10’] = amzn_df[‘Close’].rolling(window=10).mean()print(amzn_df.head())plt.plot(amzn_df[‘Date’], amzn_df[‘SMA_10’])plt.plot(amzn_df[‘Date’], amzn_df[‘Adj Close’])plt.title(“Moving average and Adj Close price for AMZN”)plt.ylabel(‘Adj Close Price’)plt.xlabel(‘Date’)plt.show()

作者图片

在上图中,蓝线是移动平均线,橙色是调整后的收盘价。我们可以为 GOOGL 做同样的事情:

googl_df[‘Date’] = pd.to_datetime(googl_df[‘Date’], format=’%Y/%m/%d’)googl_df = googl_df[googl_df[‘Date’] > cutoff]googl_df[‘SMA_10’] = googl_df[‘Close’].rolling(window=10).mean()print(googl_df.head())plt.plot(googl_df[‘Date’], googl_df[‘SMA_10’])plt.plot(googl_df[‘Date’], googl_df[‘Adj Close’])plt.title(“Moving average and Adj Close price for GOOGL”)plt.ylabel(‘Adj Close Price’)plt.xlabel(‘Date’)plt.show()

作者图片

最后是 AAPL:

aapl_df[‘Date’] = pd.to_datetime(aapl_df[‘Date’], format=’%Y/%m/%d’)aapl_df = aapl_df[aapl_df[‘Date’] > cutoff]aapl_df[‘SMA_10’] = aapl_df[‘Close’].rolling(window=10).mean()print(googl_df.head())plt.plot(aapl_df[‘Date’], aapl_df[‘SMA_10’])plt.plot(aapl_df[‘Date’], aapl_df[‘Adj Close’])plt.title(“Moving average and Adj Close price for AAPL”)plt.ylabel(‘Adj Close Price’)plt.xlabel(‘Date’)plt.show()

我要讨论的最后一种图是布林线图,这是一种可视化移动平均线离差的方法。波段由上限和下限定义,上限和下限与简单移动平均线相差两个标准差。这对交易者很有用,因为这让他们可以利用价格波动的优势。让我们为 AMZN 生成一个布林线图:

amzn_df[‘SMA_10_STD’] = amzn_df[‘Adj Close’].rolling(window=20).std()amzn_df[‘Upper Band’] = amzn_df[‘SMA_10’] + (amzn_df[‘SMA_10_STD’] * 2)amzn_df[‘Lower Band’] = amzn_df[‘SMA_10’] — (amzn_df[‘SMA_10_STD’] * 2)amzn_df.index = amzn_df[‘Date’]amzn_df[[‘Adj Close’, ‘SMA_10’, ‘Upper Band’, ‘Lower Band’]].plot(figsize=(12,6))plt.title(’10 Day Bollinger Band for Amazon’)plt.ylabel(‘Adjusted Close Price’)plt.show()

作者图片

对于谷歌来说:

googl_df[‘SMA_10_STD’] = googl_df[‘Adj Close’].rolling(window=10).std()googl_df[‘Upper Band’] = googl_df[‘SMA_10’] + (googl_df[‘SMA_10_STD’] * 2)googl_df[‘Lower Band’] = googl_df[‘SMA_10’] — (googl_df[‘SMA_10_STD’] * 2)googl_df.index = googl_df[‘Date’]googl_df[[‘Adj Close’, ‘SMA_10’, ‘Upper Band’, ‘Lower Band’]].plot(figsize=(12,6))plt.title(’10 Day Bollinger Band for Google’)plt.ylabel(‘Adjusted Close Price’)plt.show()

最后对 AAPL 来说:

aapl_df[‘SMA_10_STD’] = aapl_df[‘Adj Close’].rolling(window=10).std()aapl_df[‘Upper Band’] = aapl_df[‘SMA_10’] + (aapl_df[‘SMA_10_STD’] * 2)aapl_df[‘Lower Band’] = aapl_df[‘SMA_10’] — (aapl_df[‘SMA_10_STD’] * 2)aapl_df.index = aapl_df[‘Date’]aapl_df[[‘Adj Close’, ‘SMA_10’, ‘Upper Band’, ‘Lower Band’]].plot(figsize=(12,6))plt.title(’10 Day Bollinger Band for Apple’)plt.ylabel(‘Adjusted Close Price’)plt.show()

作者图片

如果你有兴趣访问这篇博客中使用的代码,可以在 GitHub 上找到。

有各种各样的有用工具可以从财务数据中提取、分析和生成见解。这些工具的组合使得初学者可以很容易地开始使用 Python 处理金融数据。这些技能可以用于个人投资、算法交易、投资组合构建等等。对于任何对金融感兴趣的分析师或数据科学家来说,能够快速生成统计见解、可视化关系并精确定位金融数据的趋势是非常宝贵的。

如果你有兴趣学习 python 编程的基础知识、Pandas 的数据操作以及 python 中的机器学习,请查看Python for Data Science and Machine Learning:Python 编程、Pandas 和 sci kit-初学者学习教程 。我希望你觉得这篇文章有用/有趣。

本帖原载于 内置博客 。原片可以在这里找到https://builtin.com/data-science/financial-data-analysis