TensorFlow.js: یک سیستم تشخیص هرزنامه نظرات بسازید

1. قبل از شروع

در طول دهه گذشته برنامه‌های وب با پشتیبانی از چند رسانه‌ای، نظرات و موارد دیگر در زمان واقعی توسط ده‌ها هزار نفر حتی در یک وب‌سایت نسبتاً محبوب انجام می‌شوند، اجتماعی‌تر و تعاملی‌تر شده‌اند.

این همچنین فرصتی را برای ارسال‌کنندگان هرزنامه فراهم کرده است تا از چنین سیستم‌هایی سوء استفاده کنند و محتوای کمتر خوش طعم را با مقالات، ویدیوها و پست‌هایی که دیگران نوشته‌اند مرتبط کنند، تا در تلاش برای دیده شدن بیشتر باشند.

روش‌های قدیمی‌تر تشخیص هرزنامه، مانند فهرستی از کلمات مسدود شده، به راحتی قابل دور زدن هستند و به سادگی با ربات‌های اسپم پیشرفته، که به طور مداوم در پیچیدگی خود در حال پیشرفت هستند، قابل مقایسه نیستند. به سرعت به امروز بروید، و اکنون می توانید از مدل های یادگیری ماشینی استفاده کنید که برای شناسایی چنین هرزنامه ها آموزش دیده اند.

به طور سنتی، اجرای یک مدل یادگیری ماشین برای فیلتر کردن نظرات از قبل در سمت سرور انجام می‌شد، اما با TensorFlow.js اکنون می‌توانید مدل‌های یادگیری ماشین را در سمت مشتری، در مرورگر از طریق جاوا اسکریپت اجرا کنید. شما می توانید هرزنامه را قبل از اینکه حتی به قسمت پشتی آن برخورد کند، متوقف کنید، و به طور بالقوه در منابع پرهزینه سمت سرور صرفه جویی می شود.

همانطور که ممکن است آگاه باشید، یادگیری ماشینی این روزها کلمه رایجی است که تقریباً هر صنعتی را تحت تأثیر قرار می دهد، اما چگونه می توانید اولین قدم های خود را برای استفاده از این قابلیت ها به عنوان یک توسعه دهنده وب بردارید؟

این کد لبه به شما نشان می دهد که چگونه می توانید یک برنامه وب، از یک بوم خالی، بسازید که با استفاده از پردازش زبان طبیعی (هنر درک زبان انسان با کامپیوتر) با مشکل واقعی هرزنامه نظرات مقابله کند. بسیاری از توسعه دهندگان وب در حین کار بر روی یکی از برنامه های کاربردی وب محبوب که امروزه وجود دارند، با این مشکل مواجه می شوند و این نرم افزار کد به شما این امکان را می دهد که به طور موثر با چنین مشکلاتی مقابله کنید.

پیش نیازها

این کد لبه برای توسعه دهندگان وب که به تازگی با یادگیری ماشینی آشنا هستند و به دنبال استفاده از مدل های از پیش آموزش دیده با TensorFlow.js هستند، نوشته شده است.

آشنایی با HTML5، CSS و JavaScript برای این آزمایشگاه فرض شده است.

چیزی که یاد خواهید گرفت

شما:

  • درباره چیستی TensorFlow.js و مدل‌هایی برای پردازش زبان طبیعی بیشتر بدانید.
  • یک صفحه وب ساده HTML / CSS / JS برای یک وبلاگ ویدیویی ساختگی با بخش نظرات زمان واقعی بسازید.
  • از TensorFlow.js برای بارگیری یک مدل یادگیری ماشینی از پیش آموزش‌دیده استفاده کنید که قادر به پیش‌بینی اینکه آیا جمله وارد شده احتمالاً هرزنامه است یا خیر، به کاربر هشدار دهید که نظر او برای تعدیل نگه داشته شده است.
  • جملات نظر را به گونه ای رمزگذاری کنید که توسط مدل یادگیری ماشینی قابل استفاده باشد تا سپس طبقه بندی شود.
  • خروجی مدل یادگیری ماشین را تفسیر کنید تا تصمیم بگیرید که آیا می خواهید نظر را به طور خودکار پرچم گذاری کنید یا خیر. این UX فرضی را می‌توان در هر وب‌سایتی که ممکن است روی آن کار می‌کنید مورد استفاده مجدد قرار گیرد و با هر مورد استفاده از مشتری سازگار شود - شاید یک وبلاگ معمولی، انجمن یا نوعی از CMS مانند دروپال باشد.

