ดูบน TensorFlow.org | ทำงานใน Google Colab | ดูบน GitHub | ดาวน์โหลดโน๊ตบุ๊ค | ดูรุ่น TF Hub |
ภาพรวม
Tokenization เป็นกระบวนการแบ่งสตริงออกเป็นโทเค็น โดยทั่วไป โทเค็นเหล่านี้เป็นคำ ตัวเลข และ/หรือเครื่องหมายวรรคตอน tensorflow_text
แพคเกจให้จำนวนของ tokenizers ใช้ได้สำหรับ preprocessing ข้อความต้องตามรูปแบบขึ้นอยู่กับข้อความของคุณ เมื่อดำเนินการแปลงเป็นโทเค็นในกราฟ TensorFlow คุณจะไม่ต้องกังวลเกี่ยวกับความแตกต่างระหว่างเวิร์กโฟลว์การฝึกอบรมและการอนุมาน และการจัดการสคริปต์ก่อนการประมวลผล
คู่มือนี้จะกล่าวถึงตัวเลือกการสร้างโทเค็นจำนวนมากที่มีให้โดย TensorFlow Text เมื่อคุณอาจต้องการใช้ตัวเลือกหนึ่งแทนอีกตัวเลือกหนึ่ง และการเรียกใช้โทเค็นเหล่านี้จากภายในโมเดลของคุณอย่างไร
ติดตั้ง
pip install -q tensorflow-text
import requests
import tensorflow as tf
import tensorflow_text as tf_text
ตัวแยก API
อินเตอร์เฟซหลักคือ Splitter
และ SplitterWithOffsets
ซึ่งมีวิธีการเดียว split
และ split_with_offsets
SplitterWithOffsets
ตัวแปร (ซึ่งทอดตัว Splitter
) มีตัวเลือกสำหรับการชดเชยไบต์ ซึ่งช่วยให้ผู้เรียกทราบว่าไบต์ใดในสตริงเดิมที่สร้างโทเค็นที่สร้างขึ้น
Tokenizer
และ TokenizerWithOffsets
เป็นรุ่นพิเศษของ Splitter
ที่ให้ความสะดวกสบายวิธี tokenize
และ tokenize_with_offsets
ตามลำดับ
โดยทั่วไปสำหรับการป้อนข้อมูล N มิติใด ๆ ราชสกุลกลับมาอยู่ใน N + 1 มิติ RaggedTensor กับชั้นมากที่สุดมิติของการทำแผนที่เพื่อราชสกุลสายบุคคลเดิม
class Splitter {
@abstractmethod
def split(self, input)
}
class SplitterWithOffsets(Splitter) {
@abstractmethod
def split_with_offsets(self, input)
}
นอกจากนี้ยังมี Detokenizer
อินเตอร์เฟซ ตัวสร้างโทเค็นใดๆ ที่ใช้อินเทอร์เฟซนี้สามารถยอมรับเทนเซอร์ที่มีมิติ N ของโทเค็น และโดยปกติแล้วจะส่งคืนเทนเซอร์แบบมิติ N-1 หรือเทนเซอร์มอมแมมที่มีโทเค็นที่กำหนดที่ประกอบเข้าด้วยกัน
class Detokenizer {
@abstractmethod
def detokenize(self, input)
}
Tokenizers
ด้านล่างนี้คือชุดของ tokenizers ที่จัดเตรียมโดย TensorFlow Text อินพุตสตริงจะถือว่าเป็น UTF-8 โปรดอ่าน คู่มือ Unicode สำหรับการแปลงสตริงให้เป็น UTF-8
tokenizers ทั้งคำ
tokenizers เหล่านี้พยายามแยกสตริงด้วยคำ และเป็นวิธีที่ใช้งานง่ายที่สุดในการแยกข้อความ
WhitespaceTokenizer
text.WhitespaceTokenizer
เป็น tokenizer พื้นฐานที่สุดซึ่งแยกสายในห้องไอซียูที่กำหนดตัวอักษรช่องว่าง (เช่น. พื้นที่แท็บบรรทัดใหม่) ซึ่งมักจะดีสำหรับการสร้างแบบจำลองต้นแบบอย่างรวดเร็ว
tokenizer = tf_text.WhitespaceTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
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. [[b'What', b'you', b'know', b'you', b"can't", b'explain,', b'but', b'you', b'feel', b'it.']]
คุณอาจสังเกตเห็นข้อบกพร่องของ tokenizer นี้คือ เครื่องหมายวรรคตอนจะรวมอยู่ในคำเพื่อประกอบเป็นโทเค็น ที่จะแยกคำและเครื่องหมายวรรคตอนลงในราชสกุลแยก UnicodeScriptTokenizer
ควรจะใช้
UnicodeScriptTokenizer
UnicodeScriptTokenizer
แยกสตริงขึ้นอยู่กับขอบเขต Unicode สคริปต์ รหัสสคริปต์ที่ใช้สอดคล้องกับค่า UScriptCode ของส่วนประกอบสากลสำหรับ Unicode (ICU) ดู: http://icu-project.org/apiref/icu4c/uscript_8h.html
ในทางปฏิบัตินี้มีความคล้ายคลึงกับ WhitespaceTokenizer
มีความแตกต่างที่เห็นได้ชัดที่สุดว่ามันจะแบ่งวรรคตอน (USCRIPT_COMMON) จากภาษาตำรา (เช่น. USCRIPT_LATIN, USCRIPT_CYRILLIC ฯลฯ ) ในขณะที่ยังแยกตำราภาษาจากแต่ละอื่น ๆ โปรดทราบว่าการดำเนินการนี้จะแบ่งคำที่ย่อเป็นโทเค็นแยกกัน
tokenizer = tf_text.UnicodeScriptTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
[[b'What', b'you', b'know', b'you', b'can', b"'", b't', b'explain', b',', b'but', b'you', b'feel', b'it', b'.']]
tokenizers คำย่อย
โทเค็นไนเซอร์คำย่อยสามารถใช้กับคำศัพท์ที่มีขนาดเล็กลง และอนุญาตให้โมเดลมีข้อมูลบางอย่างเกี่ยวกับคำใหม่จากคำย่อยที่สร้างมันขึ้นมา
เราสั้นหารือเกี่ยวกับตัวเลือก tokenization Subword ด้านล่าง แต่ Subword Tokenization กวดวิชา ไปเพิ่มเติมในเชิงลึกและยังได้อธิบายถึงวิธีการสร้างไฟล์คำศัพท์
WordpieceTokenizer
การแปลงโทเค็น WordPiece เป็นรูปแบบการใช้โทเค็นที่ขับเคลื่อนด้วยข้อมูล ซึ่งสร้างชุดของโทเค็นย่อย โทเค็นย่อยเหล่านี้อาจสอดคล้องกับหน่วยคำทางภาษา แต่มักไม่เป็นเช่นนั้น
WordpieceTokenizer คาดว่าอินพุตจะถูกแบ่งออกเป็นโทเค็น เพราะความจำเป็นนี้คุณมักจะต้องการที่จะแยกใช้ WhitespaceTokenizer
หรือ UnicodeScriptTokenizer
ก่อน
tokenizer = tf_text.WhitespaceTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
[[b'What', b'you', b'know', b'you', b"can't", b'explain,', b'but', b'you', b'feel', b'it.']]
หลังจากสตริงถูกแบ่งออกเป็นราชสกุลที่ WordpieceTokenizer
สามารถใช้ในการแยกออกเป็น subtokens
url = "https://github.com/tensorflow/text/blob/master/tensorflow_text/python/ops/test_data/test_wp_en_vocab.txt?raw=true"
r = requests.get(url)
filepath = "vocab.txt"
open(filepath, 'wb').write(r.content)
52382
subtokenizer = tf_text.UnicodeScriptTokenizer(filepath)
subtokens = tokenizer.tokenize(tokens)
print(subtokens.to_list())
[[[b'What'], [b'you'], [b'know'], [b'you'], [b"can't"], [b'explain,'], [b'but'], [b'you'], [b'feel'], [b'it.']]]
BertTokenizer
BertTokenizer จำลองการนำโทเค็นไปใช้ดั้งเดิมจากกระดาษ BERT สิ่งนี้ได้รับการสนับสนุนโดย WordpieceTokenizer แต่ยังทำงานเพิ่มเติมเช่นการทำให้เป็นมาตรฐานและโทเค็นเป็นคำก่อน
tokenizer = tf_text.BertTokenizer(filepath, token_out_type=tf.string, lower_case=True)
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
[[[b'what'], [b'you'], [b'know'], [b'you'], [b'can'], [b"'"], [b't'], [b'explain'], [b','], [b'but'], [b'you'], [b'feel'], [b'it'], [b'.']]]
SentencepieceTokenizer
SentencepieceTokenizer เป็นโทเคนย่อยโทเค็นที่สามารถกำหนดค่าได้สูง นี้ได้รับการสนับสนุนโดยห้องสมุดประโยค เช่นเดียวกับ BertTokenizer มันสามารถรวมการทำให้เป็นมาตรฐานและการแยกโทเค็นก่อนที่จะแยกออกเป็นโทเค็นย่อย
url = "https://github.com/tensorflow/text/blob/master/tensorflow_text/python/ops/test_data/test_oss_model.model?raw=true"
sp_model = requests.get(url).content
tokenizer = tf_text.SentencepieceTokenizer(sp_model, out_type=tf.string)
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
[[b'\xe2\x96\x81What', b'\xe2\x96\x81you', b'\xe2\x96\x81know', b'\xe2\x96\x81you', b'\xe2\x96\x81can', b"'", b't', b'\xe2\x96\x81explain', b',', b'\xe2\x96\x81but', b'\xe2\x96\x81you', b'\xe2\x96\x81feel', b'\xe2\x96\x81it', b'.']]
ตัวแยกสัญญาณอื่นๆ
UnicodeCharTokenizer
ซึ่งจะแยกสตริงออกเป็นอักขระ UTF-8 มีประโยชน์สำหรับภาษา CJK ที่ไม่มีช่องว่างระหว่างคำ
tokenizer = tf_text.UnicodeCharTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
[[87, 104, 97, 116, 32, 121, 111, 117, 32, 107, 110, 111, 119, 32, 121, 111, 117, 32, 99, 97, 110, 39, 116, 32, 101, 120, 112, 108, 97, 105, 110, 44, 32, 98, 117, 116, 32, 121, 111, 117, 32, 102, 101, 101, 108, 32, 105, 116, 46]]
ผลลัพธ์คือจุดโค้ด Unicode สิ่งนี้ยังมีประโยชน์สำหรับการสร้าง ngram ของอักขระ เช่น bigrams ในการแปลงกลับเป็นอักขระ UTF-8
characters = tf.strings.unicode_encode(tf.expand_dims(tokens, -1), "UTF-8")
bigrams = tf_text.ngrams(characters, 2, reduction_type=tf_text.Reduction.STRING_JOIN, string_separator='')
print(bigrams.to_list())
[[b'Wh', b'ha', b'at', b't ', b' y', b'yo', b'ou', b'u ', b' k', b'kn', b'no', b'ow', b'w ', b' y', b'yo', b'ou', b'u ', b' c', b'ca', b'an', b"n'", b"'t", b't ', b' e', b'ex', b'xp', b'pl', b'la', b'ai', b'in', b'n,', b', ', b' b', b'bu', b'ut', b't ', b' y', b'yo', b'ou', b'u ', b' f', b'fe', b'ee', b'el', b'l ', b' i', b'it', b't.']]
HubModuleTokenizer
นี่คือตัวห่อหุ้มรอบโมเดลที่ปรับใช้กับ TF Hub เพื่อให้การโทรง่ายขึ้นเนื่องจากปัจจุบัน TF Hub ไม่รองรับเทนเซอร์ที่ขาดความต่อเนื่อง การมีโมเดลดำเนินการโทเค็นจะมีประโยชน์อย่างยิ่งสำหรับภาษา CJK เมื่อคุณต้องการแยกคำออกเป็นคำ แต่ไม่มีที่ว่างสำหรับจัดทำคู่มือฮิวริสติก ในขณะนี้ เรามีแบบจำลองการแบ่งส่วนกลุ่มเดียวสำหรับภาษาจีน
MODEL_HANDLE = "https://tfhub.dev/google/zh_segmentation/1"
segmenter = tf_text.HubModuleTokenizer(MODEL_HANDLE)
tokens = segmenter.tokenize(["新华社北京"])
print(tokens.to_list())
[[b'\xe6\x96\xb0\xe5\x8d\x8e\xe7\xa4\xbe', b'\xe5\x8c\x97\xe4\xba\xac']]
อาจเป็นเรื่องยากที่จะดูผลลัพธ์ของสตริงไบต์ที่เข้ารหัส UTF-8 ถอดรหัสค่ารายการเพื่อให้ดูง่ายขึ้น
def decode_list(x):
if type(x) is list:
return list(map(decode_list, x))
return x.decode("UTF-8")
def decode_utf8_tensor(x):
return list(map(decode_list, x.to_list()))
print(decode_utf8_tensor(tokens))
[['新华社', '北京']]
SplitMergeTokenizer
SplitMergeTokenizer
& SplitMergeFromLogitsTokenizer
มีจุดประสงค์ที่กำหนดเป้าหมายของการแยกสตริงขึ้นอยู่กับค่าให้ระบุตำแหน่งที่สตริงควรจะแยก สิ่งนี้มีประโยชน์ในการสร้างแบบจำลองการแบ่งส่วนของคุณเอง เช่น ตัวอย่างการแบ่งกลุ่มก่อนหน้านี้
สำหรับ SplitMergeTokenizer
, ค่าเป็น 0 จะใช้ในการบ่งบอกถึงการเริ่มต้นของสตริงใหม่และค่า 1 แสดงให้เห็นตัวอักษรที่เป็นส่วนหนึ่งของสตริงปัจจุบัน
strings = ["新华社北京"]
labels = [[0, 1, 1, 0, 1]]
tokenizer = tf_text.SplitMergeTokenizer()
tokens = tokenizer.tokenize(strings, labels)
print(decode_utf8_tensor(tokens))
[['新华社', '北京']]
SplitMergeFromLogitsTokenizer
จะคล้ายกัน แต่มันแทนยอมรับคู่ค่า logit จากเครือข่ายประสาทที่คาดการณ์ถ้าตัวละครแต่ละตัวควรจะแยกออกเป็นสตริงใหม่หรือรวมเข้าเป็นหนึ่งในปัจจุบัน
strings = [["新华社北京"]]
labels = [[[5.0, -3.2], [0.2, 12.0], [0.0, 11.0], [2.2, -1.0], [-3.0, 3.0]]]
tokenizer = tf_text.SplitMergeFromLogitsTokenizer()
tokenizer.tokenize(strings, labels)
print(decode_utf8_tensor(tokens))
[['新华社', '北京']]
RegexSplitter
RegexSplitter
สามารถสตริงส่วนที่จุดพักโดยพลการกำหนดโดยการแสดงออกปกติที่จัดไว้ให้
splitter = tf_text.RegexSplitter("\s")
tokens = splitter.split(["What you know you can't explain, but you feel it."], )
print(tokens.to_list())
[[b'What', b'you', b'know', b'you', b"can't", b'explain,', b'but', b'you', b'feel', b'it.']]
ออฟเซ็ต
เมื่อสร้างโทเค็นให้กับสตริง มักจะต้องการทราบว่าโทเค็นนั้นมาจากไหนในสตริงดั้งเดิม ด้วยเหตุนี้แต่ละ tokenizer ซึ่งดำเนิน TokenizerWithOffsets
มีวิธี tokenize_with_offsets ว่าจะกลับมาชดเชยไบต์พร้อมกับสัญญาณ start_offsets แสดงรายการไบต์ในสตริงดั้งเดิมที่แต่ละโทเค็นเริ่มต้น และ end_offsets แสดงรายการไบต์ทันทีหลังจากจุดที่แต่ละโทเค็นสิ้นสุด ในการหักเห ค่าออฟเซ็ตเริ่มต้นจะรวมอยู่ด้วยและค่าออฟเซ็ตสิ้นสุดจะไม่รวมอยู่ด้วย
tokenizer = tf_text.UnicodeScriptTokenizer()
(tokens, start_offsets, end_offsets) = tokenizer.tokenize_with_offsets(['Everything not saved will be lost.'])
print(tokens.to_list())
print(start_offsets.to_list())
print(end_offsets.to_list())
[[b'Everything', b'not', b'saved', b'will', b'be', b'lost', b'.']] [[0, 11, 15, 21, 26, 29, 33]] [[10, 14, 20, 25, 28, 33, 34]]
Detokenization
Tokenizers ซึ่งใช้ Detokenizer
ให้ detokenize
วิธีการที่ความพยายามในการที่จะรวมสตริง ซึ่งมีโอกาสที่จะสูญเสีย ดังนั้นสตริงที่แยกโทเค็นออกอาจไม่ตรงกับสตริงเดิมที่เข้ารหัสไว้ล่วงหน้าทุกประการ
tokenizer = tf_text.UnicodeCharTokenizer()
tokens = tokenizer.tokenize(["What you know you can't explain, but you feel it."])
print(tokens.to_list())
strings = tokenizer.detokenize(tokens)
print(strings.numpy())
[[87, 104, 97, 116, 32, 121, 111, 117, 32, 107, 110, 111, 119, 32, 121, 111, 117, 32, 99, 97, 110, 39, 116, 32, 101, 120, 112, 108, 97, 105, 110, 44, 32, 98, 117, 116, 32, 121, 111, 117, 32, 102, 101, 101, 108, 32, 105, 116, 46]] [b"What you know you can't explain, but you feel it."]
TF Data
TF Data เป็น API ที่ทรงพลังสำหรับการสร้างไปป์ไลน์อินพุตสำหรับโมเดลการฝึกอบรม Tokenizers ทำงานตามที่คาดไว้กับ API
docs = tf.data.Dataset.from_tensor_slices([['Never tell me the odds.'], ["It's a trap!"]])
tokenizer = tf_text.WhitespaceTokenizer()
tokenized_docs = docs.map(lambda x: tokenizer.tokenize(x))
iterator = iter(tokenized_docs)
print(next(iterator).to_list())
print(next(iterator).to_list())
[[b'Never', b'tell', b'me', b'the', b'odds.']] [[b"It's", b'a', b'trap!']]