TowardsDataScience 博客中文翻译 2019(四百四十六)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

用 C 语言实现简单的神经网络

原文:https://towardsdatascience.com/simple-neural-network-implementation-in-c-663f51447547?source=collection_archive---------3-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by JJ Ying on Unsplash

作为深入研究机器学习概念的一部分,我决定在没有任何向量或矩阵库的帮助下,用 C 从头开始编写一个简单的神经网络。

“为什么 C 并没有向量或矩阵库?…"

网上发布的大多数样本神经网络都是用 Python 编写的,并且使用了 numpy 等强大的数学库。虽然这些示例中的代码简洁明了,但是当复杂的矩阵运算被压缩到一条语句中时,可能很难掌握反向传播背后的细节。当你被迫用 C 写出循环时,概念背后的数学变得更加清晰。我强烈建议这样做,即使你最终会使用一个健壮的库,比如 TensorFlow。

本文假设您已经理解了神经网络和反向传播背后的概念。如果你还没有到那里,我建议从这里开始。我将通过讨论下面的关键代码片段来浏览代码。如果你想看看完整的源代码,你可以在这里找到它

我们开始吧!我们首先定义几个辅助函数,包括激活函数及其相应的导数。第三个函数用于初始化 0.0 和 1.0 之间的权重:

// Activation function and its derivative
**double** sigmoid(**double** x) { **return** 1 / (1 + exp(-x)); }
**double** dSigmoid(**double** x) { **return** x * (1 — x); }// Init all weights and biases between 0.0 and 1.0
**double** init_weight() { **return** ((**double**)rand())/((**double**)RAND_MAX); }

我们的网络将由一个具有 2 个节点的隐藏层和一个输出层节点组成。这是学习 XOR 函数的最低配置:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下面我们定义网络的维度,并为层、偏差和权重分配数组:

**static** **const** **int** numInputs = 2;
**static** **const** **int** numHiddenNodes = 2;
**static** **const** **int** numOutputs = 1;**double** hiddenLayer[numHiddenNodes];
**double** outputLayer[numOutputs];**double** hiddenLayerBias[numHiddenNodes];
**double** outputLayerBias[numOutputs];**double** hiddenWeights[numInputs][numHiddenNodes];
**double** outputWeights[numHiddenNodes][numOutputs];

就反向传播算法而言,我考虑了与如何迭代训练数据相关的两个选项。虽然有许多口味可供选择,但最基本的两种是随机梯度下降(SGD)批量梯度下降。在这种情况下,我选择了 SGD ,其中权重基于一对输入/预期输出进行更新。用这种方法更容易将算法概念化。使用这种方法时,为了最大化网络收敛到正确解的机会,随机化训练对的顺序是很重要的。

以下是训练集:

**static** **const** **int** numTrainingSets = 4;**double** training_inputs[numTrainingSets][numInputs] = { {0.0f,0.0f},{1.0f,0.0f},{0.0f,1.0f},{1.0f,1.0f} };**double** training_outputs[numTrainingSets][numOutputs] = { {0.0f},{1.0f},{1.0f},{0.0f} };

主循环首先迭代一定数量的历元(本例中为 10,000 个),对于每个历元,它挑选一对输入和预期输出进行操作。因为 SGD 要求输入/输出对是随机的,所以我在每个时期打乱一个索引数组,以便选择一个随机对,同时确保每个时期使用所有输入:

// Iterate through the entire training for a number of epochs **for** (**int** n=0; n < epochs; n++) { // As per SGD, shuffle the order of the training set
  **int** trainingSetOrder[] = {0,1,2,3};
  shuffle(trainingSetOrder,numTrainingSets); // Cycle through each of the training set elements
  **for** (**int** x=0; x<numTrainingSets; x++) {
    **int** i = trainingSetOrder[x];

其余的代码片段在上面的循环中运行,构成了反向传播算法的“核心”。根据 SGD ,我们采用单对训练输入,由变量 i 指定,并执行以下操作:

第一部分是在给定当前权重的情况下计算网络的输出,从根据以下公式计算隐藏层激活开始:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 j 是隐藏节点的数量(2),而 k 是输入的数量(2):

// Compute hidden layer activation **for** (**int** j=0; j<numHiddenNodes; j++) {
  **double** activation=hiddenLayerBias[j];
    **for** (**int** k=0; k<numInputs; k++) {
      activation+=training_inputs[i][k]*hiddenWeights[k][j];
    }
  hiddenLayer[j] = sigmoid(activation);
}

然后,我们通过下式计算输出层激活:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 j 是输出节点(1)的数量,而 k 是隐藏节点(2)的数量:

// Compute output layer activation
**for** (**int** j=0; j<numOutputs; j++) {
  **double** activation=outputLayerBias[j];
  **for** (**int** k=0; k<numHiddenNodes; k++) {
    activation+=hiddenLayer[k]*outputWeights[k][j];
  }
  outputLayer[j] = sigmoid(activation);
}

下一步包括计算网络权重的微小增量变化,这将使网络朝着最小化网络刚刚计算的输出误差的方向移动。这一步从输出节点开始,向后进行。我们通过计算误差的导数并将其乘以该节点输出的导数来计算权重的变化( deltaOutput )。这里我们使用均方误差(MSE) 函数来计算误差。然而,请注意,对于反向传播本身,我们只需计算误差的导数,对于 MSE 而言,该导数就是预期输出和计算输出之间的差值。参见这篇文章以获得这背后更完整的数学解释。对于输出层,我们计算每个输出节点的增量:

// Compute change in output weights **double** deltaOutput[numOutputs];
**for** (**int** j=0; j<numOutputs; j++) {
  **double** dError = (training_outputs[i][j]-outputLayer[j]);
  deltaOutput[j] = dError*dSigmoid(outputLayer[j]);
}

对于隐藏层,这是一个类似的过程,除了给定隐藏节点的误差计算是所有输出节点的误差之和(对其应用适当的权重):

// Compute change in hidden weights **double** deltaHidden[numHiddenNodes];
  **for** (**int** j=0; j<numHiddenNodes; j++) {
    **double** dError = 0.0f;
    **for**(**int** k=0; k<numOutputs; k++) {
      dError+=deltaOutput[k]*outputWeights[j][k];
    }
  deltaHidden[j] = dError*dSigmoid(hiddenLayer[j]);
}

现在我们已经有了每个输出和隐藏节点的增量,最后一步是将它们应用到各自的权重矩阵和偏差单位:

// Apply change in output weights **for** (**int** j=0; j<numOutputs; j++) {
  outputLayerBias[j] += deltaOutput[j]*lr;
    **for** (**int** k=0; k<numHiddenNodes; k++) {
      outputWeights[k][j]+=hiddenLayer[k]*deltaOutput[j]*lr;
    }
}
// Apply change in hidden weights
**for** (**int** j=0; j<numHiddenNodes; j++) {
  hiddenLayerBias[j] += deltaHidden[j]*lr;
  **for**(**int** k=0; k<numInputs; k++) {
    hiddenWeights[k][j]+=training_inputs[i][k]*deltaHidden[j]*lr;
  }
}

差不多就是这样!最后一个细节是学习率,在这个应用中设置为 0.1。这是一个值,它必须随着时期的数量进行调整,以最大化网络有效学习问题的机会。对于这个问题,0.1 的学习率和 10,000 的纪元的组合似乎是一个很好的组合。这是一张追踪训练过程中误差的图表。对于该图,我每 10 个时期绘制一个样本:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

虽然编写这段代码时没有考虑到可扩展性,但是扩展它的功能,使之包括以下内容会很有趣:可配置的隐藏层数、批量梯度下降以及激活和错误函数的附加选项。请随意摆弄代码,不要犹豫提出问题或反馈!

使用张量流执行的简单神经网络模型

原文:https://towardsdatascience.com/simple-neural-network-model-using-tensorflow-eager-execution-997bbadef84a?source=collection_archive---------14-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Reference: https://colab.research.google.com/github/zaidalyafeai/Notebooks/blob/master/Eager_Execution_Enabled.ipynb

简介

渴望执行是 TensorFlow (TF)中一种从零开始构建深度学习模型的巧妙方法。它允许您构建原型模型,而没有 TF 通常使用的图形化方法带来的麻烦。

例如,使用急切执行,不需要启动图形会话来执行张量计算。这意味着更快的调试,因为您可以即时检查每一行计算,而不需要将计算包装在图形会话中。

然而,作为免责声明,使用急切执行需要一些关于深度学习中使用的矩阵代数概念的知识,特别是关于如何在神经网络中进行前向传递。如果你正在寻找一些更高级的现成的东西,我建议使用 TF 或 PyTorch 中的 Keras API。

本文将通过描述构建、训练和评估一个简单的多层感知器的过程,提供一个如何使用热切执行的例子。

建筑和符号

此示例中构建的神经网络由一个输入层、一个隐藏层和一个输出层组成。输入层包含 3 个节点,隐藏层包含 20 个节点,输出层包含 1 个节点。输出值是连续的(即神经网络执行回归)。

输入层、隐藏层和输出层的值以及层之间的权重可以表示为矩阵。对隐藏层和输出层的偏差可以表示为向量(具有一行或一列的矩阵的特殊情况)。下图显示了每个矩阵和向量的维度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Notations and dimensions for matrices and vectors

开始急切执行

在导入本例所需的依赖项(主要是 NumPy 和 TF)之后,如果您没有使用 TF 2.0,您将需要启用急切执行。下面的代码片段展示了如何启用急切执行。

为培训和评估准备数据

下一步是通过使用 NumPy 的 random 模块,随机生成一些用于训练和评估的数据(当然是为了说明的目的)。使用这种方法,我创建了两组独立的数据,一组用于训练,另一组用于评估。

每组数据包含一个输入数组和一个输出数组。输入数组的形状为(观测值的数量,要素的数量),而输出数组的形状为(观测值的数量,每个观测值的输出值的数量)。要素数量对应于输入图层中的结点数量,而每个观测值的输出值数量对应于输出图层中的结点数量。

在生成数据之后,我将测试数据分成几批,以便进行更有效的评估。训练数据也将被分成批次,但是在训练过程本身中完成。

下面的片段显示了我如何准备数据。

建立模型

我在这里做的是创建一个 Python 类,它存储负责权重和偏差初始化、正向传递、反向传播以及权重和偏差更新的代码。

权重和偏差通过从标准正态分布中抽取随机值来初始化。权重的随机初始化通常优于用值 0 或 1 初始化权重,以便减少出现诸如消失梯度等问题的机会。

正向传递可由以下等式描述。relu()代表整流线性单位函数,它以非线性方式转换输入和偏差的线性组合。输出 Y 的等式没有变换函数,因为输出应该是连续值。顺便提一下,如果期望输出是分类的,则在第二个等式中将需要诸如 sigmoid 或 softmax 之类的非线性变换函数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Matrix algebra for the forward pass

损失的反向传播以及权重和偏差的更新只需要几行代码(分别在模型类的 loss()和 backward()方法中)。

下面相当长的片段展示了如何在一个类中实现模型构建过程。额外的 compute_output()方法是前向传递算法的包装器,便于用户选择用于模型训练和评估的硬件设备(CPU 或 GPU)。

您可能已经注意到了类中使用的函数 tf.cast()。原因是,由于前面代码片段中的 from_tensor_slices()方法返回 tf.float64 数据格式的张量,而矩阵运算(例如 tf.matmul())只能处理 tf.float32 数据格式的张量,所以会触发这个奇怪的错误。我没有在 TF 2.0 上尝试过急切执行,所以我不确定这个问题是否已经在这个新版本中解决了。我所知道的是,这个数据格式的问题肯定发生在我在这个例子中使用的 TF 版本(即 1.31.1)中,所以如果在 TF 的旧版本上使用急切执行,这是需要注意的。

训练模特

准备好数据,建立好模型之后,接下来就是训练模型了。模型训练非常简单,只需要几行代码。这里的基本思想是对每个时期的每批数据重复以下步骤:通过模型输入张量以获得预测张量,计算损失,反向传播损失,并更新权重和偏差。在每个时期,训练数据将被随机分成不同的批次,以提高模型训练的计算效率,并帮助模型更好地泛化。下面的代码片段说明了如何通过热切的执行来完成培训。

评估模型

最后一步是使用测试集评估模型。这样做的代码类似于训练的代码,但是没有反向传播以及权重和偏差的更新。

结论

虽然急切执行很容易使用,但我想再次强调,这是一种低级的方法。我建议不要使用渴望执行,除非:1)你正在做的工作需要你从头开始构建深度学习模型(例如,关于深度学习模型的研究/学术工作),2)你正在试图理解深度学习背后正在发生的数学事情,或者 3)你只是喜欢从零开始构建东西。

话虽如此,但我认为急切执行是一种很好的方法,可以帮助你更好地理解我们进行深度学习时实际发生的事情,而不必摆弄复杂的图表或传统 TF 方法带来的其他令人困惑的东西。

我为这个例子创建的 Google Colab 笔记本可以在这里找到。

使用 Keras 的简单神经网络情感分析器

原文:https://towardsdatascience.com/simple-neural-network-sentiment-analyser-using-keras-179bc9f50fbc?source=collection_archive---------22-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

什么是情绪分析器?

想知道产品负责人如何在不阅读数以百万计的文章和评论的情况下,深入了解客户对其产品的反应吗?一个情绪分析器是答案,这些东西可以被快速部署,然后连接到 twitter、评论网站、数据库或所有上述网站,使我们能够了解互联网对我们的产品/服务/业务的总体感受。

这是一种非常懒惰的方式来理解一个产品是如何在很短的时间内被一大群顾客感知的。

Keras 是什么?

维基百科引用:“Keras 是一个用 Python 编写的开源神经网络库。它能够运行在 TensorFlow、微软认知工具包、Theano 或 PlaidML 之上。旨在实现深度神经网络的快速实验,它专注于用户友好、模块化和可扩展

对于那些会用 python 编码,但可能不太熟悉 TensorFlow 或 Theano 的人来说,这是一个很好的选择。

让我们开始吧…导入和格式化数据

对于这段简单的代码,我们将使用通常引用的 IMDB review 数据集,它可以直接从 Keras 中免费获得,它的使用如此频繁,甚至在他们的示例中也是如此。

我们需要做的第一件事是从 Keras 导入 IMDB 数据集,然后将其分成训练和测试数据集。

from keras.datasets import imdb top_words = 10000 (x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=top_words)

我们应该会看到一个下载屏幕和一个警告,上面写着“正在使用 tensorflow backend”,这没什么问题,让它做它自己的事吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以运行下面这段代码来看看数据集,它基本上是来自英语词典的单词和相应的 id。我们稍后将使用这些 id 进行翻译,因为神经网络更喜欢处理数字而不是纯文本。

imdb.get_word_index()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来的部分可能是唯一复杂的部分,它几乎是可选的——为了测试我们的数据看起来不错,我们需要抓住我们的第一次审查,并把关键内容转化为实际的单词。

word_dict = imdb.get_word_index() 
word_dict = { key:(value + 3) for key, value in word_dict.items() } word_dict[''] = 0 
# Padding word_dict['&amp;amp;amp;gt;'] = 1 
# Start word_dict['?'] = 2 
# Unknown word reverse_word_dict = { value:key for key, value in word_dict.items() } print(' '.join(reverse_word_dict[id] for id in x_train[0]))

我说的是可选的,但是在现实世界中,你总是想要做这些检查。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Here is our first review reversed out into text.

接下来需要做一些整理,我们需要确保所有进入神经网络的东西都是相同的形状。也就是说,我们将指定评论的最大字符长度,并将其分配给变量 max_review_length,然后遍历我们的数据集,并用零填充任何评论的结尾,以确保所有内容的长度为 500 个字符。

from keras.preprocessing import sequence 
max_review_length = 500 
x_train = sequence.pad_sequences(x_train, maxlen=max_review_length) x_test = sequence.pad_sequences(x_test, maxlen=max_review_length)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

If we print out our word dictionary, notice we just have a load of numbers? These all correspond to words in our word dictionary.

建立模型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

模型如下所示。这是一段可重用的便捷代码。如果你真的想了解这一切是如何联系在一起的,在这个博客这里有大量关于单词嵌入的信息。

您将看到代码被分解以便于理解,并显示在一个完整的块中,以供检查或复制。

首先我们导入必要的包并设置一个可变的“嵌入向量长度”。单词嵌入提供了单词及其相关含义的密集表示。

#Build the Model from keras.models 
import Sequential from keras.layers 
import Dense from keras.layers.embeddings 
import Embedding from keras.layers 
import Flattenembedding_vector_length = 32

接下来定义模型:这告诉我们,我们正在使用一个顺序模型——即由许多层堆叠在一起构建的模型,在 Keras 文档中有很多关于这方面的信息。

model = Sequential()

