
مرحبا بالجميع! اليوم سوف نتحدث عن تنفيذ التعلم الآلي على سكالا. سأبدأ بشرح كيف وصلنا إلى هذه الحياة. لذلك ، استخدم فريقنا لفترة طويلة جميع ميزات التعلم الآلي في بيثون. أنها مريحة ، وهناك العديد من المكتبات المفيدة لإعداد البيانات ، والبنية التحتية الجيدة للتنمية ، أعني Jupyter Notebook. كل شيء سيكون على ما يرام ، ولكن تواجه مشكلة موازاة الحسابات في الإنتاج ، وقررت استخدام Scala في المنتج. لم لا ، حسب اعتقادنا ، يوجد الكثير من المكتبات ، حتى Apache Spark مكتوب في Scala! في الوقت نفسه ، نطور اليوم نماذج في Python ، ثم نكرر التدريب في Scala لمزيد من التسلسل والاستخدام في الإنتاج. ولكن ، كما يقولون ، الشيطان هو في التفاصيل.
على الفور أريد أن أوضح ، عزيزي القارئ ، هذه المقالة لم تكتب لتقويض سمعة بيثون للتعلم الآلي. لا ، الهدف الرئيسي هو فتح الباب أمام عالم التعلم الآلي على Scala ، وإعطاء نظرة عامة قصيرة على النهج البديل الذي يتبع تجربتنا ، وإخبارك بالصعوبات التي واجهناها.
في الممارسة العملية ، اتضح أن الأمر لم يكن سعيدًا للغاية: لا توجد العديد من المكتبات التي تنفذ خوارزميات تعلم الآلة الكلاسيكية ، ولكن تلك التي غالبًا ما تكون مشاريع مفتوحة المصدر دون دعم من كبار البائعين. نعم ، بالطبع ، هناك Spark MLib ، لكنه مرتبط بشدة بالنظام البيئي Apache Hadoop ، ولم أرغب حقًا في جره إلى بنية الخدمات المصغرة.
المطلوب هو حل ينقذ العالم ويعيد نومًا مريحًا ، وقد وجد!
ماذا تحتاج؟
عندما اخترنا أداة للتعلم الآلي ، تابعنا المعايير التالية:
- يجب أن تكون بسيطة ؛
- على الرغم من بساطته ، لم يلغ أحد وظائف واسعة ؛
- أردت حقًا أن أكون قادرًا على تطوير نماذج في مترجم الويب ، وليس من خلال وحدة التحكم أو التجميعات والتجميعات المستمرة ؛
- توافر الوثائق يلعب دورا هاما.
- من الناحية المثالية ، سيكون هناك دعم على الأقل الإجابة على قضايا جيثب.
ماذا رأينا؟
- اباتشي سبارك MLib : لم يناسبنا . كما ذكرنا أعلاه ، ترتبط هذه المجموعة من المكتبات ارتباطًا وثيقًا بمجموعة Apache Hadoop و Spark Core نفسها ، والتي تزن أكثر من اللازم لبناء الخدمات المصغرة استنادًا إلى ذلك.
- Apache PredictionIO : مشروع مثير للاهتمام ، العديد من المساهمين ، هناك وثائق مع أمثلة. في الواقع ، هذا هو خادم REST الذي تدور فيه النماذج. هناك نماذج جاهزة ، على سبيل المثال ، تصنيف النص ، الذي تم طرح إطلاقه في الوثائق. تصف الوثائق كيف يمكنك إضافة وتدريب النماذج الخاصة بك. لم نكن ملائمين ، حيث يتم استخدام Spark تحت الغطاء ، وهذا أكثر من منطقة حل متجانسة ، بدلاً من بنية الخدمة المجهرية.
- Apache MXNet : إطار عمل مثير للاهتمام للعمل مع الشبكات العصبية ، وهناك دعم لـ Scala و Python - هذا مناسب ، ويمكنك تدريب شبكة عصبية في Python ، ثم تحميل النتيجة المحفوظة من Scala عند إنشاء حل إنتاج. نستخدمها في حلول الإنتاج ، وهناك مقالة منفصلة حول هذا هنا .
- Smile : تشبه إلى حد بعيد حزمة scikit-Learn الخاصة ببيثون. هناك العديد من تطبيقات خوارزميات تعلم الآلة الكلاسيكية والتوثيق الجيد مع الأمثلة والدعم على github ، ومتخيل مدمج (مدعوم من Swing) ، يمكنك استخدام Jupyter Notebook لتطوير النماذج. هذا فقط ما تحتاجه!
إعداد البيئة
لذلك ، اخترنا ابتسامة. سأخبرك عن كيفية تشغيله في Jupyter Notebook باستخدام خوارزمية التجميع k-mean كمثال. أول شيء يتعين علينا القيام به هو تثبيت Jupyter Notebook مع دعم Scala. يمكن القيام بذلك عبر نقطة أو استخدام صورة Docker تم تجميعها وتكوينها بالفعل. أنا مع الخيار الثاني أكثر بساطة.
لجعل Jupyter أصدقاء مع Scala ، أردت استخدام BeakerX ، وهو جزء من صورة Docker المتاحة في مستودع BeakerX الرسمي. يوصى بهذه الصورة في وثائق Smile ، ويمكنك تشغيلها كما يلي:
ولكن المشكلة الأولى كانت تنتظر: في وقت كتابة المقال ، تم تثبيت BeakerX 1.0.0 داخل صورة beakerx / beakerx ، وكان الإصدار 1.4.1 متاحًا بالفعل في github الرسمي للمشروع (بتعبير أدق ، أحدث إصدار 1.3.0 ، ولكن المعالج يحتوي على 1.4.1 ، ويعمل :-)).
من الواضح أنني أريد أن أعمل مع أحدث إصدار ، لذا فقد جمعت صورتي الخاصة على أساس BeakerX 1.4.1. لن أتحمل لك محتويات Dockerfile ، هنا
رابط لها.
بالمناسبة ، بالنسبة لأولئك الذين سيستخدمون صورتي ، ستكون هناك مكافأة صغيرة: في دليل الأمثلة ، يوجد مثال k- لتسلسل عشوائي مع التخطيط (هذه ليست مهمة تافهة تمامًا لأجهزة كمبيوتر Scala المحمولة).
تنزيل Smile in Jupyter Notebook
بيئة أعدت ممتازة! نقوم بإنشاء دفاتر ملاحظات جديدة من Scala في مجلد في دليلنا ، ثم نحتاج إلى تنزيل المكتبات من Maven حتى تعمل Smile.
%%classpath add mvn com.github.haifengl smile-scala_2.12 1.5.2
بعد تنفيذ التعليمات البرمجية ، ستظهر قائمة بملفات الجر التي تم تنزيلها في كتلة الإخراج.
الخطوة التالية: استيراد الحزم اللازمة للمثال للعمل.
import java.awt.image.BufferedImage import java.awt.Color import javax.imageio.ImageIO import java.io.File import smile.clustering._
إعداد البيانات للتجميع
الآن سنحل المشكلة التالية: إنشاء صورة تتكون من مناطق من ثلاثة ألوان أساسية - الأحمر والأخضر والأزرق (R ، G ، B). سوف تسود واحدة من الألوان في الصورة. نقوم بتجميع وحدات البكسل في الصورة ، ونأخذ المجموعة التي سيكون بها أكبر عدد من وحدات البكسل ، ونغير لونها إلى اللون الرمادي ونبني صورة جديدة من جميع وحدات البكسل. النتيجة المرتقبة: سوف تتحول منطقة اللون السائد إلى اللون الرمادي ، بينما لن تغير بقية المنطقة لونها.
نتيجة لتنفيذ هذا الرمز ، يتم عرض الصورة التالية:

