Apache Mxnet 简明教程

Apache MXNet - Python API gluon

正如我们在前几章中已经讨论的那样,MXNet Gluon 为 DL 项目提供了一个清晰、简洁且简单的 API。它使 Apache MXNet 能够对 DL 模型进行原型制作、构建和训练,而不会影响训练速度。

Core Modules

让我们了解 Apache MXNet Python 应用程序编程接口 (API) gluon 的核心模块。

gluon.nn

Gluon 在 gluon.nn 模块中提供了大量的内置 NN 层。这就是称其为核心模块的原因。

Methods and their parameters

以下是一些 mxnet.gluon.nn 核心模块涵盖的重要方法及其参数——

Methods and its Parameters

Definition

Activation(activation, **kwargs)

顾名思义,此方法将激活函数应用于输入。

AvgPool1D([pool_size, strides, padding, …])

这是时间数据的平均池化操作。

AvgPool2D([pool_size, strides, padding, …])

这是空间数据的平均池化操作。

AvgPool3D([pool_size, strides, padding, …])

这是 3D 数据的平均池化操作。数据可以是空间或时空数据。

BatchNorm([axis, momentum, epsilon, center, …])

它表示批归一化层。

BatchNormReLU([axis, momentum, epsilon, …])

它还表示批归一化层,但带有 Relu 激活函数。

Block([prefix, params])

它给出了所有神经网络层和模型的基础类。

Conv1D(channels, kernel_size[, strides, …])

该方法用于 1-D 卷积层。例如,时间卷积。

Conv1DTranspose(channels, kernel_size[, …])

该方法用于转置 1D 卷积层。

Conv2D(channels, kernel_size[, strides, …])

该方法用于 2D 卷积层。例如,图像上的空间卷积)。

Conv2DTranspose(channels, kernel_size[, …])

该方法用于转置 2D 卷积层。

Conv3D(channels, kernel_size[, strides, …])

该方法用于 3D 卷积层。例如,体积上的空间卷积。

Conv3DTranspose(channels, kernel_size[, …])

该方法用于转置 3D 卷积层。

Dense(units[, activation, use_bias, …])

该方法表示常规密集连接 NN 层。

Dropout(rate[, axes])

顾名思义,该方法对输入应用 Dropout。

ELU([alpha])

该方法用于指数线性单元 (ELU)。

Embedding(input_dim, output_dim[, dtype, …])

它将非负整数转换为固定大小的稠密向量。

Flatten(**kwargs)

该方法将输入压平为 2 维。

GELU(**kwargs)

该方法用于高斯指数线性单元 (GELU)。

GlobalAvgPool1D([layout])

借助此方法,我们可以对时间数据执行全局平均池操作。

GlobalAvgPool2D([layout])

借助此方法,我们可以对空间数据执行全局平均池操作。

GlobalAvgPool3D([layout])

借助此方法,我们可以对 3-D 数据执行全局平均池操作。

GlobalMaxPool1D([layout])

借助此方法,我们可以对 1-D 数据执行全局最大池操作。

GlobalMaxPool2D([layout])

借助此方法,我们可以对 2-D 数据执行全局最大池操作。

GlobalMaxPool3D([layout])

借助此方法,我们可以对 3-D 数据执行全局最大池操作。

GroupNorm([num_groups, epsilon, center, …])

该方法对 n-D 输入数组应用组归一化。

HybridBlock([prefix, params])

该方法支持使用 SymbolNDArray 进行转发。

HybridLambda(function[, prefix])

借助这种方法,我们可以将运算符或表达式包装为 HybridBlock 对象。

HybridSequential([prefix, params])

It stacks HybridBlocks sequentially.

InstanceNorm([axis, epsilon, center, scale, …​])

这种方法对 n 维输入数组应用实例归一化。

Implementation Examples

在下面的示例中,我们将使用 Block(),它为所有神经网络层和模型提供基本类。

