সাহায্য Kaggle উপর TensorFlow সঙ্গে গ্রেট বেরিয়ার রিফ রক্ষা চ্যালেঞ্জ যোগদান

এক্সটেনশনের ধরন

TensorFlow.org এ দেখুন GitHub-এ উৎস দেখুননোটবুক ডাউনলোড করুন

সেটআপ

!pip install -q tf_nightly
import tensorflow as tf
import numpy as np
from typing import Tuple, List, Mapping, Union, Optional
import tempfile

এক্সটেনশন প্রকার

ব্যবহারকারী-সংজ্ঞায়িত প্রকারগুলি প্রকল্পগুলিকে আরও পাঠযোগ্য, মডুলার, রক্ষণাবেক্ষণযোগ্য করে তুলতে পারে। যাইহোক, বেশিরভাগ TensorFlow API-এর ব্যবহারকারী-সংজ্ঞায়িত পাইথন প্রকারের জন্য খুব সীমিত সমর্থন রয়েছে। এই (যেমন উভয় উচ্চ পর্যায়ের API গুলি অন্তর্ভুক্ত Keras , tf.function , tf.SavedModel এবং (যেমন নিম্ন স্তরের API গুলি) tf.while_loop এবং tf.concat )। TensorFlow কোনো প্রকারের এক্সটেনশন ব্যবহারকারী-সংজ্ঞায়িত অবজেক্ট ওরিয়েন্টেড ধরনের যে অঙ্গীভূতভাবে TensorFlow এর API গুলির মাধ্যমে কাজ তৈরি করতে ব্যবহার করা যেতে পারে। একটি এক্সটেনশন টাইপ তৈরি করতে হলে, কেবল সঙ্গে একটি পাইথন বর্গ সংজ্ঞায়িত tf.experimental.ExtensionType তার বেস হিসাবে, এবং ব্যবহার টাইপ টীকা প্রতিটি ক্ষেত্রের জন্য টাইপ নির্দিষ্ট করতে।

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 বেস বর্গ একইভাবে কাজ করে typing.NamedTuple এবং @dataclasses.dataclass মান পাইথন লাইব্রেরি থেকে। বিশেষ করে, এটি স্বয়ংক্রিয়ভাবে একটি কন্সট্রাকটর এবং (যেমন বিশেষ পদ্ধতি যোগ করা __repr__ এবং __eq__ ) ক্ষেত্র প্রকার টীকা উপর ভিত্তি করে।

সাধারণত, এক্সটেনশনের ধরন দুটি বিভাগের মধ্যে একটিতে পড়ে:

  • ডেটা স্ট্রাকচার, যা গ্রুপ একসঙ্গে সংশ্লিষ্ট মান একটি সংগ্রহ, এবং যারা মান উপর ভিত্তি করে দরকারী অপারেশন প্রদান করতে পারেন। ডেটা স্ট্রাকচার (যেমন মোটামুটি সাধারণ হতে পারে TensorGraph উপরোক্ত উদাহরণে); অথবা তারা একটি নির্দিষ্ট মডেল অত্যন্ত কাস্টমাইজ করা হতে পারে.

  • ধরনের, যা বিশেষজ্ঞ বা ধারণা প্রসারিত টেন্সর-মত "টেন্সর।" এই বিষয়শ্রেণীতে অন্তর্ভুক্ত প্রকারভেদ একটি আছে rank , একটি shape , এবং সাধারণত একটি dtype ; এবং এটা তাদের টেন্সর অপারেশন (যেমন সঙ্গে ব্যবহার করার জন্য জ্ঞান করে তোলে tf.stack , tf.add , অথবা tf.matmul )। MaskedTensor এবং CSRSparseMatrix টেন্সর মত ধরনের উদাহরণ।

সমর্থিত API

এক্সটেনশন প্রকারগুলি নিম্নলিখিত TensorFlow API দ্বারা সমর্থিত:

  • Keras: কোনো প্রকারের এক্সটেনশন ইনপুট এবং Keras জন্য আউটপুট হিসাবে ব্যবহার করা যেতে পারে Models এবং Layers
  • tf.data.Dataset: কোনো প্রকারের এক্সটেনশন অন্তর্ভুক্ত করা যেতে পারে Datasets , এবং ডেটা সেটটি দ্বারা ফিরে Iterators
  • Tensorflow হাব: কোনো প্রকারের এক্সটেনশন ইনপুট এবং জন্য আউটপুট হিসাবে ব্যবহার করা যেতে পারে tf.hub মডিউল।
  • SavedModel: কোনো প্রকারের এক্সটেনশন ইনপুট এবং জন্য আউটপুট হিসাবে ব্যবহার করা যেতে পারে SavedModel ফাংশন।
  • tf.function: কোনো প্রকারের এক্সটেনশন আর্গুমেন্ট এবং আবৃত ফাংশন বিনিময়ে মান হিসাবে ব্যবহার করা যেতে পারে @tf.function প্রসাধক।
  • যখন loops: এক্সটেনশান ধরনের লুপ ভেরিয়েবল হিসেবে ব্যবহার করা যাবে tf.while_loop , এবং আর্গুমেন্ট এবং যখন লুপ লাশ বিনিময়ে মান হিসাবে ব্যবহার করা যাবে।
  • কন্ডিশন: কোনো প্রকারের এক্সটেনশন শর্তসাপেক্ষে ব্যবহার নির্বাচন করা যাবে tf.cond এবং tf.case
  • py_function: কোনো প্রকারের এক্সটেনশন আর্গুমেন্ট এবং বিনিময়ে মান হিসাবে ব্যবহার করা যেতে পারে func আর্গুমেন্ট প্রাপ্ত করতে tf.py_function
  • টেন্সর অপস: কোনো প্রকারের এক্সটেনশন সবচেয়ে TensorFlow অপস যে টেন্সর ইনপুট (যেমন, গ্রহণ সমর্থন করার জন্য বাড়ানো যেতে পারে tf.matmul , tf.gather এবং tf.reduce_sum )। আরও তথ্যের জন্য নীচের "ডিসপ্যাচ" বিভাগে দেখুন।
  • বন্টন কৌশল: কোনো প্রকারের এক্সটেনশন প্রতি প্রতিরূপ মান হিসাবে ব্যবহার করা যাবে।