الخطوة التالية: تحويل الصورة إلى مجموعة من بكسل. نعني بالبكسل كيان له الخصائص التالية:
- تنسيق الجانب العريض (x) ؛
- إحداثي جانبي ضيق (ص) ؛
- قيمة اللون
- القيمة الاختيارية لرقم الفئة / الكتلة (قبل اكتمال التجميع ، ستكون فارغة).
ككيان ، من المريح استخدام
case class
:
case class Pixel(x: Int, y: Int, rgbArray: Array[Double], clusterNumber: Option[Int] = None)
هنا ، لقيم اللون ، يتم
rgbArray
مجموعة
rgbArray
من ثلاث قيم من الأحمر والأخضر والأزرق (على سبيل المثال ، لصفيف اللون الأحمر
Array(255.0, 0, 0)
).
هذا يكمل إعداد البيانات.
بكسل اللون التجميع
لذلك ، لدينا مجموعة من البيكسلات من ثلاثة ألوان أساسية ، لذلك سنقوم بتجميع البيكسلات في ثلاثة فصول.
وتوصي الوثائق بتعيين المعلمة
runs
في حدود 10 إلى 20.
عند تنفيذ هذا الرمز ، سيتم إنشاء كائن من النوع
KMeans
. ستحتوي كتلة الإخراج على معلومات حول نتائج المجموعات:
K-Means distortion: 0.00000 Clusters of 230400 data points of dimension 3: 0 50813 (22.1%) 1 51667 (22.4%) 2 127920 (55.5%)
كتلة واحدة تحتوي على بكسل أكثر من الباقي. نحتاج الآن إلى وضع علامة على مجموعتنا من وحدات البكسل بفئات من 0 إلى 2.
إعادة رسم الصورة
الشيء الوحيد المتبقي هو تحديد الكتلة التي تحتوي على أكبر عدد من وحدات البكسل وإعادة رسم جميع وحدات البكسل المضمنة في هذه المجموعة إلى اللون الرمادي (قم بتغيير قيمة صفيف
rgbArray
).
لا يوجد شيء معقد ، فقط قم بتجميع حسب رقم المجموعة (هذا هو خيارنا
Option:[Int]
) ، احسب عدد العناصر في كل مجموعة واسحب المجموعة بأقصى عدد من العناصر. بعد ذلك ، قم بتغيير اللون إلى اللون الرمادي فقط لتلك البكسلات التي تنتمي إلى الكتلة الموجودة.
قم بإنشاء صورة جديدة واحفظ النتائج.
جمع صورة جديدة من مجموعة البكسل:
هذا ما فعلناه في النهاية.

نحن نحفظ كل الصور.
ImageIO.write(testImage, "png", new File("testImage.png")) ImageIO.write(modifiedImage, "png", new File("modifiedImage.png"))
استنتاج
تعلم الآلة على سكالا موجود. لتنفيذ الخوارزميات الأساسية ، ليس من الضروري سحب بعض المكتبات الضخمة. يوضح المثال أعلاه أنه أثناء التطوير لا يمكنك التخلي عن الوسائل المعتادة ، يمكن بسهولة تكوين Jupyter Notebook بسهولة مع Scala.
بالطبع ، للحصول على نظرة عامة كاملة على جميع ميزات Smile ، لا يكفي مقال واحد ، ولم يتم تضمين ذلك في الخطط. المهمة الرئيسية - لفتح الباب أمام عالم التعلم الآلي على سكالا - أعتقد أنه اكتمل. سواء كنت تستخدم هذه الأدوات ، بل وأكثر من ذلك ، جرها إلى الإنتاج أم لا ، أمر متروك لك!
مراجع