NumPy: البث
آخر تحديث: 2026-08-26
البث
1. ما ستتعلمه
- ❶ القواعد الثلاث للبث
- ❷ البث العددي ← 1D ← 2D
- ❸ فحوصات التوافق
- ❹ الأخطاء الشائعة
- ❺ أداء البث مقابل الحلقات
2. قصة حقيقية لمطور
(1) المشكلة
بوب يريد إضافة متجه صف 1×3 إلى كل صف من مصفوفة 4×3. يكتب حلقة for من 4 أسطر — كود قبيح، بطيء، وسهل إفساد الفهارس.
(2) الحل
أليس تنيره: "لا حاجة لحلقة — NumPy يبث تلقائيًا. متجه الصف 'يُبث' إلى 4×3 قبل الإضافة." بوب يشاهد مخطط Mermaid ويفهم فوريًا كيف يتم "توسيع الأبعاد افتراضيًا."
(3) النتيجة
بعد إزالة الحلقة، يتقلص الكود من 6 أسطر إلى سطر واحد، ويعمل أسرع بـ 50 مرة — البث هو أساس العمليات المتجهة في NumPy.
3. قواعد البث بالتفصيل
(1) القواعد الثلاث
البث يسمح لمصفوفات ذات أشكال مختلفة بالعمل معًا في العمليات الحسابية عن طريق "محاذاة" الأبعاد تلقائيًا — بدون نسخ بيانات يدوي.
| القاعدة | الوصف | مثال |
|---|---|---|
| القاعدة 1: المحاذاة | ابدأ من أقصى البعد الأيمن، حاذِ لليسار، أضف الأبعاد المفقودة على اليسار بـ 1 | (3,) + (2,3) → حشو إلى (1,3) + (2,3) |
| القاعدة 2: توسيع الحجم-1 | إذا كان البعد بحجم 1، ا نسخه على طول هذا البعد ليطابق المصفوفة الأخرى | (1,3) + (2,3) → (2,3) + (2,3) |
| القاعدة 3: الآخرون يجب أن يتطابقوا | الأبعاد غير ذات الحجم-1 يجب أن تتطابق تمامًا، أو يظهر خطأ | (2,3) + (4,3) → ❌ 2≠4 |
مرجع سريع
| السيناريو | الشكل أ | الشكل ب | الشكل الناتج | متوافق؟ |
|---|---|---|---|---|
| عددي + مصفوفة | () |
(3,4) |
(3,4) |
✅ |
| 1D + 2D | (3,) |
(4,3) |
(4,3) |
✅ |
| عمود + صف | (4,1) |
(1,3) |
(4,3) |
✅ |
| مصفوفتان 2D | (3,1) |
(1,5) |
(3,5) |
✅ |
| عدم تطابق | (2,3) |
(4,3) |
— | ❌ |
| لا يوجد حجم-1 للتوسيع | (3,) |
(4,) |
— | ❌ |
(2) خطوات البث مصورة
إضافة مصفوفة (4,3) + متجه صف (3,):
graph TB
A["المصفوفة أ<br/>shape=(4,3)"] --> D{"القاعدة 1:<br/>محاذاة الأبعاد"}
B["المتجه ب<br/>shape=(3,)"] --> D
D --> E["حشو البعد الأيسر<br/>ب: (3,) → (1,3)"]
E --> F{"القاعدة 2:<br/>توسيع البعد=1"}
F --> G["توسيع ب على طول المحور 0<br/>(1,3) → (4,3)"]
G --> H["أ + ب_موسع<br/>shape=(4,3)"]
style A fill:#4CAF50,color:#fff
style B fill:#2196F3,color:#fff
style D fill:#FF9800,color:#fff
style F fill:#FF9800,color:#fff
style G fill:#9C27B0,color:#fff
style H fill:#E91E63,color:#fff
(3) البث عمليًا
import numpy as np
---
## 4. عددي + مصفوفة
a = np.array([1, 2, 3])
print(a + 10) # [11 12 13]
---
## 5. 1D + 2D
matrix = np.arange(12).reshape(4, 3)
row = np.array([10, 20, 30])
print(matrix + row)
---
## 6. [[10 22 34]
---
7. [13 25 37]
---
8. [16 28 40]
---
9. [19 31 43]]
---
## 10. عمود + صف (عملية خارجية)
col = np.array([[1], [2], [3], [4]]) # shape (4, 1)
print(col + row)
---
## 11. [[11 21 31]
---
12. [12 22 32]
---
13. [13 23 33]
---
14. [14 24 34]]
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
15. الأخطاء الشائعة
(1) عدم تطابق الشكل
a = np.ones((3, 2))
b = np.ones((2, 3))
---
## 16. a + b # ValueError: shapes (3,2) and (2,3) غير متوافقة
(2) بث غير متوقع
a = np.ones((3, 1))
b = np.ones((3,))
---
## 17. a + b يبث إلى (3, 3) — قد لا يكون ما تتوقعه!
(3) النتيجة المقصودة
---
## 18. لتجنب البث، استخدم أشكالًا صريحة
a = np.ones((3, 1))
b = np.ones((3, 1)) # أو b[:, np.newaxis]
print((a + b).shape) # (3, 1) — لا بث
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
▶ مثال
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
: البث من عددي إلى 2D (الصعوبة ⭐)
import numpy as np
---
## 19. بث عددي
arr = np.array([[1, 2, 3],
[4, 5, 6]])
print("arr + 10:\n", arr + 10)
print("arr * 2:\n", arr * 2)
print("arr ** 2:\n", arr ** 2)
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
▶ مثال
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
: عمود + صف = عملية خارجية (الصعوبة ⭐⭐)
import numpy as np
---
## 20. توحيد البيانات: طرح المتوسط، القسمة على الانحراف المعياري
data = np.random.randn(5, 3) # 5 عينات، 3 خصائص
mean = data.mean(axis=0) # shape (3,)
std = data.std(axis=0) # shape (3,)
standardized = (data - mean) / std # بث!
print("Standardized shape:", standardized.shape) # (5, 3)
print("Mean of standardized:", standardized.mean(axis=0).round(6))
---
## 21. [ 0. 0. 0.] (ضمن حدود دقة الفاصلة العائمة)
> **المخرجات:** قم بتشغيل NumPy 2.x في بيئة Python المحلية لديك لرؤية مخرجات ndarray. خادم Piston لا يحتوي على NumPy مثبتًا مسبقًا — قم بتثبيته محليًا (`pip install numpy`) وقارن. قد تختلف القيم الفعلية حسب إصدار NumPy والبذرة العشوائية.
22. جداول المقارنة
(1) البث مقابل الحلقة
| البعد | حلقة Python for | بث NumPy |
|---|---|---|
| طبقة التنفيذ | مفسر Python | دالة ufunc على مستوى C |
| السرعة | بطيء (10-100x) | سريع |
| الكود | for i in range(n): ... |
a + b |
| الذاكرة | لا تخصيص إضافي | افتراضي (لا نسخ بيانات) |
| قابلية القراءة | منخفضة | عالية |
(2) توافق البث
| الشكل أ | الشكل ب | متوافق؟ | النتيجة |
|---|---|---|---|
| (3,) | (3,) | ✅ | (3,) |
| (3,) | (1,) | ✅ | (3,) |
| (4,3) | (3,) | ✅ | (4,3) |
| (4,3) | (4,1) | ✅ | (4,3) |
| (4,1) | (1,3) | ✅ | (4,3) |
| (2,3) | (4,3) | ❌ | خطأ |
| (3,) | (4,) | ❌ | خطأ |
23. مخطط المبدأ
graph TB
A[مصفوفات الإدخال] --> B[محاذاة الأبعاد من اليمين]
B --> C{الحجم متطابق؟}
C -->|نعم| D[عملية مباشرة]
C -->|أحدهما 1| E[توسيع البعد ذي الحجم-1]
E --> D
C -->|ليس أي منهما 1| F[ValueError: غير متوافق]
D --> G[المصفوفة الناتجة]
style A fill:#e1f5fe
style C fill:#fff9c4
style D fill:#c8e6c9
style F fill:#ffccbc
style G fill:#c8e6c9
### ▶ مثال: بث ثلاثي الأبعاد مع newaxis (الصعوبة ⭐⭐)
```python
import numpy as np
---
## 24. مصفوفة 3D + متجه 1D
arr_3d = np.arange(24).reshape(2, 3, 4)
vec = np.array([10, 20, 30, 40])
result = arr_3d + vec
print("Shape:", result.shape)
print("First layer:\n", result[0])
---
## 25. البث مع newaxis
col = np.array([0, 10, 20])[:, np.newaxis]
row = np.array([1, 2, 3, 4])
print("col + row:\n", col + row)
المخرجات:
Shape:
First layer:\n
col + row:\n
المخرجات:
TEXT 📖 للعرض فقطShape: (2, 3, 4) First layer: [[10 21 32 43] [14 25 36 47] [18 29 40 51]] col + row: [[ 1 2 3 4] [11 12 13 14] [21 22 23 24]]
❓ أسئلة شائعة
np.einsum أو np.matmul للتحكم الصريح.np.tile و np.repeat يوسعان البيانات فعليًا في الذاكرة. البث يفعلها افتراضيًا. البث أسرع ويستخدم ذاكرة أقل. استخدم tile/repeat فقط عندما تحتاج المصفوفة الموسعة لعمليات أخرى.📖 ملخص
- البث يحاذي الأبعاد من اليمين، يحشو المفقودة بـ 1، يوسع الأبعاد ذات الحجم-1
- العمليات العددية، عمليات متجه الصف/العمود، وتوحيد البيانات كلها تستخدم البث
- البث افتراضي — لا يتم نسخ البيانات فعليًا، فقط بيانات الخطوات الوصفية تتغير
- الأخطاء الشائعة: البث غير المقصود بأشكال غير متطابقة، نسيان استخدام
[:, np.newaxis] - البث دائمًا أسرع من حلقات Python ويستخدم ذاكرة أقل من التوسيع الصريح
📝 تمارين
-
مبتدئ (الصعوبة ⭐): أنشئ مصفوفة 4x3 ومتجه صف 1x3. اجمعهما معًا. ثم أنشئ متجه عمود 4x1 واجمعه مع المصفوفة. لاحظ الأشكال.
-
متوسط (الصعوبة ⭐⭐): أنشئ مصفوفة ثلاثية الأبعاد بالشكل (5, 4, 3) ومصفوفة أحادية البعد بالشكل (3,). اجمعهما. اشرح أي الأبعاد تم بثها. ثم حاول إضافة مصفوفة (4, 3) إلى المصفوفة ثلاثية الأبعاد — هل تعمل؟
-
متقدم (الصعوبة ⭐⭐⭐): أنشئ 1000 نقطة بيانات بـ 5 خصائص لكل منها. وحد البيانات (اطرح المتوسط، اقسم على الانحراف المعياري) باستخدام البث. ثم نفذ نفس العملية بحلقة Python for. قارن وقت التنفيذ.