我们添加了一个嵌入层——这是处理文本时使用的最佳实践——它将向量排列成表格,因此更容易处理大量数据。

model.add(Embedding(top_words, embedding_vector_length, input_length=max_review_length))

接下来,我们将输入数据展平,以便下一层使用

model.add(Flatten())

我们添加一些密集层,它们控制模型“如何”学习——前两层有 16 个神经元,我们可以在稍后改变这些神经元来改变模型的准确性。

model.add(Dense(16, activation='relu')) 
model.add(Dense(16, activation='relu'))

Relu 是一个激活函数——在文档中有更多,但是现在我们只需要知道 Relu 是我们正在做的事情中最流行的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The gradient of the ReLU function ensures that we don’t use all the neurons in the network at the same time, therefore its great for high performance deep learning.

最后的密集层是我们的输出层——它被设置为 1 个神经元,因为我们只想要一个整体的输出——情绪的分数!

model.add(Dense(1, activation='sigmoid'))

我们使用 sigmoid 作为我们的输出层激活函数,因为我们提供的输出是 0 到 1 之间的分数,取决于积极或消极的情绪。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来,我们需要编译或建模,这是有效地把它们粘在一起。不要进入太多的细节,优化器是我们的网络如何优化它的权重和它如何学习。你可能听说过“梯度下降”这个词,Adam 是它的变体。

model.compile(loss='binary_crossentropy',optimizer='adam', metrics=['accuracy'])

我们还可以改变衡量结果的方式。一般来说,我们使用“准确性”,但在 Keras 中有不同的说法。

我们在执行之前做的最后一件事是打印出模型——这将使我们能够检查我们对配置是否满意。

print(model.summary())

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正如所承诺的,这里是完整的代码。

import Sequential from keras.layers 
import Dense from keras.layers.embeddings 
import Embedding from keras.layers 
import Flattenmodel = Sequential()
model.add(Embedding(top_words, embedding_vector_length, input_length=max_review_length))
layer model.add(Flatten()) 
model.add(Dense(16, activation='relu')) 
model.add(Dense(16, activation='relu'))
model.add(Dense(1, activation='sigmoid')) model.compile(loss='binary_crossentropy',optimizer='adam', metrics=['accuracy'])print(model.summary())

拟合模型

拟合模型——你可能在机器学习过程中遇到过这种情况。纪元编号是我们决定进行的迭代次数,意味着我们通过神经网络的次数。

注意,我们在同一行代码中用训练数据拟合,用测试数据验证?

批次大小 128 是随机的,通常较小的批次大小会更准确,但我们仍然需要注意过度拟合—稍后讨论。

hist = model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=5, batch_size=128)

运行代码,我们应该能够跟踪神经网络,通过你要求它做的任何数量的时期——在我的例子中是 5,所以 5 行结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

These results are produced to track the progress of a neural network in Keras.

这就是我们需要小心过度拟合的地方。 如果我们看到 acc(训练精度)和 val_acc(测试集精度)值之间的精度相似,那么我们可能会有一个过拟合问题,对此的快速解决方法是记下我们完成的历元数。

模型分数

得分是固有的。我们所需要做的就是观想它!

import seaborn as sns 
import matplotlib.pyplot as plt 
%matplotlib inline 
sns.set() val = hist.history['val_acc'] epochs = range(1, len(acc) + 1) plt.plot(epochs, val, ':', label='Validation accuracy') plt.title('Validation Accuracy') plt.xlabel('Epoch') plt.ylabel('Accuracy') plt.legend(loc='upper left') 
plt.plot()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用我们的代码

现在我们需要做的就是编写一个函数,允许我们提交自己的评论,并根据我们的模型进行分析!下面的代码可以做到这一点。

import string 
import numpy as np def analyze(text): 
# Prepare the input by removing punctuation characters, converting characters to lower case, and removing words containing numbers translator = str.maketrans('', '', string.punctuation) 
text = text.translate(translator) 
text = text.lower().split(' ') 
text = [word for word in text if word.isalpha()] # Generate an input tensor input = [1] for word in text: 
    if word in word_dict and word_dict[word] &amp;amp;lt; 
    top_words: input.append(word_dict[word]) 
    else: 
       input.append(2)   
       padded_input = sequence.pad_sequences([input], maxlen=max_review_length) # Invoke the model and return the result result = model.predict(np.array([padded_input][0]))[0][0] return result

测试情感分析器

现在,我们可以使用自己的评论来测试神经网络。我们所要做的就是将我们的评论输入到我们刚刚创建的“分析”函数的参数中。

我们可以从下面我输入的基本评论中看到,非常强烈的评论得分很高,非常负面的评论得分很低,所以看起来我们的情绪分析器神经网络起作用了!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

原载于 2019 年 5 月 19 日http://drunkendatascience.com

python 中的简单绘图(因此您可以专注于更大的事情)

原文:https://towardsdatascience.com/simple-plotting-library-in-python-43e8ac687d23?source=collection_archive---------33-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Today it’s all about having the numbers

TLDR :使用的纸笔在建造原型时快速启动你的绘图和洞察力

所以你有了新的实验想法💡。也许是一种新的强化学习算法?新哈希表?我不会再尝试猜测了:)为什么要猜测,当我确定你需要做一件事,无论这个想法是什么,来验证它——你需要绘制一些实验数据。所以你知道如何用 python 实现你的想法,而且你在一个令人惊讶的短时间内就做到了。现在是时候观察这个想法在一些不同的输入上的表现了。并查看性能是否可靠,或者每次运行代码时性能是否会发生变化。

那么,抽象地说,你将采取什么步骤来可视化你正在运行的过程?以下是我在实验中的想法:

  1. 定义我要测量的量’ Y’ 。示例:批次损失
  2. 定义 Y 所依赖的数量’ x '(考虑时间步长或输入大小)
  3. 在我的代码中找到便于记录这些量的值的地方
  4. 重复几次实验,也许是针对系统的一些不同配置。
  5. 产生那些美丽而有见地的情节。

这是一个明确的计划。然而,很少有技术挑战逃过我们的注意:如果我们运行几次实验,以某种方式在图中平均结果并显示它们的方差/标准差是有意义的。

…此外,从长远来看,将所有信息存储在一个巨大的全球字典中可能是一件痛苦的事情。

…此外,这些噪声图可以使用一些过滤。

让我们看一个例子,看看我们如何解决它。让我们假设一些添加了噪声的数学函数是您正在开发的新原型:

结果,嗯,不是很好:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

介绍pen ’ n ’ paper—一个简单方便绘图的 python 库;

**import** pennpaper **as** pp

metrics = **[]for** name, func **in** funcs.items***()***:
    m = pp.Metric***(***name***)*** m.add_arrays***(***X, func***(***X***))*** metrics.append***(***m***)*** pp.plot_group***(***metrics, smoothen=**True*)***

好了,这给了我们一个有名字的传说,并且去掉了大部分的噪音:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来我想做的是,通过对过程进行多次采样,并将有关标准差的信息添加到图中,进一步降低噪声。为了简化代码,让我们从一个函数开始——正弦波。

我们得到了单独策划的罪恶:

**import** pennpaper **as** pp

name = **'sin'** func = funcs***[***name***]*** m1 = pp.Metric***(***name***)*** m1.add_arrays***(***X, func***(***X***))*** pp.plot***(***m1, smoothen=**True*)***

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你可以做的是将纸笔指标相加:

m1 = pp.Metric***(***name***)*** m1.add_arrays***(***X, func***(***X***))*** m2 = pp.Metric***(***name***)*** m2.add_arrays***(***X, func***(***X***))*** m3 = pp.Metric***(***name***)*** m3.add_arrays***(***X, func***(***X***))*** pp.plot***(***m1 + m2 + m3, smoothen=**True*)***

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

似乎有 3 个度量标准有所帮助。让我们有 300?

metrics = ***[]* for** i **in** range***(***300***)***:
    m = pp.Metric***(***name***)*** m.add_arrays***(***X, func***(***X***))*** metrics.append***(***m***)*** pp.plot***(***sum***(***metrics***)***, smoothen=**True*)***

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

大数定律在我们这边,我们得到相当精确的图。另请注意,阴影区域的大小代表标准差,与正弦波相差 2 个单位,这正是我们在噪声公式中输入的值:y += np.random.normal(0,2,size=y.size)。

让我们把我们所学的放在一起,画出所有 3 个函数,画出一个带平滑的图和一个不带平滑的图:

**import** pennpaper **as** pp
**from** collections **import** defaultdict

metrics = defaultdict***(***list***)* for** i **in** range***(***90***)***:
    **for** name, f **in** funcs.items***()***:
        m = pp.Metric***(***name***)*** m.add_arrays***(***X, f***(***X***))*** metrics***[***m.name***]***.append***(***m***)*** metrics = ***[***sum***(***v***)* for** v **in** metrics.values***()]*** pp.plot_group***(***metrics***)*** pp.plot_group***(***metrics, smoothen=**True*)***

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

No smoothing, just the effect of averaging 90 tries

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Smooth version

总结:我们已经学会了如何使用 pen’n’paper Metric class 轻松组合多个测量值,并使用。plot()和。plot_many()方法。您可以使用以下方式安装笔和纸:

pip install pennpaper

给它一颗星🌟这里:https://github.com/ikamensh/pennpaper

这是一个我为个人使用而写的便利工具,但是我想你可能会发现它的用处!😃

简单强化学习:Q-学习

原文:https://towardsdatascience.com/simple-reinforcement-learning-q-learning-fcddc4b6fe56?source=collection_archive---------1-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Typical Exploring Image for RL - Credit @mike.shots

简介

我在参加强化学习课程时学到的最喜欢的算法之一是 q-learning。可能是因为它对我来说最容易理解和编码,但也因为它似乎有意义。在这篇快速的帖子中,我将讨论 q-learning,并提供理解该算法的基本背景。

什么是 q 学习?

Q-learning 是一种非策略强化学习算法,它寻求在给定的当前状态下采取最佳行动。它被认为是不符合策略的,因为 q-learning 函数从当前策略之外的动作中学习,比如采取随机动作,因此不需要策略。更具体地说,q-learning 寻求学习一种使总回报最大化的策略。

什么是‘Q’?

q-learning 中的“q”代表质量。在这种情况下,质量代表了一个给定的行为在获得未来回报方面的有用程度。

创建一个 q 表

当进行 q-learning 时,我们创建一个所谓的 q-table 或遵循[state, action]形状的矩阵,并将我们的值初始化为零。然后,在一集之后,我们更新并存储我们的 q 值。这个 q 表成为我们的代理根据 q 值选择最佳行动的参考表。

import numpy as np# Initialize q-table values to 0Q = np.zeros((state_size, action_size))

Q-学习和更新

下一步只是让代理与环境交互,并更新我们的 q 表Q[state, action]中的状态动作对。

采取行动:探索或利用

代理以两种方式之一与环境交互。第一种是使用 q 表作为参考,并查看给定状态的所有可能动作。然后,代理根据这些操作的最大值选择操作。这就是所谓的 利用 ,因为我们利用现有的信息做出决定。

第二种采取行动的方式是随机行动。这叫做 探索 。我们不是根据最大未来回报来选择行动,而是随机选择行动。随机行动很重要,因为它允许代理探索和发现新的状态,否则在利用过程中可能不会被选择。您可以使用 epsilon ( ε )来平衡探索/利用,并设置您希望探索和利用的频率值。这里有一些粗略的代码,将取决于如何设置状态和动作空间。

import random# Set the percent you want to explore
epsilon = 0.2if random.uniform(0, 1) < epsilon:
    """
    Explore: select a random action """
else:
    """
    Exploit: select the action with max value (future reward) """

更新 q 表

更新发生在每个步骤或动作之后,并在一集结束时结束。在这种情况下,完成意味着代理到达某个端点。例如,终端状态可以是任何类似于登录到结帐页面、到达某个游戏的结尾、完成某个期望的目标等的状态。在单个情节之后,代理将不会学到太多,但是最终通过足够的探索(步骤和情节),它将收敛并学习最优 q 值或 q 星(Q∗)。

以下是 3 个基本步骤:

  1. 代理从一个状态(s1)开始,采取一个动作(a1)并收到一个奖励(r1)
  2. 代理通过随机(epsilon,ε)引用具有最高值(max) 的 Q 表来选择动作
  3. 更新 q 值

以下是 q-learning 的基本更新规则:

# Update q valuesQ[state, action] = Q[state, action] + lr * (reward + gamma * np.max(Q[new_state, :]) — Q[state, action])

在上面的更新中,有几个变量我们还没有提到。这里发生的是,我们根据贴现后的新值和旧值之间的差异来调整 q 值。我们使用 gamma 来贴现新值,并使用学习率(lr)来调整步长。以下是一些参考资料。

学习率: lr或学习率,常被称为α或α,可以简单定义为你接受新值相对于旧值的程度。上面我们取新旧之间的差值,然后用这个值乘以学习率。这个值然后被加到我们先前的 q 值上,这实质上使它朝着我们最新更新的方向移动。

γ:gammaγ 是贴现因子。它用于平衡当前和未来的奖励。从上面的更新规则中,您可以看到我们将折扣应用于未来的奖励。通常,该值可以在 0.8 到 0.99 的范围内。

奖励: reward是在给定状态下完成某个动作后获得的数值。奖励可以发生在任何给定的时间步或只在终端时间步。

Max: np.max()使用 numpy 库,并获取未来奖励的最大值,并将其应用于当前状态的奖励。这是通过未来可能的回报来影响当前的行为。这就是 q-learning 的妙处。我们将未来奖励分配给当前行动,以帮助代理在任何给定状态下选择最高回报的行动。

结论

就这样,简短而甜蜜(希望如此)。我们讨论过 q-learning 是一种非策略强化学习算法。我们使用一些基本的 python 语法展示了 q-learning 的基本更新规则,并回顾了算法所需的输入。我们了解到,q-learning 使用未来的奖励来影响给定状态下的当前行为,从而帮助代理选择最佳行为,使总奖励最大化。

关于 q-learning 还有很多,但希望这足以让你开始并有兴趣学习更多。我在下面添加了几个资源,它们对我学习 q-learning 很有帮助。尽情享受吧!

资源

  1. 使用 OpenAI Gym taxi 环境的绝佳 RL 和 q 学习示例
  2. 强化学习:导论(萨顿的免费书籍)
  3. Quora Q 学习
  4. 维基百科 Q-learning
  5. 大卫·西尔弗关于 RL 的讲座

基于 Fast.ai 随机森林的简单大豆价格回归

原文:https://towardsdatascience.com/simple-soybean-price-regression-with-fast-ai-random-forests-44ab46bf384e?source=collection_archive---------10-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

image credit: Pexels.com

将前沿机器学习应用于商品价格。

作为一名对农业感兴趣的 fast.ai 机器学习 for Coders MOOC 的学生,想到的 fast.ai 随机森林回归库的第一个应用是根据历史数据预测大豆价格。大豆是一种全球大宗商品,在过去十年里,其每蒲式耳的价格每天都在大幅波动。

个别商品的价格历史可以作为简单的结构化表格数据在网上免费获得,这使得这成为一个直截了当的开头话题。下面是代码——注意我们使用的是 Python 3 和 fast.ai 0.7,所以请遵循安装说明。

首先,我们需要在开始之前导入我们的包:fast.ai、quandl、pandas、sk learn——常见的数据科学库。

%load_ext autoreload
%autoreload 2
%matplotlib inlineimport quandlfrom fastai.imports import *
from fastai.structured import *from pandas_summary import DataFrameSummary
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
from IPython.display import displayfrom sklearn import metrics

数据来自免费的 Quandl TF grain/大豆数据集。Quandl 为他们的 API 提供了一个简单的 Python SDK,即入门指南。下拉整个数据集只有一行(很短):

data = quandl.get("TFGRAIN/SOYBEANS", authtoken="<your token")

这将返回一个 Pandas 数据帧(我们称之为“数据”),并且data.info()显示有 4535 行数据被事件日期时间索引。我们可以用data.tail()来表示格式:

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 4535 entries, 2000-12-01 to 2019-01-14
Data columns (total 4 columns):
Cash Price    4535 non-null float64
Basis         4535 non-null float64
Fall Price    4516 non-null float64
Fall Basis    4516 non-null float64
dtypes: float64(4)
memory usage: 177.1 KB

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

data.head()

由于我们有日期时间,这是一个很好的机会来利用 fast.ai 库的日期处理功能工程能力。我将索引重命名为“data ”,并创建了一个新列,其中包含可以由add_datepart()函数处理的相同值:

data.rename_axis('Date')
data['Date'] = data.index
add_datepart(data, 'Date')
data.info()