আরও বিশদ বিবরণের জন্য, নীচে "TensorFlow APIs যেটি ExtensionTypes সমর্থন করে" বিভাগটি দেখুন।

প্রয়োজনীয়তা

ক্ষেত্র প্রকার

সমস্ত ক্ষেত্র (ওরফে ইনস্ট্যান্স ভেরিয়েবল) অবশ্যই ঘোষণা করতে হবে এবং প্রতিটি ক্ষেত্রের জন্য একটি টাইপ টীকা প্রদান করতে হবে। নিম্নলিখিত ধরনের টীকা সমর্থিত:

টাইপ উদাহরণ
পাইথন পূর্ণসংখ্যা i: int
পাইথন ভাসছে f: float
পাইথন স্ট্রিং s: str
পাইথন বুলিয়ানস b: bool
পাইথন কোনটি নয় n: None
টেনসর আকার shape: tf.TensorShape
টেনসর dtypes dtype: tf.DType
টেনসর t: tf.Tensor
এক্সটেনশন প্রকার mt: MyMaskedTensor
রাগড টেনসর rt: tf.RaggedTensor
স্পারস টেনসর st: tf.SparseTensor
সূচীকৃত স্লাইস s: tf.IndexedSlices
ঐচ্ছিক টেনসর o: tf.experimental.Optional
টাইপ ইউনিয়ন int_or_float: typing.Union[int, float]
টিপলস params: typing.Tuple[int, float, tf.Tensor, int]
ভার-দৈর্ঘ্যের টিপল lengths: typing.Tuple[int, ...]
ম্যাপিং tags: typing.Mapping[str, tf.Tensor]
ঐচ্ছিক মান weight: typing.Optional[tf.Tensor]

পরিবর্তনশীলতা

এক্সটেনশনের ধরন অপরিবর্তনীয় হতে হবে। এটি নিশ্চিত করে যে টেনসরফ্লো-এর গ্রাফ-ট্রেসিং প্রক্রিয়ার দ্বারা সঠিকভাবে ট্র্যাক করা যেতে পারে। আপনি যদি নিজেকে একটি এক্সটেনশন টাইপ মান পরিবর্তন করতে চান তবে মানগুলিকে রূপান্তরিত করে এমন পদ্ধতিগুলিকে সংজ্ঞায়িত করার পরিবর্তে বিবেচনা করুন৷ উদাহরণস্বরূপ, বরং একটি সংজ্ঞা চেয়ে set_mask পদ্ধতি পরিবর্তন ঘটান করতে MaskedTensor , আপনি একটি সংজ্ঞায়িত করতে পারে replace_mask পদ্ধতি যা আয় একটি নতুন MaskedTensor :

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

ExtensionType বেস বর্গ নিম্নলিখিত কার্যকারিতা প্রদান করে:

  • একজন কন্সট্রাক্টর ( __init__ )।
  • একটি মুদ্রণযোগ্য উপস্থাপনা পদ্ধতি ( __repr__ )।
  • সমতা ও বৈষম্য অপারেটার ( __eq__ )।
  • একজন বৈধতা পদ্ধতি ( __validate__ )।
  • অপরিবর্তনীয়তা প্রয়োগ করা হয়েছে।
  • একটি নেস্টেড TypeSpec
  • টেনসর API প্রেরণ সমর্থন।

এই কার্যকারিতা কাস্টমাইজ করার বিষয়ে আরও তথ্যের জন্য নীচের "কাস্টমাইজিং এক্সটেনশন টাইপস" বিভাগটি দেখুন৷

কনস্ট্রাক্টর

কন্সট্রাকটর দ্বারা যোগ ExtensionType একটি নামাঙ্কিত আর্গুমেন্ট হিসাবে প্রতিটি ক্ষেত্রের (অনুক্রমে তারা বর্গ সংজ্ঞা তালিকাভুক্ত হয়েছে) লাগে। এই কনস্ট্রাক্টর প্রতিটি প্যারামিটার টাইপ-চেক করবে এবং প্রয়োজনে সেগুলিকে রূপান্তর করবে। বিশেষ করে, Tensor ক্ষেত্র ব্যবহার রূপান্তরিত হয় tf.convert_to_tensor ; Tuple ক্ষেত্র রূপান্তরিত হয় tuple ; s এবং Mapping ক্ষেত্র অপরিবর্তনীয় dicts রূপান্তরিত করা হয়।

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)
tf.Tensor(
[[1 2 3]
 [4 5 6]], shape=(2, 3), dtype=int32)

কন্সট্রাকটর একটি উত্থাপন TypeError একটি ক্ষেত্র মান তার ঘোষিত ধরনের রূপান্তর করা যাবে না যদি:

try:
  MaskedTensor([1, 2, 3], None)
except TypeError as e:
  print(f"Got expected TypeError: {e}")
Got expected TypeError: mask: expected a Tensor, got None

