معرفی خاصیت پخش
قبلاً دیدیم که با استفاده از توابع عمومی عملیات ریاضی رو عناصر دو آرایه انجام میشد. برای مثال دو آرایه را با هم جمع میکردیم یا دو آرایه را از هم کم میکردیم. نکته قابل توجه این بود که دو آرایه ما باید هم بُعد و هم اندازه بودند تا توابع عمومی میتوانستند روی آنها اعمال شوند. اما در این بخش یاد میگیریم که توابع عمومی میتوانند روی دو آرایه با ابعاد متفاوت نیز اعمال شوند.
در ابتدا با یک مثال توابع عمومی را یادآوری میکنیم.
a = np.array([3, 2, 6])
b = np.array([1, 5, 9])
print("a * b =", a * b)
print("a + b =", a + b)
print("a - b =", a - b)
print("a / b =", a / b)
خروجی کد:
a * b = [ 3 10 54]
a + b = [ 4 7 15]
a - b = [ 2 -3 -3]
a / b = [3. 0.4 0.66666667]
حال در نظر بگیرید که بخواهیم تمام اعضای یک آرایه را با عدد ثابت جمع کنیم برای این منظور باید کد زیر را بنویسیم
a = np.array([3, 2, 6])
b = np.array([2, 2, 2])
print("a + b =", a + b)
خروجی کد:
a + b = [5 4 8]
اما با وجود خاصیت پخش نیازی به چنین کاری نیست و فقط کافیست بنویسیم:
a = np.array([3, 2, 6])
print("a + 2 =", a + 2)
خروجی کد:
a + 2 = [5 4 8]
در واقع آنچه در بالا اتفاق افتاد همان خاصیت پخش نام دارد. در واقع آرایه کوچکتر گسترش مییابد تا خود را هم بُعد و هم اندازه (هم شکل) آرایه بزرگتر کند و در انتها عمل ریاضی مورد نظر (جمع در مثال بالا) انجام میشود. اما باید توجه کنیم که در پشت ماجرا این گسترش انجام نمیشود و در نتیجه حافظه اضافی نیز اشغال نمیشود.
در مثال بالا خاصیت پخش را برای آرایه تک بُعدی دیدیم، اما خاصیت پخش برای آرایههای چند بُعدی نیز استفاده میشود. برای مثال فرض کنید یک آرایه دو بُعدی داریم و میخواهیم سطرهای آن را با یک آرایه تک بُعدی هم اندازه با سطرهای آن جمع کنیم. برای این کار کد زیر را داریم:
a = np.array([[4, 1, 0, 3],
[5, 2, 9, 7],
[8, 4, 6, 5]])
print("a:")
print(a)
b = np.array([1, 2, 3, 4])
print("b:")
print(b)
print("a + b:")
print(a + b)
خروجی کد:
a:
[[4 1 0 3]
[5 2 9 7]
[8 4 6 5]]
b:
[1 2 3 4]
a + b:
[[ 5 3 3 7]
[ 6 4 12 11]
[ 9 6 9 9]]
در کد بالا آرایه a یک آرایه دوبُعدی 3 در 4 است در واقع shape آن (3,4) است. و آرایه b یک آرایه یک بُعدی با 4 عضو است در واقع shape آن (,4) است. نامپای برای انجام این عملیات آرایه b را به یک آرایه (1,4) تبدیل میکند. تا دو آرایه a و b هم مرتبه شوند. در ادامه پخش کردن (کپی کردن) آرایه b در راستای محور 0 (بالا به پایین) تا جایی که تعداد سطرها هم تعداد سطرهای آرایه a شود، انجام میشود. در نتیجه آن آرایه b همانند آرایه a دارای شکل (3,4) میشود. (دقت کنیم که تمام مراحل گفته شده در پشت صحنه انجام میشود و اینکه هیچ فضای اضافیای جهت پخش آرایه اشغال نمیشود).
حال فرض کنید بخواهیم ستونهای یک آرایه دوبُعدی را با یک آرایه تک بُعدی ثابت جمع کنیم. به کد زیر توجه کنید:
a = np.array([[1, 2, 4],
[5, 8, 3],
[9, 2, 1],
[5, 6, 2]])
print("a:")
print(a)
b = np.array([[3],
[1],
[2],
[4]])
print("b:")
print(b)
print("a + b:")
print(a + b)
خروجی کد:
a:
[[1 2 4]
[5 8 3]
[9 2 1]
[5 6 2]]
b:
[[3]
[1]
[2]
[4]]
a + b:
[[ 4 5 7]
[ 6 9 4]
[11 4 3]
[ 9 10 6]]
در مثال بالا آرایه a یک آرایه دوبٌعدی 4 در 3 است یعنی shape آن برابر (4,3) است. هچنین آرایه b نیز یک آرایه تک بٌعدی 4 در 1 است یعنی shape آن برابر (4,1) است. (در این مثال از آنجایی که میخواستیم هر ستون با یک آرایه ثابت جمع شود باید خودمان آرایه ثابت را به صورت ستونی تعریف کنیم) بنابراین دو آرایه هم مرتبه هستند. پس نامپای فقط آرایه b را در راستای چپ به راست پخش (کپی) میکند تا جایی که تعداد ستونهای آرایه b با آرایه a برابر شود یعنی به شکل (4,3) برسیم. حال که دو آرایه هم شکل شدند اعضای آن جمع میشوند و نتیجه حاصل میشود.