from mxnet.gluon import Block, nn
class Model(Block):
   def __init__(self, **kwargs):
      super(Model, self).__init__(**kwargs)
      # use name_scope to give child Blocks appropriate names.
      with self.name_scope():
         self.dense0 = nn.Dense(20)
         self.dense1 = nn.Dense(20)
   def forward(self, x):

      x = mx.nd.relu(self.dense0(x))
      return mx.nd.relu(self.dense1(x))

model = Model()
model.initialize(ctx=mx.cpu(0))
model(mx.nd.zeros((5, 5), ctx=mx.cpu(0)))

Output

您将看到以下输出 −

[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
<NDArray 5x20 @cpu(0)*gt;

在下面的示例中,我们将使用 HybridBlock(),它支持 Symbol 和 NDArray 进行正向传播。

import mxnet as mx
from mxnet.gluon import HybridBlock, nn


class Model(HybridBlock):
   def __init__(self, **kwargs):
      super(Model, self).__init__(**kwargs)
      # use name_scope to give child Blocks appropriate names.
      with self.name_scope():
         self.dense0 = nn.Dense(20)
         self.dense1 = nn.Dense(20)

   def forward(self, x):
      x = nd.relu(self.dense0(x))
      return nd.relu(self.dense1(x))
model = Model()
model.initialize(ctx=mx.cpu(0))

model.hybridize()
model(mx.nd.zeros((5, 5), ctx=mx.cpu(0)))

Output

输出如下:

[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
<NDArray 5x20 @cpu(0)>

gluon.rnn

Gluon 在 gluon.rnn 模块中提供了大量内置 recurrent neural network (RNN)层。那是它被称作核心模块的原因。

Methods and their parameters

以下是 mxnet.gluon.nn 核心模块涵盖的一些重要方法及其参数:

Methods and its Parameters

Definition

BidirectionalCell(l_cell, r_cell[, …])

用于双向循环神经网络(RNN)单元。

DropoutCell(rate[, axes, prefix, params])

此方法将在给定的输入上应用 dropout。

GRU(hidden_size[, num_layers, layout, …])

它将多层门控循环单元(GRU)RNN 应用于给定的输入序列。

GRUCell(hidden_size[, …])

用于门控整流单元(GRU)网络单元。

HybridRecurrentCell([prefix, params])

This method supports hybridize.

HybridSequentialRNNCell([prefix, params])

借助这种方法,我们可以顺序堆叠多个 HybridRNN 单元。

LSTM(hidden_size[, num_layers, layout, …])0

它将多层长短期记忆(LSTM)RNN 应用于给定的输入序列。

LSTMCell(hidden_size[, …])

用于长短期记忆(LSTM)网络单元。

ModifierCell(base_cell)

它是修饰器单元的基本类。

RNN(hidden_size[, num_layers, activation, …])

它通过 tanhReLU 非线性将多层 Elman RNN 应用于给定的输入序列。

RNNCell(hidden_size[, activation, …])

用于 Elman RNN 循环神经网络单元。

RecurrentCell([prefix, params])

它表示 RNN 单元的抽象基类。

SequentialRNNCell([prefix, params])

借助这种方法,我们可以顺序堆叠多个 RNN 单元。

ZoneoutCell(base_cell[, zoneout_outputs, …])

此方法在基本单元上应用 Zoneout。

Implementation Examples

在下例中,我们将使用 GRU(),它对给定的输入序列应用多层门控循环单元 (GRU) RNN。

layer = mx.gluon.rnn.GRU(100, 3)
layer.initialize()
input_seq = mx.nd.random.uniform(shape=(5, 3, 10))
out_seq = layer(input_seq)
h0 = mx.nd.random.uniform(shape=(3, 3, 100))
out_seq, hn = layer(input_seq, h0)
out_seq

Output

生成以下输出:

[[[ 1.50152072e-01 5.19012511e-01 1.02390535e-01 ... 4.35803324e-01
1.30406499e-01 3.30152437e-02]
[ 2.91542172e-01 1.02243155e-01 1.73325196e-01 ... 5.65296151e-02
1.76546033e-02 1.66693389e-01]
[ 2.22257316e-01 3.76294643e-01 2.11277917e-01 ... 2.28903517e-01
3.43954474e-01 1.52770668e-01]]


[[ 1.40634328e-01 2.93247789e-01 5.50393537e-02 ... 2.30207980e-01
6.61415309e-02 2.70989928e-02]
[ 1.11081995e-01 7.20834285e-02 1.08342394e-01 ... 2.28330195e-02
6.79589901e-03 1.25501186e-01]
[ 1.15944080e-01 2.41565228e-01 1.18612610e-01 ... 1.14908054e-01
1.61080107e-01 1.15969211e-01]]
………………………….

Example

hn

Output

生成以下输出:

[[[-6.08105101e-02 3.86217088e-02   6.64453954e-03 8.18805695e-02
3.85607071e-02 -1.36945639e-02 7.45836645e-03 -5.46515081e-03
9.49622393e-02 6.39371723e-02 -6.37890724e-03 3.82240303e-02
9.11015049e-02 -2.01375950e-02 -7.29381144e-02 6.93765879e-02
2.71829776e-02 -6.64435029e-02 -8.45306814e-02 -1.03075653e-01
6.72040805e-02 -7.06537142e-02 -3.93818803e-02 5.16211614e-03
-4.79770005e-02 1.10734522e-01 1.56721435e-02 -6.93409378e-03
1.16915874e-01 -7.95962065e-02 -3.06530762e-02 8.42394680e-02
7.60370195e-02 2.17055440e-01 9.85361822e-03 1.16660878e-01
4.08297703e-02 1.24978097e-02 8.25245082e-02 2.28673983e-02
-7.88266212e-02 -8.04114193e-02 9.28791538e-02 -5.70827350e-03
-4.46166918e-02 -6.41122833e-02 1.80885363e-02 -2.37745279e-03
4.37298454e-02 1.28888980e-01 -3.07202265e-02 2.50503756e-02
4.00907174e-02 3.37077095e-03 -1.78839862e-02 8.90695080e-02
6.30150884e-02 1.11416787e-01 2.12221760e-02 -1.13236710e-01
5.39616570e-02 7.80710578e-02 -2.28817668e-02 1.92073174e-02
………………………….

在下例中,我们将使用 LSTM(),它对给定的输入序列应用长短期记忆 (LSTM) RNN。

layer = mx.gluon.rnn.LSTM(100, 3)
layer.initialize()

input_seq = mx.nd.random.uniform(shape=(5, 3, 10))
out_seq = layer(input_seq)
h0 = mx.nd.random.uniform(shape=(3, 3, 100))
c0 = mx.nd.random.uniform(shape=(3, 3, 100))
out_seq, hn = layer(input_seq,[h0,c0])
out_seq

Output

输出如下:

[[[ 9.00025964e-02 3.96071747e-02 1.83841765e-01 ... 3.95872220e-02
1.25569820e-01 2.15555862e-01]
[ 1.55962542e-01 -3.10300849e-02 1.76772922e-01 ... 1.92474753e-01
2.30574399e-01 2.81707942e-02]
[ 7.83204585e-02 6.53361529e-03 1.27262697e-01 ... 9.97719541e-02
1.28254429e-01 7.55299702e-02]]
[[ 4.41036932e-02 1.35250352e-02 9.87644792e-02 ... 5.89378644e-03
5.23949116e-02 1.00922674e-01]
[ 8.59075040e-02 -1.67027581e-02 9.69351009e-02 ... 1.17763653e-01
9.71239135e-02 2.25218050e-02]
[ 4.34580036e-02 7.62207608e-04 6.37005866e-02 ... 6.14888743e-02
5.96345589e-02 4.72368896e-02]]
……………

Example

hn

Output

运行代码后,你将看到以下输出 −

[
[[[ 2.21408084e-02 1.42750628e-02 9.53067932e-03 -1.22849066e-02
1.78788435e-02 5.99269159e-02 5.65306023e-02 6.42553642e-02
6.56616641e-03 9.80876666e-03 -1.15729487e-02 5.98640442e-02
-7.21173314e-03 -2.78371759e-02 -1.90690923e-02 2.21447181e-02
8.38765781e-03 -1.38521893e-02 -9.06938594e-03 1.21346042e-02
6.06449470e-02 -3.77471633e-02 5.65885007e-02 6.63008019e-02
-7.34188128e-03 6.46054149e-02 3.19911093e-02 4.11194898e-02
4.43960279e-02 4.92892228e-02 1.74766723e-02 3.40303481e-02
-5.23341820e-03 2.68163737e-02 -9.43402853e-03 -4.11836170e-02
1.55221792e-02 -5.05655073e-02 4.24557598e-03 -3.40388380e-02
……………………

Training Modules

Gluon 中的训练模块如下 −

gluon.loss

mxnet.gluon.loss 模块中,Gluon 提供了预定义的损失函数。基本上,它具有用于训练神经网络的损失。这就是它称为训练模块的原因。

Methods and their parameters

以下是 mxnet.gluon.loss 训练模块中涵盖的一些重要方法及其参数:

Methods and its Parameters

Definition

Loss(weight, batch_axis, **kwargs)

这充当损失的基础类。

L2Loss([weight, batch_axis])

它计算 labelprediction(pred) 之间的均方误差 (MSE)。

L1Loss([weight, batch_axis])

它计算 labelpred 之间的平均绝对误差 (MAE)。

SigmoidBinaryCrossEntropyLoss([…])

该方法用于二元分类的交叉熵损失。

SigmoidBCELoss

该方法用于二元分类的交叉熵损失。

SoftmaxCrossEntropyLoss([axis, …])

它计算 softmax 交叉熵损失 (CEL)。

SoftmaxCELoss

它还计算 softmax 交叉熵损失。

KLDivLoss([from_logits, axis, weight, …])

它用于 Kullback-Leibler 散度损失。

CTCLoss([layout, label_layout, weight])

它用于连接主义时间分类损失 (TCL)。

HuberLoss([rho, weight, batch_axis])

它计算平滑的 L1 损失。如果绝对误差超过 rho,平滑的 L1 损失将等于 L1 损失,否则等于 L2 损失。

HingeLoss([margin, weight, batch_axis])

此方法计算通常在 SVM 中使用的铰链损失函数:

SquaredHingeLoss([margin, weight, batch_axis])

此方法计算 SVM 中使用的软边距损失函数:

LogisticLoss([weight, batch_axis, label_format])

此方法计算对数损失。

TripletLoss([margin, weight, batch_axis])

此方法计算给定三个输入张量和正面边距的三元组损失。

PoissonNLLLoss([weight, from_logits, …])

此函数计算负对数似然损失。

CosineEmbeddingLoss([weight, batch_axis, margin])

此函数计算向量间的余弦距离。

SDMLLoss([smoothing_parameter, weight, …])

此方法计算批次平滑深度度量学习 (SDML) 损失,给定两个输入张量和一个平滑权重 SDM 损失。通过将最小批次中不成对的样本用作潜在的反例,它学习成对样本之间的相似性。

Example

我们知道 mxnet.gluon.loss.loss 将计算标签与预测 (pred) 之间的 MSE(均方误差)。通过使用以下公式执行:

mean squared error

gluon.parameter

mxnet.gluon.parameter 是一个包含参数的容器,即块的权重。

Methods and their parameters

mxnet.gluon.parameter 训练模块涵盖的一些重要方法及其参数如下 −

Methods and its Parameters

Definition

cast(dtype)

此方法将把数据和此参数的梯度转换成一个新的数据类型。

data([ctx])

此方法将返回一个在一个上下文中此参数的副本。

grad([ctx])

此方法将返回一个在一个上下文中此参数的梯度缓冲区。

initialize([init, ctx, default_init, …])

此方法将初始化参数和梯度数组。

list_ctx()

此方法将返回一个已在此参数上初始化的上下文列表。

list_data()

此方法将返回一个在所有上下文中此参数的副本。将按照创建顺序执行。

list_grad()

此方法将返回所有上下文的梯度缓冲区。这将按照 values() 的顺序执行。

list_row_sparse_data(row_id)

此方法将返回所有上下文中“行稀疏”参数的副本。将按照创建顺序执行。

reset_ctx(ctx)

此方法将重新分配其他上下文的参数。

row_sparse_data(row_id)

此方法将返回与 'row_id' 相同上下文中“行稀疏”参数的副本。

set_data(data)

此方法将在此参数上的所有上下文中设置值。

var()

此方法将返回一个表示此参数的符号。

zero_grad()

此方法将所有上下文的梯度缓冲区设置为 0。

Implementation Example

在以下示例中,我们将使用 initialize() 方法初始化参数和梯度数组,如下所示:-

weight = mx.gluon.Parameter('weight', shape=(2, 2))
weight.initialize(ctx=mx.cpu(0))
weight.data()

Output

输出如下:

[[-0.0256899 0.06511251]
[-0.00243821 -0.00123186]]
<NDArray 2x2 @cpu(0)>

Example

weight.grad()

Output

输出如下 −

[[0. 0.]
[0. 0.]]
<NDArray 2x2 @cpu(0)>

Example

weight.initialize(ctx=[mx.gpu(0), mx.gpu(1)])
weight.data(mx.gpu(0))

Output

您将看到以下输出 −

[[-0.00873779 -0.02834515]
 [ 0.05484822 -0.06206018]]
<NDArray 2x2 @gpu(0)>

Example

weight.data(mx.gpu(1))

Output

执行以上代码时,应该看到以下输出 −

[[-0.00873779 -0.02834515]
 [ 0.05484822 -0.06206018]]
<NDArray 2x2 @gpu(1)>

gluon.trainer

mxnet.gluon.trainer 对一组参数应用了一个优化器。它应该和 autograd 一起使用。

Methods and their parameters

以下是 mxnet.gluon.trainer 训练模块涵盖的一些重要的方法及参数:-

Methods and its Parameters

Definition

allreduce_grads()

此方法将减少各个参数(权重)上的不同内容的梯度。

load_states(fname)

顾名思义,此方法将加载训练器状态。

save_states(fname)

顾名思义,此方法将保存训练器状态。

set_learning_rate(lr)

此方法将设置优化器的新学习率。

step(batch_size[, ignore_stale_grad])

此方法将执行一次参数更新。它应该在 autograd.backward()record() 范围外调用。

update(batch_size[, ignore_stale_grad])

此方法还会执行一次参数更新。它应该在 autograd.backward()record() 范围外且在 trainer.update() 之后调用。

Data Modules

Gluon 的数据模块在下面有说明:-

gluon.data

Gluon 在 gluon.data 模块中提供大量内置的数据集实用程序。这就是它被称为数据模块的原因。

Classes and their parameters

以下是 mxnet.gluon.data 核心模块涵盖的一些重要的方法及参数。这些方法通常与数据集、采样和 DataLoader 相关。

Methods and its Parameters

Definition

ArrayDataset(*args)

此方法表示结合了两个或两个以上类似数据集的对象(如数据集、列表、数组等)的数据集。

BatchSampler(sampler, batch_size[, last_batch])

此方法封装到另一个 Sampler 上。封装之后,它将返回样本的小批量。

DataLoader(dataset[, batch_size, shuffle, …])

类似于 BatchSampler,但此方法从数据集加载数据。加载之后,它将返回数据的小批量。

这表示抽象数据集类。

FilterSampler(fn, dataset)

此方法表示函数 fn 返回 True 的数据集中的样本元素。

RandomSampler(length)

此方法表示从 [0, length) 中无放回地随机选择样本元素。

RecordFileDataset(filename)

它表示封装 RecordIO 文件上的数据集。该文件扩展名为 .rec

Sampler

这是采样器的基类。

SequentialSampler(length[, start])

它按顺序表示集合 [start, start + length) 中的采样元素。

它按顺序表示集合 [start, start + length) 中的采样元素。

Implementation Examples

在以下示例中,我们将使用 gluon.data.BatchSampler() API,它包装另一个采样器。它返回批量迷你采样。

import mxnet as mx
from mxnet.gluon import data
sampler = mx.gluon.data.SequentialSampler(15)
batch_sampler = mx.gluon.data.BatchSampler(sampler, 4, 'keep')
list(batch_sampler)

Output

输出如下:

[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14]]

gluon.data.vision.datasets

Gluon 在 gluon.data.vision.datasets 模块中提供了大量的预定义视觉数据集函数。

Classes and their parameters

MXNet 为我们提供了有用且重要的数据集,其类和参数如下所示——

Classes and its Parameters

Definition

MNIST([root, train, transform])

这是一个有用的数据集,为我们提供了手写数字。MNIST 数据集的 URL 为 [role="bare"] [role="bare"]http://yann.lecun.com/exdb/mnist

FashionMNIST([root, train, transform])

该数据集包含 Zalando 的包含时尚产品的商品图片。它是原始 MNIST 数据集的直接替代品。您可以从 [role="bare"] [role="bare"]https://github.com/zalandoresearch/fashion-mnist 获取此数据集

CIFAR10([root, train, transform])

这是一个来自 [role="bare"] [role="bare"]https://www.cs.toronto.edu/~kriz/cifar.html 的图像分类数据集。在该数据集中,每个样本都是一个形状为 (32, 32, 3) 的图像。

CIFAR100([root, fine_label, train, transform])

这是一个来自 [role="bare"] [role="bare"]https://www.cs.toronto.edu/~kriz/cifar.html 的 CIFAR100 图像分类数据集。它还有每个样本,都是一个形状为 (32, 32, 3) 的图像。

ImageRecordDataset (filename[, flag, transform])

该数据集包装在一个包含图像的 RecordIO 文件之上。在该数据集中,每个样本都是一个图像及其对应的标签。

ImageFolderDataset (root[, flag, transform])

这是一个用于加载存储在文件夹结构中的图像文件的数据集。

ImageListDataset ([root, imglist, flag])

这是一个用于加载由条目列表指定图像文件的数据集。

Example

在以下示例中,我们将展示 ImageListDataset() 的用法,它用于加载由条目列表指定图像文件——

# written to text file *.lst

0 0 root/cat/0001.jpg
1 0 root/cat/xxxa.jpg
2 0 root/cat/yyyb.jpg
3 1 root/dog/123.jpg
4 1 root/dog/023.jpg
5 1 root/dog/wwww.jpg

# A pure list, each item is a list [imagelabel: float or list of float, imgpath]

[[0, root/cat/0001.jpg]
[0, root/cat/xxxa.jpg]
[0, root/cat/yyyb.jpg]
[1, root/dog/123.jpg]
[1, root/dog/023.jpg]
[1, root/dog/wwww.jpg]]

Utility Modules

Gluon 中的实用程序模块如下——

gluon.utils

Gluon 在 gluon.utils 模块中提供了大量的内置并行化实用程序优化器。它提供了用于训练的各种实用程序。这就是它被称为实用程序模块的原因。

Functions and their parameters

以下是该实用程序模块中包含的功能及其参数,该模块名为 gluon.utils −

Functions and its Parameters

Definition

split_data(data, num_slice[, batch_axis, …])

此功能通常用于数据并行化,并且每个切片都会发送到一个设备,即 GPU。它将 NDArray 分割为 num_slice *slices along *batch_axis

split_and_load(data, ctx_list[, batch_axis, …])

此功能将 NDArray 分割为 len(ctx_list) 个沿 batch_axis. 的切片。与上述 split_data () 功能的唯一区别在于,它还将每个切片加载到 ctx_list 中的一个上下文中。

clip_global_norm(arrays, max_norm[, …])

此功能的工作是按比例缩放 NDArray,使其 2 范数之和小于 max_norm

check_sha1(filename, sha1_hash)

此函数将检查文件内容的 sha1 哈希是否与预期哈希匹配。

download(url[, path, overwrite, sha1_hash, … ])

与名称所述一样,此函数将下载某个 URL。

replace_file(src, dst)

该函数将实现原子审计 os.replace 。这将通过 Linux 和 OSX 来完成。