بسیار تمیز. انجام دادنش سخته؟ جواب منفی. پس بیا هک کنیم...

آنچه شما نیاز دارید

  • ترجیح داده می شود یک حساب Glitch.com دنبال کنید یا می توانید از یک محیط وب سرویس دهی استفاده کنید که خودتان راحت ویرایش و اجرا می کنید.

2. TensorFlow.js چیست؟

1aee0ede85885520.png

TensorFlow.js یک کتابخانه یادگیری ماشین منبع باز است که می تواند در هر جایی که جاوا اسکریپت می تواند اجرا شود. این بر اساس کتابخانه اصلی TensorFlow نوشته شده در پایتون است و هدف آن ایجاد دوباره این تجربه توسعه دهنده و مجموعه ای از API ها برای اکوسیستم جاوا اسکریپت است.

کجا میشه ازش استفاده کرد؟

با توجه به قابلیت حمل جاوا اسکریپت، اکنون می توانید به 1 زبان بنویسید و یادگیری ماشینی را در تمامی پلتفرم های زیر به راحتی انجام دهید:

  • سمت کلاینت در مرورگر وب با استفاده از وانیلی جاوا اسکریپت
  • سمت سرور و حتی دستگاه های اینترنت اشیا مانند Raspberry Pi با استفاده از Node.js
  • برنامه های دسکتاپ با استفاده از Electron
  • برنامه های موبایل بومی با استفاده از React Native

TensorFlow.js همچنین از چندین پشتیبان در هر یک از این محیط‌ها پشتیبانی می‌کند (محیط‌های مبتنی بر سخت‌افزار واقعی که می‌تواند در داخل آن مانند CPU یا WebGL اجرا کند. "بک‌اند" در این زمینه به معنای یک محیط سمت سرور نیست - پشتیبان برای اجرا. به عنوان مثال، می تواند سمت مشتری در WebGL باشد) تا از سازگاری اطمینان حاصل کند و همچنین کارها را سریع نگه دارد. در حال حاضر TensorFlow.js پشتیبانی می کند:

  • اجرای WebGL روی کارت گرافیک دستگاه (GPU) - این سریعترین راه برای اجرای مدلهای بزرگتر (با اندازه بیش از 3 مگابایت) با شتاب GPU است.
  • اجرای Web Assembly (WASM) بر روی CPU - برای بهبود عملکرد CPU در سراسر دستگاه ها از جمله تلفن های همراه نسل قدیمی تر. این برای مدل‌های کوچک‌تر (اندازه کمتر از 3 مگابایت) که در واقع می‌توانند در CPU با WASM سریع‌تر از WebGL اجرا شوند، به دلیل هزینه‌های بارگذاری محتوا در یک پردازنده گرافیکی مناسب است.
  • اجرای CPU - نسخه بازگشتی نباید هیچ یک از محیط های دیگر در دسترس باشد. این کندترین از این سه است اما همیشه برای شما آماده است.

توجه: اگر می‌دانید در چه دستگاهی اجرا می‌کنید، می‌توانید یکی از این پشتیبان‌ها را مجبور کنید، یا اگر این مورد را مشخص نکرده‌اید، می‌توانید به سادگی اجازه دهید TensorFlow.js برای شما تصمیم بگیرد.

قدرت های فوق العاده سمت مشتری

اجرای TensorFlow.js در مرورگر وب روی دستگاه مشتری می تواند به چندین مزیت منجر شود که ارزش در نظر گرفتن دارد.

حریم خصوصی

شما می توانید بدون ارسال داده ها به وب سرور شخص ثالث، هم داده ها را در دستگاه مشتری آموزش دهید و هم طبقه بندی کنید. ممکن است مواقعی برای رعایت قوانین محلی، مانند GDPR، یا هنگام پردازش هرگونه داده ای که کاربر بخواهد در دستگاه خود نگه دارد و به شخص ثالث ارسال نشود، الزامی باشد.

سرعت

از آنجایی که مجبور نیستید داده ها را به یک سرور راه دور ارسال کنید، استنتاج (عمل طبقه بندی داده ها) می تواند سریعتر باشد. حتی بهتر از آن، دسترسی مستقیم به حسگرهای دستگاه مانند دوربین، میکروفون، GPS، شتاب سنج و موارد دیگر در صورتی که کاربر به شما اجازه دسترسی بدهد، دارید.