新列如下。杰瑞米·霍华德在 ML1 第一课中深入解释了这些新列是如何创建的,以及为什么创建。

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 4535 entries, 2000-12-01 to 2019-01-14
Data columns (total 18 columns):
id                  4535 non-null int64
Cash Price          4535 non-null float64
Basis               4535 non-null float64
Fall Price          4516 non-null float64
Fall Basis          4516 non-null float64
Year                4535 non-null int64
Month               4535 non-null int64
Week                4535 non-null int64
Day                 4535 non-null int64
Dayofweek           4535 non-null int64
Dayofyear           4535 non-null int64
Is_month_end        4535 non-null bool
Is_month_start      4535 non-null bool
Is_quarter_end      4535 non-null bool
Is_quarter_start    4535 non-null bool
Is_year_end         4535 non-null bool
Is_year_start       4535 non-null bool
Elapsed             4535 non-null int64
dtypes: bool(6), float64(4), int64(8)

为了简单起见,我在大豆价格回归中第一次删除了一些列。我只保留 col_list 变量中列出的列。

col_list = ['Cash Price', 'Basis', 'Year', 'Month', 'Week', 'Day', 'Dayofweek', 'Dayofyear']dfdata = dfdata[col_list]

为了清理格式,我从 Pandas 数据帧中提取值并重新导入:

df = dfdata.values
df = pd.DataFrame.from_records(df)
df.columns = col_list

现在我们又有了一个 Pandas dataframe,我使用了另一个方便的 fast.ai 函数,它(如文档所解释的那样)**将字符串列转换为分类值列,并就地完成。**为什么?允许随机森林回归器理解表格数据。同样,这将在本课程中更深入地讨论。

train_cats(df)

另一个 fast.ai 预处理器(如文档所述)**获取数据帧,分离响应变量,并将测向转换为全数字数据帧。**我们的因变量(‘y’)是这个谷物升降机的大豆每日现金价格,其他一切都是自变量。

df, y, nas = proc_df(df, 'Cash Price')

现在我们已经准备好适应我们的数据了!这很简单,因为:

m = RandomForestRegressor(n_jobs=-1)
m.fit(df, y)
m.score(df,y)Score: 0.9991621993655437

相当不错!Fast.ai 对此的准确率为 99.91%,因此现在我们可以向回归器投掷一个测试数据帧(具有相同的格式),并获得实际的预测。这是我们的单行测试数据框架:

df1 = pd.DataFrame({'Basis':[-.85],
                    'Year':[2019],
                    'Month':[1],
                    'Week':[4],
                    'Day':[25],
                    'Dayofweek':[6],
                    'Dayofyear':[25],})

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

并获得对 2019 年 1 月 25 日的价格的单一预测,给定 85 美分的基数:

train_cats(df1)
m.predict(df1) Return: array([8.465])

一蒲式耳大豆估计售价为 8.465 美元。

为了好玩,我画了一张图,显示基差的变化如何影响一天(2019 年 1 月 25 日)的回归。代码:

df1.iloc[0:, 0] = -.95
iterpreds = list()
a = list()
for x in range(0,10):
    df1.iloc[0, 0] += .1
    b = df1.at[0, 'Basis']
    iterpreds.append(m.predict(df1).astype(float).item(0))
    a.append(b)plt.plot(a, iterpreds)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

basis on x axis, price on y

可以做得更多!我们应该扩展我们的模型,以包括所有可用的列,看看是否有第二种商品可以添加到模型中,以探索其他作物价格是否同步移动,并绘制随着时间的推移其他变量的变化的影响。

参考资料:

[1]https://course.fast.ai/ml.html

[2]https://forums . fast . ai/t/fastai-v 0-7-install-issues-thread/24652

[3]https://docs.quandl.com/docs/getting-started

附加代码在我的 github 上:www.github.com/matthewarthur,我的 LinkedIn 是https://www.linkedin.com/in/matt-a-8208aaa/

运动鞋品牌的简单画面:“Yeezy”和“Off-White”

原文:https://towardsdatascience.com/simple-tableau-visuals-for-sneaker-brands-yeezy-and-off-white-638ff1b04cc1?source=collection_archive---------44-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

自本世纪初以来,收集和转售运动鞋一直是我的一个爱好。就个人而言,我喜欢这些运动鞋带来的故事和独特性,但作为一名高中生赚点外快也是一个好处。在我成长的过程中,我一直认为运动鞋市场和收集专属运动鞋的爱好是“城市”的事情,集中在纽约和洛杉矶这样的地区,所以我从来没有想到运动鞋行业和转售市场有一天会成为主流。像 StockX 和 Goat 这样的电子商务网站已经允许新兴市场在曾经无法获得独家发行的城市中发展。

运动鞋行业一直在快速增长,2016 年的估值为 550 亿美元。到 2025 年,该市场预计将达到 950 亿美元。根据 StockX 的数据,运动鞋转售市场目前的估值为 60 亿美元。这种大规模繁荣的一些原因包括社交媒体和运动员/名人代言的力量。社交媒体让品牌获得了更多的曝光率,从而提高了它们的知名度和需求。与运动员和音乐家的合作数量也增加了,这使得新的品牌出现和发展。虽然像耐克和乔丹这样的主要品牌在历史上取得了大部分的成功,但像 Yeezy 和 Off-White 这样的其他品牌可能会有更多的市场控制力,并标志着运动鞋界的一个支点。这些品牌正在蓬勃发展,因为消费者发现它们更有创意,更有个性。

为了更好地理解这两个新兴品牌,我使用了一个名为 Tableau 的数据可视化工具。我研究了一个 StockX 数据集,其中有他们从 2016 年到 2018 年对 Yeezy 和 Off-White 品牌的每笔交易的销售信息。然后,我创建了一些视觉效果,查看收入、销售数量和地区。最后,我将所有的视觉效果整合到一个交互式仪表盘中,提供了进一步的洞察力。这是 Tableau 更具创新性的特点之一。根据你的喜好,视觉效果可以过滤掉,并与其他人互动。

下面是一些仪表盘的截图。我还将展示当你与它们互动时,视觉效果是如何变化的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

以上图片提供了品牌和所有地区的信息。销售额最高的是加利福尼亚和纽约。总的销售价格总计超过 3000 万美元。同样值得注意的是,其他地区也能买到只有在大市场才能买到的产品。虽然主要城市仍然拥有最高的销售数量,但其他地区现在可以购买像 Yeezy 和 Off-White 这样的产品和品牌,这在十年前是闻所未闻的。电子商务网站也可以通过吸引这些地区来发展业务。电子商务使运动鞋和转售市场民主化,这也是这个行业高速发展的原因。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如你所见,当我只选择品牌 Yeezy 时,视觉效果会进行交互,并只向我提供该品牌的信息。我可以清楚地看到,考虑到所有品牌,加州的销售额约为 13,000,仅 Yeezy 品牌的销售额就约为 8800。互动的视觉效果提供了一个清晰和说明性的方式来看到这一点。此外,在比较这两个品牌时,我现在可以看到大部分钱花在了哪里。仅 Yeezy 品牌就花费了近 2000 万美元。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我只选择纽约地区时,Yeezy 品牌的总销售额大约是 300 万美元,而 Off-White 大约是 230 万美元。此外,根据预测模型,纽约地区的销售价格将保持不变。

Tableau 是对数据集进行探索性分析的好方法。它允许您创建仪表板,以有趣且易于使用的方式提供有价值的见解。

一旦你在 Tableau 中创建了你的视觉效果并将它们添加到一个仪表板,你可以通过使用位于每个视觉效果右上角的过滤方法来使视觉效果相互作用。您只需点击想要相互交流的图表上的过滤图标。

简单文本生成

原文:https://towardsdatascience.com/simple-text-generation-d1c93f43f340?source=collection_archive---------9-----------------------

如何教机器“说话”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Kaitlin Dowis on Unsplash

如果你想看完整的代码,这里有 Github 链接

目标

在本文中,我将简要介绍一种使用 Keras 和 Tensorflow 在 Python 中编码和训练文本生成模型的简单方法。我们的目标是训练一个模型来模仿它被训练的文本的说话风格。在这种情况下,我们的数据集是埃德加·爱伦·坡恐怖故事中的 7009 句话。

整理训练数据

训练任何 NLP 模型的第一步是单词的标记化。这里我们使用 Keras Tokenizer,它执行以下操作:

  1. 删除标点符号
  2. 将所有文本设置为小写
  3. 将单词拆分成列表中的单个元素,然后为每个单词分配一个唯一的整数
  4. 用整数替换该单词的所有实例。

令牌化是为嵌入层准备数据所必需的(参见下面的模型架构部分)

使用滑动窗口设置培训数据。我们正在使用一个相当基本的策略,使用前面的 19 个单词来预测第 20 个单词。这些数字的选择没有任何具体的理由,肯定可以修改以改善。

模型架构

1。嵌入层

嵌入层是任何寻求理解单词的深度学习模型的关键层。从数学的角度来看,嵌入层所做的是将向量从高维空间(数万或更多,我们的 vocab 的原始大小)带到低维空间(我们希望用来表示数据的向量的数量,在 Word2Vec、Fasttext 等模型中通常为 100–300)。

然而,它以这样一种方式做到了这一点,即具有相似含义的单词具有相似的数学值,并且存在于与其含义相对应的空间中。可以对这些向量进行数学运算,例如,‘王’减去‘人’可能等于‘皇族’。

2。两个堆叠的 LSTM 层

我不打算在这里深入 LSTM 的细节,但有大量的好文章来看看他们是如何工作的。一些需要注意的事项:

  • 康奈尔大学的这些人表示,当应用于语音识别时,堆叠的 LSTM 可能比单个 LSTM 层中的附加单元增加更多的深度。虽然我们的应用程序不完全相同,但它在使用 LSTM 的程序来尝试识别语言模式方面是相似的,所以我们将尝试这种架构。
  • 第一 LSTM 层必须将return sequences标志设置为真,以便将序列信息传递给第二 LSTM 层,而不仅仅是其结束状态

3。具有 ReLU 激活的密集(回归)层

LSTM 的输出是“隐藏层”。通常在 LSTM 后应用密集图层来进一步捕捉线性关系,但这并不是明确必需的。

4。激活 Softmax 的密集层

这一层对于将上面几层的输出转换成我们整个词汇表中的实际单词概率是必要的。它使用了 softmax 激活函数,这是一个将所有输入单词概率从(-∞,∞)转换为(0,1)的函数。这允许我们选择或生成最可能的单词。

一旦我们建立了我们的模型架构,我们就可以训练它了!

(注意,我们可以使用检查点来保持我们的进度,以防我们的训练被中断。)

部署

训练完成后,我们现在有了一个可以生成文本的模型。然而,我们需要给它一个起点。为此,我们编写了一个函数,它接受一个字符串输入,将其标记化,然后用零填充它,以便它适合我们 19 长的预测窗口。

结果

下面是给定输入字符串后的结果。注意,我们没有用任何标点符号训练我们的模型,所以句子的划分留给读者去解释。

Input String:  First of all I dismembered the corpse.

Model  3 :
first of all i dismembered the corpse which is profound since in the first place he appeared at first so suddenly as any matter no answer was impossible to find my sake he now happened to be sure it was he suspected or caution or gods and some voice held forth upon view the conditions

虽然这不是最有意义的,但它实际上似乎是可读的,并且在正确的位置有正确的单词类型。给定一组更大的训练数据,这种方法和模型可以用来生成更容易理解的文本(当然,最有可能的是通过一些参数调整)。

为了量化性能,您可以使用原始数据实现典型的训练测试分割,并根据预测和目标之间的余弦相似性对预测进行评级。

谢谢大家!

今天就到这里,感谢阅读。如果你想了解更多,这里有一些我做过的其他机器学习项目,你可以阅读一下:

量化聊天室毒性

面向成长的流媒体推荐系统

简单的变压器——介绍使用伯特、罗伯塔、XLNet 和 XLM 的最简单方法

原文:https://towardsdatascience.com/simple-transformers-introducing-the-easiest-bert-roberta-xlnet-and-xlm-library-58bf8c59b2a3?source=collection_archive---------6-----------------------

想要为 NLP 使用 Transformer 模型吗?一页页的代码让你沮丧?不再是了,因为简单的变形金刚正在工作。只需 3 行代码就可以启动、训练和评估变形金刚!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

前言

简单的变形金刚库是通过拥抱脸作为优秀的 T2 变形金刚库的包装而构建的。我永远感谢在拥抱脸的人们所做的艰苦工作,使公众能够方便地访问和使用变形金刚模型。没有你们我真不知道该怎么办!

介绍

我相信可以公平地说,Transformer 模型的成功在推进自然语言处理领域取得了惊人的成就。他们不仅在许多他们被设计解决的 NLP 任务上表现出惊人的飞跃,预先训练过的变形金刚在迁移学习上也表现得出奇的好。这意味着任何人都可以利用训练这些模型的长时间和令人难以置信的计算能力来执行无数种 NLP 任务。你不再需要谷歌或脸书的雄厚财力来构建一个最先进的模型来解决你的 NLP 问题了!

或者人们可能希望如此。事实是,让这些模型发挥作用仍然需要大量的技术知识。除非你在深度学习方面有专业知识或至少有经验,否则这似乎是一个令人生畏的挑战。我很高兴地说,我以前关于变形金刚的文章(这里是这里是这里是)似乎已经帮助了很多人开始使用变形金刚。有趣的是,我注意到不同背景的人(语言学、医学、商业等等)都在尝试使用这些模型来解决他们自己领域的问题。然而,为了使变压器适应特定的任务,需要克服的技术障碍并非微不足道,甚至可能相当令人沮丧。

简单变压器

这个难题是我决定开发一个简单的库来使用 Transformers 执行(二进制和多类)文本分类(我见过的最常见的 NLP 任务)的主要动机。我们的想法是让它尽可能简单,这意味着抽象出许多实现和技术细节。库的实现可以在 Github 上找到。我强烈建议您查看它,以便更好地了解一切是如何工作的,尽管使用该库并不需要了解内部细节。

为此,我们编写了简单的 Transformers 库,只需 3 行代码就可以初始化 Transformer 模型,在给定的数据集上进行训练,并在给定的数据集上进行评估。让我们看看这是怎么做的,好吗?

装置

  1. 这里安装 Anaconda 或 Miniconda 包管理器
  2. 创建新的虚拟环境并安装所需的软件包。
    conda create -n transformers python pandas tqdm
    conda activate transformers
    如果使用 cuda:
    conda install pytorch cudatoolkit=10.0 -c pytorch
    其他:
    conda install pytorch cpuonly -c pytorch
    conda install -c anaconda scipy
    conda install -c anaconda scikit-learn
    pip install transformers
    pip install tensorboardx
  3. 安装简单变压器

使用

快速浏览一下如何在 Yelp 评论数据集上使用这个库。

  1. 下载 Yelp 评论数据集
  2. 提取train.csvtest.csv并放入目录data/中。

(Bash 用户可以使用 这个脚本 来下载数据集)

这里没有什么特别的,我们只是以正确的形式得到数据。对于任何数据集,这都是您必须做的。

  • 为训练和评估部分创建两个熊猫DataFrame对象。
  • 每个DataFrame应该有两列。第一列包含您想要训练或评估的文本,数据类型为str。第二列有相应的标签,数据类型为int
    更新:现在建议将列命名为 *labels* *text* 而不是依赖于列的顺序。

数据整理好了,就该训练和评估模型了。

就是这样!

为了对其他文本进行预测,TransformerModel附带了一个predict(to_predict)方法,它给出了一个文本列表,返回模型预测和原始模型输出。

有关所有可用方法的更多详细信息,请参见 Github repo 。repo 还包含一个使用该库的最小示例。

默认设置以及如何更改它们

下面给出了使用的默认参数。这些都可以通过将包含相应键/值对的 dict 传递给 TransformerModel 的 init 方法来覆盖。(见下面的例子)

self.args = {
   'model_type':  'roberta',
   'model_name': 'roberta-base',
   'output_dir': 'outputs/',
   'cache_dir': 'cache/', 'fp16': True,
   'fp16_opt_level': 'O1',
   'max_seq_length': 128,
   'train_batch_size': 8,
   'eval_batch_size': 8,
   'gradient_accumulation_steps': 1,
   'num_train_epochs': 1,
   'weight_decay': 0,
   'learning_rate': 4e-5,
   'adam_epsilon': 1e-8,
   'warmup_ratio': 0.06,
   'warmup_steps': 0,
   'max_grad_norm': 1.0, 'logging_steps': 50,
   'evaluate_during_training': False,
   'save_steps': 2000,
   'eval_all_checkpoints': True,
   'use_tensorboard': True, 'overwrite_output_dir': False,
   'reprocess_input_data': False,
}

要覆盖其中任何一个,只需向 TransformerModel 传递一个带有适当的键/值对的字典。

关于每个参数的解释,请参考 Github repo

更新:当前参数见 文档

