केरस उपयोगकर्ताओं के लिए TensorFlow.js लेयर्स API

TensorFlow.js की लेयर्स एपीआई को केरस के आधार पर तैयार किया गया है और हम जावास्क्रिप्ट और पायथन के बीच अंतर को देखते हुए लेयर्स एपीआई को केरस के समान उचित बनाने का प्रयास करते हैं। इससे पायथन में केरस मॉडल विकसित करने का अनुभव रखने वाले उपयोगकर्ताओं के लिए जावास्क्रिप्ट में TensorFlow.js लेयर्स पर माइग्रेट करना आसान हो जाता है। उदाहरण के लिए, निम्नलिखित केरस कोड जावास्क्रिप्ट में अनुवादित होता है:

# Python:
import keras
import numpy as np

# Build and compile model.
model = keras.Sequential()
model.add(keras.layers.Dense(units=1, input_shape=[1]))
model.compile(optimizer='sgd', loss='mean_squared_error')

# Generate some synthetic data for training.
xs = np.array([[1], [2], [3], [4]])
ys = np.array([[1], [3], [5], [7]])

# Train model with fit().
model.fit(xs, ys, epochs=1000)

# Run inference with predict().
print(model.predict(np.array([[5]])))
// JavaScript:
import * as tf from '@tensorflow/tfjs';

// Build and compile model.
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});

// Generate some synthetic data for training.
const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);
const ys = tf.tensor2d([[1], [3], [5], [7]], [4, 1]);

// Train model with fit().
await model.fit(xs, ys, {epochs: 1000});

// Run inference with predict().
model.predict(tf.tensor2d([[5]], [1, 1])).print();

हालाँकि, कुछ अंतर हैं जिन्हें हम इस दस्तावेज़ में बताना और समझाना चाहेंगे। एक बार जब आप इन अंतरों और उनके पीछे के तर्क को समझ लेते हैं, तो आपका पायथन-टू-जावास्क्रिप्ट माइग्रेशन (या विपरीत दिशा में माइग्रेशन) अपेक्षाकृत सहज अनुभव होना चाहिए।

कंस्ट्रक्टर जावास्क्रिप्ट ऑब्जेक्ट को कॉन्फ़िगरेशन के रूप में लेते हैं

उपरोक्त उदाहरण से निम्नलिखित पायथन और जावास्क्रिप्ट लाइनों की तुलना करें: वे दोनों एक सघन परत बनाते हैं।

# Python:
keras.layers.Dense(units=1, inputShape=[1])
// JavaScript:
tf.layers.dense({units: 1, inputShape: [1]});

जावास्क्रिप्ट फ़ंक्शंस में पायथन फ़ंक्शंस में कीवर्ड तर्कों के बराबर नहीं है। हम जावास्क्रिप्ट में स्थितीय तर्कों के रूप में कंस्ट्रक्टर विकल्पों को लागू करने से बचना चाहते हैं, जो बड़ी संख्या में कीवर्ड तर्कों (उदाहरण के लिए, एलएसटीएम ) वाले कंस्ट्रक्टरों के लिए याद रखना और उपयोग करना विशेष रूप से बोझिल होगा। यही कारण है कि हम जावास्क्रिप्ट कॉन्फ़िगरेशन ऑब्जेक्ट का उपयोग करते हैं। ऐसी वस्तुएं पायथन कीवर्ड तर्कों के समान स्थितिगत अपरिवर्तनीयता और लचीलापन प्रदान करती हैं।

मॉडल वर्ग की कुछ विधियाँ, उदाहरण के लिए, Model.compile() , इनपुट के रूप में एक जावास्क्रिप्ट कॉन्फ़िगरेशन ऑब्जेक्ट भी लेती हैं। हालाँकि, ध्यान रखें कि Model.fit() , Model.evaluate() और Model.predict() थोड़े अलग हैं। चूँकि ये विधियाँ अनिवार्य x (विशेषताएँ) और y (लेबल या लक्ष्य) डेटा को इनपुट के रूप में लेती हैं; x और y आगामी कॉन्फ़िगरेशन ऑब्जेक्ट से अलग स्थितीय तर्क हैं जो कीवर्ड तर्क की भूमिका निभाते हैं। उदाहरण के लिए:

// JavaScript:
await model.fit(xs, ys, {epochs: 1000});

मॉडल.फिट() एसिंक है

Model.fit() प्राथमिक विधि है जिसके साथ उपयोगकर्ता TensorFlow.js में मॉडल प्रशिक्षण करते हैं। यह विधि अक्सर लंबे समय तक चलने वाली, सेकंड या मिनट तक चलने वाली हो सकती है। इसलिए, हम जावास्क्रिप्ट भाषा की async सुविधा का उपयोग करते हैं, ताकि इस फ़ंक्शन का उपयोग इस तरह से किया जा सके कि ब्राउज़र में चलने पर मुख्य यूआई थ्रेड अवरुद्ध न हो। यह जावास्क्रिप्ट में अन्य संभावित रूप से लंबे समय तक चलने वाले कार्यों के समान है, जैसे कि async फ़ेच । ध्यान दें कि async एक ऐसा निर्माण है जो Python में मौजूद नहीं है। जबकि केरस में fit() विधि एक इतिहास ऑब्जेक्ट लौटाती है, जावास्क्रिप्ट में fit() विधि का समकक्ष इतिहास का एक वादा देता है, जिसे प्रतीक्षित किया जा सकता है (जैसा कि ऊपर दिए गए उदाहरण में है) या तत्कालीन () विधि के साथ उपयोग किया जा सकता है।

TensorFlow.js के लिए कोई NumPy नहीं

पायथन केरस उपयोगकर्ता अक्सर बुनियादी संख्यात्मक और सरणी संचालन करने के लिए NumPy का उपयोग करते हैं, जैसे कि ऊपर दिए गए उदाहरण में 2D टेंसर उत्पन्न करना।

# Python:
xs = np.array([[1], [2], [3], [4]])

TensorFlow.js में, इस प्रकार के बुनियादी संख्यात्मक ऑपरेशन पैकेज के साथ ही किए जाते हैं। उदाहरण के लिए:

// JavaScript:
const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);

tf.* नेमस्पेस सरणी और रैखिक बीजगणित संचालन जैसे मैट्रिक्स गुणन के लिए कई अन्य फ़ंक्शन भी प्रदान करता है। अधिक जानकारी के लिए TensorFlow.js कोर दस्तावेज़ देखें।

फ़ैक्टरी विधियों का उपयोग करें, कंस्ट्रक्टरों का नहीं

पायथन में यह पंक्ति (ऊपर दिए गए उदाहरण से) एक कंस्ट्रक्टर कॉल है:

# Python:
model = keras.Sequential()

यदि जावास्क्रिप्ट में कड़ाई से अनुवाद किया जाए, तो समतुल्य कंस्ट्रक्टर कॉल निम्नलिखित की तरह दिखेगी:

// JavaScript:
const model = new tf.Sequential();  // !!! DON'T DO THIS !!!

हालाँकि, हमने "नए" कंस्ट्रक्टर का उपयोग न करने का निर्णय लिया क्योंकि 1) "नया" कीवर्ड कोड को अधिक फूला हुआ बना देगा और 2) "नए" कंस्ट्रक्टर को जावास्क्रिप्ट का "खराब हिस्सा" माना जाता है: एक संभावित नुकसान, जैसा कि जावास्क्रिप्ट में तर्क दिया गया है: अच्छे भाग । TensorFlow.js में मॉडल और परतें बनाने के लिए, आप फ़ैक्टरी विधियों को कॉल करते हैं, जिनमें लोअरकैमलकेस नाम होते हैं, उदाहरण के लिए:

// JavaScript:
const model = tf.sequential();

const layer = tf.layers.batchNormalization({axis: 1});

विकल्प स्ट्रिंग मान लोअरकैमलकेस हैं, स्नेक_केस नहीं