رسیدن و مقیاس

با یک کلیک هر کسی در جهان می تواند روی پیوندی که برایشان ارسال می کنید کلیک کند، صفحه وب را در مرورگر خود باز کند و از آنچه ساخته اید استفاده کند. بدون نیاز به راه اندازی لینوکس در سمت سرور پیچیده با درایورهای CUDA و خیلی بیشتر فقط برای استفاده از سیستم یادگیری ماشین.

هزینه

بدون سرور به این معنی است که تنها چیزی که باید برای آن هزینه کنید یک CDN برای میزبانی فایل های HTML، CSS، JS و مدل است. هزینه CDN بسیار ارزان تر از نگه داشتن سرور (به طور بالقوه با کارت گرافیک متصل) در حال اجرا 24/7 است.

ویژگی های سمت سرور

استفاده از اجرای Node.js از TensorFlow.js ویژگی های زیر را فعال می کند.

پشتیبانی کامل از CUDA

در سمت سرور، برای شتاب کارت گرافیک، باید درایورهای NVIDIA CUDA را نصب کنید تا TensorFlow بتواند با کارت گرافیک کار کند (بر خلاف مرورگری که از WebGL استفاده می کند - نیازی به نصب نیست). با این حال، با پشتیبانی کامل از CUDA، می‌توانید به طور کامل از توانایی‌های سطح پایین‌تر کارت گرافیک استفاده کنید، که منجر به آموزش سریع‌تر و زمان‌های استنتاج می‌شود. عملکرد با پیاده‌سازی Python TensorFlow برابری می‌کند، زیرا هر دوی آن‌ها باطن C++ یکسانی را به اشتراک می‌گذارند.

اندازه مدل

برای مدل های پیشرفته از تحقیقات، ممکن است با مدل های بسیار بزرگ، شاید گیگابایتی کار کنید. این مدل‌ها در حال حاضر نمی‌توانند در مرورگر وب به دلیل محدودیت‌های استفاده از حافظه در هر برگه مرورگر اجرا شوند. برای اجرای این مدل‌های بزرگ‌تر، می‌توانید از Node.js در سرور خود با مشخصات سخت‌افزاری مورد نیاز برای اجرای کارآمد چنین مدلی استفاده کنید.

IOT

Node.js در رایانه های تک بردی محبوب مانند Raspberry Pi پشتیبانی می شود، که به نوبه خود به این معنی است که می توانید مدل های TensorFlow.js را روی چنین دستگاه هایی نیز اجرا کنید.

سرعت

Node.js با جاوا اسکریپت نوشته شده است که به این معنی است که از کامپایل به موقع سود می برد. این بدان معنی است که شما اغلب هنگام استفاده از Node.js شاهد افزایش عملکرد خواهید بود، زیرا در زمان اجرا بهینه می شود، به خصوص برای هر پیش پردازشی که ممکن است انجام دهید. یک مثال عالی از این را می توان در این مطالعه موردی مشاهده کرد که نشان می دهد چگونه Hugging Face از Node.js برای افزایش عملکرد 2 برابری برای مدل پردازش زبان طبیعی خود استفاده کرد.

اکنون اصول اولیه TensorFlow.js، جایی که می‌تواند اجرا شود و برخی از مزایای آن را می‌دانید، بیایید شروع به انجام کارهای مفید با آن کنیم!

3. مدل های از قبل آموزش دیده

چرا می خواهم از یک مدل از پیش آموزش دیده استفاده کنم؟

