Files
paddlepaddle--paddle/test/dygraph_to_static/test_resnet_amp.py
T
2026-07-13 12:40:42 +08:00

142 lines
4.7 KiB
Python

# 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_utils import (
Dy2StTestBase,
enable_to_static_guard,
test_default_mode_only,
)
from test_resnet import SEED, ResNet, optimizer_setting
import paddle
from paddle.base import core
# NOTE: Reduce batch_size from 8 to 2 to avoid unittest timeout.
batch_size = 2
epoch_num = 1
place = (
paddle.CUDAPlace(0) if paddle.is_compiled_with_cuda() else paddle.CPUPlace()
)
if paddle.is_compiled_with_cuda():
paddle.set_flags({'FLAGS_cudnn_deterministic': True})
def train(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 = paddle.jit.to_static(ResNet(), build_strategy=build_strategy)
optimizer = optimizer_setting(parameter_list=resnet.parameters())
scaler = paddle.amp.GradScaler(init_loss_scaling=1024)
for epoch in range(epoch_num):
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():
pred = resnet(img)
# FIXME(Aurelius84): The following cross_entropy seems to bring out a
# precision problem, need to figure out the underlying reason.
# If we remove it, the loss between dygraph and dy2stat is exactly same.
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()
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(
f"epoch {epoch} | batch step {batch_id}, "
f"loss {total_loss.numpy() / total_sample:0.3f}, "
f"acc1 {total_acc1.numpy() / total_sample:0.3f}, "
f"acc5 {total_acc5.numpy() / total_sample:0.3f}, "
f"time {end_time - start_time:f}"
)
if batch_id == 10:
break
return total_loss.numpy()
class TestResnet(Dy2StTestBase):
def train(self, to_static: bool):
with enable_to_static_guard(to_static):
return train()
@test_default_mode_only
def test_resnet(self):
static_loss = self.train(to_static=True)
dygraph_loss = self.train(to_static=False)
np.testing.assert_allclose(
static_loss,
dygraph_loss,
rtol=1e-05,
err_msg=f'static_loss: {static_loss} \n dygraph_loss: {dygraph_loss}',
)
@test_default_mode_only
def test_resnet_composite(self):
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)
np.testing.assert_allclose(
static_loss,
dygraph_loss,
rtol=1e-05,
err_msg=f'static_loss: {static_loss} \n dygraph_loss: {dygraph_loss}',
)
if __name__ == '__main__':
unittest.main()