TensorFlow.org'da görüntüleyin | Google Colab'da çalıştırın | GitHub'da görüntüle | Not defterini indir |
genel bakış
Metin ön işleme, ham metnin bir modelin tamsayı girdilerine uçtan uca dönüştürülmesidir. NLP modellerine genellikle metnin ön işlemesi için yüzlerce (binlerce değilse) Python kodu satırı eşlik eder. Metin ön işleme, genellikle modeller için bir zorluktur çünkü:
Eğitim-hizmet çarpıklığı. Modelin girdilerinin ön işleme mantığının model geliştirmenin tüm aşamalarında (örn. ön eğitim, ince ayar, değerlendirme, çıkarım) tutarlı olmasını sağlamak giderek zorlaşıyor. Farklı hiperparametreler, belirteçleştirme, dizi ön işleme algoritmaları veya basitçe model girdilerini farklı aşamalarda tutarsız bir şekilde paketlemek, modelde hata ayıklaması zor ve yıkıcı etkiler yaratabilir.
Verimlilik ve esneklik. Ön işleme çevrimdışı yapılabilirken (örneğin, işlenmiş çıktıları diskteki dosyalara yazarak ve ardından söz konusu önceden işlenmiş verileri giriş hattında yeniden kullanarak), bu yöntem ek bir dosya okuma ve yazma maliyetine neden olur. Dinamik olarak gerçekleşmesi gereken ön işleme kararları varsa, çevrimdışı ön işleme de uygun değildir. Farklı bir seçenekle deneme yapmak, veri kümesinin yeniden oluşturulmasını gerektirir.
Karmaşık model arayüzü. Metin modelleri, girdileri salt metin olduğunda çok daha anlaşılırdır. Girdileri fazladan, dolaylı bir kodlama adımı gerektirdiğinde bir modeli anlamak zordur. Ön işleme karmaşıklığının azaltılması, özellikle model hata ayıklama, sunma ve değerlendirme için takdir edilmektedir.
Ek olarak, daha basit model arayüzleri, modeli farklı, keşfedilmemiş veri kümeleri üzerinde denemeyi (örn. çıkarım veya eğitim) daha uygun hale getirir.
TF.Text ile metin ön işleme
TF.Text'in metin ön işleme API'lerini kullanarak, bir kullanıcının metin veri setini modelin tamsayı girdilerine dönüştürebilen bir ön işleme işlevi oluşturabiliriz. Kullanıcılar, yukarıda belirtilen sorunları hafifletmek için ön işlemeyi doğrudan modellerinin bir parçası olarak paketleyebilir.
Bu eğitimde "Maskeli LM ve Maskeleme Prosedürü" nün anlatıldığı Bert modeli ve görevi antrenman öncesi maskeleme dil için girişler için girişler içine metin verileri dönüştürmek için TF.Text önişleme ops nasıl kullanılacağını gösterecek Dili Derin Çift yönlü Transformers Öncesi Eğitim: bert anlama . İşlem, metni alt sözcük birimlerine ayırmayı, cümleleri birleştirmeyi, içeriği sabit bir boyuta kırpmayı ve maskeli dil modelleme görevi için etiketleri çıkarmayı içerir.
Kurmak
İlk önce ihtiyacımız olan paketleri ve kütüphaneleri import edelim.
pip install -q -U tensorflow-text
import tensorflow as tf
import tensorflow_text as text
import functools
Bizim veriler iki metin özellikleri içerir ve bir örnek oluşturabilir tf.data.Dataset
. Amacımız sağlayabilmektedir bir işlev oluşturmaktır Dataset.map()
eğitimde kullanılmak üzere olan.
examples = {
"text_a": [
b"Sponge bob Squarepants is an Avenger",
b"Marvel Avengers"
],
"text_b": [
b"Barack Obama is the President.",
b"President is the highest office"
],
}
dataset = tf.data.Dataset.from_tensor_slices(examples)
next(iter(dataset))
{'text_a': <tf.Tensor: shape=(), dtype=string, numpy=b'Sponge bob Squarepants is an Avenger'>, 'text_b': <tf.Tensor: shape=(), dtype=string, numpy=b'Barack Obama is the President.'>}
Tokenleştirme
İlk adımımız, herhangi bir dize ön işlemesini çalıştırmak ve veri kümemizi belirtmektir. Bu kullanılarak yapılabilir text.BertTokenizer
a,, text.Splitter
için alt-kelimelerin veya wordpieces içine bulundu simgeleştirir olabilir Bert modeli oluşturulmuş bir kelime verilir Wordpiece algoritması . Sen den TF.Text mevcut diğer alt-kelime tokenizers hakkında daha fazla bilgi edinebilirsiniz burada .
Sözcük bilgisi önceden oluşturulmuş bir BERT kontrol noktasından olabilir veya kendi verileriniz üzerinden kendiniz bir tane oluşturabilirsiniz. Bu örneğin amaçları için bir oyuncak sözlüğü oluşturalım:
_VOCAB = [
# Special tokens
b"[UNK]", b"[MASK]", b"[RANDOM]", b"[CLS]", b"[SEP]",
# Suffixes
b"##ack", b"##ama", b"##ger", b"##gers", b"##onge", b"##pants", b"##uare",
b"##vel", b"##ven", b"an", b"A", b"Bar", b"Hates", b"Mar", b"Ob",
b"Patrick", b"President", b"Sp", b"Sq", b"bob", b"box", b"has", b"highest",
b"is", b"office", b"the",
]
_START_TOKEN = _VOCAB.index(b"[CLS]")
_END_TOKEN = _VOCAB.index(b"[SEP]")
_MASK_TOKEN = _VOCAB.index(b"[MASK]")
_RANDOM_TOKEN = _VOCAB.index(b"[RANDOM]")
_UNK_TOKEN = _VOCAB.index(b"[UNK]")
_MAX_SEQ_LEN = 8
_MAX_PREDICTIONS_PER_BATCH = 5
_VOCAB_SIZE = len(_VOCAB)
lookup_table = tf.lookup.StaticVocabularyTable(
tf.lookup.KeyValueTensorInitializer(
keys=_VOCAB,
key_dtype=tf.string,
values=tf.range(
tf.size(_VOCAB, out_type=tf.int64), dtype=tf.int64),
value_dtype=tf.int64),
num_oov_buckets=1
)
Hadi yapı bir text.BertTokenizer
yukarıdaki kelimeleri kullanarak ve içine metin girişi tokenize RaggedTensor
.`.
bert_tokenizer = text.BertTokenizer(lookup_table, token_out_type=tf.string)
bert_tokenizer.tokenize(examples["text_a"])
<tf.RaggedTensor [[[b'Sp', b'##onge'], [b'bob'], [b'Sq', b'##uare', b'##pants'], [b'is'], [b'an'], [b'A', b'##ven', b'##ger']], [[b'Mar', b'##vel'], [b'A', b'##ven', b'##gers']]]>
bert_tokenizer.tokenize(examples["text_b"])
<tf.RaggedTensor [[[b'Bar', b'##ack'], [b'Ob', b'##ama'], [b'is'], [b'the'], [b'President'], [b'[UNK]']], [[b'President'], [b'is'], [b'the'], [b'highest'], [b'office']]]>
Metin çıkışı text.BertTokenizer
bize metin simgeleþtirilmiþ ediliyor nasıl izin verir, fakat modeli tamsayı kimlikleri gerektirir. Biz ayarlayabilir token_out_type
için param tf.int64
(kelime içine bir indeksi olan) kimlikleri tamsayıdır elde edildi.
bert_tokenizer = text.BertTokenizer(lookup_table, token_out_type=tf.int64)
segment_a = bert_tokenizer.tokenize(examples["text_a"])
segment_a
<tf.RaggedTensor [[[22, 9], [24], [23, 11, 10], [28], [14], [15, 13, 7]], [[18, 12], [15, 13, 8]]]>
segment_b = bert_tokenizer.tokenize(examples["text_b"])
segment_b
<tf.RaggedTensor [[[16, 5], [19, 6], [28], [30], [21], [0]], [[21], [28], [30], [27], [29]]]>
text.BertTokenizer
bir döner RaggedTensor
şeklinde [batch, num_tokens, num_wordpieces]
. Ekstra gerekmez Çünkü num_tokens
mevcut kullanım durumu için boyutları, bir elde etmek son iki boyutu birleştirebilirsiniz RaggedTensor
şekli ile [batch, num_wordpieces]
:
segment_a = segment_a.merge_dims(-2, -1)
segment_a
<tf.RaggedTensor [[22, 9, 24, 23, 11, 10, 28, 14, 15, 13, 7], [18, 12, 15, 13, 8]]>
segment_b = segment_b.merge_dims(-2, -1)
segment_b
<tf.RaggedTensor [[16, 5, 19, 6, 28, 30, 21, 0], [21, 28, 30, 27, 29]]>
İçerik Kırpma
BERT'nin ana girdisi iki cümlenin birleştirilmesidir. Ancak BERT, girdilerin sabit boyutta ve şekilde olmasını gerektirir ve bütçemizi aşan içeriklere sahip olabiliriz.
Biz kullanarak bu üstesinden gelebilirsiniz text.Trimmer
(son eksen boyunca birleştirilmiş bir kez), önceden belirlenmiş bir boyuta içerik aşağı kırpmaya. Farklı vardır text.Trimmer
farklı algoritmalar kullanılarak korumak için içerik türlerini seçin. text.RoundRobinTrimmer
, örneğin her bir segment için eşit kota tahsis edecek, ancak cümleler uçlarını tıraşlayabilir. text.WaterfallTrimmer
son cümlenin sonuna başlayarak Döşeme olacaktır.
Bizim Örneğin, biz kullanacağız RoundRobinTrimmer
seçer öğeler soldan sağa bir şekilde her kesimden.
trimmer = text.RoundRobinTrimmer(max_seq_length=[_MAX_SEQ_LEN])
trimmed = trimmer.trim([segment_a, segment_b])
trimmed
[<tf.RaggedTensor [[22, 9, 24, 23], [18, 12, 15, 13]]>, <tf.RaggedTensor [[16, 5, 19, 6], [21, 28, 30, 27]]>]
trimmed
bir yığın boyunca eleman sayısı 8 eleman (eksen = -1 boyunca birleştirilmiş) olduğu şu anda segmentleri içerir.
Segmentleri birleştirme
Şimdi segmentleri kesilmiş olması, bir tek olsun bir araya getirebilirsiniz RaggedTensor
. Bert başlangıcı (belirtmek için özel belirteçleri kullanan [CLS]
bir segmentin (arasında) ve son [SEP]
). Biz de bir ihtiyaç RaggedTensor
kombine hangi öğeleri gösteren Tensor
hangi segmentin aittir. Biz kullanabilirsiniz text.combine_segments()
Bunlardan ikisi almak için Tensor
sokulan özel fişlerle.
segments_combined, segments_ids = text.combine_segments(
[segment_a, segment_b],
start_of_sequence_id=_START_TOKEN, end_of_segment_id=_END_TOKEN)
segments_combined, segments_ids
(<tf.RaggedTensor [[3, 22, 9, 24, 23, 11, 10, 28, 14, 15, 13, 7, 4, 16, 5, 19, 6, 28, 30, 21, 0, 4], [3, 18, 12, 15, 13, 8, 4, 21, 28, 30, 27, 29, 4]]>, <tf.RaggedTensor [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1]]>)
Maskeli Dil Modeli Görevi
Şimdi bizim temel girdileri olduğuna göre "Maskeli LM ve Maskeleme Prosedürü" için gerekli girdileri ayıklamak için başlayabilir görev açıklanan bert: Dil Anlayış Derin Çift yönlü Transformers Öncesi eğitim
Maskeli dil modeli görevinin düşünmemiz için iki alt sorunu vardır: (1) maskeleme için hangi öğelerin seçileceği ve (2) bunlara hangi değerler atandığı?
Ürün Seçimi
Rastgele maskeleme için öğeleri seçmek için seçecektir çünkü biz kullanacağız text.RandomItemSelector
. RandomItemSelector
rastgele verilen kısıtlamaları (bir parti denekte ürün seçer max_selections_per_batch
, selection_rate
ve unselectable_ids
) ve döner öğeler seçilen hangi belirten bir Boole maskesi.
random_selector = text.RandomItemSelector(
max_selections_per_batch=_MAX_PREDICTIONS_PER_BATCH,
selection_rate=0.2,
unselectable_ids=[_START_TOKEN, _END_TOKEN, _UNK_TOKEN]
)
selected = random_selector.get_selection_mask(
segments_combined, axis=1)
selected
<tf.RaggedTensor [[False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, True, True, True, False, False], [False, False, False, False, False, True, False, False, False, False, False, True, False]]>
Maskelenmiş Değeri Seçme
Maskeleme değerini seçmek için orijinal BERT belgesini tanımlayan metodoloji aşağıdaki gibidir:
İçin mask_token_rate
zaman, öğeyi değiştirmek [MASK]
jetonu:
"my dog is hairy" -> "my dog is [MASK]"
İçin random_token_rate
zaman, rastgele bir kelime ile öğeyi değiştirin:
"my dog is hairy" -> "my dog is apple"
İçin 1 - mask_token_rate - random_token_rate
zaman, değişmeden öğeyi tutmak:
"my dog is hairy" -> "my dog is hairy."
text.MaskedValuesChooser
bu mantığını kapsüller ve bizim ön işleme fonksiyonu için kullanılabilir. İşte ne bir örnek MaskValuesChooser
döner belirli bir mask_token_rate
% 80 ve varsayılan random_token_rate
:
input_ids = tf.ragged.constant([[19, 7, 21, 20, 9, 8], [13, 4, 16, 5], [15, 10, 12, 11, 6]])
mask_values_chooser = text.MaskValuesChooser(_VOCAB_SIZE, _MASK_TOKEN, 0.8)
mask_values_chooser.get_mask_values(input_ids)
<tf.RaggedTensor [[1, 1, 1, 1, 1, 1], [1, 1, 1, 1], [1, 10, 1, 1, 6]]>
Bir sağlandığında RaggedTensor
girişi text.MaskValuesChooser
bir döner RaggedTensor
ya ile aynı şekle sahip _MASK_VALUE
(0), bir rastgele numarası ya da aynı değişmeden id.
Maskeli Dil Modeli Görevi için Girdiler Oluşturma
Şimdi bir olduğunu RandomItemSelector
bize maskeleme ve öğeleri seçmek yardımına text.MaskValuesChooser
değerleri atamak için, kullanabileceğimiz text.mask_language_model()
bizim Bert modeli için bu görevin tüm girdileri bir araya getirmek.
masked_token_ids, masked_pos, masked_lm_ids = text.mask_language_model(
segments_combined,
item_selector=random_selector, mask_values_chooser=mask_values_chooser)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/util/dispatch.py:206: batch_gather (from tensorflow.python.ops.array_ops) is deprecated and will be removed after 2017-10-25. Instructions for updating: `tf.batch_gather` is deprecated, please use `tf.gather` with `batch_dims=-1` instead.
Hadi dalış derin ve çıktılarını incelemek mask_language_model()
. Çıkış masked_token_ids
olduğu:
masked_token_ids
<tf.RaggedTensor [[3, 22, 1, 24, 23, 1, 10, 28, 1, 15, 1, 7, 4, 16, 5, 19, 6, 28, 30, 21, 0, 4], [3, 18, 12, 15, 13, 1, 4, 21, 28, 30, 27, 1, 4]]>
Girişimizin bir sözlük kullanılarak kodlandığını unutmayın. Biz deşifre olursa masked_token_ids
bizim kelime kullanarak elde ederiz:
tf.gather(_VOCAB, masked_token_ids)
<tf.RaggedTensor [[b'[CLS]', b'Sp', b'[MASK]', b'bob', b'Sq', b'[MASK]', b'##pants', b'is', b'[MASK]', b'A', b'[MASK]', b'##ger', b'[SEP]', b'Bar', b'##ack', b'Ob', b'##ama', b'is', b'the', b'President', b'[UNK]', b'[SEP]'], [b'[CLS]', b'Mar', b'##vel', b'A', b'##ven', b'[MASK]', b'[SEP]', b'President', b'is', b'the', b'highest', b'[MASK]', b'[SEP]']]>
Bazı wordpiece belirteçleri ile ya ikame edilmiş olduğuna dikkat edin [MASK]
, [RANDOM]
ya da farklı bir kimlik değeri. masked_pos
çıkış bize değiştirildiği jeton (ilgili toplu) endeksleri verir.
masked_pos
<tf.RaggedTensor [[2, 5, 8, 10], [5, 11]]>
masked_lm_ids
bize belirteci özgün değerini verir.
masked_lm_ids
<tf.RaggedTensor [[9, 11, 14, 13], [8, 29]]>
İnsan tarafından okunabilir değerler elde etmek için burada kimliklerin kodunu tekrar çözebiliriz.
tf.gather(_VOCAB, masked_lm_ids)
<tf.RaggedTensor [[b'##onge', b'##uare', b'an', b'##ven'], [b'##gers', b'office']]>
Dolgu Modeli Girişleri
Şimdi bizim model için tüm girdileri sahip olduğunu, bizim ön işleme son adımı sabit 2 boyutlu içine paketlemek için Tensor
ler dolgu ile ve ayrıca bir maske oluşturmak Tensor
ped değerlerdir değerlerini gösteren. Biz kullanabilirsiniz text.pad_model_inputs()
bu görev bize yardımcı olmak için.
# Prepare and pad combined segment inputs
input_word_ids, input_mask = text.pad_model_inputs(
masked_token_ids, max_seq_length=_MAX_SEQ_LEN)
input_type_ids, _ = text.pad_model_inputs(
masked_token_ids, max_seq_length=_MAX_SEQ_LEN)
# Prepare and pad masking task inputs
masked_lm_positions, masked_lm_weights = text.pad_model_inputs(
masked_token_ids, max_seq_length=_MAX_PREDICTIONS_PER_BATCH)
masked_lm_ids, _ = text.pad_model_inputs(
masked_lm_ids, max_seq_length=_MAX_PREDICTIONS_PER_BATCH)
model_inputs = {
"input_word_ids": input_word_ids,
"input_mask": input_mask,
"input_type_ids": input_type_ids,
"masked_lm_ids": masked_lm_ids,
"masked_lm_positions": masked_lm_positions,
"masked_lm_weights": masked_lm_weights,
}
model_inputs
{'input_word_ids': <tf.Tensor: shape=(2, 8), dtype=int64, numpy= array([[ 3, 22, 1, 24, 23, 1, 10, 28], [ 3, 18, 12, 15, 13, 1, 4, 21]])>, 'input_mask': <tf.Tensor: shape=(2, 8), dtype=int64, numpy= array([[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]])>, 'input_type_ids': <tf.Tensor: shape=(2, 8), dtype=int64, numpy= array([[ 3, 22, 1, 24, 23, 1, 10, 28], [ 3, 18, 12, 15, 13, 1, 4, 21]])>, 'masked_lm_ids': <tf.Tensor: shape=(2, 5), dtype=int64, numpy= array([[ 9, 11, 14, 13, 0], [ 8, 29, 0, 0, 0]])>, 'masked_lm_positions': <tf.Tensor: shape=(2, 5), dtype=int64, numpy= array([[ 3, 22, 1, 24, 23], [ 3, 18, 12, 15, 13]])>, 'masked_lm_weights': <tf.Tensor: shape=(2, 5), dtype=int64, numpy= array([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1]])>}
Gözden geçirmek
Şimdiye kadar sahip olduklarımızı gözden geçirelim ve ön işleme fonksiyonumuzu bir araya getirelim. İşte sahip olduklarımız:
def bert_pretrain_preprocess(vocab_table, features):
# Input is a string Tensor of documents, shape [batch, 1].
text_a = features["text_a"]
text_b = features["text_b"]
# Tokenize segments to shape [num_sentences, (num_words)] each.
tokenizer = text.BertTokenizer(
vocab_table,
token_out_type=tf.int64)
segments = [tokenizer.tokenize(text).merge_dims(
1, -1) for text in (text_a, text_b)]
# Truncate inputs to a maximum length.
trimmer = text.RoundRobinTrimmer(max_seq_length=6)
trimmed_segments = trimmer.trim(segments)
# Combine segments, get segment ids and add special tokens.
segments_combined, segment_ids = text.combine_segments(
trimmed_segments,
start_of_sequence_id=_START_TOKEN,
end_of_segment_id=_END_TOKEN)
# Apply dynamic masking task.
masked_input_ids, masked_lm_positions, masked_lm_ids = (
text.mask_language_model(
segments_combined,
random_selector,
mask_values_chooser,
)
)
# Prepare and pad combined segment inputs
input_word_ids, input_mask = text.pad_model_inputs(
masked_input_ids, max_seq_length=_MAX_SEQ_LEN)
input_type_ids, _ = text.pad_model_inputs(
masked_input_ids, max_seq_length=_MAX_SEQ_LEN)
# Prepare and pad masking task inputs
masked_lm_positions, masked_lm_weights = text.pad_model_inputs(
masked_input_ids, max_seq_length=_MAX_PREDICTIONS_PER_BATCH)
masked_lm_ids, _ = text.pad_model_inputs(
masked_lm_ids, max_seq_length=_MAX_PREDICTIONS_PER_BATCH)
model_inputs = {
"input_word_ids": input_word_ids,
"input_mask": input_mask,
"input_type_ids": input_type_ids,
"masked_lm_ids": masked_lm_ids,
"masked_lm_positions": masked_lm_positions,
"masked_lm_weights": masked_lm_weights,
}
return model_inputs
Biz daha önce bir inşa tf.data.Dataset
ve şimdi bizim monte ön işleme işlevini kullanabilirsiniz bert_pretrain_preprocess()
içinde Dataset.map()
. Bu, ham dizi verilerimizi tamsayı girdilerine dönüştürmek ve doğrudan modelimize beslemek için bir girdi ardışık düzeni oluşturmamıza olanak tanır.
dataset = tf.data.Dataset.from_tensors(examples)
dataset = dataset.map(functools.partial(
bert_pretrain_preprocess, lookup_table))
next(iter(dataset))
{'input_word_ids': <tf.Tensor: shape=(2, 8), dtype=int64, numpy= array([[ 3, 22, 9, 1, 4, 16, 5, 19], [ 3, 18, 1, 15, 4, 1, 28, 30]])>, 'input_mask': <tf.Tensor: shape=(2, 8), dtype=int64, numpy= array([[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]])>, 'input_type_ids': <tf.Tensor: shape=(2, 8), dtype=int64, numpy= array([[ 3, 22, 9, 1, 4, 16, 5, 19], [ 3, 18, 1, 15, 4, 1, 28, 30]])>, 'masked_lm_ids': <tf.Tensor: shape=(2, 5), dtype=int64, numpy= array([[24, 19, 0, 0, 0], [12, 21, 0, 0, 0]])>, 'masked_lm_positions': <tf.Tensor: shape=(2, 5), dtype=int64, numpy= array([[ 3, 22, 9, 1, 4], [ 3, 18, 1, 15, 4]])>, 'masked_lm_weights': <tf.Tensor: shape=(2, 5), dtype=int64, numpy= array([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1]])>}
İlgili Öğreticiler
Bert ile sınıflandırır metin - sınıflandırmak metne pretrained Bert modelini nasıl kullanılacağına dair bir dokuman. BERT modeli tarafından kullanılan girdilerin nasıl önişlemden geçirileceğini bildiğinize göre, bu güzel bir takip.
TF Metin ile tokenizing - Öğretici TF.Text var tokenizers farklı detaylandırma.
İle Metin İşleme
RaggedTensor
-, oluşturmak, kullanmak ve işlemek için nasıl Detaylı rehberRaggedTensor
s.