مشاهده در TensorFlow.org | در Google Colab اجرا شود | مشاهده منبع در GitHub | دانلود دفترچه یادداشت |
معرفی
مدل های NLP اغلب زبان های مختلف را با مجموعه کاراکترهای مختلف مدیریت می کنند. یونیکد را پشتیبانی می کند یک سیستم استاندارد است که برای نشان دادن شخصیتهای تقریبا از همه زبان ها است. شخصیت هر یونیکد با استفاده از یک عدد صحیح منحصر به فرد کد گذاری شده است نقطه کد بین 0
و 0x10FFFF
. رشته یونیکد دنباله ای از صفر یا چند نقطه فعال است.
این آموزش نحوه نمایش رشته های یونیکد در TensorFlow و دستکاری آنها را با استفاده از معادل های یونیکد عملیات رشته استاندارد نشان می دهد. رشته های یونیکد را بر اساس تشخیص اسکریپت به توکن ها جدا می کند.
import tensorflow as tf
import numpy as np
tf.string
نوع داده
پایه TensorFlow tf.string
dtype
اجازه می دهد تا شما را به ساخت تانسورها از رشته بایت است. رشته یونیکد هستند UTF-8 کد گذاری به طور پیش فرض.
tf.constant(u"Thanks 😊")
<tf.Tensor: shape=(), dtype=string, numpy=b'Thanks \xf0\x9f\x98\x8a'>
tf.string
رفتار تانسور بایت رشته را به عنوان واحد اتمی است. این به آن امکان می دهد رشته های بایتی با طول های مختلف را ذخیره کند. طول رشته در ابعاد تانسور گنجانده نشده است.
tf.constant([u"You're", u"welcome!"]).shape
TensorShape([2])
اگر شما استفاده از پایتون به رشته سازه، توجه داشته باشید که رشته هستند یونیکد کد گذاری به طور پیش فرض.
نمایندگی یونیکد
دو روش استاندارد برای نمایش یک رشته یونیکد در TensorFlow وجود دارد:
-
string
اسکالر - که در آن دنباله ای از نقاط با استفاده از یک کد شناخته شده کد گذاری شده است رمزگذاری کاراکتر . -
int32
بردار - که در آن هر یک از موقعیت شامل یک نقطه کد تک.
به عنوان مثال، سه مقدار زیر همه نشان دهنده رشته یونیکد "语言处理"
(که به معنی "پردازش زبان" در زبان چینی):
# Unicode string, represented as a UTF-8 encoded string scalar.
text_utf8 = tf.constant(u"语言处理")
text_utf8
<tf.Tensor: shape=(), dtype=string, numpy=b'\xe8\xaf\xad\xe8\xa8\x80\xe5\xa4\x84\xe7\x90\x86'>
# Unicode string, represented as a UTF-16-BE encoded string scalar.
text_utf16be = tf.constant(u"语言处理".encode("UTF-16-BE"))
text_utf16be
<tf.Tensor: shape=(), dtype=string, numpy=b'\x8b\xed\x8a\x00Y\x04t\x06'>
# Unicode string, represented as a vector of Unicode code points.
text_chars = tf.constant([ord(char) for char in u"语言处理"])
text_chars
<tf.Tensor: shape=(4,), dtype=int32, numpy=array([35821, 35328, 22788, 29702], dtype=int32)>
تبدیل بین نمایش ها
TensorFlow عملیاتی را برای تبدیل بین این نمایش های مختلف ارائه می دهد:
-
tf.strings.unicode_decode
: تبدیل یک اسکالر رشته کد گذاری شده به یک بردار از نقاط کد. -
tf.strings.unicode_encode
: تبدیل یک بردار از نقاط کد به اسکالر رشته رمزنگاری شده. -
tf.strings.unicode_transcode
: تبدیل یک اسکالر رشته کد گذاری شده به رمزگذاری دیگری.
tf.strings.unicode_decode(text_utf8,
input_encoding='UTF-8')
<tf.Tensor: shape=(4,), dtype=int32, numpy=array([35821, 35328, 22788, 29702], dtype=int32)>
tf.strings.unicode_encode(text_chars,
output_encoding='UTF-8')
<tf.Tensor: shape=(), dtype=string, numpy=b'\xe8\xaf\xad\xe8\xa8\x80\xe5\xa4\x84\xe7\x90\x86'>
tf.strings.unicode_transcode(text_utf8,
input_encoding='UTF8',
output_encoding='UTF-16-BE')
<tf.Tensor: shape=(), dtype=string, numpy=b'\x8b\xed\x8a\x00Y\x04t\x06'>
ابعاد دسته ای
هنگام رمزگشایی چند رشته، تعداد کاراکترهای هر رشته ممکن است برابر نباشد. نتیجه بازگشت است tf.RaggedTensor
، جایی که طول ابعاد درونی بسته به تعداد کاراکترهای هر رشته است.
# A batch of Unicode strings, each represented as a UTF8-encoded string.
batch_utf8 = [s.encode('UTF-8') for s in
[u'hÃllo', u'What is the weather tomorrow', u'Göödnight', u'😊']]
batch_chars_ragged = tf.strings.unicode_decode(batch_utf8,
input_encoding='UTF-8')
for sentence_chars in batch_chars_ragged.to_list():
print(sentence_chars)
[104, 195, 108, 108, 111] [87, 104, 97, 116, 32, 105, 115, 32, 116, 104, 101, 32, 119, 101, 97, 116, 104, 101, 114, 32, 116, 111, 109, 111, 114, 114, 111, 119] [71, 246, 246, 100, 110, 105, 103, 104, 116] [128522]
شما می توانید این tf.RaggedTensor
مستقیم، و یا تبدیل آن به یک متراکم tf.Tensor
با لایه یا یک tf.SparseTensor
با استفاده از روش tf.RaggedTensor.to_tensor
و tf.RaggedTensor.to_sparse
.
batch_chars_padded = batch_chars_ragged.to_tensor(default_value=-1)
print(batch_chars_padded.numpy())
[[ 104 195 108 108 111 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1] [ 87 104 97 116 32 105 115 32 116 104 101 32 119 101 97 116 104 101 114 32 116 111 109 111 114 114 111 119] [ 71 246 246 100 110 105 103 104 116 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1] [128522 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1]]
batch_chars_sparse = batch_chars_ragged.to_sparse()
nrows, ncols = batch_chars_sparse.dense_shape.numpy()
elements = [['_' for i in range(ncols)] for j in range(nrows)]
for (row, col), value in zip(batch_chars_sparse.indices.numpy(), batch_chars_sparse.values.numpy()):
elements[row][col] = str(value)
# max_width = max(len(value) for row in elements for value in row)
value_lengths = []
for row in elements:
for value in row:
value_lengths.append(len(value))
max_width = max(value_lengths)
print('[%s]' % '\n '.join(
'[%s]' % ', '.join(value.rjust(max_width) for value in row)
for row in elements))
[[ 104, 195, 108, 108, 111, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] [ 87, 104, 97, 116, 32, 105, 115, 32, 116, 104, 101, 32, 119, 101, 97, 116, 104, 101, 114, 32, 116, 111, 109, 111, 114, 114, 111, 119] [ 71, 246, 246, 100, 110, 105, 103, 104, 116, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _] [128522, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _]]
هنگام رمزگذاری رشته های متعدد با طول همان، استفاده از یک tf.Tensor
به عنوان ورودی می باشد.
tf.strings.unicode_encode([[99, 97, 116], [100, 111, 103], [99, 111, 119]],
output_encoding='UTF-8')
<tf.Tensor: shape=(3,), dtype=string, numpy=array([b'cat', b'dog', b'cow'], dtype=object)>
هنگام رمزگذاری رشته های متعدد با طول متفاوت، استفاده از یک tf.RaggedTensor
به عنوان ورودی می باشد.
tf.strings.unicode_encode(batch_chars_ragged, output_encoding='UTF-8')
<tf.Tensor: shape=(4,), dtype=string, numpy= array([b'h\xc3\x83llo', b'What is the weather tomorrow', b'G\xc3\xb6\xc3\xb6dnight', b'\xf0\x9f\x98\x8a'], dtype=object)>
اگر شما یک تانسور با رشته های متعدد در قالب خالی یا پراکنده، آن را برای اولین بار تبدیل به یک tf.RaggedTensor
قبل از تماس tf.strings.unicode_encode
.
tf.strings.unicode_encode(
tf.RaggedTensor.from_sparse(batch_chars_sparse),
output_encoding='UTF-8')
<tf.Tensor: shape=(4,), dtype=string, numpy= array([b'h\xc3\x83llo', b'What is the weather tomorrow', b'G\xc3\xb6\xc3\xb6dnight', b'\xf0\x9f\x98\x8a'], dtype=object)>
tf.strings.unicode_encode(
tf.RaggedTensor.from_tensor(batch_chars_padded, padding=-1),
output_encoding='UTF-8')
<tf.Tensor: shape=(4,), dtype=string, numpy= array([b'h\xc3\x83llo', b'What is the weather tomorrow', b'G\xc3\xb6\xc3\xb6dnight', b'\xf0\x9f\x98\x8a'], dtype=object)>
عملیات یونیکد
طول کاراکتر
استفاده از unit
پارامتر از tf.strings.length
عملیات برای نشان طول شخصیت باید محاسبه شود. unit
پیش فرض به "BYTE"
، اما می توان آن را به دیگر ارزش ها، مانند مجموعه "UTF8_CHAR"
و یا "UTF16_CHAR"
، برای تعیین تعداد codepoints یونیکد در هر رشته کد گذاری.
# Note that the final character takes up 4 bytes in UTF8.
thanks = u'Thanks 😊'.encode('UTF-8')
num_bytes = tf.strings.length(thanks).numpy()
num_chars = tf.strings.length(thanks, unit='UTF8_CHAR').numpy()
print('{} bytes; {} UTF-8 characters'.format(num_bytes, num_chars))
11 bytes; 8 UTF-8 characters
زیر رشته کاراکترها
tf.strings.substr
عملیات را بپذیرد unit
پارامتر، و استفاده از آن برای تعیین چه نوع از جبران pos
و len
paremeters باشد.
# Here, unit='BYTE' (default). Returns a single byte with len=1
tf.strings.substr(thanks, pos=7, len=1).numpy()
b'\xf0'
# Specifying unit='UTF8_CHAR', returns a single 4 byte character in this case
print(tf.strings.substr(thanks, pos=7, len=1, unit='UTF8_CHAR').numpy())
b'\xf0\x9f\x98\x8a'
رشته های یونیکد را تقسیم کنید
tf.strings.unicode_split
عملیات تجزیه رشته یونیکد به زیر رشته از کاراکتر فردی است.
tf.strings.unicode_split(thanks, 'UTF-8').numpy()
array([b'T', b'h', b'a', b'n', b'k', b's', b' ', b'\xf0\x9f\x98\x8a'], dtype=object)
افست بایت برای کاراکترها
به چین تانسور شخصیت های تولید شده توسط tf.strings.unicode_decode
با رشته اصلی، آن را مفید می دانم که در آن برای هر یک از شخصیت آغاز می شود را جبران کند. روش tf.strings.unicode_decode_with_offsets
شبیه به unicode_decode
، جز این که آن را می گرداند یک تانسور دوم حاوی آغاز جبران هر یک از شخصیت.
codepoints, offsets = tf.strings.unicode_decode_with_offsets(u'🎈🎉🎊', 'UTF-8')
for (codepoint, offset) in zip(codepoints.numpy(), offsets.numpy()):
print('At byte offset {}: codepoint {}'.format(offset, codepoint))
At byte offset 0: codepoint 127880 At byte offset 4: codepoint 127881 At byte offset 8: codepoint 127882
اسکریپت های یونیکد
هر نقطه کد یونیکد متعلق به یک مجموعه واحد از codepoints شناخته شده به عنوان یک اسکریپت . خط یک کاراکتر در تعیین زبانی که ممکن است کاراکتر باشد کمک کننده است. برای مثال، دانستن اینکه "B" به خط سیریلیک است، نشان می دهد که متن مدرن حاوی آن کاراکتر احتمالاً از زبان اسلاوی مانند روسی یا اوکراینی است.
TensorFlow فراهم می کند tf.strings.unicode_script
عملیات که برای تعیین اسکریپت استفاده می کند نقطهکد داده شده است. کدهای اسکریپت int32
ارزش مربوط به قطعات جهانی یونیکد (ICU) UScriptCode
ارزش.
uscript = tf.strings.unicode_script([33464, 1041]) # ['芸', 'Б']
print(uscript.numpy()) # [17, 8] == [USCRIPT_HAN, USCRIPT_CYRILLIC]
[17 8]
tf.strings.unicode_script
عملیات همچنین می توانید به چند بعدی اعمال شود tf.Tensor
بازدید کنندگان و یا tf.RaggedTensor
بازدید کنندگان از codepoints:
print(tf.strings.unicode_script(batch_chars_ragged))
<tf.RaggedTensor [[25, 25, 25, 25, 25], [25, 25, 25, 25, 0, 25, 25, 0, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25], [25, 25, 25, 25, 25, 25, 25, 25, 25], [0]]>
مثال: تقسیم بندی ساده
تقسیم بندی وظیفه تقسیم متن به واحدهای کلمه مانند است. هنگامی که از کاراکترهای فاصله برای جدا کردن کلمات استفاده می شود، این اغلب آسان است، اما برخی از زبان ها (مانند چینی و ژاپنی) از فاصله استفاده نمی کنند، و برخی از زبان ها (مانند آلمانی) حاوی ترکیبات طولانی هستند که باید برای تجزیه و تحلیل معنای آنها تقسیم شوند. در متن وب، زبان ها و اسکریپت های مختلف اغلب با هم ترکیب می شوند، مانند "NY株価" (بورس سهام نیویورک).
ما میتوانیم با استفاده از تغییرات در اسکریپت برای تقریبی مرزهای کلمات، تقسیمبندی بسیار خشن (بدون اجرای هیچ مدل ML) انجام دهیم. این برای رشته هایی مانند مثال "NY株価" در بالا کار می کند. همچنین برای اکثر زبانهایی که از فاصله استفاده میکنند، کار میکند، زیرا کاراکترهای فاصله اسکریپتهای مختلف همه به عنوان USCRIPT_COMMON طبقهبندی میشوند، یک کد اسکریپت ویژه که با هر متن واقعی متفاوت است.
# dtype: string; shape: [num_sentences]
#
# The sentences to process. Edit this line to try out different inputs!
sentence_texts = [u'Hello, world.', u'世界こんにちは']
ابتدا جملات را به نقاط کد کاراکتر رمزگشایی کنید و شناسه اسکریپت را برای هر کاراکتر پیدا کنید.
# dtype: int32; shape: [num_sentences, (num_chars_per_sentence)]
#
# sentence_char_codepoint[i, j] is the codepoint for the j'th character in
# the i'th sentence.
sentence_char_codepoint = tf.strings.unicode_decode(sentence_texts, 'UTF-8')
print(sentence_char_codepoint)
# dtype: int32; shape: [num_sentences, (num_chars_per_sentence)]
#
# sentence_char_scripts[i, j] is the Unicode script of the j'th character in
# the i'th sentence.
sentence_char_script = tf.strings.unicode_script(sentence_char_codepoint)
print(sentence_char_script)
<tf.RaggedTensor [[72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 46], [19990, 30028, 12371, 12435, 12395, 12385, 12399]]> <tf.RaggedTensor [[25, 25, 25, 25, 25, 0, 0, 25, 25, 25, 25, 25, 0], [17, 17, 20, 20, 20, 20, 20]]>
از شناسه های اسکریپت برای تعیین اینکه مرزهای کلمه باید در کجا اضافه شوند استفاده کنید. در ابتدای هر جمله و برای هر کاراکتری که خط آن با کاراکتر قبلی متفاوت است، یک مرز کلمه اضافه کنید.
# dtype: bool; shape: [num_sentences, (num_chars_per_sentence)]
#
# sentence_char_starts_word[i, j] is True if the j'th character in the i'th
# sentence is the start of a word.
sentence_char_starts_word = tf.concat(
[tf.fill([sentence_char_script.nrows(), 1], True),
tf.not_equal(sentence_char_script[:, 1:], sentence_char_script[:, :-1])],
axis=1)
# dtype: int64; shape: [num_words]
#
# word_starts[i] is the index of the character that starts the i'th word (in
# the flattened list of characters from all sentences).
word_starts = tf.squeeze(tf.where(sentence_char_starts_word.values), axis=1)
print(word_starts)
tf.Tensor([ 0 5 7 12 13 15], shape=(6,), dtype=int64)
پس از آن شما می توانید استفاده از آن آفست شروع به ساخت یک RaggedTensor
حاوی لیستی از کلمات از تمام دسته.
# dtype: int32; shape: [num_words, (num_chars_per_word)]
#
# word_char_codepoint[i, j] is the codepoint for the j'th character in the
# i'th word.
word_char_codepoint = tf.RaggedTensor.from_row_starts(
values=sentence_char_codepoint.values,
row_starts=word_starts)
print(word_char_codepoint)
<tf.RaggedTensor [[72, 101, 108, 108, 111], [44, 32], [119, 111, 114, 108, 100], [46], [19990, 30028], [12371, 12435, 12395, 12385, 12399]]>
تا پایان، بخش کلمه codepoints RaggedTensor
تماس را به جملات و رمزگذاری به UTF-8 رشته برای خوانایی.
# dtype: int64; shape: [num_sentences]
#
# sentence_num_words[i] is the number of words in the i'th sentence.
sentence_num_words = tf.reduce_sum(
tf.cast(sentence_char_starts_word, tf.int64),
axis=1)
# dtype: int32; shape: [num_sentences, (num_words_per_sentence), (num_chars_per_word)]
#
# sentence_word_char_codepoint[i, j, k] is the codepoint for the k'th character
# in the j'th word in the i'th sentence.
sentence_word_char_codepoint = tf.RaggedTensor.from_row_lengths(
values=word_char_codepoint,
row_lengths=sentence_num_words)
print(sentence_word_char_codepoint)
tf.strings.unicode_encode(sentence_word_char_codepoint, 'UTF-8').to_list()
<tf.RaggedTensor [[[72, 101, 108, 108, 111], [44, 32], [119, 111, 114, 108, 100], [46]], [[19990, 30028], [12371, 12435, 12395, 12385, 12399]]]> [[b'Hello', b', ', b'world', b'.'], [b'\xe4\xb8\x96\xe7\x95\x8c', b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf']]