اگر یک مدل از پیش آموزش‌دیده‌شده را شروع کنید، در صورتی که با مورد مورد نظر شما مطابقت داشته باشد، مزایای زیادی دارد، مانند:

  1. بدون نیاز به جمع آوری داده های آموزشی خودتان. آماده‌سازی داده‌ها در قالب صحیح و برچسب‌گذاری آن‌ها به گونه‌ای که یک سیستم یادگیری ماشینی بتواند از آن برای یادگیری استفاده کند، می‌تواند بسیار زمان‌بر و پرهزینه باشد.
  2. توانایی نمونه سازی سریع یک ایده با کاهش هزینه و زمان.
    زمانی که یک مدل از پیش آموزش‌دیده برای انجام کارهای مورد نیاز شما خوب باشد، «اختراع مجدد چرخ» هیچ فایده‌ای ندارد و به شما امکان می‌دهد بر روی استفاده از دانش ارائه‌شده توسط مدل برای اجرای ایده‌های خلاقانه‌تان تمرکز کنید.
  3. استفاده از تحقیقات پیشرفته. مدل‌های از پیش آموزش‌دیده اغلب بر اساس تحقیقات رایج هستند و به شما این امکان را می‌دهند که در معرض چنین مدل‌هایی قرار بگیرید و در عین حال عملکرد آنها را در دنیای واقعی نیز درک کنید.
  4. سهولت استفاده و مستندات گسترده. با توجه به محبوبیت چنین مدل هایی.
  5. انتقال قابلیت های یادگیری برخی از مدل‌های از پیش آموزش‌دیده، قابلیت‌های یادگیری انتقالی را ارائه می‌دهند، که اساساً عمل انتقال اطلاعات آموخته‌شده از یک کار یادگیری ماشینی به نمونه مشابه دیگری است. به عنوان مثال، مدلی که در ابتدا برای تشخیص گربه ها آموزش دیده بود، می تواند برای تشخیص سگ ها دوباره آموزش داده شود، اگر داده های آموزشی جدیدی به آن بدهید. این سریع‌تر خواهد بود زیرا با یک بوم خالی شروع نمی‌کنید. این مدل می‌تواند از چیزهایی که قبلاً آموخته است برای تشخیص گربه‌ها استفاده کند تا چیزهای جدید را تشخیص دهد - سگ‌ها نیز چشم و گوش دارند، بنابراین اگر قبلاً می‌داند چگونه آن ویژگی‌ها را پیدا کند، نیمه راه هستیم. با روشی بسیار سریع تر، مدل را روی داده های خود دوباره آموزش دهید.

یک مدل از پیش آموزش دیده تشخیص هرزنامه نظرات

شما از معماری مدل میانگین واژه جاسازی کلمه برای نیازهای تشخیص هرزنامه نظر خود استفاده خواهید کرد، اما اگر سعی کنید از یک مدل آموزش ندیده استفاده کنید، حدس زدن هرزنامه بودن یا نبودن جملات بهتر از شانس تصادفی نخواهد بود.

برای اینکه مدل مفید باشد، باید بر روی داده های سفارشی آموزش داده شود، در این مورد، به آن اجازه می دهد تا یاد بگیرد که نظرات هرزنامه در مقابل غیر هرزنامه چگونه است. پس از آن یادگیری، شانس بیشتری برای طبقه‌بندی درست چیزها در آینده خواهد داشت.

خوشبختانه، شخصی قبلاً این معماری مدل دقیق را برای این کار طبقه بندی هرزنامه نظرات آموزش داده است، بنابراین می توانید از آن به عنوان نقطه شروع خود استفاده کنید. ممکن است مدل‌های از پیش آموزش‌دیده دیگری را بیابید که از همان معماری مدل برای انجام کارهای مختلف استفاده می‌کنند، مانند تشخیص زبانی که یک نظر نوشته شده است، یا پیش‌بینی اینکه آیا داده‌های فرم تماس وب‌سایت باید به‌طور خودکار بر اساس متن نوشته شده به تیم شرکت خاصی هدایت شوند. به عنوان مثال فروش (استعلام محصول) یا مهندسی (اشکال فنی یا بازخورد). با داده های آموزشی کافی، مدلی مانند این می تواند یاد بگیرد که چنین متنی را در هر مورد طبقه بندی کند تا به برنامه وب شما قدرت فوق العاده بدهد و کارایی سازمان شما را بهبود بخشد.

در یک آزمایشگاه کد آینده ، نحوه استفاده از Model Maker را برای آموزش مجدد این مدل هرزنامه نظرات از پیش آموزش دیده، و بهبود عملکرد آن در داده های نظرات خود بیشتر خواهید آموخت. در حال حاضر، شما از مدل تشخیص هرزنامه نظرات موجود به عنوان نقطه شروع استفاده خواهید کرد تا برنامه وب اولیه به عنوان اولین نمونه کار کند.

این مدل تشخیص هرزنامه نظرات از پیش آموزش دیده در وب سایتی به نام TF Hub منتشر شده است، یک مخزن مدل یادگیری ماشینی که توسط Google نگهداری می شود، جایی که مهندسان ML می توانند مدل های از پیش ساخته شده خود را برای بسیاری از موارد استفاده رایج (مانند متن، دید، صدا و بیشتر برای موارد استفاده خاص در هر یک از آن دسته ها). ادامه دهید و فایل‌های مدل را فعلا دانلود کنید تا بعداً در این کد لبه در برنامه وب استفاده کنید.

