Unicode dizeleri

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Not defterini indir

Tanıtım

NLP modelleri genellikle farklı karakter setleriyle farklı dilleri işler. Unicode neredeyse tüm dillerdeki karakterleri göstermek için kullanılan standart bir kodlama sistemidir. Her Unicode karakter benzersiz tamsayı kullanılarak kodlanan kod noktası arasındaki 0 ve 0x10FFFF . Bir Unicode dizgisini sıfır ya da daha fazla kod noktalarına bir dizisidir.

Bu öğretici, Unicode dizelerinin TensorFlow'da nasıl temsil edileceğini ve standart dize operasyonlarının Unicode eşdeğerlerini kullanarak bunların nasıl değiştirileceğini gösterir. Unicode dizelerini, komut dosyası algılamaya dayalı olarak belirteçlere ayırır.

import tensorflow as tf
import numpy as np

tf.string veri türü

Temel TensorFlow tf.string dtype sen bayt dizeleri tensörleri oluşturmanızı sağlar. Unicode dizeleri utf-8 varsayılan olarak kodlanmış.

tf.constant(u"Thanks 😊")
<tf.Tensor: shape=(), dtype=string, numpy=b'Thanks \xf0\x9f\x98\x8a'>

Bir tf.string tensör davranır atomik birimler olarak dizeleri bayt. Bu, farklı uzunluklardaki bayt dizilerini saklamasını sağlar. Tel uzunluğu, tensör boyutlarına dahil değildir.

tf.constant([u"You're", u"welcome!"]).shape
TensorShape([2])

Eğer yapı dizelerine Python kullanıyorsanız, not o dize hazır olan varsayılan olarak Unicode ile kodlanmış.

Unicode'u temsil etme

TensorFlow'da bir Unicode dizesini temsil etmenin iki standart yolu vardır:

  • string skalar - kod noktalarının dizisi bilinen kullanılarak kodlanır karakter kodlamasını .
  • int32 vektör - her bir konum tek bir kod noktası içerir.

Örneğin, aşağıdaki üç değer tüm Unicode dizesi temsil "语言处理" (Çince hangi vasıta "dil işleme"):

# 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)>

temsiller arasında dönüştürme

TensorFlow, bu farklı temsiller arasında dönüştürme işlemleri sağlar:

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'>

Parti boyutları

Birden çok dizenin kodunu çözerken, her dizedeki karakter sayısı eşit olmayabilir. Dönüş sonucu meydana gelir tf.RaggedTensor iç boyutu uzunluk her bir dize karakter sayısına bağlı olarak değişir.

# 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]

Bu kullanabilirsiniz tf.RaggedTensor doğrudan veya yoğun dönüştürmek tf.Tensor dolgu veya bir ile tf.SparseTensor yöntemlerle tf.RaggedTensor.to_tensor ve 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,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _,      _]]

Aynı uzunlukta olan çok sayıda dizge kodlarken, bir kullanma tf.Tensor girdi olarak kullanılmaktadır.

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)>

Değişken uzunlukta olan çok sayıda dizge kodlarken, bir kullanma tf.RaggedTensor girdi olarak kullanılmaktadır.

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)>

Eğer yastıklı veya seyrek biçimde birden çok dizeli bir tensörünü varsa, içine ilk dönüştürmek tf.RaggedTensor çağırmadan önce 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)>

Unicode işlemleri

karakter uzunluğu

Kullanım unit parametresi tf.strings.length karakter uzunlukları bilgisayarlı nasıl olması gerektiği belirten op. unit varsayılan "BYTE" , ancak bu gibi başka değerler, ayarlanabilir "UTF8_CHAR" ya da "UTF16_CHAR" , her bir kodlanmış dize Unicode codepoints sayısını belirlemek için.

# 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

Karakter alt dizeleri

tf.strings.substr op kabul unit parametresi ve nazik uzaklıklar belirlemek için kullanır pos ve len parametrelerine içerirler.

# 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'

Unicode dizelerini böl

tf.strings.unicode_split operasyonu bireysel karakterlerin alt dizelere içine unicode dizeleri böler.

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)

Karakterler için bayt ofsetleri

Tarafından üretilen karakter tensörünü hizalamak için tf.strings.unicode_decode orijinal dize ile, her karakter başladığı için ofset bilmek yararlıdır. Yöntem tf.strings.unicode_decode_with_offsets benzer unicode_decode her karakter başlangıç ofsetinin içeren ikinci tensörünün döndürmesi dışında.

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

Unicode komut dosyaları

Her Unicode kod noktası olarak bilinen codepoints tek koleksiyona ait senaryo . Bir karakterin yazısı, karakterin hangi dilde olabileceğini belirlemede yardımcı olur. Örneğin, 'Б'nin Kiril alfabesinde olduğunu bilmek, o karakteri içeren modern metnin muhtemelen Rusça veya Ukraynaca gibi bir Slav dilinden geldiğini gösterir.

TensorFlow içerir tf.strings.unicode_script olan komut, belirli bir kod noktası kullanımını belirlemek için işlem. Komut kodları int32 tekabül değerleri Unicode için Uluslararası Bileşenlerinin (YBÜ) UScriptCode değerler.

uscript = tf.strings.unicode_script([33464, 1041])  # ['芸', 'Б']

print(uscript.numpy())  # [17, 8] == [USCRIPT_HAN, USCRIPT_CYRILLIC]
[17  8]

tf.strings.unicode_script işlemi de çok boyutlu uygulanabilir tf.Tensor ler veya tf.RaggedTensor s codepoints arasında:

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]]>

Örnek: Basit segmentasyon

Segmentasyon, metni kelime benzeri birimlere ayırma görevidir. Sözcükleri ayırmak için boşluk karakterleri kullanıldığında bu genellikle kolaydır, ancak bazı diller (Çince ve Japonca gibi) boşluk kullanmaz ve bazı diller (Almanca gibi) anlamlarını analiz etmek için bölünmesi gereken uzun bileşikler içerir. Web metninde, "NY株価" (New York Menkul Kıymetler Borsası) örneğinde olduğu gibi, farklı diller ve yazılar sıklıkla birlikte karıştırılır.

Kelime sınırlarını yaklaşık olarak belirlemek için komut dosyasındaki değişiklikleri kullanarak (herhangi bir ML modeli uygulamadan) çok kaba segmentasyon gerçekleştirebiliriz. Bu, yukarıdaki "NY株価" örneğindeki gibi dizeler için işe yarar. Ayrıca, çeşitli komut dosyalarının boşluk karakterlerinin tümü, herhangi bir gerçek metinden farklı olan özel bir komut dosyası kodu olan USCRIPT_COMMON olarak sınıflandırıldığından, boşluk kullanan çoğu dilde çalışır.

# dtype: string; shape: [num_sentences]
#
# The sentences to process.  Edit this line to try out different inputs!
sentence_texts = [u'Hello, world.', u'世界こんにちは']

İlk olarak, cümlelerin kodunu karakter kod noktalarına çözün ve her karakter için kod tanımlayıcısını bulun.

# 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]]>

Kelime sınırlarının nereye eklenmesi gerektiğini belirlemek için kod tanımlayıcılarını kullanın. Her cümlenin başına ve yazısı önceki karakterden farklı olan her karakter için bir kelime sınırı ekleyin.

# 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)

Daha sonra kurmak için bu başlangıç uzaklıklar kullanabilirsiniz RaggedTensor tüm toplu kelimelerin listesini içeren.

# 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]]>

Bitirmek için, bölüm kelimesi codepoints RaggedTensor okunabilirlik için UTF-8 dizeleri içine cümle ve kodlamak içine geri.

# 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']]