يفترض هذا الدليل أنك قرأت دليل النماذج والطبقات بالفعل.
في TensorFlow.js ، هناك طريقتان لتدريب نموذج التعلم الآلي:
- باستخدام Layers API مع
LayersModel.fit()
أوLayersModel.fitDataset()
. - باستخدام Core API مع
Optimizer.minimize()
.
أولاً ، سننظر في Layers API ، وهي واجهة برمجة تطبيقات ذات مستوى أعلى لبناء النماذج والتدريب. بعد ذلك ، سوف نوضح كيفية تدريب نفس النموذج باستخدام Core API.
مقدمة
نموذج التعلم الآلي هو وظيفة ذات معلمات قابلة للتعلم تقوم بتعيين مدخلات إلى المخرجات المرغوبة. يتم الحصول على المعلمات المثلى من خلال تدريب النموذج على البيانات.
يتضمن التدريب عدة خطوات:
- إحضار مجموعة من البيانات إلى النموذج.
- مطالبة النموذج بعمل تنبؤ.
- مقارنة هذا التوقع بالقيمة "الحقيقية".
- تحديد مقدار تغيير كل معلمة حتى يتمكن النموذج من عمل تنبؤ أفضل في المستقبل لتلك الدُفعة.
سيوفر النموذج المدرب جيدًا تخطيطًا دقيقًا من المدخلات إلى المخرجات المطلوبة.
معلمات النموذج
دعنا نحدد نموذجًا بسيطًا من طبقتين باستخدام Layers API:
const model = tf.sequential({
layers: [
tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}),
tf.layers.dense({units: 10, activation: 'softmax'}),
]
});
تحت الغطاء ، تحتوي النماذج على معلمات (يشار إليها غالبًا باسم الأوزان ) يمكن تعلمها من خلال التدريب على البيانات. لنطبع أسماء الأوزان المرتبطة بهذا النموذج وأشكالها:
model.weights.forEach(w => {
console.log(w.name, w.shape);
});
نحصل على الناتج التالي:
> dense_Dense1/kernel [784, 32]
> dense_Dense1/bias [32]
> dense_Dense2/kernel [32, 10]
> dense_Dense2/bias [10]
هناك 4 أوزان في المجموع ، 2 لكل طبقة كثيفة. هذا متوقع لأن الطبقات الكثيفة تمثل وظيفة ترسم موتر الإدخال x
إلى موتر الإخراج y
عبر المعادلة y = Ax + b
حيث A
(النواة) و b
(التحيز) هي معلمات للطبقة الكثيفة.
ملاحظة: تشتمل الطبقات الكثيفة افتراضيًا على انحياز ، ولكن يمكنك استبعادها بتحديد
{useBias: false}
في الخيارات عند إنشاء طبقة كثيفة.
model.summary()
طريقة مفيدة إذا كنت ترغب في الحصول على نظرة عامة على نموذجك ومعرفة العدد الإجمالي للمعلمات:
طبقة (نوع) | شكل الإخراج | بارام # |
كثيف 1 (كثيف) | [خالية ، 32] | 25120 |
كثيف 2 (كثيف) | [خالية ، 10] | 330 |
إجمالي المعلمات: 25450 المعلمات القابلة للتدريب: 25450 المعلمات غير القابلة للتدريب: 0 |
كل وزن في النموذج هو الواجهة الخلفية لكائن Variable
. في Tensor
، Variable
هو موتر ذو فاصلة عائمة مع assign()
تستخدم لتحديث قيمه. تقوم Layers API تلقائيًا بتهيئة الأوزان باستخدام أفضل الممارسات. من أجل العرض التوضيحي ، يمكننا استبدال الأوزان عن طريق استدعاء assign()
على المتغيرات الأساسية:
model.weights.forEach(w => {
const newVals = tf.randomNormal(w.shape);
// w.val is an instance of tf.Variable
w.val.assign(newVals);
});
محسن وخسارة وقياس
قبل أن تقوم بأي تدريب ، عليك أن تقرر ثلاثة أشياء:
- محسن . تتمثل مهمة المحسن في تحديد مقدار تغيير كل معلمة في النموذج ، نظرًا لتنبؤ النموذج الحالي. عند استخدام Layers API ، يمكنك توفير إما معرف سلسلة لمحسِّن حالي (مثل
'sgd'
أو'adam'
) ، أو مثيل لفئةOptimizer
. - وظيفة الخسارة . هدف سيحاول النموذج تقليله. هدفها هو إعطاء رقم واحد "لمدى خطأ" تنبؤ النموذج. يتم حساب الخسارة على كل دفعة من البيانات بحيث يمكن للنموذج تحديث أوزانه. عند استخدام Layers API ، يمكنك توفير إما معرف سلسلة لوظيفة خسارة موجودة (مثل
'categoricalCrossentropy'
) ، أو أي دالة تأخذ قيمة متوقعة وحقيقية وتعيد خسارة. اطلع على قائمة الخسائر المتاحة في مستندات API الخاصة بنا. - قائمة المقاييس. على غرار الخسائر ، تحسب المقاييس رقمًا واحدًا ، وتلخص مدى جودة أداء نموذجنا. عادة ما يتم حساب المقاييس على البيانات الكاملة في نهاية كل حقبة. على أقل تقدير ، نريد أن نراقب أن خسارتنا تتناقص بمرور الوقت. ومع ذلك ، غالبًا ما نريد مقياسًا أكثر ملاءمة للإنسان مثل الدقة. عند استخدام Layers API ، يمكنك توفير إما معرف سلسلة لمقياس موجود (مثل
'accuracy'
) ، أو أي وظيفة تأخذ قيمة متوقعة وحقيقية وتعيد النتيجة. اطلع على قائمة المقاييس المتاحة في مستندات API الخاصة بنا.
عندما تقرر ، قم بتجميع LayersModel
عن طريق استدعاء model.compile()
مع الخيارات المتوفرة:
model.compile({
optimizer: 'sgd',
loss: 'categoricalCrossentropy',
metrics: ['accuracy']
});
أثناء التجميع ، سيقوم النموذج ببعض التحقق للتأكد من أن الخيارات التي اخترتها متوافقة مع بعضها البعض.
تمرين
هناك طريقتان لتدريب نموذج LayersModel
:
- استخدام
model.fit()
وتقديم البيانات كموتّر واحد كبير. - استخدام
model.fitDataset()
وتوفير البيانات عبر كائنDataset
.
نموذج صالح()
إذا كانت مجموعة البيانات الخاصة بك تتلاءم مع الذاكرة الرئيسية ، وكانت متوفرة كموتر واحد ، فيمكنك تدريب نموذج عن طريق استدعاء طريقة fit()
:
// Generate dummy data.
const data = tf.randomNormal([100, 784]);
const labels = tf.randomUniform([100, 10]);
function onBatchEnd(batch, logs) {
console.log('Accuracy', logs.acc);
}
// Train for 5 epochs with batch size of 32.
model.fit(data, labels, {
epochs: 5,
batchSize: 32,
callbacks: {onBatchEnd}
}).then(info => {
console.log('Final accuracy', info.history.acc);
});
تحت الغطاء ، يمكن لـ model.fit()
أن يفعل الكثير لنا:
- يقسم البيانات إلى مجموعة تدريب وتحقق من الصحة ، ويستخدم مجموعة التحقق لقياس التقدم أثناء التدريب.
- لتبديل البيانات ولكن فقط بعد الانقسام. لكي تكون آمنًا ، يجب عليك خلط البيانات مسبقًا قبل تمريرها
fit()
. - يقسم موتر البيانات الكبيرة إلى
batchSize.
- Calls
optimizer.minimize()
أثناء حساب فقدان النموذج فيما يتعلق بدفعة البيانات. - يمكنه إخطارك ببداية ونهاية كل حقبة أو دفعة. في حالتنا ، يتم إعلامنا في نهاية كل دفعة باستخدام خيار
callbacks.onBatchEnd
. تشمل الخيارات الأخرى:onTrainBegin
وonTrainEnd
وonEpochBegin
وonEpochEnd
وonBatchBegin
. - وهي تؤدي إلى الخيط الرئيسي لضمان إمكانية التعامل مع المهام الموجودة في قائمة الانتظار في حلقة حدث JS في الوقت المناسب.
لمزيد من المعلومات ، راجع وثائق fit()
. لاحظ أنه إذا اخترت استخدام Core API ، فسيتعين عليك تنفيذ هذا المنطق بنفسك.
model.fitDataset ()
إذا كانت بياناتك لا تتلاءم تمامًا مع الذاكرة ، أو يتم دفقها ، فيمكنك تدريب نموذج عن طريق استدعاء fitDataset()
، والذي يأخذ كائن Dataset
. إليك نفس رمز التدريب ولكن مع مجموعة بيانات تغلف وظيفة المولد:
function* data() {
for (let i = 0; i < 100; i++) {
// Generate one sample at a time.
yield tf.randomNormal([784]);
}
}
function* labels() {
for (let i = 0; i < 100; i++) {
// Generate one sample at a time.
yield tf.randomUniform([10]);
}
}
const xs = tf.data.generator(data);
const ys = tf.data.generator(labels);
// We zip the data and labels together, shuffle and batch 32 samples at a time.
const ds = tf.data.zip({xs, ys}).shuffle(100 /* bufferSize */).batch(32);
// Train the model for 5 epochs.
model.fitDataset(ds, {epochs: 5}).then(info => {
console.log('Accuracy', info.history.acc);
});
لمزيد من المعلومات حول مجموعات البيانات ، راجع توثيق model.fitDataset()
.
توقع البيانات الجديدة
بمجرد تدريب النموذج ، يمكنك استدعاء model.predict()
لعمل تنبؤات بشأن البيانات غير المرئية:
// Predict 3 random samples.
const prediction = model.predict(tf.randomNormal([3, 784]));
prediction.print();
API الأساسية
ذكرنا سابقًا أن هناك طريقتين لتدريب نموذج التعلم الآلي في TensorFlow.js.
تتمثل القاعدة العامة في محاولة استخدام Layers API أولاً ، حيث تم تصميمها على غرار Keras API المعتمد جيدًا. تقدم Layers API أيضًا العديد من الحلول الجاهزة مثل تهيئة الوزن ، وتسلسل النموذج ، والتدريب على المراقبة ، وقابلية النقل ، وفحص السلامة.
قد ترغب في استخدام Core API عندما:
- أنت بحاجة إلى أقصى قدر من المرونة أو التحكم.
- ولا تحتاج إلى تسلسل ، أو يمكنك تنفيذ منطق التسلسل الخاص بك.
لمزيد من المعلومات حول واجهة برمجة التطبيقات هذه ، اقرأ قسم "Core API" في دليل النماذج والطبقات .
يبدو نفس النموذج الموضح أعلاه باستخدام Core API كما يلي:
// The weights and biases for the two dense layers.
const w1 = tf.variable(tf.randomNormal([784, 32]));
const b1 = tf.variable(tf.randomNormal([32]));
const w2 = tf.variable(tf.randomNormal([32, 10]));
const b2 = tf.variable(tf.randomNormal([10]));
function model(x) {
return x.matMul(w1).add(b1).relu().matMul(w2).add(b2);
}
بالإضافة إلى Layers API ، تعمل Data API أيضًا بسلاسة مع Core API. دعنا نعيد استخدام مجموعة البيانات التي حددناها سابقًا في قسم model.fitDataset () ، والذي يقوم بالتبديل والتجميع بالنسبة لنا:
const xs = tf.data.generator(data);
const ys = tf.data.generator(labels);
// Zip the data and labels together, shuffle and batch 32 samples at a time.
const ds = tf.data.zip({xs, ys}).shuffle(100 /* bufferSize */).batch(32);
دعونا ندرب النموذج:
const optimizer = tf.train.sgd(0.1 /* learningRate */);
// Train for 5 epochs.
for (let epoch = 0; epoch < 5; epoch++) {
await ds.forEachAsync(({xs, ys}) => {
optimizer.minimize(() => {
const predYs = model(xs);
const loss = tf.losses.softmaxCrossEntropy(ys, predYs);
loss.data().then(l => console.log('Loss', l));
return loss;
});
});
console.log('Epoch', epoch);
}
الكود أعلاه هو الوصفة القياسية عند تدريب نموذج باستخدام Core API:
- حلقة حول عدد الحقب.
- داخل كل حقبة ، مرر على مجموعات البيانات الخاصة بك. عند استخدام
Dataset
،dataset.forEachAsync()
هي طريقة مناسبة للتكرار على دفعاتك. - لكل دفعة ، استدعِ
optimizer.minimize(f)
، التي تنفذf
وتقلل من مخرجاتها عن طريق حساب التدرجات اللونية فيما يتعلق بالمتغيرات الأربعة التي حددناها سابقًا. -
f
يحسب الخسارة. تستدعي إحدى وظائف الخسارة المحددة مسبقًا باستخدام توقع النموذج والقيمة الحقيقية.