![]() | ![]() | ![]() | ![]() |
Kurmak
import tensorflow as tf
from tensorflow import keras
Layer
sınıfı: durumu (ağırlıklar) kombinasyonu ve bir hesaplama
Keras merkezi soyutlama biri Layer
sınıfı. Bir katman, hem bir durumu (katmanın "ağırlıkları") hem de girdilerden çıktılara bir dönüşümü ("çağrı", katmanın ileri geçişi) kapsar.
İşte yoğun bağlantılı bir katman. Değişkenler: Bu durumu vardır w
ve 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
Bir Python işlevi gibi, bazı tensör girişlerinde onu çağırarak bir katman kullanırsınız.
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)
Ağırlıklar bu Not w
ve b
otomatik tabaka özellikler olarak ayarlandıktan sonra tabaka ile takip edilir:
assert linear_layer.weights == [linear_layer.w, linear_layer.b]
: Ayrıca bir katmana ağırlık eklemek için hızlı bir kısayol erişimi Not add_weight()
yöntemi:
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)
Katmanlar eğitilemez ağırlıklara sahip olabilir
Eğitilebilir ağırlıkların yanı sıra, bir katmana eğitilemez ağırlıklar da ekleyebilirsiniz. Bu tür ağırlıklar, katmanı eğitirken geri yayılım sırasında dikkate alınmamalıdır.
Eğitilemez bir ağırlığı nasıl ekleyeceğiniz ve kullanacağınız aşağıda açıklanmıştır:
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.]
Bu bir parçası layer.weights
ama olmayan bir eğitilebilir ağırlık olarak sınıflandırılan:
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: []
En iyi uygulama: girdilerin şekli bilinene kadar ağırlık oluşturmayı ertelemek
Bizim Linear
tabaka üzerinde bir aldı input_dim
ağırlıkları şeklini hesaplamak için kullanılmıştır bağımsız değişken w
ve b
olarak __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
Çoğu durumda, girdilerinizin boyutunu önceden bilemeyebilirsiniz ve bu değer bilindiğinde, katmanı somutlaştırdıktan bir süre sonra tembelce ağırlıklar oluşturmak istersiniz.
Keras API, biz katman ağırlıkları oluşturmaya tavsiye build(self, inputs_shape)
katmanınıza yöntemi. Bunun gibi:
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__()
katmanınıza yöntemi otomatik build denir ilk kez çalışır. Artık tembel ve dolayısıyla kullanımı daha kolay bir katmanınız var:
# 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)
Uygulama build()
ayrı ayrı yukarıdaki gibi güzel bir şekilde gösterilen her çağrı ağırlıkları kullanılarak sadece bir kez ağırlıkları oluşturmak ayırır. Ancak, bazı gelişmiş özel katmanlar için durum oluşturma ve hesaplamayı ayırmak pratik olmayabilir. Katman uygulayıcılar birinci ağırlık oluşturma ertelemek için izin verilir __call__()
, ancak daha sonra aramaları aynı ağırlıkları kullandıkları ihtiyaç dikkat çekmek için. Buna ilaveten, __call__()
muhtemelen içinde ilk defa yürütülecek olan tf.function
, içinde yer alan herhangi bir değişken oluşturulması __call__()
bir sarılmış olmalıdır tf.init_scope
.
Katmanlar özyinelemeli olarak birleştirilebilir
Bir Katman örneğini başka bir Katmanın özniteliği olarak atarsanız, dış katman, iç katman tarafından oluşturulan ağırlıkları izlemeye başlar.
Biz bu tür alt katmanlar oluşturarak tavsiye __init__()
yöntemi ve ilk bırakın __call__()
kendi ağırlıkları bina tetiğe.
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()
metodu
Yazarken call()
bir katmanın yöntemini, size eğitim döngü yazarken daha sonra kullanmak istediğiniz edeceği kaybı tensörleri oluşturabilir. Bu arayarak yapılabilir olduğunu 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
(Herhangi bir iç tabaka ile oluşturulanlar dahil olmak üzere), bu kayıplar ile alınabilir layer.losses
. Bu özellik her başlangıcında sıfırlanır __call__()
böylece, üst düzey katmana layer.losses
daima son ileriye geçiş sırasında oluşturulan kayıp değerleri içerir.
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
Buna ek olarak, loss
özelliği de bir iç katmanın ağırlıkları için oluşturulan düzenlilestirme kayıplarını içerir:
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>]
Bu kayıplar, aşağıdaki gibi eğitim döngüleri yazılırken dikkate alınmalıdır:
# 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))
Eğitim döngüler yazma konusunda detaylı bir kılavuz için, bkz sıfırdan bir eğitim döngü yazma kılavuzuna .
Bu kayıplar da ile sorunsuz çalışacak fit()
(varsa bunlar otomatik ana kaybına toplanır ve ekledi olsun):
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()
metodu
Benzer için add_loss()
, tabakalar da bir bilgisi add_metric()
eğitimi sırasında bir miktar hareketli ortalama izleme için bir yöntem.
Şu katmanı göz önünde bulundurun: bir "lojistik uç nokta" katmanı. Girişler tahminler & hedefler, bunun aracılığıyla izleyen bir kayıp hesaplar gibi sürer add_loss()
ve bunun aracılığıyla izleyen bir doğruluk sayıl, hesaplar 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)
Bu şekilde takip Metrik yoluyla erişilebilir 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
Sadece için benzeri add_loss()
bu ölçümler tarafından izlenir 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>
Katmanlarınızda isteğe bağlı olarak serileştirmeyi etkinleştirebilirsiniz
Eğer bir parçası olarak seri hale getirilebilir olması için özel katmanlar gerekiyorsa Fonksiyonel modelin , isteğe bağlı olarak bir uygulayabilirsiniz get_config()
yöntemini:
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}
O Not __init__()
baz yöntemi Layer
sınıfında özellikle bir de, bazı anahtar kelime argüman alır name
ve dtype
. Bu içinde üst sınıfa bu argümanları geçmek iyi bir uygulamadır __init__()
ve katman config dahil etmek:
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}
Onun yapılandırmasındaki tabakasını deserializing yaparken daha fazla esneklik gerekiyorsa, ayrıca geçersiz kılabilir from_config()
sınıfı yöntemini. Bu taban uygulamasıdır from_config()
:
def from_config(cls, config):
return cls(**config)
Serileştirme ve kaydetme hakkında daha fazla bilgi edinmek için komple bkz tasarrufu ve modelleri seri için rehber .
İmtiyazlı training
içinde argüman call()
yöntemiyle
Bazı katmanlar, özellikle BatchNormalization
katmanı ve Dropout
tabakası, eğitim ve çıkarsama sırasında farklı davranışlara sahip. Örneğin katman için, bir açığa standart bir uygulamadır training
içinde (boolean) argüman call()
yöntemiyle.
Bu argüman teşhir ederek call()
, yerleşik eğitim ve değerlendirme döngüler (örneğin etkinleştirmek fit()
doğru bir şekilde çalışma ve çıkarım katmanı kullanmak için).
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
İmtiyazlı mask
içinde argüman call()
yöntemiyle
Tarafından desteklenen diğer ayrıcalıklı argüman call()
olan mask
argüman.
Bunu tüm Keras RNN katmanlarında bulacaksınız. Maske, zaman serisi verilerini işlerken belirli giriş zaman adımlarını atlamak için kullanılan bir boole tensörüdür (girişteki zaman adımı başına bir boole değeri).
Keras otomatik olarak doğru geçecek mask
için bağımsız değişkeni __call__()
bir maske önceki tabaka ile üretildiğinde, bu destek katmanları. Maske üreten tabakalardır Embedding
ile yapılandırılmış tabaka mask_zero=True
ve Masking
tabakası.
Daha maskeleme ve nasıl yazmaya özellikli maskeleme katmanları hakkında bilgi edinmek için rehber kontrol edin "dolgu anlamak ve maskeleme" .
Model
sınıfı
Genel olarak, kullanmak olacaktır Layer
iç hesaplama blokları tanımlama sınıf ve kullanır Model
dış modeli tanımlamak için sınıf - antrenman nesneyi.
Örneğin, bir ResNet50 modelinde, sen sınıflara birkaç ResNet blokları olurdu Layer
ve tek Model
tüm ResNet50 ağını kapsayan.
Model
sınıfı ile aynı API vardır Layer
, aşağıda farklılıklar:
- Bu yerleşik açığa eğitim, değerlendirme ve öngörü döngüler (
model.fit()
,model.evaluate()
,model.predict()
). - Bu yoluyla, iç katman listesi ortaya
model.layers
özelliği. - Bu tasarruf ve seri hale API'leri ortaya (
save()
,save_weights()
...)
Etkin bir şekilde, Layer
ne "blok ResNet" de olduğu gibi (( "kıvrım tabaka" ya da "tekrarlayan tabaka" olduğu gibi) ya da bir "blok" olarak bir "kat" olarak literatürde bakın veya "Başlangıç blok" sınıf karşılık ).
Bu arada, Model
( "derin sinir ağı" gibi) ( "derin öğrenme modelinin" de olduğu gibi) ya da bir "ağ" olarak, bir "model" olarak literatürde adlandırılan sınıf denk gelmektedir.
Eğer merak ediyorsanız eğer öyleyse, "kullanmalıyım Layer
sınıf veya Model
sınıfı?" Diye sorun: çağrı gerekir fit()
Üzerinde? Aramaya gerekecek mi save()
üzerinde? Eğer öyleyse, ile gitmek Model
. Değilse (ya da sınıf daha büyük sisteminde sadece bir blok ya da çünkü eğitim yazma ve kodu kendiniz tasarruf çünkü), kullanım Layer
.
Mesela, bizim mini resnet örneği yukarıda almak ve bir inşa için kullanabilir Model
biz eğitebilmeyi fit()
ve biz birlikte kurtarabilecek 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)
Hepsini bir araya getirmek: uçtan uca bir örnek
İşte şimdiye kadar öğrendikleriniz:
- Bir
Layer
bir durum (oluşturulan kapsül__init__()
ya dabuild()
) ve bazı hesaplama (tanımlanmışcall()
). - Katmanlar, yeni, daha büyük hesaplama blokları oluşturmak için özyinelemeli olarak iç içe yerleştirilebilir.
- Oluşturabilir Katmanlar ve parça kayıpları (genellikle düzenlileştirme kayıpları) yanı sıra ölçümlerini aracılığıyla
add_loss()
veadd_metric()
- Dış kap, alıştırma yapmak istediğiniz şey, bir olduğunu
Model
. BirModel
sadece gibidirLayer
, ancak ilave eğitim ve seri ekipmana sahip.
Tüm bunları uçtan uca bir örnekte bir araya getirelim: Variational AutoEncoder (VAE) uygulayacağız. MNIST rakamlarıyla eğiteceğiz.
Bizim VAE bir alt sınıfı olacaktır Model
alt sınıf olduğunu tabakaların iç içe geçmiş bir kompozisyon olarak inşa Layer
. Bir düzenleme kaybı (KL sapması) içerecektir.
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 üzerinde basit bir eğitim döngüsü yazalım:
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 sınıflara beri unutmayın Model
, bu yerleşik özellikleri eğitim döngüler. Yani onu şu şekilde de eğitebilirdin:
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>
Nesneye yönelik geliştirmenin ötesinde: İşlevsel API
Bu örnek sizin için çok fazla nesne yönelimli geliştirme miydi? Ayrıca kullanarak model oluşturabilir Fonksiyonel API . Daha da önemlisi, bir stil veya diğerini seçmek, diğer stilde yazılmış bileşenlerden yararlanmanızı engellemez: her zaman karıştırıp eşleştirebilirsiniz.
Örneğin, tekrar kullanım altında fonksiyonel API örnek, aynı Sampling
tabakası biz, örneğin, yukarıda tanımlanan:
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>
Daha fazla bilgi için, okumak için emin olun Fonksiyonel API kılavuzu .