TensorFlow.org'da görüntüleyin | Google Colab'da çalıştırın | Kaynağı GitHub'da görüntüleyin | Not defterini indir |
Kurmak
!pip install -q tf_nightly
import tensorflow as tf
import numpy as np
from typing import Tuple, List, Mapping, Union, Optional
import tempfile
Uzantı türleri
Kullanıcı tanımlı türler projeleri daha okunabilir, modüler ve sürdürülebilir hale getirebilir. Ancak çoğu TensorFlow API'si, kullanıcı tanımlı Python türleri için çok sınırlı desteğe sahiptir. Buna hem yüksek seviyeli API'ler ( Keras , tf.function , tf.SavedModel gibi) hem de alt seviye API'ler ( tf.while_loop
ve tf.concat
gibi) dahildir. TensorFlow uzantı türleri , TensorFlow'un API'leriyle sorunsuz bir şekilde çalışan kullanıcı tanımlı nesne yönelimli türler oluşturmak için kullanılabilir. Bir uzantı türü oluşturmak için, temel olarak tf.experimental.ExtensionType
olan bir Python sınıfı tanımlamanız ve her alanın türünü belirtmek için tür açıklamalarını kullanmanız yeterlidir.
class TensorGraph(tf.experimental.ExtensionType):
"""A collection of labeled nodes connected by weighted edges."""
edge_weights: tf.Tensor # shape=[num_nodes, num_nodes]
node_labels: Mapping[str, tf.Tensor] # shape=[num_nodes]; dtype=any
class MaskedTensor(tf.experimental.ExtensionType):
"""A tensor paired with a boolean mask, indicating which values are valid."""
values: tf.Tensor
mask: tf.Tensor # shape=values.shape; false for missing/invalid values.
class CSRSparseMatrix(tf.experimental.ExtensionType):
"""Compressed sparse row matrix (https://en.wikipedia.org/wiki/Sparse_matrix)."""
values: tf.Tensor # shape=[num_nonzero]; dtype=any
col_index: tf.Tensor # shape=[num_nonzero]; dtype=int64
row_index: tf.Tensor # shape=[num_rows+1]; dtype=int64
tf.experimental.ExtensionType
temel sınıfı, standart Python kitaplığından.NamedTuple ve @dataclasses.dataclass
typing.NamedTuple
benzer şekilde çalışır. Özellikle, alan türü açıklamalarına göre otomatik olarak bir kurucu ve özel yöntemler ( __repr__
ve __eq__
gibi) ekler.
Tipik olarak, uzantı türleri iki kategoriden birine girme eğilimindedir:
İlgili değerler koleksiyonunu bir araya getiren ve bu değerlere dayalı olarak faydalı işlemler sağlayabilen veri yapıları . Veri yapıları oldukça genel olabilir (yukarıdaki
TensorGraph
örneği gibi); veya belirli bir modele göre son derece özelleştirilebilirler."Tensor" kavramını uzmanlaştıran veya genişleten tensör benzeri türler . Bu kategorideki türlerin bir
rank
, birshape
ve genellikle birdtype
; ve bunları Tensor işlemleriyle kullanmak mantıklıdır (tf.stack
,tf.add
veyatf.matmul
gibi).MaskedTensor
veCSRSparseMatrix
, tensör benzeri türlerin örnekleridir.
Desteklenen API'ler
Uzantı türleri, aşağıdaki TensorFlow API'leri tarafından desteklenir:
- Keras : Uzantı türleri, Keras
Models
veLayers
için girdi ve çıktı olarak kullanılabilir. - tf.data.Dataset : Uzantı türleri
Datasets
dahil edilebilir ve veri kümesiIterators
tarafından döndürülebilir . - Tensorflow hub : Uzantı türleri
tf.hub
modülleri için giriş ve çıkış olarak kullanılabilir. - SavedModel : Uzantı türleri
SavedModel
işlevleri için giriş ve çıkış olarak kullanılabilir. - tf.function : Uzantı türleri,
@tf.function
dekoratörüyle sarılmış işlevler için argümanlar ve dönüş değerleri olarak kullanılabilir. - while döngüleri : Uzantı türleri
tf.while_loop
içinde döngü değişkenleri olarak kullanılabilir ve while döngüsünün gövdesi için bağımsız değişkenler ve dönüş değerleri olarak kullanılabilir. - koşullular : Uzantı türleri
tf.cond
vetf.case
kullanılarak koşullu olarak seçilebilir. - py_function : Uzantı türleri bağımsız değişkenler olarak kullanılabilir ve
func
bağımsız değişkeni içintf.py_function
değer döndürür. - Tensör işlemleri : Uzantı türleri, Tensor girdilerini kabul eden çoğu TensorFlow işlemini destekleyecek şekilde genişletilebilir (örneğin,
tf.matmul
,tf.gather
vetf.reduce_sum
). Daha fazla bilgi için aşağıdaki " Sevk " bölümüne bakın. - dağıtım stratejisi : Uzantı türleri, çoğaltma başına değerler olarak kullanılabilir.
Daha fazla ayrıntı için aşağıdaki "Uzantı Türlerini destekleyen TensorFlow API'leri" bölümüne bakın.
Gereksinimler
Alan türleri
Tüm alanlar (örnek değişkenleri olarak da bilinir) bildirilmelidir ve her alan için bir tür ek açıklaması sağlanmalıdır. Aşağıdaki tür ek açıklamaları desteklenir:
Tip | Örnek |
---|---|
Python tamsayıları | i: int |
Python yüzer | f: float |
Python dizeleri | s: str |
Python boole değerleri | b: bool |
Python Yok | n: None |
Tensör şekilleri | shape: tf.TensorShape |
Tensör tipleri | dtype: tf.DType |
Tensörler | t: tf.Tensor |
Uzantı türleri | mt: MyMaskedTensor |
Düzensiz Tensörler | rt: tf.RaggedTensor |
Seyrek Tensörler | st: tf.SparseTensor |
Dizine Eklenen Dilimler | s: tf.IndexedSlices |
Opsiyonel Tensörler | o: tf.experimental.Optional |
Tip birlikleri | int_or_float: typing.Union[int, float] |
demetler | params: typing.Tuple[int, float, tf.Tensor, int] |
Var uzunluklu demetler | lengths: typing.Tuple[int, ...] |
Eşlemeler | tags: typing.Mapping[str, tf.Tensor] |
İsteğe bağlı değerler | weight: typing.Optional[tf.Tensor] |
değişebilirlik
Uzantı türlerinin değişmez olması gerekir. Bu, TensorFlow'un grafik izleme mekanizmaları tarafından düzgün bir şekilde izlenebilmelerini sağlar. Bir uzantı türü değerini değiştirmek istediğinizi fark ederseniz, bunun yerine değerleri dönüştüren yöntemler tanımlamayı düşünün. Örneğin, bir MaskedTensor
mutasyona uğratmak için bir set_mask
yöntemi tanımlamak yerine, yeni bir MaskedTensor
döndüren bir replace_mask
yöntemi tanımlayabilirsiniz:
class MaskedTensor(tf.experimental.ExtensionType):
values: tf.Tensor
mask: tf.Tensor
def replace_mask(self, new_mask):
self.values.shape.assert_is_compatible_with(new_mask.shape)
return MaskedTensor(self.values, new_mask)
ExtensionType
tarafından eklenen işlevsellik
ExtensionType
temel sınıfı aşağıdaki işlevleri sağlar:
- Bir yapıcı (
__init__
). - Yazdırılabilir bir temsil yöntemi (
__repr__
). - Eşitlik ve eşitsizlik operatörleri (
__eq__
). - Bir doğrulama yöntemi (
__validate__
). - Zorunlu değişmezlik.
- İç içe bir
TypeSpec
. - Tensor API gönderme desteği.
Bu işlevi özelleştirme hakkında daha fazla bilgi için aşağıdaki "Uzantı Türlerini Özelleştirme" bölümüne bakın.
yapıcı
ExtensionType
tarafından eklenen yapıcı, her alanı adlandırılmış bir bağımsız değişken olarak alır (sınıf tanımında listelendikleri sırayla). Bu kurucu, her parametreyi tip-kontrol edecek ve gerektiğinde onları dönüştürecektir. Özellikle, Tensor
alanları tf.convert_to_tensor
kullanılarak dönüştürülür; Tuple
alanları, tuple
s'ye dönüştürülür; ve Mapping
alanları değişmez diktelere dönüştürülür.
class MaskedTensor(tf.experimental.ExtensionType):
values: tf.Tensor
mask: tf.Tensor
# Constructor takes one parameter for each field.
mt = MaskedTensor(values=[[1, 2, 3], [4, 5, 6]],
mask=[[True, True, False], [True, False, True]])
# Fields are type-checked and converted to the declared types.
# E.g., mt.values is converted to a Tensor.
print(mt.values)
tutucu4 l10n-yertf.Tensor( [[1 2 3] [4 5 6]], shape=(2, 3), dtype=int32)
Alan değeri bildirilen türe dönüştürülemezse, yapıcı bir TypeError
oluşturur:
try:
MaskedTensor([1, 2, 3], None)
except TypeError as e:
print(f"Got expected TypeError: {e}")
tutucu6 l10n-yerGot expected TypeError: mask: expected a Tensor, got None
Bir alanın varsayılan değeri, değeri sınıf düzeyinde ayarlanarak belirlenebilir:
class Pencil(tf.experimental.ExtensionType):
color: str = "black"
has_erasor: bool = True
length: tf.Tensor = 1.0
Pencil()
Pencil(color='black', has_erasor=True, length=<tf.Tensor: shape=(), dtype=float32, numpy=1.0>)yer tutucu9 l10n-yer
Pencil(length=0.5, color="blue")
Pencil(color='blue', has_erasor=True, length=<tf.Tensor: shape=(), dtype=float32, numpy=0.5>)
Yazdırılabilir gösterim
ExtensionType
, sınıf adını ve her alanın değerini içeren varsayılan yazdırılabilir bir temsil yöntemi ( __repr__
) ekler:
print(MaskedTensor(values=[1, 2, 3], mask=[True, True, False]))
tutucu12 l10n-yerMaskedTensor(values=<tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 2, 3], dtype=int32)>, mask=<tf.Tensor: shape=(3,), dtype=bool, numpy=array([ True, True, False])>)
eşitlik operatörleri
ExtensionType
, aynı türe sahiplerse ve tüm alanları eşitse iki değeri eşit kabul eden varsayılan eşitlik operatörleri ( __eq__
ve __ne__
) ekler. Tensör alanları, aynı şekle sahipse ve tüm elemanlar için eleman bazında eşitse eşit kabul edilir.
a = MaskedTensor([1, 2], [True, False])
b = MaskedTensor([[3, 4], [5, 6]], [[False, True], [True, True]])
print(f"a == a: {a==a}")
print(f"a == b: {a==b}")
print(f"a == a.values: {a==a.values}")
tutucu14 l10n-yera == a: True a == b: False a == a.values: False
doğrulama yöntemi
ExtensionType
, alanlarda doğrulama kontrolleri yapmak için geçersiz kılınabilen bir __validate__
yöntemi ekler. Yapıcı çağrıldıktan sonra ve alanlar tip kontrolü yapıldıktan ve beyan edilen tiplerine dönüştürüldükten sonra çalıştırılır, böylece tüm alanların beyan edilmiş tiplerine sahip olduğunu varsayabilir.
Aşağıdaki örnek, alanlarının shape
s ve dtype
s değerlerini doğrulamak için MaskedTensor
günceller:
class MaskedTensor(tf.experimental.ExtensionType):
"""A tensor paired with a boolean mask, indicating which values are valid."""
values: tf.Tensor
mask: tf.Tensor
def __validate__(self):
self.values.shape.assert_is_compatible_with(self.mask.shape)
assert self.mask.dtype.is_bool, 'mask.dtype must be bool'
try:
MaskedTensor([1, 2, 3], [0, 1, 0]) # wrong dtype for mask.
except AssertionError as e:
print(f"Got expected AssertionError: {e}")
Got expected AssertionError: mask.dtype must be bool
try:
MaskedTensor([1, 2, 3], [True, False]) # shapes don't match.
except ValueError as e:
print(f"Got expected ValueError: {e}")
Got expected ValueError: Shapes (3,) and (2,) are incompatible
Zorunlu değişmezlik
ExtensionType
, mutasyonu önlemek için __setattr__
ve __delattr__
yöntemlerini geçersiz kılar ve uzantı türü değerlerinin değişmez olmasını sağlar.
mt = MaskedTensor([1, 2, 3], [True, False, True])
try:
mt.mask = [True, True, True]
except AttributeError as e:
print(f"Got expected AttributeError: {e}")
Got expected AttributeError: Cannot mutate attribute `mask` outside the custom constructor of ExtensionType.
try:
mt.mask[0] = False
except TypeError as e:
print(f"Got expected TypeError: {e}")
Got expected TypeError: 'tensorflow.python.framework.ops.EagerTensor' object does not support item assignment
try:
del mt.mask
except AttributeError as e:
print(f"Got expected AttributeError: {e}")
Got expected AttributeError: Cannot mutate attribute `mask` outside the custom constructor of ExtensionType.
İç İçe TipÖzellik
Her ExtensionType
sınıfı, otomatik olarak oluşturulan ve <extension_type_name>.Spec
olarak depolanan karşılık gelen bir TypeSpec
sınıfına sahiptir.
Bu sınıf, iç içe geçmiş tensörlerin değerleri dışındaki tüm bilgileri bir değerden yakalar. Özellikle, bir değer için TypeSpec
, iç içe geçmiş herhangi bir Tensor, ExtensionType veya CompositeTensor ile TypeSpec
değiştirilerek oluşturulur.
class Player(tf.experimental.ExtensionType):
name: tf.Tensor
attributes: Mapping[str, tf.Tensor]
anne = Player("Anne", {"height": 8.3, "speed": 28.1})
anne_spec = tf.type_spec_from_value(anne)
print(anne_spec.name) # Records dtype and shape, but not the string value.
print(anne_spec.attributes) # Records keys and TensorSpecs for values.
tutucu28 l10n-yerWARNING:tensorflow:Mapping types may not work well with tf.nest. Prefer using MutableMapping for <class 'tensorflow.python.framework.immutable_dict.ImmutableDict'> TensorSpec(shape=(), dtype=tf.string, name=None) ImmutableDict({'height': TensorSpec(shape=(), dtype=tf.float32, name=None), 'speed': TensorSpec(shape=(), dtype=tf.float32, name=None)})
TypeSpec
değerleri açıkça oluşturulabilir veya tf.type_spec_from_value
kullanılarak bir ExtensionType
değerinden oluşturulabilir:
spec1 = Player.Spec(name=tf.TensorSpec([], tf.float32), attributes={})
spec2 = tf.type_spec_from_value(anne)
TypeSpec
ler, değerleri statik bir bileşene ve bir dinamik bileşene bölmek için TensorFlow tarafından kullanılır:
- Statik bileşen (grafik oluşturma zamanında sabitlenir) bir
tf.TypeSpec
ile kodlanmıştır. - Dinamik bileşen (grafik her çalıştırıldığında değişebilen),
tf.Tensor
s listesi olarak kodlanmıştır.
Örneğin, bir bağımsız değişkenin daha önce görülmeyen bir TypeSpec
olduğunda, tf.function
sarılmış işlevinin izini sürer:
@tf.function
def anonymize_player(player):
print("<<TRACING>>")
return Player("<anonymous>", player.attributes)
# Function gets traced (first time the function has been called):
anonymize_player(Player("Anne", {"height": 8.3, "speed": 28.1}))
WARNING:tensorflow:Mapping types may not work well with tf.nest. Prefer using MutableMapping for <class 'tensorflow.python.framework.immutable_dict.ImmutableDict'> WARNING:tensorflow:Mapping types may not work well with tf.nest. Prefer using MutableMapping for <class 'tensorflow.python.framework.immutable_dict.ImmutableDict'> <<TRACING>> Player(name=<tf.Tensor: shape=(), dtype=string, numpy=b'<anonymous>'>, attributes=ImmutableDict({'height': <tf.Tensor: shape=(), dtype=float32, numpy=8.3>, 'speed': <tf.Tensor: shape=(), dtype=float32, numpy=28.1>}))
# Function does NOT get traced (same TypeSpec: just tensor values changed)
anonymize_player(Player("Bart", {"height": 8.1, "speed": 25.3}))
Player(name=<tf.Tensor: shape=(), dtype=string, numpy=b'<anonymous>'>, attributes=ImmutableDict({'height': <tf.Tensor: shape=(), dtype=float32, numpy=8.1>, 'speed': <tf.Tensor: shape=(), dtype=float32, numpy=25.3>}))
# Function gets traced (new TypeSpec: keys for attributes changed):
anonymize_player(Player("Chuck", {"height": 11.0, "jump": 5.3}))
<<TRACING>> Player(name=<tf.Tensor: shape=(), dtype=string, numpy=b'<anonymous>'>, attributes=ImmutableDict({'height': <tf.Tensor: shape=(), dtype=float32, numpy=11.0>, 'jump': <tf.Tensor: shape=(), dtype=float32, numpy=5.3>}))
Daha fazla bilgi için tf.function Guide'a bakın.
Uzantı Türlerini Özelleştirme
Yalnızca alanları ve türlerini bildirmeye ek olarak, uzantı türleri şunları yapabilir:
- Varsayılan yazdırılabilir gösterimi (
__repr__
) geçersiz kılın. - Yöntemleri tanımlayın.
- Sınıf yöntemlerini ve statik yöntemleri tanımlayın.
- Özellikleri tanımlayın.
- Varsayılan yapıcıyı (
__init__
) geçersiz kılın. - Varsayılan eşitlik operatörünü (
__eq__
) geçersiz kılın. - Operatörleri tanımlayın (
__add__
ve__lt__
gibi). - Alanlar için varsayılan değerler bildirin.
- Alt sınıfları tanımlayın.
Varsayılan yazdırılabilir gösterimi geçersiz kılma
Uzantı türleri için bu varsayılan dize dönüştürme operatörünü geçersiz kılabilirsiniz. Aşağıdaki örnek, değerler Eager modunda yazdırıldığında daha okunabilir bir dize temsili oluşturmak için MaskedTensor
sınıfını günceller.
class MaskedTensor(tf.experimental.ExtensionType):
"""A tensor paired with a boolean mask, indicating which values are valid."""
values: tf.Tensor
mask: tf.Tensor # shape=values.shape; false for invalid values.
def __repr__(self):
return masked_tensor_str(self.values, self.mask)
def masked_tensor_str(values, mask):
if isinstance(values, tf.Tensor):
if hasattr(values, 'numpy') and hasattr(mask, 'numpy'):
return f'<MaskedTensor {masked_tensor_str(values.numpy(), mask.numpy())}>'
else:
return f'MaskedTensor(values={values}, mask={mask})'
if len(values.shape) == 1:
items = [repr(v) if m else '_' for (v, m) in zip(values, mask)]
else:
items = [masked_tensor_str(v, m) for (v, m) in zip(values, mask)]
return '[%s]' % ', '.join(items)
mt = MaskedTensor(values=[[1, 2, 3], [4, 5, 6]],
mask=[[True, True, False], [True, False, True]])
print(mt)
tutucu38 l10n-yer<MaskedTensor [[1, 2, _], [4, _, 6]]>
yöntemleri tanımlama
Uzantı türleri, herhangi bir normal Python sınıfı gibi yöntemleri tanımlayabilir. Örneğin, MaskedTensor
türü, belirli bir default
değerle değiştirilen maskelenmiş değerlerle self
bir kopyasını döndüren bir with_default
yöntemi tanımlayabilir. Yöntemlere isteğe bağlı olarak @tf.function
dekoratörü ile açıklama eklenebilir.
class MaskedTensor(tf.experimental.ExtensionType):
values: tf.Tensor
mask: tf.Tensor
def with_default(self, default):
return tf.where(self.mask, self.values, default)
MaskedTensor([1, 2, 3], [True, False, True]).with_default(0)
tutucu40 l10n-yer<tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 0, 3], dtype=int32)>
Sınıf yöntemlerini ve statik yöntemleri tanımlama
Uzantı türleri, @classmethod
ve @staticmethod
dekoratörlerini kullanarak yöntemleri tanımlayabilir. Örneğin, MaskedTensor
türü, herhangi bir öğeyi belirli bir değerle maskeleyen bir fabrika yöntemi tanımlayabilir:
class MaskedTensor(tf.experimental.ExtensionType):
values: tf.Tensor
mask: tf.Tensor
def __repr__(self):
return masked_tensor_str(self.values, self.mask)
@staticmethod
def from_tensor_and_value_to_mask(values, value_to_mask):
return MaskedTensor(values, values == value_to_mask)
x = tf.constant([[1, 0, 2], [3, 0, 0]])
MaskedTensor.from_tensor_and_value_to_mask(x, 0)
tutucu42 l10n-yer<MaskedTensor [[_, 0, _], [_, 0, 0]]>
özellikleri tanımlama
Uzantı türleri, herhangi bir normal Python sınıfı gibi, @property
dekoratörünü kullanarak özellikleri tanımlayabilir. Örneğin, MaskedTensor
türü, değerlerin türü için bir kısayol olan bir dtype
özelliği tanımlayabilir:
class MaskedTensor(tf.experimental.ExtensionType):
values: tf.Tensor
mask: tf.Tensor
@property
def dtype(self):
return self.values.dtype
MaskedTensor([1, 2, 3], [True, False, True]).dtype
tutucu44 l10n-yertf.int32
Varsayılan yapıcıyı geçersiz kılma
Uzantı türleri için varsayılan kurucuyu geçersiz kılabilirsiniz. Özel oluşturucular, beyan edilen her alan için bir değer belirlemelidir; ve özel kurucu geri döndükten sonra, tüm alanların tipi kontrol edilecek ve değerler yukarıda açıklandığı gibi dönüştürülecektir.
class Toy(tf.experimental.ExtensionType):
name: str
price: tf.Tensor
def __init__(self, name, price, discount=0):
self.name = name
self.price = price * (1 - discount)
print(Toy("ball", 5.0, discount=0.2)) # On sale -- 20% off!
tutucu46 l10n-yerToy(name='ball', price=<tf.Tensor: shape=(), dtype=float32, numpy=4.0>)
Alternatif olarak, varsayılan kurucuyu olduğu gibi bırakmayı, ancak bir veya daha fazla fabrika yöntemi eklemeyi düşünebilirsiniz. Örneğin:
class Toy(tf.experimental.ExtensionType):
name: str
price: tf.Tensor
@staticmethod
def new_toy_with_discount(name, price, discount):
return Toy(name, price * (1 - discount))
print(Toy.new_toy_with_discount("ball", 5.0, discount=0.2))
tutucu48 l10n-yerToy(name='ball', price=<tf.Tensor: shape=(), dtype=float32, numpy=4.0>)
Varsayılan eşitlik operatörünü geçersiz kılma ( __eq__
)
Uzantı türleri için varsayılan __eq__
operatörünü geçersiz kılabilirsiniz. Aşağıdaki örnek, eşitlik için karşılaştırırken maskelenmiş öğeleri yok sayacak şekilde MaskedTensor
günceller.
class MaskedTensor(tf.experimental.ExtensionType):
values: tf.Tensor
mask: tf.Tensor
def __repr__(self):
return masked_tensor_str(self.values, self.mask)
def __eq__(self, other):
result = tf.math.equal(self.values, other.values)
result = result | ~(self.mask & other.mask)
return tf.reduce_all(result)
x = MaskedTensor([1, 2, 3, 4], [True, True, False, True])
y = MaskedTensor([5, 2, 0, 4], [False, True, False, True])
print(x == y)
tutucu50 l10n-yertf.Tensor(True, shape=(), dtype=bool)
İleri referansları kullanma
Bir alanın türü henüz tanımlanmadıysa, bunun yerine türün adını içeren bir dize kullanabilirsiniz. Aşağıdaki örnekte, Node
türü henüz (tam olarak) tanımlanmadığından alt alana açıklama eklemek için " children
"Node"
dizesi kullanılmıştır.
class Node(tf.experimental.ExtensionType):
value: tf.Tensor
children: Tuple["Node", ...] = ()
Node(3, [Node(5), Node(2)])
tutucu52 l10n-yerNode(value=<tf.Tensor: shape=(), dtype=int32, numpy=3>, children=(Node(value=<tf.Tensor: shape=(), dtype=int32, numpy=5>, children=()), Node(value=<tf.Tensor: shape=(), dtype=int32, numpy=2>, children=())))
Alt sınıfları tanımlama
Uzantı türleri, standart Python sözdizimi kullanılarak alt sınıflara ayrılabilir. Uzantı türü alt sınıfları yeni alanlar, yöntemler ve özellikler ekleyebilir; ve yapıcıyı, yazdırılabilir gösterimi ve eşitlik operatörünü geçersiz kılabilir. Aşağıdaki örnek, düğümler arasındaki bir dizi kenarı kodlamak için üç Tensor
alanı kullanan temel bir TensorGraph
sınıfını tanımlar. Ardından, her düğüm için bir "özellik değeri" kaydetmek için bir Tensor
alanı ekleyen bir alt sınıf tanımlar. Alt sınıf ayrıca özellik değerlerini kenarlar boyunca yaymak için bir yöntem tanımlar.
class TensorGraph(tf.experimental.ExtensionType):
num_nodes: tf.Tensor
edge_src: tf.Tensor # edge_src[e] = index of src node for edge e.
edge_dst: tf.Tensor # edge_dst[e] = index of dst node for edge e.
class TensorGraphWithNodeFeature(TensorGraph):
node_features: tf.Tensor # node_features[n] = feature value for node n.
def propagate_features(self, weight=1.0) -> 'TensorGraphWithNodeFeature':
updates = tf.gather(self.node_features, self.edge_src) * weight
new_node_features = tf.tensor_scatter_nd_add(
self.node_features, tf.expand_dims(self.edge_dst, 1), updates)
return TensorGraphWithNodeFeature(
self.num_nodes, self.edge_src, self.edge_dst, new_node_features)
g = TensorGraphWithNodeFeature( # Edges: 0->1, 4->3, 2->2, 2->1
num_nodes=5, edge_src=[0, 4, 2, 2], edge_dst=[1, 3, 2, 1],
node_features=[10.0, 0.0, 2.0, 5.0, -1.0, 0.0])
print("Original features:", g.node_features)
print("After propagating:", g.propagate_features().node_features)
tutucu54 l10n-yerOriginal features: tf.Tensor([10. 0. 2. 5. -1. 0.], shape=(6,), dtype=float32) After propagating: tf.Tensor([10. 12. 4. 4. -1. 0.], shape=(6,), dtype=float32)
Özel alanları tanımlama
Bir uzantı türünün alanları, bir alt çizgi ile önek eklenerek özel olarak işaretlenebilir (standart Python kurallarına göre). Bu, TensorFlow'un alanları herhangi bir şekilde ele alma şeklini etkilemez; ancak uzantı türündeki tüm kullanıcılara bu alanların özel olduğuna dair bir sinyal görevi görür.
ExtensionType'ın TypeSpec
Özelleştirme
Her ExtensionType
sınıfı, otomatik olarak oluşturulan ve <extension_type_name>.Spec
olarak depolanan karşılık gelen bir TypeSpec
sınıfına sahiptir. Daha fazla bilgi için yukarıdaki "İç içe TypeSpec" bölümüne bakın.
TypeSpec
özelleştirmek için, Spec
adlı kendi iç içe sınıfınızı tanımlamanız yeterlidir; ExtensionType
bunu otomatik olarak oluşturulan TypeSpec
için temel olarak kullanır. Spec
sınıfını şu şekilde özelleştirebilirsiniz:
- Varsayılan yazdırılabilir gösterimi geçersiz kılma.
- Varsayılan yapıcıyı geçersiz kılma.
- Yöntemleri, sınıf yöntemlerini, statik yöntemleri ve özellikleri tanımlama.
Aşağıdaki örnek, kullanımı kolaylaştırmak için MaskedTensor.Spec
sınıfını özelleştirir:
class MaskedTensor(tf.experimental.ExtensionType):
values: tf.Tensor
mask: tf.Tensor
shape = property(lambda self: self.values.shape)
dtype = property(lambda self: self.values.dtype)
def __repr__(self):
return masked_tensor_str(self.values, self.mask)
def with_values(self, new_values):
return MaskedTensor(new_values, self.mask)
class Spec:
def __init__(self, shape, dtype=tf.float32):
self.values = tf.TensorSpec(shape, dtype)
self.mask = tf.TensorSpec(shape, tf.bool)
def __repr__(self):
return f"MaskedTensor.Spec(shape={self.shape}, dtype={self.dtype})"
shape = property(lambda self: self.values.shape)
dtype = property(lambda self: self.values.dtype)
Tensör API gönderimi
Uzantı türleri, tf.Tensor
türü tarafından tanımlanan arabirimi uzmanlaştırmaları veya genişletmeleri anlamında "tensör benzeri" olabilir. Tensör benzeri uzantı türlerinin örnekleri arasında RaggedTensor
, SparseTensor
ve MaskedTensor
. Gönderim dekoratörleri , tensör benzeri uzantı türlerine uygulandığında TensorFlow işlemlerinin varsayılan davranışını geçersiz kılmak için kullanılabilir. TensorFlow şu anda üç dağıtım dekoratörü tanımlamaktadır:
-
@tf.experimental.dispatch_for_api(tf_api)
-
@tf.experimental.dispatch_for_unary_elementwise_api(x_type)
-
@tf.experimental.dispatch_for_binary_elementwise_apis(x_type, y_type)
Tek bir API için sevk
tf.experimental.dispatch_for_api
dekoratörü, belirtilen imza ile çağrıldığında belirtilen bir TensorFlow işleminin varsayılan davranışını geçersiz kılar. Örneğin, tf.stack'in MaskedTensor
değerlerini nasıl tf.stack
gerektiğini belirtmek için bu dekoratörü kullanabilirsiniz:
@tf.experimental.dispatch_for_api(tf.stack)
def masked_stack(values: List[MaskedTensor], axis = 0):
return MaskedTensor(tf.stack([v.values for v in values], axis),
tf.stack([v.mask for v in values], axis))
Bu, bir MaskedTensor
değerleri listesiyle çağrıldığında tf.stack
için varsayılan uygulamayı geçersiz kılar (çünkü values
bağımsız değişkeni typing.List[MaskedTensor]
ile açıklamalıdır):
x = MaskedTensor([1, 2, 3], [True, True, False])
y = MaskedTensor([4, 5, 6], [False, True, True])
tf.stack([x, y])
tutucu58 l10n-yer<MaskedTensor [[1, 2, _], [_, 5, 6]]>
tf.stack
karışık MaskedTensor
ve Tensor
değerlerinin listelerini işlemesine izin vermek için, values
parametresi için tür açıklamasını hassaslaştırabilir ve işlevin gövdesini uygun şekilde güncelleyebilirsiniz:
tf.experimental.unregister_dispatch_for(masked_stack)
def convert_to_masked_tensor(x):
if isinstance(x, MaskedTensor):
return x
else:
return MaskedTensor(x, tf.ones_like(x, tf.bool))
@tf.experimental.dispatch_for_api(tf.stack)
def masked_stack_v2(values: List[Union[MaskedTensor, tf.Tensor]], axis = 0):
values = [convert_to_masked_tensor(v) for v in values]
return MaskedTensor(tf.stack([v.values for v in values], axis),
tf.stack([v.mask for v in values], axis))
x = MaskedTensor([1, 2, 3], [True, True, False])
y = tf.constant([4, 5, 6])
tf.stack([x, y, x])
tutucu60 l10n-yer<MaskedTensor [[1, 2, _], [4, 5, 6], [1, 2, _]]>
Geçersiz kılınabilecek API'lerin listesi için tf.experimental.dispatch_for_api
için API belgelerine bakın.
Tüm unary elementwise API'leri için sevk
tf.experimental.dispatch_for_unary_elementwise_apis
dekoratörü, ilk bağımsız değişkenin değeri (tipik olarak x
olarak adlandırılır) tür ek açıklaması x_type
ile eşleştiğinde, tüm tekli öğesel işlemlerin ( tf.math.cos
gibi) varsayılan davranışını geçersiz kılar. Dekore edilmiş işlev iki argüman almalıdır:
-
api_func
: Tek bir parametre alan ve eleman bazında işlemi gerçekleştiren bir fonksiyon (örneğin,tf.abs
). -
x
: Elementwise işleminin ilk argümanı.
Aşağıdaki örnek, MaskedTensor
türünü işlemek için tüm tekli öğe işlemlerini günceller:
@tf.experimental.dispatch_for_unary_elementwise_apis(MaskedTensor)
def masked_tensor_unary_elementwise_api_handler(api_func, x):
return MaskedTensor(api_func(x.values), x.mask)
Bu işlev artık bir MaskedTensor
üzerinde tekli eleman bazında bir işlem çağrıldığında kullanılacaktır.
x = MaskedTensor([1, -2, -3], [True, False, True])
print(tf.abs(x))
<MaskedTensor [1, _, 3]>yer tutucu64 l10n-yer
print(tf.ones_like(x, dtype=tf.float32))
<MaskedTensor [1.0, _, 1.0]>
Tüm elementwise API'leri için ikili gönderim
Benzer şekilde, tf.experimental.dispatch_for_binary_elementwise_apis
, MaskedTensor
türünü işlemek için tüm ikili öğe tabanlı işlemleri güncellemek için kullanılabilir:
@tf.experimental.dispatch_for_binary_elementwise_apis(MaskedTensor, MaskedTensor)
def masked_tensor_binary_elementwise_api_handler(api_func, x, y):
return MaskedTensor(api_func(x.values, y.values), x.mask & y.mask)
x = MaskedTensor([1, -2, -3], [True, False, True])
y = MaskedTensor([[4], [5]], [[True], [False]])
tf.math.add(x, y)
-yer tutucu68 l10n-yer<MaskedTensor [[5, _, 1], [_, _, _]]>
Geçersiz kılınan öğe tabanlı API'lerin listesi için tf.experimental.dispatch_for_unary_elementwise_apis
ve tf.experimental.dispatch_for_binary_elementwise_apis
için API belgelerine bakın.
Toplu Uzantı Türleri
Bir dizi değeri temsil etmek için tek bir örnek kullanılabiliyorsa, ExtensionType
toplu işlenebilir . Tipik olarak bu, tüm iç içe Tensor
toplu boyutlar eklenerek gerçekleştirilir. Aşağıdaki TensorFlow API'leri, herhangi bir uzantı türü girdisinin toplu hale getirilebilir olmasını gerektirir:
-
tf.data.Dataset
(batch
, toplufrom_tensor_slices
unbatch
-
tf.Keras
(fit
,evaluate
,predict
et ) -
tf.map_fn
Varsayılan olarak BatchableExtensionType
, iç içe geçmiş Tensor
s, CompositeTensor
s ve ExtensionType
s'yi toplu işleyerek toplu değerler oluşturur. Bu, sınıfınız için uygun değilse, bu varsayılan davranışı geçersiz kılmak için tf.experimental.ExtensionTypeBatchEncoder
kullanmanız gerekecektir. Örneğin, ayrı ayrı seyrek tensörlerin values
, indices
ve dense_shape
alanlarını basitçe istifleyerek bir tf.SparseTensor
değerleri toplu işi oluşturmak uygun olmaz - çoğu durumda, uyumsuz şekillere sahip oldukları için bu tensörleri istifleyemezsiniz. ; ve yapabilseniz bile sonuç geçerli bir SparseTensor
.
BatchableExtensionType örneği: Ağ
Örnek olarak, yük dengeleme için kullanılan, her düğümde ne kadar iş kaldığını ve işi düğümler arasında taşımak için ne kadar bant genişliğinin mevcut olduğunu izleyen basit bir Network
sınıfını ele alalım:
class Network(tf.experimental.ExtensionType): # This version is not batchable.
work: tf.Tensor # work[n] = work left to do at node n
bandwidth: tf.Tensor # bandwidth[n1, n2] = bandwidth from n1->n2
net1 = Network([5., 3, 8], [[0., 2, 0], [2, 0, 3], [0, 3, 0]])
net2 = Network([3., 4, 2], [[0., 2, 2], [2, 0, 2], [2, 2, 0]])
Bu türü toplu hale getirmek için temel türü BatchableExtensionType
olarak değiştirin ve her alanın şeklini isteğe bağlı toplu iş boyutlarını içerecek şekilde ayarlayın. Aşağıdaki örnek, toplu iş şeklini takip etmek için bir shape
alanı da ekler. Bu shape
alanı tf.data.Dataset
veya tf.map_fn
tarafından gerekli değildir, ancak tf.Keras
tarafından gereklidir.
class Network(tf.experimental.BatchableExtensionType):
shape: tf.TensorShape # batch shape. A single network has shape=[].
work: tf.Tensor # work[*shape, n] = work left to do at node n
bandwidth: tf.Tensor # bandwidth[*shape, n1, n2] = bandwidth from n1->n2
def __init__(self, work, bandwidth):
self.work = tf.convert_to_tensor(work)
self.bandwidth = tf.convert_to_tensor(bandwidth)
work_batch_shape = self.work.shape[:-1]
bandwidth_batch_shape = self.bandwidth.shape[:-2]
self.shape = work_batch_shape.merge_with(bandwidth_batch_shape)
def __repr__(self):
return network_repr(self)
def network_repr(network):
work = network.work
bandwidth = network.bandwidth
if hasattr(work, 'numpy'):
work = ' '.join(str(work.numpy()).split())
if hasattr(bandwidth, 'numpy'):
bandwidth = ' '.join(str(bandwidth.numpy()).split())
return (f"<Network shape={network.shape} work={work} bandwidth={bandwidth}>")
net1 = Network([5., 3, 8], [[0., 2, 0], [2, 0, 3], [0, 3, 0]])
net2 = Network([3., 4, 2], [[0., 2, 2], [2, 0, 2], [2, 2, 0]])
batch_of_networks = Network(
work=tf.stack([net1.work, net2.work]),
bandwidth=tf.stack([net1.bandwidth, net2.bandwidth]))
print(f"net1={net1}")
print(f"net2={net2}")
print(f"batch={batch_of_networks}")
-yer tutucu72 l10n-yernet1=<Network shape=() work=[5. 3. 8.] bandwidth=[[0. 2. 0.] [2. 0. 3.] [0. 3. 0.]]> net2=<Network shape=() work=[3. 4. 2.] bandwidth=[[0. 2. 2.] [2. 0. 2.] [2. 2. 0.]]> batch=<Network shape=(2,) work=[[5. 3. 8.] [3. 4. 2.]] bandwidth=[[[0. 2. 0.] [2. 0. 3.] [0. 3. 0.]] [[0. 2. 2.] [2. 0. 2.] [2. 2. 0.]]]>
Ardından, bir grup ağda yineleme yapmak için tf.data.Dataset
kullanabilirsiniz:
dataset = tf.data.Dataset.from_tensor_slices(batch_of_networks)
for i, network in enumerate(dataset):
print(f"Batch element {i}: {network}")
tutucu74 l10n-yerBatch element 0: <Network shape=() work=[5. 3. 8.] bandwidth=[[0. 2. 0.] [2. 0. 3.] [0. 3. 0.]]> Batch element 1: <Network shape=() work=[3. 4. 2.] bandwidth=[[0. 2. 2.] [2. 0. 2.] [2. 2. 0.]]>
Ayrıca her toplu iş öğesine bir işlev uygulamak için map_fn
de kullanabilirsiniz:
def balance_work_greedy(network):
delta = (tf.expand_dims(network.work, -1) - tf.expand_dims(network.work, -2))
delta /= 4
delta = tf.maximum(tf.minimum(delta, network.bandwidth), -network.bandwidth)
new_work = network.work + tf.reduce_sum(delta, -1)
return Network(new_work, network.bandwidth)
tf.map_fn(balance_work_greedy, batch_of_networks)
tutucu76 l10n-yer<Network shape=(2,) work=[[5.5 1.25 9.25] [3. 4.75 1.25]] bandwidth=[[[0. 2. 0.] [2. 0. 3.] [0. 3. 0.]] [[0. 2. 2.] [2. 0. 2.] [2. 2. 0.]]]>
ExtensionTypes'ı destekleyen TensorFlow API'leri
@tf.fonksiyon
tf.function , TensorFlow kodunuzun performansını önemli ölçüde artırabilen Python işlevleri için TensorFlow grafiklerini önceden hesaplayan bir dekoratördür. Uzantı tipi değerleri, @tf.function
-decorated fonksiyonları ile şeffaf olarak kullanılabilir.
class Pastry(tf.experimental.ExtensionType):
sweetness: tf.Tensor # 2d embedding that encodes sweetness
chewiness: tf.Tensor # 2d embedding that encodes chewiness
@tf.function
def combine_pastry_features(x: Pastry):
return (x.sweetness + x.chewiness) / 2
cookie = Pastry(sweetness=[1.2, 0.4], chewiness=[0.8, 0.2])
combine_pastry_features(cookie)
tutucu78 l10n-yer<tf.Tensor: shape=(2,), dtype=float32, numpy=array([1. , 0.3], dtype=float32)>
input_signature
için tf.function
açıkça belirtmek istiyorsanız, uzantı türünün TypeSpec
kullanarak bunu yapabilirsiniz.
pastry_spec = Pastry.Spec(tf.TensorSpec([2]), tf.TensorSpec(2))
@tf.function(input_signature=[pastry_spec])
def increase_sweetness(x: Pastry, delta=1.0):
return Pastry(x.sweetness + delta, x.chewiness)
increase_sweetness(cookie)
tutucu80 l10n-yerPastry(sweetness=<tf.Tensor: shape=(2,), dtype=float32, numpy=array([2.2, 1.4], dtype=float32)>, chewiness=<tf.Tensor: shape=(2,), dtype=float32, numpy=array([0.8, 0.2], dtype=float32)>)
somut fonksiyonlar
Somut işlevler, tf.function
tarafından oluşturulan tek tek izlenen grafikleri kapsar. Uzatma türleri, somut işlevlerle şeffaf bir şekilde kullanılabilir.
cf = combine_pastry_features.get_concrete_function(pastry_spec)
cf(cookie)
tutucu82 l10n-yer<tf.Tensor: shape=(2,), dtype=float32, numpy=array([1. , 0.3], dtype=float32)>
Kontrol akışı işlemleri
Uzantı türleri, TensorFlow'un kontrol akışı işlemleri tarafından desteklenir:
# Example: using tf.cond to select between two MaskedTensors. Note that the
# two MaskedTensors don't need to have the same shape.
a = MaskedTensor([1., 2, 3], [True, False, True])
b = MaskedTensor([22., 33, 108, 55], [True, True, True, False])
condition = tf.constant(True)
print(tf.cond(condition, lambda: a, lambda: b))
<MaskedTensor [1.0, _, 3.0]>yer tutucu85 l10n-yer
# Example: using tf.while_loop with MaskedTensor.
cond = lambda i, _: i < 10
def body(i, mt):
return i + 1, mt.with_values(mt.values + 3 / 7)
print(tf.while_loop(cond, body, [0, b])[1])
<MaskedTensor [26.285717, 37.285698, 112.285736, _]>
İmza kontrol akışı
Uzantı türleri, tf.function içindeki (imza kullanılarak) kontrol akışı ifadeleri tarafından da desteklenir. Aşağıdaki örnekte, if
deyimi ve for
deyimleri, uzantı türlerini destekleyen tf.cond
ve tf.while_loop
işlemlerine otomatik olarak dönüştürülür.
@tf.function
def fn(x, b):
if b:
x = MaskedTensor(x, tf.less(x, 0))
else:
x = MaskedTensor(x, tf.greater(x, 0))
for i in tf.range(5 if b else 7):
x = x.with_values(x.values + 1 / 2)
return x
print(fn(tf.constant([1., -2, 3]), tf.constant(True)))
print(fn(tf.constant([1., -2, 3]), tf.constant(False)))
tutucu88 l10n-yer<MaskedTensor [_, 0.5, _]> <MaskedTensor [4.5, _, 6.5]>
Keras
tf.keras , derin öğrenme modelleri oluşturmak ve eğitmek için TensorFlow'un üst düzey API'sidir. Uzantı türleri bir Keras modeline girdi olarak geçirilebilir, Keras katmanları arasında geçirilebilir ve Keras modelleri tarafından döndürülebilir. Keras şu anda uzantı türlerine iki gereksinim getiriyor:
- Toplu hale getirilebilir olmalıdırlar (yukarıdaki "Toplu Uzantı Türleri" bölümüne bakın).
-
shape
adında bir alan veya özelliğe sahip olmalıdır.shape[0]
'in parti boyutu olduğu varsayılır.
Aşağıdaki iki alt bölümde, Keras ile uzantı türlerinin nasıl kullanılabileceğini gösteren örnekler verilmektedir.
Keras örneği: Network
İlk örnek için, düğümler arasında yük dengeleme çalışması için kullanılabilecek, yukarıdaki "Toplu Uzantı Türleri" bölümünde tanımlanan Network
sınıfını düşünün. Tanımı burada tekrarlanır:
class Network(tf.experimental.BatchableExtensionType):
shape: tf.TensorShape # batch shape. A single network has shape=[].
work: tf.Tensor # work[*shape, n] = work left to do at node n
bandwidth: tf.Tensor # bandwidth[*shape, n1, n2] = bandwidth from n1->n2
def __init__(self, work, bandwidth):
self.work = tf.convert_to_tensor(work)
self.bandwidth = tf.convert_to_tensor(bandwidth)
work_batch_shape = self.work.shape[:-1]
bandwidth_batch_shape = self.bandwidth.shape[:-2]
self.shape = work_batch_shape.merge_with(bandwidth_batch_shape)
def __repr__(self):
return network_repr(self)
tutucu90 l10n-yersingle_network = Network( # A single network w/ 4 nodes.
work=[8.0, 5, 12, 2],
bandwidth=[[0.0, 1, 2, 2], [1, 0, 0, 2], [2, 0, 0, 1], [2, 2, 1, 0]])
batch_of_networks = Network( # Batch of 2 networks, each w/ 2 nodes.
work=[[8.0, 5], [3, 2]],
bandwidth=[[[0.0, 1], [1, 0]], [[0, 2], [2, 0]]])
Network
leri işleyen yeni bir Keras katmanı tanımlayabilirsiniz.
class BalanceNetworkLayer(tf.keras.layers.Layer):
"""Layer that balances work between nodes in a network.
Shifts work from more busy nodes to less busy nodes, constrained by bandwidth.
"""
def call(self, inputs):
# This function is defined above, in "Batchable ExtensionTypes" section.
return balance_work_greedy(inputs)
Daha sonra basit bir model oluşturmak için bu katmanları kullanabilirsiniz. Bir ExtensionType
Türü'nü bir modele beslemek için, uzantı türünün TypeSpec
type_spec
ayarlanmış bir tf.keras.layer.Input
katmanı kullanabilirsiniz. Partileri işlemek için Keras modeli kullanılacaksa, type_spec
toplu iş boyutunu içermelidir.
input_spec = Network.Spec(shape=None,
work=tf.TensorSpec(None, tf.float32),
bandwidth=tf.TensorSpec(None, tf.float32))
model = tf.keras.Sequential([
tf.keras.layers.Input(type_spec=input_spec),
BalanceNetworkLayer(),
])
Son olarak, modeli tek bir ağa ve bir grup ağa uygulayabilirsiniz.
model(single_network)
<Network shape=() work=[ 9.25 5. 14. -1.25] bandwidth=[[0. 1. 2. 2.] [1. 0. 0. 2.] [2. 0. 0. 1.] [2. 2. 1. 0.]]>yer tutucu95 l10n-yer
model(batch_of_networks)
<Network shape=(2,) work=[[8.75 4.25] [3.25 1.75]] bandwidth=[[[0. 1.] [1. 0.]] [[0. 2.] [2. 0.]]]>
Keras örneği: MaskedTensor
Bu örnekte, MaskedTensor
Keras
şekilde genişletilmiştir. shape
, values
alanından hesaplanan bir özellik olarak tanımlanır. Keras, bu özelliği hem uzantı türüne hem de TypeSpec
eklemenizi gerektirir. MaskedTensor
ayrıca SavedModel
serileştirme için gerekli olacak bir __name__
değişkeni tanımlar (aşağıda).
class MaskedTensor(tf.experimental.BatchableExtensionType):
# __name__ is required for serialization in SavedModel; see below for details.
__name__ = 'extension_type_colab.MaskedTensor'
values: tf.Tensor
mask: tf.Tensor
shape = property(lambda self: self.values.shape)
dtype = property(lambda self: self.values.dtype)
def with_default(self, default):
return tf.where(self.mask, self.values, default)
def __repr__(self):
return masked_tensor_str(self.values, self.mask)
class Spec:
def __init__(self, shape, dtype=tf.float32):
self.values = tf.TensorSpec(shape, dtype)
self.mask = tf.TensorSpec(shape, tf.bool)
shape = property(lambda self: self.values.shape)
dtype = property(lambda self: self.values.dtype)
def with_shape(self):
return MaskedTensor.Spec(tf.TensorSpec(shape, self.values.dtype),
tf.TensorSpec(shape, self.mask.dtype))
Ardından, birkaç TensorFlow API'sinin varsayılan davranışını geçersiz kılmak için gönderme dekoratörleri kullanılır. Bu API'ler standart Keras katmanları ( Dense
katmanı gibi) tarafından kullanıldığından, bunları geçersiz kılmak, bu katmanları MaskedTensor
ile kullanmamıza izin verecektir. Bu örneğin amaçları doğrultusunda, maskeli tensörler için matmul
, maskelenmiş değerleri sıfır olarak ele almak (yani bunları ürüne dahil etmemek) için tanımlanmıştır.
@tf.experimental.dispatch_for_unary_elementwise_apis(MaskedTensor)
def unary_elementwise_op_handler(op, x):
return MaskedTensor(op(x.values), x.mask)
@tf.experimental.dispatch_for_binary_elementwise_apis(
Union[MaskedTensor, tf.Tensor],
Union[MaskedTensor, tf.Tensor])
def binary_elementwise_op_handler(op, x, y):
x = convert_to_masked_tensor(x)
y = convert_to_masked_tensor(y)
return MaskedTensor(op(x.values, y.values), x.mask & y.mask)
@tf.experimental.dispatch_for_api(tf.matmul)
def masked_matmul(a: MaskedTensor, b,
transpose_a=False, transpose_b=False,
adjoint_a=False, adjoint_b=False,
a_is_sparse=False, b_is_sparse=False,
output_type=None):
if isinstance(a, MaskedTensor):
a = a.with_default(0)
if isinstance(b, MaskedTensor):
b = b.with_default(0)
return tf.matmul(a, b, transpose_a, transpose_b, adjoint_a,
adjoint_b, a_is_sparse, b_is_sparse, output_type)
Ardından, standart Keras katmanlarını kullanarak MaskedTensor
girdilerini kabul eden bir Keras modeli oluşturabilirsiniz:
input_spec = MaskedTensor.Spec([None, 2], tf.float32)
masked_tensor_model = tf.keras.Sequential([
tf.keras.layers.Input(type_spec=input_spec),
tf.keras.layers.Dense(16, activation="relu"),
tf.keras.layers.Dense(1)])
masked_tensor_model.compile(loss='binary_crossentropy', optimizer='rmsprop')
a = MaskedTensor([[1., 2], [3, 4], [5, 6]],
[[True, False], [False, True], [True, True]])
masked_tensor_model.fit(a, tf.constant([[1], [0], [1]]), epochs=3)
print(masked_tensor_model(a))
-yer tutucu101 l10n-yerEpoch 1/3 1/1 [==============================] - 1s 955ms/step - loss: 10.2833 Epoch 2/3 1/1 [==============================] - 0s 5ms/step - loss: 10.2833 Epoch 3/3 1/1 [==============================] - 0s 5ms/step - loss: 10.2833 tf.Tensor( [[-0.09944128] [-0.7225147 ] [-1.3020657 ]], shape=(3, 1), dtype=float32)
Kayıtlı Model
SavedModel , hem ağırlıkları hem de hesaplamayı içeren serileştirilmiş bir TensorFlow programıdır. Bir Keras modelinden veya özel bir modelden oluşturulabilir. Her iki durumda da uzantı türleri, SavedModel tarafından tanımlanan işlevler ve yöntemlerle şeffaf bir şekilde kullanılabilir.
SavedModel, uzantı türleri bir __name__
alanına sahip olduğu sürece uzantı türlerini işleyen modelleri, katmanları ve işlevleri kaydedebilir. Bu ad, uzantı türünü kaydetmek için kullanılır, böylece model yüklendiğinde bulunabilir.
Örnek: bir Keras modelini kaydetme
Uzantı türlerini kullanan SavedModel
modelleri SavedModel kullanılarak kaydedilebilir.
masked_tensor_model_path = tempfile.mkdtemp()
tf.saved_model.save(masked_tensor_model, masked_tensor_model_path)
imported_model = tf.saved_model.load(masked_tensor_model_path)
imported_model(a)
tutucu103 l10n-yer2021-11-06 01:25:14.285250: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. WARNING:absl:Function `_wrapped_model` contains input name(s) args_0 with unsupported characters which will be renamed to args_0_1 in the SavedModel. INFO:tensorflow:Assets written to: /tmp/tmp3ceuupv9/assets INFO:tensorflow:Assets written to: /tmp/tmp3ceuupv9/assets <tf.Tensor: shape=(3, 1), dtype=float32, numpy= array([[-0.09944128], [-0.7225147 ], [-1.3020657 ]], dtype=float32)>
Örnek: özel bir modeli kaydetme
SavedModel, uzantı türlerini işleyen işlevlerle özel tf.Module
alt sınıflarını kaydetmek için de kullanılabilir.
class CustomModule(tf.Module):
def __init__(self, variable_value):
super().__init__()
self.v = tf.Variable(variable_value)
@tf.function
def grow(self, x: MaskedTensor):
"""Increase values in `x` by multiplying them by `self.v`."""
return MaskedTensor(x.values * self.v, x.mask)
module = CustomModule(100.0)
module.grow.get_concrete_function(MaskedTensor.Spec(shape=None,
dtype=tf.float32))
custom_module_path = tempfile.mkdtemp()
tf.saved_model.save(module, custom_module_path)
imported_model = tf.saved_model.load(custom_module_path)
imported_model.grow(MaskedTensor([1., 2, 3], [False, True, False]))
tutucu105 l10n-yerINFO:tensorflow:Assets written to: /tmp/tmp2x8zq5kb/assets INFO:tensorflow:Assets written to: /tmp/tmp2x8zq5kb/assets <MaskedTensor [_, 200.0, _]>
ExtensionType kullanılamadığında SavedModel yükleme
ExtensionType
kullanan ancak bu ExtensionType
mevcut olmayan (yani içe aktarılmamış) bir SavedModel
yüklerseniz, bir uyarı görürsünüz ve TensorFlow "anonim uzantı türü" nesnesini kullanmaya geri döner. Bu nesne, orijinal türle aynı alanlara sahip olacak, ancak tür için eklediğiniz özel yöntemler veya özellikler gibi başka özelleştirmelerden yoksun olacak.
TensorFlow sunumuyla ExtensionTypes'ı kullanma
Şu anda, TensorFlow hizmeti (ve SavedModel "imzalar" sözlüğünün diğer tüketicileri), tüm girdilerin ve çıktıların ham tensör olmasını gerektirir. Uzantı türlerini kullanan bir modelle TensorFlow hizmetini kullanmak istiyorsanız, uzantı türü değerlerini tensörlerden oluşturan veya ayrıştıran sarmalayıcı yöntemler ekleyebilirsiniz. Örneğin:
class CustomModuleWrapper(tf.Module):
def __init__(self, variable_value):
super().__init__()
self.v = tf.Variable(variable_value)
@tf.function
def var_weighted_mean(self, x: MaskedTensor):
"""Mean value of unmasked values in x, weighted by self.v."""
x = MaskedTensor(x.values * self.v, x.mask)
return (tf.reduce_sum(x.with_default(0)) /
tf.reduce_sum(tf.cast(x.mask, x.dtype)))
@tf.function()
def var_weighted_mean_wrapper(self, x_values, x_mask):
"""Raw tensor wrapper for var_weighted_mean."""
return self.var_weighted_mean(MaskedTensor(x_values, x_mask))
module = CustomModuleWrapper([3., 2., 8., 5.])
module.var_weighted_mean_wrapper.get_concrete_function(
tf.TensorSpec(None, tf.float32), tf.TensorSpec(None, tf.bool))
custom_module_path = tempfile.mkdtemp()
tf.saved_model.save(module, custom_module_path)
imported_model = tf.saved_model.load(custom_module_path)
x = MaskedTensor([1., 2., 3., 4.], [False, True, False, True])
imported_model.var_weighted_mean_wrapper(x.values, x.mask)
tutucu107 l10n-yerINFO:tensorflow:Assets written to: /tmp/tmpxhh4zh0i/assets INFO:tensorflow:Assets written to: /tmp/tmpxhh4zh0i/assets <tf.Tensor: shape=(), dtype=float32, numpy=12.0>
veri kümeleri
tf.data , basit, yeniden kullanılabilir parçalardan karmaşık girdi ardışık düzenleri oluşturmanıza olanak sağlayan bir API'dir. Temel veri yapısı, her öğenin bir veya daha fazla bileşenden oluştuğu bir dizi öğeyi temsil eden tf.data.Dataset
.
Uzantı türleriyle Veri Kümeleri Oluşturma
Veri kümeleri, Dataset.from_tensors
, Dataset.from_tensor_slices
veya Dataset.from_generator
kullanılarak uzantı türü değerlerinden oluşturulabilir:
ds = tf.data.Dataset.from_tensors(Pastry(5, 5))
iter(ds).next()
Pastry(sweetness=<tf.Tensor: shape=(), dtype=int32, numpy=5>, chewiness=<tf.Tensor: shape=(), dtype=int32, numpy=5>)
mt = MaskedTensor(tf.reshape(range(20), [5, 4]), tf.ones([5, 4]))
ds = tf.data.Dataset.from_tensor_slices(mt)
for value in ds:
print(value)
<MaskedTensor [0, 1, 2, 3]> <MaskedTensor [4, 5, 6, 7]> <MaskedTensor [8, 9, 10, 11]> <MaskedTensor [12, 13, 14, 15]> <MaskedTensor [16, 17, 18, 19]>
def value_gen():
for i in range(2, 7):
yield MaskedTensor(range(10), [j%i != 0 for j in range(10)])
ds = tf.data.Dataset.from_generator(
value_gen, output_signature=MaskedTensor.Spec(shape=[10], dtype=tf.int32))
for value in ds:
print(value)
<MaskedTensor [_, 1, _, 3, _, 5, _, 7, _, 9]> <MaskedTensor [_, 1, 2, _, 4, 5, _, 7, 8, _]> <MaskedTensor [_, 1, 2, 3, _, 5, 6, 7, _, 9]> <MaskedTensor [_, 1, 2, 3, 4, _, 6, 7, 8, 9]> <MaskedTensor [_, 1, 2, 3, 4, 5, _, 7, 8, 9]>
Uzantı türleriyle Veri Kümelerini toplu işleme ve toplulaştırmayı kaldırma
Uzantı türlerine sahip veri kümeleri, Dataset.batch
ve Dataset.unbatch
kullanılarak toplu ve toplu işlenmemiş olabilir.
batched_ds = ds.batch(2)
for value in batched_ds:
print(value)
<MaskedTensor [[_, 1, _, 3, _, 5, _, 7, _, 9], [_, 1, 2, _, 4, 5, _, 7, 8, _]]> <MaskedTensor [[_, 1, 2, 3, _, 5, 6, 7, _, 9], [_, 1, 2, 3, 4, _, 6, 7, 8, 9]]> <MaskedTensor [[_, 1, 2, 3, 4, 5, _, 7, 8, 9]]>yer tutucu116 l10n-yer
unbatched_ds = batched_ds.unbatch()
for value in unbatched_ds:
print(value)
<MaskedTensor [_, 1, _, 3, _, 5, _, 7, _, 9]> <MaskedTensor [_, 1, 2, _, 4, 5, _, 7, 8, _]> <MaskedTensor [_, 1, 2, 3, _, 5, 6, 7, _, 9]> <MaskedTensor [_, 1, 2, 3, 4, _, 6, 7, 8, 9]> <MaskedTensor [_, 1, 2, 3, 4, 5, _, 7, 8, 9]>