6. 分布式指标

6.1. 简介

分布式指标是指在分布式训练任务中用以评测模型效果的指标。它和单机模型评测指标的区别在于,单机指标仅评测当前节点的测试数据,而分布式指标需评测所有节点的全量测试数据。

6.2. 原理

分布式指标的计算一般包含三步,下面我们以分布式准确率为例介绍整个过程。

  1. 初始化分布式训练环境

    import paddle.distributed.fleet as fleet
    fleet.init()
    
  2. 定义指标计算需要的所有中间状态统计值,每个训练节点统计各自的状态值。准确率计算需要样本总数和正确分类的样本数两个统计值。

    ...
    pred, label = model()
    
    # 1. 定义中间状态统计值,样本总数和正确分类的样本数
    correct_cnt = paddle.static.create_global_var(name="right_cnt", persistable=True, dtype='float32', shape=[1], value=0)
    total_cnt = paddle.static.create_global_var(name="total_cnt", persistable=True, dtype='float32', shape=[1], value=0)
    
    # 2. 训练节点自己的状态统计
    batch_cnt = paddle.sum(
        paddle.full(shape=[paddle.shape(label)[0], 1], fill_value=1.0))
    batch_accuracy = paddle.static.accuracy(input=pred, label=label)
    batch_correct = batch_cnt * batch_accuracy
    
    paddle.assign(correct_cnt + batch_correct, correct_cnt)
    paddle.assign(total_cnt + batch_cnt, total_cnt)
    accuracy = correct_cnt / total_cnt
    
  3. 所有训练节点间进行 all_reduce 操作,获取全局统计值,然后根据指标计算公式,计算全局指标。

    global_cnt = fleet.metrics.sum(total_cnt)
    global_correct = fleet.metrics.sum(corrent_cnt)
    global_accuracy = float(global_correct) / float(global_cnt)
    

6.3. 分布式指标

为方便使用,Paddle在 paddle.distributed.metrics 下将常见的一些指标计算进行了封装,下面对这些API的功能及参数进行说明,并提供用法示例。

6.3.1. 分布式AUC

paddle.distributed.fleet.metrics.auc(stat_pos, stat_neg, scope=None, util=None)

分布式AUC(Area Under the Curve)。AUC 是一个二分类任务中常用的效果评价指标,指ROC曲线和横坐标轴之间的面积,该值介于0~1之间,越大代表分类器效果越好。

参数:

  • stat_pos, (numpy.array|Tensor|string, required): 单机正样例中间统计结果,即单机 paddle.static.aucstat_pos 输出。

  • stat_neg, (numpy.array|Tensor|string, required): 单机负样例中间统计结果,即单机 paddle.static.aucstat_neg 输出。

  • scope, (Scope, optional),作用域,若为None,则使用全局/默认作用域,默认为None。

  • util, (UtilBase, optinal),分布式训练工具类,若为None,则使用默认工具类 fleet.util, 默认为None。

用法示例:

...
pred, label = model()

# 1. 单机组网阶段,计算正负样例中间统计结果。
auc, batch_auc, [batch_stat_pos, batch_stat_neg, stat_pos, stat_neg] = \
    paddle.static.auc(input=pred, label=label)

# 2. 分布式训练阶段,计算全局AUC。
global_auc = fleet.metrics.auc(stat_pos, stat_neg)

6.3.2. 分布式Accuracy

paddle.distributed.fleet.metrics.acc(correct, total, scope=None, util=None)

分布式准确率。准确率(Accuracy)是分类任务中常用的一个效果评价指标。通过比对预测标签和实际标签是否一致,从而计算模型的分类效果,公式如下:

\[accuracy = \frac{correct}{total}\]

其中,correct 是预测标签等于真实标签的样本总数,total 是全部样本总数。

参数:

  • correct, (numpy.array|Tensor|string, required): 单机预测标签等于真实标签的样本总数。

  • total, (numpy.array|Tensor|string, required): 单机样本总数。

  • scope, (Scope, optional),作用域,若为None,则使用全局/默认作用域,默认为None。

  • util, (UtilBase, optinal),分布式训练工具类,若为None,则使用默认工具类 fleet.util, 默认为None。

用法示例:

...
pred, label = model()

# 1. 单机组网阶段,计算样本总数和预测正确的样本数
correct_cnt = paddle.static.create_global_var(name="right_cnt", persistable=True, dtype='float32', shape=[1], value=0)
total_cnt = paddle.static.create_global_var(name="total_cnt", persistable=True, dtype='float32', shape=[1], value=0)