একটি ক্ষেত্রের জন্য ডিফল্ট মান শ্রেণি স্তরে তার মান সেট করে নির্দিষ্ট করা যেতে পারে:

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>)
Pencil(length=0.5, color="blue")
Pencil(color='blue', has_erasor=True, length=<tf.Tensor: shape=(), dtype=float32, numpy=0.5>)

মুদ্রণযোগ্য উপস্থাপনা

ExtensionType একটি ডিফল্ট মুদ্রণযোগ্য উপস্থাপনা পদ্ধতি (যোগ করা __repr__ ) বর্গ নাম এবং প্রতিটি ক্ষেত্রের জন্য মান অন্তর্ভুক্ত যে:

print(MaskedTensor(values=[1, 2, 3], mask=[True, True, False]))
MaskedTensor(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])>)

সমতা অপারেটর

ExtensionType ডিফল্ট সমতা অপারেটার (যোগ করা __eq__ এবং __ne__ ) যে বিবেচনা যদি তারা একই ধরনের আছে এবং তাদের সব ক্ষেত্র সমান দুটি মানের সমান। টেনসর ক্ষেত্র সমান হিসাবে বিবেচিত হয় যদি তাদের আকৃতি একই থাকে এবং সমস্ত উপাদানের জন্য উপাদান অনুসারে সমান হয়।

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}")
a == a: True
a == b: False
a == a.values: False

বৈধতা পদ্ধতি

ExtensionType একটি যোগ __validate__ পদ্ধতি, যা মাঠে বৈধতা চেক সঞ্চালন ওভাররাইড করা যেতে পারে। কনস্ট্রাক্টরকে কল করার পরে এবং ক্ষেত্রগুলি টাইপ-চেক করার পরে এবং তাদের ঘোষিত প্রকারগুলিতে রূপান্তরিত হওয়ার পরে এটি চালানো হয়, তাই এটি ধরে নেওয়া যেতে পারে যে সমস্ত ক্ষেত্রে তাদের ঘোষিত প্রকার রয়েছে।

তিনি দৃষ্টান্ত অনুসরণ আপডেট MaskedTensor যাচাই করতে shape s এবং dtype তার ক্ষেত্র S:

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

অপরিবর্তনীয়তা প্রয়োগ করা হয়েছে

ExtensionType অগ্রাহ্য __setattr__ এবং __delattr__ পদ্ধতি পরিবর্তন রোধ করার জন্য, যা সুনিশ্চিত করে যে এক্সটেনশন টাইপ মান অপরিবর্তনীয় হয়।

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.

নেস্টেড টাইপস্পেক

প্রতিটি ExtensionType বর্গ একটি সংশ্লিষ্ট হয়েছে TypeSpec বর্গ, যা স্বয়ংক্রিয়ভাবে তৈরি এবং সংরক্ষণ করা হয় <extension_type_name>.Spec

এই শ্রেণীর কোনো নেস্টেড tensors মান ছাড়া একটি মান থেকে সব তথ্য ধারন করে না। বিশেষ করে, TypeSpec একটি মান তার সঙ্গে কোনো নেস্টেড টেন্সর, ExtensionType, অথবা CompositeTensor প্রতিস্থাপন দ্বারা তৈরি করা হয় TypeSpec

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.
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 মান স্পষ্টভাবে নির্মাণ করা যেতে পারে অথবা তারা একটি থেকে নির্মিত হতে পারে ExtensionType ব্যবহার মান tf.type_spec_from_value :

spec1 = Player.Spec(name=tf.TensorSpec([], tf.float32), attributes={})
spec2 = tf.type_spec_from_value(anne)

TypeSpec গুলি একটি স্ট্যাটিক উপাদান এবং একটি গতিশীল উপাদান বিভক্ত মান TensorFlow দ্বারা ব্যবহৃত হয়:

  • স্ট্যাটিক উপাদান (যা গ্রাফ নির্মাণাধীন সময়ে সংশোধন করা হয়েছে) একটি দিয়ে এনকোড করা আছে tf.TypeSpec
  • গতিশীল উপাদান (যা প্রতিটি সময় গ্রাফ চালানো হয় বিভিন্ন রকমের হতে পারে) এর একটি তালিকা হিসাবে এনকোডেড হয়েছে tf.Tensor গুলি।

উদাহরণস্বরূপ, tf.function retraces তার আবৃত ফাংশন যখনই একটি আর্গুমেন্ট পূর্বে অদেখা হয়েছে TypeSpec :

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

আরো তথ্যের জন্য, দেখুন tf.function গাইড

এক্সটেনশন প্রকার কাস্টমাইজ করা

কেবলমাত্র ক্ষেত্র এবং তাদের প্রকারগুলি ঘোষণা করার পাশাপাশি, এক্সটেনশন প্রকারগুলি হতে পারে:

  • ডিফল্ট মুদ্রণযোগ্য উপস্থাপনা (ওভাররাইড __repr__ )।
  • পদ্ধতির সংজ্ঞা দাও।
  • শ্রেণিপদ্ধতি এবং স্ট্যাটিক পদ্ধতির সংজ্ঞা দাও।
  • বৈশিষ্ট্য সংজ্ঞায়িত করুন।
  • ডিফল্ট কন্সট্রাক্টর (ওভাররাইড __init__ )।
  • ডিফল্ট সমতা অপারেটর (ওভাররাইড __eq__ )।
  • (যেমন অপারেটার নির্ধারণ __add__ এবং __lt__ )।
  • ক্ষেত্রগুলির জন্য ডিফল্ট মান ঘোষণা করুন।
  • উপশ্রেণীর সংজ্ঞা দাও।