जावास्क्रिप्ट में, प्रतीक नामों के लिए कैमल केस का उपयोग करना अधिक आम है (उदाहरण के लिए, Google जावास्क्रिप्ट स्टाइल गाइड देखें), पायथन की तुलना में, जहां सांप का केस आम है (उदाहरण के लिए, केरस में)। इस प्रकार, हमने निम्नलिखित सहित विकल्पों के लिए स्ट्रिंग मानों के लिए लोअरकैमलकेस का उपयोग करने का निर्णय लिया:

  • डेटाफ़ॉर्मेट, उदाहरण के लिए, channelsFirst के बजाय channels_first
  • इनिशियलाइज़र, उदाहरण के लिए, glorotNormal के बजाय glorot_normal
  • हानि और मेट्रिक्स, उदाहरण के लिए, mean_squared_error के बजाय meanSquaredError , categoricalCrossentropy के बजाय categorical_crossentropy

उदाहरण के लिए, जैसा कि ऊपर दिए गए उदाहरण में है:

// JavaScript:
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});

मॉडल क्रमबद्धता और अक्रमांकन के संबंध में, निश्चिंत रहें। TensorFlow.js का आंतरिक तंत्र यह सुनिश्चित करता है कि JSON ऑब्जेक्ट में साँप के मामलों को सही ढंग से संभाला जाए, उदाहरण के लिए, Python Keras से पूर्व-प्रशिक्षित मॉडल लोड करते समय।

लेयर ऑब्जेक्ट को अप्लाई() के साथ चलाएँ, न कि उन्हें फ़ंक्शन के रूप में कॉल करके

केरस में, एक लेयर ऑब्जेक्ट में __call__ विधि परिभाषित होती है। इसलिए उपयोगकर्ता ऑब्जेक्ट को फ़ंक्शन के रूप में कॉल करके परत के तर्क को लागू कर सकता है, उदाहरण के लिए,

# Python:
my_input = keras.Input(shape=[2, 4])
flatten = keras.layers.Flatten()

print(flatten(my_input).shape)

इस पायथन सिंटैक्स शुगर को TensorFlow.js में अप्लाई() विधि के रूप में कार्यान्वित किया गया है:

// JavaScript:
const myInput = tf.input({shape: [2, 4]});
const flatten = tf.layers.flatten();

console.log(flatten.apply(myInput).shape);

Layer.apply() कंक्रीट टेंसर पर अनिवार्य (उत्सुक) मूल्यांकन का समर्थन करता है

वर्तमान में, केरस में, कॉल विधि केवल (पायथन) टेन्सरफ्लो के tf.Tensor ऑब्जेक्ट्स (टेन्सरफ्लो बैकएंड मानते हुए) पर काम कर सकती है, जो प्रतीकात्मक हैं और वास्तविक संख्यात्मक मान नहीं रखते हैं। पिछले अनुभाग के उदाहरण में यही दिखाया गया है। हालाँकि, TensorFlow.js में, परतों की लागू() विधि प्रतीकात्मक और अनिवार्य दोनों मोड में काम कर सकती है। यदि apply() को SymbolicTensor (tf.Tensor का एक करीबी सादृश्य) के साथ लागू किया जाता है, तो रिटर्न मान एक SymbolicTensor होगा। ऐसा आमतौर पर मॉडल निर्माण के दौरान होता है। लेकिन यदि apply() को वास्तविक कंक्रीट Tensor मान के साथ लागू किया जाता है, तो यह एक ठोस Tensor लौटाएगा। उदाहरण के लिए:

// JavaScript:
const flatten = tf.layers.flatten();

flatten.apply(tf.ones([2, 3, 4])).print();

यह सुविधा (पायथन) टेन्सरफ्लो के उत्सुक निष्पादन की याद दिलाती है। यह गतिशील तंत्रिका नेटवर्क की रचना के लिए दरवाजे खोलने के अलावा, मॉडल विकास के दौरान अधिक अन्तरक्रियाशीलता और डिबगबिलिटी प्रदान करता है।

अनुकूलक प्रशिक्षणाधीन हैं। , अनुकूलक नहीं।

केरस में, ऑप्टिमाइज़र ऑब्जेक्ट के लिए कंस्ट्रक्टर keras.optimizers.* नेमस्पेस के अंतर्गत हैं। TensorFlow.js लेयर्स में, ऑप्टिमाइज़र के लिए फ़ैक्टरी विधियाँ tf.train.* नेमस्पेस के अंतर्गत हैं। उदाहरण के लिए:

# Python:
my_sgd = keras.optimizers.sgd(lr=0.2)
// JavaScript:
const mySGD = tf.train.sgd({lr: 0.2});