batch_cnt = paddle.sum(
    paddle.full(shape=[paddle.shape(label)[0], 1], fill_value=1.0))
batch_accuracy = paddle.static.accuracy(input=pred, label=label)
batch_correct = batch_cnt * batch_accuracy

paddle.assign(correct_cnt + batch_correct, correct_cnt)
paddle.assign(total_cnt + batch_cnt, total_cnt)
accuracy = correct_cnt / total_cnt

# 2. 分布式训练阶段,计算全局准确率。
global_accuracy = fleet.metrics.acc(correct_cnt, total_cnt)

6.3.3. 分布式MAE

paddle.distributed.fleet.metrics.mae(abserr, total_ins_num, scope=None, util=None)

分布式平均绝对误差(Mean Absolute Error)。平均绝对误差是绝对误差的平均值,一般用于计算 loss 损失值。

\[ \begin{align}\begin{aligned}abserr &= \sum |input - label|\\mae &= \frac{abserr}{total\_ins\_num}\end{aligned}\end{align} \]

其中,input 是样本预测结果, label 是样本真实标签,abserr 为绝对误差和,total_ins_num 是样本总数。

参数:

  • abserr, (numpy.array|Tensor|string, required): 单机绝对误差和统计值。

  • total_ins_num, (numpy.array|Tensor|string, required): 单机样本总数。

  • scope, (Scope, optional),作用域,若为None,则使用全局/默认作用域,默认为None。

  • util, (UtilBase, optinal),分布式训练工具类,若为None,则使用默认工具类 fleet.util, 默认为None。

用法示例:

...
pred, label = model()

# 1. 单机组网阶段,计算绝对误差和样本总数
abserr = paddle.static.create_global_var(name="abserr", persistable=True, dtype='float32', shape=[1], value=0)
total_cnt = paddle.static.create_global_var(name="total_cnt", persistable=True, dtype='float32', shape=[1], value=0)

batch_cnt = paddle.sum(
    paddle.full(shape=[paddle.shape(label)[0], 1], fill_value=1.0))
batch_abserr = paddle.nn.functional.l1_loss(pred, label, reduction='sum')

paddle.assign(abserr + batch_abserr, abserr)
paddle.assign(total_cnt + batch_cnt, total_cnt)
mae = abserr / total_cnt

# 2. 分布式训练阶段,计算全局准确率。
global_mae = fleet.metrics.mae(abserr, total_cnt)

6.3.4. 分布式MSE

paddle.distributed.fleet.metrics.mse(sqrerr, ins_num, scope=None, util=None)

分布式均方误差(Mean Squared Error)。均方误差是误差平方和的平均值,一般用于计算 loss 损失值。

\[ \begin{align}\begin{aligned}sqrerr &= \sum (input - label)^2\\mse &= \frac{sqrerr}{total\_ins\_num}\end{aligned}\end{align} \]

其中,input 是样本预测结果, label 是样本真实标签,sqrerr 为平方误差和,total_ins_num 是样本总数。

参数:

  • sqrerr, (numpy.array|Tensor|string, required): 单机平方误差和统计值。

  • total_ins_num, (numpy.array|Tensor|string, required): 单机样本总数。

  • scope, (Scope, optional),作用域,若为None,则使用全局/默认作用域,默认为None。

  • util, (UtilBase, optinal),分布式训练工具类,若为None,则使用默认工具类 fleet.util, 默认为None。

用法示例:

...
pred, label = model()

# 1. 单机组网阶段,计算平方误差和样本总数
sqrerr = paddle.static.create_global_var(name="sqrerr", persistable=True, dtype='float32', shape=[1], value=0)
total_cnt = paddle.static.create_global_var(name="total_cnt", persistable=True, dtype='float32', shape=[1], value=0)

batch_cnt = paddle.sum(
    paddle.full(shape=[paddle.shape(label)[0], 1], fill_value=1.0))
batch_sqrerr = paddle.nn.functional.mse_loss(pred, label, reduction='sum')

paddle.assign(sqrerr + batch_sqrerr, sqrerr)
paddle.assign(total_cnt + batch_cnt, total_cnt)
mse =  sqrerr / total_cnt

# 2. 分布式训练阶段,计算全局准确率。
global_mse = fleet.metrics.mse(sqrerr, total_cnt)

6.3.5. 分布式RMSE

paddle.distributed.fleet.metrics.rmse(sqrerr, total_ins_num, scope=None, util=None)

