【发布时间】:2021-11-10 17:02:33
【问题描述】:
我通过以下方式从 HuggingFace 的 transformers 获得了预训练的 BERT 和相应的分词器:
from transformers import AutoTokenizer, TFBertModel
model_name = "dbmdz/bert-base-italian-xxl-cased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
bert = TFBertModel.from_pretrained(model_name)
模型将收到一系列意大利推文,并且需要确定它们是否具有讽刺意味。
我在构建模型的初始部分时遇到问题,该部分接受输入并将它们提供给标记器,以便获得可以提供给 BERT 的表示。
我可以在模型构建环境之外进行:
my_phrase = "Ciao, come va?"
# an equivalent version is tokenizer(my_phrase, other parameters)
bert_input = tokenizer.encode(my_phrase, add_special_tokens=True, return_tensors='tf', max_length=110, padding='max_length', truncation=True)
attention_mask = bert_input > 0
outputs = bert(bert_input, attention_mask)['pooler_output']
但我在构建执行此操作的模型时遇到了麻烦。这是构建这样一个模型的代码(问题出在前 4 行):
def build_classifier_model():
text_input = tf.keras.layers.Input(shape=(), dtype=tf.string, name='text')
encoder_inputs = tokenizer(text_input, return_tensors='tf', add_special_tokens=True, max_length=110, padding='max_length', truncation=True)
outputs = bert(encoder_inputs)
net = outputs['pooler_output']
X = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64, return_sequences=True, dropout=0.1, recurrent_dropout=0.1))(net)
X = tf.keras.layers.Concatenate(axis=-1)([X, input_layer])
X = tf.keras.layers.MaxPooling1D(20)(X)
X = tf.keras.layers.SpatialDropout1D(0.4)(X)
X = tf.keras.layers.Flatten()(X)
X = tf.keras.layers.Dense(128, activation="relu")(X)
X = tf.keras.layers.Dropout(0.25)(X)
X = tf.keras.layers.Dense(2, activation='softmax')(X)
model = tf.keras.Model(inputs=text_input, outputs = X)
return model
当我调用创建这个模型的函数时,我得到了这个错误:
文本输入必须是
str(单个示例)、List[str](批量或单个预标记示例)或List[List[str]](预标记示例)类型。
我想到的一件事是,也许我必须使用tokenizer.batch_encode_plus 函数,它适用于字符串列表:
class BertPreprocessingLayer(tf.keras.layers.Layer):
def __init__(self, tokenizer, maxlength):
super().__init__()
self._tokenizer = tokenizer
self._maxlength = maxlength
def call(self, inputs):
print(type(inputs))
print(inputs)
tokenized = tokenizer.batch_encode_plus(inputs, add_special_tokens=True, return_tensors='tf', max_length=self._maxlength, padding='max_length', truncation=True)
return tokenized
def build_classifier_model():
text_input = tf.keras.layers.Input(shape=(), dtype=tf.string, name='text')
encoder_inputs = BertPreprocessingLayer(tokenizer, 100)(text_input)
outputs = bert(encoder_inputs)
net = outputs['pooler_output']
# ... same as above
但我收到此错误:
batch_text_or_text_pairs 必须是一个列表(得到
)
除了我还没有找到一种通过快速谷歌搜索将该张量转换为列表的方法之外,我必须以这种方式进出张量流似乎很奇怪。
我还查看了 huggingface 的 documentation,但只有一个使用示例,只有一个短语,他们所做的与我的“脱离模型构建上下文”示例类似。
编辑:
我也用这种方式尝试过Lambdas:
tf.executing_eagerly()
def tokenize_tensor(tensor):
t = tensor.numpy()
t = np.array([str(s, 'utf-8') for s in t])
return tokenizer(t.tolist(), return_tensors='tf', add_special_tokens=True, max_length=110, padding='max_length', truncation=True)
def build_classifier_model():
text_input = tf.keras.layers.Input(shape=(1,), dtype=tf.string, name='text')
encoder_inputs = tf.keras.layers.Lambda(tokenize_tensor, name='tokenize')(text_input)
...
outputs = bert(encoder_inputs)
但我收到以下错误:
“张量”对象没有属性“numpy”
编辑 2:
我还尝试了@mdaoust 建议的将所有内容包装在tf.py_function 中的方法并得到了这个错误。
def py_func_tokenize_tensor(tensor):
return tf.py_function(tokenize_tensor, [tensor], Tout=[tf.int32, tf.int32, tf.int32])
eager_py_func() 缺少 1 个必需的位置参数:'Tout'
然后我将 Tout 定义为分词器返回的值的类型:
transformers.tokenization_utils_base.BatchEncoding
并得到以下错误:
参数“Tout”的预期数据类型不是
最后我通过以下方式解压了 BatchEncoding 中的值:
def tokenize_tensor(tensor):
t = tensor.numpy()
t = np.array([str(s, 'utf-8') for s in t])
dictionary = tokenizer(t.tolist(), return_tensors='tf', add_special_tokens=True, max_length=110, padding='max_length', truncation=True)
#unpacking
input_ids = dictionary['input_ids']
tok_type = dictionary['token_type_ids']
attention_mask = dictionary['attention_mask']
return input_ids, tok_type, attention_mask
并在下面的行中得到一个错误:
...
outputs = bert(encoder_inputs)
ValueError: 无法获取未知等级的形状长度。
【问题讨论】:
标签: tensorflow keras huggingface-transformers bert-language-model huggingface-tokenizers