结论

那都是乡亲们!据我所知,使用变压器模型的最简单方法。

简单变压器——变压器模型的命名实体识别

原文:https://towardsdatascience.com/simple-transformers-named-entity-recognition-with-transformer-models-c04b9242a2a0?source=collection_archive---------7-----------------------

简单的变形金刚是“它只是工作”的变形金刚库。使用 Transformer 模型进行命名实体识别,只需 3 行代码。是的,真的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Brandi Redd on Unsplash

前言

简单变形金刚库是为了使变形金刚模型易于使用而设计的。变形金刚是非常强大的(更不用说巨大的)深度学习模型,在处理各种各样的自然语言处理任务方面取得了巨大的成功。Simple Transformers 使 Transformer 模型的应用程序能够用三行代码完成序列分类任务(最初是二进制分类,但不久后增加了多类分类)。

我很高兴地宣布,Simple Transformers 现在支持命名实体识别,这是另一个常见的 NLP 任务,以及序列分类。

其他功能链接:

简单变形金刚库是在优秀的变形金刚库的基础上,通过抱脸的方式构建的。拥抱脸变形金刚图书馆是为研究人员和其他需要广泛控制事情如何完成的人准备的图书馆。当你需要偏离常规,做不同的事情,或者完全做新的事情时,这也是最好的选择。简单的变形金刚简单多了。

介绍

你想尝试这个绝妙的想法,你想卷起袖子开始工作,但是成千上万行看起来神秘(但很酷)的代码甚至会让一个资深的 NLP 研究员感到害怕。简单变形金刚背后的核心思想是,使用变形金刚并不需要很困难(或令人沮丧)。

简单的转换器抽象出所有复杂的设置代码,同时尽可能保留灵活性和配置空间。Transformer 模型只需要三行代码,一行用于初始化,一行用于训练,一行用于评估。

这篇文章演示了如何使用简单的变压器执行 NER。

所有源代码可在Github Repo上获得。如果您有任何问题或疑问,这是解决它们的地方。请务必检查一下!

装置

  1. 这里安装 Anaconda 或 Miniconda 包管理器
  2. 创建新的虚拟环境并安装所需的软件包。
    conda create -n transformers python pandas tqdm
    conda activate transformers
    如果使用 cuda:
    conda install pytorch cudatoolkit=10.0 -c pytorch
    其他:
    conda install pytorch cpuonly -c pytorch
    conda install -c anaconda scipy
    conda install -c anaconda scikit-learn
    pip install transformers
    pip install tensorboardx pip install seqeval
  3. 安装简单变压器
    pip install simpletransformers

使用

为了演示命名实体识别,我们将使用 CoNLL 数据集。获得这个数据集可能有点棘手,但我在 Kaggle 上找到了一个版本,它可以满足我们的目的。