ডিফল্ট মুদ্রণযোগ্য উপস্থাপনা ওভাররাইড করা হচ্ছে

আপনি এক্সটেনশন প্রকারের জন্য এই ডিফল্ট স্ট্রিং রূপান্তর অপারেটর ওভাররাইড করতে পারেন। নিম্নলিখিত উদাহরণে আপডেট MaskedTensor একটি আরো ভালো পঠনযোগ্য স্ট্রিং উপস্থাপনা জেনারেট করতে যখন মান উৎসুক মোডে ছাপা হয় বর্গ।

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)
<MaskedTensor [[1, 2, _], [4, _, 6]]>

সংজ্ঞায়িত পদ্ধতি

এক্সটেনশন প্রকারগুলি পদ্ধতিগুলি সংজ্ঞায়িত করতে পারে, ঠিক যে কোনও সাধারণ পাইথন ক্লাসের মতো। উদাহরণস্বরূপ, MaskedTensor ধরনের একটি সংজ্ঞায়িত করতে পারে with_default পদ্ধতি যা আয় একটি কপি self ছদ্মবেশী মান একটি প্রদত্ত দ্বারা প্রতিস্থাপিত default মান। পদ্ধতি ঐচ্ছিকরূপে টীকা দেওয়া থাকতে পারে @tf.function প্রসাধক।

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)
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 0, 3], dtype=int32)>

ক্লাস পদ্ধতি এবং স্ট্যাটিক পদ্ধতি সংজ্ঞায়িত করা

কোনো প্রকারের এক্সটেনশন ব্যবহার পদ্ধতি নির্ধারণ করিতে পারিবে @classmethod এবং @staticmethod টেকনিক। উদাহরণস্বরূপ, MaskedTensor টাইপ একটি কারখানা পদ্ধতি নির্ধারণ করতে পারে যে মুখোশ একটি প্রদত্ত মান কোনো উপাদান:

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)
<MaskedTensor [[_, 0, _], [_, 0, 0]]>

বৈশিষ্ট্য সংজ্ঞায়িত করা

কোনো প্রকারের এক্সটেনশন ব্যবহার করে বৈশিষ্ট্যের সংজ্ঞায়িত পারে @property প্রসাধক, যেকোন স্বাভাবিক পাইথন বর্গ মত। উদাহরণস্বরূপ, MaskedTensor ধরনের একটি সংজ্ঞায়িত করতে পারে dtype সম্পত্তি মূল্যবোধের dtype জন্য একটি সাঁটে লেখার যে:

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
tf.int32

ডিফল্ট কনস্ট্রাক্টরকে ওভাররাইড করা হচ্ছে

আপনি এক্সটেনশন প্রকারের জন্য ডিফল্ট কনস্ট্রাক্টর ওভাররাইড করতে পারেন। কাস্টম কনস্ট্রাক্টরদের অবশ্যই প্রতিটি ঘোষিত ক্ষেত্রের জন্য একটি মান সেট করতে হবে; এবং কাস্টম কনস্ট্রাক্টর ফিরে আসার পরে, সমস্ত ক্ষেত্র টাইপ-চেক করা হবে, এবং মান উপরে বর্ণিত হিসাবে রূপান্তরিত হবে।

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!
Toy(name='ball', price=<tf.Tensor: shape=(), dtype=float32, numpy=4.0>)

বিকল্পভাবে, আপনি ডিফল্ট কনস্ট্রাক্টরটিকে যেমন আছে-এভাবে ছেড়ে দেওয়ার কথা বিবেচনা করতে পারেন, তবে এক বা একাধিক কারখানার পদ্ধতি যোগ করতে পারেন। যেমন:

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))
Toy(name='ball', price=<tf.Tensor: shape=(), dtype=float32, numpy=4.0>)

ডিফল্ট সমতা অপারেটর ওভাররাইডিং ( __eq__ )

আপনি ডিফল্ট ওভাররাইড করতে পারে __eq__ এক্সটেনশন ধরনের জন্য অপারেটর। ফলো উদাহরণ আপডেট MaskedTensor যখন সমতার জন্য তুলনা ছদ্মবেশী উপাদানের উপেক্ষা করার।

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)
tf.Tensor(True, shape=(), dtype=bool)

ফরোয়ার্ড রেফারেন্স ব্যবহার করে

যদি একটি ক্ষেত্রের ধরন এখনও সংজ্ঞায়িত করা না হয়, তাহলে আপনি পরিবর্তে টাইপের নাম ধারণকারী একটি স্ট্রিং ব্যবহার করতে পারেন। নিম্নলিখিত উদাহরণে, স্ট্রিং "Node" টীকা করতে ব্যবহৃত হয় children ক্ষেত্র কারণ Node টাইপ হয়েছে না (পুরোপুরি) এখনও সংজ্ঞায়িত।

class Node(tf.experimental.ExtensionType):
  value: tf.Tensor
  children: Tuple["Node", ...] = ()

Node(3, [Node(5), Node(2)])
Node(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=())))

সাবক্লাস সংজ্ঞায়িত করা

