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

সাবক্লাসিংয়ের মাধ্যমে নতুন স্তর এবং মডেল তৈরি করা

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

সেটআপ

import tensorflow as tf
from tensorflow import keras

Layer শ্রেণী: রাজ্য (ওজন) সমন্বয় এবং কিছু গণনার

Keras কেন্দ্রীয় বিমূর্ততা এক Layer বর্গ। একটি স্তর একটি অবস্থা (স্তরের "ওজন") এবং ইনপুট থেকে আউটপুটে রূপান্তর (একটি "কল", স্তরটির ফরোয়ার্ড পাস) উভয়কেই অন্তর্ভুক্ত করে।

এখানে একটি ঘন-সংযুক্ত স্তর। ভেরিয়েবল: এটা একটি রাষ্ট্র হয়েছে w এবং b

class Linear(keras.layers.Layer):
    def __init__(self, units=32, input_dim=32):
        super(Linear, self).__init__()
        w_init = tf.random_normal_initializer()
        self.w = tf.Variable(
            initial_value=w_init(shape=(input_dim, units), dtype="float32"),
            trainable=True,
        )
        b_init = tf.zeros_initializer()
        self.b = tf.Variable(
            initial_value=b_init(shape=(units,), dtype="float32"), trainable=True
        )

    def call(self, inputs):
        return tf.matmul(inputs, self.w) + self.b

আপনি পাইথন ফাংশনের মতো কিছু টেনসর ইনপুট(গুলি) এ কল করে একটি স্তর ব্যবহার করবেন।

x = tf.ones((2, 2))
linear_layer = Linear(4, 2)
y = linear_layer(x)
print(y)
tf.Tensor(
[[ 0.00962844 -0.01307489 -0.1452128   0.0538918 ]
 [ 0.00962844 -0.01307489 -0.1452128   0.0538918 ]], shape=(2, 4), dtype=float32)

লক্ষ্য করুন ওজন w এবং b স্বয়ংক্রিয়ভাবে স্তর বৈশিষ্ট্যাবলী যেমন সেট হওয়া উপর স্তর দ্বারা ট্র্যাক করা হয়:

assert linear_layer.weights == [linear_layer.w, linear_layer.b]

উল্লেখ্য আপনার কাছে একটি স্তর ওজন যোগ করার জন্য একটি দ্রুততর শর্টকাট এক্সেস আছে: add_weight() পদ্ধতি:

class Linear(keras.layers.Layer):
    def __init__(self, units=32, input_dim=32):
        super(Linear, self).__init__()
        self.w = self.add_weight(
            shape=(input_dim, units), initializer="random_normal", trainable=True
        )
        self.b = self.add_weight(shape=(units,), initializer="zeros", trainable=True)

    def call(self, inputs):
        return tf.matmul(inputs, self.w) + self.b


x = tf.ones((2, 2))
linear_layer = Linear(4, 2)
y = linear_layer(x)
print(y)
tf.Tensor(
[[ 0.05790994  0.060931   -0.0402256  -0.09450993]
 [ 0.05790994  0.060931   -0.0402256  -0.09450993]], shape=(2, 4), dtype=float32)

স্তরগুলির অ-প্রশিক্ষণযোগ্য ওজন থাকতে পারে

প্রশিক্ষণযোগ্য ওজন ছাড়াও, আপনি একটি স্তরে অ-প্রশিক্ষণযোগ্য ওজনও যোগ করতে পারেন। যখন আপনি স্তরটি প্রশিক্ষণ দিচ্ছেন তখন এই ধরনের ওজনগুলি ব্যাকপ্রোপাগেশনের সময় বিবেচনায় নেওয়া উচিত নয়।

এখানে কিভাবে একটি অ-প্রশিক্ষণযোগ্য ওজন যোগ এবং ব্যবহার করতে হয়:

class ComputeSum(keras.layers.Layer):
    def __init__(self, input_dim):
        super(ComputeSum, self).__init__()
        self.total = tf.Variable(initial_value=tf.zeros((input_dim,)), trainable=False)

    def call(self, inputs):
        self.total.assign_add(tf.reduce_sum(inputs, axis=0))
        return self.total


x = tf.ones((2, 2))
my_sum = ComputeSum(2)
y = my_sum(x)
print(y.numpy())
y = my_sum(x)
print(y.numpy())
[2. 2.]
[4. 4.]

এটা তোলে অংশ layer.weights কিন্তু এটি একটি অ-trainable ওজন শ্রেণীকরণ পরার:

