Skip to content

Commit 22bd3aa

Browse files
wj-McatguoshengCS
andauthored
[Unittest]Add roformer unittest (#2991)
* add roformer unittest * add roformer unittest * update test_modeling * use relative import * reduce model config to accelerate testing * remove input_embedding from pretrained model * revert slow tag * update local branch * update get_vocab method * update get_vocab method * update test_chinese method * change absolute import * update unittest * update chinese test case Co-authored-by: Guo Sheng <[email protected]>
1 parent bfc8700 commit 22bd3aa

File tree

5 files changed

+514
-2
lines changed

5 files changed

+514
-2
lines changed

paddlenlp/transformers/roformer/modeling.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,12 @@ def forward(
671671
else:
672672
return sequence_output, pooled_output
673673

674+
def get_input_embeddings(self) -> nn.Embedding:
675+
return self.embeddings.word_embeddings
676+
677+
def set_input_embeddings(self, embedding: nn.Embedding):
678+
self.embeddings.word_embeddings = embedding
679+
674680

675681
class RoFormerForQuestionAnswering(RoFormerPretrainedModel):
676682
"""

paddlenlp/transformers/roformer/tokenizer.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,18 @@ class JiebaBasicTokenizer(BasicTokenizer):
3535
Defaults to `True`.
3636
"""
3737

38-
def __init__(self, vocab, do_lower_case=True):
38+
def __init__(self,
39+
vocab,
40+
do_lower_case=True,
41+
never_split=None,
42+
tokenize_chinese_chars=True,
43+
strip_accents=None):
3944
"""Constructs a JiebaBasicTokenizer."""
45+
super().__init__(never_split=never_split,
46+
do_lower_case=do_lower_case,
47+
tokenize_chinese_chars=tokenize_chinese_chars,
48+
strip_accents=strip_accents)
4049
self.vocab = vocab
41-
self.do_lower_case = do_lower_case
4250

4351
def _tokenize_chinese_chars(self, text):
4452
output = []
@@ -140,6 +148,18 @@ class RoFormerTokenizer(PretrainedTokenizer):
140148
"https://bj.bcebos.com/paddlenlp/models/transformers/roformer/roformer-english-small-generator/vocab.txt",
141149
}
142150
}
151+
max_model_input_sizes = {
152+
"roformer-chinese-small": 512,
153+
"roformer-chinese-base": 1536,
154+
"roformer-chinese-char-small": 512,
155+
"roformer-chinese-char-base": 512,
156+
"roformer-chinese-sim-char-ft-small": 512,
157+
"roformer-chinese-sim-char-ft-base": 512,
158+
"roformer-chinese-sim-char-small": 512,
159+
"roformer-chinese-sim-char-base": 512,
160+
"roformer-english-small-discriminator": 128,
161+
"roformer-english-small-generator": 128,
162+
}
143163
pretrained_init_configuration = {
144164
"roformer-chinese-small": {
145165
"do_lower_case": True,
@@ -397,3 +417,6 @@ def get_special_tokens_mask(self,
397417
return [1] + ([0] * len(token_ids_0)) + [1] + (
398418
[0] * len(token_ids_1)) + [1]
399419
return [1] + ([0] * len(token_ids_0)) + [1]
420+
421+
def get_vocab(self):
422+
return dict(self.vocab.token_to_idx, **self.added_tokens_encoder)

tests/transformers/roformer/__init__.py

Whitespace-only changes.
Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2+
# Copyright 2020 The HuggingFace Team. All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import unittest
17+
from typing import Optional, Tuple
18+
from dataclasses import dataclass, fields, Field
19+
20+
import paddle
21+
22+
from paddlenlp.transformers import (
23+
RoFormerModel, RoFormerPretrainedModel, RoFormerForPretraining,
24+
RoFormerForSequenceClassification, RoFormerForTokenClassification,
25+
RoFormerForQuestionAnswering, RoFormerForMultipleChoice,
26+
RoFormerForMaskedLM)
27+
28+
from ..test_modeling_common import ids_tensor, floats_tensor, random_attention_mask, ModelTesterMixin
29+
from ...testing_utils import slow
30+
31+
32+
@dataclass
33+
class RoFormerModelTestModelConfig:
34+
"""RoFormerModel model config which keep consist with pretrained_init_configuration sub fields
35+
"""
36+
vocab_size: int = 200
37+
embedding_size: int = 50
38+
hidden_size: int = 36
39+
num_hidden_layers: int = 6
40+
num_attention_heads: int = 6
41+
intermediate_size: int = 16
42+
hidden_act: str = "gelu"
43+
hidden_dropout_prob: float = 0.1
44+
attention_probs_dropout_prob: float = 0.1
45+
max_position_embeddings: int = 20
46+
type_vocab_size: int = 2
47+
initializer_range: float = 0.02
48+
pad_token_id: int = 0
49+
rotary_value: bool = False
50+
51+
@property
52+
def model_kwargs(self) -> dict:
53+
"""get the model kwargs configuration to init the model"""
54+
model_config_fields: Tuple[Field,
55+
...] = fields(RoFormerModelTestModelConfig)
56+
return {
57+
field.name: getattr(self, field.name)
58+
for field in model_config_fields
59+
}
60+
61+
62+
@dataclass
63+
class RoFormerModelTestConfig(RoFormerModelTestModelConfig):
64+
"""train config under unittest code"""
65+
batch_size: int = 2
66+
seq_length: int = 7
67+
is_training: bool = False
68+
use_input_mask: bool = False
69+
use_token_type_ids: bool = True
70+
71+
# used for sequence classification
72+
num_classes: int = 3
73+
num_choices: int = 3
74+
75+
76+
class RoFormerModelTester:
77+
78+
def __init__(
79+
self,
80+
parent,
81+
config: Optional[RoFormerModelTestConfig] = None,
82+
):
83+
self.parent = parent
84+
self.config: RoFormerModelTestConfig = config or RoFormerModelTestConfig(
85+
)
86+
87+
self.is_training = self.config.is_training
88+
self.num_classes = self.config.num_classes
89+
self.num_choices = self.config.num_choices
90+
91+
def prepare_config_and_inputs(self):
92+
config = self.config
93+
input_ids = ids_tensor([config.batch_size, config.seq_length],
94+
config.vocab_size)
95+
96+
input_mask = None
97+
if self.config.use_input_mask:
98+
input_mask = random_attention_mask(
99+
[config.batch_size, config.seq_length])
100+
101+
token_type_ids = None
102+
if self.config.use_token_type_ids:
103+
token_type_ids = ids_tensor([config.batch_size, config.seq_length],
104+
config.type_vocab_size)
105+
106+
config = self.get_config()
107+
return config, input_ids, token_type_ids, input_mask
108+
109+
def get_config(self) -> dict:
110+
return self.config.model_kwargs
111+
112+
def create_and_check_model(
113+
self,
114+
config,
115+
input_ids,
116+
token_type_ids,
117+
input_mask,
118+
):
119+
model = RoFormerModel(**config)
120+
model.eval()
121+
result = model(input_ids,
122+
attention_mask=input_mask,
123+
token_type_ids=token_type_ids)
124+
result = model(input_ids, token_type_ids=token_type_ids)
125+
result = model(input_ids)
126+
self.parent.assertEqual(result[0].shape, [
127+
self.config.batch_size, self.config.seq_length,
128+
self.config.hidden_size
129+
])
130+
self.parent.assertEqual(
131+
result[1].shape, [self.config.batch_size, self.config.hidden_size])
132+
133+
def create_and_check_for_multiple_choice(
134+
self,
135+
config,
136+
input_ids,
137+
token_type_ids,
138+
input_mask,
139+
):
140+
model = RoFormerForMultipleChoice(RoFormerModel(**config),
141+
num_choices=self.config.num_choices)
142+
model.eval()
143+
multiple_choice_inputs_ids = input_ids.unsqueeze(1).expand(
144+
[-1, self.config.num_choices, -1])
145+
146+
if token_type_ids is not None:
147+
token_type_ids = token_type_ids.unsqueeze(1).expand(
148+
[-1, self.config.num_choices, -1])
149+
150+
if input_mask is not None:
151+
input_mask = input_mask.unsqueeze(1).expand(
152+
[-1, self.config.num_choices, -1])
153+
154+
result = model(
155+
multiple_choice_inputs_ids,
156+
attention_mask=input_mask,
157+
token_type_ids=token_type_ids,
158+
)
159+
self.parent.assertEqual(
160+
result.shape, [self.config.batch_size, self.config.num_choices])
161+
162+
def create_and_check_for_question_answering(self, config, input_ids,
163+
token_type_ids, input_mask):
164+
model = RoFormerForQuestionAnswering(RoFormerModel(**config))
165+
model.eval()
166+
result = model(
167+
input_ids,
168+
attention_mask=input_mask,
169+
token_type_ids=token_type_ids,
170+
)
171+
self.parent.assertEqual(
172+
result[0].shape, [self.config.batch_size, self.config.seq_length])
173+
self.parent.assertEqual(
174+
result[1].shape, [self.config.batch_size, self.config.seq_length])
175+
176+
def create_and_check_for_token_classification(
177+
self,
178+
config,
179+
input_ids,
180+
token_type_ids,
181+
input_mask,
182+
):
183+
model = RoFormerForTokenClassification(RoFormerModel(**config),
184+
num_classes=self.num_classes)
185+
model.eval()
186+
result = model(input_ids,
187+
attention_mask=input_mask,
188+
token_type_ids=token_type_ids)
189+
self.parent.assertEqual(result.shape, [
190+
self.config.batch_size, self.config.seq_length,
191+
self.config.num_classes
192+
])
193+
194+
def create_and_check_for_masked_lm(
195+
self,
196+
config,
197+
input_ids,
198+
token_type_ids,
199+
input_mask,
200+
):
201+
model = RoFormerForMaskedLM(RoFormerModel(**config))
202+
model.eval()
203+
result = model(input_ids,
204+
attention_mask=input_mask,
205+
token_type_ids=token_type_ids)
206+
self.parent.assertEqual(result.shape, [
207+
self.config.batch_size, self.config.seq_length,
208+
self.config.vocab_size
209+
])
210+
211+
def create_and_check_for_sequence_classification(
212+
self,
213+
config,
214+
input_ids,
215+
token_type_ids,
216+
input_mask,
217+
):
218+
model = RoFormerForSequenceClassification(
219+
RoFormerModel(**config), num_classes=self.config.num_classes)
220+
model.eval()
221+
result = model(
222+
input_ids,
223+
attention_mask=input_mask,
224+
token_type_ids=token_type_ids,
225+
)
226+
self.parent.assertEqual(
227+
result.shape, [self.config.batch_size, self.config.num_classes])
228+
229+
def prepare_config_and_inputs_for_common(self):
230+
config_and_inputs = self.prepare_config_and_inputs()
231+
(
232+
config,
233+
input_ids,
234+
token_type_ids,
235+
input_mask,
236+
) = config_and_inputs
237+
inputs_dict = {
238+
"input_ids": input_ids,
239+
"token_type_ids": token_type_ids,
240+
"attention_mask": input_mask
241+
}
242+
return config, inputs_dict
243+
244+
245+
class RoFormerModelTest(ModelTesterMixin, unittest.TestCase):
246+
base_model_class = RoFormerModel
247+
248+
all_model_classes = (
249+
RoFormerModel,
250+
RoFormerForMultipleChoice,
251+
RoFormerForPretraining,
252+
RoFormerForSequenceClassification,
253+
)
254+
255+
def setUp(self):
256+
self.model_tester = RoFormerModelTester(self)
257+
258+
def test_model(self):
259+
config_and_inputs = self.model_tester.prepare_config_and_inputs()
260+
self.model_tester.create_and_check_model(*config_and_inputs)
261+
262+
def test_for_masked_lm(self):
263+
config_and_inputs = self.model_tester.prepare_config_and_inputs()
264+
self.model_tester.create_and_check_for_masked_lm(*config_and_inputs)
265+
266+
def test_for_multiple_choice(self):
267+
config_and_inputs = self.model_tester.prepare_config_and_inputs()
268+
self.model_tester.create_and_check_for_multiple_choice(
269+
*config_and_inputs)
270+
271+
def test_for_question_answering(self):
272+
config_and_inputs = self.model_tester.prepare_config_and_inputs()
273+
self.model_tester.create_and_check_for_question_answering(
274+
*config_and_inputs)
275+
276+
def test_for_sequence_classification(self):
277+
config_and_inputs = self.model_tester.prepare_config_and_inputs()
278+
self.model_tester.create_and_check_for_sequence_classification(
279+
*config_and_inputs)
280+
281+
def test_for_token_classification(self):
282+
config_and_inputs = self.model_tester.prepare_config_and_inputs()
283+
self.model_tester.create_and_check_for_token_classification(
284+
*config_and_inputs)
285+
286+
@slow
287+
def test_model_from_pretrained(self):
288+
for model_name in list(
289+
RoFormerPretrainedModel.pretrained_init_configuration)[:1]:
290+
model = RoFormerModel.from_pretrained(model_name)
291+
self.assertIsNotNone(model)
292+
293+
294+
class RoFormerModelIntegrationTest(unittest.TestCase):
295+
296+
@slow
297+
def test_inference_no_attention(self):
298+
model = RoFormerModel.from_pretrained("roformer-chinese-small")
299+
model.eval()
300+
input_ids = paddle.to_tensor(
301+
[[0, 345, 232, 328, 740, 140, 1695, 69, 6078, 1588, 2]])
302+
with paddle.no_grad():
303+
output = model(input_ids)[0]
304+
expected_shape = [1, 11, 384]
305+
self.assertEqual(output.shape, expected_shape)
306+
307+
expected_slice = paddle.to_tensor(
308+
[[[0.17788891, -2.17795515, 0.28824317],
309+
[-1.70342600, -2.84062195, -0.53377795],
310+
[-0.16374627, -0.67967212, -0.37192002]]])
311+
312+
self.assertTrue(
313+
paddle.allclose(output[:, 1:4, 1:4], expected_slice, atol=1e-4))
314+
315+
@slow
316+
def test_inference_with_attention(self):
317+
model = RoFormerModel.from_pretrained("roformer-chinese-small")
318+
model.eval()
319+
input_ids = paddle.to_tensor(
320+
[[0, 345, 232, 328, 740, 140, 1695, 69, 6078, 1588, 2]])
321+
attention_mask = paddle.to_tensor([[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
322+
with paddle.no_grad():
323+
output = model(input_ids, attention_mask=attention_mask)[0]
324+
expected_shape = [1, 11, 384]
325+
self.assertEqual(output.shape, expected_shape)
326+
327+
expected_slice = paddle.to_tensor(
328+
[[[0.17788891, -2.17795515, 0.28824317],
329+
[-1.70342600, -2.84062195, -0.53377795],
330+
[-0.16374627, -0.67967212, -0.37192002]]])
331+
self.assertTrue(
332+
paddle.allclose(output[:, 1:4, 1:4], expected_slice, atol=1e-4))
333+
334+
335+
if __name__ == "__main__":
336+
unittest.main()

0 commit comments

Comments
 (0)