همانطور که در زیر نشان داده شده است، روی دکمه دانلود برای مدل JS کلیک کنید:

ab65deff89b3d939.png

4. برای کدگذاری تنظیم شوید

آنچه شما نیاز دارید

  • یک مرورگر وب مدرن
  • دانش اولیه HTML، CSS، جاوا اسکریپت و ابزار توسعه کروم (مشاهده خروجی کنسول).

بیایید کد نویسی کنیم.

ما یک الگوی Glitch.com Node.js Express boilerplate ایجاد کرده‌ایم تا از آن شروع کنید که می‌توانید به سادگی به عنوان حالت پایه خود برای این آزمایشگاه کد تنها با یک کلیک کلون کنید.

در Glitch به سادگی روی دکمه "Remix this" کلیک کنید تا آن را فورک کنید و مجموعه جدیدی از فایل‌ها را که می‌توانید ویرایش کنید ایجاد کنید.

این اسکلت بسیار ساده فایل های زیر را در پوشه www در اختیار ما قرار می دهد:

  1. صفحه HTML (index.html)
  2. صفحه سبک (style.css)
  3. فایل برای نوشتن کد جاوا اسکریپت ما (script.js)

برای راحتی شما، ما همچنین یک import برای کتابخانه TensorFlow.js به فایل HTML اضافه کرده ایم که به شکل زیر است:

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 Boilerplate

نقطه شروع شما چیست؟

همه نمونه‌های اولیه نیاز به داربست‌های اولیه 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 در اینجا قرار دهید. در واقع، در یک وب‌سایت تولیدی، همه این مقادیر بسته به صفحه‌ای که مشاهده می‌شود، توسط backend به صورت پویا ارائه می‌شوند.
  • در نهایت، شما یک section با شناسه و کلاس "نظرات" اضافه کردید که شامل یک div قابل ویرایش برای نوشتن نظرات جدید به همراه button ای برای ارسال نظر جدیدی که می خواهید اضافه کنید به همراه لیست نامرتب نظرات را اضافه کردید. شما نام کاربری و زمان ارسال را در یک تگ span در داخل هر آیتم لیست دارید و در نهایت خود نظر را در یک تگ p دارید. 2 کامنت نمونه در حال حاضر به عنوان مکان نگهدار کدگذاری شده است.

اگر در حال حاضر پیش نمایش خروجی را مشاهده کنید، باید چیزی شبیه به این باشد:

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;
}

عالی! این تمام چیزی است که شما نیاز دارید. اگر با موفقیت استایل های خود را با 2 قطعه کد بالا بازنویسی کردید، اکنون پیش نمایش زنده شما باید به این صورت باشد:

b86be8e2f6e7456.png

شیرین، حالت شب به طور پیش فرض، و انتقال جذاب CSS برای افکت های شناور روی عناصر کلیدی. خوب به نظر می رسد. اکنون برخی از منطق رفتاری را با استفاده از جاوا اسکریپت ادغام کنید.

7. جاوا اسکریپت: دستکاری 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. مدل یادگیری ماشین را ارائه دهید

شما تقریباً آماده بارگذاری مدل هستید. قبل از اینکه بتوانید این کار را انجام دهید، باید فایل‌های مدلی را که قبلاً در Codelab بارگیری شده‌اند در وب‌سایت خود آپلود کنید تا در کد میزبان و قابل استفاده باشد.

ابتدا، اگر قبلاً این کار را نکرده‌اید، فایل‌هایی را که برای مدل دانلود کرده‌اید در ابتدای این کد لبه از حالت فشرده خارج کنید. شما باید دایرکتوری با فایل های زیر را ببینید:

5634d536ef8be9ca.png