স্ট্যান্ডার্ড পাইথন সিনট্যাক্স ব্যবহার করে এক্সটেনশনের ধরনগুলি সাবক্লাস করা যেতে পারে। এক্সটেনশন টাইপ সাবক্লাস নতুন ক্ষেত্র, পদ্ধতি, এবং বৈশিষ্ট্য যোগ করতে পারে; এবং কনস্ট্রাক্টর, মুদ্রণযোগ্য উপস্থাপনা এবং সমতা অপারেটরকে ওভাররাইড করতে পারে। নিম্নলিখিত উদাহরণে মৌলিক সংজ্ঞায়িত TensorGraph বর্গ ব্যবহারসমূহ তিনটে ম্যাচ যা Tensor ক্ষেত্র নোডের মধ্যে প্রান্ত একটি সেট সঙ্কেতাক্ষরে লিখা। এটা তোলে তারপর একটি উপশ্রেণী করে একটি যোগ সংজ্ঞায়িত Tensor প্রতিটি নোডের জন্য একটি "বৈশিষ্ট্য মান" রেকর্ড করতে ক্ষেত্র। উপশ্রেণীটি প্রান্ত বরাবর বৈশিষ্ট্যের মানগুলি প্রচার করার একটি পদ্ধতিও সংজ্ঞায়িত করে।

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

ব্যক্তিগত ক্ষেত্র সংজ্ঞায়িত করা

একটি এক্সটেনশন প্রকারের ক্ষেত্রগুলিকে একটি আন্ডারস্কোর (স্ট্যান্ডার্ড পাইথন নিয়ম অনুসরণ করে) দিয়ে প্রিফিক্স করে ব্যক্তিগত চিহ্নিত করা যেতে পারে। এটি টেনসরফ্লো যেভাবে ক্ষেত্রগুলির সাথে আচরণ করে তা প্রভাবিত করে না; কিন্তু এক্সটেনশন টাইপের যেকোন ব্যবহারকারীর কাছে সহজভাবে একটি সংকেত হিসাবে কাজ করে যে সেই ক্ষেত্রগুলি ব্যক্তিগত।

ExtensionType এর কাস্টমাইজ TypeSpec

প্রতিটি ExtensionType বর্গ একটি সংশ্লিষ্ট হয়েছে TypeSpec বর্গ, যা স্বয়ংক্রিয়ভাবে তৈরি এবং সংরক্ষণ করা হয় <extension_type_name>.Spec । আরও তথ্যের জন্য, উপরের "নেস্টেড টাইপস্পেক" বিভাগটি দেখুন।

কাস্টমাইজ করতে TypeSpec , কেবল আপনার নিজের নেস্টেড বর্গ নামে সংজ্ঞায়িত Spec , এবং ExtensionType যে ব্যবহার করবে স্বয়ংক্রিয়ভাবে নির্মাণ জন্য ভিত্তি হিসেবে TypeSpec । আপনি কাস্টমাইজ করতে পারেন Spec বর্গ দ্বারা:

  • ডিফল্ট মুদ্রণযোগ্য উপস্থাপনা ওভাররাইড করা হচ্ছে।
  • ডিফল্ট কনস্ট্রাক্টরকে ওভাররাইড করা হচ্ছে।
  • পদ্ধতি, শ্রেণিপদ্ধতি, স্ট্যাটিক পদ্ধতি এবং বৈশিষ্ট্য সংজ্ঞায়িত করা।

নিম্নলিখিত উদাহরণে কাস্টমাইজ করে MaskedTensor.Spec সহজে ব্যবহার করতে করতে শ্রেণী:

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)

টেনসর API প্রেরণ

কোনো প্রকারের এক্সটেনশন, "টেন্সর-মত" হতে পারে এই অর্থে যে তারা বিশেষজ্ঞ বা ইন্টারফেস দ্বারা সংজ্ঞায়িত প্রসারিত মধ্যে tf.Tensor প্রকার। টেন্সর মত কোনো প্রকারের এক্সটেনশন উদাহরণ অন্তর্ভুক্ত RaggedTensor , SparseTensor এবং MaskedTensorডিসপ্যাচ টেকনিক যখন টেন্সর মত কোনো প্রকারের এক্সটেনশন প্রয়োগ TensorFlow অপারেশনের ডিফল্ট আচরণ ওভাররাইড করার জন্য ব্যবহার করা যেতে পারে। TensorFlow বর্তমানে তিনটি প্রেরণ ডেকোরেটর সংজ্ঞায়িত করে:

একটি একক API-এর জন্য প্রেরণ

tf.experimental.dispatch_for_api প্রসাধক একটি নির্দিষ্ট TensorFlow অপারেশন ডিফল্ট আচরণ যখন এটি উল্লিখিত স্বাক্ষর সহ বলা হয় ওভাররাইড করে। উদাহরণস্বরূপ, যদি আপনি কিভাবে নির্দিষ্ট করতে এই প্রসাধক ব্যবহার করতে পারেন tf.stack প্রক্রিয়া উচিত MaskedTensor মান:

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

এই জন্য ডিফল্ট বাস্তবায়ন অগ্রাহ্য tf.stack যখনই এটি একটি তালিকা সঙ্গে বলা হয় MaskedTensor মান (যেহেতু values আর্গুমেন্ট সহ সটীক হয় typing.List[MaskedTensor] ):

x = MaskedTensor([1, 2, 3], [True, True, False])
y = MaskedTensor([4, 5, 6], [False, True, True])
tf.stack([x, y])
<MaskedTensor [[1, 2, _], [_, 5, 6]]>

অনুমতি দিতে tf.stack মিশ্র তালিকা হ্যান্ডেল করতে MaskedTensor এবং Tensor মান, আপনার জন্য টাইপ টীকা পরিমার্জন করতে পারেন values পরামিতি এবং ফাংশন উপযুক্তভাবে লাশ আপডেট করুন:

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])
<MaskedTensor [[1, 2, _], [4, 5, 6], [1, 2, _]]>

যে ওভাররাইড করা যেতে পারে API গুলি একটি তালিকার জন্য, জন্য API ডকুমেন্টেশান দেখুন tf.experimental.dispatch_for_api

সমস্ত unary elementwise API-এর জন্য প্রেরণ করুন