数据准备

  1. Kaggle 下载数据集。
  2. 将文本文件解压到data/目录。(它应该包含 3 个文本文件train.txt, valid.txt, test.txt。我们将使用traintest文件。您可以使用valid文件来执行超参数调整,以提高模型性能。

简单变形金刚的 NER 模型既可以使用 *.txt* 文件,也可以使用熊猫 *DataFrames* 。关于 *DataFrames* 的使用示例,请参考 回购 单据中的 NER 最小启动示例。

使用自己的数据集时,输入文本文件应该遵循 CoNLL 格式。文件中的每一行都应该包含一个单词及其相关的标记,每个标记之间用一个空格隔开。简单的转换器假定一行中的第一个“单词”是实际的单词,一行中的最后一个“单词”是它的指定标签。为了表示一个新的句子,在前一个句子的最后一个单词和下一个句子的第一个单词之间添加一个空行。然而,在使用定制数据集时,使用DataFrame方法可能更容易。

神经模型

我们创建了一个NERModel,可用于 NER 任务中的训练、评估和预测。一个NERModel对象的完整参数列表如下。

  • model_type:型号类型(伯特、罗伯塔)
  • model_name:默认的变压器模型名称或包含变压器模型文件的目录路径(pytorch_nodel.bin)。
  • labels(可选):所有命名实体标签的列表。如果没有给出,将使用[“O “,” B-MISC “,” I-MISC “,” B-PER “,” I-PER “,” B-ORG “,” I-ORG “,” B-LOC “,” I-LOC”]。
  • args(可选):如果未提供此参数,将使用默认参数。如果提供的话,它应该是一个包含应该在默认参数中更改的参数的字典。
  • use_cuda(可选):如果可用,使用 GPU。设置为 False 将强制模型仅使用 CPU。

要加载一个先前保存的模型而不是默认模型,您可以将model_name 更改为包含已保存模型的目录路径。

model = NERModel(‘bert’, ‘path_to_model/’)

一个NERModel包含一个 python 字典args,它有许多属性提供对超参数的控制。在回购文件中提供了每一个的详细描述。默认值如下所示。

当创建一个NERModel或调用它的train_model方法时,只要传入一个包含要更新的键值对的dict就可以修改这些属性。下面给出一个例子。

训练模型

正如承诺的那样,训练可以在一行代码中完成。

train_model方法将在每第 n 步创建一个模型的检查点(保存),其中 n 是self.args['save_steps']。训练完成后,最终模型将保存到self.args['output_dir']

加载保存的模型如下所示。

评估模型

同样,评估只是一行代码。

这里,三个返回值是:

  • result:包含评估结果的字典。(eval_loss,precision,recall,f1_score)
  • model_outputs:原始模型输出列表
  • preds_list:预测标签列表

这里给出我得到的评测结果,供参考。

{'eval_loss': 0.10684790916955669, 'precision': 0.9023580786026201, 'recall': 0.9153082919914954, 'f1_score': 0.9087870525112148}

对于使用默认超参数值的单次运行来说,还不算太差!

把所有的放在一起

预测和测试

在实际应用中,我们通常不知道真正的标签应该是什么。要对任意示例执行预测,可以使用predict方法。这个方法与eval_model方法非常相似,除了它接受一个文本列表并返回一个预测列表和一个模型输出列表。

predictions, raw_outputs = model.predict(["Some arbitary sentence"])

包扎

Simple Transformers 提供了一种快速简单的方法来执行命名实体识别(以及其他令牌级分类任务)。借用伯特背后的人的一句台词,简单变形金刚“概念简单,经验丰富”。

用任何分类器训练有序回归的简单技巧

原文:https://towardsdatascience.com/simple-trick-to-train-an-ordinal-regression-with-any-classifier-6911183d2a3c?source=collection_archive---------5-----------------------

在这篇文章中,我将展示一个简单的方法来处理任何序数回归(序数分类)问题,使用任何现有的二进制分类算法,该方法是由 Eibe Frank 和 Mark Hal 开发的。

原始论文
(Eibe Frank 和 Mark Hal,lECML 2001。第 12 届欧洲会议)https://www . cs . waikato . AC . NZ/~ eibe/pubs/ordinal _ tech _ report . pdf

机器学习的实际应用有时涉及目标值在不同类别之间显示顺序的情况。然而,标准分类算法不能利用这种排序信息,因为它们将每个类属性视为一组无序值[1]。

本文介绍了一个简单的技巧,它能使任何标准分类算法利用类属性中的排序信息。该论文还表明,这个简单的技巧优于天真的分类方法,天真的分类方法将每个类视为一组无序的值。

问题定义

(维基百科)在统计中,有序回归(也称为有序分类)是回归分析的一种,用于预测有序变量,即一个变量的值存在于任意尺度上,其中只有不同值之间的相对顺序是有意义的。

有序回归问题的一些例子是预测人类偏好(强烈不同意到强烈同意),预测温度(热、温和、冷),预测书/电影评级(1 到 5)。

一些可能的方法

解决序数回归问题的一些简单而天真的方法是

  1. 将其视为回归问题
    如果序数值表示间隔或比率,并且我们有原始间隔/比率值,我们可以将其视为回归问题
    我们将回归算法拟合到相应的间隔/比率值,该值可以映射到实际的序数值
    缺点:如果序数值不表示任何连续的间隔/比率(如书籍/电影评级),或者如果我们没有原始间隔/比率值,我们就不能使用这种方法。
  2. 将其视为标准分类问题
    我们将每个序数值视为一个无序集,并在其上安装一个多类分类算法
    缺点:丢失每个类的排序信息,因为标准分类算法将每个类视为一组无序值

提议的方法

只要我们使用能够估计输出类别概率的分类器,所提出的方法将会工作

我们可以通过将一个 k 类有序回归问题转化为一个 k-1 二进制分类问题来利用有序类值,我们将带有有序值 V1、V2、V3、… Vk 的有序属性 A转化为 k-1 个二进制属性,每个属性对应于原始属性的前 k-1 个值。第 I 个二元属性表示测试 A > Vi [1]

例如,如果我们有一个具有从 1 到 5 顺序值电影评级的预测目标,我们可以将其转换成 4 个二进制分类问题,使得

  1. 如果等级> 1,二元目标为 1,因此分类器将预测 Pr(目标> 1)
  2. 如果等级> 2,二元目标为 1,因此分类器将预测 Pr(目标> 2)
  3. 如果等级> 4,二元目标为 1,因此分类器将预测 Pr(目标> 3)
  4. 如果等级> 4,二元目标为 1,因此分类器将预测 Pr(目标> 4)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example of the transformation to binary classification problem is done

在我们训练了 4 个二元分类器之后,我们可以使用它来预测序数值的概率,方法是:

Pr(y=1) = 1-Pr(目标> 1)
Pr(y=2) = Pr(目标> 1)-P(目标> 2)
Pr(y=3) = Pr(目标> 2)-P(目标> 3)
Pr(y=4) = Pr(目标> 3)-P(目标> 4)
Pr(y=5) = Pr(目标【T6

或者一般来说,对于第一个序数值,我们可以使用第一个分类器来预测V1**=1—Pr(y>V1) 的概率,我们可以使用最后一个分类器来预测
Vk
= Pr(Target>Vk-1)
的概率,我们可以使用中间分类器来预测
Vi 的概率

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这样我们就不会丢失来自类标签的排序信息。

Python 实现

我们通过创建OrdinalClassifier类来实现上述技巧,当调用fit时,该类将训练 k-1 个二元分类器,并且如果调用predict,将返回预测的类。在训练(fit)阶段OrdinalClassifier会将每个训练好的二进制分类器存储到一个 python 字典中。

定义我们的 OrdinalClassifier 的参数是
clf: 任何在其中实现predict_proba方法的 sklearn 分类器

举例来说,使用 max_depth = 3 的决策树创建一个 OrdinalClassifier 应该是:

clf = OrdinalClassifier(DecisionTreeClassifier(max_depth=3))

python 中实现的顺序分类器示例:

  1. init: 构造函数,简单地定义我们的OrdinalClassifier并初始化clfs作为一个字典,它将用于存储我们的 k-1 二进制分类器
  2. 拟合:首先我们存储每个可用的唯一标签,然后对于第一个 k-1 值,对于每次迭代,我们将其标签转换为表示测试 A* > Vi binary_y = (y > self.unique_class[i].astype(np.uint8))的二进制标签,然后我们在转换后的标签上拟合一个新的分类器(binary_y)最后,将我们的分类器存储到以i为关键字的clfs字典中
  3. predict_proba :要获得每个类的预测概率:首先我们从存储在clfs上的所有分类器中获得所有的预测概率,然后简单地枚举所有可能的类标签并将其预测添加到我们的predicted列表中,之后,将其作为 numpy 数组返回
  4. 预测:要获得预测的类,只需使用我们predict_probaargmax

结论

我们可以通过使用一个简单的技巧来解决一个序数分类问题,即把序数分类分成 k-1 个二进制分类

参考

[1]艾贝·弗兰克和马克·霍尔,序数分类法的一种简单方法(2001),2001 年。第 12 届欧洲会议

蒸馏伯特的简单教程

原文:https://towardsdatascience.com/simple-tutorial-for-distilling-bert-99883894e90a?source=collection_archive---------10-----------------------

基于 BERT 知识构建特定任务模型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Iker Urteaga on Unsplash

**2019 年 12 月 4 日—更新:**这种方法的实验代码可在这里获得。

关于伯特

伯特和变形金刚,总的来说,是 NLP 的一个全新步骤。它是由谷歌在 2018 年推出的,自那以来,它在不同的语言理解任务中表现出了最先进的结果。在https://papers with code . com/paper/Bert-pre-training-of-deep-bidirectional查看他们的论文和结果。

但是有一点美中不足。在生产中很难使用 BERT。 BERT-base 包含 110M 参数。较大的变型 BERT-large 包含 340M 参数。这样大的神经网络在实践中是有问题的。由于大量的参数,在移动设备等资源受限的系统中部署 BERT 非常困难。此外,低推理时间使其在实时系统中无用。这就是为什么找到让它更快的方法如此重要。

当我第一次面对变形金刚时,尝试用它们来完成日常任务是非常诱人的。文本分类就是其中之一。但是如何克服我上面写的局限性呢?在这篇文章中,我想展示一种简单而有效的方法来训练一个特定于任务的分类模型,该模型与基于 BERT 的模型在同一水平上执行。

知识的升华

有几种可能的方法可以加速 BERT。我强烈推荐阅读加速 BERT,其中包含了完整的概述。蒸馏就是其中之一。

里奇·卡鲁阿纳和他的同事描述了知识的升华。想法很简单:训练一个小的“学生”模型,模仿“教师”模型的行为。

样本问题

假设我们有一个常规的二进制文本分类问题。为了简单起见,X是句子列表,y是标签列表(0 或 1)。额外的细节对于描述主旨并不重要。

训练伯特

我就不描述微调 BERT 的全过程了:参考本帖详细了解这个过程。让我们想象一下,我们已经用来自变形金刚库num_labels=2训练了BertForSequenceClassification。这个模型将是我们想要将其知识转移到“学生”模型的“老师”。

让我们构建“学生”模型

首先,我们将训练一个小型的 BiLSTM 模型作为基线。

输入数据是词汇表中的单词索引。为了构建词汇表,我使用了torchtext包中的内置功能。这些函数将帮助我们将训练数据集中的单词翻译成单词索引。

为了简单起见,我没有使用任何预先训练的单词嵌入。我们的模型将在训练过程中学习投射到内部空间。

模型

我们的模型看起来像:

列车基线

对于这个特定的基线模型,我们设置output_dim=1,因为我们有一个二元分类,因此损失函数是 logloss。PyTorch 有BCEWithLogitsLoss类,它结合了 sigmoid 函数和二元交叉熵:

一个纪元是:

每个时期后的评估:

使用一些辅助函数进行培训的完整代码如下:

蒸馏

这个特别的想法最初来自于论文“ 从 BERT 中提取特定于任务的知识到简单的神经网络 ”。

我们的“学生”模型必须学会模仿 BERT 模型的行为。但什么是“行为”?在我们的例子中,它是训练数据集的输出y_bert。主要思想是使用原始预测,即最终激活函数之前的预测,通常是 softmax 或 sigmoid。假设通过使用原始值,模型可以比使用“硬”预测更好地学习内部表示。Softmax 将这些值归一化为 1,同时保持最大值较高,并将其他值减小到非常接近零的值。零中的信息很少,所以通过使用原始预测,我们也可以从非预测类中学习。

为了学习“行为”,我们通过在传统的交叉熵损失(L_ce)上增加一个额外的项 L _ distill 来修改损失函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 L _ distill 是学生网络的逻辑值与教师的逻辑值之间的均方误差(MSE)损失:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 z(B)和 z(S)分别是教师和学生的逻辑。

我们几乎完全重用了代码,只做了一处修改——损失函数。为了计算交叉熵损失,我使用了CrossEntropyLoss,它结合了 softmax 函数和交叉熵。

为了正确计算损失函数,我们还将输出数量从 1 改为 2。完整的代码应该是:

仅此而已。我们将知识从伯特模型转移到一个更简单的模型。

结果

在我的工作中,我尝试用这种方法来解决二元分类问题。它有高度不平衡的类,因此关键度量是平均精度分数。该模型的比较如下表所示。有趣的是,经过提炼的版本甚至比基于 BERT 的模型具有更好的平均精度分数。在我看来,这个事实是进一步研究的一个很好的切入点。

结论

这是知识升华的一个非常基本的方法。具体的浅层网络的结构和超参数将取决于您的特定任务。在我看来,在现实生活实践中还是挺有用的。它在训练时有些复杂,但是您可以得到一个更好的模型,同时在执行时保持其原始的简单性。

将机器学习模型部署到云的简单方法

原文:https://towardsdatascience.com/simple-way-to-deploy-machine-learning-models-to-cloud-fd58b771fdcf?source=collection_archive---------2-----------------------

使用简单的技术堆栈将您的第一个 ML 模型部署到生产环境中

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Randy Fath on Unsplash

机器学习领域目前看到数据科学家(DS)扮演以下两个突出角色中的一个或两个:

  1. 其中,DS 接收数据转储,对数据应用某种机器学习算法,并以某种演示或报告的形式报告结果。
  2. 其中 DS 为利益相关者创建一个可用的软件来使用机器学习模型。

在这篇博文中,我试图展示一个 DS 工作的第二个方面的示例方法,即创建一些可以被利益相关者使用的软件。具体来说,我们将创建一个 web 服务,可以通过查询从机器学习模型中获得预测。这篇文章主要是为那些想超越仅仅开发模型的机器学习实践者准备的。

Tech-stack : Python、 FlaskDockerAWS ec2

工作流程可以分为以下几个基本步骤:

  1. 在本地系统上训练机器学习模型。
  2. 将推理逻辑包装到 flask 应用程序中。
  3. 使用 docker 将 flask 应用程序容器化。
  4. 在 AWS ec2 实例上托管 docker 容器并使用 web 服务。

免责声明:这里展示的系统与商业生产系统的样子相差甚远。这篇博文的关键点应该是开发工作流程,熟悉技术栈,并初步体验构建 ML 生产系统。

让我们从第一步开始。

在本地系统上训练机器学习模型

我们需要一些可以包装在网络服务中的机器学习模型。出于演示的目的,我选择了一个逻辑回归模型来对 iris 数据集进行多类分类(是的,非常简单!# LazinessFTW)。使用 python 3.6 在本地系统上训练该模型。

使用熟悉的 scikit-learn,可以快速训练上述模型。关于模型开发,请参考本博客 github 报告中的笔记本“Model_training.ipynb”。我只想强调模型开发的两个重要方面:

  1. 训练后生成的模型文件存储为 pickle 文件,这是一种用于存储对象的序列化格式。(在回购中,该文件被命名为“iris_trained_model.pkl”)
  2. 推理调用(。predict())调用需要 numpy 数组形式的每个测试样本 4 个特征。

将推理逻辑包装到 flask web 服务中

现在我们已经有了训练好的模型文件,我们准备好查询模型来获得一个测试样本的类标签。推断非常简单,只需用测试数据对训练好的模型调用 predict()函数。然而,我们希望将推理构建为一个 web 服务。为此,我们将使用烧瓶。

Flask 是一个强大的 python microwebserver 框架,它允许我们以最少的配置麻烦快速构建基于 REST API 的 web 服务。让我们深入研究代码:

a.首先,让我们定义一个简单的函数来加载训练好的模型文件。

这里,我们定义了一个名为“model”的全局变量,并将其填充到 load_model()函数中。使用全局变量的目的很快就会变得清楚。

b.接下来,我们实例化一个名为“app”的 Flask 对象:

c.现在,我们定义一个 home 端点,当点击它时,返回一个“Hello World!”消息。

注意 app.route decorator 的使用。

d.现在,我们定义一个“预测”端点。端点接受“POST”请求,其中我们希望得到预测的测试数据由端点接收。简单地说,该函数仅在需要预测单个测试样本时才起作用(如果在对端点的单次调用中需要预测多个样本,则该函数不起作用)。

请注意通过“模型”变量对预测函数的直接调用。

e.最后,声明主函数:

在这里,对 load_model()函数的调用确保了变量“model”由经过训练的模型属性填充(因此需要一个全局模型变量)。因此,没有必要在每次调用预测端点时重复加载模型。这使得网络服务变得快速。响应以字符串的形式返回,该字符串是预测的类标签。

完整的烧瓶特定代码如下:

此时,web 服务就可以在本地运行了。我们来测试一下。

从终端执行命令python app.py。进入浏览器,点击网址0.0.0.0:80,显示一条信息Hello World!。这对应于归属端点返回消息。

注意:此时可能会收到权限错误。在这种情况下,在app.pyapp.run()命令中将端口号更改为 5000。(端口 80 是一个特权端口,所以将其更改为某个非特权端口,例如:5000)

接下来,让我们在终端上使用下面的 curl post 请求,测试我们是否可以使用这个 web 服务获得预测:

curl -X POST \
   0.0.0.0:80/predict \
   -H 'Content-Type: application/json' \
   -d '[5.9,3.0,5.1,1.8]'

curl 请求向我们的 web 服务器发送一个测试样本[5.9,3.0,5.1,1.8],并返回一个类标签。

使用 docker 将 flask 服务容器化

到目前为止,我们有一个本地运行的 web 服务。我们的最终目的是能够在云虚拟机上运行这段代码。

在软件开发领域,一个开发人员给出了一个著名的理由,他的代码被测试人员破解了:'但是它在我的机器上工作了!’。这里描述的问题通常可以归因于缺乏在不同机器上运行软件的一致环境。理想情况下,我们的代码本身应该独立于运行它的底层机器/操作系统。容器化允许开发人员提供这样的隔离。

它在这里有多重要?

我们的目的是在云虚拟机上运行我们的 web 服务。云虚拟机本身可以运行任何操作系统。我们网络服务器的容器化使我们避免了遇到环境相关问题的麻烦。如果容器化的代码能在一台机器上运行,那么不管这台机器的特性如何,它肯定能在另一台机器上运行。在这一点上,Docker 是最著名的容器化技术,我们将在这里使用同样的技术。关于 docker 的快速教程,请查看这个链接

让我们深入了解 docker 文件,它包含一组 docker 守护进程构建 docker 映像的指令。

我们从 python dockerhub repo 中提取基本 docker 映像,在其上执行我们的特定构建指令。复制命令只是从当前文件夹中取出特定的文件,并将它们复制到我们试图构建的 docker 映像中名为“deploy”的文件夹中。除了 app.py 和模型文件之外,我们还需要一个需求文件,其中列出了我们用来运行代码的 python 包的特定版本。WORKDIR 命令将工作目录更改为映像中的“deploy/”。然后,我们发出一个运行命令,使用需求文件安装特定的 python 包。EXPOSE 命令使外部世界可以访问端口 80(我们的 flask 服务运行在端口 80 上;我们需要容器内部的这个端口在容器外部是可访问的)。

发出 build 命令,以 docker 映像结束:

docker build -t app-iris .

(不要忘记命令末尾的句号)。

使用命令“docker images”查看创建了名为“app-iris”的 docker 存储库的 docker 映像。(还将看到另一个名为 python 的存储库,因为它是我们构建自定义映像的基础映像。)

现在,映像已经构建好,可以运行了。我们可以使用以下命令来实现这一点:

docker run -p 80:80 app-iris .

上述命令使用-p 标志将本地系统的端口 80 映射到 docker 容器的端口 80,以便将本地 HTTP 端口 80 上的流量重定向到容器的端口 80。(如果您使用本地端口 5000 而不是端口 80,请将命令的端口映射部分更改为 5000:80)。

让我们通过在应该显示“Hello World!”的浏览器上点击 URL: http://0.0.0.0:80 来测试这是否可行这是本地端点输出消息(如果使用端口 5000,请在 url 中将 http 端口修改为 5000)。此外,使用前面提到的 curl 请求来检查是否返回了预测的类标签。

在 AWS ec2 实例上托管 docker 容器

我们已经有了一个在本地系统上运行的容器化应用程序。现在,如果其他人希望使用该服务呢?如果我们需要围绕需要可用、自动化和可伸缩的服务构建一个架构生态系统,会发生什么?显而易见,让 web 服务在本地运行是一个非常糟糕的主意。因此,我们希望在互联网上的某个地方托管 web 服务,以满足我们列出的要求。对于这个博客,我们选择在一个 AWS ec2 实例上托管我们的服务。

作为先决条件,需要有一个 AWS 帐户才能使用 ec2 实例。对于新用户,有几个 AWS 资源可以免费使用 1 年(通常有一定的限制)。在这篇博客中,我将使用一个符合自由层条件的’ t2.micro ’ ec2 实例类型。对于已经用完 AWS 免费层的用户来说,在写这篇博客的时候,这个实例的费用大约是每小时 1 美分;一笔可以忽略不计的费用。

先说流程。

登录 AWS 管理控制台,在搜索栏中搜索 ec2 以导航到 EC2 仪表板。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Search for ec2 on the aws management console

寻找下面的窗格,选择“密钥对”并创建一个。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Select Key Pairs for looking at existing key pairs and creating new ones

这将下载一个。pem '文件,这是密钥。将此文件安全地保存在某个地方。现在,导航到系统上该文件的位置,发出下面的命令,用您的密钥文件名替换它:

chmod 400 key-file-name.pem

该命令将您的密钥对文件的权限更改为私有。稍后将解释密钥对的使用。

接下来,单击 EC2 仪表板上的“启动实例”:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Launch ec2 instance

从选项列表中选择 Amazon 机器实例(AMI)。AMI 决定了 VM 将要运行的操作系统(以及其他一些我们现在不关心的东西)。对于这篇博客,我选择了默认选择“Amazon Linux 2 AMI”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Choosing AMI

下一个屏幕允许您选择实例类型。这是可以选择虚拟机硬件部分的地方。如前所述,我们将使用“t2.micro”实例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Selecting instance type

您可以选择“查看并启动”,进入“第 7 步:查看实例启动”屏幕。在这里,您需要单击“编辑安全组”链接:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Security Groups

现在,您必须修改安全组,以允许外部世界访问您的实例的端口 80 上的 HTTP 流量。这可以通过创建规则来实现。最后,您应该会看到这样一个屏幕:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Adding HTTP rule to security group

如果没有这条规则,您的 web 服务将永远无法到达。有关安全组和配置的更多信息,请参考 AWS 文档。点击“启动”图标会弹出一个窗口,要求确认是否有密钥对。使用之前生成的密钥对的名称,并启动虚拟机。

您将被重定向到启动屏幕:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Launch Status of ec2 instance

使用“查看实例”按钮导航至显示正在启动的 ec2 实例的屏幕。当实例状态变为“正在运行”时,它就可以使用了。

现在,我们将使用命令从本地系统终端 ssh 到 ec2 机器,该命令的 public-dns-name 字段替换为您的 ec2 实例名(格式:【ec2–x–x–x–x.compute-1.amazonaws.com】和您之前保存的密钥对 pem 文件的路径)。

ssh -i /path/my-key-pair.pem [ec2-user@](mailto:ec2-user@ec2-198-51-100-1.compute-1.amazonaws.com)public-dns-name

这将使我们进入实例的提示,我们将首先安装 docker。这是我们的工作流所需要的,因为我们将在 ec2 实例中构建 docker 映像(对于这一步,有更好但稍微复杂的替代方法)。对于我们选择的 AMI,可以使用以下命令:

**sudo amazon-linux-extras install docker
sudo yum install docker
sudo service docker start
sudo usermod -a -G docker ec2-user**

有关命令的解释,请查看文档

使用“exit”命令注销 ec2 实例,然后使用 ssh 命令再次登录。通过发出“docker info”命令检查 docker 是否工作。再次注销或打开另一个终端窗口。

现在让我们复制在 ec2 实例中构建 docker 映像所需的文件。从本地终端发出命令(不是从 ec2 内部):

scp -i /path/my-key-pair.pem file-to-copy [ec2-user@](mailto:ec2-user@ec2-52-59-206-245.eu-central-1.compute.amazonaws.com)public-dns-name:/home/ec2-user

我们需要复制 requirements.txt、app.py、经过训练的模型文件和 Dockerfile 来构建 docker 映像,就像前面所做的那样。重新登录到 ec2 实例,发出’ ls '命令,查看复制的文件是否存在。接下来,使用本地系统中使用的完全相同的命令构建并运行 docker 映像(这次在代码/命令中的所有位置使用端口 80)。

使用公共 dns 名称从您的浏览器点击家庭端点,以查看熟悉的’ Hello World!'消息:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Home endpoint works from the browser (I used my ec2 public-dns-name in the address bar)

现在,在用您的名称替换 public-dns-name 之后,用您的测试样本数据从本地终端向您的 web 服务发送一个 curl 请求:

curl -X POST \
public-dns-name:80/predict \
-H 'Content-Type: application/json' \
-d '[5.9,3.0,5.1,1.8]'

这将使您得到与本地相同的预测类标签。

你就大功告成了!现在,您可以将这个 curl 请求分享给任何希望使用您的测试样本的人。

当您不再需要 web 服务时,不要忘记停止或终止 ec2 实例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Stop or terminate the ec2 instance to avoid getting charged

一些附加的想法

这是一个超级基本的工作流程,为渴望超越模型开发的 ML 从业者而设计。大量的事情需要被改变,以使这个系统成为一个更适合真实生产系统的系统。一些建议(远未完成):

  1. 在 flask 应用程序中使用 Web 服务器网关接口(WSGI ),如 gunicorn。使用 nginx 反向代理和异步工人的加分。
  2. 提高 ec2 实例的安全性:该服务目前对全世界开放。建议:限制对一组 IP 的访问。
  3. 为应用程序编写测试用例:未经测试的软件=朝自己的腿开枪,然后把自己扔进一个装满饥饿狮子的笼子,同时被扔石头。(寓意:在没有彻底测试之前,不要发布产品软件)

上面的列表中还可以添加更多的内容,但也许这是另一篇博文的内容。

Github 回购:【https://github.com/tanujjain/deploy-ml-model

如果能听到您的反馈,那就太好了!

改进 Matplotlib 的简单方法

原文:https://towardsdatascience.com/simple-ways-to-improve-your-matplotlib-b64eebccfd5?source=collection_archive---------4-----------------------

Matplotlib 的默认属性经常产生不吸引人的图。这里有几个简单的方法来美化你的形象。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Alice Bartlett. Cropped and resized by author.

Matplotlib 通常是 Python 程序员学习的第一个数据可视化包。虽然它的用户可以用几行代码创建基本的图形,但这些默认的图形在设计美学和交流能力方面往往是不够的。然而,简单的调整可以带来巨大的改进,在这篇文章中,我将分享一些关于如何升级 Matplotlib 图形的技巧。

在接下来的例子中,我将使用在这个关于谷物的 Kaggle 数据集中找到的信息。我通过食用量标准化了三个特征(卡路里、脂肪和糖),以便更好地比较谷物营养和评级。关于这些数据转换的细节和用于生成每个示例图的代码可以在我的 GitHub 上找到。

移除脊椎

默认要更新的第一个 Matplotlib 是每个图周围的黑框,由四个所谓的“脊骨”组成为了调整它们,我们首先通过 pyplot 获得我们的图形的轴,然后根据需要改变每个单独脊椎的可见性。

比方说,我们想要删除顶部和右侧的脊椎。如果我们导入了 Matplotlib 的 pyplot 子模块:

from matplotlib import pyplot as plt

我们只需要在代码中添加以下内容:

plt**.**gca()**.**spines['top']**.**set_visible(False)
plt**.**gca()**.**spines['right']**.**set_visible(False)

顶部和右侧的脊柱将不再出现。移除这些分散注意力的线条可以将更多的注意力放在你的数据上。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Removing distracting spines can help people focus on your data.

探索颜色选项

Matplotlib 的默认颜色刚刚得到升级,但是你仍然可以很容易地改变它们,使你的图更有吸引力,甚至反映你公司的品牌颜色。

十六进制代码

我最喜欢的更新 Matplotlib 颜色的方法之一是直接将十六进制代码传递给颜色参数,因为它允许我非常具体地选择颜色。

plt**.**scatter(**...**, color**=**'#0000CC')

这个方便的工具可以帮助你选择一个合适的十六进制颜色,通过测试它与白色和黑色文本,以及比较几个较亮和较暗的阴影。或者,在选择调色板时,你可以采取更科学的方法,看看布朗可视化研究实验室的康纳·格拉马齐奥的色彩学。Colorgorical 工具允许您通过平衡各种偏好(如人类感知差异和审美愉悦)来构建调色板。

xkcd 颜色

xkcd 颜色库提供了另一种更新 Matplotlib 默认颜色的好方法。这 954 种颜色是由 xkcd 颜色名称调查的几十万参与者特别策划和命名的。您可以在 Matplotlib 中使用它们,方法是在它们的名称前加上“xkcd:”前缀。

plt**.**scatter(**...**, color**=**'xkcd:lightish blue')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Matplotlib’s default colors can easily be updated by passing hex codes or referencing the xkcd library.

图层图形对象

Matplotlib 允许用户将多个图形层层叠加,这在比较结果或设置基线时非常方便。在分层的时候应该利用两个有用的属性:1) alpha用于控制每个组件的不透明度,2) zorder用于将对象移动到前景或背景。

不透明

Matplotlib 中的 alpha 属性调整对象的不透明度。该值的范围从 0 到 1,其中 0 表示完全透明(不可见👀)和一个完全不透明的。减少 alpha 将使您的绘图对象透明,允许同时看到多个层,并允许区分重叠点,比如在散点图中。

plt**.**scatter(**...**, alpha**=**0.5)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Decreasing alpha reduces opacity and can help you visualize overlapping points.

命令

Matplotlib 的 zorder 属性决定了对象与前景的距离。具有较小 zorder 值的对象看起来更靠近背景,而具有较大 z order 值的对象更靠近前面。例如,如果我正在制作一个散点图和一个伴随的线图,我可以通过增加它的 zorder 来使线前移。

plt**.**scatter(**...**, zorder**=**1)  *#background*
plt**.**plot(**...**, zorder**=**2)     *#foreground*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Plot objects can be brought to the foreground or pushed to the background by adjusting zorder.

For more tips just like these, check out my full Matplotlib Tips playlist on YouTube.

注释要点或例子

许多视觉效果可以从主要观点的注释或具体的、说明性的例子中受益,因为这些直接传达了想法并提高了结果的有效性。要向 Matplotlib 图形添加文本,只需包含指定所需文本及其位置的注释代码。

plt**.**annotate(TEXT, (X_POSITION, Y_POSITION), **...**)

用来制作这个博客视觉效果的谷物数据集包含了几种品牌谷物的营养信息,以及一个标记为“评级”的特征人们可能首先认为“评级”是一个表明消费者偏好的谷物的分数。然而,在上面的 zorder 图中,我建立了一个快速线性回归模型,表明每杯卡路里和评级之间的相关性实际上不存在。卡路里似乎不可能不成为消费者偏好的因素,所以我们可能已经对我们最初关于“评级”的假设产生了怀疑。

当检查极端情况时,这种误解变得更加明显:Cap’n Crunch 是评级最低的谷物,而全麸额外纤维评级最高。用这些有代表性的例子来注释这个图,立刻消除了关于“评级”的错误假设这种评级信息更有可能表明谷物的营养价值。(我也标注过每杯热量最多的麦片;葡萄坚果不太可能被大量食用!😆)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Annotating your visuals with a few examples can improve communication and add legitimacy.

基线和突出显示

给你的视觉效果添加基线有助于设定期望值。一条简单的水平线或垂直线为其他人提供了适当的背景,通常会加速他们对你的结果的理解。同时,突出感兴趣的特定区域可以进一步强调你的结论,也有助于与你的听众交流。Matplotlib 为基线和突出显示提供了几个选项,包括水平线和垂直线、矩形等形状、水平和垂直跨度阴影以及两条线之间的填充。

水平线和垂直线

现在让我们考虑一下谷物数据集中脂肪和糖之间的相互作用。起初,这种关系的基本散点图似乎并不有趣,但在进一步探索后,我们发现每杯谷物的脂肪中位数仅为 1 克,因为许多谷物根本不含脂肪。添加这条基线有助于人们更快地得出这一发现。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A horizontal or vertical baseline can help set the stage for your data.

在其他情况下,您可能希望完全删除 Matplotlib 提供的默认 x 轴和 y 轴,并基于一些数据集合创建自己的轴。这个过程需要三个关键步骤:1)删除所有默认的脊线,2)删除刻度线,3)添加新的轴作为水平线和垂直线。