print("weights:", len(my_sum.weights))
print("non-trainable weights:", len(my_sum.non_trainable_weights))

# It's not included in the trainable weights:
print("trainable_weights:", my_sum.trainable_weights)
weights: 1
non-trainable weights: 1
trainable_weights: []

সর্বোত্তম অনুশীলন: ইনপুটগুলির আকৃতি জানা না হওয়া পর্যন্ত ওজন তৈরি করা পিছিয়ে দেওয়া

আমাদের Linear স্তর উপরে একটি গ্রহণ input_dim যুক্তি হল যে ওজন আকৃতি গনা ব্যবহৃত হয় w এবং b মধ্যে __init__() :

class Linear(keras.layers.Layer):
    def __init__(self, units=32, input_dim=32):
        super(Linear, self).__init__()
        self.w = self.add_weight(
            shape=(input_dim, units), initializer="random_normal", trainable=True
        )
        self.b = self.add_weight(shape=(units,), initializer="zeros", trainable=True)

    def call(self, inputs):
        return tf.matmul(inputs, self.w) + self.b

অনেক ক্ষেত্রে, আপনি আপনার ইনপুটগুলির আকার আগে থেকে নাও জানতে পারেন এবং স্তরটি ইনস্ট্যান্টিয়েট করার কিছু সময় পরে সেই মানটি জানা হয়ে গেলে আপনি অলসভাবে ওজন তৈরি করতে চান।

Keras এপিআই, আমরা মধ্যে স্তর ওজন তৈরি করার প্রস্তাব দিই build(self, inputs_shape) আপনার স্তর পদ্ধতি। এটার মত:

class Linear(keras.layers.Layer):
    def __init__(self, units=32):
        super(Linear, self).__init__()
        self.units = units

    def build(self, input_shape):
        self.w = self.add_weight(
            shape=(input_shape[-1], self.units),
            initializer="random_normal",
            trainable=True,
        )
        self.b = self.add_weight(
            shape=(self.units,), initializer="random_normal", trainable=True
        )

    def call(self, inputs):
        return tf.matmul(inputs, self.w) + self.b

__call__() আপনার স্তর পদ্ধতি স্বয়ংক্রিয়ভাবে বিল্ড প্রথমবার এটা বলা হয় চালানো হবে। আপনার কাছে এখন একটি স্তর রয়েছে যা অলস এবং এইভাবে ব্যবহার করা সহজ:

# At instantiation, we don't know on what inputs this is going to get called
linear_layer = Linear(32)

# The layer's weights are created dynamically the first time the layer is called
y = linear_layer(x)

বাস্তবায়নকারী build() আলাদাভাবে যেমন চমত্কারভাবে উপরে দেখানো যে কলে ওজন ব্যবহার থেকে শুধুমাত্র একবার ওজন তৈরি আলাদা করে। যাইহোক, কিছু উন্নত কাস্টম স্তরের জন্য, রাষ্ট্র সৃষ্টি এবং গণনাকে আলাদা করা অব্যবহারিক হয়ে উঠতে পারে। লেয়ার প্রয়োগকারীদের প্রথম ওজন সৃষ্টি মুলতবি করার অনুমতি দেওয়া হয় __call__() যা পরে কল একই ওজন ব্যবহার যত্ন নেওয়া প্রয়োজন কিন্তু। উপরন্তু, যেহেতু __call__() সম্ভবত একটি ভিতরে প্রথমবারের মৃত্যুদন্ড কার্যকর করা হয় tf.function কোন পরিবর্তনশীল সৃষ্টি যে সঞ্চালিত __call__() একটি আবৃত করা উচিত tf.init_scope

স্তরগুলি পুনরাবৃত্তিমূলকভাবে কম্পোজযোগ্য

আপনি যদি একটি লেয়ার ইনস্ট্যান্সকে অন্য লেয়ারের অ্যাট্রিবিউট হিসেবে অ্যাসাইন করেন, তাহলে বাইরের লেয়ারটি ভেতরের লেয়ার দ্বারা তৈরি ওজন ট্র্যাক করা শুরু করবে।

আমরা এ ধরনের sublayers তৈরি সুপারিশ __init__() পদ্ধতি এবং প্রথম এটি ছেড়ে __call__() তাদের ওজন বিল্ডিং ট্রিগার।

class MLPBlock(keras.layers.Layer):
    def __init__(self):
        super(MLPBlock, self).__init__()
        self.linear_1 = Linear(32)
        self.linear_2 = Linear(32)
        self.linear_3 = Linear(1)

    def call(self, inputs):
        x = self.linear_1(inputs)
        x = tf.nn.relu(x)
        x = self.linear_2(x)
        x = tf.nn.relu(x)
        return self.linear_3(x)


