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, birshapeve genellikle birdtype; ve bunları Tensor işlemleriyle kullanmak mantıklıdır (tf.stack,tf.addveyatf.matmulgibi).MaskedTensorveCSRSparseMatrix, 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
ModelsveLayersiçin girdi ve çıktı olarak kullanılabilir. - tf.data.Dataset : Uzantı türleri
Datasetsdahil edilebilir ve veri kümesiIteratorstarafından döndürülebilir . - Tensorflow hub : Uzantı türleri
tf.hubmodülleri için giriş ve çıkış olarak kullanılabilir. - SavedModel : Uzantı türleri
SavedModelişlevleri için giriş ve çıkış olarak kullanılabilir. - tf.function : Uzantı türleri,
@tf.functiondekoratö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_loopiç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.condvetf.casekullanılarak koşullu olarak seçilebilir. - py_function : Uzantı türleri bağımsız değişkenler olarak kullanılabilir ve
funcbağımsız değişkeni içintf.py_functiondeğ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.gathervetf.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-yer
WARNING: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.TypeSpecile kodlanmıştır. - Dinamik bileşen (grafik her çalıştırıldığında değişebilen),
tf.Tensors 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_slicesunbatch -
tf.Keras(fit,evaluate,predictet ) -
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).
-
shapeadı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-yer
2021-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]>
TensorFlow.org'da görüntüleyin
Google Colab'da çalıştırın
Kaynağı GitHub'da görüntüleyin
Not defterini indir