شرح مكتبة NumPy في Python يركز على الحساب على مجموعات من الأعداد بدل كتابة حلقة لكل عنصر. ndarray مصفوفة ذات شكل ونوع بيانات محدد، وهي أساس تستخدمه مكتبات الصور والبيانات. سننشئ مصفوفة صغيرة، ونعيد تشكيلها، ونجمع متجهًا على صفوفها، ونحسب متوسط الأعمدة. المثال لا يحتاج OpenCV أو صورة خارجية؛ كل مدخلاته أعداد معلومة يمكن التحقق منها يدويًا.
التجهيز والمتطلبات
python -m pip install numpyالشكل والنوع وحجم البيانات
ينشئ arange الأعداد من 1 حتى ما قبل 7، أي ستة عناصر. يعيد reshape(2, 3) ترتيب عرضها في صفين وثلاثة أعمدة؛ لا يضيف عناصر أو يحذفها. يجب أن يساوي حاصل ضرب الأبعاد عدد العناصر. نختار dtype=np.int32 عندما نريد عددًا صحيحًا بعرض ثابت، ويمكن استخدام int عندما يكفي النوع الصحيح الافتراضي. تجنب np.int في الأكواد القديمة؛ الاسم المختصر أزيل من الإصدارات الحديثة، وهو مختلف عن np.int32.
Broadcasting بدل تكرار حلقات
جمع متجه طوله ثلاثة مع مصفوفة شكلها اثنان في ثلاثة يضيف العنصر المقابل إلى كل عمود في الصفين. النتيجة الأولى هي 11 و22 و33، والثانية 14 و25 و36. تسمى هذه المطابقة broadcasting، ولا تعني أن أي شكلين قابلان للجمع. تقارن الأبعاد من النهاية، ويجب أن يتطابق البعدان أو يكون أحدهما واحدًا. عند ظهور خطأ shapes ارجع إلى shape لكل طرف قبل تغيير القيم عشوائيًا.
المثال البرمجي الكامل
import numpy as np
def matrix_demo():
values = np.arange(1, 7, dtype=np.int32).reshape(2, 3)
shifted = values + np.array([10, 20, 30])
column_mean = values.mean(axis=0)
copied = values[:, :2].copy()
copied[0, 0] = 99
return values, shifted, column_mean, copied
if __name__ == "__main__":
values, shifted, mean, copied = matrix_demo()
print(values)
print("Broadcasting:\n", shifted)
print("Column means:", mean)
print("Copy:\n", copied)
print("Zeros:\n", np.zeros((2, 3), dtype=int))
axis والفرق بين view وcopy
تحسب mean(axis=0) متوسط كل عمود، فتظهر 2.5 و3.5 و4.5. أما axis=1 فيحسب متوسط عناصر كل صف. قص مصفوفة بعمليات slicing قد يعطي عرضًا يشارك البيانات الأصلية؛ لذلك نستخدم copy عندما نريد تعديل الجزء دون تغيير الأصل. في المثال نضع 99 داخل copied ونلاحظ أن أول عنصر في values يظل 1. فهم هذه العلاقة يمنع أخطاء صعبة عند تعديل صور أو تجهيز بيانات تدريب.
أصفار وقيم غير مهيأة وتجارب صغيرة
ينشئ zeros مصفوفة مملوءة بالأصفار. أما empty فيحجز مساحة دون ضمان قيم ابتدائية مفيدة؛ لا تستخدم ناتجه كأصفار ولا تقرأه قبل إسناد القيم. احفظ المثال باسم numpy_arrays.py وشغله ثم جرب reshape(3, 2) وراقب اختلاف الشكل. جرّب نوعًا عشريًا عند حسابات تحتاج كسورًا، وانتبه لاحتمال تجاوز سعة الأعداد الصغيرة. ابدأ بحسابات تستطيع مراجعتها يدويًا قبل تعميمها على ملايين العناصر.
متى يؤدي القص إلى تغيير الأصل؟
عمليات slicing الأساسية في NumPy غالبًا تشارك الذاكرة مع المصفوفة الأصلية. إذا أخذت جزءًا وعدلت عنصرًا فيه فقد يتغير الأصل، وهو سلوك مفيد أحيانًا لتجنب نسخ بيانات كبيرة. استخدم copy عندما تحتاج استقلالًا صريحًا، وافحص النتيجة على مثال صغير بدل الاعتماد على الاسم الجديد للمتغير. إسناد مصفوفة إلى متغير آخر لا ينسخ جميع عناصرها تلقائيًا، كما أن بعض عمليات الفهرسة الأخرى تعيد نسخة وفق نوع الفهرس.
كيف أختار dtype مناسبًا؟
انظر إلى مجال القيم ونوع الحساب والذاكرة. مصفوفة صور ذات قنوات ثمانية بت لا تتصرف كأعداد Python غير المحدودة؛ الجمع قد يتجاوز السعة أو يحتاج تحويلًا قبل الحساب. أما المتوسط فعادة ينتج قيمة عشرية حتى لو كانت المدخلات صحيحة. لا تحول كل شيء إلى نوع صغير لتقليل الحجم دون اختبار الحدود. استخدم dtype واضحًا في البيانات المتبادلة مع نموذج أو ملف حتى لا يتغير التفسير بين بيئتين.
هل reshape يغير ترتيب القيم؟
في الاستخدام الافتراضي البسيط يغير شكل العرض مع الحفاظ على تسلسل العناصر، لكنه قد يشارك الذاكرة أو ينسخها حسب شكل البيانات وترتيبها. لا تعتمد على reshape وحدها لتبديل صفوف وأعمدة مصفوفة؛ التبديل المنطقي للأبعاد يستخدم transpose. قارن مثالًا من اثنين في ثلاثة قبل وبعد كل عملية واكتب القيم المتوقعة يدويًا. هذه التجربة الصغيرة توضح الفرق أكثر من حفظ أسماء الدوال دون ربطها بالشكل والبيانات.
المراجع
ملاحظات NumPy حول الأسماء القديمة المحذوفة
الصور والفيديو من الشرح السابق
الكود النصي أعلاه هو النسخة المصححة؛ قد تختلف المواد المرئية السابقة في أسماء المتغيرات أو طريقة التشغيل.







