TensorFlow.js: إنشاء نظام للكشف عن التعليقات غير المرغوب فيها

1. قبل البدء

أصبحت تطبيقات الويب على مدار العقد الماضي أكثر تفاعلاً اجتماعيًا وتفاعليًا، وذلك بفضل إتاحة الوسائط المتعددة والتعليقات والمزيد في الوقت الفعلي على الأرجح من خلال عشرات الآلاف من الأشخاص على موقع إلكتروني رائج بدرجة متوسطة.

وقدم ذلك أيضًا فرصة للمرسلين غير المرغوب فيه لإساءة استخدام هذه الأنظمة وربط محتوى أقل قيمة بالمقالات ومقاطع الفيديو والمشاركات التي كتبها آخرون، وذلك في محاولة لزيادة مستوى الرؤية.

ويمكن تجاوز الأساليب القديمة لاكتشاف الرسائل غير المرغوب فيها، مثل قائمة الكلمات المحظورة، وهي بسهولة لا تتطابق مع برامج التتبع المتقدمة للرسائل غير المرغوب فيها، التي تتطور باستمرار في تعقيدها. واليوم، يمكنك الآن استخدام نماذج تعلُّم الآلة المدرَّبة على اكتشاف المحتوى غير المرغوب فيه.

كان من الممكن عادةً تنفيذ نموذج تعلُّم الآلة لفلترة التعليقات مسبقًا من جهة الخادم، لكن باستخدام TensorFlow.js يمكنك الآن تنفيذ نماذج تعلُّم الآلة من جهة العميل في المتصفّح باستخدام JavaScript. ويمكنك منع الرسائل غير المرغوب فيها قبل أن تلمس النهاية الخلفية، ما قد يؤدي إلى توفير موارد مكلفة من جهة الخادم.

كما هو معروف، في الوقت الحالي أصبحت كلمة "تعلُم الآلة" من الأمور التي لاقت رواجًا في عالم المجال تقريبًا، ولكن كيف يمكنك اتّخاذ الخطوات الأولى لاستخدام هذه الإمكانات كمطوّري برامج على الويب؟

سيوضّح لك هذا الدرس التطبيقي كيفية إنشاء تطبيق ويب من لوحة فارغة يُعالج المشكلة الحقيقية المتمثّلة في التعليقات غير المرغوب فيها باستخدام معالجة اللغات الطبيعية (فن فهم اللغة البشرية باستخدام الكمبيوتر). سيواجه العديد من مطوّري البرامج على الويب هذه المشكلة لأنهم يعملون على واحد من أي عدد متزايد من تطبيقات الويب الرائجة المتوفرة حاليًا، وسيتيح لك هذا الدرس التطبيقي حول الترميز معالجة هذه المشاكل بكفاءة.

المتطلبات الأساسية

تمّت كتابة هذا الدرس التطبيقي حول الترميز لمطوّري البرامج على الويب الذين بدأوا حديثًا في مجال تعلُّم الآلة ويريدون البدء باستخدام نماذج مدرّبة مسبقًا باستخدام TensorFlow.js.

ومن المفترض أن تكون على دراية بكل من HTML5 وCSS وJavaScript في هذا الدرس التطبيقي.

ما ستتعرّف عليه

عليك تنفيذ ما يلي:

  • اطّلِع على مزيد من المعلومات حول المقصود بأداة TensorFlow.js والطرازات المتاحة لمعالجة اللغات الطبيعية.
  • يمكنك إنشاء صفحة ويب بسيطة بتنسيق HTML / CSS / JS لمدونة فيديو وهمية مع قسم للتعليقات في الوقت الفعلي.
  • استخدِم TensorFlow.js لتحميل نموذج تعلُّم الآلة المدرَّب مسبقًا والقادر على ما إذا كان من المحتمل أن تكون الجملة التي يتم إدخالها غير مرغوب فيها أم لا، وفي حال حدوث ذلك، يمكنك تحذير المستخدم بأن تعليقه خاضع للإشراف.
  • ترميز ترميز الجمل بطريقة قابلة للاستخدام بواسطة نموذج تعلُّم الآلة لتصنيفها بعد ذلك
  • تفسير مخرجات نموذج تعلُّم الآلة لتحديد ما إذا كنت تريد الإبلاغ تلقائيًا عن التعليق أم لا يمكن إعادة استخدام تجربة المستخدم الافتراضية هذه على أي موقع إلكتروني قد تعمل عليه، ويتم تعديلها لتناسب أي حالة استخدام من جانب العميل - ربما تكون مدونة عادية أو منتدى أو أي شكل من أنظمة إدارة المحتوى (CMS)، مثل Drupal.

إلى حدٍ كبير. هل من الصعب إجراء ذلك؟ كلا. لنبدأ الاختراق...

المتطلبات اللازمة

  • ويُفضَّل متابعة حساب Glitch.com أو يمكنك استخدام بيئة عرض ويب تناسبك لتعديلها وتشغيلها.

2. ما هو TensorFlow.js؟

1aee0ede85885520.png

TensorFlow.js هي مكتبة تعلُّم آلة مفتوحة المصدر يمكن تشغيلها في أي مكان يتوفّر فيه JavaScript. تعتمد على مكتبة TensorFlow الأصلية المكتوبة بلغة Python وتهدف إلى إعادة إنشاء تجربة مطوّر البرامج هذه ومجموعة من واجهات برمجة التطبيقات لنظام JavaScript.

أين يمكن استخدامها؟

ونظرًا لقابلية نقل JavaScript، يمكنك الآن الكتابة بلغة واحدة وإجراء تعلُم الآلة عبر جميع الأنظمة الأساسية التالية بسهولة:

  • جانب العميل في متصفّح الويب باستخدام الفانيليا JavaScript
  • جانب الخادم وحتى أجهزة IoT، مثل Raspberry Pi باستخدام Node.js
  • تطبيقات سطح المكتب باستخدام Electron
  • التطبيقات المتوافقة مع نظام تشغيل الأجهزة الجوّالة التي تستخدم React Native

