הצג באתר TensorFlow.org | הפעל בגוגל קולאב | הצג ב-GitHub | הורד מחברת | ראה דגמי TF Hub |
סקירה כללית
טוקניזציה היא תהליך של פירוק מחרוזת לאסימונים. בדרך כלל, אסימונים אלו הם מילים, מספרים ו/או סימני פיסוק. tensorflow_text
החבילה מספקת מספר tokenizers הזמין עבור עיבוד מקדים טקסט נדרש על ידי המודלים מבוססי הטקסט שלך. על ידי ביצוע הטוקניזציה בגרף 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)
}
אסימונים
להלן חבילת האסימונים המסופקת על ידי TensorFlow Text. ההנחה היא שכניסות המחרוזות הן UTF-8. עיין מדריך Unicode להמרת מחרוזות UTF-8.
סימני מילה שלמים
אסימונים אלו מנסים לפצל מחרוזת לפי מילים, וזו הדרך האינטואיטיבית ביותר לפצל טקסט.
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.']]
ייתכן שתבחין שחסרון של האסימון הזה הוא שסימני פיסוק כלולים במילה המרכיבה אסימון. כדי לפצל את המילים וסימני פיסוק לתוך אסימונים נפרדים, UnicodeScriptTokenizer
צריך לשמש.
UnicodeScriptTokenizer
UnicodeScriptTokenizer
מפצלת מחרוזות מבוססות על גבולות תסריט Unicode. קודי הסקריפט שבהם נעשה שימוש תואמים לערכי UScriptCode International Components for 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'.']]
אסימוני מילות משנה
ניתן להשתמש באסימוני מילות משנה עם אוצר מילים קטן יותר, ולאפשר למודל לקבל קצת מידע על מילים חדשות מתוך מילות המשנה שיוצרות אותו.
אנו דנים באפשרויות tokenization Subword בקצרה להלן, אך הדרכת Subword Tokenization הולכת יותר לעומק וגם מסבירה איך ליצור את קבצי vocab.
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, אך גם מבצע משימות נוספות כגון נורמליזציה ו-Tokenizing למילים תחילה.
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
ה-SenencepieceTokenizer הוא אסימון משנה שניתן להגדרה. זה מגובה על ידי ספריית Sentencepiece. כמו 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. זה יכול להיות שימושי גם ליצירת ngrams של תווים, כגון 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]]
ביטול טוקן
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!']]