mlp = MLPBlock()
y = mlp(tf.ones(shape=(3, 64)))  # The first call to the `mlp` will create the weights
print("weights:", len(mlp.weights))
print("trainable weights:", len(mlp.trainable_weights))
weights: 6
trainable weights: 6

add_loss() পদ্ধতি

লেখার সময় call() একটি স্তর পদ্ধতি, আপনি ক্ষতি tensors তৈরি করতে পারেন যে আপনার যখন আপনার প্রশিক্ষণ লুপ লেখা পরে, ব্যবহার করতে চান হবে। এই কল করে করা সম্ভব হয় self.add_loss(value) :

# A layer that creates an activity regularization loss
class ActivityRegularizationLayer(keras.layers.Layer):
    def __init__(self, rate=1e-2):
        super(ActivityRegularizationLayer, self).__init__()
        self.rate = rate

    def call(self, inputs):
        self.add_loss(self.rate * tf.reduce_sum(inputs))
        return inputs

এই লোকসান (যে কোন ভিতরের স্তর দ্বারা নির্মিত সেগুলি সহ) মাধ্যমে পুনরায় উদ্ধার করা যাবে layer.losses । এই সম্পত্তি যে শুরুতে রিসেট হয় __call__() টপ লেভেল স্তরে, যাতে layer.losses সবসময় গত ফরওয়ার্ড পাস সময় নির্মিত ক্ষতি মান ধারণ করে।

class OuterLayer(keras.layers.Layer):
    def __init__(self):
        super(OuterLayer, self).__init__()
        self.activity_reg = ActivityRegularizationLayer(1e-2)

    def call(self, inputs):
        return self.activity_reg(inputs)


layer = OuterLayer()
assert len(layer.losses) == 0  # No losses yet since the layer has never been called

_ = layer(tf.zeros(1, 1))
assert len(layer.losses) == 1  # We created one loss value

# `layer.losses` gets reset at the start of each __call__
_ = layer(tf.zeros(1, 1))
assert len(layer.losses) == 1  # This is the loss created during the call above

উপরন্তু, loss সম্পত্তি তার সাথে সাথে ভিতরের স্তর এর ওজন জন্য নির্মিত নিয়মিতকরণ লোকসান রয়েছে:

class OuterLayerWithKernelRegularizer(keras.layers.Layer):
    def __init__(self):
        super(OuterLayerWithKernelRegularizer, self).__init__()
        self.dense = keras.layers.Dense(
            32, kernel_regularizer=tf.keras.regularizers.l2(1e-3)
        )

    def call(self, inputs):
        return self.dense(inputs)


layer = OuterLayerWithKernelRegularizer()
_ = layer(tf.zeros((1, 1)))

# This is `1e-3 * sum(layer.dense.kernel ** 2)`,
# created by the `kernel_regularizer` above.
print(layer.losses)
[<tf.Tensor: shape=(), dtype=float32, numpy=0.0024520475>]

প্রশিক্ষণ লুপ লেখার সময় এই ক্ষতিগুলি বিবেচনায় নেওয়া হয়, যেমন:

# Instantiate an optimizer.
optimizer = tf.keras.optimizers.SGD(learning_rate=1e-3)
loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=True)

# Iterate over the batches of a dataset.
for x_batch_train, y_batch_train in train_dataset:
  with tf.GradientTape() as tape:
    logits = layer(x_batch_train)  # Logits for this minibatch
    # Loss value for this minibatch
    loss_value = loss_fn(y_batch_train, logits)
    # Add extra losses created during this forward pass:
    loss_value += sum(model.losses)

  grads = tape.gradient(loss_value, model.trainable_weights)
  optimizer.apply_gradients(zip(grads, model.trainable_weights))

প্রশিক্ষণ লুপ লেখা সম্পর্কে একটি বিস্তারিত গাইড জন্য, দেখুন গোড়া থেকে একটি প্রশিক্ষণ লুপ লেখা গাইড

এই ক্ষতির সাথে সিম ছাড়াই কাজ করে fit() (তারা স্বয়ংক্রিয়ভাবে সংকলিত এবং প্রধান ক্ষতি যুক্ত হয়ে যদি থাকে):

import numpy as np

inputs = keras.Input(shape=(3,))
outputs = ActivityRegularizationLayer()(inputs)
model = keras.Model(inputs, outputs)

