Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Unicode dizeleri

TensorFlow.org'da görüntüleyin Google Colab'de çalıştırın Kaynağı GitHub'da görüntüleyin Defteri indirin

Giriş

Doğal dili işleyen modeller genellikle farklı karakter kümelerine sahip farklı dilleri ele alır. Unicode , hemen hemen tüm dillerdeki karakterleri temsil etmek için kullanılan standart bir kodlama sistemidir. Her karakter, 0 ile 0x10FFFF arasında benzersiz bir tamsayı kod noktası kullanılarak kodlanır. Unicode dizesi , sıfır veya daha fazla kod noktası dizisidir.

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

import tensorflow as tf

tf.string veri türü

Temel TensorFlow tf.string dtype , bayt dizelerinin tensörlerini oluşturmanıza olanak sağlar. Unicode dizeleri varsayılan olarak utf-8 olarak kodlanmıştır.

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

Bir tf.string tensörü, bayt dizeleri atomik birimler olarak değerlendirildiğinden, farklı uzunluklarda bayt dizelerini tutabilir. İp uzunluğu tensör boyutlarına dahil değildir.

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

Unicode'u temsil etmek

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

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

Örneğin, aşağıdaki üç değerin tümü Unicode dizesi "语言处理" ( "语言处理" "dil işleme" anlamına gelir) temsil eder:

# 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, en içteki boyutun uzunluğunun her dizedeki karakter sayısına bağlı olarak değiştiği bir 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]

Bu kullanabilirsiniztf.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()

Aynı uzunlukta birden çok dizeyi tf.Tensor , girdi olarak bir tf.Tensor kullanılabilir:

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 uzunluktaki birden çok dizeyitf.RaggedTensor , girdi olarak birtf.RaggedTensor kullanılmalıdı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)>

Yastıklı veya seyrek biçimde birden çok dizeye sahip bir tensörünüz varsa, unicode_encodetf.RaggedTensor önce bunu birtf.RaggedTensor dönüştürün:

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

tf.strings.length işlemi, uzunlukların nasıl hesaplanması gerektiğini belirten bir parametre unit sahiptir. unit varsayılan olarak "BYTE" , ancak kodlanmış her string Unicode kod noktalarının sayısını belirlemek için "UTF8_CHAR" veya "UTF16_CHAR" gibi diğer değerlere ayarlanabilir.

# 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

Benzer şekilde, tf.strings.substr işlemi " unit " parametresini kabul eder ve bunu " pos " ve " len " parametrelerinin ne tür ofsetler içerdiğini belirlemek için kullanır.

# default: unit='BYTE'. With len=1, we return a single byte.
tf.strings.substr(thanks, pos=7, len=1).numpy()
b'\xf0'
# Specifying unit='UTF8_CHAR', we return a single character, which in this case
# is 4 bytes.
print(tf.strings.substr(thanks, pos=7, len=1, unit='UTF8_CHAR').numpy())
b'\xf0\x9f\x98\x8a'

Unicode dizelerini bölme

tf.strings.unicode_split işlemi, unicode dizelerini tek tek karakterlerin alt dizelerine 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 uzaklıkları

tf.strings.unicode_decode tarafından oluşturulan karakter tensörünü orijinal dizeyle hizalamak için, her karakterin başladığı yerin uzaklığını bilmek yararlıdır. tf.strings.unicode_decode_with_offsets yöntemi, her karakterin başlangıç ​​ofsetini içeren ikinci bir tensör döndürmesi dışında unicode_decode benzer.

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ı, komut dosyası olarak bilinen tek bir kod noktası koleksiyonuna aittir. Bir karakterin yazısı, karakterin hangi dilde olabileceğini belirlemede yardımcı olur. Örneğin, 'Б' nin Kiril alfabesiyle yazıldığını bilmek, bu karakteri içeren modern metnin Rusça veya Ukraynaca gibi bir Slav dilinden geldiğini gösterir.

TensorFlow, belirli bir kod noktasının hangi komut dosyasını kullandığını belirlemek için tf.strings.unicode_script işlemini sağlar. 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, kod noktalarının çok boyutlu tf.Tensor s veyatf.RaggedTensor tf.Tensor da uygulanabilir:

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 bölme görevidir. Bu, kelimeleri ayırmak için boşluk karakterleri kullanıldığında 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 Borsası) gibi, farklı diller ve komut dosyaları sıklıkla karıştırılır.

Kelime sınırlarını tahmin etmek için komut dosyasındaki değişiklikleri kullanarak (herhangi bir ML modelini uygulamadan) çok kaba bölümleme gerçekleştirebiliriz. Bu, yukarıdaki "NY 株 価" örneği gibi dizeler için çalışacaktır. Ayrıca, çeşitli komut dosyalarının boşluk karakterlerinin tümü, herhangi bir gerçek metinden farklı özel bir komut dosyası kodu olan USCRIPT_COMMON olarak sınıflandırıldığından, boşluk kullanan çoğu dilde de çalışacaktı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ümleleri karakter kod noktalarına çözeriz ve her karakter için komut dosyası kimliğini buluruz.

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

Daha sonra, kelime sınırlarının nereye ekleneceğini belirlemek için bu komut dosyası tanımlayıcılarını kullanırız. Her cümlenin başına bir kelime sınırı ekliyoruz ve senaryosu önceki karakterden farklı olan her karakter için:

# 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 bu başlangıç ​​uzaklıklarını, tüm RaggedTensor sözcüklerin listesini içeren bir RaggedTensor oluşturmak için 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]]>

Son olarak, kod noktaları RaggedTensor kelimesini tekrar cümlelere RaggedTensor :

# 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.RaggedTensor [[[72, 101, 108, 108, 111], [44, 32], [119, 111, 114, 108, 100], [46]], [[19990, 30028], [12371, 12435, 12395, 12385, 12399]]]>

Nihai sonucun okunmasını kolaylaştırmak için, onu tekrar UTF-8 dizelerine kodlayabiliriz:

tf.strings.unicode_encode(sentence_word_char_codepoint, 'UTF-8').to_list()
[[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']]