ويتيح TensorFlow.js أيضًا العديد من الخلفيات الخلفية في كل بيئة من هذه البيئات (البيئات الفعلية المستندة إلى الأجهزة التي يمكن تنفيذها داخل وحدة المعالجة المركزية (CPU) أو WebGL على سبيل المثال. في حين لا يؤدي استخدام عامل التشغيل هذا إلى توفير بيئة من جهة الخادم، بل يتم في الخلفية تنفيذ عنصر من جانب العميل على WebGL على سبيل المثال لضمان التوافق ومواصلة العمل بسرعة. يوفّر TensorFlow.js حاليًا ما يلي:

  • تنفيذ WebGL على بطاقة الرسومات للجهاز (GPU): هذه هي أسرع طريقة لتنفيذ النماذج الأكبر (أكثر من 3 ميغابايت) باستخدام تسريع وحدة معالجة الرسومات.
  • تنفيذ جمعية الويب (WASM) على وحدة المعالجة المركزية (CPU): لتحسين أداء وحدة المعالجة المركزية (CPU) على الأجهزة، بما في ذلك هواتف الجوّال من الجيل القديم مثلاً. وتُعدّ هذه الطريقة مناسبة أكثر لطرازات أصغر (أقل من 3 ميغابايت) والتي يمكن في الواقع تنفيذها على وحدة المعالجة المركزية (CPU) باستخدام تقنية WASM بشكل أسرع من تلك المتوفّرة في WebGL بناءً على النفقات العامة لتحميل المحتوى إلى معالج الرسومات.
  • تنفيذ وحدة المعالجة المركزية (CPU) - يجب ألا يتوفر أي خيار احتياطي من البيئات الأخرى. دَهْ هُوَّ أَبْطَلْ ثَلَاثْ تَلَاتَة، وِلَكِنْ هَيْكُونْ فِي أَيّْ وَقْتْ دَايْمًا.

ملاحظة: يمكنك اختيار فرض إحدى هذه الخلفية الخلفية إذا كنت تعرف الجهاز الذي ستنفِّذه أو يمكنك السماح لـ TensorFlow.js باتخاذ القرار نيابةً عنك إذا لم تحدِّد ذلك.

الصلاحيات الفائقة من جهة العميل

يمكن أن يؤدي تشغيل TensorFlow.js في متصفح الويب على جهاز العميل إلى العديد من المزايا التي تستحق الاهتمام.

الخصوصية

يمكنك تدريب البيانات وتصنيفها على جهاز العميل بدون إرسال البيانات إلى خادم ويب تابع لجهة خارجية. وقد تكون هناك حالات يكون فيها ذلك شرطًا للالتزام بالقوانين المحلية، مثل اللائحة العامة لحماية البيانات على سبيل المثال، أو عند معالجة أي بيانات قد يريد المستخدم الاحتفاظ بها على جهازه ولا يتم إرسالها إلى جهة خارجية.

السرعة

ونظرًا لأنك لست مضطرًا لإرسال البيانات إلى خادم بعيد، فإن الاستنتاج (إجراء تصنيف البيانات) يمكن أن يكون أسرع. والأفضل من ذلك، لديك إمكانية الدخول المباشر إلى أجهزة استشعار الجهاز، مثل الكاميرا والميكروفون ونظام تحديد المواقع العالمي (GPS) ومقياس التسارع وغيرها في حال منحك المستخدم حق الوصول.

مدى الوصول إلى الجمهور وتوسيع نطاقه

وبنقرة واحدة، يمكن لأي شخص في العالم النقر على رابط ترسله إليه وفتح صفحة الويب في المتصفّح الخاص به والاستفادة من المحتوى الذي أنشأته. لا حاجة إلى إعداد Linux معقّد على الخادم مع برامج تشغيل CUDA وأكثر من ذلك فقط لاستخدام نظام تعلُّم الآلة.

التكلفة

أمّا بدون خوادم، فلست بحاجة إلى دفع أي رسوم إلا عن طريق شبكة توصيل المحتوى (CDN) التي تستضيف ملفات HTML وCSS وJS ونماذج النماذج. إن تكلفة شبكة توصيل المحتوى أقل تكلفة من الاحتفاظ بخادم (يُحتمل أن تكون بطاقة رسومات مرفقة به) تعمل على مدار 24 ساعة طوال أيام الأسبوع.

الميزات من جهة الخادم

يستفيد تفعيل تنفيذ Node.js من TensorFlow.js من الميزات التالية.

دعم CUDA الكامل

على جهة الخادم، لتسريع بطاقة الرسومات، يجب تثبيت برامج تشغيل NVIDIA CUDA لتمكين TensorFlow من العمل مع بطاقة الرسومات (على عكس المتصفح الذي يستخدم WebGL - لا يلزم التثبيت). ومع ذلك، مع دعم CUDA الكامل، يمكنك الاستفادة بشكل كامل من قدرات المستوى الأدنى لبطاقة الرسومات، ما يؤدي إلى الحصول على تدريب أسرع واستنتاجات بشكل أسرع. يتساوى الأداء في الأداء مع تنفيذ Python TensorFlow لأنّ كليهما يشتركان في نفس خلفية C++.

حجم الطراز

وبالنسبة إلى أحدث النماذج من الأبحاث، قد يكون السبب أنّك تتعامل مع نماذج كبيرة جدًا، قد يصل حجمها إلى غيغابايت. لا يمكن حاليًا تشغيل هذه النماذج في متصفح الويب بسبب قيود استخدام الذاكرة لكل علامة تبويب متصفح. لتشغيل هذه النماذج الأكبر حجمًا، يمكنك استخدام Node.js على خادمك الخاص مع مواصفات الأجهزة التي تحتاجها لتشغيل هذا النموذج بكفاءة.

إنترنت الأشياء

تتوفّر عقدة Node.js على أجهزة الكمبيوتر الشائعة ذات اللوحة الواحدة مثل Raspberry Pi، ما يعني أنّه يمكنك تنفيذ نماذج TensorFlow.js على هذه الأجهزة أيضًا.

السرعة

تتم كتابة Node.js بلغة JavaScript، مما يعني أنها تستفيد من التجميع في الوقت المناسب. وهذا يعني أنك قد تلاحظ في كثير من الأحيان مكاسب في الأداء عند استخدام Node.js لأنه سيتم تحسينه في وقت التشغيل، خاصةً لأي معالجة مسبقة قد تجريها. ويمكن الاطّلاع على مثال رائع على ذلك في دراسة الحالة التي توضّح كيفية استخدام ميزة Hugging Face في Node.js للحصول على زيادة في الأداء مضاعفة في نموذج معالجة اللغة الطبيعية.

لقد فهمت الآن أساسيات TensorFlow.js، حيث يمكن تشغيلها، وبعض المزايا التالية، فلنبدأ في تنفيذ إجراءات مفيدة باستخدامها.

3- نماذج مدرّبة مسبقًا

لماذا قد أرغب في استخدام نموذج مدرّب مسبقًا؟

هناك عدد من المزايا للبدء بنموذج شائع مدرّب مسبقًا إذا كان يناسب حالة الاستخدام المطلوبة، مثل:

  1. لست بحاجة إلى جمع بيانات التدريب بنفسك. إنّ إعداد البيانات بالتنسيق الصحيح وتصنيفها حتى يتمكّن نظام تعلُّم الآلة من استخدامها للتعلُّم يمكن أن يستغرق وقتًا طويلاً جدًا ويتكلّف الكثير من الوقت.
  2. امنحك القدرة على صياغة النماذج الأولية للأفكار سريعًا مع تقليل التكلفة والوقت.
    لا جدوى من إعادة تقديم العجلة، عندما يكون النموذج الذي تم تدريبه مسبقًا مناسبًا بما يكفي لتنفيذ ما تحتاج إليه، ما يسمح لك بالتركيز على استخدام المعلومات التي يوفّرها النموذج لتنفيذ أفكارك الإبداعية.
  3. استخدام حالة البحث الفني: غالبًا ما تستند النماذج المدرّبة مسبقًا إلى الأبحاث الرائجة، ما يمنحك إمكانية الاطّلاع على مثل هذه النماذج، مع فهم أدائها أيضًا على أرض الواقع.
  4. سهولة الاستخدام ومستندات شاملة. نظرًا لانتشار هذه النماذج.
  5. إمكانات التعلّم. تقدم بعض النماذج المدرّبة مسبقًا إمكانات تعلُّم النقل، وهي ممارسة نقل المعلومات المستفادة من مهمة تعلُّم الآلة إلى مثال آخر مشابه. على سبيل المثال، يمكن إعادة تدريب نموذج لتدريب الكلاب على التعرّف على الكلاب، إذا قدّمت له بيانات تدريب جديدة. وستكون هذه العملية أسرع لأنّك لن تبدأ باستخدام لوحة فارغة. ويمكن للنموذج استخدام ما تعلّمه بالفعل في التعرّف على القطط للتعرّف على الميزة الجديدة، وهي أنّها تتمتّع بعينين وأذنين أيضًا. أعِد ضبط النموذج على بياناتك الخاصة بسرعة أكبر.

نموذج مدرّب مسبقًا للكشف عن المحتوى غير المرغوب فيه

وستستخدم بنية نموذج "تضمين الكلمات" المتوسط لتلبية احتياجات اكتشاف التعليقات غير المرغوب فيها، ولكن إذا حاولت استخدام نموذج غير مدرّب، لن يكون هذا أفضل من الفرصة العشوائية لتخمين ما إذا كانت الجُمل غير مرغوب فيها أم لا.

ولجعل النموذج مفيدًا، يجب تدريبه على البيانات المخصّصة، ففي هذه الحالة، تسمح له بالتعرّف على شكل التعليقات غير المرغوب فيها مقابل التعليقات غير المرغوب فيها. ومن خلال التعلّم، ستُتاح فرصة أفضل لتصنيف العناصر بشكل صحيح في المستقبل.

ولحسن الحظ، عمل أحد الأشخاص على تدريب هذه البنية الدقيقة للنماذج على مهمة تصنيف التعليقات غير المرغوب فيها، بحيث يمكنك استخدامها كنقطة بداية. قد تجد نماذج أخرى مدرّبة مسبقًا تستخدم بنية النموذج نفسها لتنفيذ إجراءات مختلفة، مثل اكتشاف اللغة التي تمت كتابة التعليق بها، أو توقّع ما إذا كان يجب توجيه بيانات نموذج جهة الاتصال لموقع الويب إلى فريق معين من الشركات تلقائيًا استنادًا إلى النص المكتوب مثل (استفسار المنتج) أو الهندسة (خطأ فني أو ملاحظات). ومن خلال توفُّر بيانات تدريبية كافية، يمكن أن يتعلّم نموذج مثل هذا تصنيف هذا النص في كل حالة لمنح تطبيقك على الويب إمكانات متميّزة وتحسين كفاءة مؤسستك.

في درس تطبيقي حول الترميز المستقبلي، ستتعرّف على كيفية استخدام "أداة إنشاء النماذج" لإعادة تدريب نموذج التعليقات غير المرغوب فيها هذا الذي تم تدريبه مسبقًا وتحسين أدائه استنادًا إلى بيانات تعليقاتك. حاليًا، ستستخدم نموذج رصد التعليقات غير المرغوب فيها الحالي كنقطة بداية للحصول على تطبيق الويب الأولي كنموذج أوّلي.

تم نشر نموذج رصد التعليقات غير المرغوب فيها المدرَّب مسبقًا على موقع إلكتروني يُعرف باسم TF Hub، وهو مستودع نماذج تعلُّم الآلة تُديره Google، حيث يمكن لمهندسي تعلُّم الآلة نشر النماذج المعدة مسبقًا للعديد من حالات الاستخدام الشائعة (مثل النصوص والرؤية والصوت وغير ذلك لحالات استخدام معيّنة ضمن كل فئة من هذه الفئات). يمكنك الآن تنزيل ملفات النماذج في الوقت الحالي لاستخدامها في تطبيق الويب لاحقًا في هذا الدرس التطبيقي حول الترميز.

انقر على زر التنزيل لنموذج JavaScript، كما هو موضّح أدناه:

ab65deff89b3d939.png

4. بدء عملية الإعداد

المتطلبات اللازمة

  • متصفح ويب حديث.
  • معرفة أساسية بـ HTML وCSS وJavaScript وChrome DevTools (عرض مخرجات وحدة التحكم).

لنبدأ بالترميز.

لقد أنشأنا نموذجًا Glitch.com Node.js Express boilerplate للبدء منه، يمكنك استنساخه كحالة أساسية لمختبر الرمز هذا بنقرة واحدة فقط.

ما عليك سوى النقر على الزر "remix this" لتسجيله وإنشاء مجموعة جديدة من الملفات التي يمكنك تعديلها.

يوفّر لنا هذا الهيكل العظمي البسيط الملفات التالية داخل المجلد www:

  1. صفحة HTML (index.html)
  2. ورقة الأنماط (style.css)
  3. ملف لكتابة رمز JavaScript (script.js)

ولتسهيل الأمر عليك، أضفنا أيضًا في ملف HTML استيرادًا لمكتبة TensorFlow.js التي تبدو كما يلي:

index.html

<!-- Import TensorFlow.js library -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js" type="text/javascript"></script>

بعد ذلك، يتم عرض مجلد www هذا من خلال خادم Node Express بسيط من خلال package.json وserver.js

5. نموذج نموذجي HTML

ما هي نقطة البداية؟

تتطلب جميع النماذج الأولية بعض سقالات HTML الأساسية التي يمكنك عرض النتائج عليها. إعداد ذلك الآن. أنت بصدد إضافة:

  • عنوان للصفحة
  • نص وصفي
  • فيديو نائب يمثّل إدخال مدونة الفيديو
  • منطقة لعرض التعليقات وكتابتها

افتح index.html والصق الرمز الحالي مع ما يلي لإعداد الميزات المذكورة أعلاه:

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>My Pretend Video Blog</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Import the webpage's stylesheet -->
    <link rel="stylesheet" href="/style.css">
  </head>  
  <body>
    <header>
      <h1>MooTube</h1>
      <a id="login" href="#">Login</a>
    </header>
    
    <h2>Check out the TensorFlow.js rap for the show and tell!</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ipsum quam, tincidunt et tempor in, pulvinar vel urna. Nunc eget erat pulvinar, lacinia nisl in, rhoncus est. Morbi molestie vestibulum nunc. Integer non ipsum dolor. Curabitur condimentum sem eget odio dapibus, nec bibendum augue ultricies. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Sed iaculis ut ligula sed tempor. Phasellus ac dictum felis. Integer arcu dui, facilisis sit amet placerat sagittis, blandit sit amet risus.</p>
    
    <iframe width="100%" height="500" src="https://www.youtube.com/embed/RhVs7ijB17c" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

    <section id="comments" class="comments">
      <div id="comment" class="comment" contenteditable></div>
      <button id="post" type="button">Comment</button>

      <ul id="commentsList">
        <li>
          <span class="username">NotASpammer</span>
          <span class="timestamp">3/18/2021, 6:52:16 PM</span> 
          <p>I am not a spammer, I am a good boy.</p>
        </li>
        <li>
          <span class="username">SomeUser</span>
          <span class="timestamp">2/11/2021, 3:10:00 PM</span>
          <p>Wow, I love this video, so many amazing demos!</p>
        </li>
      </ul>
    </section>
    

    <!-- Import TensorFlow.js library -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js" type="text/javascript"></script>

    <!-- Import the page's JavaScript to do some stuff -->
    <script type="module" src="/script.js"></script>
  </body>
</html>

تحليل

دعنا نحلل بعض رموز HTML الموضحة أعلاه لتمييز بعض العناصر الرئيسية التي أضفتها.

  • لقد أضفت علامة <h1> لعنوان الصفحة بالإضافة إلى علامة <a> لزر تسجيل الدخول، وكل ذلك مضمّن في <header>. أضفت بعد ذلك <h2> إلى عنوان المقالة وعلامة <p> لوصف الفيديو. ما من شيء خاص هنا.
  • لقد أضفتَ علامة iframe التي تتضمّن فيديو عشوائيًا على YouTube. في الوقت الحالي، أنت تستخدم موسيقى راب من TensorFlow.js كعنصر نائب، ولكن يمكنك وضع أي فيديو تريده هنا ببساطة عن طريق تغيير عنوان URL لإطار iframe. وفي الواقع، سيتم عرض كل هذه القيم في الخلفية على موقع إلكتروني للإنتاج بشكل ديناميكي، بناءً على الصفحة التي يتم عرضها.
  • أخيرًا، تمت إضافة section مع معرّف وفئة من &quot؛comments" والتي تحتوي على div قابل للتعديل لكتابة تعليقات جديدة مع button لإرسال التعليق الجديد الذي تريد إضافته مع قائمة تعليقات غير مرتبة. ولديك اسم المستخدم ووقت النشر ضمن علامة span داخل كل عنصر من عناصر القائمة، ثم وأخيرًا التعليق نفسه في علامة p. يتم حاليًا ترميز مثالَين للتعليقات على أنّها عنصر نائب.

إذا عاينت النتيجة الآن، من المفترض أن تظهر الصورة بالشكل التالي:

73c8338334d5b251.png

يبدو الأمر سيئًا جدًا، لذا حان الوقت لإضافة بعض النمط...

6- إضافة نمط

الإعدادات التلقائية للعناصر

أولاً، يمكنك إضافة أنماط لعناصر HTML التي أضفتها للتو لضمان عرضها بشكل صحيح.

ابدأ بتطبيق إعادة ضبط CSS للحصول على نقطة بداية للتعليق في جميع المتصفحات ونظام التشغيل. استبدل محتوى style.css بما يلي:

style.css

/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/
a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:'';content:none}table{border-collapse:collapse;border-spacing:0}