# If there is a loss passed in `compile`, the regularization
# losses get added to it
model.compile(optimizer="adam", loss="mse")
model.fit(np.random.random((2, 3)), np.random.random((2, 3)))

# It's also possible not to pass any loss in `compile`,
# since the model already has a loss to minimize, via the `add_loss`
# call during the forward pass!
model.compile(optimizer="adam")
model.fit(np.random.random((2, 3)), np.random.random((2, 3)))
1/1 [==============================] - 0s 209ms/step - loss: 0.1948
1/1 [==============================] - 0s 49ms/step - loss: 0.0298
<keras.callbacks.History at 0x7fce9052d290>

add_metric() পদ্ধতি

একইভাবে করার add_loss() , স্তর এছাড়াও একটি আছে add_metric() প্রশিক্ষণের সময় একটি পরিমাণ গড় চলন্ত ট্র্যাকিং জন্য পদ্ধতি।

নিম্নলিখিত স্তরটি বিবেচনা করুন: একটি "লজিস্টিক এন্ডপয়েন্ট" স্তর। যেমন লাগে ইনপুট ভবিষ্যৎবাণী & লক্ষ্যমাত্রা, এটি একটি ক্ষতির এটা মাধ্যমে ট্র্যাক যা নির্ণয় add_loss() , এবং এটি একটি সঠিকতা স্কালে, এটা মাধ্যমে ট্র্যাক যা নির্ণয় add_metric()

class LogisticEndpoint(keras.layers.Layer):
    def __init__(self, name=None):
        super(LogisticEndpoint, self).__init__(name=name)
        self.loss_fn = keras.losses.BinaryCrossentropy(from_logits=True)
        self.accuracy_fn = keras.metrics.BinaryAccuracy()

    def call(self, targets, logits, sample_weights=None):
        # Compute the training-time loss value and add it
        # to the layer using `self.add_loss()`.
        loss = self.loss_fn(targets, logits, sample_weights)
        self.add_loss(loss)

        # Log accuracy as a metric and add it
        # to the layer using `self.add_metric()`.
        acc = self.accuracy_fn(targets, logits, sample_weights)
        self.add_metric(acc, name="accuracy")

        # Return the inference-time prediction tensor (for `.predict()`).
        return tf.nn.softmax(logits)

এই ভাবে ট্র্যাক মেট্রিক্স মাধ্যমে অ্যাক্সেসযোগ্য হয় layer.metrics :

layer = LogisticEndpoint()

targets = tf.ones((2, 2))
logits = tf.ones((2, 2))
y = layer(targets, logits)

print("layer.metrics:", layer.metrics)
print("current accuracy value:", float(layer.metrics[0].result()))
layer.metrics: [<keras.metrics.BinaryAccuracy object at 0x7fce90578490>]
current accuracy value: 1.0

শুধু মত add_loss() , এই বৈশিষ্ট্যের মান দ্বারা ট্র্যাক করা হয় fit() :

inputs = keras.Input(shape=(3,), name="inputs")
targets = keras.Input(shape=(10,), name="targets")
logits = keras.layers.Dense(10)(inputs)
predictions = LogisticEndpoint(name="predictions")(logits, targets)

model = keras.Model(inputs=[inputs, targets], outputs=predictions)
model.compile(optimizer="adam")

data = {
    "inputs": np.random.random((3, 3)),
    "targets": np.random.random((3, 10)),
}
model.fit(data)
1/1 [==============================] - 0s 274ms/step - loss: 0.9291 - binary_accuracy: 0.0000e+00
<keras.callbacks.History at 0x7fce90448c50>

আপনি ঐচ্ছিকভাবে আপনার স্তরগুলিতে সিরিয়ালাইজেশন সক্ষম করতে পারেন

আপনি আপনার কাস্টম স্তর দরকার তা যদি একটি অংশ হিসেবে serializable হতে ক্রিয়াগত মডেল , আপনি বিকল্প হিসেবে একটি বাস্তবায়ন করতে পারে get_config() পদ্ধতি:

class Linear(keras.layers.Layer):
    def __init__(self, units=32):
        super(Linear, self).__init__()
        self.units = units

    def build(self, input_shape):
        self.w = self.add_weight(
            shape=(input_shape[-1], self.units),
            initializer="random_normal",
            trainable=True,
        )
        self.b = self.add_weight(
            shape=(self.units,), initializer="random_normal", trainable=True
        )

    def call(self, inputs):
        return tf.matmul(inputs, self.w) + self.b

    def get_config(self):
        return {"units": self.units}


