TowardsDataScience-博客中文翻译-2020-十-
TowardsDataScience 博客中文翻译 2020(十)
TensorFlow 2 中 Keras 回调的实用介绍
最常用的 Keras 回调 API 教程

作者使用www.canva.com制作的图像
当训练机器学习模型时,我们希望能够监控模型性能,并根据这些性能指标执行某些操作。这就是 Keras 回调的原因。
回调是对象 TensorFlow 和 Keras 的一种重要类型,它们被设计成能够在训练运行中的某些点上监视度量中的性能,并执行一些可能依赖于那些度量值中的性能的动作。
在本文中,我们将借助一些例子来探索以下流行的 Keras 回调 API。
EarlyStopping:为提前停止而设计的回调。CSVLogger:回调将 epoch 结果流至 CSV 文件。ModelCheckpoint:训练时保存 Keras 模型或模型权重的回调ReduceLROnPlateau:当指标停止改善时,回调以降低学习率。LearningRateScheduler:对 学习率计划表 的回调。LambdaCallback:动态创建定制回调的回调。
请查看我的 Github repo 获取源代码。
1.提前停止
EarlyStopping是为提前停止设计的内置回调。首先,让我们导入它并创建一个提前停止对象:
from tensorflow.keras.callbacks import **EarlyStopping****early_stopping = EarlyStopping()**
EarlyStopping()有一些选项,默认情况下:
monitor='val_loss':使用验证损失作为绩效衡量标准,终止培训。patience=0:是没有改善的时期数。值0意味着一旦性能测量从一个时期到下一个时期变得更差,就终止训练。
接下来,我们只需要将回调对象传递给model.fit()方法。
history = model.fit(
X_train,
y_train,
epochs=50,
validation_split=0.20,
batch_size=64,
verbose=2,
**callbacks=[early_stopping]**
)
您可以看到,early_stopping在一个列表中被传递给了callbacks参数。这是一个列表,因为在实践中,我们可能会为执行不同的任务传递许多回调,例如,调试和学习速率时间表。
通过执行该语句,您应该得到如下所示的输出:
Train on 8000 samples, validate on 2000 samples
Epoch 1/50
8000/8000 - 6s - loss: 1.5632 - accuracy: 0.5504 - val_loss: 1.1315 - val_accuracy: 0.6605
......
......
Epoch 10/50
8000/8000 - 2s - loss: 0.5283 - accuracy: 0.8213 - val_loss: 0.5539 - val_accuracy: 0.8170
Epoch 11/50
8000/8000 - 2s - loss: 0.5141 - accuracy: 0.8281 - **val_loss: 0.5644** - val_accuracy: 0.7990
由于val_loss值的增加,训练在时期 11 终止,这正是条件monitor='val_loss'和patience=0。
看一个剧情往往更方便,我们来运行plot_metric(history, 'loss')来一个清晰的画面。在下图中,验证损失显示为橙色,很明显,验证误差在第 11 时段增加。

图片由作者制作(请查看笔记本)
争论
除了我们之前提到的选项monitor和patience之外,另外两个选项min_delta和mode可能会经常使用。
EarlyStopping(
monitor='val_loss',
patience=0,
min_delta=0,
mode='auto'
)
monitor='val_loss':使用验证损失作为绩效衡量标准,终止培训。patience=0:无改善的时期数。值0意味着一旦性能测量从一个时期到下一个时期变得更差,就终止训练。**min_delta**:符合改善条件的监控量的最小变化,即小于min_delta的绝对变化,将被视为无改善。**mode='auto'**:应为auto、min或max中的一种。在'min'模式下,当监控量停止下降时,训练将停止;在'max'模式下,当监控的数量停止增加时,它将停止;在'auto'模式下,方向自动从监控量的名称推断出来。
这是一个定制的提前停止的例子:
custom_early_stopping = EarlyStopping(
**monitor='val_accuracy',**
**patience=3,**
**min_delta=0.001,**
**mode='max'**
)
monitor='val_accuracy'使用验证准确度作为绩效衡量标准来终止培训。patience=3表示训练在 3 个周期后终止,没有改善。min_delta=0.001表示验证准确度必须至少提高 0.001 才能算作改进。mode='max'表示当监控的数量停止增加时,它将停止。
让我们继续,使用定制的提前停止运行它,并绘制精度图。
Train on 8000 samples, validate on 2000 samples
Epoch 1/50
......
Epoch 12/50
8000/8000 - 2s - loss: 0.5043 - accuracy: 0.8290 - val_loss: 0.5311 - val_accuracy: 0.8250
Epoch 13/50
8000/8000 - 3s - loss: 0.4936 - accuracy: 0.8332 - val_loss: 0.5310 - **val_accuracy: 0.8155**
Epoch 14/50
8000/8000 - 2s - loss: 0.4835 - accuracy: 0.8353 - val_loss: 0.5157 - **val_accuracy: 0.8245**
Epoch 15/50
8000/8000 - 2s - loss: 0.4757 - accuracy: 0.8397 - val_loss: 0.5299 - **val_accuracy: 0.8060**

图片由作者制作(请查看笔记本)
这一次,训练在时期 15 终止,因为有 3 个时期在验证准确性上没有改进(它必须≥ 0.001 才能算作改进)。
有关提前停止的更多信息,请查看这篇文章:
使用 Keras 和 TensorFlow 2.0 添加和自定义提前停止的分步教程
towardsdatascience.com](/a-practical-introduction-to-early-stopping-in-machine-learning-550ac88bc8fd)
2.CSVLogger
CSVLogger是一个回调函数,将 epoch 结果转换成一个 CSV 文件。首先,让我们导入它并创建一个CSVLogger对象:
from tensorflow.keras.callbacks import **CSVLogger****csv_log = CSVLogger("results.csv")**
接下来,我们只需要将**csv_log**对象传递给model.fit()方法。
history_csv_logger = model.fit(
X_train,
y_train,
epochs=10,
validation_split=0.20,
batch_size=64,
verbose=2,
**callbacks=[csv_log]**
)
培训完成后,我们可以查看 CSV 文件中的信息
import pandas as pd**pd.read_csv("results.csv", index_col='epoch')**

图片由作者制作(请查看笔记本)
争论
除了强制参数filename之外,其他两个选项separator和append可能会经常使用。
CSVLogger(filename, separator=',', append=False)
filename:CSV 文件的文件名。**separator**:用于分隔 CSV 文件中元素的字符串。**append**:布尔型,默认为False,True如果文件存在则追加(对继续培训有用)。False:覆盖现有文件。
3.模型检查点
ModelCheckpoint是一个回调,用于在训练期间保存 Keras 模型或模型权重,以便稍后可以加载模型或权重,以从保存的状态继续训练。
首先,让我们导入它并创建一个ModelCheckpoint对象:
from tensorflow.keras.callbacks import **ModelCheckpoint**checkpoint_path = 'model_checkpoints/'checkpoint = ModelCheckpoint(
**filepath=checkpoint_path,**
**save_freq='epoch',**
**save_weights_only=True,**
verbose=1
)
接下来,让我们将checkpoint对象传递给model.fit()方法进行训练。
history_checkpoint = model.fit(
X_train,
y_train,
epochs=10,
validation_split=0.20,
batch_size=64,
verbose=2,
**callbacks=[checkpoint]**
)

图片由作者制作(请查看笔记本)
在培训过程中,我们应该能够看到上面的打印输出。
训练完成后,我们可以通过运行以下命令来获得测试准确性:
>>> get_test_accuracy(model, X_test, y_test)
**accuracy: 0.779**
装载重量
让我们创建一个新模型new_model来演示负重是如何工作的。通过运行get_test_accuracy(new_model, X_test, y_test),我们得到了一个没有加载任何训练过的砝码的模型的测试精度 0.086 。
# Create a new model
>>> new_model = create_model()# Without loading weight
>>> get_test_accuracy(new_model, X_test, y_test)
**accuracy: 0.086**
接下来,我们用load_weights('model_checkpoints/')加载砝码,再次得到它的测试精度。这一次,我们应该能够看到与我们训练模型model相同的准确性。
# Load weights
>>> new_model.load_weights('model_checkpoints/')
>>> get_test_accuracy(new_model, X_test, y_test)
**accuracy: 0.779**
争论
下面是使用ModelCheckpoint回调时你应该知道的常用参数
filepath: string 或PathLike,保存模型文件的路径。filepath可以包含命名的格式化选项,例如,如果filepath是weights.{epoch:02d}-{val_loss:.2f},那么模型检查点将与纪元编号和验证损失一起保存在文件名中。save_freq:'epoch'或整数。使用'epoch'时,回调在每个时期后保存模型。当使用 integer 时,回调在这许多批的末尾保存模型。save_weights_only:如果True,则只保存模型的权重(model.save_weights(filepath)),否则保存整个模型(model.save(filepath))。
4.ReduceLROnPlateau
ReduceLROnPlateau是一种回调,用于在指标停止改善时降低学习率。该回调监控一个量,如果在一个patience数量的周期内没有看到改善,则学习率减少factor值(new_lr = lr * factor)。让我们借助一个例子来看看这是如何工作的。
首先,让我们导入它并创建一个ReduceLROnPlateau对象:
from tensorflow.keras.callbacks import ReduceLROnPlateaureduce_lr = ReduceLROnPlateau(
**monitor='val_loss',
factor=0.2,
patience=2,
min_lr=0.001,**
verbose=2
)
monitor='val_loss'使用验证损失作为降低学习率的绩效衡量标准。patience=2表示学习率在 2 个周期后降低,但没有改善。min_delta=0.001表示验证损失必须至少改善 0.001 才能算作改善。factor=0.2表示新的学习率将随着new_lr = lr * factor减少。
让我们用reduce_lr回调来训练模型
history_reduce_lr = model.fit(
X_train,
y_train,
epochs=50,
validation_split=0.20,
batch_size=64,
verbose=2,
**callbacks=[reduce_lr]**
)

图片由作者制作(请查看笔记本
您应该得到如上所示的输出。在上面的输出中,ReduceLROnPlateau回调已经在时间点 30 和 37 被触发。
让我们画出学习率和损失的图表,以便清楚地了解情况。

图片由作者制作(请查看笔记本)

图片由作者制作(请查看笔记本)
争论
下面是使用ReduceLROnPlateau回调时你应该知道的常用参数
monitor='val_loss':使用验证损失作为性能指标,降低学习率。factor:学习率降低的系数。new_lr = lr * factor。patience:无改善的时期数。min_delta:符合改善条件的监控量的最小变化,即小于min_delta的绝对变化,将被视为无改善。mode='auto':应为auto、min或max中的一种。在'min'模式下,当监控量停止下降时,学习率将会降低;在'max'模式中,当监控的数量停止增加时,学习率将降低;在'auto'模式下,方向由监控量的名称自动推断。min_lr:学习率的下限。
5.学习率计划程序
在训练神经网络时,随着训练的进行降低学习速率通常是有用的。这可以通过使用学习速率表或自适应学习速率来完成。LearningRateScheduler是学习率计划的内置回调。
有关学习费率表的更多详细信息,请查看以下文章:
[## 实践中的学习率计划:以 Keras 和 TensorFlow 2.0 为例
训练一个神经网络的一个痛苦的事情是我们必须处理的超参数的绝对数量…
towardsdatascience.com](/learning-rate-schedule-in-practice-an-example-with-keras-and-tensorflow-2-0-2f48b2888a0c)
让我们借助一个例子来看看LearningRateScheduler是如何工作的。
首先,让我们导入它并创建一个调度函数:
from tensorflow.keras.callbacks import LearningRateSchedulerdef **lr_decay**(epoch, lr):
if epoch != 0 and epoch % 5 == 0:
return lr * 0.2
return lr
lr_decay()取 2 个参数epoch(当前纪元)& lr(当前学习率),返回一个新的学习率。我们的lr_decay()函数将每 5 个历元将学习率降低 0.2 倍。
让我们用reduce_lr回调来训练模型
history_lr_schedule = model.fit(
X_train,
y_train,
epochs=20,
validation_split=0.20,
batch_size=64,
verbose=2,
callbacks=[**LearningRateScheduler(lr_decay, verbose=1)**]
)

您应该得到如上所示的输出。下面是学习率的曲线图。

图片由作者制作(请查看笔记本)
6.LambdaCallback
另一个有用的回调是LambdaCallback。它类似于Callback,允许我们动态构建定制回调。
LambdaCallback由下面的匿名函数构成,这些函数将在适当的时候被调用。
on_epoch_begin:在每个纪元开始时调用。on_epoch_end:在每个历元结束时调用。on_batch_begin:在每批开始时调用。on_batch_end:每批结束时调用。on_train_begin:模型训练开始时调用。on_train_end:模型训练结束时调用。
注意,回调需要位置参数,如下所示:
on_epoch_begin和on_epoch_end需要两个位置参数:epoch、logson_batch_begin和on_batch_end期待两个位置论元:batch、logson_train_begin和on_train_end期待一个位置自变量:logs
让我们借助一个例子来看看LambdaCallback是如何工作的。
首先,让我们导入它并创建 3 个不同的LambdaCallback:
from tensorflow.keras.callbacks import LambdaCallback**epoch_callback** = LambdaCallback(
on_epoch_begin=lambda epoch,logs: print('Starting Epoch {}!'.format(epoch+1))
)**batch_loss_callback** = LambdaCallback(
on_batch_end=lambda batch,logs: print('\n After batch {}, the loss is {:7.2f}.'.format(batch, logs['loss']))
)**train_finish_callback** = LambdaCallback(
on_train_end=lambda logs: print('Training finished!')
)
让我们用上面的回调来训练模型
history_lambda_callback = model.fit(
X_train,
y_train,
epochs=2, # change epoch to 2 for demo purpose
validation_split=0.20,
batch_size=2000, # change to 2000 for demo purpose
verbose=False,
callbacks=[**epoch_callback, batch_loss_callback, train_finish_callback**]
)

图片由作者制作(请查看笔记本
您应该得到如上所示的输出。这非常有用
其他回调函数
除了上述函数,在深度学习项目中,您可能会遇到或希望使用其他回调函数:
Callback:这是用于构建自定义回调的基类。它与LambdaCallback相似,但功能更强大。我们将为此再进行一次讨论。TensorBoard:一个回调为 TensorBoard 写日志,tensor board 是 TensorFlow 优秀的可视化工具。RemoteMonitor:用于将事件流式传输到服务器的回调。
好了
感谢阅读。本文涵盖了最受欢迎的 Keras 回调。
请查看笔记本获取源代码。
如果你对机器学习的实用方面感兴趣,请继续关注。
您可能对我的其他 TensorFlow 文章感兴趣:
- 实践中的学习率计划
- 谷歌机器学习实践的 7 个步骤:结构化数据的 TensorFlow 示例
- 用 Keras 和 TensorFlow 2.0 创建机器学习模型的 3 种方法
- 批量规范化实践:以 Keras 和 TensorFlow 2.0 为例
- 实践中的提前停止:以 Keras 和 TensorFlow 为例
更多可以从我的 Github 中找到
机器学习的实用介绍
一个简单的入门 ML 从业者和爱好者的参考指南,介绍了它的各种术语,概念和技术

继我之前关于数据科学的文章之后,在这里,我将尝试以一种方便、易用、语言无关的参考指南格式来总结和编译机器学习的主要实用概念。大多数信息都以简短扼要的要点形式呈现。我希望这对于初学者来说特别有价值,或者对于那些在数据科学和机器学习方面有基本经验的人来说是一个快速查询。
介绍性概念
让我们先弄清楚一些基本术语:
- 结构化数据指以预定义格式存储的数据,例如表格、电子表格或关系数据库
- 另一方面,非结构化数据没有预定义的格式,因此不能以表格形式保存。非结构化数据可能有多种类型,例如文本、图像、视频、音频文件
- 分类数据是任何可以标记的数据,通常由一系列固定值组成,如性别、国籍、风险等级。分类数据可以是名义数据(没有任何固有的排序,例如性别)或顺序数据(排序或分级数据,例如风险等级)。这些固定值被称为类或类
- 特征或预测器:ML 模型使用的输入数据/变量,通常用
X表示,用于预测目标变量 - 目标变量:我们希望用 ML 模型预测的数据点,通常用
y表示 - 分类问题涉及预测分类目标变量的离散类别,例如,垃圾邮件与否、违约或非违约
- 回归问题处理预测一个连续的数值,例如销售额、房价
- 特征工程:转换现有特征或设计新的输入特征,这些特征在模型训练期间可能更有用。例如,为日期变量计算从今天开始的月数
- 训练、验证&测试数据:初始模型训练/拟合时使用训练数据。验证数据用于评估模型,通常用于微调模型参数或在众多模型中确定最合适的 ML 模型。测试数据用于最终评估入围或微调的模型
- 过度拟合发生在模型在训练数据上表现良好,但在测试/验证数据上表现不佳的时候,即不能对新的和看不见的数据进行充分概括的时候
- 欠拟合发生在模型不够复杂和稳健,无法从训练数据中学习变量关系,甚至在应用于训练数据时精度也较低的时候
- 模型偏差和方差:当一个模型由于拟合不足而在训练数据集上表现不佳时,该模型被认为是有偏差的。方差与模型在测试/验证集上的表现好坏有关,高方差通常是由过度拟合引起的
- 泛化,与过度拟合和模型方差密切相关,指的是模型对新的、以前看不到的数据做出正确预测的能力
- 正则化技术提高了模型的概化能力,例如,通过惩罚回归系数或将回归系数收缩到零
- 集成学习是一种将多个模型组合成一个模型的建模技术
- 基线模型是一种简单的模型/启发式方法,用作评估传统 ML 模型的参考点
- 超参数是在模型训练期间可以调整的特定模型参数
数据清理和特征工程
数据清洗将原始数据转换成能够被 ML 模型有效且高效地处理的形式和格式。尽管 GIGO 原理被认为是智能和稳健的,但它在 ML 中仍然有效。更多细节请参考我之前的文章。
处理缺失数据:
- 删除所有缺少要素的记录-不推荐
- 使用领域知识的启发式插补
- 缺失值的均值/中值/众数插补
- 使用随机值或常数来填充缺失的数据
- 利用 k 个最*邻或线性回归模型来预测和估算缺失值
其他一些典型的数据清理任务包括:
- 识别并删除零方差特征
- 识别并尽可能删除显示多重共线性或高度成对相关的要素
- 利用领域知识评估低方差或接*零方差的特性。最适用于数字和名义分类数据
- 删除重复记录(如果适用)
- 识别异常值并确定适当的策略来处理它们——要么丢弃它们,要么修剪它们,要么保持原样,因为一些 ML 模型可以有效地处理异常值
特征工程
特征工程与其说是科学,不如说是一门艺术,它主要依赖于一个人的领域知识。如果操作正确,它有可能提高模型的预测能力。
数字数据的特征工程技术:
- 使用对数标度、z 值、最小值-最大值进行缩放、归一化或标准化
- 使用原始数字特征中的数学或统计交互作用创建新特征,例如通过加法、减法或统计测试
- 利用统计变换将偏斜分布转换成类似高斯的分布,例如对数/幂和 Box-Cox 变换
- 降维技术,例如主成分分析(PCA)
- 宁滨一个数字特征分类一般不推荐。但是,在某些用例中(例如,信用风险评分),它是经过验证和充分研究的行业最佳实践
分类数据的特征工程技术:
- 顺序编码:将有序分类数据转换成数值,例如,好、坏、更坏转换成 1、2、3
- 名义分类数据的一键编码。每个特征的类别被转换成一个单独的列,其中它的存在用 1 表示,不存在用 0 表示。例如,[美国,英国,澳大利亚]转换为[[1,0,0],[0,1,0],[0,0,1]]
- 在自然语言处理中广泛使用的某些特定技术,例如特征散列法和词嵌入法
建模概述和原则
那么机器学习模型到底是做什么的呢?给定训练数据中的一组特征X,ML 模型试图迭代地找到理想的统计函数(通常称为训练函数),该统计函数最准确地将X映射到训练数据的目标变量y。寻找理想的训练函数通常涉及对基础数据及其形式做出某些假设。给定X,这个训练函数然后被用于预测y未来的任何新数据。
一些基本的建模原则
在这里,我们将触及一些与建模相关的一般原则和哲学:
模型精度及其可解释性权衡
更好的模型精度通常会导致相对较低的模型可解释性。
复杂的模型,如深度神经网络和集成决策树,通常比简单的模型表现更好。然而,它们的可解释性要差得多,因为训练功能对于外行人来说不容易理解。更简单的模型,如线性回归、逻辑回归和单一决策树,很容易以准确性为代价进行解释。
考虑一个简单的逻辑回归模型。它为我们提供了每个特征的系数,进而为我们提供了关于该特征对预测问题有多有用的见解。
因此,有时,模型选择通常是由所需的复杂性和可解释性水*驱动的。一些领域,如信用评分,或多或少要求使用一个易于解释的模型。因此,逻辑回归在历史上被广泛用于信用评分问题。然而,对于图像检测、识别和自然语言处理来说,可解释性就不那么重要了。因此,复杂的深度神经网络可以安全地部署在这些领域中。
偏差/方差权衡
一般来说,模型的偏差可以通过参数调整或选择完全不同的模型来改善,而方差可以通过更多的训练数据、正则化技术或防止训练集和测试集之间的任何数据泄漏来减少。偏差和方差只能在一定程度上同时改善,超过这一程度,一个方面的改善通常会导致另一方面的恶化。
这种权衡非常普遍,在实践中需要微妙的*衡。请注意,由于数据中的随机噪声,总会有一些不可避免的方差,这使得实际上不可能将方差降至 0。
奥卡姆剃刀
奥卡姆剃刀(Occam's Razor)是一个普遍的哲学原理,它指出:如果一个事件或一个事实有两种解释,那么最简单、假设最少的解释很可能是正确的。当应用于 ML 时,奥卡姆剃刀原理意味着,当比较两个具有相似预测能力或准确性的模型时,我们应该选择更简单的模型。
没有免费的午餐定理
没有一个单一的机器学习模型能最好地解决所有可能的问题。Wolpert 和 Macready 指出:“如果一种算法在某类问题上比随机搜索表现得更好,那么它在其余问题上的表现一定比随机搜索差”。尝试多种相关模型并找到最适合您的特定问题的模型是很常见的。
建模分类学
机器学习模型可以以几种方式分类,其中一些是:
参数与非参数
参数模型对训练数据做出强假设,以识别训练函数并将其简化为已知形式,其参数完全描述并捕捉特征和目标变量之间的关系。
例如,线性回归模型假设输入要素和目标变量之间存在线性关系,并会尝试找到最佳的线性函数。然而,如果这个假设是无效的,那么该模型将预测差的结果。
参数模型的例子包括线性回归、逻辑回归和朴素贝叶斯。
非参数模型不会对训练数据或训练函数的形式做出强有力的假设,因此通常更灵活,但代价是潜在的过拟合。
非参数模型的例子包括 k *邻、决策树和支持向量机(SVM)。
有人监督与无人监督
有监督的模型试图预测已知的目标变量,而无监督的模型事先没有关于目标变量的任何知识。无监督学习的目标是尝试并理解变量或观察值之间的关系。
监督模型包括线性回归、逻辑回归和决策树,而非监督模型包括 k *邻、SVM、隔离森林和 PCA
黑盒 vs .描述性
黑盒模型利用多种复杂算法做出决策,但我们不知道决策/预测是如何得出的。例如深度学习和神经网络。
描述性模型提供了对他们为什么以及如何做出决策的清晰洞察。例如线性回归、逻辑回归、决策树
常用 ML 型号
深度机器学习领域之外的一些广泛使用的 ML 模型包括:
- 线性回归是一个简单且广泛应用于回归问题的监督学习模型。它基于特征和目标变量之间存在线性关系的假设来预测数字目标变量
- 逻辑回归广泛用于预测类别,或在给定一组特征的情况下被分配到该类别的概率。因此,它是分类问题的监督模型。逻辑回归假设所有特征与目标变量的对数优势(logit)具有线性关系。当预测不*衡类时需要非常小心
- k-最*邻(KNN) 是一个监督模型,可用于分类和回归问题。它通过距离度量(最常见的是欧几里德距离)对每个观察的最*邻居的
k数量进行简单多数投票来预测 - k-Means 聚类是一种无监督聚类算法,它以最小化每个聚类中单个观察值之间差异的方式将观察值分配给各个组
- 决策树是监督模型,可以使用一系列规则用于回归和分类问题。单个决策树很少在实践中使用,因为它有过度拟合的风险。相反,集合或 bagging 概念被用来最小化模型方差
- 随机森林是一个集成模型,它通过装袋的概念来组合多个决策树,以减少模型误差
- 支持向量机(SVM) 是一种监督分类模型,旨在找到所有可能类别之间的理想超*面或边界,使它们之间的距离最大化。这个超*面然后被用于分类
模型评估
但是我们的模型在预测方面有多好呢?模型评估给了我们答案。
评估策略
各种评估策略的简要概述如下:
训练/测试分割
将完整的数据集分成两个子集,称为训练和测试(通常以 80/20、75/25 或 70/30 的比例分割)。在训练集上训练模型,并对在测试集上做出的模型预测应用评估度量。这不是理想的方法,因为没有单独的数据集来测试、评估和比较模型参数(称为超参数优化)或多个模型。
对测试集进行这样的评估并使用结果来调整模型将导致从测试集到训练集的数据泄漏以及不可靠的最终评估度量。这是因为我们使用来自测试集的信息(应该被认为是我们在生产中会遇到的新的、看不见的数据)来训练模型。
训练/验证/测试分割
将整个数据集分成三个子集。在训练集上训练单个或多个模型,并对在验证集上做出的模型预测应用初步评估度量。使用这些结果来微调单个模型或选择最佳模型。一旦选择了最终模型,就将其应用于尚未接触的测试数据集,并对其进行评估。这可以防止任何数据泄漏,是一种更好的评估方法,但不是理想的评估方法。
交叉验证
CV 在训练/测试分割后应用于训练集。CV 将训练集拆分为多个子集(称为折叠),并在除一个子集之外的所有子集上拟合模型,并在维持集上对其进行评估。这将产生多个评估指标(取决于折叠次数),其*均值和标准偏差用于选择最终模型。
一旦选择了最终模型,它将在整个训练集上再次训练,并在测试集上进行评估,测试集在整个过程中保持不变。CV 是理想的模型评估方法。
一些标准的 CV 技术包括:
- 遗漏一个 CV (LOOCV):除了一个观察值之外,拟合和训练所有的模型
- k-Fold CV:在
k-1折叠数上拟合和训练模型,并在维持集上评估 - 重复 k-Fold CV:类似于 k-Fold CV,但是该过程重复指定的次数
- 分层 k-Fold CV:类似于 k-Fold CV,但这里的折叠是通过保留每个目标类的样本百分比来实现的。对不*衡数据有用
- 重复分层 k 倍 CV:重复 k 倍 CV 和分层 k 倍 CV 的组合
评估指标
有数十种模型评估指标,下面介绍了一些更广泛使用的指标:
分类指标:
- 准确率:正确预测占预测总数的比率。不适合不*衡的数据集
- 精度:真阳性与预测阳性总数的比率
- 回忆,也称为敏感度或真阳性率(TPR):真阳性与实际阳性数量的比率
- F-Score: 一个单独的分数,用来同时衡量精度和召回率
- 受试者工作特性曲线下面积( AUROC ):总结 ROC 曲线信息的单个数字
- 布赖尔分数、科恩的卡帕统计等。
关于这些指标的更多细节,请参考我以前的文章。
回归指标
- *均绝对误差(MAE) :实际值和预测值的*均绝对差值
- 绝对误差中值:实际值和预测值绝对差的中值
- 均方误差(MSE) :实际值和预测值的*方差的*均值
- 均方根误差(RMSE):MSE 的简单根
结论
我希望以上几点能在你的机器学习之旅中派上用场。
欢迎联系我讨论任何与机器学习或数据和金融分析相关的问题。
继续学习!
参考
[1]沃尔波特,戴维&麦克雷迪,威廉。(1997).Macready,W.G .:最优化没有免费的午餐定理。进化计算汇刊 1(1),67–82。进化计算。1.67–82.10.1109/4235.585893.
熊猫 pivot_table()函数实用介绍
有效使用 Pandas pivot_table()函数汇总数据的 7 个实用技巧

数据透视表是 Excel 最强大的功能之一。数据透视表允许我们从数据中获得洞察力。Pandas 提供了一个类似的功能叫做pivot_table()。Pandas pivot_table()是一个简单的函数,但是可以非常快速地产生非常强大的分析。
在这篇文章中,我们将借助例子来探索如何使用熊猫pivot_table()。示例涵盖以下任务:
- 最简单的数据透视表
- 指定
values并执行聚合 - 使用
columns查看分解 - 替换丢失的值
- 显示多个
values并调整视图 - 显示总计
- 生成月度报告
请查看笔记本获取源代码。更多教程可从 Github Repo 获得。
数据
在本教程中,我们将处理咖啡销售数据。你可以从我的 Github repo 下载。
让我们导入一些库并加载数据来开始。
import pandas as pd**def load_data():
return pd.read_csv('coffee_sales.csv', parse_dates=['order_date'])**df = load_data()
df.head()
我们创建了一个函数load_data()来加载 coffee_sales.csv 文件,其中列'order_date'的数据类型为 date。

所有的专栏都是不言自明的。
1.最简单的数据透视表
最简单的透视表必须有一个index。在我们的例子中,让我们使用 区域 作为我们的索引。默认情况下,它对所有可用的数字列执行'mean'聚合函数。
df.pivot_table(**index='region'**)

为了显示多个索引,我们可以将一个列表传递给index:
df.pivot_table(**index=['region', 'product_category']**)

index的值是数据透视表中分组依据的关键字。您可以更改值的顺序以获得不同的视觉表示,例如,我们想通过将区域与 产品 _ 类别 分组来查看*均值。
*df.pivot_table(index=[**'product_category', 'region'**])*

2.指定值并执行聚合
默认情况下,pivot_table对所有数值列执行mean聚合函数,并返回结果。要明确指定我们关心的列,可以使用values参数。
*df.pivot_table(index=['region'], **values=['sales']**)*

为了执行除了mean之外的聚合,我们可以将一个有效的字符串函数传递给aggfunc,例如,让我们做一个 sum:
*df.pivot_table(index=['region'], values=['sales'], **aggfunc='sum'**)*

aggfunc可以是 dict,下面是 dict 等价。
*df.pivot_table(
index=['region'],
values=['sales'],
**aggfunc={ 'sales': 'sum' }**
)*
aggfunc可以是一个函数列表,下面是一个显示总和与计数的例子
*df.pivot_table(
index=['region'],
values=['sales'],
**aggfunc=['sum', 'count']**
)# The dict equivalent
# **aggfunc={ 'sales': ['sum', 'count']}***

3.使用列查看分解
如果我们希望看到 销售额 按 产品 _ 类别 细分,那么columns参数允许我们这样做
*df.pivot_table(
index=['region'],
values=['sales'],
aggfunc='sum',
**columns=['product_category']**
)*

4.替换丢失的值
您可能会注意到前面输出中的一个NaN值。我们之所以有这种茶叶,是因为在南方没有茶叶销售。如果我们想替换它,我们可以使用fill_value参数,例如,将NaN设置为0。
*df.pivot_table(
index=['region'],
values=['sales'],
aggfunc='sum',
columns=['product_category'], **fill_value=0** )*

5.显示多个值并调整视图
如果我们还想查看 成本 的总和,我们可以将 成本 列添加到values列表中。
*df.pivot_table(
index=['region'],
values=['sales', **'cost'**],
aggfunc='sum',
columns=['product_category'],
fill_value=0
)*

这确实有用,但是当我们想要并排比较 成本 和 销售 时,这种可视化表示似乎没有用。为了获得更好的视觉表现,我们可以将 产品 _ 类别 从columns中移出并添加到index。
*df.pivot_table(
index=['region', **'product_category'**],
values=['sales', 'cost'],
aggfunc='sum',
fill_value=0
)*

现在,数据透视表可以很方便地并排看到 销售 和 成本 之间的差异。
6.显示总计
数据透视表中的另一个常见显示是显示总计。在熊猫pivot_table()中,我们可以简单的通过margins=True:
*df.pivot_table(
index=['region', 'product_category'],
values=['sales', 'cost'],
aggfunc='sum',
fill_value=0,
**margins=True**
)*

7.生成月度报告
对我们来说,原始销售数据很少按月汇总。这种类型的数据通常是按天捕获的。然而,经理们通常想要按月的报告,而不是按天的细节。要使用 Panda pivot_table()生成月度销售报告,步骤如下:
(1)使用带有key='order_date'和freq='M'的Grouper()定义 groupby 指令
(2)定义按年份过滤数据的条件,例如 2010 年
(3)使用 Pandas 方法链接过滤和pivot_table()。
*month_gp = pd.Grouper(key='order_date',freq='M')
cond = df["order_date"].dt.year == 2010(
**df[cond]**
.pivot_table(index=['region','product_category'],
**columns=[month_gp]**,
values=['sales'],
aggfunc=['sum'])
)*

好了
感谢阅读。
请在我的 Github 上查看笔记本的源代码。
如果你对机器学习的实用方面感兴趣,请继续关注。
你可能会对我的其他一些熊猫文章感兴趣:
- 何时使用 Pandas transform()函数
- 使用熊猫方法链接提高代码可读性
- 在 Pandas 数据帧中使用日期时间
- 处理熊猫中缺失的值
- 熊猫阅读 _csv()你应该知道的招数
- 用 Pandas read_csv()解析日期列应该知道的 4 个技巧
更多可以从我的 Github 中找到
实用机器学习指南
从 EDA 到模型评估的银行客户流失预测。
流失预测是机器学习领域的一个常见用例。如果你不熟悉这个术语,churn 的意思是“离开公司”。对于一个企业来说,了解客户可能流失的原因和时间是非常重要的。拥有一个强大而准确的客户流失预测模型有助于企业采取措施防止客户离开公司。

克里斯·利维拉尼在 Unsplash 上的照片
在这篇文章中,我们的目标是建立一个监督学习算法来执行分类任务。目标是使用提供的功能预测客户是否会流失(即退出= 1)。数据集可在 Kaggle 上的这里获得。
第一步是将数据集读入熊猫数据帧。
import pandas as pd
import numpy as npdf_churn = pd.read_csv("/content/Churn_Modelling.csv")df_churn.shape
(10000, 14)df_churn.columns
Index(
['RowNumber', 'CustomerId', 'Surname', 'CreditScore', 'Geography','Gender', 'Age', 'Tenure', 'Balance', 'NumOfProducts', 'HasCrCard','IsActiveMember', 'EstimatedSalary', 'Exited'], dtype='object')
数据集包含 10000 个客户(即行)和关于银行客户及其产品的 14 个特征。
探索数据
有一些多余的功能。“RowNumber”列只是一个索引。“客户 Id”和“姓氏”列对于机器学习模型来说显然是无用的。客户的姓氏或 ID 不会告诉我们任何关于客户流失的信息。因此,我们应该删除它们,以免给模型带来不必要的计算负担。
df_churn.drop(['RowNumber', 'CustomerId', 'Surname'], axis=1, inplace=True)df_churn.head()

我们还要检查数据集中是否有任何缺失值。
df_churn.isna().sum()

该数据集没有任何缺少的值,这在现实生活的数据集中是不常见的。处理缺失值是机器学习流水线的重要组成部分。如果与数据集的大小相比,缺少的值非常少,我们可以选择删除缺少值的行。否则,最好用合适的值替换它们。Pandas fillna 函数可以用来处理这个任务。
重要说明:如果您选择基于列中的非缺失值估算缺失值(例如,用列的*均值填充缺失值),您应该在将数据集拆分为训练和测试子集后执行此操作。否则,您会将测试集中的数据泄露给机器学习模型,这些数据应该是新的、以前未见过的数据。
我们还应该确保数据以适当的数据类型存储。例如,数值不应该存储为“对象”。 Dtypes 函数返回每一列的数据类型。
df_churn.dtypes

数据类型似乎是合适的。
我们永远不应该只是将原始数据转储到机器学习模型中。垃圾进,垃圾出!这就是为什么我们需要探索数据集并理解特征和目标之间的关系。
地理和性别特征可能会对客户流失产生影响。一种方法是使用熊猫的 groupby 功能。
df_churn[['Geography','Gender','Exited']].groupby(['Geography','Gender']).agg(['mean','count'])

发现:在这三个国家,女性比男性更容易跳槽。
发现:德国的流失率高于其他两个国家的流失率。法国的顾客最多。
让我们看看客户的年龄与流失率之间的关系。
plt.figure(figsize=(10,6))sns.catplot(x='Exited', y='Age', hue='Gender', data=df_churn)

就客户流失而言,年龄不会造成非常显著的差异。然而,在不流失(退出=0)的一方有更多的老年人。我们还应该检查年龄栏的分布。
plt.figure(figsize=(10,6))sns.distplot(df_churn['Age'], hist=False)

分布是右偏的,这表明异常值在右侧。这在规范化特征时很重要。我们会谈到这一点。
任期,即客户成为客户的时间,也可能是客户流失的一个指示性因素。
df_churn[['Tenure','Exited']].groupby('Tenure').agg(['mean','count']).sort_values(by=[('Exited','mean')])

在任期和流失之间没有一个容易识别的模式。
相关矩阵通过提供成对的相关值,为我们提供了变量之间关系的概述。它只接受数值。因此,最好将“地理”和“性别”列中的类别转换为数字类别。
gender = {'Female':0, 'Male':1}country = {'France':0, 'Germany':1, 'Spain':2}df_churn['Gender'].replace(gender, inplace=True)df_churn['Geography'].replace(country, inplace=True)df_churn.head()

pandas 的 corr 功能创建了一个关联矩阵,然后可以用热图可视化。
corr_matrix = df_churn.corr()plt.figure(figsize=(12,8))sns.heatmap(corr_matrix, cmap='Blues_r', annot=True)

“HasCrCard”特征与目标变量的相关性最小。此外,由于信用卡是一种产品,该特性的信息能力部分存在于“NumOfProducts”列中。
df_churn[['HasCrCard','Exited']].groupby('HasCrCard').agg(['mean','count'])

“HasCrCard”特性的两个值(0 和 1)的*均流失率几乎相同。
编码分类变量
我们将类别转换成数值。然而,我们还需要一个步骤来使它们适用于机器学习模型。
法国变成了 0,德国变成了 1,西班牙变成了 2。如果我们像这样离开他们,模型可能会认为西班牙比法国更重要。
一个解决方案是 one-hot encoding ,这意味着为每个类别创建一个新列。根据原始列中的值,新列的值为 1 或 0。
你可以使用 scikit-learn 的 onehotencoder,但我更喜欢手动操作,因为类别的数量只有 3 个。
df_churn['Germany'] = df_churn['Geography'].where(df_churn['Geography'] == 1, 0)df_churn['Spain'] = df_churn['Geography'].where(df_churn['Geography'] == 2, 0)
df_churn['Spain'] = df_churn['Spain'].replace(2,1)df_churn.drop(['Geography'], axis=1, inplace=True)df_churn.head()

如果有 n 个类别,我们需要 n-1 列。如果其他 n-1 列中的值为零,我们已经有了关于最后一列的信息。例如,原始数据帧中的第一行是“法国”。我们已经有了这些信息,因为“德国”和“西班牙”列为零。
由于“性别”列有两个不同的值,我们不需要一次性编码它。
阶层失衡
数据不*衡通常是分类问题中的一个问题,它表示类别分布不均匀。像客户流失、垃圾邮件检测这样的任务很可能具有不均匀的类别分布。

存在大约 4 比 1 的不*衡。如果分类模型是在不*衡的数据集上训练的,它将高度偏向主导类。因此,该模型将反映潜在的类别分布。为了有一个准确的模型,我们需要解决不*衡问题。
有不同的方法来使用它作为解决方案。我们可以进行过采样(增加少数类的观测值)或欠采样(减少多数类的观测值)。
有不同的过采样技术。其中最常见的是 SMOTE (合成少数过采样技术)。SMOTE 算法根据已有的样本创建新的样本。它采用两个或更多相似的观察值,并通过一次改变一个属性来创建一个综合观察值。变化量是随机的,但会将新观测值保持在所用现有观测值的相邻距离内。
from imblearn.over_sampling import SMOTEsm = SMOTE(random_state=42)X = df_churn.drop('Exited', axis=1)y = df_churn['Exited']X_res, y_res = sm.fit_resample(X, y)print(pd.Series(y_res).value_counts())
1 7963
0 7963
目标变量中的数字 0 和 1 现在相等。
列车试裂
我们现在需要将数据集分成训练和测试子集。该模型将在训练集上进行训练,并在测试集上进行测试。
在应用特征工程技术之前分割数据集是很重要的。模型不应该得到任何关于测试集的信息,测试集应该是由新的、以前看不到的特性组成的。
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X_res, y_res, test_size=0.2)
正常化
特性的取值范围差别很大。例如,“任期”的最大值是 10,而“估计工资”的值高达 20 万。
如果我们将具有不同值范围的特征输入到模型中,则具有较高值的特征可能被赋予更大的重要性。我们不希望这样,所以我们将把功能纳入类似的范围。
归一化有不同的技术,如最小最大缩放器、标准缩放器和鲁棒缩放器。
当数据集中存在异常值时,RobustScaler 是一个不错的选择。
from sklearn.preprocessing import RobustScalertransformer = RobustScaler().fit(X_train)X_train_transformed = transformer.transform(X_train)X_test_transformed = transformer.transform(X_test)
请记住,我们仅将训练集中的特征适配到缩放器。然后,训练集和测试集都用训练好的尺度进行变换。
功能选择
我们已经在一定程度上探索了特征的重要性,并深入了解了它们与目标变量之间的关系。
特性选择仅仅意味着使用更有价值的特性。这里的价值是信息。就目标变量而言,我们希望使用信息更丰富的特性。
我们将使用递归特征消除(RFE ),它通过递归消除特征来工作。该消除是基于来自估计器的输出来完成的,该估计器将某种权重分配给特征。例如,权重可以是线性回归的系数或决策树的特征重要性。
from sklearn.linear_model import LogisticRegressionfrom sklearn.feature_selection import RFElog_reg = LogisticRegression()rfe = RFE(estimator=log_reg, n_features_to_select=7, step=1)rfe.fit(X_train_transformed, y_train)rfe.ranking_
array([1, 1, 1, 3, 1, 1, 2, 1, 4, 1, 5])
我们使用逻辑回归作为估计量。所需的特征数量由 n_features_to_select 参数决定。RFE 给每个特征分配一个等级。分配有 1 的功能是选定的功能。
在我们的例子中,被删除的特征是“任期”、“HasCrCard”、“EstimatedSalary”和“西班牙”。
回想一下,在我们的 EDA 过程中,我们发现“HasCrCard”特性与“Exited”列的相关性最低。
让我们过滤所选的特征。
X_train_selected = X_train_transformed[:,[0,1,2,4,5,7,9]]X_test_selected = X_test_transformed[:,[0,1,2,4,5,7,9]]
模型
我将使用随机森林分类器。
from sklearn.ensemble import RandomForestClassifierrf = RandomForestClassifier(max_depth=10, n_estimators=200)rf.fit(X_train_selected, y_train)
我们已经训练了这个模型。让我们对训练集和测试集进行预测。然后,我们将检查模型的准确性。
from sklearn.metrics import confusion_matrixy_pred = rf.predict(X_train_selected)
cm_train = confusion_matrix(y_train, y_pred)
print(cm_train)y_test_pred = rf.predict(X_test_selected)
cm_test = confusion_matrix(y_test, y_test_pred)
print(cm_test)train_acc = (cm_train[0][0] + cm_train[1][1]) / cm_train.sum()
test_acc = (cm_test[0][0] + cm_test[1][1]) / cm_test.sum()print(f'Train accuracy is {train_acc}. Test accuracy is {test_acc}')

在训练集上的准确度是%91.7,在测试集上的准确度是%90.7。好消息是我们的模型没有过度拟合。但是,精确度可以提高。
我们还打印了混淆矩阵,显示了有多少正(1)类和负(0)类被正确预测。根据任务的不同,特定类的预测更重要。在我们的例子中,正确预测正类(Exited=1)应该是重点,因为我们想知道哪些客户会离开我们。
在分类问题上,准确性并不能提供对模型的全面评估。根据任务的不同,精度、召回率和 AUC 等其他指标可能更合适。
在的下一篇文章中,我们将致力于:
- 如何提高准确率(正负类都有)
- 如何将模型的焦点更多地向正面类倾斜
感谢您的阅读。如果您有任何反馈,请告诉我。
线性回归中的一个实用建议
机器学习
从弹性网开始,记得调好定义 l1 范数之比的超参数。

贾斯汀·科布利克在 Unsplash 上的照片
不无论你是一名经验丰富的数据科学家还是机器学习的初学者,线性回归仍然是你需要掌握的最基本的模型之一。
简单而有用的线性回归长期以来一直受到多个领域研究人员的青睐,比如生物学和金融学。原因是线性回归的优点和它的局限性一样明显。
例如,即使它依赖于 Xs 和 Y 之间的线性关系的假设,它仍然比复杂的网络更容易实现,比如深度神经网络。而且模型本身更容易解读。
然而,在一个真实的项目中,实现线性回归就像输入下面几行代码一样简单吗?
**from** **sklearn.linear_model** **import** LinearRegression
my_model = LinearRegression()
my_model.fit(X,y)
不,不是真的。
上面的代码很容易遇到 过拟合问题 。过度拟合意味着与测试数据相比,您的模型在训练数据中表现得更好。
导致过度拟合问题的原因通常是模型的高度复杂性。在上面的代码中,将 X 中的所有特征汇集到线性回归模型中,将很难对未来的数据点做出预测。
通常可以通过两种方式降低线性模型的复杂度, 特征工程、 和 正则化 。
特征工程意味着从原始 X 表中手动选择一个特征子集,然而,该过程还需要数据集的先验知识来指导特征过滤。我们不会谈论太多。
正如我所说,降低线性模型复杂性的第二种方法是通过正则化。脊回归、套索回归,以及弹性网是三种实现方式。
我不打算在这里涉及任何数学方程,所以对于那些感兴趣的人,请参考这个不错的帖子。
里脊回归
Ridge 在线性回归的原始损失函数中添加了一个“l2 范数”惩罚项,该惩罚项倾向于将所有变量的系数收缩到某一水*(基于正则化的强度)。代码如下。
**from** **sklearn.linear_model** **import** Ridgemy_alpha = 0.1
my_model = Ridge(alpha = my_alpha)
my_model.fit(X, y)
这里“my_alpha”是提到的强度。my_alpha 越高,正则化越强,模型的方差越低。
套索回归
套索回归的思想类似于岭回归的思想,但是在罚函数中用‘L1 范数’代替‘L2 范数’。
套索和脊之间的这种差异会导致套索可以将系数缩小到 0,而脊则不能。这就是为什么人们也说 LASSO 有做特征选择的能力。代码如下。
**from** **sklearn.linear_model** **import** Lassomy_alpha = 0.1
my_model = Lasso(alpha = my_alpha)
my_model.fit(X, y)
如果 my_alpha 足够大,它会将所有系数收缩为零,这就产生了最有偏差的线性模型。
弹性网
创建弹性网来混合套索和脊,其中惩罚项是 l1 和 l2 范数正则化项的组合。它引入了另一个参数 l1_ratio,以将两个不同的权重分配给 l1 和 l2 范数,其总和为 1。代码如下。
**from** **sklearn.linear_model** **import** ElasticNetmy_alpha = 0.1
my_l1ratio = 0.5
my_model = ElasticNet(alpha = my_alpha, l1_ratio = my_l1ratio)
my_model.fit(X, y)
在实际操作中,最好的 l1_ratio 总是通过交叉验证来调整。
选哪个?脊,套索,还是弹力网?

莎伦·麦卡琴在 Unsplash 上的照片
我的实际建议是总是从弹性网开始。
让我先解释一下弹力网相对于其他方法的缺点。前面提到过,弹性网归纳出一个新的参数 l1_ratio ,无法高效手动赋值。
交叉验证是调整最佳 l1_ratio 最常用的方法。因此,与脊和套索相比,弹性网的计算成本更高。
然而,我想忽略这种计算成本的增加,因为我正在工作的大多数*台都可以轻松处理更复杂的模型,如随机森林和深度神经网络。
当我对数据集有一些预先了解时,我只使用脊或套索。举个例子,如果我知道 X 中的所有特征对预测 Y 都是有用的,那么 Ridge 是首选,因为我不想丢失任何一个变量。如果我知道只有一小部分特征是有用的,我想把它们选出来,那么 LASSO 当然是更好的选择。
然而,根据我的经验,在建模步骤之前,我对数据一无所知。我更关心的是选择一个基于错误假设的模型,而不是花更长的时间来调整我的模型。这就是为什么弹性网总是我在分析中使用的第一个线性模型。
弹性网实现的真实例子

奥雷连·罗曼在 Unsplash 上拍摄的照片
这是我的示例代码,用于分析时间序列数据和驱动变化的因素之间的关系。
from sklearn.impute import SimpleImputer
from sklearn.linear_model import ElasticNet
from sklearn.model_selection import TimeSeriesSplit
from sklearn.pipeline import Pipelinedef train_EN(X,y):
# X are features
# y is output
# set cross-validation
tscv = TimeSeriesSplit(n_splits=10)
data_split = tscv.split(X)
# build a pipeline of pre-processing and elasticNet regression model
my_pipe = Pipeline([
('imputer', SimpleImputer(strategy="median")),
('std_scaler', StandardScaler()),
('en_model', ElasticNet(random_state=42))
]) # parameter space
param_grid_en = {
'en_model__alpha' : [1e-2,1e-1,1,10,100,1000,10000,],
'en_model__l1_ratio' : [0,0.25,0.5,0.75,1]
} # gridsearch for best hyper-parameters
gs_en = GridSearchCV(my_pipe, param_grid=param_grid_en, cv=data_split, scoring='neg_mean_squared_error', n_jobs=-1)
# fit dataset
gs_en.fit(X, y)
预处理(pre_pipeline)分两步完成,缺失值输入和数据规范化。为了超参数的调整( GridSearchCV ),整个训练数据集被分成 10 倍(TimeSeriesSplit(n _ splits = 10))。所选择的最佳模型将是来自超参数空间(param _ grid _ en)的一个 alpha 和一个 l1_ratio 以及特征系数的组合。
外卖
- 当你想对数据进行线性回归时,别忘了应用正则化。
- 始终从弹性网开始。
- 不要忘记调整你的训练数据集中的超参数。
我希望这篇文章对你也有帮助。

格伦·杰克逊在 Unsplash 上拍摄的照片
参考资料:
https://sci kit-learn . org/stable/modules/classes . html # module-sk learn . linear _ model
使用 Python 对随机森林和决策树进行务实的探索
从头开始的两种算法的完整代码实现
简介
不可否认,随机森林是获得大多数结构化数据问题的快速合理解决方案的最佳模型之一。它们能够适应回归和分类问题,能够抵抗过度拟合(有足够的估计量),并且它们能够在没有任何数据标准化或虚拟变量创建的情况下工作。使用这种集成技术你不会得到最好的性能,但是,它们的简单性和在解释我们的数据时的价值使它们非常有用。
基于树的模型在捕捉数据之间的复杂关系方面也很有效,而线性模型则很难捕捉到这种关系,如下例所示:

图一。使用 matplotlib 的判定边界示例。
此外,基于树的方法提供了出色的可解释性和分析功能,有助于解释我们的模型如何得出特定的结果。例如,我们可以将上面使用的单个决策树形象化:

图二。决策树图(sk learn . tree . export _ graphviz)对于图 1 中的例子。
在整篇文章中,我们将详细探索随机森林和决策树——事实上,为了充分理解它们的内部工作方式,我们将完全用 Python 从头开始编码。这篇文章补充了这里提供的 Jupyter 笔记本,我建议你在阅读时打开它。这提供了本文中使用的所有代码和示例。
形成随机森林模型的关键是决策树——我们将它们中的许多组合在一起以获得更好的整体性能。单个树的方差很大,但我们通过对许多树进行*均,显著降低了方差,同时提高了预测性能。

图 3。随机森林算法概述。作者图解。
让我们举一个例子——一个有 6 个独立评估者(决策树)的随机森林将形成总共 6 个独立的决策树模型。如果我们使用鱼市场 Kaggle 数据集作为例子,每个单独的决策树产生以下回归线:

图 4。随机森林模型中的个体决策树回归器。
我们的随机森林采用这些单独的预测,并对它们进行*均,从而生成总体上更好的拟合回归线:

图 5。组合之前显示的决策树后的整体随机森林预测。
您会注意到,与任何单个决策树相比,随机森林模型的预测更好。这可以从更优的回归线和更高的 R 值看出来。这就是合奏的好处;模型的组合通常会比任何一个单独的模型产生更好的性能。
如果我们只是将许多决策树结合在一起,我们就有了一个 bagging 模型。对于随机森林,有一个关键的区别; 去相关 。随机森林不是每次在树中进行分割时都使用我们所有的特征(数据列),而是只考虑这些特征的随机比例。这防止了一个或两个主要特征使所有的单个树相似地相关。与 bagging 模型相比,这减少了模型差异。
总的来说,随机森林算法执行以下操作:
- 从训练数据中创建 n 个引导样本,用于训练 n 个决策树。自举样本是原始训练数据的随机样本,带有替换,这意味着我们有一些副本(也有完全缺失的样本,称为 out-of-bag)。
- 使用 n 个引导样本生长 n 个决策树。
- 对于单个树中的每个分割,随机选择一个要素样本,并仅使用这些列选择最佳分割。进行这种分割的选择基于所使用的目标函数(例如熵、基尼指数、分类误差、均方误差)。
- 将我们的结果汇总在一起,形成一个总体预测。对于回归,这通常是*均值。对于分类,这通常是通过多数表决。
在这个博客中,我们将创建两个类。一个将是决策树模型,而另一个将是随机森林。随机森林模型将通过形成大量单个决策树模型并聚合它们的单个预测来形成整体预测输出。如前所述,与本文相关的所有代码都可以在本笔记本中找到,所以如果您还没有找到,请查看一下!
1.Python 决策树模型
我们将从创建一个单独的决策树开始。在此之前,快速了解一下决策树的基础知识。
1.1。决策树理论
决策树进行一系列贪婪递归二分分裂,每一次分裂都是基于信息增益的目标函数来计算的。对于分类树,常用的目标函数包括基尼指数、熵和分类误差:

图 6。分类树的信息增益目标。作者图解。
对于回归树,常见的目标函数包括均方误差(MSE)、*均绝对误差(MAE)或标准差。

图七。回归树的信息增益目标。作者图解。
对于这个博客,我们将使用 标准差缩减 来构建一个回归模型。该函数给出的结果相当于 MSE:

方程式 1。标准差。
方便的是,这个公式可以重新排列成更好的形式,用于 Python 和 Numpy 矢量化计算:

方程式 2。将标准差公式处理为*方和减去均方。
这种推导允许我们用均方和的*方根减去均方来确定标准差。听起来很拗口——但本质上,这使得我们的 Python 实现在 O(n)复杂度方面更快更有效。
该公式(或上述任何标准)用于形成成本函数,J,其在训练期间最小化。用于执行拆分的决策树算法称为分类和回归树(CART)算法 (Géron,2019,第 179 页),它使用以下成本函数:

方程式 3。决策树递归二叉分裂的 CART 算法损失函数。
这被递归地应用于每个单独的分割,直到达到最大深度。决策树模型最难的概念之一是理解递归是如何工作的。我们的树模型将在每个生成的树模型中被多次调用。每个树节点执行一个二叉分裂(除非它是一个叶子),这意味着每个节点创建两个分裂(左和右)。每次拆分都会创建一个新的决策树,反过来,每个新的决策树会执行进一步的左右拆分。这个过程一直重复,直到我们的决策树有足够的深度。
基本上,我们为每个随机的森林决策树形成许多树中的树,并且这继续直到我们到达所有左右分裂的叶节点。
最大深度的选择非常重要,它会显著影响我们的模型对数据的拟合不足或过度拟合。例如,我们可以在下面的图中看到它对鱼市场数据的拟合度的影响:

图 8。改变树的最大深度的影响。
现在我们已经讨论了基础知识,让我们继续讨论将决策树模型实现为代码的实际元素。
1.2.决策树 Python 代码
在形成这个模型的同时,大量的信用需要去杰瑞米·霍华德和 FastAI 程序员机器学习课程。本课程构建了一个基本的随机森林和决策树模型,这是我的 Python 实现的主要基础。
我们将首先展示决策树的全部代码,然后依次讨论主要方面。
代码示例 1。决策树模型的 Python 实现。
让我们开始吧,首先,我们需要用所需的参数初始化决策树,包括:
- 训练数据( X )。这将是总训练数据的行样本,行数等于所选的随机林样本大小。
- 给定训练数据 x 的训练标签( y )
- 我们的训练数据和标签的索引值( idxs )。如果我们只想使用 x 的特定索引,这可能是必需的。默认情况下,这是“无”,并将创建新的索引,最多可达定型数据 x 中的行数。
- 每个决策树的样本大小。
- 在每个二进制分割中使用的特征比例( feat_proportion )
- 停止进一步分裂并使该节点成为叶节点的样本数( min_leaf
- Bootstrap,它使我们的模型形成随机样本,并替换我们的每个决策树。如果选择此项,我们的模型将能够计算出出出袋分数。
- 形成模型时,随机种子允许可重复产生的结果。
1.3 二进制拆分
当我们形成每一个决策树时,我们希望它立即开始二分分裂。这是通过调用类 init 方法中的 self.binary_split() 来实现的,如上所示。
这个函数的目的是遍历我们选择的特性列,并在每一列中找到最佳的二进制拆分。上面的代码使用后续函数 best_binary_split,找到给定列的最佳拆分,该函数针对每个特性被迭代调用。
该模型对所有列执行此操作,并为拆分找到最佳得分。这为我们提供了最佳的特征和索引值,在该值处找到了数据样本的最佳左右分割。例如,这将为我们提供一个鱼市场数据分割,如下所示:

图 9。鱼类市场数据的初始二进制分割。
以上,宽度小于或等于(≤) 5.167 的所有数据样本进行第一次分割,而剩余样本形成另一次分割。我们可以看到,81 个样本的宽度≤ 5.167,38 个样本的宽度> 5.167。因此,在这种情况下,我们的模型选择宽度作为进行分割的最佳特征,这是使用我们的标准差成本函数推导出来的。
然后,我们使用更多的决策树形成进一步的分割,以重复相同的过程(除了较小的数据子集):

图 10。跟进鱼市场数据的每条路径上的二进制拆分。
正如我们所见,“长度 3”被选为每种情况下进行后续分割的最佳特征。我们将简要讨论如何在代码实现中做到这一点。
def best_binary_split(self, feat_idx):
x = self.x.values[self.idxs, feat_idx]
y = self.y[self.idxs] # sort our data
sorted_ind = np.argsort(x)
sorted_x = x[sorted_ind]
sorted_y = y[sorted_ind] # get count, sum and square sum of lhs and rhs
lhs_count = 0
rhs_count = self.rows
lhs_sum = 0.0
rhs_sum = sorted_y.sum()
lhs_sum2 = 0.0
rhs_sum2 = np.square(sorted_y).sum() # iterate through all values of selected feature - eval score
for i in range(0, self.rows - self.min_leaf):
...
在 best_binary_split 函数中,我们首先对训练数据 x 进行排序,并输出标签 y 。传递给函数 feat_idx 的参数对应于当前列的索引(记住这个函数是对所有列迭代完成的)。
然后,我们为当前列的数据左右拆分的计数、总和以及*方和形成初始变量。这个想法是我们从左边的 0 开始,从右边的最大值(行数)开始。当我们遍历列数据的每一行时,我们可以动态更新这些值,如下所示:
# iterate through all rows of selected feature
for i in range(0, self.rows - self.min_leaf):
# update count and sums
lhs_count += 1
rhs_count -= 1
lhs_sum += y_i
rhs_sum -= y_i
lhs_sum2 += y_i**2
rhs_sum2 -= y_i**2
在这个值更新之后,我们在继续下一步之前为每个迭代执行两个基本的检查。第一个是我们的左分裂当前是否比在 min_leaf 超参数中选择的样本少。第二个是我们是否有一个当前值与下一个匹配(重复)。在这两种情况下,我们跳过当前迭代,进入下一个迭代:
# if less than min leaf or dup value - skip
if i < self.min_leaf - 1 or x_i == sorted_x[i + 1]:
continue
现在,我们执行主要功能—使用标准差成本函数查找当前得分:
# find standard deviations of left and right sides
lhs_std = self.standard_deviation(lhs_count, lhs_sum, lhs_sum2)
rhs_std = self.standard_deviation(rhs_count, rhs_sum, rhs_sum2)
我们需要找到左右劈叉的分数。这是使用前面定义的公式计算出来的,但是对 python 实现的概括如下:

代码示例 2。标准差的 Python 实现。
一旦我们计算出每个分数,我们需要形成一个加权成本函数,就像前面等式 3 中定义的那样。我们可以通过多种方式做到这一点,但一种简单的方式是只使用当前的左侧和右侧计数,并将它们乘以各自的标准偏差分数:
# find weighted score
current_score = (lhs_count*lhs_std) + (rhs_count*rhs_std)
# if score lower (better) than previous, update
if current_score < self.score:
self.feat_idx = feat_idx
self.score = current_score
self.split = x_i
最后,在这样做之后,我们检查这次迭代的当前分数是否比以前的最好分数更好。因为这是一个成本函数,最好的分数是最低的值,所以我们寻求最小化它。如果我们找到更好的分数,我们将当前特征索引(feat_idx)、分数和样本索引(x_i)保存到我们的决策树模型中。
一旦对我们的所有特征发生了这种迭代过程(如从原始函数 binary_split 调用的),我们就获得对应于最佳得分的数据的左和右分割,并为每个分割形成新的决策树。整个过程递归重复,直到原始数据的所有分割都成为叶节点。
为了更好地理解这一点,让我们快速回顾一下整个 binary_split 函数:

代码示例 3。我们决策树模型的二元分裂函数。
我们从仅选择特征的子样本开始,以迭代地搜索最佳二进制分裂。这是为了在整个随机森林模型中去相关我们的大量决策树(稍后将详细介绍)。我们对每个特性反复调用 best_binary_split ,更新 self.score、self.feat_idx 和 self.split 中的值
如果 self.score 中的分数等于无穷大,那么我们知道我们当前处于一个叶节点,因此想要停止这个节点上的递归过程。这是通过从函数返回来完成的。然而,如果它不是叶节点,我们继续并为找到的最佳左右分裂形成新的决策树。我们将这些新的决策树作为变量存储在当前决策树中,作为 self.left_split 和 self.right_split,,随后对其中的每一个重复相同的递归过程,直到到达叶节点。
二进制拆分过程到此结束!你会很感激地知道,这是迄今为止理解决策树如何工作最困难的方面,其他一切都相对简单。
1.4 预测
为了使用我们的模型对样本值进行预测,我们需要递归地将该值与模型中的树分裂值进行比较。在下图中,我们可以看到样本在预测阶段的典型路径。

图 11。给定样本的预测过程。作者图解。
在上面的表示中,样本宽度和长度 3 特征与我们的决策树模型的分割标准进行了比较。通过红色箭头,我们得到了该样本的预测值,即重量为 42.15(以绿色突出显示)。这个预测值是通过简单地找到这个叶节点中所有 22 个样本的*均权重而获得的。
为了使用代码实现这一点,我们使用了两个函数:

代码示例 4。为我们的决策树模型预测函数。
第一个函数( predict )使用列表理解迭代调用第二个函数( predict_sample )。它这样做是为了给一个输入数组 x 生成一组预测。
第二个函数更详细,通过树分裂递归调用,直到到达一个叶节点。我们首先检查我们是否处于一个叶节点,如果是,那么预测值就是该叶中样本的*均值,等于 self.val 。
相反,如果它还不是叶节点,我们将预测样本与该节点的特征分裂值进行比较。如果predict _ sample≤split _ value,那么我们继续进行左分裂,否则我们选择右分裂。然后,我们重复这个过程,直到到达一个叶节点,以便进行预测。
2.实现随机森林
幸运的是,随机森林的实现更短,也更容易。它作为一个更高层次的类,实例化了大量的决策树。
2.1 随机森林 Python 代码
我们将从查看代码开始,然后讨论关键特性。
代码示例 5。随机森林模型的 Python 实现。
与决策树代码相比,随机森林模型实际上非常简单。为了实例化模型,我们采用一系列参数:
- 培训数据(X)
- 培训标签(y)
- 决策树的数量(num_trees)
- 每个决策树的样本大小
- 在每个二进制分割中使用的功能比例(功能比例)
- 停止进一步分裂并使该节点成为叶节点的样本数(min_leaf)
- Bootstrap,它使我们的模型形成随机样本,并替换我们的每个决策树。如果选择此项,我们的模型将能够计算出出出袋分数。
- 形成模型时,随机种子允许可重复产生的结果。
一旦我们的模型被初始化,它就创建数量等于 num_trees 的决策树,并将它们存储为 self.trees :
self.trees = [self.create_tree() for i in range(num_trees)]
这总共调用了我们的 create_tree 方法 num_tree 次,其中 create_tree 方法给出为:

代码示例 6。为我们的随机森林模型创建树函数。
这将生成一组大小为 sample_size 的随机索引,表示用于决策树模型的数据样本。假设我们的总训练集比我们的样本量大得多,那么每次调用这个函数时,它都会为每个决策树产生一个唯一的样本集。
此外,如果我们已经用 bootstrap=True 实例化了我们的随机森林,那么这个函数将生成带有替换的训练样本集。这将在后面详细解释。
最后,我们为给定的训练样本和标签集实例化一个决策树。我们还向每个决策树传递一些进一步的参数,包括:
- 在每个二进制分割中使用的特征比例( feat_proportion ),在第 3.2 节中解释。
- 出袋指数(oob_idxs),用于记录每个决策树引导样本的出袋样本。这将在下文第 3.3 节中进一步解释。
为了进行预测,我们有预测函数,它很简单:

代码示例 7。我们的随机森林模型的预测函数。
我们将输入预测样本传递给随机森林模型中的每个决策树预测函数。这将给我们一组与每个决策树的预测相对应的值。为了形成我们的总体随机森林预测,我们只需计算这些值的*均值。
这就结束了我们模型的主要部分,然而,与随机森林相关的一些关键点以及它们与上述代码的关系仍然需要解释。这些将在剩余的章节中讨论。
2.2 选择特征子集
随机森林通过在每次二进制分裂时选择一个随机特征子集来消除其决策树的相似性。这是随机森林的一个绝对必要的组成部分,也是它不同于基本装袋模型的地方。
要在 Python 中实现这一点,我们需要做的就是确保每次在决策树中执行二分分裂时,我们只选择一部分特征,而不是考虑所有的特征。
# randomly select sub-sample of feature indices to use
num_feat = int(np.ceil(self.cols*self.feat_proportion))
col_idxs = range(self.cols)
feature_subset = np.random.permutation(col_idxs)[:num_feat]
# iteratively split each col and find best
for i in feature_subset:
self.best_binary_split(i)
这是使用传递给决策树的 feat_proportion 参数来执行的,如上面的 create_tree 代码所示。
2.3 自举样本
Bootstrapping 是从一组数据中随机抽取数据进行替换的过程。这意味着我们会有重复的,也有一些样本根本不包括在每个样本中。
未包含在每个引导样本中的样本称为开箱(OOB)样本。
例如,假设我们想要从 500 个训练样本的范围中形成 500 个样本大小,那么我们可以使用以下公式选择 500 个随机指数:
samples = np.random.randint(0, 500, size=500)
对于这些样本,并不是所有的 500 个原始索引都存在,因为许多索引是重复的。我们可以找到不包括在内的样品(开箱),如下所示:
indices = np.arange(500)
oob_samples = np.array([x for x in indices if x not in samples])
出于兴趣,如果我们从 500 个训练样本的数据集形成 500 个引导样本,让我们看看*均得到多少个 OOB 样本:
oob_no = []for _ in range(500):
samples = np.random.randint(0, 500, size=500)
oob_samples = [x for x in indices if x not in samples]
oob_no.append(len(oob_samples))
sns.distplot(oob_no)
plt.title("OOB samples - mean size of {0}".format(np.mean(oob_no)))
plt.show()

图 12。开箱(OOB)样品示例。
如图所示,对于 500 人的训练集,我们的*均 OOB 样本量约为 183。这意味着对于我们创建的每个自举样本,我们有大约 183 个看不见的样本可以用来测试我们形成的树模型的性能。
对于我们的随机森林模型,我们通过包含一个函数来随机采样选定数量的样本(带替换)来支持自举。

代码示例 8。返回引导样本的自定义功能。
您会注意到,该函数需要一个“idxs”参数,这是从中选择引导样本的训练索引值的范围。我们已经包括这一点,以便我们的模型与选定的样本大小成比例地工作。如果我们不包括这一点,当使用大数据集和小样本量(数据集大小>>样本大小)时,我们的自举样本包含重复项的概率将非常低。在这种情况下,我们的 OOB 样本变得更加难以管理,这是我们在上面的代码中采用的方法所避免的。
有了创建 OOB 的自举样本的函数,我们需要做的就是在每个决策树初始化之前调用它:

代码示例 9。为我们的随机森林模型创建树函数。
如图所示,如果我们已经用 bootstrap=True 初始化了我们的随机森林模型,我们仅获得自举样本和 OOB 样本。在初始化每个决策树之后,我们通过将(数据集 x 的)原始索引值存储在名为“ oob_idxs ”的属性中来跟踪哪些 OOB 样本被分配给它。正如您接下来将看到的,这允许我们确定每个决策树的 OOB 分数,从而计算出总体*均 OOB 分数。
2.4 找到每棵树和我们的整体模型的 OOB 分数
有了之前进行的基础工作,为我们的模型找到 OOB 分数并不太困难。我们所要做的就是遍历每个决策树,对相关的 OOB 样本进行预测,然后与实际的 y 标签进行比较,计算出我们的分数。

代码示例 10。查找袋外(OOB)分数的定制功能。
在这个例子中,我们使用了 R2 分数,但是你可以使用任何你喜欢的度量标准。这将最终取决于我们正在做的任务的性质,例如回归或分类。
注意,我们按顺序遍历每棵树,只计算该树的 OOB 样本的预测,然后找到相关的 R 值。然后,我们将这个分数附加到我们的 tree_oob_scores 数组中,这样我们就可以找到所有决策树的总体*均 oob 分数——这对应于我们的随机森林 OOB 分数。
2.5 在我们的模型中寻找特征的重要性
最后一个值得一提的随机森林特性是计算特性重要性的能力。我们可以用多种方式对这个特性的重要性进行分级。流行的方法(Scikit-Learn 使用)是测量森林中所有树木的某个特征*均减少杂质的程度。对于我们的模型,这相当于测量*均每个特征在所有树模型中降低标准偏差成本函数的强度。

图十三。鱼类市场数据的特征重要性。
另一种计算重要性的方法,正如在 FastAI 面向程序员的机器学习课程中所强调的,是随机打乱每个特性列,并测量它对评估分数的影响程度。这是在数据集上训练模型之后完成的,并且一次对每个特征执行一次,以便比较它降低(甚至提高)评估分数的程度。那些引起最大下降的特征代表最重要的,而那些影响最小的特征是最不重要的。
对于我们的模型,我们使用后一种方法实现了特性重要性:

代码示例 11。用于查找特征重要性的自定义随机森林函数。
我们首先使用原始数据找到一个基线 R2 分数,然后迭代地分别洗牌并找到分数变化的结果。在任一时刻,只有一个特征列被随机打乱;所有其他列都保持其原始的非混洗状态。我们通过将这些重要性形成一个数据帧来结束这个函数,并且为了方便起见,将这个数据帧按照重要性排序后返回。
通过在我们的随机森林实例上调用这个函数,我们可以很容易地绘制出我们的相对特性重要性,如下所示:
feature_importances = random_forest.feature_importances()
feature_importances.plot.bar()
这给了我们一个很好的重要性展示,就像这样:

图 14。使用我们的自定义函数显示鱼市场数据的重要性。
瞧啊。我特别喜欢这种方法,因为这是一种不太复杂、同样有效的计算数据集特征重要性的方法。然而,这依赖于使用一个好的、有代表性的数据集来获得这些重要性,否则我们的结果将是不可靠的。还应该注意的是,由于它使用了不同的方法,它可能会给出与通过 Scikit-Learn 随机森林模型获得的结果略有不同的结果。
现在完成了……这基本上包含了我们需要在本文中讨论的所有内容。你可以用随机森林做很多其他的事情,但是我认为我们已经设法抓住了本质!我希望你喜欢它!
结论
正如我们在本文中所看到的,尽管随机森林和决策树在概念上很简单,但是仍然很难用完整的代码实现和要点来解释它们。尽管这个模型决不是专业的随机森林模型的替代品,但它应该作为一个有用的学习模型。毫无疑问,我们的模型存在许多潜在的低效和用例问题,但是对于理解随机森林来说,这已经足够了!
希望你已经喜欢了这些内容,并且在这个过程中设法学习或修改了关键概念。就像神经网络和其他机器学习算法一样,您永远也不需要从头开始实际实现随机森林或决策树。然而,对基本概念的深刻理解对在实践中使用这些工具有很大帮助,更重要的是,它帮助您获得解释和调整超参数的技能,以最适合您自己的项目。
关于本文中所有内容的完整代码实现,你可以在我的 GitHub repo 这里找到。
解释混淆矩阵的初级读本

亨利&公司在 Unsplash 上拍摄的照片
以我的猫为特色!
在我的上一篇文章中,我谈到了混淆矩阵及其在帮助我们确定模型准确性方面的重要性。本周我们将看看混淆矩阵的基本结构,以及它们如何帮助我们确定模型的准确性。
让我们从头开始…
正如我在上一篇文章中提到的,混淆矩阵归功于 1904 年的卡尔·皮尔逊,尽管对他来说这是列联表。它们在统计分类和机器学习中很受欢迎,使我们能够直观地表示分类器的性能。混淆矩阵是一种列联表,用于测量真阳性、假阳性、真阴性和假阴性的比率。下面是一个简单的例子:

看起来不太妙,是吧?嗯,它不是,但它充满了有用的信息,告诉我们我们的机器学习模型在分类方面表现如何……是否有猫。真正有用的东西。那么我们如何解读这些数据呢?好吧,让我们看看每个类别对我们意味着什么。

以上,你看到了每一类背后的真谛。在积极的预测和积极的实际相遇的地方,我们有一个真正的积极。在消极的预测和消极的实际相遇的地方,我们有一个真正的消极。这意味着在前者中,一只猫被预言,而图像本身就是一只猫。在后者中,图像被识别为不是猫,而实际图像本身也不是猫。由于我们每天与医学和一些不良医学电视的互动,许多人都知道术语“假阳性”对于那些有点困惑的人来说,这意味着在这种情况下,我们的机器根据实际上不是猫的图像来预测猫。假阴性意味着是猫的图像被预测为不是猫。这是一次通过的情况:

左上:凯文(两次乳腺癌幸存者),右上:塞斯(瑞普好朋友)
现在我们理解了这些类别,我们可以回头看看我们最初的混淆矩阵,这些数字更有意义。我们的混淆矩阵告诉我们,在这次初始运行中,5 张猫图片被准确分类,10 张被错误分类,4 张非猫图片被错误分类为猫,6 张非猫图片被正确分类为非猫。这表明我们的模型还不太擅长识别猫的图像。
混淆矩阵的度量
现在,正如你可能意识到的,一些数学家不能就这么离开。这里我们有一个清晰易读的混淆矩阵,它告诉我们模型的表现有多好。但是为了简洁,易读性和可解释性可能会半途而废。毕竟,如果我们要对我们的模型进行演示,我们不能只显示一个又一个混淆矩阵。有些人就是希望那些硬性的数字来决定成功。这就是我们确定混淆矩阵成功与否的标准。
输入我们的 4 个测试指标:准确度、精确度、召回率和 F1。我不打算在这里做太多的细节,但是我会列出每一个的功能。
准确率:准确率可以用下面的公式简单计算:
准确率=(真阳性+真阴性/总预测) 100%*
这是一个简单的度量,但并不总是最好的。客观地说,准确性衡量的是正确的猫+正确的没有猫划分的图像的总数。
Precision : Precision 表示我们的模型预测为阳性的图像实际上是阳性的图像的比例,可以通过下面的公式计算:
Precision =(真阳性)/(真阳性+假阳性) 从这个角度来看,Precision 测量识别为 Cat 的图像中,有多少实际上是 Cat?
召回:召回测试我们的模型从所有正面预测中找出正确预测的能力。使用以下公式计算:
回忆=(真阳性)/(真阳性+假阴性) 为了正确地看待这个问题,回忆实际上是 Cat 的图像的措施,有多少被准确地预测为 Cat?
F1 得分 : F1 得分是准确率和召回率的加权*均值,考虑了误报和漏报。这可以使它比准确性更有效,特别是当我们有不*衡的类或多个类时。下面是公式:
F1 = 2(精度召回)/(召回+精度)) F1 评分背后的思路是*衡精度和召回背后的顾虑。由于两者都是相关的指标,F1 让我们能够合并两个分数。
现实世界应用
现在我们知道了一些混淆矩阵的基本知识以及如何测量它们,让我们用这些知识来研究一下现实生活中的混淆矩阵。我将使用我的威士忌项目中的一些旧的混淆矩阵,因为我懒得去挖掘旧的或者做一个新的。这会有点复杂,但请耐心听我说,因为我会尽量让它简单易懂。

观察我们的 KNN 分类器的混淆矩阵。它在苏格兰威士忌的分类方面做得非常出色。这种特殊的分类在许多方面都是独一无二的。首先,它是多等级的,因为威士忌有许多国家。第二,有一个主要的阶级不*衡,我们用我们的训练假人来补偿。但在一天结束时,仍然有许多威士忌和苏格兰威士忌的风味特征随处可见。
正如你在分类报告中看到的,这个模型对苏格兰威士忌有很好的精确度,对波旁威士忌有几乎不可能的精确度。如果我们还记得精度的定义,我们会记得精度就是预测值与实际值的比率。我们可以看到,在苏格兰一栏中,虽然 KNN 在 164 种苏格兰威士忌中答对了 140 种,但它还包括 4 种波旁威士忌、5 种加拿大威士忌、6 种爱尔兰威士忌、4 种日本威士忌和 17 种世界威士忌。如果我们计算一下,我们得到的精度分数是 0.80。
回想一下,在 164 个苏格兰人中,KNN 答对了 140 个,但这次我们将移过矩阵,以解决假阴性问题!我们可以看到 KNN 分类器认为 23 个苏格兰人是加拿大人,1 个苏格兰人是爱尔兰人。如果我们对它们进行计算,我们会得到 0.82 的分数。很自然,因为 F1 是这两者的*均值,我们知道我们的 F1 分数是 0.81。
如果我们想对苏格兰威士忌进行分类,这个模型会很棒。不幸的是,当我们在国家列表中往下看时,我们看到一些非常糟糕的分数。数据科学家通常会在这里评估他们构建这些模型的目标。KNN 似乎非常擅长对苏格兰人进行分类,但如果我只想对苏格兰人进行分类,我为什么要费心去做这些其他国家的分类呢?不,根据真阳性和假阴性的分布,结合我们计算的指标,KNN 不是一个伟大的威士忌分类器。
关于多类混淆矩阵的一个注记
你们中的一些人可能已经看到了多类混淆矩阵,并认为,你是怎么看出来的?真阳性,真阴性,甚至假阳性在哪里??好吧,即使我们没有标记所有的东西,我们只需要记住所有东西的相对位置。让我们来看一个混淆矩阵的例子,好吗?

关键:绿色-真阳性,紫色-假阴性,蓝色-假阳性,红色-真阴性
这是一个混乱矩阵,表示猫、狗和老鼠的分类。如果我们想要计算我们的模型对猫进行分类的能力的精确度或召回率,我们将通过以下组来组织我们的混淆矩阵。
绿色方框代表真阳性。卡特彼勒预测值和实际值。
红框代表真阴性,这些与 Cat 预测或 Cat 实际无关,所以我们知道图像被正确预测为非 Cat
蓝框代表假阳性。真正的狗或老鼠,但被归类为猫。
紫色方框代表假阴性。被归类为狗或老鼠的真正的猫。
所以对于猫,我们知道如下:
真阳性: 8
真阴性:6+5+5+3 = 19
假阳性:1 + 5 = 6
假阴性:7 + 2 = 9
了解了这些,我们就可以开始计算准确度、精确度、召回率和 F1 分数了。同样的移位和分离可以对狗和老鼠进行,以计算它们的分数。
结论
我希望这篇关于混淆矩阵的简介对你们有所帮助。当我第一次开始使用机器学习的时候,我发现它们有点…令人困惑,因为没有更好的词。了解来龙去脉并学会解释它们将有助于您理解模型中发生的事情,进而有助于您成为更好的数据科学家。
生成语音模型初级读本
现在,通过机器学习,音频生成成为可能。学习基础知识开始。

杰森·罗斯韦尔在 Unsplash 上的照片
C 尖端的机器学习模型和技术已经允许创建几乎任何类型的内容,从图像到视频到声音。这些生成技术允许前所未见的多媒体媒体的创建和操作类型。从技术的角度来看,接下来的过程只是训练一个数学模型来接受输入类型(文本、面部、图像)并输出任何期望的类型(声音、新面部、新图像)。可以用这种方式编译的任何类型的数据都可以用来构建生成模型。
生成模型的一种强大用例是基于任何文本集生成语音选择音频。这项技术有着广泛的应用,从逼真的聊天机器人到书籍、电影和其他媒体的可调叙述。就模型架构而言,这种技术利用了几种不同类型的生成网络。为了理解这些模型是如何组合在一起的,首先要理解声音和声音文件。
我们听到的任何声音或虚拟声音片段都可以概括为一组采样率间隔的振幅值。这产生的波型的位置是在任何给定的时间听到的声音,因为它振动耳朵内的敏感毛发。振幅的振荡产生了整体波的频率,这反过来又产生了我们从任何声音中听到的独特音调。另一方面,振幅提供了任何时候振动的大小。振幅模式产生频率和音量,然后被听者听到,就像他们知道的声音一样。

吓人的傅立叶变换方程(来源)
可以对任何波执行傅立叶变换,以找到随时间变化的频谱图或频率密度。这种分析有助于显示什么类型的频率导致已知的声音。虽然这是整个波的导数,但是声谱图不能用于实际产生声音,因为此时波型是未知的。总的来说,这创造了一种动态,其中独特的声音通过频谱图被最好地创造出来,但只有转换回基于振幅的波才能被听到。没有反向 FFT,这为人工智能和机器学习创造了一个诱人的预测任务。

波形(上)和转换后的频谱图(下)(来源: MindBuilder AI Research)
有了这些知识,很明显,使用生成模型获取文本并将其转换为声音的最佳方式是构建:
文本— >声谱图关系,并训练一个模型来执行这个。
事实仍然是声谱图不能产生实际的声音。为了实现这一点,可以利用另一个生成模型来创建:声谱图— >波转换。
这两种类型的模型都经过了大量的研究,并且都有当前最先进的方法。对于文本->声谱图,存在 Tacotron2 模型架构,同样,对于声谱图- >波/声音,存在 W avenet 架构。通过将这些网络组合在一起,就可以实现将文本转换成声音的目标。

实现这个管道是为了从简单的文本生成语音。在这个总图中,我们的实现对绿色部分使用了经过训练的编码器网络,对合成器部分使用了 Tacotron2,对声码器部分使用了 WaveNet,以最终产生波形。
实时语音克隆 Github 库已经建立了实现两个网络的函数,并创建了 5 秒或更长的声音。由于从零开始积累数据以训练这种模型的困难(需要毫秒文本-声谱图数据),储存库向预训练的模型提供基于新声音进行微调的方法。这是通过利用音频库来扫描音频并创建所提供语音的权重嵌入来实现的,该权重嵌入被应用于 Tacotron2 预训练模型以生成所提供语音特有的频谱图。接下来,Wavenet 是一个通用模型,它简单地将频谱图转换为波/振幅数据。然后可以将该幅度数据转换为。wav 格式,利用存储库中包含的内置 python 库。在 demo_cli.py 中提供了该过程的演练,只需用户提供一个音频文件和文本即可生成任何句子。
最后,该模型可用于将原始文本作为输入,并生成频率与任何源音频文件相似的声谱图。如上所述,最后一步是使用 WaveNet 从声谱图到波形生成可用的音频。幸运的是,这是一个跨扬声器的通用转换,因此不需要特定的培训来产生波形。这部分使用了 Nvidia 预先训练好的模型。最终产品是一个从波形生成的. wav 文件,其声音非常类似于有声读物的声音。

图:具有深度 TacoTron 2 单元的端到端架构(来源)
为了将该体系结构带到生产系统以反映任何提供的语音,不需要在每次运行时都提供音频文件,因为只要语音不需要改变,嵌入就可以简单地保存并永久应用到 Tacotron 模型。Github repo 中的代码将显示用 Tacotron 生成声谱图的方法只需要朗读文本和嵌入。记住这一点,每次保存并简单地传递相同的嵌入是有意义的。这可以作为从 API 接收的文本的入口点。下一步可以按照 GitHub 演示流程,将生成的声谱图传递给波形生成函数。最后。wav 文件将保存到文件系统中,并带有一个指向 API 返回的资源的链接,或者如果进行了配置,可以直接从 API 返回。
该处理流程允许基于一次训练来生成语音,以创建嵌入。接下来,API 可以集成到任何接收文本输入和需要音频的地方。这种灵活的模型也可以用来创建不同声音的切换嵌入。
在未来,这项技术将为娱乐、通信和移动带来许多新的机会。随着越来越多的开发人员继续实现和调整这些架构,所生成内容的准确性和真实性将会继续提高。一个我们可以实现虚拟版自己的世界可能不远了!
在https://www.mindbuilderai.com看看我目前在做什么
参考文献
[1]https://en . Wikipedia . org/wiki/File:Fourier _ transform _ equation . png
[2]https://github.com/NVIDIA/tacotron2
[3]https://arxiv.org/pdf/1609.03499.pdf
[4]https://arxiv.org/pdf/1806.04558.pdf
[5]https://github.com/CorentinJ/Real-Time-Voice-Cloning
异常检测入门:机器学习的隐藏面

来源: Pixabay
一项困难且通常无人知晓的任务
异常不断地进入数据,识别它们非常重要。无论是黑客攻击还是巨魔攻击,允许异常出现并运行而不被注意或忽略都将是致命的。然而,不幸的是,许多数据科学课程没有深入探讨算法在异常检测中的应用。机器学习的这一面特别没意思,因为没有监督或非监督解决方案的确定方法(见半监督学习);相反,有各种创造性的技术和方法从许多角度来解决这个问题。
异常有许多类型,但一般来说,大多数可以分为四类:
- 点异常。如果一个数据点离其余数据点太远,这就是点异常。例如,当您通常只进行 10-100 美元的交易时,考虑从您的银行账户中进行 10,000 美元的交易。这也称为附加异常值。
- 语境异常。如果一个事件在特定的语境中是不寻常的,那么它就是语境异常。例如,在炎热的和寒冷的月份,冰淇淋的销量保持不变。
- 集体异常。集体异常表示关于数据集的一组异常,而不是单个对象。例如,考虑心电图中的一系列中断的节律。
- 时间异常。暂时异常是指用户数量在短时间内接*零或非常低。举例来说,这可能是服务器停机的结果。
由于一个特殊的原因,发现数据中的异常是一项特别困难的任务:决定阈值是困难的。特别是在高维数据中,当难以可视化数据时,很难决定离群点边界的宽松程度。客观地说,不可能定义什么是“离群值”。因为它的定义非常依赖于上下文,所以这是一项非常困难的任务,需要对数据非常熟悉和理解。
异常检测有各种算法和技术。
用于异常检测的 KNN是 K-最*邻算法的再利用,该算法通过根据欧几里德距离聚集 K-最*邻的类来确定邻居的类。KNN 算法不仅仅限于预测数据点的组或值,还可以用于检测异常。因为 KNN 试图对数据中的潜在关系进行细微的归纳(随着 k 的增加而增加),预测中的错误是数据点可能不符合整体趋势的迹象。使用这种方法,任何使用预测模型的算法都可以用来检测异常。理论上,任何异常的数据点都会降低模型的预测能力。使用这些标签,可以训练另一个 KNN 模型来严格识别异常/非异常。这种方法可以与其他预测方法一起使用,在某种意义上,这是一种半监督方法。
局部异常因子是一种基于密度的异常检测算法。使用 k 个最*邻居之间的欧几里德距离,可以估计局部密度。局部异常值因子将一个项目的局部密度与其相邻项目的局部密度进行比较,从而确定密度相似的区域以及密度远低于其相邻项目(异常值)的其他项目。LOF 依赖的观点是,离群点周围的密度与其邻居周围的密度有很大不同。本地离群因子是基于一个项目的本地可达性密度和它的 k 最*邻居的*均比率来计算的。虽然这是一种基于最*邻的方法,但它是不受监督的,并且不需要任何标签。
隔离森林试图通过随机选择一个特征并在最大值和最小值之间的某个分割值处随机分割该特征来隔离观察值。该算法基于这样一种想法,即隔离异常更容易,因为只需要很少的条件就可以从正常观察中分离出案例。另一方面,隔离一个正常的观察需要更多的条件。因此,异常分数可以计算为分离观察所需的条件的数量。

作者图文。
该算法首先通过创建几个隔离树(随机决策树)来构造分离,计算路径长度来隔离每个观察值。因为该方法依赖于随机性,所以 bagging 是通过聚合许多隔离树的结果来实现的。隔离森林是一个聪明的方法,它依赖于一个沉重的假设,根据上下文的不同,这个假设可能有不同程度的真实性。
时间序列异常检测是一种检测时间序列或一段时间内数值异常的方法。在训练一个时间序列模型——无论是 ARIMA(自回归综合移动*均)还是 RNN(递归神经网络)——之后,它将能够根据看不见的数据进行预测。与预测值显著不同的点(高残差)可被标记为异常。使用这种方法时一定要小心:时间序列预测因无法捕捉外部信号而臭名昭著,这些信号经常决定时间序列的值(例如,没有股票价格模型能够预测冠状病毒),可能会持续产生标记为异常的结果。为了将异常如实地标记为异常值,必须满足几个条件:
- 时间序列必须要么已经被证明是合理的预测,要么不断更新的新信号。
- 最多 5%-10%(视上下文而定)的点可以被标记为异常。否则,它们将不会是作为合法集群/信号的异常,或者,噪声可能只是数据的结构部分。
用于异常检测的各种其他更专业的技术包括:
- 最*邻算法:基于连通性的离群因子(COF)、局部离群概率(LoOP)、受影响离群度(INFLO)、局部相关积分(LOCI)
- 基于聚类的算法:基于聚类的局部离群因子(CBLOF),基于局部密度聚类的离群因子(LDCOF)
- 基于分类的算法:神经网络,贝叶斯网络,决策树,基于规则
- 基于统计的算法:参数技术,非参数技术
所讨论的每一种算法都彼此特别不同,因为人们可以从许多方向来完成异常检测任务,从无监督、有监督或半监督方法到高方差或高偏差方法,每一种技术都有许多优点,但也有许多需要完全理解的假设,特别是对于这样一个微妙的任务。
如果你喜欢,
你可能会对我其他一些关于机器学习的文章感兴趣。
为什么半监督学习是 ML 的未来
medium.com](https://medium.com/faun/supervised-learning-but-a-lot-better-semi-supervised-learning-a42dff534781) [## 组合学习是机器学习的未来
自 20 世纪 50 年代以来,机器学习已经走过了漫长的道路,当时简单机器学习算法的统计方法…
medium.com](https://medium.com/swlh/compositional-learning-is-the-future-of-machine-learning-22b56ad09edc)
领域适应入门
从理论到应用

这篇文章是由皮尔明·伦伯格和 T2·伊万·帕尼科共同完成的一项工作的总结。
免责声明:由于介质上仍然缺乏 unicode 中的下标支持,我们选择使用下面的下标符号:p_S = p 下标 S。
领域适应——一段丰富而又有些混乱的历史
机器学习的目的是在给定足够数量的适当数据的情况下,对一些现象进行统计预测。在监督机器学习中,这些数据来自一组观察值,其中一些目标数量、类别或标签取决于一些可测量的特征。在标准设置中,假设所有观测值都是独立的,并且是从同一个分布中采样的。然后,ML 算法的作用是将该训练数据转换成一个函数,该函数在给定特征的情况下准确地预测看不见的观察结果的标签。
经典的最大似然理论假设来自测试集的新观察值(我们希望对其进行预测)来自与来自训练集的观察值相同的群体。然而,这是实践中很少遇到的理想情况。
训练集相对于测试集有偏差。正如我们将要看到的,根据情况的不同,这种偏差可以是已知的,也可以是未知的。领域适应(DA)是本综述的主题,是一组旨在以某种方式补偿训练集和测试集之间的统计不对称性的方法。事实上,领域适配在 ML 中是一个全新的话题。然而,有几个原因使得新手很难对领域适应建立一个连贯的概述:
- 关于 DA 的研究论文在某个特定的学科中处理这个主题,使用了在其他地方不适用的专门词汇和概念。
- 即使对于不是专门针对某个特定学科的 DA 研究,也没有通用的术语协议来指代不同类型的领域适应。这通常会造成混乱。
- DA 有时会与迁移学习混淆,后者是当前 NLP 和深度学习领域的热门话题。TL 处理的是将从一个任务中获得的知识转移到另一个任务中,而 DA,也就是我们关注的焦点,处理的是一个训练和测试观察具有不同统计特性的单一任务。
- 从严格的统计学习角度处理数据挖掘的文献有时充斥着数学术语,这使得它对于更有实践经验的数据科学家来说很难阅读。
- 另一方面,更实用的论文常常对“达”作过于描述性的叙述,在概念的一致性方面还有许多不足之处。
因此,本教学综述的目的不是展示冗长的方法目录,而是连贯地呈现四种重要的特殊情况:【协变量移位】概念移位* 和 子空间映射 ,我们将很快对其进行定义。这篇介绍性综述的目的是帮助读者对这个广阔的领域建立一种直觉。更深入的探讨,可以参考我们的 技术文章 。*
现在让我们继续描述我们所考虑的 DA 的四种特殊情况。此后,源域将指从中提取训练观察值的群体,而目标域将指从中提取测试观察值的群体。与源域相关的对象将被“下标”,而与目标域相关的对象将被“下标”
领域适应的四个重要案例
先前班次
先验偏移指的是这样一种情况,其中用于挑选训练观测值的源分布 p _S 相对于目标分布 p T 是有偏差的,因为在两个域中标签 y _ i 的先验分布是不同的。这里我们将关注分类,其中{ω_1,…,ω n }是一个有限的标签集。最有趣和最困难的情况是目标中标记的先验分布是未知的,而源中的观察值是根据它们的标记使用一些已知的策略选择的。例如,分层抽样在每一类ω _k 中选择相同数量的观察值(y_j=ω_ k, x_ j )。另一方面,类条件分布p_ S(x|y)=p_ T(x|y)在两个域中应该是相同的。图 1 说明了这种情况。

图 1:先验移位对应于标签上的先验分布 p_S(y)和 p_T(y)在源和目标(中间)中不同的情况。另一方面,假设类别条件分布 p_S( x |y)和 p_T( x |y)在两个域中是相同的(左)。由此产生的联合分布显示在右侧。
不涉及技术细节,处理这种情况的一个好方法是基于 ML 的最大似然框架内的期望最大化 (EM)算法。回想一下,这种 ML 方法假设未知分布 p _T( x , y )由参数 θ 参数化,然后寻找参数 θ _ML,使给定训练集中的观察概率最大化。另一方面,EM 算法是一种迭代方法,当概率 p _T 因忽略未观察到的(或潜在的)变量而导致时,该方法在特定情况下找到 θ _ML。于是,当使用 EM 来处理先前移位时,想法是将目标观察值中未观察到的类别变量* y _ i 作为潜在变量,将类别的未知先前概率列表 p T(ω _j 作为参数θ _j 。一旦 EM 产生了对这些先验概率的估计,我们就可以用它们来计算目标的后验概率p T(y=ω_j|x**),从而做出预测。直观地说,在该过程的每一步,当前预测值被用于更新目标的先验概率,该先验概率又被用于通过依赖于它的因子来校正预测值。请参见图 2 中的直观图示。*

图 2:应用于先前移位的 EM 算法的直观视图。这里(s)代表程序步骤的索引。
我们描述的方法的一个好处是,它带有一个统计测试,可以区分你应该或不应该使用它的情况。
协变量移位
协变量偏移,有时也称为“真实概念漂移”,描述了源分布有偏差的情况,因为根据其特征 以比例 p _S( x ) 对训练观测值进行采样,与目标分布* p _T( x )不匹配。这应该与我们之前讨论的偏移形成对比,在先前的偏移中,源分布中存在偏差,因为观测值是根据它们的标签 y 按比例 p S( y )选择的,与 p T( y )不匹配。然而,协变量 shift 假设响应 y 对特征 x 的依赖性,如源中的条件概率p S(y|x所描述的,与目标群体中的p T(y|x相同。图 3 描述了 x 为 1D 或 2D 的情况。***

图 3:协变量移位对应源 p_S( x )和目标 p_T( x )特征分布不同的情况。上图:1D 的例子。下图:2D 的例子,虚线象征性地表示不变的条件概率 p _ S(y |x)= p _ S(y |x)。
我们强调目标特征分布 p _T( x )假设在存在协变量偏移的情况下是已知的。这再次与先前的移位形成对比,在先前的移位中,目标标签分布 p _T( y )被假定为未知。换句话说,协变量和前一次移位是 而不是 对称的情况,这是通过简单地交换带有标签 y 的特征 x 而产生的。
当挑选具有给定特征的观察值 x 的成本或难度强烈影响选择观察值( x , y )的概率,从而实际上不可能在训练集中复制目标特征分布 p _T( x )时,通常会发生协变量偏移。一个典型的例子可能是一项调查,其中一些类别的个人比其他人更难达到,而模型应该能够对所有类别进行分类。
与之前的转变相反,我们在本文中提出的方法基于 ML 的 PAC 公式。非常粗略地说,PAC 理论旨在使用源中可用的数据来找到一个预测器,该预测器将(大概和*似地)最小化目标域中的预测风险。由于我们知道边际 p _S( x )相对于 p _T( x )是有偏差的,所以策略是引入一个再加权因子* w ( x ),使得修正后的版本w(x)p_ S(分布之间的各种差异度量是可用的。我们选择深入研究所谓的 MMD 度量(最大均值差异),既是因为它的优雅,也是因为它很好地阐释了内核方法。最小化w(x)p_ S(x)和 p _T( x )之间关于 w 的 MMD 测度称为 KMM ( 核均值匹配)。它最终导致一个简单的二次优化问题,即寻找 w ( x ),对于这个问题有许多解算器可用。***
在这种情况下,没有统计测试能够准确地表明该方法是否有用,但主要的指导原则是 p _S( x )和 p _T( x )不应相差太大。
观念转变
概念转换,或者有时称为真正的概念转换,描述了目标变量 y 对特征 x 的依赖性在源和目标中不同的情况。换句话说,条件分布p_ S(y|x)≦p_ T(y|x)不同。然而,特征的先验分布应该是一致的,p_ S(x)=p_ T(x)。图 4 象征性地描述了这种情况。

图 4:在概念转换中,条件分布 p_S(y| x 和 pT(y| x )在源和目标中是不同的,而先前的分布 p_S( x )和 p_T( x )是相等的。
就像我们之前讨论的前一次转移一样,我们通常对这里的目标标签一无所知。因此,我们不能简单地通过在我们想要最小化的真实风险的定义中插入一个重新加权因子w:=p_ T(y|x)/p_ S(y|x)来处理概念的转变。
概念转变通常以概念漂移的形式出现,其中条件概率p_ T(y|x)明确取决于时间,换句话说,它发生在非*稳环境中,例如在动态渐进变化的老化系统中。
处理漂移的算法在全球范围内被称为自适应算法,因为它们被设计为动态适应不断变化的设置。在这种动态环境中,人们面临的困难的核心是能够区分响应变量 y 的随机异常值和绑定 x 和 y 的关系中的真实漂移。这里有一些基本策略可以用来应对观念的转变:
- 使用从滑动时间窗口中选择的新数据定期重新训练模型。
- 定期用新数据更新模型,同时保留部分旧数据。
- 重量训练数据与他们的年龄成反比,如果算法允许的话。
- 使用迭代方案,其中新模型学习修正最*的模型(类似于助推)。
- 检测漂移并相应选择新型号。
组织处理概念转换问题的现有方法本身就是一个挑战。这样做的一种方法是,任何这样的自适应系统都有四个部分,如图所示:
- 实际得到训练的学习算法模块,
- 一个存储模块定义哪些数据被呈现给学习算法,
- 跟踪学习算法性能的损失估计模块,
- **变化检测模块,其处理由损失估计模块提供给它的信息,并在必要时更新学习算法模块。

图 5:自适应系统的四个模块。
对这四个模块的所有选项的深入描述超出了本介绍的范围。
处理概念漂移的应用数量如此之大,以至于所有的研究都致力于将这些任务归类到一个连贯的框架中。已经确定了三组具有不同目标并使用不同类型数据的应用程序:
- 监测和控制应用:该组中的应用旨在监测一些自动化生产过程,以测量其质量或检测可能的异常值。变化发生得很快,通常在几分钟或几秒钟内。
- 信息管理应用:该组中的应用旨在组织信息。通常情况下,数据以一系列带有时间戳的 web 文档的形式出现,应该对这些文档进行分类或描述。漂移可能在几天或几周内逐渐或突然发生。
- 诊断应用。该组的任务旨在描述几个月或几年内逐渐发生的经济群体的健康状况。
每个类别中的每个应用程序通常使用不同的技术来处理它们所面临的概念转变。
基于 PAC 理论扩展的数学框架,我们在文章中描述了漂移连续且足够慢的情况。
子空间映射
我们不要背离传统,想象一下我们要训练一个分类器来识别猫和狗的图片。假设我们的训练集包含在特定光照条件下拍摄的图片,这些条件包括曝光、色彩*衡和特定类型的背景。那么我们应该如何优化我们的分类器来对这些在完全不同的光照条件下拍摄的相同宠物的图像进行分类呢?这是典型的子空间映射问题。更一般地,子空间映射处理这样的情况,其中源和目标示例同样被选择,但是在源中描述它们的特征 x 和在目标中描述它们的特征x' =T(x)之间存在未知的扭曲或坐标变化 T 。更准确地说,根据联合概率分布,我们假设对于子空间映射:
- p_ T(T*(x),y)=p_ S(x**, y )对于源域和目标域中的描述之间的某种未知扭曲 T 。*
通过边缘化和限制上述等式,我们分别获得:
- p_ T(T*(x)=p_ S(x***
- p_ T(y|T*(x)=p_ S(y|x**)*
换句话说:预测值 y 与源中的 x 和目标中的 T ( x )所描述的观测值相匹配。特别地,第一个等式意味着p_ T(x)≦p_ S(x),第二个等式意味着p_ T(y|**|【T35)≦p_ S(y|【T40)因此,看待子空间映射的另一种方式是将协变量转换与概念转换结合起来,两者都以特征上坐标 T 的变化为特征。有很多种方法试图处理子空间映射。我们选择关注图 6 所示的最佳运输方法:**

图 6:最佳传输方法寻找从源到目标的“低成本”非线性转换。
最优传输(OT)是目前处理子空间映射最通用、最优雅和最强大的方法。简而言之,最优传输寻找映射 T ,该映射将源关节分布 p _S 变形为目标关节分布 p _T ,同时使用最小的努力将质量从一个关节移动到另一个关节。当然,我们不知道目标中的标签 y _ i (这就是我们想要预测它们的原因),因此我们不能直接访问 p _T。但是我们可以使用预测符h(x_I)作为这些标签的代理。沿着这些路线的 OT 的清楚表述导致双重最小化过程,其中在运输映射 T 和预测函数 h 上,将 p _S 向 p _T 移动的努力同时最小化。一个简单的最小化程序在使用固定 T 优化 h 和使用固定 h 优化 T 之间交替进行。针对 h 的优化可以使用任何 ML API 来完成,而针对 T 的优化可以利用 OT 优化器的最新进展。
虽然 OT 的数学在几十年前就已经为人所知,但它长期以来一直被数据科学家所忽视,主要是因为它的计算成本很高。但是最*由于各种允许快速优化的计算技巧,事情发生了变化。
结论
尽管训练数据集在机器学习中具有实际重要性,但许多从业者仍然低估了处理训练数据集没有如实反映现实世界的情况的系统程序的需要。我们分析认为,这主要是由于可用的方法多种多样,并且缺乏一个统一的、广为接受的术语来描述不同的 DA 场景。出于这些原因,数据科学家通常喜欢各种技巧,如猜测适当的重采样比率或生成虚拟数据,以建立适当的训练集。
我们希望这篇综述能够有助于向更广泛的数据科学家受众阐明和传播对数据科学这一重要主题的认识。如果我们成功了,你可能想知道更多的。
广义线性模型入门
应用统计学的支柱
线性模型非常非常重要。而其他线性模型存在(分级、比例风险等。),GLMs 提供了一个很好的起点。
第一,业务方面。对于提出建议和交流结果,可解释性是关键。我想不出比 GLM 更具解释性的机器学习(ML)模型了。频率主义者可以使用 GLM 进行似然比测试来测试假设,而贝叶斯主义者可以通过使用先验拟合 GLM 来获得后验概率。
第二,技术方面。即使当可解释性不是一个问题,正则化 GLM 可能是最常用的 ML 模型。对于数据科学项目来说,它通常是“最不可行的产品”,因为它易于培训和部署,同时性能相当好。Booking.com 在的这篇文章中详细介绍了他们如何快速大规模生产模型(剧透:从 GLMs 开始)。如果您有许多可能的项目要做,那么更值得的是坚持使用 GLM,只有在您完成了所有高优先级的项目之后,才返回来改进模型。
几年前有一条病毒式的推特:
当你在筹款时,它是人工智能。
当你在招人的时候,就是 ML。
当你实施时,它是线性回归。
当你在调试时,它是 printf()。
还有人讽刺地开玩笑说:

虽然这些说法并不完全属实,但其中有一点是真实的。当然,许多工作需要的是相反的极端:深度学习。尝试使用线性回归做 NLP 或计算机视觉,祝你好运。但是深度学习不就是一堆逻辑回归堆在一起吗?(我开玩笑。)
希望你相信 GLM 是分析和数据科学中需要掌握的一项重要技能。我想把 GLMs 的精髓提炼到这篇短文中,这样你只需要花 20 分钟就可以很好地理解,而不是阅读整本教科书。
本文将首先讨论逻辑回归,因为它是最常见和最熟悉的类型。然后,它将作为一个例子来解释总体 GLM 概念。然后我们将深入研究其他类型的 GLMs。假定了解普通最小二乘(OLS)回归。
二元结果:逻辑回归
逻辑回归用于编码为 1 或 0、真或假的二进制响应。当汇总时,我们可能将成功的比例或计数作为响应变量。我们假设数据是像掷硬币一样产生的(二项式分布),我们希望根据预测因素来预测成功的概率。
我们将使用号航天飞机挑战者 号 O 型圈数据集进行演示。1986 年,航天飞机在发射后不久解体,所有乘客遇难,原因是 O 型环故障。
这一事件是可以避免的。工程师们表达了担忧,并强烈建议因天气原因推迟发射,但警告被美国宇航局管理层忽视。发射的前一天晚上,工程师艾柏林告诉他的妻子“它要爆炸了。”
工程师是怎么知道的?以下是他们所掌握的数据(要点略显紧张):

发射时,外部温度为 31 华氏度。即使通过目测,我们也应该警惕。工程师们要求等到温度上升到 53 华氏度以上。美国宇航局认为发射失败的几率为 0.001%。这次发射的风险到底有多大?
回答这个问题最天真的方法是使用 OLS 回归来预测概率:

然而,这种模式没有意义。首先,它可以预测[0,1]之外的概率,或者在这种情况下,预测[0,6]之外的预期计数。与 OLS 拟合直线不同,逻辑回归拟合的是逻辑函数,一种 S 形函数:

我们可以为我们的预测设定一个下限和上限。事实证明,预测对数概率(logit)并将其输入逻辑(逆 logit)函数可以实现我们的目标。我们的回归模型是:

注意没有ε。不可约误差来自二项式分布,它是 p 的函数。
在 R 中,我们可以用一个函数来拟合模型:
model <- glm(
damage/6 ~ temp,
data = faraway::orings,
family = 'binomial',
weights = rep(6, nrow(faraway::orings))
)
有两种方法可以将分组二项数据输入到 R 的 glm 中。我更喜欢这个,这里的响应是比例,权重是试验次数。在 95%置信区间的情况下,预测的*均值为:

根据模型假设,我们预计在发射条件下,*均有 5 或 6 个 O 型圈会失效。发射注定要失败。
现在我们已经看到了我们的第一个例子,我们将在讨论其他发行版之前讨论 GLM 的一般方面。
理论:链接功能
GLMs 预测链接函数而不是原始观察值。把它们看作是把你的观察和你的模型联系起来的一种方式。
解释链接函数的最好方法是将其与转换函数进行对比。对数变换常用于处理 OLS 回归中的右偏残差,以预测函数的条件期望 E[ln(y)|X]。使用具有对数链路的高斯 GLM 代替预测 ln(E[y|X]),作为条件期望的函数。
当我们看到假设ε服从正态分布的回归方程时,这种差异就变得更加明显:
- 对数变换:ln(y) = Xβ + ε。y 的条件分布是对数正态。
- 日志链接:ln(y + ε) = Xβ。y 的条件分布是正态。


在对数变换中,exp(fitted)不是预测的*均值,而是众数。没有一个比另一个更好:他们做了不同的假设。
链接函数在计数和二进制观测中显示了它们的惊人之处。我们经常使用 log link 函数来模拟计数。您多久会因为无法记录日志(0)而感到沮丧?在泊松假设下,即使条件均值非零,你也能观察到 0。取条件*均值的对数没有问题。
逻辑回归中的典型关联函数是 logit(对数优势)函数

我们说典范是因为它是我们从二项分布本身得到的。logit 函数是转换(0,1) → R 的一种方便的方法,但是有很多函数可供选择。为什么是这个?

看到什么熟悉的东西了吗?我们称 logit(p)为二项式分布的自然参数,因为它是与 y 相互作用的参数。练习:对泊松做同样的操作,以说明为什么 ln(λ)是规范链接。
当然,没有人强迫你使用规范链接。例如, probit 链接通常用于对罕见事件建模。
理论:GLMs 如何工作
有几种算法可以拟合 GLM,但本文将只讨论迭代加权最小二乘法(IRLS),因为它提供了最佳的直觉。透过渐变的镜头来看太抽象了。一些数学问题将被抛到一边,这样我们就可以专注于直觉。我们从 OLS 的封闭解开始:

在 OLS,所有的观察值都被假定为独立的,并且误差来自具有共同方差的同一个正态分布。如果观察值的权重不相等,则解决方案看起来像:

在 OLS,W 是单位矩阵,因此被省略。但是如果不是恒等式呢,比如在加权最小二乘中?我们保持独立性假设,所以 W 是对角矩阵。对角线上的每个条目应该是精度,或者 1/方差。
这最后一点是统计学中一个常见且重要的主题。统计学中如此多的东西可以被视为一个精确加权*均值。当我们确实对某件事有把握时(方差很小),我们希望在计算我们的估计值时给它一个很高的权重——精度告诉我们每个观察值包含多少信息。
作为一个更具体的例子,我们知道样本均值 s 的标准误差可以计算为

如果我们对数据进行分组,并假设每个单独的观察值都来自共享相同方差的特定于组的正态分布,会怎么样?如果我们有三个组,我们可以计算全局*均值为

在这种情况下,精确加权*均值与常规加权*均值完全相同。记住这种直觉。非正态分布的 GLM 中的 W 变得更复杂,但条目仍然是精确的。
下一步是用工作因变量 z 替换 y。我们并不试图直接预测 y,所以我们需要修改它以与链接函数一起工作。


这里的 e 是实际预测误差。在我们的逻辑回归例子中,如果 Xb = 1,那么我们的预测概率是 inv.logit(1) = 0.73。如果我们观察到一个成功,那么 e = 1 - 0.73 = 0.27。σ来自我们的选择分布。由于 logistic 回归使用的是二项式,所以σ = p(1 - p)。
如果我们假设正态分布有恒等环节 g(x) = x 呢?那么最后一项是

也就是刚刚的 标准化公式 !所以我们的工作因变量是我们的预测值加上多少标准差就是我们的实际值。
我们配备了 1)权重以获取加权*均值,以及 2)一个“标准化”变量以获取*均值。
最后一步是认识到 W 和σ取决于预测值,反之亦然。上面两个方程看起来是递归的吧?事实上,当且仅当样本来自正态分布时,样本均值和样本方差才是独立的。这是一个深刻的陈述——除了正态分布,没有其他分布有这个性质,这就是为什么我们可以一步解决 OLS。
我们可以把 IRLS 看作是一种期望最大化算法。我们保持预测值不变,并计算 W 和 z。然后,保持 W 和 z 不变,以计算新的预测值。迭代直到收敛。
现在我们有了。直观地说,GLM 是一种以巧妙的方式进行精确加权*均的算法。
诊断:异常
如果模型非常适合,则偏差,-2 对数似然性(+一些被忽略的常数)应遵循χ分布。根据经验,如果偏差远远高于模型自由度,那么模型可能不太符合数据。处理分组数据时要小心,因为 R 会输出不正确的偏差,您应该手动计算。简单演示:
dat <- data.frame(
y = 5:7 / 10,
n = rep(10, 3),
x = 1:3
)
model <- glm(
y~x,
data = dat,
weights = n,
family = 'binomial'
)
summary(model)

r 错误地认为 3 行= 3 个观察值,尽管我们有 30 个观察值。剩余偏差应该有 28 个自由度。
binom_deviance <- -2 * sum(
log(choose(dat$n, dat$y * dat$n)) +
log(fitted(model)) * dat$y * dat$n +
log(1-fitted(model)) * (1-dat$y) * dat$n
)
pchisq(
q = binom_deviance,
df = sum(dat$n) - length(model$coefficients),
lower.tail = FALSE
)
因为 p 值很大,为 0.9999,所以我们无法拒绝模型非常适合的零假设。
诊断:皮尔逊残差
为了直观地检查 GLM,我建议查看皮尔逊残差,即残差除以理论标准差,就像二项式的 sqrt(p × (1-p))和泊松的 sqrt(λ) 。因为方差取决于拟合值,所以这样做可以获得相同单位尺度上的所有残差,并且您可以使用标准正态的经验规则来观察。只有少数皮尔逊残差应该落在(-2,2)之外,极少情况下应该落在(-3,3)之外。
set.seed(123)
x_val <- rnorm(100)
y_poisson <- sapply(
x_val,
function(x) rpois(n = 1, lambda = exp(x))
)
y_negbin <- sapply(
x_val,
function(x) rnbinom(n = 1, size = 0.8, mu = exp(x))
)model_correct <- glm(y_poisson~x_val, family = 'poisson')
model_wrong <- glm(y_negbin~x_val, family = 'poisson')plot(
fitted(model_correct),
residuals(model_correct, type = 'pearson'),
main = 'Good fit',
ylab = 'Pearson residuals',
xlab = 'Fitted values'
)


一般来说,我们不希望皮尔逊残差遵循正态分布,因为误差项的条件分布通常是偏斜的,计数不能低于 0,概率介于 0 和 1 之间。因此,一个正常的 QQ 图从表面上看是没有帮助的。
然而,如果你取皮尔逊残差的绝对值,如果模型非常适合,它们应该类似于半正态分布。一个快速而简单的方法是复制第二份皮尔逊残差,然后翻转符号,做一个普通的 QQ 图。
double_resid <- c(
residuals(model_correct, type = 'pearson'),
-residuals(model_correct, type = 'pearson')
)
qqnorm(double_resid, main = 'Good fit')
qqline(double_resid)


假设检验:似然比检验
GLMs 测试可以通过 LRT 完成。查看我的上一篇文章详细解释。基本思想是我们想要比较两个模型,一个嵌套在另一个中。较小模型的预测值是较大模型预测值的子集。系列、数据、链接功能等。必须都一样。我们将偏差差异与χ分布进行比较,df =估计的附加参数数量:
dat <- data.frame(
x1 = rnorm(10),
x2 = rnorm(10)
)
dat$y <- dat$x1 + dat$x2 + rnorm(10)
model_small <- glm(y~x1, data = dat)
model_large <- glm(y~x1+x2, data = dat)pchisq(
q = model_small$deviance - model_large$deviance,
df = model_small$df.residual - model_large$df.residual,
lower.tail = FALSE
) # Likelihood Ratio Testsummary(model_large)$coefficients # Wald test
在这种情况下,LRT 计算 H0 的 p 值:coef(x2) = 0。它优于回归总结中包含的 p 值,后者是通过 Wald 测试得到的一个方便的*似值(根据回归公式,甚至可能无法回答正确的问题)。当二次*似法失败时,贝叶斯主义者可以进行类比。
实践中:正规化和交叉验证
当你关心 p 值和无偏估计(在模型假设下)时,你使用香草 GLM。但是如果你想让更好的预测,你可以使用正则化 GLM。当你有比观测值更多的预测值(p > n)时,你无论如何都不得不使用正则化,因为 MLE 不存在。
谈论正规化是困难的,因为不同的软件包有不同的公式。虽然最终结果是等效的,但参数的定义是不同的(C 或λ)。我将坚持使用 R 的 glmnet 文档。
GLM 最大限度地减少偏差。正则化的 GLM 将偏差最小化(乘以一个常数,我将挥去)+一个惩罚项:
- 拉索增加了 L1 规范作为惩罚。将系数的绝对值(截距除外)相加,并乘以常数λ。
- 里奇增加了 L2 标准作为惩罚。你将系数的*方和(截距除外)乘以一个常数λ。
- elasticnet 对这两种惩罚进行加权*均。你选一个常数α,罚项设为α × L1 + (1-α)/2 × L2。

正则化的几何解释(来源)
L1 范数鼓励稀疏性,可以将许多系数设置为 0,而岭将系数向 0 收缩,但永远不会达到 0。把λ项想象成设定一个“预算”,这样每个系数都不会花费太多(数量巨大)。
你需要标准化预测器(glmnet 默认这样做)来公*地分配预算。如果一个预测值是 g,而另一个是 kg,那么给 kg 更大的预算可能更有意义。(我们能生产多少蛋糕?也许每公斤面粉+1,但每克糖+0.001。)标准化把所有的预测器放在同一个尺度上。
有一点值得注意,很多人可能会忽略:通过正则化,您应该对所有级别的预测值进行编码。如果您有一个具有 k 个可能值的分类预测值,传统的哑编码将丢弃一个作为参考级别,然后创建 k-1 个指示列。通过正则化,你应该创建 k 个指示器列。拦截不会受到处罚。因为下降的电*被吸收到截距中,系数将根据下降的电*而变化,这是不希望的。
我们仍然需要设置超参数λ和α。最简单的方法是对α使用网格搜索(因为它在 0 和 1 之间,所以很容易做到均匀间隔),对λ使用 k 倍交叉验证。关于 CV 的具体细节可以在别处找到。
我注意到统计学和计算机科学之间的一个主要区别是他们如何从 CV 中选择λ(或 C)。Python 中的实现返回产生最小目标函数(lambda.min)的λ,您没有选择。在 R 中,您可以在λ. min 和最大λ之间进行选择,最大λ在最小值(λ. 1s)的一个标准误差内。
根据简约法则(奥卡姆剃刀),一些人更喜欢λ. 1se,因为它产生一个更简单的模型,其性能与λ. min 差不多。此外,λ. 1se 往往更稳定。将数据重新随机化成 k 倍可以产生非常不同的λmin,但是更相似的λ1s
所有的谈话都会变得令人困惑,所以让我们装一个套索来看看它的作用。r 代码:
library(glmnet)# The 0+ makes Species not drop a reference level
X <- model.matrix(Sepal.Length~0+., data = iris)
y <- iris$Sepal.Lengthset.seed(123)
train <- sample(1:nrow(X), floor(nrow(X) * 2/3))
model_cv <- cv.glmnet(X[train,], y[train])
plot(model_cv)model_1se <- glmnet(
X[train,],
y[train],
lambda = model_cv$lambda.1se
)
model_min <- glmnet(
X[train,],
y[train],
lambda = model_cv$lambda.min
)mse <- function(pred, actual){
mean((actual - pred)^2)
}# while sometimes model_min yields lower MSE
# generally model_1se performs better in this examplemse(predict(model_1se, X[-train,]), y[-train]) # 0.09685109
mse(predict(model_min, X[-train,]), y[-train]) # 0.1022131
是的,你可以抱怨,因为我们用了虹膜数据集。我们想预测萼片。长度使用所有其他变量。plot()函数返回

这里 log(λmin)大约为-7,而 log(λ1s)大约为-5,如虚线所示。随意尝试不同的种子值来比较 MSE,但通常 lambda.1se 表现更好。(不知道为什么 Python 里这不是默认而不是 lambda.min。手动编写交叉验证来获得 lambda.1se 是一件痛苦的事情。)
我将数据分为训练集和测试集,以说明保留数据的性能,但在实践中,您应该而不是进行这种划分。来自 CV 的误差比来自测试集的误差更可信。对整个数据进行 CV 以选择λ,然后对整个数据集进行改装。
我希望你们注意估计的系数:

versicolor 的系数被设置为 0,因为它是中间值。拉索学会了吸收云芝,而不是其他物种,进入拦截。
直观地说,如果{virginica,versicolor,setosa}是{1,2,3}并且我们去掉了 versicolor,那么 MLE 系数将是{-1,/,1},并且它们收缩相等。但是如果我们去掉 setosa,因为我们按字母顺序,那么 MLE 系数将是{-2,-1,/},并且-2 将比-1 收缩得更多。这没有意义,因为数据和现实世界都没有改变。我们不希望预测依赖于我们手动降低的水*。
现在我们已经对 GLMs 有了很好的理解,我们将继续学习其他类型。我们将只简要介绍这些内容,因为它们是建立在我们之前讨论的基础之上的。
计数数据:泊松和负二项式回归
泊松使用对数链接,因此回归方程看起来像

如前所述,log 链接的魔力允许我们采用 ln(),即使计数可以是 0。
有时,由于曝光单位不同,我们对速率而不是计数感兴趣。如果我们想模拟每个城市有多少人生病,仅从人口规模来看,一个有 10 万居民的城市应该比一个有 1000 居民的小城市多。
在逻辑回归中,我们使用权重参数,但是在泊松回归中,权重实际上不应该被触及。相反,我们使用偏移量。其中 y 是事件数,我们重新排列回归方程:

偏移仅仅意味着我们不估计斜率,而是将其固定为 1,例如 RHS 中的 ln(n)。在 R 中:
glm(y~x+offset(log(n)), family = 'poisson')
在实践中,泊松回归是不够的。许多数据表现出过度分散,即观察值的方差高于泊松分布所表明的值。这可以通过检查皮尔逊残差来发现;它们中的许多将位于(-2,2)之外。
我建议先试试泊松回归。如果有过度分散的证据,尝试负二项式回归,它也使用对数链接,但方差有一个过度分散参数。在 R 中,这是 glm.nb()函数。
负二项式真的很工整。如果对泊松分布求*均,其中每个泊松分布的λ根据伽马分布而变化,则得到负二项分布。换句话说,我们明确地建模,即使两个单元可能具有相同的 X,它们的λ 可能不同。这是解释过度离差的好方法,因为你有泊松和伽马的方差。
有时,你有比泊松或负二项式建议更多的零。如果你对数据生成过程有所了解,你可以使用零膨胀回归或栅栏模型(尽管这些在计算上很昂贵)。直觉参见此螺纹。
列联表:对数线性模型
如果我们有一组泊松随机变量,并且约束它们的总数是固定的,那么我们得到多项式分布。因此,即使列联表感觉应该被建模为多项式,泊松回归也可以完成这项工作。你应该高兴,因为处理多项式是一件痛苦的事。
对数线性模型是泊松回归的一个奇特术语,其中所有预测值都是分类的-在这种情况下,无论列联表中的类别是什么。我以前写过这方面的文章,所以如果你对更多感兴趣,请参考关于 G-test 的部分。
分类结果:多项式回归
多项式回归是一种逻辑回归,它被扩展到预测二进制以上的结果。其实就是几个逻辑回归包在一起。在逻辑回归中,我们预测对数优势,其中优势是 p/(1-p)。在多项式回归中,我们做同样的事情,除了选择一个参考类别来计算概率。
假设我们有三个类别 A、B 和 c。如果我们使用 A 作为参考类别,那么我们拟合两个逻辑回归模型:

第一个模型仅针对响应为 A 或 B 的数据进行训练,第二个模型仅针对响应为 A 或 c 的数据进行训练。我们将预测值传递给 softmax 函数以获得

1 看起来很不合适,但请记住 log(pA/pA) = log(1) = 0。
softmax 函数只是一个逻辑函数,它可以推广到两个以上的类别。它经常被用来方便地将预测转化为概率,但在这里它不仅仅是方便:它是有意义的。假设除截距外没有其他预测值,我们观察到 70 A、20 B 和 10 C,则:

使用 MLE,选择哪个类别作为参考类别并不重要。对于正则化,如果你这样做就很重要了,所以正则化多项式回归通常不是作为一组逻辑回归来实现的。
所有这些关于 sigmoid 和 softmax 函数的讨论听起来都像是神经网络。事实上,最原始的神经网络是一堆与 softmax 函数捆绑在一起的逻辑回归,尽管自那以后该领域已经取得了很大进展。
有序结果:有序回归
我个人认为有序回归很不直观。您希望将 y 编码为 1,2,3,…,k,并希望预测 y = i 的概率,其中 I 是 1 到 k 之间的整数。我们使用累积链接函数:

我们的回归方程看起来像

我只上到 k-1。记住 P(y > k)是 0。在回归方程中,βT5 不包括截距。我们用一个基本事实来做预测

并且从

好的,那么这些等式是什么意思呢?我们正在拟合一个 sigmoid 函数来预测以 X 为条件的 CDF 。在回归方程中,β对于所有 I 都是固定的,但θ会随着 I 而变化。当 X 固定时,我们拟合一个单一函数,而θ决定分界点。
问题和直觉就在这里。概率总和必须为 1。想象一根长度为 1 的棍子,我们在{1,2,3,4,5}中有一个序数变量 y。我们想把棍子分成 5 段,每段的长度对应于落入某一类别的概率。最简单的解决方案是选择 4 个点进行切割:k-1θ。
更多资源
我是这个课程网站的忠实粉丝,它是我自学旅程中的好伙伴。和往常一样,如果你有改进的建议,请告诉我。
pantab 入门
如何在数据工作流中组合熊猫和 Tableau

Python 中的 pandas 库是数据分析的基本工具,但是您知道吗,您可以将它与 Tableau Hyper API 结合使用,使您从原始数据记录到可视化的管道更加容易。这正是 Will Ayd 在 innobi 开发的 pantab 库的确切目的,它是 Tableau 的 Hyper API 的 Python 包装器。在这里,我将通过一个指导性的例子来说明如何在数据工作流程中使用 pantab。
必备材料
- 只需在您选择的环境的终端中运行
pip install pantab即可安装 pantab - 在相同的环境中运行
pip install tableauhyperapi来安装 Tableau Hyper API - 从 Github 克隆我的示例 repo,因为它包含了我们将要进行的练习的所有数据(这些数据只是我在网上搜集的一些初级口袋妖怪统计数据)
为什么要用 pantab?
在我们开始之前,我们为什么要首先使用 pantab 和 Hyper API 呢?Hyper API 允许你用 Tableau Hyper extract 文件创建自动化数据处理的函数。Hyper 是 Tableau 的内存数据引擎技术,摘录用“.”表示。hyper”扩展。所以基本上,Hyper API 允许你创建”。用于 Tableau 的“hyper”文件。您将能够使用 Python、Java 或 C++之类的语言创建和更新摘录。然而,有时使用 API 会有点麻烦。例如,下面是将数据从 CSV 转换为 Hyper 文件的 Python 代码片段:
将数据从 CSV 文件插入到超级文件中。多痛苦啊!
在一个超级文件中只包含 3 行数据需要付出很大的努力!(事实上,编写和调试这段代码花费了我更多的时间和精力,比本文中的所有代码加起来还要多)
好消息是,pantab 通过将它与 pandas 相结合并抽象 Hyper API 来简化它,使这一过程变得容易得多。如果你已经是一个熊猫从业者,这甚至更好,因为这将为你提供一个熟悉的框架来处理数据和生成你的超级文件。
这方面的一个用例是我在目前的职位上经常遇到的:有时运行提取需要很长时间,可能需要几个小时,但是如果有什么问题,我想调查一下。但是,我想通过连接到作为数据源的提取并对其进行 EDA 来研究提取的精确版本,以便在第二天数据被覆盖之前检查一些假设。使用 Python/pandas 之类的工具是最简单的,因为 Tableau 本身主要是一个数据可视化工具,但我想以一种更程序化的方式检查我的调查中的某些分组或聚合。
pantab 也是 ETL 数据管道中的一个有用工具,当您需要的数据必须从一个或多个来源转换时,它可以通过管道输出超级文件。有点像 Tableau Prep 的替代物(或者如果你没有权限的话,它的替代品)。
在撰写本文时,在 pantab API 中只有 4 个函数可以调用:
- frame_to_hyper :写一个数据帧到一个. hyper extract
- frame_from_hyper :从 hyper extract 中提取一个数据帧
- frames_to_hyper :将多个数据帧写入. hyper extract
- frames_from_hyper :从一个. hyper extract 中提取多个数据帧
让我们使用我的回购中的数据,逐一查看这些例子。
将数据帧写入 Hyper
函数的作用是将 pandas 数据帧转换成 hyper 文件中的表格。导入所需的库后,您只需读入数据作为 pandas 数据帧,然后使用 frame_to_hyper 将数据帧写入指定的 hyper 文件,如下所示:
框架到超级示例

超级提取中的结果表
这是两行代码,与直接使用 Hyper API 的代码做完全相同的事情。代码减少了很多!现在,您可以使用 pandas 直接转换数据,或者在将数据写入超级文件之前对其进行任何检查。
注意,我实际上在上面创建了两个数据帧。我这样做是为了演示您可以将表保存在不同模式的 Hyper 文件中(有关这方面的更多背景信息,请参考 Hyper API 参考)。默认模式是“public”模式,但是您可以明确地命名一个模式,就像我对上面的“Extract”模式所做的那样。为此,您必须从 tableauhyperapi 库中导入“TableName”对象(因此您确实不能 100%避免 hyperapi,但您肯定可以减少直接使用它的次数!).
从 Hyper 读取到数据帧
为什么我要费心保存我的数据两次,但是用不同的模式?我这样做是为了证明并不是 Hyper extract 文件中的所有表都在公共模式中,所以有时您需要检查它们在哪里。(特别是,如果用于创建提取的 Tableau 版本低于 10.5 版,则默认情况下它可能位于提取模式中,而不是公共模式中。)要演示这一点,请使用 pokemon_extract.hyper 文件,并尝试使用具有默认表位置的 frame_from_hyper 函数将它读入 pandas 数据帧。它以消息“出错:指定的表不存在:口袋妖怪。”因为 Tableau 10.5 及以上版本“口袋妖怪”表不在默认位置。您需要使用 TableName 对象指定模式,如下面代码片段中的第二行代码所示:
在 frame_to_hyper 函数中指定模式
将数据帧写入 Hyper 时,您可以轻松检查默认模式是否为公共模式,因为这几行具有完全相同的结果文件:
如果没有给定特定的模式,则默认为公共模式

注意左边写着“public.pokemon”

注意左边写着“Extract.pokemon”
如何将多个表读入数据帧并检查现有的表和模式
对于现有的超级文件,现有模式中可能已经有表。我们如何检查这些现有的表和模式?我们可以使用 frames_from_hyper 函数来帮助我们。frames_from_hyper 函数返回一个字典对象,其中模式/表存储为字典键,熊猫数据帧是值。查看这些键将揭示任何预先存在的模式和表。
返回我们已经拥有的模式和表
在这里,我们可以看到 public.pokemon 存在于 pokemon_public.hyper 文件中,而 Extract.pokemon 存在于 pokemon_extract.hyper 文件中。
将多个数据帧写入 Hyper
最后,我们可以通过使用 frames_to_hyper 函数将多个 pandas 数据帧写入一个 Hyper 文件。它需要一个数据帧字典作为输入,将每个数据帧写出到一个超级提取的表中,如下所示:
将多个数据帧写入超级文件
但是请注意,这将在 Hyper 文件中创建三个单独的表,无法将它们合并或联合成一个表:

都是分开的,不能用并集或合集
但是如果我们想把所有的表合并成一个呢?在这里,我们所有的表都有相同的形状和字段,所以我们最终想把它们组合起来。我们可以通过两种方式实现这一点:或者在写入超级文件之前将它们合并为一个 pandas 数据帧,或者使用 frame_to_hyper 中的 append 模式(table_mode = 'a '):
在 Hyper 中将数据帧合并到一个表中的两种方法

追加数据帧的结果

追加超级表的结果
熊猫图书馆可以使许多事情变得更容易,包括使用 Tableau 工作流程。我希望这本初级读本能帮助您了解更多关于如何使用 pantab 的知识,并为您的数据项目生成一些用例!
神经进化基本概念的初级读本
深入研究神经进化
对神经进化的广泛介绍,它的理论基础和领域的里程碑式的研究。这篇博文是我关于这个话题的专栏系列的第一篇文章。

N euroevolution 是一种机器学习技术,它通过进化算法的方式生成越来越好的拓扑结构、权重和超参数,来改善大脑即人工神经网络(简称 ann)的粗略抽象。正如大自然通过突变、交叉或删除一些潜在的遗传代码来提高大脑的能力一样,神经进化是否会改变人工神经网络的拓扑结构和权重,结合高性能人工神经网络的特征或消除低性能人工神经网络,以便找到越来越好的解决方案。这篇博客是三篇系列文章中的第一篇,将广泛介绍神经进化的基础知识,指出自己设计神经进化算法时需要考虑的方面,并强调该研究领域的重要和最新贡献。接下来的两个部分将深入探讨围绕神经进化的开源景观,特别关注我与rezza fara Hani在 2019 年谷歌代码之夏期间共同创建的tensor flow-神经进化框架【1】的设计和使用。
神经进化
神经进化是一种机器学习技术,通过使用基于群体的优化方法,不断提高该群体中每个神经网络的质量,为其应用的问题生成越来越好的神经网络。该群体中的每个个体不是作为复杂的神经网络存储的,而是作为一个基因组,它是一个简化的遗传表示,可以映射到神经网络。神经进化过程本身首先初始化一组这些基因组,然后将它们应用于问题环境,之后根据神经网络解决应用问题的程度,为每个基因组分配一个适应度分数。例如,该适应度分数可以是在图像识别任务中实现的准确度、机器人手臂移动到预定轨迹的接*程度或者代理在虚拟环境(如视频游戏)中表现如何的函数。
一旦创建了初始群体,优化循环就开始了,群体被不断地变异、重组、评估和自然选择。如果这些步骤是迭代执行的,整个种群一次只进行一步,我们说的是世代神经进化。如果神经进化算法的设计允许异步,并且优化循环在每个基因组的基础上执行,这通常被称为竞争协同进化。在这两种情况下,引入创新,评估创新,然后对创新进行分类的无尽循环构成了一个优化过程,最终将产生一个神经网络,它可以很好地解决应用问题,但可能无法用手来实现。下面的图 1 展示了一代神经进化算法的典型优化过程——可视化上述训练循环的所有步骤。

图 1:典型的世代神经进化过程图解
神经进化是一个不可知论的过程,它虽然需要参数用于其自身的进化过程,但并不为生成的神经网络规定任何特定的拓扑或超参数。相反,人工神经网络是通过对在问题环境中有效工作的反馈来开发的。可用于生成的神经网络的形成和完整规范的选择范围(拓扑、权重、超参数等)通常被称为搜索空间。虽然神经进化过程的不可知论性质允许非常广泛的搜索空间,但是限制搜索空间的粒度以便更快地遍历它是否是明智的。将基因组映射到相应神经网络的能力通过限制基因组编码的复杂性来负责搜索空间的粒度。这种能力因此被称为基因编码。
为了允许具有适当粒度的广阔搜索空间,根据问题环境的要求设计遗传编码和对其进行操作的神经进化算法是至关重要的。因此,为了设计一个好的神经进化方案,我们首先需要建立对基因编码的基本理解,这将在下一节中完成。接下来,我们将按照相关的顺序仔细查看图 1 中显示的上述进化优化循环的每一步。
遗传编码
为了有效地变异和重组人工神经网络,一种有效的人工神经网络表示是必要的。神经网络的有效表示允许频繁使用的遗传操作不必分析高度复杂的数据结构,而是让它们分析可以快速处理的紧凑遗传代码。因此,基因操作能否快速确定敏感的突变,或者两个基因组是否适合重组。因此,神经进化算法只对遗传编码进行操作,而不是对流行的机器学习框架所操作的复杂数据结构进行操作。当然,基因编码允许两种表达之间的映射。
基因组的这些有效遗传表示被称为基因型,而相应绘制的神经网络被称为表现型。该术语来自遗传进化,因为神经进化严格来说是遗传进化,其限制条件是所有表型都是神经网络。

图 2:示例性直接遗传编码的图示
遗传编码一般可以分为两个子类:直接编码和间接编码。虽然也有第三类发育编码我们省略了这种编码,因为它在最*几年几乎没有相关性。直接编码代表了神经网络的每一个方面,它们以遗传表示法明确编码。上面的图 2 是一个直接编码的例子,它被流行的 NEAT 算法所采用[3][4][5]。它直接在基因型中对每个连接及其相应的权重进行编码,但通过排除所得人工神经网络中偏差和激活函数的可能性来限制搜索空间。这种直接编码可以表示任意的前馈和递归拓扑,允许可能完全适合同时最小的拓扑。然而,允许拓扑中的这种高度灵活性导致具有精细粒度的巨大搜索空间,需要设计良好的神经进化算法,以便快速遍历该搜索空间。

图 3:间接遗传编码的例子
另一方面,间接编码规定了通常不能直观地翻译成 ANN 的定制编码,但是需要也由间接编码规定的独立翻译能力,以便将基因型映射到神经网络。上面的图 3 展示了一个间接层编码的例子,以及将规定的间接编码映射到人工神经网络的能力。如果间接编码被很好地设计,这允许通过甚至简单的突变(例如,在上面的例子中的位翻转)有意义地和快速地遍历搜索空间,以及快速地重组否则复杂的神经网络。
然而,虽然直接编码可以快速创建人工神经网络,但间接编码的翻译能力会降低处理速度,并且可能过于粗糙。在决定采用哪种编码之前,必须考虑这两种编码的优点和缺点,尤其是这两种编码的具体实现与问题领域的匹配程度。
然而,两种遗传编码都很好地展示了遗传编码如何确定搜索空间的大小,例如通过不允许激活函数或某些层类型,以及确定其粒度,例如通过仅允许将隐藏层大小调整 32 的倍数。
再现的方法和解决方案探索
与神经进化方案所采用的遗传编码密切相关的是实际遍历所定义的搜索空间的方法。这种方法是繁殖的过程,通常分解为通过突变或重组被认为适合作为下一代父母的基因组来创造新的基因组。突变让后代基因组探索新的人工神经网络结构、权重分布和超参数的可行性。重组基因组,本质上是合并两个有希望的基因组和它们不同的特征的过程,将有益的特征传播到整个群体的其余部分。
突变与遗传编码密切相关,因为它只能将神经网络的参数突变到遗传编码中所表示的程度。因此,为神经进化算法定义突变是在遗传编码允许的可能范围内定义三个方面。第一,基因编码的哪一部分会发生变异?它可以是拓扑、权重、超参数,或者在上述间接编码的例子中是随机选择的比特。再者,基因组中被选择的部分会变异到什么程度?例如,神经进化算法可以对低适应度基因组采用广泛的突变,对高性能基因组采用微小的突变——如果人工神经网络不起作用,则有效地表达出彻底改变人工神经网络设计的方法,或者如果人工神经网络工作良好,则表达出人工神经网络的细节。突变的最后一个定义是,它是定向的还是随机的。权重的突变通常在缺乏明确基础事实的环境中随机执行,尽管通过例如从以当前值为中心的正态分布中获得新的随机值来防止这种情况。然而,如果神经进化算法能够将问题环境中的性能缺乏映射到神经网络的设计或参数中的不足,则定向突变也是可能的。

图 4:竞争惯例问题的说明(来源:[5])
另一方面,重组不会使基因组突变,但仍然通过将两个亲代基因组及其独特的特征组合成一个创新的后代基因组来创造新奇事物。如果重组方法设计得很好,并且能够以无损的方式合并双亲基因组的有益特征,这是否允许前面提到的有益特征在整个群体中传播——提高所有现有基因组的适合度。因此,设计良好的重组方法的核心问题是其无损性质,即合并(也称为交叉)两个基因组的遗传编码而不丢失任何编码的 ANN 特征的性质。在神经进化算法 NEAT 之前,利用直接编码的神经进化方案确实面临着在突变和随后两个独立基因组的重组过程中出现的有损交叉的问题。上面的图 4 说明了这个被称为竞争惯例问题的问题。NEAT 算法提出了一种叫做历史标记的方法,它为每个突变提供了一个唯一的标识符,最终实现了基因组的无损重组,使其至今仍是一种基准神经进化算法。
评估的方法
尽管在问题环境中评估基因组的步骤似乎是总体优化循环中最简单的一步,但简短地解决它仍然很重要——即使只是指出潜在的警告和可能性。从根本上来说,评估方法只是将基因组映射到神经网络的过程,如其遗传编码所规定的,将其应用于问题环境,然后根据人工神经网络的表现计算适应值。一些神经进化算法还包括在将神经网络应用于实际健康评分运行之前对其进行权重训练的附加步骤。虽然这种方法非常合理,但只有当问题环境展现出清晰的基础事实时,这种方法才有可能。
在整个评估过程中,唯一可合理修改的方面是确定适合度的方式,尽管这完全取决于所应用问题的性质,并且必须根据具体情况来决定。用于确定适合度值的普通方法是将其设置为等于其在图像识别环境中的准确度或者等于在视频游戏环境中获得的点数。
新颖性搜索也是确定适合度计算时要考虑的一个重要概念,因为这个概念奖励具有较高适合度值的问题的新方法的基因组。例如,在视频游戏环境中的代理如果进入未知区域,尽管总体上获得的分数较少,但是他将获得健康提升。这促进了基因库中的创新,从而促进了更广泛、更有前途的进化过程。新颖性搜索是在 2010 年的论文“用新颖性搜索进化塑料神经网络”[7]中引入的。
创建一个设计良好的评估方法主要是一个具体实施的问题。记录可能的基本事实或充分并行化评估环境——因为拥有多个完全独立的神经网络的性质使其成为一个*凡的并行化问题。虽然这不是一个研究问题,但在实现神经进化方案时,这是一个同样重要的考虑因素吗?
自然选择和亲代选择
虽然繁殖方法决定了探索搜索空间的方式,但选择哪些基因组将作为后代的父母,哪些基因组将从基因库中删除,这是神经进化方案的另一个非常重要的方面吗?选择基因组作为后代父母的方法也很大程度上依赖于所使用的神经进化算法。
在世代神经进化中,选择适合作为下一代父母的基因组通常归结为选择当前世代中表现最好的基因组的规定部分。这个分数通常作为仍然可以配置预定义的神经进化算法的许多参数之一来提供。被选择作为亲本的基因组部分不必与被选择从基因库中去除的基因组部分互补,因为基因组可能足够有希望保证创新突变的潜力,尽管在下一代中它们自己可能被去除。神经进化算法的示例性配置是选择利用前 20%的基因组作为父代,尽管为下一代移除 90%表现最差的基因组。取决于世代神经进化算法是否采用了物种形成,被选择作为亲本或被选择移除的基因组的选择是否会发生显著变化,通常能够实现更具指导性的进化过程。
物种形成是一种世代神经进化的工具,它根据表观特征(如表型中的拓扑相似性)或更隐蔽的特征(如在应用的问题环境中达到某些状态)来聚集群体中的个体。由此产生的簇被认为是物种,理想情况下——取决于物种形成方法的选择——代表了解决手头问题的真正不同的方法。这使得生殖过程能够通过将更多的后代分配给*均适合度更高的物种来引导进化,从而有利于独特和有前途的后代的发展。然而,设计良好的物种形成也保护了基因库中的创新,仍然将一些后代分配给具有新颖独特特征的物种,这些物种还没有时间进行优化(例如,人工神经网络中独特的拓扑添加,其权重还没有优化)。因此,设计一种适当的物种形成方法,基于真正不同的解决问题的方法,将种群中的个体分离成不同的物种,可以成为更大的神经进化方法中的一个非常强大的工具,既可以将进化引导到有益的方向,又可以保护创新的新路径。
另一方面,在竞争性的共同进化方案中,基因组通常被随机配对并进行比较,更适合或更具创新性的基因组被选为亲本,而另一个则被从基因库中剔除。由于竞争协同进化的异步性质,不可能一次对群体中的所有基因组进行分类,这大大限制了用物种形成等方法指导进化的可能性。虽然自然选择和亲代选择的方法在竞争协同进化中更简单,但这是由有效的完美并行性和可扩展性弥补的。
关于神经进化的结束语
神经进化是一种非常广泛的优化人工神经网络的方法,以更好地处理问题环境。它是一种多功能的工具,不局限于机器学习的一个方面,而是可以应用于改善计算机视觉、自然语言处理或基于代理的环境的方法——因为它的多功能性和搜索空间只受其遗传编码的表达能力的限制。创建神经进化算法时要考虑和组合的方面很多,但首先需要通过对问题及其具体特征的准确分析来确定,以便可以最有效地利用问题环境。
神经进化的里程碑式研究
如果不提及该领域的重要研究,尤其是*年来的研究,对神经进化的广泛介绍是不完整的。尽管位于奥斯汀的德克萨斯大学的神经进化研究小组可能拥有该领域最完整的出版物收藏,但下面列出的里程碑式的研究及其创新想法是否提供了一个良好的开端。虽然在这个列表中的第一个条目之前已经产生了大量的研究(参见姚 1999 年的《进化的人工神经网络》[2]),但是我们是否专注于与今天最相关的研究。
通过扩充拓扑进化神经网络,2002 [3][4][5] 引入了扩充拓扑的神经进化(NEAT)算法,超越了当时大多数已建立的神经进化算法。NEAT 通过突变和无损重组以严格的加法方式进化出有限的直接编码,同时通过物种形成保护创新。由于其简单性和同步能力,NEAT 可以被认为是典型的神经进化算法,因此至今被认为是关键的基准算法。
一种用于进化大规模神经网络的基于超立方体的编码,2009 [6] 引入了 HyperNEAT,它是 NEAT 的一种扩展,使用相同的原理,但采用了一种称为组合模式产生网络(CPPNs)的间接编码。这些 CPPNs 允许神经网络复制对称和重复的基序,不仅更准确地反映人类大脑的组成,而且通过将其映射到网络拓扑来利用应用问题中固有的几何和结构。
进化超净基质中神经元的位置和密度,2010【8】引入了 ES-HyperNEAT,它通过在更高信息区域的 CPPN 编码模式中允许更密集的基质来进一步扩展超净。虽然 HyperNEAT 让用户决定在一个潜在的无限密集的几何结构中何处放置隐藏的神经元,但 ES-HyperNEAT 是否采用了一种类似四叉树的结构来决定这些隐藏节点的密度和位置。在其迭代形式[9]中,它能够在关键基准测试中胜过经典的 HyperNEAT。
通用雅达利游戏的神经进化方法,2014 [10] 本文展示了神经进化在通用视频游戏(GVGP)中的潜力,因为它采用了 CNE、CMA-ES、NEAT 和 HyperNEAT 算法来解决 61 个雅达利 2600 视频游戏。虽然神经进化在 GVGP 或 videograme AI 的研究之前已经部署,但就我们所知,这是否构成了最大规模的演示。结果如预期的那样,它们表明直接编码方法在紧凑的状态表示上工作得最好,而间接编码允许缩放到更高维的表示。
DLNE:深度学习和神经进化的杂交,用于视觉控制,2017 [11] 通过将神经进化与 CNN 的结合用于图像识别,介绍了在我看来最有趣和最有前途的用法之一。本文通过 CNN 进行图像识别,将识别的图像转换为特征表示,然后将其输入神经进化优化的神经网络,研究了复杂的第一人称射击视频游戏环境中神经进化的潜力。虽然这种方法的有效性在很大程度上取决于特征表示的质量,但即使采用简单的方法也表明了一个有前途的研究方向。

图像分类器大规模进化,2017【12】通过在 CIFAR-10/100 数据集上以前所未有的规模进化图像分类器网络,展示了神经进化的巨大潜力。研究人员利用了一个简单的竞争共同进化方案,没有物种形成或交叉,只利用基本操作来变异张量流模型,随后训练它们,然后相互评估它们。因此,所有基因组都是独立的,并且可以并行化,从而实现了巨大的规模,通过利用 Tensorflow 模型的快速 GPU 实现进一步加速了这一规模。
进化中的深度神经网络,2018【13】针对*年来深度学习的兴起,引入了对成熟的 NEAT 算法的扩展 CoDeepNEAT。本文首先定义了 DeepNEAT,一种层间接编码(包括超参数等)来以紧凑的形式表示整个深度神经网络。这些深度基因组然后被视为模块,并与蓝图共同进化,后者由多个重复模块组成,因此利用了大多数成功网络(如 GoogleNet/ResNet)由重复基元组成的事实。该网络在 CIFAR-10 数据集上进行了基准测试,结果令人满意。
图像分类器架构搜索的正则化进化,2018【14】本文是 Real 等人早期论文图像分类器大规模进化的扩展,介绍了进化后的图像分类器 AmoebaNet-A,它超越了之前的任何设计——包括手工设计——并设定了新的最先进的 83.9% top-1 / 96.6% top-5 ImageNet 精度。他们通过修改早期定义的简单竞争共同进化方案来实现这一目标,该方案具有有利于年轻基因型的年龄属性。他们这样做的同时,与一个众所周知的强化学习算法进行了对照比较,这证明了进化可以在相同的硬件上更快地获得结果。
通过神经进化设计神经网络,2019【15】这篇论文是对现代神经进化的优秀综述,由该领域最杰出的四位研究人员共同撰写。它总结并说明了神经进化的每个重要方面,尽管它没有引入新的概念,但这篇综述的目的是重新激发对该领域的兴趣,就像这篇博文一样。我们强烈推荐任何对该领域感兴趣的人阅读这篇文章。
用于深度学习的进化神经 AutoML,2019【16】引入了名为 LEAF 的强大进化 AutoML 框架,利用了来自相同作者的现有最先进的进化算法 CoDeepNEAT。虽然作者没有公开他们的源代码,但他们提供了对其设计的广泛讨论,并提供了有价值的输入。evolutionary AutoML 框架的性能在医学图像分类和自然语言分析任务上进行了评估,非常有前途,超过了现有的最先进的 AutoML 系统和最好的手工设计的解决方案。
第二部分和第三部分展望
本博客系列的第二和第三部分将关注围绕神经进化的开源环境,特别关注 Tensorflow-Neuroevolution 框架【1】。第 2 部分将重点介绍 Tensorflow-Neuroevolution 框架的设计和性能,介绍其模块化方法,给出一个自己设计自定义神经进化算法的具体示例,并为其他库提供性能基准。第 3 部分将广泛介绍 AmoebaNET 和 CoDeepNEAT 的高级神经进化方法,同时还将密切参考代码库并给出它们用法的具体示例。
承认
我要感谢rezza fara Hani,他是我 2019 年谷歌代码之夏的导师,我与他在神经进化和 TFNE 框架方面密切合作。我还要感谢伟大的谷歌代码之夏和 Tensorflow 团队,特别是 Paige Bailey 的持续支持和反馈以及一个伟大的项目。
最后一点
所有未注明出处的插图都是我创作的,并上传到与这一系列博文相关的我的 github 库。我还打算在同一个存储库中发布本系列未来的博客文章中创建的任何代码或材料。
参考
[1]保尔斯,法拉哈尼;tensor flow-神经进化框架;2019
[2]姚; 进化人工神经网络;IEEE1999
[3]欧·斯坦利,米库莱宁; 通过扩充拓扑进化神经网络;麻省理工学院出版社;2002
[4]欧·斯坦利,米库莱宁; 高效进化的神经网络拓扑;德克萨斯大学奥斯汀分校;2002
[5]欧·斯坦利; 通过复杂化高效进化神经网络;德克萨斯大学奥斯汀分校;2004
[6]欧·斯坦利、德安布罗休、高西; 一种用于进化大规模神经网络的超立方体编码;MITP;2009
[7]瑞西,休斯,欧·斯坦利; 进化具有新颖性搜索的塑料神经网络;适应性行为——动物、动画、软件代理、机器人、适应性系统;2010
[8]瑞西、雷曼、欧·斯坦利; 进化出超净基底中神经元的位置和密度;GECCO2011
[9]里西,欧·斯坦利; 增强 ES-HyperNEAT 进化出更复杂的规则神经网络;GECCO2011
[10] Hausknecht,Lehman,Miikkulainen, 一种用神经进化方法玩一般雅达利游戏的方法;IEEE2014
[11]普雷希特·鲍尔森、索霍格、赫维什赫·冯奇、里西; DLNE:深度学习和神经进化的杂交,用于视觉控制;IEEE2017
[12] Real,Moore,Selle,Saxena,leon Suematsu,Tan,Le,Kurakin 大规模进化的图像分类器;CoRR2017
[13]米库莱宁、梁、迈耶森、拉瓦尔、芬克、弗兰肯、拉朱、沙尔扎德、纳夫鲁兹扬、达菲、霍德贾特; 不断进化的深度神经网络;神经网络和大脑计算时代的人工智能;2018
[14] Real,Aggarwal,黄,乐; 用于图像分类器架构搜索的正则化进化;CoRR2018
[15]欧·斯坦利、克吕纳、雷曼、米库莱宁; 通过神经进化设计神经网络;自然机器智能;2019
[16]梁,迈耶森,霍德贾特,芬克,,米库拉宁; 深度学习的进化神经 AutoML;GECCO2019
[17]得克萨斯大学奥斯汀分校; 神经进化研究组
最重要的机器学习方法入门

麦克斯威尔·尼尔森https://unsplash.com/@maxcodes拍摄的照片
机器学习已经存在于我们的日常生活中,并且是我们经常使用的许多产品和服务的重要部分。公司使用机器学习来创造新的令人惊叹的产品,使他们现有的产品和服务更好,并解决广泛的商业问题。随着公司急于将机器学习用于自己的优势,他们将大部分转型努力和预算集中在使用这些技术来实现增长上。
为了在商业环境中成功地应用机器学习,不管专业背景或以前的机器学习经验如何,理解方法的差异是关键。知道何时使用哪种方法以及如何开始,有助于发现和实现增长潜力。当处理不同类型的挑战时,能够为特定用例找到正确的技术对成功至关重要。从图像分类或营销活动影响预测,关于不同机器学习方法的知识有助于朝着正确的方向前进。
本文将介绍机器学习,它的范围和三个重要的区别,这有助于决定哪种机器学习技术用于哪种类型的问题。
机器学习的定义和主要范围
机器学习有许多定义,从不同的角度来看——有些更通用,有些更面向工程。
下面的定义应该能给我们所讨论的内容一个好的印象:
“机器学习是给计算机编程的科学(和艺术),让它们能够从数据中学习。”(未知)
这里是一个更强调学习部分的一般定义:
“[机器学习是]一个研究领域,它赋予计算机无需明确编程就能学习的能力。”(阿瑟·塞缪尔,1959)
最后一个定义代表了更加面向工程的观点:
“如果一个计算机程序在 T 上的性能(由 P 测量)随着经验 E 而提高,则称该程序从关于某个任务 T 和某个性能测量 P 的经验 E 中学习。”(Tom Mitchell,1997)
机器学习可以用来解决各种各样的问题。在向它输入训练数据(包括输入特征和相关结果的示例)后,它会计算出一个规则集,用于对未来进行预测。规则集是通过所选技术采用的算法在幕后生成的。这是传统数据分析方法的一个主要区别,传统数据分析方法经常手动构建显式逻辑。如果一个问题很复杂,并且涉及各种不同的参数,这可能会变得很乏味。尤其是当情况发生变化时,手动生成的规则集需要更新,有时甚至需要完全重新校准。此外,消化大量数据和手动检测底层逻辑在传统方法中可能是一个巨大的问题,而机器学习很好地解决了这个问题。
垃圾邮件分类的例子可以说明机器学习的好处。通过使用机器学习来构建垃圾邮件过滤逻辑,可以避免为电子邮件中的垃圾邮件短语手动实现长的规则列表。如果实施更复杂的垃圾邮件攻击,手动列表方法会变得非常复杂。在这种情况下,这种方法通常不适合根据不断变化的攻击来调整过滤逻辑。相比之下,机器学习是毫不费力地为成功的垃圾邮件分类建立复杂逻辑的方法。它避免了大量的手动调整,可以处理波动的环境和大量的数据。
机器学习方法的不同点
有各种角度,可以用来区分机器学习方法。三种常见的是:
- 人工监督
- 在线或批量学习
- 基于实例或基于模型的学习
人工监督
当涉及到人类监督时,主要类型有监督学习、非监督学习、半监督学习和强化学习。
监督学习
监督学习的关键特征是输出的标签是预先定义的。人类决定结果的结构,从而直接监督模型的训练工作。在监督学习中,主要的任务类型是分类和回归。
分类预测数据集属于或导致预定义输出类别的可能性。在分类训练期间,由特征(也称为预测值)和标签(也称为类别)组成的数据被输入算法,每个数据集与类别和类别分配的关系的可能性就出来了。分类问题的一个常见例子是上述电子邮件垃圾邮件过滤,其中对“垃圾邮件”和“非垃圾邮件”进行了明确的分类。
另一种主要方法是回归,目的是根据输入数据的特征预测一个特定的数值。与分类一样,训练是基于输入特征以及相应的结果来完成的。当新数据输入模型时,可以预测输出值。监督学习中回归任务的用例包括股票价格预测、经济统计和客户满意度得分。
对于分类和回归这两种方法,经常使用以下算法:
- k-最*邻
- 线性回归
- 逻辑回归
- 支持向量机
- 决策树和随机森林
- 神经网络
虽然一些算法自然倾向于这两种方法中的一种,但是它们也可以用于另一种。
无监督学习
与监督学习(人类通过指定输出的标签来决定输出的结构)相比,无监督学习完全不考虑预定义标签的使用-系统独立学习并建议输出结构。
无监督学习问题的主要类型是聚类、异常和新奇检测、可视化和降维以及关联规则学习。
通过使用聚类算法,您可以将数据集分成组,例如,将客户分成具有相似特征或行为的不同客户群。最重要的是,层次聚类允许在已经找到的聚类中进行额外的细分,因此客户细分可以被分割成更小的单元。
异常检测可用于检测和移除数据中的异常值。这种技术用于检测不正常的信用卡交易,从而防止欺诈活动。它还可用于预测性维护工作,以识别潜在的机器数据异常,并在早期阶段防止缺陷。与异常检测密切相关的是新奇检测,其仅在正常数据上训练,并且在该过程中不期望异常值。
可视化也属于无监督学习方法。通过提供大量非结构化和无标签的信息,该方法产生了信息的图形可观察的描绘(主要是二维或三维的)。这可以很容易地绘制出来,以了解信息是如何组成的,从而得出潜在的模式。与之密切相关的是降维,其目标是在不丢失重要信息的情况下减少数据量。这在特征提取中也起作用。它通过降低模型的维度(即从三阶函数到二阶函数)来*衡模型的复杂性和手头的问题。这种技术可以用来避免过度拟合。除了通过降维模型生成的增强洞察力之外,您还可以将结果用作其他机器学习方法的输入。
关联规则学习是我们无监督学习概述中的最后一种方法,旨在揭示大型数据集中有趣的关系,主要是通过找出特征之间的联系。突出的应用通常出现在零售领域,其中经常一起购买的商品通过关联规则学习工作来识别,并因此在超市货架上彼此靠*放置。
用于无监督学习方法的主要算法有:

无监督学习方法的算法
半监督学习
在半监督学习这个术语的背后,是监督学习和非监督学习这两个领域的方法的结合。这种混合方法适用于部分标记的训练数据,其中大部分实际上是未标记的,小部分是标记的。半监督学习的突出例子是科技公司(如谷歌、苹果)的照片应用程序,该应用程序可以识别哪些人经常出现在照片中,并相应地对照片进行聚类(=无监督),让用户为这些聚类提供标签,这些标签是被识别的人的名字(=有监督)。
半监督学习的流行算法是深度信念网络 (DBNs),它与受限波尔兹曼机器 (RBMs),一种特定类型的人工神经网络一起工作,用于无监督部分。它们也可以相互堆叠。在训练 RBMs(无监督的)之后,可以通过使用各种监督学习方法来增强它们。
强化学习
与监督、非监督和半监督学习相比,强化学习是一种非常不同的动物。这种技术集中于学习系统、它运行的环境、它所具有的状态以及改变它以便更接*预定目标的方法。
强化学习系统被称为代理,它具有感知环境以及决定和执行动作的能力。每次行动后,系统都会收到一份奖励,奖励可以是积极的,也可以是消极的,这取决于该行动是否有助于实现目标。在训练期间,强化学习系统必须学习最佳策略(= 策略)以最大化回报。策略可以被理解为当系统被放置到一个环境中并朝着一个目标前进时要执行的行动计划。
强化学习最受欢迎的例子之一是 AlphaGo,这是一台基于人工智能的超级计算机,在围棋比赛中击败了人类世界冠军。AlphaGo 在很大程度上基于深度强化学习,并制定了一种策略来赢得围棋比赛。AlphaGo 成功的一个令人惊讶的方面是,该系统能够开发出非常非常规的策略,这些策略最初被人类对手认为是有害的,并导致混乱。然而,它们被证明是为人工智能在稍后的时间点最终赢得游戏而做的准备,这使人们认识到人工智能已经能够做到什么。
在线与批量学习
对机器学习方法进行分类的第二个角度是区分它是否可以增量学习,即从数据流中学习,或者需要在单独的批次中训练。
批量学习
批量学习不适用于基于输入数据的增量适应,而是必须使用一部分可访问的数据一次性进行。由于批量学习在计算上是昂贵的,并且不是在线进行的,而是作为一个不连续的作业,所以它也被称为离线学习。在对系统进行训练并将其投入生产环境后,它将使用学到的功能,而无需重新训练,直至另行通知。
批量学习是大多数机器学习应用程序的标准情况,只要每条新信息对模型的质量都不是至关重要的。在涉及边缘设备的物联网使用案例中,如联网农业,几乎不可能建立自我再培训基础设施。在这种情况下,物联网设备携带一个版本的模型,该模型已经过批量数据训练,并在现场进行预测,直到预测质量变得不足。在这种情况下,设备将离线,并使用重新训练模型进行更新。
在线学习
与批量学习相反,在线学习以增量方式训练机器学习系统。数据以单个数据片段或所谓的小批量顺序发送到系统。通过这种方法,模型可以即时消化新的数据,使其成为任何给定时间的最佳预测器。学习率用于衡量模型适应新输入数据的能力。对于在线学习,增量学习迭代在计算上是廉价的。您可以在使用数据流的用例中找到在线学习方法,每条新信息对模型的质量都很重要。一个典型的例子是金融市场中的算法交易。
基于实例与基于模型的学习
比较机器学习系统的第三个角度是指处理输入数据的方法。这里的关键区别在于,新信息是仅仅与现有数据进行比较,还是用于建立模型,该模型用作检测到的模式的*似,以进行预测。
基于实例的学习
作为一种专注于新数据与历史数据比较的方法,基于实例的学习擅长记住以前数据的确切表示。在模型应用期间,通过采用相似性度量将新数据与历史数据进行比较,该相似性度量可以简单到数据集之间的公共数据点的数量。
基于实例的学习在推荐系统中得到应用,因为它评估相似性,即客户兴趣,这可以用于推荐相似客户观看的电影或相似客户购买的文章。
基于模型的学习
基于模型的学习不直接与训练数据进行比较,而是从训练示例中构建新的模型来预测结果。由于模型是基于从训练中提取的规则进行概括的,因此可能容易出现训练数据中的不准确性,这应该通过探索性数据分析和特征工程来发现并最小化。此外,所选择的模型类型应该适合手头任务的复杂性和类型。为了测量预测的质量,使用性能度量,其可以是效用函数或成本函数。效用函数衡量模型的“正确”程度,而成本函数评估误差的大小。
基于模型的学习是大多数非*凡机器学习应用的典型方法,因为非常复杂的问题通常可以通过模型而不是实例相似性比较来更有效地*似。
总结
机器学习定义| 机器学习是给计算机编程的科学(和艺术),以便它们可以从数据中学习。
机器学习的目的| 机器学习是一种基于复杂逻辑、波动环境和大量数据进行预测的方法。
监督学习| 输入算法的训练数据包括所需的标签。监督学习可以执行关于类分配(=分类)或数值分配(=回归)的预测。
无监督学习| 训练数据是无标签的,系统独立学习以揭示数据中的模式——方法有聚类、异常和新奇检测、可视化和维数减少以及关联规则学习。
半监督学习| 使用非监督和监督学习算法的机器学习方法。它处理部分标记的训练数据。
强化学习| 专注于学习系统(=代理)的方法,该系统在环境中行动,并试图制定行动策略以达到目标状态——根据行动的成功获得积极或消极的奖励。
批量学习| 基于所有可访问数据的高强度训练,无需增量再训练——用于没有完整训练基础设施的环境,即物联网边缘设备。
在线学习| 一种计算成本低廉的方法,它以增量方式训练机器学习系统,使模型在任何给定时间都可能成为最佳预测器。
基于实例的学习| 将新数据与现有数据进行比较并采用相似性度量的训练方法。
基于模型的学习| 从训练样本中建立新模型的学习方法,以效用或成本函数衡量的准确度预测结果。
本文的灵感来自《使用 Scikit-Learn、Keras 和 TensorFlow 进行机器学习:构建智能系统的概念、工具和技术》一书,该书提供了更多的深度和实践练习。
对机器学习的以原则为中心的理解是一种超能力
想象一本以原理为中心的机器学习书
如果你一直在关注这个趋势,那么一个在网络上越来越流行的问题就是“我该如何开始或者从哪里开始学习 ML?”人们总是用不同的方式问同一个问题。听起来这个问题还没有得到充分的回答。我的诊断是,人们得到了善意的答案,却没有就什么是最好的教学方法或学习途径达成一致。这背后的原因是,大多数推荐的学习路径都属于以技术为中心或以方法为中心的学习方法。我推荐采取 以原则为中心的方法。
以原则为中心的方法一直存在,并且一直被推荐。传奇人物吉姆·凯勒推荐(直到第二分钟)推荐一种以原则为中心的方法,如果你想擅长某件事,可以用“执行一个食谱 vs 了解烹饪”+ 类比
为什么是超级大国?
将你的第一个逻辑回归或递归神经网络(RNN) 模型拟合在一个表现良好的精选数据集上会感觉像是魔术一样,直到你面临一个复杂的现实世界的业务问题,数据集非常混乱,甚至更糟,根本没有数据集。大多数 ML 从业者,尤其是那些有编程背景的人,想知道为什么他们会在 ML 的旅程中碰壁。这完全是基于当前流行的以方法为中心或以技术为中心的 ML 教学法。一种以技术为中心的教育学将强制的严格性剥离,以实现一些狭隘的承诺。在我的第一次 Kaggle 游乐场比赛中,我花了 188 份作品才进入前 1%。当我们没有很好地掌握原则时,就会发生这种情况。所以请相信我的话。
“方法可以有一百万种以上,原理却很少。掌握原则的人能够成功地选择自己的方法。尝试方法的人,忽视原则,肯定会有麻烦。”——哈林顿·埃默森
套用哈林顿的话,如果你知道这些原则,你就可以定制特定问题的方法来创造性地应用 ML。在像 ML 这样的超衍生领域,掌握好原则是你超越同行的独特竞争优势。
- 职业灵活性:它为从业者提供了一条坚实的道路,使他们能够转变为经验丰富的 ML 从业者(或基于倾向的 ML 研究者)。ML 从业者是应用 ML 解决现实世界问题的人,而 ML 研究者是寻找 ML 下一个前沿的边界推进者。但是与传统智慧相反,也就是说,不要认为洗钱实践和洗钱研究是两条独立的职业道路,认为洗钱研究是洗钱实践的自然进展有更好的效用。以原则为中心的教学法可以帮助你轻松地通过这个范围。
入门级 M L 从业者 →资深 ML 从业者 →资深 ML 从业者 → ML 研究员
- 整体产品思维:以原则为中心的方法可以帮助您超越仅仅拟合模型,并从整体上对产品进行推理,该模型将如何以及在哪里使用,谁是用户,用户体验和 SLA 承诺是什么,有哪些约束,什么是成功的关键,以及有哪些权衡。
- 学习速度: ML 是一个非常跨学科的领域,由于最*的大肆宣传,它以极快的速度发展,所以你不能通过放弃原则和从 10 或 100 个食谱中学习来线性扩展你的技能。不仅仅是在 ML 中,更快地自学硬东西的能力也是一种竞争优势。了解这些原则会缩短你的学习周期。你将能够进行广泛而深入的推理。
- 通用语:因为 ML 非常跨学科,它吸引了来自不同行业的从业者,从应用统计学家到物理学博士,可能还有参加深度学习课程的音乐家或艺术家。ML 从业者的人口是非常异质的,不像普通的程序员。所以对原则有一个很好的理解可以帮助你和它们进行有意义的对话。
- 遗留包袱和兔子洞:因为 ML 是非常跨学科的,所以根据你来自哪个阵营,它带有大量的多义词(一词多义)和负载词(多词一义)。这通常会让你掉进兔子洞。了解这些原则可以帮助你更容易地理解复杂的概念。
- 躲避炒作:你会知道什么是技术上可行的。这样你就可以教育自己和他人 ML 的局限性,做出有意义的承诺。
点击这里查看我的新书
**** 我不是想卖书,这本书是 免费阅读 。 我的分享纯粹是基于人类利他主义的精神****

数据科学的深入概率速成课程
集合论,概率性质,样本空间,计数技术,条件概率,贝叶斯定理

目录
- 介绍
- 集合论
- 可能性
- 计数技术
- 条件概率
- 贝叶斯定理
介绍
无论你是否从事数据科学职业,理解概率的基本原理都将大有裨益。不管怎样都是好知识。我的目标是提供一个全面的概率基础速成课程,你应该知道,以便你的数据科学之旅(或一般的旅程)更顺利地前进。
说了这么多,让我们开始吧!
集合论
条款
- 一个集合是元素的集合。
- 更具体地说,样本空间(表示为 S) 是给定实验的所有可能结果的集合。例如,骰子(骰子的单数)所有可能结果的样本空间是 S = {1,2,3,4,5,6}。
- 有限样本空间是具有 n 个小于无穷大的不同元素的样本空间。
- 简单样本空间 (SSS)是一个有限的样本空间,其中所有的结果都是同等可能的。
- 通用集合,记为 U ,是万物的集合。
- 空集,记为 ∅ ,是一个里面什么也没有的集合。它是…空的。
- 基数定义为集合 A 中元素的个数,记为 |A| 。
- 如果集合 a 中的所有元素也在集合 b 中,则集合 a 是集合 b 的子集,符号等价为⊆。
- 一个事件是一组可能的结果。S 的任何子集都是事件。

a 是 B 的子集
- 给定集合 A 的补集是具有集合 A 所没有的所有元素的集合,记为A’。见下图。

- 集合 a 和集合 b 的交集是集合 A 和集合 b中的元素,记为 A⋂B 。见下图。

A 和 B 的交点
- 集合 a 和集合 b 的并是集合 A 或集合 b中的元素,记为 A⋃B 。见下图。

A 和 B 的结合
如果集合 a 和集合 b 的交集等于空集(A⋂B=∅). ),则称集合 a 和集合 b 不相交

集合 A 与集合 B 不相交的例子
集合运算定律
补充
- a⋃a' = u(a 和补 a 的并集等于泛集)
- a⋂a' =∅(a 和补 a 的交集等于空集)
- A ' ' = A(A 的补码的补码等于 A)
换位定律
- a⋃b = b⋃a(a 和 b 的并等于 b 和 a 的并)
- a⋂b = b⋂a(a 和 b 的交集等于 b 和 a 的交集)
摩根定律
- (A⋃B)' = A'⋂B' )
- (A⋂B)' = A'⋃B' )
结合律
- 【a⋃(b⋃c】=(a⋃b)⋃c = a⋃b⋃c
- 【a⋂(b⋂c】=(a⋂b)⋂c = a⋂b⋂c
分配定律
- A⋃(B⋂C) = (A⋃B)⋂(A⋃C)
- A⋂(B⋃C) = (A⋂B)⋃(A⋂C)
可能性
对于作为样本空间 S 的子集的每个事件 A,存在概率 A,表示为 P(A)。
概率公理
- 0 ≤ P(A) ≤ 1
- P(S) = 1
- 如果 A⋂B = ∅,那么 p(a⋃b = p(a)+p(b)
- 假设有 k 个不相交的事件。所有 k 个事件联合的概率等于每个个体概率之和。
概率的性质
注意:我不打算看样张,所以如果你想知道样张,你可以在谷歌上搜索样张或者在 LinkedIn 上给我发短信。
- P(∅) = 0
- P(A') = 1 — P(A)
- 对于任何两个事件 a 和 b,P(A⋃B) = P(A) + P(B) - P(A⋂B)
- 对于任何三个事件 a,b,c,p(a⋃b⋃c)= p(a)+p(b)+p(c)-p(a⋂b)-p(b⋂c)-p(a⋂c)+p(a⋂b⋂c)
- 如果 A 是 B 的子集,那么 P(A) ≤ P(B)
计数技术
注意:这些技术严格用于简单样本空间(SSS)。
加法规则
定义:如果做一件事有 n 种方式,做另一件事有 m 种方式而你不能同时做,那么就有 n+m 种方式选择一件事去做。
例如,有 5 种冰淇淋口味可供选择,4 种冷冻酸奶口味可供选择,而你只能选择一种,那么你有 9 个选项可供选择(4+5)。
这可以扩展到 1 次操作之外。
乘法法则
定义:如果做一件事有 n 种方式,做另一件事有 m 种方式,那么这两种动作都有 n*m 种执行方式,其中一件事在另一件事之前执行。
例如,如果从加拿大到美国有 2 种不同的方式,从美国到墨西哥有 4 种不同的方式,那么从加拿大到墨西哥有 8 种不同的方式(2*4)。
这可以扩展到 1 次操作之外。
排列
定义:n 个元素的排列是那 n 个元素按照确定的顺序的任意排列。有 n 个阶乘(n!)排列 n 个元素的方式。注意粗体字:顺序很重要!
一次取 r 的 n 个事物的排列数被定义为可以从 n 个不同元素中取出的 r 元组的数目,并且等于以下等式:

例子:一个 6 位数的车牌有多少种排列?

组合
定义:从 n 个对象中选择 r 的方法的数量,其中顺序无关紧要。
一次取 r 的 n 个事物的组合数被定义为一个具有 n 个元素的集合中具有 r 个元素的子集的数目,等于以下等式:

示例:从一副 52 张牌中抽取 6 张牌有多少种方法?

条件概率
条件概率是在一个事件已经发生的情况下,另一个事件发生的概率。形式上,如果 P(B) > 0,那么给定 B 的条件概率等于下面的等式:

给定这个等式,我们可以推导出下面的等式…


性能
- 0 ≤ P(A|B) ≤ 1
- P(S|B) = 1
- 如果 a1⋂a2 =∅→p(a1⋃a2|b)= p(a1 | b)+p(a2 | b)
独立性ˌ自立性
- 如果 a 和 B 互不相关,则称它们相互独立。
- a 和 b 是独立的当且仅当 P(A⋂B) = P(A)P(B)
- 如果 P(B) > 0 并且 A 和 B 是独立的,那么 P(A|B) = P(A)
贝叶斯定理
全概率定律
全概率定律如下。

在上面的一个例子中,你实际上已经看到了这一点。(还记得下图吗?)

考虑全概率定律以及下面的等式:

考虑到这两个方程,我们来看看贝叶斯定理。
贝叶斯定理
如果 n 个事件 A 构成 S 的一个划分,B 是任意事件,那么:

贝叶斯定理在数据科学中的主要应用之一是朴素贝叶斯分类器。如果你想了解更多,请查看我的文章,5 分钟内对朴素贝叶斯的数学解释!
感谢阅读!
特伦斯·申
创始人ShinTwin|我们来连线一下LinkedIn|项目组合这里是。
餐厅空调研究的一个问题
你可能最*在广州的一家餐馆看到了新型冠状病毒病毒的潜在传播。它摘自《新兴传染病》杂志上一篇尚未定稿的论文。令人担忧的是,如此多的媒体将这篇文章和图片作为事实分享。
该研究报告了相邻三桌的人后来如何被检测出新型冠状病毒阳性,但餐厅中其他不同桌的人却没有。作者总结道:“空调通风促进了飞沫传播。”作者报告了桌子之间的*均距离,但没有给出确切的距离。当你看下面左边的图表时,你可以看到他们将 8.3 米和 17.5 米视为完全相同的距离,将一个狭长的餐厅变成了一个正方形。这使得没有感染的桌子看起来比我们根据实际尺寸将它们*均隔开时更*:

来自广州的餐厅布局,在这里重新安排以显示餐厅的实际尺寸。
正如你在图中看到的,当我们更精确地绘制距离时,没有感染者的桌子看起来更远。作为参考,本文如下:
[## 图-2020 年中国广州与餐馆空调有关的新冠肺炎病毒爆发…
2020 年 1 月 26 日-2 月 10 日期间,2019 年新型冠状病毒疾病在…
wwwnc.cdc.gov](https://wwwnc.cdc.gov/eid/article/26/7/20-0764-f1)
这是那篇论文的原始图表:

【https://wwwnc.cdc.gov/eid/article/26/7/20-0764-f1】来源:
这个错误似乎不仅仅是“17.5 米”的错误,因为作者报告的空间总*方米数为 145 *方米,这与 8.3 米 x 17.5m 米的尺寸一致。“6.0 米”和“8.3 米”的水*尺寸似乎成比例,因此只有垂直尺寸有问题。
我从事流行病跟踪和灾难响应工作多年,包括空间数据建模,我从未见过有人像这样压缩维度(尽管我从未在室内从事灾难响应的空间数据建模工作)。特别值得关注的是,在垂直维度上的压缩使得图像支持他们的结论,但是在该论文中没有提到压缩及其原因。
时间重叠也让人摸不着头脑。根据该论文,表 A 与表 B 重叠了 53 分钟,与表 C 重叠了 73 分钟。表格 A 与 E 或 F 重叠了多久?这是没有报道的。
世界上最大的媒体机构转载了这一扭曲的形象,却没有对此发表评论。例如,《纽约时报》以“冠状病毒如何在一家餐馆感染了一些人,但不是所有人”为标题报道了这张图片。《印度斯坦时报》以“空调气流在中国餐厅传播新冠肺炎”为标题进行了报道,并进一步精心制作了一个新版本的图形,在那里他们将其介绍为“发生了什么”:

《印度斯坦时报》仔细复制了整个图像,并为每张被感染的桌子制作了日历,但没有注意到,如果与“6 米”尺寸在同一尺度上,它们的“5 米”尺寸实际上大约是“3.5 米”。他们还危险地将模棱两可的发现报道为“发生了什么”。来源:https://www . hindustantimes . com/world-news/AC-air-flow-spread-新冠肺炎-在中国-餐厅/story-4x u9 yvc 3 bayakahv 7 bmoo . html
我们能相信这项研究吗?
不,这个研究不可信。我们已经知道距离是传播的主要因素之一,这项研究没有提供证据来改变这一点。在报告 A 桌的人和 B 桌、C 桌、E 桌和 F 桌的人之间的确切距离以及他们重叠的时间长度之前,该论文是不可信的。目前,该论文仅报告了表之间的距离为“大约 1 米”,当我们查看非失真图中的可用空间时,这对于表 E 和 F 是极不可能的。
即使人与人之间的距离和时间重叠是一样的,就像论文暗示的那样,结果仍然是微弱的。例如,有 21 人不在 A 桌,但被呈现为坐在 A 桌附*,其中 5 人后来检测为阳性:
5/21 = 23.8% chance of being infected
E 桌和 F 桌有 5 个人。那么,一张 5 人的桌子上至少有一个人被 23.8%的传染率感染的可能性有多大?
1-(1-(5/21))⁵ = 74.3% chance that at least one person at a table of 5 is infected.
这不是很有力的证据。换句话说,与表 A 相邻的所有表的感染率有 1/4 的几率是完全随机的。没有哪个科学领域应该接受只有 74.3%正确几率的结论。
对于本文而言,74.3%是最佳情况。作者指出,传播可能只针对邻桌的一个人,然后再传播给其他人。在这种情况下,邻桌至少有一人被感染的可能性只有 39.4%:
1-(1-(2/21))⁵ = 39.4% chance that at least one person at a table of 5 is infected.
因此,如果模式是 A 桌的一个人感染 B 桌和 C 桌的一个人,这些人又感染他们组中的其他人,那么 E 桌和 F 桌更有可能而不是被感染,即使它们离 A 桌的距离相同,并且人们在那里停留的时间相同。
我还期待一个更复杂的数学模型,包括更长距离的更大分散,我很惊讶这没有出现在原始论文中。气流箭头似乎是推测的,而不是基于观察。还有许多其他因素:A 桌的源人是否走* B 桌和 C 桌(他们在去洗手间的路上会经过 B 桌或 C 桌);是否靠*空调增加了表 C 的传播机会,因为鼻腔干燥;以及感染完全来自其他地方的可能性。考虑到所有这些因素,以及距离和时间重叠的正确建模,附*赌桌的 74.3%和 39.4%的概率几乎肯定会下降。
如此小的样本数,置信区间也会非常高。例如,如果我们只带走一个感染者,并得出结论,只有 4 个人在 E 桌坐了足够长的时间,那么 74.3%就变成了 61.2%。从这么少的数据点中获取精确的信息是不可能的。有了所有人之间的距离和重叠时间的准确细节,这些数据就可以整合到更大的研究中,包括其他地方记录的潜在传输。但是没有这些信息,这篇文章不能帮助我们得出可操作的结论。
虽然我在灾难应对领域工作多年,包括流行病跟踪,但我不是流行病学家或传染病传播方面的专家。因此,即使我能从他们的研究中得出有力的结论,我也不会分享它们。如果你没有这方面的经验,你也不应该这样做:已经有太多的流行病学专家了。然而,你对任何媒体报道背后的科学方法进行批判性分析是正确的,特别是像维度压缩超过 50%这样的不一致。
请注意,可以拒绝基于简单的最佳情况模型的结论,就像我上面所做的那样。然而,一个简单的最佳情况模型不能用来支持其他一些结论。如果你有数据科学技能,并希望为新冠肺炎应对措施做出贡献,那么有许多方法可以帮助你,而不需要事先了解感染知识。我推荐我的文章:数据科学家可以帮助应对新冠肺炎的 5 种方式和避免的 5 种行动:
[## 数据科学家可以帮助应对新冠肺炎的 5 种方式和应避免的 5 种行动
数据科学家如何在其组织内以及更广泛的范围内帮助应对新冠肺炎疫情?
towardsdatascience.com](/5-ways-data-scientists-can-help-respond-to-covid-19-and-5-actions-to-avoid-d2accab283d1)
你将在文章中看到第三种方法是“准备可能与回答直接相关的数据”。这正是我想做的。在新冠肺炎病毒爆发前,我在食品安全部门工作,我试图整理数据,以帮助流行病学家更好地模拟传播风险。
我们知道气流可能是病毒传播的一个因素,所以这是一个值得研究的问题。但是,目前形式的论文根本没有提供证据来支持这样的结论,即除了距离之外,其他任何因素都是这家餐厅传播的主要因素。在我意识到他们压缩了图表中的一个维度之前,我曾经读过这篇论文,并在我的社交媒体订阅中看过这张图片十几次甚至更多次。
这是一个很大的问题,因为像《纽约时报》和《印度斯坦时报》这样的媒体机构正在报道这项研究,而大多数人(像我一样)在第一次看到它时并没有注意到图像的问题。我目前正在帮助数千万人传达新冠肺炎应对措施的信息,当这样的研究被报道为事实时,这对每个人都是不利的。如果人们改变他们的行为的原因不是基于可靠的科学,这很可能使事情变得更糟。
罗伯特·芒罗
2020 年 5 月
作者注: 本文非医学建议。这篇文章中其他人的建议不一定适用于你。向您信任的医疗服务提供者咨询您的医疗建议。
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
使用地理空间数据进行移动分析的产品
是什么让实时位置数据的分析与众不同?

来源:蚱蜢
如今,Geo 几乎无处不在!
随着 GPS 在我们周围的普及和智能手机的兴起,位置数据被大量收集。传说说几乎所有公司存储的数据(~80%)都有位置成分。
我们的生活现在充满了产品和服务,只需轻轻一打电话,就能在几分钟内送货上门!如今,很难找到一款不需要你的位置许可的应用。
在 GIS(地理信息系统)世界里有一句著名的名言说 “一切都发生在某个地方。” 当你从任何一款送餐 app 下单时,从下单开始,到配送主管(DE)被指派,再到 DE 从餐厅取货,再到他送货,每一个事件都发生在某个特定的 lat-long!
这就引出了我的下一个观点:
为什么我们会执着于“位置”这个维度?
首先,没有动态定位就没有“移动性”。换句话说,每当地面上有资产(人、车辆、货物、包裹)移动时,位置是一个基本方面。毕竟,在城市中每*方公里都有变化的城镇,加入这些地区的“背景”是很重要的。
对于我们所处的按需经济,实时分析所有维度(用户、商店、合作伙伴)的位置数据变得非常重要。这是因为你必须将你的供应与需求相匹配,进行基于位置的定价、促销或更快更准确的大规模交付!
最后,对消费者来说,最成功的基于位置的体验是基于非常精细的连续活动:你在哪里?你需要去哪里?到了那里你想做什么?当你需要通过定向广告获得客户,并通过研究他们的行为来留住和吸引他们时,这就变得很重要。
位置不仅仅是地图上的一个点。它是关于一条线的。它是关于运动的。

Airbnb 客人对罗马街区的评价。资料来源:Inverse.com
地点令人兴奋!如果运用得当,它可以推动收入的显著增长(典型的例子:优步& Airbnb)。它的高使用率和实时性使它真正具有价值和粘性。
但是一直以来,选址因素在商业决策中一直被 T2 忽视。这是因为传统的分析工具对于企业拥有的统计数据宝库来说非常棒,但在某些地方,它们达不到基于位置的决策。
你可能会奇怪:“但是,为什么?”
在我们深入探讨之前,让我们了解地理空间数据与统计数据有何不同。
是什么将地理空间数据与统计数据区分开来?
就像文本、声音、图像是不同类型的数据一样,经纬度是一种不同类型的数据,可以在时空环境中为统计数据增加巨大的深度、意义和洞察力。
统计数据以表格形式出现,通常由两个元素组成:随时间变化的值。地理空间数据(也称为地理数据或位置数据)通常被格式化为点(经纬度坐标)、多边形或折线。
它在顶部融入了第三个维度:跨越时间和动态位置的价值——这需要一种完全不同的方法和处理方式。计算静态资产的度量包括在地图上绘制点并计算度量。运动分析关注的是我们如何可视化、分析和优化地面上的物体运动!
地理空间数据的两个特殊属性是自相关性和非*稳性,这使得它很难满足传统(非空间)统计方法(如 OLS 回归)的假设和要求。
空间自相关表示我的测量值在附*的观测值之间有多相似(相关)。也符合地理第一定律——万事万物都与其他事物相关,但*物比远物更相关 ”。
空间不稳定性是一种简单的“全局”模型无法解释变量之间的空间关系的情况。模型的性质会随着空间的变化而变化,并且在研究区域的不同部分表现不同。
现在让我们来回答我们悬而未决的问题:
为什么当前的统计工具不适用于空间分析?

来源:Hyper
如今,公司内部处理位置数据的现行方式已被打破。由于缺乏任何位置分析产品,大多数企业别无选择,只能依赖传统的商业智能和分析工具。这是一个非常无效的策略,这并不令人费解,因为这些工具并不真正用于地理分析。
㈠格式:
大多数公司以ping的形式收集位置日志数据。分析它们所包含的模式的方法是拥有一个可以实时接收这些 pings 的基础设施——这是 Periscope 或 Tableau 等*台无法满足的。****
此外,位置数据以不同的结构存在于不同的数据库中。因此,跨表实时分割变量变得更加复杂。
㈡可视化:
我们都知道,统计仪表板包含条形图和图表,它们是通过对变量进行运算(求和、计数、除法、*均等)而产生的。虽然通过图表上的峰值和谷值获得实时趋势更新可能会有所帮助,但这些图表在汇总的历史数据上工作得更好。
添加或分割经纬线,并在其上创建棒线和图表是徒劳的。为了搞清楚这些纬度,你需要在身边放一张地图来了解它们的空间分布。
控制地理空间仪表板所有属性的另一个重要方面是层。没有这种可以用来在地图上显示多种类型的数据点的分层机制,可能会忽略这一点。例如,层有助于查看我的订单(第一层)和合作伙伴位置(第二层)在我的区域集群(第三层)中的分布情况。
如果地面上有相关部件发生移动,地图也比条形图和图表更有助于推断。因此,当一切都是动态的时,实时地理分析变得至关重要。

可视化纽约出租车旅行。来源:Kepler.gl
㈢汇总:
像 PowerBI 和 Geckoboard 这样的传统 BI 工具提供了在地图上绘制点的能力。然而,仅仅在地图上绘制点是不够的,因为空间中的十亿个点不是很直观。此外,
位置智能不仅仅是在地图上跟踪和标绘点!
像聚类、热图、聚合、索引等策略。派上用场吸收大量积分。
一些工具如 Tableau 和潜望镜也允许创建热图——一种描绘度量模式的奇妙方式。热图的缺点是,它们只是一种可视化表示,因此限制了您对其进行任何类型的分析。
要了解热图不起作用的更多原因,请查看以下内容:
**** [## 让基于位置的实验成为我们 DNA 的一部分
我们能从基于网络的实验中学到什么?
medium.com](https://medium.com/locale-ai/making-location-based-experimentation-a-part-of-our-dna-d30280fc25cc)
更有效的聚合方式是在六边形网格或地理散列上索引它们。一旦您分析了跨网格的度量模式(如需求和供应),您也可以在模型中将单元作为一个单元使用。索引也有助于您的分析变得更加精细。
如果你想了解网格,你可以看看这个:
为什么我们在现场喜欢六边形网格!
towardsdatascience.com](/spatial-modelling-tidbits-honeycomb-or-fishnets-7f0b19273aab)
㈣数据准备:
清理:使用潜望镜和 Thoughtspot ,您可以通过处理空白、空格、数据格式、NAs 等来清理您的统计数据,而 GPS 数据的清理包括将其捕捉到最*的道路或修正空间异常值。(在使用谷歌地图时,你一定经常观察到,GPS 会随机出现在很远的地方。)可以肯定地说,GPS 作为一项技术还有很长的路要走!
合并:像 Tableau Prep 或 Metabase 这样的*台允许你在一个公共标识符的基础上使用一个内连接、左连接或右连接来合并两个表。例如,如果您有跨三个维度的数据:用户、交付合作伙伴和商店(有时它们以不同的格式出现),那么使用这些*台进行空间合并是非常困难的。
空间连接涉及在空间透视图中将一个图层的一个要素表中的列插入到另一个要素表中。例如。合并 Kormangala 区域多边形及其内的所有乘车点。
丰富:丰富任何数据都意味着添加新的信息层,并将其与第三方或外部数据源合并。在 GIS 领域,我们丰富了空间数据,以便更好地了解点所在区域的环境。这意味着添加道路、交通、天气、兴趣点、人口统计、建筑物等环境图层。

QGIS 桌面。资料来源:NextGIS
内部解决方案行不通吗?
当然,一些公司意识到了这一点,并绕开开源工具(如 Kepler.gl 或 QGIS )。但是这些开源工具有它们自己的一系列约束和限制。
然而,这个问题并没有在这里得到解决,因为地理空间数据本身就充满了挑战。
对流数据执行地理空间查询变得非常计算密集型,而传统技术(如 ArcGIS)提供的支持非常少。随着可视化大型地理空间数据集以及各种规模的交互,复杂性也随之增加。
有时开发人员也构建他们自己的内部工具,但是大多数时候他们并不适合公司内部所有不同的受众。因为这些工具不是以可伸缩的方式构建的,所以维护它们经常会耗费大量开发人员的带宽!
很多时候甚至有重复的努力,轮子一遍又一遍地被重新发明。正如 Twilio 的杰夫·劳森(Jeff Lawson)所说——“构建软件比以往任何时候都容易,但操作软件比以往任何时候都难”。
我们为什么要建立 Locale.ai?
一切都始于一个个人问题。作为处理地理空间数据的数据科学家,现有的分析产品在我们的日常工作流程中毫无用处。因此,我们必须为我们的日常工作流程构建自己的工具和库。
我们随后意识到,在位置数据方面,全球的数据科学家都面临着类似的问题。因此,企业正在努力提高运营效率!
在地点,我们计划一劳永逸地解决这些问题。我们希望减少所有这些过程的痛苦,建立一个在几分钟内就能轻松获得所有地理空间答案的世界!这就是为什么我们要回到绘图板,完全从零开始手工制作这种体验。
所以,下次你想在紧急情况下订购药品时,你不会希望在屏幕上看到,“送货员不在。请稍后再检查。“下一次,送货员再也不用在酷热、寒冷或下雨的天气里无所事事地等待订单了。
他们可以被激励去高需求地区,可以赚更多的钱。你收到的推送通知不会是垃圾邮件,它们会在正确的时间和正确的地点发送给你。
感谢阅读!如果你想进一步钻研,可以查看我们的 网站 出来或者联系我上LinkedIn或者Twitter。****
产品经理机器学习指南:*衡计分卡
研究表明,只有一小部分机器学习(“ML”)项目会产生商业影响。在这篇文章中,我将探索和分享我自己的经验建立记分卡,以最大限度地提高 ML 项目的成功。

在亚马逊从事顶线/底线战略时,我的一个重点是获得设计和构建 ML 模型的工作知识。例如,我学会了使用神经网络来建立图像分类。构建 ML 模型并观察其结果对我来说绝对是一件令人着迷的事情。不管 ML 有多吸引人,或者将会变得多么吸引人,我目前还没有转变成数据科学家或应用科学家的计划。产品管理是我的热情所在,但我总是发现自己被数学和 ML 的应用所吸引!当我在亚马逊找到一个具有领先 ML 特性的角色时,我欣喜若狂。我喜欢产品管理和 ML 之间的最佳*衡点。
“我们 ML 这个东西吧!”
分享我在亚马逊担任 ML 产品经理期间学到的五条经验:
1.角色 —第一个也是最明显的教训是,知道如何建立一个 ML 模型与领导一个 ML 产品是不同的。
- ML 项目与软件相关项目 —领导一个传统的软件相关项目与领导 ML 项目是不同的。科学方法(即观察、假设、测试、学习等。)仍然适用于传统软件和 ML 项目。然而,与传统的软件模型相反,ML 完全依赖于与业务问题相关的数据的质量和数量。一旦克服了数据的局限性,就有了损失、优化和评估的复杂性。我提到评估业务价值来源和客户价值主张的模糊性了吗?
3.复杂程度——“你只需要在这个产品中启动 ML 特性”并不像听起来那么简单。理解并尊重这些年来因为 ML 而需要重新调整的技术架构。你挖得越多,发现的骨骼就越多。
4.业务影响——计算一个 ML 模型的业务影响是极其模糊的。企业需要“展示资金”作为产品经理,你要拿出量化的价值。识别、理解和评估正确的假设起着关键作用。当然,这需要与更广泛的组织保持一致。
5.客户影响 —使用 ML 验证客户影响可以在没有 ML 的情况下完成。我了解到,我们可以验证一个 ML 模型的有效性和影响,而无需构建一个 ML 模型。向后工作!构建模拟(各种格式)来测试这些假设。拥有一些验证数据可以增强组织的信心,并帮助其他人团结在事业周围。
冰山一角

总结一下我学到的经验:ML 给商业利益相关者增加了大量的不确定性。推出 ML 产品时出现的问题是:它能给企业带来好处吗?存在什么证据?假设是什么?有哪些财务风险?谁受它的影响最大?实现有多复杂?用于训练 ML 模型的数据是否真正代表生产?我们有足够的标签吗?这些只是冰山一角。在推出 ML 产品的整个过程中,还会出现更多类似的问题。
构建记分卡
如你所见,在领导一个 ML 产品时,需要在任何给定的时间同时理解和管理几个领域。在读 MBA 期间,我读过一个案例研究和一篇关于构建*衡计分卡概念的文章。大约 30 年前,罗伯特·S·卡普兰和大卫·P·诺顿为管理商业的各个方面提供了这个解决方案。他们建议使用*衡计分卡从四个重要的角度来看待业务:
- 客户如何看待我们?
- 我们必须擅长什么?
- 我们能持续改进并创造价值吗?
- 我们如何看待股东?
“把*衡计分卡想象成飞机驾驶舱里的刻度盘和指示器。对于导航和驾驶飞机的复杂任务,飞行员需要关于飞行许多方面的详细信息。他们需要有关燃油、空速、高度、方位、目的地以及总结当前和预测环境的其他指标的信息。”
我们能否采用*衡记分卡的概念并对其进行定制,以管理机器学习产品?以下是我从自己的经历中总结出的记分卡:
1。数据,数据,数据
是啊!夏洛克!我同意没有粘土就不能砌砖。没有正确的数据,我们无法构建 ML 解决方案。所以,让我们从数据开始,数据,数据。理解和积累适合您项目的数据是无可替代的。根据您在项目中所处的位置,与您的应用科学家坐下来了解他们对数据的限制。认真对待这些问题,并召集你的团队来解决这些问题。制定一个计划,逐步建立数据。这是一个说明我的数据记分卡的表格。
2。给我钱
ML 工作与业务单位的顶层指标紧密相关。将 ML 输出链接到 topline 对于项目的持续成功至关重要。当利益相关者表达对潜在影响的担忧时,理解被质疑的假设,并制定计划来确认这些假设。收集证据,向风险承担者展示模型的影响。结合莫斯科项目框架,以避免范围蔓延,即使在计算影响时也是如此。
3.内部记分卡
通过清晰的沟通流程减少跨职能部门的歧义。每个人都投入了大量精力来沟通项目中各个里程碑的状态。
4.顾客
客户为你的项目制造了一个很好的共鸣板,尽早让他们参与进来,然后逆向工作。这对于任何一个产品经理来说都应该是显而易见的一步,我就不拿这个来烦你了。
邀请您:
仅仅专注于推出 ML 解决方案而没有一个*衡的方法会让你走上一条循环的道路。利用上述*衡计分卡提高推出正确解决方案的几率。问题列表和记分卡的类型越来越多。请随意在你的项目中使用这些记分卡。我邀请您分享其他对您有帮助的记分卡或相关问题。祝你一切顺利!
引文:
[1]:弗莱明、雷蒂卡和菲尔·费施特。“如何避免你隐约出现的机器学习危机。”HFS 研究,2018 年 7 月。https://1 PCL 3 wzgyqw 5 KF 62 erficswwpengine . net DNA-SSL . com/WP-content/uploads/2018/07/RS _ 1807 _ HfS-POV-machine learning-crisis . pdf .
[2]:卡普兰&诺顿。(1992).*衡计分卡——推动绩效的衡量标准。《哈佛商业评论》,71–79 页。检索自https://HBR . org/1992/01/the-balanced-score card-measures-the-drive-performance-2
产品经理的机器学习指南:云机器学习
为什么获得亚马逊网络服务机器学习专业(“AWS ML”)认证是获得云机器学习关键要素实用知识的最佳起点之一。

本杰明·艾略特在 Unsplash 上拍摄的照片
当我第一次开始学习 ML 时,我发现自己陷入了一个无尽迷宫中令人失望的死胡同。很长一段时间,我从来没有非常成功地接触过机器学习组件,因为我总是被困在的迷宫中,而循环、理解、容器和函数。当时,缺乏进展令人沮丧。我的许多死蟒的回复默默地证明了这一点。
为了在开始漫长而艰苦的学习 ML 的旅程之前形成一个良好的心智模型,我们必须首先获得一个整体的观点,然后挖掘更详细的目标。类似于绘制森林地图,第一步是查看森林的景观,然后是查看森林的树木(即树干和大树枝),然后也只有在那时,你才会注意森林的树叶和树枝。

在这个学习曼梯·里的迷宫中,我觉得自己好像在和树叶和树枝打交道。我想在被杂草、树枝和树叶缠住之前看到森林的全景。我发现 AWS ML 认证给了你一个有利的视角来看待 ML 的广阔森林。如果这些观点鼓舞了你,那么你将有力量和动力不放弃旅程。通过这个测试是激励和验证。
值得吗?
这不是一个廉价的测试。它需要 300 美元和几个月的课后学习。在准备考试之前,我谷歌了一下“AWS ML 认证值得吗?”。我没有找到一个明确回答这个问题的答案:“值得吗?”。以下是为什么这项测试值得进行以及它能提供什么的一些考虑因素:
这是一个易于应用的基于案例的测试: 我真正喜欢这个测试是因为它是基于案例的。它给出了一个场景,并询问如何将各种 ML/AWS 解决方案应用于该场景。当测试呈现各种情况时,它扩展了你的批判性思维和你可以用 ML/AWS 做什么的可能性。有时我发现自己在说:“哦,哇!你能做到吗?”,“嗯,我从来没有想到这一点”。看到可能性是很有趣的。你不能在这次考试中死记硬背。类似于 ML 的核心思想,概括知识是关键。这种基于案例的方法提高了人们为给定的商业问题选择和证明适当的 ML 方法的能力。
为理解算法提供了优秀的框架: Sagemaker 内置了 17 种算法。您可以看到算法的本质,特定算法将解决的问题的类型,它的学习类型,它的超参数,数据输入模式,文件类型(Record-IO,CSV,JSON,Text),实例类的类型(CPU 与 GPU)。了解算法的不同特征,使你能够表达基本 ML 算法背后的直觉。此外,您将了解损失函数,优化模型性能,并学习评估模型输出。要快速阅读这三个核心观点,请阅读本文:
在进入机器学习的树叶和小树枝之前,先了解一下树干和大树枝。
towardsdatascience.com](/a-product-managers-guide-to-machine-learning-core-ideas-ba837885d5a)
给出了基础后端知识的极好的鸟瞰图: 为了构建、设计和部署 ML,它需要 DevOps。在为考试而学习的时候,你会看到大多数 AWS 后端系统和服务。您将体验到这些服务是如何相互作用来获取、培训、测试和部署 ML 解决方案的。这种公开使您能够识别适当的 AWS 服务来实现 ML 解决方案。这些服务可以是 Sagemaker、Kinesis、EMR、EC2、Glue、Athena、KMS、S3、Apache spark 等。随着更多的接触(实践经验),设计和实现可扩展的、成本优化的、可靠的和安全的 ML 解决方案将成为一种直觉而不是一个谜。
有了新的心智模型,我最好和我的应用科学家和工程师讨论: 获得你同事的信任是值得的。作为准备工作的一部分,部署您自己的 ML 模型并观察它的工作是值得的。
本测试还将拓展你的职能技能,这些技能不受公司/行业的限制:本测试考察的核心理念可应用于各种行业,如医疗、公共政策、金融等。

最后,这个测试的范围和深度是巨大的。要学的东西太多了。我推迟了两次考试,因为我担心我的准备不充分。这是一个复杂的课题和艰难的考验。因为旅程的每一步都很艰难,所以当我通过测试时,胜利的感觉是真实的!知道自己能做难的事情,是值得的。
邀请:
这个测试也将拓展你的职能技能,这是公司/行业不可知的。下面我提供了我使用过的资源。
资源:
哪些资源帮助我准备了考试,我将如何评价我从这些资源中获得的价值(下面提供了这些资源的所有链接):
- SageMaker Docs (40%):核心信息在这里。重读这些。
- Udemy 课程(30%):该课程涵盖了文档中没有的细节。有时会有点干,但你能熬过去。我使用模拟测试进行基准测试。
- AWS 常见问题解答(20%):这些将各种系统和服务联系起来。
- 随机 AWS 在线技术深度挖掘视频(10%):我必须深入挖掘容器、超参数、分布式学习等。
资源链接
亚马逊 SageMaker 是一个完全托管的机器学习服务。有了 Amazon SageMaker,数据科学家和开发人员可以…
docs.aws.amazon.com](https://docs.aws.amazon.com/sagemaker/latest/dg/whatis.html) [## AWS 认证机器学习专业 2020 -动手!
对通过 AWS 认证机器学习专业考试(MLS-C01)感到紧张?你应该害怕!毫无疑问…
www.udemy.com](https://www.udemy.com/course/aws-machine-learning/)
AWS 常见问题解答
从以下产品和技术常见问题列表中选择。浏览这些常见问题,找到常见问题的答案…
aws.amazon.com](https://aws.amazon.com/faqs/)
我的认证
验证码:55X5DDYKMJQQ14W7
请输入位于 AWS 证书右下角的验证码。单击提交以验证…
aws.amazon.com](http://aws.amazon.com/verification)
产品经理机器学习指南:核心思想
在进入机器学习的树叶和小树枝之前,先了解一下树干和大树枝。

辛金·托马斯在 Unsplash 上的照片
语境
对于产品经理来说,通过机器学习来推动业务影响的需求越来越大。在写这篇文章的时候,我作为亚马逊的高级产品经理正在发布 ML 驱动的产品/特性。在这段时间里,我花了很多时间在日常工作中学习和使用 ML 概念。希望我的经历能对你的学习有所启发,在“产品经理机器学习指南”系列中,我将记录我的收获。
这篇文章是为那些产品经理而写的,他们想比核心 ML 过程概念更深入一点:设定目标、获取数据、分割数据、培训、验证、测试、评估和发布。
文章:路线图
以上面提到的 ML 过程为背景,我发现 3 个核心概念是 ML 的主干和大分支。
3 个核心概念是 1)损失 2)优化和 3)评估。
你不必知道这些概念的细枝末节。我将使用简单的视觉和语言来交流这些线性回归算法的概念。
免责声明——每一个主题都是如此广泛和详细,以至于人们可以就每个主题写一本书。本文是对主要思想的简单介绍。

图 1:核心概念
介绍
“要做的工作”理论也可以应用于机器学习。在我们进入 3 个核心概念之前,让我们花点时间来理解——线性回归算法的工作是什么?为什么我们要雇佣这个算法?
线性回归算法的目的是在数据点之间定位一条线(图 1:蓝点)。目标是我们想要学习信息 X,称之为特征,有关于 y ( 称之为目标/标签),以便我们可以预测一个新的或未知的 X 的 y 。这里 X 和 y 本质上是定量的。
例如:我们能多准确地估计出 X 对 y 的影响?广告(X)对销售额(y),房间数(X)对房价(y),身高(X)对体重(y)等。如果只有一个特征,它被称为简单线性回归,我们在 X 和 y 之间拟合一条线。如果有许多 X s ,它被称为多元线性回归,你在 Xs 和 y 之间拟合一个*面。

图 2:拟合模型的简单图示
如图 2 所示,该算法遍历了许多不同的线,为我们提供了一个最佳模型。即使是小孩也能看出最合适的是最合适的。
fit 作业的输出是什么?
线性回归模型的输出是一个等式,该等式捕获了 Xs 关于 y 的信息。当模型准确地学习到参数β时,就会发生这种情况。如图 3 所示。企业需要这些参数来了解如何分配有限的资源或产生影响。

图 3:多元线性回归
嗯,模特怎么知道最合适的?
之前我说过,一个孩子可以看出图 1 中最右边的拟合是最佳拟合。但是怎么做呢?这样的结论背后的直觉是什么。这种直觉可以通过观察实际值(蓝点)和预测值(线上的一点)之间的距离来捕捉。

图 3:损失的简单说明
失败
实际值和预测值之间的距离越大,预测就越差。你是说——啊!这就是所谓的损失,一种糟糕预测的惩罚。任何算法都有一种或多种类型的损失。这些也被称为损失函数。我们将在这里检验的线性回归模型使用了一个称为*方损失的损失函数。单个示例的*方损耗如下:

图 4:*方损失
我们希望降低模型无法对未知数据产生良好预测的风险,因此我们引入了训练集和测试集的概念。这些不同的数据集将引入方差的概念(模型为不同的数据集生成不同的拟合),即过拟合和欠拟合等。我们想使模型不被训练集的特性所影响,这一意图向我们介绍了另一个叫做正则化的概念。正则化建立在残差*方和的基础上,这是我们最初的损失函数。
- 普通回归:残差*方和-(1)
- 岭回归,也称为 L2 正则化,通过惩罚权重*方来最小化模型的复杂性:(1) + λ *权重*方和-(2)
- Lasso 回归,也称为 L1 正则化,通过使无信息系数等于零来最小化模型的复杂性:(1)+λ*绝对权重之和| — (3)
- 弹性网= (1) + (2) + (3)
最佳化
我想你可能会问这个问题——在数据点之间放置线可能有成千上万种变化。这是如何实现的?为了形象化,请看图 5。图 5 的目的是展示为了得到合适的拟合,实际上会发生什么。

图 5:拟合的变化
你可以找到关于这个主题的大量书籍,这些书籍可以填满一个小型图书馆。作为一名产品经理,我不需要也不期望我知道这些书中描述的优化的枝叶。这个想法很简单——优化。如果你有一个送报路线,你就优化了路线,也就是说,在最少的时间内送更多的报纸。如果你有孩子,你会选择制造最少混乱的玩具。如果你是一个 ML 模型,你优化拟合产生最小损失函数。
在我们的例子中,我们最小化实际 y 和预测y之间的*方距离。这个最小化损失的过程可能需要几毫秒到几天。有不同的方法来优化我们寻找最小*方和的过程。也就是说,有各种优化算法来完成目标。例如:1)梯度下降 2)随机 GD 3) Adagard 4) RMS Prop 等是一些优化算法,仅举几个例子。按照惯例,大多数优化算法都与最小化有关。
例如,在图 6 中,我们可以使用梯度下降到损失函数的最低点,该点将成为图 3 中输出方程的截距和其他参数。

图 6:参数的错误率
估价
一旦损失被确定并减少,我们就到达了最后的核心概念:评估。通常,这是业务所有者会面并熟悉模型性能以实现业务目标的地方。
在线性回归中,可以根据均方误差(损失函数)评估模型,越小越好,R *方,调整 R *方,越高越好。
- R - *方测量线性回归模型中自变量(X)解释的因变量(Y)的变化比例。
- 调整后的 R - *方根据模型中独立变量的数量调整统计数据。
邀请
机器学习的应用令人敬畏。不要让数学和词汇阻止你追求机器学习。如你所见,核心概念是熟悉和基本的。正如产品经理需要机器学习一样,它需要充分利用机器学习的产品经理。我希望这些核心观点能帮助你在与你的 ML 团队合作时思考正确的问题。
基于 fastText 的文本分类生产机器学习流水线
了解如何在多个步骤中组织您的 ML 代码,并使用 Valohai 创建受版本控制的 ML 管道。

带有执行和工件的数据谱系图。
在生产中做机器学习的时候,模型的选择只是众多重要标准中的一个。同样重要的是正确定义问题,收集高质量的数据并构建机器学习管道。
本文着重于为一个流行的问题构建一个机器学习管道:文本分类。管道获取带标签的数据,对其进行预处理,自动调优 fastText 模型,在所有数据中重新训练模型,并输出度量和预测以进行迭代。
我使用 Valohai 创建一个 ML 管道,并对每一步进行版本控制。最后,只需点击几下鼠标,您就可以在云上运行管道,并探索每个中间结果。
构建生产就绪基线
在 Kaggle 竞赛中,你在一个确定的问题和一个冻结的数据集上工作。你对排行榜上的好成绩有所了解。
在现实世界的应用中,数据集不断发展,模型会定期重新训练。例如,在文本分类中,添加新的标签数据和更新标签空间是很常见的。
为了构建 ML 管道,我使用了来自 BBC 新闻的 2225 份文件的数据集,分为五个主题:商业、娱乐、政治、体育和科技。数据集为每个文档分配一个标签,这就是所谓的多类问题。

您可以在任何包含两列的 CSV 文件上运行管道:文本和标签。如果您想为多标签问题训练它,您可以添加具有相同文本和不同标签的额外行。
使用快速文本进行文本分类
脸书在 2016 年宣布 fastText 是一个高效的文本分类和表示学习库。官方快速文本文件中报告的一些优势:
- 在标准多核 CPU 上几分钟内训练 10 亿个单词。
- 在不到一分钟的时间内对 312K 个类别中的 50 万个句子进行分类。
- 创建对拼写错误具有鲁棒性的子词向量。
- 包括易于使用的 CLI 和 Python 绑定。
2019 年,脸书为 fastText 添加了自动超参数调谐,我将它作为管道中的一个步骤。
集成 fastText 和 Valohai
我用 Click 为每个 ML 步骤创建一个命令,这是一个 Python 库,它修饰函数,将它们转换成命令。每个命令接受数据和参数,并生成数据和指标。
例如,autotune 命令在训练分割上训练几个模型,以找到验证分割上的最佳参数。
get_input_path 和 get_output_path 函数在本地和 Valohai 云环境上返回不同的路径。 train_supervised 方法接受参数来限制训练的持续时间和模型的大小。保存最佳参数,以便以后根据所有数据重新训练模型。
为了在云中运行 autotune 命令,我将它添加到 valohai.yaml.
检查 Github 中的所有 valohai.yaml 代码。
创建机器学习管道
Valohai 管道是一个版本控制的步骤集合,在图中表示为节点。每个数据依赖导致步骤之间的边缘。

文本分类管道有 5 个步骤:
- 预处理:对 fastText 使用的原始数据进行预处理。
- 拆分:将预处理后的数据拆分成训练、验证和测试数据。
- 自动调优:在验证数据上找到最佳参数。
- 训练:用所有数据上的最佳参数训练最终模型。
- 测试:获取测试数据的度量和预测。
与执行类似,管道在 valohai.yaml 文件中由两部分声明:节点和边缘。
检查 Github 中所有的 valohai.yaml 代码。
一旦声明了管道,就可以运行它,并通过单击它来检查每个管道节点。下面您可以看到自动调优节点的详细信息。

Valohai 管道是声明性的,很容易与您的代码集成。对于动态管道,可以将 Valohai 与气流整合。
自动跟踪数据沿袭
数据沿袭图显示了执行和工件之间的数据依赖关系。在 Valohai 中,您可以跟踪每个依赖项,以便更快地调试管道。

Valohai 生成的数据谱系图。
迭代问题、数据和模型
自动调优步骤是获得良好结果的关键。F1 分数从默认参数的 0.3 变为测试数据集的最终 F1 分数 0.982。中间结果由 fastText autotune 命令记录,可以在日志中读取。最终得分记录在 JSON 中,并由 Valohai 存储为执行指标。

但是只看一个指标不足以知道你的模型是否工作良好。最有趣的信息在 test_predictions.csv 文件中。它包含模型在 222 条记录的测试数据集上产生的 4 个错误。

反复讨论这个问题
第四个错误将 0.59 的概率分配给商业标签,而不是 0.39 的政治标签。探究全文可以发现,文章谈到了这两个话题。该观察可能导致对问题进行迭代,以变成多标签,并分配高于概率阈值的所有标签。
对数据进行迭代
总的来说,标记的数据是高质量的。我们可以认为一些 p@1 较高的误差是对标记数据的修正。在另一个具有由不同过程产生的标记数据的数据集中,模型预测可用于校正标记数据。
在模型上迭代
如果最终指标对您的业务案例不满意,可以添加新功能,并培训不同的模型。但是我认为最好从正确的问题定义和数据开始。这些是你的 ML 管道的成分。
使用 Valohai 在您自己的数据集上尝试 fastText
自己在云端运行管道很容易。下面的按钮将邀请您注册/登录到您的 Valohai 帐户,并创建一个项目来尝试这个管道。
创建项目后,请按照以下步骤操作:
- 在设置选项卡>常规选项卡中,将默认环境设置为微软 Azure F16s v2(无 GPU) 。
- 在 Pipeline 选项卡中,使用蓝图 fasttext-train 创建一个管道。
- 点击创建管道运行管道。
当管道运行时,您可以单击图中的每个节点,并查看日志和输出。管道完成后,您可以单击一个节点,并通过单击 Trace 按钮获得数据谱系图。
恭喜你,你已经运行了你的第一个 ML 管道!现在你可以用你自己的数据来尝试一下,为你的文本分类问题获得一个基线:
- 在数据选项卡>上传选项卡中,上传数据集。数据集应该是一个包含两列的 CSV 文件:文本和标签。
- 在运行管道之前,单击预处理节点。在输入部分,用步骤 1 中上传的数据替换默认输入数据。
结论和下一步措施
在多个步骤中组织你的 ML 代码是创建受版本控制且易于调试的生产机器学习管道的关键。CLI 是 ML 代码工业化的一个流行选择。
对于文本分类等常见问题,fastText 是一个强大的基线构建库。有了 Valohai 你就有了一个版本控制的机器学习管道,你可以在你的数据上运行。在另一篇文章中,我重用了管道来将 400 万个 Reddit 帖子分类到 4k 个子编辑中。
有用的资源
人工智能的一个难题
我如何教一个 AI 玩 2048

作者图片
嗨!我叫 Rinat Maksutov,在俄罗斯埃森哲技术公司的智能工程服务部门工作,负责定制开发项目。在我在埃森哲的漫长职业生涯中,我经历了许多不同的领域:移动开发、前端、后端,甚至是带有机器学习的数据科学。然而,我的故事不会是关于工作,而是关于一个爱好。我真的很喜欢通过我个人喜欢的项目来学习和探索新的领域。今天我将告诉你其中的一个——我如何教一个强化学习(RL)代理玩著名的益智游戏“2048”。这篇文章故意不包含代码、数学、最先进的方法和该领域的最新发现,所以对 RL 非常熟悉的人不会为自己发现任何新东西。这篇文章是给大众的一个故事,讲述了我是如何给自己设定一个不寻常的目标并实现它的。
我们公司在持续的员工培训上投资巨大。例如,去年推出了一个项目,员工可以免费参加 Udacity 上的一个纳米学位课程(纳米学位是一系列课程和一个最终项目)。我已经在这个*台上做过深度学习 Nanodegree,所以这次我决定上强化学习的课程。
该课程很好地揭示了 RL 的基础,但有一个很大的缺点:该课程提供的教育项目是基于现成的任务——在这些任务中,代理运行的环境已经由某人为您编写好了。也就是说,您只需实现学习算法并调整超参数,以达到目标分数并通过考试。
因此,在完成课程后,你将无法完全应用 RL 并解决你自己的问题,因为你只学习了这个领域的一部分。以及如何为代理人正确地构建环境、如何为其正式化任务、如何为各种行为正确地分配奖励等问题——留在括号之外,你必须自己解决(所有这些术语的含义,我将在下面解释)。
为了弥合这一差距,我试图解决一些以前没有人解决过的问题(至少在 RL 的帮助下),并用它来研究为代理人构建环境的各个方面。作为这样一个任务,一个机械简单的益智游戏 2048 被选中(你可以在这里的浏览器中玩它:https://play2048.co/或者在谷歌 play 或应用商店搜索你的智能手机)。在这个游戏中,玩家通过在四个方向(上、下、右、左)之一移动细胞,需要将具有相同值的细胞组合起来,并尝试收集具有最大可能值的细胞。当你进行移位时,一个新的 2(概率为 0.9)或 4(概率为 0.1)出现在随机的自由单元格上。当场上没有空的格子,并且玩家不能组合任何格子时,游戏结束。
尽管名字如此,2048 并不是游戏中最大的单元格值。经过适当的训练,您可以得到值 4096、8192 个单元格等等。理论上可能的最大单元值是 131,072,即 2 ^ 17:

来源:维基百科
但是获得这个值是非常困难的。这是因为这个游戏没有一个策略可以保证获得尽可能多的分数。只有一种策略能增加你实现它的机会。粗略地说,它包括定义两个优先的垂直方向(例如,向下和向右),大多数移动只在这些方向上移动细胞,很少在其他方向上移动。因此,较大的值将在四个角中的一个角上彼此靠*地“累积”,并且将它们组合起来以获得甚至更大的值将会方便得多。
为什么这个策略不能保证胜利?
- 空的单元格被随机地填入两个或四个新的数字——也就是说,你可能很幸运,一个“方便”的单元格会被填满,或者它可能不幸运,一个单元格会被填满,使你不容易收集到所需的组合。
- 收集每个下一个值的复杂性(所需的步骤数)*似呈指数增长。而且越深入,它就越依赖于新价值的“成功”出现,错误行为的代价就越高。
因此,代理人的任务将是学习这种策略,以便在每一步选择最有可能在未来允许的行动,以在游戏中获得单元的最大可能值。
强化学习的小介绍
上面我写道,我不会让你沉浸在 RL 的理论中,但仍然值得简要回顾一下主要观点。强化学习是机器学习的一个领域,其目标是教会智能体在某种环境下执行必要的动作。这里的代理是一个虚拟实体(程序、模型),它接收其运行环境的当前状态作为输入。然后,根据这种状态,它选择最有价值的动作,将其传达给环境,并从环境接收反馈和新的状态。如此循环,直到环境达到最终状态。
在代理的引擎盖下,可能存在一些数学模型,该模型基于环境的当前状态来确定哪个动作将是最佳的。最初,一般来说,代理人不知道什么样的环境给他,以及它的行动如何影响它。代理人通过所谓的“奖励”接收来自环境的反馈。这是一个数字,代理可以通过它来判断所选择的动作有多正确。代理的任务是学习一种“策略”——一种在代理存在于环境中的整个时期内使代理的报酬最大化的行动策略。这种奖励正是“强化”,这意味着正确的行为得到积极奖励的支持,错误的行为受到消极奖励的阻碍。因此,通过多次迭代,代理(或者更确切地说,模型)开始更准确地预测每个可能的行动的潜在回报,并选择最有价值的行动。
Udacity 有一个有趣的小狗训练类比。你给它一个命令,起初它不明白你想要什么。它开始执行随机的动作来响应你的命令:吠叫、跳跃、仰卧、跑来跑去。当它随机选择正确的动作时,你就给了它一个奖励。狗意识到,你很可能希望它按照这个指令做那个动作。这样反复几次——命令——动作——好吃,之后狗就确信了所选动作的正确性。
*年来,大量关于人工智能的大型媒体故事都与强化学习有关:AlphaGo 算法的胜利,在专业水*上玩星际争霸,等等。但你需要明白,在强化学习领域仍有许多未解决的问题,其中一个主要问题是所学技能对其他任务的可移植性差,以及学习的高度不稳定性,这甚至会受到环境最轻微变化的影响。也就是说,如果算法在一个游戏中学习玩得很好,那么它很可能在另一个游戏中显示糟糕的结果。在这个方向上有一些进展,但距离相对通用的算法还有很长的路要走,最有可能的是,开发它们在经济上尚不可行。
另一个重要的问题是,在实践中,很少有任务可以借助强化学习来解决。与花时间训练代理相比,实现解决问题的已知算法通常更容易、更快、更可靠。由于这个原因,强化学习还没有像机器学习的其他领域一样受到重视。
事实是,传统上机器学习用于自动化任务:1)难以算法化,2)由受过充分训练的人容易执行,但是 3)需要人花费大量时间来完成任务。例如,在图像识别任务中,一个人可以很容易地确定想要的对象是否在上面,但是很难编写一个足够可靠并且或多或少通用的算法来确定对象,同时,对于大量的图像,一个人将在很长的时间内完成这项工作。或者,例如,欺诈检测:受过训练的人将能够通过交易序列识别可疑活动,但他们的搜索和分析将花费大量时间,并且这项任务也很难用普遍预定义的规则集来描述。
现在我们从这个角度来看强化学习。这个领域的目的是教一个代理在特定的环境中行动,也就是说,根据当前的情况做出决定。没有多少任务符合这一想法——主要是在控制某些东西的领域,例如,装配线上的机械臂,路上的汽车,星际争霸中的一群 zergs,等等。但是通常人们已经知道了达到预期结果的规则或策略。我们不希望一个装配线上的操作者在开始做正确的事情之前,先学会把一个零件放在正确的位置上几万个周期,然后毁掉几万个产品。编写一个在装配过程的每一步精确定位机械臂的程序要安全得多。我们不希望汽车行驶数百万公里,并通过一周内的罚款来了解每个路标的意思——最初输入这些知识要快得多,也更可靠。这就是为什么强化学习仍然是一个非常实验性的领域,它的实际应用很少。三年前的一篇关于这个话题的精彩文章仍然很有意义,并且很好地描述了这个问题,我建议你读一读。介绍到此结束,我们回到我们的任务。
耙子和自行车

博罗米尔的另一个迷因。图片作者。
到达 cell 2048(虽然对于一个或多或少有经验的玩家来说,2048 根本不是一个成就)是一个漫长的尝试、错误、失望、最愚蠢的 bug、灵感和喜悦的旅程。
起初,一切看起来都很简单:我们从我在 Udacity 上的作业中获得了实现 Deep Q-network 的现成代码,将其稍加修改以适应我们自己的环境,一切都会迎刃而解。太天真了。
这样你就能理解 3 个月的实验都花在了什么上(如果什么都不清楚,你可以对子弹的数量感到惊讶,并进一步滚动):
环境状态表示
- 独热编码向量(16 个单元*每个单元 18 个可能的状态)
也试过:
- 具有“原样”单元格值的向量
- 具有 Log2 像元值的向量
- 卷积网络的 4 乘 4 矩阵
奖励
- 当前步骤中棋盘上折叠单元格的 log2 值之和减去移动单元格的罚分和错误移动的罚分
也试过:
- 板上单元格值的总和
- 所有时间内折叠单元格值的总和
- 整个时间内折叠单元格的 log2 值之和
训练
- 每场比赛后 10 次训练迭代,批次大小为 1024,初始ε: 0.05,递减因子为ε: 0.9999,
也试过:
- 每场比赛后 1、3、5、20 次训练迭代
- 从 1.0 到 0.01 的不同ε值(行动的因子随机化)
经验的积累和运用
- 缓冲 100,000 个最*的动作
也试过:
- 随机经验抽样(无优先顺序)
- 5 万和 20 万的缓冲
- 通过棋盘上的总和、最大单元格、错误值、奖励(包括行动分配的*衡)来确定经验优先级
协助学习(作弊)
- 不
也试过:
- “从中间开始”:每 N 集让代理人在一个随机产生大细胞的环境中发射,以便让他熟悉他以前从未达到过的价值观。
- “*行宇宙”:除了一个选定的步骤,其余 3 个可能的步骤被计算并保存在历史中,以便在训练中有更多可比较的例子
什么被最大化
- 提前两步折扣奖励
也试过:
- 下一步中的帐户
- 所有后续步骤中的折扣分数
- 下一步奖励
神经网络
- 5 层:288–3x 1024–4,ReLU 和 Adam 优化器激活
也试过:
- 2,4 个隐藏层
- 其他优化器和激活
- 隐藏层中有 256,512 个神经元
- 不同的学习率值
- 卷积网络
如果神经网络配置和训练参数是一个人每次都必须处理的非常标准的事情,当你解决深度学习中的一个问题时,那么其他的都是强化学习特有的。
我不得不面对的第一件事是在培训代理人方面毫无进展。这与代理人从环境中接收的信息有关。
代理的环境
为游戏编写棋盘逻辑变得非常简单,只需要几个小时。几个简单的矩阵技巧,引擎就准备好了。它根据选定的操作执行单元格的“折叠”和移动,填充新的单元格并计算点数。因此,环境的当前状态由一个简单的 4x4 矩阵描述,其中每个单元包含相应单元的值。由于我使用了常规的全连接神经网络,因此在将环境状态发送到神经网络之前,必须将其转换为 1x16 向量:

游戏板转型。作者图片
第一个问题出现了。当代理到达 512 单元时,训练质量停止增长。不管我怎么训练它,它都不能收集更多的了。这里的问题出在单元格的值上,它有一个巨大的范围:从 0 到几十万。让专家们见谅,但这里对这种行为的原因有一个非常松散的解释——我故意简化,以便大致思路清晰。
每个输入值都是神经网络的信号。这个信号的强度与输入值成正比,神经网络输出端的误差也将与其成正比。药剂到达的细胞越大,来自这些大细胞的信号就越强,而来自较小细胞的信号就越弱。然而,发现小像元的数量级比大像元多,并且它们比大像元更重要,因为通过正确收集小值可以获得大值。事实证明,代理学习收集的值越大,它开始与较小的细胞一起工作就越差,因为它们的信号对于神经网络来说越来越弱。
事实证明,解决这个问题相当简单。我只是将这些值放到了一个更统一的尺度上:单元格值的 log2。然后指数增长的值变成了一个普通的序列:

也就是说,在每次移动之前,计算当前棋盘的每个单元格的 log2,然后将这个矩阵输入到神经网络中。这个技巧使得克服值 512 的上限并达到 1024 成为可能。但是学习过程仍然非常缓慢。很明显,这种环境对于神经网络来说信息不够丰富。
在某种程度上,我认为代理并不真正关心单元格的值。将一种价值观转化为另一种价值观的机制才是重要的,也就是说,一种新的价值观是从另外两种相同的价值观中产生的。我们可以用下面一行来补充我们的表:

对代理人来说,唯一的意义就是 a + a = b,b + b = c,等等。,而不是 a、b、c 后面藏着什么值(这里的“+”不是加法,同样是“折叠”)。这意味着单元格的值不能被视为数值,而是分类值。因为我们知道一个单元的最大可能值,所以每个单元可以表示为一个独热编码向量。也就是说,对于每个单元,不使用它的值,而是使用 18 维的向量,其中所有值都是零,并且只有一个值等于 1,该值的位置对应于我们可能的值之一。这样的向量——通过细胞的数量。我仍然不清楚为什么,但正是这个,而不是数字表示,帮助代理更快地达到更高的值。
报酬
最初,奖励简单地计算为棋盘上所有单元格的值之和。看起来这个分数将是代理人进步的引擎,因为通过分数的逐渐增加,人们可以判断是否选择了正确的行动,这可以用作奖励。事实证明不是。原因就在于游戏的机制。
就拿《太空入侵者》这种非常简单的游戏来说吧。几年前,谷歌对其代理进行了这方面的培训。

来源:维基百科
在这个游戏中,每击中一个外星人,分数就会增加。即动作(“出手”)、环境中的结果(“命中”)与分数之间有直接关系。
在 2048 年,这种方法不起作用。原因如下。假设您有两个相邻的值相同的单元格。你把它们折叠起来,然后…黑板上的分数没有改变。因为它们的值分别等于新单元的值。也就是说,在执行了正确的动作之后,代理人将不会得到积极的强化,也不会学到任何东西。此外,在每个动作之后,一个新的随机单元格被填充值 2 或 4。因此,无论代理执行什么操作,它都会收到一个值作为响应,该值等于[计数到步骤+ 2 或 4]。显然,这些信息不足以理解代理人如何选择动作。正因为如此,训练实际上没有进展。
因此,该奖项必须以不同的方式实现。起初我试图给它的不是棋盘上细胞的当前值,而是游戏开始以来折叠细胞的值。现在代理人有了一个更可靠的参考点,训练进行得更快了:代理人看到哪个动作大大增加了分数,哪个没有。但即使如此,训练并没有像我希望的那样快,所以这个想法提出了一个更具体的指标:只给出当前步骤中崩溃细胞的总价值作为奖励。这使它能够清楚地了解什么样的行动应该导致什么样的结果,并大大加快学习过程。
但是还有一个与游戏机制相关的细节。向两个相反的方向移动的回报将是相同的,但棋盘将处于不同的状态,并将在接下来的步骤中导致不同的后果。但是更重要的是,如果你记得的话,转变应该主要发生在选定的方向上。也就是说,如果我们收集右下角的细胞,那么只有在特殊情况下才应该进行左移。因此,我们可以假设向右移位的预期报酬较大,向左移位的预期报酬较小。这意味着我们不仅需要预测当前步骤的预期回报,还需要预测下一步的预期回报。
为了训练模型来预测奖励,我使用了“玩过”游戏的历史记录——以前游戏的每一步都保存在一个特殊的缓冲区中,用于训练。首先,我尝试使用从当前步骤到游戏结束的所有奖励的总和作为预测的目标值。此外,离当前的一步越远,其回报的总和权重就越小。为此,我将它乘以一个几何递减级数的相应序数值。但是这种方法,由于动作变化太多,给出了糟糕的预测。然后我把预测深度限制在当前步骤,权重为 1.0,下一步权重为 0.1。查看日志,我发现随着时间的推移,对潜在回报和最有价值的行动的预测实际上变得越来越接*实际发生的情况。但是,这个模型还是经常在非优先方向上移动,从而破坏了棋盘上的局面。有必要以某种方式“劝阻”行为者不要做出对自己有害的行为,而这是在惩罚的帮助下完成的。
惩罚
这种方法在 RL 中经常使用,这样代理不仅可以学习如何执行任务,还能以最简单的方式完成任务。为了告诉它哪些步骤是精益的,哪些是浪费的,你需要把这些信息放在奖励里。在我的例子中,我决定在每次移动时惩罚代理,因为所有的细胞在选择的动作后都移动了(也就是说,改变了它们的位置)。移动的细胞越多,惩罚就越高。也就是说,如果它在右下角累积了较大的值,并继续向右或向下移动,则只有新单元格的值会成为它每一步的惩罚。如果它突然决定向上或向左移动,那么不仅新的细胞会移动,所有集中在右下角的细胞也会移动,惩罚将是巨大的。随着时间的推移,代理人意识到,最大的奖励不仅是在它折叠更大的细胞时获得的,而且是在它移动最少数量的细胞时获得的——这迫使它坚持所选择的策略,并且只有在特殊情况下才会在“非优先”方向上采取步骤——当预期的奖励(包括罚款)确实更高时。

在每个游戏中所选移动方向的份额分配。图片作者。
在这张图片上,我们可以看到策略是如何逐渐向正确的方向变化的:在第一场游戏中,移动的方向被均匀地选择,但随后“优先”的方向出现了——向右和向下。
特工的行为还有一个搞笑的瞬间,大大拖慢了训练进度。正如我上面写的,代理人并不知道游戏规则。因此,它不知道,如果你已经把所有的细胞都压到了棋盘的右边,就不可能再移动了,比如说,向右移动。也就是说,即使你做了这样的移动,棋盘上的任何东西都不会改变。在某些时候,神经网络出于某种原因决定,最有利可图的移动是没有一个细胞移动的移动,因为如果没有移动,那么就不会有惩罚。也许是因为它们的大小,轮班惩罚比没有得到倒塌细胞的奖励更糟糕。因为在这样的移动之后,棋盘没有改变,所以下一步的输入保持不变。当然,选择了相同的动作。如此反复数千次,直到“随机”移动发生(在每次迭代中,以非常低的概率——十分之一或百分之一——随机移动而不是计算的移动,以便,除了别的以外,摆脱这样的循环)。这个问题本来可以通过调整惩罚和奖励来解决,但我只是决定非常严厉地惩罚“不可能”移动的代理,它很快就放弃了这样做。
结果

哇信号。图片作者。
绿色图表显示了每场游戏中的最大单元格值。离群值—在一个游戏中,单元格的最大值是 2048。

去 2048 号牢房。图片作者。
为了学会组装细胞 2048,代理必须玩六万多一点的游戏。然而,一个重要的细节是,一个单一的成就并不意味着代理已经学会了持续地做这件事。请看绿色图表的开头,您可以看到代理是如何学习到达 1024 单元的。起初有同样的爆发,然后 1024 越来越频繁地出现,然后在 3 万场比赛后的某个地方,代理人开始非常自信地达到 1024。所以如果我们说代理人真的“学习”如何收集 2048,那么,外推模式,我们可以估计代理人将需要超过一百万场比赛来巩固这一技能,并奔向下一个目标——4096。
你可能已经厌倦了阅读,所以我用 20 分钟的 cell 2048 聚会视频(从 16:40 开始)来结束我的长篇阅读:
我在我的笔记本电脑上进行训练,所以花了大约两天时间才得到这个结果。但是正如我上面写的,2048 年在这个游戏中远远不是极限。因此,如果你有计算能力和时间,这是很有可能达到更大的细胞-采取我的代码在 GitHub 和尝试训练自己的代理人!如果你设法击败我的成就,请在评论中发送你的结果的 gif 和链接。感谢阅读!
Google 云*台发布/订阅的并发消费者通用框架
一个示例展示了如何将消息发布到 Pub/Sub,并使用 Python 多处理模块构建一个服务来同时使用这些消息
这个博客也可以在 Linkedin 找到。
本博客将向您介绍谷歌云*台(GCP)中的实时消息队列,即 Pub/Sub。首先,我将解释什么是消息队列,以及我们何时需要消息队列。其次,我将向你介绍 GCP 酒吧。之后,我将展示如何向 GCP 发布消息。最后,我将解释一个使用 Python 中的多处理模块实现的并发消费者。我将在这一部分花大部分时间,因为它是使用 Python 多处理模块的并发消费者的通用代码框架,可以在您的项目中无需任何修改地重用。
我们什么时候需要消息队列?
消息/任务队列接收来自一个或多个应用程序的消息,另一方面将这些请求/消息分派给多个分布式工作器来消费这些任务。在此过程中,产生任务并将其发布到任务队列中的应用程序称为生产者,而从任务队列中接收和消费任务的工作者称为消费者。一个好的任务队列应该能够支持分布式的工人/生产者,并以可接受的延迟分派任务。

GCP 发布/订阅的并发消费者示例
在后台运行异步任务的应用程序中需要任务队列,如下所示。我们有一个前端用户界面,用户通过点击提交按钮触发一系列的工作。这些作业需要异步运行,因为它们非常耗时。作为一个解决方案,我们在这个项目中需要一个任务队列,以守护模式将从生产者(即这个场景中的前端 UI)接收的任务分派给消费者。您可以提出一个解决方案,将从前端接收的任务信息记录在一个 MySQL 表中,然后让工人使用 MySQL 表中的任务。嗯,MySQL 表不适合做任务队列的原因有很多。在 MySQL 表作为任务队列的那种情况下,(1)你的工作人员需要从 MySQL 服务器上一遍又一遍的查询表,这会给你的服务器带来很大的负担,可能会影响你的其他 MySQL 操作。(2)也可能发生两个工作者试图同时消耗相同的任务,尽管使用适当的锁定逻辑,这种概率很小。(3)由于 MySQL 服务器不是分布式的,所以这种设计是不可扩展的。因此,我们应该考虑在这个场景中使用任务队列。
什么是谷歌云*台 Pub/Sub?
谷歌云*台(GCP) Pub/Sub 是一个消息队列管理系统。它类似于芹菜消息队列,但好处是您不需要构建和维护基础设施。在 GCP 发布/订阅中,一个主题是一个接收生产者发布的消息的任务队列。对于一个主题,我们可以创建一个或多个订阅。发布/订阅会将主题中的所有消息发送给每个订阅。多重订阅适用于有多个应用程序使用相同的消息但目的不同的情况。在我们的场景中,单一订阅就足够了。现在你可能会想,如果只有一个订阅,我们怎么会有多个消费者。嗯,订阅不是消费者,在 Pub/Sub 中表示为订阅者。一个订阅可以有多个分布式订阅者,因此发布/订阅会将消息分派给这些订阅者,以便他们可以并发地使用异步任务。
本文将实现一个消费者/订阅者从发布/订阅请求多个消息,并并发运行工作器。要在实际项目中扩大规模,您只需要在不同的计算引擎中运行多个连接到同一个订户的消费者。
如何向 GCP 发布消息?
请参阅以下伪代码作为示例。类似的例子也可以在 GCP 的 GitHub 中找到。
这里,我们在对 Pub/Sub 的单个调用中批量处理多个消息,以提高吞吐量,因为在我们的场景中,延迟并不是那么关键。 BatchSettings() 如果批量消息的大小达到 10240 字节或每 60 秒发布一次。在from _ service _ account _ JSON()中,我们使用 gcp_key 文件作为对 gcp 的认证。并且每次 message_data 发布后,都会触发一个回调函数 log_pub_result() 来显示其发布状态。这里注意,在 Python3 中, PublisherClient 只接受字节串作为数据类型,这就是为什么我们需要将“ message_data ”编码为“ utf-8 ”。
在我们的示例中,Rest API 将触发这个 publisher 模块,以便发布从前端接收到的消息。
如何接收 GCP 酒馆/订阅的消息?
从 Pub/Sub 接收消息的方法有两种: pull 和 push 。在拉的情况下,订阅者/消费者向 Pub/Sub 发送请求以拉消息,而 Pub/Sub 基于消息的发布率向订阅者/消费者推送消息。在我们的场景中,我们将实现消费者从发布/订阅获取消息,因为我们可以控制吞吐量,延迟对我们来说并不重要。在拉取过程中,我们还可以控制每次从服务中拉取的消息数量,这样我们就可以控制单个订阅者/消费者中并发工作人员的数量。一旦消息被发送给订户/消费者,在处理该消息时,它将不会被再次发送给其他订户/消费者。但是,如果消息在确认窗口内没有被确认,那么发布/订阅将考虑再次调度它。因此,在任务完成后确认消息并在任务完成前更新确认窗口非常重要。
使用 Python 多重处理模块的并发消费者通用代码框架
在这一部分中,我将解释使用 Python 中的多处理模块实现的并发消费者的通用代码框架。因为我们的任务是 CPU 受限的,所以我们将使用 Python 中的多处理模块实现并发订阅者/消费者。(1)我们将首先为每个员工分配一条消息/任务。我们将等待所有的工人完成他们的任务。(3)当我们等待工作者时,我们将定期检查消息的确认窗口是否需要每隔一段时间更新。(4)一旦工作者完成其任务,我们将确认该消息。在这样的实现中,如果在消息运行期间抛出任何异常,则消息将不会被确认,这样,发布/订阅将在以后再次将它们分派给订阅者。
然后我将详细解释守护程序服务。完整的示例代码可以在我的 GitHub 中找到。为守护进程服务实现了两个文件, service.py 和 internal/subscriber.py 。 service.py 由 main 函数和任务组成,而 internal/subscriber.py 由从 Pub/Sub 提取消息并启动并发工作器的所有助手函数组成。 internal/subscriber.py 中的代码对于 Pub/Sub 的并发消费者来说是通用的,这些代码无需任何修改就可以在其他项目中重用。
我们先来看看驱动部分,也就是 service.py 中的 main 函数。在这个例子中,它配置了日志,但这与我们的主题无关。除了日志部分,它除了 start_service() 之外什么都不做。
start_service() 函数由 python decorator 包装,它是实现我们的任务的地方,例如示例中的 run_step1() 和 run_step2() 。需要提到的一点是 start_service() 的输入参数。很容易知道“ message ”是从 Pub/Sub 接收的消息,分配给这个 worker,而“ return_vals 是一个字典,用于与 worker 的调用函数进行通信。
装饰器“ listen ”在 internal/subscriber.py 中实现。为了解释 service.py 的作用,我需要展示它的实现。
基本上,“ listen ”接收一个函数作为输入参数,并返回一个新函数 subscriber_wrapper() ,该函数包装了原始函数。因此, service.py 试图启动的服务是包装器:
首先,它通过 connect_to_queue() 连接到 GCP 发布/订阅。然后运行死循环,直到守护程序服务被终止。在循环中, process_messages() 将拉取消息并启动 workers 来完成 start_service 中实现的任务。在所有工作器完成这一轮的任务后,守护进程服务会休眠一段时间,然后反复启动下一轮,直到被杀死。
在上面的解释中,我们实际上使用了普通函数来代替装饰器。在我们的实现中引入装饰器的原因是因为“ listen 中的包装器可以重用,因此我们使用装饰器将它包含在 internal/service.py 中。
现在我们来看 connect_to_queue() ,就是连接 GCP Pub/Sub,没什么特别的。同样,我们使用 json 密钥文件作为对 GCP 的认证。
现在让我们来*距离观察一下 process_messages() 。
它首先从发布/订阅中提取 8 条消息。并调用 start_workers() 衍生出 8 个进程,在每个进程中运行 start_service() 。
在 start_workers() 中使用了多重处理模块。对于每条消息,都会产生一个单独的进程来运行 start_service() (作为参数“ fn ”)函数。如前所述, return_vals 是使用多重处理 管理器创建的,用于与工人通信。注意"workers[worker]=(message . ack _ id,msg_data,1,worker_num)" 记录每个 worker 的消息的 ack_id ,以便在任务完成后用于确认消息。
让我们回到 process_messages() 。创建并启动 8 个进程后,主进程将继续监控这 8 个进程,直到全部完成。在每一轮监控过程中,它都会检查每一个工蚁,看它是活着还是不活着。如果它已经死了,那么我们将检查由 return_vals 返回的任务状态。如果任务完成,没有任何异常,那么我们将需要确认消息,否则不要确认,稍后 Pub/Sub 将再次调度它。
如果工作者仍然活着,那么我们需要检查是否需要扩展确认窗口。否则,在确认窗口到期后,当工作进程仍在处理该消息时,Pub/Sub 将再次调度该消息。如果工作者已经运行了太长时间并且超过了 SLA,那么我们将终止工作者而不延长确认窗口。请注意,每次我们将确认窗口延长 ACK_DEADLINE_SECONDS 秒,这应该大于监控工人的睡眠间隔ACK _ SLEEP _ INTERVALS _ SECONDS。否则,可能会发生确认窗口没有及时更新的情况。
结论
希望现在你已经清楚地了解为什么我们需要任务队列,什么是 GCP 发布/订阅,我们可以用它做什么。此外,希望在 internal/service.py 中实现的代码可以在您自己的项目中重用。
轻松创建统计数据的 Python 包
Statsfig 可以用一行代码创建分布图和盒须图

作者创造的形象。
**Table of Contents**[**Introduction**](#52fd)1\. [Installation](#8ea6)
2\. [List of Functions](#678c)
3\. [Bernoulli distribution: bernofig()](#86cc)
4\. [Binomial Distribution: binofig()](#fac1)
5\. [Box and Whisker Plot: boxplot()](#299a)
6\. [Chi-square Distribution: chifig()](#1c71)
7\. [Exponential Distribution: expofig()](#912f)
8\. [Gamma Distribution: gammafig()](#ce92)
9\. [Normal Distribution: normcdf](#f25a)
10\. [Poisson Distribution: poisfig()](#53fe)
11\. [Uniform Distribution: uniformfig()](#b08e)
12\. [Terminal](#21fd)[**Conclusion**](#5040)
介绍
有时,您可能需要幻灯片或课程的分布图。由于您没有使用数据,您需要一个快速的解决方案。
Python 包 Statsfig 可以用一行代码创建不同的分布图。
我将向您展示创建每个图形是多么容易。
装置
使用pip:
pip install statsfig
然后导入。
import statsfig as sf
功能列表
您可以使用 11 种功能。十个分布函数和一个图。
函数名称和描述。
伯努利分布:伯诺菲格()
bernofig()函数创建了一个伯努利分布,下表显示了所有参数。
伯诺菲格参数。
默认函数的概率为 0.5,大小为 1000。
fernofig()默认函数。
下面的例子显示了概率为 0.6,不同的颜色,没有网格。
具有不同概率、颜色和网格的 bernofig()。
二项式分布:二项式()
binofig()函数创建了一个二项式分布,下表显示了所有参数。
binofig()参数。
默认函数的概率为 0.5,大小为 1000。
binofig()默认函数。
以下示例的概率为 0.7,数字为 30 次试验,向右移动 1。
具有不同参数的 binofig()示例。
[## 如何在 Docker 上运行 Jupyter 笔记本
不再有 Python 环境和包更新
towardsdatascience.com](/how-to-run-jupyter-notebook-on-docker-7c9748ed209f)
盒须图:盒图()
这是唯一一个不是分布图的。
boxplot()功能创建一个盒须图,下表显示了所有参数。
boxplot()参数。
默认函数的info参数有以下值。
{‘bplot 1’:[-9, -4, 2, 4, 9], ‘bplot 2’:[-5, -2, 1, 3, 8], ‘bplot 3’:[1, 4, 6, 8, 10]}
info必须有带name:[min, lower quartile, median, upper quartile, max]的字典形式。
boxplot()默认函数。
如果只想显示一个盒须图,可以这样做:
具有不同参数的 boxplot()示例。
改变vert=False水*显示图形。
具有不同参数的 boxplot()示例。
卡方分布:chifig()
chifig()函数创建卡方分布,下表显示了所有参数。
chifig()参数。
默认函数的自由度为[1,4,6,7]。
chifig()默认函数。
您可以通过使用 python 列表更改dof参数来更改自由度,如下所示。
具有不同参数的 chifig()示例。
指数分布:指数函数()
expofig()函数创建一个指数分布,下表显示了所有参数。
expofig()参数。
默认函数的标准差为 1,大小为 1000。
expofig()默认函数。
您可以通过将hist参数更改为False来隐藏直方图。
具有不同参数的 expofig()示例。
Gamma 分布:gammafig()
gammafig()功能创建伽马分布,下表显示了所有参数。
gammafig()参数。
默认函数的形状参数为 5,大小为 1000。
gammafig()默认函数。
你可以通过改变color参数来改变颜色。您可以使用字符{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}中的一个,它们是蓝色、绿色、红色、青色、品红色、黄色、黑色和白色的缩写。您也可以使用十六进制 RGB 或 RGBA 字符串(如'#4287f5'或'#4287f580')。
具有不同参数的 gammafig()示例。
正态分布:normcdf
normcdf()函数创建正态分布,下表显示了所有参数。
normcdf()参数。
默认函数的*均值为 0,标准差为 1。
normcdf()默认函数。
如果您愿意,可以将大多数参数更改如下:
具有不同参数的 normcdf()示例。
改变下四分位数lb和上四分位数ub,可以找到两个值之间的概率。
另一个不同参数的 normcdf()示例。
norm pdf _ STD normpdf_std()函数创建具有不同标准差的正态分布。下表显示了所有参数。
normpdf_std()参数。
默认函数显示的自由度为[1,2,3,4]。
normpdf_std()默认函数。
您可以使用 Python 列表来更改不同自由度的val参数。
具有不同参数的 normpdf_std()示例。
normpdf _ mean normpdf_mean()函数用不同的*均值创建正态分布。下表显示了所有参数。
normpdf_mean()参数。
默认函数有[0,1,2,3]用于显示*均值。
normpdf_mean()默认函数。
您可以按如下方式更改标题、x 轴最小值和最大值:
具有不同参数的 normpdf_mean()示例。
泊松分布:泊松分布()
poisfig()函数创建泊松分布,下表显示了所有参数。
poisfig()参数。
默认函数的值为 4μ,大小为 1000。
poisfig()默认函数。
具有不同参数的 poisfig()示例。
均匀分布:uniformfig()
uniformfig()函数创建均匀分布,下表显示了所有参数。
uniformfig()参数。
默认函数的大小为 1000,从 10 开始,宽度为 20。
uniformfig()默认函数。
在这里,我们正在改变颜色,网格,以及图形的宽度和长度。
具有不同参数的 uniformfig()示例。
末端的
您也可以从您的终端创建一个图形。

从终端创建图形。

结论
我希望你发现用 Statsfig 软件包创建图形要容易得多。我很想听听关于这个包的任何意见。欢迎在下面留言,或者通过推特联系我。
请继续关注下一篇文章。
通过 成为 会员,获得媒体上所有故事的访问权限。

https://blog.codewithshin.com/subscribe
对 DICOM 文件进行排序的 Python 脚本
这个脚本将帮助您理解和组织您的医学图像数据集
这篇文章是我之前介绍 DICOM 文件的后续文章。特别感谢我的好朋友吉安·马可·康特博士帮助我写这篇文章。
简单回顾一下,DICOM 文件是存储医学图像的主要格式。所有临床算法必须能够读写 DICOM。但是这些文件很难组织。DICOM 文件在文件头中保存了与图像相关的信息,文件头可能很大。文件分为 4 层:
- 病人
- 研究
- 系列
- 情况
在本教程中,我将分享一些 python 代码,这些代码读取一组 DICOM 文件,提取标题信息,并将文件复制到分层的文件夹结构中,以便轻松加载数据科学任务。
有许多很好的资源可以用来使用 Python 或其他语言解析 DICOM。 DicomSort 有一个灵活的 GUI,可以根据文件头中的任何字段来组织文件(DicomSort 也可以作为一个带有“pip install dicomsort”的 Python 包获得)。我还想感谢这个报告让我开始阅读 DICOM 像素数据集的代码。最后,这篇伟大的论文中有一节是关于图像压缩的,我在这里简单地提一下。
最终,我决定编写自己的实用程序,因为我喜欢确切地知道我的代码在做什么,它还提供了对 DICOM 头的介绍,这是任何从事医学成像项目的数据科学家的基本知识。
我已经为 CT 和 MRI 检查验证了这个代码;它应该适用于任何设备——所有 DICOM 文件都会报告患者、研究和系列信息。
所需的代码包
这段代码使用 Python 包 PyDicom 来读写 Dicom 文件。
我想简单提一下 GDCM 包。DICOM 文件可能在存储期间或通过 DICOM 接收器传输期间进行图像压缩。例如,在我们的机构,所有的 DICOMs 都有 JPEG2000 压缩。GDCM 是一个基于 C 的包,允许 PyDicom 读取这些加密文件。它以 conda 包(“conda install gdcm”)的形式提供,或者使用 cmake 从源代码构建。我在下面的代码中偷偷添加了几行代码,使用 GDCM 来解压缩像素数据,这样我以后就不用担心了。
更新——自从写了这篇文章,我开始使用比 GDCM 更容易安装的pylibjpeg包。我在文章末尾补充了更多的信息。
代码演练
完整的、不间断的代码版本在本文末尾。
首先,我们指定哪个目录包含我们的 DICOM 文件(“src”),以及它们将被复制到哪里(“dst”)。请注意,该文件是复制的,而不是移动的,因此我们最终将存储每个文件的 2 个副本。我们将不分先后地阅读 DICOM 文件——每个文件在文件头中都包含足够的信息,可以准确地识别它来自哪里。
对于列表中的每个文件,我们将使用 PyDicom 包将文件头作为字典加载。
我们将在患者、研究和系列级别对 DICOM 文件进行分类(有关这些术语含义的更多信息,我鼓励您通读我的之前的介绍)。我还添加了一个额外的级别,即研究日期,如果您希望对同一患者进行多项研究,这将是非常有用的信息。
有两个字段分别与患者、研究和系列相关联:一个唯一标识符(UID) 和一个文本描述。您将看到的大多数 DICOM 数据集都是使用 uid 排序的。尽管 uid 总是唯一的,但是它们会导致很长的文件夹树,不容易理解。我已选择将每个文件保存在文本描述下,同时保留患者 ID 以提供一层匿名性(尽管患者姓名仍将出现在标题中)。
在几个数据集上使用这段代码,我还没有遇到过病历报告或系列信息丢失的情况,但是在极小的可能性下,我们会用“NA”替换它。
最后,我将包含一个小函数,用于清理“禁止”字符的文本描述,删除空格,并将文本转换为小写,这使得目录名更加清晰。
文件名将由设备 (CT、MRI 等)连接而成。)、系列 UID 和实例号。我将包含研究 UID ,但是这会产生一个很长的文件名。
最后,我将删除任何 JPEG2000 或任何其他文件压缩。这是使用 GDCM 包完成的,它是一个可选的包,可以安装在 PyDicom 的下面。这不是 100%万无一失的(像 DICOM 的大部分内容一样),因此我的新手尝试/例外语句:
脚本的其余部分创建了我们的分层文件夹树。同样,我增加了一个额外的按研究日期排序的级别。否则,可能很难区分我们单独的病历报告,并且如果两份病历报告有相同的描述,所有系列将被集中在一个文件夹中。
使用数据集上的代码
为了测试这段代码,让我们在数据集上运行它。我选择了 2019 年 RSNA·卡格尔比赛,该比赛以诊断颅内出血的头部 CT 为特色。
现在,所有的文件都保存在一个目录中,这也是数据最初可用的方式。让我们看看这个脚本是否能帮助我们组织它:


图一。该代码按照患者、日期、研究描述和系列描述(右)将我们的非结构化 DICOM 文件列表(左)解析为嵌套的文件夹结构。文件也根据设备、系列 UID 和实例号进行重命名。图片作者。
虽然文件列表很长,我们只能看到最上面的文件夹,但是请注意,文件已经按照患者 ID (已被取消识别)扫描日期、以及系列和研究描述进行了分类,这些描述告诉我们一些关于我们正在查看的图像的信息。此外,这些文件已被重命名为模态、系列 UID 和实例号,以便于按行排序。
完整代码
更新—用于文件压缩的新软件包
自从写了这篇文章,我遇到了比我上面提到的 GDCM 包更容易安装和配置的 pylibjpeg 包。
Pylibjpeg 有几个依赖项,下面是我从我的 requirements.txt 中复制的列表
pylibjpeg
pylibjpeg-openjpeg
pylibjpeg-libjpeg
pydicom
如何建立量化交易市场数据仓库
如何组织从 Polygon.io 获得的数据的回顾和示例

图片由 Pixabay 的 Pexels 提供
为什么交易基础设施战略是相关的
定量金融需要大量的数据工程。一旦您开始处理小于每日数据的时段,这一点尤其正确。通过数据工程,我定义了用于检索、存储、解析、确保质量和向最终客户分发数据的方法、技术、软件、程序和基础设施。
虽然这个领域的光芒不及获得成功交易策略的算法,但它是一个重要的部分,必须正确处理。这种基础设施的设置是专业操作的一部分,也是业余人员和专业人员在该领域的不同之处之一。定义正确的基础设施是业务运营的一部分,在利用量化交易赚钱的中长期旅程中扮演着重要角色。
不同的方法
有不同的方法来满足这种数据工程的需要。所有方法都同样有效,但它们之间存在明显的权衡,了解您的资源和环境以选择正确的方法非常重要。我将描述我所看到的,这些信息来自我的实验,从行业人士那里收集的信息,由富有的量化交易者提供的信息,以及我从成熟的交易公司收集的信息(主要是自营交易和商品,不幸的是,我不知道这个行业有多少参与者)。
供应商环境方法
不需要高速或精细时间粒度来移动大量交易资本的大公司可以选择专有环境(如微软生态系统)来移动和存储数据。通过这样做,你可以指望友好的编程环境,无论何时需要定制任何东西(C#和 Python),通过 Azure 和微软 ETL 工具集成云存储,以建立一个易于维护的数据管道——微软这么说的——。这种方法的优点是对所有事情都使用相同的技术,并且您可以期望不同组件之间的*滑集成。使用商业解决方案还提供了供应商支持,这总是好的。作为一个权衡:它是昂贵的,您依赖于一个供应商,它涉及经常性成本,并且某些活动不能正确地完成,因为您正在使用通用工具。我在一家信誉卓著的商品交易公司看到过这种方法。如果你需要处理高速的或者非常定制的或者 ML 密集型的策略,这可能不是最好的环境。
全 Python 方法
业界广泛使用的另一种方法是构建纯 Python 解决方案。对于那些在过去读过其他文章的人来说,你可能已经知道我个人对 Python 的感觉是复杂的。Python 的一个优点是非常容易编码,并且可以使用许多 ML 库,Jupyter 笔记本可以简化结构的维护,并且它促进了程序的自文档化。这不是最佳解决方案,但在混合环境中,我真的认为它可以在运营方面提供真正的好处。我一直在想,Python 无论从性能还是速度上来说都不是一个好的选择,但是编码高级别的可维护软件层却是极好的。更短的开发时间和更容易的团队协作的好处胜过性能障碍。有经验的 Python 开发人员也可以采用其他方法来提高 Python 的速度,尽管您正在将 Python 推向超越其本质的极限。我看到这种方法在一家规模较小、声誉卓著的对冲基金公司得到了非常成功的应用。
C++/Java 方法
另一种方法是使用 C++或 Java 作为环境,开发一个定制的框架来处理数据。这是公司在一天内或高频率操作大量数据时使用的方法。对于分笔成交点数据,您可能至少在基础设施的某些领域需要这种方法。关于要使用的具体语言,C++是旗舰机构公司的首选,但 Java 可以以更低的运营成本使用,我已经看到非常成功的小公司用 Java 交付所有东西。事实上,你可以拥有与 C++几乎相同的性能,但是比 C++更容易管理语言和开发/调试环境。我最*在用 Java 做很多东西,因为我不是一个特别好的程序员。交易软件的某些方面用 C/C++语言来表示要好得多(具体来说,我发现用 C 为 OHLC 和分笔成交点数据定义数据结构比用 Java 更自然)。在交易中使用 Java 总是涉及到以一种对 Java 程序员来说不太自然的方式编码,因为你需要总是从低级编程和性能的角度来考虑,因此 C 语言背景是有益的。
存储替代方案
数据本身可以(并且通常存储在)数据库中,但这可能是一个错误。SQL 和非 SQL 方法都可以使用。我不再将 SQL 用于市场数据——我最开始使用它——但这是因为我现在的重点是用很少的工具进行日内策略,所以我必须处理大量非常同质的数据。关系数据库在这方面没有任何价值。另一种方法是使用 CSV 文件(是的,它们被广泛使用,这是有原因的)或其他纯文本方法(比如我使用的方法,我将在后面描述)。这种方法的优点是可以轻松地使用、检查和访问数据,并且有效地消除了另一个维护点和难点:数据库。
这些描述的方法的共同点是它们通常依赖于给定的语言或技术,而不是系统工程方法。这并不意味着不涉及某些系统工程,但往往不是主要的方法。
另一种方法可以被成功使用,特别是对于个体交易者、资源有限的小型对冲基金或小型自营交易公司(或初创公司)。声明:这种方法会伤害感情,因为它提倡重复使用 40 年的老技术。
UNIX:基于文件的协作小工具方法
在追求简单性的过程中,我尽可能地去除了许多层和软件,同时也减少了需要交付的定制代码的数量。任何有助于实现这一目标的因素都有助于降低运营费用,减少需要完成的总工作量和维护量。在思考这个问题时,我发现,基于 UNIX 系统工程而不是基于 DevOps 或基于编程语言的基础设施,重用文件和小型协作工具的经典 UNIX 方法可能非常有利于设置操作。
我总是使用 UNIX 这个词,因为我使用 FreeBSD,但它同样适用于 Linux。
有一本 1985 年由 Kernighan & Pike 写的名为《UNIX 编程环境》的书。它是一本非常古老的书,C 代码甚至是 K & R pre-ANSI 风格,但在 C 编程社区中仍然广为人知;这可能是你能阅读的理解什么是真正的 UNIX 的最好的一本书:一个编程环境,可以轻松地重用小程序和工具,不费吹灰之力地构建解决方案。
诸如广泛的文件使用(“一切都是文件” UNIX 方法)这样的概念已经在很大程度上被抛弃,以包含更复杂的结构和解决方案。但是你总是可以停下来花一分钟思考一下:你真的需要一个数据库吗?或者你只是假设你需要一个数据库,因为每个人都这么告诉你?你真的需要一个基于 API 的云存储吗?或者你可以使用一个普通的文件系统——它可以完美地备份或存储在云上,这没什么不对的。您真的需要使用最新的流行框架在 Python 中编写 API 访问代码吗?或者在您的数据文件系统上安装一个 HTTP 服务或远程文件服务器就足够了吗?第一个选项甚至允许构建一个 REST 访问系统,而无需编写任何代码。
这些问题通常不受有偏见的专业人士的欢迎,尤其是那些专攻某项技术或语言的专业人士,因为它用简单的工具和零维护的方法来挑战当前普遍膨胀的实践。
零维护对于像我这样已经达到一定年龄(经验)的人来说非常重要,因为我们在过去已经犯过建造复杂东西的错误。对于缺乏资源和团队的小型企业,部署简单的解决方案是必要的。
我将在以下部分描述如何建立一个 1 秒钟的外汇数据基础设施服务。这是我的最新基础设施设置的一部分,用于回测和分析外汇中的量化策略,我将说明依靠 UNIX 系统中的小型合作工具的混合环境如何能够加快操作。
业务需求:定量分析
在我上次的定量分析中,我想使用外汇数据,使用 1 分钟的汇总数据。一分钟汇总数据意味着我想探索价格信息如何取代交易量信息(交易量信息在外汇交易中并不总是可用)。这来自于合并市场概况(其中时间和价格等于利息或价值)和成交量概况(其中成交量等于利息或价值)的市场概念。因此,时间和价格可以取代成交量,因此可以用来成功驾驭市场(这是我的前提,也是我想要分析的,它可能是错的,也可能是对的,但听起来是合理的)。
要获得 1 分钟的市场概况,我们需要一定的粒度,最好是分笔成交点数据,但让我们假设 1 秒钟的价格信息就足够了(同样,这是我们的前提、假设或公理,可能是对的,也可能是错的)。
这是我的业务需求:分析 1 分钟蜡烛线以上的市场概况信息是否可以用来控制市场。这种业务需求转化为技术或基础设施需求:我需要能够在我的分析中轻松消耗外汇市场 1 分钟蜡烛线的市场概况。
因此,我需要存储每 1 分钟分组一次的数据,并可能在以后处理这些数据并生成包含聚合信息的附加文件。
任何技术需求的背后,总要有一个业务需求。在任何技术解决方案的背后,都必须有完整的成本/资源分析,包括项目和运营费用。这些基本检查并不总是专门为只具有技术背景的人进行的,他们可能对中长期运营成本没有自然的了解。
从 Polygon.io 收集市场数据
无论是历史数据还是实时数据,您总是需要一个数据提供者。如果您要使用数据,将数据存储在本地(或您的私有云)作为缓存是有意义的,但专用数据公司将比您更好地确保连续性和可靠性,最终,您需要访问市场数据,并且您可以不支付(或者即使您可以支付也没有意义)交易所市场访问费和相关的项目成本。
让我们检索欧元兑美元的 1 秒钟数据,让我们看看用于此的 Polygon.oi API:

polygon.io API 从 Forex 检索 1 秒钟的买卖价格信息
有几种方法可以检索和存储这些数据,通常想到的第一种方法是使用编程语言和数据库。所以 Python 和 SQL 可能是一个选项。由于 Polygon.io 返回的记录数量被限制为 10.000,您将需要执行几次调用来填充偏移量参数,直到您检索到所有信息,因此某些编程是明确需要的。信息也以 JSON 的形式被检索,但是我们肯定不想存储或处理 JSON,因为它非常低效。
以下是我对这项任务的建议:
技巧 1:定义如何存储数据
这里我不会使用任何数据库。相反,我将把所有的出价/要价信息作为空格分隔的值存储在一个文件中。由于我们显然需要某种随机访问,我们将在每个自然日将这些数据分离到一个文件中。20 年来,这造成了最多 7300 个文件,这无疑是任何现代操作系统所能处理的极限数字。
技巧 2:简化时区
时区很重要,它们通常是一个挑战和难点。我发现最好的选择是简化它们:我总是使用东部时间。我这样做是因为大多数数据供应商在这个时区提供数据(即使是欧洲的工具/资产)。我这样做是因为就交易而言,纽约的现金交易时段可能是一天中最重要的时段(或者至少是相关的时段)。我这样做是因为知道你所有的数据,不管是什么,都是以东部时间存储的,这非常简单。
提示 3:不要担心会议开始的时间
我应该根据纽约的现金交易时段来分组我的数据吗?也许是的。但是根据我存储数据的经验,使用东部时区的自然日要好得多。如果你想分析一个特定的时间(例如 9:30 以后),你可以在你的分析中这样做。但数据应在自然天数内保存。为什么?我这样做只是因为根据我的经验这是最容易做到的事情。你可能会提出异议,如“亚洲时段可以包括前一个自然日的结束和当前自然日的开始”或“我想处理常规和延长的交易时间,延长的时间跨越两个自然日”,等等。所有的反对意见都是有效的,但是,我发现的最简单的答案,即使在处理这些问题时,也总是一样的:按照东部时间的自然天数来存储你的数据。
技巧 4:在目录中排列文件
UNIX 世界的一个伟大成就是目录结构。用吧,免费,零维护。因此,将你的文件按年、年、月或年、月、日分类。在我的例子中,我选择了后者,因为我打算进一步部署更多包含聚合信息的文件。
因此,如果您想要 2019 年 4 月 3 日的欧元美元数据,您已经知道它位于/data/EURUSD/2019/04/03/EURUSD . 2019 . 04 . 03 . tape .中,如果您想要读取它,您只需在该文件上执行 cat 即可显示其内容:
memmanuel@almaz:~ % head /data/EURUSD/2019/06/27/EURUSD.2019.06.27.tape
1.13735 1.13745 1561593600000
1.13717 1.13761 1561593600256
1.13719 1.13761 1561593600560
1.13718 1.13760 1561593600791
1.13719 1.13761 1561593602595
1.13719 1.13761 1561593602995
1.13740 1.13770 1561593603000
1.13718 1.13760 1561593603222
1.13719 1.13761 1561593603521
1.13735 1.13743 1561593605000
看到了吗?它简单得令人尴尬,而且方便。
技巧 5:将数据存储为固定大小的字段
不要在 CSV 中存储数据,使用固定大小的字段。这种差别很细微,但对以后的性能有很大的好处。在前一种情况下,字段是可变长度的(1.1373 和 1.13732),在第二种情况下,您为每个字段定义精确的长度,并在需要时填充零(1.13730 和 1.13732)。在上面的例子中,我们知道 EURUSD 有 5 个小数位和 1 个自然位,所以每个价格正好有 7 个字符。这简化了 C 和 Java 中低级例程的使用,这将使您的回溯测试数据检索更快。不要使用逗号,因为在 UNIX 中,列通常由空格分隔,并且当列由空格分隔时,手动检查文件更容易,通过这样做,您可以始终使用 CSV 技术,但也可以通过读取固定宽度的字段来获得性能。
技巧 6:编写一个简单的工具来检索一个自然日
编写一个简单的、自包含的命令行工具来检索给定日期的所有数据并存储它。因为您已经定义了每天的数据去向,所以您可以很容易地做到这一点。令人惊讶的是,你甚至不需要编写任何程序来检索数据,有人,比你我都聪明,已经编写了一个名为 curl 的工具,它将为你检索数据。您仍然需要一个小脚本来迭代请求,因为每天可能会有超过 10000 条记录。你可以用 Python 或者 shell 脚本来实现,如下例所示。注意重用现有工具是如何简化编程的:
- 我们用 curl
curl消费 REST 服务。 - 我们使用
jq将 JSON 转换成文本文件。 - 我们使用
awk.将数字转换成固定宽度
从 Polygon.io 下载每日外汇数据的示例命令行工具。用 Bash 编写,可以用 Python 或 Perl 编写。它使用 curl、jq 和 awk 来简化某些任务。
这就是 UNIX 的设计用途:只做一件事的小工具。
技巧 7:构建重用基本命令的助手命令。
每天检索数据真的很耗时。所以你可以写一个命令来检索一整年的数据。在这种情况下,用 Python 解析日期更容易,所以用 Python 编写命令。它只是在循环中调用前一个。
这个工具最好用 Python 编写,因为处理日期更容易。它遵循构建小工具的 UNIX 方法,只解决一个具体的需求。
摘要
在这篇文章中,我简要回顾了通常是如何根据存储财务数据进行回溯测试的,我还介绍了一种非常简单的检索和存储数据的方法。下一步是对数据进行预处理,以获得您想要的分析(在我的例子中,我希望及时分析出价/要价和价格分布,因此我将相应地生成更多的文件)。这篇特定文章的要点是,通过执行这些简单的步骤,我们已经有效地将数据的检索和存储从我们的策略分析中分离出来(只用了两个简单的工具)。不仅如此,我们还定义了一种存储数据的方法,这种方法非常容易交流、理解和记忆,并且无需维护。解耦在任何软件项目中都非常重要,因为这是制造可重用组件和避免未来问题的最佳策略。
使用普通文件存储数据不会让所有人都满意。“文件太多”、“文件描述符太多”、“速度慢”(未经测试)、“有更好的选项”、“缺乏功能”、“不够酷”。但是最后,你会发现很难找到一个人提出不使用文件的真正好处(在某些情况下可能存在)。
不要被复杂的亚马逊 AWS 或任何最新的云存储 API 所困扰。大多数情况下,您不需要这种复杂性。
这些文件很紧凑,很容易按自然日寻址。您可以很容易地定位任何特定的时间,因为每个文件都有固定宽度的记录,大约 80k 字节,这很容易解析,如果您真的需要跳转到特定的位置,也很容易实现搜索算法(不过我认为将整个文件读入内存更容易)。
在下一个聚合阶段,使用您的分析所需的特定聚合数据创建新文件,这强化了这一点。普通列固定宽度文件可以在每种语言或工具(Octave、R、Python、C、Java、sed、awk 等)中使用,如果考虑到每条记录(行)的长度总是相同的话,它甚至会非常有效。
在自营交易运行分析和对历史数据进行回溯测试的情况下尤其如此。主要关心的可能是访问时间,但是回溯测试和分析通常涉及对顺序数据的大量计算,因此磁盘访问时间通常可以忽略不计。如果没有,数据总是可以放在缓存的 RAM 文件系统中,这解决了问题,而无需编写一行代码。
如果需要远程访问数据,可以使用简单的 NFS,或者部署 HTTP 服务器来分发文件。只需几行配置,您将拥有一个 REST 服务,而无需编写一行简单的代码。从中可以看出,UNIX 有许多旨在简化和重用的工具和服务,不管这项技术看起来有多古老:编程并不总是解决问题的答案。
补充说明:如果您正在处理聚集的基本 OHLC 数据,那么根本不存储数据并向数据提供者请求按需数据可能是一种选择。但通常情况下,你总是想用数据、自定义计算或聚合来做事情。或者你正在迭代大量的数据,所以通常情况下,我发现你总是需要下载数据并在本地访问它。
随机森林回归快速肮脏指南

随机森林回归的实践方法
作为机器学习实践者,我们会遇到各种各样的机器学习算法,我们可以应用它们来构建我们的模型。在这篇文章中,我将尝试给你一个关于随机森林模型如何从头开始工作的概念的直觉。该算法可用于计算回归和分类问题。
首先,我们将熟悉一些重要的术语,如集成学习和引导聚合,然后我将尝试给你一个算法的直觉,最后,我们将使用随机森林回归器建立我们自己的机器学习模型。
在开始这篇文章之前,我建议你看一下我以前关于决策树的文章这里,这对于任何期待学习这个算法的人来说都是至关重要的先决条件。
集成学习:
假设你想看一部关于网飞的网络连续剧。你会登录你的账户,观看弹出的第一个网站,还是浏览几个网页,比较评分,然后做出决定。是的。很有可能你会选择第二个选项,而不是直接下结论,你也会考虑其他选项。

图片来自维基共享资源
这正是集成学习的工作方式。集成学习是一种将来自多个机器学习算法的预测结合起来的技术,可以比任何单独的模型都更准确地预测。简而言之,集合模型是由许多模型组成的模型。有许多综合技术,如堆垛、装袋、混合等。让我们详细看看其中的几个。
增压
顾名思义,Boosting 是一种通过将单个弱学习者分组以形成单个强学习者来促进学习的技术。这是一个连续的过程,每个后续模型都试图纠正前一个模型的错误。后续模型依赖于前一个模型。

图片来自奥莱利媒体
自举聚合
Bootstrapping 是一种采样技术,其中我们从原始数据集创建观察值的子集。这种技术也被称为装袋。所用子集的大小与原始集的大小相同。在这种技术中,通过组合各种预测模型的结果来获得一般化的结果。为打包创建的子集的大小可能小于原始集。
决策树的问题
尽管决策树是一种有效的回归模型,但仍有一些差异会阻碍决策树的顺利实现。其中一些如下所述:
- 数据的微小变化可能会导致一组完全不同的数据,从而导致模型给出不正确的预测。
- 决策树对它们被训练的数据非常敏感,对训练集的微小改变会导致明显不同的树结构。
- 决策树倾向于寻找局部最优解,而不是考虑全局最优解。
为了解决这些问题,兰登森林公司来了。
随机森林
随机森林是一种监督学习算法,它使用集成方法(bagging)来解决回归和分类问题。该算法通过在训练时构建大量决策树并输出各个树的预测均值/模式来运行。

图片来自 Sefik
随机森林背后的基本概念是群体的智慧,其中大量不相关的模型作为一个委员会运作,将胜过任何单个的组成模型。
这背后的原因是,这些树相互保护,避免各自的错误。在一个随机森林中,个体树之间没有相互作用。随机森林充当一种估计算法,它聚合许多决策树的结果,然后输出最佳结果。

图片来自简单统计
现在我们有了什么是随机森林的要点,我们将尝试构建我们自己的随机森林回归器。构建这个回归模型的代码和其他资源可以在这里找到。
第一步:导入所需的库
我们的第一步是导入构建模型所需的库。没有必要在一个地方导入所有的库。Python 给了我们在任何地方导入库的灵活性。首先,我们将导入 Pandas、Numpy、Matplotlib 和 Seaborn 库。
#Import the Libraries and read the data into a Pandas DataFrameimport pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as snstest = pd.read_csv("california_housing_test.csv")
train = pd.read_csv("california_housing_train.csv")
一旦导入了这些库,我们的下一步将是获取数据集并将数据加载到我们的笔记本中。对于这个例子,我采用了加州住房数据集。
第二步:可视化数据
成功加载数据后,我们的下一步是可视化这些数据。Seaborn 是一个优秀的库,可以用来可视化数据。
#Visualise the dataplt.figure()
sns.heatmap(data.corr(), cmap='coolwarm')
plt.show()sns.lmplot(x='median_income', y='median_house_value', data=train)
sns.lmplot(x='housing_median_age', y='median_house_value', data=train)
第三步:特征工程
特征工程是利用领域知识通过数据挖掘技术从原始数据中提取特征的过程。对于这个模型,我选择了只有数值的列。为了处理分类值,应用了标签编码技术。
#Select appropriate featuresdata = data[[‘total_rooms’, ‘total_bedrooms’, ‘housing_median_age’, ‘median_income’, ‘population’, ‘households’]]
data.info()data['total_rooms'] = data['total_rooms'].fillna(data['total_rooms'].mean())
data['total_bedrooms'] = data['total_bedrooms'].fillna(data['total_bedrooms'].mean()
当特征数量非常大时,特征工程变得更加重要。特征工程最重要的用途之一是减少过度拟合,提高模型的准确性。
步骤 4:拟合模型
选择所需参数后,下一步是从 sklearn 库中导入 train_test_split,该库用于将数据集拆分为训练和测试数据。
#Split the dataset into training and testing dataimport train_test_split
X_train, X_test, y_train, y_test = train_test_split(train, y, test_size = 0.2, random_state = 0)y_train = y_train.reshape(-1,1)
y_test = y_test.reshape(-1,1)
在此之后从 sklearn.ensemble 中导入 RandomForestRegressor ,并且模型适合训练数据集。参数 n_estimators 决定了森林中树木的数量。默认情况下,该值设置为 100。
from sklearn.ensemble import RandomForestRegressor
rfr = RandomForestRegressor(n_estimators = 500, random_state = 0)
rfr.fit(X_train, y_train))
如果 bootstrap 设置为 true,则子样本大小由 max_samples 参数控制,否则将使用整个数据集来构建每棵树。
随机森林的优势
- 它可以在大型数据集上高效运行。
- 随机森林比其他算法有更高的准确率。
- 它有一个有效的方法来估计缺失数据,并在大部分数据缺失时保持准确性。

图片来自维基百科
随机森林的缺点
- 随机森林可能会导致某些数据集过度适应有噪声的回归任务。
- 对于分类变量具有不同层数的数据,发现随机森林偏向于那些具有更多层数的属性。
至此,我们已经到了这篇文章的结尾。我希望这篇文章能帮助你理解随机森林回归的本质。如果你有任何问题,或者如果你认为我有任何错误,请联系我!您可以通过邮箱或 LinkedIn 与我联系。
建立和测试股票交易策略的快速简单的方法
回溯测试、数据、度量、实时实现和缺陷

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
算法交易策略开发
回溯测试是量化交易的标志。回溯测试采用历史或综合市场数据,测试算法交易策略的盈利能力。这个主题需要统计学、计算机科学、数学、金融和经济学方面的专业知识。这就是为什么在大型量化交易公司里,对相关学科有丰富知识(通常是博士水*)的人会有特定的角色。专业知识的必要性不可低估,因为它将成功(或看似成功)的交易策略与失败的交易策略区分开来。我这篇文章的目标是将我认为的基本回溯测试过程分成几个不同的部分…
- 一、回溯测试引擎
- 二。历史和综合数据管理
- 三。回溯测试指标
- 四。现场实施
- 五、战略发展中的陷阱
回溯测试引擎
主回溯测试引擎将使用名为 backtrader 的库在 Python 中构建。Backtrader 使得建立交易策略并根据历史数据立即实施变得非常容易。整个图书馆以脑波强化器课程为中心。顾名思义,您可以将此视为回溯测试的大脑或引擎。
我决定构建一个函数,这样我就可以动态地参数化回溯测试的不同方面(并最终构建一个管道)。我们需要讨论的下一门反向交易课程是策略课程。如果您查看我为存放 Cerebro 实例而构建的函数,您会看到它将一个策略作为输入——这需要一个 backtrader 策略类或子类。Strategy 类的子类正是我们将用来构建自己的策略的。如果你需要一个多态和继承的复习者或者不知道那是什么意思,请看我的文章 3 分钟内的 3 个 Python 概念。让我们为我们的回溯测试建立一个策略…
在主策略中,我在上面的策略子类中创建了我们在做交易决定之前有兴趣了解的字段。假设每日数据频率,我们在后推过程中每一步可以访问的字段是…
- 开盘当日价格
- 当日收盘价格
- 日低价格
- 日价格高
- 日交易量
不需要天才就能明白,你不能用最高价、最低价和收盘价来做最初或当天的交易决定,因为我们无法实时获得这些信息。但是,如果您想存储它并访问以前的信息,这是很有用的。
你现在脑子里的大问题应该是数据从哪里来?
这个问题的答案在反向交易库的结构中。在运行容纳 Cerebro 的函数之前,我们将添加我们想要进行回溯测试的所有策略和一个数据馈送——其余的都由 Strategy 超类处理,因为 Strategy 超类保存了容纳所有市场数据的数据系列。
这让我们的生活变得异常轻松。
让我们通过制定一个简单的只做多均值回归风格的交易策略来结束主策略课。为了访问一个数据点,我们覆盖了下一个函数并添加了交易逻辑…
每天都会得到一个根据我们将买入或卖出股票的数量计算出来的 z 值(与*均值的标准偏差数)。请注意,是的,我使用当天的收盘价来做决定,但我也使用当天的收盘价作为我交易的进场价格——使用第二天的开盘价更明智。
下一步是将策略添加到我们容纳大脑实例的功能中…
在上面的代码中,我将提供给函数的策略添加到了 Cerebro 实例中。这超出了本文的范围,但是我觉得有必要把它包括进来。如果我们进行回溯测试的策略需要额外的数据(一些 AI 模型),我们可以在 args 参数中提供它,并将其添加到策略子类中。
接下来,我们需要找到历史数据或合成数据的来源。
历史和综合数据管理
我将历史和合成市场数据作为同义词使用,因为一些研究人员发现合成数据无法与其他市场数据区分开来(因此其生成性更丰富)。出于这个例子的目的,我们将使用 backtrader 提供的 YahooFinance 数据提要,同样使实现变得非常容易…
向我们的回溯测试中添加一个数据馈送是如此容易,这几乎是荒谬的。数据对象使用 backtraders YahooFinanceData 类根据符号、fromdate 和 todate 检索数据。之后,我们只需将这些数据添加到脑波机实例中。backtrader 架构的真正魅力在于实现了数据自动放置在其中,并通过添加到 Cerebro 实例的每个策略进行迭代。
回溯测试指标
有很多指标可以用来评估交易策略的表现,我们将在这一部分介绍一些。同样,backtrader 使得添加分析器或性能指标变得极其容易。首先,让我们为我们的 Cerebro 实例设置一个初始现金值…
我们可以使用多种指标来评估风险、回报和绩效,让我们来看看其中的一些…
夏普比率
正如《show Billions》中提到的,每单位风险的回报率,夏普比率。定义如下…

几次失败和假设。它基于历史表现,假设正态分布,经常被用来错误地比较投资组合。然而,它仍然是任何策略或投资组合的主要部分。
系统质量号
这是一个我一直喜欢使用的有趣指标,因为它包括了特定时期的交易量。计算方法是将 SQN 乘以交易次数,然后将乘积除以 100。下面是不同细分市场、地区和行业的价值图表。

图片来自万瑟普
现在,让我们将这些指标添加到脑波强化器中,并运行回溯测试…
现在,我们所要做的就是运行上面的代码,我们会根据我们指定的指标获得我们策略的性能…
这是输出…
Starting Portfolio Value: 100000.002018-01-30, 160.95
2018-01-30, BUY CREATE, 160.952018-01-31, 161.4
2018-02-01, 161.74
2018-02-02, 154.72
2018-02-02, BUY CREATE, 154.72
2018-02-05, 150.85
2018-02-05, BUY CREATE, 150.85
2018-02-06, 157.16
2018-02-07, 153.792018-02-08, 149.56
2018-02-09, 151.39
2018-02-12, 157.49
2018-02-13, 159.07
2018-02-14, 162.0
2018-02-15, 167.44
2018-02-16, 166.9
2018-02-20, 166.332018-02-21, 165.58
2018-02-22, 166.96
2018-02-23, 169.87
2018-02-26, 173.23
2018-02-27, 172.66
2018-02-28, 172.42018-03-01, 169.38
2018-03-02, 170.55
2018-03-05, 171.15
2018-03-06, 171.0
2018-03-07, 169.41
2018-03-08, 171.26
2018-03-09, 174.2
2018-03-12, 175.89
2018-03-13, 174.19
2018-03-14, 172.71
2018-03-15, 172.92
2018-03-16, 172.31
2018-03-19, 169.67
2018-03-20, 169.62
2018-03-21, 165.77
2018-03-21, BUY CREATE, 165.77
2018-03-22, 163.43
2018-03-22, BUY CREATE, 163.43
2018-03-23, 159.65
2018-03-23, BUY CREATE, 159.652018-03-26, 167.22
2018-03-27, 162.94
2018-03-28, 161.14
2018-03-29, 162.4
2018-04-02, 161.33
2018-04-03, 162.99
2018-04-04, 166.1
2018-04-05, 167.252018-04-06, 162.98
2018-04-09, 164.59
2018-04-10, 167.69
2018-04-11, 166.91
2018-04-12, 168.55
2018-04-13, 169.12
2018-04-16, 170.18
2018-04-17, 172.522018-04-18, 172.13
2018-04-19, 167.25
2018-04-20, 160.4
2018-04-23, 159.94
2018-04-24, 157.71
2018-04-25, 158.4
2018-04-26, 158.952018-04-27, 157.11
2018-04-30, 159.96
2018-05-01, 163.67
2018-05-02, 170.9
2018-05-03, 171.212018-05-04, 177.93
2018-05-07, 179.22
2018-05-08, 180.08
2018-05-09, 181.352018-05-10, 183.94
2018-05-11, 183.24
2018-05-14, 182.81
2018-05-15, 181.15
2018-05-16, 182.842018-05-17, 181.69
2018-05-18, 181.03
2018-05-21, 182.31
2018-05-22, 181.85
2018-05-23, 183.02
2018-05-24, 182.812018-05-25, 183.23
2018-05-29, 182.57
2018-05-30, 182.18
2018-05-31, 181.57
2018-06-01, 184.84
2018-06-04, 186.392018-06-05, 187.83
2018-06-06, 188.482018-06-07, 187.97
2018-06-08, 186.26
2018-06-11, 185.812018-06-12, 186.83
2018-06-13, 185.29
2018-06-14, 185.39
2018-06-15, 183.48
2018-06-18, 183.392018-06-19, 180.42
2018-06-20, 181.21
2018-06-21, 180.2
2018-06-22, 179.68
2018-06-25, 177.0
2018-06-25, BUY CREATE, 177.002018-06-26, 179.2
2018-06-27, 178.94
2018-06-28, 180.24
2018-06-29, 179.862018-07-02, 181.87
2018-07-03, 178.7
2018-07-05, 180.14
2018-07-06, 182.64
2018-07-09, 185.172018-07-10, 184.95
2018-07-11, 182.55
2018-07-12, 185.61
2018-07-13, 185.9
2018-07-16, 185.5
2018-07-17, 186.022018-07-18, 185.0
2018-07-19, 186.44
2018-07-20, 186.01
2018-07-23, 186.18
2018-07-24, 187.53
2018-07-25, 189.292018-07-26, 188.7
2018-07-27, 185.56
2018-07-30, 184.52
2018-07-31, 184.89
2018-08-01, 195.78
2018-08-02, 201.51
2018-08-03, 202.09
2018-08-06, 203.14
2018-08-07, 201.24
2018-08-08, 201.37
2018-08-09, 202.96
2018-08-10, 202.35
2018-08-13, 203.66
2018-08-14, 204.52
2018-08-15, 204.99
2018-08-16, 208.0
2018-08-17, 212.15
2018-08-20, 210.08
2018-08-21, 209.67
2018-08-22, 209.682018-08-23, 210.11
2018-08-24, 210.77
2018-08-27, 212.5
2018-08-28, 214.22
2018-08-29, 217.42
2018-08-30, 219.41
2018-08-31, 221.952018-09-04, 222.66
2018-09-05, 221.21
2018-09-06, 217.53
2018-09-07, 215.78
2018-09-10, 212.882018-09-11, 218.26
2018-09-12, 215.55
2018-09-13, 220.76
2018-09-14, 218.25
2018-09-17, 212.44
2018-09-18, 212.79
2018-09-19, 212.92
2018-09-20, 214.542018-09-21, 212.23
2018-09-24, 215.28
2018-09-25, 216.65
2018-09-26, 214.92
2018-09-27, 219.34
2018-09-28, 220.112018-10-01, 221.59
2018-10-02, 223.56
2018-10-03, 226.282018-10-04, 222.3
2018-10-05, 218.69
2018-10-08, 218.19
2018-10-09, 221.212018-10-10, 210.96
2018-10-11, 209.1
2018-10-12, 216.57
2018-10-15, 211.94
2018-10-16, 216.612018-10-17, 215.67
2018-10-18, 210.63
2018-10-19, 213.84
2018-10-22, 215.14
2018-10-23, 217.172018-10-24, 209.72
2018-10-25, 214.31
2018-10-26, 210.9
2018-10-29, 206.94
2018-10-30, 207.98
2018-10-31, 213.42018-11-01, 216.67
2018-11-02, 202.3
2018-11-02, BUY CREATE, 202.30
2018-11-05, 196.56
2018-11-05, BUY CREATE, 196.562018-11-06, 198.68
2018-11-06, BUY CREATE, 198.68
2018-11-07, 204.71
2018-11-08, 204.02018-11-09, 200.06
2018-11-12, 189.99
2018-11-12, BUY CREATE, 189.99
2018-11-13, 188.09
2018-11-13, BUY CREATE, 188.092018-11-14, 182.77
2018-11-14, BUY CREATE, 182.77
2018-11-15, 187.28
2018-11-16, 189.362018-11-19, 181.85
2018-11-20, 173.17
2018-11-20, BUY CREATE, 173.17
2018-11-21, 172.972018-11-23, 168.58
2018-11-26, 170.86
2018-11-27, 170.48
2018-11-28, 177.042018-11-29, 175.68
2018-11-30, 174.73
2018-12-03, 180.84
2018-12-04, 172.88
2018-12-06, 170.952018-12-07, 164.86
2018-12-10, 165.94
2018-12-11, 165.0
2018-12-12, 165.46
2018-12-13, 167.27
2018-12-14, 161.91
2018-12-17, 160.41
2018-12-18, 162.49
2018-12-19, 157.42
2018-12-20, 153.45
2018-12-20, BUY CREATE, 153.45
2018-12-21, 147.48
2018-12-21, BUY CREATE, 147.48
2018-12-24, 143.67
2018-12-24, BUY CREATE, 143.67
2018-12-26, 153.78
2018-12-27, 152.78
2018-12-28, 152.86
2018-12-31, 154.34
Final Portfolio Value: 100381.48
Return: OrderedDict([('rtot', 0.0038075421029081335), ('ravg', 1.5169490449833201e-05), ('rnorm', 0.003830027474518453), ('rnorm100', 0.3830027474518453)])
Sharpe Ratio: OrderedDict([('sharperatio', None)])
System Quality Number: AutoOrderedDict([('sqn', 345.9089929588268), ('trades', 2)])
实时实施
这与其说是一部分,不如说是我用来实施交易策略的资源的集合。如果你想向前迈进,并在现实市场中实施你的策略,看看这些文章…
算法交易策略陷阱
- 不了解策略中盈利的驱动因素:有些人认为,不管财务或经济驱动因素如何,如果你能获得足够的数据,并以这样的方式激发数据,你就能制定出盈利的交易策略。我年轻的时候也是这样,对算法交易比较陌生,也比较幼稚。事实是,如果你不能理解你自己的交易算法的本质,它永远不会盈利。
- 不了解如何分割历史数据或合成数据来搜索和优化策略:这是一个大问题,后果是可怕的。我在大学的一个同事告诉我,他开发了一个有 300%回报的交易系统。很自然地,我马上就知道他完全把一个模型过度拟合到了历史数据上,并且从来没有在实际数据中实现过。问了一个关于他优化过程的简单问题,证实了我的怀疑。
- 不愿意接受下跌日:这个很有意思,对新手的影响似乎比经验丰富的交易者更大。老兵们知道会有低潮,会有损失,但是最重要的目标是赢的比输的多。这个问题通常出现在部署中——假设其他流程
- 不愿意让以前盈利的系统退役:损失控制,请了解风险管理和损失控制。你的系统是成功的,这太棒了——这意味着你理解了设计过程,并且可以再做一次。不要纠结于它做得有多好看看它做得有多好。这与理解您战略中的盈利驱动因素有所重叠——如果您理解了系统不再盈利的原因,您就会知道何时以及为何该淘汰系统。
因果推断估计的快速比较
有许多方法来估计因果效应的大小,这里我们使用一个最小复杂因果结构来检查这些估计是否一致。

来源: Fascinadora 通过 shutterstock (SL)
1。简介
作为一名实验行为科学家,我一直认为理解统计关系的因果方向性是实证科学的核心。我接受过经典实验设计的培训,在这种设计中,研究人员被认为对环境有完全的控制权,他们主要担心的是如何在时间或空间上定位不同的实验条件(例如拉丁方设计)。然而,一旦你离开受控实验室实验的安全性,推断因果关系就成了一个大问题,很容易危及你结论的内在有效性。幸运的是,在过去的几十年里,统计因果关系的研究在理论和方法上都取得了巨大的进步,现在因果推断正在成为数据科学家工具箱中一个相当常见的工具。为了跟上当前的方法,我做了一个快速回顾,我对过多的估计因果效应的方法感到有些惊讶。在这个项目中,我将列出我在文献中发现的最常见的方法,将它们应用于一个简化的因果问题,并比较观察到的估计值。这种比较旨在作为一个简要的高层次概述,而不是作为因果推理的教程。关于这个主题的简要介绍,我推荐 Pearl 等人(2016 年),关于深入的报道,感兴趣的读者可以查看 Pearl (2009 年)、Morgan 和 Winship (2015 年)或 Jason Roy 教授的在线课程(Roy,2020 年)。
2。因果模型示例
当使用统计方法推断因果关系时,通常我们感兴趣的是原因 X 对结果 y 的影响程度。当我们只观察这些变量时,或者如果随机化存在挑战(例如选择偏差),我们通常需要考虑更广泛的变量集。在图 1 中,我给出了一个假设例子的因果图。这个例子包括三种主要类型的附加变量,帮助我们得到一个无偏的估计:后门,前门和工具变量。

图一。在存在其他变量的情况下,原因 X 影响结果 Y 的假设性图形因果模型。如果我们测量这三个集合中的任何一个,就可以估计 X 对 Y 的因果影响:{X,Y,BD}、{X,Y,IV}或{X,Y,FD}
假设 X 是一个二元变量,表示至少每周锻炼的效果(如果锻炼,X = 1;否则 x = 0 是连续测量的预期寿命。X 对 Y 的影响完全由变量 FD ( 前门标准)调节,在我们的例子中,该变量可以是体重指数。此外,Y 和 X 都受到变量 BD ( 后门标准 ) 的影响,在我们的情况下,这可能是一些遗传因素,它们不直接影响 FD。最后,X 还受到 IV ( 工具变量)的影响,在我们的示例中,它可能是靠*体育设施。
我们可以用以下模型实例化这个因果图:
IV = U
BD = U
X = { 0,if IV — BD + U <= 0
1, if IV — BD + U > 0}
FD = X + U
Y = 65 + FD + BD + U
模型 1:实例化图 1 中图形模型的结构因果模型。U 分量是均值为 0 且 SD = 2 的正态分布误差项(或来自外部变量的输入)。
出于当前模拟的目的,我从模型 1 中随机生成了 10,000 个实例,在下一部分中,我将使用不同的统计方法来估计 X 对 Y 的因果影响。
以下是相关代码:
generate_df <- function(n = 1000, path_weights) {
#generate data frame from path_weights
a <- path_weights
sd_noise = 2
iv <- rnorm(n, sd = sd_noise)
bd <- rnorm(n, sd = sd_noise)
x <- rnorm(n) + a[1]*iv + a[2]*bd
x <- ifelse(x<=median(x), 0, 1)
lm(x~iv + bd) %>% summary
fd <- (rnorm(n, sd = sd_noise) + a[3]*x )
lm(fd ~ x) %>% summary()
y <- (65 + rnorm(n, sd = sd_noise) + a[4]*fd + a[5]*bd )
lm(y ~ fd + bd) %>% summary()
id <- rnorm(n)
df <- data.frame(
id = id, x = x, y = y, iv = iv, fd = fd, bd = bd)
return(df)
}
path_weights <- c(1,-1,1,1,1)
df <- generate_df(n = 10000, path_weights)
3。简单估计(观察 X 和 Y)
X 对 Y 的因果效应的简单估计可以简单地从 X 预测 Y 的回归系数中获得。在这个例子中,因果效应是 b_naive = -0.97,令人惊讶地表明运动缩短了预期寿命*一年。
naive_fit <- lm(y~x, data = df)
summary(naive_fit)
当研究人员确信没有需要考虑的 BD 变量时(例如,当 X 被随机分配或好像被随机分配时),简单估计是有用的。然而,对于大多数观察性研究和准实验性设计来说,天真的估计通常不是很有用。
4。后门变量调节(观察 X、Y 和 BD)
如果除了 X 和 Y 之外,您还可以测量 BD,那么您可以计算 X 对 Y 的因果影响的无偏估计,从而避免天真估计存在的问题。这里 BD 只是一个变量,但是它也可以是一组满足后门标准的变量。在回顾文献时,我发现了以下五种方法来估计因果关系,同时调整后门变量:
4.1 协变量
估计 X 对 Y 的因果影响的一种方法是运行回归模型,从 X 预测 Y,并将 BD 作为协变量。对于大多数受过线性回归训练但没有因果推理训练的研究人员来说,这通常是最直观的方法。
covariates_fit <- lm(y~x+bd, data = df)
summary(covariates_fit)
将这种方法应用于我们模拟的数据,我们发现 X 对 Y 的因果效应是 b _ 协变量= 1.01。根据这一分析,如果你锻炼,你会多活一年。请注意,这个估计不仅不同于天真的估计,两个估计实际上具有相反的符号,并导致相互矛盾的结论(查看辛普森悖论
4.2 直接匹配
上述协变量调整也可以通过直接匹配治疗组和对照组参与者的 BD 分数来完成。主要思想是,匹配程序将通过仅比较在 BD 分数上已经相似的对照组和治疗组受试者来消除 BD 对因果估计的影响:
greedymatch <- Matching::Match(Tr = df$x, M = 1, X = df[,”bd”])
matched <- df[unlist(greedymatch[c(“index.treated”, “index.control”)]),]
t.test(matched$y[matched$x == 1],matched$y[matched$x == 0], paired = TRUE)
当使用这种方法时,我们得到 b_direct_match = 1.05,这与我们使用协变量方法时观察到的结果非常接*。
4.3 倾向评分匹配
如果你需要考虑多个 BD 变量,找到好的匹配可能会非常困难(查看维数灾难)。取而代之的是,你可以使用倾向分数匹配,在这里你首先计算在治疗组中的概率(也称为倾向分数,查看这篇论文或者这篇博客文章),然后根据这些概率匹配参与者。
ps_fit <- glm(x~bd, data = df, family = “binomial”)
df$ps_score <- ps_fit$fitted.values
logit <- stats::qlogis # rename the function for clarity
greedymatch <- Match(Tr = df$x, M = 1, X = logit(df[,”ps_score”]), caliper = .2)
matched <- df[unlist(greedymatch[c(“index.treated”, “index.control”)]),]
t.test(matched$y[matched$x == 1],matched$y[matched$x == 0], paired = TRUE)
因果效应估计为 b_ps_match = 1.05,这实际上与前面的调整方法相同。
4.4 治疗权重的逆概率
您也可以使用加权回归,其中权重基于治疗的概率。具有高倾向分数的对照参与者和具有低倾向分数的治疗参与者接收更高的权重,调整由于 BD 变量引起的治疗/对照失衡。
df$weight <- ifelse(df$x == 1, 1/df$ps_score, 1/(1-df$ps_score))
iptw_fit <- lm(y ~ x, data = df, weights = weight)
summary(iptw_fit)
模拟数据的估计值为 b_iptw = 0.92,非常接*之前的估计值。
4.5 双重稳健估计
这是一种更先进的方法,为模型的错误设定提供了更多的空间。为了获得因果效应的无偏估计,正确指定倾向评分模型或结果回归模型就足够了。
dr_fit <- drgee::drgee(oformula=y~bd,
eformula=x~bd,
iaformula=~bd, olink=”identity”, elink=”identity”,
estimation.method=”dr”,
data=df)
summary(dr_fit)
因果效应是 b _ doubly _ robust = 1.01,也非常类似于之前的其他调整方法。
5。工具变量(观察 X、Y 和 IV)
如果你知道 BD 存在,但是你无法测量它,怎么办?如果您可以测量变量 IV,您仍然可以估计 X 对 Y 的因果影响。这种方法称为工具变量法,其中工具 IV 对 Y 的影响以 X 为中介,可用于估计 X 对 Y 的影响。运行这种分析的常用方法称为两阶段回归,其中第一阶段我们在工具 IV 上回归 X,第二阶段我们在第一阶段的残差上回归结果 Y。
stage1_fit <- stats::lm(x~iv, data = df)
df$stage1_predict <- predict(stage1_fit, type = “response”)
stage2_fit <- stats::lm(y~stage1_predict, data = df)
summary(stage2_fit)
在我们的例子中,工具变量法估计 X 对 Y 的因果影响为 b_iv = 0.96,非常接*于 BD 调整法。
6。前门调节(观察 X、Y 和 FD)
即使我们既不能测量 IV 也不能测量 BD,仍然有可能计算出 X 对 y 的因果影响的无偏估计。前门调整允许我们通过测量 X 对 FD 和 FD 对 y 的影响来实现这一点。
x_fd_fit <- lm(fd~x, data = df)
fd_y_fit <- lm(y~fd + x, data = df) # here x is included to block back-door effects
x_fd_fit$coefficients[2]*fd_y_fit$coefficients[2]
使用前门调整,我们估计 X 对 Y 的因果效应为 b_fd = 1.03。
7。跨方法协议
虽然我理解为什么有些方法应该返回相等或非常接*的估计值,但我仍然发现 X 和 Y 的因果关系可以用如此多的方法来估计,这既令人吃惊又有点令人困惑。为了检查不同方法的一致性,我基于图 1 中的因果图运行了一系列模拟。我使用了与模型 1 中概述的相同类型的关系,但对于每个模拟,我随机分配了一个随机回归系数,绝对值范围从 0.3 到 3。作为参考,对于较弱的关系(系数设置为 0.3),FD 和 BD 一起解释了 Y 中 8%的方差,而较强的关系(系数设置为 3)解释了 68%的方差(基于 R)。

图二。这里讨论的八种因果推断方法的因果效应估计值之间的相关性。
我运行了 2000 次模拟,每次有 2000 行。对于每个模拟,我用上面列出的方法计算了 X 对 Y 的因果影响的八个不同的估计。图 2 描述了不同方法之间的一致性。如图所示,这两种方法基本一致,皮尔逊相关系数远高于 0.9。天真估计也与其他方法正相关,但它经常低估或高估真正的因果关系。
8。警告和进一步观察
当前项目的目标是为估计因果影响的主要方法提供一个快速的总体示例,并证明这些方法在结果上基本一致。然而,这个例子非常简短,忽略了许多重要的细节,其中一些我需要明确提到:
- 在这里,我把因果关系作为一个单一的概念,然而有不同类型的因果关系。例如,工具变量估计局部*均治疗效果,而这里应用的其他方法估计(边际)*均治疗效果。这两种影响不一定相等。
- 虽然图 1 中的因果图和随后的模型是基于各种理论原则和假设,但我只提供了外部参考,在此不做讨论。
- 这里的不同方法在估计上基本一致,但这部分是由于我用来生成数据的简单模型。例如,我没有包括异质性治疗效果,不*衡组或偏斜分布,所有这些都会降低方法间的一致性。
- 匹配方法对所使用的特定算法以及 X 和 BD 之间的关系强度很敏感。
- 在试验因果关系的数量时,我注意到较弱的因果关系与方法间的一致性的显著下降有关。工具变量估计值尤其受到弱统计关系的影响(check Bound,Jaeger 和 Baker,1995 年)
9。结论
我发现赶上因果推理领域既具有挑战性又令人兴奋。对于一个新手来说,这个领域可能看起来支离破碎,不一致,并且经常专注于抽象的理论而不是应用。然而,除了这些最初的印象,令人着迷的是发现理论和方法逐渐趋同,并为研究人员提供了过多的创造性工具来寻找因果关系。将这些工具中最常见的放在一起,帮助我看到了理论和方法的融合,我希望它可能对其他研究人员和数据科学家有所帮助。
参考文献
奥斯汀市(2011 年)。减少观察性研究中混杂效应的倾向评分方法介绍。多元行为研究,46(3),399–424。
Bellemare,M. F .,& Bloem,J. R. (2019)。如何使用前门标准评估治疗效果?
邦德、杰格、D. A .、贝克、R. M. (1995 年)。当工具和内生解释变量之间的相关性较弱时,工具变量估计的问题。美国统计协会杂志,90(430),443–450。
邦德、杰格、D. A .、贝克、R. M. (1995 年)。当工具和内生解释变量之间的相关性较弱时,工具变量估计的问题。美国统计协会杂志,90(430),443–450。
摩根公司和温希普公司(2015 年)。反事实和因果推断。剑桥大学出版社。
珀尔,J. (1993 年)。专家系统中的贝叶斯分析:评论:图形模型,因果关系和干预。统计科学,8(3),266–269。
j .珀尔(2009 年)。因果关系。剑桥大学出版社。
j .珀尔、m .格里穆尔和 N. P .朱厄尔(2016 年)。统计学中的因果推断:初级读本。约翰·威利的儿子们。
《因果关系速成班:从观察数据推断因果关系》。coursera.org,网址:https://www.coursera.org/learn/crash-course-in-causality
一个快速的深度学习方法:用 Python 中的 Keras 进行时间序列预测
在本教程中,我们将讨论/比较三个不同的人工神经网络(DNN、RNN 和 LTSM)在同一个单变量数据集上的表现——一家电子商务公司的广告日常支出。
目录
- 简介
- 时间序列分析
- 为什么选择深度学习
- 进行深度学习的过程
2.车型
- DNNs
- RNNs
- LSTM
3.对比车型
4.期末总结
1.1 时间序列分析
详细说明在我以前的帖子这里。
1.2 为什么选择深度学习
我们知道统计模型可以预测时间序列。但是,这些方法有一些限制:
- 需要完成数据进行培训。某些缺失值会导致模型的性能非常差。尽管有一些方法可以处理丢失的值,但是很难做到
- 通常,处理单变量数据集,应用于多变量数据集具有挑战性
- 对缺失值敏感
深度学习方法能够应对上述挑战:
- 对缺失值不敏感
- 合并外生变量的容易程度(适用于单变量数据集和多变量数据集 )
- 捕捉非线性特征交互
- 自动特征提取
我将简要解释神经网络方法的关键组件/概念,并展示如何用 python 代码中的 Keras 一步一步地应用神经网络。对于每个模型,我将遵循 5 个步骤来展示如何使用 Keras 建立一个预测时间序列的基本网络。
- 预处理
- 定义神经网络形状和模型编译
- 拟合模型
- 估价
- 可视化预测
现在,让我们编码吧!
首先,快速浏览一下数据集:2017 年 1 月 1 日至 2019 年 9 月 23 日的广告日支出包括 996 天。数据集的前五行:

数据帧的前五行
绘制滚动*均值以可视化趋势/季节性,并运行 Dickey-Fuller 测试以检查数据集的*稳性,与我们在之前的教程第一部分和第二部分中所做的一样。

模式 1: DNN
一个深度神经网络(【DNN】)是一个 人工神经网络 ( 安 )在输入层 和输出层—来自维基
如何对时间序列数据应用 DNN?这里的关键思想是:我们把时间序列看作线性模型:{X(i) …X(i+t)}~Y(i+t+1)。在该格式中,显示了使用 t 步输入时间序列来预测下一步 Y(i+t+1)。

带有一个隐藏层的简单 DNN
在图中,我显示了一个隐藏层的 DNN 结构。接下来,让我们看看如何在我们的广告支出数据上实现这个模型。
第一步:数据预处理
导入 convert2matrix 的辅助函数来修整数据集,以便创建 DNN 的二维输入形状。一个完全连接的网络——RNN 和 LTSM 的主要区别
将数据集分为测试数据集和训练数据集。
第二步:定义神经网络形状并编译模型
我建立了一个非常简单的 DNN,只有一个隐藏层。
第三步:拟合模型
model=model_dnn(回看)
history=model.fit(trainX,trainY,epochs=100,batch_size=30,verbose=1,validation_data=(testX,testY),callbacks =[early stopping(monitor = ' val _ loss ',patience=10)],shuffle=False)
第四步:模型评估
打印出误差指标并生成模型损耗图。

从上面的图表中,很明显我们过度拟合了我们的模型,因为模型在 40 个时期后几乎没有做任何事情。
步骤五。可视化预测
通过调用以下命令检查预测图:
预测 _ 绘图(测试,测试 _ 预测)

从图上看,尽管它错过了一些波峰和波谷,但它能够捕捉总体趋势和季节性,而无需任何参数调整或归一化预处理。
模式 2: RNN
RNN(递归神经网络)处理的序列不同于之前显示的全连接 DNN。
这里的关键思想:时序数据集是序列。

有两个隐藏层的 RNN
我们将在下面的案例研究中看到这个 RNN 形状。
第一步:数据预处理
RNN 输入形状:(批量大小,窗口大小,输入特征)
导入助手函数以创建矩阵
第二步:定义神经网络形状并编译模型
建立了一个有两个隐藏层的 RNN 模型。
第三步:拟合模型
模型=模型 _rnn(回望)
history=model.fit(trainX,trainY,epochs=100,batch_size=30,verbose=1,validation_data=(testX,testY),callbacks =[early stopping(monitor = ' val _ loss ',patience=10)],shuffle=False)
第四步:模型评估
打印出误差指标并生成模型损耗图。
产量低于

从上面的图表中,很明显我们过度拟合了我们的模型,因为模型在 20 个时期后几乎没有做任何事情。
第五步。可视化预测

一般来说,预测看起来不错,测试误差较小。尽管它错过了一些高峰和低谷,但它能够捕捉总体趋势和季节性。
模式 3:LSTM——RNN 家庭的一员
LSTM(长短期记忆),由四个主要部件构成:输入门、输出门、存储单元和遗忘门
- 输入门:控制向单元格状态添加信息。换句话说,输入门将考虑哪些信息应该添加到单元状态,以确保添加重要信息而不是冗余信息或噪声。
- 内存 单元格 : (1)控制可以删除或刷新的值(2)包含可能需要保存的值,作为许多其他时间步骤的附加信息。
- 输出门:控制从当前单元状态中选择有用的学习信息作为输出。
- 遗忘门:控制从细胞状态中删除 LTSM 学习不再需要或不太重要的信息。这有助于优化 LSTM 网络的性能。

我修改了 https://en.wikipedia.org/wiki/Long_short-term_memory 的原始图片
第一步:数据预处理:
LSTMs 对输入数据的规模很敏感。在预处理步骤中,我应用了 scikit-learn 模块中的 MinMaxScaler 预处理类来标准化/重定数据集。
导入助手函数以创建矩阵
将数据集的范围重新调整为 0–1。
将数据集分为训练数据集和测试数据集。为 LSTM 创建输入三维输入形状。
第二步:定义神经网络形状并编译模型
这里,一个非常简单的两层 LTSM 没有隐藏层
第三步:拟合模型
model=model_lstm(回望)
history = model.fit(trainX,trainY,epochs=100,batch_size=30,validation_data=(testX,testY),callbacks =[early stopping(monitor = ' val _ loss ',patience=10)],verbose=1,shuffle=False)
这里有一个小提示:通常,当 LSTM 表现出过度适应时,尝试 GRU(门控循环单元)是 LSTM 的“简化版”。
第四步:模型评估
打印出误差指标并生成模型损耗图。

从上面的图表中,很明显我们过度拟合了我们的模型,因为模型在 20 个时期后几乎没有做任何事情。
通过在本文中比较不同模型的误差度量,我们得到了更好的结果(LSTM 显示了更小的误差度量)。迄今为止,LSTM 的表现优于其他两款车型。我们预测大约 2 个月(具体来说是 65 天),MAE 等于 3744。换句话说,2 个月的预测广告支出将比实际支出少大约 3744 美元。*均每月花费 250 万美元以上。这是一个非常好的预测!此外,这是对我另一篇文章中的统计模型结果的一大改进。
第五步。可视化预测

尽管它不能完美地捕捉所有的波峰和波谷,但在这个用例中,它确实比 DNN 或 RNN 模型做了更好的预测。
总结
到目前为止,我展示了在这个用例中使用深度学习来预测单变量时间序列数据。实际上,深度学习可以做得更多!我们可以通过添加其他特征(如星期几、节假日、经济影响等)将单变量时间序列数据转换为多变量时间序列,这对于应用于传统的统计模型来说是一个挑战。
除了为输入数据添加更多特征之外,还可以考虑其他过程来改进神经网络。
- 增加嵌入输出大小
- 添加批量标准化图层
- 尝试不同的学习率,激活功能,其他超参数
- 稍后添加辍学
- 尝试其他模式,如 GRU 或切换到有线电视新闻网
- 等等。
参考资料:
计算机视觉在我们的社会中已经变得无处不在,在搜索、图像理解、应用程序、地图绘制…
cs231n.stanford.edu](http://cs231n.stanford.edu/) [## keras-team/keras
mnist_mlp.py 在 mnist 数据集上训练一个简单的深度多层感知器。py 在…上训练一个简单的 convnet
github.com](https://github.com/keras-team/keras/tree/master/examples)*
k 均值聚类
一个简单快捷的基本机器学习工具教程
作者安德鲁·科尔
数据至少是模糊的。它包含无限的信息宝藏,而解开这些信息需要同样模糊的方法。但是,和任何事情一样,必须有一个起点。分类是最有效的机器学习方法之一,它试图根据数据已有的特征将数据分类到特定的组中。然而,我们并不总是知道这些特征是什么,这就是问题所在。我们甚至不知道我们在数据集里看到了什么,我们只是呆呆地盯着它,而它也在看着我们。
幸运的是,有 ML 分类方法可以帮助解决这个模糊的问题。机器学习以两种状态存在:
- 监督学习:算法从已经包含标记数据的训练数据集中“学习”。训练数据集包含输入和输出数据,这是模型验证自身性能的方式。例如,我们有一个医院病人,我们知道他表现出症状 X、Y 和 Z,他们患有疾病 1。输入数据表示三种症状,而输出表示患者确实患有疾病 1。因为输入和输出是已知的,我们可以利用监督机器学习。
- 无监督学习:算法用未知的结果来推断数据中的模式。你不能真正地将数据归类到一个结果中,因为你甚至不知道结果的值可能是什么。例如,您有一家拥有 100,000 名客户及其购买历史的企业,您希望了解这些客户的人口统计分组,以便更好地调整您的业务模型。无监督学习方法在这里会更合适,因为它们将有效地将那些客户“分组”到仅基于可用数据的相似分组中。
K 均值聚类—模型
我们将深入探讨如何创建一个基本的无监督学习模型,以及如何评估其成功的教程。无监督学习有许多应用,但我们将特别关注其中一个:聚类。聚类实质上将分散所有的数据点,并根据它们的特征对它们进行分组。目标是进行分组,使得类内相似性高(聚类内的相似性),同时保持类间相似性低(聚类间的相似性)。
聚类的主要目标是将数据点分组在一起,而不知道这些数据点实际上是什么。
利用 k-均值聚类,我们确定有 k- 个聚类中心。通用算法流程如下:
1.数据将围绕整个数据集中预定数量的中心点进行分组。
2.每个单独的数据观测值将被分配到距离中心点“最*”的聚类(欧几里德距离)。
3.各个聚类中心点将被重新计算,因为它们周围都有它们的观测值
4.现在,根据一些“规则”,观察值被重新分配给其中一个集群(见下面的 Init )
5.这个过程是迭代的,所以如果观测点的重新分配可以实现更*的距离,它就会发生。如果没有,模型就完成了。
为了开始建模过程,我们导入必要的库并生成随机数据:



在这里,我们可以清楚地看到有 5 到 7 个清晰的数据点或数据簇。K-Means 算法现在将计算并试图找到“K”个聚类的中心点。我们将定义‘k’= 7。算法本身有些简单:

与任何机器学习模型一样,有大量的参数选项来帮助调整您的模型以适应您的数据(括号中的参数选项)。
- n_clusters: 这是你的“k”值。该参数告诉算法将数据分组到多少个聚类中,因此需要计算多少个中心点。没有确定的方法来预先确定准确的 k 数,因此模型的迭代是必要的,并且最佳执行结果度量(我们稍后将讨论)将告诉您哪个数用于您的最终模型。
- init: 这是你初始化函数的“规则”方法( k-means++: 默认;选择初始聚类中心以追求更快的收敛;随机:选择 k-随机观测值来选择初始中心; ndarray: 此参数允许您提供自己的初始中心点)
- 算法:指定聚类时使用的算法( full: “全期望最大化”);在每次迭代中,出现 E 步(将点分配到最*的中心点)和 M 步(根据聚类元素更新聚类均值);埃尔坎:效率更高;使用稀疏数据时不可用;自动:根据给定数据自动拾取满/elkan)

上述代码的结果如下图所示。7 个聚类中每个聚类正中心的黑点代表每个聚类的计算中心点。

K 均值聚类:评估指标
如前所述,聚类是一个迭代过程。没有很好的方法来预先确定我们应该在我们的模型中使用多少 k-clusters,因此我们必须运行多个模型,然后比较结果指标。sk-learn 库中可能有许多指标,但我们将重点关注两个:
- 方差比(Calinski-Harabasz 评分):这是一个聚类内的点的方差比。方差比率得分越高=模型性能越好。



- 剪影评分:评分越高=模特越好

— a = 一个数据样本与同一个聚类中所有其他点之间的*均距离
— b = 一个数据样本与下一个最*聚类中所有其他点之间的*均距离
值得注意的是,这两个指标都不一定比另一个“更好”。然而,重要的是,一旦你选择了一个评估指标,你就要坚持在所有模型中使用相同的指标。
剪影得分:k = 7

卡林斯基-哈拉巴斯评分(方差比):k = 7

现在我们有了 k=7 个集群的模型性能指标,我们将再次迭代模型,这次使用 k = 6。一旦新模型被拟合和预测,我们将比较指标。无论哪个更高,都将是性能更好的模型。代码如下:


当您比较两个生成的模型图时,我们无法真正区分两个中心,除了右上的浅紫色样本簇(x = -5,y = 0.0)这一事实。因此,我们必须比较评估指标,以确定哪个分数更好。让我们使用剪影分数作为我们的比较(同样,一旦你选择了一个指标,你必须在所有的模型迭代中使用它)。

结论
我们现在有两个指标进行比较。
- k = 7;轮廓得分= 0.70
- k = 6;轮廓得分= 0.68
k=7 的轮廓分数高于 k=6,因此 k=7 是性能最好的模型。
Python 中一种快速、简单的数据反透视方法
在熊猫中使用融化功能

让我们学习如何在熊猫身上融化数据(来源:Nik Piepenbreier)
在之前的一篇文章中,我们看了一下在 Python 中执行三个常见的 Excel 任务。今天我们来看看一个函数,虽然在 Excel 中是可能的,但它隐藏得很好,有点笨拙。我说的是 Excel 中的“非透视”数据。
为什么取消数据透视?

让我们让下载的数据更有用!资料来源:Nik Piepenbreier
Python 和 Excel 使得分析数据和以跨表格式呈现分析变得非常容易。但是如果您只接收那种格式的数据呢?为了进行更有意义的分析,通常需要花费大量时间来重新格式化数据。我们称这个过程为“非旋转”。
开始取消透视数据
让我们通过运行以下命令将数据集加载到 Pandas 数据帧中:
import pandas as pd
df = pd.read_excel('[https://github.com/datagy/mediumdata/raw/master/pythonexcel.xlsx](https://github.com/datagy/mediumdata/raw/master/unpivot.xlsx)')
如果你想探索 Excel 中的数据,你可以在这里下载文件。
我们可以通过编写以下代码打印出列名:
print(df.columns)
这将返回:
['Product', 'Quarter 1', 'Quarter 2', 'Quarter 3', 'Quarter 4']
本质上,我们希望将所有的季度放在一个列中(称为季度),并将销售额放在一个单独的列中。熊猫融化功能使这变得非常容易。我们可以简单地写:
df = df.melt(id_vars = 'Product', var_name = 'Quarter', value_name = 'Sales')
让我们稍微分解一下:
- id_vars :标识要用作标识符变量的列
- value_vars :要取消透视的列。如果为空(如这里的情况),则使用除了那些在 id_vars 中标识的列之外的所有列
- var_name :为取消透视的列指定一个名称
- 值名称:为值列指定一个名称
当我们现在打印出 df 时,我们看到它以如下方式返回:

我们融化的数据框。资料来源:Nik Piepenbreier
在 Excel 中取消数据透视

在 Excel 中取消数据透视。资料来源:Nik Piepenbreier
现在,假设我们想在好的、旧的 Excel 中做这件事。我们该怎么做呢?在 Excel 2016 之前,这需要下载 Power Query 插件。从该版本开始,附加组件的功能被内置到主版本中。让我们从打开数据集开始。从那里开始:
- 选择数据选项卡
- 选择表格后,在获取和转换数据中选择表格/范围
- 切换到变换菜单
- 选择要取消透视的列
- 单击取消透视列
- 在主页选项卡上选择关闭并加载
- 享受你的数据!
感谢阅读这篇文章!请务必查看我的其他帖子,包括轻松学会如何!!)用 Python 做 3 个高级 Excel 任务。
CARTO BigQuery Tiler 的快速实验!
从 BigQuery 和 CARTO BigQuery Tiler 的实践教程开始。
我和我的朋友、共同主持人、数据黑客同事朱莉 ( 推特),以及 CARTO 的帮助下创建的!
你好,世界!
最*,CARTO 推出了 BigQuery Tiler,我们有机会出席 2020 年空间数据科学大会,一睹 Tiler 的风采。
我们做了一个报告!
我们为这个演示创建了几个演示,我们想把它作为一个“你好,世界”的练习分享给 tiler!我们已经将数据和查询/代码加载到了一个 Github 库中,欢迎您尝试一下。当第一次构建这些组件时,我们发现了许多关于许多不同组件的有用信息,但试图将它们联系在一起并不总是直截了当的,因此这包括了我们在此过程中吸取的许多经验教训,并给出了从数据创建到可视化的完整端到端示例。
在运行演示之前,需要回顾一些要点。readme 文件中列出了它们,但这里也值得重申一下:
- 这是演示代码,旨在用于学习,而不是用于生产。它不是受支持的产品,因此随着时间的推移,情况可能会发生变化和损坏,我们将尽力修复它!
- 如果这是你第一次使用谷歌云,一定要开始你的免费试用并创建你的项目!
- 这使用了 Google BigQuery ,会产生成本。请务必通过定价页面了解您的项目将如何产生成本,如果这是您的第一个项目,请务必了解 Google Cloud 试用和免费等级。
- 这也使用 CARTO BigQuery Tiler。你需要成为测试版的一员。在这里找到关于这个的更多信息。
- 当然,你还需要一个卡通账户!
- 对于在 Google Cloud 和 BigQuery 的命令行中完成的任务,您可以利用预先安装了命令行工具的云外壳,或者您可以将 Google Cloud SDK 安装到您的本地(或虚拟)机器上。
- 在命令行中,确保通过运行
gcloud auth login来设置您的用户,并运行gcloud init来设置您的默认项目。
加载数据
阅读完这些信息并设置好项目后,就可以加载数据集了。有两个数据集要加载; NIFS 火灾周界数据和来自 OpenAQ 的数据。继续克隆/下载 Github 库,并按照readme 中的步骤加载数据。完成后,BigQuery 中应该有下面的表:
geo.geo_dataset_nifs_perimetersgeo.geo_dataset_openaq_demogeo.geo_dataset_osm_planet_features_buildingsgeo.tileset_openaq_wildfiregeo.tileset_osm_planet_features_buildings
可视化 OpenStreetMaps (OSM)数据
当加载地理数据集时,您可以直接在 BigQuery 界面中预览它们(T4 ),看看它们是什么样子。一旦你创建了一个 tileset,你也可以预览它们,但因为它是原始的 tileset 数据,它可能不会有太大的意义。您可以使用 QGIS、deck.gl 和 Carto 的在线查看器等工具来可视化切片集。Carto Online Viewer 是一个基于 web 的 tilesets 可视化工具,可以让您快速查看数据的外观。当加入测试版时,它的文档会让你知道如何设置在线查看器,使用本教程中创建的 OSM tileset 就是一个很好的例子。如果您已经加入了测试版,并且可以访问它,那么现在是使用geo.geo_dataset_osm_planet_features_buildings表进行尝试的好时机。

CARTO Online Viewer 中的 OSM tileset 将如下所示。(图片由作者提供)
可视化 NIFS 和 OpenAQ 数据
为了制作演示中使用的第二个示例,我们使用 deck.gl 在网页中创建可视化效果。我们还使用了 codepen.io 来测试和显示网页和可视化效果,但是您也可以将代码粘贴到 Github Gist 中,并使用bl.ocks.org来呈现它,或者如果您有自己喜欢的编辑和服务工作流,请使用它!
为了显示 NIFS 野火多边形,我们使用了cartossqllayer下拉数据并将其可视化。这意味着您还必须在 CARTO 中创建一个数据集才能使用它。在 CARTO 仪表板中,转到数据页面,创建一个新的 BigQuery 数据源,并使用您用来访问 Google Cloud 的帐户进行身份验证。在向导中,在 BigQuery 中选择存储您的geo数据集的项目,将输出命名为geo_dataset_nifs_perimeters,并使用以下查询:
SELECT geom, IncidentNa as INCIDENT_NAME, GISAcres as ACRES FROM `geo.geo_dataset_nifs_perimeters`

BigQuery 数据的 CARTO 向导。(图片由作者提供)
选择不同步下一页中的数据(这只是静态数据的一次性提取,因此不需要同步),并将数据导入!这将为您提供一个来自 BigQuery 的 CARTO 新数据集,您可以使用它。

闪亮的新数据!(图片由作者提供)
该数据集现在可用于查询。包含源代码的 HTML 页面在[/2_fire_perimeters/index.html](https://github.com/slagathorr/sdsc20-bqtiler-demo/tree/main/2_fire_perimeters)的 Github 资源库中,需要做一些改动。
首先是 API 键。确保获得您的 CARTO API 密钥,授予其访问geo_nifs_perimeters数据集的权限,并使用这些凭证来填充 index.html 文件中第 259 和 260 行的变量。
您还需要获得一个 Google Maps API 密钥,因为我们将它用作可视化中的底图。按照指令获取您的 API 密钥,然后将其插入到第 9 行的 API 调用中。
最后,您需要为 BigQuery 中的 tilesets 添加数据访问。为此,我们使用了多视图层。在第 268 行中,用 tileset 的 URL 模板替换url占位符。在 BigQuery Tiler 文档的“使用 QGIS”一节中,有一节介绍了如何获取生成模板的 URL。您将得到一个包含大量信息的 JSON 响应,但是所需的 URL 将是第一个对象,看起来像这样:

原谅我的涂鸦。(图片由作者提供)
用生成的新 URL 替换urls,您应该可以开始了!您将获得一个可视化效果,显示任何给定野火质心 100 公里范围内的 OpenAQ 中的测量点,并与野火本身的多边形分层。

空气测量点和地图上的野火多边形。(图片由作者提供)
应该就是这样了!希望您能够浏览所有这些内容,作为 CARTO BigQuery Tiler 的介绍,以及可视化这些数据集的一些选项,这很有帮助。如果您遇到任何问题,请务必让我们知道。如果您有任何希望分享该功能帮助的使用案例,我们也很乐意听到!请务必在这里或在 Twitter ( @brian_suk 和 @juliepricetech )上发表评论,为我们呐喊!谢谢,祝映射愉快!
深度学习中激活函数的快速指南
深度学习中所有主要激活功能的快速讨论。

作者图片
在这篇文章中,我将给出一个在神经网络中使用的一些最常见的激活函数的快速概述。但在讨论它们之前,让我们先讨论一些与激活函数相关的基本概念。
内容-
- 为什么我们需要激活函数?
- 为什么我们总是在神经网络中选择非线性激活函数?
- 通用逼*定理
- 消失和爆炸梯度问题
- 激活功能-
- Sigmoid 函数
- Softmax 函数
- 双曲正切值
- 热卢
- 泄漏 Relu
- 嗖嗖
- 参数化 Relu
- ELU
- Softplus 和 Softsign
- 卢瑟
- 格鲁
- 线性激活函数
6.如何决定应该使用哪个激活函数?
7.结论
8.信用
为什么我们需要激活函数?
正如我们所知,在人工神经元中,输入和权重是给定的,由此计算出输入的加权和,然后将其提供给激活函数,该函数将其转换为输出。所以基本上激活函数被用来将输入映射到输出。这种激活功能有助于神经网络学习数据中的复杂关系和模式。现在的问题是,如果我们不使用任何激活函数,让一个神经元给出输入的加权和作为输出,会怎么样。在这种情况下,计算将非常困难,因为输入的加权和没有任何范围,根据输入,它可以取任何值。因此,激活功能的一个重要用途是将输出限制在特定范围内。激活函数的另一个用途是在数据中添加非线性。我们总是选择非线性函数作为激活函数。让我们看看,为什么它很重要。
为什么我们总是在神经网络中选择非线性激活函数?
非线性意味着不能从输入的线性组合中产生输出。非线性在神经网络中很重要,因为线性激活函数不足以形成通用函数逼*器。如果我们在深度神经网络中使用线性激活函数,无论我们的网络有多深,它都将等同于没有隐藏层的线性神经网络,因为这些线性激活函数可以组合起来形成另一个单一的线性函数。因此,基本上我们的整个网络将被简化为一个单一的神经元,以组合的线性函数作为其激活函数,而这个单一的神经元将无法学习数据中的复杂关系。由于大多数现实世界的问题非常复杂,我们需要神经网络中的非线性激活函数。没有非线性激活函数的神经网络将只是一个简单的线性回归模型。
然而,在神经网络的最后一层,我们可以选择线性激活函数。
通用逼*定理
直接引用维基百科-
普适逼*定理指出,由人工神经元构成的前馈网络可以很好地逼* Rⁿ.紧集上的任意实值连续函数
简而言之,这个定理表明神经网络可以学习任何连续函数。现在的问题是是什么让它这样做。答案是激活函数的非线性。
消失和爆炸梯度问题-
在反向传播期间的神经网络中,每个权重接收与误差函数的偏导数成比例的更新。在某些情况下,这个衍生项非常小,以至于更新非常小。特别是在神经网络的深层,通过各种偏导数的相乘来获得更新。如果这些偏导数非常小,那么总的更新变得非常小,接*于零。在这种情况下,权重将不能更新,因此将有缓慢或没有收敛。这个问题被称为消失梯度问题。
类似地,如果导数项非常大,那么更新也将非常大。在这种情况下,算法将超过最小值,并且不能收敛。这个问题被称为爆炸梯度问题。
有各种方法可以避免这些问题。选择合适的激活函数就是其中之一
激活功能-
1.Sigmoid 函数-
Sigmoid 是一个“S”形数学函数,其公式为-

来源:维基百科
这是 sigmoid 函数的图表。你一定在学习逻辑回归的时候遇到过这个函数。尽管 sigmoid 函数非常受欢迎,但由于以下原因,它并不常用

乙状结肠函数(来源:维基百科)
优点-
- Sigmoid 函数是连续且可微的。
- 它将输出限制在 0 和 1 之间
- 非常明确的二进制分类预测。
缺点是
- 它会导致渐变消失的问题。
- 它不是以零为中心。
- 计算成本高
示例-

作者图片
2.Softmax 函数-
Softmax 函数是 sigmoid 函数对多类设置的推广。它通常用于多类分类的最后一层。它取一个“k”实数的向量,然后将其归一化为一个概率分布,该概率分布由对应于输入数的指数的“k”个概率组成。在应用 softmax 之前,一些向量分量可能是负的,或者大于 1,并且可能不等于 1,但是在应用 softmax 之后,每个分量将在 0-1 的范围内,并且将等于 1,因此它们可以被解释为概率。

来源:维基百科
优点-
它可用于多类分类,因此可用于神经网络的输出层。
缺点是
这在计算上是昂贵的,因为我们必须计算大量的指数项。
示例-

作者图片
3.双曲正切值
双曲正切或简称为“tanh”由以下各项表示

作者图片

作者图片
它非常类似于 sigmoid 函数。它以零为中心,范围在-1 和+1 之间。

来源:维基百科
优点-
- 它在任何地方都是连续且可微的。
- 它以零为中心。
- 它会将输出限制在-1 到+1 的范围内。
缺点是
- 它会导致渐变消失的问题。
- 计算开销很大。
示例-

作者图片
4.Relu-
整流线性单元通常称为整流器或 relu

作者图片

图像来源
优点-
- 容易计算。
- 不会导致渐变消失的问题
- 由于不是所有的神经元都被激活,这造成了网络的稀疏性,因此它将是快速而有效的。
缺点是
- 导致爆炸梯度问题。
- 不在零中心。
- 可以永远杀死一些神经元,因为它总是给负值 0。
示例-

作者图片
为了克服 relu 激活中的爆炸梯度问题,我们可以设置它的饱和阈值,即函数将返回的最大值。

作者图片

图片来源
5.泄漏的 Relu-
漏 relu 是 relu 函数的改进。Relu 函数在每次迭代中会杀死一些神经元,这就是所谓的死亡 relu 条件。Leaky relu 可以克服这个问题,它不会给负值 0,而是使用相对较小的输入分量来计算输出,因此它永远不会杀死任何神经元。

来源:维基百科

图片来源
优点-
- 容易计算。
- 不会导致渐变消失的问题
- 不会导致将死的问题。
缺点是
- 导致爆炸梯度问题。
- 不在零中心
示例-

作者图片
6.参数化 Relu-
在参数化 relu 中,它不是为负轴固定一个速率,而是作为一个新的可训练参数传递,网络可以自行学习以实现更快的收敛。

来源:维基百科
优点-
- 网络将自己学习最合适的α值。
- 不会导致渐变消失的问题
缺点是
- 难以计算。
- 性能取决于问题。
在 Tensorflow 中,参数化 relu 被实现为自定义层。示例-

作者图片
7.嗖嗖-
swish 函数是通过 x 乘以 sigmoid 函数得到的。

来源:维基百科

图像来源
swish 功能是谷歌大脑团队提出的。他们的实验表明,在几个具有挑战性的数据集上,swish 往往比 Relu 的深度模型工作得更快。
优点-
- 不会导致渐变消失的问题。
- 被证明比 relu 略胜一筹。
缺点是
计算成本高
8.ELU-
指数线性单元(ELU)是 relu 的另一种变体,它试图使激活接*零,从而加快学习速度。它比 relu 具有更好的分类精度。elu 具有负值,使得激活的*均值更接*于零。

来源:维基百科
优点-
- 不会导致将死的问题。
缺点是
- 计算开销很大。
- 没有避免爆炸梯度问题。
- 阿尔法值需要决定。

作者图片
9.Softplus 和 Softsign
Softplus 功能是-

来源:维基百科
它的导数是一个 sigmoid 函数。
软设计功能是-

图像来源
Softplus 和 Softsign 用得不多,一般而言,relu 及其变体比它们更受欢迎。
优点-
- 不会导致渐变消失的问题。
缺点是
- 计算开销很大。
- 比 Relu 慢。
示例-

作者图片

作者图片
10.卢瑟-
卢瑟代表比例指数线性单位。卢瑟被定义为-

图片来源
其中 alpha 和 scale 是常量,其值分别为 1.673 和 1.050。选择 alpha 和 scale 的值,使得只要权重被正确初始化,输入的均值和方差在两个连续层之间保持不变。卢瑟被证明比 relu 更好,并具有以下优点。
优点-
- 不会导致渐变消失的问题。
- 不会导致死亡的问题
- 比其他激活功能更快更好。
示例-

作者图片
11.线性激活-
正如我们之前讨论的,我们应该在神经网络中使用非线性激活函数。然而,在用于回归问题的神经网络的最后一层,我们可以使用线性激活函数。
示例-

作者图片
如何决定应该使用哪个激活函数
- 由于消失梯度问题,应避免使用 Sigmoid 和 tanh。
- 还应避免使用 Softplus 和 Softsign,因为 Relu 是更好的选择。
- 对于隐藏层,应该首选 Relu。如果它导致了将死的 relu 问题,那么应该使用它的修改版本,如 leaky relu、elu、SELU 等。
- 对于深度网络,swish 比 relu 表现更好。
- 对于回归的最终图层,线性函数是正确的选择,对于二元分类,sigmoid 是正确的选择,对于多类分类,softmax 是正确的选择。在自动编码器中应该使用相同的概念。
结论-
我们已经讨论了所有流行的激活函数及其优缺点。还有很多激活功能,但我们并不经常使用。我们也可以定义我们的激活函数。这里讨论的一些激活函数从未用于解决现实世界的问题。他们只是为了知识。大多数情况下,对于隐藏层,我们使用 relu 及其变体,对于最终层,我们根据问题的类型使用 softmax 或线性函数。
学分-
- https://keras . io/API/layers/activations/# layer-activation-functions
- https://www . analyticsvidhya . com/blog/2020/01/fundamentals-deep-learning-activation-functions-when-to-use-them/
- https://towards data science . com/everything-you-need-know-to-know-about-activation-functions-in-deep-learning-models-84ba 9 f 82 c 253
- https://towards data science . com/comparison-of-activation-functions-for-deep-neural-networks-706 AC 4284 c8 a
- https://missing link . ai/guides/neural-network-concepts/7-types-neural-network-activation-functions-right/
- https://en . Wikipedia . org/wiki/Rectifier _(neural _ networks)
- https://mlfromscratch.com/activation-functions-explained/#/
- https://en . Wikipedia . org/wiki/Universal _ approximation _ theory

作者图片
那都是我这边的。感谢阅读这篇文章。使用的少数图片的来源被提及,其余的是我的创作。请随意发表评论,建议改正和改进。通过 Linkedin 与我联系,或者你可以给我发邮件,地址是 sahdevkansal02@gmail.com。我期待听到您的反馈。查看更多这样的文章我的媒体简介。
亚马逊 SageMaker 上 TensorFlow 和 Horovod 分布式培训快速指南
了解分布式培训是如何工作的,以及 Amazon SageMaker 如何让它像在笔记本电脑上培训一样简单

使用horovod和 Amazon SageMaker 在多个 GPU 上分发培训,以实现更快的培训和更高的生产率
在深度学习中,越多越好。更多的数据、更多的层和更多的计算能力通常会导致更高的准确性和更好的模型鲁棒性。
我可能无法帮助你收集更多数据,但我可以展示你如何在大量机器上进行分布式训练,以更快地训练和运行更多实验,并提高你的生产率。
在这篇博文中,我将介绍如何在不管理基础设施的情况下运行分布式培训——无需启动实例、设置集群、管理存储卷,也无需构建容器。带上你的训练脚本,指定 GPU 的数量,让 Amazon SageMaker 处理剩下的事情。
在本指南的第一部分,我将提供一步一步的指导来更新您的训练脚本,以使用 Horovod 库。为了使分布式训练工作,不同 GPU 上的训练过程需要通信。Horovod 实现了这种无缝的通信,并提供了一个方便的 API 来为分发培训准备您的培训脚本。您所做的更改与 GPU 的数量无关,因此这是一次性的工作。
在本指南的第二部分,我将展示如何使用 Amazon SageMaker 在任意数量的 GPU 上运行更新后的训练脚本,或者只需修改一行代码。
想在阅读的时候跟着阅读并运行示例吗?Jupyter 笔记本和培训脚本可从以下网址获得:
https://github . com/shashankprasanna/distributed-tensor flow-horovod-sage maker
Horovod 和环全归约方法
Horovod 是一个分布式深度学习框架,支持流行的深度学习框架——tensor flow、Keras、PyTorch 和 Apache MXNet。本指南中的示例使用 TensorFlow 和 Keras。如果您是 PyTorch 或 MXNet 用户,更新您的脚本将遵循与这里描述的非常相似的过程。Horovod 文档页面也包含了大量其他框架的例子。
在分布式训练中,多个进程需要相互通信。为了实现训练过程之间的通信,Horovod 使用一种称为消息传递接口(MPI)的通信协议。为了*均梯度和更新模型的所有副本,它使用了一种称为 ring-all reducce 的方法(我们将回到这一点)。这些方法并不新鲜,在高性能计算(HPC)领域工作的科学家、研究人员和工程师已经使用了多年,以解决计算流体动力学、分子动力学、计算机图形学和其他领域的问题。
MPI 本身定义了在集群中的多个进程之间发送和接收信息的基本概念,例如allreduce、allgather和broadcast。正如你可能已经从它们的名字中推断出的那样——allgather从所有过程中收集数据(在深度学习的情况下,是梯度)。广播,将数据(梯度)从一个进程广播到所有其他进程。allreduce(从概念上讲)结合了这两种操作—从所有过程中收集数据,执行归约操作(例如,*均梯度),然后广播(*均梯度)。

在 3 台各有 2 个 GPU 的机器上使用 6 个进程的 ring allreduce 的图示。rank 是全局唯一 ID,而 local rank 是每个 GPU 的本地唯一 ID
随着训练进程数量的增加,进程间通信也会增加,通信开销开始影响扩展效率。
ring all-reduce方法通过使通信成本独立于系统中的进程数量,对传统的allreduce方法进行了改进。它通过在逻辑环中安排进程来实现这一点,其中每个进程只接收来自其“左”邻居的数据,并向其“右”邻居发送数据,如附图所示。
深度学习的ring-allreduce过程在 Horovod 博文和 Horovod 论文中有更详细的描述。要使用 horovod 库,你并不真的需要知道ring-allreduce是如何工作的,但是对你使用的算法和库如何工作有一个直觉总是有帮助的。
要使用 update your training script 来使用 Horovod 库,您首先需要了解以下关键概念:
- 大小:进程/GPU 总数。这等于集群中计算实例的数量乘以每个实例的 GPU 数量。例如,如果您有 2 个
p3.16xlargeEC2 实例。大小应该是 2(实例)x 8(GPU)= 16。 - 等级:唯一的进程 ID(大小— 1)。GPU 中的每个进程都知道自己的唯一级别。
- 本地等级:机器内唯一的进程 ID。例如,在每个有 8 个 GPU 的
p3.16xlargeEC2 实例中,一个 GPU 的本地等级将从 0 到 7 不等。
分布式培训期间会发生什么?
出于说明的目的,让我们以 2 个 GPU 上的分布式训练作业为例——它们可以在相同的不同系统上,这无关紧要。以下是幕后发生的事情:

用两个培训过程说明分布式培训过程中发生的情况
第一步:正向传递期间,一切照常。模型的每个副本都使用它接收到的 batch_size 数据向前传递。
步骤 2: 然后执行反向传递以计算梯度。但是梯度还没有用于更新权重。
步骤 3: Horovod 现在对所有进程进行allreduce操作(*均梯度,然后广播)。在这个例子中是两个 GPU。
步骤 4: 最终的allreduced梯度现在用于更新每个模型
通过允许每个 GPU 对不同批次的数据进行训练,并降低梯度,您可以有效地对更大批次进行训练,从而加快训练速度。
更新您的培训脚本以使用 Horovod API
对于此演示,我将使用 CIFAR-10 数据集,该数据集由 60,000 张 32x32 的图像组成,这些图像属于 10 个不同的类(每个类 6,000 张图像)。博客帖子的 GitHub 存储库中提供了培训脚本以及 Jupyter 笔记本来运行完整的示例:
https://github . com/shashankprasanna/distributed-tensor flow-horo VOD-sage maker
本节描述了为准备分布式培训而对以下文件所做的更改:
[cifar10-tf-horovod-sagemaker.py](https://github.com/shashankprasanna/distributed-tensorflow-horovod-sagemaker/blob/master/code/cifar10-tf-horovod-sagemaker.py):主训练脚本[model_def.py](https://github.com/shashankprasanna/distributed-tensorflow-horovod-sagemaker/blob/master/code/model_def.py):模型架构定义脚本
为了让您更容易理解,我在上面的脚本中包含了完全相同的部分标题作为注释。寻找“变化NUMBER

在上面的脚本中寻找与注释完全相同的部分标题
变化 1:导入 horovod 和 keras 后端
将这些放在您的培训脚本的顶部,以导入 horovod。
import horovod.tensorflow.keras as hvd
import tensorflow.keras.backend as K
变化 2:初始化 horovod 并获得集群的大小
初始化horovod并获得集群中的 GPU 总数。如果只在 CPU 上运行,那么这将等于实例总数。
hvd.init()
size = hvd.size()
将 3 引脚 GPU 更改为本地进程(每个进程一个 GPU)
将 GPU 固定到当前进程。
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
config.gpu_options.visible_device_list = str(hvd.local_rank())
K.set_session(tf.Session(config=config))
变化 4:使用集群的规模(工人总数)来扩展学习
通过根据 GPU 数量调整学习率来更新学习率。分布式训练时的有效批次为 batch_size 乘以hvd.size()。这个变化是在model_def.py
通过提高学习速率,您可以补偿批量大小的有效增加。
opt = SGD(lr=lr * size, decay=weight_decay, momentum=momentum)
变化 5:使用 Horovod 包装 Keras 优化器,使其成为分布式优化器
分布式优化器使用allreduce或allgather对梯度进行*均和广播,然后用*均梯度更新权重。这个变化是在model_def.py
opt = hvd.DistributedOptimizer(opt)
更改 6:添加了用于同步初始状态的回调,并且只在第一个工作线程(等级 0)上保存检查点
变化 7:更新步骤/时期的数量
您需要将每批图像的总数除以 GPU 的数量。
更改 8:更新脚本以接受超参数作为命令行参数
Amazon SageMaker 将在启动分布式培训作业时将这些值传递给脚本。
在 Amazon SageMaker 上运行分布式培训
现在,您已经完成了最困难的部分——修改您的训练脚本,使其可以分发。
剩下的过程——分布式培训——使用 Amazon SageMaker 相对简单。
要使用 Amazon SageMaker 运行分布式培训作业,请下载并安装 SageMaker Python SDK 。为了更方便的体验,你还可以启动一个亚马逊 SageMaker 笔记本实例,它预装了 Jupyter 笔记本服务器、SageMaker Python SDK 和流行的深度学习框架。
运行 SageMaker 培训工作只涉及两个关键步骤,我将在下面重点介绍:
- 创建 SageMaker
TensorFlow估算器 - 调用
fit()函数
以下代码节选自博客文章库中的 Jupyter 笔记本。
使用 SDK,您需要指定以下细节,以便 Amazon SageMaker 可以获得所请求的资源并为培训做准备
- 你的训练脚本
- 具有培训脚本依赖关系的目录
- 保存已训练模型的位置
- 要在其上进行培训的 CPU 或 GPU 实例的类型
- 每个实例的 GPU 数量
- TensorFlow 版本
- 分布类型— MPI(由 Horovod 使用)或参数服务器(分布式培训的替代方法)
您可以在 SageMaker TensorFlow 估算器中指定更多选项,您可以在文档中找到完整列表:https://sagemaker.readthedocs.io/en/stable/index.html
实现如下:
定义估算器后,您需要指定亚马逊 S3 中训练、验证和测试数据集的路径,并将其传递给估算器的拟合函数。
你完了!坐下来,等待分布式培训作业完成。
您可以(并且应该)监控进度,我将在下一节中介绍这一点,但是首先,让我们仔细看看幕后发生了什么。

亚马逊 SageMaker 工作流程图
Amazon SageMaker 自动为您做了几件事,因此您不必担心基础架构级别的细节。简言之,SageMaker 将:
- 选择您的培训脚本和依赖项
- 在完全受管的群集中调配指定数量的实例
- 提取指定的 TensorFlow 容器图像
- 在每个实例上实例化容器。
- 将训练代码下载到实例中,并使其在容器中可用
- 从亚马逊 S3 复制训练数据集并使其在容器中可用
- 使用 MPI 启动培训
当培训开始时,Amazon SageMaker 在每个实例上运行与 Horovod 更新的培训脚本完全相同的副本。每个副本使用 hvd.local_rank()知道其唯一的本地等级,并且 GPU 被固定到该特定进程。然后 Horovod 负责执行ring-allreduce,并用*均梯度更新每个 GPU 上的权重。

显示每个运行完全相同的训练脚本副本的 GPU 的图示。每个培训过程都由其等级唯一标识
一次培训完成后,SageMaker 将自动:
- 上传训练工件,如训练模型、检查点、张量板日志等。到亚马逊 S3 桶你指定
- 拆除培训集群,这样您就不会产生额外的成本
监控培训培训进度
有几个不同的监视作业的选项:
- 亚马逊 SageMaker 控制台
- 张量板
亚马逊 SageMaker 控制台
如果你进入 AWS 控制台> Amazon SageMaker >培训作业,你可以看到一个当前正在运行的作业和你过去运行过的作业的列表。单击一个作业,您可以看到诸如进度状态、实例类型、超参数、数据集和模型工件的 S3 位置等详细信息。

显示 Amazon SageMaker 控制台上培训工作的屏幕截图
进一步向下滚动,您可以看到 CPU、GPU 和其他资源利用率。

显示 Amazon SageMaker 控制台上的作业监控的屏幕截图
您还可以找到一个到Amazon cloud watchdashboard 的链接,在这里您可以监控所有实例的培训工作日志。当出现问题时,这对于调试和诊断非常方便。

显示亚马逊 CloudWatch 上培训工作日志的屏幕截图
张量板
在培训脚本中,您会注意到有两个 Keras 日志回调函数。第一个用于在本地容器中保存 tensorboard 日志文件,第二个用于将这些日志同步到调用 SageMaker estimator 函数时指定的亚马逊 S3 位置。
callbacks.append(TensorBoard(log_dir=logdir))
callbacks.append(Sync2S3(logdir=logdir, s3logdir=tensorboard_logs))
现在你可以在任何你喜欢的地方运行 TensorBoard(你的笔记本电脑,台式机,EC2 实例),并通过 TensorBoard 日志将它指向你在亚马逊 S3 的位置。您需要确保您拥有访问亚马逊 S3 的权限,并且可以使用 AWS CLI 进行设置。
在安装了 tensorboard 并具有 S3 读取权限的计算机上运行以下命令:
S3_REGION=us-west-2 tensorboard — logdir s3://{bucket_name}/tensorboard_logs/

多型号分布式训练进度实时监控。日志保存在亚马逊 S3,这使你可以运行 tensorboard,并监控任何机器上访问你的 S3 桶的进展。
节省时间有什么不好呢?
在处理大型模型和数据集时,分布式培训可以节省您的时间。有了 Horovod 这样的图书馆和 Amazon SageMaker 这样的服务,你可以不费吹灰之力扩大培训规模。在这篇博文中,我介绍了两个关键概念:
- 如何使用 Horovod 更新您现有的培训脚本,使其可以分发。
- 如何使用您的 horovod 更新培训脚本,并使用 Amazon SageMaker 运行分布式培训,同时必须设置和管理集群
我将为您提供一些为分布式培训选择合适实例的指导原则:
为了获得更好的性能,请始终支持使用多个 GPU 的单个实例,而不是使用单个 GPU 的多个实例。
在 AWS 上,您可以使用 1 个 GPU ( p3.2xlarge)、4 个 GPU(p3.8xlarge)和 8 个 GPU(p3.16xlarge和p3dn.24xlarge)访问实例。
假设你想用 4 个 GPU 来运行分布式训练,总是倾向于单个p3.8xlarge实例,而不是 4 个p3.2x large。这样做的好处是,当进程需要通信来执行所有的 reduce 操作时,它们不会跨越网络障碍来与其他实例的 CPU 和 GPU 通信。这将增加通信延迟,可能会影响培训效果。同样,如果你想将训练分配给 8 个 GPU,那么选择单个p3.16xlarge或带有 8 个 GPU 的p3dn.24xlarge对 8 个p3.2xlarge或 2 个p3.8xlarge。这些多 GPU 实例包括 NVIDIA 的 NVLink 技术,该技术支持高带宽的 GPU 间通信,以加速 Horovod 执行的 allreduce 操作。
感谢阅读,我希望你喜欢这个指南。GitHub 上的所有代码和示例都可以在这里找到:
https://github . com/shashankprasanna/distributed-tensor flow-horovod-sage maker
如果您对本指南有任何疑问,对如何改进它有任何建议,或者对新指南有任何想法,请通过 twitter (@shshnkp)、LinkedIn 联系我,或者在下面留下评论。尽情享受吧!
使用 Pandas 的基本探索性数据分析指南。
更好地理解您的数据。

艾萨克·史密斯在 Unsplash 上拍摄的照片
使用库(比如 Matplotlib)绘制图形或查询数据相对容易。然而,为了能够绘制图表,数据必须采用特定的格式。这篇文章背后的动机之一是理解如何为进一步的处理准备数据。本文还讨论了执行基本操作,如查询、排序和可视化 Pandas 数据帧。
读取数据。
虽然数据可以以多种格式提供,但为了便于讨论,我们假设数据是逗号分隔值(CSV)格式。
import pandas as pd
df = pd.read_csv("path/to/file.csv")
上面的语法非常标准,大多数时候已经足够了。 read_csv() 的默认行为假设 csv 文件中的第一行是列标题,并将其用作创建的数据框的标题。但是,下面的变化要求使用第一行作为数据的一部分。
df = pd.read_csv("path/to/file.csv", header=None)
在这种情况下,您可以将列标题明确指定为—
df = pd.read_csv("path/to/file.csv", names=["Column 1", "Column 2"])
如果未指定 names 参数,则从 0 开始对列进行索引。

read_csv()函数概述。(使用谷歌幻灯片创建)。
熟悉数据。
一旦你读了你的数据,下一步就是让你自己适应数据集。让我们从查看数据集中的记录数量开始。
#Assume that the data is stored in a variable df
rowsInData = df.shape[0]
colsInData = df.shape[1]#A concise way
rowsInData, colsInData = df.shape
一旦你知道了数据的大小,让我们看看数据是什么样子的。您可以使用 head() 函数来查看数据集的起始行。 tail() 函数用于查看数据集的底部行。
df.head()# The default behaviour of head() is to show the first five rows of the data. You can pass an integer value to view more or less rows. The following variation shows the first 10 row.df.head(10)
看到这些数据后,让我们试着更好地理解这些数据。如果您知道存储在列中的数据的数据类型,这将非常有帮助。它帮助您将适当的功能应用到列。例如,如果列是 float 或 integer 数据类型,那么您可以对它们应用像 mean() 和 max() 这样的函数。 info() 函数返回数据帧的摘要以及每一列的数据类型。
df.info()
让我们看看存储在列中的不同类型的数据。
df[col].value_counts(dropna=False)
上面的命令将帮助你看到你存储在' col '中的每一项的频率。在某些情况下,您可能会看到不想要的值,例如数字的 NaN 值或字符串的空值。让我们在下一节讨论如何清理数据集。

熟悉数据集的总结。(使用谷歌幻灯片创建)。
清理数据集。
清理数据集最简单的方法是删除包含不需要的值的行。另一个令人信服的方法是估算缺失数据。让我们看看如何处理非数字(NaN)值。
#To get the count of null values in each column use the following syntax
df.isnull().sum()#Dropna removes rows containing NaN values.
df.dropna()
除了删除行之外,您还可以选择用 0 来替换 NaN 值,或者用相应列的*均值来替换它。
#Fill missing values with zeros
df[col].fillna(0, inplace=True)#Fill missing values with column mean
mean = df[col].mean()
df[col].fillna(mean,inplace=True)# inplace = True parameter modifies the original dataframe. In case inplace = False a new data frame is returned after the necessary operations are applied.
显然,您不能计算字符串值的*均值,但是可以使用 comparison 和 regex 来查找不需要的格式的字符串,并用您选择的值替换它们,或者删除相应的行。
#There can be multiple ways to drop rows but let's see two ways #The following command replaces strings having a single space character with NaN and then uses dropna() function to remove the rows as discussed earlier.df[col].replace(' ', np.nan, inplace=True)
df.dropna()#If you are familiar with regex it can be extremely useful. The following command uses regular expressions to grab a string which is composed of whitespaces (\s in regex refers to whitespace characters) and replaces them with NaN.df[col].replace(r'^\s*$', np.nan, regex=True, inplace=True)
df.dropna()
如果您不想删除,而是想要替换丢失的字符串值,您可以按如下方式操作—
#Replace using strict comparison
df[col].replace(' ', "Some Value", inplace=True)#Replace using regular expression
df[col].replace(r'^\s*$', "Some Value", regex=True, inplace=True)

数据集清理总结。(使用谷歌幻灯片创建)。
更改列的数据类型。
假设您希望 CSV 中的某个特定字段只有整数值,但是该列意外地有一个字符串值。在这种情况下,不能将列作为整数处理。让我们看看如何处理这种情况。
如前所述,您可以选择查找字符串值并用任何合适的值替换它。
一旦替换了字符串值,就可以按如下方式转换列的数据类型
df[col] = pd.to_numeric(df[col])
使用数据集。
一旦处理完数据,下一步就是从数据中提取有价值的信息。为了便于讨论,让我们考虑一个由几个学生的分数组成的非常小的数据集。下面是 CSV 数据的表格表示。
讨论中使用的数据集的表格表示。
查询数据。
基本的查询是列出分数高于某个值的学生。以下查询显示了 Test1 得分大于 15 的所有记录。除了大于号运算符,还可以使用其他关系运算符,如> =、
df.query('Test1 > 15')
Rows in which marks stored in Test1 are more than 15.
The following query shows how to perform comparison on string values. There also exists the not equal (!=) operator. The following query retrieves marks for John.
df.query('Name == "John"')
Retrieving marks for John.
Apart from basic comparison for string you can also apply functions such as startswith() 、 endswith() 和 contains() 来过滤数据。以下示例查询姓名以 j 开头的学生的分数。
df.query('Name.str.startswith("J")', engine='python')
检索姓名以 j 开头的学生的分数。
虽然 pandas 提供了基于字符串值列的过滤方法,但是没有比使用 regex 更强大的了。下面的示例使用 regex 检索以开头的名称。
df.query('Name.str.contains("^A", regex=True)', engine='python')
使用正则表达式获取姓名以 a 开头的学生的分数。
您也可以使用和和或组合多个条件。以下查询检索学生在前两次测试中得分超过 16 分的记录。
df.query('Test1 > 16 and Test2 > 16)')
学生在测试 1 和测试 2 中的分数超过 16 分的记录。
您并不总是希望将值与常数进行比较。以下语法用于比较两列的相应值,并返回满足条件的行。该查询显示了与第一次测试相比,在第二次测试中成绩有所提高的学生列表。
df.query('Test1 < Test2')
与测试 1 相比,学生在测试 2 中的表现有所提高的记录。
列选择。
您可能不希望看到包含所有列的结果。让我们来看看如何有条件地检索仅用于 Test2 的标记。
#The following statement shows just the Name and Test2 columns only if test2 marks are more than 15\. It doesn't show full rows as earlier.df[['Name', 'Test2']].query('Test2 > 15')
仅显示名称和 Test2 列,因此 Test2 > 15。
整理数据。
下一个最常见的操作是对数据进行排序。让我们看一个例子,按照 Test3 中获得的分数降序排列学生。
#Let's select only Name and Test3 columns first.
temp = df[['Name', 'Test3']]#Now's let's sort by Test3 in ascending order.
temp.sort_values(by=['Test3'])#Sorting by Test3 in descending order.
temp.sort_values(by=['Test3'], ascending=False)
按降序排列的 Test3。
绘制数据图表。
您可以使用 Matpoltlib 等库来绘制和可视化数据,这将有助于快速找到数据中的趋势和模式。但是为了统一起见,让我们使用 Pandas dataframe 类提供的 plot() 函数。
“姓名”和“测试 1”中得分的条形图。
df.plot.bar(x='Name', y='Test1')

测试 1 的分数。
下图比较了每个学生在所有三次考试中的分数。
df.plot.bar(x='Name', y=['Test1', 'Test2', 'Test3'])

每个学生在三次测验中的分数。
您当然可以根据自己的需求绘制更多信息图表,但是为了使讨论简单,我们就在这里结束吧。
管理机器学习实验的快速指南
如何使用亚马逊 SageMaker 组织您的机器学习实验、试用、作业和元数据,并获得安心

作者插图。受 xkcd.com 的启发
“实验”这个词对不同的人有不同的含义。对于科学家来说(也希望对于严谨的数据科学家来说),实验是一个确定结果是否与某些假设一致或冲突的经验程序。在机器学习实验中,你的假设可能是某个特定的算法(比如梯度提升树)比备选方案(比如随机森林、SVM、线性模型)更好。通过进行一项实验并通过改变变量值进行多次试验,您可以收集数据并解释结果以接受或拒绝您的假设。科学家称这个过程为科学方法。
不管你是否遵循科学方法,进行和管理机器学习实验都是困难的。这很有挑战性,因为要跟踪和管理大量的变量和工件。以下是你可能想要跟踪的一些事情的非详尽列表:
- 参数:超参数,模型架构,训练算法
- 作业:预处理作业、培训作业、后处理作业——这些作业消耗其他基础设施资源,如计算、网络和存储
- 工件:训练脚本、依赖项、数据集、检查点、训练模型
- 度量:训练和评估准确度,损失
- 调试数据:权重、偏差、梯度、损耗、优化器状态
- 元数据:实验、试验和作业名称、作业参数(CPU、GPU 和实例类型)、工件位置(例如 S3 桶)
作为一名开发人员或数据科学家,您最不想做的事情就是花更多的时间管理电子表格或数据库来跟踪实验和相关的实体以及它们之间的关系。

作者插图
您是否经常努力找出一周前训练的模型使用了哪些数据集、训练脚本和模型超参数?一个月前?一年前?你可以查看你的笔记、审计跟踪、日志和 Git 提交,并尝试拼凑出导致该模型的条件,但你永远无法确定你是否在一开始就组织好了一切。我有不止一个开发人员告诉我“我们不知道如何复制我们的生产模型,从事这项工作的人已经不在了——但是它很有效,我们不想弄乱它”。
在这篇博文中,我将讨论如何定义和组织你的实验,这样你就不会陷入这样的境地。通过一个代码示例,我将展示如何使用 Amazon SageMaker Experiments 运行实验、跟踪实验数据并检索数据进行分析。你需要的关于特定实验或培训工作的数据总是可以在你需要的时候快速获得,而不需要你记账。
GitHub 上提供了 Jupyter 笔记本中的完整示例:https://GitHub . com/shashankprasanna/sage maker-experiments-examples . git
剖析一个机器学习实验
跟踪机器学习实验的关键挑战是有太多的实体要跟踪,它们之间的关系很复杂。实体包括参数、工件、作业,实验、试验和实体之间的关系可以是一对一、一对多、多对一。如果能自动追踪一切不是很好吗?这样你就可以少担心,变得更有效率,因为你知道你的实验总是自我记录的。这正是我们要采取的方法。
让我们从介绍几个关键概念开始。在整篇文章中,我将继续讨论这些问题,所以这不会是你最后一次听到它们。通过提前展示这些关键概念,我希望在您浏览示例时,它能让您更好地理解实验、试验、试验组件、工作、工件、指标和元数据之间的关系。

实验、试验和试验组件之间的关系。作者插图。
- 机器学习实验:测试假设的系统程序(如模型 A 优于模型 B,超参数 X 对响应 Y 有积极影响)
- 变量:您改变和测量响应的可控因素(例如,模型架构、超参数)
- 试验:对特定变量集的训练迭代。变量集可以从变量交互的详尽集合(例如,模型架构、优化器、其他超参数)中取样。
- 试验组件:各种参数、作业、数据集、模型、元数据和其他工件。试用组件可以与试用相关联(例如培训工作),也可以是独立的(例如元数据)
实验、试验和试验组件的属性:
- 一个实验的独特之处在于它的目标或假设
- 一个实验通常包含多个试验,每个变量集一个试验。
- 试验的唯一特征是其变量集,从您定义的变量空间取样。
- 试验组件是与特定试验相关联的任何工件、参数或作业。
- 试验组件通常是试验的一部分,但它可以独立于实验或试验而存在。
- 试用组件不能与实验直接关联。它必须与实验相关的试验相联系。
- 一个试验组件可以与多个试验相关联。这有助于跟踪实验中所有试验共有的数据集、参数和元数据。
这些概念会随着你对例子的理解而变得更加清晰,所以如果你没有记住它们也不用担心。我们将从创建实验开始构建每一步。
使用亚马逊 SageMaker 管理机器学习实验、试验、作业和元数据
内化到目前为止所讨论的概念的最好方法是通过代码示例和插图。在这个例子中,我将定义一个问题陈述,制定一个假设,创建一个实验,创建跟踪各种工件和参数的跟踪器,运行试验,最后分析结果。我将使用亚马逊 SageMaker 实验来完成这项工作。我在 GitHub 上的以下 Jupyter 笔记本中为您提供了完整的工作示例:sage maker-experiments-examples . ipynb。
运行这款笔记本最快最简单的方法就是在亚马逊 SageMaker Studio 上运行。SageMaker Studio 笔记本让您只需单击一下即可启动 Jupyter 笔记本环境,它包括一个实验跟踪窗格和可视化功能,使跟踪您的实验变得更加容易。你也可以在装有亚马逊 SageMaker python SDK 和亚马逊 SageMaker Experiments 包的笔记本电脑或台式机上运行这个。
第一步:制定一个假设并创建一个实验
第一步是定义你的假设。如果你更喜欢商业演讲而不是学术演讲,你可以指定一个实验目标。“尝试一堆东西,选择最好的”可能很诱人,但是在定义你的问题之前做一点努力会让你以后安心。
让我们定义一个假设的例子。你的假设考虑了你的领域专长和你所做的任何初步研究或观察。例如:
假设:如果我使用我的自定义图像分类模型,它将在 CIFAR10 数据集上提供比 ResNet50 模型更好的准确性

一个实验是由其假设唯一定义的。通过陈述假设,你现在有了一个清晰的路径来设计一个实验,选择正确的变量并收集足够的数据来接受或拒绝这个假设。使用 SageMaker 实验 SDK,您可以如下定义一个实验。在描述中,我包括了我的实验假设。
以下代码创建了一个 SageMaker 实验:
步骤 2:定义实验变量
一个实验包括一系列变量,这些变量在多次试验中会发生变化。这些变量可能是超参数,如批量大小、学习速率、优化器、模型架构或您认为会对响应产生影响的其他因素,即我们示例中的准确性或损失。在实验设计领域,这些也被称为受控因素。

在我们的例子中,我想测试我们定制的神经网络架构的功效,我认为它比现成的 ResNet50 更好。因此,模型架构是我们的第一个可变或受控因素。我还想研究其他超参数对响应的影响——优化器(adam、sgd、rmsprop)、时期(在更少的时期获得高精度)。我可以用下面的代码来定义这些。
输出:

不属于实验一部分的其他超参数可以是静态的(在整个实验中不变),所以我称它们为静态超参数。
注意:这并不意味着静态超参数对响应没有影响。这意味着在这个实验中,它不是一个你能控制的变量。还有一些你无法控制的因素,比如,软件的 bug,操作系统低效的资源分配,天气或者你运行实验时的心情。这些在实验设计领域被称为不可控因素。
步骤 3:跟踪实验数据集、静态参数、元数据
在我为步骤 2 中的每个超参数选项启动几个实验测试和训练工作之前,我必须确保我还跟踪了测试中常见的工件和参数。

在本例中,以下各项在试验中保持不变:
- 静态超参数(批量、学习率、重量衰减、动量)
- 变量列表(模型架构和变量超参数)
- 培训、验证和测试数据集
- 生成 TFRecord 文件的数据集预处理脚本
你可以追踪任何你想和这个实验相关的东西。以下代码使用上述信息创建了一个名为“实验-元数据”的跟踪器:
该跟踪器是一个试用组件,目前与实验无关。回想一下,在“机器学习实验的剖析”中,试验组件不能与实验直接关联。它必须首先与试验相关联。在下一节中,我将把这个公共试验组件与实验中的所有试验关联起来。
步骤 4:创建试用并启动培训工作
在第 2 步中,我通过改变优化器、模型和时期创建了一个包含 18 个变量集的列表。在这一步中,我将遍历这些集合,并为每个集合创建一个试验和一个培训作业。这里是方法。对于每个变量集,我将:

- 创建一个试验,并将其与实验相关联
- 将步骤 3 中的追踪器与该试验相关联,作为试验组件
- 创建新的跟踪器来跟踪试验特定的超参数,并将其作为试验组件与试验相关联
- 使用试验特定的超参数创建培训作业,并将其作为培训作业试验组件与试验相关联
以下代码摘录显示了如何实现上述步骤 a-d。
所展示的节选内容仅供举例说明,完整示例,在 Github 上运行本笔记本:https://Github . com/shashankprasanna/sage maker-experiments-examples/blob/master/sage maker-experience-examples . ipynb
运行上述代码后,您将看到 SageMaker 产生了多个培训作业,每个作业都与其独特的试验相关联。

在亚马逊 SageMaker Studio 中,还可以在左侧的实验窗格中查看实验试用。

如果双击其中一个试验,您可以看到相关的试验组件:

- cifar 10-training-rms prop-resnet-120-XXXXX:培训工作的试用组件
- 试验-元数据-XXXXX :试验特定超参数的试验组件
- 实验-元数据:所有试验共有的实体的试验组件(静态超参数、变量列表、训练、验证和测试数据集、数据集预处理脚本)
第五步:分析实验结果
在训练作业完成运行之后,我现在可以比较所有的试运行,并对实验进行推断。只需在前期做一点点努力,仔细定义和组织您的实验,并利用 SageMaker Experiments 等服务,您就不必花太多时间通过组合多个数字和模拟源来获取分析报告。你可以休假或从事不同的项目,而你的老板认为你正在努力梳理 Git 提交、审计跟踪和将数据输入电子表格。

作者插图。
在这一部分,我将提取一份关于我刚刚运行的实验的报告。我需要的只是实验的名称,使用 SageMaker 实验包,我可以使用下面的代码进行分析:
在下面的输出中,您可以看到,( 1)总体最佳精度,( 2)60 个历元时的最佳精度,( 3)30 个历元时的最佳精度都与我的定制模型相对应。

我可以使用这些数据来接受或拒绝我的假设,即对于 CIFAR10 数据集,我的自定义模型比 ResNet50 提供了更好的准确性。我构建这个例子是为了说明实验管理的关键概念,上面的数据可能不足以得出任何结论。在这种情况下,你可以通过更新你的假设和变量来进行另一个实验。
(奖励)步骤 6:使用 SageMaker 调试器可视化性能曲线
如果您喜欢深入研究每项培训工作并分析指标、权重或梯度信息,您可以使用 SageMaker 调试器。SageMaker Debugger 自动从每个培训作业中捕获一些默认的调试信息,您还可以定制应该发出哪些数据供以后分析。如果你对用 SageMaker 调试机器学习感兴趣,可以看看我之前的一篇深入调试的文章:
smdebug 开源库允许您读取和分析调试数据。下面的代码将下载训练期间每个步骤的所有试验的验证准确性,并绘制 30、60 和 90 个时期的 3 个最佳模型。您还可以在训练期间绘制中间张量和梯度,以便进一步调试。查看上面的博文了解更多细节。

最高性能模型在 30、60 和 120 个时期的验证准确度与步骤
感谢阅读
自机器学习的早期以来,我们已经走过了漫长的道路。从高质量的开源机器学习框架到大规模培训和部署模型的全面管理服务,以及端到端的实验管理,无论您的机器学习需求是什么,都不缺乏工具。在这篇博文中,我介绍了如何使用 Amazon SageMaker 减轻与管理机器学习实验相关的痛苦。我希望你喜欢阅读。GitHub 上的所有代码和示例都可以在这里找到:
https://github . com/shashankprasanna/sage maker-experiments-examples
如果你觉得这篇文章有趣,请看看我在机器学习和 SageMaker 上的其他博客帖子:
- 如何调试机器学习模型以尽早发现问题
- 亚马逊 SageMaker 上 TensorFlow 和 Horovod 分布式培训快速指南
- 亚马逊 SageMaker 使用 Spot 实例节省培训成本快速指南
- Kubernetes 和亚马逊 SageMaker 的机器学习——两全其美
如果你对这篇文章有疑问,对如何改进它有建议或者对新帖子有想法,请在 twitter ( @shshnkp ), LinkedIn 联系我或者在下面留下评论。尽情享受吧!
神经网络优化器(快速)指南及其在 Keras 中的应用
SGD,Adagrad,Adam 等等
随着深度学习的快速发展,出现了过多的优化器,人们可以选择来编译他们的神经网络。有这么多优化器,很难选择一个来使用。本文将简要说明各种神经网络优化器之间的区别。
SGD
与批量梯度下降或普通梯度下降相反,随机梯度下降更新每个训练示例 x 和 y 的参数。SGD 以高方差执行频繁更新,导致目标函数大幅波动。

新币波动。来源
SGD 的波动使它能够从一个局部极小值跳到一个可能更好的局部极小值,但是使收敛到一个精确的极小值变得复杂。
动量是 SGD 的一个参数,可以添加到峡谷中以帮助 SGD,峡谷是表面在一个维度比另一个维度弯曲得更陡的区域,常见于 optima 周围。在这些场景中,SGD 在峡谷的斜坡周围振荡,沿着局部最优的底部犹豫前进。

动量有助于在正确的方向上加速 SGD,因此抑制了多余的振荡,如图 2 所示。
内斯特罗夫动量是对标准动量的改进——一个盲目跟随斜坡的球是不令人满意的。理想情况下,球会知道它要去哪里,所以它可以在山坡再次向上倾斜之前减速。内斯特罗夫加速梯度(NAG)可以通过在 SGD 到达上坡区域之前减慢它的速度,帮助减少收敛中不必要的冗余,从而使动量具有预见性。
阿达格拉德
Adagrad 使学习率适应参数,对与频繁出现的特征相关联的参数执行较小的更新(低学习率),对与不频繁出现的特征相关联的参数执行较大的更新(高学习率)。因此,Adagrad 在处理稀疏数据方面是有帮助的。
Adagrad 消除了手动调整学习率的需要——大多数实现都保留默认值 0.01。然而,Adagrad 的算法导致学习率随着每次迭代而收缩,最终变得无穷小,在这个速度下,算法无法获得任何新知识。
Adadelta 是 Adagrad 的扩展,它寻求解决模型学习率收敛到 0 的问题。RMSprop 是 Adadelta 的另一个版本,它试图解决 Adadelta 试图解决的相同问题。
亚当
Adam 是为每个参数计算自适应学习率的另一种方法。除了像 Adadelta 和 RMSprop 一样存储以前的渐变,Adam 还实现了 momentum 的一个版本。Adam 的行为就像一个有摩擦的重球,更喜欢误差曲面中的*坦极小值,可以被视为 RMSprop 和 SGD 的组合,具有动量。
Nadam 是另一个优化器,它结合了 adam 和 NAG。
形象化
比尔函数

GIF:亚历克·拉德福德
请注意,Adagrad、Adadelta 和 RMSprop 几乎立即朝着正确的方向前进,并非常快地收敛,而具有动量的 SGD 和 NAG 则偏离了轨道,让人想起一个球滚下山坡的形象。然而,NAG 很快就能通过向前看来纠正它的路线。
鞍点

GIF:亚历克·拉德福德
注意 SGD(有动量和没有动量)和 NAG 发现很难突破到最小值,并且卡在中间。然而,新币与势头和唠叨最终逃脱鞍点。阿达格拉德、RMSprop 和阿达德尔塔迅速向负斜率下驶去。
我应该使用哪种优化器?
如果输入数据是稀疏的,最好的结果将来自自适应学习率方法。总体而言,Adam 可能是深度神经网络的最佳总体选择。
如果你喜欢阅读,看看我在神经网络方面的其他工作:
DBMS 中关系代数运算符的快速指南
带有示例的关系代数运算符快速介绍
数据库管理系统(DBMS)必须有一种查询语言,以便用户可以访问存储在数据库中的数据。关系代数(RA) 被认为是一种过程查询语言,用户在其中告诉系统执行一组操作以获得期望的结果。即用户告诉应该从数据库中检索什么数据以及如何检索。在本文中,我将简要介绍关系代数,并通过示例和 PostgreSQL 命令完成一些操作。

什么是关系代数?

图一。关于关系数据库的基本术语
根据维基百科,
关系代数是一个代数家族,具有良好的语义,用于对存储在关系数据库中的数据进行建模,并在其上定义查询。
RA 为关系数据库提供了理论基础。我假设您知道关系数据库中使用的基本术语。现在注意术语关系、属性和元组,如图 1 所示。
在本文中,我们将介绍以下 RA 运算符。
- 推断
- 选择
- 重新命名
- 叉积
- 自然连接
- 条件连接
- 联盟
- 交集
- 集合差异
我们将考虑以下 3 个表作为示例来解释这些 RA 操作。我们有一个会员表(会员详情)图书表(图书详情)借阅表(借阅图书详情)。

图二。三个示例关系
1.投影(π)
投影用于从关系中选择所需的数据列。请注意,投影会删除重复的数据(元组)。
查询:借书会员的会员 id。

查询:会员的会员 id 及其所借书籍的书籍 id。

2.选择(σ)
选择用于从关系中选择所需的数据元组。在选择过程中,我们可以指定数据必须满足的某些条件。
查询:1997 年 10 月 21 日出生的成员的详细信息。

3.重命名(ρ)
重命名操作允许重命名某个输出关系。
查询:将成员关系重命名为 LibraryMemebr。

4.叉积(✕)
叉积用于将两个不同关系中的数据组合成一个组合关系。如果我们考虑两个关系: A 带 n 元组和 B 带 m 元组, A ✕ B 将由 n.m 元组组成。
查询:会员✕借

注意,成员关系有 5 个元组,钻取关系有 5 个元组。因此成员✕·博洛有 5✕5 = 25 个元组。
5.自然连接(⋈)
两个或多个关系之间的自然连接将产生元组的所有组合,其中它们对于公共属性具有相等的值。
查询:会员⋈借

请注意,本例中的公共属性是成员 ID。
6.条件连接(⋈c)
条件连接类似于自然连接,但是在条件连接中,我们可以使用操作符大于、小于、等于或不等于来指定任何连接条件。您也可以使用 AND (^)和 OR (v)运算符来组合条件。
查询:挖掘了多本书的会员的借阅明细。

7.联盟(⋃)
RA 中的并运算非常类似于集合论中的并运算。但是,对于两个关系的联合,这两个关系必须具有相同的属性集。
查询:Charlie 和 Mike 所借图书的图书 id。

8.十字路口(⋂)
RA 中的交集运算与集合论中的非常相似。但是,对于两个关系的交集,这两个关系必须具有相同的属性集。
查询:同时借阅了《Fences》和《Inheritance》两本书的会员的会员 id。

9.设置差异(-)
RA 中的集差运算非常类似于集合论中的集差运算。然而,对于两个关系之间的集合差异,两个关系必须具有相同的属性集合。
查询:从未借过书的会员的会员 id。

R1 将返回所有成员爱丽丝、鲍勃、查理、迈克和凯蒂的详细信息。R2 将归还爱丽丝、查理、迈克和凯蒂借书的详细资料。当我们取 R1 和 R2 之间的差值时,将返回 Bob 的详细信息。
最后的想法
创建这些关系的 PostgreSQL 命令和演示每个 RA 操作符的查询可以在下面给出的 SQL Fiddle 链接中找到。你运行它们,到处玩,看看会发生什么。😊
[## 一个简单的在线测试和分享数据库问题及其解决方案的工具。
模式面板使用此面板来设置您的数据库问题(创建表、插入以及您需要的任何其他语句…
sqlfiddle.com](http://sqlfiddle.com/#!15/3ca77/24)
此外,如果您想在您的机器上试验这些命令,您可以从下面链接中提供的 gists 下载它们。
关系代数操作符看起来很简单,但是在表示复杂查询和查询优化时,它们变得非常强大(将在以后的文章中讨论)。
希望这篇文章对你有用。我很想听听你的想法。😊
感谢您的阅读!
干杯!😃
使用 spaCy | NLP |进行标记化和短语匹配的快速指南第 2 部分
使用 spaCy 的文本预处理步骤,NLP 库
spaCy是专门为生产使用而设计的。它帮助您构建处理和“理解”大量文本的应用程序。它可以用来构建信息抽取或自然语言理解系统或为深度学习预处理文本。在本文中,您将了解使用 spaCy 的标记化、词条化、停用词和短语匹配操作。
这是空间系列的第二篇文章。在我的上一篇文章中,我已经解释了空间安装和基本操作。如果您对此不熟悉,我建议从第 1 条开始,以便更好地理解。
标记化
标记化是文本处理任务的第一步。记号化不仅仅是将文本分解成单词、标点符号等称为记号的部分。然而,还不止这些。spaCy do 智能标记器,它在内部识别一个“.”是标点符号并将其分隔成标记,或者它是缩写(如“美国”)的一部分,但不要分隔它。
spaCy 应用特定于语言类型的规则。我们用一个例子来理解。
import spacy
nlp = spacy.load("en_core_web_sm")doc = nlp("\"Next Week, We're coming from U.S.!\"")
for token in doc:
print(token.text)

- 空白首先根据原始文本中的可用空白开始拆分。
- 然后,它从左到右处理文本,并对每个项目(基于空白的拆分器)执行以下两项检查:
- 例外规则检查:“美国”中可用的标点符号不应被视为进一步的标记。它应该保持不变。然而,我们的惶然应该被分裂成“我们”和“‘惶然’
- 前缀、后缀和中缀检查:标点符号,如逗号、句号、连字符或引号,将被视为标记并分离出来。
如果匹配,则应用规则,标记器继续循环,从新分割的子字符串开始。这样,spaCy 可以拆分复杂的嵌套标记,如缩写和多个标点符号的组合。

- 前缀:查找开头的字符
$ ( " ¿ - 后缀:查找末尾的字符
mm ) , . ! "mm 是一个单位的例子 - 中缀:查找中间的字符
- -- / ... - 异常:特殊情况规则,当应用标点规则时,将一个字符串拆分成几个记号或防止一个记号被拆分
St. N.Y.
请注意,标记是原始文本的一部分。标记是 Doc 对象的基本构建块——帮助我们理解文本含义的一切都是从标记及其相互关系中派生出来的。
作为标记的前缀、后缀和中缀
- 空格将分隔不构成单词组成部分的标点符号。
- 句子末尾的引号、逗号和标点符号将被赋予各自的符号。
- 但是,作为电子邮件地址、网站或数值的一部分存在的标点符号将作为令牌的一部分保留。
doc2 = nlp(u"We're here to guide you! Send your query, email contact@enetwork.ai or visit us at http://www.enetwork.ai!")for t in doc2:
print(t)

注意感叹号、逗号都被赋予了自己的记号。然而,电子邮件地址和网站 URL 中的冒号并不是孤立的。因此,电子邮件地址和网站都会保留。
doc3 = nlp(u'A 40km U.S. cab ride costs $100.60')
for t in doc3:
print(t)

在这里,距离单位和美元符号被赋予它们自己的记号,然而,美元数量被保留,数量中的点不是孤立的。
令牌生成中的异常
作为已知缩写的一部分存在的标点符号将作为标记的一部分保留。
doc4 = nlp(u"Let's visit the St. Louis in the U.S. next year.")
for t in doc4:
print(t)

在这里,“圣”和“美国”的缩写都保留了下来。St .旁边的均值点不作为令牌分开。美国也一样。
清点代币
使用 len()函数,可以计算文档中的标记数。
len(doc4)

统计 Vocab 条目
Vocab对象包含一个完整的项目库!

请注意,所有的 doc 对象都是从英语语言模型创建的,我们在开始时使用
*nlp = spacy.load("en_core_web_sm")*
因此 vocab len 将是相同的。
令牌中的索引和切片
Doc对象可以被认为是token对象的列表。- 因此,可以通过索引位置检索各个标记。
- 可以通过切片来检索令牌的跨度:

不允许分配令牌

词汇化
- 与词干化相反,词汇化看起来不仅仅是单词缩减,而是考虑一种语言的全部词汇来对单词进行形态分析。
- was 的引理是 be,rats 的引理是 rat,mice 的引理是 mouse。此外,“meeting”的引理可能是“meet”或“meeting ”,这取决于它在句子中的用法。
- 词汇化查看周围的文本来确定给定单词的词性。它不对短语进行分类。
注意空间没有词干。因为变元化被认为比词干化更能提供信息。
doc1 = nlp(u"I am a runner running in a race because I love to run since I ran today")
for token in doc1:
print(token.text, '\t', token.pos_, '\t', token.lemma, '\t', token.lemma_)

创建一个函数,以更结构化的方式查找并打印词条。
def find_lemmas(text): for token in text: print(f'{token.text:{12}} {token.pos_:{6}} {token.lemma:<{22}}{token.lemma_}')
在这里,我们使用一个 f 字符串通过设置最小字段宽度和添加 lemma 哈希值的左对齐来格式化打印文本。
现在,让我们调用这个函数
doc2 = nlp(u"I saw eighteen mice today!")
find_lemmas(doc2)

注意中saw的引理是see,mice的引理是mouse , mice是mouse的复数形式,see eighteen是一个数,不是是eight的扩展形式,这是在计算引理时检测到的,因此保持eighteen不变。
doc3 = nlp(u"I am meeting him tomorrow at the meeting.")
find_lemmas(doc3)

这里meeting的引理是由其词性标签决定的。
对于作为动词的第一个meeting,它已经将引理计算为meet。第二个meeting是一个名词,它将引理计算为meeting本身。
这就是我们可以看到 spaCy 在计算引理时处理词性的地方。
doc4 = nlp(u"That's an enormous automobile")
find_lemmas(doc4)

注意词汇化不会而不是将单词缩减到它们最基本的同义词——也就是说enormous不会变成big,automobile不会变成car。
停止言语
- 像“a”和“the”这样的词出现得如此频繁,以至于它们不像名词、动词和修饰语那样需要彻底标记。
- 我们称之为停用词,可以从待处理的文本中筛选出来。
- spaCy 有一个内置列表,里面有大约 305 个英文停用词。

您可以使用 len() 功能打印停用词的总数。

添加用户定义的停用词
有时,您可能希望在默认集合中添加停用字词。也许你决定'btw'(“顺便说一下”的常用简写)应该被认为是一个停用词。
#Add the word to the set of stop words. Use lowercase!
nlp.Defaults.stop_words.add('btw') #alwasy use lowercase while adding the stop words#Set the stop_word tag on the lexeme
nlp.vocab['btw'].is_stop = True

删除停用词
或者,您可以决定'without'不应被视为停用词。
#Remove the word from the set of stop words
nlp.Defaults.stop_words.remove('without')#Remove the stop_word tag from the lexeme
nlp.vocab['without'].is_stop = Falselen(nlp.Defaults.stop_words)nlp.vocab['beyond'].is_stop

词汇和匹配
在这一部分中,我们将识别和标记与我们自己定义的模式相匹配的特定短语。
基于规则的匹配
- spaCy 提供了一个名为
Matcher的规则匹配工具。 - 它允许您构建一个令牌模式库。
- 然后,它将这些模式与 Doc 对象进行匹配,以返回找到的匹配项的列表。
您可以匹配令牌的任何部分,包括文本和注释,并且可以向同一个匹配器添加多个模式。
#Import the Matcher library
from spacy.matcher import Matcher
matcher = Matcher(nlp.vocab)

创建模式
在文学作品中,“united states”这个短语可能是一个或两个单词,带或不带连字符。在这一节中,我们将开发一个名为“unitedstates”的匹配器来查找所有三个:
pattern1 = [{'LOWER': 'unitedstates'}]
pattern2 = [{'LOWER': 'united'}, {'LOWER': 'states'}]
pattern3 = [{'LOWER': 'united'}, {'IS_PUNCT': True}, {'LOWER': 'states'}]matcher.add('UnitedStates', None, pattern1, pattern2, pattern3)
进一步打破它:
pattern1查找小写文本为“unitedstates”的单个令牌pattern2按顺序查找两个相邻的单词“united”和“states”pattern3查找三个相邻的记号,中间的记号可以是任何标点。*
请记住,单个空格是没有标记的,所以它们不算标点符号。
一旦我们定义了我们的模式,我们将它们传递给名为‘United States’的matcher,并将回调*设置为None
将匹配器应用于 Doc 对象
为了让你明白,我把美国写成了不同的形式,比如“美国”、“美国”、“美国”和“美国”
doc = nlp(u'The United States of America is a country consisting of 50 independent states. The first constitution of the UnitedStates was adopted in 1788\. The current United-States flag was designed by a high school student - Robert G. Heft.')found_matches = matcher(doc)
print(found_matches)for match_id, start, end in found_matches:
string_id = nlp.vocab.strings[match_id] # get string representation
span = doc[start:end] # get the matched span
print(match_id, string_id, start, end, span.text)

设置模式选项和量词
您可以通过传递一个'OP':'*'参数来使令牌规则可选。这让我们可以简化我们的模式列表:
#Redefine the patterns:
pattern1 = [{'LOWER': 'unitedstates'}]
pattern2 = [{'LOWER': 'united'}, {'IS_PUNCT': True, 'OP':'*'}, {'LOWER': 'states'}]#Remove the old patterns to avoid duplication:
matcher.remove('UnitedStates')#Add the new set of patterns to the 'SolarPower' matcher:
matcher.add('someNameToMatcher', None, pattern1, pattern2)doc = nlp(u'United--States has the world's largest coal reserves.')found_matches = matcher(doc) print(found_matches)

这找到了两个单词的模式,有和没有连字符!
以下量词可以传递给'OP'键:

小心旅鼠!
假设我们在某个句子中有另一个词“太阳能”。现在,如果我们想同时匹配“太阳能”和“太阳能供电”,寻找“供电”的引理并期望它是“电力”可能很有诱惑力。情况并不总是这样!形容词‘powered’的引理还是‘powered’:
pattern1 = [{'LOWER': 'solarpower'}]
pattern2 = [{'LOWER': 'solar'}, {'IS_PUNCT': True, 'OP':'*'}, {'LEMMA': 'power'}] # CHANGE THIS PATTERN#Remove the old patterns to avoid duplication:
matcher.remove('someNameToMatcher') #remove the previously added matcher name#Add the new set of patterns to the 'SolarPower' matcher:
matcher.add('SolarPower', None, pattern1, pattern2)doc2 = nlp(u'Solar-powered energy runs solar-powered cars.')found_matches = matcher(doc2)
print(found_matches)

matcher 找到了第一个词,因为 lemmatizer 将“Solar-powered”视为动词,而不是第二个词,因为它认为它是形容词。
对于这种情况,最好设置显式令牌模式。
pattern1 = [{'LOWER': 'solarpower'}]
pattern2 = [{'LOWER': 'solar'}, {'IS_PUNCT': True, 'OP':'*'}, {'LOWER': 'power'}] pattern3 = [{'LOWER': 'solarpowered'}] pattern4 = [{'LOWER': 'solar'}, {'IS_PUNCT': True, 'OP':'*'}, {'LOWER': 'powered'}]#Remove the old patterns to avoid duplication:
matcher.remove('SolarPower')#Add the new set of patterns to the 'SolarPower' matcher:
matcher.add('SolarPower', None, pattern1, pattern2, pattern3, pattern4)found_matches = matcher(doc2)
print(found_matches)

其他令牌属性
除了引理之外,我们还可以使用各种令牌属性来确定匹配规则:
令牌通配符
您可以传递一个空字典{}作为通配符来表示任何标记。例如,您可能想在不知道#字符后面是什么的情况下检索标签:
短语匹配器
在上一节中,我们使用了令牌模式来执行基于规则的匹配。另一种更有效的方法是在术语列表上进行匹配。在这种情况下,我们使用 PhraseMatcher 从短语列表中创建一个 Doc 对象,并将其传递给matcher。
#Perform standard imports, reset nlp
import spacy
nlp = spacy.load('en_core_web_sm')# Import the PhraseMatcher library
from spacy.matcher import PhraseMatcher
matcher = PhraseMatcher(nlp.vocab)
在这个练习中,我们将导入一篇维基百科上关于里根经济学
的文章来源:https://en.wikipedia.org/wiki/Reaganomics
with open('../TextFiles/reaganomics.txt') as f:
doc3 = nlp(f.read())#First, create a list of match phrases:
phrase_list = ['voodoo economics', 'supply-side economics', 'trickle-down economics', 'free-market economics']#Next, convert each phrase to a Doc object:
phrase_patterns = [nlp(text) for text in phrase_list]#Pass each Doc object into matcher (note the use of the asterisk!):
matcher.add('VoodooEconomics', None, *phrase_patterns)#Build a list of matches:
matches = matcher(doc3)#(match_id, start, end)
matches


前四个匹配项是里根经济学定义中使用这些术语的地方:
doc3[:70]

查看比赛
有几种方法可以获取匹配周围的文本。最简单的方法是从文档中获取一片比匹配更宽的令牌:

这都是关于文本预处理操作,包括标记化、词条化、停用词和短语匹配。希望你喜欢这篇文章。
相关文章:
- Spacy 安装和基本操作| NLP 文本处理库|第 1 部分
- 使用 spaCy | NLP |第 3 部分进行词性标注和依存解析
- 命名实体识别 NER 使用空间|自然语言处理|第 4 部分
- 如何使用 spaCy | NLP 系列|第 5 部分进行句子分割或句子分词
- 从文本中提取数字特征| NLP 系列|第 6 部分
- 使用空间的 Word2Vec 和语义相似度| NLP 空间系列|第 7 部分
如果您有任何改进内容的反馈或想法,请写在下面的评论部分。你的评论很有价值。
谢谢大家!
参考资料:
- https://spacy.io/usage/spacy-101
- https://www . udemy . com/course/NLP-natural-language-processing-with-python/
原载于 2020 年 4 月 6 日【http://ashutoshtripathi.com】。
Amazon SageMaker 使用 Spot 实例的快速指南
通过 Amazon SageMaker 上的托管现场培训,降低您的深度学习培训成本

亚马逊 SageMaker 将自动备份和同步检查点亚马逊 S3,让您可以轻松恢复训练
降低机器学习培训成本的最简单方法之一是使用亚马逊 EC2 Spot 实例。与按需费率相比,Spot 实例允许您以高达 90%的大幅折扣访问备用 Amazon EC2 计算能力。那么为什么不总是使用 Spot 实例呢?好吧,可以,只要你的工作量能容忍突然的打扰。由于 Spot 实例是备用容量的一部分,因此只需通知 2 分钟就可以回收它们!
深度学习培训是可以容忍中断的工作负载的一个很好的例子,我以前写过关于使用亚马逊 EC2 Spot 实例进行深度学习培训的。然而,作为一名机器学习开发人员或数据科学家,您可能不希望管理现场车队请求、轮询容量、轮询终止状态、手动备份检查点、在恢复培训时手动同步检查点,以及在每次想要运行培训作业时设置一切。
亚马逊 SageMaker 提供管理的现场培训,这是一种使用亚马逊 EC2 现场实例为亚马逊 SageMaker 培训工作降低培训成本的便捷方式。这意味着您现在可以节省高达 90%的培训工作量,而无需设置和管理 Spot 实例。Amazon SageMaker 将自动为您提供 Spot 实例,如果 Spot 实例被回收,Amazon SageMaker 将在容量可用后自动恢复培训!
在这篇博客文章中,我将提供一个分步指南,通过 Amazon SageMaker 使用 Spot 实例进行深度学习训练。我将介绍您需要做哪些代码更改来利用 Amazon SageMaker 的自动检查点备份和同步到 Amazon S3 特性。我将使用 Keras 和 TensorFlow 后端来说明如何利用 Amazon SageMaker 管理的现场培训。您还可以在另一个框架上实现相同的步骤,比如 PyTorch 或 MXNet。
GitHub 上有一个关于 Jupyter 笔记本的完整例子:【https://github.com/shashankprasanna/sagemaker-spot-training
哪些工作负载可以利用 Spot 实例?
为了利用 Spot 实例节省,您的工作负载必须能够容忍中断。在机器学习中,有两种类型的工作负载大致属于这一类别:
- 无状态的微服务,比如模型服务器(TF Serving,TorchServe — 读我的博文),服务推理请求
- 有状态作业,如深度学习训练,能够通过频繁的检查点保存其完整状态。
在第一种情况下,如果 Spot 实例被回收,流量可以被路由到另一个实例,假设您已经为高可用性设置了冗余服务。在第二种情况下,如果 Spot 实例被中断,您的应用程序必须立即保存其当前状态,并在容量恢复后继续训练。
在本指南中,我将涵盖第二种用例,即使用开源深度学习框架(如 TensorFlow、PyTorch、MXNet 等)的深度学习培训工作的 Spot 实例。
快速回顾亚马逊 SageMaker 如何开展深度学习培训
我先说亚马逊 SageMaker 是如何运行深度学习训练的。这一背景对于理解 SageMaker 如何管理 Spot 训练以及备份您的检查点数据和恢复训练非常重要。如果你是亚马逊 SageMaker 用户,这应该是一个快速提醒。
你的职责:

开发您的培训脚本并将其提供给 SageMaker SDK Estimator 函数,Amazon SageMaker 会处理剩下的工作
- 使用 TensorFlow、PyTorch、MXNet 或其他支持的框架编写培训脚本。
- 编写一个 SageMaker Python SDK Estimator 函数,指定在哪里可以找到您的训练脚本,在什么类型的 CPU 或 GPU 实例上进行训练,在多少个实例上进行训练(对于分布式),在哪里可以找到您的训练数据集,以及在亚马逊 S3 的哪里可以保存训练好的模型。
亚马逊 SageMaker 的职责:

亚马逊 SageMaker 培训工作流程
亚马逊 SageMaker 将管理基础设施细节,所以你不必这样做。亚马逊 SageMaker 将:
- 将您的培训脚本和依赖项上传到亚马逊 S3
- 在完全受管的群集中调配指定数量的实例
- 提取指定的 TensorFlow 容器映像,并在每个实例上实例化容器。
- 从亚马逊 S3 下载训练代码到实例中,并使其在容器中可用
- 从亚马逊 S3 下载训练数据集,并使其在容器中可用
- 跑步训练
- 将训练好的模型复制到亚马逊 S3 的指定位置
运行亚马逊 SageMaker 管理的现场培训
Spot 实例可以被抢占,并且只需 2 分钟通知就可以终止,因此经常检查训练进度非常重要。谢天谢地,亚马逊 SageMaker 将管理其他一切。它会自动将您的培训检查点备份到亚马逊 S3,如果培训实例因容量不足而终止,它会持续轮询容量,并在容量可用时自动重新开始培训。
Amazon SageMaker 会自动将您的数据集和检查点文件复制到新的实例中,并将其提供给 docker 容器中的训练脚本,以便您可以从最新的检查点恢复训练。

亚马逊 SageMaker 将自动备份和同步检查点文件到亚马逊 S3
让我们来看一个例子,看看你如何准备你的培训脚本,使现场培训准备就绪。
亚马逊 SageMaker 通过 TensorFlow 和 Keras 管理现场培训
为了确保您的训练脚本能够利用 SageMaker 管理的 Spot 实例,您需要实现:
- 频繁节省检查点和
- 从关卡恢复训练的能力。
我将展示如何在 Keras 中进行这些更改,但是您可以在另一个框架中遵循相同的步骤。
步骤 1:保存检查点
亚马逊 SageMaker 会自动备份和同步你的训练脚本生成的检查点文件到亚马逊 S3。因此,您需要确保您的训练脚本将检查点保存到运行训练的 docker 容器上的本地检查点目录中。保存检查点文件的默认位置是/opt/ml/checkpoints,Amazon SageMaker 会将这些文件同步到特定的 Amazon S3 存储桶。本地和亚马逊 S3 检查站的位置都是可定制的。

将您的检查点本地保存到/opt/ml/checkpoints(路径是可定制的),Amazon SageMaker 会将其备份到 Amazon S3
如果你正在使用 Keras,这是非常容易的。创建 ModelCheckpoint 回调类的一个实例,并通过将其传递给 fit()函数将其注册到模型中。
完整的实现可以在这个文件中找到:https://github . com/shashankprasanna/sagemaker-spot-training/blob/master/code/cifar 10-training-sagemaker . py
以下是相关摘录:
请注意,我正在通过initial_epoch,这是您通常不会在意的。这让我们可以从某个纪元开始恢复训练,当你已经有了检查点文件时,这将会很方便。
步骤 2:从检查点文件恢复
当 spot 容量在中断后重新可用时,Amazon SageMaker 将:
- 启动新的 spot 实例
- 用您的训练脚本实例化 Docker 容器
- 将数据集和检查点文件从亚马逊 S3 复制到容器中
- 运行您的培训脚本
您的脚本需要实现从检查点文件恢复训练,否则您的训练脚本将从头开始训练。您可以实现如下所示的load_checkpoint_mode函数。它接受本地检查点文件路径(/opt/ml/checkpoints是缺省值),并返回从最新检查点加载的模型和相关的纪元编号。
有许多方法可以查询目录中的文件列表,从文件名中提取纪元编号,并用最新的纪元编号加载文件名。我使用os.listdir()和正则表达式。我相信你能想出更聪明、更优雅的方法来做同样的事情。
该文件中提供了完整的实现:https://github . com/shashankprasanna/sagemaker-spot-training/blob/master/code/cifar 10-training-sagemaker . py
以下是相关摘录:
第三步:指导亚马逊 SageMaker 进行现场培训
您可以从您的笔记本电脑、台式机、Amazon EC2 实例或 Amazon SageMaker 笔记本实例启动 Amazon SageMaker 培训工作。只要您安装了 Amazon SageMaker Python SDK,并且拥有运行 SageMaker 培训作业的正确用户权限。
要运行托管的现场培训作业,您需要为标准的 Amazon SageMaker Estimator 函数调用指定几个附加选项。
该文件中提供了完整的实现:https://github . com/shashankprasanna/sage maker-spot-training/blob/master/TF-keras-cifar 10-spot-training . ipynb
以下是相关摘录:
**train_use_spot_instances**:指示亚马逊 SageMaker 运行托管现场培训**checkpoint_s3_uri**:指示 Amazon SageMaker 将您的检查点文件同步到这个 Amazon S3 位置**train_max_wait**:指示 Amazon SageMaker 在此时间过后终止作业,并且现货产能不可用。
就是这样。这些都是你需要做出的改变,以大幅降低你的培训成本。
要监控您的培训工作并查看节省情况,您可以查看 Jupyter 笔记本上的日志或导航至Amazon SageMaker Console > Training Job,点击您的培训工作名称。一旦训练完成,你应该看到你节省了多少。例如,在一个p3.2xlarge GPU 实例上进行 30 个纪元的培训,我能够节省 70%的培训成本!

Amazon SageMaker 控制台中显示成本节约和其他有用信息的培训工作截图
在亚马逊 SageMaker 上模拟现场中断
如果出现中断,你如何知道你的训练是否能正常恢复?
如果您熟悉运行 Amazon EC2 Spot 实例,那么您知道可以通过终止 Amazon EC2 Spot 实例来模拟应用程序在 Spot 中断期间的行为。如果有能力,Spot fleet 将启动一个新实例来替换您终止的实例。您可以监视您的应用程序,检查它是否处理中断并正常恢复。不幸(还是幸运?),您不能手动终止 Amazon SageMaker 培训实例。你唯一的选择就是停止整个培训工作。
幸运的是,在恢复训练时,您仍然可以测试代码的行为。要做到这一点,首先要运行一个 Amazon SageMaker 管理的 Spot training,如前一节所述。假设你运行了 10 个纪元的训练。Amazon SageMaker 会将您的检查点文件备份到指定的 Amazon S3 位置 10 个时期。前往亚马逊 S3 验证检查点是否可用:

亚马逊 S3 的检查站,由亚马逊 SageMaker 自动为您备份
现在运行第二个训练运行,但是这次提供第一个任务的检查点位置给checkpoint_s3_uri
checkpoint_s3_uri = tf_estimator.checkpoint_s3_uri。
以下是来自 Jupyter 笔记本的相关摘录:
通过向checkpoint_s3_uri提供你之前工作的检查点,你是在告诉 Amazon SageMaker 将这些检查点复制到你新工作的容器中。然后,您的训练脚本将加载最新的检查点并继续训练。在下图中,你可以看到训练将从第 10 个纪元开始恢复。

从亚马逊 S3 自动复制的先前工作的最新检查点恢复训练
以这种方式模拟中断和 Amazon SageMaker 如何管理中断之间的关键区别在于,您正在创建一个新的培训任务来测试您的代码。在现场中断的情况下,Amazon SageMaker 将简单地恢复现有的中断作业。
拯救快乐!
我知道我没有必要说服你节约成本是一件好事。希望我已经向您展示了,使用 Amazon SageMaker 管理的现场培训可以轻松节省培训成本。通过最少的代码更改,您可以节省超过 70%的培训成本。你现在可以*静地运行 GPU 培训工作,而不会破产。
感谢阅读,我希望你喜欢这个指南。GitHub 上的所有代码和示例都可以在这里找到:
如果你对这篇文章有疑问,对如何改进它有建议,或者对新的指南和文章有想法,请在 twitter ( @shshnkp ), LinkedIn 联系我,或者在下面留下评论。拯救快乐!
快速介绍英特尔的 OpenVINO 工具包,用于更快的深度学习推理
让我们优化您的深度学习模型

由 Unsplash 上的 Clarisse Croset 拍摄的照片
深度学习模型正变得日益沉重,除了更快地训练它们,很多关注点也围绕着 IOT/ Edge 设备上实时用例的更快推理。因此,大约两年前,英特尔发布了 OpenVINO toolkit ,用于在英特尔硬件上优化深度学习模型的推理。
为了了解 OpenVINO 的所有基础知识,我把这篇文章分成了 3 个部分,根据你的兴趣,你可以选择下面的任何一个:
- 什么 是 OpenVINO
- 为什么/什么时候 打开葡萄酒
- 如何从 到构建 & 运行一个玩具 NN 上 OpenVINO
什么是 OpenVINO
英特尔的OpenVisualINNeural networkOoptimization(Open vino)toolkit 使视觉应用(或任何其他 DNN)能够在英特尔的处理器/硬件上更快地运行。
open vino toolkit 是一个全面的工具包,用于快速开发模拟人类视觉的应用程序和解决方案。基于卷积神经网络(CNN),该工具包扩展了英特尔硬件上的 CV 工作负载,最大限度地提高了性能。
-https://docs.openvinotoolkit.org/
直截了当地说,英特尔试图出售他们的底层处理器(CPU、igpu、vpu、高斯&神经加速器和FPGA),让你的 AI(视觉)应用运行得更快。
这不是为了更快的训练你的深度学习任务的工具包,而是为了更快的推断你已经训练好的深度神经模型。
OpenVINO toolkit 的工具主要组件有
关于工具包的完整细节,请查看。

英特尔 OpenVINO,来源
模型优化器(单个框架的一个.py文件)的任务是获取一个已经训练好的 DL 模型,并对其进行调整,以优化目标设备的执行。模型优化器的输出是您的 DL 模型的中间表示。
IR 是一组 2 个文件,描述您的 DL 模型的优化版本
*.xml-描述网络拓扑*.bin-包含权重(&偏差)的二进制数据
模型优化器的输出(IR 文件)是我们必须传递给推理机的,推理机在您的硬件上运行它。
因此,为了充分利用您的英特尔硬件,在生产环境中运行您的 ML(边缘、云……)应用,您只需生成您的 DL 模型的 IR 文件,并在推理引擎上运行,而不是直接在硬件上运行。
为什么/何时打开葡萄酒
如上所述,许多边缘/云应用已经在使用更先进的英特尔硬件/处理器/架构。
因此,人们想要转向 OpenVINO 的最重要原因之一是充分利用底层英特尔硬件。
除此之外,我还看到许多应用开发团队转向 OpenVINO,仅仅是为了英特尔已经为他们的边缘应用优化的预训练模型
[## open vino Toolkit 英特尔发行版的预训练模型
英特尔发布的 open vino toolkit 包括两组优化的模型,可以加快开发和…
software.intel.com](https://software.intel.com/content/www/us/en/develop/tools/openvino-toolkit/pretrained-models.html) [## opencv/open _ model _ 动物园
该存储库包括优化的深度学习模型和一组演示,以加快高性能…
github.com](https://github.com/opencv/open_model_zoo)
因此,您需要做的就是,下载一个预训练模型的 IR 文件,并将其与您的最终应用程序的推理引擎一起使用。
这种预训练模型的主要缺点是,当需要时,用你的服装数据重新训练这些模型并不总是容易的,因为不是所有提供的模型的重新训练/微调都有很好的记录。
如果你正在考虑使用一个 TF 模型动物园(或者类似的其他 DL 框架)或者构建/训练你自己的定制 Tensorflow(或者 PyTorch 等等..)模型,并期望很容易(甚至每次都可能)将其转换为所需的 IR 文件,但情况并非总是如此。
因此,在决定将您的任何应用程序移植到 OpenVINO 时,快速检查以下几点非常重要:
- 如果您从 IR 文件开始,那么您也有适当的理解/文档来重新训练所提供的 IR 文件背后的模型
- 如果您正在构建自己的 DNN 模型,您可以使用 Model Optimizer 将您的模型架构(尽管尚未训练)转换为 IR
只要您对以上两点都满意,您应该可以选择 OpenVINO 作为您的 DL 应用程序,但是如果不是,您可能需要重新评估您的决定。

如何使用 OpenVINO
如何在 OpenVINO 上构建和运行一个玩具 NN
理解 OpenVINO 如何工作的最佳方式是在其上构建、训练和推断你自己的玩具深度学习模型。请记住,只有在我们保存了 DL 模型之后,OpenVINO 才会出现。
因此,让我们构建一个我们想要解决的玩具线性回归问题,决定一个我们想要尝试的 DL 框架,我为这篇文章选择了 PyTorch,但可以随意获得相同的 TensorFlow 版本。
回归问题:Y = 2 X1 + 5 X2
让我们生成相同的样本数据
让我们建立一个快速神经网络来解决上述回归问题。
让我们训练我们的神经网络模型
在保存 PyTorch 模型并将其用于 OpenVINO 之前,请检查其预测输出
predicted = model.forward(torch.torch.FloatTensor(normed_test_data.values)).data.numpy()
print(model.state_dict())
现在,让我们首先保存您的 pyTorch 模型,以便我们可以在以后使用 model optimizer 获得模型的 IR 文件。
现在这就是我们需要 OpenVINO 的地方
所以在我们进入下一步之前,我们需要安装 OpenVINO 工具包。
选择打算用于开发或部署的操作系统。Linux*(支持 Ubuntu、CentOS 和 Yocto…
software.intel.com](https://software.intel.com/content/www/us/en/develop/tools/openvino-toolkit/choose-download.html)
安装完工具包后,让我们将保存的 PyTorch 模型转换成 IR 文件
现在,一旦我们有了 IR 文件,最后一步就是在 OpenVINO 推理引擎上运行我们的 NN 模型
注意:虽然下面的演示是在我的带英特尔 CPU 的笔记本电脑上运行的,但是您可以根据您的目标硬件更新设备。
恭喜你。
您已经成功地在 OpenVINO 上端到端地构建、训练并执行了一个玩具神经网络模型。
如果您需要查看示例代码,请查看下面的 repo:
[## AbhishekAshokDubey/OpenVino
在 GitHub 上创建一个帐户,为 AbhishekAshokDubey/OpenVino 开发做贡献。
github.com](https://github.com/AbhishekAshokDubey/OpenVino)
所以去吧,自己试试!
更多参考:
- https://docs.openvinotoolkit.org/
- https://www.youtube.com/watch?v=kY9nZbX1DWM
- https://github.com/AbhishekAshokDubey/OpenVino
- https://docs . openvinotoolkit . org/latest/_ docs _ IE _ DG _ introduction . html
- https://software . Intel . com/content/www/us/en/develop/tools/open vino-toolkit . html
CMIP6 快速介绍
气候数据科学
如何用 Python 轻松访问下一代气候模型?
耦合模型相互比较项目 (CMIP)是一项巨大的国际合作努力,旨在提高关于气候变化及其对地球系统和我们社会的影响的知识。它从 90 年代就开始了,今天我们正走向第六阶段(CMIP6),这将为政府间气候变化专门委员会(IPCC)的下一份评估报告(AR6)提供大量信息。
CMIP6 正在赞助几个不同的团体研究几个不同的科学问题,从遥远过去的气候到森林砍伐和土地使用变化的影响。完成后,整个项目预计将从 20 多个气候模型中释放大约 20 到 40pb 的数据。这就是你所谓的大数据,但是你怎么能尝试所有这些信息呢?

CMIP6 中的 MIPs。图片来源:辛普金斯(2017) 。
设置您的工具箱
import intake
import xarray as xr
import proplot as plot
import matplotlib.pyplot as plt
除了Matplotlib,这些包不是你通常在数据科学教程中看到的。另一方面,如果您想处理气象数据集,这些包是绝对重要的。
- 入口:共享和加载数据集的包。这将是您通过
[intake-e](https://intake-esm.readthedocs.io/en/latest/installation.html)[sm](https://intake-esm.readthedocs.io/en/latest/installation.html)目录与云的连接。 - Xarray :这是针对 n 维数据集的
Pandas,比如气候模型的输出。 - Proplot:Python 中数据可视化的下一件大事。说真的。
- Matplotlib:在任何 Python 生态系统中用于数据可视化的旧的好的标准包。
读取数据目录
# necessary url
url = "[https://raw.githubusercontent.com/NCAR/intake-esm-datastore/master/catalogs/pangeo-cmip6.json](https://raw.githubusercontent.com/NCAR/intake-esm-datastore/master/catalogs/pangeo-cmip6.json)"# open the catalog
>>> dataframe = intake.open_esm_datastore(url)
由于 Pangeo 的努力,现在您可以通过利用intake-esm包访问所有可用的 CMIP6 数据集。上面的df变量本质上是一个常见的DataFrame,您可能对Pandas很熟悉,因此您可以很容易地检查像列名这样的重要信息。
>>> dataframe.df.columns
Index(['activity_id', 'institution_id', 'source_id', 'experiment_id', 'member_id', 'table_id', 'variable_id', 'grid_label', 'zstore', 'dcpp_init_year'],dtype='object')
这些列中的每一列都是以 CMIP 项目的受控词汇表命名的,这种组织方式确保了数百万个数据集被整齐地保存,就像在一个巨大的图书馆中一样。你可以在这里读到更多关于这个的内容。
搜索数据集
弄乱了词汇表之后,获得想要的数据集就非常简单了。在这里,你将直接看到历史实验的 NCAR 模型每月*地面气温输出。对此的查询如下所示:
>>> models = dataframe.search(experiment_id='historical',
table_id='Amon',
variable_id='tas',
institution_id='NCAR',
member_id='r11i1p1f1')
这个搜索产生了一个intake_esm.core.esm_datastore数据类型,您可以使用它来最终获得您搜索的数据集。变量models给你更多关于它的信息,它基本上是一个类似字典的结构。
>>> models
pangeo-cmip6-ESM Collection with 1 entries:
> 1 activity_id(s)
> 1 institution_id(s)
> 1 source_id(s)
> 1 experiment_id(s)
> 1 member_id(s)
> 1 table_id(s)
> 1 variable_id(s)
> 1 grid_label(s)
> 1 zstore(s)
> 0 dcpp_init_year(s)
终于拿到数据了
为此,您首先需要从字典中获取数据集:
>>> datasets = models.to_dataset_dict()
Progress: |███████████████████████████████████████████████████████████████████████████████| 100.0%
--> The keys in the returned dictionary of datasets are constructed as follows:
'activity_id.institution_id.source_id.experiment_id.table_id.grid_label'
--> There are 1 group(s)
这产生了另一个dict,但是不同的是,现在您可以用datasets.keys()获得数据集的键:
>>> datasets.keys()
dict_keys(['CMIP.NCAR.CESM2.historical.Amon.gn'])>>> dset = datasets['CMIP.NCAR.CESM2.historical.Amon.gn']
好消息是dset是一个直接的xarray.core.dataset.Dataset,所以你可以通过强大的Xarray包很容易地使用它做任何你想做的事情,它特别适合处理网格气象数据。
绘图永远是有趣的部分,你可能熟悉地理空间投影的卡通包和其他几个应用程序。然而,这里您将使用新的Proplot包,因为它简单易用。一个简洁明了的情节如下:
fig, ax = plot.subplots(axwidth=4.5, tight=True,
proj='robin', proj_kw={'lon_0': 180},)
# format options
ax.format(land=False, coast=True, innerborders=True, borders=True,
labels=True, geogridlinewidth=0,)map1 = ax.contourf(dset['lon'], dset['lat'], dset['tas'][0,0,:,:],
cmap='IceFire', extend='both')ax.colorbar(map1, loc='b', shrink=0.5, extendrect=True)plt.show()
然后瞧!好看的罗宾逊投影中的*地面气温图。

最后的话
由于 Pangeo 社区的努力,CMIP6 比以往任何时候都更容易为任何想要尝试的人所用。复杂的气候模型现在对任何学生、公民科学家或全职科学家来说,只要有一个相对像样的互联网连接就可以使用。
这有着巨大的潜力,可以开启新的贡献,增进知识,并有助于实现气候抗御力和缓解战略。
PS:上面代码的 Jupyter 笔记本在这个资源库中可用。
谷歌地球引擎快速介绍
气候数据科学
云中卫星和气候数据财富的一瞥。
谷歌地球引擎 (GEE)是一个基于云的地理空间应用*台,拥有来自卫星的大量数据,包括来自著名的 Landsat 计划的数据和几个气候数据集。最棒的是,任何有足够兴趣和相对体面的互联网连接的人都可以使用该*台,使环境处理易于使用,并提供给最需要的人。
使用 GEE 有几种方法,每一种都有它的优点和缺点。虽然基于 Javascript 的代码编辑器可能是最常用的工具,而资源管理器非常适合休闲的外观,但在这里您将接触 Python API。与此同时,您可以随意探索可用数据集和许多成功的案例研究。
报名
基本上,任何拥有谷歌账户的人都可以注册使用 GEE,安装必要的软件包非常简单。注册后,可以用pip安装地球引擎 Python API:
pip install earthengine-api
之后,您需要在您的计算机上设置您的身份验证凭据。整个(不太长)过程在手册中有详细描述,鼓励您按照最后的描述测试安装。完成这些快速步骤后,您就可以开始收集大量可供探索的数据集了。
导入包
地球引擎包简称为ee,有了它,你就可以开始设置你的工具箱了。除了ee,在本教程中,你还需要用于交互式地图的[Folium](https://python-visualization.github.io/folium/index.html)和[geehydro](https://pypi.org/project/geehydro/),这是一个用于 GEE *台中淹没动力学的包,但非常有用,因为它模拟了 Javascript API 的一些功能。你也可以用pip安装这些其他的包:
pip install folium
pip install geehydro
要导入所有包:
import ee
import folium
import geehydrofrom datetime import datetime as dt
from IPython.display import Image
当您使用 API 时,您需要做的第一件事是初始化到服务器的连接:
# initialize the connection to the server
>>> ee.Initialize()
选择世界上的一个地区
有了卫星图像,你可以调查地球上的任何地方,甚至是你永远无法涉足(或者至少你不应该涉足)的偏远地方。在本教程中,您将探索巴西帕拉州 Ituna/Itatá 土著土地的最新状况。这片受保护的土地是一些孤立的土著部落的家园,也是亚马逊地区采矿、伐木和经营牧场绝对违法的地方之一。不幸的是,根据巴西国家空间研究所(INPE)的说法,这个地方也成为去年受巴西农业边界推进影响最大的地方,威胁到居住在那里的部落的生活和生物多样性。
借助Folium,你可以看看这个遥远的地方在哪里:
# the Ituna/Itatá Indigenous Land in Brazil.
Ituna_map = folium.Map(location=[-4.06738, -52.034], zoom_start=10)
>>> Ituna_map

与 Koatinemo 土著土地相邻的 Ituna/Itatá土著土地的边界。
Landsat 8 系列
Landsat 8 是长期运行的 Landsat 计划的最新成员,自 2013 年以来一直在轨道上运行,持续评估全球各地的地表状况。大地卫星图像在农学、环境保护和与土地使用有关的变化等领域的应用广为人知并已确立。
关于 Landsat 8 有几个技术细节,但你应该知道的基本知识是,它以中等分辨率收集多光谱空间信息,在电磁波谱的 11 个不同波段中,波段范围为 15 至 100 米分辨率。它还有 16 天的重访时间,这意味着每 16 天你就有一个特定地方的新图像。
使用ee,您可以通过一行代码访问整个 Landsat 8 集合:
landsat = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR")
每个系列都有自己的 id,您可以在 GEE 目录中找到它们。上图中, Landsat 8 表面反射等级 1 产品的 EE 片段 id 为"LANDSAT/LC08/C01/T1_SR",与目录中描述的相同。
这将为您提供整个世界的全部影像,因此您必须根据您感兴趣的区域和时间对其进行裁剪。对于该区域,您将使用纬度/经度信息和ee.Geometry.Rectangle在 Ituna/Itatá Land 周围设置一个矩形:
# setting the Area of Interest (AOI)
Ituna_AOI = ee.Geometry.Rectangle([-51.84448, -3.92180,
-52.23999, -4.38201])
.filterBounds()方法允许您选择上面定义的 AOI:
# filter area
landsat_AOI = landsat.filterBounds(Ituna_AOI)
另一个细节是,您可能对收集的整个时间跨度不感兴趣,而是对特定的时间段感兴趣。对于 Ituna/Itatá Land,您将选择该地区 2019 年旱季的一小段时间。为什么是旱季?云是卫星图像分析的一个主要问题,在亚马逊地区,这个问题更加严重,因此选择没有强降雨和云层覆盖的月份是一个不错的策略。此外,在这几个月里,森林砍伐非常猖獗,(人类引起的)火灾季节开始了。
# choose dates
landsat = landsat.filterDate('2019-07-01','2019-12-01')
一点元数据
你可以很容易地.getInfo()了解上面的 Landsat 集合或者任何你可能感兴趣的特定信息。对于上面量身定制的landsat_AOI系列,它将为您提供关于它的所有信息,这些信息可能会有点杂乱且过于专业。
>>> landsat_AOI.getInfo()

而且还不止这些。
可以更有选择性,过滤掉不想要的信息。假设您只需要知道在上面选择的时间段内您从 Landsat 获得了多少图像,只需:
>>> print('Total number:', landsat_AOI.size().getInfo())
Total number: 9
另一个例子是显示 Landsat 8 的每个波段是如何命名的,这对后续步骤很有用:
# the names of each Landsat 8 band
>>> landsat_AOI.first().bandNames().getInfo()['B1',
'B2',
'B3',
'B4',
'B5',
'B6',
'B7',
'B10',
'B11',
'sr_aerosol',
'pixel_qa',
'radsat_qa']
选择一个Image
可以更有选择性,根据特定标准设置系列。在本教程中,您将根据'CLOUD_COVER' id 从landsat_AOI集合中选择最不模糊的图像。
# the least cloudy image
least_cloudy = ee.Image(landsat_AOI.sort('CLOUD_COVER').first())# how cloudy is it?
>>> print('Cloud Cover (%):', least_cloudy.get('CLOUD_COVER').getInfo())
Cloud Cover (%): 0
方便的是,亚马逊地区 0%的卫星图像很难看到。这张很完美,但是是什么时候拍的?
# when was this image taken?
date = ee.Date(least_cloudy.get('system:time_start'))
time = date.getInfo()['value']/1000.>>> dt.utcfromtimestamp(time).strftime('%Y-%m-%d %H:%M:%S')'2019-08-11 13:36:22'
八月是亚马逊地区旱季最干燥的月份之一,所以它的干旱率为 0%也就不足为奇了。
可视化卫星图像
使用卫星影像进行分析时,通常的做法是组合不同的波段。由于每个波段代表电磁波谱的一部分,由于植被、水、土壤等类型的光谱特征,将它们组合起来可以看到同一表面的不同视图。最简单的方法是红绿蓝(RGB)合成,当使用 Landsat 8 影像时,您需要使用波段 4(红色)、3(绿色)和 2(蓝色)。
基于 Javascript 的代码编辑器很容易允许使用Map.AddLayer()进行交互式可视化,但不幸的是,这对于标准 Python API 是不可用的。使用来自ee的.getThumbURL()模块和来自IPython的本地.display()模块可以制作一个简单的静态地图:
parameters = {'min': 0,
'max': 1000,
'dimensions': 512,
'bands': ['B4', 'B3', 'B2'],
'region': Ituna_AOI}
>>> Image(url = least_cloudy.getThumbUrl(parameters))

在 Ituna/Itatá土著土地上非法砍伐森林的进展。
parameters变量存储了使用ee分析卫星图像时可以探索的选项。它的工作方式与 Javascript API 的工作方式相同,我们鼓励你组合不同的波段并对其进行调整,以获得相同数据的不同可视化效果。
出于本教程的目的,简单的 RGB 合成图像很好地调查了非法伐木和其他行为的发展,而这些行为是不应该发生的。在上面的图片中,所有不是强烈绿色的东西都是违法的。这发生在 2019 年 8 月中旬,但不幸的是,作为 2020 年的 2 月,情况要糟糕得多。
归一化差异植被指数(NDVI)
有更多的定量方法来调查土地使用变化和森林砍伐。也许最著名的方法是使用归一化差异植被指数(NDVI ),它广泛存在于一些土地管理、农业和保护研究中。
NDVI 需要*红外(NIR)和可见(VIS)波段的信息,对于大地卫星 8 号来说,这是波段 5 和 4。计算简单,NDVI =(*红外-可见光)/(*红外+可见光),但从中获得的见解可能是巨大的。在一些更经典的研究中,它的范围是-1 比 1 或 0 比 1。值为负或 0 的像素可能是许多事物,如河流或严重退化的土地,而接* 1 的像素肯定是植被密集的部分。
由于这是一种常见的做法,您可以快速计算任何归一化差异指数( NDVI 是而不是唯一的)与.normalizedDifference:
ndvi = least_cloudy.normalizedDifference(['B5', 'B4'])
在这之后,你肯定会希望在一张漂亮的地图上看到它。虽然您已经知道了原生方式,但是geehydro允许您使用Folium 绘制交互式地图,就像代码编辑器使用Map.AddLayer()一样:
palette = ['red', 'yellow', 'green']ndvi_parameters = {'min': 0,
'max': 1,
'dimensions': 512,
'palette': palette,
'region': Ituna_AOI}Ituna_map.addLayer(ndvi, ndvi_parameters)
Ituna_map

Ituna/Itatá土著土地的 NDVI 互动地图。
使用geehydro允许 Javascript 和 Python API 之间更大程度的可复制性,在两种不同的人之间架起了一座桥梁。如果你对 Javascript 一窍不通,现在你可以理解互联网上的几个 GEE 教程中的代码了。
最后的话
GEE 是一个很好的学习如何使用卫星图像的工具,可能性是巨大的。土地使用变化研究、可持续农业和对敏感地区(如 Ituna/Itatá)的监测,只要有良好的互联网连接和足够的兴趣,任何人都可以参与其中。灵活的 Python API 和geehydro的有用性可以结合起来,快速搭建*台使用。有了它,大量不同的数据集和丰富的信息随时可以被发现。活着是多么美好的时光。
本教程的交互式 Jupyter 笔记本在我的 气候数据科学 资源库中免费提供。
购物篮分析快速入门
带有真实世界演示的初级读本

零售商可以获得前所未有的购物者交易量。随着购物习惯变得越来越电子化,每次购物的记录都整齐地存储在数据库中,随时可供读取和分析。有了这样一个数据仓库,他们可以发现消费者的行为模式。
什么是购物篮分析?
购物篮分析是一组关联性计算,旨在确定哪些商品一起销售。例如,杂货店可以使用购物篮分析来确定消费者通常同时购买热狗和热狗面包。
如果你曾经去过一个在线零售商的网站,你可能会在一个产品的页面上看到这样的推荐:“购买了这个产品的顾客也购买了”或者“顾客一起购买这些”。更有可能的是,这家在线零售商进行了某种市场购物篮分析,将这些产品联系在一起。
精明的零售商可以利用这一知识来为定价、促销和商店布局决策提供信息。前面提到的杂货店可能会出售热狗,但会增加热狗面包的利润。顾客会买更多的热狗,感觉好像找到了便宜货,而商店会卖出更多的产品,增加他们的收入。
购物篮分析背后的数学
对于所购买商品的每一个组合,都会计算三个关键的统计数据:支持度、信心和提升度。
支持度是一个项目相对于其他所有购买项目的普遍受欢迎程度。在杂货店,牛奶会有很高的支持度,因为许多购物者每次旅行都会买。支持以 0 到 1 之间的数字给出。数学上:

置信度是购买了产品 A 的顾客也购买了产品 b 的条件概率。棉花糖和全麦饼干之间的置信度可能很高,因为它们通常是一起购买的。置信度是一个介于 0 和 1 之间的数字。数学上:

Lift 是购买产品 A 时,产品 B 的销量增加。汉堡肉饼和小圆面包之间可能有很大的差距,因为随着肉饼的销量增加,它们会带动小圆面包的销量。数学上:

与其他两种方法相比,Lift 有点不同寻常。升力不是一个介于 0 和 1 之间的值,而是由它与 1:
- Lift = 1 表示产品之间没有关系
- lift > 1 表明产品之间存在正相关关系
- lift < 1 表示产品之间存在负相关关系
Apriori 算法

克莱顿·罗宾斯在 Unsplash 上的照片
到目前为止,执行购物篮分析最常用的方法是 Apriori 算法。该算法由 Agrawal 和 Srikant 于 1994 年首次提出,由于其对零售商有意义地跟踪交易关联的影响,已经变得具有历史重要性。
虽然 Apriori 算法仍然有用并被广泛使用,但它在较大数据集上的计算时间也很长。幸运的是,大多数实现都提供了信心和支持的最小参数,并对每个事务的项目数进行了限制,以减少处理时间。
为了演示,我将使用名为 高效的 Python 实现——apriori。注意,这个库是为 Python 3.6 和 3.7 设计的。老版本的 Python 可能会使用apy ori,支持 2.7 和 3.3–3.5。
数据处理
为了展示 Apriori 算法的应用,我将使用在 Kaggle 上提供的一个面包店的交易数据集。
*import pandas as pd
import numpy as np# Read the data
df = pd.read_csv("BreadBasket_DMS.csv")# eliminate lines with "NONE" in items
df = df[df["Item"] != "NONE"]*
在通常导入 Pandas 和 Numpy 来帮助处理数据之后,先前保存的 CSV 文件被读取到数据帧中。
有几行数据在 Item 列中包含“NONE ”,这不是特别有用,所以这些数据被过滤掉了。
*# Create and empty list for data processing
transaction_items = []# Get an array of transaction numbers
transactions = df["Transaction"].unique()for transaction in transactions:
# Get an array of items per transaction number
items = df[df["Transaction"] == transaction]["Item"].unique() # Add the item to the list as a tuple
transaction_items.append(tuple(items))*
与其他支持 Pandas 数据框的库不同,efficient-apriori 需要事务行作为一个列表中的一系列元组。
为了创建这种数据结构,需要收集一系列唯一的事务 ID 号。对于每个事务 ID,与该 ID 相关联的 Numpy 个项目数组被分组。最后,它们被转换成元组并放在一个列表中。
执行 Apriori 算法
*# import apriori algorithm
from efficient_apriori import apriori# Calculate support, confidence, & lift
itemsets, rules = apriori(transaction_items, min_support = 0.05, min_confidence = 0.1)*
导入库后,Apriori 算法可以放在一行中。请注意 min_support 和 min_confidence 参数,它们指定了要计算的最小支持值和置信度值。这些的实际值在不同类型的数据之间会有所不同。将它们设置得太高不会产生任何结果。将它们设置得太低会产生太多的结果,并且需要很长时间来运行。
这是一个需要反复试验才能确定的金发女孩问题。对于特别大的数据集,可能需要一些初步的支持计算来确定一个好的基线。
对于这个特定的数据集,大多数交易包含一个单一的项目购买。虽然这本身是一个有趣的结果,但这意味着支持和信心的最小值需要设置得相对较低。
*# print the rules and corresponding values
for rule in sorted(rules, key = lambda rule: rule.lift):
print(rule)*
最后,结果被放入规则变量中,该变量可能会被打印出来。结果应该如下所示:
*{Coffee} -> {Cake} (conf: 0.114, supp: 0.055, lift: 1.102, conv: 1.012)
{Cake} -> {Coffee} (conf: 0.527, supp: 0.055, lift: 1.102, conv: 1.103)*
为了更好地理解输出,请看指定咖啡和蛋糕规则的两行。这两条线都给出了信心(conf)、支持(supp)和升力,但是两条线之间的顺序被交换了。
在第一行中,概率被测量为以咖啡为条件的蛋糕,而在第二行中,概率被测量为以蛋糕为条件的咖啡。换句话说,在买了咖啡的顾客中,没有多少人还买了蛋糕。然而,在购买蛋糕的顾客中,大多数也购买了咖啡。这就是置信度值不同的原因。
这是一个微妙但重要的区别,需要理解。
此外,提升值大于 1,表明蛋糕的销售促进了咖啡的销售,反之亦然。
了解这一点后,面包店可以通过以下方式利用这一分析:
- 将咖啡和蛋糕更紧密地放在菜单板上
- 提供一餐蛋糕和一杯咖啡
- 开展蛋糕优惠券活动,推动咖啡销售
结论
市场篮子分析是一套计算方法,旨在帮助企业了解其销售中的潜在模式。某些互补商品经常一起购买,Apriori 算法可以隐藏它们。
了解产品销售如何应用于从促销、交叉销售到推荐的方方面面。虽然我给出的例子主要是零售驱动的,但任何行业都可以从更好地了解他们的产品如何移动中受益。
关于 KNN 的简短一课
对于初学者,由初学者

这与 KNN 无关。虽然现在想想,我猜这些树技术上来说都是邻居!(来源:作者)
如题所示,这里有一个关于如何在 SciKit-Learn 中构建一个简单的 KNN 模型的简短课程。我将使用这个数据集。它包含学生学习成绩的信息。
包括的特征有学生举手的次数、他们的性别、家长满意度、他们缺课的频率以及他们参与课堂讨论的频率。
每个学生被分成三个班级:高年级(H)、中等年级(M)和低年级(L)。我使用了其他特征来预测它们属于哪个类别。
仅供参考:
- 高,90–100
- 中等,70–89
- 低,0–69
好吧,酷!让我们开始吧。
库导入
**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**import** **seaborn** **as** **sns**
**import** **statsmodels.api** **as** **sm**
**from** **sklearn.model_selection** **import** train_test_split
**from** **sklearn.preprocessing** **import** StandardScaler
**from** **sklearn.neighbors** **import** KNeighborsClassifier
**from** **statsmodels.formula.api** **import** ols**from** **sklearn.metrics** **import** precision_score, recall_score,
accuracy_score, f1_score**import** **matplotlib.pyplot** **as** **plt**
%matplotlib inline
首先,您想要导入您将需要的所有库。有些人在过程的每个阶段导入每个库,但是我个人喜欢在开始的时候全部导入。
从技术上讲,我们不会真的使用 Seaborn 或 MatplotLib,但我喜欢把它们放在身边,以防万一我想在这个过程中可视化一些东西。
初始数据导入
df = pd.read_csv('xAPI-Edu-Data.csv')
df.head()

部分输出截图。
酷!数据一开始就很好。没有丢失的值,也没有异常值。然而,我们必须做少量的预处理来为我们的模型做好准备。
预处理
*# Dropping all unnecessary columns*
df = df.drop(['NationalITy', 'PlaceofBirth', 'StageID', 'GradeID',
'SectionID', 'Topic', 'Relation',
'ParentAnsweringSurvey'],
axis = 1,
inplace = False)
df.head()

输出截图。
在为 KNN 模型提供信息时,您只希望包含您实际上希望做出决策的特性。这似乎是显而易见的,但我认为值得一提。
*# Binary encoding of categorical variables*
df['gender'] = df['gender'].map({'M': 0, 'F': 1})
df['Semester'] = df['Semester'].map({'F': 0, 'S': 1})
df['ParentschoolSatisfaction'] = df['ParentschoolSatisfaction'].map({'Good': 0, 'Bad': 1})
df['StudentAbsenceDays'] = df['StudentAbsenceDays'].map({'Under-7': 0, 'Above-7': 1})
df.head()

输出截图。
如果你从来没有这样做过,可能不太明显的是,你必须编码你的分类变量。想想也有道理。一个模型并不能真正诠释‘好’或‘坏’,但它可以诠释 0 和 1。
*# Check for missing values*
df.isna().sum()

输出截图。
我知道我已经说过,我们没有任何缺失的价值观,但我只是想彻底了解一下。
*# Create a new dataframe with our target variable, remove the target variable from the original dataframe*
labels = df['Class']
df.drop('Class', axis = 1, inplace = **True)**
然后—
df.head()

截图输出。
labels.head()

输出截图。
接下来,我们希望将目标特征与预测特征分开。我们这样做是为了给我们的数据创建一个训练/测试分割。说到!
训练/测试分割
X_train, X_test, y_train, y_test = train_test_split(df, labels,
test_size = .25,
random_state =
33)
*我意识到上面的格式很糟糕,我只是想让它对于这篇中型文章来说更易读。
缩放数据
下一部分提出了两个要点:
- 你需要缩放数据。如果不这样做,绝对值较大的变量将在模型中被赋予更大的权重,而没有真正的原因。我们有二进制编码的特征(0,1),但我们也有学生举手次数的特征(0-80)。我们需要把它们放在同样的尺度上,这样它们在模型中就有同样的重要性。
- 您必须在执行训练/测试分割后缩放数据。如果你不这样做,你会有泄漏,你会使你的模型失效。要获得更全面的解释,请查看 Jason Browlee 的这篇文章,他拥有大量关于机器学习的惊人资源。
好消息是,这非常容易做到。
scaler = StandardScaler()
scaled_data_train = scaler.fit_transform(X_train)
scaled_data_test = scaler.transform(X_test)
scaled_df_train = pd.DataFrame(scaled_data_train, columns =
df.columns)scaled_df_train.head()

输出截图。
太棒了。简单的柠檬榨汁机,我们的数据是成比例的。
符合 KNN 模型
*# Instantiate the model*
clf = KNeighborsClassifier()
*# Fit the model*
clf.fit(scaled_data_train, y_train)
*# Predict on the test set*
test_preds = clf.predict(scaled_data_test)
真的就这么简单。现在,我们想看看我们的基线模型表现如何。
评估模型
**def** print_metrics(labels, preds):
print("Precision Score: **{}**".format(precision_score(labels,
preds, average = 'weighted')))
print("Recall Score: **{}**".format(recall_score(labels, preds,
average = 'weighted')))
print("Accuracy Score: **{}**".format(accuracy_score(labels,
preds)))
print("F1 Score: **{}**".format(f1_score(labels, preds, average =
'weighted')))print_metrics(y_test, test_preds)

输出截图。
就这样,几乎不费吹灰之力,我们就创建了一个预测模型,能够以 75.8%的准确率将学生分类到他们的学术表现类别。还不错。
我们或许可以通过调整模型的参数来改善这一点,但我将把这留给另一篇文章。
快乐学习。😁
快速浏览澳洲的新冠肺炎
澳大利亚在病例、死亡和检测方面的表现如何

皮沙贝
新冠肺炎扰乱了整个世界,影响了我们生活中的几乎所有事情。虽然澳洲是一个远离一切的“大岛”,但它没有逃过世界卫生组织(世卫组织)3 月 11 日宣布的疫情。自 2019 年 12 月中国武汉报告冠状病毒爆发以来,它已在几个月内蔓延至全球危机。
截至 2020 年 4 月 15 日,全球确诊病例总数已达 198 万例,死亡人数超过 12.66 万。澳大利亚记录了 6440 例确诊病例和 63 例死亡。为了了解澳大利亚与世界其他国家相比的新冠肺炎,我们调查了澳大利亚与其他国家在容量、速度和测试方面的比较数据。
数据
我们使用了来自人道主义数据交换( HDE )的时间序列和人口数据集。它包含从 1 月 22 日记录的病例数,由约翰·霍普金斯大学系统科学和工程中心汇编。
- 数据集追踪全球受新冠肺炎影响的人数,包括确诊、康复和死亡病例。
- 跟踪各国开展的测试数量的数据集。
鉴于 HDE 的数据集没有 1 月 22 日之前中国的数据,我们使用了 1 月 1 日至 21 日中国记录的病例数据,数据来源于“2019 年新型冠状病毒疾病爆发的流行病学特征(新冠肺炎)-中国,2020 年”(《中国疾病预防控制中心》,CCDC 周刊/第 2 卷/第 x 期)。
将澳洲与较早或同时出现新冠肺炎病例的国家进行比较
2020 年 1 月 26 日,澳大利亚记录了首例确诊病例。在澳洲之前或同时,总共有 12 个国家报告了新冠肺炎病例。除中国之外,所有其他 11 个国家从第 1 天起报告的病例数(1-5)处于类似规模。如下图所示,我们从第一天开始绘制了所有国家的地图。截至 2020 年 4 月 15 日的第 80 天,澳大利亚在确诊病例数方面在这些 13 个国家中排名第7,这使澳大利亚处于这些国家的中间。
美国、法国、加拿大与澳大利亚正处于相同的转折点,在第一例病例传入该国 30 天后,病例数量急剧增加。有趣的是,直到第 55 天左右(2020 年 3 月 25 日),加拿大和澳大利亚都在同一轨迹上。3 月 23 日实施了第一阶段限制,一个月后实施了第二阶段限制。从那以后,加拿大在人数上继续增长,与美国和法国一样,但是澳大利亚开始变*曲线。
与新加坡、台湾和越南等其他几个较早推出全国性社会距离措施的国家相比,澳大利亚在没有政府管理措施的情况下,肯定在第二个月就超过了他们的速度。然而,我们可以看到,差距在第三个月越来越小,而澳大利亚花了很大的努力来拉*曲线。

将澳洲与新冠肺炎早些时候或同时死亡的国家进行比较
3 月 4 日,澳大利亚记录了首例死亡病例。总共有 10 个国家在澳洲之前或同时报告了新冠肺炎的死亡。如下图所示,我们从第一天开始绘制了所有国家的地图。在这 11 个国家中,截至 2020 年 4 月 15 日的第 46 天,澳大利亚在死亡人数上排名第第 9,澳大利亚排名垫底。
像美国、意大利和法国这样的国家从死亡报告开始就一直在上升,并且在进入第二个月时仍在上升,数量更大,速度更快。有趣的是,日本和澳大利亚的死亡人数几乎相同。
台湾的人口与澳大利亚相似,但人口密度要高得多,但他们设法保持了异常低的死亡人数。根据台湾国立卫生研究院传染病主任的说法,台湾已经采取了措施,并利用了他们以前应对 SARS 的经验。

将澳大利亚与有更多或相同确诊病例的国家进行比较
截至 4 月 15 日,即澳大利亚自首例确诊病例以来的第 80 天,共有 30 个国家报告了比澳大利亚更多的确诊病例。鉴于已经有 6 个国家比澳大利亚更早或与澳大利亚同时发现新冠肺炎病例,其余 24 个国家都在本国发现了首例病例,但病例数量的增长速度比澳大利亚快得多。例如,土耳其在一个月内就达到了与中国几乎相同的确诊病例数。大量国家比澳大利亚更快地出现更多病例,这可能表明澳大利亚在总体上控制传播方面行动较早。

将澳大利亚与死亡人数更多或相同的国家进行比较
如前所述,有 10 个国家比澳大利亚更早或同时报告死亡,其中 8 个国家的死亡人数比澳大利亚多。截至 4 月 15 日,这是澳大利亚自第一例确诊以来的第 46 天,另有 43 个国家在报告第一例死亡后的短时间内报告的死亡人数超过澳大利亚。例如,比利时在一个月内报告的死亡人数与中国几乎相同,而不是两个月。大多数 T2 国家报告的死亡人数以更快的速度急剧上升。这可能表明,与这些国家的其他卫生保健系统相比,澳大利亚卫生系统在处理感染病例方面总体上处于更好的条件或状况。

将澳大利亚与测试排名靠前的国家进行比较
测试已经成为控制传播和确定开放国家或缓解社会距离措施的准备状态的关键措施。为了了解澳大利亚的情况,我们看一下截至 4 月 15 日的快照数据,如下图所示,澳大利亚在已进行或记录的测试总数方面排名第第 8。
美国、意大利、法国和英国在检测数量和确诊病例之间的比例相似。这些国家做了大量的检测,也有非常多的确诊病例。有趣的是,韩国和澳大利亚在这一比例方面更接*,但有大量的检测和少量的确诊病例。值得一提的是,在这些做大量检测的顶尖国家中,澳大利亚是死亡人数最少的一个。

为了比较澳大利亚和世界上每百万人口检测数排名前 10 位的国家,见下图。除了德国和意大利,所有其他国家在每百万人口的检测数量上都从榜首滑落。总的来说,澳大利亚总的测试次数和每百万人的测试次数表明,与其他国家相比,我们在测试方面做得相当好。

全部的
截至 2020 年 4 月 15 日,澳大利亚共有 6440 例确诊病例,共有 63 例死亡,病死率为 0.97%。这远低于 6.39%的世界*均水*。没有世界级的医疗保健系统和政府采取的严格措施,这是不可能的。当然,还有许多其他因素,如测试和财务方案等,对澳大利亚的曲线变*产生了很大影响。
我们所有人都在帮助澳洲对抗新冠肺炎并保持团结方面扮演着重要的角色!
吉塔达斯 是计算机视觉和机器学习领域的研究者和开发者。如果我们能帮助人们了解新冠肺炎,Gita 和我都有同样的热情探索数据,并与新冠肺炎一起获得洞察力。
请随时访问GitHub repo,我们欢迎您的反馈和意见。
这篇文章在 LinkedIn 帖子 上也有。
编者注: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
5 种 scikit-learn 分类算法的快速概述
了解如何使用这五种算法,只用几行代码就能构建模型

图片来自皮克斯拜
简介
在本文中,我将向您展示如何使用 scikit- learn 为分类目的构建快速模型。
我们将使用具有三个不同目标值的 Iris 数据集,但是您应该能够对任何其他多类或二进制分类问题使用相同的代码。
您将学习如何拆分模型的数据,如何使算法适合五种不同类型模型的数据,然后使用分类报告对结果进行简要评估。
我们将在这里使用的算法是:
逻辑回归
KNN
决策图表
随机福里斯特
梯度推进
是时候开始了!
加载数据和快速数据浏览
让我们使用以下代码加载 Iris 数据集:
from sklearn.datasets import load_iris
import pandas as pddata = load_iris()
df = pd.DataFrame(data['data'], columns=data['feature_names'])
df['species'] = data['target']
df.head()

这个数据集中只有五列。最后一栏物种是我们将试图预测的,我们将称之为目标。所有其他列将作为特征,并使用它们来进行预测。
在您自己的数据集中,清楚地确定什么是目标,什么是特征是很重要的。
让我们调用 info()函数来进一步了解我们的数据:
df.info()

如您所见,只有 150 个条目,任何一列都没有丢失值。此外,所有值要么是浮点数,要么是整数。
然而,从数据集描述中,我知道物种不是一个连续变量,而是一个分类变量(因此分类不是回归)。
我们可以检查这一点,并通过 value_counts()函数查看目标值是如何分布的:
df.species.value_counts()2 50
1 50
0 50
Name: species, dtype: int64
我们可以看到,物种列只有三个值:0、1 和 2,并且所有的类都有相同数量的例子:每个类 50 个。就目标值分布而言,这是一个完美*衡的数据集。
由于我们的数据是“非常干净”,没有缺失值或分类变量作为特征,并且在目标方面*衡良好,我们可以实际进入建模部分。
***如果您的数据有缺失值,您必须通过删除或用*似值替换它们来处理。此外,如果有分类变量作为特征,那么就需要一键编码。
将数据集分为训练和测试
在将数据拟合到模型之前,有必要将数据分为训练和测试部分。这一点很重要,因为您不应该在对其进行训练的相同数据上测试您的模型。
幸运的是,使用 scikit-learn 中的 train_test_split 函数很容易做到这一点:
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(df.drop('species', axis=1), df.species ,test_size = 0.2, random_state=13)
由于此功能,我们现在将数据分为 4 个部分:
x _ 火车
x _ 测试
y _ 火车
y _ 测试
x 前缀是指保存特征信息的数据部分,y 前缀的数据保存数据的目标部分。你可以从我之前写的文章中了解更多关于这个函数是如何工作的。
从现在开始,我将在列车部分(x_train 和 y_train)拟合模型,并在测试部分(x_test 和 y_test)进行测试。
我们现在可以安装我们的第一个模型。
逻辑回归
让我们从实现逻辑回归的第一个模型开始。
我们将从 scikit-learn 线性模型包中导入模型,并使用 fit()函数训练模型,然后使用 predict()函数对测试集进行预测:
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression().fit(x_train, y_train)
predictions = clf.predict(x_test)
如您所见,我使用了 fit()函数训练数据部分(x 和 y 部分),为了进行预测,我仅使用了 x_test。我现在可以将预测值与实际目标值进行比较(y_test)。
直到现在我也不知道我的模型是否做了正确的预测。为了对此进行评估,我将使用 sci-kit learn 中的 classification_report:
from sklearn.metrics import classification_report
print(classification_report(y_test, predictions))

分类报告将我们对目标变量的预测与实际类别进行比较。我希望你们主要关注的指标是准确性。在这种情况下,我们已经正确预测了 97%的类,还不错。
在本文中,我不打算详细解释分类报告,但我想强调的是,在比较模型和准确性的同时,关注精确度、召回率和 f 值是非常重要的。为此,我打印了整个报告,而不仅仅是准确性。我认为这是一个方便的功能,可以将所有这些指标汇总在一起。如果你想了解更多关于精确度、召回率、f 分数的知识,也想学习阅读混淆矩阵,请查看这篇文章。
回到准确性…看起来简单的逻辑回归允许我们获得 97%的正确预测。毫无疑问,这是一个很好的起点,如果我对此感到满意,我就可以用它来高精度地预测花卉种类。
K-最*邻(KNN)
现在让我们在相同的数据上训练K-最*邻:
from sklearn.neighbors import KNeighborsClassifier
neigh = KNeighborsClassifier()
neigh.fit(x_train, y_train)
predictions = neigh.predict(x_test)
我们已经为算法使用了默认参数,所以我们正在寻找五个最*的邻居,并且在估计类预测时给它们相等的权重。
您现在可以调用分类报告:
from sklearn.metrics import classification_report
print(classification_report(y_test, predictions))

具有默认值的 KNN 似乎比逻辑回归略差。准确率从 0.97 下降到 0.9,*均召回率、准确率和 f 值似乎也降低了。
我们可以和 KNN·帕拉姆一起玩,看看是否可以改进。可能的改进包括改变用于预测的邻居数量或使用考虑邻居邻*性的不同权重。
决策树
让我们看看另一种分类算法。我现在将调用一个带有默认参数的决策树来执行:
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(random_state=0)
clf.fit(x_train, y_train)
predictions = clf.predict(x_test)
我提供的唯一参数是一个随机状态。这就是为什么我的结果是可重复的。
from sklearn.metrics import classification_report
print(classification_report(y_test, predictions))

正如你所看到的,这个决策树在测试数据集上表现得非常好。我预测所有的类都是正确的!
乍一看似乎很棒,但我可能在这里太适合了。我可能应该使用交叉验证来调整模型参数,以防止过度拟合。
以下代码仅对训练数据执行 10 重交叉验证,并打印出每一重的准确度:
from sklearn.model_selection import cross_val_score
cross_val_score(clf, x_train, y_train, cv=10)array([1\. , 0.92307692, 0.91666667, 0.91666667, 0.91666667,
1\. , 0.91666667, 1\. , 1\. , 0.90909091])
通过检查输出,我可以看到,在一些数据拆分中,我确实获得了 100%的准确性,但有相当多的数据拆分的准确性几乎低了 10%。原因是我使用的数据集非常小。仅仅一个实例的错误分类就会导致巨大的准确性波动。
***一般来说,正如我在这里演示的那样,使用默认算法构建第一个模型是没问题的,但下一步应该是使用交叉验证运行参数。
随机福里斯特
让我们尝试用它的默认参数调用随机森林分类器。
您可以将随机森林视为一组决策树。森林实际上是通过使用许多决策树,然后对结果进行*均来构建的。我不打算在这里解释算法的细节,而是用它的默认参数调用它。
from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(random_state=0)
clf.fit(x_train, y_train)
predictions = clf.predict(x_test)
让我们运行一个分类报告:
from sklearn.metrics import classification_report
print(classification_report(y_test, predictions))

我们这里有 93%的准确率。我们已经看到了以前的分类算法的一些更好和一些更差的结果。
为了调整和改进算法,您可以调整估计器的数量、深度和结构。这需要学习更多关于树和算法本身如何工作的知识。有很多关于这方面的文章,所以我建议你搜索一下,如果你想了解更多的话。
梯度增强
让我们试试我们将在本文中提出的最后一个算法:梯度推进分类器。这是另一种树型算法,对于许多机器学习问题非常有效。
让我们使用 scikit-learn 函数调用 is:
from sklearn.ensemble import GradientBoostingClassifier
clf = GradientBoostingClassifier(random_state=0)
clf.fit(x_train, y_train)
predictions = clf.predict(x_test)
并运行分类报告:
from sklearn.metrics import classification_report
print(classification_report(y_test, predictions))

这是另一个得分很高的算法。我们已经达到了 97%的准确率。
看起来我们所有的模型都做了相当不错的预测,即使使用了默认的未调整参数!
比较分类算法
你可以看到,我们已经提出了五个算法,它们都在测试集上取得了很高的准确率。该算法的准确率从 90% (KNN)到 100%(决策树)。
理论上,这种算法中的任何一种都可以用来以相当高的准确度(超过 90%)预测花卉香料。
因为我们已经做了相当快速的分析,并且没有深入每个实现的细节,所以很难决定哪个算法是最好的。这将需要对每个算法实现进行更多的分析和调整。
总结
您已经大致了解了五种基本分类算法,并学习了如何使用默认参数调用它们。阅读完本文后,您还应该能够使用快速分类报告来评估它们的性能。
下一步应该是更多地了解每种算法,并对其进行调整以提高性能和避免过度拟合。
最初发表于 about datablog . com:5 个 scikit-learn 分类算法的快速概述,2020 年 5 月 19 日。**
PS:我正在 Medium 和aboutdatablog.com上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的 邮件列表 以便在我每次写新文章时得到通知。如果你还不是中等会员,你可以在这里加入**。****
下面还有一些你可能喜欢的帖子
学习如何使用折线图、散点图、直方图、箱线图和其他一些可视化技术
towardsdatascience.com](/9-pandas-visualizations-techniques-for-effective-data-analysis-fc17feb651db) [## python 中的 lambda 函数是什么,为什么你现在就应该开始使用它们
初学者在 python 和 pandas 中开始使用 lambda 函数的快速指南。
towardsdatascience.com](/what-are-lambda-functions-in-python-and-why-you-should-start-using-them-right-now-75ab85655dc6) [## 当你开始与图书馆合作时,7 个实用的熊猫提示
解释一些乍一看不那么明显的东西…
towardsdatascience.com](/7-practical-pandas-tips-when-you-start-working-with-the-library-e4a9205eb443)***
对数据科学和研究导向的专业人员、方法和结果的快速调查
这项民意调查旨在评估在求职过程中,在数据科学和其他研究相关专业领域工作的专业人士中,薪资有多重要
介绍
在与现任、前任和有抱负的数据科学家交谈时,我听到了一个常见的抱怨。招聘人员会根据你的薪资历史或你的薪资期望来筛选你。
招聘人员这样做我很困扰,不仅是为了应聘者,也是为了招聘人员。为了进一步推动对话,我利用社交媒体进行了一次民意调查。
我在 2020 年 10 月底和 11 月初进行了这项民意调查。我在 LinkedIn、Twitter 和脸书上发布了调查结果。我使用了标签、关键词和论坛,我认为它们会鼓励那些从事数据科学或其他研究导向职业的人做出回应。我还(通过 Twitter)推广了这项调查,以增加回复数量。
伴随民意调查的提示和帖子要求受访者在决定如何回答时考虑他们当前或最*的求职情况。
结果

Image credit:作者对社交媒体投票结果的可视化。
这些民意调查收集了 343 份答复。Twitter 有 269 条,脸书有 47 条,LinkedIn 有 27 条。这里的视觉聚集了来自所有三个*台的响应。
下面的图片提供了分类结果的视图。
尽管综合结果显示,大多数受访者将薪资列为第二、第三、第四或较低的关注点,但各*台的回复模式有所不同。在脸书的回答中,大多数人确实表示薪水是他们最关心的问题。在 Twitter 和 LinkedIn 的回复中,薪资并不是第一关注点。
这和随后的视觉崩溃反应从四类降到两类。
结论

Image credit:作者对社交媒体投票结果的可视化。该图显示,在脸书的回答中,大多数人确实表示薪水是他们最关心的问题。然而,在 Twitter 和 LinkedIn 的回复中,薪水并不是第一关注点。
这项简短的、非科学的民意调查表明,数据科学家和其他研究专业人士认为薪水是他们求职的一个重要因素。但是,也许有一半的候选人有他们认为更重要的其他考虑。
尽管这项调查有许多已知和未知的弱点,但它为在招聘过程中询问薪水的相关讨论带来了曙光。
当招聘人员问这个问题时,我对候选人有些担心。候选人似乎面临着一个不可能的选择,要么提出他们认为招聘者会满足的薪水(可能薪酬过低),要么提出代表应得和应得的职业发展的薪水(可能有被拒绝的风险)。
我也担心招聘人员。当招聘人员在讨论薪资要求的早期筛选候选人时,就失去了从候选人那里了解什么才是真正重要的机会。这种策略也有可能错过优秀的候选人,这些人可能会被与薪资无关的因素所吸引。与此相关的是,对非薪金因素做出反应的候选人现在可能会抵制以后被其他组织聘用的尝试。
对于招聘人员来说,更好的方法是问候选人“在工作机会谈判中,你最重要的考虑因素是什么?”然后,听候选人说。之后,谈谈对候选人重要的考虑因素。然后在入职期间和之后,确保进一步解决你现在知道对新员工很重要的需求和愿望。
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
adamrossnelson.medium.com](https://adamrossnelson.medium.com/membership)
感谢阅读
感谢阅读。把你的想法和主意发给我。你可以写信只是为了说声嗨。如果你真的需要告诉我是怎么错的,我期待着尽快和你聊天。推特:@ adamrossnelsonLinkedIn:亚当罗斯尼尔森。
数据科学项目 JustPy 快速入门
只用 Python 构建一个简单的原型站点

你知道什么最棒吗?
制作一个新的模型,并展示出来进行更多的测试。
你知道什么不好吗?
做一个新模型,却没有一个很好的方式来展示它。
越来越容易找到一些数据并建立一个模型(无论是低劣的还是深刻的)。你可以训练和测试(以及更多的测试),但是就像你做的任何东西一样,在使用新数据之前,很难说它有多有用。我确实制作了一些模型,认为它们得分很高,然后当用新的输入进行测试时,显示出它们的真实面目。
你有时会遇到的麻烦是把这个模型放到一个可用的版本中,比如一个网站。你不想要一个蹩脚的纯文本页面,但编写网站代码需要时间和完全不同的技能。不要误解我的意思,我认为 HTML、CSS 和 Javascript 通常是每个人都知道的很好的语言,因为它们在我们现代世界的几乎每个领域都很方便,但是拥有丰富的 web 设计经验不应该是制作有用的数据科学项目的先决条件。有一些 web 框架可以利用您的 Python 技能(比如 Flask 和 Django),但对我来说,这两种框架都有自己独特的复杂性。
输入 JustPy 。这个方便的 Python 包为您提供了在 Python 文件中快速创建网页的能力。它并没有消除对熟悉 web 设计语言的需求,但是可以大大简化事情,特别是对一个模型的测试。它还可以很好地处理熊猫和共享数据可视化。我花了一些时间创建了一个基本模板,您可以在自己的数据科学项目中使用它,但我想分享一下基本知识的概述。
你好世界!
在此之前,让我们先来看看这两个神奇的编码词。您首先需要安装 JustPy,这可以通过 pip 轻松完成:
pip install justpy
接下来,您创建一个 Python 文件,这是您的基本页面:
import justpy as jp
def hello_world():
wp = jp.WebPage()
p = jp.P()
p.text = 'Hello!'
return wp
jp.justpy(hello_world)
让我们一行一行地了解一下。首先,我们开始导入 JustPy 并使用他们喜欢的缩写jp。接下来,我们将整个页面放在一个函数中,使其清晰且易于调用。在函数内部,我们首先用jp.WebPage()创建一个网页实例。需要知道的重要一点是,我们总是要创建页面的实例,然后向其中添加内容。就像网页一样,我们所有的其他标准 web 组件也以类的形式存在。对于这个例子,我们创建一个段落标签的实例,jp.P(),然后用一个值设置它的文本属性。有了这些,我们就可以返回网页实例了。最后,我们用jp.justpy调用我们的函数,我们就有了一个页面!
查看标签类
所以我注意到有助于理解标记类的许多选项。让我们看一个 div 标签:
main = jp.Div(
classes='bg-gray-400 italic', text="My main div", a=wp)
这需要您将要更新的三个主要实例变量:classes、text和a。是您想要添加到标签中的类。关于 JustPy 需要注意的一件重要事情是,它集成了 Tailwind CSS ,这是一个实用的 CSS 框架,可用于轻松设置页面元素的格式和样式。与其他一些 CSS 框架不同,Tailwind 是相当低级的,所以要获得你想要的外观可能需要一些组合类。text显而易见,但了解这一点很重要。是嵌套标签的标签。因为你不像 HTML 那样嵌套标签,你必须告诉每个标签实例它需要放在哪里。在上面的例子中,我只是把这个 div 放在我们的主网页实例中。
轻松输入
我认为最初吸引我测试它的原因之一是它可以如何无缝地与输入一起工作,当连接 Python 和 HTML 时,这有时感觉像是一件苦差事。有使用表单的能力,但是对于一个简单的文本输入例子,你可以有这样的东西:
in = jp.Input(placeholder='Please type here')
嘣,投入!输入的值将存储在类实例中,在这个场景中,它将存储在in.value中。您可以实时查看异步函数输入的内容,或者存储并提交进行处理。
推出垃圾邮件检测器
好了,我们对基础有了一些了解,让我们来看一个例子!假设您的任务是为公司电子邮件帐户创建一个垃圾邮件检测器。你有一套很好的电子邮件标签,并建立了一个非常直接的逻辑回归模型,你感觉很好。然后就发生了,有人说“我能试试吗?”。与其惊慌失措,不如把这个模型处理掉,然后和你的网页一起放入一个新的 Python 文件中!
为了帮助简化设计,我找到了一个带有顺风模板的网站,并以此为基础。我创建了两个主要函数,一个用于处理输入,一个用于网页。所以在一个 Python 文件中,viola:

看起来相当不错!最重要的是,它不需要大量的文件或依赖项目录。我的整个页面是用一个 Python 文件构建的,还有一个我构建模型的地方。我将它设置为在输入时自动处理,但是你可以看到它在查找垃圾邮件时表现良好。
优点:

坏消息是:

您可以从我的回购这里跳出来,创建自己的 easy JustPy 模型网页来测试我们自己的数据科学项目。尽情享受吧!
统计能力的 4 步复习
当你忘记如何计算功耗时,这是一个简单易懂的指南
10 多年来,我经常谈论统计的力量,但无法记住细节。如果你和我一样,收藏这篇文章!我将快速介绍在更新您的幂计算知识时需要遵循的四个步骤。
- 了解你的重要性测试
- 知道如何从 p 回来工作
- 处理两次不确定性
- 从 p 开始工作两次
复制这篇文章的所有代码在 GitHub 上都有。
我们的数据和统计测试
我们将使用双尾单样本 t 测试来评估以下问题的*均答案是否与 0 有显著差异。

在我们的疫情问题中,人们对回家的感觉从-2(糟糕)到 2(很好)进行评分。由谷歌从*面图标制作的图标
1.了解你的重要性测试
首先要知道你的功率计算意味着真正知道你如何从数据到 p 值。单样本 t 测试的步骤:
- 根据*均值、标准偏差和样本量计算出一个 t 统计量:

获得 t 统计量的公式,然后从相应的 t 分布映射到 p 值。sd =标准偏差,n =样本量。使用编码准备的方程式。
- 将其映射到带有自由度的 t- 分布,样本大小减 1。
- 从该点开始的曲线百分比等于 p 值。

注:为清晰起见,只显示了一面。双边测试的 p 值加倍。
2.知道如何从 p 返回工作
功率计算从p-值返回到关于数据的缺失信息。假设我们知道标准偏差(1.17)和样本量(10),并希望计算*均值,其中 p = 0.05。有了p-值和样本量,我们就可以得到t-值(回想一下,这是一个双尾检验)。

将所有内容代入公式:

做数学和mean(x) = +/-0.84。对于我们的标准差和样本,高于 0.84 或低于-0.84 的*均值将具有小于 0.05 的p-值。
3.两次处理不确定性
假设人口*均值确实是 0.84,确切地说,t = 2.26,T2 = 0.05。你不能保证得到一个重要的结果。记得为什么吗?
在 null (0)附*有一个t-分布,因为即使它是真的,我们也很少用那个精确的值对一个组进行采样。同样,我们很少会看到 0.84,即使它是真正的潜在*均值。所以有第二个分布,它描述了在给定真实总体均值的情况下,我们可能观察到的情况。为了简单起见,我们将使用一个等价于零的 t- 分布,但是看看非中心性参数如何被用于变得严重。

如果总体*均值在临界值 t 上,这意味着我们将有 50%的时间观察到样本*均值高于临界值。这是“功效”——在给定特定总体均值的情况下,观察到统计显著结果的概率——总体均值为 0.84。
任何值的幂是其采样分布下超出与零值显著差异点的面积。就像计算另一个 p 值一样,如果你知道你的显著性测试,这应该是轻而易举的。在这个例子中,1.40 的总体*均值映射到 3.76 的 t 值,并且具有 92%的功效。

4.从 p 返回工作两次
计算功效很有趣,但更实际的是计算样本大小或可能产生显著结果的效果。两者都涉及设定两种概率:
- 显著性的阈值(称为 alpha,通常为 0.05)。
- 期望的功率(称为β,通常为 0.80)
计算效果大小
让我们从了解样本大小开始,并希望评估我们可以检测到多大的影响。假设我们可以将我们的调查发送给另外 10 个人,并认为标准差与之前大致相同(1.17)是合理的。显著性阈值为 0.05 时,什么总体均值(正向)具有 0.80 的功效(样本产生显著结果的概率为 80%)。
p1。 算出位于意义边界的意思。这里没有变化。是+/-0.84。
p2。计算出将分布中最低的 20%和最高的 80%分开的*均值。如果 T30 分布集中在 0(我们马上会解决这个问题),它将是-0.33。
我们现在需要找到这两点的交汇点。想象移动总体*均值的分布(用于 p2 ),直到定义 80%功效的值与显著性阈值相同。也就是说,移动分布,使得-0.33 现在是 0.84。分布的中心/*均值相应地移动并落在 1.17(纯粹是巧合,它与标准偏差相匹配)。瞧啊。对于我们已知的样本大小和标准偏差,如果真实总体均值为 1.17 或更大——对应于 3.15 的 t 值——我们将有相当好的机会(80%)观察到显著的结果。

计算样本大小
让我们反过来试试。假设*均值 1.17 是对我们有意义的最小值,但是我们不确定需要多大的样本。其他标准相同(标准差= 1.17,显著性阈值= 0.05,功效= 0.80)。
这个问题更棘手,因为在不知道样本大小(这涉及到自由度)的情况下,我们不知道 t 分布的形状。我们可以通过一些迭代来解决它。在高层次上…
第一步。选择一个样本大小。
第二步。从 p 回工作两次:
p1。 算出位于意义边界的*均值。 p2。 算出将人口分布分割为 80%的*均值。移动它,使人口值集中在预先确定的效果大小(1.17)。第三步。如果 p1 和 p2 的结果相等,则停止。 如果不是,从步骤 1 开始用不同的样本量。
有很多方法可以优化这一点,你可以在我的代码中找到一个简单的解决方案。不管你怎么做,结果都是 10(验证最后一部分)。为了多样化,让我们尝试一些不同的东西。如果总体均值为 0.02,我们需要多大的样本量才能达到 80%的功效?
27,037!
结论
统计学,像所有的技术课题一样,具有挑战性。学习细节会加深你的理解,但不要觉得有压力去记忆它们。当你学习新技术的时候,学习它的实用价值,它们能解决和不能解决的问题,优势和劣势。当需要技术资料的时候,就准备一篇这样的文章吧:)
感谢阅读。如果你喜欢这个,并且对更高级的电力话题感兴趣,你可能会喜欢我的文章,“Booking.com 如何用 CUPED 增加在线实验的电力”
Numpy 和 Matplotlib 快速回顾

Python 是数据科学的首选语言,只是因为它提供了大量的包和库,这些包和库增强了我们的数据可视化和解释,从而获得最大的生产率。Python 提供的两个这样的包是 Numpy 和 Matplotlib,我们今天要讨论这两个包。因此,让我们深入了解两个最简单但却是最基本的数据科学工具的一些基础知识。
Numpy
Numeric Python,或 Numpy,是一个基本的 Python 包,它提供了常规 Python 列表的替代方案,即 Numpy n 维同构数组。列表是 Python 提供的一个非常有用的工具,因为它可以让你一次存储不同类型的值,并对其执行许多操作。但是它有一定的局限性,对链表的一些操作效率不高。例如:
列表法
在这里,Numpy 可能非常有益。它可以在一行代码中解决我们的问题,而无需使用 loop:
数字阵列法
Numpy 不仅对此很有帮助,而且还允许您在这些数组上执行大量复杂的科学计算。这些计算包括,但不限于,线性代数、矩阵乘法和矩阵操作,所有这些都不使用循环,以一种无障碍且高效的方式进行。
安装 Numpy
所以,我们看到了 Numpy 数组是多么有用,但是如何使用它们以及从哪里获得它们。嗯,要获得 Numpy,你可以在计算机的命令行中使用**pip install numpy** ,或者你可以使用任何科学的 Python 发行商(推荐使用 Anaconda )。要了解下载 Numpy 的详细步骤,请点击此链接。
现在安装 Numpy 后,要使用它,您需要导入它,因为它不容易使用。你可以通过**import numpy** 来实现。但通常只是为了避免一直键入全名,它是用别名‘NP’导入的:
import numpy as np
您已经准备好使用这个受到所有数据科学家喜爱的漂亮工具。首先,让我们熟悉创建 Numpy 数组的不同方法。
创建 Numpy 数组
Numpy 数组主要是使用np.array()方法定义的,但这不是唯一的方法。下面列出了定义 Numpy 数组的多种方法:
**np.array()**: 可以用来定义任何维度的任何一种数组,是最常用的方法。dtype在将输出定义为我们首选的数据类型时,可以添加参数。如下所示:
使用 np.array()
2.**np.zeros()** : 使用np.zeros()只会产生一个零数组。你只需要定义零数组的维数。
使用 np.zeros()
3.**np.ones()** : 使用np.ones()只会产生一个 1 的数组。同样,您只需要定义数组的维数。
4.**np.arange()** : 当你想要一个数组,里面的值在一个给定的范围内有规律的间隔,你可以用np.arange()来实现。它接受三个值,前两个是范围值,第三个是跳过值。请注意,该范围的第二个值不包含在内。
创建 Numpy 数组还有许多其他方法,如np.linspace()、np.identity()等。
数字阵列的一些特殊方法
**.size**: 返回数组中元素的个数,不考虑其维数。**.shape**: 以(row,columns)的形式返回数组的行数和列数。**.reshape()**: 让你把给定数组的维数改成自己选择的维数。**.resize()**: 其操作与 shape 相同,唯一不同的是使用resize()会改变原来的数组。
所有上述方法如下所示:
子集数数组
Numpy 数组与 Python 列表非常相似,这是它们有多相似的另一个例子。Numpy 数组中的元素的选择方式与 Python list 中的选择方式相同。要选择数值范围,您可以使用**np_arr_name[start:end:skip]** 。就像列表一样,end 位置的元素是不包含的,skip决定两个选定值之间的间隔。
Numpy 有一种特殊的数组子集化方法,那就是使用一个布尔数组。为此,您只需使用条件创建一个布尔数组,并将该数组作为对象传递给 Numpy 数组。
下面展示了各种子集设置方式:
二维数组
二维数组基本上是数组中的数组。这在数据科学中很常见,因此,您应该非常熟悉它。
子集化
该数组可以被认为是一种矩阵形式,其中子集数组的数量是行,每个子集数组中的元素数量是列。可以使用格式**np_arr[start:end:skip,start:end:skip]** 来选择这种类型的阵列中的元素,即使用两个方向上的切片,第一个方向用于行,第二个方向用于列。
矩阵运算
矩阵中的算术运算可以通过简单地使用运算符(+、-、*、/等)来完成。)以给出期望的输出。对矩阵的各种操作如下所示:
在这里,当我们执行标量加法或减法时,Numpy 让我们将一个整数与整个矩阵相加。这是因为 播 才有可能。
对于广播,这两个维度要么相同,要么其中一个为 1。在后一种情况下,Numpy 将维度更改为值不为 1 的维度。例如,
A (4d array): 8 x 1 x 6 x 1
B (3d array): 7 x 1 x 5
Result (4d array): 8 x 7 x 6 x 5
如果维数不相等且不是 1,那么它将抛出一个错误:**ValueError: operands could not be broadcast together** 。
数字矩阵的一些特殊性质
- 乘法:在 Numpy 中,您可以使用
np.dot()执行常规的矩阵乘法,即点积。它还允许你像对任何向量一样执行叉积。这是使用np.cross()完成的。 - 转置:转置是同一个矩阵,但是将原矩阵的行作为新矩阵的列,原矩阵的列作为新矩阵的行。这是用
matrix.T方法完成的。 - 行列式:要计算矩阵的行列式,就必须使用
linalg模块。行列式可以用np.linalg.det(matrix)来计算。 - 求逆:可以使用
linalg模块以类似于行列式的方式计算求逆。语法是np.linalg.inv(matrix)。
所有上述特征如下所示:
数字统计
现在,我们知道了 Numpy 中的很多操作和工具。但是,如果我们实际上获得了大量数据,这是机器学习中的典型情况,该怎么办呢?简单地查看数据,或者将数据打印成数组或矩阵不会有任何帮助。为了从这些数据中得到有用的东西,我们需要对其进行一些统计分析,Numpy 是一个很好的工具。各种统计操作包括均值、中位数、标准差、方差等。所有这些操作既可以在整个数组上完成,也可以只在行或列上完成。下面演示了其中的一些操作:
还有很多其他的方法像sum()、 sort()、corcoeff()等等。,这在进行深入的数据分析时会派上用场。
好了,我们快搞定 Numpy 了。你所要做的就是练习,练习,练习,真正擅长它,并了解在分析大数据时应该使用什么。现在你必须考虑从哪里得到练习,从哪里得到数据,这样你就可以执行一些操作并分析它。你可以自己生成数据。
生成数据
我们可以使用 Numpy np.random.normal()函数模拟数据。它接受三个参数: 1) 均值, 2) 标准差, 3) 样本数。
现在,你已经拥有了进入这个领域的所有工具,并开始进入机器学习领域。
Matplotlib
在上一节中,您了解了可以用来深入了解数据的各种操作。这些都是数字,你必须用你的头脑来分析这些数据。如果我们能对数据进行可视化分析会怎么样?那不是超级有帮助,而且容易理解吗?Matplotlib 来救你了。Matplotlib 是最强大的可视化库。要使用它,您需要导入它的子包 pyplot。我将谈谈 Matplotlib 的一些基本知识,它可以帮助你实现数据可视化。
要使用 Matplotlib,我们需要使用以下方式导入它:
**import matplotlib.pyplot as plt**
Matplotlib 基础
所有图中最简单的是线图。plt.plot()方法会给你一个线图。它接受两个数组作为参数。我们将学习线形图中绘图的各个方面。plt.show()方法将显示图表。如果不想一直打,可以用%matplotlib inline。
- 标签:您可以给图形的 x 轴和 y 轴添加标签。要为 x 轴设置标签,我们可以使用
plt.xlabel()。同样对于 y 轴,我们可以使用plt.ylabel(). - 标题:你可以使用
plt.title()来设置你的图的标题。 - 刻度:您可以根据自己的选择标注 x 轴或 y 轴的位置。例如,x 轴上的人口可以标记为“1B”、“2B”、“3B”等。,代替写 1,2,3 等。这将增加图形的可读性。x 轴和 y 轴分别使用
plt.xticks()和plt.yticks()完成。 - 图形尺寸:您可以使用
figure()方法增加或减小图形的尺寸。要更改大小,您需要将一个包含行和列的长度值的元组分配给参数figsize。 - 支线剧情:有时候你可能想要在同一个人物中出现不止一个剧情。在这种情况下,您可以使用
plt.subplot()方法。它接受三个参数:nrows即行数,ncols即列数,index即每个图的索引号。 - 支线剧情:支线剧情与支线剧情十分相似,但是
plt.subplots()的结果被解包在两个变量中,即图形和轴,因此更容易引用生成的图形中的特定剧情。
上述内容的演示如下:
用户化
制作一个图表是一回事,但是使用颜色和线条使它引人注目和更有成效是另一回事。定制我们的图表使它更有洞察力,更容易阅读。
- 颜色:要设置图形的颜色,您可以指定
plt.plot()方法的color参数。您可以以字符串的形式传递颜色的名称。 - 标记:标记是图中点的格式。要更改标记,只需将包含您选择的标记的字符串传递给
plt.plot方法的mark参数。 - 线条样式:线条样式定义图形线条的格式。要更改 linestyle,只需将包含您选择的标记的字符串传递给
plt.plot方法的linestyle参数。
不同颜色、市场和线型的不同地块如下所示:
不同类型的地块
Matplotlib 提供了各种类型的绘图来帮助您更好地可视化数据。下面解释了一些图表:
条形图:
如果我们有按类别组织的数据,那么我们可以使用条形图来描述它,其中每个条形的高度代表特定类别中数据的值。您可以使用plt.bar()绘制常规条形图,使用plt.barh()绘制水*条形图。有不同类型的条形图,即水*堆叠条形图和垂直堆叠条形图。要绘制水*堆叠条形图,您需要定义index和width来定义图上条形的位置和大小,而要绘制垂直堆叠条形图,您需要定义一个bottom参数来定义图上条形的正确描述。所有这些如下所示:
直方图:
我们看到的柱状图,显示了不同条件下变量的值。现在,我们将讨论直方图。直方图有助于我们将特定变量的值的分布可视化。可使用plt.hist()绘制直方图。默认情况下,它将绘制一个有十个柱的直方图,即本例中的柱。但是你可以把它定制成你选择的数字,或者用数字列表来作为 x 轴上的位置。您也可以使用plt.hist()方法的histtype参数自定义直方图的类型。
方框图:
箱线图是一种统计可视化工具,它显示一个数据的五个数字摘要,即最小值、第一个四分位数、中值、第三个四分位数和最大值。使用plt.boxplot()绘制。
散点图:
散点图是获得数据洞察力的另一个超级重要的图,特别是当我们必须在我们的观察中比较不同的变量时。可以使用plt.scatter()方法绘制。
好了,现在你知道了一些工具,它们是机器学习的基础。有了这个,我们更加接*了解真正的机器学习算法。一旦你熟悉了在数据科学中非常重要的所有工具和库,我就会写这些东西。
接下来,我会写一篇关于熊猫的深度博客,这是另一个非常重要的工具。了解熊猫将有助于你处理更大的数据集,了解如何获得洞察力并对更大的数据框架进行有效的分析。
我希望你在阅读这篇文章时感到有趣,并且你发现一切都很容易理解。如果你需要任何主题的进一步信息,请在回复中告诉我。
网上学习 Python 的最佳免费资源的快速汇总
你不需要付费就可以开始使用 Python

TLDR;
- 提出好的问题(见下面的模板)。
- learnpython.org 是一个经常被忽视的资源,它能让你从最基本的开始
- 编写程序是一本很好的介绍 CS 的教科书,里面有使用 Python 的例子
- Regex One 非常适合学习高级字符串操作
- 对于练习来说,这是非常棒的
- 约翰·菲利普·琼斯在 YouTube 上有一个很棒的频道
- 学到足够危险的东西,然后开始做自己的项目
介绍
Python 已经成为数据分析和数据科学领域任何顶级职位的必备技能。不幸的是,很多数据人在学习 Python 的时候忽略了基础。我创建了这个资源列表,以支持一个希望转型到更具技术性的角色的朋友。
问伟大的问题
几乎每个程序员都在网上寻求帮助,Python 的优势之一是支持性社区可以帮助回答他们。获得帮助的最好方法是提出好的问题。这是我在 Udemy 上从 Ziyad Yehia 改编的最佳实践列表(非免费资源)。
- 为你的问题起一个清晰的标题
- 描述观察到的行为
- 描述预期的行为
- 在 github 上链接到您的代码(您应该注册一个 github 帐户)
- 说出你认为问题可能出在哪里和什么地方
- 说你已经做了什么来试图解决这个问题
- 包括完整的错误消息
- 包括您正在使用的 Python 版本
- 不要仅仅发布你的代码的图片,而不让别人复制它
遵循这些步骤,你会更快地获得帮助。
基础知识
Learnpython.org 会让你掌握所有的基础知识。你可以在你的浏览器中运行代码,所以你不需要担心安装任何东西,它们的描述是用简单的语言写的,可以让你快速编码。
免费计算机科学教科书
编写程序是一个免费的计算机科学教科书,使用 Python 中的例子快速涵盖了计算机科学的最重要的部分。它在数学上比许多人认为的要难一些,但是它会给你一个坚实的基础。
操纵字符串
Regex One 是我最喜欢的学习如何使用正则表达式的资源之一,正则表达式是操作字符串和清理数据的常见任务。虽然不是 Python 特有的,但是很好地处理正则表达式将会在解决实际问题时给你很大的帮助
练习练习练习
Exercism.io 有一系列使用多种语言的指导练习题。在学习语言的过程中,他们有两种选择,有人指导和自我指导。都是免费的。
完全公开,我是他们 Python 轨道上的导师。我的建议是实际上不要使用指导。我在指导过程中的经历是,导师(所有志愿者)都是不一致的,我经常会等上几天,得不到特别有价值的反馈。
也就是说,很少有在线资源能让我像做练习一样快地学会编码。它迫使你去解决各种各样的问题,并打破你的舒适区。
油管(国外视频网站)
YouTube 上有无数的 Python 教程。我喜欢约翰·菲利普·琼斯,因为他的频道制作精良,涵盖了初学者和更高级主题的广泛话题,并有易懂的解释。
学到足够危险的程度
我的最后一条建议是学习足够的 Python 来解决你生活中的实际问题。我花了几个月的时间绞尽脑汁试图理解循环。当我不得不在工作中解决一个需要我使用 for 循环的问题时,我才真正开始理解它们。
编程的主体是条件语句(If、elif、else)和循环。一旦你知道了这些和基本的数据结构(列表、字典、元组),你就可以开始应用你所知道的。
你最喜欢的让你更擅长 Python 的免费资源有哪些?
关于作者:
Charles Mendelson 是 PitchBook 的营销数据分析师。在过去的五年里,他一直在销售和营销机构工作。他的工作是分析师和开发人员的混合角色。他不断努力成为一名更好的程序员,目前正通过自学计算机科学课程沉浸在计算机科学的基础知识中。如果他有超能力,他会花很多时间思考如何解决问题,而不仅仅是解决问题。
原载于 2020 年 9 月 26 日【https://charlesmendelson.com】。
Gephi 布局快速教程—使用问答 StackOverflow 数据集
前几天,当我为一个做社交网络分析的朋友准备教学/咨询服务时,我需要修改 Gephi 的布局。以下是我重新学习的总结。
Gephi 是一个令人惊叹的开源网络分析和(交互式!)可视化软件,提供大量非常有用的工具,用于探索图形数据、计算统计数据、检测集群、社区等。它不需要任何编码技能。即使你有的编码技能,也请暂时停止使用 Python 的 NetworkX,尝试一下 Gephi。值了。
Gephi 提供的一个非常好的特性是一系列不同的布局算法——也就是您实时查看图表的方式。让我们尝试它们,看看它们背后的直觉是什么,以及它们的利弊。
我们将使用这个来自 Kaggle 的 StackOverflow 数据集。我创建了一个以人为节点的网络,当且仅当 A 回答了 B 的问题时,A — > B 链接才存在。边的权重就是答案的分数。我用 Python 中的 pandas 库创建了这个。
当我在 Gephi 中可视化结果图时,它看起来并不太好——因为它是随机布局:

StackOverflow 图的 R̶o̶r̶s̶c̶h̶a̶c̶h̶ ̶t̶e̶s̶t̶随机布局。
ForceAtlas
我们来试试另一种布局: ForceAtlas 。这对于小世界/无标度网络是一个有用的布局,对于探索网络也是有用的,因为它不会在绘图时引入偏差。复杂度为 O(N ),建议将其用于< 10K 节点。该算法将强连接的节点拉在一起,并将弱连接的节点推开。你通常需要调整它的参数来得到一个好的显示。
一些定义:
- 小世界:对于每个节点来说,它没有很多邻居,但它的邻居很可能是彼此的邻居,并且大多数节点可以通过小步数从每个其他节点到达。(听说过六度分离的想法吗?)
- 无标度:这只是程度分布遵循幂律:

我们如何检验我们的网络是否是无尺度的?直接去统计,运行“*均度”计算。这是我的:

看起来像是幂律!也许原力图集会好看。

ForceAtlas(默认参数)
这更好——至少孤立的节点被推到了外面。不过网络的中心有点乱。通过选择“按大小调整”参数,我们避免了节点重叠。如果你想要更高的精度,速度可以降低。这是这个过程的前 20 秒:

使用“按大小调整”参数移除重叠的节点
这是最后的结果:

按大小调整强制图集
我们可以做得更好。通过到这里:

选择“节点”、“等级”和同心圆选项,我们可以使节点的大小与度量成比例,例如,出度。在这之后,我们可以再次运行布局算法,我们得到这个:

节点大小与输出度成比例
我们甚至可以通过悬停在其中一个大节点上来关注它:

节点的邻域
最后,通过计算模块性统计,我们可以根据节点所属的社区对节点进行着色:
着色的过程类似于用于节点大小的过程——只是这次我们需要选择调色板,以及用于排序的模块化类。结果如下:

社区可视化
在进入下一个布局之前,让我们再玩一个参数:通过选择景点分布,枢纽(具有高出度的节点)被推到外围,而权威(高入度)更集中。有时,从随机布局重新开始会更好,因为它收敛得更快。
更改后,我们可以看到中心(突出显示)确实位于外围—如果我们过滤出度高于 12、入度低于 3 的节点,我们可以看到中心也不是权威:

具有吸引力分布的 Force Atlas 将枢纽投入到 perifery 中
弗鲁特曼-莱因戈尔德
该布局将节点模拟为质量粒子,将边模拟为字符串。然后,它只是最小化系统的能量。复杂度也是 O(N ),但建议使用最多 1K 个节点,因为实际收敛很慢。
请注意,这些边被视为无方向的。这种布局有助于理解图形的拓扑结构,因为拓扑上的*节点位于相同的邻*区域,而远节点彼此远离。因此,断开的组件很容易可视化。
我们将在我们的(已经按社区划分的)网络上运行它。

实际上,我们的图表中有很多不相连的部分。我们可以控制布局的面积和重心来避免它们的分散:

奥彭德
这种布局需要一个无方向的加权图,对于检测集群非常有用。它比其他布局更快——复杂度为 O(N log(N))并且推荐用于高达 1M 节点的网络。
OpenOrd 基本上是 Fruchterman-Reingold,带有一个额外的参数(edge cut ),在优化过程中控制边的最大长度。默认值为 0.8:这意味着在优化过程中,长度超过当前最长边长 80%的每条边都被切割。这使得星团可以分离,因为高权重的长边会对远处的星团产生不适当的影响(还记得 Fruchterman-Reingold 基本上是一个弦系统吗?)
值 1 对应于标准 Fruchterman-Reingold,因为没有边的长度大于最长的边,值 0 对应于真正的侵略性切割(受每个非孤立节点必须保留至少一条边的事实的约束)。

我们在这里切换到黑色背景,因为这将有助于我们理解边缘的切割。而且,它看起来更酷。
我们可以看到一些边在优化过程中是如何被切割的,因为一些节点现在不自然地远离:

OpenOrd —关注一个节点。
圆形布局
我不得不安装这个,因为它不是默认提供的——这很简单。你只需进入工具>插件>可用插件,检查其名称并点击安装。不幸的是,您需要重启应用程序来完成安装。
这种布局简单但功能强大:它根据您能想到的任何度量或属性对节点进行排序。您可以使用它来可视化它们的节点及其链接的分布。这种布局速度非常快——O(N ),因为它不需要运行任何优化。

圆形布局(按向内角度顺时针排序)
你也可以用这个来准备一个不那么无聊的演示文稿!例如,我们可以使用 pandas(提示:使用group by+nunique)计算每个节点回答的不同标签 (Python、C#等)的数量。姑且称此为知识 _ 综艺。我们可以用一个方框图来展示这个指标的分布,但也可以用一个圆形布局。

幻灯片示例使用圆形布局和节点大小来说明网络的统计事实
双圆形布局
这是圆形布局的一个很酷的变体,您可以将顶部节点放置在外圆中,下面是度数的一个示例:

双圆形布局(按度数顺序,顺时针方向)
如果您既想可视化指标的分布,又想更详细地了解排名靠前的节点,这将非常有用。
径向轴
这个将节点分组,并呈现为从一个中心圆向外辐射。它带有圆形布局插件。它也是 O(N ),并且对研究与属性相关的同向性极其有用。
然后,我们可以将节点的 knowledge_variety 分布在一个圆中,并将它们的度数分布在来自该圆的螺旋中。下面是它的样子——40 个螺旋,顺时针顺序(最大知识 _ 11 和 12 标记之间的变化)和低边缘宽度。请记住,节点大小与外部程度相关,颜色表示社区:

径向轴
- 最长的尾巴在第 1 小时;那里用户的外向度很低:大多数用户贡献的内容很少,而且是关于非常具体的主题。
- Out-degree 与 knowledge_variety 相关:这是有道理的,因为你的知识越多样化,你就越能为整个社区做出贡献。然而,也有一些例外——超级用户知道很多非常具体的主题。
其他
还有很多其他的布局,如果我感兴趣的话,将来我会再写一篇关于地理网络布局的教程!祝你黑客生涯愉快!
你可以随时通过 LinkedIn 这里 联系我,讨论数据科学,自由职业优惠,数学,桌游。
用 Python 进行 AWS 转录的快速教程
通过 Google Colab 和 Google Drive 使用 AWS 转录的转录服务简介
去年夏天,我开发了一些涉及语音转文本机制的产品,我认为最好使用现有的 API 来实现这些目的。在这篇文章中,我想与那些想尝试这些美妙技术的人分享我使用这些 API 的一点点经验。希望你们觉得有帮助:)
哦!而这里是我将涉及的快速内容:
-设置:通用包和初始化基本功能
-单扬声器文件
-多扬声器文件
-通过 Colab 和 Google Drive 访问文件并上传到 S3 存储器
-创建词汇表以增强转录准确性
代码链接:Google Colab ( 此处)、Gist ( 此处)或 Github( 此处)。

为什么选择语音转文本?
语音转文本是一项很有前途的技术,不是作为一个产品本身,而是更多地基于它对许多其他产品的底层应用。由于我们的阅读速度比听力速度快得多,阅读转录比听类似内容的音频节省更多的时间。谷歌的新旗舰手机:Pixel 4,引入了执行实时转录的录音应用程序!有前途的产品可能是会议记录(Zoom 已经提供了这个功能)、讲座(文本记录)等等。
多年来,语音转文本已经是一个相当成熟的领域。由于这种挑战更多的是横向的,而不是纵向的,因此拥有来自各种输入源的大量数据的公司会胜出。毫无疑问,像亚马逊、谷歌、IBM、微软这样的大公司是在他们的云上提供转录服务的领导者。
每种产品都有其优点和缺点,可能会不同程度地满足您的需求。我强烈建议尝试所有这些服务,并选择最适合您所需用例的服务。在这篇文章中,我将重点放在 Amazon Transcription 服务上,因为它有丰富的输出:一个 JSON 文件,包含所有时间戳和其他信息,这非常有用!
(对我(希望)下一篇帖子的小炒作:Google Cloud(执行单个说话者转录时):输出没有任何标点符号。我希望写一个 RNN 模型来添加标点符号,以丰富输出。但这是在未来。让我们暂时回到 AWS!)
我将通过使用谷歌 Colab 的步骤。完整代码的链接是这里是。我们开始吧!
设置:通用软件包和初始化基本功能。
!pip install boto3
import pandas as pd
import time
import boto3
Boto 是用于 Python 的 AWS 软件开发工具包。更多关于 Boto 3 文档的信息可以在这里找到。
我们还需要 AWS 帐户的访问密钥。如果你还没有创建一个帐户,请这样做(它是免费创建的,如果你不使用太多,还有免费层)!
当您拥有自己的帐户时,以下是获取个人访问密钥的方法(如果您已经有了访问密钥,请随意使用):
- 步骤 1:转到 AWS 管理控制台页面。
- 第二步:点击右上角的用户名,选择“我的安全凭证”
- 步骤 3:选择“访问密钥(访问密钥 ID 和秘密访问密钥。”
- 第四步:创建新的密钥,并记住保存它!
- 步骤 5:添加到我们的代码中:初始化转录作业。
transcribe = boto3.client('transcribe',
aws_access_key_id = #insert your access key ID here,
aws_secret_access_key = # insert your secret access key here
region_name = # region: usually, I put "us-east-2"
此外,我们需要创建/连接我们的亚马逊 S3 存储。
AWS 转录将从您的 S3 存储中转录文件。这非常方便,因为你可以将文件存储到亚马逊 S3,并直接从云中处理它们。点击阅读如何创建你的 S3 桶。
尝试上传一个随机的音频/视频文件到 S3 存储,让我们试试转录服务!这些是我们的价值观
- job_uri: S3 访问链接,通常为“S3://bucket _ name/”+audio _ file _ name(如“S3://viethoangtranduong/AWS . wav”)
- job_name:对于每个转录调用,我们需要一个作业名。在这种情况下,我使用音频文件名本身。我们也可以使用散列函数来自动化系统。
注意:如果已经存在同名作业,作业将会崩溃。避免这些问题的可能方法是 :- 一个哈希函数来编码音频文件名和作业的时间戳(这将避免重复,即使文件具有相同的名称)
- 一个密钥生成器数据库:如果我们使用 base 62(因为我们想避免“/”和“+”),那么我们可以有 62⁶ = 56.8 B 唯一代码(这应该足够了)。我们可以将未使用的密钥用于每项工作。
我们可以有两个数据库来存储使用和未使用的密钥。每次使用一个未使用的键时,我们将它移动到另一个数据库。我们必须跟踪文件名和匹配的键,以便将来遍历。使用这种方法,我们可以进一步发展成转录文件的链接缩写。
- file_format:文件格式。AWS 可以处理大多数文件,如. mp3、.wav,甚至像. mp4 这样的视频
为了简单起见,我创建了一个函数调用 check_job_name 来处理重复的作业名。
def check_job_name(job_name):
job_verification = True # all the transcriptions
existed_jobs = transcribe.list_transcription_jobs() for job in existed_jobs['TranscriptionJobSummaries']:
if job_name == job['TranscriptionJobName']:
job_verification = False
break if job_verification == False:
command = input(job_name + " has existed. \nDo you want to override the existed job (Y/N): ") if command.lower() == "y" or command.lower() == "yes": transcribe.delete_transcription_job(TranscriptionJobName=job_name)
elif command.lower() == "n" or command.lower() == "no": job_name = input("Insert new job name? ") check_job_name(job_name)
else:
print("Input can only be (Y/N)")
command = input(job_name + " has existed. \nDo you want to override the existed job (Y/N): ")
return job_name
对于单扬声器文件
def amazon_transcribe(audio_file_name):
job_uri = # your S3 access link
# Usually, I put like this to automate the process with the file name
# "s3://bucket_name" + audio_file_name # Usually, file names have spaces and have the file extension like .mp3
# we take only a file name and delete all the space to name the job
job_name = (audio_file_name.split('.')[0]).replace(" ", "") # file format
file_format = audio_file_name.split('.')[1]
# check if name is taken or not
job_name = check_job_name(job_name)
transcribe.start_transcription_job(
TranscriptionJobName=job_name,
Media={'MediaFileUri': job_uri},
MediaFormat = file_format,
LanguageCode='en-US')
while True:
result = transcribe.get_transcription_job(TranscriptionJobName=job_name)
if result['TranscriptionJob']['TranscriptionJobStatus'] in ['COMPLETED', 'FAILED']:
break
time.sleep(15)
if result['TranscriptionJob']['TranscriptionJobStatus'] == "COMPLETED":
data = pd.read_json(result['TranscriptionJob']['Transcript']['TranscriptFileUri'])
return data['results'][1][0]['transcript']
因为转录可能需要时间,所以我们创建了一个 while 循环来等待它完成(每 15 秒重新运行一次)。
最后一个“if”语句从 JSON 文件中提取特定的脚本。我将在文章的最后讨论如何提取时间戳。
对于多扬声器文件
对于 AWS 为多个扬声器转录,它可以检测的最大扬声器是 10 个。这次我将接受两个参数作为输入:audio_file_name 和 max_speakers。我强烈建议使用 max_speakers 值来提高 AWS 的准确性。但是,您也可以将其留空。
def amazon_transcribe(audio_file_name, max_speakers = -1):
if max_speakers > 10:
raise ValueError("Maximum detected speakers is 10.")
job_uri = "s3 bucket link" + audio_file_name
job_name = (audio_file_name.split('.')[0]).replace(" ", "")
# check if name is taken or not
job_name = check_job_name(job_name)
if max_speakers != -1:
transcribe.start_transcription_job(
TranscriptionJobName=job_name,
Media={'MediaFileUri': job_uri},
MediaFormat=audio_file_name.split('.')[1],
LanguageCode='en-US',
Settings = {'ShowSpeakerLabels': True,
'MaxSpeakerLabels': max_speakers})
else:
transcribe.start_transcription_job(
TranscriptionJobName=job_name,
Media={'MediaFileUri': job_uri},
MediaFormat=audio_file_name.split('.')[1],
LanguageCode='en-US',
Settings = {'ShowSpeakerLabels': True}) while True:
result = transcribe.get_transcription_job(TranscriptionJobName=job_name)
if result['TranscriptionJob']['TranscriptionJobStatus'] in ['COMPLETED', 'FAILED']:
break
time.sleep(15) if result['TranscriptionJob']['TranscriptionJobStatus'] == 'COMPLETED':
data = pd.read_json(result['TranscriptionJob']['Transcript']['TranscriptFileUri'])
return result
这一次,输出不再是文本,而是一个文件结果(在 Python 中,它是一种字典数据类型)。
data = pd.read_json(result['TranscriptionJob']['Transcript']['TranscriptFileUri'])
transcript = data['results'][2][0]['transcript']
这段代码将为您提供原始的转录(没有扬声器标签):结果将类似于将这些文件输入到单扬声器模型中。
如何添加扬声器标签?
现在,我们将读取“TranscriptFileUri”中的 JSON 文件。
由于我们正在使用 Google Colab,我还将演示如何访问特定文件夹中的文件。假设我们已经把它放在一个文件夹中:Colab Notebooks/AWS transcript reader:下面是访问它的方法。
from google.colab import drive
import sys
import os drive.mount('/content/drive/')
sys.path.append("/content/drive/My Drive/Colab Notebooks/AWS Transcribe reader")
os.chdir("/content/drive/My Drive/Colab Notebooks/AWS Transcribe reader")
现在,我们需要处理来自 AWS 转录的 JSON 输出。下面的代码将提供一个带有[时间戳,演讲者标签,内容]的. txt 文件。
当输入“filename.json”文件时,期待完整抄本的“filename.txt”文件。
import json
import datetime
import time as ptime def read_output(filename):
# example filename: audio.json
# take the input as the filename
filename = (filename).split('.')[0]
# Create an output txt file
print(filename+'.txt')
with open(filename+'.txt','w') as w:
with open(filename+'.json') as f:
data=json.loads(f.read())
labels = data['results']['speaker_labels']['segments']
speaker_start_times={}
for label in labels:
for item in label['items']:
speaker_start_times[item['start_time']] = item['speaker_label'] items = data['results']['items']
lines = []
line = ''
time = 0
speaker = 'null'
i = 0
# loop through all elements
for item in items:
i = i+1
content = item['alternatives'][0]['content'] # if it's starting time
if item.get('start_time'):
current_speaker = speaker_start_times[item['start_time']] # in AWS output, there are types as punctuation
elif item['type'] == 'punctuation':
line = line + content
# handle different speaker
if current_speaker != speaker:
if speaker:
lines.append({'speaker':speaker, 'line':line, 'time':time})
line = content
speaker = current_speaker
time = item['start_time'] elif item['type'] != 'punctuation':
line = line + ' ' + content
lines.append({'speaker': speaker, 'line': line,'time': time}) # sort the results by the time
sorted_lines = sorted(lines,key=lambda k: float(k['time']))
# write into the .txt file
for line_data in sorted_lines:
line = '[' + str(datetime.timedelta(seconds=int(round(float(line_data['time']))))) + '] ' + line_data.get('speaker') + ': ' + line_data.get('line')
w.write(line + '\n\n')
然后,在同一个文件夹中,会出现“filename.txt”文件,其中包含所有的抄本。
奖励 1:直接访问和上传文件到 S3 存储器
将文件上传到 AWS S3 存储肯定会使许多过程自动化。
# define AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and bucket_name
# bucket_name: name of s3 storage folder
s3 = boto3.client('s3',
aws_access_key_id = AWS_ACCESS_KEY_ID,
aws_secret_access_key = AWS_SECRET_ACCESS_KEY,
region_name = "us-east-2")s3.upload_file(file_name, bucket_name, file_name)
红利二:我们为什么不创建一个词汇表来增强准确性?
我们可以通过控制台管理将词汇表手动上传到 AWS 转录服务中。接受的文件有。csv 或. txt.
然而,如果我们想用 Python 来自动化这个过程,那就有点棘手了。
下面是我发现的一种方法:AWS 通过 Python 接受特定类型的输入,这是一个有 4 列的 data frame:[' Phrases ',' IPA ',' SoundsLike ',' DisplayAs']转换成。txt 文件。有关各列含义和自定义词汇的更多信息,请阅读此处的。
def vocab_name(custom_name):
vocab = pd.DataFrame([['Los-Angeles', np.nan, np.nan, "Los Angeles"], ["F.B.I.", "ɛ f b i aɪ", np.nan, "FBI"], ["Etienne", np.nan, "eh-tee-en", np.nan]], columns=['Phrase', 'IPA', 'SoundsLike', 'DisplayAs']) vocab.to_csv(custom_name+'.csv', header=True, index=None, sep='\t')
import csv
import time
csv_file = 'custom_name+'.csv
txt_file = 'custom_name+'.txt with open(txt_file, "w") as my_output_file:
with open(csv_file, "r") as my_input_file:
my_output_file.write(" ".join(row)+'\n') for row in csv.reader(my_input_file)]
my_output_file.close()
ptime.sleep(30) # wait for the file to finish bucket_name = #name of the S3 bucket
s3.upload_file(txt_file, bucket_name, txt_file)
ptime.sleep(60) response = transcribe.create_vocabulary(
VocabularyName= custom_name,
LanguageCode='en-US',
VocabularyFileUri = "your s3 link" + txt_file)
# the link usually is bucketname.region.amazonaws.com# after running vocab_name, we can check the status through this line# if it's ready, the VocabularyState will be 'READY'
transcribe.list_vocabularies()
上传和添加词汇表花费了相当多的时间。这可能不是最佳的方法,但它是有效的(在尝试字符串列表、列表列表中,但目前没有一个有效)。
如果你找到了进一步自动化的方法,请评论!我很乐意讨论和了解更多。
结论和…下一步是什么?
这里有一个关于 AWS 转录的快速教程。希望你觉得有用!此外,我希望听到你的想法,并进一步讨论它们。(我可能会写一些关于在 Google Cloud little-punctuations 抄本中添加标点符号的内容,所以我希望我不会偷懒)。
链接到代码:Google Colab ( 这里),Gist ( 这里,或者 Github( 这里)。
欢迎通过linkedin.com/in/viethoangtranduong/联系我或在此发表评论,我会尽力尽快回复!
附:实时转录比转录一个类似的文件要好得多。
参考资料 五分钟概述 AWS 转录
AWS 转录为 Docx。
隆起建模:快速介绍
了解提升建模如何改善传统数据科学应用。

摄影爱好者:摄影工作室
简介
本文涵盖了隆起建模背后的思想。
到本文结束时,你将会很容易向别人解释隆起建模是什么。
这是隆起建模系列的第一篇文章。
- 隆起建模:快速介绍
- 使用 Python 的应用隆起建模示例(即将推出)
- 通过提升建模引领优化示例(即将推出)
- 不同提升技术的比较(即将推出)
- 隆起建模的 5 个技巧(即将推出)
- 端到端提升建模项目(即将推出)
问题介绍
我们从一个实际应用开始,然后概括提升建模如何对任何行业和业务单位有用。
一家保险公司正在根据收集到的订单将前一天的新线索分配给保险代理人。通过呼出电话营销活动,代理可以将 5%的销售线索转化为销售额。
该公司已经意识到,他们现在一天产生的销售线索比代理能够工作的还要多。还有一种感觉是,很多线索都是浪费时间。
为了更好地实现数据驱动,该公司的数据科学团队希望优化处理线索的顺序。利用从网站上收集的线索数据,他们建立了一个模型,对每条线索转化为销售的可能性进行评分。
这样,代理可以在每天开始时密切关注最有机会在未来转化为销售的销售线索。他们还可以避免在很可能永远不会促成销售的线索上浪费时间。
该模型投入生产后,公司发现代理商现在将 10%的工作线索转化为销售。这是对旧操作的 100%改进!
我们需要休息一下!还没有击掌…
这个数据科学项目有一个重大缺陷。
这个项目看似成功,但你如何知道呼出电话营销活动是否导致了客户的转变?这可能只是樱桃采摘容易获胜。
换句话说,倾向模型所做的只是收集最有可能转化为销售的线索。它没有将已经打算购买的客户与需要通过呼出电话说服的客户区分开来。
欢迎来到隆起建模的世界——因果推理和机器学习之间的桥梁。上面的案例研究忘记考虑的是说服、渐进或外向销售活动的真实效果。
隆起建模
那么隆起建模是如何工作的呢?
上一节强调的购买倾向模型使用机器学习来回答这个问题:
“客户将来购买的可能性有多大?”
隆起建模通过回答更重要的问题对此进行了改进:
- “我的广告让顾客从我这里购买了吗?”
- “我是不是浪费钱向已经打算从我这里购买的顾客做广告?”
- 我的广告是否降低了人们购买的可能性(负面影响)?
换句话说,经典倾向模型(和大多数机器学习算法)在给定特征(x)的情况下预测目标(y)。在给定特征(x)的情况下,提升旨在解决处理(t)对目标(y)的影响。
隆起建模通常用四个客户群来解释(Siegel 2011 年):

1.无论什么(确定的东西)都会购买的人
2.只有在看到广告时才会购买的人(有说服力)
3.无论如何都不会购买的人(失败原因)
4.如果看到广告,那些不会购买的人(睡狗)
倾向模型通过帮助你避免失败的原因来增加价值。提升建模通过只关注可说服细分市场中的客户,进一步提高了针对性。

常见应用
这如何应用于任何业务单位或行业?
政治竞选:
提升建模已被用于识别和锁定持观望态度的选民( Stedman 2013 )。通过利用提升模型,政治营销活动可以避免那些对他们的政党死心塌地的人,而是只关注可说服的人。
一种新的健康疗法:
不仅仅是评估整个治疗组与对照组的结果,隆起建模可以帮助理解治疗如何不同地影响某些组。还有,这些影响的差异有多大。
也许这种治疗对 50 岁以上有潜在健康问题的人有很大的积极影响,但对 50 岁以下健康的人影响不大。
销售线索优化:(这听起来应该很熟悉)
一家公司有销售线索数据库,但他们生成的销售线索比能够处理的还要多,而且许多销售线索都是浪费时间,目前代理可以按照他们选择的任何顺序处理销售线索。
交叉销售:
一家公司想要开展交叉销售活动,假设他们不想向他们的整个客户群进行交叉销售,因为预算有限,一些人可能不需要或不想要其他产品。
保留:
一家公司希望接触到即将流失的客户,并拯救他们。该公司希望在接触客户时防止进一步扰乱客户,并只关注高风险的可挽救客户。
用户体验测试:
一家公司希望了解他们网站或应用程序的更改是否产生了预期的结果。
常用技法
在一个快速发展的空间里,我觉得技术目前可以分成三大支柱。

传统倾向模型
这实际上不是一个提升模型,但需要包括在内,因为这是解决提升问题的经典方法。该算法通常是像逻辑回归这样的分类器。这些算法可以输出 0 到 1 的概率,用于对观众进行排序。那么可以选择一个阈值(可能 0.70 的概率或更大)作为那些应该接受治疗的人的截止值。
直接提升型号
这个支柱代表的技术和算法可以让你直接模拟治疗效果。它需要像随机森林这样的算法完全重新设计,以进行特征选择、超参数调整,并适合解决给定(x)时(t)对(y)的影响。像 Scikit-learn 这样的包中的典型算法不能做到这一点。您可以使用 R 的包提升和 Python 的 CausalML 来实现提升树。
元学习者
最后一个支柱代表可用于对提升建模的技术和算法,但使用某种快捷方式来获得提升的代理。代理方法在大多数应用中是有用的,并且这些快捷方式通常在速度和/或简单性方面提供好处。
似乎有许多技术,所以下面的列表绝不是全面的。根据您要去的地方,似乎也有不同的方法来实现这些技术。

隆起建模的当前挑战
为什么隆起建模会很棘手。
- 除非数据是合成的,否则真相标签是不可用的。
在机器学习中,通常有特征(帮助预测的输入)和基本事实标签(预测的目标)。
在隆起建模中,地面真相是永远不可用的,因为个人不能既看到又看不到广告。因果推理模拟了没有发生的场景,因此有可能估计地面真相标签,并将其视为机器学习问题。
因为基本事实标签不可用,这使得测量和验证不太直接。通常,您可以通过比较预测值和实际值来了解模型的表现。在提升建模中,您可以通过与估计的实际值进行比较来了解模型的表现。
生成用于验证的合成数据的优势在于,它可以被构建为模拟两种场景。这样,不同的技术可以更清楚地评估,以选择一个赢家。然而,合成数据可能永远不会完美地反映您想要提升模型的真实世界数据。
2.像 Scikit-learn 这样高度优化的包并不是为了解决升级而设置的。
如前所述,机器学习算法被设置为在给定特征(x)的情况下预测目标(y)。直接建模需要调整算法和整个机器学习管道。功能选择、型号选择、超参数调整以及与 Scikit-learn 等优化包的匹配并不简单。
目前,(在撰写本文时)直接方法是可用的,但即使在小数据集上也很慢。
3.事物和技术的名称是无组织无共识的。
为了证明这一点,就连隆起建模的名称也会因观察地点的不同而有所变化:
根据我自己的研究,我不确定是否有一个全面的技术列表或关于如何实现每种技术的共识。
资源
重新列出我自己的收藏,然后还有其他值得注意的链接。
这是隆起建模系列的第一篇文章。
- 快速提升建模简介
- 使用 Python 的应用隆起建模示例(即将推出)
- 通过提升建模引领优化示例(即将推出)
- 不同升级产品包的比较(即将推出)
- 隆起建模的 5 个技巧(即将推出)
- 端到端提升建模项目(即将推出)
推荐包:
参考文献:
费,g .(2019 . 10 . 29)。直接建模抬升:以 KL 散度和欧氏距离为分裂准则的抬升决策树。
古铁雷斯,P. &杰勒迪,J. (2016)。因果推理和隆起模型:文献综述。 JMLR:研讨会和会议记录 67:1–13
昆泽尔、塞孔、比克尔和于(2019)利用机器学习评估异质治疗效果的金属学者。美国国家科学院院刊,116(10):4156–4165
米歇尔·雷内,施纳肯伯格,I .,&马滕斯,t .冯。(2019).目标提升:净得分介绍。查姆:斯普林格国际出版公司。
西格尔,E. (2011 年 10 月 19 日)。通过预测来优化营销影响力。
斯特德曼,C. (2013 年 11 月 11 日)。提升建模如何帮助奥巴马的竞选——以及如何帮助营销人员——机器学习时代——机器学习&数据科学新闻。
易,r .&弗罗斯特,w .(2019 . 2 . 7)。Pylift:用于隆起建模的快速 Python 包。
一种快速重新格式化熊猫数据框中的列的方法
大蟒
使用 df.melt 将多个列压缩成一列。

姐姐塑造的形象
直接进入分析可能很诱人,但在此之前的一个重要步骤是预处理。
Pandas 提供了许多内置功能,允许您按照自己需要的方式重新格式化数据帧。在执行计算或创建可视化之前,大多数数据集都需要某种形式的整形。
在这篇文章中,我们将会看到如何使用一个 **df.melt** 函数将多个列的值合并成一个。
这意味着您正在将数据帧从“宽”格式更改为“长”格式。当许多列在技术上具有相同类型的值时,这很有帮助。
例如,假设你拥有一家咖啡店,开始经营两种饮料。为了跟踪每种饮料的成分,您制作了一个如下所示的表格:

目前这可能行得通,但是如果你想包含一种有三种成分的饮料呢?您必须创建另一个类似“配料 3”的列,但是如果您想要一种含有 4、5 甚至 10 种配料的饮料呢?每次需要输入更多数据时都生成新列并不是最优雅的解决方案。
相反,如果你有一张这样的桌子就太好了:

现在,你的桌子灵活多了。您的饮料可以根据您的需要添加或多或少的配料,并且您不需要为不同类型的数据条目改变表格结构。
让我们在一个更复杂的例子上看看如何用df.melt来做这件事。我们将使用这个视频游戏销售数据的修改版本,所以如果你想继续的话,请下载 csv 文件。我已经为这个练习加载并预处理了它,所以您可以使用下面的代码开始。
# pre-processing data
df = pd.read_csv('vgsales.csv').dropna()
df['Year'] = df['Year'].astype(int)
df = df.loc[df['Publisher']=='Nintendo']
df = df.loc[(df['Platform']=='Wii') | (df['Platform']=='WiiU')]
df = df[['Platform','NA_Sales','EU_Sales','JP_Sales','Other_Sales','Global_Sales']]
df = df.groupby('Platform').sum().reset_index()

边注:如果你不熟悉 *df.loc[]* 功能,你可以看看我写的这篇文章和下面的其他矢量化熊猫解决方案。
用向量化解决方案看一下“for 循环”的替代方案。
towardsdatascience.com](/you-dont-always-have-to-loop-through-rows-in-pandas-22a970b347ac)
如何融化数据帧
您可以在上表中看到,我们有几个不同地区的总销售额。虽然这很容易阅读,但它不是最好的表结构。
我们的目标是将所有的销售额放在一列中,将所有的销售区域放在另一列中。
在此之前,我们先简单介绍一下df.melt函数。该函数有四个关键参数:
- id_vars - >用来标识每一行的列(类似于索引列)—传递一个列表;
- value_vars - >表格中要压缩(或取消透视)的列。如果您想压缩除 id_vars 之外的所有列,您可以将其留空—传递一个列表;
- var_name - >新“类别”列的名称,其中的值是您传递给“value_vars”的列名—传递一个标量值;
- value_name - >新“值”列的名称-传递一个标量值。
对于我们的表,我们需要用“Platform”列标识每一行,所以我们将把它传递给id_vars。我们的值列将是除“全球销售”之外的所有销售列,因为从技术上讲,这不是一个区域类别。我们将把一个列名列表传递给value_vars来实现这一点。
为了提高可读性,我们还将两个新列命名为“销售区域”和“销售额(百万)”,分别包含在var_name和value_name参数中。
最终的代码如下所示:
df = df.melt(id_vars=['Platform'],
value_vars=['NA_Sales','EU_Sales','JP_Sales','Other_Sales'], var_name='Sales Region',
value_name='Sales (millions)')

就在那里!我们已经将所有旧的列名移到一个新的 category 列中,并将它们的值合并到一个 values 列中。
为了更好地表示,我们还可以用一行额外的代码对表进行排序:
df1 = df1.sort_values(['Platform','Sales (millions)'], ascending=False)

我希望你发现这个df.melt的快速浏览对你的熊猫工作有用!不涉及太多细节,您也可以实现这种技术来创建满足 1NF 的表,并更好地组织关系数据库的输入。
Pandas 还提供了比我上面使用的方法更多的排序方法,所以如果你想了解更多,你可以看看这篇文章:
正确探索、理解和组织您的数据。
towardsdatascience.com](/4-different-ways-to-efficiently-sort-a-pandas-dataframe-9aba423f12db)
祝你和熊猫的冒险之旅好运!
通过网络抓取构建数据集的更快捷方式
通过抓取 Yelp 评论来比较 Autoscraper 和 Selenium + BeautifulSoup

托马斯·毕晓普在 Unsplash 上的照片
如果你想跳过 HTML 标签的挖掘,直接进入抓取,这里是要点。注意,scraper 试图与你想要的列表中的每一项进行精确匹配。否则,请继续阅读有关网络抓取的简短背景知识,这对于抓取网站很有用,以及抓取时您可能会遇到的一些挑战。
背景
我最*在研究美国的泡沫茶趋势。我想看看饮料订单的变化,精品和特许泡泡茶店开业的时间,以及顾客对这些店的评价。很自然地,我转向 Yelp。但是一些限制很快让我退缩了;我被限制在 Yelp API 上的前 1000 个商家,每个商家我只能得到三个 Yelp 精选评论。
从商业的角度来看,这是有意义的——你不希望其他企业轻易窥探你的成功和失败,并重复这些。但它也展示了网络抓取的更大不幸。一方面,这是为我们感兴趣的课题获取数据的好方法。另一方面,公司很少希望机器人在他们的网站上互动。即使他们提供了 API,他们也不总是公开所有需要的信息。
针对网络抓取的安全性也提高了。从标题数据验证,到验证码挑战,再到机器学习指导的行为方法,已经投入了大量工作来使机器人更难祸害网站。最后,大多数页面不会立即用 HTML 提供有用的信息。相反,它们是通过 JavaScript 执行注入的,并且只有在检测到“真实用户”时才注入。
因此,值得信赖的过程:
- 手动导航到网站
- 突出显示感兴趣的部分
- 右键单击并检查元素
- 复制 html 标记或 XPath,并使用 BeautifulSoup 之类的库来解析 HTML
该过程
这是我项目中的一个例子。比方说,你想解析 Yelp 上关于某个泡泡茶店的评论https://www . Yelp . com/biz/chun-yang-tea-flushing-new York-flushing?osq = bubble % 20 tea&sort _ by = date _ desc(我不属于这家泡泡茶店,也不属于 Yelp。这是我目前项目中的一个样本,分析美国的泡沫茶趋势。)
为了在动态网页上执行任何 JavaScript,您首先需要设置一个无头浏览器,或者模拟真实浏览器的标题。
然后,将它连接到一个可以从 HTML 和 XML 文件中提取数据的库。
为了找出将我引向评论的特定标签lemon--span__373c0__3997G raw__373c0__3rKqk,我按照上面编号的步骤列表,突出显示一个示例评论,检查元素,并四处窥探感兴趣的标签。
问题是
这实际上是非常脆弱的,因为网站可能会随时改变它们呈现页面的方式。更重要的是,这个过程是多余的,因为我们需要首先手动找到想要的标签,然后才能设置一个自动化的 webscraper。
另一种方法
与其搜索 HTML 标记或 XPath,为什么不使用简单的匹配规则自动进行手动搜索呢?这是 Alireza Mika 的 AutoScraper 库的基本前提。让我们完成搜集 Yelp 评论的相同任务,这次是用 AutoScraper 库。
AutoScraper对象#3 接受目标 url #1 和想要的项目列表#2,并围绕提供的参数#4 建立一些规则。请注意,它只会标记与感兴趣的项目完全匹配的标签;因此,我列入通缉名单的评论是 Yelp 网页上第一篇完整的评论。
在打印results时,你将会看到 webscraper 找到的所有元素。您可以使用以下命令在同一个或另一个 url 上再次获取这些结果。
scraper.get_result_similar(url)
你可能会注意到,刮刀已经获得了一些无关的信息。您可以微调其选择,方法是首先根据刮刀已学习的规则对其进行分组:
groups = scraper.get_result_similar(url, grouped=True)
由于groups是一个字典,你可以通过调用print(groups.keys())得到规则的名称
然后,您可以使用特定的规则键入字典:
groups['rule_io6e']
如果指定规则的结果准确地反映了期望的结果,你可以选择用方法调用来保持规则:
scraper.keep_rules('rule_io6e')
最后,您可以将模型保存到文件中以备后用。
scraper.save('yelp-reviews')
最后
当然,这个库并不是万无一失的。如果没有浏览器模拟器,点击量大的网页(如谷歌的商业评论)将很难实现自动化。
由于 AutoScraper 希望通缉列表中的物品与网站上出现的物品完全匹配,因此很难确定一个不断更新的值,如股票价格。
然而,作为开发人员,我们的部分职责是将解决方案沿着管道连接在一起,以迭代或创建新产品。希望你可以利用这个抓取库,无论是在 scrapy 这样的框架中,还是只是为了简化你的下一个抓取任务。
不管你如何决定刮一个网站,这样做负责任!
- 不要用请求轰炸网站。这是网络抓取新手犯的头号错误:他们试图通过一次从多个服务器发送多个请求来加快抓取速度——这是一种 DDoS 攻击!
- 尊重 robots.txt:你通常可以通过在索引页面添加
robots.txt来找到它们。比如https://www.yelp.com/robots.txt - 使用提供的 API!
TensorBoard 快速入门指南
如何使用 TensorBoard 可视化 ML 实验

艾萨克·史密斯在 Unsplash 上拍摄的照片
大家都认同“视觉胜于文字”。可视化在任何一种解释中都提供了可行性和交互性。ML 建模也是如此。人们可能希望监控训练损失或权重和偏差,以改善模型性能。这可以用 TensorBoard 来可视化。
TensorBoard 是 TensorFlow 的可视化工具包。它提供了各种功能来绘制/显示机器学习管道的各个方面。
在本文中,我们将介绍 TensorBoard 的基础知识,并了解如何可视化各种机器学习任务中的一些要素。
如何推出 TensorBoard?
首先,我们需要了解如何使用命令行/笔记本导入和启动 TensorBoard。我们使用这个神奇的命令加载 TensorBoard 笔记本扩展:
%load_ext tensorboard
通过命令行或在笔记本中启动 TensorBoard。在笔记本上,使用 %tensorboard 线条魔法。在命令行上,运行不带“%”的相同命令。
%tensorboard --logdir <log_directory>
在接下来的章节中,我们将会看到什么是日志目录以及它的重要性。
损耗
一个模型应该是通用的,而且必须对看不见的数据做出准确的预测。为此,我们监控验证(或开发)数据的损失和其他指标,并确保损失不会相差太多。这可以通过在培训时间内可视化这些指标以更有洞察力的方式来完成。

可视化训练和评估损失和准确性
前面提到的是 TensorBoard 对 Train(橙色)和 Val(蓝色)损耗和精确度的交互式可视化(从上到下)。可以清楚地观察到,训练和 val 损失在训练过程中一直在减少(横轴是历元),这给出了模型正在实现泛化以及低偏差的直觉。读取偏差-方差权衡。
那么,我们该怎么做呢?
使用 Keras API
当使用 keras API 训练一个模型时,我们创建一个 tensorboard 回调,确保指标被记录在指定的目录中。
日志记录指标
使用自定义训练循环
当手动定义训练循环时,我们需要手动记录损失。 tf.summary API 促进了这一点。首先,我们为指定的日志目录定义一个文件写入器(分别用于训练和测试),然后使用这个文件写入器实例,我们在每个时期后将数量记录为标量。因此,我们可以在训练过程中逐步观察这些指标的趋势。
自定义培训中的手动登录
可训练参数
在前面的部分中,在创建 tensorboard 回调时,我们将 histogram_freq 参数设置为 1。
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, **histogram_freq=1**)
直方图和分布仪表盘允许我们可视化张量随时间的分布。使用这些,我们可以监控权重、偏差、激活等等。
histogram_freq 告诉 tensorflow 在每个历元后计算分布。如果设置为 0,则不会绘制任何分布。

密集层权重分布的偏移和叠加直方图
上图是模型中密集(完全连通)图层的权重分布直方图。左边是偏移视图,而右边是同一分布的叠加视图。
请注意,该分布类似于正态分布。
偏移视图
在偏移视图中,我们有一个三维图形:
- 水*轴对应于权重的值;基本上这一层的权重取值范围。在这种情况下,[-0.6 到 0.6]。
- 垂直轴对应于分布。直观地,这些值显示了层中相应权重值相对于其他值的出现次数。例如,在上面的图像中,我们可以看到峰值为 0.0626 的 685,这表面上意味着 685 个输入假定值为 0.0626。
- 深度轴本质上是步骤(或时期)。我们可以观察这些步骤中重量分布的变化。
覆盖视图
叠加视图本质上是同一直方图的二维表示。这里,深度(历元)轴被压缩以获得分布之间的直接比较。我们可以将鼠标悬停在图上,突出显示特定步骤的分布。
还有另一种方法来可视化权重在各个时期的分布。

各时期权重和偏差范围的趋势
这是 tensorboard 互动工具包的发行版标签。
相邻的图实际上是先前直方图中深度和水*轴之间的图。
该图本质上描述了层的权重值在各个时期的变化范围。
韵律学
使用 TensorBoard,以及前面讨论的默认指标,我们还可以记录和可视化我们在建模中使用的任何自定义指标。在本例中,我们将可视化学习率,该学习率将由自定义学习率调度程序进行调整。
自定义学习率计划程序回调
我们首先定义一个自定义的学习率计划。然后我们为它创建一个回调,确保调度程序在定义每个时期的学习速率时被调用。我们已经使用 tf.summary API 记录了学习率,我们在前面的小节中已经讨论过了。

监控各时期的学习率
可以观察到,无论我们在调度程序中定义了什么,学习率都会下降(参见时期 10、20 和 50)。
计算图表
我们可以使用图形仪表板轻松查看模型结构的概念图,并确保它与我们的预期设计相匹配。这也是对 TensorFlow 如何解释模型的一个很好的洞察。

TensorBoard 的图表仪表板
每个展开的视图都显示了对模型计算工作流的更深入的了解。
对于 Keras 模型,除了创建一个 tensorboard 回调来查看 graphs 仪表板之外,不需要任何特别的工作。
然而,在必须定义自定义计算的情况下, tf.function 注释将 python 计算函数转换成张量流图。可以使用 tf.summary 跟踪 API 来跟踪和记录这个图表。
追踪 tf.function 图
如文档中所述,要使用摘要跟踪 API:
- 在您的函数调用站点之前立即使用 tf.summary.trace_on() 。
- 通过传递 profiler=True 向图形添加分析信息(内存、CPU 时间)
- 使用摘要文件编写器,调用TF . Summary . trace _ export()保存日志数据
形象
绘制图像类似于绘制任何其他标量值。但是要用 TensorBoard 可视化 matplotlib 的图,需要先转换成图像。为此,我们有一个将 pyplot 图转换成图像的样板代码:
绘制到图像
这里,我们举一个例子,用 tensorboard 绘制一个视觉上生动的混淆矩阵。
首先,我们添加一个 LambdaCallback,它将在每个时期后被调用,计算混淆矩阵并记录下来。
创建 lambda 回调
然后,我们使用 pyplot 创建混淆矩阵的可视化。
情节混乱矩阵
这将返回一个 pyplot 图,我们使用前面讨论过的样板代码将它转换成图像。

混淆矩阵在历元上的转换
嵌入
嵌入本质上是非常复杂的量在向量方面的表示,其中向量中的值具有相对于其他相关量的归属的概念。我们可以使用 TensorBoard 的嵌入投影仪来可视化高维嵌入。这对监控 keras 嵌入层很有用。

使用 TensorBoard 的嵌入投影仪可视化嵌入
我们以序列分类任务为例,将 imdb 电影评论分类为正面或负面。我们构建了一个简单的模型,包含一个嵌入层和几个完全连接的层。
为了记录和可视化,我们首先将词汇表中的单词写到文件中。
将词汇表写入文件
然后,我们将训练好的嵌入权重检查点放入一个变量,然后放入一个文件。
从变量中保存训练的权重
最后,我们设置投影仪配置并投影嵌入:
配置和投影
结论
我们看到了什么是 TensorBoard,并探索了一些基本的东西。然而,我想特别提到一些我在这里没有提到的东西。
- 超参数调谐
- 假设分析工具
- 仿形
- 公*性指标(Beta)
如果有兴趣,你可以在这里查看这些。
这里的是本文所涉及主题的完整代码的链接,可以随意分叉。
参考
本指南中使用的代码引用自以下官方 TensorFlow 文档:
[## TensorBoard | TensorFlow 入门
在机器学习中,为了改进某些东西,你通常需要能够测量它。TensorBoard 是一款提供…
www.tensorflow.org](https://www.tensorflow.org/tensorboard/get_started) [## 了解张量板(权重)直方图
看到和理解 TensorBoard 中的标量值真的很简单。然而,不清楚如何…
stackoverflow.com](https://stackoverflow.com/questions/42315202/understanding-tensorboard-weight-histograms)
请参见
[## 深入 TensorBoard:示例教程- neptune.ai
有一个常见的商业说法是,你不能改进你没有衡量的东西。这在机器学习中是正确的,因为…
海王星. ai](https://neptune.ai/blog/tensorboard-tutorial)
CNN 深度学习阅读指南
第一部分:图像识别和卷积骨干网
本系列的下一部分是:第二部分:图像分割
这个系列是关于什么的
想象一下,你一觉醒来,感觉有一种数据科学探险的冲动。你决定投身于人们谈论的深度学习。太好了,在深入无尽的 Github 森林,在远程资源库中四处乱砍之前,您打开 PC,查看一些艺术文献。在你准备的过程中,可能会发生的是,你偶然发现了一个有前途的作品,告诉你他们已经使用了三重 ResNeXt-101 级联掩模 R-CNN 或类似的东西…啊哈…

来源:img lip
你的旅程可能会在这里结束,你会回到你舒适的小屋,没有装满闪亮的算法和知识的箱子,你可以在你当地的酒馆里分享。
这一系列是关于通过你在冒险中必须知道的术语和历史提供一个指南。深度学习文献、科学出版物以及关于它的博客和讨论,充满了概念和模型的缩写和花哨的名称。开始阅读它感觉就像试图用一个普通的水桶抓住一个瀑布。 在这个系列中,你会找到一个阅读指南,引导你浏览科学和非科学的里程碑文献,以及关于深度学习和卷积神经网络(CNN)的额外解释。
这个系列的动机
几年前,我正处于投入深度学习冒险的境地。尽管有数据分析的背景,但习惯深度学习中应用的术语和概念还是有点挑战。开始阅读深度学习文学对我来说就像开始阅读《权力的游戏》小说一样:一大堆无尽的名字和关系;高度分支的家族树,以几乎相同的名字在这里和那里合并和分支…仍然,相当令人兴奋的阅读。
我开始从字面上绘制这些深度学习架构的家谱,最终有了从 2012 年到 2019 年底的 CNN 在图像识别、图像分割和对象检测方面的发展概况。我决定把它写下来,它最终变成了这篇开放存取评论论文[1]:
[## 基于对地观测数据深度学习的目标检测和图像分割:综述-部分…
深度学习(DL)对大部分科学产生了巨大影响,并日益成为一种自适应的学习方法
www.mdpi.com](https://www.mdpi.com/2072-4292/12/10/1667)
非常欢迎任何对以科学文献为重点的 CNN 图像处理深度学习的科学但直观的综述和直接阅读指南感兴趣的人阅读它。尽管它是为遥感杂志写的,但它从计算机视觉的角度讲述了进化,因此适用于使用 CNN 进行图像处理的每个领域,而不仅仅是遥感。
"好吧,既然这个指南已经存在,为什么还要写这篇中间文章呢?"合法的问题,为了进一步强调《权力的游戏》的类比,这样考虑它:主要的书籍讲述了所有事实和进展的故事,直到结束;与在会议、同行评审期刊和 arXiv 上发表的关于深度学习的科学文献相同。你可以通过阅读主要文献来了解整个故事。但是还有更多的,支持主要情节的次要故事,同人小说和关于单个角色的讨论,关于我们感兴趣的世界起源的整个故事,或者仅仅是传说。对我来说,我认为像 Medium、Youtube 或 Stackexchange boards 这样的地方是你可以找到关于深度学习文献的知识的来源,这使得主要故事更加直观。因此,除了科学文献之外,这份阅读指南还有一些其他的来源,我发现这些来源对于思考科学发表的论文中所讨论的内容非常有帮助。
如何使用本指南
下面的表格是以这样一种方式组织的,你可以决定你想要深入到什么程度。每个表格中的前几个来源是介绍、概述或评论。其余的按某种方式排序,你将逐步需要以前来源的信息。所以,我建议去这个系列的 Github 库,拿到表格,开始阅读,自己做笔记。花所有你需要的时间来通过,但是每次你在信息的深地牢中迷路时,回到指南并想出下一步去哪里,或者回到一个你感觉舒服的点并重新开始。
这份阅读指南发表在媒体故事系列中,是一份关于 CNN 深度学习的阅读指南。它补充道…
github.com](https://github.com/thho/CNN_reading_guide)
我希望你能像我一样享受这次冒险,并经历那些洞察力开始相互交融的史诗般的时刻!
深度学习

来源: imgflip
图像识别和卷积骨干网
2012 年,Alex Krizhevsky 等人[2]通过引入 CNN AlexNet 赢得了 ILSVRC。加上 Ciresan 等人(2012) [3]的发表,2012 年可以被视为深度学习和 CNN 研究现代发展的起点。这两个出版物都是关于预测图像的单个标签的任务,即所谓的图像识别或图像分类。这项任务的后继者正致力于优化 CNN 的重要特征提取器,即所谓的卷积骨干网。由于卷积骨干也用于例如图像分割和对象检测,图像识别的发展成为整个领域的驱动力。因此,理解细胞神经网络在图像识别方面的发展对于进一步阅读是至关重要的。

介绍用于图像识别的 CNN 架构及其在 ImageNet 2012 数据集上的性能,圆圈的大小与对数标度中的参数数量有关。资料来源: Hoeser and Kuenzer 2020 第 10 页 [1]。
上图显示了分为 5 个系列的里程碑建筑,有助于组织阅读
古典建筑
Vintage 架构以其堆叠运算的理念而闻名,该理念在深入网络的同时从输入数据中提取要素。他们建立了这种经常被比作哺乳动物视觉皮层的结构。
盗梦空间系列
Inception 家族起源于 Le Cun 等人 1989 年的早期工作[4](所谓的 LeNet),其网络也被称为 GoogLeNet。他们因以下原因而闻名:
- 复杂的构建模块
- 参数高效设计,如卷积运算的瓶颈设计或因子分解
- 最重要的是,Inception 家族引入了批量规范化,这对训练深度网络非常重要。
ResNet 家族
ResNet 家族都是关于残余连接的。这种设计卷积模块的新方法,通过连接绕过卷积运算,使网络变得相当深入,但仍然是可训练的。ResNet 家族的架构是当今非常受欢迎的特征提取器。
高效的设计
最后一组是 NAS 和 MobileNet 系列,因为它们的目标都是参数高效,它们共同发展,最终成为 2019 年的高效网络模型,即 sota 架构。
手头有了这些文献,你就为深度学习冒险的第一个挑战做好了充分的准备。我强烈建议你做些旁门左道的事情,比如访问一个在线课程,或者通过探索 TensorFlow 或 Pytorch 来尝试一下,如果你已经准备好进行下一步,就回到你的阅读指南。在本系列的下一部分中再见,我们将探讨图像分割这一章。
参考
[1]赫泽,T;利用对地观测数据的深度学习进行目标探测和图像分割:综述-第一部分:发展和最*趋势。遥感 2020,12(10),1667。DOI: 10.3390/rs12101667。
[2]克里热夫斯基,a;苏茨基弗岛;Hinton,例如,使用深度卷积神经网络的 ImageNet 分类。神经信息处理系统的进展:f .佩雷拉、Burges、C.J.C .、Bottou、l .、Weinberger、K.Q .编辑。;柯伦联合公司:美国纽约州红钩镇,2012 年;第 25 卷,第 1097-1105 页。
[3] Ciresan,d;Meier,u;用于图像分类的多列深度神经网络。2012 年 IEEE 计算机视觉和模式识别会议(CVPR)论文集,美国罗德岛普罗维登斯,2012 年 6 月 16-21 日;第 3642-3649 页。
[4] LeCun,y;博瑟湾;登克,J.S。亨德森博士;霍华德;哈伯德,w。应用于手写邮政编码识别的反向传播。神经计算。1989, 1, 541–551.
CNN 深度学习阅读指南
第二部分:图像分割
欢迎回到本系列的第二部分。如果你错过了第一部分,看看这里:第一部分:图像识别与卷积骨干 。
在这一部分中,您将通过有关卷积神经网络(CNN)图像分割的文献找到指南,直到 2019 年。它在 这篇开放存取综述论文 中增加了非科学来源,以进一步增加对 CNN 进化的直观理解。
与第一部分相同,您可以在 github 资源库中找到源代码表:
这份阅读指南发表在媒体故事系列中,是一份关于 CNN 深度学习的阅读指南。它补充道…
github.com](https://github.com/thho/CNN_reading_guide)
现在,让我们和 CNN 一起进入深度学习冒险的下一个篇章。
基于细胞神经网络的图像分割概述
在图像分割过程中,对每个像素预测一个类别,如下所示:

图像分割示例。修改依据: Hoeser and Kuenzer 2020 第 8 页【1】
当我们在第一部分中讨论的 CNN变得更加流行时,它们首先被用于所谓的基于小块的图像分割。因此,CNN 以移动窗口方式在输入图像上移动,并预测小块(整个图像的一小部分)或整个小块的中心像素的类别。
随着 Long 等人 2014 年[2]的工作,所谓的全卷积网络(FCNs)被引入,使用 CNN 的图像分割变得更加复杂。总的来说,FCNs 中的处理看起来是这样的:首先通过使用卷积骨干从输入图像中提取特征(编码器,参见第一部分)。因此,分辨率越来越小,而特征深度越来越大。这样提取的特征图具有高语义,但是没有精确的定位。由于我们需要对图像分割进行逐像素预测,因此该特征图会被向上采样回输入分辨率(解码器)。与输入图像的不同之处在于,每个像素持有一个离散的类别标签,因此图像被分割成语义上有意义的类别。
存在两种主要的不同概念,即如何在解码器中进行上采样:
- 朴素解码器(该术语例如在 Chen 等人 2018 [3]中使用):通过应用例如双线性插值来完成上采样
- 编码器-解码器:上采样是通过可训练的去卷积操作和/或通过在上采样期间将来自编码器部分的特征与更高的定位信息合并来完成的,参见那些例子:

资料来源:Hoeser 和 Kuenzer 2020 年第 17 页【1】
为了利用深度学习深入研究图像分割,下表中的来源是很好的起点。请注意,除了 CNN 之外,还有其他执行图像分割的深度学习模型类型,如生成对抗网络(GANs)或长短期记忆(LSTM)方法;本指南主要关注 CNN。此外,有时从图像分割的角度讨论 R-CNN 家族的模型。本指南将在下一部分讨论物体检测时讨论它们。所以,当你在别的地方读到它们(比如在评论文章中)而这里没有提到它们时,不要感到困惑。
模糊神经网络在图像分割中的发展

PASCAL-VOC 2012 基准数据集上不同 FCN 启发的里程碑式架构的性能演变概述。*这些模型在其他数据集上进行了测试。资料来源:Hoeser 和 Kuenzer,2020 年,第 17 页[1]
DeepLab 家族的发展是 FCN 启发的图像分割模型发展的特征。DeepLab 变体可以在 naive-decoder 和 encoder-decoder 模型中找到。因此,本指南首先着眼于简单的解码器,然后转向编码器-解码器模型,从而对这一系列进行定位。
朴素解码器模型
朴素解码器模型的最重要的见解主要是建立所谓的 atrous 卷积和用于像素级预测的长距离图像上下文开发。阿特鲁卷积是普通卷积的一种变体,它允许在不损失图像分辨率的情况下增加感受野。DeepLab-V2 [4]中著名的阿特鲁空间金字塔池模块( ASPP 模块)以及后来的组合:Atrous 卷积和长距离图像上下文开发。阅读以下文献时,请关注这些功能的发展——阿特鲁卷积、ASPP 模块和远程图像上下文开发/解析。
编码器-解码器模型
今天,最著名的编码器-解码器可能是 U-Net [5]。为分析医学图像而开发的 CNN。其清晰的结构吸引了许多研究人员进行试验和采用,并以其跳跃连接而闻名,这允许编码器和解码器路径之间共享功能。编码器-解码器模型关注于在解码器中的上采样期间,利用来自编码器的更局部精确的特征映射来增强语义丰富的特征映射。
有了手头的文献,你将能够思考现代图像分割论文和 CNN 的实现。让我们在第三部分再次见面,我们将讨论对象检测。
参考
[1]赫泽,T;利用对地观测数据的深度学习进行目标探测和图像分割:综述-第一部分:发展和最*趋势。遥感 2020,12(10),1667。DOI: 10.3390/rs12101667。
[2]龙,j;谢尔哈默,e;语义分割的完全卷积网络。IEEE Trans。肛门模式。马赫。智能。2014, 39, 640–651.
[3]陈;朱;帕潘德里欧;施若夫,f;语义图像分割的阿特鲁可分卷积编码器-解码器。在计算机视觉领域——ECCV 2018;法拉利 v,赫伯特 m,斯明奇塞斯库 c;韦斯,y,编辑。;施普林格国际出版公司:瑞士查姆,2018 年;第 833-851 页
[4]陈;帕潘德里欧;科基诺斯岛;墨菲,k。用深度卷积网、阿特鲁卷积和全连接条件随机场进行语义图像分割。IEEE Trans。肛门模式。
马赫。智能。2016, 40, 834–848.
[5] Ronneberger,o;菲舍尔,p。生物医学图像分割的卷积网络。医学图像计算和计算机辅助介入——MICCAI 2015;Navab,Hornegger,j .,
Wells,W.M .,Frangi,A.F .编辑;施普林格国际出版公司:瑞士查姆,2015 年;第 234-241 页。
Python 中的实时产品推荐器

克里斯蒂安·威迪格在 Unsplash 上拍摄的照片
我们如何调整我们的电子购物体验?
我们可能会同意,我们这些熟悉网上购物的人都有在亚马逊购物的经历。多年来,它无疑已经成为最大的电子购物中心之一。因此,当我们搜索某样东西时,我们可以依靠亚马逊的搜索算法,根据我们的搜索词为我们提供几个最佳选择。让我们来谈谈如何轻松使用基于亚马逊结果的实时产品推荐器,并微调我们的购物体验。
这个想法背后的动机
驱动的想法是,看看我们能使我们的购物过程变得多么健壮和用户友好。比如说,我们想买一副耳机。如果我们在亚马逊上搜索,它会给出一个大约 25-30 种产品的列表。现在,每个买家都有一些偏好。这些偏好中最重要的是品牌规格和定价。除此之外,买家还会考虑其他几个因素,如产品受欢迎程度、产品评级、产品评论和最佳价格匹配。此外,作为用户,我们有时也会觉得,如果我们能一眼看到几个产品提供的规格,并从专家的角度做出决定,那就太好了。
现在,每个顾客的需求都不一样。比方说,一些购物者关注评论,一些关注评级,而另一些则坚持价格。所以,如果我们能给用户提供决定他/她想关注什么的权力,这不是很好吗?所以,让我们看看如何实现这些目标。
这个想法
这个想法是给每个产品分配一个基于字段的分数,用户可以在购物时查看。例如,我们分配一个产品,基于流行度的分数,基于评论的分数,等等。随后,我们根据用户偏好计算加权分数。
让我们用一个具体的例子来看看这个想法。比如说,我们想买一个耳机。因此,我们搜索并获得一个包含 25 个项目的列表。我们根据评级为每个产品分配可变分数 x1,根据受欢迎程度分配 x2,根据评论分配 x3,根据价格限制分配 x4。现在,我们询问用户他/她是否有任何偏好,比如更关注某个方面。例如,如果用户希望更多地关注评论,我们将整体得分计算如下:
y= x1+x2+ax3+x4
这给了 x3 更多的权重。如果用户没有这样的偏好,那么我们可以计算为。
y= x1+x2+x3+x4
这里,我们将每个值标准化为最大值 1,以保持每个因素的权重*衡。接下来,我们可以根据 y 值对产品进行排序,以获得我们的结果。
同时,我们将创建所有产品的规格列表,以帮助具有特定需求的用户直观地了解哪种产品最适合他们。
让我们跳到应用程序
应用
如果我们在亚马逊网站上搜索,我们的选项如下所示。

我们将废弃亚马逊搜索算法给出的选项。我们将使用 Selenium Webdriver 来完成这项工作。

如果我们仔细观察搜索栏,并打破它,我们可以很容易地框住我们的直接搜索网址,这将有助于我们登陆亚马逊搜索页面。
import re
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoupimport requests
def search_am(phrase):
link="[https://www.amazon.in/s?k=](https://www.amazon.in/s?k=)"
l_end="&ref=nb_sb_noss"
phrase_w= phrase.replace(' ','+')
link_full=link+phrase_w+l_end
#print(link_full)
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 5)
driver.get(link_full)
names_f=[]
names=driver.find_elements_by_tag_name("a")
i=0
for name in names:
className = name.get_attribute('class')
if className=='a-link-normal a-text-normal':
names_f.append(name)
i+=1
links=[]
for i in names_f:
temp= i.get_attribute('href')
links.append(temp)
driver.quit()
return links
上面的函数帮助我们抓取搜索页面上所有列出的产品的所有链接,并返回链接。
每个链接都将我们引向一个特定的产品页面。

接下来,我们将重点关注产品页面的某些部分。
- 评级部分:

这部分提到产品的等级。
2.受欢迎程度部分:在这里,我用收视率来衡量受欢迎程度。

3.价格部分:这部分给出了产品的价格。

4.规格部分:它列出了所有的产品规格和细节。

5.评论部分:这个部分反映了产品的评论。

现在,如果我们在这里用粗体字显示,那么每个评估都有一个声明。这一行给出了评论的要点。我们会拿起这些句子,判断情绪,分配复习分数。
让我们首先从产品页面中删除所需的细节。
def get_element_dets(link):
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 2)
driver.get(link)
title_o= driver.find_elements_by_id("productTitle")
title=title_o[0].text
number_o= driver.find_elements_by_id("acrCustomerReviewText")
try:
popularity=(number_o[0].text)
except:
popularity='0'
rate=driver.find_elements_by_css_selector("#reviewsMedley > div > div.a-fixed-left-grid-col.a-col-left > div.a-section.a-spacing-none.a-spacing-top-mini.cr-widget-ACR > div.a-fixed-left-grid.AverageCustomerReviews.a-spacing-small > div > div.a-fixed-left-grid-col.aok-align-center.a-col-right > div > span > span")
try:
rate_o=(rate[0].text).split(' ')[0]
except:
rate_o='0'
feat_f=[]
tag=[]
value=[]
#features=driver.find_elements_by_css_selector("#feature-bullets > ul > li > span")
#for f in features:
# feat_f.append(f.text)
price=0
try:
tag_o=driver.find_elements_by_tag_name('th')
for name in tag_o:
className = name.get_attribute('class')
if className=='a-color-secondary a-size-base prodDetSectionEntry':
tag.append(name.text)
value_o=driver.find_elements_by_tag_name('td')
for name in value_o:
className = name.get_attribute('class')
if className=='a-size-base':
value.append(name.text)
i=0
while i<len(value):
t=str(tag[i])+':'+str(value[i])
feat_f.append(t)
i+=1
except:
feat_f=[':']
try:
price_o= driver.find_elements_by_id("priceblock_ourprice")
for name in price_o:
className = name.get_attribute('class')
if className=='a-size-medium a-color-price priceBlockBuyingPriceString':
price=(name.text)
break
except:
price=0
#price=price_o.text
feedbacks=driver.find_elements_by_tag_name("a")
feedback_f=[]
for feed in feedbacks:
className = feed.get_attribute('class')
if className=='a-size-base a-link-normal review-title a-color-base review-title-content a-text-bold':
feedback_f.append(feed.text)
driver.quit()
return feedback_f,title,rate_o,popularity,feat_f,price
上面的代码片段有助于删除产品页面所需的所有细节,并返回产品标题反馈、评分、流行度和其他所需的值。
def caller(phrase):
links=search_am(phrase)
data={}
print(len(links))
for link in links:
data[link]={}
feedback_f,title,rate,popularity,feat_f,price=get_element_dets(link)
data[link]['feedback']=feedback_f
data[link]['title']=title
data[link]['rate']=rate
data[link]['popularity']=popularity
data[link]['features']=feat_f
if isinstance(price, int):
data[link]['price']=price
else:
data[link]['price']=price.split(' ')[1]
#print(len(data))
return data
上面的代码片段有助于以字典格式排列所有产品及其相应的特性。

每个产品的键都是它的链接,相应地,嵌套字典中的所有特性都是键值对。
Amazon 页面的标签很少会有变化,不过,最好还是使用 try 和 exception 块来处理错误,以防万一。
现在,在我们丢弃了所有需要的数据之后,让我们开始分配分数。
基于流行度和等级的系统
def assign_popularity_rating():
with open('products.json', 'r') as openfile:
data = json.load(openfile)
temp=0
for k in data.keys():
p=int(data[k]['popularity'].split(' ')[0])
r=float(data[k]['rate'])
if p<50:
temp=1
elif p<100:
temp=2
elif p<150:
temp=3
else:
temp=4
score=(temp)
data[k]['Popularity_Score']=score
data[k]['Rating_Score']=r
with open("products_mod.json", "w") as outfile:
json.dump(data, outfile)
上面的代码用于根据人口和评级来分配每个产品的分数。对于人口,我使用了宁滨或类的方法。我们已经从刮擦获得的值中获得的评级。
审查基于情感的系统
from textblob import TextBlob
def assign_sentiment_rating():
with open('products_mod.json', 'r') as openfile:
data = json.load(openfile)
sm=0
for k in data.keys():
temp=data[k]['feedback']
z=0
sm=0
for i in temp:
#print(i)
z+=1
t=TextBlob(i).sentiment.polarity
#print(t)
sm+=t
if (z==0):
rating=0
else:
rating=sm/z
data[k]['Review_Score']=rating
with open("products_mod_2.json", "w") as outfile:
json.dump(data, outfile)
对于评论情感极性检测,我使用了 TextBlob 库的情感极性功能。它根据从评论中检测到的情绪分配一个从-1 到+1 的值。对于一个产品,我们有多个评论,因此,对于每个评论,我们都有一个值。因此,我们将从所有评论中获得的所有值相加,并除以评论的数量,试图使总分小于或等于-1。因此,我们对每个产品重复这一过程,并获得每个产品的评级。
价格相关性系统
def check_price_relevence():
with open('products_mod_2.json', 'r') as openfile:
data = json.load(openfile)
print("Specify the approx price to tune search")
price=int(input())
print("Specify a margin")
margin=int(input())
for k in data.keys():
data_ref=str(data[k]['price']).replace(',','')
temp=float(data_ref)
if temp<price+margin and temp>price-margin:
rating=1
else:
rating=0
data[k]['Price_relevence_Score']=rating
with open("products_mod_3.json", "w") as outfile:
json.dump(data, outfile)
这是我们的价格相关性函数。它要求一个大概的价格和比较的利润。然后,它比较产品的价格和范围,以分配相关性分数。
在分配完所有分数后,我们的字典会为每个产品添加以下内容。

收集规格
接下来,我们将为有特定需求的客户创建一个包含所有列出产品规格的 csv 或 excel 文件。
import pandas as pd
def form_featureset():
with open('products_mod_3.json', 'r') as openfile:
data = json.load(openfile)
feat=[]
set_c=[]
for k in data.keys():
temp=data[k]['features']
temp2=[]
for i in temp:
tag=i.split(':')[0]
if tag not in feat:
feat.append(tag)
#print(feat)
for k in data.keys():
temp=data[k]['features']
temp2=[-1]*len(feat)
for i in temp:
tag=i.split(':')[0]
#print(tag)
ind= feat.index(tag)
#print(ind)
temp2[ind]= i.split(':')[1]
set_c.append(temp2)
df=pd.DataFrame(set_c,columns=feat)
df.to_csv('product_descriptions.csv',index=False)
return df
这个片段生成了一个数据框,其中包含所有产品及其列出的规格,以提供对可用规格的洞察。


生成的规格表如下所示。对于产品页面中没有给出的值,我填了-1。
这些表格将有助于客户比较查找规格。
加权分数
def tune_search(choice):with open('products_mod_3.json', 'r') as openfile:
data = json.load(openfile)
for k in data.keys():
price_rel=data[k]['Price_relevence_Score']
review_score=data[k]['Review_Score']
pop_score=data[k]['Popularity_Score']
pop_score_k=pop_score/4
rate_score=data[k]['Rating_Score']
rate_score_k=rate_score/5
if choice==1:
total_score=5*pop_score_k+rate_score_k+review_score+price_rel
if choice==2:
total_score=pop_score_k+5*rate_score_k+review_score+price_rel
if choice==3:
total_score=pop_score_k+rate_score_k+review_score+5*price_rel
if choice==4:
total_score=pop_score_k+rate_score_k+5*review_score+price_rel
else:
total_score=pop_score_k+rate_score_k+review_score+price_rel
data[k]['Total_score']=total_score
#print(data[k]['Total_score'])
links=sort_d(data)
return links
这段代码片段根据用户的选择提供了一个分数。我使用了一个非常基本的条件驱动方法。我将收视率除以 5,人口除以 4,以保持数值在 0 和 1 之间。这里权重值固定为 5。只是随便选的。
这都是关于我们的代码。
应用
给定的视频演示了该应用
无论选择是什么,我也给出了其他选择的链接,只是为了给用户额外的安慰和尝试其他选择的机会。
在我的例子中,你会看到 chrome 窗口,虽然它是自动的,会自己关闭,但会不断弹出,你可以使用 headless chrome 阻止它启动,并使用 chromeoptions()为你的 chrome 驱动程序利用它。
展望未来
可以通过两种方式修改应用程序或使其更加健壮,但这两种方式都需要数据,目前似乎还没有数据(据我所知)。
- 如果当前的亚马逊情感数据集可用,我们可以制作自己的情感分类器,在其中我们可以将其他类别与积极和消极的情感放在一起,这将有助于我们基于评论的评分更加稳健。
- 如果数据或规格是绝对存在的,我们可以为规格创建我们自己的特性嵌入。例如,如果我们有足够的笔记本电脑数据实例,我们可以为笔记本电脑创建一个嵌入或编码空间。我们可以将每台笔记本电脑表示为其规格的嵌入向量。我们可以根据用户需求创建新的规格向量。在那里,我们可以应用 K-最*邻算法来获得与需求向量最*的 K 个嵌入向量,并根据它们的欧几里德距离对它们进行排序。因此,我们可以获得规格接*用户要求的 k 笔记本电脑。这将让我们添加一个基于相关规范的分数,使我们的系统更加健壮。
结论
因此,我们可以通过几个步骤用 python 构建一个实时产品推荐引擎。
这里是 Github 的链接。
希望这有所帮助。
现实世界的时间序列预测:每日*均汇率
如何应用 ARIMA 模型预测时间序列数据

时间序列数据的*稳性意味着序列的均值、方差和自相关等统计属性不会随时间而改变。序列*稳性的概念对于应用统计预测模型非常重要,因为:
- 像 ARIMA 这样的大多数统计方法都是基于过程是*稳或*似*稳的假设[1]。
- *稳的时间序列可以提供有意义的样本统计,如均值、方差、与其他变量的相关性[1]。
过程的*稳性可以通过目视检查时间序列图或序列的变差图来验证。可以执行像增强的 Dickey-Fuller** 测试这样的统计测试来检查过程的*稳性。本文通过直观检查时间序列图和变异函数来验证*稳性。**
时间序列图— 如果给定的时间序列图显示一段时间内的恒定均值和方差,则该时间序列图可视为*稳过程。
变异函数— 是一种检查时间序列数据*稳性的图形工具。如果给定过程(时间序列)的变差函数在一定数量的滞后后显示稳定,则该过程被定义为*稳过程。
如果原始时间序列没有表现出*稳性,那么可以通过实施变换(例如对数变换)和差分来稳定该序列。
我们将把 ARIMA 模型应用于真实世界的数据集“美元和欧元之间的日*均汇率”。Sorren Bissgard 和 Murat Kulachi 在《时间序列分析和实例预测》一书中给出了数据集。下面给出了数据集的一个片段:

美元和欧元之间的日*均汇率
*稳性:原始时间序列及其变差函数
图 1 和图 2 分别展示了原始时间序列及其变异函数。图 1 显示该序列不是稳定的,因为它不遵循恒定的均值和方差。图 2 中的变差函数没有显示出稳定性,因为在大约 80°滞后之后,变差函数显示出下降趋势,从长远来看,变差函数可能无法保持稳定的模式,这表明该过程不是稳定的。

图 1:原始时间序列

图 2:原始系列的变差函数
*稳性:区别原始序列
图 3 和图 4 分别显示了原始序列的一元差分过程的时间序列及其变异函数。图 3 示出了一个差分序列遵循恒定的均值和方差,表示*稳序列。此外,图 4 中的一阶差分变异函数显示了稳定系列的特征,因为它证明了长期稳定。因此,一个差分序列适合用于进一步分析。

图 3:原始时间序列的一个不同过程

图 4:一个差分系列的变差函数
调查候选模型并选择最佳模型
可以阅读这篇文章 — 时间序列分析:利用 ACF 和 PACF 图识别 AR 和 MA—了解如何利用 ACF 和 PACF 图选择 ARMA 模型的阶数。
图 5 和图 6 显示了一个差分序列的 ACF 和 PACF。ACF 在一个滞后之后切断,并且 PACF 也从系列的开始切断。因此,ARIMA(p,d,q)可以是其中 p = 0,d = 1,q = 1 的候选模型。然而,我们也试验了 ARIMA (1,1,1)、ARIMA (0,1,2)和 ARIMA (1,1,2)来研究模型的性能。在应用不同的模型后,我们将把 AIC 作为一个性能指标来选择最佳模型。

图 5:一个差分系列的 ACF

图 6:一个差分序列的 PACF
图 6、7、8 和 9 显示了我们在一个差分序列上实现的 4 个不同的前述模型的结果。所有候选模型的方差和标准误差大致相似。AIC 也显示了所有四种模型的相似值。ARIMA (1,1,1)模型的 AIC 最低,为-1398(图 8),尽管所有的估计参数在统计上并不显著。ARIMA (0,1,1)和 ARIMA (0,1,2)可被视为最佳模式,因为它们的 AIC 是第二低的,但 ARIMA (0,1,2)的估计参数不显著。因此,我们最终选择 ARIMA (0,1,1)作为最佳模型(图 6)。

图 6: ARIMA (0,1,1)模型

图 7: ARIMA (1,1,2)模型

图 8: ARIMA (1,1,1)模型

图 9: ARIMA (0,1,2)模型
最终模型的分析
以下是最终模型 ARIMA (0,1,1)的图。白噪声概率显示了白噪声的显著性,残差图显示了正态性。IACF 没有显示出任何不稳定性,白噪声概率是显著的。Q-Q 图遵循线性模式,残差分布也遵循正态曲线,这表明该模型满足正态假设。


时间数列预测法
表 1 显示了该比率的预测值。标准误差显示预测值的稳定性,因为所有标准误差都不显著。图 10 显示了 7 天预测值的曲线,表明曲线稳定。表二。将原始比率值与预测值进行比较。*方误差(SE)显示原始值和预测值之间的*方误差。每个预测比率的 SE 显示预测比率非常接*原始比率,这表明 ARIMA 模型的预测质量良好。

表 1:*均汇率预测

图 10:未来 7 天的汇率预测

表 2:原始汇率和预测汇率的比较
参考
[1]https://people.duke.edu/~rnau/411diff.htm
(真正)温和地介绍命名实体识别以及如何使用它进行数据分析。
自然语言处理变得简单
用 Spacy 发现《权力的游戏》书中最受欢迎的名字!

话来了!托马斯·博诺梅蒂在 Unsplash 上拍摄的照片
NLP 是热门的东西,任何有抱负的数据科学家都应该学习它,对吗?当然,但是 NLP 除了在机器学习项目中的应用之外,还可以发挥更大的作用,因为它可以为数据分析带来强大的工具。
在本文中,我将使用 spacy ,它是最流行的 NLP 任务库之一。它有很好的文档,提供了 10 种语言的模型,还有一个多语言库。我们的数据集将是流行的《权力的游戏》系列的第一本书,可以在这里下载。所有的代码和图表都来自我专门为你制作的笔记本,所以请自便。
为什么使用 NLP 进行分析?
作为数据分析师,我注意到当我们开始学习时,我们学习的很多内容都集中在 ML 建模、预测和人工智能上,有很多很酷的东西要学。然而,当遇到第一份工作机会时,通常会与数据分析、数据清理和数据可视化相关,所以我们应该投入更多的注意力来提高我们在这些领域的技能,NLP 可以在这个过程中提供很多帮助。
文本数据是杂乱的,很难组织。帮助我们理解它的方法之一是将单词转换成记号,记号是单词的数字表示。Spacy 出色地做到了这一点,它还使用一个通常非常有效的复杂统计模型来预测一个词在给定上下文中的功能。
什么是命名实体识别(NER)?
根据文档:“命名实体是一个“现实世界的物体”,它被赋予了一个名字——例如,一个人、一个国家、一个产品或一本书的书名”。下面你可以找到一个例子:

完整的列表可以在这里找到。
如何使用 NER 进行数据分析?
在今天的例子中,我们使用的是《权力的游戏》第一本书,名为《国王的冲突》。假设你正在做你的分析,在这么多的角色中,你问自己,哪一个名字在那本书里出现得最多?好了,不要再害怕了,因为 NER 在这里帮助你!

想把它们都记住是不可能的!来源
首先,让我们看看数据是什么样子的:

来源:作者
好的,这是一个文本文件,每行都是一行。我们需要遍历这些行,并要求 spacy 选择一个名称,并将其保存到一个列表中。很简单,对吧?让我们把它翻译成代码!

首先,创建 NLP 对象。来源:作者
我们首先需要创建一个 NLP 对象。它加载模型,在这种情况下是英文模型,并使用这个对象,我们将转换和预测文本中的单词,如下例所示:

2:迭代每一行。
上面的代码的作用是:
- 创建一个空列表来存储我们的名字;
- 要求 nlp 对象处理每一行;
- 然后,当它预测单词是一个人时,它得到每个标记的文本;
- 最后,它应该将该名称存储在空列表中。
现在,我们可以看到为我们的书选择十大名字的结果:

来源:作者
哇!看那个!请记住,我们没有给算法任何信息,它自己预测了名字,至少对于前 10 名,它们都是正确的。另外,我们只用了很少几行代码就完成了所有这些工作。现在,为了让这些信息看起来更好,为什么不创建一个条形图呢?

结论
今天就到这里。在本文中,我向您展示了自然语言处理不仅仅是关于机器学习,还可以用于分析。我们探索了什么是 NER 以及如何使用它,并给出了一个实际的例子,欢迎您不仅仅是自己去尝试。
我希望你喜欢阅读,请在评论中告诉我你的想法,并在下一篇文章中看到你!
Python 中 NLP 的(非常)温和的介绍
自然语言处理变得简单
握住我的手,让我们一起开始吧。

帕特里克·托马索在 Unsplash 上的照片
我知道,这不容易。NLP 是每个人都在谈论的事情,似乎每个人都在做,除了在人群中迷失和悲伤的你自己。不用担心,自然语言处理(NLP)是一个很难学的东西,即使很少有人会承认这一点。
在本教程中,我将一步一步地讲述基础知识,没有冗长的解释(因为这里的目标只是介绍主题),也提供了后面的所有代码(笔记本是在这里等着你),所以你可以跟随我通过整个过程。
数据来自巴西一家网上商店的顾客评论,原始数据集可以在 OLIST 存储库中找到。我为 NLP 分析创建的转换后的文件可以在这里找到。让我们检查第一行,看看是关于什么的:

来源:作者。
第一列是来自客户留下的评论的文本,第二列告诉是否是正面评论,如果是正面评论,则值为 1 ,如果不是正面评论,则值为 0 。您可以查看本笔记本了解更多关于我如何合并不同数据集以及如何创建目标要素的详细信息。
在这第一个教程中,我将介绍:
- NLP 的使用及其在机器学习中的应用;
- 基本预处理技术;
- 词汇化;
- 标记化。
自然语言处理的使用
我们先来思考一下 NLP 的可能性。理解人们对某事的看法是一个强有力的工具,但是语言是一个很难学的东西。想想我们自己学习语言的过程,用词汇中所有不同的单词和它们之间的组合,以一种有意义的方式完全吸收它需要多长时间?然后,我们需要发展发现隐藏在词语背后的微妙情绪的技能,以便将一些事情分为真诚、傲慢、真实、虚假、讽刺等。如果这对我们来说很难,因为计算机要复杂得多,因为它根本不理解任何单词!
是的,它是正确的,计算机只理解数字,而不是单词。那么,如何让他们理解我们所说或所写的东西呢?简单来说,我们需要将单词转换成数字。当我们这样做时,计算机可以处理信息,并根据计算产生强大的洞察力,因此需要在运行任何机器学习文本数据中的算法之前进行这种转换。
自然语言处理和机器学习
在我们让计算机理解单词之后,我们可以使用机器学习来预测这些单词,如构建翻译应用程序,在打字时建议下一个单词,以及更复杂的应用程序,如理解文本的情感。
预处理技术
使文本计算机友好的第一步是清理它。我们这样做是为了让学习过程更顺利、更快。由于本文无意全面研究预处理技术,所以我将向您展示最基本的技术:
- 小写单词:否则电脑会把“猫”和“猫”理解成不同的东西。
- 移除:
1- 标点:因为标点本身没有任何意义。
2- 停用词:是经常出现的常用词,如“该”、“安”、“他”、“自己”等。删除这些单词减少了算法需要处理的数据量,使其速度更快。
词汇化
词汇化是将一个词转换成其基本形式的过程。我们可以认为基本形式应该出现在字典中,例如,英语中的单词“walked”、“walking”和“walks”都来自同一个词根“walk”,这就是该单词的引理和。
有趣的是,词汇化也用于根据词义而不仅仅是拼写来转换单词。一个例子是“更好”,它有“好”作为它的引理。这是一个强大的工具,因为它有助于减少以后需要处理的单词数量。
标记化
还记得我说过计算机只能理解数字吗?嗯,标记化就是将一个单词转换成一个数字表示,或者一个标记的过程。标记非常有用,因为它们使得在文本数据中应用机器学习模型成为可能,并且很少有方法可以做到这一点。
在 python 中,有一个名为 spacy,的库,它附带了一些非常方便的函数,可以帮助我们用几行代码完成所有这些预处理。我已经创建了下面的例子,所以你可以检查它的行动:

来源:作者
我们可以看到,记号将每个单词和标点符号分隔成单独的记号,并且引理将单词简化为它们的基本形式。如果你是一个说葡萄牙语的人,你会注意到它并没有那么好,就像将“antes”(之前)转换为“antar”,这没有任何意义。它也没有删除一些常见的单词,如“e”和“ok”。葡萄牙语库似乎是一个正在进行的项目,所以如果你打算使用除英语之外的任何包,请注意,但这是一个很好的第一种方法。请随意在其他文本中尝试该代码,看看它是如何工作的。
今天就到这里,我希望它能帮助你理解如何从 NLP 开始。非常欢迎你在下面的评论中留下你的想法。在你看来,NLP 的真正基础是什么?
(非常)温和地介绍了 Python 中的 Web 抓取
废弃你的第一个网页,开始创建你自己的数据集!

就像在一个建筑工地,网页抓取是关于使用正确的工具!来源
当我写了一篇关于数据科学家有能力废弃自己的数据的重要性的文章时,我收到了几个关于如何开始这样做的问题,尽管有一些令人惊叹的教程,但它们可能会变得非常复杂,使完全初学者很难轻松跟上。
我在这里的目的是向您展示有关工具和代码的基础知识,您可以使用这些工具和代码来收集数据并构建您的第一个数据集。在此之后,我希望您能够放心地继续学习和提高您对数据科学这一迷人领域的知识。
写满所有代码的笔记本就在这里。请便:)
你喜欢你的汤吗?
在 python 中,做网页抓取最流行的库是美汤。它帮助我们从 HTML 文件中获取信息,并且,由于所有的网页都是用 HTML 编写的,我们使用大量我们称之为 soup 命令来提取我们需要的数据。
关于 HTML,至少有一些关于它的基本知识是有用的,包括它的书写方式和语法,但我应该警告你,这不是你在几天内就能学会的,所以我建议你在练习抓取技巧的同时学习它,至于我,就我个人而言,当我看到它们被用于实际例子时,我会学得更好。
从哪里开始刮?
在进入亚马逊、IMDB(电影评论)等真实世界的页面之前,我建议你看一下抓取中心,在那里你可以找到专门为想要练习抓取的人创建的页面。我之所以建议这样做,是因为像 e-bay 和其他巨头不希望人们抓取他们的页面,因为这会影响 page 的性能,所以他们创建了一些机制,使抓取变得更加困难。在本教程中,我们将使用一个虚构的书店,所以让我们来看看它是什么样子的:

http://books.toscrape.com/登陆页面。
我们的使命
今天的重点是基础知识,所以我们的目标是用每本书的标题和价格创建一个数据框架,这正是我们接下来要一步一步做的事情。
1-制作汤
第一步是找出我们想要的信息(书名和价格)在网站上的存储位置。要做到这一点,如果使用 Chrome,点击鼠标右键,选择“检查”。将显示所有 HTML 信息。然后,点击检查框左上角的箭头,用吸尘器将它吸到第一本书上,这样它将显示存储该项目信息的类的名称:

图书信息发现课。来源:作者。
所有图书信息都存储在“product _ pod”类下,这创建了我们所说的容器,一个存储一组数据的对象。然后,我们将创建一个 soup 对象,只需使用命令 find_all() 获取该页面上每本书的信息:
20
结果显示,我们检索了大约 20 本书的信息。这是因为在 1000 本书的宇宙中,我们在这一页上只展示了 20 本书。我们以后会想办法获取所有书籍的信息。现在,我们将专注于探索第一本书,找出我们需要的信息,书名和价格,存储在哪里。
2-探索第一本书
如上所述,有 20 个容器可用,都具有相同的结构。让我们探索第一个:
结果很长,但是请花几分钟逐行阅读。你能弄清楚标题和价格在哪里吗?
<article class="product_pod"> <div class="image_container">
<a href="catalogue/a-light-in-the-attic_1000/index.html"><img alt="A Light in the Attic" class="thumbnail" src="media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg"/></a>
</div> <p class="star-rating Three">
<i class="icon-star"></i>
<i class="icon-star"></i>
<i class="icon-star"></i>
<i class="icon-star"></i>
<i class="icon-star"></i> </p> <h3><a href="catalogue/a-light-in-the-attic_1000/index.html" title="A Light in the Attic">A Light in the ...</a></h3> <div class="product_price">
<p class="price_color">£51.77</p>
<p class="instock availability"> <i class="icon-ok"></i> In stock </p>
<form>
<button class="btn btn-primary btn-block" data-loading-text="Adding..." type="submit">Add to basket</button>
</form>
</div>
</article>
如果你不熟悉 HTML,可以把它想象成一棵树。这里我们树的主干是<article class = " product _ pod ">,在这个结构中,一切都在后面。您应该已经注意到,我们在“a”元素下有一个标题,它也在“h3”元素内:

查找书名
要获得这些信息,语法类似于您想要访问数据框中的列,但是使用命令 get() 在“a”元素内导航:
'A Light in the Attic'
很简单,不是吗?价格呢?逻辑总是一样的,但现在我们有了不同的情况:

这里,我们将信息存储在元素“p”的一个类中。要访问它,我们需要使用 find() 函数,它需要对象和类名作为参数:
'51.77'
瞧啊。我们现在有了获取数据所需的代码!
3-抓取所有页面
让我们想想我们需要废弃多少页。通常,像我们这里这样的在线商店,喜欢在每个页面上展示按几个元素分组的产品。在我们的例子中,第一页显示了前 20 本书:

检查网页的组织方式总是很重要的。
有时我们拥有的总页数会显示在页面底部,所以让我们来看看:

要废弃的总页数。
我们不得不删除 50 页,因为每个页面的链接都是一样的,我们需要更改 url 的页码。有了这些知识,我们要做的是:
- 创建一个数字从 1 到 50 的列表;
- 启动两个空列表来存储关于标题和价格的信息;
- 启动一个 for 循环 ,该循环将迭代 50 页;
- 在每个页面中创建一个请求,然后为每本书创建容器;
- 使用另一个 for 循环,迭代每个容器以获得标题和价格;
- 最后,将这些信息添加到列表中。
这正是下面的代码所做的。我再一次邀请你一行一行地仔细阅读。我试图让它尽可能简单,因为理解代码是如何编写的很重要,所以你可以用你自己的方式来写:
4-创建数据框
创建列表后,我们只需使用我们的老朋友熊猫将列表“压缩”在一起,并创建我们想要的数据框:
结果,我们有了一个新鲜出炉的数据框,随时可以使用!

抓取网页后产生的数据框。
最终考虑
我希望你对网络抓取的可能性感到兴奋。这可能非常具有挑战性,因为每个网站都是不同的,我们需要执行的策略也是如此,以便检索每个网站上的数据。但是在我看来,练习使用 Beautifulsoup 是提高你的网页抓取技能的最好方法。接下来,您可以使用该项目的笔记本作为起点,并尝试向数据框中添加更多信息,例如:
- 评级和
- 现货供应。
在您对语法感到满意之后,您还可以尝试改进循环,在每一页书内导航并获得产品描述。无论如何,你在这里学到的知识可以在网上的任何地方使用。
非常感谢你花时间阅读这篇文章,下一篇再见!
一个非常简单的方法来编辑熊猫数据帧中的一行一行
大蟒
使用 pd.loc 根据条件更改数据的子集。

图片由@ siscadraws 创建(Instagram)
您是否曾经需要根据某些条件编辑表格中的每一行?
这是数据分析项目的常见任务。每次需要这样做时,我都会在 StackOverflow 中搜索解决方案。最后,我阅读了 Pandas 文档,并创建了一个模板,每当我需要逐行编辑数据时,这个模板都能工作。
下面我们来看看如何使用熊猫。 loc 方法来选择你的数据的一个子集,如果它满足一个条件就编辑它。
注意,在尝试下面的任何代码之前,不要忘记导入熊猫。
import pandas as pd
对…的快速介绍。位置[]
熊猫文档对“有这样的描述。loc[] ":
通过标签或布尔数组访问一组行和列(在
*.DataFrame*中)。
对于我们的例子,我们将使用这样的方法:
df.loc[row_indexer,column_indexer]
这里有一些样本数据,并举例说明了row_indexer和column_indexer指的是什么。(关于如何获取样本数据的解释,请查看我的另一篇文章轻松从网站获取表格。)
df = pd.read_html('[https://finance.yahoo.com/quote/TSLA/profile?p=TSLA')[0](https://finance.yahoo.com/quote/TSLA/profile?p=TSLA')[0)]

摘自雅虎财经的样本表格
要设置一个row_indexer,您需要选择一个蓝色的值。最左边一列中的这些数字是“行索引”,用于标识每一行。一个column_indexer,你需要选择一个红色的值,它们是数据框的列名。
如果我们想要选择文本“Mr. Elon R. Musk”,我们需要执行以下操作:
df.loc[0,'Name']
这给了我们想要的输出:

选择 Elon Musk 名字的 df.loc 的输出
现在我们已经有了基本的东西,我们准备开始编辑我们的表格!
基于一组条件逐行编辑数据帧
现在,假设我们想要编辑表中一些人的“Title”值。让我们把埃隆·马斯克(Elon Musk)改成“老板”,扎卡里·柯克霍恩(Zachary Kirkhorn)改成“投资人”,其他人都改成“另一个家伙”。
我们需要遍历表中的每一行,检查“Name”值是什么,然后根据我们指定的更改编辑“Title”值。
为了逐行浏览数据,我们将使用 df.index ,它从数据帧中选择“行索引”。为了了解其工作原理,我们可以在一个基本的“for”循环中打印样本表中的索引:
for index in df.index:
print(index)

for 循环的输出,用于打印数据帧的索引值
这为我们提供了与您在第一个屏幕截图中看到的最左边一列相同的值。
为了搜索和编辑数据帧中每一行的数据子集,我们使用下面的代码:
for index in df.index:
if df.loc[index,'Name']=='Mr. Elon R. Musk':
df.loc[index,'Title'] = 'The Boss Man'
elif df.loc[index,'Name']=='Mr. Zachary J. Kirkhorn':
df.loc[index,'Title'] = 'The Money Man'
else:
df.loc[index,'Title'] = 'Another Dude'
这个循环将遍历数据帧的每一行,检查“名称”是什么,然后根据它满足的条件编辑“标题”。我们的条件是,每一行的价值“名称”是否与“埃隆·r·马斯克先生”、“扎克里·j·柯克霍恩先生”和其他所有人在一起。
在本例中,因为第一行的“姓名”是“Mr. Elon R. Musk ”,所以脚本会将第一行的“头衔”值更改为“老板”。因为我们使用 df.loc[] 指定了行索引,所以它知道哪一行要执行这个更改。
生成的数据帧如下所示:

已编辑的数据帧,根据条件更改了“标题”值
我们已经根据前面指定的条件成功地更改了每一行的“Title”值!
我希望下一次您必须梳理成千上万的行并根据某些条件编辑值时,您会发现这很有用。
你应该查看一下 [df.loc[]文档](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.loc.html),了解更多关于如何使用该方法的信息。你也可以看看 Pandas 用户指南来获得更多关于索引和选择数据的提示。
编辑愉快!
ML-Ops 的配方:机器学习的扩展和操作
在解决问题方面,机器学习理论得到了更多的重视,但对操作化和商业化的思考太少。让我们探索一下如何将规模带入 ML 解决方案。

典型的机器学习生命周期&实现大规模 ML 解决方案的相应驱动因素
前提
本文旨在给出有效扩展机器学习解决方案所需的概念层次。
与质量取决于代码/*台架构的传统软件不同,数据科学/机器学习完全是关于微调指标,质量不仅取决于代码/*台架构,还取决于数据和调整的程度。(来源:数据报)
这是一个持续改进的生命周期,除了与健壮的部署管道无缝集成之外,还必须不断地使用/试验多种技术。
作为我们讨论的基础,本文以可再生能源、风力预测为例。所使用的 ML 算法超出了本文的范围,但是我们将看到如何给引擎装上轮子,扩展以满足每天处理的万亿字节信号。
设定目标
捕捉问题定义与雇佣最好的数据科学家来解决问题一样重要。考虑到可再生能源预测领域,针对一般受众的单一目标可总结如下:
获取可用的最佳功率预测
根据地区法规/市场要求,根据所需的预测类型、提交时间、提交频率和预测粒度(例如:每小时、每半小时、每“n”分钟等)设定目标。
数据准备:
根据手头的问题,数据科学家需要决定训练和部署模型所需的数据类型。数据工程团队将并行工作以创建主干网,并考虑以下因素:
- 摄取方法(是否是 ftp、IOT、API、数据湖等)
- 数据量/频率
- 清洗/清洁:(去除噪声、副本、输入等)
- 可靠性(质量、完整性、解决数据缺口、延迟等)
模型开发/培训/评估:
数据科学家在检查可用数据的性质之前,不应该开始开发模型。
算法的选择应与当前预测问题的性质以及这些算法对数据中观察到的不规则性/噪声的响应程度相关联。
*台是从一开始就要做出的另一个重要选择:
- 可伸缩性:这方面不仅包括各种预测下的模型/代码可伸缩性,还包括条件。为概念验证而编写的代码很少是可伸缩的。为可伸缩系统编写代码时,本质会发生变化,甚至数据科学家也可能需要忘记和重新学习。
- 该*台需要容纳一个高效的数据管道:一个健壮的系统,用于及时接收、存储和检索,以便每天进行多次预测。
- 再现性,跟踪&存储:全新场景培训的初始阶段包括实验和比后期更多的微调。因此,重要的是每个实验在所有水*上都是可重复的:即,模型被训练的条件。(注意:模型版本化不同于代码版本化,这里模型将被标记上所有用于重新生成模型的工件。诸如ml flow等框架都内置了这些特性。)。
- 标准化:无论使用何种方法/算法,都应采用即插即用格式,与外部子系统的接口(如果适用)应通过标准接口,最好通过 API 封装。
- 度量/ KPI s:性能度量的选择取决于领域,并且主要由业务参数驱动。例如:与准确性相关的指标,如 nmae、RMSE、MAPE 等。正被用于预测分析领域。
- 当然,对于用于开发模型的代码和输入配置文件,隐含了软件配置管理&版本控制的原则。
- 产品化就是让模型适应现实世界的条件,在这种条件下模型要经受 。通常在纸面上或概念证明通常会在交叉验证层面产生良好的结果,但需要详细考虑的是操作准确性。通常,在部署到生产中之前,应在*场条件下评估模型。尽管模型性能是一个主观的问题,但是新的模型应该至少比部署的模型大几个点,如果不是这样,回归系统应该发出警报,并且记录异常/异常值。
部署:
- 成本&规模:风力发电场通常根据其能源容量和资产数量进行分级。每个客户都需要一个基于单个服务器场的预测,或者需要一个包含多个服务器场的合并提交格式的预测,因此,每次部署的计算成本可能会有很大差异。与此同时,*台和架构的选择应该确保成本不会随着部署的增加而呈指数增长,并且最终会趋于*稳。
- 可扩展的机器学习*台在不断发展,因此频繁的升级和图书馆的 eol ( 寿命终止)公告是常见的。因此,任何类型的软件升级,无论是更新的型号,还是库升级,都应该是 100%自动化的。同样,解决方案架构扮演着重要的角色。理想情况下,基于容器的实现是首选,但这同样取决于要解决的问题以及随之而来的约束。
- 部署模型的可审核性与可再现性同样重要;如果某项工作失败或未能以最佳方式执行,了解其原因非常重要,这将直接影响客户的响应时间。
监控/诊断/反馈回路:
- 机器学习是一个持续改进的过程,因此部署模型意味着开发监控工具来提供可操作的见解。这些包括指标、异常值、异常值等。大多数公司低估了为此目的构建内部工具的优势,因为这些工具捕捉了这些模型所暴露的实际工作环境。
- 由于季节变化、有限数据集上的训练、数据管道问题等,模型会随时间漂移。因此,安装一个漂移监控系统有利于操作。主动预警机制确保一个运行良好的系统能够管理大量模型。
- 在设定部署目标的阶段,客户可能没有用于比较性能的基准数据。但是,一旦每日预测到位,更多的洞察力就会产生,从而导致一组更精确的目标。这最后一英里的连接是一个重要的环节,它导致从现场到产品管理/数据科学家的反馈循环。这通常会导致目标、再培训和度量的细化。
ML-Ops 与 Dev-Ops
Dev-Ops 致力于建立生产大规模软件解决方案的自动化管道。因为预期的 o/p 是已知的,所以基于规则的系统非常适合这个范例。
但是,由于预测解决方案的主观性质(即,这里没有放之四海而皆准的标准,即期望的准确性水*)。),因此为管道移植严格的基于规则的通过/失败方法可能不适用于 ML-Ops 中的所有级别。
典型的部署管道可能包括以下内容:

Airflow、Luigi 等是工作流创作工具的例子。它们标识了作业之间的依赖关系,并在出现故障时挂钩要采取的行动。调度通常包括设置 cron 作业——有许多类型的语法,有时当有复杂的调度时,创造性地组合它们。
从培训、再培训到部署,能源预测是否有 100%CI/CD管道?假设一个非常干净的数据管道,理论上是可以的。但大多数情况下,在培训过程中会涉及手动流程,例如:对于新客户,历史数据会更少,并且大多数特征是未知的。因此,训练者有意识地选择初始数据集。同样,在评分过程中,由于极端天气条件,某一天或一天中的某个时间的准确度误差飙升并不罕见,这并不意味着模型没有发挥作用。
只要有更多的数据可用,随着更复杂的机制的发展,就可以实现完整的 CI/CD。
结论
- 仅仅关注理论和技术,而没有对模型执行环境的理解将导致机器学习世界中的许多循环。
- 参与运营的团队需要具备基本的技术技能,并且应该能够有效地与客户端和数据科学家交流。
- 机器学习解决方案总是持续改进模式,因此有必要拥有用于部署的健壮的&高效的管道和用于监控的诊断工具。
- 目标, 基于证据的 数据驱动的决策是长期客户满意度的关键。
组织数据科学项目的秘诀

罗马卡夫在 Unsplash 上拍摄的照片
了解如何创建结构化和可重复的数据科学项目
数据科学项目本质上是实验性和探索性的。在从事这类项目时,很容易以一大堆难以破译或复制的代码告终。
数据科学项目在这方面不同于传统的软件工程项目。然而,创建一个可靠的代码结构是可能的,它将确保您的项目及其结果对于您自己和其他人来说都是可重复的和可扩展的。
在下面的文章中,我将为您提供一个包括工具、流程和技术的方法,用于建立数据科学项目,它将为您带来以下好处:
- 一致的项目结构,以便您的代码易于理解。
- 版本控制,这样您就可以在不破坏核心项目的情况下进行跟踪和更改。
- 一个隔离的虚拟环境,以便项目可以轻松地重现。
- 道德和安全项目。
项目结构
大多数 web 和软件开发编程语言都带有预定义的标准代码结构。例如,我最*一直在学习 Bootstrap ,当我下载这个项目时,我会自动得到一些类似下图所示的框架代码,这给我留下了深刻的印象。

这意味着,不管您正在构建的项目的确切性质如何,一个外人看到以这种标准方式组织的代码时,会立即知道在哪里可以找到某些文件,并可以轻松地跟踪您的代码。它对协作和再现性有很大的帮助。
有一个为数据科学项目开发的工具,可以自动创建一个名为cookiecutter-data-science的标准项目结构。该工具可以通过 pip 安装。
pip install cookiecutter
要启动一个新项目,只需键入以下内容,没有必要先创建一个新目录,因为 cookiecutter 会为您完成这项工作。
cookiecutter https://github.com/drivendata/cookiecutter-data-science
该工具将带您通过一系列问题来设置您的项目。第一个将要求输入项目名称,该名称将是创建的目录的名称。

出现提示时继续回答问题。许多问题是可选的,你可以简单地点击与你的项目无关的回车键。
现在,您将拥有一个新目录,其名称与您为项目命名的名称相同。如果您导航到它,它将包含一个类似于此图的文件结构。项目结构包含一点 python 样板文件,但不限于 Python 项目,因为如果您使用不同的编程语言,它总是可以被删除。

Github 知识库
Github 是一个版本控制工具,它存储项目的远程版本,称为存储库。任何有权限的人都可以将这个存储库克隆到他们的本地机器上。在提交到主版本之前,可以在这里进行更改和测试。
版本控制确保可以安全地对项目进行更改,而不会破坏原始代码库。这有助于项目的协作,也确保您不会破坏自己的代码!
要在您的项目中使用 Github,一旦您有了帐户,您应该在您的 Github 主页上创建存储库。通过点击新建按钮并遵循以下说明。

在 cookiecutter 设置过程中,它会要求您提供一个远程存储库。如果您给出了您创建的资源库的名称,那么您的项目将被存储在 Github 上。
关于 Github 更详细的使用说明,请看我之前的文章这里。
虚拟环境
您创建的每个项目都可能需要您正在使用的不同版本的编程语言和特定的库。虚拟环境在本地系统中创建一个隔离区域,包含项目的确切库和版本。
您或其他人可以很容易地复制这些环境,并且可以从任何位置创建和运行项目。它们是协作和可复制数据科学项目的重要组成部分。
创建虚拟环境有许多不同的工具。数据科学项目的热门选项包括 Conda environments 、 Virtualenv 和 Pipenv 。
您选择的工具通常取决于个人偏好或特定的项目需求,例如与项目所需的其他工具的兼容性。我个人使用 Pipenv,因为我主要使用 Python。我将快速浏览一下如何使用 Pipenv 为项目创建虚拟环境。
Pipenv 需要通过自制软件安装,如下所示。
brew install pipenv
要使用特定版本的 python 创建一个新环境,请将cd放入您的项目目录,然后运行如下所示的命令。
mkdir pip-test
cd pip-test
pipenv --python 3.7
要激活环境运行pipenv-shell,您现在将进入一个名为“pip-test”的新环境。
如果我们检查目录的内容,我们会看到 Pipenv 创建了一个名为Pipfile的新文件。这是需求文件的 Pipenv 等价物。每次在环境中安装软件包时,软件包名称和版本都会添加到该文件中。然后,可以在另一个系统或计算机上使用 pipfile 来为您的项目构建精确的环境。
伦理学
道德和数据保护的主题在数据科学领域变得越来越重要。我们必须确保正在构建的数据和模型不包含不公*的偏见,因为这些模型正越来越多地涉及人们的日常生活。保护敏感的客户数据免受潜在的黑客攻击或泄露也很重要。
您可以在项目中使用一些常用工具和程序来采取一些措施保护数据并确保项目无偏见。
首先是gitignore.档。您将在 cookiecutter 项目中看到这个文件是自动生成的。这些文件是一种确保某些文件或目录被忽略且不提交到您的存储库中的方法。例如,您通常不希望您的数据或模型文件在线可用。通过将它们添加到这个文件中,Github 将会忽略它们。如果我将data/*添加到这个文件中,那么整个数据目录将不会被添加到远程存储库中。
第二个工具叫做 deon 。这使您可以轻松地向数据科学项目添加道德检查表。要使用该工具,只需运行pip install deon或者如果您在 Pipenv 环境中运行pipenv install deon。
要添加清单,只需运行deon -o ETHICS.md。这将把清单作为一个名为 ETHICS.md 的文件添加到您的项目目录中。该文件如下所示,包含一个建议问题列表,用于在整个项目中审查,以确定它是否符合伦理考虑。

我在本文中给出的方法适用于大多数数据科学项目。当然,在某些特殊情况下,您需要进行更改或添加额外的步骤。然而,我发现,通过遵循这些步骤,我可以更容易地创建有组织的项目,这些项目可以被他人分享、理解和处理。
感谢阅读!
我每月都会发一份简讯,如果你想加入,请点击此链接注册。期待成为您学习旅程的一部分!
告诉我你想要什么:基于客户偏好和产品评论的推荐系统

德克萨斯州奥斯汀市西湖高中。
如今,消费者面临着一个巨大的挑战,他们要从任何产品类别的众多选择中做出选择。我开发并测试了一个系统,该系统可以将购物者对产品特性的偏好与在线评论推荐相匹配。我还执行了功能级别的情感分析,以确保推荐的产品在首选功能方面具有较高的客户满意度。这种推荐系统与最常见的方法有很大的不同,最常见的方法是将产品(如电影)作为输入,并找到类似的产品作为推荐。它也不使用购物者的历史,因此避免了冷启动问题,也非常适合一次性购买。
作为一名越野赛跑运动员,我想为跑鞋建立一个推荐系统。我的推荐系统(【runningshoe4you.com】)对来自 18 家制造商的 505 款跑鞋进行了 10 万次评论,与综合评分最高的跑鞋相比,它找到了更符合消费者理想偏好的跑鞋,而无需阅读大量的产品评论。我为这个推荐系统编写的 Python 代码可以从我的一个 GitHub 仓库获得:https://github.com/JoshB02/recommender-system-tools
对于消费者来说,如果不花费大量的时间和精力来评估众多的备选方案,就很难找到符合其偏好的合适产品。奇怪的是,Amazon.com 网站给用户增加了阅读评论的负担,一次一个产品。例如,通过关键字“跑鞋”进行搜索会产生许多页面的结果,在第一页上就显示了 68 种产品。用户必须点击一个产品,并阅读该产品的评论;对于另一个产品的评论,用户必须点击第二个产品,并重复这个乏味的过程。我确信亚马逊已经发现这种展示产品信息的方式可以使其利润最大化,但是我觉得这占用了我们过多的时间。
为了让它变得简单一点,亚马逊确实提供了一组按钮,代表它从词频分析中找到的评论关键词或短语。图 1 显示了某双跑鞋的关键字或主题按钮。如果我们点击一个按钮,比如说,完美匹配,亚马逊会显示所有包含该关键词的评论。虽然这种方法很有用,因为它允许购物者根据她在产品中寻找的东西来关注评论,但它仍然需要她阅读许多评论,每个产品一次一个功能。这个过程可能会令人沮丧。

图 1:亚马逊网站上一双鞋评论的关键词按钮(来源:Amazon.com)
提取用户评论中提到的产品特征
我用了名词(如舒适)、动词(如舒适)、形容词(如舒适)和副词(如舒适)从评论中提取产品特征。

我将产品评论集转换成二进制值(0 或 1)的矩阵,这是基于它们是否包含对这些特性或相关词的提及,如表 1 所示。

表 1:使用特征的产品评论的向量表示
从上表中可以看出,每个评论都可以表示为一个特征向量,其中 1 (0)表示该特征或相关词在该评论中(未)被提及。原始评论数据对于进行情感分析仍然是有价值的,因为所有与情感相关的信息都将在上述步骤中丢失。作为二进制表示的替代,我们也可以使用词频-逆文档频率( tf - idf )来表示评论向量。
获得关于期望特征的用户输入
有两种可能的方法可以在不侵犯用户隐私的情况下获得用户的输入。首先,我可以让用户从列表中选择她喜欢的产品特性。这将提供期望的特征向量。

然而,如果我只考虑用户已经明确指定的特性,那么这些推荐会更有意义。


图 2:购物者选择的具有三个特征的特征空间
有时,购物者可能不确定她喜欢的功能,但可以指出她可能听说过或感兴趣的产品。在这种情况下,我们可以使用以下公式来确定客户评论中哪些功能与该产品密切相关:

如果关联值大于 1,则关系显著,我们可以推断,当人们写产品 A 时,他们将其与特征 f 相关联(反之亦然)。1 以上的关联值越大,关系越强。因此,当购物者表示对产品感兴趣时,将具有高关联值的特征作为她可能感兴趣的特征集是合理的。
获得偏好和评论之间的匹配分数
有多种方法可以获得评论和所需特征向量之间的匹配分数。余弦相似性是最常见的方法,在这种情况下,余弦相似性是同一空间中期望的特征向量和评论向量之间的角度的余弦。设 D 是由用户选择的或者从与所选产品的高关联值推断的特征集合。


一个产品和一组期望的特征的*均余弦值向我们展示了购物者在产品中寻找的东西和评论中提到的特征之间的匹配。如果分数接* 0,则匹配度低,而分数接* 1 表示强匹配。如果总共有 N 个评论,那么对于给定的一组特征,将获得 N 个余弦分数,并计算每个产品的*均值。
余弦相似度中要求精确单词匹配的替代方法是单词嵌入。虽然原则上更好,但是对于单词嵌入,我面临着推荐系统不能很好地区分不同特征的问题。例如,虽然缓冲和舒适是跑鞋的两个不同特征,但标准的单词嵌入是基于新闻和其他主题,其中缓冲和舒适很可能彼此非常接*地出现。因此,在单词嵌入方法中,缓冲和舒适被视为相似的单词,这导致了较差的推荐。我在创业的时候写过一篇关于这个话题的文章:https://medium . com/swlh/word-embeddings-vs-bag-of-words-The-curious-case-of-recommenders-systems-6ac 1604d 4424
特征级情感分析
虽然相似性分析显示了关注推荐系统的用户认为重要的相同特征的评论,但是它不能区分正面和负面的情感。考虑两个简短的评论:
点评(一):“这鞋一点都不舒服,但是很耐穿”。
评论(二):“如此令人惊讶的舒适的鞋子,加上我也喜欢的支持。”
如果购物者将舒适度指定为重要特征,则两条评论的相似性得分会更高;然而,与第一次评论相关的产品不应该被推荐,假设类似的观点在产品的其他评论中得到回应。因此,除了计算相似性得分之外,还需要进行情感分析。
虽然一个产品的总体情感分数可能是有用的,但我们需要知道用户对产品的某个特定特性的感受。我们可以使用的一个简单假设是,客户将在特征词周围的词窗口中表达她对特征的情感。例如,在简短评论“这些鞋子具有卓越的耐用性”中,卓越的一词抓住了关于特征耐用性的情感。因此,从一篇评论中,如果我们提取一个窗口,比如说,在特征词的右边和左边都有三个词(当可用时),我们可以将这个词窗口通过情感分析器。例如,窗口大小为 3,排除像 a 、 the 或 be 这样的停用词,我们将从上面两个简短评论中获得以下内容:
来自评论(一):鞋子一点也不舒服
从审查(二):如此令人惊讶的舒适的鞋子,加上也
这些评论的提取部分现在可以通过情感分析器发送,产生的情感分数可以归因于特征舒适度。
虽然所有的情感分析量表都包含负值,但用户更熟悉亚马逊的 1-5 评级量表。我使用 Python 中的 VADER 情感分析器,它有[-1,+1]的标度。为了给出亚马逊量表上的情感评分,我运行了一个线性回归:亚马逊评分=C+*a** VADER+误差,其中 C 是一个常数,而 a 是 VADER 评分的系数。根据我收集的数据,我得到 C = 3.66 和 a = 1.36,调整后的 R *方为 42.2%。均方根误差(RMSE)为 0.228,相当不错。因此,我的推荐系统不会显示 VADER 的情感评分,而是显示亚马逊对每个产品特性的预测评分,评分范围为[1,5]。
提出建议
对于每件产品,我计算了购物者选择的特征的相似性得分和情感得分的加权和。由于 VADER 的量表是[-1,+1],这种相似性和情感分数的增加不会对量表造成问题。推荐的产品是加权分数最高的产品。
数据采集和预处理
我用 Selenium 用 Python 写了一个刮刀,从亚马逊产品评论页面和其他网站上刮了超过 100k 条跑鞋评论。大量文本的一个常见问题是语料库包含大量单词。为了减少这些词汇,我有选择地删除了停用词,同时保留了否定停用词,因为它们颠倒了情感的极性。为了进一步减少总字数,我使用了词汇化。此外,我转换了所有的词类(例如,舒服,舒服,等等。)和同义词转化为相应的名词(comfort)。然而,出于情感分析的目的,我保留了原始的评论集。
对于购物者指定的每个组合,我的推荐系统计算(I)特征向量与每个评论向量 rid 的余弦相似性,(ii)每只鞋的*均余弦相似性,计算为一只鞋的所有评论的*均值,以及(iii)对于每个选择的特征,每只鞋的*均亚马逊调整情感分数。
作为一个例子,考虑一个用户告诉系统,一双跑鞋的三个特征——舒适、支撑和耐穿——对她来说很重要。对于这三个特征,来自我的系统的三个推荐显示在表 2 中,包括匹配分数(在 0 和 1 之间),亚马逊为每个特征调整的情绪,以及*均特征情绪。为了评估我的建议,我考虑了 Amazon.com 评价最高的三款跑鞋。如表 3 所示,这些鞋子的匹配分数(*均值= 0.20)明显低于我的系统推荐的分数(*均值= 0.52)。类似地,评分最高的鞋子的每个特征的情感评分都低于我的推荐。更重要的是,在我的推荐中,讨论这三个偏好特征的评论的百分比明显更高(我们的推荐*均为 50.1%,而评分最高的鞋子为 14.5%)。不同的顾客可能出于各种原因喜欢一种产品。因此,一个总体评价很高的产品仅仅意味着很多顾客在产品中找到了喜欢的东西。然而,这并不一定意味着产品非常适合购物者的特定偏好。

表 2:特性舒适性、支撑性和耐久性的四项建议

表 3:使用亚马逊三个最高综合评分推荐的鞋子
相似的功能,更低的价格?
尽管大牌品牌的吸引力显而易见,但我的推荐系统可以找到价格低于顶级品牌、但具有相似特征的产品,并且可能对这些特征有更积极的看法。例如,如果用户指定一种产品,系统计算该产品和十二个特征中的每一个之间的关联值。然后,它选择三个关联度最高的功能,并推荐,比如说,三个价格较低的产品,但由于与更贵的产品具有相同的功能而受到评论者的称赞。下面显示了用户指定零售价格标签为$240 的水野彩香波预言 8 的情况下的结果(表 4)。

表 4:与购物者指定的产品相关的特征
我的系统发现与该产品关联最大的三个特征是坐垫、稳定性和外观。基于这些特征,系统建议的三个备选产品的价格明显较低(120 美元至 150 美元),而匹配得分则高得多,特征情感得分也是如此(表 5)。

表 5:三款价格较低、功能匹配较好的推荐产品
外卖
虽然电子商务使提供无限种类的产品成为可能,但其成功的最大障碍是购物者在搜索、发现和评估大量不熟悉的选择时所付出的大量时间和精力。我的方法是通过匹配购物者对产品的需求和之前顾客对其购买的描述来推荐产品。结果,消费者只能选择几个她真正看重的产品特征。
同样,我为这个项目写的 Python 代码可以在:https://github.com/JoshB02/recommender-system-tools获得
代理驱动的探索中的好奇心
通过揭开认知的秘密走向人工通用智能之路

最*,我在听一些与人工智能相关的讲座,并偶然看到了 GOTO Copenhagen 会议,会上 Unity Technologies 的人工智能和人工智能副总裁 Danny Lange 讨论了智能在生物进化和学习中的作用。我发现他的演讲非常有趣,我想与你分享我的一些直觉。
像 Siri 和 Alexa 这样的代理真的有智能吗?
今天存在的智能体不能真正被归类为智能体。例如,Siri 和 Alexa 等个人助理使用一些机器学习来进行语音识别和其他一些活动,但它们基本上是硬编码的软件,是由人为人设计的。
几年前,亚马逊为他们的 Alexa 项目配备了大约 10,000 名员工,所以很多后端实际上是由人来运行的。看起来好像是计算机在执行某些任务,但实际上是人在执行这些任务,这意味着它非常依赖于人来完成。甚至亚马逊和网飞的预测也只是基于聪明人挑选各种商品的建议的算法。欺诈检测、股票交易和脸书馈送都是人们创造的智能算法,但它们本身并不真正智能。
那么什么是真正的智慧呢

人类通常被认为是智能的缩影,但机器最终会超越人类。超级计算机的处理能力和内存已经超过人类,人类的内存相对于计算机真的很差。那么,如果这些极其聪明的个人助理如 Alexa 甚至人形机器人如 Sophia 都不能被归类为具有智能,那么是什么造就了智能呢?
字典对智力的定义大致为:
“获取知识和技能的能力”
人类所知的唯一真正的智慧是生物系统。动物和人类都有智力。大自然赋予了生命智慧,但是为什么人类真的有智慧,或者有智慧的目的是什么。它基本上是基于几个原则,其中之一是熵。
所以,对于一个生物有机体来说,为了维持自身,它需要消耗能量来维持其复杂的结构。在这个世界上有这种持续的能量流动,一个生物吃东西来消耗能量和维持秩序,而这些能量又会被另一个生物吃掉。
另一个原则是所有生物都需要繁殖和变得丰富,最重要的是应该了解物理学,特别是惯性和重力。例如,人类需要意识到走路时不会摔倒。我们需要智慧,这是实践这些原则的持续需要。因此,人类基本上可以被视为作用于环境并改变环境以造福自身的主体。

大自然发明了大脑,大脑从根本上来说只是基础设施,通过大脑,它通过化学机制、细胞结构、使用化学机制相互交流的多细胞生物、控制肌肉和提供嗅觉、触觉、味觉、听觉和视觉的感觉器官的能力来实现智能。
像视觉这样的东西在很久以前就出现了,从感光细胞到眼睛的进化,可能仅仅经历了 35 万年。因此,大自然不断进化这些东西,使其变得更有效率,这就是智能的来源,而当前的人工智能系统远远不具备上述智能能力。
大自然的学习方法——强化
本文提出了一个在机器学习代理中开发这些系统的框架。该框架建立在神经网络和强化学习(RL)的基础上,但不使用任何标准的 RL 方法。该系统展示了生物系统中存在的智能形式,并使用不同于标准的学习方法来密切模拟现实世界中的学习过程。拟议系统的一部分将类似于世界级 AlphaGo Zero 和 AlphaZero 中使用的系统,这种系统能够在没有人类输入的情况下在大约三天内学会围棋(而象棋只需四个小时)。
众所周知,智能存在于人类(和其他动物)身上,它基于神经网络,因此要发明人工智能,你必须求助于自然。具有空间环境、物理引擎、重力、惯性、碰撞等的 3D 引擎是一个受控的封闭生态系统,将非常类似于真实世界。所以,把游戏引擎想象成人工智能开发的生物穹顶。

像 Unity 这样的公司已经建立了一个名为 ML agents 的开源框架,在这个框架中,人们可以尝试所有这些概念,如了解物理,导航以解决问题,并取得一些成就。围绕视觉理解,在机器学习和人工智能方面有很多研究,比如第一人称射击游戏,其中有一个机器人试图真正擅长射击。在机器人学习如何行走的运动控制方面也有很多研究,在认知挑战方面,如 DeepMind 的 AlphaGo,这是很了不起的。然而,它们都是真正有限的。像 Unity 正在使用的生态系统有各种各样的工具和现有资产,比迄今为止使用的要复杂得多。
DeepMind 的联合创始人兼首席执行官戴密斯·哈萨比斯说:
“作为一名前视频游戏设计师,我非常高兴能与 Unity 合作,为开发和测试解决现实世界问题所需的智能灵活算法创造虚拟环境。”
视频游戏实际上比其他任何东西都更能促进人工智能的发展,因为它非常接*真实世界,而真实世界在自然界已经存在了大约 5 亿年,环境具备所有的基本要素,因此它不会因为对人工智能的发展有任何贡献而被抛弃。
代理驱动的探索
使用外在和内在奖励的代理驱动的探索在人工智能社区中产生了很多谈论,它离人工通用智能(AGI)更*了一步。
外在奖励是指从环境中获取、实现或收集某些东西。它出现在各种游戏中,代理人必须收集点数或金币。
它是特定于环境的,它与获得“富有”这一外在奖励的想法相比较。内在奖励指的是好奇心、耐心或不耐烦、快乐、韧性、爱、同理心等。这些是非常重要的,因为所有的人类都是基于这些内在的奖赏而生活,这些奖赏是自然专门为代理人开发的。所有的人和动物都有内在的奖励,这是它们赖以生存的基础。它可以和外在奖励相比,就像变得“快乐”和变得“富有”一样。
标准的强化学习有一定的限制,在那里,非常不可能发生的荒谬的不可能场景发生了,然后更不可能的事情也发生了,所以所有这些不可能的场景聚集在一起,形成了一个不可思议的不可能场景,称为稀疏回报空间。
假设一个代理人处于这种极不可能的场景中。一个代理进入一个房子,房子有许多房间,在一个随机的房间里,一个按钮出现。当代理按下按钮时,一个金字塔将出现在另一个房间中。还有一些静态金字塔来忽悠代理。代理人必须去推倒金字塔,拿到金字塔顶上的金盒子。现在代理必须完成所有这些场景。

使用标准的强化学习算法,随机探索,它不会学习它,因为它不会在这个随机的事件链上绊倒。
因此,我们需要其他东西来帮助代理理解这个复杂的场景,并在这个环境中实现它的目标。
关键成分——好奇心
但是大自然解决了这个问题,因为人类可以学习这种不可能的场景及其结果。这个问题的解决方案是增加探索的策略,偏向代理人而不是随机性,考虑内在的回报。这就是好奇心内在回报的来源。
对新奇事物的追求在数学上可以定义如下:
○观察值 xt 和 xt+1
○ 在动作,使得 xt 转换到 xt+1
○嵌入! (x)
○预测 p( ! (xt+1) | xt,at )
○ 奖励rt =—log p()(XT+1)| XT,at
○训练到最大 rt
○代理现在倾向于预测误差高的转换

所以通常当一个机器学习模型被建立时,主要的焦点是最小化误差,以便预测变得尽可能好。
也就是说,现在具有高预测误差的转换是受欢迎的,并且代理不确定它是否做了什么,因此它做了(或者出于好奇)。
所以,在这个只有外在奖励的场景中,代理人在做随机探索,它没有发现太多东西。当内在奖励时,好奇心只给予代理人,它还没有解决问题,但它从一个房间到另一个房间,在看到静态金字塔时撞倒它们,以知道如果它撞倒金字塔会发生什么。代理因此更具探索性,它不断地寻找它所知最少的东西。

现在代理人被给予了好奇心的内在奖励和外在奖励,也就是同时保持好奇心和变得富有。经过训练后,可以观察到代理更有方向性,它会寻找并找到按钮,它不会被所有其他金字塔愚弄,它只会打翻金色金字塔并解决问题。
很多人已经预测,强化学习有各种各样的限制,就像无法解决的稀疏问题,所以很明显,人类将进入下一个人工智能冬天。但是,像上面这样的问题是相当复杂的,它正在由某些公司实施。因此,系统需要查看整个目录,挑选客户从未见过的商品,并尝试购买,而不是随机挑选商品展示给用户。也就是说,它首先从最不可能的产品开始,然后通过好奇而不是随机地尽可能多地了解用户。

好奇心一直是许多科技发现和人类发展进步背后的主要因素,甚至可能成为真正智能机器的核心原则。
参考资料:
https://gotocph . com/2018/sessions/571/on-the-road-to-artificial-general-intelligence
哪个更重要?在你用随机森林做决定之前要小心
再看特征重要性和随机森林

无论你是谁,是一名刚刚完成他/她的第一门机器学习课程的学生,还是一名经验丰富的数据科学家,或者基本上是当今任何从事技术工作的人,你都必须听说过 Random Forest。随机森林是一种集合树模型,主要用于分类。它出现于 90 年代,至今仍是许多行业中最常用、最稳定、最精确的模型之一。
然而,今天我们不会关注随机森林本身。相反,我们应该重新审视一下特征重要性,或者可变重要性,不管你喜欢怎么称呼它。我们都知道,大多数随机森林实现(例如 s klearn,也称为 Sci-Kit Learn )都有内置的可用特性重要性,这种特性重要性最早出现在 Leo Breiman 在 2001 年的论文“随机森林”中,该论文首次恰当地介绍了随机森林。也就是说,将所有节点的加权杂质减少相加,并对所有树进行*均。这种方法被称为 MDI 或*均减少杂质。
1.基尼系数和排列重要性
MDI 中的杂质实际上是一个函数,当我们使用一个众所周知的杂质函数 Gini index 时,该度量就变成了 Gini importance,内置在 Sklearn 的 RandomForestClassifier 中。
除了 Gini 重要性或 MDI,还有另一种评估特征重要性的方法,即随机置换袋外样本中的特征值。这被称为*均降低精度,MDA,也称为排列重要性。已经有关于评估特征重要性的这两种不同方法的比较的研究:
我将使用一个非常简单的展示来比较这两种方法,使用 python 中的 sklearn 包中的随机森林分类器和 Iris 数据集,以及rfpip包(用于计算排列重要性)。

使用 sklearn 的两种方法的比较
对于这样一个简单的数据集,这两种方法给出了不同的结果,这再明显不过了。此外,如果您自己尝试多次(您可以在页面底部找到我的代码),您将会看到这些结果实际上每次都有所不同。这是因为这两种方法不仅都使用了某种类型的随机抽样,而且都来自于一个具有随机内在特性的随机森林模型。
您应该注意的另一件事是运行时。如前所述,与排列重要性相比,内置的基尼重要性具有几乎实时的运行时间。但是在我们的例子中,由于 Iris 的大小,差异并不是很大:它只有 150 个观察值,只有 4 个特征。如果我们在更大的数据集上进行比较:

使用较大数据集的运行时比较
现在你一定在想,我有这些优点和缺点,我应该用哪一个呢?嗯,也许有第三条路比这两条都好?
2.空气(实际杂质减少)的重要性
在上面的比较中,我们知道,与排列重要性相比,基尼系数的重要性以惊人的速度增长。如果我们能在基尼系数 1 上做一点小小的改变,这样我们不仅能得到更快的结果,而且偏差也更小,会怎么样呢? Stefano Nembrini 在他的 2018 论文中介绍了这样的方式:
在常规 RF 中,在每个树节点处,从𝕆≡{1,…,p}.采样 mtry 分裂候选变量相反,我们从 1 到 2 p 采样,即变量从𝕆∪ℙ采样,而ℙ≡{p+1,…,2p}.如果选择的变量索引为 j∈𝕆,那么 Xi=j 通常用于拆分。如果 j∈ℙ,变量πXi = j p,即具有重新排序的样本 ID 的原始变量,用于分割。如果是 j∈𝕆,这种分裂导致的杂质减少通常会导致 Xi 的重要性变化,而如果是 j∈ℙ.,则杂质减少请注意,不会重复执行该过程。
最后,在整个森林生长之后,变量 Xi 的估计去偏置杂质重要性计算如下:

我们将这种新的 VIM 称为实际杂质减少(空气),以避免与其他 VIM 产生误解。
可悲的是,自从 AIR 被引入才一年,并没有很多研究关注这种新方法的正确性和准确性。此外,AIR 目前仅在 R 库 Ranger 中可用,这是一个因其在 R 上快速实现随机森林而闻名的库。当分配新的 Ranger 对象时,您可以将参数“importance”指定为“infinity _ corrected”以使用 AIR 重要性。

Ranger (R)中可用的三种不同方法的条形图
这里的运行时间是在一定重要性方法下拟合随机森林模型所花费的时间。看起来三种方法的性能相似,主要是因为我们使用的数据集很小。如果我们把它换成我们之前用 5000 个观察值和 500 个特征建立的数据集,我们仍然可以看到运行时间上的巨大差距:

5000 * 500 数据集上三种不同方法的条形图,此处仅显示前 10 个特征
3.鸣人?博鲁塔!
Boruta 也是 R 上的一个库,专注于使用置换随机值来选择特征。它将所有特征分为三类:拒绝、尝试和确认。希望感谢 丹尼尔·霍莫拉 ,这个特性选择库在 python 中可用。它速度更快,并且有更多的自定义设置。

经过 8 次迭代后,Boruta 选择了所有 4 个“重要”的特性
与 R 上的原始版本相比,python 上的 Boruta 有一些令人兴奋的有趣的新参数,包括我最喜欢的一个, perc ,它为功能选择设置了阈值的百分位数,如果感觉太苛刻的话。将此值设置为较低的值允许选择更多的功能,但也会导致较高的错误率。
4.Shap,在 Shapley 值中
我知道你可能在博弈论讲座中听过这个名字很多次,在一些专注于数据科学的网站上也试图介绍这个包。是的,这个包是用博弈论的方法编写的,是的,它是一个强大而流行的工具,但是我不打算解释关于博弈论和算法本身的事实。我将用一个简单的例子来说明它能做什么。
现在,假设我们想看看数据的第一次观察如何影响预测:

虹膜的首次观察

单一观察值的解释
我们可以看到花瓣长度为 1.4 厘米和花瓣宽度为 0.2 厘米是第一次预测为 1 的主要“原因”。
如果我们稍微移动一下代码,我们还可以看到数据集中每个观察的效果:

所有观察结果的解释
Shap 的可视化不仅丰富多彩,更好看,而且是交互式的,这意味着如果你将鼠标移到它上面,你可以看到每个观察的信息。然而,正如你们中的一些人可能已经发现的那样,Shap 与多类别分类斗争。上面的 X 轴是按原始样本排序的,应与 Iris 一样,保持第 1 类 50、第 2 类 50 和第 3 类 50 的顺序。
好了,最后但同样重要的是,回到特性重要性。使用 shap 值,我们可以解释特性如何影响模型的输出。因此,我们可以预期 shap 值是特征重要性的度量:

每个特征的*均绝对形状值的条形图
几乎和我们之前谈过的方法一样的趋势,是吗?然而,无论您为同一个随机森林模型运行多少次代码,您都会得到相同的结果:Shap 值为要素提供了一致的重要性评估。
结论
我们已经讨论了使用随机森林模型评估要素重要性的所有不同方法。哪个最好?谁也说不准。我们只有数学证据证明哪一个更有偏见。老实说,你可以接受上面为 Iris 数据集介绍的任何特征重要性,因为这个问题没有正确的答案。毕竟,机器学习和数据科学都与解释有关。无论你使用什么工具,只要它有意义,并且你能让数据故事流动,使用它绝对没有错。下面是我做的比较所有这些方法的表格(运行时间使用之前生成的 5000*500 数据集计算):

- : AIR 仅在 R 上可用,AIR 运行时与 Gini 运行时在 R 上几乎相同
最后但同样重要的是, LIME 也是用于特性重要性的非常流行的包之一。希望我将来会介绍石灰,并添加所有这些工具之间的比较。
点击此处查看来自我的 Github 的所有源代码。
用 Python 和 Plotly 重新制作真实气泡图
可视化
让我们用基于数据的世界观更新我们的知识

图片来源: Gapminder
去年,我的一个最好的朋友送给我一本书,并附上一张纸条:“我希望这将是你对世界的理解的一个修正,也是对你的全球焦虑的一个补救”。这本书有一个醒目的橙色封面,标题是:“真实性:我们对世界错误的十个理由——以及为什么事情比你想象的更好”,作者是上图中气泡图背后的先生汉斯·罗斯林,以及其他合著者。
这本书改变了我看待世界的方式,并为我提供了正确解读我所收到的关于我们这个世界的信息的工具。这里,最热烈的掌声送给封面中的气泡图(出现在第一页):

从一本已经写好的书上重新做一个图表似乎有点多余,但是…
我并不希望有一天每个人都会读这本书,而是决定采取行动,在不同的媒介上传播真实,因为一位智者曾对我说:
宇宙为行动喝彩,而不是一厢情愿。
使用 Gapminder 的公开数据中的公开数据,我将展示如何制作这个气泡图。Python 和交互式可视化库 Plotly 是这次翻拍的最佳工具。
这篇文章的重点是传播事实和创造互动的视觉效果。如果你想了解数据加载、清理和格式化的适度但必要的步骤,我鼓励你在这里查看代码,在这里查看源数据。
让我们从气泡图的元素开始:
- 每个泡泡代表一个国家
- 颜色是一个区域
- 泡泡的大小显示了这个国家的人口
我们将使用以下数据框,重新创建地块:

以下是代表世界四个地区的颜色:

使用上面的颜色编码,让我们重新制作气泡图:
最新的世界图片
- y 轴上以年为单位的寿命
- x 轴是经通货膨胀调整的人均国内生产总值(PPP ),即收入
你可以将鼠标悬停在图表上,查看国名以及一个国家的财富和健康状况的确切数字!
我们的世界不再划分为“发达”与“发展中”或“富裕”与“贫穷”[根据你过时的世界观插入一对对比]。现在,世界各国根据世界银行认可的四种收入水*进行分类。
最重要的是,大多数国家处于中等水*(2 级和 3 级),*均预期寿命为 73 岁!
如果你想知道从 19 世纪到 2018 年,我们可爱的世界是如何在收入水*和预期寿命方面取得长足进步的:

加分:汉斯·罗斯林讲解各国 200 年动画泡泡图:
恭喜你!你用基于事实和数据的观点更新了你对世界的认识,谢谢你和我一起踏上了这段旅程😊。如果你想跟上我们世界的统计数据,那就继续使用 Gapminder 工具!
对于评论或建设性的反馈,您可以通过回复、 Twitter 或 Linkedin 联系我!
来源:
每个人都能理解的动画全球统计数据
www.gapminder.org](https://www.gapminder.org/tools/#\(state\)time$value=2018;;&chart-type=bubbles) [## ✨推出 Plotly 快递✨
Plotly Express 是一个新的高级 Python 可视化库:它是 Plotly.py 的包装器,公开了一个简单的…
medium.com](https://medium.com/plotly/introducing-plotly-express-808df010143d)
生成对抗网络研究综述
甘一家是如何改变机器学习的工作方式的?
深度学习的历史已经显示出有点不寻常。许多实践,比如 80 年代发明的卷积神经网络,在 20 年后才卷土重来。虽然大多数方法都卷土重来,但生成对抗网络是过去十年中深度学习领域最具创新性的技术之一。虽然具有行为良好的梯度的传播和丢弃算法的判别网络显示出非常成功,但是生成网络的情况就不一样了。在最大似然估计期间,深度生成网络在*似难以处理的概率计算方面存在问题。此外,它不能在生成上下文中利用线性单位的优势。甘斯来协助这个领域解决这两个问题,同时将一个生成性和一个歧视性的网络结合在一起。
gan 最初是由蒙特利尔大学的 Goodfellow 等人[1]提出的。 基本框架包含一个对抗对手的生成器,而鉴别器则学习分辨一个样本是属于数据分布还是来自生成网络。这个想法是让这两个网络在相互竞争的同时变得更好。
最直接的建模是将鉴别器和发生器作为多层神经网络。生成器学习从潜在空间到数据分布的映射,趋向于变得类似于地面数据分布。另一方面,鉴别器试图区分真实的数据分布和生成器生成的数据。生成网络的目标是欺骗鉴别器,使其认为产生的新数据来自真实的数据分布;这样,它增加了鉴别器的错误率。

图 1:GAN 的构建模块(https://MC . ai/deep-convolutionary-generative-adversarial-networks DCG ans/)
我们应该强调,GAN 的作用不是复制训练中使用的数据,而是产生新的数据。我们可以将其描述为两人游戏,这两个网络彼此对立,这意味着最终目标是实现一种均衡,在这种均衡中,这些经过训练的网络对彼此具有最佳反应。此时,他们无法再提高,训练停止。然而,这种*衡很难达到,甚至难以维持,这是 GANs 的第一个问题。另一个问题是,没有办法验证生成器是否已经像其他深度学习技术一样,学会了在保留的数据集中产生类似于真实生活数据分布的分布。
在原始论文中,实验表明,数据量和网络深度对更好的性能起着巨大的作用。当数据点是图像时,这意味着数据量应该与像素数成指数关系。考虑到图像有数百/数千个像素,这意味着在现有的计算能力和数据还无法实现的网络中可以实现更好的结果。
GANs 的应用非常广泛,从艺术、时尚、广告、科学到视频游戏。然而,这些网络也被用于恶意目的,例如使用 GANs 生成的合成图像创建虚假的社交媒体档案。我们可以看到,它在计算机视觉领域的应用更加广泛。

图 GANs 自原始论文以来的路线图,受[9]启发
图 1 给出了从原始文件开始的 GANs 路线图。由于篇幅所限,我将简单列出所提到的方法以及它们所解决的问题——许多论文在培训过程中进行的修改都集中在原来的工作上。
深度卷积 gan(DC gan)[2]具有更好的性能,因为当用于图像时,它不是用多层感知器来定义生成器(G)和鉴别器(D ),而是用 CNN 来定义。它没有汇集图层,因此为了增加空间维度,它使用了反卷积。对 G 和 D 中除 D 的最后一层和 G 的第一层之外的所有层的批次进行归一化,以便不会丢失关于数据分布的正确*均值的信息。
训练设置的改变是由 ImprovedGANs [3]提出的,与小批量鉴别、虚拟批量标准化和特征匹配有关。鉴于原始 GANs 的分辨率较低,LAPGAN [4]在拉普拉斯金字塔中使用 CNN 生成了分辨率更高的图像。渐进 GANs (PGGAN) [5]还提出了一种基于渐进神经网络的训练修改,通过渐进增加新层,从低到高分辨率增加鉴别器和生成器。
图像到图像的转换传统上使用包含对齐对的训练集来学习输出和输入图像之间的映射。CycleGANs [6]使用对抗性损失将图像从源域 X 映射到目标域 Y,缺少对。此外,他们将这种损失与实现循环恒定性的逆映射相结合。
原始甘的另一个问题是模式崩溃,这意味着它们倾向于产生相似的样本,即使在不同的数据集上训练。包装工用他们所谓的包装来处理这个问题。主要的变化发生在判别网络中,使得网络能够基于来自同一类的多个样本,来自真实的和生成的数据分布,来做出决策。
自我注意力生成对抗网络(SAGAN) [8]提出使用具有注意力的远程依赖性模型来生成图像。它使用 G 和 D 的频谱归一化,并证明改善训练过程。
使用 GANs 的另一种不同方式是在单一自然图像上训练生成器,使用 FC GANs 的金字塔,每个学习图像的不同尺度的分布。
GANs 中有待解决的一个问题是,它们假设生成的样本具有不同的生成参数,这意味着它们不能直接产生离散数据。另一个公开的问题是如何测量一个训练有素的生成网络的不确定性。
- I. Goodfellow、J. Pouget-Abadie、M. Mirza、B. Xu、D. Warde-Farley、S. Ozair、a .库维尔和 Y. Bengio,《神经信息处理系统进展》,第 2672-2680 页,2014 年。
- A.拉德福德,l .梅斯和 s .钦塔拉,“利用深度卷积生成对抗网络的无监督表示学习”,arXiv 预印本 arXiv:1511.06434,2015 年。
- T.Salimans,I. Goodfellow,W. Zaremba,V. Cheung,a,和 X. Chen,“训练 gans 的改进技术”,载于《神经信息处理系统进展》,第 2234-2242 页,2016 年。
- E.L. Denton,S. Chintala,R. Fergus 等人,“使用拉普拉斯金字塔对抗网络的深度生成图像模型”,载于《神经信息处理系统进展》,第 1486–1494 页,2015 年。
- T.Karras、T. Aila、S. Laine 和 J. Lehtinen,“为提高质量、稳定性和变化性而逐步种植甘蔗”,arXiv 预印本 arXiv:1710.10196,2017 年。
- J.-Y. Zhu,T. Park,P. Isola 和 A. A. Efros,“使用循环一致的对抗网络进行不成对的图像到图像翻译”,载于 IEEE 计算机视觉国际会议论文集,第 2223-2232 页,2017 年。
- Z.林,A. Khetan,G. Fanti 和 S. Oh,“Pacgan:两个样本在生成性对抗网络中的力量”,载于《神经信息处理系统进展》,第 1498-1507 页,2018 年。
- H.张,I .古德菲勒,d .,a .奥登纳,“自我注意生成性对抗网络”,arXiv 预印本 arXiv:1805.08318,2018。
- J.桂,孙志军,温永义,陶,叶,“生成性对抗网络:算法,理论与应用”arXiv 预印本 arXiv:2001.06937,2020 .
IBM 高级机器学习和信号处理述评
Coursera 上的高级机器学习和信号处理课程的全面可视化指南

沙哈达特·拉赫曼在 Unsplash 上拍摄的照片
T 他的评论不仅旨在向您提供我对这门课程的看法,还旨在让您深入了解课程所涵盖的主题,并教授一些关键概念。
高级机器学习和信号处理课程由 IBM 开发,可在 Coursera 上获得。它可以作为单独的课程,也可以作为由四部分组成的大规模开放在线课程(MOOC)的一部分,即高级数据科学专业。
可扩展数据科学基础重点介绍了云中 Apache Spark 的基础知识,并介绍了 IBM Watson Studio (IBM 的云服务)。相比之下,这门课程明显更深入,侧重于更高级的机器学习概念和信号处理。
该课程由两位 IBM 数据科学家讲授,分别是罗密欧·肯兹勒和尼古拉·曼切夫。我发现他们两个都是优秀的导师。
第一周
第一周从 ML 线性代数的概述开始。它非常简单,涵盖了 ML 中使用的不同数据对象以及对这些对象的数学运算。这里实际上有一些非常有用的知识片段,例如(1)一个向量必须只包含一种数据类型,而一个元组可以包含多种数据类型。(2)张量可以作为任意 N 维空间的通称:

标量>矢量>矩阵>张量
高维向量空间是第一课之后的自然进展。在这里,罗密欧描述了几个有用的定义和概念,并触及了高维数据背后的直觉。我们将在本课程的后面部分更深入地探讨这些概念。


投影到 2D *面上的 3D 数据(左)和投影到 3D 超级*面上的 4D 数据(右)——第三周会有更多的介绍
我们还讨论了有监督的和无监督的机器学习之间的区别。简而言之就是—

监督学习:机器学习,其中输出标签、标志或值已被分配给每个样本。这是算法的目标,并指导学习过程。例子包括-
- 分类-目标值是离散的
- 回归-目标值是连续的

无监督学习:不存在输出标签、标志或值的机器学习。这意味着算法需要在数据中找到模式,并输出一些有助于我们理解这些模式的东西。例子包括-
- 聚类-样本被分成不同的聚类/类别
- 维数减少-减少了特征的数量,同时最大限度地减少了数据丢失
最后,罗密欧谈到了 ML 管道,它是你的数据处理步骤的“流程”。例如,对于简单的多类分类,您可以使用以下管道。

这里一个特别有用的概念是数据管道的模块化。通过将该过程的每个步骤分割成独立的部分,我们能够快速切换不同的预处理方法、ML 算法或其他训练参数。
有了 Spark pipeline 对象,完整的集成流程将拥有 fit 、 evaluate 和 score 功能。这使得不同模型之间的快速原型和比较成为可能。这意味着我们可以用更少的时间建立一个更好的模型。
本周的代码非常多,我认为这是非常好的,因为它是从上一门课开始的。编程任务只是检查您的环境设置是否正确,不幸的是,我认为这错过了复习本周所涉及的关键编码部分的机会。

第二周
我们这周讨论了很多。涵盖的主题总结如下:
- 线性回归
- 批量梯度下降
- 拆分(训练集、验证集和测试集)
- 过度装配和装配不足
- 估价
- 逻辑回归
- 朴素贝叶斯
- 支持向量机
- 交叉验证
- 超参数调谐
- 集成学习(决策树、随机森林、梯度推进等)
- 正规化
这似乎很多。是很多。
这真的让我惊讶,这个星期包括了多少。仅仅是关于朴素贝叶斯的那一节,如果研究到一个合理的深度就可以轻易地耗费许多许多小时(贝叶斯统计是一个 非常 深的兔子洞)。
尽管如此,这一周教授的主题范围很广,深度也很深。一些讲座深入许多算法背后的数学和直觉。而其他人展示了如何用 Apache SparkML 应用算法,这真的很酷。
作为一个例子,我们用 Spark 构建了一个梯度提升树分类器,如下所示:
- 首先我们导入必要的模块(假设我们已经导入了我们的训练数据 df ,它被存储为一个熊猫数据帧)
from pyspark.ml.feature import StringIndexer, VectorAssembler,
Normalizer
from pyspark.ml.linalg import Vectors
from pyspark.ml.classification import GBTClassifier
- 利用我们在第一周学到的知识,我们初始化数据管道的每个组件:
# create unique index for each unique string (our target classes)
indexer = StringIndexer(inputCol='class', outputCol='label')# convert our multiple dataframe input columns to a vector
vectorAssembler = VectorAssembler(inputCols=['x', 'y', 'z'],
outputCol='features')# normalize our input values
normalizer = Normalizer(inputCol='features', outputCol='features_norm', p=1.0)
…包括分类器:
gbt = GBTClassifier(labelCol='label', featuresCol='features',
maxIter=10) # this will run for 10 iterations
- 创建每个组件后,我们将它们放入一个 Spark 管道对象中:
pipeline = Pipeline(stages=[indexer, vectorAssembler, normalizer,
gbt])
现在我们已经构建了管道,我们只需输入pipeline.fit(df_train) 来训练我们的模型。
在 IBM Watson Studio 中使用 Spark 实现这一点意味着我们可以轻松扩展。在这种情况下,它不是必需的,但是对于大型数据集和更复杂的模型,它非常有用。
这周有几个小测验,大部分都很短,但还是不错的。编程任务非常简单,在到达顶点项目之前通常都是如此。

由 Norbert Levajsics 在 Unsplash 上拍摄的照片
第三周
本周我们关注无监督机器学习。特别是聚类和主成分分析 (PCA)。
聚类部分非常直观。总体而言,聚类是一种非常简单的算法。但是我相信课程的这一部分提供的解释和例子非常令人难忘,而且非常容易理解。
PCA 部分更有挑战性。涵盖以下内容:
- 降维
- PCA(当然)
- 协方差和相关矩阵
- 特征向量和特征值
- 数据投影
PCA 用于降维,我们试图减少数据集中的维数(特征),同时保留尽可能多的信息。

3D 数据被投影到 2D *面上
通过将 3D 空间中的每个点投影到 2D *面上,我们可以轻松地将数据集从 3D 缩减到 2D(如上所示)。
在高层次上,PCA 做同样的事情,但是试图尽可能地保持数据点之间的距离。
这种尽可能多地保留信息(距离)的行为在分类中至关重要。因为正是这些距离允许我们将数据点分成不同的类别。
例如,让我们从两个不同的方向看一个 3D 图:


如果我们去除两幅图中的颜色差异,我们仍然能够很容易地区分左边图像中的两个独立的集群。然而,在正确的图像中,我们不会。
现在想象我们把这些点投射到一个*行于我们视线的表面上。聚集左边的投影点很容易,右边的就不可能了。
通过将点投影到使点之间的方差最大化的表面上,PCA 有效地优化了我们左边的场景。
总的来说,这一周非常有趣,每个概念都非常直观,这很棒!像每周一样,有测验和一个编程作业。再说一次,这个任务很简单。

张秀坤·施罗德在 Unsplash 上拍摄的照片
第四周
这就是本课程“信号处理”部分的内容。虽然在很大程度上是数据科学或机器学习,但我发现这一周绝对令人着迷。
傅里叶变换
我们从傅立叶变换(FT)开始,它允许我们将复杂信号(时域)分解为构成信号的频率(频域)。
这取决于你的背景,可能有也可能没有任何意义,所以简而言之。
噪音由振动组成。最简单的振动由重复的上下运动组成,产生正弦曲线(或正弦波)。

y 轴代表波的振幅,x 轴代表时间。一次完整的上下运动的长度称为波长。

如果我们合并两个波长,它们会产生一个新的波,这个新的波是这些波的振幅相加,这种合并被称为叠加。
现在考虑下面的波:

每个波都是一个简单的正弦曲线,但它们组合在一起就形成了一个复杂得多的模式:

傅立叶变换允许我们输入复合波信号,并输出每个组成正弦波的频率和振幅。

查看波形有两种方式。在时域(左),或者在频域(右)。
时间域是你已经看到的,它是波形。x 轴上有时间,y 轴上有振幅。
相反,频域显示了构成波的组成频率。x 轴上有频率,y 轴上有振幅。
傅立叶变换在这两幅图之间转换(逆傅立叶变换涵盖了频域到时域转换)。
周摘要
金融时报引人入胜,但不是本周的唯一焦点。它分为两个主题,这两个主题都包括以下子主题:
傅立叶变换
- 信号分解、时域和频域
- 信号产生和相移
- FT 背后的数学和直觉
- 离散快速傅立叶变换
小波
- 连续小波变换
- 缩放和*移
- 机器学习中的小波
小波和 FT 一样有趣。我发现自己很容易参与到这个星期的活动中,这是由于所涵盖的主题和教学标准的混合。我相信这在很大程度上是因为尼古拉对材料的了解。
编程作业也不是特别具有挑战性,有点填鸭式。但这是我唯一的抱怨,这一周真的很吸引人,教得很好,并在最后的讲座中很好地联系到机器学习。
结论
我发现这门课非常有益。由于该课程仅在 IBM Watson Studio 上进行,因此还有一层额外的用途。这是对 IBM 云服务的完美介绍。当然,这通过增加曝光率为 IBM 带来了好处,但对于任何数据专业人员来说,这也是一项无价的额外技能。
课程的技术性更强的方面非常好。材料的范围很广,大部分主题都有合理的深度。
与任何 MOOC 一样,我认为重要的是要注意到,要真正加深你的理解,最好是密切关注所教的内容。然后,去找更多的材料,进一步研究。
最后,试着学以致用,写/说你学到的东西。如果你能应用并解释你所学到的东西,你会理解得更多,从而从课程中获得更多。
编程作业并不特别具有挑战性。在斯坦福的机器学习课程中,我经常会花几个小时完成每项作业。相比之下,通过这门课程,我通常可以在 10-20 分钟内完成编程作业。
然而 ,这是由顶点工程保存的,是全专精的一部分。这引出了我的最后一点:
整体明显大于部分之和。
我认为,要从本课程中获得最大的利益,最好是完成完全专业化。一旦完成一到三门课程,最后的顶点项目是真正巩固所学的一切。
我希望这篇评论对你有所帮助,非常感谢你读到这里!如果你对课程有任何问题,请在下面告诉我!
谢谢,
如果您有兴趣了解 IBM 的可伸缩数据科学基础,我在这里写了另一篇评论!
我的想法是,在 IBM 的高级数据中,对可伸缩数据科学基础中的关键概念进行分解…
towardsdatascience.com](/a-summary-of-the-advanced-data-science-with-ibm-specialization-1-4-5caf48c011df)
综合表格数据工具和模型综述
正在彻底改变我们共享数据方式的匿名化方法

米卡·鲍梅斯特的图片 @mbaumi 。https://unsplash.com/photos/Wpnoqo2plFA
数据隐私的重要性
我们生活在一个数据驱动的时代,大数据、数据挖掘和人工智能(以及其他时髦词汇)正在彻底改变我们从数据中获取价值的方式。挑战在于,私营公司和公共实体都没有办法在内部或外部轻松共享这些数据。主要障碍是:合规法律、对数据滥用的担忧、患者/客户隐私以及无法安全传输数据。如果没有这些限制,数据科学家、开发运营团队、研究小组和其他数据专业人员可以提供更高效的问题解决方案。
传统的数据匿名方法:数据屏蔽
在机器学习流行之前,匿名化数据的原始方法通常以牺牲数据效用为代价来产生匿名化的数据。统计属性经常被部分或完全破坏,匿名方法通常也很薄弱,容易被逆向工程破坏,从而暴露 PII(个人身份信息)。
代替
数据中的真实值被替换为不同的“真实”值。例如,用从外部姓名列表中随机选择的姓名替换一列中的所有真实姓名。在某些情况下,替换可能涉及用随机编码的字符串替换 PII,只有原始数据管理员才能将其匹配回原始记录。例如,将“John Smith”替换为“R7JxvOAjtT”。
Pro: 对于替换值,任何人都不可能知道真正的值是什么,因为原始值已经完全从数据集中删除了。
Con: 需要一个可访问的替代“真实”数据列表来执行替换。这可能需要购买精心策划的数据集,如假姓名、电话号码、地址等,这可能很昂贵。
反对:逆向工程。参见下面的案例研究。
随机化算法“洗牌”
旨在随机排列同一列中的数据顺序。与用来自外部源的相似值替换值的替换不同,混排可以被认为是内部替换的一种形式,它只替换同一列中的值。
Pro: 与其他数据屏蔽方法结合使用时可以有效。例如,在供应商名称和合同价值的给定数据集中,简单地打乱供应商名称是无效的,因为任何具有行业特定知识的人都可以拼凑出合同规模和供应商的可能组合。如果供应商名称被掩盖和被打乱,那么几乎不可能找出供应商。
弊:依赖与其他有效的掩蔽方法一起使用会破坏它的使用。
弊:逆向工程。当单独使用时,具有数据领域知识的攻击者可以简单地交换列值以获得原始值。
指零
简单地将机密数据替换为“空”值,如“NA”、“null”、“Missing”等。
Pro: 跨不同列实施的简单解决方案。
反对意见:很明显,数据被修改过,并不完全是原始的。还让用户确切地知道哪些单元丢失,如果不使用其他屏蔽方法,这使得有针对性的逆向工程攻击更容易。
弊:空值会使数据集难以分析,因为空的纯数字列会变成文本或字符串。
删除
从数据集中删除 PII 列。
Pro: 快速实现。
反对:对于应该删除哪些列,需要一定程度的主观性。定义哪些列被认为是 PII 并不总是那么简单,因为攻击者可能使用几个非 PII 列的组合来推断 PII。
缺点:删除几列可能会严重影响屏蔽数据集的效用。
掩饰
用类似“X”的替代符号模糊部分数据值。例如,信用卡号码 XXX — XXXX — XXXX — 9823。屏蔽和置零的主要区别在于,屏蔽保留了原始数据的一般格式。例如,我仍然可以看到信用卡号码是由 4 个数字“XXXX”组成的,即使我不知道它们的值。
Pro: 隐藏敏感数据,无需完全删除或使用置零。
弊:可能会遇到与零化相同的数据分析问题,因为替代符号会降低数据的效用。
摄动
推荐阅读:https://pdfs . semantic scholar . org/f541/758 a 9179998 a1 b21d 28 D1 feb 90428 dafad 90 . pdf
数据扰动是一种隐私保护方法,最初是为电子健康记录设计的[1]。目标是使用假数据或重用同一数据集中的数据,将“噪声”注入数据。噪音意味着你引入了关于数据集中真实值的不确定性。不确定性=数据屏蔽中似是而非的可否认性因为攻击者无法知道他看到的是否是真实的数据值。有两种扰动方法。 1) 分布方法 —用仍然允许数据集保持相似统计属性的假值替换数据中的值。可以通过替换同一分布样本或分布本身的值来实现这一点。 2) 值失真 —使用乘法或加法或您选择的其他随机过程添加噪声。例如,将 1-5 之间的随机数添加到人的年龄中,或者将列表中的每个工资随机更改为真实值的+/- 10%,这样真实工资不会被披露,但趋势仍然可以观察到。
Pro: 高度灵活的解决方案,允许以无限多种方式向数据添加噪声,同时保持统计属性。
反对:逆向工程。参见下面的案例研究。
传统方法导致的数据泄漏:案例研究
Netflix 奖
2006 年,网飞发起了“Netflix 奖”,这是一项设计算法来预测顾客对电影评价的在线竞赛。网飞提供了一个由 48 万用户为 17k 部电影制作的 1 亿收视率数据集。网飞对数据集进行了匿名化处理,用替换法将用户名替换成编码字符串,并用虚假评分扰乱一些评分。2008 年,德克萨斯大学奥斯汀分校的两名学生发表了“大型稀疏数据集的稳健去匿名化”一文,详细介绍了针对高维微观数据的一类新的统计去匿名化攻击。通过结合网飞的数据和 IMBD 的数据,学生们能够揭示谁是用户。在数据泄露的例子中,Netflix 奖现在无处不在。
斯威尼对州长维尔德[3]
推荐阅读:https://dataprivacylab . org/projects/identificability/paper 1 . pdf
1997 年,马萨诸塞州团体保险委员会公布了医院就诊数据,目的是改善医疗保健和控制成本。这篇文章引起了 Latanya Sweeney 的注意,她当时是麻省理工学院研究计算披露的研究生。时任马萨诸塞州州长的威廉·韦尔德向公众保证,PII 等名字已经从数据中删除。Sweeney 知道 Weld 州长住在剑桥,一个只有 7 个邮政编码的小镇,他有一种直觉,医院的数据可以很容易地追溯到对目标只有基本了解的个人。花 20 美元从市里买了一份选民名单,包括:姓名、地址、邮政编码、出生日期和性别。Sweeney 发现只有少数人知道 Weld 州长公开的出生日期,其中只有一个人的邮政编码与 Weld 居住的城镇相匹配。斯威尼把他自己的诊断和处方清单寄给了州长的办公室。#野蛮人。2000 年,Sweeney 发表了另一篇论文[4],指出只需要 3 条信息:邮政编码、出生日期和性别就可以识别 87%的美国人。
匿名数据的现代方法:差分隐私
推荐阅读:【https://arxiv.org/pdf/1911.12704.pdf】T4
今天,最新和最流行的数据匿名形式之一是差分隐私,它本质上是一种更加形式化和参数化的扰动形式[5]。具体来说,就是的分配方式。差分隐私提供了一个数学框架来量化必须注入数据集的最小噪声量,以确保数据泄漏不超过某个限制“ε”。
创建一个私人系统(一个可以匿名化你的数据的系统)的过程包括思考你的最终目标,然后逆向工作。您首先要考虑您希望共享的特定功能/数据列。然后,你决定一个正式的隐私系统,这是一套数学标准,当满足时,意味着你的数据集不能泄漏超过极限ε的数据。然后你选择你的噪声注入方法。噪声注入的方法是任意的,有许多方法和算法可以使用。重要的是,无论您选择哪种方法,您都可以将它参数化,以便它可以用来证明它满足您在隐私系统中指定的条件。当这些条件得到满足时,该系统被称为正式私有。
“差异”一词在哪里起作用?
差分指的是这样一个事实,即对于给定的将噪声注入数据集的计算任务“T ”,有许多算法可以实现给定ε的期望噪声。因为有许多不同的方式来实现 epsilon 隐私,我们说数据是不同的隐私。因此,差分隐私是一个定义,不是一种算法。因此,有可能创建一个正式的私有系统(满足您的隐私系统的条件),但不是差别私有,并且只有一种方式满足您的系统的噪音标准。选择使用差分隐私还是正式的非差分隐私系统取决于使用案例。此外,也可以选择使用非形式化的“特定”噪声注入,但存在创建匿名化较差的数据的风险,这些数据很容易被攻击者(例如 Netflix Prize)进行逆向工程。
为什么有人会选择特别的“非形式化”数据隐私?
差分隐私设置可能很复杂,也很及时。正如在匿名化水*和数据效用之间存在权衡一样,在隐私系统的努力和复杂性之间也存在权衡。差分隐私的最大问题是,当ε很小时(少量数据泄漏),为‘T’找到精确的(很好地保持统计特性)差分隐私算法变得越来越困难。在这种情况下,有人可能会选择一个正式的无差别的私有系统。如果无法找到一个单一的算法来满足一个非差异私有系统,那么您可能会默认一个特定的、非形式化的系统作为最后的手段。
可以说,一个正式的隐私系统的最大好处之一是,它作为一种质量控制的形式,因为该系统及其标准是有文件证明的。这在医疗保健、金融和银行等隐私敏感行业非常重要。对于许多公司机构来说,除非有明确的理由、合理的理论和可追溯的实施,以经受住行业和政府审计的严格性,否则什么都不能实施。坦率地说,就今天的隐私要求而言,网飞在 12 年前实施的特设隐私系统是可笑的。然而,它是一个重要的提醒,提醒我们隐私系统已经发展到了什么程度。
差异隐私解决了这样一个悖论:在学习关于一个群体的有用信息的同时,却对一个个体一无所知[5]
差分隐私工具箱
DP-SYN
基于图形模型的评估
https://github.com/ryan112358/private-pgm
论文:https://arxiv.org/abs/1901.09136
DP-SGD
https://github.com/tensorflow/privacy
论文:https://arxiv.org/abs/1607.00133
古普特https://github.com/prashmohan/GUPT
论文:https://www.cs.umd.edu/~elaine/docs/gupt.pdf
ARX 数据匿名工具
差分私有凸优化基准——各种差分私有凸优化算法的集合
https://github.com/sunblaze-ucb/dpml-benchmark
- *似极小值扰动
论文:http://www.uvm.edu/~jnear/papers/TPDPCO.pdf
- 私有随机梯度下降
论文:https://arxiv.org/abs/1405.7085
论文:https://arxiv.org/pdf/1607.00133.pdf
- 基于私有凸扰动的随机梯度下降
论文:https://arxiv.org/pdf/1606.04722.pdf
- 二等兵弗兰克-沃尔夫
论文:https://arxiv.org/pdf/1411.5417.pdf
二重唱
https://github.com/uvm-plaid/duet
论文:https://arxiv.org/abs/1909.02481
埃克泰罗
https://github.com/ektelo/ektelo
论文:https://dl.acm.org/citation.cfm?id=3196921
隐私保护应用
https://github . com/us dot-its-JPO-data-portal/privacy-protection-application
教师集体的私人聚集https://github.com/tensorflow/privacy/tree/master/research
论文:【https://arxiv.org/abs/1610.05755】T42
论文:https://arxiv.org/abs/1802.08908
DP comp——基于网络的工具,旨在帮助从业者和研究人员评估基于 DPBench 的最新差分私有算法的准确性
【https://github.com/dpcomp-org/dpcomp_core#dpbench
论文:https://people.cs.umass.edu/~dzhang/dpcomp_demo.pdf
DPBench —隐私算法标准化评估框架
论文:https://arxiv.org/abs/1512.04817
Gretel —使用神经网络创建差分私有数据的包
https://github.com/gretelai/gretel-synthetics
推荐阅读:
https://towards data science . com/understanding-differential-privacy-85ce 191 e 198 a
https://digitalcommons.ilr.cornell.edu/ldi/49/
https://www . science mag . org/news/2019/01/can-set-equations-keep-us-census-data-private
MWEMhttps://arxiv.org/abs/1012.4763
双重查询https://arxiv.org/abs/1402.1526
HDMMhttps://arxiv.org/abs/1808.03537
远离匿名方法:合成数据
随着机器学习模型变得更加复杂,关于数据匿名化的想法也发生了变化。研究小组没有将复杂的算法应用于数据集,而是尝试着教导模型识别数据集内的模式,然后根据模型所学生成“综合”数据。
决策树和贝叶斯网络通过对表格数据中的离散变量建模,提供了一种新的匿名化数据的方法,并且效果良好。随后 copulas 用于建模非线性相关连续变量。使用 copulas 的一个好处是能够对各种分布进行建模,例如单变量数据(高斯、贝塔、伽马、高斯 KDE、截断高斯)双变量数据 (Clayton、Frank、Gumbel、Ali–Mikhail–Haq、Joe)和多变量数据 (Guassian、D-Vine、C-Vine、R-Vine)。
不要脸的塞:https://medium . com/@ Timothy pillow/introduction-to-copulas-ad 1 a3 b 83 a 297
合成数据和匿名数据有什么区别?
推荐阅读:https://www-cdn . law . Stanford . edu/WP-content/uploads/2019/01/bello vin _ 2019 01 29-1 . pdf
包括形式化隐私系统在内的传统匿名方法可以被认为是扭曲或净化技术,旨在将扭曲和不确定性直接应用于原始数据集。在某种意义上,你可以说你“将匿名化应用到衣服本身”。
合成数据的关键区别在于,结果是由原始数据集间接生成的,因为它是“学习”分布的结果。因此,尽管合成数据具有与原始数据集相似的属性,但是可以将其视为与原始数据不同的。
合成数据的一个问题是,如果模型很好地学习了联合分布,则*由于合成数据由从模型学习的分布中随机采样的组成,因此合成数据集包含值的组合的可能性非常小,这些值完全可能对应于:与原始数据集相同的行,或者更可能对应于:可以在原始数据集中找到的行内的部分值。如果这些值对应于任何高风险 PII 数据,如邮政编码、出生日期或性别的真实组合,这尤其是个问题。因此,将合成数据与差分隐私相结合可能会两全其美。*****
关于命名的快速警告
术语“合成数据”在差分隐私中被随意使用。常见术语,如“差分隐私合成数据”或“差分隐私生成的合成数据”是不明确的,因为它要么意味着 1)合成数据是使用“不同布”的方法生成的,并使用差分隐私进一步净化或 2) 差分隐私已用于创建对原始数据唯一的匿名化数据集,因此被假定为“合成的”。不幸的是,后一个定义是最常用的,我认为它是最模糊的。我个人认为,如果数据是“相同的布料”,它就没有被合成;已经被扭曲/消毒了。无论如何,当你看到有差别的私有数据时,要记住一点:仅仅因为它是合成的并不意味着它是有差别的私有的,仅仅因为它是有差别的私有的并不意味着数据最初是使用“不同布料”的方法合成的。
综合数据工具箱
决策树
CART(分类和回归树)—离散变量
https://github.com/ColleenBobbie/Cancer-Prediction
SDT(空间分解树)—空间数据
论文:https://arxiv.org/abs/1103.5170
隐私树—空间数据
论文:https://arxiv.org/abs/1601.03229
贝叶斯网络
CLBN
论文:【https://ieeexplore.ieee.org/document/1054142
PrivBN(通过贝叶斯网络发布私人数据)
论文:http://dimacs.rutgers.edu/~graham/pubs/papers/PrivBayes.pdf
数据合成器
https://github.com/DataResponsibly/DataSynthesizer
论文:https://faculty . Washington . edu/bill Howe/publications/pdf/ping 17 data synthesizer . pdf
连系
SDV-Copulas(综合数据仓库)
https://github.com/sdv-dev/Copulas
SDV——建模和采样关系数据库
https://github.com/sdv-dev/SDV
论文:https://ieeexplore.ieee.org/document/7796926
合成数据的最新方法:GANs
推荐阅读:https://towardsdatascience . com/review-of-gans-for-tabular-data-a30a 2199342
生成性对抗网络(GANs)由两个在迭代循环中相互对抗的模型组成。一个模型扮演“发生器”,另一个扮演“鉴别器”。与使用 GANs 生成深度赝品的方式类似,它们也可以用于生成与原始数据非常相似的合成表格数据。除了使用应用于神经网络的权重和过滤器来添加噪声之外,将噪声添加到数据集的相同基础也适用于 gan。用于图像的 GANs 和用于合成数据的 GANs 之间的另一个区别是,用于图像的 GANs 通常使用卷积神经网络(CNN),因为生成/检测伪图像的环境要求模型迭代图像的层,而一层不影响下一层的生成。例如,如果鉴别器使用边缘检测滤波器,那么您不希望边缘滤波器的检测能力基于应用于图像的先前滤波器而改变[6]。本质上,你不希望过滤器有记忆。
用于合成表格数据的 GAN 通常将使用递归神经网络(RNN) 作为架构,因为您可以实现长短期记忆(LSTM)。LSTM 网络和 CNN 之间的一个关键区别是,LSTM 能够为网络增加内存,从而可以学习的长期依赖性,当您希望 GAN 能够识别数据集内的相关属性时,这一点尤为重要。
GAN 工具箱
梅德根
https://github.com/mp2893/medgan
论文:https://arxiv.org/abs/1806.06397
相关论文:https://arxiv.org/abs/1703.06490
维根
https://github.com/akashgit/VEEGAN
论文:https://arxiv.org/abs/1705.07761
TableGAN
https://github.com/mahmoodm2/tableGAN
论文:http://www.vldb.org/pvldb/vol11/p1071-park.pdf
埃尔根
论文:https://arxiv.org/abs/1709.01648
肉酱
论文:https://openreview.net/pdf?id=S1zk9iRqF7
相关论文:https://arxiv.org/pdf/1906.09338.pdf
DP-WGAN
https://github . com/nesl/NIST _ differential _ privacy _ synthetic _ data _ challenge
论文:https://github . com/nesl/NIST _ differential _ privacy _ synthetic _ data _ challenge/blob/master/reports/UCLANESL _ solution _ privacy _ proof . pdf
相关论文:https://papers . nips . cc/Paper/7159-improved-training-of-wasser stein-gans . pdf
DP-GAN(张炘炀、纪守灵、)
https://github.com/alps-lab/dpgan
论文:【https://arxiv.org/pdf/1801.01594.pdf
【DP-GAN(李阳谢,林凯翔,,,)
https://github.com/illidanlab/dpgan
论文:https://arxiv.org/pdf/1802.06739.pdf
TGAN
https://github.com/sdv-dev/TGAN
论文:https://arxiv.org/abs/1811.11264
CTGAN
https://github.com/sdv-dev/CTGAN
论文:https://arxiv.org/abs/1907.00503
合成数据的未来?
到目前为止,我们已经看到,机器学习在从数据中学习方面非常有效,并且能够复制合成数据,这些数据:
-保持与原始数据相同的统计分布
-了解不同列之间的相关性
-提供出色的数据匿名功能
-可缩放至任何尺寸
-可以无限次取样
与数据监管服务和使用传统方法泄露数据时的法律诉讼成本相比,生成合成数据极具成本效益。正在进行越来越多的研究来比较对原始数据集和合成数据集进行的数据分析的质量。此外,一些研究人员对合成数据如此有信心,以至于“科学家可以像使用控制数据一样使用合成数据”。
随着数据隐私越来越受到公众的重视,这是一个可能会以指数速度增长的研究领域。
51%的高级企业受访者表示,部门之间缺乏数据共享是数据战略中的一个关键问题。【7】
消费者数据显示…
86%的人希望对公司掌握的数据行使更大的控制权
76%的人担心分享数据会让他们成为营销活动的目标
34%的人提供了伪造的个人信息,以避免泄露个人信息 [8]
数据屏蔽市场预计将以 14.8%的复合年增长率增长(CAGR),到 2022 年价值将达到 7.67 亿美元 [9]
全球隐私管理软件市场预计将增长 33.1%(CAGR)。【10】
请随时给我发消息,我会把它们添加到列表中。
[1]D . v .,Kumar N . k .,& R.Lakshmi Tulasi,D. (2018)。基于综合数据扰动的云增量数据集隐私保护技术。国际工程与技术杂志,7(3.34),331–334。http://dx.doi.org/10.14419/ijet.v7i3.34.19219
[2] A. Narayanan 和 V. Shmatikov,“大型稀疏数据集的稳健去匿名化”, 2008 年 IEEE 安全和隐私研讨会(sp 2008) ,加利福尼亚州奥克兰,2008 年,第 111–125 页。https://ieeexplore.ieee.org/document/4531148
[3] Barth-Jones,Daniel,“威廉·韦尔德州长医疗信息的‘重新识别’:对过去和现在的健康数据识别风险和隐私保护的关键重新检查”( 2012 年 7 月)。http://dx.doi.org/10.2139/ssrn.2076397
[4] L. Sweeney,简单的人口统计数据通常可以唯一地识别人。卡内基梅隆大学,数据隐私工作文件 3。匹兹堡 2000。https://dataprivacylab . org/projects/identificability/paper 1 . pdf
[5]辛西娅·德沃克和亚伦·罗斯。2014.差分隐私的算法基础。找到了。趋势理论。计算机。Sci。9,3–4(2014 年 8 月),211–407。https://doi.org/10.1561/0400000042
[6] Bellovin,Steven M .和 Dutta,Preetam K .和 Reitinger,Nathan,《隐私和合成数据集》(2018 年 8 月 20 日)。斯坦福技术法律评论,即将出版。http://dx.doi.org/10.2139/ssrn.3255766
[7]大卫·罗杰斯,唐·塞克斯顿。大数据时代的营销投资回报率:2012 年 BRITE/尼亚马转型营销研究。哥伦比亚商学院。2012.https://www 8 . gsb . Columbia . edu/global brands/sites/global brands/files/images/2012-BRITE-尼亚马-营销-投资回报-研究. pdf
[8]马修·金特和大卫·罗杰斯。数据共享的未来是什么?消费者心态和品牌的力量。哥伦比亚商学院。2015 年 10 月https://www8 . gsb . Columbia . edu/global brands/sites/global brands/files/images/The _ Future _ of _ Data _ Sharing _ Columbia-Aimia _ December _ 2015 . pdf
[9]市场与市场。按数据屏蔽类型(静态和动态)、组件(软件和服务)、部署类型、组织规模、业务职能(财务、营销和销售、运营和法律)、垂直市场和地区划分的数据屏蔽市场—到 2022 年的全球预测。2017 年 12 月https://www . marketsandmarkets . com/Market-Reports/data-masking-Market-24977919 . html
[10]市场观察。CAGR 占 33.1%,到 2025 年隐私管理软件市场规模将达到 32.9 亿美元。2020 年 4 月 6 日。https://www . market watch . com/press-release/at-331-cagr-privacy-management-software-market-size-set-to-register-32.9 亿美元-by-2025-2020-04-06
多臂 Bandit 算法路线图
最*一直在读 Tor Lattimore 和 Csaba Szepesvári 的 Bandit Algorithms,并在一个读书会上讨论。我想,在思考或描述强盗问题时,最好退后一步,在一个非常高的层次上总结一些人们可能会问的主要问题!
如果你还不熟悉 bandit 算法,不用担心!我希望在我的小组通过 Bandit 算法文本进行研究时,能对它们做一个很好的记录(真的很好!).但是现在,让我做一个简短而甜蜜的总结:
Bandit 算法是一种可以在不确定环境中执行的学习算法。具体来说,他们的名字来源于老丨虎丨机的想法。它可能有许多手臂,拉一只手臂可能会给你奖励。其思想是,通过*衡探索和利用,bandit 算法可以理解每只手臂的潜在奖励分布,允许学习者利用并获得可能的最佳累积奖励。
那么,他们为什么被称为土匪呢?因为他们拿走你所有的钱(或者说,老丨虎丨机确实 lol)。

正如我们将从我提出并强调的一些问题中看到的,bandit 算法为许多学习问题提供了一个非常通用的公式,只要我们保留某些关键假设(例如今天选择一个动作不会改变明天可用的动作)。对于更复杂的学习问题,强化学习就变得必要了!
我们将在本帖中考虑的一些问题包括:

事不宜迟,让我们开始吧!
行为空间
你的环境是什么样的,你的学习者需要什么样的行动空间来与环境互动?
无限对有限
首先要区分的是无限和有限动作空间之间的区别。有限动作空间很好理解。这类似于每次“选择 k 个分支中的一个”,很可能是大多数人第一次想象 bandit 算法与他们的环境交互的方式。
相比之下,无限的行动空间也是可能的。你可能会想“但是怎么做呢?”因为这几乎是不可能的。但事实上,如果我们的空间有限,这是很有可能的。我的意思是,想象你只有一个动作,但是你可以用从 0 到 1 的一系列值来选择它。现在你的空间是无限的!零到一之间的任何数字都是可能的(也许是我们施加在手臂上的力的大小)。关键是这里有一些约束使得问题成为可能,比如奖励结构上的李普希茨条件,使得最优行动不能隐藏在任意小的空间中。
单一动作对组合动作
你的土匪和它的环境互动时,是只允许拉一只胳膊(玩一个动作)还是可以同时玩多个?这就是单一作用空间和组合作用空间的区别!如果你有一个环境,让你的学习者可以同时拉多个手臂(同时玩多个动作),那么你就有了一个组合动作空间。
想象一下,你有一个图,你的学习者想要从节点 S 到节点 t。每一轮,学习者有机会选择它将包括在从 S 到 t 的路径中的边。然后,整个图中的每条边将以该边唯一的概率被丢弃。如果你的学习者的路径完全完好无损,那么当它从 S 导航到 t 时,它会得到奖励。否则,它不会得到任何奖励。这种边的子选择是组合动作空间的一个例子!
总而言之:

问题结构
处理强盗问题的另一个基本问题是你的问题/环境是否有结构。我的意思可以简单地表述为:选择一个动作会显示出你没有玩过的动作的任何信息吗?如果是,问题有结构!否则,你有一个无组织的土匪问题。
一个非结构化的土匪问题并不是没有希望的(事实上,这似乎很常见)。这只是意味着,如果我有一个双臂强盗,我不能通过玩手臂 1 来学习任何关于手臂 2 的东西。我可能知道他们都是通过高斯分布产生奖励,但是这并没有给我任何联系。
相比之下,我们可以有一个双臂土匪,双臂产生的回报与伯努利分布,有一个单一的参数。我的意思是说,臂 1 由𝜃θ参数化,臂 2 由 1−𝜃1−θ.参数化只有一个参数需要学习,这是整个问题的基础,通过弹奏第一只手臂,我获得了关于另一只手臂的信息!
外信息
你的学生可以利用任何额外的信息吗?这可以极大地提高算法的性能(通常是以好的方式)。
例如,如果你有一个上下文,你的学习者可以通过上下文强盗算法来利用它。假设你有一个双臂土匪,但手臂在一周的不同天表现不同(但在一周的相同天表现相同)。如果你用一个普通的 bandit 算法来解决这个问题,回报将会非常不稳定,并且会损害性能。然而,如果你在行动决策过程中使用上下文(一周中的几天),那么你的学习者应该表现得更好!
再一次,想象你的 bandit 算法正试图学习一个流行的搜索引擎的广告投放。它可以只从动作集中选择一个广告并显示给用户,但这可能会导致整体表现不佳。相反,如果有一个向量表示使用搜索引擎的用户的一些信息,也许我们可以将用户上下文向量合并到我们的 bandit 算法学习过程中!
奖励机制
土匪问题如何产生奖励?它们是随机的,并且来自同一个分布吗?或者,也许,环境是敌对的,奖励被选择为最坏的情况,给定了关于 bandit 算法如何学习的知识。
随机的
在随机奖励生成设置下,每个动作对应一个 IID 奖励。也就是说,每个动作都有一个基础分布,当选择一个动作时,它会从中进行采样。它永远不会改变,因此学习者只需要探索手臂,直到它能够正确地限制奖励产生分布的形状。
非*稳的
从技术上讲,奖励分布可以是非*稳的,但学习算法将为此付出代价。鉴于如何回报将是不稳定的某种规则,分析可以考虑这将如何影响整体表现。这可以被看作是对随机设置的放松,但这是有代价的。
对手的
在对抗的环境中,所有的假设都被抛弃了。奖励是以对抗的方式选择的,旨在选择最差的结果,让学习者失去兴趣。幸运的是,在这样的环境中,学习者仍然可以做很多事情(随机化是关键)。我希望在另一个帖子中更详细地谈论这一点!
总结一下:

学习者反馈
我们在这里要强调的最后一个问题是,强盗式学习者收到的反馈的性质。为了使一个问题成为强盗问题,学习者需要在每一轮/每一时间步结束时收到一个奖励信号。但是学习者收到了多少反馈呢?
土匪反馈
Bandit feedback 是一个术语,指的是只从学习者选择的行为中获得奖励信息。如果手臂一被使用,只有手臂一的奖赏被观察;其他的手臂,虽然可以玩,但不能玩,所以学习者不能获得关于它们或它们的奖励的信息。
这是传统的强盗设定,例如,当环境是随机的时,这很有意义。在组合设置中,非常有趣的是,bandit 反馈只为子动作的组合提供了一个信号。也就是说,学习者不会立即看到每个子动作提供了什么,而是看到了累积的信号。
全面反馈
另一方面,学习者可以观察到每一步的所有行动回报。这在对抗环境中非常有用,并且允许开发一些有趣的算法。在随机环境中,这没有任何意义,因为这样一来,学习者就永远不需要探索了。他们会简单地根据有界观测值选择最佳臂,然后在每个时间步更新边界。这会使随机问题变得非常琐碎。
部分反馈/半土匪反馈
可以把这个反馈场景看作是 bandit 和 full feedback 之间的中间地带。它在组合设置中最有意义,指的是观察到累积奖励信号的情况,但在组合空间中选择的每个子动作的子分量信号也是如此。
如果一个人正在对上班所花费的时间进行建模,这可能很有意义。如果我今天走了一条小路,并且知道这样做需要大约 5 分钟,那么当我明天开车去上班时,我可以应用那个子信息。
部分监控
在不是每一轮都收到反馈的情况下,我们处于 bandit 算法之外。然而,如果你感兴趣,我鼓励你研究一下部分监控。
以下是这些设置的汇总图:

包扎
所以,这就是我目前总结的在处理多臂土匪和土匪问题时要考虑的一些关键问题。我做得怎么样?我错过了什么关键问题吗?让我知道!
销售仪表板告诉你人们最喜欢为 2019 年圣诞节买什么
圣诞节刚刚过去。今年圣诞节你收到了什么礼物,送了什么礼物?你是否好奇 2019 年圣诞节最畅销的商品是什么,人们最想要的礼物是什么?这些问题的答案都在我下面做的圣诞销售仪表盘里。让我们来看看。
这个圣诞仪表板是我用互联网上的数据制作的在线销售仪表板。
我们先来看左边的两张图表。下面的柱状图展示的是每一类产品的销售额,上面的折线图展示的是某一类产品的年销售额。注意,左边的两个图表是联动的,即如果你在下面的柱状图中点击不同的产品类别,上面的折线图中就会显示出对应产品类别的年销量。

中间酷炫的 3D 地球地图显示了圣诞节订购商品的物流路线,流线的粗细对应着商品的销量。我们还可以定制流线的样式。
仪表盘右上角是一个字云图,显示了人们最想要的圣诞礼物类别。字体越大,这类礼物越受欢迎。
最后,让我们看看右下角的实时销售图表。该图表可以连接到数据库系统,以更新实时销售数据。并且通过上面的水球图,可以实时观察产品的仓库库存。当存储容量低于警戒线时,会显示红色警告,并弹出一个框通知您:缺货。
现在,我相信你们都知道什么是最受欢迎的圣诞产品类别。这个圣诞销售仪表板上的数据可能不准确,但您仍然可以从数据可视化的实现和销售仪表板的设计中学习。如果你有兴趣,我很乐意和你分享制作这个圣诞仪表盘的方法和技巧。以下是具体制作过程。
步骤 1:选择工具并准备数据
首先,我们需要选择一个合适的数据可视化工具或 BI 工具来设计很酷的仪表盘。如果你有很强的技术功底,也可以用 Python 或者 r 之类的编程语言,我做这个圣诞仪表盘用的工具是 FineReport 。可以从官网下载其个人版免费使用。
N OTE: FineReport 是我工作的数据研究所开发的一款 BI 报告工具。个人使用完全免费。你可以下载它来练习制作图表、报告和仪表板。
圣诞节仪表盘中的数据来自统计公司。并将数据存储在 Excel 文件中。接下来,我们需要将数据导入 FineReport。
步骤 2:导入数据
下载 FineReport 后,将 Excel 文件放在计算机上的“Reportlets”文件夹中。或者您可以使用自己的数据并将 FineReport 直接连接到您的数据库。



第三步:图表链接
要实现数据的联动,可以选择一个数据库来连接数据。



而要实现图表联动,使用简单的 SQL 语句作为条件。

第四步:设计布局
准备好数据后,开始布局。我选择绝对布局的类型。点击“body”,可以设置其属性。


步骤 5:插入图表
我们只需要拖放来插入图表。对于图表的选择,可以参考本文 数据可视化中前 16 种图表类型 。

总体布局如下。

然后为图表设置数据。依次选择图表所需的数据。

对于链接效果,我们之前已经设置了简单的 SQL 语句。现在我们为需要链接的图表设置参数。

第六步:实时显示数据
右下方的实时销售图表可以实时更新销售数据。这种效果是 FineReport 的免费插件直接实现的。

对了,雪花的效果是用 JS 实现的。你可以自己做。

终于
嗯,这些是制作圣诞仪表盘的主要步骤。如果你对操作还有疑问,还有两个更详细的指南供你参考: 制作销售仪表盘的分步指南 和 新手如何打造一个很棒的仪表盘 。
您可能也会对…感兴趣
用于自动化结构化数据准备的可扩展预测引擎
活动讲座
Ihab 易勒雅斯| TMLS2019
来自多伦多机器学习峰会的演讲:【https://torontomachinelearning.com/
关于演讲者
伊哈布·易勒雅斯是滑铁卢大学的计算机科学教授,也是 Tamr |https://cs.uwaterloo.ca/~ilyas/的联合创始人
关于谈话
“数据科学家花费大量时间准备、清理和转换原始数据,然后才有机会将这些数据提供给他们精心制作的模型。
尽管努力建立稳健的预测和分类模型,但数据错误仍然是低质量结果的主要原因。这种大规模的劳动密集型数据清理工作仍然是数据科学自动端到端人工智能管道的主要障碍。
在本次演讲中,我将重点讨论作为推理问题的数据准备和清理,这可以通过利用 ML 中的现代抽象来实现自动化。
我将描述 HoloClean 框架,这是一个用于结构化数据的可伸缩预测引擎。该框架有多个成功的概念证明,包括清理普查数据、市场研究数据和保险记录。多个商业企业的试点显示,在将源(训练)数据提供给下游分析之前,这些数据的质量有了显著提高。
HoloClean 构建了两个主要的概率模型:一个数据生成模型(描述数据的预期外观);以及一个实现模型(描述错误如何被引入到预期的干净数据中)。该框架使用少量学习、数据扩充和自我监督来学习这些模型的参数,并使用它们来预测错误及其可能的修复。"
朱莉娅语言快速浏览
体验朱莉娅,而不必做任何困难的事情

钱德勒·陈在 Unsplash 上的照片
介绍
Julia 是一种新的多用途编程语言,旨在通过提供易用性和速度来解决“两种语言问题”。
2010 年代开发的另外两种最受欢迎的新语言,Go 和 Rust,看起来都像是经过清理的 C 或 C++。相比之下,Julia 看起来像 Python 或 Matlab,只是稍微有点变化。这就是为什么 Julia 在科学家和学者中引起了很大的兴趣,他们通常更喜欢更容易开发和理解的语言。然而,随着 Julia 的库的成熟,Julia 在数据科学社区中获得了一些人气,尤其是在深度学习方面。
朱莉娅越来越受欢迎
如今,Julia 的下载量超过 100 万次,年增长率为 161%。包括亚马逊、苹果、迪士尼、脸书、福特、谷歌、IBM、微软、NASA、甲骨文和优步在内的大公司都是 Julia 的用户、合作伙伴或者正在雇佣 Julia 程序员。

纽约美联储银行的经济学家已经采用茱莉亚作为模型。他们报告说,有了 Julia,他们估算模型的速度比 T8 快了 10 倍,代码行数减少了一半,节省了时间,提高了可读性,减少了错误
用他们的话说:
“我们希望用我们的模型解决困难的问题——从理解金融市场发展到对家庭异质性建模——只有当我们接*编程的前沿时,我们才能做到这一点。”
一粒盐
虽然朱莉娅很令人兴奋,但重要的是不要轻信所有关于朱莉娅的炒作(T21)。处于编程的前沿并不总是一件好事。因为它太新了,所以 Julia 的代码库可能会有所欠缺。许多 Julia 库仍在更新和扩展,每隔几个月就有新的特性添加到语言中。随着旧功能的贬值,这可能会带来一些成长的烦恼。
是时候让朱莉娅成为你的主要语言了吗?也许吧。这取决于你需要从你的编程语言中得到什么。如果你需要更广泛使用的东西,Julia 可能不是最好的选择。但是,不管它是否应该是你的主要语言,朱莉娅是值得调查的。
茱莉亚代码的风景照
接下来的部分包含解决不同领域问题的 Julia 代码片段。这些代码的目的是以简单易懂的方式展示日常编程在 Julia 中的样子。
数学和统计学
基础数学:
**# Polynomial function. Evaluating p(1) returns 9* p(x) = x^2 + 2x + 6# Make a (2,2) matrix of 1s
A = fill(1, 2, 2)# Matrix vector multiplication
x = rand(2)
y = A * x# Elementwise multiplication
B = A .* 5# Square every element of an array
B = B .^ 2*
从分布中随机抽取样本:
*using Distributions*# Take 100 samples from a normal distribution* dist = Normal(0, 1)
x = rand(dist, 100)*
求矩阵的特征值:
*using LinearAlgebraA = rand(10, 10)
evals = eigvals(A)*
文件 IO 和字符串
读入文件并列出单词列表:
*fstream = open("my_file_name.ext")
lines = readlines(fstream)
split_space(x) = split(x, " ")
words = map(split_space, lines)
all_words = reduce(append!, words)*
在目录中查找.txt文件:
*current_directory = @__DIR__
files = readdir(current_directory)
is_txt(x) = endswith(x, ".txt")
txt_files = filter(is_txt, files)*
数据结构
创建最大堆并获得最大值:
*using DataStructuresdata = rand(100)
heap = BinaryMaxHeap(data)
max_val = top(heap)*
机器学习
制作并训练一个密集的神经网络。(感谢吉米·罗耶更新了代码)
*using Flux
using Flux: msemodel = Chain(
Dense(2,100, relu),
Dropout(.5),
Dense(100, 100, relu),
Dropout(.5),
Dense(100, 1, relu),
softmax
)# Random points in the plane
X = rand(2, 1000)# Label where points are within the unit circle or not
Y = sum(X .^ 2, dims=1) .< 1println("Example data")
for index in 1:10
println("x1, x2, y = ", X[1, index], ", ", X[2, index], ", ", Y[index])
end# Mean squared error loss function
loss(x, y) = mse(model(x), y)# Format data and extract trainable parameters
data = [(X, Y)]
ps = Flux.params(model)# Train with stochastic gradient descent
optimizer = Descent(0.01)for epoch in 1:300
Flux.train!(loss, ps, data, optimizer)
end*
结论
我已经用 Julia 写了一年多的代码,对这门语言非常感兴趣。虽然它要像 Python 一样成熟还有很长的路要走,但我相信它会成为科学计算和数据科学的顶级语言之一。
跳到好的方面
towardsdatascience.com](/how-to-learn-julia-when-you-already-know-python-641ed02b3fa7) [## Julia 如何利用多重调度击败 Python
亲自看
medium.com](https://medium.com/swlh/how-julia-uses-multiple-dispatch-to-beat-python-8fab888bb4d8)*
寻找有效的元学习:哺乳动物、爬行动物和相关物种
一个经常被抱怨的事实是,现代机器学习的能力往往是狭窄和脆弱的:虽然给定的技术可以应用于许多任务,但个人学习的模型只专注于一个,并且需要大量数据来获得这种专业能力。
元学习提出:有没有一种方法可以跨任务训练一个模型,使特定新任务的获取更快、数据效率更高,而不是在每个新任务上从头开始?元学习和相关的少量学习学科的方法有许多形式——从学习任务不可知的嵌入空间到递归网络,递归网络顺序传递训练数据并在它们的状态进化权重中编码学习算法——但可以说这些方法中最直观的是 MAML:模型不可知的元学习。

[题外话:这篇博客文章将假设一定量的元学习背景,主要围绕学习不是发生在单一任务上,而是发生在任务分布上的想法。如果你对这种想法或元学习作为一个概念有点不确定,我推荐你阅读我之前关于元学习的文章,然后回到这篇文章,它更详细地研究了 MAML 和相关方法。]
MAML 的前提是:如果我们想要一个初始模型,它可以适应从一些任务分布中抽取的新任务,给定每个新任务上的少量数据点,我们应该将我们的模型构造成直接针对那个目标进行优化。具体而言,MAML 执行以下一系列步骤:
- 定义一些组初始参数 : θ
- 从任务分布中抽取一个任务t,对来自 t 的训练批次数据进行 k(一般为< 10)步梯度下降,初始化参数值为θ。在 k 步的末尾,你得到了参数ϕ.
- 从任务 t 在参数值ϕ评估你在测试批次上的损失,然后计算该损失相对于我们初始参数θ的导数。也就是说,计算我们如何修改我们的跨任务网络初始化,以在对新任务进行少量优化步骤后导致更好的损失。这种导数,通过学习过程本身传播回起始权重的值,与我们通常在梯度下降中采用的导数非常明显不同,我们很快会深入研究。
- 使用该梯度向量来更新我们的θ初始化参数,丢弃为该特定任务学习的ϕ,并使用新的采样任务再次开始该过程,用我们最*更新的θ值初始化我们的网络。
根据这种方法,一个合理的问题是:
这和训练一个*均来说对所有任务都有效的参数向量是一回事吗?
我将对这种方法使用的简写是联合训练,在这种方法中,我们只是从不同的任务中抽取交替的批次,并对每个批次进行正常的梯度下降。我不清楚 MAML 是否真的胜过联合训练的实证答案,但是从概念上来说,MAML 试图做的事情有微妙的不同,而且,以我的经验来看,解开这种差异的项目很有价值,不仅有助于更清楚地了解 MAML 本身,还有后来提出的对它的修改。
什么样的初始化是好的?
MAML 学习一个好的跨任务初始化的目标提出了一个显而易见的问题:不同的参数初始化有哪些不同的方式使变得好?它们可能会以哪些方式影响最终损失值?更简单地说,对于某些任务分配,是什么使一个初始化比另一个更好?

因为,有时候,最开始并不是参数开始的最佳位置
首先,让我们想象一下我们在一个新任务上根本不优化的情况。在这种情况下,我们的“最终”参数值ϕ和初始θ值没有区别。θ的变化意味着ϕ的等价变化,因为它们是相同的值。
当我们真正开始对任务采取优化步骤,并学习不同于θ的特定任务ϕ时,事情就变得更有趣了。
就像上面一样,你的元学习θ的好处只是它在任务中具有低损失,因此从那里采取的优化步骤获得了领先,因为从那个低损失值开始。一般来说,优化会使你的损失相对于你的起点更好,所以有一个较低的损失初始化提供了一个较低的最终损失的粗略上限,可以使你学到的最终ϕ更好。
然而,让我们想象另一种情况,出于某种原因,我们只能在初始化值θ之间进行选择,这些值在您绘制的新任务中具有相同的损失值。在这个世界上,我们不能通过降低初始参数的损失来降低优化后的损失,因为我们已经人为地移除了那个杠杆。在这种情况下,一个初始化比另一个初始化更好的其他方式有哪些?
为了形象化,让我们想象一个简单的例子,其中我们所有的等效损耗点都在理论最小值周围的 2D 圆内。想象一下,一个点位于一个高原上,当你向最小值的方向移动时,它停留在一个高损耗处,直到它在最后一刻下降。另一个点位于向下朝向最小值的缓坡顶部。即使这些点以相同的(相对较高的)损失开始,渐变山顶上的点显然更好,至少在使用梯度下降作为优化策略的情况下,因为梯度下降将很容易沿着从起点到最小损失点的倾斜路径进行。另一方面,高原上的点不会给梯度下降提供任何初始工作,因此寻找最小值会更加困难。
因此,这是两个粗略的概念,在这两个概念中,初始化可能是“好的”:
- 他们可以自己有低损失在期待跨任务
- 他们可以通过更好的方式进行定位,以促进任务中后续的损失减少步骤
这显然是一个粗略的概念分类,我当然不会说这完全抓住了参数和损失之间的关系,但我确实认为这是一个有用的二分法
在高层次上,MAML 的希望是,因为它计算的导数说明了初始值的变化如何通过梯度下降传播以影响最终值——简而言之,因为它通过 SGD 本身反向传播——它可以(理论上)找到根据标准(1)和标准(2)都是好的初始化。
联合训练没有每任务优化的内部循环,不能显式地考虑这种优化的效果,由于在没有进一步优化的情况下,每个采样任务的损失较低,联合训练只会倾向于找到好的初始化。
为什么我们会关心这种区别呢?一个原因是,很难找到一组参数可以很好地“*均”解决所有任务;它可能只需要在一个参数向量中捕获太多的信息。然而,考虑到在整个任务分布中学习到的任何参数都必须在分布中不同任务的性能之间进行权衡,如果我们能够找到能够在新任务中有效学习的参数,我们将有望从给定少量特定任务示例的固有均值回归中恢复过来。
在实践中,对于任何给定的算法或任务集,这两个标准实际上不是非此即彼的二分法,而是一种混合物——算法可能更多地依赖于一种方法或另一种方法来驱动其性能,并且可能在不同的任务中不同程度地依赖于每一种方法。我见过的大多数经验评估都没有很好地区分它们的性能提升是来自低损失初始化还是容易优化的初始化。公*地说,这种概念上的区别可能太混乱,很难映射到一个清晰的实验度量上;我当然没试过。
但是,在缺乏良好的实证测试的情况下,很难知道:也许从易于优化的初始化中可以获得巨大的收益,MAML 在寻找这种初始化方面具有理论优势,或者也许它们只是理论上的边缘情况,没有真正的实际价值,元学习通常只是通过找到*均良好的参数而成功。我认为我们还没有十分肯定地回答这个问题。但是记住 MAML 的理论价值命题很大程度上依赖于找到好的初始化的希望是有用的,因为低损失和每任务优化的容易。
打破链条
让我们仔细看看 MAML 用来优化的导数。用话说,MAML 的目标是:
我如何修改我的初始化参数(θ)以减少参数(ϕ)的损失,我在应用每任务梯度下降到θ的几个步骤后达到?
从数学上来说,看起来是这样的:

来源:具有隐式梯度的元学习(Rajeswaran 等人)。我们在这里列出的方程的最终量,是用我们在多个步骤后达到的参数计算的损失的导数,相对于你的初始θ
让我们更仔细地看看这两个组成部分。

Alg(θ)这里是对初始θ参数应用优化算法(本例中为 SGD 的 k 步)后得到的值。ϕ和 Alg(θ)是一个意思;后者只是强调了一个事实,即你的终点(ϕ)是你起点 (θ),的函数,而到达终点的算法是梯度下降。等式的这一部分与你执行另一步正常梯度下降是一样的:评估你在任务 i 中损失的梯度,无论你最终得到什么参数(在这种情况下,ϕ,也称为 Alg(θ))。所以,导数的这一部分简单明了。

这就是事情变得棘手的地方。通常情况下,计算梯度所依据的权重与将要更新的权重相同。但在这种情况下,我们在最终权重ϕ计算单任务损失梯度,但随后想要更新我们的初始权重θ。这些是任务之间的权重,是我们在每个新任务开始时开始优化的共享初始化。这些是我们最终想要在元学习循环中学习的权重,所以我们需要一个梯度。这意味着,我们不仅仅需要相对于ϕ的损失梯度,还需要更深一层,相对于θ。这就是为什么 MAML 算法可以优化一组参数,以支持有效的学习过程,,而不仅仅是性能更好的固定参数点。
这种二级衍生是MAML 不同于简单联合训练的最显著方式。
这个“更深一层”要求我们使用链式法则。为了在这里使用链式法则,我们需要将ϕ的损失梯度乘以ϕ的参数值相对于θ的梯度。换句话说,为了知道如何操纵θ来影响我们在ϕ的损失,我们需要:
- 知道改变ϕ的方向,以降低损失
- 知道改变θ的方向,以便在特定方向上移动优化后的值ϕ
直观地说,该导数的目标是捕捉多步梯度下降过程的动态,并对θ的变化进行优先排序,这将有效地通过该过程传播影响。在不知道(2)的情况下,如果你只是天真地对θ应用和对ϕ一样的变化,你可能最终不能有效地减少损失,因为从新θ开始的学习过程可能不会导致ϕ值朝着你想要的方向移动。
我们从初始化θ到ϕ的方法是通过对新采样任务的 k 个批次执行梯度下降。

捕捉基本梯度下降中参数更新过程的方程。最终的 phi 值取决于损耗相对于在沿着链的每个中间参数值处计算的参数的导数(由下标为 0-k 的θ表示)
为了确定θ的偏移如何传播到最终ϕ的变化,您需要捕捉在这个链中的每个点计算的梯度将如何响应计算它们的参数点的值的变化。如果我们改变θ,我们会得到不同的参数初始值(显然),但我们也会计算出不同于之前的梯度。这是二阶导数,测量θ的变化如何影响在该θ值下计算的矢量值损失梯度。计算完整的 MAML 导数需要计算在更新的 k 步骤中使用的 k 导数的的二阶导数。
这带来了一些问题。首先,二阶导数的计算和存储成本很高,因为默认情况下它们是 n 参数*方的矩阵。此外,它要求我们记录在 k 次更新中遇到的不同权重向量,因为我们需要在梯度计算步骤中使用它们来计算每个位置的二阶导数。这意味着,对于一个 N 参数模型——在现代模型中,N 可以非常大——一个 k 步元学习模型将需要访问 kN 内存,以存储内部循环中的那些中间参数矩阵。
这种与 MAML 的天真实现相关联的强烈的存储器需求给了研究人员有意义的激励,以搜索捕捉完全实现的梯度的一些元素的有效*似,但是具有较低的计算需求。这种冲动是 MAML 变体的动机,我们将在这篇文章的剩余部分进行探索。
一阶 MAML

事实证明很难有元算法的好图片,所以,这里是科学家认为所有当前哺乳动物的第一个祖先看起来像什么的渲染图,一个一阶哺乳动物,如果你愿意的话...
这里要解决的问题是:如何计算导数来告诉你对初始值的改变如何影响最终损失值?你是如何做到这一点的呢?
解决问题最简单的方法是…让我们试着忽略这个问题,看看这会给我们带来多大的损失。务实的本能,即使不是最令人满意的。这是一阶 MAML(或 FOMAML)采取的策略。
在数学上,不是实际估计上述参数间导数矩阵(参数向量ϕ相对于初始参数向量θ的导数,这需要缓存中间 SGD 步骤),而是 FOMAML 假设导数只是一个单位矩阵。换句话说,这意味着对初始参数的单位变化对应于梯度下降后参数值的单位变化的假设进行编码。
从概念上讲,如果这个假设成立,这将意味着初始化值的差异不会导致不同的优化路径,它们只会导致固定优化路径的移动(因为,如果您将路径想象为不变的和刚性的,当您移动起点时,终点也会移动相同的量)。
通过假设相对于ϕ的梯度是一个单位矩阵,你失去了捕捉初始化可能改变你的优化路径的方式的能力,而不仅仅是移动它,但是,从积极的一面来看,链式法则中难以计算的部分消失了,我们相对于θ的更新就变成了我们在ϕ.得到的损失梯度

θ按绿色箭头的方向更新,这是在ϕ计算的测试集损耗的梯度
FOMAML 获得更好损失值的策略是根据在ϕ对测试集计算的损失梯度来更新θ。有趣的是,考虑到这与简单地执行联合训练(最基本的多任务方法,混合来自不同任务的批量数据,并对每个数据采取一个正常的一阶梯度步骤)既不同又相似。
最大的相似之处在于,用于更新θ的步骤本质上与您在普通梯度下降中使用的步骤完全相同:在单个点计算的单个一阶梯度。
第一个区别是,在 FOMAML 中,我们使用一个单独的每任务测试集来计算梯度,这在 k 步训练中没有使用。然而,我并不认为这是一个有意义的区别:在只有小 k 步训练的情况下,从训练集中采样的新批次重复这 k 步训练中看到的示例的可能性非常低,这将使从相同基础分布中采样的训练集和测试集在数据点对模型的新颖性方面基本相等。
第二个区别是,我们采取梯度下降的几个步骤,然后在这些步骤之后根据梯度来更新我们的参数,而不是根据梯度来更新我们的参数向量。这是一个差异,但至少对我来说,我们应该预期的含义是什么还不清楚:在优化链中的几个步骤之后计算的梯度似乎并不比之前计算的梯度本质上更有信息量。**
冷血的单纯
全 MAML 和一阶 MAML 展示了光谱的两端:一端是概念上合理的方法,具有强烈的内存和计算要求,另一端是简化,降低计算负担,但代价是一组非常有限的假设。
在这种背景下,OpenAI 的爬虫方法出现了,作为这两种对立选择的中间点:一种启发式方法,它添加了比单个梯度步骤捕获的更多的信息,但以一种回避 MAML 的明确形式主义的方式这样做。(题外话:不,作者没有解释为什么这种方法被称为爬行动物,除了它为现有的 MAML 方法提供了一种替代方案的明显背景之外)。

“真的吗?以我命名的机器学习模型?”
正如机器学习中的许多事情一样,我发现爬行动物最容易首先作为算法来解释,然后再用数学形式主义的语言来解释。
就像在 MAML 一样,这个问题被构造为对任务分布的少量学习:每次任务被采样,我们对来自该任务的批数据执行 k 步梯度下降,其中 k 变化,但通常小于 10。
对于每个任务,爬虫取ϕ,即在任务上 k 步后达到的参数,并计算对初始参数θ的更新,作为在这 k 次更新中参数空间的总移动,或(ϕ-θ)。这相当于采取多个梯度下降步骤,在步骤 0 开始的位置和步骤 k 结束的位置之间画一条线,然后使用该向量作为θ的更新方向。有趣的是,如果 k=1,这和联合训练是一样的:由于单个梯度步长的起点和终点之间的线和步长本身是一样的,而θ只会被拉向任务在该点的损失的一阶导数的方向。

θ根据绿色箭头更新:指向 k 步优化解决方案的向量
当我们采取多步梯度下降时,事情变得更加有趣。现在,我们获得了关于损失面的更多信息,因为我们汇总了在多个不同点做出的损失估计。这为我们提供了类似于通过计算显式二阶导数获得的信息——如果多个梯度都通过向同一方向前进而相互加强,这意味着梯度值在该点没有太大变化,我们的聚合向量将更强烈地指向该方向。
这里要注意的是,这个公式打破了干净的 MAML 链规则推导:我们不直接计算最终的测试集损失导数,并乘以一个参数到参数,就像我们以前做的那样。这纯粹是一种启发性的说法,即“向从几个步骤的任务训练中产生的全局参数移动”。但是,在直观的层面上,因为我们在多个步骤上聚合梯度,所以当初始化在“易于优化”的位置时,我们给予单任务损失梯度更大的权重,因为这些位置更有可能在一行中有多个梯度都指向相同的方向,这将加在一起。如果初始化是在一个给定的任务中,由于多个步骤中的噪声、冲突梯度而难以优化的地方,则单个步骤的梯度将会抵消。如果你眯着眼睛,你可以看到这在概念上相当于根据一个项来更新θ,该项通过θ对ϕ的影响量来缩放ϕ的损耗,因为如果θ位于更嘈杂的梯度处,对θ所做的任何改变都可能导致优化路径找到有意义的不同ϕ值,其中你上次计算的梯度可能不再适用。
所有这一切都表明:这绝对是一种启发,你应该把我的这个框架作为一种可能的解释,而不需要任何具体的实证检验。
作者还认为,这种方法具有找到θ初始化的效果,即在参数空间中期望接*每个任务的最佳参数。他们在这里的主张是基于将 k 个步骤后达到的参数视为最佳参数的良好*似。这让我觉得不是很有说服力:在梯度下降的一个步骤和带你找到一个任务的最优解的整个优化过程之间,有一个非常有意义的质的区别。即使爬行动物采取 k 个步骤,该 k 通常相当小,因此看起来每个任务上达成的解决方案在质量上更类似于单步更新的结果,而不是最佳参数配置。
隐式 MAML
正如我几次提到的,完全计算最终参数ϕ相对于初始参数θ的导数是一件痛苦的事情。为了能够通过多步计算过程传播导数,您需要存储 k 步中每一步的中间参数。当我们谈论百万参数神经网络时,必须为每个元更新步骤在内存中存储整个网络的多个副本是一个有意义的障碍,特别是当 k 步内部优化循环中的 k 上升时。
其中,FOMAML 假设一个世界中的导数是微不足道的,而爬行动物构建了一个启发式算法,该算法无需直接计算梯度信息的各个方面,隐式 MAML 或 iMAML 构建了一个*似导数,该*似导数在分析上比爬行动物的更有根据,但比 FOMAML 的梯度只是恒等式的假设允许更大程度的表达。
iMAML 将问题框定为:
最优单任务参数ϕ*相对于θ的导数是多少?
如果你使用这种新的框架,一些量在分析上变得更简单,更容易处理。但是,乍一看,这似乎是一个注定要失败的努力:你的损失空间中的最小损失点就是它所在的位置,而不管你在哪里初始化你的参数。那么,你的θ初始化参数怎么可能影响最小损失点的位置,使得计算该点相对于它们的导数成为可能呢?
隐式 MAML 的作者引入了一个修正来解决这个问题:一个正则化,根据解与初始值的距离来惩罚解。当您在单个任务的更新中远离初始值时,距离的*方损失最终会超过较低损失的好处,并且您会达到最小损失的*衡点。因此,在这个修改的目标下,不同的初始点将在不同的地方定位该*方距离损失的中心,并且因此导致混合损失的不同最小损失点,该混合损失包括真实的潜在损失和距离损失。这在初始参数值和空间的最小损耗点(在混合损耗下)之间建立了关系,使得讨论最小损耗参数相对于θ的导数变得有意义。
起初,这个修改的目标看起来像是一个纯粹任意的改变,以使导数被很好地定义(在某种程度上这是真的),但当我们记住元学习试图解决在每个新任务的几步学习设置中表现良好的初始化时,这似乎更合理。所以,如果你的问题的定义意味着你在一个新的任务上只是采取了一些学习步骤,那意味着你将永远没有机会远离你的初始化。在这种情况下,优先考虑附*解决方案的修改目标似乎更像是一个合理的*似,而不是纯粹出于数学上的权宜之计。

由θ和当前参数值之间的*方范数正则化的正常损耗
足够方便的是,该目标的最优参数相对于θ的梯度具有封闭形式的解析解,并且该封闭形式的解可以使用共轭梯度有效地计算,而不需要存储计算全导数所需的中间优化参数值的链。我不打算深入共轭梯度如何工作的细节,以及为什么它会更有效,因为那将是它自己的独立博客帖子,但我强烈推荐这本写得很好,容易理解的教程,如果有人想了解更多。

Alg*的导数——对应于正则化目标的最优值的参数——相对于初始参数。这就是我们用作参数对参数的导数,乘以ϕ的损失得到我们的 MAML 式更新
因此,如果我们假设在 k 个步骤之后我们得到的参数足够接*于我们的正则化目标下的最优,那么最优参数值相对于θ的导数将是我们实际得到的参数的导数的非常好的*似。有了这个*似的分量,我们就可以把它和易于计算的ϕ损耗梯度结合起来,并把它们插入到更新规则中。
的确,除非我们的正则项如此强大,以至于我们在几步之后淹没了实际损失的影响,否则我们很可能不会实际到达最小损失点:k 通常很小,因此ϕ只是在最小值(有希望的)方向上梯度下降几步的结果。但是假设总是要求有一点点错误,以使你的计算更好,这一点在实践中似乎很有可能成立。
将这种方法与 MAML 和一阶 MAML 放在一起是有用的。在原始的 MAML 中,ϕ相对于θ的梯度就是字面上的量,完全和适当地计算,痛苦的内存需求和所有。在一阶 MAML 中,我们假设初始参数的变化导致最终值的不断变化,并且基本上放弃了捕捉 k 步学习过程的动态如何可能取决于您的起点。在隐式 MAML 中,我们允许θ的实际值影响参数间梯度,但仅通过考虑由θ引起的(正则化的)理论最优值,而不是我们从θ到ϕ所采用的经验 SGD 路径。因此,这介于两者之间:一个简化的假设,但仍能捕捉我们初始参数周围的损失情况的特征。
所有的简化都有其简单的方式
下图试图将这些不同的方法结合在一起,并直观地展示它们之间的区别。单个小箭头表示特定任务中特定批次的损耗梯度。绿色表示使用哪个梯度或梯度组合来更新初始参数θ。

联合训练使用在初始化时计算的损失来更新,因为联合训练只使用每个任务的单个批次。MAML 的各种变体都以虚线箭头梯度开始,这是在 k 个更新步骤后达到的参数ϕ处计算的损耗。一阶 MAML 直接使用该损失作为初始化的更新向量。MAML 取该向量,并将其乘以ϕ相对于θ的(矩阵)梯度。iMAML 将其乘以修改的目标最优参数相对于θ的梯度。爬虫将所有单个 k 更新相加,然后缩小该向量,并使用它来更新θ。
在联合训练中,在更新参数之前,每个任务只运行一个批次,因此它们本质上只使用来自第一个(也是唯一的)批次的梯度进行更新。在 MAML 的变体中,我们采取多个更新步骤,并且在乘以最终参数相对于初始参数的梯度的某个版本之后,来自这些批次中的最后一个批次的梯度被用于更新θ。
结论
除了脆弱性之外,对现代机器学习的另一个广泛批评是它倾向于给自己讲一般的故事:为其方法为什么应该有效提出理论上的理由,观察实证性能增益,并假设后者验证了前者的理论主张。
本着这种精神,用一些基础的经验问题来*衡这篇主要是概念性和理论性的文章似乎是有用的,有助于思考哪些概念性的主张得到了最多的支持。
利用二阶信息的算法真的比类似 FOMAML 的联合训练算法更好吗?
据我所知,是的,但这种差异在 k 值较小时更明显,有点矛盾地表明,大部分值在θ中,在任务中的损失较低,使用多步信息更有利于获得低损失。当 k 较大时,您可能能够更有效地“弥补”在优化方面的不足。在较大的 k 值下,MAML、伊玛目和爬行动物在测试任务中仍然表现出色,但没有那么显著。
更有原则的 iMAML 是否胜过更具启发性的爬行动物?
我……不确定。这方面的实证结果很少,而且似乎没有定论。看看 iMAML 论文中报道的那些,iMAML 在 Omniglot 上的表现比爬虫好(在 Omniglot 上,每个任务对来自不同字母表的字母进行分类),但是在 mini ImageNet 上在它的误差范围内
这里的部分问题是——因为原始 MAML 本身的计算非常昂贵——我们主要是在现有模型已经表现很好的简单任务上进行测试,并关注 97 %- 99%之间的准确性差异。我希望看到更多在没有元方法的情况下确实难以学习的评估任务,但显然这将带来很高的计算成本。
元学习有一个崇高的理想——学会如何学习,如何适应一项看不见的任务。而且它确实比更简单的联合训练方式要好。但重要的是,不要过于陷入元学习为自己创造的大框架中,而是要试图识别更简单和更复杂方法之间的实际机械区别,并严格评估我们对它们所增加的价值的推理是否符合现实。
我还有一些未解决的问题:
- 是否存在一个 k 值,使得福马尔和 MAML 收敛到等价的性能?测试的 k 值 1 和 5 比你实际使用的要低得多,即使对于非常数据有效的微调也是如此,而且不清楚元优化方法是否仍然能在那些更现实的领域中提供价值
- 相对于仅仅找到一个一般的好的起点,元学习在多大程度上实际上优化了更有效和高效的几步更新?我希望看到更多的度量标准(或指出现有的)通过实际描述更新路径来分割这种差异,并实际定性地检查 MAML 与联合训练方法所学到的东西。
基于半监督嵌入的模糊聚类
维基百科名人页面的自动标记

聚类 是将群体或数据点分成若干组,使得同一组中的数据点更加相似的任务。而另一方面, 模糊聚类 是一种聚类形式,其中每个数据点可以属于多个聚类。 半监督学习 是一类机器学习,我们通过显示少量已标记数据,让机器学习或决定大量未标记数据。
既然我们已经完成了所有术语的定义,让我们来讨论一些现实生活中的场景,并进入这篇博客的主题。
通常情况下,我们对自己想要的集群有一个想法。例如,如果我们对城市进行分组,我们希望看到更多的城市被分组在一起,而不是城市郊区或城镇。类似地,如果我们对人进行聚类,我们希望看到来自相似背景/领域/爱好的人被分组在一起。
这篇博客的主要思想是通过向我们的算法展示一些我们希望我们的聚类是什么样子的例子,来定义一种创建模糊聚类的新方法。在这个博客中,我们将把维基百科名人分为 5 个组/群。更多细节,这个名人数据集是如何创建的可以在这里找到。但是,这并不重要,因为我已经提供了数据的子集和所需的代码,供您尝试和使用这个概念。最重要的是,这种技术非常通用,它可以很容易地应用于许多用例,比如 plug & play。
问题陈述
我们有一个维基百科名人数据集(包含所有过去或现在有维基页面的名人)。我们想自动将这些人分成 5 组。
- 艺术家 :所有演员、音乐家、电影制作人、艺术创作人、画家等
- 运动员:任何运动项目的运动员
- 科学家/研究人员 :任何背景的科学家,如物理学家、化学家、生物学家、历史学家、计算机科学家等
- 领导人/政治家:任何国家或地区的领导人/政治家
- 其他影响者 :哲学家、教师、医生、企业家、技术人员等
值得注意的一点是,有些人可能属于多个类别,正如我们所知,许多运动员后来进入政界或在职业生涯中表演等。因此,我们想要实现的是模糊分组/聚类,而不是硬聚类。
对数据的研究
在设计策略或算法之前,我们先看一次数据。

数据集快照
数据集由两列组成,标题和内容。标题是这个维基百科页面的人的名字,内容是关于他们童年、职业、成就等的页面内容(大文本)。
维基百科大约有 598 万页面,其中有 105 万页面是关于人的。所以,我们的数据集由 105 万个名人的维基百科页面组成。
可能有许多现在或过去的运动员、艺术家、领导人等等,人们可能不知道。这种算法的美妙之处在于,它能以适当的概率自动为它们找到正确的聚类。
设计战略
步骤 1:创建一个小标签数据
第一步将是利用半监督学习的好处,或者简单地说,利用我们拥有的少量信息。 我们会列出每个组的一些知名人士,并获取他们的维基百科页面。这个列表可能是你的选择,可能因人而异。让我们看看我列出的不同类别的人。
艺人 :莱昂纳多·迪卡普里奥,阿米特巴·巴强,盖尔·加朵,艾德·希兰
运动员 :安德烈·阿加西、玛丽亚·莎拉波娃、萨钦·滕杜尔卡尔、莱昂内尔·梅西
科学家/研究人员 :阿尔伯特·爱因斯坦、艾萨克·牛顿、德米特里·门捷列夫、查尔斯·达尔文
领导人/政治家 :巴拉克·奥巴马、纳伦德拉·莫迪、弗拉基米尔·普京
:史蒂夫·乔布斯、拉里·佩奇、比尔·盖茨、艾伦·格林斯潘、萨尔·汗、杰弗里·辛顿

艺人

运动员

科学家/研究人员

领导人/政治家

其他影响者
这个列表就像我们创建的 21 个人的小标签数据。训练集看起来像

21 人的培训组
步骤 2:为有限的标记数据生成嵌入
我们现在有 21 个维基百科页面的语料库。我们可以把每一页称为语料库的一个文档。我们将生成每个文档的嵌入。一个 嵌入 是一个相对低维的空间,你可以将高维向量*移到其中。嵌入使得在大量输入上进行机器学习变得更加容易,比如表示单词的稀疏向量。它可以是任何长度。在这项工作中,我使用了 100 维嵌入。不同长度绝对可以玩。我使用 NMF (非负矩阵分解)来生成这些嵌入。
非负矩阵分解
非负矩阵因式分解 (NMF 或 NNMF)是一种算法,其中矩阵 V 被因式分解成(通常)两个矩阵 W 和 H,其性质是所有三个矩阵都没有负元素。
矩阵 V 被分解成两个矩阵 W 和 H 的乘积
V = W.H

矩阵 V 分解成 W & H 矩阵
在上面的例子中,矩阵 V 的维数是 4 * 6。我们可以把它看作一个有 4 个文档和 6 个单词的语料库。单元格 Aᵢⱼ的每个条目是单词 Wⱼ在文档 Dᵢ.中出现的次数我们将文档的特征维度从 6 降低到 2。因此,矩阵 W 的维数为 4 * 2,矩阵 H 的维数为 2 6。*
从另一个角度来看,在新的映射中,每个文档由两个潜在特征表示,即矩阵 w。矩阵中某个单元的值越高,该文档与潜在特征的关联程度越高。矩阵 H 定义了每个单词属于这些潜在特征的程度。

直观矩阵分解
我们可以用矩阵 W 作为嵌入或降维矩阵。降维使得对大量输入进行机器学习变得更加容易,比如表示单词的稀疏向量。在 python 中,我们可以简单地使用 sklearn 提供的 NMF 包。
使用 NMF 创建 V 矩阵并将其分解为 W 和 H
结果,我们把 Vᵀᴿᴬᴵᴺ分解成了 Wᵀᴿᴬᴵᴺ和 Hᵀᴿᴬᴵᴺ

Wᵀᴿᴬᴵᴺ矩阵
步骤 3:创建组嵌入
我们有 5 个群体:艺术家、运动员、科学家、政治家和领导人。我们从每个组中挑选了一些人,并创建了 21 个包含训练集的记录。我们将使用在 Wᵀᴿᴬᴵᴺ为每个组学习的嵌入的*均值,并将其称为组/簇嵌入。
例如,艺术家嵌入将作为:
Artistsᵉᵐᵇᵉᵈᵈᶦⁿᵍ =*均水*(莱昂纳多·dicaprioᵉᵐᵇᵉᵈᵈᶦⁿᵍ,阿米塔布·bachchanᵉᵐᵇᵉᵈᵈᶦⁿᵍ,加尔·gadotᵉᵐᵇᵉᵈᵈᶦⁿᵍ,埃德·sheeranᵉᵐᵇᵉᵈᵈᶦⁿᵍ)
生成集群嵌入的代码
步骤 4:为整个语料库生成嵌入
测试集包含除了 21 个名人页面之外的所有剩余的 105 万个名人页面,我们已经将其作为标记的训练数据。现在,对于每个文档,我们需要生成一个嵌入,并且潜在特征需要与训练集的潜在特征相同。也就是说,我们需要产生 Vᵀᴱˢᵀ、Wᵀᴱˢᵀ和 Hᵀᴱˢᵀ.
让我们一个一个地看每个矩阵
- Vᵀᴱˢᵀ :通过计算单词‘w’在文档中出现的次数,我们可以很容易地生成 Vᵀᴱˢᵀ。只是我们需要小心,我们只采用我们在训练数据中看到的单词,并以相同的顺序忽略新单词。
- Hᵀᴱˢᵀ :矩阵 Hᵀᴱˢᵀ代表每个单词属于潜在特征的多少。因此它和 Hᵀᴿᴬᴵᴺ.是一样的即 Hᵀᴱˢᵀ = Hᵀᴿᴬᴵᴺ
- Wᵀᴱˢᵀ: 这是主要的也是唯一剩下的让我们去寻找的母体。我们将使用矩阵代数来找到它。让我们看看如何-

计算 Wᵀᴱˢᵀ的矩阵代数
在代码中,我们不需要接受 inverse 和 all,因为包为我们做了这些,没有隐式地指定它。
计算 Wᵀᴱˢᵀ的代码
步骤 5:分配聚类概率
最后一步是分配每个维基百科名人聚类分数,并将其转换为概率。为此,我们使用聚类嵌入对页面嵌入进行余弦相似度计算,然后归一化得分以获得概率。
例如,如果我们必须给演员汤姆·汉克斯分配聚类分数,过程将是:
分数计算
艺术家=余弦 _sim(汤姆·汉克斯 ᵉᵐᵇᵉᵈᵈᶦⁿᵍ , Artistsᵉᵐᵇᵉᵈᵈᶦⁿᵍ) = 0.68
SportsPerson = cosine_sim(汤姆·汉克斯 ᵉᵐᵇᵉᵈᵈᶦⁿᵍ ,sportspersonsᵉᵐᵇᵉᵈᵈᶦⁿᵍ)= 0.04
科学家=余弦 _sim(汤姆·汉克斯 ᵉᵐᵇᵉᵈᵈᶦⁿᵍ ,scientistsᵉᵐᵇᵉᵈᵈᶦⁿᵍ)= 0.1
政客=余弦 _sim(汤姆·汉克斯 ᵉᵐᵇᵉᵈᵈᶦⁿᵍ ,politiciansᵉᵐᵇᵉᵈᵈᶦⁿᵍ)= 0.01
影响者=余弦 _sim(汤姆·汉克斯 ᵉᵐᵇᵉᵈᵈᶦⁿᵍ ,influencersᵉᵐᵇᵉᵈᵈᶦⁿᵍ)= 0.1
余弦相似度是一个总是在 0 到 1 之间的数字。0 表示没有相似性,1 表示完全相似
分数对概率的标准化
艺人概率= 0.68/(0.68+0.04+0.1+0.01+0.1)~ 0.72
运动员概率= 0.04/(0.68+0.04+0.1+0.01+0.1)~ 0.05
科学家概率= 0.1/(0.68+0.04+0.1+0.01+0.1)~ 0.11
政治家概率= 0.01/(0.68+0.04+0.1+0.01+0.1)~0.01
影响者概率= 0.1/(0.68+0.04+0.1+0.01+0.1)~ 0.11
概率加起来是 1。汤姆·汉克斯是一名艺术家,有 72%的机会被分配到艺术家群体。我们对所有的名人维基页面都这样做,并得到聚类概率。
用于分配聚类概率的代码
看看一些名人的这些概率。概率被转换成下面的百分比。

一些名人的百分比聚类概率。
结束注释
我们设计了一种非常新颖和有效的基于半监督嵌入的模糊聚类技术。这对于许多用例来说是相当普遍的。我们使用先验知识给集群一个形状和一个启动。
可以通过以下方式进一步改善结果:
- 使用提供的初始标记数据。我们可以提供更多高质量的数据来改善最终结果。
- 播放或交叉验证正确的嵌入长度。
- 设计一个更具创新性的策略来发现集群嵌入,而不仅仅是简单的*均。
如果任务是分别标记每个运动项目的运动员,那么你的种子数据和算法会有什么变化?请评论你的想法。所有的代码和一小部分维基百科名人数据集可以在这里找到。
我的 Youtube 频道更多内容:
嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…
www.youtube.com](https://www.youtube.com/channel/UCg0PxC9ThQrbD9nM_FU1vWA)
关于作者-:
Abhishek Mungoli 是一位经验丰富的数据科学家,拥有 ML 领域的经验和计算机科学背景,跨越多个领域并具有解决问题的思维方式。擅长各种机器学习和零售业特有的优化问题。热衷于大规模实现机器学习模型,并通过博客、讲座、聚会和论文等方式分享知识。
我的动机总是把最困难的事情简化成最简单的版本。我喜欢解决问题、数据科学、产品开发和扩展解决方案。我喜欢在闲暇时间探索新的地方和健身。在 中 、Linkedin或insta gram关注我,查看我以前的帖子。我欢迎反馈和建设性的批评。我的一些博客-********
- 以简单&直观的方式分解时间序列
- GPU 计算如何在工作中拯救了我?
- 信息论& KL 散度第一部分和第二部分
- 使用 Apache Spark 处理维基百科,创建热点数据集
- 每个数据科学家都应该避免的五个错误
- 比较哪种机器学习模型表现更好**
一个闪亮的手动推断统计程序
关于如何构建置信区间和手动对 3 个主要参数进行假设检验的指南

推断统计学的闪亮应用:假设检验和置信区间
统计学分为四个主要分支:
- 描述统计学
- 推论统计
- 预测分析
- 探索性分析
描述性统计提供了数据的概要;它有助于以简洁的方式解释数据,而不会丢失太多信息。数据可以用数字或图形来概括。参见手工描述性统计或 R 中的以了解更多关于这一统计分支的信息。
预测分析的分支旨在根据一个或几个自变量预测一个因变量。根据要预测的数据类型,它通常包括回归或分类等方法。
探索性分析侧重于使用图形方法来深入研究数据,并确定数据集中不同变量之间存在的关系。因此,它们更类似于数据可视化。
推断统计学使用从总体中随机抽取的数据样本进行推断,即得出关于总体的结论(参见总体和样本的差异)。换句话说,来自样本的信息用于对总体中感兴趣的参数进行归纳。推断统计学中的两个主要工具是置信区间和假设检验。这里有一个闪亮的应用程序,可以帮助你使用这两个工具:
这个闪亮的应用程序专注于置信区间和假设检验:
- 1 和 2 表示(非配对和配对样本)
- 1 和 2 的比例
- 1 和 2 差异
以下是完整的代码,如果你想加强它(见一个例子,如何使用这个应用程序后,嵌入式代码):
请注意,如果应用程序已达到每月使用限额,链接可能会失效。如果是这种情况,请稍后再试。
这个 app 怎么用?
请遵循以下步骤:
- 通过此链接打开应用程序
- 选择您想要进行推断的参数(即*均值、比例或方差)
- 在样本中写入您的数据。观察值由逗号分隔,小数是一个点
- 设置零假设和替代假设
- 选择显著性水*(大多数情况下α=0.05)
在结果面板中(根据屏幕大小位于右侧或下方),您将看到:
- 用一些适当的描述性统计数据概括一下你的样本
- 置信区间
- 假设检验
- 解读
- 以及假设检验的说明
还提供了达到最终结果的所有公式、步骤和计算。
我希望你会发现这个应用程序有助于进行推断统计,尤其是手动置信区间和假设检验。
和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。
相关文章:
原载于 2020 年 1 月 15 日 https://statsandr.com。
从 Google BigQuery 分析公共数据的简短指南

图片来源:凯文·Ku 摄于 Pexels
这里有一个如何使用 Google BigQuery 分析大数据集的指南。
互联网上有大量的数据集需要分析,但却没有足够的磁盘空间来存储它们。如果您像我一样是数据科学的新手,那么您很有可能遇到过这个错误“您已经用完了磁盘空间”,而您的代码运行在一个 10 GB 的 CSV 文件上,该文件被压缩在您的磁盘上的某个地方,并因缺少足够的空间而喘不过气来。
欢迎来到云的世界。这对我简直是一个启示。我用谷歌大查询开始了这个伟大的旅程。它肯定不是唯一的,当然也不是最便宜的。但是,谷歌允许你至少在一年内免费使用它的服务,直到一个固定的期限。
这篇文章假设读者对 SQL 有基本的了解,因为它是与数据库通信的最有效的方式。如果你想学习 SQL 或 SQLite,考虑参加 Datacamp 或 Coursera 的在线课程,一旦你对它有点熟悉了,练习是关键。
在接下来的段落中,我们将一步一步地介绍使用 Google BigQuery 的过程,并在此过程中制作出一份精美的分析报告。请注意,BigQuery 的范围相当广泛,但我将从它最基本的用途开始,即访问公共数据集并在 R 上查询它(无需下载到我的磁盘上)。
什么是 BigQuery?正是谷歌的“企业数据仓库让你能够利用谷歌基础设施的处理能力运行超快的 SQL 查询。因此,当您运行大数据分析时,您的磁盘可以呼吸。
要开始使用 BigQuery,您可以上传自己的数据集,或者访问他们的一个公开可访问的数据集。这个库不是很大,但是足够好让你开始练习你的动作。
第一步。首先在谷歌云上登录或创建一个账户。当你登录时,你会看到一个显示你使用谷歌云服务的仪表盘。在左侧面板中,浏览主页–>大数据–>大查询。
第二步。进入 BigQuery 页面后,创建一个新项目并将数据集存储在该项目中,这样就可以跟踪所有的查询和数据集。好处是 BigQuery 存储了您过去对一个项目的所有查询,因此您可以在将来的任何时候重新运行它们。节省了大量时间。有 20 个免费项目的报价。所以,放轻松。
要创建一个新项目,请在上面的蓝色面板中,Google Cloud Platform 旁边,单击 new project。给它一个名字,BigQuery 会自动给它分配一个项目 ID。我们以后需要这个身份证。项目创建后,您将在上面的蓝色面板中看到它。我的项目名为“选举数据”。

我的谷歌大查询项目的快照
第三步。我们现在可以开始探索数据集库了。在左侧面板中,单击添加数据–>浏览公共数据集。数据集根据它们所属的广泛主题进行分类。你挑吧。或者,有一个选项也可以添加位于“Resources ”-> big query-public-data 下面的左侧面板中的数据集。滚动浏览数据集,并单击您想要分析的数据集。我选择了“谷歌政治广告”进行分析。

我的谷歌大查询项目的快照
第四步。你已经完成一半了。我们现在将从探索主面板上的数据集开始。顾名思义,Schema 对列定义进行布局。详细信息部分显示选定数据集下相关表中的大小、类型和公共列。我的数据集是六个表的集合,可以在查询时轻松地处理它们。最后一部分“预览”给出了所选表格前几行的简要预览。

我的谷歌大查询项目的快照
第五步:从这里开始,我们可以选择两种方式进行。首先,在 BigQuery 控制台中运行查询并保存结果。其次,将这个 BigQuery 设置与您选择的 IDE 链接起来,就像您在 Python、R 或任何其他选择的语言中处理 SQL 一样。我选择了 R-studio。
步骤 6:要在 R-studio 中处理 BigQuery 数据集,将项目 ID 存储在一个变量中,然后按如下方式进行。这里,get_table 中的一个项目是一个大文件夹,所有公共数据集都存储在这个文件夹中。“数据集”是您选择用于分析的数据集的名称,“表”是主数据集中选择的表。运行此区块以访问数据集。

我的 R Studio 项目的快照
第 7 步:这是第一个查询。FROM here 显示了从所选的查询数据集访问的最终表的名称,在这里它用“.”链接到主数据集。这里是您的项目 ID,useLegacySQL = TRUE 允许我们使用遗留 SQL 命令进行查询。
该查询计算表中的行数,即 56,987。

我的 R Studio 项目的快照

我的 R Studio 项目的快照
BigQuery 对一个人可以查询和访问的数据量施加了每日限制。不过,在疯狂使用查询之前熟悉一下自己是个好主意。
该查询显示了表中的所有列和十行。

我的 R Studio 项目的快照
所以,就这样了。我希望它很容易理解和使用。让我知道您在探索 BigQuery 时想到了什么,或者您对其他类似*台的体验如何。我还在下决心。🙂
数据可视化简史
简要介绍一些将数字转化为美丽图片的主要创新和创新者
借助现代技术,可视化数据变得前所未有的简单。只需点击几下鼠标,就可以或多或少地将一个巨大的原始数字表变成一个视觉上吸引人且易于理解的图表。图表数据为理解和表达你的观点提供了一条高速捷径。
今天的许多可视化技术是在工业革命期间发明的,该领域在 19 世纪中期取得了长足的进步。对于 200 年前的人来说,今天看起来简单明了的东西,比如条形图或折线图,可能会很陌生。在本文中,我们来看看数据图形化表示方面的一些主要创新者以及他们的一些著名作品。
地图制作者

托勒密的世界地图——来源:维基百科
可以说,第一次数据可视化是在制图学领域。地图最初用于导航、土地所有权和一般人类好奇心的目的,已经以某种形式存在了至少一万年。在古代,从目击者的叙述(和相当数量的猜测)中整理出来的关于世界的信息会被刻在石头或泥土上。几个世纪以来,指南针(公元前 200 年)和六分仪(1731 年)等仪器允许更精确的测量和越来越精确的地图,印刷机使它们能够大规模生产。
1569 年,佛兰德制图家杰拉杜斯·麦卡托的《世界地图》标志着我们如何在一张*面纸上描绘球形地球表面的重大发展。
在他的墨卡托投影中,当地的地理被保留下来,当看着罗盘时,地图上的直线被转换成恒定方位的线,这使得它成为海上导航的理想选择。事实证明,它很受欢迎,原始版本被印刷了数百份,并且仍然是我们今天看到的最常见的世界地图投影。
威廉·普莱费尔
威廉·普莱费尔的简历相当不拘一格。在一个曲折的职业生涯中,这在今天是不可想象的,他涉足间谍活动、工程(就像因蒸汽机而出名的詹姆斯·瓦特的私人助理)、制图、会计、发明、金属加工、投资经纪、经济学、翻译、宣传、土地投机、银行、勒索和新闻。在法国大革命期间,他为英国政府充当间谍,经营伪造货币的业务以瓦解法国货币,并参与攻占巴士底狱。他是一个有点无赖和无赖的人,在几次失败的生意后,他也进了债务人监狱。然而,他的永久遗产是在统计学领域,他设计的图表形成了今天数据可视化的核心。
在 Playfair 的时代,数据通常显示在枯燥的表格中,很少考虑对它们的解释。如果你想理解某件事,没有直观的捷径,只有在数字中来回钻研、记忆、复制和比较数字的艰苦工作。

来源:维基百科
然后,在 1765 年,上面这张来自约瑟夫·普利斯特列的时间表出现了,显示了不同的古典政治家和哲学家的重叠的一生。Priestley 并不只是列出姓名、出生年份和死亡年份,而是将它们标在时间线上,这样就能立即看出哪些历史人物是同时代的。这些时间线被证明是成功的,并直接激发了 Playfair 发明条形图,首次出现在他的商业和政治地图集。

威廉·普莱费尔——商业和政治图集——来源
这张图表显示了苏格兰与欧洲和新大陆各地区的贸易差额。通过这种方式呈现数据,很容易发现苏格兰与爱尔兰的紧密经济联系及其与俄罗斯的贸易不*衡。
对英国来说,他有更多的可用数据,并能够制作时间序列图表,显示贸易*衡如何随着时间的推移而变化。这些图表被巧妙地、煞费苦心地刻在金属印刷板上,在用纸压之前,先把墨水涂在凹槽里,然后复制出来。有人认为,在早期的复制中,Playfair 可能亲自给图表上色。这些天我们过得很轻松!

威廉·普莱费尔——商业和政治图集——来源
15 年后,他又开始了这项工作,这次用的是有时会引起争议的饼状图和各种创造性的组合。令人惊讶的是,两百多年后,一个人的想法仍然在最先进的数据可视化软件中占据了图表选项的大部分。

威廉·普莱费尔——土耳其帝国在亚洲、非洲和欧洲的比例——来源
查尔斯·约瑟夫·密纳德
几十年后,出现了一位法国土木工程师,他在结合统计学和制图学领域方面做出了重大创新。
1845 年,他绘制了第戎(以芥末闻名)和法国东部米卢斯周围地区的“流动地图”,展示了从穿过该地区的道路上收集的交通数据。在穿越该地区的新铁路线铺设之前,这份文件被分发给数十名利益相关者。也许是这些地图的结果,现代铁路网大致沿着较低的暗线穿过多尔、贝桑松和贝尔福特。

Charles Joseph Minard —第戎和米卢斯之间的道路交通— 来源
然而,他最著名的是对拿破仑 1812 年灾难性入侵俄罗斯的描绘。他下面的流程图生动地描绘了拿破仑的军队在往返莫斯科的途中,从将* 50 万到几乎为零的消耗。这是这场运动失败及其人员伤亡的鲜明例证。这些类型的图表现在通常被称为“桑基图表”。

查理·约瑟夫·密纳德——拿破仑的俄国战役地图——来源
弗洛伦斯·南丁格尔
现代护理的创始人,也是一个天才的数学家,是统计学的图形表示的先驱。基于 Playfair 的想法,她将图表融入到她的许多出版物中,并被认为是极区图或“花花公子”的发明者。

“东部军队死亡原因图”——来源:维基百科
该图表描述了克里米亚战争中不同月份的不同死亡原因,每个楔形区的面积代表了统计数据的大小。这种类型的图表非常适合周期性数据,尽管在这种情况下,南丁格尔提供了她所涵盖的两年的单独图表。
南丁格尔对克里米亚、印度和英国的卫生条件进行了多次研究,并使用如上图表游说改革。她的工作对 1875 年的公共健康法案产生了巨大的影响,该法案被一些人认为将英国人的预期寿命延长了 20 年。
弗朗西斯·高尔顿
散点图是双变量分析的支柱,没有人可以自称是发明者。然而有一个人很接*,那就是维多利亚时代的统计学家弗朗西斯·高尔顿。作为一名多产的作家和科学家,他对统计学领域的贡献是巨大的,尽管现在由于他与优生学的联系而有些争议。
在分析两个变量之间的关系时,高尔顿设计了一种图形技术,将每个组合的频率绘制在一个网格上。在这个网格上,等高线被覆盖,显示数据的密度。对于两个相关的、正态分布的变量,这些等高线应形成一个椭圆,其长轴充当一种形式的线性回归。

成年孩子的身高与他们父母的*均身高的比较。来源:http://Euclid . psych . yorku . ca/SCS/Gallery/images/Galton-corr . jpg
信息时代
在二十世纪上半叶,事情进展得相当缓慢,但后来出现了计算机。1981 年,Xerox 8100 Star 推出了第一个商业图形用户界面(GUI ),并随之推出了电子表格等应用程序,这些应用程序能够从信息表中自动生成图形。曾经需要几个小时仔细蚀刻或绘制的东西,现在只需点击几下鼠标就可以完成,同时编辑、格式化和更新也更加容易。从那时起,各种各样的制图技术和风格就出现了,无数的软件包提供了一系列呈现数据的方法。
荣誉奖
Charles Dupin:1826 年,他绘制了已知最早的克洛普图,标出了全法的文盲率。

查理斯·杜*— 法兰西大众教育学院,1826 年
约翰·斯诺:使用点状地图绘制了 1854 年布罗德街霍乱爆发的地图,显示疾病是通过被污染的水传播的,而不是之前认为的空气。

玛丽·埃莉诺·斯皮尔:1952 年,在美国公务员系统担任图形分析师后,她在自己的书《图表统计》中提出了方框图。

自然语言理解简史

照片由 Unsplash 上的 @allecgomes 拍摄
人工智能中自然语言处理的一个子课题
在探索自然语言处理时,我偶然发现了术语自然语言理解。这让我对语言有了更多的思考,不仅仅是处理过程,还有意义。
黄色的花是什么意思?
当然,它可以简单地表示一朵黄色的花,作为一个物体。
它可以是你所爱的人最喜欢的花,让你想起婚礼的那一天,一段珍贵的回忆或悲伤,这取决于具体情况。
也许你总是带黄色的花去你祖母的坟墓。
在墨西哥,黄色的花金盏花象征着死亡。墨西哥的庆祝活动以金盏花鲜艳的黄色和橙色为特色。

照片由 @albrb 拍摄
黄色的花可以代表开悟,这就是为什么它在印度经文中被广泛用来代表佛陀和毗湿奴。
在法国,黄色的花代表嫉妒。
随着时间的推移,意思是一样的吗?
在维多利亚时代的英国,黄色的花被用来象征单恋。维多利亚时代的人用花就像我们用表情符号一样。
说到表情符号——这个看起来很无辜。
🍆
它在网上最常用来代表阴茎。
当汗液滴表情符号旁边时,表示射精。
我们从开花到射精有点快。
无论是口语、文本还是符号,语言中的意义和语境都不是那么容易的。
什么是自然语言理解?
如果意义是如此的困难,那么将这种意义变成一个自动的过程似乎是一个挑战。
在这篇文章中,我探索了术语自然语言理解,主要从维基百科的文章开始,并通过一些我感兴趣的其他来源进一步阐述。
“自然语言理解 ( NLU )或自然语言解释 ( NLI )是人工智能中自然语言处理的一个子课题,处理机器阅读理解。”
以这种方式,它处理一些相当困难和复杂的事情。
如果在人工智能(AI)领域内操作,它可以被认为是一个人工智能难题。什么是 理解 ?
“理解是一个与抽象或物理对象(如人、情况或信息)相关的心理过程,通过这一过程,一个人能够思考它并使用概念来充分处理该对象。理解是知者和理解对象之间的关系。”
理解可以自动化吗?

照片由 @heathermount 拍摄
这个过程可以被充分描述以复制它或者使用人工语言(编程/代码)来更好地理解它吗?
如果这两个问题的答案都是肯定的,那么你可能对自然语言理解有些兴趣。
然而,这些问题可能不相关,你可能只是想从自然语言的角度来探索它——人类说话、发短信或交流。
如果你曾经学过一种不同于你母语的语言,你可能在某种程度上理解句子可以表达相同的意思,也可以表达不同的意思,而且有不同的社会背景,这些句子表达不同的意思。
语言具有社会性和动态性,它是不断变化的,而不是一成不变的。
Insight 可以应用于自动推理、机器翻译、问答、新闻收集、文本分类、语音激活、存档和大规模内容分析。
自然语言理解的历史
可能有许多方法来讲述自然语言理解的历史,但是如果我们从你在维基百科上能读到的东西来看,它是从学生程序开始的。
1964 年学生丹尼尔·鲍勃为他在麻省理工学院的博士论文写的。
学生使用基于规则的系统进行逻辑推理。
这些规则由软件开发人员预先编程,能够解析自然语言。
这被认为是计算机理解自然语言的最早尝试之一。
在此之前,约翰·麦卡锡在 1955 年创造了人工智能这个术语。
丹尼尔·鲍勃的论文题目是 计算机问题解决系统的自然语言输入 。
事实上,这份出版物可以在 ResearchGate 上找到。

Daniel Bobrow 题为计算机问题解决系统的自然语言输入的论文截图
它展示了计算机如何理解简单的自然语言输入来解决代数问题。
1965 年,一年后,麻省理工学院的约瑟夫·韦岑鲍姆写了《伊莉莎》。
伊莱扎是一个互动程序,用英语就任何话题进行对话,最受欢迎的是心理治疗。

与伊莱扎聊天机器人的对话。权利:公共领域。
创作者将程序视为一种展现人机交流肤浅性的方法。
然而,令他惊讶的是,许多人把类似人类的感觉归功于计算机程序,包括他的秘书。
伊莱扎的工作是通过简单的分析和把关键词替换成固定短语。
伊莱扎作为一个玩具项目获得了惊人的人气。
尽管如此,它仍可被视为 2020 年商业系统的早期范例。
1969 斯坦福大学的 Roger Schank 为自然语言理解引入了概念依赖理论。
该模型使用以下基本表示性标记:
- 现实世界的物体,每个都有一些属性。
- 现实世界的动作,每个都有属性
- 次
- 位置
一组概念转换然后作用于这个表示。
如何使意义独立于输入中使用的单词?
1970 ,William A. Woods 引入了扩充转换网络(ATN)来表示自然语言输入。
这些网络称为一组‘有限状态自动机’。
可以在现代社会的许多设备中观察到状态机的行为,这些设备根据它们所呈现的事件序列执行预定的动作序列。
这与相位结构规则形成对比。阶段结构规则用于将自然语言句子分解成其组成部分,也称为'句法类别',包括词汇类别(词类)和短语类别
有限状态自动机被递归调用。
“一个有限自动机可以被看作一个只有有限内存量的程序。一个递归自动机就像一个可以使用递归 ( 递归地调用过程和)的程序,但是在它的变量空间中又超过了有限的内存量。[ 递归自动机 ]
1971 年,特里·维诺格拉德在麻省理工学院完成了他的博士论文《SHRDLU》。
这个程序可以在一个受限的儿童积木世界中理解简单的英语句子,以指导机械臂移动物品。

斯坦福 HCI 发布的原始屏幕显示。
这一成功的演示为该领域的继续研究提供了巨大的动力。
维诺格拉德出版了他的书《作为认知过程的语言的 T2》。
这本书可能是有史以来第一部在计算机帮助下对自然语言处理的思想史进行全面、权威和原则性的描述【书评
让这个故事更加有趣的是维诺格拉德后来建议的那个人。
拉里·佩奇是谷歌的创始人之一,特里·维诺格拉德是他的顾问。
20 世纪 70 年代和 80 年代,SRI International 的自然语言处理小组继续进行该领域的研究和开发。
“SRI 国际(SRI)是一个美国非营利性科学研究机构和组织,总部设在加利福尼亚州门洛帕克。斯坦福大学的董事们于 1946 年建立了斯坦福研究所,作为支持该地区经济发展的创新中心。该组织成立时名为斯坦福研究所。斯坦福国际研究所于 1970 年正式脱离斯坦福大学,并于 1977 年更名为斯坦福国际研究所。
1982 ,另外 Gary Hendrix 成立了赛门铁克公司,最初是一家为个人电脑上的数据库查询开发自然语言界面的公司。
然而,赛门铁克改变了方向。
1983 ,Michael Dyer 在耶鲁开发了 BORIS 系统,该系统与 Roger Schank 和 W. G. Lehnert 的工作有相似之处。
在 20 世纪 80 年代和 2010 年之间的几十年里,进步变得更加模糊,这仍然是我需要了解更多的一段时间。至少在自然语言理解方面(NLU)。就 NLP 而言,总体而言,确实取得了进展。
1980 年随着用于语言处理的机器学习算法的引入,自然语言处理发生了一场革命。
计算能力稳步增长,乔姆斯基语言学理论的主导地位逐渐减弱(例如,乔姆斯基语言学理论的理论基础阻碍了语料库语言学的发展,而语料库语言学是语言处理机器学习方法的基础)。
乔姆斯基发展了一套文法的形式理论,其中转换不仅操纵表面字串,也操纵与它们相关的剖析树,使得转换文法成为一套树状自动机系统
最早使用的机器学习算法,如决策树,产生了类似于现有手写规则的硬 if-then 规则系统。
→ 统计模型最*受到了更多的关注,它基于将实值权重附加到组成输入数据的特征来做出软概率决策。
在维基百科的“自然语言处理的历史”页面上有一个最新软件的列表。这可以追溯到 1954 年 T2 的乔治城实验。然而,我选择展示 20 世纪 80 年代到 20 世纪 10 年代。

并非所有这些系统都专注于自然语言理解。
*几十年来,我们看到了其他系统的崛起,如 IBM Watson。
2011 年,沃森计算机系统参加了危险边缘的比赛!对阵冠军布拉德·鲁特和肯·詹宁斯。
一方面,这是一个有趣的进步,另一方面,人们还在争论这样的系统到底有多“理解”**例如根据约翰·塞尔的说法,沃森甚至没有理解这些问题。
认知科学家、帕托姆理论的发明者约翰·鲍尔支持这一评估。
从最*的语音助手可以注意到,如 Siri、亚马逊(Alexa)和谷歌(Nest)这些并不总是理解你。不得不说更*了,现在的人都在用设备对话。
数以亿计的人正在与盒子或智能手机交谈,这些设备在某种程度上可以理解你。
在未来的岁月里,看看我们如何理解或解释语言肯定会很有趣。现在是 2020 年,我们正在接*理解人类如何交流。我们也更接*于理解如何让设备以一种人类可以理解并进行对话的方式进行交流。
我希望你觉得这篇文章很有趣,并且让你对自然语言理解更感兴趣。
当我们理解这个世界的时候,它一定会在某个地方发生变化。虽然我们在任何时候都可能只有有限的理解,但创建一张地图并看看它通向哪里肯定是有趣的。
这可能会导致一些误解。
机器能被编程理解你吗?

照片由 @kristapsungurs 拍摄
这是#500daysofAI,您正在阅读第 425 篇文章。500 天来,我每天都在写一篇关于或与人工智能相关的新文章。
ggvis 简介
例谈图形的语法
Grammar of Graphics是 Leland Wilkinson 在图形领域数十年工作和研究的成果,它为 R 图形库提供了哲学基础,如 ggplot2、ggvis 和 Julia 图形库,如牛虻。虽然,还有其他库可以为您提供真正令人惊叹的图形,但这些包的不同之处在于,它们基于 Wilkinson 所做的研究,该研究试图将图形视为一种语言,并将其分解为单独的组件,就像任何其他语言将其组件分解为主语、动词、宾语等。
威尔金森在 20 世纪 70 年代早期写了一个以其全面的图形而闻名的统计软件包,后来他在 90 年代中期把它卖给了 SPSS。在 SPSS 工作的时候,他写了他的突破性的研究,不久前提到过。他的研究对计算机科学中的图形哲学产生了重大影响。由 Winston Chang 和 Hadley Wickham 维护的Rgg plot 2 中最著名的绘图软件包,其基本原理来自于图形语法。另一个这样的软件包是 ggvis。我们会谈到后者。

由 Jason Coudriet 在 Unsplash 上拍摄的照片
为什么是 ggvis 而不是 ggplot2?
《T21》本身就是一个了不起的包。ggvis 没有从中拿走任何东西,相反,它只是前者的扩展,具有构建 HTML 图形的能力。因为 ggvis 图形是 HTML,所以它们可以用在一个漂亮的 web 应用程序、R markdown 报告中,也可以和 JavaScript 一起使用。一会儿我们会弄清楚其中一些意味着什么。
资源
关于 ggvis 的文档可以在这里找到,还有一个关于数据营的非常好的教程。如需更多信息,您可以访问 ggvis 上的 RStudio 的博客,以及一份关于 图形 语法的简明摘要。本帖的主要目的是探究和理解 ggvis 的语法和句法。
$ religiongdp <- read.table("/Users/kovid.rathee/Downloads/ReligionGDP.csv", header=TRUE, sep=",")
$ religiongdp %>% ggvis (~GDP, ~Religiosity) %>% layer_points()
我们首先要了解的是从 马格里特 包中取出的管道操作符 % > % 。这就像壳管操作器的工作一样。

从第一张图片本身来看,这种模式很明显。越是宗教化的国家,越不繁荣(从 GDP、幸福等方面来看)。这里不算,因为我们没有数据)他们是。不过,也有一些例外。但是,我们也可以从数据中看到这一点。为什么要创建图表?因为图表很容易理解。他们讲述完整的故事,而不是一篇十页的文章。他们让我们预测未来——或者至少他们应该让我们预测未来。
religiongdp %>% compute_smooth(GDP ~ Religiosity) %>% ggvis (~pred_, ~resp_) %>% layer_lines(stroke := "darkblue", strokeWidth := 3, strokeDash := 5)

religiongdp %>% compute_smooth(GDP ~ Religiosity) %>% ggvis (~pred_, ~resp_) %>% layer_points(fill := "darkblue", size = 0.5)
回归和趋势线
用一条有点像的线来绘制原始数据。我们可以认为是一条回归线。数据集中的特征不足以进行适当的分类从而猜测一个国家或一个州的 GDP 应该是多少。除了宗教信仰,还有很多更重要的东西,比如人口,政府形式等等。但是,即使从这张图表中,我们也可以粗略地确定 GDP 和宗教信仰之间存在负相关关系——尽管有两个主要的例外,科威特和美国。我们可以称他们为离群值。

虽然橙色趋势线是数据的一个相当不错的表示,但如果我们在这里谈论做出预测,基于不同算法的分类,如 KNearestNeighbour 等。可能需要。这个想法是将所谓的离群值也放入算法运行其原因后将创建的许多类中的一个。
请注意重现右上角的设置按钮。当你点击那个按钮时,它会为你提供一个选项来下载一个 svg 文件或者一个 png 文件。

你想要什么?可缩放矢量图形或便携式网络图形。阅读一些关于什么时候使用哪个的信息。
交互式图表
ggvis 也有别于 ggplot2 ,因为它具有类似输入滑块的交互功能。互动性是 ggvis 的主要成就之一。它的工作方式与在 Tableau 或 Qlikview 环境中的工作方式相同,但是,当您使用这些库编写自己的代码时,您将对这些图形的渲染方式有更多的控制和更清晰的理解。这里有一个例子:
religiongdp %>% ggvis (~GDP, ~Religiosity) %>% layer_points(fill := "darkblue", size := input_slider (5,15,value=1)) %>% layer_smooths(stroke:="orange", span = input_slider (5,15,value=1))

带有滑块输入的图形。制作了一个非常好的交互式图表,可以嵌入到应用程序中。
iris %>% ggvis(~Sepal.Length,~Sepal.Width,fill=~Species) %>% layer_smooths(span = 2, stroke := “darkred”, strokeDash := 6) %>% layer_smooths(span = 1, stroke := “darkblue”) %>% layer_smooths(span = 0.5, stroke := “orange”)

只需使用%>%运算符,就可以用不同的格式在图上定义不同的线。这让生活变得简单多了。
iris %>% ggvis(~Sepal.Length,~Sepal.Width,fill=~Species) %>% layer_points() %>% add_axis ("x",title="Sepal Length",properties=axis_props(axis=list(stroke="darkblue"),grid=list(stroke="brown",strokeDash=3),ticks=list(stroke="orange",strokeWidth=2),labels=list(angle=45, align="left", fontSize=12)))

著名 Iris 数据集的基本点状图。在这种情况下,我们可以通过颜色来识别花的种类,位置代表了叶子的尺寸——长度和宽度。
iris %>% ggvis (~Sepal.Length,~Sepal.Width) %>% mutate(Sepal.Length = Sepal.Length * 1.5) %>% layer_points(fill=~Species,size=~Petal.Width) %>% add_axis(“x”,title=”Sepal Length”,orient=”top”) %>% add_axis(“y”,title=”Sepal Width”,orient=”right”) %>% add_legend(c(“size”,”fill”),title=”Petal Width”))

在这里,我们试图添加另一个变量到图中。花瓣宽度——除了能够绘制萼片尺寸和通过颜色识别物种,我们还可以通过一个点的强度/大小来表示花瓣宽度。
iris %>% ggvis(x=~Sepal.Length,y=~Petal.Length,fill=~Species) %>% layer_points(opacity=~Sepal.Width) %>% layer_model_predictions(model="lm",stroke:="green",opacity=3)

使用图层模型预测的线性拟合线。有很多预定义的模型可以用来绘图。线性拟合线在这里没有什么意义。但如果是这样的话,它应该是这样的。
iris %>% ggvis(x=~Sepal.Length,y=~Petal.Length,fill=~Species) %>% layer_points(opacity=~Sepal.Width) %>% layer_model_predictions(model="loess",stroke:="green",opacity=3)

可能,不正确的例子使不透明度成为萼片宽度的函数。但这对于可视化变量的强度、严重性和大小非常有用——这些变量无法绘制在 x-y *面上。
结论
ggvis 是一个很棒的包,它提供了对 ggplot2 的升级,具有许多新时代的功能,如交互式绘图和创建 HTML 绘图的能力,使这些绘图能够嵌入到闪亮的应用程序中等等。威尔金森的工作极大地影响了绘图语言中的话语——这是日常工作,同时进行数据分析、商业智能、机器学习等。
Go-Explore 简介
如何打败最难的雅达利游戏

介绍
这些天我们在机器学习社区看到的是一场真正的军备竞赛:每个月,每个星期研究人员都发表新的论文,声称在数据集上产生最先进的(SOTA)结果。总的来说,我对机器学习的很多领域都感兴趣,所以我真的很难跟上新论文的潮流。在这方面,有一个网站给了我很大的帮助,那就是 paperswithcode ,它展示了对无数不同数据集的 SOTA 模型的全面概述。竞争极其激烈的领域之一是经典的雅达利游戏。就在今年,来自谷歌的研究人员提出了一种新方法来实现两个众所周知的困难游戏陷阱和蒙特祖马的复仇的超人性能。下面是他们是如何做到的。
为什么强化学习很难
首先,我们需要两个来理解为什么特别是这两场比赛如此艰难。强化学习的整个思想是代理人通过从环境中收集奖励来学习。代理人会尝试一系列的行动,并选择能产生最高综合回报的行动组合。最佳环境有非常密集的奖励,所以代理人立即得到反馈,它的行动有多好。这方面的一个例子是吃豆人,那里的迷宫充满了收集的硬币。如果奖励太少,就会出现问题。那么代理缺乏反馈来改进他的行动。根据谷歌的论文,那些稀疏的奖励引发的两个主要问题是脱离和出轨
超脱
为了解决奖励稀少的问题,人们提出了内在奖励的概念。在这里,奖励被人为地均匀分布在整个环境中,以鼓励代理人去探索。
说明超脱的最简单的方法是通过一个简单的图片。请看图 1。这里的 im 是绿色的,分布在两个迷宫中。

图 1:拆卸图【1】
代理从中间开始,首先探索左侧的迷宫。大多数强化学习算法的行为是随机的,所以在某个时间点,代理可能会决定开始探索正确的迷宫。现在的问题是在左边的迷宫中还有一些部分没有被探索,因此仍然有奖励,但是代理不太可能收集它们。原因是强化学习中的另一个问题叫做灾难性遗忘。当一个代理探索一个新的区域时,它会覆盖它过去的经验,因此它访问某个区域的时间越长,情况就越糟。
出轨
为了理解这个问题,我们需要稍微了解一下强化学习算法。在许多环境中,在探索和开发之间存在冲突,即代理人可以采取一条已经众所周知的路径,在这条路径上保证有好的回报(开发),或者执行新的行动,希望这会导致更高的回报,但有接受更低回报的风险(探索)。为了应对这种冲突,许多算法采用了某种ɛ-greedy 策略。这意味着,在大多数情况下,代理将执行尽其所知最佳的动作(利用),但在某些概率下,它将执行随机动作(探索)。这可能会有问题。想象一个智能体想要达到某个状态,而这个状态只有通过一系列动作的组合才能达到。代理甚至不太可能达到这种状态,因为在这个过程中,它将执行许多不同的动作,偏离了实际所需的路径。
去探索
谷歌的研究人员已经开发出一种方法来解决分离和出轨。它包括两个不同的阶段,即探索阶段和强健阶段。
第一阶段:探索
这个阶段没有使用任何神经网络或其他机器学习算法,而是完全基于随机(可能是半指导)探索。在这里,作者介绍了细胞的概念。单元格是实际游戏帧的缩小和灰度图像(图 2)。

图 2:从帧到单元格【1】
这里的主要目标是找到感兴趣的细胞。那些是什么?有趣的细胞,以前没有发现,并在那里的代理收集了高奖励,以达到目的。每当发现新的单元时,四个值被添加到单元档案中:
- 这个细胞的完整轨迹
- 该牢房的环境状况
- 该轨迹实现的总回报
- 这个轨迹的长度
如果遇到已经在档案中的细胞,则相应的条目被更新,以防它“更好”,即更高的总回报或更短的轨迹。
在每次迭代中,该算法执行以下操作:
- Go: 使用试探法选择一个“好的”单元格,然后前往该单元格。试探可能选择具有最高总回报、最少访问等的单元。
- 探索:执行随机动作,从这个有希望的细胞中寻找新的细胞。同样:这是随机的,没有政策或网络来选择一个动作。
这两个步骤有助于防止脱轨和脱离。我们建立了一个状态以及如何到达那里的档案,所以好的状态不会丢失(防止分离)。第一步,我们直接去国家,没有政策,因此没有随机行动。出轨也因此得以避免。
第二阶段:强健
第一阶段做了一个巨大的隐含假设:我们的环境是决定性的。为了从我们的档案中“转到”某个单元,我们需要能够重置环境,并确保我们存储的一系列操作确实会导致我们想要的“好”单元。这在电脑游戏中很容易实现,尤其是在简单的 Atari 游戏中,因为在这里相同的动作总是会导致相同的结果。但是当然,人们也想在现实世界中使用强化方法,这通常很难确定。这就是我们需要这个第二阶段的目的:使我们通过随机探索发现的良好结果细胞的轨迹对噪声和非确定性更加鲁棒。
为此,本文使用了所谓的向后算法。图中,我们有一系列单元格 c(1),c(2),…,c(n-1),c(n),我们在探索阶段发现这些单元格非常好,现在想做得更健壮。在第一步中,我们将我们的环境设置为 c(n-1 ),并训练一个强化算法来执行达到 c(n)所必需的动作。如果这个算法找到了一条轨迹,与我们随机找到的相比,它得到了相同或更高的回报,我们就返回到 c(n-2),并试图从那里到达 c(n)。这是一个不断重复的过程,直到我们找到一个好的策略,找到一系列从 c(1)(开始状态)到 c(n)(结束状态)的动作。
如上所述,Atari 游戏是确定性的,但我们希望使我们的策略对非确定性更加鲁棒。那么,该怎么办呢?在我们的环境中引入噪声有两种相对简单的方法:
- 没有操作:雅达利游戏有一个内置的计时器,它可以确定某些危险是否存在,或者危险和敌人在哪里。因此,如果我们在游戏开始时等待随机数量的帧,世界将总是处于稍微不同的状态。
- 粘性动作:人类玩得不完美。他们的反应需要一些时间,所以他们有时按下按钮的时间比他们应该按的时间要长。强化算法通过粘性动作来模拟这一点,即根据算法的策略,随机执行动作的时间比应该执行的时间稍长。
结果
使用 Go-Explore 方法获得的结果是杰出的:不仅比任何其他强化算法执行得更好,而且它们还在超人的水*上运行(图 3)。

图 3:Go-探索蒙特祖马的复仇与其他方法的性能对比【1】
来源
[1] A. Ecoffet,J. Huizinga,J. Lehman,K. O. Stanley 和 J. Clune: Go-Explore:一种解决难探索问题的新方法 (2020)
新冠肺炎数据来源简评
一些流行的新冠肺炎数据源的利与弊
作为一名数据科学家,我一直在寻找分析疫情冠状病毒的“最佳”数据源。不幸的是,周围有这么多不同的来源,每一个都有点不同。以下是截至 2020 年 3 月 26 日的简短回顾。我将介绍以下数据源的优点和缺点,以便您可以选择最适合您需求的数据源:
更新 2020–03–30:世界计量、美国事实、和纽约时报在#5 丁香元之后讨论。
简而言之,如果不需要 API,那么 1Point3Acres 的数据和可视化最好。
如果你确实需要一个 API,那么 【约翰霍普金斯】 的数据,连同COVID 跟踪项目 的信息,为测试提供了一个很好的起点。
以下是详细内容。
1.3 亩:
如果您正在寻找美国新冠肺炎数据,并且您不需要 API,那么就不要再找了。这是最好的网站。
优势:
- 有关于确认和死亡人数的县级详细信息。这是我找到的唯一包含此信息的数据源。
- 来自许多其他来源的综合信息。比如测试数据(来自https://covidtracking.com/)、各种来源的新闻、来自 YouTube 的相关视频等。
- 非常可靠和高质量的数据,甚至美国疾病控制和预防中心每天都使用它的数据。
- 非常好的视觉效果。便于读者选择自己感兴趣的状态。和其他国家对比也毫不费力。而《赛车》条形图(使用花枝作为后端)也很有信息量,在其他网站很少见到。
****
缺点:
- 没有公共 API。如果您想以编程方式使用他们的数据,那么您需要联系他们。
- 关注美国和加拿大。如果你的主要兴趣在其他地方,那么这不是你的来源。
约翰霍普金斯 CSSE (系统科学与工程中心)
如果您正在寻找全球数据,这是要去的数据源。自冠状病毒流行早期以来,它就被广泛引用。
优势:
- 涵盖世界各地的数据封面。
- 2020 年 3 月 22 日及之后的数据包含美国的县级数据。
- 数据在 GitHub 中公开,并在世界各地积极开发和使用。这样你就可以轻松地自己玩了。事实上,大多数其他数据源都是建立在这个数据集之上的。例如,您可以通过以下方式获取 2020 年 3 月 25 日的每日报告 CSV:
缺点:
- 2020 年 3 月 22 日之后的美国县级信息。考虑到美国已于 2020 年 3 月 13 日宣布全国进入紧急状态,这并不理想。纽约时报数据源(本文后面会提到)有自 2020 年 1 月 21 日以来的县级信息。
- 仪表板 GUI 的信息量小于 1Point3Acres。除了地图,您只能看到确诊病例和每日增加病例的时间序列图。您无法比较不同的区域,无法查看对数比例的图,等等。

COVID 跟踪项目
如果您只需要美国的数据,并且您需要一个 API,那么这就是要去的数据源。
这是一个独特的数据源,因为它不仅包含已确认/死亡人数,还包含美国的测试数据,即阳性和阴性结果、待定测试和测试总人数。这些信息非常有价值,因为它揭示了许多尚未“确认”的“实际”患者人数的信息。这些测试数据也被 1Point3Acres 用在他们的网站上。
优势:
- 包含测试数据
- API (Google sheet、CSV、JSON、download 和 API 端点)公开可用,并且非常容易使用。例如,您可以通过以下方式获取每日 JSON 和 CSV:
缺点:
- 没有县级数据
- 没有全局数据
ka ggle 新型冠状病毒数据集
如果您想要构建医疗细节的统计数据,这是首选的数据源。
优势:
- 使用约翰霍普金斯大学 CSSE 分校的数据作为主要的底层数据源
- 有几千个病例的医学细节,如症状、旅行史、慢性病等。它还可以通过谷歌电子表格格式获得。

弱点:
- 与约翰霍普金斯大学的数据基本相同。在 2020 年 3 月 22 日之前没有县数据,也没有测试数据。
Ding Xiang Yuan (丁香园)
如果你正在为中国寻找最好的数据,这是可以去的数据源。这是公众可以获得的最早的数据来源。自 2020 年 1 月冠状病毒爆发以来,它已被广泛使用。
优势:
- 包含中国最早和最详细的(市级)数据
缺点:
- 没有公共 API。但是,你可以在 GitHub 中找到网络爬虫,它从丁象元获取数据。比如艾萨克·林的时间序列数据仓库。这也是我在这篇媒体文章中为自己的 GitHub 项目分析中国疫情数据时使用的数据源。
- 网站上的可视化是原始的。没有适当的组织,所有的图都挤在一起,并且没有可用的对数比例图。
- 全球数据只有国家总数,没有细分到各州。

更新 2020 年 3 月 30 日:
世界计量表
总的来说,我更喜欢约翰·霍普金斯大学 CSSE 分校。在 Worldometers 没有提供太多的信息,但在约翰霍普金斯 CSSE 大学没有。查看该网站的唯一原因是它将已确认的数量分为轻度和严重/危急。然而,该网站没有说明这种分裂的来源或方法,因此很难判断他们有多可信。
美国事实
一般来说,我更喜欢 1Point3Acres 而不是 USAFacts。两个网站都提供县级信息。但是 1Point3Acres 具有更好的可视化效果,如对数标度图、州级图、赛车条形图等。此外,1Point3Acre 可以轻松地将数字与其他国家进行比较,而 USAFacts 则不能。
然而,尽管 USAFacts 没有任何 API,但它确实提供了县一级确诊和死亡人数的下载链接:
死亡:https://usafactsstatic . blob . core . windows . net/public/data/新冠肺炎/covid_deaths_usafacts.csv
纽约时报数据集
纽约时报从 2020 年 3 月 27 日开始在 GitHub 上发布他们的数据集。如果您正在寻找美国的县级数据集,这是一个不错的去处。然而,据我所知,他们的县级数字加起来并不完全是州总数。另外,纽约时报的数据有点延迟,你可能要等到第二天才能得到更新的每日数据。
还有,他们没有测试数据,也没有国际数据。所以如果你需要这些信息,你需要从其他地方合并。
最后的话
我见过的大多数其他数据源都是从这些数据源中的一个或多个派生出来的。如果你看到任何其他好的数据来源,请不要犹豫,给我留下评论。谢了。
承认
我要感谢我的朋友 David Tian,他是一名机器学习工程师,他对本文提出了宝贵的建议。看看他有趣的自驾 DeepPiCar 博客。
朴素贝叶斯分类及其实现的简短教程
朴素贝叶斯从计数开始,然后转向概率

图片来源:Unsplash
朴素贝叶斯分类是数据挖掘或机器学习中最简单和最流行的算法之一(被 CRC Press Reference [1]列为十大流行算法)。朴素贝叶斯分类的基本思想非常简单。
(如果你觉得视频格式更适合你,可以跳这里你也可以去笔记本。)
基本直觉:
比方说,我们有两类书。一类是体育,一类是机器学习。我统计了“匹配”(属性 1)和“算法”(属性 2)这两个词的出现频率。让我们假设,我从这两个类别各有 6 本书,这 6 本书的字数如下图所示。

图 1:书籍中的字数
我们清楚地看到,“算法”这个词更多地出现在机器学习的书籍中,“比赛”这个词更多地出现在体育运动中。有了这些知识,假设我有一本书,它的类别是未知的。我知道属性 1 的值是 2,属性 2 的值是 10,我们可以说这本书属于体育类。
基本上,我们想要找出哪一个类别更有可能,给定属性 1 和属性 2 的值。

图 2:根据数量查找图书的类别
从计数到概率:
这种基于计数的方法适用于少量类别和少量单词。使用条件概率可以更好地遵循同样的直觉。

图 3:条件概率(图片来源:作者)
有一个例子可以更好地理解条件概率
让我们假设
事件 A:面值为奇数|事件 B:面值小于 4
P(A) = 3/6(有利情况 1,3,5 总情况 1,2,3,4,5,6)类似地 P(B)也是 3/6(有利情况 1,2,3 总情况 1,2,3,4,5,6)。条件概率的一个例子是,给定一个小于 4 的奇数(A)的概率是多少(B)。为了找到这一点,我们首先找到事件 A 和 B 的交集,然后除以情况 B 中的案例数。更正式地说,这由以下等式给出

图 4:条件概率(图片来源:作者)
P(A|B)是条件概率,读作给定 B 的概率。这个等式构成了中心原则。现在让我们再回到我们的图书类别问题,我们想更正式地找到图书的类别。
条件概率到朴素贝叶斯分类器
让我们使用下面的符号 Book=ML 是事件 A,book=Sports 是事件 B,“属性 1 = 2,属性 2 = 10”是事件 C。事件 C 是一个联合事件,我们一会儿就会谈到这一点。
因此问题变成这样,我们计算 P(A|C)和 P(B|C)。假设第一个值为 0.01,第二个值为 0.05。那么我们的结论将是这本书属于第二类。这是一个贝叶斯分类器,朴素贝叶斯假设属性是独立的。因此:
P(属性 1 = 2,属性 2 = 10) = P(属性 1 = 2) * P(属性= 10)。我们把这些条件分别称为 x1 和 x2。

图 5:用条件概率寻找类(图片来源:作者)
因此,使用可能性和先验,我们计算后验概率。然后,我们假设属性是独立的,因此可能性扩展为

图 6:扩展条件概率
上面的等式显示了两个属性,但是,可以扩展到更多。因此,对于我们的特定场景,等式变为如下。它仅在 Book='ML '中显示,在 Book ='Sports '中也会类似地显示。

图 7:书籍的朴素贝叶斯方程示例(图片来源:
实施:
让我们使用著名的朴素贝叶斯流感数据集,并导入它,你可以改变路径。你可以从这里下载数据。
导入数据:

图 8:流感数据集
nbflu=pd.read_csv('/kaggle/input/naivebayes.csv')
数据编码:
我们将列存储在不同的变量中,并对它们进行相同的编码
**# Collecting the Variables**
x1= nbflu.iloc[:,0]
x2= nbflu.iloc[:,1]
x3= nbflu.iloc[:,2]
x4= nbflu.iloc[:,3]
y=nbflu.iloc[:,4]# **Encoding the categorical variables**
le = preprocessing.LabelEncoder()
x1= le.fit_transform(x1)
x2= le.fit_transform(x2)
x3= le.fit_transform(x3)
x4= le.fit_transform(x4)
y=le.fit_transform(y)**# Getting the Encoded in Data Frame**
X = pd.DataFrame(list(zip(x1,x2,x3,x4)))
模型拟合:
在这一步中,我们将首先训练模型,然后为患者进行预测
model = CategoricalNB()
*# Train the model using the training sets*
model.fit(X,y)
*#Predict Output*
*#['Y','N','Mild','Y']*
predicted = model.predict([[1,0,0,1]])
print("Predicted Value:",model.predict([[1,0,0,1]]))
print(model.predict_proba([[1,0,0,1]]))
输出:
Predicted Value: [1]
[[0.30509228 0.69490772]]
输出表明不流感的概率是 0.31,流感的概率是 0.69,因此结论是流感。
结论:
朴素贝叶斯作为基线分类器工作得非常好,它速度快,可以处理较少数量的训练样本,可以处理有噪声的数据。挑战之一是它假设属性是独立的。
参考:
[1]吴 X,库马尔 V,编者。数据挖掘的十大算法。CRC 出版社;2009 年 4 月 9 日。
[2]https://towards data science . com/all-about-naive-Bayes-8e 13 cef 044 cf
一种构建推荐系统的简单方法
利用惊喜包在 Python 中构建协同过滤推荐器

具有协同过滤的示例推荐系统。莫莉·里伯斯金图片。
要理解推荐系统的力量,最简单的方法就是关注网飞,他最先进的推荐系统让我们在电视机前呆上几个小时。然而,推荐人是极其多样化的,他们在交叉销售产品、确定具有相似技能的员工候选人以及寻找会对促销信息做出回应的客户方面发挥着作用。这些例子仅仅触及了如何使用推荐系统的表面。
尽管推荐器可能非常复杂,但有两种简单的方法可以作为一个良好的起点。
- 基于内容的过滤:使用项目特征来推荐与用户以前喜欢或交互过的项目相似的项目。潘多拉的音乐基因组项目识别每首歌曲的音乐属性,并利用这些信息找到相似的歌曲并做出推荐。
- 协同过滤:根据相似用户对每个项目的评价来确定用户喜欢的项目。网飞通过确定相似用户观看的内容来识别用户喜欢的节目和电影。
这篇文章将重点介绍使用巴西电子商务公司 Olist 发布的销售交易数据开发一个协同过滤推荐系统。
入门指南
为了构建推荐器,我们将使用 Surprise ,一个为协同过滤而构建的 Python scikit 包。
第一步是加载我们需要的包和数据集。数据集由 8 个表组成,但是出于演示的目的,我已经连接了表并隔离了我们需要的列。完整代码在这里。
#Import packages **import** pandas **as** pd
**import** matplotlib.pyplot **as** plt
**import** seaborn **as** sns**from** surprise **import** NormalPredictor, Reader, Dataset, accuracy, SVD, SVDpp, KNNBasic, CoClustering, SlopeOne**from** surprise.model_selection **import** cross_validate, KFold, GridSearchCV, train_test_split#import dataset
olist_data = pd.read_csv('olist_data.csv')
正如现实世界的数据经常发生的那样,这个数据集不是为创建协作推荐系统而完美构建的。这里的一个大挑战是,几乎 90%的用户都是第一次购买,这意味着我们没有他们以前的评分来确定喜欢的产品。相反,我们将把数据集分为重复用户和首次用户,并且只把重复用户输入到协作过滤模型中。对于第一次购买的顾客,我们仍然可以提供推荐,但它们会更加通用,侧重于商品的受欢迎程度和用户的位置。
**def** repeat_and_first_time(data): repeaters = data.groupby('customer_unique_id').filter(**lambda** x: len(x) > 1)
first_timers = data.groupby('customer_unique_id').filter(**lambda** x: len(x) == 1)
**return** repeaters, first_timers
利用惊喜
为了利用 surprise 内置的用户评级矩阵转换,我们需要提供一个包含用户 id 列、项目 id 列和评级列的数据框架。
**def** create_user_ratings_df(data):
df = data.groupby(['customer_unique_id','product_id'])['review_score'].agg(['mean']).reset_index()
df = df.rename({'mean':'estimator', 'product_id':'productId'}, axis=1)
**return** dfuser_ratings_df = create_user_ratings_df(repeater_data)user_ratings_df.head()

用户评级矩阵示例。莫莉·里伯斯金图片。
从这里开始,Surprise 将帮助我们生成一个用户评级矩阵,其中每个用户 id 是一行,公司提供的每个产品是一列。这将产生与创建熊猫数据透视表相同的效果。我们将用 80/20 分区将数据帧分成训练集和测试集。
**def** surprise_df(data):
scale = (data.estimator.min(), data.estimator.max())
reader = Reader(rating_scale=scale)
df = Dataset.load_from_df(data[['customer_unique_id',
'productId',
'estimator']], reader)
**return** dfuser_ratings_matrix = surprise_df(user_ratings_df)train_set, test_set = train_test_split(user_ratings_matrix, test_size=0.2, random_state=19)
惊喜提供了 11 种不同的预测算法,包括各种 KNN 和维数缩减技术,如奇异值分解和 NMF。在本次演示中,我们将测试一些最常见的技术。
使用 5 重验证,我们将比较以下模型的结果。
- NormalPredictor:根据假定为正态的训练集分布预测随机评级的基线模型。
- 奇异值分解:一种矩阵分解技术,作为网飞奖的一部分由西蒙·芬克推广。
- KNNBasic:利用余弦相似性(或用户确定的距离度量)来执行 KNN。
- 协同聚类:一种算法,以类似于 k-means 的方法为聚类分配点数。
有两种方法可以评估模型性能。定性地说,你可以观察一个给定的用户,考虑到他们喜欢的其他产品,确定这个推荐是否有意义。例如,如果有人喜欢恐怖电影,不喜欢浪漫喜剧,《闪灵》相对于真爱会是一个不错的推荐。对于这个数据集,我们没有每个产品的信息,只有一个产品 id,所以我们将使用一个定量的测量方法,均方根误差。这两种方法的结合是理想的,尽管定量测量在生产中更现实。
kf = KFold(n_splits=5, shuffle=**True**, random_state=19)**def** model_framework(train_data): #store the rmse values for each fold in the k-fold loop
normp_rmse, svd_rmse, knn_rmse, co_rmse, slope_rmse = [],[],[], [],[]
**for** trainset, testset **in** kf.split(train_data):
*#baseline*
normp = NormalPredictor()
normp.fit(trainset)
normp_pred = normp.test(testset)
normp_rmse.append(accuracy.rmse(normp_pred,verbose=**False**))
*#svd*
svd = SVD(n_factors=30, n_epochs=50,biased=**True**, lr_all=0.005, reg_all=0.4, verbose=**False**)
svd.fit(trainset)
svd_pred = svd.test(testset)
svd_rmse.append(accuracy.rmse(svd_pred,verbose=**False**))
*#knn*
knn = KNNBasic(k=40,sim_options={'name': 'cosine', 'user_based': **False**}, verbose=**False**)
knn.fit(trainset)
knn_pred = knn.test(testset)
knn_rmse.append(accuracy.rmse(knn_pred,verbose=**False**))
*#co_clustering*
co = CoClustering(n_cltr_u=3,n_cltr_i=3,n_epochs=20)
co.fit(trainset)
co_pred = co.test(testset)
co_rmse.append(accuracy.rmse(co_pred,verbose=**False**))
mean_rmses = [np.mean(normp_rmse),
np.mean(svd_rmse),
np.mean(knn_rmse),
np.mean(co_rmse),
np.mean(slope_rmse)]
model_names = ['baseline','svd','knn','coclustering','slopeone']
compare_df = pd.DataFrame(mean_rmses, columns=['RMSE'], index=model_names)
**return** compare_dfcomparison_df = model_framework(train_set)
comparison_df.head()

莫莉·里伯斯金图片。
基于以上所述,我们确定 SVD 具有最低的 rmse,并且是我们将继续调整的模型。
模型调整:惊奇的网格搜索
这个令人惊讶的包提供了一个使用 GridSearchCV 调整参数的选项。我们将为 GridSearchCV 提供一个参数字典,并计算和比较每个参数组合的 rmse。
**def** gridsearch(data, model, param_grid):
param_grid = param_grid
gs = GridSearchCV(model, param_grid, measures=['rmse'], cv=5)
gs.fit(data)
new_params = gs.best_params['rmse']
best_score = gs.best_score['rmse']
print("Best score:", best_score)
print("Best params:", new_params)
**return** new_params, best_scoresvd_param_grid = {'n_factors': [25, 50,100],
'n_epochs': [20,30,50],
'lr_all': [0.002,0.005,0.01],
'reg_all':[0.02,0.1, 0.4]}
svd_params, svd_score = gridsearch(train_set, SVD, svd_param_grid)
从该搜索中,我们得到一个输出,告诉我们获得的最佳分数(最低 rmse)是 1.27,它是使用参数{'n_factors': 25,' n_epochs': 50,' lr_all': 0.01,' reg_all': 0.1}产生的。
最终模型和指标
利用上面的参数,我们然后在没有交叉验证的完整训练集上运行该模型,并根据测试集获得准确度分数。
**def** final_model(train_set, test_set):
params = {'n_factors': 10, 'n_epochs': 50, 'lr_all': 0.01,
'reg_all': 0.1}
svdpp = SVDpp(n_factors=params['n_factors'],
n_epochs=params['n_epochs'],
lr_all=params['lr_all'],
reg_all=params['reg_all'])
svdpp.fit(train_set)
predictions = svdpp.test(test_set)
rmse = accuracy.rmse(predictions,verbose=**False**)
**return** predictions, rmse
final_predictions, model_rmse = final_model(train_set, test_set)
的。测试属性输出预测,其中包含用户 id、项目 id、用户实际评级、模型估计评级以及可能做出预测的指示器。除了查看来自最终训练模型的 model_rmse 输出,我们还将查看所有预测的绝对误差分布。为此,我们将把预测输出打包到一个数据帧中,并添加一个列来指示每个预测的错误。然后,我们将通过绘制误差直方图来可视化结果。
results = pd.DataFrame(final_predictions, columns=['userid', 'item_id', 'user_rating', 'model_est', 'details'])
results['err'] = abs(results.model_est - results.user_rating)
在下面的图中,我们看到,尽管完整数据集的误差为 1.0,但当用户给产品的评分高于 3 时,模型做出了更好的预测,误差仅为 0.8。相比之下,当用户给产品打 3 分或 3 分以下的分数时,误差明显更高,为 1.5 分。这是一个很好的结果,因为为了提供好的推荐,我们更关心准确预测用户喜欢并评分高于 3 的产品。

比较整体模型误差与等级> 3 和等级≤3 的误差的图。莫莉·里伯斯金图片。
然后,可以使用转储模块对模型进行打包,转储模块是 Pickle 的包装器。对于这个例子,协同过滤推荐只是整个系统的一部分。它根据每个地理区域的总体畅销产品和最佳表现者进行推荐。
附加注释
为了熟悉这个过程,Surprise 有一些很好的内置数据集,文档详细解释了不同的交叉验证方法、相似性度量和预测算法。
目前,Surprise 还不能处理隐式评级、执行内容过滤或生成混合推荐。然而,对于初学者来说,Surprise 是一个简单直接的协作过滤包。
你可以在 github 上找到这个例子的所有代码。
Python 中的简单突破交易策略
对客观的系统突破策略进行编码和回溯测试
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
我刚刚出版了一本新书《Python 中的新技术指标》。它对复杂的交易策略进行了更完整的描述和补充,Github 页面致力于不断更新代码。如果你对此感兴趣,请随时访问下面的链接,或者如果你喜欢购买 PDF 版本,你可以在 Linkedin 上联系我。
亚马逊网站:交易策略之书(9798532885707): Kaabar,Sofien:书籍
交易分为许多不同的策略,依赖于趋势跟踪、均值回归、波动性或其他因素。成功的策略依赖于当前的市场状态,例如,当市场趋势强劲时,均值回归策略往往会失败,因此我们必须相应地调整我们的市场方法。下面是一个突破策略,它使用了一个叫做唐奇安通道的指标。基本的想法是让区间尽可能客观(即可以衡量),然后在突破时交易(即趋势的开始)。因此,本文的目的是看这个指标是否能增加我们整个交易系统的价值。它能提供好的信号吗?这些触发因素值得认真对待吗?
唐奇安海峡
理查德·唐奇安创造了这个简单而伟大的指标,用来识别突破和反转。就像布林线一样,它的使用方式也差不多。我们的目标是通过超越或突破任何障碍来客观地确定区间出场。它的形成方法是首先计算最* n 个周期高点的最大值和最* n 个周期低点的最小值,然后计算它们的*均值。这给了我们三个小节:唐奇安高频带、低频带和中频带。下面是数学公式,随后是用于 OHLC 数据结构的 Python 代码。

*def donchian(Data, low, high, where_up, where_down, median, period):
for i in range(len(Data)):
try:
Data[i, where_up] = max(Data[i - period:i + 1, 1])
except ValueError:
pass
for i in range(len(Data)):
try:
Data[i, where_down] = min(Data[i - period:i + 1, 2])
except ValueError:
pass
for i in range(len(Data)):
try:
Data[i, median] = (Data[i, where_up] + Data[i, where_down]) / 2
except ValueError:
passdonchian(Data, 2, 1, 4, 5, 6, 20)'''
plt.plot(Data[-500:, 3], color = 'black')
plt.plot(Data[-500:, 4])
plt.plot(Data[-500:, 5])
plt.plot(Data[-500:, 6])
plt.grid()'''*
从视觉上看,唐奇安通道似乎包围了价格,这是可以理解的,因为它考虑了当前的极端情况,因此市场永远不会位于通道之外。

欧元兑美元 H3 时间框架和 20 期唐奇安通道。
制定战略
唐奇安海峡的基本战略是突围战略。它直观而清晰,下面是规则:
- 当市场超过最后一个上升通道时买入。
- 每当市场突破最后一个较低通道时,卖出(做空)。
*def donchian_signals(Data, onwhat, donch_up, donch_down):
for i in range(len(Data)):
if Data[i, where_close] > Data[i - 1, donch_up]:
Data[i, 6] = 1
elif Data[i, where_close] < Data[i - 1, donch_down]:
Data[i, 7] = -1
return Data# Note: The onwhat variable is the closing price*
我们选择最后的唐奇安水*,因为我们想知道我们什么时候打破我们最后的高点或低点。请记住,该公式考虑了当前的最高价和最低价,因此当前价格永远不会突破它们。
回测选择的条件更多的是长期突破,因为我们使用的是 60 天的日线图。这意味着,如果市场超过了过去 60 天的上唐奇安通道,那么我们买入趋势。我在下面的三个测试货币对中加入了一个简单的 100 点的止损单。我选择了三个主要的货币对作为这个策略的代理,它们是欧元兑美元,美元兑瑞士法郎和 GBPUSD。下面的图表显示了三个后验测试的信号图。



欧元兑美元、美元兑瑞郎和 GBPUSD 的信号图。绿色箭头表示买入订单,而红色箭头表示卖出订单。
出于比较的原因,在 10,000 美元的手数中,每笔交易 0.5 点后的净值曲线。初始余额为 1000 美元,因此杠杆比率为 1:100。

遵循唐奇安策略的权益曲线。
如果你也对更多的技术指标和使用 Python 创建策略感兴趣,那么我关于技术指标的畅销书可能会让你感兴趣:
亚马逊网站:Python 中的新技术指标:9798711128861: Kaabar,Sofien 先生:书籍
显然,它需要一些改进,唐奇安通道应该有另一个指标,以确认信号或增加波动因素,稳定结果。

唐奇安突围战略的绩效表。*
这里还可以采用另一种策略。它依赖于中间波段。我们可以尝试使用与上述相同的回溯测试条件来开发基于它们的策略。从上面的介绍中我们知道,中间波段只是上下波段的*均值,因此它可以与布林线的移动*均值相比较。如果你有兴趣了解更多关于布林线的信息,你可以查看这篇文章,我提供了更多的回溯测试:
* [## 使用 RSI 和布林线创建交易策略。使用 Python 的新想法。
绝大多数交易者使用著名的相对强弱指数来帮助他们做决定,虽然它…
因此,中间波段策略的规则是:
- 当市场超过中间波段时买入。
- 每当市场突破中间波段时,卖出(做空)。

欧元兑美元日时间框架与唐奇安 60 天中间带。
def donchian_signals_middle(Data, onwhat, donch_middle, buy, sell):
for i in range(len(Data)):
if Data[i, onwhat] > Data[i, donch_middle] and Data[i - 1, onwhat] < \
Data[i, donch_middle]:
Data[i, buy] = 1
elif Data[i, onwhat] < Data[i, donch_middle] and Data[i - 1, onwhat] > \
Data[i, donch_middle]:
Data[i, sell] = -1# Note: The buy and sell variables are the triggers (equivalent to column 6 and 7 in the first strategy code)
第二种策略的信号图如下:



欧元兑美元、美元兑瑞郎和 GBPUSD 的信号图。绿色箭头表示买入订单,而红色箭头表示卖出订单。
股权曲线就没那么令人印象深刻了。

遵循唐奇安中带策略的权益曲线。

东中带突破策略表现表。
结论
虽然第一个策略显示了一些潜力,但第二个策略未能给人留下深刻印象。很明显,唐奇安通道还有很多事情要做,但是很高兴知道我们可以尝试量化范围和交易突破。

https://pix abay . com/illustrations/entrepreneur-idea-competence-vision-4313671/*
ROC 曲线改变了我们看待分类问题的方式
没有一种机器学习算法能最好地解决所有问题
接收器工作特性(ROC) 曲线是一条概率曲线,它说明了我们的二元分类在基于真阳性率和假阳性率进行分类时有多好。
曲线下面积(AUC) 是一个范围从 0 到 1 的指标。它是(ROC)曲线下的面积。

ROC 曲线和 AUC 的示例。资料来源:Huy Bui
动机
为什么理解 ROC 曲线和 AUC 对数据科学家很重要?为了回答这个问题,我们来看看下面的乳腺癌数据集:
from sklearn.datasets import load_breast_cancer
import pandas as pddata=load_breast_cancer()
columns=data.feature_names
X=pd.DataFrame(data.data, columns=columns)
y=pd.DataFrame(data.target, columns=['Target'])
df=pd.concat([y,X],axis=1)

乳腺癌数据集:591 个观察和 30 个特征。资料来源:Huy Bui
当处理分类问题时,应该考虑准确性的折衷。如果医院使用这些数据来检测乳腺癌,模型应该强调从患者身上检测癌症的能力。该模型还需要小心翼翼地将可能被错误标记为癌症的健康患者的数量降至最低,因为癌症治疗的副作用可能会很严重。
该数据集的目标是恶性(1)和良性(0)。让我们看看下面的直方图:

良性和恶性的分布。资料来源:Huy Bui
通常,对于这种类型的问题,数据集更加不*衡。根据美国乳腺癌统计数据,12%的美国女性在其一生中将发展为浸润性乳腺癌。然而,这只是出于教育目的,我们可以忽略数据集的现实方面。
如上所述,我们需要在召回和假阳性率之间找到一个好的*衡。你可能会问为什么是假阳性率而不是精确度。提醒一下:
回忆:也叫真阳性率(TPR)。TPR 是正确的癌症预测与癌症病例总数之间的比率。从数学上来说, TPR=TP/(TP+FN) 其中 FN 是那些被错误归类为良性的。
精度:所有正确癌症与预测癌症总数之比。精度 = TP/(TP+FP)
假阳性率: FPR=FP / (TN+FP)
根据数学公式,我们可以看出精度和 FPR 之间的区别。Precision 关注模型检测癌症的能力。相反,FPR 关注的是癌症检测的失败率。如果你想了解更多,这里有一个关于精确召回(PR)和 FPR 召回(ROC)的长时间讨论。
简而言之,只有当正面类比负面类有趣得多,并且正面/负面比率很小(严重不*衡)时,我们才应该使用精确回忆。然而,在这种情况下,良性肿瘤约占恶性肿瘤的 4/7,这表明数据只是轻度不*衡。正如我们上面讨论的,错误分类的癌症可能会导致不良后果。因此,在这里使用 ROC 曲线是合理的。
注意:精确召回的方法与 ROC 曲线非常相似,你可以在这里找到它的文档。
受试者工作特征曲线
我们将要使用的模型是逻辑回归。通常,当我们进行分类时,输出已经被某个阈值四舍五入。ROC 曲线使用不同的阈值来绘制 TPR-FPR 之间的关系。因为我们想要研究 TPR、FPR 和阈值之间的关系,所以让我们在舍入之前先看看逻辑回归输出。
from sklearn.linear_model import LogisticRegressionlogreg = LogisticRegression(fit_intercept=False, C=1e12, solver='liblinear')
logreg.fit(X, y.values.flatten())
prediction=logreg.decision_function(X) #Values before the ouput#Define positive and negative
cancer_index=y[y.Target==1].index
no_cancer_index=y[y.Target==0].index
cancer_prob=prediction[cancer_index]
no_cancer_prob=prediction[no_cancer_index]#Histogram
n_bins = 20
fig, axs = plt.subplots(1, 2, sharey=True, tight_layout=True)
axs[0].hist(cancer_prob, bins=n_bins)
axs[1].hist(no_cancer_prob, bins=n_bins)
plt.show()

在做出边界决定之前,评估良性和恶性之间的频率。资料来源:Huy Bui
如果我们使用核密度估计将这两个直方图放在一起,并截断一些异常值,我们会获得一个漂亮的图形:

两类决策边界
蓝线是决策边界。它将图表分为 4 个部分:
- 纯绿色:无癌症(真阴性)
- 纯红色:癌症(真阳性)
- 左侧混合:有癌症,但被检测为无癌症(假阳性)
- 右混合:没有癌症,但被检测为患有癌症(假阴性)
注意,一个好的二进制分类模型将最小化混合区域。因此,在获得一个好的模型后,研究 ROC 曲线将告诉我们我们的模型是否在 TPR 和 FPR 之间做了很好的*衡。下面我们来看看 ROC 曲线:
from sklearn.metrics import roc_curve, auc# Normalize the Data
X = X.apply(lambda x : (x - x.min()) /(x.max() - x.min()),axis=0)
X_train, X_test, y_train, y_test = train_test_split(X, y.values.flatten(), random_state=0)y_score = logreg.fit(X_train, y_train).decision_function(X_test)
fpr, tpr, thresholds = roc_curve(y_test, y_score)def ROC_curve(fpr,tpr):
# Seaborn's beautiful styling
sns.set_style('darkgrid', {'axes.facecolor': '0.9'})print('AUC: {}'.format(auc(fpr, tpr)))
plt.figure(figsize=(10, 8))
lw = 2
plt.plot(fpr, tpr, color='darkorange',
lw=lw, label='ROC curve')
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.yticks([i/20.0 for i in range(21)])
plt.xticks([i/20.0 for i in range(21)])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic (ROC) Curve')
plt.legend(loc='lower right')
plt.show()
ROC_curve(fpr,tpr)

物流回归 ROC 曲线。资料来源:Huy Bui
模型中的虚线是随机选择(概率 50%)。因为有两类,这条线的斜率处处都是 1,因此我们得到单位正方形的对角线。注意这条线下的面积(AUC)是 0.5。
橙色线是 ROC 曲线。它位于虚线上方,表明我们的准确性优于随机选择。通过增加阈值的数值,越来越多的观察结果属于癌症类别。所以 TP 趋*于 1,FN 趋*于 0。这使得 TPR 趋*于 1 。类似地,增加阈值将导致 FP 接* 1,TN 接* 0。这会使 FPR 趋*于 1。因此,我们得出结论,FPR、TPR 和阈值彼此成正比。ROC 曲线仅显示了 2 轴 FPR 和 TPR,但是现在我们知道阈值是产生该图的混杂变量。
再看一下图表。AUC 评分为 0.96,接*完美。我们还想看看 ROC 曲线,看看在图中的哪个点我们有 FPR 和 TPR 的完美组合。例如,如果我们将当前模型调整为具有 97%的 TPR,则 FPR 大约为 6%。如果我们将 FPR 降低到 5%,那么 TPR 只有 82%。所有调整模型的不同方法都是不同领域的不同主题。
结论
我们可以使用 ROC 分析来选择基于成本背景或类别分布的可能的最优模型。ROC 分析也非常类似于诊断决策的成本/收益分析。这是一个伟大的工具,每个数据科学家都应该评估他们的分类器性能。
你可以从我的库中找到这个博客的完整代码。
请在下面留下任何评论、问题或建议。感谢您的阅读!
Python 中一个简单的遗传算法
用遗传算法优化员工计划

染色体是遗传学的重要元素。国家癌症研究所在 Unsplash 上拍摄的照片。
遗传算法
遗传算法是模拟自然选择过程的优化算法。他们没有使用“数学技巧”,而是简单地复制了一个我们知道行得通的逻辑。
遗传算法中的自然选择
这种自然选择的过程是建立在适者生存的基础上的:自然界中让最优秀的个体(动物、植物或其他)生存下来的过程。那些最适合的个体然后互相交配,产生新的一代。自然也以基因突变的形式增加了一点随机性。
新一代是好的和坏的个体的混合体,但是在这里,好的个体会生存下来,然后交配,然后产生新一代。
结果是一代又一代的持续改进。
人员规划的遗传算法
员工规划是优化研究的一个主题,在许多公司都会出现。一旦一家公司有了很多员工,就很难找到既能满足业务需求又能遵守某些约束的计划。在其他现有的解决方案中,遗传算法是解决这个问题的一种优化方法。
Python 实现
在之前的一篇文章中,我已经向展示了如何使用 Python 中的 DEAP 库来实现开箱即用的遗传算法。在这篇文章中,我将更详细地说明如何理解遗传算法的不同部分。
下面的代码是遗传算法的生产代码的简化版本。它是为了更好地理解示例而优化的,而不是为了速度和可重用性。它包含应用于示例数据的每个列出的步骤。
6 步遗传算法代码演练
遗传算法的步骤:
- 如何为遗传算法编码数据?
- 如何评价遗传算法的解?
- 如何为遗传算法编码交配(交叉)?
- 如何为遗传算法编码突变?
- 如何定义遗传算法的选择?
- 如何定义遗传算法的迭代和停止?
步骤 1——如何为遗传算法编码数据?
输入数据—两种类型的规划
在这段代码中,我们将使用两种不同形状的相同人员计划。
第一类规划——每名员工

为每个员工的遗传算法(类型 1 规划)编码数据。作者配图。
第一个形状将是员工的员工计划,详细的看法。这个每周总计划是一个包含每天列表的列表(在我们的例子中是 5 天)。每个每日列表包含一个班次列表(在我们的例子中,员工有 11 个班次)。每个班次都是一个员工 id(从 0 到 11,仅供参考)、开始时间(0 到 24 点之间)和班次持续时间(0 到 10 小时之间)的列表。
我们的员工需要这种类型的计划来了解他们何时工作。
类型 2 计划—每小时总计

遗传算法的编码数据-类型 2 规划-每小时总数。作者配图。
第二种类型的计划是每小时配备的员工总数。店主将使用该计划来决定该计划是否符合商店的估计需求。
步骤 2——如何评估遗传算法的解?
为了评估一个小时制员工计划,我们需要定义一个目标情境。定义这个目标不是优化的一部分:这将是另一个项目的问题。

定义遗传算法的评估——定义目标情况。作者配图。
我们确实需要定义如何评估提议的计划和目标计划之间的差异。这将基于小时计划,通过合计过多的员工小时总数和缺少的员工小时数来完成。这将是一个我们需要最小化的成本函数。

定义遗传算法的评估——定义成本函数。作者配图。
我们可以为人员过多或不足添加权重,但在本例中,我让它们的权重相等。
步骤 3-如何为遗传算法编码交配(交叉)?
遗传算法中有两个关键步骤:交配(也称为交叉或重组)和变异。
在交配阶段,新的一代是由亲代个体的后代形成的,就像在自然选择中一样。
为了将这一点应用到我们的例子中,考虑到以后,我们将生成许多不太好的员工计划,并试图将最好的计划结合在一起。因此,我们需要定义一种方法来“混合”两个人(员工计划)。
在本例中,我决定将代码编写如下:
- 从人群中随机选择一个妈妈
- 从人群中随机选择一个爸爸
- 创建一个与父节点大小相同的子节点,但随机填充 0 和 1。
- 孩子有 1 的位置,我们从他父亲那里得到数据,孩子有 0 的位置,我们从他母亲那里得到数据。
- 我们对每个孩子重复这个过程(孩子的数量等于人口数量)

为遗传算法定义交叉。作者配图。
这是一种方法,还有许多其他可能的方法。为了使遗传算法工作,组合码中具有随机性是很重要的。当然,组合必须符合您在步骤 1 中选择的数据结构。
步骤 4——如何为遗传算法编码突变?
遗传算法的第二个重要步骤是变异。它包括给新一代增加一个完全随机的变化。这种随机变化允许向不再存在的群体添加新值。
例如,考虑这样一种情况,其中算法已经进行了几次迭代,并且由于选择和组合过程中的随机性,它已经取消选择了上午 10 点之前的所有开始时间。如果没有突变,算法将永远无法得到这个值,尽管它可能在以后实际上给出一个更好的解决方案。
随机插入(非常少量的)新值有助于算法摆脱这种情况。

为遗传算法定义变异。作者配图。
它在这里被编码为用 0 和 10 之间的随机值替换一个班次的持续时间或开始时间。如果我们指定一个 n_mutations 值,这可以重复。
步骤 5——如何定义遗传算法的选择?
选择过程非常简单:
- 首先,选择所有可行的解决方案:去掉那些员工工作时间超过 10 小时的方案。

为遗传算法定义选择—可行性。作者配图。
- 然后,将评估函数应用到每个个体(即每个员工规划)并选择最佳个体。所选个体的数量在代码中保持可变。

定义遗传算法的选择——成本。作者配图。
步骤 6——如何定义遗传算法的迭代和停止?
代码的最后一部分是将所有前面的构建块添加到一个迭代的整体代码中。

为遗传算法定义迭代。作者配图。
优化参数调整
为了使遗传算法完美地工作,选择正确的参数是很重要的:世代大小、n 次突变和 n 次最佳在这方面很重要。
调整这三者可以找到最佳组合,使两者:
- 收敛到一个解决方案(而不是在没有改进的情况下随意转向)
- 避免陷入局部最优
如果调整后你的算法仍然停滞不前,另一个改进的方向是调整交配和变异函数,看看会发生什么。
因为这篇文章的目标是从头开始开发一个简单实用的遗传算法,所以我不会详细讨论如何找到那些最佳参数:那需要另一篇文章。
感谢您的阅读。不要犹豫,继续关注更多!
一个简单的梯度增强树解释
梯度推进树的简单介绍。
介绍
几年前,Kaggle 的官方博客“没有自由的预感”发布了一篇 Kaggle 大师本·戈尔曼(Ben Gorman)解释渐变增强的文章。文章发表后不久,我在博客上评论了这篇文章。快进到大约一年后,我正在为我的博客查看我的谷歌分析账户,我注意到我的评论得到了很多点击。在进一步的检查中,我发现原来的“没有自由的预感”文章被删除了,因此解释了为什么我的文章得到了这么多的点击(即人们在寻找原来的文章)。鉴于这些新信息,我更新了我的文章,并向人们介绍了我在 GitHub 上的一些工作,这些工作可能会有所帮助。有趣的是,我从来没有喜欢过卡格尔的原创文章。我有一些想法来真正削减脂肪和解释核心概念,这正是这篇文章!我希望这篇文章对那些刚刚开始理解梯度推进树的人有用。

在 Unsplash 上由 Belinda Fewings 拍摄的照片
最简短的解释
在梯度推进树中,我们不断地在我们的模型误差上构建决策树,并且我们使用这些误差预测来修正\更新我们的原始模型预测。

更详细的简短解释
我们建立一个决策树。这个模型对于每个数据点都有一个误差。如果我们可以在这些错误的基础上建立另一个决策树,并使用我们预测的错误来修改我们原来的预测,会怎么样?我们可以!我们可以根据错误建立另一个决策树,并使用这些预测来修改我们最初的预测。我们可以继续这个过程,直到我们决定停止!
更详细的简短解释+可视化
注意:以下图片并非来自 Jupyter 或 Python 或任何实数,我们的可视化只是在 Microsoft Paint 中创建的草图。
首先,我们有一些数据。

由作者在 Microsoft Paint 中创建
因此,我们想用 X 来预测 Y。在此之前,可以通过取 Y 的*均值来推导出一个简单的 Y 模型(所以先忽略 X),我们可以在未来的所有情况下用它来预测 Y。

由作者在 Microsoft Paint 中创建
这种模式似乎在某些方面做得不错,而在其他方面做得很差。因此,每个数据点都有一个错误,下面用红色表示。

由作者在 Microsoft Paint 中创建
如果我们可以建立一个误差模型,这样我们就可以在未来修正我们的误差(因为我们手头没有因变量)。嗯,我们可以!

由作者在 Microsoft Paint 中创建
上面我们看到了 X 的残差图,我们可以使用 X 来帮助预测第一个模型的残差。这个模型说我们想要增加 X 低端的值,减少所有其他的值。我们可以用这些预测来更新我们原来的预测!

由作者在 Microsoft Paint 中创建
所以我们采用了最初的预测,并用第二个模型的预测误差对它们进行了修正。
我们可以一遍又一遍地继续这个过程。实际上,我们通常使用“学习率”来只取误差\误差更新的一小部分。当我们多次运行(包括学习率)时,我们可能会得到如下结果。

由作者在 Microsoft Paint 中创建
就是这样!
你可以看到这个算法是如何得到它的名字的,它的灵感来源于梯度下降。
技术细节和演示
要了解更多技术细节,以及使用 Python 的演示,您可以点击这里查看我在 GitHub 上的分类示例。
概括起来
- 梯度推进树只是根据我们的模型误差不断构建决策树的过程,我们使用这些预测来修改\更新我们的原始模型预测。
- 关于使用数据和代码的演示,你可以点击这里查看我在 GitHub 上的分类示例。
感谢阅读!!😄
数据科学 A/B 测试简单指南
数据科学家最重要的统计方法之一

图片由我、Terence Shin 和 Freepik 创建
查看我的文章' 假设检验尽可能简单的解释 '如果你还不知道什么是假设检验的话先!
A/B 测试是数据科学和整个技术世界中最重要的概念之一,因为它是对任何假设做出结论的最有效的方法之一。理解什么是 A/B 测试以及它通常是如何工作的很重要。
目录
什么是 A/B 测试?
从最简单的意义上来说,A/B 测试是对两个变量进行的实验,根据给定的度量标准来看哪一个表现更好。通常,两个消费者群体接触同一事物的两个不同版本,以查看会话、点击率和/或转化率等指标是否有显著差异。
以上面的图片为例,我们可以将我们的客户群随机分成两组,一个控制组和一个变异组。然后,我们可以用一个红色的网站横幅来展示我们的变体组,看看我们是否会获得显著的转化率增加。需要注意的是,在执行 A/B 测试时,所有其他变量都需要保持不变。
更专业地说,A/B 测试是一种统计和双样本假设测试。统计假设检验是一种将样本数据集与总体数据进行比较的方法。双样本假设检验是确定两个样本之间的差异是否具有统计显著性的方法。
为什么知道很重要?
了解什么是 A/B 测试及其工作原理非常重要,因为这是量化产品变化或营销策略变化的最佳方法。在一个数据驱动的世界里,这一点变得越来越重要,因为商业决策需要事实和数字的支持。
如何进行标准的 A/B 测试
1.阐明你的假设
在进行 A/B 测试之前,您需要陈述您的零假设和替代假设:
零假设是指样本观察结果纯属偶然。从 A/B 检验的角度来看,零假设表明对照组和变异组之间没有差异。
替代假设是指样本观察值受到一些非随机原因的影响。从 A/B 测试的角度来看,另一种假设认为对照组和变异组之间存在差异。
当开发您的空假设和替代假设时,建议您遵循 PICOT 格式。皮科特代表:
- 人群:参与实验的一群人
- I 干预:指研究中的新变体
- C 比较:指的是你计划用来与你的干预措施进行比较的参照群体
- O utcome:表示您计划测量的结果
- ime:指体验的持续时间(收集数据的时间和时间)
实施例:“与对照干预相比,干预 A 将改善在 3 个月时具有临床焦虑水*的癌症患者的焦虑(通过 HADS 焦虑子量表中相对于基线的*均变化来测量)。”
它是否遵循 PICOT 标准?
- 人群:具有临床焦虑水*的癌症患者
- 干预:干预 A
- 对比:对照干预
- 结果:通过 HADS 焦虑分量表中基线的*均变化来衡量焦虑的改善
- 时间:与对照干预相比的第 3 个月。
是的,确实如此——因此,这是一个强假设检验的例子。
2.创建您的对照组和测试组
一旦你确定了你的无效假设和替代假设,下一步就是创建你的控制和测试(变量)组。在这一步中,有两个重要的概念需要考虑,随机抽样和样本大小。
随机抽样
随机抽样是一种技术,在这种技术中,群体中的每个样本都有均等的机会被选中。随机抽样在假设检验中很重要,因为它消除了抽样偏差,而消除偏差也很重要,因为你希望你的 A/B 检验结果能代表整个群体,而不是样本本身。
样本量 在进行 A/B 测试之前,确定测试的最小样本量是非常重要的,这样你就可以消除覆盖偏差,即由于采样太少而产生的偏差。有很多在线计算器可以用来计算这三个输入的样本量,但是如果你想了解背后的数学原理,请点击链接!
3.进行测试,比较结果,拒绝或不拒绝零假设

一旦你进行了实验并收集了数据,你想确定你的控制组和变异组之间的差异是否有统计学意义。确定这一点有几个步骤:
- 首先,你要设置你的 alpha ,犯类型 1 错误的概率。通常,alpha 设置为 5%或 0.05
- 接下来,您希望通过首先使用上述公式计算 t 统计量来确定概率值(p 值)。
- 最后,将 p 值与 alpha 值进行比较。如果 p 值大于 alpha,不要拒绝 null!
如果这对你没有意义,我会花时间在这里 学习更多关于假设检验的知识 !
更多类似的文章,请看 https://blog.datatron.com/的
感谢阅读!
如果你喜欢我的工作,想要支持我,请在我的电子邮件列表这里注册!
参考
A/B 测试(也称为桶测试或分割测试)是一个随机实验,有两个变量,A 和 B。它…
en.wikipedia.org](https://en.wikipedia.org/wiki/A/B_testing)
Python 中 A/B 测试的简单指南
可视化和模拟数据

桌子上的两个苹果 由保罗·塞尚、公有领域
A/B 测试是一项至关重要的数据科学技能。它通常用于测试网站 A 与网站 B 或药物 A 与药物 B、的有效性,或者具有相同主要动机的一个想法的任何两个变体,无论是销售、药物疗效还是客户保留。这是容易产生额外混乱的统计概念之一,因为假设检验本身就需要理解正态分布、z 值、p 值和零假设的仔细构建。对于 A/B 测试,我们有两个样本要处理。然而,A/B 测试本质上仍然只是假设测试!本指南将是简单的单样本假设检验到双样本假设检验或 A/B 检验的基本演练。
简单的单样本假设检验
让我们考虑苹果农民的领域和苹果大小。我们知道,在历史上,一组特定果园中的红苹果*均宽度为 3.5 英寸,标准偏差为 0.2 英寸。因此:

总体均值和标准差
但是农民麦金托什声称他的果园里有一种特殊的新型红苹果,比其他农民的苹果格外美味,而且个头也更大。分别构建零假设和替代假设,或𝐻0 和 H1:

显著性水*为 5%
α选择 5%的显著性水*,这是单样本假设检验的标准显著性水*,也是统计学家和研究人员之间有点随意的约定。假设我们从农民麦金托什的果园里取了 40 个苹果样本,每个苹果*均 4 英寸,样本标准偏差为 0.5:

我们现在有了进行测试所需的一切。为了刷新任何假设检验背后的逻辑,看一下下面获得检验统计量的等式:

这个想法是我们取 x-bar,这是我们的样本均值,找到它与总体的差异意味着样本可能来自。在这种情况下,是 3.5,然后除以标准误差,得到我们的测试统计量:

提醒一下,测试统计是一个指标,表明假设零假设为真,我们有多大可能完全随机获得这个样本。标准正态表,或者 z-score 表,可以用来求正态曲线下对应的面积,就是偶然得到那个结果的概率。在 Python 中,scipy.stats是一组非常有用的内置函数,用于此目的,scipy.stats.norm.cdf和scipy.stats.norm.sf分别给出了测试统计数据在正态分布下的面积。在这种情况下,6.32 是一个非常高的检验统计量,相当于偶然获得这些苹果大小的概率极低:

因为我们的 alpha 被设置为 0.05,所以我们可以使用st.norm.isf(.05)来确定临界值,如果我们的测试统计超过了这个临界值,我们就可以拒绝零假设。在这种情况下,临界值计算为1.64,这是一个常见且可识别的数字,因为在正态假设下,它总是α为 0.05 的临界值。我们的测试统计值是 6.32,这远远超过了临界值,所以我们可以安全地拒绝零假设,并说农民麦金托什肯定生产大于*均水*的苹果。
用模拟数据进行 A/B 测试
现在我们已经完成了单样本假设检验的过程,让我们看一些模拟数据来感受一下双样本检验,记住 A/B 检验在一天结束时仍然是检验一个零假设和一个替代假设。Jupyter 笔记本和数据可以在我的 Github 上找到,我鼓励您亲自实际运行一些函数,以便获得数据的实际感受,即使您只是改变随机种子来见证采样是如何变化的。
这是一千个随机生成的正态分布的点,使用sklearn.datasets.make_gaussian_quantiles.创建,我们称之为我们的总体:
pop, ignore_classes = make_gaussian_quantiles(n_samples=1000, n_features = 2, cov=1, n_classes=1, random_state=0)plt.figure(figsize=(15,10))
plt.scatter(pop[:,0], pop[:,1], s=5, color='cornflowerblue')
plt.show()

为了简单起见,让我们将测试的范围限制在 x 轴上。这意味着这些可视化可以在一个数字线上,但是二维可以让我们更容易地可视化随机样本的分布。
现在让我们从这个群体中随机抽取两个 30 人的样本:
rand1 = np.random.choice(range(1000), 30, replace=False)
rand2 = np.random.choice(range(1000), 30, replace=False)sample1_x = pop[:,0][rand1]
sample2_x = pop[:,0][rand2]

我们的第一个样本*均值(红色)是-.23,样本标准偏差是 0 . 93,第二个样本*均值(绿色)是-.13,样本标准偏差是 0 . 99。因为我们知道真实的总体均值和标准差(因为最初的一千个点是从正态分布生成的)是 μ =0 和 σ =1.0,所以我们可以有把握地说这些样本很好地代表了总体。但是他们的代表性如何呢?看起来两种手段都有点低于真品。在这一点上,我们会产生怀疑,说也许这些样本完全来自不同的人群?这个问题就是 A/B 测试试图回答的。
就像单样本假设检验一样,我们有一个两个样本的检验统计公式。尽管它看起来要复杂得多,但它仍然只是零假设和替代假设之间的差异除以标准误差:

两个样本的检验统计公式
本质上,即使我们处理两个样本,我们仍然假设两个样本都来自正态分布,因此在两个样本测试的零假设下,我们假设样本均值之间的差异为零。这有效地将两个样本的检验简化为一个单一样本的假设检验。挑选显著性水*(alpha)和寻找临界值的过程几乎是相同的。
以下代码片段演示了一个用于 A/B 测试的 Python 函数,其中包含一个用于设置不同 alphas 的选项:
def ab_test(sample_A, sample_B, alpha=.05):
mean_A = np.mean(sample_A)
mean_B = np.mean(sample_B)
std_A = np.std(sample_A)
std_B = np.std(sample_B)
standard_error = np.sqrt((std_A**2)/len(sample_A) + (std_B**2)/len(sample_B))
difference = mean_A - mean_B
test_statistic = difference/standard_error
crit = st.norm.ppf(p_value/2)*-1
reject_status = 'Reject Null Hypothesis' if crit < test_statistic else 'Fail to Reject Null Hypothesis'
return 'Test Statistic: ', test_statistic, 'Critical Value: ', crit, reject_status
让我们看看,我们获得这些样本*均值(我们知道它们的差值应该为零)的可能性有多大,这完全是因为偶然:

我们对这两个样本的检验统计量非常接*于零,这是应该的,所以显然我们拒绝零假设,因为这两个样本的均值都应该是零。
然而,让我们不断地创建随机样本,直到我们通过将α设置为. 0001 而获得两个非常不可能的样本,这将允许我们拒绝零假设:

需要 26,193 次随机抽样才能产生足够的样本均值来拒绝零假设!由于仅有一对随机样本的纯粹偶然性,这种情况发生的可能性是 0.002%。让我们想象一下这些例子:

我们可以看到大部分红点在零的右边,大部分绿点在左边,然而我们获得这两个样本纯属偶然(经过 26193 个做作样本)!
这里的要点是,对于真实数据,我们不知道两个样本是否来自不同的人群,我们必须依靠 A/B 测试来告诉我们样本是否真的足够不同,从而可以自信地对他们的人群做出断言。
对于测试不同网站版本或药物功效的公司来说,这是至关重要的信息,并且具有更高的显著性水*,如. 05,实际上获得允许我们基于纯粹的机会错误地拒绝零假设的样本是相对常见的(也称为 I 型错误)。因此,通常会引入修正,如 Bonferroni 的修正,以减少因参数空间增加而产生的误差,这被称为多重比较问题或别处查看效应。
和往常一样,在对数据做出强有力的声明之前,了解数据的里里外外是很重要的,即使在运用统计测试和执行 A/B 测试时也是如此,因为虚假但明显的统计显著性在许多领域都很普遍,并且很容易获得看似不可能的样本数据,即使在上面的例子中花费了人为的努力(即使将这个 Jupyter 笔记本中的随机种子改为 42,由于“运气”,我们也可以获得两个样本均值,这两个均值允许我们在 0001 的α水*上拒绝零假设。试试看。)
自己处理数据确实有助于理解测试背后的统计直觉,尤其是 A/B 测试,因为有这么多移动的部分。但是所有的假设检验实际上都是同样的程序。所以生成一些数据,自己试试,感谢阅读!
卷积神经网络的简单指南
卷积神经网络揭秘没有任何花哨的技术术语!

识别人和物体的卷积神经网络(来源)
汽车可以识别路标。脸书知道你最好朋友的名字。可以用脸解锁手机。这都是由魔法完成的。
我只是在开玩笑,这里没有魔法,只是简单的,古老的数学。但是严肃地说,我刚才提到的所有东西都是 卷积神经网络的例子。
但是在深入研究卷积网络的代码之前,让我们先了解一下什么是卷积神经网络(CNN)以及它是如何工作的。
第 0 部分:什么是 CNN?为什么要用?
那么,我们为什么要使用 CNN 而不是另一种类型的神经网络,比如多层感知器?这是因为 CNN 能够提取图像的特征,而像多层感知器(MLP)或递归神经网络(RNN)这样的算法不具备这种能力。
卷积神经网络的架构如下所示:

卷积神经网络的架构
我们应该从中注意到一些事情。网络从 2 个卷积和最大池层、开始,接着是 2 个全连接层,以一个输出层结束。卷积+最大池图层是识别影像(提取要素)的位置,完全连接图层是将影像分类到预定义类别的位置。
第 1 部分:图像识别
卷积神经网络中的第一部分过滤图像以从图像中提取特征,然后它汇集提取的特征以减少数据的大小,最后添加激活函数,使得网络是非线性函数。这可以归结为卷积 + 汇集+激活层。
盘旋
过滤器是从图像中提取特征的矩阵(这是学习发生的地方)。滤波器值和图像像素值之间的点积形成卷积层。
过滤张量是一个权重矩阵。每当网络执行反向传播时,滤波器矩阵中的值被更新。然而,滤波器矩阵的维数由程序员明确确定。

将滤波器张量与图像的像素值张量相乘。(来源)
在 CNN 中,有许多不同的过滤器来提取图像中的各种特征。随着我们在网络中前进,从图像中提取的特征变得越来越具体。让我们以停车标志为例。
由于第一层中的过滤器用于检测易于识别的特征,因此这可能是停车标志的八角形形状。第二层中的过滤器将用于检测更具体的内容,如文本“停止”。第三层中的过滤器可以用来检测更具体的东西,如“STOP”中的字母“S”。
在 Keras(tensor flow中的深度学习框架)中,第一个卷积层的代码如下所示:

注意:我不会太深入地讲述代码是如何工作的,但我会简单谈谈架构。
所以在这里,我的卷积层是 16 X 16 X 3,一个 5 X 5 的过滤器。程序员必须明确定义滤波器的维数,但滤波器中的值是网络自学的。
联营
在图像通过第一个过滤器后,它将继续到池层。池层减小了过滤层的大小,这使我们可以更快地训练模型。此外,它通过丢弃滤波器张量中不需要的值来防止过拟合。
一种流行的汇集方法被称为最大汇集。这与滤波过程相同,但这次我们取最大值,而不是点积。看看下面的动画:

最大池层的动画
鲁热
现在,我们要增加数学。Re-Lu(校正线性单元)是神经网络中常用的激活函数。激活函数用于向神经网络添加非线性。这使得我们能够解决比我们的网络只是一个线性函数更复杂的问题。如果我们的网络中从来没有激活函数,它将是一个简单的线性回归算法。

Re-Lu 激活功能(源)
Re-Lu 激活函数是一个只有当值大于零时才返回值的函数,有助于减少训练时间。
第 2 部分:图像分类
既然卷积层已经提取了图像的所有特征,那么是时候对图像进行分类了。
在完全连接的层中,每个神经元都与它之前和之后的层中的所有其他神经元共享连接。这就是为什么它被称为“完全连接”层。下面是它们的样子:

CNN 中的全连接层(来源)
变*
在将我们复杂的输入输入到一个密集(全连接)层之前,我们必须展*张量(我们的输入)。扁*化就是把多维输入张量变成一维输入张量。例如,假设最后的卷积层输出一个(28,28,3)张量。展*此输出将为下一层提供(2352,1)的输入。2352 来自于乘以 28 X 28 X 3,这是前面输出张量的维数。

展*汇集张量的例子(来源)。
这意味着图像中总共有 2352 个像素。扁*化允许我们分析每一个像素,因为现在,图像中的每一个像素都有自己的神经元。
拒绝传统社会的人
输入展*后,它会穿过密集层。密集层完成了它的任务,然后就在我们到达最后一个密集层之前,我们做了一件叫做辍学的事情。放弃神经元是将一些输出神经元随机设置为零,只是为了加快训练和反向传播过程,并防止过度拟合我们的网络。
第 3 部分:训练网络
你刚刚学会如何建立一个 CNN,但一个未经训练的网络有什么用!要掌握 CNN 的艺术,你也必须知道如何训练他们。在本文中,我将讨论 CNN 中使用的损失函数和优化器。
损失函数
简而言之,损失函数是一种计算数据精确度的方法。任何优化问题(任何神经网络)的目标都是最小化代价函数。
有各种类型的损失函数。在 CNN 的,使用的损失函数是交叉熵。交叉熵计算概率分布(可以是向量、矩阵、张量等)之间的差异。)和标签的概率分布。
在我们的例子中(在 CNN 中),数据用向量表示。交叉熵损失计算标签向量(y)中每个元素与网络输出向量(X)之间的差值,然后将所有这些值相加,得出网络的总损失。

交叉熵损失的可视化(来源:Udacity
那里陈述的公式包括一些非常密集的数学符号,所以如果你想在数学上更深入,我建议你去下面的链接。然而,你不需要精通数学来写 CNN(特别是在像 Keras 或 Pytorch 这样的框架中,因为你只需要写“loss = cross _ entropy”,Keras/Pytorch 会处理剩下的)。
最佳化
机器学习中的优化是找到将返回最低成本(损失)的最佳权重/偏差。优化器就是一种能做到这一点的算法。在 CNN(和大多数其他深度神经网络)中,我们使用 Adam 优化器。
如果你真的有兴趣学习更多关于 Adam 优化器的知识,戴上你的统计学和微积分头盔,点击下面的链接。
Adam 是一种自适应学习率优化算法,专为训练深度神经…
towardsdatascience.com](/adam-latest-trends-in-deep-learning-optimization-6be9a291375c)
像以前一样,您不需要理解优化器如何工作背后的本质数学。在 Keras 中,使用 Adam 优化器仅仅是一行代码( optimizer="Adam")
这是一个总结!
厉害!你现在知道了 CNN 的基本知识,所以现在你应该选择一个你真正热爱的 CNN 项目,这样你就可以去应用你刚刚学到的东西。同时,看看下面这个很棒的教程,在那里我学会了如何写一个路标分类器!
在本教程中,您将学习如何训练自己的交通标志分类器/识别器能够获得 95%以上的…
www.pyimagesearch.com](https://www.pyimagesearch.com/2019/11/04/traffic-sign-classification-with-keras-and-deep-learning/)
关键要点
总结一下这一切:
- CNN 是一种深度神经网络,通常用于图像数据和复杂的分类问题。
- CNN 的架构涉及各种类型的层,包括:卷积、最大池化、密集、丢弃。
- 卷积层通过将过滤矩阵与图像张量相乘,从图像中提取特征信息,创建图像的过滤层。这是所有学习发生的地方
- 然后,合并过滤层(过滤层的大小减小)。这是通过最大池完成的。
- 在图像通过几个卷积+最大池层后,它得到展*并进入密集层。
- 在致密层完成它的工作后,一些神经元被随机丢弃以防止过度拟合。
- 我们使用 Adam 优化器和交叉熵损失来训练我们的模型。
现在是时候建立你自己的 CNN 了!
了解你的神经网络和激活的简单指南。
分析哪个功能似乎合适

生物神经网络一览。
为了更好地理解激活函数的意图和目的,让我们分析一下我们自身的一个等效模型——神经元(首先是神经网络的灵感)。一个生物神经网络简单来说就是由一个细胞 体,树突(来自神经元的输入)和轴突(输出到其他神经元)。一个有用的术语是突触,它来自一个神经元与另一个神经元通信的接触点。树突上覆盖着由其他神经元轴突末端形成的突触。来自所有树突的突触在细胞体中累积,细胞体根据累积跨越的阈值(类似于各种激活功能)确定细胞的状态激活/未激活。然后这些突触穿过轴突,到达沿途交流的其他神经元。

神经元的简单解剖
人工神经网络
人工神经网络确实保持了其生物学等效物的完整性,尽管多了一些术语。
重量
偏差

神经元的处理过程
输出=σ(权重*输入)+偏差
这遵循线性方程y = MX+c其中权重对应于“m ”,偏差对应于“c”
重量(瓦特)
权重,通常是突触权重,代表一个神经元对另一个神经元的强度,使整体连接更强。
偏见
作为截距,偏差项使网络符合实际情况,而不是理想情况。如果缺少偏差项,训练点将只通过原点,这是一个太简单的分析。一个网络往往是更强大的偏差项,因为它是开放的,以新的方式考虑和拟合。此外,它还决定了激活功能生效的时间点。
选择您的激活功能
现在,我们已经对生物神经网络和人工神经网络进行了基本的比较,我们将看看各种激活函数,并检查它们的优点和局限性。
每个激活函数取一个值,并对其执行数学运算。
1.乙状结肠的

乙状结肠的
- 它接受一个实数值,并将其压缩到范围[0,1]内
- 其数学形式:σ(x)= 1/(1+e x)
但是,由于以下限制,它很少实现:
- 乙状结肠饱和,从而消除梯度 当激活在 1,0 达到饱和时,梯度减小到零。
因此,在反向传播期间,该零梯度与梯度输出相乘,产生一个非常小的数字,阻碍信号流过权重和输入。 - 非零中心输出 如果进入神经元的数据总是正的,则反向传播期间的权重将产生全正或全负的梯度。这导致梯度更新中不期望的行为。
2。Tanh

双曲正切
虽然与 sigmoid 函数相似,但 tanh 函数解决了它的一个限制:非零中心输出。
- tanh(x)= 2σ(2x)1
- 它将一个实数值压缩到[-1,1]范围内
局限性:
- 它在与它的乙状结肠对应物相同的线上饱和。
3.热卢

热卢
- f(x)=max(0,x)
- 随机梯度的收敛速度大约加快了 6 倍。
- 它将激活矩阵的阈值设置为零,并且由于没有指数或缺少指数,所以成本较低。
- 随着 x 的增加,不存在饱和。
- 然而,它提出了“垂死的 ReLU”问题的局限性。
当零处的梯度为零时(当 x <为 0 时),一个垂死的 ReLU 对任何输入产生相同的输出。梯度学习不会改变权重。 - 这是由于
-一个非常高的学习率
-一个大的负偏差
4。泄漏的 ReLU

泄漏的 ReLU 和 PReLU
泄漏的 ReLU 试图解决垂死的 ReLU 问题的局限性。
- 当 x < 0.
例如 y = 0.01x 时,泄漏 ReLU 具有小的负斜率 - 参数 ReLU ( PReLU)是泄漏 ReLU 的变体,其中斜率被视为要调整的参数。α代表斜率参数。y =α x
- 因此,由于负值斜率的存在,它确实会对相应的输入产生一个输出,从而产生变化。
- 然而,泄漏的 ReLU 并不总是一致的。
所以,问题。我应该选择哪个激活功能?
避免使用 sigmoid 函数。您可以选择 ReLU 或泄漏 ReLU(作为 ReLU 函数的替代)。不过,要监控你的学习速度。
你可以给 Tanh 一个机会,但是它可能产生比 ReLU 更差的结果。
资源
[## 用于视觉识别的 CS231n 卷积神经网络
斯坦福 CS231n 课程材料和笔记:视觉识别的卷积神经网络。
cs231n.github.ioo](http://cs231n.github.io/) [## ReLU -人类的机器学习- TinyMind
TL;DR: ReLU 代表整流线性单位,是一种激活函数。数学上定义为 y…
www.tinymind.com](https://www.tinymind.com/learn/terms/relu) [## 人与机器:人工神经网络和生物神经网络的比较
学习能力被认为是智慧生命的标志之一。机器学习现在有能力学习和…
news.sophos.com](https://news.sophos.com/en-us/2017/09/21/man-vs-machine-comparing-artificial-and-biological-neural-networks/)
面向数据科学家的面向对象编程简单指南
如何轻松阅读复杂的 Python 包?

作为一名数据科学家,您可能不会像开发人员那样每天都编写面向对象(OO)代码。在您的整个职业生涯中,您可能永远都不需要编写 OO 代码!然而,在不知不觉中,您每天都在通过使用包和框架与面向对象编程(OOP)进行交互。关键的数据科学库,如 pandas、numpy 和 scikit-learn 都严重依赖 OOP。
看看这些库的源代码,它们充满了类、方法、属性等等。你可能还想知道为什么你需要声明一个回归模型(例如)作为一个类的实例,然后运行一个 fit 方法来训练你的机器学习模型。
如果你是一个非常好奇的人,你可能想阅读和理解一个很酷的机器学习包的源代码。理解 OOP 可以帮助你轻松做到这一点。如果有一天你想写一个 Python 包或者框架,这些知识将是极其有价值的。
在这篇文章中,我将解释一些主要的 OOP 原则来帮助你开始。
*Edit 2022:你也可以在我的 Youtube 频道上观看下面这篇整篇文章的视频版本,我在其中更详细地描述了 OOP 概念。
首先,我们为什么需要 OOP?
如果我们不知道 OOP 能解决什么样的问题,我们就无法理解和欣赏它。
我们大多数人害怕意大利面条式的代码,因为它太混乱了,难以阅读和维护。但是意大利面代码是如何创建的呢?

意大利面条代码。来源:作者。
看看这个代码结构。希望你看着眼熟:)。我们可以看到 5 个不同的函数相互调用,还有一堆全局变量被一个或多个函数访问和使用。想象一下这个结构扩展几倍,事情会变得非常混乱,难以理解。OOP 通过两个原则解决了这个问题:封装和抽象。
包装

OOP 将变量和函数从我们上面的意大利面条式结构中组合在一起,形成称为“对象”的实体。对象内部的变量称为属性/特性,函数称为方法。把属性想象成一个物体的特征(比如一只猫有蓝色的眼睛)。另一方面,方法本质上是一个对象做事情的能力(比如一只猫知道怎么抓老鼠,会说“喵”)。
对象通过引用彼此的属性和调用彼此的方法进行交互。
封装使得代码更容易复制和维护。如果我们想将一个对象复制成 10 个对象,我们只需复制整个对象,而不是复制对象中的每个变量和函数。
抽象

当我们不希望其他对象访问和修改一个对象的属性时,我们对其他对象隐藏这些属性。理想情况下,只有一个对象的基本元素通过该对象的接口对其他对象可用。
这就是所谓的“抽象”。我们的手机是抽象的例子。它们的界面只为我们提供了使用它们的相关手柄,但芯片和存储卡等东西对我们来说是隐藏的。
Python 中的 OOP
在 Python 中,类用作创建对象的代码模板。这类似于 JavaScript 中的构造函数。
使用类的构造函数创建对象。这个对象将被称为类的instance。在 Python 中,我们以下列方式创建实例:
Instance = class(arguments)
让我们看下面一个类的例子:

类的例子。来源:作者
一个类中的函数不能直接访问该类的属性,就像我们通常认为的“全局变量”一样。相反,我们需要使用self关键字来访问类的属性。这也类似于 JavaScript。在 Python 中,self关键字总是放在第一个参数中。
要实例化该类,我们只需调用:
>>> MySuperCuteCat = SuperCuteCat()
你也可能经常在 Python 类中看到 __init__方法。这个方法只是用来初始化一个类的几个属性。
我希望这篇文章能让你对 OOP 有一个更清晰的认识,并帮助你作为一名数据科学家更好地理解 Python 包和框架。如果你有兴趣学习更多关于面向对象的知识,这个页面可能会很有趣。
感谢您的阅读!享受学习。
一个简单的指标添加到您的交易系统
提出一个简单的指标概念,应该包含在你的交易框架中
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
金融研究是一个无穷无尽的令人兴奋的领域,有许多“找到了”和“哦,不!”瞬间。我们总是在寻找那个一直有效并让我们晚上睡得好的黄金策略,但是我们经常会遇到“哦,不!”瞬间。这很正常,我们是在大海捞针,针是一个体面的策略,而大海捞针是想法的无限可能性。
刚刚在 Python 中 新技术指标成功后出了新书。它对复杂的交易策略进行了更完整的描述和补充,Github 页面致力于不断更新代码。如果你对此感兴趣,请随时访问下面的链接,或者如果你喜欢购买 PDF 版本,你可以在 Linkedin 上联系我。
亚马逊网站:交易策略之书(9798532885707): Kaabar,Sofien:书籍
有时候,简单是成功的关键。我们不需要几十个技术指标到处发出信号,到头来却发现自己成了净输家。我们必须了解关于技术指标的两件事:
- 它们是价格衍生的。这意味着他们取价格,分解价格,了解一些特征。因此,他们不是向前看,而是向后看。我们希望这种落后的关系在未来继续下去。例如,如果我们看到 RSI 出现背离,我们希望它会像往常一样导致价格衰竭。这种背离并没有窥视未来,它只是一个简单的数学观察。
- 他们不太可能独自提供成功的策略。如果是这样的话,那么为什么我们不都是依靠随机指标上的超买/超卖区成为百万富翁呢?交易比这复杂得多,需要更全面的方法来发现有利可图的交易。
考虑到这一点,我们应该把指标看作是我们信念的小帮手。例如,当我们发现足够的信息告诉我们做多(购买)一项资产时,我们可以检查技术指标,看看它们是否证实了这一点。我们还应该检查当前的市场状态,以了解指标是否会提供良好的信号。这意味着当我们处于趋势市场时,我们不应该使用均值回复指标。下图显示了原因。这是 RSI 在上升趋势市场中给出的卖出信号。请注意蓝色矩形内的价格趋势,很明显,信号的质量很差。

RSI 信号图——欧元兑美元每日时间框架。(图片作者)
现在,我们可以试着从一个很简单的想法中找到一个简单的指标,那就是归一化。标准化的好消息是,买卖条件已经列出来了,而且很直观,因此,我们要做的就是找到一个合适的周期(如 RSI 中的 14 默认周期)。我们将看到如何在不偏离指标的情况下找到这个周期。
规范化的概念
这个伟大的技术允许我们捕捉 0 和 1 之间的值(或者 0 和 100,如果我们想乘以 100 的话)。这个概念围绕着从当前值中减去某个回望周期中的最小值,再除以同一回望周期中的最大值减去最小值(在命名器中相同)。

(图片作者)
我们可以尝试用 python 编写这个公式。以下函数对给定的 OHLC 类型的时间序列进行归一化处理:
def normalizer(Data, lookback, onwhat, where):
for i in range(len(Data)):
try:
Data[i, where] = (Data[i, onwhat] - min(Data[i - lookback + 1:i + 1, onwhat])) / (max(Data[i - lookback + 1:i + 1, onwhat]) - min(Data[i - lookback + 1:i + 1, onwhat]))
except ValueError:
pass
Data[:, where] = Data[:, where] * 100return Data# The **onwhat** variable is what to normalize and the **where** variable is where to print the normalized values, i.e. which colum.
如果我们将该函数应用于欧元兑美元每日时间框架的收盘价,并有 50 个回望期(也就是说,该函数将查看最后 50 个值,并从中选择最小值和最大值),我们将得到下图。

欧元兑美元每日时间框架及其标准化值。(图片作者)
现在,如果我们形成一个简单的策略,当归一化值等于 0 时买入,当归一化值等于 100 时做空,我们得到下图。这些信号似乎确实捕捉到了一些顶部和底部。就其本身而言,这是一个良好的开端,因为选择 50 是完全随意的。为简单起见,我们可以称归一化值:归一化指数(NI) 。
如果你也对更多的技术指标和使用 Python 创建策略感兴趣,那么我关于技术指标的畅销书可能会让你感兴趣:
亚马逊网站:Python 中的新技术指标:9798711128861: Kaabar,Sofien 先生:书籍
欧元兑美元遵循 50 天标准化指标的信号图。(图片作者)
然而,我们希望从这种奇妙的技术(即规范化)中提取尽可能多的价值。怎么会?基本想法是这样的:
我们不想说 20 天周期比 50 天周期更适合标准化,因此我们可以形成一个全标准化指数(ANI ),它使用从 2 到 100 的回顾周期,并相应地对它们进行加权。这样,我们将有一个加权的标准化指数,它考虑了广泛的回望期。
如果 10 天期标准化指数显示值为 40,那么它在全标准化指数中的真实值为 40 / 100 = 0.40。因此,我们将拥有一个由 100 个规范化索引器组成的介于 0 和 100 之间的索引。
用 Pythonic 语言来说,我们将有以下创建全规范化索引(ANI)的循环语句,请记住,我们仍然处于 OHLC 数据结构中(第 0 列表示开放,第 1 列表示高,第 2 列表示低,第 3 列表示关闭):
# Starting from column 4 (i.e. the first Normalized Index)
b = 4# Looping and adding 1 so that the correct column will be populated
for a in range(2, 102):
Asset1 = normalizer(Asset1, a, 3, b)
b = b + 1# Formatting
normalized_values = Asset1[:, 4:104]# Calculating the ANI
all_normalizer = np.sum(normalized_values, axis=1) / 100# Reshaping
all_normalizer = np.reshape(all_normalizer, (-1, 1))
Asset1 = deleter(Asset1, 4, 110)# Concatenating the OHLC Data with the ANI
Asset1 = np.concatenate((Asset1, all_normalizer), axis = 1)
Asset1 = adder(Asset1, 10)
Asset1 = Asset1[102:,]
让我们看看我们的新指标是什么样的。剧透警报,看起来像个指示器。顺便说一句,如果你喜欢通过 Python 研究和回测策略,那么我写的这本书可能会让你感兴趣, 《回测之书:客观交易:回测和揭秘交易策略 。

与 ANI 的欧元兑美元每日时间框架。(图片作者)
因此,上述指标是一百个标准化索引器的*均值,给我们的信号似乎稍微好一点(我们总是可以优化它)。让我们检查下面的信号图。

ANI 之后的欧元兑美元信号图。(图片作者)
我们可以在 ANI 上添加我们的触觉,因为信号有点稀少。加个 8 日均线怎么样?这可以根据均线何时穿过 ANI 给我们一些信号。下图说明了前一点,我们有更多的信号,移动*均线做得很好,*滑了 ANI。

与 ANI 和 8 日均线的欧元兑美元每日时间框架。(图片作者)
如果您对另一个标准化指标感兴趣,请查看我写的这篇文章:
[## 标准化的布林线指标。另一种交易范围的方式。Python 中的回溯测试。
深入挖掘并修改布林线。
结论
这个指标有什么用?嗯,衡量动量是交易中的一个关键概念,标准化指数通过使用纯粹的收盘价数据完美地做到了这一点。如果随机振荡器使用稍微修改的归一化版本,那么后者可以帮助我们看到纯粹的收盘动量。如果你想取消一步棋,你可以向 ANI 确认你的观点。
经验法则是,如果 ANI 的读数高于 95,那么它支持你的看跌观点,如果 ANI 的读数低于 5,那么它支持你的看涨观点。我们可以使用 ANI 的另一个方法是它的移动*均线交叉。当然,8 期 MA 是个人选择,如果更适合你可以选择另一期。

图片由皮克斯拜的 Gerd Altmann 提供
Python 正则表达式的简单介绍
我们将通过一些在 Python 中使用 Regex ( 正则表达式 )的基本例子,展示这个框架如何用于强大的文本处理。

图片来源: Pixabay(免费商业使用)
介绍
文本挖掘是当今数据科学的一个热门话题。文本数据的数量、种类和复杂性正以惊人的速度增长。
根据本文,2019 年全球文本分析市场价值为 54.6 亿美元,预计到 2025 年将达到 148.4 亿美元。

正则表达式用于 识别 一个模式是否存在于一个给定的字符序列(字符串)中,也用于 定位 该模式在文本语料库中的位置。它们有助于操纵文本数据,这通常是涉及文本分析的数据科学项目的先决条件。
因此,对于初露头角的数据科学家来说,对于未来的项目和分析任务来说,初步了解这个强大的工具非常重要。
在 Python 中,有一个名为 re 的内置模块,需要导入该模块才能使用 Regex。
**import re**
这是官方文档页面 的 起点。
在这篇简短的回顾中,我们将通过 Python 中的一些实际例子,介绍正则表达式在简单文本处理中的基本用法。
“匹配”方法
我们使用**match**方法来检查一个模式是否匹配一个字符串/序列。它区分大小写。

一个``compile`d 程序
我们可以使用**compile**创建一个正则表达式程序并使用内置方法,而不是重复代码。

因此,编译后的程序返回特殊对象,如**match**对象。但是如果它们不匹配,它将返回**None**,这意味着我们仍然可以运行我们的条件循环!

位置匹配
我们可以很容易地使用match对象中的附加参数来检查字符串模式的位置匹配。

上面,我们注意到一旦我们用模式thon创建了一个程序prog,我们就可以用不同的字符串多次使用它。
另外,请注意,pos参数用于指示应该在哪里查找匹配。对于最后两个代码片段,我们改变了起始位置,得到了不同的匹配结果。虽然字符串是相同的。
一个简单的用例
让我们看一个用例。我们想知道列表中有多少单词的最后三个字母是 ing。

“搜索”方法
为了解决上面的问题,我们可以使用一个简单的字符串方法。
regex 有什么强大的地方?
答案是它可以匹配非常复杂的模式。但是要看这么高级的例子,我们先来探讨一下**search**的方法。

注意,match方法如何返回None(因为我们没有在文本中指定模式的正确起始位置),但是search方法找到匹配的位置(通过扫描文本)。
自然,我们可以使用由search返回的match对象的span()方法来定位匹配模式的位置。

findall 和` finditer '方法
search功能强大,但也仅限于查找文本中第一个出现的匹配。要发现一个长文本中的所有匹配,我们可以使用findall和finditer方法。
findall方法返回一个带有匹配模式的列表。你可以通过统计条目的数量来了解被搜索的条目在文本中出现的频率。
finditer方法产生一个迭代器。我们可以使用它来查看更多信息,如下所示。

通配符匹配(使用单个字符)
现在,我们轻轻地进入 Regex 闪耀的竞技场。正则表达式最常见的用法与“通配符匹配”或“模糊匹配”有关。这是你没有完整的模式,但它的一部分,你仍然想找到在一个给定的文本中,类似的东西出现。
这里有各种各样的例子。这里我们还将对由search返回的对象应用group()方法,以返回匹配的字符串。
单点单字符匹配
点.匹配除换行符以外的任何单个字符。

小写\w 匹配任何单个字母、数字或下划线
DOT 仅限于字母字符,所以我们需要用其他工具来扩展曲目。

(\W 或大写 W)匹配没有包含\w 的任何内容
除了字母、数字和下划线之外,还有其他符号。我们用\W 来捕捉它们。

用空白字符匹配模式
\s(小写 s)匹配单个空白字符,如空格、换行符、制表符、回车符。当然,这是用来搜索一个有空白的模式,比如一对单词。

\d 匹配数字 0-9
这里有一个例子。

这是一个实际应用的例子。假设,我们有一篇描述一些学生在一次测试中的分数的文章。分数范围为 10-99,即两位数。其中一个分数被错打成了 3 位数(Romie 得了 72,却被打成了 721)。下面的简单代码片段使用\d 通配符匹配来捕获它。

字符串的开头
^(caret)匹配字符串开头的模式(但不匹配其他任何位置)。

字符串的结尾
$(美元符号)匹配字符串末尾的模式。下面是一个实际的例子,我们只对苹果的专利信息感兴趣,而忽略其他公司。我们检查文本末尾的“Apple ”,只有当它匹配时,我们才使用前面显示的数字匹配代码取出专利号。

通配符匹配(有多个字符)
现在,我们可以转到更复杂的多字符通配符匹配,这让我们拥有更大的能力和灵活性。
匹配 0 次或更多次重复
*****匹配前面正则表达式的 0 次或多次重复。

匹配 1 次或多次重复
**+**使产生的 re 匹配前面 RE 的一次或多次重复。

精确匹配 0 或 1 次重复
**?**使结果 RE 精确匹配前一个 RE 的 0 或 1 次重复。

控制匹配的重复次数
**{m}**精确地指定了**m**RE 要匹配的副本。较少的匹配导致不匹配并返回**None.**

**{m,n}**精确指定**m**到**n**的副本 RE 来匹配。省略**m**指定下限为零,省略**n**指定上限无穷大。



**{m,n}?**指定**m**到**n**RE 的副本以非贪婪方式进行匹配。

匹配字符集
**[x,y,z]**匹配 x、y 或 z。

集合中的字符范围
在集合中可以匹配一系列字符。这是使用最广泛的正则表达式技术之一。我们用**-**来表示距离。例如,a-z或A-Z将匹配a和z或A和Z之间的任何内容,即整个英文字母表。
让我们假设,我们想要提取一个电子邮件 id。我们放入一个模式,用字母字符+ @ + .com 匹配正则表达式,但是它不能捕获一个包含一些数字的电子邮件 id。

因此,我们稍微扩展了一下正则表达式。但是我们只提取带有域名的电子邮件 id。' com '。因此,它无法捕捉其他领域的电子邮件。

这很容易扩展,但巧妙的电子邮件操作可能会阻止用这样的正则表达式提取。

通过 OR-ing 结合正则表达式的功能
像任何其他好的可计算对象一样,Regex 支持布尔运算来扩展它的范围和能力。单个正则表达式模式的 OR 运算特别有趣。
例如,如果我们想查找包含区号“312”的电话号码,下面的代码无法从第二个字符串中提取出区号。

我们可以如下创建正则表达式对象的组合来扩展功能,

一个组合的例子
现在,我们展示一个使用findall()从文本中提取有效电话号码的例子,以及我们到目前为止学到的多字符匹配技巧。
请注意,区号为 312 的有效电话号码是 312-xxx-xxxx 或 312.xxx.xxxx。

拆分方法
最后,我们讨论一种方法,它可以创造性地用于从不规则的语料库中提取有意义的文本。下面显示了一个简单的例子,我们用打乱了一个常规句子的外部字符构建了一个正则表达式模式,并使用**split()**方法从句子中去掉这些字符。

摘要
我们回顾了使用 Python 定义正则表达式对象和搜索模式的要点,以及如何使用它们从文本语料库中提取模式。
Regex 是一个庞大的主题,它本身几乎就是一种小型编程语言。鼓励读者,尤其是那些对文本分析感兴趣的读者,从其他权威来源更多地探索这个主题。这里有一些链接,
你是那种因为正则表达式看起来像外语而远离它的人吗?我在……
medium.com](https://medium.com/free-code-camp/regular-expressions-demystified-regex-isnt-as-hard-as-it-looks-617b55cf787)
对于 JavaScript 爱好者来说,
正则表达式不是外来语言。在这里学习 JavaScript 中 Regex 的基础知识。
codeburst.io](https://codeburst.io/an-introduction-to-regular-expressions-regex-in-javascript-1d3559e7ac9a)
十大最需要的正则表达式,现成的,
十大最常用(也是最需要的)正则表达式
medium.com](https://medium.com/factory-mind/regex-cookbook-most-wanted-regex-aa721558c3c1)
A lso,你可以查看作者的 GitHub 知识库获取机器学习和数据科学方面的代码、思想和资源。如果你和我一样,对人工智能/机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
[## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…
通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和有趣…
www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)
使用开源工具过渡到网络安全的简单介绍。

网络安全——胡安·卡西尼的艺术作品
现在是 2020 年 2 月,我已经看到多篇文章预测,由于缺乏信息安全方面的人才,大规模的末日正在向我们走来。有些是危言耸听吗?大概吧。但现实是,大多数行业都在向科技发展,而科技带来了网络威胁。因此,传统的 IT 部门不得不适应并开始将网络安全放在首位。随着 IR35 的变化将于 2020 年 4 月生效(尽管它从 2000 年就已经存在了),雇佣承包商来保护你的安全将不再那么容易。这对 IT 部门意味着什么?对一些部门来说,这意味着招聘人才,无论是内部招聘还是着眼于当前市场?由于英国退出欧盟即将对英国移民体系进行改革,这可能会变得更加困难。然而,对于那些希望进入这个行业的人来说,这为进入一个需求巨大的行业提供了机会。
因此,让我们假设你已经在技术领域工作,并想将流转换为网络,你从哪里开始呢!
网络安全的角色那么多,知道自己的兴趣在哪里是一个很好的开始。解决这个问题的一个好方法是开始消费网络内容,可以是播客、书籍、YouTube,甚至是媒体阅读。 你 觉得什么有趣?如果你来自数据科学背景,并且热爱数据,那么网络安全🤝数据科学=一个豆荚里的两颗豌豆。这辈子,你要热爱你做的事情,当你热爱你做的事情的时候,感觉就不像工作了,对吧?你越喜欢你所做的事情,你就会变得越好奇,并且会走得更远。在网络安全领域,求知欲是必需的这可能是从同一所学院毕业、成绩相同的候选人之间的区别。
让我们从一些你需要的工具开始,⚒️
虚拟机将是你最好的朋友。这不仅是一个比建造你的实验室更环保的解决方案,而且它提供了一个复制(在某种程度上,这是由你的家用机器有多强大决定的)场景的机会,对于那些不习惯命令行的人来说也是一个机会。
VirtualBox 是大多数人用来部署虚拟机的最常见的开源虚拟化工具。一种常见的做法是部署一台易受攻击的机器(让我们说一台具有已知漏洞的邮件服务器),然后部署另一台带有 Kali Linux 或 Parrot OS 的虚拟机,设置网络设置以确保它们可以通信,然后继续利用漏洞。
我应该试用什么操作系统?
Kali 通常是最推荐的网络安全操作系统,尤其是如果你正在进行渗透测试的话。然而,Kali 也是一把拥有许多工具的瑞士军刀,所以对于第一次使用的人来说,它可能会令人生畏,令人困惑,而且处理起来太多了。那么,你该如何应对呢?
熟能生巧!
好的,让我们假设您是一名 DBA,已经与数据库打交道很长时间了,但现在想转换立场,加入我们的 infosec。你知道数据库,但从未使用过 Kali,所以学习它的最好方法是用 MongoDB 构建一个 VM,并安装一个你知道有漏洞的版本。识别网络安全漏洞的标准被称为“常见漏洞和暴露”( CVE s)。例如,搜索 MongoDB 会返回 36 个 CVE,这些 CVE 现在都将被打补丁。但是,例如,如果您在虚拟机上下载并安装了一个没有为CVE-2015–7882打补丁的 MongoDB 版本,该版本由于对版本 3.0.0 到 3.0.6 的 LDAP 身份验证处理不当而允许未经身份验证的客户端获得未经授权的访问,那么您就可以练习使用类似 Metasploit 或其他数据库破解工具。这种方法背后的原理是让你使用 Kali 中的一些工具包,切换数据库和工具,并学习渗透测试的基础知识。人们常说进攻是最好的防御方式。这也适用,尤其是在网络安全领域。如果你不知道它是如何被攻击的,你就不能保护它,对吗?
但是网络安全不仅仅是渗透测试信不信由你!
这里是我最喜欢的虚拟机之一。这是一个完整的安全套件,可以用来加强您的家庭防御。这可能是开始使用你的数据作为学习手段的好方法。介绍安全洋葱!
Security Onion 是一个免费的开源 Linux 发行版,用于入侵检测、企业安全监控和日志管理。它包括 Elasticsearch、Logstash、Kibana、Snort、Suricata、Bro、Wazuh、Sguil、Squert、CyberChef、NetworkMiner 和许多其他安全工具。
这里提到了许多工具,让我们来分解一下:
- ELK Stack—Elastic Stack 由 Elasticsearch、Kibana 和 Logstash 组成,像 Voltron 一样,它们结合在一起共同工作,形成一个伟大的 SIEM 工具,Logstash 摄取&处理日志,Elasticsearch 存储和解析,Kibana 显示它们以供分析。

麋鹿栈还包括 Beats!——承蒙弹力
- SNORT —是一款免费开源的网络入侵检测系统和入侵防御系统。由 Martin Roesch 于 1998 年创建,能够进行实时流量分析和数据包记录。
那么 SNORT 是如何工作的呢?
让我们以CVE-2017–0144-Windows SMB 远程代码执行漏洞为例,也称为永恒之蓝,它是 2017wanna cry 流行病的催化剂。SNORT 允许您在网络上设置规则,以阻止任何利用此漏洞的企图。例如,WannaCry 已知会与某个 sinkhole 进行通信,并检查某个 URL 是否是活动的,因为这是一个已知的指标,您网络中显示此行为的任何机器都很可能会受到危害,因此拥有检测和阻止此行为的规则将是一个很好的防御策略。数据科学家将喜欢使用 SNORT 规则和它生成的数据,结合 Kibana,您将能够构建图表并结合机器学习来预测&分析趋势。

通过 Kibana 发出 SNORT 警报——由 sý nesis 提供
- BRO —现在叫 Zeek,但知道的人不多。但是 BRO 是一个网络分析框架,与典型的 IDS 有很大的不同。
- Wazuh —是一款开源的企业级安全监控解决方案,用于威胁检测、完整性监控、事件响应和合规性。
- Sguil 是由网络安全分析师为网络安全分析师打造的。Sguil 的主要组件是一个直观的 GUI,它提供对实时事件、会话数据和原始数据包捕获的访问。Sguil 促进了网络安全监控和事件驱动分析的实践。
- Squert —是一个 web 应用程序,用于查询和查看存储在 Sguil 数据库中的事件数据(通常是 IDS 警报数据)。Squert 是一个可视化工具,它试图通过使用元数据、时间序列表示以及加权和逻辑分组的结果集来为事件提供额外的上下文。希望这些观点能引发一些问题,否则这些问题可能不会被提出。

网络安全🤝良好的图形用户界面——由 Squert 项目提供。
从远处看,看到所有这些工具并思考我不知道自己在做什么可能会令人生畏,但控制你的环境,查看教程并努力解决任务和漏洞是一种很好的学习方式。每当我在 Kali 上执行任何活动时,我总是确保我在监控会话,然后返回并试图通过日志重放它。通过查看每个分析工具发生了什么,它帮助我在日常工作中识别和记住我以前见过的行为。
Windows 事件日志是实践中一个很好的例子。用户登录时会发生什么?如果通过 LDAP 服务器或 VPN 登录,哪些日志与登录相关联?能够看到成功的登录,并将它们与系统尝试的日志进行比较,有助于形成您对基础架构环境的理解。
推荐购买!

阅读团队现场手册— 本·克拉克写的一本书,我一直把它放在办公桌上!
我总是把这本书放在身边,尤其是当命令行不是你的强项或者你正在使用 Windows CMD 并且需要复习常用命令的时候。绝对值得 4.94!这里可以买到!
想学笔考,但是没时间搭建环境?
在家学习是许多领域发展的关键,但在网络安全领域,这也是发现新人才和专业化的关键。但不是每个人都有时间或资源来建立他们的家庭实验室。这就是像 Hack The Box 这样的工具出现的原因。Hack The Box 由哈里斯·皮拉里诺斯(Haris Pylarinos)创建,提供了一个测试和提升渗透技能的在线*台。随着材料的不断变化,你现在可以在 YouTube 上找到有人如何侵入一个退休系统的视频。你只能找到退役系统的视频,顺便说一句,这是为了确保每个人都有公*的机会尝试新系统,并能在排行榜上排名。有趣的是,要获得一个账户,你必须黑进去。

是的,要得到你的邀请码,你必须黑进去。享受挑战吧!——承蒙 HTB
如果你正在进入网络安全领域,并且意识到有很多东西需要学习,一个好的记忆方法是开始写关于它的文章。了解如何安装一个新的 GoPhish 钓鱼服务器?写一篇关于它的博客。你面临的问题,别人肯定会遇到,你的叙述甚至可能比我经常发现的文档更好。我会一直关注 Medium 来理解一个新工具,因为经常有人写我可能没有考虑过的替代方案,或者推荐优秀的内容来帮助学习。
延伸阅读:
- 这篇文章是我在 2017 年写的一篇关于我如何获得我在网络安全领域的第一份工作的文章的更新版本。
- 安全洋葱文档
- 学习 Elasticsearch —本指南涵盖 6.3 版之前的 Elastic
- 如何在 AWS 上部署安全洋葱作者 Iain Dickson
斯蒂芬·查彭达玛
一种简单的卡尔曼滤波实现
一个储罐液位测量应用程序,帮助你开发卡尔曼滤波器的直觉

泰勒·尼克斯在 Unsplash 上的照片
传感器本身并不能解决您的测量问题。它们本质上很吵,这可能会导致严重的问题。例如,当用作 PID 控制器的输入时,噪声数据可能会产生单位脉冲——高频信号的导数变得无穷大,导致执行器饱和,过程控制穿过窗口。
另一种需要准确性的情况是批量转移。在这种情况下,供应商希望尽可能精确地测量转移产品的体积,以防止损失金钱或向客户多收费。
在本文中,我们将演示一个简单的例子,说明如何开发一个卡尔曼滤波器来使用超声波传感器测量水箱的水位。
该传感器
HC-SR04 配有声学接收器和发射器。发射机发出一个波,这个波经过障碍物反射后到达接收机。传播时间除以两倍音速,得到传感器和感兴趣物体之间的距离。该传感器的工作范围为 2 至 400 厘米。

与许多传感器不同,这款传感器不需要模拟端口。通过微控制器的数字输出激活“Trig”引脚后,传感器将发出一个声波,该声波将反射并返回传感器,到达接收器,“Echo”引脚将变为高电*。“Trig”和“Echo”激活之间的时间除以 2 就是波传播时间。
该设置
我在公寓的阳台上养了一些植物,为此我在上面放了一个带水泵的水箱,定期给它们浇水。每次这个油箱低于 30%时,我都会收到系统的电子邮件通知。如果你有兴趣了解如何实现物联网,你可以看看我写的另一篇文章:
自动给植物浇水,获取警报,并分析数据
medium.com](https://medium.com/@cunhafh/iot-home-irrigation-system-using-losant-and-particle-photon-130df98ce386) 
我知道,我需要清理这个水箱。
卡尔曼滤波器
该算法分为预测和更新两个阶段。

不要让代数符号吓倒你,让我们分解这些方程。
在预测期间,系统通过执行过去的估计和系统输入的线性组合来估计储罐的容积。在我们的例子中,矩阵 F 将*似等于 1(为了简单起见,我们可以忽略蒸发的影响),因此在给定时刻罐的体积将是过去时刻的体积减去由泵抽吸的体积(我的系统输入)。
因为我每天只灌溉植物一次,而且我的数据是通过 wi-fi 传输的,所以我想最小化负载。因此,我们可以忽略系统输入' u '的影响。但是请注意,这是有代价的,滤波器的动态响应将受到影响。
预测的第二步是估计协方差 Pk。我们不知道储罐液位的真实值,我们能做的最好的事情是估计最可能的值,并将其分配给最可能的方差。

在创新步骤中,我们将添加更多的信息,并尝试改进这一估计。让我们来看看:
首先,我们需要计算增益 k,现在忽略计算的数学过程,我们将简化它。
一旦计算出 K,我们就可以计算出'后验'状态估计。注意,该量对应于预测状态和‘T4’新息的线性组合,新息由增益和误差的乘积定义。
最后,我们需要更新协方差 p。
算法将总是从产生较小 p 值的组件(预测或创新)获得更多贡献。
因此,对于我们的状态观测器,我们将有:
f =[1]
B =[0]
H =[1]
Q =[1e-5]
R =[3e-3]
所以我们可以把方程改写成:

密码
有大量的 C++卡尔曼滤波器库可供您使用。我仍然认为编写自己的代码来巩固知识是有用的。在我的例子中,我在本地声明了所有的变量,这样它们就可以被函数访问,但是还有更好的方法。
int kalman_filter(){
//prediction
x_hat_k_a_priori = x_hat_k_minus_1;
P_k_a_priori = P_k_minus_1 + Q;
//obtaining z_k: my tank height = 25.4, calculates %
digitalWrite(trigger, LOW);
delayMicroseconds(2);
digitalWrite(trigger, HIGH);
delayMicroseconds(10);
digitalWrite(trigger, LOW);
duration = pulseIn(echo, HIGH);
z_k = (25.4-duration*0.017)/25.4;
//innovation
K_k = P_k_a_priori * (P_k_a_priori + R);
x_hat_k = x_hat_k_a_priori + K_k * (z_k - x_hat_k_a_priori);
P_k = (1 - K_k) * P_k_a_priori;
return x_hat_k;
}
结果
下图显示了获得的结果。注意时间序列是*滑的。

储罐液位瞬时和历史测量值
体积的突然增加是由于油箱重新装满。由于泵的激活,出现了小的下降。
结论
实施并测试 KF 算法以从超声波传感器 HC-SR04 获取数据。测试结果表明,该算法能够显著降低噪声。
卡尔曼滤波器可用于多种应用,如传感器融合、不可及变量的状态估计甚至股票市场预测。
如果你喜欢这篇文章或者想分享你的想法,请不要犹豫,在下面留下你的评论。
谢谢!
一个简单的线性回归模型
探索电价与碳排放数据之间的关系
回归分析是一种强大的统计方法,能够在感兴趣的变量之间进行检查。它可以用来评估变量之间关系的强度,并对它们之间的未来关系进行建模。
经济学家痴迷于回归。这可能就是为什么它们是我大学生活中不可或缺的一部分。这种定量估计是理解经济理论最重要和最常用的工具之一。
在经济学中,相关性是常见的,但识别两个或更多变量之间的相关性是否是因果关系却很难做到。回归分析使我们能够预测变化的方向和距离,以及变量之间这种关系的重要性。
它也是统计学、数据科学和机器学习中最广为人知和理解的算法之一。它的简单意味着它是一个很好的起点,对于那些想进入这个领域的人来说。
我之前的工作让我参与了能源行业的一个科技初创企业,特别是电力行业。鉴于我的非能源背景,我有很多关于电力市场运作的东西要学。
我通过接触这个行业获得的一个信息片段——简单易懂,但不是每个人都知道——是电价和电网的碳排放强度是相关的。
这些变量构成了我的线性回归的基础。
查找数据
碳强度
任何数据科学项目的第一部分都是寻找数据。国家电网提供了一个交互式网站,并托管了一个易于使用的 API。我选择了一周的每小时碳强度数据来分析最*的电网排放。
它们还提供了对未来 48 小时的估计。他们这样做是为了尝试和鼓励公司根据他们的预测,使用他们的 API 来自动化 IOT 设备的电力消耗。想想用风力而不是煤炭发电机充电的电动汽车。
我只选择了 2019 年 10 月 20 日至 27 日的日期,来看看上周的情况。
电价
当我们以家庭为单位消耗电力时,我们被给予固定的小时费率,而不管一天中的什么时间。然而,公用事业对批发市场有一些敞口。为了最大限度地减少这种情况,大型企业确保绝大多数英国电力通过双边协议出售,远离公开市场,从而限制了它们的价格风险。
然而,因为电力不能大规模储存,所以供给必须始终等于需求。这意味着必须建立一些市场机制来确保*衡。其中之一,前一天市场,正如它听起来的那样——买家和卖家提前 24 小时出价。有各种更不稳定的短期市场机制,确保市场清算和*衡,但是 NordPool 集团的数据相对容易处理。
可视化
前一天市场上一周内每兆瓦时的价格。

电网*均碳强度(gC02/kWh)

上面的图表直观地展示了我们一天中不同的电力需求(和供应)的结果。总体情况是,价格和碳强度在早上上升,在上午 8 点达到峰值,白天下降,然后在晚上再次上升,在晚上 8 点达到峰值。这在碳强度和价格方面大体相似。
下面作图,可以更清楚的看到这种关系。

这些可视化可以证明是获得数据感觉的有用工具,但在变量之间的相互作用的统计分析中是有限的。
虽然看起来有某种相关性,但线性回归允许我们进一步研究这种关系。
假设
线性回归需要满足五个关键假设:
- 线性关系
- 多元正态性
- 没有或很少多重共线性
- 无自相关
- 同方差性

普通最小二乘法
我导入并运行了 stats models——一个 python 库——来执行普通的最小二乘回归(OLS)。
OLS 发现 Y(电价)的*均变化是由 X(碳强度)的变化引起的。最小二乘法是指通过绘制最佳拟合线来找到这一*均变化。它采用实际数据和预测值(最佳拟合线)之间的距离,计算误差并对其求*方,以找到预测值的实际距离。如果模型可以改进,直线会移动到该点,直到它与所有数据点的距离尽可能小。

Statsmodels 使用它的 summary()超级功能提供了一个非常棒的模型摘要,这正是我选择使用它而不是其他也可以执行回归分析的库的原因
可视化可以再次帮助描绘模型。

该模型显示了变量之间的*均关系。如果我们知道哪些发电机目前正在运行,它们的碳强度和当前输出,我们将应该能够参考这条线并估计价格。然而,其准确性取决于通过各种统计测试来评估其显著性。
在这种情况下,由于其低 durbin-watson 结果,它不符合无自相关的假设。除此之外,它的 Jarque-Bera 比可接受的高得多,表明非正态分布。这可能会使我们的模型失效。
误差分布:
检查同质性

首先,当价格正态分布时:

碳强度不是:

结果讨论
因此,我们的模型在统计学上充其量是可疑的,但这并不意味着某种关系不存在。如果我有更多的时间,或者得到别人的帮助,这段关系肯定会很有趣。最重要的是,如此小的数据集不可能产生这些无关紧要的结果。
极度简化的高碳密度燃料和高价格是相互关联的,因为可再生能源发电不需要燃料,以及随之而来的所有成本:采购燃料、购买土地、钻探或挖掘燃料、提炼燃料、运输燃料、处理废物。
煤炭是效率最低的燃料来源,也是我们电网中最脏的,在转换成电力时会损失 70%的能量。另一方面,风能最终成为最有效的能源,产生的电能比它所消耗的能量多 1126%。
继续进一步建模
为了进一步分析电价指标,我们可以使用各种方法来强化我们的模型:
包含更多数据:
这可能包括更长时间内的数据,或来自其他国家的数据——前提是我们还可以访问或计算电网的碳强度。(这通常很难计算)
包含更多变量:
包括其他变量,如全球油价、天然气和煤炭价格,显然是帮助预测价格的有力竞争者。除此之外,我们还可以研究太阳能电池板成本和风力涡轮机成本,甚至探索局部天气数据的粒度,预测电力需求(大型体育赛事往往会产生有趣的结果——尽管橄榄球世界杯没有)。
使用线性回归作为分析电价的基础可以证明是能源转型的有用工具。如果我们想摆脱对化石燃料的依赖,将我们的能源需求转向可再生和低碳发电是至关重要的。
分析和预测是让我们实现这一目标的第一步,有像 Nest 这样的公司帮助控制大量房屋的能源消耗,以限制我们的碳足迹。
这一点尤其重要,因为我们的交通工具实现了电气化,电力消耗激增。如果所有这些额外的需求都由煤炭而不是风力来提供,那么关键的好处将会丧失。
一个简单的电影推荐系统
基于亚马逊基于商品的协同过滤
机器学习领域的推荐系统已经变得非常流行,对于网飞、亚马逊等科技巨头来说,这是一个巨大的优势,可以让他们的内容面向特定的受众。这些推荐引擎在预测方面非常强大,它们可以根据用户与应用程序的交互动态改变用户在页面上看到的内容的状态。

格伦·卡斯滕斯-彼得斯在 Unsplash 上拍摄的照片
基于项目的协同过滤
基于项目的协同过滤是由 Amazon 开发的一种方法,用于推荐系统中,主要基于数据集中各种项目之间的相似性向用户提供推荐。这些推荐是基于用户对该特定项目的评级来计算的。
一种电影推荐系统
我们将在这个项目中使用的数据集来自 MovieLens 。
让我们从将数据集导入笔记本开始。有两个文件特别需要导入。因此,将用户的评级导入到 r_cols 数据帧中,将电影导入到 m_cols 数据帧中。我们还将把编码类型设置为 utf-8 。
import pandas as pdr_cols = ['user_id', 'movie_id', 'rating']
ratings = pd.read_csv('ml-100k/u.data', sep='\t', names=r_cols, usecols=range(3), encoding="ISO-8859-1")m_cols = ['movie_id', 'title']
movies = pd.read_csv('ml-100k/u.item', sep='|', names=m_cols, usecols=range(2), encoding="ISO-8859-1")
现在,我们必须合并这两个数据帧,以获得一个完整的数据帧,该数据帧包含任何给定电影的用户评级。
ratings = pd.merge(movies, ratings)
让我们看看这个数据帧是什么样子的,
ratings.head()

下一步是旋转这个表,创建一个用户和他们评价的电影的矩阵。这个表格是为了让我们了解哪个用户看过什么电影,以及他们提供了什么样的评级。
movieRatings = ratings.pivot_table(index=['user_id'],columns=['title'],values='rating')
movieRatings.head()

我们将对 1977 年的星球大战电影进行分析。所以,让我们把所有星球大战的这些值分配给一个叫做星球大战等级的数据框架。
starWarsRatings = movieRatings['Star Wars (1977)']
starWarsRatings.head()

我们将使用 pandas corr()函数来查找与星球大战相关的所有列之间的成对相关性。
similarMovies = movieRatings.corrwith(starWarsRatings) # pairwise correlation of Star Wars vector of user rating with every other movie
让我们放弃任何没有数据的结果,
similarMovies = similarMovies.dropna() # Drop any results that have no data
构建具有关于星球大战的每部电影的相关分数的新鲜的新数据帧。
df = pd.DataFrame(similarMovies) # Construct a new Dataframe of movies and their correlation score to Star Wars
让我们看看这个数据框里有什么,
df.head(10)

现在让我们根据分数对这些值进行排序,
similarMovies.sort_values(ascending=False)

是的,这些结果没有任何意义。
这是因为我们的结果被那些只被一小撮人评级的电影搞砸了,他们也给《星球大战》评级。让我们来看看这些条目。
import numpy as np
movieStats = ratings.groupby('title').agg({'rating': [np.size, np.mean]})
movieStats.head()

让我们去掉那些少于 100 人评价的条目。
popularMovies = movieStats['rating']['size'] >= 100 # Ignore movies rated by less than 100 people
movieStats[popularMovies].sort_values([('rating', 'mean')], ascending=False)[:15]

将这些数据与类似于《星球大战》的原始电影集结合起来。
df = movieStats[popularMovies].join(pd.DataFrame(similarMovies, columns=['similarity']))
现在让我们来看看我们的数据框。
df.head()

最后,根据相似性得分对这些值进行排序。
df.sort_values(['similarity'], ascending=False)[:5]

结果
瞧😆!你可以看到,我们刚刚获得的最终输出中的前三个条目都是星球大战电影。接下来的几部电影基于相似的类型,即动作和冒险。我们刚刚建立了一个令人惊叹的电影推荐系统,它能够建议用户观看与他们过去观看过的内容相关的电影。
你可以在我的 GitHub 上找到完整的代码。如有任何疑问,请随时通过我的 LinkedIn 联系我。
谢谢你。
功率 BI 中的简单时间计算
…DAX 日期、小时和分钟。

Johannes Plenio 在 Unsplash 上拍摄的照片
我今天遇到了一个“简单”的问题。在我开始做之前,我觉得这很简单。见鬼,这太简单了,我甚至说我可以在 5 分钟内解决这个问题。有时候一个简单的问题对每个人来说可能都不简单。
5 分钟变成了一个小时,还需要大量的谷歌搜索。

作者图片
我真的不需要处理精确到分钟的时间分析,所以如果这听起来对你来说是一个简单的问题,那么你能够解决它就很好了。
背景:
我有一个调查的完成时间栏。它包括日期和时间,如下所示。

我只想做一个声明说,“所有在 10 月 14 日上午 8:48 之前回复的人”说“已报告”。
我尝试了下面的计算列。
Incorrect =VAR DAY = DATE(2020,10,14)VAR HOUR = HOUR(8)VAR MINUTES = MINUTE(48)VAR Cut_Off = DAY+HOUR+MINUTERETURNCut_Off
好像不管用。

作者图片
至少对我来说是合理的。Power BI 将日、小时和分钟相加,并将其与[完成时间]列进行比较。
它并不完全有效。权力毕没有拿起我的意思是小时和分钟。我想要的不是 12 点。现在是早上 8 点 48 分。
然后我意识到可能是因为时间的原因,也可能不是日期时间数据类型,所以我把它改成了下面的。
Time_Solution =VAR DAY = DATE(2020,10,14)VAR HOUR_MINUTE = TIME(8,48,00)VAR Cut_Off = DAY+HOUR_MINUTERETURNCut_Off
成功了:)。现在,我刚刚添加了 If 语句,它非常有效。

作者图片
然后我泡了一杯咖啡,意识到了一些事情。
有一个索引栏可以帮我。我知道当有更多的回答者时,这个索引栏会自动填充。它总是以 1 为增量增加。随着调查结果的出现,数字会变得更高,所以我会做相应的调整。
现在我有两个解决方案:
1)将 ID 用作比较器— Id_Solution
2)使用时间作为比较器—时间解决方案
我的表现在看起来像这样。
Id_Solution = IF([ID]<=30,"Reported","Did not Report")

作者图片
我甚至不需要时间去做我想做的事情。我想用最短的代码来代替 Id 解决方案。
问题是很难有人知道为什么我用 30 这个数字作为比较。
因为还有其他人在使用这个文件,所以我只能选择最容易解释的。也就是时间解。
这种情况让我想起了一句名言。
"的确,通过帮助他人成功,你可以最快最好地获得成功。"拿破仑·希尔。
一个问题有很多解决方案,但是有时候对你来说最明显的一个可能对所有人来说都不是最明显的。
最好实施一个每个人都理解的解决方案,而不仅仅是你。如果团队中的每个人都理解你的解决方案,这对每个人都是一个胜利。
带走:
- 可以使用 TIME()函数添加日、小时、分钟、秒钟。不需要单独的列。
- 索引列可能比您想象的更有用。
- 想想你的队友。他们会理解你的措施在做什么吗?容易解释吗?车型怎么样?
- 帮助你的队友成功,你也会成功
如果你想知道如何在 Power BI 中使用日期和日历,这里有一篇文章给你。
保重,注意安全!
一个简单的 Python 歌曲推荐系统(教程)
协同过滤和推荐系统的基础,以及为什么脸书和谷歌似乎知道你在说什么,即使他们不记录你的谈话。
本材料基于我在 2020 年 4 月教授的一个研讨会的内容。

DJ R3X 在 Oga 的酒吧策划歌曲。图片来源 : 约书亚·苏多克(迪斯尼公园)
我们大多数人现在每天都在使用基于人工智能的推荐系统:在网飞上寻找一个节目,在社交媒体上滚动,在 YouTube 上观看“up next”视频,在 Spotify 上收听“Discover Weekly”播放列表。
那么这些推荐器是如何工作的呢?
他们变得非常好,在某些情况下,好得令人毛骨悚然。我们中的许多人都收到了一些推荐和广告,这让我们不禁要问:“他们在给我录音吗?“一般来说,公司不会通过窃听你的麦克风,录下你的对话来做推荐。相反,他们会给你做一个模型,或者像特里斯坦·哈里斯所说的那样,“一个小小的巫毒娃娃,你的化身版本”,然后对那个娃娃做出预测。我会把这个娃娃称为你品味的数学模型。
本教程中的方法远没有谷歌、脸书和 Spotify 使用的方法复杂,它们不会产生任何令人毛骨悚然的好推荐。尽管如此,大多数建议的工作原理都是一样的,分为三个步骤:
- 公司为你和其他人建立了一个数学模型
- 他们利用这些模型来寻找和你相似的人
- 他们发现那些相似的人喜欢什么,并推荐给你
我将重复这三个步骤两次,首先是一个简单的可视化示例,然后是一个更大的基于代码的示例。
第 1 部分:视觉介绍
为你的品味建立一个数学模型
让我们首先考虑三个人(杰克、尼克和特雷弗)以及他们如何在 1 到 5 的范围内给三首歌曲(一支舞、向前一步和向日葵)评分。这是一个简单的表格:
我们现在有了一个简单的音乐品味的数学模型。在现实世界中,Spotify 使用其他信号来确定这个评级,比如你听了一首歌多少次。不管怎样,原则是把你的喜好转化成一串数字,其中也被称为向量、矩阵或数组。不管你怎么称呼它们,把这些数字形象化在图表上是很有帮助的。下面,我们将“一支舞”的评分放在 x 轴上,将“倚在”的评分放在 y 轴上:

使用该模型寻找相似的人
我们现在有了一个记录你音乐品味的数字列表,所以我们可以进入下一步:找到有相似品味的人。让我们回到图表:

在视觉表征中,相似的人只是附*的人。因此,找出谁与杰克“最相似”只是找出谁与杰克最接*的问题。我们可以用中学几何中古老的毕达哥拉斯定理来测量这个距离:

酷!我们快到了。我们已经可以看出,杰克最像尼克,而不是特雷弗,但让我们把它正式化:

数学证实:在歌曲品味的小宇宙中,杰克离特雷弗有 3.2 个单位的距离,但离尼克只有 1.4 个单位。
推荐相似的人喜欢的东西
现在我们知道杰克和尼克有相似的品味,我们可以根据尼克是否喜欢向日葵来预测杰克是否会喜欢《向日葵》。只需要在表中查找:
尼克给了“向日葵”5/5 的评分,所以我们可以预测杰克可能也会喜欢这首歌。
显然,这个微小宇宙的规模比 Spotify 的宇宙要小很多。我们看了三首歌和三个人,而 Spotify 据称拥有超过 5000 万首歌曲和超过 2.71 亿活跃用户。所以现在,我们要扩大规模。
第 2 部分:用 Python 编写示例代码
为你的品味建立一个数学模型
为了生成更大的数据集,我们将加载一个更大的表。这里的是一个有 25 首歌和 8 个人的:
在 Python 中,您可以使用 Pandas 通过以下命令加载这些数据:
from pandas import read_csvdata_url = 'https://gist.githubusercontent.com/jackbandy/5cd988ab5c3d95b79219364dce7ee5ae/raw/731ecdbecc7b33030f23cd919e6067dfbaf42feb/song-ratings.csv'ratings = read_csv(data_url,index_col=0)
使用该模型寻找相似的人
现在,让我们试着预测一下我(还是杰克)会不会喜欢《7 响》这首歌。就像在视觉示例中一样,我们会找到离我最*的人。使用勾股定理,二维空间中的距离函数就是distance=sqrt(a^2 + b^2),我们可以这样写:
def distance(person1,person2):
a_squared = (person1[0] - person2[0])**2
b_squared = (person1[1] - person2[1])**2
c = sqrt(a_squared+b_squared)
return c
但这一次,有 25 个维度,而不仅仅是 2 个。当我们有 25 个维度而不是只有一个 x 轴和一个 y 轴时,我们如何找到最接*的人?
事实证明,可信的毕达哥拉斯定理非常普遍。(大多数推荐器使用其他距离度量,如余弦距离,但在本教程中我们将忽略它)。如果有三个维度,我们可以称之为a、b、c,然后在*方根下面加上:distance=sqrt(a^2 + b^2 + c^2)就可以了。实际上我们可以在任何维度上这样做:distance=sqrt(a^2 + b^2 + c^2 + d^2 + ... + n^2)。
scipy 库编写了一个函数来完成我们需要的功能:计算任意维数的欧几里德距离。让我们使用它:
from scipy.spatial.distance import euclideandef distance(person1,person2):
distance = euclidean(person1,person2)
return distance
现在,我们可以使用距离函数来查看任何两个人之间的相似性。唯一的问题是我们需要使用fillna用“0”填充空白。下面的块执行该操作,然后检索这三个人的数据行:
ratings=ratings.fillna(0)jack=ratings.loc['Jack']
nick=ratings.loc['Nick']
trevor=ratings.loc['Trevor']
然后,我们可以看看杰克和另外两个人之间的距离:
print("Distance between Jack and Nick:")
print(distance(jack,nick))
# 10.63014581273465print("Distance between Jack and Trevor:")
print(distance(jack,trevor))
# 13.490737563232042
就像在《小宇宙》中,杰克离尼克(10.63 个单位远)比离特雷弗(13.49 个单位远)更*。但实际上,我们想看看杰克和其他人之间的距离。下面是一个使用“for 循环”来实现这一目的的函数:
def most_similar_to(name):
person = ratings.loc[name]
closest_distance=float('inf')
closest_person='' for other_person in ratings.itertuples():
if other_person.Index==name:
# don't compare a person to themself
continue distance_to_other_person = distance(person,ratings.loc[other_person.Index]) if distance_to_other_person < best_similarity:
# new high score! save it
closest_distance = distance_to_other_person
closest_person = other_person.Index return closest_person
开头是这样说的:“到目前为止最亲*的人,在无限远的地方。”然后,它循环查看每个人,并询问“这个人比目前为止最亲*的人更亲*吗?”回答“和 Jack 最相似的人是 Jack”并没有太大帮助,这也是为什么名字相同的话循环会跳过(即continue)。
现在,我们可以只调用most_similar_to来查看谁与任何人最接*。让我试试(杰克):
print("Jack is most similar to:")
person_most_similar_to_jack = most_similar_to('Jack')
print(person_most_similar_to_jack)
print(distance)# Meg
# 8.660254037844387
推荐相似的人喜欢的东西
最后,我们可以通过看和我最相似的用户来预测我是否会喜欢“7 环”。当时资料上说这是梅格,那我们来看看梅格是怎么评价这首歌的:
print(ratings.at['Meg', '7 Rings (Ariana Grande)'])
# 3.0
梅格对这首歌的评价是 3/5,所以我可能不会对它太着迷。
一个 Google Colab 笔记本全部代码都有 这里 。
后续步骤
如果你真的想做 Spotify 正在做的事情,你会利用每个 T21 人的音乐品味做出预测,而不仅仅是最亲*的人。例如,也许如果我知道特雷弗和我一直有非常不同的品味,认识到特雷弗喜欢《7 环》可能会告诉我,我会不喜欢这首歌。我可能会在未来的教程中涉及到这一点,所以如果您感兴趣,请告诉我!
向任何人解释版本控制的简单故事
让我们一起盖房子吧…用 git。

当我开始在项目中使用版本控制时,这个概念很难理解。我看到很多人,包括我自己,运行着 git pull、git push 之类的命令,应用着我不理解的进程。为什么我既需要承诺又需要推动?为什么每个新特性都需要一个新的分支?在一个每天使用 Git 的项目中工作了几个月之后,这个概念对我来说变得非常清晰,我终于理解了使用版本控制,更具体地说,使用 Git 进行协作的全部潜力。
在 12 月的最后两周,我被要求举办一个关于版本控制的研讨会,更具体地说是如何在项目中使用 git。由于研讨会将有不同背景的人参加,我想到了一个小故事来说明版本控制的工作方式及其在项目中的优势。
让我们一起盖房子吧
在这个美丽的合作项目中,我们试图一起建造一所房子。简单点说,我们只有两个人在那栋房子里工作。我们不是房子的主人,我们为其他人工作,一个利益相关者,他告诉我们他想要什么,他想要在哪里。
免责声明:我绝不是建筑师,我对实际建造一栋真正的房子知之甚少。请记住,这只是一个帮助人们容易理解版本控制概念的故事。

我们有 4 面墙——我们的主分支
我们从 4 面墙(和一个屋顶?),坚固、耐用且非常精细。这四面墙代表我们的总支。它们目前仍然有效,已经实施,不会被删除。利益相关者认可了这四面墙,他甚至可能自己选择了它们,他想保留它们。我们需要做的只是改善这四面墙,并在它们的顶部或周围进行建设。无论如何,我们将要建造的任何东西都将以这四堵墙为基础。
主人想要一个客厅和一个厨房——特色树枝
正如我之前提到的,有两个人在做这个项目,我和另一个人,我们叫他鲍勃,因为我对名字没有任何想象力。每个房间都是一个特色。在这种情况下,为了最大化结果,Bob 和我将致力于不同的功能。我将设计客厅,鲍勃将设计厨房。到目前为止一切顺利。简单。
我们都创建了一个特性分支。我们也知道我们必须使用约定来命名我们的分支。所以我们将从我们的名字开始,我们正在做什么(在这种情况下,一个新的特性)和那个特性的名字。
- 朱莉娅/特写/客厅
- 鲍勃/特写/厨房
(分支机构的命名有几种惯例。这只是一个建议。)
我们都从主分支创建我们的特征分支。所以我们都从同样的四面墙开始。然而,我们的特性分支是完全独立于主分支的副本,对主分支的内容没有直接影响。这确保了如果 Bob 或我完全破坏了主墙中的一面,包含我们四面墙的主分支仍然屹立不倒,并且可以依靠。
我想在本地保存我的设计— git commit
提交就像在本地保存您的更改一样。每个新的提交都有一个数字,也代表一个你可以返回的保存点,就像在一个任务游戏中,你可以返回到上一个保存点。因此,当 Bob 构建厨房橱柜时,他可以提交它们,以便不丢失他的更改,并且如果他构建的下一部分危及橱柜的质量,他还可以提交。
每个提交还需要一个消息,因为写一些关于你的提交的东西是一个好习惯,为了让每个人都知道这个“保存点”包括什么,sweet Bob 写了“创建红色的厨房橱柜”。
我想把我的设计保存在一个安全的地方,在资源库上——git push
您的存储库是存储所有分支的地方,包括主分支。它就像一个文件夹,其中包含了有关项目的所有文件,包括它们的修订历史。
Git push 获取您所有的提交,并将它们发送到您的分支的 remote 版本,该版本可以在您的在线存储库中获得,在那里所有相关的开发人员都可以看到对您的分支所做的更改。因此,Bob 将他的提交推送到他的远程分支,我现在可以看到 Bob 关于红色文件柜的提交。
我的客厅完工了。现在怎么办?-开发分支和合并请求
我们的开发分支是整合我们的房间(或功能)的地方。这是我们尝试将我们的设计(或功能)结合在一起的地方,看看我们的客厅和厨房是否能很好地配合。
如果我想把我的客厅添加到开发分支,我必须做一个合并请求(或者拉请求,这取决于你使用的*台)。一般来说,在合并发生在远程分支之前,至少有一个其他开发人员必须批准您的合并请求。
鲍勃的厨房完工了。我们的设计不相配。—合并冲突
我正在尝试将 Bob 的新更改合并到我的分支中。但是,如果我没有在鲍勃的开放式厨房一侧做好墙,会发生什么呢?我们的设计(代表代码,记得吗?)有冲突。 Git 可以自动解决一些冲突,但不是全部。Git 有时需要您的帮助来确定哪些更改应该保留,因为其中一些更改是冲突的。换句话说,它需要知道谁的“设计”(或代码)是应该保留的。
假设我是犯错的人(不要责怪可怜的鲍勃)。我可以告诉 Git,当涉及到厨房墙壁时,保留 Bob 的部分设计,而不是我的。
什么时候可以把我们的厨房和客厅加到 Master 分店?
项目的这一部分通常包括测试、涉众和批准(至少)。一旦我们的设计被彻底测试,这意味着它们也能很好地一起工作,并且我们的利益相关者,房屋所有者批准了设计,我们就可以决定将我们的变更合并到主分支。这意味着从现在开始,我们房子的稳定版也将包括我们的客厅和厨房。所以所有新的分支机构至少应该包括这些房间。
在某些情况下,一个聪明的方法可能包括将主分支的每个以前的版本作为以前的版本保存在不同的分支中。然而,处理主分支的正确方法取决于您的团队和公司可能有的需求或指导方针。(我保持这个故事简单。不是每个团队或公司都以相同的方式处理主分支。)
总之,版本控制是轻松安全协作的核心。
在一个团队项目中使用 Git 允许几个开发人员在同一个项目中独立工作,而不会经常干扰彼此的输入。每个开发人员都可以获得独立版本的代码,他们可以修改这些代码,而不必冒破坏代码稳定版本的风险。
复制代码和在不同版本上独立工作的能力使 Git 成为任何构建应用程序的人的好选择,甚至是单独工作的开发人员。它让您有机会保留代码的几个版本,并跟踪每个更改的所有特征,例如谁在何时做了更改。
感谢阅读!
一个简单的基于 SVM 的半监督学习实现
扫清半监督学习的迷雾

来源:-https://unsplash.com/photos/GhFn3mddePk
我们都遇到过作为一种机器学习问题的半监督学习。但这是一个没有被很好理解的概念。最好通过弄脏我们的手来理解这一点,而这正是我们正在带来的。
用例很简单,我们有一些数据,可能有 100 个观察值,其中 30 个是有标签的(有监督的),其余的是无标签的(无监督的),我们正在解决一个分类问题。我想大家都会同意,如果我们可以使用所有 100 个观察值,那么通过对 30 个案例或观察值进行训练所能达到的性能会更低,不幸的是,其中 70 个没有标记。

图 1:无监督学习场景(来源:作者)
本质上这是一个二元分类问题。这两个类别由蓝色三角形和红色圆圈表示。灰色菱形表示未标记的数据。
我们的第一个策略是
步骤 1:在标记的数据上建立一个分类器(常规的东西)
第二步:用这个来预测未标记的数据。然而,除了预测,你还要检查你的信心水*。
第三步:将这些观察结果添加到你有一定把握的训练数据中。这些被称为伪标记与标记数据相对照。
步骤 4:使用这个扩充数据集,现在用于训练,并使用这个模型。
由于我们使用非监督数据来增加监督学习的训练数据,这介于两者之间,因此称为半监督。

图 2:扩展数据集
在上图中,说明了训练数据的扩展。对于我们有信心的观察结果,我们使用了伪标签,而对于我们没有信心的观察结果,我们仍然保持不加标签。
让我们现在跳到代码
我们正在创建一个虚拟场景,其中我们将数据集(wine)分为 train(已标记)、unl(未标记)和 test。
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=1)
X_train, X_unl, y_train, y_unl = train_test_split(
X_train, y_train, test_size=0.7, random_state=1)
这里分别是训练、测试和未标记的形状。请注意,我们不会考虑 unl 部分的标签信息,因此将其视为未标记

数据集的形状(图片来源:作者)
接下来,我们简单地在标记的部分进行训练,它刚刚走了 19 行。
clf = svm.SVC(kernel='linear', probability=True,C=1).fit(X_train, y_train)
clf.score(X_test, y_test)
获得的精度如下

初始分类准确性(来源:作者)
接下来,我们对未标记的数据进行预测
df = pd.DataFrame(clp, columns = ['C1Prob', 'C2Prob','C3Prob'])
df['lab']=lab
df['actual']=y_unl
df['max']=df[["C1Prob", "C2Prob","C3Prob"]].max(axis=1)
你可能已经注意到了,我们使用了预测概率,它预测了类别概率,而不是标签,这实际上会帮助我们找到有把握的猜测

对预测的信心(来源:作者)
我们只看预测概率之间的绝对差异
- 当这三个类别的概率相等时,则所有类别的概率大约为 0.33
- 任何大于这个值的值都显示出一定的可信度
本质上,我们希望在训练中添加这些概率差异较大的观察值。代码如下
下图给出了置信度的分布,以最有可能的类别的概率表示。

对预测的信心(图片来源:作者)
接下来,我们运行一个循环,对于最可能类的不同阈值,将数据添加到观察值中。

不同阈值下的准确性(来源:-作者)
- 当最可能的类的概率大于 0.4 且高达 0.55 时,情况会有所改善
- 在那之后,几乎没有任何改善,因为在那些我们超级自信的人身上,这并没有增加知识,因为观察结果与标记非常相似。
尾注:
在本教程中,我们已经展示了如何使用 SVM 来采用简单的半监督策略。这种技术可以很容易地扩展到其他分类器。影响将取决于类的重叠或区分程度、要素的信息量等等。
参考资料:
[1]https://www . ka ggle . com/saptarsi/a-simple-semi-supervised-strategy-based-on-SVM
一种在不同服务器之间自动化和安排 SQL Server 数据库复制的简单方法

图片提供:https://www . spiria . com/site/assets/files/2398/2016-SQL-server-logo。-large.jpg
微软 SQL Server 提供了SQL Server Replication功能,我们可以利用这些功能将一个数据库设置为Publisher和另一个数据库为Subscriber,这样我们就可以在脚本中通过定制来复制数据库。但是,有时需求可能没有那么复杂,因此 SQL Server 复制可能有点过头了。
例如,最*我的一个客户想要启动一个概念验证项目来构建一个数据仓库。他们担心他们赖以保持业务运行的生产数据库。因此,在我们从数据库中提取数据来构建数据仓库之前,我们需要复制数据库,以便所有的开发工作都可以在这些副本上进行。
在这种情况下,没有必要在复制过程中包括任何定制,这只是简单地镜像数据库。在本文中,我将介绍一种在不同服务器之间自动复制 SQL Server 数据库的非常简单的方法。
在 Azure 中创建 SQL 服务器
让我们首先为这个实验创建两个 SQL 服务器。强烈建议使用 Azure,否则,您需要准备两台不同的机器,获得适当的 SQL Server 许可证并安装 SQL Server 软件,这可能需要一整天的时间。
如果你是 Azure 的新用户,当你注册 Azure 为新用户时,你将获得 200 美元的积分(一个月内)。
转到您的 Azure 订阅,首先创建一个资源组,这将是 SQL 服务器的容器。然后,去 marketplace 搜索“sql server”,如截图所示选择 Windows Server 2016 上的 SQL Server 2017。

在下拉手册中,选择标准版以拥有所有标准功能。然后,单击“从预设配置开始”以节省时间。

在这里,我们可以选择开发/测试环境和 D 系列虚拟机(都是最小的)来节省成本,特别是如果您已经用完了所有的免费积分。然后,单击“创建虚拟机”

确保您选择了为此创建的资源组。然后,单击下一步。

填写管理员凭据。

磁盘对这个实验不重要,所以我们可以跳过。然而,虚拟网络非常重要。确保您创建了一个新的虚拟网络和子网,更重要的是,如果您不想在这个实验中产生一些可访问性问题,那么稍后创建的另一个 SQL Server 必须在同一个虚拟网络和子网中。另外,为了方便起见,打开 RDP 端口 3389。

不要更改默认端口号并创建 SQL 身份验证。之后,我们已经完成了配置。点击创建按钮在 Azure 中创建资源。

在等待部署资源的同时,我们可以创建另一个 SQL Server。我就叫它SQL-Server-Test。
准备“生产”SQL Server
在部署了第一个 SQL Server 之后,转到资源组并找到用于SQL-Server-Prod的 Windows VM。因为我们已经为该机器打开了 RDP 端口,所以我们可以使用它的公共 IP 地址来远程控制该虚拟机。
请记录私有 IP 地址,稍后测试机器将使用该地址连接到该产品机器

下载一个示例数据库
让我们安装一个来自微软的示例数据库。在生产机器上,下载数据库备份:https://github . com/Microsoft/SQL-server-samples/releases/download/adventureworks/adventureworks 2017 . bak
在 SSMS,使用默认的 Windows 管理员帐户登录数据库实例。

恢复示例数据库
右键单击“数据库”并选择“恢复数据库”。

在弹出窗口中,单击“设备”单选按钮右侧的浏览按钮->添加->浏览您刚刚下载的 bak 文件->确定->确定->确定。恢复整个数据库可能需要大约 1 分钟。

准备备份路径
接下来,我们需要创建一个文件夹来存放备份文件。此外,我们需要在网络中共享这个文件夹,以便测试机器可以访问备份文件并恢复它。
我创建了目录C:\backup\。然后,将该文件夹共享到另一台机器上的同一个管理员帐户。

请注意,将MSSQLSERVER用户添加到共享中很重要。否则,共享后 SQL Server 可能无法将备份文件写入此文件夹。只需输入MSSQLSERVER用户名并点击添加按钮,然后确保授予它读/写权限。


在测试机器上,我们现在将能够访问backup目录。

在 SQL-Server-Production 上创建备份
因为 SQL Server 代理在默认情况下是禁用的,所以我们需要再次远程控制生产机器来启用它。右键点击SQL-Server-Agent - >开始。然后,在弹出的确认窗口中点击Yes。


等到 SQL Server 代理启动后,返回测试计算机。您需要重新连接生产 SQL Server 才能看到 SQL 代理的启用。
右键Jobs->-New Job...。

在New Job窗口中,输入名称并转到Steps选项卡。

在Steps页签中,点击New按钮。

在New Job Step窗口中,输入步骤名称和脚本如下:
USE AdventureWorks2017
GODECLARE [@filename](http://twitter.com/filename) varchar(255)
DECLARE [@date](http://twitter.com/date) datetimeSELECT [@date](http://twitter.com/date)=getdate()
SELECT [@filename](http://twitter.com/filename)='C:\backup\AdventureWorks2017-' + CAST(DATEPART(yyyy, [@date](http://twitter.com/date)) as varchar) + '-' + CAST(DATEPART(mm, [@date](http://twitter.com/date)) as varchar) + '-' + CAST(DATEPART(dd, [@date](http://twitter.com/date)) as varchar) + '.bak'BACKUP DATABASE AdventureWorks2017 TO DISK=[@filename](http://twitter.com/filename) WITH INIT
GO

之后,进入Advanced选项卡,配置成功和失败行为。这里,你需要考虑你的情况,比如你的数据库有多大等等。

点击确定确认应用作业步骤,然后转到Schedule选项卡并点击新建按钮。您可以根据自己的需求配置时间表。在本例中,我将让备份在每天凌晨 1:00 进行。然后,单击“确定”按钮确认该计划。

您可能还希望创建警报或通知,例如在作业失败时发送电子邮件。在这个实验中,我们将跳过这一步,因为并不总是需要。
现在,与其等到明天凌晨 1 点,我想测试一下这个作业。我们可以右键单击我们创建的作业,然后选择“在第…步启动作业”来测试该作业。由于我们在此作业中只有 1 个步骤,它将直接启动并运行备份步骤。

过一会儿,作业就成功了,您也可以在备份目录中找到备份文件。

在 SQL-Server-Test 上还原备份
首先,我们通过 access \\SQL-Server-Prod\backup\<backup-file>来检查一下测试机上备份文件的可访问性。

另一个关键步骤是将远程备份文件夹装载到本地驱动器。这是因为 SQL Server Windows 服务通常是作为无权使用网络/远程资源的服务帐户运行的,因此远程资源对它是不可见的。
只需右键单击备份文件夹并选择“映射网络驱动器…”。

让我们将它安装到测试机上的 Z: drive。

然后,我们需要让 SQL Server 使用xp_cmdshell命令识别网络驱动器。默认情况下,这个命令是不启用的,所以我们需要启用它。打开一个新的查询表,并运行以下脚本来启用它。
EXEC sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
EXEC sp_configure 'xp_cmdshell',1
GO
RECONFIGURE
GO
然后,使用xp_cmdshell定义网络驱动器。您可以使用任何可以访问该网络驱动器的 Windows 用户。注意,您只需要运行这个命令一次,所以密码不会以明文格式保存在任何地方。
EXEC XP_CMDSHELL 'net use Z: \\SQL-Server-Prod\backup <password> /USER:<username>'
在 result 面板中,您应该会看到输出,表明它是成功的。

我们也可以通过下面的脚本来测试它是否有效。
EXEC XP_CMDSHELL 'dir Z:'
如果可以,您应该会看到包含备份文件的文件列表。

之后,我们只需要创建另一个 SQL Server 代理作业,其中包含从所标识的网络驱动器还原数据库的步骤。该步骤的脚本如下:
DECLARE [@filename](http://twitter.com/filename) varchar(255)
DECLARE [@date](http://twitter.com/date) datetimeSELECT [@date](http://twitter.com/date)=getdate()
SELECT [@filename](http://twitter.com/filename)='Z:\AdventureWorks2017-' + CAST(DATEPART(yyyy, [@date](http://twitter.com/date)) as varchar) + '-' + CAST(DATEPART(mm, [@date](http://twitter.com/date)) as varchar) + '-' + CAST(DATEPART(dd, [@date](http://twitter.com/date)) as varchar) + '.bak'RESTORE DATABASE AdventureWorks2017
FROM DISK=[@filename](http://twitter.com/filename)
WITH REPLACEGO
然后,重复我们之前在生产计算机中所做的操作,右键单击代理作业并选择“在步骤启动作业”来测试作业。等待一段时间,直到恢复完成,右键单击“数据库”刷新数据库列表,你会看到恢复的数据库!
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@qiuyujx/membership)
如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)
资源
使网络路径对 SSMS 的 SQL Server 备份和恢复可见:
https://www . MSSQL tips . com/SQL Server tip/3499/make-Network-Path-Visible-For-SQL-Server-Backup-and-Restore-in-ssms/
BACKUP 语句(Transact-SQL,微软官方文档):
https://Docs . Microsoft . com/en-us/SQL/t-SQL/Statements/BACKUP-Transact-SQL?view=sql-server-ver15
RESTORE 语句(Transact-SQL,微软官方文档):
https://Docs . Microsoft . com/en-us/SQL/t-SQL/Statements/RESTORE-Statements-Transact-SQL?view=sql-server-ver15
用 Python 分析学生成绩数据的简单方法

斯蒂芬·道森在 Unsplash 上拍摄的照片
探索如何使用 Python 和 Dremio 以高效的方式分析数据和构建信息图表
介绍
数据分析和数据可视化是数据科学的重要组成部分。实际上,在机器学习时代之前,所有的数据科学都是关于用不同的工具解释和可视化数据,并对数据的本质做出结论。如今,这些任务仍然存在。他们只是众多杂项数据科学工作中的一个。通常,所谓的 EDA(探索性数据分析)是机器学习管道中的一个必需部分。它允许更好地理解数据、其分布、纯度、特征等。此外,建议可视化,以向不同的利益相关者呈现机器学习工作的结果。他们可能不熟悉复杂的数据科学原理,但查看图形和图表对他们来说很方便。此外,如果不需要深入挖掘数据,数据分析和可视化可以作为独立的任务来完成。无论如何,一个好的数据科学家应该知道如何分析和可视化数据。
在本教程中,我们将展示如何分析数据,以及如何构建美观且信息丰富的图表。我们将使用流行的 Python 库进行可视化,即 matplotlib 和 seaborn。此外,我们将使用 Pandas 作为操纵数据帧的工具。我们将使用的数据集是学生表现数据集。我们将演示如何将数据加载到 AWS S3,以及如何通过 Dremio 将数据导入 Python。Dremio 也是数据管理和预处理的完美工具。这就是为什么我们会在 Dremio 中立即对数据做一些事情,然后再将它放入 Python 的手中。
假设
本文假设您拥有对 Dremio 的访问权限,并且拥有一个 T2 AWS 账户。我们将使用 Python 3.6 和 Pandas 、 Seaborn 和 Matplotlib 包。要将 Dremio 连接到 Python,还需要 Dremio 的 ODBC 驱动。所有 Python 代码都是在 Jupyter Notebook 环境下编写的。
将数据加载到 AWS S3 有两种方式,通过 AWS web 控制台或以编程方式。在本教程中,我们将展示如何直接从 Python 代码向 S3 发送数据。为了能够从 Python 管理 S3,我们需要创建一个用户,您将代表该用户从代码中执行操作。为此,从 AWS 控制台的服务列表中选择,单击,然后按按钮:

给新用户起一个名字(在我们的例子中,我们选择了 test_user )并为这个用户启用编程访问:

下一步,您必须设置权限。在大多数情况下,这是一个重要的阶段,您可以为不同的用户调整权限。您甚至可以在这里创建自己的访问策略。但是在本教程中,为了简单起见,只给用户对 AWS S3 的完全访问权:

创建用户后,您应该复制所需的凭证(访问密钥 ID 和秘密访问密钥)。您将在后面的代码中使用它们向 AWS S3 发出请求。

在配置文件中,设置要为其创建存储桶的区域,等等。在 S3:
现在一切都为编码做好了准备!先做点简单的吧。例如,显示 S3 的现有时段:
在上面的代码中,我们导入库 boto3 ,然后创建客户端对象。作为一个参数,我们指定“ s3 ”来表明我们想要使用这个 AWS 服务。之后,我们使用创建的对象的 list_buckets() 方法来检查可用的桶。下面是我们在响应变量中得到的结果(一个带有桶的空列表):

现在让我们创建一个桶。为此,使用客户端对象的 create_bucket() 方法:
下面是创建存储桶后, list_buckets() 方法的输出:

您还可以在 AWS web 控制台中看到创建的存储桶:

我们有两个文件需要加载到亚马逊 S3, student-por.csv 和 student-mat.csv 。为了加载这些文件,我们使用客户端对象的 upload_file() 方法:
最后,您应该能够在 AWS web 控制台中看到这些文件(在前面创建的存储桶中):

连接到您的 AWS S3 数据源
要连接 Dremio 和 AWS S3,首先转到服务列表中的部分,选择 删除根访问密钥 选项卡,然后按下 管理安全凭证 按钮。然后选择 访问键 选项卡然后点击 新建访问键 按钮。按下 显示访问键 后,复制 AWS 访问键和AWS 访问密码:

在 Dremio GUI 中,单击按钮添加新源。然后选择 亚马逊 S3 。应该会出现以下窗口:

在上面的窗口中,您应该指定源的名称( student_performance )以及您在上一步中生成的凭证。
准备您的数据
在这部分教程中,我们将展示如何处理关于学生在葡萄牙语课上表现的数据框架。然而,需要同样的行动来管理其他数据框架(关于数学课的表现)。
首先,打开 student_performance 源文件中的 student-por.csv 文件。请务必更改字段分隔符的类型(“;”),行分隔符(" \n "),并勾选 提取字段名 复选框,如下图所示:

我们不需要 G1 和 G2 列,我们把它们去掉吧。单击每列名称旁边的箭头,调出上下文菜单。然后从菜单中选择选项:

通过同一个下拉菜单,我们可以将 G3 列重命名为 final_target 列:

接下来,我们注意到所有的数值都是字符串数据类型。我们想把它们转换成整数。为此,单击列名附*的小 Abc 按钮,然后选择所需的数据类型:

结果中将出现以下窗口:

在这个窗口中,我们需要指定新列的名称(具有新数据类型的列),还需要设置一些其他参数。准备好后,按下按钮。我们应该对所有数字列进行类型转换,这些数字列是字符串: age、Medu、Fedu、traveltime、studytime、failures、famrel、freetime、goout、Dalc、Walc、health、absenties。
在对数据执行上述所有操作后,我们将数据帧保存在名为端口 1 的学生性能空间中。
在 Dremio 中,您所做的一切都会在 SQL 代码中得到反映。例如,我们上面描述的所有操作都生成了下面的 SQL 代码(您可以通过点击 SQL 编辑器 按钮来检查):
此外,您可以编写自己的 SQL 查询。假设我们想要创建新的列 famsize_bin_int 。该列应为二进制。当来自列 famsize 的给定行中的值等于“GT3”时,它应该包含“1”;当 famsize 列中的相应值等于“LE3”时,它应该包含“0”。下面是实现这一想法的 SQL 代码:
在下图中,您可以看到在单击按钮后,列 famsize_int_bin 出现在 dataframe 中:

最后,我们希望根据 final_target 列对 dataframe 中的值进行排序。我们希望在表格顶部看到分数最低的学生,因此我们从下拉菜单中选择 升序 选项:

最后,我们在student _ performance _ space中以 port_final 的名字保存策划的数据帧。数学数据集也是如此(我们将其保存为 mat_final 表)。
连接到 Python
要连接 Dremio 和 Python 脚本,我们需要使用 PyODBC 包。下面的代码用于将 port_final 和 mat_final 表作为 pandas dataframes 导入 Python。
如您所见,我们需要指定主机、端口、dremio 凭证和 Dremio ODBC 驱动程序的路径。然后我们使用 PyODBC 对象的方法 connect()建立连接。Pandas 使用 read_sql()方法从远程数据源获取数据。在创建 SQL 查询时,我们使用了表的完整路径(name _ of _ the _ space . name _ of _ the _ data frame)。
Python 中的数据分析和可视化
探索性数据分析的主要目标是理解数据。它可以作为一项独立的任务,也可以作为机器学习过程中的准备步骤。EDA 有助于确定您的数据具有哪些特征,分布情况如何,是否需要进行数据清理和预处理等。
可能每个 EDA 都是从探索数据集的形状和浏览数据开始的。为了显示 dataframe 中的前 5 条记录,可以在 Pandas dataframe 上调用 head() 方法。您还可以将行数指定为该方法的参数。换句话说,5 是该方法显示的默认行数,但是您可以将其更改为 10,例如。

要检查数据的形状,使用数据帧的形状属性:

你可以看到葡萄牙语数据框中的行数远远多于数学数据框中的行数。此外,在本教程中,我们将只使用葡萄牙语数据帧,以避免文本过载。但是这些数据框架是完全相同的,如果你愿意,你可以用数学数据框架做同样的操作,并比较结果。

现在我们只想看看来自市区的学生。为此,我们只提取那些在地址列中包含值“U”的行:

从上面的输出,我们可以说来自城市地区的学生比来自农村地区的学生多。例如,如果我们继续进一步研究机器学习模型,我们可能会发现这些信息对一些特征工程很有用。
除了 head()函数,还有另外两个 Pandas 方法允许查看数据帧的子样本。 tail() 方法从表的末尾返回行。 sample() 方法从 dataframe 返回随机的 N 行。如果您不仅想查看表的开头或结尾,还想显示数据帧不同部分的不同行,这可能会很有帮助:

为了检查你的数据框架有哪些列,你可以使用列属性:

如果需要编写代码来处理列名,可以使用 Python 的原生列表轻松完成。
任何 EDA 中的一个重要步骤是检查数据帧是否包含空值。对于熊猫,这不需要任何复杂的代码就可以完成。只需在数据帧上调用 isnull() 方法,然后使用 sum() 方法聚合值:

正如我们所看到的,我们的数据帧经过了很好的预处理,它不包含丢失的值。
同样,您可能希望查看不同列的数据类型。数据类型可通过 dataframe 的 dtypes 属性访问:

我们数据集中的所有列要么是数字型(整数),要么是分类型(对象)。
了解数据集的基本统计数据通常很有用。在 Pandas 中,您可以通过调用 describe() 方法来实现这一点:

此方法返回统计数据(计数、*均值、标准偏差、最小值、最大值等)。)关于数据帧的每个数字列。要查看关于分类特性的一些信息,您应该指定 describe() 方法的 include 参数,并将其设置为 ['O'] (见下图)。但是对于分类列,该方法只返回计数、唯一值的数量、最频繁的值及其频率。我们的大多数分类列都是二元的:


现在我们要用 Matplotlib 和 Seaborn 构建可视化。但是首先,我们需要导入这些包:
import matplotlib.pyplot as plt import seaborn as sns
让我们看看数据集中男性和女性的比例。为此,我们选择列性别,然后使用 value_counts() 方法,其中 normalize 参数等于 True 。然后我们调用 plot() 方法。这将使用 Matplotlib 来构建一个图形。我们可以看到数据集中的女生(大约 60%)比男生(大约 40%)多。相应的代码和可视化你可以在下面找到。

我们已经看到了性别特征在数据集中的分布。但是通常,最有趣的列是目标列。在我们的例子中,这个列叫做 final_target (它代表一个学生的最终成绩)。这次我们将使用 Seaborn 制作一个图表。Seaborn 包有用于此目的的 distplot() 方法。我们指定的参数是颜色(绿色)和箱数 (10)。代码和图像如下:

从上面的直方图中,我们可以说最频繁的等级在 10–12 左右,但是从左侧开始有一个尾部(接*零)。也许在未来,在建立模型之前,值得对目标变量的分布进行转换,使其更接*正态分布。
Seaborn 包有很多方便的比较图形的函数。其中一个函数是 pairplot() 。您可以选择要分析的列,Seaborn 将在对角线上构建这些列的分布,并在所有其他位置构建散点图。每个散点图显示两个指定列之间的相互关系。在我们的例子中,这种可视化可能没有它应有的用处。它更适合连续的特征,而不是整数。但是,您可以理解这种可视化的要点:

让我们使用 Matplotlib 来看看数据集中所有数字列的分布。首先,我们创建一个只有数字列的 data frame(df _ num)。为此,我们使用 select_dtypes() Pandas 方法。我们指定只接受 float64 和 int64 数据类型,但是对于这个数据集,只接受整数列就足够了(没有浮点值)。此外,我们删除了 famsize_bin_int 列,因为它最初不是数字。

现在,我们在 df_num dataframe 上使用 hist() 方法来构建一个图:

在 hist() 方法的参数中,我们已经指定了绘图的大小、标签的大小和容器的数量。
或许,分析不同列和特定条件下的值的范围是很有趣的。这是如何工作的。我们想看看 final_target 列的范围如何根据学生父母的工作而变化。为此,我们使用 Seaborn 的函数 boxplot() 。在此之前,我们使用 Matplotlib 调整绘图的大小。父亲工作的图表如下所示:

这是母亲工作的图表:

箱线图允许查看*均值以及数据的高低四分位数。胡须显示了分布的其余部分。胡须外的点代表异常值。
从上面的图表中你可以得到一个有趣的认识,那就是如果学生的父亲或母亲是老师,那么这个学生很有可能获得高分。
同样的,我们可以看到女生在学业上比男生更成功:

EDA 最有趣的一点是探索变量之间的相关性。我们可以分析相关性,然后使用 Seaborn 将其可视化。这里我们只看数字列。在为机器学习模型训练做真正的准备时,科学家应该对分类变量进行编码,并像处理数字列一样处理它们。但是这超出了我们教程的主题。
下面代码的第一行使用方法 corr() 来计算不同列和 final_target 特性之间的相关性。我们丢弃最后一条记录,因为它是 final_target (我们对 final_target 与自身具有完美相关性这一事实不感兴趣)。
代码的第二行过滤掉所有弱相关性。在我们的例子中,我们只想看相关性,它大于 0.12(绝对值)。我们还想对列表进行降序排序。
第三行只是打印出结果。

我们可以看到,有 8 个特征与目标变量密切相关。有些是正相关,有些是负相关。例如,最强的负相关性与故障特征相关。如果学生过去成绩不好,他/她将来也可能继续学习不好,这是合理的。
此外,学生在周末或工作日饮酒越多,他/她的最终成绩越低。在空闲时间和行程时间变量之间也存在负相关性。学生的空闲时间越多,他/她的表现就越差。旅行越多的学生成绩也越差。
同时,我们有 3 个与目标变量正相关:studytime,Medu,Fedu。很明显,你花在学习上的时间越多,你的学习成绩就越好。有趣的事实是,父母的教育程度也与孩子的表现密切相关。
在热图上,您不仅可以看到与目标变量的相关性,还可以看到变量之间的相关性。例如,父亲和母亲的教育程度、学生外出的时间和饮酒量、失败次数和学生年龄等之间有很强的相关性。

探索相关性是 EDA 中最重要的步骤之一。它允许理解哪些功能可能是有用的,哪些是多余的,以及哪些新功能可以人工创建。
结论
在本文中,我们介绍了如何以编程方式将数据加载到 AWS S3,如何使用 Dremio 准备存储在 AWS S3 中的数据,以及如何在 Python 中分析和可视化这些数据。我们还展示了如何使用 Dremio 以及 Dremio 和 Python 代码连接到您的数据湖。在工作过程中,我们使用了 Matplotlib 和 Seaborn 包。
最初发表于【https://www.dremio.com】。
创建 python CLI 应用程序的简单方法
将机器学习应用程序包装到命令行界面的简单示例

克里斯里德在 Unsplash 上的照片
当我们创建任何类型的应用程序时,我们必须提供一个其他人有机会使用的接口。我想向您展示一个将 ML 应用程序包装到 CLI 界面的简单示例。
我认为可以肯定地说,我们希望用最少的努力获得最好的结果。在这种情况下,fire库将是最好的选择。fire是一个库,由 Google 开发并广泛使用。让我们通过具体的例子来探索它的功能:
main.pyimport fire
def add(a: int, b: int):
*"""
Returns sum of a and b* ***:param*** *a: first argument* ***:param*** *b: second argument* ***:return****: sum of a and b
"""* return a+b
if __name__ == "__main__":
fire.Fire({
"sum": add
})
这里fire从函数add创建 CLI 命令sum。从 python doc 中,它创建一个命令描述。
python main.py sum --help的输出:
NAME
main.py sum - Returns sum of a and bSYNOPSIS
main.py sum A BDESCRIPTION
Returns sum of a and bPOSITIONAL ARGUMENTS
A
first argument
B
second argumentNOTES
You can also use flags syntax for POSITIONAL ARGUMENTS
因此,您现在可以通过多种方式使用该命令:
python main.py 1 2
python main.py --a 1 --b 2
此外,您可以通过在函数定义中定义默认值来定义可选的命令参数:
def add(a: int, b: int = 2):
*"""
Returns sum of a and b* ***:param*** *a: first argument* ***:param*** *b: second argument (default: 2)* ***:return****: sum of a and b
"""* return a+b
现在python main.py sum --help的结果是:
NAME
main.py sum - Returns sum of a and bSYNOPSIS
main.py sum A <flags>DESCRIPTION
Returns sum of a and bPOSITIONAL ARGUMENTS
A
first argumentFLAGS
--b=B
second argument (default: 2)NOTES
You can also use flags syntax for POSITIONAL ARGUMENTS
因此,您现在可以通过多种方式使用该命令:
python main.py 1
python main.py 1 2
python main.py 1 --b 2
python main.py --a 1 --b 2
无需多言,您可以看到 CLI 应用程序配置是多么简单快捷。
现在让我们为 ML 应用程序的一个常见用例创建一个程序框架。假设您需要创建一个具有两个函数train和predict的 CLI 应用程序。训练函数输入是训练数据和一些模型参数,输出是经过训练的模型文件。Predict 接受用于预测的输入数据、定型模型,并将预测保存到输出文件中。
除了函数映射,fire可以从 python 类实例创建 CLI 接口,在这种情况下,这可能是一个更好的选择。在我们的例子中,代码可能是:
import fire
import pickle
import logging
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def load_model(model_path: str):
*"""Loads model from `model_path`"""* with open(model_path, 'rb') as file:
saved_model = pickle.load(file)
return saved_model
def save_model(model, model_path: str):
*"""Saves `model` to `model_path`"""* with open(model_path, 'wb') as file:
pickle.dump(model, file)
class Classifier:
*"""
Some classifier, that makes some random classifications.
"""* def train(self, train_data_path: str, model_path: str, k: int = 5):
*"""
Trains model on `train_data_path` data and saves trained model to `model_path`.
Additionaly you can set KNN classifier `k` parameter.* ***:param*** *train_data_path: path to train data in csv format* ***:param*** *model_path: path to save model to.* ***:param*** *k: k-neighbors parameter of model.
"""* logger.info(f"Loading train data from {train_data_path} ...")
df = pd.read_csv(train_data_path)
X = df.drop(columns=['y'])
y = df['y']
logger.info("Running model training...")
model = KNeighborsClassifier(n_neighbors=k)
model.fit(X, y)
logger.info(f"Saving model to {model_path} ...")
save_model(model, model_path)
logger.info("Successfully trained model.")
def predict(self, predict_data_path: str, model_path: str, output_path: str):
*"""
Predicts `predict_data_path` data using `model_path` model and saves predictions to `output_path`* ***:param*** *predict_data_path: path to data for predictions* ***:param*** *model_path: path to trained model* ***:param*** *output_path: path to save predictions
"""* logger.info(f"Loading data for predictions from {predict_data_path} ...")
X = pd.read_csv(predict_data_path)
logger.info(f"Loading model from {model_path} ...")
model = load_model(model_path)
logger.info("Running model predictions...")
y_pred = model.predict(X)
logger.info(f"Saving predictions to {output_path} ...")
pd.DataFrame(y_pred).to_csv(output_path)
logger.info("Successfully predicted.")
if __name__ == "__main__":
fire.Fire(Classifier)
python main.py的输出为:
NAME
main.py - Some classifier, that makes some random classifications.SYNOPSIS
main.py COMMANDDESCRIPTION
Some classifier, that makes some random classifications.COMMANDS
COMMAND is one of the following:predict
Predicts `predict_data_path` data using `model_path` model and saves predictions to `output_path`train
Trains model on `train_data_path` data and saves trained model to `model_path`. Additionaly you can set KNN classifier `k` parameter.
以及相应的命令文档:
python main.py train --help:
NAME
main.py train - Trains model on `train_data_path` data and saves trained model to `model_path`. Additionaly you can set KNN classifier `k` parameter.SYNOPSIS
main.py train TRAIN_DATA_PATH MODEL_PATH <flags>DESCRIPTION
Trains model on `train_data_path` data and saves trained model to `model_path`. Additionaly you can set KNN classifier `k` parameter.POSITIONAL ARGUMENTS
TRAIN_DATA_PATH
path to train data in csv format
MODEL_PATH
path to save model to.FLAGS
--k=K
k-neighbors parameter of model.NOTES
You can also use flags syntax for POSITIONAL ARGUMENTS
python main.py predict --help:
NAME
main.py predict - Predicts `predict_data_path` data using `model_path` model and saves predictions to `output_path`SYNOPSIS
main.py predict PREDICT_DATA_PATH MODEL_PATH OUTPUT_PATHDESCRIPTION
Predicts `predict_data_path` data using `model_path` model and saves predictions to `output_path`POSITIONAL ARGUMENTS
PREDICT_DATA_PATH
path to data for predictions
MODEL_PATH
path to trained model
OUTPUT_PATH
path to save predictionsNOTES
You can also use flags syntax for POSITIONAL ARGUMENTS
使用示例:
python main.py train train.csv knn.sav --k 7
python main.py predict test.csv knn.sav out.csv
现在,您可以使用这个代码片段来创建自己的 CLI 应用程序。进一步改进的一些提示:
- 使用日志记录代替打印
- 创建参数验证
- 为最终用户创建带有简短应用程序使用说明的自述模板。
- 在https://github.com/google/python-fire上探索更多酷炫功能
我希望这篇文章将是有用的和信息丰富的。期待您的反馈!
向您的 Dash 应用程序添加广告身份验证
使用 Flask 集成 Dash 和 LDAP 的一个非常简单的方法

在 Unsplash 上由 Dane Deaner 拍摄的照片
在大多数组织中,登录凭证由目录服务(如 Active Directory)管理。如果您设法将 Dash 与您组织的目录服务相集成,那么用户只需使用他们现有的凭证登录您的 Dash 应用程序。一种常见的方式是通过 LDAP (一种用于与 Active Directory 等目录服务对话的开放协议)和 Flask (一种轻量级 web 应用程序框架)。在这篇文章中,我将演示如何用 Python 中的 Dash 以最简单的方式集成 LDAP 和 FLASK。
先决条件
在进入任何代码之前,您需要已经启动并运行了 LDAP。这是一个重要的步骤,超出了本文的范围,本文只关注 Python 方面的内容。然而,如果你需要广告整合,我假设你在一个有自己 IT 部门的大公司工作,希望这个部门(1)不是你,( 2)愿意帮助你!
假设 LDAP 已经启动并运行,继续运行以下命令,从 GitHub 克隆示例代码:
git clone https://github.com/epetrovski/dash_ldap
我们还需要几个库来构建一个 Dash 应用程序,并让它与 LDAP 一起工作——总共四个。如果您已经使用了 Pipenv ,只需在克隆的 dash_ldap 目录内的终端中运行以下命令,即可获得一个安装了依赖项的完整的工作虚拟环境:
pipenv sync
如果您不想弄乱 Pipenv,只需安装您需要的依赖项:
pip install dash flask flask-simpleldap gunicorn
app.py 演练
你需要的所有代码都在 app.py 里。让我们一行一行地过一遍。
第一个技巧是让 Dash 在一个 Flask 应用程序中运行,这个应用程序向外界提供 Dash 应用程序。这是通过在初始化时将 Flask 对象传递给 Dash 应用程序的服务器参数来实现的,如下所示:
app = Dash(__name__, server=Flask(__name__))
然后,为了举例,我们定义一个 Dash 应用程序。这个应用程序只是一个简单的占位符,但是不要担心,当你用高级回调等构建自己的应用程序时。,它不需要对 LDAP 集成设置进行任何更改。
app.layout = html.P('Hello world!')
您现在需要通过更新 Flask 的配置字典来为 LDAP 配置 Flask。下面的详细信息只是一个占位符,因为您的凭据将取决于您公司的 LDAP 设置—再次询问!
app.server.config.update({
'LDAP_BASE_DN': 'OU=users,dc=example,dc=org',
'LDAP_USERNAME': 'CN=user,OU=Users,DC=example,DC=org',
'LDAP_PASSWORD': os.getenv('LDAP_PASSWORD')})
你可能已经注意到,我冒昧地在LDAP_PASSWORD后面加了一个os.getenv()。我假设你永远不会在代码中存储密码,而是使用类似于环境变量的东西。
非常重要的是,现在我们需要通过用LDAP(app.server).basic_auth_required()包装所有已经用 Flask 注册的视图函数来保护它们:
for view_func in app.server.view_functions:
app.server.view_functions[view_func] = LDAP(app.server).basic_auth_required(app.server.view_functions[view_func])
最后,我们可能需要一种方法来快速运行 Flask 应用程序以进行测试。通常我们会使用app.run(),但是因为这个应用是在 Flask 服务器上提供的,所以我们使用app.run_server():
if __name__ == '__main__':
app.run_server()
测试一下
您可以通过运行以下命令来确认 AD 集成正在运行:
python3 app.py
现在导航到 http://127.0.0.1:8000 ,您应该会看到一个登录提示。输入你的身份证明,你应该会看到“你好,世界!”首页。
既然您对一切顺利运行感到满意,请记住,使这一切工作的关键部分是 flask-simpleldap 包。这是一个很棒的 Python 包,它可以解决一个非常乏味但却至关重要的 It 需求。
投入生产
如果您在生产中运行 Dash 应用程序,您应该在生产级 http 服务器上运行该应用程序,如 gunicorn 。您已经安装了这个,所以只需运行:
gunicorn app:server
这是因为在app.py中,我定义了:
server = app.server
这就是你要的,一个登录受保护的 Dash 应用程序,集成了一个目录服务,适合生产!
在 Python 中优化“某物”的简单方法
使用 Python 中的线性规划解决预算优化问题

为什么优化预算很重要?它让我们能够控制广告支出,决定花费多少,并最大化预期结果(访问,点击等)。例如,给定 10,000 美元的预算及其约束条件,我们能够确定每个营销渠道的最优预算分配,从而使结果最大化。这将使我们能够避免在单一渠道上的拥挤,即我们把所有东西都放在一个篮子里,而是分散到表现最好的渠道。
优质的预算优化策略可以显著提高搜索广告活动的效果,从而帮助广告主在激烈的在线营销竞争中取得成功。
什么是线性规划?

线性规划优化中的一个线性规划问题的图解
线性规划(LP)是获得最佳结果的最广泛使用的优化技术之一。David G. Luenberger 所著《线性和非线性编程》一书摘录:
顾名思义,线性规划问题的特征在于未知数的线性函数;目标在未知数中是线性的,约束是未知数中的线性等式或线性不等式。
似乎线性规划的流行主要在于分析的公式化阶段,而不是求解阶段——这是有道理的。因此,对于我们今天所关心的问题,它可以表述为:
预算约束限制在三个不同渠道(电视、广播、报纸)之间分配的资金总量,预算约束采用 x1 + x2 + x3 ≤ B 的形式,其中 B 是预算。电视的总花费应该少于 200 美元,广播应该少于 500 美元,报纸应该少于 500 美元。而总预算上限为 1000 美元。
除此之外,我们还应该找出一个问题的目标函数,在这个问题中,我们计划最大化或最小化我们喜欢的结果(点击、销售等)。

从 David G. Luenberger 于 1973 年出版的《线性和非线性规划》一书中获得的线性规划问题公式示例
我将使用来自 Kaggle 的开源广告数据集来展示它是如何工作的!
履行
理想情况下,当使用 LP 时,目标函数应该是线性的。
如果一个目标函数由于其固有的定义而不是纯线性的,那么将其定义为线性的往往比决定某种其他函数形式并使其他人相信更复杂的形式是最好的选择要容易得多。因此,线性由于其简单性,经常被选择作为简单的解决方法,或者当寻求一般性时,被选择作为在一类类似问题中同样适用(或不适用)的唯一函数形式

纸浆优化工艺2009
建立预测模型

数据帧
我们首先使用 SK-Learn 的线性回归建立一个多元线性回归模型。这个内核提供了一个很好的方法来验证线性回归是否可以被使用,因为线性回归受到几个假设的限制。
### SCIKIT-LEARN ###feature_cols = ['TV', 'Radio', 'Newspaper']
X = df_advertising[feature_cols]
y = df_advertising[["Sales"]]# instantiate and fit
lr = LinearRegression()
model = lr.fit(X, y)# print the coefficients
print(SkLearn_result.intercept_)
print(SkLearn_result.coef_)

y 轴截距和系数
我们能够从给定的模型中获得 y 截距和系数。

我们模型的准确性
RMSE 为 1.509,我们的模型非常准确,根据上图,我们可以看到,与实际值相比,它的预测相对较好。有了预测模型,我们现在可以开始构建线性规划的目标函数。
使用 LP 优化
我们将使用一个名为 PuLP 的 python 包。这是一个针对 Python 的优化包。纸浆是直截了当的,非常容易使用!
prob = LpProblem("Ads Sales Problem", LpMaximize)
我们从使用 LpProblem 函数定义问题开始,我们希望最大化输出,因此“LpMaximize”将是参数。然后,我们将指定我们的约束条件,例如我们应该为给定的渠道花费多少预算。
#TV <= 200
x = LpVariable("x", 0, 200)#Radio <= 500
y = LpVariable("y", 0, 500)#Newspaper <= 500
z = LpVariable("z", 0, 500)#Should be less than $1000
prob += x + y + z <= 1000
有了约束条件,我们现在可以使用模型给出的系数构建我们的目标函数:

coef = model.coef_prob += coef.item(0) * x + coef.item(1) * y + coef.item(2) * z + model.intercept_[0]
然后通过调用 solve()函数,它将为我们解决这个问题,我们还可以检查优化的状态。通过打印它,我们可以得到下面的结果。
prob.solve()
LpStatus[status]

我们如何知道每个变量的最优值?
只需使用一个简单的 for 循环来访问概率变量,我们就能够获得每个变量的最优值以及下面的最大目标值。
for v in prob.variables():
print(v.name, "=", v.varValue)
print("Objective = %f" % (prob.objective.value()))

分析
现在我们知道了每个营销渠道应该花多少钱,我们肯定应该使用它作为基线模型来分配我们下一次营销活动的预算。实际上,我们可以实现整个流程的自动化,在这一过程中,每天都可以为一次活动分配或优化预算。
结论
当可以应用于正确的用例时,优化的线性规划是强大的,因为它提供了关键的管理洞察力。广告商通常将预算视为简单的约束,并投入大量精力来寻找更有效的方式,以实现各种市场所定义的可能运营。一个简单的预算分配和调整策略可以在活动管理中显著减少有效点击/收入/销售方面的损失。
参考
- 线性和非线性规划https://www.springer.com/gp/book/9780387745022
- 纸浆—【http://coin-or.github.io/pulp/
- 本教程的资源库—https://github . com/georgeblu 1/Data-Projects/blob/master/Budget % 20 optimization . ipynb
- https://towards data science . com/linear-programming-and-discrete-optimization-with-python-using-pulp-449 F3 C5 F6 e 99
图像引用
- https://www . researchgate . net/figure/Graphical-solution-of-a-linear-programming-problem _ fig 1 _ 2420905
- https://link.springer.com/book/10.1007/978-0-387-74503-9
- http://coin-or.github.io/pulp/
如果您有任何问题或反馈,请随时通过我的 LinkedIn 联系我。简单介绍一下,我是 Airasia.com 的一名数据科学家,专注于打造优秀的产品和推动增长,因为我热爱我所做的事情。
如何挑选合适的型号
从精确度分布来看,IQR 和箱线图是选择最佳模型的一种方法

在数据科学中,发现自己有几个表现几乎相同的模型/方法并不少见。当这种情况发生时,您如何知道选择哪个模型呢?在本文中,我将介绍一种选择最佳模型的方法,即真实模型。
我将使用乳腺癌威斯康星州数据集,可在这里:【https://www.kaggle.com/uciml/breast-cancer-wisconsin-data】T2。它包含 569 个观察值和 32 个描述性变量。因变量诊断是二元的。如果癌症是恶性的,它等于 1,如果癌症是良性的,它等于 0。让我们从导入所需的包和数据开始。
library(ggplot2)
library(randomForest)
library (e1071)
library(devtools)
library(ggbiplot)**#Import data** df = read.csv("data.csv")
然后,快速地,让我们清理数据(有些列是空的或无用的),将诊断变量转换为[0,1]变量,而不是字符串。
**#Y as factor** df$diagnosis = ifelse(df$diagnosis=="M", gsub("M", 1, df$diagnosis), gsub("B", 0, df$diagnosis))df$diagnosis = as.factor(df$diagnosis)**#Remove useless columns** df = df[,c(-33,-1)]
这是因变量的分布:

诊断分布
这些课程看起来并不不*衡。我们现在可以进入下一步了。下面,我将创建一个“for 循环”。在循环的每次迭代中,我会将数据分成两组,训练和验证。之后,我将使用随机森林、SVM 和逻辑回归来训练和预测三个独立的模型。通过将所有这些放入一个“for 循环”并每次改变种子,它将允许我每次收集三个模型在每次迭代中的精度性能。更改 set.seed()会更改训练和验证之间数据的随机重新分配。
这实质上是同时在三个模型上进行交叉验证。这也是有益的,因为它允许我每次都在相同的数据集上比较模型。对于每次迭代,每个模型都在相同的数据上进行训练和验证。这意味着我们可以在每个拟合模型之间进行公*和一致的比较。代码如下:
这是三个模型在 200 次迭代中的*均精确度:
- 随机森林:96.7%
- SVM: 95.1%
- 逻辑回归分析:97.1%
逻辑回归似乎是该数据集的最佳算法。然而,要选择正确的模式,我们不能止步于此。
选择正确的模型
查看上面的结果,我们看到逻辑回归胜出,但其准确性与其他模型准确性的差异并不显著。为了知道我们是否真的有最好的模型,我们需要查看准确性度量的分布。这类似于边际解释 vs 条件解释的思想:无论数据如何,模型*均来说是好的还是总是表现良好。
这很有用,因为它让我们知道模型是否总是精确的,或者它们的性能是否是可变的。根据具体情况,我们可能需要最佳*均模型或最小变量模型。拥有准确的分布信息只会有助于做出一致的选择!
以下是如何使用密度函数获得存储在 result_matrix 中的分布图:
a=density(result_matrix[,1])**#Getting the plot** plot(a, xlim=c(0.92, 1), ylim=c(0, 60), col='blue', lwd=2, main='Accuracy distribution of all models',
xlab='Accuracy')
lines(density(result_matrix[,2]), col='red', lwd=2)
lines(density(result_matrix[,3]), col='green', lwd=2)
legend(x=0.975, y=59,legend = c("Random Forest", "SVM", "Logistic Regression"), col = c("blue","red", 'green'), lty = c(1,1))

三种模型的精度分布
我们看到,逻辑回归似乎确实比随机森林好得多,即使两种精度分布都非常对称地分布在它们的*均值附*(逻辑回归似乎稍微瘦一些)。事实上,这两种分布看起来都很正常。然而,SVM 分布似乎更易变,传播范围更大,几乎第二次达到约 95%的准确性。
我们还可以获得箱线图和分位数间范围,这将让我们看到我们是否有异常值(使用箱线图),以及在我们的准确度值中第一和第三分位数之间的范围有多窄(使用 IQR)。下面是如何做到这一点:
**#Boxplots** boxplot(result_matrix, use.cols = TRUE,
main='Boxplot by algorithm',
ylab='Accuracy', xaxt = "n", col=c('blue', 'red', 'green'))
axis(1, at=1:3, labels=c('Random Forests', 'SVM', 'Logistic Regression'))**#IQR** IQR(result_matrix[,1])
IQR(result_matrix[,2])
IQR(result_matrix[,3])

三种模型的箱线图
以下是三种算法的 iqr:
- 随机森林:1.05
- SVM: 1.4
- 逻辑回归:1.05
这意味着对于随机森林和逻辑回归,50%的值(在第一个和第三个分位数之间)在 1.05%的精确度范围内。对于 SVM 来说,IQR 更宽一些,为 1.4%。
查看箱线图,我们看到的是,对于所有三种方法,我们只有很少的异常值(1 或 2)。逻辑回归只有 1,而随机森林有 2。
现在,我相信我们可以客观地说,逻辑回归算法是在我们的情况下使用的最佳算法,我们有数据来证明这一点。
感谢阅读!
一个简单而有用的 EDA 数据可视化库
探索性数据分析/双变量分析/数据科学
以有意义的方式可视化因变量和任何特征之间的关系

探索性数据分析(EDA)尤其适用于包含表格数据的项目。在 EDA 过程中,谨慎的数据科学家通常会通过寻找异常值或检查某些列是否有异常数量的缺失值来评估数据集的质量。EDA 也是初步了解预测变量和因变量之间的二元关系的理想*台。
对于连续数据,传统的线性相关系数通常表现不错,可以快速显示最具预测性的特征。然而,对于分类数据,事情变得有点复杂。
令我惊讶的是,我找不到一个 python 库*可以让你快速理解目标和任何预测器之间的关系,不管它们是什么类型(连续的还是分类的)。因此,我决定按照以下要求编写自己的工具:
- 提供与数据类型无关的统一接口
- 生成易于传达给非技术受众(如业务利益相关者)的视觉输出
这篇文章的目的是提供一个图书馆主要功能的游览。这个库被命名为 tprojection,它可以在 GitHub 上获得,并且可以很容易地用 pip 安装
pip install tprojection
我将使用流行的 Titanic 数据集来说明该库的主要功能。
案例 1:目标和预测都是分类的
构建预测模型时,您通常会寻找允许您定义与目标值有很大差异的部分的特征。这些都是很好的预测。
当目标和预测器都是分类的时,您可以通过将目标投影到每个设备上来评估预测器的质量。这可以通过一个熊猫声明来实现:
df.groupby(predictor).agg({target: [“mean”, “count”]})
如果我们对预测值“性别”应用此命令,并且目标从 Titanic 数据集中“幸存”,我们将获得类似的结果:

从这个结果来看,很明显男性比女性更不容易存活。在其最基本的用途中,库投影将简单地提供一种可视的方式来携带上述信息。

此图表显示了目标“存活”和预测值“性别”之间的关系。蓝色条表示每种设备的观察次数(左侧 y 轴)。红线代表每个设备的目标*均值(右侧 y 轴)。黑色虚线表示目标在整个数据集上的*均值(右侧 y 轴)。红色阴影区域是通过引导数据估计的置信区间。
上面的图表可以用几行代码生成:
from tprojection import Tprojection
from tprojection.datasets import load_datadf = load_data("titanic")
target = "survived"
predictor = "sex"tproj = Tprojection(df, target, predictor, target_type=”categorical”, feature_type=”categorical”, n_estimators=100)
tproj.plot()
首先,用所需的参数和选项创建一个 Tprojection 实例。然后,调用方法plot并绘制图表。标题中提供了情节的完整描述。请注意,图表坐标轴存储为属性(tproj.ax1和tproj.ax2),因此您可以轻松地更改图表的属性。
当观察数量变小时,置信区间(红色阴影区域)特别有用。在这种情况下,我们可能会观察到条件*均值与基线概率的较大偏差,这表明该模态适用于分割目标。然而,当置信区间很大时,这种解释必须小心。事实上,这意味着预测值和目标值之间的关系可能在不同的引导样本中有很大差异,这表明存在过度拟合的风险。
这种影响在下图中可以清楚地看到,该图分析了该目标对父母/子女人数的依赖性。对于模式parch = 3和parch = 5,我们观察到存活率相对较高,而相关的置信区间跨越基线概率的两侧。

目标“存活”和预测值“烤焦”之间的关系。
有趣的是,与parch = 4 和parch = 6相关联的置信区间的宽度等于零,即使相应的观察数量很小。当目标和模态之间存在一对一的关系时,就会发生这种情况。换句话说,在载有 4 或 6 名父母/儿童的乘客群体中没有幸存者。
该库还可以处理具有高基数的预测器。在这种情况下,显示设备的完整列表会使图表变得非常模糊。为了解决这一点,您可以向 tprojection 传递一个可选参数,该参数允许您根据最大值nb_buckets对设备进行分组。
tproj = Tprojection(df, target, “parch”, target_type=”categorical”, feature_type=”categorical”, n_estimators=100, nb_modalities=10)
tproj.plot()

预测者“小屋”和目标“幸存”之间的关系。左图显示原始设备,右图显示分时段设备。
上面的图表清楚地显示了这种方法的好处。左图显示了原始模态的预测值“舱室”和目标值之间的关系,无法阅读。右边的图更清晰,因为它只显示了一些编码的模态。可以通过一个属性来访问原始设备和编码设备之间的映射:
print(tproj.encoding)
当其他模态被分组时,投影将试图“按原样”保存具有足够数量观察值的模态。t 投影旨在构建包含大约相同数量观察值的nb_buckets组。然而,这并不总是可能的,特别是如果模式的分布严重倾斜。而实际情况往往如此。在上面的例子中,我们最初需要 10 个桶,但最终只需要 3 个桶。这是因为模态cabin = nan构成了几乎 80%的观察结果。因此,剩余的观察值仅分布在 3 个桶上。桶g1和g2各包含大约 10%的观测值,其余的分配给g3。
情况 2:目标是连续的,而预测值是分类的。
这在某种程度上是第一种情况的变体。除了目标*均值之外,我还添加了一个箱线图,描述目标在每种设备上的分布。置信区间的计算和显示已被禁用,以保持 viz 可读。
tproj = Tprojection(df, "fare", “cabin”, nb_modalities=10)
tproj.plot()

预测“舱位”(分桶)和目标“票价”之间的关系。
在上面的代码片段中,没有指定选项target_type和predictor_type。在这种情况下,库使用经验法则来评估变量是连续的还是分类的。
情况 3:目标是分类的,而预测值是连续的
在这种情况下,我们简单地比较由目标值决定的预测值的分布。为了便于比较,直方图被归一化。图例中提供了每个目标值的计数。
tproj = Tprojection(df, "survived", “fare")
tproj.plot()

预测值“票价”和目标值“存活”之间的关系。
默认情况下,正类对应于二进制目标的少数类。您可以通过用可选参数target_modality指定所需的值来改变这种行为。在这个阶段,tprojection 还不能真正处理多类问题,但是请注意,您可以通过使用target_modality kwarg 来模拟一种以一敌众的方法。
情况 4:预测值和特征都是连续的
包含这个案例是为了详尽,但它肯定不是项目带来最大价值的地方。该库只显示两个变量的散点图以及线性相关系数。还显示了从 seaborn regplot方法得出的最佳回归线。没有额外的特殊功能,因为有许多好的工具提供高级功能来分析两个连续变量之间的相关性。
tproj = Tprojection(df, "fare", “age")
tproj.plot()

预测值“年龄”和目标值“票价”之间的关系。
那都是乡亲们!我希望你会发现这个简单的库很有用。随意派生出 repo ,破解代码,并使其适应您的需求。
*免责声明:我在发布这个帖子之前发现了伟大的 sweetviz 库。尽管 sweetviz 包括类似的功能和更多功能,我仍然认为 tprojection 带来了有趣的特性。尤其是关于置信区间的内置估计或它处理高基数预测值的方式。
一种使用 PyCaret 进行异常检测的简化方法
用 python 中的 PyCaret 包解释离群点检测。

鲁珀特·布里顿在 Unsplash 上拍摄的照片
什么是异常?
按照谷歌的定义“ ”偏离标准、正常或预期的 ”的东西。同样的引用适用于数据科学领域,我们遇到了这样的异常,需要检测、处理或消除这些异常,以提供更好的业务解决方案或建立最佳的预测机器学习模型。就数据集而言,这些异常也被称为“异常值”,也指新奇、噪声、偏差和异常。
异常检测用例
有各种各样的领域实施这种技术,例如故障检测、入侵、欺诈检测、医疗保健监控、检测生态系统干扰等等。
在本文中,我们将学习如何使用 python 中的 PyCaret 库,通过几个步骤来检测给定数据集的异常值。
👉安装 PyCaret 库
建议在安装 PyCaret 库之前创建一个单独的 Conda 环境。如果您尝试在基本环境中安装它,可能会出现一些与依赖项相关的错误。当我尝试在一个新的单独的 Conda 环境中安装时,它很容易安装。要通过创建新的 Conda env 来了解安装的完整细节,请单击[ 此处
为了演示 PyCaret 库的异常值检测,我创建了一个数据集,并有意引入了一些极值。
在继续之前,请查看异常检测模块文档及其工作原理,以便更好地理解[ 此处为 ]
👉创建数据集

数据集中突出显示的异常值
👉导入模块并初始化设置()
setup()函数将采用强制数据帧参数,并在执行后开始处理。它自动推断变量的所有数据类型,要求我们确认或退出。从下面可以看出,数据类型被推断为分类的而不是数值的。我们需要包含另一个参数来更改数据类型。

输入退出,因为数据类型不是分类的

添加 numeric_features 参数后安装完成
👉创建模型
create_model()函数用于创建模型,有许多预定义的算法可用。我选择了“隔离森林”估计量,缩写为“iforest”。它返回训练好的模型对象。它们是“knn”,“PCA”,“SVM”,以及更多可供探索的模型。

使用 iforest 训练模型
👉可视化离群值
感谢 PyCaret 如此精彩的 3d 剧情。从下面的图中,我们可以看到黄点代表异常值,这些标记为 1。


表示标签的 3D 可视化绘图
👉分配标签
assign_model()函数返回带有异常值标志(1 =异常值,0 =内部值)和决策得分的数据帧。


离群值用标签值 1 表示
现在我们可以看到 PyCaret 如何轻松地检测异常值。还有其他函数也可用于预测,以便在该模块中保存和部署模型。请在此浏览 py caret中异常检测模块的文档
总结
在数据科学领域,有许多统计技术和传统方法可用于检测异常值。人们应该了解这些技术,以获得这一概念背后的基本原理,并在处理异常值时理解业务的细微差别。
本文通过一个示例数据集来展示 PyCaret 库在异常检测方面的强大功能,以便更好地理解。您可以使用真实数据集在项目中实现这种方法,以节省时间并捕捉美丽的图形。
我成为了 PyCaret 库的粉丝,我希望你也能经历同样的事情😊
你可以从我的 GitHub [ 链接 ]中找到代码
参考文献
- https://pycaret.org/anomaly-detection/
- https://pycaret.org/
- https://www.youtube.com/watch?v=q0dxYDq1A40
感谢阅读,快乐学习!🙂
ML 术语被终结:电气和电子工程师的监督机器学习
电气和电子工程师监督机器学习术语的简单解释
如果你进入了电气或电子工程领域(就像我曾经自己一样),你可能一直在和电阻、电容和电感打交道。
假设您以前没有去过实验室,但您还是仔细阅读了实验室分发的材料,并且能够识别出在实验过程中提供给您的不同电阻、电容和电感。
恭喜你!你的大脑刚刚执行了一个监督机器学习算法。

为什么我称之为监督?
因为你已经知道它们是什么,它们看起来是什么样子,可能是它们如何工作的一些细节。这是训练机器的经典方法之一,向它们提供每个小数据单元的含义。
因此,让我们按顺序将其分解为机器学习术语:
1.实例或数据点
知识的来源是以文本、数字或图像的形式呈现的信息单元,就像你在去实验室之前已经在你的讲义中学习过的那样。对你来说,成功识别的食物是你手中的照片,可能类似于下面的照片。

2.数据标志
你认为之前的图像有足够的信息吗?你怎么知道哪张图是电阻还是电容?你的传单上一定有图片说明。所以你知道了每张图片对应的是什么。
考虑一下这个:

因此,每当你指出一个实例并告诉你的计算机它是什么时,它就被称为数据标签,无论你告诉你的计算机关于你的实例的什么都是你的数据标签。
3.特征
你有没有注意到电阻的黄色调和红蓝带?或者可能是他们的沙漏图。你一定注意到了电容器的圆柱形状。陶瓷电容器是圆形和扁*的。至于电感,你一定注意到了它们周围的线圈。
这些都是电阻、电容和电感的特性或特征,有助于你正确识别它们。你基本上有一个如何识别它们的思维导图,但是在把它们输入 Excel 表格后,看起来会像这样。

你看到“标签”一栏了吗?这个标签列就是我们在电子白板上预测的那个。
4.培训用数据
你在传单上读到的一切都是你的训练数据。对于一个机器学习算法来说,表中的观察值汇总就是训练数据。
5.监督机器学习算法
一旦你在脑海中有了自己的特征,你就已经试着在黑板上寻找模式并匹配它们。人类的思维很敏捷,不是吗?
机器学习模型的基础是良好的数据。

如果你有这样的图像,就很难画出图案。机器学习算法本质上是从训练数据中的大量实例中学习,并试图找到类似人脑的模式。
但是我们为什么需要机器学习算法呢?
这里看起来很简单,有三个不同的标签。嗯,在大多数真实世界的场景中,情况并非如此。将会有成千上万的标签和天文训练实例。这能用人脑测量吗?不是吧?我们有自己的局限性,这就是为什么我们需要计算机辅助预测。我们利用机器的巨大计算能力,这就是为什么使用机器来学习模式是重要的。
6.测试数据和性能
当你试图从一个电容中识别出一个电阻时,你已经在处理测试数据了。测试数据是机器应用识别的模式并试图预测标签的看不见的实例。
现在,想象一下,如果您的实验室教师对每个正确的电阻给一分,对每个识别错误的电阻扣一分。然后将你的总分加起来,你发现你在我们班排名第五。
类似地,机器学习算法根据其在测试数据上的性能进行评估。对于监督学习,最常见的指标是准确度、精确度和召回率。重要的是要评估性能指标,以了解哪个是性能最好的模型。
7.因此,让我们尝试一个测试实例
你认为这是什么?

两个固定的圆柱形*顶物体,有一个线圈——它是一个感应器。
盛大,你猜对了!您刚刚使用训练数据集中的特征通过监督方法正确标记了一个看不见的感应器,这就是监督 ML 算法所做的事情!
图片来源:图片用于演示,来源于图片标题中提到的链接。没有侵犯版权的意图。
感谢光临。我希望你喜欢阅读这篇博客。
分析飞机登机方法的模拟框架
开发 Python 程序来计算各种配置的登机时间并可视化登机程序

照片由 Suhyeon Choi 在 Unsplash 上拍摄
1.介绍
人们害怕字母 C 有各种各样的原因。较低的学术等级用 C 表示,复杂的、较低级的编程语言被命名为 C,然而,在一个晴朗的冬天早晨,最让我害怕的 C 出现在我的登机牌上——西南寄宿组 C。
对于那些不熟悉西南航空公司登机流程的人,在办理登机手续时,您会被分配到三个组别(A、B 或 C)中的一个。A 组先登机,然后是 B 组,最后是 c 组。每个人在队列中都有一个号码(例如 A-10 或 B-25),并根据各自组的号码登机。当我的航班被指定 C-10 号时,你可以理解我的沮丧。
因此,我是最后几个登机的人之一。当 A 组和 B 组登机的时候,我在悲伤和安静的沉思中度过。我从来没有真正考虑过航空公司如何选择登机,但那天我考虑了。我想知道分析登机程序和比较各种方法的性能的可能性。
2.这个想法
如果给你一架飞机和几百名志愿者,让你测试一种登机方法的性能,你会怎么做?简单!给他们分配座位,排好队,装满飞机,测量完成这个过程需要的时间。
但是我没有飞机,我也不认为我能说服几百个人浪费他们宝贵的时间来满足我狂热的好奇心。所以我考虑在电脑上做同样的事情(这没什么可抱怨的)。
主要思想可以分为以下五点:
- 将飞机座位图表示为一个矩阵,每个元素都有一个唯一的索引(座位号)。
- 将外面的乘客队列和过道表示为一维数组。
- 给每位乘客一个预定义的座位号和他们在过道上移动的速度。
- 根据启发法,定义将乘客从过道转移到各自指定座位的规则。例如,移动到空行比移动到有人坐的行的座位更快。
- 将乘客从最初的队列转移到过道,然后转移到他们的座位,直到所有座位都被占用。然后测量整个过程所用的时间。
现在我们已经定义了原始的想法,让我们试着把它转化成一个算法,并用代码实现它。
3.定义移动规则
在我们开始编写代码之前,我们需要基于行为学定义一些东西,比如乘客速度和移动规则。
3.1 乘客通道移动
让我们假设一般人在过道里从一个座位移动到另一个座位所需的时间是 1 。请注意,我们在这里没有定义任何单位(如 s 或 min)。你可以认为这是无量纲的时间。
如果我们将时间 1 分配给所有乘客,由于每个人都有自己不同的速度,该模型将不太适用于现实生活。为了让它更真实,我们可以从*均值为 1、标准偏差为 0.2 (这是任意的,可以改变)的高斯分布(或钟形曲线)中采样通道移动的时间。因此,我们可以考虑乘客速度的可变性。
3.2 存放行李和座椅移动
当乘客到达他们指定的座位时,他们会先把行李放在头顶的行李架上,然后移到他们的座位上。这会占用一些时间,并导致后面的乘客停下来。让我们假设这个时间等于 2(移动时间的两倍)。
关于从过道到座位的移动规则,有 6 种可能的情况:
- 靠窗的座位,相邻的两个座位空着。
- 靠窗的座位,中间的座位有人,靠走廊的座位空着。
- 中间和过道都有人的靠窗座位。
- 中间靠过道的座位空着。
- 中间靠过道的座位有人。
- 靠过道的座位。
从过道移动到相应座位所需的时间取决于以下哪种情况适用。对于靠窗的座位,如果相邻的座位是空的,搬进去会更快。否则,相邻座位上的人必须首先走到过道,让乘客进来,然后回到自己的位置上。所有这些都会占用登机过程中的大量时间。
因此,计算每个乘客在每个场景中需要走多少步,我们可以定义一组乘数,当乘以乘客的移动时间,给出移动到特定座位所需的时间。
我们将乘数定义如下(每个乘数加 2 以说明行李的存放):
- 空行:1+2=3
- 过道占用:4+2=6
- 中间被占用:5+2=7
- 过道和中间有人:7+2=9
我们现在准备开始算法和代码。
4.用 Python 实现
我们将在 Jupyter 笔记本中详细介绍上述想法的实现。代码片段贴在下面,整个 Jupyter 笔记本的链接在最后给出。
步骤 1:初始化
我们将只需要 scipy 模块进行模拟,所以我们从导入它开始。
注意:像可视化这样的附加特性将需要像 matplotlib 这样的绘图工具,但这不包括在本演示中。关于可视化,请参考文章末尾的“可视化说明”。
import scipy as sci
首先,我们需要初始化许多参数和数组/矩阵来存储所有的乘客数据。由于西南航空公司通常使用一架波音 737 ,我们将把它的规格包括在我们的模型中。它有 23 行和 6 列。
我们将使用大量的字典来记录事物。所有乘客都将被分配一个从 0 到 137 的独一无二的识别号码(比如说 UIN 的号码),这个号码将作为我们字典的密钥。下面定义的变量执行以下功能:
- 座位:存储飞机座位图(-1 表示无人,乘客 UIN 表示有人)
- 过道 _q :存储飞机的过道车道(-1 表示无人,乘客 UIN 表示有人)
- pass_q :存储机外乘客队列(乘客 uin 列表,从 0 到 137)
- row_q_init 和 col_q_init :存储分配给每位乘客的座位行号和列号。
moveto 数组和字典将在后面的章节中解释。
#Initialize
#Define number of rows and columns
n_rows=23
n_cols=6#Calculate number of passengers
n_pass=n_rows*n_cols#Create seat matrix
seats=sci.zeros((n_rows,n_cols))
seats[:,:]=-1#Create aisle array
aisle_q=sci.zeros(n_rows)
aisle_q[:]=-1#Create initial passenger number queue
pass_q=[int(i) for i in range(n_pass)]
pass_q=sci.array(pass_q)#Create array for seat nos
row_q_init=sci.zeros(n_pass)
col_q_init=sci.zeros(n_pass)#Let's create moveto arrays
moveto_loc=sci.zeros(n_pass)
moveto_time=sci.zeros(n_pass)moveto_loc_dict={i:j for i in pass_q for j in moveto_loc}
moveto_time_dict={i:j for i in pass_q for j in moveto_time}
第二步:分配座位
在乘客进入过道之前,他们需要分配座位。座位分配的顺序取决于登机方式。例如,与随机订单相比,从后到前的董事会订单将有不同的座位分配。
我们将在这里看一下两种不同的座位分配(更多信息,请参考文章末尾的 Jupyter 笔记本)。我们将在这里定义一个函数,它接受行和列数组(空),一个指定分配类型、乘客数量和行数的字符串(最后两个是预定义的)。这里定义的第一个顺序是超理想不实际(SINP) ,第二个是随机顺序。
我们将在最后看一下各种不同的登机方法及其结果,但现在,SINP 包括首先填满所有的窗口,然后是所有的中间,然后是所有的过道,这样就绝对不会浪费时间在换座位上。这是(几乎)最理想的寄宿方式。随机是不言自明的——座位分配是随机的。
代码中需要理解的内容:
- 0 和 5 列指的是窗口
- 1 和 4 列指的是中间
- 第 2 栏和第 3 栏指的是过道
很难定义座位顺序,因为它本质上涉及到 2D 座位图到 1D 乘客队列的编码。有多种方法可以做到这一点,下面的代码代表了其中一种可能的方法。你可以自由地尝试你自己的顺序和方法来定义它们。
def AssignSeats(rq,cq,assign_type,n_pass=n_pass,n_rows=n_rows):
if(assign_type=="SINP"):
#Initialize initial and final positions
i=0
f=n_rows
#Define column seating positions
c=[0,5,1,4,2,3]
#Define iteratiion counter
count=0
#Assign queue
while(f<=n_pass):
rq[i:f]=list(reversed(range(0,n_rows)))
cq[i:f]=[c[count]]*n_rows
i+=n_rows
f+=n_rows
count+=1
if(assign_type=="Random"):
#Initialize possible row positions
av_rows=sci.arange(0,n_rows,1)
#Make as many copies of these positions as the number of columns
av_rows=sci.tile(av_rows,(n_cols,1))
av_rows=av_rows.T.flatten()
#Initialize possible column positions
av_cols=sci.arange(0,n_cols,1)
#Make as many copies of these positions as the number of rows
av_cols=sci.tile(av_cols,(n_rows,1)).flatten()
#Create list of all possbile seat positions
av_seats=sci.zeros((n_pass,2))
for i in range(n_pass):
av_seats[i]=[av_rows[i],av_cols[i]]
#Randomize seat positions
sci.random.shuffle(av_seats)
rq=av_seats[:,0]
cq=av_seats[:,1]return rq,cq
第三步:定义时间,运动规则和字典
现在我们已经定义了分配座位的函数,是时候使用它来创建我们的乘客队列了。出于演示的目的,我们将使用 random 。
此外,我们需要为每个乘客分配移动时间(基于高斯分布)并定义我们的乘数。
我们还需要将所有这些信息编码到字典中,以便根据每个乘客的 UIN 轻松获得他们的时间和座位分配。
最后,我们需要定义这里所谓的 sum_time 。当时间到的时候,每个乘客都必须从外面的乘客队列移到过道。这基本上是在他们前面的乘客的时间总和已经过去的时候。然后你会看到我们需要定义一个数组,数组中的每个元素都等于当前乘客的时间和前面乘客的时间之和。
#Assign seating order
row_q,col_q=AssignSeats(row_q_init,col_q_init,"Southwest")#Create array for times
mean_time=1.
stddev_time=0.2
time_q=sci.random.normal(loc=mean_time,scale=stddev_time,size=n_pass)#Define multipliers (+2 for stowing luggage)
empty_mult=1+2
aisle_mult=4+2
middle_mult=5+2
aisle_middle_mult=7+2#Create seat and speed dictionary
pass_dict={}
time_dict={}seat_nos=sci.column_stack((row_q,col_q))
for i in range(n_pass):
pass_dict[i]=seat_nos[i]for i in range(n_pass):
time_dict[i]=time_q[i]#Create sum time array
sum_time=sci.zeros(n_pass)
for i in range(n_pass):
sum_time[i]=sum(time_q[:i+1])
步骤 4:定义从乘客队列到过道的移动
我们的乘客队伍已经在飞机外面准备好了。在我们开始登机之前,我们需要定义他们从外面的队列到里面的通道的移动。这可以通过定义一个简单的函数来完成。该功能检查乘客的 sum_time 是否已过。如果有(并且通道中的第一个位置是空的),那么它将乘客的 UIN 复制到通道中,并从乘客队列中删除它。因此,随着时间的推移,乘客队伍将变得越来越短,最终会空出来。
#Create function to move passengers into aircraft
def MoveToAisle(t,aisle_q,pass_q,sum_time):
if(t>sum_time[0]):
if(aisle_q[0]==-1):
aisle_q[0]=pass_q[0].copy()
pass_q=sci.delete(pass_q,0)
sum_time=sci.delete(sum_time,0)
return aisle_q,pass_q,sum_time
第五步:让乘客登机
这是代码中最复杂的部分,因为它涉及到嵌套许多 if 条件和玩弄字典。
基本理念是为乘客分配行动,要么分配到他们过道前面的位置,要么分配到他们的座位(如果他们已经到达那一排),当时间到了,通过像移动棋子一样移动乘客来“行动”。每位乘客将在通道中向前移动一段等于其移动时间的时间,并在一段等于其移动时间乘以适当乘数的时间后进入座位。
算法如下:
- 浏览所有过道元素。对于过道中的每个乘客,执行以下操作。
- 检查是否有任何移动被分配给乘客。
- 如果已经分配了移动,检查时间是否已经过去。如果有,将乘客移到他们的座位(如果他们已经到达指定的排)或过道的下一个位置(如果是空的)。如果时间还没有过去,什么也不要做。
- 如果没有分配移动,请参考乘客座椅分配。如果他们已经到达分配给他们的排,给他们各自的座位分配一个移动,并分配一个适当的移动时间。如果他们还没有到达分配给他们的排,分配一个移动到通道中的下一个位置,并分配一个合适的移动时间。
- 更新时间并返回步骤 1。
算法退出条件如下:座位图中所有乘客的 uin 之和必须与飞机外初始乘客队列中所有乘客的 uin 之和相匹配。
下面的代码墙可能看起来很长,令人望而生畏,但几乎每一步之后都有注释来解释。
5.结果
文章中给出的代码只能为一种登机方法运行一次登机程序。如果该过程重复多次,则可以为每种登机方法计算*均时间(以及等于标准偏差的误差)。这是针对六种不同的方法进行的,并且比较了它们的时间。每个登机方法模拟运行 20 次。
5.1 超理想不实际(SINP)
方法:首先登上所有窗户,然后是中间,最后是过道。然而,必须这样做,使得第一个乘客到最后一排,第二个到倒数第二排,等等,以确保没有时间浪费在站在过道上。
时间:2105
5.2 窗口-中间-过道(WMA):
方法:这类似于 SINP,但是窗户、中间和过道是随机登上的,这样一些时间就浪费在过道上了。这种方法被一些航空公司使用,比如联合航空。
时间:2699
5.3 随机
方法:随机登板,无特定方案或顺序。
时间: 347 19
5.4 西南
方法:没有“西南方法”,因为开放式座位意味着你可以坐任何你想坐的座位。然而,我在西南航空公司的航班上观察到了一种特殊的模式,这种模式是由于乘客的偏好而产生的。通常情况下,飞机前部的靠窗和靠过道的座位会被占满,然后是后面的座位。接下来,所有的中间座位都是从前到后填满的(对飞机中间座位的厌恶似乎是普遍的,因此给西南航空公司的登机过程提供了某种模式)。
时间: 362 11
5.5 从后到前(BTF)
方法:分三组登机,第一组占飞机后三分之一,最后一组占前三分之一。这是大多数航空公司登上经济舱的方法。
时间: 366 20
5.6 从前到后(FTB)
方法:你了解 BTF 吗?把它反过来。这听起来是个糟糕的主意,对吗?头等舱、商务舱和非常特别的超级高级行政舱的座位就是这样做的。
时间: 418 18
6.讨论

一些意见和相关结论:
- 模型给出的时间数字只有在比较这些方法时才有意义。如果我们需要以秒或分钟为单位的精确登机时间,我们需要根据实验数据定义移动时间和乘数。
- SINP 和 WMA 方法提供了比其他方法更高的性能,因为在过道上的等待时间明显更少,座位移动也更少。它们的标准差也很低,因为其中有相当小的随机因素。
- 令人惊讶的是(也可能不是,根据实验和其他计算机模拟),随机方法比常用方法更好。这是因为如果人们真的是随机分布的,过道里的等待时间会更少。
- 西南和 BTF 的方法同样有效。虽然《流言终结者》的研究显示,西南方的方法比普通的 BTF method⁴方法要好得多,但由于我们在模型中所做的假设,这种方法在这里可能没有得到很好的体现。一个更详细的模型,允许乘客动态地占据空的位置和那些导致更少等待时间的位置,可能会导致西南方法的更好性能。
- 毫不奇怪,FTB 的方法效果最差。即使从视觉上也很清楚,这种方法具有最长的过道等待时间,当乘客从前到后占据座位时,会导致非常频繁的停车。
SINP 方法似乎是完美的缩影(尽管一点也不实用)。然而,在 Jason Steffen 的一篇研究文章中,实际上定义了一种更快的理论方法,称为 Steffen 方法。你可以从文章末尾的链接中了解更多信息。
7.关于可视化的注释
本文中的视觉效果是通过在每几次迭代后捕捉座位图矩阵,并使用 matplotlib 制作 imshow 图来生成的。然而,我没有在文章中包含代码,因为它不涉及任何算法复杂性,而只是一些绘图技巧。
我已经编写了一个通用程序,可以解决任何方法(如果需要的话,可以多次)并绘制一个可以保存的动画。可以在 GitHub 上查看并下载。
如果您想查看模拟的 Jupyter 笔记本,请点击此处。
参考资料和阅读
- “不同的航空公司如何搭载他们的乘客”(Lifehacker),https://life hacker . com/How-Different-Airlines-Board-Their-Passengers-1794474413
- “飞机登机方法实验测试”(杰森·h·斯特芬,乔恩·霍奇基斯),【https://arxiv.org/pdf/1108.5211v1.pdf
- “航空公司乘客的最佳登机方法”(杰森·h·斯特芬),https://arxiv.org/pdf/0802.0733.pdf
- 《流言终结者》第 222 集:飞机登机(流言终结者)https://mythresults.com//airplane-boarding
关于这个话题的一个有趣的视频:“航空公司不会使用的更好的登机方法”(CGP Grey 在 YouTube 上),https://www.youtube.com/watch?v=oAHbLRjF0vo&VL = en
免责声明:这篇文章和分析背后的动机纯粹是好奇,而不是试图证明任何一种方法优于另一种方法。
如果您有任何问题、意见或建议,您可以[给我发电子邮件](mailto: gauravsdeshmukh@outlook.com)或在 Twitter 上联系我。
从网页中抓取数据集的一行 Python 代码

马库斯·斯皮斯克在 Unsplash 上的照片
使用 Python 从网页和下载中搜寻 API 端点
无论我们拥有什么水*的数据科学/分析技能,没有数据集你什么都做不了。
的确,有许多开源数据集,如 Kaggle 和 Data.world。然而,它们更适合用于练习和学习目的,但可能无法满足我们的一般需求。
通常,数据科学家/分析师可能有或多或少的网络搜集技能,所以无论何时你在网站上看到数据集,都更容易获得。从网站上抓取内容后,一系列的转换、提取和清洗操作将帮助我们为下一步获取干净的数据集。这是 Python 的典型用法之一,因为 Python 中有很多优秀的 web 抓取库可用,比如 Scrapy 和 Beautiful Soup。
然而,学习这些网络抓取库并不容易。此外,对于那些没有 web 开发背景的人来说,这可能不是数据科学家/分析师的常见技能,理解和确定 HTML DOM 和 XPath 等概念可能会更加困难。
然而,在本文中,我将介绍一种更简单的从网站下载数据集的方法。你会发现你甚至可以用熊猫来做所有的工作!
新冠肺炎新病例数据集

第一个例子是新冠肺炎新案例数据集。原来有许多公开的数据来源,如政府网站将公布这一点。然而,我只是想以此为例,因为我发现这是一个非常好的典型例子。
今天,当我从“时代”(澳大利亚的一个受欢迎的媒体)网站扫描新闻时,我发现有一个条形图显示澳大利亚每天新增的确诊病例(见下面的截图)。

截图来自网站:https://www.theage.com.au/
如果我想得到他们的数据呢?让我们找到它的 API 端点!
搜寻 API 端点
现在大多数流行的 web 浏览器都提供了它们的开发人员控制台。我们将使用控制台来完成这项工作。以下是从浏览器调用控制台的一些快捷方式:
- 谷歌浏览器:Ctrl + Shift + I
- 火狐:Ctrl + Shift + K
- 微软 Edge: F12
在这里我将使用谷歌浏览器进行演示。但是不用担心,大多数浏览器都有非常相似的开发者控制台。相信你一定能搞清楚特色在哪里。

谷歌 Chrome 开发者控制台截图
控制台出现后,转到“网络”选项卡。我们正在寻找一个 API 端点,所以如果它可用的话,它将被捕获为一个“XHR”请求。因此,让我们选择 XHR 滤波器。
XMLHttpRequest ( XHR )是一个对象形式的 API,其方法在网络浏览器和网络服务器之间传输数据。该对象由浏览器的 JavaScript 环境提供。特别是,从 XHR 检索数据以不断修改加载的网页是 Ajax 设计的基本概念。不管名字如何,XHR 可以用于除 HTTP 之外的协议,数据不仅可以是 XML 的形式,也可以是 JSON、HTML 或纯文本的形式。[1]
有时,网页可能会有一些 JavaScripts 在后台运行,以完成一些预定的任务,浏览器会捕捉到它们。如果您想要一个更清晰的捕获请求列表,最好的方法是
- 确保“录制”按钮已启用
- 刷新网页
- 当您看到与数据相关的内容已经完全呈现在网页上时,请停止“记录”
现在,您将在开发人员控制台中看到一个请求列表。

谷歌 Chrome 开发者控制台截图
好的。这个很明显。我们可以看到,有人请求将其名称命名为“新冠肺炎-新-案例-JSON . JSON……”。一定是这样!
转到“Headers”选项卡,您将看到该请求的详细信息。最重要的是网址。

谷歌 Chrome 开发者控制台截图
现在,让我们将 URL 作为另一个浏览器选项卡打开,看看会发生什么。

截图来自谷歌 Chrome
酷!这是我们正在寻找的 API 端点。
使用 Pandas 读取 API 端点
怎么消费?极其容易!
我相信如果你是数据科学家或数据分析师,你一定会使用 Pandas Dataframe。只需一行 Python 代码,您就可以将所有内容直接放入 Pandas Dataframe。
df = pd.read_json('[https://www.theage.com.au/interactive/2020/coronavirus/data-feeder/covid-19-new-cases-json.json?v=3'](https://www.theage.com.au/interactive/2020/coronavirus/data-feeder/covid-19-new-cases-json.json?v=3'))

宜家家具清单

并不是所有的网站都在使用 REST API 端点,所以我不会说这是一种通用的方法。然而,你会发现有相当多的网站在使用它。让我们再举一个例子,宜家网站。
假设你想从宜家获得所有的床和产品细节,以便进行分析。下面是我的浏览器从 URL(https://www.ikea.com/au/en/cat/beds-bm003/)捕捉到的请求。

这个更有趣。请注意,它说“产品计数”是 220,但“产品窗口”只给出其中的 24 个。如果你注意一下这个页面,就会发现只有 24 种产品会列在这个页面上,如果你想继续浏览更多,还会提供一个“加载更多”按钮。嗯,这在 Web 开发中很常见,以节省带宽和服务器资源。
但这意味着我们必须放弃吗?绝对不是。让我们来看看请求 URL:

你见过有一种属性叫“大小”吗?它正好等于 24,这是页面大小。让我们尝试将它改为size=220,并使用 Python 内置库requests发送请求。
import requestsjson = requests.get(
'[https://sik.search.blue.cdtapps.com/au/en/product-list-page?category=bm003&sort=RELEVANCE&size=220&c=plp&v=20200430'](https://sik.search.blue.cdtapps.com/au/en/product-list-page?category=bm003&sort=RELEVANCE&size=220&c=plp&v=20200430')
).json()['productListPage']['productWindow']
这次我们不能直接使用 Pandas 的原因是产品列表不在 JSON 对象的根级别。相反,它在root.productListPage.productWindow。
之后,请求会将 JSON 对象转换为 Python 字典,因此我们现在可以使用 Pandas 来读取它。
df = pd.DataFrame.from_dict(json)

摘要

照片由 Aaron Burden 在 Unsplash 上拍摄
那不是又快又容易吗?不用学那些网页抓取库。但是,当然,这种方法不会对所有的网站都有效,这就是为什么网络抓取库仍然是必要的。然而,当网站上有可用的 API 端点时,为什么不直接找到它并直接使用它呢?
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@qiuyujx/membership)
如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)
参考
[1]维基百科。XMLHttpRequest。https://en.wikipedia.org/wiki/XMLHttpRequest
一个 Python 函数生成了一个精彩的条形图比赛视频

由 Shutterbug75 在 Pixabay 上拍摄的照片
从原始数据集到条形图比赛视频的逐步教程
最*,一种非常奇特的数据可视化方式在 YouTube 等各种*台上流行起来。只要有一些“实体”具有随时间变化的单一度量,这种类型的可视化就可以完美地说明这些实体之间的动态排序。
这就是条形图竞赛。它通常可以被看作是一个视频。下面的视频是我自己用一个 Python 函数生成的。看一看,你就知道我在说什么了。
你相信上面的视频是用一个只有几行代码的 Python 函数生成的吗?我会告诉你怎么做。
TD;分升
文章不算太短,因为我想提供一些可以循序渐进的东西。我认为 95%的时间我们都在做数据预处理。如果你真的想跳过直接进入正题,请到“生成条形图比赛视频”部分获取生成视频的代码:)
数据准备

为了确保本教程是可实现的,我不仅会提供生成条形图比赛视频的代码,还会提供如何获取数据集并对其进行预处理。因此,准备好的数据集是可操作的,然后可以放入 Python 中的条形图 race 库中。
获取原始数据集
我使用的数据集是由欧洲疾病预防和控制中心提供的,可以公开获得。每个人都可以免费下载新冠肺炎数据集。我在以前的一篇文章中也使用了这个数据集。
3 行 Python 代码创建一个交互式可玩的新冠肺炎泡泡地图
官网在这里:
在上面的网页上有一个链接,我们可以下载 CSV 格式的数据集。事实上,我们不必将数据集下载到本地机器,因为 Pandas Dataframe 可以直接读取远程 CSV 文件,如下所示。
df = pd.read_csv('[https://opendata.ecdc.europa.eu/covid19/casedistribution/csv/data.csv'](https://opendata.ecdc.europa.eu/covid19/casedistribution/csv/data.csv'))
然后,我们可以看看数据集中有哪些列,以及通过df.head()得到的值是什么样子。

如果你看过前面的视频,你可能会意识到我用确诊病例数作为衡量标准。那么,让我们开始数据清理和转换。
数据转换
在数据转换中,我们需要将数据改造成我们可以使用的东西。为了生成条形图比赛视频,我们将使用名为“bar-chart-race”的 Python 库(将在下一节介绍)。它期望数据帧使用日期时间对象作为索引,实体名称作为列名。所以,我们一起来转换数据。
1。移除无用的列
因为我们只对日期、国家和病例数感兴趣,所以我们可以只使用这三列来过滤数据帧,如下所示。
df = df[['dateRep', 'countriesAndTerritories', 'cases']]

2。将日期字符串转换为 **datetime** 对象
如果我们检查列的数据类型,我们会发现dateRep实际上是 objects,它将被视为 strings 而不是datetime object。这将导致一些麻烦,因为我们不能期望基于日期字符串列的排序结果。

因此,我们需要将其转换成datetime型。
df['date'] = pd.to_datetime(df['dateRep'], dayfirst=True)

在这之后,让我们再次检查dtypes。

3。添加累积病例
您可能已经注意到,案例数量是针对相应日期的。但是,我们需要每天的累计总病例数,以便每天的数据条目可以作为视频中的一帧生成。
因此,我们生成一个名为total_case的列,它表示当天到目前为止的案例总数。
df['total_cases'] = df.sort_values('date').groupby('countriesAndTerritories').cumsum().sort_index()

4。再次删除无用的列,并重命名这些列
因为我们已经生成了新的date和total_cases列,所以我们不需要dateRep和cases列。此外,让我们重命名国家名称列,以保持简单。
df = df[['date', 'countriesAndTerritories', 'total_cases']]
df = df.rename(columns={'countriesAndTerritories': 'country'})

5。旋转工作台
还记得我们需要使用国家名作为列名吗?所以,我们需要旋转桌子。这在熊猫数据框中很容易做到。
df = pd.pivot_table(df, index=['date'], columns=['country'], values=['total_cases'])
我们使用date作为索引,country应该是列,值是total_cases。然后,我们将得到如下的数据透视表。

由pivot_table函数生成的多级索引很难看,可能会导致问题。所以,让我们来解决它。
df.index.name = None
df.columns = [col[1] for col in df.columns]

我们完成了原始数据集的转换。然而,我们仍然需要清理数据。
数据清理

你看到我们在数据框里还有很多NaN值吗?这是因为该国从来没有病例记录,这是有道理的。然而,它们可能会在以后引起问题。
1。用零填充 NaN 值
由于NaN值意味着该国没有确诊病例,所以用零填充所有NaN值是安全的。
df = df.fillna(0).astype(int)
请注意,这里我们还将数据类型更改为整数,因为用浮点数表示事例数是没有意义的。
2。删除例外列
在我们的数据框中已经是列的所有国家中,有一个列叫做Cases_on_an_international_conveyance_Japan,它不是一个国家。指的是钻石公主号邮轮。因为它实际上不是一个国家,乘客实际上来自不同的国家,所以我想在这种情况下将其从我们的统计数据中删除。
df = df.drop(columns=['Cases_on_an_international_conveyance_Japan'])
3。删除国家名称中的下划线
国家名称(我们的列名)在单词之间有下划线。我想用空格替换这些下划线,这样当我们看到它们作为条形图标签时会更漂亮。
df.columns = [col.replace('_', ' ') for col in df.columns]
4。删除从未进入前 10 名的国家
这一步是可选的。然而,当我们生成视频时,它将提高性能。我们的数据集中总共有 200 多个国家,但并不是每个国家都排在前 10 名。由于我们将创建一个前 10 名条形图比赛数据可视化,这些国家将永远不会显示。
我们可以如下删除这些国家。
country_reserved = set()for index, row in df.iterrows():
country_reserved |= set(row[row > 0].sort_values(ascending=False).head(10).index)df = df[list(country_reserved)]
这里,我们首先生成一个名为country_reserved的集合。使用集合是因为它会忽略重复的值。然后,迭代数据框的每一行,如果当天国家/地区的案例总数排在前 10 名,则将国家/地区名称追加到集合中。
最后,我们将有一组曾经排在前 10 名的国家。将集合转换为列表并过滤列将产生一个更小的数据框,我们将在后面使用。

现在我们只剩下 30 个国家了。
生成条形图比赛视频

由 Pixabay 上的 StartupStockPhotos 拍摄的照片
好的。我们花了很多时间来争论数据集。事实上,正如我在这篇文章中提到的,生成视频非常简单。
我们只需要下载名为bar-chart-race的库,pip马上就会完成。
pip install bar-chart-race
导入库。
import bar_chart_race as bcr
简单地如下调用bar_chart_race函数。
bcr.bar_chart_race(
df=df,
filename='/content/drive/My Drive/covid-19.mp4',
n_bars=10,
period_fmt='%B %d, %Y',
title='COVID-19 Confirmed Cases by Country'
)
df是我们准备的数据帧filename是视频的输出文件名n_bars是我们要在条形图中显示的条形数,也可以认为是我们要显示的“前 n 个”。period_fmt是我们要在条形图上显示的日期格式。title只是条形图的标题。
过一会儿,视频将在我们指定的路径和名称下生成。
摘要

万岁!另一个令人惊叹的 Python 库!
在本文中,我介绍了另一个令人惊叹的 Python 库“条形图竞赛”。只需一个函数和几行代码,我们就可以生成一个 MP4 格式的华丽的条形图比赛视频。
事实证明,条形图比赛库中有更多可配置的项目。强烈建议你自己尝试一下。参考资料中给出了官方文档的链接!
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@qiuyujx/membership)
如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)
参考
欧洲疾病预防和控制中心
该可下载的数据文件每天更新,包含关于新冠肺炎的最新公共数据。你可以使用…
www.ecdc.europa.eu](https://www.ecdc.europa.eu/en/publications-data/download-todays-data-geographic-distribution-covid-19-cases-worldwide)
条形图比赛文档
[## 条形图竞赛
使用 bar_chart_race 包在 Python 中制作动画条形图比赛
www.dexplo.org](https://www.dexplo.org/bar_chart_race/)
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
关于新的 Tokenizers 库的一个小计时实验——一篇文章
剧透:速度惊人🔥

GitHub 上的 Tokenizers 库的自述文件
一周前,可爱的人在 抱脸 向公众发布了他们的新 Tokenizers 库 。tokenizers 用 Rust 编程语言编写(与 Python 相比,它以性能著称),提供了“当今最常用的 Tokenizers 的实现,重点关注性能和通用性”。
因此,这篇文章介绍了一些小型计时实验的结果,这些实验对比和比较了吴等人(2016 年)介绍的分词器的不同实现,并随着 Devlin 等人(2018 年)发布和出版的BERT而得到推广。与这些计时实验相关的所有代码都可以在下面的 Jupyter 笔记本中找到:
🤗变形金刚 vs💥标记化者
在第一个计时实验中,我比较了在流行的 变形金刚库 (也是通过拥抱脸)中实现的 Bert 单词块标记器的性能(在执行时间方面)和新的标记器库的性能。对于这两者,我在 5 次独立运行中标记(编码)了 100 万个英语句子,其结果可以在下面找到:
变压器与令牌化器定时实验
如您所见,*均执行时间仅为 45.6 秒,与 Transformers 库实现(*均执行时间为 6 分 42 秒)相比,Tokenizers 库实现的速度提高了* 9 倍。
🧵多线程性能
Tokenizers 还提供了一种一次(批量)编码多个句子的方法,由于其多线程实现(在 Rust 中),这可以显著提高性能。然而,Python 也支持多线程,例如使用[concurrent.futures](https://docs.python.org/3.7/library/concurrent.futures.html)。
因此,与第一次计时实验类似,这里我比较了使用concurrent.futures.ThreadPoolExecutor与submit和map的 Bert 单词块标记器的性能,以及标记器的本机encode_batch,结果如下:
多线程性能计时实验
正如你所看到的,令人惊讶的是,submit和map与非多线程令牌化相比,性能(相等)更差。然而,更有趣(也更令人印象深刻)的是,Tokenizers 库自带的多线程encode_batch只需要 10.6 秒就可以标记一百万个句子!
结论
正如宣传的那样,拥抱脸的新 Tokenizers 库提供了比 Transformers 库快得多(几乎 9 倍)的 BERT 单词块 tokenizer 实现。然而,当批量对句子进行分词时,性能更加令人印象深刻,因为只需 10.6 秒就可以对 100 万个句子进行分词。因此,我想我可以有把握地断定它快得惊人🔥!
虽然新的 Tokenizers 库提供了更多的好处,而不仅仅是其令人印象深刻的性能(例如,在新词汇上训练标记器的能力),但应该说,这种性能的显著提高不仅允许对越来越大的数据集进行标记(在运行中),而且允许这些方法和技术更好的民主化(例如,在更便宜的硬件上部署,如移动电话和 SOC),允许来自各种背景的有抱负的 NLP 爱好者开始使用最新和最棒的 NLP🤗
参考
[1] Y. Wu 等, Google 的神经机器翻译系统:弥合人与机器翻译的鸿沟 (2016),【arXiv 预印本 arXiv:1609.08144 。
[2] J. Devlin 等, Bert:用于语言理解的深度双向变换器的预训练 (2018), arXiv 预印本 arXiv:1810.04805 。
一个程序员用的剪切工具
一个用 Python 编写的截取工具,它可以自动识别截取图像中的文本,并执行 google 搜索。
像许多程序员一样,我发现自己经常复制和粘贴文本。大部分时间我都是从我的 IDE 或者终端上复制一些错误信息,然后在 Google 上搜索。其余时间,我将一个方法或函数复制到 google 中来阅读文档。随着时间的推移,高亮显示文本、复制、打开浏览器、粘贴然后搜索的过程会变得有点乏味(我知道的第一世界问题)。我决定用 Python 来自动化这个过程。

马特·阿特兹在 Unsplash 上拍摄的照片
解决方案是…
我想要一个桌面应用程序,将坐在后台,像 windows 剪贴工具的行为。它将有两个功能:剪切和搜索和剪切和复制。

程序员图形用户界面的剪切工具
这两个函数都允许我将一个文本区域剪成图像,对图像执行字符识别,然后返回一个字符串。然后,截取和搜索功能将自动打开一个浏览器标签,并在谷歌中搜索截取图像中的字符串。另一方面,剪切和复制函数会将字符串保存到我的剪贴板中。
下面是如何使用该程序的演示。当你从不能用通常的方法复制的地方复制文本时,比如终端,图片或者 youtube 教程,它实际上是非常有用的。

“剪切和搜索”功能的演示

“剪切和复制”功能的演示
您可以找到完整的代码或下载。exe 文件放在我的 Github 上。请注意,目前这款应用只在我运行 Windows 10 的电脑上进行了测试。需要进行修改,以确保该应用程序在其他操作系统上工作。我以后可能会讲到这个。
所以我是怎么做到的…
正如我之前提到的,该应用程序是用 Python 编写的,使用的主要库是 PyQT5 , cv2 , Pillow 和pytesserac。GUI 允许我设置我希望使用的浏览器,并等待按下功能按钮。一旦按下一个功能按钮,就会创建一个裁剪工具小部件的实例,并等待用户通过单击和拖动来裁剪屏幕上的一个区域。github 上的 harupy 创造了一个用 Python 写的很棒的剪切工具应用程序,这必须要归功于他。他的代码构成了该项目的 snipping 工具部分的基础。
一旦剪切了一个区域,就使用 cv2 库将图像转换为灰度数组,然后使用 P yTesseract 库将图像传递给 Tesseract 光学字符识别(OCR)引擎。这是 Google 开源 Tesseract-OCR 引擎的包装器。
一旦被截取的图像被分析并且文本被识别,字符串或者使用 pyperclip 库被保存到剪贴板,或者在指定的浏览器中执行搜索。然后,GUI 重置并等待下一个 snip。
文本识别不是 100%准确,尤其是在较长的部分和文本是特定颜色时。我确信在进入 Tesseract OCR 引擎之前,我可以在 cv2 中用一些更高级的图像处理来改进这一点。如果我有时间,这些改变可能会在将来完成。如果我实现了任何改进,我将在将来更新这篇文章。欢迎任何改进的建议。祝你愉快!
使用 Tensorflow 对象检测模型和 OpenCV 的社交距离和遮罩检测器
结合深度学习和计算机视觉的隔离项目。
介绍
社交距离这个词席卷了整个世界,并正在改变我们的生活方式。社交距离也被称为“物理距离”,意思是在你和其他不在你家的人之间保持一个安全的空间。随着该国开始在激增的新冠肺炎病例中解锁,保持社交距离已成为一个关键问题。围绕新冠肺炎疫情的最大担忧是,这种感染会以多快的速度通过接触甚至是接*感染者而从一个人传播到另一个人。社会距离在这里停留的时间比预期的要长,以对抗新冠肺炎。
因此,这让我想到开发一个人工智能模型,来检测人们是否在遵循社交距离,同时戴着面具。这是模型结果的一个例子。借助深度学习和 OpenCV,我们可以从视频片段中提取有趣的见解。红色边框表示这个人与另一个人很接*,蓝色边框表示这个人保持着社交距离。我们有单独的边界框来识别这个人是否戴着面具。

社交距离和面具检测
你可以找到我在我的 Github Repo 上使用的代码。
步骤概述
TensorFlow 对象检测 API 是用于创建解决对象检测问题的深度学习网络的框架。API 提供了预训练的对象检测模型,它们被称为模型动物园,已经在 COCO 数据集上进行了训练。上下文 ( COCO )中的常见对象数据集有 200,000 幅图像,在 90 个常见对象中有超过 500,000 个对象注释。请参见下图中属于 COCO 数据集的对象。

Coco 对象类别。图片来自https://arxiv.org/pdf/1405.0312.pdf
在这种情况下,我们关心属于 COCO 数据集的类“Person”。
该 API 还支持大量的模型。请参见下表以供参考。

API 支持的一小部分模型
这些模型在速度和准确性之间进行了权衡。这里我选择了 ssd_mobilenet_v1_coco 来检测‘人’。一旦我们使用对象检测 API 识别出“人”,为了预测这个人是否保持社交距离,我们可以使用 OpenCV,这是一个强大的图像处理库。一旦检测到社交距离,我就使用faster _ rcnn _ inception _ v2 _ cocoAPI 来检测这个人是否戴着面具,我之前使用 GPU(NVIDIA Quadro p 4000 Linux)对 top 2000 图像进行了训练。
深入探究主要步骤
现在让我们详细研究一下代码。
如果您是第一次使用 Tensorflow 对象检测 API,请从这个链接下载 GitHub。
我遵循的主要步骤是(请跟随我的 Github 上的 jupyter 笔记本)
-
将 ssd_mobilenet_v1_coco 模型加载到图中,并加载属于 coco 数据集的类列表
-
使用 cv2 打开视频。VideoCapture(文件名)并逐个读取每一帧并将其写入一个路径
-
对于每一帧,使用加载的图形执行对象检测
-
从 ssd_mobilenet_v1_coco 返回的结果是每个已识别的类及其置信度得分和边界框预测。
-
基于类别和置信度得分> 0.60,检测一帧中的人数,如下所示。
-
根据我们之前得到的包围盒预测画出蓝色彩色包围盒,并找到宽度的中点。用 id 标记每个边界框。
-
找出一帧中点之间的欧几里德距离。
-
有了欧几里德距离,找到距离小于 200 的包围盒,将包围盒的颜色改为红色。
-
将所有的代码片段放在一起,传递所有的帧,并将它们保存在一个路径中。因此,我们将有一组社会距离检测帧
-
将我在上面训练的带遮罩和不带遮罩图片的 frozen _ inference _ graph . Pb(faster _ rcnn _ inception _ v2 _ coco)加载到一个图形中,并加载类列表
-
对于每个检测到的社交距离帧,使用 faster _ rcnn 模型的加载图来执行戴着面具的人的对象检测
-
最后,使用之前获得的帧,使用 python 中可用的 moviepy 包创建一个视频
结论和改进
这就把我们带到了我文章的结尾。社交距离以及其他基本的卫生措施对于尽可能减缓新冠肺炎的传播非常重要。这个项目只是一个概念验证。
我很清楚这个项目并不完美。因此,有一些关于如何改进该应用程序的想法:
- 我遇到过一些方法,人们将视频转换成俯视图或鸟瞰图,然后计算图像中两个物体之间的距离
- 考虑摄像机校准****
“家是躲避风暴的避难所——各种各样的风暴。在家注意安全。”
使用 Tensorflow 对象检测模型、Python 和 OpenCV 的社交距离检测器。
结合深度学习和计算机视觉的隔离项目。

介绍
在隔离期间,我花时间在 github 上探索 Tensorflow 的大量预训练模型。在做这件事的时候,我偶然发现了一个仓库,里面有 25 个预先训练好的目标检测模型,带有性能和速度指标。有了一些计算机视觉方面的知识,考虑到实际的环境,我认为使用其中的一个来构建一个社交距离应用程序会很有趣。
更有甚者,上学期在我的计算机视觉课上,我被介绍给了 OpenCV ,并在做一些小项目时意识到它的强大。其中之一包括对图片进行鸟瞰转换。一个鸟瞰图基本上是一个场景的自上而下的表示。这是在构建自动汽车驾驶应用程序时经常执行的任务。

这让我意识到,在我们想要监控社交距离的场景中应用这种技术可以提高质量。这篇文章介绍了我如何使用深度学习模型以及计算机视觉中的一些知识来构建一个健壮的社交距离检测器。
这篇文章的结构如下:
- 型号选择
- 人物检测
- 鸟瞰图变换
- 社会距离测量
- 结果和改进
以下所有代码以及安装说明都可以在我的 github 库中找到。
1.型号选择
Tensorflow 对象检测模型 zoo 上可用的所有模型都已经在 COCO 数据集(上下文中的常见对象)上进行了训练。这个数据集包含 120,000 幅图像,在这些图像中总共有 880,000 个被标记的对象。这些模型被训练来检测这个数据集中标记的 90 种不同类型的对象。所有这些不同对象的完整列表可以在 github repo 的数据部分获得。这份物品清单包括一辆汽车、一把牙刷、一根香蕉,当然还有一个人。

可用模型的非详尽列表
根据模型的速度不同,它们有不同的性能。我做了一些测试,以确定如何根据预测的速度来*衡模型的质量。由于这个应用程序的目标不是能够执行实时分析,所以我最终选择了【faster _ rcnn _ inception _ v2 _ coco,它的 mAP(验证集上的检测器性能)为 28,相当强大,执行速度为 58 毫秒。
2.人物检测
使用这种模型,为了检测人,有几个步骤必须完成:
- 将包含模型的文件加载到张量流图中。并定义您希望从模型中获得的输出。
- 对于每一帧,通过图形传递图像,以获得所需的输出。
- 过滤掉弱预测和不需要检测的对象。
加载并启动模型
张量流模型的设计工作方式是使用图。第一步意味着将模型加载到张量流图中。该图将包含为获得所需检测而将完成的不同操作。下一步是创建一个会话,它是一个负责执行上图中定义的操作的实体。更多关于图表和会话的解释可在这里获得。我决定实现一个类来保存所有与 tensorflow 图相关的数据。
通过模型传递每一帧
为每个需要处理的帧启动一个新的会话。这是通过调用 run() 函数来完成的。这样做时,必须指定一些参数。这些包括模型需要的输入类型,以及我们希望从中获得的输出。在我们的例子中,需要的输出如下:
- 包围盒中每个物体的坐标
- 每个预测的置信度** (0 到 1)**
- 预测的类别 (0 到 90)
过滤掉弱预测和不相关的对象

人员检测的结果
模型检测到的许多类别之一是人。与人员相关联的类别是 1。
为了排除弱预测(阈值:0.75** )和除了人以外的所有其他对象类别,我使用了一个 if 语句来组合这两个条件,以从进一步的计算中排除任何其他对象。**
**if int(classes[i]) == 1 and scores[i] > 0.75**
但是由于这些模型已经被预先训练,所以它们不可能只检测这个类。因此这些模型需要相当长的时间来运行,因为它们试图识别场景中所有 90 种不同类型的对象。
3.鸟瞰图变换
正如介绍中所解释的,执行鸟瞰视图变换给我们一个场景的顶视图。幸运的是,OpenCV 有很好的内置函数将这种方法应用于图像,以便将从透视角度拍摄的图像转换为该图像的俯视图。我用了伟大的阿德里安·罗斯布鲁克的教程来理解如何做到这一点。****
第一步包括在原始图像上选择 4 个点,这 4 个点将成为将要变换的*面的角点。这些点必须形成一个至少有两条对边*行的矩形。如果不这样做,当转换发生时,比例将不会相同。我已经在我的资源库中实现了一个脚本,它使用 OpenCV 的 setMouseCallback() 函数来获取这些坐标。计算变换矩阵的函数也需要使用图像计算的图像尺寸。图像的形状属性。
**width, height, _ = image.shape**
这将返回宽度、高度和其他不相关的颜色像素值。让我们看看如何使用它们来计算转换矩阵:
请注意,我选择也返回矩阵,因为它将在下一步中用于计算每个检测到的人的新坐标。这样做的结果是帧中每个人的“GPS”坐标。使用这些比使用原始地面点要精确得多,因为在透视图中,当人们在不同的*面图中时,距离是不一样的,而不是在离摄像机相同的距离。与使用原始帧中的点相比,这可以大大改善社交距离测量。
对于检测到的每个人,返回构建边界框 a 所需的 2 个点。点是盒子的左上角和右下角。从这些,我通过得到它们之间的中点来计算盒子的质心。利用这个结果,我计算了位于盒子底部中心点的坐标。在我看来,这个点,我称之为地面点,是图像中一个人的坐标的最佳表示。****
然后,我使用转换矩阵来计算每个检测到的地面点的转换坐标。在检测到帧中的人之后,使用cv2 . perspective transform()对每一帧进行这一操作。我是这样实现这个任务的:
4.测量社交距离
在每一帧上调用这个函数后,返回一个包含所有新变换点的列表。根据这个列表,我必须计算每一对点之间的距离。我使用了来自 itertools 库中的函数 combinations() ,它允许在一个列表中获得所有可能的组合,而无需保留双精度。这在这个堆栈溢出问题上解释得很好。剩下的就是简单的数学:在 python 中使用 math.sqrt() 函数可以很容易地计算两点之间的距离。选择的阈值是 120 像素,因为它在我们的场景中大约等于 2 英尺。
一旦识别出两个点彼此过于接*,标记该点的圆的颜色将从绿色变为红色,并且对于原始帧上的边界框也是如此。
5.结果
让我来介绍一下这个项目是如何运作的:
- 首先获得*面图的 4 个角点,并应用透视变换以获得该*面图的鸟瞰图,并保存变换矩阵。
- 获取在原始帧中检测到的每个人的边界框。
- 计算这个盒子的最低点。它是位于两脚之间的点。
- 使用这些点的变换矩阵来获得每个人的真实“GPS”坐标。
- 使用 itertools.combinations() 测量帧中每个点到所有其他点的距离。
- 如果检测到社交距离违规,将边界框的颜色更改为红色。
我使用了来自 PETS2009 数据集的视频,该数据集由包含不同人群活动的多传感器序列组成。它最初是为人群中的人数统计和密度估计等任务而构建的。我决定使用第一个角度的视频,因为这是最宽的角度,具有最佳的场景视图。该视频展示了获得的结果:
6.结论和改进
如今,社交距离和其他基本的卫生措施对于尽可能减缓新冠肺炎病毒的传播非常重要。但是这个项目只是一个概念验证,并不是为了监控公共或私人领域的社交距离,因为道德和隐私问题。
我很清楚这个项目并不完美,所以这是如何改善这个应用程序的一些想法:
- 使用更快的模型来执行实时社交距离分析。
- 使用对遮挡更鲁棒的模型。
- 自动标定是计算机视觉中的一个众所周知的问题,它可以大大改善不同场景下的鸟瞰图变换。
这篇文章是我对《走向数据科学和媒体》的第一篇贡献。我已经把代码放在我的 Github 上了。如果您对代码本身或本文有任何疑问,请随时提问。如果您有可能改进的想法或任何类型的反馈,请随时联系我,我将不胜感激。我希望你觉得这很有帮助,如果你喜欢,可以随意分享。
来源
在实施这个项目的过程中,我发现了许多在线文章,它们帮助我度过了困难:
** [## 使用 Tensorflow 对象检测和 OpenCV 分析一场足球比赛
用数据做很酷的事情!
towardsdatascience.com](/analyse-a-soccer-game-using-tensorflow-object-detection-and-opencv-e321c230e8f2) [## 4 点 OpenCV getPerspective 转换示例— PyImageSearch
凌晨 4 点 18 分。警报响了。外面还是漆黑一片。床很暖和。我光着脚会觉得地板很冷。但是我得到了…
www.pyimagesearch.com](https://www.pyimagesearch.com/2014/08/25/4-point-opencv-getperspective-transform-example/) [## 里奇伦的鸟瞰项目研究
一般来说,车载摄像机具有严重的透视效果,如图 1(a)所示。因为透视效应,所以…
developer.ridgerun.com](https://developer.ridgerun.com/wiki/index.php?title=Birds_Eye_View/Introduction/Research) [## 宠物 2009
数据集是包含不同群体活动的多传感器序列。如果…请发电子邮件给 datasets@pets2009.net
www.cvg.reading.ac.uk](http://www.cvg.reading.ac.uk/PETS2009/a.html#s0)**
英国政治景观的空间表现
政治学中的主成分分析
空间术语对于任何政治领域的描述都是必不可少的。政治行动者在问题上采取“立场”,他们执行“U 型转弯”,当然他们要么位于“左翼”,要么位于“右翼”,要么位于“中间地带”。这种语言也不是纯粹的学术语言,而是延伸到所有参与政治的个人的词汇中;无论是政治家、记者还是普通大众。然而,空间语言在政治背景下的使用主要是假设性的,“纯粹是概念性的,不可能实际观察到”(Laver 和 Benoit,2012,195)。因此,个人必须投入相当多的精力去理解从中得出相对政治立场的许多变量。本研究的目的是提出一个物理框架,在此基础上,这些变量可用于绘制聚合群体(如投票选区)的偏好。为此,我将研究的其余部分分为三个部分,同时利用英国 2019 年大选作为背景。1)首先,我开始讨论政治空间的概念,从而为这项工作提供必要的色彩和背景。2)然后,我检查和批判现有的投射政治空间的方法论和学术方法。3)最后,我解释了如何使用主成分分析(“PCA”)将政治空间的许多维度简化为直观的呈现。在本节中,我还将通过利用英国选区层面的数据来展示 PCA 的优点,以说明如何定量捆绑相关变量(政治或其他)来了解每个选区在大选中最有可能支持哪个政党及其原因。
政治空间的概念
在政治学中,空间的概念是通过根据特定变量将政策偏好/政治代理人排列成一条直线来赋予实体性的(见图 1)。在这样做的过程中,一个相似性的光谱被创造出来——点与点之间的欧几里得距离代表了不同的程度(亚当等人,2005 年,施菲尔德,2008 年)。线性政策谱后来成为许多普遍思想的基石,这些思想不仅主导了政治学术领域,也主导了现实世界的实践:例子是 Downsian 的“中间选民定理”概念,以及“左”和“右”翼对政治偏好的理解。
图 1:英国 2019 年大选中假设的一维政策轴

这个将单个变量映射到一维框架的简单框架可以扩展为创建多个变量的多维框架。这种框架理论上可以包含几乎无限数量的维度,因此即使在概念层面也存在挑战。随后,通常避免字面意义上的尝试,而倾向于将相关变量(可以是明确的政策偏好,也可以基于人口统计数据)分组为广泛的主题,如社会主题(自由到保守)或经济主题(自由市场到国家管理)(见图 2)。简单的分类当然会有问题,例如,在 2019 年的大选中,反对在希思罗机场增加一条跑道的人可能会被描绘成自由主义者/国家管理的人,即使这是由首相倡导的:一个保守主义者/自由市场主义者。然而,通过使用这种方法,政治科学家可以创建地理空间的简约点来放置政治偏好。这些地图随后能够包含比简单的一维比例尺更多的信息。
图 2:英国 2019 年大选中假想的二维政策轴

2)对现有方法的批评
在物理空间上呈现政治偏好的实际任务由两部分组成。第一阶段是估计潜在的维度,在这些维度上可以绘制偏好,第二阶段是将偏好映射到这些维度上。在现有的文献中,对过程的第一阶段采取的对比方法定义和区分方法风格。随后,我将第一阶段的方法分为两大类,并对其进行研究。这些组被定义为在先验定义的尺度上估计位置的组,以及在根据数据归纳定义的尺度上估计位置的组。
估算量表维度的两种方法都依赖于上一节讨论的概念框架(维度是通过将相关变量分组到广泛的主题中来确定的)。对于维度的先验估计,这意味着利用专家分析师的先验知识来创建和缩放维度的定性方法。这通常被认为是一种优越的方法,因为使用先验知识大大降低了任务的复杂性,并建立在数百年的政治话语之上(Laver 和 Benoit,2012,198)。然而,这种方法当然会受到许多针对任何定性研究的普遍批评。这主要包括关于可复制性、可比性和为大型数据集提供充分分析的问题。
在 Mcelroy 和 Benoit (2007 年)关于这一主题的工作中可以找到一个明显的例子。他们的工作整理了专家对欧洲政治的意见,并试图从中推断出对欧洲政党政策的空间理解。物理表示最初是建立在一个二维框架上,与图 2 中的轴相同。然而,在后续工作中,y 轴上的社会维度取代了对欧盟一体化的看法。结果,政党的空间位置完全改变了,这意味着新的位置无法与以前的重复进行比较,更不用说其他调查了。同样,他们对专家分析的使用也存在与基于访谈的研究类似的问题——无法保证不同的专家会使用彼此相同的维度,甚至无法保证相同的专家会两次得出相同的分析。此外,虽然他们的方法可用于绘制欧盟的政党地图,但试图绘制欧盟所有政治选区的地图会耗费大量劳动力,这与我在最后一节中承担的任务类似。
同时,对于试图归纳得出空间位置的研究来说,这种方法是完全不同的,本质上是更加定量的。这些定量方法通常基于通过因子分析等技术识别潜在维度(事实上,我在下一节中使用了这种方法的变体)。这种方法再次以概念框架所描述的方式来缩放维度,然而在这种情况下,显式地计算相关性束以导出变量的宽泛分组。这种方法的一个极端例子是 Gabel 和 Huber (2000),他们将整个比较宣言项目映射到一个单一的维度上——左右翼经济规模。
这种方法的问题是,通过让基本向量完全开放,我们留下了“基本上无法验证”的位置(Benoit 和 Laver,2012,198)。其结果是,行动者的定位反而通过现有的政策维度概念得到认可,并需要专家分析才能从地图中获得任何洞察力——前面提到的 Gabel 和 Huber 的工作就是一个明显的例子,因为它依赖于左/右翼经济规模。因为地图应该努力实现普遍可访问性,所以这种技术仍然是欠缺的。因此,在下一节中,我建议通过归纳计算政治空间,然后有意识地将现有知识分层,我们可以提供关于政治代理人的政策和政党偏好的变量意味着什么的宝贵见解,而不需要任何重要的先验知识。
3)使用 PCA 创建英国 2019 年大选英格兰和威尔士选区政治偏好的空间表示
到目前为止所描述的任务可以理解为多变量分析,其最终目标是降低维度。PCA 是我们可以用来完成这项任务的归纳工具之一。它是一个合适的工具,因为它的明确目的是以一种允许它们被映射到二维图上的方式压缩多个变量。该方法通过分析原始数据集中变量之间的共线性(或缺乏共线性)(图 3 ),并将这些变量转换为新变量(主成分)来实现这一点。然后,新创建的变量可以用相似的组聚集在一起来绘制,差异通过距离来显示——因此,这种方法仍然可以在政治空间的传统概念框架内识别。
我用来进行分析的数据集由从英国选区级数据库收集的潜在相关和潜在不相关指标组成。混合相关和不相关变量的目的是,在政治学中,我们无法总是预先知道哪些变量是重要的。随后,我加入了潜在的非相关变量来削弱模型,从而提供了一个关键案例和更强大的例子来证明这种方法的未来使用(Hancke,2009)。
使用的变量如下(下议院图书馆,2020 年):
低于最低工资的工作比例
女性人口比例
男性人口比例
拥有住房的家庭比例
65 岁以上人口比例
35-65 岁人口比例
16-35 岁人口比例
白人人口比例
黑人人口比例
亚裔人口比例
混血人口的比例
其他种族的人口比例
留下投票的人口比例
投票支持脱欧的人口比例
肥胖人口比例
抑郁人口比例
管理人员占人口的比例
中位房价与中位收入水*
工资中位数
宽带速度
数据是公开的,并在参考书目中有链接。这项研究只包括英格兰和威尔士的选区。二元变量,如男性/女性或离开/留在不需要都包括在 PCA 中。然而,自从观想结束后,它们就更容易被理解了。
图 3:英国选区层面数据的相关矩阵

通过使用主成分分析,我们可以创建一个系统的框架,它很容易重现,并可以缩放维度和定位变量。图 4 显示了五氯苯甲醚的初始产品。从这一点出发,我们可以利用先验知识来推断右下角的选区可能类似于图 2 中所示的右上角的选区(社会保守和经济自由)。类似地,我们可以将对面的角落(根据种族多样性和宽带速度判断,可能是市中心的选民)视为社会自由派和经济左翼。此外,轴标题告诉我们,x 轴上的欧几里得距离比 y 轴上的欧几里得距离占更多的方差(即,水*距离比垂直距离代表更多的差异)。因此,这两个集群之间的差异最大。不幸的是,正如这一分析所证明的那样,这样一幅地图最好通过现有政治维度的棱镜来理解,并且具有我所批评的 Gabel 和 Huber 的工作的缺陷。
图 4:英国选区层面数据的 PCA

为了提高从数据中推断维度的方法的解释能力,以及减少对专家见解的依赖,我用他们投票支持的政党来标记选区(图 5)。这种做法并不新奇,但在政治科学中却鲜有应用。然而,这样做的结果是,我们可以很容易地确定与特定政党最相关的变量,以及每个选区相对于彼此的位置。因此,我们已经表明,当我们分层附加信息时,定量方法可以合并大量变量并创建直观的地图。
图 5:英国选区级别数据的 PCA,带有政党投票颜色编码

更进一步,我们还可以确定工党在 2019 年大选中输给保守党的席位(图 6)。这让我们看到,工党失去的席位与 1)人口老龄化,2)公投脱欧和 3)低于最低工资的工作比例高有关。此外,高比例的肥胖和抑郁似乎也与这一位置有关——尽管直觉上我们可以假设这与财富水*有关。这种趋势有一个值得注意的例外——在地图的左下方,我们可以看到肯辛顿(可以选择识别单个点,但没有在下面显示,因为它会挤满可视化)——这是一个在上次选举中获胜但后来在大选中失败的剩余席位工党。
有趣的是,该地图表明工党应该争取更贫穷的脱欧选民,因为这些席位比大都会留欧派席位更接*保守党席位群——尽管这种说法当然忽略了工党可能会失去席位给第三方的可能性。无论如何,我们可以清楚地看到,颜色编码的 PCA 提供了一种有效的方式来理解演员的政治定位。
图 6:英国选区级别数据的 PCA,投票从工党切换到保守党,颜色编码

结论
在上面的报告中,我已经展示了 PCA 分析是一种如何很好地与创建政治的空间表示的过程相一致的工具,如政治学中存在的一般概念理解所定义的。此外,我还证明了它在分析选民群体时识别政策偏好的适用性,以及颜色编码创建了一个易于解释的地图。在做上述工作时,我还提出了对英国 2019 年大选的新颖见解,以及一种应用于现实世界的政治策略。对这一领域的进一步研究可能希望尝试类似的方法,如 t-SNE 图和多维标度,并比较结果。考虑到数据的空间异质性,地理加权的主成分分析也值得进一步研究。
文献学
亚当斯 JF,梅里尔 S 和格罗夫曼 B (2005)政党竞争的统一理论:整合空间和行为因素的跨国分析。剑桥:剑桥大学出版社。
Benoit K 和 Laver M (2012)政治空间的维度。伦敦:劳特利奇。
唐斯 A (1957)的《民主的经济理论》。伦敦:普伦蒂斯霍尔
Gabel M 和 Huber J (2000)把政党放在他们的位置:从政党宣言推断政党的左右意识形态立场。美国政治科学杂志 44(1):94–113。
Hancké,B ,( 2009)智能研究设计:社会科学新手研究指南。牛津:牛津大学出版社
下议院图书馆 2019,本地数据仪表板,2020。查看日期:【2020 年 3 月 11 日,https://commonslibrary.parliament.uk/local-data/
McElroy G 和 Benoit K (2007)欧洲议会中的政党团体和政策立场。政党政治 13(1):5–28。
施菲尔德·N(2008)政治的空间模型。伦敦:劳特利奇。
感知机器人的星球大战故事
如果星球大战的故事是由机器写的会怎么样?

作者图片
简介
想象一下,机器人带着未来的知识来到 21 世纪,却只有当前的技术来改写他们的星球大战故事。
在这篇文章中,我们将看到一个机器人(机器学习模型)如何利用未来的知识(星球大战书籍)生成它的星球大战故事。

来源: neonbrand
模型的架构
该模型采用单词的输入序列。我们用 LSTM 来理解句子的上下文。因为简单的 RNN 会有消失渐变问题,所以对于文本生成,我使用 LSTM。
该模型的输出是最可能的下一个单词的单词分数。下面的代码显示了使用 PyTorch 的模型架构。
故事生成
故事生成是通过将单个单词和文本长度作为输入来完成的。该单词被传递给模型以获得下一个最可能的单词,我们继续这个过程,直到达到文本长度。前 K 个采样用于在选择下一个最可能的单词时引入一些随机性。
生成的样本
以下是用各种输入单词和文本长度生成的文本的 12 个例子。
样品 1:
我觉得提到韩是个白痴很有趣。我们可以看到这个顺序,虽然不是很好,但很有意义。
输入单词:绝地
文本长度:12
生成的输出
jedi.
han was a idiot, not looking in his datapad
样品 2:
以下是为绝地武士生成的不同序列。到目前为止,较小的文本长度似乎更有意义。我不得不在《星球大战》故事中寻找与绝地、贸易联盟和十一人的联系🤔
输入单词:绝地
文本长度:12
生成的输出
jedi. and the trade federation, servers of the eleven, commissioned
样品 3:
这让我觉得它在说尤达无所不知!我喜欢尤达,所以我同意它😄
输入单词:尤达
文本长度:12
生成输出
yoda. the jedi had expanded on the galaxy, but he knew
样品 4:
这个文本长度更长。
"猎鹰的脸似乎,然后弹射出窗外"
对于这篇文字,我想象一个星际战斗机飞行员正透过他/她的窗户看着千年隼的前方。当千年隼移动时,飞船似乎从这个维度弹射到另一个维度😜
输入单词:尤达
文本长度:100
生成的输出
yoda. ”
“i don’t know—fly the fancy, ” yoda replied quietly.
“no, ” luke called, uncharacteristically the robot of happiness and disappointment.
“we know. ”
“and luke’s anger. ” lando yelled.
the falcon ’s face seemed, then catapulted out the window.
the phantom- cloaked girl swiveled at the princess of the death.
" i know you were dead."
" no, not...."
" i don't know about him," ferus said
样品 5:
这个很有趣,说维德在操纵他的方式!还提到了冲锋队的男子气概(我认为它是在说“匹配”,但男子气概更有趣)
输入单词:维达
文本长度:35
生成的输出
vader could react in the main navy, manipulating his way to the limit, then turned back to the main scout. the stormtrooper of the two- east jawas were just only a matchto
样品 6:
该序列正确地链接了 r2-d2,可能输入中提到了足够多的 r2-d2 名称实例。
"但是帝国将由帝国掌管!"
嗯,不知道 r2-d2 在想什么,但我们不能让这种事情发生😂
“我不认为我们能找到它”
看起来 r2-d2 正在和 c-3po 通话
输入字:r2
文本长度:75
生成输出
r2- d2. " i don't think we can find it," he said." but the imperials will be in charge of the empire!" he looked over to his chair." i can't have to be a long idea," ferus answered." we can get out of the temple." " we know, i have to tell you
样品 7:
同样,这里欧比和欧比旺的联系是正确的。
嗯,这似乎是一个很好的想象练习,如果奥比万的飞船是一架巴托克星际战斗机呢!哈哈,我可想不出这个🤣或者是巴托克偷了贸易联盟的星际战斗机,然后给了欧比万?我会让你弄明白的
输入单词:obi
文本长度:100
生成的输出
obi- wan's ship. the bartokk starfighter fired in a heap overlooking the arena with a violent, hanging out of the roof.
he had heard the emperor, and he wouldn't be happy for the time of his life.
" the queen has been destroyed to me."
" the senate is not a trap," obi- wan said.
" i can tell him. you can tell him that you have a chance to collect."
" i don't know."
" you don't
样品 8:
有原则的丘巴卡,是的,我喜欢!
输入单词:丘巴卡
文本长度:10
生成的输出
chewbacca, with the connectors and the principles.
样品 9:
“你根本不了解绝地,”费罗斯说。但绝地将是唯一的一个——原力”
看起来费罗斯·奥林正在教阿纳金·天行者关于绝地的知识。也许它会结束,因为绝地将是阻止邪恶的唯一力量。
输入单词:阿纳金
文本长度:50
anakin, and the naboo star destroyers and services."
" yes, master."
" what do we commit?"
" you have no idea of a jedi," ferus said." but the jedi will be the only one— the force
样品 10:
所以我们从下面的文本中了解到了索拉·纳贝里和绝地将在纳布之战中一起对抗抵抗组织的故事?
输入单词:sola
文本长度:100
生成的输出
sola. and the jedi had begun to overthrow the resistance."
" you don't know," ferus said.
" i don't know," he said." it is no of the founding reasons."
" you know you were a good one!" the boy asked irritably." but the chancellor are not happy to unravel the emperor's advisor in the galaxy," ferus said." i can see it." the boy nodded." i have a feeling,"
样品 11:
卢克·天行者似乎想通知某人关于联邦飞船的事。
输入单词:联邦
文本长度:22
生成的输出
federation droids of the rebel star cruisers, indomitable.
" i have to tell the first naval," the boy
样品 12:
我会把样品交给莱娅公主👸
下面的文字似乎把莱娅公主、纳尔·沙达和汉·索洛联系了起来。它似乎是从《走私者的月球之书》中获取上下文的。
输入单词:公主
文本长度:30
生成的输出
princess the freighters of his shaddaa, alerting the empire, and the jedicouncil of the sith lords of the force.
han was not nervous to triggerits his own
结论
生成的文本不是很好,因为模型需要更多的微调。虽然我们对最准确的模型来完美地预测训练数据中的每个单词不感兴趣,但我们希望推广该模型。在过度拟合和泛化之间保持*衡。模型的当前损失为 4.1。我想测试增加纪元,增加批量大小,降低学习率,增加层数和隐藏维度,以获得更低的损失和更好的预测。我的 1080Ti 需要很长时间来训练。我正在等待 AWS 团队给我 Sagemaker ml.p2 实例来对此进行微调!
创建可信数据科学组合项目的分步指南
请跟随我一起探索德国最大的旅游论坛 Vielfliegertreff

作者图片
作为一名鼓舞人心的数据科学家,构建有趣的投资组合项目是展示你技能的关键。当我作为一名商科学生通过在线课程学习编码和数据科学时,我不喜欢数据集由的虚假数据组成,或者在之前就被解决,比如波士顿房价或Kaggle 上的泰坦尼克号数据集。
在这篇博客文章中,我想向你展示我是如何开发有趣的数据科学项目想法并一步一步实现它们的,比如探索德国最大的常旅客论坛 Vielfliegertreff。如果你时间不够,可以直接跳到结论 TLDR。
第一步:选择你感兴趣的相关话题
作为第一步,我想一个潜在的项目,满足以下三个要求,使它最有趣和愉快:
- 解决自己的问题或燃眉之急
- 与最*发生的一些事件相关联或特别有趣
- 在之前没有被解决或覆盖吗
由于这些想法仍然很抽象,让我给你简单介绍一下我的三个项目是如何满足需求的:
概述我自己的数据科学组合项目,以满足上述三个要求。
作为初学者不要追求完美,而是选择你真正好奇的事情并写下你想在你的话题中探索的所有问题。
第二步:开始收集你自己的数据集
鉴于你遵循了我的第三个要求,将不会有公开可用的数据集,你将不得不自己收集数据。在浏览了几个网站后,我在不同的场景中使用了三个主要的框架:
我使用的 3 个主要框架的概述。
对于 Vielfliegertreff,我使用 scrapy 作为框架,原因如下:
- 没有隐藏数据的 Java 脚本支持的元素。
- 网站的结构很复杂必须从每个论坛主题到所有主题,从所有主题到所有帖子网页。有了 scrapy,你可以很容易地实现复杂的逻辑,以一种有组织的方式产生新的回调函数。
- 有相当多的帖子,所以抓取整个论坛将需要一些时间。Scrapy 允许你以令人难以置信的速度异步抓取网站。
为了让你知道 scrapy 有多强大,我很快对我的 MacBook Pro (13 英寸,2018,四个雷电 3 端口)进行了基准测试,测试采用了 2,3 GHz 的四核英特尔酷睿 i5 处理器,能够每分钟刮 3000 页左右:

Scrapy 刮削基准。(图片由作者提供)
为了美观而不被堵塞,重要的是你要轻轻地刮,例如启用 scrapy 的 自动节流功能 。此外,我还通过项目管道将所有数据保存到一个 SQL lite 数据库,以避免重复,并打开记录每个 url 请求,以确保如果我停止并重新启动抓取过程,不会给服务器带来更多负载。
知道如何抓取给了你自己收集数据集的自由,同时也教会了你一些重要的概念,比如互联网如何工作,什么是请求,以及 html/xpath 的结构。
对于我的项目,我最终得到了 1.47 gb 的数据,这接*论坛中的 100 万个帖子。
步骤 3:清理数据集
随着你自己的杂乱数据集,投资组合项目最具挑战性的部分来了,数据科学家*均花费 60%的时间:

图片由众筹 2016
与干净的 Kaggle 数据集不同,你自己的数据集可以让你建立数据清理的技能,并向未来的雇主展示你已经准备好处理现实生活中杂乱的数据集。此外,您可以通过利用库来探索和利用 python 生态系统,这些库解决了其他人以前解决的一些常见数据清理任务。
对于我来自 Vielfliegertreff 的数据集,有几个常见的任务,比如将日期转换为熊猫时间戳,将数字从字符串转换为实际的数字数据类型,以及将非常混乱的 html post 文本清理为可读且可用于 NLP 任务的内容。虽然有些任务有点复杂,但我想分享一下我最喜欢的三个库,它们解决了我的一些常见数据清理问题:
- date parser:轻松解析网页上常见的几乎任何字符串格式的本地化日期。
- 明文 : 用明文对抓取的数据进行预处理,创建一个规范化的文本表示。这也是惊人的删除个人身份信息,如电子邮件或电话号码等。
- fuzzywuzzy:模糊串匹配像个 boss。
步骤 4:数据探索和分析
当在 Udacity 上完成数据科学 Nanodegree 时,我遇到了跨行业数据挖掘标准流程(CRISP-DM) ,我认为这是一个非常有趣的框架,可以用一种系统的方式来组织你的工作。
在我们当前的流程中,我们隐含地遵循了我们项目的 CRISP-DM:
通过在步骤 1 中提出以下问题来表达业务理解:
- 新冠肺炎如何影响像 Vielfliegertreff 这样的在线常旅客论坛?
- 论坛里有哪些最好的帖子?
- 作为新加入者,我应该关注哪些专家?
- 人们对航空公司或机场最差或最好的评价是什么?
利用收集到的数据,我们现在能够将上面的初始业务问题转化为具体的数据解释问题:
- 每月发布多少帖子?新冠肺炎之后,2020 年初的职位减少了吗?是否也有某种迹象表明,加入*台的人越来越少,无法旅行?
- 点赞数排名前 10 的帖子有哪些?
- 谁发布的帖子最多,*均收到的赞也最多?这些是我应该定期关注的用户,以便看到最好的内容。
- 对每个帖子进行情感分析,结合命名实体识别来识别城市/机场/航空公司,会产生有趣的正面或负面评论吗?
对于 Vielfliegertreff 项目,人们可以肯定地说,这些年来职位一直呈下降趋势。从 2020 年 1 月开始,我们可以清楚地看到新冠肺炎的职位数量迅速减少,当时欧洲正在关闭边境,这也严重影响了旅行:
按月创建的帖子。(图表由作者提供)
此外用户注册在过去几年里一直在下降,自 2009 年 1 月开始以来,论坛似乎越来越看不到它的快速增长:
几个月来注册用户的数量。(图表由作者提供)
最后但同样重要的是,我想检查一下最受欢迎的帖子是关于什么的。不幸的是,这是在德国,但这确实是一个非常有趣的帖子,一个德国人被允许在美国航空母舰上度过一段时间,并在 C2 飞机上体验了弹射起飞。帖子里有一些非常好看的图片和有趣的细节。如果你懂一些德语,请随意查看这里的:

Vielfliegertreff 上最受欢迎帖子的图片样本(图片由flekenmann提供)
第五步:通过博客或网络应用分享你的作品
完成这些步骤后,您可以更进一步,创建一个对某些数据点进行分类或预测的模型。对于这个项目,我没有进一步尝试以特定的方式使用机器学习,尽管我有一些关于对与某些航空公司相关的帖子的情感进行分类的有趣想法。
然而,在另一个项目中,我模拟了一个价格预测算法,允许用户获得任何类型拖拉机的价格估计。该模型随后被部署了 awesome streamlit 框架,可以在这里找到(请耐心加载,它可能会加载得慢一点)。
另一种分享你作品的方式是像我一样,在 Medium、 Hackernoon 、 KDNuggets 或其他热门网站上发表博文。写博文的时候,关于作品集项目或者其他话题,比如 牛逼的交互 AI 应用 ,我总是尽量让它们变得有趣,视觉化,互动性。以下是我的一些最佳建议:
- 为了容易理解和打破一些长文本包括漂亮的图片
- 包括互动元素,比如让用户互动的推文或视频
- 通过 airtable 或 plotly 等工具和框架,将枯燥的表格或图表转变为交互式的表格或图表
结论& TLDR
想出一个博客帖子的主意,来回答你的一个紧迫问题或者解决你自己的问题。理想情况下,这个话题的时机是相关的,并且在之前没有被任何人分析过。根据你的经验、网站结构和复杂程度,选择一个最适合抓取工作的框架。在数据清理期间利用现有的库来解决棘手的数据清理任务,如解析时间戳或清理文本。最后,选择如何最好地分享你的作品。在成为数据科学家的征途上,一个交互式部署的模型/仪表板或者一篇写得很好的中型博客文章都可以让你与其他申请者区分开来。
一如既往,请随时与我分享一些伟大的数据科学资源或您的一些最佳组合项目!







浙公网安备 33010602011771号