اینجا چی داری؟

  • model.json - این یکی از فایل هایی است که مدل آموزش دیده TensorFlow.js را تشکیل می دهد. بعداً در کد TensorFlow.js خود به این فایل خاص اشاره خواهید کرد.
  • group1-shard1of1.bin - این یک فایل باینری است که حاوی وزن های آموزش دیده (در اصل تعدادی از اعدادی است که برای انجام وظایف طبقه بندی خود به خوبی یاد گرفته است) مدل TensorFlow.js و باید در جایی روی سرور شما برای دانلود میزبانی شود.
  • vocab - این فایل عجیب و غریب بدون پسوند چیزی از Model Maker است که به ما نشان می دهد چگونه کلمات را در جملات رمزگذاری کنیم تا مدل نحوه استفاده از آنها را بفهمد. در بخش بعدی بیشتر به این موضوع خواهید پرداخت.
  • labels.txt - این به سادگی شامل نام کلاس های به دست آمده است که مدل پیش بینی می کند. برای این مدل، اگر این فایل را در ویرایشگر متن خود باز کنید، به سادگی "نادرست" و "درست" فهرست شده است، که به عنوان خروجی پیش بینی "not spam" یا "spam" را نشان می دهد.

فایل های مدل TensorFlow.js را میزبانی کنید

ابتدا model.json و *.bin را که روی سرور وب ایجاد شده‌اند، قرار دهید تا بتوانید از طریق صفحه وب به آنها دسترسی داشته باشید.

فایل ها را در Glitch آپلود کنید

  1. روی پوشه دارایی ها در پانل سمت چپ پروژه Glitch خود کلیک کنید.
  2. روی آپلود دارایی کلیک کنید و group1-shard1of1.bin را انتخاب کنید تا در این پوشه آپلود شود. اکنون باید پس از بارگذاری به این شکل باشد:

25a2251c7f165184.png

  1. عالی! حالا همین کار را برای فایل model.json انجام دهید. 2 فایل باید در پوشه دارایی های شما مانند این باشد:

51a6dbd5d3097ffc.png

  1. روی فایل group1-shard1of1.bin که به تازگی آپلود کردید کلیک کنید. شما می توانید URL را در مکان آن کپی کنید. اکنون این مسیر را مطابق شکل کپی کنید:

92ded8d46442c404.png

  1. اکنون در پایین سمت چپ صفحه، روی Tools > Terminal کلیک کنید. صبر کنید تا پنجره ترمینال بارگیری شود. پس از بارگذاری، عبارت زیر را تایپ کرده و سپس اینتر را فشار دهید تا دایرکتوری را به پوشه www تغییر دهید:

پایانه:

cd www
  1. در مرحله بعد، از wget برای دانلود 2 فایلی که به تازگی آپلود شده اند استفاده کنید، با جایگزین کردن 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. مدل 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

در کنسول، 2 عدد چاپ شده را مشاهده می کنید:

  1. 0.9996011
  2. 0.0003989

در حالی که این ممکن است مرموز به نظر برسد، این اعداد در واقع نشان دهنده احتمالاتی هستند که مدل فکر می کند طبقه بندی برای ورودی هایی است که به آن داده اید. اما آنها چه چیزی را نشان می دهند؟

اگر فایل labels.txt خود را از فایل‌های مدل دانلود شده‌ای که در دستگاه محلی خود دارید باز کنید، خواهید دید که دارای 2 فیلد نیز هست:

  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] بود. [1,3,12,18,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] هرزنامه نبود (یعنی نادرست).

توجه داشته باشید که false اولین برچسب در labels.txt و با اولین خروجی در نسخه چاپی کنسول نشان داده می شود که چگونه می دانید پیش بینی خروجی به چه چیزی مربوط می شود.

خوب، اکنون می دانید که چگونه خروجی را تفسیر کنید، اما آن دسته بزرگ از اعداد دقیقاً چه چیزی به عنوان ورودی داده شده است و چگونه جملات را به این فرمت برای مدل تبدیل می کنید؟ برای آن، باید در مورد توکن سازی و تانسورها بیاموزید. ادامه مطلب

10. توکن سازی و تانسورها

توکن سازی

بنابراین معلوم می شود که مدل های یادگیری ماشینی فقط می توانند تعداد زیادی اعداد را به عنوان ورودی بپذیرند. چرا؟ خوب اساساً به این دلیل است که یک مدل یادگیری ماشینی اساساً مجموعه‌ای از عملیات ریاضی زنجیره‌ای است، بنابراین اگر چیزی را به آن بفرستید که یک عدد نیست، کار سختی با آن خواهد داشت. بنابراین اکنون این سوال مطرح می شود که چگونه جملات را برای استفاده با مدلی که بارگذاری کرده اید به اعداد تبدیل می کنید؟

روند دقیق از مدلی به مدل دیگر متفاوت است، اما برای این یکی یک فایل دیگر در فایل های مدلی که دانلود کرده اید به نام vocab, و این کلید نحوه کدگذاری داده ها است.