# Now you can recreate the layer from its config:
layer = Linear(64)
config = layer.get_config()
print(config)
new_layer = Linear.from_config(config)
{'units': 64}

লক্ষ্য করুন __init__() ভিত্তির পদ্ধতি Layer বর্গ বিশেষ একটি মধ্যে কিছু শব্দ আর্গুমেন্ট লাগে, name এবং dtype । এটা পিতা বা মাতা বর্গ এইসব আর্গুমেন্ট পাস ভাল অভ্যাস __init__() এবং তাদের স্তর কনফিগ অন্তর্ভুক্ত করতে:

class Linear(keras.layers.Layer):
    def __init__(self, units=32, **kwargs):
        super(Linear, self).__init__(**kwargs)
        self.units = units

    def build(self, input_shape):
        self.w = self.add_weight(
            shape=(input_shape[-1], self.units),
            initializer="random_normal",
            trainable=True,
        )
        self.b = self.add_weight(
            shape=(self.units,), initializer="random_normal", trainable=True
        )

    def call(self, inputs):
        return tf.matmul(inputs, self.w) + self.b

    def get_config(self):
        config = super(Linear, self).get_config()
        config.update({"units": self.units})
        return config


layer = Linear(64)
config = layer.get_config()
print(config)
new_layer = Linear.from_config(config)
{'name': 'linear_8', 'trainable': True, 'dtype': 'float32', 'units': 64}

আপনি আরো নমনীয়তা প্রয়োজন যখন তার কনফিগ থেকে স্তর deserializing, এছাড়াও আপনি ওভাররাইড করতে পারে from_config() বর্গ পদ্ধতি। এই বেস বাস্তবায়ন from_config() :

def from_config(cls, config):
  return cls(**config)

ধারাবাহিকতাতে ও সংরক্ষণ সম্পর্কে আরো জানতে, সম্পূর্ণ দেখতে সংরক্ষণ এবং মডেল serializing গাইড

প্রিভিলেজড training মধ্যে যুক্তি call() পদ্ধতি

কিছু স্তর, বিশেষ BatchNormalization লেয়ার এবং Dropout স্তর, প্রশিক্ষণ ও অনুমান সময় বিভিন্ন আচরণে আছে। যেমন স্তরগুলির জন্য, এটি একটি এক্সপোজ করতে মান অভ্যাস training মধ্যে (বুলিয়ান) যুক্তি call() পদ্ধতি।

এই যুক্তি প্রকাশক দ্বারা call() , আপনি বিল্ট ইন প্রশিক্ষণ ও মূল্যায়ন লুপ (যেমন সক্ষম fit() সঠিকভাবে প্রশিক্ষণ ও অনুমান মধ্যে স্তর ব্যবহার করতে)।

class CustomDropout(keras.layers.Layer):
    def __init__(self, rate, **kwargs):
        super(CustomDropout, self).__init__(**kwargs)
        self.rate = rate

    def call(self, inputs, training=None):
        if training:
            return tf.nn.dropout(inputs, rate=self.rate)
        return inputs

প্রিভিলেজড mask মধ্যে যুক্তি call() পদ্ধতি

অন্যান্য সুবিধাপ্রাপ্ত যুক্তি দ্বারা সমর্থিত call() হল mask যুক্তি।

আপনি এটি সমস্ত Keras RNN স্তরগুলিতে পাবেন৷ একটি মুখোশ হল একটি বুলিয়ান টেনসর (ইনপুটে প্রতি টাইমস্টেপে একটি বুলিয়ান মান) টাইমসিরিজ ডেটা প্রক্রিয়া করার সময় নির্দিষ্ট ইনপুট টাইমস্টেপগুলি এড়িয়ে যাওয়ার জন্য ব্যবহৃত হয়।

Keras স্বয়ংক্রিয়ভাবে ঠিক পাস হবে mask আর্গুমেন্ট প্রাপ্ত করতে __call__() স্তর যা এটিকে সমর্থন করে, যখন একটি মাস্ক একটি পূর্বে স্তর দ্বারা উত্পন্ন হয়। মাস্ক-উৎপাদিত স্তর আছে Embedding স্তর কনফিগার mask_zero=True এবং Masking স্তর।

মাস্কিং এবং কিভাবে লিখতে মাস্কিং-সক্রিয় স্তর সম্পর্কে আরো জানতে, গাইড চেক করুন "প্যাডিং বোঝার এবং মাস্কিং"

Model বর্গ

