ستتعلم في هذه السلسلة التعليمية كيفية تطوير مشروع يدمج خوارزميات تعلم الآلة للتنبؤات والواقع المعزز لتصور البيانات.
في هذا المشروع، سنستخدم Unity 3D وEasyAR، وسنبني خوارزميات تعلم الآلة من الألف إلى الياء لنمنحك فهمًا أفضل لكيفية عمل تعلم الآلة.
سيتم تقسيم هذا البرنامج التعليمي إلى ثلاثة أجزاء:
- كيفية تحميل مجموعة بيانات وكتابة خوارزميات تعلم الآلة في Unity 3D
- تصور البيانات باستخدام Unity 3D
- ربط مخرجات خوارزمية التعلم الآلي مع تصورات بيانات الواقع المعزز باستخدام EasyAR
Unity
Unity هو محرك ألعاب متعدد المنصات تم تطويره بواسطة Unity Technologies، وهو يمنح المستخدمين القدرة على إنشاء ألعاب ثنائية وثلاثية الأبعاد، ويقدم المحرك واجهة برمجة تطبيقات نصية أساسية في C#، لكل من محرر Unity في شكل مكونات إضافية وألعاب أنفسهم، بالإضافة إلى وظيفة السحب والإفلات.
في هذا البرنامج التعليمي، سيتم استخدام Unity 3D لإنشاء تصور ثلاثي الأبعاد للبيانات في الواقع المعزز.
Unity هي أداة التطوير المفضلة لغالبية منشئي XR. تدعم هذه المنصة أغلبية AR SDK، مثل ARCore وARKit وEasyAR، مما يسمح لنا بتطوير تجارب الواقع المعزز لجميع الأجهزة تقريبًا. تم إنشاء غالبية تجارب الواقع المعزز حول العالم باستخدام Unity.
إذا لم تقم بتثبيت Unity 3D بعد، فيمكنك تنزيل Unity Personal مجانًا من موقع Unity على الويب.
تعلم الآلة
تعلم الآلة (ML) هو مجموعة فرعية من الذكاء الاصطناعي الذي يتكون من تطبيق التقنيات الإحصائية والخوارزميات، من أجل جعل الآلات قادرة على التعلم من البيانات وتنبؤات المخرجات.
التطبيقات الممكنة لتعلم الآلة تكاد لا تنتهي. اعتمادًا على الموقف الذي نريد التعامل معه (على سبيل المثال، توقع ما إذا كان هناك شذوذ في مجموعة البيانات، أو التنبؤ بنمو مبيعات سلعة/خدمة أو التعرف على الصور وتصنيفها)، يمكننا استخدام خوارزميات وتقنيات معالجة مختلفة.
في هذا البرنامج التعليمي، سنستخدم تعلم الآلة للتنبؤ بعدد المرضى المستقبليين الذين سيتم إدخالهم إلى مستشفى وهمي. لهذا الغرض، سوف نستخدم الانحدار الخطي.
الانحدارالخطي
الانحدار الخطي هو طريقة إحصائية تسمح لنا بدراسة العلاقة بين متغيرين مستمرين. أحدهما هو المتغير التابع بينما واحد أو أكثر هو المتغيرات التوضيحية. ويسمى بالانحدار الخطي لأننا نفترض أن هناك علاقة خطية بين متغيرات الإدخال (x) ومتغيرات الإخراج (y). عندما يكون متغير الإدخال فريدًا نتحدث عن الانحدار الخطي البسيط، وعندما يكون المدخل أكثر من ذلك نتحدث عن الانحدار الخطي المتعدد.
إعداد المشروع الخاص بك
أولاً، لنفتح Unity وننشئ مشروعك، مع تحديد 3D
دعونا نملأ مشهدنا، وننشئ لوحة جديدة من أجل بناء واجهة مستخدم، حيث سنضيف النصوص والمدخلات والزر.
لقد غيرت خلفية اللوحة إلى شفاف، لكن لا تتردد في اختيار اللون الذي تفضله.
سأستخدم TextMeshPro، وهو مجاني للنصوص ذات المظهر الأفضل في واجهة المستخدم، ويمكنك العثور عليه في Unity Asset Store.
بعد استيراد asset، قم بإضافة كائن TextMeshPro Text إلى اللوحة، والآن يجب أن ترى العنصر الجديد في قائمة واجهة المستخدم. لقد قمت بتخصيص النص والحجم باستخدام المفتش. في حالتي، اخترت اللون الأسود و18 كحجم ولكن يمكنك تخصيص النص الخاص بك كما تريد. من أجل تغيير النص، عليك ببساطة تغيير النص في مربع الإدخال وخصائصه في قسم المفتش ذي الصلة.
لقد قمت بتثبيت النص في أعلى اليسار، لذا حتى مع اختلاف أحجام الشاشة، سيظل النص دائمًا في أعلى اليسار. يعد هذا أمرًا مهمًا لجعل واجهة المستخدم لدينا سريعة الاستجابة، نظرًا لأن الأجهزة المحمولة بها مجموعة متنوعة من أحجام الشاشات. من أجل القيام بذلك، يمكننا استخدام أقسام الإعدادات المسبقة للإرساء داخل المفتش، فقط انقر على أيقونة الإرساء. يمكنك رؤية مثال في لقطة الشاشة أدناه.
ثم قمت بإعادة تسمية شبكة النص إلى “DatasetText”، وسنستخدم هذا النص لاحقًا لتصور محتوى مجموعة البيانات.
دعونا نلقي نظرة على ملف dataset.csv الخاص بنا، فهو يحتوي على عمودين، السنة والكمية.
يحتوي كل صف على سنة وكمية الطلبات المستلمة في ذلك العام.
وكما نرى في الصف الأول، لدينا عام 2000 و200 كعدد من المرضى الميسورين في ذلك العام. وكما كتبت في المقدمة، نريد في هذا المشروع التنبؤ بعدد المرضى الذين سيستقبلهم المستشفى في السنوات المقبلة.
سنستخدم هذا النص لاحقًا لتصور مخرجات التنبؤ بالانحدار الخطي.
أنشئ مجلدًا جديدًا باسم “Resources”، ثم قم بتنزيل ملف dataset.csv داخل هذا المجلد من هذا الرابط.
بعد ذلك، لنقم بإنشاء كائن لعبة فارغ حيث سنقوم بتعيين البرنامج النصي الخاص بنا، وقمت بإعادة تسمية الكائن “ScriptObject”.
ثم نقوم بإنشاء مجلد آخر للنصوص البرمجية يسمى “Scripts“.
يمكننا إنشاء برنامج نصي جديد، والنقر بزر الماوس الأيمن داخل المجلد والنقر على البرنامج النصي C#.
أولاً، لنقم بإنشاء واجهة بيانات لمجموعة البيانات الخاصة بنا، وإنشاء برنامج نصي يسمى DataInterface.cs في مجلد البرامج النصية.
تحتوي الواجهة في C# على إعلان عن الأساليب والخصائص والأحداث فقط، وليس التنفيذ. سيقوم الفئة بتنفيذ الواجهة من خلال توفير التنفيذ لجميع أعضاء الواجهة، مما يسهل صيانة البرنامج.
إذا كنت تريد معرفة المزيد عن الواجهات في C# أقترح عليك هذا الرابط.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DataInterface
{
public int year;
public int quantity;
}
كما ترون لدينا متغيرين، واحد لكل عمود من مجموعة البيانات.
الآن، لنقم بإنشاء برنامج نصي جديد يسمى LinearRegression.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class LinearRegression : MonoBehaviour
{
public TextMeshProUGUI textDatasetObject;
List<double> yearValues = new List<double>();
List<double> quantityValues = new List<double>();
void Start()
{
TextAsset csvdata = Resources.Load<TextAsset>("dataset");
string[] data = csvdata.text.Split(new char[] { 'n' });
textDatasetObject.text = "Year Quantity";
for (int i = 1; i < data.Length - 1; i++)
{
string[] row = data[i].Split(new char[] { ',' });
if (row[1] != "")
{
DataInterface item = new DataInterface();
int.TryParse(row[0], out item.year);
int.TryParse(row[1], out item.quantity);
yearValues.Add(item.year);
quantityValues.Add(item.quantity);
textDatasetObject.text += "n" + item.year + " " + item.quantity;
}
}
}
في البداية، يمكنك أن ترى أنني كتبت:
- using System لتمكين المزيد من الميزات.
- استخدام UnityEngine.UI لعناصر واجهة المستخدم
- استخدام TMPro لعناصر TextMeshPro
بعد ذلك، قمت بالإعلان عن TextMesh، وسنقوم لاحقًا بربطه بكائن نصي في واجهة المستخدم.
في السطرين أدناه، قمت بإنشاء قائمتين مختلفتين، إحداهما تحتوي على جميع السنوات والأخرى تحتوي على جميع الكميات.
لقد قمت بتحميل مجموعة البيانات في دالة Start من موارد أصول النص، واستخرجت لكل صف من dataset.csv السنة والكمية النسبية.
لقد قمت بتعيين رأس نص لكائن Dataset Text لتجنب النتائج غير المتوقعة، مثل تكرار الأسطر.
لقد استخدمت Split لاستخراج الصفوف من الملف ووضعها في صفوف مختلفة باستخدام n لكسر السطور. لقد كتبت حلقة للتنقل بين الصفوف، واستخرجت باستخدام TryParse قيمة السنة أو الكمية من كل صف.
لقد أضفت هذه القيم إلى القوائم النسبية وقمنا بملء كائن نص مجموعة البيانات بكل المحتوى من القائمتين، باستخدام n دائمًا لإخراج كل سطر على حدة.
دالة Start هي دالة محجوزة في Unity، وسيتم تنفيذ هذه الدالة على الفور عند إنشاء الكائن الذي تم تعيين هذا البرنامج النصي له. مع أخذ هذا في الاعتبار، إذا قمنا بتضمين كائن من بداية المشهد، فسيتم تنفيذ البرنامج النصي مباشرة عندما يبدأ المشهد. ولهذا السبب أنشأنا كائنًا فارغًا مع تعيين هذا البرنامج النصي، لذلك سيتم تحميل مجموعة البيانات من البداية.
دعونا نتصور مجموعة البيانات الخاصة بنا داخل لوحة واجهة المستخدم. أولاً، نقوم بتعيين برنامج الانحدار الخطي إلى ScriptObject، مع سحب البرنامج النصي داخل مفتش ScriptObject.
ثم نقوم بسحب كائن DatasetText داخل فتحة نص البرنامج النصي.
الآن، يمكننا رؤية محتويات مجموعة البيانات في واجهة المستخدم، بالنقر فوق تشغيل في محرر Unity.
دعونا نضيف جزءًا آخر من واجهة المستخدم، وسنقوم بإنشائه من قسم قائمة واجهة المستخدم:
- TextMeshPro، كتسمية لحقل الإدخال، قمت بإعادة تسمية هذا الكائن “EnterYearLabel“
- InputField، لإدخال سنة التنبؤ
- Button، لكي نبدأ بالتنبؤ، قم بتغيير نص الزر إلى “التنبؤ”
- TextMeshPro، من أجل تصور نتيجة توقعنا، قمت بإعادة تسمية هذا الكائن “ResultPredictionText“
لقد قمت بتثبيت كل هذه العناصر في الزاوية اليمنى العليا من الشاشة.
لنقم بإنشاء الوظيفة التي ستحسب الانحدار الخطي داخل LinearRegression.cs
public static void LinearRegressionCalc(
double[] xValues,
double[] yValues,
out double yIntercept,
out double slope)
{
if (xValues.Length != yValues.Length)
{
throw new Exception("Input values should be with the same length.");
}
double xSum = 0;
double ySum = 0;
double xSumSquared = 0;
double ySumSquared = 0;
double codeviatesSum = 0;
for (var i = 0; i < xValues.Length; i++)
{
var x = xValues[i];
var y = yValues[i];
codeviatesSum += x * y;
xSum += x;
ySum += y;
xSumSquared += x * x;
ySumSquared += y * y;
}
var count = xValues.Length;
var xSS = xSumSquared - ((xSum * xSum) / count);
var ySS = ySumSquared - ((ySum * ySum) / count);
var numeratorR = (count * codeviatesSum) - (xSum * ySum);
var denomR = (count * xSumSquared - (xSum * xSum)) * (count * ySumSquared - (ySum * ySum));
var coS = codeviatesSum - ((xSum * ySum) / count);
var xMean = xSum / count;
var yMean = ySum / count;
yIntercept = yMean - ((coS / xSS) * xMean);
slope = coS / xSS;
هذه الدالة هي ببساطة تقوم بتحويل المعادلة الرياضية للانحدار الخطي إلى كود C#. كما ترون في الكود، قمت بتمرير داخل هذه الوظيفة القيم المتعلقة بالسنوات والقيم المتعلقة بالكميات. لقد قمت بتمرير قائمة السنوات كـ xValues وقائمة الكمية كـ yValues من أجل التنبؤ بالكميات المستقبلية.
تُخرج هذه الدالة تقاطع وانحدار الانحدار الخطي، وسنستخدم هذه القيم لبناء تنبؤنا في الدالة التالية.
الآن، دعونا نتعمق في المشروع، ونقوم بتوصيل الكود الذي كتبناه من قبل!
دعونا نضيف المراجع إلى عناصر واجهة المستخدم الجديدة:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class LinearRegression : MonoBehaviour
{
public TextMeshProUGUI textPredictionResult;
public TextMeshProUGUI textDatasetObject;
public InputField inputObject;
List<double> yearValues = new List<double>();
List<double> quantityValues = new List<double>();
void Start()
{
TextAsset csvdata = Resources.Load<TextAsset>("dataset");
string[] data = csvdata.text.Split(new char[] { 'n' });
textDatasetObject.text = "Year Quantity";
for (int i = 1; i < data.Length - 1; i++)
{
string[] row = data[i].Split(new char[] { ',' });
if (row[1] != "")
{
DataInterface item = new DataInterface();
int.TryParse(row[0], out item.year);
int.TryParse(row[1], out item.quantity);
yearValues.Add(item.year);
quantityValues.Add(item.quantity);
textDatasetObject.text += "n" + item.year + " " + item.quantity;
}
}
}
كما ترون، قمت في الأسطر الأولى بتضمين المراجع إلى حقل الإدخال ونص نتيجة التنبؤ الجديد:
- public TextMeshProUGUI textPredictionResult، ستكون الفتحة في البرنامج النصي حيث نقوم بتعيين النص الذي سيخرج التنبؤ
- سيكون public TextMeshProUGUI textDatasetObject هو الفتحة الموجودة في البرنامج النصي حيث نقوم بتعيين النص الذي سيخرج مجموعة البيانات
- سيكون public InputField inputObject هو الفتحة الموجودة في البرنامج النصي حيث نقوم بتعيين حقل الإدخال حيث سيقوم المستخدم بإدراج سنة التنبؤ
الآن، لنقم بإنشاء الدوال التي ستنتج التنبؤ في واجهة المستخدم الخاصة بنا.
public void PredictionTask()
{
double intercept, slope;
LinearRegressionCalc(yearValues.ToArray(), quantityValues.ToArray(), out intercept, out slope);
var predictedValue = (slope * int.Parse(inputObject.text)) + intercept;
textPredictionResult.text = "Result: " + predictedValue;
Debug.Log("Prediction for " + inputObject.text + " : " + predictedValue);
}
في دالة PredictionTask، أقوم أولاً بالتحويل إلى مصفوفة وتمرير القائمتين كقيمتين x وy. بعد أن أحصل على نتائج دالة LinearRegressionCalc أقوم بحساب التنبؤ. لقد استخدمت قيمة حقل نص الإدخال كسنة للتنبؤ بالكمية، وضرب قيمتها بميل الدالة وإضافة التقاطع. في النهاية، أقوم بإخراج نتيجة التنبؤ في كائن النص الخاص بتنبؤ واجهة المستخدم.
الآن، نقوم بتوصيل البرامج النصية إلى واجهة المستخدم. لنقم بسحب LinearRegression.cs إلى مفتش الزر.
بعد ذلك، نقوم بسحب حقل الإدخال ونص التنبؤ ونص مجموعة البيانات إلى مكون البرنامج النصي داخل مفتش الزر.
نقوم بسحب الزر داخل قسم onClick للزر نفسه، ونضبط حدث onClick على دالة PredictionTask.
كما ترون في لقطة الشاشة أدناه، قمنا بتعيين PredictionTask من البرنامج النصي LinearRegression.
أخيرًا، في نافذة لعبة Unity Game، انقر فوق “تشغيل”. يمكننا أن نرى الآن نتيجة توقعنا بإدخال عام في حقل الإدخال والنقر على زر التنبؤ. سيكون لدى مستشفانا توقع لعدد المرضى الذين سيتعين عليهم الاعتناء بهم في السنوات القادمة ويتم التصرف وفقًا لذلك:
- توظيف أطباء جدد مقدما
- التخطيط لبناء مناطق جديدة بالمستشفى لتتمكن من رعاية عدد كبير من المرضى
ستستغرق كل هذه الأشياء وقتًا، لذا من الأفضل التصرف في أقرب وقت ممكن، والتنبؤ يسمح لنا بالقيام بذلك تمامًا. شيء آخر يجب ملاحظته هو أنه في تطبيقات العالم الحقيقي، من الأفضل استخدام متغيرات متعددة لزيادة دقة التنبؤ.
هذا كل ما في الجزء الأول من البرنامج التعليمي، وآمل أن تستمتع به!
في الجزء التالي، سنقوم بإنشاء تصورات البيانات ثلاثية الأبعاد. في هذه الأثناء، استمتع بنموذجنا، وحاول تضمين مجموعات بيانات أخرى وتخصيص واجهة المستخدم! 🙂
اكتشاف المزيد من بايثون العربي
اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.