LoadLayersModel() एक URL से लोड होता है, HDF5 फ़ाइल से नहीं

केरस में, मॉडल आमतौर पर HDF5 (.h5) फ़ाइल के रूप में सहेजे जाते हैं, जिसे बाद में keras.models.load_model() विधि का उपयोग करके लोड किया जा सकता है। विधि .h5 फ़ाइल के लिए एक पथ लेती है। TensorFlow.js में load_model() का समकक्ष tf.loadLayersModel() है। चूँकि HDF5 एक ब्राउज़र-अनुकूल फ़ाइल स्वरूप नहीं है, tf.loadLayersModel() एक TensorFlow.js-विशिष्ट प्रारूप लेता है। tf.loadLayersModel() अपने इनपुट तर्क के रूप में एक model.json फ़ाइल लेता है। मॉडल.जेसन को टेंसरफ़्लोज पिप पैकेज का उपयोग करके केरस एचडीएफ5 फ़ाइल से परिवर्तित किया जा सकता है।

// JavaScript:
const model = await tf.loadLayersModel('https://foo.bar/model.json');

यह भी ध्यान दें कि tf.loadLayersModel() tf.Model का Promise लौटाता है।

सामान्य तौर पर, TensorFlow.js में tf.Model s को सहेजना और लोड करना क्रमशः tf.Model.save और tf.loadLayersModel विधियों का उपयोग करके किया जाता है। हमने इन एपीआई को केरस के सेव और लोड_मॉडल एपीआई के समान डिज़ाइन किया है। लेकिन ब्राउज़र वातावरण बैकएंड वातावरण से काफी अलग है, जिस पर केरस जैसे प्रमुख गहन शिक्षण ढांचे चलते हैं, विशेष रूप से डेटा को बनाए रखने और संचारित करने के लिए मार्गों की श्रृंखला में। इसलिए TensorFlow.js और Keras में सेव/लोड एपीआई के बीच कुछ दिलचस्प अंतर हैं। अधिक जानकारी के लिए tf.Model को सहेजने और लोड करने पर हमारा ट्यूटोरियल देखें।

tf.data.Dataset ऑब्जेक्ट का उपयोग करके मॉडल को प्रशिक्षित करने के लिए fitDataset() का उपयोग करें

Python TensorFlow के tf.keras में, एक मॉडल को डेटासेट ऑब्जेक्ट का उपयोग करके प्रशिक्षित किया जा सकता है। मॉडल की fit() विधि ऐसी वस्तु को सीधे स्वीकार करती है। TensorFlow.js मॉडल को डेटासेट ऑब्जेक्ट के समकक्ष जावास्क्रिप्ट के साथ भी प्रशिक्षित किया जा सकता है ( TensorFlow.js में tf.data API का दस्तावेज़ देखें)। हालाँकि, पायथन के विपरीत, डेटासेट-आधारित प्रशिक्षण एक समर्पित विधि, अर्थात् फिटडेटासेट के माध्यम से किया जाता है। फिट() विधि केवल टेंसर-आधारित मॉडल प्रशिक्षण के लिए है।

परत और मॉडल ऑब्जेक्ट का मेमोरी प्रबंधन

TensorFlow.js ब्राउज़र में WebGL पर चलता है, जहां लेयर और मॉडल ऑब्जेक्ट का वजन WebGL टेक्सचर द्वारा समर्थित होता है। हालाँकि, WebGL में कोई अंतर्निहित कचरा संग्रहण समर्थन नहीं है। परत और मॉडल ऑब्जेक्ट आंतरिक रूप से अपने अनुमान और प्रशिक्षण कॉल के दौरान उपयोगकर्ता के लिए टेंसर मेमोरी का प्रबंधन करते हैं। लेकिन वे उपयोगकर्ता को उनके कब्जे वाली WebGL मेमोरी को मुक्त करने के लिए उनका निपटान करने की भी अनुमति देते हैं। यह उन मामलों में उपयोगी है जहां एक ही पेज लोड के भीतर कई मॉडल इंस्टेंस बनाए और जारी किए जाते हैं। किसी लेयर या मॉडल ऑब्जेक्ट का निपटान करने के लिए, dispose() विधि का उपयोग करें।