সাধারণভাবে, আপনি ব্যবহার করবে Layer ভেতরের গণনার ব্লক নির্ধারণ করতে বর্গ, এবং ব্যবহার করবে Model বাইরের মডেল সংজ্ঞায়িত করতে বর্গ - বস্তু আপনি শেখাতে হবে।

উদাহরণস্বরূপ, একজন ResNet50 মডেল, আপনি subclassing বিভিন্ন ResNet ব্লক হবে Layer , এবং একটি একক Model সমগ্র ResNet50 নেটওয়ার্কের encompassing।

Model শ্রেণী হিসেবে একই এপিআই হয়েছে Layer নিম্নলিখিত পার্থক্য:

  • এটা তোলে বিল্ট-ইন প্রশিক্ষণ, মূল্যায়ন, এবং Prediction লুপ অনাবৃত ( model.fit() , model.evaluate() , model.predict() )।
  • এটা তার ভেতরের স্তরগুলির তালিকা প্রকাশ মাধ্যমে model.layers সম্পত্তি।
  • সংরক্ষণ এবং ধারাবাহিকতাতে API গুলি অনাবৃত ( save() , save_weights() ...)

কার্যকরীভাবে, Layer কি আমরা একটি "স্তর" হিসেবে (সাহিত্যে পড়ুন ( "সংবর্তন স্তর" বা "পৌনঃপুনিক স্তর" হিসেবে) অথবা একটি "ব্লক" হিসাবে "ব্লক ResNet" হিসেবে অথবা "ইনসেপশন ব্লক" এ বর্গ অনুরূপ )

এদিকে, Model কি একটি "মডেল" হিসেবে সাহিত্যে উল্লেখ করা হয় ক্লাসের অনুরূপ ( "গভীর লার্নিং মডেল" হিসেবে) অথবা একটি "নেটওয়ার্ক" নামে ( "গভীর স্নায়ুর নেটওয়ার্ক" এ হিসাবে)।

আপনি হতাশ করছি তাই আপনি যদি, "আমি ব্যবহার করা উচিত Layer বর্গ বা Model বর্গ?", নিজেকে জিজ্ঞাসা: আমি কল করতে হবে fit() এটা? আমি ফোন করার প্রয়োজন হবে save() এটিতে? যদি তাই হয়, সাথে যেতে Model । যদি তা না হয় (হয় কারণ আপনার বর্গ একটি বড় সিস্টেমের মধ্যে মাত্র একটি ব্লক, অথবা কারণ আপনার প্রশিক্ষণ লেখার & নিজেকে কোড সংরক্ষণ করা হয়), ব্যবহার Layer

উদাহরণস্বরূপ, আমরা উপরোক্ত আমাদের মিনি- resnet উদাহরণ নিতে পারে, এবং এটি ব্যবহার একটি নির্মাণ করতে Model যে আমরা প্রশিক্ষণের পারে fit() , এবং আমরা সংরক্ষণ করি পারে যে save_weights() :

class ResNet(tf.keras.Model):

    def __init__(self, num_classes=1000):
        super(ResNet, self).__init__()
        self.block_1 = ResNetBlock()
        self.block_2 = ResNetBlock()
        self.global_pool = layers.GlobalAveragePooling2D()
        self.classifier = Dense(num_classes)

    def call(self, inputs):
        x = self.block_1(inputs)
        x = self.block_2(x)
        x = self.global_pool(x)
        return self.classifier(x)


resnet = ResNet()
dataset = ...
resnet.fit(dataset, epochs=10)
resnet.save(filepath)

এটি সব একসাথে রাখা: একটি শেষ থেকে শেষ উদাহরণ

আপনি এখন পর্যন্ত যা শিখেছেন তা এখানে:

  • একটি Layer একটি রাষ্ট্র (তৈরি করা encapsulate __init__() বা build() ) এবং কিছু গণনার (সংজ্ঞায়িত call() )।
  • নতুন, বৃহত্তর গণনা ব্লক তৈরি করতে স্তরগুলি পুনরাবৃত্তভাবে নেস্ট করা যেতে পারে।
  • স্তরসমূহ তৈরি করতে পারেন এবং ট্র্যাক লোকসান (সাধারণত নিয়মিতকরণ লোকসান) পাশাপাশি মেট্রিক্স মাধ্যমে add_loss() এবং add_metric()
  • বাইরের ধারক, জিনিস আপনি শেখাতে চাই, একটি হল Model । একটি Model শুধু একটি মত হল Layer , কিন্তু যোগ প্রশিক্ষণ ও ধারাবাহিকতাতে ইউটিলিটি সঙ্গে।