بعد ذلك، أضِف بعض أنماط CSS المفيدة إلى واجهة المستخدم.

أضف ما يلي إلى نهاية style.css أسفل رمز إعادة ضبط CSS الذي أضفته أعلاه:

style.css

/* CSS files add styling rules to your content */
body {
  background: #212121;
  color: #fff;
  font-family: helvetica, arial, sans-serif;
}

header {
  background: linear-gradient(0deg, rgba(7,7,7,1) 0%, rgba(7,7,7,1) 85%, rgba(55,52,54,1) 100%);
  min-height: 30px;
  overflow: hidden;
}

h1 {
  color: #f0821b;
  font-size: 24pt;
  padding: 15px 25px;
  display: inline-block;
  float: left;
}

h2, p, section, iframe {
  background: #212121;
  padding: 10px 25px;
}

h2 {
  font-size: 16pt;
  padding-top: 25px;
}

p {
  color: #cdcdcd;
}

iframe {
  display: block;
  padding: 15px 0;
}

header a, button {
  color: #222;
  padding: 7px;
  min-width: 100px;
  background: rgb(240, 130, 30);
  border-radius: 3px;
  border: 1px solid #3d3d3d;
  text-transform: uppercase;
  font-weight: bold;
  cursor: pointer;
  transition: background 300ms ease-in-out;
}