پیش بروید و vocab را در یک ویرایشگر متن محلی در دستگاه خود باز کنید و چیزی شبیه به این خواهید دید:

81e8bca3fbf62429.png

اساساً این یک جدول جستجو در مورد چگونگی تبدیل کلمات معنی‌دار مدل به اعدادی است که می‌تواند بفهمد. همچنین موارد خاصی در بالای فایل <PAD> ، <START> و <UNKNOWN> وجود دارد:

  • <PAD> - این کوتاه برای "padding" است. به نظر می رسد که مدل های یادگیری ماشینی دوست دارند تعداد ورودی ثابتی داشته باشند صرف نظر از اینکه جمله شما چقدر طولانی است. مدل مورد استفاده انتظار دارد که همیشه 20 عدد برای ورودی وجود داشته باشد (این توسط خالق مدل تعریف شده است و در صورت آموزش مجدد مدل قابل تغییر است). بنابراین اگر عبارتی مانند "من ویدیو را دوست دارم" دارید، فضاهای باقی مانده در آرایه را با 0 پر کنید که نشان دهنده نشانه <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" به عدد "3" تبدیل شده است که صحیح است. اگر کلمات دیگر را جستجو کنید، اعداد مربوط به آنها را نیز خواهید یافت.

تانسورها

قبل از اینکه مدل ML ورودی عددی شما را بپذیرد، یک مانع نهایی وجود دارد. شما باید آرایه اعداد را به چیزی به نام Tensor تبدیل کنید، و بله، درست حدس زدید، TensorFlow از این چیزها نامگذاری شده است - جریان تانسورها از طریق یک مدل اساسا.

تانسور چیست؟

تعریف رسمی از TensorFlow.org می گوید:

تانسورها آرایه های چند بعدی با نوع یکنواخت هستند. همه تانسورها تغییر ناپذیر هستند: شما هرگز نمی توانید محتویات یک تانسور را به روز کنید، فقط یک تانسور جدید ایجاد کنید.

به زبان انگلیسی ساده، این فقط یک نام ریاضی فانتزی برای آرایه‌ای از هر بعد است که دارای توابع دیگری در جسم تنسور است که برای ما به عنوان توسعه‌دهندگان یادگیری ماشین مفید است. با این حال باید توجه داشت که Tensor داده‌ها را فقط از یک نوع ذخیره می‌کند، به عنوان مثال همه اعداد صحیح یا تمام اعداد ممیز شناور، و پس از ایجاد، هرگز نمی‌توانید محتوای یک Tensor را تغییر دهید - بنابراین می‌توانید آن را به عنوان یک جعبه ذخیره دائمی برای اعداد در نظر بگیرید!

فعلا زیاد نگران این موضوع نباشید. حداقل، آن را به عنوان یک مکانیسم ذخیره‌سازی چند بعدی برای مدل‌های یادگیری ماشینی در نظر بگیرید تا زمانی که با کتاب خوبی مانند این کتاب عمیق‌تر غواصی کنید - اگر می‌خواهید درباره تنسورها و نحوه استفاده از آنها بیشتر بدانید، توصیه می‌شود.

همه را کنار هم بگذارید: تانسورهای کدگذاری و توکن سازی

بنابراین چگونه از آن فایل vocab در کد استفاده می کنید؟ سوال عالی!

این فایل به تنهایی برای شما به عنوان یک توسعه دهنده JS بی فایده است. اگر این یک شی جاوا اسکریپت بود که بتوانید به سادگی وارد کنید و از آن استفاده کنید، بسیار بهتر است. می توان مشاهده کرد که تبدیل داده های موجود در این فایل به فرمت هایی مانند این بسیار ساده است:

// 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 می شود. حتی بهتر از آن، اشیاء جاوا اسکریپت دارای ویژگی های زیر هستند:

"نام ویژگی شی می تواند هر رشته معتبر جاوا اسکریپت یا هر چیزی که می تواند به یک رشته تبدیل شود، از جمله رشته خالی باشد. با این حال، هر نام ویژگی که یک شناسه معتبر جاوا اسکریپت نیست (به عنوان مثال، نام ویژگی که دارای فاصله است. یا خط تیره، یا که با یک عدد شروع می شود) فقط با استفاده از علامت کروشه مربع قابل دسترسی است."

بنابراین تا زمانی که از نماد براکت استفاده می کنید، می توانید یک جدول جستجوی نسبتاً کارآمد از طریق این تبدیل ساده ایجاد کنید.