আসুন এই সমস্ত জিনিসগুলিকে একটি এন্ড-টু-এন্ড উদাহরণে একত্রিত করি: আমরা একটি পরিবর্তনশীল অটোএনকোডার (VAE) বাস্তবায়ন করতে যাচ্ছি। আমরা এটিকে MNIST সংখ্যায় প্রশিক্ষণ দেব।

আমাদের VAE একটি উপশ্রেণী হতে হবে Model , যে উপশ্রেণী স্তর একটি নেস্টেড রচনা হিসেবে নির্মিত Layer । এটি একটি নিয়মিতকরণ ক্ষতি (কেএল ডাইভারজেন্স) বৈশিষ্ট্যযুক্ত হবে।

from tensorflow.keras import layers


class Sampling(layers.Layer):
    """Uses (z_mean, z_log_var) to sample z, the vector encoding a digit."""

    def call(self, inputs):
        z_mean, z_log_var = inputs
        batch = tf.shape(z_mean)[0]
        dim = tf.shape(z_mean)[1]
        epsilon = tf.keras.backend.random_normal(shape=(batch, dim))
        return z_mean + tf.exp(0.5 * z_log_var) * epsilon


class Encoder(layers.Layer):
    """Maps MNIST digits to a triplet (z_mean, z_log_var, z)."""

    def __init__(self, latent_dim=32, intermediate_dim=64, name="encoder", **kwargs):
        super(Encoder, self).__init__(name=name, **kwargs)
        self.dense_proj = layers.Dense(intermediate_dim, activation="relu")
        self.dense_mean = layers.Dense(latent_dim)
        self.dense_log_var = layers.Dense(latent_dim)
        self.sampling = Sampling()

    def call(self, inputs):
        x = self.dense_proj(inputs)
        z_mean = self.dense_mean(x)
        z_log_var = self.dense_log_var(x)
        z = self.sampling((z_mean, z_log_var))
        return z_mean, z_log_var, z


class Decoder(layers.Layer):
    """Converts z, the encoded digit vector, back into a readable digit."""

    def __init__(self, original_dim, intermediate_dim=64, name="decoder", **kwargs):
        super(Decoder, self).__init__(name=name, **kwargs)
        self.dense_proj = layers.Dense(intermediate_dim, activation="relu")
        self.dense_output = layers.Dense(original_dim, activation="sigmoid")

    def call(self, inputs):
        x = self.dense_proj(inputs)
        return self.dense_output(x)


class VariationalAutoEncoder(keras.Model):
    """Combines the encoder and decoder into an end-to-end model for training."""

    def __init__(
        self,
        original_dim,
        intermediate_dim=64,
        latent_dim=32,
        name="autoencoder",
        **kwargs
    ):
        super(VariationalAutoEncoder, self).__init__(name=name, **kwargs)
        self.original_dim = original_dim
        self.encoder = Encoder(latent_dim=latent_dim, intermediate_dim=intermediate_dim)
        self.decoder = Decoder(original_dim, intermediate_dim=intermediate_dim)

    def call(self, inputs):
        z_mean, z_log_var, z = self.encoder(inputs)
        reconstructed = self.decoder(z)
        # Add KL divergence regularization loss.
        kl_loss = -0.5 * tf.reduce_mean(
            z_log_var - tf.square(z_mean) - tf.exp(z_log_var) + 1
        )
        self.add_loss(kl_loss)
        return reconstructed

আসুন MNIST-এ একটি সাধারণ প্রশিক্ষণ লুপ লিখি:

original_dim = 784
vae = VariationalAutoEncoder(original_dim, 64, 32)

optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)
mse_loss_fn = tf.keras.losses.MeanSquaredError()

loss_metric = tf.keras.metrics.Mean()

(x_train, _), _ = tf.keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype("float32") / 255

train_dataset = tf.data.Dataset.from_tensor_slices(x_train)
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)

epochs = 2

# Iterate over epochs.
for epoch in range(epochs):
    print("Start of epoch %d" % (epoch,))

    # Iterate over the batches of the dataset.
    for step, x_batch_train in enumerate(train_dataset):
        with tf.GradientTape() as tape:
            reconstructed = vae(x_batch_train)
            # Compute reconstruction loss
            loss = mse_loss_fn(x_batch_train, reconstructed)
            loss += sum(vae.losses)  # Add KLD regularization loss

        grads = tape.gradient(loss, vae.trainable_weights)
        optimizer.apply_gradients(zip(grads, vae.trainable_weights))

        loss_metric(loss)

        if step % 100 == 0:
            print("step %d: mean loss = %.4f" % (step, loss_metric.result()))
