chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:42 +08:00
commit e25996e7db
15472 changed files with 3536181 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
file(
GLOB TEST_OPS
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
"test_*.py")
string(REPLACE ".py" "" TEST_OPS "${TEST_OPS}")
list(REMOVE_ITEM TEST_OP test_resnet_cinn test_resnet_prim_cinn
test_prim_simplenet_cinn)
foreach(TEST_OP ${TEST_OPS})
py_test_modules(${TEST_OP} MODULES ${TEST_OP} ENVS ${GC_ENVS})
endforeach()
set_tests_properties(test_resnet_prim PROPERTIES TIMEOUT 850)
set_tests_properties(test_bert_prim PROPERTIES TIMEOUT 500)
if(WITH_CINN)
set_tests_properties(test_bert_cinn PROPERTIES TIMEOUT 500)
set_tests_properties(test_bert_prim_cinn PROPERTIES TIMEOUT 500)
set_tests_properties(test_resnet_prim PROPERTIES LABELS "RUN_TYPE=CINN")
set_tests_properties(test_bert_prim PROPERTIES LABELS "RUN_TYPE=CINN")
set_tests_properties(test_bert_cinn PROPERTIES LABELS "RUN_TYPE=CINN")
set_tests_properties(test_bert_prim_cinn PROPERTIES LABELS "RUN_TYPE=CINN")
endif()
+919
View File
@@ -0,0 +1,919 @@
# Copyright (c) 2023 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.
from __future__ import annotations
import functools
import warnings
import numpy as np
import paddle
import paddle.nn.functional as F
from paddle import Tensor, nn
from paddle.base.data_feeder import convert_dtype
from paddle.distributed.fleet.utils import recompute
from paddle.io import DataLoader, Dataset
from paddle.nn import MultiHeadAttention
try:
from paddle.incubate.nn import FusedTransformerEncoderLayer
except ImportError:
FusedTransformerEncoderLayer = None
VOCAB_SIZE = 30522
class Stack:
def __init__(self, axis=0, dtype=None):
self._axis = axis
self._dtype = dtype
def __call__(self, data):
data = (
np.stack(data, axis=self._axis).astype(self._dtype)
if self._dtype
else np.stack(data, axis=self._axis)
)
return data
def is_tensor(x):
if isinstance(x, paddle.Tensor):
return True
return isinstance(x, np.ndarray)
class BertConfig:
def __init__(self):
self.attention_probs_dropout_prob = 0.1
self.fuse = False
self.hidden_act = 'gelu'
self.hidden_dropout_prob = 0.1
# Decrease config to speed up unittest
# self.hidden_size = 768
self.hidden_size = 60
self.initializer_range = 0.02
self.intermediate_size = 3072
self.layer_norm_eps = 1e-12
self.max_position_embeddings = 512
self.model_type = 'bert'
# self.num_attention_heads = 12
self.num_attention_heads = 6
# self.num_hidden_layers = 12
self.num_hidden_layers = 6
self.pad_token_id = 0
self.paddlenlp_version = None
self.pool_act = 'tanh'
self.type_vocab_size = 2
self.vocab_size = VOCAB_SIZE
self.use_return_dict = False
self.output_hidden_states = False
self.output_attentions = False
self.use_cache = False
class BertLMPredictionHead(nn.Layer):
def __init__(self, config: BertConfig, embedding_weights=None):
super().__init__()
self.transform = nn.Linear(config.hidden_size, config.hidden_size)
self.activation = getattr(nn.functional, config.hidden_act)
self.layer_norm = nn.LayerNorm(config.hidden_size)
self.decoder_weight = (
self.create_parameter(
shape=[config.vocab_size, config.hidden_size],
dtype=self.transform.weight.dtype,
is_bias=False,
)
if embedding_weights is None
else embedding_weights
)
self.decoder_bias = self.create_parameter(
shape=[config.vocab_size],
dtype=self.decoder_weight.dtype,
is_bias=True,
)
def forward(self, hidden_states, masked_positions=None):
if masked_positions is not None:
hidden_states = paddle.reshape(
hidden_states, [-1, hidden_states.shape[-1]]
)
hidden_states = paddle.tensor.gather(
hidden_states, masked_positions
)
# gather masked tokens might be more quick
hidden_states = self.transform(hidden_states)
hidden_states = self.activation(hidden_states)
hidden_states = self.layer_norm(hidden_states)
hidden_states = (
paddle.tensor.matmul(
hidden_states, self.decoder_weight, transpose_y=True
)
+ self.decoder_bias
)
return hidden_states
class BertPretrainingHeads(nn.Layer):
def __init__(self, config: BertConfig, embedding_weights=None):
super().__init__()
self.predictions = BertLMPredictionHead(config, embedding_weights)
self.seq_relationship = nn.Linear(config.hidden_size, 2)
def forward(self, sequence_output, pooled_output, masked_positions=None):
prediction_scores = self.predictions(sequence_output, masked_positions)
seq_relationship_score = self.seq_relationship(pooled_output)
return prediction_scores, seq_relationship_score
class BertEmbeddings(nn.Layer):
def __init__(self, config: BertConfig):
super().__init__()
self.word_embeddings = nn.Embedding(
config.vocab_size, config.hidden_size
)
self.position_embeddings = nn.Embedding(
config.max_position_embeddings, config.hidden_size
)
self.token_type_embeddings = nn.Embedding(
config.type_vocab_size, config.hidden_size
)
self.layer_norm = nn.LayerNorm(config.hidden_size)
self.dropout = nn.Dropout(config.hidden_dropout_prob)
def forward(
self,
input_ids: Tensor,
token_type_ids: Tensor | None = None,
position_ids: Tensor | None = None,
past_key_values_length: int | None = None,
):
if position_ids is None:
ones = paddle.ones_like(input_ids, dtype="int64")
seq_length = paddle.cumsum(ones, axis=-1)
position_ids = seq_length - ones
if past_key_values_length is not None:
position_ids += past_key_values_length
position_ids.stop_gradient = True
if token_type_ids is None:
token_type_ids = paddle.zeros_like(input_ids, dtype="int64")
input_embeddings = self.word_embeddings(input_ids)
position_embeddings = self.position_embeddings(position_ids)
token_type_embeddings = self.token_type_embeddings(token_type_ids)
embeddings = (
input_embeddings + position_embeddings + token_type_embeddings
)
embeddings = self.layer_norm(embeddings)
embeddings = self.dropout(embeddings)
return embeddings
class BertPooler(nn.Layer):
def __init__(self, config: BertConfig):
super().__init__()
self.dense = nn.Linear(config.hidden_size, config.hidden_size)
self.activation = nn.Tanh()
self.pool_act = config.pool_act
def forward(self, hidden_states):
# We "pool" the model by simply taking the hidden state corresponding
# to the first token.
first_token_tensor = hidden_states[:, 0]
pooled_output = self.dense(first_token_tensor)
if self.pool_act == "tanh":
pooled_output = self.activation(pooled_output)
return pooled_output
class BertModel(nn.Layer):
def __init__(self, config: BertConfig, to_static, enable_cinn):
super().__init__()
self.config = config
self.pad_token_id = config.pad_token_id
self.initializer_range = config.initializer_range
self.embeddings = BertEmbeddings(config)
if config.fuse and FusedTransformerEncoderLayer is None:
warnings.warn(
"FusedTransformerEncoderLayer is not supported by the running Paddle. "
"The flag fuse_transformer will be ignored. Try Paddle >= 2.3.0"
)
self.fuse = config.fuse and FusedTransformerEncoderLayer is not None
if self.fuse:
self.encoder = nn.LayerList(
[
FusedTransformerEncoderLayer(
config.hidden_size,
config.num_attention_heads,
config.intermediate_size,
dropout_rate=config.hidden_dropout_prob,
activation=config.hidden_act,
attn_dropout_rate=config.attention_probs_dropout_prob,
act_dropout_rate=0.0,
)
for _ in range(config.num_hidden_layers)
]
)
else:
encoder_layer = nn.TransformerEncoderLayer(
config.hidden_size,
config.num_attention_heads,
config.intermediate_size,
dropout=config.hidden_dropout_prob,
activation=config.hidden_act,
attn_dropout=config.attention_probs_dropout_prob,
act_dropout=0,
)
self.encoder = nn.TransformerEncoder(
encoder_layer, config.num_hidden_layers
)
if to_static:
backend = "CINN" if enable_cinn else None
self.encoder = paddle.jit.to_static(
self.encoder, None, backend=backend, full_graph=True
)
self.pooler = BertPooler(config)
# self.apply(self.init_weights)
def get_input_embeddings(self):
return self.embeddings.word_embeddings
def set_input_embeddings(self, value):
self.embeddings.word_embeddings = value
def forward(
self,
input_ids: Tensor,
token_type_ids: Tensor | None = None,
position_ids: Tensor | None = None,
attention_mask: Tensor | None = None,
past_key_values: tuple[tuple[Tensor]] | None = None,
use_cache: bool | None = None,
output_hidden_states: bool | None = None,
output_attentions: bool | None = None,
return_dict: bool | None = None,
):
return_dict = (
return_dict
if return_dict is not None
else self.config.use_return_dict
)
output_hidden_states = (
output_hidden_states
if output_hidden_states is not None
else self.config.output_hidden_states
)
output_attentions = (
output_attentions
if output_attentions is not None
else self.config.output_attentions
)
use_cache = (
use_cache if use_cache is not None else self.config.use_cache
)
past_key_values_length = None
if past_key_values is not None:
past_key_values_length = past_key_values[0][0].shape[2]
if attention_mask is None:
attention_mask = paddle.unsqueeze(
(input_ids == self.pad_token_id).astype(
self.pooler.dense.weight.dtype
)
* -1e4,
axis=[1, 2],
)
if past_key_values is not None:
batch_size = past_key_values[0][0].shape[0]
past_mask = paddle.zeros(
[batch_size, 1, 1, past_key_values_length],
dtype=attention_mask.dtype,
)
attention_mask = paddle.concat(
[past_mask, attention_mask], axis=-1
)
else:
if attention_mask.ndim == 2:
# attention_mask [batch_size, sequence_length] -> [batch_size, 1, 1, sequence_length]
attention_mask = attention_mask.unsqueeze(axis=[1, 2]).astype(
paddle.get_default_dtype()
)
attention_mask = (1.0 - attention_mask) * -1e4
embedding_output = self.embeddings(
input_ids=input_ids,
position_ids=position_ids,
token_type_ids=token_type_ids,
past_key_values_length=past_key_values_length,
)
if self.fuse:
assert not output_attentions, (
"Not support attentions output currently."
)
assert past_key_values is None, (
"Not support past_key_values currently."
)
hidden_states = embedding_output
all_hidden_states = [] if output_hidden_states else None
for layer in self.encoder:
hidden_states = layer(hidden_states, attention_mask)
if output_hidden_states:
all_hidden_states.append(hidden_states)
pooled_output = self.pooler(hidden_states)
return (
(hidden_states, pooled_output, all_hidden_states)
if output_hidden_states
else (hidden_states, pooled_output)
)
else:
self.encoder._use_cache = use_cache # To be consistent with HF
encoder_outputs = self.encoder(
embedding_output,
src_mask=attention_mask,
cache=past_key_values,
output_attentions=output_attentions,
output_hidden_states=output_hidden_states,
return_dict=return_dict,
)
if isinstance(encoder_outputs, type(embedding_output)):
sequence_output = encoder_outputs
pooled_output = self.pooler(sequence_output)
return (sequence_output, pooled_output)
else:
sequence_output = encoder_outputs[0]
pooled_output = self.pooler(sequence_output)
return (sequence_output, pooled_output, *encoder_outputs[1:])
class Bert(nn.Layer):
def __init__(self, to_static, enable_cinn):
super().__init__()
config = BertConfig()
self.bert = BertModel(config, to_static, enable_cinn)
self.cls = BertPretrainingHeads(
config,
embedding_weights=self.bert.embeddings.word_embeddings.weight,
)
# self.apply(self.init_weights)
def forward(
self,
input_ids: Tensor,
token_type_ids: Tensor | None = None,
position_ids: Tensor | None = None,
attention_mask: Tensor | None = None,
masked_positions: Tensor | None = None,
labels: Tensor | None = None,
next_sentence_label: Tensor | None = None,
output_hidden_states: bool | None = None,
output_attentions: bool | None = None,
return_dict: bool | None = None,
):
with paddle.static.amp.fp16_guard():
outputs = self.bert(
input_ids,
token_type_ids=token_type_ids,
position_ids=position_ids,
attention_mask=attention_mask,
output_attentions=output_attentions,
output_hidden_states=output_hidden_states,
return_dict=return_dict,
)
sequence_output, pooled_output = outputs[:2]
prediction_scores, seq_relationship_score = self.cls(
sequence_output, pooled_output, masked_positions
)
total_loss = None
if labels is not None and next_sentence_label is not None:
loss_fct = paddle.nn.CrossEntropyLoss()
masked_lm_loss = loss_fct(
prediction_scores.reshape(
(-1, prediction_scores.shape[-1])
),
labels.reshape((-1,)),
)
next_sentence_loss = loss_fct(
seq_relationship_score.reshape((-1, 2)),
next_sentence_label.reshape((-1,)),
)
total_loss = masked_lm_loss + next_sentence_loss
output = (prediction_scores, seq_relationship_score, *outputs[2:])
return ((total_loss, *output)) if total_loss is not None else output
class BertPretrainingCriterion(paddle.nn.Layer):
def __init__(self, vocab_size=VOCAB_SIZE):
super().__init__()
# CrossEntropyLoss is expensive since the inner reshape (copy)
self.loss_fn = paddle.nn.loss.CrossEntropyLoss(ignore_index=-1)
self.vocab_size = vocab_size
def forward(
self,
prediction_scores,
seq_relationship_score,
masked_lm_labels,
next_sentence_labels,
masked_lm_scale,
):
with paddle.static.amp.fp16_guard():
masked_lm_loss = F.cross_entropy(
prediction_scores,
masked_lm_labels,
reduction="none",
ignore_index=-1,
)
masked_lm_loss = masked_lm_loss / masked_lm_scale
next_sentence_loss = F.cross_entropy(
seq_relationship_score, next_sentence_labels, reduction="none"
)
return paddle.sum(masked_lm_loss) + paddle.mean(next_sentence_loss)
def layer_init_wrapper(func):
@functools.wraps(func)
def _impl(self, *args, **kwargs):
enable_recompute = kwargs.pop("enable_recompute", False)
func(self, *args, **kwargs)
if paddle.in_dynamic_mode():
self.enable_recompute = enable_recompute
else:
self.enable_recompute = False
return _impl
def _convert_attention_mask(attn_mask, dtype):
if attn_mask is not None and attn_mask.dtype != dtype:
attn_mask_dtype = convert_dtype(attn_mask.dtype)
if attn_mask_dtype == 'bool' or 'int' in attn_mask_dtype:
attn_mask = (paddle.cast(attn_mask, dtype) - 1.0) * 1e9
else:
attn_mask = paddle.cast(attn_mask, dtype)
return attn_mask
def _transformer_encoder_layer_fwd(
self, src, src_mask=None, cache=None, output_attentions=False
):
self.self_attn.need_weights = output_attentions
src_mask = _convert_attention_mask(src_mask, src.dtype)
residual = src
if self.normalize_before:
src = self.norm1(src)
attn_outputs = self.self_attn(src, src, src, src_mask, cache)
if isinstance(attn_outputs, tuple):
src = attn_outputs[0]
outputs = attn_outputs[1:]
else:
src = attn_outputs
outputs = None
src = residual + self.dropout1(src)
if not self.normalize_before:
src = self.norm1(src)
residual = src
if self.normalize_before:
src = self.norm2(src)
src = self.linear2(self.dropout(self.activation(self.linear1(src))))
src = residual + self.dropout2(src)
if not self.normalize_before:
src = self.norm2(src)
return (
src if outputs is None else ((src, *outputs[::-1]))
) # hidden_states, cache, attentions
def _transformer_decoder_layer_fwd(
self,
tgt,
memory,
tgt_mask=None,
memory_mask=None,
cache=None,
output_attentions=False,
):
residual = tgt
# self attention
self.self_attn.need_weights = output_attentions
tgt_mask = _convert_attention_mask(tgt_mask, tgt.dtype)
if self.normalize_before:
tgt = self.norm1(tgt)
self_attn_outputs = self.self_attn(
tgt, tgt, tgt, tgt_mask, cache[0] if cache else None
)
# self_attn_outputs = (tgt, attn_weights, incremental_cache) or only tgt
if isinstance(self_attn_outputs, type(tgt)):
tgt = self_attn_outputs
else:
tgt = self_attn_outputs[0]
if output_attentions:
self_attn_weights = self_attn_outputs[1]
if cache:
incremental_cache = self_attn_outputs[-1]
tgt = residual + self.dropout1(tgt)
if not self.normalize_before:
tgt = self.norm1(tgt)
residual = tgt
# cross attention
if memory is not None:
self.cross_attn.need_weights = output_attentions
memory_mask = _convert_attention_mask(memory_mask, memory.dtype)
if self.normalize_before:
tgt = self.norm2(tgt)
cross_attn_outputs = self.cross_attn(
tgt, memory, memory, memory_mask, cache[1] if cache else None
)
if isinstance(cross_attn_outputs, type(tgt)):
tgt = cross_attn_outputs
else:
tgt = cross_attn_outputs[0]
if output_attentions:
cross_attn_weights = cross_attn_outputs[1]
if cache:
static_cache = cross_attn_outputs[-1]
tgt = residual + self.dropout2(tgt)
if not self.normalize_before:
tgt = self.norm2(tgt)
residual = tgt
if self.normalize_before:
tgt = self.norm3(tgt)
tgt = self.linear2(self.dropout(self.activation(self.linear1(tgt))))
tgt = residual + self.dropout3(tgt)
if not self.normalize_before:
tgt = self.norm3(tgt)
if not output_attentions and cache is None:
return tgt
else:
outputs = (tgt,)
if output_attentions:
outputs += (
self_attn_weights,
cross_attn_weights if memory is not None else None,
)
if cache:
outputs += (
(
incremental_cache,
static_cache if memory is not None else None,
),
)
return outputs
def _transformer_encoder_fwd(
self,
src,
src_mask=None,
cache=None,
output_attentions=False,
output_hidden_states=False,
return_dict=False,
):
src_mask = _convert_attention_mask(src_mask, src.dtype)
output = src
# To get cache from None when use_cache is True, which is compatible with HF
# while HF requires decoder. The implementation here uses cache update in the
# MultiHeadAttention not so efficiently, and maybe optimize it later.
if cache is None and getattr(self, "_use_cache", False):
cache = [tuple(self.layers[0].gen_cache(src))] * len(self.layers)
# To be compatible with `TransformerEncoder.forward`, `_use_cache` defaults
# to True when cache is not None.
new_caches = (
[] if cache is not None and getattr(self, "_use_cache", True) else None
)
all_attentions = [] if output_attentions else None
# NOTE: Also includes embedding output which is same as HF.
all_hidden_states = [output] if output_hidden_states else None
for i, mod in enumerate(self.layers):
if self.enable_recompute:
# Note: recompute do not support pass as **kwargs yet.
layer_outputs = recompute(
mod,
output,
src_mask,
(
None
if cache is None
else (
cache[i]
if isinstance(cache[i], MultiHeadAttention.Cache)
else MultiHeadAttention.Cache(*cache[i])
)
),
output_attentions,
)
else:
layer_outputs = mod(
output,
src_mask=src_mask,
cache=(
None
if cache is None
else (
cache[i]
if isinstance(cache[i], MultiHeadAttention.Cache)
else MultiHeadAttention.Cache(*cache[i])
)
),
output_attentions=output_attentions,
)
if isinstance(layer_outputs, tuple):
output = layer_outputs[0]
outputs = layer_outputs[1:]
else:
output = layer_outputs
outputs = None
if output_hidden_states:
all_hidden_states.append(output)
if output_attentions:
all_attentions.append(outputs[-1])
if new_caches is not None:
new_caches.append(
outputs[0]
if isinstance(cache[i], MultiHeadAttention.Cache)
else (tuple(outputs[0]))
)
if self.norm is not None:
output = self.norm(output)
if output_hidden_states:
all_hidden_states[-1] = output
outputs = tuple(
tuple(v) if isinstance(v, list) else v
for v in [
output,
new_caches,
all_hidden_states,
all_attentions,
]
if v is not None
)
if len(outputs) == 1:
return output
else:
return outputs
def _transformer_decoder_fwd(
self,
tgt,
memory=None,
tgt_mask=None,
memory_mask=None,
cache=None,
output_attentions=False,
output_hidden_states=False,
return_dict=False,
):
tgt_mask = _convert_attention_mask(tgt_mask, tgt.dtype)
if memory is not None:
memory_mask = _convert_attention_mask(memory_mask, memory.dtype)
new_caches = [] if cache else None
all_hidden_states = [tgt] if output_hidden_states else None
all_self_attns = [] if output_attentions else None
all_cross_attns = [] if output_attentions else None
for i, mod in enumerate(self.layers):
if cache is None:
if self.enable_recompute:
outputs = recompute(
mod,
tgt,
memory,
tgt_mask,
memory_mask,
None,
output_attentions,
)
else:
outputs = mod(
tgt,
memory,
tgt_mask=tgt_mask,
memory_mask=memory_mask,
cache=None,
output_attentions=output_attentions,
)
else:
outputs = mod(
tgt,
memory,
tgt_mask=tgt_mask,
memory_mask=memory_mask,
cache=cache[i] if cache else None,
output_attentions=output_attentions,
)
if isinstance(outputs, type(tgt)):
tgt = outputs
else:
tgt = outputs[0]
if cache:
new_caches.append(outputs[-1])
if output_attentions:
all_self_attns.append(outputs[1])
all_cross_attns.append(outputs[2])
if output_hidden_states:
all_hidden_states.append(tgt)
if self.norm is not None:
tgt = self.norm(tgt)
if output_hidden_states:
all_hidden_states[-1] = tgt
if isinstance(outputs, type(tgt)):
return tgt
temp_list = [
tgt,
new_caches if cache else None,
all_hidden_states,
all_self_attns,
all_cross_attns,
]
return tuple(v for v in temp_list if v is not None)
# patches of paddle.nn.Transformer to get all hidden_states and attentions
paddle.nn.TransformerEncoderLayer.forward = _transformer_encoder_layer_fwd
paddle.nn.TransformerDecoderLayer.forward = _transformer_decoder_layer_fwd
paddle.nn.TransformerEncoder.forward = _transformer_encoder_fwd
paddle.nn.TransformerDecoder.forward = _transformer_decoder_fwd
_encoder_init = paddle.nn.TransformerEncoder.__init__
_decoder_init = paddle.nn.TransformerDecoder.__init__
paddle.nn.TransformerEncoder.__init__ = layer_init_wrapper(_encoder_init)
paddle.nn.TransformerDecoder.__init__ = layer_init_wrapper(_decoder_init)
class PretrainingDataset(Dataset):
def __init__(self, input_file, max_pred_length):
self.input_file = input_file
self.max_pred_length = max_pred_length
keys = [
"input_ids",
"input_mask",
"segment_ids",
"masked_lm_positions",
"masked_lm_ids",
"next_sentence_labels",
]
self.inputs = np.load(input_file)
self.inputs = [self.inputs[key] for key in keys]
def __len__(self):
"Denotes the total number of samples"
return len(self.inputs[0])
def __getitem__(self, index):
[
input_ids,
input_mask,
segment_ids,
masked_lm_positions,
masked_lm_ids,
next_sentence_labels,
] = [
(
input[index].astype(np.int64)
if indice < 5
else np.asarray(input[index].astype(np.int64))
)
for indice, input in enumerate(self.inputs)
]
# TODO: whether to use reversed mask by changing 1s and 0s to be
# consistent with nv bert
input_mask = (
1
- np.reshape(
input_mask.astype(np.float32), [1, 1, input_mask.shape[0]]
)
) * -1e9
index = self.max_pred_length
# store number of masked tokens in index
# outputs of torch.nonzero diff with that of numpy.nonzero by zip
padded_mask_indices = (masked_lm_positions == 0).nonzero()[0]
if len(padded_mask_indices) != 0:
index = padded_mask_indices[0].item()
else:
index = self.max_pred_length
# masked_lm_labels = np.full(input_ids.shape, -1, dtype=np.int64)
# masked_lm_labels[masked_lm_positions[:index]] = masked_lm_ids[:index]
masked_lm_labels = masked_lm_ids[:index]
masked_lm_positions = masked_lm_positions[:index]
# softmax_with_cross_entropy enforce last dim size equal 1
masked_lm_labels = np.expand_dims(masked_lm_labels, axis=-1)
next_sentence_labels = np.expand_dims(next_sentence_labels, axis=-1)
return [
input_ids,
segment_ids,
input_mask,
masked_lm_positions,
masked_lm_labels,
next_sentence_labels,
]
def create_pretraining_dataset(
input_file, max_pred_length, shared_list, batch_size, worker_init
):
train_data = PretrainingDataset(
input_file=input_file, max_pred_length=max_pred_length
)
# files have been sharded, no need to dispatch again
train_batch_sampler = paddle.io.BatchSampler(
train_data, batch_size=batch_size, shuffle=True
)
# DataLoader cannot be pickled because of its place.
# If it can be pickled, use global function instead of lambda and use
# ProcessPoolExecutor instead of ThreadPoolExecutor to prefetch.
def _collate_data(data, stack_fn=Stack()):
num_fields = len(data[0])
out = [None] * num_fields
# input_ids, segment_ids, input_mask, masked_lm_positions,
# masked_lm_labels, next_sentence_labels, mask_token_num
for i in (0, 1, 2, 5):
out[i] = stack_fn([x[i] for x in data])
_, seq_length = out[0].shape
size = sum(len(x[3]) for x in data)
# Padding for divisibility by 8 for fp16 or int8 usage
if size % 8 != 0:
size += 8 - (size % 8)
# masked_lm_positions
# Organize as a 1D tensor for gather or use gather_nd
out[3] = np.full(size, 0, dtype=np.int32)
# masked_lm_labels
out[4] = np.full([size, 1], -1, dtype=np.int64)
mask_token_num = 0
for i, x in enumerate(data):
for j, pos in enumerate(x[3]):
out[3][mask_token_num] = i * seq_length + pos
out[4][mask_token_num] = x[4][j]
mask_token_num += 1
# mask_token_num
out.append(np.asarray([mask_token_num], dtype=np.float32))
return out
train_data_loader = DataLoader(
dataset=train_data,
batch_sampler=train_batch_sampler,
collate_fn=_collate_data,
num_workers=0,
worker_init_fn=worker_init,
return_list=True,
)
return train_data_loader
if __name__ == '__main__':
bert = Bert()
+126
View File
@@ -0,0 +1,126 @@
# Copyright (c) 2023 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 os
import time
import unittest
import numpy as np
from bert import Bert, BertPretrainingCriterion, create_pretraining_dataset
import paddle
from paddle import base
from paddle.base import core
from paddle.dataset.common import DATA_HOME, download
SEED = 2023
BATCH_SIZE = 2
URL = 'https://paddle-ci.gz.bcebos.com/prim_cinn/bert_training_data.npz'
MODULE_NAME = 'test_bert_prim_cinn'
MD5SUM = '71e730ee8d7aa77a215b7e898aa089af'
SAVE_NAME = 'bert_training_data.npz'
if core.is_compiled_with_cuda():
paddle.set_flags({'FLAGS_cudnn_deterministic': True})
def train(to_static, enable_prim, enable_cinn):
if core.is_compiled_with_cuda():
paddle.set_device('gpu')
else:
paddle.set_device('cpu')
base.core._set_prim_all_enabled(enable_prim)
np.random.seed(SEED)
paddle.seed(SEED)
# paddle.framework.random._manual_program_seed(SEED)
train_data_loader = create_pretraining_dataset(
os.path.join(DATA_HOME, MODULE_NAME, SAVE_NAME),
20,
{},
batch_size=BATCH_SIZE,
worker_init=None,
)
# Now only apply dy2st for encoder
bert = Bert(to_static, enable_cinn)
criterion = BertPretrainingCriterion()
optimizer = paddle.optimizer.Adam(parameters=bert.parameters())
losses = []
for step, batch in enumerate(train_data_loader):
start_time = time.time()
(
input_ids,
segment_ids,
input_mask,
masked_lm_positions,
masked_lm_labels,
next_sentence_labels,
masked_lm_scale,
) = batch
prediction_scores, seq_relationship_score = bert(
input_ids=input_ids,
token_type_ids=segment_ids,
attention_mask=input_mask,
masked_positions=masked_lm_positions,
)
loss = criterion(
prediction_scores,
seq_relationship_score,
masked_lm_labels,
next_sentence_labels,
masked_lm_scale,
)
loss.backward()
optimizer.minimize(loss)
bert.clear_gradients()
losses.append(loss.numpy().item())
print(
f"step: {step}, loss: {loss.numpy()}, batch_cost: {time.time() - start_time:.5}"
)
if step >= 9:
break
print(losses)
return losses
class TestBert(unittest.TestCase):
@classmethod
def setUpClass(cls):
download(URL, MODULE_NAME, MD5SUM, SAVE_NAME)
def tearDown(self):
paddle.set_flags({'FLAGS_deny_cinn_ops': ''})
@unittest.skipIf(
not (paddle.is_compiled_with_cinn() and paddle.is_compiled_with_cuda()),
"paddle is not compiled with CINN and CUDA",
)
def test_cinn(self):
paddle.set_flags({'FLAGS_deny_cinn_ops': "dropout"})
dy2st_cinn = train(to_static=True, enable_prim=False, enable_cinn=True)
dy2st_pir = train(to_static=True, enable_prim=False, enable_cinn=False)
np.testing.assert_allclose(dy2st_cinn, dy2st_pir, rtol=1e-5)
if __name__ == '__main__':
unittest.main()
+151
View File
@@ -0,0 +1,151 @@
# Copyright (c) 2023 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 os
import time
import unittest
import numpy as np
from bert import Bert, BertPretrainingCriterion, create_pretraining_dataset
import paddle
from paddle import base
from paddle.base import core
from paddle.dataset.common import DATA_HOME, download
SEED = 2023
BATCH_SIZE = 2
URL = 'https://paddle-ci.gz.bcebos.com/prim_cinn/bert_training_data.npz'
MODULE_NAME = 'test_bert_prim_cinn'
MD5SUM = '71e730ee8d7aa77a215b7e898aa089af'
SAVE_NAME = 'bert_training_data.npz'
if core.is_compiled_with_cuda():
paddle.set_flags({'FLAGS_cudnn_deterministic': True})
def train(to_static, enable_prim, enable_cinn):
if core.is_compiled_with_cuda():
paddle.set_device('gpu')
else:
paddle.set_device('cpu')
base.core._set_prim_all_enabled(enable_prim)
np.random.seed(SEED)
paddle.seed(SEED)
# paddle.framework.random._manual_program_seed(SEED)
train_data_loader = create_pretraining_dataset(
os.path.join(DATA_HOME, MODULE_NAME, SAVE_NAME),
20,
{},
batch_size=BATCH_SIZE,
worker_init=None,
)
# Now only apply dy2st for encoder
bert = Bert(to_static, enable_cinn)
criterion = BertPretrainingCriterion()
optimizer = paddle.optimizer.Adam(parameters=bert.parameters())
losses = []
for step, batch in enumerate(train_data_loader):
start_time = time.time()
(
input_ids,
segment_ids,
input_mask,
masked_lm_positions,
masked_lm_labels,
next_sentence_labels,
masked_lm_scale,
) = batch
prediction_scores, seq_relationship_score = bert(
input_ids=input_ids,
token_type_ids=segment_ids,
attention_mask=input_mask,
masked_positions=masked_lm_positions,
)
loss = criterion(
prediction_scores,
seq_relationship_score,
masked_lm_labels,
next_sentence_labels,
masked_lm_scale,
)
loss.backward()
optimizer.minimize(loss)
bert.clear_gradients()
losses.append(loss.numpy().item())
print(
f"step: {step}, loss: {loss.numpy()}, batch_cost: {time.time() - start_time:.5}"
)
if step >= 9:
break
print(losses)
return losses
class TestBert(unittest.TestCase):
@classmethod
def setUpClass(cls):
download(URL, MODULE_NAME, MD5SUM, SAVE_NAME)
def tearDown(self):
paddle.set_flags({'FLAGS_deny_cinn_ops': ''})
@unittest.skipIf(
not (paddle.is_compiled_with_cinn() and paddle.is_compiled_with_cuda()),
"paddle is not compiled with CINN and CUDA",
)
def test_prim(self):
if "H20" in paddle.cuda.get_device_name():
DY2ST_PRIM_GT = [
10.834290504455566,
10.328838348388672,
10.342059135437012,
10.281204223632812,
10.226964950561523,
10.220486640930176,
10.174433708190918,
10.127359390258789,
10.134778022766113,
10.03632926940918,
]
else:
DY2ST_PRIM_GT = [
10.649632453918457,
10.333406448364258,
10.33541202545166,
10.260543823242188,
10.219606399536133,
10.176884651184082,
10.124699592590332,
10.072620391845703,
10.112163543701172,
9.969392776489258,
]
dy2st_prim = train(to_static=True, enable_prim=True, enable_cinn=False)
np.testing.assert_allclose(dy2st_prim, DY2ST_PRIM_GT, rtol=1e-5)
if __name__ == '__main__':
unittest.main()
+143
View File
@@ -0,0 +1,143 @@
# Copyright (c) 2023 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 os
import time
import unittest
import numpy as np
from bert import Bert, BertPretrainingCriterion, create_pretraining_dataset
import paddle
from paddle import base
from paddle.base import core
from paddle.dataset.common import DATA_HOME, download
SEED = 2023
BATCH_SIZE = 2
URL = 'https://paddle-ci.gz.bcebos.com/prim_cinn/bert_training_data.npz'
MODULE_NAME = 'test_bert_prim_cinn'
MD5SUM = '71e730ee8d7aa77a215b7e898aa089af'
SAVE_NAME = 'bert_training_data.npz'
DY2ST_PRIM_CINN_GT = [
11.086677551269531,
10.342002868652344,
10.336370468139648,
10.272554397583008,
10.224645614624023,
10.184449195861816,
10.14853572845459,
10.096378326416016,
10.117865562438965,
9.99058723449707,
]
if core.is_compiled_with_cuda():
paddle.set_flags({'FLAGS_cudnn_deterministic': True})
def train(to_static, enable_prim, enable_cinn):
if core.is_compiled_with_cuda():
paddle.set_device('gpu')
else:
paddle.set_device('cpu')
base.core._set_prim_all_enabled(enable_prim)
np.random.seed(SEED)
paddle.seed(SEED)
# paddle.framework.random._manual_program_seed(SEED)
train_data_loader = create_pretraining_dataset(
os.path.join(DATA_HOME, MODULE_NAME, SAVE_NAME),
20,
{},
batch_size=BATCH_SIZE,
worker_init=None,
)
# Now only apply dy2st for encoder
bert = Bert(to_static, enable_cinn)
criterion = BertPretrainingCriterion()
optimizer = paddle.optimizer.Adam(parameters=bert.parameters())
losses = []
for step, batch in enumerate(train_data_loader):
start_time = time.time()
(
input_ids,
segment_ids,
input_mask,
masked_lm_positions,
masked_lm_labels,
next_sentence_labels,
masked_lm_scale,
) = batch
prediction_scores, seq_relationship_score = bert(
input_ids=input_ids,
token_type_ids=segment_ids,
attention_mask=input_mask,
masked_positions=masked_lm_positions,
)
loss = criterion(
prediction_scores,
seq_relationship_score,
masked_lm_labels,
next_sentence_labels,
masked_lm_scale,
)
loss.backward()
optimizer.minimize(loss)
bert.clear_gradients()
losses.append(loss.numpy().item())
print(
f"step: {step}, loss: {loss.numpy()}, batch_cost: {time.time() - start_time:.5}"
)
if step >= 9:
break
print(losses)
return losses
class TestBert(unittest.TestCase):
@classmethod
def setUpClass(cls):
download(URL, MODULE_NAME, MD5SUM, SAVE_NAME)
def tearDown(self):
paddle.set_flags({'FLAGS_deny_cinn_ops': ''})
@unittest.skipIf(
not (paddle.is_compiled_with_cinn() and paddle.is_compiled_with_cuda()),
"paddle is not compiled with CINN and CUDA",
)
def test_prim_cinn(self):
dy2st_prim_cinn = train(
to_static=True, enable_prim=True, enable_cinn=True
)
np.testing.assert_allclose(
dy2st_prim_cinn, DY2ST_PRIM_CINN_GT, rtol=1e-5
)
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,115 @@
# Copyright (c) 2022 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 unittest
import numpy as np
import parameterized as param
import paddle
from paddle.base import core, framework
@param.parameterized_class(
('name', 'primals', 'stop_gradients', 'cotangents', 'dtype'),
(
(
'test_normal_case',
(np.random.rand(2, 3, 4), np.random.rand(2, 3, 4)),
(False, False),
(np.random.rand(2, 3, 4),),
np.float32,
),
(
'test_broadcast_diff_rank',
(np.random.rand(2, 3, 1, 4), np.random.rand(3, 3, 4)),
(False, False),
(np.random.rand(2, 3, 3, 4),),
np.float32,
),
(
'test_broadcast_same_rank',
(np.random.rand(2, 3, 1, 4), np.random.rand(2, 1, 3, 4)),
(False, False),
(np.random.rand(2, 3, 3, 4),),
np.float32,
),
(
'test_stop_gradient',
(np.random.rand(2, 3, 1, 4), np.random.rand(2, 1, 3, 4)),
(False, True),
(np.random.rand(2, 3, 3, 4),),
np.float32,
),
),
)
class TestMultiplyGradComp(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.primals = tuple(primal.astype(cls.dtype) for primal in cls.primals)
cls.cotangents = tuple(co.astype(cls.dtype) for co in cls.cotangents)
def setUp(self):
paddle.enable_static()
def tearDown(self):
paddle.disable_static()
def as_tuple(self, x):
return (x,) if isinstance(x, framework.Variable) else x
def net(self):
primals, cotangents = self.primals, self.cotangents
mp, sp = paddle.static.Program(), paddle.static.Program()
with paddle.static.program_guard(mp, sp):
primals = tuple(
paddle.static.data(f'primal{i}', primal.shape, primal.dtype)
for i, primal in enumerate(primals)
)
for primal, flag in zip(primals, self.stop_gradients):
primal.stop_gradient = flag
cotangents = tuple(
paddle.static.data(f'cotangent{i}', co.shape, co.dtype)
for i, co in enumerate(cotangents)
)
out = self.as_tuple(paddle.tanh(paddle.multiply(*primals)))
grads = paddle.static.gradients(out, primals)
exe = paddle.static.Executor()
exe.run(sp)
return exe.run(
program=mp,
feed={f'primal{i}': primal for i, primal in enumerate(self.primals)}
| {f'cotangent{i}': co for i, co in enumerate(self.cotangents)},
fetch_list=[g for g in grads if g is not None],
)
def test_comp(self):
core._set_prim_backward_enabled(True)
actual = self.net()
core._set_prim_backward_enabled(False)
desired = self.net()
self.assertEqual(len(actual), len(desired))
for i, j in zip(actual, desired):
np.testing.assert_allclose(
i,
j,
rtol=1e-6,
atol=0,
)
if __name__ == '__main__':
unittest.main()
+191
View File
@@ -0,0 +1,191 @@
# Copyright (c) 2023 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
import paddle
from paddle import base
from paddle.base import core
from paddle.vision.models import resnet50
SEED = 2020
base_lr = 0.001
momentum_rate = 0.9
l2_decay = 1e-4
batch_size = 2
epoch_num = 1
# In V100, 16G, CUDA 11.2, the results are as follows:
# DY2ST_CINN_GT = [
# 5.847336769104004,
# 8.336246490478516,
# 5.108744144439697,
# 8.316713333129883,
# 8.175262451171875,
# 7.590441703796387,
# 9.895681381225586,
# 8.196207046508789,
# 8.438933372497559,
# 10.305074691772461,
# note: Version 2.0 momentum is fused to OP when L2Decay is available, and the results are different from the base version.
# The results in ci as as follows:
DY2ST_CINN_GT = [
5.847333908081055,
8.347576141357422,
5.1415300369262695,
8.373777389526367,
8.05331802368164,
7.437496185302734,
9.630914688110352,
8.547889709472656,
8.343082427978516,
10.203847885131836,
]
if core.is_compiled_with_cuda():
paddle.set_flags({'FLAGS_cudnn_deterministic': True})
def reader_decorator(reader):
def __reader__():
for item in reader():
img = np.array(item[0]).astype('float32').reshape(3, 224, 224)
label = np.array(item[1]).astype('int64').reshape(1)
yield img, label
return __reader__
class TransedFlowerDataSet(paddle.io.Dataset):
def __init__(self, flower_data, length):
self.img = []
self.label = []
self.flower_data = flower_data()
self._generate(length)
def _generate(self, length):
for i, data in enumerate(self.flower_data):
if i >= length:
break
self.img.append(data[0])
self.label.append(data[1])
def __getitem__(self, idx):
return self.img[idx], self.label[idx]
def __len__(self):
return len(self.img)
def optimizer_setting(parameter_list=None):
optimizer = paddle.optimizer.Momentum(
learning_rate=base_lr,
momentum=momentum_rate,
weight_decay=paddle.regularizer.L2Decay(l2_decay),
parameters=parameter_list,
)
return optimizer
def run(model, data_loader, optimizer, mode):
if mode == 'train':
model.train()
end_step = 9
elif mode == 'eval':
model.eval()
end_step = 1
for epoch in range(epoch_num):
total_acc1 = 0.0
total_acc5 = 0.0
total_sample = 0
losses = []
for batch_id, data in enumerate(data_loader()):
start_time = time.time()
img, label = data
pred = model(img)
avg_loss = paddle.nn.functional.cross_entropy(
input=pred,
label=label,
soft_label=False,
reduction='mean',
use_softmax=True,
)
acc_top1 = paddle.static.accuracy(input=pred, label=label, k=1)
acc_top5 = paddle.static.accuracy(input=pred, label=label, k=5)
if mode == 'train':
avg_loss.backward()
optimizer.minimize(avg_loss)
model.clear_gradients()
total_acc1 += acc_top1
total_acc5 += acc_top5
total_sample += 1
losses.append(avg_loss.numpy().item())
end_time = time.time()
print(
f"[{mode}]epoch {epoch} | batch step {batch_id}, "
f"loss {avg_loss:0.8f}, "
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 >= end_step:
break
print(losses)
return losses
def train(to_static, enable_prim, enable_cinn):
if core.is_compiled_with_cuda():
paddle.set_device('gpu')
else:
paddle.set_device('cpu')
np.random.seed(SEED)
paddle.seed(SEED)
paddle.framework.random._manual_program_seed(SEED)
base.core._set_prim_all_enabled(enable_prim)
dataset = TransedFlowerDataSet(
reader_decorator(paddle.dataset.flowers.train(use_xmap=False)),
batch_size * (10 + 1),
)
data_loader = paddle.io.DataLoader(
dataset, batch_size=batch_size, drop_last=True
)
resnet = resnet50(False)
if to_static:
backend = "CINN" if enable_cinn else None
resnet = paddle.jit.to_static(resnet, backend=backend, full_graph=True)
optimizer = optimizer_setting(parameter_list=resnet.parameters())
train_losses = run(resnet, data_loader, optimizer, 'train')
if to_static and enable_prim and enable_cinn:
eval_losses = run(resnet, data_loader, optimizer, 'eval')
return train_losses
if __name__ == '__main__':
unittest.main()
+219
View File
@@ -0,0 +1,219 @@
# Copyright (c) 2023 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
import paddle
from paddle import base
from paddle.base import core
from paddle.vision.models import resnet50
SEED = 2020
base_lr = 0.001
momentum_rate = 0.9
l2_decay = 1e-4
batch_size = 2
epoch_num = 1
# In V100, 16G, CUDA 11.2, the results are as follows:
# DY2ST_PRIM_GT = [
# 5.8473358154296875,
# 8.354944229125977,
# 5.098367691040039,
# 8.533346176147461,
# 8.179085731506348,
# 7.285282135009766,
# 9.824585914611816,
# 8.56928825378418,
# 8.539499282836914,
# 10.256929397583008,
# ]
# note: Version 2.0 momentum is fused to OP when L2Decay is available, and the results are different from the base version.
# The results in ci as as follows:
DY2ST_PRIM_GT = [
8.852441787719727,
8.403528213500977,
7.157894134521484,
8.536691665649414,
7.061797142028809,
7.612838268280029,
7.831070423126221,
8.562232971191406,
8.49091911315918,
7.967043876647949,
]
# IN V100, 16G, CUDA 12.0, the results are as follows:
DY2ST_PRIM_GT_CUDA12 = [
8.852443695068359,
8.403528213500977,
7.158357620239258,
8.539973258972168,
7.070737838745117,
7.629122734069824,
7.809022426605225,
8.636153221130371,
8.410324096679688,
7.992737293243408,
]
if core.is_compiled_with_cuda():
paddle.set_flags({'FLAGS_cudnn_deterministic': True})
def reader_decorator(reader):
def __reader__():
for item in reader():
img = np.array(item[0]).astype('float32').reshape(3, 224, 224)
label = np.array(item[1]).astype('int64').reshape(1)
yield img, label
return __reader__
class TransedFlowerDataSet(paddle.io.Dataset):
def __init__(self, flower_data, length):
self.img = []
self.label = []
self.flower_data = flower_data()
self._generate(length)
def _generate(self, length):
for i, data in enumerate(self.flower_data):
if i >= length:
break
self.img.append(data[0])
self.label.append(data[1])
def __getitem__(self, idx):
return self.img[idx], self.label[idx]
def __len__(self):
return len(self.img)
def optimizer_setting(parameter_list=None):
optimizer = paddle.optimizer.Momentum(
learning_rate=base_lr,
momentum=momentum_rate,
weight_decay=paddle.regularizer.L2Decay(l2_decay),
parameters=parameter_list,
)
return optimizer
def run(model, data_loader, optimizer, mode):
if mode == 'train':
model.train()
end_step = 9
elif mode == 'eval':
model.eval()
end_step = 1
for epoch in range(epoch_num):
total_acc1 = 0.0
total_acc5 = 0.0
total_sample = 0
losses = []
for batch_id, data in enumerate(data_loader()):
start_time = time.time()
img, label = data
pred = model(img)
avg_loss = paddle.nn.functional.cross_entropy(
input=pred,
label=label,
soft_label=False,
reduction='mean',
use_softmax=True,
)
acc_top1 = paddle.static.accuracy(input=pred, label=label, k=1)
acc_top5 = paddle.static.accuracy(input=pred, label=label, k=5)
if mode == 'train':
avg_loss.backward()
optimizer.minimize(avg_loss)
model.clear_gradients()
total_acc1 += acc_top1
total_acc5 += acc_top5
total_sample += 1
losses.append(avg_loss.numpy().item())
end_time = time.time()
print(
f"[{mode}]epoch {epoch} | batch step {batch_id}, "
f"loss {avg_loss:0.15f}, "
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 >= end_step:
break
return losses
def train(to_static, enable_prim, enable_cinn):
if core.is_compiled_with_cuda():
paddle.set_device('gpu')
else:
paddle.set_device('cpu')
np.random.seed(SEED)
paddle.seed(SEED)
paddle.framework.random._manual_program_seed(SEED)
base.core._set_prim_all_enabled(enable_prim)
dataset = TransedFlowerDataSet(
reader_decorator(paddle.dataset.flowers.train(use_xmap=False)),
batch_size * (10 + 1),
)
data_loader = paddle.io.DataLoader(
dataset, batch_size=batch_size, drop_last=True
)
resnet = resnet50(True)
if to_static:
backend = "CINN" if enable_cinn else None
resnet = paddle.jit.to_static(resnet, backend=backend, full_graph=True)
optimizer = optimizer_setting(parameter_list=resnet.parameters())
train_losses = run(resnet, data_loader, optimizer, 'train')
if to_static and enable_prim and enable_cinn:
eval_losses = run(resnet, data_loader, optimizer, 'eval')
return train_losses
class TestResnet(unittest.TestCase):
@unittest.skipIf(
not (paddle.is_compiled_with_cinn() and paddle.is_compiled_with_cuda()),
"paddle is not compiled with CINN and CUDA",
)
def test_prim(self):
dy2st_prim = train(to_static=True, enable_prim=True, enable_cinn=False)
standard_prim = DY2ST_PRIM_GT
if paddle.version.cuda() == "12.0":
standard_prim = DY2ST_PRIM_GT_CUDA12
np.testing.assert_allclose(
dy2st_prim, standard_prim, rtol=2e-2, atol=1e-2
)
if __name__ == '__main__':
unittest.main()
+192
View File
@@ -0,0 +1,192 @@
# Copyright (c) 2023 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
import paddle
from paddle import base
from paddle.base import core
from paddle.vision.models import resnet50
SEED = 2020
base_lr = 0.001
momentum_rate = 0.9
l2_decay = 1e-4
batch_size = 2
epoch_num = 1
# In V100, 16G, CUDA 11.2, the results are as follows:
# DY2ST_PRIM_CINN_GT = [
# 5.8473358154296875,
# 8.322463989257812,
# 5.169863700866699,
# 8.399882316589355,
# 7.859550476074219,
# 7.4672698974609375,
# 9.828727722167969,
# 8.270355224609375,
# 8.456792831420898,
# 9.919631958007812,
# ]
# note: Version 2.0 momentum is fused to OP when L2Decay is available, and the results are different from the base version.
# The results in ci as as follows:
DY2ST_PRIM_CINN_GT = [
5.847333908081055,
8.342670440673828,
5.130363941192627,
8.511886596679688,
8.13458251953125,
7.35969352722168,
9.874241828918457,
8.126291275024414,
8.637175559997559,
10.385666847229004,
]
if core.is_compiled_with_cuda():
paddle.set_flags({'FLAGS_cudnn_deterministic': True})
def reader_decorator(reader):
def __reader__():
for item in reader():
img = np.array(item[0]).astype('float32').reshape(3, 224, 224)
label = np.array(item[1]).astype('int64').reshape(1)
yield img, label
return __reader__
class TransedFlowerDataSet(paddle.io.Dataset):
def __init__(self, flower_data, length):
self.img = []
self.label = []
self.flower_data = flower_data()
self._generate(length)
def _generate(self, length):
for i, data in enumerate(self.flower_data):
if i >= length:
break
self.img.append(data[0])
self.label.append(data[1])
def __getitem__(self, idx):
return self.img[idx], self.label[idx]
def __len__(self):
return len(self.img)
def optimizer_setting(parameter_list=None):
optimizer = paddle.optimizer.Momentum(
learning_rate=base_lr,
momentum=momentum_rate,
weight_decay=paddle.regularizer.L2Decay(l2_decay),
parameters=parameter_list,
)
return optimizer
def run(model, data_loader, optimizer, mode):
if mode == 'train':
model.train()
end_step = 9
elif mode == 'eval':
model.eval()
end_step = 1
for epoch in range(epoch_num):
total_acc1 = 0.0
total_acc5 = 0.0
total_sample = 0
losses = []
for batch_id, data in enumerate(data_loader()):
start_time = time.time()
img, label = data
pred = model(img)
avg_loss = paddle.nn.functional.cross_entropy(
input=pred,
label=label,
soft_label=False,
reduction='mean',
use_softmax=True,
)
acc_top1 = paddle.static.accuracy(input=pred, label=label, k=1)
acc_top5 = paddle.static.accuracy(input=pred, label=label, k=5)
if mode == 'train':
avg_loss.backward()
optimizer.minimize(avg_loss)
model.clear_gradients()
total_acc1 += acc_top1
total_acc5 += acc_top5
total_sample += 1
losses.append(avg_loss.numpy().item())
end_time = time.time()
print(
f"[{mode}]epoch {epoch} | batch step {batch_id}, "
f"loss {avg_loss:0.8f}, "
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 >= end_step:
break
print(losses)
return losses
def train(to_static, enable_prim, enable_cinn):
if core.is_compiled_with_cuda():
paddle.set_device('gpu')
else:
paddle.set_device('cpu')
np.random.seed(SEED)
paddle.seed(SEED)
paddle.framework.random._manual_program_seed(SEED)
base.core._set_prim_all_enabled(enable_prim)
dataset = TransedFlowerDataSet(
reader_decorator(paddle.dataset.flowers.train(use_xmap=False)),
batch_size * (10 + 1),
)
data_loader = paddle.io.DataLoader(
dataset, batch_size=batch_size, drop_last=True
)
resnet = resnet50(False)
if to_static:
backend = "CINN" if enable_cinn else None
resnet = paddle.jit.to_static(resnet, backend=backend, full_graph=True)
optimizer = optimizer_setting(parameter_list=resnet.parameters())
train_losses = run(resnet, data_loader, optimizer, 'train')
if to_static and enable_prim and enable_cinn:
eval_losses = run(resnet, data_loader, optimizer, 'eval')
return train_losses
if __name__ == '__main__':
unittest.main()