モデル概要
モデル特徴
モデル能力
使用事例
🚀 BERT-th
このプロジェクトは、ThAIKeras/bert をベースに、HuggingFace/Transformersライブラリに適応させたものです。
🚀 クイックスタート
元のモデルのトークン化と一致させるために、元のThaiTokenizerを実行する必要があります。この手順をスキップすると、mBERTやランダムな予測と大差なくなってしまいます!
このCoLabノートブックを参照 するか、以下の手順に従ってください。
pip install pythainlp six sentencepiece python-crfsuite
git clone https://github.com/ThAIKeras/bert
# ThAIKeras/bert > Tokenizationセクションから.vocabと.modelファイルをダウンロード
または、.vocab と .model のリンクからダウンロードすることもできます。
その後、TensorFlowの依存関係を削除するように若干修正されたThaiTokenizerクラスを設定します。
import collections
import unicodedata
import six
def convert_to_unicode(text):
"""Converts `text` to Unicode (if it's not already), assuming utf-8 input."""
if six.PY3:
if isinstance(text, str):
return text
elif isinstance(text, bytes):
return text.decode("utf-8", "ignore")
else:
raise ValueError("Unsupported string type: %s" % (type(text)))
elif six.PY2:
if isinstance(text, str):
return text.decode("utf-8", "ignore")
elif isinstance(text, unicode):
return text
else:
raise ValueError("Unsupported string type: %s" % (type(text)))
else:
raise ValueError("Not running on Python2 or Python 3?")
def load_vocab(vocab_file):
vocab = collections.OrderedDict()
index = 0
with open(vocab_file, "r") as reader:
while True:
token = reader.readline()
if token.split(): token = token.split()[0] # to support SentencePiece vocab file
token = convert_to_unicode(token)
if not token:
break
token = token.strip()
vocab[token] = index
index += 1
return vocab
#####
from bert.bpe_helper import BPE
import sentencepiece as spm
def convert_by_vocab(vocab, items):
output = []
for item in items:
output.append(vocab[item])
return output
class ThaiTokenizer(object):
"""Tokenizes Thai texts."""
def __init__(self, vocab_file, spm_file):
self.vocab = load_vocab(vocab_file)
self.inv_vocab = {v: k for k, v in self.vocab.items()}
self.bpe = BPE(vocab_file)
self.s = spm.SentencePieceProcessor()
self.s.Load(spm_file)
def tokenize(self, text):
bpe_tokens = self.bpe.encode(text).split(' ')
spm_tokens = self.s.EncodeAsPieces(text)
tokens = bpe_tokens if len(bpe_tokens) < len(spm_tokens) else spm_tokens
split_tokens = []
for token in tokens:
new_token = token
if token.startswith('_') and not token in self.vocab:
split_tokens.append('_')
new_token = token[1:]
if not new_token in self.vocab:
split_tokens.append('<unk>')
else:
split_tokens.append(new_token)
return split_tokens
def convert_tokens_to_ids(self, tokens):
return convert_by_vocab(self.vocab, tokens)
def convert_ids_to_tokens(self, ids):
return convert_by_vocab(self.inv_vocab, ids)
次に、独自のテキストを事前トークン化します。
from pythainlp import sent_tokenize
tokenizer = ThaiTokenizer(vocab_file='th.wiki.bpe.op25000.vocab', spm_file='th.wiki.bpe.op25000.model')
txt = "กรุงเทพมหานครเป็นเขตปกครองพิเศษของประเทศไทย มิได้มีสถานะเป็นจังหวัด คำว่า \"กรุงเทพมหานคร\" นั้นยังใช้เรียกองค์กรปกครองส่วนท้องถิ่นของกรุงเทพมหานครอีกด้วย"
split_sentences = sent_tokenize(txt)
print(split_sentences)
"""
['กรุงเทพมหานครเป็นเขตปกครองพิเศษของประเทศไทย ',
'มิได้มีสถานะเป็นจังหวัด ',
'คำว่า "กรุงเทพมหานคร" นั้นยังใช้เรียกองค์กรปกครองส่วนท้องถิ่นของกรุงเทพมหานครอีกด้วย']
"""
split_words = ' '.join(tokenizer.tokenize(' '.join(split_sentences)))
print(split_words)
"""
'▁กรุงเทพมหานคร เป็นเขต ปกครอง พิเศษ ของประเทศไทย ▁มิ ได้มี สถานะเป็น จังหวัด ▁คําว่า ▁" กรุงเทพมหานคร " ▁นั้น...' # continues
"""
📦 インストール
前処理
データソース
BERT-thの学習データは、2018年11月2日の 最新のタイ語ウィキペディアの記事ダンプ から取得されます。生テキストは WikiExtractor を使用して抽出されます。
文章分割
入力データは、BERTモジュールによるさらなる処理の前に、個々の文章に分割する必要があります。タイ語には文章の終わりを明示するマーカーがないため、文章の境界を特定するのはかなり難しい問題です。私たちの知る限り、他にタイ語の文章分割の実装はありません。そのため、このプロジェクトでは、空白、文章の長さ、一般的な接続詞を考慮した単純なヒューリスティックを適用して文章分割を行っています。
前処理後の学習コーパスは、約200万文と4000万語(PyThaiNLP による単語分割後の語数)で構成されています。平文と分割されたテキストは ここ からダウンロードできます。
トークン化
BERTはトークン化メカニズムとして WordPiece を使用していますが、これはGoogleの内部技術であるため、既存のタイ語の単語分割を適用してからWordPieceを利用してサブワードユニットのセットを学習することはできません。最適な代替手段は SentencePiece で、これは BPE を実装しており、単語分割を必要としません。
このプロジェクトでは、BPEmb から事前学習されたタイ語のSentencePieceモデルを採用しています。25000語彙のモデルが選択され、語彙ファイルにはBERTの特殊文字 '[PAD]'、'[CLS]'、'[SEP]'、'[MASK]' が追加されています。モデルと語彙ファイルは ここ からダウンロードできます。
SentencePiece
とBPEmbの bpe_helper.py
は両方ともデータをトークン化するために使用されます。ThaiTokenizerクラス
は、タイ語のテキストをトークン化するためにBERTの tokenization.py
に追加されています。
事前学習
事前学習の前に、このスクリプトを使用してデータを準備することができます。
export BPE_DIR=/path/to/bpe
export TEXT_DIR=/path/to/text
export DATA_DIR=/path/to/data
python create_pretraining_data.py \
--input_file=$TEXT_DIR/thaiwikitext_sentseg \
--output_file=$DATA_DIR/tf_examples.tfrecord \
--vocab_file=$BPE_DIR/th.wiki.bpe.op25000.vocab \
--max_seq_length=128 \
--max_predictions_per_seq=20 \
--masked_lm_prob=0.15 \
--random_seed=12345 \
--dupe_factor=5 \
--thai_text=True \
--spm_file=$BPE_DIR/th.wiki.bpe.op25000.model
次に、以下のスクリプトを実行して、モデルをゼロから学習させることができます。
export DATA_DIR=/path/to/data
export BERT_BASE_DIR=/path/to/bert_base
python run_pretraining.py \
--input_file=$DATA_DIR/tf_examples.tfrecord \
--output_dir=$BERT_BASE_DIR \
--do_train=True \
--do_eval=True \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--train_batch_size=32 \
--max_seq_length=128 \
--max_predictions_per_seq=20 \
--num_train_steps=1000000 \
--num_warmup_steps=100000 \
--learning_rate=1e-4 \
--save_checkpoints_steps=200000
私たちは、モデルを100万ステップ学習させました。Tesla K80 GPUでは、完了するまでに約20日かかりました。ただし、下流の分類タスクでより良い結果が得られるため、80万ステップのスナップショットを提供しています。
💻 使用例
下流分類タスク
XNLI
XNLI は、クロス言語の推論分類タスクを評価するためのデータセットです。開発セットとテストセットには15の言語が含まれており、データは十分に編集されています。学習データの機械翻訳版も提供されています。
タイ語専用の事前学習済みBERTモデルは、タイ語に翻訳された学習データを使用してXNLIタスクに適用することができます。学習データの単語間の空白は、事前学習ステップの入力と一致させるために削除する必要があります。タイ語に関連するXNLIの処理済みファイルは ここ からダウンロードできます。
その後、このスクリプトを使用してXNLIタスクを学習させることができます。
export BPE_DIR=/path/to/bpe
export XNLI_DIR=/path/to/xnli
export OUTPUT_DIR=/path/to/output
export BERT_BASE_DIR=/path/to/bert_base
python run_classifier.py \
--task_name=XNLI \
--do_train=true \
--do_eval=true \
--data_dir=$XNLI_DIR \
--vocab_file=$BPE_DIR/th.wiki.bpe.op25000.vocab \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--init_checkpoint=$BERT_BASE_DIR/model.ckpt \
--max_seq_length=128 \
--train_batch_size=32 \
--learning_rate=5e-5 \
--num_train_epochs=2.0 \
--output_dir=$OUTPUT_DIR \
--xnli_language=th \
--spm_file=$BPE_DIR/th.wiki.bpe.op25000.model
この表は、タイ語専用モデルをXNLIのベースラインと、翻訳データを使用して学習された多言語ケースモデルと比較しています。
XNLI Baseline | BERT | ||
Translate Train | Translate Test | Multilingual Model | Thai-only Model | 62.8 | 64.4 | 66.1 | 68.9 |
Wongnaiレビューデータセット
Wongnaiレビューデータセットは、Wongnai ウェブサイトからレストランのレビューと評価を収集しています。このタスクは、レビューを5つの評価(1〜5星)のいずれかに分類することです。データセットは ここ からダウンロードでき、以下のスクリプトを実行することで、このタスクにタイ語専用モデルを使用することができます。
export BPE_DIR=/path/to/bpe
export WONGNAI_DIR=/path/to/wongnai
export OUTPUT_DIR=/path/to/output
export BERT_BASE_DIR=/path/to/bert_base
python run_classifier.py \
--task_name=wongnai \
--do_train=true \
--do_predict=true \
--data_dir=$WONGNAI_DIR \
--vocab_file=$BPE_DIR/th.wiki.bpe.op25000.vocab \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--init_checkpoint=$BERT_BASE_DIR/model.ckpt \
--max_seq_length=128 \
--train_batch_size=32 \
--learning_rate=5e-5 \
--num_train_epochs=2.0 \
--output_dir=$OUTPUT_DIR \
--spm_file=$BPE_DIR/th.wiki.bpe.op25000.model
追加の前処理やさらなる微調整なしで、タイ語専用のBERTモデルは、公開テストセットと非公開テストセットのスコアでそれぞれ0.56612と0.57057を達成することができます。



