[中文|英語]
BERTの実装。公式の事前トレーニング済みモデルをロードして、特徴の抽出と予測を行うことができます。
pip install keras-bert
特徴抽出デモでは、公式モデルchinese_L-12_H-768_A-12
と同じ抽出結果が得られるはずです。また、予測デモでは、文中の欠落している単語を予測することができました。
抽出デモでは、TPU で実行されるモデルに変換する方法を示します。
分類デモでは、モデルを単純な分類タスクに適用する方法を示します。
Tokenizer
クラスは、テキストの分割とインデックスの生成に使用されます。
from keras_bert import Tokenizer
token_dict = {
'[CLS]' : 0 ,
'[SEP]' : 1 ,
'un' : 2 ,
'##aff' : 3 ,
'##able' : 4 ,
'[UNK]' : 5 ,
}
tokenizer = Tokenizer ( token_dict )
print ( tokenizer . tokenize ( 'unaffable' )) # The result should be `['[CLS]', 'un', '##aff', '##able', '[SEP]']`
indices , segments = tokenizer . encode ( 'unaffable' )
print ( indices ) # Should be `[0, 2, 3, 4, 1]`
print ( segments ) # Should be `[0, 0, 0, 0, 0]`
print ( tokenizer . tokenize ( first = 'unaffable' , second = '钢' ))
# The result should be `['[CLS]', 'un', '##aff', '##able', '[SEP]', '钢', '[SEP]']`
indices , segments = tokenizer . encode ( first = 'unaffable' , second = '钢' , max_len = 10 )
print ( indices ) # Should be `[0, 2, 3, 4, 1, 5, 1, 0, 0, 0]`
print ( segments ) # Should be `[0, 0, 0, 0, 0, 1, 1, 0, 0, 0]`
from tensorflow import keras
from keras_bert import get_base_dict , get_model , compile_model , gen_batch_inputs
# A toy input example
sentence_pairs = [
[[ 'all' , 'work' , 'and' , 'no' , 'play' ], [ 'makes' , 'jack' , 'a' , 'dull' , 'boy' ]],
[[ 'from' , 'the' , 'day' , 'forth' ], [ 'my' , 'arm' , 'changed' ]],
[[ 'and' , 'a' , 'voice' , 'echoed' ], [ 'power' , 'give' , 'me' , 'more' , 'power' ]],
]
# Build token dictionary
token_dict = get_base_dict () # A dict that contains some special tokens
for pairs in sentence_pairs :
for token in pairs [ 0 ] + pairs [ 1 ]:
if token not in token_dict :
token_dict [ token ] = len ( token_dict )
token_list = list ( token_dict . keys ()) # Used for selecting a random word
# Build & train the model
model = get_model (
token_num = len ( token_dict ),
head_num = 5 ,
transformer_num = 12 ,
embed_dim = 25 ,
feed_forward_dim = 100 ,
seq_len = 20 ,
pos_num = 20 ,
dropout_rate = 0.05 ,
)
compile_model ( model )
model . summary ()
def _generator ():
while True :
yield gen_batch_inputs (
sentence_pairs ,
token_dict ,
token_list ,
seq_len = 20 ,
mask_rate = 0.3 ,
swap_sentence_rate = 1.0 ,
)
model . fit_generator (
generator = _generator (),
steps_per_epoch = 1000 ,
epochs = 100 ,
validation_data = _generator (),
validation_steps = 100 ,
callbacks = [
keras . callbacks . EarlyStopping ( monitor = 'val_loss' , patience = 5 )
],
)
# Use the trained model
inputs , output_layer = get_model (
token_num = len ( token_dict ),
head_num = 5 ,
transformer_num = 12 ,
embed_dim = 25 ,
feed_forward_dim = 100 ,
seq_len = 20 ,
pos_num = 20 ,
dropout_rate = 0.05 ,
training = False , # The input layers and output layer will be returned if `training` is `False`
trainable = False , # Whether the model is trainable. The default value is the same with `training`
output_layer_num = 4 , # The number of layers whose outputs will be concatenated as a single output.
# Only available when `training` is `False`.
)
AdamWarmup
オプティマイザーはウォームアップとディケイのために提供されています。学習率は、 warmpup_steps
ステップでlr
に達し、 decay_steps
ステップでmin_lr
まで減衰します。 2 つのステップを計算するためのヘルパー関数calc_train_steps
があります。
import numpy as np
from keras_bert import AdamWarmup , calc_train_steps
train_x = np . random . standard_normal (( 1024 , 100 ))
total_steps , warmup_steps = calc_train_steps (
num_example = train_x . shape [ 0 ],
batch_size = 32 ,
epochs = 10 ,
warmup_proportion = 0.1 ,
)
optimizer = AdamWarmup ( total_steps , warmup_steps , lr = 1e-3 , min_lr = 1e-5 )
いくつかのダウンロード URL が追加されました。ダウンロードして圧縮されていないチェックポイントのパスは、次の方法で取得できます。
from keras_bert import get_pretrained , PretrainedList , get_checkpoint_paths
model_path = get_pretrained ( PretrainedList . multi_cased_base )
paths = get_checkpoint_paths ( model_path )
print ( paths . config , paths . checkpoint , paths . vocab )
トークンまたは文の特徴が (さらに調整せずに) 必要な場合は、ヘルパー関数extract_embeddings
使用できます。すべてのトークンの特徴を抽出するには:
from keras_bert import extract_embeddings
model_path = 'xxx/yyy/uncased_L-12_H-768_A-12'
texts = [ 'all work and no play' , 'makes jack a dull boy~' ]
embeddings = extract_embeddings ( model_path , texts )
返される結果は、テキストと同じ長さのリストです。リスト内の各項目は、入力の長さによって切り詰められた numpy 配列です。この例の出力の形状は(7, 768)
と(8, 768)
です。
入力がペアになった文で、 NSP
の出力と最後の 4 層の最大プーリングが必要な場合:
from keras_bert import extract_embeddings , POOL_NSP , POOL_MAX
model_path = 'xxx/yyy/uncased_L-12_H-768_A-12'
texts = [
( 'all work and no play' , 'makes jack a dull boy' ),
( 'makes jack a dull boy' , 'all work and no play' ),
]
embeddings = extract_embeddings ( model_path , texts , output_layer_num = 4 , poolings = [ POOL_NSP , POOL_MAX ])
結果にはトークンの特徴はありません。 NSP
と max-pooling の出力は、最終的な形状(768 x 4 x 2,)
と連結されます。
ヘルパー関数の 2 番目の引数はジェネレーターです。ファイルから特徴を抽出するには:
import codecs
from keras_bert import extract_embeddings
model_path = 'xxx/yyy/uncased_L-12_H-768_A-12'
with codecs . open ( 'xxx.txt' , 'r' , 'utf8' ) as reader :
texts = map ( lambda x : x . strip (), reader )
embeddings = extract_embeddings ( model_path , texts )