تبدیل به فرمت مفیدتر

فایل vocab خود را به صورت دستی از طریق ویرایشگر متن یا با استفاده از این ابزار در اینجا به فرمت بالا تبدیل کنید. خروجی به دست آمده را به عنوان 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() را به روز کنید تا در صورت شناسایی یک نظر به عنوان هرزنامه، یک سبک تنظیم کنید.

For now you will simply change the style, but later you can choose to hold the comment in some sort of moderation queue or stop it from sending.

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. Real-time updates: Node.js + Websockets

Now you have a working frontend with spam detection, the final piece of the puzzle is to use Node.js with some websockets for real-time communication and update in real time any comments that are added that are not spam.

Socket.io

Socket.io is one of the most popular ways (at time of writing) to use websockets with Node.js. Go ahead and tell Glitch you want to include the Socket.io library in the build by editing package.json in the top level directory (in the parent folder of www folder) to include socket.io as one of the dependencies:

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"
  }
}

Great! Once updated, next update index.html within the www folder to include the socket.io library.

Simply place this line of code above the HTML script tag import for script.js near the end of the index.html file:

index.html

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

You should now have 3 script tags in your index.html file:

  • the first importing the TensorFlow.js library
  • the 2nd importing socket.io that you just added
  • and the last should be importing the script.js code.

Next, edit server.js to setup socket.io within node and create a simple backend to relay messages received to all connected clients.

See code comments below for an explanation of what the Node.js code is doing:

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);
});

Great! You now have a web server that is listening for socket.io events. Namely you have a comment event when a new comment comes in from a client, and the server emits remoteComment events which the client side code will listen for to know to render a remote comment. So the last thing to do is to add the socket.io logic to the client side code to emit and handle these events.

First, add the following code to the end of script.js to connect to the socket.io server and listen out / handle remoteComment events received:

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);

Finally, add some code to the loadAndPredict function to emit a socket.io event if a comment is not spam. This allows you to update the other connected clients with this new comment as the content of this message will be relayed to them via the server.js code you wrote above.

Simply replace your existing loadAndPredict function with the following code that adds an else statement to the final spam check where if the comment is not spam, you call socket.emit() to send all the comment data:

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
      });
    }
  })
}

Great job! If you followed along correctly, you should now be able to open up 2 instances of your index.html page.

As you post comments that are not spam, you should see them rendered on the other client almost instantly. If the comment is spam, it simply will never be sent and instead be marked as spam on the frontend that generated it only like this:

ee0f13398ea4e91e.gif

12. Congratulations

Congratulations, you have taken your first steps in using machine learning with TensorFlow.js in the web browser for a real world application - to detect comment spam!

Try it out, test it on a variety of comments, you may notice some things still get through. You will also notice that if you enter a sentence that is longer than 20 words, it will currently fail as the model expects 20 words as input.

In that case you may need to break long sentences into groups of 20 words and then take the spam likelihood of each sub sentence into consideration to determine if to show or not. We will leave this as an optional extra task for you to experiment with as there are many approaches you could take for this.

In the next codelab we will show you how to retrain this model with your custom comment data for edge cases it does not currently detect, or even to change the input expectation of the model so it can handle sentences that are larger than 20 words, and then export and use that model with TensorFlow.js.

If for some reason you are having issues, compare your code to this completed version available here , and check if you missed anything.

Recap

In this codelab you:

  1. Learned what TensorFlow.js is and what models exist for natural language processing
  2. Created a fictitious website that allows real time comments for an example website.
  3. Loaded a pre-trained machine learning model suitable for comment spam detection via TensorFlow.js on the web page.
  4. Learned how to encode sentences for use with the loaded machine learning model and encapsulate that encoding inside a Tensor.
  5. Interpreted the output of the machine learning model to decide if you want to hold the comment for review, and if not, sent to the server to relay to other connected clients in real time.

بعدش چی؟

Now that you have a working base to start from, what creative ideas can you come up with to extend this machine learning model boilerplate for a real world use case you may be working on?

Share what you make with us

You can easily extend what you made today for other creative use cases too and we encourage you to think outside the box and keep hacking.

Remember to tag us on social media using the #MadeWithTFJS hashtag for a chance for your project to be featured on our TensorFlow blog or even future events . We would love to see what you make.

More TensorFlow.js codelabs to go deeper

Websites to check out