PaddlePaddle / Paddle

PArallel Distributed Deep LEarning: Machine Learning Framework from Industrial Practice (『飞桨』核心框架,深度学习&机器学习高性能单机、分布式训练和跨平台部署)
http://www.paddlepaddle.org/
Apache License 2.0
22.13k stars 5.55k forks source link

GPU多卡情况下加载模型评估结果有误 #16556

Closed Ashleychen closed 4 years ago

Ashleychen commented 5 years ago

我在GPU多卡下的模型预测结果有问题。 我在模型训练的时候每隔n个batch会用测试数据评估一下,假设这个时候模型的预测值为A; 然后在模型训练完成之后我想重新加载模型再次用同样的测试数据评估,然后这个时候模型的预测值为B; 但是我发现 GPU单卡的情况下B==A;GPU多卡的情况下B!=A。 而且很奇怪的是,多卡的情况下,一个batch里面前半部分的预测结果是对的,而后半部分的预测结果是错的。

luotao1 commented 5 years ago

我在模型训练的时候每隔n个batch会用测试数据评估一下,假设这个时候模型的预测值为A; 然后在模型训练完成之后我想重新加载模型再次用同样的测试数据评估,然后这个时候模型的预测值为B

这两个阶段模型就不一样了,预测值一样,但预测的分数肯定不一样。

GPU单卡的情况下B==A;GPU多卡的情况下B!=A。

如果模型已经收敛到一个固定值,预测值和预测分数会一样。所以GPU单卡是收敛了,GPU多卡是未收敛情况?请补充更多信息。

多卡的情况下,一个batch里面前半部分的预测结果是对的,而后半部分的预测结果是错的。

你是用什么规则来判断对还是错呢?用B!=A么?

Ashleychen commented 5 years ago

我指的是,训练的时候训2个batch我就把模型保存下来,但是重新加载这个模型来评估的时候模型的预测结果跟我当时保存它的时候不一致。 因为我保存模型参数的时候和我重新加载模型参数进行评估的时候,我都用同一份测试数据进行预测,按道理模型参数一致,测试数据一致,预测结果也应该一致。

luotao1 commented 5 years ago

两个预测数据差多少,是用python预测的么?用什么api接口进行保存和加载模型的呢?

Ashleychen commented 5 years ago

image 这是我测一个batch的数据,预测结果有两维,左边的是加载模型之后的预测结果,右边的是保存模型时的预测结果,如图所示前17个分数是一致的,从第18个结果开始就不一致了。 用的是Python预测的,用fluid.io.load_params加载模型,用fluid.io.save_params保存模型。

luotao1 commented 5 years ago

python预测接口是load_inference_model和save_inference_model. 需要把program desc即model保存下来。

Ashleychen commented 5 years ago

所以是因为接口用错了吗

luotao1 commented 5 years ago

http://paddlepaddle.org/documentation/docs/zh/1.3/api_guides/low_level/inference.html 用预测接口保存吧。

Ashleychen commented 5 years ago

http://paddlepaddle.org/documentation/docs/zh/1.3/api_guides/low_level/inference.html 用预测接口保存吧。

这个借口有参数为parallelExecutor的示例吗。

def save_inference_model(self, model_path):
        if model_path != '':
            if not exists(model_path):
                os.makedirs(model_path)
                fluid.io.save_inference_model(
                        dirname=model_path,
                        feeded_var_names=self.conf.inference_var_names,
                        target_vars=self.test_outputs,
                        executor=self.test_exe,
                        main_program=self.test_program)
                logging.info("Saving model: %s succeeds." % model_path)

def load_inference_model(self, model_path):
        if model_path != '':
            assert exists(model_path), (model_path, 'does not exists')
            [inference_program, feed_target_names, fetch_targets] = \
                    fluid.io.load_inference_model(
                            dirname=model_path,
                            executor=self.exe)
                    return inference_program, feed_target_names, fetch_targets

我使用时传给executor的不是parallelExecutor,在只用一张卡的情况下的OK的,但是多卡的情况下评估还是有点问题,只predict了一部分的结果。

luotao1 commented 5 years ago

示例是https://github.com/PaddlePaddle/models/blob/8a6f5942bd8676003ed9f1be2f494996d3a23ede/fluid/PaddleRec/gnn/train.py 但executor和parallelExecutor,是一样的用法。

Ashleychen commented 5 years ago

目前这个问题还没有解决,而且我现在test program还需要在线训练,所以我现在用了save_persistables和load_persistables这两个api,我检查了以下几种情况的预测结果,分别是:

  1. 训练过程中
  2. 保存模型后重新加载参数,然后用单卡预测
  3. 保存模型后重新加载参数,然后用多卡预测
  4. 保存模型后重新加载参数,然后用单cpu预测
  5. 保存模型后重新加载参数,然后用多cpu预测 这几种情况下的结果都不一致。 以下截图分别是我如何调用save_persistables和load_persistables,执行test program。 image image
Superjomn commented 5 years ago

executor 是用的哪个? ParallelExecutor ?

保存模型后重新加载参数,然后用单卡预测 保存模型后重新加载参数,然后用多卡预测 保存模型后重新加载参数,然后用单cpu预测 保存模型后重新加载参数,然后用多cpu预测

建议离线使用; 在线训练使用单卡,不要用多卡预测。

Ashleychen commented 5 years ago

image image 为什么在线训练的时候只能使用单卡呢?

Superjomn commented 5 years ago

单卡预测

Superjomn commented 5 years ago

可以多线程多卡(单卡1线程)预测

paddle-bot-old[bot] commented 4 years ago

Since you haven\'t replied for more than a year, we have closed this issue/pr. If the problem is not solved or there is a follow-up one, please reopen it at any time and we will continue to follow up. 由于您超过一年未回复,我们将关闭这个issue/pr。 若问题未解决或有后续问题,请随时重新打开,我们会继续跟进。