header a {
  background: #efefef;
  float: right;
  margin: 15px 25px;
  text-decoration: none;
  text-align: center;
}

button:focus, button:hover, header a:hover {
  background: rgb(260, 150, 50);
}

.comment {
  background: #212121;
  border: none;
  border-bottom: 1px solid #888;
  color: #fff;
  min-height: 25px;
  display: block;
  padding: 5px;
}

.comments button {
  float: right;
  margin: 5px 0;
}

.comments button, .comment {
  transition: opacity 500ms ease-in-out;
}

.comments ul {
  clear: both;
  margin-top: 60px;
}

.comments ul li {
  margin-top: 5px;
  padding: 10px;
  transition: background 500ms ease-in-out;
}

.comments ul li * {
  background: transparent;
}

.comments ul li:nth-child(1) {
  background: #313131;
}

.comments ul li:hover {
  background: rgb(70, 60, 10);
}

.username, .timestamp {
  font-size: 80%;
  margin-right: 5px;
}

.username {
  font-weight: bold;
}

.processing {
  opacity: 0.3;
  filter: grayscale(1);
}

.comments ul li.spam {
  background-color: #d32f2f;
}

.comments ul li.spam::after {
  content: "⚠";
  margin: -17px 2px;
  zoom: 3;
  float: right;
}

رائع! هذا كل ما تحتاج إليه. إذا تمت كتابة الأنماط بنجاح باستخدام الجزءين من الرمز أعلاه، من المفترض أن تبدو المعاينة المباشرة الآن على النحو التالي:

b86be8e2f6e7456.png

يتم تلقائيًا تفعيل "الوضع الليلي" و"CSS" الساحر للحصول على تأثيرات التمرير في العناصر الرئيسية. أحسنت. والآن عليك بدمج بعض المنطق السلوكي باستخدام JavaScript.

7- JavaScript: معالجات DOM ومعالجات الأحداث

الإشارة إلى عناصر DOM الرئيسية

يجب التأكُّد أولاً من إمكانية وصولك إلى الأجزاء الرئيسية في الصفحة التي ستحتاج إلى التلاعب بها أو الوصول إليها لاحقًا في الرمز، بالإضافة إلى تحديد بعض ثوابت فئات CSS للتصميم.

ابدأ باستبدال محتوى script.js بالثوابت التالية:

Script.js

const POST_COMMENT_BTN = document.getElementById('post');
const COMMENT_TEXT = document.getElementById('comment');
const COMMENTS_LIST = document.getElementById('commentsList');
// CSS styling class to indicate comment is being processed when
// posting to provide visual feedback to users.
const PROCESSING_CLASS = 'processing';

// Store username of logged in user. Right now you have no auth
// so default to Anonymous until known.
var currentUserName = 'Anonymous';

التعامل مع نشر التعليقات

بعد ذلك، أضِف أداة معالجة الحدث والتعامل معه إلى POST_COMMENT_BTN حتى يتمكّن من الحصول على نص التعليق المكتوب وضبط فئة CSS للإشارة إلى أن المعالجة قد بدأت. يُرجى العلم أنّك لم تنقر على الزر في حال كانت المعالجة قيد التنفيذ حاليًا.

script.js

/** 
 * Function to handle the processing of submitted comments.
 **/
function handleCommentPost() {
  // Only continue if you are not already processing the comment.
  if (! POST_COMMENT_BTN.classList.contains(PROCESSING_CLASS)) {
    POST_COMMENT_BTN.classList.add(PROCESSING_CLASS);
    COMMENT_TEXT.classList.add(PROCESSING_CLASS);
    let currentComment = COMMENT_TEXT.innerText;
    console.log(currentComment);
    
    // TODO: Fill out the rest of this function later.
  }
}

POST_COMMENT_BTN.addEventListener('click', handleCommentPost);

رائع! في حال إعادة تحميل صفحة الويب ومحاولة نشر تعليق، من المُفتَرض أن يظهر لك الآن زر التعليق والنص باللون الرمادي، وفي وحدة التحكّم، من المفترض أن يظهر لك التعليق المطبوع كما يلي:

827b5f3d09afbb21.png

لديك الآن بنية HTML / CSS / JS أساسية، حان الوقت لإعادة لفت انتباهك إلى نموذج تعلّم الآلة حتى تتمكن من دمج هذه الصفحة مع صفحة الويب الرائعة.

8- تقديم نموذج تعلُّم الآلة

أنت مستعد تقريبًا لتحميل النموذج. ومع ذلك، قبل أن تتمكّن من إجراء ذلك، عليك تحميل ملفات النماذج التي تم تنزيلها في وقت سابق من الدرس التطبيقي إلى موقعك الإلكتروني حتى تتم استضافتها ويمكن استخدامها داخل الرمز.

يجب أوّلاً فك ضغط الملفات التي نزّلتها للنموذج في بداية هذا الدرس التطبيقي، في حال لم يسبق لك تنفيذ ذلك. من المفترض أن يظهر لك دليل يحتوي على الملفات التالية في:

5634d536ef8be9ca.png

ما هي الأدوات المتوفّرة لديك؟

  • model.json: هذا هو أحد الملفات التي تشكّل نموذج TensorFlow.js المُدرَّب. ستشير فعليًا إلى هذا الملف المحدّد لاحقًا في رمز TensorFlow.js.
  • group1-shard1of1.bin: هذا ملف ثنائي يحتوي على القيم التقديرية المتدرّبة (مجموعة من الأرقام التي تعلّمتها لتنفيذ مهمة التصنيف بشكل جيّد) من نموذج TensorFlow.js ويجب استضافته في مكان ما على الخادم للتنزيل.
  • vocab - هذا الملف الغريب الذي ليس له إضافة هو شيء من مصمم النماذج يوضح لنا كيفية ترميز الكلمات في الجمل حتى يتمكن النموذج من فهم كيفية استخدامها. ستستعرض المزيد من التفاصيل في القسم التالي.
  • labels.txt: يحتوي هذا ببساطة على أسماء الفئات الناتجة التي سيتوقّعها النموذج. بالنسبة إلى هذا النموذج، في حال فتح هذا الملف في محرِّر النصوص يحتوي فقط على &quot؛false"&&&;;&;;true" مُدرج أو يشير إلى &&;رسالة غير مرغوب فيها&&; أو غير مرغوب فيه أو أو & صلاحية غير مرغوب فيها & ;

استضافة ملفات نموذج TensorFlow.js

ابدأ في أول model.json و*.bin من الملفات التي تم إنشاؤها على خادم ويب حتى تتمكن من الوصول إليها عبر صفحة الويب.

