![]() | ![]() | ![]() | ![]() |
सेट अप
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
परिचय
Keras कार्यात्मक एपीआई मॉडल की तुलना में अधिक लचीले होते हैं बनाने के लिए एक रास्ता है tf.keras.Sequential
एपीआई। कार्यात्मक एपीआई गैर-रेखीय टोपोलॉजी, साझा परतों और यहां तक कि कई इनपुट या आउटपुट वाले मॉडल को संभाल सकता है।
मुख्य विचार यह है कि एक गहन शिक्षण मॉडल आमतौर पर परतों का एक निर्देशित चक्रीय ग्राफ (DAG) होता है। कार्यात्मक एपीआई तो परतों के रेखांकन के निर्माण के लिए एक तरीका है।
निम्नलिखित मॉडल पर विचार करें:
(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)
यह तीन परतों वाला एक मूल ग्राफ है। कार्यात्मक एपीआई का उपयोग करके इस मॉडल को बनाने के लिए, एक इनपुट नोड बनाकर शुरू करें:
inputs = keras.Input(shape=(784,))
डेटा का आकार 784-आयामी वेक्टर के रूप में सेट किया गया है। बैच आकार हमेशा छोड़ा जाता है क्योंकि प्रत्येक नमूने का केवल आकार निर्दिष्ट होता है।
हैं, उदाहरण के लिए, आप के आकार के साथ एक छवि इनपुट है (32, 32, 3)
, आप का प्रयोग करेंगे:
# Just for demonstration purposes.
img_inputs = keras.Input(shape=(32, 32, 3))
inputs
कि लौटा दिया जाता है आकार और बारे में जानकारी शामिल dtype
इनपुट डेटा की है कि आप अपने मॉडल के लिए खाते हैं। यहाँ आकार है:
inputs.shape
TensorShape([None, 784])
यहां डीटाइप है:
inputs.dtype
tf.float32
आप इस पर एक परत को फोन करके परतों के ग्राफ में एक नया नोड बनाने inputs
वस्तु:
dense = layers.Dense(64, activation="relu")
x = dense(inputs)
"लेयर कॉल" क्रिया "इनपुट्स" से आपके द्वारा बनाई गई इस लेयर पर एक तीर खींचने की तरह है। आप कर रहे हैं "गुजर" आदानों dense
परत, और आप प्राप्त x
आउटपुट के रूप में।
आइए परतों के ग्राफ़ में कुछ और परतें जोड़ें:
x = layers.Dense(64, activation="relu")(x)
outputs = layers.Dense(10)(x)
इस बिंदु पर, आप एक बना सकते हैं Model
परतों के ग्राफ में अपनी इनपुट और आउटपुट को निर्दिष्ट करके:
model = keras.Model(inputs=inputs, outputs=outputs, name="mnist_model")
आइए देखें कि मॉडल सारांश कैसा दिखता है:
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 _________________________________________________________________
आप मॉडल को ग्राफ़ के रूप में भी प्लॉट कर सकते हैं:
keras.utils.plot_model(model, "my_first_model.png")
और, वैकल्पिक रूप से, प्लॉट किए गए ग्राफ़ में प्रत्येक परत के इनपुट और आउटपुट आकार प्रदर्शित करें:
keras.utils.plot_model(model, "my_first_model_with_shape_info.png", show_shapes=True)
यह आंकड़ा और कोड लगभग समान हैं। कोड संस्करण में, कनेक्शन तीरों को कॉल ऑपरेशन द्वारा बदल दिया जाता है।
एक "परतों का ग्राफ" एक गहन शिक्षण मॉडल के लिए एक सहज मानसिक छवि है, और कार्यात्मक एपीआई मॉडल बनाने का एक तरीका है जो इसे बारीकी से प्रतिबिंबित करता है।
प्रशिक्षण, मूल्यांकन और अनुमान
प्रशिक्षण, मूल्यांकन, और निष्कर्ष काम बिल्कुल के लिए के रूप में कार्यात्मक एपीआई का उपयोग कर निर्मित मॉडलों के लिए उसी तरह से Sequential
मॉडल।
Model
वर्ग प्रदान करता है एक अंतर्निहित प्रशिक्षण लूप ( fit()
विधि) और एक अंतर्निहित मूल्यांकन लूप ( evaluate()
विधि)। ध्यान दें कि आप आसानी से कर सकते हैं इन छोरों को अनुकूलित प्रशिक्षण दिनचर्या देखरेख सीखने से परे (जैसे लागू करने के लिए Gans )।
यहां, एमएनआईएसटी छवि डेटा लोड करें, इसे वैक्टर में दोबारा बदलें, डेटा पर मॉडल फिट करें (सत्यापन विभाजन पर प्रदर्शन की निगरानी करते समय), फिर परीक्षण डेटा पर मॉडल का मूल्यांकन करें:
(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
आगे पढ़ने के लिए, देखें प्रशिक्षण और मूल्यांकन गाइड।
सहेजें और क्रमबद्ध करें
सहेजा जा रहा है मॉडल और क्रमबद्धता काम कार्यात्मक एपीआई का उपयोग कर के रूप में वे के लिए क्या बनाया मॉडलों के लिए उसी तरह Sequential
मॉडल। एक कार्यात्मक मॉडल को बचाने के लिए मानक तरीका कॉल करने के लिए है model.save()
एक एकल फाइल के रूप में पूरे मॉडल को बचाने के लिए। आप बाद में इस फ़ाइल से उसी मॉडल को फिर से बना सकते हैं, भले ही मॉडल बनाने वाला कोड अब उपलब्ध न हो।
इस सहेजी गई फ़ाइल में शामिल हैं:
- मॉडल वास्तुकला
- मॉडल वजन मान (जो प्रशिक्षण के दौरान सीखे गए थे)
- मॉडल प्रशिक्षण config, यदि कोई हो (के लिए पारित रूप में
compile
) - अनुकूलक और उसकी स्थिति, यदि कोई हो (प्रशिक्षण को फिर से शुरू करने के लिए जहां आपने छोड़ा था)
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
जानकारी के लिए, मॉडल पढ़ क्रमबद्धता और बचत गाइड।
एकाधिक मॉडलों को परिभाषित करने के लिए परतों के समान ग्राफ़ का उपयोग करें
कार्यात्मक एपीआई में, मॉडल परतों के ग्राफ में उनके इनपुट और आउटपुट को निर्दिष्ट करके बनाए जाते हैं। इसका मतलब है कि कई मॉडल बनाने के लिए परतों के एकल ग्राफ का उपयोग किया जा सकता है।
नीचे दिए गए उदाहरण में, आप दो मॉडल का दृष्टांत करने के लिए परतों का एक ही ढेर का उपयोग करें: एक encoder
मॉडल है कि 16 आयामी वैक्टर में बदल जाता है छवि आदानों, और एक अंत से अंत autoencoder
प्रशिक्षण के लिए मॉडल।
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 _________________________________________________________________
इधर, डिकोडिंग वास्तुकला इतनी उत्पादन आकार इनपुट आकार के समान है, सख्ती से एन्कोडिंग वास्तुकला के लिए सममित है (28, 28, 1)
।
एक के पीछे Conv2D
परत एक है Conv2DTranspose
परत है, और एक के पीछे MaxPooling2D
परत एक है UpSampling2D
परत।
सभी मॉडल कॉल करने योग्य हैं, बिल्कुल परतों की तरह
आप किसी भी मॉडल का इलाज कर सकते मानो कि यह एक पर यह लागू द्वारा कोई परत हो Input
या एक और परत के उत्पादन पर। एक मॉडल को कॉल करके आप न केवल मॉडल के आर्किटेक्चर का पुन: उपयोग कर रहे हैं, आप इसके वजन का भी पुन: उपयोग कर रहे हैं।
इसे क्रिया में देखने के लिए, यहां ऑटोएन्कोडर उदाहरण पर एक अलग टेक दिया गया है जो एक एन्कोडर मॉडल, एक डिकोडर मॉडल बनाता है, और ऑटोएन्कोडर मॉडल प्राप्त करने के लिए उन्हें दो कॉलों में श्रृंखलाबद्ध करता है:
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 _________________________________________________________________
जैसा कि आप देख सकते हैं, मॉडल को नेस्टेड किया जा सकता है: एक मॉडल में उप-मॉडल हो सकते हैं (चूंकि एक मॉडल एक परत की तरह है)। मॉडल घोंसले के लिए उपयोग आम तौर ensembling है। उदाहरण के लिए, यहां बताया गया है कि मॉडल के एक सेट को एकल मॉडल में कैसे जोड़ा जाए जो उनकी भविष्यवाणियों को औसत करता है:
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)
जटिल ग्राफ टोपोलॉजीज में हेरफेर करें
कई इनपुट और आउटपुट वाले मॉडल
कार्यात्मक एपीआई कई इनपुट और आउटपुट में हेरफेर करना आसान बनाता है। इस के साथ संभाला नहीं जा सकता Sequential
एपीआई।
उदाहरण के लिए, यदि आप प्राथमिकता के आधार पर ग्राहक जारी टिकटों की रैंकिंग के लिए एक प्रणाली बना रहे हैं और उन्हें सही विभाग में भेज रहे हैं, तो मॉडल में तीन इनपुट होंगे:
- टिकट का शीर्षक (पाठ इनपुट),
- टिकट का टेक्स्ट बॉडी (टेक्स्ट इनपुट), और
- उपयोगकर्ता द्वारा जोड़ा गया कोई भी टैग (श्रेणीबद्ध इनपुट)
इस मॉडल में दो आउटपुट होंगे:
- 0 और 1 के बीच प्राथमिकता स्कोर (स्केलर सिग्मॉइड आउटपुट), और
- वह विभाग जिसे टिकट संभालना चाहिए (विभागों के सेट पर सॉफ्टमैक्स आउटपुट)।
आप इस मॉडल को कार्यात्मक एपीआई के साथ कुछ पंक्तियों में बना सकते हैं:
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],
)
अब मॉडल प्लॉट करें:
keras.utils.plot_model(model, "multi_input_and_output_model.png", show_shapes=True)
इस मॉडल को संकलित करते समय, आप प्रत्येक आउटपुट के लिए अलग-अलग नुकसान निर्दिष्ट कर सकते हैं। आप प्रत्येक नुकसान के लिए अलग-अलग भार भी निर्दिष्ट कर सकते हैं - कुल प्रशिक्षण हानि में उनके योगदान को संशोधित करने के लिए।
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],
)
चूंकि आउटपुट परतों के अलग-अलग नाम हैं, इसलिए आप संबंधित परत नामों के साथ हानियों और हानि भारों को भी निर्दिष्ट कर सकते हैं:
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 सरणियों की सूची पास करके मॉडल को प्रशिक्षित करें:
# 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>
जब एक साथ फिट बुला Dataset
वस्तु, यह या तो जैसे सूचियों का एक टपल उपज चाहिए ([title_data, body_data, tags_data], [priority_targets, dept_targets])
या तरह शब्दकोशों की एक टपल ({'title': title_data, 'body': body_data, 'tags': tags_data}, {'priority': priority_targets, 'department': dept_targets})
।
अधिक विस्तृत विवरण के लिए, का उल्लेख प्रशिक्षण और मूल्यांकन गाइड।
एक खिलौना रेसनेट मॉडल
एकाधिक इनपुट और आउटपुट के साथ मॉडल के अलावा, कार्यात्मक एपीआई आसान गैर रेखीय कनेक्टिविटी टोपोलोजी हेरफेर करने के लिए बनाता है - इन परतों कि क्रमिक रूप से नहीं जुड़े हैं, जिसके साथ मॉडल हैं Sequential
एपीआई को संभाल नहीं कर सकते हैं।
इसके लिए एक सामान्य उपयोग मामला अवशिष्ट कनेक्शन है। आइए इसे प्रदर्शित करने के लिए CIFAR10 के लिए एक खिलौना ResNet मॉडल बनाएं:
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 __________________________________________________________________________________________________
मॉडल प्लॉट करें:
keras.utils.plot_model(model, "mini_resnet.png", show_shapes=True)
अब मॉडल को प्रशिक्षित करें:
(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>
साझा परतें
कार्यात्मक एपीआई के लिए एक और अच्छा उपयोग मॉडल है कि साझा परतों का उपयोग कर रहे हैं। साझा परतें परत उदाहरण हैं जिन्हें एक ही मॉडल में कई बार पुन: उपयोग किया जाता है - वे उन विशेषताओं को सीखते हैं जो ग्राफ-ऑफ-लेयर्स में कई पथों से मेल खाते हैं।
साझा परतों का उपयोग अक्सर समान स्थानों से इनपुट को एन्कोड करने के लिए किया जाता है (जैसे, पाठ के दो अलग-अलग टुकड़े जो समान शब्दावली दिखाते हैं)। वे इन विभिन्न आदानों में सूचनाओं को साझा करने में सक्षम होते हैं, और वे ऐसे मॉडल को कम डेटा पर प्रशिक्षित करना संभव बनाते हैं। यदि दिए गए शब्द को किसी एक इनपुट में देखा जाता है, तो यह उन सभी इनपुट के प्रसंस्करण को लाभान्वित करेगा जो साझा परत से गुजरते हैं।
कार्यात्मक एपीआई में एक परत साझा करने के लिए, एक ही परत आवृत्ति को कई बार कॉल करें। उदाहरण के लिए, यहाँ एक है Embedding
परत दो अलग-अलग पाठ आदानों के पार साझा:
# 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)
परतों के ग्राफ़ में नोड्स निकालें और पुन: उपयोग करें
क्योंकि परतों का ग्राफ आप जोड़-तोड़ कर रहे हैं, एक स्थिर डेटा संरचना है, इसे एक्सेस और निरीक्षण किया जा सकता है। और इस तरह आप कार्यात्मक मॉडल को छवियों के रूप में प्लॉट करने में सक्षम हैं।
इसका मतलब यह भी है कि आप मध्यवर्ती परतों (ग्राफ में "नोड्स") की सक्रियता तक पहुंच सकते हैं और उन्हें कहीं और पुन: उपयोग कर सकते हैं - जो कि फीचर निष्कर्षण जैसी किसी चीज के लिए बहुत उपयोगी है।
आइए एक उदाहरण देखें। यह एक VGG19 मॉडल है जिसका वजन ImageNet पर दिखाया गया है:
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
और ये ग्राफ़ डेटा संरचना को क्वेरी करके प्राप्त मॉडल के मध्यवर्ती सक्रियण हैं:
features_list = [layer.output for layer in vgg19.layers]
एक नया फीचर-एक्सट्रैक्शन मॉडल बनाने के लिए इन सुविधाओं का उपयोग करें जो मध्यवर्ती परत सक्रियण के मान लौटाता है:
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)
इस तरह के कार्यों के लिए काम में आता तंत्रिका शैली हस्तांतरण , अन्य बातों के अलावा।
कस्टम परतों का उपयोग करके एपीआई का विस्तार करें
tf.keras
की एक विस्तृत श्रृंखला शामिल है में निर्मित परतों, उदाहरण के लिए:
- Convolutional परतों:
Conv1D
,Conv2D
,Conv3D
,Conv2DTranspose
- पूलिंग परतों:
MaxPooling1D
,MaxPooling2D
,MaxPooling3D
,AveragePooling1D
- RNN परतों:
GRU
,LSTM
,ConvLSTM2D
-
BatchNormalization
,Dropout
,Embedding
, आदि
लेकिन अगर आपको वह नहीं मिलता है जिसकी आपको आवश्यकता है, तो अपनी खुद की परतें बनाकर एपीआई का विस्तार करना आसान है। सभी परतों उपवर्ग Layer
वर्ग और लागू:
-
call
विधि, कि निर्दिष्ट करता है अभिकलन परत द्वारा किया। -
build
विधि, उस परत के वजन बनाता है (आपको वजन बना सकते हैं यह सिर्फ एक शैली सम्मेलन है__init__
, साथ ही)।
खरोंच से परत बनाने के बारे में अधिक जानने के लिए, कस्टम परतें और मॉडल गाइड।
निम्न में से एक बुनियादी कार्यान्वयन है 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)
अपने कस्टम परत में क्रमबद्धता समर्थन के लिए, एक परिभाषित get_config
विधि उस परत उदाहरण के निर्माता तर्क देता है:
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})
वैकल्पिक रूप से, वर्ग विधि को लागू from_config(cls, config)
जो जब पुनः एक परत उदाहरण, अपना config शब्दकोश दिया जाता है। के डिफ़ॉल्ट कार्यान्वयन from_config
है:
def from_config(cls, config):
return cls(**config)
कार्यात्मक एपीआई का उपयोग कब करें
आप एक नया मॉडल बनाने के लिए, या बस उपवर्ग Keras कार्यात्मक एपीआई का उपयोग करना चाहिए Model
सीधे वर्ग? सामान्य तौर पर, कार्यात्मक एपीआई उच्च-स्तरीय, आसान और सुरक्षित होता है, और इसमें कई विशेषताएं होती हैं जो उपवर्ग मॉडल का समर्थन नहीं करती हैं।
हालांकि, मॉडल सबक्लासिंग उन मॉडलों का निर्माण करते समय अधिक लचीलापन प्रदान करता है जो परतों के निर्देशित चक्रीय रेखांकन के रूप में आसानी से व्यक्त नहीं होते हैं। उदाहरण के लिए, आप कार्यात्मक एपीआई के साथ एक ट्री-RNN को लागू नहीं कर सके और उपवर्ग करना होगा Model
सीधे।
कार्यात्मक एपीआई और मॉडल उपवर्गीकरण के बीच मतभेद पर एक गहन देखने के लिए, पढ़ने के TensorFlow 2.0 में प्रतीकात्मक और पहल एपीआई क्या हैं? .
कार्यात्मक एपीआई ताकत:
निम्नलिखित गुण अनुक्रमिक मॉडल (जो डेटा संरचनाएं भी हैं) के लिए भी सही हैं, लेकिन उपवर्ग मॉडल के लिए सही नहीं हैं (जो कि पायथन बाइटकोड हैं, डेटा संरचनाएं नहीं)।
कम क्रिया
कोई भी नहीं है super(MyClass, self).__init__(...)
, कोई def call(self, ...):
, आदि
तुलना करना:
inputs = keras.Input(shape=(32,))
x = layers.Dense(64, activation='relu')(inputs)
outputs = layers.Dense(10)(x)
mlp = keras.Model(inputs, outputs)
उपवर्गित संस्करण के साथ:
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)))
अपने कनेक्टिविटी ग्राफ को परिभाषित करते हुए मॉडल सत्यापन
कार्यात्मक एपीआई में, इनपुट विनिर्देश (आकार और dtype) पहले से बनाई गई है (का उपयोग कर Input
)। हर बार जब आप किसी परत को कॉल करते हैं, तो परत यह जांचती है कि उसे दिया गया विनिर्देश उसकी मान्यताओं से मेल खाता है, और यदि नहीं तो यह एक उपयोगी त्रुटि संदेश देगा।
यह गारंटी देता है कि कार्यात्मक एपीआई के साथ आप जो भी मॉडल बना सकते हैं वह चलेगा। सभी डिबगिंग - अभिसरण से संबंधित डिबगिंग के अलावा - मॉडल निर्माण के दौरान स्थिर रूप से होती है न कि निष्पादन समय पर। यह एक कंपाइलर में टाइप चेकिंग के समान है।
एक कार्यात्मक मॉडल प्लॉट करने योग्य और निरीक्षण योग्य है
आप मॉडल को ग्राफ़ के रूप में प्लॉट कर सकते हैं, और आप इस ग्राफ़ में इंटरमीडिएट नोड्स तक आसानी से पहुंच सकते हैं। उदाहरण के लिए, मध्यवर्ती परतों की सक्रियता को निकालने और पुन: उपयोग करने के लिए (जैसा कि पिछले उदाहरण में देखा गया है):
features_list = [layer.output for layer in vgg19.layers]
feat_extraction_model = keras.Model(inputs=vgg19.input, outputs=features_list)
एक कार्यात्मक मॉडल को क्रमबद्ध या क्लोन किया जा सकता है
क्योंकि एक कार्यात्मक मॉडल कोड के एक टुकड़े के बजाय एक डेटा संरचना है, यह सुरक्षित रूप से क्रमबद्ध है और इसे एक एकल फ़ाइल के रूप में सहेजा जा सकता है जो आपको किसी भी मूल कोड तक पहुंच के बिना ठीक उसी मॉडल को फिर से बनाने की अनुमति देता है। देखें क्रमबद्धता और बचत गाइड ।
एक subclassed मॉडल को क्रमानुसार के लिए, यह implementer एक निर्दिष्ट करने के लिए के लिए आवश्यक है get_config()
और from_config()
मॉडल के स्तर पर विधि।
कार्यात्मक एपीआई कमजोरी:
यह गतिशील आर्किटेक्चर का समर्थन नहीं करता
कार्यात्मक एपीआई मॉडल को परतों के डीएजी के रूप में मानता है। यह अधिकांश गहन शिक्षण आर्किटेक्चर के लिए सही है, लेकिन सभी के लिए नहीं - उदाहरण के लिए, पुनरावर्ती नेटवर्क या ट्री आरएनएन इस धारणा का पालन नहीं करते हैं और कार्यात्मक एपीआई में लागू नहीं किया जा सकता है।
मिक्स-एंड-मैच एपीआई शैलियाँ
कार्यात्मक एपीआई या मॉडल उपवर्ग के बीच चयन करना एक द्विआधारी निर्णय नहीं है जो आपको मॉडल की एक श्रेणी में प्रतिबंधित करता है। में सभी मॉडलों tf.keras
एपीआई एक दूसरे के साथ बातचीत कर सकते हैं, चाहे वे कर रहे हैं Sequential
मॉडल, कार्यात्मक मॉडल, या subclassed मॉडल है कि खरोंच से लिखा जाता है।
तुम हमेशा एक कार्यात्मक मॉडल या उपयोग कर सकते हैं Sequential
एक subclassed मॉडल या परत के हिस्से के रूप में मॉडल:
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)
आप लंबे समय के लिए यह एक को लागू करता है के रूप में के रूप में किसी भी subclassed परत या कार्यात्मक एपीआई में मॉडल का उपयोग कर सकते हैं call
विधि है जो निम्न पैटर्न में से एक इस प्रकार है:
-
call(self, inputs, **kwargs)
- जहांinputs
एक टेन्सर या tensors के लिए एक आंतरिक संरचना (tensors के जैसे एक सूची) है, और जहां**kwargs
गैर टेन्सर तर्क (गैर आदानों) कर रहे हैं। -
call(self, inputs, training=None, **kwargs)
- जहांtraining
एक बूलियन यह बताते हैं कि परत प्रशिक्षण मोड और निष्कर्ष मोड में व्यवहार करना चाहिए है। -
call(self, inputs, mask=None, **kwargs)
- जहांmask
एक बूलियन मुखौटा टेन्सर है (, RNNs के लिए उपयोगी उदाहरण के लिए)। -
call(self, inputs, training=None, mask=None, **kwargs)
- बेशक, आप एक ही समय में दोनों मास्किंग और प्रशिक्षण विशेष व्यवहार हो सकता है।
साथ ही, यदि आप को लागू get_config
अपने कस्टम परत या मॉडल पर विधि, कार्यात्मक मॉडल आपके द्वारा बनाए गए अभी भी serializable और cloneable हो जाएगा।
यहां एक कस्टम आरएनएन का एक त्वरित उदाहरण दिया गया है, जिसे स्क्रैच से लिखा गया है, जिसका उपयोग कार्यात्मक मॉडल में किया जा रहा है:
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)))