XGBoost 的置信区间
构建正则化分位数回归目标
更新:发现我关于渐变提升的新书,实用渐变提升。这是用 python 中的许多例子对渐变增强的深入探究。
[## 实用的渐变增强:深入探究 Python 中的渐变增强
这本书的梯度推进方法是为学生,学者,工程师和数据科学家谁希望…](https://amzn.to/3GqteUN)
梯度增强方法是一种非常强大的工具,可对大型数据集、非线性依赖于大量要素的复杂变量快速执行精确预测。潜在的数学原理在我的另一篇文章中有解释:
[## 用不到 200 行 python 代码 DIY XGBoost 库
XGBoost 解释了梯度推进方法和惠普调整,通过建立自己的梯度推进库…
towardsdatascience.com](/diy-xgboost-library-in-less-than-200-lines-of-python-69b6bf25e7d9)
而且实现方式多种多样: XGBoost 、 CatBoost 、GradientBoostingRegressor,各有千秋,这里讨论这里讨论或者这里讨论。这些实现都有一个共同之处,那就是能够选择一个给定的目标进行最小化训练。更有趣的是,XGBoost 和 CatBoost 提供了对自定义目标函数的简单支持。
为什么我需要定制物镜?
大多数实现都提供了标准的目标函数,如最小二乘法、最小偏差法、休伯法、RMSE 法……但有时,您正在处理的问题需要更具体的解决方案来达到预期的精度水平。使用自定义物镜通常是我最喜欢的调整模型的方法。
请注意,您可以使用超参数调节来帮助找到最佳物镜。参见我关于这个主题的两篇论文:
[## 用 XGBoost 调优 XGBoost:编写自己的 Hyper Parameters 优化引擎
towardsdatascience.com](/tuning-xgboost-with-xgboost-writing-your-own-hyper-parameters-optimization-engine-a593498b5fba) [## 用 SMAC 进行快速超参数调整的 AutoML
使用 AutoML 在高维空间中寻找你的路径
towardsdatascience.com](/automl-for-fast-hyperparameters-tuning-with-smac-4d70b1399ce6)
你能给我们举个例子吗?
当然可以!最近,我一直在寻找一种方法,将我们的一个模型的预测与置信区间联系起来。简单提醒一下,置信区间有两个特征:
- 区间[x_l,x_u]
- 置信水平 C 确保 C%的时间,我们想要预测的值将位于该区间。
例如,我们可以说地球平均温度的 99%置信区间是[-80,60]。
将置信区间与预测相关联可以让我们量化预测的可信度。
你如何计算置信区间?
你需要训练两个模特:
- 一个代表区间的上限
- 一个代表区间的下限
你猜怎么着?您需要特定的指标来实现:分位数回归目标。scikit-learnGradientBoostingRegressor和 CatBoost 实现都提供了一种使用分位数回归目标函数计算这些值的方法,但两者都使用了这种回归的非平滑标准定义:
其中 t_i 为第 I 个真值, a_i 为第 I 个预测值。 w_i 是用于衡量误差的可选权重。并且α定义了分位数。
例如,使用这个目标函数,如果您将 alpha 设置为 0.95,95%的观察值低于预测值。相反,如果将 alpha 设置为 0.05,只有 5%的观测值低于预测值。90%的真实值介于这两个预测值之间。
让我们使用下面的代码来绘制它,对于范围[-10,10]和各种 alphas:
正如你在下面的结果图中看到的,这个目标函数是连续的,但它的导数不是连续的。(0,0)中有一个奇点,即。就误差而言,这是一个 C_0 函数,但不是 C_1 函数。这是一个问题,因为梯度增强方法需要 C_2 类的目标函数,即可以微分两次来计算梯度和 hessian 矩阵。
如果您熟悉 MAE 目标,您应该已经认识到这些分位数回归函数只是 MAE、缩放和旋转函数。如果你不是,下面的截图应该可以说服你:
对数目标
提醒一下,MAE 目标的公式很简单
MAE 目标公式
上图还显示了 MAE 的正则化版本,logcosh 目标。如您所见,该目标非常接近 MAE,但却是平滑的,即其导数是连续且可微的。因此,它可以用作任何梯度增强方法中的目标,并且与默认的不可微方法相比,提供了合理的收敛速度。
因为它是 MAE 的非常接近的近似值,如果我们设法缩放和旋转它,我们将得到分位数回归目标函数的两次可微近似值。
你可能已经注意到,平均风速曲线和对数余弦曲线之间有轻微的偏移。我们将在下面详细解释这一点。
对数曲线的公式很简单:
对数目标的公式
对数曲线的旋转和缩放
我们现在需要做的就是找到一种方法来旋转和缩放这个目标,使它成为分位数回归目标的一个很好的近似。这里没什么复杂的。由于 logcosh 与 MAE 相似,我们应用了与分位数回归相同的变化,即我们使用 alpha 对其进行缩放:
使用对数余弦的平滑分位数回归
这可以用这 12 行代码来完成:
这是可行的,如下所示:
但是等一下!
您可能会好奇为什么将 log 和 cosh 这两个非线性函数结合起来会得到如此简单的近似线性曲线。
答案就在 cosh 的公式里:
科斯公式
当 x 为正且足够大时, cosh 可以近似为
当 x >> 0 时 cosh 的近似值
相反,当 x 足够负时, cosh 可以近似为
x << 0
We begin to understand how combining these two formulae leads to such linear results. Indeed, as we apply the log to these approximations of cosh, we get :
logcosh simplification for x > > 0 时 cosh 的近似值
对于 x >>0。同样代表 x << 0 :
It is now clear why these two functions closely approximate the MAE. We also get as a side benefit the explanation for the slight gap between the MAE and the logcosh. It’s log(2)!
让我们在一个真实的例子上试试
现在是时候确保我们上面进行的所有理论数学在现实生活中有效了。我们不会在一个简单的窦上评估我们的方法,如 scikit 这里所提议的;)相反,我们将使用从 TLC 行程记录数据集中提取的真实世界数据,该数据包含超过 10 亿次出租车行程。
下面的代码片段实现了上面提出的想法。它定义了对数分位数回归目标 log_cosh_quantile ,计算其梯度和 hessian。这些是最小化目标所必需的。
如本文开头所述,我们需要训练两个模型,一个用于上限,另一个用于下限。
代码的剩余部分只是加载数据并执行最少的数据清理,主要是删除异常值。
在这段代码中,我们选择计算 90%的置信区间。因此,我们使用α= 0.95作为上限,使用α= 0.05作为下限。
超参数调整已经手动完成,使用相当标准的值。当然还可以改进,但是结果已经足够好来说明这篇论文了。
脚本的最后几行专用于绘制随机构建的测试集的前 150 个预测及其置信区间:
请注意,我们还在脚本末尾包含了一个计数器,用于计算置信区间正确的实数值的数量。在我们的测试集上,24 889 个真实值中有 22 238 个(89.3%)在计算的置信区间内。
该模型已经在 TLC 行程记录数据集的 2020 年 1 月数据集的前 100 000 行上进行训练。
结论
通过简单的数学,我们已经能够定义一个平滑的分位数回归目标函数,该函数可以插入任何基于目标优化的机器学习算法中。
使用这些正则化函数,我们已经能够为我们的预测预测可靠的置信区间。
这种方法比这里的所示的方法具有无参数的优势。超参数调优已经是优化 ML 模型的一个要求很高的步骤,我们不需要用另一个参数来增加配置空间的大小;)
机密机器学习
在培训之前、期间和之后保密
机密机器学习- ConfML - 是数据所有者在与 ML 服务共享训练数据时遵循的协议。该协议在训练过程中保持训练数据的机密性。
静态数据和传输中数据的机密性可以通过加密来确保。数据在训练开始之前就被解密,并且在训练过程结束之前一直是易受攻击的。ConfML 解决了这个漏洞:它确保了训练过程中训练数据的机密性。
ConfML 协议由两个步骤组成,这两个步骤结束了培训过程:
- 数据所有者在将训练数据文件发送到 ML 服务之前,使用秘密密钥对它们进行加扰。秘密密钥不与 ML 服务共享。
- 在从 ML 服务接收到网络训练加扰数据后,数据所有者使用步骤 1 的秘密密钥将该网络转换成一个行为相同的网络,就好像它是在原始的未加扰数据上训练的一样。
这两个步骤确保 ML 服务永远看不到原始数据,而数据所有者获得他们想要的网络。
机密机器学习(图片由作者提供)
scramble_files.py
数据所有者可以使用类似于以下程序的东西来扰乱将用于训练完全连接的前馈深度神经网络的特征和标签文件。
该程序使用密钥对特征和标签 CSV 文件中列的顺序进行加密。这种列顺序的混乱使得入侵者很难理解数据,但对训练质量几乎没有影响。
#scramble_files.pyimport random
import pandasdef bld_scram_idx(lst_len, key_secret): #random list based on a key
my_seed = int(''.join(list(map(str, map(ord, key_secret)))))
random.seed(my_seed * lst_len)
scram_idx = list(range(lst_len))
random.shuffle(scram_idx)
*return* scram_idxdef scram_list(lst, scram_idx): #scramble a list of integers
scram_lst = [0] * len(lst)
*for* i, item *in* enumerate(lst):
scram_lst[i] = scram_idx.index(item)
*return* scram_lstdef scram_df(df, scram_idx): #scramble a dataframe
cols_idx = list(range(len(df.columns)))
cols_idx_scram = scram_list(cols_idx, scram_idx)
*return* df.reindex(labels = cols_idx_scram, axis='columns')def read_csv_file_write_scram_version(csv_fname, key_secret):
df_csv = pandas.read_csv(csv_fname, header=None)
scram_idx = bld_scram_idx(len(df_csv.columns), key_secret)
df_csv = scram_df(df_csv, scram_idx)
csv_scram_fname = csv_fname.split('.csv')[0] + '_scrambled.csv'
df_csv.to_csv(csv_scram_fname, header=None, index=None)
print(csv_scram_fname + ' file written to disk')KEY_SECRET, FT_CSV_FNAME, LB_CSV_FNAME = "", "", "" #insert values
read_csv_file_write_scram_version(FT_CSV_FNAME, KEY_SECRET)
read_csv_file_write_scram_version(LB_CSV_FNAME, KEY_SECRET)
解读 _net.py
数据所有者使用该程序,结合用于对训练数据文件进行加扰的密钥,将网络训练加扰数据转换成一个网络,该网络的行为就好像是对原始数据进行训练一样。
这种转换的结果将是网络在原始数据上具有与网络训练加扰数据的在加扰数据上相同的精度。
这个程序的细节根据网络如何用代码实现而有所不同。然而,主要思想是根据scramble_files.py
程序中建立的加扰指数恢复网络输入和输出的顺序。
为 AWS 上的批处理 ML 作业配置云环境
在这篇文章中,我将带您完成准备步骤,使您能够在 AWS 上将容器化的机器学习模型作为批处理作业进行调度。这是本系列文章的第二部分,假设您已经完成了第 1 部分中的前 2 步,创建了一个Dockerfile
并构建了一个容器映像。
为了了解您在准备什么,最终,我们将使用 AWS Batch 来安排 ML 作业。
AWS Batch 使用弹性容器服务(ECS)将作业作为 Docker 容器执行。它根据提交的批处理作业的数量和特定资源要求,动态调配计算资源的最佳数量和类型(例如,CPU 或内存优化实例)。
如果您的模型需要很长时间运行或者有复杂的依赖关系,AWS Batch 是一个很好的解决方案。它支持任何可以作为 Docker 容器执行的作业。
但是为了能够使用 AWS Batch,需要为您的云环境做一些准备。在本文中,我们将首先在注册表中注册我们构建的容器,并确保我们有适当的配置。
步骤 3—注册您的容器👩🏻✈️
我们构建的 Docker 映像当前驻留在我们的本地机器上。要在其他地方运行它,比如云,我们需要把它推到 Docker 注册中心。这非常像将您的本地代码推送到 GitHub,以便您的 EC2 可以克隆它。
类似于我们有不同的版本控制工具,如 GitHub、GitLab、BitBucket 等,也有不同的容器注册中心。Docker Hub 是最受欢迎的一个,但是 AWS 、 Azure 、 GCP 也都提供了它们自己的容器注册表。你可以根据自己的喜好选择其中的任何一个。对于本教程,我们将使用 AWS 原生— Amazon 弹性容器注册中心(或 ECR)。
创建存储库
打开 AWS 控制台并转到 ECR,选择 Create repository 并给它命名。然后点击创建存储库。
创建存储库
现在,您已经准备好将容器从您的终端推送到这个存储库了(需要 AWS CLI )。单击存储库名称查看推送命令。
通过单击存储库名称查看推送命令
查看推送命令
容器注册库的推送命令
推送命令是什么意思
1)向您的注册中心认证您的 Docker 客户端
打开您的终端,复制步骤 1 中括号中的内容,以检索您的登录命令,该命令向您的注册表验证您的 Docker 客户端。然后运行返回的登录命令。
如果您有不同的配置文件设置(比如一个用于个人,一个用于商业),记得在最后添加--profile username
选项来检索正确的凭证。
2)树立你的形象
3)标记图像,这样我们可以将图像推送到这个注册表
所以在这里,我们用你的亚马逊 ECR 注册 URI 来标记你创建的图像。
$ docker tag <IMAGE_NAME>:<TAG> 012345678901.dkr.ecr.us-east-1.amazonaws.com/<IMAGE_NAME>:<TAG>
4)将图像推送到该注册表
$ # push your image to the AWS ECR repository
$ docker push 012345678901.dkr.ecr.us-east-2.amazonaws.com/<IMAGE_NAME>:<TAG>
您可以通过从注册表中提取来测试推送是否成功。
$ docker pull 012345678901.dkr.ecr.us-east-2.amazonaws.com/<IMAGE_NAME>:<TAG>
现在,您的云帐户可以访问您的容器了,您已经准备好进入第 4 步来配置您的云环境。
步骤 4 —配置权限和环境👩🏻🎤
EC2
你们大多数人都已经熟悉 EC2 的设置,但我只想在这里提几件事。我们不会手动创建 EC2,但是无论您选择在 AWS 上使用什么服务,它最终都会创建一些 EC2 来进行计算,因此拥有正确的设置非常重要。
1)密钥对
我们需要为 AWS 批处理计算环境容器实例(ec2)设置 pem 密钥。您可以在 EC2 控制台中创建密钥对。创建密钥对后,您可以在创建计算环境时指定密钥对的名称,然后在使用 SSH 登录时提供私钥。
2)安全组
我们还需要为 AWS 批处理容器实例指定防火墙规则。例如,允许从您自己的 IP 使用 SSH,从任何地方使用 HTTP 和 HTTPS,以及任何其他规则来打开您的任务所需的端口。您也可以在 EC2 控制台中进行设置。
VPC
虚拟私有云(VPC)使您能够将 AWS 资源启动到您定义的虚拟网络中。您可以完全控制虚拟网络环境,包括选择自己的 IP 地址范围、创建子网以及配置路由表和网络网关。
为了在您安全实践中更加警惕,我们应该设置一个 VPC,并让我们的计算节点驻留在 VPC 的私有子网中(如果需要访问互联网,则使用 NAT 网关)。
但是出于测试目的,您可以创建一个带有单个公共子网的 VPC,我们应该没问题。
IAM 角色和权限
在您开始尝试 AWS Batch 之前,请通过参考该清单确保您拥有所需的权限(如果您是管理员,请跳过此步骤)。
简而言之,AWS Batch 将创建一个 EC2 节点来使用 Amazon ECS 运行您的代码,因此您需要创建一个 IAM 角色,该角色具有访问计算环境和容器实例的权限,然后将该角色与您的计算环境相关联。
AWS 批处理计算环境和容器实例角色是在首次运行控制台时自动创建的,因此如果您打算使用 AWS 批处理控制台,可以继续下一节。如果您计划使用 AWS CLI,在创建您的第一个计算环境之前,完成 AWS 批处理服务 IAM 角色和 Amazon ECS 实例角色中的过程。
AWS CLI
如果你还没有安装 AWS CLI,现在是安装的好时机。我们将使用它将我们的容器推送到 AWS 注册中心,并与 AWS 批处理交互。
现在我们已经将代码容器化,构建了容器映像,设置了基本的云环境,并确保我们拥有所需的权限,我们已经准备好开始在 AWS 上调度我们的第一批作业。本系列的第 3 部分再见!
参考
- aCloudGuruAWS ECS——由 Nick Janetakis 教授的 Scaling Docker 课程
- 从 AWS 文档开始使用 AWS 批次
- 使用 AWS 文件中的 AWS 批次进行设置
- 创建简单的“获取&运行”AWS 批处理作业Bryan Liston
- Sunit Mehta 的 AWS 批次入门
- 快速介绍 Docker 标签
关于作者💁🏻
我是一名机器学习工程师,除了技术教程之外,我还撰写关于生产力和自我发展的文章。我最近的兴趣是学习广东话和中国书法。
用 YAML 配置 XGBoost 型号
如何使用 YAML 文件使您的模型快速共享,非常灵活,并为生产做好准备
介绍
没有什么比开始一个新的 ML 项目更令人愉快的了。首先,你用一些数据清理来弄脏你的手,然后你开始将那些干净的数据加载到熊猫 df 中,开始一些探索性的数据分析(在那里你不可避免地发现你需要回去做更多的数据清理……)接下来,你进入特征工程,然后最后,你处于准备构建一些模型和实验的阶段!
在整个过程中,您可能已经将所有代码放在了您可信赖的 jupyter 笔记本中。现在,您想要实际应用您的模型,但是您该如何开始呢?你当然不能把笔记本投入生产。
人们可以写一本关于机器学习模型生产化的书。我并不想教你生产所需的所有工程步骤。相反,把这篇文章看作是生产化 改善 :你可以对你的代码做一个小小的改变来为生产做准备。
在本文中,我将向您展示如何使用 YAML 配置文件来使您的代码更整洁、更具可伸缩性、更易于维护,并且在运行实验时更高效。
YAML 不是标记语言
YAML 是一种递归命名的语言,用于以人类可读的格式存储信息[1]。
对 yaml 结构的详细讨论将使我们离题太远,所以为了满足我们的目的,让我们考虑下面的 yaml 块来初始化 XGBoost 分类器。该块定义了一个字典“模型设置”,将另一个字典作为其值*参数字典。*参数 字典保存我们想要设置的 xgboost 模型的每个参数的值。
# basic yaml config
model_settings:
random_state: 90210
objective: 'binary:logistic'
eval_metric: ['error', 'map', 'auc', 'aucpr']
n_jobs: -1
learning_rate: 0.01
colsample_bytree: 0.8
subsample: 0.75
reg_alpha: 2.5
reg_lambda: 1.25
max_depth: 7
gamma: 0.2
n_estimators: 1251
max_delta_step: 8.5
scale_pos_weight: 2.0
通过在 yaml 配置中编写模型的参数,您可以获得 4 个主要好处:
- 在模型的初始化中,参数不再是硬编码的,这使得代码更加清晰
- 合作者可以通过传递单个文件(最好是在 git repo 中)轻松实现您的模型
- 对模型进行更改不再需要代码重构
- 遵循(3),您可以轻松地在您的模型上进行“假设”实验。例如 如果 我把 max-depth 改成更深一层呢?
您的模型的配置对象
我们希望能够将 yaml 文件中包含的信息传递给项目中的其他脚本。为此,我们为您的项目定义了一个包含所有子类(将它们视为模块)的超类,这些子类将包含 yaml 中的值。通过这样做,我们可以强制类型,这样用户就不能在需要 int 的地方传递字符串。让我们定义一个这样的对象。
class YamlDemo:
class ModelSettings:
def __init__(self, random_state: int, objective: str, eval_metric: list, n_jobs: int,
learning_rate: float, colsample_bytree: float, subsample: float,
reg_alpha: float, reg_lambda: float, max_depth: int, gamma: float,
n_estimators: int, max_delta_step: float, scale_pos_weight: float):
self.random_state = random_state
self.objective = objective
self.eval_metric = eval_metric
self.n_jobs = n_jobs
self.learning_rate = learning_rate
self.colsample_bytree = colsample_bytree
self.subsample = subsample
self.reg_alpha = reg_alpha
self.reg_lambda = reg_lambda
self.max_depth = max_depth
self.gamma = gamma
self.n_estimators = n_estimators
self.max_delta_step = max_delta_step
self.scale_pos_weight = scale_pos_weight
def __init__(self, model_settings: ModelSettings, config_path: str):
self.model_settings = model_settings
self.config_path = config_path
配置分析器
有了 yaml 配置和配置对象,最后一个组件是编写解析器来读取 yaml 并用值填充配置对象。一个简单的配置解析器函数可以帮你做到这一点。
import yamldef parse_config(config_path: str) -> YamlDemo:
"""
parses yaml config; returns populated YamlDemo object
"""
with open(config_path, 'r') as stream:
try:
config_settings = yaml.safe_load(stream)
except yaml.YAMLError as e:
print(e)model_settings = YamlDemo.ModelSettings(
random_state = config_settings["model_settings"]["random_state"],
objective = config_settings["model_settings"]["objective"],
eval_metric = config_settings["model_settings"]["eval_metric"],
n_jobs = config_settings["model_settings"]["n_jobs"],
learning_rate = config_settings["model_settings"]["learning_rate"],
colsample_bytree = config_settings["model_settings"]["colsample_bytree"],
subsample = config_settings["model_settings"]["subsample"],
reg_alpha = config_settings["model_settings"]["reg_alpha"],
reg_lambda = config_settings["model_settings"]["reg_lambda"],
max_depth = config_settings["model_settings"]["max_depth"],
gamma = config_settings["model_settings"]["gamma"],
n_estimators = config_settings["model_settings"]["n_estimators"],
max_delta_step = config_settings["model_settings"]["max_delta_step"],
scale_pos_weight = config_settings["model_settings"]["scale_pos_weight"]
)
config = YamlDemo(model_settings=model_settings, config_path=config_path)
assert isinstance(config, YamlDemo)
return config
将配置对象传递给模型
现在,这个过程的最后一步是将 config 对象中的信息传递给模型。
首先,我们必须解析我们的配置以获得一个填充的对象:
config_settings = parse_config('/Users/cole.brendel/Desktop/demo.yaml')
接下来,让我们获取一个示例数据集,以查看“运行中”的模型:
from sklearn.datasets import load_iris
X,y = load_iris(return_X_y=True)# notice how I set the value for `random_state` from the config!from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.33, random_state=config_settings.model_settings.random_state)
最后,我们将把这个配置传递给一个训练模型的函数。
# fits a model on the training set/evals on test set
import pandas as pd
from pandas import DataFrame
import xgboost
from xgboost import XGBClassifier
from sklearn.metrics import classification_reportdef fit_xgb_model(config_settings: YamlDemo, X_train: DataFrame, y_train: DataFrame, X_test: DataFrame, y_test: DataFrame) -> xgboost.XGBClassifier:
"""
fits an XGB model and returns model obejct
"""
eval_set = [(X_test, y_test)] # used for early stopping# populate the model with settings from config
xgb = XGBClassifier(
random_state=config_settings.model_settings.random_state,
objective=config_settings.model_settings.objective,
eval_metric=config_settings.model_settings.eval_metric,
eval_set=eval_set,
n_jobs=config_settings.model_settings.n_jobs,
learning_rate=config_settings.model_settings.learning_rate,
colsample_bytree=config_settings.model_settings.colsample_bytree,
subsample=config_settings.model_settings.subsample,
reg_alpha=config_settings.model_settings.reg_alpha,
reg_lambda=config_settings.model_settings.reg_lambda,
max_depth=config_settings.model_settings.max_depth,
gamma=config_settings.model_settings.gamma,
n_estimators=config_settings.model_settings.n_estimators,
max_delta_step=config_settings.model_settings.max_delta_step,
scale_pos_weight=config_settings.model_settings.scale_pos_weight
)
# fit the model
xgb_fit = xgb.fit(X_train, y_train)
# predict on test set
y_pred = xgb.predict(X_test)
# show results
print(classification_report(y_test, y_pred, digits=4, target_names=['setosa', 'versicolor', 'virginica']))
return xgb_fitxgb = fit_xgb_model(config_settings, X_train, y_train, X_test, y_test)
还有维奥莱!模型已经训练评估过了!
已配置 XGBoost 模型的分类报告
这个过程的优点的简短题外话
你可能会问自己:
为什么我要写这些代码只是为了给我的模型传递一些参数呢?这看起来像一吨的工作和方式比必要的更多的代码!
确实,您可以简单地用所有的参数填充一个模型,但是您现在将自己锁定在那个配置中了!要进行更改,您需要进入并修改代码。如果你想向你的队友展示你的最新配置,它产生了最好的结果?你会复制/粘贴你的模型代码吗?为什么不把配置文件松掉呢?
这个配置只是冰山一角。通过使用我在这里概述的过程,您可以很容易地指定更多与您的模型管道相关的附加信息。例如,培训文件放在哪里?将该路径放入配置中!每个 ETL 应用后要运行哪些 ETL,临时文件存放在哪里?*配置那个!RandomSearch 应该运行多少次迭代?*再次配置!为了让您对这些配置的范围有所了解,请考虑以下高度简化的示例:
ec2_settings:
ip_address: xxx.xxx.xxx
pem_file: '/Users/{}/Desktop/demo/ssh/my.pem'
data_settings:
deploy_date: 'today' # or 'YYYY-MM-DD'
target_names: ['no', 'yes']
raw_bucket: '/Users/{}/Desktop/demo/datasets/raw'
etl_bucket_train: '/Users/{}/Desktop/demo/datasets/etl_train'
etl_bucket_score: '/Users/{}/Desktop/demo/datasets/etl_score'
tmp_bucket: '/Users/{}/Desktop/demo/datasets/tmp'
df_name: 'df.csv'
logger_settings:
log_name: 'demo.log'
logs_path: '/Users/{}/Desktop/demo/logs'
etl_settings:
pickles: '/Users/{}/Desktop/demo/src/etls/pickles'
target_variable: 'xxx_yyy'
idx_column: 'idx_col'
model_settings:
pickles: '/Users/{}/Desktop/demo/src/modeling/pickles'
predictions: '/Users/{}/Desktop/demo/predictions'
eval_metric: ['error', 'map', 'aucpr']
n_iters: 500
sampling_points: 1000
optimization_metric: 'f1_weighted'
cv_folds: 5
有了这样一个系统,分享结果和实验就变得简单了,就像把你的同事的文件从一个 yaml 文件中删除一样。
结论和下一步措施
现在,您已经拥有了开始为您的机器学习项目编写配置所需的所有工具!这个过程需要一些时间来建立,但从长远来看是值得的。
您可以进行快速实验,并且不必与代码交互就可以对模型进行更改。你使其他科学家能够简单地改变一些设置并进行测试。通过将 YAML 读入 python 类,您可以轻松地强制类型并防止传递错误的值,然后再花钱购买昂贵的计算资源。
参考
python 中统计计算的数据结构,McKinney,第九届科学中的 Python 会议录,第 445 卷,2010 年。
@software{reback2020pandas,
author = {The pandas development team},
title = {pandas-dev/pandas: Pandas},
month = feb,
year = 2020,
publisher = {Zenodo},
version = {latest},
doi = {10.5281/zenodo.3509134},
url = {https://doi.org/10.5281/zenodo.3509134}
}
Harris,C.R .,Millman,K.J .,van der Walt,S.J .等人用 NumPy 进行阵列编程。自然 585,357–362(2020)。DOI:10.1038/s 41586–020–2649–2。
sci kit-learn:Python 中的机器学习,Pedregosa 等人,JMLR 12,第 2825–2830 页,2011 年。
陈,t .,& Guestrin,C. (2016)。XGBoost:一个可扩展的树提升系统。第 22 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集*(第 785–794 页)。美国纽约州纽约市:ACM。https://doi.org/10.1145/2939672.2939785*
在 Windows 子系统 Linux (WSL2)中配置 Jupyter 笔记本
我将解释如何配置 Windows 10/11 和 Miniconda 来与使用 WSL2 的笔记本一起工作
我们将了解如何:
- 安装和配置 WSL2
- 安装和配置 Windows 终端
- 安装 Miniconda 和公共库
- 发布 Jupyter 实验室/笔记本电脑
- 将 GUI 和远程桌面安装到 WSL2,以便像 Spyder 或 Anaconda Navigator 一样使用所需的 GUI
- 谢谢
- 一些有用的资源
首先,安装 WSL2
Windows 子系统 Linux (WSL2)将于 2020 年 5 月在 Windows 10 版本 2004 中推出。如果你没有,那么按照https://docs.microsoft.com/en-us/windows/wsl/install-win10中的说明安装一个 Ubuntu 发行版
我推荐从微软商店安装 Windows 终端,而不是使用默认的 Ubuntu 终端,因为这样可以让你在同一个窗口中拥有多个终端。
使用 Sublime Text 或 Notepad++从 Windows 资源管理器编辑 Linux 文件也更方便,使用的路径是: *\wsl$*
您可以在窗口中浏览和编辑 Ubuntu 文件:
并将默认配置文件更改为打开至 Ubuntu 终端打开设置文件,并根据 Ubuntu 指南更改 defaultProfile 的值:
用 Visual Studio 代码打开的 settings.json
更新你的 Linux 系统
在 Ubuntu 上打开一个新的终端,运行以下命令:
sudo apt-get update
sudo apt-get upgrade
sudo apt autoremove
我将使用 Ubuntu 20.04.1 LTS 来检查版本,如下所示:
lsb_release -a
uname -r
安装迷你康达
最好用 Miniconda 而不是 Anaconda。后者包含了许多你通常不会用到的库,这意味着更慢的发行版更新和更多的磁盘空间。
我的朋友 Ted Petrou 在https://medium . com/dunder-data/anaconda-is-budget-set-up-a-lean-robust-data-science-environment-with-miniconda-and-conda-forge-b 48 E1 AC 11646中写了一篇详细的文章
从https://repo.anaconda.com/miniconda/下载最后一个文件,并按照说明操作:
cd ~
wget [https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh](https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh)
chmod +x Miniconda3-latest-Linux-x86_64.sh
sh Miniconda3-latest-Linux-x86_64.sh
rm Miniconda3-latest-Linux-x86_64.sh
如果你更喜欢 **Anaconda,**过程类似,你需要使用来自https://repo.anaconda.com/archive/的最后一个文件
按回车键并阅读完整的许可证
选择安装位置,回车默认
我推荐“是”来设置你的 Ubuntu 用户的活动环境
下次打开终端时,您会注意到在 user@server 提示符前有一个 (base) 文本,这意味着在 conda:
python
conda info
conda info --envs
接下来,我们将进行一些更新:
conda update conda
conda update --all
安装库&工具
接下来,我们将进行一些基础安装,以获得熊猫、Jupyter 实验室/笔记本和机器学习:
conda install pandas scikit-learn matplotlib jupyter jupyterlab sqlalchemy seaborn pip git
然后安装 Jupyter 扩展并刷新任何更新:
conda install -c conda-forge jupyter_contrib_nbextensions
conda update conda
conda update --all
推出 Jupyter 实验室和笔记本电脑
我更喜欢 Jupyter Lab 而不是 Notebook,因为它可以让你更灵活地在同一个标签浏览器下打开多个窗口,允许你在命令提示符之外打开多个文件。为了避免消息错误,运行每个带有无浏览器参数的命令
朱庇特实验室
使用以下命令打开一个新的 Ubuntu 终端:
jupyter lab --no-browser
复制并粘贴完整的 URL,包括令牌
Jupyter 笔记本
使用以下命令打开一个新的 Ubuntu 终端:
jupyter notebook --no-browser
复制并粘贴完整的 URL,包括令牌。
网络连接问题
如果您失去了网络连接,例如,在 ping Google 时显示超时错误,那么可能与 resolv.conf 文件中的 servername 的更改有关。
ping google.com
要修复它,您需要删除该文件以断开与运行文件夹的链接,并创建一个 wsl.conf 文件以避免再次生成 resolv.conf 文件,并执行以下语句:
sudo rm /etc/resolv.conf
sudo bash -c 'echo "nameserver 8.8.8.8" > /etc/resolv.conf'
sudo bash -c 'echo "[network]" > /etc/wsl.conf'
sudo bash -c 'echo "generateResolvConf = false" >> /etc/wsl.conf'
sudo chattr +i /etc/resolv.conf
解决本地主机的问题
有些版本无法使用 localhost 连接。Windows 将发布更新来解决此问题,直到您可以使用 IP 地址连接并更改 localhost 。要知道您的 IP 地址,您可以通过命令使用斜杠前面的数字:
ip addr | grep eth0 | grep inet
安装图形界面和远程桌面
WSL2 不包括 GUI,任何需要用户界面的程序都会给出类似的错误:
QStandardPaths: XDG_RUNTIME_DIR not set
qt.qpa.screen: QXcbConnection: Could not connect to display
Could not connect to any X display.
如果您想运行一些图形接口,如 anaconda-navigator 或 spyder IDE,下一步是可选的。使用以下命令安装:
conda install spyder anaconda-navigator
如果你通过终端启动程序会这样失败:
按照以下步骤在端口 3390 中安装 XFCE4 lightdm 和远程桌面( xrdp )。我更改了端口以避免与本地窗口冲突。
运行下面的命令,选择 lightdm 作为 X 显示管理器:
sudo apt update && sudo apt -y upgrade
sudo apt-get purge xrdp
sudo apt-get install -y xfce4 xfce4-goodies
sudo apt-get install xrdp
sudo cp /etc/xrdp/xrdp.ini /etc/xrdp/xrdp.ini.bak
sudo sed -i 's/3389/3390/g' /etc/xrdp/xrdp.ini
sudo sed -i 's/max_bpp=32/#max_bpp=32\nmax_bpp=128/g' /etc/xrdp/xrdp.ini
sudo sed -i 's/xserverbpp=24/#xserverbpp=24\nxserverbpp=128/g' /etc/xrdp/xrdp.ini
echo xfce4-session > ~/.xsession
sudo systemctl enable dbus
sudo /etc/init.d/dbus start
sudo /etc/init.d/xrdp start
sudo /etc/init.d/xrdp status
选择 lightdm
使用您的 :3388 远程桌面连接
打开终端运行 spyder IDE
谢谢
最后,我要感谢泰德·彼得鲁和 T2·斯科特·波斯顿,他们是善良而知识渊博的人,在我开始学习 Python 熊猫的时候给了我指导和帮助,还有我的兄弟 T4·迈克尔·萨维德拉,是他们启发了我写这篇文章。
有用的资源
[## Anaconda 过于臃肿——用 Miniconda 和 Conda-Forge 建立一个精简、健壮的数据科学环境
在本教程中,我将描述在您的……上建立一个瘦的和完整的 Python 数据科学环境的过程
medium.com](https://medium.com/dunder-data/anaconda-is-bloated-set-up-a-lean-robust-data-science-environment-with-miniconda-and-conda-forge-b48e1ac11646) [## 使用 WSL 在 Windows 上构建 Python 开发环境
2016 年,微软推出了面向 Linux 的 Windows 子系统(WSL),为 Windows 带来了强大的 Unix 功能。在…
pbpython.com](https://pbpython.com/wsl-python.html) [## 用 Visual Studio 代码在 Linux 的 Windows 子系统中开发
Visual Studio Code Remote - WSL 扩展允许您将 Windows Subsystem for Linux (WSL)用作您的全职…
code.visualstudio.com](https://code.visualstudio.com/docs/remote/wsl) [## 使用 Visual Studio 代码在 Linux 的 Windows 子系统中工作
本教程将带您了解如何启用 Windows Subsystem for Linux (WSL ),以及如何使用…
code.visualstudio.com](https://code.visualstudio.com/docs/remote/wsl-tutorial) [## 在 Visual Studio 代码中使用 Jupyter 笔记本
Jupyter(以前的 IPython Notebook)是一个开源项目,可以让您轻松地将 Markdown 文本和可执行文件结合起来…
code.visualstudio.com](https://code.visualstudio.com/docs/python/jupyter-support) [## Linux 的 Windows 子系统概述
Linux 的 Windows 子系统允许开发人员运行 GNU/Linux 环境——包括大多数命令行工具…
docs.microsoft.com](https://docs.microsoft.com/en-us/windows/wsl/) [## Craig Loewen,Windows 命令行的作者
该网站使用 cookies 进行分析、个性化内容和广告。通过继续浏览本网站,您同意…
devblogs.microsoft.com](https://devblogs.microsoft.com/commandline/author/crloewenmicrosoft-com/)
确认偏差是探索性数据分析的敌人
人类有一种倾向,想要证明先前的信念,这可能会对数据分析推动变化的能力产生毁灭性的影响。
在 16 世纪到 19 世纪之间,在西欧,成千上万的妇女在政治迫害中被处死。由于识别女巫的困难性,特殊的测试被用来确定一个女人是否是女巫。
其中一个例子是将这名女子双手反绑扔进水中。如果她漂浮,她是一个女巫,被认为是被撒旦所救,并被判处死刑。如果她是淹死的,她是无辜的。
确认偏差
尽管政治迫害和数据分析之间的联系可能还不清楚,但它们都受制于被称为确认偏差的认知偏差。
当一个人搜索或解释信息以符合他们先前的信念时,就会产生确认偏差。
政治迫害经常被用作确认偏差的一个例子。如果一个女人在这个过程中死去,证明她是无辜的没有任何实际意义。但这不是测试的重点。取而代之的是,它被设计成一种纯粹的方法来确认先前的信念,内疚。
探索性数据分析
探索性数据分析 (EDA)是对数据的初步调查,通常使用统计和图形表示,对其进行总结和理解。
本质上,EDA 是回答关于数据的问题的过程。其中一些可能非常简单:
- 数据有多少行/列?
- 列的类型有哪些?
- 有没有数据缺失?
然而,随着 EDA 的发展,问题开始变得更加复杂。让我们以显示一部新电影票房信息的数据集为例。一个问题可能是
周末售票多吗?
你可能会注意到,我写这个问题是为了确保可以用简单的“是”或“不是”来回答。这可能看起来微不足道,但正是在这里,偏见可能开始出现。我可以用不同的方式写这个问题,
一周中的特定日子会有更多的门票销售吗?
我没有设计一个问题来确定一周的门票销售分布,而是提出了一个问题来验证我现有的信念,即周末会卖出更多的门票。
杰瑞米·雅普在 Unsplash 上的照片
背景可能相去甚远,但这和女巫测试是一样的,设计女巫测试只是为了证明女人是女巫,而不是一个女人是不是女巫。
偏见的问题
这似乎是一个微不足道的观点。在一天结束的时候,你将最终决定周末是否能卖出更多的票。
问题不在于分析本身,而在于之后会发生什么。就其本质而言,EDA 是通向另一个问题的垫脚石…那又怎样?
我们使用 EDA 过程中发现的信息来推动变革;也许修改现有的过程或创建一个新的过程。但是改变本身就包含了对原有信念的颠覆。
如果确认偏见阻止人们寻找违背他们先前信念的证据,那么再多的 EDA 也不能推动有意义的改变。
相反会发生什么?
想象一下,我们发现这一周的门票销售增加了。大多数人会跳进解释的兔子洞,而不是采取行动(也许在周末增加广告以提高周末门票销售)。
利用进一步的(通常是人为的)分析,他们会试图解释为什么他们的信念是正确的,尽管有证据。然后,EDA 不再成为变革的工具,而是成为无效理论的自我提升。
减轻确认偏差
人类对确认偏差有一种天然的倾向,我们经常分不清自己在做什么。因此,我们需要确保我们正在采取积极和有目的的措施来减轻它。
小的改变,比如如上所述的重新构思问题,可以产生很大的不同,因为我们下意识地将自己从这种偏见中移除。
这并不是说我们应该完全无视我们先前的信念。我们通常有一个理由,如果有相反的证据,我们应该质疑它。相反,我们需要确保当我们质疑它时,我们是从公平和平衡的角度这样做的。
这通常是很难做到的,所以另一个避免确认偏差的技巧是获得第二意见。请其他人看看证据,看看他们的想法。
EDA 是建立在数据基础上的强大工具。但是数据不仅包含固有的偏见,而且还会被分析它的人所偏见。我们有责任了解何时何地我们可能会有偏见,并减少偏见。
如果你喜欢这篇文章,你可能会喜欢阅读 为什么所有数据科学家都应该了解行为经济学 以了解更多关于确认偏差以及它如何与其他类型的认知偏差一起影响数据分析和数据科学的信息。
以人性化的个人化面对认知的不公正
利用 GDPR 的伦理基础引入数字身份和个性化的新范式
GDPR 基于欧洲对人的特殊看法,旨在保护数字时代人的基本方面。 DDP 在 Unsplash 上拍照
基于机器学习的个性化服务已经成为我们日益数字化的生活中不可或缺的一部分。个性化依赖于大量的行为大数据(BBD) :人类与应用程序、设备和社交网络交互时产生的个人数据。BBD 是我们数字表现的基本原材料。
随着网络生活的稳步发展,人的数字表现在法律和道德上变得越来越重要。有影响力的欧洲法律理论家和哲学家甚至写了一份关于生活的宣言,围绕着数字时代对人类意味着什么展开讨论。与此同时,IEEE 已经阐明了一个伦理一致设计 (EAD)的愿景,让“个人能够管理他们的身份和他们数据的伦理含义。”
但是这样的设计对于推荐系统来说意味着什么呢?而给人这种权力又有什么意义?驱动这种想法的是人类的哪些潜在观念?这就是我们要解开的。
威廉·狄尔泰和马克斯·韦伯认为人文科学需要与自然科学完全不同的方法论。我们建议将叙事理解作为一种范式,赋予我们的数字体验以意义,并尊重不同的观点。Andriyko Podilnyk 在 Unsplash 上拍摄的照片
我们的愿景:人性化个性化
我们引入我们的概念 人性化个性化 作为思考数字身份和个性化的一种方式,这借鉴了欧盟通用数据保护条例 (GDPR)中体现的基本道德价值观。人性化的个性化首先着眼于哪些能力使人与众不同,然后试图想象如果推荐系统和个性化支持这些能力,它们会是什么样子。
我们的人性化个性化概念设想通过数据控制者和数据主体之间的对话叙事结构的概念,从由我们的“有机体”兴趣主导的隐含的、基于行为的表示范式,转变为以意识为中心的、明确的和“反思的】反馈。人文主义的个性化受到康德、黑格尔、哈贝马斯、利科、德里达等人的哲学思想的启发。
除了个性化,对叙事的关注可能会对人工智能/人工智能的未来产生广泛的影响。如果我们要打破人工智能中意义的障碍,我们也需要打破叙事的障碍。此外,叙事的内在可理解性在“以用户为中心”的可解释人工智能的新兴领域可能是有用的,特别是在 GDPR 等法规赋予数据主体对算法决策进行清晰、可理解的解释的权利的情况下。最后,由于其直观的“解释力”,叙事解释可以作为因果建模新方法的有趣镜头。
叙述的准确性和认知的不公正
我们提出 叙述准确性 的概念,作为个性化的定向设计目标。通过最大化用作推荐系统输入的个人数据和最终推荐本身的叙述准确性,我们可以减少通过个性化对个人造成的 认知不公正 。
认知不公正是多方面的。它指的是我们以一种不公平的方式“分配”可信度给一个人的真理主张,即贬低他们作为一个认知者的能力。这也意味着我们缺乏理解他人经历的概念资源。为什么关注叙述的准确性及其补充,认知的不公正?
因为我们相信叙事的概念是值得保护的人类经验的重要特征。与此同时,我们拒绝启蒙理想中解决真理问题的单一、普遍的“方法”。
换句话说,实现完全客观的“无中生有的观点”是不可能的。相反,当我们融合来自不同视角的不同输入时,知识会变得更加强大。如果你想阅读更多的细节,特别是关于 GDPR 的哲学人类学,请参阅我们的工作论文 《超越我们的行为:GDPR 和人文个性化 》。
那么,什么是个性化呢?
个性化是一项巨大的业务。例如,网飞声称由于其个性化努力每年节省 1B 美元。下面是脸书描述它如何使用你的个人数据来“个性化”你在这个平台上的体验的新服务条款:
您在脸书的体验与众不同:从您在 News Feed 或我们的视频平台上看到的帖子、故事、事件、广告和其他内容,到您关注的页面和您可能使用的其他功能,如趋势、市场和搜索。我们使用我们拥有的数据来个性化您的体验,例如,关于您建立的联系、您选择的选项和设置,以及您在我们的产品上和产品外分享和做的事情。
为什么我们建议在 GDPR 建立人工智能伦理
简而言之,我们认为 GDPR 作为人工智能/人工授精的法律规范和伦理基础具有双重意义。主要原因是我们不认为增加当前道德 AI/ML 的竞争原则、指导方针和框架是有成效的。仅一篇论文就列出了至少 84 个“AI 伦理”指南的例子,其中大部分还不到 4 年。没有人能理解这一切。
此外,通过 GDPR 将道德原则与法律规范联系起来是有价值的,因为原则上,GDPR 适用于世界任何地方的任何数据控制者(T0)———处理居住在欧盟的数据主体(T5)的个人数据。法律有制度支持,通过国家对合法使用武力的垄断来实现遵守。因此,在我们看来,(潜在地)由武力支持的道德更有可能促进全球工业和研究人员的遵守。
信息自决和人格权
GDPR 赋予数据主体的权利反映了欧洲对人的某种理解。这些原则很有价值,因为它们经受住了几个世纪以来激烈的哲学审视。从欧洲的角度来看,数据保护和隐私是旨在维护人类尊严的工具。如果你真的对细节感兴趣,我们会在与上面链接的论文中探索使人类生命有价值背后的哲学思想。
无论如何,两个关键概念构成了 GDPR 的伦理基础:信息自主及其前身个人个性自由发展的权利。根据法律学者 Antoinette Rouvroy 和 Yves Poullet 的说法,信息自决被定义为“个人对有关他的数据和信息的控制”,并且是任何人类自决的先决条件。自决也有一个政治层面,因为一个合作、民主的社会取决于其公民是否有自决的能力。在我们的论文中,我们将这些观点与尤尔根·哈贝马斯的“交流理性”联系起来。
我们的数字行为从根本上被曲解了
我们断言,并不是个性化如此难以置信地准确,而是我们作为语言、社会和身体动物,在我们自由活动和思想的潜力方面欺骗了自己。
数字环境进一步限制和约束了人类的潜能。也许更糟糕的是,随着数字环境中自由度的减少,人类行为的诠释学问题出现了,并提出了伦理问题。首先,收集隐性数据背后的行为主义假设没有意识到一个重要的警告:数字行为的意义从根本上说是不确定的。因为人类是有意识、有意图的存在,我们发起的每一个行动都可以从外部/物理主义或内部/现象学的角度来看。
当 BBD 平台和数据科学家将复杂行为(例如,完成一项交易)分解为过于狭窄的“子符号”类别(例如,点击、鼠标轨迹和其他“微行为”)时,意图变得与结果分离。更重要的是,从意图到行动的明确的一对一映射变得不可能。一个人不能意愿去做他不能首先识别的事情。
正如心理学家 Vallacher 和 Wegner 所说,
正如哲学家早就注意到的,行为的任何部分都可以有意识地用许多不同的方式来识别。像“与某人见面”这样简单的事情……任何一个有轻微活跃精神生活的人都可能认为是“社交”、“寒暄”、“了解一个新的人”、“展示一个人的个性”,甚至是“说话”。
因此,误解(或缺乏完整的解释)被融入到数字生活中,当自动化系统能够实时动态地改变数字环境时,这种情况会变得更糟,比如脸书使用的基于强化学习的推荐系统。因此,我们面临着解释的危机。怎么办?
如果我们遵循 GDPR,我们让数据主体自己决定。
根据哲学家保罗·里科尔的说法,我们是“角色”,其行为通过融入我们讲述的关于自己的故事而获得意义。照片由雅各布·欧文在 Unsplash 上拍摄
通过叙事身份连接道德和社会身份
著名的心理学家和语言学家迈克尔·托马塞罗认为,我们在语言群体中的成员关系维系着我们的社会和道德身份。我们为自己的行为给出的理由与我们在这个社区中的角色和地位有关。从很小的时候起,孩子们就必须决定做什么,形成什么样的道德和社会身份。孩子们做出这些决定的方式对他们社区中的其他人和他们自己都是合理的。
社会身份和道德身份是通过与他人交流、讲道理的过程联系在一起的。托马塞罗声称,这一过程已经内化为一种规范的自我管理形式,构成了我们的道德身份。从内在视角(自我、私人)和外在视角(他人、公众)来看,我们的心理统一性要求我们做某些事情,以便继续做我们自己。对同一事件的内在和外在观点之间的认知差距是驱动认知不公正的原因,我们将在下面讨论。
道德和社会身份是共时(横截面)结构。它们是我们在特定的时间点向自己展示自我的方式。但是我们还没有解释这些身份是如何随时间演变的。为此,我们需要一个历时(纵向)的身份账户。
叙事身份:随着时间的推移,它赋予你的生活意义
根据心理学家杰罗姆·布鲁纳的说法,叙事是我们的大脑构建现实的工具。值得指出的是,它们的一些独特特征捕捉到了人类经历中所有混乱和不完美的荣耀。
- 历时性:叙事说明了人类时间内有序事件的顺序,而不是绝对的“时钟时间”
- 特殊性:记叙文是由叙述者的特定化身讲述的按时间顺序排列的事件。
- 意向状态蕴涵:在一个叙述中,原因是意向状态(信念、欲望、价值观等)。)作为原因和/或解释。
- 解释学可组合性:文本与文本意义之间存在差距。意义产生于对部分与整体关系的理解。
- **可指性:**叙事中的现实主义来自共识,而不是来自与某种“真实”现实的对应。
- 语境敏感性和协商性:一篇文章的读者“根据自己的条件吸收它”,从而在这个过程中改变自己。我们通过对话协商意义。
通过叙事的历时性,我们随着时间的推移将我们的道德和社会身份结合起来,从而产生了人的独特性。
当个人的真理主张没有得到适当的证据支持时,认知不公正就会出现。由粘土银行在 Unsplash 上拍摄
叙述的准确性和认知的不公正
认识论是对知识及其基础的研究。我们改编了米兰达·弗里克的认知不公正概念,并用它来揭示个性化叙事的准确性问题。
弗里克对不公正感兴趣,因为它涉及到不尊重某人的“认知能力”认知上的不公正本质上降低了一个人对自己判断的信任和理解自己生活经验的能力。认知不公正有康德和黑格尔的两个方面。值得注意的是,认知公正要求相互承认他人的观点和经验,特别是那些处于不对称认知权力位置的人(即,相对于数据收集者的数据主体)。
证明不公
有两个维度的认知不公正适用于数据主体接收个性化推荐的情况。首先,当偏见或偏向导致数据收集者对数据主体对记录的行为或事件(包括建议)的解释给出“降低的可信度”时,可能会出现证据不公正。
例如,如果一个数据收集者只使用无意识产生的 BBD,而不对明确的反馈进行加权,那么就出现了一种证明不公正。另一个例子可能是 BBD 平台允许用户“降级”不好的推荐,但是这些实际上并没有被考虑到改变推荐。
从贝叶斯模型平均的角度来看,我们也可以认为,当模型选择中的不确定性(忽略数据主体的主观“模型”)被忽略而有利于数据收集器或处理器的预定义模型时,证明是不公平的。
诠释的不公正
当数据收集者或数据收集平台缺乏“解释资源”来理解数据主体的生活经历,从而使其处于不利地位时,可能会出现解释不公正。根本问题是, 算什么 ?
在对一个事件的一种解释下,我们可以产生统计规律,而在另一种解释下,我们可以得到不同的统计规律,这些规律被编码在 ML 模型的参数中。因此,BBD 没有一个“最佳”的表示或编码。
对于什么算什么,在不同的解释下有不同的表达。
例如,目前,BBD 平台记录的事件类别通常由系统设计者预先定义,而没有来自平台用户的任何输入。如果推荐系统的设计者在使用该系统时不考虑数据主体的预期行为、价值和目标的多样性和丰富性,解释的不公正将是不可避免的。
人性化个性化的未来
制作和维持连贯的数字自我叙事是人类独有的能力,我们不能把它留给他人或外包给自动化代理。这种观点得到了 GDPR 和 IEEE EAD 原则的认同。我们是讲述自己的故事中的人物。我们知道哪些事件定义了我们,我们知道哪些价值观驱动着我们,我们知道我们行为背后的原因。如果我们做不到,我们有能力去尝试找出答案。
BBD 收集平台的公司所有者和数据科学家可能会根据他们对我们观察到的行为的统计分析提出相反的主张,但我们认为信息自决权胜过这些主张。
正如后现代主义者所指出的,伦理和解释的问题是不可分的。我们所相信的真理会影响我们对正确事物的判断。但如果意义是社会建构的,单靠数据主体是无法解决这些问题的。这需要社区和真诚的交流来制定我们共同语言游戏的“规则”。数据科学家将需要在数字领域的意义协商和身份形成的辩证中发挥更大的作用。毕竟,如果类别的原意是“公开指责”,那么数据主体作为公众的一员,应该在这个过程中发挥作用。
怀疑论者可能会反驳说,优化叙事准确性需要在推荐系统准确推荐项目和预测特定行为的能力之间进行权衡。商业利润也可能受到影响。然而,GDPR 迫使我们问这样一个问题:
我们最终是否希望根据企业或人类的需求和利益来代表自己?
[1] 解释学最初是关于圣经文本解释方法的研究,但在 20 世纪被哲学家们重新发明为一种认识论方法。
[2]最初在希腊语中,“category”一词的意思是“公开指责”注意社会共识所扮演的角色。
困惑于如何在 Coursera 上挑选最好的在线课程?
Psst,建一个航向分析器。
帕特里克·托马索在 Unsplash 上的照片
问题是
如今网上课程并不缺乏。在过去几年中,MOOC 平台的受欢迎程度飙升,促使许多其他此类平台涌现出来。
其中最受欢迎的 Coursera 长期以来一直是许多学习者的宠儿。
然而,并不是很多用户对目前的所有课程都满意。
有时难度太高,或者动手实验已经过时,或者教师隐藏在技术术语后面,或者视频缺乏上下文清晰度等等。
面对如此多的课程,学习者只选择最好的课程来节省时间和金钱是很重要的。
一门课程的真正勇气是由负面评价的数量来检验的,因为只有真正失望的用户才会费心去写一个糟糕的评价并给出一个低评级;这就是为什么即使很高的负面评价率也能告诉我们很多关于课程质量的信息。在这个时间就是金钱的时代,重要的是我们不要在不那么好的课程上投入时间。
但是怎么做呢?每门课程都有成千上万的评论,如果不是几百的话,而且大多数显示在首页的评论都是顶级评论,嗯…总是好的。
此外,人们不能只看收视率,因为它们几乎不可靠。甚至我还见过高达 3/4 星的收视率还伴随着差评。
需要是发明之母。
我需要一个工具来判断选择哪门课程,而不用列出我所有潜在课程的所有评论和意见。
而 CourseraAnalyzer 就是这样诞生的。
在这篇文章中,我将带您快速浏览一下我是如何开发这个为我提供了极好用途的本地 web 应用程序的。如果您想更深入地研究这背后的代码,请随意查看这个项目的库。
解决方案
构建一个应用程序,查找用户指定的课程,对评论进行情感分析,然后以可视化的形式显示结果。
听起来很简单,对吧?
不完全是。
这包含了网络抓取+自然语言处理+机器学习+网络开发。难?是的。不可能?号码
我的第一步是摘录课程的评论。
我用的是 BeautifulSoup(想用硒也可以)刮痧。将 URL 作为输入后,我修改了 URL 以访问课程的评论页面,然后从所有页面中抓取所有评论。
( 注意 :如果您不能完全理解这一点,请不要担心,因为代码片段只是整个文件的一小部分。我的目的只是给你一个小小的机会,让你知道它是如何工作的。)
然后,我使用一个文本分类器(我已经事先训练和腌制过)将评论分为正面和负面评论。
统计完评论后,我将数字传递给 Chart.js,它在网页上显示漂亮的交互式图表。
但是有一个讨厌的小问题。
花了太多时间。
搜集成千上万的评论并对它们使用文本分类器是非常耗时的。但我想让它走得更快。
所以我创建了一个. json 文件来存储搜索到的课程列表及其结果。如果用户输入的课程已经存在于。json 文件,我只是加载结果,而不是每次有请求时都重复相同的过程。
最后,我创建了一个小 Flask 应用程序,定义了不同的 API 端点和函数,以便将所有这些程序转换成一个单元。我用 Heroku 把它放到了网上。
这是网站https://courseraanalyzer.herokuapp.com/主页的截图。
我显然不是最擅长设计的人,但是,只要它能用,对吗?
在左下方,显示了已经分析过的课程列表。如果您正在寻找的课程不存在,请在搜索框中输入课程的 URL,然后单击“分析”。
它将给出所有评论的简要报告,并显示一些可视化效果来帮助您得出结论。
就是这样!
这个应用程序在许多方面仍然落后,但是对于第一个版本来说,这已经很好了。如果您对此有任何疑问,请随时联系我。谢谢大家!
Github 库:
https://github.com/sthitaprajna-mishra/coursera-analyzer
用于目标检测的混淆矩阵
一种评估实例分割模型性能的度量
在训练机器学习分类器之后,下一步是使用相关度量来评估其性能。混淆矩阵是评估指标之一。
混淆矩阵是显示给定一些真值/实例的分类器性能的表格(监督学习类型)。
但是对于对象检测和实例分割任务,混淆矩阵的计算不太直观。首先,有必要理解另一个支持度量:并集上的交集(IoU)。交集/并集(IoU)在对象检测和实例分割任务的计算指标中起着关键作用。
交集超过并集(借据)
IoU ,也称为 Jaccard index ,是一种评估地面真实掩码( gt )和预测掩码( pd )之间重叠的度量。在对象检测中,我们可以使用 IoU 来确定给定的检测是否有效。
IoU 的计算方法为 gt 和 pd 之间的重叠/相交面积除以两者之间的并集面积,即:
IoU 的定义如下:
图 1(来源:作者)
注: IoU 度量范围从 0 到 1,0 表示没有重叠,1 表示 gt 和 pd 之间完全重叠。
混淆矩阵由 4 个分量组成,即真阳性(TP)、真阴性(TN)、假阳性(FP)和假阴性(FN) 。为了定义所有组件,我们需要根据 IoU 定义一些阈值(比如α)。
图 2:2 类的混淆矩阵:1 和 2(来源:作者)
- 真阳性(TP) —这是当事实确实为阳性时分类器预测为阳性的实例,即 IoU ≥ α的检测。
- 假阳性(FP) —这是一种误阳性检测,即 IoU < α的检测。
- 假阴性(FN)-这是分类器未检测到的实际实例。
- 真阴性(TN) —如果实际实例也是阴性的,此度量意味着阴性检测。在对象检测中,该度量不适用,因为存在许多不应该在图像中检测到的可能预测。因此,TN 包括未被检测到的所有可能的错误检测。
这些概念可以通过一些图形示例直观地理解(让我们考虑 IOU 阈值,α = 0.5)
图 3:左:假阴性(FN),右:真阳性(TP),演职员表:丹尼尔·延森在 Unsplash 上的照片
图 4:都是假阳性(FP),演职员表:照片由丹尼尔·延森在 Unsplash 上拍摄
**备注:**根据 IoU 阈值的定义,如果我们选择阈值大于 0.86,则图 3 右侧变为 FP,如果我们选择 IoU 阈值小于 0.14,则图 4 右侧变为 TP
可以从混淆矩阵中得出的其他指标包括:
- 精度是分类器仅识别相关对象的能力。它是正确的正面预测的比例,由下式给出
- Recall 是一个衡量分类器找到所有相关案例(即所有基本事实)的能力的指标。它是在所有基本事实中检测到的真阳性的比例,定义为
₁分数是精确度和召回率的调和平均值。
示例
考虑下面的图像,带有基本事实(深蓝色)和分类器检测(红色)。通过观察,你能说出 TP,FP 和 FN 的数目吗?
图 5(来源:富士-SfM 数据集(引用于参考资料部分))
Python 实现
在 Python 中,可以使用 Shapely 库计算混淆矩阵。以下函数 ( **evaluation(ground,pred,iou_value)**
→用于 **TP、FP、FN、Precision、Recall、F₁的 6 值元组)**可用于确定上述图像的混淆矩阵(图 5)
参数:
- 地面 —是n×m×2数组,其中 n 是给定图像的地面真实实例的数量, m 是在掩膜圆周上采样的 (x,y) 对的数量。
- pred 为 p × q × 2 数组,其中 p 为检测数, q 为预测掩码采样的 (x,y) 点数
- iou_value 为 iou 阈值
对于图 5 和 IoU 阈值,α = 0.5,**evaluation(ground,pred,iou_value)**
→
TP: 9 FP: 5 FN: 0 GT: 10
Precall: 0.643 Recall: 1.0 F1 score: 0.783
感谢您的阅读:-)
在 https://medium.com/@kiprono_65591/membership加入媒体以获取媒体上的所有报道。
你也可以在我发文章的时候通过这个链接把文章发到你的邮箱里:https://medium.com/subscribe/@kiprono_65591
参考文献
若尔迪·吉恩-莫拉、里卡多·桑斯-科尔蒂埃拉、琼·罗塞尔-波罗、何塞普-拉蒙·莫罗斯、哈维尔·鲁伊斯-伊达尔戈、维罗尼卡·维拉普拉纳和爱德华·格雷戈里奥。(2020).富士 SfM 数据集。芝诺多。http://doi.org/10.528/zenodo.3712808
Everingham,m , es lami,s . A , Van Gool,l , Williams,c . k , Winn,j ,和 Zisserman,A,《Pascal 视觉对象类挑战:回顾》。国际计算机视觉杂志,111(1):98–136,2015。
对 ROC 分析的介绍。模式识别快报,27(8):861–874,2006。
混淆矩阵—已解释
如何利用混淆矩阵
分类是一种监督学习方法,其中目标变量是离散的(或分类的)。评估机器学习模型和构建它一样重要。我们正在创建模型来处理新的、以前看不到的数据。因此,需要进行全面和多方面的评估,以创建稳健的模型。当涉及到分类模型时,评估过程变得有些棘手。
困惑矩阵背后的动机
准确度显示正确预测与所有预测的比率:
在某些情况下,准确性不足以评估模型。假设我们为二元分类任务建立一个模型,目标变量的分布是不平衡的(93%的数据点在 A 类中,7%在 B 类中)。
我们有一个只预测 A 类的模型,甚至很难称之为“模型”,因为它预测 A 类,没有任何计算。然而,由于 93%的样本属于 A 类,因此我们的模型的准确率为 93%。
如果正确检测 B 类样本至关重要,而我们又不能对任何 B 类样本进行错误分类(例如癌症预测),该怎么办?这就是混淆矩阵发挥作用的地方。
混乱矩阵
混淆矩阵不是评估模型的指标,但它提供了对预测的洞察。学习混淆矩阵对于理解其他分类指标很重要,例如精度和召回。
混淆矩阵通过显示每个类别的正确和错误(即真或假)预测,比分类准确性更深入。在二进制分类任务的情况下,混淆矩阵是 2×2 矩阵。如果有三个不同的类,那就是一个 3x3 的矩阵,以此类推。
假设 A 类是正类,B 类是负类。混淆矩阵的关键术语如下:
- 真阳性(TP) :预测阳性类别为阳性(ok)
- 假阳性(FP) :将阴性类别预测为阳性(不正常)
- 假阴性(FN) :将阳性类别预测为阴性(不正常)
- 真阴性(TN) :预测阴性类别为阴性(ok)
期望的结果是预测类和实际类是相同的。这可能看起来令人困惑,但你可以想出一个窍门来记住。我的如下:
第二个词是模型预测的。
第一个字表示预测是否正确。
注意:假阳性也称为 I 型错误。假阴性也称为 II 型错误。
混淆矩阵用于计算精度和召回率。
精度和召回
精确度和召回率度量将分类准确性向前推进了一步,并允许我们获得对模型评估的更具体的理解。选择哪一个取决于任务和我们的目标。
Precision 衡量当预测为正时我们的模型有多好。它是正确的正面预测与所有正面预测的比率:
回忆测量我们的模型在正确预测正类方面有多好。它是正确的正面预测与所有正面类别的比率。
精度的焦点是正预测所以它表示有多少正预测是真的。召回的焦点是实际肯定类别,因此它指示模型能够正确预测多少肯定类别。
精准还是召回?
我们不能试图同时最大化精确度和召回率,因为它们之间有一个平衡。提高精度会降低召回率,反之亦然。我们可以根据任务来最大化精确度或回忆。
考虑一个垃圾邮件检测模型,我们试图最大化精确度,因为我们希望当一封邮件被检测为垃圾邮件时是正确的。我们不想将一封普通的电子邮件标记为垃圾邮件(即误报)。如果模型不能捕捉一些垃圾邮件,这是可以接受的。但是,如果一封非常重要的电子邮件被标记为垃圾邮件,后果可能会很严重。
另一方面,对于取消细胞检测任务,我们需要最大化召回,因为我们想要检测每个阳性类别(恶性细胞)。如果模型预测恶性细胞为良性(即假阴性),这将是一个严重的错误。
还有一个将精确度和召回率结合成一个数字的方法,那就是 F1 分数。
F1 分数
F1 分数是精确度和召回率的加权平均值。
对于类别分布不均匀的问题,F1 分数是比准确度更有用的度量,因为它考虑了假阳性和假阴性。
f1 得分的最佳值是 1,最差值是 0。
敏感性和特异性
敏感度,也称为真阳性率(TPR),与回忆相同。因此,它测量被正确预测为阳性的阳性类别的比例。
特异性类似于敏感性,但侧重于负类。它测量被正确预测为负面的负面类别的比例。
结论
免费的午餐定理在这里也不适用。对于所有的任务,没有一个最优的、容易找到的选择。我们需要清楚地定义需求,并根据这些需求选择度量标准。
感谢您的阅读。如果您有任何反馈,请告诉我。
多类机器学习模型的混淆矩阵
关于如何计算多类分类问题的精确度、召回率和 F1 分数的初学者指南。
混淆矩阵是一种可视化预测模型性能的表格方式。混淆矩阵中的每个条目表示模型做出的正确或错误分类的预测数量。
任何已经熟悉混淆矩阵的人都知道,大多数情况下,它是针对二元分类问题来解释的。这个解释不在其中。今天我们将看到混淆矩阵如何在多类机器学习模型上工作。然而,我们将从使用二元分类的一点背景开始,只是为了正确地看待事情。
二元分类的混淆矩阵
二元分类的混淆矩阵
如你所见,二进制分类问题只有两个类要分类,最好是一个正类和一个负类。现在让我们看看混淆矩阵的度量。
真阳性(TP): 指分类器正确预测阳性类为正的预测次数。
真否定(TN): 指分类器正确预测否定类为否定的预测次数。
假阳性(FP): 指分类器错误地将阴性类预测为阳性的预测次数。
假阴性(FN): 指分类器错误地将阳性类预测为阴性的预测次数。
用混淆矩阵作为你的机器学习模型的评估标准总是比较好的。它为您的模型提供了一个非常简单而有效的性能测量方法。以下是困惑矩阵中一些你可以使用的最常见的绩效衡量标准。
准确性:它给出模型的总体准确性,即被分类器正确分类的样本占总样本的比例。计算精度,用下面的公式:(TP+TN)/(TP+TN+FP+FN)**。
错误分类率:它告诉你有多少预测是错误的。它也被称为分类错误。可以用(FP+FN)/(TP+TN+FP+FN)或者(1-精度)** 来计算。
Precision: 它告诉你一个正类的预测中有多少部分实际上是正的。要计算精度,用下面的公式: TP/(TP+FP) 。
回忆:它告诉您所有阳性样本中有多少被分类器正确预测为阳性。它也被称为真阳性率(TPR)、灵敏度、检测概率。计算召回率,使用以下公式:【TP/(TP+FN)**。
特异性:它告诉您所有阴性样本中有多少部分被分类器正确预测为阴性。它也被称为真实负利率(TNR)。要计算特异性,用下面的公式:【TN/(TN+FP)**。
F1-score: 它将精确度和召回率结合成一个单一的度量。从数学上来说,这是精确度和召回率的调和平均值。它可以计算如下:
现在,在一个完美的世界里,我们想要一个精度为 1,召回率为 1 的模型。这意味着 F1 分数为 1,即 100%的准确率,这通常不是机器学习模型的情况。因此,我们应该尝试的是获得更高的查准率和更高的查全率。好了,现在我们知道了混淆矩阵的性能度量,让我们看看如何在多类机器学习模型中使用它。
多类分类的混淆矩阵
为了简单起见,让我们考虑我们的多类分类问题是一个 3 类分类问题。比方说,我们有一个数据集,它有三个类标签,即 苹果 、 桔子 和 芒果 。下面是这些类的一个可能的混淆矩阵。
多类分类的混淆矩阵
与二进制分类不同,这里没有正类或负类。起初,找到 TP、TN、FP 和 FN 可能有点困难,因为没有正类或负类,但实际上很容易。这里我们要做的是找到每个类的 TP,TN,FP 和 FN。例如,如果我们取苹果类,那么让我们看看混淆矩阵中的度量值是多少。
- TP = 7
- TN =(2+3+2+1)= 8
- FP = (8+9) = 17
- FN = (1+3) = 4
由于我们从混淆矩阵中获得了苹果类的所有必要度量,现在我们可以计算苹果类的性能度量。例如,苹果公司有
- 精度= 7/(7+17) = 0.29
- 回忆= 7/(7+4) = 0.64
- F1-得分= 0.40
类似地,我们可以计算其他类的度量。下表显示了每个类的每个测量值。
每门课的精确度、召回率和 F1 分数
现在我们可以通过这些措施做更多的事情。我们可以将每个类的 F1 分数结合起来,为整个模型提供一个单一的度量。有几种方法可以做到这一点,现在让我们来看看。
微型 F1
这被称为微观平均 F1 分数。它是通过考虑模型的总 TP、总 FP 和总 FN 来计算的。它不单独考虑每个类,而是全局计算指标。所以在我们的例子中,
- 总 TP = (7+2+1) = 10
- 总 FP =(8+9)+(1+3)+(3+2)= 26
- 总 FN =(1+3)+(8+2)+(9+3)= 26
因此,
- 精度= 10/(10+26) = 0.28
- 回忆= 10/(10+26) = 0.28
现在,我们可以使用 F1 分数的常规公式,并使用上述精度和召回率获得微观 F1 分数。
微 F1 = 0.28
正如您所看到的,当我们计算全局指标时,所有度量都变得相等。如果你计算准确度,你会发现,
精度=召回=微 F1 =准确度
宏 F1
这是 F1 的宏观平均分数。它分别计算每个类别的指标,然后取这些指标的未加权平均值。从图 【精确度、召回率和 F1-每类得分】 中我们看到,
- 类苹果 F1-得分= 0.40
- 级橙 F1-得分= 0.22
- 类芒果 F1-得分= 0.11
因此,
宏 F1 = (0.40+0.22+0.11)/3 = 0.24
加权 F1
最后一个是加权平均 F1 分。与宏 F1 不同,它采用测量值的加权平均值。每个类别的权重是该类别的样本总数。因为我们有 11 个苹果,12 个橘子和 13 个芒果,
加权 F1 =((0.40 * 11)+(0.22 * 12)+(0.11 * 13))/(11+12+13)= 0.24
最后,让我们看一个使用 Python 的 Scikit-learn 计算这些度量的脚本。
下面是脚本的输出。
信用:谷歌 Colab
注意:Scikit-Learn使用行作为“真实类”,使用列作为“预测类”这与我们对苹果、桔子和芒果例子的考虑相反,但在逻辑上是相似的。无论如何,您都可以考虑真实类和预测类。但是如果你使用 Scikit-Learn,那么你必须遵守他们的规则。
希望你找到了你想要的。感谢阅读。
混乱矩阵-不再那么混乱了!
机器学习基础
了解混淆矩阵的所有方面
在本帖中,我们将重点了解混淆矩阵和使用混淆矩阵计算的指标——I 型误差、II 型误差和准确度。这在分类算法的情况下使用,以确定/评估模型的性能。
在构建任何统计或 ML 模型时,我们从开发数据集开始。将数据集分为两部分:训练和测试。将测试数据集放在一边,并使用训练数据集训练模型。一旦模型准备好进行预测,我们就尝试对测试数据集进行预测。一旦我们将结果分割成类似于上图所示的矩阵,我们就可以看到我们的模型能够正确预测多少,以及它的预测有多少是错误的。
我们用测试数据集中的数字填充上图所示的 4 个单元格(例如,有 1000 个观察值)。
- **TP(真阳性)😗*在测试数据集中,该列的实际标签为“是”,而我们的逻辑回归模型也预测为“是”。(500 次观察)
- **TN(真阴性)😗*在测试数据集中,该列的实际标签为“否”,而我们的逻辑回归模型也预测为“否”。(200 项观察)
- **FP(假阳性)😗*在测试数据集中,该列的实际标签为“否”,但我们的逻辑回归模型预测为“是”。(100 项观察)
- **FN(假阴性)😗*在测试数据集中,该列的实际标签为“是”,但我们的逻辑回归模型预测为“否”。(200 项观察)
这 4 个单元格构成了“混淆矩阵”,因为在该矩阵中,通过清楚地描绘出我们模型的预测能力,可以减轻对我们模型的良好性的所有混淆。
混淆矩阵是一个表格,通常用于描述分类模型(或“分类器”)对一组真实值已知的测试数据的性能。
可以理解的与混淆矩阵相关的其他指标
第一类错误
第 1 类错误也称为假阳性,当分类模型错误地预测了最初错误观察的真实结果时就会发生。
例如:假设我们的逻辑模型正在处理垃圾邮件,而不是垃圾邮件。如果我们的模型将一封重要的电子邮件标记为垃圾邮件,那么这就是我们的模型的第一类错误的例子。在这个特定的问题陈述中,我们对尽可能减少 I 类错误非常敏感,因为重要的电子邮件进入垃圾邮件会产生严重的后果。
3.第二类错误
第二类错误也称为假阴性,发生在分类模型错误地预测了原本真实的观察结果的错误结果时。
例如:假设我们的逻辑模型正在处理一个用例,它必须预测一个人是否患有癌症。如果我们的模型将一个患有癌症的人标记为健康人,并将其错误分类,那么这是我们模型的第二类错误的一个例子。在这个特定的问题陈述中,我们对尽可能减少 II 型错误非常敏感,因为在这种情况下,如果疾病在受影响的人中继续未被诊断,假阴性可能导致死亡。
4.准确(性)
现在,上面讨论的三个指标是通用指标,与您拥有的训练和测试数据的种类以及您为问题陈述部署的分类算法的种类无关。
我们现在将讨论非常适合特定类型数据的指标。
让我们从这里开始讨论准确性,这是一个最适合用于平衡数据集的指标。参考下图,该图来源于本媒体文章。
来源:链接
如您所见,一个平衡的数据集是这样的:1 和 0、是和否、正和负由训练数据均等地表示。另一方面,如果两个类别标签的比率是倾斜的,那么我们的模型将偏向一个类别。
假设我们有一个平衡的数据集,让我们学习什么是准确性。
准确度是测量结果与真实值的接近程度。它告诉我们,我们的分类模型能够多准确地预测问题陈述中给出的类别标签。
例如:假设我们的分类模型试图预测客户流失情况。在上图中,在总共 700 个实际流失客户(TP+FN)中,模型能够正确地对 500 个流失客户进行分类(TP)。同样,在总共 300 个保留客户(FP+TN)中,该模型能够正确地对 200 个保留客户(TN)进行分类。
准确率=(TP+TN)/客户总数
在上面的场景中,我们看到模型在 1000 个客户的测试数据集上的准确率是 70%。
现在,我们知道了准确性是一个应该只用于平衡数据集的指标。为什么会这样呢?让我们看一个例子来理解这一点。
在这个例子中,这个模型是在不平衡的数据集上训练的,甚至测试数据集也是不平衡的。准确性指标的得分为 72%,这可能给我们的印象是我们的模型在分类方面做得很好。但是,仔细看,这个模型在预测负面的阶级标签方面做得很糟糕。它只预测了 100 个总阴性标签观察中的 20 个正确结果。这就是为什么如果数据集不平衡,就不应该使用精度指标。
这篇文章的重点是全面理解困惑矩阵。
如果您想了解更多有关可用于评估分类模型的其他指标,如召回率、精确度、AUC-ROC 等。,您可以参考我下面关于这个主题的详尽文章。
解释非常规,这将作为评估分类机器学习模型的详尽列表。
towardsdatascience.com](/top-10-model-evaluation-metrics-for-classification-ml-models-a0a0f1d51b9)
请继续关注这个空间,了解更多关于数据科学、机器学习和统计的信息!
快乐学习:)
混淆矩阵“未混淆”
打破混乱矩阵
工业中应用机器学习的目标是驱动商业价值。因此,能够评估您的机器学习算法的性能对于深入了解您的模型极其重要。
在这篇文章中,我的目标是以一种对那些积极使用它们的人和那些只是好奇的人来说容易理解的方式深入到困惑矩阵中。也就是说,本文的结构如下:
- 什么是混淆矩阵
- 如何解读混淆矩阵
- 案例研究(准确度、召回率、精确度和 F 值)
混淆矩阵是什么?
混淆矩阵是用于机器学习中分类任务的有用工具,其主要目的是可视化机器学习模型的性能。
在负类为 0、正类为 1 的二元分类设置中,混淆矩阵由一个 2x2 网格表构成,其中行是数据的实际输出,列是模型的预测值。
图 1:混淆矩阵的可视化表示(没有注释)
我将解释为什么某些网格是一种颜色,而其他的却是另一种颜色,现在,这只是混淆矩阵是什么以及它对于二进制分类任务看起来会是什么样子的视觉表示。
注意:许多来源以不同的方式构建混淆矩阵,例如,行可能是预测值,列可能是实际值。如果您正在使用框架(即 Sci-kit learn ),阅读混淆矩阵的文档以了解混淆矩阵的格式是很重要的。
无论您在图 1 中停留在哪个网格块上,其相邻的网格都会以另一种颜色高亮显示。这考虑到了混乱矩阵的不同变化,如果您简单地旋转网格,您可能会看到这些变化。
图 2:混淆矩阵的变化
很好!既然你已经熟悉了二元分类任务的混淆矩阵的格式,现在知道如何填写混淆矩阵是很重要的。
让我们用经典的猫和狗的例子。如果我们的分类任务已经被训练来区分猫和狗,混淆矩阵将为预测模型创建结果摘要以供进一步分析。
图 3:取自 Badgerati 的混淆矩阵结果
在图 3 中的 50 只猫中,模型预测实际上有 15 只猫,35 只狗。关于狗,模型预测 40 只为猫,10 只为狗。所有正确的预测都被分配在表格的对角线上(从上到下)——是的,你猜对了!这就是为什么这些盒子被涂上了与图 1 中一样的颜色。
你现在已经学会了如何绘制你自己的困惑矩阵。作为数据科学家,我们想知道为什么模型做得不好,以便我们更好地了解我们的数据,我们可以使用这些数据为下一个建模阶段设计新功能。
如何解读困惑矩阵
我将首先描述一些术语,如果你能猜出它们的走向,那么你就成功了一半:
**真阳性:**模型预测阳性,标签实际阳性。
**真阴性:**模型预测为阴性,标签实际为阴性。
**假阳性:**模型预测为阳性,而标签实际上是阴性——我喜欢把这想象成 被错误地归类为阳性 。
**假阴性:**模型预测为阴性,而标签实际上是阳性——我喜欢把这想象成 被错误地归类为阴性 。
图 4:带注释的混淆矩阵
如果你能够将这些标签归类到这些列中,那就太棒了,你现在已经全面掌握了混淆矩阵。让我们进一步挖掘!
我们的混淆矩阵在我们的网格上有两个红色补丁,这向我们推断出我们的模型正在犯的错误的类型。第一类错误是当我们的模型错误地将实际上是阴性的东西分类为阳性(假阳性)——因此它可以被认为是一个错误的警报——例如预测某人患有哮喘,而他们实际上没有。第二类错误是当我们错误地将实际上是阳性的东西归类为阴性(假阴性)——在我们的哮喘病例中,这将是说某人没有哮喘,而实际上他们有。
我知道这些文字会让你很难理解,所以如果你觉得它还没有被很好地接受,回到图 4 来获得一个视觉概念。
您现在已经了解了混淆矩阵是一种用于评估预测模型在分类任务中的性能的工具。此外,您还知道与我们的预测模型的每个输出相关的术语。
案例研究:
我们的任务是建立一个分类器,预测不同交易的欺诈或非欺诈。这些数据是由英国一家安全措施非常严格的大银行交给我们的——出于隐私考虑,所有客户的个人信息都被加密了——因此欺诈交易不会经常发生。事实上,他们给我们的数据有 10,000 个负面案例(非欺诈)和 1000 个(欺诈)案例。图 5 显示了我们分类器的结果。
图 5:用例模型的结果
准确度
准确度是指测量值与标准值或已知值的接近程度。在我们建立了一个分类器并使用它进行预测之后,我们很快地调出我们的混淆矩阵来确定我们的模型有多准确,我们惊讶地发现我们的模型有 92%的准确性。当我们开始梦想我们将从中获得的奖金时,有什么东西拉了拉我们的数据科学骨骼并告诉我们更多地查看我们的模型预测,因为我们不知道为什么我们的模型如此准确,因为当我们的目标变量(在这种情况下,欺诈或非欺诈)不平衡时,准确性可能是一个误导性的指标。我们再次回顾了混淆矩阵(参见图 5) ,以获得更多的指标来告诉我们为什么我们的模型如此准确。
图 6:精确度公式
精度和召回
精度(也称为阳性预测值)告诉我们,从我们的分类器标记为阳性的标签,实际上是阳性的量。
图 7:精度公式
另一方面,回忆(也称为敏感度或真实阳性率)告诉我们我们的模型正确识别的实际阳性的数量。
图 8:召回公式
注:精确度和召回率基于对阳性标签(相关性)的理解和测量。
我们计算刚刚学过的精确和回忆公式:
精度 = 83%
是啊!!这太棒了,这意味着 83%被我们标记为阳性的标签实际上是阳性的。这是惊人的…是吗?让我们检查一下召回情况。
回忆 = 24%
这告诉我们,我们的分类器正确识别的阳性标签的数量。换句话说,欺诈在 76%的时间里都没有被发现!不需要博士学位就知道这一点也不好。
对于这个问题,我们希望优化召回,这意味着我们希望通过在更多情况下预测阳性来减少假阴性的数量(当实际标签是阳性时错误地分类为阴性)。然而,有些时候你可能想优化精确度,例如在垃圾邮件分类器中,我们不希望重要的邮件被归类为垃圾邮件并发送到我们的垃圾邮件中。就我们的欺诈分类器而言,我们希望优化召回率,为了做到这一点,我们必须降低分类器的阈值,以将其分类为肯定类别。请注意,由于我们的分类器现在预测阳性更多,它降低了(我们曾经很高的)83%的精度,因为现在我们的模型预测假阳性发出更多假警报的可能性更高,但在这种情况下我们不介意。
精确和回忆爱恨关系
精确度和召回率很少被孤立地讨论,正如我们在上面发现的,它们之间经常有一种反比关系——增加一个度量就会减少另一个。当我们需要在精确度和召回率之间取得平衡时,一个更好的度量标准是 F1 值(也称为 F 值)。F1-score 是一种考虑精确度和召回率的精确度衡量标准(下面的公式将向您展示它是如何做到这一点的)。
图 9:F1 分数的公式
总之,从我们的混淆矩阵中可以得出更多的度量。对混淆矩阵中的术语有一个牢固的理解,这是继续理解可以推导出的其他度量的坚实基础。如果你想继续, Sarang Narkhede 在他的个人资料上有一个关于困惑矩阵的惊人帖子(点击这里导航到那里)。 Koo Ping Shung 更详细地介绍了何时使用准确度、精确度、回忆和 F1 分数,并且以友好的方式撰写,因此任何人都可以理解(单击此处获取链接)。我们还有著名的维基百科,你可以点击这里进入。我在下面附上了一个帖子,它扩展了混淆矩阵,我们用它来绘制 ROC 曲线,如果你不知道那是什么,或者你知道但不太理解它,那么点击下面的链接可以很好地掌握它。
深入了解 AUC-ROC…
towardsdatascience.com](/comprehension-of-the-auc-roc-curve-e876191280f9)
国会如何投票?
Unsplash 的 Darren Halstead
使用机器学习来预测国会投票
使用国会投票记录,我们将尝试预测国会议员对某些国会问题的投票,并可视化投票。
数据
数据集可以在 Kaggle 这里找到。
这些栏目是:“班级名称”、“残疾人-婴儿”、“水项目-费用分摊”、“通过预算-决议”、“医生-费用-冻结”、“萨尔瓦多-援助”、“宗教团体-学校”、“反卫星-禁试”、“援助-尼加拉瓜-contras “、” MX-导弹”、“移民”、“合成燃料-公司-削减”、“教育-支出”、“超级基金-起诉权”、“犯罪”、“免税-出口”、“出口-管理-法案-南非”。
第一栏“班级名称”不是“共和党”就是“民主党”。其他几栏代表国会的决定,或者是‘n’代表‘不’,或者是‘y’代表‘是’,或者是“?”缺少值。
清理数据
为了将数据传递到机器学习模型中,所有数据都必须是数字。用 Python 的。map()函数,我们可以将数据转换成数值形式。
当前数据为 435 行 17 列。理想情况下,我们会删除所有 NaN 值以保持最高的数据质量,而不必猜测丢失的值是什么。但是,在删除所有具有 NaN 值的行之后,得到的数据是 232 行乘 17 列,大约减少了一半。
相反,我们将选择估算,或计算每个 NaN 值的最可能值。一些估算方法包括众数、中位数和平均数,但在这种情况下,没有一种方法有效,因为我们无法根据最流行或最平均的观点来确定政治家在某个问题上的立场。
KNN 估算
相反,我们将使用 K-最近邻(KNN)来计算缺失值。
KNN 是如何工作的?
首先,所有的数据点都绘制在多维空间中,这取决于数据有多少个特征(列)。我们的数据有 16 个维度,因为每个国会成员投票表决了 16 个不同的国会决定。
其次,KNN 计算了 k 个最近的数据点(使用欧几里德距离)。需要指定 k 的值。然后,数据点是 k 邻居值的平均值(或模式,如果指定的话)。
应用 KNN 估算后,数据如下所示:
在 65–35 训练测试分割上训练逻辑回归模型后,该模型的平均绝对误差(MAE)值约为 0.006。
在尝试了所有的k-值之后,MAE 似乎没有什么变化:
因此,我们现在将坚持使用值为 5 的 k- 。
系数分析
逻辑回归模型的系数可用于分析:
具有正系数的要素增加了选民是共和党人的概率,具有负系数的要素减去了选民是共和党人的概率(增加了选民是民主党人的概率)。这些系数如下所示:
下面是一个 SHAP (SHapley 附加解释)图,它分析了特征对于确定分类的重要性。这形象化了党派间最大的分歧——也就是说,立法机关冻结了医生医疗保险费用,削减了合成燃料公司。底部的功能,如向萨尔瓦多提供援助或反卫星测试禁令,是有争议的,这意味着许多共和党人和民主党人都投了赞成票和反对票,无法根据支持度合理预测政党。
排列重要性是评估特征重要性的另一种方法。通过打乱每一列并观察随之而来的准确性下降,排列重要性可以看出哪些列对准确性最重要。绿色的列是那些更多地被党派界线划分的列,红色的列是更多的混合。
SHAP 价值观也可以用其他方式来形象化。
这张 SHAP 力量图显示了哪些因素增加或减少了选民是共和党人的可能性。不支持冻结医生费用或批准采用预算决议等因素增加了可能性,而缺乏对水项目成本的支持则降低了可能性。这个力图是根据一个单独的案例绘制的。
结论
- 医生医疗费用冻结几乎完全是由政党路线投票决定的。
- 不支持免费医疗保险是共和党的一个非常重要的特征。
- 对尼加拉瓜反政府组织和萨尔瓦多的援助是最有争议的,这意味着共和党人和民主党人都投票赞成和反对一项提议。
共轭先验解释
有例子和证据
1.什么是先验?
先验概率是在我们看到数据之前某个事件的概率**。
在贝叶斯推断中,先验是我们在新数据可用之前,基于我们现在所知的对概率的猜测。**
2.什么是共轭先验?
不知道贝叶斯推理就无法理解共轭先验。
贝叶斯推理的艺术在于你如何实现它…](https://medium.com/@aerinykim/bayesian-inference-intuition-and-example-148fd8fb95d6)
对于博客的其余部分,我假设你知道先验、抽样和后验的概念。**
本质上共轭先验
****对于一些似然函数,如果选择某个先验,后验最终与先验处于相同的分布。这样的先验称为共轭先验。
通过例子来理解总是最好的。下面是计算二项式概率的后验概率的代码。θ** 是成功的概率,我们的目标是选择最大化后验概率的 θ。**
问你一个问题:在上面的代码块中有什么让你担心的吗?
有两件事使得后验计算很昂贵。
首先,我们计算每个θ 的后验概率。
为什么我们要计算成千上万个 thetas 的后验概率?因为你正在使后部正常化(第 21 行)。即使选择不归一化后验概率,最终目标也是找到后验概率的最大值**(最大后验概率)。为了以简单的方式找到最大值,我们需要考虑每个候选者——对于每个 θ的可能性 P(X|θ) 。**
第二,如果没有后验分布的闭合形式公式,我们就得通过数值优化来求最大值,比如 梯度下降 或者牛顿法。
3.共轭先验有什么帮助?
当你知道你的先验是共轭先验时,你可以跳过posterior = likelihood * prior
的计算。此外,如果你的先验分布有一个封闭形式的表达式,你已经知道最大后验概率是多少。
在上面的例子中,贝塔分布在二项式可能性之前是共轭的。这是什么意思?这意味着在建模阶段,我们已经知道后验也将是贝塔分布。因此,在进行更多的实验后,你可以简单地将接受和拒绝的次数分别加到现有的参数α,β上来计算后验概率,而不是将似然性乘以先验分布。这个很方便!(下一节证明。)
作为一名数据/ML 科学家,你的模型永远不会完整。随着更多数据的到来,你必须更新你的模型(这就是为什么我们使用贝叶斯推理)。如你所见,贝叶斯推理中的计算可能很繁重,有时甚至难以处理。然而,如果我们可以使用共轭先验的封闭形式公式,计算变得非常轻。
4.证明——为什么贝塔分布是二项式可能性之前的共轭分布?
当我们使用贝塔分布作为先验时,二项似然的后验也将遵循贝塔分布。
显示贝塔产生贝塔。
二项式和 Beta 的 pdf 是什么样子的?
让我们把它们代入著名的贝叶斯公式。
θ 是成功的概率。
x 是成功次数。
n 是试验的总次数,因此 n-x 是失败的次数。
为什么最后一个积分变成 B(x+α,n-x+β) ?→https://bit.ly/2t1i2KT
先验分布 P(θ) 为β(α,β)** ,从实验中得到 x 个成功和 n-x 个失败后,后验也变成参数为 (x+α,n-x+β)的β分布。**
这里的好处是,你不用做计算,就可以通过分析知道这个。
5.共轭先验分布
贝塔分布是伯努利分布、二项式分布、负二项式分布和几何分布的共轭先验分布(看起来这些分布涉及成功&失败)。
**<Beta posterior>**
Beta prior * **Bernoulli** likelihood → Beta posterior
Beta prior * **Binomial** likelihood → Beta posterior
Beta prior * **Negative Binomial** likelihood → Beta posterior
Beta prior * **Geometric** likelihood → Beta posterior **<Gamma posterior>**
Gamma prior * **Poisson** likelihood → Gamma posterior
Gamma prior * **Exponential** likelihood → Gamma posterior**<Normal posterior>**
Normal prior * Normal likelihood (mean) → Normal posterior
这就是为什么这三种分布(β、γ和正态**)被大量用作先验分布的原因。**
一种有趣的说法是,即使你做了所有这些实验,并将你的可能性乘以先验,你最初选择的先验分布如此之好,以至于最终分布与先验分布相同。
等式中的共轭先验 P(θ) :
**P(θ) such that P(θ|D) = P(θ)**
共轭先验=方便先验
需要注意一些事情:
- 当我们使用共轭先验时,顺序估计(每次观察后更新计数)给出的结果与批量估计相同。
- 为了找到最大后验**、,你不必归一化似然(抽样)和先验(分母中每个可能的 θ 的积分)的乘积。**
不用归一化还是能找到最大值。然而,如果你想比较不同模型的后验概率,或者计算点估计,你需要归一化。
将 BigQuery 连接到 Google Sheets
在这篇谷歌博客文章之后。
由 Linus Mimietz 在 Unsplash 上拍摄的照片
你为什么会这样做?为什么不是 SQL 数据库?
我的一个朋友是一家非营利机构的总裁,这家机构(谢天谢地)正经历着成长的烦恼。一群 20 岁出头的电气和机械工程师策划了一项为乌干达的学校安装太阳能电池板的计划,辛勤的工作和慷慨的捐赠推动了更大计划的成功。但是,可惜的是,他们的数据以 Google Sheets 的形式分散在不同的驱动帐户中,以当前的数据状态理解他们的影响或可视化他们的未来是不可能的。我很幸运地通过我的朋友加入了这个组织,他抱怨说他们的数据收集很糟糕,他们试图将所有的信息收集到一个数据库中。作为一名正在攻读公共政策硕士学位的学术数据科学家,我无法相信他们有如此宝贵的数据,如乌干达农村学校安装太阳能电池板前后的学生健康和教育的学校级数据,并请求伸出援手。
在一间公寓的会议室里,一边吃着甜甜圈和喝着咖啡,我亲眼目睹了可以想象的最不整洁的数据集。生产和太阳能电池板零件表在一个人的驱动中,学校调查和安装程序在另一个人的驱动中。他们甚至不知道所有的数据在哪里。
第一步是在一个地方收集所有的数据。我们同意在两周内会面,将所有数据放在一个地方,我来处理云集成。他们想要的非常简单:使用 SQL 语法查询多个工作表。我做了一个巧妙的演示,展示了一个 dash 网站的原型,该网站使用 SQL 数据库来生成报告,但是当我问“数据将如何更新?”时,这个演示就消失了他们回答说,“我们将复制并粘贴到谷歌的工作表中。”我立即意识到,我是房间里唯一一个具有 SQL 或云工程知识的人,但这不是一个优势,而是非营利组织的一个负债,因为它不能因为我的缺席或退出而失去对数据库的访问权。
BigQuery 太神奇了
由于数据库将通过 Google Sheets 随机访问和更新,我决定推迟我最初为这个数据库项目准备的 Airflow + SQL + Flask 应用程序。由于预算限制和组织不愿意建立一个复杂的云流程,我需要在谷歌上建立一些便宜又简单的东西。BigQuery 和 Data Studio 立刻跃入我的眼帘。
在下一次会议之前,我想有一个 BigQuery 可以为他们的组织做什么的原型,并决定使用联合国人类发展报告——次国家指数来建立一个模拟数据库。
创建项目
在 Google 云平台中,创建一个新项目。我选择了“HDR-SubnatIndex”作为我的项目名称。
创建新项目。
启用 API
接下来,为您的新项目启用 Sheets API。请注意,我在顶部的项目是 HDR-SubnatIndex。
启用工作表 api。
创建数据集
导航到 BigQuery 控制台并选择创建数据集。
为数据集命名,并配置到期和加密。单击创建数据集。
创建表格
找到您想要连接到 BigQuery 的工作表,并复制它的可共享链接。
在左下角的项目下选择新的数据集,然后选择 CREATE TABLE。
选择 Create table from: Drive,将整个工作表 URI 粘贴到 Select Drive URI 中,选择 CSV(我注意到选择 Google 工作表时出现了一些问题,它无法识别列名),输入表名,在这种情况下,我们可以自动检测模式和参数。
运行测试查询
BigQuery 的美妙之处在于它能够对任何东西执行 SQL 查询。若要确保正确允许与工作表的连接,请运行测试查询。这里我选择了数据集的前 10 行。
现在让我们运行一个稍微高级一点的查询,只提取乌干达的地区、年份、健康指数、收入指数和教育指数的国家以下级别的数据。
但是这些信息都可以很容易地从应用于 Google Sheets 的过滤器中收集到,对吗?这种方法的好处是,您现在有了一个可以随时保存和运行的查询,而不必复制数据集和重新创建筛选步骤。然而,BigQuery 真正突出的地方在于它在多个表之间执行连接的能力。
SQL 连接
我按照上面相同的步骤,从我的 google drive 中的 google sheet 添加了第二个 BigQuery 表,其中包含来自世界银行的 GDP 数据。如果没有 BigQuery 和 SQL JOINS 的帮助,使用 Google Sheets 组合这两个数据集并链接它们会困难得多。在这里,我查询了这两个表,以创建每个国家的年度国家人类发展指数和 GDP 的报告。
在分析多维贫困时,这是一个重要的比较,因为国内生产总值(GDP)并不能说明全部情况。《联合国人类发展报告》建立了人类发展指数,将健康、教育、预期寿命、平均受教育年限、预期受教育年限和人口等变量考虑在内,从而对特定国家的需求或所经历的贫困类型有了更加动态的了解。
结论
BigQuery 数据集本质上是表之上的抽象,它允许您对动态表中的多个数据源运行 SQL 查询。现在您有了一个查询,您可以在需要时保存并运行它,或者通过单击 Explore Data 导出到 Data Studio。此外,从 Data Studio 中,您可以创建一个报告,并在您的 BigQuery 数据集上使用相同的查询作为报告的数据源。
奖励:BI 引擎
现在您已经看到了 BigQuery 从 google sheets 收集数据和标准化报告的强大功能,让我们试着加快查询速度,好吗?Google BI Engine 本质上是为一个项目购买加速计算资源。
在 BigQuery 控制台的左侧,选择 BI 引擎。如果需要,启用它。选择创建预订。选择资源将位于的区域。我们的小查询将使用不到 1 GB 的存储空间。
现在,您将看到您的新 BI 引擎列在 BI 引擎下。运行相同的查询后,我们只看到时间减少了 2.3 秒。但是 BI Engine 真正的亮点是在 Google Data Studio 中,当你玩图表来寻找可视化分析的最佳方式时,它的更新速度明显更快。
感谢您的阅读!
使用环境变量隐藏您的密钥
Python | 编程 | 办公时间
关于如何在使用 Python 连接到数据库时使用环境变量保护密码的教程
我向我的读者强烈推荐的课程:
- Python 中的命令行自动化(data camp)→学习自动化许多常见的文件系统任务,并能够管理和与进程通信。
介绍
假设您正在进行一个数据科学项目,您决定通过使用 Python 建立连接来从公司数据库中提取数据。如果有必要通过 GitHub 分享你的脚本,让更广泛的团队审阅,那该怎么办?那么,在这种情况下,为了避免其他人滥用,你最好隐藏你的秘密细节。
在本文中,我将展示如何通过命令行使用环境变量来保证用户名、密码和数据库名的安全,避免不必要的信息泄露。
[## 使用 Python 将 Google 电子表格写入数据库
在本教程中,学习如何用几行代码构建简单的 ETL 来跨系统移动数据。
towardsdatascience.com](/write-datasets-from-g-sheet-to-your-database-with-python-bd2c2643f958)
环境变量解释
环境变量是 KEY=value 对,类似于 Shell 变量,可以通过命令行*、*创建,但功能更强大,因为一旦声明,它们就可以被任何编程语言使用,因为它们与您的环境/操作系统相关联。
在命令行环境中:
- 变量键必须用 大写字母 书写,并且可以是字符、数字和下划线的混合。
- 另一方面,任何值数据类型都可以赋给它们,在 Bash 中使用字符串时引号是可选的,除非字符串包含空格。这是因为 Bash 对空格很敏感,所以包含空格的字符串除非用引号括起来,否则无法正常工作。
- 最后,在“*=”*符号前后不能留有空格,如下所示:
**MY_VARIABLE=”my_value”** --> works(capital, no space, quotes)**MY_VARIABLE=my_value** --> works(capital, no space, no quotes but underscore)**MY_VARIABLE=my value** --> fails(capital, no space, space in value)**MY_VARIABLE = ”my_value”** --> fails(capital, space between equal sign, quotes)
在这篇简短的教程中,我将展示如何在 Python 中计算加权平均值,要么定义自己的函数,要么使用…
towardsdatascience.com](/3-ways-to-compute-a-weighted-average-in-python-4e066de7a719)
配置环境变量
在使用 Mac OS 时永久声明环境变量的一个简单方法是将它添加到中。bash_profile 是在您的主目录中定义的一个隐藏文件,用于在您的系统中配置 Bash Shell。要访问该文件,首先运行您的终端,使用 cd ~ 导航到主目录,然后在打开的情况下打开文件编辑器。bash_profile 命令:
$ cd ~$ open .bash_profile
在文件编辑器中,为您想要隐藏的秘密信息键入 KEY=value 对,前面是 export 命令,表明您希望这些变量在 shell 之外也可用:
export USERNAME=”Insert Your User Name”
export DBPW=”Insert Your PW"
export DBNAME=”Insert Your DB Name"
添加完所有变量后,保存文本文件并用源刷新 bash 概要文件。bash_profile 命令:
$ source .bash_profile
如果您忽略运行上面的命令,您将无法立即看到刚刚创建的环境变量,您需要退出并重新登录命令行。
现在,在尝试数据库连接之前,让我们通过在命令行中打开交互式 Python 控制台并导入 os 模块 来确保变量确实可以在 Python 中使用。其中,os 模块使 Python 能够使用您的操作系统环境变量。您可以使用 os.environ 列出它们,这是一个返回 Python 字典的方法,该字典包含系统中当前可用的所有变量,或者选择每个键,如下所示:
**$ ipython****In [1]: import os****In [2]: os.environ['USERNAME']****Out[2]: 'Insert Your User Name'****In [3]: os.environ['DBPW']****Out[3]: 'Insert Your PW'****In [4]: os.environ['DBNAME']****Out[4]: 'Insert Your DB Name'**
太棒了。似乎您现在可以在数据库连接设置中用环境变量键替换秘密信息字符串。如果你像我一样使用psycopg2.connect()
和pd.read_sql()
方法和来连接红移,你会得到这样的结果:
结论
在本教程中,我尝试解决了一个我最近几次遇到的实际问题:在处理共享 Python 脚本时隐藏密钥,我希望你会发现环境变量对你的工作流和对我一样有用。请注意,这只是一个介绍性的指南,还有很多关于环境变量的内容需要学习。例如,我发现一门特别有启发性的课程是由 DataCamp 教授的 Python 中的命令行自动化。
免责声明:这个帖子包括附属链接,如果你购买的话,我可以免费给你一点佣金。
你可能也喜欢:
[## 在你开始第一个项目之前,要掌握 15 个 Git 命令
您需要掌握的最后一个 Git 教程是命令行版本控制。
towardsdatascience.com](/15-git-commands-you-should-learn-before-your-very-first-project-f8eebb8dc6e9) [## Python 编码面试前要解决的 10 个算法
在这篇文章中,我介绍并分享了 FAANG 中经常出现的一些基本算法的解决方案
towardsdatascience.com](/10-algorithms-to-solve-before-your-python-coding-interview-feb74fb9bc27) [## 5 套算法解决之前,你的 Python 编码屏幕
你对 Python 中的集合了解多少?用这些“简单”和“中等”的 LeetCode 问题挑战自己。
medium.com](https://medium.com/analytics-vidhya/5-pythons-sets-problems-to-solve-before-your-coding-interview-41bb1d14ac25)
从本地机器连接到 Docker 容器中运行的 MySQL
在 Docker 容器中部署带有持久存储的 MySQL 数据库并连接 Docker 化的 MySQL 数据库的分步指南
来自皮萨贝的帕帕萨恰里亚斯
如果你在软件工程行业工作,或者如果你打算在软件工程领域工作,你可能听说过码头工人。
2013 年, Docker 引入容器概念,永远改变了软件工程版图。
容器是一个标准化的软件单元,它允许开发者将他们的应用从环境中分离出来,解决了“它在我的机器上工作”的头痛问题。码头工人仍然是集装箱化的“事实上的”标准。
Docker 的另一个重要用途是,开发人员可以下载并运行任何容器化的应用程序,而无需直接将其安装在本地机器上。由于几乎所有必需的应用程序都有 Docker 版本,Docker 有助于尝试和运行应用程序,同时保持您的操作系统简洁明了。
MySQL 是最流行的开源数据库之一,也是“四大”关系数据库之一。它被工业界、学术界和社区广泛使用。在一篇博文中,我对业界十大数据库做了详细的分析和排名,MySQL 拔得头筹。如果您想进一步了解 MySQL 为什么是第一大数据库,包括它的主要特性、使用案例、托管 MySQL 服务和替代方案,您可以阅读我的文章:
MySQL,Oracle,PostgreSQL,微软 SQL Server,MongoDB,Redis,Elasticsearch,Cassandra,MariaDB,IBM Db2
towardsdatascience.com](/top-10-databases-to-use-in-2021-d7e6a85402ba)
在这里,我将展示如何运行一个 Dockerized MySQL 数据库,然后从您的本地机器连接它。
安装 Docker
你可以在几乎所有的主要操作系统中安装 Docker,无论是 Linux、Windows 还是 macOS。请按照 docker 官方网站上的说明在你的本地机器上安装 Docker:https://docs.docker.com/engine/install/
安装并启动 Dockerized MySQL
Docker 容器是无状态的。所以,如果你使用一个容器化的 MySQL,那么一旦重启容器,你将会丢失所有保存的数据。避免这个问题的一个方法是创建一个 docker 卷,并将其附加到 MySQL 容器中。以下是在本地机器上创建一个包含附加卷的 MySQL 容器的命令:
以下命令将在您的本地计算机上创建卷,您可以稍后用 MySQL 容器连接该卷:
*λ* **docker volume create mysql-volume**
mysql-volume
以下命令将从 Docker 注册表中提取 MySQL server 8 . 0 . 20 版,然后实例化一个名为“mk-mysql”的 Docker 容器。它还会将之前创建的卷“mysql-volume”与数据库连接起来,并公开端口 3306,以便您可以访问容器外部的 mysql 数据库:
*λ* **docker run --name=mk-mysql -p3306:3306 -v mysql-volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql/mysql-server:8.0.20**
Unable to find image ‘mysql/mysql-server:8.0.20’ locally
8.0.20: Pulling from mysql/mysql-server
您可以通过列出正在运行的容器来检查容器是否正在运行:
*λ* **docker ps**
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d54e7992094b mysql/mysql-server:8.0.20 "/entrypoint.sh mysq…" Less than a second ago Up 4 seconds (health: starting) 0.0.0.0:3306->3306/tcp, 33060/tcp mk-mysql
您还可以使用以下命令检查正在运行的 MySQL 容器的日志文件:
*λ* **docker logs mk-mysql**
现在,您可以使用以下命令连接到容器的交互式 bash shell:
*λ* **docker exec -it mk-mysql bash**
bash-4.2#
一旦进入容器,就可以连接到 MySQL 服务器并创建一个新的数据库,如下所示:
bash-4.2# mysql -u root -p
Enter password:
...mysql> CREATE DATABASE MYSQLTEST;
Query OK, 1 row affected (0.00 sec)
请注意,您必须给出与我们定义的相同的密码来运行容器( my-secret-pw )。
默认情况下,出于安全原因,MySQL 限制除本地机器(这里是 Docker 容器)之外的连接。因此,要从本地机器连接,您必须更改连接限制:
mysql> update mysql.user set host = ‘%’ where user=’root’;
Query OK, 1 row affected (0.02 sec)
尽管出于安全原因,最好创建一个新的非管理员用户,并只授予该用户访问权限。
安装 Dockerized phpMyAdmin
您可以使用任何 MySQL 客户端程序来连接 MySQL 服务器。我个人最喜欢的是 phpMyAdmin,这是一个简单而强大的 Web MySQL 客户端。此外,与其在我的机器上安装 phpMyAdmin,我更喜欢使用 Dockerized phpMyAdmin。
您可以从 docker 注册表中提取 phpMyAdmin 映像,并使用以下命令运行容器:
**λ docker volume create phpmyadmin-volume**
phpmyadmin-volume
**λ docker run --name mk-phpmyadmin -v phpmyadmin-volume:/etc/phpmyadmin/config.user.inc.php --link mk-mysql:db -p 82:80 -d phpmyadmin/phpmyadmin**
ef21905790dc42bc2e20d449b853d675d4922cb1249131513fdee885fc1088f8
您可以通过列出所有正在运行的容器或检查日志文件来检查 phpMyAdmin 是否正在运行:
λ **docker ps -f "name=mk-phpmyadmin"**
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef21905790dc phpmyadmin/phpmyadmin "/docker-entrypoint.…" Less than a second ago Up 10 minutes 0.0.0.0:82->80/tcp mk-phpmyadmin**λ docker logs mk-phpmyadmin**
Mac/Windows 的注意事项:
基于你的操作系统,你的 DOCKER_HOST 是不同的。在 Linux 上,它将是您的本地主机。对于 Mac/Windows,您可以使用以下命令获取 DOCKER_HOST:
λ **docker-machine ip default**
对于 Windows/Mac,您可以连接 DOCKER_HOST IP 地址。另一个选项是端口转发。在 Windows 中,Docker 机器是在主机中的 VirtualBox 下运行的虚拟机。
要为 MySQL 和 phpMyAdmin 启用端口转发,请执行以下步骤:
- 打开“Oracle 虚拟机虚拟箱”
- 选择您的 Docker 机器 VirtualBox 映像(例如,默认)
- 打开设置->网络->高级->端口转发
- 添加应用程序名称、所需的主机端口和来宾端口,如下所示:
通过 phpMyAdmin 访问 MySQL
打开浏览器,访问http://localhost:82进入 phpMyAdmin UI:
一旦您使用之前配置的密码(my-secret-pw)登录,您应该能够查看 phpMyAdmin 管理视图,如下所示:
在左侧面板中,您可以看到之前创建的数据库(MYSQLTEST)。现在,您应该能够管理您的数据库(创建/删除表,运行 SQL 查询,等等。).
如果您已经如上所述配置了 Docker 卷,那么即使您重新启动 MySQL 容器,您的数据库更改也将保持不变。否则,您在数据库中所做的所有更改都将丢失。
类似文章:
MySQL,Oracle,PostgreSQL,微软 SQL Server,MongoDB,Redis,Elasticsearch,Cassandra,MariaDB,IBM Db2
towardsdatascience.com](/top-10-databases-to-use-in-2021-d7e6a85402ba) [## 2021 年使用的 5 个最佳公共云数据库
亚马逊 DynamoDB,谷歌 BigQuery,Azure SQL Server,Azure Cosmos DB,亚马逊红移
towardsdatascience.com](/5-best-public-cloud-database-to-use-in-2021-5fca5780f4ef) [## 有效的微服务:10 个最佳实践
正确实施微服务架构的 10 个技巧
towardsdatascience.com](/effective-microservices-10-best-practices-c6e4ba0c6ee2)
使用 psycopg2 的 Python 模块连接到 PostgreSQL 数据库服务器
Jan Antonin Kolar 在 Unsplash 上拍摄的照片
动手教程
开发一个整洁的脚本和目录来本地或远程连接到 PostgreSQL
目录(仅适用于 web)
1 [What’s it all about?](#6107)
2 [The psycopg module to connect a PostgreSQL](#64a2)
3 [How to connect with PostgreSQL](#2ac2)
4 [Create, Read, Update, and Delete (CRUD) using psycopg2](#23f6)
• [Create a table](#e1a3)
• [Insert data to a table](#be50)
• [Retrieve a table](#b149)
• [Update a table](#5d20)
• [Delete rows or a table](#fd24)
5 [Conclusion](#194d)
6 [References](#0c68)
这是怎么回事?
ostgreSQL 是一个关系数据库管理系统,它是开源的,也有很多功能。在 Python 中,我们有几个模块可以连接到 PostgreSQL,比如**SQLAlchemy**
、**pg8000**
、**py-postgresql**
等。然而,**psycopg2**
成为最受欢迎的一个。所以在本教程中,我们将讨论如何使用**psycopg2**
连接到 PostgreSQL。
连接 PostgreSQL 的 psycopg 模块
**psycopg2**
是 Python 开发人员通常用来连接 Python 的 PostgreSQL 连接器。它是本教程的核心模块,所以请确保我们已经在机器上安装了它。在终端上使用以下命令安装**psycopg2**
模块。
**$**pip3 install psycopg2
如何连接 PostgreSQL
要连接到 PostgreSQL,我们必须在 PostgreSQL 上创建一个代表我们的数据库的文件。我们将把数据库配置文件保存到**<filename>.ini**
。 如果我们与公众分享我们的主要 Python 脚本 ,它会保证我们数据库配置的安全。在这种情况下,我们将它命名为**database.ini**
。请输入您的数据库配置,如主机名,数据库名,用户名,密码,端口号等至**database.ini**
如下。
[postgresql]
host = localhost
database = customer
user = postgres
password = admindb
port = 5432
关于数据库配置的信息。
**host**
—是运行 PostgreSQL 的服务器名称或 IP 地址**database**
—是我们要连接的数据库名称**user**
—是 PostgreSQL 的用户名称**password**
—是连接 PostgreSQL 所需的密钥**port**
—监听 TCP/IP 连接时将使用的端口号。默认端口号是 5432
为了解析来自**database.ini**
文件的信息,我们用如下脚本创建了**config.py**
文件。它还创建了一个返回项目根文件夹的函数。
注意:
**section = ‘postgresql’**
的设置取决于**database.ini**
文件的文件头。我们以后可以修改它。
# Import libraries
from configparser import ConfigParser
from pathlib import Path
def get_project_root() -> Path:
"""Returns project root folder."""
return Path(__file__).parents[1]
def config(config_db):
section = 'postgresql'
config_file_path = 'config/' + config_db
if(len(config_file_path) > 0 and len(section) > 0):
# Create an instance of ConfigParser class
config_parser = ConfigParser()
# Read the configuration file
config_parser.read(config_file_path)
# If the configuration file contains the provided section name
if(config_parser.has_section(section)):
# Read the options of the section
config_params = config_parser.items(section)
# Convert the list object to a python dictionary object
# Define an empty dictionary
db_conn_dict = {}
# Loop in the list
for config_param in config_params:
# Get options key and value
key = config_param[0]
value = config_param[1]
# Add the key value pair in the dictionary object
db_conn_dict[key] = value
# Get connection object use above dictionary object
return db_conn_dict
当我们的作品需要定期读取数据库上的表格时,我们可以创建一个文件名为**db_conn.py**
的函数,如下。它将加载符合我们输入的表(**config_db**
和**query**
)。
# Import libraries
import pandas as pd
import psycopg2
from config.config import config
# Take in a PostgreSQL table and outputs a pandas dataframe
def load_db_table(config_db, query):
params = config(config_db)
engine = psycopg2.connect(**params)
data = pd.read_sql(query, con = engine)
return data
为了编译我们的脚本,我们设置我们的目录来定位**database.ini**
、**config.py**
和**db_conn.py**
。使用以下设置。
运行脚本的推荐目录(图片由作者提供)
等等!有**main.py**
文件,是什么?好吧,那么,它必须是一个 Python 脚本来测试我们通过 Python 的 PostgreSQL 连接。所以,这里是**main.py**
。
# Import libraries
from src.data.db_conn import load_db_table
from config.config import get_project_root
# Project root
PROJECT_ROOT = get_project_root()
# Read database - PostgreSQL
df = load_db_table(config_db = 'database.ini', query = 'SELECT * FROM tablename LIMIT 5')
print(df)
有用!现在,我们将自定义并创建其他 PostgreSQL 命令,以便通过 Python 创建、读取、更新或删除。
使用 psycopg2 创建、读取、更新和删除(CRUD)
创建表格
通过**psycopg2**
创建一个表使用了**CREATE TABLE**
语句,但是是在 Python 脚本中。之前,我们保存了数据库配置文件。当我们想连接 PostgreSQL 时,只需导入**config**
函数。
# Import libraries
import pandas as pd
import psycopg2
from config.config import config
# Connect to PostgreSQL
params = config(config_db = 'database.ini')
engine = psycopg2.connect(**params)
print('Python connected to PostgreSQL!')
# Create table
cur = con.cursor()
cur.execute("""
CREATE TABLE customer(
customer_id INT PRIMARY KEY NOT NULL,
name CHAR(50) NOT NULL,
address CHAR(100),
email CHAR(50),
phone_number CHAR(20));
""")
print('Table created in PostgreSQL')
# Close the connection
con.commit()
con.close()
将数据插入表格
创建一个新表**customer**
后,我们将通过 SQL 语句**INSERT INTO**
向表中插入一些值。这里有一个例子。
# Import libraries
import pandas as pd
import psycopg2
from config.config import config
# Connect to PostgreSQL
params = config(config_db = 'database.ini')
engine = psycopg2.connect(**params)
print('Python connected to PostgreSQL!')
# Insert values to the table
cur = con.cursor()
cur.execute("""
INSERT INTO customer (customer_id,name,address,email,phone_number)
VALUES (12345,'Audhi','Indonesia','myemail@gmail.com','+621234567');
""")
cur.execute("""
INSERT INTO customer (customer_id,name,address,email,phone_number)
VALUES (56789,'Aprilliant','Japan','email@gmail.com','+6213579246');
""")
print('Values inserted to PostgreSQL')
# Close the connection
con.commit()
con.close()
取回桌子
我们通过**SELECT**
SQL 语句检索我们的**customer**
表。在这种情况下,我们将检索**customer**
表的前五行。
**注意:**要从 PostgreSQL 中检索数据,请确保我们选择了正确的表名和列。不要使用
*****
语句,因为它会减慢我们的进度
# Import libraries
import pandas as pd
import psycopg2
from config.config import config
# Connect to PostgreSQL
params = config(config_db = 'database.ini')
engine = psycopg2.connect(**params)
print('Python connected to PostgreSQL!')
# Read the table
cur = con.cursor()
cur.execute("""
SELECT customer_id,name,email FROM customer LIMIT 5;
""")
print('Read table in PostgreSQL')
# Close the connection
con.commit()
con.close()
更新表格
当在数据库上工作时,定期更新我们的数据库是正常的,使用**UPDATE**
语句很容易执行。假设我们将更新拥有**customer_id = 12345**
的客户的地址。查看我们的表格,它将通过**psycopg2**
自动更新。
# Import libraries
import pandas as pd
import psycopg2
from config.config import config
# Connect to PostgreSQL
params = config(config_db = 'database.ini')
engine = psycopg2.connect(**params)
print('Python connected to PostgreSQL!')
# Insert values to the table
cur = con.cursor()
cur.execute("""
UPDATE customer SET address = 'Japan' WHERE customer_id = 12345;
""")
print('Values updated in PostgreSQL')
# Close the connection
con.commit()
con.close()
删除行或表格
最后, D 用于使用**DELETE**
语句删除(行或表)。在这种情况下,我们希望从一个**customer**
表中删除拥有**customer_id = 12345**
的客户信息。
# Import libraries
import pandas as pd
import psycopg2
from config.config import config
# Connect to PostgreSQL
params = config(config_db = 'database.ini')
engine = psycopg2.connect(**params)
print('Python connected to PostgreSQL!')
# Delete rows from the table
cur = con.cursor()
cur.execute("""
DELETE FROM customer WHERE customer_id = 12345;
""")
print('Values deleted from PostgreSQL')
# Close the connection
con.commit()
con.close()
结论
当处理大量代码时,我们不仅需要创建一个特定的脚本,还需要创建一个整洁干净的目录。有时,我们的脚本包含秘密信息,如数据库配置等。所以,我们在主脚本之外创建了**database.ini**
。对于**psycopg2**
模块,它有许多函数可以与 PostgreSQL 本地或远程交互,这使得我们可以更容易地开发自动化,而不是通过 PgAdmin 手动进行 CRUD 操作。
参考
[1] Python-Dev。psycopg 2 2 . 8 . 6【https://pypi.org/project/psycopg2/】【2020】。