tf.experimental.dispatch_for_unary_elementwise_apis প্রসাধক ওভাররাইড সব ইউনারী elementwise অপস (যেমন ডিফল্ট ব্যবহারকে tf.math.cos ) যখনই প্রথম আর্গুমেন্ট (সাধারণত নামে জন্য মান x ) টাইপ টীকা সাথে মেলে x_type । সজ্জিত ফাংশন দুটি আর্গুমেন্ট নিতে হবে:

  • api_func : একটি ফাংশন যা একটি একক পরামিতি এবং সঞ্চালিত elementwise অপারেশন (যেমন, লাগে tf.abs )।
  • x : elementwise অপারেশন প্রথম যুক্তি।

নিম্নলিখিত উদাহরণে আপডেট সব ইউনারী elementwise অপারেশন পরিচালনা করতে MaskedTensor টাইপ:

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

এই ফাংশনটি এখন ব্যবহৃত হবে যখনই একটা ইউনারী elementwise অপারেশন উপর বলা হয় হতে হবে MaskedTensor

x = MaskedTensor([1, -2, -3], [True, False, True])
 print(tf.abs(x))
<MaskedTensor [1, _, 3]>
print(tf.ones_like(x, dtype=tf.float32))
<MaskedTensor [1.0, _, 1.0]>

বাইনারি সব elementwise API-এর জন্য প্রেরণ করুন

একইভাবে, tf.experimental.dispatch_for_binary_elementwise_apis সব বাইনারি elementwise অপারেশন পরিচালনা করতে আপডেট করার জন্য ব্যবহার করা যেতে পারে MaskedTensor টাইপ:

@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)
<MaskedTensor [[5, _, 1], [_, _, _]]>

Elementwise API গুলি ওভাররাইড করছে একটি তালিকার জন্য, জন্য API ডকুমেন্টেশান দেখুন tf.experimental.dispatch_for_unary_elementwise_apis এবং tf.experimental.dispatch_for_binary_elementwise_apis

ব্যাচযোগ্য এক্সটেনশন প্রকার

একটি ExtensionType batchable যদি একটি একক উদাহরণস্বরূপ মান একটি ব্যাচ প্রতিনিধিত্ব করতে ব্যবহার করা যেতে পারে। সাধারণত, এই সব নেস্টেড করার ব্যাচ মাত্রা যোগ দ্বারা সম্পন্ন হয় Tensor গুলি। নিম্নলিখিত টেনসরফ্লো এপিআইগুলির প্রয়োজন যে কোনও এক্সটেনশন প্রকারের ইনপুট ব্যাচযোগ্য হতে হবে:

ডিফল্টরূপে, BatchableExtensionType কোনো নেস্টেড Batching দ্বারা শ্রেণীবদ্ধ মান সৃষ্টি Tensor এস, CompositeTensor s, এবং ExtensionType গুলি। যদি এটি আপনার ক্লাসের জন্য উপযুক্ত নয়, তাহলে আপনি ব্যবহার করতে হবে tf.experimental.ExtensionTypeBatchEncoder এই ডিফল্ট আচরণ ওভাররাইড করতে। উদাহরণস্বরূপ, এটি একটি ব্যাচ তৈরি করতে উপযুক্ত হবে না tf.SparseTensor কেবল পৃথক বিক্ষিপ্ত tensors 'সারিবদ্ধ দ্বারা মান values , indices এবং dense_shape ক্ষেত্র - বেশিরভাগ ক্ষেত্রেই, এইসব tensors গাদা করতে পারে না, যেহেতু তারা বেমানান আকার আছে ; এবং এমনকি আপনি করতে পারে যদি, ফলে কোন বৈধ হবে না SparseTensor

ব্যাচযোগ্য এক্সটেনশন টাইপ উদাহরণ: নেটওয়ার্ক

উদাহরণস্বরূপ, একটি সহজ বিবেচনা Network ভারসাম্য জন্য ব্যবহৃত বর্গ, যা ট্র্যাক কত কাজ প্রতিটি নোডের এ কিছু করার বাকি, এবং কত ব্যান্ডউইথ নোডের মধ্যে কাজ সরাতে পাওয়া যায়:

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

এই ধরনের batchable করতে, বেস টাইপ পরিবর্তন BatchableExtensionType , এবং প্রতিটি ক্ষেত্রের আকৃতি সমন্বয় ঐচ্ছিক ব্যাচ মাত্রা অন্তর্ভুক্ত করা। নিম্নলিখিত উদাহরণে একটি যোগ shape ব্যাচ আকৃতি keept ট্র্যাকের ক্ষেত্র। এই shape ক্ষেত্র দ্বারা প্রয়োজন হয় না tf.data.Dataset বা tf.map_fn , কিন্তু এটা দ্বারা প্রয়োজন বোধ করা হয় tf.Keras

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}")
net1=<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.]]]>

এর পরে আপনি ব্যবহার করতে পারেন tf.data.Dataset নেটওয়ার্ক একটি ব্যাচ মাধ্যমে পুনরুক্তি করতে:

dataset = tf.data.Dataset.from_tensor_slices(batch_of_networks)
for i, network in enumerate(dataset):
  print(f"Batch element {i}: {network}")
Batch 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.]]>

এবং আপনি ব্যবহার করতে পারেন map_fn প্রতিটি ব্যাচ উপাদানে একটি ফাংশন প্রয়োগ করতে:

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

টেনসরফ্লো এপিআই যা এক্সটেনশন টাইপ সমর্থন করে

@tf.function