分布式均方根误差(Root Mean Squared Error)。均方根误差是均方误差的算术平方根,亦称标准误差,一般用于计算 loss 损失值。

\[ \begin{align}\begin{aligned}sqrerr &= \sum (input - label)^2\\rmse &= \sqrt{\frac{sqrerr}{total\_ins\_num}}\end{aligned}\end{align} \]

其中,input 是样本预测结果, label 是样本真实标签,sqrerr 为平方误差和,total_ins_num 是样本总数。

参数:

  • sqrerr, (numpy.array|Tensor|string, required): 单机平方误差和统计值。

  • total_ins_num, (numpy.array|Tensor|string, required): 单机样本总数。

  • scope, (Scope, optional),作用域,若为None,则使用全局/默认作用域,默认为None。

  • util, (UtilBase, optinal),分布式训练工具类,若为None,则使用默认工具类 fleet.util, 默认为None。

用法示例:

...
pred, label = model()

# 1. 单机组网阶段,计算平方误差和样本总数
sqrerr = paddle.static.create_global_var(name="sqrerr", persistable=True, dtype='float32', shape=[1], value=0)
total_cnt = paddle.static.create_global_var(name="total_cnt", persistable=True, dtype='float32', shape=[1], value=0)

batch_cnt = paddle.sum(
    paddle.full(shape=[paddle.shape(label)[0], 1], fill_value=1.0))
batch_sqrerr = paddle.nn.functional.mse_loss(pred, label, reduction='sum')

paddle.assign(sqrerr + batch_sqrerr, sqrerr)
paddle.assign(total_cnt + batch_cnt, total_cnt)
mse =  sqrerr / total_cnt
rmse = paddle.sqrt(mse)

# 2. 分布式训练阶段,计算全局准确率。
global_rmse = fleet.metrics.rmse(sqrerr, total_cnt)

6.3.6. 分布式Sum

paddle.distributed.fleet.metrics.sum(input, scope=None, util=None)

分布式求和。一般用于自定义指标计算。

参数:

  • input, (numpy.array|Tensor|string, required),需要分布式求和的输入参数。

  • scope, (Scope, optional),作用域,若为None,则使用全局/默认作用域,默认为None。

  • util, (UtilBase, optinal),分布式训练工具类,若为None,则使用默认工具类 fleet.util, 默认为None。

用法示例:

...
# 1. 单机组网阶段,计算Loss
loss = model()

# 2. 分布式训练阶段,计算全局Loss和
loss_val, = exe.run(paddle.static.default_main_program(),
                    fetch_list=[loss.name])
loss_sum = fleet.metrics.sum(loss_val)

6.3.7. 分布式Max

paddle.distributed.fleet.metrics.max(input, scope=None, util=None)

分布式求最大值。一般用于自定义指标计算。

参数:

  • input, (numpy.array|Tensor|string, required),需要分布式求最大值的输入参数。

  • scope, (Scope, optional),作用域,若为None,则使用全局/默认作用域,默认为None。

  • util, (UtilBase, optinal),分布式训练工具类,若为None,则使用默认工具类 fleet.util, 默认为None。

用法示例:

...
# 1. 单机组网阶段,计算Loss
loss = model()

# 2. 分布式训练阶段,计算全局最大Loss
loss_val, = exe.run(paddle.static.default_main_program(),
                    fetch_list=[loss.name])
max_loss = paddle.metrics.max(loss_val)

6.3.8. 分布式Min

paddle.distributed.fleet.metrics.min(input, scope=None, util=None)

分布式求最小值。一般用于自定义指标计算。

参数:

  • input, (numpy.array|Tensor|string, required),需要分布式求最大值的输入参数。

  • scope, (Scope, optional),作用域,若为None,则使用全局/默认作用域,默认为None。

  • util, (UtilBase, optinal),分布式训练工具类,若为None,则使用默认工具类 fleet.util, 默认为None。

用法示例:

...
# 1. 单机组网阶段
loss = model()

# 2. 分布式训练阶段,计算全局最小Loss
loss_val, = exe.run(paddle.static.default_main_program(),
                    fetch_list=[loss.name])
min_loss = fleet.metrics.min(loss_val)

6.4. 使用方法

完整运行示例见 examples/wide_and_deep

通过fleetrun指令运行分布式任务。命令示例如下,其中server_num, worker_num分别为服务节点和训练节点的数量。

fleetrun --server_num=2 --worker_num=2 train.py