Skip to main content

Transformer-based models implemented in tensorflow 2.x(Keras)

Project description

transformers-keras

Python package PyPI version Python

English | 中文文档

基于tf.keras的Transformers系列模型实现。

所有的Model都是keras模型,可以直接用于训练模型、评估模型或者导出模型用于部署。

目录

安装

pip install -U transformers-keras

安装依赖:

pip install tensorflow tensorflow-addons

支持加载的预训练权重

支持加载的预训练BERT模型权重:

支持加载的预训练ALBERT模型权重:

简单使用示例

这里是基于BERT的模型的使用示例。所有基于ALBERT的模型用法和BERT类似,所以这里只使用BERT为例,不再重复用ALBERT举例。

对这个库的模型使用有任何疑问,首先推荐看源代码中的各个模型实现,它们提供了很好的示例。也欢迎开issue讨论。

BERT特征抽取示例

from transformers_keras import Bert

# 加载预训练模型权重
model = Bert.from_pretrained('/path/to/pretrained/bert/model')
input_ids = tf.constant([[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]])
segment_ids = tf.constant([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
attention_mask = tf.constant([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
sequence_outputs, pooled_output = model(inputs=[input_ids, segmet_ids, attention_mask], training=False)

另外,可以通过构造器参数 return_states=Truereturn_attention_weights=True 来获取每一层的 hidden_statesattention_weights 输出:

from transformers_keras import Bert

# 加载预训练模型权重
model = Bert.from_pretrained(
    '/path/to/pretrained/bert/model', 
    return_states=True, 
    return_attention_weights=True)
input_ids = tf.constant([[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]])
segment_ids = tf.constant([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
attention_mask = tf.constant([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
sequence_outputs, pooled_output, hidden_states, attn_weights = model(
    inputs=[input_ids, segment_ids, attention_mask], training=False)

BERT微调模型示例

微调模型有两种风格,一种是使用keras functional api构建新的模型,一种是直接subclassing Model的方式。

这里提供一个使用functional api构建微调模型的例子:

这里提供两个预制的微调模型,都是使用subclassing的方式实现的:

使用函数式API构建BERT微调模型

以构建一个序列分类网络为例:

from transformers_keras import Bert

input_ids = tf.keras.layers.Input(shape=(None,), dtype=tf.int32, name='input_ids')
segment_ids = tf.keras.layers.Input(shape=(None,), dtype=tf.int32, name='segment_ids')
attention_mask = tf.keras.layers.Input(shape=(None,), dtype=tf.int32, name='attention_mask')
bert = Bert.from_pretrained('/path/to/pretrained/model')
_, pooled_output = bert(inputs=[input_ids, segment_ids, attention_mask])
outputs = tf.keras.layers.Dense(2, name='output')(pooled_output)
model = tf.keras.Model(inputs=[input_ids, segment_ids, attention_mask], outputs=outputs)
model.compile(loss='binary_cross_entropy', optimizer='adam')
model.summary()

可以得到以下的网络输出:

Model: "model"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_ids (InputLayer)          [(None, None)]       0                                            
__________________________________________________________________________________________________
segment_ids (InputLayer)        [(None, None)]       0                                            
__________________________________________________________________________________________________
attention_mask (InputLayer)     [(None, None)]       0                                            
__________________________________________________________________________________________________
bert (Bert)                     [(None, None, 768),  102267648   input_ids[0][0]                  
                                                                 segment_ids[0][0]                
                                                                 attention_mask[0][0]             
__________________________________________________________________________________________________
output (Dense)                  (None, 2)            1538        bert[0][1]                       
==================================================================================================
Total params: 102,269,186
Trainable params: 102,269,186
Non-trainable params: 0
__________________________________________________________________________________________________

使用预制的BertForSequenceClassification

你可以使用BERT构建序列的二分类网络:

from transformers_keras import BertForSequenceClassification

model = BertForSequenceClassification.from_pretrained('/path/to/pretrained/model')
model.summary()

model.compile(
    loss='binary_crossentropy',
    optimizer='adam',
    metrics=['acc']
)
model.fit(train_dataset, epoch=10, callbacks=[])

可以得到下面的模型输出:

Model: "bert_for_sequence_classification"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_ids (InputLayer)          [(None, None)]       0                                            
__________________________________________________________________________________________________
segment_ids (InputLayer)        [(None, None)]       0                                            
__________________________________________________________________________________________________
attention_mask (InputLayer)     [(None, None)]       0                                            
__________________________________________________________________________________________________
bert (BertModel)                ((None, None, 768),  59740416    input_ids[0][0]                  
                                                                 segment_ids[0][0]                
                                                                 attention_mask[0][0]             
__________________________________________________________________________________________________
dense (Dense)                   (None, 2)            1538        bert[0][1]                       
==================================================================================================
Total params: 59,741,954
Trainable params: 59,741,954
Non-trainable params: 0
__________________________________________________________________________________________________

使用预制的BertForQuestionAnswering

另一个例子,使用BERT来做Question Answering:

from transformers_keras import BertForQuestionAnswering

model = BertForQuestionAnswering.from_pretrained('/path/to/pretrained/model')
model.summary()

model.compile(
    loss='sparse_categorical_crossentropy',
    optimizer='adam',
    metrics=['acc']
)
model.fit(train_dataset, epoch=10, callbacks=[])

可以得到下面的模型输出:

Model: "bert_for_question_answering"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_ids (InputLayer)          [(None, None)]       0                                            
__________________________________________________________________________________________________
segment_ids (InputLayer)        [(None, None)]       0                                            
__________________________________________________________________________________________________
attention_mask (InputLayer)     [(None, None)]       0                                            
__________________________________________________________________________________________________
bert (BertModel)                ((None, None, 768),  59740416    input_ids[0][0]                  
                                                                 segment_ids[0][0]                
                                                                 attention_mask[0][0]             
__________________________________________________________________________________________________
dense (Dense)                   (None, None, 2)      1538        bert[0][0]                       
__________________________________________________________________________________________________
head (Lambda)                   (None, None)         0           dense[0][0]                      
__________________________________________________________________________________________________
tail (Lambda)                   (None, None)         0           dense[0][0]                      
==================================================================================================
Total params: 59,741,954
Trainable params: 59,741,954
Non-trainable params: 0
__________________________________________________________________________________________________

BERT导出SavedModel格式的模型用Serving部署

你可以很方便地把模型转换成SavedModel格式。

这里是直接把BERT模型导出部署的示例:

# 加载预训练模型权重
model = Bert.from_pretrained(
    '/path/to/pretrained/bert/model', 
    return_states=True, 
    return_attention_weights=True)
model.save('/path/to/save')

接下来,就可以使用 tensorflow/serving 来部署模型了。

本项目所有的模型,都可以使用这种方式导出成SavedModel格式,然后直接用serving部署。

完整解决方案

目前上述目录提到的模型都已经实现了。但是具体的使用文档还没有更新。

其实使用起来非常简单,等不及的朋友可以可以阅读源码,然后自己实现下游各种任务。

TODO:

  • [] 集成各个下游任务的数据预处理
  • [] 增加各个下游任务的训练脚本
  • [] 增加各个下游任务完整的使用文档。

进阶使用

支持的高级使用方法:

  • 加载预训练模型权重的过程中跳过一些参数的权重
  • 加载第三方实现的模型的权重

加载预训练模型权重的过程中跳过一些参数的权重

有些情况下,你可能会在加载预训练权重的过程中,跳过一些权重的加载。这个过程很简单。

这里是一个示例:

from transformers_keras import Bert, Albert

ALBERT_MODEL_PATH = '/path/to/albert/model'
albert = Albert.from_pretrained(
    ALBERT_MODEL_PATH,
    # return_states=False,
    # return_attention_weights=False,
    skip_token_embedding=True,
    skip_position_embedding=True,
    skip_segment_embedding=True,
    skip_pooler=True,
    ...
    )

BERT_MODEL_PATH = '/path/to/bert/model'
bert = Bert.from_pretrained(
    BERT_MODEL_PATH,
    # return_states=False,
    # return_attention_weights=False,
    skip_token_embedding=True,
    skip_position_embedding=True,
    skip_segment_embedding=True,
    skip_pooler=True,
    ...
    )

所有支持跳过加载的权重如下:

  • skip_token_embedding, 跳过加载ckpt的 token_embedding 权重
  • skip_position_embedding, 跳过加载ckpt的 position_embedding 权重
  • skip_segment_embedding, 跳过加载ckpt的 token_type_emebdding 权重
  • skip_embedding_layernorm, 跳过加载ckpt的 layer_norm 权重
  • skip_pooler, 跳过加载ckpt的 pooler 权重

加载第三方实现的模型的权重

在有一些情况下,第三方实现了一些模型,它的权重的结构组织和官方的实现不太一样。对于一般的预训练加载库,实现这个功能是需要库本身修改代码来实现的。本库通过 适配器模式 提供了这种支持。用户只需要继承 AbstractAdapter 即可实现自定义的权重加载逻辑。

from transformers_keras.adapters import AbstractAdapter
from transformers_keras import Bert, Albert

# 自定义的BERT权重适配器
class MyBertAdapter(AbstractAdapter):

    def adapte_config(self, config_file, **kwargs):
        # 在这里把配置文件的配置项,转化成本库的BERT需要的配置
        # 本库实现的BERT所需参数都在构造器里,可以简单方便得查看
        pass

    def adapte_weights(self, model, config, ckpt, **kwargs):
        # 在这里把ckpt的权重设置到model的权重里
        # 可以参考BertAdapter的实现过程
        pass

# 加载预训练权重的时候,指定自己的适配器 `adapter=MyBertAdapter()`
bert = Bert.from_pretrained('/path/to/your/bert/model', adapter=MyBertAdapter())

# 自定义的ALBERT权重适配器
class MyAlbertAdapter(AbstractAdapter):

    def adapte_config(self, config_file, **kwargs):
        # 在这里把配置文件的配置项,转化成本库的BERT需要的配置
        # 本库实现的ALBERT所需参数都在构造器里,可以简单方便得查看
        pass

    def adapte_weights(self, model, config, ckpt, **kwargs):
        # 在这里把ckpt的权重设置到model的权重里
        # 可以参考AlbertAdapter的实现过程
        pass

# 加载预训练权重的时候,指定自己的适配器 `adapter=MyAlbertAdapter()`
albert = Albert.from_pretrained('/path/to/your/albert/model', adapter=MyAlbertAdapter())

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

transformers_keras-0.4.3.tar.gz (41.1 kB view hashes)

Uploaded Source

Built Distribution

transformers_keras-0.4.3-py3-none-any.whl (57.8 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page