tf.function একটি প্রসাধক যে পাইথন ফাংশন, যা যথেষ্ট আপনার TensorFlow কোডের পারফরম্যান্সের উন্নতি করতে precomputes TensorFlow গ্রাফ। এক্সটেনশন টাইপ মান স্বচ্ছভাবে সাথে ব্যবহার করা যাবে @tf.function -decorated ফাংশন।

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)
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([1. , 0.3], dtype=float32)>

আপনি স্পষ্টভাবে উল্লেখ করতে চান input_signature জন্য tf.function , তাহলে আপনি তাই এক্সটেনশন টাইপ এর ব্যবহার করতে পারবেন TypeSpec

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

কংক্রিট ফাংশন

কংক্রিট ফাংশন পৃথক আঁকা গ্রাফ যে আগে থেকেই রয়েছে encapsulate tf.function । এক্সটেনশন প্রকারগুলি কংক্রিট ফাংশনগুলির সাথে স্বচ্ছভাবে ব্যবহার করা যেতে পারে।

cf = combine_pastry_features.get_concrete_function(pastry_spec)
cf(cookie)
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([1. , 0.3], dtype=float32)>

নিয়ন্ত্রণ প্রবাহ অপারেশন

এক্সটেনশন প্রকারগুলি TensorFlow-এর কন্ট্রোল-ফ্লো অপারেশন দ্বারা সমর্থিত:

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

অটোগ্রাফ নিয়ন্ত্রণ প্রবাহ

এক্সটেনশন প্রকারগুলি tf.function-এ (অটোগ্রাফ ব্যবহার করে) নিয়ন্ত্রণ প্রবাহ বিবৃতি দ্বারা সমর্থিত। নিম্নলিখিত উদাহরণে, if বিবৃতি এবং for বিবৃতি স্বয়ংক্রিয়ভাবে রূপান্তরিত হয় tf.cond এবং tf.while_loop অপারেশন, যা সমর্থন কোনো প্রকারের এক্সটেনশন।

@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)))
<MaskedTensor [_, 0.5, _]>
<MaskedTensor [4.5, _, 6.5]>

কেরাস

tf.keras বিল্ডিং এবং গভীর লার্নিং মডেলগুলির প্রশিক্ষণ জন্য TensorFlow এর উচ্চ পর্যায়ের এপিআই হয়। এক্সটেনশনের ধরনগুলি কেরাস মডেলে ইনপুট হিসাবে পাস করা যেতে পারে, কেরাস স্তরগুলির মধ্যে পাস করা যেতে পারে এবং কেরাস মডেল দ্বারা ফেরত দেওয়া হতে পারে। কেরাস বর্তমানে এক্সটেনশন প্রকারের জন্য দুটি প্রয়োজনীয়তা রাখে:

  • এগুলি অবশ্যই ব্যাচযোগ্য হতে হবে (উপরে "ব্যাচযোগ্য এক্সটেনশন টাইপস" দেখুন)।
  • একটি ক্ষেত্র বা সম্পত্তি নামে থাকতে হবে shapeshape[0] ব্যাচ মাত্রা হতে অধিকৃত হয়।

নিচের দুটি উপবিভাগ উদাহরণ দেয় যে কিভাবে এক্সটেনশনের ধরন কেরাসের সাথে ব্যবহার করা যেতে পারে।

Keras উদাহরণ: Network

প্রথম উদাহরণস্বরূপ, বিবেচনা Network বর্গ উপরের "Batchable ExtensionTypes" বিভাগে সংজ্ঞায়িত, যা লোড নোড মধ্যে কাজ মিট জন্য ব্যবহার করা যাবে। এর সংজ্ঞা এখানে পুনরাবৃত্তি করা হয়েছে:

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

আপনি একটি নতুন Keras স্তর যে প্রক্রিয়া বর্ণনা করতে পারেন Network গুলি।

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)

তারপরে আপনি একটি সাধারণ মডেল তৈরি করতে এই স্তরগুলি ব্যবহার করতে পারেন। একটি ভোজন ExtensionType একটি মডেল মধ্যে, আপনি একটি ব্যবহার করতে পারেন tf.keras.layer.Input সঙ্গে স্তর type_spec এক্সটেনশন টাইপ এর সেট TypeSpec । Keras মডেল প্রক্রিয়া ব্যাচ করতে ব্যবহার করা হবে, তাহলে type_spec ব্যাচ মাত্রা অন্তর্ভুক্ত করা আবশ্যক।

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(),
    ])

অবশেষে, আপনি একটি একক নেটওয়ার্কে এবং নেটওয়ার্কের একটি ব্যাচে মডেলটি প্রয়োগ করতে পারেন৷

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

কেরাস উদাহরণ: মাস্কডটেনসর

এই উদাহরণে, MaskedTensor সমর্থন করার জন্য বাড়ানো হয় Kerasshape একটি সম্পত্তি থেকে গণনা করা হয় যে হিসাবে সংজ্ঞায়িত করা হয় values ক্ষেত্র। Keras thatyou উভয় এক্সটেনশন টাইপ এবং তার এই সম্পত্তি যোগ প্রয়োজন TypeSpecMaskedTensor একটি সংজ্ঞায়িত __name__ পরিবর্তনশীল, যার জন্য প্রয়োজন হবে SavedModel ধারাবাহিকতাতে (নীচে)।

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

