![]() | ![]() | ![]() | ![]() |
Kurmak
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
Tanıtım
Keras fonksiyonel API daha esnektir modelini oluşturmak için bir yöntemdir tf.keras.Sequential
API. İşlevsel API, doğrusal olmayan topolojiye, paylaşılan katmanlara ve hatta birden çok girdi veya çıktıya sahip modelleri işleyebilir.
Ana fikir, bir derin öğrenme modelinin genellikle katmanların yönlendirilmiş bir döngüsel grafiği (DAG) olmasıdır. Fonksiyonel API Yani tabakaların grafikleri inşa etmek için bir yoldur.
Aşağıdaki modeli göz önünde bulundurun:
(input: 784-dimensional vectors)
↧
[Dense (64 units, relu activation)]
↧
[Dense (64 units, relu activation)]
↧
[Dense (10 units, softmax activation)]
↧
(output: logits of a probability distribution over 10 classes)
Bu, üç katmanlı temel bir grafiktir. İşlevsel API'yi kullanarak bu modeli oluşturmak için bir giriş düğümü oluşturarak başlayın:
inputs = keras.Input(shape=(784,))
Verinin şekli 784 boyutlu bir vektör olarak ayarlanır. Parti boyutu her zaman atlanır çünkü her örneğin sadece şekli belirtilir.
Örneğin, Eğer bir şekle sahip olan bir görüntü girişi varsa (32, 32, 3)
, kullanmak olacaktır:
# Just for demonstration purposes.
img_inputs = keras.Input(shape=(32, 32, 3))
inputs
döndürülen şekil ve hakkında bilgi içerir dtype
size modeline besleyenler girdi verilerinin. İşte şekil:
inputs.shape
TensorShape([None, 784])
İşte tip:
inputs.dtype
tf.float32
Buna bir tabaka arayarak tabakaların grafikte yeni bir düğümün yaratılması inputs
nesne:
dense = layers.Dense(64, activation="relu")
x = dense(inputs)
"Katman çağırma" eylemi, oluşturduğunuz bu katmana "girdilerden" bir ok çizmeye benzer. Sen sizsiniz, girdileri "geçen" dense
tabakası ve aldığınız x
çıktı olarak.
Katman grafiğine birkaç katman daha ekleyelim:
x = layers.Dense(64, activation="relu")(x)
outputs = layers.Dense(10)(x)
Bu noktada, bir oluşturabilir Model
tabakalarının grafikte kendi giriş ve çıkışları ile belirli:
model = keras.Model(inputs=inputs, outputs=outputs, name="mnist_model")
Model özetinin nasıl göründüğüne bakalım:
model.summary()
Model: "mnist_model" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) [(None, 784)] 0 _________________________________________________________________ dense (Dense) (None, 64) 50240 _________________________________________________________________ dense_1 (Dense) (None, 64) 4160 _________________________________________________________________ dense_2 (Dense) (None, 10) 650 ================================================================= Total params: 55,050 Trainable params: 55,050 Non-trainable params: 0 _________________________________________________________________
Modeli bir grafik olarak da çizebilirsiniz:
keras.utils.plot_model(model, "my_first_model.png")
Ve isteğe bağlı olarak, çizilen grafikte her katmanın giriş ve çıkış şekillerini görüntüleyin:
keras.utils.plot_model(model, "my_first_model_with_shape_info.png", show_shapes=True)
Bu şekil ve kod hemen hemen aynıdır. Kod versiyonunda, bağlantı okları çağrı işlemi ile değiştirilir.
"Katman grafiği", derin öğrenme modeli için sezgisel bir zihinsel görüntüdür ve işlevsel API, bunu yakından yansıtan modeller oluşturmanın bir yoludur.
Eğitim, değerlendirme ve çıkarım
Tam gelince fonksiyonel API kullanarak inşa modeller için aynı şekilde eğitim, değerlendirme ve çıkarım çalışmaları Sequential
modelleri.
Model
sınıf teklifler yerleşik bir eğitim döngüsü ( fit()
yöntemi) ve yerleşik bir değerlendirme döngü ( evaluate()
yöntemi). Kolayca ki Not bu döngüler özelleştirmek denetimli öğrenme ötesinde (örneğin eğitim rutinleri uygulamak Gans ).
Burada, MNIST görüntü verilerini yükleyin, vektörlere yeniden şekillendirin, modeli verilere sığdırın (bir doğrulama bölünmesinde performansı izlerken), ardından modeli test verileri üzerinde değerlendirin:
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype("float32") / 255
x_test = x_test.reshape(10000, 784).astype("float32") / 255
model.compile(
loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
optimizer=keras.optimizers.RMSprop(),
metrics=["accuracy"],
)
history = model.fit(x_train, y_train, batch_size=64, epochs=2, validation_split=0.2)
test_scores = model.evaluate(x_test, y_test, verbose=2)
print("Test loss:", test_scores[0])
print("Test accuracy:", test_scores[1])
Epoch 1/2 750/750 [==============================] - 3s 3ms/step - loss: 0.3430 - accuracy: 0.9035 - val_loss: 0.1851 - val_accuracy: 0.9463 Epoch 2/2 750/750 [==============================] - 2s 3ms/step - loss: 0.1585 - accuracy: 0.9527 - val_loss: 0.1366 - val_accuracy: 0.9597 313/313 - 0s - loss: 0.1341 - accuracy: 0.9592 Test loss: 0.13414572179317474 Test accuracy: 0.9592000246047974
Daha fazla okumak için bkz eğitim ve değerlendirme kılavuzu.
Kaydet ve seri hale getir
Modeli ve seri hale esere onlar için ne kadar işlevsel API kullanarak inşa modeller için aynı şekilde kaydetme Sequential
modelleri. Fonksiyonel bir modelini kurtarmak için standart bir yol çağırmaktır model.save()
tek bir dosya olarak tüm modeli kaydedin. Modeli oluşturan kod artık mevcut olmasa bile, daha sonra aynı modeli bu dosyadan yeniden oluşturabilirsiniz.
Bu kaydedilen dosya şunları içerir:
- model mimarisi
- model ağırlık değerleri (eğitim sırasında öğrenilen)
- model eğitim yapılandırma, varsa (geçirilen olarak
compile
) - optimize edici ve varsa durumu (eğitimi kaldığınız yerden yeniden başlatmak için)
model.save("path_to_my_model")
del model
# Recreate the exact same model purely from the file:
model = keras.models.load_model("path_to_my_model")
2021-08-25 17:50:55.989736: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. INFO:tensorflow:Assets written to: path_to_my_model/assets
Ayrıntılar için, modeli okumak seri & tasarrufu kılavuzu.
Birden çok model tanımlamak için aynı katman grafiğini kullanın
İşlevsel API'de modeller, girdileri ve çıktıları bir katman grafiğinde belirtilerek oluşturulur. Bu, birden fazla model oluşturmak için tek bir katman grafiğinin kullanılabileceği anlamına gelir.
Aşağıdaki örnekte, iki model örneğini aynı katman yığını kullanın: Bir encoder
bir model olduğu 16-boyutlu bir vektörleri içine döner görüntü girişi ve bir uç-uca autoencoder
eğitim modeli.
encoder_input = keras.Input(shape=(28, 28, 1), name="img")
x = layers.Conv2D(16, 3, activation="relu")(encoder_input)
x = layers.Conv2D(32, 3, activation="relu")(x)
x = layers.MaxPooling2D(3)(x)
x = layers.Conv2D(32, 3, activation="relu")(x)
x = layers.Conv2D(16, 3, activation="relu")(x)
encoder_output = layers.GlobalMaxPooling2D()(x)
encoder = keras.Model(encoder_input, encoder_output, name="encoder")
encoder.summary()
x = layers.Reshape((4, 4, 1))(encoder_output)
x = layers.Conv2DTranspose(16, 3, activation="relu")(x)
x = layers.Conv2DTranspose(32, 3, activation="relu")(x)
x = layers.UpSampling2D(3)(x)
x = layers.Conv2DTranspose(16, 3, activation="relu")(x)
decoder_output = layers.Conv2DTranspose(1, 3, activation="relu")(x)
autoencoder = keras.Model(encoder_input, decoder_output, name="autoencoder")
autoencoder.summary()
Model: "encoder" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= img (InputLayer) [(None, 28, 28, 1)] 0 _________________________________________________________________ conv2d (Conv2D) (None, 26, 26, 16) 160 _________________________________________________________________ conv2d_1 (Conv2D) (None, 24, 24, 32) 4640 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 8, 8, 32) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 6, 6, 32) 9248 _________________________________________________________________ conv2d_3 (Conv2D) (None, 4, 4, 16) 4624 _________________________________________________________________ global_max_pooling2d (Global (None, 16) 0 ================================================================= Total params: 18,672 Trainable params: 18,672 Non-trainable params: 0 _________________________________________________________________ Model: "autoencoder" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= img (InputLayer) [(None, 28, 28, 1)] 0 _________________________________________________________________ conv2d (Conv2D) (None, 26, 26, 16) 160 _________________________________________________________________ conv2d_1 (Conv2D) (None, 24, 24, 32) 4640 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 8, 8, 32) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 6, 6, 32) 9248 _________________________________________________________________ conv2d_3 (Conv2D) (None, 4, 4, 16) 4624 _________________________________________________________________ global_max_pooling2d (Global (None, 16) 0 _________________________________________________________________ reshape (Reshape) (None, 4, 4, 1) 0 _________________________________________________________________ conv2d_transpose (Conv2DTran (None, 6, 6, 16) 160 _________________________________________________________________ conv2d_transpose_1 (Conv2DTr (None, 8, 8, 32) 4640 _________________________________________________________________ up_sampling2d (UpSampling2D) (None, 24, 24, 32) 0 _________________________________________________________________ conv2d_transpose_2 (Conv2DTr (None, 26, 26, 16) 4624 _________________________________________________________________ conv2d_transpose_3 (Conv2DTr (None, 28, 28, 1) 145 ================================================================= Total params: 28,241 Trainable params: 28,241 Non-trainable params: 0 _________________________________________________________________
Çıktı şekli girdi şekli ile aynıdır, bu nedenle burada dekode mimari, kodlama mimarisi tamamen simetrik olan (28, 28, 1)
.
Bir ters Conv2D
tabakası a, Conv2DTranspose
tabakası ve bir arka MaxPooling2D
tabakası bir olduğunu UpSampling2D
katmanı.
Tüm modeller, katmanlar gibi çağrılabilir
Bir onu çağırarak bir katman sanki herhangi modeli tedavi edebilir Input
ya da başka bir katmanın çıkışı üzerine. Bir modeli çağırarak, sadece modelin mimarisini yeniden kullanmıyorsunuz, aynı zamanda ağırlıklarını da yeniden kullanıyorsunuz.
Bunu çalışırken görmek için, bir kodlayıcı modeli, bir kod çözücü modeli oluşturan ve bunları otomatik kodlayıcı modelini elde etmek için iki çağrıda zincirleyen otomatik kodlayıcı örneğine farklı bir bakış:
encoder_input = keras.Input(shape=(28, 28, 1), name="original_img")
x = layers.Conv2D(16, 3, activation="relu")(encoder_input)
x = layers.Conv2D(32, 3, activation="relu")(x)
x = layers.MaxPooling2D(3)(x)
x = layers.Conv2D(32, 3, activation="relu")(x)
x = layers.Conv2D(16, 3, activation="relu")(x)
encoder_output = layers.GlobalMaxPooling2D()(x)
encoder = keras.Model(encoder_input, encoder_output, name="encoder")
encoder.summary()
decoder_input = keras.Input(shape=(16,), name="encoded_img")
x = layers.Reshape((4, 4, 1))(decoder_input)
x = layers.Conv2DTranspose(16, 3, activation="relu")(x)
x = layers.Conv2DTranspose(32, 3, activation="relu")(x)
x = layers.UpSampling2D(3)(x)
x = layers.Conv2DTranspose(16, 3, activation="relu")(x)
decoder_output = layers.Conv2DTranspose(1, 3, activation="relu")(x)
decoder = keras.Model(decoder_input, decoder_output, name="decoder")
decoder.summary()
autoencoder_input = keras.Input(shape=(28, 28, 1), name="img")
encoded_img = encoder(autoencoder_input)
decoded_img = decoder(encoded_img)
autoencoder = keras.Model(autoencoder_input, decoded_img, name="autoencoder")
autoencoder.summary()
Model: "encoder" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= original_img (InputLayer) [(None, 28, 28, 1)] 0 _________________________________________________________________ conv2d_4 (Conv2D) (None, 26, 26, 16) 160 _________________________________________________________________ conv2d_5 (Conv2D) (None, 24, 24, 32) 4640 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 8, 8, 32) 0 _________________________________________________________________ conv2d_6 (Conv2D) (None, 6, 6, 32) 9248 _________________________________________________________________ conv2d_7 (Conv2D) (None, 4, 4, 16) 4624 _________________________________________________________________ global_max_pooling2d_1 (Glob (None, 16) 0 ================================================================= Total params: 18,672 Trainable params: 18,672 Non-trainable params: 0 _________________________________________________________________ Model: "decoder" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= encoded_img (InputLayer) [(None, 16)] 0 _________________________________________________________________ reshape_1 (Reshape) (None, 4, 4, 1) 0 _________________________________________________________________ conv2d_transpose_4 (Conv2DTr (None, 6, 6, 16) 160 _________________________________________________________________ conv2d_transpose_5 (Conv2DTr (None, 8, 8, 32) 4640 _________________________________________________________________ up_sampling2d_1 (UpSampling2 (None, 24, 24, 32) 0 _________________________________________________________________ conv2d_transpose_6 (Conv2DTr (None, 26, 26, 16) 4624 _________________________________________________________________ conv2d_transpose_7 (Conv2DTr (None, 28, 28, 1) 145 ================================================================= Total params: 9,569 Trainable params: 9,569 Non-trainable params: 0 _________________________________________________________________ Model: "autoencoder" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= img (InputLayer) [(None, 28, 28, 1)] 0 _________________________________________________________________ encoder (Functional) (None, 16) 18672 _________________________________________________________________ decoder (Functional) (None, 28, 28, 1) 9569 ================================================================= Total params: 28,241 Trainable params: 28,241 Non-trainable params: 0 _________________________________________________________________
Gördüğünüz gibi, model iç içe olabilir: bir model alt modeller içerebilir (çünkü bir model bir katman gibidir). Model yuvalama için yaygın bir kullanım durumu asamblesi edilir. Örneğin, bir dizi modeli, tahminlerinin ortalamasını alan tek bir modelde nasıl birleştireceğiniz aşağıda açıklanmıştır:
def get_model():
inputs = keras.Input(shape=(128,))
outputs = layers.Dense(1)(inputs)
return keras.Model(inputs, outputs)
model1 = get_model()
model2 = get_model()
model3 = get_model()
inputs = keras.Input(shape=(128,))
y1 = model1(inputs)
y2 = model2(inputs)
y3 = model3(inputs)
outputs = layers.average([y1, y2, y3])
ensemble_model = keras.Model(inputs=inputs, outputs=outputs)
Karmaşık grafik topolojilerini yönetin
Çoklu giriş ve çıkışlı modeller
İşlevsel API, birden çok giriş ve çıkışı değiştirmeyi kolaylaştırır. Bu ele alınamaz Sequential
API.
Örneğin, müşteri sorun biletlerini önceliğe göre sıralamak ve bunları doğru departmana yönlendirmek için bir sistem oluşturuyorsanız, modelin üç girişi olacaktır:
- biletin başlığı (metin girişi),
- biletin metin gövdesi (metin girişi) ve
- kullanıcı tarafından eklenen herhangi bir etiket (kategorik giriş)
Bu modelin iki çıktısı olacaktır:
- 0 ile 1 arasındaki öncelik puanı (skaler sigmoid çıktısı) ve
- bileti işlemesi gereken departman (departmanlar kümesi üzerinden softmax çıktısı).
İşlevsel API ile bu modeli birkaç satırda oluşturabilirsiniz:
num_tags = 12 # Number of unique issue tags
num_words = 10000 # Size of vocabulary obtained when preprocessing text data
num_departments = 4 # Number of departments for predictions
title_input = keras.Input(
shape=(None,), name="title"
) # Variable-length sequence of ints
body_input = keras.Input(shape=(None,), name="body") # Variable-length sequence of ints
tags_input = keras.Input(
shape=(num_tags,), name="tags"
) # Binary vectors of size `num_tags`
# Embed each word in the title into a 64-dimensional vector
title_features = layers.Embedding(num_words, 64)(title_input)
# Embed each word in the text into a 64-dimensional vector
body_features = layers.Embedding(num_words, 64)(body_input)
# Reduce sequence of embedded words in the title into a single 128-dimensional vector
title_features = layers.LSTM(128)(title_features)
# Reduce sequence of embedded words in the body into a single 32-dimensional vector
body_features = layers.LSTM(32)(body_features)
# Merge all available features into a single large vector via concatenation
x = layers.concatenate([title_features, body_features, tags_input])
# Stick a logistic regression for priority prediction on top of the features
priority_pred = layers.Dense(1, name="priority")(x)
# Stick a department classifier on top of the features
department_pred = layers.Dense(num_departments, name="department")(x)
# Instantiate an end-to-end model predicting both priority and department
model = keras.Model(
inputs=[title_input, body_input, tags_input],
outputs=[priority_pred, department_pred],
)
Şimdi modeli çizin:
keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True)
Bu modeli derlerken her bir çıktıya farklı kayıplar atayabilirsiniz. Toplam eğitim kaybına katkılarını modüle etmek için her bir kayba farklı ağırlıklar bile atayabilirsiniz.
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=[
keras.losses.BinaryCrossentropy(from_logits=True),
keras.losses.CategoricalCrossentropy(from_logits=True),
],
loss_weights=[1.0, 0.2],
)
Çıktı katmanlarının adları farklı olduğundan, ilgili katman adlarıyla kayıp ve kayıp ağırlıkları da belirtebilirsiniz:
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss={
"priority": keras.losses.BinaryCrossentropy(from_logits=True),
"department": keras.losses.CategoricalCrossentropy(from_logits=True),
},
loss_weights={"priority": 1.0, "department": 0.2},
)
NumPy girdi ve hedef dizilerinin listelerini ileterek modeli eğitin:
# Dummy input data
title_data = np.random.randint(num_words, size=(1280, 10))
body_data = np.random.randint(num_words, size=(1280, 100))
tags_data = np.random.randint(2, size=(1280, num_tags)).astype("float32")
# Dummy target data
priority_targets = np.random.random(size=(1280, 1))
dept_targets = np.random.randint(2, size=(1280, num_departments))
model.fit(
{"title": title_data, "body": body_data, "tags": tags_data},
{"priority": priority_targets, "department": dept_targets},
epochs=2,
batch_size=32,
)
Epoch 1/2 40/40 [==============================] - 5s 9ms/step - loss: 1.2899 - priority_loss: 0.7186 - department_loss: 2.8564 Epoch 2/2 40/40 [==============================] - 0s 9ms/step - loss: 1.2668 - priority_loss: 0.6991 - department_loss: 2.8389 <keras.callbacks.History at 0x7fc1a66dc790>
Bir ile uyum ararken Dataset
nesnesi, bu gibi listeleri bir demet ya vermelidir ([title_data, body_data, tags_data], [priority_targets, dept_targets])
ya da bu gibi sözlük bir başlığın ({'title': title_data, 'body': body_data, 'tags': tags_data}, {'priority': priority_targets, 'department': dept_targets})
.
Daha ayrıntılı açıklama için bkz eğitim ve değerlendirme rehberi.
Bir oyuncak ResNet modeli
Birden fazla giriş ve çıkışları olan modellerde ek olarak, işlevsel bir API kolay doğrusal olmayan bağlantı topolojisini değiştirmek mümkün kılar - bu sırayla bağlı olmayan katmanlar, birlikte modelleri Sequential
API işleyemez.
Bunun için yaygın bir kullanım durumu, artık bağlantılardır. Bunu göstermek için CIFAR10 için bir oyuncak ResNet modeli oluşturalım:
inputs = keras.Input(shape=(32, 32, 3), name="img")
x = layers.Conv2D(32, 3, activation="relu")(inputs)
x = layers.Conv2D(64, 3, activation="relu")(x)
block_1_output = layers.MaxPooling2D(3)(x)
x = layers.Conv2D(64, 3, activation="relu", padding="same")(block_1_output)
x = layers.Conv2D(64, 3, activation="relu", padding="same")(x)
block_2_output = layers.add([x, block_1_output])
x = layers.Conv2D(64, 3, activation="relu", padding="same")(block_2_output)
x = layers.Conv2D(64, 3, activation="relu", padding="same")(x)
block_3_output = layers.add([x, block_2_output])
x = layers.Conv2D(64, 3, activation="relu")(block_3_output)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(256, activation="relu")(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(10)(x)
model = keras.Model(inputs, outputs, name="toy_resnet")
model.summary()
Model: "toy_resnet" __________________________________________________________________________________________________ Layer (type) Output Shape Param # Connected to ================================================================================================== img (InputLayer) [(None, 32, 32, 3)] 0 __________________________________________________________________________________________________ conv2d_8 (Conv2D) (None, 30, 30, 32) 896 img[0][0] __________________________________________________________________________________________________ conv2d_9 (Conv2D) (None, 28, 28, 64) 18496 conv2d_8[0][0] __________________________________________________________________________________________________ max_pooling2d_2 (MaxPooling2D) (None, 9, 9, 64) 0 conv2d_9[0][0] __________________________________________________________________________________________________ conv2d_10 (Conv2D) (None, 9, 9, 64) 36928 max_pooling2d_2[0][0] __________________________________________________________________________________________________ conv2d_11 (Conv2D) (None, 9, 9, 64) 36928 conv2d_10[0][0] __________________________________________________________________________________________________ add (Add) (None, 9, 9, 64) 0 conv2d_11[0][0] max_pooling2d_2[0][0] __________________________________________________________________________________________________ conv2d_12 (Conv2D) (None, 9, 9, 64) 36928 add[0][0] __________________________________________________________________________________________________ conv2d_13 (Conv2D) (None, 9, 9, 64) 36928 conv2d_12[0][0] __________________________________________________________________________________________________ add_1 (Add) (None, 9, 9, 64) 0 conv2d_13[0][0] add[0][0] __________________________________________________________________________________________________ conv2d_14 (Conv2D) (None, 7, 7, 64) 36928 add_1[0][0] __________________________________________________________________________________________________ global_average_pooling2d (Globa (None, 64) 0 conv2d_14[0][0] __________________________________________________________________________________________________ dense_6 (Dense) (None, 256) 16640 global_average_pooling2d[0][0] __________________________________________________________________________________________________ dropout (Dropout) (None, 256) 0 dense_6[0][0] __________________________________________________________________________________________________ dense_7 (Dense) (None, 10) 2570 dropout[0][0] ================================================================================================== Total params: 223,242 Trainable params: 223,242 Non-trainable params: 0 __________________________________________________________________________________________________
Modeli çizin:
keras.utils.plot_model(model, "mini_resnet.png", show_shapes=True)
Şimdi modeli eğitin:
(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()
x_train = x_train.astype("float32") / 255.0
x_test = x_test.astype("float32") / 255.0
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)
model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss=keras.losses.CategoricalCrossentropy(from_logits=True),
metrics=["acc"],
)
# We restrict the data to the first 1000 samples so as to limit execution time
# on Colab. Try to train on the entire dataset until convergence!
model.fit(x_train[:1000], y_train[:1000], batch_size=64, epochs=1, validation_split=0.2)
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 170500096/170498071 [==============================] - 11s 0us/step 170508288/170498071 [==============================] - 11s 0us/step 13/13 [==============================] - 2s 29ms/step - loss: 2.3364 - acc: 0.1063 - val_loss: 2.2986 - val_acc: 0.0850 <keras.callbacks.History at 0x7fc19df22610>
Paylaşılan katmanlar
Fonksiyonel API diğer bir avantajı paylaşılan katmanları kullanmak modellerdir. Paylaşılan katmanlar, aynı modelde birden çok kez yeniden kullanılan katman örnekleridir -- katman grafiğindeki birden çok yola karşılık gelen özellikleri öğrenirler.
Paylaşılan katmanlar genellikle benzer alanlardan gelen girdileri kodlamak için kullanılır (örneğin, benzer kelime dağarcığına sahip iki farklı metin parçası). Bu farklı girdiler arasında bilgi paylaşımını mümkün kılarlar ve böyle bir modelin daha az veri üzerinde eğitilmesini mümkün kılarlar. Girdilerden birinde belirli bir kelime görülürse, bu, paylaşılan katmandan geçen tüm girdilerin işlenmesine fayda sağlayacaktır.
İşlevsel API'de bir katmanı paylaşmak için aynı katman örneğini birden çok kez çağırın. Örneğin, burada bir var Embedding
iki farklı metin girişleri arasında paylaşılır katman:
# Embedding for 1000 unique words mapped to 128-dimensional vectors
shared_embedding = layers.Embedding(1000, 128)
# Variable-length sequence of integers
text_input_a = keras.Input(shape=(None,), dtype="int32")
# Variable-length sequence of integers
text_input_b = keras.Input(shape=(None,), dtype="int32")
# Reuse the same layer to encode both inputs
encoded_input_a = shared_embedding(text_input_a)
encoded_input_b = shared_embedding(text_input_b)
Katman grafiğindeki düğümleri ayıklayın ve yeniden kullanın
Manipüle ettiğiniz katmanların grafiği statik bir veri yapısı olduğu için erişilebilir ve incelenebilir. Ve bu şekilde işlevsel modelleri görüntü olarak çizebilirsiniz.
Bu ayrıca, ara katmanların (grafikteki "düğümler") aktivasyonlarına erişebileceğiniz ve bunları başka bir yerde yeniden kullanabileceğiniz anlamına gelir; bu, özellik çıkarma gibi bir şey için çok faydalıdır.
Bir örneğe bakalım. Bu, ağırlıkları ImageNet üzerinde önceden eğitilmiş bir VGG19 modelidir:
vgg19 = tf.keras.applications.VGG19()
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg19/vgg19_weights_tf_dim_ordering_tf_kernels.h5 574717952/574710816 [==============================] - 15s 0us/step 574726144/574710816 [==============================] - 15s 0us/step
Ve bunlar, grafik veri yapısını sorgulayarak elde edilen modelin ara aktivasyonlarıdır:
features_list = [layer.output for layer in vgg19.layers]
Ara katman aktivasyonlarının değerlerini döndüren yeni bir özellik çıkarma modeli oluşturmak için bu özellikleri kullanın:
feat_extraction_model = keras.Model(inputs=vgg19.input, outputs=features_list)
img = np.random.random((1, 224, 224, 3)).astype("float32")
extracted_features = feat_extraction_model(img)
Bu gibi görevler için kullanışlı nöral tarzı transferi başka şeylerin yanı sıra,.
Özel katmanları kullanarak API'yi genişletin
tf.keras
geniş bir yelpazede Dahili katmanlar, örneğin:
- Evrişimsel katmanları:
Conv1D
,Conv2D
,Conv3D
,Conv2DTranspose
- Havuzlaması katmanları:
MaxPooling1D
,MaxPooling2D
,MaxPooling3D
,AveragePooling1D
- RYSA katmanları:
GRU
,LSTM
,ConvLSTM2D
-
BatchNormalization
,Dropout
,Embedding
vb
Ancak ihtiyacınız olanı bulamazsanız, kendi katmanlarınızı oluşturarak API'yi genişletmek kolaydır. Tüm katmanlar alt sınıf Layer
sınıfını ve uygulamak:
-
call
yöntemi, yani belirtir katmanı tarafından yapılan hesaplama. -
build
tabakasının ağırlıklarını oluşturan yöntem, (eğer ağırlıkları oluşturabilir beri bu sadece bir stil kuralıdır__init__
sıra).
Sıfırdan katmanları oluşturma hakkında daha fazla bilgi edinmek okumak için özel katmanlar ve modelleri kılavuzu.
Aşağıdaki temel bir uygulamasıdır tf.keras.layers.Dense
:
class CustomDense(layers.Layer):
def __init__(self, units=32):
super(CustomDense, 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
inputs = keras.Input((4,))
outputs = CustomDense(10)(inputs)
model = keras.Model(inputs, outputs)
Özel tabakasında seri destek, bir tanımlayan get_config
bir katman, örneğin kurucu bağımsız döner yöntem:
class CustomDense(layers.Layer):
def __init__(self, units=32):
super(CustomDense, 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}
inputs = keras.Input((4,))
outputs = CustomDense(10)(inputs)
model = keras.Model(inputs, outputs)
config = model.get_config()
new_model = keras.Model.from_config(config, custom_objects={"CustomDense": CustomDense})
İsteğe bağlı olarak, sınıf yöntemi uygulamak from_config(cls, config)
bir tabaka örneği, yapılandırma sözlüğü verilmiştir yeniden zaman kullanılır. Varsayılan uygulama from_config
geçerli:
def from_config(cls, config):
return cls(**config)
İşlevsel API ne zaman kullanılır?
Yeni bir model oluşturmak, ya da sadece alt sınıf Keras fonksiyonel API kullanmalıyım Model
doğrudan sınıfını? Genel olarak, işlevsel API daha yüksek düzeyde, daha kolay ve daha güvenlidir ve alt sınıf modellerin desteklemediği bir dizi özelliğe sahiptir.
Bununla birlikte, model alt sınıflama, yönlendirilmiş döngüsel olmayan katman grafikleri olarak kolayca ifade edilemeyen modeller oluştururken daha fazla esneklik sağlar. Örneğin, fonksiyonel API ile bir Ağaç RNN uygulamak olamazdı ve alt sınıf zorunda kalacak Model
doğrudan.
Fonksiyonel API ve model subclassing arasındaki farklara derinlemesine bir görünüm için, okumak TensorFlow 2.0 Sembolik ve Emir API'ler nelerdir? .
İşlevsel API güçlü yönleri:
Aşağıdaki özellikler sıralı modeller için de geçerlidir (bunlar aynı zamanda veri yapılarıdır), ancak alt sınıflı modeller için doğru değildir (bunlar veri yapıları değil Python bayt kodudur).
Daha az ayrıntılı
Diye bir şey yok super(MyClass, self).__init__(...)
hiç def call(self, ...):
vs.
Karşılaştırmak:
inputs = keras.Input(shape=(32,))
x = layers.Dense(64, activation='relu')(inputs)
outputs = layers.Dense(10)(x)
mlp = keras.Model(inputs, outputs)
Alt sınıf versiyonu ile:
class MLP(keras.Model):
def __init__(self, **kwargs):
super(MLP, self).__init__(**kwargs)
self.dense_1 = layers.Dense(64, activation='relu')
self.dense_2 = layers.Dense(10)
def call(self, inputs):
x = self.dense_1(inputs)
return self.dense_2(x)
# Instantiate the model.
mlp = MLP()
# Necessary to create the model's state.
# The model doesn't have a state until it's called at least once.
_ = mlp(tf.zeros((1, 32)))
Bağlantı grafiğini tanımlarken model doğrulama
Fonksiyonel API, giriş özellikleri (şekil ve d_type) (kullanarak önceden oluşturulur Input
). Bir katmanı her çağırdığınızda, katman kendisine iletilen spesifikasyonun varsayımlarıyla eşleşip eşleşmediğini kontrol eder ve değilse yardımcı bir hata mesajı verir.
Bu, işlevsel API ile oluşturabileceğiniz herhangi bir modelin çalışacağını garanti eder. Yakınsama ile ilgili hata ayıklama dışındaki tüm hata ayıklama, yürütme zamanında değil, model oluşturma sırasında statik olarak gerçekleşir. Bu, bir derleyicide tip denetimine benzer.
İşlevsel bir model çizilebilir ve denetlenebilir
Modeli grafik olarak çizebilir ve bu grafikteki ara düğümlere kolayca ulaşabilirsiniz. Örneğin, ara katmanların aktivasyonlarını çıkarmak ve yeniden kullanmak için (önceki bir örnekte görüldüğü gibi):
features_list = [layer.output for layer in vgg19.layers]
feat_extraction_model = keras.Model(inputs=vgg19.input, outputs=features_list)
İşlevsel bir model seri hale getirilebilir veya klonlanabilir
İşlevsel bir model, bir kod parçasından ziyade bir veri yapısı olduğundan, güvenli bir şekilde seri hale getirilebilir ve orijinal kodlardan herhangi birine erişmeden aynı modeli yeniden oluşturmanıza olanak tanıyan tek bir dosya olarak kaydedilebilir. Bkz seri & tasarrufu kılavuzu .
Bir sınıflandırma modeli seri için, uygulayıcı bir belirlemek için gerekli olan get_config()
ve from_config()
modeli seviyesindeki bir yöntem.
İşlevsel API zayıflığı:
Dinamik mimarileri desteklemiyor
İşlevsel API, modelleri katmanların DAG'leri olarak ele alır. Bu, çoğu derin öğrenme mimarisi için geçerlidir, ancak tümü değil - örneğin, özyinelemeli ağlar veya Ağaç RNN'leri bu varsayımı izlemez ve işlevsel API'de uygulanamaz.
API stillerini karıştır ve eşleştir
İşlevsel API veya Model alt sınıflandırması arasında seçim yapmak, sizi tek bir model kategorisiyle sınırlayan ikili bir karar değildir. Tüm modeller tf.keras
API onlar ister, birbirleriyle etkileşime girebilir Sequential
modelleri, fonksiyonel modeller veya sıfırdan yazılır sınıflandırma modelleri.
Her zaman işlevsel bir model veya kullanabilir Sequential
subclassed model veya katmanın bir parçası olarak modelini:
units = 32
timesteps = 10
input_dim = 5
# Define a Functional model
inputs = keras.Input((None, units))
x = layers.GlobalAveragePooling1D()(inputs)
outputs = layers.Dense(1)(x)
model = keras.Model(inputs, outputs)
class CustomRNN(layers.Layer):
def __init__(self):
super(CustomRNN, self).__init__()
self.units = units
self.projection_1 = layers.Dense(units=units, activation="tanh")
self.projection_2 = layers.Dense(units=units, activation="tanh")
# Our previously-defined Functional model
self.classifier = model
def call(self, inputs):
outputs = []
state = tf.zeros(shape=(inputs.shape[0], self.units))
for t in range(inputs.shape[1]):
x = inputs[:, t, :]
h = self.projection_1(x)
y = h + self.projection_2(state)
state = y
outputs.append(y)
features = tf.stack(outputs, axis=1)
print(features.shape)
return self.classifier(features)
rnn_model = CustomRNN()
_ = rnn_model(tf.zeros((1, timesteps, input_dim)))
(1, 10, 32)
Uzun bir uygulayan kadar işlevsel API herhangi sınıflandırma katmanı veya modeli kullanabilirsiniz call
aşağıdaki desenlerden birini takip yöntemi:
-
call(self, inputs, **kwargs)
-inputs
bir tensör veya tensörlerinin iç içe bir yapı (tensörlerinin örneğin listesi) ve**kwargs
olmayan tensör argümanlar (non-girişler) bulunmaktadır. -
call(self, inputs, training=None, **kwargs)
-training
tabakası eğitim modu ve çıkarsama modunda davranması gerekip gerekmediğini gösteren bir boolean. -
call(self, inputs, mask=None, **kwargs)
-mask
bir boolean maske tensörünü olduğu (örneğin, RNNs için faydalıdır). -
call(self, inputs, training=None, mask=None, **kwargs)
- Tabii ki, aynı anda hem maskeleme ve eğitim özgü davranış olabilir.
Eğer uygulamak Ek olarak, get_config
özel Katmanı veya modele yöntemi, oluşturmak fonksiyonel modeller hala seri hale getirilebilir ve kopyalanabilen olacaktır.
İşlevsel bir modelde kullanılan, sıfırdan yazılmış özel bir RNN'nin hızlı bir örneği:
units = 32
timesteps = 10
input_dim = 5
batch_size = 16
class CustomRNN(layers.Layer):
def __init__(self):
super(CustomRNN, self).__init__()
self.units = units
self.projection_1 = layers.Dense(units=units, activation="tanh")
self.projection_2 = layers.Dense(units=units, activation="tanh")
self.classifier = layers.Dense(1)
def call(self, inputs):
outputs = []
state = tf.zeros(shape=(inputs.shape[0], self.units))
for t in range(inputs.shape[1]):
x = inputs[:, t, :]
h = self.projection_1(x)
y = h + self.projection_2(state)
state = y
outputs.append(y)
features = tf.stack(outputs, axis=1)
return self.classifier(features)
# Note that you specify a static batch size for the inputs with the `batch_shape`
# arg, because the inner computation of `CustomRNN` requires a static batch size
# (when you create the `state` zeros tensor).
inputs = keras.Input(batch_shape=(batch_size, timesteps, input_dim))
x = layers.Conv1D(32, 3)(inputs)
outputs = CustomRNN()(x)
model = keras.Model(inputs, outputs)
rnn_model = CustomRNN()
_ = rnn_model(tf.zeros((1, 10, 5)))