لایههای API TensorFlow.js بر اساس Keras مدلسازی شدهاند و ما تلاش میکنیم با توجه به تفاوتهای بین جاوا اسکریپت و پایتون، API لایهها را تا حد منطقی شبیه Keras کنیم. این امر باعث میشود کاربران با تجربه در توسعه مدلهای Keras در پایتون مهاجرت به لایههای TensorFlow.js در جاوا اسکریپت را آسانتر کنند. به عنوان مثال، کد Keras زیر به جاوا اسکریپت ترجمه می شود:
# 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]});
توابع جاوا اسکریپت معادل آرگومان های کلمه کلیدی در توابع پایتون ندارند. ما میخواهیم از پیادهسازی گزینههای سازنده بهعنوان آرگومانهای موقعیتی در جاوا اسکریپت خودداری کنیم، که یادآوری و استفاده از آن برای سازندههایی با تعداد زیادی آرگومان کلیدواژه (مثلاً LSTM ) دشوار است. به همین دلیل است که ما از اشیاء پیکربندی جاوا اسکریپت استفاده می کنیم. چنین اشیایی همان سطحی از تغییرپذیری موقعیت و انعطاف پذیری آرگومان های کلیدواژه پایتون را ارائه می دهند.
برخی از متدهای کلاس Model، به عنوان مثال، Model.compile()
نیز یک شی پیکربندی جاوا اسکریپت را به عنوان ورودی می گیرند. با این حال، به خاطر داشته باشید که Model.fit()
، Model.evaluate()
و Model.predict()
کمی متفاوت هستند. از آنجایی که این روش داده های اجباری x
(ویژگی ها) و y
(برچسب ها یا اهداف) را به عنوان ورودی می گیرند. x
و y
آرگومان های موقعیتی جدا از شیء پیکربندی بعدی هستند که نقش آرگومان های کلیدواژه را ایفا می کنند. به عنوان مثال:
// JavaScript:
await model.fit(xs, ys, {epochs: 1000});
Model.fit() async است
Model.fit()
روش اولیه ای است که کاربران با آن آموزش مدل را در TensorFlow.js انجام می دهند. این روش اغلب می تواند طولانی مدت باشد و برای چند ثانیه یا چند دقیقه طول بکشد. بنابراین، ما از ویژگی async
زبان جاوا اسکریپت استفاده میکنیم تا بتوان از این تابع به گونهای استفاده کرد که در هنگام اجرا در مرورگر، رشته اصلی رابط کاربری مسدود نشود. این شبیه به سایر توابع بالقوه طولانی مدت در جاوا اسکریپت است، مانند واکشی async
. توجه داشته باشید که async
ساختاری است که در پایتون وجود ندارد. در حالی که متد fit()
در Keras یک شی History برمی گرداند، همتای متد fit()
در جاوا اسکریپت یک Promise of History را برمی گرداند که می تواند منتظر ویرایش (مانند مثال بالا) باشد یا با متد then() استفاده شود.
NumPy برای TensorFlow.js وجود ندارد
کاربران Python Keras اغلب از NumPy برای انجام عملیاتهای عددی و آرایهای پایه مانند تولید تانسورهای دوبعدی در مثال بالا استفاده میکنند.
# 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، شما متدهای کارخانهای را فراخوانی میکنید که نامهای CamelCase پایینتری دارند، برای مثال:
// JavaScript:
const model = tf.sequential();
const layer = tf.layers.batchNormalization({axis: 1});
مقادیر رشته گزینه lowCamelCase است نه snake_case
در جاوا اسکریپت، در مقایسه با Python، که در آن حروف مار رایج است (مثلاً در Keras) استفاده از camel case برای نام نمادها رایج تر است (به عنوان مثال، راهنمای سبک جاوا اسکریپت گوگل را ببینید). به این ترتیب، ما تصمیم گرفتیم از lowCamelCase برای مقادیر رشته برای گزینه هایی از جمله موارد زیر استفاده کنیم:
- DataFormat، به عنوان مثال،
channelsFirst
به جایchannels_first
- Initializer، به عنوان مثال،
glorotNormal
به جایglorot_normal
- ضرر و معیارها، به عنوان مثال،
meanSquaredError
به جایmean_squared_error
،categoricalCrossentropy
به جایcategorical_crossentropy
.
به عنوان مثال، مانند مثال بالا:
// JavaScript:
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});
با توجه به سریال سازی و سریال زدایی مدل، مطمئن باشید. مکانیسم داخلی TensorFlow.js تضمین می کند که موارد مار در اشیاء JSON به درستی مدیریت می شوند، به عنوان مثال، هنگام بارگیری مدل های از پیش آموزش دیده از Python Keras.
اشیاء لایه را با application() اجرا کنید، نه با فراخوانی آنها به عنوان توابع
در Keras، یک شی لایه دارای متد __call__
تعریف شده است. بنابراین کاربر می تواند منطق لایه را با فراخوانی شی به عنوان یک تابع فراخوانی کند، به عنوان مثال،
# Python:
my_input = keras.Input(shape=[2, 4])
flatten = keras.layers.Flatten()
print(flatten(my_input).shape)
این قند نحوی پایتون به عنوان متد application() در TensorFlow.js پیاده سازی شده است:
// JavaScript:
const myInput = tf.input({shape: [2, 4]});
const flatten = tf.layers.flatten();
console.log(flatten.apply(myInput).shape);
Layer.apply() از ارزیابی ضروری (اشتیاق) بر روی تانسورهای بتنی پشتیبانی می کند
در حال حاضر، در Keras، روش فراخوانی فقط میتواند روی اشیاء tf.Tensor
TensorFlow (با فرض پشتوانه TensorFlow)، که نمادین هستند و مقادیر عددی واقعی را در خود ندارند، (پایتون) عمل کند. این همان چیزی است که در مثال در بخش قبل نشان داده شده است. با این حال، در TensorFlow.js، متد application() لایهها میتواند در هر دو حالت نمادین و دستوری عمل کند. اگر apply()
با یک SymbolicTensor (مشابه نزدیک tf.Tensor) فراخوانی شود، مقدار بازگشتی یک SymbolicTensor خواهد بود. این معمولا در طول ساخت مدل اتفاق می افتد. اما اگر apply()
با یک مقدار واقعی تانسور بتن فراخوانی شود، یک تانسور بتن برمی گرداند. به عنوان مثال:
// JavaScript:
const flatten = tf.layers.flatten();
flatten.apply(tf.ones([2, 3, 4])).print();
این ویژگی یادآور اجرای مشتاق تنسورفلو (Python) است. این قابلیت تعامل و اشکال زدایی بیشتری را در طول توسعه مدل فراهم می کند، علاوه بر این درها را به روی ایجاد شبکه های عصبی پویا باز می کند.
بهینه سازها زیر قطار هستند. نه بهینه سازها
در Keras، سازنده اشیاء Optimizer در زیر فضای نام 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
در Keras، مدلها معمولاً بهعنوان فایل HDF5 (.h5) ذخیره میشوند که بعداً میتوان با استفاده از روش keras.models.load_model()
بارگذاری کرد. این روش مسیری به فایل .h5 می گیرد. همتای load_model()
در TensorFlow.js tf.loadLayersModel()
است. از آنجایی که HDF5 یک فرمت فایل مناسب برای مرورگر نیست، tf.loadLayersModel()
فرمت مخصوص TensorFlow.js را می گیرد. tf.loadLayersModel()
یک فایل model.json را به عنوان آرگومان ورودی خود می گیرد. model.json را می توان از فایل Keras HDF5 با استفاده از بسته pip tensorflowjs تبدیل کرد.
// JavaScript:
const model = await tf.loadLayersModel('https://foo.bar/model.json');
همچنین توجه داشته باشید که tf.loadLayersModel()
یک Promise
از tf.Model
را برمی گرداند.
به طور کلی ذخیره و بارگذاری tf.Model
s در TensorFlow.js به ترتیب با استفاده از روش های tf.Model.save
و tf.loadLayersModel
انجام می شود. ما این APIها را به گونه ای طراحی کردیم که شبیه به ذخیره و load_model API Keras باشند. اما محیط مرورگر کاملاً متفاوت از محیط باطن است که چارچوبهای یادگیری عمیق اصلی مانند Keras روی آن اجرا میشوند، بهویژه در مجموعهای از مسیرها برای ماندگاری و انتقال دادهها. از این رو تفاوت های جالبی بین API های ذخیره/بارگذاری در TensorFlow.js و در Keras وجود دارد. برای جزئیات بیشتر به آموزش ما در مورد ذخیره و بارگیری tf.Model مراجعه کنید.
از fitDataset()
برای آموزش مدل ها با استفاده از اشیاء tf.data.Dataset
استفاده کنید
در tf.keras Python TensorFlow، یک مدل را می توان با استفاده از یک آبجکت Dataset آموزش داد. fit()
مدل چنین شیئی را مستقیماً می پذیرد. یک مدل TensorFlow.js را می توان با معادل جاوا اسکریپت اشیاء Dataset نیز آموزش داد ( مستندات API tf.data را در TensorFlow.js ببینید). با این حال، برخلاف پایتون، آموزش مبتنی بر Dataset از طریق یک روش اختصاصی، یعنی fitDataset انجام میشود. روش fit() فقط برای آموزش مدل مبتنی بر تانسور است.
مدیریت حافظه اشیاء لایه و مدل
TensorFlow.js روی WebGL در مرورگر اجرا میشود، جایی که وزن اشیاء لایه و مدل توسط بافتهای WebGL پشتیبانی میشوند. با این حال، WebGL هیچ پشتیبانی داخلی برای جمع آوری زباله ندارد. اشیاء لایه و مدل به طور داخلی حافظه تانسور را برای کاربر در طول استنتاج و فراخوانی های آموزشی مدیریت می کنند. اما آنها همچنین به کاربر اجازه می دهند تا آنها را از بین ببرد تا حافظه WebGL را که اشغال می کند آزاد کند. این در مواردی مفید است که نمونههای مدل زیادی در یک بارگذاری صفحه ایجاد و منتشر میشوند. برای از بین بردن یک شیء لایه یا مدل، از متد dispose()
استفاده کنید.