تحميل الملفات إلى glgl

  1. انقر على مجلد مواد العرض في اللوحة اليمنى لمشروع Glitch.
  2. انقر على تحميل مادة عرض واختَر group1-shard1of1.bin لتحميلها إلى هذا المجلد. من المفترض أن يظهر الآن على النحو التالي بعد التحميل:

25a2251c7f165184.png

  1. رائع! عليك الآن تنفيذ الإجراء نفسه لملف model.json. يجب وضع ملفَين في مجلد مواد العرض كما يلي:

51a6dbd5d3097ffc.png

  1. انقر على ملف group1-shard1of1.bin الذي حمّلته للتو. ستتمكن من نسخ عنوان URL إلى موقعه. انسخ هذا المسار الآن كما هو موضح:

92ded8d46442c404.png

  1. الآن في أسفل يمين الشاشة، انقر على الأدوات &gt؛ الوحدة الطرفية. انتظر حتى يتم تحميل نافذة الوحدة الطرفية. بعد التحميل، اكتب ما يلي، ثم اضغط على Enter لتغيير الدليل إلى مجلد www:

مبنى الركاب:

cd www
  1. بعد ذلك، استخدِم wget لتنزيل الملفَين اللذين تم تحميلهما للتو من خلال استبدال عناوين URL أدناه بعناوين URL التي أنشأتها للملفات في مجلد مواد العرض في Glitch (تحقَّق من مجلد مواد العرض لكل ملف عنوان URL مخصّص). لاحظ أن المسافة بين عنواني URL تختلف عن عناوين URL التي تحتاج إلى استخدامها، ولكنها تبدو متشابهة:

المحطة

wget https://cdn.glitch.com/1cb82939-a5dd-42a2-9db9-0c42cab7e407%2Fmodel.json?v=1616111344958 https://cdn.glitch.com/1cb82939-a5dd-42a2-9db9-0c42cab7e407%2Fgroup1-shard1of1.bin?v=1616017964562

رائع، لقد أنشأت الآن نسخة من الملفات التي تم تحميلها إلى مجلد www ولكن سيتم تنزيلها الآن بأسماء غريبة.

  1. اكتب ls في الوحدة الطرفية واضغط على Enter. ستظهر لك رسالة كالتالية:

9cc90f1d053f517f.png

  1. باستخدام الأمر mv، يمكنك إعادة تسمية الملفات. اكتب ما يلي في وحدة التحكم واضغط على <kbd>Enter</kbd> أو <kbd>return</kbd> بعد كل سطر:

المحطة الطرفية:

mv *group1-shard1of1.bin* group1-shard1of1.bin
mv *model.json* model.json
  1. أخيرًا، عليك إعادة تحميل مشروع Glitch من خلال كتابة refresh في الوحدة الطرفية والضغط على <kbd>Enter</kbd>:

المحطة الطرفية:

refresh
  1. بعد التحديث، سيظهر لك model.json وgroup1-shard1of1.bin في المجلد www على واجهة المستخدم:

50dd98c0a8f3e629.png

رائع! ويمكنك الآن استخدام ملفات النموذج المحمّلة مع بعض الرموز الفعلية في المتصفّح.

9- تحميل &amp؛ استخدام نموذج TensorFlow.js المستضاف

أنت الآن في مرحلة يمكنك من خلالها اختبار تحميل نموذج TensorFlow.js الذي تم تحميله مع بعض البيانات للتحقق مما إذا كان يعمل.

في الوقت الحالي، سيبدو نموذج إدخال البيانات الذي سيظهر لك أدناه غامضًا (مجموعة من الأرقام)، وسيتم توضيح كيفية إنشاء البيانات في القسم التالي. وما عليك سوى عرضه كمصفوفة من الأرقام في الوقت الحالي. في هذه المرحلة، من المهم أن تختبر أن النموذج يمنحنا إجابة بدون خطأ.

أضِف الرمز التالي إلى نهاية ملف script.js، وتأكّد من استبدال قيمة السلسلة MODEL_JSON_URL بمسار ملف model.json الذي أنشأته عند تحميل الملف إلى مجلد "مواد عرض Glitch" في الخطوة السابقة. (تذكَّر أنّه يمكنك ببساطة النقر على الملف في مجلد مواد العرض في Glitch للعثور على عنوان URL).

اقرأ تعليقات الرمز الجديد أدناه لمعرفة ما يقوم به كل سطر:

script.js

// Set the URL below to the path of the model.json file you uploaded.
const MODEL_JSON_URL = 'model.json';
// Set the minimum confidence for spam comments to be flagged.
// Remember this is a number from 0 to 1, representing a percentage
// So here 0.75 == 75% sure it is spam.
const SPAM_THRESHOLD = 0.75;

// Create a variable to store the loaded model once it is ready so 
// you can use it elsewhere in the program later.
var model = undefined;


/** 
 * Asynchronous function to load the TFJS model and then use it to
 * predict if an input is spam or not spam.
 */
async function loadAndPredict(inputTensor) {
  // Load the model.json and binary files you hosted. Note this is 
  // an asynchronous operation so you use the await keyword
  if (model === undefined) {
    model = await tf.loadLayersModel(MODEL_JSON_URL);
  }
  
  // Once model has loaded you can call model.predict and pass to it
  // an input in the form of a Tensor. You can then store the result.
  var results = await model.predict(inputTensor);
  
  // Print the result to the console for us to inspect.
  results.print();
  
  // TODO: Add extra logic here later to do something useful
}

