TowardsDataScience-博客中文翻译-2021-五十七-

TowardsDataScience 博客中文翻译 2021(五十七)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

大 O 符号介绍

原文:https://towardsdatascience.com/introduction-to-big-o-notation-820d2e25d3fd?source=collection_archive---------0-----------------------

使用线性搜索和二分搜索法示例开始使用大 O 符号

介绍

大 O 符号是衡量算法效率的一种方式。它测量输入增加时运行函数所花费的时间。或者换句话说,函数的伸缩性有多好。

衡量效率有两个部分——时间复杂度和空间复杂度。时间复杂度是根据计算步骤来衡量函数运行的时间。空间复杂度与函数使用的内存量有关。这篇博客将用两种搜索算法来说明时间复杂性。

大 O 有时被称为算法的上限,这意味着它处理最坏的情况。最好的情况实际上并没有告诉我们什么——它将在第一遍中找到我们的项目。我们使用最坏情况来消除不确定性——算法的性能永远不会比我们预期的差。

Jr Korpa 在 Unsplash 上拍摄的照片

线性搜索示例

让我们看一个简单的例子。

我们将在 1-8 的范围内搜索数字 8。

我们的第一个策略是从数组的第一个数字开始,向上移动一个数字,直到找到目标数字。我们的算法步骤应该是这样的。

  1. 从头开始
  2. 将当前值与我们的目标值进行比较
  3. 移动到下一个值
  4. 到达列表的末尾

线性搜索-作者图片

在第一轮,我们选择一号。这是不正确的,所以我们转到第二轮,排除第一个选项。第二步也不正确,我们一直继续,直到我们选择第八个。

在我们最坏的情况下,这不是很有效。我们必须检查列表中的每一个数字,直到找到我们的答案。这种方法叫做线性搜索。线性搜索的大 O 符号是 O(N) 。复杂度与输入的大小直接相关-算法对每个额外的数据元素采取额外的步骤。

def linear_search(arr, x):  #input array and target

    for i in range(len(arr)): 
          if arr[i] == x: 
            return i 

    return -1   
# return -1 if target is not in the array

二分搜索法的例子

让我们试试不同的策略。这个策略的关键部分是列表必须有序。

这次我们从列表的中间开始。我们检查是否选择了目标数字。如果不是,我们检查数字是小于还是大于我们的选择。在这两种情况下,我们都排除掉不包括我们目标的一半列表。然后,我们在剩余值的中间选择一个数字。

  1. 找到列表的中间——中点
  2. 将中点与目标进行比较
  3. 如果我们的价值和目标相符,我们就停下来——我们找到了目标
  4. 如果我们的值比目标值小,我们制作一个新的列表,从中点加 1 到最大值。
  5. 如果我们的值大于目标值,我们会创建一个新的列表,范围从最小值到中点减一。
  6. 重复,直到我们找到目标或到达最后一个元素,它不匹配目标。

二分搜索法——作者图片

我们第一选择的中点是 4。目标值大于 4,所以我们排除值为 4 及以下的值,并创建一个从 5 到 8 的新列表。我们选择一个中点值 6,然后再次选择。我们继续,直到只剩下第八个。

这种策略被称为二分搜索法。它是有效的,因为它在每一遍中消除了一半的列表。如果我们加倍搜索,在 1-16 的范围内寻找第 16 个,我们只需要再多一轮。令人惊讶的是,如果我们要在 1 到 100 万之间选一个数字,最坏的情况是 20 次猜测。

当我们得到这样的大数字时,我们可以清楚地看到这种方法比使用线性搜索有效得多:20 次猜测对 1,000,000 次猜测。

我们可以对此进行数学建模。数字 8 等于 2 x 2 x 2。我们也可以用指数来表达这个方程:2 的 3 次方,或 2。

指数的倒数是对数。以 2 为底的 8 的对数意味着你要用多少次 2 乘以 8 才能得到 8。如上图所示,2 x 2 x 2 =8,所以 Log2 8 = 3。

一般来说,二分搜索法的最坏情况是 n + 1 的对数。二分搜索法的大 O 符号是 O(log N) 。与 O(N)对每个数据元素采取额外步骤相反,O(log N)意味着每次数据加倍时算法采取额外步骤。

def binary_search3(arr, target):
    left = 0
    right = len(arr) - 1while left <= right:
        mid_point = (left + right) // 2    

        if target < arr[mid_point]:
            right = mid_point - 1
        elif target > arr[mid_point]:
            left = mid_point + 1
        else:
            return mid_pointreturn -1

注意:即使二分搜索法比线性搜索更有效,你也不会总是在每个例子中选择它。这是因为第一个条件。二分搜索法要求该列表是有序的。对列表进行排序本身就很复杂,所以在某些情况下,使用线性搜索可能比首先对列表进行排序更有效。

书写大 O 符号

当我们写大 O 符号时,随着输入变得越来越大,我们寻找增长最快的项。我们可以通过去掉常数和任何非主导项来简化方程。比如 O(2N)变成 O(N),O(N + N + 1000)变成 O(N)。

二分搜索法是 O(log N ),比线性搜索简单。还有很多更复杂的算法。二次算法或 O(N)的一个常见例子是嵌套的 for 循环。在嵌套循环中,我们在外部循环中迭代整个数据。然后,对于每个元素,我们在一个内部循环中遍历数据。这是 N×N 乘以 N。

复杂性——作者形象

这是这些大运行时间在图表上的样子。这篇博客中的例子是两个最不复杂的符号。

大 O 图—作者图片

摘要

通常有许多选择来编写代码以获得解决方案。理解大 O 符号在编写算法时很重要。它帮助你确定你的算法何时变快或变慢。你也可以比较不同的方法,选择最有效的。

额外资源

通过 freeCodeCamp 的 Treehouse 有一个很棒的 YouTube 课程,带你从初学者到理解大 O 符号。警告它超过五个小时长。(这里有一个博客,里面有一些高效观看 YouTube 的技巧)

树屋教程

大 O 小抄

https://www.bigocheatsheet.com/

🚀PyCaret 二元分类简介

原文:https://towardsdatascience.com/introduction-to-binary-classification-with-pycaret-a37b3e89ad8d?source=collection_archive---------4-----------------------

使用 PyCaret 的 Python 二进制分类的循序渐进的初学者友好教程

Unsplash 上由麦克 U 拍摄的照片

1.0 简介

PyCaret 是一个用 Python 编写的开源、低代码的机器学习库,可以自动化机器学习工作流。这是一个端到端的机器学习和模型管理工具,可以成倍地加快实验周期,提高您的工作效率。

与其他开源机器学习库相比,PyCaret 是一个替代的低代码库,可以用来用几行代码替换数百行代码。这使得实验快速有效。PyCaret 本质上是几个机器学习库和框架的 Python 包装器,比如 scikit-learn、XGBoost、LightGBM、CatBoost、spaCy、Optuna、Hyperopt、Ray 等等。

PyCaret 的设计和简单性受到了公民数据科学家这一新兴角色的启发,这是 Gartner 首先使用的术语。公民数据科学家是超级用户,他们可以执行简单和中等复杂的分析任务,这些任务在以前需要更多的技术专业知识。

想了解更多关于 PyCaret 的信息,可以查看官方网站或者 GitHub

2.0 教程目标

在本教程中,我们将学习:

  • 获取数据:如何从 PyCaret 存储库中导入数据
  • 设置环境:如何在 PyCaret 中设置实验并开始构建分类模型
  • 创建模型:如何创建模型、执行分层交叉验证和评估分类指标
  • 调整模型:如何自动调整分类模型的超参数
  • 绘图模型:如何使用各种绘图分析模型性能
  • 敲定模型:如何在实验结束时敲定最佳模型
  • 预测模型:如何对看不见的数据进行预测
  • 保存/加载模型:如何保存/加载模型以备将来使用

3.0 安装 PyCaret

安装很容易,只需几分钟。PyCaret 从 pip 的默认安装只安装在 requirements.txt 文件中列出的硬依赖项。

pip install pycaret

要安装完整版:

pip install pycaret[full] 

4.0 什么是二进制分类?

二元分类是一种受监督的机器学习技术,其目标是预测离散且无序的分类标签,例如通过/失败、肯定/否定、默认/非默认等。下面列出了一些分类的真实使用案例:

  • 确定患者是否患有某种疾病的医学测试——分类属性是疾病的存在。
  • 工厂中的“通过或失败”测试方法或质量控制,即决定是否符合规格——通过/不通过分类。
  • 信息检索,即决定一个页面或一篇文章是否应该出现在搜索结果集中——分类属性是文章的相关性或对用户的有用性。

5.0 py caret 中分类模块的概述

PyCaret 的分类模块 ( pycaret.classification)是一个受监督的机器学习模块,用于根据各种技术和算法将元素分类到二进制组中。分类问题的一些常见用例包括预测客户违约(是或否)、客户流失(客户将离开或留下)、发现疾病(阳性或阴性)。

PyCaret 分类模块可用于二进制或多类分类问题。它有超过 18 个算法和 14 个图来分析模型的性能。无论是超参数调整、集成,还是堆叠等高级技术,PyCaret 的分类模块都具备。

教程的 6.0 数据集

对于本教程,我们将使用一个来自 UCI 的数据集,名为 信用卡客户数据集 的默认值。此数据集包含从 2005 年 4 月到 2005 年 9 月台湾信用卡客户的违约付款、人口统计因素、信用数据、付款历史和账单等信息。有 24,000 个样本和 25 个特征。每列的简短描述如下:

  • ID: 每个客户端的 ID
  • LIMIT_BAL: 以新台币为单位的给定额度(包括个人和家庭/补充额度)
  • 性别:性别(1 =男性,2 =女性)
  • 学历:(1 =研究生院,2 =大学,3 =高中,4 =其他,5 =未知,6 =未知)
  • 婚姻:婚姻状况(1 =已婚,2 =单身,3 =其他)
  • 年龄:以年为单位的年龄
  • PAY_0 至 PAY _ 6:n 个月前的还款状态(PAY_0 =上月… PAY_6 = 6 个月前)(标签:-1 =按时还款,1 =延迟一个月还款,2 =延迟两个月还款,…8 =延迟八个月还款,9 =延迟九个月及以上还款)
  • BILL_AMT1 至 BILL _ AMT 6:n 个月前的对账单金额(BILL_AMT1 = last_month..BILL_AMT6 = 6 个月前)
  • PAY _ am t1 to PAY _ AMT 6:n 个月前的付款金额(BILL_AMT1 = last_month..BILL_AMT6 = 6 个月前)
  • 违约:违约付款(1 =是,0 =否)Target Column

数据集确认:

利奇曼(2013 年)。UCI 机器学习知识库。加州欧文:加州大学信息与计算机科学学院。

7.0 获取数据

您可以从这里找到的原始数据源https://archive.ics.uci.edu/ml/datasets/default+of+credit+card+clients下载数据,并使用 pandas (了解如何使用) 加载数据,或者您可以使用 PyCaret 的数据存储库,使用get_data()函数加载数据(这将需要互联网连接)。

**# loading the dataset** from pycaret.datasets import get_data
dataset = get_data('credit')

**# check the shape of data** dataset.shape>>> (24000, 24)

为了演示对看不见的数据使用predict_model函数,从原始数据集中保留了 1200 条记录的样本(约 5%),用于最终的预测。这不应该与训练-测试-分割相混淆,因为这种特定的分割是为了模拟真实场景而执行的。另一种思考方式是,在训练机器学习模型时,这 1200 个客户是不可用的。

**# sample 5% of data to be used as unseen data**
data = dataset.sample(frac=0.95, random_state=786)
data_unseen = dataset.drop(data.index)
data.reset_index(inplace=True, drop=True)
data_unseen.reset_index(inplace=True, drop=True)**# print the revised shape** print('Data for Modeling: ' + str(data.shape))
print('Unseen Data For Predictions: ' + str(data_unseen.shape))>>> Data for Modeling: (22800, 24)
>>> Unseen Data For Predictions: (1200, 24)

8.0 在 PyCaret 中设置环境

PyCaret 中的setup函数初始化环境,并为建模和部署创建转换管道。在 pycaret 中执行任何其他函数之前,必须调用setup。它有两个强制参数:一个 pandas dataframe 和目标列的名称。所有其他参数都是可选的,可用于定制预处理管道。

当执行setup时,PyCaret 的推理算法会根据某些属性自动推断出所有特性的数据类型。应该可以正确推断出数据类型,但情况并非总是如此。为了处理这个问题,一旦执行了setup,PyCaret 就会显示一个提示,要求确认数据类型。如果所有数据类型都正确,您可以按 enter 键,或者键入quit退出设置。

确保数据类型正确在 PyCaret 中非常重要,因为它会自动执行多个特定于类型的预处理任务,这些任务对于机器学习模型来说是必不可少的。

或者,您也可以使用setup中的numeric_featurescategorical_features参数来预定义数据类型。

**# init setup** from pycaret.classification import *
s = setup(data = data, target = 'default', session_id=123)

成功执行设置后,它会显示信息网格,其中包含一些关于实验的重要信息。大部分信息与执行setup时构建的预处理流水线有关。这些特性的大部分超出了本教程的范围,但是,有一些重要的事情需要注意:

  • session_id: 在所有函数中作为种子分发的伪随机数,用于以后的可再现性。如果没有通过session_id,则自动生成一个随机数,分配给所有函数。在本实验中,为了以后的再现性,将session_id设置为123
  • ****目标类型:二进制或多类。自动检测并显示目标类型。二元或多类问题的实验方式没有区别。所有功能都是相同的。
  • ****标签编码:当目标变量为字符串类型(即“是”或“否”)而不是 1 或 0 时,自动将标签编码为 1 和 0,并显示映射(0:否,1:是)以供参考。在这个实验中,不需要标签编码,因为目标变量是 numeric 类型。
  • ****原始数据:显示数据集的原始形状。在这个实验中(22800,24)意味着包括目标列在内的 22800 个样本和 24 个特征。
  • ****缺失值:当原始数据中存在缺失值时,将显示为真。对于这个实验,数据集中没有缺失值。
  • ****数字特征:推断为数字的特征数量。在该数据集中,24 个要素中有 14 个被推断为数字。
  • ****分类特征:被推断为分类的特征的数量。在该数据集中,24 个特征中有 9 个被推断为分类特征。
  • ****变换后的训练集:显示变换后的训练集的形状。注意,对于变换后的训练集,( 22800,24)的原始形状被变换为(15959,91 ),并且由于一次热编码,特征的数量从 24 增加到 91。
  • ****转换后的测试集:显示转换后的测试/保持集的形状。测试/保留组中有 6841 个样本。该分割基于默认值 70/30,可使用设置中的train_size参数进行更改。

请注意,执行建模所必需的一些任务是如何自动处理的,例如缺失值插补(在这种情况下,训练数据中没有缺失值,但我们仍然需要用于未知数据的插补器)、分类编码等。setup中的大多数参数是可选的,用于定制预处理流水线。这些参数超出了本教程的范围,但是我们将在以后的教程中介绍它们。

9.0 比较所有模型

一旦设置完成,比较所有模型以评估性能是建模的推荐起点(除非您确切地知道您需要哪种模型,而事实往往并非如此)。该函数训练模型库中的所有模型,并使用分层交叉验证对它们进行评分以进行指标评估。输出打印一个评分网格,显示平均准确度、AUC、召回率、精确度、F1、Kappa 和 MCC(默认为 10)以及训练时间。

best_model = compare_models()

上面打印的评分网格突出显示了最高绩效指标,仅供比较之用。默认情况下,网格使用Accuracy (从最高到最低)排序,这可以通过传递sort参数来更改。例如,compare_models(sort = 'Recall')将通过回忆而不是准确性来对网格进行排序。

如果您想将折叠参数从默认值10更改为不同的值,那么您可以使用fold参数。例如compare_models(fold = 5)将对所有模型进行 5 重交叉验证比较。减少折叠次数将改善训练时间。默认情况下,compare_models根据默认的排序顺序返回性能最好的模型,但也可以通过使用n_select参数返回前 N 个模型的列表。

print(best_model)**>>> OUTPUT**RidgeClassifier(alpha=1.0, class_weight=None, copy_X=True, fit_intercept=True,
                max_iter=None, normalize=False, random_state=123, solver='auto',
                tol=0.001)

10.0 创建模型

create_model是 PyCaret 中粒度最细的函数,通常是大多数 PyCaret 功能的基础。顾名思义,该函数使用交叉验证来训练和评估模型,交叉验证可以用fold参数来设置。输出打印出一个得分网格,按倍数显示准确性、AUC、召回率、精确度、F1、Kappa 和 MCC。

对于本教程的剩余部分,我们将使用下面的模型作为我们的候选模型。这些选择仅用于说明目的,并不意味着它们是此类数据的最佳选择或理想选择。

  • 决策树分类器
  • k 邻居分类器(“knn”)
  • 随机森林分类器(“rf”)

PyCaret 的模型库中有 18 个可用的分类器。要查看所有分类器的列表,要么查看文档,要么使用models功能查看库。

**# check available models** models()

10.1 决策树分类器

dt = create_model('dt')

**# trained model object is stored in the variable 'dt'.** 
print(dt)**>>> OUTPUT**DecisionTreeClassifier(ccp_alpha=0.0, class_weight=None, criterion='gini',
                       max_depth=None, max_features=None, max_leaf_nodes=None,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=1, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, presort='deprecated',
                       random_state=123, splitter='best')

10.2 K 邻居分类器

knn = create_model('knn')

10.3 随机森林分类器

rf = create_model('rf')

请注意,所有型号的平均分数与compare_models中打印的分数相匹配。这是因为打印在compare_models分数网格中的指标是所有简历折叠的平均分数。与compare_models类似,如果您想将折叠参数从默认值 10 更改为不同的值,那么您可以使用fold参数。例如:create_model('dt', fold = 5)将使用 5 重分层 CV 创建一个决策树分类器。

11.0 调整模型

当使用create_model功能创建模型时,它使用默认超参数来训练模型。为了调整超参数,使用tune_model功能。该功能使用预定义搜索空间上的随机网格搜索自动调整模型的超参数。输出打印一个得分网格,显示最佳模型的准确度、AUC、召回率、精确度、F1、Kappa 和 MCC。要使用自定义搜索网格,您可以在tune_model函数中传递custom_grid参数(参见下面的 11.2 KNN 调谐)。

11.1 决策树分类器

tuned_dt = tune_model(dt)

**# tuned model object is stored in the variable 'tuned_dt'.** print(tuned_dt)**>>> OUTPUT**DecisionTreeClassifier(ccp_alpha=0.0, class_weight=None, criterion='entropy',
                       max_depth=6, max_features=1.0, max_leaf_nodes=None,
                       min_impurity_decrease=0.002, min_impurity_split=None,
                       min_samples_leaf=5, min_samples_split=5,
                       min_weight_fraction_leaf=0.0, presort='deprecated',
                       random_state=123, splitter='best')

11.2 K 邻居分类器

import numpy as np
tuned_knn = tune_model(knn, custom_grid = {'n_neighbors' : np.arange(0,50,1)})

print(tuned_knn)**>>> OUTPUT**KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
                     metric_params=None, n_jobs=-1, n_neighbors=42, p=2,
                     weights='uniform')

11.3 随机森林分类器

tuned_rf = tune_model(rf)

默认情况下,tune_model会优化Accuracy,但这可以使用optimize参数进行更改。例如:tune_model(dt, optimize = 'AUC')将搜索产生最高AUC而不是Accuracy的决策树分类器的超参数。出于本例的目的,我们使用默认指标Accuracy只是为了简单起见。一般来说,当数据集不平衡时(比如我们正在处理的信用数据集),Accuracy不是一个值得考虑的好指标。选择正确的度量来评估分类器的方法超出了本教程的范围,但是如果您想了解更多,您可以 单击此处 阅读关于如何选择正确的评估度量的文章。

在最终确定生产的最佳模型时,度量并不是您应该考虑的唯一标准。其他要考虑的因素包括训练时间、kfolds 的标准偏差等。随着教程系列的进展,我们将在中级和专家级别详细讨论这些因素。现在,让我们继续考虑调优的随机森林分类器tuned_rf,作为本教程剩余部分的最佳模型。

12.0 绘制模型

在模型最终确定之前,plot_model函数可用于分析不同方面的性能,如 AUC、混淆矩阵、决策边界等。该函数接受一个经过训练的模型对象,并根据测试集返回一个图。

有 15 种不同的图可用,请参见plot_model文档中的可用图列表。

12.1 AUC 图

plot_model(tuned_rf, plot = 'auc')

12.2 精确召回曲线

plot_model(tuned_rf, plot = 'pr')

12.3 特征重要性图

plot_model(tuned_rf, plot='feature')

12.4 混淆矩阵

plot_model(tuned_rf, plot = 'confusion_matrix')

分析模型性能的另一种方法是使用evaluate_model()功能,该功能显示给定模型所有可用图的用户界面。它在内部使用plot_model()功能。

evaluate_model(tuned_rf)

13.0 预测测试/保留样品

在最终确定模型之前,建议通过预测测试/坚持集和审查评估指标来执行最后的检查。如果您查看上面第 8 节中的信息网格,您将会看到 30% (6,841 个样本)的数据被分离出来作为测试/保留样本。我们上面看到的所有评估指标都是基于训练集(70%)的交叉验证结果。现在,使用我们存储在tuned_rf中的最终训练模型,我们将预测测试/保留样本并评估指标,以查看它们是否与 CV 结果有实质性差异。

predict_model(tuned_rf);

与在tuned_rf CV 结果(见上文第 11.3 节)上获得的**0.8203**相比,测试/保持设置的精度为**0.8116**。这不是一个显著的差异。如果测试/保持和 CV 结果之间存在较大差异,则这通常表明过度拟合,但也可能是由于其他几个因素,需要进一步调查。在这种情况下,我们将继续最终确定模型,并根据看不见的数据进行预测(我们在开始时已经分离出来的、从未向 PyCaret 公开的 5%)。

(提示:使用create_model时,看看 CV 结果的标准差总是好的)

14.0 最终确定部署模型

模型定型是实验的最后一步。PyCaret 中正常的机器学习工作流程从setup开始,然后使用compare_models比较所有模型,并列出几个候选模型(基于感兴趣的度量)来执行几种建模技术,如超参数调整、集成、堆叠等。这一工作流程最终将引导您找到用于对新的和未知的数据进行预测的最佳模型。finalize_model函数将模型拟合到完整的数据集上,包括测试/保留样本(本例中为 30%)。此函数的目的是在将最终模型部署到生产中之前,在完整的数据集上对其进行训练。(这是可选的,您可以使用 finalize_model,也可以不使用)。

**# finalize rf model**
final_rf = finalize_model(tuned_rf)**# print final model parameters**
print(final_rf)**>>> OUTPUT**RandomForestClassifier(bootstrap=False, ccp_alpha=0.0, class_weight={},
                       criterion='entropy', max_depth=5, max_features=1.0,
                       max_leaf_nodes=None, max_samples=None,
                       min_impurity_decrease=0.0002, min_impurity_split=None,
                       min_samples_leaf=5, min_samples_split=10,
                       min_weight_fraction_leaf=0.0, n_estimators=150,
                       n_jobs=-1, oob_score=False, random_state=123, verbose=0,
                       warm_start=False)

警告:最后一句警告。一旦模型最终确定,包括测试/拒绝集的整个数据集用于训练。因此,如果在使用finalize_model后,该模型用于对拒绝集进行预测,打印的信息网格将会产生误导,因为您正试图对用于建模的相同数据进行预测。为了证明这一点,我们将使用predict_model下的final_rf来比较信息网格和上面第 13 节中的信息网格。

predict_model(final_rf);

请注意final_rf中的 AUC 是如何从**0.7407**增加到**0.7526**的,尽管模型是相同的。这是因为final_rf变量已经在包括测试/拒绝集的完整数据集上进行了训练。

15.0 根据看不见的数据进行预测

predict_model函数也用于对未知数据集进行预测。与上面第 13 节唯一不同的是,这次我们将通过data_unseen。它是在本教程开始时创建的变量,包含原始数据集的 5% (1200 个样本),该数据集从未暴露给 PyCaret。(参见第 7 节的解释)

unseen_predictions = predict_model(final_rf, data=data_unseen)
unseen_predictions.head()

LabelScore列被添加到data_unseen组中。标签是预测,分数是预测的概率。请注意,当所有转换都在后台自动执行时,预测结果会连接到原始数据集。您还可以检查这方面的指标,因为您有一个实际的目标列default可用。为此,我们将使用pycaret.utils模块。请参见下面的示例:

**# check metric on unseen data** from pycaret.utils import check_metric
check_metric(unseen_predictions['default'], unseen_predictions['Label'], metric = 'Accuracy')**>>> OUTPUT** 0.8167

16.0 保存模型

我们现在已经通过最终确定tuned_rf模型完成了实验,该模型现在存储在final_rf变量中。我们还使用存储在final_rf中的模型来预测data_unseen。这使我们的实验接近尾声,但仍有一个问题要问:当你有更多的新数据要预测时,会发生什么?你必须再次经历整个实验吗?答案是否定的,PyCaret 的内置函数save_model()允许您保存模型和整个转换管道以备后用。

**# saving the final model** save_model(final_rf,'Final RF Model 11Nov2020')>>> Transformation Pipeline and Model Successfully Saved

17.0 加载保存的模型

为了在将来的某一天在相同或不同的环境中加载已保存的模型,我们将使用 PyCaret 的load_model()函数,然后轻松地将已保存的模型应用于新的未知数据进行预测。

**# loading the saved model**
saved_final_rf = load_model('Final RF Model 11Nov2020')>>> Transformation Pipeline and Model Successfully Loaded

一旦模型加载到环境中,您就可以使用相同的predict_model()函数简单地使用它来预测任何新数据。下面我们应用加载模型来预测我们在上面第 13 节中使用的相同的data_unseen

**# predict on new data** new_prediction = predict_model(saved_final_rf, data=data_unseen)
new_prediction.head()

注意unseen_predictionsnew_prediction的结果是相同的。

from pycaret.utils import check_metric
check_metric(new_prediction['default'], new_prediction['Label'], metric = 'Accuracy')>>> 0.8167

18.0 总结/后续步骤?

本教程涵盖了从数据摄取、预处理、训练模型、超参数调整、预测和保存模型以备后用的整个机器学习管道。我们已经在不到 10 个命令中完成了所有这些步骤,这些命令是自然构建的,记忆起来非常直观,例如create_model()tune_model()compare_models()。在没有 PyCaret 的情况下,重新创建整个实验在大多数库中需要 100 多行代码。

我们只讲述了pycaret.classification的基础知识。在未来的教程中,我们将更深入地研究高级预处理、集成、广义堆叠和其他技术,这些技术允许您完全定制您的机器学习管道,并且是任何数据科学家都必须知道的。

感谢您阅读🙏

重要链接

教程py caret 新手?查看我们的官方笔记本!
📋社区创建的示例笔记本
📙博客投稿人的教程和文章。
📚文档py caret 的详细 API 文档
📺视频教程我们的视频教程来自各种赛事。
📢讨论有疑问?与社区和贡献者互动。
🛠️ 变更日志变更和版本历史。
🌳路线图 PyCaret 的软件和社区开发计划。

作者:

我写的是 PyCaret 及其在现实世界中的用例,如果你想自动得到通知,你可以在媒体LinkedInTwitter 上关注我。

助推树木简介

原文:https://towardsdatascience.com/introduction-to-boosted-trees-2692b6653b53?source=collection_archive---------9-----------------------

助推技术

机器学习中的助推算法——第一部分

照片由卡斯登·沃斯(➡️@卡斯登.沃斯)Unsplash 上拍摄

欢迎来到我的新文章系列:机器学习中的助推算法!这是本系列的第 1 部分。在这里,我会给你一个简短的介绍升压,它的目标,一些关键的定义和一个升压算法列表,我们打算涵盖在未来的职位。

先决条件

你应该熟悉初级的基于树的机器学习模型,比如决策树随机森林 。除此之外,建议好好了解一下 Python 及其 Scikit-learn 库。

创造助推树木的目的

当我们想要创建非线性模型时,我们可以尝试创建基于树的模型。首先,我们可以从决策树开始。决策树的主要缺点是过度拟合训练数据。决策树的一个很好的替代品是随机森林。我们可以通过一种叫做Bagging(bootstrap aggregating)的技术组合多个决策树来创建一个随机森林。随机森林比决策树有更好的性能。

随机森林也有一个缺点。他们不能处理由他们个人的决策树产生的错误(如果有的话)。由于并行学习,如果一个决策树出错,整个随机森林模型都会出错。随机森林的一个很好的替代方案是提升树模型。这种模型的主要目标是通过避免上述缺点来超越决策树和随机森林。

什么是助推?

像 bagging 一样,boosting 是一种集成方法,其中用一组决策树创建 boosted 树。区分装袋和助推是有用的。

装袋是自举聚集的简称。当算法进行样本替换时,称为自举。随机森林通过聚合自举决策树样本的预测来做出最终预测。因此,随机森林是一种 bagging 系综方法。随机森林中的树是相互独立的。

相比之下,

Boosting 处理之前决策树产生的错误。在 boosting 中,通过考虑前几轮树的错误来形成新的树。因此,新的树一棵接一棵地被创造出来。每棵树都依赖于前一棵树。这种类型的学习被称为顺序学习,其中并行计算并不理想。

升压的一些关键考虑因素是:

  • Boosting 将弱决策树(称为弱学习器)转换为强学习器。
  • 每个新树的建立都考虑了先前树的错误。
  • 在 bagging 和 boosting 中,算法都使用一组(总体)决策树。打包和提升被称为集成元算法。
  • 升压是一个迭代过程。每棵树都依赖于前一棵树。因此,很难并行化 boosting 算法的训练过程。培训时间会高一些。这是 boosting 算法的主要缺点。
  • 从增强过程中修改的树被称为增强树

基础学习者

基础学习者是任何集成技术的基本组成部分。它是一个单独的模型,更常见的是一个决策树。在增压中,一个基本的稀薄器被称为弱稀薄器。当弱学习器是决策树时,专门称为决策树树桩决策树桩浅决策树只有一个内部节点(根)连接两个叶节点( max_depth=1 )的 1-分裂决策树

助推算法

这里列出了机器学习中使用的一些流行的 boosting 算法。我们将在接下来的文章中详细介绍每个算法及其 Python 实现。

摘要

我们刚刚开始我们的新文章系列:机器学习中的助推算法。除了讨论以上算法,我还会增加一些专题。

Boosting 算法是基于树的算法,对于在非线性数据上构建模型非常重要。因为大多数真实世界的数据是非线性的,所以学习这些算法将是有用的。在本系列文章结束时,您将对 boosting 算法及其 Python 实现有一个清晰的了解。

今天的帖子到此结束。我的读者可以通过下面的链接注册成为会员,以获得我写的每个故事的全部信息,我将收到你的一部分会员费。

https://rukshanpramoditha.medium.com/membership

非常感谢你一直以来的支持!下一个故事再见。祝大家学习愉快!

特别要感谢 Unsplash 网站上的 Karsten WürthT3,他为我提供了这篇文章的封面图片。

鲁克山·普拉莫迪塔
2021–10–21

数据科学中的引导介绍—第 1 部分

原文:https://towardsdatascience.com/introduction-to-bootstrapping-in-data-science-part-1-6e3483636f67?source=collection_archive---------12-----------------------

入门

大胆探索理论从未涉足的领域。

乔舒亚·科尔曼Unsplash 上拍摄的照片

你知道程序:有一个总体,你想估计一个特征,例如,平均值。不幸的是,你不能测量群体中的每一个人,所以你抽取一个样本。遵循你最喜欢的统计学书籍中的指导方针,你通过假设参数分布是正态的并且样本大小足够大以至于中心极限定理开始生效来简化问题。在这些假设下,您注意到手头的任务类似于“方差未知的正态分布均值的置信区间”,因此您查找相应的数学方程,填入数值,然后…工作完成!

图 1:理论框架。图片作者。

传统的统计方法依赖于大样本、一些众所周知的理论分布和中心极限定理的安全网来工作。这些快捷方式让研究人员在大多数情况下都可以解决问题,尽管在某些情况下这是不可能的。作为数据科学家,我们经常面临挑战性的问题,这些问题超出了传统统计学的安全范围,仅限于有限数量的熟悉场景。可悲的是,现实是顽固的,数据以各种扭曲的形式出现,有时你只需要估计比简单平均值更复杂的参数。

但还是有希望的。由于计算技术不可阻挡的发展,对大型复杂数据集的研究现在是可行的。几年前禁止进行的模拟也是如此。目前,有一些方法可以放松传统推理的一些必要条件,并使数据科学家的工作变得更容易。在没有任何理论认可的方法的挑战性场景中,你仍然可以茁壮成长。

本文温和地介绍了 bootstrapping 方法,它可以应用于单变量数据样本的几乎任何统计。第一部分解决了一个众所周知的问题,为证明自举和理论方法的一致性奠定了基础。然后,我们进入一个更复杂的场景,在那里理论没有什么帮助,随后,我们用 bootstrapping 解决这个问题。

引导限制

在我们继续之前,让我们解决一些误解:bootstrap 不创建数据。它实际上做的是估计统计数据、置信区间,并在广泛的情况下进行假设检验,即使它们没有被现存的统计理论所涵盖。仍然有一些完全不可避免的限制:

  • 输入必须是人口的随机样本。对此没有变通办法。如果样本不是随机的,那么它就不具有代表性,因此该方法将失败。
  • 非常小的样本仍然是个问题。我们不能无中生有,凭空创造数据。引导引入了该方法固有的一定量的变化。大部分来自原始样本的选择,只有一小部分来自重采样过程。因此,样本越大越好。小样本将严重损害自举结果的可靠性。
  • 一些统计数据本来就比其他的更难。例如,自举中位数或其他分位数是有问题的,除非样本量非常大。

图二。示例中考虑的人口(平均值正好为 0.5)。图片作者。

示例 1.1:传统均值估计

在本例中,我们通过应用传统方法和引导方法来解决一个常见问题。对于图 2 中所示的总体,让我们通过随机样本来估计均值。如图 1** 所述,这是一个典型的推理问题,我们可以安全地应用该理论。在某些假设下,我们可以使用右下角熟悉的表达式来计算置信区间。所以过程如下:**

  1. 随机抽取人口样本(见图 3 )。
  2. 应用带有 t 统计量的公式来计算间隔。

图 3。样本(n=100,平均值=0.566)。图片作者。

sample_mean=0.566 sample_std=0.502
(0.46606681302580744, 0.6661796676261962)

样本均值为 0.566,标准差为 0.502,总体均值的 95%置信区间为[0.466,0.666],其中包含实际值(0.500)。

示例 1.2:自举均值

自举的优势之一是其惊人的简单性(参见图 4 ):

  1. 随机抽取人群样本(同上)。
  2. 用完全相同的尺寸,从原始样本中画出替换的重新样本。
  3. 计算重新取样的统计量(在这种情况下是平均值),并将结果存储在一个列表中。
  4. 转到 2,重复几百次甚至几千次。

图 4。自举算法。图片作者。

这些值的分布就是 bootstrap 分布,其中应该模仿理论抽样分布。一般来说,它以样本(而不是总体)中的统计值为中心,允许有小的偏差。绘制它并检查它是否近似正常总是一个好主意。如果是这样,你可以回到传统的 t 统计,这种方法被称为 bootstrap-t 。否则,只需计算非参数 bootstrap 百分位置信区间,也就是说,选择 bootstrap 分布下包含您的置信水平所需区域的两个分位数。第二种方法不受偏斜度的影响,所以只要偏斜度小,它通常更准确。

自举是一种非常有效的技术。然而,如果您得到一个相对较大的偏差或 bootstrap 分布明显偏离正常,这两个明显的症状表明该过程可能不会按预期工作。在那种情况下,你应该小心行事。

Bootstrap results:
 n=100 m=1000 sample_fn=0.566 bootstrap_mean=0.567 bias=-0.001 bootstrap_se=0.049
Confidence interval 95%:
 [0.471 .. 0.566 .. 0.670]

图 5。均值的自助分布。图片作者。

如果我们与传统方法比较,两种结果都非常接近。再次强调,自举不会创建数据。这是一种没有抽样分布理论支持的前进方式。我们使用 bootstrapping 结果有两个目的:估计参数及其可变性。我们不需要做出诸如人口正态性的理论假设,也不需要依赖中心极限定理。即使理论不能解释我们的统计数据的抽样分布,这种方法也是有效的(下一个例子中会详细介绍)。bootstrap 分布(见图 5 )填补了这一空白,并允许我们直接从中估计置信区间。

例 2:前 50%的平均值

我们想计算人口中前 50%的个人的平均值。换句话说,高于中值的平均值。这个自定义参数不像平均值那样常见,因此,您在教科书中找不到任何估计它的提示。没有理论方法,我们不得不求助于自举。

多亏了插件原理,我们可以通过计算从中抽取的样本上的相同属性来估计群体的几乎任何属性。Bootstrapping 会处理剩下的事情,为我们提供适当的 bootstrap 分布来近似其他的一切。

这个过程和以前完全一样,只是有一点小小的变化:我们必须用新的统计量代替平均值。因此,我们编写一个新的函数,并重用其余的代码。

Bootstrap results:
 n=100 m=1000 sample_fn=0.979 bootstrap_mean=0.981 bias=-0.002 bootstrap_se=0.067
Confidence interval 95%:
 [0.850 .. 0.983 .. 1.112]

图 6。自定义统计的 Bootstrap 分布。图片作者。

结果相当好,因为前 50%的平均值的实际值是 0.902,正好在提供的区间内。一眨眼的功夫,计算机已经运行了一千次迭代来构建 bootstrap 分布,并计算了一个在我们的教科书中没有的新颖统计的置信区间。这是一个很好的例子,说明了这种方法的强大和方便。

最后的话

“bootstrapping”一词的所谓来源是《孟乔森男爵奇异历险记》https://en.wikipedia.org/wiki/Baron_Munchausen(1786)的一个版本中的一段话,当主角通过拉自己靴子的带子从一个洞里出来时。

这一比喻在一定程度上适用:虽然自举并不创造数据,但这一简单的计算技术让我们可以利用手头的数据更进一步,即使在理论不可用或无法安全做出假设的情况下,这一方法也能奏效。

我将在后续文章中介绍各种各样的引导应用程序(见下文)。如果你对这个话题感兴趣,我强烈建议你看看参考资料。感谢您的阅读!

* *

参考文献

[1]埃夫龙,B. (1979 年)。自举方法:再看折刀统计年鉴,1–26。

[2]埃夫龙,b .,蒂布拉尼,r .,,蒂布拉尼,R. J. (1994 年)。自举简介。查普曼&霍尔/CRC。

[3]戴维森和欣克利(1997 年)。 Bootstrap 方法及其应用(剑桥统计与概率数学丛书)。剑桥:剑桥大学出版社。

[4]哥伦比亚特区蒙哥马利和佐治亚州龙格(2013 年)。工程师应用统计与概率。约翰·威利&的儿子们。

[5]摩尔博士、麦凯布博士和克雷格学士(2014 年)。统计学实践入门。第八版。纽约:麦克米伦高等教育公司 W.H. Freeman and Company。

数据科学中的引导介绍—第 2 部分

原文:https://towardsdatascience.com/introduction-to-bootstrapping-in-data-science-part-2-ef7236e464a7?source=collection_archive---------34-----------------------

使用您选择的任何自定义统计数据比较两个样本

艾米·珊布伦Unsplash 上拍摄的照片

在本系列的第一部分中,我们描述了如何使用随机样本和简单的迭代算法 bootstrapping 来估计更广泛人群中几乎任何特征的置信区间。这种方法比传统的统计方法有决定性的优势:它是一种通用的方法,允许我们用几行代码来面对挑战性的问题。有趣的是,它也将我们从理论框架中解放出来,这些框架通常受到假设的约束,而这些假设可能并不适用于所有可能的情况。说实话,在很多情况下,我们不能依赖那些众所周知的教科书解决方案。

好消息是,bootstrapping 可以很容易地应用于其他设置,如双样本问题假设检验。我们将在本文中讨论前者,并将后者留给本系列的第三部分也是最后一部分(敬请关注!).在本文的第一部分,我们将使用参数法和自举法来估计两个正态分布的差异,其中方差未知且不等于,作为两种方法一致的证明。然后,我们将提出一个更具挑战性的问题,这个问题没有简单的参数解,而 bootstrapping 可以毫不费力地解决它。

例 1.1:方差未知且不相等的传统均值差

假设我们有两个服从正态分布的总体(这是一个很大的假设),均值和方差未知。我们也知道方差互不相同。在这种情况下,我们需要估计均值的差异,并提供一个合理的置信区间。尽管这是一个有些不利的样本比较案例,但这也是一个众所周知的问题,你可以在你最喜欢的统计学教科书中查找(图 1 ):

图 1:理论框架。图片作者。

上面的一些等式相对来说比较密集,但是没有什么是我们不能用 Python 处理的。此外,如果样本量足够大,你可以简化问题,切换到一个 z 统计量而不是一个 t 统计量(并摆脱复杂的自由度计算)。在任何情况下,让我们坚持完整的公式,并遵循以下程序:

  1. 从每个群体中随机抽取一个样本(参见图 2图 3 )。
  2. 使用图 1 中所示的理论近似值计算统计值和置信区间。

图 2:两个种群 A 和 B 的分布,均值分别为 1.0 和 0.0。图片作者。

图 3:样品取自 A 和 B,尺码分别为 20 和 30。图片作者。

这是一个估计置信区间的 Python 函数:

Difference=1.092
Confidence interval (95%): [0.741, 1.444]

在 95%的置信度下,我们可以保证均值差异大于 0.741 且小于 1.444。这个结果已经足够好了,因为实际值是 1。

示例 1.2:自举解决了相同的问题

自举函数来了。该算法非常类似于本系列第篇文章中详细描述的单样本版本:

图 4: 两个样本的自举算法。图片作者。

  1. 从两个群体中抽取样本 A 和 B(参见图 23 )。
  2. 用完全相同的尺寸,从原始样品 A 中画出替换的重新样品。
  3. 用完全相同的尺寸,从原始样品 B 画一个替换的重样品。
  4. 计算两次重采样的统计值(在这种情况下,平均值的差异)。
  5. 将统计数据存储在列表中。
  6. 转到 2。重复几千遍。

图 5:均值差异的 Bootstrap 分布。图片作者。

n1=20 n2=30 iterations=10000
sample_fn=1.092 **bootstrap_mean=1.091** bias=0.002 bootstrap_se=0.169
**Confidence interval (95%): [0.762 ... 1.090 ... 1.418]**

列表中数值的分布为 bootstrap 分布,其近似于理论抽样分布。一般来说,它以样本(而不是总体)中的统计值为中心,允许有小的偏差。绘制它并检查它是否近似正常总是一个好主意。接下来,我们计算非参数 bootstrap 百分位置信区间。也就是说,选择在 bootstrap 分布下包含您的置信水平所需区域的两个分位数。

参数结果和自举结果都非常接近。但是,请注意,参数化方法是专门为这个问题定制的,而自举完全是通用的。例如,如果我们需要估计方差或任何其他自定义度量的差异,会发生什么?对于参数方法,我们必须寻找一组不同的方程(如果它们存在的话)。相反,引导只需要对代码进行少量更新。下一节将通过另一个例子精确地描述这些变化。

例 2:两家公司的工资比较

假设我们想比较两家竞争公司的薪酬分配。为他们中的任何一个工作都很有吸引力,作为一个工作前景,除了报酬之外,没有任何明显的区别。不幸的是,他们没有透露这类信息,但是我们设法弄到了两个随机样品:

图 6:从公司 A 和公司 b 中随机抽取的月薪样本。

第一个问题是:“两种方法如何相互比较?”传统和自举方法都可以解决这一步,结果是:

Difference=-77.982
Confidence interval (95%): [-460.342, 304.377]

通过自举:

图 7:均值差异的 Bootstrap 分布。图片作者。

n1=75 n2=150 iterations=10000
sample_fn=-77.982 **bootstrap_mean=-78.844** bias=0.862 bootstrap_se=191.647
**Confidence interval (95%): [-454.325 ... -78.545 ... 296.170]**

请注意,置信区间从-454.325 到+296.170,因此它包含 0。因此,我们不能忽视手段之间没有区别的可能性。这个事实引出了一个有趣的话题:如何在假设检验中使用 bootstrapping,我们将在本系列的最后一篇文章中讨论。

现在我们想更进一步。作为经验丰富的数据科学家,我们有充分的信心在公司阶梯的前 30%找到一个位置。因此,我们想把我们的分析范围缩小到收入最高的四分之一人群。在这一点上,没有“传统的”参数化方法可以求助,所以我们应用 bootstrapping。如上所述,除了计算统计数据的函数之外,我们可以方便地重用所有代码。在这种情况下,我们写一个新的来得到高于第 70 个百分位数的平均工资的差异:

图 8:第 70 百分位以上均值差异的 Bootstrap 分布。图片作者。

n1=75 n2=150 iterations=10000
sample_fn=680.252 **bootstrap_mean=676.566** bias=3.686 bootstrap_se=256.013
**Confidence interval (95%): [161.172 ... 683.415 ... 1164.408]**

所以我们有理由确信(95%的信心)T4 公司 A 支付给他们前 30%的员工比 B 多。对于给定的样本,该差异估计为每月 683。

为了仔细检查,让我在下面包括我用来生成样本的实际分布。两者都刻意远离正常,均值相等(差正好为 0)。然而,30%以上(约 1,000)的工资差别很大。所以置信区间足够好了!

图 9:A 公司和 b 公司的月工资分布,均值差为 0,30%以上的工资均值差约为 1000。图片作者。

最后的话

Bootstrapping 是一种优雅的方法,它允许我们在没有任何理论框架(如果存在的话)的先验知识的情况下,轻松地构建自定义指标并比较总体。我们评估一个特征(或在这种情况下的特征比较),并以置信区间的形式评估它的可靠性。当问题变得越来越复杂时,参数方程通常会变得更加复杂,并且需要更多的假设。然而,自举算法保持不变,只需要针对特定问题进行微小的调整。这就是这种方法的优雅和方便之处。

感谢您的阅读,敬请期待第三部分!

参考

[1]埃夫龙,B. (1979 年)。自举方法:再看折刀统计年鉴,1–26。

[2]埃夫龙,b .,蒂布拉尼,r .,,蒂布拉尼,R. J. (1994 年)。自举简介。查普曼&霍尔/CRC。

[3]戴维森和欣克利(1997 年)。 Bootstrap 方法及其应用(统计与概率数学中的剑桥系列)。剑桥:剑桥大学出版社。

[4]哥伦比亚特区蒙哥马利和佐治亚州龙格(2013 年)。工程师应用统计与概率。约翰·威利的儿子们。

[5]摩尔博士、麦凯布博士和克雷格学士(2014 年)。统计学实践入门。第八版。纽约:麦克米伦高等教育公司 W.H. Freeman and Company。

脑-机接口导论

原文:https://towardsdatascience.com/introduction-to-brain-computer-interfaces-d05d533e3543?source=collection_archive---------29-----------------------

当科幻电影中的技术变成现实

杰西·马丁尼在 Unsplash 上的照片

人脑和计算机(或一般机器)的连接听起来像科幻小说——像来自乌托邦(或反乌托邦)未来的技术。然而,现代脑机接口(或 BCI)的发展始于大约 100 年前,当时汉斯·伯杰发现了人类大脑的电活动,并通过一种后来被称为脑电图(简称 EEG)的方法测量了这些信号。如今,脑机接口已经有了许多不同的应用,但我们才刚刚起步,在不久的将来可能会看到一些令人印象深刻的进步。

在讨论脑机接口的当前应用以及对其未来用途的一些猜测之前,我们将首先介绍不同的“读心术”,或者更科学地说,测量大脑活动的方法。最后,我们将讨论与 BCIs 相关的伦理问题。

脑机接口

首先:不,目前不可能读懂人们的想法——至少不能直接读懂。然而,我们能做的,是测量人们的大脑活动。我们可以从收集的数据中获得信息,例如对环境中事件的反应或意图,如有计划的运动。数据的分析取决于所收集的大脑活动的类型。

脑-机接口可以分为三类:侵入式、部分侵入式和非侵入式脑-机接口。虽然侵入性和部分侵入性 BCI 需要某种手术,但我们将重点关注非侵入性 BCI,因为它们更容易建立,更便宜,并且具有不需要手术的明显优势。(尽管也有令人震惊的侵入性 BCI 的例子——比如埃隆·马斯克的 Neuralink 训练一只猴子玩 pong)。

量化大脑活动最常见的方法是测量头皮上由大脑神经活动产生的电信号。这被称为 脑电图脑电图,更具体地说是测量电极和参考之间的电压。

与脑电图类似的是 EOG ( 眼电描记术),它使用放置在眼睛周围的电极来测量不同点之间的电压。由于眼睛前后之间的电势,测量电压的变化可以用来计算和跟踪眼睛的运动。

其他测量大脑活动的方法是所谓的 fNIRS ( 功能近红外光谱)和 fMRI ( 功能磁共振成像),它们分别测量血液动力学活动和血流量,这两种方法都源于神经活动。

不同的技术有不同的优缺点。虽然 fMRI 具有高空间分辨率,但是记录单个样本需要几秒钟,并且 MRI 扫描仪(非常)大并且(非常)昂贵。相比之下,EEG、EOG 和 fNIRS 设备的空间分辨率较低(取决于电极/光极的数量),仅测量头皮上的活动,但采样频率较高,便于携带且便宜得多。

大多数现代脑机接口是基于脑电图的,但也可以找到脑电图和 EOG 或脑电图和 fNIRS 的组合。

归根结底,上述两种方法都不是在测量神经活动,而是某种(嘈杂的)代理,如电极之间的电位,这种电位受到环境背景噪声的影响。

脑机接口系统的应用

尽管记录脑电图已有很长的历史,但对它们的有效分析却远非简单明了。分析 EEG 数据的一种常见方法是调查特定大脑区域中某些频带的功率谱密度。然而,这只能在相当低的水平上解释大脑活动。从技术上来说,这意味着更容易测量注意力的水平,但很难(如果不是不可能的话)区分某人是否在想颜色红色蓝色。(脑电图分析的基础,如事件相关电位、频带或常见空间模式将是未来文章的主题)。我们目前从脑电图记录中获得的这种水平的见解指出了应用的方向。

在医学上的应用

脑电图的一个可能的应用是基于我们可以测量人类大脑中意识状态变化的想法。这允许在外科手术过程中监控镇静/麻醉的水平。

癫痫发作、睡眠障碍、帕金森病或其他疾病的诊断通常基于对 EEG 的分析(通过专家或基于人工智能的系统)。

此外,脑电图经常用于康复(特别是与虚拟现实或假体相关),目的是通过神经可塑性恢复运动功能。

除了诊断和康复,脑电图在医学上的用途是多方面的,甚至通过听觉诱发电位来评估听觉系统的功能。

其他应用

在实验室和诊所之外,脑机接口越来越受欢迎,但消费级脑机接口的应用目前相当有限。

测量意识状态不仅与医学相关。有一些脑机接口可以通过监控用户的注意力来促进冥想。类似的系统可能会在交通和教育等领域引起人们的兴趣,因为司机和学生也需要集中注意力。

在未来,消费级 BCI 可以成为各个领域的游戏改变者。在市场营销中,营销人员将获得消费者的直接反应,并据此调整他们的策略和产品。通过与物联网设备连接,BCIs 可以创建下一代智能环境,包括家庭、工作和交通。与 VR 结合,电脑游戏会更加身临其境,更加直观。BCI 有可能实现无缝身份认证,并改变我们对安全性的理解。最后,BCIs 将彻底改变人类和机器之间的连接,更具体地说是 cobots(协作机器人)。

从负面来看,技术发展可能会允许反乌托邦小说中的(军事)用例。

伦理问题

上面我们专门解决了记录大脑活动的非侵入式单向脑机接口。然而,从中长期来看,我们可能会看到脑机接口允许信号以相反的方式传播——从计算机到人脑。在这一点上,精神控制成为一个需要考虑的紧迫的伦理问题。虽然还不清楚自由意志是什么意思,也不知道它是否存在于物理层面,但在人类的情感和运动被计算机控制后,这个概念需要重新思考。通过脑深部刺激,BCI 使用者的大脑以及随后的个性可能会发生变化。

但是,即使在这两种方式都有可能实现之前,在某种程度上,从远处测量大脑活动是可能的,这将有效地允许读心术和一些严重侵犯隐私的行为。一首著名的德国歌曲说“思想是自由的”——让我们希望这在未来依然如此。

结论

尽管我们还远远没有普及消费级脑机接口,并且存在一些严重的社会问题(正如每一项新技术一样),但我们可能会在不久的将来看到一些令人惊叹的、有益的和积极的发明,这些发明可以改善许多人的生活。

脑机接口是一个活跃的研究领域,有着惊人的发展和对社会的严重机遇和威胁。我们正处在一个十字路口,需要确保技术被用于好的方面(无论这对你意味着什么)。

与 AGI 类似,我个人认为,分散的研发是避免滥用 BCIs 的关键。意识到这一点后,我转行开发脑机接口。你会怎么做?

因果推理导论(第一部分)

原文:https://towardsdatascience.com/introduction-to-causal-inference-part-1-d65f2e1ab89?source=collection_archive---------10-----------------------

在这里,我们讨论因果推断的一些基本概念,以形成对测量治疗效果的基本理解,理解什么是 SUTVA、科学表和其他概念。

Bradyn Trollip 在 Unsplash 上拍摄的照片

在我们有大量虚假“发现”的现代世界,理解因果推理机制变得越来越重要。媒体推测不同药物、饮食和生活方式的有效性。问题是,在许多课题上都有不错的研究,但人们通常不理解它们,因为它们是用对其他科学家来说乏味的语言写的。我希望这篇文章能帮助你学习和理解因果推理的一些基本概念,从而更好地理解科学研究,不被媒体上的虚假“发现”所误导。

我将把这篇文章分成两部分,因为主题相当广泛。这是第一部分,我们将讨论因果推理的主要范式、度量标准和基本问题。在第二部分中,我们将研究一些更高级的概念,这些概念建立在我们在这一部分中讨论的思想之上。你可以在这里找到《T4》第二部。

整个讨论都是从这个问题开始的:好吧,这到底是怎么回事?这门科学是关于什么的?
这里我们不是说现在数据科学家流行的预测、分类等问题。我们谈论的是实验和观察研究,其主要目标是找出应用于样本或人群的某种治疗的效果。你可以把这想象成医学试验:我们有两组,第一组的参与者服用新药(治疗组),另一组的参与者服用安慰剂(对照组)。我们的目标是了解新药的效果,并对其进行评估。然而,正如我们将在本文后面看到的,一些在数据科学中非常流行的概念,如线性和逻辑回归,在解决因果推理的基本问题时非常有用。

“经典范式”和“潜在结果框架”

有两种范式可用于分析研究数据:
经典范式着眼于潜在原因(如人们吸烟)和观察到的结果(如肺癌)之间的联系,并试图找出这种关系是否是因果关系。这里问的主要问题是:“要发现吸烟导致肺癌,我们应该知道些什么?”

潜在结果框架从不同的角度看待同一个问题。这个框架说的是每个单位有两种(简化情况下)潜在结果:治疗中的潜在结果 (Y(1)) 和不治疗或控制中的潜在结果 (Y(0))。这里的主要问题是:“如果一个人吸烟和不吸烟会有什么不同?”

经典范式主要基于关联,声称关联越强,潜在结果越可能,在我看来,这是解决因果推理问题的更可取的方式,尽管当我们谈论现实世界的观察研究时,这带来了一些困难。我们稍后会谈到它们。

也就是说,潜在结果框架声称所有的潜在结果都已经存在,我们只能选择我们想要观察的结果。这显示在下面的科学表格中,该表格是由姜懿翔·鲁宾在鲁宾(1978)“因果效应的贝叶斯推断:随机化的作用”中介绍的。

科学表格示例

D. Rubin 自己也很好地描述了这种表的价值:“所有潜在可观察值的明确表示导致大量的符号,但一旦建立,符号允许几乎立即得出重要的结论”。

基本上,科学表描述了以下列方式收集的整个数据集:

  • 单位:单位或单位组的索引(用于更大的研究)
  • 协变量:这些都是治疗前的参数,我们可以在治疗前观察到,并可以用来调整我们的研究设计(为了简单起见,上图中只显示了一个协变量)
  • 处理:表示哪些单元被处理(1)以及哪些单元在对照组中(0)
  • 潜在结果:Y(1)是每个单位的潜在结果向量,如果他们接受治疗,Y(0)-如果他们在对照组。实际上,我们并不知道这两种价值观
  • 观察到的:那是我们在实验中观察到的实际值。它等于一个潜在的结果,取决于他们是否得到治疗或得到控制。

сausal estimands 和因果推理的基本问题

因此,当我们知道如何描述从研究中收集的数据时,是时候计算一些指标了。因果推断的目标是计算治疗效果。简单地说——我们想知道治疗对人群/样本/亚群的影响有多大。这有助于我们理解基本的因果关系,并基于这种理解做出决定。

例如,这些估计值在临床试验中用于确定一种新药是否有效。在此基础上,当局决定是否允许这种药物上市。

因此,这些指标都非常相似,只是衡量对象不同(总体/样本/亚组)。所有这些计算起来都相当简单,基本上对每个单位的因果效应的处理是:

一级方程式赛车。一个单位的处理效果。

然而,因果推理的基本问题变得更加复杂,尤其是潜在结果框架,因为我们不知道同一个单元的两个潜在结果。我们只知道其中的一个——被观察到的那个。

这个问题基本上有两种可能的解决方案:

  1. 科学的解决方案。这里,我们利用我们对环境的先验知识来推断另一个潜在的结果(我们没有观察到的)。我们还可以实现一些假设,使因果推理合法,如:
  • T 时间稳定性—Y(0)的值不取决于何时将该单元放入控制组。基本上单位时间稳定。
  • 因果短暂性— Y(1)不受单元优先受控(Y(0))这一事实的影响。这样就可以在治疗组和对照组之间转换单位。
  • 单位齐性—Yi(1)= Yi '(1),Yi(0) = Yi'(0)的值。这意味着,对于具有相同解释变量(协变量)的单元,所有潜在结果的期望值是相同的。

2.统计解决方案。当其他潜在的结果即使在这些假设下也不明显时,我们使用基于以下技术的“欺骗”统计方法:利用总体。相同的单元可以在不同的时间点进行不同的处理,或者不同的单元可以同时进行不同的处理。使用这些我们可以做以下的技巧:

  • 找到另一个治疗组中一个单位的近似替代物,如果它在协变量方面与我们正在比较的单位相等,则使用它。然后我们可以用公式 1 计算个体治疗效果。
  • 估计平均因果效应对样本或总体中的单位进行平均。

方程式 2。平均治疗效果的估计。

以下是计算平均治疗效果的主要指标:

  1. 样本平均处理效果(状态):

方程式 3。安全

2.条件平均治疗效果 (CATE)。它本质上与 SATE 相同,但以单位的协变量为条件。对它们的调节使得子群 n_x:

方程式 4。美食

3.人群平均治疗效果 (PATE)。同样的事情,但对于整个人口 N:

方程式 5。佩特

它来了。因果推断的一个基本问题是计算在不同的环境中,在不同的限制条件下,在不同的单位分布下的平均治疗效果,但主要问题是——我们不知道相同单位的两种潜在结果。

估计平均治疗效果的方法之一是使用回归。事实证明,我们可以建立一个回归模型,使其中一个系数的估计值等于治疗效果的估计值。此外,当存在明显的单位组(如性别、年龄、地理集群、不同职业等)时,这被证明是对协变量进行调整的好方法。),它们的混合将对治疗效果估计产生一些额外的偏差。我们将在文章的第二部分讨论这些技术。

在文章的这一部分,我想强调的最后一点也是一个基本假设,它对于计算这些影响是必要的,并且在许多其他方面也是有用的。称为稳定单位治疗值假设(SUTVA) 。它由两部分组成:

  1. “不干涉”的假设。简而言之,这意味着研究中任何单位的潜在结果都不会受到应用于该研究中其他单位的治疗的影响。
    这个假设不成立的情况的一个例子:一对夫妇中的一方接种了疫苗,这个决定可以影响另一方的决定。
  2. “没有多种治疗方案”的假设。基本上,它是说无论一个单位如何得到一个待遇,潜在的结果 Y(1)都是一样的。
    这个假设不成立的情况的一个例子:当一个人得到一种注射形式的药物而不是一种药丸时,他/她将得到更快和更强的效果,因为药物直接进入血液。

总结一下我们深入因果推理的第一部分,我想鼓励你花些时间自己深入这个主题。因果推理是包括疫苗在内的所有现代发现的基础(理解疫苗的临床试验结果在 2020 年变得如此重要)。这门科学乍看起来似乎微不足道,而且在发现之初就认为这是我的错误。因果推理可以开阔你的眼界,让你了解科学研究的世界,并帮助你设计好自己的实验。

点击阅读第 2 部分继续探索!

因果推理导论(二)

原文:https://towardsdatascience.com/introduction-to-causal-inference-part-2-13dc0fe2eb90?source=collection_archive---------10-----------------------

我们继续讨论因果推理的基本概念。在这一部分中,我们涵盖了随机研究设计、因果推断中回归的使用以及观察性研究。

照片由 Lucas SantosUnsplash 上拍摄

这是文章的第二部分。如果你还没有读过《T4》的第一部分,我强烈推荐你去读一读,因为它们彼此紧密相连。在这一部分中,我将基于我们在第一部分中讨论的概念。

随机设计在因果推断中是一个非常有用的研究设计,它给我们一些假设的自由,从而使计算更容易。此外,当我们将讨论观察性研究时,我们会看到我们的目标是试图将它们框定为随机实验。因此,我们将暂时关注它们。通常,随机实验的设计由分配机制定义:

一级方程式赛车。随机实验中的分配机制

有几种随机研究设计:

  1. 伯努利试验。根据伯努利分布分配治疗。
  2. 完全随机实验,当所有单位的治疗概率相同,且治疗单位的数量固定时
  3. 成组和成对设计,本质上是通过“类型”分割单元的相同概念——减少了潜在结果推断的变化。

前两种分配机制不依赖于潜在的结果(这意味着它们是可忽略的不成立的)和单位特征。这给我们带来了无知的假设:

方程式 2。可忽略性假设

可忽略性为我们提供了各治疗组之间平衡的潜在结果,因此,通过比较治疗组和对照组的平均结果,我们得到了 SATE 和 PATE 的无偏估计。然而,由于它是随机化,我们有可能得到一个“不幸的分配”:

表 1。“不幸的任务”的例子

在这里,我们可以计算 SATE(平均治疗效果),我们将看到我们得到的估计是完全错误的。因为这是一个玩具示例,我们可以看到两种可能的结果,所以我们知道真实状态= 7.5。然而,在现实生活中,我们只会看到观察到的结果(表 1 中的 Yobs)。在此基础上,我们将计算出治疗组和对照组的平均观察结果之间的差异,等于 state =-5。这种估计状态与真实状态的巨大偏差来自“不幸的分配”,在这种情况下,这意味着我们通常将年轻的单元分配给治疗组,而将年长的单元分配给对照组,实际上我们可以看到年龄越大,潜在结果的数量越多。这给我们的估计带来了很大的偏差。

这个问题通过第三种类型的设计——模块化设计解决了。这种分配机制的关键思想是在已知的组(块)中随机化(可能不同)——在我们的例子中是不同年龄的组。这样的设计给我们提供了更少的“不吉利的任务”,并且在每个街区内仍然没有发现。对于每个区块,我们测量条件平均治疗效果(CATE)。

为了计算 SATE,我们基本上可以使用以下方法之一:

  • 计算 CATEs 的加权(单位数)平均值
  • 使用针对块调整的回归(我们将在本文后面讨论这种方法)。

最后,配对设计是封闭设计的夸张版本。这里我们有与处理中的单元数量一样多的块(!)组。这是很有代表性的,因为我们基本上试图重现每个单元的未观察到的潜在结果。然而,很明显,要为每个单位找到一个完全匹配的配对是不太可能的,除非它们中有几个(甚至全部)在协变量方面是相同的。

也有一些现实生活中的困难可以“打破”随机设计。其中最讨厌的就是单位的不服从。有一些技术可以消除不遵从的后果,例如意向治疗分析、治疗分析、符合方案分析。为了节省时间,我们不会在这里介绍它们,但是你可以自己阅读它们——它们非常简单。

现实生活中的另一个困难是缺少数据。它可以是缺失的治疗前变量值(协变量)或治疗后变量值(取决于治疗应用)或两者。通常,解决这个困难的简单方法是删除缺少变量值的单元。问题是它会“取消”随机化的好处。

因果推理中的回归

是时候把回归分析作为因果推理的重要工具之一了。在因果推断中,回归可用于以下目的:

  • 估计样本或总体的治疗效果
  • 调整背景变量(治疗前协变量)
  • 估算未观察到的潜在结果(并以不同的方式计算治疗效果)

在所有情况下,我们可以使用简单的最小二乘回归模型或贝叶斯回归。这种回归模型的最简单视图如公式 3 所示。

方程式 3。因果推理回归模型的一般观点

这里我们可以看到所有熟悉的变量:

  • Y_i —是我们试图预测的潜在结果
  • Z_i —是治疗值
  • X_i —是协变量(也可以有一个协变量矩阵)

有趣的是:在随机研究中,我们可以在给定数据上拟合回归模型后,将 tau 的估计值解释为治疗效果。字面上这么简单!

这里有一个特点我们应该记住。像在任何统计推断问题中一样,我们担心我们估计的不确定性。这就是为什么我们需要在这里使用其中一种方法:我们可以使用经典推理或贝叶斯推理(这也意味着使用适当的回归类型)。

  1. 经典推断依赖于抽样分布。如果我们有一些数据总体,我们可以从总体中抽取一些(甚至无限)样本。然后,我们对每个样本进行回归拟合,找到相应的τ估计值,并计算所有样本的平均τ估计值。这是我们的最新估计。这种方法的缺点是,当给定的人口非常少时,它不是非常有效,因为它基本上没有捕捉到组合的可能变化,因此也将偏差归因于我们的估计。
  2. 贝叶斯推理通过使用先验信息(分布)将其与样本数据相结合来解决小样本问题。当然,这产生了另一个问题——我们并不总是有先验分布。

在实践中,这两种类型通常是结合在一起的:我们试图利用先验信息和模拟额外样本的能力。

有趣的事实是,当我们使用随机治疗分配时,我们并不关心线性回归是否正确。随机化保证了 ate 的无偏估计,即使模型被错误地指定。

回归用法的另一个巨大好处是,将 X 包含到回归中基本上起到了调整各组单元之间不平衡的作用。也就是说,我们不需要像前面讨论的那样明确使用不同的设计作为阻塞或匹配对。

这里需要重点关注的一个重要方面是,我们在回归中仅包括治疗前的变量(即仅包括那些不受所应用治疗影响的变量)!

围绕选择最佳方法估计平均治疗效果的问题存在一些争论。将 ate 估计为回归系数 tau 的替代方法更简单:我们可以使用拟合的模型来预测未观察到的潜在结果,然后使用标准公式来计算 ATE(我们在文章的第一部分中讨论了它)。我们也可以应用贝叶斯方法来预测未观察到的结果几次(比如 1000 次)并计算 1000 个状态。对它们进行平均将为我们提供对 PATE 的估计。

观察研究

好了,现在我们已经讨论了随机实验的因果推断的基础。没那么难吧。因果推断部分的简单性是基于我们已经讨论过的所有假设和随机治疗分配的事实。然而,在现实世界中,如果我们仅仅局限于随机设计的实验,我们将无法研究来自观察的大量数据。事实上,许多发现,至少在它们的起源中,来自于对“自然地”(意思是没有特别的意图)出现的情况的观察。

因此,现在有了一些来自舒适的随机设计领域的讨论工具,我们将走出去到现实世界,并试图使用它们来估计一些对观察数据的因果影响。这可能是因果推理中最令人兴奋的部分,许多科学文章正是基于观察数据。

因此,现在,当我们不知道分配机制时,可忽略性假设不再有效,因此我们不能保证在治疗组之间实现平衡,我们也不能直接估计治疗效果。现在很难确定两组单位之间观察到的差异是由于某种“处理”还是由于某种系统差异(不平衡)。

所有这些问题的解决方案是试图组织观察性研究的数据,以模仿近似的随机研究,然后用我们现有的仪器进行正常的分析。

观察性研究的主要假设是,本研究中的分配机制是有条件忽略的:

方程式 4。观察性研究的分配机制公式

方程式 5。观察性研究的条件忽略性

换句话说,假设说,如果我们有定义观察结果(满足公式 4)的所有协变量,并且我们以它们为条件,那么我们可以假设一些正确的指定模型可以正确地预测未观察到的结果并估计治疗效果。

违反条件可忽略性假设意味着以下问题:

  • 隐藏的偏见
  • 省略变量偏差
  • 不可测混杂

因此,这里有一个很好的工具来计算满足条件忽略的观察数据——倾向得分(由 Rosenbaum 和 Rubin (1983a,1984,1985)引入)。

P 平衡分数——是所谓平衡分数的变体。这个分数估计了一个单元在所有可用协变量 x 上被处理的概率。

方程式 6。倾向得分

这个想法是使用单位的倾向分数来调整观察数据的混淆。这就产生了一个平衡的数据集,我们可以用一个近似随机的设计来分析它。所以使用倾向分数的策略是:

  1. 将它们用作“阻塞”因素。这个想法是将那些具有最接近倾向分数的单元集合在一起。然后对每块 i 的单元计算 CATEI= YI(1)-YI(0)。对它们求平均值会给我们带来满足感。
  2. 我们还可以使用它们来检查数据在治疗组之间是否平衡。当来自治疗组的单位在所有方面都与来自对照组的单位非常不同时,可能会出现棘手的情况(这可以通过两个问题来表达:来自治疗组的单位在其倾向分数方面的分布缺乏重叠,以及它们在重叠部分中的分布不平衡)。在这种情况下,从这些数据中得出的任何推论都是不充分的。

情节一。数据问题的例子:不平衡和缺乏重叠

所以,现在简单来说,有一个很好的算法来处理观察研究,包括 5 个步骤:

  1. 设置设计。明智地选择潜在的结果、治疗、混杂因素(与治疗和结果相关的协变量)和预测因素(仅与结果相关的协变量)。了解你要估计什么样的治疗效果。(尽可能)深入了解分配机制是什么。
  2. 计算倾向得分。使用简单的逻辑回归来估计倾向得分,其中预测值是治疗值(Z ),预测值是混杂因素(X)。
  3. 使用从倾向得分中获得的信息预处理和设计数据:您可以在缺少重叠的地方使用分块或修剪数据等。我们还没有讨论使用倾向分数对设计的所有可能的调整,所以我鼓励你自己研究这个话题。
  4. 检查平衡和重叠,并检查从上一步获得的数据集总体上是否是随机实验的良好近似。如果您仍然发现数据集不平衡,或者缺少单位混杂分布的重叠,那么您应该再次执行步骤 3。
  5. 像随机设计一样评估治疗效果。

这些是因果推理的基本概念和机制。我们没有涵盖本文中的所有内容,但我试图涵盖阅读和理解科学出版物甚至建立自己的研究所必需的基础知识。我希望,现在当你在媒体上听到科学家发现吃某种东西会产生一些无意义的影响,或者当人们在讨论新疫苗试验的有效性时,你会带着相当程度的怀疑,并能够亲自检查最初的研究。这应该有助于你自己做决定。

使用 PyCaret 介绍 Python 中的集群

原文:https://towardsdatascience.com/introduction-to-clustering-in-python-with-pycaret-5d869b9714a3?source=collection_archive---------4-----------------------

一步一步,初学者友好的教程,使用 PyCaret 在 Python 中进行无监督聚类任务

Paola Galimberti 在 Unsplash 上拍摄的照片

1.介绍

PyCaret 是一个用 Python 编写的开源、低代码的机器学习库,可以自动化机器学习工作流。这是一个端到端的机器学习和模型管理工具,可以成倍地加快实验周期,提高您的工作效率。

与其他开源机器学习库相比,PyCaret 是一个替代的低代码库,可以用来用几行代码替换数百行代码。这使得实验快速有效。PyCaret 本质上是几个机器学习库和框架的 Python 包装器,比如 scikit-learn、XGBoost、LightGBM、CatBoost、spaCy、Optuna、Hyperopt、Ray 等等。

PyCaret 的设计和简单性受到了公民数据科学家这一新兴角色的启发,这是 Gartner 首先使用的术语。公民数据科学家是超级用户,他们可以执行简单和中等复杂的分析任务,这些任务在以前需要更多的技术专业知识。

想了解更多关于 PyCaret 的信息,可以查看官方网站或者 GitHub

2.教程目标

在本教程中,我们将学习:

  • 获取数据:如何从 PyCaret 资源库导入数据。
  • 设置环境:如何在 PyCaret 的无监督聚类模块中设置实验。
  • 创建模型:如何训练无监督聚类模型,并为训练数据集分配聚类标签以供进一步分析。
  • 出图模型:如何利用各种出图(肘、剪影、分布等)分析模型表现。).
  • 预测模型:如何根据训练好的模型,给新的、看不见的数据集分配聚类标签。
  • 保存/加载模型:如何保存/加载模型以备将来使用。

3.正在安装 PyCaret

安装很容易,只需几分钟。PyCaret 从 pip 的默认安装只安装在 requirements.txt 文件中列出的硬依赖项。

pip install pycaret

要安装完整版:

pip install pycaret[full]

4.什么是集群?

聚类是对一组对象进行分组的任务,使同一组(称为簇)中的对象彼此之间比其他组中的对象更相似。它是一种探索性的数据挖掘活动,是统计数据分析的常用技术,用于许多领域,包括机器学习、模式识别、图像分析、信息检索、生物信息学、数据压缩和计算机图形学。集群的一些常见实际使用案例有:

  • 根据购买历史或兴趣进行客户细分,以设计有针对性的营销活动。
  • 根据标签、主题和文档内容将文档分为多个类别。
  • 分析社会/生命科学实验的结果,以发现数据中的自然分组和模式。

5.PyCaret 中的聚类模块概述

PyCaret 的聚类模块 ( pycaret.clustering)是一个无监督的机器学习模块,它执行的任务是以这样一种方式对一组对象进行分组,即同一组(称为一个聚类)中的对象彼此之间比其他组中的对象更相似。

PyCaret 的集群模块提供了几个预处理特性,可以在通过setup函数初始化设置时进行配置。它有超过 8 个算法和几个图来分析结果。PyCaret 的聚类模块还实现了一个名为tune_model的独特功能,允许您调整聚类模型的超参数,以优化监督学习目标,如用于分类的AUC或用于回归的R2

6.教程的数据集

在本教程中,我们将使用来自 UCI 的名为 小鼠蛋白质表达 的数据集。数据集由 77 种蛋白质的表达水平组成,这些蛋白质在皮质的细胞核部分产生可检测的信号。该数据集包含每种蛋白质总共 1080 次测量。每次测量可以被认为是一个独立的样本(鼠标)。

数据集引用:

Higuera C,Gardiner KJ,CIO KJ(2015)自组织特征图确定了唐氏综合征小鼠模型中对学习至关重要的蛋白质。PLoS ONE 10(6): e0129126。[网页链接] journal.pone.0129126

您可以从这里找到的原始数据源https://archive.ics.uci.edu/ml/datasets/Mice+Protein+Expression下载数据,并使用 pandas (了解如何使用) 加载数据,或者您可以使用 PyCaret 的数据存储库使用get_data()函数加载数据(这将需要互联网连接)。

from pycaret.datasets import get_data
dataset = get_data('mice')

**# check the shape of data**
dataset.shape>>> (1080, 82)

为了演示对看不见的数据使用predict_model函数,从原始数据集中保留了 5% (54 条记录)的样本,用于实验结束时的预测。

data = dataset.sample(frac=0.95, random_state=786)
data_unseen = dataset.drop(data.index)

data.reset_index(drop=True, inplace=True)
data_unseen.reset_index(drop=True, inplace=True)

print('Data for Modeling: ' + str(data.shape))
print('Unseen Data For Predictions: ' + str(data_unseen.shape))**>>> Data for Modeling: (1026, 82)
>>> Unseen Data For Predictions: (54, 82)**

8.在 PyCaret 中设置环境

PyCaret 中的setup函数初始化环境,并为建模和部署创建转换管道。在 pycaret 中执行任何其他函数之前,必须调用setup。它只需要一个强制参数:熊猫数据帧。所有其他参数都是可选的,可用于定制预处理管道。

当执行setup时,PyCaret 的推理算法将根据某些属性自动推断出所有特征的数据类型。应该可以正确推断出数据类型,但情况并非总是如此。为了处理这个问题,一旦执行了setup,PyCaret 就会显示一个提示,要求确认数据类型。如果所有数据类型都正确,您可以按 enter 键或键入quit退出设置。

确保数据类型正确在 PyCaret 中非常重要,因为它会自动执行多个特定于类型的预处理任务,这些任务对于机器学习模型来说是必不可少的。

或者,您也可以使用setup中的numeric_featurescategorical_features参数来预定义数据类型。

from pycaret.clustering import *

exp_clu101 = setup(data, normalize = True, 
                   ignore_features = ['MouseID'],
                   session_id = 123)

成功执行设置后,它会显示信息网格,其中包含一些关于实验的重要信息。大部分信息与执行setup时构建的预处理流水线有关。这些特性的大部分超出了本教程的范围,但是,有一些重要的事情需要注意:

  • session_id: 一个伪随机数,作为种子分布在所有函数中,以便以后再现。如果没有通过session_id,则自动生成一个随机数,分配给所有函数。在本实验中,为了以后的再现性,将session_id设置为123
  • ****缺失值:当原始数据中存在缺失值时,显示为真。请注意,上面信息网格中的Missing ValuesTrue,因为数据中包含缺失值,对于数据集中的数字特征,使用mean自动估算,对于分类特征,使用constant自动估算。可使用setup功能中的numeric_imputationcategorical_imputation参数改变插补方法。
  • ****原始数据:显示数据集的原始形状。在这个实验中,( 1026,82)意味着 1026 个样本和 82 个特征。
  • ****转换数据:显示转换数据集的形状。请注意,原始数据集的形状(1026,82)被转换为(1026,91)。由于数据集中分类要素的编码,要素的数量有所增加。
  • ****数字特征:推断为数字的特征数量。在该数据集中,82 个要素中有 77 个被推断为数值型。
  • ****分类特征:被推断为分类的特征的数量。在该数据集中,82 个要素中有 5 个被推断为分类要素。还要注意,我们使用ignore_feature参数忽略了一个分类特征MouseID,因为它是每个样本的唯一标识符,我们不希望在模型训练期间考虑它。

请注意执行建模所必需的一些任务是如何自动处理的,例如缺失值插补、分类编码等。setup功能中的大多数参数是可选的,用于定制预处理流水线。这些参数超出了本教程的范围,但是我将在后面写更多关于它们的内容。

9.创建模型

在 PyCaret 中训练聚类模型很简单,类似于在 PyCaret 的监督学习模块中创建模型。使用create_model函数创建聚类模型。该函数返回一个经过训练的模型对象和一些非监督的指标。请参见下面的示例:

kmeans = create_model('kmeans')

print(kmeans)**>>> OUTPUT** KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
       n_clusters=4, n_init=10, n_jobs=-1, precompute_distances='deprecated',
       random_state=123, tol=0.0001, verbose=0)

我们已经使用create_model训练了一个无监督的 K-Means 模型。请注意,n_clusters参数被设置为4,这是您不向num_clusters参数传递值时的默认值。在下面的例子中,我们将创建一个有 6 个集群的kmodes模型。

kmodes = create_model('kmodes', num_clusters = 6)

print(kmodes)**>>> OUTPUT** KModes(cat_dissim=<function matching_dissim at 0x00000168B0B403A0>, init='Cao',
       max_iter=100, n_clusters=6, n_init=1, n_jobs=-1, random_state=123,
       verbose=0)

要查看模型库中可用模型的完整列表,请查阅文档或使用models功能。

models()

10.指定模型

现在我们已经训练了一个模型,我们可以通过使用assign_model函数将分类标签分配给我们的训练数据集(1026 个样本)。

kmean_results = assign_model(kmeans)
kmean_results.head()

注意,一个名为Cluster的新列被添加到原始数据集中。

请注意,结果还包括我们在setup期间实际删除的MouseID列。不要担心,它不用于模型训练,而是仅在调用assign_model时追加到数据集。

11.绘制模型

plot_model函数用于分析聚类模型。此函数接受一个经过训练的模型对象并返回一个绘图。

11.1 聚类 PCA 图

plot_model(kmeans)

分类标签会自动着色并显示在图例中。当您将鼠标悬停在数据点上时,您将看到默认情况下使用数据集第一列(在本例中为 MouseID)的附加要素。您可以通过传递参数feature来改变这一点,如果您想在图上打印标签,您也可以将label设置为True

11.2 弯管图

plot_model(kmeans, plot = 'elbow')

肘方法是一种解释和验证聚类内一致性分析的启发式方法,旨在帮助在数据集中找到适当数量的聚类。在本例中,上面的肘形图表明5是最佳的聚类数。

了解更多关于肘击剧情

11.3 轮廓图

plot_model(kmeans, plot = 'silhouette')

剪影是一种解释和验证数据簇一致性的方法。该技术提供了一个简洁的图形表示,显示每个对象的分类情况。换句话说,轮廓值是一个对象与其自己的簇(内聚)相比与其他簇(分离)有多相似的度量。

了解更多剪影剧情

11.4 分布图

plot_model(kmeans, plot = 'distribution')

分布图显示了每个簇的大小。将鼠标悬停在条形上方时,您将看到分配给每个聚类的样本数。从上面的例子中,我们可以观察到聚类 3 具有最高数量的样本。我们还可以使用distribution图来查看与任何其他数字或分类特征相关的聚类标签的分布。

plot_model(kmeans, plot = 'distribution', feature = 'class')

在上面的例子中,我们使用了class作为一个特征,所以每个条代表一个class,它用一个分类标签(右边的图例)着色。我们可以观察到t-SC-m类和c-SC-m类大多以Cluster 3类为主。我们也可以用同样的图来看任何连续特征的分布。

plot_model(kmeans, plot = 'distribution', feature = 'CaNA_N')

12.根据看不见的数据预测

predict_model函数用于将聚类标签分配给一个新的看不见的数据集。我们现在将使用我们训练好的kmeans模型来预测存储在data_unseen中的数据。该变量是在本教程开始时创建的,包含来自原始数据集的 54 个样本,这些样本从未暴露给 PyCaret。

unseen_predictions = predict_model(kmeans, data=data_unseen)
unseen_predictions.head()

13.保存模型

我们现在已经完成了实验,使用我们的kmeans模型来预测看不见的数据上的标签。

这使我们的实验接近尾声,但仍有一个问题要问:当你有更多的新数据要预测时,会发生什么?你必须再次经历整个实验吗?答案是否定的,PyCaret 的内置函数save_model允许您保存模型和整个转换管道以备后用。

save_model(kmeans,’Final KMeans Model 25Nov2020')

为了在将来的某一天在相同或不同的环境中加载已保存的模型,我们将使用 PyCaret 的load_model函数,然后轻松地将已保存的模型应用于新的未知数据进行预测。

saved_kmeans = load_model('Final KMeans Model 25Nov2020')
new_prediction = predict_model(saved_kmeans, data=data_unseen)
new_prediction.head()

14.总结/后续步骤?

我们只介绍了 PyCaret 的集群模块的基础知识。在下面的教程中,我们将更深入地探讨高级预处理技术,这些技术允许您完全定制您的机器学习管道,并且是任何数据科学家的必备知识。

感谢您阅读🙏

重要链接

教程py caret 新手?查看我们的官方笔记本!
📋社区创建的示例笔记本
📙博客投稿人的教程和文章。
📚文档py caret 的详细 API 文档
📺视频教程我们的视频教程来自各种赛事。
📢讨论有疑问?与社区和贡献者互动。
🛠️ 变更日志变更和版本历史。
🌳路线图 PyCaret 的软件和社区开发计划。

作者:

我写的是 PyCaret 及其在现实世界中的用例,如果你想自动得到通知,你可以在媒体LinkedInTwitter 上关注我。

人脑认知计算模型导论(上)

原文:https://towardsdatascience.com/introduction-to-cognitive-computational-modelling-of-human-brain-part-i-90c61e0e24c9?source=collection_archive---------25-----------------------

思想和理论

机器学习和认知任务

解剖功能磁共振成像的可视化(图片由作者提供)

材料

这是该系列的第一篇文章,即“腹侧颞叶皮层时空功能磁共振成像的认知计算模型”。如果你想了解整个系列,请点击下面的链接。

我将介绍认知计算建模的话题及其在大脑解码研究中的用例。让我们开始吧。

所有相关资料都放在我的 Github 页面上。别忘了去看看。如果你是一个纸质爱好者,你可以阅读这一系列文章的纸质版,也可以在我的回购中找到。

https://github.com/cankocagil/Cognitive-Computational-Modelling-for-Spatio-Temporal-fMRI-in-Ventral-Temporal-Cortex

人类大脑中的腹侧颞叶皮层对来自自然的视觉刺激的不同表示具有选择性,腹侧物体视觉通路产生分布式和重叠的神经反应[21]。进行单细胞研究以证明非人灵长类动物腹侧颞叶皮层中单个神经元的差异调谐对不同种类的对象具有选择性,并形成代表性特征[6,21]。然而,它们的选择性顺序对于更高程度的对象表示是不可概括和可扩展的[8]。为了模拟腹侧皮层的神经结构,开发了统计算法,但是通路中的不确定性仍然存在。关于神经成像的最新进展表明,人类感知、记忆和思维的时空解码可以通过功能性磁共振成像(fMRI)方法进行解码[11]。然而,由于时空分辨率的神经能力,fMRI 数据的复杂性和分布需要复杂的科学工具。随着机器学习的进步,神经科学家在大规模 fMRI 数据集中发现统计和结构模式,以解决神经科学背景下的各种任务。此外,深度学习的最新进展使研究人员能够解决未解决的神经科学任务[12],并具体展示了深度学习的重要性。在这项研究中,我们建立了端到端的发现机器学习管道,以解码人类受试者基于 fMRI 数据观看的视觉刺激的类别。我们利用最先进的解释性神经成像技术,如回波平面、感兴趣区域(RoI)、统计图、解剖和玻璃脑方法,来可视化和预分析 fMRI 样本的视觉结构。

我的实验是基于区块设计的 4-D 时间序列 fMRI 数据集,即 Haxby 数据集[7,15,8],来自对人脸和物体表征的研究。它由 6 名受试者组成,每名受试者 12 次[8]。在每一轮实验中,受试者被动地观看八个物体类别的灰度图像,这些物体被分成由休息时间分隔的 24s 块[8,7]。每个图像显示 500 毫秒,然后是 1500 毫秒的刺激间隔[7]。全脑 fMRI 数据以 2.5s 的体积重复时间记录,因此,刺激块被大约 9 个体积覆盖[8]。它由每个受试者的高分辨率解剖图像组成,除了第六个 4D fMRI 时间序列图像数据,其形状为 1452 个体积,具有 40×64×64 体素(对应于 3.5×3.75×3.75mm 的体素尺寸和 2.5 秒的体积重复时间)[8]。我们有 8 个不同的刺激类别,分别是剪刀、脸、猫、乱码、瓶子、椅子、鞋子和房子。静止状态的组块被消除,因为它不提供解码视觉刺激的额外信息[8]。

视觉刺激的例子(图片由作者提供)

在深入研究获取 Haxby 数据集及其探索性 fMRI 分析的 Python 代码之前,让我们先来看看整体分析的鸟瞰图,以及如何在神经解码的上下文中执行认知计算建模。

1.发现神经成像分析

作为发现神经成像分析,我们执行了最先进的解释性神经成像技术,如回波平面、感兴趣区域(RoI)、统计地图、解剖和玻璃脑方法,以可视化和预分析 fMRI 样本的视觉结构。我们将在本系列文章的第二部分进行深入讨论。

2.腹侧颞叶皮层的功能连接和相似性分析

我们执行了基于相关性、精确度和部分相关性的功能连接性分析,以及基于余弦、闵可夫斯基和欧几里德距离的相似性分析,以发现腹侧颞叶皮层中的重叠表示。

这在解释性 fMRI 分析中非常有用,因为它从统计和数学角度显示了人脑中分布的区域如何共享相似的特征。我们将在本系列文章的第三部分进行深入讨论。

3.人脑分布区域的流形学习与降维

对每个对象的腹侧时间掩模执行流形学习和维数减少方法,以提取时空掩模的潜在变量,这将有助于人脑的进一步解码。作为降维方法,我们应用了主成分分析(PCA)、线性判别分析(LDA)、独立成分分析(ICA)、非负矩阵分解(NNMF)和多维标度(MDS) 然后通过它们的 3D 可视化来比较这些获得的子空间。此外,我们执行流形学习算法提取掩盖腹侧颞区的潜在流形分布。我们执行了t-随机邻居嵌入(t-SNE)、一致流形近似和投影(UMAP)、ISOMAP、局部线性嵌入(LLE)和谱嵌入(SE) ,然后通过它们的 3D 可视化比较它们的低维流形,进一步帮助解码过程。

这将全面介绍理解人脑腹侧颞叶皮层的测地线关系。从人工智能的角度来看,这将是对无监督学习和人脑的交叉的深度回顾。我们将在本系列文章的第四部分进行深入讨论。

此时,我们只执行了发现分析来了解 fMRI 数据样本及其分布。接下来,我们将深入解码过程。

4.时空 fMRI 解码:ML 和 DL 算法

开发了端到端的机器学习算法,以根据腹侧颞叶皮层中的分布和重叠区域对刺激进行分类。准确地说,我们执行了以下机器学习算法:线性支持向量分类器(LinearSVC)、随机梯度下降分类器(SGDClassifier)、多层感知器(MLP)、感知器、逻辑回归、逻辑回归交叉验证、支持向量分类器(SVC)、校准分类器(用保序回归进行概率校准)、被动攻击分类器、标签传播分类器、随机森林分类器、梯度增强分类器、二次判别分类器、脊分类器交叉验证、脊分类器、AdaBoost 分类器、额外树分类器、K-邻居分类器、伯努利朴素贝叶斯分类器、高斯朴素贝叶斯分类器、Nu-支持向量分类器、最近质心分类器和 Bagging 分类器。作为稳健的集成解码,我们应用了正则化模型的新集成;FREM:L2 正则化 SVCs 的交叉验证集合,FREM:L2 正则化 Logistic 回归的交叉验证集合。我们通过利用不同视觉表示流之间的交互作用,进一步构建了认知神经网络,确切地说是具有 GELU 非线性的MLPs【10】、2D 和 3D 卷积神经网络。我们将在本系列文章的第五部分深入讨论,这将是本系列的最后一篇文章。

是的,那是巨大的。我知道,但是进行许多解码实验并比较它们的结果是至关重要的。不用担心,我们将在仅仅“两行”代码中实现几乎所有的 ML 算法。是的,我是认真的。我们将用两行代码实现几乎所有的算法。ML 工具的力量!

开始编码吧。在本文中,我们将只使用“nilearn”框架从 web 下载 Haxby 数据集,其中只有一行代码,该框架将在后面的系列文章中介绍,并探索数据集的结构。

首先,我们需要安装必要的 Python 包。打开您最喜欢的 Jupyter 笔记本,复制并粘贴以下代码进行必要的安装。

安装必要的 Python 包

然后,让我们导入我们将在这个过程中使用的所有必需的包。如果你想保存你的结果,创建一个名为“图像”和“结果”的文件夹,或者你可以删除下面的 66-67 行。

导入所有必需的 Python 包

我们准备开始了!请阅读下面的 docstring 以了解 Haxby 数据集,乍一看可能不容易理解,但不用担心。我们稍后会讨论更多。请注意,从网上下载数据大约需要 30 分钟,这取决于您的下载速度等。

感谢 Nilearn 从网络上获取 fMRI 数据

是的,我们下载了 fMRI 数据集。当你打印 haxby_dataset 时,你会看到这样一个屏幕。

我们简单讨论一下输出。上面有详细的描述,你也可以去参考 Haxby 数据集。还有

  • anat:fMRI 数据的解剖结构
  • func: Nifti 图像的 fMRI 数据(将被转换成 NumPy 矩阵)
  • session_target: Files 对应我们的目标变量(后面会讨论)
  • mask,mask_vt,mask_faces,…(提取腹侧颞叶皮层激活区域的不同空间掩模)

让我们潜入更深的地方。这里,我们打印受试者的 fMRI 数据的文件名。不要担心“nii.gz”格式。它只是 fMRI 数据的有效表示。我们将使用“ Nilearn ”库轻松解码这个扩展,并将其转换为 NumPy 数组。

本文到此为止。我们讲述了我们如何以及为什么构建时空计算技术来理解人脑。我们从网上下载了哈克斯比数据集。讨论了数据集。最后,简要回顾了数据集。恭喜你!你完成了第一篇文章,并通过认知计算方法对人脑解码迈出了一步。

在下一篇文章中,我们将使用最先进的神经成像方法来分析和可视化 fMRI 数据集。

文章链接

  1. 发表文章

https://cankocagil.medium.com/introduction-to-cognitive-computational-modelling-of-human-brain-part-i-90c61e0e24c9

https://cankocagil.medium.com/discovery-neuroimaging-analysis-part-ii-b2cdbdc6e6c3

https://cankocagil.medium.com/functional-connectivity-and-similarity-analysis-of-human-brain-part-iii-c427c88ca5bb

https://cankocagil.medium.com/unsupervised-representation-learning-on-distributed-regions-in-the-human-brain-part-iv-55fecf4e1b6f

2.在路上(即将推出…)

  1. 第五部分的占位符

进一步阅读

我在机器学习和神经科学方面的研究中使用了以下参考文献列表。我强烈建议复制粘贴参考资料,并简要回顾一下。

参考

[1]巴、基罗斯和辛顿。图层归一化,2016。

[2] L. Buitinck,G. Louppe,M. Blondel,F. Pedregosa,A. Mueller,O. Grisel,V. Niculae,P. Prettenhofer,A. Gramfort,J. Grobler,R. Layton,J. VanderPlas,a .乔利,B. Holt,10 和 G. Varoquaux。机器学习软件的 API 设计:scikit-learn 项目的经验。在 ECML PKDD 研讨会:数据挖掘和机器学习的语言,第 108–122 页,2013。

[3]褚,田,王,张,任,魏,夏,沈。双胞胎:重新审视《视觉变形金刚》中空间注意力的设计,2021。

[4] K .克拉默、o .德克、j .凯舍特、s .沙莱夫-施瓦兹和 y .辛格。在线被动攻击算法。2006.

[5] K. J .弗里斯顿。统计参数映射。1994.

[6]格罗斯、罗查-米兰达和本德。猕猴下颞皮质神经元的视觉特性。神经生理学杂志,35(1):96–111,1972。

[7] S. J .汉森、t .松坂和 J. V .哈克斯比。用于物体识别的腹侧颞叶组合编码。

[8]哈克斯比、戈比尼、富里、伊沙伊、斯豪滕和彼得里尼。《视觉物体识别》,2018。

[9]赫克曼、哈伊纳尔、贾巴尔、吕克特和哈默斯。结合标记传播和决策融合的自动解剖脑 mri 分割。神经影像,33(1):115–126,2006。

10d .亨德里克斯和 k .金佩尔。高斯误差线性单位(gelus),2020。

[11]黄少华,邵文伟,王明林,张德庆.人脑活动视觉信息的功能解码:简要综述。国际自动化和计算杂志,第 1-15 页,2021。

[12] R. Koster、M. J. Chadwick、Y. Chen、D. Berron、A. Banino、E. Duzel、D. Hassabis 和 D. Kumaran。海马系统内的大循环复发支持跨发作的信息整合。神经元,99(6):1342–1354,2018。

[13]马奥尔。勾股定理:4000 年的历史。普林斯顿大学出版社,2019。

[14] K. A. Norman、S. M. Polyn、G. J. Detre 和 J. V. Haxby 超越读心术:功能磁共振成像数据的多体素模式分析。认知科学趋势,10(9):424–430,2006。

[15]奥图尔、江、阿卜迪和哈克斯比。腹侧颞叶皮层中物体和面孔的部分分布表征。认知神经科学杂志,17(4):580–590,2005。

[16] F .佩德雷戈萨、g .瓦洛夸、a .格拉姆福特、v .米歇尔、b .蒂里翁、o .格里塞尔、m .布隆德尔、p .普雷登霍弗、r .魏斯、v .杜伯格、j .范德普拉斯、a .帕索斯、d .库尔纳波、m .布鲁彻、m .佩罗特和 e .杜切斯内。sci kit-learn:Python 中的机器学习。机器学习研究杂志,12:2825–2830,2011。

17 r . a .波尔德拉克。功能磁共振成像的感兴趣区域分析。社会认知和情感神经科学,2(1):67–70,2007。

[18] M. Poustchi-Amin、S. A. Mirowitz、J. J. Brown、R. C. McKinstry 和 T. Li。回波平面成像的原理和应用:普通放射科医师回顾。放射学,21(3):767–779,2001。

[19] R. P. Reddy,A. R. Mathulla 和 J. Rajeswaran。心理健康专家的观点采择和情绪传染的初步研究:移情的玻璃脑观点。印度心理医学杂志,0253717620973380,2021 页。

[20]史密斯、米勒、萨利米-科尔希迪、韦伯斯特、贝克曼、尼科尔斯、拉姆齐和伍尔利奇。功能磁共振成像的网络建模方法。神经影像,54(2):875–891,2011。

21 田中先生。下颞叶皮层和物体视觉。神经科学年度评论,19(1):109–139,1996。

[22] M. S .特雷德。Mvpa-light:一个多维数据的分类和回归工具箱。神经科学前沿,14:289,2020。

[23] M. P .范登赫维尔和 H. E .波尔。探索大脑网络:静息态功能磁共振成像功能连接综述。欧洲神经精神药理学,20(8):519–534,2010。

[24] G. Varoquaux,A. Gramfort,J. B. Poline 和 B. Thirion。大脑协方差选择:使用群体先验的更好的个体功能连接模型。arXiv 预印本 arXiv:1008.5071,2010。

[25] Y. Wang,J. Kang,P. B. Kemmer 和 Y. Guo。一种利用偏相关估计大规模脑网络功能连接的有效可靠的统计方法。神经科学前沿,10:123,2016。

26s . Wold、K. Esbensen 和 P. Geladi。主成分分析。化学计量学和智能实验室系统,2(1–3):37–52,1987。

27s . Wold、K. Esbensen 和 P. Geladi。主成分分析。化学计量学和智能实验室系统,2(1–3):37–52,1987。

康达虚拟环境简介

原文:https://towardsdatascience.com/introduction-to-conda-virtual-environments-eaea4ac84e28?source=collection_archive---------5-----------------------

照片由张秀坤·兰格Unsplash 拍摄

数据科学基础

Python 中的可再现数据科学项目

再现性是一个好的数据科学项目的重要特征。从设置随机种子、数据版本控制到使用虚拟环境,许多因素都有助于提高数据科学项目的可重复性。在这篇文章中,我们将看看用 Conda 管理 Python 虚拟环境的基础。

照片由迪帕克·纳特Unsplash 拍摄

1.稍微了解一下康达及其相关术语📖

在我们开始学习管理虚拟环境的命令之前,熟悉一些关于 Conda 的常用术语可能会有所帮助。

📍 1.1.康达 vs 迷你康达 vs 蟒蛇

Conda 是一个独立于语言的工具,用于包管理环境管理作为软件包管理器,康达可以安装、更新和删除软件包。作为环境管理员,it 可以管理虚拟环境。

Anaconda 是最流行的 Python 发行版(即将 Python 分发给像你我这样的最终用户的方式)。通过安装 Anaconda,你可以安装 Miniconda、 Anaconda Navigator (即一个图形用户界面)和精选软件包。

迷你巨蟒是巨蟒的迷你版本。它也是一个 Python 发行版。通过安装 Miniconda,你得到了 conda,Python 和少量的安装包。

正如我们所见, Conda 包含在 Anaconda 和 Miniconda 中。

📍 1.2.康达 vs Pip vs Venv

Pip 是 Python 的一个包管理器。

这意味着 Conda 和 Pip 都可以用来安装、更新和删除 Python 中的包。Pip 提供了在Python 包索引(PyPI) 上可用的更大范围的包,而 Conda 提供了在 its 频道上可用的相对较小范围的包。因此,有时某个包只能通过 Pip 安装。

Venv 是 Python 的环境管理器。

Conda 和 Venv 都擅长使用不同版本的包管理虚拟环境(即隔离和独立的环境)。然而,与 Venv 相比,Conda 的一个明显优势是易于管理多个 Python 版本。换句话说,Conda 使得使用不同版本的 Python 创建虚拟环境变得无缝。使用 Venv,我们将需要使用额外的工具来管理 Python 版本,或者在创建虚拟环境之前安装多个 Python 版本。

作者图片

2.使用 Conda 的虚拟环境💻

现在,让我们学习使用 Conda 管理虚拟环境的基础知识。我鼓励你在阅读的时候跟着电脑走,获得实践经验。

布鲁斯·杰斯特罗在 Unsplash 上拍摄的照片

📍 2.1.做好准备

如果您按照部分中的命令进行操作,请确保您的计算机通过 Anaconda 或 Miniconda 安装了 Conda(版本 4.6+)。

我们可以通过 Windows 上的 Anaconda 提示符和 Mac 上的终端访问 Conda。让我们首先按照以下说明为您的操作系统打开相关的命令行界面:

Windows: 按 Windows 键➡️键入 Anaconda 提示符➡️回车
MAC:按 cmd +空格键➡️键入终端➡️回车

现在,是时候创建虚拟环境了!

📍 2.2.创建虚拟环境

首先,让我们看看现有虚拟环境的列表:

$ conda env list # Option 1
$ conda info --envs # Option 2

我们有一个名为 base 的虚拟环境。当我们安装 Miniconda 或 Anaconda 时,它会创建一个名为 base 的默认环境。这就是我们在输出中看到的。

我们现在将学习创建虚拟环境的三种常用方法。

📍2.2.A .从 YAML 文件创建虚拟环境

创建虚拟环境的一种常见方式是从 YAML 文件:environment.ymlenvironment.yaml中创建。该文件包含虚拟环境的规范(例如,环境名称、包、它们的版本和 Python 版本)。你可以从这里这里看到一些 YAML 文件的例子。如果我们在当前工作目录中有这样的 YAML 文件,我们可以使用下面的命令之一从它创建一个虚拟环境:

$ conda env create -f environment.yml # Short form
$ conda env create --file environment.yml # Long form

现在,让我们再次查看虚拟环境列表:

$ conda env list

截断输出

我们现在有了一个新的 Conda 环境,称为测试。带有星号的环境表示我们所处的活动环境。这意味着我们仍然处于基础环境中。让我们激活新环境,并再次检查虚拟环境列表:

$ conda activate test
$ conda env list

截断输出

我们可以看到新虚拟环境旁边的星号: test 。我们还可以在命令行的开头看到()中的活动环境名称,如上面截图的左上角所示。

📍2.2.B .通过克隆创建虚拟环境

创建虚拟环境的另一种方法是克隆现有环境。使用以下命令,我们克隆了一个名为 test 的环境,并将该克隆命名为 testclone :

$ conda create -n testclone --clone test # Short form
$ conda create --name testclone --clone test # Long form

一旦创建了环境,我们就可以像以前一样激活新创建的环境。

📍2.2.C .使用命令构建虚拟环境

有时候我们需要自己营造环境。让我们使用 Python 版本 3.9.7 创建一个环境,并将其命名为另一个测试:

$ conda create -n anothertest python=3.9.7

出现提示时,键入y并按 enter 键继续创建。如果我们不想被提示,我们可以在命令中添加-y:

$ conda create -n anothertest python=3.9.7 -y

让我们激活环境并检查 Python 版本:

$ conda activate anothertest
$ python --version

我们可以确认新环境使用的是 Python 3.9.7。在创建 Conda 环境时,我们可以上下 Python 版本。例如,如果我的基本 Python 是 3.7.1,我可以用 Python 3.5.3 或 3.9.7 创建一个环境。如果我们没有指定 Python 版本:conda create -n anothertest -y,新环境将使用与基本 Python 相同的 Python 版本。

一次安装一个软件包会导致依赖冲突。Conda 的官方文档建议同时安装所有软件包,以便解决依赖冲突。因此,我们现在将一次安装多个软件包,而不是逐个安装。这里有一个例子:

$ conda install "numpy>=1.11" nltk==3.6.2 jupyter -y

下面是我们在安装软件包时指定版本的不同方法:

来源:康达备忘单(第 2 页)

如果我们不指定软件包的版本:conda install numpy nltk jupyter -y,Conda 将安装这些软件包的最新版本。

📍 2.3.康达频道

默认情况下,conda install会从它的defaults通道安装软件包。有时,某个包在此频道上不可用,但可能在其他 Conda 频道上可用,如由社区维护的热门频道conda-forge。我们可以使用以下命令检查当前通道:

$ conda config --show channels

要添加conda-forge频道并再次检查当前频道:

$ conda config --add channels conda-forge
$ conda config --show channels

我们可以看到一个额外的通道:conda-forge。这些频道的显示顺序显示了频道优先级。在这个例子中,conda-forge是高优先级信道。这意味着当我们运行conda install package_name时,Conda 将尝试从conda-forge通道安装一个包,如果它在conda-forge中不可用,它将尝试从defaults通道安装一个包。信道的这种变化不是特定于环境的,相反,它影响 Conda 的一般配置方式。如果你想删除一个conda-forge通道,你可以使用下面的命令:

$ conda config --remove channels conda-forge

如果我们不想添加一个通道,但仍想安装在另一个通道中可用但在defaults通道中不可用的软件包,我们可以使用以下替代命令从其他通道安装软件包:

$ conda install package_name -c conda-forge -y # Short form
$ conda install package_name --channel conda-forge -y # Long form

这不会改变通道配置,但会从该场合所需的通道(如本例中的conda-forge)安装软件包。

如果在 Conda 通道中没有可用的软件包,您可以使用pip install命令从活动环境中的 Pip 安装该软件包:

$ pip install package_name

现在是时候学习一些其他有用的命令来管理虚拟环境了。

📍 2.4.停用虚拟环境

使用完虚拟环境后,如果想要切换回基本环境,可以使用以下方法之一停用环境:

$ conda activate # Option 1
$ conda deactivate test # Option 2

📍 2.5.将环境规格导出到 YAML 文件

我们可以通过以下方式检查当前环境的规格:

$ conda list

这将显示环境细节,如使用的 Python 版本、安装的包名及其版本。要将当前环境的规范导出到当前目录下的 YAML 文件中,我们可以使用以下命令之一:

$ conda env export > environment.yml # Option 1
$ conda env export -f environment.yml # Option 2

📍 2.6.正在删除虚拟环境

现在让我们删除我们在本教程中创建的所有测试环境:

$ conda activate # Need to deactivate the environment first
$ conda env remove -n test
$ conda env remove -n testclone
$ conda env remove -n anothertest
$ conda env list

如果你用的是 Windows,我也建议你删除环境文件夹。如果你不确定在哪里可以找到这些文件夹,conda env list会显示位置。例如,文件夹在我电脑上的这个位置:

删除它之后,所有的测试环境都将被完全删除。现在轮到你为你的项目创建一个虚拟环境了!

照片由 AARN GIRIUnsplash 上拍摄

在这篇文章中,我们介绍了使用命令行的 Conda 虚拟环境的基础知识。如果您想探索,也可以使用 Anaconda Navigator 管理虚拟环境。如果你想了解更多关于康达的信息,这里有一篇由杰克·范德普拉斯撰写的关于“康达神话和误解”的深刻文章。

您想访问更多这样的内容吗?媒体会员可以无限制地访问媒体上的任何文章。如果您使用 我的推荐链接成为会员,您的一部分会费将直接用于支持我。

感谢您阅读我的文章。如果你感兴趣,这里有我其他一些帖子的链接:

◼️️ 面向数据科学的 Python 虚拟环境简介
◼️️ 面向数据科学的 Git 简介
◼️️ 贝叶斯定理讲解
◼️️ 比较随机森林与梯度推进
◼️️ 决策树是如何构建的?
◼️️ 管道、ColumnTransformer 和 FeatureUnion 说明
◼️️ FeatureUnion、ColumnTransformer &管道用于预处理文本数据

再见🏃 💨

D3.js 中的数据驱动形状简介

原文:https://towardsdatascience.com/introduction-to-data-driven-shapes-in-d3-js-8c169a3477b3?source=collection_archive---------21-----------------------

Unsplash 上由 Ira Mint 拍摄的照片

使用斐波纳契数列

作为一个虔诚的 python 爱好者,我很遗憾地避开了探索许多超出 Matplotlib、Seaborn 和 Plotly 等库范围的数据可视化工具。然而,当在这个可视化图库中仔细阅读 D3.js 的各种功能时,我非常兴奋能够尝试一下。

D3 是一个 JavaScript 库,支持高度可定制和交互式的基于 web 的数据可视化。它是“数据驱动文档”的缩写,它允许开发者基于数据创建和操作 web 文档。之前熟悉 HTML、CSS 和 JavaScript 会让 D3 更容易上手,但是只需要最基本的东西就可以制作简单的形状。本文将介绍 D3 的一些常见形状——包括矩形、圆形、椭圆形、线条和文本——它们的大小将基于斐波那契数列中的数字。这些仅仅是可以用 D3 代码轻松生成的多种类型形状的一个例子。

你需要什么

要开始在 D3 中进行可视化,您需要一个文本编辑器,比如 Atom ,来编辑您的代码。您还需要复制 D3.js 最新版本的内容,并将其粘贴到您的文本编辑器中的一个. js 文件中。除了 D3 文件,您还需要以下内容:

  • 一个 HTML 文件用于引用 CSS 和 JavaScript 文档并格式化网页的结构
  • 一个 CSS 文件用于格式化网页内容
  • D3 代码的一个 JavaScript 文件

我们现在将仔细看看这些文件的内容。

HTML 文件

HTML 文件允许您在浏览器中呈现在 D3 中创建的可视化效果。我们将使用的 HTML 代码非常简单:

第一行声明这是一个 HTML 文档,第二行指定文档的内容将使用英语。head 标签标记文档的 head 元素,其中包含元数据。当您在浏览器中打开 HTML 文档时,title 标签中的文本会呈现在浏览器选项卡中。

head 标签中接下来的两行分别引用 CSS 文件和 D3 版本 6 的内容。如果您选择对您引用的文件使用不同的名称,这些行中的名称需要更新。这同样适用于在文档主体中引用的“shapes.js”文件,该文件包含其所有可见的内容。最后,结束 html 标记标志着文档的结束。

CSS 文件

CSS 是一种样式表语言,处理网页中的颜色、字体和间距等功能。在这个简单的文件中,我们将页面的边距设置为零像素(元素周围没有空白),高度设置为 100%(较大的元素将填充页面,但不会超出其边界来呈现滚动条):

JavaScript 文件

“shapes.js”文件是我们放 D3 代码的地方,用来创建基于斐波那契数列的形状。这个数字序列从 0 和 1 开始,后面的每个数字都是前面两个数字的和。下面,我们定义一个变量“dataArray ”,该变量包含形状将基于的数据:

我们还将使用以下代码创建一个“svg”变量:

svg 代表“可缩放矢量图形”,这个 SVG 元素可以被认为是 D3 形状的空白画布。我们选择 HTML 文档的主体部分,并向其追加(即添加)一个 svg 元素。高度和宽度属性都设置为 100%,因此附加到该元素的形状将填充整个页面。

长方形

接下来,我们将添加一些矩形:

在这里,我们选择将被追加到 svg 元素的所有矩形,随后的属性控制它们的尺寸、颜色和在页面上的位置。将**.data(dataArray)** 链接到选区会将我们的斐波那契数据绑定到矩形。请注意,矩形的静态宽度为 50 像素,但其高度是动态的:

作者图片

这是因为高度是基于使用绑定到选择的“dataArray”的函数。函数定义中的“d”和“I”分别表示单个数据点及其在数组中的位置(索引)。您可以给这些参数起任何您喜欢的名字,函数仍然会有相同的输出。

该函数按顺序遍历数据数组。在上面你看到的最短、最左边的矩形中,高度是 1*15 或 15 像素。第二个矩形也是 15 像素高,第三个矩形是 30 像素,依此类推。数据数组还用于动态改变“x”和“y”属性,使矩形垂直居中,水平间隔均匀。您可以更改这些属性函数中的值,以观察矩形的位置如何变化。

接下来,我们将在页面上添加一些圆圈:

我们首先定义一个新变量“newX”,供以后在设置圆的水平位置的函数中使用。请注意,我们选择了页面上所有的“circle.first”元素。我们将“first”分配给 circles 的“class”属性,因为我们将向页面添加多组圆圈。创建类并指定特定类的元素可以消除对要选择的形状的任何混淆。圆的半径由“r”属性决定,是 3 和数组中每个数据点的乘积。

我们现在将添加第二组圆:

请注意,在下图中,银色圆圈的间距比紫色圆圈更近,序列中最初的圆圈半径略小,并且在页面上的垂直位置较低。这些差异由分配给“第一”和“第二”类圆属性的单独值(静态和动态)决定:

作者图片

椭圆

椭圆类似于圆,但它们没有单一的“r”属性,而是同时具有“rx”和“ry”属性:

这些属性允许您分别调整椭圆的水平和垂直半径。以下椭圆的静态垂直半径为 50 像素,动态水平半径为其在数据数组中对应值的三倍:

作者图片

尽管被分配了一个静态值,但在序列的后面的点上,垂直半径可能会减小。随着 x:y 比率的变化,水平半径的稳定增加产生了这种外观。

线

现在让我们来看一些添加行的代码:

下图显示了每个新属性的含义:

  • x1: 直线右端的水平位置
  • x2: 直线左端的水平位置
  • y1: 直线右端的垂直位置
  • y2: 直线左端的垂直位置
  • 笔画:线条的颜色
  • 线条宽度:线条的宽度

作者图片

因为 x2 和 y2 是静态的,你会注意到所有的线都是从一个点开始的,但是它们的长度和位置会根据它们被赋予的斐波那契值而改变。

文本

最后,我们来补充一些文字!

与其他形状一样,描边和描边宽度是指形状的轮廓颜色和宽度。“文本锚”属性允许您调整文本对齐方式,这里是页面的开始或左侧。的’。' text '行将数据数组中的每个数据点添加到文本中。下面,这段代码被重新使用,以包括页面上不同颜色和不同 y 位置的多行斐波纳契数列:

作者图片

结论

斐波纳契数列不是有意义的数据,但它有助于说明 D3 形状的大小、间距和其他属性如何根据数组中的数据动态更新。这篇文章甚至还没有触及 D3 所有可能的形状的表面,但是我希望它鼓励其他初学者和我一起探索这个强大的可视化库!

Singer.io 数据管道简介

原文:https://towardsdatascience.com/introduction-to-data-pipelines-with-singer-io-ca57969d2cb1?source=collection_archive---------16-----------------------

数据管道在各种数据平台中扮演着至关重要的角色,无论是预测分析还是商业智能,或者仅仅是各种异构数据存储之间的 ETL(提取—传输—加载)。它们都依赖于实时或批量接收数据,并进一步处理这些数据以获得见解和做出预测,或者只是总结和重塑数据以用于报告。让我们探索数据管道的解剖结构,以便更好地理解这个概念,然后我们将开始使用 Python 中称为 Singer 的开源 ETL 工具创建数据管道。

西格蒙德Unsplash 上拍照

什么是数据管道?

就像水管将水从水源输送到目的地一样,我们也使用数据管道将数据从一个源系统输送到目的地系统。使用数据管道的几种情况:

1)在异构数据存储之间同步数据。例如,将数据从 Oracle 数据库实例同步到 PostgreSQL 数据库实例。

2)在数据清理、整形、汇总等之后,将数据从暂存区移动到生产系统。例如,从各种网站收集的数据可以被收集在暂存区中,该暂存区然后以结构化的方式适合消费,然后被传送到数据库。

3)从中央数据源将分段数据分布到各个子系统。例如:由一个组织在 Google Sheets 中收集的各种产品的调查数据可能会被划分并广播给相应的产品团队进行处理。

数据管道的关键特征

1)数据频率:目标系统要求数据的速度,即定期小批量或实时。管道应该能够保持目标系统所需的数据传输频率。

2)弹性:数据管道的容错性和弹性如何,即如果管道因突然的数据加载或被忽略的代码错误而崩溃,数据不应丢失。

3)可扩展性:如果数据负载增加,用于开发数据管道的工具和技术必须能够重新配置数据管道,以扩展到更多的硬件节点。

什么是歌手

歌手的核心目标是成为“编写移动数据脚本的开源标准”。它涉及使用标准化脚本进行数据提取和接收,可以根据需要与各种源/目标混合和匹配。

歌手的核心特征

1)Tap——从中提取数据的数据源称为 Tap,Singer 网站上有现成的 Tap 可供使用,也可以创建自定义 Tap。

2)目标—从 Tap 获取数据的数据目标称为目标。与 Taps 一样,我们可以使用歌手网站上的现成目标,也可以创建自己的目标。

3)数据交换格式——在 singer 中,JSON (JavaScript 对象符号)格式被用作数据交换格式,使其与源/目标无关。

Taps 和目标很容易与基于 Unix 的管道操作符结合在一起,而不需要任何守护程序或复杂的插件。

5)它通过维护调用之间的状态来支持增量提取,即时间戳可以在调用之间存储在 JSON 文件中,以记录目标消耗数据的最后实例。

Singer 中数据管道的组件

我们可以根据我们的要求为歌手定制水龙头/水槽,或者只安装和使用歌手网站上已经有的水龙头/水槽。

用 Singer 构建数据管道

让我们创建一个数据管道,从 REST API 获取雇员记录,并使用 Singer 的 tap 和 sink 方法将它们插入 PostgreSQL 数据库表。

先决条件:Python 环境和 PostgreSQL 数据库实例。

由于 Singer.io 需要设置 tap 和 sink,我们将为两者创建单独的 virtualenvs,以避免版本冲突,因为它们中的每一个都可能依赖于不同的库。这被认为是与 Singer 合作的最佳实践。

设置 Tap: Rest API

在这个演示中,我们将创建自己的 Tap 来从 REST API 中获取雇员记录。

1)创建并激活虚拟

python3 -m venv ~/.virtualenvs/Singer.io_rest_tapsource ~/.virtualenvs/Singer.io_rest_tap/bin/activate

2)安装 Singer python 库

pip install singer-python

3)在您喜欢的编辑器中打开一个名为 tap_emp_api.py 的新文件,并添加以下代码

import singerimport urllib.requestimport json#Here is a dummy JSON Schema for the sample data passed by our REST API.schema = {‘properties’: {‘id’: {‘type’: ‘string’},‘employee_name’: {‘type’: ‘string’},‘employee_salary’: {‘type’: ‘string’},‘employee_age’: {‘type’: ‘string’},‘profile_image’: {‘type’: ‘string’}}}#Here we make the HTTP request and parse the responsewith urllib.request.urlopen(‘http://dummy.restapiexample.com/api/v1/employees') as response:emp_data = json.loads(response.read().decode(‘utf-8’))#next we call singer.write_schema which writes the schema of the employees streamsinger.write_schema(‘employees’, schema, ‘id’)#then we call singer.write_records to write the records to that streamsinger.write_records(‘employees’, records=emp_data[“data”])

设置目标:PostgreSQL

PostgreSQL 的一个目标已经在 Singer 网站上可用,所以我们将设置一个 virtualenv 来安装它。

1)创建并激活虚拟

python3 -m venv ~/.virtualenvs/Singer.io_postgres_targetsource ~/.virtualenvs/Singer.io_ postgres_target /bin/activate

2)安装 Singer python 库

pip install singer-target-postgres

3)接下来,我们需要在以下位置创建一个配置文件

~/。virtualenvs/singer . io _ postgres _ target/bin/target _ postgres _ config . JSON

使用 postgres 连接信息和目标 postgres 模式,如下所示:

{“postgres_host”: “localhost”,“postgres_port”: 5432,“postgres_database”: “singer_demo”,“postgres_username”: “postgres”,“postgres_password”: “postgres”,“postgres_schema”: “public”}

使用 Singer 数据管道

一旦我们设置了龙头和目标,就可以通过简单地敲击由壳体中的管道操作者分开的龙头和目标来使用管道,即

python ~/.virtualenvs/Singer.io_rest_tap/bin/tap_emp_api.py | ~/.virtualenvs/Singer.io_postgres_target/bin/target-postgres — config database_config.json

这就对了。根据我们为 Tap 创建的 database_config 文件和模式,从 API 获取的所有记录都将被插入到一个表中。很简单,不是吗?!

下一步是什么?

浏览 Singer.io 文档,根据您的使用案例尝试各种点击/目标组合,或者创建您自己的点击和目标。

您还可以探索数据管道编排工具,如气流Luigi ,它们也具有广泛的功能。

在我即将发布的帖子中,我会提供一些关于气流的有趣指南。直到那时..保持快乐的管道您的数据管道!

DataSecOps 简介

原文:https://towardsdatascience.com/introduction-to-datasecops-77ad9103d973?source=collection_archive---------27-----------------------

以及为什么它是数据民主化的推动者。

米卡·鲍梅斯特在 Unsplash 上的照片

在本文中,我将介绍 DataSecOps 的定义,以及它目前的主要原则。由于 DataSecOps 是一种非常令人兴奋的新思想,随着 DataSecOps 获得更多的经验和信息,这些原则将不可避免地发生变化。

数据概念的定义

让我们从 DataSecOps 的建议定义开始: DataSecOps 是一种灵活、全面、安全的嵌入式方法,用于协调不断变化的数据及其用户,旨在快速实现数据价值,同时保持数据的私密性、安全性和良好的管理。

让我们分解这个定义,以便理解数据概念的一些核心概念:

DataSecOps 是敏捷。如今,与数据相关的过程(即数据或其可访问性的变化)变得比过去更加频繁和重要,来自不同团队的许多用户访问相同的数据。因此,DataSecOps 必须是敏捷的,否则它将无法跟上数据发生的操作变化。

DataSecOps 是整体的。随着数据民主化过程使更多的用户和团队能够利用数据,这种转变也在组织中引入了大量的数据利益相关者。这些利益相关者包括数据所有者或管理者、许多不同的消费者(他们以不同的方式消费数据),当然还有组织内的利益相关者,如数据工程、安全、GRC、IT、隐私和法律团队(仅举几例)。如果一个组织中只有数据工程团队、安全团队或者两者都有 DataSecOps 的想法,那么这种方法是不够的。

DataSecOps 是一项集体运动,数据访问和操作周期中的每个人都应该有相同的思维模式。在许多公司中,这需要大量的团队来共享 DataSecOps 思维模式。

安全嵌入式方法意味着安全与所有数据项目和操作交织在一起。换句话说,安全不应仅仅通过数据项目结束时的安全检查或年度审计来实现。安全性需要成为重中之重,应该从设计开始就嵌入到项目中,甚至在项目完成后通过持续的监控继续下去。

当我们提到不断变化的数据及其用户时,我们指的是 DataSecOps 与以数据为中心的公司相关,在这些公司中,数据及其用户会经历很多变化。这些变化可能是新的数据源和生产者、丰富过程、数据转换和移动、平台变化等等。用户是数据消费者和生产者,他们需要定期更改他们的数据访问策略。

最后,从 DataSecOps 中获得的价值是一种平衡,组织及其团队可以从数据中快速获得价值,而不会损害隐私、安全性和治理。为了保证数据安全而延迟数据访问是无法实现数据安全的,因为这意味着延迟组织将数据转化为价值。我们需要找到能够让我们同时拥有这两者的流程和技术。

数据概念的原理

现在,让我们浏览一下 DataSecOps 的当前原则。

安全性是数据操作的一个连续部分,而不是事后的想法

当安全性是事后的想法时,它可能会导致不利的后果。例如,假设您有一个旨在与客户共享新数据的数据项目。如果安全性是事后才想到的,那么一旦修改您的方法变得非常昂贵,您可能会在过程的后期遇到安全性问题。您可能需要“回到绘图板”并替换您创建的一些基础结构或代码。

在 DataSecOps 思维模式的组织中,安全始终是数据操作和项目的一部分,安全部门积极参与此类项目的设计,以防止以后出现此类问题。此外,由于安全性是整个流程的一部分,如果确实出现了安全问题,可以在实施价格仍然较低的情况下立即处理。

比起临时项目,更喜欢连续的过程

由于当今的数据在快速变化,新的数据对象和用户非常频繁地涌现,围绕安全性、隐私和治理的临时数据项目往往很快就会过时。

例如,一年一次(甚至一个季度一次)执行的敏感数据发现项目,如果更改的频率比这高得多,就可能有风险。理想情况下,只要有可能,这样的项目应该被连续的过程所替代或者伴随着连续的过程。例如,使用 Satori 的软件可以在正在进行的过程中发现敏感数据。

环境、测试和自动化的分离

在应用程序开发和部署中,几乎没有听说过工程团队在没有适当的环境分离(这些环境通常被分为测试、试运行和生产)以及没有代码和配置变更的自动化测试的情况下工作。

不幸的是,这些实践并不总是发生在数据操作中。在许多情况下,根本没有环境分离,测试直接在生产环境中执行。此外,自动化测试通常不存在,特别是在安全性方面。

在 DataSecOps 思维模式的组织中,有一个带有相关安全配置的临时环境,并且测试是以连续的方式进行的。例如,通过这种方式,您可以测试特定角色或用户是否有权访问某些应该对其屏蔽的数据(例如 PII)。

优先级是关键:关注敏感数据

因为你可能没有你想要的所有资源,你需要优先分配资源、任务和项目。在数据方面,您应该优先考虑的几乎总是敏感数据,因为敏感数据的安全问题确实非常敏感。

确定敏感数据优先级的先决条件是了解敏感数据的位置及其内容(以便在敏感数据中确定优先级)。如果您不确定您的敏感数据在哪里,找出这些信息将是一个很好的起点。然后,探索您可以应用哪些措施来保护它,了解谁可以访问它,并知道他们的访问是否可以被撤销或限制(例如通过屏蔽敏感数据)。

数据应明确归谁所有

在处理数据时,清晰性非常重要,然而,在许多情况下,组织拥有没有明确所有权的数据对象。这些可能是老项目,要么是不活跃的,没有人“敢”移除,甚至是在不断使用,但缺乏明确所有权的项目。重要的是要了解谁拥有这些数据,尤其是如果它可能包含敏感数据,并删除垃圾数据或确保数据所有者清楚谁有权访问这些数据以及这些数据会发生什么(例如,如果其他项目和团队使用这些数据)。

简化且确定的数据访问

当我们谈到清晰的主题时,数据访问需要简化和确定。这意味着,如果某个用户或团队需要在特定条件下访问特定数据集(例如,临时只读访问),他们将获得与其他具有相同案例的人相同的答案,并获得相同的推理。如果答案总是否定的,那也没什么,但是建立一个清晰的允许访问数据的流程是必须的。

例如,如果敏感数据被屏蔽,数据科学家可以获得除特定数据集之外的所有数据的访问权限。如果可能的话,这种清晰的策略可以实现自动化,以支持自助式数据访问并简化数据访问(请记住,DataSecOps 的核心是快速实现价值)。

快速实现价值,而不影响安全性

最后一个原则是使组织成为“数据驱动的”,并允许数据民主化而不损害安全性。我们可以通过确保围绕数据访问有明确的政策和流程来实现这一理想,这样,当访问数据出现延迟时,它们是由于“正确的原因”(即很少发生的边缘情况,需要特别批准),而不是因为有一个漫长的手动流程,所有数据消费者都需要等待很长时间才能获得数据访问。

这种瓶颈可能是数据工程团队需要手动设置数据访问设置或复制不必要的数据。

DataSecOps 需要你!

DataSecOps 虽然还年轻,但却极其重要。如果您想成为 DataSecOps 的一员,请联系我以了解更多关于 DataSecOps 的信息以及您可以如何影响它。

Ben 是Satori的首席科学家,用 DataSecOps 精简数据访问和安全。

Datasette 简介:在一行代码中探索和发布您的数据

原文:https://towardsdatascience.com/introduction-to-datasette-explore-and-publish-your-data-in-one-line-of-code-cbdc40cb4583?source=collection_archive---------24-----------------------

现在,您可以与他人分享探索数据的乐趣了!

动机

您是否曾经想要在浏览器中浏览数据集或发布您的数据集,以便其他人可以浏览和下载您的数据?如果有,试试 Datasette。

下面是您的数据在使用 Datasette 发布后的网站外观。

作者 GIF

在深入研究这篇文章之前,您可以先尝试使用 Datasette】探索一下FiveThirtyEight 的仇恨犯罪数据集。

什么是 Datasette?

Datasette】是一个在网络浏览器中浏览数据并将其发布为交互式网站的工具。

要安装 Datasette,请键入:

pip install datasette

如果这对您不起作用,请在这里找到安装 Datasette】的其他方法。

要使用 Vega 可视化网站中的数据,请键入:

pip install datasette-vega

由于 Datasette 使用 sqlite,我们也将安装 sqlite-utils 来操作 SQLite 数据库。

pip install sqlite-utils

创建数据库和表

什么是数据库和表?数据库是表格形式的多条信息的集合。表格是行和列中特定数据记录的集合。

比如下图中,fivethirtyeight数据库可以有ahca_pollsairline-safety等多个表。

作者图片

让我们试着创建我们自己的数据库和表。我们将从创建一个名为test.db的空数据库开始:

$ touch test.db

举例来说,我们将从 Kaggle 下载学生考试成绩数据:

作者图片

然后将下载的 CSV 文件中的记录插入到student_performance表中。

$ sqlite-utils insert test.db student_performance \ StudentsPerformance.csv --csv

不错!现在,我们应该可以在输入时看到我们刚刚创建的表

$ sqlite-utils tables test.db --schema --table

输出:

table                schema
-------------------  --------------------------------------
student_performance  CREATE TABLE [student_performance] (
                        [gender] TEXT,
                        [race/ethnicity] TEXT,
                        [parental level of education] TEXT,
                        [lunch] TEXT,
                        [test preparation course] TEXT,
                        [math score] TEXT,
                        [reading score] TEXT,
                        [writing score] TEXT
                     )

在浏览器中浏览数据

现在,我们已经准备好对刚刚创建的数据库运行 Datasette 来研究数据了!类型:

$ datasette test.db

http://localhost:8001 上启动 web 服务器。单击该链接,您应该会看到如下内容:

作者图片

点击sudent_performance浏览student_performance表:

作者 GIF

在这个 web 服务器中,我们可以:

  • 浏览数据内容,包括排序和过滤。下面是使用 Facet 仅显示性别为女性的行的示例:

作者 GIF

  • 使用 Vega 可视化数据

作者图片

  • 编写自定义 SQL 查询

作者图片

  • 将数据保存为 CSV 或 JSON 文件:

作者图片

发布到 Heroku

Datasette 最好的特性之一是能够将本地数据发布到互联网上。你需要一个 Heroku 或谷歌云的托管账户。

由于 Heroku 使我们能够在云中免费运行应用程序,我们将使用 Heroku 来发布我们的数据。

从在 Heroku 创建账户开始。然后单击右上角的“新建”创建一个新应用程序:

作者图片

创建一个名为performance-in-exam的新应用:

作者图片

然后通过键入以下命令登录:

$ heroku login

我们准备使用 Datasette 将我们的数据发布到 Heroku!

$ datasette publish heroku test.db -n performance-in-exam \
--install datasette-vega

在上面的代码中:

  • -n指定部署时要使用的应用程序名称
  • --install指定要安装的附加软件包。我们添加了datasette-vega来在部署应用程序时安装datasette-vega包。

您应该会看到类似这样的内容:

[https://performance-in-exam.herokuapp.com/](https://performance-in-exam.herokuapp.com/) deployed to Heroku

现在你可以点击https://performance-in-exam . heroku app . com/test/student _ performance在你的浏览器中浏览数据!

定制您的网站

您还可以为网站上的元数据添加标题和“关于”标签。要添加标题和 about,请在命令中添加—-title--about:

$ datasette publish heroku test.db -n performance-in-exam \
--install datasette-vega \
--title "Students Performance in Exams" \
--about "This data set consists of the marks secured by the students in various subjects."

作者图片

应该有一个标题和描述被添加到您的网站!

如果我们想在数据库或表格中添加描述,我们可以将这些信息添加到metadata.json文件中:

然后将--metadata添加到命令中:

$ datasette publish heroku test.db -n performance-in-exam \
--install datasette-vega \
--metadata metadata.json

您的表将有一个新的标题、描述、许可和到数据源的链接!

作者图片

在这里找到你的metadata.json文件的更多选项。

我还可以用 Datasette 做什么?

Datasette 还允许通过使用插件来实现附加功能。以下是一些你可以尝试的很酷的插件:

使用地图浏览您的数据

dataset-cluster-map是一个dataset 插件,它检测具有latitudelongitude列的表格,并将其绘制在如下所示的地图上:

作者 GIF

试试 global-power-plants.datasettes.com 的插件

为您的页面添加安全性

datasete-auth-passwords是一个 datasete 插件,允许您使用如下密码进行身份验证。当你只希望某些用户访问私人数据时,这个插件是理想的。

作者 GIF

试试https://dataset-auth-passwords-demo . dataset . io上的插件

一次搜索所有可搜索的表格。

datasete-search-all是一个 datasete 插件,允许您一次搜索所有表格,如下所示:

作者 GIF

https://datasette.io/plugins/datasette-search-all 试用这个插件。

在这里找到其他 Datasette 插件

结论

恭喜你!您刚刚学习了如何在一行代码中使用 Datasette 来探索和发布数据。我鼓励你用自己的数据来尝试 Datasette。想象一下,如果你能与你的队友或关系分享探索你的数据的快乐,那该有多有趣!

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

DeepMind 的图形网络介绍

原文:https://towardsdatascience.com/introduction-to-deepminds-graph-nets-b389430476fd?source=collection_archive---------21-----------------------

图网核心组件的简要概述

Iza Gawrych 在 Unsplash 上拍摄的照片

2018 年 10 月,来自 DeepMind/Google、麻省理工学院和爱丁堡大学的 27 名研究人员组成的团队发表了一篇论文,题为: “关系归纳偏差、深度学习和图网络”

https://deepmind.com/research/open-source/graph-nets-library

本文的关键部分是“立场文件”和实际实现,因为它包括一个用于在 TensorFlow 和 Sonnet 中构建图形神经网络的库(Sonnet 是 DeepMind 在 TensorFlow 之上的神经网络库)。到目前为止,这篇论文已经被引用了近 1000 次,因此值得进一步研究。

https://github.com/deepmind/graph_nets

在本说明中,Mark Needham 和我将首先总结论文提出的关键理论论点,然后通过一个玩具示例来说明图形网络库。

TLDR : Graph-Nets 是 DeepMind 的低级图形神经网络模型和库,它提供了如此大的灵活性,几乎任何现有的 GNN 都可以使用 6 个核心函数来实现,并且可以扩展到时态图。

理论上…

该论文的前提如下:为了使 AI 获得类似人类的能力,它必须应用(CG),并且为了实现这一目标,它必须将其学习偏向于 结构化的 表示和计算。

组合概括的定义是:

从已知的构建模块中构建新的推理、预测和行为。

非正式地:一小组元素,比如单词,可以以无限的方式有效地组合,比如句子和一本书。人类有能力“无限使用有限的手段”。

那么,如何才能提高 AI 对于 CG 的能力呢?
我们通过前面提到的“将学习偏向结构化表示和计算……特别是在 上操作的系统”来做到这一点。或者更简洁地说:这篇论文的主题是,为了推进人工智能,我们需要转向对图形的学习。

本文通过定义“关系推理和“归纳偏差”将这种方法形式化如下:

"关系推理被定义为使用规则操纵实体和关系的结构化表示."

实体是具有属性的元素,因此节点,关系是它们之间的关系,而一个“规则是将实体和关系映射到其他实体和关系的函数。

**归纳偏差(或学习偏差)是一组假设,学习算法使用这些假设来预测它没有遇到的给定输入的输出。

一个例子是K-最近邻居* :假设/偏差是彼此靠近的事件倾向于属于同一类,并且在一开始就被确定。*

懒惰的程序员

然后,“关系归纳偏差”是指在学习过程中对实体之间的关系和交互施加约束(即假设/偏差)的归纳偏差。一个例子是多层感知器(MLP ),其中分级处理是一种关系归纳偏差。

是的,这听起来太棒了,但是我怎样才能把它用在实际的图表上呢?

好吧,这篇论文抱怨说, 缺少一个模型 ,该模型具有实体和关系的显式表示,以及找到计算它们的交互的规则的学习算法。
然后指出一般来说 是一种支持任意(成对)关系结构的表示,在图上的计算确实提供了很强的关系归纳偏向,比 RNN、CNN 等更优越。

就这样作者引入了“ 图网络【GN】的概念,定义为:

“GN 框架定义了一类用于关系推理和图形结构表示的函数”

总之,GN 框架有效地概括和扩展了现有的图形神经网络。GN 框架提供的关键扩展是它能够处理和预测图形序列,从而预测动态系统随时间的轨迹。理论上,打台球可以被建模为:

台球桌等刚体系统——图片摘自巴塔格利亚等人

GN 框架中的主要计算单元是“GN 块”,它是一个图到图* 模型,它将一个图作为输入,执行结构的计算,并返回一个图作为输出。*

GN 块——从巴塔格利亚等人中提取的图像

在代码中,这样的块由“ GraphsTuple ”表示。一个 GN 块由 6 个核心功能组成:

  • 3 个“更新”功能:每个节点、边和全局属性一个
  • 3 个“聚合”功能:聚合每个节点的边属性,聚合全局的边和节点属性

这种方法具有很大的灵活性,因此 GN 框架可以用来实现各种各样的架构。

实际上…

表示图结构数据的核心构件是 GraphsTuple 类。该对象代表一个或多个图 的 批次,所有网络模块将 GraphsTuple 的实例作为输入,并返回 GraphsTuple 作为输出。

这些图表是…

  • **有向(单向边),
  • **属性化(允许节点级、边级和图级特征),
  • **多图(多条边可以连接任意两个节点,允许有自边)。

为了创建一个 GraphsTuple,从而创建一个图,我们需要创建一个字典列表,其中包含关键字:globalsnodesedges,这些关键字代表各自的浮点值特征向量。

边列表senders表示,receivers由整数值节点索引表示。

我们也可以通过简单地从字典中省略关键字来加载没有特征的图。同样,简单集合可以表示为一个图,其中节点特征是集合的元素。在这种情况下,字典只包含一个键值对。

如何在图形网络中创建图形的示例:

*https://colab.research.google.com/drive/1J4a7ngAK744svL4_pYTZqln8nGmIkLJb?usp=sharing

图表中的这个图形可以显示如下:

GraphTuples 渲染,用 https://arrows.app 制作

图网库及应用

重申一下,GN 框架定义了一类函数,因此,Graph-Nets 库列出了 51 类函数。

这些可以分成三个主要部分。

  • 首先,核心模块graph-nets.modules给出,由 7 个组成。
  • 其次,为了构建定制的图形网络模块,需要部署[graph_nets.blocks](https://github.com/deepmind/graph_nets/blob/master/docs/contents.md)中的类
  • 最后,剩下的函数是效用函数。

我们将简要描述和说明两个模块的构造:GraphNetworkInteractionNetwork

如何实例化一个图形网络模块?

图形网络的实现基本上是使用[modules.GraphNetwork](https://github.com/deepmind/graph_nets/blob/master/docs/graph_nets.md)类完成的,它构造了核心 GN 块。
该配置可以为边缘节点全局获取三个可学习的子功能,并且是对 Sonnet 库和模块的调用。
这些可以是线性模块([snt.Linear](https://sonnet.readthedocs.io/en/latest/api.html#linear-modules))或多层感知器([snt.nets.MLP](https://sonnet.readthedocs.io/en/latest/api.html#mlp)),或者是十四行诗的循环模块中的 14 个类中的任何一个。

Sonnet 在后端提供的功能看起来确实很强大,为任何 GNN 的设计提供了很大的灵活性。

一旦创建了一个 GraphsTuple,正如我们前面所做的,剩下的工作就是创建一个 GraphNetwork 来指定这些函数,下面是一个例子:

OUTPUT_EDGE_SIZE = 6
OUTPUT_NODE_SIZE = 5
OUTPUT_GLOBAL_SIZE = 3graph_network = modules.GraphNetwork(
 edge_model_fn=lambda: snt.Linear(output_size=OUTPUT_EDGE_SIZE),
 node_model_fn=lambda: snt.Linear(output_size=OUTPUT_NODE_SIZE),
 global_model_fn=lambda: snt.Linear(output_size=OUTPUT_GLOBAL_SIZE))output_graphs = graph_network(graphs_tuple)

互动网络

“消息传递神经网络”的一个例子由[modules.InteractionNetwork](https://github.com/deepmind/graph_nets/blob/master/graph_nets/modules.py?q=class:InteractionNetwork)给出,它实现了巴塔格利亚等人的论文的工作:“用于学习关于对象、关系和物理的交互网络”。在这里,作者开发了一个模型,“它可以推理复杂系统中的对象如何交互”,对于这个模型,消息传递组件是至关重要的一部分。

同样,一旦构建了 GraphsTuple,它只需要指定十四行诗函数并传递 GraphsTuple,如下所示:

interact = modules.InteractionNetwork(
 edge_model_fn=lambda: snt.Linear(output_size=OUTPUT_EDGE_SIZE),
 node_model_fn=lambda: snt.Linear(output_size=OUTPUT_NODE_SIZE)
)interact_graph = interact(graphs_tuple)

这将返回一个带有更新的边和节点的 GraphsTuple,如下所示:

可以看出,节点和边特征得到了实质性的转化和扩展,为 交互网络模型 提供了基础。

作者还提供了许多可运行的例子作为笔记本

https://colab.research.google.com/github/deepmind/graph_nets/blob/master/graph_nets/demos/graph_nets_basics.ipynb [## 谷歌联合实验室

colab.research.google.com](https://colab.research.google.com/github/deepmind/graph_nets/blob/master/graph_nets/demos/graph_nets_basics.ipynb)

结论

Graph-Nets 是一个低级库,用于在 TensorFlow/Sonnet 中构建 GNN,它提供了很大的灵活性,允许实现大多数(如果不是所有)现有的 GNN 架构。

组成“GN 块”的能力允许动态系统上的图形序列和计算。

至于未来的工作,我们打算探索如何将 Graph-Nets 与 Neo4j 集成,并探索其他 GNN 库,如【jraph】Deep Graph Library 。*

表格 MC 强化学习简介—21 点示例

原文:https://towardsdatascience.com/introduction-to-direct-reinforcement-learning-by-example-3f69af9353b2?source=collection_archive---------19-----------------------

在经典的赌徒游戏中寻找最优策略

二十一点是一种受欢迎的赌博游戏,在世界各地被广泛玩。历史上被称为黑杰克和 Vingt-U,或 20 是一种游戏,据信起源于 17 世纪的欧洲。

强化学习是一门学科的高级术语,它寻求在不向学习者或代理人提供明确信息的情况下最大化某种回报,学习者或代理人必须与环境进行交互,以学习并产生可以推广到环境的规则或政策。

执行强化学习任务的方法之一是使用蒙特卡罗方法,在编程中,蒙特卡罗方法泛指在寻找最优解时需要随机化的任何方法。通俗地说,这意味着您正在创建一个相当于新生婴儿的代理,他们在开始时大多不知道它在做什么,他们的行为也可能是随机的。这些代理完全通过反复试验来学习。随着他们成功或失败,他们正在建立这个“经验法则”,或政策,他们将最终获得在每种情况下必须采取的行动的知识。在本文中,我们将使用最基本版本的 21 点来执行这种学习任务的最简单形式,而不使用许多赌场都有的规则变体。

(图 1)通过直接 RL 的强化学习,没有基于模型的规划(以虚线示出)

基于策略(基于策略的决策)的直接 RL 循环要求代理(学习者)知道它自己的状态和可用的动作。一个值可以绑定到状态或操作,也可以绑定到两者,如下例所示。学习者从一张白纸开始,并开始与环境互动,环境通常以奖励的形式提供体验。政策更新以反映奖励好坏的变化为标志,因此它将在未来制定更好的行动。为了简化示例,我们将不使用模型。

强化学习的一个重要步骤是找到一种方法来表示环境,这通常是说起来容易做起来难。然而,对于像 21 点这样的游戏来说,这是非常简单的。为了避免冗余,只显示了 Python 代码的关键部分。(完整代码此处提供)

首先,定义卡片的分布。为了使规则更简单,我们会草率地假设游戏实际上没有可用的 a(a 为 11),这在今天的大多数赌场中是不正确的。此外,从经验上讲,每次卡片用完时,都会装载一副牌,因此,这里的卡片数量假定是有限的,并且一直玩到结束。

第二,我们定义庄家,我们假设庄家严格按照自己手里的牌出牌,保持最少 15 张,足够短:

最后,这里的玩家(代理)必须定义有更多允许学习的组件:

这里的关键输入参数是:

  • ϵ:探索因素。范围从 0 到 1,决定其决策中随机成分的数量。
  • γ,γ:贴现因子。我们将使用一个 n 步(n=1)前瞻来添加比当前状态超前 1 步的状态的预期回报,乘以贴现因子。

播放器的重要初始化是:

  • 操作—代理可用的操作:点击或不予处理
  • states —所有精确的状态(总数= 380):(玩家的手牌总数)x(是否有 5 张牌)x(庄家的顶牌),这是我们希望代理考虑的每种状态的组合
  • 奖励、价值和政策——它们的数据层次结构包含所有状态下每个状态的一些行动数值(即 s∈S,a∈A(s))。初始值对启动学习很重要。

当然,玩家必须根据自己的政策决定每一轮做什么:

当您看到这种类型的数据列表时,它可能会让您想起来自动态编程的概念,这些概念需要我们“记住”。玩家作为代理人的核心部分在于其学习能力:

此处按顺序显示了用于更新的伪代码:

在一集(一场游戏)中对国家行为回报的一步前瞻预期

通过将 G 附加到退货来更新退货

通过平均状态-动作对的回报来更新值

针对最优与非最优动作的每个状态的ε-贪婪策略的更新

执行上述更新将导致以下收敛。更多详情请参见广义策略迭代(GPI)

最后,我们将游戏放在一起,其中代理人将反复玩尽可能多的次数来训练代理人的策略,游戏规则定义如下:

在玩了 20,000 场游戏后,下面显示了代理人感知的状态-价值函数及其在不同牌局采取特定行动的政策偏向。其他因素(如庄家的顶牌或手中可以满足 5 张牌的查理的牌数)也可以类似地以这种形式查看。

在结果中首先要指出的是,与随机游戏相比,代理人在遵守这些规则方面明显损失更少(图 2a)。如果你真的随机玩,预计你会输掉超过 40%的钱。然而,玩最优游戏实际上能让你获利 10%左右!这可能是赌场收取赌金或要求玩家维持最低赌金的原因。

我们可以清楚地看到状态-值函数中的预期趋势,其中随着获胜几率的增加,值向 21 增加(图 2c)。在 10 到 11 之间有一个重要的峰值范围,其中状态值较高,这是因为有更高的机会用面牌得到 19 到 21,并且在 11 之后突然转向负值。不幸的是,在 20,000 次试验中,没有一个代理人有 5 张查理牌(图 2b),这表明这种情况发生的可能性有多大。对于行动策略,当手牌总数小于 13 时,代理通常选择击中,当总数变大时,代理选择不打(图 2b)。

(图 2)在 n= 20000 次试验后对 RL 代理人表现的评估,对于发牌者顶牌= 5(图 2a)的情况,RL 参与者(橙色)的回报明显优于随机参与者(绿色)和阴性对照(蓝色)。(图 2b)在有/没有 5 张查理牌的状态中的代理的平均状态值,以及(图 2c)在手牌总和的每个状态中的代理的平均状态值。(图 2d)给定手数总和的每种状态下采取行动的概率。

如果你是 21 点的新手,可以考虑在这个没有可用 a 的模拟真实游戏中从代理那里学习一些规则。如果您想要高级或情境洞察力,考虑通过添加来自赌场的真实规则来改进此模拟,并让代理学习战胜困难。

总之,这展示了强化学习最幼稚的实现之一,即通过记录经验并直接根据经验做出判断来学习。在这个系统中有很多东西你可以调整,比如探测超参数。如果您想将强化学习提升到下一个级别,您可以添加一个监督学习模型,如神经网络或时间序列预测模型,该模型试图在这些经验中找到模式,以提前规划政策。这样做可以大大提高性能和收敛速度,实现我们的目标。

作为一个有趣的后续问题,如果你想让一个代理知道它是否愿意选择赌博,你会如何实现它?

分布式数据存储简介

原文:https://towardsdatascience.com/introduction-to-distributed-data-storage-2ee03e02a11d?source=collection_archive---------5-----------------------

有效使用分布式数据存储需要知道的一切!

存储在 quartz 上的数据—经微软许可使用。

D ata 是今天的基础!它支持从您最喜爱的猫视频到每天发生的数十亿次金融交易的所有内容。所有这些的核心是分布式数据存储。

在本文中,我们将学习 什么是 分布式数据存储, 为什么 我们需要它,以及如何有效地使用它。本文旨在帮助您开发应用程序,因此我们将只讨论应用程序开发人员需要了解的内容。这包括基本的基础、开发人员遇到的常见陷阱,以及不同分布式数据存储之间的差异。

本文不需要任何分布式系统知识!编程和数据库经验会有所帮助,但是你也可以在我们遇到主题时查找它们。开始吧!

什么是分布式数据存储?

分布式数据存储是在多台机器上存储和处理数据的系统。

作为一名开发人员,您可以将分布式数据存储想象成存储和检索应用程序数据、指标、日志等的方式。您可能熟悉的一些流行的分布式数据存储有 MongoDB、亚马逊网络服务的 S3 和谷歌云平台的 Spanner。

实际上,有很多种分布式数据存储。它们通常是由云提供商管理的服务或您自己部署的产品。您也可以从头开始或在其他数据存储的基础上构建自己的数据库。

我们为什么需要它?

为什么不直接使用单机数据存储呢?要真正理解,我们首先需要认识到当今数据的规模和无处不在。让我们来看一些具体的数字:

  • Steam 峰值 1850 万并发用户,部署了 2.7 Pb SSD 的服务器,2018 年向用户交付了 15。
  • 2020 年,纳斯达克在一天之内就消化了 1130 亿条记录,比两年前的平均 300 亿条有所增加。
  • 谷物公司凯洛格的 2014 年模拟促销活动每周处理 16tb 的数据。

老实说,我们使用的数据之多令人难以置信。这些位中的每一位都在某个地方被小心地存储和处理。某处是我们的分布式数据存储。

单机数据存储根本无法支持这些需求。因此,我们使用分布式数据存储,它在可靠性 方面提供关键优势。让我们来理解一下这些优势在实践中真正意味着什么。

性能、可扩展性和可靠性

****性能是一台机器工作的好坏。

性能至关重要。有无数的研究量化并显示了像 100ms⁴.这样短暂的延迟对业务的影响缓慢的响应时间不仅让人们感到沮丧,还会损失流量、销售额,最终还会损失 revenue⁵.

幸运的是,我们确实可以控制应用程序的性能。在单机数据存储的情况下,简单地升级到更快的机器通常就足够了。如果这还不够,或者您依赖于分布式数据存储,那么其他形式的可伸缩性就发挥作用了。

可伸缩性是增加或减少基础设施资源的能力。

当今的应用程序经常经历快速增长和循环使用模式。为了满足这些负载需求,我们“扩展”了我们的分布式数据存储。这意味着我们根据需要按需提供或多或少的资源。可伸缩性有两种形式。

  • 水平缩放 表示添加或删除计算机(也称机器或节点)。
  • 垂直缩放 是指改变机器的 CPU、RAM、存储容量或其他硬件。

水平扩展是分布式数据存储能够超越单机数据存储的原因。通过将工作分散到数百台计算机上,聚合系统具有更高的性能和可靠性。虽然分布式数据存储主要依赖于水平扩展,但垂直扩展也可用于优化整体性能和 cost⁶.

从手动到完全管理的范围内都存在扩展。有些产品具有 手动扩展 功能,您可以自行调配额外容量。其他 自动缩放 基于剩余存储容量等指标。最后,一些服务处理所有的伸缩问题,开发者甚至不用考虑,比如亚马逊网络服务的 S3。

不管采用哪种方法,所有服务都有一些不能增加的限制,比如最大对象大小。您可以查看文档中的配额来了解这些硬限制。您可以查看在线基准测试,看看实际上可以达到什么样的性能。

可靠性是成为 failure-free⁷.的概率

有些应用程序对我们的生活至关重要,甚至几秒钟的故障都是不可接受的。这些应用程序不能使用单机数据存储,因为不可避免的硬件和网络故障会危及整个服务。相反,我们使用分布式数据存储,因为它们可以适应个别计算机或网络路径故障。

为了高度可靠,系统必须同时是 available⁸和 fault-tolerant⁹.

  • 可用性 是服务可达并正常响应请求的时间百分比。
  • 容错 是容忍硬件和软件故障的能力。完全容错是不可能的,⁰.

虽然可用性和容错性初看起来很相似,但实际上它们是完全不同的。让我们看看如果你有一个而没有另一个会发生什么。

  • ****可用但不容错:考虑一个系统,每分钟发生一次故障,但在毫秒内恢复。用户可以访问该服务,但长时间运行的作业永远没有足够的时间来完成。
  • ****容错但不可用:考虑一个系统,其中一半节点永久重启,其他节点稳定。如果稳定节点的容量不足,那么一些请求将不得不被拒绝。

外卖食品

对于应用程序开发人员来说,关键是分布式数据存储可以扩展性能和可靠性,远远超过单台机器。问题在于,他们在工作方式上有一些限制其潜力的限制。

它是如何工作的?

让我们来看看应用程序开发人员需要了解分布式数据存储是如何工作的——分区、查询路由和复制。这些基础知识将让您深入了解分布式数据存储的行为和特征。它将帮助您理解警告、权衡,以及为什么我们没有一个擅长所有事情的分布式数据存储。

分割

我们的数据集通常太大,无法存储在一台机器上。为了克服这一点,我们 将我们的数据 划分成更小的子集,以便各个机器可以存储和处理。有许多方法可以对数据进行分区,每种方法都有各自的优缺点。两种主要的方法是垂直和水平分区。

作者图片

垂直分割 是指按照相关字段分割数据。字段可能因为许多原因而相关。它们可能是某个公共对象的属性。它们可能是查询经常一起访问的字段。它们甚至可能是以相似频率访问的字段,或者是由具有相似权限的用户访问的字段。跨机器垂直划分数据的确切方式最终取决于您的数据存储的属性和您正在优化的使用模式。

(也称为 分片 )是指我们将数据分割成具有相同模式的子集。例如,我们可以通过将行分组为存储在不同机器上的碎片来对关系数据库表进行水平分区。当一台机器无法处理数据量或数据的查询负载时,我们就对数据进行分片。分片策略分为两类,算法和动态,但混合存在⁰.

作者图片

算法分片 根据数据键的函数决定将数据分配给哪个分片。例如,当存储将 URL 映射到 HTML 的键值数据时,我们可以通过根据 URL 的第一个字母拆分键值来 范围划分 我们的数据。例如,所有以“A”开头的 URL 将出现在第一台机器上,“B”出现在第二台机器上,依此类推。有无数的策略都有不同的权衡。

动态分片 明确选择数据的位置,并将该位置存储在查找表中。为了访问数据,我们使用查找表查询服务或检查本地缓存。查找表可能非常大,因此它们可能有指向子查找表的查找表,像B+-树。动态分片比算法分片更加灵活。

实际上,分区是相当棘手的,会产生许多需要注意的问题。幸运的是,一些分布式数据存储将为您处理所有这些复杂性。其他人处理一些或不处理。

  • 碎片可能有 不均匀的数据 大小。这在算法分片中很常见,因为函数很难得到正确的结果。我们通过围绕数据定制分片策略来缓解这一问题。
  • 碎片可能有 热点 ,其中某些数据比其他数据更频繁地被查询。例如,考虑一下你在社交网络中查询名人的频率会比普通人高多少。谨慎的模式设计、缓存和副本在这里会有所帮助。
  • 在维护高可用性时,重新分发 数据以处理向系统添加或从系统中删除节点是很困难的。
  • 索引 可能也需要分区。索引可以索引存储它的碎片(本地索引),或者它可以索引整个数据集并被分区(全局索引)。每个都有权衡
  • 跨分区的事务 可能工作,也可能被禁用、变慢,或者以令人困惑的方式不一致。当从单机数据存储构建您自己的分布式数据存储时,这尤其困难。

查询路由

对数据进行分区只是故事的一部分。我们仍然需要将查询从客户端路由到正确的后端机器。查询路由可以发生在软件栈的不同级别。我们来看三种基本情况。

  • 客户端分区 是指客户端持有查询哪个后端节点的决策逻辑。优点是概念简单,缺点是每个客户端都必须实现查询路由逻辑。
  • 基于代理的分区 是客户端将所有查询发送给一个代理。这个代理然后确定查询哪个后端节点。这有助于减少后端服务器上的并发连接数,并将应用程序逻辑与路由逻辑分开。
  • 基于服务器的分区 是当客户端连接到任何后端节点时,该节点将处理、重定向或转发请求。

实际上,大多数分布式数据存储都处理查询路由。通常,您配置一个客户端,然后使用该客户端进行查询。但是,如果您正在构建自己的分布式数据存储,或者使用像 Redis 这样的不支持分布式数据存储的产品,您就需要考虑到这一点,⁴.

分身术

我们要讨论的最后一个概念是复制。复制意味着存储相同数据的多个副本。这有很多好处。

  • 数据冗余: 当硬件不可避免地出现故障时,数据并没有因为有另一份拷贝而丢失。
  • 数据可访问性: 客户端可以从任何副本访问数据。这提高了针对数据中心中断和网络分区的恢复能力。
  • 增加读取吞吐量: 可以处理数据的机器越多,整体容量就越高。
  • 降低网络延迟: 客户端可以访问离自己最近的副本,降低网络延迟。

实施复制需要令人难以置信的共识协议和对故障场景的详尽分析。幸运的是,应用程序开发人员通常只需要知道数据在何时何地被复制。

数据复制的范围从一个数据中心内到跨区域、地区,甚至是大洲。通过紧密地复制数据,我们最大限度地减少了在机器之间更新数据时的网络延迟。但是,通过将数据复制到更远的地方,我们可以针对数据中心故障、网络分区提供保护,并可能降低读取的网络延迟。

数据被复制时可以同步也可以异步。

  • 同步 复制是指在响应请求之前将数据复制到所有副本。这样做的好处是,以更高的写入延迟为代价,确保副本之间的数据完全相同。
  • 异步 复制是指在响应请求之前,数据仅存储在一个副本上。这样做的优点是写入速度更快,缺点是数据一致性较弱,可能会丢失数据。

外卖食品

分区、查询路由和复制是分布式数据存储的构造块。不同的实现表现为不同的特性和属性,您需要在它们之间进行权衡。

有什么区别?

分布式数据存储都是特殊的雪花,每个都有其独特的特性。我们将通过将它们的不同之处分成几类并涵盖每一类的基础知识来对它们进行比较。这将有助于你知道要问什么问题,以及将来要深入阅读什么。

数据模型

要考虑的第一个区别是数据模型。数据模型是数据的类型以及如何查询数据。常见类型包括

  • 文档:JSON 文档的嵌套集合。使用关键字或过滤器进行查询。
  • 键值: 键值对。用键查询。
  • 关系: 具有显式模式的行表。用 SQL 查询。
  • 二元物体: 任意二元斑点。用键查询。
  • 文件系统: 文件的目录。使用文件路径进行查询。
  • 图形: 带边的节点。使用图形查询语言进行查询。
  • 消息: 一组键值对,就像 JSON 或 python 的 dict。来自队列、主题或发件人的查询。
  • 时序: 按时间戳排序的数据。使用 SQL 或其他查询语言进行查询。
  • 文本: 自由格式文本或日志。使用查询语言进行查询。

不同的数据模型适用于不同的情况。虽然您可以将所有内容都存储为二进制对象,但这在查询数据和开发应用程序时会很不方便。相反,使用最适合您的查询类型的数据模型。例如,如果您需要快速、简单地查找少量数据,请使用键值。我们将在下面的图表中提供更多关于预期用途的详细信息。

请注意,一些数据存储是多模型的,这意味着它们可以有效地操作多个数据模型。

担保

不同的数据存储提供不同的行为“保证”。虽然您在技术上不需要保证来开发健壮的应用程序,但是强保证极大地简化了设计和实现。您将遇到的常见保证如下:

  • 一致性 就是数据对所有读者看起来是否一样,是否是最新的。请注意,具有讽刺意味的是,“一致性”一词严重超载——请确定⁵.指的是哪种类型的一致性
  • 可用性 就是你是否可以访问你的数据。
  • 持久性 是存储的数据是否保持安全和不被破坏。

一些服务提供商甚至会通过服务水平协议(SLA)来保证服务水平,例如 99.99%的可用性。如果他们不遵守协议,你通常会得到一些补偿。

生态系统

生态系统(集成、工具、支持软件等。)对于分布式数据存储的成功至关重要。需要检查一些简单的问题,比如什么 SDK 可用,支持什么类型的测试。如果你需要数据库连接器、移动同步、 ORMs协议缓冲区、地理空间库等功能。,您需要确认它们是否受支持。文档和博客会有这些信息。

安全性

安全责任由您和您的产品/服务提供商共同承担。您的职责将与您管理的堆栈数量相关联。

如果您使用分布式数据存储作为服务,您可能只需要配置一些身份和访问策略、审计和应用程序安全性。但是,如果您构建并部署了所有这些,您将需要处理一切,包括基础架构安全性、网络安全性、静态/传输中的加密、密钥管理、修补等。检查您的数据存储的“共享责任模型”来解决这个问题。

服从

合规性可能是一个关键的优势。许多应用程序需要遵守关于如何处理数据的法律法规。如果您需要遵守安全策略,如 FEDRAMP、PCI-DSS、HIPAA 或任何其他策略,那么您的分布式数据存储也需要遵守。

此外,如果您对客户做出了有关数据保留、数据驻留或数据隔离的承诺,您可能需要一个具有内置功能的分布式数据存储。

价格

不同的数据存储定价不同。一些数据存储仅根据存储容量收费,而另一些则计入服务器和许可证费用。文档中通常会有一个价格计算器,您可以用它来估算账单。请注意,虽然一些数据存储一开始可能看起来成本较高,但它们可能会在工程和操作时间节省方面弥补这一点。

外卖食品

分布式数据存储都是唯一的。我们可以通过文档、博客、基准、价格计算器,或者通过与专业支持人员交谈和构建原型来了解和比较它们的不同特性。

有哪些选择?

我们现在对分布式数据存储有了很多抽象的了解。让我们绑在一起,看看真正的工具!

貌似 - 无限 选项,可惜没有最好的。每个分布式数据存储都有不同的用途,需要适合您的特定用例。要了解不同的类型,请查看下表。慢慢来,关注一般类型和用例。

最后,请注意,真正的应用程序和公司有各种各样的工作要做,因此它们依赖于多个分布式数据存储。这些系统协同工作,为最终用户以及开发人员和分析人员服务。

关闭

数据已经存在,而分布式数据存储正是实现这一点的基础。

在本文中,我们了解到分布式数据存储的性能和可靠性可以远远超越单机数据存储。分布式数据存储依赖于具有许多机器的体系结构来分区和复制数据。应用程序开发人员不需要知道所有的细节,他们只需要知道足够多的信息来理解实践中出现的问题,如数据热点、事务支持、数据复制的价格等。

像其他任何东西一样,分布式数据存储有各种各样的特性。起初,可能很难将其概念化,但希望我们的分解有助于定位你的思维过程,并指导你未来的学习。

希望现在你知道什么是大局,以及应该深入了解什么。请考虑查阅参考资料。很高兴听到你的任何评论!😃

常见问题解答

问:我在谷歌上搜索了“容错”、“分片”等术语。不是你说的那样。

a)是的,术语在不断发展,而且已经超载。在实践中,解决这个问题的方法是澄清所指的是哪个定义。

参考

[1] 汽— 2018 年回顾 (2018),汽

[2] 纳斯达克使用 AWS 开创了在云中存储证券交易所数据的先河 (2020),AWS

[3] 凯洛格公司案例研究 (2014),AWS

[4] B .帕维奇,c .安特西,j .瓦格纳,为什么速度很重要? (2020),网络开发

[5] G .林登,玛丽莎·梅耶尔在 Web 2.0 (2006)

[6] 第一章。可扩展性初级读本 (2012),奥赖利

[7] J .潘,软件可靠性 (1999),卡内基梅隆大学

[8] A. Somani,N. Vaidya,了解容错和可靠性 (1997),IEEE

[9] 容错,Imperva

[10] M. Kleppmann,设计数据密集型应用 (2017),O'Reilly

[11] 水平、垂直和功能数据分区 (2017),微软

[12] F. Chang 等著 Bigtable (2006),谷歌

[13] G. Guo,T. Kooburat,使用分片管理器扩展服务 (2020),

[14] 分区,Redis

[15] I .张,一致性应该更一致!

人工智能在战争中应用的伦理学导论

原文:https://towardsdatascience.com/introduction-to-ethics-in-the-use-of-ai-in-war-9e9bf8ba71ba?source=collection_archive---------25-----------------------

快速浏览道德和治理问题

第 1 部分:快速基础知识、优势和成本

伯明翰博物馆信托基金会在 Unsplash 上拍摄的照片

人工智能的进步已经扩展到国防应用中,这引发了许多伦理问题。虽然有许多详细的文档讨论了在作战应用中使用人工智能的特定领域,但我想在这里对这些问题进行概述,并讨论一些基本想法,这些想法将有助于您以更明智的方式讨论和解决该领域的问题。

让我们通过以下项目来建立对为什么在战争中使用人工智能会引起如此多的伦理问题的理解:

  1. 快速基础
  2. 优势与成本
  3. 当前伦理原则的局限性
  4. 关键问题
  5. 开放式问题

在第 1 部分(本文)中,我们将讨论第 1 和第 2 部分,并将在第 2 和第 3 部分中讨论第 3–5 部分。

在我们开始之前,这里的一个简短的帖子不可能是全面的,所以如果你发现了一些遗漏的和可以扩展的东西,请不要犹豫,留下评论并分享资源,以便我们可以一起积累知识!

1.快速基础

让我们了解一些基本的定义,以便我们对术语有一个共同的理解,并可以提出和解决问题,同时牢记这些界限。

什么是自主武器系统(AWS)?

本质上,AWS 指的是以下功能:

在没有人类控制的情况下识别、选择和攻击目标。

识别是指在构成视频帧的图像中挑选出一部分“对象”,这些图像将被传递到管道的下一阶段,例如将军事目标与民用资产分开。

选择指的是将对象列表缩小到符合某些标准的对象,例如高价值的军事目标。

交战是指发动攻击,例如对前一阶段选定的目标发射弹药。

在这种情况下,有意义的人工控制是指由自动化系统承担这些管道的所有方面,而不需要人工干预来识别、选择或参与目标。此外,这还指能够在战场上遇到的不确定性中具有一定程度的自力更生能力,并且即使在与人类控制中心失去联系的情况下也能够继续运作。

什么是半自治?

基本上半自治指的是以下概念:

系统中的部分自治程度,通过与人的联系进行监督和控制

对于我们在上一节中确定的每个阶段,即识别、选择和参与,半自主通常在以下情况下对人类有延迟:对目标的识别、所做的选择和参与目标的策略的不确定性。这通常也被称为人在回路(HITL)。

什么是完全自主?

完全自治指的是以下两个概念:

  • 执行其所有功能,无需任何有意义的人工控制和链接
  • 独立应对不断变化的环境,以实现预先设定的目标

上面第一点的第二部分需要进行一些检查,因为这意味着我们并不总是依赖人工智能的能力。这可以通过一种方式来体现,当失去人类控制和联系时,我们有一套预编程的规则来继续发挥作用,或者安全地脱离进入休眠状态,等待重新获得与指挥中心的联系。

什么是致命使用?

尽管根据法律规定,致命使用可能有细微差别和细微变化,但它指的是以下情况:

对人的生命造成重大威胁,包括有意和无意的生命损失。

什么是非致命使用?

这些通常是人工智能的后台或其他用途,不涉及造成直接伤害:支持功能,实现系统的基本操作,如起飞和着陆辅助,避免地面碰撞和炸弹处理等。

不过有一点要注意,一些非致命的用途可能会有导致致命后果的下游用途。

2.优势与成本

正如任何双重或多用途技术一样,在战场上使用人工智能有优势也有成本。我将在介绍系列之后的后续文章中探讨一个警告,即拥有 HITL 本身并不总是一个积极的结果,这种参与可能会产生更多的相关成本,而不是由此产生的潜在优势。

潜在优势

请注意在标题中故意使用了“潜力”这个词,因为我相信在战场上使用人工智能所带来的好处确实比成本更确定。

当我们谈论在战争中使用人工智能时,这些是我们最常遇到的一些潜在优势:

  • 减少平民伤亡
  • 减少对军事人员的需求
  • 通过更精确的定位减少整体伤害

更好的识别和选择可以减少平民伤亡。通过远程操作,对军事人员的需求(或至少具有更高的安全性)是可能的,这可能降低在战场上受伤的风险,包括身体和精神上的损失。然而,如果他们看到令人不安的图像,例如,他们在无人机远程操作中遇到的图像,情绪上的损失仍然可能发生。如果攻击目标的方式和目标本身更加精确,净伤害也可以减少,这可能会减少战争中不可避免的附带伤害。

费用

请注意,我故意在章节标题中省略了潜在一词的使用,因为可能发生的成本有更高程度的确定性。一个额外的考虑是,人工智能在战争中的应用如何带来一种内在的敌对动态,这种动态鼓励“人工智能军备竞赛”,导致系统能力和限制方面的合作和开放减少,这将损害生态系统的健康。

这些是我们在战争中使用人工智能时可能会遇到的一些最常见的成本:

  • 不同代理之间的紧急互动导致意外升级,这些代理具有潜在冲突的预编程目标。
  • 甚至在小型非国家行为者的手中也能扩大伤害
  • 从机器学习安全的角度来看,军事基础设施的其余部分暴露了新的攻击面。

第一个成本是一个非常现实的问题,值得那些为作战应用开发和部署人工智能系统的人充分关注。具体而言,随着自动化系统可以采取的行动的快速步伐,如果存在需要在对其采取行动之前与多方商议和协商的信息,这可能会成为一个问题,除非明确的延迟被编程来考虑这些情况。也有许多人强烈支持在战场上以任何身份使用人工智能,因为会出现许多误用和伤害。

正如我们已经看到的信息生态系统面临机器人充斥社交媒体平台的危害一样,通过使用自动化武器来扩大负面影响的影响甚至更严重。

最后,正如我们在人工智能道德简报中多次指出的,机器学习安全是一个非常现实的问题,当将 ML 组件集成到传统网络安全措施不足以解决问题的现有软件基础设施中时,需要考虑这一点。

第一部分的结论

希望这部分已经为你提供了一些我们在讨论战争中人工智能伦理时经常遇到的基本术语。我们还探索了在战争中使用人工智能的潜在优势和成本。

在此之后,我们将探索以下领域:

  • 当前伦理原则的局限性
  • 关键问题—第 1 部分

第二部分:当前伦理原则的局限性和关键问题

迈克尔·阿丰索在 Unsplash 上的照片

在这篇文章的第一部分的基础上,让我们深入一些关于在战争中使用人工智能的伦理讨论。

在第 1 部分中,我介绍了:

  • 快速基础知识,谈到了自主武器系统,半自主,全自主,致命的使用,和非致命的使用
  • 潜在的优势和成本

如果您还没有机会阅读第一部分,我强烈建议您阅读,因为我们将在那一部分解释的定义的基础上讨论这一部分的问题。

让我们深入了解:

  • 当前伦理原则的局限性
  • 关键问题—第 1 部分

1.当前伦理原则的局限性

今天,围绕在战争中使用人工智能的伦理问题的讨论虽然不断发展,但仍然有一些关键的考虑因素,如果没有这些考虑因素,我们就有可能以一种可能造成重大伤害的方式利用这些系统,并且前一篇文章中概述的成本将开始远远超过潜在的好处。

A.对人工智能安全性和可靠性的不同程度的重视

目前,这个子域中的问题的措辞方式,对人工智能的安全性和可靠性有不同程度的强调。这是一个问题,因为在战场上使用人工智能会产生许多意想不到的和紧急的行为,特别是当你在一个动荡的环境中有编程实体相互交互时,由于对意图和目的的误解而导致意外升级。

这还不包括这样一个事实,即我们在战场上也有对人工智能系统的敌对操纵,通过混淆的例子,明确的目的是从系统中引出边界情况破坏行为,这些行为可以触发一连串的其他行动,导致升级和不必要的伤害。

B.长期人工智能安全研究资金不足

这一领域的某些问题仍需进一步研究。这些包括:在其他长期安全影响中的对抗性鲁棒性,如自主程度对战争中人机交互动力学的影响。由于更直接地关注人工智能的使用所带来的一些伦理挑战,这些问题没有得到充分的探索、资金不足和重视。

这并不是说这些不重要——它们肯定很重要,但这也意味着,如果在这一至关重要的长期安全研究方面投资不足,那么我们保护自己的能力将会有限。当那些不相信人工智能系统不能在战争中使用的人选择部署它们时,这尤其如此,这增加了其他国家行为者的风险,他们没有准备好应对这些系统在战场上的影响。

C.软法律是不够的

目前围绕这一主题的大多数讨论都在推动在我们达成更具强制性的法律文书之前的过渡时期采用软法律方法,核安全领域的先例表明,这可能需要很长时间才能取得成果。虽然倡导这种软法律和自我监管方法没有任何害处,但首先不相信这些理念的国家和非国家行为者遵守这些方法的可能性非常低,只会削弱那些首先遵守这些道德原则并随后可能在国际舞台上遵守这些原则的国家的能力。

D.在关键主题上趋于一致,但仍脱离具体实施

正如更大的人工智能伦理领域的情况一样,自 2017 年以来,在对该领域问题的理论分析方面做了大量工作——以至于它可能已经变得不利于实际从原则转向实践。

考虑人工智能在战争中使用的伦理问题的工作在某种程度上是相似的,在关键思想上有很多高水平的趋同,但在应用于战争中时,仍然与人工智能系统的一些实际、当前的能力和限制有很多分离。也就是说,我们遇到了一个经典的问题,即在如何治理这类系统的问题上,要么寻求监管不足,要么寻求监管过度。我们也可能因为对核心问题缺乏了解,或者对系统的实际能力了解有限,从而陷入高估短期能力和低估长期能力的经典困境,而最终关注错误的领域。

E.缺乏稳固的治理结构

在治理方法方面也存在碎片化,这确实将处理战场上人工智能存在的整个工作方式置于风险之中。也就是说,我们支持建立不同的治理机制,因为人工智能的存在及其带来的独特挑战,而其他人则主张将这种治理纳入现有的结构,并授权当前指挥链中的人了解和解决使用人工智能带来的挑战。

我强烈主张利用现有的指挥结构链作为治理机制,因为这使我们能够利用一些经过几十年形成并经过多年战斗考验和磨练的最佳做法。这也具有将责任和控制的中心保持在受过战争环境下操作训练的人身上的优势,并保持我们对现有法律机制的支配,这些法律机制可以利用法院和法律来裁定由于机器、人或两者的结合而发生的侵权行为。

F.潜在不正确的政策先例

由于这种系统被匆忙用于战场,潜在的原因是害怕错过或被对手的机动击败,我们冒着为未来的使用设定不正确的政策先例的风险,甚至这些系统更先进的版本也可能以意想不到的方式失败。

政策先例问题有可能不仅仅局限于作战,还会延伸到其他关键任务领域,在这些领域,我们可能会将对人类生活有重大影响的系统匆忙投入生产和使用的过程正常化,同时推迟对收益是否大于成本的判断。

2.关键问题—第 1 部分

谈到战争自动化,有一大堆问题,其中一些是技术性的,另一些是组织性和社会性的。所有这些都值得进一步研究,以确保我们正在建立的系统可能有助于首先避免使用它们,或至少有助于使战争更加人道,最大限度地减少不必要的伤害。

A.缺乏召回系统的能力

当给系统注入足够的自主性以独立做出决策时(比如当与控制断开连接时),在没有故障保护机制和不断发展的不确定性的情况下,当这样的系统在战场上遇到挑战时(包括物理和虚拟挑战),可能会出现意外行为的风险很高。

基于意外升级的主题,这是我们无法召回系统的能力可能导致额外伤害的情况的完美候选,特别是考虑到自动化系统与人类相比的决策和执行速度。这可能会导致与其他自动化系统的反馈回路失控,无论是友好的还是敌对的,这进一步加剧了该领域的问题。

B.刚性目标

受过训练的人类军官拥有的关键技能之一是他们吸收新信息并在新信息出现时重新调整目标和战略决策的能力。对于没有经过充分实战测试的自动化系统来说,这可能是一件具有挑战性的事情,这些系统的能力随后被约束(有时是理所当然的)到它在人工智能开发生命周期的训练阶段所学习的目标。

但是,当战场上的紧急情况(通过外交或其他变化)需要重新评估,并且系统无法更新其内部表示以允许其纳入新信息时,这种僵化可能会成为不利因素,从而导致潜在的不必要的伤亡。

C.使造成伤害的能力民主化

最后,或许也是最重要的,自动化系统使造成伤害的能力民主化(以一种不好的方式)。我们已经看到了这种动态在信息生态系统中的表现,机器人能够操纵对话并推动话语的方向,通过进一步分化社区并向他们展示信息生态系统的一小部分实际状态,从而对社区造成伤害。基本上,少数行为者已经能够在自动化的帮助下扩大他们的造谣努力。

自动化武器有可能(在现实世界中)造成巨大破坏,通过赋予一小群人以工具,使他们有能力与较小的民族国家(也许不是世界上最大的军队,因为他们拥有庞大的基础设施和资源)同等行动,自动化武器也可以做到这一点。这是一个很大的问题,因为它可能会更加破坏世界的稳定,并把我们带到一个我们可能会遇到意想不到的威胁的地方,这些威胁来自那些设法获得这些自动化武器的小角色。

第二部分的结论

现在让我们进入本文的第 3 部分,它将涵盖以下内容:

  • 关键问题—第 2 部分
  • 开放式问题

第 3 部分:关键问题(续)和开放式问题

托马斯·塔克在 Unsplash 上拍摄的照片

在文章的第 1 部分和第 2 部分的基础上,让我们深入一些关于人工智能在战争中使用的伦理问题的讨论。

在第 1 部分中,我介绍了:

  • 快速基础知识,谈到了自主武器系统,半自主,全自主,致命的使用,和非致命的使用
  • 潜在的优势和成本

在第 2 部分中,我介绍了:

  • 当前伦理原则的局限性
  • 关键问题—第 1 部分

如果你还没有机会阅读第一部分和第二部分,我强烈建议你这样做,因为我们将在那些部分解释的定义的基础上讨论这一部分的问题。

让我们深入了解:

  • 关键问题—第 2 部分
  • 开放式问题

1.关键问题—第 2 部分

随着我们更多地考虑这种系统是否应该在实践中使用,还有一些更关键的问题需要进一步研究。通过深入研究下面提出的一些要点,我们可以对潜在的优势和成本有更细致的了解。这种方法将使决策更加稳健,特别是在面对紧急和突发情况时,我们可能会被迫做出快速决策。拥有之前已经充分讨论过的强大方法和推理将使我们能够做出更好的决策。

A.系统的不可靠性

人工智能系统本质上具有内在的概率性。结合战场上的不确定性和快速变化的环境,我们最终会从系统中获得导致不可靠性的紧急行为。至少从我们试图更好地掌握这些系统可能做出反应的潜在途径的角度来看是这样的。

我们面临着“人工智能的迷雾”,这使得我们很难保证系统会可靠地运行,即使它受到有意(敌对的例子)或无意的意外输入的轰炸。

B.对国际条约缺乏共识

目前的气氛充满了怀疑和不同的观点。各国通过《特定常规武器公约》(CCW)等论坛举行会议,但在涉及法律时,对国际条约的发展方向很少或没有共识的审议已经进行了多年。

在美国国家安全委员会(NSCAI)最近发布的人工智能指南中,这种缺乏共识的情况体现在一些论点上,即为什么美国应该继续在这一领域进行投资,因为缺乏全球能力来监测和验证对开发和使用这种武器系统的禁令的遵守情况。

C.对法律的谴责缺乏一致性

如果没有学术和行业实验室的努力,所有的开发和部署都是不可能的,这些实验室致力于人工智能的各个子领域,最终为这些系统提供动力。由于人工智能在各行各业的广泛应用,像物体检测这样的技术可以帮助识别手机上所有有你的狗的照片,但也可以重新用于(当然是改变)识别战场上的目标。

也许,研究人员和实践者发出的拒绝从事很可能在战争中被重用的应用程序的响亮号召可以给我们更多的时间,同时我们可以找出允许安全使用的治理和技术措施(如果我们曾经决定在这种情况下使用这样的系统是有意义的)。

2.开放式问题

虽然本文和上一篇文章中强调的关键问题也为要考虑的事情提供了一些启示,但在我们能够应用我们试图从之前的关键问题讨论中得出的一些细微差别之前,有一些首要问题需要进行经验和理论研究。这些开放性问题的目标是为我们的社区提供一些潜在的研究方向,不仅仅是在战争中使用人工智能,还包括随着时间的推移可能出现类似问题的相邻领域。

A.什么是有意义的人类控制?

当谈到有意义的人类控制时,有如此多的分级标记,这仍然是一个开放的问题。特别是,需要进一步研究的是有意义的人类控制意味着什么的共同进化方面。具体来说,随着新技术在世界范围内扩散,基本的能力和理解水平以及对系统能力和局限性的期望也在发展。随着新一批操作员进入该领域并与该领域的资深操作员一起工作,这将变得相关,从而导致不同技能水平的操作员并肩工作。在这种情况下,需要定制培训计划以满足所有这些需求,并且可能还需要采用评估协议以适应性方式进行认证,从而解决这些差异。

为了避免“人的令牌”问题,我们还需要考虑动态环境中人和机器之间的交互,在这种环境中,每个组件都以一种利用彼此独特优势的方式服从另一个组件。

最后,有意义是指应该以一致的方式在可能在现场使用这些系统的不同机构之间进行阐述。统一的认识将有助于发展上述一些机制,从而帮助不同机构的所有行为者同步前进,而不是落在后面,因为后者可能会损害早期采用者在该领域所做工作的效力。

B.如何设定致命和非致命用途的界限?

对于法律专家和军事行动者来说,明确区分这两个国家对于为法律制定过程提供适当的指导以及帮助不同民族国家和其他行动者达成共识至关重要。

正如我们在第一部分和第二部分中所谈到的,目前的灰色地带不仅是这种系统所造成的道德难题的巨大恐慌来源,而且也是适用于这些系统的采购和操作的标准和实践的巨大恐慌来源。

此外,这也将对有意义的人类控制方面产生影响,因为它将要求一种有区别的方法,这种方法使我们在允许系统自主运行的方法中清楚地知道何时我们必须更严格或更不严格。

C.如果自治在这里正常化,对其他领域有哪些溢出影响?

这是一个更大的问题,可能需要任何认真考虑使用自治系统的领域来解决。考虑溢出影响的原因是因为人工智能天生是多用途的,子域通常通过开放访问和开源发布模型进行大量混合。此外,随着治理框架发展的初期阶段,我们正在进入一个时代,在这个时代,条约、法律、法规和标准将被编纂成文,并为我们设定特定的道路。

如果我们开始将某些用途正常化,并认为为了“更大的利益”(一种非常功利的观点)而使用此类系统可能产生的一些附带损害是理所当然的,那么我们将更容易证明为了遵循相同的逻辑而使用风险越来越大的系统是合理的,而无需在开发和部署这些系统之前同意其他制衡措施,如社区咨询和跨学科审议。

结论

我将保持这个相对简短的结束语,因为我们已经有机会走过许多与 AI 在战争中的使用相关的细微差别。这样做的决定,就像在任何高风险场景中使用人工智能的情况一样,归结为拥有关于系统能力和限制的足够信息,然后以审慎的方式利用这些信息来为我们的决策提供信息。建立可以提前管理我们行为的护栏,而不是在面对紧急和突发情况时做出反应,也将有助于充分考虑在战争中使用人工智能的潜在优势和成本。本系列文章中提出的观点只是一个起点,我鼓励我所有的同行花时间深入研究本系列文章中的观点,以便我们能够以负责任的方式部署这些技术。

希望这一系列介绍在战争中使用人工智能的伦理的文章是有用的。请在这里的评论区留下您的评论和任何您认为有用的资源。期待一次富有成效的谈话!

我正在撰写《可操作的人工智能伦理》(Actionable AI Ethics),这本书将于 2021 年发布(曼宁),将帮助人工智能设计师和开发者从人工智能伦理的原则转向实践。

你可以在这里找到更多:https://actionableaiethics.substack.com

功能数据分析(FDA)

原文:https://towardsdatascience.com/introduction-to-functional-data-analysis-fda-c9d298e8fcf5?source=collection_archive---------16-----------------------

小窍门

照片由罗斯蒂斯拉夫·萨维钦Unsplash 拍摄

维度的诅咒是真实的。这听起来像是某种巫术,在处理高维数据时会引起实质性的问题。有不同的解决方案来减轻与高维度相关的问题,例如像主成分分析(PCA)或线性判别分析(LDA)这样的降维技术。降维的一个缺点是信息可能会丢失,新的变量可能更难解释。

在某些情况下,范式转换有助于保持可解释性并防止信息丢失。

在这篇博文中,我们将看到从高维空间转移到无限维空间如何简化数据分析。

介绍

好吧,我知道,“功能性数据”听起来很可怕,所以我们在进入细节之前先从一个例子开始。

图 1:2013-2017 年悉尼日最低气温;x 轴:时间,y 轴:摄氏温度;作者图片

假设我们对澳大利亚的气候感兴趣,观测了 2013 年到 2017 年的每日气温(见图 1)。对于每一年,我们有 365 次观察(不考虑闰年)。换句话说,我们可以把每一年看作一个 365 维的观察。现在,我们有 5 个 365 维的观测值,这是高维数据的经典设置。我们可以简单地继续处理这种类型的数据,但会遇到与维数灾难相关的问题。

这种方法听起来可能很合理,我们觉得自己像巫医(你知道——因为我们试图打破维度的诅咒),但这不是最有希望的方法。事实上,我们会忽略重要的信息。随着天气变暖,每日最低温度会平稳变化,因此将温度视为随时间变化的连续函数更有意义。

直觉上,将平滑变化的数据建模为连续函数是有意义的,但是这在数学上是如何工作的呢?和高维数据相比有什么区别?

假设我们有维度 dn 个观测值 X(1),…,X(n) ,那么每一个观测值 X(i) 都是一个d-维度向量 ( X(i,1),…,X(i,d) ) 。在上例中, n = 5d = 365 。被认为是在 d 维欧几里得空间中的向量,观测值具有 d 自由度。如果 d 增长到无穷大,那么维度和自由度也趋向于无穷大。这是有问题的,因为这些功能存在的空间在增长。

在上面的例子中,假设我们每年测量连续两年的温度 d 次,并且第二年的温度在任何时候正好比第一年的温度高一度,那么 ( X(0,1) + 1,…,X(0,d) + 1 ) = ( X(1,1),…,X(1,d) ) ,或者简单地使用 vectorX(0)+1 = X(1)这两年之间的欧几里得距离是

其随着每年的观察次数(即维度 d )增长到无穷大,这可能不是所期望的,因为温差保持恒定。转向函数数据范式有助于解决高维数据的这种(以及其他)不良行为。

走向功能数据

代替在 d 维欧几里德空间中的向量,我们可以考虑将 X(i) 的坐标作为一个底层函数Y(I)【X】的求值,对于 x【0,1】中,其中Y(I)【j/d)= X(I,j) 。例如,如果我们测量 1 月 1 日、4 月 1 日、7 月 1 日和 10 月 1 日的温度,我们将重新调整时间(1 月 1 日→0;4 月 1 日→1/4;7 月 1 日→ 1/2 和 10 月 1 日→ 3/4),并且对于年份 iX(i,“1 月 1 日”)= Y(i,0);X(i,“1 Apr”)= Y(I,1/4);X(i,“17 月 1 日”)= Y(i,1/2)X(i,“10 月 1 日”)= Y(i,3/4)

在许多设置中,假设函数 Y(i) 是连续的是合理的。在其他设置中,我们甚至可以假设函数是光滑的,即一次或多次可微。这些假设降低了函数的自由度。如果我们测量连续两年的温度,第二年的温度又比第一年的温度高一度,即 Y(0,x) + 1 = Y(1,x) ,那么这些函数的 L 距离为

这不依赖于每年的观察次数 d 。相同的数据,不同的计算,更好的解释结果。这就是功能数据分析的力量。

注:L-函数的范数和L-向量的范数有联系。如果我们把等式(1)两边分开,让 d 收敛到无穷,我们确实得到等式(2)。

另一个经常使用的范数是上确界范数,它不计算平方和,而是计算两点的最大距离。在上面的例子中,函数设置中的上确界范数与高维设置中的上确界范数一致,因为在两种情况下它都等于 1。

降维与变量选择

现在,如果我们有功能性数据,就有一些降维技术,它们执行起来很简单,也很容易解释,比如投影和变量选择。

给定一组函数 Y(i),i=1,…,n ,变量选择的目的是找到点 t(1),…,t(p) ,使得 Y(i) 在这些点的评估包含与函数 Y(i) 基本相同的信息【更多信息参见 Berrendero et al. (2016) 】。

通过投影减少维度与傅立叶分析有关。函数空间 L ([0,1]) ,即区间 [0,1] 上的平方可积函数空间,是一个希尔伯特空间,因此有一个正交基。这个空间中一个众所周知的基是傅立叶基

我们可以用它来估计函数 Y(i) 。更具体地说,我们可以计算阶为 p 的傅立叶级数

其对于足够大的 p 任意好地逼近 Y(i) 。例如,我们可以通过不同阶次的傅立叶级数来近似计算图 1 中的日温度,见图 2。

图 2:2017 年悉尼日最低气温,不同阶次的傅里叶近似(p=0,4,8,16);x 轴:时间,y 轴:摄氏温度;作者图片

变量选择和傅立叶基础上的投影都是高度可解释的。

函数空间中的数据科学和统计学

数据科学和统计学中的一些概念在功能空间和传统环境中是一样的。例如,k-最近邻算法可用于函数数据,唯一的区别是度量距离的选择( l vs. L )。

此外,函数时间序列的分析与单变量或多变量时间序列的传统分析非常相似:

其他概念也可用于功能数据,但它们的适应稍微复杂一些。比如,不清楚如何定义和解释随机函数的期望值:对于一个函数 Y(x)EY 是什么意思?好消息是,在最重要的连续或平方可积函数的情况下,期望值可以逐点解释: EY = E[Y(x)] ,即 Y(x) 的平均值等于 Yx 处计算的平均值,详见 Bücher et al. (2019)

基于函数数据的期望值,也可以推广两个样本的 t 检验和方差分析来比较各组观察值的均值函数,参见张等(2010)Cuevas 等(2004)

结论

功能数据在不同的环境中自然出现,例如股票的当天价格、年度温度曲线或脑电图数据。我们已经看到了一些例子并且有点(或者太多了?)功能数据理论。如果您想了解更多关于函数数据分析的信息,那太好了!确保签出链接的引用。如果你对功能数据不太感兴趣,那也没关系(是吗?),但在某些时候,FDA 可能也会对你有用。在这种情况下,只要记住:相同的数据,不同的计算,更好的解释结果。

如果你对时间序列感兴趣,这个可能适合你:

如果你一直想了解核密度估计或核回归:

如果您想查看时间序列分析在生产中监控 ML 模型的应用,请点击此处:

高斯过程编程介绍

原文:https://towardsdatascience.com/introduction-to-gaussian-process-programming-in-plain-english-8dd7a94cb18d?source=collection_archive---------33-----------------------

什么是高斯过程(GP),它为什么有用,以及如何实现它

我在网上找到的许多高斯过程(GP)的定义和解释很难阅读和理解。在这篇文章中,我将在梳理了许多资料后,尝试用尽可能简单的语言来解释 GP。此外,我将通过实现一个简单的 GP 程序来宣传为什么 GP 可以成为一个有用且强大的统计工具。

M. B. M.Unsplash 上拍摄的照片

注:在试图用更简单的语言解释 GP 时,我将不可避免地失去一些准确性。这篇文章不是用来作为正式的参考,而是作为一篇介绍性的文章。在这篇文章的最后,我会提供适当的资源让你了解更多。

目录:

  1. 为什么是高斯过程(GP)?
  2. GP 是什么?
  3. 如何实施自己的 GP 计划?

为什么是高斯过程(GP)?

假设你是一名气象员,收集了美国各地的一系列每日温度测量数据。你对气温的年度趋势有一个粗略的概念:夏季气温上升,冬季气温下降,其间偶尔会有一些波动。什么函数最能捕捉温度的季节性?二次方程足以估计这种趋势吗?或者其他多项式方程?

想到的直接解决方案是执行回归分析并插入最佳拟合线。是的,这肯定是可行的:有了这个最佳拟合方程,你现在可以预测一年中某一天的温度。

最佳拟合回归模型

但是,你的经理可能会问你以下问题:你对自己的预测有多少信心?手里拿着最佳拟合线,很难评估自己预测的不确定性程度,也很难准确评估自己的估计有多可能。

这就是高斯过程(GP)的用武之地。

GP 不仅给你精确的预测值,还给你其不确定度的范围

现在一个大问题来了,GP 到底是如何做到这一点的?为此,我们需要首先回答一个类似的相关问题:什么是 GP?

GP 是什么?

如前所述,GP 是点之间相似性的度量,用于从训练数据中预测未知点的值。然而,预测不仅仅是对该点的估计,而是由不确定性信息组成。

这种不确定性信息具有一维正态(高斯)分布,随着更多的点被输入并被模型学习,该分布不断更新(过程);因此有了术语高斯过程。

考虑下图。蓝色阴影区域是遵循高斯分布的不确定性范围。注意在有两个彼此靠近的点的区域中,蓝色阴影区域是如何缩小的?还有,在两个相邻点相距较远的区域,蓝色阴影区域是如何突然扩大的?

解释很直观:数据越少,不确定性越大,反之亦然。

图示了简单的高斯过程(GP)

这使得 GP 成为统计编程中一个极其强大的工具,在这种编程中,数据通常是稀疏的,预测很少是准确的。因为现在我们可以解释每一个预测的不确定性了!

现在我们对 GP 如何工作有了一些直觉,让我们使用我们在开始时介绍的类似温度案例研究来实现一个简单的 GP!

如何实施自己的 GP 计划?

对于这项研究,请点击此处下载温度数据集。

1.安装和导入软件包

首先,确保您的机器中安装了以下软件包。如果您还没有这样做,请在您的终端中运行这些命令。

$ pip install GPy
$ pip install shapely
$ pip install numpy
$ pip install pandas
$ pip install navpy
$ pip install geopandas

通过导入必要的包来完成这一步。

# Common libraries
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import geopandas as gpd
from shapely.geometry import Point, Polygon# Utilities
import copy# Gaussian Process library
import GPy

2.数据预处理

现在,让我们将温度数据集加载到 dataframe 对象中。

tmax_filename = './gt-contest_tmax-14d-1979-2018.h5'
sf_tmax = pd.read_hdf(tmax_filename)
df_tmax = sf_tmax.to_frame()
df_tmax = df_tmax.reset_index(level=[0, 1])df_tmax.head()

您将能够看到数据集的结构:对于每个唯一的温度记录,都有一个相应的时间( start_date )和空间( lat 和 lon )属性。

数据帧统计

不幸的是,我们有 750 万次测量!!

print("Full dataset shape:", df_tmax.shape)
>>> Full dataset shape: (7502858, 3)

对于我们当前的用例,让我们将分析限制在 2014 年 7 月 25 日的一个晴天。

analysis_date = pd.Timestamp('2014-07-25')df_full = copy.copy(df_tmax.loc[analysis_date, :])
df_full['date'] = df_tmax_date.index 

我们现在有了一个更容易管理的 514 记录!

print("Maximum tempreature:", df_full.shape)
>>> Maximum temperature: (514, 4)

3。数据可视化

在定义或拟合任何 ML 模型之前,一个好的实践是了解我们的数据是如何分布的。为此,让我们做一个快速的可视化程序。

首先,我们需要使用 geopandas 将数据框架转换为地理数据框架实例。

gdf = gpd.GeoDataFrame(copy.copy(df_full))

接下来,我们必须初始化要放置数据点的底图。

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
world = world.to_crs({'init':'epsg:4326'})

最后,我们将定义绘图(plt)对象。

ax = gdf.plot(ax=world.plot(figsize=(10, 6), color='grey'), marker='o', c=gdf["tmax"])

美国最高温度测量

到目前为止看起来很漂亮!

4.训练/测试数据分割

建模步骤之前的最后一步是将数据分为训练集和测试集。

df_shuffle = df_all.sample(frac=1.0, replace=False, axis=0)# Split the data with 33% training and 67% testing
df_split = np.array_split(df_shuffle, [df_shuffle.shape[0] // 3])df_train = df_split[0]
df_test = df_split[1]

5.培训全科医生

一个 GP 需要一个内核来评估不同的点对在数学上是如何的。虽然内核不在本文讨论范围之内,但是你可以在这里找到更多关于的信息。现在,我们将使用流行的径向基函数(RBF)核。

不要忘记定义我们的 X 属性(“坐标”)和 y 响应变量(“tmax”)。然后,我们可以简单地通过调用 GPy 包中的 GPRegression 函数来拟合模型,并将 X、y 和我们选择的内核作为属性传递。

X = np.array([df_train['lat'], df_train['lon']]).T
y = np.atleast_2d(np.array(df_train["tmax"])).Tkernel = GPy.kern.RBF(input_dim=2)m = GPy.models.GPRegression(X, y, kernel)# Plot the trained GP model
fig = m.plot()

高斯过程预测

在上图中,您有代表不确定性值的径向水平曲线。可用的训练数据越少,预测变得越不确定,颜色变得越浅。

结论

我们已经成功地介绍了 GP 的基础知识以及如何实现一个简单的 GP。我建议您尝试不同的可用内核,以便获得一些实践。此外,您可以执行一些内核优化(类似于超参数优化)来使您的模型性能更好。现在,你对 GP 有什么看法?

做订阅我的邮件简讯:https://tinyurl.com/2npw2fnz在这里我定期用通俗易懂的语言和漂亮的可视化方式总结 AI 研究论文。

进一步阅读

[1]https://peterroelants . github . io/posts/Gaussian-process-tutorial/

[2]http://Newton . CX/~ Peter/2014/03/elementary-Gaussian-processes-in-python/

[3]http://www . cs . Cornell . edu/courses/cs 4780/2018 fa/lectures/lectures note 15 . html

生成网络简介

原文:https://towardsdatascience.com/introduction-to-generative-networks-e33c18a660dd?source=collection_archive---------29-----------------------

Unsplash 上的 Pietro Jeng 拍摄

什么是 GANs,它们是如何工作的?

根据该领域几位著名专家的说法,GANs 是过去十年中机器学习领域最令人兴奋的发现。2014 年,Ian J Goodfellow 的一篇文章首次提出了 GANs 的想法,自发现以来,该想法一直非常受欢迎。

gan 是生成网络领域的一大进步。以前,生成工作是使用变分自动编码器完成的,变分自动编码器采用重新参数化策略,并基于从特征分布中随机生成的数字。这导致 VAEs 创建非现实的图像。GANs 在这方面做得更好。

在这篇文章中,我们将看到生成网络背后的思想,生成网络的类型,以及它们的工作方式

生成网络背后的思想

让我们用一个简单的例子来理解这个想法。假设我们有尺寸为 100 x 100 的小狗的 RGB 图像。因此,我们将有 100×100×3 = 30000 个不同的像素。我们乘以 3,因为 RGB 在图像中有 3 个通道。现在,如果我们展平图像,我们将得到一个 30000 维的向量。

图像可以表示为 30000 维向量空间中的点向量。类似地,如果我们将小狗图像数据集中的所有图像绘制成向量空间上的点向量,我们将得到图像的整个分布。所以,从分布中,我们可以得到一个清晰的思路,3 万维向量空间中的哪些点可以代表一只小狗。

从上图我们可以得出一个想法,蓝点分布就是数据集小狗图像的分布。现在,如果我们可以从这个向量空间中选择任何一个点向量,我们将能够使用给定的分布获得这个点成为小狗图像的概率。由于蓝点代表数据集中用于创建分布的所有点,所以代表小狗的所有点的概率之和必须等于 1。简而言之,我们正在使用数据集中的样本创建一个概率密度分布。

现在,如果我们考虑点 1 和点 2,与点 2 相比,点 1 更有可能代表一只小狗,这在图表中非常明显。因此,要生成原始数据集中没有的图像,我们只需从给定数据集创建的概率分布中随机抽取一个向量点。

上述方法的问题是给定的分布太复杂,无法从中取样。上面的图像是一个简化的表示,但在实际情况下,我们有大量的维度,分布变得过于复杂。无法采样的原因是我们无法真正获得给定分布的分布函数,也不可能生成如此复杂的随机变量。

为了解决这个问题,我们使用转换。在这种方法中,我们生成一个随机变量来创建一个简单的均匀随机分布。然后,我们使用一个复函数来转换这个简单分布,将我们的简单分布转换成我们需要的复杂分布。这里我们知道分布函数,可以从中随机抽样。

我们已经找到了一种方法来创建数据集给出的复杂分布,现在实现的挑战来了。为了转换信号,我们实际上需要复杂的分布函数,当然我们没有。我们所拥有的是数据样本,我们可以绘制这些样本来获得分布。因此,我们使用两种分布,一种是通过绘制样本获得的 N 维复数分布,另一种是通过生成 N 个均匀随机变量(每个维度一个)创建的。我们现在有两个分布,都是 N 维的。

我们可以使用伪随机数发生器生成简单的随机均匀变量。它生成一个近似于 0 到 1 之间的随机分布的数字序列。

正如我们在上面看到的,我们创建了 N 变量均匀分布,并使用复变函数将其转换为类似于给定的复变分布。因此,我们可以将数据集中的点绘制为样本,以获得分布,并将两个分布拉近,使它们相似,如上图所示。因此,我们可以创建一个分布,并将其转换为给定的复杂分布,并从中进行采样,以生成所需的输出。需要注意的一点是,在创建新的均匀随机分布后,我们进行上采样,以便我们可以比较和转换,用新创建的分布来逼近原始的复杂分布。

实施

因此,到目前为止,我们已经知道,我们的实际任务是制定一个复杂的函数,我们可以使用它将我们创建的简单正态均匀分布转换为给定的复杂分布。我们知道我们可以用神经网络来表达转换的函数。神经网络使用一定程度的非线性,这使得神经网络可以设计任何所需的复杂函数。因此,神经网络充当转换功能。

现在,根据它们用来执行任务的程序,有两种类型的生成网络架构是可能的。

  1. 生成匹配网络
  2. 生成对抗网络

所以,让我们来看看他们的工作方式。

生成匹配网络

生成匹配网络是解决这一问题的直接方法。它只是试图最小化生成的分布和实际复杂分布之间的距离。它选取一些随机样本,生成分布,并在每次迭代后计算生成的分布与实际分布之间的差异。该差作为误差,通过模型反向传播,并且使用梯度下降来更新模型参数。我们再次获得生成的分布,并继续上述过程。

上图代表 GMN。现在,在每次迭代中,我们将真实分布与每个阶段生成的分布进行匹配以生成误差,我们称之为生成匹配网络。对于每一个神经网络的工作,我们需要一个损失函数,网络最小化。从上面的讨论中,很明显,在这种情况下,损失函数是生成的分布和真实分布之间的差异或距离。

现在,出于这个目的,我们可能已经使用了任何损失函数,例如计算两个给定分布之间差异的 KL 散度,但是最大平均差异(MMD)被用作 GMT 情况下的损失函数。MMD 定义了两个概率分布之间的距离,可以基于这些分布的样本来计算(估计)该距离。关于 MMD 的细节可以在她的文章中找到。我们的神经网络的主要目标是最小化 MMD 误差或损失函数。需要注意的一点是,网络的输入是随机生成的 N 维点向量,在这些情况下被视为噪声。

我们很少使用 gmn,因为它们很难建立和训练。

让我们揭开最常用的生成网络 gan,并深入了解其概念。

生成对抗网络

一般敌对网络被认为是一种解决问题的间接方法。gan 训练发电机网络来完成一项任务,从而减少原始分布和生成分布之间的差异。这里的任务是增加鉴别器模型的误差。因此,由于我们没有直接研究真正的动机,我们称之为“敌对”网络。

现在,让我们详细说明 GANs 的工作原理。GANs 有两个神经网络,一个生成器和一个鉴别器。生成器生成矢量点,鉴别器的功能是在生成的点和真实数据点之间进行鉴别。因此,鉴别器试图通过正确识别生成的数据来减少分类误差,而生成器试图通过生成更好的数据点来增加分类误差。

这个网络背后的想法是基于博弈论中的均衡概念。这被称为纳什均衡。

在博弈论中,以数学家小约翰·福布斯·纳什命名的纳什均衡是定义涉及两个或更多玩家的非合作游戏的解决方案的最常见方式。在纳什均衡中,每个参与者都知道其他参与者的均衡策略,没有人会因为只改变自己的策略而获益。维基百科。

两个模型,鉴别器和生成器,同时被训练以在两人游戏中击败对方并达到纳什均衡。我们可以理解,在现实世界的双人游戏中,一个玩家的行动会影响另一个玩家的行动。类似地,这里发生器的目标根据鉴频器产生的误差而移动。如果目标或鉴别器误差在变化或移动,发生器将很难工作。因此,为了避免这种情况,在生成器训练期间不训练鉴别器,反之亦然。但重要的是,这两种模式一起学习,以使它们趋同。所以,首先,我们训练鉴别器,然后我们继续训练发生器。

GAN 模型

上图显示的是 GAN 模型。这是谷歌开发者基于原始设计的一个设计。正如我们所看到的,生成器依赖于鉴别器。

现在,鉴频器损耗只是反向传播到鉴频器网络。发电机损耗通过鉴别器反向传播到发电机。鉴别器的权重在生成器训练期间被冻结,使得它们不会由于生成器训练期间的反向传播而被更新。

程序:

  1. 发生器和鉴别器都被初始化。
  2. 随机噪声被传入生成器,用于创建假的或生成的实例。
  3. 生成的实例和真实的实例一起被传递给鉴别器。
  4. 鉴别器试图将假实例分类为假实例,将真实实例分类为真实实例
  5. 获得了鉴别器和发生器损耗
  6. 损失被反向传播,鉴别器和发生器被相继训练。

上述步骤显示了在一个时期内训练 GAN 的过程。最初,鉴别器表现出色,因为生成器根本没有经过训练,生成的输出与实际情况相差甚远。

损失函数

我们知道,对于任何要训练的网络,我们都需要一个损失函数,通过鉴别器网络和生成器网络来学习,这个损失函数将最小化。

在介绍性论文中,GAN 的损失函数被提议为最小最大损失。极大极小损失也是从博弈论的极大极小算法发展而来的。我试着举个例子。

比如说,两个玩家玩一个游戏,比赛。博弈论表明,整个游戏和双方在游戏的每个阶段的每一个可能的举动都可以用一个 n 元树结构清楚地表示出来。n 的值取决于游戏和移动的类型。这叫做博弈树。现在,我们可以根据赢得游戏的潜力来给玩家的棋打分。这就叫效用。所以,走得最好的人有最大的效用,他/她就赢了。效用不过是解释获胜可能性的一种方式。

我们可以看到,要想赢,一个玩家必须最大化自己的效用,最小化对手的效用。但是为此我们必须找出对手能做出的最好的移动,所以我们也需要找到他们未来最大效用的移动。因此,算法需要我们进行递归调用来最大化和最小化。所以,这个算法叫做极小极大算法。你可以在这里阅读更多关于这个算法的内容。

上述等式显示了鉴频器损耗函数。E(x)是概率和的期望值。D(x)是鉴别器预测实例 x 为真实的概率。G(x)是随机噪声 x 产生的输出,z 是给定的随机噪声。

在这个等式中,第一部分对应于真实的实例。x 是实数,因此,这里 D(x)需要为 1 或更接近 1,鉴别器才能更好地工作。我们需要第一部分的价值增加。还是那句话,G(z)是假的,所以我们需要 D(G(z))低,所以,我们尽量增加(1- D(G(z))。这种损失类似于交叉熵损失。这是鉴频器损耗。鉴别器试图最大化上面给出的损失函数,相反,它试图最小化它的负值。

发电机以相反的方向工作。因此,它试图最小化给定的损失函数。第一部分不受发生器的影响。所以,它只影响第二部分(1-D(G(z))。生成器最小化(1-D(G(z)))或最大化 D(G(z))。因此,它希望鉴别器为生成的实例预测成为真实实例的高概率。

挑战

gan 在应用和设计方面面临一些挑战。来说说他们吧。

  1. 我们知道,发电机是由鉴频器损耗驱动的。最初,鉴别器很容易区分真实实例和生成实例,因此生成器学习得很好,但是在生成器经过训练并开始生成与真实实例非常相似的生成实例之后,鉴别器的任务变得非常困难,并开始表现得幼稚。实例的预测概率变为 50%。因此,在这一点上,发电机被训练在最佳水平。现在,发生器必须停止使用鉴频器损耗进行训练,否则发生器将开始表现不佳,因为它正在对错误的输入进行训练。网络的训练必须停止在某一水平。
  2. 最初,鉴别器很容易对数据实例进行分类。因此,它可以很容易地将假的归类为假的,将真实的实例归类为真实的。现在,如果鉴频器完美地做到了这一点,鉴频器损耗变为零,无法最小化,这会导致 GANs 在训练的早期阶段进入次优状态。同样,如果损耗太小,即鉴别器正确地预测了它们中的大部分,由于消失梯度问题,损耗不会反向传播到发生器,再次使发生器失败。这再次导致次优状态。这被称为消失梯度问题
  3. 第三类问题是存在的。这是众所周知的。这就是所谓的模式崩溃问题。有时,鉴别器会遇到次优的局部最小值,无法进一步优化。如果损失非常小并且在反向传播过程中消失,这实际上也会发生。这导致鉴别器不能正确识别一些实例。鉴别器需要更新其权重并自我校正,但由于次优状态而失败。现在,生成器需要创建不同类型的实例。但是如果它得知鉴别器不能识别特定类型的实例。它生成相同数据的多个实例,并欺骗鉴别器。鉴别器永远不会逃脱陷阱,因此生成器会过度优化自己。

修正损失函数

上述问题证明,我们必须修改损失函数,以消除消失梯度的挑战。让我们看看修改后的损失函数:

  1. 修正的极大极小损失:已经确定,在极大极小损失中,如果对于生成器,不是最小化 log(1-D(G(z)),而是直接开始最大化 log(D(G(z)),则消失梯度问题得到解决,并且模型性能提高。因此,损耗被适当地传播,并且次优状态被避免。
  2. 瓦瑟斯坦损失:瓦瑟斯坦损失的概念是从推土机的距离建立的。

在统计学中,推土机距离(EMD)是区域 d 上两个概率分布之间距离的度量。在数学中,这被称为 Wasserstein 度量。非正式地,如果分布被解释为在区域 D 上堆积一定量的灰尘的两种不同方式,EMD 是将一堆变成另一堆的最小成本;其中成本假定为移动的灰尘量乘以移动的距离。

推土机的距离可以公式化并作为运输问题来解决。假设有几个供应商,每个供应商都有给定数量的货物,需要供应给几个消费者,每个消费者都有给定的有限能力。对于每一对供应商-消费者,运输一件商品的成本是已知的。运输问题就是找到一条从供应商到消费者的最便宜的物流路线,满足消费者的需求。—维基百科

因此,推土机的距离基本上给出了移动一个分布的点以匹配另一个分布所需的最小成本。利用这种损耗的 GAN 称为 Wasserstein GAN 或 WGAN。这里,鉴别器并不试图将实例分类为生成的或真实的。鉴别器分配一个分数。鉴别器试图为真实实例分配比虚假实例更大的分数。没有这样的截止日期。只是分配给真实实例的数量要大得多。现在,由于歧视者不分类,它被称为评论家。这种损失被称为评论家损失。生成器试图增加虚假实例的分数。

批评家损失: D(x) — D(G(z))

发电机损耗: D(G(z))

D(x)是 x 实例的评论家的输出值。正如我们从批评家的损失中看到的,批评家试图增加真实和虚假实例的输出值之间的差异。所以,它最大化这个函数或者最小化它的否定。类似地,生成器试图增加或最大化鉴别器给生成的实例的输出值。这些值不限制在 0 和 1 之间,并且具有较大的值,因此不存在渐变消失的问题。

结论

在这篇文章中,我们已经看到了生成网络的介绍,并侧重于 GAN。

我希望这有所帮助。

使用 EasyGA Python 包介绍遗传算法——带示例代码

原文:https://towardsdatascience.com/introduction-to-genetic-algorithms-using-the-easyga-python-package-includes-example-code-c6591eb56215?source=collection_archive---------21-----------------------

创建遗传算法应用程序比以往任何时候都容易。

照片来自 Unsplash,作者是 Clément Hélardot

一种遗传算法是达尔文自然进化论的产物。该算法是围绕自然选择的思想建立的,在自然选择中,群体中的个体进行繁殖,希望产生更好的后代。这个过程会持续多代,希望能产生想要的结果。

有了 python 包,这个复杂的过程被简化了。asyGA python 包 将编写一个合适的 GA 的复杂而耗时的过程缩短到了几分钟,而不是几个小时。

遗传算法介绍—包括示例代码

先说一个初学者的例子。当我第一次开始写自然选择算法时,我受到了 Vijini Mallawaarachchi 的介绍性文章的启发,所以对我来说,利用她在基因库中得到所有 1 的问题是很自然的,或者在这种情况下,我们将基因库称为染色体。

首先,您需要安装 python 包。

pip3 install EasyGA

下面是她使用 EasyGA 解决问题的完整示例代码。

作者编写的代码。

输出:

Current Generation     : 1
Best Chromosome     : [1][1][0][0][1]
Best Fitness        : 3
--------------------------------------------------
Current Generation     : 2
Best Chromosome     : [1][1][0][1][1]
Best Fitness        : 4
--------------------------------------------------
Current Generation     : 3
Best Chromosome     : [1][1][0][1][1]
Best Fitness        : 4
--------------------------------------------------
Current Generation     : 4
Best Chromosome     : [1][1][1][1][1]
Best Fitness        : 5

如你所见,我们创造了一种遗传算法来解决我们染色体中有五个 1 的问题。对于如此强大的软件包来说非常简单。让我们试试另一个例子,一个求根算法。维基百科中定义的求根算法:

在数学和计算中,求根算法是一种寻找零的算法,也称为连续函数的“根”。从实数到实数或从复数到复数的函数 f 的零点是一个数 x ,使得 f ( x ) = 0。

在小学/高中,我们被教导如何化简方程来求根。然而,在这个例子中,我们将使用遗传算法来完成这项工作。不再多想,直接输入,得到答案。

我们的求根函数。作者照片。

下面是我们将要做的事情的安排。如你所见,EasyGA 不仅允许我们运行复杂的遗传算法,而且只用了 33 行 python 代码就完成了。

作者编写的代码。

输出:

图片作者。

输出:

Current Generation     : 10000Chromosome - 0:

[0.0004391616070176241]
[-0.00018549426948410996]
[0.0014267659834530377] Fitness = 2.26293221262846e-06Chromosome - 1:
[0.0004391616070176241]
[-0.00018549426948410996]
[0.0014267659834530377]Fitness = 2.26293221262846e-06Chromosome - 3:[0.3639195265169164]
[-0.00018549426948410996]
[0.0014267659834530377] Fitness = 0.00013243949184959217Chromosome - 4:[0.3639195265169164]
[-0.00018549426948410996]
[0.0014267659834530377]Fitness = 0.00013243949184959217
etc

摘要

在本教程中,我们展示了如何使用 EasyGA Python 包在基因库问题中简单地“寻找所有的 1 ”,然后用它来寻找数学方程的根。

包安装后,需要五个步骤来运行 EasyGA:

  • 进口 EasyGA
  • 设置您的 gene_impl 或 chronous _ impl 变量
  • 创建和定义你的健身功能
  • 进化你的遗传算法
  • 最后,使用图表或打印您的解决方案来打印您的结果。

如果你想了解我的研究和其他活动的最新情况,你可以在 YoutubeGithub 甚至 Twitch 上关注我做一些现场编码。

感谢您的阅读,
丹尼尔·威尔扎克

连续域函数的全局优化算法介绍;

原文:https://towardsdatascience.com/introduction-to-global-optimization-algorithms-for-continuous-domain-functions-7ad9d01db055?source=collection_archive---------19-----------------------

蚁群优化(ACO)算法来救援!!

Salmen BejaouiUnsplash 上拍摄的照片

在本文中,我将概述蚁群优化(ACO)算法的实现(带有示例代码)以及如何使用它来解决一些常见基准连续域函数的优化(最小化)。ACO 算法属于所谓的自然启发的元启发式算法家族,这种算法在机器学习领域越来越受欢迎。

这篇文章的结构如下:

  • 介绍
  • 问题说明
  • 蚁群算法
  • 代码实现细节
  • 基准测试结果
  • 结束语
  • 参考
  1. 简介

全局优化是数学和计算机科学的一个分支,它开发的算法可用于寻找连续域函数或给定数据集的一组函数的全局最小值或最大值[1]。各种各样的最优化问题出现在许多定量学科中。机器学习(ML)中的一些例子包括:

  • ML 算法的超参数优化[2]
  • ML 算法特征选择[3]
  • 深度学习或经典 ML 算法的损失/成本函数优化[4,5]
  • 神经网络最佳架构设计[6]
  • 最佳路径优化——如旅行推销员问题[7]

一般来说,优化问题包括通过在其边界内迭代地选择 N 个输入并计算函数值来最小化(或最大化)连续 N 维函数的计算。

全局优化算法可以大致分类如下:

  • 确定性全局优化[8]
  • 元启发式全局优化[9]

ACO 是一个自然启发的元启发式优化例程,本文将主要关注这个算法。然而,还有许多其他自然启发的元启发式优化算法,其中一些包括:

  • 模拟退火
  • 遗传算法
  • 粒子群优化
  • 人工蜂群优化
  • 多方面优化
  • 蝙蝠算法优化
  • 萤火虫算法
  • 和许多其他的,进一步的细节可以在[10]中找到

我将在以后的文章中探讨这些元启发式算法。本文的下一部分将描述问题规范。

2。问题说明

问题规格是使用 ACO 算法解决 5 个基准经典连续域函数的最小化。这些功能是:

  1. Rosenbrock 具有属性[11]:
  • 维数,d = 10
  • Xi ∈ [-5.0,10.0],对于所有 i = 1,…,d
  • 在 X* = (1.0,…,1.0)处,f(X*) = 0.0

2.具有属性[12]的 Ackley:

  • 维数,d = 10
  • Xi ∈ [-32.768,32.768],对于所有 i = 1,…,d
  • 在 X* = (0.0,…,0.0)处,f(X*) = 0.0

3.球体[13]具有以下属性:

  • 维数,d = 10
  • Xi ∈ [-5.12,5.12],对于所有 i = 1,…,d
  • 在 X* = (0.0,…,0.0)处,f(X*) = 0.0

4.Styblinski-Tang 具有属性[14]:

  • 维数,d = 10
  • Xi ∈ [-5.0,5.0],对于所有 i = 1,…,d
  • f(X) = -39.16599d,X = (-2.903534,…, -2.903534)

5.具有属性[15]的 Rastrigin:

  • 维数,d = 10
  • Xi ∈ [-5.12,5.12],对于所有 i = 1,…,d
  • 在 X* = (0.0,…,0.0)处,f(X*) = 0.0

3。蚁群算法

用于解决上一节中描述的最小化问题的 ACO 算法的伪代码概述如下:

ACO 作者伪代码

例如,阿克利问题(在第 2 节中描述)有 10 个变量(d = 10)的 Xi,每个变量有一个连续的域边界:Xi ∈ [-32.768,32.768]。Ackley 函数的 3D 图如下所示(即,自然地,该图针对维度 d = 2):

作者绘制的“Ackley”基准问题的三维图

算法输入/输出为:

由作者输入 Ackley 问题的 ACO 参数

按作者输出“Ackley”问题的 ACO 结果

“Ackley”问题目标函数的期望值为:

在 X* = (0.0,…,0.0)处,f(X*) = 0.0

结果表明,蚁群算法在优化最小搜索方面表现良好。ACO 计算的收敛图如下所示:

作者的 ACO 优化‘Ackley’问题的收敛图

4。代码实现细节

ACO 算法的实现是用 Python 编写的,代码的 Github repo 可以在这里找到。这段代码部分是由[16]提供的 Matlab 实现的 python 移植,是对 ACO 群体智能[17]的一篇论文的解释。用于调用 ACO 算法的核心组件是 AcorContinuousDomain 类。可以通过向构造函数提供以下参数来构造该类:

  • 蚂蚁种群数量大小(__n_pop)
  • 被优化的连续函数的变量/维数(__n_vars)
  • 正在优化的成本函数(__cost_func)
  • 被优化的成本函数的上界和下界(__domain_bounds)

如以下代码片段所示:

要调用 ACO 算法主循环并获得最优解,请使用以下代码片段:

请注意,ACO 代码利用助手类 ProblemConstantsAcoConstants 来指定问题域用例以及超参数配置,如以下代码片段所示:

用于演示 ACO 算法的代码路径可以在 Client.py 模块中找到。该模块包含 runAcoClient()函数,该函数可用于演示特定问题用例的 ACO 解决方案,如以下代码片段所示:

5。基准测试结果

除了为 Ackley 连续域问题/函数获得的结果(在第 3 节中描述)。本节概述了对其他 4 个连续域问题/函数(在第 2 节中描述)获得的测试结果,即:

  • 罗森布罗克
  • 范围
  • 斯蒂布林斯基-唐
  • 拉斯特里金

请注意,这些函数是使用 ACO 算法求解的,其中维度/变量的数量设置为 2。这些函数的三维图如下所示:

作者绘制的 Rosenbrock 函数图

作者绘制的球面函数图

作者对汤功能的构思

作者绘制的栅格函数图

每个问题使用的 ACO 算法输入和结果输出如下:

作者提出的“Rosenbrock”问题的输入参数和输出结果

作者提出的“球体”问题的输入参数和输出结果

作者提出的“Styblinski-Tang”问题的输入参数和输出结果

作者的“光栅化”问题的输入参数和输出结果

6。结束语

本文向观众介绍了蚁群优化(ACO)的自然启发元启发式技术的使用。在这种情况下,用于多元连续函数的最小化(或最大化)。

它提供了如何用 python 实现 ACO 算法的分步演示。它还展示了 ACO 算法在一组经典的基准连续域优化问题上令人印象深刻的收敛特性(当配置了适当的 ACO 超限仪时)。

在我以后的文章中,我将探索使用其他自然启发的元启发式算法来优化连续域问题。

7。参考文献

[1] 数学优化 (2021),维基百科

[2] 超参数优化 (2021),维基百科

[3] 特征选择 (2021),维基百科

[4] H. Martin 等,卷积神经网络的元启发式算法 (2016),计算智能与神经科学

[5] Z. Ahmed,训练神经网络(Numpy) —粒子群优化(PSO) (2020),中

[6] B. A .加罗和 R. A .瓦兹奎使用粒子群优化算法设计人工神经网络 (2015),计算智能和神经科学

[7] V. Chandra 使用优化技术的选址和最佳路径—加拿大邮政示例 (2020),中等

[8] 确定性全局优化 (2020),维基百科。

[9] 元启发式 (2021),维基百科

[10] F. Aljarah 等人,EvoloPy:Python 中一个受自然启发的开源优化框架 (2016),载于《第八届国际计算智能联合会议论文集》(IJCCI 2016) -第 1 卷

11s . Sonjanovic 和 D. Bingham。,模拟实验虚拟图书馆:测试函数和数据集-罗森布罗克函数 (2013),西蒙弗雷泽大学

12s . Sonjanovic 和 D. Bingham。,仿真实验虚拟库:测试函数和数据集-阿克利函数 (2013),西蒙弗雷泽大学

13s . Sonjanovic 和 D. Bingham。,仿真实验虚拟库:测试函数和数据集-球函数 (2013),西蒙弗雷泽大学

14s . Sonjanovic 和 D. Bingham。,仿真实验虚拟库:测试函数和数据集- Styblinski-Tang 函数 (2013),西蒙弗雷泽大学

15s . Sonjanovic 和 D. Bingham。,仿真实验虚拟库:测试函数和数据集- Rastrigin 函数 (2013),西蒙·弗雷泽大学

16m . k .赫里斯。,MATLAB 中连续域的 ACO(2015),Yarpiz

[17]国际法院里亚迪案。,认知蚁群优化:群体智能的新框架 (2014),博士论文,英国曼彻斯特索尔福德大学

Github

ACO 实现的完整代码(包括单元测试)可以在这里找到。

感谢您阅读本文!

你可以通过 Github 和我联系

Python 中 Google 的 Compact Language Detector v3 简介

原文:https://towardsdatascience.com/introduction-to-googles-compact-language-detector-v3-in-python-b6887101ae47?source=collection_archive---------27-----------------------

一种用于语言识别的神经网络模型

汉娜·赖特在 Unsplash 上拍摄的照片

通过阅读这篇文章,你将学会使用 Google CLD 3 的 Python 绑定来检测和识别文本中使用的语言。供您参考,Compact Language Detector v3 (CLD3)是 Google 发布的一个语言识别包。在撰写本文时,它已经对大多数通用语言提供了巨大的支持。您可以在以下链接中找到完整列表。

它包含基于 C++的训练模型和推理代码。根据官方文档

“…推理代码从输入文本中提取字符 ngrams,并计算每个字符出现的时间。

该模型根据分数平均对应于每个 ngram 类型的嵌入,并且平均的嵌入被连接以产生嵌入层。网络的其余组件是一个隐藏(校正线性)层和一个 softmax 层。"

CLD3 的基本架构如下,使用banana作为输入文本:

图片取自 CLD3 的 Github 页面

自 2020 年 8 月底以来,他们发布了一个官方的 Python 包,其中带有 Python 推理代码。从官方库中查看下面的代码,了解基于pybind包的实际实现。

让我们继续下一部分,开始安装必要的模块。

设置

为了从 PyPI 安装 CLD3,您需要在本地计算机上安装以下附加软件包:

  • Protobuf 编译器是protoc的可执行文件
  • Protobuf 开发头文件和libprotoc
  • 一个编译器,最好是g++

原蟾蜍

如果您使用的是 Debian/Ubuntu 操作系统,请运行以下命令:

sudo apt-get install -y --no-install-recommends g++ protobuf-compiler libprotobuf-dev

有关其他操作系统安装过程的更多信息,请查看自述文件中的

CLD3

强烈建议您在继续安装之前创建一个虚拟环境。激活它并在您的终端中运行以下命令来安装 CLD3 的官方 Python 绑定:

pip install gcld3

履行

一旦安装了所有必需的包,就可以直接在 Python 脚本中使用它。创建一个名为test.py的新 Python 脚本。

导入

在文件顶部添加以下 import 语句。

import gcld3

语言标识符对象

接下来,初始化一个新的NNetLanguageIdentifier对象。

detector = gcld3.NNetLanguageIdentifier(min_num_bytes=0, max_num_bytes=1000)

它接受以下参数:

  • min_num_bytes:推断时要考虑的最小字节数。将此项设置为大于 0 的值将返回空字符串的und
  • max_num_bytes:推断时要考虑的最大字节数。如果输入文本超过了设置的值,它将截断多余的字节。

如果您想过滤掉空字符串和短字符串,可以按如下方式初始化实例:

detector = gcld3.NNetLanguageIdentifier(min_num_bytes=10, max_num_bytes=1000)

检测单一语言

CDL3 附带了两个推理函数。第一个是用于单一语言推理的FindLanguage函数。它接受代表样本文本的单个text参数。

sample = "Welcome to Medium."
result = detector.FindLanguage(text=sample)

它返回一个包含以下字段的Result对象:

  • language:BCP 47 式表示的语言代码。
  • is_reliable:反映检测可靠性的布尔值。
  • proportion:float,表示样本文本中预测语言的比例和权重。范围从 0 到 1。该字段在多语言检测过程中很有用。
  • probability:预测的置信度。范围从 0 到 1。

只需如下调用每个字段即可获得相应的值:

result.languageresult.is_reliableresult.proportionresult.probability

检测多种语言

您应该使用FindTopNMostFreqLangs来检测多种语言。除了text参数,它还接受另一个名为num_langs的整数参数。

sample = ("Welcome to Medium. Bienvenido a Medium.")
results = detector.FindTopNMostFreqLangs(text=sample, num_langs=2)

FindTopNMostFreqLangs返回一个Result对象列表。只需在一个循环中调用相应的字段,就可以获得所需的输出。

for i in results:
    print(i.language)

请注意,列表长度基于num_langs。如果将它的值设置为 5,它将返回列表中的 5 个Result对象。

你可以在下面的要点中找到完整的代码。

结论

让我们回顾一下你今天所学的内容。

本文首先简要介绍了 Google 的 Compact Language Detector v3 背后的基本架构和概念。

接下来,它讲述了基于您所拥有的操作系统的安装过程。CLD3 的 Python 包通过pip install安装。

在实现部分,以FindLanguageFindTopNMostFreqLangs函数为基础进行说明。这两个函数都返回a single或一个包含一些有用参数的Result对象列表,如languageprobability

感谢你阅读这篇文章。希望你会回来看我的其他文章!

参考

  1. Github — CLD3
  2. PyPI — gcld3

点击流数据的图形模型介绍

原文:https://towardsdatascience.com/introduction-to-graph-models-for-clickstream-data-c2bc44da90bb?source=collection_archive---------16-----------------------

来自模拟教室的教育示例

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

简介

每当我们分析人们如何与数字内容互动时,我们倾向于将人们的行为视为他们思想和情感的表达。但这只是硬币的一面。人们行动的环境(在线或离线)对人们与之互动的方式有着重要的影响。

图片和大的浮华元素吸引注意力,页面底部的小东西经常被忽略。如果我们想创造有意义的数字旅程,让人们的生活更轻松,我们需要了解数字内容对用户及其行为有什么影响。

但是我们怎样才能理清这两种影响的来源呢?在班伯格大学,我参与了一个在教育背景下解决这个问题的研究项目。我来详细说明一下。

研究背景

让我们想想学校。

我们想知道老师们对学生成绩的判断究竟是如何形成的。由于真实的教室是一个高度复杂和互动的环境,我们选择了一个参与者可以在电脑上工作的模拟版本。通过这种方式,我们可以记录每一次鼠标点击,并最终获得一组点击流数据。但是如何处理这些数据呢?

这就是 指数随机图模型【ERGM】进入的阶段。但是我们先来看看研究设置。

实验设置

我们选择了 12 个不同类型的数学任务,难度范围很广。学生能力通过每个学生达到的最高任务难度 T30 来操作。当任务难度超过特定学生的能力时,学生解决特定任务的概率从 1 变到 0(参见确定性潜在特质模型[1])。我们版本的模拟教室如下图所示。

模拟课堂软件截图。图片作者。

最初,参与者必须估计 12 个项目的难度。在第二步中,呈现六个学生描述,指示学生的姓名年龄性别兄弟姐妹数量及其父母的职业,以便给出潜在相关和不太相关的信息。下图给出了两个示例说明。

图片作者。

在模拟教室中,参与者可以使用最初评估的 12 个项目来评估六名模拟学生的能力,目的是对六名模拟学生的能力做出判断。分配给学生的每个项目被视为一次互动。在模拟教室中完成评估后,参与者必须用 11 分的李克特量表(Likert-Scale)从 0 到 100 分评估学生的数学能力。

样品

样本由 37 名德国中学教师组成。59%的参与者是女性。参与者平均有 11.37 年(标准差= 10.13)的教学经验。

我们来谈谈网络。

点击流网络

点击流数据可以理解为在基于模拟或数字的环境中工作期间采取的一系列行动。该序列中的每个操作都记录在日志文件中。对于每一步,参与者可以从一组有限的可能行动中进行选择。未来的行动通常会受到先前行动的影响。

这些点击流数据可以表示为网络。每个节点代表一个动作,节点之间的有向边表示从一个动作到下一个动作的转换。乏色曼和浮士德[2]将这些类型的网络描述为加权有向网络有向图。那些可以定义为一组节点 V = {v1,v2,…。,vg),一组连杆 L = {l2,l2,…,lt)和一组连杆的权重 W = {w1,w1,…wg}。这种网络可以用一个 g x g 邻接矩阵 M 来描述。节点以行和列来表示,单元中的数字表示从行中的节点到列中的节点的转换被选择的频率

定义节点至关重要

我们将节点定义为一个项目被分配给一个学生。有了 12 个项目和 6 个学生,这就形成了一个 72 节点的网络,每个学生-任务组合有一个节点。因此,每个节点代表两个选项,一个用于项目,一个用于学生。

由于参与者被限制在最多 50 个动作,导致 49 条纽带代表节点之间的顺序交互,单个网络非常稀疏。因此,样本被分为两组的基础上,判断准确性的估计学生的能力。他们的能力判断和学生的经验能力之间的等级相关性 r = .70 或更高的参与者被认为具有高的判断准确性。每个群组的 r < .70 was considered to be low. This results in n(high) = 25 and n(low) = 12 participants. By adding up the 个邻接矩阵的等级顺序关联我们最终得到了两个群组网络,它们更加紧密连接

指数随机图模型

一般来说,任何观测值之间存在潜在依赖关系的系统都可以被视为一个网络。应用标准回归方法并因此忽略相关性会导致有偏估计,并违反回归模型中的假设,即观察值必须相互独立且同分布。

指数随机图模型 (ERGMs)允许我们显式地对这些依赖关系建模。ERGMs 的重点是描述二元一元高阶机制协变量共同导致观察到的结构【3】。ERGMs 建立在网络统计数据(例如,边的数量、相互关系(互惠)的数量或中心性度量)的基础上,并根据这些统计数据为图形分配一个概率:

给定网络 N 的概率由网络统计量之和除以与 N 具有相同边数和相同网络统计量的 N 的所有排列之和给出。 θ 是网络统计量 h( N )的系数向量。

ERGM 的输出,即 θ 系数估计值可以解释为类似于回归模型的输出。对应于结构特征(如互易性)的系数的积极且显著的影响意味着该特征出现的频率比预期的要高[4]。对应于节点属性(协变量)的系数的解释是不同的。在这种情况下,连接两个节点 I 和 j 的边的条件对数优势被理解为增加了两个节点的系数和协变量值之和的乘积。

建立模型

我们以高和低的判断准确度计算两组参与者的 ERGMs。使用 R 包 statnet [5]进行分析。变量和系数估计值如下表所示。下面结果中的模型系数只能在两个模型中解释。参考同一变量的不同模型的系数不会被调查为彼此(显著)不同。这两个模型是同等指定的,即它们包含相同的变量。

结果

请记住:ERGMs 只能处理二元边,也就是说,一条领带要么存在,要么不存在。由于我们从两个基于组的网络中的加权边开始,我们丢失了一定量的信息。两个模型的结果如下表所示。

设计的影响

模拟教室的设计方式是参与者只能从有限的一组动作中进行选择,项目和学生必须交替选择。如果参与者没有完全随机地选择项目和学生,参与者通过设计产生一个学生和/或项目焦点。结果显示两组都有一个明显的倾向,即把一个项目分配给多个学生( 同一个项目 ),以及集中于一个学生并给这个学生分配不同的项目( 同一个学生 )。然而,这些趋势可能会受到模拟教室设计的影响,即,对项目和学生进行选择性选择的限制,并不纯粹反映有意义的认知选择过程。

男孩还是女孩?

学生性别的相关性的结果指向类似的方向。两组的参与者似乎交替地给男孩和女孩分配项目( 同性 )。这可能是模拟教室中座位位置的反映(交替的性别属性),因此倾向于选择学生按顺序坐在一起

富家子弟穷孩子

将具有相同社会地位属性的学生连接成一排( 相同社会地位 )可能意味着参与者想要对比那些学生。也可能是给坐在一起的学生分配物品的结果。模拟教室里的学生是这样安排的,三个社会地位相同或高或低的学生挨着坐。将项目分配给具有相同社会地位属性的学生的显著趋势可以被解释为伪效应。

座位安排

在模拟教室中,沿着座位位置移动的参与者会自动询问一排中具有相同社会地位的学生。这反映了一种特定的行为模式,而不是主动利用社会地位信息的潜在认知过程。与高判断准确性组的参与者相比,低判断准确性组的参与者表现出明显的倾向于遵循某种评估惯例,该惯例在模拟教室中沿着学生的座位移动,并且表现出比高判断准确性组的参与者更少区分的评估行为。

到目前为止我们学到了什么

两组的参与者都没有表现出更关注男孩和女孩或者社会地位高和低的学生的倾向。此外,没有模拟学生特别受欢迎,即,与任何其他学生相比,被问了更多的问题。在这个模拟课堂环境中,学生的总体特征似乎对两组参与者的判断过程没有相关的影响。这些发现支持这样的解释,即性别和社会地位的相似性效应反映了行为倾向 而不是有目的的选择过程

但是物品呢?

到目前为止,结果主要描述了使用学生特征和一般评估策略的总体趋势。通过包含Item术语,我们可以探究在考虑到上述学生特征和评估策略后,参与者是否使用不同的术语。高判断准确性组和低判断准确性组的结果表明,在选择项目评估学生能力方面有明显的差异。

与具有中等经验难度的项目 2 的基线相比,高判断准确性组的模型显示了对 11 个项目中的 10 个项目的显著和负面影响。其他项目都是低难度和相当高的实证难度。这意味着,在控制学生特征和评估策略后,与高或低经验难度的项目相比,高判断准确性组的参与者对中等经验难度的项目略有偏好。

来自低判断准确率组的参与者没有表现出项目选择的区分效果。在低判断准确性组的模型中,所有项目的系数与 0 没有显著差异。所有项目都有相同的机会被选中。

包装完毕

通过使用 ERGMs,我们能够在一个模型中同时考虑内容变量,如项目学生属性以及行为变量,这些变量来自参与者与模拟教室的交互。这让我们更好地了解数字内容(在这种情况下,模拟教室)的设计实际上对人们与之互动的方式有多大影响。这项研究的结果当然需要验证,因为 ERGMs 本质上不能包含所有相关因素,尤其是加权边。

在后续文章中,我将更多地讨论技术方面以及从数据准备到用 R 代码进行模型评估的整个工作流程。

参考文献

[1] L .古特曼,尺度图分析的基础(1950),载于 S.A .斯托福(编辑),美国大兵。第二次世界大战中的社会心理学研究,普林斯顿:普林斯顿大学出版社

[2] S. Wassermann & K. Faust,《社会网络分析:方法与应用》(2018),剑桥大学出版社

[3] G. Robins,P. Pattison,Y. Kalisher 和 D. Lusher,社会网络的指数随机图(p*)模型介绍(2007 年),社会网络

[4] M .朱,z .舒和 A. A .冯·达维尔,利用网络可视化和分析教育评估过程数据(2016),教育测量杂志

[5] M. S. Handcock,D. R. Hunter,C. T. Butts,S. M. Goodreau & M. Morris,statnet:网络数据的表示、可视化、分析和模拟的软件工具(2008 年),《统计软件杂志》

点击流数据的图模型介绍。2

原文:https://towardsdatascience.com/introduction-to-graph-models-for-clickstream-data-pt-2-1c3314dc1703?source=collection_archive---------31-----------------------

用 R 语言从数据准备到模型评估

Robynne Hu 在 Unsplash 上的照片

介绍

在之前的文章“点击流数据图模型介绍”中,我介绍了一种使用指数随机图模型(ERGM)【1】分析点击流数据的方法。当我们试图从与数字内容的交互中建模数据时,这种方法会很有帮助。由此产生的点击流数据不仅仅是人们思想的反映。数字内容及其布局对人们与之互动的方式有着同样重要的影响。如果我们想要建立更有意义和更愉快的数字体验,理清这两种影响来源是至关重要的。

为了说明核心概念,我使用了班伯格大学一个研究项目的数据,我们想找出老师是如何形成对学生成绩的判断的。我们使用了一个模拟教室环境(见下图),参与者必须选择项目(从非常容易到非常困难),并将它们分配给模拟学生。每次点击都被记录下来并储存在数据库中。

模拟课堂软件截图。图片作者。

此外,六个学生描述被呈现,指示学生的姓名年龄性别兄弟姐妹的数量和他们的父母的职业,以便给出潜在相关和不太相关的信息。下图给出了两个示例说明。

图片作者。

来自与模拟教室交互的点击流数据表示为网络,其中每个节点表示两个选择:一个用于项目,一个用于学生。此外,我们计算了经验学生能力和我们的参与者的能力评估之间的等级顺序相关性,以创建两组:一组具有高判断准确性 ( r > = .70),另一组具有低判断准确性 ( r < .70)。这导致 n(高)= 25 个参与者,n(低)= 12 个参与者。

接下来,我将向您介绍我的分析,并详细说明指定网络参数以及模型估计和模型评估的过程。

数据准备

装载和清洁

首先,我们需要加载所需的包和数据。在这种情况下,每个参与者有一个数据帧,每个步骤记录在一行中。

通过以这种方式加载数据,我最终得到了一个包含所有数据的数据框,但它需要被清理。正如在 bind_rows 参数中设置的,我们保留了一个 id 变量来标识数据中的每个参与者。这个 id 变量包含路径和文件名,文件名是唯一的参与者编号。我们只需要保存文件名中的数字作为标识符。此外,我们只需要每隔一行为项目schueler (学生)提供一个有效条目。

遵循这些步骤会生成一个仅包含相关条目和格式良好的 id 的数据帧。

将按行排列的数据转换成矩阵

创建网络对象要求数据采用边列表邻接矩阵的形式。你可以选择任何一种方式,但我选择将单个点击流数据转换为邻接矩阵。读取矩阵的基本结构总是从行到列。单元格中的每个条目表示从行中的节点到列中的节点有一个转换。该条目可以是 0(不存在)或 1(存在),如果我们有多次转换,甚至可以大于 1。

在模拟教室中,我们有 12 个项目6 个学生,产生 72 个项目学生组合。对于某些网络分析,尤其是可视化,使用单独的开始和结束节点来显式包含这些步骤是非常有益的。

矩阵遵循一个基本结构:第一行和第一列代表附加的开始节点。第 2-13 行代表学生 1,所有 12 个项目都分配给学生 1。在行和列中,14 到 25 是分配给学生 2 的所有项目。这种模式一直持续到第 74 行和第 74 列,代表单独的结尾音符。

创建嵌套数据结构

我在介绍中提到了两个判断准确度组。为了创建两个群组网络对象,我们必须首先创建单独的邻接矩阵。为了使数据易于管理,我们可以将整个数据框架转换成一个嵌套的数据框架,并将 id 作为指示变量。然后,我们只需将该函数应用于每个嵌套的数据帧,以便为每个参与者创建一个邻接矩阵,并将其存储在整个数据帧的另一个变量中。

创建两个评判小组

本项目中未显示整体判断准确性的计算。我选择创建两个索引向量,包含具有高和低判断准确性的参与者的 id。然后我们只需要把每组的所有邻接矩阵加起来。即使我们在上面的邻接矩阵中引入了单独的开始和结束节点,我们也不需要在我们的网络模型的网络对象中有这两个节点。这导致两个 72×72 邻接矩阵,每个判断准确度组一个。

准备属性对象

为了能够添加网络属性,我们需要首先加载这些信息。我为每个节点创建了一个单独的属性数据帧,其中包含了项目性别学生社会地位 (ses)的信息。实际上,我忘了在属性文件中添加学生变量(这里让它保持真实),但是我们可以为它创建一个向量,并将其作为变量添加到属性数据框中。两种方式都同样有效。向每个节点添加属性是忽略单独的开始和结束节点是有益的主要原因。我们很难为这两个节点设置任何属性,这在我们构建模型时会是一个问题。开始和结束节点的所有连接不能连接到任何节点属性,因此将是无属性的随机变化。

创建网络对象

现在我们终于可以创建网络对象并开始构建模型了。但和往常一样,数据准备需要一些时间,也很重要。

模型说明和解释

创建基线

有几个不同的包来构建网络模型。在这种情况下,我与 statnet 合作。我们从建立一个只包含一个项的基线模型开始。这不会让我们走得很远,但可以让我们看到当我们添加其他变量时,我们的模型是如何改进的。同样,我们对两个网络对象都这样做。为了有一个跨不同模型版本的整体模型性能的指标,我们从高判断准确性组的 AIC 4147 和低判断准确性组的 AIC 2729 开始。

高判断精度模型的模型总结。

添加变量

通过包含不同的节点因子项,我们可以测试具有特定因子级别的节点是否比其他节点连接得更频繁。这些节点因子术语的解释类似于逻辑回归中的变量,其中一个水平设定为基线,其他水平与基线水平进行比较。

我们开始看到这两种模式之间的差异。这里需要注意的重要一点是:模型参数不能跨不同的模型进行解释。我们只能解释同一个模型中与其他参数相关的参数!

我们看到学生 5 和 6 的节点因子项的参数无法估计。这表明模型还没有被很好地指定。

带有边和不同节点因子项的模型摘要。

第一个不同点

当我们查看与学生相关的变量(学生性别社会地位)时,在高判断准确性组(模型 1)中节点因子. ses.low 有一个显著的正系数。这意味着属性为低社会地位的节点通常比属性为高社会地位的节点更经常被连接。

对此的一种解释可能是,高判断准确率组的参与者实际上想更仔细地看看那些社会地位信息低的学生(正如一开始学生描述中他们父母的工作所表明的)。这是一个证据充分的事实,即社会地位对感知能力有负面影响,因此特别关注这些学生似乎是合理的。做出非常准确判断的参与者意识到了这种影响,并希望在这里小心不要成为它的受害者。对于低判断准确性组,我们没有发现任何显著的影响。

从项目来看,我们在模型 2(低判断准确率组)中没有发现差异化的项目选择。当选择项目 2 (难度中等)作为基线类别时,所有项目系数与 0 无显著差异。在模型 1(高判断准确度组)中,我们的情况正好相反,与第 2 项相比,几乎所有系数都是显著的。这支持了高判断准确性组的参与者进步更深思熟虑的解释。他们似乎比其他人更关注一些学生,似乎也更有意识地选择他们的项目。

看看 AIC,我们看到一些微小的改进。高分组的 AIC 值为 4144,低分组的 AIC 值为 2748。因此,即使我们包括了额外的变量,这两个模型都没有显著改善。

添加行为变量

在最终的模型中,我添加了一些变量,作为参与者如何在模拟教室中导航的代理。在网络术语中,它们是节点匹配术语。一般来说, nodematch 术语检查节点是否有更高的概率连接到具有相同属性的其他节点。我为学生项目性别社会地位添加了节点匹配术语,在下面的汇总表中描述为评估策略。从技术上来说,这些本身并不是行为变量,但在这种情况下,它们捕捉到的效果很好地代表了行为模式。

包含所有变量的完整模型摘要。

对于两个模型中的节点匹配学生 ( 同一学生)和节点匹配项目 ( 同一项目)项,我们都有非常显著的系数。这主要是由于模拟教室的设计方式。参与者必须交替选择项目和学生。如果你不完全随机地这样做,就无法避免连续两次(或更多次)选择一个项目或一个学生。

在这两个模型中,我们都发现了一个有效的负系数用于节点匹配 gende r 项(同性)。这似乎是模拟教室建筑的人工制品:男生坐在女生旁边,反之亦然。将不同性别的学生联系起来可能反映了有意的评估过程,也可能只是意味着“让学生坐在一起”。最后一种解释得到了低判断准确率组中节点匹配 ses ( 相同社会地位 ) 的正系数的支持。这意味着参与者选择具有相同社会地位的学生。模拟教室里的学生被设置成上排社会地位高,下排社会地位低。因此,这个节点匹配术语似乎再次捕捉到了参与者如何在模拟教室中导航的效果:紧密地沿着座位排列。

有趣的是,node factor ses**low(low social status)项,这个在没有行为变量的模型中显著为负的项不再显著。

查看两个模型的 AIC 值,我们会发现两个模型这次都有所改善。对于高判断准确性组,我们的 AIC 值为 3066,对于低判断准确性组,我们的 AIC 值为 2212。

事情变得非常网络化

如果我们看一下模型规格,到目前为止,我们离逻辑回归并不太远。通过增加一个三角形项来改变这种情况。这个三角形项是网络中局部聚集的指示器。对于高判断准确率组,我们发现一个小的负面影响,这意味着网络有轻微的趋势,形成局部集群。这再次表明在模拟教室中有一个更深思熟虑和更有计划的评估程序。

模型评估

到目前为止,我只谈到了 AIC 作为一个模型性能的指标。评估网络模型的拟合优度是一项非常直观的任务。基本概念是使用估计的系数,用这些系数对新网络进行采样,并测量描述网络的某一组参数。然后,将来自采样网络的这些参数与我们凭经验观察的网络的参数进行比较(我们为此建立了模型)。如果它们匹配,我们就可以确定已经建立了一个模型,能够合理地捕捉数据生成过程。如果有更大的差异,我们将不得不回到理论上,思考如何使模型更加精确。

在 btergm 包[3]中有一个很好的函数来估计和绘制拟合优度。通过观察下图可以看出,经验模型参数和从样本网络中估计的参数之间没有显著差异(在方框图中)。这总是步入正轨的好迹象。

高判断准确度模型的拟合优度图。来源:作者

观点

ERGMs 的一个主要限制是它们只能处理二进制边缘。因为我决定将多个参与者分组,并且只查看他们的汇总数据,所以我丢失了一些信息。如果两个连续动作之间的转换出现一次或五次,肯定会有很大的不同。但是这个问题有一个解决方案:广义指数随机图模型 (GERGMs) [4]。ERGMs 的这种一般化形式能够处理加权边并使用全部信息量。但是它们在计算上要求很高。在一台普通机器上,估计一个具有 20-30 个节点的中等规模网络的 GERGM 很容易需要几天甚至几周的时间。选择不同的似然估计(最大伪似然,而不是马尔可夫链蒙特卡罗最大似然估计)可以显著加快速度,但会引入有偏差估计的风险。

我将在下一篇文章中探讨这个问题。如果你对建立新模式有任何问题或想法,请随时联系 Linkedin 或 twitter (@MMuckshoff)。完整的代码也在 github 上。

参考

[1] G. Robins,P. Pattison,Y. Kalisher 和 D. Lusher,社会网络的指数随机图(p*)模型介绍(2007 年),社会网络

[2] M. S. Handcock,D. R. Hunter,C. T. Butts,S. M. Goodreau & M. Morris,statnet:网络数据的表示、可视化、分析和模拟的软件工具(2008 年),《统计软件杂志》,24(1)

[3] P. Leifeld,S. J. Cranmer & B. A. Desmarais,带 btergm 的时间指数随机图模型:估计和 Bootstrap 置信区间(2017),统计软件杂志 83(6)

[4] J. D. Wilson,M. J. Denny,S. Bhamidi,S. Cranmer & B. Desmarais,随机加权图:灵活的模型规范和模拟(2017),社会网络,49

层次聚类简介(第 1 部分——理论、联系和相似性)

原文:https://towardsdatascience.com/introduction-to-hierarchical-clustering-part-1-theory-linkage-and-affinity-e3b6a4817702?source=collection_archive---------25-----------------------

什么是层次聚类、亲和度和关联度

杰里米·毕晓普在 Unsplash 上的照片

使聚集

聚类是称为无监督学习的机器学习的一部分。这意味着,与监督学习相比,我们没有特定的目标,因为我们的结果变量不是预先定义的。例如,在回归或分类中,我们已经知道我们的模型试图通过预测一个连续的目标变量(y)或已经定义的类来实现什么。相比之下,对于聚类,我们没有定义的目标变量,相反,我们试图自己做出那些最终的组,然后我们可以根据我们预先存在的知识进行解释。

这在我们希望从现有数据中识别有意义的人群、目标、活动、地点等情况下非常有用。这种方法的商业应用包括识别购买相似商品的客户群,识别具有相似属性的地点,或者将我们想要从中识别聚类的某些行为或属性组合在一起。虽然我们人类可能擅长于从小数据集识别组,但是对于具有许多实例(行)和许多属性(列)的数据来说,这变得非常复杂。因此,算法已经被设计成能够帮助我们做到这一点,包括 kmeans、dbscan 或分层聚类。

分层聚类

通过创建不同组的层次结构,层次聚类适合更广泛的聚类算法世界,范围从所有数据点在它们自己的聚类中到所有数据点在同一个聚类中。其工作原理是找到在某个阈值距离内的点,然后一点一点地将它们组合在一起。具体来说,这种算法有两种形式:自顶向下或自底向上。第一种是自上而下的,首先将所有点视为单个聚类的一部分,然后逐渐将它们分解成单独的聚类(分割),直到它们都是自己的聚类的一部分。第二种是自底向上的,从所有点都是它们自己的聚类的一部分的基础开始,然后迭代地将两个最近的点分组在一起,直到它们都是单个聚类的一部分(聚集的)。这种聚类的层次结构可以表示为如下的树(或树形图),树叶表示单个聚类,距离随着聚类的增加而增加。

作者图片

作者图片

我们在这里可以看到,根据您采用的算法形式,聚类逐渐建立或分解,最常见的形式是自底向上/凝聚方法。这里我们可以看到,当我们沿着树状图往上走,在下面的图中可以看到,集群逐渐连接起来,直到我们到达同一个紫色集群的所有点。因此,我们可以清楚地看到一个层次结构的形成,其中集群联合起来,因为集群是由其他集群组成的。

就最终创建的聚类而言,该算法的结果会受到两个主要因素的影响:所选择的相似性度量(如何计算点之间的距离)和所选择的链接方法(计算点之间的距离)。sklearn 包中的不同形式如下:

吸引力

这些也将取决于所使用的距离度量(相似性)的选择:

欧几里得(l2)

这是用于测量聚类之间距离的默认距离度量,简单来说就是两点之间的直线距离。这在数学上表示为:

形象地表现为:

曼哈顿(l1)

这个距离是所有维度上的点之间的绝对差之和。这就好像点与点之间有网格状的路径一样。这在数学上表示为:

形象地表现为:

这也称为出租车几何形状和城市街区距离等。该距离通常适用于稀疏要素。

余弦

这个距离度量测量两个向量之间的角度。当点与点之间的大小无关紧要,但方向很重要时,就使用这种方法,这种方法通常用于自然语言编程中。这被测量为:

cos(𝜃)=𝐴𝐵˙||𝐴||∗||𝐵||cos⁡(θ)=ab˙||a||∗||b||

预先计算的

如果您已经为您的观测值预先计算了距离矩阵,则使用此选项。

选择的度量旨在最大化不同类别中样本之间的距离,并最小化每个类别之间的距离 1

联系

这些组的形成取决于不同链接度量的选择:

单人/分钟

这将两个聚类的相似性度量为彼此最接近的点之间的最小相似性。在数学上,这表示为:

形象地表现为:

这种方法的好处是它可以处理非标准形状的聚类,但如果有噪声,就不能正确地分离聚类。

完整/最大

这与最小值方法相反,因为两个聚类的相似性等于每个聚类内的点之间的最大相似性。这可以写成:

形象地表现为:

如果聚类之间有噪声,这种方法在分离聚类时效果很好,但是它偏向于圆形聚类,并且倾向于分解大的聚类。

平均的

这种关联度量使用两个集合的所有观察值的平均距离。在数学上,这表示为:

形象地表现为:

如果聚类之间有噪声,这在分离聚类方面做得很好,但是偏向于形成斑点的聚类。

病房

除了计算距离 Pi 和 Pj 的平方和之外,这种计算两个聚类之间相似性的方法与组平均相同。本质上,这最小化了被合并的聚类的方差。从数学上讲,这可以写成:

形象地表现为:

这种方法的好处是,如果有噪声,它在分离聚类方面做得很好,但是它偏向于圆形聚类组。

与其他聚类方法相比,层次聚类的优点在于它不需要指定聚类的数量。此外,该算法对距离度量并不敏感,这意味着结果不应该受到选择相似性度量的影响。当底层数据具有分层结构或者这就是我们对数据的预期时,这种算法特别有用,从中我们可以看到聚类最终如何组合在一起形成越来越少的聚类(或者相反)。

然而,由于 O(n)的时间复杂度和 O(n)的空间复杂度,这是以较低的效率为代价的。此外,与 kmeans 或 DBscan 不同,分层聚类没有自然的性能指标来判断哪些聚类最适合数据。更复杂的是,一旦集群形成,它将不会分裂(只要您采用凝聚模型),并且只会随着您增加距离度量或减少集群数量而继续形成更大的组。这意味着,如果您有难以解释的集群,它们不太可能改变,除非您改变相似性或关联度量。

因此,总的来说,尽管由于复杂性和优化原因,该算法的使用率低于 dbscan 或 kmeans 算法,但当数据预计具有或已经具有层次结构,并且您拥有能够运行模型的计算资源时,该算法非常有用。

第 2 部分展示了 python 在这方面的应用,可以在这里找到:

尽管受地理位置限制的实现可以在这里找到:

如果你想在 Medium 上阅读更多我和其他人的精彩文章,请随意使用我的推荐链接注册:

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

来源:

[1]https://sci kit-learn . org/stable/modules/clustering . html # hierarchical-clustering

[2]https://towards data science . com/importance-of-distance-metrics-in-machine-learning-modeling-e 51395 FFE 60d

[3]https://www . analyticsvidhya . com/blog/2020/02/4-机器学习中的距离度量类型/

[4]https://towards data science . com/understanding-the-concept-of-hierarchical-clustering-technique-c6e 8243758 EC

[5]https://www . saedsayad . com/clustering _ hierarchical . htm #:~:text = In % 20 average % 20 linkage % 20 hierarchical % 20 cluster,point % 20 In % 20 the % 20 other % 20 cluster

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

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

分层聚类介绍(第 2 部分——python 实现)

原文:https://towardsdatascience.com/introduction-to-hierarchical-clustering-part-2-python-implementation-73d367f9c298?source=collection_archive---------17-----------------------

伦敦犯罪数据的 Python 实现

本杰明·戴维斯在 Unsplash 上拍摄的照片

的上一篇文章中,介绍了层次化集群的目的以及对其工作原理的广泛描述,本文的目的是在此基础上,通过 sklearn 包展示其实现的结果。作为其中的一部分,我认为将这个问题与了解不同类型的犯罪如何在伦敦聚集在一起的问题结合起来会很好。

通过等级聚类识别的这些犯罪聚类,不是犯罪的数量,而是伦敦的犯罪类型。例如,在伦敦是否有一些地区,不管犯罪数量多少,都有很高比例的特定数量的犯罪,如盗窃或入室盗窃。如果这些区域被确定,那么理论上特定的干预措施可以针对特定类型的犯罪,而不是将这些资源分散到整个伦敦。这方面的一个例子可能是,预计伦敦市中心的盗窃率相对较高,那里有许多游客和个人,因为针对盗窃的具体干预措施,如增加警力和多种语言的警告标志,可以在这里实施,但效果不如伦敦外围地区。作为这一过程的一部分,由于我们在地理上代表这些集群,从同类犯罪的高比例来看,属于同一犯罪集群的地区在地理上应该是接近的。在盗窃案件中,我们假设伦敦市中心的区域都是盗窃高发区。这只是遵循了地理第一定律“万物皆相关,但近物比远物更相关”[1]。

第一步是获取数据。由于这里使用的例子是伦敦,大伦敦的犯罪数据可以很容易地通过伦敦数据库访问(伦敦市除外)[2]。这些数据经过清理,以便提取 2019 年伦敦每个较低超级产出地区(LSOA)的每种主要犯罪类型(相对于该地区犯罪总数)的百分比。这些结果可以可视化:

#extract the columns that we don't want to plot
not_plot = ["LSOA11CD", "geometry", "LSOA Code", "Total_crime"]
#use this to extract the columns that we do want to plot
to_plot = [col for col in London_crime.columns if col not in not_plot]#print(to_plot)#create a subplot axis, given that we have 10 different categories this has to be a 3 by 4 matrix of plots
fig, axis = plt.subplots(3,4, figsize = (30,30))
#flatten the axis so that we can iterate over them
axis = axis.flatten()#creating the plot function
#use the enumerate to get the value and its index
for i, col in enumerate(to_plot):
    #set the axis as in the rows
    ax = axis[i]
    #to make it cleaner move two axis across
    if i >=8:
        ax = axis[i+1]
    #plot the crime map using the magma color map
    crim_plt = London_crime.plot(column = col, ax=ax, cmap = "magma", vmin =0, vmax = 1)
    #remove the axis so that it looks cleaner
    ax.set_axis_off()
    #set the plot title as the column name
    ax.set_title(col, fontsize = 25)#plt.subplots_adjust(right = 0.8)
#cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7])
#cbar = plt.colorbar(cax=cbar_ax)#adding a color bar for the overall plto
#[https://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots/11558629#11558629](https://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots/11558629#11558629)
vmin, vmax = 0,100#create a subaxis within the figure
fig = ax.get_figure()
plt.subplots_adjust(right = 0.8)
cax = fig.add_axes([0.85, 0.15, 0.05, 0.7], label = "Percentage of crime")
#create a colorbar and plot it
sm = plt.cm.ScalarMappable(cmap='magma', norm=plt.Normalize(vmin=vmin, vmax=vmax))
sm._A = []
cb = fig.colorbar(sm, cax=cax)
#change the size of the tick parameters
cb.ax.tick_params(labelsize = 30)
#set the label title
#[https://stackoverflow.com/questions/17475619/how-do-i-adjust-offset-colorbar-title-in-matplotlib](https://stackoverflow.com/questions/17475619/how-do-i-adjust-offset-colorbar-title-in-matplotlib)
cb.set_label("Percentage of crimes committed in 2019 (%)", rotation = 270, fontsize= 40, labelpad = 50)
#
#cax.tight_layout()#remove axis of plots not covered
axis[8].set_axis_off()
axis[11].set_axis_off()
#show the results
plt.show()

作者图片

从这个图中我们可以看到伦敦有 10 种主要的犯罪类型被报道。由此可以看出,入室行窃、盗窃、车辆犯罪和针对人身的暴力似乎在价值上有最大的差异,并在犯罪中占最大的总百分比。这对于我们的聚类算法来说意味着,由于聚类会受到因素之间不同方差的强烈影响,因此该算法可能会关注这四个因素。这有可能通过标准化这些值来控制,例如根据最小-最大值将每个犯罪的每个百分比置于 0 到 1 的范围内,或者计算 z 分数,这在理论上可以将所有值置于相同的范围内。然而,由于我们关心的是识别由一种犯罪类型支配的聚类,进一步的标准化/规范化可能会删除我们感兴趣的任何有价值的信息。因此,这种不同的范围和变化目前是可以接受的,但是可以改变以观察这如何影响算法的性能。

因此,现在我们已经在空间上看到了结果,我们可以尝试对结果进行聚类,以查看聚类是如何发展的。第一个实现的代码如下:

#import the necessary module
from sklearn.cluster import AgglomerativeClustering#extract the values that we want to plot
crime_clus = London_crime[to_plot]#create the model that we want, setting the linkage to ward, the distance threshold to 4 and 
#set the number of clusters to none so that we can plot the dendrogram afterwards
model = AgglomerativeClustering(linkage="ward", distance_threshold = 4, n_clusters=None)#fit the model to the data
model.fit(crime_clus)

这段代码导入了凝聚聚类算法,提取了我们希望算法处理的值,创建了我们想要的模型,并使模型适合数据。这里我们使用了 wards 链接,距离阈值等于 4,使用默认的欧几里德距离度量,并将聚类数设置为无。我们使用distance_threshold而不是n_clusters的原因是因为我们希望能够在以后绘制树状图。然而现在,我们想看看算法实际上是如何执行的。我们可以通过绘制实际的集群来做到这一点:

#extract the model labels
London_crime["Aggl_clus"] = model.labels_#get the means of each cluster
agglom_means =London_crime.groupby("Aggl_clus")[to_plot].mean()#transpose the dataframe so that we get the column titles as individual clusters
agglom_means_T = agglom_means.T.round(3)#reset the index
agglom_means_T.reset_index(inplace=True)#create the subplot
fig, ax = plt.subplots(1,4, figsize = (15,8), sharey = True, sharex = True)#get the colours
colors = ["blue", "red", "pink", "tab:cyan"]#create subplots for each cluster
fig, ax = plt.subplots(1,4, figsize = (15,8), sharey = True, sharex = True)
#flatten the axis
axis = ax.flatten()#going over each column
for i, col  in enumerate(agglom_means_T.columns):
    #ignore the index column
    if col != "index":
        ax = axis[i-1]
        #plot the bar chart
        ax.bar(height = agglom_means_T[col], x=agglom_means_T["index"], color = colors[i-1] )
        #rotate the x-ticks
        ax.set_xticklabels(labels =agglom_means_T["index"], rotation = 90)
        #set the title
        ax.set_title(f"Cluster {col}", fontsize = 20)

#plot the results on London
fig, ax = plt.subplots(figsize = (10,10))London_crime.plot(column = "Aggl_clus", categorical = True, legend=True, ax=ax)ax.set_axis_off()

agglom_sizes = London_crime.groupby("Aggl_clus").size()
agglom_sizes#Out:
0    2083
1     441
2    1644
3     661

根据这些图和结果,假设聚类的目的是能够创建我们可以解释的组,我们可以为每个聚类分配标签如下:

群组 0:对人的暴力行为(没有明确的地理区域)

第一组:伦敦市中心的盗窃

第二组:伦敦郊区的车辆犯罪和入室盗窃

群组 3:盗窃和暴力侵害人身(没有明确的地理区域)

这种标记暗示了簇 0 和 3 以及 1 和 3 之间潜在地存在某种程度的重叠。这表明我们不一定有独特的集群。此外,考虑到我们的研究问题,我们对聚类的地理表示感兴趣,其中聚类 0 和 3 没有显示出必要的清晰地理表示,这意味着我们的目标没有完全达到。此外,从每个组中 LSOAs 的数量来看每个集群的大小,我们可以看到集群 1 和 3 比 0 或 2 小得多,这支持了这一观点,即这不是最佳的集群结果,因为这些组并不均匀(不均匀的集群并不总是表明有问题,但如果它们非常不同,则值得研究)。

假设这是层次聚类,那么我们可以看看模型是如何表现的,我们可以使用从文档中获得的以下代码:

import numpy as np
from scipy.cluster.hierarchy import dendrogramdef plot_dendrogram(model, **kwargs):

    counts = np.zeros(model.children_.shape[0])
    n_samples = len(model.labels_)
    for i, merge in enumerate(model.children_):
        current_count = 0
        for child_idx in merge:
            if child_idx < n_samples:
                current_count +=1
            else:
                current_count += counts[child_idx-n_samples]
        counts[i] = current_count

    linkage_matrix = np.column_stack([model.children_, model.distances_,
                                     counts]).astype(float)

    dendrogram(linkage_matrix, **kwargs)fig, ax = plt.subplots(figsize = (10,10))
ax.set_title("Hierarchical clustering dendrogram")
#plot the top three levels of the dendrogram
plot_dendrogram(model, truncate_mode='level', p=3)
plt.axhline(y = 4, color = "r", linestyle = "--")
ax.set_xlabel("Number of points in node")
plt.show()

这表明在当前距离阈值为 4 的情况下,我们得到了我们看到的四个集群。然而,假设我们可以看到,在稍高的距离阈值处,两个最小的聚类合并,并且直到下一次合并的距离阈值很长(表明这些聚类相对稳定),这将表明聚类 1 和 3 可能更好地合并以获得更好的输出。因此,我们可以将距离度量更改为距离阈值 6,并再次探索结果。

然而,我们也可以反过来看,将聚类距离减少到 3.45,以将两个最大的聚类分成更小的聚类。这将有效地减小最大和最小集群之间的大小差异,并且潜在地产生关于如何创建集群 0 和 2 的更多信息。我们可以在树状图上看到这两个不同的距离度量,方法是在图上再添加两个plt.axhline(y= d, color = "r", linestyle = "--"),得到:

因此,我们可以遵循与之前相同的工作流程,以便可视化和理解距离阈值设置为 6 且距离阈值设置为 3.45 的聚类输出:

#distance threshold of 6
model6 = AgglomerativeClustering(linkage="ward", distance_threshold = 6, n_clusters=None)
#fit the model to the data
model6.fit(crime_clus)#assign labels
London_crime["Aggl_clus_6"] = model6.labels_#distance threshold of 3.45
model3_45 = AgglomerativeClustering(linkage="ward", distance_threshold = 3.45, n_clusters=None)
#fit the model to the data
model3_45.fit(crime_clus)
London_crime["Aggl_clus_3_45"] = model3_45.labels_#plot the London resultsfig, ax = plt.subplots(1, 2, figsize = (15,30))London_crime.plot(column = "Aggl_clus_6", categorical = True, legend=True, ax=ax[0])
ax[0].set_axis_off()
ax[0].set_title("Distance threshold 6 cluster")London_crime.plot(column = "Aggl_clus_3_45", categorical = True, legend=True, ax=ax[1])
ax[1].set_axis_off()
ax[1].set_title("Distance threshold 3.45 cluster")

agglom_means =London_crime.groupby("Aggl_clus_6")[to_plot].mean()
agglom_means_T = agglom_means.T.round(3)agglom_means_T = pd.DataFrame(agglom_means_T)agglom_means_T.reset_index(inplace=True)colors = ["blue", "brown", "tab:cyan"]fig, ax = plt.subplots(1,3, figsize = (15,8), sharey = True, sharex = True)
axis = ax.flatten()
for i, col  in enumerate(agglom_means_T.columns):
    if col != "index":
        ax = axis[i-1]
        ax.bar(height = agglom_means_T[col], x=agglom_means_T["index"],  color = colors[i-1])
        ax.set_xticklabels(labels =agglom_means_T["index"], rotation = 90)
        ax.set_title(f"Cluster {col}", fontsize = 20)

plt.suptitle("Clusters with distance threshold 6", fontsize = 20)

agglom_means =London_crime.groupby("Aggl_clus_3_45")[to_plot].mean()
agglom_means_T = agglom_means.T.round(3)agglom_means_T = pd.DataFrame(agglom_means_T)agglom_means_T.reset_index(inplace=True)colors = ["blue", "green", "purple", "pink", "tab:olive", "tab:cyan"]fig, ax = plt.subplots(2,3, figsize = (30,20), sharey = True, sharex = True)
axis = ax.flatten()
for i, col  in enumerate(agglom_means_T.columns):
    if col != "index":
        ax = axis[i-1]
        ax.bar(height = agglom_means_T[col], x=agglom_means_T["index"],
               color = colors[i-1])
        ax.set_xticklabels(labels =agglom_means_T["index"], rotation = 90)
        ax.set_title(f"Cluster {col}", fontsize = 20)

plt.suptitle("Clusters with distance threshold 3", fontsize = 20)

当然,理解聚类算法如何执行的关键是能够解释输出。首先,我们可以探索距离阈值为 6 的结果。对于这个集群,标签可以解释为:

第 0 类—盗窃主要发生在伦敦市中心
第 1 类—伦敦市中心周围针对人身的暴力行为。
第二组——伦敦郊区的车辆犯罪和入室盗窃

我们可以从原始组中看到,这将组 1 和组 3 组合在一起,因此我们现在在地理上和解释上都获得了更明显的组。这也大致符合我们的预期,因为我们预计游客数量多的伦敦市中心的盗窃率高,而在伦敦外围,我们预计车辆犯罪和盗窃的比例更高,因为在郊区,因此与伦敦市中心相比,有更多的房子和更多的汽车使用。

接下来,查看带有distance_threshold =3.45的结果,我们可以看到标签可能被解释为:

聚类 0 —伦敦外围盗窃案高发
聚类 1 —伦敦市中心盗窃案高发
聚类 2 —针对人身的暴力和盗窃案高发,无明确的地理区域
聚类 3 —相对较高的盗窃案、针对人身的暴力和盗窃案,无明确的地理区域
聚类 4 —针对人身的暴力案高发,无明确的地理区域
聚类 5 —针对人身的暴力案和纵火案高发,无明确的地理区域

虽然其中一些集群在犯罪类型和地理区域方面相对容易解释,但其他集群则不太清楚。我们还可以看到,虽然有一个大的集群(集群 5 有 1566 个 LSOAs),但其余的集群大小相对相似,这表明比距离阈值为 4 时更适合。

从这些结果中,我们可以清楚地看到层次结构是如何工作的,当我们的距离为 3.45 时,聚类 3 和 0 合并形成聚类 2,当我们的距离阈值为 4 时,然后是 6。然后再次从距离 3.45 开始,当距离阈值被设置为 4 时,聚类 4 和 5 合并以形成聚类 1,当距离阈值为 6 时,聚类 1,而距离为 3.45 的剩余两个聚类在距离阈值为 6 时合并以形成聚类 0。

当然,由于这是无监督的学习,因此没有明确的目标可以最大化或像有监督的学习那样瞄准,什么结果是最好的通常是主观的。分层聚类也不同于 dbscan 或 kmeans 聚类,后者没有根据聚类数量来确定最佳匹配的方法。

因此,由于这种拟合的目标是能够识别伦敦周围特定 rimes 组的地理聚类,查看方法和视觉图,那么距离阈值 6,3 个清晰的清晰聚类,在给定我们当前拥有的数据的情况下,看起来是最好的,并且最符合我们对伦敦的了解。这可以通过添加更多的地理信息来得到加强,以便能够解释这些群体,或者了解与其他因素(如收入、交通联系和年龄)的联系,这些因素也可以与每个 LSOA 联系起来。然后,该链接可以潜在地证明具有 6 个聚类的距离阈值 3.45 将是更好的拟合。

然而,考虑到这样做的目的是在空间上识别聚类,我们还没有从地理溢出的角度考虑数据的空间维度,因此我们将在第 3 部分的后续文章中对此进行研究。

本三部曲的第一部分涵盖了理论联系和亲和力,可在以下网址找到:

使用地理约束集群的最后一部分可以在这里找到:

该代码可在以下网址找到:

https://github.com/PhilipDW183/London_crime_clusters

如果你想在 Medium 上阅读更多我和其他人写的好文章,请随意使用我的参考链接注册 Medium 会员:

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

来源:

[1]托布勒·w .(1970)“模拟底特律地区城市增长的计算机电影”经济地理,46(增补):234–240。

[2]https://data.london.gov.uk/

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

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

层次聚类简介(第 3 部分—空间聚类)

原文:https://towardsdatascience.com/introduction-to-hierarchical-clustering-part-3-spatial-clustering-1f8cbd451173?source=collection_archive---------21-----------------------

在层次聚类中引入空间维度

卡菲刘Unsplash 上的照片

的上一篇文章中,我们试图对伦敦的犯罪进行聚类,在执行聚类时,我们忽略了数据的空间维度。因此,本文试图通过明确说明这一点来解决这个问题。

由于聚类的目的是确定不同的聚类在空间上是如何表现出来的,并且最初的理论是位于另一个 LSOA 附近的一个很可能与主要的犯罪类型相关,因此我们需要考虑这种潜在的空间关系。这是通过对集群施加空间约束来实现的。

在这样做的过程中,这就创建了用特定聚类来标识的区域。这种行为在真实世界的数据集中很容易看到,例如在欧洲,我们有 NUTS1、NUTS2 和 NUTS3 经济边界,它们对应于不同的经济区域,这些经济区域的规模从主要经济区域向更小的区域减小。与算法相关的不同之处在于,这些区域不是用于经济分析的功能单元,而是统计定义的,考虑到了它们的自然地理分布。

集成到算法中的这种地理分布可以来自识别或说明这些地理关系的各种不同方法。有关这些不同类型关系的更多信息,以及可用于定义地理接近度的方法,请参见 Rey 等人,【2021】

出于我们的目的,我们希望看到彼此相邻的 LSOAs 之间的溢出,因此我们可以使用邻接空间矩阵。这意味着我们检查共享公共边界或顶点的空间单元。这种邻近性的两种类型可以被定义为鲁克的邻近性(冯诺依曼的邻近性)和女王的邻近性(摩尔的邻近性)。这些类别中的前一个类别是地理相邻者,即共享直接边界的那些类别,后一个类别将相邻者表示为共享直接边界和顶点的那些类别。这可以表示为:

左:车,右:皇后

对于这一点,由于我们关心的是犯罪可能蔓延的邻居,我们把前一个例子作为车的相似性,作为那些根据共享相似边界而连接的车的相似性。我们可以在现有的数据框架上实现这一点,如下所示:

#import the necessary packages
from libpysal import weights#calculate the weights matrix
#selecting Rook's similarity
wq = weights.contiguity.Rook.from_dataframe(London_crime)

然后我们可以想象这在地图上是什么样子:

#looking at London
fig, ax = plt.subplots(1,2, figsize = (15,15))London_crime.plot(edgecolor = "blue", facecolor = "w", ax=ax[0])wq.plot(London_crime, ax=ax[0],
       edge_kws=dict(color="r", linestyle = "--", linewidth =1),
       node_kws=dict(marker=''))ax[0].set_axis_off()#Second plot looking into deepr depth
London_crime.plot(edgecolor = "blue", facecolor = "w", ax=ax[1])wq.plot(London_crime, ax=ax[1],
       edge_kws=dict(color="r", linestyle = "--", linewidth =1),
       node_kws=dict(marker=''))
#zzoming ino Canary Wharf
ax[1].axis([536_000, 540_000, 178_000, 181_000])ax[1].set_axis_off()

右:整个伦敦,左:金丝雀码头

在整个地图上看起来有点乱,但我们可以通过放大金丝雀码头来更清楚地看到这种关系,在金丝雀码头,当 LSOAs 共享边界时,它们相互连接。

考虑到这一点,问题就变成了我们用来聚类的变量(犯罪百分比)在多大程度上是空间自相关的。这意味着要衡量地理位置相近的地区之间的相关犯罪率。我们可以使用衡量空间自相关整体程度的莫兰 I 值对此进行整体测试。这个值越大,如果这些值靠得很近,它们溢出或彼此紧密相关的可能性就越大。这可以通过以下方式实现:

#code from: [https://geographicdata.science/book/notebooks/10_clustering_and_regionalization.html](https://geographicdata.science/book/notebooks/10_clustering_and_regionalization.html)#import Moran
from esda.moran import Moran#extract the resutls for each column
mi_results = [Moran(London_crime[col], wr) for col in to_plot]#create a table based on this
#extract the variable, and results from the zipped list
table = pd.DataFrame([(to_plot, res.I, res.p_sim) \
                          for to_plot,res \
                          in zip(to_plot, mi_results)
                         ], 
                     #set the columns
                     columns=['Variable', "Moran's I", 'P-value'])\
              .set_index('Variable')
#set the index to the variable#sort the tables values 
table.sort_values(by= ["Moran's I"], ascending=False)

从这些结果中我们可以看出,所有类型的犯罪都有很大程度的空间自相关性(P 值< 0.01), but that this is especially strong for Theft, Vehicle Offences, Violence against the Person and Burglary. It is interesting to note that these are the main variables which were used to define clusters in the previous article in terms of their means and how they are spatially represented. This is because this suggests that these crimes are spatially related to each other and thus there is a degree of spillover.

What is good about agglomerative clustering is that we can add a connectivity constraint in the algorithm so that only adjacent clusters can be merged together. Given that we have a spatial matrix defined by Rooks contiguity, we can then input this into the algorithm to account for the spatial relationship. This is done through the 【 parameter as follows:

#create the model with wards linkage
model = AgglomerativeClustering(linkage="ward", 
                                #define the connectivity
                                connectivity = wr.sparse,
                                #set the distance threshold
                                distance_threshold = 2.5, 
                                n_clusters=None)#fit the model
model.fit(crime_clus)

It is important to note that how this algorithm performs when using the connectivity measures depends on the linkage parameter chosen, as noted in the sklearn documentation, ward’s linkage avoids the ‘rich getting richer’ problem associated with other linkage options 【1】),因此我们希望看到相对均匀的聚类。

正如我们之前所做的那样,我们可以绘制结果图来查看聚类的结果:

#extract labels
London_crime["Aggl_clus_spa"] = model.labels_#creating axis
fig, ax =plt.subplots(figsize = (10,10))#plt the results
London_crime.plot(column = "Aggl_clus_spa", categorical = True, legend=True, ax = ax)
ax.set_axis_off()

以及这些集群在犯罪方面的表现:

agglom_means =London_crime.groupby("Aggl_clus_spa")[to_plot].mean()agglom_means_T = pd.DataFrame(agglom_means.T.round(3))agglom_means_T.reset_index(inplace=True)colors = ["tab:blue", "tab:green", "tab:brown", "tab:grey", "tab:cyan"]fig, ax = plt.subplots(2,3, figsize = (15,20), sharey = True, sharex = True)
axis = ax.flatten()
for i, col  in enumerate(agglom_means_T.columns):
    if col != "index":
        ax = axis[i-1]
        ax.bar(height = agglom_means_T[col], x=agglom_means_T["index"],
               color = colors[i-1])
        ax.set_xticklabels(labels =agglom_means_T["index"], rotation = 90)
        ax.set_title(f"Cluster {col}", fontsize = 20)axis[5].set_axis_off()

plt.suptitle("Clusters with distance threshold 3", fontsize = 20)

然后,我们可以将这些集群解释为:

群组 0:针对人身的严重暴力,伦敦市区

第 1 组:伦敦西南中部的高盗窃和公共秩序犯罪

第二组:伦敦北部外围的高车辆犯罪和入室盗窃

第三组:伦敦市中心的高盗窃率

集群 4:伦敦中北部暴力和盗窃高发

我们还可以创建树状图来查看算法是如何到达这一点的,但这与之前不同,因为我们现在考虑了地理邻近性:

import numpy as np
from scipy.cluster.hierarchy import dendrogramdef plot_dendrogram(model, **kwargs):

    counts = np.zeros(model.children_.shape[0])
    n_samples = len(model.labels_)
    for i, merge in enumerate(model.children_):
        current_count = 0
        for child_idx in merge:
            if child_idx < n_samples:
                current_count +=1
            else:
                current_count += counts[child_idx-n_samples]
        counts[i] = current_count

    linkage_matrix = np.column_stack([model.children_, model.distances_,
                                     counts]).astype(float)

    dendrogram(linkage_matrix, **kwargs)fig, ax = plt.subplots(figsize = (10,10))
ax.set_title("Hierarchical clustering dendrogram")
#plot the top three levels of the dendrogram
plot_dendrogram(model, truncate_mode='level', p=3)
ax.set_xlabel("Number of points in node")
plt.show()

我们可以从中看出,尽管使用了 wards 连锁,但我们仍然有一个 0 的优势聚类问题,它包含 3811 个 LSOAs,这表明我们的连锁和地理邻近性措施可能没有创建最合适的聚类。这一点,以及所产生的集群难以解释的事实。

因此,在 was 中考虑地理上的接近可能没有产生我们想要的结果,因为集群很难根据它们的犯罪和地理位置来解释。因此,可以使用空间接近度的替代方法,或者可以将犯罪百分比标准化,这样我们就不会查看百分比,而是查看平均值的方差。我们还可以尝试不同的链接或距离度量,以查看算法如何执行以及输出如何变化。因此,这突出了与聚类相关的困难,因为为了获得正确的结果,可以考虑许多不同的方法和因素,并且最终,结果是否正确是主观的。

本文的代码可以在以下位置找到:

https://github.com/PhilipDW183/hierarchical_clustering

尽管可以在此处找到对分层集群的首次介绍:

第一个不受地理位置限制的 python 实现可以在这里找到:

如果你想在 Medium 上阅读更多我和其他人的精彩文章,请随意使用我的推荐链接注册:

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

分层时间序列预测简介—第一部分

原文:https://towardsdatascience.com/introduction-to-hierarchical-time-series-forecasting-part-i-88a116f2e2?source=collection_archive---------3-----------------------

Edvard Alexander lvaag 在 Unsplash 上拍摄的照片

问题定义和不同方法概述

大多数关于时间序列预测的文章都集中在特定的聚合级别上。然而,当我们可以深入我们的聚合数据以在更细粒度的级别上观察相同的系列时,挑战就出现了。在这种情况下,我们经常会发现低层的预报与总的预报不一致——它们是不连贯的。为了确保不出现这种情况,我们可以采用一种叫做分层时间序列(HTS)预测的方法。

理论介绍

我们应该从数据开始介绍。当谈到合计和分解时间序列时,我们可以区分两种情况。通过分析一个例子来理解它们是最容易的,所以让我们假设我们是一个在线零售商,在许多市场上销售不同种类的产品(比如亚马逊)。

第一个场景涉及清晰的数据层次结构,其中较低的级别唯一地嵌套在较高级别的组中。最简单的例子就是地理分裂。作为零售商,我们可以查看所有市场的总销售水平,然后按国家细分汇总的系列。如有必要,我们可以更深入地了解每个地区的销售额(如美国各州等。).当我们的数据遵循这样的结构时,我们处理的是层次时间序列

分层时间序列的一个例子。图片由作者提供。

第二种情况涉及时间序列,其中各层次是交叉的,而不是嵌套的。作为零售商,我们可以有多个层次的细节:产品类别、价格范围、我们自己的产品与第三方卖家销售的产品的对比,等等。有了这样的分割,就没有单一的“正确”聚合方式。在这种情况下,我们用分组的时间序列工作。

分组时间序列示例。图片作者。

自然地,当我们分析地理位置和产品类别时,分层和分组的时间序列可以混合成更复杂的结构。

分层时间序列预测(为了清楚起见,该名称还包括分组和混合情况)的整个挑战是生成在整个聚合结构中一致的预测。所谓一致,我指的是以与基础聚合结构一致的方式相加的预测。例如,所有区域的预测应添加到国家一级,所有国家一级应添加到更高一级,等等。或者,不一致的预测可以被调和以使它们一致。

还有一点需要澄清的是,分层时间序列预测不是时间序列预测的方法论(如 ARIMA、ETS 或 Prophet) 本身。相反,它是一个不同技术的集合,使预测在给定的单个时间序列层次上保持一致。

下面,我们来看看层次时间序列预测的主要方法。

自下而上的方法

在自下而上的方法中,我们预测层次结构中最细粒度的级别,然后汇总这些预测以创建更高级别的估计值。回到最初的在线零售商的例子,我们将预测每个地区的销售额,然后将它们相加,以创建各个国家的预测。我们可以再次求和,得出洲/地区级别,然后最终得出总计。

优势:

  • 汇总不会导致信息丢失,因为预测是在最低级别获得的。

缺点:

  • 系列之间的关系(例如,不同区域之间的关系)没有被考虑,
  • 倾向于在高度聚合的数据上表现不佳,
  • 计算量大(取决于任务和较低级别中系列的数量),
  • 在最精细的级别上,数据中的噪声越多,预测的整体准确性就越差。

自上而下的方法

自上而下的方法包括预测层次结构的顶层,然后将预测分成更细化的系列。最常见的是,历史比例用于确定分割。举个例子,我们会预测总计水平。然后,查看过去的数据,我们可以推断美国占销售额的 50%,欧洲占 40%,等等。然后,我们可以迭代并将系列分解成更细粒度的级别。

优势:

  • 最简单的方法,
  • 对更高层次的可靠预测,
  • 只需要一个预测。

缺点:

  • 由于信息丢失(通过历史比例),较低层次的预测不太准确。

中间向外方法

中间剔除法是上述两种方法的结合,只能用于严格分级的时间序列。在这种方法中,我们选择中间级别并直接预测它。然后,对于所选级别之上的所有级别,我们使用自下而上的方法—我们将层级向上求和。对于中间一层以下的层,我们使用自顶向下的方法。

由于它是两种不同方法之间的折衷,因此得到的预测不会丢失太多信息,并且计算时间不会像自底向上方法那样激增。

最佳协调方法

上面描述的三种方法集中于在一个层次上预测时间序列,然后使用它们来推断其余的层次。与它们相反,在最佳协调方法中,我们使用给定层次结构可以提供的所有信息和关系来预测每个级别。

在这种方法中,我们假设基本预测(对于所有级别的每个系列)近似满足层次结构。这意味着预测应该相对准确,而不是扭曲平衡。然后,我们使用线性回归模型来协调个人预测。实际上,一致性预测是所有级别的所有基本预测的加权和。为了找到权重,我们需要求解一个方程组,以确保不同级别之间的层次关系得以保留。

优势:

  • 更准确的预测,
  • 以最小的信息损失对所有级别进行公正的预测
  • 考虑时间序列之间的关系,
  • 由于每个预测都是独立创建的,该方法允许使用不同的预测方法(ARIMA、ETS、Prophet 等)。)每一级。此外,不同的级别可以使用不同的特性集,因为某些变量在给定的粒度级别上可能不可用。

缺点:

  • 最复杂的方法,
  • 可能是计算密集型的—不能很好地适应大量的系列。

还有其他可用的协调方法,例如 MinT(最小跟踪)最佳协调方法,您可以在此处阅读

结论

在本文中,我简要介绍了分层时间序列预测,并描述了用于应对这一挑战的最流行的方法。一个明显的问题是使用哪种方法。你可能已经猜到了,答案是:视情况而定。

前三种方法倾向于偏向于他们预测的水平,这在直觉上是有意义的。因此,当获得特定水平的准确预测是最重要的,并且我们希望获得其余的作为副产品时,我们可能希望从一个更简单的方法开始,看看我们是否满意。

否则,我们可能会研究在层次结构的所有级别上都相当准确的最佳协调方法。理想情况下,我们可以尝试所有不同的方法,同时采用某种时间序列交叉验证方案来评估每种方法的性能,并选择最适合我们问题的方法。

关于如何用 Python 实现分层时间序列预测的例子,请看文章的第二部分

一如既往,我们欢迎任何建设性的反馈。你可以在推特或评论中联系我。

如果您喜欢这篇文章,您可能还会对以下内容感兴趣:

参考

  • Hyndman,R.J .,& Athanasopoulos,G. (2021) 预测:原理与实践,第三版,OTexts:澳洲墨尔本。OTexts.com/fpp3.
  • Rob J. Hyndman,Roman A. Ahmed,George Athanasopoulos,Han L Shang (2011) 计算统计与数据分析 55 (9),2579–2589

分层时间序列预测简介—第二部分

原文:https://towardsdatascience.com/introduction-to-hierarchical-time-series-forecasting-part-ii-e73dfd3de86b?source=collection_archive---------0-----------------------

布鲁克·坎贝尔在 Unsplash 上拍摄的照片

Python 中使用 scikit-hts 的示例

在本文的第一部分中,我介绍了分层时间序列预测,描述了不同类型的分层结构,并回顾了预测这种时间序列的最流行的方法。在第二部分中,我将展示一个例子,说明如何使用scikit-hts库在 Python 中完成这样的任务。

设置

一如既往,我们从设置开始。首先,我们需要使用pip安装scikit-hts。然后,我们导入以下库。

注意scikit-hts被简单地作为hts导入。

数据

在本文中,我们使用澳大利亚旅游数据集,它也用于预测:原则和实践(你可以在这里阅读我对本书的看法)。数据集在名为tsibble的 R 包中自带,但你也可以从 Kaggle 或 my GitHub 下载。

该数据集包含 1998 年至 2016 年期间前往澳大利亚的季度次数。此外,它还附有地理细分(每个州和地区)和旅行目的(商务、度假、旅游、其他)。因此,我们可以创建一个层次或分组的时间序列预测。对于本文,我们将关注严格的层次结构(尽管scikit-hts也可以处理分组变体)。

原始数据集包含 8 个状态,而我们将要处理的数据集只包含 7 个状态。不同的是塔斯马尼亚岛,它显然在 Kaggle 数据集中被删除了。

在下面的代码片段中,我们执行了一些预处理步骤。两个值得注意的步骤是聚合目的(因为我们将使用严格的层次结构)和将澳大利亚各州重命名为它们的缩写。最后,我们还创建了一个州和地区的连接,以创建一个惟一的标识符,然后我们将使用它来创建层次结构。

完成所有步骤后,数据帧如下所示:

作者图片

使用这个一行程序,我们可以检查数据集中每个州内的区域。

# inspect all the regions per state
df.groupby("state")["region"].apply(set).to_frame()

作者图片

下一步是创建一个数据框架,我们可以将它提供给scikit-hts模型。数据框架应该以列的形式包含每个时间序列,行表示给定时间段(在本例中为季度)的观察值。

使用上面的代码片段,我们创建了三个数据帧,层次结构的每一级都有一个数据帧:

  • 底层—这只是一个将长格式的初始数据帧转换为宽格式的枢纽,
  • 中层—在旋转数据框架之前,我们首先对状态求和,
  • 总级别—最高级别,是所有状态的总和。

准备好数据帧后,我们使用索引将它们连接起来,并打印层次结构中每一层的唯一系列的数量:

Number of time series at the bottom level: 77
Number of time series at the middle level: 7

加上总计水平,我们得到 85 个独特的时间序列。

创建层次结构

我们将要使用的估计量也需要层次结构的明确定义。准备它的最简单的方法是将层次树构建成一个字典。每个节点(在字典中被标识为键)都有一个孩子列表,作为字典中的相应值。然后,每个孩子也可以是字典中的一个关键,并有自己的孩子。

理解它最简单的方法是看一个例子。在下面的代码片段中,我们创建了时间序列的层次结构。

如您所见,我们受益于创建唯一的州-地区名称,因为现在我们可以通过检查地区名称是否以州的缩写开头来轻松识别州的子地区。下面我们展示一段hierarchy字典。

作者图片

或者,我们可以使用HierarchyTree类来表示我们系列的底层结构。我们必须提供数据帧和字典作为输入,然后我们可以直接将实例化的对象传递给估计器(不需要HierarchyTree的单独组件)。一个额外的好处是稍微好一点的树的结构表示,您可以在下面看到。

作者图片

可视化数据

使用准备好的层次结构,我们可以快速可视化数据。我们从总计水平开始。在该图中,我们可以观察到该练习可用数据的整个历史。

hierarchy_df["total"].plot(title="Trips - total level");

作者图片

第二步,我们把所有的州级系列都标出来。为此,我们可以简单地获取所有列,这些列是已经定义的层次结构中总级别的子级。

ax = hierarchy_df[hierarchy['total']].plot(title="Trips - state level")
ax.legend(bbox_to_anchor=(1.0, 1.0));

作者图片

最后,让我们画出西澳大利亚州的最低水平。我选择这一个,因为它有最少的区域,所以情节仍然容易阅读。

ax = hierarchy_df[hierarchy['WA']].plot(title="Trips - regions of Western Australia")
ax.legend(bbox_to_anchor=(1.0, 1.0));

作者图片

分层时间序列预测

最后,我们可以专注于建模部分。在本文中,我只想强调一下scikit-hts的功能。这就是为什么我提出了简化的例子,其中我使用整个数据集进行训练,然后预测未来的 4 个步骤(一年)。当然,在现实生活中,我们会采用适当的时间序列交叉验证方案,并尝试调整模型的超参数以获得最佳拟合。

本库的主类是HTSRegressor。任何以前使用过scikit-learn的人都会熟悉这个库的用法(初始化估计器- >拟合数据- >预测)。我们要注意的两个论点是modelrevision_method

model确定用于预测单个时间序列的模型的基础类型。目前,该库支持:

  • auto_arima —从pmdarima库中,
  • SARIMAX —来自statsmodels
  • 霍尔特-温特斯指数平滑法—同样来自statsmodels
  • 脸书的先知。

revision_method参数负责分层时间序列预测的方法。我们可以选择:

  • BU —自下而上的方法,
  • AHP —平均历史比例(自上而下的方法),
  • PHA —历史平均值的比例(自上而下的方法),
  • FP —预测比例(自上而下的方法),
  • OLS —使用 OLS 的最佳组合,
  • WLSS -使用结构加权 OLS 的最佳组合,
  • WLSV -使用方差加权 OLS 的最佳组合。

要更详细地了解这些方法,我建议你参考 预测:原理与实践

自下而上的方法

我试图从自底向上的方法开始,但是,我不断遇到奇怪的错误。同样的语法也适用于其他修订方法,所以我认为库中存在某种缺陷。

但是我们还是可以看看语法。首先,我实例化估计器——在这种情况下,我使用自动 ARIMA 和自底向上的修正方法。然后,我使用熟悉的fit方法拟合模型。作为参数,我传递包含所有时间序列的数据帧和包含层次结构的字典。最后,我使用predict方法获得了 4 个样本外预测。得到的数据帧包含n + 4行,其中n是原始数据帧中的行数。我们得到拟合值(n)和在这些值之上的 4 个预测值。

自上而下的方法

在运行上一个例子失败后,我使用平均历史比例转移到自上而下的方法。这一次,代码运行成功。

下面,您可以看到三个级别(总计级别、州和地区级别)的拟合值和预测值。为了简洁起见,我只展示了一个较低层次的例子。在笔记本中,您可以找到一个方便的函数,用于为层次结构的任何级别生成图。

使用自上而下方法的总计水平。图片由作者提供。

使用自上而下方法的状态级别(SA)。图片由作者提供。

使用自上而下方法的最低级别系列之一的示例。图片由作者提供。

正如我们所看到的,这些模型在时间序列的起点非常偏离,但是它们很快就稳定下来了。当然,这是一个非常不科学的性能评估,但是如前所述,我们纯粹关注于获得分层预测,并且调整它们超出了本文的范围。另一个观察结果是,较低的级别更不稳定,也就是说,它们包含更多的噪声。

在玩这个库的时候,我注意到了一些怪癖:

  • scikit-learn API 不同,我们不能使用n_jobs=-1来指示使用所有可用的内核。当使用除 0 以外的数字时(如库的作者提供的例子),我得到了奇怪的结果。
  • 在可用的例子中,作者建议在调用fit方法时分配一个输出。
  • 当使用 Prophet 作为底层模型时,结果会大相径庭。你可以在下图中看到这一点。

使用 Prophet 和自顶向下的方法时会产生奇怪的结果。图片由作者提供。

使用 OLS 的最优组合

最后,我们利用 OLS 进行最优协调。代码只需稍加调整。

为了便于比较,我们展示了与自上而下方法完全相同的水平图。

使用 OLS 方法得出的总计水平。图片由作者提供。

使用 OLS 方法的州级(SA)。图片由作者提供。

使用 OLS 方法的最低级别系列之一的示例。图片由作者提供。

这种差异在最低层次上最明显,使用 OLS 方法的拟合要好得多,尽管该系列本身非常嘈杂。这并不奇怪,因为最佳协调方法可以提供最准确的预测(有关其优势的更多信息,请参见之前的文章)。

还有一件事我们应该知道——OLS 方法为第一次观察创造了一个负的拟合值。正如我们所知,数列中的所有值都是非负的。然而,考虑到它只是拟合值,并且只是针对系列中的第一次观察(当算法具有非常少的信息时),这应该不是问题。

结论

在本文中,我展示了如何在 Python 中使用scikit-hts进行分层时间序列预测。该库提供了一个类似于 scikit-learn的 API,并且很容易上手。

但是,该库是 alpha 版本。在花了相当多的时间试图让这个例子工作(并不是所有的修订方法都成功)之后,我必须说 Python 库要赶上 R 的对等体fable还有很长的路要走。不幸的是,文档也很不完整,不容易理解(回购中的例子也是如此)。

话虽如此,如果在一个严肃的项目中使用scikit-hts是有意义的,我会给予额外的考虑。我要么考虑创建一个定制的解决方案(特别是如果使用更简单的方法,比如自底向上的方法),要么可能针对特定的预测转移到 R。

您可以在我的 GitHub 上找到本文使用的代码。如果你设法克服了我在文章中提到的问题,我会很高兴听到你是如何做到的。此外,欢迎任何建设性的反馈。可以在 Twitter 或者评论里联系我。

喜欢这篇文章吗?成为一个媒介成员,通过无限制的阅读继续学习。如果你使用这个链接成为会员,你将支持我,不需要你额外付费。提前感谢,再见!

您可能也会对以下文章之一感兴趣:

</5-free-tools-that-increase-my-productivity-c0fafbbbdd42>

参考

K-均值聚类介绍:实现和图像压缩。

原文:https://towardsdatascience.com/introduction-to-k-means-clustering-implementation-and-image-compression-8c59c439d1b?source=collection_archive---------14-----------------------

蚂蚁

本文通过 K-means 集群的 Python 实现对其进行了介绍。此外,它还包括其在图像压缩中的应用。

K-means 聚类是最流行的无监督聚类算法之一。聚类意味着由于某些相似性而分组在一起的数据点的集合。聚类有大量的应用,如细分、排序、营销和销售等。在本文中,我将通过 K-means 聚类的 Python 实现来介绍它的思想,以及如何将它用于图像压缩。

算法

k 均值算法。来源:Incheol via Wikimedia

  1. 初始化:从输入图像中随机抽取 k 种颜色。这些是初始的 k 均值

2.对于图像中的每个像素,将其分配到由下式给出的最接近的平均值

欧几里得距离

3.使用步骤 2 中的像素分配更新平均值。

找到每个聚类的中间点

4.重复步骤 2 和 3,直到收敛。

Python 实现

现在我附上我的上述算法的 Python 实现。然而,这种实现仅用于教育目的,因此在时间方面效率不高。为了看出这一点,我将比较两种实现处理相同图像所用的时间。

图像压缩

为什么需要图像压缩技术?

图像压缩可能有多种需求,例如:

  1. 数据压缩后需要的空间更少,从而可以用更少的磁盘空间存储更多的数据。这在医疗保健中至关重要,因为医疗图像需要存档,而且数据集的量非常大。
  2. 有时我们需要提取并存储图像中最有用的部分,这被表示为嵌入,因此图像压缩可能是存储更多数据的非常有益的方法。

圣巴西勒大教堂。来源:Julius SilverviaWikimedia

让我们以上面显示的一幅图像为例,仔细看看如何使用 K-means 聚类来解决这个问题。我将把我们的任务分解为以下子任务:

  1. 数据预处理
  2. 使用点云可视化颜色空间
  3. 可视化 K-意味着减少颜色空间

数据预处理

您可能已经知道,一幅图像由三个通道组成,即红色、绿色和蓝色,每个通道的值都在[0,255]的范围内。因此,某个图像可能有 255 * 255 * 255 种不同的颜色。因此,在我们输入图像之前,我们需要对其进行预处理。首先,我们需要通过将图像除以 255,将图像归一化到[0,1]的范围内。最后,我们需要展平图像,因为我们可以将 3D 数据输入到我们的算法中。

使用点云可视化色彩空间

原始色彩空间

可以看出,我们的原始图像色彩非常丰富。事实上,有超过 1600 万种可能的颜色。此外,我们可以注意到,一个图像包含多个蓝色阴影,这可能是代表所有表示的整个集群。使用 K-means 聚类算法,我们可以通过相应的质心来概括所有这些颜色。因此,仅通过使用质心来压缩图像。

实现比较

可视化 K-意味着减少颜色空间

压缩色彩空间

在我们对图像进行聚类之后,我们可以看到颜色空间中的颜色变化更加剧烈,因为我们只使用了 16 个质心来表示图像。此外,我们的实现与原始实现的比较表明,它几乎慢了三倍;因此,我只提供给你理解。最后,如果原始图像需要大约 96 kB,那么压缩表示只需要 60 kB,同时保留足够的信息来表示圣巴西勒大教堂。

圣巴西勒大教堂的压缩图像

现在,假设您有 1GB 的空间来存储数据集。您可以存储大约 10,922 张大小为 96kB 的图像,也可以将图像压缩为每张 60kB,存储大约 17,476 张图像。空间越大,这些数字给人的印象就越深刻。

一些遗言

有不同的方法来压缩我们的图像。所以,如果你有兴趣进一步研究它,我附上一些有用的文章。此外,我鼓励您熟悉聚类算法的其他应用。这个作品在我的 GitHub :)上很容易找到

相关文章

https://heartbeat.fritz.ai/a-2019-guide-to-deep-learning-based-image-compression-2f5253b4d811

Python 中 Kafka 流处理简介

原文:https://towardsdatascience.com/introduction-to-kafka-stream-processing-in-python-e30d34bf3a12?source=collection_archive---------2-----------------------

卡夫卡|流媒体| PYTHON

使用 Faust 在 Python 中轻松处理 Kafka 流的分步指南

亨特·哈里特在 Unsplash 上的照片

在我们开始之前,卡夫卡是什么?

让我们首先为那些不了解 Apache Kafka 技术的人提供一个快速的介绍。

Kafka 简单来说就是 Apache 的开源分布式事件流平台。Kafka 允许我们建立和管理实时数据流管道。

为了这篇文章,你需要了解卡夫卡的四个主要概念。

  1. 话题 : 卡夫卡所有的信息都是通过话题传递的。主题只是我们组织和分组信息集合的一种方式。我们可以有多个主题,每个主题都有一个唯一的名称。
  2. 消费者: 消费者是 Kafka 内部的一个实体(通常称为订阅者),负责连接(或订阅)某个特定主题以阅读其消息。
  3. 制作者: 制作者是 Kafka 内部的一个实体(俗称出版者),负责撰写(或发布)某个特定主题的消息。
  4. 消费群体:在卡夫卡中,我们可以有多个主题,有多个消费者订阅。我们也可以有多个服务(即外部应用程序)订阅相同的主题。为了防止重叠和数据问题,每个服务都可以有自己的使用者组来跟踪哪些消息已经被处理(通常称为偏移量)。

TL;速度三角形定位法(dead reckoning)

阿帕奇卡夫卡是一个信息传递系统。

消息按主题组织。

生产者向主题发送数据。

消费者从主题中读取数据。

消费者团体管理一组消费者。

设置本地 Kafka 实例

wurstmeister 为在 docker 容器中运行 Kafka 提供了一个非常好的仓库。

如果我们希望我们的 Kafka 集群可以从外部访问(即从您的终端或服务),我们需要更新 docker-compose.yml 文件。

vim docker-compose.yml 并用以下内容更新它:

然后在终端中 docker-compose up -d

以上将打开 localhost:9092 上的卡夫卡监听器。

一旦构建了 docker 映像,我们应该会看到 Kafka 实例正在运行。

运行中的卡夫卡实例

要进入 Kafka bash shell,我们可以使用:

kafka-docker % docker exec -i -t -u root $(docker ps | grep docker_kafka | cut -d' ' -f1) /bin/bash

现在是我们创建第一个主题的时候了。我们可以通过以下方式做到这一点:

$KAFKA_HOME/bin/kafka-topics.sh --create --partitions 4 --bootstrap-server kafka:9092 --topic test

要列出 Kafka 实例中所有可用的主题,我们可以使用:

$KAFKA_HOME/bin/kafka-topics.sh --bootstrap-server kafka:9092 --list

为了测试是否一切正常,让我们发送一些消息。

在主题测试中启动一个生成器:

$KAFKA_HOME/bin/kafka-console-producer.sh --broker-list kafka:9092 --topic=test

测试制作人

启动主题测试的消费者:

$KAFKA_HOME/bin/kafka-console-consumer.sh --from-beginning --bootstrap-server kafka:9092 --topic=test

测试消费者

我们可以确认消费者阅读了生产者发布的所有消息。

介绍浮士德

Faust 是 Robinhood 开发的流和事件处理框架。Python 社区最终分叉了知识库,并诞生了浮士德流。在这篇文章的整个过程中,我们将使用浮士德流。

《浮士德》背后的概念相对简单,并且很大程度上基于《T4》和《卡夫卡》背后的思想。Faust 使用异步编程,然后要求 Python 版本≥ 3.6.0(由于 async/await 关键字)。

快速提示:对于异步和并发编程的技能复习者,请随意查看这些文章。

浮士德背后的主要概念是:

  1. 浮士德应用程序——实例化浮士德并连接到我们的卡夫卡经纪人。
  2. 代理—创建流处理器。代理是一个异步定义函数。我们使用 @app.agent 装饰器来定义代理。

我们可以使用以下命令通过 pip 安装 Faust:

pip install faust-streaming

构建我们的第一个浮士德应用程序

运行浮士德应用程序非常简单。让我们在 myapp.py 中构建我们的第一个应用。

我们可以使用以下工具运行我们的应用程序:

faust -A myapp worker -l info

这将启动 myapp 的 Worker 实例(由 Faust 处理)。日志 Worker ready 表示 Worker 已经成功启动并准备开始处理流。

这个应用程序将每 5 秒钟向我们的测试 Kafka 主题发送一条消息,并让代理实时消耗它,并为我们打印出来。

运行我们的第一个 Faust 应用程序的示例输出

让我们开始一点一点地剖析代码。

浮士德应用程序

app = faust.App*(*'myapp', broker='kafka://localhost:9092'*)*

在这里,我们为我们的应用程序命名(这也将用于创建 Kafka 消费群),并指定我们的 Kafka 经纪人的位置。假设您和我一起遵循本指南,您不需要更改代理设置。当然,如果您有不同的代理 URL,请指定它们!

这些是《浮士德》入门所需的最低参数。app 参数的完整列表可以在这里找到。

我们还使用 app.topic() 函数指定我们想要使用的主题。我们传入参数 value_type 来强制消息结构。该参数主要用于向 Kafka 主题发送消息。如果我们不需要强制任何消息类型,我们可以将 value_type 设置为使用字节(value _ type = bytes)。

可以通过创建一个 Python 类来实现消息类型,该类扩展了类 faust。记录

代理人

我们通过使用**@ app . agent()装饰器来表示一个函数是浮士德代理。我们传递希望代理订阅的主题,作为装饰器的一部分。

代理应该总是协程。因此,我们应该使用 async def 关键字来定义代理函数。

因为我们的代理订阅了一个主题,所以我们需要一个异步循环来检查流中的消息。我们通过对关键字使用异步来做到这一点。

在这个 for 循环中,我们现在可以访问代理使用的每一条消息。在这里,我们可以开始实现我们的流处理逻辑。

除了为代理订阅 Kafka 主题之外,我们还可以让代理发布一些 Kafka 主题的消息。代理装饰器接受一个参数——sink——它定义了用于发布消息的 Kafka 主题。

在上面的例子中,我们将目标主题作为接收器传递给代理(在本例中,是我们用于源的相同测试主题)。在消费第一条消息(如上所示,我们可以通过生产者发送)时,代理将开始执行异步循环中的逻辑。

我们正在向接收器/目的地主题发出另一条消息。在我们的例子中,目的主题与源主题相同,模拟了我们的 Kafka 主题中不断接收消息的行为。

成批处理

代理还为我们提供了批量处理任何 Kafka 流的能力。我们可以通过 stream.take() 函数实现这种行为。

take() 函数接受两个参数:

  • 最大 _ — 批量消息的最大数量
  • 在-等待接收 max_ messages 的超时时间

我们在例子中还使用了另一个应用装饰器— @app.timer ( 间隔=5.0 ) 。这是一个与代理类似的协程,但是它没有订阅任何 Kafka 流或主题。取而代之的是,这个协程将在每个间隔被触发(在我们的例子中,我们将间隔设置为 5 秒)。

这些装饰器被称为动作。你可以在这里找到已接受行动的完整列表

我们可以在应用程序中定义多个动作(就像我们的例子中所做的那样)。

项目结构

在我们的例子中,我们用一个 python 脚本编写了整个 Faust 应用程序。对于生产代码或更复杂的应用程序,最好将我们的项目结构组织成适当的层次结构。

浮士德建议大型项目采用以下项目结构:

*+ proj/
    - setup.py
    - MANIFEST.in
    - README.rst
    - setup.cfg + proj/
        - __init__.py
        - __main__.py
        - app.py       # APP initialisation and app settings

        + <APP_NAME>/
        -   __init__.py
        -   agents.py  # all agents and actions
        -   models.py  # message structures as python classes
        -   views.py   # all web views*

注意:使用这种结构,我们将在不同的模块中有几个代理和其他动作装饰器。要告诉浮士德搜索这些装修工,我们可以将auto discover = True选项传递给 app.py 中的浮士德 App。

结论

在本文中,我们讨论了如何在 Docker 中生成 Kafka 集群,以及如何使用 Faust 健壮地处理来自 Python 的事件流。我们讨论了如何启动一个最小的浮士德应用程序来订阅 Kafka 流并处理其事件。

就这些吗?肯定不是。浮士德是一个不断发展的巨大图书馆,还有许多其他惊人的功能。但是现在,我们已经有了开始构建高性能分布式系统的基础。

我强烈建议你阅读一下 Faust 文档并继续尝试本库提供的不同功能!

你喜欢这篇文章吗?如果是的话,也许你可以考虑成为会员来支持我和你其他喜欢的作家。

*https://david-farrugia.medium.com/membership *

想给我买杯咖啡吗?

*https://paypal.me/itsdavidfarrugia?country.x=MT&locale.x=en_US *

想联系吗?

我很想听听你对这个话题的想法,或者任何关于 Python 和 AI 的想法。如果你想联系我,请发邮件到 davidfarrugia53@gmail.com 给我。

Linkedin——Twitter

线性规划导论

原文:https://towardsdatascience.com/introduction-to-linear-programming-b6647d20d5f6?source=collection_archive---------18-----------------------

识别线性程序问题并使用 CVXPY 在 Python 中解决它们

Unsplash 上的 Karoline Stk 拍摄的照片

动机

想象一下,不管出于什么原因,你想只吃苹果和草莓。你并不真的偏爱一种水果,但你想确保你…

  1. 摄入足够的维生素 C 和
  2. 摄入足够的热量。

除了维生素 C 和卡路里含量不同,苹果和草莓的价格也不同。所以,很自然地,你会要求最便宜的饮食,同时满足你的两个约束

数例

假设你想每天至少摄入 300 毫克的维生素 C(这太多了,但是这让问题变得更好),以及至少 2000 卡路里的热量。水果数据如下所示:

图片由作者提供。

现在怎么才能找到苹果和草莓的最佳组合呢?从变量开始总是好的:我们将你每天消耗的苹果质量记为 A ,草莓质量记为 S (都以 100 克为单位)由于 AS 都是量,应该都大于等于零

有了这些定义,我们就可以用 AS 和价格:c= 0.3 **A+0.4 S来写成本。 c 应该是最小化了,不过这个到目前为止很容易:什么都不吃,花 0€。然而,我们目前没有纳入我们的营养限制。分别是4.6 A+58.8 **S≥30052 A+33 **S≥2000。饮食 A = 0, S = 0 违反了这些约束,因此不是解决方案。

上面的问题是一个简单的带有两个变量和四个约束的线性规划的情况,可以通过线性规划来解决。

用一种更简洁的表示法,我们必须解决以下问题:

图片由作者提供。

你可以在维基百科上找到的确切定义。

注:称之为线性规划是因为最小化项是线性的, 不是 是因为约束是线性的。

有几种方法可以解决这个问题。为了获得一些直觉,我们将首先通过一个图解方法。这是唯一可能的,因为我们只有两个变量,可以画在平面上。在更高的维度中,我们需要使用不同的算法来解决问题。

图解法

我们能够画出我们所拥有的约束。例如,约束 4.6 A+58.8 **S≥300可以被可视化如下:**

图片由作者提供。

**粗橙线正好是等式 4.6 A+58.8 **S= 300。因为我们有更大的等号,所以不仅线上的点,而且线上的每个点也遵守这个约束。

让我们加上卡路里限制:

图片由作者提供。

此外,我们有约束条件,A和 SS 应该是正数,但我就是这样限制情节的。这意味着我们搜索的解决方案必须在右上区域带有交叉阴影图案的某处,因为只有这些点考虑所有约束。我们称这个区域为可行区域

好的,我们知道现在要去哪里找,但是目标是什么?最小化 0.3* A + 0.4* S !****

我们现在可以从可行域中盲目地插入一些值,但是由于有无限多的点,我们不能期望得到正确的解。比如 A = 60, S = 3 就是候选。这种减肥法的成本是 0.360 + 0.43 = 19.2 €,由 6 公斤苹果和 300 克草莓组成。

一天 6 斤苹果,让每个医生永远远离。

图片由作者提供。

你能想到更好的候选人吗?为了最小化成本,小值的 AS 是有利的,那么我们如何从✖移动到底部和左侧呢?

图片由作者提供。

我们插上,点在 A = 37, S = 2.2 左右。这种减肥法的费用是 0.337 + 0.42.2 ≈ 12 €,比第一种减肥法便宜 7 €左右!作为一个很好的副作用,我们每天只需要吃 3.7 公斤的苹果。愿这是最好的解决方案?

嗯,是的!现在有一些很好的理论说:

最优解总是在可行域的某个角落。

让我们检查一下另一个角,大约在 A ≈ 65, S = 0。这里的成本大约是 0.3*65 = 19.5 €,再次高于其他角落的成本。因此,我们用图解法找到了最优解。甚至没有那么难。

使用 CVXPY 解决问题

正如我之前所说,我们可以解决它,因为我们有两个变量。在更高维度中,我们不能画一些线和检查角落。在这些情况下,我们需要依靠算法来解决这类问题。其中一些是 Dantzig 的单纯形算法或内点方法族,我在此不再描述。相反,让我们使用 Python 库 CVXPY 来完成繁重的工作。

之后,你可以用下面几行来解决上面的饮食问题:

import cvxpy as cp

A = cp.Variable()
S = cp.Variable()

objective = cp.Minimize(0.3*A + 0.4*S)

constraints = [
    4.6*A + 58.8*S >= 300,
    52*A + 33*S >= 2000,
    A >= 0,
    S >= 0
]

linear_program = cp.Problem(objective, constraints)

result = linear_program.solve()

print(f'A = {A.value:.2f}, S = {S.value:.2f}, costs = {result:.2f}')

这个短程序输出 A = 37.06, S = 2.20,costs = 12.00,这证实了我们的图形解决方案确实是正确的!

看看 CVXPY 库的界面有多漂亮。没有比这更瘦的了。你告诉它最小化,并给出公式,你提供一个简单的约束列表,你可以很容易地写,你创建一个问题实例,然后你解决它。你可以清楚地看到我们之前用过的所有公式。

还有其他很棒的包装,另一个著名的是果肉。然而,我认为 CVXPY 语法仍然是最好的。

结论

在本文中,我们已经看到,线性程序不是一种特殊风格的计算机程序,而是一个优化问题。我们制定了一个简单的玩具问题,并用两种不同的方法解决了它。

  1. 最多只能处理两个变量的图解法,但易于理解和手动应用。
  2. 隐藏在 CVXPY 等令人敬畏的高级线性程序库中的高级算法。

CVXPY 甚至可以解决比线性规划更一般的问题,比如最小化公式为二次的二次规划。它还可以解决带有某些约束的线性程序,这些约束使求解变得更加困难,例如变量必须是整数,或者只能是 0/1 。这些问题甚至是 NP-complete ,这通常意味着解决大型实例变得不可行。但是 CVXPY 还是尽力了。

最后一点,当然,还有比我们讨论的更有趣的线性程序。例如,检查一下斯蒂格勒饮食,这是一个类似的问题,但是有更多的食物和营养。无论如何,你现在能够发现线性规划,并相应地采取行动解决它们!

我希望你今天学到了新的、有趣的、有用的东西。感谢阅读!

作为最后一点,如果你

  1. 想支持我多写点机器学习和
  2. 无论如何都要计划获得中等订阅量,

为什么不做 通过这个环节 ?这将对我帮助很大!😊

透明地说,给你的价格不变,但大约一半的订阅费直接归我。

非常感谢,如果你考虑支持我的话!

有问题就在LinkedIn上写我!**

用图介绍机器学习

原文:https://towardsdatascience.com/introduction-to-machine-learning-with-graphs-f3e73c38d4f8?source=collection_archive---------9-----------------------

这是一个关于机器学习的概念性介绍,包括图表和与这个研究领域相关的任务。

图片作者。

什么是图?

图是描述复杂系统中实体之间的关系和交互的数据结构。一般来说,一个图包含一组称为节点的实体和另一组称为边的一对节点之间的交互。节点代表实体,可以是与我们的问题领域相关的任何对象类型。通过用边连接节点,我们将得到一个节点图(网络)。此外,每个节点和边可能有属性(或特征),包含关于那些实例的附加信息。

例如,如果我们想知道一家银行的客户根据他们的资金交易是如何相互关联的,那么我们可以将此建模为一个客户网络,这些客户通过整个客户数据集相互转移资金。在这个网络中,每个节点都是一个客户端,两个客户端之间的边表示这两个客户端曾经互相转账。节点属性可以是银行账号和出生日期。边缘属性可以是总金额、交易次数和第一次交易的日期。图一。显示了该网络的可视化效果。

图一。无向齐次图。图片作者。

无向图与有向图

不包含节点对之间相互作用方向的图称为无向图(Needham&Hodler)。图 1 的图形示例是无向图,因为根据我们的业务问题,我们感兴趣的是基于客户是否已经向彼此汇款来发现客户是否彼此相关。我们对谁是汇款人或收款人不感兴趣。因此,相互作用的方向无关紧要。然而,如果我们对谁是汇款人和收款人感兴趣,那么汇款的方向就很重要。包含一对节点之间交互方向的图称为有向图。我们通过在图的边缘放置箭头来形象化这一点。根据上面的例子,我们也可以将网络建模为一个有向图。在这种情况下,从节点 Adam 到 Barry 的箭头意味着钱已经从 Adam 转移到 Barry。因此,在这笔资金交易关系中,亚当是汇款人,巴里是受益人。图二。显示了这种情况。

图二。有向齐次图。图片作者。

同构与异构图形

另一种区分图形的方法是通过查看图形的节点类型。当图中的所有节点只有一个相同的类型时,那么这个图称为齐次图。上图 1 中的例子。是一个同构图形,因为所有节点都表示“person”类型。想象一下,银行的客户不全是个人,也包括公司。那么该图将包括代表“公司”的另一种类型的节点,这些“公司”具有它们自己的一组节点特征,例如商会编号和成立日期。拥有一种以上节点类型的图称为异构图。此外,还有不同类型边的图。这意味着在网络中,节点可以通过多种方式相互交互。这些图被称为多关系。有一点需要注意的是,在许多用例中,异构图中的边受到它所连接的节点类型的约束。因为某些交互只能发生在两个特定的节点类型之间。图三。显示了公司和个人之间的资金转移网络。该图包含边方向和异构节点。

图三。有向异构图。图片作者。

创建图表时,理解您试图解决的业务问题是关键,因为这将决定图表中的边是否应该有方向,以及它是同构的还是异构的。这很重要,因为当我们运行图算法来计算网络属性时,我们会在有向图和无向图上得到不同的结果。例如,当在无向支付交易网络模型上运行网络算法时,我们假设被转移的钱是双向的。这是极不可能的。

什么是带图的机器学习?

机器学习已经成为通过从历史数据中学习以发现模式和预测未来事件来解决问题的关键方法。当我们试图根据给定的输入标记数据预测目标输出值时,我们是在以监督的方式处理问题。如果目标是在我们的数据中发现模式,我们经常为此创建数据点的聚类,那么我们的方法就是所谓的无监督。使用图形的机器学习融合了这种区别,因为在处理问题时存在两个关键差异。

带图的 ML 从数据点之间的连接中学习
带图的机器学习与传统(无监督)方法之间的第一个关键区别是,后者从单个数据点的属性中学习。这些属性或特征不包括关于各个数据点如何相互连接的信息,而关于数据点之间关系的属性提供了描述数据集的有价值的信息。在图形中,这些数据点由节点表示,关于关系的信息在网络的边中捕获。然而,传统的机器学习方法需要数据科学家手动挑选信息,并在机器学习开发周期的“特征工程”步骤中将它们转化为特征(汉密尔顿)。

带图的 ML 是半监督学习
第二个关键区别是,带图的机器学习试图解决监督和非监督模型试图解决的相同问题,但训练期间是否有标签的要求不是严格强制的。通过对图进行机器学习,我们采用完整的图来训练模型,这也包括所有未标记的节点。尽管这些节点中的某些节点上的标签丢失了,但是我们仍然可以使用测试集中关于邻域节点和边的所有信息来在训练期间改进模型。这与监督模型明显不同,监督模型在训练期间不包括未标记的数据。在这种情况下,图上的机器学习使用标记和未标记的数据来训练模型,因此通常被称为半监督 ( 汉密尔顿)。这里我想指出的是,半监督学习并不仅仅是图上的机器学习。有一个公平的研究和应用领域致力于生成模型,该模型可以从未标记的数据中学习,以提高监督分类器的性能。

最近被充分研究和应用的带有图的机器学习技术可以粗略地分为三个任务:节点嵌入、节点分类和关联预测。我将概括地描述这些任务,说明它们需要什么以及如何在实践中使用它们。

节点嵌入

创建节点嵌入是聚集节点在图中的位置及其本地邻居的信息的任务。这个聚集过程产生一个编码的特征向量,称为节点嵌入,它概括了一个节点的属性及其与本地邻居节点的关系。在许多情况下,获得节点嵌入是实现带有图形的机器学习模型的第一步。通常,在训练期间,作为附加特征,所得到的节点嵌入将被传递到另一个下游机器学习模型中。这里的直觉是,添加节点嵌入将提高下游模型的模型性能,因为它包含关于数据点的基础结构信息,这些数据点不是用模型的初始特征集捕获的( Hamilton,应& Leskovec )。

图 4。生成节点嵌入。图片作者。

例如,让我们从上面亚当和巴里之间的交易数据,并应用随机森林分类器来确定一个人是否是一个骗子。一般来说,典型的机器学习生命周期将从使用一些特征工程技术将原始数据转换为结构化数据开始,这些技术允许我们将这些特征传递到我们的随机森林模型中以预测标签。然而,通过节点嵌入的任务,我们正在学习交易网络中每个人的特征表示。然后,我们像所有其他特征一样,将该节点作为特征向量嵌入到我们的随机森林模型中,并照常预测标签。参见图 5。最近的应用表明,网络特征与常规特征的结合可以大大提高性能。

图五。结合常规特征使用节点嵌入作为下游随机森林分类器的输入特征向量。图片作者。

节点分类

上面我们已经看到了如何通过将节点嵌入作为输入特征向量添加到随机森林模型中来改进机器学习模型。然而,也可以直接从图结构数据中对节点标签进行分类,而不依赖于下游的机器学习模型。这个任务叫做节点分类。节点分类的目标是基于每个节点与其他邻居节点的关联来预测每个节点的标签。真正的标签只包含在整个图形的子集上。因此,给定一个部分标记的图,预测没有标记的节点的标记。

例如,如果我们要对一个野生动物交易网络进行建模,以识别非法交易活动和交易方,那么在这个图中,每个节点都可以是买方或卖方,而一条边则代表这些买方和卖方之间的交易。节点属性可以包括姓名、出生日期和银行账号,而边属性可以包括产品名称、贸易单据号和价格。假设根据报告的数据,一部分卖家被标记为非法交易者。在这种情况下,节点分类旨在预测未被标记的交易者是否应该被标记为非法。它通过调查网络中其他人的交易行为来做到这一点。具有相似特征的节点以及被标记为非法的节点的边也更有可能是非法的。参见图 6。

图六。节点分类:给定一个带有标记和未标记节点的图,根据其节点特征和其邻域节点预测无标记节点。图片作者。

链接预测

链接预测的任务是确定一个图中两个节点之间链接的概率(【詹】&陈)。执行这项任务的一类众所周知的方法叫做启发式方法。这些方法基于它们的试探法(例如图形距离、公共邻居或 Pagerank)来计算两个节点之间的相似性得分。启发式方法基本上揭示了图形、节点和边在某一时间点的属性。我们可以从图中直接计算这些属性,以获得每个节点对的相似性得分。之后,我们根据节点对的相似性得分对其进行排序,并预测得分最高的节点对之间应该存在一条边。最后,我们通过检查初始时间框架中不存在的边是否在稍后的时间点出现来评估我们的预测。

启发式方法的一个缺点是,它假设当两个节点有共同的邻居时,它们更有可能连接。当该图表示一个社会网络(如上面的非法野生动物交易示例)时,可能会出现这种情况,但例如,在蛋白质相互作用网络中,共享许多共同邻居的两个蛋白质不太可能相互作用( Hamilton )。这里的挑战是确定我们应该使用哪种启发式方法来计算对我们的用例有意义的相似性得分。最近的研究表明,我们实际上可以了解这种启发式方法应该如何优化我们的链接预测。这个想法是,我们为每条边取封闭节点,并为这些节点生成一个嵌入。然后,我们将这两个节点嵌入传递到一个连接(或求和、平均、距离等)的函数中。)将它们转换成新的特征向量,并将其传递给下游的二元分类器。参见图 7。

图 7。链接预测:给定一个节点对,它们之间没有链接,根据它们的节点特征和邻域节点预测它们将来是否会连接。图片作者。

结论

图形分析侧重于调查数据集中数据点之间的关系。将数据结构表示为图形使我们能够发现关系和模式,如果我们围绕孤立的数据点对数据建模,这些关系和模式可能会被忽略。图上的机器学习帮助我们对这样的图结构进行编码,这些图结构可以被机器学习模型进一步利用(汉密尔顿)。

来源

https://www.cs.mcgill.ca/~wlh/grl_book/】图表示学
图表示学

图的表征学习:方法与应用 https://arxiv.org/abs/1709.05584

基于图神经网络的链接预测https://papers . nips . cc/paper/2018/file/53f 0d 7 c 537d 99 b 3824 f 0f 99d 62 ea 2428-paper . pdf

图算法 https://www . oreilly . com/library/view/Graph-Algorithms/9781492047674/

Python 市场营销组合建模简介

原文:https://towardsdatascience.com/introduction-to-marketing-mix-modeling-in-python-d0dd81f4e794?source=collection_archive---------1-----------------------

营销分析

哪些广告支出真正推动了你的销售?

蒂姆·约翰逊Unsplash 上拍照

广告入门

为了维持一家公司的运营,在广告上花钱是至关重要的——无论这家公司是小公司还是老牌公司都是如此。这个行业的广告支出是巨大的:

来源:https://www . webstrategiesinc . com/blog/how-much-budget-for-online-marketing-in-2014文章更新于 2020 年)

这些数量使得明智地使用每一美元广告成为必要。然而,说起来容易做起来难,正如美国零售业巨头约翰·沃纳梅克或英国实业家勒弗胡尔姆勋爵在大约一百年前所说的:

“我花在广告上的钱有一半都浪费了;问题是我不知道是哪一半。”

你可能认为现在这已经不是什么问题了,但奇怪的是,它仍然存在。幸运的是,我们能够访问大量数据和强大的计算机,通过高级分析来改变这种状况,如归因建模营销组合建模。在本文中,我们将关注后者,因为它有一个很大的优势,那就是它在我们即将进入的 无烹饪世界 中工作。

示例数据集和简单建模

现在想象一下,你负责某家知名公司的营销预算。为了增加销售额,你在三个不同的广告渠道打广告:

  • 电视
  • 无线电
  • 网页横幅

数据

每周,你决定在每个频道上花多少钱,或者不花。此外,你可以观察每周的销售额。200 周收集的数据可能如下所示:

图片由作者提供。

表格中的所有数字都是你选择的货币,从现在开始我将使用€。 你可以在这里得到上面的文件。

从上面的小偷偷看,我们可以看到有很多周没有电视广告(71%),也有一些没有广播广告(54%)。只有大约 24%的调查对象禁用了网页横幅,这使其成为最常用的渠道。

然而,当我们进行电视广告支出时,它们往往高于广播广告支出,而广播广告支出又高于网络横幅广告支出。再者,一直都有销售。

现在,在开始建模之前,让我们先明确目标。

目标

最终,我们希望能够回答以下问题

截至 2021 年 10 月 10 日的一周,€15,904.11 英镑的销售额中有多少是由电视广告产生的?广播和网络横幅广告的费用是多少?基线是什么,也就是说,如果没有任何广告,我们会有多少销售额?

潜在的结果。图片由作者提供。

如果我们的模型可以做到这一点,我们也可以用它来计算投资回报率和优化支出,这是公司最终想要的。考虑到这个目标,我们可以将自己限制在加法模型,即

销售额= f(电视)+ g(广播)+ h(横幅)+基数

因为他们让我们轻松分解销售。销售额只是某个仅依赖于电视支出的函数、另一个仅依赖于广播支出的函数、另一个仅依赖于网络广告支出的函数和(恒定)基线的总和。

诸如随机森林梯度提升、或(简单前馈)神经网络之类的模型在这里并不合适,因为我们无法从它们那里得到这样的分解。

注: 当然,有做我们想做的事情的沙普利价值观,但往往按照沙普利价值观的贡献是负数,这是营销人不愿意听到的不合理的东西。

给我们每个通道一个加性贡献的候选是一个老朋友——线性回归,加性模型最简单的代表!

你可以在这里找到更详细模型的后续文章:

https://towardsdatascience . com/an-upgraded-marketing-mix-modeling-in-python-5 ebb 3 bddc 1b 6

通过线性回归建模

将上述数据存储在变量data中后,我们执行以下操作:

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score, TimeSeriesSplit
import pandas as pd

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']

lr = LinearRegression()

print(cross_val_score(lr, X, y, cv=TimeSeriesSplit()))

# Output: [0.69594303 0.69302285 0.66850729 0.78807363 0.73512387]

注: 我们这里不使用标准的 k -fold 交叉验证,因为我们处理的是时间序列数据。 *TimeSeriesSplit* 是比较合理的做法,可以在这里https://scikit-learn.org/stable/modules/cross_validation.html#time-series-split了解更多。

嗯,这看起来已经很合理了,尽管还可以做得更好。但是这种模式让我们可以随心所欲地拆分销售,因为公式很简单

*销售额= 0.36 *电视+ 0.49 *广播+ 1.23 横幅+ 6678.40

我们可以通过一个简单的

*lr.fit(X, y) # refit the model with the complete dataset

print('Coefficients:', lr.coef_)
print('Intercept:', lr.intercept_)

# Output:
# Coefficients: [0.35968382 0.48833246 1.2159193 ]
# Intercept: 6678.396933606161*

分解销售

为了说明贡献的计算,让我们考虑一周:

图片由作者提供。

让我们把数字代入,看看我们会得到什么:

*print(lr.predict(([[11543.58, 4615.35, 2518.88]])))

# Output: [16147.01594158]*

这并不完全是上表中 15904.11 的正确答案,但现在让我们坚持下去。我们现在可以看到,电视的(未经调整的)贡献是

coef _ TV * spendings _ TV = 0.36 * 11543.58 = 4155.69,

并且相应地用于其他通道。现在,贡献总计为模型预测 16147.0159,这不是 15904.11 的真正目标,因此让我们将贡献和基线乘以修正因子 correction _ factor = 15904.11/16147.0159≈0.985,一切都很好。我们得到了

贡献 _TV =修正 _ 因子 4155.69 = 4089.57。*

我们也得到

  • 贡献 _ 无线电= 2219.92 和
  • 贡献 _ 横幅= 3016.68
  • 基数= 6577.93。

把所有东西加起来就产生了我们想要的观察标签:

4089.57 + 2219.93 + 3016.68 + 6577.93 = 15904.11.

我们可以为所有观察值生成一个很好的贡献图,如下所示:

*weights = pd.Series(
    lr.coef_,
    index=X.columns
)

base = lr.intercept_

unadj_contributions = X.mul(weights).assign(Base=base)

adj_contributions = (unadj_contributions
                     .div(unadj_contributions.sum(axis=1), axis=0)
                     .mul(y, axis=0)
                    ) # contains all contributions for each day

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)
)*

输出是:

图片由作者提供。

我们可以看到(或计算出)基线是每天大约 6500 次销售,横幅广告和广播活跃时平均贡献大约 2500 次,电视活跃时大约 3500 次。不错!

计算投资回报(ROI)

我们现在可以确定哪个渠道在 ROI 方面是最好的,ROI 是一个衡量效率的数字。公式很简单:

channel_ROI =渠道销售额/渠道支出

有了上面的代码片段,我们已经拥有了计算所需的所有数据。您可以按如下方式计算电视投资回报率:

*sales_from_tv = adj_contributions['TV'].sum()
spendings_on_tv = data['TV'].sum()
tv_roi = sales_from_tv / spendings_on_tv
# tv_roi is around 0.36*

就这么简单。投资回报率小于 1 意味着渠道表现不佳。对于电视投资回报率,我们可以说:

我们在电视上每花 1 €,就能得到 36 美分的回报。

如果我们想让公司生存下去,这种交易就不要做得太频繁。另一方面,横幅广告的投资回报率为 1.21,这要好得多,看起来这个渠道在我们考虑的时间段内工作得相当好。

这个简单方法的问题

虽然上述方法似乎合理,但它有一些我们必须解决的缺点:

  1. 表演可以更好。有时候,我们对糟糕的表现无能为力,因为它在很大程度上取决于数据,但无论如何我们都应该尽力而为。
  2. 更严重的是:模型本身绝对不能反映现实。根据线性公式,我们可以通过在广告上花费越来越多的钱来推动销售。由于横幅广告的系数很高,为 1.23,因此我们在该渠道中每花费 1 €,就会产生 1.23 €的额外销售额。重复无限的钱,客户会讨厌这种伎俩!
  3. 优化也变得琐碎和不现实。为了实现销售最大化,我们现在将把所有资金投入到网络横幅广告渠道,因为它的系数最高。我们将完全放弃电视和广播广告,如果公司想在人们中保持知名度,这可能不是正确的做法。

我们将在后续文章中解决所有这些问题,敬请关注!

总结与展望

我们已经看到,公司将收入的很大一部分用于广告,以鼓励客户购买他们的产品。然而,有效地使用营销预算并不容易,无论是一百年前还是今天。要弄清楚某个电视广告支出对销售的影响有多大,并由此确定广告支出是否值得,以及如何在下次进行优化,这并不容易。

为了解决这个问题,我们创建了一个小型营销组合模型,允许我们将观察到的销售分成几部分:电视、广播、横幅和基本份额。这些渠道贡献让我们可以计算投资回报率,从而了解每个渠道的表现。

然而,这种模型过于简单,无法捕捉现实,这就产生了许多问题。但是,我们将学习如何通过使模型稍微复杂一些,但仍然可以解释来规避这些问题。

你可以在这里找到后续文章:

* *

我希望你今天学到了新的、有趣的、有用的东西。感谢阅读!

作为最后一点,如果你

  1. 想支持我多写点机器学习和
  2. 无论如何,计划获得一个中等订阅,

为什么不通过此链接https://dr-robert-kuebler.medium.com/membership***?这将对我帮助很大!😊*****

说白了,给你的价格不变,但大约一半的订阅费直接归我。

非常感谢,如果你考虑支持我的话!

有问题就在 LinkedIn 上写我!

马尔可夫链编程导论

原文:https://towardsdatascience.com/introduction-to-markov-chain-programming-8ddbe0ac1c84?source=collection_archive---------8-----------------------

什么是马尔可夫链,为什么有用,如何实现

想象以下场景:你想知道明天的天气是晴天还是雨天。现在,根据你的经验和对天气的历史观察,你可能会有一种自然的直觉。如果过去一周天气晴朗,那么你有 90%的把握明天也会是晴天。但是,如果前一周左右的天气一直是阴雨连绵,那么明天是晴天的可能性就不太好了:只有 50%的可能性。这个场景可以描述为一个 马尔可夫链 的过程。

邵杰Unsplash 上拍照

什么是马尔可夫链?

但是什么是马尔可夫链呢?马尔可夫链是一个数学系统,它描述了根据某些随机或概率规则从一个状态到另一个状态的转换的集合。

以我们之前预测第二天天气的场景为例。如果今天天气晴朗,那么根据我们(可靠的)经验,明天天气转变为雨天的概率是 10%,晴天的概率是 90%。另一方面,如果目前天气是多雨的,那么明天保持多雨和晴朗的概率是 50%。

不同状态之间的这些变化(或没有变化)被称为转变,而感兴趣的变量(即雨天或晴天)被称为状态。

遵循马尔可夫规则的天气转变

然而,对于这些转移来说,要成为马尔可夫链,它们必须满足马尔可夫性质。属性声明转移的概率完全只取决于当前状态,而不取决于前面的序列集。这个特性允许马尔可夫链无记忆

为什么是马尔可夫链?

既然我们已经讨论了什么是马尔可夫链,我们来讨论一下为什么值得去熟悉。马尔可夫链在现实世界的过程中有许多应用,例如博弈论、物理学、经济学、信号处理、信息论等等。

此外,这个看似简单的过程是许多更复杂的随机模拟方法的基础,如马尔可夫链蒙特卡罗(MCMC)或隐马尔可夫链。此外,马尔可夫链是许多现代数据科学技术的前身,例如贝叶斯统计的构建模块之一。

总之,马尔可夫链将成为你理解数据科学中更高级的统计建模技术的良好起点。因此,当务之急是通过数学理解来理解马尔可夫过程的基础知识,并对其算法实现进行编码。

关于马尔可夫链的更多信息:数学定义

马尔可夫链模型将状态转移的概率表示为一个 转移矩阵 如果系统有 N 个可能的状态(例如 N =2 用于我们的天气预测情况),那么转移矩阵将有一个 N x N 形状的转移矩阵。随后,矩阵的单个条目 N(i,j) 将指示在状态 I 和状态 j 之间转换的概率。

对于我们的天气预测情况,转移矩阵,可以表示为:

转移矩阵, T ,用于天气预报问题

如果你想确定多个阶段的概率,比如说在接下来的 M内天气会下雨,会发生什么?你可以简单地把转移概率提高到 m 的幂。**

编程马尔可夫链

让我们试着用 Python 编写上面的例子。

  1. 导入必要的库
*import numpy as np
import random as rm*

2.定义状态及其概率(注意:确保每行的总概率总和为 1)

*states = ["sunny", rainy"]
transitions = [["SS", "SR"],["RS", "RR"]]T = [[0.9, 0.1],[0.5, 0.5]]*

3.让我们编写(相当乏味的)马尔可夫链函数来预测未来 n 天的天气!(注意:你可能应该寻找更好的 Python ,它抽象了马尔可夫链的实现)。

4.比如说,在接下来的 5 天里运行这个程序。

*future_weathers = weather_forecast(n_days = 5)*

结论

我们已经描述性地和正式地讨论了什么是马尔可夫链,以及为什么学习它的基本原理是重要的。我们还从头开始编写了一个非常基本的马尔可夫过程。既然您已经熟悉了马尔可夫链的工作原理,那么您可以深入研究更复杂的随机建模技术,比如隐马尔可夫过程或 MCMC。更多这些后续内容敬请期待!

做订阅我的邮件简讯:【https://tinyurl.com/2npw2fnz】***在那里我定期用通俗易懂的英语和漂亮的可视化总结 AI 研究论文。*****

内存映射 IO 简介

原文:https://towardsdatascience.com/introduction-to-memory-mapped-io-3540454770f7?source=collection_archive---------11-----------------------

利用内存映射 IO 实现超高速并行文件写入

附身摄影Unsplash 上拍照

什么是内存映射文件?

内存映射文件虚拟内存中的一段。虚拟内存是物理内存的抽象,由 操作系统 (OS)提供给 进程 。如果操作系统耗尽内存或看到某个进程长时间空闲,这些虚拟内存段将被“分页”到物理磁盘位置上(“交换”)。所以“交换本质上是磁盘上的那部分虚拟内存。

更准确地说,内存映射文件是完全由操作系统管理的虚拟内存上的部分(或全部)文件的镜像

换句话说,每当一个文件被内存映射时,操作系统会立即将文件内存映射到虚拟内存上的一个区域。你可以认为这是一些内存空间。每当操作系统将文件内容转储到磁盘(以容纳另一个任务)时,就会发生页面错误。这时操作系统会返回并将内容重新加载到 RAM 中。但是我们的程序将永远看不到这种变化,而是在 内存映射 IO 中面临偶尔的延迟。

在本文中,我将只讨论内存映射写。下次再读!我将以一个生物信息学相关的任务作为运行实例。请随意将它转换到您自己的领域并进行尝试。

内存映射文件写入的额外好处

使用或不使用内存映射文件有很多理由。我只谈优点!

并行性:内存映射区可以认为是一个巨大的字节数组。所以你可以从尽可能多的线程中写/读。或者甚至在进程之间共享。只要不出现竞态条件。

性能:内存映射写入通常很快,因为不使用流/文件缓冲区。操作系统执行实际的文件写入,通常一次写入几千字节的数据块。

不利的一面是,除非你按顺序写,否则可能会有页面错误减缓你的程序。

开始编码吧!

照片由丹尼尔·伊德里Unsplash 拍摄

在这个例子中,我们的任务如下:

给定 100 万个 DNA 序列,将其矢量化,并以文本形式写入,用于未来的机器学习任务。注意,每个向量具有 136 维的固定大小,并且使用函数 *vectorize(sequence)* 来获得,因为它是如何完成的并不相关。为了使它更有趣,让我们从单线程的常规文件写入开始,逐步改进我们的程序。

单线程操作

我们将简单地读取序列并进行矢量化。得到的向量将被转换成一个字符串,并写到输出缓冲区。概要 C++代码可在这里获得。

while (seq := has_sequence(input_file))
    vector := vectorize(seq)
    output << to_string(vector)

多线程操作

在多线程操作中,我们需要确保输出和输入的顺序相同。否则,我们可能会忘记哪个数据点是哪个数据点。因此,我将使用一个数据队列进行读取,并使用一个消费者进行批处理和并行处理。这两个过程是异步发生,因此队列总是满的。

Queue = {}thread_1
while (seq := has_sequence(input_file) and Queue.size() < 20000)
    Queue := Queue + seqthread_2
while Queue.size() != 0
    batch := dequeue(Queue, 10000 items)
    batch_vectors := vectorize_batch(batch)
    output << to_string(batch_vectors)

注意,为了清楚起见,我省略了互斥和其他细粒度的同步技巧。概要 C++代码可在这里获得。我使用了条件变量来访问队列和终止线程。

存储器映射操作

关于内存映射操作,有一些事情需要记住。当创建一个新的内存映射文件时,我们必须指定一个大小。这是因为我们不能动态地增加操作系统分配给我们的区域(我们可以通过复制来增加大小,比如调整数组大小。这可能非常慢)。因此,我们需要对总产出规模有一个概念。这对我们来说很容易,因为我们知道向量的大小。我们还可以通过在数据集上快速迭代一次来获得数据项的总数。所以我们的代码如下:

num_sequences := iterate_once_get_seqs()
vector_size := 136
float_size := 8 
size_of_line := vector_size * (float_size + 1)
size_of_file := size_of_line * num_sequences
mmap_file := mmap.open(output, size_of_file, write_mode)

请注意,此时我们已经创建了一个内存映射文件。我们固定了浮点值的长度(要么填充零,要么截断十进制精度)。让我们在以固定宽度方式书写时变得容易。

vectorize_function:
   lock(mutex)
   seq := has_sequence(input_file)
   unlock(mutex)
   if (seq):
       vec := vectorize(seq)
       mmapfile.write(**offset**, to_string(vec))thread_pool(many threads)for _ in range(num workers)
    thread_pool.add_worker(vectorize_function, mmapfile)

注意,我们有一个偏移参数。这可以通过下面的等式获得:

offset := size_of_line * sequence_id

序列 id 是数据集中从零开始的序列的索引。我们将把内存映射文件指针从开始增加到偏移量,并在该偏移量处复制字符串向量。操作系统会处理剩下的事情。

注意,我们在文件读取时只有一个互斥体!不再有阻塞的调用或序列的批处理。

每种方法的性能

我使用了/usr/bin/time -v program.o命令来获得每种方法使用的 CPU 和 Wall 时间。结果如下。

作者图片

请注意,CPU 使用率从 80%增加到了 420%。它几乎是批处理多线程方法的两倍。CPU 时间几乎保持不变,因为我们要做的计算量大致相同。墙壁时间减少到四分之一。然而,由于操作系统将内存映射文件保存在 RAM 中,RAM 的使用从 2MB 增加到了近 1GB。因为我有足够的内存,操作系统似乎一直在内存中维护文件。使用 linux diff命令验证了结果。

我们几乎用光了我电脑的全部 4 个内核!这是一个胜利!也节省了很多时间。

卢卡斯·布拉塞克Unsplash 拍摄的照片

结束语

我们可以通过使用各种其他技巧(比如使用内存映射来读取文件)来进一步优化这个程序。然而,收益是以额外的工作和编码为代价的。在这个例子中,我使用了 C++ Boost 库(#include <boost/iostreams/device/mapped_file.hpp>)。Boost 有一个可移植的内存映射扩展,它可以帮助你忘记你运行的平台。

Python 也有类似的实现(参考文档)。因此,即使对于 python 程序员来说,这也应该相当简单。

我希望你喜欢阅读这篇文章,并相信这些知识将有助于编写更好更快的程序。在下面找到完整的项目(面向生物信息学家);

https://github.com/anuradhawick/seq2vec

祝您愉快!😃

R 中的元分析介绍

原文:https://towardsdatascience.com/introduction-to-meta-analysis-in-r-468e9b33925c?source=collection_archive---------6-----------------------

如何将研究结合起来提供一个洞见的世界

meta 这个词是希腊语,意思是“T1”后面的“T0”,或者“T2”后面的“超越”。所以荟萃分析是指后分析后分析。虽然这听起来有些奇怪,但元分析实际上是一种方法,可以:

  1. 结合分析几次试验。
  2. 估计一个总结治疗效果。
  3. 获得一个超出单独分析数据时发现的(单一)影响的发现。

元分析这个词是研究综合的同义词。它综合了各种研究的结果,以便得出一个总的结论。研究越同质,结论就越明确。荟萃分析既看内部效度,也看是否有影响?—和外部有效性——这种效果可以推广到哪一部分?。也许描述元分析的最佳方式是谈论苹果、梨和(腐烂的)水果。

元分析的唯一目标是比较苹果和梨。然而,如果你的研究是异质的,你可能不仅会得到一个苹果或一个梨,还会得到一个香蕉、一个橘子和一些葡萄。现在,在这种情况下,苹果和梨之间的比较受到严重影响,你能做的最好的事情就是谈论水果。如果研究本身存在严重的方法缺陷,你就只能吃腐烂的水果了。也许最好什么都不要说,尽管这样的发现实际上可能比明确的荟萃分析更有趣。

进行荟萃分析的主要原因是:

  1. 当单一试验由于局限性和/或异质性无法提供治疗效果时,如农业中的农场,增加功率
  2. 农场/国家的处理效果的变化进行估计。****
  3. 中确定哪些农场和国家的治疗显示出我们想要看到的效果。

因此,荟萃分析的目标不仅仅是报告平均治疗效果,而是理解效果的模式。如果跨研究的效应大小是一致的,我们需要知道并考虑其含义。如果 T2 发生变化,我们也需要知道这一点,并考虑其影响。最终,您将:

  1. 结合不同的研究,通过增加样本量和统计功效来展示治疗效果。
  2. 减少小型个体研究中常见的高II 型误差(假阴性结果)的不确定性。
  3. 在广泛的实验条件下获得更多自信结论(外部效度)。

然而,在大多数研究领域,一项功能强大的随机对照试验 (RCT)仍然被认为足以提供可靠的治疗评估和变更指南。在农业中,我们通常期望动物代表种群,这对于来自单一农场的研究来说是没有意义的。此外,由于农场的限制,仅使用一个农场来设计一个功能强大的研究即使不是不可能,也是具有挑战性的。此外,如果我们对不同农场、甚至不同国家的治疗效果感兴趣,我们需要对治疗的外部有效性有一个全面的认识。

理论上,要进行荟萃分析,你至少需要两项研究。最好,你包括更多,没有上限。为了提高效率,纳入的研究必须进行完全相同的处理。然而,它们不必有完全相同的设置——有时我们实际上想要不同的设置来增加外部有效性。包含各种设置可能会产生负面的结果——添加任何新的东西都等于增加了变化,而这种变化并不总是能够用一个新的设置来解释。

在任何荟萃分析中,最重要的考虑是确定包括哪些研究。如果至少纳入的治疗方法完全相同,那么荟萃分析是最强有力的。此外,您必须确定是否存在使试验不可比的试验因素。所有这些都取决于研究者,而不是统计学家。关键是要确定影响处理效果的因素,这些因素超出了因不同农场或国家而产生的随机变化的预期。

简而言之,你的研究设计应该反映你进行荟萃分析的目的。这意味着所有纳入的研究应具有相同的研究设计、相同的治疗和相同的研究方案。在开始元分析的第一项研究之前,应该做一个合理的功效计算,记住元分析

到目前为止,应该很清楚进行一个合理的元分析需要做出几个选择,这些选择是科学的而不是统计的。一旦你开始分析,算法并不能抵消你选择包括水果而不仅仅是苹果和梨。因此,您需要在设计阶段预先确定潜在的影响者,并确定他们的重要性。你应该想到的重要问题是:

  1. 治疗效果会不会没那么强?
  2. 治疗效果会不会走向另一个方向?
  3. 在设计阶段限制/删除其影响的可能性有多大?
  4. 如果我不能在设计阶段限制他们的影响,那么在分析中限制/删除他们的影响的可能性有多大?
  5. 如果我不能限制它们的影响,而且影响很大,我还能把这项研究纳入荟萃分析吗?

现在,当我们到达分析阶段时,大多数人不太清楚的是,元分析理论上是一个混合模型:

  1. 固定效果→治疗
  2. 随机效应→研究(方差之间)
  3. 重复效应→研究(方差内)

因此,荟萃分析着眼于研究间差异的治疗效果,可以使用包括研究内和研究间差异的两级混合模型进行描述。在第一级,效果大小估计只是效果大小参数加上随机变化。如果我们结合所有的效应大小估计,我们得到平均效应大小估计。在第二级,效应大小参数由平均效应大小加上特定研究的随机效应决定。随机效应代表研究间的差异。随机效应的变化描述了研究间的变化量

在左边,你有一个固定效应元分析,它把数据处理成只有一个真实效应+随机变化。在右边,你有一个随机效应元分析,它将数据处理为具有多个真实效应+跨研究的随机变化。(图片来自 https://ebmh.bmj.com/content/17/2/53BMJ)

现在,在必要的介绍之后,让我们开始吧。进行元分析的代码出奇的少,因为元分析的所有重要工作都必须在实际分析之前完成。垃圾进,垃圾出。

metafor 包是这篇文章的核心。

接下来是数据争论和根据感兴趣的结果分割数据集。

数据显示,元分析没有太多必要。这里,我们有每个研究结果组合的平均值、标准差(SD)和两种治疗的观察次数(N)。还有一些额外的变量可能会影响分析,但我们暂时不考虑它们。图片作者。

现在,我们将使用必要的指标——mean、sd、N——来估计所请求的感兴趣的度量。这里,我们指定处理之间的平均差异。然而, metafor 包允许估计更多的度量。

对于每个感兴趣的结果,我们要求根据每个治疗的平均值、标准差和观察次数计算特定结果的平均差异。

现在发生的是,基于输入,算法将分别为每个研究计算平均差异()和抽样方差( vi )。

在这里,您可以看到每项研究的平均差异和抽样方差。图片作者。

这两个指标是下一个算法——随机效应荟萃分析——需要详细说明治疗效果和差异,以及获得总体治疗效果和研究间异质性的估计。就像我已经说过的,它本质上是一个混合模型,所以将会发生的是——在研究水平上——一个固定的治疗效果和一个随机的研究截距是合适的。这将为我们提供治疗差异的总体估计、治疗间方差的估计(这里称为 I)以及研究内变异的估计。

下面的代码是 metafor 为每个结果请求的:

  1. 进行随机效应荟萃分析。
  2. 提供了异质性的估计。
  3. 提供了置信区间。
  4. 使用森林图显示结果。

元分析的分析非常简单

下面你会看到随机效应模型的结果。总共包括 7 项研究,初步估计显示异质性很小。这意味着我们可以更加肯定地“相信”所提供的显示治疗之间显著差异的比较。

图片作者。

方差的置信限显示了估计自然边界为零的指标的置信限有多困难。尽管如此,还是要密切关注,因为零点估计值之上的宽间隔可能暗示着收敛误差。图片作者。

尽管查看置信区间等指标总是好的,但元分析真正最好的评估是通过它的森林图。在这里,人们可以很容易地发现过多的内部和之间的差异,并获得一个良好的总体估计的有效性的感觉。

在下图中,除了一个点(研究 3)之外,所有的点估计都显示了类似的效果。它们的内方差不同,但间方差很小甚至不存在。因此,正如输出中已经显示的,我们有一个同质批次。

最重要的是理解我必须解释的东西——而且还必须解释无数次:没有显示出统计学意义的研究,可能会导致具有统计学意义的汇总估计。原因是所有的研究估计被汇集以获得更好的信噪比。如果研究过于异质性,或者没有显示出相同的效果,荟萃分析实际上可能弊大于利。

显示每项研究的平均差异和变异内的森林图,导致汇总估计和研究间变异的估计。图片作者。

并非所有的结果都表现出相同的同质性。图片作者。

下面的代码结构可以提供更好的情节。

图片作者。

现在,请记住,进行荟萃分析的危险隐藏在我刚刚展示的简单性中。当一个荟萃分析显示出很多异质性时,你必须接受结果是垃圾,不能使用。在这一点上,分组或敏感性分析可能会对你有所帮助——还有元回归——但是这些选择本身也有危险,我将在以后的文章中讨论。

别忘了,荟萃分析是一个混合模型。因此,适用于混合模型的所有假设在这里也适用。

表格数据建模简介:用最大似然法预测学生被录取的机会

原文:https://towardsdatascience.com/introduction-to-modelling-tabular-data-predicting-a-students-chance-of-gaining-admission-using-ml-3a440f709c71?source=collection_archive---------19-----------------------

我们如何使用回归模型、随机森林和神经网络来预测学生被研究生院录取的机会?

简介

这种分析的目的是探索学生进入研究生院的最重要因素,并选择最准确的模型来预测学生进入研究生院的机会。

我将使用的数据是大学毕业生录取 2 数据集,它可以在 Kaggle 上找到,灵感来自加州大学洛杉矶分校的录取数据集。

导入所需的库

#import required libraries
from pandas.api.types import is_string_dtype, is_numeric_dtype, is_categorical_dtype
from fastai.tabular.all import *
from sklearn.ensemble import RandomForestRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from IPython.display import Image, display_svg, SVG
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import statsmodels.api as sm
import numpy as np

探索性数据分析

我们首先将 csv 文件加载到 Pandas DataFrame 中,并删除不需要的列。

#load csv into Pandas dataframes
data_df = pd.read_csv('../input/graduate-admissions/Admission_Predict_Ver1.1.csv')#drop the serial no. of the students as we dont need it 
data_df.drop('Serial No.', axis = 1, inplace = True)

然后,我们将执行 EDA,以更好地理解我们的数据,并观察数据中的任何模式。

首先,我们可以绘制一个热图来可视化变量之间的相关性。

corr = data_df.corr()#plot correlation matrix heatmap
hm = sns.heatmap(data = corr, annot = True, cmap = sns.color_palette("flare", as_cmap=True)
)

相关矩阵热图。图片作者。

从相关矩阵热图来看,似乎所有的变量都与录取机会正相关,CGPA、GRE 分数和 TOEFL 分数是与录取机会最相关的变量。

为了进一步形象化我们的数据,我们绘制了入学机会对变量的散点图。

#plot scatter plots of Chance of Admission to each of the variables
column_names = list(data_df.columns)
column_names.pop(-1)fig = plt.figure(figsize = (20,10))
fig.subplots_adjust(hspace=0.4, wspace=0.4)
for i in range(0, len(column_names)):
    ax = fig.add_subplot(2, 4,i+1)
    sns.scatterplot(x = data_df[column_names[i]], y = data_df['Chance of Admit '], hue = data_df[column_names[i]] )

从上面的图来看,CGPA,TOEFL 成绩,GRE 成绩都显得与录取几率呈线性关系。大学排名较高的学生似乎也有更高的录取机会。具有更高目标陈述(SOP)和推荐信强度(LOR)的人似乎也有更高的录取机会。此外,有研究经验的学生往往有更高的录取机会。

造型

我们将拟合 3 种不同的模型,即多元线性回归模型、随机森林和神经网络。我们还将尝试集成模型以产生更精确的模型。

我们将使用均方差来评估我们的数据。较低的均方误差表示模型更精确。

然后,我们在拟合我们的机器学习模型之前分割我们的数据集。

#split our data into train and test data
Y = data_df['Chance of Admit ']
X = data_df.drop(columns = {'Chance of Admit '})X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)

线性回归

我们将使用 statsmodel 库将 OLS 线性回归模型拟合到我们的数据中。与 sklearn 库相比,我更喜欢使用 statsmodel 库进行回归建模,因为 stats model 提供了关于所用模型的更多见解,但是使用任何一个库都会产生相同的结果。

我们将拟合以下没有交互项的模型:

录取几率= beta_0 + beta_1 * GRE 成绩+ beta_2 *托福成绩+ beta_3 *大学评级+beta _ 4 * SOP+beta _ 5 * LOR+beta _ 6 * CGPA+beta _ 7 *研

#fit a multiple linear regression model using statsmodels#add a constant
X1_train = sm.add_constant(X_train)
X1_test = sm.add_constant(X_test)#fit model
model = sm.OLS(Y_train, X1_train).fit()
predictions = model.predict(X1_test)print_model = model.summary()
print(print_model)#i used statsmodels as it provides additional insights about the model but both would work perfectly fine
#below is the code for fitting with sklearn
"""
from sklearn.linear_model import LinearRegression# with sklearn
regr = linear_model.LinearRegression()
regr.fit(X_train, Y_train)"""

上面的代码给出了以下输出:

statsmodels 输出。图片来自作者。

从上面的输出中,我们可以看到模型的 R 平方为 0.821,表明与数据非常吻合。我们还可以观察到,大学评级系数和 SOP 与 p 值不显著,分别为 0.541 和 0.721。该模型在测试集上给出了 0.003705 的均方误差。移除不显著变量会导致稍微高一点的均方差 0.003773 以及 R 平方值稍微下降。因此,我们将使用完整的模型。

请注意,在实践中,如果准确性略有下降,我们通常会选择更简单的模型,因为更简单的模型通常更容易解释和推广。

随机森林

我们将使用 sklearn 库来使随机森林模型符合我们的数据。

forest = RandomForestRegressor(n_estimators=1100,max_depth =6 ,max_features = 0.5)
forest.fit(X_train, Y_train)
predictions_rf = forest.predict(X_test)#calculate the mean squared error 
mean_squared_error(predictions_rf, Y_test)

在拟合我们的随机森林模型后,我们不仅想知道我们的模型有多精确,还想知道我们的模型是如何进行预测的。为此,特性重要性让我们深入了解这一点。

def rf_feat_importance(m, df):
    return pd.DataFrame({'cols':df.columns, 'imp':m.feature_importances_}
                       ).sort_values('imp', ascending=False)#check most important features
fi = rf_feat_importance(forest, X_train)def plot_fi(fi):
    return fi.plot('cols', 'imp', 'barh', figsize=(12,7), legend=False)plot_fi(fi);

特征重要性图。作者图片

从图中,我们可以看到像 CGPA,GRE 分数和 TOEFL 分数这样的特征对模型来说是最重要的,而像 Research 和 LOR 这样的特征对模型来说是不太重要的。因为没有一个特征具有非常低的特征重要性值,所以我们可以将这些特征保留在模型中。

随机森林模型在测试集上给出的均方差为 0.003922

神经网络

我们将使用构建在 PyTorch 之上的强大的 FastAI 库来为我们的数据拟合神经网络。为此,我们必须对数据进行预处理,并创建数据加载器将数据输入神经网络。为了处理连续变量和分类变量,我们可以使用 fastai 的函数 cont_cat_split(),它会自动拆分连续变量和分类变量。请注意,该函数将“SOP”误认为是一个连续变量,因为它有 0.5 个值,但实际上它是分类变量。

train_df = X_train
test_df = X_test
train_df = train_df.join(Y_train)
test_df = test_df.join(Y_test)#split the variables into continuous variables and categorical variables using fastai's factory method
cont_nn,cat_nn = cont_cat_split(train_df, dep_var='Chance of Admit ')

然后,我们可以创建数据加载器。

#create dataloaders
procs_nn = [Categorify, FillMissing, Normalize]
to_nn = TabularPandas(train_df, procs_nn, cat_nn, cont_nn, y_names='Chance of Admit ',splits = RandomSplitter(valid_pct=0.4)(range_of(train_df))
)
dls = to_nn.dataloaders()

在创建数据加载器之后,我们可以在 FastAI 中创建一个表格学习器。

#create tabular learner
learn = tabular_learner(dls, y_range=(0.3,1),n_out=1, loss_func=F.mse_loss)

然后,我们可以使用 fit_one_cycle 对我们的模型进行 15 个时期的训练,看看它看起来如何:

learn.lr_find()

学习率查找器。图片作者。

learn.fit_one_cycle(15, 1e-2)

图片作者。

神经网络在测试集上给出的均方差为 0.003744

test_df.drop(['Chance of Admit '], axis=1, inplace=True)
dl = learn.dls.test_dl(test_df)preds = learn.get_preds(dl=dl)#convert the predictions into a list
y = []
for i in range(0,len(Y_test)):
    x = preds[0][i].tolist()
    y += x

mean_squared_error(y,Y_test)

组装

作为线性回归模型,随机森林和神经网络都有各自的优缺点。我们可以做的事情是把三个世界结合起来,试图产生一个更好的结果。有许多方法可以做到这一点,但我们将只使用一种简单的方法,即取模型预测的平均值。

ens_preds = (predictions + predictions_rf + y) /3
mean_squared_error(ens_preds, Y_test)

通过组合模型,我们在测试集上获得了 0.003607 的均方误差,这优于所有 3 个模型本身!

结论

汇总表。图片作者。

在这种情况下,与神经网络和随机森林相比,线性回归似乎表现得最好,这证明复杂的模型并不总是产生更好的结果。然而,与单独的 3 个模型相比,组合模型产生了更好的结果。

代码可以在我的 Github 中找到

自然语言处理深度学习理论简介

原文:https://towardsdatascience.com/introduction-to-nlp-deep-learning-theories-9d6801e3aa7d?source=collection_archive---------13-----------------------

NLP 深度学习

我从自然语言处理和深度学习课程中学到的总结

帕特里克·托马索在 Unsplash 上的照片

在这篇文章中,我将总结我从斯坦福大学提供的自然语言处理与深度学习中学到的东西,包括【2017 年冬季视频讲座,以及【2019 年冬季系列讲座。两场讲座都由斯坦福大学的克里斯托弗·曼宁教授授课。这两个讲座中涉及的深度学习 NLP 理论的几个主题包括:

  • 单词表示法
  • NLP 神经网络
  • 注意力和变压器
  • 最近的 NLP 深度学习模型

1.单词表示法

深度学习模型依靠数字向量来“理解”输入的单词。我们可以认为数字向量是代表输入单词的高维特征。在这个高维度空间中,单词的位置要么彼此靠近,要么彼此远离。

通过为给定语料库中的所有单词找到适当的数字向量表示来构建单词表示。单词表示的质量依赖于语料库。这可以很容易地理解为两个人对同一个词可以有不同的理解,取决于他喜欢花时间读现代报纸还是莎士比亚的文学。此外,单词表示的质量很大程度上依赖于找到所有单词的数字向量表示的方法。有几种通过从单词的上下文中学习来生成单词表示的方法。

从一个字所交的朋友,你就可以知道这个字。

约翰·鲁珀特·弗斯

1.1 基于计数的方法:共生矩阵

共现描述了两个词在一定距离内的出现,该距离由固定的窗口大小定义。在语料库层面上,共现矩阵捕捉语料库中所有独特单词对的共现频率。这样,它提供了语料库的统计描述。共现矩阵中的每一行都是代表一个单词的数值向量。

然而,为了捕获语料库中所有独特单词对的共现频率,该共现矩阵会占用大量内存。假设你有一个拥有 10k 个唯一词的语料库,那么共现矩阵的规模就是 10k 乘 10k!同时,每个词向量的维数是 10k!为了降低单词向量的维数,通常使用奇异值分解(SVD)。

从小型语料库构建的共现矩阵。

1.2 基于预测的方法:Word2vec

除了纯粹依赖于统计的基于计数的共现矩阵方法之外,还可以通过使用浅层前馈神经网络模型的基于预测的方法来生成词向量。这种基于预测的方法包括 word2vec,它可以用 skip-gram 或连续词包(CBOW)算法来实现。skip-gram 和 CBOW 算法都是针对固定窗口大小内的词进行预测,它们的预测方向不同。Skip-gram 使用中心单词预测上下文单词,而 CBOW 使用上下文单词预测中心单词。

skip-gram 算法使用给定的中心单词预测上下文单词。

使用浅层神经网络来训练 Skip-gram,并且输入是 T 个唯一单词的语料库。每个单词被随机分配为一个 d 维向量。这样,在这个浅层神经网络中有 2Td 个参数需要优化,中心词矩阵和上下文词矩阵各有 T*d 个参数。该神经网络通过迭代地将每个单词作为中心单词并在给定当前中心单词的情况下最大化上下文单词的概率来训练。

Word2vec 可以在 Gensim 上获得,它可以很容易地导入到代码中,以生成基于预测的词向量。

1.3 基于计数和基于预测相结合的方法:Glove

一方面,共现矩阵在语料库水平上提供单词共现的统计描述。另一方面,word2vec 通过使用浅层神经网络来捕获窗口大小内的上下文单词的预测能力。Glove 是一种被提出来结合这两种方法的架构,以具有统计能力和局部上下文预测能力。与 word2vec 类似,Glove 也是使用浅层神经网络进行训练的。成本函数是 Glove 与 word2vec 的区别。Glove 的成本函数包括 Xᵢⱼ,即单词 j 在单词 I 的上下文中出现的次数,并且这并入了语料库的统计描述。

Glove 也可以作为 Python 库使用。斯坦福 Glove Python 库可以作为预训练的词向量生成器,因为它是在大规模网络数据集上预训练的,具有像维基百科和 Twitter 这样的语料库。此外,它还可以在新的语料库上进行训练。

手套成本函数

2.NLP 神经网络

到这里,我们已经学习了单词表示法,即将单词变成机器可以理解的数字向量。然后,下一步是弄清楚如何使用这些单词表示来完成 NLP 任务。

许多 NLP 任务可以被认为是分类问题。一个简单的例子是情感分析,它可以简单到将电影评论分为积极或消极的情感。一个不太直接的例子是下一个单词预测的 NLP 任务。当我想预测“我喜欢吃……”后面的下一个单词时,这个下一个单词可以是我的语料库中的任何单词。下一个单词预测的方法是计算我的语料库中所有唯一单词的概率,然后选择概率最大的单词。Softmax 通常用于归一化多个输出类的概率。

下一个单词预测任务的 Softmax

softmax 的问题在于它是输入单词向量的线性变换。因此,对于多类分类问题,它只能给出一个线性的决策边界。对于复杂的 NLP 任务,单词向量的线性变换是不够的。我们需要在将单词向量送入 softmax 的最后一层之前引入非线性。神经网络是一种解决方案,可以在 softmax 的最后一层之前实现,以将非线性引入模型。

在本节中,我们将从基本的神经网络元素——神经元开始,然后讨论 NLP 任务的三种基本神经网络架构,即递归神经网络(RNN)、卷积神经网络(CNN)和树形递归神经网络(树形 RNN)。

2.1 神经元

神经元是神经网络中的基本计算单位。在一个神经元中,输入经过线性变换后,结果被送入逻辑回归。逻辑回归将非线性引入到神经元的计算中。因此,神经元本质上是一个二元逻辑回归单元。神经网络由多层组成,其中每层进一步由一束神经元组成。我们可以将每一层想象成同时运行的几个逻辑回归,然后将结果输入到另一个逻辑回归中。

神经元和神经网络

2.2 递归神经网络(RNN)

通常,在 NLP 任务中,我们会处理一系列单词,这些单词可以是不完整句子的电影评论或写得很好的研究文章。预测下一个单词需要对前面的单词序列有一个整体的理解。RNN 是一种适合处理数据序列的体系结构。基本上,在每个时间步,一个单词向量被输入到 RNN 的一个神经元中。除了在该时间步长的输入单词向量之外,神经元还接收携带关于先前时间步长的信息的隐藏状态。这样,单词序列的信息在神经网络中传递。

递归神经网络体系结构

上面提到的 RNN 建筑也被称为香草 RNN。香草 RNN 遭受消失梯度问题,这是由反向传播过程中的参数更新的长链引起的。反向传播旨在更新神经网络参数以最小化输出误差。然而,由于香草 RNN 的顺序连接性质,进一步的神经元的参数不能有效地更新。这样,神经元很容易死亡。为了克服香草 RNN 的消失梯度问题,提出了两个先进的 RNN 建筑解决方案:门控循环单元(GRU)和长短期记忆(LSTM)。GRU 和 LSTM 解决渐变消失问题的方法是通过引入某种形式的门控机制来控制传递到当前单元格的前一个单元格的信息量。

门控循环单元体系结构

长短期记忆结构

2.3 卷积神经网络(CNN)

RNN 允许信息跨时间流动,从而能够理解全球语义。这在本质上决定了 RNN 计算是一个缓慢的过程,因为后面的神经元等待来自前面神经元的信息流。作为一种更快的解决方案,CNN 已经被探索用于一些对全局语义理解要求较低的 NLP 任务。

CNN 广泛应用于计算机视觉模型中。CNN 的基本思想是对输入数据并行应用多个滤波器,每个滤波器提取某个特征。在计算机视觉任务中,这些过滤器识别空间中的局部模式。类似地,当应用于 NLP 任务时,这些过滤器可以被训练来识别时间上的局部模式。

当窗口滑过输入时,过滤器对给定窗口大小内的输入单词向量进行处理,其中窗口大小是在 CNN 训练中要优化的超参数。对于每个过滤器,当找到一个特定的模式时,它将强烈激发,并可以由后续的 max-pooling 层选择。例如,在情感分析中,当发现“不喜欢”时,窗口大小为 3 的过滤器将强烈启动。这样,我们可以把一个窗口大小为 n 的滤波器想象成 n 元模式搜索器。

3.注意力和变压器

RNN 和 CNN 是 NLP 深度学习模型中广泛使用的基本单元。RNN 擅长顺序学习远程语义,而 CNN 擅长学习局部语义,可以通过并行计算实现。远程语义和并行计算很重要,有可能两者同时实现吗?在本次会议中,我将讨论一些最新的高级神经网络架构。

3.1 注意:基于解码器查询对齐编码器信息池的相似性评分机制

由于伯特模型,许多人都听说过“注意力”和“变压器”这两个词。然而,与 transformer 架构(直到最近才在谷歌 2017 年名为 Attention is All You Need ⁴的出版物中提出)不同,注意力机制在神经机器翻译中已经使用了很长时间。根据 Christopher Manning 的说法,神经机器翻译是通过一个大型人工神经网络对整个机器翻译过程进行建模的方法。

传统上,神经机器翻译使用带有编码器和解码器的序列到序列模型,编码器和解码器使用 RNN 单元构建。在没有注意机制的编码器-解码器架构中,编码器序列中的最后一个神经元是连接到解码器的唯一单元。然而,编码器序列中的最后一个神经元可能无法携带输入序列中的所有有用信息。注意机制可以解决这个问题。

无注意机制的神经机器翻译

注意机制允许解码器神经元从编码器的信息池中提取隐藏状态。注意层采用两个输入向量,这是编码器和解码器的隐藏状态,并返回归一化的相似性得分。这样,关注层有助于根据给定的解码器查询来调整编码器信息。

具有注意机制的神经机器翻译

3.2 自我关注:具有并行计算能力的序列处理

RNN 可以携带长距离的语义信息,但是由于顺序处理的性质,计算是缓慢的。相比之下,CNN 作为局部过滤器工作,可以很容易地在并行计算中实现,但同时缺乏长程语义信息。自我注意是一种以并行计算方式获得输入的全局理解的解决方案。

RNN 和 CNN

在自我注意中,每个输入单词首先被编码成三个向量:q、k 和 v。在每个位置计算输出向量。为了获得输出向量,使用输出位置的 q 和所有的 k 来计算注意力得分。然后注意力得分和每个 v 向量的加权和生成输出向量。

我认为自我关注是一种修正的 CNN 结构。在 CNN 中,过滤器仅适用于特定窗口大小内的附近输入向量。这样看来,CNN 善于捕捉地方特色。由于该滤波过程是纯粹的矩阵运算,因此可以容易地以并行方式实现,多个滤波器同时工作以寻找不同的特征。在自我关注中,这个过滤过程被修改,改为在每个输入位置取一个编码向量。这种修改使人们能够关注 CNN 固有的矩阵运算和并行实现的优势,同时也带来了理解全局语义的新优势。

自我注意机制

3.3 变压器:建立在自关注机制上的基本单元

transformer 是 2017 年提出的深度学习基本单元架构,使用自关注机制构建。该变换器可以代替 RNN,取序列输入,产生序列输出,同时可以实现并行计算。

变压器 architecture⁴

4.最近的 NLP 深度学习模型

到目前为止,我已经讨论了单词表示(共现矩阵,word2vec,Glove)和初级深度学习单元架构(RNN,CNN,transformer)。在这一节中,我们将回顾自然语言处理领域的最新进展。

迁移学习已经广泛应用于计算机视觉领域,从图像分类到目标检测的计算机视觉任务大多使用在大型图像数据集上预先训练的模型。然而,NLP 中的迁移学习直到 2018 年才成为可能。在过去的两年里,已经出现了几个预先训练好的通用语言模型。我们将经历一些突破。杰伊·阿拉玛写的一篇关于最近 NLP 发展的好文章可以在这里找到。

4.1 ELMo:首个上下文单词嵌入模型

语言嵌入模型(ELMo)是第一个上下文词嵌入模型,于 20 世纪初在⁸⁵.发表我们已经在这篇文章的第一部分讨论了单词表示。然而,在 ELMo 之前的所有单词表示模型,包括 word2vec 和 Glove,都只能生成静态的单词嵌入。对于静态单词嵌入,我们的意思是每种单词类型只有一个单词嵌入。例如,在“河岸”和“银行账户”中,“银行”一词将具有相同的矢量表示。这种静态单词嵌入不能很好地表示单词在特定语言环境中的含义。

相反,ELMo 通过使用两个双层 LSTM 的内部状态来生成上下文单词嵌入,这两个双层包括向前和向后单元。确定如何使用内部状态来生成加权和结果(即上下文单词嵌入)的参数是在每个特定的 NLP 任务中学习的。

ELMo⁶正反两层 LSTM 结构

4.2 ULMFit:用 transformer 代替 lstm,探索 NLP 迁移学习

继 ELMo 之后,通用语言模型微调(ULMFiT)也于 20 世纪初在⁸⁷.发布 ELMo 和 ULMFiT 的一个区别是,ULMFiT 用一个变压器取代了所有的 LSTM 单元,这是谷歌在 2018 年初刚刚发布的。

ULMFiT 的目标是实现一个可用于迁移学习的通用语言模型。实现 ULMFit 分为两个阶段:在通用领域语料库上进行语言模型预训练,以及在特定的自然语言处理任务中进行微调。这样,预先训练的语言模型学习到了语言的一般特征,迁移学习有助于快速训练模型适应不同的 NLP 任务。

4.3 GPT:使用正向变换器的大规模预训练 NLP 语言模型

在 ULMFit 中,在通用领域语料库上的预训练语言模型的第一阶段是无监督的学习任务。未标记的文本语料库非常丰富,而标记良好的文本语料库却很难找到。预训练语言模型的无监督学习方式使得该模型通常可以从大量可用文本中学习。ULMFiT 在一个相对较小的语料库上进行预训练,以证明迁移学习语言模型的可能性。然后在 ULMFiT 之后不久,生成性预训练(GPT)由 OpenAI 在 20 ⁸⁸.出版与 ULMFiT 类似,GPT 使用前向变换器,但 GPT 是在模型中有更多参数的更大语料库上训练的。

2019 年初,OpenAI 发布了 GPT- ⁹,这是一个比 GPT 更大、更强大的预训练语言模型。它有 1.5B 个参数,并在 40GB 的互联网文本上进行了预训练。

GPT⁶的正向变压器

4.4 BERT:使用双向转换器的大规模预训练 NLP 语言模型

2018 年底,谷歌发布了变形金刚(BERT)⁶.)的双向编码器表示与 GPT 相似,BERT 也是一种语言模型,与 ULMFiT 相比,它在更大的语料库上进行预训练,具有更多的参数。

由于我在这次 Kaggle TensorFlow 2.0 问答比赛中使用了 BERT,因此在本系列的后续帖子中将提供更多关于 BERT 的讨论。

BERT⁶的双向变压器

5.摘要

在这篇文章中,我总结了我从自然语言处理和深度学习课程中学到的东西。文章介绍了单词表示和 NLP 神经网络结构。希望你觉得总结有用!

[1] Pennington,Jeffrey,Richard Socher 和 Christopher Manning。"手套:单词表示的全局向量."在2014 年自然语言处理经验方法会议(EMNLP) 中,第 1532–1543 页。2014.

[2]赵京贤、巴特·范·梅林波尔、卡格拉尔·古尔切雷、迪米特里·巴丹瑙、费特希·布加雷斯、奥尔赫·施文克和约舒阿·本吉奥。"使用统计机器翻译的 RNN 编码器-解码器学习短语表示." arXiv 预印本 arXiv:1406.1078 (2014)。

[3] Hochreiter、Sepp 和 Jürgen Schmidhuber。“长短期记忆。”神经计算 9,8 号(1997):1735–1780。

[4] Vaswani、Ashish、Noam Shazeer、Niki Parmar、Jakob Uszkoreit、Llion Jones、Aidan N. Gomez、ukasz Kaiser 和 Illia Polosukhin。“你需要的只是关注。”在神经信息处理系统进展中,第 5998–6008 页。2017.

[5]彼得斯、马修·e、马克·诺依曼、莫希特·伊耶、马特·加德纳、克里斯托弗·克拉克、肯顿·李和卢克·塞特勒莫耶。"深度语境化的词语表达." arXiv 预印本 arXiv:1802.05365 (2018)。

[6] Devlin,Jacob,张明蔚,Kenton Lee 和 Kristina Toutanova。"伯特:用于语言理解的深度双向转换器的预训练." arXiv 预印本 arXiv:1810.04805 (2018)。

[7]霍华德、杰里米和塞巴斯蒂安·鲁德。“用于文本分类的通用语言模型微调。” arXiv 预印本 arXiv:1801.06146 (2018)。

[8]拉德福德、亚历克、卡蒂克·纳拉辛汉、蒂姆·萨利曼斯和伊利亚·苏茨基弗。"通过生成性预训练提高语言理解能力."网址https://S3-us-west-2。 亚马逊鹦鹉。com/open ai-assets/research covers/language unsupervised/语言理解论文。pdf (2018)。

[9]拉德福德、亚历克、杰弗里·吴、雷文·蔡尔德、戴维·栾、达里奥·阿莫代伊和伊利亚·苏茨基弗。"语言模型是无人监督的多任务学习者." OpenAI 博客 1,第 8 期(2019)。

标准化流程简介

原文:https://towardsdatascience.com/introduction-to-normalizing-flows-d002af262a4b?source=collection_archive---------0-----------------------

为什么以及如何实现 gan 和 vae 上的标准化流

学习复杂数据表示的表示是机器学习中的一个基本问题。这项任务的重要性在于可以获得大量非结构化和无标签的数据,这些数据只能通过无监督学习来理解。它可以应用于密度估计、离群点检测、文本摘要、数据聚类、生物信息学、DNA 建模等。多年来,已经引入了许多方法来学习大数据集的概率分布。这些技术包括生成式对抗网络(GANs)、变分自动编码器(VAEs)和规范化流程。

来自发光模型的样本(来源

GANs 和 VAEs 在学习复杂的数据分布和简单的推理方法方面显示了令人惊叹的结果。然而,GAN 和 VAE 都缺乏对概率分布的精确评估和推断,这通常导致 VAEs 中的低质量模糊结果,并且在 GAN 中具有挑战性的 GAN 训练具有诸如模式崩溃和消失梯度后验崩溃等挑战。通过使用可逆函数,标准化流被提出来解决 gan 和 vae 的许多当前问题。

标准化流程

简而言之,标准化流是一系列可逆的简单函数,或者可以计算出函数的解析逆。例如,f(x) = x + 2 是可逆函数,因为对于每个输入,存在唯一的输出,反之亦然,而 f(x) = x 不是可逆函数。这种函数也称为双射函数。

(来源:作者)

从上图可以看出,归一化流程将复杂的数据点(如 MNIST 图像)转换为简单的高斯分布,反之亦然。从训练生成器的 GANs 中可以看出明显的差异,该生成器采用随机向量并产生图像,其中基于流量的模型在训练期间从数据点转换为简单分布。在测试期间,从高斯分布中抽取随机样本,以从模型反向获得 MNIST 图像。

使用负对数似然损失函数训练基于流量的模型,其中 p(z)是概率函数。下面的损失函数是利用基本统计学中的变量变化公式得到的。

(来源

标准化流程的优势:-

规范化流提供了各种优于 GANs 和 VAEs 的优势。其中一些列举如下

  • 标准化流模型不需要在输出中加入噪声,因此可以具有更强大的局部方差模型。
  • 与 GAN 的 GAN 训练相比,基于流的模型的训练过程非常稳定,GAN 训练需要仔细调整生成器和鉴别器的超参数。
  • 与 GANs 和 VAEs 相比,标准化流更容易收敛。

标准化流程的缺点:-

虽然基于流的模型有其优点,但它们也有如下一些缺点

  • 由于流模型在密度估计等任务上表现平平,人们认为它们不如其他方法有表现力。
  • 流动模型双射的两个要求之一是变换时的体积保持,这通常导致非常高维的潜在空间,这通常更难解释。
  • 与 GANs 和 VAEs 相比,通过基于流量的模型生成的样本没有那么好。

为了更好的理解,我们以 Glow 架构为例,这是 OpenAI 在 2018 年提出的基于流程的模型。下图显示了 Glow 架构。

发光建筑(来源)

glow 架构是由本文后面讨论的一些表面层组合而成的。首先,我们将通过辉光模型的多尺度架构。光晕模型由一系列重复层(称为“比例”)组成。每个秤都包含一个挤压功能,后跟一个流动步骤。每个流程步骤都包含 ActNorm、1x1 卷积和耦合层,后跟一个分裂函数。分裂函数在通道维度上将输入分成两个相等的部分,其中一半进入进一步的层。相比之下,后半部分去损失函数。进行分割是为了减少梯度消失的影响,当以端到端的方式训练模型时,会发生梯度消失。

挤压函数通过对张量进行横向整形,将大小为[c,h,w]的输入张量转换为大小为[4c,h/2,w/2]的张量,如下所示。此外,在整形期间,可以在测试阶段使用函数来将输入[4c,h/2,w/2]整形为大小为[c,h,w]的张量。

(来源)

其他层如 ActNorm、1x1 卷积和仿射耦合层可以从下表中理解,该表以正向和反向方式显示了每层的功能。

(来源)

实施:

在讨论了标准化流程和发光模型的基础知识后,我们将使用 PyTorch 实现该模型,并在 MNIST 数据集上进行训练。

发光模型:

首先,我们将使用 PyTorch 和 nflows 实现 Glow 架构,它包含所有层的实现,以节省实验时间。

该模型可以在各种数据集上进行训练,例如 MNIST、CIFAR-10、ImageNet 等。在本文中,我们将仅限于 MNIST 数据集。像 MNIST 这样的数据集可以很容易地从 Graviti 的开放数据集平台中访问,该平台包含机器学习中常用的所有开放数据集,用于各种任务,如分类、密度估计、对象检测和基于文本的分类数据集等。

要访问一个数据集,用户需要在 Graviti 平台上创建一个账户,派生相关数据集以下载并导入他们管道中的数据集。基本代码片段和相关文档可在 TensorBay 平台上获得。

为 MNIST 数据集创建 PyTorch 数据集的代码示例如下所示。

训练模型:

要训练模型,可以编写一个简单的脚本,如下所示。该代码使用 Graviti tensorbay 管道创建数据加载器。ACCESS_KEY 可以从 accounts 部分的设置中获得。

以上脚本用于为 MNIST 数据集训练规范化流量模型。通过替换相应数据集的数据加载器,可以类似地训练其他数据集的模型。

生成样本:

在为两个数据集训练模型之后,我们可以生成如下样本

nflows 库提供了一种仅使用一行代码生成样本的完美方式。显示功能在正方形网格中显示生成的样本。为两个数据集生成的样本如下

在 MNIST 数据集上生成的样本

结论:

本文介绍了标准化流的基本知识,并将其与其他 gan 和 vae 进行了比较,然后讨论了 Glow 模型。我们还实现了发光模型,并使用 MNIST 数据集对其进行了训练,并从两个数据集采样了 25 幅图像。在 Graviti 的开放数据集平台的帮助下,数据集可以更容易地访问。除了采样之外,还可以使用潜在空间向量来做更多的事情,比如让一张脸微笑或者改变性别或头发颜色,以及许多其他事情。

使用 MongoDB 介绍 NoSQL

原文:https://towardsdatascience.com/introduction-to-nosql-with-mongodb-8e5a2513c9e8?source=collection_archive---------24-----------------------

实用入门指南

照片由金莎·艾利斯Unsplash 上拍摄

关系数据库以带有标签的行和列的表格形式存储数据。尽管关系数据库通常为存储数据提供了一个不错的解决方案,但在某些情况下,速度和可伸缩性可能是一个问题。

大多数关系数据库管理系统使用 SQL(结构化查询语言)来管理以表格形式存储数据的数据库。NoSQL 指的是非 SQL 或非关系数据库设计。它仍然提供了一种有组织的方式来存储数据,但不是以表格的形式。

NoSQL 数据库存储数据的常用结构是键值对、宽列、图形或文档。数据科学生态系统中使用了几个 NoSQL 数据库。在本文中,我们将使用其中一个流行的 MongoDB。

MongoDB 将数据存储为文档。MongoDB 中的文档由字段-值对组成。例如,下面的内容可以是 MongoDB 中的一个文档。

{
 "name": "John",
 "age": 26,
 "gender": "Male",
}

文档被组织在一个称为“集合”的结构中。打个比方,我们可以把文档想象成表格中的行,把集合想象成表格。

文档采用 JSON (JavaScript 对象表示法)格式。JSON 是一种常用的格式,但是它有一些缺点。

因为 JSON 是基于文本的格式,所以很难解析。就内存效率而言,这也不是一个非常理想的选择。JSON 还限制了支持的数据类型的数量。

为了克服这些挑战,MongoDB 引入了一种叫做 BSON (Binary JSON)的新格式。可以认为是 JSON 的二进制表示。与 JSON 相比,它非常灵活和快速。BSON 的另一个优点是它比 JSON 消耗更少的内存。

由于 BSON 是二进制编码,它不是人类可读的,这可能是一个问题。然而,MongoDB 通过允许用户以 JSON 格式导出 BSON 文件解决了这个问题。

我们可以以 BSON 格式存储数据,并以 JSON 格式查看。任何 JSON 格式的文件都可以作为 BSON 存储在 MongoDB 中。

简单介绍之后,我们来做一些练习。您可以在 Linux、macOS 或 Windows 上安装 MongoDB 社区版。如何安装在 MongoDB 文档中解释得很清楚。

我已经在我的 Linux 机器上安装了它。我们使用以下命令从终端启动 MongoDB。

$ sudo systemctl start mongod

然后,我们只需在终端中键入 mongo 即可开始使用它。

$ mongo

以下命令将打印出服务器中的 MongoDB 数据库。

> show dbsadmin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB

我们可以用 use 命令选择一个数据库。

> use test
switched to db test

我们之前提到过,MongoDB 中的文档被组织在一个称为集合的结构中。为了查看数据库中的集合,我们使用 show collections 命令。

> show collections
inventory

测试数据库中当前有一个集合。我们想创建一个名为“客户”的新集合。这相当简单。我们只需创建一个新文档并插入到集合中。如果数据库中不存在指定的集合,MongoDB 会自动创建它。

> db.customers.insertOne(
... {name: "John",
...  age: 26,
...  gender: "Male",
... }
... ){
 "acknowledged" : true,
 "insertedId" : ObjectId("60098638be451fc77a72a108")
}

正如我们在输出中看到的,文档成功地插入到集合中。让我们再次运行“显示集合”命令。

> show collections
customers
inventory

我们现在在测试数据库中有两个集合。我们可以使用 find 命令查询集合中的文档。

> db.customers.find(){ "_id" : ObjectId("60098638be451fc77a72a108"), "name" : "John", "age" : 26, "gender" : "Male" }

将显示字段-值对以及对象 id。因为 customers 集合中只有一个文档,所以我们没有在 find 函数中指定任何条件。

查找功能允许指定查询数据库的条件。从这个意义上说,它类似于 SQL 中的 select 语句。

结论

我们已经用 MongoDB 简单介绍了 NoSQL。当然,在 NoSQL 和 MongoDB 中还有更多的内容要介绍。

SQL 和 NoSQL 在数据科学生态系统中都至关重要。数据科学的燃料是数据,因此一切都始于正确、维护良好且易于访问的数据。SQL 和 NoSQL 都是这些过程的关键角色。

我将会写更多关于 SQL 和 NoSQL 数据库的文章。敬请期待!

感谢您的阅读。如果您有任何反馈,请告诉我。

目标检测模型评估简介

原文:https://towardsdatascience.com/introduction-to-object-detection-model-evaluation-3a789220a9bf?source=collection_archive---------5-----------------------

超市货架上的物品——查尔斯郡的郡主

评估对象检测模型并不简单,因为每个图像可以有许多对象每个对象可以属于不同的类别。这意味着我们需要衡量模型是否找到了所有的对象,以及验证找到的对象是否属于正确的类。

这意味着对象检测模型需要完成两件事:

  • 查找图像中的所有对象
  • 检查找到的对象是否属于正确的类别

在本文中,您将看到对象检测研究人员如何创建将这两者结合在一个单一指标中的方法,即平均精度(mAP)。

最近发布了两个开源工具,它们在这些评估任务上给了我们很大的帮助。这意味着现在是开始研究对象检测模型的好时机。我们开始吧!

目标检测任务

当你标注对象时,边界框是你画出的指示位置的框。

边界框的例子,来自维基百科

对象检测模型产生三个分量的输出:

  • 如果使用 COCO 文件格式,边界框x1, y1, width, height
  • 边界框的
  • 该预测的概率得分——模型确定该类实际上是预测的类的程度

我们需要仔细看看概率得分的组成部分。主要是因为现代神经网络校准不良[1]:

神经网络架构和训练的最新进展——模型容量、标准化和正则化——对网络校准产生了强烈的影响— 郭川、杰夫·普莱斯、孙玉、基利安·q·温伯格关于现代神经网络校准的文章

现在,假设您需要比较两种不同对象检测模型的性能。因为我们知道概率分数校准得很差,所以在另一个模型上,概率分数为 80%的边界框很可能与概率分数为 50%的边界框具有相同的位置坐标。我们将如何着手比较这些模型的性能?我们将在下一节中解决这个问题。

如您所见,对象检测任务引入了一些我们在常规分类任务中没有看到的新挑战。让我们在接下来的章节中讨论其中的三个。

问题 1:如何分割训练/测试数据集?

在多类分类任务中,您知道数据集在每个影像中的分布,因为每个影像只能有一个类。这意味着你可以很容易地分割你的训练/测试数据。但是在目标检测中,每幅图像可以有许多来自不同类别的目标。

假设您有一个数据集,其中包含超市货架上的图像。假设您无法访问新数据,并且需要拆分此数据集来创建测试集,您将如何将图像拆分到训练/测试组中?

在我参与的一个项目中,我们使用品牌和产品数量进行了一些聚类实验,以从图像中获取样本。我们仍然需要做更多的研究来展示这些发现,但它似乎为我们提供了一个很好的代理来创建对象检测数据集中的训练/测试组。

问题 2:你如何知道一个物体的位置?

为了评估对象是否被定位,我们使用并集上的交集(IoU)作为相似性度量。它由重叠区域的面积除以两个边界框的并集的大小得到。

并集上的交集是如何计算的— 维基百科

IoU 值的一些例子— 维基百科

需要 IoU 来计算平均精度,因为第一步是定义两个边界框是否指向同一个对象。为了回答这个问题,我们使用的默认 IoU 值是 0.5。

问题 3:如何使用单一指标比较模型?

该模型输出边界框的坐标和预测类的概率得分。问题是神经网络没有得到很好的校准,这意味着我们没有直接的方法来比较两个不同模型的概率得分。

这个问题的解决方案是使用每个模型输出的边界框的排序。这是计算平均精度(AP)指标的方法。您开始对概率分数进行排序,然后使用 IoU 阈值来比较边界框是真阳性还是假阳性。

正如Harshit Kumar【2】在这个伟大的解释中所指出的,如果对单个物体有一个以上的检测,则具有最高 IoU 的检测被认为是 TP,其余的被认为是 FP。

计算边界框的精度和召回率——图片来自 Harshit Kumar 文章

计算累计 TP 和累计 FP,并计算每行的精度/召回率。通常,平均精度计算为 11 个等距召回级别的平均精度。Mean Average Precision(mAP)是所有对象类别的平均 AP,它更多地用于评估对象检测模型。

由于我们首先对预测进行了排名,现在绝对概率得分并不重要,我们可以对不同的模型使用相同的指标。

对象标注任务的一个特点是,在对象的位置和大小的表示上缺乏共识,并且性能评估工具实现不同的度量标准[3]。

如果您需要评估一个对象检测模型,并且不想从头开始计算指标(您为什么想要这样做?哈哈)[3]的作者开发并发布了一个名为的开源工具,用于对象检测度量。该工具包填补了目标检测指标的可靠来源的空白。

如果我们需要比较模型,地图是好的,但是如果我们的目标是对它的表现有一个定性的看法呢?我们将在下一节讨论这一点。

为什么平均精度不够

该地图适用于比赛环境或快速评估模型的表现,但如果您想了解模型的表现,您需要不同的指标。

对象检测任务中的误差来源可能是多种多样的:

  • 模型可以找到边界框的正确位置,但输出的类不正确
  • 该模型可以找到具有正确类别的对象,但是对于边界框的位置是完全错误的
  • 模型可能会完全漏掉一个对象
  • 等等

为了解决这个问题,[4]的作者开发了 TIDE 。TIDE 是一个通用工具箱,用于计算和评估对象检测和实例分割对整体性能的影响。

潮汐聚焦视频为 ECCV 2020 造势

工具箱通过修复错误并观察导致的地图变化来确定给定错误对地图整体的重要性。我们来看看分析什么样的错误,他们是怎么做的。

介绍 TIDE(用于识别对象检测错误的工具箱)

作者定义了 6 种错误类型:

  1. 分类错误:定位正确但分类错误
  2. 定位错误:分类正确但定位不正确
  3. Cls 和 Loc 错误:分类错误,定位错误
  4. 重复检测错误:如果不是更高评分的检测,将是正确的
  5. 背景错误:检测到背景为前景
  6. 遗漏燃气轮机错误:所有未被检测到的地面真相(假阴性)尚未被分类或定位错误覆盖

TIDE 错误— Tide:用于识别物体检测错误的通用工具箱

为了测量每种类型的误差,实施了一个 oracle 来纠正它们,并且该工具计算如果不存在这种类型的误差,地图将如何增加。这些信息是黄金,因为它可以指导我们如何改进模型。

下面是一个潮汐结果的例子:

-- mask_rcnn_bbox --

bbox AP @ 50: 61.80

                         Main Errors
=============================================================
  Type      Cls      Loc     Both     Dupe      Bkg     Miss
-------------------------------------------------------------
   dAP     3.40     6.65     1.18     0.19     3.96     7.53
=============================================================

        Special Error
=============================
  Type   FalsePos   FalseNeg
-----------------------------
   dAP      16.28      15.57
=============================

我们可以看到,如果您纠正遗漏的 GT 错误,您可以将地图增加7.53点。现在,您可以研究训练图像和验证图像,以找出如何修复这些错误。如果我们只使用地图结果,61.80,这可能需要很长时间才能弄清楚。

结论

目标检测任务带来了我们在多类分类任务中没有看到的挑战。使用对象检测,您需要找到对象并预测正确的类。此外,每个图像通常具有可变数量的注释对象。

幸运的是,许多优秀的研究人员一直在研究这些问题,现在我们有办法解决它们。为了比较两个边界框是相似的,我们使用并集上的交集(IoU ),并且使用平均精度(mAP)来测量模型性能。用于对象检测度量的开源工具箱提供了一个开源工具,它支持许多边界框格式,并使用不同的度量来评估检测。

仅有地图还不足以确定需要做些什么来提高模型的性能。为了解决这个问题,[4]的作者创建了 TIDE,这是一个计算和评估对象检测对整体模型性能的影响的工具箱。

参考

[1] 郭川杰夫·普莱斯孙玉基连·q·温伯格,《论现代神经网络的校准》arXiv:1706.04599【cs。LG],2016 年 8 月。

[2]库马尔,哈什特。“对象检测和分割的评估指标:地图”。https://kharshit . github . io/blog/2019/09/20/evaluation-metrics-for-object-detection-and-segmentation

[3] Padilla,Rafael 等人,“使用配套的开源工具包对对象检测度量的比较分析”电子学 10.3 (2021): 279。

[4] Bolya,Daniel,等,“Tide:识别对象检测错误的通用工具箱”arXiv 预印本 arXiv:2008.08115 (2020)。

单向方差分析介绍:比较两组以上的平均值的检验

原文:https://towardsdatascience.com/introduction-to-one-way-anova-a-test-to-compare-the-means-between-more-than-two-groups-a656cb53b19c?source=collection_archive---------8-----------------------

不同组的结果看起来不同,但它们在统计上不同吗?

拉奎尔·马丁内斯在 Unsplash 上拍摄的照片

动机

t 检验有助于发现两组之间是否存在显著差异。然而,t 检验不能用于比较三个或更多的独立组。

例如,如果您是产品开发人员,您可能想知道合成纤维中使用的棉花百分比的变化是否会导致纤维拉伸强度的增加。

为了找到答案,你可以进行一个完全随机的实验,有五个棉花含量水平,重复实验五次,代表五次试验。数据可能如下表所示:

从实验的设计和分析中获得的数据,第八版

单看表格,很难知道这 5 个棉花含量水平的平均值之间是否有统计上的显著差异。由于有超过 2 组被比较,在这种情况下不能使用 t 检验。

有没有一种方法可以确定这些均值在统计上是否彼此不同,并产生如下所示的有意义的输出?

统计上无差异的棉花含量水平对:

  • (15,20)
  • (15,25)
  • (15,30)
  • (20,30)
  • (25,35)
  • (30,35)

统计上不同的棉花含量水平对:

  • (15,35)
  • (20,25)
  • (20,35)
  • (25,30)

这时单向方差分析就派上用场了。

什么是单向方差分析?

单向 ANOVA 比较您感兴趣的组的平均值,并确定这些平均值之间是否存在统计差异。单向 ANOVA 有一个独立变量,而双向 ANOVA 有两个独立变量。

由于我们的问题中只有一个独立变量,即拉伸强度,我们将使用单向 ANOVA。

为了在 Python 中执行单向 ANOVA,我们将安装并使用 statsmodels 包:

pip install statsmodels

创建数据

我们将创建简介中显示的数据。

从实验的设计和分析中获得的数据,第八版

不错!数据设置完毕。现在我们准备使用单向 ANOVA 测试。

比较不同组之间的平均值

我们首先测试某些棉花含量水平的平均值在统计上是否不同。

  • 零假设:均值没有差异
  • 替代假设:平均值并不都相等

由于[anova-lm](https://www.statsmodels.org/stable/generated/statsmodels.stats.anova.anova_lm.html)需要一个或多个拟合的线性模型,我们从将普通最小二乘(OLS)模型拟合到我们的数据开始,然后将其用作anova_lm的参数。

模型的 F 统计量为 14.962217。模型的 p 值是 8e-06。

由于 p 值小于 0.05 的显著性水平,因此有足够的证据声称不同水平的棉花含量的一些平均值在统计上是不同的。

即使我们知道一些平均值在统计上总体不同,****两种棉花含量的哪个具体水平不同?这时图基的 HSD(诚实显著差异)就派上用场了。

使用 Tukey 的 HSD 比较每一对平均值

Tukey 的 HSD 发现了哪些特定群体的方法是不同的。该测试比较所有可能的平均值对。

让我们使用MultiComparision和它的turkeyhsd()方法来测试多重比较。

上表解释:

  • group1被比作group2
  • meandiff:group1group2的平均差值
  • p-adj:在多大程度上group1group2具有相同的含义
  • lowerupper:置信区间的下限和上限。
  • reject:如果是True,则拒绝零假设。有足够的证据表明,被比较的两种水平的棉花的平均值是显著不同的。

统计上不同的棉花含量水平对:

  • (15, 35)
  • (20, 25)
  • (20, 35)
  • (25, 30)

为了更好地理解结果,让我们来看看每组有一个置信区间的显著差异图。

上图比较了第 15 组(含 15%棉的纤维)的平均值和其他组的平均值。

  • 因为第 35 组的平均值与第 15 组的平均值在统计上没有差异,所以第 35 组是灰色的。
  • 因为组 20、25 和 30 的平均值与组 15 的平均值显著不同,所以它们被标为红色。

选择下拉栏中的其他选项进行其他比较。

检查模型假设

ANOVA 假设每个样本都是从正态分布的总体中抽取的。要使用方差分析,我们需要确保这个假设得到满足。

为了检验正态性,我们将创建一个 Q-Q 残差图。Q-Q 图绘制了数据的分位数与正态分布的分位数。

由于数据点沿着 Q-Q 图中的直对角线,数据集可能遵循正态分布。因此,数据满足方差分析的正态性假设。

结论

恭喜你!您刚刚学习了如何使用单向 ANOVA 来比较三个或更多独立组的平均值。无论你的数据有多好,如果你没有一个好的测试技术,你将无法从你的数据中提取有意义的见解。

使用 ANOVA,您将能够确定三组或更多组之间的平均值差异是偶然的,还是确实存在显著差异。最终,它会帮助你决定选择一个群体是否有益。

本文的源代码可以在这里找到:

**https://github.com/khuyentran1401/Data-science/blob/master/statistics/ANOVA_examples.ipynb **

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 T2 Twitter 上与我联系。

这个回购如果你想检查我写的所有文章的代码。在 Medium 上关注我,了解我的最新数据科学文章,例如:

**

https://towards data science . com/top-6-python-libraries-for-visualization-which-one-to-use-Fe 43381 CD 658

参考

"单向方差分析。"单向 ANOVA——介绍何时应该运行该测试以及测试假设| Laerd Statistics ,Statistics . Laerd . com/statistical-guides/One-Way-ANOVA-statistical-guide . PHP。**

Pandas 简介——用于数据操作和分析的 Python 库

原文:https://towardsdatascience.com/introduction-to-pandas-hands-on-tutorial-part-one-2e74f35ab166?source=collection_archive---------24-----------------------

实践教程—第 1 部分

本教程面向数据科学和/或 Python 编程的初学者。它侧重于使用 Python 中的 Pandas 库进行探索性数据分析、数据操作和数据过滤。

库纳尔·卡拉在 Unsplash 上拍摄的照片

如果你是一个经常处理数据的 Python 开发者,我肯定你听说过甚至使用过 Pandas 库。这是一个面向数据科学和/或 Python 编程领域初学者的实践教程。我坚信“边做边学”,因此我觉得实践指导是学习的最好方式。我不会用太多的理论来烦你,并确保本教程是中肯的。我的目标是为你探索无穷无尽的数据科学世界铺平道路。

所以,让我先简单介绍一下熊猫。 Pandas 是一个库,允许你处理表格数据、时间序列数据、矩阵数据等等。熊猫让我们的生活变得更轻松的几个很好的例子是:

  • 逗号分隔值(CSV)文件、JSON 文件等导入数据。
  • 填写数据集中缺失的值
  • 数据争论和操纵
  • 将多个数据集合并成一个数据集
  • 将我们的结果导出为逗号分隔值(CSV)文件、JSON 文件等。

说到这个图书馆能提供什么,可能性是无穷无尽的。所以事不宜迟,让我们开始第一个教程。我已经将本教程分解为易于遵循的步骤,最后我列出了一些活动,你可以在方便的时候做,以提高你的技能。

第一步——安装熊猫

首先,让我们从如何安装熊猫库开始。本教程我使用的是 Windows 10 PC,但是你可以自由选择使用任何操作系统(MacOS,Linux 等等)。我们有很多方法可以安置熊猫。我将亲自解释我是如何做的。但是如果你想用其他方式,这里有一套完整的安装熊猫的说明。

安装 Pandas 最简单的方法是通过 Anaconda 发行版,这是科学计算领域最流行的 Python 发行版。熊猫图书馆将作为发行的一部分。我目前有 Python 版本 3.8.5,但它应该可以完美地用于 Python 版本 3.5.3 和更高版本。

让我们确认我的声明,熊猫库是 Anaconda 发行版的一部分。如果您的 Anaconda 安装成功,那么您的 PC 上应该安装了一个名为 Anaconda Navigator 的应用程序。在 Anaconda Navigator 的闪屏页面上,应该有一个名为“CMD.exe Prompt”的应用。点击“发射”。

Anaconda 导航器启动页面

一旦你点击“发射”,一个终端就会打开。此终端可用于安装/卸载库,如 Pandas。

CMD.exe 提示

终端出现后,键入以下命令之一,然后按“Enter”键。

conda install pandaspip install pandas

熊猫已经安装好了!

你应该看到熊猫已经安装好了!

Anaconda 附带了集成开发环境 (IDE),比如已经安装的 Jupyter Notebook 。我将使用 Jupyter 笔记本来完成我的教程,但是你可以自由选择你喜欢的 IDE。

步骤 2 —设置 Jupyter 笔记本

现在,我们准备深入熊猫的世界。但首先我想向您展示如何设置 Jupyter 笔记本 IDE。如果你打算使用 Jupyter 笔记本,请跟随本教程。如果没有,可以跳到第 3 步。

打开“CMD.exe 提示符”,如步骤 1 所示。然后输入下面的命令并点击“回车”。

**jupyter notebook**

使用 CMD.exe 提示符打开 Jupyter 笔记本

或者,您可以在 Anaconda Navigator 启动器中搜索 Jupyter notebook 应用程序,并启动 Jupyter notebook。

点击 Jupyter 笔记本上的“启动”

您的浏览器上将打开一个页面,如下所示:

Jupyter 的启动页面

点击“新建”,选择“笔记本”下的“Python 3”

瞧啊。你应该有你自己的 Jupyter 笔记本!

重要的事情先来!我们把笔记本重新命名为“熊猫 _ 教程”之类的吧。你可以随意给它起任何名字。

现在我们可以开始编码了!万岁!

步骤 3—从熊猫的 CSV 文件中导入数据

如果你坚持到了这里,好事情很快就会到来,我的朋友!抓紧,准备发射!

让我们从非常重要的一步开始:在我们的 Jupyter 笔记本中输入熊猫

我们可以通过打字进口熊猫

**import pandas as pd**

使用熊猫的别名(如 pd)可以减少您在后续步骤中输入的工作量,尽管这是完全可选的。

进口熊猫

现在让我们下载一个 CSV 文件,我们将在本教程中使用。我将使用 Spotify 音乐分类的数据集。在 Kaggle 上注册/签到即可下载。我选择这个数据集的原因是,它有许多描述歌曲的“特征”或“属性”,我们可以用它们来获得一些有趣的见解。这个过程被称为探索性数据分析,在这个过程中,我们将尝试找出关于数据集的有意义的信息,例如:

  • 寻找前 K 首“最有活力/最没活力”的歌曲
  • 查找持续时间最短/最长的前 K 首歌曲
  • 寻找 K 首最适合跳舞/最不适合跳舞的歌曲

诸如此类。

我们可以使用以下代码导入该数据集:

**df = pd.read_csv(r“**<File Path>**\data.csv”)**

文件路径前的 r 不是输入错误,而是表示原始字符串的特殊字符。如果我们不指定它,我们可能会在 Windows 机器上得到一个“FileNotFoundError”。

Pandas 使用一种叫做 DataFrame 的数据结构来保存这些数据。DataFrame 允许我们存储“关系”或“表格”数据,并为我们提供了许多内置函数来操作数据。

我们可以只写下数据帧的名称来查看它,如下所示:

**df**

将 CSV 导入数据帧并查看

但通常,我们不想查看全部数据。我们只想先睹为快。这是你可以做到的。

**df.head() #**By default it shows the first 5 rows

我们还可以在 head()函数中指定行数,如下所示:

**df.head(10) #**It will show the first 10 rows

数据帧的前 5 行

如果我们想查看最后几行呢?

**df.tail() #**By default it shows the last 5 rows

我们还可以在 tail()函数中指定行数,如下所示:

**df.tail(10) #**It will show the last 10 rows

数据帧的最后 5 行

如果我们不想查看数据,而是想快速浏览整个数据框,比如列的数据类型、列中 Null/非 Null 值的数量等等,该怎么办?我们可以如下使用 df.info() 函数

**df.info()**

关于数据帧的信息

从上面的截图中,我们可以观察到 DataFrame 中有 16 列。我们也可以观察到有 2017 个数据点。我们还可以看到没有空值,这表明数据得到了很好的维护。我们还可以看到数据帧中所有列的数据类型。

如果我们只对列的数据类型感兴趣,我们可以使用 df.dtypes 来检查它

数据帧所有列的数据类型

通过这种方式,我们可以查看数据并提取关于数据的有意义的信息。如果这个数据集有空值,我们也必须处理那些丢失的值。对于教程 2,我计划使用一个包含空值的数据集,这样我就可以演示如何解决这个问题。

步骤 4——过滤数据帧中的数据

过滤是数据科学中经常使用的术语。它基本上意味着将数据帧分解成满足特定条件的子集。

在这个数据集中,我们可以使用诸如可跳性、持续时间等属性。要过滤出符合特定标准的前 K 首歌曲,如下所示:

十大“最不适合跳舞”的歌曲:

我们可以根据danceability列(默认为升序)对行进行排序,找到前 10 行并只提取song_title列的数据。这将给我们带来十大“最不适合跳舞”歌曲的song_title

df.sort_values('danceability')['song_title'].head(10) 

十大“最不适合跳舞”的歌曲

假设我们还想查看艺术家姓名,因为歌曲标题可能不是唯一的。我们可以通过在想要查看的列中添加artist来做到这一点,如下所示:

df.sort_values('danceability')[['song_title', 'artist']].head(10) 

十大“最不适合跳舞”的歌曲名和艺人名

最长的 10 首歌:

我们可以根据duration_ms列对行进行排序,找到最后 10 行(因为默认情况下这些值是按升序排列的),并提取song_title, artist, duration_ms列的数据,如下所示:

df.sort_values('duration_ms')[['song_title', 'artist', 'duration_ms']].tail(10)

持续时间最长的歌曲及其持续时间和艺术家姓名

如果我们想做一个更复杂的查询呢?

对于时长少于 400 秒的歌曲,找出前 10 首“最有活力”的歌曲:

这里我们将不得不应用两个过滤器。

第一个过滤器是:寻找少于 400 秒的歌曲

如果我们应用第一个滤波器,我们可以观察到 1925 首歌曲的持续时间小于 400000 毫秒(即 400 秒)。因此,在 2017 年的歌曲中,我们只需要查看 1925 年的歌曲进行下一次筛选。

df_filt = df[df['duration_ms'] < 400000] #Our first filter in action

现在我们将应用我们的第二个过滤器。我们将从过滤的数据帧(df_filt)中以能量的升序排列这些歌曲,并提取最后 10 个值。

df_filt2 = df_filt.sort_values('energy')[['song_title', 'artist', 'duration_ms']].tail(10)

持续时间少于 400000 毫秒(400 秒)的前 10 首“最有活力”的歌曲

我们已经得到了我们想要的结果!但是现在我们观察到这些值是按升序排列的。既然我们已经要求了前 10 个值,让我们通过在sort_values()函数中设置属性ascending=False来将它们转换成降序,以获得更好的可读性。就这样,我们的任务完成了!

ans = df_filt2.sort_values('energy', ascending=False)

最终答案

我们还可以在应用第二个过滤器时按降序排列行,这样效率会高得多。但是我想一步一步地解释这些概念,所以我选择这样做。

步骤 5—将数据导出为 CSV 格式

假设我们在一个数据帧上进行一些数据操作,并在一个数据帧中得到预期的结果。如果我们想将其导出为 CSV 格式,用于其他地方或作为备份存储,我们可以执行以下操作:

df_filtered = df.sort_values('duration_ms')[['song_title', 'artist', 'duration_ms']].tail(10)
df_filtered.to_csv(r'<File Path>\filtered_data.csv')

将 CSV 导出到本地

CSV 下载到本地

我们仅仅触及了使用这个库所能做的令人惊奇的事情的表面。俗话说“熟能生巧”,所以我会敦促你在收工前做以下活动!我知道你有这个能力!先别放弃!

提高技能的活动

如果你需要额外的练习,你可以尝试做以下活动:

  • 查找energy列的值大于 0.4 的歌曲,并显示song_title列的值。
  • 对于持续时间duration_ms值小于 300000 毫秒(300 秒)的歌曲,查找前 10 首“最快”的歌曲(tempo列值最高的歌曲)并显示song_title, artist列的值。
  • 查找artist列= Drake 且energy列的值大于 0.5 的歌曲,并显示song_title列的值。

Photo by 蔡 世宏 on Unsplash

包装

我知道你现在可能像上面的熊猫一样又累又困。但是我有一些好消息,我们已经完成了教程的第一部分。我计划再发布一篇关于熊猫的教程,其中我将介绍如何合并多个数据集,并且我还将使用 Matplotlib 来执行信息可视化,这是另一个充满乐趣的 Python 库。我希望你读的时候和我写的时候一样开心!

下次再见朋友们!

实用 Python 熊猫技巧-第 1 部分:导入和创建数据帧

原文:https://towardsdatascience.com/introduction-to-pandas-part-1-import-and-create-dataframe-e53326b6e2b1?source=collection_archive---------38-----------------------

导入各种数据文件,并使用列表和字典从头开始创建数据框架

Geran de Klerk 在 Unsplash 上拍摄的照片

本文是熊猫系列节目的第一部分。请继续关注更多关于这个主题的文章。

第 1 部分:导入并创建数据帧

第二部分:数据预览和子集化

第三部分:数据角力

介绍

毫无疑问 Pandas 是数据科学领域最流行的 Python 库之一。它的多功能性和功能性使它成为数据转换和探索的强大工具。熟悉熊猫已经成为数据科学专业人士的必备技能。

先决条件

**# Install pandas library**
!pip install pandas**# Import pandas library**
import pandas as pd

从现有数据源导入数据

导入一个 CSV 文件

df = pd.read_csv('file_name.csv')

从网站导入 CSV 文件

df = pd.read_csv('[https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'](https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'))

导入 Excel 文件

df = pd.read_excel(open('file_name.xlsx', 'rb'), sheet_name='sheet_name')

从 SQL 数据库导入数据:在我们编写从 SQL 数据库提取数据的查询之前,我们需要使用有效的凭证连接到数据库。Python 库,SQLAlchemy 让 Python 和 SQL 数据库之间的交互变得很容易。

import sqlalchemyconnection = sqlalchemy.create_engine('dialect+driver://username:password@host:port/database').connect()sql = 'CREATE TABLE df AS SELECT ...'
connection.execute(sql)output = pd.read_sql('SELECT * FROM df', con=connection)

从头开始创建数据框架

方法 1: 从字典列表中创建数据帧

data = [{'Salary': 30000, 'Exp': 1, 'Gender': 'M'},             
        {'Salary': 40000, 'Exp': 3, 'Gender': 'F'}]        
df = pd.DataFrame(data)

输出:

(作者创作)

方法 2: 从列表字典中创建数据帧

data= {'Salary': [30000, 40000, 50000, 85000, 75000],            
        'Exp': [1, 3, 5, 10, 25],          
        'Gender': ['M','F', 'M', 'F', 'M']} 
df = pd.DataFrame(data)

输出:

(作者创作)

方法 3 :使用 from_dict 创建数据帧。如果您想使用传递的字典的关键字作为结果数据帧的列名,请将 orient 设置为“列”。否则,如果键应该是行,则将 orient 设置为“index”。

data= {'Salary': [30000, 40000, 50000, 85000, 75000],            
        'Exp': [1, 3, 5, 10, 25],          
        'Gender': ['M','F', 'M', 'F', 'M']} 
df1 = pd.DataFrame.from_dict(data, orient = 'columns')
df2 = pd.DataFrame.from_dict(data, orient = 'index')

输出:

(由阿瑟创作)

方法 4: 从多个列表的列表中创建 DataFrame。我们可以分别使用“索引”和“列”选项来定义用户定义的索引和列名。

# pd.DataFrame([[Row 1], [Row 2], [Row 3],...])df = pd.DataFrame([[0, 2, 3], [0, 4, 1], [10, 20, 30]],                   index=['r1', 'r2', 'r3'], columns=['A', 'B', 'C'])

输出:

(作者创作)

感谢您的阅读!!!

如果你喜欢这篇文章,并且想请我喝杯咖啡,点击这里

您可以注册一个 会员 来解锁我的文章的全部访问权限,并且可以无限制地访问介质上的所有内容。如果你想在我发表新文章时收到电子邮件通知,请订阅。

实用 Python 熊猫技巧-第 2 部分:数据预览和子集化

原文:https://towardsdatascience.com/introduction-to-pandas-part-2-quick-data-exploration-582fc9b0de28?source=collection_archive---------40-----------------------

有用的熊猫函数和技巧来预览和子集化数据帧

照片由杰·曼特里Unsplash 上拍摄

这篇文章是熊猫系列的第二部分。请继续关注更多关于这个主题的文章。

第 1 部分:导入并创建数据帧

第二部分:数据预览和子集化

第三部分:数据角力

介绍

在任何数据科学项目的开始,我们总是希望尽快熟悉数据。查看前 n 行并计算基本信息,如列名、数据类型、分布、统计汇总,将有助于我们理解数据。一旦我们对数据有了初步的了解,最常见的数据清理步骤之一就是子集化。

在本文中,我将使用“supermarket _ sales—sheet 1 . CSV”(下载链接)作为数据源来介绍一些 Pandas 函数,这些函数允许我们进行快速数据探索和子集化。

先决条件

**# Install pandas library**
!pip install pandas**# Import pandas library**
import pandas as pd**# Import data source**
df = pd.read_csv('supermarket_sales - Sheet1.csv')

快速数据预览

头&尾:我们不用回顾整个数据集,只需要几行记录就能轻松消化信息。这两个函数分别返回 dataframe 的前 n 行和后 n 行。

**df.head(5)**
Out[65]: 
    Invoice ID Branch       City  ... gross margin percentage gross income Rating
0  750-67-8428      A     Yangon  ...                4.761905      26.1415    9.1
1  226-31-3081      C  Naypyitaw  ...                4.761905       3.8200    9.6
2  631-41-3108      A     Yangon  ...                4.761905      16.2155    7.4
3  123-19-1176      A     Yangon  ...                4.761905      23.2880    8.4
4  373-73-7910      A     Yangon  ...                4.761905      30.2085    5.3[5 rows x 17 columns]**df.tail(5)**
Out[66]: 
      Invoice ID Branch  ... gross income Rating
995  233-67-5758      C  ...       2.0175    6.2
996  303-96-2227      B  ...      48.6900    4.4
997  727-02-1313      A  ...       1.5920    7.7
998  347-56-2442      A  ...       3.2910    4.1
999  849-09-3807      A  ...      30.9190    6.6[5 rows x 17 columns]

技巧 1: 当我们想要预览一个巨大的 CSV 文件(> 10GB)时,我们可能不想等待很长时间来导入整个数据。有时,快速的数据片段对于确定数据文件及其数据结构中包含的信息非常有帮助。在这种情况下,我们可以使用read_csv中的skiprowsnrows选项来指定我们想要跳过和读取的行数,这可能会将导入时间从几个小时减少到几秒钟。

skiprows = 0
lenrow = 100
preview_df = pd.read_csv('supermarket_sales - Sheet1.csv', skiprows = skiprows, nrows = lenrow, header=0, engine='python')

列&信息:了解列名和数据类型对于初始检查非常重要。columnsinf函数可以输出列名、非空值的个数和每列的数据类型。

**df.columns** 
Index(['Invoice ID', 'Branch', 'City', 'Customer type', 'Gender',
       'Product line', 'Unit price', 'Quantity', 'Tax 5%', 'Total', 'Date',
       'Time', 'Payment', 'cogs', 'gross margin percentage', 'gross income',
       'Rating'],
      dtype='object')**df.info()**
Data columns (total 17 columns):
 #   Column                   Non-Null Count  Dtype  
---  ------                   --------------  -----  
 0   Invoice ID               1000 non-null   object 
 1   Branch                   1000 non-null   object 
 2   City                     1000 non-null   object 
 3   Customer type            1000 non-null   object 
 4   Gender                   1000 non-null   object 
 5   Product line             1000 non-null   object 
 6   Unit price               1000 non-null   float64
 7   Quantity                 1000 non-null   int64  
 8   Tax 5%                   1000 non-null   float64
 9   Total                    1000 non-null   float64
 10  Date                     1000 non-null   object 
 11  Time                     1000 non-null   object 
 12  Payment                  1000 non-null   object 
 13  cogs                     1000 non-null   float64
 14  gross margin percentage  1000 non-null   float64
 15  gross income             1000 non-null   float64
 16  Rating                   1000 non-null   float64
dtypes: float64(7), int64(1), object(9)
memory usage: 132.9+ KB

技巧 2: 您可能会注意到上面输出中的object数据类型。object可以包含整数、浮点、字符串等多种不同类型,统称为object。为了进一步检查给定列的数据类型,我们可以使用type来输出更多的细节。

在下面的示例中,“Salary”列包含整数值和字符串值。通过使用type,我们能够产生频率计数并基于数据类型查看子集。

(作者创作)

data= {'Salary': [30000, 40000, 50000, 85000, '75,000'],            
        'Exp': [1, 3, 5, 10, 25],          
        'Gender': ['M','F', 'M', 'F', 'M']} 
df_salary = pd.DataFrame(data)
**df_salary.info()**Out[74]:
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   Salary  5 non-null      object
 1   Exp     5 non-null      int64 
 2   Gender  5 non-null      object**df_salary.apply(lambda x: type(x['Salary']), axis = 1).value_counts()**Out[75]:
<class 'int'>    4
<class 'str'>    1
dtype: int64**df_salary[df_salary.apply(lambda x: type(x['Salary']), axis = 1)== str]**Out[80]: 
   Salary  Exp Gender
4  75,000   25      M

招数 3: 我上面提到过 value_counts 。它输出给定列的唯一值的计数。有时,我们需要制作两列的交叉表格。交叉表是一个方便的函数。默认情况下,它通过数据帧中的任意两列生成一个频率表。也可以传递一个聚合函数,比如sum。在下面的代码中,我们可以通过“产品线”和“城市”来计算总“数量”。

**df['City'].value_counts()**
Out[19]: 
Yangon       340
Mandalay     332
Naypyitaw    328
Name: City, dtype: int64**pd.crosstab(df['Product line'], df['City'])**
Out[22]: 
City                    Mandalay  Naypyitaw  Yangon
Product line                                       
Electronic accessories        55         55      60
Fashion accessories           62         65      51
Food and beverages            50         66      58
Health and beauty             53         52      47
Home and lifestyle            50         45      65
Sports and travel             62         45      59**pd.crosstab(df['Product line'], df['City'], values = df['Quantity'], aggfunc= 'sum')** Out[98]: 
City                    Mandalay  Naypyitaw  Yangon
Product line                                       
Electronic accessories       316        333     322
Fashion accessories          297        342     263
Food and beverages           270        369     313
Health and beauty            320        277     257
Home and lifestyle           295        245     371
Sports and travel            322        265     333

描述:该函数输出一个描述性的统计摘要,包括观察值、平均值、标准偏差、最小值、最大值和百分位数。

**df.describe()**
Out[18]: 
        Unit price     Quantity  ...  gross income      Rating
count  1000.000000  1000.000000  ...   1000.000000  1000.00000
mean     55.672130     5.510000  ...     15.379369     6.97270
std      26.494628     2.923431  ...     11.708825     1.71858
min      10.080000     1.000000  ...      0.508500     4.00000
25%      32.875000     3.000000  ...      5.924875     5.50000
50%      55.230000     5.000000  ...     12.088000     7.00000
75%      77.935000     8.000000  ...     22.445250     8.50000
max      99.960000    10.000000  ...     49.650000    10.00000[8 rows x 8 columns]

招数四:描述有帮助,但是熊猫 _ 侧写。ProfileReport 更好。Python 库,熊猫 _ 剖析。ProfileReport 允许我们生成全面的数据探索报告。类似于 describe,pandas_profiling。ProfileReport 将产生每一列的基本信息和描述性统计摘要。

**# Install the library**
!pip install pandas-profiling**# Import the library**
import pandas_profilingprofile = pandas_profiling.ProfileReport(df, title = "Data Exploration")
profile.to_file(output_file='Data Profile Output.html')

它还可以生成每一列的快速直方图,并允许我们创建任意两个数字列的散点图。此外,它还包括不同类型的列相关性和缺失值的计数。所有这些有用的信息都可以用几行代码生成。

使用此功能的另一个好处是,我们可以将报告保存为 web 格式,然后发送给其他人查看。

(作者创作)

(作者创作)

(作者创作)

子集数据框架

对于本节,让我们创建另一个示例数据帧。在该数据帧中,它包含['r1 ',' r2 ',' r3']的索引和['A ',' B ',' C']的列。

# Create a dataframe
df2 = pd.DataFrame([[0, 2, 3], [0, 4, 1], [10, 20, 30]],                 index=['r1', 'r2', 'r3'], columns=['A', 'B', 'C'])

(作者创作)

使用括号进行行选择

df[开始行:结束行]: 这将给连续数据行的子集。例如,df2[0:3]产生数据帧中的第一行到第三行。

招数五: df2[0]不提取第一行。相反,这会给我们一个名为“0”的列,这在我们的数据列['A ',' B ',' C']中是不可用的。相反,我们应该使用 df[0:1]来获取第一行。

df[condition(boolean)]:这将基于指定的条件创建数据帧的子集。例如,df2[df2[' C ']>10]生成列“C”大于 10 的行。df2[df2[' C ']≥3&df2[' A ']>3]生成列“C”大于或等于 3 且列“A”大于 3 的行。

招数六:在指定多个条件时,我们也可以在布尔条件内部使用apply,更加灵活。例如,axis = 1允许我们以行的方式实现分析。我们可以通过boolregular expression 来输出真/假。

df2[df2.apply(lambda x: x['C']>=3 & x['A'] > 3, axis = 1)]
df[df.apply(lambda x: bool(re.findall('beauty', x['Product line'])) & (x['Gender'] == 'Female'), axis = 1)]

招数 7: 我们可以用query来指定一个布尔表达式。一个优点是我们不需要多次显式地写数据帧名称。

# df[df['Gender']=='Female']
df.query('Gender == "Female"') # df[df['Quantity']> 7]
df.query('Quantity > 7')

使用 iloc 选择行

df . iloc[所选行]:]:iloc允许我们根据行号提取一个子集。例如:df2.iloc[0:10,:]将生成前 10 行,而 df2.iloc[[0,2,5],:]将生成包含第一、第三和第六行的子集。方括号内的:意味着我们将保留所有的列。

使用 loc 进行行选择

df.loc[Selected Index,:】 : loc允许根据索引提取子集。例如,df2.loc['r1 ',:]将生成一个带有“index = 'r1 '”的子集。df2.loc[['r1 ',' r2'],:]将生成一个带有“index = 'r1 '和' r2 '”的子集。

使用双括号选择列

df[[选择的列]]: 使用一个双括号,我们可以在一个数据帧中选择单个或多个列。例如,df[['单价','数量']]将提取数据帧中的'单价'和'数量'列。

招数八:单支架 vs 双支架。我们可以使用单个括号来提取单个列。但是输出将被存储为一个系列,而一个双括号将给我们一个数据帧

test1 = df[['Quantity']]type(test1)
Out[176]: pandas.core.frame.DataFrametest2 = df['Quantity']type(test2)
Out[178]: pandas.core.series.Series

df.iloc[:,Selected Columns]vs df . loc[:,Selected Columns]:ilocloc都可以从数据帧中提取列的子集。区别在于iloc基于列号,而loc使用实际的列名。例如,df2.iloc[:,0]将提取第一列而不提及列名,而 df2.loc[:,' A']将从数据帧中提取列“A”。

感谢您的阅读!!!

如果你喜欢这篇文章,并且想请我喝杯咖啡,点击这里

您可以注册一个 会员 来解锁我的文章的全部访问权限,并且可以无限制地访问介质上的所有内容。如果你想在我发表新文章时收到电子邮件通知,请订阅。

实用的 Python 熊猫把戏-第 3 部分:数据争论

原文:https://towardsdatascience.com/introduction-to-pandas-part-3-data-wrangling-b490f8e47ca2?source=collection_archive---------26-----------------------

任何统计分析和机器学习模型都可以和你输入的数据质量一样好

Unsplash 上拍摄的照片

这篇文章是熊猫系列的第三部分。请继续关注更多关于这个主题的文章。

第 1 部分:导入并创建数据帧

第二部分:数据预览和子集化

第三部分:数据角力

介绍

在这篇文章中,我将介绍 Pandas 清理和转换数据帧的函数。我认为这是任何数据科学项目中最重要的步骤之一。 任何统计分析和机器学习模型都可以和你输入其中的数据质量一样好。

先决条件

**# Install pandas library**
!pip install pandas**# Import libraries**
import pandas as pd
import numpy as np

缺少值

先说和熊猫处理缺失值。我将使用下面的 dataframe 作为数据源。

data = {'emp_id': [1, 1, 2, 2],
        'emp_name': ['Jane Dow', 'Jane Dow', 'Thomas Daley', 'Thomas Daley'],
        'gender': [np.nan, 'M', 'F', 'F'],
        'year': [2019, 2020, 2019, 2020],
        'compensation': [53000, np.nan, 53000, '$56,000']}df2  = pd.DataFrame(data)
df2Out[107]: 
   emp_id      emp_name gender  year compensation
0       1      Jane Dow    NaN  2019        53000
1       1      Jane Dow      M  2020          NaN
2       2  Thomas Daley      F  2019        53000
3       2  Thomas Daley      F  2020      $56,000

is null()&not null():isnull()允许我们根据指定的列显示缺少值的行,而notnull()将返回没有缺少值的行。

**df2[df2['compensation'].isnull()]**
Out[108]: 
   emp_id  emp_name gender  year compensation
1       1  Jane Dow      M  2020          NaN**df2[df2['compensation'].notnull()]**
Out[109]: 
   emp_id      emp_name gender  year compensation
0       1      Jane Dow    NaN  2019        53000
2       2  Thomas Daley      F  2019        53000
3       2  Thomas Daley      F  2020      $56,000

在我们检查了丢失的数据之后,我们可以删除它们或者用适当的值填充丢失的单元格。(关于缺失数据可以查看我的另一篇文章】。)

在此数据框架中,我们看到“性别”和“薪酬”列中缺少值。我们可以用每个员工的非缺失性别值来填充缺失的性别,因为性别不会随时间而改变。此外,人力资源部门告诉我们,薪酬缺失意味着该员工已在当年离开公司。我们应该用 0 代替缺失的补偿。

fillna()允许我们用任何值替换丢失的值。在这种情况下,我们用值 0 替换丢失的补偿。我们可以将method = 'backfill''ffill'groupby()一起使用,用给定员工的上一次或下一次有效观察来填充缺失的性别。

**df2['compensation'].fillna(0, inplace = True)**df2['gender'] = df2.groupby('emp_id')['gender'].**fillna(method = 'backfill')**df2['gender'] = df2.groupby('emp_id')['gender'].**fillna(method = 'ffill')**print(df2)
   emp_id      emp_name gender  year compensation
0       1      Jane Dow      **M**  2019        53000
1       1      Jane Dow      M  2020           ** 0**
2       2  Thomas Daley      F  2019        53000
3       2  Thomas Daley      F  2020      $56,000

字符串操作

str.split(): str.split()允许我们将给定列中的文本拆分成多列。在下面的代码中,使用选项expand = True将“emp_name”列拆分为“first_name”和“last_name”列。默认情况下,列中的文本由空白分割,但是您可以使用选项pat = '<str>'指定分隔符。

df2[['first_name', 'last_name']] = df2['emp_name'].str.split(expand = True)
print(df2)

(作者创作)

str.replace & re():字符串值包含字符,如“$”和“,”。

**df2.apply(lambda x: type(x['compensation']), axis = 1).value_counts()**Out[118]: 
<class 'int'>    3
<class 'str'>    1
dtype: int64 **df2[df2.apply(lambda x: type(x['compensation']), axis = 1)== str]**

(作者创作)

很容易使用str.replace()来删除“$”和“,”。但是当我们这样做时,我们注意到整数值将被替换为np.nan,因为str.replace()不能处理整数值。

# Incorrect Method 
**df2['compensation'].str.replace('\$|,', '')**Out[124]: 
0      NaN
1      NaN
2      NaN
3    56000
Name: compensation, dtype: object

技巧 1: 为了正确地清理混合了字符串和数值的列,我们需要首先使用astype()将列中的值转换为字符串值,然后根据需要使用str.replace()re.sub()替换相关的字符串值。最后,我们将列转换回数值。

# Method 1: Using str.replace() with astype()
df2['compensation'].astype(str).str.replace('\$|,', '').astype(int)# Method 2: Using apply with re.sub()
df2['compensation'] = df2.apply(lambda x: re.sub('\$|,', '', str(x['compensation'])), axis = 1).astype(int)

窗口功能

窗口功能在称为窗口框架的一组行上实现。窗口框架是基于一列或多列的同一组中的所有行。当一个窗口函数被实现时,一个新的列将被产生,并且输出将具有与原始数据集相同数量的行

创建行号为的新列

df['new_column_name'] = df.groupby('{column name}').cumcount()+1

在组内创建计数/最大值/最小值/平均值/总和

在熊猫中,我们经常使用带窗口函数的变换,比如,count,max,min,avg,sum。

df.groupby('gender')['salary'].transform('count')
df.groupby('gender')['salary'].transform('max')
df.groupby('gender')['salary'].transform('min')
df.groupby('gender')['salary'].transform('mean')
df.groupby('gender')['salary'].transform('sum')

在组内创建运行总和

df.groupby('gender')['salary'].transform('cumsum')

在组内创建百分位数

# create median 
df.groupby('gender')['salary'].transform(lambda x: x.quantile(0.5))

在组内创建滞后/领先

# create lag variable
df.groupby('gender')['salary'].transform(lambda x: x.shift(1)) 
# create lead variable
df.groupby('gender')['salary'].transform(lambda x: x.shift(-1))

创建组内排名

df.groupby('gender')['salary'].rank('dense', ascending = False)

聚合函数

集合函数的实现方式与窗口函数相同。但是结果会更紧凑。最终输出中的观察值数量将等于不同组的数量(即分组变量中的唯一值)。

折叠一个组中具有计数/最大值/最小值/平均值/总和的行

在 Pandas 中,有许多方法可以实现聚合函数。我在下面的代码片段中包含了 3 种不同的方法。

  • 使用 groupby 将聚合函数作为默认函数运行
  • 使用应用运行内置聚合函数或带有 groupby 的用户自定义函数
  • 使用 agg 更灵活地运行内置聚合函数或用户定义函数,例如命名新列和创建多个新列
df.groupby('gender')['salary'].mean().reset_index()
df.groupby('gender')['salary'].min().reset_index()
df.groupby('gender')['salary'].max().reset_index()
df.groupby('gender')['salary'].sum().reset_index()df.groupby('gender').apply(lambda x: x['salary'].mean()).reset_index()df.groupby('gender').agg(count = pd.NamedAgg('salary', 'mean')).reset_index()

在组内创建百分位数

df.groupby(‘gender’)[‘salary’].quantile(0.9).reset_index()

你可以在本文中查看更多关于 窗口函数&聚合函数 的内容。

招数二:应用自定义函数apply函数让我们有更大的灵活性和可控性来创建自定义函数。在下面的例子中,我将使用“supermarket _ sales—sheet 1 . CSV”(下载链接)作为数据源。我们将根据“评级”列中的值创建一个新的评级类别列。

# Import data source
df = pd.read_csv('supermarket_sales - Sheet1.csv')def **rating_category**(rating):
    if rating >= 4 and rating <6:
        return 'Low'
    elif rating >= 6 and rating <8:
        return 'Mid'
    else:
        return 'High'df['rating_cat'] = df.apply(lambda x: **rating_category**(x['Rating']), axis = 1)

招数三:使用 tqdm 显示进度条——处理大数据集时,运行apply函数需要一段时间。如果我们知道工作状态以及我们预计任务完成的时间,那就太好了。Python 库tqdm与熊猫无缝协作。你只需要把apply换成progress_apply,其他都不变。

from tqdm import tqdm
tqdm.pandas()
df.progress_apply(lambda x: rating_category(x['Rating']), axis = 1)**100%|██████████| 1000/1000 [00:00<00:00, 104413.84it/s]**

技巧 4:使用 Swifter 加速 —能够充分利用硬件能力来加速运行时间对于数据科学任务来说非常重要。如果决策者希望在短时间内看到结果,您的分析可能对他们没有帮助,但是您的程序需要几周或几个月才能运行。

Python 库[swifter](https://medium.com/@jmcarpenter2/swiftapply-automatically-efficient-pandas-apply-operations-50e1058909f9)可以有效地利用硬件能力,以最快的方式将任何函数应用于 Pandas 数据帧或系列对象。语法很简单,你只需要在apply函数前加上swifter

import swifter
df.swifter.apply(lambda x: rating_category(x['Rating']), axis = 1)

连接多个数据框架

组合行

append() & concat(): 我们可以使用append()concat()按行方式组合两个数据帧,并产生相同的输出。我们可以使用reset_index(drop=True)来重置组合数据帧中的索引。

df3 = pd.DataFrame({'emp_id': 3, 'emp_name': 'Jason Zandi', 'gender': 'M', 'year': 2020, 'compensation': 60000}, index = [0])**df2.append(df3).reset_index(drop=True)
pd.concat([df2, df3]).reset_index(drop=True)**Out[182]: 
   emp_id      emp_name gender  year compensation
0       1      Jane Dow    NaN  2019        53000
1       1      Jane Dow      M  2020          NaN
2       2  Thomas Daley      F  2019        53000
3       2  Thomas Daley      F  2020      $56,000
4       3   Jason Zandi      M  2020        60000

合并列

join()&merge():join()merge()都可以按列的方式组合两个数据帧。区别在于 **join()** 是基于索引,而 **merge()** 是基于两个数据帧的公共列。在下面的示例中,当使用基于索引的 join()组合 df2 和 df4 时,我们有一个匹配索引为[0]的行。当基于列“emp_id”使用 merge()组合 df2 和 d5 时,我们实现了一个典型的左连接操作。

df4 = pd.DataFrame({'test': 300}, index = [0]) 
df4
Out[190]: 
   test
0   300df5 = pd.DataFrame({'emp_id': [1, 2], 'title': ['Engineer', 'Analyst']})
df5
Out[192]: 
   emp_id     title
0       1  Engineer
1       2   Analyst **df2.join(df4)**
Out[188]: 
   emp_id      emp_name gender  year compensation   test
0       1      Jane Dow    NaN  2019        53000  300.0
1       1      Jane Dow      M  2020          NaN    NaN
2       2  Thomas Daley      F  2019        53000    NaN
3       2  Thomas Daley      F  2020      $56,000    NaN**df2.merge(df5, on = 'emp_id', how = 'right')**
Out[189]: 
   emp_id      emp_name gender  year compensation     title
0       1      Jane Dow    NaN  2019        53000  Engineer
1       1      Jane Dow      M  2020          NaN  Engineer
2       2  Thomas Daley      F  2019        53000   Analyst
3       2  Thomas Daley      F  2020      $56,000   Analyst

重新格式化数据帧

将数据帧从长转换为宽

pivot()pivot_table()都会生成一个(宽)表,汇总来自一个更大(长)表的数据。不同的是pivot_table()还可以合并聚合函数,比如 sum、average、max、min 和 first。在下面的示例中,我们尝试基于“year”列创建单独的薪酬列“2019”和“2020”。

df2
Out[200]: 
   emp_id      emp_name gender  year compensation
0       1      Jane Dow      M  2019        53000
1       1      Jane Dow      M  2020            0
2       2  Thomas Daley      F  2019        53000
3       2  Thomas Daley      F  2020      $56,000**df_wide = df2.pivot(index = ['emp_id', 'emp_name', 'gender'], columns = ['year'], values = 'compensation').reset_index()**
print(df_wide)
year  emp_id      emp_name gender   2019     2020
0          1      Jane Dow      M  53000        0
1          2  Thomas Daley      F  53000  $56,000**df_wide2 = df2.pivot_table(index = ['emp_id', 'emp_name', 'gender'], columns = ['year'], values = 'compensation', aggfunc = 'first').reset_index()**
print(df_wide2)
year  emp_id      emp_name gender   2019     2020
0          1      Jane Dow      M  53000        0
1          2  Thomas Daley      F  53000  $56,000

将数据帧从宽转换为长

melt()允许我们将数据帧格式从宽改为长。这与创建数据透视表相反。在下面的示例中,我们希望将薪酬列“2019”和“2020”合并为一列,并创建一个新的“年份”列。

**df_long = df_wide.melt(id_vars= ['emp_id', 'emp_name', 'gender'], var_name= 'year', value_vars= [2019, 2020], value_name="Compensation")**
print(df_long)
   emp_id      emp_name gender  year Compensation
0       1      Jane Dow      M  2019        53000
1       2  Thomas Daley      F  2019        53000
2       1      Jane Dow      M  2020            0
3       2  Thomas Daley      F  2020      $56,000

感谢您的阅读!!!

如果你喜欢这篇文章,并且想请我喝杯咖啡,请点击这里

您可以注册一个 会员 来解锁我的文章的全部访问权限,并且可以无限制地访问介质上的所有内容。如果你想在我发表新文章时收到电子邮件通知,请 订阅

使用 PAMI 的空气污染分析

原文:https://towardsdatascience.com/introduction-to-periodic-frequent-pattern-mining-using-pami-python-library-49a6e9dbc2e5?source=collection_archive---------20-----------------------

通过周期-频繁模式识别日本的污染热点

信息和通信技术领域的技术进步使各组织能够收集大数据。这些数据库中隐藏着能够使最终用户实现社会经济发展的有用信息。模式挖掘领域的出现是为了发现大数据中可能存在的有趣模式(或项目集)。本教程涵盖以下主题:

  • 什么是周期性频繁模式?
  • 如何在时态大数据中发现周期-频繁模式?
  • 通过使用 PAMI 软件包中可用的算法寻找周期-频繁模式。
  • 周期-频繁模式挖掘的优点和局限性是什么?

什么是周期-频繁模式?

周期频繁模式[1]是存在于时态数据库中的一类重要的规则。在现实世界的应用程序中找到这些模式具有很高的价值,因为它们代表了数据库可以预测的东西。周期-频繁模式挖掘的目标是发现数据库中定期出现的所有频繁模式。

图一。确定日本人们经常暴露于有害水平的 PM2.5 的地点[图片由作者提供]

例如:空气污染是日本许多心血管疾病的主要原因。日本平均每年有 4.26 万人因污染而死亡。为了解决这个问题,日本环境省建立了一个名为 SORAMAME (大气环境区域观测系统:AEROS) [3]的全国性传感器网络来监测污染。图 1a 显示了这些传感器在日本的空间位置。该系统每小时生成的空气污染物的原始数据(见图 1b)可以表示为时间数据库(见图 1c)。对该数据库的周期性-频繁模式挖掘(见图 1c)为环境学家和决策者提供了关于人们经常暴露于有害空气污染水平的区域的有用信息(见图 1d & 1e)。

表 1:一个样本时态数据库[图片由作者提供]

{S1,S2,S3,S4,S5,S6} 为一组空气污染测量传感器。表 1 显示了由这些传感器产生的假设的空气污染时间数据库。该数据库包含 12 个事务。该数据库的初始时间戳,即 ts_initial=0 。该数据库的最终时间戳,即 ts_final=15 。该数据库中的第一个事务提供了传感器 S1、S2、S5 记录了 PM2.5 的危险水平的信息。该数据库中的其他事务可以用类似的方式解释。传感器的集合, S1S2 ,即 {S1,S2} ,称为一个模式(或一个项集)。在表 1 中,这种模式出现在时间戳 1、3、6、8、9、12 和 14。因此,{S1,S2}的支持度(或频率)为 7。如果用户指定的最小支持度,记为 minSup 为 5,则 {S1,S2} 称为频繁模式。此模式的周期为:1 (=1-ts_initial)、2(= 3–1)、3(= 6–3)、2(= 8–6)、1(= 9–8)、3(= 12–9)、2(= 14–12)、1 (=ts_final-14)。该模式的最大周期被认为是其周期。于是, {S1,S2}周期性,即 per({S1,S2})=max(1,2,3,2,1,3,2,1) = 3 。这意味着传感器 S1S2 至少每 3 小时同时记录一次 PM2.5 的危险水平。如果用户指定的最大周期 ( maxPer )为 3,那么频繁模式 {S1,S2} 就称为周期-频繁模式。这种模式表示如下:

{S1,S2 }[支持度=7,周期=3]

如何在时态大数据中发现周期-频繁模式?

项目集格中项目的空间表示周期频繁模式挖掘的搜索空间。因此,周期-频繁模式挖掘的搜索空间是 2^n-1 ,其中 n 表示数据库中的项目总数。挖掘算法通过使用先验/反单调/向下闭包性质来减少这个巨大的搜索空间。这个性质表示"周期-频繁模式的所有非空子集也是周期-频繁模式"这一特性使得模式挖掘在现实世界的大型数据库中变得可行。发现周期性频繁模式的算法有:

  • PFP-增长
  • PFP-增长++版
  • PS-增长和
  • PFP-ECLAT。

什么是 PAMI?怎么安装?如何实现在 PAMI 可用的周期-频繁模式挖掘算法?

PAMI 代表模式挖掘。它是一个 Python 库,包含几个模式挖掘算法。这个库是在 GPL V3 许可下提供的。用户只需执行以下命令即可安装该库:

pip install pami

PAMI 库的好处是数据库中的条目可以是整数或字符串。为了便于说明,我们使用空气污染数据库作为测试案例。点击这里下载数据库。用户可以尝试使用其他数据集。但是,请记住,时态数据库必须以以下格式存在:

timestamp<sep>item1<sep>item2<sep>...<sep>itemN

PAMI 算法使用的默认分隔符是制表符(默认)。然而,用户可以使用其他分隔符,如逗号和空格。如上所述,PAMI 包含几个算法来寻找周期频繁模式。然而,为了简洁起见,我们在本教程中使用 PS-growth 算法[4]。

PS-growth 算法的逐步含义如下:

步骤 1:从 PAMI 库中导入 PS-growth 算法

from PAMI.periodicFrequentPattern.basic import PSGrowth as alg

步骤 2:通过提供 data、minSup 和 maxPer 参数来初始化和执行挖掘算法。请注意,数据可以是 HTTP 链接、文件或数据帧。点击此处下载数据集。

URL="https://www.u-aizu.ac.jp/~udayrage/datasets/temporalDatabases/temporal_pol_pm2_16.csv"
obj = alg.PSGrowth(iFile=URL,minSup=100,maxPer=24)   #initialization
obj.startMine()                                      #execution 

步骤 3:将模式存储在文件中

obj.savePatterns('patterns.txt')

第四步:印刷图案

df = obj.getPatternsAsDataFrame()
df

步骤 5:计算模式、内存和运行时间的数量

print(len(df))
print(obj.getMemoryRSS())
print(obj.getRuntime())

周期-频繁模式挖掘算法的优缺点是什么?

优点:

  • 向下封闭性使得挖掘算法可以部署在大规模数据库上
  • 几个用户指定的(或超级)参数

缺点:

  • 仅查找完全/完美出现的周期模式。因此,丢失了部分周期性出现的周期性模式。
  • 数据库中可能生成了太多模式。

结论

在这篇博客中,我们介绍了可能存在于时态数据库中的周期-频繁模式模型。这些模式的重要性也通过一个例子得到了证明。最后,我们描述了如何利用我们的 PAMI Python 库来发现空气污染数据中的隐藏模式。

参考文献:

[1] Syed Khairuzzaman Tanbeer,Chowdhury Farhan Ahmed,Byeong-Soo Jeong,Young-Koo Lee:在事务数据库中发现周期-频繁模式。pak DD 2009:242–253

[2]Statista:https://www . Statista . com/statistics/935022/number-deaths-air-pollution-Japan/#:~:text = In % 202019% 2C % 20 the % 20 number % 20of,attribute % 20 to % 20 air % 20 pollution % 20 exposure

[3]SORAMAME:【https://soramame.env.go.jp/ (2021 年 11 月 14 日访问)

[4] R. Uday Kiran,Alampally Anirudh,Chennupati Saideep,Masashi Toyoda,P. Krishna Reddy,Masaru Kitsuregawa:使用周期摘要在时态数据库中寻找周期-频繁模式。《数据科学与模式识别》第 3 卷第 2 期第 24–46 页(2019 年)

Postgresql 简介:第 1 部分

原文:https://towardsdatascience.com/introduction-to-postgresql-part-1-6ca9f25b02e1?source=collection_archive---------14-----------------------

让我们从头开始

詹姆斯·哈蒙德在 Unsplash 拍摄的照片

不久前,我写了一篇比较 MySQL 和 Postgresql 的文章。虽然这只是一个概述,但我对 Postgres 产生了兴趣。现在,这不是我第一次听说 Postgresql,我以前也尝试过使用它。然而,自从我接触它已经有一段时间了,我想现在是时候重新开始做一个教程了。首先,我们需要讨论 Postgresql 是什么,然后如何安装它,最后如何启动它。我使用 Ubuntu 命令行进行安装和配置。

关于 Postgresql 的更多信息

Postgresql 是一个开源的数据库管理系统。它既强大又符合 ACID(原子性、一致性、隔离性、持久性)。Postgres 是一个对象关系数据库管理系统(ORDBMS),这意味着它不同于 MySQL 等数据库管理系统。ORDBMS 结合了关系数据库管理系统和面向对象编程的特点。第一个主要区别在于数据类型。

Postgresql 支持所有常规 sql 数据类型,但也添加了典型 SQL RDBMS 不支持的各种类型。例如,Postgres 可以同时支持 JSON 和 XML 数据类型。它还可以支持数组、复合或范围等类型。Postgresql 甚至可以支持网络地址数据类型。这些数据类型不一定符合 ACID,因为它们不是原子的,但是在编码时允许更大范围的灵活性。

Postgresql 还体现了面向对象的能力。能够声明和使用函数就是这样一种能力。多态性也是 Postgres 可以容纳的一个因素。与此同时,继承也是 Postgres 的一项功能。使用 Postgresql 甚至可以进行数据封装和抽象。

为了帮助减少锁的机会,Postgres 实现了多版本并发控制(MVCC)。提醒一下,并发是指一次支持多个请求/操作的能力。它与并行不同,因为并行指的是同时运行两个或更多的请求/操作。MVCC 的一个主要目标是确保作者可以在不妨碍读者的情况下工作,反之亦然。MVCC 允许同一记录的多个版本,这样,即使正在进行更改,多个用户也可以访问该记录。在这种控制方法中,在写入数据库的用户提交更改之前,无论是添加、更新还是删除更改,都不会显示给正在读取记录的用户。

现在我们对 Postgresql 有了更多的了解,让我们来简单了解一下 Postgres 是为谁准备的,什么时候是使用 Postgresql 的好时机。

Postgresql 是我的正确选择吗?

在选择您的数据库管理系统时,没有人比您更了解您的项目或项目的需求。然而,有几个很好的理由说明 Postgresql 为什么是一个很好的选择。

第一个原因是有多种数据类型可以使用。不仅是特定于 SQL 的,还有其他类型,如文档类型、几何类型,甚至是定制类型。这为您的数据库提供了更大的灵活性。

在选择数据库管理时,数据的完整性是另一个关键的考虑因素。Postgresql 通过各种可供选择的约束和锁来确保其数据。Postgres 也是 ACID 兼容的。除了完整性,Postgresql 还强调性能。无论是通过高级索引、实时(JIT)表达式编译、复杂的查询优化器,甚至是表分区,性能和可靠性都使 Postgres 成为编码人员技能的重要补充。

除了可靠性,您还需要考虑您可能需要什么类型的安全性。Postgresql 既有各种类型的身份验证,也有多因素身份验证。甚至对列和行级别都有安全性。但是在可靠性方面,你需要知道你可以恢复。因此,Postgres 也有灾难恢复计划。能够实施恢复计划,如预写日志(WAL)、不同类型的复制,甚至时间点恢复(PITR)。

就增长而言,Postgresql 有各种各样的可扩展特性。例如,因为它实现了一些面向对象的编程特性,所以可以实现函数和继承,以及多态。您还可以添加 PostGIS 等功能。Postgres 还支持 SQL 和 JSON 路径表达式。您甚至可以定制表的存储接口。最后一点,Postgresql 支持国际字符集,以及不区分重音的排序规则,并且可以实现全文搜索。

安装 Postgresql

是时候安装 Postgres 了。提醒一下,我是用 Ubuntu 命令行安装的。

所以首先,我们需要更新我们的 apt-get,以防有我们目前没有安装的软件包更新。

sudo apt-get update

一旦运行完毕,我们现在就可以安装 Postgresql 了。我们将安装“postgresql”包和“postgresql-contrib”。回想一下,这可以在一行中完成。“contrib”包是可选的,只包含一些附加功能。然而,该功能的测试覆盖范围不如常规的“postgresql”包。如果您担心安装所需的空间,只需将“contrib”包从您的安装中去掉。

sudo apt-get install postgresql postgresql-contrib

现在我们已经安装了包,我们准备开始设置我们的数据库。

设置 Postgresql

安装 Postgres 后,为了能够开始创建我们的数据库,我们需要确保它已经启动并运行。我们可以使用以下命令来检查服务的状态:

sudo service postgresql status

检查 PostgreSQL 服务的状态。

在我的例子中,看起来服务需要启动。我们可以用下面的命令来实现:

sudo service postgresql start

现在,我们再次运行状态并检查结果:

sudo service postgresql status

PostgreSQL 服务已启动。

如您所见,Postgresql 现在已经启动并运行了。现在,我们必须做的就是启动命令行界面。为此,我们使用以下代码行:

sudo -u postgres psql

PostgreSQL 命令行界面。

我们的最后一步是创建数据库,供下一部分使用。对于我的数据库,我将称它为“Recipes ”,因为我为这个例子创建了一个 recipe 数据库,但是您可以随意命名它:

CREATE DATABASE Recipes;

创作回应。

现在,要查看我们的数据库是否已创建,请使用以下代码(反斜杠 l):

\I

列出所有数据库。配方数据库已确认创建。

结论

Postgresql 是一个开源的对象关系数据库管理系统(ORDBMS)。它是标准 SQL 和面向对象编程特性(如继承和多态)的有力结合。除了典型的 SQL 类型之外,Postgres 还支持各种数据类型,比如几何类型、文档类型(比如 JSON)、网络地址类型,甚至是定制的数据类型。Postgresql 还实现了 MVCC(多版本并发控制),并且是 ACID 兼容的。Postgres 的主要目标是保持完整性和可靠性。为了更加可靠,Postgresql 提供了不同的安全性、身份验证和灾难恢复选项。在选择 DBMS 时,Postgresql 的受欢迎程度和社区支持使它成为编码人员的资产。

在本系列中,我们将通过一个示例数据库来学习如何使用 Postgresql。我已经为我的表画出了图表,但是您可以使用任何您喜欢的数据库名称或表。这只是为了娱乐和教育。在这一部分中,我们主要学习了更多关于 Postgresql 的知识,我们安装并准备了它,并且创建了我们的数据库。在确认创建成功之后,我们就可以开始创建表了。但是我将在下一部分处理这个问题。所以,下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想看完介质上的所有文章?成为中等 成员 今天!

查看我最近的文章:

[## SQLite vs TinyDB

towardsdatascience.com](/sqlite-vs-tinydb-7d6a6a42cb97) https://python.plainenglish.io/python-virtual-environments-what-you-need-to-know-95487982c586 https://python.plainenglish.io/tinydb-b646e3270fd7 https://python.plainenglish.io/python-database-dumping-9a8658994e5a [## 学习图表 QL

towardsdatascience.com](/learning-graphql-4e913f12640d)

参考资料:

https://www.postgresql.org/about/ https://www.postgresql.org/docs/9.5/datatype.html https://www.postgresql.org/docs/7.1/mvcc.html#MVCC-INTRO https://www.postgresql.org/docs/9.0/sql-createdatabase.html https://vladmihalcea.com/how-does-mvcc-multi-version-concurrency-control-work/

Postgresql 简介:第 2 部分

原文:https://towardsdatascience.com/introduction-to-postgresql-part-2-c25c346925d?source=collection_archive---------40-----------------------

让我们开始这个派对吧

Geran de Klerk 在 Unsplash 上拍摄的照片

在第 1 部分中,我们讨论了什么是 Postgresql,它的预期用途,以及如何安装它。一旦安装了 Postgresql,我们就可以创建数据库了。为了打开 Postgresql,我们实际上使用了用户“Postgres”。这有点像你的默认管理员帐户。我们使用这个是因为我们没有创建任何当前用户,但这是我们稍后要做的事情。对于这一部分,我们需要创建我们的表。在最后一部分,我谈到了创建我的“食谱”数据库。同样,您可以使用任何适合您自己项目的数据库。

当你准备好你的数据库时,在你面前画一个 ERD(实体关系图)也无妨。它不仅有助于您完成数据库设计,还有助于可视化表之间的关系。我的 ERD 已经准备好了,让我们回到 Postgresql 命令行版本,开始使用这些表。

创建表格

提醒一下,首先我们将运行以下命令进入 Postgresql 命令行界面:

sudo -u postgres psql

同样,“postgres”是用户,直到我们设置另一个用户。我们将在以后做那件事。如果您收到这样的错误,服务可能没有运行:

尝试启动 Postgresql 时出错。

要解决这个问题,我们只需启动服务,然后登录:

sudo service postgresql start

在第一部分的最后,我们创建了“食谱”数据库(不区分大小写)。在创建第一个表之前,我们需要连接到那个数据库。在 Postgresql 命令行界面中,这是通过使用“\c”实现的,如下所示:

\c recipes

连接到食谱数据库。

现在我们可以创建我们的第一个表。查看 ERD 或创建表时,请记住需要创建的顺序。需要在关系中的任何子表之前创建父表。

我的第一个表将只包含两列,其中一列只是主键。根据经验,通常不需要这些表。因为它只有一个表,所以我们可以只使用子表中的一列来代替。但是,我将在稍后的一个简短的 API 调用中使用这个表,所以为了只返回所需的数据,为了简单起见,我将创建这个表。但是需要注意的是,在常规实践中只有两列,所以不需要这个表。

这是第一张表:

CREATE TABLE MealType(
     MealTypeID SERIAL PRIMARY KEY,
     MealName VARCHAR NOT NULL
);

确认 MealType 已成功创建。

您可能注意到了,语法非常类似于 MySQL。但是,主键的设置略有不同。在 MySQL 中,我们使用一个“INT NOT NULL AUTO_INCREMENT”,或者使用一个“IDENTITY”列,并像往常一样添加您的主键。在 Postgres 中,通过简单地使用一个“SERIAL”值来增加值来声明我们的密钥似乎非常简单。

让我们用一个十进制值和另一个缺省值设置下一个表。它也将是父表。DECIMAL 类型是标准的 SQL 数据类型,因此声明它与其他 SQL 类型(如 MySQL)没有什么不同。在我们为默认值声明了数据类型之后,只需使用关键字 default 和您想要的值。

CREATE TABLE Pantry(
     PantryID SERIAL PRIMARY KEY,
     Title VARCHAR NOT NULL,
     TotalAmt DECIMAL (5, 2) NOT NULL,
     TotalAmtUnit VARCHAR DEFAULT 'LBS' NOT NULL
);

确认茶水间已成功创建。

我需要的下一个表是食谱表。该表将有一个外键。为此,创建一个外键约束,就像在 MySQL 中一样。添加列后,添加外键,声明该键将是哪一列,然后是关键字引用,最后是表和该表的主键。

CREATE TABLE Recipe(
     RecipeID SERIAL PRIMARY KEY,
     MealTypeID INT NOT NULL,
     Title VARCHAR NOT NULL,
     FOREIGN KEY(MealTypeID) REFERENCES MealType(MealTypeID)
);

确认配方已成功创建。

我们的下一个表将包含每个食谱的说明,所以我们也需要一个外键。这张桌子没什么特别的:

CREATE TABLE Instructions(
     InstructionID SERIAL PRIMARY KEY,
     RecipeID INT NOT NULL,
     StepNum INT NOT NULL,
     Description VARCHAR NOT NULL,
     FOREIGN KEY(RecipeID) REFERENCES Recipe(RecipeID)
);

确认说明已成功创建。

最后一张桌子是配料的。该表将有两个外键。一个是菜谱桌,另一个是配餐桌。这将是关联表(创建食谱和配餐项目之间的关联)。我想要实现的未来元素需要这个连接。一旦前端开始运行,我希望能够知道我是否有足够的配料来烹饪或烘焙食谱。要做到这一点,我需要知道我有多少配料,还有多少还留在食品柜里。如果储藏室里有足够的食物,食谱就可以用了,我必须决定如何处理没有所有必需食材的食谱。

CREATE TABLE Ingredient(
     IngredientID SERIAL PRIMARY KEY,
     RecipeID INT NOT NULL,
     MeasurementAmt DECIMAL(5, 2) NOT NULL,
     MeasurementUnit VARCHAR NOT NULL,
     Title VARCHAR NOT NULL,
     PantryID INT NOT NULL,
     FOREIGN KEY(RecipeID) REFERENCES Recipe(RecipeID),
     FOREIGN KEY(PantryID) REFERENCES Pantry(PantryID)
);

确认配料已成功创建。

现在我们已经定义并创建了表,我们需要确保可以在数据库中找到它们。要查看我们的表列表,我们需要 MySQL 的 SHOW TABLES 的等价物。在 Postgresql 中,我们使用以下内容:

\dt

显示所有表格。

创建好所有的表格后,我们就可以开始插入测试数据了。但是为了保持简短和易于理解,我们将在下一部分开始插入那些测试记录。您创建的表可能比我创建的数据库更小或更大。也许您需要不同类型的字段,包括非标准的 SQL 数据类型,如文档类型或网络地址类型。就我的目的而言,我目前不需要这些类型。如果我们想到要添加什么,我们可以以后再做。

结论

在这一部分中,我们学习了如何创建表。在很大程度上,语法与 MySQL 非常相似。但是,还是有一些不同,比如在创建自动递增主键字段时。在 Postgresql 中,我们使用串行数据类型。我们还学习了如何声明主键和外键。当比较语法时,这些也很像 MySQL。我们还学习了如何连接到食谱数据库。一旦创建了所有的表,我们还学习了如何显示我们创建的所有表。因为我们使用所有者“postgres”创建了它们,这是我们之前登录时使用的。我们还没有一个特定的用户创建,但我们会在以后做的。

对于下一部分,我们可以插入我们的测试数据,也许更新和删除记录。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

查看我最近的文章:

[## SQLite vs TinyDB

towardsdatascience.com](/sqlite-vs-tinydb-7d6a6a42cb97) https://python.plainenglish.io/python-virtual-environments-what-you-need-to-know-95487982c586 https://python.plainenglish.io/tinydb-b646e3270fd7 https://python.plainenglish.io/python-database-dumping-9a8658994e5a

参考资料:

https://stackoverflow.com/questions/10335561/use-database-name-command-in-postgresql https://www.postgresqltutorial.com/postgresql-show-tables/ https://kb.objectrocket.com/postgresql/how-to-use-the-postgresql-double-precision-type-1435 https://www.geeksforgeeks.org/postgresql-numeric-data-type/ https://dba.stackexchange.com/questions/212249/how-to-use-default-value-of-data-type-as-column-default https://www.postgresqltutorial.com/postgresql-describe-table/

Postgresql 简介:第 3 部分

原文:https://towardsdatascience.com/introduction-to-postgresql-part-3-83f64fa68ed?source=collection_archive---------30-----------------------

插入、更新、删除的时间…

马修·斯皮特里在 Unsplash 上的照片

第二部分中,我们学习了如何在 Postgres 中创建表格。我们还研究了如何连接到数据库,所以如果您需要复习,请参阅第 2 部分。对于这一部分,我们将看看如何插入、更新和删除。一旦我们学会了做所有这三件事,我们的数据库将为我们以后可能想要创建的任何 API 或前端做好准备。

正如我们在上一部分中注意到的,Postgresql 在语法上与 MySQL 非常相似。随着我们今天了解得越来越多,我发现这些相似之处仍在继续,只是有一些不同。总的来说,如果你了解 MySQL,那么转换到 Postgresql 会比其他 SQL 转换简单得多。因此,知道我们的目标是什么,让我们直接进入代码。

插入

显然,您需要启动 Postgresql,跳转到它的界面,然后连接到数据库。如果您有任何问题,可以回顾本教程的前几部分,了解如何启动 Postgres 服务以及如何登录。一旦进入,我们需要连接到数据库。我们已经在第 2 部分学到了这一点,但是作为一个简短的复习,您可以使用下面的命令:

\c recipes

接下来,我们可以看看我们的表。同样,我们在第 2 部分中讨论了这一点,但是如果您已经有一段时间没有查看数据库了,那么在尝试插入数据之前,最好先回顾一下您创建了哪些表。

\dt

对于我的数据库,我们将添加到 MealType 表的第一个表。要插入,我们指定要插入的列,然后列出值:

NSERT INTO MealType(MealName) VALUES (‘Breakfast’);

插入餐饮类型。

为了确保数据在那里,我们可以简单地从表中选择所有:

SELECT * FROM MealType;

查询 MealType 表。

在开始使用这些数据之前,我们还需要表中的一些记录。然而,由于还要添加四条记录,创建多个 INSERT 语句可能会变得很乏味。然而,使用 Postgres,我们可以简单地用逗号分隔一系列值,以便一次插入多条记录:

INSERT INTO MealType(MealName) VALUES (‘Lunch’),
     (‘Appetizer’),
     (‘Entree’),
     (‘Dessert’);

插入了多种膳食类型。

并再次选择以确保主键的序列值正常工作。

显示所有的餐饮类型。

检查我们的桌子,我们接下来要添加餐具室的桌子。但是,如果我们忘记了列名怎么办?在 MySQL 中,我们会使用 DESCRIBE 语句。Postgresql 也有一个这样的语句,它将以下命令与您的表名一起使用:

\d pantry;

餐具室桌子的描述。

现在我们知道了列是什么,以及需要什么,我们可以开始添加更多的数据。我们可以一次添加多个记录,但只会添加创建第一个食谱所需的食品柜项目。

简单地说,我在写出下面几行时犯了一个语法错误。它是一个丢失的逗号。通常,有一个通用的语法错误语句。然而,Postgresql 给我留下了这样一个错误消息:

语法错误消息。

如你所见,它非常具体,甚至指出了问题所在。一旦修复,我们可以在我们的记录中添加:

INSERT INTO Pantry(Title, TotalAmt, TotalAmtUnit) VALUES (‘Flour’, 5, ‘LBS’),
     (‘Butter’, 1, ‘LBS’),
     (‘Milk’, 1, ‘GAL’),
     (‘Salt’, 1, ‘LBS’),
     (‘Sugar’, 5, ‘LBS’),
     (‘Baking Powder’, 5, ‘LBS’),
     (‘Egg’, 12, ‘Egg’);

插入多个食品柜项目。

查询餐具室表。

我要添加的下一个表是 Recipe 表,它有一个来自 MealType 表的外键。我们需要查看 MealType 记录来确定外键的 ID。在这种情况下,我们正在制作的食谱是针对早餐的,因此我们将需要 ID 1,即“早餐”。接下来,我们准备插入我们的价值观。

INSERT INTO Recipe(MealTypeID, Title) VALUES (1, ‘Pancakes’);

插入配方表。

成功插入新配方。

接下来,我将添加到我的说明表中。这将有一个来自食谱表的外键。因为我们只向表中添加了一个配方,所以我们知道 ID 必须是 1。

INSERT INTO Instructions(RecipeID, StepNum, Description) VALUES (1, 1, ‘Melt butter and allow to cool. Add milk and one egg. Mix thoroughly.’),
     (1, 2, ‘Mix dry ingredient together in a separate bowl.’),
     (1, 3, ‘Preheat non-stick pan to medium, or use no-stick spray on pan.’),
     (1, 4, ‘Pour wet ingredients into dry ingredients. Mix until just combined. Do not overmix.’)
     (1, 5, ‘Pour ¼ cup fulls of pancake batter into heated pan. Flip once bubbles pop or until golden brown. Serve hot.’);

插入所有配方说明。

指令已成功插入。

你可以看到我已经打错字了,但是没关系。一旦我们开始更新记录,这些问题就可以得到纠正。现在,我只剩下一张桌子了。然而,该表是一个关联表,这意味着它至少连接了我们的两个表。在这种情况下,配料表连接食谱和餐具室。出于这个原因,我们将需要查看这两者,以找到我们的外键值应该是什么。同样,我们可以假设 Recipe 为 1,因为该表中没有其他记录。但是对于 Pantry,我们需要查看记录,这样我们就可以关联每种配料需要哪些键。

插入的成分。

成功插入配方配料。

更新

插入记录后,我们可以看看如何更新记录。在设置说明的时候,我用了“成分”而不是“配料”。然而,这很容易解决。我们可以用一个简单的更新来改变文本。在我们的更新中,我们将首先声明表,然后将值设置为我们想要的列,最后,还添加了一个 WHERE 子句,以确保我们不会更新表中的所有记录。该语句的语法类似于 MySQL 中的语法。

UPDATE Instructions
SET Description = ‘Mix dry ingredients together in a separate bowl.’
WHERE InstructionID = 2;

更新了说明表。

为了检查我们的更改,我们可以将 WHERE 子句添加到 SELECT 语句中:

SELECT *
FROM Instructions
WHERE InstructionID = 2;

显示更新的记录。

对于更新,像任何其他 SQL 一样,您不必使用主键来更新。只需去掉 WHERE 子句,就可以更新表中的所有内容。我们不会这样做,因为我们必须将多个字段改回来。然而,我们可以使用成分表中的任何其他字段。如果你记得的话,我在成分表中为我们的测量单位将“tsp”和“tbsp”都设置为小写。但是如果我只想把单个的“T”换成大写的“T”呢?为此,我们可以只使用替换功能。注意,我知道我没有其他的 t 作为值,所以更新是安全的。如果您有可能因此而更改的其他记录,您可能还需要定义 ID。

UPDATE Ingredient
SET MeasurementUnit = REPLACE(MeasurementUnit, ‘t’, ‘T’);

更新的成分表。

“7”这个数字让我很担心。我认为应该只有“3”,因为这是应该更新的记录数。因此,我查看了所有记录,看起来所有记录都与预期完全一致:

升级成分表的结果。

删除

首先,我将向 MealType 添加一个随机条目,以便我们可以删除它。这将是一个副本:

MealType 表中有重复记录。

如您所见,有两个“早餐”条目。因为这是一个重复,虽然它不会被认为是一个数据库,而有单独的 id,我们将想要删除它。同样,语法将类似于 MySQL。首先,启动 DELETE 并选择哪个表,然后使用 WHERE 子句确定要删除的记录:

DELETE FROM MealType
WHERE MealTypeID = 6;

已删除记录。

重复记录已删除。

删除时,序列号不会重置。这意味着您插入的下一条记录将是“7”,尽管表中只有 6 条记录。这很好,因为 ID 只是为了唯一性。

对于下一个删除测试,我想转储一个表中的所有记录。但是,它将是一个父表。现在,这种删除应该会失败,因为有子记录附加到父记录。我们没有指定级联应该打开,所以它不应该自动级联。然而,安全总比后悔好。为了确保我们不会丢失所有的工作,我们将执行第一次数据库转储。我在以前的文章中已经这样做了,但是因为这不是 Postgres 特有的,所以我们将再看一看。再次使用我们的 Postgres 用户,我们将执行 pg_dump。另外,请注意这不会发生在 Postgresql 终端内部,而是发生在常规的 bash 终端中。

sudo -u postgres pg_dump recipes > recipes.sql

转储文件已创建。

现在我们可以尝试从配方表中删除:

DELETE FROM Recipe;

级联删除错误。

看起来我们得到了一个错误,因为级联没有自动打开。如果 CASCADE 打开,它将删除与父记录相关联的所有子记录。但是现在,我们已经学习了足够多的关于插入、更新和删除的知识,可以让您在个人 Postgresql 数据库上有一个良好的开端。

结论

在这一部分中,我们讨论了如何在 Postgresql 数据库中插入、更新和删除记录。在插入过程中,我们了解到只需一条语句就可以添加多条记录。通过更新,我们了解到不仅可以更改整个值,还可以在 SET 语句中使用 REPLACE right 之类的函数。在删除过程中,我们了解到,尽管最好还是小心为上,但在更新或删除事件时,表不会自动设置为级联。相反,用户可以选择何时级联什么。如果它不是自动的,我们就不会意外地同时删除所有的食谱、配料和说明。

目前,这将是我们在实际数据库方面所做的全部工作。以后可能还会回来加个前端。在此之前,我需要为此构建一个 API。它可能会使用 FastAPI。但在此之前,我希望本教程是有教育意义的,令人愉快的。干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

查看我最近的文章:

https://python.plainenglish.io/hosting-your-own-pypi-a55f2a6eca4d https://python.plainenglish.io/middleware-in-fastapi-what-is-it-fa028349489d

参考资料:

https://www.postgresqltutorial.com/postgresql-insert-multiple-rows/ https://stackoverflow.com/questions/109325/postgresql-describe-table https://stackoverflow.com/questions/27152413/postgresql-update-substring-replacement https://www.tutorialspoint.com/mysql/mysql-delete-query.htm

概率分类导论:机器学习的视角

原文:https://towardsdatascience.com/introduction-to-probabilistic-classification-a-machine-learning-perspective-b4776b469453?source=collection_archive---------0-----------------------

从预测标签到预测概率的指南

资料来源:纳赛尔·塔米米在 Unsplash 上。

您能够训练和评估分类模型,包括线性和非线性模型结构。干得好!现在,你想要类别概率而不是类别标签。不读了。这是你正在寻找的文章。本文将带您了解不同的评估指标、其优缺点以及针对多个 ML 模型的最佳模型训练。

给猫和狗分类

设想创建一个模型,其唯一目的是对猫和狗进行分类。分类模型不会是完美的,因此会错误地对某些观察结果进行分类。有些猫会被归类为狗,反之亦然。这就是生活。在这个例子中,模型对 100 只猫和狗进行分类。混淆矩阵是显示预测准确性的常用可视化工具,图 1 显示了该示例的混淆矩阵。

图 1:100 只猫狗分类的混淆矩阵。来源:作者。

让我们把注意力集中在 12 个观察结果上,模型预测的是一只猫,而实际上它是一只狗。如果模型预测有 51%的概率是猫,而结果是一只狗,那肯定是可能的。但是,如果模型预测 95%的概率是猫,结果是狗呢?这似乎不太可能。

图 cat 的预测概率和分类阈值。来源:作者。

分类器使用预测的概率和阈值对观察值进行分类。图 2 显示了阈值为 50%的分类。使用 50%的阈值似乎是直观的,但是对于调整阈值没有限制。所以,最后唯一重要的是观察的顺序。改变目标来预测概率而不是标签需要不同的方法。为此,我们进入概率分类领域。

评估指标 1:对数损失

让我们从猫和狗推广到 0 和 1 的类标签。类别概率是 0 到 1 之间的任何实数。模型目标是将预测概率与类别标签相匹配,即最大化等式中给出的可能性。1,在给定预测概率的情况下观察类别标签。

等式 1:类别标签的可能性 y 和基于特征的预测概率 x

这种可能性的一个主要缺点是,如果观察次数增加,个体概率的乘积会变得越来越小。因此,有了足够的数据,任何计算机的数值精度都有可能下溢。其次,参数的乘积很难区分。这就是为什么对数的可能性是首选,通常被称为对数似然。对数是其自变量的单调递增函数。因此,函数的对数最大化等价于函数本身的最大化

等式 2:类别标签的对数损失 y 和基于特征的预测概率 x

尽管如此,对数似然性仍然随观察次数而变化,因此平均对数似然性是解释观察到的变化的更好的度量。然而,在实践中,大多数人最小化负的平均对数似然,而不是最大化平均对数似然,因为优化器通常最小化函数。数据科学家通常将这一指标称为对数损失,如等式 1 所示。2.关于 Logloss 及其与分类模型评估中通常使用的评估指标的关系的更详细的讨论,我建议您参考本文

评估标准 2: Brier 评分

Logloss 旁边的 欧石南得分 ,如 Eq 中给出。3,通常用作预测概率的评估指标。本质上,它是对预测概率和类别标签的二次损失。注意回归模型评估中使用的均方误差(MSE) 之间的相似性。

等式 3:类别标签的 Brier 分数 y 和基于特征的预测概率 x

然而,与 MSE 的一个显著区别是 Brier 的最低分数不是 0。Brier 分数是标签和概率的平方损失(T21),因此根据定义不为 0。简而言之,如果底层过程是非确定性的,则最小值不为 0,这是首先使用概率分类的原因。为了解决这个问题,通常在相对的基础上用其他概率分类器来评估概率,例如使用 Brier Skill 分数。

带有虚拟数据的示例

在本节中,我将展示一个使用虚拟数据从分类到概率估计的步骤示例。这个例子将展示多个 ML 模型,从逻辑回归到随机森林。让我们首先使用 Sklearn 创建虚拟数据。虚拟数据集包含信息性特征和冗余特征,并且引入了每个类的多个聚类。

使用 ML 模型结构对虚拟数据进行分类:

使用 ROC-AUC 分数评估 ML 模型的正确分类能力。图 3 显示,所有的最大似然模型在分类虚拟数据方面做得相当好,即 ROC-AUC > 0.65,而 RBF SVM 和 RF 表现最好。

图 3:不同 ML 模型结构的样本外数据的 ROC-AUC 得分。来源:作者。

但是,请注意,模型的目标是预测概率。ML 模型能够准确地对观察结果进行分类是件好事,但是模型预测分类概率的能力有多强呢?有两种评估预测概率的方法:

  • 定量地用 Brier 评分和 Logloss
  • 用校准图定性。

概率的定量评估

首先,使用 Brier 评分和 Logloss 对 ML 模型进行定量评估。图 4 显示 RBF SVM 和 RF 在基于 Brier 评分(左)和 Logloss(右)的概率估计中表现最佳。注意,DT 的 Logloss 相对较高,要了解其原因,请参考本文。

图 4:不同 ML 模型结构的样本外数据的 Brier 得分(左)和 Logloss(右)。来源:作者。

概率的定性评估

其次,使用校准图对 ML 模型进行定性评估。校准图的目的是显示和评估预测的概率是否与实际的阳性分数相匹配。该图将预测的概率存储在统一的存储桶中,并将预测的平均值与阳性分数进行比较。图 5 显示了我们示例的校准图。您可以看到 LR 和 RBF SVM 得到了很好的校准,即平均预测概率与阳性分数非常匹配。然而,检查 LR 的预测概率的分布表明,预测概率比 RBF SVM 更集中。接下来,你会看到 DT 校准不当,预测概率的分布似乎是错误的。

图 5:不同 ML 模型的校准图(上图)和概率分布图(下图)。来源:作者。

为什么预测概率与后验概率不匹配?

Niculescu-Mizil 和 Caruano 在他们 2005 年的论文 “用监督学习预测好的概率” 中解释了为什么一些 ML 模型观察到与后验概率相比扭曲的预测概率。让我们从解释根本原因开始。当分类模型没有被训练来降低对数损失时,预测概率与后验概率不匹配。对此的解决方案是将模型训练后的预测概率映射到后验概率,这被称为训练后校准。常用的概率校准技术有:

  • 普拉特标度(普拉特,1999 年)
  • 等渗回归(Zadrozny,2001 年)

图 6:用普拉特标度和保序回归进行训练后概率校准后的模型性能。资料来源:(Niculescu 等人,2005 年)

校准决策树和随机森林

ML 模型使用 Platt 标度和保序回归进行校准,这两种方法在 Sklearn 中都很容易编码。注意,LR 没有被校准,因为该模型结构被训练以减少对数损失,因此默认情况下具有校准的概率。

唯一可调的参数是概率校准的交叉验证数。Niculescu (2005)表明,小的校准集大小可能会降低性能,并且对于增强和打包的决策树和支持向量机来说,性能改善是最积极的。我们的示例在测试数据集中包含 8,000 个观察值。对于 5 重交叉验证,为校准集大小保留 1,600 个观察值。

图 7:不同 ML 模型和不同校准集大小的 Platt 标度和保序回归的 Brier 评分。资料来源:(Niculescu 等人,2005 年)

概率校准后的模型评估

让我们看看概率校准是否改善了 Brier 分数、Logloss 和校准图。图 7 显示了概率校准后的 Brier 评分和对数损失。因为数据集包含足够数量的观察值,所以保序回归具有与普拉特缩放相当的性能。考虑到保序回归的非参数性质,我必须警告校准集规模较小的情况。但是,如果你打算在小数据量上做概率分类,我建议你使用先验信息,探索贝叶斯分类的领域。

图 7:对样本外数据进行训练后校准后的 Brier 得分(左)和 Logloss(右)。来源:作者。

图 8 显示了训练后校准后的校准图。你会看到 SVM、DT 和 RF 的预测概率有所提高。其次,预测概率的分布完全覆盖[0,1]的范围,并提供准确的平均预测概率。

图 8:ML 模型训练后校准后的校准图(上图)和概率图(下图)。来源:作者。

概率校准会影响分类能力吗?

校准不会改变预测概率的排序。校准仅改变预测的概率以更好地匹配观察到的阳性分数。图 9 显示,在概率校准后,通过 ROC-AUC 分数测量的模型的分类能力相等或更好。

图 9:不同 ML 模型结构的训练后校准后的 ROC-AUC 得分。来源:作者。

预测概率?校准模型!

虚拟示例清楚地表明,训练后校准对于精确估计所讨论的 ML 模型的类概率是至关重要的。

额外资源

下面的教程/讲座对我个人理解概率分类非常有帮助。我已经根据(个人)重要性对这些资源进行了排名,我强烈建议查看这些资源。

学术界

  1. 斯坦福大学电气工程教授桑杰·拉尔。
  2. 研究科学家 Andreas Müller,计算机科学@ 哥伦比亚

行业

  1. 数据科学家贝基·塔克,@ 网飞
  2. 数据科学家 Gordon Chen,@ 甲骨文

参考

[1]普拉特,J. (1999 年)。支持向量机的概率输出以及与正则似然方法的比较。大间距分类器的进展(第 61-74 页)。

[2]b . Zadrozny 和 c . Elkan(2001 年)。从决策树和朴素贝叶斯分类器获得校准的概率估计。 ICML (第 609–616 页)。

[3]尼古列斯库-米齐尔和卡鲁阿纳(2005 年)。用监督学习预测好的概率。过程。第 22 届机器学习国际会议(ICML 05)。

如果你热衷于阅读更多,请看下面我的文章:

https://medium.com/@larsterbraak/cost-decomposition-for-a-vwap-execution-algorithm-buy-side-perspective-1126f9eebf40 https://medium.com/@larsterbraak/beyond-traditional-return-modelling-embracing-thick-tails-67f457dfbf6b

Pyspark ML Lib 简介:构建您的第一个线性回归模型

原文:https://towardsdatascience.com/introduction-to-pyspark-ml-lib-build-your-first-linear-regression-model-68631cdcf08a?source=collection_archive---------45-----------------------

按比例创建您的第一个 ML 模型

照片由 吉纳萨

随着公司产生越来越多样化和以用户为中心的数字商品和解决方案,应用于构建个性化、建议和未来分析的机器学习变得越来越重要。Apache Spark 机器学习库(MLlib)使数据工程师能够专注于特定的数据挑战和算法,而不是处理不同数据集的复杂性。

对一个相关因素和一个或多个随机因素之间的关系进行建模的线性技术称为线性回归。它是最基本和最广泛使用的预测建模之一。

什么是 Spark MLlib?

照片由 马里乌斯·马萨拉尔

Spark MLlib 是 Spark 最吸引人的功能之一,因为它具有大规模处理的能力,这正是机器学习模型所需要的。但是,有一些机器学习模型无法正确实现,这是一个缺点。

MLlib 是一个全面的机器学习包,包括分类、回归、聚类、合作过滤和基本的优化原语,以及其他流行的学习方法和工具。

什么是线性回归模型?

通过将一条线与给定的信息相匹配,回归方法说明了变量之间的联系。在这个系统中使用直线,而在非线性系统中使用曲线路径。

还可以开始使用回归来预测依赖于自变量特征的因变量的特征。使用简单的线性回归估计两个定性参数之间的联系。

为什么对 ml 使用 spark Mllib

由于速度快,Spark 对于数据科学家来说是一个强大的集中式平台。这也是一个简单易用的工具,可以帮助他们快速获得想要的结果。这使得数据科学家能够在更大的规模上修复深度学习的复杂性以及模式计算、广播和交互式请求处理。

r、Python 和 Java 只是 Spark 中可用的几种语言。2015 年 Spark 研究,采访了 Spark 社区,揭示了 Python 和 R 的主要快速增长。特别是,58%的参与者说他们使用 Python,18%的参与者说他们目前正在使用 R API。

对更全面的教程感兴趣:

看看这段 youtube 视频:

Pyspark ML Lib 简介:通过 Anuj Syal 构建您的第一个线性回归模型

使用 Spark Mllib 创建您的第一个线性回归模型

  • 第一步:Pyspark 环境设置对于本地机器上的 pyspark 环境,我的首选是使用 docker 运行jupyter/pyspark-notebook image。然而,如果你对广泛的安装指南感兴趣,看看我的博客文章youtube 视频
  • 步骤 2:创建 spark 会话
from pyspark.sql import SparkSession spark = SparkSession.builder.master("local")
.appName("linear_regression_model").getOrCreate()

对于数据集,我使用来自 Kaggle 的一个简单的房地产数据集,它包含具有连续特征的房地产的简单数据,如distance from mrt stationcoordinatessize

下载后,将数据集读入 spark 数据框

real_estate = spark.read.option("inferSchema","true").csv("real_estate.csv",header=True)

我们可以使用 spark 中的一些内置函数来探索数据的不同属性/列。

PrintSchema()查看具有数据类型的列

real_estate.printSchema()
Out:
root
 |-- No: integer (nullable = true)
 |-- X1 transaction date: double (nullable = true)
 |-- X2 house age: double (nullable = true)
 |-- X3 distance to the nearest MRT station: double (nullable = true)
 |-- X4 number of convenience stores: integer (nullable = true)
 |-- X5 latitude: double (nullable = true)
 |-- X6 longitude: double (nullable = true)
 |-- Y house price of unit area: double (nullable = true)

Show()检查几行并理解数据

real_estate.show(2)
Out:
+---+-------------------+------------+--------------------------------------+-------------------------------+-----------+------------+--------------------------+
| No|X1 transaction date|X2 house age|X3 distance to the nearest MRT station|X4 number of convenience stores|X5 latitude|X6 longitude|Y house price of unit area|
+---+-------------------+------------+--------------------------------------+-------------------------------+-----------+------------+--------------------------+
|  1|           2012.917|        32.0|                              84.87882|                             10|   24.98298|   121.54024|                      37.9|
|  2|           2012.917|        19.5|                              306.5947|                              9|   24.98034|   121.53951|                      42.2|
+---+-------------------+------------+--------------------------------------+-------------------------------+-----------+------------+--------------------------+
only showing top 2 rows

describe()查看列的统计信息

real_estate.describe().show()
Out:
+-------+-----------------+-------------------+------------------+--------------------------------------+-------------------------------+--------------------+--------------------+--------------------------+
|summary|               No|X1 transaction date|      X2 house age|X3 distance to the nearest MRT station|X4 number of convenience stores|         X5 latitude|        X6 longitude|Y house price of unit area|
+-------+-----------------+-------------------+------------------+--------------------------------------+-------------------------------+--------------------+--------------------+--------------------------+
|  count|              414|                414|               414|                                   414|                            414|                 414|                 414|                       414|
|   mean|            207.5| 2013.1489710144933| 17.71256038647343|                    1083.8856889130436|              4.094202898550725|  24.969030072463745|  121.53336108695667|         37.98019323671498|
| stddev|119.6557562342907| 0.2819672402629999|11.392484533242524|                     1262.109595407851|             2.9455618056636177|0.012410196590450208|0.015347183004592374|        13.606487697735316|
|    min|                1|           2012.667|               0.0|                              23.38284|                              0|            24.93207|           121.47353|                       7.6|
|    max|              414|           2013.583|              43.8|                              6488.021|                             10|            25.01459|           121.56627|                     117.5|
+-------+-----------------+-------------------+------------------+--------------------------------------+-------------------------------+--------------------+--------------------+--------------------------+

Kaggle 还提供了这些属性的详细信息,如计数、平均值、标准差。这将允许您决定将哪些参数用作模型的特征

作者数据属性的屏幕截图

  • 步骤 4: VectorAssembler 将数据转换为特征列

决定使用 VectorAssembler 格式化数据框的列后

from pyspark.ml.feature import VectorAssemblerassembler = VectorAssembler(inputCols=[ 
 'X1 transaction date',
 'X2 house age',
 'X3 distance to the nearest MRT station',
 'X4 number of convenience stores',
 'X5 latitude',
 'X6 longitude'],
 outputCol='features')data_set = assembler.transform(real_estate)
data_set.select(['features','Y house price of unit area']).show(2)Out:
+--------------------+--------------------------+
|            features|Y house price of unit area|
+--------------------+--------------------------+
|[2012.917,32.0,84...|                      37.9|
|[2012.917,19.5,30...|                      42.2|
+--------------------+--------------------------+
only showing top 2 rows
  • 步骤 5:分成训练集和测试集
train_data,test_data = final_data.randomSplit([0.7,0.3])
  • 步骤 6:训练你的模型(用训练数据拟合你的模型)
from pyspark.ml.regression import LinearRegressionlr = LinearRegression(labelCol='Y house price of unit area')
lrModel = lr.fit(train_data)
  • 第六步:用相关性进行描述性分析

用测试集验证后检查系数:

test_stats = lrModel.evaluate(test_data)
print(f"RMSE: {test_stats.rootMeanSquaredError}")
print(f"R2: {test_stats.r2}")
print(f"R2: {test_stats.meanSquaredError}")

Out:
RMSE: 7.553238336636628
R2: 0.6493363975473592
R2: 57.051409370037256

测试数据的均方根误差(RMSE )= 7 . 54860 . 68686868661

结论

Spark 不仅是理解我们信息的更好方法;也快了很多。Spark 使我们能够以首选语言处理各种各样的数据挑战,从而改变了数据分析和研究。Spark MLlib 使新数据科学家能够轻松地使用他们的模型,专家可以根据需要进行微调。

分布式网络可能是数据工程师的主题,而机器学习方法和算法可能是数据科学家的主题。Spark 通过允许数据科学家专注于对他们至关重要的数据挑战,同时公开利用 Spark 单一系统的性能、便利性和集成性,极大地改进和革新了机器学习。

最初发表于【https://anujsyal.com】

Python 简介

原文:https://towardsdatascience.com/introduction-to-python-c43e17aaa78b?source=collection_archive---------18-----------------------

Python 是谁,是什么,为什么

所以你已经决定开始编程,并且可能已经听说 Python 是一种流行的语言。在深入研究之前,了解这门语言的内容是很重要的。在本文中,我们将带您了解什么是 Python,它可以用来做什么,您将会对 Python 的工作原理有所了解。

你将学到什么

  1. 为了能够理解 python 如何适应编程语言的环境
  2. 当你使用 python 而不是其他编程语言时
  3. 你能用 Python 做什么
  4. Python 项目的潜在弱点

python 为什么这么受欢迎?

你可能听说过 Python,以及有多少人在使用它。很难给出一个完整的答案来解释为什么有些东西如此受欢迎,但是我们可以尝试给你一个理解,我们认为 python 在过去的 10 年里已经起飞了。

首先是 python 的可读性,python 作为一门编程语言就应该是可读的。也就是说,你使用的代码不需要读者太多的努力就能理解。当你有一个捆绑了 100,000 行代码的软件时,这变得非常重要,有一些可以遵循的东西降低了想要学习它的人的门槛。

使用 python,开始使用 python 编写代码的学习曲线非常短!这使得它非常适合作为第一语言来学习。

作为一种编程语言,它是编程范式不可知的,我们的意思是有不同的编程方式,python 给了你这种灵活性。你可能听说过诸如函数式和面向目标的编程之类的术语,如果没有,不要担心!不用说,python 并不专注于你如何编程。

生产率是 Python 的另一个亮点,用其他语言如 C++和 Java 编写的程序通常要大得多(有时大 3 倍!)并需要中间步骤来运行程序。相比之下,Python 程序会立即运行。这意味着用 Python 制作原型只需要很少的时间。Python 也可以在所有操作系统上运行,所以无论你喜欢什么,你都可以开始编码。

Python 也有许多直接有用的内置函数,通常可以使编写代码的体验更加容易。这可能不是你马上想到的细节,或者在短期内有很大的影响,但是你使用一种语言越多,你就越能理解编写程序的好处和坏处。当你理解在其他语言中做同样的功能是多么困难的时候,你就会开始喜欢 python 的内置函数。

基于流行的 StackOverflow 论坛,他们的调查显示,在接受采访的 44,000 名程序员中,44.1%在他们的日常活动中使用 python。你还可以看到,在 6 年的时间里,StackOverflow 论坛上的 python 问题数量呈指数级增长,这通常是有多少人在学习这种语言的标志。

【2020 年 StackOverFlow 调查

【2012 年至 2018 年的 StackOverflow 问题数量

Python 是什么?

现在了解了 Python 流行的原因,我们可以开始理解它是什么了。Python 语言是 Guido Van Rossum 在 1985 年到 1990 年间创造的,Guido 以 Monty Python 命名了这种语言!圭多显然是个粉丝!Python 是一种通用编程语言,它有几个独特的属性,下面将对其进行概述。

{ 
  name: 'Aaron'
 }

1.面向对象

python 代码中的一切都是对象,这就是所谓的编程范式。总的来说,对象是表示数据和数据间关系的一种方式。Python 是隐式基于对象的,这意味着有特定的方法来表示数据之间的关系以及如何操作这些数据。对象也是一种将程序组织成功能盒子的清晰方式,并且能够以可伸缩的方式与这些盒子进行交互。

2.Python 是一种解释型语言。

要知道这意味着什么,我们必须先从 python 向外扩展一下。编程语言可以分为两种不同的类型,需要编译的语言和需要解释的语言。

编译语言接受编写的代码,并要求将其转换成硬件可以使用的代码。这种转换后的代码被称为机器码,它使你的程序能够在实际运行之前被计算机硬件运行。

像 Python 这样的解释型语言逐行读取代码,并动态地评估和转换这些代码为机器代码。这种转换发生在引擎盖下,你不必去想它。因此,代码开发时间比在运行程序之前必须先将代码转换成机器可读的东西要短。

3.Python 是动态类型的。

这意味着对象在代码运行时保存在内存中,不像其他语言那样,在运行程序之前不需要声明使用什么数据类型。这是 C++和 Java 程序比 python 大得多的部分原因。然而,这也意味着错误信息不会出现,直到你开始运行你的程序。如果你不小心你的代码,这会导致一些麻烦!

4.Python 是强类型的,

这意味着它强制您使用什么类型的数据,所以您不能混合不同数据类型的操作。如果您试图这样做,Python 将抛出一个错误。另一种选择是,您必须像在其他语言中一样定义您的数据类型。这可能会大大增加您编写代码的时间。

现在你知道 python 是基于对象的,它是一种动态的、强类型的解释语言。有点拗口,但当你记住这个词汇时,你就可以开始看到其他语言的不同了。

你能用 Python 做什么?

了解 python 是什么以及它为什么受欢迎是很重要的,但是实际上你能用它做什么呢?!

我们提到 python 是一种通用编程语言。这里有一个不太完整的列表,列出了适合 python 的任务和一些用于创建程序的库。

  1. 自动化任务,即重命名文件、更新电子表格(内置模块)
  2. 网络开发(烧瓶django
  3. 数据科学与数据库编程(熊猫)
  4. 机器学习( TensorFlowKerasScikit-learn )
  5. 生物信息学( Biopython
  6. 网络编程
  7. 机器人和硬件编程(Arduino)
  8. 金融
  9. 数值和科学编程( NumpySciPy )

你可能会问这一切是怎么做到的?!嗯,Python 有非常丰富的支持系统。有许多程序员帮助开发了可以与 python 一起使用的模块,以完成各种不同类型的工作,从机器人学、生物信息学到人工智能。如果你对 python 能做的各种事情感兴趣,请参考这里的链接获取 python 可用库的详细列表。

在数据科学领域,python 得到了大量的支持,它是进行这类研究的主要编程语言。因此,如果您对数据科学领域感兴趣,那么 python 是您应该考虑学习的语言。

除了上面列出的 python 可用的库,下面列出了目前使用 python 的公司提供的少量库。这表明 python 作为一门语言是多么有效,以及为什么它值得你花时间去理解它!

Python 的弱点

在这篇文章中,我们描绘了 python 是一种每个人都应该学习的奇妙语言。然而,它并不适用于所有场合,并且确实有一些限制。

1.移动开发

Python 没有强大的移动开发能力,目前也缺乏第三方库支持!两个流行的框架是 KivyBeeware ,但是它们目前仍然没有针对大量用户使用进行优化。Python 是消耗内存的,目前使用 python 的应用程序消耗电池的速度比用 Java 开发的移动应用程序要快得多。

记住这两点,Python 的移动应用程序开发还没有起步,但是这是一个将会随着时间而改变的领域。

2.Python 很慢

Python 速度慢有很多原因,但总的来说,主要是因为它的动态特性和编程范式的多样性。

不幸的是,Python 一次只运行一个操作,这被称为全局解释器锁(GIL)。大多数现代应用程序同时运行多个进程,这意味着 python 很难扩展应用程序的规模。在 python 中,全局解释器锁的概念是一个详细的主题,除了知道它的存在,你不需要知道细节。

另一个原因与语言本身的解释部分有关,它在运行时自动转换代码,这需要时间,不像编译语言。是的,对于编译语言,你必须转换代码,但是一旦代码被转换,速度会很快。

3.内存消耗

所有的程序都必须管理内存,也就是说我们如何在运行程序的时候存储代码来使用它?现在,因为 python 中的一切都是对象,所以用它来运行程序实际上是非常消耗资源的。每个对象都消耗内存。如果您的脚本很小并且程序不是关键任务,这可能没什么关系,但是如果您的项目雄心勃勃并且变得越来越大,它可能会在以后引起真正的问题。当您的应用程序被许多用户使用,并且应用程序的需求变得更大时,这是一个需要考虑的问题

3.处理错误

我们提到 python 是动态类型的,这意味着只有当我们运行程序时才会出现错误。这与编译过的程序相比,编译过的程序一旦被正确编译,就会一直运行。这种动态输入意味着如果不小心的话,一遍又一遍地做小的改动会很烦人!当您第一次开始 python 之旅时,请记住这一点。

你什么时候不会使用 Python

我们已经讨论了 python 的原型是多么的快速和简单,它的通用性质意味着它非常适合许多任务。

你可以想象 python 可以从性能的角度进行优化,但是如果性能是绝对关键的,Python 可能不是应该使用的语言!然而,它非常适合快速构建应用程序原型,并在用户群中进行测试,这就是它在初创企业群体中如此受重视的原因。

Python 适用于小型图形用户界面(GUI)程序,但是如果您正在开发的任何程序严重依赖于能够与 GUI 交互的需求,那么 python 可能不是您的首选语言。就此而言,在速度是绝对必要的时候,尝试创建一个基于 python 的操作系统是不明智的。

注意到上面所说的,你可以想象任何涉及硬件的事情都会被依赖,依赖 python 可能不是你最感兴趣的。

摘要

综上所述,Python 是一种通用编程语言,拥有巨大的第三方库支持。它可以用来自动完成任务,为人工智能研究创建神经网络。它很灵活,可读性很强,学习曲线很短,并且在学习的同时很容易开始创建真正的脚本。

它的主要缺点是性能速度,所以任务关键的程序,你可以想象,如果你计划维护大型项目,这可能不是使用的语言。

这对于原型创意和轻松启动项目非常有用,这也是为什么有很多初创公司使用 python 来启动他们的项目。

测试你知识的问题

解释语言和编译语言的区别是什么?

动态类型化是什么意思?

强类型是什么意思?

Python 有哪些弱点?

你什么时候会考虑使用 Python 之外的另一种语言?

放弃

本文首发于 CodeMD,此处。我们 CodeMD 热衷于将 Python 带给医疗专业人员。如果你对医疗保健和 Python 感兴趣,请加入我们。

https://codemd.co.uk/2021/03/03/starting-your-python-journey-with-ease/

关于作者

我是一名执业医师和教育家,也是一名网站开发者。

请看这里关于我在我的博客和其他帖子上关于项目的更多细节。更多技术/编码相关内容,请点击这里订阅我的简讯

我将非常感谢任何评论,或者如果你想与 python 合作或需要帮助,请联系我。如果你想和我联系,请在这里 asmith53@ed.ac.uk 或在 twitter 上联系。

面向数据科学的 Python 虚拟环境简介

原文:https://towardsdatascience.com/introduction-to-python-virtual-environment-for-data-science-3c216929f1a7?source=collection_archive---------37-----------------------

数据科学最佳实践

了解虚拟环境的基础知识

如果您使用 Python 已经有一段时间了,那么您可能会遇到这样的情况:即使您已经安装了所需的包,在其他人的计算机上运行完全相同的脚本却不能在您的计算机上运行。这可能是因为两台计算机上使用的 Python 环境不同(例如,可能使用两个不同版本的包)。能够重现准确的输出不仅依赖于准确的脚本,还依赖于正确的环境设置。我们可以通过创建虚拟环境来确保为我们的项目建立合适的 Python 环境。

虚拟环境可以帮助我们提高项目的可重复性,更容易与其他人协作,并使部署更加顺利。

在本帖中,我们将熟悉一个虚拟环境管理器: venv 并了解虚拟环境的基础知识。

马库斯·斯皮斯克Unsplash 上拍摄的照片

📍基础

0.设置

这篇文章假设你的电脑上已经安装了 Python 3.3+。

Python 标准库包括 venv ,因此当你安装 Python 时默认安装它。因此,我们不需要安装任何额外的包来开始。

1.转到项目目录

我们将使用命令行来键入命令。这里有一种打开命令行界面的方法,取决于你的操作系统:
◼️如果你在 Mac 上,打开一个终端窗口,步骤如下:
➡️按 cmd +空格键➡️类型终端➡️按 enter
◼️如果你在 Windows 上,打开一个命令提示窗口,步骤如下:➡️按 windows 键➡️键入 cmd ➡️按 enter

现在将您的工作目录更改为您的项目目录。例如,如果您的项目目录在桌面上,下面的脚本将帮助您实现这一点。如果您的项目文件夹在其他地方,您可以相应地调整脚本。

$ cd Desktop/project # Mac
$ cd Desktop\project # Windows

2.创建虚拟环境

既然我们现在在项目文件夹中,让我们创建一个虚拟环境。在本例中,我们选择将虚拟环境命名为'。这将创建一个包含虚拟环境文件的隐藏(因为名称以点开头)目录。你可以替换掉'。用你喜欢的任何名字。但是,如果您对虚拟环境的名称没有强烈的偏好,我建议遵循我们在这里使用的相同命名约定:'。venv'* 。这个命名约定得到了布雷特·卡农的认可。如果你好奇,这里是他关于这个话题的讨论。*

要创建一个虚拟环境,我们只需要运行下面的一个命令行程序:

$ python -m venv .venv

这将使用基础 Python 的相同 Python 版本(或最新 Python 版本,如果您有多个版本)创建一个虚拟环境。一旦执行了这个命令,您会注意到您有了一个名为''的新文件夹。venv' 。在创建虚拟环境之前和之后,如果您在 Mac 上,可以使用ls -A检查项目目录中的内容;如果您在 Windows 上,可以使用dir检查项目目录中的内容。

3.激活虚拟环境

让我们检查一下你已经安装在你的基础 Python 上的包的版本(即 Python 的系统安装)。在本例中,我们将选择 numpy ,但它可以替换为您选择的任何第三方软件包:

$ python -c "import numpy as np; print(np.__version__)"

它应该返回您的基本 Python 环境中的包版本。现在,让我们激活虚拟环境并再次检查软件包版本:

# Activate virtual environment
$ source .venv/bin/activate # Mac
$ .venv\Scripts\activate # Windows# Check again
$ python -c "import numpy as np; print(np.__version__)"

当我们运行与之前完全相同的脚本时,它会返回一个错误。这是因为我们刚刚创建的新虚拟环境被激活,我们不再使用基本的 Python 环境。判断虚拟环境已激活的最简单方法是在命令行的开头查找环境名称。

4.设置/准备虚拟环境

当我们创建一个虚拟环境时,它就像一张白纸。我们需要将所有必需的包安装到环境中来设置它。将软件包安装到虚拟环境非常简单。你可以像平常安装软件包一样使用pip。在这样做的时候,您需要确保您的虚拟环境是激活的。

让我们安装一个与基础环境中的版本不同的特定版本的包。我们将继续我们的 numpy 示例,并选择版本 1.19.4(如果这恰好与您的基本版本 numpy 相同,请选择另一个版本)进行本练习:

# Install numpy v1.19.4
$ pip install numpy==1.19.4# Check again
$ python -c "import numpy as np; print(np.__version__)"

这应该会返回 1.19.4。因此,我们只是在虚拟环境中安装了不同版本的 numpy 。在上面的例子中,如果我们只想安装软件包的最新版本,我们可以键入软件包名称而不指定任何版本:pip install numpy

更常见的是,我们需要根据概述必要包版本的 requirements.txt 文件来准备我们的虚拟环境。下面是如何根据 requirements.txt 中概述的规范安装软件包:

$ pip install -r requirements.txt

一旦使用必要的包设置并激活了您的环境,您就可以开始使用该环境为项目开发和测试 Python 代码了。

5.在虚拟环境中导出包版本

有时,您可能需要导出您创建的虚拟环境的需求。我们只用一行代码就可以做到:

$ pip freeze > requirements.txt

如果您想检查您刚刚保存的 requirements.txt 的内容,您可以像打开其他文件一样打开它。txt 文件。或者,您可以使用以下脚本在命令行解释器中查看其内容:

$ cat requirements.txt # Mac
$ type requirements.txt # Windows

6.停用虚拟环境

在环境中完成工作后,如果您想切换回基本 Python,您需要做的就是像这样停用环境:

$ deactivate

运行此命令后,命令行的前缀应该不再显示虚拟环境的名称。这将向您确认虚拟环境已被停用。

7.删除虚拟环境

如果您想要删除虚拟环境,只需删除文件夹()。venv' 文件夹)就像你通常删除任何文件夹一样。如果您希望从命令行删除,可以使用以下脚本:

$ rm -r .venv # Mac
$ rd /s .venv # Windows, when prompted press Y and enter

摘要🍀

总结一下,下面是我们在这篇文章中访问过的主要命令的整理摘要:

# Create a virtual environment
$ python -m venv <environment_name># Activate a virtual environment
$ source <environment_name>/bin/activate # Mac
$ <environment_name>\Scripts\activate # Windows# Install required packages from requirements.txt
$ pip install -r requirements.txt# Install a package with a specified version
$ pip install <package_name>==<version># Export installed libraries to requirements.txt
$ pip freeze > requirements.txt# Deactivate virtual environment
$ deactivate

通常你会在项目开始的时候建立一个虚拟环境(可能在这里有一个小的调整,稍后需要)。设置完成后,典型的项目工作流程主要涉及激活和停用虚拟环境。

阿诺德·弗朗西斯卡在 Unsplash 上拍摄的照片

您想访问更多这样的内容吗?媒体会员可以无限制地访问媒体上的任何文章。如果您使用 我的推荐链接成为会员,您的一部分会费将直接用于支持我。

谢谢你看我的帖子。希望你在使用 venv 时感觉更舒服。对于那些狂热的学习者,这里有一些其他流行的创建虚拟环境的方法:
◼️ 康达虚拟环境t13】◼️pyenv用于管理多个版本的 Python

如果你喜欢这篇文章,这里有我的一些其他文章的链接:
◼️git 数据科学简介
◼️ 用这些提示整理你的 Jupyter 笔记本
◼️python 中的简单数据可视化,你会发现有用的
◼️ 在 Seaborn (Python)中更漂亮和定制情节的 6 个简单提示
◼️️ 给熊猫用户的 5 个提示
◼️️

再见🏃💨

Python 的 Boto3 简介

原文:https://towardsdatascience.com/introduction-to-pythons-boto3-c5ac2a86bb63?source=collection_archive---------6-----------------------

AWS SDK 简单易行

图片来自 Unsplash.com,作者: @azizayad

自从在一家可以访问 AWS 和云的初创公司工作以来,我不得不学习一些新工具。这是加入创业公司最有趣的事情之一!一开始,我很自然地开始在我的本地机器上做数据科学。然而,随着数据资产的建立和新人的加入,我不得不做出改变。我开始利用我们的 AWS 云环境。更具体地说,我需要访问亚马逊 S3。我一步一步摸索着 stackoverflow,浏览了几个教程。最后我学到了很多。我想我应该分享一些我一路走来学到的东西,希望能帮助别人。

在这篇文章中,我将解释一些关于 Boto3 、python 的 AWS SDK 和亚马逊 S3 的高级概念。我将提供一步一步的 python 代码来做一些基本的,但是在尝试遍历和访问 S3 的信息时非常有用的事情。让我们跳进来吧!

首先要做的事情

  1. 你需要安装 Boto3: pip install boto3
  2. 接下来,您需要在本地机器上一个名为“aws”的隐藏文件夹中创建一个凭证文件。从技术上讲,您可以直接传递您的凭证,而不是创建一个文件,但我不建议这样做。
  • 打开一个终端,cd进入这样的目录路径(这是 Mac 用的):/Users/your_name
  • 创建一个名为“aws”的隐藏文件夹:mkdir .aws
  • cd进入新的隐藏文件夹,用你喜欢的任何文本编辑器创建一个空白文件。我用 vim,所以对我来说只是vim credentials
  • 进入文件后,插入以下项目并保存:
[default]
aws_access_key_id = your_access_key
aws_secret_access_key = your_secret_access_key
region = your_region

您可以在 AWS 文档中找到如何找到您的访问密钥特定区域代码。一旦你安装了 Boto3 并且设置了你的证书,你就可以连接到 S3 了。

低水平和高水平 API

Boto3 中有几个不同的 API 与 AWS 接口。分别是:client()resource()。您需要知道的是,客户端是 AWS 的一个"低级接口,其方法与服务 API 的映射接近 1:1 ",资源是一个"比服务客户端发出的原始、低级调用更高级别的抽象"【1】要了解更多信息,这个 stackoverflow 答案给出了每个 API 的详细描述。对于这篇文章,我将使用resource(),因为它很好地抓住了基本要素,但如果你认为自己需要更多,那么较低层次的client()可能是最好的。如果你想在下面的代码中使用client(),你需要做一些小的调整。据我所见,这两个 API 之间只有细微的差别,至少我在这里展示的是这样。

亚马逊 S3 桶系统

一个目录系统,就像你的本地机器,是一个层次系统,你可能有文件夹或者子文件夹的深层目录路径,比如:/Users/your_name_most_likely/folder/sub_folder1/sub_folder2/...。亚马逊 S3 不使用目录系统。它是一个完全扁平的结构,有桶和物体。对象存储在一个桶中。当您查看 bucket 中的对象时,就像我们下面将要看到的,它看起来像一个目录或文件夹系统,但它只是一个单一的路径或文件夹对象。看起来像这样的原因是因为 S3 使用所谓的前缀和分隔符作为组织工具。因此,根据文档,您可能想要创建对象路径,如下图所示,使用前缀North America/USA/来限制结果并只返回 2 个对象路径。这就是在存储桶和对象级别进行组织的方式。这需要一点时间来适应,但过一会儿感觉就一样了。

Europe/France/Nouvelle-Aquitaine/Bordeaux
North America/Canada/Quebec/Montreal
North America/USA/Washington/Bellevue
North America/USA/Washington/Seattle

Boto3 中的一些基本步骤和命令

  • 连接到 Amazon s3

只要上面的凭证文件已经创建,您就应该能够连接到您的 S3 对象存储。

import boto3s3_client = boto3.resource('s3')
  • 创建和查看存储桶

创建存储桶时,有许多内容可以配置(位置约束、读访问、写访问等),您可以使用客户端 API 来实现。在这里,我们仍然使用上面代码块中的高级 API resource()。创建新时段后,现在让我们查看 S3 所有可用的时段。一定要注意水桶命名限制(对所有蛇案粉丝表示歉意!).

# create a bucket with given name
andre_bucket = s3_client.create_bucket(Bucket='andre.gets.buckets')# view buckets in s3
>>> for bucket in s3_client.buckets.all():
...     print(bucket.name)andre.gets.buckets
data.staging.us.east.1
data.lake.us.east.1
website.images.production
website.images.staging

你可以看到新创建的桶andre.gets.buckets(小篮球为你双关!).

  • 检视时段内的物件

现在我们已经创建了一个桶,让我们向其中添加一些对象,然后查看特定桶中的所有对象。

# point to bucket and add objects
andre_bucket.put_object(Key='andre/added/a/new/object1')
andre_bucket.put_object(Key='andre/added/a/new/object2')
andre_bucket.put_object(Key='andre/added/a/new/object3')# view objects within a bucket
>>> for obj in andre_bucket.objects.all():
...     print(obj.key)andre/added/a/new/object1
andre/added/a/new/object2
andre/added/a/new/object3

真棒。我们所有的新对象都在我们的存储桶中找到。现在,让我们面对现实吧!让我们从 S3 桶上传、下载和删除一些数据。

  • 上载、下载和删除对象

让我们上传我桌面上的一个 CSV 文件。然后,我们将再次查看存储桶中的对象,以查看是否显示新数据。

# upload local csv file to a specific s3 bucket
local_file_path = '/Users/andreviolante/Desktop/data.csv'
key_object = 'andre/added/a/new/object/data.csv'

andre_bucket.upload_file(local_file_path, key_object)>>> for obj in andre_bucket.objects.all():
...     print(obj.key)andre/added/a/new/object/data.csv
andre/added/a/new/object1
andre/added/a/new/object2
andre/added/a/new/object3

成交。我们刚刚将一个数据文件上传到了 S3 桶andre_bucket中,并将其组织在了前缀andre/added/a/new/object下,这对于你来说可能是更有意义的事情。

现在,让我们下载相同的 CSV 文件,以展示其功能。我仍然将key_object作为我的数据所在的“目录”。

# download an s3 file to local machine
filename = 'downloaded_s3_data.csv'

andre_bucket.download_file(key_object, filename)

太棒了。现在,我可以在桌面上看到一个名为downloaded_s3_data.csv的新文件。

最后,让我们删除其中一些对象。有两种方法可以真正做到这一点:1)删除特定对象或 2)删除存储桶中的所有对象。我们会双管齐下。

# delete a specific object
andre_bucket.Object('andre/added/a/new/object2').delete()>>> for obj in andre_bucket.objects.all():
...     print(obj.key)andre/added/a/new/object/data.csv
andre/added/a/new/object1
andre/added/a/new/object3

我们刚刚移除了对象andre/added/a/new/object2。现在,让我们把剩下的去掉。

# delete all objects in a bucket
andre_bucket.objects.delete()>>> for obj in andre_bucket.objects.all():
...     print(obj.key)>>>

一个很好的单一行删除所有对象内的桶!现在,由于我们有一个空桶,让我们展示如何删除一个桶。

# delete specific bucket
andre_bucket.delete()>>> for bucket in s3_client.buckets.all():
...     print(bucket.name)data.staging.us.east.1
data.lake.us.east.1
website.images.production
website.images.staging

相当简单。这是一个重要的过程,因为除非桶为空,否则不能删除桶。如果尝试,您将看到如下错误:The Bucket you tried to delete is not empty

结论

恭喜你。我们成功地使用 Boto3(用于 AWS 的 Python SDK)来访问亚马逊 S3。简单回顾一下,我们连接到亚马逊 S3,遍历桶和对象,创建桶和对象,上传和下载一些数据,然后最终删除对象和我们的桶。这些有帮助的日常命令应该让你快速启动并运行 S3,同时给你足够的知识去谷歌其他任何东西。快乐云穿越!

参考

  1. 客户资源文档
  2. Boto3 文档此处
  3. Git Repo 及所有附带代码
  4. 查看我的其他故事

pyvi 简介:Python 越南语 NLP 工具包

原文:https://towardsdatascience.com/introduction-to-pyvi-python-vietnamese-nlp-toolkit-ff5124983dc2?source=collection_archive---------20-----------------------

利用“pyvi”包进行标记化、词性标注和重音标记修改

马库斯·温克勒在 Unsplash 上的照片

在过去,我已经发表了许多与各种亚洲语言的 NLP 工具包相关的文章:

今天,让我们来更深入地探讨一下越南语。通过阅读这篇文章,您将学会通过一个名为pyvi的开源 Python 包对越南语文本进行语言分析。

在撰写本文时,pyvi提供了以下功能:

  • 标记化
  • 词性标注
  • 去除重音符号
  • 重音符号添加

让我们继续下一节,开始安装必要的软件包。

设置

在继续安装之前,建议创建一个新的虚拟环境。激活它并运行以下命令:

pip install pyvi

标记化

标记化

在本节中,您将学习对越南语文本执行标记化。创建一个新的 Python 文件,并在其中添加以下代码。

from pyvi import ViTokenizertext = 'Xin chào! Rất vui được gặp bạn.'
result = ViTokenizer.tokenize(text)
print(result)

您应该得到以下输出:

Xin chào ! Rất vui được gặp bạn .

每个令牌将由一个空格分隔。通过用空格分割文本,可以很容易地将其转换为列表:

result.split(' ')

新的输出如下:

['Xin', 'chào', '!', 'Rất', 'vui', 'được', 'gặp', 'bạn', '.']

spacy_tokenize

除此之外,pyvi确实提供了一个名为spacy_tokenize的替代功能,以便更好地与spaCy包集成。简单的叫它如下:

result = ViTokenizer.spacy_tokenize(text)

输出是一个包含以下项目的元组:

  • 令牌化令牌的列表
  • 一个布尔值列表,指示标记后面是否跟有一个空格

运行该文件时,您应该得到以下输出:

(['Xin', 'chào', '!', 'Rất', 'vui', 'được', 'gặp', 'bạn', '.'], [True, False, True, True, True, True, True, False, False])

使用索引 0 获取列表:

result[0]

词性标注

词性标注包括两个步骤:

  • 将文本标记为由空白分隔的新文本
  • 对标记化的文本执行词性标注

后标记

在对文本进行标记后,只需调用postagging函数:

from pyvi import ViPosTaggerresult = ViPosTagger.postagging(ViTokenizer.tokenize(text))
print(result)

以下文本将显示在您的终端上:

(['Xin', 'chào', '!', 'Rất', 'vui', 'được', 'gặp', 'bạn', '.'], ['V', 'V', 'F', 'R', 'A', 'R', 'V', 'N', 'F'])

同样,它包含一个具有以下项目的元组:

  • 标记化文本的列表
  • 对应于令牌的 POS 标签列表

只需遍历列表,获取令牌的相应标记:

for index in range(len(result[0])):
    print(result[0][index], result[1][index])

您应该会看到以下输出:

Xin V
chào V
! F
...

POS 标签的完整列表如下:

  • 形容词
  • C —并列连词
  • e-介词
  • I —感叹词
  • L —限定词
  • M —数字
  • n——普通名词
  • 名词分类器
  • Ny —名词缩写
  • Np —专有名词
  • Nu —单位名词
  • 代词
  • R —副词
  • 从属连词
  • T —助词、语气词
  • 动词
  • X —未知
  • F —过滤掉(标点符号)

后置标记 _ 令牌

此外,还有一个名为postagging_tokens的替代函数,它接受一个令牌列表。您可以将其与spacy_tokenize结合使用,以获得相同的输出:

tokens = ViTokenizer.spacy_tokenize(text)[0]
result = ViPosTagger.postagging_tokens(tokens)
print(result)

去除重音符号

有时,可能会出现应该从文本中删除重音符号(音调符号)的情况。在这种情况下,您可以利用remove_accents功能来帮您完成:

from pyvi import ViUtilsresult = ViUtils.remove_accents(text)
print(result)

它返回一个字节字符串:

b'Xin chao! Rat vui duoc gap ban.'

如果您希望将输出作为字符串使用,您需要做的就是根据 UTF-8 编码对其进行编码:

result.encode('utf8')

添加重音符号

另一方面,如果没有重音符号,越南语文本可能会模糊不清。使用add_accents功能将非重音文本转换为重音文本:

unaccented_text = 'truong dai hoc bach khoa ha noi'
result = ViUtils.add_accents(unaccented_text)
print(result)

输出应该如下所示:

Trường Đại học Bách Khoa hà nội

结论

让我们回顾一下你今天所学的内容。

本文首先简要介绍了pyvi中可用的特性。

然后,通过pip install进入安装过程。

它继续深入解释了一些核心功能,如标记化和词性标注。此外,本教程还介绍了关于音调符号的部分,包括删除和添加越南语文本的重音符号。

感谢你阅读这篇文章。请随意阅读我的其他文章。祝你有美好的一天!

参考

  1. Github — pyvi

R 简介

原文:https://towardsdatascience.com/introduction-to-r-318ca6dcb56?source=collection_archive---------43-----------------------

R 语言适合我吗?

克里斯·利维拉尼在 Unsplash 上的照片

有时,我喜欢浏览我所在地区的工作机会。它不仅有助于寻找新的机会,而且还提供了一个关于哪些技能是有前途的视角。尽早知道学习哪种语言对找工作至关重要。这就是我在大学的个人研究课程中创建了一个关于覆盆子 Pis 的 Kubernetes 集群的原因。这也是为什么我正在做更多 Kubernetes 的工作,现在转向虚拟机。如果你想了解更多关于这个项目的信息,我在 Kubernetes 上还有另外一个系列,你可以点击这里查看。

在挖掘各种工作时,我开始注意到,对于一些后端开发人员的工作,雇主希望至少有一点熟悉 r。因为雇主希望有一点熟悉,我认为这可能是一个不错的做法。不要深究,但让我们了解一下 R 的皮毛,了解它是什么,它是为谁制造的,为什么是 R,以及一些基本功能。

R 是什么?

r 是一种为创建图形和统计计算而构建的语言。然而,R 能做的不仅仅是计算。还有 CRAN(Comprehensive R Archive Network),它同时托管 FTP 和 web 服务器。

不仅如此,R 还可以深入机器学习。r 还可以处理数据库,连接其他语言(比如 rJava),甚至有一个 markdown 框架。

最重要的一点是,R 是一种简单易学的语言,这也是它主要面向商业领域的原因。任何技能的用户都可以学习如何创建数据的可视化表示。

r 也是多平台的。它可以在 Unix、Windows 或 macOS 上运行。

R 代表谁?

r 可以用于许多不同类型的用户。一个这样的用户是数据挖掘者。另一个是统计学家。但是 R 也可以被商业用户使用。虽然 PowerBI 变得越来越受欢迎,但 R 有更容易的学习曲线,也有更多的功能。特别是有了许多不同图表的功能,任何人都需要图表和数据的可视化表示。

为什么是 R?

如前所述,R 比许多其他数据分析工具更容易学习,同时在商业数据科学方面仍然具有广泛的能力。也提到了,R 拥有广泛的能力,不仅仅局限于分析,比如机器学习和 CRAN。

关于 r 的讨论已经够多了,是时候了解一点语法了。

数据的基本图形表示

为了安装运行 R 所需的组件,我首先必须通过命令行在我的 Ubuntu 16.04 服务器上安装一个软件包。这是为了确保我能够在 VS 代码中从终端运行命令。首先,我在终端上安装了 r base 核心包:

sudo apt-get install r-base-core

这是我让 R 在我的 Ubuntu 服务器上工作所需的唯一一行代码。现在来看 VS 代码。

首先,我安装了“R”、“R LSP Client”和“r-vscode-tools”扩展。

下载完扩展后,我创建了一个名为“rTutorial”的文件。r”。确保扩展名 R 是大写的。我们现在可以开始编码了。需要注意的是,对于我完成的每一段代码,因为需要执行 R 文件,所以我会在终端中使用以下命令:

Rscript rTutorial.R

这确保了 R 文件将执行并显示结果。我不会在每次运行代码时都使用这一行,因为都是一样的。

如前所述,我们今天不会深入研究 R。只是一些基本功能的简要概述。为了进行计算,首先,我们需要声明一个变量:

testScores <- c(92,87,58,74,90,86,86,94,82)

查看很像 Python,只需要一个 print 语句。

print(testScores)

测试分数输出。

第一个基本计算将是数据集的平均值。变量中可以有句点,我们将用它来描述下一个变量:

mean.testScores <- mean(testScores)
print(mean.testScores)

测试分数的平均值。

中值在语法上非常相似。我们可以简单地调用变量中的函数,然后显示输出:

median.testScores <- median(testScores)
print(median.testScores)

测试分数的中位数。

模式稍微难一点。这是因为它不仅可以计算整数/十进制值,还可以计算字符串值。因此,我们需要创建一个函数来查找唯一的模式值:

findMode <= function(x) {
     uniqv <- unique(x)
     uniqv[which.max(tabulate(match(x, uniqv)))]
}

现在,您可以返回正常通话:

mode.testScores <- findMode(testScores)
print(mode.testScores)

考试成绩模式。

R 的另一个有用的工具是能够容易地定位任何异常值。为此,只需查看箱线图版本并找到超出范围的值。当然,变量可以表示该值:

outVals = boxplot(testScores)$out
print(outVals)

考试分数的异常值。

您也可以选择简单地查看没有任何异常值的数据集:

testScores[ !(testScores %in% outVals) ]

没有异常值的数据集。

接下来可以快速完成的计算是正态分布。尽管通常需要更多的数学计算,R 可以简单地用一个函数来计算:

norm <- rnorm(testScores)
print(norm)

正态分布。

R 的另一个非常基本的用途是找到数据集的标准偏差。同样,不需要数学。r 也有一个函数来处理这个问题:

standDev = sd(testScores)
print(standDev)

标准差。

我们没有学到的一个重要功能是图形方面。这是因为目前我们使用命令行来执行代码,因为所有的 R 代码都在命令行中。r 文件。因为命令行中没有显示图形,所以我们没有显示这段代码。不过,我可以让你开始。对于基本柱状图,只需对数据集使用函数:

barplot(testScores)

当然,还有许多其他类型的图形、图表、直方图等等。一个方便的选择是使用 RStudio,它是一个有用户界面的程序。这不仅可以让你不断地查看变量,还可以查看任何想要的图形。例如,如果我打开 windows 桌面上已安装的 RStudio 版本,首先声明数据集:

RStudio 数据集。

现在我们可以使用柱状图功能:

测试分数柱状图。

图表的选项范围很广。您可以操作颜色、方向、添加标签等。现在,我们已经很好地开始了 R 学习,并学到了一些新东西。

结论

虽然我们没有在 R 上花太多时间,但是我们学到了很多关于它能做什么。我们了解到它主要是为统计和图形计算而构建的,并看到了它们各自的示例。我们还了解到,虽然 R 可以用于深度机器学习和数据挖掘,但它也可以成为需要数据清晰表示的业务用户的强大工具。

我希望你和我一样喜欢学习更多关于 R 的知识。下次见,干杯!

| 报名加入我的邮件列表 这里

| 参考文献

https://www.r-project.org/ https://www.business-science.io/business/2020/12/17/six-reasons-to-use-R-for-business-2021.html https://data-flair.training/blogs/why-learn-r/ https://www.tutorialspoint.com/r/r_mean_median_mode.htm http://www.r-tutor.com/elementary-statistics/numerical-measures/standard-deviation

| 看看我最近的一些文章

https://medium.com/codex/a-journey-with-kubernetes-part-4-apis-19b311290a4f https://medium.com/swlh/why-i-needed-to-graduate-college-with-no-debt-2bdcd37ccd4f https://medium.com/python-in-plain-english/3-ways-to-handle-errors-in-fastapi-that-you-need-to-know-e1199e833039 https://medium.com/python-in-plain-english/speechrecognition-in-python-df4e56fecf51

sklearn 的随机森林分类器简介

原文:https://towardsdatascience.com/introduction-to-random-forest-classifiers-9a3b8d8d3fa7?source=collection_archive---------30-----------------------

我们看到一个真正的“无位置”NBA 出现了吗?

照片由 JC GellidonUnsplash

诚然,我是 NBA 的超级粉丝,尽管我住在英国,所以我没有机会看很多比赛。这意味着我主要是通过跟踪统计数据和赛后集锦来解决问题。虽然我很遗憾我没有看尽可能多的比赛,但我喜欢分析,喜欢观看和跟踪统计数据,通常能够向任何不知情的受害者说出这些数据。鉴于这一点,我认为将我对篮球和分析的热爱结合起来,将它们融入我对数据科学的学习会很好。因此,我的一个项目是能够根据 NBA 球员的数据预测他们的位置,试图回答我们是否正在见证一个真正的“无位置”联盟的问题。

这方面的数据来自篮球参考网站[1],该网站列出了 2018-2019 赛季每个 NBA 球员的数据。使用本赛季是因为 2019-2020 赛季的比赛有限,这可能会影响任何可能进行的分析。每个球员的数据包括:比赛时间、上场时间、射门次数、射门次数等。这是典型的 NBA 统计表。当然,作为任何数据分析的一部分,必须首先清理数据。我提取的数据是本赛季所有球员的总数据,并且有一些球员在赛季中期被交易时的副本。首先要做的是删除这些重复项,并将总数转换成每分钟的统计数据,这样就不会让总数的差异影响分析。当然,这可能表明效率,而不是其他任何东西(即每分钟的点数),但它被视为性能的最佳无偏见指标。这给我留下了 22 个独立变量,从中确定位置,使用相关图,去除了几个被视为高度相关或可能使结果有偏差的变量:

corrMatrix = NBA.corr()
f, (ax) = plt.subplots(figsize=(15,15))
sns.heatmap(corrMatrix, annot=True, ax=ax)
plt.show()

作者图片

删除了“投篮命中率”、“投篮命中率”、“投篮命中率”(因为它们是 2 分和 3 分变量的集合)以及“罚球命中率”、“两分命中率”和“三分命中率”等列,因为这些也可以用罚球命中率、“2 分命中率”和“三分命中率”来表示。

之后,分析可以继续进行。这包括将数据分割成自变量和因变量,并创建一个训练测试分割,以便验证模型。

X = NBA.drop(columns = ["Pos"])
y = NBA.Posfrom sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state=42)

随机森林分类器

随机森林分类器算法是一种集成方法,它利用决策树分类器方法,但不是只创建一个决策树,而是创建多个决策树。这样做时,它利用了数据的随机采样,因为每棵树都从随机采样的数据点中学习,这些数据点是在没有替换的情况下绘制的,并且使用了在分割节点时考虑的特征的子集。生成单个树的这种随机性最小化了过度拟合的可能性,并提高了模型的整体预测准确性。这是因为最终的预测是通过平均每个个体树的预测做出的,因此遵循了群体的表现优于个体的表现的逻辑。

这样做的优点是:

  • 随机性消除了过度拟合的可能性
  • 结果可以被看作是高度准确和稳健的
  • 我们可以提取特征重要性,它告诉我们哪些变量对结果的贡献最大

当然,也有缺点:

  • 由于增加的复杂性,该模型可能比任何决策树花费更长的时间
  • 由于许多决策树的组合,与单个决策树相比,该模型可能难以解释

然而,对于这种应用,随机森林算法是一种合适的算法,因为它的复杂性,它的高度精确和稳健的能力,以及在模型中包含大量独立变量的情况下提取特征重要性的潜力。

应用

在使用随机森林分类器时,我们还希望对照基线测试结果,为此我们可以创建一个虚拟分类器,根据简单的规则做出决策,例如将所有球员归入最大类别,在本例中是得分后卫位置:

from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_score
from sklearn import metricsdc = DummyClassifier(strategy='most_frequent')
dc.fit(X_train,y_train) 
dc_preds = dc.predict(X_test)
print (metrics.classification_report(y_test, dc_preds))

作者图片

现在,我们实际上想要为我们的数据生成模型,并查看它如何比较。因此,第一件事是导入取自sklearn.ensemble模块的随机森林分类器算法。有各种各样的参数可以改变,这取决于我们想从决策树中得到什么,这里的和这里的给出了解释。出于我们的目的,我们仍将使用默认的基尼分割标准,将估计数设置为 100,以创建 100 个单独的决策树,将 oob_score 设置为 True,将 max_depth 设置为 3,以便我们稍后可以可视化一些单独的树:

#import the classifier
from sklearn.ensemble import RandomForestClassifierclf = RandomForestClassifier(n_estimators =100, oob_score=True, max_depth =3)#fit it to the training data
clf.fit(X_train, y_train)
#extract the predictions
test_pred_random_forest = clf.predict(X_test)

一旦拟合完成,我们就可以根据模型生成的预测生成混淆矩阵。这里,真实标签在 Y 轴上给出,而预测标签在 X 轴上给出:

# get the confusion matrix
confusion_matrix2 = metrics.confusion_matrix(y_test, test_pred_random_forest)#conevrt the matrix to a dataframe
matrix2_df = pd.DataFrame(confusion_matrix2)# set axis to add title and axis labels later
ax = plt.axes()
sns.set(font_scale=1.3) # for label size
plt.figure(figsize=(12,12))plot = sns.heatmap(matrix2_df, annot=True, fmt='g', ax=ax, cmap = "magma") #fmt so that numbers aren't scientific#axis labels and title
ax.set_title('Confusion Matrix - Random Forest', fontsize = 17)
ax.set_xlabel('Predicted Label', fontsize = 15)
ax.set_ylabel('True Label'     , fontsize = 15)# change tick labels from 0-4 to 1-5
labels = ("C", "PF", "PG", "SF", "SG")
ax.set_xticklabels(labels)
ax.set_yticklabels(labels)
plt.show()fig = plot.get_figure()

作者图片

由此我们可以看出,该模型在预测中锋和大前锋方面做得相对较好,主要问题是预测他们是彼此,小前锋经常与大前锋混淆,控球后卫和得分后卫之间也有一些混淆。当然,我们可以通过精确度、召回率、f1 分数和准确度指标对此进行量化,就像我们对虚拟分类器所做的那样:

print (metrics.classification_report(y_test, test_pred_random_forest))

作者图片

有关每个指标的描述,请参见此处的,但是我们可以看到,与虚拟分类器相比,该模型的整体准确性从 0.28 大幅提高到 0.63,这表明我们的模型优于简单的决策规则。然而,只有 63%的准确率,我们仍然错误地预测了 37 %,这表明我们的模型并不完美。因此,我们可以考虑如何提高模型的拟合度。

特征重要性

与单个决策树相比,随机森林分类器的好处是我们可以更仔细地检查特征的重要性。这是因为虽然单个决策树可能关注数据的特定部分,从而将高重要性与该特征相关联,即使它不一定具有高重要性,但是跨多个决策树的随机采样和特征选择允许我们识别哪些特征始终具有高重要性。通过创建多个树,我们可以使用特征的平均预测能力,以便减少在使用单个树时与特征重要性相关联的方差。

通过这种理解,我们可以删除不重要的特性并再次重新运行模型,或者简单地使用信息来理解哪些特性对模型不重要。移除特征将降低模型的复杂性,从而减少计算时间,因此权衡是从特征获得的信息与计算时间。

fi = pd.DataFrame({'feature': list(X.columns),
                  'importance': clf.feature_importances_}).\
                    sort_values('importance', ascending=True)plot = fi.plot.barh(x = 'feature', y = 'importance', figsize=(15,15))fig = plot.get_figure()

作者图片

我们的结果显示,6 个特征信息丰富,而其余 11 个特征信息不丰富。移除这些特征(如果有的话)的决定通常基于阈值(例如 1%),或者我们可以将它们与随机特征(即随机的一组数字)进行比较,如果它们的性能比它们更差,则将被移除,因为它们仅仅代表噪声。

另一种衡量方法是排列重要性,它使用随机重排来观察每个变量如何影响模型结果。这是通过训练基线模型、记录分数(在本例中为 R 分数)、然后重新排列数据集中某个要素的值并重新运行预测来实现的。这里的特征重要性是基准分数和修改分数之间的差异,因此值越高,特征对于模型越重要:

from sklearn.metrics import r2_score
from sklearn.inspection import permutation_importanceresult = permutation_importance(clf, X_test, y_test, n_repeats=10,
                                random_state=42, n_jobs=2)
sorted_idx = result.importances_mean.argsort()fig, ax = plt.subplots(figsize=(15,15))
ax.boxplot(result.importances[sorted_idx].T,
           vert=False, labels=X_test.columns[sorted_idx])
ax.set_title("Permutation Importances (test set)")
fig.tight_layout()
plt.show()

作者图片

从这里我们可以看到与特征重要性结果相似的结果,本质上显示罚球尝试和个人犯规没有给模型增加信息。

利用这一点,我们可以创建一个决策规则来丢弃模型中的结果,如果一个特性的重要性小于 1%,我们将使用这个规则。这会影响结果:

#extracting unimportant features
UIF = list(fi[fi.importance <= 0.01].feature)X_trainIF = X_train.drop(columns = UIF)
X_testIF = X_test.drop(columns = UIF)clf.fit(X_trainIF, y_train)
test_pred_random_forest_IF = clf.predict(X_testIF)train_accuracy = clf.score(X_trainIF, y_train)
test_accuracy = clf.score(X_testIF, y_test)
oob_score = clf.oob_score_print(f"The training score of the random forest classifier is : {train_accuracy:.3f}")
print(f"The out of basket score is: {oob_score:.3f}")
print(f"The test score of the random forest classifier is {test_accuracy:.3f}")print (metrics.classification_report(y_test, test_pred_random_forest_IF))

其中,在扣分、三分百分比、罚球百分比和罚球之后,模型的准确性总体上没有变化!从而降低模型的复杂性,同时不改变模型的准确性。还有一种方法可以改进这个模型。

调整超参数

我们尝试改进模型的最后一种方法是调整超参数,这些参数影响模型的工作方式和随机森林的创建。为此,我们将选择max_depthmin_samples_split,它们分别影响每个决策树可以走多远,这将增加复杂性,以及在分支可以分裂之前需要多少样本。增加最大深度会增加复杂性,但可以改进我们的模型,同样地,减少最小样本分割也是如此。鉴于我们希望能够看到我们是否能够准确预测 NBA 的位置,我们将使用网格搜索进行训练的衡量标准是整体准确性:

from sklearn.model_selection import GridSearchCVtuned_parameters = [{'max_depth': [4,5,6,7,8], 
                     'min_samples_split': [1,3,5,7,9]}]scores = ['accuracy']for score in scores:

    print()
    print(f"Tuning hyperparameters for {score}")
    print()

    clf = GridSearchCV(
        RandomForestClassifier(), tuned_parameters,
        scoring = f'{score}'
    )
    clf.fit(X_trainIF, y_train)

    print("Best parameters set found on development set:")
    print()
    print(clf.best_params_)
    print()
    print("Grid scores on development set:")
    means = clf.cv_results_["mean_test_score"]
    stds = clf.cv_results_["std_test_score"]
    for mean, std, params in zip(means, stds, clf.cv_results_['params']):
        print(f"{mean:0.3f} (+/-{std*2:0.03f}) for {params}")

作者图片

结果表明,最佳参数为max_depth =7 和min_samples_split =9。将这些输入回模型会导致:

clf = RandomForestClassifier(n_estimators =100, oob_score=True, max_depth =6, min_samples_split = 7)clf.fit(X_trainIF, y_train)
test_pred_random_forest = clf.predict(X_testIF)print (metrics.classification_report(y_test, test_pred_random_forest))

作者图片

这导致精度的总体提高,但只是从 0.63 到 0.64 的小幅度提高。

因此,使用随机森林分类器,只有 0.64 的准确性表明,使用这些统计数据,我们可以在一定程度上预测位置,但是在某些位置可能会有一些重叠,即中锋和大前锋,得分后卫和得分后卫。这可能表明联盟中存在一定程度的无位置现象,但事实是,在第一个例子中创建的混淆矩阵表明没有大前锋或中锋与控卫混淆,这可能表明我们不是在一个真正的无位置联盟中,位置根本不重要。

这个结论当然也可能受到球队本身的影响,小球的兴起意味着不需要传统的中锋,比如休斯顿(尽管他们目前有自己的问题)。还可以有更准确的统计数据,如高级统计数据,可以用来通知这一点,因此可以建议每个位置仍然可以非常明确地定义,或者甚至其他方法来分类位置!分析总是可以改进的,在未来我希望用不同的方法和潜在的更多的统计数据重新做这个分析,甚至比较这些年来位置是如何变化的!

完整代码见此处

[1]https://www . basketball-reference . com/联赛/NBA_2019_per_game.html

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

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

递归和合并排序简介

原文:https://towardsdatascience.com/introduction-to-recursion-and-merge-sort-2e143b1b7615?source=collection_archive---------15-----------------------

了解 Python 中的递归和合并排序代码

照片由 Mykyta MartynenkoUnsplash 拍摄

递归是数学和计算机科学中的一个重要概念,有多种形式。它们的本质如下:

有一个对象由它自身的较小版本组成。通常有一个最小的原子对象——这是递归结束的地方。

我们对使用递归解决问题特别感兴趣。比如对数字或其他元素进行排序,即将类似
[1, 4, 5, 2, 6, 3, 6]的输入数组变成[1, 2, 3, 4, 5, 6, 6]

这是计算机科学中的一个基本问题,许多研究人员对此进行了广泛的研究——作为数据科学家,我们应该对此感到非常高兴,因为我们一直都需要排序。仅举几个例子:

  • 使用pandas_dataframe.sort_values()numpy.sort(numpy_array)
  • 构建决策树,因为排序用于为每个特征寻找最佳分割点
  • k 最近邻算法中寻找 k 最近邻

读完这篇文章后,你将能够

  • 理解什么是递归
  • 解释合并排序是如何工作的,它是最快最简单的排序算法之一
  • 计算合并排序的运行时间

很可能你以前在很多地方见过他们。如果你足够大,也许你知道这个迷因:

艺术家未知,但图片来自 knowyourmeme.com。

或者当你第一次尝试录制屏幕时,你偶然发现了这个:

图片由作者提供。

如果你理解了这些图片,你就掌握了递归的要点。然而,让我们通过更多的数学例子来更好地感受各种形式的递归。

简单的例子

斐波那契数

作为一个例子,让我们来看一个定义众所周知的斐波那契数的递归公式:

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, …

属于这个序列的递归公式是

图片由作者提供。

如果你插上 n =1 或者 n =2,你得到 1,这是上面序列的前两个数。n2 后面的数字是前面两个数字的和。

您可以在这里看到递归特性,因为获得斐波那契数列的第 n 个数字涉及计算第( n -1)个和第( n -2)个数字。这些是较小的物体。对于 n =1 或 n =2,不再需要递归调用——这些是容易评估的原子对象。

谢尔比斯基三角

一个著名的递归形状,也被称为分形,是sierpiski 三角形。它由三角形组成,而三角形又由更小的三角形组成。然而,反过来描述这个过程更容易:你从一个大的等边三角形开始,把它砸成三个更小的三角形。然后你把三个小的打碎成更小的。重复,直到你累了。

图片由作者提供。

现在让我们转向递归的主要用例:用算法解决问题。如上所述,我们将使用排序算法 merge sort 作为工作示例。

合并排序

要找到一个递归算法来解决任何问题,总是问自己以下问题:

如果我能神奇地解决大问题中的小问题,这对我有什么帮助?我可以用这些解决方案来解决小问题,然后把它们组合起来解决大问题吗?

合并步骤

现在来说说排序数字:大问题是排序 n 个数字。应用上述问题的一种方法如下:

如果我能分别对前 n/2 个数字和后 n/2 个数字进行排序,我能把这些解放在一起得到一个完整的排序数组吗?

这将产生同一个问题的两个版本,其大小是原始问题的一半。我们来做一个例子。我们有以下要排序的数字:

初始序列。图片由作者提供。

现在,把它们分成大小相等的两堆:

把它分开。图片由作者提供。

如果我们神奇地把左半边和右半边排序:

对两个较小的数组进行排序。图片由作者提供。

我们怎样才能得到初始数组的完整排序呢?这就是我们所说的合并步骤,这就是 merge sort 的名字。

这个想法很简单:你将左堆(2)的第一个条目与右堆(1)的第一个条目进行比较。这些数字中较小的一个(1)归入结果数组。它现在只包含一个 1 。然后,您在右堆中再向右移动一步,因为您刚刚使用了那里的一个数字。****

然后,将左堆(2)的第一个条目与右堆(3)的第二个条目进行比较。这些数字中较小的一个(2)归入结果数组。现在它包含了 1,2 。然后,您在左边的中再向右移动一步,因为您刚刚使用了那里的一个数字。

然后,将左堆(4)的第二个条目与右堆(3)的第二个条目进行比较。这些数字中较小的一个(3)归入结果数组。现在包含 1,2,3 。然后,您在右堆中再向右移动一步,因为您刚刚使用了那里的一个数字。****

你自己试试吧,听起来比实际要难。既然图片胜过千言万语:

合并步骤。图片由作者提供。

递归步骤

但是我们如何神奇地对两个更小的数组进行排序呢?好吧,那就用归并排序吧!😎这就是递归的美妙之处:我们对大数组应用合并排序来对数字进行排序。在这样做的时候,在较小的数组上又调用了两次合并排序,这又总共调用了四次合并排序,依此类推。我们在推卸这个问题。但是在某些时候,我们必须交付一些东西。

那么,我们什么时候能停下来?当我们必须对包含一个数字的数组进行排序时,很容易停下来。这绝对是我们可以做到的。

听起来很复杂?让我们把它变成 Python 代码。设arr是一个包含数字的数组。然后,我们可以编写一个简单的合并排序,如下所示:

def mergesort(arr):
    n = len(arr)
    if n == 1:
        return arr # sorting a single number :) easy!
    else:
        left_sorted = mergesort(arr[:n//2])
        right_sorted = mergesort(arr[n//2:])

    return merge(left_sorted, right_sorted) # have to define merge!

又短又甜,对吧?我们只需要编写前面提到的函数merge,将两个已经排序的数组混在一起。

一个简单的方法是

def merge(left, right):
    res = [] # store fully sorted array here
    while left and right: # both arrays are not empty
        if left[0] <= right[0]:
            res.append(left.pop(0))  # take first element
        else:                        # and put it to the result
            res.append(right.pop(0))
    res = res + left + right # left or right is empty at this point
                             # just append the rest, as it is sorted
    return res

这个有点难,但是它确实在做我们之前讨论过的事情,并且可以从动画中看到。只需插入merge([1, 3, 5], [2, 4, 6])并观看它返回[1, 2, 3, 4, 5, 6]

让我们用我们的算法来看看它是否有效:

a = [82, 10, 89, 62, 77, 62, 63, 73, 95, 73, 74, 53, 14, 18, 41]

mergesort(a)

# Out:
# [10, 14, 18, 41, 53, 62, 62, 63, 73, 73, 74, 77, 82, 89, 95]

太好了!这就是你理解这个算法如何工作以及为什么工作所需要的全部。唯一的问题是这个算法实际上有多快。递归可能看起来很复杂,尤其是当你想计算运行时间的时候。我们会发现事实并非如此。

运行时间分析

我不会在这里正式介绍运行时分析和大 O 符号——相反,我们以脚踏实地的方式来做。我将使用单词步骤来描述一些简单的事情,例如

  • 比较两个元素
  • 向数组追加内容
  • 检查数组是否为空

除了别的以外。最后,我们可以这样陈述

如果问题的输入大小为 n,算法需要 T(n)步来输出解。

我们要量化这个 T ( n )。

我们的未排序输入列表中有 n 个数字。mergesort中发生的情况如下:

  1. mergesort应用到输入数组的左半部分(大小 n /2)。
  2. mergesort应用到输入数组的右半部分(大小 n /2)。
  3. 合并结果。

这直接转化为

图片由作者提供。

我们最终得到一个递归公式!看起来很复杂,但是我们会用初等数学来看如何处理它。我们唯一需要做的就是计算merge使用的步数。

那么,那里发生了什么?对于每个数字,我们

  1. 比较两个数字并
  2. 将一个数字转移到result数组中,

即每个数字 2 步。因此,merge所走的步数总共是 2 n 步。

为了使公式显式,即消除递归,让我们重复插入公式。下面的等式看起来像个怪物,但是一旦你像这样明确地写下来,模式就真的很简单了。这是我可以一直推荐的东西。

图片由作者提供。

我们可以看到递归地插入公式 k 次给我们

图片由作者提供。

对于每个 k 。这对我们有什么帮助?只要插上 k =log₂( n 就能见证神奇!首先,请注意 T (1)=1,因为如果我们输入一个大小为 1 的数组,该函数什么也不做,只是再次按原样输出它。我们得到了

图片由作者提供。

不太难,对吧?您刚刚证明了归并排序的时间复杂度大约为nlog(n)**,去掉了一些常量和无关紧要的项。

上面的陈述是更一般的主定理的一个例子。类似于我们所做的,你也可以证明这个定理,这并不困难。不要让名字欺骗了你。

结论

在本文中,我们已经看到了许多递归的例子,即

  • 公式
  • 几何形状
  • 算法

在算法方面,我们已经描述了合并排序,一种更好的排序算法。这个算法甚至可以在 NumPy 中使用,这表明合并排序不仅是一个学术上有趣的算法,也可以在实践中使用。

我们甚至可以证明,合并排序使用了大约 n log( n )步,这与众所周知的 quicksortheapsort 的数量级相同,并且比使用大约 n 步的简单排序算法插入排序要快得多。术语 n log( n )也不是随机的:它是基于比较的排序算法需要至少才能对 n 元素进行排序的下界,使得归并排序成为最优排序算法。

在我让您离开之前,这里有一个警告:这个合并排序的实现有一个问题,它需要比长度为 n 的初始数组更多的内存,因为我们在变量left_sortedright_sorted中存储了两个更小的排序列表。然而,有一些方法可以减轻这一点,但是它们让这个漂亮的算法变得更加漂亮,并且引入了其他问题,比如让它变得不稳定或者更慢。

尽管如此,这是一个有竞争力的,易于理解的算法,你现在甚至能够解释!你刚刚升级了你的数据科学游戏。

[1]卡塔杰宁,Jyrki 孙铁麟帕萨宁;朱卡·特霍拉(1996 年)。“实用就地归并排序”北欧计算杂志3(1):27–40。

我希望你今天学到了新的、有趣的、有用的东西。感谢阅读!

作为最后一点,如果你

  1. 想支持我多写点机器学习和
  2. 无论如何都要计划得到一个中等订阅量,

为什么不做 通过这个环节 ?这将对我帮助很大!😊

透明地说,给你的价格不变,但大约一半的订阅费直接归我。

非常感谢,如果你考虑支持我的话!

有问题就在 LinkedIn 上写我!

使用 PyCaret 介绍 Python 中的回归

原文:https://towardsdatascience.com/introduction-to-regression-in-python-with-pycaret-d6150b540fc4?source=collection_archive---------0-----------------------

卢克·切瑟在 Unsplash 上的照片

1.介绍

PyCaret 是一个用 Python 编写的开源、低代码的机器学习库,可以自动化机器学习工作流。这是一个端到端的机器学习和模型管理工具,可以成倍地加快实验周期,提高您的工作效率。

与其他开源机器学习库相比,PyCaret 是一个替代的低代码库,可以用来用几行代码替换数百行代码。这使得实验快速有效。PyCaret 本质上是几个机器学习库和框架的 Python 包装器,比如 scikit-learn、XGBoost、LightGBM、CatBoost、spaCy、Optuna、Hyperopt、Ray 等等。

PyCaret 的设计和简单性受到了公民数据科学家这一新兴角色的启发,这是 Gartner 首先使用的术语。公民数据科学家是超级用户,他们可以执行简单和中等复杂的分析任务,这些任务在以前需要更多的技术专业知识。

想了解更多关于 PyCaret 的信息,可以查看官方网站或者 GitHub

2.教程目标

在本教程中,我们将学习:

  • 获取数据:如何从 PyCaret 资源库导入数据。
  • 设置环境:如何在 PyCaret 中设置回归实验,开始构建回归模型。
  • 创建模型:如何创建模型、执行交叉验证和评估回归指标。
  • 调整模型:如何自动调整回归模型的超参数。
  • 图模型:如何使用各种图分析模型性能。
  • 预测模型:如何对新的/看不见的数据进行预测。
  • 保存/加载模型:如何保存/加载模型以备将来使用。

3.正在安装 PyCaret

安装很容易,只需几分钟。PyCaret 从 pip 的默认安装只安装在 requirements.txt 文件中列出的硬依赖项。

pip install pycaret

要安装完整版:

pip install pycaret[full]

4.什么是回归?

回归分析是一组统计过程,用于估计因变量(通常称为“结果变量”或“目标变量”)与一个或多个自变量(通常称为“特征变量”、“预测变量”或“协变量”)之间的关系。机器学习中回归的目标是预测连续值,如销售额、数量、温度等。

了解更多回归

5.PyCaret 中的回归模块概述

PyCaret 的回归模块 ( pycaret.regression)是一个受监督的机器学习模块,用于使用各种技术和算法预测连续值/结果。回归可用于预测值/结果,如销售额、售出单位、温度或任何连续的数字。

PyCaret 的回归模块有超过 25 个算法和 10 个图来分析模型的性能。无论是超参数调整、集成,还是堆叠等高级技术,PyCaret 的回归模块都具备。

6.教程的数据集

在本教程中,我们将使用 PyCaret 的数据集存储库中的数据集。该数据包含 6000 条用于训练的记录。每列的简短描述如下:

  • ID: 唯一标识每个观察(菱形)
  • 克拉重量:钻石的重量,单位为公制克拉。一克拉等于 0.2 克,大致相当于一枚回形针的重量
  • 切工:五个数值之一,按以下合意性顺序指示钻石的切工(签名-理想、理想、非常好、良好、一般)
  • 颜色:六个数值中的一个,表示钻石的颜色,顺序如下(D、E、F——无色,G、H、I——接近无色)
  • 净度:表示钻石净度的七个值之一,按以下顺序排列(F——无瑕疵,IF——内部无瑕疵,VVS1 或 vvs 2——非常、非常轻微,或 VS1 或 VS2——非常轻微,SI1——轻微)
  • 抛光度:表示钻石抛光度的四个数值之一(ID —理想、EX —优秀、VG —非常好、G —良好)
  • 对称性:表示钻石对称性的四个数值之一(ID —理想,EX —优秀,VG —非常好,G —良好)
  • 报告:两个值之一“AGSL”或“GIA”表示哪个分级机构报告了钻石质量
  • 价格:钻石估价的美元金额Target Column
from pycaret.datasets import get_data
dataset = get_data('diamond')

#check the shape of data
dataset.shape(6000, 8)

为了演示对看不见的数据使用predict_model函数,从原始数据集中保留了 600 条记录的样本用于预测。这不应与训练/测试分割相混淆,因为这种特定的分割是为了模拟真实场景而执行的。另一种思考方式是,在进行这个机器学习实验的时候,这 600 条记录是不可用的。

data = dataset.sample(frac=0.9, random_state=786)
data_unseen = dataset.drop(data.index)

data.reset_index(drop=True, inplace=True)
data_unseen.reset_index(drop=True, inplace=True)

print('Data for Modeling: ' + str(data.shape))
print('Unseen Data For Predictions: ' + str(data_unseen.shape))**>>> Data for Modeling: (5400, 8)
>>> Unseen Data For Predictions: (600, 8)**

7.在 PyCaret 中设置环境

setup函数在 pycaret 中初始化环境,并创建转换管道,为建模和部署准备数据。在 pycaret 中执行任何其他函数之前,必须调用setup。它有两个强制参数:一个 pandas dataframe 和目标列的名称。所有其他参数都是可选的,用于定制预处理管道(我们将在后面的教程中看到)。

当执行setup时,PyCaret 的推理算法将根据某些属性自动推断所有特征的数据类型。应该可以正确推断出数据类型,但情况并非总是如此。考虑到这一点,PyCaret 在执行setup函数后显示一个包含特征及其推断数据类型的表格。如果所有数据类型都被正确识别,可按下enter继续,或按下quit结束实验。

确保数据类型正确在 PyCaret 中非常重要,因为它会自动执行多个特定于类型的预处理任务,这些任务对于机器学习模型来说是必不可少的。

或者,您也可以使用setup中的numeric_featurescategorical_features参数来预定义数据类型。

from pycaret.regression import *
s = setup(data = data, target = 'Price', session_id=123)

成功执行设置后,它会显示包含几条重要信息的信息网格。大部分信息与执行setup时构建的预处理流水线有关。这些特性的大部分超出了本教程的范围。但是,在此阶段需要注意的一些重要事项包括:

  • session_id: 一个伪随机数,作为种子分布在所有函数中,以便以后再现。如果没有通过session_id,则自动生成一个随机数,分配给所有功能。在本实验中,为了以后的再现性,将session_id设置为123
  • 原始数据:显示数据集的原始形状。对于这个实验,(5400,8)意味着包括目标列在内的 5400 个样本和 8 个特征。
  • 缺失值:当原始数据中存在缺失值时,显示为真。对于这个实验,数据集中没有缺失值。
  • 数字特征:推断为数字的特征数量。在该数据集中,8 个要素中有 1 个被推断为数值型。
  • 分类特征:推断为分类的特征数量。在该数据集中,8 个特征中有 6 个被推断为分类特征。
  • 转换后的训练集:显示转换后的训练集的形状。注意,对于转换后的训练集,( 5400,8)的原始形状被转换为(3779,28)。由于分类编码,特征的数量从 8 个增加到 28 个
  • 转换后的测试集:显示转换后的测试/保持集的形状。在测试/保留组中有 1621 个样本。该分割基于默认值 70/30,可使用setup中的train_size 参数进行更改。

请注意,执行建模所必需的一些任务是如何自动处理的,例如缺失值插补(在这种情况下,训练数据中没有缺失值,但我们仍然需要用于未知数据的插补器)、分类编码等。setup中的大多数参数是可选的,用于定制预处理流水线。这些参数超出了本教程的范围,但是当您进入中级和专家级别时,我们将更加详细地介绍它们。

8.比较所有模型

一旦设置完成,比较所有模型以评估性能是建模的推荐起点(除非您确切地知道您需要哪种模型,而事实往往并非如此)。该函数训练模型库中的所有模型,并使用 k-fold 交叉验证对它们进行评分以进行度量评估。输出打印一个评分网格,显示平均平均平均误差、平均均方误差、RMSE、R2、均方根误差和 MAPE(默认为 10)以及每个模型花费的训练时间。

best = compare_models()

一行代码,我们已经使用交叉验证训练和评估了 20 多个模型。上面打印的评分网格突出显示了最高绩效指标,仅供比较之用。默认情况下,网格使用R2(从高到低)排序,这可以通过传递sort参数来改变。例如,compare_models(sort = 'RMSLE')将按照 RMSLE 对网格进行排序(从低到高,因为越低越好)。

如果您想将折叠参数从默认值10更改为不同的值,那么您可以使用fold参数。例如compare_models(fold = 5)将对所有模型进行五重交叉验证比较。减少折叠次数将改善训练时间。

默认情况下,compare_models根据默认的排序顺序返回性能最好的模型,但是也可以通过使用n_select参数返回前 N 个模型的列表。

9.创建模型

create_model是 PyCaret 中粒度最细的函数,通常是大多数 PyCaret 功能的基础。顾名思义,该函数使用交叉验证来训练和评估模型,交叉验证可以用fold参数来设置。输出打印出一个得分网格,按折叠显示 MAE、MSE、RMSE、R2、RMSLE 和 MAPE。

对于本教程的剩余部分,我们将使用下面的模型作为我们的候选模型。这些选择仅用于说明目的,并不意味着它们是此类数据的最佳选择或理想选择。

  • AdaBoost 回归器(“ada”)
  • 光梯度推进机
  • 决策树(“dt”)

PyCaret 的模型库中有 25 个可用的回归变量。要查看所有回归变量的完整列表,请检查 docstring 或使用models函数查看库。

models()

9.1 AdaBoost 回归器

ada = create_model('ada')

print(ada)**>>> OUTPUT** AdaBoostRegressor(base_estimator=None, learning_rate=1.0, loss='linear', n_estimators=50, random_state=123)

9.2 光梯度推进机

lightgbm = create_model('lightgbm')

9.3 决策树

dt = create_model('dt')

请注意,所有型号的平均分数与compare_models中打印的分数相匹配。这是因为打印在compare_models分数网格中的指标是所有 CV 折叠的平均分数。与compare_models类似,如果您想将折叠参数从默认值 10 更改为不同的值,那么您可以使用create_model功能中的fold参数。例如:create_model('dt', fold = 5)使用五重交叉验证创建决策树。

10.调整模型

当使用create_model功能创建模型时,它使用默认的超参数来训练模型。为了调整超参数,使用了tune_model功能。该功能在预定义的搜索空间中使用RandomGridSearch自动调整模型的超参数。输出打印出一个得分网格,按折叠显示 MAE、MSE、RMSE、R2、RMSLE 和 MAPE。要使用自定义搜索网格,您可以在tune_model函数中传递custom_grid参数。

10.1 AdaBoost 回归器

tuned_ada = tune_model(ada)

print(tuned_ada)**>>> OUTPUT** AdaBoostRegressor(base_estimator=None, learning_rate=0.05, loss='linear',n_estimators=90, random_state=123)

10.2 光梯度推进机

import numpy as np
lgbm_params = {'num_leaves': np.arange(10,200,10),
                        'max_depth': [int(x) for x in np.linspace(10, 110, num = 11)],
                        'learning_rate': np.arange(0.1,1,0.1)
                        }tuned_lightgbm = tune_model(lightgbm, custom_grid = lgbm_params)

print(tuned_lightgbm)**>>> OUTPUT**LGBMRegressor(boosting_type='gbdt', class_weight=None, colsample_bytree=1.0,
              importance_type='split', learning_rate=0.1, max_depth=60,
              min_child_samples=20, min_child_weight=0.001, min_split_gain=0.0,
              n_estimators=100, n_jobs=-1, num_leaves=120, objective=None,
              random_state=123, reg_alpha=0.0, reg_lambda=0.0, silent=True,
              subsample=1.0, subsample_for_bin=200000, subsample_freq=0)

10.3 决策树

tuned_dt = tune_model(dt)

默认情况下,tune_model会优化R2,但这可以使用optimize参数进行更改。例如,tune_model(dt, optimize = 'MAE')将搜索导致最低MAE而不是最高R2的决策树回归的超参数。在本例中,我们使用默认指标R2只是为了简单起见。选择正确的度量来评估回归变量的方法超出了本教程的范围,但是如果您想了解更多,您可以 单击此处 了解回归误差度量。

在最终确定生产的最佳模型时,度量并不是您应该考虑的唯一标准。要考虑的其他因素包括训练时间、k 倍的标准偏差等。现在,让我们向前看,把存储在tuned_lightgbm变量中的调整后的光梯度增强机器作为本教程剩余部分的最佳模型。

11.绘制模型

在模型最终确定之前,plot_model函数可用于分析不同方面的性能,如残差图、预测误差、特征重要性等。此函数接受一个经过训练的模型对象,并基于测试/保留集返回一个图。

有超过 10 个地块可用,请参见plot_model文档中的可用地块列表。

11.1 残差图

plot_model(tuned_lightgbm)

11.2 预测误差图

plot_model(tuned_lightgbm, plot = 'error')

11.3 特征重要性图

plot_model(tuned_lightgbm, plot='feature')

分析模型性能的另一种方法是使用evaluate_model功能,该功能显示给定模型所有可用图的用户界面。它在内部使用plot_model功能。

evaluate_model(tuned_lightgbm)

12.根据测试/保留样本进行预测

在最终确定模型之前,建议通过预测测试/坚持集和审查评估指标来执行最后的检查。如果您查看上面第 6 节中的信息网格,您将看到 30% (1621 个样本)的数据被分离出来作为测试/保留样本。我们上面看到的所有评估指标都是仅基于训练集(70%)的交叉验证结果。现在,使用我们存储在tuned_lightgbm中的最终训练模型,我们将预测拒不接受的样本并评估指标,以查看它们是否与 CV 结果有实质性的不同。

predict_model(tuned_lightgbm);

与在tuned_lightgbm CV 结果(见上文第 10.2 节)上获得的**0.9708**相比,测试/保持装置上的 R2 为**0.9652**。这不是一个显著的差异。如果测试/保持和 CV 结果之间存在较大差异,则这通常表明过度拟合,但也可能是由于其他几个因素,需要进一步调查。在这种情况下,我们将继续最终确定模型,并对看不见的数据进行预测(我们在开始时已经分离出来的 10%的数据,从未向 PyCaret 公开)。

13.最终确定用于部署的模型

模型定型是实验的最后一步。PyCaret 中的机器学习工作流从setup开始,然后使用compare_models比较所有模型,并列出几个候选模型(基于感兴趣的度量),以执行几种建模技术,如超参数调整、集成、堆叠等。这一工作流程最终将引导您找到用于对新的和未知的数据进行预测的最佳模型。

finalize_model函数将模型拟合到完整的数据集上,包括测试/保留样本(本例中为 30%)。此函数的目的是在将模型部署到生产中之前,在完整的数据集上训练模型。

final_lightgbm = finalize_model(tuned_lightgbm)print(final_lightgbm)**>>> OUTPUT**LGBMRegressor(boosting_type='gbdt', class_weight=None, colsample_bytree=1.0,
              importance_type='split', learning_rate=0.1, max_depth=60,
              min_child_samples=20, min_child_weight=0.001, min_split_gain=0.0,
              n_estimators=100, n_jobs=-1, num_leaves=120, objective=None,
              random_state=123, reg_alpha=0.0, reg_lambda=0.0, silent=True,
              subsample=1.0, subsample_for_bin=200000, subsample_freq=0)

警告:最后一个警告。使用finalize_model最终确定模型后,包括测试/拒绝集在内的整个数据集将用于训练。因此,如果在使用finalize_model后,该模型用于对拒绝集进行预测,则打印的信息网格将会产生误导,因为您试图对用于建模的相同数据进行预测。

为了证明这一点,我们将使用predict_model下的final_lightgbm来比较信息网格和上面第 12 节中的信息网格。

predict_model(final_lightgbm);

请注意,final_lightgbm中的 R2 是如何从**0.9652**增加到**0.9891**的,尽管型号是相同的。这是因为final_lightgbm变量是在包括测试/拒绝集的完整数据集上训练的。

14.根据看不见的数据预测

predict_model函数用于预测未知/新数据集。与上一节唯一不同的是,这一次我们将传递data_unseen参数。data_unseen是在本教程开始时创建的变量,包含原始数据集的 10% (600 个样本),该数据集从未暴露给 PyCaret。(参见第 5 节的解释)

unseen_predictions = predict_model(final_lightgbm, data=data_unseen)
unseen_predictions.head()

Label列被添加到data_unseen集合中。标签是使用final_lightgbm模型的预测值。如果您想要对预测进行舍入,您可以使用predict_model中的round参数。您还可以检查这方面的指标,因为您有一个实际的目标列Price可用。为此,我们将使用pycaret.utils模块。

from pycaret.utils import check_metric
check_metric(unseen_predictions.Price, unseen_predictions.Label, 'R2')**>>> OUTPUT** 0.9779

15.保存模型

我们现在已经完成了实验,最终确定了现在存储在final_lightgbm变量中的tuned_lightgbm模型。我们还使用了存储在final_lightgbm的模型来预测data_unseen。这使我们的实验接近尾声,但仍有一个问题要问:当你有更多的新数据要预测时,会发生什么?你必须再次经历整个实验吗?答案是否定的,PyCaret 的内置函数save_model允许您保存模型和整个转换管道以备后用。

save_model(final_lightgbm,'Final LightGBM Model 25Nov2020')Transformation Pipeline and Model Successfully Saved

**>>> OUTPUT**
(Pipeline(memory=None,
          steps=[('dtypes',
                  DataTypes_Auto_infer(categorical_features=[],
                                       display_types=True, features_todrop=[],
                                       id_columns=[], ml_usecase='regression',
                                       numerical_features=[], target='Price',
                                       time_features=[])),
                 ('imputer',
                  Simple_Imputer(categorical_strategy='not_available',
                                 fill_value_categorical=None,
                                 fill_value_numerical=None,
                                 numeric_strategy='...
                  LGBMRegressor(boosting_type='gbdt', class_weight=None,
                                colsample_bytree=1.0, importance_type='split',
                                learning_rate=0.1, max_depth=60,
                                min_child_samples=20, min_child_weight=0.001,
                                min_split_gain=0.0, n_estimators=100, n_jobs=-1,
                                num_leaves=120, objective=None, random_state=123,
                                reg_alpha=0.0, reg_lambda=0.0, silent=True,
                                subsample=1.0, subsample_for_bin=200000,
                                subsample_freq=0)]],
          verbose=False),
 'Final LightGBM Model 25Nov2020.pkl')

16.加载保存的模型

为了将来在相同或不同的环境中加载已保存的模型,我们将使用 PyCaret 的load_model函数,然后轻松地将已保存的模型应用于新的未知数据进行预测。

saved_final_lightgbm = load_model('Final LightGBM Model 25Nov2020')Transformation Pipeline and Model Successfully Loaded

一旦模型被加载到环境中,您可以使用相同的predict_model函数简单地使用它来预测任何新数据。下面我们应用了加载模型来预测我们在上面第 13 节中使用的相同的data_unseen

new_prediction = predict_model(saved_final_lightgbm, data=data_unseen)new_prediction.head()

注意unseen_predictionsnew_prediction的结果是相同的。

from pycaret.utils import check_metric
check_metric(new_prediction.Price, new_prediction.Label, 'R2')0.9779

17.总结/后续步骤?

本教程涵盖了从数据摄取、预处理、训练模型、超参数调整、预测和保存模型以备后用的整个机器学习管道。我们已经在不到 10 个命令中完成了所有这些步骤,这些命令是自然构建的,记忆起来非常直观,例如create_model()tune_model()compare_models()。在没有 PyCaret 的情况下,重新创建整个实验在大多数库中需要 100 多行代码。

我们只讲述了pycaret.regression的基础知识。在未来的教程中,我们将更深入地研究高级预处理、集成、广义堆叠和其他技术,这些技术允许您完全定制您的机器学习管道,并且是任何数据科学家都必须知道的。

感谢您阅读🙏

重要链接

教程py caret 新手?查看我们的官方笔记本!
📋社区创建的示例笔记本
📙博客投稿人的教程和文章。
📚文档py caret 的详细 API 文档
📺视频教程我们的视频教程来自各种赛事。
📢讨论有疑问?与社区和贡献者互动。
🛠️ 变更日志变更和版本历史。
🌳路线图 PyCaret 的软件和社区发展计划。

作者:

我写的是 PyCaret 及其在现实世界中的用例,如果你想自动得到通知,你可以在媒体LinkedInTwitter 上关注我。

Scikit-learn 管道介绍

原文:https://towardsdatascience.com/introduction-to-scikit-learns-pipelines-565cc549754a?source=collection_archive---------14-----------------------

使用 scikit-learn 构建端到端的机器学习管道

照片由 JJ 英Unsplash

当涉及到我们必须遵循的过程时,尝试解决机器学习问题通常是一项相当重复的任务。一般来说,当我们想要解决表格数据中的回归或分类问题时,我们遵循三个步骤:

  1. 从源读取数据
  2. 以不同的方式预处理数据
  3. 向模型提供预处理的数据

在这篇文章中,我想向初学数据的科学家展示如何使用 scikit-learn 的管道以更易读、更易维护和更容易的方式完成这些步骤。如果你不是初学者,你可能知道管道是如何工作的,以及它们带来的好处。

许多数据科学初学者倾向于在不同的代码块中使用不同的函数逐个执行每个预处理步骤。尽管这是可行的,但是这种预处理数据和创建模型的方式一点也不干净和可维护。

假设我们有一个简单的数据集,比如 scikit-learn 的葡萄酒数据集。一个初学数据的科学家可能会这样做:

如果我们仔细观察这段代码,我们会看到很多冗余的代码,因为我们两次应用了相同的转换。然而,这个代码工作正常,我们得到 97.77%的准确率。

现在,我们将使用 scikit-learn 的管道复制上面的代码。但是等等,什么是 scikit-learn 管道?

scikit-learn 管道是 scikit-learn 包提供的一个组件,它允许我们在 scikit-learn 的 API 中合并不同的组件,并按顺序运行它们。这非常有帮助,因为一旦我们创建了管道,组件就为我们做所有的 X_train 和 X_test 预处理和模型拟合,它可以帮助我们在数据转换和拟合过程中最大限度地减少人为错误。让我们看一个例子:

这种方法也能达到 97.77%的准确率,但是它比其他代码块更具可读性和可维护性。

使用该管道的一个主要优点是,我们可以将它们保存为 scikit-learn 中的任何其他模型。这些管道是估算器,因此我们可以使用 joblib 轻松地将它们与所有预处理和建模步骤一起保存到二进制文件中,一旦保存了它们,我们就可以随时从二进制文件中加载它们:

结论

正如您在上面看到的,scikit-learn 管道是一个非常强大的工具,每个数据科学家在进行任何预处理步骤之前都应该牢记在心。然而,本文仅仅触及了使用该组件可以做的事情的表面。如果您有兴趣了解更多关于管道的知识,我可能会在将来写另一篇文章,解释如何创建可以插入 scikit-learn 管道的定制预处理函数,或者如何对管道内部的组件进行一些超参数调优。

如果你喜欢这篇文章,你也可以关注我并查看我的其他文章:

情感分析简介

原文:https://towardsdatascience.com/introduction-to-sentiment-analysis-f623f7d40bfa?source=collection_archive---------11-----------------------

入门

用 Python 创建您的第一个情感分析模型

来源:flaticon(参见许可证详情)

BTS 的《炸丨药》有 11,768,848 条评论,是 YouTube 上评论最多的视频。假设一个 BTS 成员想知道这些听众对这首歌的感受。每秒阅读一条评论,仍然要花费他 4 个多月的时间。幸运的是,使用机器学习,他可以自动将每个评论标记为正面或负面。这就是所谓的情感分析。同样,通过在线评论、调查反馈和社交媒体帖子,企业可以获得大量的客户反馈。情感分析对于分析和理解这些数据变得至关重要。

在本文中,我们将介绍使用 Python 构建情感分析模型的过程。具体来说,我们将使用 SVM 创建一个单词袋模型。通过解释这个模型,我们也理解了它是如何工作的。在此过程中,您将学习文本处理的基础知识。我们会检查关键的代码片段,你可以在 GitHub 上找到完整的项目。在我们深入所有这些之前,让我们先解释一下什么是情感分析。

什么是情感分析?

情绪是某人用语言表达的想法或感觉。记住这一点,情感分析是预测/提取这些想法或感觉的过程。我们想知道一篇文章的情绪是积极的、消极的还是中性的。我们所说的积极/消极情绪的确切含义取决于我们试图解决的问题。

对于 BTS 的例子,我们试图预测听众的意见。积极的情绪意味着听众喜欢这首歌。我们可以使用情绪分析来标记我们平台上潜在的仇恨言论。在这种情况下,负面情绪意味着文本包含种族主义/性别歧视的观点。其他一些例子包括预测讽刺/挖苦,甚至一个人的意图(例如,他们是否打算购买产品)。

用 Python 进行情感分析

因此,有许多类型的情感分析模型。做情感分析也有很多方法。我们将集中应用这些方法中的一种。那就是用 SVM 创造一个单词袋模型。让我们从帮助我们做到这一点的 Python 包开始。

包装

在第 2–5 行,我们有一些标准的包,如 Pandas/NumPy 来处理我们的数据,Matplotlib/Seaborn 来可视化它。对于建模,我们使用来自 sci-kit learn 的 svm 包(第 7 行)。我们还使用一些度量包(第 8 行)来度量我们模型的性能。最后一组包用于文本处理。它们将帮助我们清理文本数据并创建模型特征。

资料组

为了训练我们的情感分析模型,我们使用了来自sensition 140数据集的推文样本。该数据集包含 160 万条被分类为正面或负面情绪的推文。您可以在表 1 中看到一些例子。

表 1:推文示例

使用下面的代码,我们加载整个数据集。1,600,000 行是一个很大的数据量,尤其是考虑到我们必须清理文本并从中创建要素。因此,为了让事情更容易管理,在第 9 行,我们随机抽取了 50,000 条推文。

文本清理

下一步是清理文本。我们这样做是为了删除文本中不重要的部分,并希望使我们的模型更加准确。具体来说,我们将使我们的文本小写,并删除标点符号。我们还将从文本中删除非常常见的词,即停用词。

为此,我们创建了下面的函数,它获取一段文本,执行上述清理并返回清理后的文本。在第 18 行,我们将这个函数应用于数据集中的每条 tweet。我们可以在表 2 中看到这个函数如何清理文本的一些例子。

注意所有清理过的 tweets 都是小写的,没有标点符号。第一条推文中的词语“有”、“是”、“关于”、“所以”、“要”、“是”和“如何”都被删除了。这些都是停用词的例子。我们预计这些词在正面和负面的推文中都会出现。换句话说,他们不会告诉我们任何关于一条推文的情绪。所以,去掉它们,我们就有希望留下传达情感的词语。

表 2:干净的 tweet 示例

接下来,思考文本清理将如何影响你的模型是很重要的。对于某些问题,停用词和标点符号可能很重要。比如生气的客户可能更容易用感叹号!!!如果你不确定,你可以把文本清理当作一个超参数。您可以使用停用词和非停用词来训练模型,并查看对准确性的影响。

特征工程(词汇袋)

即使在清理之后,像所有的 ML 模型一样,SVM 也不能理解文本。这意味着我们的模型不能接受原始文本作为输入。我们必须首先用数学的方法来描述文本。换句话说,我们必须将推文转换成模型特征。一种方法是使用 N 元语法。

N-gram 是 N 个连续单词的集合。在图 2 中,我们看到了一个例子,一个句子是如何被分解成一元语法(unigrams)和二元语法(bigrams)的。单字就是句子中的单个单词。二元模型是所有两个连续单词的集合。三元组(3 个字母)是所有 3 个连续单词的集合,依此类推。你可以通过简单地计算某些 N 元语法出现的次数来用数学方法表示文本。

图 1:一元和二元示例

对于我们的问题,我们从我们的推文中选取了 1000 个最常见的单字/双字。也就是说,我们计算这些 N 元语法在我们清理过的推文中出现的次数,并取前 1000 个。为了创建模型特征,我们然后计算这些 N 元语法在每条推文中出现的次数。这种方法被称为词汇袋

表 3 给出了使用这种方法创建的特征矩阵的例子。第一行给出了 1000 个 N-gram 中的每一个。每条推文都有一个编号行。矩阵中的数字给出了 N-gram 在 tweet 中出现的次数。例如,“抱歉”在 tweet 2 中出现一次。本质上,我们将每条推文表示为一个向量。换句话说,我们正在使用 N-gram 的计数来矢量化我们的推文。

表 3:使用词袋的特征矩阵

下面的代码用于创建这些特征矩阵中的一个。我们首先将数据集分成训练集(80%)和测试集(20%)。在第 6 行,我们定义了一个 CountVectoriser,它将使用前 1000 个一元/二元模型对我们的 tweets 进行矢量化。在第 7 行,我们用它来矢量化我们的训练集。fit_transform() 函数将首先获取 1000 个最常见的 N 元语法,然后统计它们在每条 tweet 中出现的次数。

我们遵循类似的过程来矢量化我们的测试集。在这种情况下,我们使用。transform() 函数。这将使用与训练集相同的列表来计数每个 N 元语法出现的次数。使用相同的 N 元文法列表对每个集合进行矢量化是很重要的。对测试集使用不同的列表会导致模型做出不正确的预测。

最后,我们使用最小-最大缩放来缩放特征矩阵。这确保了我们所有的功能都在同一范围内。这一点很重要,因为支持向量机可能会受到具有较大值的特征的影响。与 N 元文法列表一样,我们以相同的方式缩放这两个集合(即,使用来自训练集合的最大值和最小值)。

我们已经转换了我们的测试集,使用从训练集中获得的 N-grams 和缩放权重。如前所述,这样做是为了以相同的方式对两个集合进行矢量化。这样做也是为了避免数据泄露。在实践中,我们的模型将用于新的/看不见的推文。这些推文,以及它们的 N-gram 和重量,在训练期间是不可用的。因此,为了更好地预测未来的性能,我们的模型应该在一个被视为未知的集合上进行测试。

系统模型化

准备好我们的训练和测试集后,我们现在可以训练我们的模型了。我们在下面代码的第 2 行中做了这件事。这里我们在训练台上训练一只 SVM。具体来说,我们使用具有线性核的 SVM,并将惩罚参数设置为 1。在第 5 行,我们使用这个模型对测试集进行预测,在第 8 行,我们计算这些预测的准确性。

最终,该模型在测试集上的准确率为 73.4%。通过查看图 2 中的混淆矩阵,我们可以更深入地了解模型的性能。与 1747 个假阳性相比,有 915 个假阴性。换句话说,大多数错误来自于模型错误地将带有负面情绪的推文预测为带有正面情绪。因此,作为初稿,我们的模型还不算太差,但仍有很大的改进空间。

图 2:混淆矩阵

用于创建混淆矩阵的代码

我们可以从几个方面改进模型的性能。我们可以花更多的时间调整模型的超参数。如上所述,我们已经将惩罚参数设置为 1。这实际上是在测试了几个不同的值(即 0.001、0.01、0.1、1 和 10)并查看哪个值具有最高的 k 倍交叉验证准确性之后选择的。其他超参数,比如内核和文本清理步骤,也可以用同样的方式进行调优。我们也可以解释我们的模型,弄清楚它是如何工作的,并根据这些发现做出改变。

解读我们的模型

解释 SVM 的一种方法是查看模型权重/系数。通过训练 SVM 的过程,训练集中的每个 N 元语法被赋予一个权重。具有正权重的 n-gram 与积极情绪相关联。同样,那些负权重的人与消极情绪有关。

在图 3 中,我们看到了 1000 个 N 元图中 15 的系数。前 5 个都有很高的正系数。这是有道理的,因为你可能希望带有“开心”或“微笑”等词的推文有积极的情绪。类似地,具有负系数的词:“无聊”、“憎恨”等等……会与消极情绪联系在一起。请注意,也有 N-gram 的系数接近 0。

图 3: SVM 系数权重

用于可视化模型系数的代码

系数小的 n-gram 不会对我们模型的预测产生太大影响。系数可能很小,因为 N 元语法往往出现在带有积极和消极情绪的推文中。换句话说,它们不会告诉我们任何关于一条推文的情绪。像停用词一样,我们可以删除这些词,并有望提高模型的性能。

超参数调整和模型解释是我们可以提高准确性的许多方法中的一部分。你也可以通过尝试不同的模型,比如神经网络,得到更好的结果。你可以使用更先进的技术,比如单词嵌入,而不是单词袋,来对推文进行矢量化。有这么多的选择,希望这篇文章给你一个好的起点。

情感分析是自然语言处理中的一类问题。在下面的文章中,我将带您了解解决另一个问题的过程——语言识别。如果你对 NLP 感兴趣,我推荐你去看看。我们还建立在上面解释的许多概念之上。

图像来源

所有图片都是我自己的或从www.flaticon.com获得的。在后者的情况下,我拥有他们的高级计划中定义的“完全许可”。

参考

[1]评论最多的音乐视频(2021),【https://kworb.net/youtube/topvideos_comments.html

[2]情绪分析:权威指南(2021 年),https://monkeylearn.com/sentiment-analysis/

[3] Susan Li ,网络抓取,酒店点评的文本挖掘与情感分析(2018),https://towards data science . com/Scraping-tripadvisor-Text-Mining-and-opining-Analysis-for-Hotel-Reviews-cc 4 e 20 AEF 333

Python SHAP 简介

原文:https://towardsdatascience.com/introduction-to-shap-with-python-d27edc23c454?source=collection_archive---------0-----------------------

如何创造和解读 SHAP 情节:瀑布、力量、卑鄙的 SHAP、蜂群和依赖

更新日期:2023 年 3 月 12 日

(来源:作者)

SHAP 是理解和调试模型的最强大的 Python 包。它可以告诉我们每个模型特征是如何对单个预测做出贡献的。通过聚合 SHAP 值,我们还可以了解多个预测的趋势。通过几行代码,我们能够识别和可视化模型中的重要关系。

我们遍历用于计算和显示 SHAP 值的代码。这包括对以下 SHAP 图的解释:

  • 瀑布图
  • 力图
  • 平均 SHAP 图
  • 蜂群图
  • 依赖图

我们为预测一个连续目标变量的模型做这个。最后,我们解释了对于二元目标变量的解释是如何相似的。你可以在 GitHub 上找到完整的项目。

还有一个视频过一遍这篇文章的内容。如果你想要更多,请查看我的 SHAP 课程 注册我的 简讯 :)即可免费获取

资料组

为了演示 SHAP 包,我们将使用一个有 4177 个观察值的鲍鱼数据集。下面,你可以看到我们的数据集的快照。鲍鱼是一种美味的贝类。我们想用数据集来预测他们的年龄。更具体地说,我们的目标变量是鲍鱼壳中的数量。我们将使用鲍鱼的壳长壳径总重等特征。

(来源: UCI 机器学习库)(许可证:CC0:公共领域)

在下面的图表中,我们展示了一些特征和目标变量之间的关系。剥壳重量是鲍鱼肉的重量(即鲍鱼肉从壳中取出后的重量)。我们可以看到,环的数量随着去皮重量的增加而增加。这是有道理的,因为我们预计老鲍鱼会更大,有更多的肉。

图 1:体重和性别特征的数据探索(来源:作者)

我们还可视化了鲍鱼的性别,这是一个分类特征。在我们可以在模型中使用这个特性之前,我们需要使用一键编码来转换它。如您所见,这将为每个生成的二进制要素生成一个单独的 SHAP 值。这使得很难理解原始分类特征的总体贡献。我们在下面的文章中探索了一个解决方案。

对于数据探索的最后一点,我们为连续特征创建一个相关矩阵。你可以看到我们正在处理高度相关的特征。长度和直径完全相关。同样,整体重量与其他重量测量值高度相关。例如肉的重量(去壳重量)和除去肉的壳的重量(壳重)。

图 2:关联热图(来源:作者)

包装

我们在下面导入必要的 Python 包。我们有一些用于管理和可视化数据的标准库(第 2-5 行)。XGBoost 用于建模目标变量(第 7 行),我们导入一些包来评估我们的模型(第 8 行)。最后,我们导入 SHAP 包(第 10 行)。我们初始化包(第 11 行)。这是为了让我们可以在笔记本上显示一些 SHAP 的情节。

系统模型化

我们利用数据探索为特征工程提供信息。首先,我们从 X 特征矩阵中去掉长度和整体重量(第 10-11 行)。我们看到这些与其他特征完全相关。

我们看到是一个分类特征。在模型中使用它之前,我们需要将其转换成 3 个虚拟变量(第 2-4 行)。然后,我们从特征矩阵中删除原始特征(第 5 行)。

我们现在有 8 个模型特征。你可以在下面看到这些的快照。

(来源:作者)

我们现在可以训练一个模型来预测鲍鱼壳上的年轮数量。因为我们的目标变量是连续的,所以我们使用 XGBRegressor (第 2 行)。我们在整个特征集上训练模型(第 3 行)。

这个模型应该足以证明 SHAP 一揽子计划。我们可以通过使用图 3 中的散点图对其进行评估来了解这一点。我们将模型的预测(第 2 行)与实际的环数进行比较。红线给出了我们完美预测的值。

图 3:实际与预测环的散点图(来源:作者)

注意:我们没有在模型上投入太多精力。除非您使用 SHAP 进行数据探索,否则您应该始终使用最佳实践。你的模型越好,你的 SHAP 分析就越可靠。

SHAP 地块

最后,我们可以用 SHAP 值来解释这个模型。为此,我们将模型传递给 SHAP 解释器函数(第 2 行)。这将创建一个解释器对象。我们用它来计算特征矩阵中每个观察值的 SHAP 值(第 3 行)。

情节 1:瀑布

对于特征矩阵中的 4,177 个观察值中的每一个,都有 8 个 SHAP 值。这是我们模型中每个特征的一个 SHAP 值。我们可以使用瀑布函数来可视化第一次观察的 SHAP 值(第 2 行)。

E[f(x)] = 9.933 给出了所有 4177 只鲍鱼的平均预测年轮数。f(x) = 12.668 是这种特殊鲍鱼的预测年轮数。SHAP 值是介于两者之间的所有值。例如,去皮重量增加了预测环数 1.68

图 4:第一次观察的瀑布图(来源:作者)

在我们的数据集中,每个观察/鲍鱼都有一个独特的瀑布图。都可以用和上面一样的方式来解读。在每种情况下,SHAP 值告诉我们与平均预测相比,特征对预测的贡献如何。较大的正值/负值表示该特征对模型的预测有重大影响。

剧情 2:武力剧情

另一种可视化的方法是使用力场图。你可以认为这是一个浓缩的瀑布图。我们从相同的基值 9.933 开始,您可以看到每个特征如何影响 13.04 的最终预测。

图 5:第一次观察的力图(来源:作者)

图 3:堆叠力图

瀑布图和力量图非常适合解释个人预测。为了了解我们的模型是如何进行预测的,我们需要汇总 SHAP 值。一种方法是使用堆积力图

我们可以将多个力图组合在一起,创建一个堆叠力图。这里,我们在力图函数中传递前 100 次观察的 SHAP 值。每个单独的力图现在是垂直的,并并排堆叠。

你可以在下面看到这个情节是互动的。我们还可以更改绘图的顺序,并选择要显示的特征贡献。

图 6:交互式堆叠力图(来源:作者)

例如,在下图中,我们有:

  • 仅显示壳重量的 SHAP 值( y 轴 =壳重量影响)
  • 通过壳重量特征值( x 轴 =壳重量)命令力图

从该图中,我们可以看出,随着壳体重量的增加,SHAP 值也增加。换句话说,老鲍鱼的壳更重。

图 7:外壳重量的叠加力图(来源:作者)

这是理解我们的模型所捕捉的关系的本质的一种方式。我们将看到蜂群图和依赖图也可以这样使用。

情节 4:卑鄙的 SHAP

下一张图将告诉我们哪些特征是最重要的。对于每个特征,我们计算所有观测的平均 SHAP 值。具体来说,我们取绝对值的平均值,因为我们不希望正值和负值相互抵消。最后,我们有下面的条形图。每个功能都有一个栏。例如,我们可以看到壳重具有最大的平均 SHAP 值。

图 8:绝对均值图(来源:作者)

具有较大正/负贡献的要素将具有较大的平均 SHAP 值。换句话说,这些特征对模型的预测产生了重大影响。在这种意义上,该图可以以与特征重要性图相同的方式使用。

情节 5:蜂群

接下来,我们有一个最有用的情节。蜂群将所有的 SHAP 值可视化。在 y 轴上,值按要素分组。对于每个组,点的颜色由特征值决定(即特征值越高越红)。

图 7:蜂群图(来源:作者)

像卑鄙的 SHAP 一样,蜂群可以用来突出重要的关系。事实上,上图中的特征是由平均 SHAP 排序的。

我们也可以开始理解这些关系的本质。对于壳重,注意当特征值增加时,SHAP 值如何增加。我们在叠加力图中看到了类似的关系。它告诉我们,壳重量的值越大,预测的环数就越多。

你可能已经注意到去皮重量有相反的关系。查看蜂群图,我们可以看到该特性的较大值与较小的 SHAP 值相关联。我们可以使用依赖图来仔细观察这些关系。

图 6:依赖图

相关性图是单个特征的 SHAP 值与特征值的散点图。如果特征与目标变量具有非线性关系,它们特别有用。

例如,以壳重量的相关图为例。查看蜂群图,我们可能假设 SHAP 值随着特征值线性增加。依赖图告诉我们,这种关系并不是完全线性的。

图 8:弹壳重量的相关图(来源:作者)

我们还可以使用第二个特征的值来给散点图着色。我们现在有相同的图,去皮重量越大,点越红。我们可以看到,当壳重和去壳重都很大时,SHAP 值也很大。

图 9:用去壳重量着色的壳重相关图(来源:作者)

这些图可以用来可视化功能之间的相互作用,但要小心!在我们的例子中,情节是两个特征之间相互关联的结果。

我们也有剥壳重量(即鲍鱼肉的重量)的依赖图。使用这个图,我们可以确认我们在蜂群图中看到的关系。SHAP 值随着去皮重量的增加而降低。

图 10:去皮重量的相关图(来源:作者)

直觉上,这种关系似乎很奇怪。难道我们不会期待老鲍鱼更大,肉更多吗?事实上,这是壳重和去壳重之间的相互作用的结果。由于相关性,我们在相关性图中看不到它。在下面的文章中,我们将探讨如何使用 SHAP 互动值来识别这样的互动。

二元目标变量

二元目标变量的 SHAP 值的解释与上述类似。SHAP 值仍然会告诉我们每个因素对模型预测的贡献大小。不同的是,我们现在用对数概率进行预测。这是一个正面预测的对数几率。在图 11 中,您可以看到 SHAP 值给出了预测对数优势和平均预测对数优势之间的差异。

图 10:用对数优势解释 SHAP 值(来源:作者)

为了更好地理解这一点,让我们深入 SHAP 的情节。我们首先创建一个二进制目标变量(第 2 行)。这具有以下值:

  • 1 如果鲍鱼的年轮数高于平均值
  • 0 否则

我们使用目标变量和之前相同的特征来训练一个 XGBoost 分类器(第 5–6 行)。该模型的准确率为 96.6%

我们现在计算 SHAP 值(第 2-3 行)并显示瀑布图(第 6 行)。注意,代码与连续变量的代码相同。

如图 11 所示,即使是瀑布图也是相似的。不同的是基值现在是 E[f(x)] = -0.789 。这是所有鲍鱼的平均预测对数概率。对于这种特定的鲍鱼,模型预测其年轮数高于平均水平的概率为 0.3958 (即 P = 0.3958 )。这给了我们一个预测的对数几率为f(x)= ln(0.3958/(1–0.3958))=-0.423。

图 11:带有二元目标变量的瀑布图(来源:作者)

正 SHAP 值被解释为增加对数几率。例如,脱壳重量增加了对数几率 1.32 。此功能增加了模型预测高于平均年轮数的可能性。同样,负值会降低对数几率。

我们也可以像以前一样聚合这些值。好消息是,对《蜜蜂群》或《SHAP 均值》的解读将是一样的。你只需要记住,我们现在处理的是对数概率。

正如我们所见,SHAP 值是用来理解我们的模型如何进行预测的有用工具。然而,我们只是触及了该方案所能提供的皮毛。如果你想了解更多,我写了很多关于 SHAP 的文章。下面的文章深入探讨了 SHAP 和沙普利价值观的某些方面。

我希望这篇文章对你有帮助!如果你想看更多,你可以成为我的https://conorosullyds.medium.com/membership推荐会员来支持我。你可以访问 medium 上的所有文章,我可以得到你的部分费用。

**https://conorosullyds.medium.com/membership

你可以在|Twitter|YouTube|时事通讯上找到我——注册免费参加 Python SHAP 课程

图像来源

所有图片都是我自己的或从www.flaticon.com获得。在后者的情况下,我拥有他们的保费计划中定义的“完全许可”。

参考

南伦德伯格, SHAP 蟒包 (2021) 【T2,

南伦德伯格和 s .李,解释模型预测的统一方法 (2017 年),https://arxiv.org/pdf/1705.07874.pdf

C.Molnar,可解释机器学习(2021)https://christophm . github . io/Interpretable-ml-book/shap . html**

SQL 简介:每个数据专家必须知道的 5 个关键概念

原文:https://towardsdatascience.com/introduction-to-sql-5-key-concepts-every-data-professional-must-know-fd26ea4e6da7?source=collection_archive---------34-----------------------

用 PostgreSQL、DVD 租赁数据库和这本初学者友好的指南掌握 SQL 的基础知识。

阿德里安·匡威Unsplash 拍摄的照片

SQL 已经存在了几十年,是数据分析和查找的首选语言。随着 R 和 Python 等与数据相关的编程语言的兴起,很容易将 SQL 仅用于简单的SELECT *语句,并在以后执行过滤和聚合。虽然很诱人,但这不是最好的解决方案。

今天,您将通过大量的实践示例学习 SQL 的基础知识。您需要安装一个 PostgreSQL 数据库来跟进。

这篇文章的结构如下:

  • 数据集介绍
  • 选择数据
  • 过滤数据
  • 排序数据
  • 匹配数据
  • 连接和分组数据
  • 结论

数据集介绍

如前所述,您需要安装 PostgreSQL 数据库。您还需要 Dvd 租赁数据集,您可以通过恢复功能将其加载到您的数据库中。

Dvd 租赁数据集的 ER 图如下所示:

图 1 — DVD 租赁数据库图(来源:https://www . PostgreSQL tutorial . com/PostgreSQL-sample-database/)

在整篇文章中,您将使用客户和付款表,但是您可以自由地探索其他表格。

选择数据

对 SQL 最基本的操作是选择数据。它是用SELECT关键字完成的(不区分大小写)。如果想从特定的表中获取所有的列,可以使用SELECT * FROM <table_name>语法。同样,如果只需要特定的列,可以用列名替换星号。

让我们看几个例子来全面了解一下。

以下是如何从客户表中获取所有数据的方法:

结果如下图所示:

图 2 —来自客户表的数据(作者图片)

但是,如果您只想要客户 ID、名字和姓氏的数据,该怎么办呢?你可以这样做:

结果如下:

图 3 —来自客户表的数据—自定义列(作者图片)

指定列名而不是使用星型语法总是一个好习惯。该表的结构将来可能会改变,所以您可能会得到比预期更多的列。即使事实并非如此,选择不使用的列又有什么意义呢?

过滤数据

很可能不需要表中的所有记录。这就是过滤发挥作用的地方。您可以使用WHERE关键字过滤结果集。任何必须满足的条件都会随之而来。

以下是如何抓住不活跃的顾客:

结果如下所示:

图 4 —客户表中的非活跃客户(按作者分类)

但是如果要按多个条件过滤呢?不能再使用WHERE关键字。相反,您可以列出由AND关键字分隔的条件。

下面是如何从第一个商店(store_id 为 1)中选择所有非活动客户的方法:

结果如下:

图 5 —第一家商店的不活跃客户(图片由作者提供)

您可以在此条件后添加任意多的过滤条件;只要确保用AND关键字将它们分开。

排序数据

排序是所有分析的重要组成部分。也许你想按注册日期对用户进行分类,按到期日期对产品进行分类,或者按评级对电影进行分类——ORDER BY关键词已经涵盖了这一切。

让我们看看如何根据客户各自的 ID 对其进行排序:

结果如下所示:

图 6 —按客户 ID 排序的客户(按作者排序的图片)

如您所见,默认情况下,排序是按升序进行的。有时您希望项目从最高到最低排序(降序),因此您需要一个额外的关键字— DESC

以下是如何进行同样的排序,但按降序排列:

结果如下图所示:

图 7-按客户 ID 降序排序的客户(按作者排序的图片)

这就是数据分类的全部内容。

匹配数据

有时候你不知道你到底在找什么,但是你有一个大概的想法。例如,您可能知道感兴趣的客户的姓名以某个字母(或一系列字母)开头,但您不太确定。

这就是匹配的作用。在 SQL 中,匹配是用LIKE关键字实现的。有多种方法可以进行匹配,但我们将只讨论基本的方法。

例如,假设您只想查看名字以“An”开头的客户:

结果如下所示:

图 8-名字以“An”开头的客户(图片由作者提供)

你可以在变量的不同部分进行匹配。例如,假设您只想要那些名字以“ne”结尾的客户:

结果如下:

图片 9-名字以“ne”结尾的客户(图片由作者提供)

还有更高级的匹配操作,比如指定前后的字符数,但这超出了今天的范围。

连接和分组数据

您需要的所有数据都存储在一个表中是不太可能的。通常情况下,您必须使用连接来合并两个或多个表的结果。幸运的是,使用 SQL 很容易做到这一点。

连接有多种类型:

  • INNER JOIN–返回在两个表中具有匹配值的行
  • LEFT JOIN–返回左表中的所有行,只返回右表中匹配的行
  • RIGHT JOIN–返回右表中的所有行,只返回左表中匹配的行
  • FULL JOIN–在任一表中有匹配项时返回所有行

下面是如何使用连接来组合客户付款表,并提取每笔交易的付款金额:

结果如下所示:

图 10 —客户每笔交易支付的金额(图片由作者提供)

如您所见,每个客户都有多条记录。这是因为一条记录代表一笔交易,而一个客户可以进行多笔交易。

如果你想得到每个客户的总金额,你必须使用GROUP BY关键字和一个聚合函数。让我们来看一个例子:

结果如下所示:

图 11 —每位客户的总金额(图片由作者提供)

这里发生了什么?简而言之,您将每个名字和姓氏分成不同的组(假设每个客户都有唯一的名字),并计算每个组的总和。

有几件事可以改进。例如,现在我们返回所有完全未排序的记录。以下代码片段按总和(降序)对行进行排序,并且只保留前五行:

结果如下:

图 12 —按消费金额排名的前 5 名客户(按作者排序的图片)

您仍然可以改进这个结果集。例如,假设您想要将名字和姓氏合并为一个名为 customer_name 的列,并且您还想要将聚合列重命名为 total :

结果如下所示:

图 13 —按消费金额排名的前 5 名客户(v2)(图片由作者提供)

结论

今天,您已经学习了 PostgreSQL 环境中的 SQL 基础知识。SQL 是一个广泛的主题,您可以(也应该)学习更多。更多中高级指南即将推出,敬请期待。

总结一下——在数据库中进行尽可能多的数据过滤/聚合。这比将整个数据集拖到内存中并在那里执行过滤要快得多。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

原载于 2021 年 1 月 27 日 https://appsilon.com**的

SQL 介绍和真实生活的例子:分析你的购物习惯

原文:https://towardsdatascience.com/introduction-to-sql-with-real-life-examples-analyze-your-grocery-shopping-habits-a6c6987b61cd?source=collection_archive---------6-----------------------

作者图片

SQL 是数据科学家工具箱的基本组成部分。这是一个探索和准备数据的伟大工具,无论是用于分析还是创建机器学习模型。

学习 SQL 的一个有效方法是把重点放在你想回答的问题上,而不是放在具体的方法或函数上。一旦你知道你在寻找什么,你想用数据回答什么问题,你用来达到目的的函数和操作数将会更有意义。

本文围绕有关数据的问题展开,您将熟悉:

  • SQL 查询的结构,
  • 检查数据质量,
  • 用 SQL 过滤、汇总和组合数据。

分析你的购物习惯

你是那种喜欢记录自己日常活动的人,其中之一就是购物。最近你保留了所有的杂货店收据,这样你就可以分析你的购买模式。

创建你的购物数据库

分析你的购买模式的一个方法是使用 SQL,通过本地数据库引擎 sqlite 。你下载了 sqlite ,并使用命令行创建了一个杂货数据库。

创建杂货数据库。

现在你在 sqlite shell 中(见提示 sqlite > )。

Sqlite shell。

然后,您开始考虑如何组织来自收据的数据。您还没有考虑具体的问题,但是您知道将数据组织到两个表中:

  • 杂货店 _ 访问汇总了您去杂货店的日期、购物时间和消费金额。
  • 杂货店列表有每次逛杂货店时所买物品的名称和类别。

因此,在 sqlite shell 中,您可以使用以下命令在本地数据库中创建这些表:

create table grocery_visit(date TEXT, time_spent_min INTEGER, amount_spent REAL);create table grocery_list(date TEXT, item_name TEXT, item_category TEXT);

在 sqlite 中创建表杂货 _ 访问杂货 _ 列表

为了确保表确实被创建了,您使用命令 .tables. 进行了双重检查

检查您的表实际上是创建的。

然后你仔细检查购物清单上的每一项。

insert into grocery_list values("2020-12-03", "Hamburger patties", "Meat and Fish");insert into grocery_list values("2020-12-03", "Chips", "Pantry");insert into grocery_list values("2020-12-03", "Avocado", "Fruits and Vegetables");insert into grocery_list values("2020-12-03", "Lime", "Fruits and Vegetables");insert into grocery_list values("2020-12-03", "Tomato", "Fruits and Vegetables");insert into grocery_list values("2020-12-15", "Rice cakes", "Pantry");insert into grocery_list values("2020-12-15", "Graham crackers", "Pantry");insert into grocery_list values("2020-12-15", "Toothpaste", NULL);insert into grocery_list values("2020-12-15", "Flour", "Pantry");insert into grocery_list values("2020-12-15", "Yeast", "Pantry");insert into grocery_list values("2020-12-15", "Popcorn", "Pantry");insert into grocery_list values("2020-12-15", "Eggs", NULL);insert into grocery_list values("2020-12-15", "Milk", "Dairy");insert into grocery_list values("2020-12-15", "Bananas", "Fruits and Vegetables");insert into grocery_list values("2020-12-15", "Frozen waffles", NULL);insert into grocery_list values("2020-12-23", "Mayo", "Pantry");insert into grocery_list values("2020-12-23", "Flour", "Pantry");insert into grocery_list values("2020-12-23", "Milk", "Dairy");insert into grocery_list values("2020-12-23", "Roasted Chicken", "Meat and Fish");insert into grocery_list values("2020-12-23", "Chocolate chip cookies", "Pantry");insert into grocery_list values("2020-12-23", "Yogurt", "Dairy");insert into grocery_list values("2020-12-23", "Soda", NULL);insert into grocery_list values("2020-12-23", "Grapes", "Fruits and Vegetables");

现在你所有的购物数据都已经储存了,你可以开始提问了!

SQL 查询的剖析

在开始编写用数据回答问题的 SQL 之前,让我们来看看 SQL 查询的构造块。

您可以将查询视为过滤、转换和组合一个或多个数据集的结果。

从广义上讲,SQL 查询由两部分组成,一部分是强制的,另一部分是可选的:

  • 强制部分定义了输出,以及你从哪些数据中提取,
  • 可选部分允许您通过过滤、汇总、排序或限制输出大小来操作数据。

SQL 查询的结构。

查询的每个部分,这里编号为 1 到 6,称为一个子句,您可以使用不同的保留关键字来引用它。每个子句都允许您对手头的数据集执行特定的操作:

  1. Select 之后的所有内容 select 关键字表示您的查询的输出。这是最终的结果。
  2. 来自你正在操作的数据。它可以是一个表,也可以是另一个查询的结果,通常称为子查询内部查询
  3. 其中用于过滤数据,并指定数据需要符合的一组条件,以便生成输出。
  4. 分组依据表示您正在汇总数据,例如,对数值进行计数或求和。
  5. Order by 您希望如何对结果进行排序。
  6. 限制表示您只想显示一定数量的结果。

让我们编写一些查询,看看所有这些是如何工作的!

瞥一眼数据

数据项目的第一步是数据探索,了解你的数据。一旦你知道了你的数据,使用正确的方法或函数来回答你的问题就会容易得多。

当您探索这个数据集时,您可能会先问:

  • 我能看看所有的数据吗?
  • 我能看一眼数据吗?
  • 我能看到某一列所有可能的值吗?

我能看看所有的数据吗?

在这种情况下,你只有很少的数据,所以有可能看到所有的数据。

您可以使用 s *elect ** 来查看表格中的所有数据,即所有的行和列。

select * from grocery_visit;

通配符* 意味着您希望看到结果数据集中的所有列。但是,您可能只对少数几列感兴趣:

select date, amount_spent from grocery_visit;

仅从杂货店中选择几列 _ 访问

注意,在每个查询语句的末尾总是有一个分号。这表示查询结束,sqlite 可以继续评估查询。

即使您看到了日期金额 _ 花费列的所有数据,也很难将这些值映射到相应的列。如果您正在处理由其他人构建的数据集,这将特别方便。

在 sqlite 中,您可以调整设置以输出列名,也称为表标题

*.headers on*

因此,如果您再次运行查询,您将看到列名。

查询结果现在显示列名。

似乎是一个小细节,但现在更容易理解结果了。从现在开始,所有查询都将输出结果数据集的标题。

好吧,回到你的问题!

我能看一眼数据吗?

如果您只想看一眼您可以使用的数据,例如, limit 操作数表示将该查询的结果限制为只有 X 条记录

*select * from grocery_list limit 10;*

这将从杂货店 _ 列表表中返回前 10 条记录。

用极限操作数查看杂货店列表

检查数据质量

您只是快速浏览了一下数据,但是在开始分析之前,检查任何数据质量问题也很重要。

例如,你可能已经注意到杂货清单中的一些商品没有类别。所以你可以问我的购物清单中哪些项目没有分类?**

要检查这一点,您可以使用 where 子句并过滤输出,只包括具有 null 类别的项目。

*select * from grocery_list
where item_category is null;*

检查杂货清单中有空类别的商品。

您还可以抽查无效值,例如带有拼写错误的项目名称或其他在相关列中没有意义的值。为此,您使用了 distinct reserved 关键字,因此它将输出唯一值的列表,而不是某一列中的所有值,因为可能会有一些重复。

*select distinct item_name
from grocery_list;select distinct item_category
from grocery_list;*

项目名称项目类别的不同值。

甚至没有名字的空类别也在这里出现。

过滤您的数据

在 SQL 中,您通过在 where 子句中定义一组规则来过滤数据集。您只是用来查找具有空值的项目类别。

这只是一个简单的规则,但是你可以问其他有趣的问题。

我买过哪些不同的水果?

在这种情况下,你知道商品类别的确切名称,水果和蔬菜,但是假装你不知道😀

你有一种预感,类别名称一定涉及到水果、水果甚至其复数的某种变体。因此,您可以尝试使用操作符一样对项目类别进行模式匹配。使用这个操作符,您实际上是对任何像这样的项目类别使用过滤器。**

*select *
from grocery_list
where item_category like 'Fruit';*

对于您的具体问题,使用的方式不正确,如操作符。

但是你不能像这样使用它,因为在实践中,你所做的是一个精确的匹配,相当于使用一个等号而不是像一样使用。**

要进行模式匹配,您需要使用通配符%。这表示过滤任何名称中有水果的项目类别。由于通配符在字符串的末尾,只要它以 Fruit 开头,就会有一个匹配。

*select *
from grocery_list
where item_category like 'Fruit%';*

使用类似的操作器进行模式匹配。**

在 sqlite 中,操作符是不区分大小写的,所以条件像‘Fruit %’像‘Fruit %’产生相同的输出。

我什么时候买过牛油果和牛奶?

对于这个问题,您希望基于多个条件过滤数据集。因此您可以使用带有两条规则的 where 子句:

  • 一个给你所有你买鳄梨的日子,
  • 一个给你所有你买牛奶的日子。
*select *
from grocery_list
where item_name = 'Avocado'
or item_name = 'Milk';*

您可以用 操作符中的**重写这个 where 子句,它将根据一个项目列表过滤数据集。在这种情况下,列表只包含鳄梨牛奶。****

*select *
from grocery_list
where item_name in ('Avocado', 'Milk');*

无论您想用哪种方式过滤,都会得到相同的输出。

使用多个条件或项目列表过滤数据。

我能看到特定范围内的数据吗?

您还可以过滤数据集,以便只输出在特定值范围内的数据。

例如,您可能想要查看 12 月上半月所有的杂货店访问量。

*select *
from grocery_visit
where date >= '2020-12-01'
and date <= '2020-12-15';*

这里,您使用 where 子句中的两个条件过滤数据集,但是,如果您想让它更容易阅读,您可以使用运算符之间的**。****

*select *
from grocery_visit
where date between '2020-12-01' and '2020-12-15';*

使用 where 子句中的多个条件(左)和运算符之间的(左)过滤特定数据范围的数据集。**

汇总数据

你可能想问的另一组问题可以被看作是寻找一种总结数据的方法。

例如,你去杂货店的总结可以包括:

  • 你去杂货店的次数,使用计数 功能。
  • 使用 minmax 功能,您去杂货店的最短和最长时间是多久。
  • 使用平均 功能,你平均花了多少时间购物。
*select count(*) as total_visits
, min(time_spent_min) as shortest_visit
, avg(time_spent_min) as average_visit
, max(time_spent_min) as longest_visit
from grocery_visit;*

你逛杂货店的总结。

在你去杂货店的三次访问中,最短的用了 10 分钟,最长的用了 50 分钟,平均来说,你去杂货店大约用了 29 分钟。

通配符 ,意味着您正在计算杂货店 _ 访问表中的所有记录。*

对结果进行排序

当您浏览数据集时,对输出进行排序也很有用。

回到 SQL 查询的结构,您可以使用可选的 order by 子句来指定您希望如何对结果进行排序。然后,使用 排序术语 ascdesc ,输出按升序或降序排序。默认情况下, order by 子句按升序对输出进行排序。

我在杂货店花了多少钱?

这里您可以使用默认值,从最低到最高输出每次杂货店访问的amount _ spend

*select *
from grocery_visit
order by amount_spent;*

我可以按日期查看所有的杂货店访问吗,从最近的开始?

这里是完全相同的查询,但是指定结果按降序排序。

*select date
from grocery_visit
order by date desc;*

但是,相反,你可能只想看到你最后一次去杂货店。在这里,您可以使用到目前为止已经看到的子句和操作数。

*select *
from grocery_visit
order by date desc
limit 1;*

显示了最近一次去杂货店的次数。

组合数据

到目前为止,您一直在操作一个表。然而,大多数情况下,您需要组合多个表来获得洞察力。

在 SQL 中,使用连接操作符组合多个表。有不同类型的连接,每种连接都根据不同的规则组合两个表。

因为您也经常去百货商店,所以您决定将这些访问的数据存储在表 dept_store_visit 中。

*create table dept_store_visit(date TEXT, time_spent_min INTEGER, amount_spent REAL);insert into dept_store_visit values ('2020-12-01', 40, 45.99);
insert into dept_store_visit values ('2020-12-15', 25, 37.30);
insert into dept_store_visit values ('2020-12-19', 20, 15.82);*

根据对两家商店的访问数据,你可以提出一个非常有趣的问题。

我什么时候在杂货店或百货商店购物花费超过 15 美元?

连接通常被描述为维恩图(左图),但是您也可以考虑连接两个数据集(右图),这两个数据集可能共享也可能不共享特征,即列。

回答这个问题的一种方法是将一个表中的每条记录与另一个表中的每条记录相结合,以确保生成的数据集能够捕获两个表中的所有数据。

要做到这一点,你可以使用一个交叉连接,然后当你花费超过15 美元时,通过杂货店访问进行过滤。

交叉连接的可视化表示。

在 SQL 中,您可以编写以下查询:

*select *
from grocery_visit
cross join dept_store_visit
where grocery_visit.amount_spent > 15
and dept_store_visit.amount_spent > 15;*

默认情况下,在大多数数据库引擎中,sqlite 也不例外,您可以省略,您将获得相同的输出。

杂货店访问和部门商店访问之间的交叉连接的输出。

因为记录是多对多映射的,并且杂货店 _ 访问表只有一个大于$15 的记录,所以它最终与部门 _ 商店 _ 访问中的 3 个记录成对出现。因此,您会看到来自杂货店 _ 访问表的记录在输出中重复了 3 次。

这肯定回答了您的问题,但是输出的结构可能并不完全是您想要的。

如果输出是您去杂货店和百货商店的日期列表,那么解释起来会容易得多。就好像您附加了过滤这些表的结果一样。

为此,您可以使用联合操作符

union 运算符的可视化表示。

因为要追加每个表中的记录,所以两个表必须具有完全相同的结构,或者在执行 union 时选择结构匹配的列。

*select date, amount_spent
from grocery_visit
where amount_spent > 15unionselect date, amount_spent
from dept_store_visit
where amount_spent > 15;*

**杂货店 _ 访问百货 _ 访问的联合输出。

我在购买面包制作物品时花了多少钱?

这里,回答这个问题所需的数据存在于多个表中,因此您需要组合:

  • **杂货店 _ 访问以获得花费金额,以及
  • **杂货店 _ 列表根据面粉、酵母和鸡蛋等面包制作项目进行过滤。

您刚刚学习了交叉连接。让我们使用它!

*select *
from grocery_visit
cross join grocery_list
where grocery_list.item_name in ('Flour', 'Yeast', 'Eggs');*

如果在进行聚合之前检查生成的数据集,您会发现有些地方不太对劲。

交叉连接不是回答这个问题的最佳方式。

输出数据集确实包含了您正在寻找的所有项目,但是因为您使用了交叉连接,所以杂货店 _ 访问表中的所有记录都与您想要的杂货店 _ 列表中的记录成对出现。**

如果你现在做平均,你会看到错误的结果,因为得到的数据集实际上不是你想要的。

您真正想要的是,当您已经购买了面粉、酵母和鸡蛋时,只获得杂货店访问的数据。

谢天谢地,还有另一个连接操作符可以使用,即内部连接

通过一个内部连接,你将组合两个具有相似特征的数据集,并返回它们之间的共同点。为了使内部连接工作,两个表必须至少有一列是相同的,因为您需要指定两个表中哪个特征需要相等。

它遵循以下格式:

tableA 内部连接 tableB tableA . shared _ column = tableB . shared _ column

即使两个表有一个或多个相同的列,它们也必须有完全相同的值。否则,您的输出数据集将为空。

使用维恩图类比,您正在寻找这两个领域之间的交集。

一个内部连接的可视化表示。

要回答这个问题,您需要在逛杂货店的当天匹配两张表。

*select *
from grocery_visit
inner join grocery_list
on grocery_visit.date = grocery_list.date
where grocery_list.item_name in ('Flour', 'Yeast', 'Eggs');*

因此,看一下内部连接的结果,您会看到:

您还可以注意到,您在 2020 年 12 月 15 日购买了多种这些商品,因此那次杂货店访问的数据是重复的。但是,您只想计算 2020 年 12 月 15 日和 2020 年 12 月 23 日两次访问的平均消费金额

所以,当你计算平均花费的时候,你需要确保你不会多次计算数值。你可以使用独特的 关键字来处理这个问题。

*select avg(distinct amount_spent) as avg_amount_spent
from grocery_visit
inner join grocery_list
on grocery_visit.date = grocery_list.date
where grocery_list.item_name in ('Flour', 'Yeast', 'Eggs');*

你在杂货店购买面粉、酵母和鸡蛋的平均花费。

但是你可能会说,如果不同的杂货店消费相同的金额会怎么样?**

回到 SQL 查询的剖析,from 子句的可以像您到目前为止所做的那样直接从一个表中提取数据,或者从另一个查询(称为子查询)的结果中提取数据。**

确保你去过所有不同的杂货店购买面粉、酵母和鸡蛋,但也要考虑到:

  • 在同一天发生的访问,但是花费了不同的金额,
  • 不同日期的访问,花费完全相同。

您可以将该逻辑封装在一个子查询中,然后进行平均。这样你就能保证不会多算或少算任何一次去杂货店的次数。

*select avg(amount_spent) as avg_amount_spent
from
(
    select distinct grocery_visit.date, amount_spent
    from grocery_visit
    inner join grocery_list
    on grocery_visit.date = grocery_list.date
    where grocery_list.item_name in ('Flour', 'Yeast', 'Eggs');
)*

由于您已经根据感兴趣的项目进行了筛选,并且您担心每次访问中没有过多或过少地计算支出,因此您可以忽略子查询中【杂货店 _ 列表】的所有列。

在我去杂货店的日子里,我也去百货商店吗?如果是,我在这些访问中花了多少时间?

在这个问题中,很明显您想要组合杂货店 _ 访问部门 _ 商店 _ 访问表中的数据。

但是主要的焦点是去杂货店。

你将使用一个左连接来回答这个问题。

使用维恩图类比,您将需要杂货店 _ 访问中的所有数据,并且只需要来自部门 _ 商店 _ 访问的与杂货店访问日期匹配的记录。

左连接的可视化表示。

你可以把左连接想象成把所有东西都放在左边(表),只从右边(表)取出匹配的东西。**

*select grocery_visit.*
, dept_store_visit.time_spent_min as time_spent_dept_store
, dept_store_visit.amount_spent as amount_spent_dept_store
from grocery_visit
left join dept_store_visit
on grocery_visit.date = dept_store_visit.date;*

这里杂货店 _ 参观。** 表示输出包含来自*杂货 _ 访问的所有列。**

根据访问日期,杂货店 _ 访问部门 _ 商店 _ 访问的左连接输出。

你也可以反过来想这个问题在我去百货公司的那几天,我是不是也去了杂货店?如果是,我在这些访问中花了多少时间?**

大多数数据库引擎支持右连接,听起来正是左连接的反义词。然而,sqlite 不支持右连接

右连接的可视化表示。

与右加入你保持一切在右边(表),只带火柴在左边(表)。实际上,这意味着翻转最后一个查询中的另一个表。

让您的输出可以用别名来解释

您可能还注意到,在最后一个查询中, dept_store_visit 的输出与原始的列名不同。那是因为我们用了一个别名。

别名使得引用具有更易理解的名称的表和子查询变得更加容易。在这种情况下,我们使用别名将输出列重命名为与其他表中的列不同的名称。

您已经全面了解了 SQL 查询的基础知识!但是不要担心,它不一定要在这里结束,您可以使用高级 SQL 函数和操作数提出许多更微妙的问题。

希望这篇文章让你对 SQL 和如何用数据回答问题感到好奇。

感谢阅读!

生存分析导论

原文:https://towardsdatascience.com/introduction-to-survival-analysis-in-cows-using-r-28b82c2821fb?source=collection_archive---------21-----------------------

在使用 R

我的背景是心理学和生命科学,这意味着你迟早会处理生存分析。特别是在我读博士期间,我评估了数百篇关于癌症干预的论文,最感兴趣的结果是生存率——总生存率、无病生存率、复发生存率。

在农业领域,情况有所不同,我很少看到进行生存评估,尽管有很大的空间。本质上,生存分析是事件分析的一个更性感的术语,这就是它的全部——事件分析。

因此,要开始进行事件分析或生存分析,您只需要两个变量:

  1. 时间的数字度量,如天数。
  2. 事件的分类标识符,通常标记为 0 或 1。

结合起来,这两个变量可以表明:

  1. 如果感兴趣的主题遇到了感兴趣的事件(绝对可以是任何事情!)还是没有。
  2. 感兴趣的受试者是否以及何时进入研究。
  3. 如果感兴趣的受试者离开研究

这就是我们进入 审查 的领域,这在事件分析中可能是最难理解的部分。当在观察框架(研究的结束-开始)中观察到事件时,我们对感兴趣的受试者有时间变量和事件变量。然而,对于其他人,我们可能没有确切的开始日期和/或我们可能永远不会观察到事件。这两个问题分别导致左右审查。右删截要常见得多,为了简洁起见,我们现在将离开区间删截。

请记住,当您想要进行事件分析时,您的数据集需要有事件时间(或无事件时间)和事件的列。算法会为你找出审查!

让我们加载必要的包来执行生存分析。

然后进行必要的数据讨论,包括标准化的协变量。

这里你可以看到用来进行生存分析的数据集。对于每头牛,我们都有一个 SurvivalTime 指标和一个 Vstatus (event)指标。其余的是利益和潜在价值的协变量。

值得注意的是,在事件分析中,重要的是事件的数量,而不是观察的数量或观察花费的时间。如果没有感兴趣的事件,分析就毫无意义!

寻找潜在利益因素存活时间差异的第一批图。

事件在一段时间后开始发生,这些变量之间似乎存在差异。图片作者。

现在,开始分析事件最直接的方法是使用卡普兰-迈耶方法。这是一种非参数方法,基本上意味着它并不真正关心任何潜在的模型假设。只要数据集有它需要的东西(观察到的时间和事件),就可以开始了。在这里,我们开始询问生命表和简单的事件分析。结合起来,它们将根据观察到的时间-事件组合,为您提供在特定时间点幸存的总体概率。

生命表和事件曲线来观察在特定时间点存活的概率。图片作者。

一年后,发生了 9 起事件,导致 64%的生存概率[48% — 86%]。

生命表是评估是否有足够的事件进行事件分析的好方法。如果是这样,你可以转到感兴趣的分析,这是治疗之间的事件曲线的比较。在卡普兰-迈耶模型中,通过对数秩检验进行比较,这是另一种非参数方法。

治疗之间似乎有统计学上的显著差异,但治疗-2 的巨大置信区间并没有对 p 值的价值给予很大的信任(这通常值得很多不信任)。图片作者。

一旦你抛开卡普兰-迈耶,转而采用 Cox 回归——也称为比例风险模型,事件分析就变得非常有趣。Cox 回归是一种半参数方法,能够包含多个预测因子。半参数意味着它关心假设,但不需要截距或基线风险。考克斯回归的问题在于,它很容易打破自己的假设,尤其是给它起了个名字的假设——比例风险假设。

但是,我们还没有讨论什么是危险。危险通常是一种风险,更具体地说,是在任何给定的时间点从非事件转变为事件的风险。因此,这是遇到感兴趣事件的风险,与时间无关。这就是为什么使用 Cox 回归几乎不切实际的原因,但不管怎样,让我们继续吧。在以后的文章中,我将讨论更多关于应用参数模型和处理这种假设的方法。

进行 Cox 回归的代码并不难。

下面的总结是回归输出,毫无疑问。我们看到我们有 43 个感兴趣的对象,并观察了 22 个事件。对于每个感兴趣的因素,我们得到几个输出:

  1. 系数——对数标度上的估计危险系数
  2. exp(coef) —危险比(HR)。在这里,4.9 意味着 490%。因此,治疗 2 ,与治疗 1 相比,增加了几乎 500%的危险!
  3. exp(-coef) — 逆危险比,即治疗 1 的 HR。

一致性统计是用于事件分析的 ROC 统计。似然性、Wald 和评分测试表明,该模型优于不含预测因子的模型。这个消息与之前的试探性情节一致。

要求方差膨胀因子(VIF)以检测严重的交叉相关性/相互依赖性,这通常会导致标准误差或不收敛。

风险比、置信区间和 P 值。图片作者。

所以,到目前为止,一切似乎都很简单,这实际上是生存分析中最大的问题——它真的没有那么难。但是,我们也说过,通过从非参数方法转移到半参数方法,我们有一些假设要研究,这是我们现在要做的。要检查的最重要的假设是危险比例(PH)假设。我们将通过查看舍恩菲尔德残差和绘制每个预测值的累积双对数曲线来实现这一点。

您需要的是:

  1. 累积双对数曲线间的比例距离。
  2. 残差的均匀性。

PH 值假设似乎适用于 TREAT、INF 和 Ca4,但对其他两种则让我感到困扰。舍恩菲尔德残差看起来很干净。图片作者。

接下来,我们将通过绘制鞅残差来看看线性假设。

这里没什么可奇怪的。图片作者。

然后,我们将看一看感兴趣的有影响力的主题。

一些观察似乎是有影响的,但由于只有 43 个受试者感兴趣,我很难删除任何没有显示生物学不相容数据的受试者。图片作者。

Cox 回归和假设评估似乎暗示了两个可能引起问题的预测因子。我现在要做的是使用 L1 和 L2 的惩罚方法来看看他们实际上对数据有多少贡献。这些代码已经有 5 年的历史了,所以我确信现在有更多的自动化方法,但是它们仍然可以运行!

让惩罚方法运行起来的代码还真不少。

惩罚暗示了兴趣的三个预测因素。图片作者。

第二种方法与第一种方法一致。图片作者。

不感兴趣的系数也是不符合 PH 假设的系数。这是有意义的——任何使模型不稳定的预测器都将被引导到重采样方法中,重采样方法侧重于限制过度拟合的可能性。

最后但同样重要的是,让我们疯狂一点,仅用三个感兴趣的预测因子重新调整 Cox 回归,并多次对分析进行重新采样。通过这种方式,我们可以很好地了解高于和超出从 Cox 回归本身得到的分布置信区间的风险比的稳定性(顺便说一下,已经显示了一些较大的置信区间)。

有很多代码要运行,但它是有效的。最后,我让 R 对 Cox 回归进行重采样,并将其所有输出存储在一个适合绘图的数据帧中。

基于 Bootstrapping 的风险比的偏斜分布。因此,应该非常仔细地考虑每个 HR 的点估计值。图片作者。

Jack-knife 评估着眼于感兴趣的主题的个人贡献。您希望这些图沿着水平线。图片作者。

我希望这篇文章将通过包括 Kaplan-Meier、Cox 回归、惩罚回归和 Bootstrapping 技术来评估数据集的价值,从而帮助你走上事件分析之路。

请记住,这是关于事件,而不是观察的数量!

尽情享受吧!

合成少数过采样技术及其从头实现

原文:https://towardsdatascience.com/introduction-to-synthetic-minority-over-sampling-technique-and-its-implementation-from-scratch-77593647c10d?source=collection_archive---------10-----------------------

Piret IlveronUnsplash

一种从不平衡数据集中构造分类器的方法

不平衡数据集

如果分类标签没有被同等地表示,则数据集是不平衡的,因此 100 比 1 数量级的不平衡在诸如欺诈检测的大量真实世界场景中是常见的问题。已经进行了大量的尝试来解决这个问题。然而,这个问题仍然被广泛讨论和研究。在本文中,我想谈谈在这种情况下使用的一种简单而有趣的方法。为了让它更有趣,我想讨论一下它可能的应用和实现。

模型的性能通常通过其预测准确性来评估。然而,当处理不平衡数据集时,这是不合适的。让我们考虑下面的例子

不平衡二分类问题的散点图

在上面的玩具数据集中,有 9900 个样本属于类别 0,而后者只有 100 个样本,比例为 1:100。假设您正在使用上述数据集训练您的模型,而不考虑分布。处理不平衡数据集时发生的最大问题是模型变得偏向主导类。因此,对于一个模型来说,给每个样本分配一个标签 0 以达到 99%的准确率并不困难。然而,重要的是使用不同的度量标准,这可以给你更多的洞察力。如果我们的任务是分类垃圾邮件,我们的模型将完全无用。当然,获得更多的数据总是更好的;然而,这可能极其困难。

处理不平衡数据

有不同的方法来解决这个问题。一些常见和简单的是欠采样和过采样。大多数情况下,过采样优于欠采样技术,因为通过移除数据,我们可能会丢失一些重要特征。然而,随机过采样可能导致过拟合,这是另一个问题。也可以两者并用,实现相对平衡的数据。然而,我想介绍一个简单而有趣的算法,它允许我们生成合成数据。

SMOTE:合成少数过采样技术

SMOTE 是一种过采样技术,允许我们为少数类别生成合成样本。下面的算法描述了 SMOTE 的工作原理。请慢慢理解。

SMOTE 算法摘自这篇论文。

正如我们所看到的,这个想法是基于 K-最近邻算法。如果你不熟悉,我会附上我的文章,以及它的 Python 实现:)。因此,我们得到一个样本和它的 k 个最近邻之一之间的差,并乘以(0,1)范围内的某个随机值。最后,我们通过添加从前面的操作中获得的值来生成一个新的合成样本。

SMOTE 变换的不平衡二分类问题散点图

上图显示了我们应用 SMOTE 后的数据集。现在,每个类别有 9900 个样本。

为什么它对我有意义

如果您有图像分类的经验,图像增强是一种用于获取更多训练样本的非常常见的技术。然而,假设一个模型试图将一幅图像转换到某个高维空间,一个增强的样本应该落在它的原始样本附近的某个地方。因此,在 SMOTE 的情况下,合成样本将等同于增强图像。然而,毫无疑问,收集更多的数据更好,因为它有助于收集特定对象的更广泛的表示。

履行

我附上我为 Pytorch 编写的 SMOTE 实现。这很容易翻译成数字。

一些应用

假设,您正在使用嵌入开发一个推荐系统,并且您能够检索与一个人喜欢的项目相关联的嵌入。然而,没有足够的关于某个用户的数据来产生一些有意义的推荐。因此,您可以使用现有的嵌入和生成合成嵌入,并计算更有用的推荐。因此,你可以想象使用 SMOTE 作为某种测试时间增加(TTA)。

一些遗言

如果分类标签没有被同等地表示,则数据集是不平衡的,因此 100 比 1 数量级的不平衡在诸如欺诈检测的大量真实世界场景中是常见的问题。已经进行了大量的尝试来解决这个问题。然而,这个问题仍然被广泛讨论和研究。今天,您将了解一个简单而有趣的算法来生成合成样本。其实 SMOTE 版本有很多种。您可以查看更多不同版本的 SMOTE 算法,并比较它们相对于原始版本的优势。上面的实现可以很容易地在我的 GitHub 上找到。

SMOTE:合成少数过采样技术

相关文章

</5-smote-techniques-for-oversampling-your-imbalance-data-b8155bdbe2b5>

张量流概率简介

原文:https://towardsdatascience.com/introduction-to-tensorflow-probability-6d5871586c0e?source=collection_archive---------3-----------------------

用张量流概率建立贝叶斯神经网络不应错过的关键模块

照片由 cyda

目标

在前面的文章中,我们讨论了贝叶斯神经网络(BNN)的概念及其背后的数学理论。对于那些刚到 BNN 的人,确保你已经检查了下面的链接。

</8-terms-you-should-know-about-bayesian-neural-network-467a16266ea0>

今天,我们将探索使用张量流概率来实现 BNN 模型的概率规划。从本文中,您将学习如何使用张量流概率来

  1. 构建不同的发行版并从中取样。
  2. 使用双射函数转换数据。
  3. 概率层与 Keras 结合起来构建 BNN 模型。
  4. 推论并说明不同类型的不确定性

什么是张量流概率?

TensorFlow Probability (TFP)是 TensorFlow 中用于概率推理和统计分析的库。它提供了概率方法与深度网络的集成,使用自动微分的基于梯度的推理,以及通过硬件加速(GPU)和分布式计算对大型数据集和模型的可扩展性。事实上,TFP 是一个综合的工具,由许多模块组成,包括概率层、变分推理、MCMC、Nelder-Mead、BFGS 等。但我不会深入所有模块,只会挑选和演示其中的一部分。如果你想知道更多的细节,请查看下面的技术文档。

https://www.tensorflow.org/probability

分布

作为概率编程包,TFP 支持的关键模块之一是不同种类的统计分布。老实说,我不得不说 TFP 做得非常好,它覆盖了相当多的发行版(包括很多我不知道是什么的发行版,哈哈)。经过统计,我发现截至 2021 年 10 月,已经提供了 117 个发行版。我不打算在这里列出他们的名字。更多细节,可以查看他们的 api 文档这里

今天,我想和大家分享一些我认为有用的功能。在下面,我将使用二项式作为说明。

import tensorflow_probability as tfp
tfd = tfp.distributionsn = 10000
p = 0.3
binomial_dist = tfd.Binomial(total_count=n, probs=p)

1。样本数据

假设我们想从刚刚创建的二项分布中抽取 5 个样本。您只需使用 样本 方法,并指定您想要抽取的样本数量。

binomial_dist.sample(5)

< tf。张量:shape=(5,),dtype=float32,numpy = array(
【3026。, 3032., 2975., 2864., 2993.],dtype=float32) >

2。汇总统计数据

另一个很酷的特性是获取汇总统计数据。对于像二项式这样的简单分布,我们可以很容易地通过下式得出统计数据

照片由 cyda 拍摄

然而,对于一些复杂的分布,计算统计数据可能并不容易。但是现在你可以简单地利用这些工具。

mu = binomial_dist.mean()
std = binomial_dist.stddev()
print('Mean:', mu.numpy(), ', Standard Deviation:', std.numpy())

均值:3000.0,标准差:45.825756

3.概率密度函数(PDF)

要找到给定的 x 的 PDF,我们可以使用 prob 的方法。

x = 3050
pdf = binomial_dist.prob(x)
print('PDF:', pdf.numpy())

PDF: 0.004784924

import matplotlib.pyplot as plt
fig = plt.figure(figsize = (10, 6))
x_min = int(mu-3*std)
x_max = int(mu+3*std)
pdf_list = [binomial_dist.prob(x) for x in range(x_min, x_max)]
plt.plot(range(x_min, x_max), pdf_list)
plt.title('Probability Density Function')
plt.ylabel('$pdf$')
plt.xlabel('$x$')
plt.show()

cyda 拍摄的照片

4。累积密度函数

要找到给定 x 的 CDF,我们可以使用方法 cdf

x = 3050
cdf = binomial_dist.cdf(x)
print('CDF:', cdf.numpy())

CDF: 0.865279

fig = plt.figure(figsize = (10, 6))
x_min = int(mu-3*std)
x_max = int(mu+3*std)
cdf_list = [binomial_dist.cdf(x) for x in range(x_min, x_max)]
plt.plot(range(x_min, x_max), cdf_list)
plt.title('Cumulative Density Function')
plt.ylabel('$cdf$')
plt.xlabel('$x$')
plt.show()

cyda 拍摄的照片

5。对数似然

我想介绍的最后一个方法是 log_prob 。这用于计算对数似然。根据前两篇文章,我想每个人都会意识到这有多重要,因为我们总是用它作为损失函数。因此,要找到对数似然,我们只需调用

x = 3050
l = binomial_dist.log_prob(x)
print('Log-likelihood:', l.numpy())

对数可能性:-5.342285

fig = plt.figure(figsize = (10, 6))
x_min = int(mu-3*std)
x_max = int(mu+3*std)
l_list = [binomial_dist.log_prob(x) for x in range(x_min, x_max)]
plt.plot([j for j in range(x_min, x_max)], l_list)
plt.title('Log-Likelihood')
plt.ylabel('$l$')
plt.xlabel('$x$')
plt.show()

cyda 拍摄的照片

双喷射器

双射体是由张量流命名的术语,基本上是指双射变换。根据定义,双射变换是两个集合的元素之间的函数,其中一个集合的每个元素恰好与另一个集合的一个元素配对,而另一个集合的每个元素恰好与第一个集合的一个元素配对。

对我来说,我会把双对象看作是现成的数据转换函数。在这里你可以找到很多常用的函数,比如LogExpSigmoidTanhsoft plussoft sign等等。

您可以简单地用下面的代码调用 bijector。

tfb = tfp.bijectors
exp = tfb.Exp()

要应用转换,只需将值传递给对象。

import numpy as np
x = np.linspace(-3, 3, 100)
y = exp(x)fig = plt.figure(figsize = (10, 6))
plt.plot(x, y)
plt.title('Exponential Transform')
plt.ylabel('$exp(x)$')
plt.xlabel('$x$')
plt.show()

cyda 拍摄的照片

我想分享一个小技巧,有一个名为 Chain、 的双射器,用于应用一系列双射器。例如,如果我们想将 x 传递给 softplus 函数,然后传递给 exp 函数。我们可以这样写

exp = tfb.Exp()
softplus = tfb.Softplus()
chain = tfb.Chain([exp, softplus])

这样做相当于

cyda 拍摄的照片

x = np.linspace(-3, 3, 100)
y_chain = chain(x)
y_exp = exp(x)fig = plt.figure(figsize = (10, 6))
plt.plot(x, y_chain, label = 'Chain')
plt.plot(x, y_exp, label = 'Exp')
plt.title('Exponential Transform')
plt.ylabel('$exp(x)$')
plt.xlabel('$x$')
plt.legend()
plt.show()

cyda 拍摄

tfp.layers 模块通过将原来的层替换为概率层,为开发人员建立了一个用户友好的界面,方便他们将模型从标准神经网络切换到贝叶斯神经网络。在下面,我将列出一些我经常使用的层作为参考。

  • 认知的不确定性
  • 独立正态 : 随机不确定性
  • 分布λ:随机不确定性

1。创建数据集

因此,为了训练 BNN 模型,首先,我们必须创建数据集。

def create_dataset(n, x_range, slope=2, intercept=10, noise=0.5):
    x_uniform_dist = tfd.Uniform(low=x_range[0], high=x_range[1])
    x = x_uniform_dist.sample(n).numpy().reshape(-1, 1)
    y_true = slope*x+intercept
    eps_uniform_dist = tfd.Normal(loc=0, scale=1)
    eps = eps_uniform_dist.sample(n).numpy().reshape(-1, 1)*noise*x
    y = y_true + eps
    return x, y, y_truen_train = 5000
n_val = 1000
n_test = 5000
x_range = [-10, 10]
x_train, y_train, y_true = create_dataset(n_train, x_range)
x_val, y_val, _ = create_dataset(n_val, x_range)
x_test = np.linspace(x_range[0], x_range[1], n_test).reshape(-1, 1)

样本数据实际上是一个线性拟合,带有一个异质方差以及 x 的值。为了更好地可视化,您可以使用以下代码进行绘图。

def plot_dataset(x_train, y_train, x_val, y_val, y_true, title):
    fig = plt.figure(figsize = (10, 8))
    plt.scatter(x_train, y_train, marker='+', label='Train')
    plt.scatter(x_val, y_val, marker='+', color='r', label='Val')
    plt.plot(x_train, y_true, color='k', label='Truth')
    plt.title(title)
    plt.xlabel('$x$')
    plt.ylabel('$y$')
    plt.legend()
    plt.show()plot_dataset(x_train, y_train, x_val, y_val, y_true, 'Dataset')

cyda 拍摄的照片

2.标准神经网络

在训练 BNN 之前,我想制作一个标准的神经网络作为比较的基线。

import tensorflow as tf
tfkl = tf.keras.layers# Model Architecture
model = tf.keras.Sequential([
    tfkl.Dense(1, input_shape = (1,))
])# Model Configuration
model.compile(optimizer=tf.optimizers.Adam(learning_rate=0.01), loss=tf.keras.losses.MeanSquaredError())# Early Stopping Callback
callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=30, min_delta=0, mode='auto', baseline=None, restore_best_weights=True)# Model Fitting
history = model.fit(x_train, y_train, validation_data=(x_val, y_val), epochs=1000, verbose=False, shuffle=True, callbacks=[callback], batch_size = 100)

正如你可能观察到的,简单模型只设置了一个 密集 隐藏层,为了检查模型的执行情况,我们可以使用 预测 方法。

y_pred = model.predict(x_test)
fig = plt.figure(figsize = (10, 8))
plt.scatter(x_train, y_train, marker='+', label='Train')
plt.plot(x_train, y_true, color='k', label='Truth')
plt.plot(x_test, y_pred, color='r', label='Predict')
plt.legend()
plt.title('Standard Neural Network')
plt.show()

cyda 拍摄的照片

看起来,预测与预期的真实线性线相匹配。然而,使用 SNN 不能告诉预测的不确定性。

3.贝叶斯神经网络

所以就到了主菜。让我们一步一步地讨论代码。

3.1 模型架构

tfpl = tfp.layersmodel = tf.keras.Sequential([
    tfkl.Dense(2, input_shape = (1,)),
    tfpl.DistributionLambda(lambda t: tfd.Normal(loc=t[..., :1], scale=1e-3+tf.math.abs(t[...,1:])))
])

你可能会注意到,我们将有一个 密集 层输出两个神经元。你能猜出这两个参数是干什么用的吗?它们是均值标准差,将被传递给我们在 分布层 中指定的正态分布。

3.2 车型配置

negloglik = lambda y_true, y_pred: -y_pred.log_prob(y_true)
model.compile(optimizer=tf.optimizers.Adam(learning_rate=0.01), loss=negloglik)

根据我们在以前文章中的讨论,我们将对 BNN 使用负对数似然,而不是 MSE。如果你不知道我在说什么,我强烈建议你回到前两篇文章,先熟悉一下概念和理论。

3.3 训练模型

# Early Stopping Callback
callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=300, min_delta=0, mode='auto', baseline=None, restore_best_weights=True)# Model Fitting
history = model.fit(x_train, y_train, validation_data=(x_val, y_val), epochs=10000, verbose=False, shuffle=True, callbacks=[callback], batch_size = 100)

这里没有什么特别的,基本上一切都和 SNN 的场景相似,所以我将跳过这一部分。

3.4 预测

今天最有价值的代码就在这里。

# Summary Statistics
y_pred_mean = model(x_test).mean()
y_pred_std = model(x_test).stddev()

通过调用 meanstddev 函数,现在可以告诉你预测的不确定性水平。

fig = plt.figure(figsize = (10, 8))
plt.scatter(x_train, y_train, marker='+', label='Train')
plt.plot(x_train, y_true, color='k', label='Truth')
plt.plot(x_test, y_pred_mean, color='r', label='Predicted Mean')
plt.fill_between(x_test.ravel(), np.array(y_pred_mean+1*y_pred_std).ravel(), np.array(y_pred_mean-1*y_pred_std).ravel(), color='C1', alpha=0.5, label='Aleatoric Uncertainty (1SD)')
plt.fill_between(x_test.ravel(), np.array(y_pred_mean+2*y_pred_std).ravel(), np.array(y_pred_mean-2*y_pred_std).ravel(), color='C1', alpha=0.4, label='Aleatoric Uncertainty (2SD)')
plt.fill_between(x_test.ravel(), np.array(y_pred_mean+3*y_pred_std).ravel(), np.array(y_pred_mean-3*y_pred_std).ravel(), color='C1', alpha=0.3, label='Aleatoric Uncertainty (3SD)')
plt.title('Bayesian Neural Network')
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.legend()
plt.show()

cyda 拍摄的照片

结论

看,你现在能够区分模型输出的任意不确定性。等等,那么认知的不确定性在哪里?我把这部分留给你们去进一步探索。提示是将 密集 层替换为 密集 层。去试试吧。=)

赫斯特指数简介 Python 代码

原文:https://towardsdatascience.com/introduction-to-the-hurst-exponent-with-code-in-python-4da0414ca52e?source=collection_archive---------4-----------------------

图片由 StockSnap 来自 Pixabay

一种快速调查给定时间序列是趋势、均值回复还是随机游走的方法

在金融领域,一些最常用的交易策略是基于动量和均值回复的。我将试着对这两者做一个简单的解释。

基于动量的策略中,投资者试图利用现有市场趋势的持续性。例如,在最后一个利息期,某家公司经营良好,股价随着时间的推移稳步上升。在这种情况下,投资者可能会押注价格将继续上涨,从而进入多头头寸。或者反之为空头。自然,策略不是那么简单,进入和退出的决定通常是基于一系列的技术指标。

均值回归假设股票收益和波动性等属性会随着时间的推移回归到它们的长期平均值。在数学上,这样的时间序列被称为奥恩斯坦-乌伦贝克过程。在这种策略中,投资者试图通过假设在一些极端事件(无论是积极的还是消极的)之后,股价将恢复到长期模式来赚钱。

我们可以很容易地在描绘股价随时间演变的图上识别出这两种模式。然而,当建立自动交易策略时,手动检查每一只股票并决定哪种模式在图上可见是不可行的。这就是为什么我们需要使用某种自动化的方法来确定在给定的股票价格中我们可以观察到两种模式中的哪一种。

在本文中,我将介绍如何使用 Hurst 指数来识别给定的时间序列(不仅仅是股票价格或收益等金融时间序列)是趋势性的、均值回复的还是简单的随机游走。

赫斯特指数

我们可以使用赫斯特指数 (H)作为时间序列长期记忆的度量,也就是说,测量该序列偏离随机游走的程度。标量代表时间序列强烈回归平均值(均值回复模式)或在某个方向聚集(趋势模式)的相对趋势。

赫斯特指数的值介于 0 和 1 之间。根据 H 的值,我们可以将任何时间序列分为三类:

  • H < 0.5 —均值回复(反持续)系列。该值越接近 0,均值回归过程越强。实际上,这意味着高值后面跟着低值,反之亦然。
  • H = 0.5 — 一个几何随机游走。
  • H > 0.5 —趋势(持续)系列。数值越接近 1,趋势越强。实际上,这意味着一个高值后面跟着一个更高的值。

至少有几种计算赫斯特指数的方法。不幸的是,他们的结论并不总是一致的(你可以在这里看到一个这样的例子)。

在本文中,我将只展示最简单的实现,它是基于对数价格的方差来估计扩散行为的速率。

先把 x 定义为股价的对数 S

任意滞后的方差(用 τ 表示)可以表示为:

如果股票价格遵循几何布朗运动(GBM,随机漫步),方差将随着滞后 τ: 线性变化

然而,股票价格并不总是遵循 GBM。在偏离随机游走的情况下(因此当某种形式的自相关存在时),给定滞后的方差不再与滞后本身成比例,但它会获得一个异常指数。新关系如下所示:

其中 H 再次代表赫斯特指数。

另一种计算赫斯特指数的可能方法是基于 重标范围(R/S)分析 。为了保持文章的简短,我不会在这里描述所有需要的步骤,但会让你参考一个逐步说明。文献表明,与其他方法(如自相关分析、方差比等)相比,使用 R/S 统计会产生更好的结果。但是,它也有一个缺点,就是对短程依赖非常敏感。

Python 中的示例

和往常一样,我们需要首先导入一些库。然而,这一次我们不会完全依赖于一个库,而是自己创建一个函数来计算 Hurst 指数。

然后,我们准备数据。作为一个真实的例子,我们将使用标准普尔 500 10 年的历史价格。我们可以使用yfinance库轻松下载价格。如果你对库的更多细节感兴趣,请查看我的另一篇文章。

作者图片

我们还将生成一些人工数据来反映赫斯特指数可以识别的所有三种情况:均值回复、随机游走和趋势。我们在下面的代码片段中这样做。

作者图片

我想说这个系列清楚地展示了我们希望他们展示的模式。也许趋势图有点矫枉过正,但至少应该很容易正确分类。

下一步是定义一个用于计算赫斯特指数的函数。

为了计算赫斯特指数,我们首先计算一个序列和它的滞后版本之间的差异的标准偏差,对于一系列可能的滞后。然后,我们将赫斯特指数估计为滞后数对上述标准偏差的双对数图的斜率。

滞后的数量多少有些随意。默认值 20 基于 Matlab 对 Hurst 函数的实现。然而,据文献报道,如果我们将滞后数设置得太高,结果可能会不准确。我们会尽快调查的。

让我们从标准普尔 500 的数据开始。总的来说,我们可以在图上看到该系列的趋势——除了一些例外,总体趋势是积极的。我们通过选择最大滞后值来计算赫斯特指数,看看它是如何影响指数值的。

默认值为 20,标准普尔 500 系列似乎是轻度均值回归。随着我们增加滞后的数量,均值回复只会更强(指数值向 0 递减)。

Hurst exponent with 20 lags: 0.4394 
Hurst exponent with 100 lags: 0.3834 
Hurst exponent with 300 lags: 0.3257 
Hurst exponent with 500 lags: 0.3231 
Hurst exponent with 1000 lags: 0.1795

请记住,这些值是为 10 年系列获得的。如果我们把范围缩小到某个时间段,结论可能会大不相同!这也是在实践中使用赫斯特指数时需要记住的事情。

现在是时候为人工生成的系列重复这个练习了。让我们看看基于赫斯特指数的结论是否会与预期相符。

Hurst exponents with 20 lags ---- 
mean_rev: 0.0064 
gbm: 0.4539 
trending: 0.8715 
Hurst exponents with 100 lags ---- 
mean_rev: -0.0021 
gbm: 0.5401 
trending: 0.8442 
Hurst exponents with 300 lags ---- 
mean_rev: 0.0002 
gbm: 0.5691 
trending: 0.7463 
Hurst exponents with 500 lags ---- 
mean_rev: 0.0015 
gbm: 0.4854 
trending: 0.6662

均值回复序列的结论在所有滞后值上都是最一致的。我们应该注意,最大滞后的负值 100 可能是由于一些近似值,按照设计,它应该停止在 0。

对于随机游走系列,指数的值在预期的 0.5 附近振荡。

最后,趋势系列由所有选定滞后的 Hurst 指数正确识别,然而,随着我们增加滞后,指数的值向 0.5 减小,这将表明随机游走。

我们可以得出结论,总的来说,结果足够接近最初的预期,但是,我们考虑的滞后的最大值会影响我们的结论。这种分析表明,一个给定的序列既不是纯粹的均值回复序列,也不是趋势序列。政权的状态取决于我们是着眼于短期还是长期(通过观察不同范围的滞后)。这就是为什么在实际尝试根据赫斯特指数制定交易策略之前,最好先对它有一些 T2 的感觉。

最后,如前所述,有相当多的方法来计算赫斯特指数。对于基于重标范围(R/S)分析的赫斯特指数的实现,您可以查看hurst库()。我没有在本文中使用它,因为这个库还没有开发(最后一次更新是在 2 年前)。但是,你绝对可以试一试。

外卖食品

  • 赫斯特指数是时间序列中记忆的一种度量,用于将序列分类为均值回复、趋势或随机游走。
  • 根据最大滞后参数的选择(即,我们看的是短期还是长期),结果可能会有很大不同。
  • 有几种方法可以计算 Hurst 指数,最常用的两种方法是基于异常扩散和重标极差分析。

您可以在我的 GitHub 上找到本文使用的代码。此外,欢迎任何建设性的反馈。你可以在推特上或者评论里联系我。

免责声明:前方加盟商链接

最近,我在进行基于动量交易策略的 MOOC 时遇到了赫斯特指数。Quantra 是一个提供交互式课程的平台,重点是量化金融的 Python。我给写了一篇短文,展示了这个平台的一些特性,并描述了我的个人经历。

如果您喜欢这篇文章,您可能还会对以下内容感兴趣:

参考

结构主题模型(STM)简介

原文:https://towardsdatascience.com/introduction-to-the-structural-topic-model-stm-34ec4bd5383?source=collection_archive---------11-----------------------

使用主题模型进行社会科学研究的独特方式

马林·斯特兰德瓦尔在 Unsplash 上拍摄的照片

关于主题建模最酷的事情之一是它在许多领域都有应用。它可以帮助激发探究,提供对文本的独特见解,并为您提供组织文档的新方法。

结构主题模型(STM)是一种专门为社会科学研究设计的主题模型。STM 允许我们将元数据合并到我们的模型中,并揭示不同的文档如何使用不同的单词选择来谈论相同的潜在主题。

激励 STM

主题建模描述了在文档语料库中发现潜在的主题。最著名的话题模型大概是潜在狄利克雷分配(LDA) 。LDA 的基本前提是将文档建模为主题的分布(主题流行度)和主题作为词的分布(主题内容)。查看这个媒体指南,了解一些关于 LDA 的基础知识。

LDA 很棒,但它确实做了一些限制性的假设:

  1. 文档中的 opics 相互独立。在英语中:仅仅因为文件 1 有潜在主题 1,它没有给我们任何信息是否文件 1 有潜在主题 2,3,等等。
  2. 词在主题(即主题内容)中的分布是固定的。在英语中:文档 1 的主题 1 使用与文档 2、3 等的主题 1 相同的单词。
  3. 主题可以完全基于文档的文本进行建模。在英语中:LDA 在确定主题时只查看文档的文本,不考虑任何其他信息(作者、日期、来源)。

为了解决独立性的第一个假设,看看相关主题模型 (CTM)。STM 采用了 CTM,但是在此基础上增加了一些特性。

从社会科学或人文科学的角度来看,假设二有些次优。两份文件可能是关于同一个主题——比如抗议——但是从不同的角度来看这个主题。也许一方倾向于强调“警察暴行”或“和平抗议者”,而另一方则使用“法律与秩序”和“激进暴徒”这样的术语。这两个文档可以说是关于相同的主题,但是主题内容(即组成主题的单词)因文档而异。

至于第三个假设,我们可以想象特定文档的主题流行度和主题内容都与关于该文档的“元数据”相关。例如,某些来源可能更倾向于写政治或以特定的方式写政治。元数据可以包括发布日期、作者、出版物、社交媒体上的喜欢,或者关于文档的任何数量的分类或数字变量。

STM 解决方案

在 LDA 中,我们的主题流行度和内容来自我们预先设置的具有超参数的狄利克雷分布——有时被称为 ab 。使用 STM,我们的主题流行度和内容来自文档元数据。我们将用于生成主题流行度的文档元数据矩阵称为“ X ”,用于生成主题内容的文档元数据矩阵称为“ Y ”然而,为了简单起见,我们假设 X = Y (也就是说,我们在两种情况下使用相同的元数据),并且两者都是 dxp 矩阵,其中 d 是语料库中文档的数量, p 是我们将使用的元数据特征的数量。

话题流行度

对于主题流行度,我们的目标是得到每个文档的概率向量,我们称之为θᵢ.我们需要从特定文档的 X ᵢ(一个 1xp 元数据向量)到θᵢ(一个 1xk 向量,其条目总和为 1,本质上对应于该文档有多少是由给定主题组成的。出于我们的目的, i 仅仅意味着这个θ是特定于一个给定的文档 i 抱歉;下标" i "通常是下标" d ",就像文献中的" document "一样,但是我怎么也找不到一个 Unicode 下标" d "。

为了得到θᵢ,我们将把 X ᵢ乘以一个叫做“τ”的权重矩阵 pxk τ从何而来?我们把τ的列叫做“γ” R STM 包的默认设置是针对 γₚ,ₖ~N(0,σₖ ) 其中σₖ~半柯西(1,1)

从解释上来说,半柯西(1,1) 先验意味着大多数参数将从零附近开始(正态分布的平均值为零,而半柯西(1,1) 意味着方差也将接近零)。在推理步骤中,我们将学习实际的参数值,但是这些参数的先验会将这些值拉向零,这意味着只有与主题高度相关的元数据才会最终产生影响。半柯西先验将非影响系数收缩到零,但实际上并不将参数归零。如果你有大量的元数据,而这些元数据可能与文档的主题不相关(例如,一键编码的特性),我们可能希望引入稀疏性。对于这些情况,R 包支持带有 L1 或弹性网正则化的伽玛先验。

在我们陷入 STM 的实现细节之前,最重要的事情是我们已经完成了从一个 1xp 元数据向量到一个 1xk 向量的线性转换,大致对应于主题流行度。

我们仍然没有一个概率向量。从τ * X ᵢ得到的矢量将作为最终生成θ的逻辑正态分布的平均值:

θᵢ ~逻辑正常(τ X ᵢ,σ)

这意味着我们将τ X ᵢ的结果视为方差为σ的多元正态分布的平均值。事实上,σ是 kxk 主题协方差矩阵(更全面的解释见 CTM),这就是我们如何打破假设一,将主题之间的相关性纳入我们的模型。然后,我们将多元正态分布的结果向量(称为η)通过逻辑函数转换成概率。

从这里开始,它只是常规的 LDA,其中我们基于由这些主题概率组成的多项式来生成每个单词的主题( z ),即 z ᵢ,ₙ~ 多项式( θᵢ ),用于文档 i 中的每个 n 单词。既然我们已经知道了文档中每个单词的主题,我们仍然需要计算出不同单词对于给定主题的概率,这将在下一节中探讨。

主题内容

对于文档的主题内容,我们从 Y ᵢ开始,我们的 1xp 给定文档的元数据向量 i. 我们的最终目标是一个叫做βᵢ的 kxV 矩阵,其中 V 是我们的词汇长度。在βᵢ,每一个 k 行都只是一个概率向量,其中每一列的值都是该主题生成一个单词的概率。正如下标 i 所示,这个β是特定于单个给定文档的。

为了获得单个文档(βᵢᵏ)中单个主题的单词概率,我们将从基线单词概率开始,我们称之为 mm 是一个 1xv 向量,基本上代表了全局单词概率:通常这意味着任意给定单词在语料库中的对数转换率,但也可以根据一些已知的词频预先设定。

从那里,我们将偏离基线,加入一些向量,我们称之为κ。注意,κ (kappa)和k不一样,我知道这很混乱,但请记住,κ是一组偏离全局词频的偏差,而 k 是主题的数量。

首先,我们将添加一个偏离基线的主题,名为κₖᵗ.上标“t”只是提醒这是我们的“主题”偏差,而“k”下标则进一步提醒这种偏差是特定于主题 k 的。更准确地说,κᵗ是一个带有κₖᵗ的矩阵,意味着我们现在只看第 k 行。无论如何,在这一点上,它基本上像常规的 LDA 一样,因为κₖᵗ是主题对词频的非文档特定影响。

其次,我们将通过向基线添加文档偏差来改进 LDA,我们称之为κᵧᵢᶜ(假设“γi”实际上是“ y ᵢ"… Unicode 再次胜过我)。上标“c”只是象征这是“协变量”偏差(元数据的另一种说法),而γi/ y ᵢ也表示这个协变量来自特定文档的元数据。换句话说,κᵧᵢᶜ是基于模型认为元数据将如何影响我们的词频的偏差。

最后,为了更好地衡量,我们将添加一个与主题和协变量(又名元数据)的交互偏差:κᵧᵢ,ₖ,ᵥⁱ.这里没有什么值得大书特书的;这最后一个κ术语仅仅涵盖了我们的基础,以防元数据和给定主题之间存在影响词频的“相互作用”(上标“I”表示)。

一旦我们将所有这些加在一起,我们就可以应用一些逻辑转换,我们将得到给定文档中给定主题的单词概率。

βᵢ,ₖ,ᵥ.的全配方奶粉βᵢ,ₖ,ᵥ的意思是:对于给定的文档 i 和给定的话题 k,给定单词 v 的概率是多少

κ从哪里来并不重要,因为我们在后验推理过程中学到了它。虽然κ可能看起来有点不透明,但简单地说,它为我们提供了特定于文档的主题内容。一旦我们建立了 STM 模型,我们就可以在不同的文档中看到相同主题 k 的最频繁出现的单词(即最高βᵢᵏ)。

这样,我们基本上就完成了!这是最终的板块图。

STM 平板图。回忆 z 是我们θ产生的话题。w 是从那个题目中选出来的词,基于β。 M 是语料库中文档的数量。 N 是一个文档的字数。框有点像循环,意味着我们在为每个文档的每个单词重复最内部的过程(z 和 w)。

这是总体的后验分布:

后验分布。回想一下,η本质上是我们在将其转换为概率的逻辑转换之前的主题流行度。

超级简要推理侧边栏

这个大等式说的是,在 STM 中,我们被给定了文档的单词( W) 文档的元数据( X,Y ,以及主题的数量( k )。我们需要估计潜在的主题流行率(η);具体的主题分配( z )、与基线主题内容的协变量和交互偏差(κ)、从元数据到主题流行度的映射参数(γ)以及主题之间的相关性(σ)。

如果你对推理感兴趣,选择 STM 算法是“非共轭变分期望最大化(EM)的快速变体。”概括地说,我们首先估计(估计/E-step)主题内容和流行参数,然后使用两种不同的算法(最大化/M-step)更新所有参数。我们正在测试这些参数给定数据的可能性,根据我们的数据更新参数,并迭代直到参数的变化低于某个阈值(即模型收敛)。这看起来很复杂,毫无疑问在计算上很困难,但是在高层次上,它可以归结为常规的贝叶斯推理。

2 快速注释:我已经包括了 k 作为我们预先设置的超参数。R STM 包有一个“searchK”功能,它会尝试自动找到最佳的 k。它是如何确定最优的 k,不值得深究,就我们所关心的而言,后验概率将 k 视为给定值,因此我们在此将其作为超参数。然而原作者并没有把它包含在他们的后验方程中,也没有把 m 包含在内回忆一下我们可以预先设定 m 或者从 W 推导出来。不管怎样,这不是我们估计的,但确实会影响κ,所以我把它包括在我们的后验概率中。

结论

概括一下:STM 不仅支持更高质量的模型,还提供了对语料库的洞察,例如元数据如何影响文档在主题中使用的单词。有了这些,你就有希望理解关于气候变化意识形态两极分化的论文背后的方法了。

您也有希望开始在 R 中使用 STM(或者如果 R 让您头疼,那么您可以使用这个 GUI 来代替)。我强烈推荐看一下 STM 主页,那里有方法论文、更多 STM 包和更多使用 STM 发表的论文的链接。

[1] M. Roberts、B. Stewart、D. Tingley 和 E. Airoldi,《结构主题模型和应用社会科学》(2013),为 NIPS 2013 年主题模型研讨会准备:计算、应用和评估。

[2] M. Roberts,B. Stewart,E. Airoldi,社会科学实验的文本模型 (2016),美国统计协会杂志。

[3] D .布莱,A. Ng。,和 M. Jordan,潜在狄利克雷分配 (2003),《机器学习研究杂志》。

[4] D. Blei 和 J. Lafferty,相关主题模型 (2005),NIPS'05:第 18 届神经信息处理系统国际会议论文集。

时间序列分析简介—使用 Python 进行数据辩论和转换

原文:https://towardsdatascience.com/introduction-to-time-series-analysis-data-wrangling-and-transformation-with-python-4ad5063720f6?source=collection_archive---------27-----------------------

准时系列

如何准备和分析时间序列数据

照片由思想目录Unsplash 上拍摄

时间序列课程通常主要关注统计测试的应用和预测模型的创建。然而,我发现这在很大程度上假设了读者的能力水平。如果你和我一样,那么你可能只通过本科统计学课程和 YouTube 视频了解时间序列的概念。

在这篇文章中,我们将回顾你将如何处理数据和进行探索性的数据分析。

我们开始吧!

一如既往,让我们导入所需的 Python 库。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as tkr

很好,现在让我们加载数据。在这篇文章中,我们将利用贾斯汀·基金斯的鳄梨价格数据。这样的数据可以在这里找到。

让我们通过熊猫加载数据。

df_av = pd.read_csv('avocado.csv')

图一。原始数据

我们可以看到数据是而不是简单而干净的数据列,事实上实际上有多个时间序列变量。这将最终允许我们从事更丰富的分析;然而,让我们首先关注清理数据。

我们可以看到数据有一个日期列。为了方便起见,让我们将该列分配给索引,并去掉未命名的列。

df_av = pd.read_csv('avocado.csv', index_col='Date')
df_av.drop(df_av.columns[0],axis=1,inplace=True)
df_av.head(5)

图二。更干净的数据

这些数据现在更有用了,现在让我们绘制一个折线图(时间序列数据的一种常见的可视化选择)。为了简单起见,让我们只关注总体积。

ax = df_av['Total Volume'].plot(figsize=(20,5))
ax.set_title('Total Volume of Avocados', fontsize = 22)
ax.set_xlabel('Year', fontsize = 15)
ax.set_ylabel('Volume', fontsize = 15)
plt.grid(True)
plt.show()

图三。一段时间内鳄梨的总量

我们可以看到曲线图 nice 绘出了这段时间内鳄梨的总量;然而,你们中的一些读者可能会认为这些数据看起来有点奇怪。如果你这么认为,那么恭喜你,你似乎对时间序列数据的本质有很好的直觉。

如果我们再看一遍数据,我们就能真正看到发生了什么。

图 4。再次查看数据

我们可以看到数据本身是而不是纯粹的时间序列,有一个地理指示器标记为区域。我们拥有的数据实际上是统计学家和经济学家所说的面板数据。数据本身包含 54 个不同的地区,所有地区的数据量相同(新墨西哥州是明显的例外)。

图五。所有区域值的计数

面板数据完全是一种稍微不同的动物,所以为了继续,让我们选择一个单独的区域。就我而言,我选择把重点放在旧金山。

图六。旧金山鳄梨的数量

我们可以看到数据还是比较奇怪的。这是因为数据中列出了两种鳄梨,常规有机。让我们把这两者分别画在不同的图上。

图 7。分解旧金山的鳄梨产量

我们可以看到,常规牛油果的体积远远大于有机牛油果;然而,两者似乎呈现出相似的总体增长趋势。让我们继续关注传统鳄梨的数量。

让我们看看每月的平均交易量,而不是每天的交易量。要做到这一点,必须首先找到提取月份的方法。到目前为止,我们仅有的日期数据是索引数据。

df_sfo_co = df_sfo[df_sfo['type'] == 'conventional']
df_sfo_co.index

图 8。索引数据

我们可以看到该索引包含月份数据。为了提取它,让我们使用列表理解。注意,出于本文的目的,我们将提取年和月。原因稍后将变得明显。

[f"{i.split('-')[0]} - {i.split('-')[1]}" for i in df_av.index]

图九。提取年月标签

然后可以将数据放入原始数据帧中。

df_sfo_co['year_month'] = [f"{i.split('-')[0]} - {i.split('-')[1]}"  
                           for i in df_sfo_co.index]
df_sfo_co.index

图 10。添加了年月列

既然我们已经附加了 year_month 数据,现在让我们通过获得月平均值而不是实际数量来折叠数据。

df_sfo_co = df_sfo_co.groupby('year_month', as_index=False).agg({'Total Volume':'mean', 'year' : 'mean'})
df_sfo_co

图 11。年月合计

太好了,这看起来更像你的典型时间序列数据,让我们画出来。

ax = df_sfo_co['Total Volume'].plot(figsize=(20,5))
ax.set_title('Volume of Avocados', fontsize = 22)
ax.set_xlabel('Month', fontsize = 15)
ax.set_ylabel('Price', fontsize = 15)
ax.set_xticks(np.arange(0, len(df_sfo_co['Total Volume'])+1, 2))   ax.get_yaxis().set_major_formatter(tkr.FuncFormatter(lambda x, p: format(int(x), ',')))plt.grid(True)
plt.show()

图 12。月聚合线图

最后,最好始终记住,时间序列数据不需要以上述格式呈现。我们还可以设置图表,使 x 轴只包含月份,用几条线代表几年。

关于这一点的争论相当广泛,但请容忍我。

df_sfo_pivot = df_sfo_co.pivot(index='year_month',
                            columns='year',
                            values='Total Volume')shift_value = -12
year_list = [2016, 2017, 2018]
for i in year_list:
    df_sfo_pivot[i] = df_sfo_pivot[i].shift(shift_value)
    shift_value -= 12df_sfo_pivot.dropna(how = 'all', inplace = True)
df_sfo_pivot.index = list([i.split('-')[1] for i in df_sfo_pivot.index])
df_sfo_pivot

图 13。争论和旋转的数据

很好,现在剩下的唯一任务就是绘制它。

图 14。堆积折线图

上图让我们可以更好地看到不同年份之间的差异,以及不同年份之间是否存在季节性。从上面的图表中,我们可以清楚地看到每年2 月需求出现峰值,随后在3 月需求明显下降。然后似乎没有明显的季节性成分,直到 2016 年和 2017 年12 月需求上升。

总之

时间序列分析对于任何参与发现趋势和分析市场(尤其是股票市场)的数据科学家来说都是一个强大的工具。虽然本文没有深入到具体的时间序列分析技术,但是我发现写一下实践中的数据争论和转换方面是谨慎的。这种技能不仅对时间序列分析至关重要,对每个处理数据的人也是如此。

时间序列预测简介

原文:https://towardsdatascience.com/introduction-to-time-series-forecasting-part-1-average-and-smoothing-models-a739d832315?source=collection_archive---------4-----------------------

第 1 部分:平均和平滑模型

时间序列是一个独特的领域。它本身就是一门科学。专家引用“一个好的预测是一种福气,而一个错误的预测可能是危险的”。本文旨在介绍时间序列的基本概念,并简要讨论用于预测时间序列数据的常用方法。

内森·杜姆劳在 Unsplash 上的照片

时间序列数据是在不同的时间点 t 观察到的关于响应变量 Y(t)的数据。关于变量的数据以规则的间隔和时间顺序收集。任何随时间顺序观察到的事物都是时间序列。

例如,在几个时间间隔内收集的智能手机销售数据、一个国家每年的 GDP、每年/每月的发电量等。都是时间序列数据的例子。

预测时间序列数据的目的是了解观察序列在未来将如何继续。

时间序列数据将具有以下一个或多个组成部分:

  1. 趋势分量 —它是数据在整个时间跨度内的持续向上或向下移动。趋势可以是线性的,也可以是非线性的
  2. 季节性成分 —它是一个日历年内以固定间隔发生的趋势的反复向上或向下波动。它总是有一个固定和已知的频率。
  3. 周期性成分 —周期性波动是由经济衰退等宏观经济因素引起的。在这里,复读之间的间隔超过几年。周期性波动的周期性不是固定的。周期性模式的平均长度比季节性模式的平均长度长。
  4. 不规则波动(也称白噪声) —它是时间序列数据中不相关的随机成分。如果时间序列数据只有白噪声作为分量,则不能用于预测。这是因为该系列的观测值是相同且独立分布的,平均值为 0,方差为常数。

预测模型的选择将取决于时间序列中存在的成分。时间序列预测模型可以大致分为简单模型(均值模型、线性趋势模型、随机游走模型)、平均和平滑模型(移动平均、指数平滑)、线性回归模型、ARIMA 模型。

简单模型实际上是底层模型,更复杂的模型建立在底层模型之上。

在深入研究平滑和 ARIMA 等复杂模型之前,让我们先了解这些底层模型。

简单预测模型:

平均模型:

对于独立同分布的时间序列(I . I . d——没有趋势,所有观测值具有相同的概率分布,并且彼此独立),时间 t+1 的预测由时间 t 之前的历史数据的平均值给出。该平均值使均方误差最小,也是一个无偏预测值。

如果我们预测未来很长一段时间,预测将是一条水平线或平均值。这是因为该模型假设所有未来的观察值将来自同一分布。考虑平均值为 45 的数列 X。因此,根据均值模型,所有未来期间的 X 预测值应为 45。我们知道这是一个不切实际的假设,除非 X 是一组不随时间变化的来自总体的独立随机样本。

线性趋势模型:

线性趋势模型是简单回归模型的一种特殊情况,其中独立变量是时间 t。它用于均值随时间逐渐增加的时间序列,即存在恒定趋势。在这种情况下,不使用水平线或均值模型来预测未来值,而是用一条斜线来拟合数据。线性趋势模型试图找到最符合历史数据的斜率和截距。

随机漫步模型:

在随机游走模型中,时间序列 X 在 y(t+1)处的值等于 y(t)加上一个随机噪声。

假设 t=0,X0 = 0。

那么在 t=1 时,X1 = X0 + Z1(其中 Z1 为随机噪声)。但是给定 X0 =0,X1= Z1。

在 t=2 时,X2 = X1+Z2。但是 X1 = Z1,因此,X2 = Z1 + Z2

如果我们在遥远的未来执行这个运算,我们得到 X(t) = Z1+Z2+…Z(t)。

因此,时间 t 的预测值是到时间 t 的白噪声的总和

我们如何解读这一点?

该模型假设,在每个周期中,变量从其先前值中随机移出一步,并且这些步在大小上独立且相同地分布,即,时间 t 和 t-1 的序列值的变化是完全随机的,并且具有零均值。

随机游走模式见于股票价格。价格变动不是随机的,但是每天的价格变化是随机的,因此不可能预测第二天的价格。

随机漫步的另一种变化是带有漂移的随机漫步。这里,该系列从其最后记录的位置开始随机步进,步进具有非零均值,即 y(t)= y(t-1)+α,其中α是漂移参数。

现在让我们进入实际的时间序列预测。

我们将使用工业生产—公用事业的数据来更好地理解时间序列预测的概念。所用数据可来源于此环节:【https://fred.stlouisfed.org/series/IPG2211A2N】。该数据集给出了从 1940 年到 2020 年美国所有天然气和电力公用事业的每月工业产量。

让我们首先从导入 Python 中的重要库开始:

*# Importing Libraries*
**import** **pandas** **as** **pd**
**import** **numpy** **as** **np**
**import** **matplotlib.pyplot** **as** **plt**
**import** **seaborn** **as** **sns**
**import** **warnings**
warnings.filterwarnings('ignore')
%matplotlib inline
**from** **statsmodels.tsa.seasonal** **import** seasonal_decompose
**from** **numpy** **import** mean
**from** **sklearn.metrics** **import** mean_squared_error
**import** **math**
**from** **statsmodels.graphics.tsaplots** **import** plot_acf, plot_pacf 
**from** **statsmodels.tsa.stattools** **import** adfuller
**from** **statsmodels.tsa.arima_model** **import** ARIMA
**import** **statsmodels.api** **as** **sm**
**import** **pmdarima** **as** **pm**
**from** **statsmodels.tsa.api** **import** ExponentialSmoothing
**from** **matplotlib** **import** pyplot
**import** **warnings**
**import** **itertools**

让我们也看看最初的观察结果。有两列:名为“IPG2211A2N”的日期和生产列。

df.head() DATE            IPG2211A2N
0  1939-01-01      3.3298
1  1939-02-01      3.3552
2  1939-03-01      3.4315
3  1939-04-01      3.4569
4  1939-05-01      3.4569

我们将把列名“IPG2211A2N”改为“Energy_Production”。日期采用对象格式。我们将把它改为日期时间。总共有 989 个观测值没有缺失数据。

让我们画出时间序列。

我们可以观察到既有趋势性又有季节性。我们可以使用 Python 中的函数' decompose '将时间序列数据分解成单独的部分。

y_decompose = seasonal_decompose(df['Energy_Production'], model = 'additive', freq = 12)
y_decompose_plot = y_decompose.plot()

使用这个函数,我们得到四个不同的图。其中包括系列的整体视觉图、趋势部分、季节部分和残差。人们也可以分别查看每个时间序列的组成部分。

时间序列的季节性成分

plt.figure(figsize=(15,3))
y_decompose.seasonal.plot();

时间序列的趋势分量

plt.figure(figsize=(15,3))
y_decompose.trend.plot();

如果我们观察这些单独的图,我们可以推断出趋势和季节成分都存在于时间序列中,并且是相加的。

这是什么意思?

相加时间序列是趋势和季节性的幅度不随时间增加的时间序列。它们保持相当稳定。乘法时间序列是趋势性和季节性的幅度随着时间段的增加而增加的时间序列。

我们将首先使用简单的预测方法,检查误差指标(RMSE 和 MAPE),然后使用更复杂的预测方法,如 SARIMA。

方法 1:简单移动平均法(SMA)

这种方法更适合没有强烈趋势和季节性成分的数据。

SMA 是最简单的预测方法之一,利用过去 N 次观测值的平均值来预测一个时间序列数据的未来值。这里,N 是超参数。平均模型的基本假设是序列具有缓慢变化的均值。因此,我们采用移动平均值来估计平均值的当前值,然后用它来预测未来。如果系列或多或少稳定,可以采用较低的 N 值。如果系列非常不稳定,则应采用较高的 N 值。需要探究 N 的值以找到最佳拟合模型。

移动平均法的公式如下:

给定的时间序列具有很强的季节性,也具有很强的趋势。SMA 的预测方法在这里行不通。但是,我们仍然会继续使用它,以了解为什么它不是最佳模型。

我们将采用 12 个月的移动平均线,因为我们在看月度数据,这种模式每年都会重复。然后,我们将绘制实际趋势和预测趋势,并观察预测值与实际时间序列的接近/远离程度。下面的 python 代码。滚动(窗口=12)采用超参数 n。

df1 = df.copy()
df1['Moving Avg_12'] = df1['Energy_Production'].rolling(window=12).mean().shift(1)

让我们绘制两个时间序列,即实际时间序列和预测时间序列。

plt.figure(figsize=(17,4))
plt.ylabel('Energy Production')
plt.title('Trend of Actual and Forecasted')
plt.plot(df1[['Energy_Production','Moving Avg_12']]);

显然移动平均法给出了平均趋势。它不能反映实际数据的波峰和波谷。因此,在这种情况下,我们无法预测产量。我们将使用 RMSE(均方根误差)和 MAPE(平均绝对百分比误差)等指标来检查预测的准确性。

对于初学者来说, RMSE 是平方误差平均值的平方根。由公式给出:

使用的另一个精度指标是平均绝对百分比误差。它是绝对百分比误差的平均值。它很容易解释,因为它用百分比表示平均误差。MAPE 的公式如下:

我们将构建一个自定义函数来计算 MAPE。对于 RMSE 来说,python 有一个内置函数。我们将检查最近 60 次观察的测试数据的准确性,即最近 5 年的数据

*# Function for MAPE*
**def** get_mape(actual, predicted):
    **return** np.round(np.mean(np.abs((actual-predicted) / actual))*100,2)get_mape(df1['Energy_Production'][928:].values, df1['Moving Avg_12'][928:].values)

8.48

*# Calculate RMSE* **
from** **sklearn.metrics** **import** mean_squared_error
np.sqrt(mean_squared_error(df1['Energy_Production'][928:].values, df1['Moving Avg_12'][928:].values))

10.158

因此,12 个月移动平均法的预测精度指标为:RMSE = 10.15,MAPE = 8.48

这肯定可以使用更先进的方法进一步改进。

方法 2:指数平滑法

简单移动平均法的缺点是它对所有的观察值给予同等的权重。直觉上,最近的观察应该比早期的观察给予更大的权重。指数平滑法通过给过去的观察值分配不同的权重来消除这种限制。在这里,分配给过去数据的权重以指数方式下降,而最近的观察被分配较高的权重。重量减少的速率由一个超参数控制,也称为“平滑常数”。

与简单平均法相比,指数平滑法的另一个重要优势是平滑常数可以使用“求解器”轻松优化,以最小化均方误差。

指数平滑方法有三种:

  1. 单指数平滑
  2. 双指数平滑和
  3. 三重指数平滑法或霍尔特温特斯法

让我们详细介绍一下其中的每一个。

单指数平滑:

这种方法只处理时间序列的水平部分。它使用一个称为平滑常数的超参数α,其值介于 0 和 1 之间。因为只使用一个平滑常数,所以称为单指数平滑。

这里,在时间 t 的预测被给出为Ft =α*** y(t-1)+(1-α)* F(t-1)**

双指数平滑:

这解决了时间序列的水平(l)和趋势(b)部分。因此,使用两个平滑常数,即α用于水平分量,β用于趋势分量。这些等式如下:

l(t)=α y(t)+(1-α)*(l(t-1)+b(t-1))———水平l
b(t)=
β(l(t)-l(t-1))+(1-β)* b(t-1)——趋势** b
y**

beta 值较低的模型假设趋势变化非常缓慢,而 beta 值较大的模型假设趋势变化非常迅速。

单一指数平滑法假设时间序列相对稳定,没有趋势性和季节性。但是,在这种情况下,数据表现出很强的趋势性和季节性。因此,我们不能使用单一指数法进行预测。双指数平滑法考虑了平均值或水平分量和趋势分量。它没有考虑季节性。因此,我们也不能使用双指数平滑法。

我们将因此使用三重指数平滑法,也称为霍尔特温特模型。它考虑到了水平、趋势和季节因素。

三重指数平滑法/霍尔特温特法:

在这种方法中,除了水平和趋势分量之外,我们还对季节分量应用平滑。平滑是跨季节应用的。也就是说,一个季节的第四分量相对于前一个季节的第四分量、前两个季节的第四分量等等被平滑。因此,将会有四个方程——水平、趋势、季节性各一个,最后一个方程包含所有单个组件。****

****由于模型是加法或乘法,等式会有所不同。老实说,人们需要付出巨大的努力来理解这些方程背后的数学。如果你想更深入地了解方程式背后的直觉,可以参考这个链接:https://grisha . org/blog/2016/02/17/triple-index-smoothing-forecasting-part-iii/

加法霍尔特·温特方法的四个方程如下:

这里 s 是季节长度,即新的季节开始之前的数据点数。

让我们看看如何用 Python 编写三重指数平滑的代码。我们将使用训练数据来建模。

**from** **statsmodels.tsa.holtwinters** **import** ExponentialSmoothingfit1 = ExponentialSmoothing(np.asarray(df1['Energy_Production'][:928].values), seasonal_periods=12 ,trend='add', seasonal='add',).fit()fit1.summary()

模型输出给出了平滑参数α、β和γ的最佳值。

**Exponential Smoothing Model Results   **                    
====================================================================
Dep. Variable:                endog   No. Observations:  928            
Model:        Exponential Smoothing   SSE: 2846.672                          
Optimized:                     True   AIC: 1072.171                          
Trend:                     Additive   BIC: 1149.500                          
Seasonal:                  Additive   AICC: 1072.924                         
Seasonal Periods:                12   Date: Wed, 21 Jul 2021
Box-Cox:                      False   Time: 18:40:08                 
Box-Cox Coeff:                 None                                         
====================================================================
                              **coeff                   code  **               
--------------------------------------------------------------------
**smoothing_level               0.4085441                alpha                 
smoothing_slope              5.4582e-17                 beta                 
smoothing_seasonal            0.3517790                gamma   **              
initial_level                 58.340136                  l.0                 
initial_slope                 0.1026049                  b.0                 
initial_seasons.0            -55.146903                  s.0                 
initial_seasons.1            -55.161188                  s.1                 
initial_seasons.2            -55.142231                  s.2                 
initial_seasons.3            -55.137545                  s.3                 
initial_seasons.4            -55.138415                  s.4                 
initial_seasons.5            -55.097211                  s.5                 
initial_seasons.6            -55.101285                  s.6                 
initial_seasons.7            -55.096024                  s.7                 
initial_seasons.8            -55.072809                  s.8                 
initial_seasons.9            -55.106835                  s.9                 
initial_seasons.10           -55.102856                 s.10                 
initial_seasons.11           -55.147951                 s.11                 
--------------------------------------------------------------------

我们现在将根据测试数据检查模型。预测之后,我们将绘制实际测试数据和预测数据。我们将再次使用 MAPE 和 RMSE 作为准确性指标。

train_data = df1['Energy_Production'][:928]
test_data = df1['Energy_Production'][928:]
y_hat_avg = test_data.copy()
y_hat_avg['Holt_Winter'] = fit1.forecast(len(test_data))**rms = math.sqrt(mean_squared_error(test_data, y_hat_avg.Holt_Winter))
print(rms)**

3.9916714233453447

**get_mape(test_data, y_hat_avg.Holt_Winter)**

3.27

让我们画出实际的和预测的数列。

fig = plt.figure(figsize=(15,5));
future, = plt.plot(test_data.index, test_data, 'r.-', label='Actual Output');
predicted_future, = plt.plot(test_data.index, y_hat_avg.Holt_Winter, 'g.-', label='Forecasted Output');
plt.legend(handles=[future, predicted_future]);
plt.title('Actual Production vs. Predicted Output');

我们可以看到预测产量与实际产量非常接近。与简单的移动平均法相比,性能更好。

三重指数平滑法的预测精度为:RMSE 3.99,MAPE 3.27。我们可以尝试更先进的技术来进一步优化指标。

这就把我们带到了第一部分的结尾。

我将总结本文中的要点:

  1. 在一个时间序列数据中,因变量是 Y(t),在不同的时间点观察到 t
  2. 一些技术,如简单模型,平均和平滑模型,线性模型和 ARIMA 模型,用于预测时间序列数据。
  3. MAPE 和 RMSE 等指标更常用于评估预测模型的准确性。
  4. 简单和加权移动平均等技术是最简单的预测方法之一,但是它们不适合具有高度季节性和趋势性的数据。
  5. 平滑技术提供了对移动平均法的改进。在这里,过去的观察被赋予不同的权重。
  6. 最重要的一点是,在某些情况下,平滑和移动平均等简单模型可能会优于 ARIMA 等基于复杂回归的模型。因此,在选择最终模型之前,使用不同的技术开发多个模型是有好处的。

在第 2 部分中,我们将使用更复杂的方法,如 ARIMA 及其扩展、萨里玛或季节性 ARIMA,并详细了解平稳性等术语。

希望这篇文章对你有用。我欢迎任何问题或建议。

时间序列预测导论第二部分(ARIMA 模型)

原文:https://towardsdatascience.com/introduction-to-time-series-forecasting-part-2-arima-models-9f47bf0f476b?source=collection_archive---------2-----------------------

大多数时间序列预测方法都假设数据是“平稳的”,但实际上它往往需要某些变换才能进一步处理。

Miguel Luis 在 Unsplash 上拍摄的照片

在第一篇文章中,我们看了简单的移动平均和指数平滑方法。在这篇文章中,我们将看看更复杂的方法,如 ARIMA 及其扩展。

方法 3:季节性自回归综合移动平均数

季节性 ARIMA 是 ARIMA 模型的一个变种。它是支持数据季节性的 ARIMA 方法的扩展。让我们首先了解 ARIMA 模式的运作。

ARIMA 是一种用于预测时间序列数据的统计模型。ARIMA 方程是一个回归型方程,其中自变量是因变量的滞后和/或预测误差的滞后。ARIMA 模型的方程式如下:

*y '(t)= c+ϕ1 y '(t1)+⋯+ϕp*y′(t−p)+θ1 ε(t1)+⋯+θq ε(TQ)+εt

等式中有三项:

AR:自动回归:时间序列用其以前的值回归,即 y(t-1),y(t-2)等。滞后的顺序表示为 p.

I:积分:时间序列使用差分使其平稳。差值的阶数表示为 d.

MA:移动平均:用过去观测值的残差对时间序列进行回归,即误差 ε (t-1),误差 ε (t-2)等。误差滞后的阶数表示为 q.

上式中,y′t为差分数列, ϕ1 为第一项 AR 的系数, p 为 AR 项的阶次, θ1 为第一项 MA 的系数, q 为 MA 项的阶次, εt 为误差。

ARIMA 不支持季节性数据。对于具有显著季节性模式的时间序列,使用季节性 ARIMA 模型。

它和 ARIMA 有什么不同?除了 ARIMA 的三个参数,即 P、D、Q,SARIMA 还有三个季节参数(P、D、Q)。额外的三个参数说明了季节水平的自回归分量(P)、差异分量(D)和移动平均分量(Q)。

可以表示如下:ARIMA (p,D,q) (P,D,Q)m 这里 m 是每个季节的观测次数(在我们的例子中,m 是 12)。模型的季节性成分用大写字母表示,模型的非季节性成分用小写字母表示。

在我们进入萨里玛的细节之前,让我们先了解一下术语‘自相关’和‘偏自相关’。

自相关函数(ACF) : 滞后 k 的自相关是 Y(t)和 Y(t-k)之间的相关性,在不同的 k 滞后处测量。对于滞后 1,在 Y(t)和 Y(t-1)之间测量自相关,类似地,对于滞后 2,在 Y(t)和 Y(t-2)值之间测量自相关。不同 k 值的自相关图被称为自相关图或相关图。

偏自相关(PACF) : 滞后 k 的偏自相关是在所有其他中间值(Y(t-1),Y(t-2),…)的影响下,Y(t)和 Y(t-k)之间的相关。Y(t-k+1))同时从 Y(t)和 Y(t-k)中删除。例如,y(t)和 y(t+1)之间的部分自相关与它们的自相关相同,因为它们之间没有中间项。y(t)和 y(t+2)之间的部分自相关将从 y(t)和 y(t+2)中去除 y(t+1)的影响。不同 k 值的部分自相关图称为部分自相关图。

在我们使用 ARIMA 或其任何扩展之前,我们需要确保时间序列是平稳的。

时间序列的平稳性是什么意思?

如果一个时间序列具有以下三个性质,则称它是平稳的:

  1. 它有一个恒定的平均值,即平均值随时间保持不变
  2. 它有一个恒定的方差,即方差随时间保持恒定
  3. 它有一个恒定的协方差。两个时间段之间的协方差值取决于两个时间段之间的滞后,而不取决于计算协方差的时间。这意味着 t=2 和 t = 4 时序列之间的协方差应该与 t=7 和 t=9 时序列之间的协方差大致相同。

平稳时间序列将具有相同的统计特性,即相同的均值、方差和协方差,无论我们在什么点测量它们,因此这些特性是时不变的。从长期来看,这个系列没有可预测的模式。时间图将显示序列大致水平,具有恒定的平均值和方差。

为什么我们需要平稳的时间序列?因为如果时间序列不是平稳的,我们只能研究它在那个时间段的行为。时间序列的每个周期都有其独特的行为,如果序列不是稳定的,就不可能预测或概括未来的时间周期。

一个平稳的时间序列将趋向于返回到它的平均值,围绕这个平均值的波动将具有恒定的幅度。因此,由于方差有限,平稳时间序列不会偏离均值太多。

平稳时间序列的一个例子是“白噪声”。由于其固有的平稳性,它没有可预测的长期模式。因此它是无记忆的。

以下是白噪声的分布情况:

*#* ***Plot for White Noise with Mean 0 and standard deviation as 0.8***
wnoise= np.random.normal(loc=0, scale=0.8, size=800)
plt.figure(figsize=(15, 4)),
plt.plot(wnoise);
plt.title('Distribution of White Noise');

从上面的图中可以看出,平均值的分布是恒定的,完全是随机的。很难预测时间序列的下一步动向。如果我们绘制该序列的自相关图,将会观察到完全的零自相关。这意味着任何时间 t 的序列与其滞后值之间的相关性为零。

acr = plot_acf(wnoise, lags = 50)

在上面的 ACF(自相关图)中,你可以看到所有的滞后都在蓝色突出显示的区域内。这表明不同滞后的观测值之间几乎没有相关性。如果一个或多个尖峰在这个范围之外,或者超过 5%的尖峰在这些范围之外,那么我们可以推断该序列不是“白噪声”。

我们如何检查平稳性?

用于检查平稳性的两个流行测试是增强迪基富勒测试(ADF)和科维亚特科夫斯基-菲利普斯-施密特-申测试(KPSS) 。让我们详细看看每个测试。

1。增强的迪基富勒测验:

这种统计检验属于称为单位根检验的类别。它检查时间序列是否有单位根,从而是非平稳的。当我们进行这个测试来检查平稳性时,我们检查单位根。

零假设 Ho :有单位根,即时间序列是非平稳的
交替假设 Ha :没有单位根,即时间序列是平稳的

单位根是什么意思?

观察到两种非平稳随机时间序列:

  1. 无漂移随机行走模型
  2. 漂移随机游动模型

无漂移随机游走中,序列的均值是常数,等于其初始值或起始值,但方差随时间增加。因此,该序列是非平稳的。通常,股票价格被认为是遵循随机游走的。显示随机游走的数据具有长周期的上升或下降趋势,以及方向上的突然和不可预测的变化。
因此,这个模型的预测是最后一次观察,因为未来的运动是不可预测的,同样有可能上升或下降。

时间序列 Y 在 t 时刻的值等于其在 t-1 时刻的值加上一个随机冲击即 Y(t) = Y(t-1) +误差 u(t)
无漂移随机游走的一阶差分是一个平稳的时间序列。为什么?原因从上式可知,Y(t) — Y(t-1) =误差项 u(t)。误差项是具有均值 0 和恒定方差的白噪声或平稳序列

在有漂移的随机游走中,序列的均值和方差都随时间增加。因此,该序列不是静止的。这里,时间 t 的时间序列值等于时间(t-1)的值加上漂移参数α加上随机冲击,即 Y(t)= Y(t-1)+α+u(t)。漂移参数α是系列从一个周期到下一个周期的平均增量。

随机游走模型被称为单位根过程。

写为:Y(t) = (Delta) Y(t-1) + u(t)*

如果 delta 的值为 1(随机游走)或大于 1(有漂移的随机游走),则序列是非平稳的。如果 delta 的值小于 1,我们断定该序列是平稳的。

请注意,非平稳性或单位根也可能是确定性趋势的原因。我在本文中没有涉及这一部分。

现在让我们看看 KPSS 测试。

2。科维亚特科夫斯基-菲利普斯-施密特-申(KPSS 测试):

这是另一个不太流行的检验平稳性的测试。这里的零假设和交替假设与 ADF 检验相反。

零假设:过程是趋势平稳的。

交替假设:数列有单位根(数列不是平稳的)。

如果我们使用这两种测试来确认平稳性,则可能出现以下四种情况之一:

情景一— 两个测试都得出平稳性结论。因此,数列是平稳的。

情景二 —两个测试都得出非平稳性的结论。因此,该序列是非平稳的。

情景三 — ADF 检验得出平稳性结论,但 KPSS 检验得出非平稳性结论。这表明需要使用差分来使序列平稳。这里,创建了一个新的序列,其中时间 t 处的观测值由时间 t 处的实际值和时间 t-1 处的值之间的差给出。因此,

差分序列的值(t)=观测值(t)-观测值(t-1)

情景四 — ADF 检验得出非平稳性结论,但 KPSS 检验证实平稳性。这表明需要使用去趋势来使系列静止。常见的去趋势方法包括使用对数变换、原始序列的平方根变换。

一旦数列稳定下来,下一步就是建立 ARIMA 模型。建立 ARIMA 模型有两种方法。

方法 1: 通过查看差异数据的 ACF 和 PACF 图,手动选择模型阶数,并确定 p 和 q 的最佳值。使用不同的 p 和 q 值构建多个模型,并选择最终模型,即具有最低 AIC 的模型。(AIC 或阿凯克的信息准则是一个有用的模型选择工具。给定一组时间序列数据的模型,最佳模型是具有最低 AIC 的模型。它通过惩罚具有更多参数的模型来平衡拟合优度和过度拟合。)

方法 2: 使用 Auto Arima (auto.arima())寻找给定时间序列的最佳模型。

实际上,这两种方法混合使用。使用方法 1,确定 p 和 q 的范围。在下一步中,Auto Arima 函数用于步骤 1 中确定的范围。

在方法 1 中提到的 ARIMA 模型中,有一些用于确定 p、d 和 q 的最佳值的指导原则。这些措施如下:

准则 1:确定 ARIMA 模型中的差分顺序:

拟合 ARIMA 模型的第一步也是最重要的一步是决定差分的阶次,以使序列平稳。正确的方法是从最低差值开始,即 d=1。通常这将使系列静止。然而,如果仍然有一个显著的趋势,或者如果滞后≥10 的自相关为正显著,那么序列需要二阶差分。阶数大于 2 的差分从来不是优选的。

如果差分序列的滞后 1 的自相关为零或负值,或者如果自相关都很小且没有模式,则该序列不需要更多的差分。如果滞后-1 自相关比-0.5 更负,则表明序列可能已被过度差分。

准则 2:识别 ARIMA 模型中的应收账款或并购术语:

一旦我们有了平稳序列,下一步就是确定 ARIMA 模型中的 AR 和 MA 项。直觉如下:

  1. 如果差分序列的 PACF 显示出一个锐截止和/或 lag1 自相关为正(这表明一个“欠差分”序列),而 ACF 衰减较慢,则考虑在模型中增加一个 AR 项。AR 术语的数量将取决于 PACF 截止的滞后时间。
  2. 如果差分序列的 ACF 显示出锐截止和/或 lag1 自相关为负(这表示“过度差分”序列),而 PACF 衰减较慢,则考虑将 MA 项添加到模型中。这里,通过添加 MA 项来解释自相关模式。MA 项的数量将取决于 ACF 截止的滞后。
  3. AR 项与滞后 1 处的欠差分或正自相关相关,而 MA 项与滞后 1 处的过差分或负自相关相关。

准则 3:最终确定哪种 ARIMA 模式?

选择与 AR 或 MA 项差异水平较低的模型。然而,AR 和 MA 的混合模型有时可能是最佳选择。

如果 AR 系数之和等于 1 或几乎等于 1(即存在单位根),则增加差分阶数并减少 AR 项数。

如果 MA 系数之和等于 1 或接近 1,则降低差分阶数,增加 MA 项数。

AR 系数之和或 MA 系数之和等于 1 的模型称为有“单位根”。这种模型没有作为白噪声的残差。

除了 ARIMA 模型中的 P、D、q,像萨里玛这样的季节性模型还有额外的季节性项 P、D、q。这些也可以从 ACF 和 PACF 图中确定。

季节性 ARIMA (SARIMA)指南:

准则 4 :识别季节性和非季节性差异顺序:

SARIMA 模型中最重要的一步是决定是否需要季节差异。如果季节性很强,应该使用季节差异的顺序。如果序列在应用季节差异后仍然不是平稳的,我们可以考虑应用非季节差异。H 然而,永远不要使用一个以上的季节差异,季节和非季节差异之和不应超过 2。

我们使用季节性差异和非季节性差异的顺序并不重要,但是,如果我们有高度季节性的数据,最好先执行季节性差异,然后执行非季节性差异。

准则 5:识别季节性和非季节性 AR 和 MA 术语:

如果季节性滞后 k 处的自相关为正(在我们的例子中 k=12,24,36 ),则向模型添加季节性 AR 项(P)。如果季节性滞后的自相关为负,则向模型添加季节性 MA 项(Q)。应注意不要在同一个模型中同时包含季节性 AR 和 MA 术语,并且每个术语的顺序不应超过 1。

这些是杜克大学的罗伯特·瑙提出的指导方针。请参考以下链接,以获得对上述准则的详细理解。https://people.duke.edu/~rnau/411arim.htm

让我总结一下ARIMA/萨里玛造型的关键步骤:

  1. 绘制时间序列数据,观察趋势和季节性
  2. 使用 ADF 和 KPSS 等统计测试来检查平稳性
  3. 如果序列不稳定,请使用差分或去趋势等变换。对于季节性数据,除了非季节性差异外,可能还需要季节性差异。
  4. 一旦确定了差分的阶数,我们就需要决定最佳的 AR 和 MA 项。
  5. 使用 ACF 和 PACF 图获得参数 P,P,Q,Q 的范围。使用 auto.arima 并指定这些参数的范围。
  6. 检查回归模型的假设,即误差的正态性和误差之间没有自相关。

现在让我们一次一个地完成这些步骤。

数据的曲线如下:

plt.figure(figsize=(15,5))
plt.ylabel('Energy Production')
plt.title('Trend of Energy Production')
plt.plot(df['Energy_Production'],'b-');

这里我们将去掉某一部分数据,即从 1940 年到 1964 年的观测数据。原因是非常旧的数据,可能会引起不必要的噪声。

df1 = df.copy()
df2 = df1['Energy_Production'][312:]
df2 = pd.DataFrame(df2)
df2.head()

能源 _ 生产日期
1965–01–01 29.4598
1965–02–01 28.7989
1965–03–01 28.8497
1965–04–01 28.1889
1965–05–01 27.7059

我们现在可以继续运行统计测试来检查平稳性。

测试 1:增强的 Dickey Fuller 测试:

X = df2['Energy_Production'].values
result = adfuller(X)
print('ADF Statistic: **%f**' % result[0])
print('p-value: **%f**' % result[1])
print('Critical Values:')
**for** key, value **in** result[4].items():
    print('**\t%s**: **%.3f**' % (key, value))**ADF Statistic: -2.231551
p-value: 0.194994
Critical Values:
	1%: -3.440
	5%: -2.866
	10%: -2.569**

这里,p 值大于 0.05,因此我们不能拒绝零假设。因此,级数有单位根,是非平稳的。

测试 2 : KPSS 测试

**from** **statsmodels.tsa.stattools** **import** kpss

**def** kpss_test(timeseries):
    print("Results of KPSS Test:")
    kpsstest = kpss(timeseries, regression="c")
    kpss_output = pd.Series(
        kpsstest[0:3], index=["Test Statistic", "p-value", "Lags Used"]
    )
    **for** key, value **in** kpsstest[3].items():
        kpss_output["Critical Value (**%s**)" % key] = value
    print(kpss_output)kpss_test(df2['Energy_Production'].values)**Results of KPSS Test:
Test Statistic            3.273962
p-value                   0.010000
Lags Used                20.000000
Critical Value (10%)      0.347000
Critical Value (5%)       0.463000
Critical Value (2.5%)     0.574000
Critical Value (1%)       0.739000
dtype: float64**

这里,p 值小于 0.05。然而,KPSS 检验的零假设与 ADF 检验相反。因此,在这里,我们将拒绝平稳序列的零假设,并得出结论,该序列是非平稳的。

这与场景 2 类似,两个测试都确认给定序列是非平稳的。我们现在将考虑使数列平稳的步骤。

鉴于季节性很强,我们将首先使用季节差异。给定 m=12,我们需要将时间 t 的观测值与其在 t-12 的滞后值区别开来。如果我们这样做,差分序列的前 12 个观测值将取 NaN 值。这里,季节差异 D 的顺序是 1。

df2['Energy_Production_diff'] = df2['Energy_Production'] - df2['Energy_Production'].shift(12)
df2[['Energy_Production','Energy_Production_diff']].head(13)

日期能源 _ 生产能源 _ 生产 _ 差异
1965–01–01 29.4598 南
1965–02–01 28.7989 南
1965–03–01 28.8497 南
1965–04–01 28.1889 南
1965–05–01 27.7059 南
1965–06–08

我们将删除 NaN 观测值,并绘制数据序列,以检查差分是否使序列平稳。

plt.figure(figsize=(18,5));
plt.xlabel('Time');
plt.ylabel('Energy Production');
plt.title('Differenced Time Series of Energy Production');
plt.plot(df2['Energy_Production_diff1']);

尽管方差不是常数,但该序列看起来几乎是平稳的。我们将再次运行这两个测试来确认稳定性。

**# ADF Test:** 
X = df2['Energy_Production_diff1'].dropna().values
result = adfuller(X)
print('ADF Statistic: **%f**' % result[0])
print('p-value: **%f**' % result[1])
print('Critical Values:')
**for** key, value **in** result[4].items():
    print('**\t%s**: **%.3f**' % (key, value))**ADF Statistic: -7.448126
p-value: 0.000000
Critical Values:
	1%: -3.440
	5%: -2.866
	10%: -2.569**

这里,p 值小于 0.05。因此,我们将拒绝零假设,并得出结论,该序列是平稳的。

**# KPSS Test** 
kpss_test(X)Results of KPSS Test:
**Test Statistic            0.575462
p-value                   0.024867**
Lags Used                20.000000
Critical Value (10%)      0.347000
Critical Value (5%)       0.463000
Critical Value (2.5%)     0.574000
Critical Value (1%)       0.739000
dtype: float64

KPSS 检验的 p 值小于 0.05。因此,我们将拒绝数列是平稳的零假设。KPSS 检验的结论是该序列是非平稳的。

这个结果类似于本文上面提到的场景 3。两种检验都给出了相互矛盾的结果,ADF 的结论是序列是平稳的,而 KPSS 检验的结论则相反。因此,我们可以得出结论,该序列是非平稳的。如果我们绘制差分序列的 ACF 和 PACF 图,我们可以看到初始滞后之间的强正自相关。

acf_plot = plot_acf(df2['Energy_Production_diff1'].dropna(), lags= 30)

pacf_plot = plot_pacf(df2['Energy_Production_diff1'].dropna(), lags= 30)

因此,我们将继续下去,并再次差分序列,使其静止。这将是 1 阶的非季节性差异,即 d = 1

df2['Energy_Production_diff121'] = df2['Energy_Production_diff1'] - df2['Energy_Production_diff1'].shift(1) 

我们将使用两个统计测试来检查和确认平稳性。

**# ADF Test** 
X = df2['Energy_Production_diff121'].dropna().values
result = adfuller(X)
print('ADF Statistic: **%f**' % result[0])
print('p-value: **%f**' % result[1])
print('Critical Values:')
**for** key, value **in** result[4].items():
    print('**\t%s**: **%.3f**' % (key, value))**ADF Statistic: -8.939993
p-value: 0.000000**
Critical Values:
	1%: -3.441
	5%: -2.866
	10%: -2.569# **KPSS Test:**
kpss_test(X)
Results of KPSS Test:
**Test Statistic            0.017791
p-value                   0.100000**
Lags Used                20.000000
Critical Value (10%)      0.347000
Critical Value (5%)       0.463000
Critical Value (2.5%)     0.574000
Critical Value (1%)       0.739000
dtype: float64

在这一步,两个测试都确认系列是稳定的。让我们绘制 ACF 图和 PACF 图,以及总体差异系列图。

acf_plot = plot_acf(df2['Energy_Production_diff121'].dropna(), lags= 30)

pacf_plot = plot_pacf(df2['Energy_Production_diff121'].dropna(), lags= 30)

这两个图确实有明显的滞后,但我们将继续处理序列平稳,如 ADF 和 KPSS 测试所证实的。差分序列的曲线如下:

plt.figure(figsize=(18,5));
plt.xlabel('Time');
plt.ylabel('Energy Production');
plt.title('Differenced Time Series of Energy Production');
plt.plot(df2['Energy_Production_diff121']);

这个图看起来很像白噪声的分布。我们可以从上面的图中推断出这个数列是平稳的。

到目前为止,我们已经使用了两次差分,即一次 D=1 阶的季节性差分和一次 d=1 阶的非季节性差分。下一步是确定 AR 和 MA 参数。在 ACF 图中,在 1、12 和 24 处有显著的负滞后。因此,MA 参数应为 1,季节性 MA 参数应为 2。(准则 2,5) 。鉴于 PACF 图在 1 和 12 处也有负滞后,根据指南,我们将不包括 AR 和季节性 AR 项。

由此,模型的最终顺序似乎是(0,1,1)(0,1,2)12。

在遵循 ACF 和 PACF 图的方法 1 时,很难在第一时间提出最佳模型。这是因为要正确解读这些情节是非常困难的。因此,一般的方法是将这两种方法结合起来。使用第一种方法,我们可以确定非季节性参数 P、D、q 和季节性参数 P、D、q 的范围。然后,这可以作为 auto arima 函数的输入。

让我们看看它是如何实现的。

我们将首先安装库“pmdarima ”,然后导入它。

**import** **pmdarima** **as** **pm
from** **pmdarima** **import** auto_arima
*# Ignore harmless warnings*
**import** **warnings**
warnings.filterwarnings("ignore")df3 = df2['Energy_Production']

我们将从 ACF 和 PACF 图中定义 P、Q、P、Q 值的范围。这里,我们取了 d=D=1。(在这种情况下,ADF 和 KPSS 测试是同步的)。我们将参数 P,P,Q,Q 初始化为 0,最大值为 2。正如指南中提到的,我们不应该建立具有更高阶 AR、MA、SAR、SMA 参数的模型。假设数据是季节性的,这里 m 是 12,search = ' True '。

model = auto_arima(df3, start_p=0, start_q=0,
                          max_p=2, max_q=2,m=12,start_P=0,start_Q=0, 
                          max_P = 2, max_Q = 2,
                          seasonal=**True**,
                          d=1,D=1,trace=**True**,
                          error_action='ignore',   
                          suppress_warnings=**True**,  
                          stepwise=**True**)

上面的代码需要一些时间来运行,因为它评估了许多模型的组合。代码的输出是具有最小 AIC 的模型。

Performing stepwise search to minimize aic
 ARIMA(0,1,0)(0,1,0)[12]             : AIC=3281.487, Time=0.08 sec
 ARIMA(1,1,0)(1,1,0)[12]             : AIC=3171.654, Time=0.23 sec
 ARIMA(0,1,1)(0,1,1)[12]             : AIC=3018.258, Time=0.58 sec
 ARIMA(0,1,1)(0,1,0)[12]             : AIC=3218.537, Time=0.08 sec
 ARIMA(0,1,1)(1,1,1)[12]             : AIC=3015.997, Time=0.92 sec
 ARIMA(0,1,1)(1,1,0)[12]             : AIC=3141.548, Time=0.28 sec
 ARIMA(0,1,1)(2,1,1)[12]             : AIC=2994.828, Time=1.94 sec
 ARIMA(0,1,1)(2,1,0)[12]             : AIC=3058.224, Time=0.81 sec
 ARIMA(0,1,1)(2,1,2)[12]             : AIC=2977.369, Time=5.76 sec
 ARIMA(0,1,1)(1,1,2)[12]             : AIC=3010.587, Time=3.48 sec
 ARIMA(0,1,0)(2,1,2)[12]             : AIC=3047.276, Time=4.01 sec
 ARIMA(1,1,1)(2,1,2)[12]             : AIC=2912.252, Time=7.25 sec
 ARIMA(1,1,1)(1,1,2)[12]             : AIC=2931.644, Time=4.72 sec
 ARIMA(1,1,1)(2,1,1)[12]             : AIC=2918.937, Time=3.15 sec
 ARIMA(1,1,1)(1,1,1)[12]             : AIC=2937.865, Time=1.59 sec
 ARIMA(1,1,0)(2,1,2)[12]             : AIC=3010.240, Time=6.52 sec
 ARIMA(2,1,1)(2,1,2)[12]             : AIC=2914.225, Time=9.10 sec
 ARIMA(1,1,2)(2,1,2)[12]             : AIC=2914.220, Time=7.80 sec
 ARIMA(0,1,2)(2,1,2)[12]             : AIC=2930.445, Time=5.22 sec
 ARIMA(2,1,0)(2,1,2)[12]             : AIC=2980.502, Time=6.62 sec
 ARIMA(2,1,2)(2,1,2)[12]             : AIC=2916.073, Time=16.42 sec
 ARIMA(1,1,1)(2,1,2)[12] intercept   : AIC=2914.035, Time=21.91 sec

**Best model:  ARIMA(1,1,1)(2,1,2)[12] **         
Total fit time: 108.511 seconds

让我们看看模型的总结。Auto Arima 给出(1,1,1)(2,1,2)12 作为最佳模型,即具有最小 AIC 的模型。

print(model.summary())**Statespace Model Results        **                         
===================================================================
Dep. Variable:      y                 No. Observations: 677
Model: SARIMAX(1, 1, 1)x(2, 1, 2, 12) Log Likelihood: -1449.126            
Date:  Wed, 28 Jul 2021               AIC: 2912.252                      
Time:  17:14:03                       BIC: 2943.740                      
Sample: 0- 677                        HQIC : 2924.454                                                                                                            Covariance Type: opg                                                                  
====================================================================
                 coef    std err          z      P>|z|      
**ar.L1**          0.5133      0.034     15.039      0.000             
**ma.L1**         -0.9304      0.018    -52.457      0.000           
**ar.S.L12**       0.6594      0.090      7.340      0.000             
**ar.S.L24**      -0.3230      0.041     -7.930      0.000           
**ma.S.L12 **     -1.3218      0.093    -14.195      0.000           
**ma.S.L24**       0.5492      0.075      7.350      0.000            
sigma2         4.5143      0.186     24.224      0.000             
====================================================================
Ljung-Box (Q): 52.32                  Jarque-Bera (JB): 112.23       
Prob(Q): 0.09                         Prob(JB):0.00                         
Heteroskedasticity (H):4.73           Skew: 0.07                            
Prob(H) (two-sided): 0.00             Kurtosis: 5.01
====================================================================

Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).

需要进行某些检查:AR 和 MA 项的系数小于 1,两个季节性 AR 项的系数之和小于 1,两个 MA 项的系数之和也小于 1。这些项中的每一项在 p 值小于 0.05 时都是显著的。这似乎是一个很好的模式。因此,萨里玛模型(1,1,1) (2,1,2)12 是最终选择的模型。 (这接近我们从图中识别的模型(0,1,1)(0,1,2)12)

我们现在将数据分为训练和测试,并计算测试数据的预测。

train = df3[:612]
test = df3[612:]**from** **statsmodels.tsa.statespace.sarimax** **import** SARIMAX
final_model = SARIMAX(train,order=(1,1,1),seasonal_order=(2,1,2,12))
result = final_model.fit()
print(result.summary())

摘要如下:

Statespace Model Results                                 
====================================================================
Dep. Variable: Energy_Production        No. Observations:612                 
Model: SARIMAX(1, 1, 1)x(2, 1, 2, 12)   Log Likelihood :-1247.862               
Date:  Wed, 28 Jul 2021                 AIC :2509.724                           
Time:  17:14:32                         BIC :2540.491                         
Sample: 01-01-1965- 12-01-2015          HQIC: 2521.702                         

====================================================================
                 coef    std err          z      P>|z|     
--------------------------------------------------------------------
**ar.L1 **         0.5832      0.038     15.368      0.000       
**ma.L1  **       -0.9411      0.017    -55.676      0.000      
**ar.S.L12  **     0.6723      0.167      4.020      0.000       
**ar.S.L24 **     -0.2318      0.047     -4.908      0.000      
**ma.S.L12  **    -1.3065      0.169     -7.738      0.000      
**ma.S.L24**       0.5211      0.125      4.175      0.000       
**sigma2  **       3.7119      0.161     23.044      0.000      
===================================================================================
Ljung-Box (Q): 61.31                  Jarque-Bera (JB): 109.28              
Prob(Q): 0.02                         Prob(JB): 0.00                        
Heteroskedasticity (H): 4.62          Skew: -0.11
Prob(H) (two-sided): 0.00             Kurtosis: 5.08                         
====================================================================
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).

我们还将运行模型诊断来检查误差的正态性假设和残差分布。如果误差是正态分布的,并且彼此不相关,那么我们实际上有一个好的模型。

result.plot_diagnostics(figsize=(15, 12));

我们在这里可以看到残差是白噪声,也是正态分布。因此,我们可以继续这一模式。

我们现在将预测测试数据,然后检查准确性。

*# Obtain predicted values*
start=len(train)
end=len(train)+len(test)-1
predictions = result.predict(start=start, end=end, dynamic=**False**, typ='levels').rename('SARIMA(1,1,1)(2,1,2,12) Predictions')*# Plot predictions against known values*
title = 'Energy Production - Actual vs. Predicted'
ylabel='Production'
xlabel='Date'

ax = test.plot(legend=**True**,figsize=(12,6),title=title)
predictions.plot(legend=**True**)
ax.autoscale(axis='x',tight=**True**)
ax.set(xlabel=xlabel, ylabel=ylabel

我们可以看到预测值与实际值非常接近。如果我们计算模型的 MAPE 和 RMSE,我们分别得到 3.09 和 4 的值。我们可以将这些值与测试系列的平均值进行比较,以检查误差的大小是否可以接受。在这种情况下,它是。(我们无法将这些指标与平均和平滑方法进行比较,因为数据维度不同)

这就把我们带到了时间序列预测的第 2 部分的结尾。这是一篇相当长的文章,这里有太多的东西需要吸收。时间序列预测是一门科学,这只是冰山一角。这里有更多值得探索的地方。

下面是这篇文章的要点。

  1. ARIMA 模型基本上是回归模型,其中独立变量是序列的滞后值和/或滞后预测误差。
  2. 使用 ARIMA 模型进行预测的必要条件之一是序列应该是平稳的。
  3. 平稳序列具有恒定的均值、恒定的方差,并且对于等滞后的观测值,协方差大致相同。
  4. 时间序列的平稳性用扩展的迪基-富勒检验和 KPSS 检验来检验。如果序列不是稳定的,就使用差分法。可能只有一个差异(即使用 D 或 D)或两者都有。如果我们同时使用季节性差异和非季节性差异,建议在数据系列具有高度季节性的情况下首先使用季节性差异。
  5. 参数 AR(p)、MA(q)、s AR(p)、SMA(Q)使用 ACF 和 PACF 图来识别。有一些准则可以帮助粗略估计这些参数的顺序。但是,最终的模型是使用 auto.arima()函数构建的。
  6. 最终模型应该满足某些假设,如误差的正态性和残差之间的零自相关,即残差应该是白噪声。最终模型中所有参数的 p 值应该是显著的。

有许多链接对理解这个主题非常有帮助。下面是其中的几个。

  1. https://otexts.com/fpp2/index.html——这是著名的在线书籍《预测——原理与实践》的链接,作者是罗布·J·海曼和乔治·阿萨纳索普洛斯
  2. https://people.duke.edu/~rnau/411home.htm——理解预测的另一个非常有用的来源。我多次提到这几页。
  3. https://online.stat.psu.edu/stat510/lesson/4/4.1

希望这篇文章对你有用。一如既往,如果有任何问题或更正或建议,请告诉我。

使用 Scikit-Learn 进行主题建模简介

原文:https://towardsdatascience.com/introduction-to-topic-modeling-using-scikit-learn-4c3f3290f5b9?source=collection_archive---------7-----------------------

探索 3 种无监督技术,从文档中提取重要主题

托尔加·乌尔坎Unsplash 拍摄的照片

基于我以前关于自然语言处理的文章

让我们来探索如何使用另一个流行的机器学习模块scikit-learn来执行主题提取。在本教程中,我们将学习以下无监督学习算法:

  • 非负矩阵分解(NMF)
  • 潜在狄利克雷分配
  • TruncatedSVD(与 count 或 tfidf 矩阵一起使用时,也称为潜在语义分析)

至于数据集,可以选择使用自己的或者下载公开的 20 新闻组数据集。它由大约 20k 个与新闻组相关的文档组成。总共有 3 种变化:

  • 20news-19997.tar.gz—包含原始的未修改的 20 个新闻组数据集
  • 20news-bydate.tar.gz—除了删除重复项和一些标题外,数据集还按日期排序。分成训练和测试文件夹。
  • 20news-18828.tar.gz—删除重复的邮件,邮件头只包含发件人和主题。

我在本教程中使用了20news-18828数据集。为了使事情简单和简短,我将只使用 20 个主题中的 5 个。

  • 体育运动曲棍球
  • 宗教,基督教
  • 谈论。政治。中东
  • 比较图形
  • 科学地穴

scikit-learn’s Vectorizers期望一个列表作为输入参数,每一项用字符串表示一个文档的内容。您可以通过以下代码轻松处理数据集并将其存储在 JSON 文件中:

在将数据放入任何Vectorizers之前,从单个文件中读取数据要快得多。

请注意,我们创建的新数据集包含不必要的标题,如From,后跟电子邮件和人名。这样的噪音会影响你最终预测的结果。在实际的用例中,您应该删除它们,只保留与文档相关的信息。

让我们继续下一部分,开始安装必要的模块

设置

强烈建议您在继续安装之前创建一个虚拟环境。

sci kit-学习

您可以通过在终端中运行以下命令来轻松安装最新版本的scikit-learn:

pip install -U scikit-learn

熊猫

接下来,继续安装 pandas,这是一个强大的数据分析和处理工具。

pip install pandas

Numpy

在撰写本文时,最新的numpy版本是1.19.4。它有一个严重的错误,导致 Windows 操作系统出现以下错误。

The current Numpy installation fails to pass a sanity check due to a bug in the windows runtime

numpy背后的开发者发布了

“…解决此问题的错误修复 1.19.3。这个 bugfix 破坏了 Linux 上的其他东西,所以我们不得不在 1.19.4 版中恢复这个修复,但你仍然可以通过 pip install numpy==1.19.3 安装 1.19.3。”

换句话说,您应该根据您机器的操作系统安装工作版本。

  • Windows — 1.19.3
  • Linux — 1.19.4

运行下面的命令来安装numpy。相应地修改版本。

pip install numpy==1.19.3

您应该在虚拟环境中安装以下软件包。

cycler          0.10.0
joblib          1.0.0
kiwisolver      1.3.1
matplotlib      3.2.0
numpy           1.19.3
pandas          1.2.0
Pillow          8.0.1
pip             20.3.3
pyparsing       2.4.7
python-dateutil 2.8.1
pytz            2020.5
scikit-learn    0.24.0
scipy           1.5.4
setuptools      51.1.0
six             1.15.0
threadpoolctl   2.1.0

履行

在这一节中,我们将使用三种不同的算法来实现我们的主题建模代码。创建一个名为test.py的新 Python 文件。

导入

在文件顶部添加以下 import 语句。

import pandas as pdfrom sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizerfrom sklearn.decomposition import NMF, LatentDirichletAllocation, TruncatedSVDimport numpy as np
import json
import random

正在加载数据集

接下来,我们将加载之前创建的数据集。在将列表放入一个Vectorizer之前,将列表中的所有项目打乱是一个好主意。

corpus = []with open('data.json', 'r', encoding='utf8') as f:
    corpus = json.loads(f.read())
    random.shuffle(corpus)

变量

初始化下面的变量,稍后会用到。

n_features = 1000
n_components = 5
n_top_words = 20

n_components表示主题的数量,而n_top_words表示要为单个主题提取的热门单词的数量。

默认情况下,预测过程中没有相应主题的标签。需要自己识别,之后手动标注。

定义以下变量作为每个算法的标签:

nmf_topics = ['soc.religion.christian', 'sci.crypt', 'rec.sport.hockey', 'talk.politics.mideast', 'comp.graphics']lsa_topics = ['soc.religion.christian', 'sci.crypt', 'rec.sport.hockey', 'talk.politics.mideast', 'comp.graphics']lda_topics = ['talk.politics.mideast', 'rec.sport.hockey', 'soc.religion.christian', 'sci.crypt', 'comp.graphics']

此外,在每次运行期间,主题的顺序和排列不是有序的,特别是对于诸如 LDA 的概率模型。因此,您应该在运行整个训练和预测管道后修改这种安排。

计数矢量器

将一组文本文档转换成一个包含所有令牌计数的矩阵。有时,令牌计数被称为术语频率。

有一个非常有用的输入参数可以修改:

  • max_df —忽略频率高于给定阈值的术语。接受浮点数(范围从 0 到 1)或整数。Float 表示文档的比例,而 integer 表示绝对计数。
  • min_df —类似于max_df,但忽略频率低于给定阈值的术语
  • max_features —将只考虑给定的特征,这些特征在整个语料库中按词频排序
  • stop_words —接受要从语料库中删除的自定义停用词列表。您可以指定字符串english,它使用内置的英语停用词。
  • ngram_range —表示 n 元语法提取的上下边界的元组。

继续添加以下代码:

tf_vectorizer = CountVectorizer(max_df=0.95, min_df=2, max_features=n_features, stop_words='english', ngram_range=(1, 2))tf = tf_vectorizer.fit_transform(corpus)

它将删除出现在少于2个文档中或出现在至少95%个文档中的单词。将ngram_range设置为(1, 2)表示我们在对数据集进行矢量化时使用的是一元语法和二元语法。

tfidf 矢量器

CountVectorizer不同,TfidfVectorizer将文档转换为 TF-IDF 特征矩阵。最终结果类似于通过CountVectorizer后接TfidfTransformer的处理。

输入参数与CountVectorizer大致相同。除了基于字数和文档数的算法(如潜在狄利克雷分配(LDA ))之外,您应该尽可能这样做。

添加以下代码,初始化TfidfVectorizer并向量化文档的输入列表。

tfidf_vectorizer = TfidfVectorizer(max_df=0.95, min_df=2, 
max_features=n_features, stop_words='english', ngram_range=(1, 2))tfidf = tfidf_vectorizer.fit_transform(corpus)

输入参数与我们之前用于CountVectorizer的参数完全相同。

非负矩阵分解(NMF)

顾名思义,这种算法是用来寻找

“……两个非负矩阵(W,H),它们的乘积近似于非负矩阵 x。”

这些结果对降低特征维数和源分离非常有用。此外,它还可以用于主题抽取。

初始化

有几个输入参数可以微调。例如,您可以更改初始化程序的init参数:

  • random —非负随机矩阵
  • nndsvd —非负双奇异值分解。这是稀疏的首选。
  • nndsvdanndsvd用 x 的平均值填零,不需要稀疏的时候用。
  • nndsvdarnndsvd用小随机值填零。与nndsvda相比,速度更快但精度更低。

默认情况下,该值是随机的,除非n_components < n_features。如果是这种情况,将使用nndsvd

解决者

您可以使用以下选项之一调整数值solver参数:

  • cd —坐标下降
  • mu —乘法更新

贝塔损失

NMF可应用三种不同的目标函数(在 sklearn 中调用函数时称为beta_loss):

  • frobenius
  • kullback-leibler
  • itakura-saito —只能在mu solver中使用,输入矩阵 X 不得包含零。

目标函数在实例化时将默认为frobenius。当运行 NMF 时,时间复杂度是多项式的。

实例化 NMF

初始化一个新的实例,它接受TfidfVectorizer的输出矩阵。

nmf = NMF(n_components=n_components, random_state=1, alpha=.1, l1_ratio=.5, init='nndsvd').fit(tfidf)

alphal1_ratio与正规化有关。如果您不想进行调整,请将alpha值设置为 0。

LatentDirichletAllocation

LDA 是一种很好的生成概率模型,用于从文本语料库等离散数据集中识别抽象主题。

学习方法

scikit-learn中的 LDA 基于在线变分贝叶斯算法,支持以下learning_method:

  • batch —在每次更新中使用所有训练数据。
  • online —每次更新使用小批量的训练数据。训练数据量大的话会比batch快很多。

从 0.20 版本开始,默认learning_method为批量。

实例化 LDA

拟合 LDA 时,您应该使用CountVectorizer而不是TfidfVectorizer,因为 LDA 是基于术语计数和文档计数的。用TfidfVectorizer拟合 LDA 将导致稀有词被不成比例地采样。这样一来,他们会对最终的话题分布产生更大的冲击和影响。

使用以下代码创建一个新的 LDA 实例。

lda = LatentDirichletAllocation(n_components=n_components, random_state=1).fit(tf)

由于 LDA 是一个概率模型,所以每次运行它时,最终结果都会有所不同。因此,最好将random_state参数设置为一个固定的数字,并使用 pickle 在本地保存模型,以保留它稍后推断主题的方式。

潜在语义分析

另外,scikit-learn还附带了一个很棒很有用的降维模型,叫做Truncated Singular Value Decomposition ( TruncatedSVD)。与 PCA 不同,该模型计算奇异值分解时不将数据居中。

如果TruncatedSVD模型配有 count 或 tfidf 矩阵,它也被称为Latent Semantic Analysis (LSA)。大多数文章倾向于称之为 LSA,而不是 T9。为了保持一致,在本教程中我也将它称为 LSA。

算法

它支持两种不同的算法:

  • randomized —快速随机奇异值分解求解器
  • arpack —基于 SciPy 的 ARPACK 包装器作为特征值求解器

实例化 LSA

通过以下代码创建一个符合 tfidf 矩阵的新实例TruncatedSVD

lsa = TruncatedSVD(n_components=n_components, random_state=1, algorithm='arpack').fit(tfidf)

请注意,在执行转换之前,您应该将该类的实例与预定义的random_state匹配一次。这防止了sign indeterminnancy问题,因为转换的输出取决于算法和random_state

主题和推理

获取主题

完成后,让我们创建一个通用函数,以 DataFrame 的形式从模型返回主题。我们的实现基于下面教程中的函数,但做了一点改动。请根据您的用例随意修改它。

基于文本输入的推理

我们将需要另一个函数来对我们选择的任何输入文本进行推理。定义一个名为get_inference的新函数,并在其中添加以下代码。

这是我自己的实现,它返回

  • 可信度最高的主题标签
  • 所有主题的置信度值
  • 超过特定阈值的所有主题的标签

请注意,根据所使用的算法,特定主题的置信度值可以是负数。

结果

最后一步是运行我们之前创建的两个函数,并打印出结果。我将使用下面的输入文本,其中应该映射到comp.graphics

text = 'you should use either jpeg or png files for it'

继续调用我们所有模型上的函数。

对于NMF,我得到了以下输出,它展示了输入文本的主题分布和最终推断:

作者图片

尽管最终结果是准确的,但是LSA的结果却不太乐观。基于主题分布,有相当多的词被错误地建模。

作者图片

另一方面,LDA返回了以下结果。单词edu被预测为三个话题的最热门单词。这主要是因为我使用的数据集有From标题,其中包含相当多以.edu结尾的电子邮件地址。

作者图片

请注意,主题和热门词汇的顺序可能会在每次运行时有所不同,尤其是如果您没有指定random_state或使用online学习。

如果您想在每次执行时保留相同的结果,可以考虑使用pickle在本地保存Vectorizer和模型。

结论

让我们回顾一下今天所学的内容。

我们从探索 20 个新组数据集开始,这些数据集分为三个不同的类别。我们还处理了数据,只使用了 5 个主题,而不是完整的数据集。

然后,我们继续安装必要的 Python 模块,并将数据集加载到 Python 文件中。

此外,我们还创建了 CountVectorizer 和 TfidfVectorizer,用于在将文档拟合到我们的模型之前对它们进行矢量化。

我们基于non-negative matrix factorizationlatent dirichlet allocationTruncatedSVD构建了三个不同的模型。

最后,我们创建了通用函数来获取主题,并从我们构建的模型中执行推理。

感谢你阅读这篇文章。希望在下一篇文章中再见到你!

参考

  1. 20 个新闻组数据集
  2. StackOverflow — Numpy 运行时问题
  3. SkLearn —话题抽取

用 Airflow 和 SQLAlchemy 反思数据库

原文:https://towardsdatascience.com/introspecting-databases-with-airflow-and-sqlalchemy-6ef18d85acce?source=collection_archive---------16-----------------------

迭代自动自省数据库对象的教程

pawebukowskiUnsplash 拍摄的照片

在最近一个利用了气流的数据迁移项目中,我需要连接到一个数据库并自动自省它的模式和表。一个需要内省的数据库有数百个模式。每个模式都有几十个不同的表,其中大多数都有不同的列和列约束。

换句话说,我们的数据库元数据由成千上万的对象组成,没有人会手动将这些对象输入到配置文件或硬编码的 Python 列表中。知道了 Airflow 使用 SQLAlchemy 模块尽可能地用方言和引擎与数据库通信,我有一种预感,我可以利用 Airflow 与数据库的 SQLAlchemy 连接来生成模式、表、列或我需要访问的任何数据库对象的列表。

我的预感是对的!SQLAlchemy 和 Airflow 的 DB API 钩子使得获得任何连接数据库的 SQLAlchemy 引擎变得容易。

预赛

这个演示需要遵循几个初步步骤。我们将使用 PostgreSQL,但几乎任何常见的数据库都可以。

安装气流

从这里的开始。用对接器安装很容易。

创建 PostgreSQL 数据库

AWS 提供了一个关于如何做的快速指南。如果您愿意,可以用表填充public模式(或其他模式),并插入一些数据。(如果已经有了一个填充了可以连接的模式和表的 Postgres 数据库,可以跳过这一步。)

气流设置

以下步骤可以通过 Airflow CLI 完成,但 web UI 简单而漂亮。

运行气流

运行气流调度程序和 web 服务器。如何运行气流包含在气流入门教程中。一旦气流开始,将你的浏览器指向网络用户界面。如果您通过 Docker 或本地安装了 Airflow,URL 很可能是http://localhost:8080/

创建到 Postgres 数据库的连接

从 web UI 的导航栏中,单击管理 > 连接

通过 Airflow web UI 创建 Postgres 数据库连接

点击蓝色的 + 按钮添加一个新的连接。

通过 Airflow web 用户界面添加新连接

输入您的数据库主机连接详情,并点击保存按钮。注意:“模式”字段实际上是您想要连接的数据库。我正在使用我的dvdrental数据库中现成的 DVD 租赁数据。记下您的连接 Id ,因为我们在下一步中需要它。

通过 Airflow web UI 定义您的 Postgres 数据库连接

创建 DAG

在气流安装过程中创建的dags文件夹中,添加一个名为introspect_db.py的 Python 文件。将此 DAG 代码复制并粘贴到文件中。如果你有 Conn Id postgres_conn,保持代码不变。否则,更改pg_hook分配行以反映您的连接 Id

import logging
import re
from typing import List

from airflow import DAG
from airflow.operators.dummy import DummyOperator
from airflow.operators.python import PythonOperator
from airflow.providers.postgres.hooks.postgres import PostgresHook
from airflow.utils.dates import days_ago
from airflow.utils.task_group import TaskGroup

from sqlalchemy.inspection import inspect
from sqlalchemy.engine.reflection import Inspector
from sqlalchemy.engine import Engine

def log_info(info, *args, **kwargs):
    logging.info(f"info={info}")
    logging.info(f"args={args}")
    logging.info(f"kwargs={kwargs}")

default_args = {
    "owner": "airflow",
}

with DAG(
        dag_id="introspect_db",
        default_args=default_args,
        schedule_interval="@once",
        start_date=days_ago(2),
) as dag: pg_hook = PostgresHook(postgres_conn_id="postgres_conn")
    pg_engine: Engine = pg_hook.get_sqlalchemy_engine()
    pg_inspector: Inspector = inspect(pg_engine)

    schema_names: List[str] = pg_inspector.get_schema_names()

    schema_task_groups: List[TaskGroup] = [
        TaskGroup(group_id=f"{s}") for s in schema_names
    ]

    for schema_tg in schema_task_groups:
        # Ex. of schema_tg.group_id: "public"
        schema_name: str = schema_tg.group_id

        table_names: List[str] = \
            pg_inspector.get_table_names(schema=schema_name)

        table_task_groups: List[TaskGroup] = [
            TaskGroup(group_id=f"{t}", parent_group=schema_tg)
            for t in table_names
        ]

        for table_tg in table_task_groups:
            # Ex. of table_tg.group_id: "public.actor"
            table_name_p = re.compile(r"^\w+\.(\w+)$")
            table_name: str = re.match(
                table_name_p,
                table_tg.group_id
            ).group(1)

            start_table = PythonOperator(
                task_id=f"start_{table_name}",
                task_group=table_tg,
                python_callable=log_info,
                op_kwargs={
                    "info": [
                        f"table_tg.group_id={table_tg.group_id}",
                        f"table_name={table_name}",
                    ]
                }
            ) end_table = DummyOperator(
                task_id=f"end_{table_name}",
                task_group=table_tg
            ) start_table >> end_table start_schema = PythonOperator(
            task_id=f"start_{schema_name}",
            task_group=schema_tg,
            python_callable=log_info,
            op_kwargs={
                "info": [
                    f"schema_tg.group_id={schema_tg.group_id}",
                    f"schema_name={schema_name}",
                ]
            }
        ) end_schema = DummyOperator(
            task_id=f"end_{schema_name}",
            task_group=schema_tg
        )

        start_schema >> table_task_groups >> end_schema

    start = DummyOperator(task_id="start")
    end = DummyOperator(task_id="end")

    start >> schema_task_groups >> end

DAG 代码中有几个片段值得一提。

片段 1。第一个代码片段(如下)说明了如何获取数据库的模式名。首先,使用 Postgres 连接(如上定义)获得一个 Postgres 挂钩。这个钩子用于获取 SQLAlchemy 引擎。反过来,该引擎用于检查连接的数据库中所有模式名称的列表。

# Snippet 1pg_hook = PostgresHook(postgres_conn_id="postgres_conn")
pg_engine: Engine = pg_hook.get_sqlalchemy_engine()
pg_inspector: Inspector = inspect(pg_engine)schema_names: List[str] = pg_inspector.get_schema_names()

片段 2。下一个代码片段演示了如何为每个自省模式创建一个 TaskGroup 对象列表。我们迭代每个模式 TaskGroup 对象,从模式 TaskGroup 的组 ID 中获取每个模式名称作为字符串,然后在模式中执行某种工作。

# Snippet 2schema_task_groups: List[TaskGroup] = [
    TaskGroup(group_id=f"{s}") for s in schema_names
]for schema_tg in schema_task_groups:
    # Ex. of schema_tg.group_id: "public"
    schema_name: str = schema_tg.group_id ...

片段 3。在这种情况下,我们在每个模式中所做的“工作”是自省模式的所有表。为了做到这一点,我们采用了与模式相似的方法。然而,这一次我们需要做两件不同的事情。首先,为了创建每个表 TaskGroup 对象,我们需要将schema_tg TaskGroup 对象传递给parent_group参数。其次,我们需要从表 TaskGroup 对象的group_id中解析出表名。任务组 ID 的格式是<schema>.<table>,所以我使用了re regex 模块来解析出表名。例如,对于一个表任务组 ID 为public.actor,正则表达式模式^\w+\.(\w+)$将允许我们提取任务组 ID 的actor部分。

# Snippet 3 table_names: List[str] = \
        pg_inspector.get_table_names(schema=schema_name)

    table_task_groups: List[TaskGroup] = [
        TaskGroup(group_id=f"{t}", parent_group=schema_tg)
        for t in table_names
    ]

    for table_tg in table_task_groups:
        # Ex. of table_tg.group_id: "public.actor"
        table_name_p = re.compile(r"^\w+\.(\w+)$")
        table_name: str = re.match(
            table_name_p,
            table_tg.group_id
        ).group(1) ...

片段 4。最后,注意任务依赖是如何定义的。任务对startend以及start_schemaend_schema是单个任务。在每个任务对之间是一个变量,代表一组 TaskGroup 对象。这类似于用类似于task_1 >> [task_2, task_3] >> task_4的列表定义任务依赖关系,因为schema_task_groupstable_task_groups是 TaskGroup 对象的列表

# Snippet 4 start_schema >> table_task_groups >> end_schema ...start >> schema_task_groups >> end

代码准备好了。现在,我们可以与 web 用户界面进行交互。

查看 DAG 的结构

http://localhost:8080/返回 web UI,点击 introspect_db DAG 链接,然后点击图形视图按钮。您应该在 web UI 中看到模式任务组。

我的看起来像这样。

图表视图中的方案任务组

单击其中一个模式任务组将其展开。您应该可以在所选的模式任务组中看到表任务组。

图表视图中的表任务组

最后,单击其中一个表任务组将其展开,您将显示表组中的任务。

图表视图中表任务组中的任务

结论

在本教程中,我们使用了 Airflow 中包含的工具来自省数据库的对象,将这些对象反映为嵌套的任务组,并遍历这些对象。您在任何级别上对对象做什么工作都由您决定。我希望这个指南对解决你的类似问题有所帮助。感谢阅读!

A/B 样本规模背后的直觉

原文:https://towardsdatascience.com/intuition-behind-a-b-sample-sizing-cb7e9c4fb992?source=collection_archive---------16-----------------------

了解埃文·米勒的样本量计算器

马库斯·斯皮斯克在 Unsplash 上的照片

TLDR: 这篇文章展示了埃文·米勒网站上样本量计算器背后的 R 代码(和数学)。

为什么要阅读另一篇关于这方面的文章呢?

在由 Diane Tang 和谷歌团队在 Udacity 开设的关于 A/B 测试的热门课程中,他们简要讨论了“大小与功率的权衡,并建议用户参考 Evan Miller 的在线计算器来确定α & β的理想水平所需的样本大小。但是如果你像我一样喜欢打开黑匣子,这篇文章就是为你准备的。(如果你想跳过数学,只得到代码,滚动到最后。)

让我们从一个简单的设置开始

  • 假设我们网站上“订阅”按钮的当前点击率(CTR)为 25%(即,当用户加载页面时,有 25%的概率会点击它。)
  • 现在假设,我们提出一个我们认为(即假设)会增加 CTR 的设计变更。虽然我们不知道这种变化需要测试多少,才能产生实际的商业意义,但至少需要提高 2 个百分点(即从 25%增加到至少 27%)。

A/B 测试是这个测试的完美框架。然而,在运行测试之前,我们需要确定运行测试的样本大小。应该是 100 个用户、10000 个用户还是 1000 万个用户?(你懂了大意)**

假设我们保持对照组和治疗组的样本大小相等(=N),让我们看看我们对α & β的选择如何驱动 N 的最小值。

α对样本量的影响

α或“显著性水平”表示类型 1 错误的概率,这是 P(拒绝 Null | Null 为真),在以下假设下(注意这是一个* 双尾检验) 😗

如果我们只对控制 1 型误差感兴趣,那么对于选定的α值,我们可以使用以下等式来确定所需效应(δ,在我们的例子中为+2%)所需的最小 N 值(如果检测到,则为“统计显著”),或者确定对于给定的 N 值具有统计显著性的最小正效应(δ min)(在下面的等式中,我们使用α/2,因为这是一个双尾测试。然而,我们只关注右端的尾部,因为从商业角度来看,我们只对δ的正值感兴趣。)

上面的公式是从下面给出的 t.test 公式推导出来的,有两个简化:

  • 对照组和治疗组的样本量相等,等于 N
  • 给定我们的零假设,对于对照组和治疗组,二项分布的概率(=25%,本例中的 CTR)是相同的。

使用混合方差计算检验统计量:

哪里,

  • 下标 C & T 分别表示对照组和治疗组,
  • P 是二项式分布的概率(在我们的示例中,它代表 CTR,更一般的是基本转换率)

然而,在我们的实验中,我们还希望控制 2 型误差,用β表示。让我们看看这如何影响我们的样本量估计。

β对样本量的影响

β度量 2 类错误的概率,为 P(拒绝 Null 失败| Null 为假)。

但是让我们考虑一下这个问题。说‘当 Null 为 false 时’是什么意思?在我们上面的设置中,空值是“δ = 0”。因此,对于δ的任何(真)非零值,空值将为假。对于δ =-0.05(如果由于某种原因我们提议的变更恶化了 CTR),或者对于δ =+0.001(如果提议的变更改善了 CTR,但只是略微改善),它将是假的。然而,对于这两种情况,给定 N 的β值(反之亦然)会非常不同。那么,我们对‘Null is false’的哪个版本感兴趣呢?

答案是我们只对 Delta 至少大到+2% 的版本感兴趣。这与前面提到的具有实际意义的最小量+2%相同。

  • 在(真)δ < +2%, we don’t care about β, because the result is of no practical importance to us anyway.
  • And, for scenarios where (true) δ ≥ +2%, as long as we control β for δ = +2% case, β for cases where δ > +2%的情况下,将在我们的公差范围内。这是基于β随δ增加而减小的事实。

在讨论方程之前,让我们以一种更直观且与我们上面的评论一致的方式重新陈述我们的零假设。(注意这是一个* 单(左)尾测试)*

在这些新的假设下,我们可以将β表示为 P(拒绝 Null | Null 为真)。这类似于我们在原始假设下表达α的方式。

将这一切结合在一起

等式(1)和(2)给出了δ的范围,分别满足我们期望的α和β水平。为了确保在满足α容差的δ最小值下,我们的测试全部满足β容差,我们将两个等式相等,并估计 N 的最小值如下:

例子

在我们的示例中,N 的值等于 7,415。参考下面的 R 代码。

这与埃文·米勒的计算器得出的值一致

来源:埃文·米勒的计算器

感谢您的阅读。如果你有问题或意见,请留言。

中心极限定理背后的直觉

原文:https://towardsdatascience.com/intuition-behind-central-limit-theorem-8dc1ca40de1a?source=collection_archive---------16-----------------------

莱昂纳多·巴尔德斯拉号航天飞机上的照片

中心极限定理 (CLT)是统计学领域最基本的概念之一。没有它,我们将在现实世界中游荡,遇到的问题多于解决方案。它的应用非常广泛——从参数估计到假设检验,从制药行业到电子商务。在任何行业中,几乎没有任何实证研究可以不利用 CLT 原理。一个多世纪前的一句话总结了 CLT 的重要性。

“我几乎不知道有什么比[中心极限定理]所表达的宇宙秩序的奇妙形式更能打动想象力了。如果希腊人知道的话,他们会将法律拟人化并神化。”

——弗朗西斯·高尔顿爵士,1889,自然遗传

在我们深入探究神秘莫测的中心极限定理(CLT)世界之前,我们需要理解几个术语来理解和表达潜在的语言。在本博客中,我们将首先了解人口与样本、参数与统计、推断统计的相关性以及抽样分布。我们还将从人群中提取一些样本并进行比较,为 CLT 奠定基础。我们最终会以 CLT 的正式定义,它的局限性和一个在实践中可以看到的 CLT 原则的例子来结束这篇文章。

人群对比样本

什么是群体,它与样本有何不同?

人口 指一组/一组数据中的每一个成员所有的美国公民,一个城市的所有居民,一所学校的所有学生,等等。进行调查以收集全部人口数据的过程称为 人口普查

样本 指时间和资源允许测量的人群中的成员子集。进行调查以收集样本数据的过程称为 样本调查

取样流程

采样有多有用?

让我们考虑一下在印度首都地区引人注目的连锁企业 81C 面包店。该公司希望推出一个新的标志,以更好地与目标受众——30 岁以下的成年人——联系起来。该公司必须从内部利益相关者小组列出的三个相关设计中选择最佳设计。公司是如何着手的?明智的做法是收集目标受众的反馈,考虑他们的意见,然后再决定哪种设计最能引起群体的共鸣。

然而,公司是否应该对所有客户(现有的或潜在的)进行调查,以找出最合适的设计?从时间和成本的角度来看,这难道不是一项极其昂贵的工作吗?

采样的魔力来了。公司需要做的只是从总体中选择有限的一组成员,并对这组样本进行调查。随后,利用抽样调查的结果,公司可以得出关于人群偏好(特征)的(合理)结论,并选择最佳标志设计继续前进。请记住,样本需要是无偏的代表总体的,并且需要从相关总体中随机抽取。只有这样,样本才可以作为合适的代表来帮助人们解决手头的问题。

样本需要无偏代表总体的,并且需要从相关总体中随机抽取

参数与统计

什么是参数,它与统计数据有何不同?

参数 是描述总体(特征)的数字/数量,而 统计 是描述样本的数字/数量。用于描述人口/样本特征的数字可以是对集中趋势(平均值、中位数或众数)的度量,也可以是对离差(方差、标准差、范围或四分位间距)的度量。

以下是在总体和样本背景下几个重要且广泛使用的度量的符号和公式。在下表中, x 表示总体或样本集中的个体值。

推断统计的相关性

样本统计有什么用?

在推断统计学的帮助下,我们可以使用(样本的)统计数据进行有根据的猜测,并得出(总体的)参数的结论。同时也可以理解推断结论中的置信度(或不确定性)。由于我们只能收集和研究有限的数据集,而不是整个人口,因此与人口参数估计相关的不确定性出现了。

置信区间是一个区间估计(两个值之间的范围),用于表示与总体参数估计相关的不确定性。给定一个样本统计量,我们可以有把握地估计真实总体参数(如均值)的区间。换句话说,区间只是表明在一定的置信水平下,真实的总体参数位于估计的范围内。例如,我有 90%的信心,真实的人口平均数在 9.05 和 11.25 之间。

如果你对置信区间的概念及其计算更感兴趣,可以参考文章

样本的唯一性和局限性

为什么统计值不能为我们提供参数的精确值而不是估计值

假设约翰、迈克和凯文每个人都分别被分配了任务去推断印第安纳州霍金斯的一个假想城镇的居民的平均年龄。让我们假设这三个人都被分配了单独的资源来解决手头的问题,并且他们在整个练习过程中不会相互协作。每个人从人群中随机抽取 100 个年龄。

你认为任何样本的平均年龄(统计数据)会与城市人口的平均年龄(参数)相同吗?嗯,很可能不是,因为样本由于其受限制的大小( n )而只能获得关于总体的有限的信息,因此没有足够的技能来辨别准确的参数值本身。然而,三个样本统计值中的任何一个仍然可能偶然等于参数值,即使这种事件发生的可能性很小。

你认为 Mike 样本的统计值(平均年龄)会与 Kevin 样本的统计值完全匹配吗?同样,很可能不会,因为每个样本很可能以来自总体的一组不同的值结束,从而产生一个唯一的统计值。然而,两个不同的样本仍然可能偶然地具有相同的一组值,即使这种事件发生的概率非常低。

让我们从总体中抽取三个不同的样本,见证一个样本在行动中的“唯一性”和“局限性”。

这是霍金斯小镇所有 15 万居民的(模拟)年龄分布。分布的形状是伽玛,人口的平均年龄(参数)是 18 岁。

印第安纳州霍金斯的模拟人口

让我们通过随机独立从人群中选择 100 个年龄,为每个约翰、迈克和凯文准备单独的样本。“独立”确保任何选择都不依赖于先前的选择。因此,我们很可能在样本中再次发现相同的年龄。只有通过在下一次选择发生之前用替换群体中的一个值,才能保证这一条件。

下图以地毯图的形式显示了三个样本的分布。每个样本的成员值由接触 x 轴上侧的刻度表示。

你有没有注意到年龄组的独特性,以及每个样本的统计数据(平均年龄)的独特性?所有统计值(17.84、16.21 和 19.12)彼此不同,并且与群体参数(18.0)也不同。然而,统计值似乎是围绕参数旋转的。

统计值的方差(或抽样误差)的出现是因为每个样本通过其自己的唯一有限窗口窥视(和访问)总体——唯一性的出现是由于随机抽样和有限样本大小的限制。

如果我们从人群中抽取数千个样本,会发生什么?许多(统计值)的力量能以某种方式揭示真实的参数吗?

采样分布

如果我们从总体中抽取数千个构造相似的样本(随机且独立,每个样本大小为 100)并计算每个样本的平均年龄(统计),我们可以绘制一个直方图,称为 采样分布 ,以展示收集的数千个平均统计值的频率。请记住,John、Mike 和 Kevin 只是构成下面抽样分布的成千上万个样本中的三个。

抽样分布是由样本统计的所有可能值组成的概率分布。它显示了从同一总体中抽取的每个可能的样本(大小为 n) 中统计值可能出现的频率。

请记住,统计数据可以是均值、中值、方差或任何其他定量描述样本(特征)的度量。然而,对于当前的问题,我们特意选择了平均值作为统计量,因为 CLT 原则仅适用于平均值统计量/参数。

下面是从上面的抽样分布中得到的一些重要观察结果。

  • 在样本大小( n )为 100 的情况下,抽样分布的形状被证明是近似正态(又名高斯)且对称的,即使原始人口分布向右倾斜。正如我们将在后面看到的,人口分布越偏斜或不对称, n 就必须越高,抽样分布才能接近正态形状。
  • 统计值/样本均值的平均值,也就是统计值(平均年龄)的期望值,为 18.01 岁,与参数(人口平均年龄= 18.0 岁)非常接近,可以毫无保留地认为等于参数。统计值的期望值,用 E() 表示,是统计值在重复抽样中的长期平均值,因此是我们对任何特定试验中该值的最佳猜测。
  • 统计的标准误差,简单来说就是样本均值的标准差,是 1.83 年。它表示抽样分布有多分散,或者在样本的平均年龄中观察到的方差有多大。我们将在后面看到, n 越高,标准误差就越低。

整个过程——抽样、计算统计值(平均值)和寻找统计值的期望值——是 CLT 的基础,可以形象地概括如下。

样本大小对样本分布的影响

样本大小对抽样分布有影响吗?如果是,为什么?

事实证明,样本大小对样本分布的形状和宽度有着深远的影响。让我们看看当样本大小( n )改变时,抽样分布是如何变化的。

下面是从 Hawkins 的人口(年龄)中产生的抽样分布,但是具有不同的样本大小(注意每个图右上角的图例)。

在改变样本大小 n 时,我们观察到两件重要的事情。

  • 随着样本量的增加,抽样分布接近于正态分布。 n =15 的抽样分布是不对称的——它稍微向右倾斜(左边部分的宽度大致为 9.75 年,而右边部分的宽度超过 14 年),模仿原始人口分布。将样本大小增加到至少 100 会使分布呈现对称性,因此呈正态分布。

样本量越大,形状越接近正态曲线。

  • 随着样本量( n) 的增加,统计的标准误差(分布的宽度)减小。

想一想这个问题。如果一个样本有能力挑选出(几乎)所有的人口,难道它就不能非常有把握地告诉我们总体的平均值吗?为什么这些样本的平均值会有任何(明显的)差异?请注意,在最后一个采样分布中,n =150k(等于整个人口的大小),平均年龄的标准误差最小,为 0.03 岁。

根据同样的推理,如果每个样本在抽样过程中能够挑选出更少的总体成员,从而获得更少的总体信息,那么这些样本的均值将显示出更高的方差。这从上面的采样分布中可以明显看出,其中 n =15、100 和 500。随着我们增加 n ,样本均值的方差减小。你还记得约翰、迈克和凯文的样本的平均值吗,每个样本的大小都限制在 100?你还记得它们不相等,因此显示出一些差异吗?

随着样本量的增加,统计的标准误差减小。

中心极限定理

这是 CLT 的一个更正式的定义;这基本上就是我们到目前为止所讨论的内容。

如果我们抽取样本,每个样本的大小为𝑛,并计算每个样本的平均值,我们将期望获得一个值的分布,称为平均值的抽样分布。CLT 指出,对于大型随机样本,无论被抽样的总体/过程是如何分布的,均值的抽样分布都是近似正态的。样本量 n 越大,抽样分布就越接近精确的正态分布。

CLT 术语的符号

表示(样本均值的)抽样分布的符号如下,其中' ~ '读作“分布为”,“N”读作“正态”。

CLT 建立了抽样分布特征与相关总体分布特征之间的关系,如下所示。

注意,随着 n 的增加,平均统计的标准误差减小。这也正是我们在上一节中观察到的。

根据上面的公式,我们也可以说样本均值呈正态分布,其均值(即期望值)等于总体均值,其方差等于总体方差除以构成抽样分布的样本大小。因此,CLT 的精髓可以在下面的公式中得到体现。

根据 CLT 原理,当样本量时,达到采样分布的(近似)正态性。但是样本量应该有多大才能达到样本分布的正常形状呢?

尽管许多书籍/文章推荐n30 作为经验法则,样本的大小取决于人口的形状。如果潜在的(人口)分布是近似对称的,那么我们的抽样分布应该是非常正常的。在这种情况下,我们甚至可以将 n 减少到 10。但是,如果基本分布严重偏斜,那么我们需要增加样本量,以获得样本分布的正常形状。还记得 Hawkins 居民的年龄偏右的情况吗,我们需要 100 的样本量来得到样本分布的正态形状?

下图显示了四种不同类型的人口分布的抽样分布。为了在相应的抽样分布中实现像样的正态形状,对于给定的正态、均匀、伽玛和双峰总体分布,分别需要 10、25、100 和 250 的最小样本量。

CLT 的局限性

只有当满足下列条件时,CLT 原理才能应用于一个问题。

a)总体必须有一个有限的平均值和方差。例如,柯西分布就是这样一种没有定义均值和方差的分布,因此不符合 CLT 原理。也就是说,大多数现实世界的案例都涉及有限的均值和方差。

b)CLT 建立的总体分布特征与抽样分布特征之间的关系仅适用于均值统计量,不适用于样本的方差、标准差、众数或中位数。

c)对于正态、均匀或其他对称的总体分布,样本大小可以低至 10。然而,对于一个不对称的总体,根据分布的偏斜程度,样本量需要增加到一个较大的值(也许是数百)。因此,除非我们确信总体是对称分布的,否则只有当样本量很大时,我们才应该应用 CLT 原理。

d)我们需要确保抽样以随机和独立的方式进行。在一个样本中,如果对其任何成员的选择依赖于对任何其他成员的选择,那么抽样就不是独立的。在这种情况下,我们不能应用 CLT 原理根据总体分布的特征来辨别抽样分布的特征,反之亦然。

例题

这是一个展示 CLT 原理应用之一的解决方案的问题。

问题:谷歌 Waymo 的使命是通过推出市场上最安全的自动驾驶电动汽车来颠覆汽车行业。这家公司不仅关心社会和环境,也关心员工。人力资源部计划在今年夏天的某个星期五为员工举办一次野餐。100 个人响应参加 4 小时的郊游。活动的组织者为与会者准备了 53 加仑的水。在夏天四个小时的郊游中,一个成年人平均需要半加仑的水;需水量的变化是 0.01 加仑平方。组织者需要知道团队在野餐结束前用完可用水的概率是大于还是小于她的阈值 5%。

解决方案:

由于对水的需求因人而异,所以一个成年人在夏季外出 4 小时所需的水量可以认为是一个均值为 0.5 加仑、标准差为 0.1 加仑的分布,即方差为 0.01 的平方根。我们可以把这种分布看作形状未知的关注人群。

如果我们从人口分布中随机选取 100 个需水量样本,我们将得到一个唯一的(统计)人均需水量值。如果我们要抽取五万个结构相似的样本,我们最终会得到一个人平均需水量的抽样分布。

根据 CLT 原理,不管原始总体分布的形状如何,对于大量随机样本,抽样分布应接近正态分布,其期望值等于总体均值,其标准误差等于总体的标准偏差除以样本大小的平方根。当然,我们假设人口分布并没有荒谬地远离对称形状,因此,100 是一个足够“大”的样本量,足以使 CLT 原则适用于手头的问题。

抽样分布可以表示如下。

100 名员工有 53 加仑的水,平均每个人有 0.53 加仑的水可用。我们需要做的就是计算出一个样本每人需要超过 0.53 加仑水的概率。通俗地说,50,000 个样本(在抽样分布中)中有多少个样本需要每人 0.53 加仑以上?

给定采样分布的标准偏差为 0.01,很容易意识到样本统计量(0.53)在右侧距离平均值 0.5 有 3 个标准偏差。这被称为样本统计的 z 得分,它告诉我们样本统计与平均值的差距,即分布的标准差。(你可以在这里阅读更多关于 z-score

如下图所示,在正态分布中,大约有 99.7%的数据落在距离平均值 3 个标准差以内。由于 0.53 位于右侧,距离均值 3 个标准差,其出现的概率为 0.15% —参考下面正态分布最右侧的微小区域。

回答:组织者可以放心,团队用完 53 加仑水的概率远低于她设定的 5%的门槛水平。

总结:以下是解决手头问题的步骤要点。

  • 参数——总体的平均值和标准偏差——被提供给我们,
  • 利用 CLT 原理,计算抽样分布的特征——统计量的期望值和标准误差,
  • 给定的统计值(每人 0.53 加仑)在抽样分布中的位置被确定,并且
  • 基于正态分布的已知特征,估计统计数据出现的概率。

我希望这篇文章能帮助你很好地理解中心极限定理背后的上下文和直觉,以及它的原理和应用。如果一开始觉得难以接受,一两天后再看一遍。很容易与一些技术术语混淆,如样本、样本均值和样本分布,但如果你耐心地按照文章中描述的顺序一次理解一个,那么一切都会变得有意义。

如果您有任何问题或反馈,请随时留下您的评论。你也可以通过我的 LinkedIn 个人资料联系我。

甘辨伪背后的直觉

原文:https://towardsdatascience.com/intuition-behind-gans-discriminator-122ed821e9e5?source=collection_archive---------27-----------------------

打造您的 GAN 系列——第 2 部分,共 4 部分

图片由 Ohmydearlife 来自 Pixabay

生成对抗网络由两个网络组成,一个生成器和一个鉴别器。在本教程中,我们将看看鉴别器是如何工作的。

有用的链接

这是构建你的生成性敌对网络的第二部分:

第一部分:生成对抗网络背后的直觉
第二部分:甘鉴别器背后的直觉 (this)
第三部分:甘生成器背后的直觉
第四部分:训练生成对抗网络

笔记本:训练甘生成手写数字
GitHub repo :包含本教程系列

什么是量词?

看这张照片:

生成的一只猫的图像,这些猫并不存在

没费多大力气就知道这是一只猫的照片。即使它像狗一样有四条腿和一条尾巴,你也可以 100%确定这是一只猫而不是一只狗。神经网络分类器的目标是执行与您刚才所做的相同的操作,将此图像分类为“猫”,而不是“狗”。

分类器是一个神经网络,它接受特征,并输出一组类别的概率。例如,如果我们将一只猫的图像输入分类器,它会产生一组概率,其中所有概率的总和是1

一开始,它做得很糟糕,将0.5分为catdog两类。这意味着模型认为这个图像有 50%的可能性是一只猫,另外 50%是一只狗。

鉴别者认为这个图像 50%是一只猫。[图片由作者 ]

这是我们想要修正模型的时候,这样它就可以改进它的预测。我们将输入正确的答案,即1代表猫,0代表狗,模型将使用“成本(或损失)函数”计算其预测与正确标签的差距。

有了成本函数,我们可以在网络中更新那些内部参数,称为“权重”,根据这个成本函数的梯度,在下一次预测猫和狗时变得更好。在我们向模型展示了数千张猫和狗的照片后,它会调整自己的权重,以学习猫长什么样,狗长什么样。

鉴别器是一个分类器

鉴别器是一个分类器,它确定输入样本是真的还是假的。这些输入样本可以是来自训练数据的真实样本,也可以是来自生成器的虚假样本。

最初,它的表现很差,将假样本错误分类为real。判别网络的权值被更新以减少其分类误差。在转动它的重量几圈后,它能更好地区分真假样品。

在概率方面,鉴别器模拟给定一组输入X的假样本的概率。在多类上下文中,鉴别器模拟样本是特定类的可能性。

鉴别器模拟给定一组输入的样本概率X。[图片由作者

例如,给定由生成器生成的一张一美元钞票的图像,如果鉴别器确定这是一张假钞的概率为 13%,则鉴别器认为这是一张真的一美元钞票。在这种情况下,当训练具有 sigmoid 输出的标准二元分类器时,成本函数,二元交叉熵损失(torch . nn . bcewithlogitsloss)被最小化。

PyTorch 代码

摘自古德菲勒、伊恩等人的《生成性敌对网络》论文:

当模型都是多层感知器时,对抗性建模框架最容易应用。我们还定义了第二个多层感知器 D(x;θd ),它输出单个标量。D(x)代表 x 来自数据而不是 pg 的概率。我们训练 D 以最大化将正确标签分配给训练样本和来自 g 的样本的概率

我们将构建四层的鉴别器。网络接受图像张量并返回单个值,该图像是真实还是虚假的概率。由于 MNIST 图像的大小是 28x28,我们将使图像变平,这给了我们一个输入维度784

笔记本:训练甘生成手写数字

概括起来

鉴别器是一个分类器,旨在捕捉条件概率P(y|x)。它学习在给定一组输入特征的情况下,对一个实例是真的还是假的概率进行建模。来自鉴别器的输出概率是分类标签。

判别模型的目标是检测虚假生成的数据,因此训练判别神经网络以最小化最终分类误差。它通过查看生成器创建的真实样本和假样本来学习区分不同的类别,并尝试辨别哪些是真实的,哪些是假的。

GitHub repo :包含本教程系列

下一步是什么?

让我们看看发电机是如何工作的。

甘发电机背后的直觉

原文:https://towardsdatascience.com/intuition-behind-gans-generator-e66f6b0dfa7c?source=collection_archive---------39-----------------------

打造您的 GAN 系列——第 3 部分,共 4 部分

图片来自 Pixabaypeter_pyw

生成对抗网络由两个网络组成,一个生成器和一个鉴别器。在上一个教程中,我们已经看到了鉴别器是如何工作的,在这个教程中,我们将看看发生器是如何工作的。

有用的链接

笔记本:训练甘生成手写数字
GitHub repo :包含本教程系列

这是构建你的生成性敌对网络的第 3 部分:

第一部分:生成对抗网络背后的直觉
第二部分:甘鉴别器背后的直觉
第三部分:甘生成器(this)
第四部分:训练生成对抗网络

什么是输入和输出?

生成器的目标是根据输入特征生成样本。我们输入到生成器中的有两个输入特征,1)类别和 2)噪声。

生成器根据输入特征、1)类别和 2)噪声生成样本。[图片由作者

。如果我们已经用猫和狗的图像训练了我们的模型,那么通过请求一只“猫”,我们期望生成器输出一只看起来很棒的猫的图像。如果我们的模型只为一个类训练,那么这个输入特性是不需要的。

噪音。在用猫图像训练了一个生成模型之后,我们期望我们的模型能够生成各种各样的猫。因为我们不想每次都得到相同的猫图像,因此我们也输入一个噪声向量,它是一组随机值。这种随机噪声为模型提供了不同的输入特征。它可以帮助我们生成逼真多样的表象,比如白猫或橘猫,波斯或孟加拉,站着或躺着。

因此,噪声向量(有时带有类别y)作为输入馈入发生器神经网络;它将生成一个图像——类y的现实而多样的表示。

我们设计我们的生成器来输出形状为[channel, width, height]的张量,在生成图像的情况下,我们倾向于用三个通道来表示图像(对于三种颜色,红色绿色蓝色)。如果你是生成音乐,也许你只需要[channel, time]

此噪声向量也近似于类的样本分布,其中常见要素比罕见要素更有可能被生成。例如,对于“猫”类,如果数据集包含许多尖耳朵的猫,则更有可能生成尖耳朵的猫。而打呵欠的猫可能更难被摄像机捕捉到;因此,不太可能产生打哈欠的猫。

发电机是怎么学习的?

首先,我们将一个噪声向量和一个类别(y)输入生成器(G),神经网络计算并产生一组特征(G(z))——模型认为猫长什么样的图像。

生成器的目标是在给定类别标签“猫”的情况下,最大化生成猫图像的概率。[图片由作者

这是给定类别Y的特征X的条件概率。给定类别标签y,生成器模拟特征x的概率。因此,如果给定类别标签“猫”,该模型旨在最大化其生成猫图像的概率。

这个生成的图像被输入鉴别器(D),它执行分类(D(G(Z))并产生数据属于类别y的概率。换句话说,它决定了它认为基于输入的东西有多真实,有多假。

训练发电机的过程。[图片由作者 ]

利用鉴别器的预测,我们可以计算一个成本函数(g_loss),该函数查看由生成器生成的样本在多大程度上被鉴别器认为是真实的。生成器将改进和调整其权重,以提高这一指标-鉴别器认为图像是真实的概率(p(x))。

实际类别和输出之间的差异用于更新权重和改进模型,以生成可以欺骗鉴别器的更真实的图像。

当我们训练出了一个可以骗过鉴别器,骗过人类以为是真的生成器,我们就可以拯救生成器神经网络了。我们可以将噪声输入向量提供给这个生成器,它将生成真实的样本。使用不同的噪声向量,它可以生成各种各样的样本。因此,我们可以生成这些不存在的猫

PyTorch 代码

发生器网络接收噪声矢量,通过 4 个linear+batchnorm+relu模块应用非线性变换。然后输出大小为784的张量,以匹配展平的 MNIST 图像的输出大小28x28

笔记本:训练甘生成手写数字

概括起来

生成模型的目标是学习产生真实的样本来欺骗鉴别器,因此生成神经网络被训练为最大化最终分类误差。

就像一个艺术家可以画出看起来像真实的绘画或风景的图片,或者生成具有不同变化的猫的图片,而鉴别器无法从生成的数据中分辨出真实的。

GitHub repo :包含本教程系列

下一步是什么?

让我们将生成器和鉴别器结合起来,开始训练模型。

生成性对抗网络背后的直觉

原文:https://towardsdatascience.com/intuition-behind-generative-adversarial-networks-52628d3119f5?source=collection_archive---------45-----------------------

打造您的 GAN 系列——第 1 部分,共 4 部分

图片由来自 Pixabay斯蒂芬·凯勒拍摄

生成敌对网络(GANs)是强大的模型,它学习产生难以与现有真实对象区分的现实对象,如图像和音频(语音/音乐)。

在本教程中,我们将看看 GANs 的基本结构,以获得一些关于 GANs 模型如何工作的直觉。我们将看看伊恩·古德菲勒等人介绍甘斯的原始论文

有用的链接

这是构建你的生成性敌对网络的第一部分:

第一部分:生成对抗网络背后的直觉 (this)
第二部分:甘鉴别器背后的直觉
第三部分:甘生成器背后的直觉
第四部分:训练生成对抗网络

笔记本:训练甘生成手写数字
GitHub repo :包含本教程系列

GAN 模型有两个主要部分,一个发生器和一个鉴别器;这是两个独立的神经网络。

生成器学习生成看起来像真的假货来欺骗鉴别器。鉴别者学会区分什么是真的什么是假的。

所以你可以把生成器想象成伪造者,把鉴别器想象成警察。生成器伪造假钞,试图看起来尽可能真实,它这样做是希望愚弄鉴别器。而鉴别器学习并更好地识别真钞和伪钞。

鉴别者——警察

鉴别者就像一名正在接受识别伪钞训练的警察。它的工作是看一张照片,并告诉我们照片中是否包含真钱。由于我们在看图片,这个神经网络接收一个图像,然后输出单个值——在这种情况下,图像是否包含真钱的图片(或者没有)。

如你所见,这里的判别模型是一个用于分类的卷积神经网络。他们取一组特征(X),一批图像,并学习区分类别(Y),在这种情况下,

鉴别器预测图像为“假”的概率。【图片由 作者

换句话说,在给定一组特征X的情况下,他们试图对类别Y的概率进行建模。它开始时很难区分真钱和假钱,但在训练过程中,它学会了更好地区分真钱和假钱。

生产者——造假者

另一方面,生产者是正在学习如何制造假币的伪造者。与接收图像并输出值的鉴别器不同,生成器接收输入要素并输出图像。我们将两个输入特征输入到生成器中,1)一个类(Y),以及 2)一个噪声向量。

生成器使用噪声矢量并生成图像。【图片由* 作者*

****类。我们可能希望我们的模型学会生成几个不同的对象。有时,我们不希望只是生成一个随机的账单,我们希望这个模型根据我们的选择生成 1 美元、5 美元或 20 美元。但是如果我们只生成一个类,那么我们不需要这个类Y输入。

****噪音。我们需要模型来生成一个类的不同表示。例如,我们旨在创造各种各样的逼真的狗;噪声确保了生成的总是不同的东西,因为持续生成同一只狗是没有意思的。这种随机噪声也作为一种输入,可以帮助我们创建具有各种特征的图像。有时狗站着或躺着。有时它有尖尖的耳朵,有时它的舌头伸出来。通过添加噪声,这些模型将生成真实且多样的表示。

在开始的时候,生成器不会生成一些现实的东西;它一边学习,一边设法欺骗鉴别器,直到我们得到一个好的生成器,可以生成我们想要的逼真图像。此外,生成器没有输入用于训练的真实图像,所以这对于生成器来说很难学习,尤其是在开始的时候。

一起工作(或竞争)

这两个网络在开始时都不擅长它们的任务,但是在训练过程中,它们相互竞争,相互学习,直到它们达到我们不再需要鉴别器的程度。然后我们可以使用发电机;给定任何类(Y)和任何随机噪声,都可以产生逼真的图像。

现在我们有一个警察,就是寻找假币的鉴别者(D)。和一个伪造者,发电机(G),谁是印刷假币。让我们让他们互相学习。

在第一轮中,生成器获取一个随机数向量(z)并生成一个图像。因为制造者对货币应该是什么样子一无所知,它会制造出可怜的伪造品,几乎不像真的货币(G(z))。

Noobie 发电机产生一张可怜的假钞。【图片由 作者

与生成的货币一起,它被馈送到鉴别器。鉴别器将一组真实(x)或生成(G(z))的图像作为输入,并产生该数据是真实的概率(P(x))。但是鉴别器在识别钱的工作上同样糟糕,所以它不会知道区别。事实上,鉴别者可能会认为美元是真的!

Noobie 鉴别器认为假钞是真的!【图片由 作者

此时,我们会介入,告诉鉴别者这张美钞其实是假的。然后我们给它看一张真的美钞,问它和假的有什么不同(loss_d)。鉴别者将努力学习如何不被愚弄来抓住发生器,即使是最接近的复制品,以便鉴别者可以寻找新的细节来区分真假。

通过这种方式,鉴别器可以将像这样画得不好的图像与稍微好一点的和真实的图像区分开来。例如,鉴别者可能会注意到真钱上有一个人的照片,而假钱上没有。利用这些知识,鉴别器在区分真假方面变得稍微好一点。

现在鉴别者意识到真的钞票上有一张脸,而这张没有,所以它是假的。【图片由 作者**

随着鉴别器变得更好,并分类出钞票是假的,我们将结果反馈给生成器,生成的货币被检测为假的,因此它需要加强其游戏。生成器将通过查看由鉴别器产生的真实数据的概率(P(x))来知道如何改进(loss_g)。为了欺骗鉴别者,生成器会试图伪造看起来更像真样本的新样本。

生成器生成了一张更好的假钞,现在包括了一张脸。【图片由 作者**

这个看起来更真实一点,因为它现在包含了一张脸;假钞又被认为是有效的了!同样,鉴别器必须查看真实样品并提取特征来检测假冒样品。

这在训练过程中在生成器和鉴别器之间来回进行,直到两个网络都是专家。最终,生产者可以制造出近乎完美的赝品,鉴别者的眼睛变得更加敏锐,能够察觉最细微的错误。

因此,在训练过程的每次迭代中,生成网络的权重被更新以增加分类误差。相反,鉴别网络的权重被更新,以便减小这个误差。

这些相反的目标和两个网络的对抗性训练的隐含概念,这就是为什么它们被称为“对抗性网络”,名称为“生成性对抗性网络”。随着时间的推移,生成器和鉴别器相互竞争,都变得越来越好。他们之间的竞争使得这两个网络朝着各自的目标前进。

概括起来

生成模型的目标是学习产生逼真的样本来糊弄鉴别器,所以生成神经网络被训练成最大化最终的分类误差。就像一个艺术家可以画出看起来像真实的绘画或风景的图片,或者生成具有不同变化的狗的图片,而鉴别器无法从生成的数据中分辨出真实的。

鉴别模型的目标是检测虚假生成的数据,因此训练鉴别神经网络以最小化最终分类误差。它通过查看生成器创建的真实样本和假样本来学习区分不同的类别,并尝试辨别哪些是真实的,哪些是假的。

编码

想看看整个训练过程在行动中,这个笔记本包含代码,用于训练一个生成性的对抗性网络,学习生成手写数字。

笔记本:训练甘生成手写数字
GitHub repo :包含本教程系列

下一步是什么?

让我们看看鉴别器是如何工作的。

*** ***

独立同分布的直觉

原文:https://towardsdatascience.com/intuition-for-independent-and-identically-distributed-dc59e1528162?source=collection_archive---------48-----------------------

数据科学

理解统计学中的一个关键假设及其含义

一般来说,数据科学的主要目的,特别是机器学习的主要目的,是利用过去来预测未来。在各种统计模型的具体假设之外,不可避免的假设是,未来可以从过去的事件中预测。

图片提供Unsplash

我们假设有一些我们可以描述的函数,它接收我们观察到的数据,并输出某个未来事件的概率— P(Y | X) ,给定 X 输入,输出 Y 的概率。我们必须仔细构建我们的模型,以确保 X 提供的信息对预测 Y 有用且可靠。除了“虚假关联,我们选择直接或间接告知 Y 的特征。

同分布

假设我们想预测第一次从一副牌中抽出黑桃皇后的几率——通过建模以非常迂回的方式……从数学上来说,这只是 1/52 的几率,但请继续玩下去。

每一次观察,或者每一行,都是我们从一副牌中随机抽取一张牌的一次尝试。我们将这样做 10,000 或 100,000 或 100 万次。当 N → ∞时,我们第一次抽到黑桃皇后的概率应该接近 1/52!

但这是假设所有的套牌都是一样的!这是我们的同分布假设。我们必须假设每副牌都有从 a 到 k 的所有 13 张花色牌。如果每三副牌只有 50 张牌呢?或者一副牌缺少所有的黑桃?我们的概率会发生不可预测的变化。如果在我们汇编了所有这些训练数据之后,我们发现我们实际上是在预测从一副 euchre 牌中抽出黑桃皇后的概率,那该怎么办呢!总共 25 张牌只有 9 到 a(高)!我们希望我们的训练和测试数据来自同一个分布。

自主的

我们还假设每个甲板和拉力都是独立的。例如,如果我们在没有替换的情况下对牌组进行抽样,这意味着在我们抽了一张不是黑桃皇后的牌之后,我们不把它放回牌组,最终我们将不得不抽黑桃皇后!我们的概率会在每次抽牌后更新,从 1/52 … 1/51 … 1/50 直到它的 1/1(如果黑桃皇后是这副牌中的最后一张)。

当一件事的结果不受另一件事的影响时,独立性就得到满足。在这个例子中,第二次抽牌的结果受到第一次抽牌的影响,因为我们的牌组中少了一张牌!这就是为什么我们假设独立性,并且通常用替换抽样。

有一个度量标准可以量化有替代和无替代抽样之间的差异,协方差:两个随机变量的联合变异性。在机器学习项目中,协方差绝对是您应该知道并在您的数据中调查的东西。[ 1

图片CMG LeeWikimedia 上以 CC BY-SA 4.0 许可证提供。

如果协方差为零,那么这两个变量是独立的,互不影响。如果变量倾向于表现出相似的行为,比如一个变量的增加对应于另一个变量的增加,那么它们具有正的协方差。归一化协方差给出了相关系数,其定义了这种关系的大小。

含义

假设独立同分布对于使用我们的模型进行预测非常重要,因为我们假设过去——我们现有的数据 X —将代表问题空间,并准确预测未来 Y

还有一些假设独立同分布的特定技术,如自举聚合(bagging)模型或交叉验证。特别是 Bagging,像随机森林一样,使用数据的随机子样本来生成许多不同的模型,然后将这些模型组合或平均在一起,以减少方差和过度拟合。如果数据不是独立同分布的,那么每个子样本会有很大的不同,并且不会描述数据集的基本分布。

bagging 算法专门使用替换进行采样,以确保新训练集的独立性。对于容易过度拟合的模型,如神经网络和决策树,bagging 是减少方差/增加稳定性的一个很好的工具。

正如 Nate Silver 所说,“很容易过度拟合一个模型,当你只是在描述噪音时,认为你已经捕捉到了信号”。[2]

你可以在这里阅读中心极限定理,在这里阅读 Bagging

连接

我一直在寻找连接和探索其他项目!你可以在 GitHub 或者 LinkedIn 上关注我,在 Medium 上查看我的其他故事。我也有一个推特

来源

斯蒂芬妮·格伦StatisticsHowTo.com的《有置换的抽样/无置换的抽样》:我们这些人的基本统计!https://www . statistics show to . com/sampling-with-replacement-without/

[2] N. Silver,《信号与噪音:为什么如此多的预测失败——但有些没有(2012 年)。

直觉对学习数据科学非常有帮助

原文:https://towardsdatascience.com/intuitions-are-extremely-helpful-in-learning-data-science-c17c6b7bc3dc?source=collection_archive---------26-----------------------

意见

我非常喜欢 Francois Chollet 的 Python 深度学习

介绍

根据我的经验,在数学方面有两种人。例如,考虑针对这两类受众的主成分分析的两种解释:

  • 喜欢故事的人:在 PCA 中,你可以旋转数据集的轴,以便更有效地描述你的数据

使用 PCA 旋转轴。图片作者。

  • 喜欢数学的人 : PCA 被定义为一种正交线性变换,它将数据转换到一个新的坐标系,这样数据的一些标量投影的最大方差就位于第一个坐标上(维基百科)

后者更符合传统的大学数学教育。你花了很多时间学习基本的数学技能,这些技能最终会叠加成更复杂、更有用的数学概念,比如深度神经网络。这种方法的优点是,它允许你真正深入地理解神经网络内部发生了什么。如果你的目标是研究新类型的架构,这种深刻的知识肯定是需要的。然而,这种学习数据科学的方法非常耗时,并且不适合每个学生。

和我一起工作的学生往往不太倾向于数学。他们的目标不是真正深入深度学习的本质,而是学会应用它来解决实际问题。根据我的经验,他们从基于故事和直觉的数学演示中受益匪浅。这些直觉更加模糊,但是为学生提供了很好的定位点来吸收新知识。此外,他们往往足以能够实际应用深度学习。

我为什么喜欢巧克力

一本提供一些极好的直觉的书是 Francois Chollet写的用 Python 进行深度学习。我很喜欢他对深度学习的实用和平易近人的解释。您可能无法根据这本书从头开始编写 tensorflow,但它为您提供了使用 Keras 构建实用深度学习模型的知识。

让这本书与众不同的两点是经验法则和直觉。经验法则的例子是哪种损失函数用于哪种类型的数据,或者在隐藏层中使用多少个神经元。关于直觉,考虑一下书中的以下引文和我写的一个更数学化的句子:

(Chollet)深度学习是一个从数据中学习表示的数学框架

通过计算损失向量函数相对于网络权重的偏导数,并选择使损失函数最小化的权重变化,来训练神经网络的连续层

后一句要精确很多,但也需要你有很多先验知识(偏导数,损失函数)。Chollet 的前一段引用提供了神经网络如何试图解决问题的更多直觉。Chollet 将这些令人敬畏的直觉塑造成连贯的叙述的方式使得这本书读起来很有乐趣。

这对学习意味着什么?

对于初学深度学习的爱好者来说,直觉是建立知识库的好方法。直觉为你的学习过程提供了基础,更详细的知识有了嵌入的空间。特别是对于一个更注重实践的学生来说,这种更自上而下的学习方式被证明是非常有效的。

但我相信,这些直觉也可以被证明对那些采用更多数学方法进行深度学习的学生有益。与更注重实践的学生一样,直觉让你将数学概念嵌入到更广阔的背景中。这让你看到深度学习少了一系列的数学运算,更多的是作为一个整体的问题解决机器。

我是谁?

我叫 Paul Hiemstra,是荷兰的一名教师和数据科学家。我是科学家和软件工程师的混合体,对与数据科学相关的一切都有广泛的兴趣。你可以在 medium 上关注我,或者在 LinkedIn 上关注我。

如果你喜欢这篇文章,你可能也会喜欢我的其他一些文章:

深度学习中不同激活函数背后的直觉

原文:https://towardsdatascience.com/intuitions-behind-different-activation-functions-in-deep-learning-a2b1c8d044a?source=collection_archive---------24-----------------------

衍生产品、优点、缺点、Python 实现和用例

来源:乔希·里默尔在 Unsplash 上的照片

正如我们所知,在神经网络中,神经元以相应的权重、偏置和各自的激活函数工作。权重与输入相乘,然后在进入下一层之前对元素应用激活函数。

作者图片

为什么需要激活功能?

激活函数有助于将非线性引入神经元的输出,这有助于准确性、计算效率和收敛速度。为了优化的目的,激活函数相对于权重应该是单调的、可微分的和快速收敛的。

在本文中,我们将讨论以下重要的激活功能:

1)乙状结肠

2)双曲正切值

3)整流线性单元(ReLU)

4)泄漏的 ReLU

5)指数线性单位(ELU)

6)参数重新逻辑(预逻辑)

  1. Softmax

1) 乙状结肠

这是最常见的激活功能之一,也称为逻辑功能。该函数定义为:

作者图片

该函数及其导数如下所示:

作者图片

从上图中,我们观察到:

a)函数看起来像 S 形曲线

b)该函数在 0 和 1 之间转换输入值,并以 0.5 ie 为中心。不以零为中心。

c)函数是单调且可微的。注意,sigmoid 函数的导数范围在 0 到 0.25 之间。

乙状结肠的缺点

a) 消失梯度:在神经网络中,在反向传播阶段,权重(w)更新如下:

作者图片

从图中,我们可以理解导数的范围是 0 到 0.25。由于微分的链式法则,导数可能很低,以至于权重可能不会显著改变或更新。这导致在反向传播阶段更新权重的问题,并且没有值得注意的信息被传递到随后的层。这个问题叫做消失梯度。

b) 由于其指数性质,计算开销很大

c) 输出不是以零为中心,这降低了更新权重的效率。

2) 双曲正切(Tanh)

另一个非常常用的激活函数是 Tanh,其定义为:

图片来自作者

该函数及其导数如下所示:

图片来自作者

从上图可以清楚地看出:

a)函数看起来像 S 形曲线

b)该函数转换-1 和 1 之间的值,并以 0 为中心。

c)函数是单调且可微的。注意,双曲正切函数的导数范围在 0 到 1 之间。

Tanh 和 sigmoid 都是单调递增函数,当它接近+inf 和-inf 时,渐近于某个有限值。

Tanh 的缺点:与 Sigmoid 类似,Tanh 也有消失梯度的问题,并且由于其指数运算而计算量大。

双曲正切函数优于 Sigmoid 函数的优势:正如我们注意到的,双曲正切函数以零为中心,这意味着双曲正切函数关于原点对称。因此,如果训练集上每个输入变量的平均值接近于零,收敛通常会更快。

3) 整流线性单元(ReLU)

ReLU 是更新隐藏层时最常用的激活函数。当传递负输入时,ReLU 返回 0,对于任何正输入,它返回值本身。该功能定义为:

图片来自作者

该函数及其导数如下所示:

图片来自作者

从上图中,我们观察到:

a)对于任何小于零的值,该函数输出 0,对于正值,该函数是单调和连续的。

b)对于 z <0 and 1 for z> 0,函数的导数为 0,但是函数在点 0 处不可微。

c)它是不可微的,对于负输入,导数是 0。

ReLU 的优点

a) ReLU 克服了消失梯度的问题,因为对于 z>0,导数为 1。

b)由于其简单的方程,与 Sigmoid 和 Tanh 激活函数相比,其计算速度更快。

缺点(Dying ReLU): 如上所述,对于负输入,导数为 0,因此等式(1)导致 w(new) = w(old)。这意味着,进入这种状态的神经元将停止对错误/输入的变化做出响应(因为梯度为 0,所以没有变化)。这就是所谓的垂死的 ReLu 问题。这导致死神经元不能在反向传播中更新权重。为了克服这个问题,漏 ReLU 出现了。

4)漏液 ReLU

这是对 ReLU 的改进,通过调整负输入的函数,如下所示:

作者图片

该函数及其导数如下所示:

作者图片

基本上,泄漏 ReLU 允许一个小的非零恒定梯度。这确保了神经元不会因为引入非零斜率而死亡。

Leaky ReLU 的缺点:如果大部分权重是负数,那么根据导数的链式法则,它会乘以 0.01 的倍数。这将最终导致渐变消失,我们试图克服这一点。

5) 指数线性单位(ELU)

为了解决这个问题并保持 leaky relu 的其他特性,elu 出现了。这被定义为:

作者图片

该函数及其导数如下所示:

作者图片

优点:

a)濒死再禄问题得到解决

b)输出 id 以零为中心

c)不需要在 0 找到导数

缺点:由于其指数性质,计算量很大。

6) 参数 ReLU (PReLU)

这是所有不同 ReLU 变体的最一般化形式。该函数定义为:

作者图片

其中,β被授权在反向传播期间学习,并且可以被视为学习参数。

注意,如果β = 0,类似于 ReLU

如果β = 0.01,类似于泄漏 ReLU

7)soft max

Softmax 计算 n 个不同事件的概率分布。它计算每个目标类相对于所有可能的目标类的概率。之后,计算出的概率有助于确定给定输入的目标类别。该函数定义如下:

作者图片

该函数如下所示:

作者图片

Softmax 通常用于多类问题。如果层数超过 2 层,则在最后一层使用该激活功能。“最大”部分返回最大值,“软”部分确保较小的值具有较低的概率,但不会被丢弃。还要注意,所有类别的概率之和将是 1。

Python 代码片段

下面的 python 代码用于为每个函数及其相应的导数创建上面的图形。

图片来自作者

不同激活功能的快速汇总

作者图片

更多激活功能

这些是深度学习中经常使用的激活功能,但列表并没有到此为止:

何时使用哪些激活功能

通常,如果输出范围在(0,1)或(-1,1)之间,则可以使用 sigmoid 或 tanh。另一方面,要预测大于 1 的输出值,通常使用 ReLU,因为根据定义,tanh 或 sigmoid 不合适。

在二元分类器的情况下,应该使用 Sigmoid 激活函数。预测多类问题的概率时,应在最后一层使用 softmax 激活函数。同样,tanh 或 sigmoid 通常在隐藏层中效果不佳。应该在隐藏层中使用 ReLU 或 Leaky ReLU。当隐藏层数很高(接近 30)时,使用 Swish 激活功能。

然而,激活函数的使用主要取决于数据、手头的问题和预期输出的范围。

希望你喜欢这篇文章!!

免责声明:本文所表达的观点是作者以个人身份发表的意见,而非其雇主

参考文献:

https://arxiv.org/pdf/1811.03378.pdf

https://machine learning mastery . com/choose-an-activation-function-for-deep-learning/

相关主题模型的直观指南

原文:https://towardsdatascience.com/intuitive-guide-to-correlated-topic-models-76d5baef03d3?source=collection_archive---------15-----------------------

LDA 的一个简洁的扩展,它可以成为更高级主题模型的主干

吴怡Unsplash 上拍照

自从大卫·布莱、吴恩达和迈克尔·乔丹(不,不是篮球运动员;不,不是演员)在 2003 提出了潜在的狄利克雷分配(LDA),主题建模已经成为所有数据科学中最受欢迎的模型之一。有趣的事实:最初的 LDA 论文是被机器学习研究杂志引用最多的论文。

简单地说,主题建模就是找出文档是关于什么的。与有监督的文档分类不同,我们不可能事先知道主题。相反,我们采取一种无人监督的方法,发现文档中的潜在主题。LDA 对于文档建模、分类甚至协同过滤特别有用。

在这篇文章中,我将介绍一个重要的,但有些被忽视的 LDA 扩展:相关主题模型(CTM)。

激励 CTM:LDA 的局限性

我们将从头开始,首先回顾 LDA,然后展示 CTM 如何试图超越 LDA。medium 上已经有几个很棒的 LDA 指南,我强烈推荐它们来补充这个简要概述。

LDA 将文档建模为主题的分布,将主题建模为单词的分布。我们的单词生成过程包括从文档的主题分布中选择一个主题(一个我们称之为θᵢ的多项式分布,其中 i 仅仅意味着这个θ特定于文档 i )并从该主题的单词分布中选择一个单词(另一个多项式通常称为β)。这些分布是由狄利克雷分布生成的。现在,我们只关注产生θᵢ的第一个狄利克雷,文档的主题分布。

LDA 的位置图。方框右下角的意思是重复操作那么多次。 M 是语料库中文档的数量;n 是文档中的字数;k 是主题的数量。z 是θ抛出的特定主题,它决定了我们使用哪个β概率向量来选择我们的最终单词 w。a 和 b 是各自狄利克雷分布的超参数。

对于那些不太熟悉狄利克雷的人来说,可以把它看作贝塔的多元推广。它不仅为单个伯努利试验产生概率,而且为多个类别的概率向量产生概率,在我们的例子中,为我们模型中的 k 主题产生概率。换句话说,狄利克雷是多项式的共轭先验。

我知道这有点晦涩难懂,但即使您不完全理解,也有两点需要注意:

  1. 事实上,狄利克雷是多项式的共轭先验,当我们开始实际处理数据时,数学会很好地出来。我们仍然需要做一些近似来得到我们的最终主题和它们的分布,这可以通过变分推理或者其他技术如折叠吉布斯采样来完成。
  2. 狄利克雷产生独立的主题概率(用数学术语来说:它产生一个中性向量)。回想一下多项式,如果您删除其中一个类别,其余的概率只是围绕剩余的概率进行重新归一化。其余类别不会改变相对大小。狄利克雷模型被设计用来生成概率,这意味着我们不能对相关的主题建模。

如果我们认为话题高度相关呢?这并不太牵强:一个潜在的主题可能包含一串关于食物的单词,而另一个主题可能包含关于健康和健身的单词。这两个话题大概至少有些依赖。与随机选择的文档相比,关于健康和健身的文档更有可能也是关于食物的。

CTM 解决方案

我们将忽略生成模型的其余部分,只关注如何生成θs。为了引入相关性,我们将从多元正态分布而非狄利克雷分布开始。如果狄利克雷是贝塔的多元推广,那么多元正态就是正态的多元推广。和以前一样,我们的目标是为我们的概率向量生成 k 个值(每个主题一个)。

对于单变量正态分布,我们需要一个均值和标准差。对于多元正态分布,我们需要 k 均值和 k 标准差。我们还会考虑不同主题之间的协方差。总之,我们为多元正态分布提供两个参数:平均值的长度向量(μ)和协方差矩阵(σ)。

在这一点上,我们的模型将会产生一个任意大小的向量 k,我们称之为η。这些数字可能是负的,也可能是巨大的。最终,我们的目标是得到一个非负数的概率向量,其和为 1(称为单纯形)。

为了将多元正态分布的结果映射到概率中,我们将通过逻辑函数的一个变量来传递所有的值。具体来说,对于每个输出多元正态ηⱼ(其中 j 对应于一个主题),我们应用变换:

将多元正态通过逻辑转换的最终结果称为 logit 正态分布。总之,我们所做的只是将狄利克雷分布—θ*Dir(*α*)*—与对数正态分布—θf(N(μ,σ)交换,其中 f(x)是逻辑变换,N 是多元正态分布。

CTM 板块图。“Log”表示上面列出的逻辑转换。

这个小开关有几个重要的含义。不幸的是,多元常态,加上最后的逻辑转换,并不像狄利克雷那样有整齐的性质。

因此,我们不能再使用 LDA 使用的标准变分推理技术。相反,CTM 使用了一种叫做平均场变分推论的方法。平均场变分推论的力学是…涉及的。让我们把它留下,我们现在有额外的变分参数,需要迭代方法来优化。就我们的目的而言,主要的要点是 CTM 的培训时间可能会稍长一些。

这种更长时间的培训的回报是,我们不仅得到了更好的主题,我们还得到了看到主题之间关系的额外好处。在 LDA 中,研究人员将不得不在训练后尝试手动整理相关性。有了 CTM,我们只需看看模型本身就能观察到相关性。也许关于领导力的书籍也使用了大量的宗教语言,反之亦然,这可能在相关性中表现出来。也许我们通过相关性找到超集-子集关系(例如,具有一般体育词汇的主题可能与具有篮球词汇的主题相关)。

在以下情况下,CTM 特别有用:

  • 我们事先就有预感,话题很可能是相关的。
  • 我们正在对许多主题进行建模,在这种情况下,至少有几个主题是相关的。

然而,我应该限定相关性不是主题之间某种形式的语义距离。我们只是观察到某些主题可能一起出现,也可能不一起出现。因为 CTM 依赖于参数推断/估计,而不是一些封闭形式的解决方案,所以最好不要太深入地解读主题之间的精确相关性。然而,当涉及到在 EDA 过程中提供广泛的笔触或激发进一步的探究时,这些种类的见解会非常有趣。

结论

概括一下:

  • 主题建模是一种发现文档潜在主题的无监督方法。
  • 最常见、最著名的主题建模方法是潜在的狄利克雷分配。在 LDA 中,我们将文档建模为(独立的)主题的分布,这些主题本身就是单词的分布。
  • 如果我们允许主题之间的相关性,我们可以改进这个基线。
  • 这是以更长的训练时间为代价的。
  • 然而,它使研究者能够检查主题之间的关系。

老实说,CTM 并不完全是 ML 社区的开箱即用的宠儿。然而,CTM 绝对有它的用处(见 CTM 过去三年的论文关于新冠肺炎研究高等教育研究气候变化新闻),CTM 背后的直觉是一些非常酷的模型的有益起点。

想到了两个非常酷的 CTM 扩展:

现在,我链接到原始的论文,但我希望在未来能发布更直观的嵌入式和结构化主题模型的指南。敬请期待!

[1] D .布莱,A. Ng .,和 m .乔丹,潜在的狄利克雷分配 (2003),《机器学习研究杂志》。

[2] D. Blei 和 J. Lafferty,(2005),NIPS’05:第 18 届神经信息处理系统国际会议论文集。

直观的 Kaggle 任务探索和模型基线

原文:https://towardsdatascience.com/intuitive-kaggle-task-exploration-and-model-baselining-e5f641943d08?source=collection_archive---------36-----------------------

插图照片由来自 Pexels马里乌斯·文特尔拍摄。

这篇文章展示了如何利用 PyTorch Lightning 和 TorchVision 模型探索数据集和准备基线方法。

在前一篇文章中,我们描述了配置 Kaggle 开发环境和获取数据集的最佳实践。

现在我们已经配置了一个环境,让我们遍历我们的 Kaggle 内核并一步一步解释每个单元。主要阶段将是:(1)加载数据,(2)检查标签分布,以及(3)观看每个类的一些样本图像。稍后,我们开始将数据包装到 PyTorch 类,也就是 Dataset 和 Dataloader。最后,我们把它们放在一起,并且(5)训练一个简单的基线 CNN 模型。

我选择了 PyTorch Lightning 来完成这项任务,因为它有助于将我的数据科学代码从深度学习工程中分离出来,使我们能够专注于:
a)使用[LightningDataModules](https://pytorch-lightning.readthedocs.io/en/stable/extensions/datamodules.html)加载和处理数据。
b)选择在我们的[LightningModules](https://pytorch-lightning.readthedocs.io/en/stable/common/lightning_module.html)中使用的模型/架构。
c)用[TorchMetrics](https://torchmetrics.readthedocs.io/en/stable/)评估绩效。

https://github.com/Borda/kaggle_plant-pathology

数据探索

虽然植物病理学 2021-fgvc 8挑战赛组织者提供了任务描述,但我始终建议自己做一些数据探索,以验证你知道如何处理给定的数据。

首先,我们检查图像文件夹和标签,加载它们并观察使用了什么注释格式。在这种情况下,它是一个两列的表格,第一列是图像名称,第二列是多个字符串标签。

使用 pandas 数据帧从注释 CSV 表中获取快照。

对于分类任务,检查标签分布有助于了解预期情况。理想情况下,每个类中的样本数量应该几乎相等;如果不是,你应该部署一些技术来平衡你的数据集,如果它是严重不平衡的(平衡技术超出了本文的范围)

植物病理学数据集的标签分布。

将数据包装到 PyTorch 类

Pytorch Lightning 只是组织了 Pytorch 在引擎盖下使用标准 Pytorch 对象和方法进行数据处理,如Dataset Dataloader对象。Datasets定义了如何从存储器(如硬盘)加载数据,并将输入数据(图像)与注释(标签)结合起来。需要实现的主要方法是__getitem__,简单来说可能如下所示:

来自共享的代码片段

与几乎所有的分类机器学习任务一样,该模型不直接与文本标签一起工作,我们需要将我们的文本转换为我们可以建模的表示。

我们使用二进制编码来表示标签,对于图像中出现的特定标签使用1,否则使用0。所得到的二进制向量位置对应于所有可能标签的固定集合中的标签索引,所有可能的标签都是子数据集划分——训练/验证/测试。

例如,健康样本的图像由[0,0,1,0,0,0]表示,标有“锈痂”的图像为[0,0,0,0,1,1]。下面,我们展示了一些来自我们实现的Dataset的图像编码对的例子:

来自编码数据集的样本配对图像和标签。图片来源:植物病理学 2021 — FGVC8

将数据包装到 Lightning 类

最后一个数据相关的步骤是定义一个LightningDataModule。这个 PyTorch Lightning 组件封装了所有的数据处理步骤,包括:
1。创造一个Dataset2
。将Dataset分割成训练/验证(/测试)子数据集
3。将子数据集包装到特定的 PyTorch 本机中DataLoader

这些DataLoaders然后在模型训练期间直接访问LightningDataModule。下面是一个示例,让您对LightningDataModule 结构有一个简单的了解:

来自共享的代码片段

基础数据扩充

数据扩充是一种基本的机器学习技术,旨在通过训练数据集的合成扩展来扩展可变性,并有望防止人工过度拟合。增强的思想是在最终的外观方向上生成新的样本,这些样本可能在训练数据集中丢失。但是,它仍然有可能在验证或生产的后期出现。在图像领域,典型的增强是几何变换和颜色/强度变化。

我们使用垂直/水平翻转、旋转、小裁剪和小透视变换的随机组合来模拟不同的观察位置(参见下面带有一系列torchvision变换的代码快照)。

来自共享的代码片段。

基线模型拟合

在训练一个复杂的模型之前,我们应该用一个基线模型来检查我们的数据集,以验证我们的训练管道没有泄漏。这种最佳实践消除了下游的混乱,因为如果我们从一个不收敛的非常复杂的模型开始,我们就不知道问题出在数据处理、训练过程还是我们的模型本身。

调整火炬视觉模型

我们从 TorchVision 软件包中推荐一个简单的 ResNet50 (通常被认为是模型复杂性和学习能力之间的一个很好的权衡),它具有预先训练的权重,可以加速任何收敛并将其打包成一个模块。

需要包装预训练模型,因为基本 ResNet50 有 1000 个输出(因为它是在 ImageNet 数据集上训练的),而我们的分类只需要六个输出/类——我们用新的线性层替换最后一个线性层。

来自共享的代码片段

准备闪电模型

LightningModule是 PyTorch Lightning 的一个核心对象,它聚集了所有与模型相关的过程——模型(架构&权重)、如何执行训练/验证步骤、记录指标等。

第一步是定义一个新的LightningModule——包装我们的模型、度量、损失函数和训练所需的其他参数。对于图像分类指标,我们使用传统的准确度、精确度F1 得分指标。作为损失函数,由于数据是多标签数据,我们使用具有 Logits 的二元交叉熵。

来自共享的代码片段

编写LightningModule的下一步是定义训练和验证步骤,在该步骤中,我们指定如何将数据输入模型以获得预测并计算损失。该损失被传递给优化,用于自动权重更新。您可以看到它们非常相似,因为我们想要跟踪相似的度量标准来进行培训和验证;区别在于training_step需要回波损耗。

来自共享的代码片段

最后一步是定义我们想要使用的优化器和一个可选的调度器,该调度器根据训练进度(由训练步骤索引驱动)管理训练期间的学习率变化。我们使用带有默认参数的加权 Adam 优化器。

来自共享的代码片段

用闪电训练模型

PyTorch Lightning 拥有丰富的回调生态系统。它们为最佳实践提供开箱即用的支持,从检查点(在训练期间保存模型权重)和提前停止(如果模型不再改进,则停止训练)到高级技术,如修剪随机权重平均

我们在训练期间配置检查点以保存具有最佳验证 F1 分数的模型:

ckpt = pl.callbacks.ModelCheckpoint(
    monitor='valid_f1',
    filename='checkpoint/{epoch:02d}-{valid_f1:.4f}',
    mode='max',
)

现在我们有了开始训练所需的所有代码。

在 PyTorch 闪电中,训练被抽象为闪电Trainer。我们设置训练参数,如学习率、历元数、我们想要使用的 GPU 数量(对于 Kaggle,使用所有 GPU)、训练精度(我们将浮点精度从 32 位降低到 16 位,这不会损害训练性能,但允许我们将每批中的数据量增加一倍)等等。

trainer = pl.Trainer(
    gpus=1,
    callbacks=[ckpt],
    max_epochs=35,
    precision=16,
    accumulate_grad_batches=24,
    val_check_interval=0.5,
)

训练呼叫trainer.fit(model=model, datamodule=dm)开始我们模型的训练…坐在你舒适的椅子上,观察你的模型如何学习…

几个时代的训练表演。

在这篇文章中,我们分享了如何筛选给定的数据集,以及你应该关注哪些有趣的方面。我们展示了如何将类似文件的数据集包装到 PyTorch 类数据集,这是数据处理的核心。此外,我们在 PyTorchLightning 中基于 TorchVision 模型编写了一个基本的图像多标签分类模型,并在 GPU 上以混合精度无缝训练,无需额外代码。

在未来,我将展示如何使用一些最简单的可持续性技巧将笔记本转换为可共享的 Python 包,以及如何使用公开的训练参数编写一个简单的 CLI,以便更容易地进行超参数搜索。

敬请关注,关注我了解更多!

https://devblog.pytorchlightning.ai/best-practices-to-rank-on-kaggle-competition-with-pytorch-lightning-and-grid-ai-spot-instances-54aa5248aa8e

关于作者

Jirka boro vec已经在几家不同的 IT 公司从事机器学习和数据科学工作好几年了。特别是,他喜欢探索有趣的世界问题,并用最先进的技术解决它们。此外,他开发了几个开源 python 包,并积极参与其他知名项目。在 Grid.ai 工作,担任研究工程师,是pytorchlightning . ai的主要撰稿人。

变压器自我关注机制背后的直观数学和代码

原文:https://towardsdatascience.com/intuitive-maths-and-code-behind-self-attention-mechanism-of-transformers-for-dummies-7dfc28a30aaa?source=collection_archive---------12-----------------------

这篇博文将深入关注机制的本质细节,并使用 python 从头开始创建一个关注机制

罗伯特·卡茨基在 Unsplash 上的照片

在开始这篇博文之前,我强烈推荐你访问我之前关于变形金刚概述的博文。为了充分利用这个博客,请按以下顺序查看我以前的博客。

  1. 变形金刚——你只需要关注。
  2. 变形金刚自我关注机制背后的直观数学和代码。
  3. 关于位置编码的概念你可能不知道。

这篇博文将深入关注机制的本质细节,并使用 python 从头开始创建一个关注机制。代码和直观的数学解释密不可分。

变压器编码器部分

我们要学什么?

  1. 注意机制概念
  2. 自我注意机制所涉及的步骤(直观的数学理论和代码)
  • 输入预处理
  • 查询、键和值矩阵的角色
  • 标度注意分数的概念

3.多头注意力机制

所以没有任何进一步的拖延,让我们开始吧。

注意机制概念

正如上一篇文章中所讨论的,当一个句子通过注意机制时会发生什么。例如,假设我们有一个句子“他拿起帽子并仔细检查了它”,注意机制通过记住每个单词如何与句子中的其他单词相关来创建每个单词的表示(嵌入)。在上面的句子中,注意机制对句子的理解达到了可以将单词“it”与“hat”联系起来,而不能与“He”联系起来。

A

自我注意机制涉及的步骤

1.以正确的格式获取输入:-

我们现在都知道文本输入不适合被转换器/计算机解释。因此,我们用数字向量来表示文本中的每个单词。让我们为句子创建嵌入,例如:- “这是本书”,并且让我们假设嵌入维度为 5。所以对于每个单词,我们有一个长度为 5 的向量,如下所示。

输入到变压器

print(f”Shape is :- {np.random.randn(3,5).shape}”)
X=np.random.randn(3,5)
X

输出:-

输出(作者图片)

从上面的输入矩阵,我们将创建一对新的矩阵,即关键,查询和值矩阵。矩阵在注意机制中起着至关重要的作用。让我们看看如何?

2.获取查询、键和值矩阵

首先,我们需要查询、键和值权重矩阵。目前,我们已经随机地初始化了它,但是实际上,像神经网络中的任何其他权重一样,这些是参数,并且是在训练过程中学习到的。最终使用最佳权重。假设这些权重是最佳权重,如代码所示。下图总结了我们在代码部分要做的事情

下面的代码片段 ( 图片由作者提供)将遵循此步骤中涉及的整体操作

查询矩阵的优化权重

weight_of_query=np.random.randn(5,3)
weight_of_query

输出:-

输出(作者图片)

关键矩阵的优化权重

weight_of_key=np.random.randn(5,3)
weight_of_key

输出:-

输出(图片由作者提供)

价值矩阵的优化权重

weight_of_values=np.random.randn(5,3)
weight_of_values

输出:-

输出(图片由作者提供)

然后,这些权重将乘以我们的输入矩阵(X ),这将给出我们最终的键、查询和值矩阵

关键矩阵的计算

Key=np.matmul(X,weight_of_key)
Key

输出(图片由作者提供)

查询矩阵的计算

Query=np.matmul(X,weight_of_query)
Query

输出(图片由作者提供)

价值矩阵的计算

Values=np.matmul(X,weight_of_values)
Values

输出(图片由作者提供)

查询、键和值矩阵中的第一行表示单词“ This ”的查询、键和值向量,其他单词依此类推。到目前为止,查询、键和值矩阵可能没有多大意义。让我们看看自我关注机制是如何通过使用查询、键和值向量来发现每个单词如何与句子中的其他单词相关,从而创建每个单词的表示(嵌入)的。

3.标度注意力分数

标度注意力分数的公式

标度注意力公式

dimension=5
Scores=np.matmul(Query,Key.T)/np.sqrt(dimension)
Scores

输出(图片由作者提供)

Q.K(转置)中发生的是查询和键矩阵之间的点积,点积定义了相似性,如下图所示。

注:——下图中的数字都是为了便于解释而编造的,不相加。

我们如何用数学方法计算注意力分数? ( 图片由作者提供)

所以在查询向量 q1(This) 和所有关键向量 k1(This),k2(is),k3(book) 之间有一个点积。这个计算告诉我们查询向量 q1(This) 如何关联/类似于密钥矩阵 k1(This)、k2(is)、k3(book)中的每个向量。同样,如果我们关注最终的输出矩阵,我们可以看到,如对角线矩阵所示,句子中的每个单词与其自身的关联度都高于其他任何单词。这是因为点积值更高。其次,单词“This”“book”更相关,如上图中用红色突出显示的。如代码的最后一部分所示,我们将 Q.K(转置)除以 sqrt(维度)。这是一种标准化步骤,目的是使梯度稳定。

下面代码中的 Softmax 有助于将它设置在 0 到 1 的范围内,并分配概率值。

from scipy.special import softmax
Softmax_attention_scores=np.array([softmax(x) for x in Scores])
Softmax_attention_scores

输出(图片由作者提供)

上面的矩阵是中间 softmax 标度的注意力得分矩阵,其中每行对应于序列中每个单词的中间注意力得分/概率得分。它显示了每个单词与其他单词在概率上的关系。为了得到最终的注意力向量,我们将把上面的分数乘以价值矩阵并求和。总结出“这个”这个词对应的三个注意力向量。

在下面的代码片段中,softmax_attention_scores[0][0]是该特定单词的权重,values[0]是对应于单词“ This ”的值向量,以此类推。

Softmax_attention_scores[0][0]*Values[0]+\
Softmax_attention_scores[0][1]*Values[1]+\
Softmax_attention_scores[0][2]*Values[2]

输出(图片由作者提供)

类似地,我们可以计算其他单词如 is 和 book 的关注度。这就是自我关注的机制。接下来,我们将研究多头注意机制,它的基本原理来自自我注意机制。

多头注意力机制:-

简而言之,多头注意力机制只不过是多个自我注意力机制串联在一起。如果我们将每个自我关注流/过程表示为一个,那么我们将通过将所有自我关注机制串联在一起而得到一个多头关注机制。

当我们在即将到来的博客文章中动手操作时,我们会看到每个编码器的输出都有一个 512 的维度。总共有 8 个头。因此,所发生的是,每个自我注意模块被制作成使得它向(句子中的单词数,64)维矩阵给出输出。当所有这些维度被连接时,我们将看到最终的矩阵将是(句子中的单词数,(64*8)=512)维。最后一步是将连接的头部与权重矩阵相乘(假设权重矩阵已经在该过程中被训练过),这将是我们的多头注意力的输出。

在我们的下一篇博文中,我们将讨论变形金刚的拥抱脸实现,再见。如果你觉得这很有帮助,请随意查看我关于变形金刚的其他博文

  1. 变形金刚——你只需要关注。
  2. 变形金刚自我关注机制背后的直观数学和代码。
  3. 关于位置编码你可能不知道的概念。

理解动态时间扭曲的直观方法

原文:https://towardsdatascience.com/intuitive-ways-of-understanding-dynamic-time-warping-5fb60fcbe037?source=collection_archive---------16-----------------------

通过编辑距离和等效性

Joshua Sukoff 在 Unsplash 上拍摄的照片

动态时间扭曲(DTW),尽管它的名字很科幻,但它只不过是一种(特别有用的)测量两个时间序列x=(x1,...,xn)y=(y1,...,ym)之间距离的技术。

  • “动态的”,因为算法涉及动态规划
  • 时间,因为它是时间序列
  • 因为它可以被解释为计算xy的扭曲版本之间的“通常”距离

如何计算它的机制和各种可视化已经存在(例如,罗曼·塔维纳德在他们的博客上,章晓虎在 Medium 上,泰雷兹·塞恩·科尔廷在 YouTube 上),但是这些解释缺少的是一种更深层次的直觉和一种你可以自己想出距离的感觉。

我在这里的目的是通过编辑距离和等价性给出一些解释,这将让你对 DTW 的现状有一个更直观的了解。你甚至可以用这些想法来构建你自己的距离概念!

为了帮助解释,我将使用示例x=(0,1,1,-2,0)y=(0,0,1,-1)来说明为什么这两个序列之间的 DTW 距离是 1。

DTW 通过编辑距离

编辑距离通常用于自然语言处理和 DNA 分析。维基百科关于编辑距离的文章给出了很好的描述:

编辑距离是一种通过计算将一个字符串转换成另一个字符串所需的最少操作次数来量化两个字符串之间不同程度的方法

标准的操作是:删除一个字符,插入一个字符,用一个字符替换另一个字符,每一个对距离的贡献是相等的。

DTW 可以被认为是编辑距离的一种形式,其中的操作如下:

  • 可以在相邻空间中插入或删除条目的副本。这是零成本的。例如,通过复制-2条目从(0,1,1,-2,0)(0,1,1,-2,-2,0)将是零成本操作。或者从(0,1,1,-2,0)(0,1,-2,0),移除一个1将是零成本操作。
  • 可以编辑条目。如果把a编辑成b,代价就是ab之间的距离。例如,通过将1编辑为5(0,1,1,-2,0)转到(0,1,5,-2,0)将是成本为 4 的操作。
  • 可以在序列末尾插入或删除零。这是零成本的。例如,通过移除末端的0(0,1,1,-2,0)(0,1,1,-2)将是零成本操作。

xy的 DTW 距离将是使用这三种操作编辑xy的最低成本方式。注意第三个操作的原因是为了灵活地处理不同长度的系列。

作为一个小练习/挑战,尝试使用编辑距离显示x=(0,1,1,-2,0)y=(0,0,1,-1)之间的距离等于1

不,真的,我建议试一试。通过主动参与,然后被动阅读别人的答案,你会学到更多!

下面是我如何从xy。(注意,可能会有多个编辑序列达到最小距离):

  • x=(0,1,1,-2,0)开始
  • 然后是(0,0,1,1,-2,0),通过复制0。成本为 0
  • 然后通过移除重复的1来移除(0,0,1,-2,0)。成本为 0
  • 然后是(0,0,1,-1,0),将-2编辑为-1。成本为 1
  • 然后通过移除末端的0移动(0,0,1,-1),即 y 轴。成本为 0

所以总成本是 1,因此 DTW 距离是 1。

请注意,这让我们对变形的构成有了一些了解。如果你要在图表上绘制这些时间序列:

  • 添加或删除重复项对应于水平地局部挤压或拉伸事物
  • 编辑一个条目相当于局部挤压或垂直拉伸东西

经由等价的 DTW

另一种方法是问:我希望距离捕捉到xy之间的哪些差异,以及我希望距离忽略哪些差异?

有几种更正式的表达方式:

  • 我怎样才能改变xy而不影响它们之间的距离
  • 距离函数的不变性是什么
  • 我认为哪个时间序列与x的距离为 0
  • 我认为哪些序列等同于x。这是我将使用的视角。

一旦你建立了等价的概念,我们就可以定义xy之间的距离如下:

  • X是等价于x的所有级数的集合
  • Y是等价于y的所有数列的集合
  • d是一些“通常的”距离概念,例如欧几里德距离d(x,y) = sqrt(sum (xi-yi)^2)或与 L1 范数的距离d(x,y) = sum |xi-yi|
  • 然后将xy之间的距离定义为d(x', y')的最小值,其中x'距离Xy'距离Y

这是你如何使用等价来创造距离概念的一般框架。(注意,这与如何测量点集之间的距离有关,例如,在聚类中,如果您知道如何测量单个点之间的距离)。

要使用此等效框架获得 DTW 距离:

  • 我们说两个序列是等价的,如果你可以通过添加/删除重复的条目或者在末尾添加/删除 0 来从一个序列到另一个序列
  • d是距离 L1 范数的距离,所以d(x,y) = sum |xi — yi|

再一次,作为一个小练习,试着用这个视角来展示x=(0,1,1,-2,0)y=(0,0,1,-1)之间的 DTW 距离是 1。

再说一次,我真的强烈建议你试试!如果你不确定该怎么做,那就意味着我的解释不太好;如果是这样的话,请告诉我,我可以为将来做些改进!

这就是我如何得到 1:

  • (0,1,1,-2,0)相当于x'=(0,0,1,1,-2,0)
  • (0,0,1,-1)相当于y'=(0,0,1,1,-1,0)
  • x'y'之间的距离为0+0+0+0+1+0 = 1

结束语

我提供了两种不同的 DTW 算法的解释:

  • 给定一组可能的操作,确定最小编辑距离
  • 确定时间序列等价版本之间的最小 L1 范数距离

最后,我应该承认,我对小练习的回答忽略了一个重要的细节:我展示了如何可能得到 1,但我没有给出任何明确的论据证明这是最小的可能距离!对于具体的例子,这并不太难,但一般来说,这将是确定距离最困难的部分。

然而,这正是“动态”部分的用武之地!DTW 算法的好处在于,它为你提供了一个紧凑而简单的算法来计算最小值。

直观理解最大似然

原文:https://towardsdatascience.com/intuitively-understand-maximum-likelihood-121893bea5d0?source=collection_archive---------23-----------------------

基本概念

用简单的日常例子来理解基本概念,这样你甚至可以向你的祖母解释。

罗斯·索科洛夫斯基在 Unsplash 上的照片

数据科学和机器学习有很多术语。往往需要一段时间才能真正理解一些往往被形式定义和数学方程掩盖的概念。据称,根据爱因斯坦的说法,

"除非你能向你的祖母解释,否则你不会真正理解某件事。"

最大似然法是机器学习中估计参数的两种基本方法之一(另一种是最小二乘估计),许多新方法都是从这两种方法中得到启发的。

尽管如此,许多解释最大似然法的课程和书籍都没能清楚地表明这种技术只是常识。刚学的时候(十几年前)我的经历没什么不同。然而,读完这篇文章后,你会有更好的学习体验。我也相信在读完这篇文章后,你会很好地理解最大似然的概念,甚至可以向你的祖母解释。让我们开始吧。

我们通常都使用最大似然估计

想象一个场景,你的冰箱里有最美味的巧克力冰淇淋,可以在晚餐时享用。此外,想象你正在照顾 4 个孩子(阿尔法、贝塔、伽马和德尔塔),你明确指示他们白天不要吃冰箱里的冰淇淋。你出去买杂货。当你回来时,你发现四个孩子中的一个已经咬了一口冰淇淋。你现在的任务是确定 4 个孩子中谁吃了冰淇淋。

你将如何辨认吃冰淇淋的孩子?我们还假设这四个孩子都不合作。你现在必须像侦探一样收集线索(即收集数据)。在您收集任何数据之前,您已经提出了一个模型,它是:

【孩子的名字】 吃起冰淇淋来。

该模型有一个自由参数, 【孩子的名字】 。如果你不收集任何进一步的线索(数据),你最好的估计是模型中的自由参数可以以相等的概率(即 0.25)取四个子名中的任意一个。然而,你最终还是收集到了一些线索。让我们把这些不同的线索叫做 x1x2 ,…。, xn 暗示你一共收集了 n 条线索。一旦你考虑了你收集的所有线索,每个孩子吃过冰淇淋的概率就会改变。

利用线索(您收集的数据)来帮助识别孩子是通过最大可能性来完成的。当您试图识别正确的孩子时,您应该这样做。马上关注!

在你的脑海中,你会说:

根据我现在观察到的所有数据,那个 阿尔法 吃了冰淇淋的 可能性有多大?

然后,您将对测试版重复同样的问题:

给定我现在观察到的所有数据,那个 贝塔 吃了冰淇淋的 可能性有多大?

然后,你将为伽马和德尔塔重复它。

你会如何总结并得出答案?嗯,你只需选择可能性最高的孩子。

换句话说,你将选择给你 最大可能性的答案。

就是这样。你刚刚完成了最大似然估计程序。概括地说,您选择了一个有参数的模型。最终答案要求为该参数选择一个特定值。你观察到一些数据。然后,考虑模型中参数的每个值来估计似然值。最后,您选择了与最高可能性相关联的最终参数值。换句话说,你选择了最有可能的答案。

将直觉与现有的书籍和课程相结合

me 来看看目前大多数课程和书籍是如何教授最大似然概念的,以进一步巩固你的理解。到目前为止,解释最大似然的最常见的例子是估计正态曲线(也称为高斯曲线)的参数。正态分布曲线由平均值和标准偏差参数化。

为简单起见,以一维正态分布为例,平均值决定了曲线的位置,左边还是右边。sigma 参数决定曲线的宽度或宽度。

比较两条正态分布曲线。每条正态曲线都用平均值和标准偏差来表示。均值决定曲线的位置,标准差决定曲线的宽度(图片由作者提供)

现在想象一下,一个商业投资者来找你,他想开一家冰淇淋店。他在两个地点中的一个之间感到困惑,并选择你来帮助他决定。你需要弄清楚他需要选择两个地点中的哪一个来开一家新的冰淇淋店。对于每个城市,随机抽取 100 人进行抽样调查,以 1 到 10 分(10 分是最好的,0 分是最差的)表示他们对冰淇淋的喜爱程度。

你的任务是利用他掌握的这两个城市的所有数据,想出一个数据驱动的答案。你假设对冰淇淋的爱是正态分布的。接下来的任务是确定两个城市的均值和标准差的具体参数,然后确定哪一个会带来更高的利润。

对于每个城市,您使用最大似然法来估计平均值和标准差。换句话说,假设你观察了 100 个人对一个给定城市的评价,最能解释每个城市的冰淇淋评价的最可能分布是什么。

从数学上来说,我们对每个位置做了以下工作:

联合条件概率函数,用于确定函数最大时 θ 的值(图片由作者提供)

在较早的谁吃了冰淇淋的例子中,我们手动输入θ(孩子的名字)的每个可能值,然后找到可能性的值。我们不需要手动操作。我们使用数学和一些简化的假设来求解最大似然方程。

我希望这个帖子能够被广泛地访问,所以我不会再放任何方程了(如果你感兴趣,请留下评论,我会有一个后续的帖子,有更多的数学知识)。

说白了,我们假设这 100 个数据点是https://en.wikipedia.org/wiki/Independent_and_identically_distributed_random_variables(独立同分布)。 iid 假设有助于将联合概率函数简化为每个单独数据点概率的乘积(因为独立性假设)。随后,我们通过使用“对数”技巧将乘积项转换为总和,使我们的生活变得更加简单。最后,我们使用微积分(微分)来推导平均值和标准偏差的最终方程。**

这里的数学步骤特定于我们拥有的初始联合概率模型(似然函数)。对于法方程参数的估计,我们可以解析求解。然而,对于其他模型,我们可能不得不求助于数值解并使用迭代算法。

摘要

最大似然法是机器学习的基本方法之一。它帮助我们找到似然函数的未知参数。似然函数是以我们需要估计的参数为条件的联合概率函数。

数学方法给了我们一种估计这些参数的方法。从概率上来说,最大似然法使我们能够证明,给定我们观察到的数据,我们选择的带有估计参数的模型是最有可能解释这些数据的模型。

这都是常识,即使我们没有意识到或者没有被正式教导,我们在日常生活中已经在大脑中这样做了。

**https://ahmarshah.medium.com/membership **

从 Zillow 翻转业务的失败中吸取宝贵的数据科学经验

原文:https://towardsdatascience.com/invaluable-data-science-lessons-to-learn-from-the-failure-of-zillows-flipping-business-25fdc218a62?source=collection_archive---------3-----------------------

哪里出了问题?

丹尼尔·陶西斯在 Unsplash 上的照片

介绍

Zillow 是一家成立于 2006 年的在线房地产公司。它在 2019 年创造了 27 亿美元的收入。很长一段时间以来,他们在很多方面都做得更好。这篇文章不是关于进展顺利的事情。我们会关注最近的错误。这导致该公司停止其翻转业务,并削减了 25%的员工。

一、什么是房地产的翻转业务?当某人购买一处房产,并打算在将来转售获利时。该公司通常以相对较低的价格购买房产。花钱进行翻新和其他改进。然后以更高的价格出售房产。这是一种用来赚快钱的流行技术。

如你所知,这里最重要的因素是准确预测房地产价格。这样房产就能以较低的价格买进,卖出获利。

根据的文章,2006 年 Zillow 的数据库中有大约 4300 万套房屋,他们能够以 14%的中位绝对百分比误差预测房产价格。到 2017 年,他们的数据库中约有 1.1 亿套住房。误差率已经降低到 5%。用于预测房价的模型,拥有数千个复杂的统计模型和海量数据。

哪里出了问题?

由于许多原因,他们模型的精度开始下降。这导致人们以远高于售价的价格购买房产。根据这里的消息,Zillow 在 2021 年第三季度因其翻转业务亏损超过 3 亿美元。根据这篇《彭博》文章,Zillow 现在期待出售大约 7000 套房屋,价值 28 亿美元。

下面是一些显示损失有多大的推文,

这是另一篇文章,其中有许多 Zillow 试图以低于购买价格的价格出售房产的例子。

基于这些数据,很明显失败的主要原因是无法准确预测价格。数据科学家可以从这次失败中吸取很多教训。我将根据公共领域中可用的内容来阐述可能的原因。

1.数据质量

机器学习模型表现良好的首要因素是高质量的数据。当机器学习算法的输入是垃圾时,你不能指望它有多好。

https://www.investopedia.com/articles/personal-finance/111115/zillow-estimates-not-accurate-you-think.asp

根据上面的文章,肯定存在数据质量问题的可能性。Zillow 一直依赖于用户共享的数据和公开的数据集。如果说 Zillow 的数据质量是垃圾,那就太苛刻了。尤其是因为他们的模型在很多情况下都做得很好。但是这里误差的影响是巨大的。让我用一个例子来解释一下,

Zillow 正在考虑购买一处名为“ABC”的房产,然后计划投资一些资金进行改造,并在几周内出售以获取利润。假设 Zillow 的 Zestimate 对房产“ABC”的估价为 50 万美元。如果模型有 10%的误差,这意味着实际价格应该是 45 万美元。现在,Zillow 以 5 万美元的溢价买下了这处房产。Zillow 将很难在这块地产上获利。

如上例所述,对于每一个百分比,模型都偏离准确预测。附在预测上的价值正在偏离一个很大的值。价值百万美元的房产 10%的误差就是 10 万美元。仅仅几个这样的财产就可能造成超过一百万的损失。此外,预测郊区房地产价格的错误会影响附近其他房地产的价格,并在总体上影响该地区本身的房地产价值。

数据中的一个简单错误,如房产中房间的数量、离最近学校的距离,以及其他与关键属性有关的问题,都很容易导致预测错误。这很容易产生滚雪球效应。

第三课:在任何数据科学问题中,都应该关注数据的质量。有适当的指标来衡量数据的质量是很好的。在像 Zillow 这样的场景中,小错误可能导致大错误,应该有一种方法至少部分地验证数据质量。这有助于在质量问题造成巨大影响之前发现它。

2.算法依赖性

算法不错。他们很有见地。这对决策有很大帮助。他们容易出错和出问题,这也是事实。不建议完全依赖算法。尤其是当你在解决一个有很多不确定性的问题时。

房价取决于很多因素。有太多的外部因素会对房价产生影响。不可能监控这些外部因素并将其纳入模型。因为每一个改变在投入使用之前都需要经过测试。

当用例没有巨大的货币影响时。预测出现一些误差是可以的。例如,假设我们想要预测客户的终身价值。客户终身价值 10%的误差不会严重影响财务状况。但与房价类似,也有小误差不可接受的情况。

第七课:在我们无法承受预测偏差的情况下。模型输出应该作为一种补充,帮助业务用户做出决策。例如,在为保险公司承保的情况下。承销过程有巨大的财务影响。模型输出应该补充信息,但不应该做出决策。这个决定还是应该由承销商来做。因为承保人是领域专家,他可以发现算法可能遗漏的东西。

下次当你在解决数据科学问题时。总是询问关于重要性和影响的问题。如果风险很高,那么应该有一个专家小组来监督模型输出并做出决定。

3.玩弄系统

当涉及到金钱时,用户总是有可能试图欺骗系统。

https://www.theguardian.com/business/2021/nov/04/zillow-homes-buying-selling-flip-flop

上述文章清楚地阐述了系统被利用的可能性。很明显,郊区的房价很少能带动郊区的房价上涨或下跌。明白这一点的人可以人为地提高郊区房价。

想知道怎么做吗?假设有一个代理人,在郊区持有多套房产。起初,代理人会以人为抬高的价格向一个已知的内部联系人出售部分房产。一旦影响波及到郊区的其他房产。他们以更高的利润出售其他财产。

教训:确保系统不被利用的唯一方法是建立一个防欺诈团队。反欺诈团队将会获得所有以高于或低于市场价格出售的资产。以确保这些影响不会传递到模型上。

4.选择性聚焦

很明显,在 Zillow 的案例中,人们对房产及其价格预测有着太多的关注。对买家的关注还不够。最终是投资房产的人。没有很好地了解买家可能会有问题。

对于房地产公司来说,了解买家行为非常重要。不了解买家,就无法准确衡量需求。因此价格本身无法准确预测。

第一课:任何数据科学问题都要从所有可能的角度去分析。应该以整体的方式研究它们。此外,如果你在模型投入使用前就学习是不够的。即使在模型投入使用后,也应继续进行整体数据分析。情况可能会有变化。

为了简单地解释这一点,假设我们想要预测正在搅动的客户。有一个内部焦点来理解客户为什么会有各种各样的原因是一回事。这将告诉你很多关于导致客户流失的问题的信息。但是,可能有其他因素,如竞争提供更好的折扣。因此,如果不从不同的角度处理这个问题,就不可能做出有把握的决定。在这个例子中,如果只关注客户和提供的服务是不够的。它还需要对互动、社交媒体上的情绪、竞争策略等进行分析。

5.外部因素

外部因素在任何问题中都起着巨大的作用。在房价预测的情况下,也有很多外部因素会影响房地产的价格。

例如,假设 Zillow 计划以 500,000 美元的价格购买一处房产“ABC ”,计划投资 50,000 美元进行装修,并计划以 600,000 美元的价格出售该房产。

为了简单起见,让我们假设 500,000 美元的购买价格是准确的,并且反映了当前的市场价格。现在,翻新的计划预算为 50,000 美元,但由于外部因素,劳动力需求增加,因此翻新成本也增加了 25,000 美元。最重要的是,由于像 Covid 这样前所未有的事件,对房子的需求减少了。这导致了房产价格的下降。因此迫使 Zillow 亏本出售房产。此外,长期持有该物业并不理想,因为这将吸引额外的维护成本。

Zillow 拥有的许多房产现在正在亏本出售。有许多外部因素在起着巨大的作用。不可能总是识别所有的外部因素。但是应该努力将这些事件纳入模型中。此外,应该努力分散风险。

在 Zillow 的案例中,很明显,根据这里的文章,他们在投资组合中增加了太多的房产,而不是正在出售的房产。增加如此多的房产增加了对装修所需劳动力的需求。对劳动力需求的增加增加了劳动力成本。从而使局势进一步恶化。

最后一个音符

有如此多的数据科学应用为企业增加了巨大的价值。他们中的一些人帮助企业赚钱。其中一些有助于解决问题。其中一些有助于改善体验。但确实也有一些人失败了。其中一些失败并没有造成很大的损失,而另一些却造成了巨大的损失,比如 Zillow。

心智模型对于正确分析商业问题非常有帮助。它也有助于构建思维过程,从而得出最佳解决方案。这是一篇关于使用思维的基本原则来解决数据科学问题的文章

[## 如何用第一性原理思维解决数据科学问题?

towardsdatascience.com](/how-to-use-first-principle-thinking-to-solve-data-science-problems-db94bc5af21)

其他参考文献

https://www.theguardian.com/business/2021/nov/04/zillow-homes-buying-selling-flip-flop

保持联系

零售库存管理——确定性需求

原文:https://towardsdatascience.com/inventory-management-for-retail-deterministic-demand-311682c02518?source=collection_archive---------15-----------------------

建立一个简单的模型来模拟几种补货规则(基本、EOQ)对库存成本和订购成本的影响

需求确定的库存管理—(图片由作者提供)

对于大多数零售商来说,库存管理系统采用固定的、基于规则的方法来进行预测和补货订单管理。

考虑到需求的分布,目标是建立一个补货策略,使您的订购、持有和短缺成本最小化。

  • 订购成本:因管理成本、系统维护或制造成本而订购的固定成本(欧元/订单)
  • 持有成本:持有库存所需的所有成本(储存、保险和资金成本)(欧元/单位 x 时间)
  • 短缺/缺货成本:没有足够库存满足客户需求的成本(销售损失、罚款)(欧元/单位)

在本文中,我们将介绍一种简单的方法,使用用 Python 构建的离散模拟模型来测试几个库存管理规则。

  • 确定性恒定需求:D (单位/年)
  • 订购和补货之间的提前期(天)
  • 短缺和储存成本(欧元/单位)

💌新文章直接免费放入你的收件箱:时事通讯

**SUMMARY**
**I. Scenario
Problem Statement** As an Inventory Manager of a mid-size retail chain, you are in charge of setting the replenishment quantity in the ERP.
**Objective
II. Build your Model
Economic Order Quantity (EOQ)** *What is the best compromise between ordering and holding costs?* **1\. Visualize the current rule
2\. Economic Order Quantity: Q = Q*****3\. Include replenishment lead time
4\. Real-Time visualization of Cost of Goods Sold (COGS)**
**III. Conclusion & Next Steps**

一.情景

问题陈述

作为一家中型零售连锁店的库存经理,您负责在 ERP 中设置补货数量。

根据商店经理的反馈,你开始怀疑 ERP 的补货规则是否是最佳的,尤其是对那些跑得快的人,因为你的商店正面临着因缺货而导致的销售损失。

对于每个 SKU,您希望构建一个简单的模拟模型来测试几个库存规则,并估计对以下各项的影响:

  • 总成本:接收、储存和销售该产品的成本是多少?
  • 缺货:缺货导致的销售损失百分比是多少?

在本文中,我们将构建这个模型,

# Total Demand (units/year)
**D = 2000**
# Number of days of sales per year (days)
**T_total = 365**
# Customer demand per day (unit/day)
**D_day = D/T_total**
# Purchase cost of the product (Euros/unit)
**c = 50**
# Cost of placing an order (/order)
**c_t = 500**
# Holding Cost (% unit cost per year)
**h = .25**
c_e = h * c
# Selling Price (Euros/unit)
**p = 75**
# Lead Time between ordering and receiving
**LD**
# Cost of shortage (Euros/unit)
**c_s = 12**

为了简化理解,让我们介绍一些符号

方程式—(图片由作者提供)

目标

在本文中,我们将

  1. 想象商店经理使用的当前规则
  2. 计算经济订货量并模拟影响
  3. 想象订购和接收之间的交付周期的影响
  4. 每个规则的齿的实时可视化

http://samirsaci.com

二。建立模型

密码

你可以在这个 Github 资源库中找到完整的代码:链接
我的其他项目组合:萨米尔萨奇

经济订购数量(EOQ)

许多库存优化模型使用的经济订货量(EOQ)背后的理论是找到最优订货量 Q*,它将是订货成本和持有成本之间的最佳折衷。

  • 较低的订单数量会增加您的订购成本(增加:D/Q 的补货订单数量),但会降低您的持有成本(降低平均库存水平:(Q/2))
  • 高阶数量的倒数

总相关成本的最小值—(图片由作者提供)

评论

在上图中,我们可以看到总相关成本(TRC) (不含采购成本 cD 的总成本)在 Q*=400 单位/订单时最小。

TRC(Q *)= 5000 欧元

1.可视化当前规则

目前的规则是每 10 天订购一次满足 10 天需求所需的确切数量。

这个量远低于 Q*,我们很容易理解 TRC 将远高于其最佳值:

TRC(10) = 100,062 欧元

为了理解为什么让我们模拟 365 天的规则:

当前规则模型化-(图片由作者提供)

备注 非常短的补货周期,使补货订单数量成倍增加。

2.经济订货量:Q = Q*

对于每个补货周期,您订购 Q* = 400 个订单,并在库存水平为零时再次订购。

经济订货量—(图片由作者提供)

备注 更长的补货周期使订单数量减少 7 倍= >更低的 TRC

http://samirsaci.com

3.包括补货提前期

如果我们有一个补货提前期 LD = N 天,缺货水平会是多少?

提前 25 天的经济订购量—(图片由作者提供)

备注 订购和收货之间有 25 天的提前期,我们每个补货周期达到 140 单位的缺货量。

4.销货成本(COGS)的实时可视化

如果你想说服你的商业团队和商店经理;你需要说他们的语言。

您可以使用 COGS (这里我们将排除购买成本 COGS = TRC) 准备一个简单的潜在营业额可视化,以了解一年中的影响。

初始规则

具有初始规则的 COGS(图片由作者提供)

点评
由于补货量少导致的再订货频率高,COGS 主要由订货成本驱动。

EOQ 法则

与 Q*的齿轮(EOQ)——(作者图片)

三。结论和后续步骤

关注我的 medium,了解更多与供应链数据科学相关的见解。

结论

这种简单的建模是设计基本模拟模型的机会,该模型显示了客户需求和库存规则对关键绩效指标的影响。

它让您可以了解您的订购频率、库存水平以及供应链中交付周期的影响。

后续步骤

恒定确定性需求的初始假设非常乐观。在下一篇文章中,我们将研究需求的可变性对总相关成本和销售损失的影响。

**https://www.samirsaci.com/inventory-management-for-retail-stochastic-demand-2/ **

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运作和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

**https://samirsaci.com **

参考

[1]供应链科学,华莱士·j·霍普

零售业的库存管理——随机需求

原文:https://towardsdatascience.com/inventory-management-for-retail-stochastic-demand-3020a43d1c14?source=collection_archive---------9-----------------------

假设需求呈正态分布,模拟安全库存水平对库存管理绩效指标的影响

需求随机的库存管理—(图片由作者提供)

对于大多数零售商来说,库存管理系统采用固定的、基于规则的方法来管理预测和补货订单。

考虑到需求的分布,目标是建立一个补货策略,使您的订购、持有和短缺成本最小化。

在上一篇文章中,我们建立了一个模拟模型,假设确定性恒定需求 (单位/天)

在本文中,我们将改进这个模型,并向介绍一种简单的方法,使用 Python 构建的离散模拟 模型来测试几个库存管理规则,假设客户需求呈正态分布。

💌新文章直接免费放入你的收件箱:时事通讯

**SUMMARY**
**I. Scenario** 1\. Problem StatementAs an Inventory Manager of a mid-size retail chain, you are in charge of setting the replenishment quantity in the ERP.
2\. Limits of the deterministic modelWhat could be the results with a normally distributed demand?
**II. Continuous Review Policy: Order Point, Order Quantity (s, Q)** 1\. Introduction of the Inventory Policy2\. Definition of the Safety Stock3\. How do you define k? **III. Example of replenishment policies**
1\. Target of CSL = 95%
2\. Target of IFR = 99%
**III. Conclusion & Next Steps**

一.情景

1.问题陈述

作为一家中型零售连锁店的库存经理,您负责在 ERP 中设置补货数量。

根据商店经理的反馈,你开始怀疑 ERP 的补货规则是否是最佳的,尤其是对那些跑得快的人,因为你的商店正面临着因缺货而导致的销售损失。

对于每个 SKU,您希望构建一个简单的模拟模型来测试几个库存规则,并估计对以下各项的影响:

绩效指标

  • 周期服务水平(CSL) :每个周期发生缺货的概率 (%)
  • 物品填充率(IFR) :满足顾客需求而不缺货的百分比(%)

在本文中,我们将构建这个模型,

# Total Demand (units/year)
**D = 2000**
# Number of days of sales per year (days)
**T_total = 365**
# Customer demand per day (unit/day)
**D_day = D/T_total**
# Purchase cost of the product (Euros/unit)
**c = 50**
# Cost of placing an order (/order)
**c_t = 500**
# Holding Cost (% unit cost per year)
**h = .25**
c_e = h * c
# Selling Price (Euros/unit)
**p = 75**
# Lead Time between ordering and receiving
**LD**
# Cost of shortage (Euros/unit)
**c_s = 12
# Order Quantity** Q = 82 (units/order)

为了简化理解,让我们介绍一些符号

符号—(作者提供的图片)

2.确定性模型的局限性

在前一篇文章中,我们假设需求是一个常数确定性的;我们现在将引入随机性以更接近真实需求。

恒定需求 D = 5.4 单位/天的初始模型—(图片由作者提供)

需求呈正态分布会有什么结果?

符号—(作者提供的图片)

**µ_D = 2000 (items/year)
σ_D = 50(items/year)**

随机年度需求分布 N(2000,50)的初始模型

你需要改进你的补货政策,以弥补需求的波动。

你听说过库存周转率 KPI 吗?
在这个短片中了解更多,

http://samirsaci.com

二。持续审查政策:订购点、订购数量(s,Q)

密码

您可以在我的 Github 资源库中找到完整代码: 链接 (跟随我:D)
我的投资组合与其他项目:
萨米尔萨奇

1.库存政策介绍

为了解决这个需求波动的问题,我们将引入一个持续的评审策略(s,Q)

  • 持续审查=每天都会检查您的库存水平
  • (s,Q) =如果您的库存水平≤ s 您的 ERP 将订购 Q

为了简化理解,让我们介绍一些符号:

符号—(作者提供的图片)

2.安全库存的定义

再订购点可以定义为在订购和接收之间的交付周期内满足客户需求所需的最低库存水平。

安全库存是补偿需求波动的缓冲。

3.你怎么定义 k?

您的绩效指标将直接受到安全库存水平的影响;k 值越高,你的表现就越好:

  1. 你为这两个指标中的任何一个设定目标(例如:我希望我的 CSL 是 95%)
  2. 你计算 k 来达到这个目标
  3. 你修正你的再订购点

http://samirsaci.com

三。补充政策示例

1.CSL 的目标= 95%

根据 CSL 的定义,我们有:

方程式—(图片由作者提供)

k = 1.64
Reoder point with CSL: 36 units

s = 32 个单位的(s,Q)模型—(图片由作者提供)

评论

在这个例子中,我们可以看到,我们没有面临任何股票,最低库存水平非常接近于零。

代码

2.IFR 的目标= 99%

在前面的例子中,我们的目标是 95%的补货周期没有缺货。

在这个例子中,我们将更加关注我们以 IFR 为目标全面交付产品的能力。这个公式使用的是单位正常损耗函数(关于这个函数的更多信息可以在这里找到: 链接 )。

方程式—(图片由作者提供)

IFR 的最佳 k 值= 99%——(图片由作者提供)

# G(k) = Q/sigma_ld * (1 - IFR)
IFR = 0.99
G_k = (Q/sigma_ld) * (1 - IFR) = 0.14# Final value of k
k = 0.71
Reoder point with CSL: **31 units**

s = 31 个单位的(s,Q)模型—(图片由作者提供)

评论

要在不缺货的情况下达到 99%的需求单位,您需要一个较低的安全库存。(31 个单位对 32 个单位)

代码

http://samirsaci.com

四。结论和下一步措施

关注我的 medium,了解更多与供应链数据科学相关的见解。

结论

这个改进的模型带来了更好的结果,因为它考虑了安全库存大小需求的可变性。

这个过程很简单,首先确定你的绩效指标目标(IRF、CSL),然后用 k 值计算你的安全库存水平。

后续步骤

持续审查政策的主要问题是,如果您的投资组合中有许多 SKU,则需要大量的补货。

作为商店经理(或仓库经理),你更喜欢固定补货时间(例如:每周两次)。因此,我们将在下一篇文章中介绍定期审查策略。

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运营和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

参考

[1]供应链科学,华莱士·j·霍普

[2]零售库存管理—确定性需求,萨米尔 Samir,链接

使用 Python 在可视化中研究图像和自定义颜色

原文:https://towardsdatascience.com/investigating-images-and-customizing-colors-in-visualizations-with-python-5226c834cb65?source=collection_archive---------33-----------------------

使用 Alteryx Designer 中的图像配置文件工具快速了解您的图像数据集,然后添加几行 Python 代码,使用自定义调色板创建数据可视化

萨姆比斯利

看电视侦探注意细节并通过环顾犯罪现场来破案总是很有趣。他们的观察力是戏剧性的,令人印象深刻(尽管有时他们会面临一些幽默的挑战,这取决于节目)。

图像通过 GIPHY

新的图像轮廓工具也非常擅长快速观察图像的细节。Alteryx Intelligence Suite 的计算机视觉工具组的新成员可以快速分析图像,使您可以将对图像的见解整合到更大的工作流程中。您可以获得关于每张图像的格式、颜色、拍摄地点的信息(如果 EXIF 数据可用并包含 GPS 细节),以及关于图像的各种汇总统计数据。(后者的一个例子是找到图像像素值的标准偏差,以量化图像中的对比度水平。)

你可以将这些信息用于各行各业,从农业到零售业到制造业。也许你想知道哪种产品颜色在你的顾客中最受欢迎。也许你想通过图像的附加位置数据来绘制图像,以寻找地理模式,并使用 Designer 的分配工具来构建人口统计细节。也许您想在推荐引擎或基于图像的搜索系统中使用图像数据。您可以从图像中收集的“证据”可以增强许多项目。

图片经由 GIPHY

无论您的动机是什么,我将向您快速介绍该工具及其选项,并且我将为我们的 Python 爱好者提供一个奖励:一种使用 Stitch Fix 发布的开源 Python 包为图像最常见的颜色指定人类友好名称的方法。另外,我们将探索一种方法来生成这些颜色的自定义可视化。开始调查吧!

图片经由 GIPHY

如果鞋子合脚:准备服装数据集

在这个演示中,我使用了 3781 张不同服装在普通背景上的图片。我使用一个目录工具将图像引入工作流,然后使用一个 Regex 工具从每个目录的名称中提取服装的类型,认为这可能对以后的排序和分析有用。然后,我使用一个图像输入工具开始工作流程的图像部分。

在进入剖析步骤之前,我使用了一个图像处理工具。我对这些图像的初步探索表明,令人惊讶的是,很大一部分图像以不同深浅的灰色为主色调。许多衣服是在灰色背景上拍摄的。我使用图像处理工具将图像裁剪为中心区域的 200 像素的正方形,以试图将焦点集中在实际拍摄的服装上。这不是一个完美的策略。裤腿和鞋子之间的间隙可能会稍微扭曲最终结果。这个过程中的一个物体检测步骤有助于将分析集中在衣服上。但是在增加这一步后,我看到了更多“丰富多彩”的不同结果,所以这似乎有所帮助。

图像通过 GIPHY

询问图像:工作中的图像轮廓

最后,调查者进入场景:图像轮廓工具,它需要最少的配置。只需告诉它哪个字段包含您的图像,以及您想要为每个图像检索哪个(些)简档,或此处描述的一组细节

作者图片

运行工作流会提供每个图像的关键细节。基本配置文件包括如下所示的字段以及更多内容。下面是显示图像中最常见颜色的字段,以 RGB 和十六进制格式表示,以及暗像素和亮像素的数量。

作者图片

自我解释:将颜色结果转化为人类术语

从来没有人说:“我最喜欢的颜色是#afada6!”或者“我想要一件[37,150,190]色调的衬衫。”那些是什么颜色?

您可能对 RGB 和/或十六进制代码感到满意。例如,您可以使用这些 RGB 细节来聚类图像,或者使用最近邻来匹配新图像。但是如果把你的颜色结果翻译成人类术语并想象它们的频率会有所帮助,请继续阅读。

图片经由 GIPHY

像往常一样, xkcd 给我们指路。由网络漫画的创作者进行的颜色命名调查的结果被集成到开源 Python 包 colornamer 中并得到增强,该包由 Stitch Fix 的数据科学团队开发。这些数据科学家尤其需要确保他们在推荐服装时对颜色进行了细微的区分。为此,他们创建了一个颜色层次,具有特定的、人类可读的名称和不同级别的区别,调色板选项的大小从 900 多种命名颜色到两种选项(“颜色”或“中性”)。他们的过程和调色板的所有细节都显示在 the Stitch Fix 博客帖子中,同时还有一个颜色的交互式图形。

使用 colornamer 和 Python 工具中的几行代码,我能够为每张图像最常见的颜色生成友好的名称,并将其添加到我的数据集中。例如,看看下面的图片和它的主色。

作者图片

图像配置文件工具告诉我们,最常见的颜色的 RGB 值是[70.72,28.02,37.88],该颜色的十六进制代码是#461c25。那种颜色显示在右上方。使用 colornamer,我们可以检索这些值的名称,从最具体到最不具体:

xkcd 颜色:深栗色

设计颜色:深酒红色

常见颜色:栗色

颜色系列:红色紫色

颜色类型:深色

彩色或中性:彩色

这些颜色名称可以帮助您以易于理解的方式对图像进行筛选或分组,然后在文档中使用这些图像或使用报告工具自动生成 PowerPoint 幻灯片。

图片经由 GIPHY

在可视化中使用自定义颜色

从这一点来看,绘制一个图表来显示每种颜色在图像数据集中占主导地位的频率是非常简单的。但就我个人而言,我发现在绘图中看到所有颜色的名称都用一种默认颜色来描绘令人不安。(这是一个很好的 Stroop 效应的例子,在这个效应中,我们的大脑努力处理不一致的刺激!)

幸运的是,根据最常出现的主要图像颜色创建自定义调色板并在绘图中使用它们并不太难。然后,我们可以简单地使用 pandas 内置的绘图功能来生成一个条形图,并将其位置输出到我们的工作流中。(我在这里写了关于从 Python 工具中获取绘图的博客。)从那里,很容易查看和/或保存情节。

作者图片

我绘制了这个数据集中前 10 种主色出现的频率。仍然有很多灰色,但通过一些灰色占主导地位的图片可以证实,实际的衣服,而不仅仅是背景,确实经常是灰色的。(在这里,我认为我自己的灰色主题衣柜是一个异数。)

请记住,自定义调色板可能是也可能不是色盲友好的。你可以在这篇博文中阅读更多关于这个问题的内容,并找到一些工具和资源。

图像通过 GIPHY

用图像求解

图像配置文件工具提供了将图像的有趣信息引入工作流程的绝佳机会。享受您自己的图像调查,配备这一新的检查工具。我希望你能找到一些激动人心的、引人注目的结果!

想试试这个吗?下载数据集,解压缩它,并获取这篇文章所附的工作流程,如最初在 Alteryx 社区上发布的。使用目录工具将数据集引入工作流。(也请确保在工作流程结束时更新渲染工具中的文件路径。)您需要以管理员身份运行 Designer,以便 Python 工具可以为您安装 colornamer 包。

原载于 Alteryx 社区数据科学博客

调查美国屋顶太阳能数据

原文:https://towardsdatascience.com/investigating-u-s-rooftop-solar-data-aeafa0206237?source=collection_archive---------43-----------------------

使用 Tableau 可视化

作者照片

寒假期间,我决定利用一些空闲时间来学习更多关于 Tableau 的知识。这是一个强大的工具,我在学校项目中使用过,但我想探索如何用它来帮助回答关于数据的高层次问题。鉴于我对能源的兴趣,我寻找可以用来学习更多可再生能源知识的数据集。

我偶然发现了谷歌正在做的与太阳能相关的工作,名为“天窗项目”。我想知道我是否可以利用他们的数据来更多地了解美国太阳能投资的多样性。

根据我在东西海岸和中西部生活的时间,我知道每个地区对太阳能有不同的看法。例如,与我在俄亥俄州长大的地方相比,在北加州这里的房子上看到太阳能电池板要常见得多。

虽然美国各地的天气模式明显不同,使得太阳能在一些地方比其他地方更可行,但我不得不相信在我长大的地方仍然有太阳能的潜力。这让我想到了我想回答的问题:

哪些州的太阳能潜力最大?

这篇文章的其余部分向你展示了我是如何得到我的结果的,希望你喜欢!

项目天窗

项目天窗是谷歌的一项事业,使个人太阳能更容易获得。他们创造了一个工具,用户可以输入他们的地址,并找出他们的房子每年接受多少可用的阳光,他们的屋顶有多少可用于太阳能电池板,以及他们潜在的能源账单节省。

项目天窗用户界面

它还提供了如何获得太阳能电池板的信息,这有助于居民了解他们个人可以采取的步骤,以转移到清洁能源。

过程

这个过程的第一步是登录 Google Cloud 控制台,并使用 BigQuery 工具。Google 在 Google 云平台 BigQuery 工具【2】上提供了大量来自 Project 天窗的数据,可以使用他们的免费层访问。在公共数据集下,项目天窗有两个数据集,一个按邮政编码分组,另一个按人口普查区域分组。我认为使用邮政编码来汇总州一级的数据是最简单的方法。

查询完所有数据后,我将其下载到一个 csv 文件中,以便在本地工作。我在 PostgreSQL 中创建了一个数据库,并导入了数据。数据集包含大量要素,但并非所有要素都是分析所必需的。下面的 SQL 查询显示了从完整的集合中提取的信息,这些信息在州级别上进行分组。每个要素都有一个注释,更详细地描述正在提取的数据。

项目天窗数据的 SQL 查询

有了这些数据,我就可以创建一个可视化的东西来理解这些信息了。我用 Tableau 创建了一个交互式的美国地图。地图根据太阳能建筑的数量给每个州涂上颜色。可用的建筑越多,橙色越深。此外,还有一个条形图,显示安装了太阳能的建筑在所有可安装太阳能的建筑中所占的百分比。例如,您可以在条形图的顶部看到夏威夷,这表示他们在所有可利用太阳能的建筑上安装了很高比例的太阳能电池板。

用户可以通过一个或多个状态进行过滤,并单击状态或相应的栏来访问更详细的信息。

点击下面的图片,亲自尝试一下吧!

点击上图查看交互式仪表盘

回答?

我很惊讶地得知,我的家乡俄亥俄州,以及伊利诺伊州和密歇根州,是一些最大的未充分利用的潜力。

加利福尼亚州、德克萨斯州、佛罗里达州和亚利桑那州每年能够产生的潜在 GWh 最高。俄亥俄州排名第五(48,049 GWh),伊利诺伊州排名第六(47,048 GWh),密歇根州排名第九(40,840 GWh)。

有序的年潜在太阳能发电量

就目前屋顶太阳能的利用量而言,这些中西部州都处于光谱的低端。俄亥俄州、伊利诺伊州和密歇根州的利用率都是 0.20,相当于所有州的第 36 个百分点。

已利用太阳能潜力百分比的汇总统计

在俄亥俄州长大的我,不会想到基础设施或天气会允许数据显示的潜力。这一分析很好地提醒了我们,数据可以帮助揭示挑战我们认知的事实。

未来的研究

这些数据帮助我量化了屋顶太阳能的潜力。尽管如此,还有很多事情可以做。收集更多与成本相关的数据,以了解不同转型水平所需的投资规模,或许有助于相关政策的实施,这将是令人感兴趣的。

这个 web 应用程序是用 Django 创建的,托管在 Heroku 上。查看 github 仓库以了解更多细节。

https://github.com/jackseagrist/Project_Rooftop_Solar

Jack Seagrist 目前是斯坦福大学的一名学生,正在攻读环境工程硕士学位。他热衷于使用最新的数据驱动流程来解决气候挑战。通过 twitterlinkedin 联系,或者查看他的网站来了解更多关于他的工作。

参考资料:

1-https://www.google.com/get/sunroof

2-https://cloud.google.com/bigquery

使用 Turi Create 的 iOS 计算机视觉对象检测

原文:https://towardsdatascience.com/ios-computer-vision-object-detection-with-turi-create-be109edd4257?source=collection_archive---------31-----------------------

iOS 计算机视觉项目概述,该项目的构建和部署不到一天时间

卡尔·海尔达尔在 Unsplash 上拍摄的照片

计算机视觉项目无处不在。

不幸的是,训练你的计算机视觉模型并不总是容易的。Keras 中的对象检测需要一些操作,而在 Tensorflow 或 PyTorch 中编写相同的代码需要一些严肃的代码柔术。那么,即使你能够训练你的模型,也要祝你好运把它放到移动设备上。谷歌云的 AutoML 解决了部分问题,但简单的 iOS 部署可能难以实现。

苹果用它的 Create ML 工具做了一件惊人的工作,让 iOS 的计算机视觉更加平易近人。如果你不关心超参数调整,或者如果你被 Python 或 Keras 吓到了,那么苹果提供了一种快速简单的方法,只需拖放你的标记图像,然后开始训练。训练后,模型可以很容易地放到 iOS 应用程序中,让其他人也能很容易地使用你创造的东西。作为起点,苹果开发者文档提供了一个用于对象检测的优秀示例应用

但是,如果您试图训练的模型过于耗费资源,无法在标准 Mac 硬件上构建,该怎么办?如果您想利用 GPU 来加快训练过程,该怎么办?根据这篇文章的标题,你可能会认为这是 Turi Create 的切入点。

https://github.com/apple/turicreate

为了更好地了解一个端到端的 Turi Create 项目是什么样子的,你可以看看这个用于计算机视觉扑克牌检测的 repo ,以及这个总结项目的论文这个视频概述

https://github.com/mcgovey/compvision-playing-card-detection

对于那些不熟悉 Turi Create T1 的人来说,它是一个 Python 库,抽象了 Tensorflow、PyTorch 甚至 Keras 的复杂性。它的 Python API 可以很容易地将数据格式化为所需的预处理图像格式,然后创建一个可以在不同类型的硬件上运行的模型(不仅仅是像 Create ML 这样的 MAC)。

使用笔记本电脑之外的东西最好的一点是,有一个免费的资源可以帮助使用已经可用的 GPU 进行培训,Google Colab。根据你的模型的复杂性,你可能需要升级你的账户,以利用谷歌 Colab Pro 的高内存和更快的 GPU。

项目演练

在使用 Turi Create 做任何事情之前,您必须将数据转换成一种叫做 sFrame 的格式。这意味着您计划用来训练计算机视觉模型的图像必须具有概述图像、标签和边界框尺寸的格式(如果是对象检测模型)。这本笔记本讲述了一个物体探测模型的例子。

一旦你的数据在一个 sFrame 中,你就可以开始使用 Turi Create 构建你的模型了。本笔记本会带你完成这些步骤。如上所述,加速模型训练的方法之一是使用 GPU。如果您使用的是 Google Colab,您可以通过单击运行时>更改运行时类型>然后选择硬件加速器下的下拉菜单并将其更改为 GPU 来实现。

在 Google Colab 中改变运行时类型。

一旦设置被更改,你仍然需要让 Turi Create 来识别你的 GPU。在 linux 系统上(这是 Google Colab 构建的基础),你可以用下面的代码块来做这件事(注意,在这些命令之间还有其他事情要做,但是我想强调一下特定于 GPU 的命令。

!pip install turicreate!pip uninstall -y tensorflow!pip install tensorflow-gpu!export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATHtc.config.set_num_gpus(-1)

要了解更多关于本库实现的细节,请查看 Turi 创建文档

一旦将数据加载到 sFrame 和环境设置中,就可以开始训练模型了。您可以决定您希望模型运行多少次迭代。对于您的第一次运行,您将希望从少量的迭代开始,以确保一切按预期运行。

# Create a modelmodel = tc.object_detector.create(train_data, max_iterations=10)

训练就是这么简单!

既然您已经训练了您的模型,请确保保存它。如果你想以后再来看它,那么你要确保把它保存为一个。型号文件。当你准备把它放到 iOS 应用程序中时,把它存为一个。mlmodel

# Save the model for later use in Turi Createmodel.save(’mymodel.model’)# Export for use in Core MLmodel.export_coreml(’mymodel.mlmodel’)

最后一件事!你会想看看你的模型表现如何。您可以使用 model.evaluate(test_data)方法来查看模型在训练数据或样本数据之外的表现。

这并不难!所以下一次当你试图建立一个计算机视觉模型,并且你不想担心在 Keras 中训练一个模型和担心转换格式,或者创建 ML 花费太长时间的时候,想想 Turi Create!

用于数据科学的 iPad Pro + Raspberry Pi 第 1 部分:首次操作系统初始化

原文:https://towardsdatascience.com/ipad-pro-raspberry-pi-for-data-science-part-1-first-time-os-initialization-854371dc9201?source=collection_archive---------8-----------------------

树莓派+ iPad

让您从拆箱到操作系统初始化都可以使用 iPad + Pi!

几周前,我写了一篇关于能够在 iPad Pro 上执行数据科学活动的状态的文章。虽然我真的很惊讶看到苹果近年来取得的进步,但我们仍然没有 100%达到有人可以放弃笔记本电脑只在 iPad 上做事情的程度。我个人希望这一切发生,因为我喜欢用我的 iPad 做任何事情,从平面设计到用屏幕播放我的钢琴曲。

正如我在上一篇文章中引用的:

因为 iOS 不是传统的操作系统,有许多事情我不能做,因为我依赖命令行工具、Docker 映像等等。我很有兴趣看看苹果是否能够克服这些障碍,但不幸的是,它们在 2021 年 1 月仍然存在。

说实话,我看不到苹果会很快拿出解决这些问题的本土方案。在做了一些关于人们如何使用 iPad 作为通用软件开发机器的互联网研究后,我遇到了一件奇怪的事情:使用树莓 Pi 作为一种“计算附件”。因为 Raspberry Pi 是它自己的电脑,它可以运行 Linux,并从原生 iOS 中带回许多缺失的功能。(不是 100%完美;稍后会详细介绍。)

此外,这些人想出了如何直接连接 Raspberry Pi,并通过命令行以虚拟屏幕和 SSH 的形式与之交互。因此,从理论上讲,你可以在一个没有互联网连接的偏僻地方,做几乎所有的数据科学工作,只要你事先保存数据并预装依赖关系。不错!

听起来很酷,所以我想试试。给刚接触树莓派的你一点鼓励:这是我第一次拥有或设置一个。我很久以前就知道它是什么了,但直到现在我才觉得有必要拥有它。现在,这是我的设置的样子:

作者捕获的图像

在这篇文章中,我们将从头开始讲述一切。我将像几周前第一次打开树莓酱时那样开始。当连接到显示器/键盘/鼠标时,我们将努力实现一个全功能的 Raspberry Pi。在接下来的文章中,我们将关注 iPad 和 Pi 之间的硬连接,安装数据科学工具,甚至安装一个很酷的 JupyterHub 应用程序。

首先,让我们来看看您需要的硬件。

数据科学 Pi 的硬件

这个项目实际上需要两类硬件。第一个类别显然是 Raspberry Pi 及其相应的组件,但是为了第一次设置 Pi,第二个类别包含了我们在很短时间内需要的所有东西。

让我们从第一类开始。

作者创建的图像

树莓 Pi 本身就是一款树莓 Pi 4 型号 B 。这种型号有三种不同的内存:2GB、4GB 或 8GB。我个人选择了 8GB,但我认为你可以用一个更小的版本。我在亚马逊上以的名义买了一个小套件,里面还包括一根电源线和散热器。回想起来,我意识到如果没有他们的电源线,我也可以直接购买 Pi。活到老,学到老!

接下来,你需要一个 microSD 卡来存放操作系统和数据。我个人有一个 200GB 的卡(是的,我有类似的东西),但我认为你可以用低得多的容量。我在网上看过最低 16GB,更推荐 32GB。鉴于目前 microSD 卡如此便宜,我肯定会选择 32GB 或更高的。

最后需要的是 USB-C 到 USB-C 电缆。它将作为 Pi 的电源和 Pi 与 iPad 之间的网络通道。这里你有很多选择,但是要注意:它必须符合 PD(功率传输)标准。令人惊讶的是,iPad 附带的电缆不起作用。如果你喜欢我的电缆,你可以在这里找到它

最后一张图片不是必须的,但绝对推荐。你会注意到我的 Pi 被一个内置冷却风扇的盒子包围着。你可能会感到惊讶,但它出奇地便宜,而且易于安装。(亚马逊上 10 美元左右。)它为 Pi 提供了一些不错的冷却和一些聊胜于无的保护。

现在,让我们来看看我们只在第一次设置时需要的东西。

作者创建的图像

在接下来的安装部分,你会看到我们首先需要使用外部计算机在 microSD 卡上安装 Raspberry Pi 操作系统。不幸的是,我不认为有办法在 iPad 上加载操作系统,所以你需要一台电脑。我将使用我的个人 MacBook,但由于我们只是在很短的时间内使用电脑,你可以很容易地借用朋友的电脑一个小时来完成这一步。

最后,在将 Pi 连接到 iPad 之前,我们必须直接在 Pi 上执行一些初始化步骤。也就是说,你需要以下东西:

  • USB-C 电源
  • 用于连接微型 HDMI 插槽的显示器电缆(注:不要将微型 HDMI 误认为微型 HDMI。我自己可能做过,也可能没有…)
  • 外部显示器/监视器
  • USB-有线键盘
  • USB-有线鼠标

还是那句话,可以的话可以临时借用那些东西。我自己借用我爸爸的键盘和鼠标,因为我实际上不再拥有有线键盘或鼠标了。

收集好材料后,让我们进入第一步:在 microSD 卡上安装操作系统。

在 microSD 卡上安装操作系统

作者创建的图像

好吧,我撒谎了。如果你和我一样,你从其他你不用的设备上拿了一张 microSD 卡。我的 200GB microSD 卡实际上是我的旧任天堂 Switch 卡,所以我首先必须吹掉那里的所有数据,为安装操作系统做准备。为此,我们将正确格式化 microSD 卡,为了确保万无一失,我甚至建议在新卡上使用这种方法。我不打算在这里讨论这个,但是这篇 WikiHow 文章实际上在展示 Windows、Mac 甚至 Android 的步骤方面做得很好。

为了让事情变得简单,我们不打算做任何花哨的事情,而是选择通过官方的 Raspberry Pi Imager 安装标准的 Raspberry Pi 操作系统。将 microSD 卡连接到计算机后,导航到成像仪软件的链接,然后按照屏幕上的说明进行操作。您应该会看到类似于我在上面的截图中显示的 UI。

大约 10 分钟后,成像仪将完成 Raspberry Pi 操作系统的安装,并为您提供“全部清除”信息,以便安全地从您的计算机中移除 microSD 卡。这就是电脑!现在,让我们继续将 microSD 卡放入 Raspberry Pi,将显示器和附件连接到 Pi 本身,并首次启动 Raspberry Pi。

Raspberry Pi 操作系统初始化

作为帮助自己回忆第一次是如何实现这一切的一部分,我清除了自己的 Raspberry Pi 来重新创建和记录我第一次遵循的相同步骤。在我初始化 Raspberry Pi 操作系统的两次过程中,都花了 3-4 次断开/重新连接 Pi 电源,因为它会随机挂起。老实说,这让我感到不安,但在这两种情况下,操作系统最终加载得很好,没有任何问题。

一旦它最终加载完毕,你应该会看到一个桌面界面,背景是日落前的一些寺庙。操作系统会问你几个问题,包括一个要求更改默认用户密码的问题,所以按照 UI 提示的去做。它可能会提示额外的更新,正如你在下面的截图中看到的那样。否则,恭喜你!你有一个功能齐全的树莓派。🎉

作者创建的图像

…未完待续!

现在我们已经完全初始化了操作系统,我们准备好进入将 iPad 正确连接到 Raspberry Pi 的步骤。不可否认,这个过程是漫长而艰巨的,因为这篇文章已经够长了,我们将在下一篇文章中专门讨论 Pi 与 iPad 的强硬连接。同时,欢迎您将您的 Pi 与显示器/键盘/鼠标组合一起使用,如果您愿意,甚至可以提前工作。剧透:下一篇文章将建立在互联网上其他资源的基础上。你是个精明的人,不用我帮忙,你大概也能从这里弄清楚!😉

对于那些想等到下一篇文章的人来说,我保证过不了多久我就会发表它。我已经开始写了!如果你继续关注,我会非常感激。一如既往,非常感谢你阅读这篇文章!

用于数据科学的 iPad Pro + Raspberry Pi 第 2 部分:设置硬线连接!

原文:https://towardsdatascience.com/ipad-pro-raspberry-pi-for-data-science-part-2-setting-up-the-hardline-connection-555f939c29c2?source=collection_archive---------9-----------------------

树莓派+ iPad

带您完成设置,让 iPad Pro 和 Raspberry Pi 通过 USB-C 硬线连接相互对话

朋友们,又见面了!在我们系列的下一篇文章中,我们将把树莓 Pi 用作 iPad Pro 的“计算 DS 附件”。如果你错过了第一篇文章,请通过下面的链接查看,因为这篇文章将建立在第一篇文章的基础上:

在我们第一篇文章的结尾,我们刚刚初始化了 Raspberry Pi 的操作系统,并使用了硬连线的显示器/键盘/鼠标。您的设置目前可能如下所示:

作者捕获的图像

在这篇文章的最后,我们将让你的 iPad Pro 通过一根直接的硬线 USB-C 电缆与你的 Raspberry Pi 交谈,你将不再需要硬连线的显示器/键盘/鼠标组合。您将能够以两种不同的方式从 iPad 与 Raspberry Pi 交互:通过命令行的 SSH 连接和作为虚拟显示。

公平的警告:这篇文章将会是最长和最麻烦的。我特意清除了我自己的树莓派,并重新创建了这里的所有步骤,只是为了确保您在这里没有任何问题。请务必仔细阅读每一步,我相信你会做得很好。

好了,让我们开始吧!

Raspberry Pi 网络配置

在这篇文章的第一部分,我们需要使用我们的显示器/键盘/鼠标组合来直接与 Raspberry Pi 交互,并正确配置文件,以便它可以很好地连接到 iPad。我们在很大程度上是在这篇文章的基础上发展起来的,所以要特别感谢本·哈迪尔为我们开辟了这条道路!

(注意:本文假设您知道如何使用基本的 Linux 命令进行必要的调整。如果这是你不熟悉的东西,我可以推荐这个免费的在线课程来帮助你入门。)

这些步骤是直接从本的超级便利的帖子中摘录的。我个人使用sudo nano直接从命令行修改文件。欢迎您以您最熟悉的方式进行调整。

  • dtoverlay=dwc2添加到文件/boot/config.txt的最后
  • modules-load=dwc2添加到文件/boot/cmdline.txt的最后
  • /boot目录中创建一个名为ssh的空文件(我是使用命令sudo touch ssh完成的)
  • libcomposite添加到文件/etc/modules的末尾
  • denyinterfaces usb0 (usb zero,而非“O”)添加到文件/etc/dhcpcd.conf的最后
  • 使用下面的命令安装dnsmasq:sudo apt-get install dnsmasq(在这个过程中,它会要求你点击“Y”来确认安装。)
  • 在目录/etc/dnsmasq.d下创建一个名为usb的新文件,并填入以下内容:
interface=usb0
dhcp-range=10.55.0.2,10.55.0.6,255.255.255.248,1h
dhcp-option=3
leasefile-ro
  • 在目录/etc/network/interfaces.d/下创建一个名为usb0的新文件,并填入以下内容:
auto usb0
allow-hotplug usb0
iface usb0 inet static
  address 10.55.0.1
  netmask 255.255.255.248
  • /root/目录下,创建一个名为usb.sh的新文件,并用以下内容填充它:(注意:三次检查你得到的都是正确的。这是我个人因为愚蠢的错误而犯错最多的地方。为了确保万无一失,我可能会推荐从本·哈迪尔的网站上复制/粘贴这个脚本。)
#!/bin/bash
cd /sys/kernel/config/usb_gadget
mkdir -p pi4
cd pi4
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
echo 0xEF > bDeviceClass
echo 0x02 > bDeviceProtocol
mkdir -p strings/0x409
echo "fedcba9876543211" > strings/0x409/serialnumber
echo "David Hundley" > strings/0x409/manufacturer
echo "PI4 USB Device" > strings/0x409/product
mkdir -p configs/c.1/strings/0x409
echo "Config 1: ECM network" > configs/c.1/strings/0x409/configuration
echo 250 > config/c.1/MaxPower
mkdir -p functions/ecm.usb0
HOST="00:dc:c8:f7:75:14" # "HostPC"
SELF="00:dd:dc:eb:6d:a1" # "BadUSB"
echo $HOST > functions/ecm.usb0/host_addr
echo $SELF > functions/ecm.usb0/dev_addr
ln -s functions/ecm.usb0 configs/c.1/
udevadm settle -t 5 || :
ls /sys/class/udc > UDC
ifup usb0
service dnsmasq restart
  • 使用下面的命令使/root/usb.sh成为我们刚刚创建的可执行文件:sudo chmod +x /root/usb.sh
  • 在文件/etc/rc.local中,在显示exit 0的行之前添加行/root/usb.sh

唷!这无疑是本教程中最难的部分。如果一切顺利,你现在应该可以将 Raspberry Pi 直接插入 iPad,并在设置中将 Raspberry Pi 识别为以太网设备。这是我的 iPad 目前的样子:

作者捕获的图像

好了,我们几乎完成了显示器/键盘/鼠标的组合,但是在我们可以单独使用 iPad 之前,我们还需要做最后一件事。

Raspberry Pi 虚拟机和显示设置

在本文的最后一部分,我们将在 iPad 上使用一个特定的应用程序来连接 Pi,就像它是一个虚拟机一样,为了正确使用它,我们必须再做一些额外的调整,以便虚拟机显示可以在应用程序中正确显示。

首先,我们需要在 Raspberry Pi 配置设置中手动设置 Pi 的分辨率。这样做的原因是 Pi 应该为您动态地选择它,但是出于一些奇怪的原因,它没有显示在我们将使用的 VM iPad 应用程序中。(你只是得到这个奇怪的“显示器无法显示”的信息。)为了将屏幕分辨率设置为特定设置,您需要遵循以下说明:

  • 运行命令sudo raspi-config,这将显示一个基本的 UI
  • 导航至Display Options,然后导航至Resolution
  • 选择分辨率DMT Mode 83 1600x900 60Hz 16:9(老实说,我肯定别人也行;这只是我碰巧选的一款,而且效果很好。)

那件作品到此为止。我们需要配置的另一部分是 VNC 连接设置。你可以在右上角的任务栏中找到它。我的看起来像这样:

作者捕获的图像

在这个小界面中,通过点击右上角的“汉堡”图标并选择“选项”来导航到 VNC 设置在“Security”部分,您会注意到“Authentication”方法自动默认为“UNIX password”。我们将把它更改为“VNC 密码”,所以您现在应该会看到类似这样的内容:

作者捕获的屏幕截图

点击“应用”,你就可以开始了。在离开 VNC 连接用户界面之前,记下它在主屏幕上显示的 IP 地址。我的名字碰巧是10.0.0.74,如果你的名字也是,我也不会感到惊讶。仅供参考,我在这里分享的这些说明与我们将要使用的应用程序的支持页面上记录的说明是相同的,所以如果您迷路了或我错过了什么,请参考链接到此处的它们的文档

现在,我们终于准备抛弃显示器、键盘和鼠标了!继续关闭您的 Pi,并用 USB-C 电缆将其连接到 iPad。我们将使用各自的虚拟机和命令行应用程序。

用于与您的 Pi 交互的 iPad 应用程序

最后,我们期待已久的部分!如果你做到了这一步,你就可以开始在 iPad Pro 上直接使用你的树莓 Pi 了。在最后一个主要部分,我们将介绍两种不同的方式来与您的 Raspberry Pi 交互:一种方式作为命令行界面,另一种方式作为虚拟机显示。你可能更喜欢其中的一个,但是实际上我发现在某些用例中两者都是必要的。

让我们从命令行界面应用程序开始。

对于我们的命令行界面,我们将使用 Blink Shell 应用程序(19.99 美元)。这个应用程序被设计成非常好地与 Mosh 和 SSH 客户端集成,我们将使用它作为 SSH 客户端与我们的 Pi 进行交互。

这个应用程序本身非常简单。当你第一次打开它时,你会看到一个熟悉的黑屏和一个简单的命令行界面。为了 SSH 到您的 Pi,您需要执行以下命令:

ssh <your_pi_name>@<your_ip_address>

如果您遵循我的指示并保持简单,更精确的语法将如下所示:

ssh pi@10.55.0.1

然后会提示您输入密码,一旦输入正确,您就可以开始了!现在让事情变得更简单,Blink Shell 允许您保存配置设置,以便更快地进入 Pi。为此,输入config命令。然后,您会看到一个类似如下的用户界面:

作者捕获的屏幕截图

这包含了 Blink Shell 应用程序的所有设置。要保存您的 SSH 凭证,请导航到“主机”并点击 UI 右上角的+按钮。在这里,您需要输入主机名(pi)、主机名(10.55.0.1)和密码。(您可以保留默认端口,在我的例子中是 22。)点击右上角的Save,现在你可以开始了。

现在,你只需要在命令行输入ssh pi,它就会自动连接到你的 Raspberry Pi。我看起来是这样的:

作者捕获的屏幕截图

就是这样!命令行界面完成!相对于 VM 显示方法,我个人更喜欢使用这种连接到我的 Pi 的方法,但是正如我之前提到的,VM 显示方法确实有它的用途。现在让我们继续进行配置。

屏幕:进入您的 Pi 的虚拟机窗口

伙计们,我们现在到了最后阶段。对于最后一部分,你需要下载名为Screens(19.99 美元)的应用程序。说实话,我们可以在这里使用其他免费选项,但它们不提供屏幕所提供的交互性。使用 Screens 应用程序,您可以使用键盘和鼠标光标直接与 Raspberry Pi UI 进行交互,就像它是您的 iPad 自带的一样。不幸的是,免费选项不提供这种程度的交互性。

当你第一次打开应用程序时,你会看到一个简单的空白屏幕。在用户界面的右上角,你会看到一个+图标,这将允许我们输入设置以连接到我们的树莓 Pi。点击图标,然后点击“新屏幕”按钮,你会看到这个小界面:

作者捕获的屏幕截图

如果你想知道,它永远不会自动找到我们的 Pi,所以我们需要通过导航到Custom...选项来插入我们自己的设置。看到Screen Settings界面后,您需要输入以下信息:

  • 名字:无论你想它是什么,这都没关系
  • IP 地址:不管你的 VNC 服务器 IP 地址是什么(我的是 10.55.0.1)
  • 端口:保持默认值 5900
  • 操作系统:改为“树莓派”
  • 认证方式:保留为“VNC 密码”
  • 密码:您可以在这里保存您的密码,否则每次您尝试登录时它都会提示您输入密码。你的选择;我个人把密码保存在这里。

保存这些设置,我们就正式完成了!现在,你可以点击屏幕用户界面中的适当项目,就像它直接在你的 iPad 上运行一样,与 Raspberry Pi 操作系统界面打招呼。

作者捕获的图像

唷,那是一篇很长的帖子,但我们终于成功了!你现在应该可以通过硬线连接从你的 iPad Pro 直接与你的 Raspberry Pi 连接了!我们已经完成了显示器/键盘/鼠标组合,所以如果你像我一样借了任何东西,你可以把这些东西还给你的朋友,并对他们说谢谢!

但是我们还没有完成。在下一篇文章中,我们将把我们的设置提升到一个新的水平,开始使用一些你会经常用到的数据科学工具。与普通电脑相比,在树莓派上安装东西可能有点不寻常,所以请继续关注下一篇文章。感谢您的阅读,祝您编码愉快!

用于数据科学的 iPad Pro + Raspberry Pi 第 3 部分:安装我们的数据科学工具

原文:https://towardsdatascience.com/ipad-pro-raspberry-pi-for-data-science-part-3-installing-our-data-science-tools-77d020e485f2?source=collection_archive---------18-----------------------

树莓派+ IPAD

在你的 Raspberry Pi 上安装从 Docker 到 Git 到 JupyterHub 的工具

欢迎回来,伙计们!我们又回来了,这是我们的第三篇,也可能是最后一篇文章,让树莓 Pi 与 iPad Pro 一起工作,进行数据科学工作。如果到目前为止你一直在跟进,那么你已经能够通过 USB-C 到 USB-C 的直接连接将 Raspberry Pi 连接到你的 iPad Pro。如果你错过了让我们走到这一步的前两个帖子,它们又出现了:

在本帖中,我们将介绍如何将所有数据科学工具正确安装到 Pi 上。如果你不知道,树莓派的 CPU 使用 ARM 架构,而其他许多现代计算机使用 x86 架构。不要担心,你不需要知道这些到底是什么意思,但它是说安装一些东西可以有点不寻常。

好了,我们有很多内容要讲,所以让我们开始吧,进入我们的第一个工具:熊猫。

熊猫

在大多数情况下,您可能熟悉使用类似pip install pandas的命令从 PyPi 下载 Python 库。好消息是pip仍然适用于许多 Python 库;坏消息是,奇怪的是,它对其他一些工具不起作用。由于 Pandas 是数据科学家工具箱中最重要的工具之一,我认为提出这种替代的安装方式是很重要的。

为了让我们的熊猫下载到 Pi,我们将使用apt。如果你不熟悉的话,这是在基于 Linux 的机器上安装软件的一种常见方式。(APT 代表“高级打包工具”。)为了在您的 Pi 上正确安装 Pandas,您需要做的就是在您的 CLI 中运行以下命令

sudo apt install python3-pandas

就是这样!你现在可以用熊猫了。我们的下一个工具!

Git / GitHub

如果您像我和大多数其他数据科学家一样,那么您很可能正在使用某种形式的 Git 来执行版本控制和与队友的代码集成。在我的日常工作中,我使用 Git 和 GitLab,对于我的个人工作,我使用 Git 和 GitHub。如果你像我一样,你也可能使用 GitHub 来展示你的个人作品。也就是说,我们将安装 git,并“git”您的 Git 与您的个人 GitHub 帐户一起工作。(你喜欢我的双关语吗?)

为了安装 git 本身,apt再次拯救了我们。你需要做的就是运行下面的命令:sudo apt install git。这就是我们安装 Git 所需要做的一切。在开始将 git 连接到 GitHub 之前,让我们首先设置 Git 配置设置。运行以下命令分别设置您的姓名和电子邮件:

git config --global user.name "Your Name"
git config --global user.email "your_email@yourdomain.com"

好了,现在我们准备好将 Git 连接到 GitHub。这将比我们到目前为止所做的要复杂一些,所以请小心遵循下面过程中的每一步。实际上,你可以在 GitHub 的官方文档中找到几乎所有这些相同的步骤,但是我将在这里继续讲述,因为官方文档并不完全是线性的。(如果你和我用的是同一个屏幕应用程序,有一件事很特别。)

在下面的步骤中,我们将执行这三个高级操作:生成一个新的 ssh 密钥,将 SSH 密钥添加到 ssh-agent,以及将 SSH 密钥添加到 GitHub。

生成新的 SSH 密钥

自从我这么做已经有一段时间了,我真的不记得 SSH 密钥是否已经成为你的 Raspberry Pi 操作系统初始化的标准了。在任何情况下,我们将继续前进,并创建一个新的,使我们自己的东西相似。以下是实现这一目标的步骤:

  1. 打开您的 CLI。(如果你遵循了我上一篇文章中的步骤,这将是你的 Blink Shell 应用程序。)
  2. 通过运行以下命令创建一个新的 SSH 密钥,替换掉您自己的 GitHub 电子邮件:
    ssh-keygen -t ed25519 -C "your_email@yourdomain.com"
  3. 当你点击“回车”时,它会要求你“输入一个保存密钥的文件”。如果您不输入任何内容,它将进入默认位置。我们对它转到默认位置没有意见,所以不要输入任何内容,继续操作并再次点击“enter”。
  4. 输入两次您希望用于 SSH 的密码,这就完成了这篇文章!

向 ssh 代理添加 SSH 密钥

现在已经创建了 SSH 密钥,我们需要将 SSH 密钥添加到 ssh-agent 中。这是一个非常简单的过程,可以分为两步:

  1. 使用以下命令在后台启动 ssh-agent:eval "(ssh-agent -s)"
  2. 通过运行下面的命令,将新的 SSH 私有密钥添加到 ssh-agent 中。请注意,如果您按照上面的建议选择了默认位置,下面的命令将正常运行。如果没有,您可能需要做一些小的调整,以确保您的 ssh-agent 获得正确的密钥。
    ssh-add ~/.ssh/id_ed25519

将 SSH 密钥添加到 GitHub

我们就快到了!这就是事情变得有点奇怪的地方,因为我们使用 iPad 连接到我们的 Pi。只有在我们上一步安装了 Screens 应用程序的情况下,这些步骤才有意义。遗憾的是,在最后一部分,我们不能只使用 CLI (Blink Shell ),因为我们将使用 iPad 的 web 浏览器来输入这些 SSH 凭证。

1.我们将使用一个名为xclip的小工具将 SSH 公钥文件的内容复制到剪贴板。为了安装这个,我们将再次使用我们的老朋友 apt:sudo apt install xclip

2.如果你还没有,现在是时候启动屏幕应用程序了。这样做的原因是因为xclip工具将 SSH 密钥文件的内容复制到 Raspberry Pi 的剪贴板,而不是 iPad 本身的剪贴板。幸运的是,Screens 应用程序允许我们在 iPad 和 Pi 之间来回传输剪贴板内容。

3.在您的 Raspberry Pi 界面中打开终端。为了确保我们在同一页上,这是我现在看到的:

作者捕获的图像

4.运行以下命令将您的 SSH 密钥复制到 Raspberry Pi 剪贴板:xclip -selection clipboard < ~/.ssh/id_ed25519.pub

5.为了继续在 iPad 上直接使用 SSH 密钥,我们需要将 Raspberry Pi 剪贴板的内容转移到 iPad 的剪贴板上。这在屏幕上非常容易做到。在屏幕 UI 的右下角,您会看到一个带有向上箭头的小方块。单击它,然后单击“获取剪贴板”选项。现在你的 SSH 密钥将会出现在你的 iPad 的剪贴板上!

作者捕获的屏幕截图

6.打开您最喜欢的浏览器,导航到您的个人 GitHub 帐户。

7.通过点击用户界面右上角的个人资料照片图标,然后点击“设置”,导航至您的帐户设置

作者捕获的屏幕截图

8.在左侧导航菜单中,点击“SSH 和 GPG 键”

9.单击绿色的“添加新的 SSH 密钥”按钮。

10.你现在应该可以看到下面截图中的用户界面。从你的剪贴板粘贴密钥,并给密钥起一个你喜欢的名字。我刚喝了一杯叫“树莓派”的。

作者捕获的屏幕截图

11.点击绿色的“添加 SSH 密钥”按钮,我们就完成了!

恭喜你。您现在可以从您的 Raspberry Pi 与您的个人 GitHub 进行交互了!

码头工人

我个人经常使用 Docker 图像,所以我对在 iPad 上进行数据科学研究的最大抱怨之一是,真的没有办法在本机上构建或使用 Docker 图像。虽然 Pythonista 是一个为直接使用 Python 提供了很好的界面的应用程序,但是没有专门的应用程序来构建 Docker 图像。(而且是的,我明白这是为什么。那不会阻止我对此感到不安。)

像我们的其他工具一样,在 Raspberry Pi 上安装 Docker 是非传统的,但幸运的是它不像其他一些东西那么复杂。再次感谢 Sofija Simic 在本网站提供这些指导

  1. 通过运行以下命令,确保我们运行的是最新的版本:sudo apt-get update && sudo apt-get upgrade
  2. 通过运行以下命令从 Docker 的官方网站下载安装脚本:curl -fsSL [https://get.docker.com](https://get.docker.com) -o get-docker.sh
  3. 执行你刚刚下载的脚本:sudo sh get-docker.sh
  4. 通过运行以下命令sudo usermod -aG docker [user_name]将您的 Pi 用户添加到 Docker 组(注意:如果您在初始化您的 Raspberry Pi 时保留了默认用户设置,您的用户名将是“Pi”。)

就是这样!如果你想确保一切运行正常,我会运行“hello-world”容器(sudo docker run hello-world),看看你是否得到了正确的输出。我们已经准备好进入我们最后的,也许是最有趣的工具:JupyterHub。

朱庇特枢纽

你可能用过 Jupyter 笔记本或者 JupyterLab,但是你可能不熟悉 JupyterHub。JupyterHub 在创建合法的发现环境方面更上一层楼。这是因为 JupyterHub 允许多个用户、多个计算资源和多个数据源聚集在一个屋檐下。它非常棒,我们实际上在我的财富 50 强公司的日常工作中使用 JupyterHub。

所以你可能会想,为什么我们要在小小的树莓派上启用这种“企业级”的东西呢?我有两个原因,你可能不在乎其中一个,但肯定会在乎另一个。您可能不关心的一点是支持多用户。但另一个更重要的原因是,我们将设置 JupyterHub 在 Pi 启动时立即启动,我们将能够从我们的 iPad 立即连接到它,而不必启动任何特殊的启动命令。

再次感谢 Gerold Busch 为我的这一部分提供了基础。让我们开始在您的 Pi 上启用 JupyterHub!(注意:我不会在这篇文章中讨论用户管理,但是如果你对此感兴趣,Gerold 的文章在这方面做得很好。)

我们将在这里讨论两个最重要的话题。第一个是在您的 Raspberry Pi 上启用 JupyterHub 的自动启动,第二个将向您展示如何直接从您的 iPad 上快速使用 JupyterHub。

在您的 Pi 上安装 JupyterHub

1.如果您还没有,请确保您已经准备好了所有的 Python 配置设置。如果到目前为止您一直在关注这个系列,那么您可以跳到下一步。否则,您需要运行以下命令:

sudo rm /usr/bin/python
sudo ln -s /usr/bin/python3 /usr/bin/python
sudo apt-get update
sudo apt-get install python3-pip
sudo pip3 install --upgrade pip

2.为了配置一个允许 JupyterHub 正确接收用户的代理,我们需要安装 NPM(节点包管理器)和另一个叫做configurable-http-proxy的工具。我们可以通过运行以下命令来安装它们:

sudo apt-get install npm
sudo npm install -g configurable-http-proxy

3.我们现在需要安装来自 PyPi 的 Jupyter 笔记本和 JupyterHub。我们可以通过一个简单的命令来实现:

sudo -H pip3 install notebook jupyterhub

4.JupyterHub 使用基于 Python 的配置文件来存储 JupyterHub 的设置。为了正确使用它,我们需要首先生成它,然后将它移动到/root目录中。我们可以使用以下命令来实现这一点:

jupyterhub --generate-config
sudo mv jupyterhub_config.py /root

5.我们现在需要编辑刚刚创建的配置文件中的bind_url。我们将它设置为端口 8888,但不一定非要这样。为此,运行命令sudo nano /root/jupyterhub_config.py。然后,我们需要取消注释并使用此信息更新以下行:

c.JupyterHub.bind_url = 'http://:8888'

6.好了,我们的 JupyterHub 初创企业的基本行为现在可以开始了。现在我们只需要让我们的 Raspberry Pi 在 OS 启动时启动 JupyterHub。为此,我们首先需要在systemd中创建一个新文件。为了启动这个过程,运行下面的命令:sudo nano /lib/systemd/system/jupyterhub.service.

7.用以下信息填充这个新文件:

[Unit]
Description=JupyterHub Service
After=multi-user.target[Service]
User=root
ExecStart=/usr/local/bin/jupyterhub --config=/root/jupyterhub_config.py
Restart=on-failure[Install]
WantedBy=multi-user.target

8.运行下面的命令,让一切井然有序,并启动和运行 JupyterHub:

sudo systemctl daemon-reload 
sudo systemctl start jupyterhub 
sudo systemctl enable jupyterhub 
sudo systemctl status jupyterhub.service

在 iPad 上使用 JupyterHub

如果您将我的帖子与 Gerold 的原始帖子进行比较,您会注意到我忽略了将 JupyterLab 作为 JupyterHub 实例的默认接口。这并不是因为我不喜欢 Lab,而是因为它不能与 Juno Connect 一起工作,Juno Connect 是我们用来连接 JupyterHub 的应用程序。

说到 Juno Connect,您可能还记得我在以前的一篇文章中推荐使用 Juno 作为 Jupyter 接口。Juno 和Juno Connect(9.99 美元)由同一家公司制造,但区别在于 Juno 被设计为在 iPad 上本地工作,而 Juno Connect 仅用于与远程服务器一起工作。我真的很喜欢原生的 Juno,但是它有一点限制,因为您只能使用纯 Python 库。(还是那句话,原生 iPad 的另一个局限。)Juno Connect 将使用 Raspberry Pi 的计算资源,因此我们不会受到本地 Juno 的限制。它们都有自己的用例,所以我个人都安装了。

抱歉,如果最后一段有点风的话。让我们开始设置 Juno 连接您的 Pi。你只需要打开应用程序,点击“添加 Jupyter 服务器”如果到目前为止您已经完成了本系列,您将能够使用这些设置填写服务器信息:

作者捕获的屏幕截图

点击“保存”,你就可以开始了!如果您现在导航到您的任何一台笔记本电脑,您将看到与您熟悉的基本 Juno 应用程序相同的用户界面。我的设置现在看起来是这样的:

作者捕获的图像

这种工作方式最酷的一点是,您不仅限于与 Juno Connect 甚至 iPad 进行交互。如果你喜欢更自然的体验,你可以在普通的浏览器中直接用你的 IP 地址连接到 JupyterHub。我在我的 iPhone 上测试了同一个 IP 地址——它根本没有直接连接到 Pi——你瞧,它工作了!(虽然这将是一个可怕的工作方式!)

作者捕获的图像

这篇文章到此结束!我确信我们还可以添加更多的工具,但我认为这已经足够让您开始使用了。我不确定这个系列是否会有另外一个帖子。我目前正在寻找方法来启用一个小型 Kubernetes 集群,只是为了学习,但是我目前正在努力启用它。如果我能让它工作,我会写另一篇文章。但就算我不再写“树莓 Pi + iPad”的帖子,我也一定会多写一些数据科学的帖子。敬请关注,再次感谢您的阅读!

用于数据科学的 iPad Pro + Raspberry Pi 第 4 部分:为学习目的安装 Kubernetes

原文:https://towardsdatascience.com/ipad-pro-raspberry-pi-for-data-science-part-4-installing-kubernetes-for-learning-eb7f8ac31198?source=collection_archive---------17-----------------------

树莓派+ iPad Pro

教你如何在你的树莓派上安装 Kubernetes 来展示新的学习理念

你好,朋友们!我们再次回到我们系列的第四部分,让树莓派直接与 iPad Pro 配合使用。如果你一直在关注,你会记得我不确定我会写第四篇文章。我已经花了几个星期的时间在这个特定的帖子上,因为,老实说,让它工作起来是一场斗争。在我们开始讨论为什么我要写第四篇文章之前,我想鼓励新读者看看之前的三篇文章:

作为一名机器学习工程师,我日常工作的主要职责是与我们的数据科学家合作,生产他们构建的机器学习解决方案,以便与我们的其他企业级系统进行适当的交互。当然,执行这项工作的部署环境不止一个,但是最近出现的最流行的一个是 Kubernetes。当谈到我的日常工作时,我要么在内部 Kubernetes 集群上工作,要么使用像 SageMaker 这样的 AWS 服务。

也就是说,我喜欢在沙盒空间中测试我的新实验,以免影响生产中运行的任何东西。说到我的个人设置,我一直在一个名为 Minikube 的工具的帮助下,在我的个人 MacBook Pro 上运行单节点 Kubernetes 集群。Minikube 已经很棒了,但不幸的是它不能与树莓 Pi 一起工作。这是因为 Raspberry Pi 使用基于 ARM 的 CPU 架构,不幸的是,目前还没有一款 Minikube 支持这种架构。

但是不用担心!我发现了一个不同的解决方案,叫做 K3s,我们将在这篇文章中启用它。如果你不知道,Kubernetes 经常被缩写为“k8s”,这是因为在 Kubernetes 的“k”和“s”之间有 8 个字符。我不能肯定地说这一点,但我不得不猜测 K3s 的命名方式,因为它是一个更轻量级版本的 Kubernetes。我不知道我是否会将它推荐给一个完整的企业级生产系统,但作为一个测试新想法的沙盒空间——就像在我们的 Raspberry Pi 上——K3s 肯定能完成任务。

在开始安装 K3s 之前,我应该注意到这篇文章不会涉及任何关于使用 Kubernetes 的“操作方法”。即使你从未使用过 Kubernetes,你也一定可以继续关注这篇文章,但是我们不会在这篇文章中讨论任何类型的机器学习部署模式。但请继续关注,因为我还有一些其他的帖子将在 Kubernetes 上演示,我个人将使用我的 iPad/Raspberry Pi 组合来执行这项工作。

好了,让我们开始安装吧!

K3s 初始安装

好的,在我们进入实际安装之前,我们需要做一件简单的事情。您需要在/boot/cmdline.txt文件中添加一些东西。将这些项目添加到该文件的末尾,与其他项目位于同一行:

cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory

重启你的 Pi,现在我们可以继续了!

K3s 在你的 Raspberry Pi 上的实际安装非常简单,尽管在我最终弄清楚我需要做什么之后才变得简单。您只需运行以下命令:

curl -sfL [https://get.k3s.io](https://get.k3s.io) | sh -s - --write-kubeconfig-mode 644

这个命令做了几件事。正如你可能从这里的curl命令中知道的,我们首先从 K3s 网站下载适当的文件,然后用从下载中得到的 shell 脚本安装组件。我第一次做的时候没有注意到的是--write-kubeconfig-mode命令。这个 Kubernetes 部署的独特之处在于,K3s 使用一个特定的k3s.yaml文件进行配置设置。如果你不运行带有644值的标志,K3s 将不能识别那个文件,你基本上不能使用 Kubernetes。

完成安装需要一点时间,但是一旦完成,您应该能够运行下面的命令并看到某种成功消息:sudo systemctl status k3s。除了启动 Kubernetes 集群本身,K3s 安装脚本还会做一些其他的事情。首先,它将创建一个额外的 shell 脚本来轻松卸载 K3s。如果您遇到任何问题,并且需要从头开始,运行以下命令将完全清除您的 Pi 中的 K3s:

bash /usr/local/bin/k3s-uninstall.sh

K3s 安装做的第二件事是它会为你安装kubectl命令行工具,这非常方便。如果你不熟悉那是什么,kubectl是我们用来与 Kubernetes 环境交互的主要工具。当在 Kubernetes 集群中安装东西、检查东西的状态等等时,您将使用kubectl来执行所有这些命令。

好了,尽管我们已经启动并运行了基线 Kubernetes 集群,但是还需要做一些事情来设置我们的理想配置。让我们继续设置一种方法,将本地存储用于持久性卷。

为永久卷设置本地存储

如果您以前没有使用过 Kubernetes,您将会了解到,Kubernetes 计算资源(例如 pods)默认使用临时存储。Kubernetes 的伟大之处在于,如果某个资源由于某种原因而死亡(比如从集群断开电源),它会在可能的时候重建该资源。坏消息是,由于 pod 存储的短暂性,您将丢失存储后创建的任何新数据。

当然,Kubernetes 有一个机制来保护我们。Kubernetes 允许我们在被称为“持久卷”或简称为 PV 的存储设备中使用广泛的存储设备。有了实例化的 PV,Kubernetes 部署就可以以持久卷声明(简称 PVC)的形式使用 PV 的一小部分。

对于我们的实验目的,我们可以通过我们的 Raspberry Pi 利用我们的 microSD 卡上的存储,只需进行一点额外的配置。当然,这取决于你的 microSD 卡的大小。我个人使用的是 200GB 的 microSD 卡,所以我有足够的空间来使用这种模式。如果您使用的是容量较小的卡,您可能不想为您的 PV 启用本地存储。

注意到这一点,K3s 的制造商——Rancher——创建了一个小脚本,使您能够非常容易地使用您的本地存储。您只需运行以下命令:

kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml

就是这样!现在,您可以通过 K3s 使用您的本地存储。如果你想进一步测试,Rancher 在他们的 GitHub 页面上提供了一些很棒的说明和演示材料。你可以在这个链接找到那个

至此,在结束这篇文章之前,我们还有最后一部分要讲,这肯定是你会感兴趣的一部分。让 K3s 列车继续前行吧!

利用自定义 Docker 图像

所以我真的不知道这是为什么,但默认情况下,K3s 不能使用自定义的 Docker 图像。如果您找到一个发布到 Docker Hub 的,您就可以使用这些现成的,但是如果您使用自己的本地映像进行本地测试,这确实需要一点额外的步骤。(说实话,我觉得可能有更好的方法来做这件事,但我还没有想出来。如果有,我会回来更新这篇文章。)

为了使用你自己的自定义镜像,你必须压缩你的 Docker 版本并使用 K3s 命令行,以便在你的 K3s 部署中使用它们。以下是实现这一点的步骤:

  • 使用标准的docker build命令构建您的容器。
  • 将构建的 Docker 图像保存为 TAR 文件。Docker 天生就有这种能力,您可以通过运行这个命令来启动它:docker save --output YOUR_IMAGE.tar NAME_OF_YOUR_DOCKER_IMAGE:latest。(如果您使用不同的标签,请将其替换为最新的。)
  • 使用 K3s CLI 将目标映像复制到 K3s。这里有一个如何做到这一点的例子:sudo k3s ctr images import YOUR_IMAGE.tar

坦率地说,每次更新图像时,这都是一件令人头疼的事情,所以我建议您构建一个小的 shell 脚本来实现自动化。这里有一个例子,我是如何在我的另一个个人项目中做到这一点的。

朋友们,这就是我们这篇文章的结尾!如果我找到更好的方法来做上面的任何事情,我一定会用更好的内容更新这篇文章。否则,你应该很乐意在你的树莓派上搭配 K3s!正如我的 Pi 上的其他数据科学工具一样,我发现启用这种模式有很多价值。事实上,整篇文章,从标题图片到正文内容再到代码片段,都是在我的 iPad 上写的。所以你知道,当我说这种模式有效并且很棒的时候,我是认真的。😃

与计算机科学学位相比,编码训练营值得吗?

原文:https://towardsdatascience.com/is-a-coding-bootcamp-worth-it-compared-to-a-computer-science-degree-140a9fa38130?source=collection_archive---------39-----------------------

这完全是时间和金钱的问题

通过像素成像

当你想知道,“编码训练营值得吗?“你要看几个因素。编码训练营的平均费用在 13,000 美元左右。无论你选择亲自参加还是在线参加编码训练营,都是如此,尽管编码训练营的费用有很大的差异,根据语言、时长和负责人的不同,从 3000 美元到 20000 美元不等。

你还应该考虑其他选择。也许你会问“一个编码训练营值得吗?“因为你正处于计算机科学潜在职业的开端。你看到了你学习计算机科学道路上的障碍,你想知道是否值得去克服它们。13,000 美元(甚至 3,000 美元)是一笔不小的数目。

然而,如果你想知道编码训练营要花多少钱,一个编码训练营是否值得,你可能知道一个典型的选择:计算机科学学位。不仅需要更长的时间——至少两年,更可能是四年——才能完成,而且通常也更昂贵。通常,文凭比编码训练营花费更多的钱。

这是许多人说是的,一个编码训练营值得吗的部分原因:因为计算机科学雇主对计算机科学学位的价格有问题。对合格的、有才华的计算机科学家有极高的需求。而且供应量少。2019 年,有 50 万个职位空缺,但只有 72000 名毕业生。编码训练营有助于填补这一空白。

计算机科学工作很有趣,因为它们是一些最不传统的雇主。你还能想象出哪一门课程可以用 13 周的课程取代 4 年的结构化学习?但他们足够绝望,也足够开明,以技能来判断申请人,而不是一张纸上的名字,这张纸花费了数十万美元和四年时间来完成。

好消息是,对于想知道训练营费用的人来说,你比其他科目有更多的灵活性。只要你能证明你知道自己在做什么,你就能在你最喜欢的雇主那里获得一份理想的工作。

让我们来看看编码训练营要花多少钱,一个计算机科学学位要花多少钱,以及它们对你来说是否值得。简而言之,每个人的情况不一样,所以每个人的答案也会不一样。

编码训练营要花多少钱?当你看价格的时候,一个编码训练营值得吗?

在考虑一个编码训练营的成本时,没有足够多的人考虑到的一件事是机会成本。是的,这有直接的金钱成本——而且编写训练营代码并不便宜!你至少要花几千美元。3000 美元被认为是训练营的低价。

但是仅仅比较金钱忽略了编码训练营更大的成本:当你选择编码训练营时,你放弃了什么。

无论编码训练营花费你多少钱,你选择的那个也将花费你时间,这是在编码训练营是否值得的问题中要考虑的另一个因素。编码训练营比计算机科学学位花费的时间少,是的,但是放弃你的生活,在这个编码训练营上花费几个星期或几个月也会让你付出代价。

虽然学位很难与工作或生活平衡,但这是可能的。编码训练营对精神要求如此之高,以至于你不得不把所有的时间都投入到完成编码训练营的单一追求中。你花在苦读功课上的每一个小时,都可能是花在获得工作经验、观看 YouTube 教程,甚至只是花时间和你的狗在一起。

此外,编码训练营是专业化的。应该学围棋还是 Python?计算机科学学位将为你提供多种语言和技术经验的坚实基础,而训练营将专注于获得入门级工作的单一途径,即使这意味着抄近路,使你在未来更难进步。编码训练营会让你失去学习其他语言或技能的选择,因为你必须在早期致力于一个单一的主题。大多数编码训练营的学生缺乏做出正确决定的基础知识。

一个编码训练营值得吗?

老实说,这取决于你想要什么。如果你已经做了研究,并且你致力于用一些在线学习来补充你在营地获得的简化教育,那么是的,一个编码训练营可能是值得的,即使价格很高。你可以很容易地证明花费 2 万美元和 4 个月的时间来获得你的完美工作,支付 10 万美元以上的惊人福利和奇妙的工作/生活平衡是合理的。

如果不是,那么不,编码训练营对你来说是不值得的。你冒着花费几个月时间和大量金钱的风险,这些可能会让你得到一次面试机会,但不会让你为真正的面试要求做好准备。更糟糕的是,你可能会发现自己把时间和金钱花在一个特定的项目上,却发现自己其实想学习一门不同的技能或语言。

这完全取决于你的个人情况。考虑替代方案也很重要。如果编码训练营是获得你梦想工作的唯一途径,那么任何代价都是值得的。幸运的是,就业形势对申请者非常有利,这意味着你可以通过多种途径学习技能来获得编码工作。

计算机科学学位要多少钱?

一个这样的选择是计算机科学学位。当然,如果你正在读这篇文章,你可能已经获得了另一个学科的学位,或者一开始就不想要学位,这让你开始研究一个编码训练营要花多少钱,是否值得。在人生的这个阶段,你甚至可能不会考虑将计算机科学学位作为一个可能的选择。

但这将是一个错误。计算机科学学位绝对是一个选择,无论你在生活中处于什么位置,都应该被视为编码训练营的替代选择。

以前是你大学毕业,用学历找工作。但是,现代社会的工作已经超出了学位所能提供的传统范围,工作机会也远远超过了颁发的文凭数量。计算机科学就是这样一个领域。

如果你已经 50 岁了,并且获得了你的第一个计算机科学学位,雇主不会看不起你。如果你不是从麻省理工学院拿到的,他们不会拒绝你。许多当地社区大学提供计算机科学学位——我姐姐毕业于佐治亚理工学院,获得了计算机科学学位,5 年的教育费用为 40,000 美元,包括学费、住宿费、伙食费和教科书费。

当然,计算机科学学位比编码训练营花费更多,也需要更多的时间。但是它们有两个明显的成本优势。首先,它们更加灵活。一个学位需要几年时间,但是你可以在网上完成你的课程,同时工作,存钱,住在家里,等等。此外,它们提供了更多的知识。你学到的不仅仅是一套专业技能——你获得了更多的信息,一旦你有了基础,你就可以选择专业化。

这个网站列出了顶尖大学计算机科学学位的在线费用——根据你是否在本州,一个计算机科学学位的费用在 15000 美元到 67400 美元之间。

就像一个编码训练营,计算机科学学位值得吗?是的,在某些情况下。如果你有更多的时间,你不太确定你想如何使用你的计算机科学知识,你需要一个彻底的基础知识,这个代价是值得的。如果这些情况不适合你的情况,计算机科学学位对你来说可能不值得。

你冒着花费数年时间和大量金钱的风险,而实际上你并不需要。更糟糕的是,你冒着花费金钱和时间的风险,然后仍然在毕业前辍学,就像我们 40%的本科生一样。

确实存在比编写训练营代码更便宜、更快捷的替代方案。

如果你已经做到了这一步,但没有一个选择吸引你,你会很高兴知道还有其他选择。再次,我想重申计算机科学雇主是多么开明。他们不关心你是如何获得知识或技能的。这些雇主只是想知道你有什么需要。来自编码训练营的文凭或证书是获得和证明这些技能的一个有用的方法,但是有替代编码训练营和学位的选择,花费更少的时间和金钱。一个编码训练营值得吗?有时候成本太高。

首先,你总是可以选择自学。许多大学免费提供讲座,如今 YouTube 上的信息之丰富是不可想象的。如果你能为自己设计一个在线学习计算机科学的课程,那么你就很有可能从网上著名的、知识渊博的资源那里获得免费的教育和信息。

优势是显而易见的——它是免费的,或者非常便宜。这完全是自定进度的。你可以挑选你所涉及的话题。成本也很简单:要达到你将要面试的标准需要一些时间,另外你必须激励自己坚持下去,老师或讲师可能会在学位课程或编码训练营中激励你。

另外,你必须做大量的跑腿工作来证明你值得一次机会。文凭和编码训练营证书很好地向雇主证明了你有知识,并能让你通过面试。自学意味着你必须找到另一种方式在简历上展示你的知识,以便进入面试的大门。在这方面,编码训练营值得吗?是的。

还有一些地方可以在线获得计算机科学证书,价格比编程训练营和计算机科学学位便宜得多。例如, Qvault 是一个在线计算机科学学习平台,提供编程基础、计算机科学基础、围棋、实用密码学等课程。Qvault 按月或按年收费,两年的访问费用在 144 美元到 480 美元之间。它还有一个作品集,你可以向潜在雇主展示你所获得的技能和经验。

对我来说什么是正确的选择?

归根结底,只有你能回答这个问题。一个编码训练营值得吗?你应该以文凭为目标吗?能不能靠进一个自考课程?网上证书够你用吗?我不能回答你,因为每个人的正确答案都不一样。

本指南旨在帮助您为自己提供一个答案。到目前为止,您应该对每个选项的具体优势和成本(金钱和其他方面)有了透彻的了解。在你投入同样宝贵的金钱或时间之前,彻底考虑和调查每一个选择都是值得的。

你可以选择将编码 bootcamp 的成本花在相对快速、极具针对性的知识上。你可以在慢节奏、填鸭式的课程上花更多的时间和金钱,让你从一所认证的大学获得学位,并彻底了解计算机科学的基础知识。你可以遵循自己的自学课程,并接受向雇主证明你的知识的费用。或者你可以选择 Qvault 这样的平台,它提供一些计算机科学基础领域的自我驱动的证书。

无论如何,要记住的重要一点是,你可以相信雇主迫切需要合格的计算机科学员工。你所要做的就是找到最适合你的道路,知道如何最好地向雇主展示自己,让他们了解你的技能和经验。这使得编码训练营是否值得,或者计算机科学学位是否值得,这些问题的答案进入适当的环境,让你做出选择。

原载于 2021 年 3 月 29 日https://qvault . io

艾是来找你工作的吗?

原文:https://towardsdatascience.com/is-ai-coming-for-your-job-2f593ab72b55?source=collection_archive---------22-----------------------

意见

矛盾的是,用人工智能取代工人创造了对更多工人的需求

AI 正在抢走很多工作。但它也创造了新的。作者图片

自大规模工业化开始以来,自动化导致了大规模、广泛的失业。当汽车工业用机器人取代大量人类时,像 T2、底特律和 T3 这样的城市成了受害者。今天,许多受灾最严重的地方几乎看不到过去繁华和繁荣的影子。

给经济增加机器人会取代工人。芝加哥大学的一项研究发现,每 1000 名工人增加一台机器会导致就业率下降至少 0.18%。这听起来可能不多,但在美国这样大的国家,这相当于大约 50 万人失业。这相当于一个中等城市的工人没有工作。

这些工人面临着直接的危机,因为他们不得不寻找新的工作,甚至可能是全新的领域。他们的失业还会对更广泛的经济产生下游影响,因为他们在失业期间会削减支出。失业影响到每个参与经济的人。

随着第四次工业革命的全面爆发,这种恐惧再次显而易见。人工智能有潜力自动化甚至非常复杂的任务,更不用说简单和重复的任务了。只有在你考虑社会后果之前,这种节省劳动力的潜力听起来才是伟大的。没有一个城市想在破产和衰落中狼狈收场。没有人愿意失去他们的生计,尽管他们工作的某些部分可能是枯燥和重复的。

但是消息并不都是坏的。如果没有汽车工业中的机器人,像通用汽车或特斯拉这样的公司制造的创新产品甚至不会存在于我们最疯狂的梦想中。没有科技工厂里的机器人,你正在阅读这篇文章的设备也不会存在。如果没有基于人工智能的推荐算法,你可能永远不会偶然发现这篇文章。

像底特律衰落这样的故事令人心痛。但有理由相信,在人工智能推动的革命方面,历史不会重演。

采用机器人的公司雇佣更多的工人

在宏观经济层面,逻辑似乎很简单:如果人工智能让工人过时,那么采用它将导致失业率上升。乍一看,法国的一项研究证实了这种怀疑。作者发现,在一个给定的行业中,机器人增加 20%会导致该行业的就业率下降 1.6%。当然,机器人是一个比人工智能更通用的术语,但我们可以假设人工智能会导致类似的结果。

然而,当把视角从国家经济转移到个体企业时,现实是不同的。有些违反直觉的是,采用机器人的公司雇佣更多的工人。诚然,这一数据可能有点误导,因为增长更强劲的公司可以更快地购买更多机器人,这使得它们的规模更快。

然而,有几个令人信服的理由相信机器人有助于公司扩大人力资源。法国的研究表明,如果工人和机器人分担工作量,那么每个工人的附加值就会增加。

例如,假设一家公司雇佣五名工人生产价值 100 美元的产品。平均每个工人为最终产品贡献 20 美元。在经历了一些增长后,这家公司购买了一些机器人,现在每件产品只需要两名工人,因为机器人完成了剩下的工作。结果,剩下的两个工人每人为最终产品贡献了 50 美元。由于这是效率的大幅提高,该公司可能会扩大其活动并雇用更多的工人,由于效率的提高,他们现在也可以贡献 50 美元——相比之下,机器人出现前的阶段是 20 美元。这种机制增加了公司的劳动力需求,因此它可能会决定雇佣更多的工人来扩大其产品和服务的范围。

人类和 AI 走的是不同的路。作者图片

采用机器人的企业也增加了员工人数,因为当它们不是手工制作时,提供产品和服务通常会变得更便宜。当然,购买机器是一项前期投资,一些维护工作是必要的。然而,机器人不会累、生病或需要去度假。从长远来看,这种效率是值得的。成本的降低使这些公司更容易在他们的行业中获得更多的市场份额,因为他们可以以相同的价格提供更高质量的产品,或者保持相同的质量,但提供比竞争对手更低的价格。

来自加拿大、T2、丹麦、T4 和西班牙的研究也得出了相似的结论。尽管美国尚未开展此类研究,但如果公司想保持竞争力,就需要投资机器人,即使该行业的就业率因此下降。

然而,我们应该记住,每个人工智能系统都可以被看作是一个机器人,但不是每个机器人都包含人工智能。投资人工智能可能会像通用机器人一样带来更多的企业增长。幸运的是,与其他机器人不同,人工智能可能不会导致整个行业的就业率下降。

荷兰的一项研究得出了与法国、加拿大、丹麦和西班牙相似的结论,即更多的自动化——意味着更多的机器人——会导致更多的失业。尽管如此,电脑化,我们可以安全地计算人工智能,对失业没有影响。

换句话说,虽然物理机器人确实在一定程度上消除了工作岗位,但计算机和 AI 并没有同样的效果。然而,这项研究没有表明人工智能和经济增长之间的联系。但是其他的研究有。

人工智能将推动爆炸式增长

那些见证了互联网崛起的年纪足够大的读者(作者当时还太小)可能还记得它是如何引起人们对失业的类似担忧的。尽管它在仅仅 20 年前变得普遍,但它已经创造了数百万个工作岗位,并占美国国内生产总值的 10%。或许更重要的是,互联网并没有像汽车工业的自动化那样导致城市的衰落。

根据普华永道的数据,目前,63%的首席执行官认为人工智能将比互联网产生更大的影响。在他们的全球人工智能研究中,普华永道估计,到 2030 年,仅人工智能一项,全球 GDP 就将增长 26%。这比中国和印度目前的 GDP 总和还要多。

普华永道不是房间里唯一的乐观主义者。世界经济论坛估计,到 2025 年,人工智能将创造 9700 万个新工作岗位。他们还估计,同期将有大约 8500 万个工作岗位流失,但这仍然是 1200 万个工作岗位的净盈余。

也就是说,这些工作的分配可能是不平等的。在瑞典和美国,由于人工智能,到 2035 年,生产力预计将增加超过 35%。然而,对于法国和西班牙来说,增长可能不到 20%。

我们将创造和消费越来越多的人工智能。作者图片

不过,这种影响可能没有听起来那么大。世界经济论坛估计到 2030 年,只有 40%的人工智能相关的经济增长将来自生产力的提高;另外 60%将来自消费。换句话说,不到一半的增长将来自工人变得更有效率或被人工智能取代。其余的增长将来自于人们将使用人工智能产品,如社交网络或流媒体服务。关于这一点需要注意的是,我们在这里比较两个不同的时间跨度,因为一个预测是 10 年,另一个是 15 年。然而,很明显,生产率只是对整体经济增长做出贡献的等式的一部分。

尽管存在合理的担忧,但似乎人工智能的采用将导致持续的经济增长,从而刺激就业率。重要的是让这种增长对国内和国际上尽可能多的公民公平公正。在一个国家内,这意味着确保边缘化群体,如妇女、LGBTQ+个人、超重者、残疾人和有色人种获得人工智能方面的培训和教育。我们还必须努力根除目前存在的算法偏差。在国际层面上,这意味着让低收入国家能够获得计算资源,并促进不同国家之间的合作和研究。

基于人工智能的管理可能是不健康的

然而,在你对世界经济论坛的发现过于热情之前,想想经济增长并不意味着每个人都更富有。冒着听起来过于社会主义和欧洲化的风险(没关系,那是我来自的地方),让我说工人的权利经常被 AI 压榨致死。

The Verge 很清楚地报道了这一点:用 AI 来接手枯燥重复的任务是可以的。但是如果你把一个算法提升到一个中层管理人员呢?算法经理专注于 KPI,没有怜悯和人性。这台机器的唯一目标是尽可能高效地达到预期效果。结果是,它减少了休息时间,提高了目标,最终可能会裁员。

我们已经看到人工智能管理的负面结果。在 AI 经理的管理下,工人们通常会耗尽的精力。有些人甚至会受到严重的身体伤害。人工智能管理的生产率指标似乎也不太有效。例如,算法被用来衡量软件开发人员的生产力。矛盾的是,这种测量方法似乎并没有提高生产率,而是摧毁了生产率。

如果我们不是把算法作为最底层的工人,而是作为管理者来使用,我们至少应该教他们一些人类的礼仪。例如,在算法中包含一些硬边界,指定员工有资格享受多少次休息。此外,即使没有人工智能,激励员工超越团队中最好的人也是常见的做法。但是,让他们稍微高于平均水平,然后用算法实现这个目标怎么样?

这些方法在短期内可能听起来像是浪费资源,但我的直觉是它们最终会有回报。事实上,如果我们不采取一种更温和的方法来提高生产率,我们很可能会以大量没有工作、收入和未来的工人而告终,不是因为他们被解雇,而是因为他们已经超出了极限。

强调人工智能在创造新就业机会方面的能力非常重要。然而,这些必须是人道的,否则就没有意义了。

我们需要创造为工人服务的人工智能,而不是让工人为人工智能服务。作者图片

如何防止人工智能末日

我不是在提出社会平等的观点,因为我是一个守护天使。我只是一个普通的,自私的人。但我相信,作为人类,如果我们周围的人过得好,我们就会受益。当失业率下降时,这为政府节省了一大笔钱,并为未来开辟了新的机会。毕竟,在这些保住工作的底层工人中,或许有一两个人有一天会成为未来几十年的史蒂夫·乔布斯(Steve Jobs)或埃隆·马斯克(Elon Musk)。

还有另一个问题:如果像世界经济论坛所建议的那样,通过人工智能创造了 9700 万个工作岗位,而只有 8500 万个工作岗位被摧毁,那么没有人能保证这 8500 万名下岗工人会在 9700 万名幸运儿的行列中。人口增长,人们迁移,因此 9700 万个工作岗位可能终究是一种相当稀缺的资源。

为了给 8500 万下岗工人一个视角,必须对他们进行再培训和技能提升,最好是在他们丢掉原来的工作之前。人工智能可以成为解决方案的一部分,因为学习机器人可以自动完成继续教育的课程。人工智能算法也应该被创造出来,以使工人与新的机会相匹配,并为全新的工人配备必要的技能,最好是在他们离开大学之前。

人工智能创造的就业机会将超过它摧毁的就业机会。但我们需要人工智能来确保这些新工作的公平分配。

https://medium.datadriveninvestor.com/at-the-origin-of-c-were-a-school-teacher-and-a-string-of-failures-efebcb6c91db

投资于您的员工

幸运的是,政府开始明白发生了什么。例如,法国非常重视人工智能主导的未来世界。在一份来自 2019 年的报告中,France Stratégie 提议培养更多真正理解人工智能对技术、法律、经济和整个社会意味着什么的人工智能专家和工作者。

此外,France Stratégie 建议“改进计划,以保障将受到自动化风险严重影响的部门和子部门的职业道路。”换句话说,商界和政府中一些聪明的决策者需要聚在一起,在一个快速变化的环境中,一个行业一个行业地为工人制定计划。我赞成这种做法。

这需要很大的远见,没有人有水晶球。我们会犯错误。但是如果我们,作为一个社会,想要向前发展,我们需要解决对衰落的根本恐惧,对跟不上不断变化的技术的恐惧。人工智能会给许多人带来繁荣,给少数人带来厄运,但我们需要现在就行动起来,遏制这种厄运,让繁荣惠及每一个工人。

AI 到了吗?

原文:https://towardsdatascience.com/is-ai-there-yet-ef57cd306555?source=collection_archive---------32-----------------------

今天人工智能面临的问题的快速总结

照片由杰克森煨Unsplash

人非圣贤,孰能无过。

底特律的冬天很冷,但阳光灿烂。罗伯特·威廉斯决定花些时间和他的两个女儿一起处理房子的前期贷款。他的妻子和岳母在一个角落里徘徊,一边喝着热饮,一边闲聊。突然,警察不知从哪里冒了出来,让一个完美的家庭日戛然而止。罗伯特被从他哭泣的女儿们的怀里夺走,没有任何解释,冰冷的手铐现在抓住了他的手。警察立刻把他带走了!他的家人被展现在他们眼前的场景震惊得不敢相信。接下来罗伯特被警方拘留了 30 个小时。随后,他因盗窃指控被传讯,需缴纳 1000 美元的保释金。但是没有人费心去问罗伯特在所谓的盗窃发生时他是否有不在场证明!对他来说幸运的是,在抢劫发生时,他刚刚在 Instagram 上发布了一段来自另一个地点的视频,从而给他提供了确凿的数字证据。

但是哪里出了问题呢?密歇根州警方收集了所有与盗窃有关的镜头,并使用面部识别软件从 4900 万张图像的数据库中识别出潜在的嫌疑人。罗伯特·威廉斯是被算法识别出的不幸的人。司法的崩溃凸显了两个关键问题。

首先,面部识别并不完美;事实上,它只有 95%的准确率。当然,人们可能认为这个比例相当高。但是这 5%的误差会带来什么影响呢?这个小小的错误对罗伯特·威廉斯和他的家人产生了悲剧性的影响,因为他们现在已经伤痕累累。再者,如果罗伯特在抢劫时没有在 Instagram 上发布照片,他今天可能还在监狱里。有些人可能会说,这是为这些系统提供的额外保护付出的小小代价。毕竟,这只是一个小小的错误,是吗?

2009 年,中国开始部署全国性的社会信用体系。它建立了一个由超过 2 亿个公共摄像头和大量传感器组成的网络。这些数据,加上从移动设备上获取的所有信息,给了中国当局关于其公民的精确信息。该系统背后的理念是促进“值得信赖”的行为。如果一个人违反了中国法律(如不纳税、闯红灯或在火车上吸烟),这个人的社会信用评分就会降低。如果他依法办事,社会信用分就会上去。事实上,就在 2018 年,有 2400 万中国人被禁止旅行,因为他们的社会信用评分太低。

考虑到中国近 14 亿的总人口,这个问题变得更加复杂。他们的摄像系统中 5%的误差率可能会对 7000 万人造成错误分类和负面影响。因此,说真的,尽管人工智能系统在过去几十年中表现出了令人难以置信的壮举(在某些情况下甚至超过了人类的水平),但我们还没有达到那种程度,如果管理不善,它们的影响可能是灾难性的。

偏见在于旁观者的电子眼

我们应该关心的不仅仅是错误。当我们创建人工智能算法时,偏见是另一个有问题的问题。佐治亚理工学院对最先进的自动驾驶汽车系统进行的分析发现,这些汽车中使用的传感器和摄像头更有可能检测到肤色较浅的人。这自然意味着自动驾驶汽车在撞上有色人种之前不太可能停下来。这适用于所有被测试的系统,对于肤色较深的人,准确率下降了 5%。

有些人可能会说,机器不可能是种族主义者,因为它不理解种族的概念。这是真的,事实上,问题不在于我们的算法的固有性质。出现的问题反映了我们用来训练算法的基础数据。几个月前发布了一款名为 Face Depixelizer 的新工具,证明了这一点。这个程序背后的想法是拍摄一个人的像素化照片作为输入。然后,系统将使用人工智能对其进行处理,并返回清晰、准确的面部图像。当给系统输入美国前总统巴拉克·奥巴马的像素化图像时,该算法将他变成了一个白人,尽管这张像素化图像用肉眼非常容易识别。同样的算法被用于测试亚历山德里亚-奥卡西奥·科尔特斯(Alexandria-Ocasio Cortez)的像素化图像,这位美国国会女议员有着拉丁裔血统,刘玉玲是著名的亚裔美国女演员。在这两种情况下,算法都将他们的脸重建成白色。

这些算法易受用于训练的数据的影响。正如早期 IBM 程序员 George Fuechsel 曾经说过的:“垃圾进,垃圾出”。这些算法是一张白纸;如果在不平衡的数据集上训练它们,它们会自动产生错误的分类。正因为如此,数据科学家必须竭尽全力确保他们的数据集能够代表正在建模的领域。考虑到我们生活的世界已经存在偏见,这并不容易。在谷歌上快速搜索护士,可以找到 80 万名女护士和 60 万名男护士的参考资料。另一项对医生的搜索发现 200 万个男医生的链接,而 150 万个女医生的链接。这些数字代表了典型的性别陈规定型观念,即护士通常被描绘成女性,医生被描绘成男性。如果这些数据在没有首先平衡数据集的情况下被直接输入到算法中,算法将会学习偏差并将其应用于判断中(从而扭曲结果的有效性)。

2015 年,亚马逊成为这个问题的受害者。由于该公司在全球范围内招聘了数千人,他们的工程师决定创建一个人工智能招聘工具。使用几次后,很明显这个工具歧视妇女。原因如下。当工程师设计人工智能时,他们需要在一些数据上训练算法。他们突然意识到,亚马逊目前的员工完全符合该组织的企业文化,他们有适当的要求,公司对他们的表现很满意。工程师们推断,如果人工智能学会识别与已经受雇的人相似的人,它将成功地识别出有前途的候选人。因此,他们使用当前员工的简历来训练算法。然而,他们没有意识到在科技行业有 75%的劳动力是男性主导的。所以偏见是不可避免的!亚马逊的系统告诉自己,男性候选人更受欢迎,并惩罚包含“女性”一词的简历。它也偏爱那些在简历中充斥着某些带有男性含义的动词的候选人。

这不是一个孤立的案例。微软也研究过人工智能,但最终发展出了许多负面特征。这一切都是从对话理解的实验开始的。微软创建了一个名为 Tay 的 Twitter 聊天机器人,它的任务是通过随意的对话与人交流。对话的戏谑没有持续很长时间,Tay 开始对人们发表厌恶女人和种族主义的评论,并夹杂着脏话。聊天机器人开始时几乎是一片空白,在不到 15 个小时的时间里,它成功捕捉到了与之互动的人的负面情绪。这就好像你在丛林中抚养一个孩子,并期望他长大后能识字。事情不是这样的。

此外,网络世界充斥着各种不同的观点,如果不加以引导,人工智能系统很快就会误入歧途。事实上,Tay 在其短暂的生命周期中成功处理了数千条消息,每秒钟产生近 2 条消息。人们只能想象这种系统会给人们带来多大的伤害。这个事件也应该提醒我们,即使像微软这样的大公司有时也会忘记采取预防措施来保护我们免受粗糙的人工智能。

解释自己的时间

近年来出现了一个新的人工智能子领域,称为可解释人工智能(XAI),以解决这些问题。其目的是创建不隐藏其底层工作的算法,而是透明地提供完整的解释。我们已经看到了各种例子,证明人工智能算法产生的结果是有问题的。但在其他情况下,问题并不那么明显。计算机科学家创造了看起来运行良好的系统,人们盲目地相信结果,但它们并不总是正确的。

神奇的雪分类器

区分哈士奇和狼并不是一项简单的任务,但算法可以达到 90%的准确率。或者他们有吗?

华盛顿大学最近的一项实验试图创造一种能够区分狼和哈士奇图像的分类器。该系统在几张照片上进行训练,并在一组独立的图片上进行测试,这通常是机器学习中的情况。令人惊讶的是,即使哈士奇与狼非常相似,该系统也能达到 90%左右的准确率。研究人员对这样的结果欣喜若狂。然而,在运行一个能够解释为什么算法能够获得如此好的结果的解释器函数时,很明显该模型主要是基于背景做出决定的。狼的图片通常描绘了一个多雪的环境,而哈士奇的图片很少描绘。因此,研究人员无意中创造了一个伟大的雪探测器,而不是创造一个狼对哈士奇的分类器。仅从准确性等传统性能指标来看,这种错误并不明显!当然,这样的玩具实验是基于实验室的,但如果病人的生命依赖于那个人工智能,会发生什么?

缺失环节

对患者的风险等级进行分类并不是一件简单的事情,尤其是考虑到这个决定所带来的责任。20 世纪 90 年代,匹兹堡大学进行了一项预测肺炎患者并发症风险的研究。目标是找出哪些肺炎患者是低风险或高风险的。低风险患者被送回家,并开了抗生素鸡尾酒和鸡汤,而其他人则被送入医院。该系统围绕人工神经网络(ANN)架构(一种受大脑启发的模型)设计,分析了 23 个州 78 家医院的不少于 75 万名患者,死亡率为 11%。令人惊讶的是,它设法获得了大约 86%的高精度。

当该系统在实际病人身上进行测试时,医生们注意到了一个严重的错误。同时患有哮喘的肺炎患者被归类为低风险患者。医生们立刻皱起了眉头,因为分类错误太严重了。他们向程序员指出了这个问题,系统被送回了绘图板。计算机科学家对其进行了彻底的分析,然而他们在数据或现有系统中找不到任何错误。然而,当他们试图进一步探究该系统如何得出这样的结论时,他们立即面临一堵墙。系统核心的人工神经网络受到大脑内部工作方式的启发。然而,它通常被认为是一个黑匣子。这意味着我们给它一个输入,我们得到一个输出,但我们不能清楚地看到算法的内部工作。这使得寻找解释的任务变得异常复杂,在某些情况下,对于人类来说是不可能完成的。为了克服这个障碍,他们在人工神经网络架构的基础上建立了一个基于规则的系统。这样做,他们能够阅读和理解系统生成的规则。

令人惊讶的是,基于规则的系统也得出了与人工神经网络相同的结论。然而,研究人员进一步发现,根据数据,患有肺炎和哮喘的患者比其他人的恢复率更高。算法漏掉的是他们变好的原因。这绝对不是因为他们有哮喘!原因是在过去,哮喘患者被医生自动标记为高风险。正因为如此,他们立即被送入重症监护室,最终比普通病人更有效地恢复了健康。这证明了两件事;首先,人类的直觉是必不可少的,因为当面对自动化系统的结果时,医生立即标记了这个问题。其次,它应该提醒我们,相关性并不意味着因果关系。

太多的选择导致糟糕的决定。

到目前为止,我们看到的决策相对简单,但是如果事情变得无限复杂呢?自动驾驶汽车将不得不做出艰难的决定,我们需要能够理解这些决定背后的基本原理。对于肺炎病例中的患者来说幸运的是,一个人控制了那个系统,但是如果我们有像自动驾驶汽车这样的自主系统呢?想想著名的电车问题,无人驾驶汽车无法避免事故。而这样的结果,肯定会有人死!人工智能应该选择什么?

优先考虑人类而不是动物?

乘客超过行人?

以少救多?

重女轻男?

年轻人优先于老年人?

选择社会地位高的人?

奖励守法者而不是罪犯?

或者保持航向,不要干预?

在大多数情况下,没有对错。结果会有人死。事实上,我们没有这些问题的答案。但是让我们把争论放在一边,因为这不是问题的结束。有人死亡后,一个中肯的问题是,谁将对事故负责?程序员、生产汽车的公司还是车主?

车主对车辆的驾驶没有直接的发言权。他可以决定目的地,但也差不多了。所以不太可能是车主的过错。生产这种汽车的公司使用软件开发商开发的程序。它对代码本身没有发言权,而且在安装到汽车上之前,它确实通过了国家当局强加给汽车公司的严格测试。程序员可能使用最新的方法来开发正确的代码。一旦车辆开始运行,它就开始根据自己的道路经验获取信息。在某些情况下,这些汽车甚至会借鉴其他车辆的经验。当然,一旦机器上路,程序员几乎无法控制它实际知道什么。因此,我们兜了一个圈子,似乎没有人对此负责,我们也不知道。

结论

我们面临的挑战是找出推进人工智能的最佳方式,同时创造我们可以信任和理解的解决方案。正因为如此,向 XAI 转移是很自然的。当前的人工智能模型对于人们来说是不透明、不直观和复杂的,但如果我们希望人们信任人工智能系统的自主决策,用户必须理解、有信心并有效地管理它。

除了前面提到的问题,还有其他考虑因素,例如:

  • 算法和自动化变得越来越普遍。人工智能驱动的分析正在解决许多商业挑战,我们看到人类专家在传统上无可争议的领域(例如医疗诊断)取得了进展。AI 可以处理比人类操作员多得多的数据;他们速度更快,而且不会累。另一方面,我们必须小心,因为偏见和错误的决定会传播得更快。
  • 人工智能模型正变得庞大,有数百万个参数,这使得人类用户更难理解它们。一些系统正在对人类操作员进行培训,但这不足以获得人们的信任。此外,一些模型无法控制算法背后的逻辑,也没有简单的方法来纠正任何错误。
  • 随着 2018 年 5 月 25 日欧洲通用数据保护条例(GDPR)的出台,黑盒方法在商业中的使用变得更具挑战性,因为它们无法提供对其内部工作方式的解释。除了被遗忘权之外,GDPR 还引入了删除权。因此,任何人都可以向任何组织提出请求,要求删除他们的个人数据。然而,这比听起来要复杂得多。这不仅仅是从搜索结果中删除个人数据的问题。必须将其从存储该数据的知识库、故障恢复备份、其他数据中心镜像的数据中删除,并从硬盘中物理删除(而不仅仅是删除链接)。所有这些都使得删除任务过于复杂。

我们面临的挑战是找出推动这些创新的最佳方式,同时创造我们可以信任和理解的解决方案。我们还没到那一步,AI 也不应该被认为是我们盲目追随的这个神奇的神。另一方面,我们不能忽视它和它给我们带来的好处。如果我们能够设法应对前面提到的挑战,我们就能真正改善许多人的生活。

这是我想出的一本书的节选,我还在找出版商。因此,如果你喜欢这篇文章,并想与我联系,请这样做🐦*https://twitter.com/alexieidingli,🔗LinkedIn,📷Instagram或者😊* 脸书 **

**

阿列克谢·丁力教授 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他已经出版了几本同行评审的出版物,并成为马耳他的一员。由马耳他政府成立的人工智能特别工作组,旨在使马耳他成为世界上人工智能水平最高的国家之一。**

Apache Airflow 2.0 是否足以满足当前的数据工程需求?

原文:https://towardsdatascience.com/is-apache-airflow-2-0-good-enough-for-current-data-engineering-needs-6e152455775c?source=collection_archive---------6-----------------------

新版本中有什么变化:气流 2.0

照片由 Pexels 的 Alexas Fotos 拍摄

几个月前,我写了一篇文章讨论 Apache Airflow 作为 ETL 和数据科学的工作流管理平台的利与弊。由于最近的重大升级,我想更新一下气流 2.0 中的变化。为了全面了解情况,您可能想先看看之前的文章:

目录

air flow 2.0 相对于以前版本的优势
新的 UI 看起来清新而现代
调度程序不再是瓶颈
Airflow 终于有了一个成熟的 REST API
智能传感器
整个项目已经过重组
新的特性没有说服我 通过任务流抽象在任务间共享
新版本中尚未解决的气流弱点
令人困惑的调度逻辑
仍然没有对您的数据管道进行版本控制
配置过载
本地开发
结论

与以前版本相比,Airflow 2.0 的优势

新的用户界面看起来更好

安装 Airflow 2.0 后,您将能够访问比以前版本看起来更好的 UI。新用户界面的主要优势是自动刷新功能— 您不再需要不断刷新浏览器来获取工作流程的最新状态。相反,用户界面会自动刷新,您可以通过单击来停用它,如下图所示。

Airflow 2.0 的 UI——图片由作者提供

调度程序不再是瓶颈

您不再需要在触发 DAG 运行后休息一会儿来查看工作流程的进度。与以前的任何气流版本相比,这个调度程序似乎快了好几光年。根据天文学家[6]进行的性能基准测试,调度器现在比以前快了 17 倍(取决于用例)。

最大的(积极的)惊喜是调度程序在超过 100 秒没有接收到心跳后重新启动。

调度程序日志—作者提供的图像

气流终于有了一个成熟的 REST API

到目前为止,Airflow 只有一个功能有限的实验性 API。在 2.0 版本中,您现在可以利用完整的 REST API 来创建、读取、更新或删除 DagRuns、变量、连接或池。

如果本地有 Airflow 运行,可以通过以下网址访问 Swagger UI:http://localhost:8080/API/v1/UI/。它为您提供了完整的文档,以便您可以开始在 Airflow 的基础上构建额外的功能,甚至可以使用 Python 之外的编程语言。

智能传感器

传感器很棘手,因为它们不断探测状态,可能会消耗大量资源。在新版本中,Airflow 对传感器的逻辑进行了更改,使其更加节省资源和“更加智能”。对于那些希望将所有工作流放在一个地方,而不是依赖于 FaaS(如 AWS Lambda )的事件驱动用例的人来说,这个特性可能会有所帮助。

整个项目已经进行了重组

Airflow 有一个受欢迎的社区,到目前为止,它允许对操作符、传感器或钩子的库进行贡献,而无需过多考虑这些贡献模块的结构。随着时间的推移,它导致airflow.contrib变得如此之大,以至于依赖性管理,以及下一个版本的计划和测试变得具有挑战性。正如 Jarek Potiuk(气流 PMC 成员)说得好[3]:

除了厨房水槽,所有东西都被扔进了一个“阿帕奇气流”包里,不管你想不想用。

在 Airflow 2.0 中,模块已经根据可以与 Airflow 一起使用的外部系统进行了重组。这意味着,如果您想使用与 AWS 相关的操作符,而不是与 GCP 和 Kubernetes 相关的操作符,那么您只能使用 Amazon provider 子包来安装 Airflow:

pip install apache-airflow[amazon]

这种变化是显著的,因为它允许关注点的分离、特定组件的更快的发布周期,以及可以找到与特定外部系统相关的代码的更清晰的组织结构。从先前版本迁移工作流时,请确保使用正确的导入。例如,代替:

from airflow.contrib.operators.aws_athena_operator import AWSAthenaOperator

您应该使用[4]:

from airflow.providers.amazon.aws.operators.athena import AWSAthenaOperator

看起来不成熟的新功能

有些新的抽象表面上看起来很棒,但需要谨慎对待。

任务组功能

这种新的抽象允许将一组任务视为单个任务。它的动机是许多数据工程师在使用子标记时遇到的低效和错误。尽管这种任务分组在 UI 中似乎很有帮助,但是从设计的角度来看,它并没有解决许多数据工程师试图使用子标记来解决的实际问题,即关注点的分离和分离。

通过任务流抽象在任务之间共享数据

这是一个很多人都很好奇的特性,因为它承诺了数据共享功能,并且应该允许编写简单的 Python 函数而不是 Airflow 操作符。在回顾了这个特性之后,它似乎是这个版本的一个弱点,因为任务流抽象留下的问题比它回答的问题要多。

以下是这些功能(任务流和任务组)的详细概述:

新版本中尚未解决的气流的弱点

令人困惑的调度逻辑

调度逻辑没有任何变化。Airflow 仍然在调度间隔的结束时开始调度工作流,这意味着您的 DAG 不会在调度周期的时间立即启动,而只会在execution_date达到start_date + schedule_interval时启动。

作为最终用户,这对您意味着什么?这意味着,当您看到计划作业的最后一次运行“2020–12–28”是在凌晨 1 点整,如下图所示,这并不一定意味着工作流实际上是在当天凌晨 1 点整运行的,而是作业的执行日期,它是工作流计划周期的开始时间戳。在这段时间结束时触发作业的执行。在本例中,作业实际上是在一天后触发的。仅对于手动触发的作业,上次运行字段将指示作业运行的实际时间戳。

计划作业的上次运行时间=执行日期,而不是作业实际运行时间的时间戳-按作者排序的图像

如果您想更多地了解整个调度逻辑,本文提供了一个很好的解释:

仍然没有数据管道的版本控制

存储关于工作流的元数据更改有助于分析随着时间的推移发生了什么变化。使用 Airflow 2.0,您仍然无法跟踪工作流程的版本历史。如果你感兴趣的话,这里有一个关于计划如何实施的提议

配置过载

气流是为了满足许多不同人群的需求而建造的。它可以作为一种工具来协调 Kubernetes 上的容器化工作负载,使用几种不同的技术作为您选择的消息代理,它试图在一个产品中以半灵活的方式完成所有这些工作。这种方法的缺点是增加了复杂性和您需要配置的东西的数量,以便根据您的需要定制工具。作为新用户,您需要学习许多组件和广泛的 Airflow 词汇,以便以正确的方式利用该工具。

例如,您需要了解与前面提到的调度逻辑相关的所有细微差别(包括带有 catchup 的潜在陷阱)、如何编写气流代码的语法、执行器的逻辑、消息代理和芹菜队列、操作符、钩子、XComs、元数据数据库,以及如何将所有这些不同的组件放在一起并维护它们。

你可以说这适用于任何工具。但是气流只是有如此多的特定的(不直观的)词汇和成分,它可能导致一个重要的进入壁垒。除非你学会了这个工具的所有组件和词汇,否则你不可能成为一个有效的用户。这样做可能需要大量昂贵的培训,而使用具有更直观抽象的平台可以避免这些培训。事实上,令人头痛的气流管理可能是工作流编排空间目前出现新的更用户友好的解决方案的原因。

气流如何解决这个问题?如今,抽象出一些与最终用户无关的内部组件可能是有益的。举个例子:作为最终用户,你为什么要关心开始和执行日期?定义您的时间表和部署您的 DAG,并让调度平台处理其余的事情还不够吗?

如果您自己动手,为生产设置气流架构是很困难的

维护气流及其所有组件只需要管理平台和底层基础架构的全职资源。有几家供应商提供商业气流产品。财务上参与这个开源项目的公司要么提供全面管理的气流服务、咨询、培训服务,要么提供所有这些服务的组合。

  • 天文学家 —提供托管服务,在开源版本、企业支持、培训和咨询的基础上提供一些额外的功能,并有几名 PMC 气流成员作为员工为开源项目做出贡献。
  • Polidea —与天文学家类似,它也有几名 PMC 成员,但他们似乎主要专注于维护代码库和提供咨询服务。
  • 谷歌(Google)——提供全面管理的服务:GCP 上的云作曲家服务
  • Amazon —提供完全托管的服务,具有弹性(即自动扩展)工作节点容量的额外优势:Apache Airflow 的托管工作流。本文提供了更多相关信息:

地方发展

使用开源版本的 Airflow 进行本地开发很困难,因为您的本地环境通常与生产中使用的环境完全不同。当使用默认的本地安装时,您可能会遇到许多奇怪的错误。为了使这一过程不那么痛苦,来自天文学家的astro CLI 有助于本地开发[1]。他们的 CLI 允许您初始化一个本地气流环境,该环境旋转包括 Postgres 数据库在内的 Docker 容器。如果您使用他们的商业产品,您可以利用另一个 CLI 命令将 Dag 部署到生产环境中。借助码头化环境,您可以确保开发和生产环境的对等性,这有助于在将 Dag 从开发环境转移到生产环境时避免任何意外。

结论

总的来说,借助 Airflow 2.0,该项目已经达到了允许其用于生产工作负载的成熟水平。与以前的版本相比,该调度程序快了几个数量级,也更可靠。由于将不同提供者的代码分离到子包中,您还可以期待更快的发布周期。

感谢您的阅读!

参考资料&附加资源

[1] 使用 astro CLI 开始指南—天文学家 io

[2] Airflow 2.0: DAG 创作重新设计的 — Polidea

[3] 气流 2.0 提供商——Polidea

[4] 一个新的提供商包的例子—Github 上的气流

[5] Apache Airflow 2.0 在此 —文档

[6] Airflow 的调度程序基准—天文学家 io

[7] 发行说明 —显示了 Airflow 2.0 版本中添加的完整功能列表。

《变形金刚》中你真正需要的是关注吗?

原文:https://towardsdatascience.com/is-attention-what-you-really-need-in-transformers-6c161c2fca83?source=collection_archive---------20-----------------------

实践教程

探索变形金刚模型中自我注意机制的有希望的替代和改进。

近年来,基于自我关注的方法,尤其是变形金刚,出现了爆炸式增长,首先出现在自然语言处理领域,最近也出现在计算机视觉领域。

如果你不知道什么是变形金刚,或者你想了解更多关于自我关注的机制,我建议你看看我关于这个话题的第一篇文章。

与以前的架构(如自然语言处理中的 RNNs 或计算机视觉中的卷积网络)相比,变压器的成功与它们以更好的方式解决重要问题的极端效率和能力有关。在变形金刚的基础上,有而且一直都有注意力的机制,被认为是“你所需要的一切”,是这个建筑不可或缺的和真正跳动的心脏。但并非所有闪光的都是金子,事实上,自我注意力的计算带来了巨大的计算和存储成本,例如需要非常大量的视频存储器并导致很高的训练时间。

苹果和谷歌等大公司并没有忽视这一点,它们一直在努力制造不仅能够实现最先进效果,而且效率也很高的变压器。

高效变压器

最近,《变形金刚》的联合创作者之一、谷歌的研究员卢卡斯·凯泽(Lukasz Kaiser)提出了一系列改进,让变形金刚在保持自我关注机制的情况下更加高效,而他关注的第一个、可能也是最重要的一个方面就是内存效率。

基于高效变压器

变形金刚使用大量内存,因为在它们执行期间会创建和维护多个中间张量,并且随着它们的累积,它们会在缺少大量资源的情况下很快使视频内存饱和。

Google Brain 提出的解决这个问题的方法是避免将所有张量保存在内存中,而是使这个过程的每一步都是可逆的。

基于高效变压器

为此,每一步都要维护两个张量,一个来自层的应用,另一个是前一个张量的副本。这允许过程继续,而不必维护整个中间张量链,而只维护最后一步的那些。

基于高效变压器

通过这种策略,我们可以显著降低内存成本,同时仍能获得与普通变压器相同的效果。这可能是目前已知的最聪明的方法之一,以保持变压器架构完全基于传统的自我关注,但成本较低。

AFT:无注意变压器

但是在什么情况下,自我关注的计算变得如此复杂而难以管理呢?有没有消除二次复杂度的方法?我们现在真的需要注意力计算吗?这些是苹果公司的研究人员问自己的问题,也是注意力自由变形金刚的基础。

问题在于点积,点积用于组合查询、键和值,它是通过将每个输入向量都视为一个查询来完成的。意识到这一点,注意力自由变压器的目的是永远不会点产品,同时保留的好处。

与最初的转换器一样,AFT 最初创建 Q、K 和 V,作为输入与查询、键和值的矩阵的线性转换的结果。

独特之处在于,在这一点上,不是执行点积来创建关注矩阵,而是对每个目标位置执行值的加权平均。这样做的结果通过逐元素乘法与查询相结合。

来源:一个注意力不集中的变形金刚

通过这种机制,可以获得依赖于输出特征数量和所考虑序列长度的线性计算和空间复杂度。从概念上讲,这只是一种不同的使信息在序列中流动的方式,但成本要低得多。

通过使用原始变压器在文献中先前测试的许多任务上测试注意力自由变压器,可以看到,例如在图(左)所示的视觉变压器的情况下,从 AFT(右)获得的特征(在这种情况下,是 AFT-Conv 版本)即使被近似也似乎仍然是有意义的。

来源:一个注意力不集中的变压器

通过这种机制,不仅可以降低计算注意力的成本,而且在所有考虑的任务中都获得了优异的结果,这表明该解决方案能够保持点积的所有优点,而不需要计算成本。

FNet:傅立叶网络

但也有人考虑完全放弃注意力的计算,转而寻求一种与注意力同样有效但计算成本却不那么高的机制。

看起来傅立叶变换是这项任务的一个很好的候选者。傅立叶变换只不过是在一个域(如时间域)中取一个函数,并将其带入另一个域(如频率域)中。

谷歌提出的基于该机制的傅立叶网络与普通变压器完全相同,但注意力计算模块被一个处理傅立叶变换的层所取代。

具有由 T 个记号组成的 N 个输入向量,傅立叶变换首先应用于所谓的“隐藏域”,然后应用于“序列域”。所有这些都是在没有任何类型的参数的情况下完成的,这带来了巨大的优势,因为其他层中存在的参数是唯一可以训练的参数,从而减少了模型参数的数量。

因此,转换是线性的,首先按列,然后按行应用于输入。除了通过应用傅立叶变换获得的简单性之外,还有它是可逆的优点。

与 AFT 的情况完全一样,这一系列转换使得序列的各个部分能够相互影响,并且结果是包含从输入序列的各个部分导出的信息的转换表示。

显然,这似乎是一个非常有趣的方法,能够显著降低注意力计算的成本,并获得离散的结果。事实上,FNet 似乎并不比经典变压器更好,可能有其他更好的方法以更低的成本获得类似的结果,但在缺乏大量计算资源的情况下,FNet 可能是一个真正有效的选择。

未来等待我们的是什么?

现在很清楚,Transformer 是一个非常强大的架构,能够以我们从未见过的结果解决最多样化的问题,从翻译到分割到分类。然而,这些问题长期以来一直与它们对资源的过度消耗联系在一起,它们在计算机视觉领域的出现更加突出了这个问题,并促使许多研究人员寻求解决方案。在未来,我们可能会看到基于注意力的变形金刚,但经过优化后变得更轻,或者变形金刚失去了注意力机制,为更近似的技术腾出空间,或者全新的网络,类似于变形金刚,但采用不同的输入变换策略,如傅立叶变换。如果你想做好准备并了解更多,我建议你读一下我写的关于变形金刚 T2 和恐龙 T4 的文章。

有一件事是肯定的,如果目前大多数人还不可能充分利用这种架构,它很快就会为每个人所用,其巨大的潜力加上可访问性将使变形金刚比现在更加普遍和重要。

参考文献和见解

[1]《卢卡什·凯泽》。"高效变压器

[2]《双飞斋等人》。"无注意力变压器"

[3]《李中清-索普等人》。" FNet:用傅立叶变换混合令牌"

[4]《扬尼克·基尔彻》。" FNet:混合令牌与傅立叶变换(机器学习研究论文讲解)"

[5]《大卫·柯考米尼》。"关于变压器、定时器和注意事项"

[6]《大卫·柯考米尼》。在迪诺上,无标签自蒸馏

云数据科学是未来吗?

原文:https://towardsdatascience.com/is-cloud-data-science-the-future-5d3b1eb40535?source=collection_archive---------38-----------------------

所有的算法会很快运行在云中吗?

(图片由 GDJPixabay 上提供)

介绍

一年多来,我一直想在我的博客上讨论云中的机器学习和数据科学。问题是我觉得我对这个软件领域的一个组成部分——集成开发环境(ide)本身没有足够的了解。当然,作为程序员,工具很重要。每个人都有自己选择的 IDE 或文本编辑器。正如我的读者可能知道的,我更喜欢 Atom 作为基于 GUI 的文本编辑器,然后我喜欢使用 GNU Nano 作为我所有的终端文本编辑会话。

然而,随着人工智能和数据科学服务在过去几年中的激增,我们已经看到越来越多的新平台推出,这些平台希望利用云计算的便利来赚钱。有一大堆可用的工具,其中一些可以成功地创建一个完全有效的开发环境,在这个环境中,用户永远都不需要下载文件。

这方面的一些东西总是引起我的兴趣,所以我开始在 Julia 中制作我自己的笔记本服务器会话。我仍在编写该模块,实际上我对此非常兴奋——因为它将与我正在做的许多其他工作结合在一起。今天,我想参观一下基于云的数据科学 IDE 的世界,并讨论我是否认为数据科学会议可以完全转移到 web 上。

计算机

让我们绕一会儿弯路,谈谈计算机。我的意思是,计算机毕竟是数据科学工作流程中非常重要的一部分。计算机正朝着更薄的方向发展,几乎没有挡板,也不包括大量的硬件。这并不是说现在没有 15 英寸的大笔记本了,只是这种电脑远没有那么受欢迎。因此,今天可能使用的大多数计算机可能是更小的外形、学校、工作、上网本和笔记本电脑。其中一些可能运行 WebOS,比如谷歌 Chromebook。

有趣的是,虽然完全有可能在 Chrome books 或任何类似这样的轻量级笔记本电脑(或在某些情况下,手机)上进行数据科学研究,但重点当然仍然是网络浏览器。这里真正的问题是,考虑到我们现在必须使用的所有基于网络的解决方案来进行科学研究,这样的笔记本电脑对于数据科学家的日常使用是否可行。答案可能有点复杂,但是考虑到今年以及 IDE、计算机和服务器的技术水平,现在可能是开始考虑使用服务器而不是笨重的计算机的好时机。此外,如果您想了解更多关于将 Chromebook 转变为数据科学机器的信息,我实际上在大约 2 年前写了一篇文章,在这篇文章中,我使用了一台联想 C330 Chromebook,并且能够在 ARM-64 处理器上运行我所需要的一切,您可以在这里阅读:

优点和缺点

很难不谈论 CloudML,远程进行数据科学确实有很多优势。对于这些优势,我将积累不同类型的 IDE、服务器和设置可能提供的优势。对于多台计算机或多个环境的用户来说,一个显著的优势可能是远程环境将所有东西都放在一个地方。在我的例子中,我的局域网(LAN)上有大容量存储,我可以从地球上的任何地方通过路由器上的转发端口 SSH 到其中。

明确地说,这仍然符合云计算的定义,因为我是通过 SSH 在互联网上执行文件的。这涵盖了在您自己的服务器上做一名系统管理员的全部想法。您可以构建一个坚固的服务器,然后在其上启动您的笔记本会话,您甚至可以拥有一个始终运行并随时可用的笔记本服务器。老实说,对于这种事情,人们可以有很多很酷的选择和长度——可能性是无穷无尽的。

也就是说,不是所有人都知道如何管理 Linux 服务器,尽管他们可能应该知道。幸运的是,这些人在互联网上还有其他选择。一个这样的选择是 Google Colab,它可以用你的 Google 帐户立即启动一个完全远程的虚拟笔记本会话,然后将这些文件保存到 Google Drive——甚至 Github。Github 的交互性,以及诸如此类的东西将成为一台不想做下载文件之类事情的机器的巨大推动力。也就是说,Colab 可能是这种设置的最佳选择之一,但仍然存在问题。

Google Colab 有许多令人惊叹的功能,而且访问起来非常方便。然而,Google Colab 的规模是静态的,这是有问题的。在你回到无处计算的起点之前,你只能使用这么多的磁盘和内存。这给 Google Colab 带来了一个可能——我认为 Colab 的有效性很可能与项目实际涉及的数据量有关。只需加载一个数据帧,就可以达到 Colab 的极限,因此很容易理解为什么会有问题。

当然,云计算、数据科学笔记本等其他平台也在发展。然而,除了 Colab,几乎所有的都需要付费。根据我的经验,这种计算的成本通常都很高。因此,我对数据科学家是否可以只为他们的项目使用云有一些想法…

当他们的所有数据都在云中时,还会遇到一些基本问题。当然,在某些情况下,可能会丢失数据或无法访问数据。所有东西都在互联网上的坏处是,如果没有互联网,就没有所有东西。我认为这可能是人们最大的担忧。

你应该只用云吗?

这个问题仍然存在..作为一名数据科学家,完全转向云计算是个好主意吗?在大多数情况下,答案肯定是否定的。然而,我确实认为肯定有一些很好的方式,人们可以使用服务器来受益于数据科学。然而,我认为在某些情况下,只使用云是一个好主意。请考虑以下规格。

数据科学家..

  • 有权访问他们的默认网关。
  • 可以转发端口。
  • 有备用计算机或服务器。
  • 有服务器管理经验(或者了解 Linux)。)

考虑到这些条件,可能有一些服务器上的事情你不能做!也就是说,有了合适的工具和专业知识,肯定有办法在当地实现这一目标。话虽这么说,这一切还是围绕着兰的想法。我只是不认为有任何服务器可以让人们获得自由和灵活性来创建真正的数据科学应用程序、算法和发现。这在未来可能会改变,真的我们只需要等着看行业走向。

结论

数据科学令人兴奋的一点是不断有新的事情发生。拥有一个先进的数据科学设置可以提高生产力,并使一个人的工作容易得多。我计划用我的新软件包 Jockey.jl 使我的个人数据科学生活变得容易得多,我完全可以看到我自己建立一个网络服务器,供我网络中的所有计算机访问。也就是说,我不是每个数据科学家,也不是每个数据科学家都了解 Bash。关于数据科学需要特别注意的一点是,它是一套多样化的技能,因此数据科学家通常来自这些技能范围内的各行各业。我可能比其他人更擅长做这样的事情。出于这个原因,我对 Jockey 的未来感到兴奋,因为 Jockey 应该非常容易使用——一旦软件包完成,我可能会考虑只使用云服务。

如果您想了解 Jockey.jl 的更多信息,因为这个包还处于早期阶段(我仍在开发后端来处理所有的会话数据),您可以查看 Jockey.jl Github 并查看我存储在那里的代码和文件。

https://github.com/ChifiSource/Jockey.jl

谢谢你读这篇文章,它对我来说意味着整个世界。我希望在数据科学和人工智能方面有一个伟大的未来,希望这些项目有助于这样的事情。祝您有美好的一天,祝您数据科学工作愉快!

D3.js 有看起来那么难吗?从头开始创建数据探索应用程序

原文:https://towardsdatascience.com/is-d3-js-as-hard-as-it-looks-creating-a-data-exploration-app-from-scratch-c87dafb04c90?source=collection_archive---------25-----------------------

比较电影平台——TMDb 与 IMDb

Unsplash 上由 Myke Simon 拍摄的照片

JavaScript 的 D3 库以其创建交互式和/或动画可视化的灵活性和功能以及陡峭的学习曲线而闻名。

这个库是由 Mike Bostock 开发的,他也提供了大量高质量的可视化及其代码。这些例子可以在官方网站这里找到。我发现这些可视化示例是很好的资源,甚至可以用来集思广益,决定哪种类型的可视化更适合您的目的,不过,主要的力量来自所提供的代码,这些代码在理解了一些 D3 基础知识后可以很容易地进行修改。

真的有看起来那么难吗?

事实上,与其他数据可视化工具相比,初始投资成本更高,尽管我认为这个库的难度被夸大了。当我开始学习 d3(通过直接开始一个可视化项目)时,我甚至没有任何 JavaScript 方面的经验。我想说的是,在学习了一些概念(如数据连接、进入、更新、退出循环)后,事情变得非常清楚,甚至非常复杂的动画/交互式可视化也变得非常容易实现。

那这个项目是什么?

这是一个数据探索和可视化项目,是不久前作为作业完成的。这是关于创建一个数据可视化工具来比较电影和电影数据库。

我们都熟悉 IMDb 这是一个盈利组织,另一方面, TMDb 是另一个众包平台。我最初想调查他们的用户的电影口味之间是否有任何显著的差异。因此,我开发了这个应用程序。

我在下面添加了可视化的链接,你可以去发现什么类型的电影受到社会的喜爱,或者为他们幸运的制片人带来更多的利润。

http://anilgurbuz.com/visualisation/Page2.html

PS:我知道网页的设计违背了所有的启发法,但是当时唯一的担心是可视化的设计。

在下一部分中,我将尝试解释我在项目中使用的 D3 的一些方面,并希望它能对一些在网上寻找什么是进入-更新-退出循环的初学者有所帮助——我们都经历过。

如何使用 D3 创建交互式/动画可视化?

显然,这是一个非常宽泛的问题,可能有很多答案,但所有这些答案都需要首先学习 D3 如何将数据绑定到 DOM 元素。因此,我们会研究一下。

如果你问自己什么是 DOM 元素,这个链接可能有助于理解 DOM 的概念。简而言之,DOM 元素是一个存储网页中对象的容器,是的,D3 将数据分配给这些容器,因此我们可以使用该数据的任何维度对网页/容器/DOM 元素的相应部分进行更改。

D3 里如何控制数据绑定?—进入、更新、退出循环

我们通过一个 3 步的过程控制数据绑定到 DOM 元素;
进入-更新-退出循环。

  1. 在 Enter 步骤中,我们选择没有匹配 DOM 元素的数据,并创建新的 DOM 元素来分配所选数据。
  2. 在 Update 步骤中,我们选择被绑定的 DOM 元素和数据,并由于 DOM 元素的现有绑定数据的任何变化而更新所选 DOM 元素的属性。这一步要求 DOM 元素和匹配数据都存在。
  3. 退出是我们选择没有匹配数据的 DOM 元素并删除这些 DOM 元素的步骤。

进入-更新-退出循环

在这个可视化中,我们将创建 DOM 元素来渲染散点图中的圆圈,绑定数据将是关于电影的,因为图中的每个点将代表 IMDb 或 TMDb 中的一部电影。

让我们看看应用程序的一些用户动作和相应的反应,以了解数据绑定如何控制所有这些动作-反应循环,然后我们将查看代码。

在此处再添加一次链接以访问应用程序。

http://anilgurbuz.com/visualisation/Page2.html

用户使用滑块或按钮过滤数据

  1. 当用户使用 gif 中的滑块过滤数据时应用程序的反应:
  • 反应 1.1:重新缩放 x 轴,以在 x 轴上为新点集获得更合适的值范围。
  • 反应 1.2:移除(点的下落)和增加点(从顶部落入可视化)。

用户悬停点

2。当用户悬停在 gif: 中的& off 点时应用程序的反应

  • Reaction2.1:发出一个 API 请求,构造响应,并呈现由悬停点表示的电影的海报和元数据。
  • 反应 2.2:增加悬停点的不透明度。
  • 反应 2.3:当用户悬停时,回滚到可视化的初始状态。

密码

下面的代码显示了“render”函数,每次用户通过过滤数据进行更改时都会调用该函数。此代码包括散点图圆圈的整个进入-更新-退出循环。

代码中的一些变量:
d:
将要呈现的数据。它存储电影的利润、评级、投票数信息。海报图像不包括在这个加载的数据集中,因为这些图像是通过 API 请求与用户动作同时获得的。
xScale: D3 缩放对象。从技术上讲,是输入数据值到轴值的映射器。

重新缩放 x 轴

我们首先通过改变映射器的域来重新调整 x 轴(反应 1.1),以便我们的 x 轴将只包括过滤用户后保留的值。比如用户想和 Min 一起看电影。利润 6 亿美元,那么,借助代码第 5–7 行的修改,x 轴将从 6 亿美元开始。

但还有一点,我们不希望我们的轴只是消失,并重新出现一个新的值看起来平滑。因此,transition.duration(1000) part 使 DOM 元素的变化在一秒钟内发生,而不是立即发生。—在这种情况下,DOM 元素是“xAxis”。d3.select()选择的元素。

进入阶段

这个阶段从这个代码的selectAll("circle").data(d)开始,我们选择现有圆圈的所有 DOM 元素,然后给每个圆圈分配一行数据。使用enter()之后的命令,我们为没有任何绑定 DOM 元素的数据创建一个新的圆圈。例如,如果我们在图中有 100 个圆,我们改变了过滤器,使其为 150,这意味着我们的数据点比 DOM 元素多。这是在进入步骤中通过创建 50 个额外的 DOM 元素(“圆圈”)来处理的,以便与手边的数据匹配。

如上所述,enter 是我们为没有有界 DOM 元素的数据创建新 DOM 元素的步骤。append("circle")是创建这些新元素的命令,然后我们指定这些圆的属性。例如,attr("cx",d=> xScale(d.Profit))指定圆的“cx”属性,这是数据“d”的“利润”属性。xScale 将原始利润值转换为绘图中的坐标。

.on("mouseover"...可以被认为是这些圆圈的另一个属性,它描述了用户悬停时 DOM 元素的反应。我们已经提到了反应 2.1 和反应 2.2。因此,通过为“mouseover”属性定义一个函数来实现这些反应。

使用 d3.json()函数,我们发出一个 API 请求,并获取电影海报下呈现的海报图像和信息。这样,我们就不用在服务器上保存海报图像,当用户悬停在一个圆圈上时,就可以立即从 API 中获取。

showPoster 是我实现的一个函数,用来调整海报图像的大小并渲染它。这个函数也在.on("mouseout"...中使用,当用户把鼠标从圆圈中拿出来时,不渲染任何东西。另外,.on("mouseover"...)中的d3.select(this).on("mouse out"...选择用户悬停的 DOM 元素。

更新阶段

这是更新现有 DOM 元素属性的步骤。如果在 d3.select 中选择了一个 DOM 元素,这个步骤将数据的变化反映到 DOM 元素的属性中。更新步骤没有关键字,可以在输入步骤之后通过选择已经与数据绑定的现有 DOM 元素来启动。只有当数据和 DOM 元素都存在,并且数据发生变化时,这一步才会发生变化。

退出阶段

如果 DOM 元素没有附加数据,我们将在这里删除它们。当我们通过向右移动奥斯卡雕像来应用滤镜时,这种情况就会发生。我们过滤数据,所以一些 DOM 元素的数据被过滤了。因此,这些 DOM 元素在这一步被删除。

Mycircle.exit()选择过滤了数据的圆,使用attr("cy",...,我们在remove()命令前改变这些圆的位置。我们还使用了transition().duration(1000),所以这些点的 y 轴值不会立即改变,尽管这些点会在 1 秒钟内转换到新的位置。这样,我们可以使点像反应 1.2 中描述的那样下落,而不是消失。

结论

进入-更新-退出阶段只是代表了我们选择没有 DOM 的数据,数据和 DOM 都有对方,或者没有数据的 DOM 元素的步骤。通过这种方式,我们可以控制数据— DOM 元素绑定并操纵 DOM 元素的属性。这个概念在开始的时候可能有点混乱,但是一旦你明白了,它看起来就很直观了。

数据分析也适用于中小型公司吗?

原文:https://towardsdatascience.com/is-data-analytics-also-available-for-small-and-medium-sized-companies-677356b92867?source=collection_archive---------32-----------------------

关于分析如何帮助中小型企业提高绩效的一些提示。

Austin DistelUnsplash 上拍摄

MEs 在一个高度动态和竞争日益激烈的市场中运作。提高和保持盈利能力和竞争优势的压力一直存在。他们必须应对不断增长的客户需求,以维持自己的地位。

随着中小企业在发展和创新方面面临越来越多的挑战,一种业务友好的方法,特别是一种专注于数据分析(DA)的方法,可以用来帮助企业采取正确的措施,在日益复杂和混乱的世界中保持相关性和竞争力。

什么是数据分析,它如何帮助中小型企业?

数据或业务分析可以用简单概括的方式来解释:DA 将大数据技术和原理与高级统计、算法和商业智能工具相结合,从海量数据中获取商业价值,并提供对关键业务问题的客观分析。

这些只是分析可以为中小企业带来的众多好处中的一部分:

消除不必要的开支:许多企业在营销、广告、企业对企业关系和其他通常不相关的成本上花费数百万美元。然而,分析允许公司监控对成功至关重要的最具成本效益的资源。通过只关注重要的支出,他们可以降低总体成本,并使他们的产品和服务对客户更具吸引力。

Damir spanickUnsplash 上拍摄的照片

更好的服务质量:当客户投诉增加时,公司可以使用分析工具轻松识别问题。这样,他们可以快速开发新的程序来避免这种情况,并使服务更合适。

多元化和全球化:分析的另一个好处是,公司能够专注于核心业务,而不是只关注活动的小方面。这意味着,在分析数据时,他们将能够发现每个市场的需求,并适应它们。当一家小型企业发展壮大,需要关注越来越多的服务和客户时,他们可以很容易地跟踪他们的销售额和利润率,这在大型企业中是非常困难的。

更好的客户服务:客户的要求越来越高。他们希望企业能够理解他们的需求,并提供高质量的服务。分析将帮助公司了解他们的客户群,因此他们将能够根据他们的反馈改进他们的业务。

Amy Hirschi 在 Unsplash 上的照片

更高效的业务流程:分析的一个重要好处是它能够帮助企业变得更加有效。DA 广泛用于改善业务流程,如生产、客户服务和库存管理。这是通过关注过程、理解它们是如何工作的以及识别它们的弱点来实现的。

最后但并非最不重要的是,商业风险管理的实质性改善,这对中小企业来说至关重要,因为大公司在大多数情况下都有迅速从错误中恢复的财务能力,但对较小的公司来说,情况就大不相同了。

处理业务不确定性的最佳方式之一是实施基于数据分析的特定技术。例如,异常检测在生成业务洞察和维护核心运营方面发挥着至关重要的作用。对异常情况的及时检测可以帮助您防范风险并遏制其对业务的累积影响。

约翰·莫塞斯·鲍恩在 Unsplash 拍摄的照片

如果没有具备这方面知识的员工,中小企业如何从这些新方法中受益?

如上所述,分析应该是任何业务的核心,但经理们经常忙于日常运营问题,不知道如何或几乎没有时间分析做出更好决策所需的数据。

在中小型公司中实现数据分析的最有效方法之一是通过经验丰富的业务顾问的服务,他们将指导您应用定义良好的流程和以业务为导向的方法,这将保证更好的结果。业务分析顾问将通过订购和分析数据来确保持续的进展,以 360 度的视角改善您的业务。

中小企业实施分析的主要限制是,他们认为这些新方法只适用于大公司,或者他们没有足够的资源来处理这种性质的项目。

当然,这些类型的服务在过去非常昂贵,至少从中小企业的角度来看是如此,但是随着新技术(计算能力、存储容量、云服务等)的进步。)这些解决方案越来越容易获得,只需很少或不需要硬件或软件投资,而且相对于它带来的好处,价格非常合理。

Unsplash 上的 krakenimages 拍摄的照片

DA 流程是如何工作的?

数据分析通常从业务的一般描述或诊断开始,然后应用一个过程来帮助详细了解主要限制、改进选项以及如何将数据分析作为一种新的管理方式,从而在您的行业中产生显著的竞争优势。

DA 流程通常遵循以下步骤:

1.确定并描述你的业务需求。

2.评估您当前的数据

3.确定数据来源

4.寻找潜在的分析方法和模型

5.测试想法和模型

6.实施解决方案

需要注意的是,这个过程不是线性的,相反,它永久性地回到前面的阶段进行改进。

一旦这一过程完成,就有可能评估企业在哪些方面可以提高效率和资源利用率。这种方法不仅允许中小企业监测、衡量和跟踪其业务的进展,而且它们还可以试验一些变化并快速衡量其有效性。

照片由 Myriam JessierUnsplash 上拍摄

与传统方法相比,数据分析有几个关键优势。它允许在跨多个异构数据库管理大量数据时实现更高的速度、可扩展性、适应性、效率和灵活性,从而实现更主动的信息管理策略。

这种方法可以帮助中小企业发现新的有利可图的商业机会,更好地评估风险,清楚地了解客户及其购买行为,更有效地了解竞争格局,从而为中小企业带来竞争优势。

DA 可以帮助中小型企业通过提高效率和寻找新方法来节省大量资金,从而变得更高效、更有利可图,最重要的是,变得更加成功。

数据网格适合您的组织吗?

原文:https://towardsdatascience.com/is-data-mesh-right-for-your-organisation-adde60786576?source=collection_archive---------34-----------------------

如何知道您的组织是否真的准备好深入数据网格?

照片由 马里奥·高

在上一篇文章中,我们讨论了像野火一样在数据社区中传播的新企业数据架构— 数据网格架构。我们提到,它代表了数据架构中的一种范式转变,数据行业也随之转变,从优先考虑集中式、整体式数据湖和数据库的大规模数据团队转变为优先考虑数据域和数据产品的一等公民。

简而言之,它呈现了分布式领域驱动架构、自助服务平台设计和数据化产品思维的融合。为了更好地理解这一概念,我们与 Data Edge 的合作伙伴管理顾问 Daniel Tidströ进行了交谈,他至少在相当长的一段时间内一直从事数据网格的部分工作。

丹尼尔解释说,当公司快速扩张时,数据网格变得至关重要。随着数据源和数据消费者的激增,让一个中央团队来管理和掌控数据接收、数据转换以及向所有潜在利益相关方提供数据,将不可避免地导致扩展问题鉴于数据在我们的组织中日益重要,为可扩展团队和可扩展平台进行设计至关重要,”Daniel 解释道。

关于数据网格,他提到的一件重要的事情是开始讨论数据的分布,因为数据创建在所有公司中都是固有分布的。“随着数据源的数量每天都在增长,许多组织可能至少应该考虑一下他们的扩展选项。

对于想知道数据网格是否适合他们的公司,丹尼尔建议,如果你有领域驱动的开发,开始使用微服务,或者如果你进行云迁移,这是一个考虑它的好时机。

Monte Carlo 的联合创始人兼首席执行官 Barr Moses 表示,面向领域的数据架构,如数据网格,为团队提供了两个世界中最好的东西:一个集中式数据库(或分布式数据湖),其中的领域(或业务领域)负责处理他们自己的管道。这样,数据网格通过将数据架构分解成更小的、面向领域的组件,使得数据架构更容易扩展。

来自派克斯派克斯的照片

数据网格对所有类型的组织都有意义吗?

在采访中,Scling 的创始人 Lars Albertsson 将数据网格描述为扩展大型数据组织的一种方式,在大型数据组织中,由于在数据平台中工作的团队数量众多,数据管理和治理变得非常具有挑战性。

“通过将数据管理和治理联合到拥有数据源和数据管道的团队,数据网格可以让公司进一步扩展,”Lars 解释道。

采用大数据和数据运营的公司在多年的时间里经历了围绕数据的组织结构的几个阶段。在早期阶段,有一个团队或几个紧密协作的团队使用单个数据平台,其中的核心组件通常是与批处理管道相结合的数据湖,潜在地补充了流处理能力。

大多数公司要么处于这些早期阶段,要么还没有建立起他们的第一个数据平台。越来越多的数据成熟公司已经成功地将数据创新扩展到先锋团队之外,并将数据处理能力大众化。为了促进数据民主化并使治理易于管理,数据平台技术和开发流程保持同质。Lars 补充说,通常会有小的变化,但是如果熵没有得到控制,过度的摩擦将会阻止数据民主化。

照片由西格蒙德Unsplash 上拍摄

集中式数据平台可以扩展到大型组织。对于其文化难以扩展集中式服务的公司来说,集中式数据治理可能被视为一个瓶颈。在这种情况下,数据网格可以通过分配治理责任来进一步扩展。在实践中,数据网格化身是一个数据平台和湖,它被分成多个池和多个处理环境,由不同的团队控制和操作。Lars 解释说,数据网格的大小取决于公司协调中央数据平台的能力。

最后,Lars 指出,数据网格并不是扩展到大量团队的唯一选择;有足够能力协调数据管理的公司可以保持一个集中的数据平台,避免分散化的开销。

阅读 Lars Albertsson 的全部采访内容

然而,如何知道您的组织是否真的准备好深入数据网格?为了帮助公司做出决定,Barr Moses 和她的团队以调查的形式为公司创建了计算,以确定你的组织投资数据网格是否有意义。通过回答有关他们的数据源、数据团队、数据域、数据工程瓶颈、数据治理和数据可观察性的问题,他们会得到一个分数,帮助他们决定是否应该采用数据网格。您可以在蒙特卡洛首席执行官 Barr Moses 和蒙特卡洛首席技术官 Lior Gavish 撰写的数据网格实施指南中找到计算方法。

照片由马太·亨利

数据网格和数据操作的未来展望

Data Mesh 和 DataOps 都将在未来十年颠覆数据和分析行业。但是他们会进步并改变组织吗?

关于上述内容,Lars 表示,与传统公司相比,完全采用 DataOps 的组织在处理数据方面的效率要高出 10-100 倍。尽管这些特征是基于对成熟度范围内许多公司的观察而做出的主观估计,并且没有针对数据运营的科学测量,但 Lars 表示,它们与不同 DevOps 成熟度水平的公司的科学测量运营指标相匹配,如 DevOps 报告的状态所示。数据运营在新想法的交付时间和出现故障时的恢复时间方面似乎具有类似的效果。

"这种效率差距如此之大,以至于具有破坏性."DataOps 实际上是从机器学习技术中获得可持续价值的一个要求。构建和运行机器学习应用程序,保持它们的健康,并进行迭代以不断改进它们是复杂和昂贵的。Lars 说,没有实现高水平数据成熟度的公司可能会碰上一两次运气,但无法以可持续和可重复的方式提供人工智能创新。

与此相反,Lars 表示,数据网格不是一个颠覆性的概念,但它是数据非常成熟的大公司进一步扩展的一种方式。“这些公司已经从数据中获得了颠覆性的价值,并完全采用了机器学习技术。”

拉尔斯认为令人担忧的是,围绕数据网格的大部分讨论是在尚未达到这一成熟度水平的公司之间进行的。

“过早采用数据网格可能是有害的;如果您尚未在数据平台中建立强大、同质的约定和流程,那么分散化将会引入异构性,从而减缓创新并阻止有效的数据民主化。”

Lars 认为,对于大多数组织来说,采用数据网格实际上可能是一种倒退,并重新引入大数据时代之前的数据孤岛。"对数据网格的描述倾向于强调拥有数据的团队有责任将干净、高质量的数据作为数据产品发布,这种模式也被称为数据中心。"

他说,将数据质量改进的责任转移给拥有领域专业知识的团队通常是一个好主意,也是迈向数据成熟的一个进化步骤,但基础原始数据也必须可用。

照片由 Anyrgb

为了澄清,Lars 举了无效金融交易的例子,对于财务报告的情况来说,可能需要清除这些交易,但它们可能是欺诈检测信号的金矿。“将原始数据隐藏在筒仓中是数据中心的一个缺点,也是采用数据网格时的一个重大风险,除非公司首先在一个集中式平台中建立强大的数据民主实践。因此,我担心围绕数据网格的讨论将是有害的,并诱使数据不太成熟的公司建立数据孤岛。”

与此相反,DataOps 没有这种风险。“如果您的公司能够让拥有不同技能的人很好地合作,那么只会带来好处,并会加速您的数据成熟之旅。”

您有过实施数据网格的经验吗?请在下面的评论中分享你的想法。

原载于 2021 年 1 月 28 日 Hyperight.comhttps://hyperight.com/is-data-mesh-right-for-your-organisation/

数据科学是科学吗?

原文:https://towardsdatascience.com/is-data-science-a-science-a43cfbd7b227?source=collection_archive---------16-----------------------

主张数据科学领域确实应该被视为基础科学的论点

罗马法师在 Unsplash 上拍摄的照片

什么是科学?

从本质上来说,所有基础科学都是关于以实验的形式做出预测:精确可量化可证伪 预测。正如理查德·p·费曼所说:

科学的基本原则,几乎是这样定义的:任何想法有效性的唯一检验就是实验

那么,如果科学是关于预测的,那么它与占星家的预测有什么不同呢?核心区别在于各自做出的预测种类。例如,大多数星象会给你大致的预测。这些星座通常会说这样的话,“你今天会有美好的一天。”另一方面,科学预测是精确的定量的预测;他们没有说你会有美好的一天,而是说你会在下午 3:07 准时走出家门,然后被流星击中!

诚然,大多数预测并不那么可怕,而且通常在本质上更加平淡无奇。但是预测本身,我们也可以称之为实验,是基础科学的核心。我们可以认为基础科学关注宇宙最基本的方面,物质和能量。对基础科学的考察揭示了这种基础科学与计算之间的密切关系。

事实上,我们可以将计算视为将世界的一种表示(即我们的输入)转换为世界的另一种表示(即我们的输出)的过程,如这里的所示。例如,输入可能是早上 6 点校园内分布的每个传感器的温度列表,输出可能是所有传感器温度值的平均值。将输入转换为输出的过程或方法是平均值本身的计算。因此,我们可以说计算所有传感器在早上 6 点的平均温度的问题是一个可计算的问题

碰巧的是,基础科学的一个重要组成部分处理宇宙中那些可计算的问题。正如 David Deutsch 在[Zenil 2012]中所说,“物理定律只适用于可计算的函数。”这意味着,在非常现实的意义上,所有的物理定律都属于这组可计算函数,即使可计算函数本身只是所有可能的数学函数的一个很小的子集!

那么这和数据科学有什么关系呢?

Boitumelo PhetlaUnsplash 上拍摄的照片

在我们讨论数据科学是否是一门科学这个似乎没有明确答案的问题之前,让我们后退一步,看看证明的概念。这是一个经常被滥用的词,因为有许多不同种类的证明:例如,有科学证明、法律证明和数学证明。

在数学中,证明是一种推理论证,表明一个陈述在公理、定义、定理和假设的支持下是正确的。数学家通常使用演绎推理来证明前提(也称为陈述)为真。直接证明是表明给定的陈述总是正确的证明,证明通常用符号语言写成。在间接证明中,数学家通常使用矛盾证明,他们假设相反的陈述是正确的,并最终得出一个矛盾,表明假设是错误的。

在科学领域,我们无法证明任何假设是正确的,因为这需要无数次的观察,所以我们所能希望做的最好的事情就是使用归纳推理作为我们归纳的基础,并认为它暂时是正确的。正如李·洛文杰(Lee Loevinger)在谈到卡尔·波普尔(Karl Popper)时所指出的那样,“在这种被广泛接受的观点中,假设可以被证伪或推翻,但不能被证实或证明。”一旦广泛且一致地验证,并且我们认为它被充分证实,我们就称它为理论

在法律上,法律证明是运用证据确立一个事实的过程。在科学上,我们可以称之为对某个理论的验证,因为这通常也是以论证的形式出现,你提出一系列前提来支持某个结论。与法律中的证明类似,科学中的证明通常仅限于使用数据来证明事实的有效性。D.H. Kaye 在[Kaye 1991]中详细讨论了这一点,表明使用定量观察陈述提供了证明事实的证据,或者如我们在科学中所说,显示事实的有效性。因此,在某种意义上,我们可以说,法律论证使用证据来证明理论的有效性,而科学使用数据来证伪理论。

例如,继[Kaye 1991]之后,从指向蟹状星云的射电望远镜中收集各种频率的辐射强度和偏振的可量化的数据是显示(在法律上,证明)蟹状星云方向的某些东西是射电源的证据,即事实。这些事实可以从观察陈述和证据中推断出来。因此,事实是基于一些可重复的观察或测量,这些观察或测量通常被认为在相同的情况下以相同的值或相同的方式重复出现。

然后,这些事实被用于归纳推理被研究系统的假设模型。由该模型做出的预测被进一步验证,并且当足够的预测被独立验证时,该假设或假设集被认为是充分有效的,被称为理论

如果它看起来像科学,听起来也像科学…

照片由 Kai Alyssa BossomUnsplash 拍摄

这个过程,这个科学方法,正是我们在数据科学框架内利用我们的机器学习模型,如假设测试或决策树,并使用数据来迭代测试和改进我们的模型时所采用的方法。根据费曼的公式,我可能会进一步争辩说,只要你使用系统模型来做出预测,然后用数据测试这些预测,并使用这些结果验证或改进你的模型迭代,你就在 科学

将这些科学模型应用于具体问题,而无需反复改变或进一步开发这些模型,这就产生了工程技术原则。因此,我可能倾向于将数据分析归类为工程学科,将探索性数据分析归类为技术应用。

阅读更多关于数据科学与数据分析的内容。我的新书中的 10 本,也可以在 ResearchGate 上公开查看。

[1] H. Zenil,一个可计算的宇宙:理解和探索作为计算的自然。美国新泽西州 River Edge:世界科学出版公司,2012 年

[2]归纳至少在某种程度上像理查德·费曼和卡尔·波普尔这样的思想家会这样认为,费曼在他关于科学的钥匙的论述中以及波普尔在他的猜想和批判的表述中也是如此。

[3] D. H. Kaye,法律和科学中的证明,《法学杂志》,第 32 卷,第 313 页,1991 年

数据科学 10 年后会死吗?

原文:https://towardsdatascience.com/is-data-science-dead-in-10-years-3cde3963552?source=collection_archive---------0-----------------------

真实困境还是危言耸听的话语?

数据科学正在消亡吗?数据科学工作是否过饱和?现在进入数据科学还来得及吗?

最近,这些是我在 YouTube,Twitter,LinkedIn,甚至 Instagram 上被问得最多的问题。

这些问题似乎源于三个主要的怀疑来源:

  1. 他们认为“数据科学的趋势”已经结束,社会正在走向下一个最重要的事情
  2. 他们听说许多数据科学任务可能会自动化,因此他们认为自动化将取代对数据科学技能的需求
  3. 他们认为数据科学工作将会过饱和

在这篇文章中,我评估这些说法是否属实。我还尽力阐明这对数据科学家和求职者意味着什么。

如果你喜欢视频格式,看这里:https://www.youtube.com/watch?v=2qVWurPFwfc

风暴探索者Unsplash 上的照片

数据科学是否在走下坡路?

在给出我个人对此的想法之前,我认为看一下数据是很重要的。

让我们看看谷歌趋势,看看数据科学是否仍然是一个相关的话题。

蓝色代表对数据科学的兴趣,而红色代表对机器学习的兴趣

从上面的图表可以看出,在过去的 5 年里,人们对该领域的兴趣一直很稳定。我们可以看到,机器学习也遵循了类似的趋势。

有趣的是,这是一件有利于数据科学在可预见的未来存在的好事。没有急剧上升或下降。这可能意味着数据科学不会在不久的将来突然消失。如果说有什么不同的话,那就是随着时间的推移会慢慢下降,目前还没有任何证据表明这一点。

黄色代表对人工智能的兴趣,而蓝色和红色仍然分别代表对数据科学和机器学习的兴趣

当我将人工智能加入其中时,可以在上图中看到一个非常清晰的上升趋势。有趣的是,这可能是一件好事,也可能是一件坏事。好消息是,大多数数据科学家都在从事现有的人工智能项目。如果情况继续如此,这对数据科学家来说是个好兆头。另一方面,如果人工智能需要更多的专业化,那么数据科学家是否也同样需要?我一会儿会更深入地讨论这个问题。

在对这一趋势进行了简单的分析后,我会将此作为数据科学继续存在的一个尝试点。我个人认为用数据做决策不是趋势。对我来说,这是一种常识性的做法。不管你叫它什么(即数据科学、数据分析等。),我不认为它会很快消失。

数据科学会自动化吗?

AutoML、无代码/低代码工具和大数据平台在过去几年变得越来越流行。许多人认为,这些工具的进步将取代数据科学家目前所做的许多工作。

这种说法有根据吗?

我们能做的最好的事情是看看其他类似的领域,看看技术是否已经破坏了它们。我经常回去学习的一门课程是会计学。已经有技术可以取代这个领域中几乎所有的工作。然而,对会计师和审计师的需求仍在增长。

我以前用 TurboTax 记账。这是一个伟大的自助产品,价格合理。尽管我可以自己处理税务,但还是有很多我不明白的地方。我目前和一名会计师一起工作,因为他们对我的免税、信贷和国税局有专门的了解。即使我自己有工具来做这件事,仍然需要一个专家来帮忙。

我以同样的方式看待数据科学的角色。即使工具可以帮助任何人进行分析,问题还是会出现。他们会对解释结果感到舒服吗?他们能够理解模型的局限性或者他们得到的奇怪结果吗?

另一个案例研究是网站开发者。理论上,有图形用户界面可以让你自己建立一个看起来很不错的网站,但是网站开发者仍然很受欢迎。即使使用最好的图形 web 开发工具,对网站进行独特的定制仍然很困难。当公司的网站和产品由他们自己的堆栈编码或完成时,他们对网站和产品的控制明显更多。

在可预见的未来,自动化非常适合解决大规模问题,但他们很难找到非常具体的解决方案和独特的定制。对于那些在车库里为自己的企业创建网站的人来说,这很棒,但是对于一家财富 500 强公司来说,几乎所有的自动化工具都是有限的。

不管是好是坏,数据科学在很大程度上是关于边缘案例和独特分析的。虽然 AutoML 对于获得基本模型来说可能很棒,但数据中的细微差别仍然需要具有真正数据科学经验的人的眼光。

会计和网络开发都比数据科学存在得更久。科技也已经存在很长时间了。尽管有了新工具,这些领域仍然欣欣向荣,我希望数据科学也是如此。

事实上,新工具可以让数据科学工作更有价值。允许我们更容易地向利益相关者解释见解的工具将是天赐之物。虽然我不认为新技术会减少对数据科学家的需求,但我确实认为数据科学家的角色可能会发生变化。我认为未来的数据科学家将会花更多的时间做三件事,而不是投入大量的时间训练模型(AutoML 在这方面做得很好):

  1. 专注于探索性分析(我认为 AutoML 可以努力完成的任务)
  2. 解释模型如何为业务创造价值(本质上在业务中扮演一个更加面向咨询的角色)
  3. 实现这些模型(类似于机器学习工程师所做的事情)

在可预见的未来会有数据科学的工作吗?

再来看一些数据。我想几乎每个人都认为数据科学应该成为几乎每个公司的一部分。这是在商业中发现价值的一种清晰的方式。

然而,根据 MicroStrategy (2020),只有 57%的企业组织使用数据和分析来推动战略和变革。这告诉我,在数据科学的采用方面还有很长的路要走。

许多人看着谷歌、亚马逊和其他大型科技公司,认为所有的数据科学都必须处于前沿。也许这些公司会在未来几年内放缓招聘数据科学家的步伐,但随着他们的不断成熟,还有成千上万的其他公司迫切需要数据科学。对某些人来说,这个数据成熟过程可能需要几年,甚至几十年。这再次向我表明,对数据科学工作的需求将持续相当长一段时间。

MicroStrategy (2020)还发现,95%的雇主表示数据科学和分析技能很难找到。对于求职者来说,这真是一个好消息。如果这么多公司认为你的技能稀缺,那么需求可能很大。

此外,根据美国劳工统计局(2021 年)的数据,数据科学和计算机信息研究领域预计从 2020 年到 2030 年将增长 22%,是平均专业增长率的三倍。

一个更有趣的数字是,根据 DICE 的 2020 年技术工作报告,数据工程职位正以每年 50%的更高速度增长。对我来说,这对数据科学的未来来说是一件不可思议的事情。数据工程师使数据科学家能够尽最大努力完成工作。如果公司在数据科学家的上游雇佣许多角色,他们可能会准备在未来大量投资数据科学。

我认为,这些数据表明,对数据科学工作的需求正在明显增长。供给端呢?有多少人希望进入数据科学就业市场?

说明数据科学工作兴趣趋势的折线图

虽然我对此没有一个完美的估计,但我们可以回到谷歌趋势数据来探索数据科学工作是否越来越有兴趣。从上面的模式来看,在过去的 5 年里,寻找数据科学工作的人似乎一直没有什么变化。

我预计这里没有显示的需求有所增加,但看起来数据科学申请人的供应并不像许多人认为的那样多。

如果需求明显增加,而希望进入该行业的人数没有相应增加,那么在未来 10 年,数据科学领域的机会可能会变得更容易获得。

结论

根据我的分析,我认为很明显(至少对我来说),数据科学将会存在很长一段时间。我不禁要问:场场没落的情绪从何而来?

我的期望是,这很大程度上是由于缺乏对数据科学领域本身的定义。公司仍在努力定义这个角色,以及它与数据分析师、数据工程师或机器学习工程师的区别。我认为人们被这个术语弄糊涂了,忘记了所有这些职位仍然在数据科学的大伞下工作。

我希望这篇文章能帮助你以不同的方式思考数据科学的未来。我鼓励你对这个话题做自己的研究,做适合你职业生涯的事情。很明显,我热爱这个领域,我很高兴看到它继续发展!

在做这个研究的时候,我真的学到了很多,我很高兴能和你分享!如果你想看到更多这样的内容,请随时关注我的 Medium 或者注册我的简讯!此外,考虑通过注册会员来支持我和成千上万的其他作家。

感谢您的阅读,祝您在数据科学之旅中好运!

参考文献:

  1. 微观战略。(2020).2020 年全球企业分析状况https://www . microstrategy . com/en/resources/research-and-reports/the-2020-global-state-of-enterprise-analytics
  2. 美国劳工统计局。(2021).计算机和信息研究科学家。https://www . bls . gov/ooh/computer-and-information-technology/computer-and-information-research-scientists . htm
  3. 骰子。(2020). Dice Tech 工作报告:增长最快的中心、角色和技能。http://marketing . Dice . com/pdf/2020/Dice _ 2020 _ Tech _ Job _ report . pdf
  4. 塔克。M. (2018)。数据科学家之死。数据科学中心。https://www . datasciencecentral . com/profiles/blogs/the-death-of-the-data-scientist 科学家
  5. 安东尼 J. (2020)。 70 相关分析统计:2021/2022 市场份额分析&数据。金融在线。https://financesonline.com/relevant-analytics-statistics/
  6. 梁家杰(2021)。2021 年该不该成为数据工程师?走向数据科学。https://towards data science . com/should-you-been-2021-4 db 57 b 6 CCE 35

数据科学实际有用吗?

原文:https://towardsdatascience.com/is-data-science-practically-useful-1effdce39bf1?source=collection_archive---------27-----------------------

我在日常生活中使用数据科学的 3 种方式

图片由 pasja1000 来自 Pixabay

总的来说,数据科学名声不好。

大多数人认为 it 是一个只对拥有大量数据的大企业实用的职业。在我为一些小公司做顾问的早期,他们经常解释数据科学并不是他们所需要的。他们只是没有足够的规模来证明昂贵且过度设计的数据科学解决方案的合理性。所以,我坚持做小规模的分析。

他们没有错。我的意思是,数据科学家很昂贵,模型需要时间来建立和训练,数据需要被标记。此外,为了在面对大量数据变化时保持准确,模型需要尽可能多地暴露在这些变化中。换句话说,你需要大量的数据。

当你试图考虑数据科学对个人的实用性时,这个问题只会加剧。个人没有很多标记数据,他们不知道他们在某些任务上花了多少时间,日常任务需要更多的如果-那么思考,而不是可能性和概率。

但事情是这样的。

我要和你直说了。

这一直困扰着我。我一直很欣赏那些能用自己的技能做实事的人。我是《孤独的 T4》和《裸体与恐惧》等节目的狂热观众。生存技能是实用的。生存技能很酷。

数据科学不是生存技能。我不能用数据科学来放火。数据科学并不能保护我免受大型饥饿动物的伤害。我知道这个。

尽管如此,困扰我仍然存在。但不会太久。

在某个时候,不管是出于需要还是好奇,还是纯粹的固执,我终于不再陷入一天的惰性,真正把这个问题抛在脑后。

我的日常生活需要一次数据科学的碰撞。

在这里,我描述了我在日常生活中应用数据科学技能时收集到的三个实际用途。

数据科学就像数据科学一样

尽管从事该行业多年,但我花了一些时间来摆脱日常生活中的“如果-那么”思维模式,并开始分析数据科学如何对我有用(不仅仅是我帮助应用它的公司)。

这一切都始于我一天中的一次暂停,以评估占据我大部分时间的任务。

解决家庭纠纷

我对实用数据科学的探索始于花大量时间与家人和脸书的朋友讨论政治。我发现自己在寻找比较极右和极左政治的数据,以指出这两者根本不一样。

但我的轶事和难以找到的研究文章似乎只被当作耳边风。所以,为了节省我自己的时间,减少挫折,用数据武装自己,我把时间花在了数据科学上。

我建立了一个生态系统,从极右和极左组织的时事通讯中收集数据。我写了一个网络抓取脚本,使用“右翼[左翼]媒体的当前趋势”这样的短语抓取前 50 个搜索链接,从这些网站中提取文本,并添加一些高级元数据(例如,它是. com 还是. org 网站?).

然后,我在一些主题分析、实体提取和情感分析上进行分层。最后一步,把所有东西打包,制作一些直观的图表,展示两种极端意识形态之间的差异。

那个图茨阿姨是什么?你认为极右翼使用不那么极端的语言?哇,这里有一张图表显示右翼分子比左翼分子更经常使用“继续战争”这个短语。问题解决了,时间恢复了。

这个解决方案现在做两件事:1.它给了我一个快速的、由数据驱动的政治脉搏,我可以与我喜欢争论的社交圈分享。这有助于进一步分化我和我的家庭😊

你知道他们说什么。节省下来的时间是值得花的钱。继续下一个!

给学生作业评分

另一个占用我大量时间的领域是教学。我已经当了多年的助教。对我来说,不幸的是,有时我的教学负担成了我时间的倍增器,严重影响了我完成其他事情的能力。

必须做些什么来使我的教学时间更有效率。对我来说很糟糕?批改试卷。即使我已经建立了一个注释字典来处理我在过去的论文中看到的 90%的问题,我在每篇论文上花费了 5-15 分钟。

尽管我有组织好的评论字典,我仍然发现花时间去关注正确的评论。为了解决这个问题,我需要一种方法来根据每篇论文的内容向自己推荐评论。

我首先创建了一个文件夹,里面放有我为一个特定作业评分的所有过去的论文。接下来,我从每篇论文中提取文本、评论和评分。我在段落层次上组织了所有的信息,用论文、论文摘录的段落、评论和分数创建了一个简单的数据框架。

评论和分数都被用作我建立模型的目标。该段落表示将用于预测评论或分数的特征工程的来源。

为了让事情变得更加简单,我使用 spaCy 的文档分类管道来训练一个模型,该模型将推荐给定段落的评论。我使用了一个简单的回归模型来预测从论文中提取的关键词作为特征的得分。

最终的解决方案将消耗新的论文,分解段落(超过特定字符长度的任何段落),并为该段落提供具有置信度得分的推荐评论。我的模型还根据对所有段落的整体观察预测了论文的分数。

有了这两个工具,我把每篇论文的评分时间减少到了不到 5 分钟。我仍然手动审阅每篇论文,但我的模型提供了快速获取每段所需的最可能的反馈。

提出创意内容

前两个例子属于智能自动化的范畴。采取一些重复的,但不容易描述为一系列如果-那么规则,并开发统计模型来帮助自动化这些任务,而不必编写一百万个如果-那么语句。

最后一个例子更多的是创造性的灵感,而不是智能自动化,尽管它最终帮助我节省了时间。

几年前,我和儿子开了一家 t 恤公司。他真的很擅长画画,我真的很擅长把他的画廉价地转换成数字图像。一旦转换,他可以着色,增强,并进一步完善他的艺术内容。

起初,我们很兴奋,创意源源不断。t 恤满天飞,机器人被画了出来(他对机器人有特殊的定位),能量上升了。但是,在家里所有的爸爸和奶奶都买了他们的限量版之后,销售额急剧下降。新鲜感已经消失,我们遭遇了一些重大的创作障碍。

“我:儿子,我们的 t 恤产量正在下滑。你必须回去画画。业务全靠你了。你未来的命运悬而未决。

儿子:爸爸,别这么戏剧化。还有,我也不知道还能画什么。我已经没有新机器人的灵感了。"

就在那时,我发现了 GANs,或者更正式地称为的生成性对抗网络。GAN 是两个神经网络,一个从随机输入生成输出,另一个试图将来自生成模型的输出(以及一堆其他训练数据)分类为真实的或生成的。这些网络相互对抗,因此生成模型试图学习如何生成输出,以欺骗分类器将其标记为真实。

随着我对 GAN 的了解和对它们的一些实现的启发,比如来自 OpenAI 的 DALL-E ,我决定尝试构建一个 GAN,它可以绘制像我儿子一样的机器人。

好吧,所以我不想说我如何在几分钟内成功地建立了一个 GAN 来像我儿子一样绘制,从而使最后一个解决方案失败。恰恰相反,事实上,在我写这篇文章的时候,我还在努力。

是啊,甘很难训练。它们需要很长的时间来训练,对调谐参数非常敏感,并且需要很长的时间来训练…等等,我已经说过了吗?…作为强调。

冒着让你失望的风险,这一个将不得不继续工作。但是潜力将是巨大的…相信我这一点😉

在我看来,我的 GAN 很快就能生成新奇的图像,我们可以把这些图像印在衬衫上,大大提高我们的产量。此外,这些输出还可以用来进一步激励我的儿子,并在他感到缺乏灵感时充当创造性的拐杖。

随着 OpenAI 最新的 GPT-3 模型可以通过一些简单的提示生成新颖的内容,内容作者甚至开始玩弄这些生成性应用

有争议,但如果负责任地使用,这些工具可能是任何创意工具包的有用补充。

现在,我把我的生成模型的最新输出留给你。经过几天的训练,我的模特可以画一条线。我保证,这是一条线😊

作者图片

闭幕词

希望你自己的实用性——汁液现在正常流动。数据科学是有用的,有很多工具我还没有提到,它们可以用来帮助你解决很多其他的实际问题。

我希望你找到它们,用它们做实验,也许你会发现自己获得了一些价值。至少,你会在这个过程中学到一些东西。

比如参与学习更多关于数据科学、职业发展或糟糕的商业决策的知识?加入我

2021 年数据科学还是一个上升的职业吗

原文:https://towardsdatascience.com/is-data-science-still-a-rising-career-in-2021-722281f7074c?source=collection_archive---------2-----------------------

检查数据科学行业的需求、供应和增长,看看它在 2021 年是否仍然是一个上升的职业

照片来自 Unsplash,作者是绍洛·莫哈纳

根据 Glassdoor 的年度排名,2020 年是自 2016 年以来的第一年,数据科学家不是美国的头号工作。这个头衔属于前端工程师,然后是 Java 开发人员,最后是数据科学家。

2020 年美国最佳工作,通过玻璃门

现在获得第三名一点也不坏,事实上你还在领奖台上。但数据科学家这个闪亮的头衔终于要掉下来了,还是只是成为了 2020 年的又一个受害者?

为了确定这一点,我们来看看影响职位排名的 3 个经济因素:

  • 需求
  • 供应
  • 成长

如果数据科学在 2021 年仍然是一个上升的职业,检查这些因素将会给我们答案。

需求

如果你回到几年前,2010 年代初最耀眼的头衔是程序员和网页设计师。当时两人的工资都很高,但随着供给赶上需求,工资一直处于平稳状态。

对于数据科学家来说还不是这样,因为需求仍然很高。

数据科学家在工作排名中名列前三是有原因的,因为他们的需求绝对是荒谬的,而且看不到放缓的迹象。

这种需求从何而来?

数据驱动的决策。这是这个问题的简单答案。要想在 21 世纪成为一家成功的公司,你必须利用数据。

以前,许多人通过使用 excel 来分析数据,但现在任何人都可以访问和使用数据处理工具,如:

  • 谷歌分析——基于云的数字营销服务
  • Tableau,Power Bi —用于商业智能的数据可视化工具
  • Python,R——用于用几行代码执行复杂分析的编程语言

全世界最大的公司都是由数据科学推动的企业。看看谷歌、亚马逊和脸书。每个公司都使用数据科学来创建算法,以提高客户满意度并实现利润最大化。

  • 谷歌——对网页进行排名,以确保顶部链接能够回答任何问题。
  • 亚马逊——根据消费者过去的行为和兴趣推荐产品。
  • 脸书——有针对性的广告(他们知道你喜欢的运动、偏好的价格区间、食物等)增加了市场成功。

最后,需求仍然很高的主要原因是,如果你的竞争对手依赖于数据驱动的决策,而你没有,他们将超过你,偷走你的市场份额。

因此,公司必须适应并采用数据科学工具和技术,否则他们就会被挤出市场。

意思是… 数据科学家在 2021 年是必须的

供应

数据科学家的供应,这是因为即使在 2021 年,数据科学领域仍然相对较新。

你看,20 年前,由于互联网连接速度慢,计算能力低的原始编程语言,学习数据科学是不可能的。然而,随着时间的推移,计算机的能力开始呈指数增长,数据科学成为可能。

这种指数式的增长和对该领域的兴趣是无法预测的,传统教育无法满足那些想要学习这一不断增长的领域的人的需求。

很少有项目是为培养有抱负的数据科学家而创建的。研究表明,进入这一领域的人通常是从商业、心理学和生命科学等其他领域转行过来的。

大多数转型者通过阅读书籍和参加在线课程的自我准备来学习技能…

没有通过传统的教育体系

来自 Unsplash 的照片由 Changbok Ko

就业率统计

那些进入数据科学领域的人有一个优势,那就是开始一条职业道路,在这条道路上,空缺的职位比合格的候选人更多。

事实上,数据科学工作的空缺时间比所有其他工作的平均时间长 5 天。这表明竞争减少,导致招聘人员需要额外的时间来寻找合适的候选人。

这些正确的候选人是幸运的,因为大多数人只需要一个学士学位就能被录用。低供给导致 61%的数据科学家职位提供给拥有学士学位的人,而只有 39%的数据科学家职位需要硕士学位或博士学位。

增长

如果您一直在关注这篇文章,那么您可能对数据科学工作的增长轨迹有一个很好的假设。

根据 LinkedIn 的数据,自 2012 年以来,数据科学的工作岗位增加了 650%。Glassdoor 为这一说法提供了证据,因为他们在 2016 年有大约 1700 个职位空缺,数据科学是主要角色。这个数字在 2018 年上升到 4500,在 2020 年持平在 6500 左右。

新冠肺炎是 2020 年的大事件,大概也是这一趋势变平的原因。尽管总体而言,科技行业的工作在疫情期间被证明是有弹性的,现在已经是第十个月了。

照片来自 Unsplash,由 Elena Mozhvilo 拍摄

不要押注于增长

对数据科学家的需求仍然很高,而供应却很低。据 IBM 称,这种趋势在未来几年将继续保持强劲。同意这一说法的另一个可信来源是美国劳工统计局。

美国劳工统计局看到了数据科学领域的强劲增长,并预测到 2026 年就业数量将增加约 28%。给那 28%一个数字,那大概是1150 万该领域的新工作岗位。

从长远来看,不把数据科学作为职业发展的赌注可能是不明智的,特别是当你把这个领域扩大到包括研究工程师和机器学习工程师等相关职位时。

最终想法

那么数据科学在 2021 年还是一个上升的职业吗?答案是响亮的是的!世界各地对数据科学家的需求丝毫没有减少,这些工作缺乏竞争使得数据科学成为一个非常有利可图的职业选择。

参考

[1] A. Woodie,为什么数据科学仍然是一份顶级工作(2020)https://www . datanami . com/2020/11/16/Why-Data-Science-Is-Still-a-Top-Job/

[2]加州大学宾夕法尼亚分校,数据科学职业、工作、薪水|数据科学家 (2019),https://www . calu . edu/academics/本科生/学士/Data-Science/Jobs-career-Salaries . aspx #:~:text = Data % 20 Science % 20 was % 20 named % 20 the,engineer % 2C % 20 和%20business%20analyst。"

[3] 365 数据科学,数据科学真的是一个上升的职业吗 (2020),https://www.youtube.com/watch?v=PXLVLS1vJHY

数据科学是你的职业吗?

原文:https://towardsdatascience.com/is-data-science-the-career-for-you-3596b6f0291a?source=collection_archive---------1-----------------------

帮助你做决定的 6 个问题

照片由上的爆裂未爆裂

我们都想追求自己热爱的、热爱做的、能帮助我们体面谋生的职业。近年来,随着科技在我们生活中的广泛应用,世界各地的科技工作呈指数增长。这些工作中的大多数都提供很好的福利,而且通常比其他领域的工资要高。

随着技术的不断发展,新的工作岗位将不断被创造出来并供不应求。这就是为什么科技行业的工作对考虑转行的人或选择职业道路的学生来说总是很有吸引力。

虽然科技行业的工作确实有很多优势,从工资到各种工作以及远程工作的可能性,但科技职业肯定不适合所有人。最著名的技术职业道路之一是数据科学,这是一个对当今世界既广泛又重要的领域。在过去的十年里,从事数据科学职业的人和数据科学工具的数量都呈爆炸式增长。

</5-online-data-science-courses-you-can-finish-in-1-day-5b60f353fa8e>

在这十年中,数百万人学习了数据科学,无论是通过在线课程还是通过获得该领域的学位。成为数据科学家的前提和好处今天仍然吸引着人们,在不久的将来也会如此。但是,包括我在内的所有这些人都会问自己一个问题:“数据科学是我的职业道路吗?”。

一个领域是否报酬丰厚,是否在这个世界上是必不可少的,并不能帮助你决定进入这个领域,就像把它作为职业一样。数据科学没有什么不同,也不是每个人的正确道路。在本文中,我将提出 6 个问题,你可以问自己是否喜欢在数据科学领域工作。

问题 1:你有好奇心吗?

先说我认为最重要的问题,“你有好奇心吗?”。你喜欢解谜吗,理解事物为什么是这样的,它们是如何变成这样的?当你面对有趣的发现或情况时,你会问自己“为什么”吗?

这是一个好迹象,表明数据科学可能是你的一个潜在领域。在数据科学中,当数据科学家检查数据时,他们的好奇心会产生很大的影响。这种好奇心会引导他们问正确的问题,这将导致更好的分析,从而做出更好的决策。

</9-comprehensive-cheat-sheets-for-data-science-46005d72b485>

但是,如果你对这个问题的回答是“不”,“我真的不在乎为什么事情是这样,或者为什么人们做他们做的事情。”那么追求数据科学对你来说可能有点挑战。

问题 2:你能接受总是学习新事物吗?

技术是一个正在发展的领域;它一直在进化和发展,这些年来没有一个技术问题是固定不变的。如果你正在考虑一般的技术职业,特别是数据科学,你需要随时准备跟上该领域的最新发展,并愿意随时学习。

学习新工具、新算法、新编程语言,解决新问题,提出新解决方案。在科技领域,总会有新的东西需要学习,新的问题需要解决。所以,如果你热爱学习和探索新的选择,你不会介意对你的领域一无所知。那么也许数据科学是你的领域。

问题 3:你是一个有耐心的人吗?

耐心在生活的许多方面都很重要;这无疑是成功的关键。但是在数据科学中,尤其是在任何项目的数据收集、清理和分析阶段,耐心是必不可少的。当给数据科学家一个新的数据集来探索和分析时,需要检查它,检查它是否是结构化的,并耐心地使用不同的可视化方法来更好地理解它。

在将你的模型应用于数据之前,当你训练你的模型时,你也需要耐心,耐心处理几乎每天发布的大量新工具。但是,做一个有耐心的人可以让你在数据科学或任何其他技术领域走得更远。

</5-types-of-machine-learning-algorithms-you-need-to-know-5ac7fce8920d>

问题 4:你喜欢和别人一起工作吗?

作为一名数据科学家不是一个人的角色;你需要一直和不同背景的人一起工作。也许数据科学中最明显的人与人的交互是客户与数据科学家的交互。此外,大多数数据科学项目旨在改进业务模型的某些方面。

因此,作为一名数据科学家,你将与来自商业背景的人一起工作,与其他数据科学家、图形设计师甚至作家一起工作,帮助他们使用数据做出更好的决策,并使他们的业务进一步发展。如果你喜欢与来自不同背景的人密切合作,有时在不同的国家,那么数据科学可能是你的职业道路。

问题 5:你喜欢在智力上挑战自己吗?

这个问题直接联系到我们之前问的关于渴望学习新东西的问题。但是除了学习新事物,数据科学是最具智力挑战性但又非常令人满意的领域之一。因此,要进入数据科学领域,你需要学习许多起初看起来没有联系的东西。

你需要学习编程、数学、统计学、可视化、商业、决策和解决问题。你需要挑战自己,了解许多领域,以便在数据科学中脱颖而出。这可能是许多人放弃进入数据科学的原因之一,但如果你像我一样,这可能是进入该领域的原因。

</6-data-science-certificates-to-level-up-your-career-275daed7e5df>

问题 6:你能轻松地交流复杂的想法吗?

最后一个问题——就目前而言——是,你喜欢轻松地交流复杂的术语吗?你能把一个复杂的概念,有效地简化,并解释给和你背景不同的人吗?你能向一个孩子解释吗?给一个年长的?

科学传播在数据科学中发挥着重要作用;正如我们刚刚看到的,在数据科学中,您需要与不同的人一起工作,所有人都有不同的知识库,您需要以一种对他们有意义的方式向他们解释您的工作流程。如果你喜欢简单地解释复杂的事情,并且喜欢开发创造性的方法来做到这一点,那么数据科学可能是适合你的领域。

最后的想法

选择职业道路不是一个容易的决定;需要认真做,需要大量的研究和考虑。但是,最近,科技行业的工作吸引了许多人,因为它们在收入、位置和生活重要性方面有很多优势。

如今,许多人考虑的技术职业之一是数据科学。数据科学是一个非常广泛的职业道路,涵盖许多角色,混合了技术、数学、统计和科学通信。对于一些喜欢解决特定问题并愿意不断学习的人来说,这是一个很好的领域。

但是,尽管数据科学很有趣,但它肯定不是一个适合所有人的领域。所以现在的问题是,你如何决定数据科学是否适合你?你如何判断从事这个领域是否会给你的职业生涯带来满足和快乐?

这些问题没有直接的答案,也没有固定的答案。然而,有一些方法可以让你知道数据科学是否是适合你的职业道路。在本文中,我带您回顾了我在进入数据科学之前问自己的问题,这些问题让我意识到,我将满足于在这个领域拥有一份职业。我所希望的是,它们也能帮助你做决定。

数据科学真的死了吗?

原文:https://towardsdatascience.com/is-data-science-truly-dead-b11cd76eafc8?source=collection_archive---------0-----------------------

意见

从数据科学家到 AI 实践者

图片由来自 PixabaySteve Bidmead 提供

也许你已经听说过,或者读到过,或者两者兼而有之。数据科学家正在死去,我们几乎无法保住我们的高薪、摇滚明星般的形象和膨胀的自我。显然,我在这里夸大了事情的戏剧性效果,但对于许多数据科学专业人士来说,这一信息仍然令人焦虑,他们已经开始在他们的工业水域中闻到血液的味道,因为越来越多的高管团队正在四处扔像“公民数据科学家”、“分析民主化”和“自动化机器学习”这样的概念。几年前,当马特·塔克的文章“数据科学家之死”发表在数据科学中心上时,这种担忧被点燃,尽管这并不是第一个做出这种断言的文章。但是,我们今天所知的数据科学家真的是注定要灭绝的物种吗?在这篇文章的剩余部分,我将探讨这一观点,同时为当前的数据科学专业人员提供一个未来可能会是什么样子的替代视角。

机器的崛起

在最基本的层面上,争论是这样的:数据科学家的许多活动本质上是可量化的或统计的,因此是可自动化的。因此,我们能够以自动化的方式更好地协调统计模型,数据科学家就越不需要拉动那些杠杆来选择、优化和部署他们的数据驱动的洞察力。事实上,DataRobot、谷歌的 AutoML 等公司和产品,以及对预先训练的、基于服务的数据科学模型(Azure Cognitive Services、谷歌人工智能服务、AWS、Watson)的不断扩展的访问,已经在实现这一目标方面取得了重大进展,人工数据科学家。

来自 Pixabay斯蒂芬·凯勒的图片

从流行到必需

尽管这是一个总是定义不清的领域的可怕预测,但那些声称拥有数据科学家头衔的人仍然发展了足够的技能,以适应即将到来的人工数据科学浪潮。因此,我们必须用探险者驾驭人工智能技术炒作浪潮的图像来取代我们虚构的世界天网正在崛起以推翻人类数据科学家最后剩下的据点的图像,这些人工智能技术从根本上嵌入了只有人类数据科学家真正理解的技能。为了实现这种发展,有三个领域是实践数据科学家必须关注的,也是未来雇主必须启发的:不断发展/扩展的工具包,用户体验的重要性,以及行业的福音。

不断发展/扩展的工具包

如果有一件事是数据科学家擅长的,那就是引起轰动(以及一些新工具的出现)。数据科学的概念本身是一个时髦的术语,许多对商业有统计知识的专业人士都把它与自己联系在一起,以提高他们的市场竞争力,并取得良好的效果。为什么我们应该期待人工智能的建筑浪潮会有所不同?随着数据科学家概念的发展,与之相关的工具也在发展,因此该领域的专业人员一直在不断地通过接触最新的可用工具来保持相关性。尽管变化的速度已经接近压倒性,但那些幸存下来并能够展示这些数据科学技术核心功能的能力的人,已经准备好利用人工智能工具。因此,学习进化的数据科学家将学习如何将自己重塑为人工智能的实践者。但是为了能够让其他人相信这个品牌重塑,这些专业人士需要继续扩展他们的工具包。虽然 21 世纪初为我们带来了 Hadoop、NoSQL、物联网、Python 的 scikit-learn、Tensorflow 和 Spark,但下一代将利用人工智能即服务、云计算、智能自动化和容器化进行分析。这意味着数据科学家必须继续学习如何利用 API 调用,构建支持数据科学的云环境,以及部署分析来公开 API 端点。

图片由 PixabayEd Zilch 提供

用户体验的重要性

如上所述,统计工具并不是帮助数据科学家在快速变化的环境中生存的唯一工具。人工智能不仅仅是统计技术,而是将这些统计技术嵌入到用户体验中。因此,精明的数据科学生存论者将发现使用嵌入式统计分析解决问题的机会。这些工作需要对软件编程概念有更深的理解,数据科学家已经通过获得开源脚本工具和与应用程序开发团队更紧密合作的能力做好了准备。从技术和理论的角度来看,有许多方法可以解决用户体验问题(例如,参见我们之前的博客文章),并且什么有效总是取决于用户的满意度,但关键是要确定统计模型改善用户体验的策略。这样,数据科学家将需要继续发展他们解决问题的方法。我们曾经关注使用尖端建模技术从数据中提取洞察力,现在我们需要关注它们在应用程序中的效用。

图片由皮克斯拜的 Gerd Altmann 提供

宣传某一行业

最后,因为我们的数据科学产品的真正测试取决于用户从这些产品中获取价值的能力,所以我们必须准备好利用我们对这些支持人工智能的技术的专业理解,并赋予公民数据科学家权力,而不是武断地认为我们的特殊知识是神圣的。尽管自动化数据科学产品的冲击承诺了明显的易用性,但公民数据科学家仍然缺乏对其应用的理解。正如一位 Reddit 用户如此优雅地描述的那样,“大多数人几乎不会使用 Excel,甚至大多数数据/业务分析师也很难理解基本的聚合和统计之外的任何东西。”因此,企业将依靠数据科学家来培训未来的公民数据科学家,以便在用例允许的情况下使用这些工具。之所以需要数据科学家,是因为数据科学不是一种工具,而是一种思考和解决问题的方式。工具当然会带来新的思考方式,但是人们需要接受如何思考工具的培训,以便工具能够改变他们解决问题的方式。简而言之,我们必须向人工数据科学家传播工具。在这种情况下,数据科学家成为组织内人工和人类数据科学产品的中心,而公民数据科学家成为代言人。

图片来自com break来自 Pixabay

从数据科学家到 AI 实践者

总之,数据科学家并没有死,或者正在死去,而是需要一场即将到来的进化。那些最成功地继续扩展其工具包以利用人工智能服务、向应用程序公开结果并与之交互,以及传授他们的思维方式以支持他人的人,将最有信心满足人工智能从业者对未来数字企业的需求。

比如参与学习更多关于数据科学的知识?加入我吧。

数据科学家适合你吗?

原文:https://towardsdatascience.com/is-data-scientist-the-right-job-for-you-f24dc7203049?source=collection_archive---------39-----------------------

数据科学招聘经理的一封信。

数据科学家已经成为需求最高的工作之一。由于许多人都在寻求成为一名数据科学家,今天,我整理了一份成为数据科学家的简短总结。

米利安·耶西耶Unsplash 上拍摄的照片

按照工作描述,数据科学家做什么?

  • 处理大型复杂数据集收集、处理和分析数据。
  • 根据需要,通过开发数据产品和/或运行战略分析以及应用高级分析方法(实验、统计或机器学习模型),告知并影响关键产品和业务决策
  • 设计核心指标作为团队工作的北极星
  • 跨职能工作具备有效的沟通和演示技巧

数据科学家的类型

许多公司的数据科学家分为以下三类。以上描述适用于所有三种类型的数据科学家。

  • 产品:专注于为客户打造新的功能或产品。主要的跨职能合作伙伴包括产品和工程
  • 增长/营销:专注于通过收购和保留/参与策略来扩大用户群。主要的跨职能合作伙伴包括营销和产品
  • 研究/算法:开发新的可扩展的统计或机器学习方法。主要的跨职能合作伙伴包括工程和产品。

日常工作

一般来说,我们每天花时间做以下工作。

  • 理解问题:我们工作中最重要的部分是理解手头的业务问题。我们需要能够回答“我们试图解决什么”这个问题以及“我的工作将如何为解决这个问题增加价值?”在开始任何数据科学项目之前。这将进一步帮助建立一个清晰有效的研究计划。
  • 数据收集和处理:信不信由你,完成数据科学项目的大部分时间都花在这上面。没有完美的数据。我们需要仔细检查数据是如何收集的,并了解团队/公司定义和收集数据的常用方法(例如,每日活跃用户是在帐户级别还是在人员级别计算的?)
  • 运行分析:一旦您理解了问题并处理了数据,就用“适当的”方法对其进行分析。请注意,找到并应用正确的方法是数据科学家工作中最重要的部分之一。应用复杂的机器学习方法论来炫耀自己的技能,并不是正确的道路。
  • 传达见解和建议:有效地传达调查结果以影响关键的商业决策,这对于您的项目产生影响非常重要。数据科学项目的最后一步是可视化数据,通过洞察力讲述故事,并分享后续步骤的建议。

数据科学家有一个普遍的误解,他们认为一旦开始工作,他们就可以应用他们学到的所有伟大的技术。我警告你,这不全是阳光和玫瑰。通常,我们大部分时间都在与跨职能合作伙伴开会,或者坐在电脑前试图理解数据并清理数据。

另请注意,随着数据科学家在职业生涯中的资历越来越高,他们可能会花更多的时间来了解更广泛的业务问题,将其分解为更小的可行分析计划,并与跨职能合作伙伴沟通。

那么,作为一名数据科学经理,我在招聘时需要什么呢

  • 技术专长:如上所述,通过数据找到解决业务问题的正确方法是一项必备技能。这就是为什么数据科学家要经历 3 到 4 次技术面试,包括数据争论(SQL)、编程(Python/R)、实验和机器学习。
  • 问题解决者:我寻找通过数据主动解决业务问题的候选人。一个数据科学家需要抛出问题,积极寻找方法论。一个只能用一种方法解决问题的人,或者一个给出教科书式答案的人,往往不是最佳人选。
  • 战略合作伙伴:我寻找具备出色沟通技巧、能够在协作工作环境中取得成功的候选人。毕竟,一个数据科学家不会坐在角落里,整天盯着数据。

我想澄清一下,这并不意味着公司或管理者一直在寻找一个优秀的多面手。像谷歌或脸书这样的大公司通常会在面试阶段发现多面手,然后在通过面试后进行团队匹配。然而,较小的公司或创业公司可能会在某些时候为特定技能而招聘。例如,当我在一家初创公司建立数据科学团队时,我曾经需要一个可以扩展 ML 算法的人,而另一次我需要一个可以建立非常规实验框架的人。在那些时候,我不得不放弃那些总体上很棒,但在特定领域缺乏深厚知识的候选人。

蒂姆·莫斯霍尔德在 Unsplash 上的照片

那么你真的想成为一名数据科学家吗?如果你有,这是我的最后一条建议:

  • 把你的基本知识掌握好!与其花时间学习在 Python 上运行机器学习模型的函数,不如花时间了解模型的属性。
  • 大量阅读!阅读别人是如何解决问题的。今天有许多资源,包括 Medium、LinkedIn、Quora、公司网站和其他可以阅读人们如何通过数据解决商业问题的资源。
  • 遇见人!当然,我们不能在新冠肺炎期间这样做。但是一旦问题解决了,就去见见其他人,听听他们是如何解决问题的。参加公司聚会,让其他数据科学家分享他们的经验。

享受您的数据科学家之旅!

dbt 是分析的未来吗?

原文:https://towardsdatascience.com/is-dbt-the-future-of-analytics-d6ff93cbb20c?source=collection_archive---------5-----------------------

该工具如何改变数据分析师的工作方式

汤姆·帕克斯Unsplash 上拍照

如果你听说过一个分析工程师或者了解数据建模,那么你可能对 dbt 很熟悉(如果你不熟悉,在这里阅读什么是)。它现在是非常热门的工具,因为它让数据团队的生活变得更加轻松!这不正是我们都希望在工具中实现的吗?

我第一次接触 dbt 是在两年前,当时我是一名数据工程师。我不知道它是什么,也不知道如何正确使用它。我阅读了大量的文档,老实说,我仍然很困惑。直到我把这个工具付诸行动,我才真正看到它的价值。

由于我在一个工程团队,我们实际上根本不关注分析。这是一个支持我们业务财务方面的工程团队。我们使用 dbt 来编译和测试我们的 SQL 代码,使得它比我们期望使用的内部平台运行起来要快得多。

因此,虽然我已经使用 dbt 很多年了,但我从未将它用于分析目的,直到我最近的角色。我们选择将其实现到由其他新工具组成的数据堆栈中,如 Fivetran雪花提督

在新的数据堆栈中一起使用这些工具,我们的数据文化已经开始转变。我们已经看到了数据质量、模型运行速度和使用文档的巨大改进。Dbt 将在分析领域长期存在,原因如下。

数据质量

dbt 最棒的地方在于,它消除了反复重写相同代码的需要。您可以编写一个模型,然后在其他模型中引用它。这创建了更可靠的代码,因为您在所有模型中使用了相同的逻辑。

这在分析中派上用场的方法之一是通过您公司的关键绩效指标。我们有一种方法来定义和计算它。通常,如果这个 KPI 在许多不同的模型中被不同地计算,就有很多事情出错的空间。

Dbt 通过使我们的代码模块化来提供帮助。我们可以简单地重用而不是重新编码!这不仅提高了数据质量,还为我们分析师节省了大量宝贵的时间。

dbt 提高数据质量的另一种方式是鼓励直接在源代码中进行转换和重命名。你可以在他们的文档这里了解更多。但是,本质上,您在基本模型中完成了所有较小的数据“管理”任务。这些是直接从原始源表中选择的模型。

然后,您的其他模型只引用这些基础模型,而不是任何原始数据。这可以防止错误,比如意外地将日期转换为两种不同类型的时间戳(是的,我以前也遇到过这种情况),或者给同一列取两个不同的名称。

这些类型的问题很简单,但当您深入编写数据模型时,可能是最难弄清楚的。两种不同的时间戳转换导致所有的日期在下游被不正确地连接,将模型变成了一场巨大的灾难。幸运的是,我们能够在投入生产之前发现并修复这个问题。

速度

如果您正在使用 dbt 之外的另一种转换工具,那么您可能理解对速度的需求。我见过运行时间超过 8 小时的数据模型!很抱歉,如果您的数据模型需要那么长时间才能运行,那么您就不可能拥有高效的分析工作流。

Dbt 使您能够将代码组织成基本数据模型和中间数据模型,从而大大加快核心数据模型的运行速度。因为您的模型也是模块化的,所以您运行它们一次,并在您的其他模型中引用它们。您不会浪费时间和资源一遍又一遍地运行相同的代码块。

Dbt 模型在使用dbt run命令执行时也是并行运行的。有依赖关系的模型在它们的上游模型完成之前不会运行,但是相互不依赖的模型会同时运行。这增加了吞吐量,并最大限度地减少了运行时间。

模型通过使用一种叫做“多线程”的技术并行运行。不同的模型在不同的线程上处理,允许它们一起执行。当你在你的dbt_project.yml文件中看到thread: 300时,那只是指你允许同时运行多少个模型。

证明文件

在分析和数据建模领域,文档是最被低估的优势之一。你的数据的有用程度取决于它被记录的程度。它不仅使新团队成员成功入职的速度提高了三倍,还让团队中的每个人对数据有了更深入的理解。

如果你正确地进行分析,你会不断地问关于你的数据的问题。当提出问题时,dbt 文档可以提供答案。即使已经在公司工作多年的人也不得不偶尔参考数据定义。数据上的数据永远不嫌多。美国数据迷喜欢一些好的元数据。

Dbt 允许你将模型的描述直接添加到代码中。这也使得跟踪列名和描述变得容易。这个文档被写在一个与你的模型存储目录相对应的.yml中。

然后,这些.yml文件可以用来围绕所有 dbt 文档生成一个网站。Dbt 通过向用户提供dbt docs命令使这变得非常容易。您只需在命令行上运行以下命令:

  1. dbt docs generate
  2. dbt docs serve

运行这两个命令后,将会填充一个本地网站供您查看。通常,您只需导航到 localhost:8080,就可以看到易读格式的文档。

dbt 实验室在 dbt 上拍摄的照片

这是一个网站看起来像什么的例子。您可以在左侧看到您的项目和数据库,它们的组织方式与您在代码环境中看到的类似。当您单击一个模型时,您可以阅读描述并查看该模型中各列的信息。

dbt 文档中我最喜欢的特性可能是谱系图(也称为 DAG )。这类似于您在编排网站上看到的内容。它提供了一个模型之间相互依赖的很好的视觉效果。通过查看这里,您可以很容易地看到您所有的核心模型都使用了哪些基础模型和中间模型。

如果您想在您的公司内部使用该文档,我建议您将该网站托管在公司内部网站上,或者使用像 Netlify 这样的解决方案。您每月为每个用户支付 19 美元,并且您的所有数据模型都有一个很好的真实来源。

结论

Dbt 正在帮助公司采取下一步措施,成为数据驱动的文化。它正在改变现代数据堆栈的理念,将所有其他的转换工具打得落花流水。Dbt 将继续成为公司提高数据质量、速度和文档化的重要手段。

Dbt 不会很快消失。它是一种工具,将一直存在。我强烈建议学习它,并将其融入到您团队的数据文化中。你越早开始整合它,你就能从它身上学到越多,并允许它对你如何使用数据做出不可思议的改变。

通过订阅我的电子邮件列表,了解更多关于 dbt 和其他流行的现代数据堆栈工具的信息

如何评价深度学习是否适合自己?

原文:https://towardsdatascience.com/is-deep-learning-right-for-you-b59a2219c457?source=collection_archive---------29-----------------------

可能不会!在浪费时间之前,这里是你需要知道的

深度学习和传统机器学习如何抉择?—图片由金德媒体Pexels 拍摄

深度学习是目前人工智能领域最热门的趋势之一。这也是最难理解的一个,所以在开始实施之前,你必须知道深度学习可以为你的业务做些什么。

这篇博文将讨论如何评估深度学习何时适合你,以及它可能提供的好处。

深度学习也被称为深度神经网络。这是因为它模仿了你大脑中用来思考和学习的神经网络,这些神经网络可以被认为是相互堆叠的层或部分。利用深度学习,在输入数据(例如,图像)和输出(例如,物体或人脸)之间可能有几个隐藏层。

深度学习尤其擅长从大量数据中筛选出模式。这对于像图像或声音识别这样的任务来说非常有用,在这些任务中,你有几十万甚至几百万个例子。

传统模式确实有其优点。

深度学习并不是所有情况下的理想解决方案。有时候,传统模型比深度学习表现得更好,因为它们更容易解释。

在传统模型中,您可以看到哪些特性会影响决策和性能。相比之下,深度学习可能很难解释,因为在得出答案之前,并不总是清楚你的数据会去哪里,或者它是如何被处理的。这种不透明性意味着其他人可能需要更长的时间来信任其结果,尤其是对于需要批准的任务。

传统方法对于具有较少特征的小数据集表现更好。他们也比深度学习模型学得更快

这并不是说传统模型总是优于深度学习,但它有时确实会发生!因此,如果你陷入了什么方法最适合你所面临的项目或业务问题,不要指望你的旧机器学习技术。

你也可以尝试使用像 SVM 这样的特征选择和提取工具,帮助你筛选大量数据,找到你的业务所需要的。通过教授它有关功能和要求的知识,SVM 可以用比深度学习所需更少的数据建立模型,同时提供准确的结果。

这也在几项研究中得到了验证。这里有一个说 SVM 模型比卷积神经网络(CNN)有更好的结果。)

你如何选择正确的机器学习方法?

头号策略是尝试直接比较两种方法,这样你就知道哪种方法最适合你的问题。

例如,你可以将数据分成两部分,用一组例子建立传统模型,另一组建立深度学习模型。然后比较它们的性能,看看哪一个对您的业务问题或用例产生了更好的结果。

如果你 有一大堆特性深度学习可能是你的正确选择。

在现实世界的问题中,通常有比数据点更多的特征,因此并不总是能够看出哪些是重要的。这意味着机器学习算法需要在选择最佳特征之前筛选所有数据。

深度学习有助于找到哪个特征 是最重要的,就像识别图像中的人脸,即使它被转开或部分遮挡。这意味着在训练前调整传统的机器学习算法以选择正确的算法所需的时间更少,以获得更好的整体性能。

深度学习实际上是做什么的?

通过深度学习,你将数据输入到模型中,它会学习如何自己识别模式。例如,如果有一堆沙子和另一堆仅包含岩石,输入图层可能会看到两堆沙子和岩石。网络中的每一个更深层次都可以从那些简单的概念中学到更复杂的概念,比如添加更多的石头或混合泥土。这些信息一次穿过所有的层。

深度学习最适用于图像和语音识别等问题,但它也需要大量数据。例如,我们知道深度学习可以做得很好,有 10 万个或更多的例子可以学习。因此,如果您只有 1000 个示例(即图像),那么传统模型可能是最佳选择。

一个常见的挑战是深度学习所需的计算资源。训练深度学习模型可能需要几天甚至几周的时间,因此在开始之前,您需要将数据和工作流准备就绪。

你还想确定你的问题可以用深度学习来解决。深度学习擅长图像、语音和文本识别等任务,所以一定要看看下面流行的深度学习用例列表。

如果你的企业碰巧面临一个你可以通过深度学习解决的问题,不要放弃上面列出的其他方法!例如,如果你需要一个可解释的模型来帮助他人信任它的输出,那么像 SVM 这样的传统方法可能是一个更好的选择。

深度学习哪里表现好?

当谈到计算机视觉时,深度学习的可能性是无限的。它用于自动驾驶汽车、图像识别(例如,脸书可以为你标记你的照片)、医学成像(如放射学和病理学报告)、绘制地形或扫描地面的无人机、机场面部识别等安全系统,甚至 Prism 等智能手机应用程序。

具有许多隐藏层和更多神经元的更深层次的神经网络也可以帮助计算机检测语音模式,这就是苹果的 Siri 和亚马逊 Echo 在理解你说的话方面如此出色的原因。谷歌语音搜索是这项技术的另一个很好的例子。它使用深度学习模型来捕捉最远 20 英尺外的噪音,同时过滤背景声音。

深度学习也使得构建更有吸引力的聊天机器人变得更加容易。这些计算机程序可以与用户进行对话,这就是为什么如果你曾经使用 Facebook Messenger 的 M assistant 进行过对话,或者与 Poncho 等基于互联网的客户服务机器人聊过天,你最近可能会使用一个程序。

深度学习模型帮助这些助手理解你在说什么,并提供有益的回应。

结论

总之,深度学习是机器学习的一个分支,它使用深度神经网络,可以学习声音、图像和语言等抽象特征。与其他机器学习方法相比,深度学习有几个优势,包括在视觉、语音或文本识别任务中的更好性能。

然而,它比传统模型需要更多的计算资源。此外,如果没有太多的数据,传统的方法表现更好,因为他们需要较少的训练。如果你选择使用深度学习,确保你的问题适合这种类型的模型。

差不多就是这样!希望你喜欢阅读…

感谢阅读,在 LinkedInTwitterMedium 上向我问好。

还不是中等会员?请使用此链接使 成为 的会员,因为,在不为你额外付费的情况下,我为你引荐赚取一小笔佣金。

F1 是使用的合适标准吗?F2,F3,…,Fβ呢?

原文:https://towardsdatascience.com/is-f1-the-appropriate-criterion-to-use-what-about-f2-f3-f-beta-4bd8ef17e285?source=collection_archive---------6-----------------------

使用 F1 度量进行二元分类是非常常见的。这就是众所周知的调和平均数。然而,更通用的 F_beta 评分标准可能更好地评估模型性能。那么,F2,F3,和 F_beta 呢?在本帖中,我们将回顾 F 值。

介绍

许多数据科学家认为,最可靠的模型性能衡量标准是准确性。它不仅是权威的模型度量,还有许多其他的度量。周期性地,准确性可能很高,但是假阴性(将在后续中定义)也很高。另一个关键指标是目前机器学习中常见的 F-measure,用于评估模型性能。它成比例地结合了精度和召回措施。在这篇文章中,我们探索了两者不平衡的不同方法。

初步:混淆矩阵、精确度和回忆

困惑矩阵(图片由作者提供)

混淆矩阵总结了 ML 中监督学习算法的性能。它更有益,因为它提供了比普通精度测量更详细的分析。在混淆矩阵中,每行代表预测类中的实例,每列代表实际类中的实例。如上所述,简化的混淆矩阵包含两行和两列,其中:

缩写(图片由作者提供)

为了进一步讨论,我们还得定义两个重要的度量: Precision :所有 P 样本除以 TP 样本的数量(真与假),以及 Recall :除以( TP + FN )的 TP 的数量。

精确度和召回率(图片由作者提供)

由于这两种方法都非常重要,因此需要一种方法将两者结合起来。因此,提出了精确度和召回率的调和平均值,也称为 F1 分数。

F1 分数

该度量由下式给出:

F1 分数的主要优点(同时也是缺点)是召回率和精确度同等重要。在许多应用中,情况并非如此,应该施加一些重量来打破这种平衡假设。这种平衡假设可能适用于数据分布不均匀的情况,如大量正负数据。

F2 和 F3 分数

利用加权平均,我们可以很容易地得到测度【F2】:

F2(图片由作者提供)

F2(图片由作者提供)

以同样的方式,获得 F3 分数:

F3(图片由作者提供)

F_beta 分数

概括加权平均法可得出 Fβ测量值,由下式提供:

F beta(图片由作者提供)

这种方法允许我们定义召回比精确度重要多少。在 sklearn 中使用 Fβ测量非常简单,只需遵循以下示例:

https://scikit-learn.org/stable/modules/generated/sklearn.metrics.fbeta_score.html?highlight=f beta#sklearn.metrics.fbeta_score

**>>> from** **sklearn.metrics** **import** fbeta_score
**>>>** y_true = [0, 1, 2, 0, 1, 2]
**>>>** y_pred = [0, 2, 1, 0, 0, 1]
**>>>** fbeta_score(y_true, y_pred, average='macro', beta=0.5)
0.23...
**>>>** fbeta_score(y_true, y_pred, average='micro', beta=0.5)
0.33...
**>>>** fbeta_score(y_true, y_pred, average='weighted', beta=0.5)
0.23...
**>>>** fbeta_score(y_true, y_pred, average=**None**, beta=0.5)
array([0.71..., 0\.        , 0\.        ])

摘要

在这篇文章中,我回顾了 F 值。我希望所提供的数据将帮助那些处理分类任务的人,并激励他们使用 F 值和准确度。

关于作者

Barak 获得了以色列理工学院的航空工程学士学位(2016 年)、硕士学位(2018 年)以及经济和管理学士学位(2016 年,成绩优异)。他曾在高通工作(2019-2020),在那里他主要研究机器学习和信号处理算法。巴拉克目前正在海法大学攻读博士学位。他的研究兴趣包括传感器融合、导航、机器学习和估计理论。

https://www.researchgate.net/profile/Barak-Or

www.barakor.com

延伸阅读

[1] C.J .范·里斯贝根:https://en.wikipedia.org/wiki/C._J._van_Rijsbergen

[2] 马修斯相关系数是你从未听说过的最佳分类指标

人工智能和数据干旱的令人担忧的未来

原文:https://towardsdatascience.com/is-federate-data-sharing-our-last-great-hope-to-scare-off-the-next-ai-winter-96854d54b720?source=collection_archive---------26-----------------------

意见

缺乏可用数据阻碍了机器学习解决方案的采用。联合数据共享可能是答案。

谈到高质量的数据,许多组织都受到了冷落(照片由哈里森·海恩斯Pexels 拍摄)

从希腊神话中最早的人工智能主题开始,人们就一直在思考人工智能及其可能带来的可能性。随着计算和数学的进步,艾伦·图灵 1950 年关于思维机器的论文引发了这方面的首次实际发展。第一个概念证明是通过艾伦·纽厄尔、克里夫·肖和希尔伯特·西蒙的、逻辑理论家 一个旨在模仿人类解决问题能力的程序进行初始化的——被许多人认为是 1956 年提出的第一个人工智能程序。

艾还年轻 60 岁,我们才刚刚开始。

尽管它已有 60 年的历史,而且在过去几年里大肆宣传,但还有很长的路要走。我们已经看到了无数令人不安的道德挑战和大企业的一些失败(世界经济论坛的这篇文章是一个很好的起点)。

然而,还有另一个迫在眉睫的威胁,它已经夺走了试图开发人工智能解决商业问题的受害者的公平份额。我已经从组织和个人那里看到和听到了足够多的信息,知道这种威胁是普遍的,并导致整个行业的幻灭。

这种威胁首先是缺乏可用的数据。

艾·温特斯

决策冻结——我们正在走向另一个可怕的“人工智能冬天”吗?(照片由 Ricardo Gomez AngelUnsplash 拍摄)

自现代诞生以来,人工智能领域已经经历了几次突破性的时刻,随之而来的是热情和辉煌的进步。正是在这些时期,人工智能吸引了一批新的人,他们被似乎充斥媒体的承诺和机会所吸引。

然而,在许多情况下,这种热情是短暂的。一些组织在没有真正了解如何成功部署这些解决方案并从中获取价值的情况下行动过快。或者他们只是期望太多,却遇到了令人沮丧的现实。

然后钟摆摆向另一边,媒体几乎打开了纪律。越来越多关于失败项目和“人工智能冬天”的报道进入了对话。我听说过这样的团队,在一个被认为是成功的项目之后,又回到了旧的工具和方法,因为基础没有建立起来,无法让这些胜利持续下去。

这很大程度上是由于实验室报告的结果与实践中可达到的结果相比而造成的。有一些令人难以置信的重大胜利,也有一些业界应该引以为豪的巨大成果。你应该保持警惕,尽管有人卖给你这些巨大的成果,作为你的公司没有重大投资的速赢。

如果你不熟悉 Gartner 炒作周期,我建议你在这里阅读一下。我相信,对于大多数围绕人工智能的讨论来说,我们已经超越了巅峰。人们开始敏锐地意识到几年前被故意忽视的局限性。

我想我们也要崩溃了。在很大程度上。许多组织现在已经尝试了人工智能,却发现即使是开始也很难。

大多数组织根本没有必要的数据来使人工智能取得成功。

数据荒

没有数据,我们什么都没有!(布拉德·赫尔墨克在 Unsplash 上的照片)

互联网的兴起、云计算、大数据处理技术的进步和获取都是人工智能最近崛起的因素。再加上图像处理令人兴奋(有时也令人害怕)的视觉效果,图像处理已经永远改变了物体检测和面部识别等领域,你就有了吸引公众注意力的完美秘诀。

在很多领域,深度学习仍然举步维艰。Deepmind 的最新重大胜利 AlphaFold 可能是医学新一轮进步的开端,但除此之外,深度学习在许多更复杂的领域都很艰难。研究中的可能性和对一个组织有用且有价值的东西之间的差距是很难跨越的。

组织无法在不泄露秘密的情况下安全地访问和共享可用数据。

即使在组织内部,数据也可能存储在筒仓中,这往往导致沮丧的数据团队重复工作或错过潜在的金矿。已经转向更集中和/或分离的架构,如 data lake、lakehouse 或 data mesh,它们为内部数据共享提供了一些解决方案。然而,伴随着这些解决方案而来的是新的挑战——实现这些工作所需的技能需求量很大,而新技术和程序的采用可能既缓慢又昂贵。

在许多领域,单个组织没有足够的高质量数据来构建强大的模型。最近的许多突破都依赖于大量的数据。获取更多信息是一笔大生意——看看像 Scale 这样的公司取得的巨大成功就知道了——这是一家成立于 2016 年的数据标签公司,目前估值为 35 亿美元

考虑到像 GDPR 这样的立法,犯这种错误的代价从错失机会到严重的罚款。随着人工智能的伦理和公平使用的发展,我希望我们会看到类似的规定在世界各地出现,这对保护公民的隐私至关重要。这将给组织带来沉重的负担,限制了确保合规性的解决方案。

找到一种在保护数据安全和隐私的同时跨越组织边界共享数据的方法,将为中小型组织扫除这些障碍。

数据共享(但不要太多)

找到一种在数据集上合作的方法将是成功的关键

如果趋势是更加隐私和安全,那么建立或消除信任的需要可能会成为一个中心主题。为了确保这不会减缓创新并导致某种形式的数据饥荒,技术需要跟上。

在“联合数据共享”的保护伞下,一些解决方案即将出现。

有几种技术属于这一类别,包括:

  • 差分隐私 —当从数据集中删除敏感信息还不够时,引入噪声可以让各方成功共享信息。
  • 同态加密 —对数据进行加密,以便可以对其进行分析,而信息本身除了目标方之外不能被任何人读取。
  • 零知识证明 —允许一方证明特定信息,而无需分享除预期之外的任何内容。
  • 安全多方计算 —允许各方对多家机构持有的私有数据进行分析,而不会泄露输入内容。
  • 联合学习 —分别对每个不同的数据集进行分析,然后跨数据集分享见解。

尽管处于不同的成熟阶段,许多工具仍在研究中,但这些工具将使组织能够在不暴露自己或其敏感数据的情况下进行数据协作。

对于 AI 模型开发,联邦学习可能是最相关的(也是更发达的方法之一)。它允许用户使用跨设备和位置分布的多个数据集来训练机器学习模型,同时防止数据泄露和隐私问题。

有三种主要的联邦学习方法。

水平的

这种方法根据特性来划分数据资产,通常用于特性比用户有更多重叠的地方。例如,考虑在不同地理位置运营的同一行业的本地企业-它们将拥有许多相同类型的数据,但如果它们位于国家的两端,则可能不会共享一个客户。

垂直的

当功能几乎不重叠但用户重叠时,可以使用垂直联合学习。我们已经在医疗保险和可穿戴设备、物流和本地商业等服务领域看到了这一点。获得描述您的用户的新功能可能是解锁新服务和产品的关键,这将大大增加您向他们提供的价值。垂直联合学习允许双方将所有这些特征聚集到一个更具描述性的数据集,双方可以协作使用。

转移

就像我们习惯于使用预先训练的模型进行图像处理并将它们应用于其他领域一样,同样的想法也可以应用于组织数据。这可能很困难,因为它需要对不同的领域和高层次的抽象有深刻的理解才能使它有效。

随着时间的推移,我们将看到这些技术的巨大进步,因为整个行业的问题变得更加尖锐。

结论

近年来,我们经历了人工智能和机器学习的强劲增长期。不幸的是,许多组织在其旅程的早期就遇到了障碍。许多人面临的最大障碍之一是无法获得相关的高质量数据。

新方法有望让组织安全可靠地与其他人合作,构建更强大的数据集。我相信这将成为开启人工智能为中小型企业提供的许多承诺的关键。

只有时间能证明一切。

进一步阅读

深入了解金融服务领域的联合共享:

https://www.weforum.org/whitepapers/the-next-generation-of-data-sharing-in-financial-services-using-privacy-enhancing-techniques-to-unlock-new-value

和医疗保健:

https://www.weforum.org/reports/sharing-sensitive-health-data-in-a-federated-data-consortium-model-an-eight-step-guide

在这里可以找到对最近一些道德准则的评论:

https://link.springer.com/article/10.1007/s11023-020-09517-8

深入了解对数据科学家和数据工程师的要求:

https://www.kdnuggets.com/2021/02/dont-need-data-scientists-need-data-engineers.html

posted @ 2024-10-18 09:27  绝不原创的飞龙  阅读(232)  评论(0)    收藏  举报