*#1\. Remove spines*
for spine in plt.gca().spines.values():
    spine.set_visible(False)*#2\. Remove ticks*
plt.xticks([])
plt.yticks([])*#3\. Add horizontal and vertical lines*
plt.axhline(Y_POSITION, ...)  *#horizontal line*
plt.axvline(X_POSITION, ...)  *#vertical line*

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

You can also create new axes for your data by removing spines and ticks and adding custom lines.

矩形

既然我们已经把谷物的脂肪和糖含量标绘在新的坐标轴上,看来很少有谷物是低糖高脂肪的。也就是说,左上象限几乎是空的。这似乎是合理的,因为谷物通常不好吃。为了使这一点非常清楚,我们可以通过在它周围画一个矩形并加以注释,将注意力引向这个低糖、高脂肪的区域。Matplotlib 通过其补丁模块提供了对几种形状的访问,包括一个矩形甚至一个海豚。首先导入矩形的代码:

from matplotlib.patches import Rectangle

然后,要在图形上创建一个矩形,请抓取当前轴,并添加一个矩形补片及其位置、宽度和高度:

plt**.**gca()**.**add_patch(Rectangle((X_POSITION, Y_POSITION), 
                              WIDTH, HEIGHT, **...**)

这里,x 和 y 位置指的是矩形左下角的位置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

To direct people toward a particular part of your visual, consider adding a rectangle.

明暗法

阴影提供了另一种选择,用于将注意力吸引到图形的特定区域,有几种方法可以使用 Matplotlib 添加阴影。

如果您打算突出显示整个水平或垂直区域,只需在视觉效果中添加一个跨度:

plt**.**axhspan(Y_START, Y_END, **...**)  *#horizontal shading*
plt**.**axvspan(X_START, X_END, **...**)  *#vertical shading*

之前讨论过的属性像alphazorder在这里很关键,因为你可能想要让你的阴影透明和/或把它移到背景。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Shading also provides an effective way to highlight a particular region of your plot.

但是,如果您想要着色的区域遵循更复杂的逻辑,您可以在两条用户定义的线之间使用着色。这种方法需要一组 x 值,第一行和第二行的两组 y 值,以及一个可选的where参数,该参数允许您使用逻辑过滤到您感兴趣的区域。

plt**.**gca()**.**fill_between(X_VALUES, Y_LINE1, Y_LINE2, 
                       WHERE**=**FILTER LOGIC, **...**)

要使之前用矩形突出显示的相同区域变暗,只需为 x 轴定义一个等距糖值数组,在 y 轴上填充中间值和最大脂肪值(高脂肪),并向下过滤小于中间值的糖值(低糖)。

sugars **=** np**.**linspace(df**.**sugars_per_cup**.**min(),       
                     df**.**sugars_per_cup**.**max(), 
                     1000)plt**.**gca()**.**fill_between(sugars, 
                       df**.**fat_per_cup**.**median(), 
                       df**.**fat_per_cup**.**max(), 
                       WHERE**=**sugars **<** df**.**sugars_per_cup**.**median(), 
                       **...**)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

More complex shading logic is accomplished by filling between two lines and applying a filter.

结论

Matplotlib 的名声很差,因为它的缺省值很差,而且需要大量代码来产生看起来不错的视觉效果。希望这篇博客中提供的技巧能帮助你解决第一个问题,尽管我承认最后几个示例图需要很多更新和大量代码。如果所需的大量代码困扰着你,那么 Seaborn 可视化库是 Matplotlib 的一个很好的替代品。它提供了更好的默认设置,需要更少的代码行,并且如果需要的话,支持通过传统的 Matplotlib 语法进行定制。

当您可视化数据时,无论您选择哪个包,都要记住的主要事情是您的受众。我在这里提供的建议旨在通过以下方式平滑数据交流过程:1)删除多余的部分,如不必要的线条或刻度线;2)通过设置分层和基线来更快地讲述数据故事;3)通过阴影和注释突出主要结论。由此带来的美感也有所改善,但主要目标是更强大、更无缝的数据通信。

我最近在 ODSC 纽约 的一次数据可视化演讲中分享了类似的内容。你可以在这里访问我的会议资料以及我的 GitHub上的各个幂例图。**

[1] J.D. Hunter,Matplotlib:2D 图形环境 (2007),科学计算&工程。

[2] C .克劳福德, 80 谷物 (2017),卡格尔。

[3] C.C. Gramazio,D.H .莱德劳和 K.B. Schloss, Colorgorical:为信息可视化创建可区分和优选的调色板 (2017),IEEE 可视化和计算机图形学汇刊。

使用 Python 的 Selenium 进行简单的 Web 抓取

原文:https://towardsdatascience.com/simple-web-scraping-with-pythons-selenium-4cedc52798cd?source=collection_archive---------2-----------------------

沙滩球搜索,从网页到 CSV!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image Courtesy of Shahadat Rahman via Unsplash

使用 Selenium 模块

夏天对我来说意味着两件事,在沙滩上消磨时间和踢足球。随着天气的好转和 2019 年 FIFA 女足世界杯的进行,我现在需要买一个沙滩足球。这似乎是一个很好的机会来展示我们的网络抓取能力,并编写一个简单的网络抓取器来收集来自沃尔玛的沙滩球数据。

这篇文章旨在介绍如何使用 Selenium 模块进行网页抓取。此外,增加一个额外的挑战,让我们收集数据,不只是从一个网页,而是许多!为了便于数据解释,我将把输出写到一个 CSV 文件中。

我们开始吧!

首先,我们需要安装一个 Webdriver,我们将使用 Selenium 模块通过 Python 来控制它。我们将在本教程中使用的 web 驱动程序是 Chromedriver,可以通过导航到此链接下载。

接下来,我们需要安装 Selenium。在我的 Windows 命令提示符下,我写 pip install selenium。当 Chrome webdriver 和 selenium 模块都安装好后,我就可以导入 webdriver 了。

现在我们可以让 Python 代码使用 Chrome webdriver 来控制浏览器。在 webdriver.chrome()中,需要传递 chromedriver 可执行文件的路径。在这里,chromedriver.exe 在我的本地工作目录中。我把它赋给变量 browser。我们现在可以通过 Python 代码来控制浏览器。

我们可以使用 browser.get()导航到一个网站,方法是将该网站的路径用引号括起来。在这里,我想导航到沃尔玛的网页,其中包括所有关于沙滩球的信息。

我们可以在浏览器上使用许多不同的方法。我们可以使用 CSS select 查询来查找感兴趣的特定元素。CSS 选择器对于网页抓取非常有用。例如,CSS 类定义了多个标签的样式,这是一个可以在网页抓取过程中有效利用的特性!由于我们搜索的元素可能有一个规则的样式,它们很可能有相同的 CSS 类。

在第一个 web 页面上,我希望找到一个包含某个商品所有相关信息的包装器。当我导航到该网页时,右键单击并选择 inspect,我可以看到我感兴趣的包装器有一个 li 标签和一系列类,如下所示:

<李 class = " Grid-col u-size-1–4-l u-size-3–12 米 u-size-6–12 u-size-1–5-XL "

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我在浏览器中时,为了帮助找到所有这些列表项,我可以切换到 Chrome 的开发者工具中的控制台标签。当我在这里时,我可以编写一个测试查询。为此,我写了两个美元符号$$并在括号内输入我的查询,如下所示:

$ $(‘李。grid-col . u-size-1–4-l . u-size-3–12-m . u-size-6–12 . u-size-1–5-XL ')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这将显示一个长度为 40 的列表,如上面的括号所示。我通过滚动列表项并查看浏览器中相应的突出显示,快速验证了每个列表项都对应于 web 页面上相应的沙滩球。我鼓励的一个工作实践是检查列表中的最后一项,并检查它是否是页面上您感兴趣的最后一项。

对我们来说是这样的!

如果不是这样,您可以在控制台开发工具中再次尝试不同的 CSS 查询。这是一个很好的实践,因为我们可以在浏览器中执行初始验证,而不是在 Python 脚本中。它也非常容易看到,因为我们可以同时查看 CSS 查询和浏览器页面!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们现在可以将这个查询直接传递给**。find _ elements _ by _ CSS _ selector**方法。我创建了一个名为 beach_balls 的变量,它指向找到的所有沙滩球的列表。我们现在可以迭代这个 beach_balls 列表。

print(type(beach_balls))
<class 'list'>

使用同样的方法,我可以编写一个简单的 for 循环来提取我感兴趣的信息。

这里,我使用find _ element _ by _ CSS _ selector(我使用了 element,而不是 elements )来查找与原始包装器中包含的其他信息相关的标签和类。当我为 desc ect 找到合适的元素时,我使用。text 方法提取文本,lstrip 方法对字符串进行简单清理。

这段代码运行良好,但是 web 抓取真正有用的方面是它提供的自动化。为了演示,我将用沃尔玛的沙滩球抓取 2 页(尽管我们可以很容易地抓取更多页面的数据)。我写了一个 while 循环,它将根据提供的条件迭代两次。

需要注意的是并非每个项目都有所有信息。例如,在一些情况下,运输信息丢失。通常,当您在编写 scraper 时遇到这种情况时,您应该在 for 循环中编写一个条件,这样所有信息都会匹配。然而,沃尔玛的这个页面是这样组织的,当信息丢失时,空白填充空间。这意味着在这种情况下,在 for 循环中不需要条件检查,但是要小心,情况并不总是这样!

多页刮擦

在每次迭代中,我将相关的项目添加到适当的列表中。在 for 循环的第一次迭代结束时,我点击进入下一页。我找到对应于下一页的标签和类,并使用**。单击()**方法导航到它上面。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果一切正常,脚本应该在第三页结束。根据我的 while 条件,应该有两次迭代。

该脚本已按预期工作。下面,第三个页面已经加载,如网页底部的绿色图标所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,我将把输出写到一个 CSV 文件中,通过使用 pandas Dataframe 方法把我的列表压缩在一起并给它们起一个合理的名字。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本教程重点介绍了如何使用 selenium 从一个网站抓取多个页面。如果我们想要,我们可以从不同的网站搜集信息,并开始为我们的沙滩球或任何其他我们可能感兴趣的物品构建一个价格比较模型。

但作为总结,去给自己买个沙滩球,去海滩吧!

对 ClinicalTrials.gov 简单而实用的分析

原文:https://towardsdatascience.com/simple-yet-practical-analysis-of-clinicaltrials-gov-f84b367e1e68?source=collection_archive---------16-----------------------

通过少量的机器学习

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

临床研究工作教会了我一些重要的事情,所有这些都可以用一句话来表达:

“用心做好事情,让自己免于恐惧.”

对于临床试验来说尤其如此,在临床试验中,研究人员要对患者的健康和幸福负责。

开发一种药物的整个过程极其复杂,可能需要几十年时间。一种新药首先在实验室里进行研究,如果这种药看起来有希望,在临床试验过程中就会对其进行仔细的人体研究。

进行临床试验是为了找到预防、诊断和治疗疾病的更好方法。所以从本质上来说,临床试验的目标是确定一种药物是否既安全又有效。

今天,大多数临床试验都要经过彻底的注册程序。FDA ( *美国食品药品监督管理局)*要求所有正在进行人体临床试验的药物和设备必须在ClinicalTrials.gov上注册,这是一个基于网络的资源,为公众提供了一个方便获取公共和私人支持的临床研究信息的途径。虽然它无疑是帮助患者找到他们可能参与的研究的一个很好的工具,但它也为研究人员和卫生保健专业人员提供了关于新药开发的最新信息。

这就是我在数据科学之旅中学到的另一件事:没有什么比处理易于访问和结构化的数据更令人满意的了。

一个包含所有 XML 格式研究记录的 zip 文件可供下载。让我们看看我们能从这些数据中获得什么样的见解。

首先,最好能显示这些年来在世界各地进行的临床研究的数量。点击此处查看用 plotly 创建的交互式地图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由于 ClinicalTrials.gov 提供有关美国临床试验的信息,难怪大多数研究来自美国。除此之外,美国医药市场是世界上最大的国家市场。

现在让我们看看哪个国家倾向于更积极地参与临床试验。为了弄清楚这一点,我将每个国家 2016 年开始的研究数量除以该国人口。你可以在这里查看地图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

出乎意料的是,美国在这里失去了领导地位。丹麦的人均审判次数似乎比其他任何国家都多。很可能,如此大量的研究是丹麦政府将该国确立为临床试验首选国家的多项举措的结果。

另一个例子是许多肺癌试验的地图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

尽管美国是领导者,我们可以看到中国是癌症研究的主要地区之一。主要原因可能是中国是世界上最大的烟草消费国和生产国。

T3 机器学习来了

在从事临床研究时,我对制药公司如何决定研究方向特别感兴趣。大多数公司试图专注于特定的利基市场,开发针对特定疾病群体的产品。使用主成分分析(PCA)有可能将排名前 50 位的公司的研究成果可视化。

每个公司由一个向量表示,其中每个值是该公司对特定疾病进行研究的次数。我还将这些值标准化,并使用主成分分析来可视化数据。我鼓励你点击这个链接来查看可视化效果(警告:可能需要一些时间才能打开)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

This way we can see which companies share the same interests in clinical research

这里你可以看到一些公司形成了独立的集群。例如,黄点(赛诺菲巴斯德、MedImmune LLC 和诺华疫苗)是主要从事疫苗研究的公司。底部的紫色公司(波士顿科学公司、圣犹达医疗公司和美敦力心律和心力衰竭公司)因开发心脏病学产品而闻名。不出所料,基因泰克和霍夫曼-罗氏公司也走得很近。

我相信这种分析是一种很好的方式,可以让你对临床试验有一个更全面的了解。毫无疑问,机器学习在临床研究中的潜力很难被高估。

请在下面的评论中分享你对机器学习如何应用于临床研究的想法。

复杂中的简单

原文:https://towardsdatascience.com/simplicity-in-the-complexity-2e0e0adaad4f?source=collection_archive---------27-----------------------

向非技术人员解释神经网络

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作为一名数据科学家,我听说过对人工智能的两种极端解释。一方面,人工智能就是使用命令。适合“plus”。用提供的工具“预测”,因此我们可以通过简单地导入库来实现人工智能。另一方面,人工智能是一项神奇的任务,其他领域的人很难理解。

虽然对于数据科学家来说,戴上一个看似花哨的头衔,暗示着神奇的工作,这可能很方便,但事实上,这并没有那么花哨。

如果我们能够解释人工智能背后的基本思想,以一种任何人都可以直观理解的方式去神秘化它,那么我们就可以帮助提高组织采用人工智能的速度,就像采用上个世纪改变了我们商业运作方式的任何其他技术一样。

这让我思考,我该如何向非技术观众解释人工智能?经常被问到的一个问题是最热门的算法之一——神经网络,这是一种近年来重新流行的方法,并形成了深度学习的基础。

那么简单来说什么是神经网络呢?让我们把这个术语分解成“神经元和“网络”。

要解读“神经元”,我们可以把它想象成一个把 A 映射到 b 的黑盒,或者更具体地说,它是一个数学函数,取输入 A,给出输出 b。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

比方说,我们想预测房价 b。在最简单的情况下,我们假设房价线性依赖于房子的大小 A 乘以常数 C,加上购买该房子所涉及的一些固定法律费用 L。把它放入公式中,我们有一个假设 B = C * A + L,它代表了房价“成分”的基本事实。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里最本质的任务是确定常数 C 和常数 l,一旦我们在黑盒里有了这样一个公式,给定任何房子的大小,我们就可以预测它的价格。

几乎在所有情况下,我们没有足够的知识来揭示投入和产出之间的真实关系,在这种情况下,房子的大小和房价。那我们怎么去找 C 和 L 呢?

然而,我们确实有一堆数据,每个数据点代表一个特定的房子大小和各自的价格。正是通过这些数据,我们希望了解一个模型,它足够代表我们假设的现实。

换句话说,对于每个问题,都有一个“正确的神经元”可以解决问题。

这是一个最简单的“神经元”的例子,其中输入和输出之间的关系是线性的。事实上,在大多数实践中,这种神经元还包括一个额外的非线性转换,有助于捕捉更复杂的关系。

在许多科学领域,寻找“正确的神经元”的想法确实是解决问题的长期方法。

给定一个问题,我们想要对输入和输出之间的关系进行建模,以试图完全描述一个系统的特征。我们写下一些公式,把这个问题抽象成可解的形式。

许多实际问题往往太复杂,无法用这种方式解决。以房价为例。事实上,价格不仅取决于房子的大小,还取决于许多其他因素,如位置、设施和经济状况。因此,即使是知识最渊博的专家也不可能提供一个公平的公式来考虑所有相关因素,并根据这些因素计算相应的房价。

如果单个神经元不能处理这种复杂性,那么多个神经元能完成这项工作吗?

这就是“网络”概念的由来。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

神经网络由多个神经元组成,每个神经元接受一些输入并给出一些输出。一个神经元的输出可以成为其他一些神经元的输入。通过多个神经元,神经元网络可以执行更复杂的计算,同时保持每个神经元相对“简单”。

现在,复杂性正在部分地从神经元内部结构转移到网络结构。有了这样的网络,模型就能够表现更复杂的现象。

本质上,神经网络在复杂中描绘了一幅简单的美丽画面——嵌入在复杂网络中的“简单”神经元。

机器学习中的简单性与复杂性——找到正确的平衡

原文:https://towardsdatascience.com/simplicity-vs-complexity-in-machine-learning-finding-the-right-balance-c9000d1726fb?source=collection_archive---------17-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在统计学和机器学习中,偏差-方差权衡是一组预测模型的属性,其中在参数估计中具有较低偏差的模型在样本间具有较高的参数估计方差,反之亦然。偏差-方差困境或问题是试图同时最小化这两个误差源的冲突,这两个误差源阻止监督学习算法推广到它们的训练集之外:

  • 偏差是学习算法中错误假设的误差。偏高(过于简单)会导致算法错过特征和目标输出之间的相关关系(欠拟合)。
  • 方差是对训练集中小波动的敏感性误差。高方差(过于复杂)会导致算法对训练数据中的随机噪声建模,而不是对预期输出建模(过拟合)。

简单模型优于复杂模型的 3 个原因

  1. 防止过度拟合:具有太多特征的高维数据集有时会导致过度拟合(模型捕捉真实和随机效果)。
  2. 可解释性:具有太多特征的过于复杂的模型可能难以解释,尤其是当特征相互关联时。
  3. 计算效率:在低维数据集上训练的模型在计算上是高效的(算法的执行需要较少的计算时间)。

当使用高维数据集构建机器学习模型时,从简单的模型开始总是可取的,然后可以根据需要增加复杂性。在模型评估过程中,执行多项测试以确保模型不会捕捉数据集中的随机效应非常重要。为了能够发现随机效应,对你试图解决的问题有充分的了解是很重要的。

在本文中,我们使用 PyLab 来说明偏差-方差问题。通过一个例子,我们讨论了欠拟合(偏差误差,由模型过于简单引起)和过拟合(方差误差,由模型过于复杂引起)的概念。我们展示了如何在简单性和复杂性之间取得平衡。

例子:向上抛向空中的物体的位置

我们考虑一个实验,其中一个物体被抛向空中,其位置作为时间的函数被测量。从这个假设实验中获得的数据如下所示:

**#import necessary libraries**
import pylab
import numpy as np
import matplotlib.pyplot as plt**#create the dataset**
t = np.linspace(0,1,11)
h = np.array([1.67203, 1.79792, 2.37791,2.66408,2.11245, 2.43969,1.88843, 1.59447,1.79634,1.07810,0.21066])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The measured height of a particle at various times.

从我们对力学的研究中,我们知道高度应该随着时间的平方而变化,因此我们应该使用二次曲线来代替数据的线性拟合:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了说明偏差-方差问题,让我们回到位置数据,并对数据拟合一个线性、一个二次和一个 10 次多项式:

plt.figure(figsize=(15,5))**# fig 1**
plt.subplot(131)
**#perform linear fit using pylab**
degree = 1
model=pylab.polyfit(t,h,degree)
est_h=pylab.polyval(model,t)
#calculating R-squared value
R2 = 1 - ((h-est_h)**2).sum()/((h-h.mean())**2).sum()#plot of observed and modeled data
pylab.scatter(t,h, c='b', label='observed')
pylab.plot(t,est_h, c='r', label='predicted:' + ' R2' '='+ ' ' + str(round(R2,4)))
pylab.xlabel('t(s)')
pylab.ylabel('h(m)')
pylab.title('linear model is not good (underfit)')
pylab.legend()**# fig 2**
plt.subplot(132)
#**perform quadratic fit using pylab**
degree = 2
model=pylab.polyfit(t,h,degree)
est_h=pylab.polyval(model,t)
#calculating R-squared value
R2 = 1 - ((h-est_h)**2).sum()/((h-h.mean())**2).sum()#plot of observed and modeled data
pylab.scatter(t,h, c='b', label='observed')
pylab.plot(t,est_h, c='r', label='predicted:' + ' R2' '='+ ' ' + str(round(R2,4)))
pylab.xlabel('t(s)')
pylab.ylabel('h(m)')
pylab.title('quadratic model is what we need')
pylab.legend()**# fig 3**
plt.subplot(133)
#**perform higher-degree fit using pylab**
degree = 10
model=pylab.polyfit(t,h,degree)
est_h=pylab.polyval(model,t)
#calculating R-squared value
R2 = 1 - ((h-est_h)**2).sum()/((h-h.mean())**2).sum()#plot of observed and modeled data
pylab.scatter(t,h, c='b', label='observed')
pylab.plot(t,est_h, c='r', label='predicted:' + ' R2' '='+ ' ' + str(round(R2,4)))
pylab.xlabel('t(s)')
pylab.ylabel('h(m)')
pylab.title('degree=10 captures random error (overfit)')
pylab.legend()pylab.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Illustration of bias error (underfit) and variance error (overfit).

对于线性拟合,R2 (R 平方)参数为 0.3953,非常低。如果我们有一个很好的拟合,我们会期望 R2 值更接近 1.0。对于二次拟合,R2 值为 0.8895。因此,二次拟合比线性拟合有了相当大的改进。使用次数= 10 的多项式,我们发现 R2 值等于 1.0。我们看到高次多项式捕捉到了真实的和随机的效果。在这个问题中,我们的力学知识表明,在二次模型之外进行高阶近似是没有好处的。

总之,我们用一个非常简单的例子讨论了偏差-方差问题。我们已经看到,决定一个好的拟合的主要因素是你要拟合的函数形式的有效性。当然,只要有可能,关于物理问题的理论或分析信息都应该整合到模型中。通常,与过于复杂的模型相比,模型参数较少的简单模型总是更容易解释。

参考

  1. 维基百科上的偏差-方差权衡。
  2. 《计算物理学的第一课》,作者:Paul L. DeVries,John Wiley & Sons,1994 年。

理解辍学背后的简化数学

原文:https://towardsdatascience.com/simplified-math-behind-dropout-in-deep-learning-6d50f3f47275?source=collection_archive---------2-----------------------

在这里,我们将理解驱动辍学的数学。如何导致正规化?为什么0.5的辍学率导致最正规化?什么是高斯辍学

<了解深度学习,了解更多> >

尽管报告了突破性的结果,但从理论的角度来看,人们对辍学知之甚少。同样,辍学率为 0.5 的重要性以及它应该如何随着层的变化而变化并不明显。此外,我们能把辍学推广到其他方法吗?下面将提供一些解释。

深度学习架构现在变得越来越深入和广泛。有了这些更大的网络,我们能够实现良好的精确度。然而,大约十年前并非如此。事实上,深度学习因过度适应问题而声名狼藉。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1. A dense neural network.

然后在 2012 年左右,萌生了退学的想法。这个概念彻底改变了深度学习。我们在深度学习方面的成功很大程度上归功于辍学。

快速回顾:什么是辍学?

  • Dropout 将学习所有权重的概念改变为在每次训练迭代中学习网络中的一小部分权重。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2. Illustration of learning a part of the network in each iteration.

  • 这个问题解决了大型网络中的过拟合问题。突然之间,更大、更精确的深度学习架构成为可能。

在这篇文章中,我们的目标是理解辍学背后的数学原理。然而,在我们进入数学之前,让我们后退一步,了解辍学改变了什么。这将是接触数学的动力。

退学前一个主要的研究领域是正规化。在神经网络中引入正则化方法,如 L1 和 L2 权重罚值,始于 21 世纪初[1]。然而,这些调整并没有完全解决过拟合问题。

原因是共同适应。

神经网络中的协同适应

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3. Co-adaption of node connections in a Neural Network.

学习大型网络的一个主要问题是共同适应。在这样的网络中,如果所有的权重一起学习,通常一些连接将比其他连接具有更强的预测能力。

在这种情况下,随着网络被反复训练,这些强大的连接被学习得更多,而较弱的连接被忽略。经过多次迭代,只有一小部分节点连接被训练。其余的停止参与。

这种现象被称为共适应。像 L1 和 L2 那样的传统正规化无法避免这一点。原因是它们也基于连接的预测能力进行调整。因此,它们在选择和拒绝权重时变得接近确定性。因此,强者愈强,弱者愈弱。

这样做的一个主要后果是:扩大神经网络的规模无助于。因此,神经网络的规模和准确性变得有限。

然后就辍学了。一种新的正则化方法。它解决了共同适应。现在,我们可以建立更深更广的网络。并利用它的预测能力。

在这样的背景下,让我们深入研究辍学的数学。你可以直接跳到辍学相当于正规化网络部分的推论*。*

辍学背后的数学

考虑网络中的单层线性单元,如下图 4 所示。详情请参考[ 2

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 4. A single layer linear unit out of network.

这称为线性激活,因为 f(x) = x 是线性的,如图 4 所示,该层的输出是输入的线性加权和。我们正在考虑这种简化的情况,以获得数学上的解释。这些结果(根据经验)适用于通常的非线性网络。

对于模型估计,我们最小化损失函数。对于这个线性层,我们将考虑普通的最小二乘损耗,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

情商。1 显示常规网络和 Eq 的损耗。2 用于辍学网络。在 Eq 中。2、辍学率是𝛿,其中𝛿 ~伯努利( p )。这意味着𝛿等于 1,概率为 p,否则为 0。

网络训练的反向传播使用梯度下降法。因此,我们首先来看看等式(1)中压差网络的梯度。2,然后再来情商里的正规网络。1.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,我们将试图找到这个梯度和规则网络的梯度之间的关系。为此,假设我们使等式中的w’ =p*w。1.因此,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对等式求导。4、我们发现,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,我们有了有趣的部分。如果我们找到压差网络梯度的期望值,我们得到,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们看情商。6、有漏失的梯度的期望,等于正则化正则网络 Eɴ的梯度如果w’ =p*w .

等效于正则化网络的丢失

这意味着最小化压差损失(在等式中)。2)等效于最小化正则化网络,如等式所示。7 以下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

也就是说,如果你在方程中对正则化网络进行微分。7,你将得到一个压差网络的(预期)梯度,如等式。6.

这是一种深刻的关系。从这里,我们可以回答:

为什么辍学率, p = 0.5,产生最大正则化?

这是因为等式中的正则化参数 p (1- p )。7,在 p = 0.5 时最大。

不同的层应该选择什么样的 p 值?

在 Keras 中,辍学率参数为(1- p )。对于中间层,对于大型网络,选择(1- p ) = 0.5 是理想的。对于输入层,(1- p )应该保持在大约 0.2 或更低。这是因为丢弃输入数据会对训练产生不利影响。不建议使用 A (1- p ) > 0.5,因为它会剔除更多的连接,而不会促进正则化。

为什么我们在测试或推理过程中用 p 来衡量权重 w?

因为一个失落网络的期望值相当于一个常规网络,其权重与失落率 p 成比例。这种缩放使得从一个断开的网络中得到的推论可以与完整的网络相比较。还有计算上的好处,这在[ 1 ]中用集合建模的观点进行了解释。

在我们走之前,我想谈谈高斯辍学。

什么是高斯辍学?

正如我们之前看到的,在 Dropout 中,我们放弃了与概率(1- p )的联系。用数学方法,用等式。2 我们将连接权重乘以随机变量𝛿,其中𝛿 ~伯努利( p )。

这个退出过程可以看作是在每个连接上放置一个伯努利门。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 5. Dropout seen as a Bernoulli gate on connections.

我们可以用另一个门代替伯努利门。例如高斯门。这给了我们一个高斯漏失。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 6. Dropout generalized to a Gaussian gate (instead of Bernoulli).

高斯辍学生被发现和普通辍学生一样好,有时甚至更好。

在高斯下降的情况下,激活的期望值保持不变(见等式。8).因此,与常规放弃不同,推理过程中不需要权重缩放。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这一特性也为高斯压降提供了计算优势。我们将在接下来的帖子中探讨高斯辍学的表现。在那之前,我要提醒你一句。

虽然漏失门的概念可以推广到除伯努利分布以外的其他分布,但建议理解新的分布将如何影响激活的预期。基于此,应该对激活进行适当的缩放。

结论

在这篇文章中,我们讨论了辍学背后的数学原理。我们在一些简化的条件下做了这道数学题。然而,该结果扩展到深度学习中的一般情况。总之,我们知道,

  • 辍学和正常化之间的关系,
  • 0.5 的辍学率将导致最大的正规化,以及
  • 将辍学推广到高斯-安德洛普。

参考

  1. n . Srivastava,g . hint on,a . krijevsky,Sutskever,I .,& Salakhutdinov,R. (2014 年)。辍学:防止神经网络过度拟合的简单方法。《机器学习研究杂志》15 (1),1929–1958。
  2. 巴尔迪,p .,&萨多夫斯基,P. J. (2013)。理解辍学。在神经信息处理系统的进展(第 2814-2822 页)。

使用熊猫简化数据集清理

原文:https://towardsdatascience.com/simplify-your-dataset-cleaning-with-pandas-75951b23568e?source=collection_archive---------3-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Markus Spiske on Unsplash

我听到很多分析师/数据科学家说他们花了大部分时间清理数据。你可能已经看过很多清理数据集的教程,但你可能已经知道:它永远不会是 100%干净的,在继续阅读本文之前,你必须理解这一点。所以我实话实说:我不会给你一个神奇的方法来解决你的数据集可能存在的所有数据问题。清理规则取决于您正在处理的域和项目的上下文。本文中的例子来自我自己在现实世界中处理数据的经验。

我已经处理了本文中详述的所有问题/过程。有时问题可能来自数据源本身,您必须清理它,有时只是您的同事或经理要求最终文件中的某些特定字段。欢迎在评论中分享你从经历中看到的主要问题。

开始前你需要什么

计算机编程语言

您需要最新的 Python 版本:3.7+。我推荐使用 Anaconda 发行版来获得 Python、Pandas 和 Jupyter。如果您已经安装了 Anaconda,请忽略以下两个命令。

Seaborn

pip install seaborn

熊猫

pip install pandas

Jupyter 笔记本

pip install jupyter

开始工作

让我们从我在 Kaggle 上找到的一个基本数据集开始。这个数据集是在 Google 上搜索“航班”和“机票”的搜索结果报告。当你在谷歌上搜索一个查询时,“有机的”结果会在搜索结果页面中排名,在这个数据集中每个查询只列出 10 个。正如您所猜测的,我们可能会在某些字段中遇到重复项。

我们将讨论以下主题:

  1. 删除无用字符
  2. 从系列中提取相关内容
  3. 检查 NaN 值
  4. 更改系列的类型

打开新的 Jupyter 笔记本并导入数据集:

import os
import pandas as pddf = pd.read_csv('flights_tickets_serp2018-12-16.csv')

我们可以使用 3 个神奇的函数快速检查数据集的外观:

  • 。info():显示行数和类型
df.info()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 。describe():显示数据集中每个数字列的主要统计信息
df.describe()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 。head():显示数据集的前 5 行(可以通过传递一个整数作为参数来更改这个数字)
df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们甚至可以显示列名,因为我们有太多的列名,它们不适合显示在屏幕上:

df.columns

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我们对我们正在处理的事情有了更好的认识。从这一点出发,根据你公司的环境和你的目标,你不会寻找同样的东西。此外,如果这个数据集将被用来为机器学习算法提供训练,或者如果你需要为你的经理运行分析,你的输出数据帧看起来不会一样。但这不是这里的主题。我们继续第一个话题。

1.删除无用字符

为什么我们要删除充满数据的数据集中的字符?嗯,数据集并不总是为你的个人用例而构建的,而是为多种用途而构建的。同样,根据你的项目,你的关注点会有所不同。

在你从事 NLP(=自然语言处理)项目的情况下,你需要让你的文本非常干净,去掉那些不改变意思的不常见的字符。如果我们仔细看看“标题”一栏,

df['title']

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

First 10 values in the “title” column

我们可以看到几个要删除的特殊字符,比如:,。()[ ] + | -

为了安全起见,可以使用特殊字符的完整列表,并使用循环删除它们:

spec_chars = ["!",'"',"#","%","&","'","(",")",
              "*","+",",","-",".","/",":",";","<",
              "=",">","?","@","[","\\","]","^","_",
              "`","{","|","}","~","–"]for char in spec_chars:
    df['title'] = df['title'].str.replace(char, ' ')

现在你不应该在你的标题栏中有这些字符。因为我们用加号替换了特殊字符,所以在某些标题中,我们可能会以双空格结束。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

String example before removing the special character

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

String example after removing the special character which creates an extra space

让我们通过使用空格拆分每个标题并使用连接再次重新连接单词来删除它们。

df['title'] = df['title'].str.split().str.join(" ")

我们完成了这个专栏,我们删除了特殊字符。注意,我没有包括货币字符和点“.”在上述特殊字符列表中。原因是一些结果标题包含他们正在销售的机票的价格(例如“514.98 美元”),在下一部分中提取这些信息可能会很有意思。

2.从系列中提取相关内容

使用数据集时,重要的是使数据集更加清晰、易读。你的数据集可能最终被摄入机器学习管道,也就是说,这个想法是从这个数据集中提取大量信息。我将展示一个例子,但是您将提取的信息的粒度取决于您的目标。

假设您想从结果标题(即标题列)中提取所有以美元表示的价格。我们使用一个正则表达式函数来完成这个任务。如果你愿意,你可以在这里用你的正则函数做一些测试。

df['dollar_prices'] = df['title'].str.extract('(\$\.d*\.?\d*)')

我们现在已经在标题列中提取了所有以美元为单位的价格。

我们现在显示结果列的唯一值:

df['dollar_prices'].unique()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正如你所看到的,我们有一些 NaN(=非数字)值(上面数组中的第四个位置)。有些图书没有美元价格,所以 regex 规则找不到它,取而代之的是“nan”。我们将在下一节看到如何处理 NaN 值。

3.检查 NaN 值

大多数情况下,一个大型数据集将包含 NaN 值。如何处置他们?我们应该离开他们吗?绝对不行!你不能离开他们,因为你可能要在数字列上执行计算,或者仅仅是因为你将来要为一个数据科学团队建模。对于那些了解机器学习的人来说,或多或少,你知道你的特征/变量/预测器在训练一个模型之前应该是数值型的。出于所有这些原因,我们希望修复 NaN 值。我不会花太多时间讨论不同的策略,有很多文章解释不同的策略。您可以做什么:

  • **移除相应的行:**只有在移除行不影响数据集中的分布或者它们不显著时,才可以这样做。如果在您的 1M 数据集中只有 3 行具有一些 NaN 值,那么删除这些行应该是安全的。否则,您可能不得不采用下一个选项。
  • **用统计量替换它们(在数值列中)😗*可以用列的平均值替换 NaN 值。小心,你不想歪曲数据。查看另一个列(如分类列)并根据每个类别的平均值替换 NaN 值可能更合适。让我解释一下。例如,在泰坦尼克号的数据集中,每一行代表一名乘客。票价列中的一些值丢失(NaN)。为了用更准确、更接近实际的值来替换这些 NaN:例如,您可以用同一票种的各行票价的平均值来替换它们。你这样做是假设买同一种票的人支付的价格大致相同,这是有道理的。
  • **否则:**试着了解你的领域,你的背景,这将帮助你知道如何以一种安全的方式替换丢失的变量。如果您不会在机器学习管道中使用该数据集,您可以用另一个值来替换 NaN,如字符串(在字符串类型列的情况下)“None”或“NoData”,任何与您和将使用该数据集的人相关的值。

关于处理 NaN 值的更多例子,我推荐阅读一篇关注这一点的文章。

关于我们的数据集,让我们使用名为 seaborn 的可视化库来看看 NaN 值的比例是多少。您可以直接使用 Pandas 函数,但我认为最好先使用可视化方式,以便了解您的数据:

sns.heatmap(df.isnull(), cmap='viridis')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这张热图中,您可以看到每列中的 NaN 值为黄色(取决于您使用的 cmap ,但我的是黄色)。这并不意味着没有黄色的列没有任何 NaN,它只是在热图的顶部或底部有一些 NaN,所以它们与热图的图形边框相混淆(这是由于笔记本中打印的图像的分辨率)。无论如何,不要犹豫使用显示原始数据。isnull() 熊猫功能。

在我们的例子中,我们将只保留在标题中有美元价格的行,因此我们将只保留在美元价格列中有值的行:

df = df.dropna(subset=['dollar_prices'])

得到的 DataFrame 只包含 dollar_price 有值的行,其他的都被删除了。

4.更改系列的类型

在这个数据集中,我们可能没有太多的类型变化要做。这取决于你的背景和数据集的质量。如果您对我们在 df.info() 中看到的列类型感到满意,那很好。

输入文件可能来自您的一位同事,他将数据保存到 Excel 文件(.xlsx)。在这种情况下,这是因为 Excel 在这方面很糟糕,您的列的格式可以更改,特别是对于您的 Ids 列。我所说的“Id”是指一个列,它代表您所列出的实体之一的 Id。例如,如果您正在操作一个包含产品库存的数据集,那么其中可能会有一个 ProductId 列。无论如何,Excel 中的数字 id 可以被解释为数字列或文本列,老实说,我不知道 Excel 何时选择其中之一。

对于您的数据操作,这取决于您希望如何处理脚本中的 id,您希望操作文本(字符串)还是数值(整数)?这取决于你,但是在你的脚本中要保持一致,如果你需要连接两个数据帧,例如,基于一个 Id 列,首先以相同的格式转换它们(字符串整数,但是你必须选择一个)。

让我们回到我们的数据集。在第二部分中,我们创建了一个包含美元价格的新列。在这一点上,我们知道有美元,对不对?因为关于货币的信息在列名中。也就是说,我们可以去掉美元字符:

df['dollar_prices'] **=** df['dollar_prices'].str.replace('$', '')

最后一步是检查这个列的类型。我们应该有一个字符串,因为我们用 regex 规则提取了数据作为字符串:

df.dtypes

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里我们的美元价格是一个对象,实际上意味着一个 s 字符串。我们真的想把我们的价格当成字符串吗?对于价格,我们更喜欢使用 floats ,我们只需要转换列类型。

df['dollar_prices'] = pd.to_numeric(df['dollar_prices'], errors='coerce')

如果您再显示一次 dtypes ,您会注意到 dollar_prices 列不再是一个对象,而是一个 float64 类型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

我希望你能找到一些你可能问过自己的问题的答案。正如我在开始时所说的,没有统一的方法来清理数据集,一些检查必须完成,例如 NaN 值。剩下的真的要看项目需要什么水平的质量了?要提取哪些相关数据?

此外,请记住,您可以从数据集(第 2 节)中提取的所有内容可能对可视化专家非常有帮助,他们将使用您的数据集作为源来构建仪表板。

Jupyter 笔记本可以在我的 GitHub 这里找到

不要犹豫写评论和问题。

用 Fast.ai 简化深度学习

原文:https://towardsdatascience.com/simplifying-deep-learning-with-fast-ai-37aa0d321f5e?source=collection_archive---------13-----------------------

Fast.ai 程序员实用深度学习课程概述

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

深度学习是一个因守门而臭名昭著的领域。如果你试图在网上寻找如何进入这个领域的答案,你可能会发现自己被一长串要求淹没了。

这通常会吓跑该领域的潜在贡献者,给我们留下世界上一小部分可以消费和生成深度学习模型的人。

Fast.ai 是一个试图解决这种不平等的组织。它是由杰瑞米·霍华德雷切尔·托马斯在 2016 年创立的,目标是让深度学习变得更容易实现。它主要以其免费课程和开源库而闻名(名为 fastai ,建立在脸书 PyTorch 库之上)。这是最受欢迎的课程之一,本文的重点是面向程序员的实用深度学习。

“我希望很多人会意识到,即使他们不是斯坦福大学深度学习博士,他们也可以实现深度学习的最先进成果。”— 杰瑞米·霍华德

由于数据和计算资源的可用性增加,面向门外汉的深度学习是一个非常受欢迎的领域。它在图像识别、自然语言处理和语音识别等领域产生了最先进的成果。它是自动驾驶汽车、垃圾邮件过滤器和内容推荐系统的动力。高级别的深度学习是神经网络的扩展,它使用一组输入来训练一组权重,然后产生一个输出(就像将图像分类为热狗)。在深度学习的情况下,有更多的层,这意味着要学习更多的权重。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fast.ai 引入了一种自上而下的学习方式,这与大多数其他课程不同,这些课程都是从基础开始,然后逐步向上。直觉上这是有意义的,如果你教某人打篮球,你没有教他们这项运动的物理学。相反,你教他们足够多的东西来开始玩,让他们的兴趣引导他们对这项运动有更深的理解。同样,在深度学习课程的前 45 分钟内,Jeremy 从头到尾向您介绍了如何构建一个最先进的图像分类器。第二课让你根据你在谷歌上找到的图像建立和生产你自己的图像分类器。

在本文中,您将对他们的深度学习课程有一个高层次的概述。你还将学习如何从课程中获得最大收益,以及这对深度学习的未来意味着什么。

课程概述

1。图片分类 第一课涵盖了 Jeremy 的背景和资历,参加课程的动机以及完成课程后的可能性。他揭穿了一些关于深度学习的常见神话(例如需要大量数据和 GPU),并展示了一些过去的学生项目和成功故事。

本课程的其余部分涉及使用 fastai 库构建图像分类器,以达到最先进的精度。因为这门课是以自上而下的方式教授的,所以第一课的重点是让一些东西尽快运转起来。

课堂笔记

2。生产;继续讨论图像分类器的主题,你现在有机会构建自己的图像分类器。在根据你在谷歌上找到的图片训练出一个模型后,你就可以学习如何将这个模型投入生产。本课最精彩的部分是从一个想法到一个生产应用程序的容易程度(这里有一个在本课中构建的熊图像分类器的实例)。

课程的其余部分包括学习随机梯度下降,从头开始构建。

课堂笔记

3。多标签;第三课的第一部分概述了如何处理多标签分类。它还介绍了 fastai 库中使用的一些函数和类。

随着课程的深入,您将进入图像分割的任务。当然,这在自动驾驶汽车和图像标记等应用中得到了广泛应用。你也开始遇到一些与应用程序相匹配的理论,比如学习为什么某些学习速率会产生更好的结果。

这一课也给出了自然语言处理(NLP)的预览。

课堂笔记

4。NLP 表格数据;推荐系统
第一个是迁移学习的想法,它允许你使用一个预先训练好的模型来完成一项特定的任务。有了这个预先训练好的模型,你就可以学习如何预测负面或正面的电影评论。基于这个简单的例子,你可以使用标准化的迁移学习方法达到最先进的效果。

然后,您将继续讨论为表格数据(您可能会在电子表格或关系数据库中看到的数据)构建深度学习模型的主题。构建的示例模型预测个人收入是否超过 5 万美元。

本课最后概述了推荐系统(协同过滤)。Jeremy 探讨了冷启动问题(如何向新用户推荐某样东西?)并向您展示一个简单的 Excel 电影推荐示例。

课堂笔记

5。反向投影;从零开始的神经网络 顾名思义,这节课更多的是基于理论。在这一点上,你开始学习更多关于微调、解冻/冻结层、正则化、使用区别学习率、嵌入、偏差和其他在前面的课程中从你那里抽象出来的东西。

本课以一个在 excel 中构建的神经网络示例结束,向您展示它是如何工作的。

课堂笔记

6。CNN 深潜;伦理学 第六课继续理论的探索,比如辍学的重要性,为什么会有好的结果。本课另一个有趣的部分是数据扩充的主题。这是将一幅图像转换成多幅图像的过程(如下图所示)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后你会接触到更多关于卷积神经网络的理论,并深入了解 CNN 被训练时到底发生了什么。

本课的最后一部分专门讨论数据科学中的道德规范。这很大程度上包括了机器学习技术被误用或有能力被误用的所有方式。面部识别系统和翻译服务中的偏见是滥用的两个例子。

课堂笔记

7 .。Resnet 优网;GANs 最后一课继续以理论为基础,涵盖了使用 Resnet 和 U-net 来实现最先进的结果。

你也有机会接触到生殖对抗性网络,这个话题最近通过 DeepFakes 等应用程序得到了一些媒体报道。本课中的 GAN 应用于清理映像的环境中,您也有机会了解其内部工作原理。

最后一节回顾了 NLP 并探讨了递归神经网络的主题,在这里您有机会构建一个预测序列中下一个单词的模型。

作为最后的行动号召,Jeremy 建议采取以下后续步骤来巩固和发展从课程中学到的知识

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

课堂笔记

在 7 节课结束时,你将会涵盖一系列广泛的主题,如下图所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第二部分将于 2019 年 6 月发布,将涵盖以下主题:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

充分利用 Fast.ai

为了从本课程中获得最大收益,我们建议你看一遍讲座,然后看第二遍或第三遍,重点是复制笔记本。一旦你觉得你已经掌握了一些东西,你就可以开始用你自己的数据和项目,甚至是一场 Kaggle 比赛来实现这些技术。把一个项目看完比留下几个未完成的要好得多。

阅读研究论文也是获取你所学知识并在此基础上发展的好方法。拥有博士学位并不是阅读研究论文的必要条件,所以不要感到害怕。Arxiv Sanity Preserver 是一个很好的起点,因为它提供深度学习各种子专业的免费预印论文。如果你不确定如何阅读研究论文,看看这两个指南(指南一指南二)

简化深度学习

虽然 Fast.ai 并不承诺你在完成他们的课程后会成为深度学习专家,但它确实为你开始实验和修补埋下了最初的种子。许多 Fast.ai 学生继续做许多有趣的工作,无论是在谷歌这样的人工智能驻地,还是在初创公司的深度学习。

简化深度学习背后的整个想法是,它将允许领域专家将他们独特的专业知识与深度学习结合起来。认为一小群机器学习博士将能够解决深度学习可以解决的所有问题是不现实的。尤其是如果他们没有通过严格的学习和实践建立起来的相关领域的专业知识。

Fast.ai 是深度学习领域一个很有前景的发展。如果你对深度学习感兴趣,这是最好的资源之一,可以开始并看看有什么可能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值