Start of epoch 0
step 0: mean loss = 0.3184
step 100: mean loss = 0.1252
step 200: mean loss = 0.0989
step 300: mean loss = 0.0890
step 400: mean loss = 0.0841
step 500: mean loss = 0.0807
step 600: mean loss = 0.0787
step 700: mean loss = 0.0771
step 800: mean loss = 0.0759
step 900: mean loss = 0.0749
Start of epoch 1
step 0: mean loss = 0.0746
step 100: mean loss = 0.0740
step 200: mean loss = 0.0735
step 300: mean loss = 0.0730
step 400: mean loss = 0.0727
step 500: mean loss = 0.0723
step 600: mean loss = 0.0720
step 700: mean loss = 0.0717
step 800: mean loss = 0.0715
step 900: mean loss = 0.0712

মনে রাখবেন যে, VAE subclassing হয় যেহেতু Model , এটা বৈশিষ্ট্য বিল্ট-ইন প্রশিক্ষণ লুপ। সুতরাং আপনি এটির মতো প্রশিক্ষণও দিতে পারেন:

vae = VariationalAutoEncoder(784, 64, 32)

optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)

vae.compile(optimizer, loss=tf.keras.losses.MeanSquaredError())
vae.fit(x_train, x_train, epochs=2, batch_size=64)
Epoch 1/2
938/938 [==============================] - 3s 3ms/step - loss: 0.0745
Epoch 2/2
938/938 [==============================] - 3s 3ms/step - loss: 0.0676
<keras.callbacks.History at 0x7fce90282750>

অবজেক্ট-ভিত্তিক বিকাশের বাইরে: কার্যকরী API

এই উদাহরণটি কি আপনার জন্য খুব বেশি বস্তু-ভিত্তিক উন্নয়ন ছিল? এছাড়াও আপনি ব্যবহার মডেলের নির্মাণ করতে পারেন ক্রিয়াগত এপিআই । গুরুত্বপূর্ণভাবে, একটি বা অন্য স্টাইল বেছে নেওয়া আপনাকে অন্য স্টাইলে লিখিত উপাদানগুলিকে কাজে লাগাতে বাধা দেয় না: আপনি সর্বদা মিশ্র-এন্ড-ম্যাচ করতে পারেন।

উদাহরণস্বরূপ, পুনঃব্যবহৃত হয়নি নিচে ক্রিয়াগত এপিআই উদাহরণ একই Sampling স্তর আমরা উপরোক্ত উদাহরণে সংজ্ঞা দিয়েছে:

original_dim = 784
intermediate_dim = 64
latent_dim = 32

# Define encoder model.
original_inputs = tf.keras.Input(shape=(original_dim,), name="encoder_input")
x = layers.Dense(intermediate_dim, activation="relu")(original_inputs)
z_mean = layers.Dense(latent_dim, name="z_mean")(x)
z_log_var = layers.Dense(latent_dim, name="z_log_var")(x)
z = Sampling()((z_mean, z_log_var))
encoder = tf.keras.Model(inputs=original_inputs, outputs=z, name="encoder")

# Define decoder model.
latent_inputs = tf.keras.Input(shape=(latent_dim,), name="z_sampling")
x = layers.Dense(intermediate_dim, activation="relu")(latent_inputs)
outputs = layers.Dense(original_dim, activation="sigmoid")(x)
decoder = tf.keras.Model(inputs=latent_inputs, outputs=outputs, name="decoder")

# Define VAE model.
outputs = decoder(z)
vae = tf.keras.Model(inputs=original_inputs, outputs=outputs, name="vae")

# Add KL divergence regularization loss.
kl_loss = -0.5 * tf.reduce_mean(z_log_var - tf.square(z_mean) - tf.exp(z_log_var) + 1)
vae.add_loss(kl_loss)

# Train.
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)
vae.compile(optimizer, loss=tf.keras.losses.MeanSquaredError())
vae.fit(x_train, x_train, epochs=3, batch_size=64)
Epoch 1/3
938/938 [==============================] - 3s 3ms/step - loss: 0.0748
Epoch 2/3
938/938 [==============================] - 3s 3ms/step - loss: 0.0676
Epoch 3/3
938/938 [==============================] - 3s 3ms/step - loss: 0.0676
<keras.callbacks.History at 0x7fce90233cd0>

আরো তথ্যের জন্য, পড়া নিশ্চিত করা ক্রিয়াগত এপিআই নির্দেশিকা