loadAndPredict(tf.tensor([[1,3,12,18,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]));

في حال إعداد المشروع بشكل صحيح، من المفترض أن ترى الآن شيئًا مثل ما يلي المطبوع على نافذة وحدة التحكم، عند استخدام النموذج الذي حمّلته لتوقع نتيجة من الإدخال الذي تم تمريره إليه:

e72acc17383bec33.png

في وحدة التحكّم، سيظهر لك رقمان مطبوعان:

  1. 0.9996011
  2. 0.0003989

وعلى الرغم من أنّ هذه الأرقام قد تبدو مشفرة، تمثّل هذه الأرقام احتمالية لما يمثّله النموذج في أنّه التصنيف الذي أدخلته. ولكن ما المقصود بها؟

إذا فتحت ملف labels.txt من ملفات النماذج التي تم تنزيلها على جهازك المحلي، سترى أن ذلك يحتوي أيضًا على حقلين:

  1. خطأ
  2. صحيح

وبالتالي، يشير النموذج في هذه الحالة إلى أن نسبة الإدخال 99.96011% متأكدة (الموضّحة في عنصر النتيجة كـ 0.9996011) أنّ القيمة التي أدخلتها هي ([1,3,12,18,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]) كانت ليست رسالة غير مرغوب فيها (أي خطأ).

ملاحظة: كانت القيمة false هي أول تصنيف في labels.txt ويتم تمثيلها بالمخرجات الأولى من لوحة التحكّم، وهي الطريقة التي تعرف بها التوقّعات الناتجة.

حسنًا، أصبحت تعرف الآن كيفية تفسير المخرجات، ولكن ما هي مجموعة الأرقام الكبيرة التي تمت إضافتها على أنها الإدخال وكيف يمكنك تحويل الجمل إلى هذا التنسيق كي يستخدمها النموذج؟ لتنفيذ هذا الإجراء، يجب أن تتعلّم كيفية إنشاء الرموز المميّزة وأداة Tensors. يُرجى مواصلة القراءة للاطّلاع على التفاصيل.

10- إنشاء الرمز المميّز وأداة Tensors

إنشاء رمز مميز

لذا اتضح أن نماذج تعلُم الآلة لا يمكنها قبول سوى مجموعة من الأرقام كإدخالات. ما السبب؟ ويعود السبب في ذلك في الأساس إلى أنّ نموذج تعلُّم الآلة يمثّل في الأساس مجموعة من العمليات الحسابية المرتبطة بسلاسل، وبالتالي إذا مرّرت إليه موضوعًا ليس رقمًا، ستواجه صعوبة في التعامل معه. وبذلك يصبح السؤال الآن كيف يمكنك تحويل هذه الجمل إلى أرقام لاستخدامها مع النموذج الذي حمّلته؟

تختلف العملية تحديدًا من نموذج إلى آخر، ولكن بالنسبة إلى هذا النموذج، هناك ملف آخر في ملفات النموذج التي نزّلتها بعنوان vocab,، وهذا هو مفتاح طريقة ترميز البيانات.

افتح vocab في محرِّر نصوص محلي على جهازك وسترى ما يلي:

81e8bca3fbf62429.png

يشكّل هذا الجدول أساسيًا للبحث عن كيفية تحويل الكلمات المفيدة التي تعلّمها النموذج إلى أرقام يمكنه فهمها. هناك أيضًا بعض الحالات الخاصة في أعلى الملف <PAD> و<START> و<UNKNOWN>:

  • <PAD> - هذا العنوان قصير الأخصى ";&&;;.. تبيّن أنّ نماذج تعلُّم الآلة ترغب في الحصول على عدد ثابت من الإدخالات بغض النظر عن مدّة الجملة. يتوقع النموذج المستخدَم أن يكون هناك دائمًا 20 رقمًا للإدخال (أي تم تحديده من قِبل منشئ النموذج ويمكن تغييره إذا أعدت تدريب النموذج). لذلك، إذا كانت لديك عبارة مثل "&أنا أحب الفيديو"، ستملأ المسافات المتبقية في المصفوفة باستخدام 0's الذي يمثل الرمز المميز <PAD>. وإذا كانت الجملة أكبر من 20 كلمة، ستحتاج إلى تقسيمها بحيث تتناسب مع هذا الشرط، وبدلاً من ذلك يتم إجراء تصنيفات متعددة على العديد من الجُمل الصغيرة.
  • <START>: هذا هو دائمًا أول رمز مميّز للإشارة إلى بداية الجملة. ستلاحظ في نموذج الإدخال التالي أن مصفوفة الأرقام بدأت بـ "&&;1" - كان هذا يمثل الرمز المميز <START>.
  • <UNKNOWN> - كما قد تكون خمنت، إذا كانت الكلمة غير موجودة في عملية البحث عن الكلمات هذه، يمكنك ببساطة استخدام الرمز المميز <UNKNOWN> (الذي يمثله &&;2" على أنه الرقم.

وبالنسبة إلى كل كلمة أخرى، فإنها تكون موجودة في البحث ولها رقم خاص مرتبط بها، لذا يمكنك استخدامها أو عدم وجودها. وفي هذه الحالة، يمكنك استخدام رقم الرمز <UNKNOWN> بدلاً من ذلك.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Take another look at the input used in the prior code you ran:

[1,3,12,18,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

ستلاحظ الآن أنّ هذه الجملة كانت عبارة عن جملة مكوّنة من 4 كلمات لأنّ الرمز الباقي هو <START> أو رمز مميّز (<PAD>) وهناك 20 رقمًا في الصفيف. تَمَامْ، بَدْءِ الْمَعْلُومَة أَكْتَرْ شِوَيَّة.

العبارة التي كتبتها في هذا الإطار هي: "أحب كلبتي" يمكنك أن ترى من لقطة الشاشة أعلاه أن "I" تم تحويلها إلى الرقم &quot؛ 3&quot؛ وهو صحيح. وإذا بحثت عن الكلمات الأخرى، ستعثر على الأرقام المقابلة لها أيضًا.

أجهزة الاستشعار

هناك عقبة أخيرة قبل أن يقبل نموذج تعلّم الآلة مشاركتك الرقمية. يجب تحويل مصفوفة الأرقام إلى شيء يُعرف باسم Tensor، ونعم، خمنت ذلك، تم تسمية TensorFlow بعد هذه العناصر، وهو تدفق Tensors من خلال نموذج بشكل أساسي.

ما هو مصدر Tensor؟

التعريف الرسمي من TensorFlow.org مفاده:

"المستشعرات هي مصفوفات متعددة الأبعاد ولها نوع موحّد. كل سنوتات غير قابلة للتغيير: لا يمكنك مطلقًا تعديل محتوى Tensor، وإنشاء محتوى جديد فقط.

باللغة الإنجليزية البسيطة، هي اسم رياضي راقٍ لمجموعة من أي أبعاد تحتوي على بعض الوظائف الأخرى المضمّنة في عنصر Tensor Object، وتكون مفيدة لنا كمطوّري تقنية لتعلّم الآلة. جدير بالذكر أنّ Tensors تُخزِّن البيانات من نوع واحد فقط، مثل جميع الأعداد الصحيحة أو جميع أرقام النقاط العائمة، وبعد إنشائها، لا يمكنك تغيير محتوى Tensor مطلقًا، لذلك يمكنك اعتباره مربّع تخزين دائمًا للأرقام.

لا تقلق كثيرًا بشأن هذا الأمر في الوقت الحالي. وعلى أقل تقدير، اعتبِرها كآلية تخزين متعدّدة الأبعاد لنماذج تعلُّم الآلة التي تعمل معها إلى أن تعمّق في قراءة كتاب جيد كهذا الكتاب، وننصح بشدة باستخدام هذه السمة إذا أردت معرفة المزيد من المعلومات عن أدوات Tensor وكيفية استخدامها.

اختصاص الميزات: Tensorsors and Tokenization

إذًا، كيف تستخدم ملف vocab هذا في الرمز؟ نشكرك على طرح هذا السؤال.

هذا الملف في ما يخصه غير مفيد كثيرًا لك بصفتك مطوّر برامج JavaScript. لولا عنصر JavaScript، يمكنك استيراده واستخدامه بسهولة. يمكن أن ترى كيف يمكن أن يكون من السهل جدًا تحويل البيانات في هذا الملف إلى تنسيق أكثر مثل هذا:

// Special cases. Export as constants.
export const PAD =  0;
export const START = 1;
export const UNKNOWN = 2;

// Export a lookup object.
export const LOOKUP = {
  "i": 3,
  "check": 4,
  "video": 5,
  "song": 6,
  "com": 7,
  "please": 8,
  "like": 9
  // and all the other words...
}

وباستخدام محرر النصوص المفضّل لديك، يمكنك بسهولة تحويل ملف vocab إلى أن يكون بتنسيق معيّن مع بعض البحث والاستبدال. يمكنك أيضًا استخدام هذه الأداة المصمّمة مسبقًا لتسهيل ذلك.

عند إجراء هذا العمل مسبقًا وحفظ ملف vocab بالتنسيق الصحيح، سيتم منعك من إجراء هذه الإحالة الناجحة والتحليل في كل تحميل صفحة، ما يؤدي إلى هدر موارد وحدة المعالجة المركزية (CPU). والأفضل من ذلك، تحتوي عناصر JavaScript على السمات التالية:

"يمكن أن يكون اسم خاصية الكائن أي سلسلة JavaScript صالحة أو أي شيء يمكن تحويله إلى سلسلة، بما في ذلك السلسلة الفارغة. ومع ذلك، لا يمكن الوصول إلى أي اسم موقع ليس معرّف JavaScript صالحًا (على سبيل المثال، اسم موقع يحتوي على مسافة أو واصلة أو يبدأ برقم) إلا باستخدام علامة قوس مربعة، وما إلى ذلك.

وبالتالي طالما أنك تستخدم علامة قوس مربعة، يمكنك إنشاء جدول بحث فعّال إلى حد ما من خلال هذا التحويل البسيط.

تحويل المحتوى إلى تنسيق أكثر فائدة

حوِّل ملف كلمة المرور إلى التنسيق أعلاه، سواء يدويًا بنفسك من خلال محرِّر النصوص أو باستخدام هذه الأداة هنا. احفظ النتيجة الناتجة بتنسيق dictionary.js في مجلد www.

وفي تطبيق Glitch، يمكنك ببساطة إنشاء ملف جديد في هذا المكان ولصقه في نتيجة التحويل لحفظه على النحو التالي:

c80f68535c92baf.gif

بعد أن يصبح لديك ملف dictionary.js محفوظ بالتنسيق أعلاه، يمكنك الآن إضافة الرمز التالي إلى أعلى script.js لاستيراد وحدة dictionary.js التي كتبتها للتو. ويمكنك هنا أيضًا تحديد ENCODING_LENGTH ثابتة إضافية لكي تعرف مقدار المحتوى الذي يمكن إضافته لاحقًا في الرمز، إلى جانب دالة tokenize التي ستستخدمها لتحويل مجموعة من الكلمات إلى موتّر مناسب يمكن استخدامه كإدخال في النموذج.

يُرجى الاطّلاع على التعليقات في الرمز أدناه لمعرفة المزيد من المعلومات حول وظيفة كل سطر:

script.js

import * as DICTIONARY from '/dictionary.js';

// The number of input elements the ML Model is expecting.
const ENCODING_LENGTH = 20;


/** 
 * Function that takes an array of words, converts words to tokens,
 * and then returns a Tensor representation of the tokenization that
 * can be used as input to the machine learning model.
 */
function tokenize(wordArray) {
  // Always start with the START token.
  let returnArray = [DICTIONARY.START];
  
  // Loop through the words in the sentence you want to encode.
  // If word is found in dictionary, add that number else
  // you add the UNKNOWN token.
  for (var i = 0; i < wordArray.length; i++) {
    let encoding = DICTIONARY.LOOKUP[wordArray[i]];
    returnArray.push(encoding === undefined ? DICTIONARY.UNKNOWN : encoding);
  }
  
  // Finally if the number of words was < the minimum encoding length
  // minus 1 (due to the start token), fill the rest with PAD tokens.
  while (i < ENCODING_LENGTH - 1) {
    returnArray.push(DICTIONARY.PAD);
    i++;
  }
  
  // Log the result to see what you made.
  console.log([returnArray]);
  
  // Convert to a TensorFlow Tensor and return that.
  return tf.tensor([returnArray]);
}

رائع، والآن ارجع إلى دالة handleCommentPost() واستبدلها بهذا الإصدار الجديد من الدالة.

اطّلع على الرمز للتعليقات على ما أضفته:

script.js

/** 
 * Function to handle the processing of submitted comments.
 **/
function handleCommentPost() {
  // Only continue if you are not already processing the comment.
  if (! POST_COMMENT_BTN.classList.contains(PROCESSING_CLASS)) {
    // Set styles to show processing in case it takes a long time.
    POST_COMMENT_BTN.classList.add(PROCESSING_CLASS);
    COMMENT_TEXT.classList.add(PROCESSING_CLASS);
    
    // Grab the comment text from DOM.
    let currentComment = COMMENT_TEXT.innerText;
    // Convert sentence to lower case which ML Model expects
    // Strip all characters that are not alphanumeric or spaces
    // Then split on spaces to create a word array.
    let lowercaseSentenceArray = currentComment.toLowerCase().replace(/[^\w\s]/g, ' ').split(' ');
    
    // Create a list item DOM element in memory.
    let li = document.createElement('li');
    
    // Remember loadAndPredict is asynchronous so you use the then 
    // keyword to await a result before continuing.
    loadAndPredict(tokenize(lowercaseSentenceArray), li).then(function() {
      // Reset class styles ready for the next comment.
      POST_COMMENT_BTN.classList.remove(PROCESSING_CLASS);
      COMMENT_TEXT.classList.remove(PROCESSING_CLASS);
      
      let p = document.createElement('p');
      p.innerText = COMMENT_TEXT.innerText;
      
      let spanName = document.createElement('span');
      spanName.setAttribute('class', 'username');
      spanName.innerText = currentUserName;
      
      let spanDate = document.createElement('span');
      spanDate.setAttribute('class', 'timestamp');
      let curDate = new Date();
      spanDate.innerText = curDate.toLocaleString();
      
      li.appendChild(spanName);
      li.appendChild(spanDate);
      li.appendChild(p);
      COMMENTS_LIST.prepend(li);

      // Reset comment text.
      COMMENT_TEXT.innerText = '';
    });
  }
}

أخيرًا، عدّل وظيفة loadAndPredict() لضبط نمط إذا تم اكتشاف تعليق على أنّه غير مرغوب فيه.

في الوقت الحالي، ما عليك سوى تغيير النمط، ولكن يمكنك لاحقًا اختيار تعليق التعليق إلى حد ما من بين قائمة انتظار الإشراف أو منع إرساله.

script.js

/** 
 * Asynchronous function to load the TFJS model and then use it to
 * predict if an input is spam or not spam.
 */
async function loadAndPredict(inputTensor, domComment) {
  // Load the model.json and binary files you hosted. Note this is 
  // an asynchronous operation so you use the await keyword
  if (model === undefined) {
    model = await tf.loadLayersModel(MODEL_JSON_URL);
  }
  
  // Once model has loaded you can call model.predict and pass to it
  // an input in the form of a Tensor. You can then store the result.
  var results = await model.predict(inputTensor);
  
  // Print the result to the console for us to inspect.
  results.print();

  results.data().then((dataArray)=>{
    if (dataArray[1] > SPAM_THRESHOLD) {
      domComment.classList.add('spam');
    }
  })
}

11- التعديلات في الوقت الفعلي: Node.js + Websockets

لديك الآن واجهة أمامية تعمل على اكتشاف المحتوى غير المرغوب فيه، إلا أن الجزء الأخير من اللغز هو استخدام Node.js مع بعض مآخذ الويب للاتصال في الوقت الفعلي وتحديث أي تعليقات لا تتم إضافتها إلى المحتوى غير المرغوب فيه في الوقت الفعلي.

Socket.io

Socket.io هو واحد من أكثر الطرق شيوعًا (في وقت الكتابة) لاستخدام المقابس على الويب مع Node.js. تابِع وأطلب من Glitch أن تريد تضمين مكتبة Socket.io في الإصدار من خلال تعديل package.json في دليل المستوى الأعلى (في المجلد الرئيسي لمجلد www) لتضمين socket.io كأحد التبعيات:

package. json

{
  "name": "tfjs-with-backend",
  "version": "0.0.1",
  "description": "A TFJS front end with thin Node.js backend",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.17.1",
    "socket.io": "^4.0.1"
  },
  "engines": {
    "node": "12.x"
  }
}

رائع! بعد التحديث، حدِّث index.html في المجلد www مرة أخرى لتضمين مكتبة socket.io.

ما عليك سوى وضع سطر الرمز هذا فوق استيراد علامة HTML البرمجية لملف Script.js بالقرب من نهاية ملف index.html:

index.html

<script src="/socket.io/socket.io.js"></script>

يجب أن يكون لديك الآن 3 علامات نص برمجي في ملف index.html:

  • عملية الاستيراد الأولى لمكتبة TensorFlow.js
  • المقبس الثاني الذي أضفته للتو
  • والأخيرة يجب أن تستورد استيراد Script.js.

بعد ذلك، عدّل server.js لإعداد socket.io داخل العقدة وإنشاء خلفية بسيطة لإرسال الرسائل المستلمة إلى جميع البرامج المتصلة.

اطّلِع على تعليقات الرموز أدناه للحصول على شرح عن وظيفة رمز Node.js:

server.js

const http = require('http');
const express = require("express");
const app = express();
const server = http.createServer(app);

// Require socket.io and then make it use the http server above.
// This allows us to expose correct socket.io library JS for use
// in the client side JS.
var io = require('socket.io')(server);

// Serve all the files in 'www'.
app.use(express.static("www"));

// If no file specified in a request, default to index.html
app.get("/", (request, response) => {
  response.sendFile(__dirname + "/www/index.html");
});


// Handle socket.io client connect event.
io.on('connect', socket => {
  console.log('Client connected');

  // If you wanted you could emit existing comments from some DB
  // to client to render upon connect.
  // socket.emit('storedComments', commentObjectArray);  
 
  // Listen for "comment" event from a connected client.
  socket.on('comment', (data) => {
    // Relay this comment data to all other connected clients
    // upon receiving.
    socket.broadcast.emit('remoteComment', data);
  });
});


// Start the web server.
const listener = server.listen(process.env.PORT, () => {
  console.log("Your app is listening on port " + listener.address().port);
});

رائع! لديك الآن خادم ويب يستمع إلى أحداث socket.io. على وجه التحديد، لديك حدث comment عندما يأتي تعليق جديد من أحد العملاء، ويُصدِر الخادم أحداث remoteComment يستمع إليها الرمز الجانبي للعميل لمعرفة التعليق عن بُعد. وبالتالي، فإن آخر إجراء يجب اتخاذه هو إضافة منطق socket.io إلى رمز جهة العميل لإرسال هذه الأحداث ومعالجتها.

أولاً، أضِف الرمز التالي إلى نهاية script.js للاتصال بخادم socket.io واستمع إلى أحداث المعالجة عن بُعد التي تم تلقيها:

script.js

// Connect to Socket.io on the Node.js backend.
var socket = io.connect();


function handleRemoteComments(data) {
  // Render a new comment to DOM from a remote client.
  let li = document.createElement('li');
  let p = document.createElement('p');
  p.innerText = data.comment;

  let spanName = document.createElement('span');
  spanName.setAttribute('class', 'username');
  spanName.innerText = data.username;

  let spanDate = document.createElement('span');
  spanDate.setAttribute('class', 'timestamp');
  spanDate.innerText = data.timestamp;

  li.appendChild(spanName);
  li.appendChild(spanDate);
  li.appendChild(p);
  
  COMMENTS_LIST.prepend(li);
}


// Add event listener to receive remote comments that passed
// spam check.
socket.on('remoteComment', handleRemoteComments);

وأخيرًا، أضف بعض الرموز إلى دالة loadAndPredict لإرسال حدث socket.io إذا كان التعليق غير مرغوب فيه. ويسمح لك هذا بتحديث العملاء المرتبطين الآخرين بهذا التعليق الجديد لأنه سيتم ترحيل محتوى هذه الرسالة إليهم عبر رمز server.js الذي كتبته أعلاه.

ما عليك سوى استبدال دالة loadAndPredict الحالية بالرمز التالي الذي يضيف عبارة else إلى عملية التحقق النهائية من المحتوى غير المرغوب فيه، وإذا كنت تعتقد أن التعليق ليس غير مرغوب فيه، يمكنك استدعاء socket.emit() لإرسال جميع بيانات التعليقات:

script.js

/** 
 * Asynchronous function to load the TFJS model and then use it to
 * predict if an input is spam or not spam. The 2nd parameter
 * allows us to specify the DOM element list item you are currently
 * classifying so you can change it+s style if it is spam!
 */
async function loadAndPredict(inputTensor, domComment) {
  // Load the model.json and binary files you hosted. Note this is 
  // an asynchronous operation so you use the await keyword
  if (model === undefined) {
    model = await tf.loadLayersModel(MODEL_JSON_URL);
  }
  
  // Once model has loaded you can call model.predict and pass to it
  // an input in the form of a Tensor. You can then store the result.
  var results = await model.predict(inputTensor);
  
  // Print the result to the console for us to inspect.
  results.print();

  results.data().then((dataArray)=>{
    if (dataArray[1] > SPAM_THRESHOLD) {
      domComment.classList.add('spam');
    } else {
      // Emit socket.io comment event for server to handle containing
      // all the comment data you would need to render the comment on
      // a remote client's front end.
      socket.emit('comment', {
        username: currentUserName,
        timestamp: domComment.querySelectorAll('span')[1].innerText,
        comment: domComment.querySelectorAll('p')[0].innerText
      });
    }
  })
}

رائع إذا تابعت بشكل صحيح، من المفترض أن تتمكن الآن من فتح مثيلين من صفحتك في index.html.

وعندما تنشر تعليقات ليست غير مرغوب فيها، يجب أن تراها معروضة على البرنامج الآخر على الفور تقريبًا. إذا كان التعليق غير مرغوب فيه، فلن يتم إرساله مطلقًا وسيتم وضع علامة عليه كغير مرغوب فيه بدلاً من ذلك في الواجهة الأمامية التي أنشأتها على النحو التالي فقط:

ee0f13398ea4e91e.gif

12- تهانينا

تهانينا، لقد اتّخذت خطواتك الأولى في استخدام تعلُم الآلة باستخدام TensorFlow.js في متصفح الويب لتطبيق فعلي - لاكتشاف التعليقات غير المرغوب فيها.

ننصحك بتجربة هذه الميزة واختبارها على مجموعة متنوّعة من التعليقات وقد تلاحظ أنّ بعض المشاكل لا تزال قيد المعالجة. وستلاحظ أيضًا أنه في حال إدخال جملة أطول من 20 كلمة، سوف تفشل حاليًا حيث يتوقع النموذج إدخال 20 كلمة كإدخال.

في هذه الحالة، قد تحتاج إلى تقسيم الجُمل الطويلة إلى مجموعات مكوّنة من 20 كلمة، ثمّ أخذ احتمالية كل جملة فرعية في الاعتبار لتحديد ما إذا كانت ستظهر أم لا. وسوف نترك ذلك كمهمة إضافية اختيارية لتجربتها نظرًا لوجود العديد من الأساليب التي يمكنك اتباعها لهذا.

في الدرس التطبيقي التالي حول الترميز، سنوضح لك كيفية إعادة ضبط هذا النموذج باستخدام بيانات التعليقات المخصّصة لحالات الأحرف التي لم يرصدها حاليًا، أو حتى لتغيير توقّعات الإدخال للنموذج، بحيث يمكنه التعامل مع الجمل التي تكون أكبر من 20 كلمة، ثم تصدير هذا النموذج واستخدامه مع TensorFlow.js.

إذا كنت تواجه مشكلة لسبب ما، قارِن رمزك بهذا الإصدار المكتمل المتوفر هنا، وتحقَّق من عدم وجود أي شيء.

الملخّص

في هذا الدرس التطبيقي حول الترميز:

  1. تعرّفت على المقصود بأداة TensorFlow.js والنماذج المتاحة لمعالجة اللغات الطبيعية.
  2. أنشأت موقعًا إلكترونيًا وهميًا يسمح بإضافة تعليقات في الوقت الفعلي لأحد المواقع على الويب.
  3. تم تحميل نموذج تعلُّم الآلة المدرّب مسبقًا والمناسب لرصد التعليقات غير المرغوب فيها من خلال TensorFlow.js على صفحة الويب.
  4. تعرّفت على كيفية ترميز الجُمل لاستخدامها مع نموذج تعلُّم الآلة الذي تم تحميله وتغليف ذلك الترميز داخل Tensor.
  5. تم تفسير مخرجات نموذج تعلُّم الآلة لتحديد ما إذا كنت تريد إخضاع التعليق للمراجعة، وإذا لم يكن الأمر كذلك، سيتم إرساله إلى الخادم لإرساله إلى عملاء آخرين متصلين في الوقت الفعلي.

ما الخطوات التالية؟

بعد أن بدأت إعداد قاعدة عمل، ما هي الأفكار الإبداعية التي يمكنك طرحها لتوسيع نموذج تعلُّم الآلة هذا بحيث يقتصر على استخدام عملي عملي؟

مشاركة ما تنشئه معنا

يمكنك تمديد فترة اشتراكك بسهولة في حالات استخدام تصميمات الإعلانات الأخرى أيضًا، ونشجّعك على التفكير خارج الصندوق ومواصلة الاختراق.

لا تنسَ الإشارة إلينا على وسائل التواصل الاجتماعي باستخدام الهاشتاغ #MadeWithTFJS حتى تتمكّن من عرض مشروعك على مدوّنة TensorFlow أو حتى الأحداث المستقبلية. نتطلّع إلى معرفة ما تقدّمه.

المزيد من الدروس التطبيقية حول الترميز TensorFlow.js لمعرفة المزيد من المعلومات

المواقع الإلكترونية لإتمام الدفع