طرق إنشاء الموترات (Tensors) في PyTorch: دليل شامل للمطورين
PyTorch هي مكتبة مفتوحة المصدر مبنية على Python، وتُعد حجر الزاوية في تطوير نماذج التعلم العميق (Deep Learning). توفر هذه المكتبة مرونة وسرعة فائقة في بناء وتدريب ونشر هذه النماذج المعقدة. في جوهرها، تعتمد PyTorch بشكل أساسي على عمليات الموترات (Tensors). الموتر هو تمثيل رياضي يمكن أن يكون رقماً فردياً (scalar)، أو متجهاً (vector)، أو مصفوفة (matrix)، أو أي مصفوفة متعددة الأبعاد (n-dimensional array). في هذا المقال، سنتعمق في استكشاف الطرق المختلفة لإنشاء الموترات باستخدام دوال PyTorch المخصصة لذلك، مما يمنحك فهماً شاملاً لكيفية التعامل مع هذه اللبنات الأساسية.
سنغطي الطرق التالية لإنشاء الموترات:
tensor()zeros()ones()full()arange()linspace()rand()randint()eye()complex()
دالة tensor(): الأساس في إنشاء الموترات
تُعد دالة tensor() الطريقة الأكثر مرونة لإنشاء موتر في PyTorch. تقوم هذه الدالة بإرجاع موتر عند تمرير بيانات (data) إليها. يمكن أن تكون هذه البيانات عبارة عن قيمة عددية مفردة (scalar)، أو مجموعة (tuple)، أو قائمة (list)، أو حتى مصفوفة NumPy (NumPy array).
على سبيل المثال، إذا قمت بإنشاء مصفوفة NumPy باستخدام np.arange() ومررتها إلى دالة tensor()، فستحصل على موتر أحادي البعد (1-D tensor). لإنشاء موتر متعدد الأبعاد، يمكنك تمرير مجموعة من المجموعات (tuple of tuples)، أو قائمة من القوائم (list of lists)، أو مصفوفة NumPy متعددة الأبعاد. من الجدير بالذكر أنه عند تمرير مجموعة أو قائمة فارغة إلى tensor()، فإنها تُنشئ موترًا فارغًا.
دالة zeros(): موترات الأصفار
كما يوحي اسمها، تُرجع دالة zeros() موترًا تكون جميع عناصره أصفارًا. يتم تحديد حجم (size) أو شكل (shape) هذا الموتر. يمكن تحديد الحجم كمجموعة (tuple) أو قائمة (list)، أو يمكن تمرير الأبعاد مباشرة كمعاملات منفصلة.
على سبيل المثال، لتكوين موتر بحجم (3, 2)، يمكنك تمرير (3, 2) كمجموعة أو [3, 2] كقائمة. من البديهي أن تمرير أرقام سالبة أو أرقام عشرية كأبعاد سيؤدي إلى خطأ في وقت التشغيل (runtime error). عند تمرير مجموعة أو قائمة فارغة، تُنشئ الدالة موترًا بحجم (بعد) 0، ويحتوي على العنصر 0 فقط، ويكون نوع بياناته افتراضياً float.
دالة ones(): موترات الآحاد
على غرار دالة zeros()، تُرجع دالة ones() موترًا تكون جميع عناصره مساوية للرقم 1. يتم تحديد حجم (size) أو شكل (shape) هذا الموتر بنفس الطريقة، إما كمجموعة أو قائمة أو كمعاملات منفصلة.
وكما هو الحال مع zeros()، فإن تمرير مجموعة أو قائمة فارغة إلى ones() يؤدي إلى إنشاء موتر ذي بعد 0، يحتوي على العنصر 1 فقط، ويكون نوع بياناته افتراضياً float.
دالة full(): موترات بقيمة محددة
ماذا لو أردت أن تكون جميع عناصر الموتر مساوية لقيمة معينة غير 0 أو 1؟ ربما 2.9؟ هنا تأتي فائدة دالة full(). تُرجع هذه الدالة موترًا بالشكل المحدد بواسطة الوسيط size، وتكون جميع عناصره مساوية للقيمة المحددة في الوسيط fill_value.
على سبيل المثال، يمكننا إنشاء موتر بحجم (3, 2) مع قيمة تعبئة (fill_value) تساوي 3. مرة أخرى، يؤدي تمرير مجموعة أو قائمة فارغة إلى إنشاء موتر عددي (scalar tensor) ذي بعد صفري. عند استخدام full()، من الضروري تحديد size كمجموعة أو قائمة.
دالة arange(): موترات المتتاليات الحسابية
تُرجع دالة arange() موترًا أحادي البعد، يحتوي على عناصر تبدأ من start (شاملة) وتصل إلى end (غير شاملة)، مع فارق مشترك (step). القيمة الافتراضية لـ start هي 0، بينما القيمة الافتراضية لـ step هي 1. يمكن وصف عناصر الموتر بأنها في متتالية حسابية (Arithmetic Progression)، حيث يمثل step الفارق المشترك.
على سبيل المثال، يمكننا إنشاء موتر يبدأ من 2 ويصل إلى 20 (غير شاملة) بفارق step قدره 2. يمكن أن تكون جميع المعلمات الثلاثة (start، end، و step) موجبة أو سالبة أو عشرية. عند اختيار هذه المعلمات، يجب التأكد من أن start و end متناسقان مع إشارة step. فمثلاً، إذا كان step مضبوطًا على -2، فلا يمكن لـ -42 أن يصل إلى -22 (غير شاملة) بشكل تصاعدي، مما سيؤدي إلى خطأ.
دالة linspace(): موترات المسافات المتساوية
تُرجع دالة linspace() موترًا أحادي البعد، يحتوي على عناصر تبدأ من start (شاملة) وتصل إلى end (شاملة). ومع ذلك، على عكس arange()، فإن steps هنا لا يمثل الفارق المشترك، بل يمثل عدد العناصر التي يجب أن يحتوي عليها الموتر. يقوم PyTorch تلقائيًا بحساب الفارق المشترك بناءً على عدد steps المحدد.
تجنب عدم توفير قيمة لـ steps لأنه أصبح مهملًا (deprecated). للتوافق مع الإصدارات السابقة، يؤدي عدم توفير قيمة لـ steps إلى إنشاء موتر يحتوي على 100 عنصر. وفقًا للوثائق الرسمية، في إصدار مستقبلي من PyTorch، سيؤدي الفشل في توفير قيمة لـ steps إلى حدوث خطأ في وقت التشغيل (runtime error). على عكس arange()، يمكن أن تكون قيمة start في linspace() أكبر من end، حيث يتم حساب الفارق المشترك تلقائيًا. بما أن steps هنا هو عدد العناصر وليس فارقًا مشتركًا، فيجب أن يكون عددًا صحيحًا غير سالب.
دالة rand(): موترات الأرقام العشوائية الموحدة
تُرجع دالة rand() موترًا مملوءًا بأرقام عشوائية تم إنشاؤها من توزيع موحد (uniform distribution) على الفترة من 0 (شاملة) إلى 1 (غير شاملة). يتم تحديد شكل (shape) الموتر بواسطة الوسيط size. يمكن تحديد الوسيط size كمجموعة أو قائمة أو كمعاملات منفصلة. يؤدي تمرير مجموعة أو قائمة فارغة إلى إنشاء موتر عددي (scalar tensor) ذي بعد صفري.
دالة randint(): موترات الأعداد الصحيحة العشوائية
تُرجع دالة randint() موترًا مملوءًا بأعداد صحيحة عشوائية تم إنشاؤها بشكل موحد بين low (شاملة) و high (غير شاملة). يتم تحديد شكل الموتر بواسطة الوسيط size. القيمة الافتراضية لـ low هي 0.
عند تمرير وسيط واحد فقط من نوع int، يحصل low على القيمة الافتراضية 0، ويحصل high على القيمة الممررة. يقبل الوسيط size مجموعة أو قائمة فقط. يؤدي تمرير مجموعة أو قائمة فارغة إلى إنشاء موتر ذي بعد صفري.
دالة eye(): موترات مصفوفة الوحدة
تُرجع دالة eye() موترًا ثنائي الأبعاد (2-D tensor) تكون فيه جميع العناصر على القطر الرئيسي (diagonal) مساوية للرقم 1، بينما تكون جميع العناصر الأخرى أصفارًا. يتم تحديد عدد الصفوف (rows) بواسطة n وعدد الأعمدة (columns) بواسطة m. القيمة الافتراضية لـ m هي قيمة n.
عند تمرير n فقط، تُنشئ الدالة موترًا على شكل مصفوفة وحدة (identity matrix). مصفوفة الوحدة هي مصفوفة تكون عناصرها القطرية 1 وجميع العناصر الأخرى 0.
دالة complex(): موترات الأعداد المركبة
تُرجع دالة complex() موترًا للأعداد المركبة (complex tensor)، حيث يكون جزؤه الحقيقي مساويًا لـ real وجزؤه التخيلي مساويًا لـ imag. يجب أن يكون كل من real و imag موترات بحد ذاتها.
يجب أن يكون نوع بيانات كل من الموترين real و imag إما float أو double. بالإضافة إلى ذلك، يجب أن يكون حجم (size) كلا الموترين real و imag متطابقًا، حيث تشكل العناصر المقابلة في المصفوفتين عددًا مركبًا واحدًا.
الخلاصة التقنية
في هذا المقال، استعرضنا عشر طرق مختلفة وفعالة لإنشاء الموترات في مكتبة PyTorch، وهي اللبنة الأساسية لأي عملية تعلم عميق. بدءًا من الدالة العامة tensor() التي تتيح مرونة كبيرة في إدخال البيانات، وصولًا إلى الدوال المتخصصة مثل zeros() و ones() و full() لإنشاء موترات بقيم محددة. كما غطينا دوال إنشاء المتتاليات مثل arange() و linspace()، ودوال توليد الأرقام العشوائية rand() و randint()، بالإضافة إلى eye() لإنشاء مصفوفات الوحدة، و complex() للتعامل مع الأعداد المركبة. فهم هذه الدوال واستخداماتها يمثل خطوة أساسية للمطورين الذين يسعون لبناء نماذج تعلم عميق قوية ومرنة باستخدام PyTorch. يُنصح دائمًا بالرجوع إلى الوثائق الرسمية لـ PyTorch لاستكشاف المزيد من الدوال والميزات المتقدمة.