এরপরে, ডিসপ্যাচ ডেকোরেটরগুলি বেশ কয়েকটি TensorFlow API-এর ডিফল্ট আচরণ ওভাররাইড করতে ব্যবহৃত হয়। যেহেতু এই API গুলি মান Keras স্তর (যেমন দ্বারা ব্যবহার করা হয় Dense স্তর), এই অগ্রাহ্য সাথে সাক্ষাত স্তর ব্যবহার করার অনুমতি দেবে MaskedTensor । এই উদাহরণে উদ্দেশ্য পূরণকল্পে, matmul ছদ্মবেশী tensors জন্য (তাদের পণ্যের মধ্যে অন্তর্ভুক্ত নয় বড়) শূন্য যেমন ছদ্মবেশী মান চিকিত্সা সংজ্ঞায়িত করা হয়।

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

এর পরে আপনি একটি Keras মডেল যে গ্রহণ করে গঠন করা যেতে পারে MaskedTensor ইনপুট, মানক Keras স্তর ব্যবহার করছে:

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

সংরক্ষিত মডেল

একজন SavedModel উভয় ওজন ও গণনার সহ একটি ধারাবাহিকভাবে TensorFlow প্রোগ্রাম, হয়। এটি একটি কেরাস মডেল বা একটি কাস্টম মডেল থেকে তৈরি করা যেতে পারে। উভয় ক্ষেত্রেই, সংরক্ষিত মডেল দ্বারা সংজ্ঞায়িত ফাংশন এবং পদ্ধতিগুলির সাথে এক্সটেনশন প্রকারগুলি স্বচ্ছভাবে ব্যবহার করা যেতে পারে।

SavedModel মডেল, স্তর এবং ফাংশন রক্ষা করতে পারে যে প্রক্রিয়া কোনো প্রকারের এক্সটেনশন, যতদিন কোনো প্রকারের এক্সটেনশন একটি আছে __name__ ক্ষেত্র। এই নামটি এক্সটেনশন টাইপ নিবন্ধন করতে ব্যবহৃত হয়, তাই মডেলটি লোড হলে এটি অবস্থিত হতে পারে।

উদাহরণ: কেরাস মডেল সংরক্ষণ করা

Keras মডেলের যে কোনো প্রকারের এক্সটেনশন ব্যবহার ব্যবহার সংরক্ষণ করা হতে পারে SavedModel

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

উদাহরণ: একটি কাস্টম মডেল সংরক্ষণ

SavedModel কাস্টম সংরক্ষণ করতে ব্যবহার করা যেতে পারে tf.Module যে প্রক্রিয়া কোনো প্রকারের এক্সটেনশন ফাংশন সঙ্গে উপশ্রেণী।

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]))
INFO:tensorflow:Assets written to: /tmp/tmp2x8zq5kb/assets
INFO:tensorflow:Assets written to: /tmp/tmp2x8zq5kb/assets
<MaskedTensor [_, 200.0, _]>

এক্সটেনশন টাইপ অনুপলব্ধ হলে একটি সংরক্ষিত মডেল লোড করা হচ্ছে

আপনি যদি একটি লোড তাহলে SavedModel একটি ব্যবহার করে ExtensionType , কিন্তু যে ExtensionType (অর্থাত, আমদানি করা হয়েছে) পাওয়া যায় না, তাহলে আপনি একটি সতর্কতা দেখতে পাবেন এবং TensorFlow একটি "বেনামী এক্সটেনশন টাইপ" বস্তু ব্যবহারে ফিরে আসবে। এই অবজেক্টের মূল টাইপের মতো একই ক্ষেত্র থাকবে, কিন্তু টাইপের জন্য আপনার যোগ করা আর কোনো কাস্টমাইজেশনের অভাব থাকবে, যেমন কাস্টম পদ্ধতি বা বৈশিষ্ট্য।

TensorFlow পরিবেশনের সাথে ExtensionTypes ব্যবহার করা

বর্তমানে, TensorFlow ভজনা (এবং SavedModel "স্বাক্ষর" অভিধানের অন্যান্য ভোক্তাদের) প্রয়োজন যে সব ইনপুট এবং আউটপুট কাঁচা tensors হও। আপনি যদি এক্সটেনশন প্রকারগুলি ব্যবহার করে এমন একটি মডেলের সাথে টেনসরফ্লো সার্ভিং ব্যবহার করতে চান, তাহলে আপনি র্যাপার পদ্ধতিগুলি যোগ করতে পারেন যা টেনসর থেকে এক্সটেনশন প্রকারের মানগুলি রচনা বা পচন করে। যেমন:

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)
INFO:tensorflow:Assets written to: /tmp/tmpxhh4zh0i/assets
INFO:tensorflow:Assets written to: /tmp/tmpxhh4zh0i/assets
<tf.Tensor: shape=(), dtype=float32, numpy=12.0>

ডেটাসেট

tf.data একটি API আপনি সহজ থেকে জটিল ইনপুট পাইপলাইন, পুনর্ব্যবহারযোগ্য টুকরা গড়ে তুলতে সক্ষম করে। এর মূলে ডেটা স্ট্রাকচার tf.data.Dataset , যা উপাদানের একটি ক্রম, যা প্রতিটি উপাদান এক বা একাধিক উপাদান নিয়ে গঠিত প্রতিনিধিত্ব করে।

এক্সটেনশন প্রকারের সাথে ডেটাসেট তৈরি করা

ডেটাসেট ব্যবহার এক্সটেনশন টাইপ মান থেকে নির্মিত হতে পারে Dataset.from_tensors , Dataset.from_tensor_slices , অথবা Dataset.from_generator :

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

এক্সটেনশন প্রকারের সাথে ডেটাসেট ব্যাচিং এবং আনব্যাচিং

কোনো প্রকারের এক্সটেনশন সঙ্গে ডেটাসেট ব্যবহার batchand এবং unbatched হতে পারে Dataset.batch এডিএন Dataset.unbatch

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