# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import time import unittest import numpy as np from dygraph_to_static_util import test_and_compare_with_new_ir from test_resnet import SEED, ResNet, optimizer_setting import paddle from paddle import fluid from paddle.fluid import core # NOTE: Reduce batch_size from 8 to 2 to avoid unittest timeout. batch_size = 2 epoch_num = 1 if fluid.is_compiled_with_cuda(): fluid.set_flags({'FLAGS_cudnn_deterministic': True}) def train(to_static, build_strategy=None): """ Tests model decorated by `dygraph_to_static_output` in static graph mode. For users, the model is defined in dygraph mode and trained in static graph mode. """ np.random.seed(SEED) paddle.seed(SEED) paddle.framework.random._manual_program_seed(SEED) resnet = ResNet() if to_static: resnet = paddle.jit.to_static(resnet, build_strategy=build_strategy) optimizer = optimizer_setting(parameter_list=resnet.parameters()) scaler = paddle.amp.GradScaler(init_loss_scaling=1024) resnet, optimizer = paddle.amp.decorate( models=resnet, optimizers=optimizer, level='O2', save_dtype='float32' ) for epoch in range(epoch_num): loss_data = [] total_loss = 0.0 total_acc1 = 0.0 total_acc5 = 0.0 total_sample = 0 for batch_id in range(100): start_time = time.time() img = paddle.to_tensor( np.random.random([batch_size, 3, 224, 224]).astype('float32') ) label = paddle.to_tensor( np.random.randint(0, 100, [batch_size, 1], dtype='int64') ) img.stop_gradient = True label.stop_gradient = True with paddle.amp.auto_cast( enable=True, custom_white_list=None, custom_black_list=None, level='O2', ): pred = resnet(img) loss = paddle.nn.functional.cross_entropy( input=pred, label=label, reduction='none', use_softmax=False ) avg_loss = paddle.mean(x=pred) acc_top1 = paddle.static.accuracy(input=pred, label=label, k=1) acc_top5 = paddle.static.accuracy(input=pred, label=label, k=5) scaled = scaler.scale(avg_loss) scaled.backward() scaler.minimize(optimizer, scaled) resnet.clear_gradients() loss_data.append(float(avg_loss)) total_loss += avg_loss total_acc1 += acc_top1 total_acc5 += acc_top5 total_sample += 1 end_time = time.time() if batch_id % 2 == 0: print( "epoch %d | batch step %d, loss %0.3f, acc1 %0.3f, acc5 %0.3f, time %f" % ( epoch, batch_id, total_loss.numpy() / total_sample, total_acc1.numpy() / total_sample, total_acc5.numpy() / total_sample, end_time - start_time, ) ) if batch_id == 10: break return loss_data class TestResnet(unittest.TestCase): def train(self, to_static): paddle.jit.enable_to_static(to_static) build_strategy = paddle.static.BuildStrategy() # Why set `build_strategy.enable_inplace = False` here? # Because we find that this PASS strategy of PE makes dy2st training loss unstable. build_strategy.enable_inplace = False return train(to_static, build_strategy) @test_and_compare_with_new_ir(False) def test_resnet(self): if fluid.is_compiled_with_cuda(): static_loss = self.train(to_static=True) dygraph_loss = self.train(to_static=False) # NOTE: In pure fp16 training, loss is not stable, so we enlarge atol here. np.testing.assert_allclose( static_loss, dygraph_loss, rtol=1e-05, atol=0.001, err_msg='static_loss: {} \n dygraph_loss: {}'.format( static_loss, dygraph_loss ), ) def test_resnet_composite(self): if fluid.is_compiled_with_cuda(): core._set_prim_backward_enabled(True) static_loss = self.train(to_static=True) core._set_prim_backward_enabled(False) dygraph_loss = self.train(to_static=False) # NOTE: In pure fp16 training, loss is not stable, so we enlarge atol here. np.testing.assert_allclose( static_loss, dygraph_loss, rtol=1e-05, atol=0.001, err_msg='static_loss: {} \n dygraph_loss: {}'.format( static_loss, dygraph_loss ), ) if __name__ == '__main__': unittest.main()