اذهب إلى المحتوى
  • 0

خطأ ValueError: operands could not be broadcast together with shapes في Numpy

Amer Abdallah

السؤال

لدي مصفوفتان numpy الأولى: x هي (m ، n) والثانية: y متجه (n ، 1)

عندما أحاول إتمام عملية الضرب كالتالي:

x*y

أحصل على الخطأ:

ValueError: operands could not be broadcast together with shapes (97,2) (2,1) 

عندما يكون حجم المصفوفة x هو (7,2) وحجم المصفوفة y هو (2,1) فمن المفترض أن تتم عملية الضرب بدون مشكلة ويكون الناتج عبارة عن مصفوفة حجمها (7,1)

لماذا يظهر الخطأ السابق؟ وكيف أقوم بعملية الضرب هنا؟

رابط هذا التعليق
شارك على الشبكات الإجتماعية

Recommended Posts

  • 1

هذا صحيح يجب أن تتم العملية من دون مشاكل لأن شرط ضرب المصفوفتين محقق، لكن أنت تستخدم المعامل الخطأ لضرب المصفوفتين.فالمعامل * يستخدم لتطبيق عملية الضرب عنصر بعنصر أي eliment-wise أي يقوم بضرب العناصر المتقابلة من المصفوفتين وبالتالي يجب أن تكون المصفوفتين بأبعاد متطاااابقة بالطول والعرض. أما إذا أردت تنفيذ عملية الضرب العادي للمصفوفات فهنا يجب أن تستخدم التابع dot (ولاتخلط بينه وبين ال . فال . ليس لها علاقة بالجداء وإنما هي خاصة بال attribute واستخدامها هنا سيعطي خطأ):

import numpy as np
a = np.array([[2, 1],[2,4]])
b = np.array([[2, 1],[2,4]])
# ضرب عاددي
print(a.dot(b))
"""
[[ 6  6]
 [12 18]]
"""
# eliment-wise
print(a * b)
"""
[[ 4  1]
 [ 4 16]]
"""

 لكن مهلاً دعني أوضح معنى الخطأ هو يقول لك أنه فشل في تطبيق عملية تسمى "brodcast" وهي عملية يطبقها بايثون عندما تكون العملية المطلوبة غير قابلة للتطبيق (في حالتك لديك مصفوفتين بأبعاد مختلفة وتحاول تطبيق عملية ضرب عنصر بعنصر وهذا غير ممكن، لكن بايثون لاتستسلم بهذه السهولة، لذا يحاول جعل المصفوفة الصغيرة بنفس أبعاد الكبيرة لكي تتم العملية لكنه أيضاً يفشل لماذا؟ سأشرح هذا بعد قليل).
حسناً ..بايثون تدعم مانسميه ال broadcast وهو مصطلح يشير إلى  كيفية تعامل numpy مع المصفوفات ذات الأبعاد المختلفة أثناء العمليات الحسابية التي لها قيود معينة، يتم تطبيق broadcast للمصفوفة الأصغر لتتطابق مع المصفوفة الأكبر بحيث يكون لها شكل متوافق لتنفيذ العملية. وهذا أمر مفيد جداً في علوم تعلم الآلة. وبشكل أوضح أو أكثر دقة عندما تحاول تطبيق عملية (eliment-wise) ضرب أو طرح أو تطبيق أي عملية رياضية على مصفوفتين غير متوافقتين بالأبعاد فإن بايثون سيحاول جعل المصفوفتين متوافقتين لكي تتم العملية، حيث يقوم بنسخ وتكرار وتوسيع للمصفوفة الصغيرة بحيث تحقق شرط تطبيق العملية المطلوبة، وبشكل أدق ركز معي: لو كان لديك مصفوفة ابعادها (m,n) وقمت بجمعها او طرحها او ضربها او قسمتها على مصفوفة من الحجم (1 عمود و n سطر) سيتم نسخ المصفوفة الثانية m مرة ليصبح حجمها مثل حجم المصفوفة الأولى. وبشكل مشابه لو كان لديك مصفوفة بحجم m سطر و 1 عمود، سيتم نسخ هذه المصفوفة n مرة لتصبح بحجم الأولى أي (m,n) ومن ثم تطبيق العملية المرادة.
، مثال:

import numpy as np
a1 = np.array([2, 4, 3])
a1.shape
# (3,)
a2 = np.array([50, 2, 10])
a2.shape
# (3,)
# هنا مصفوفتين متوافقتين بالحجم لكن لايمكن ضربهما ضرب مصفوفات عادي لكن هنا يتم ضربهما عنصر بعنصر
c = a1 * a2
print (c)
#[350   4 180]

مثال آخر:

import numpy as np
a1 = np.array([2, 4, 3])
a1.shape
# (3,)
a2 = 3
#brodcast هنا غير متطابقين ولا يتحقق شرط الجمع لكن يتم تنفيذ عملية 
c = a1 + a2
print(c)
#[5 7 6]

مثال:

import numpy as np
a1 = np.array([[1, 2, 3], [10, 2, 30]])
a2 = 4
C = a1 + a2
print(C)
"""
[[ 5  6  7]
 [14  6 34]]
"""

لكن لل brodcast شروط وهي أن المصفوفتين يجب أن تتطابق إحدى أبعادهما وإلا يفشل وهذا ماحدث معك.

a = np.random.randn(97,2)
b = np.random.randn(2,1)
a*b #ValueError: operands could not be broadcast together with shapes (97,2) (2,1) 

 

تم التعديل في بواسطة Ali Haidar Ahmad
رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

يحصل هذا الخطأ لأنك تستخدم العملية الخاطئة, يجب أن تسخدم الدوت " . " لهذه العملية بينما عملية * تقوم بفعل أمر آخر, إذا كانت X و y من النوع numpy.matrix ، فيمكن استخدام علامة النجمة كضرب مصفوفة ولكن حاول الابتعاد عن numpy.matrix لأنها تعقد الامور بدل من تبسيطها, حاول تنفيذ الامر كالتالي

x.y

 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

هذه المشكلة تحدث بسبب شكل المصفوفات التي تريد ضربهما، دعنا نفهم كيف تتم ضرب المصفوفات.

لضرب مصفوفتين يجب ان يكون عدد الاعمدة في المصفوفة الاولى يساوى عدد صفوف المصفوفة الثانية، حيث ان ترتيب الضرب يهم، كمثال لضرب مصفوفة ذات ابعاد (5,3) * (4,5) تنتج مصفوفة ذات ابعاد (4,3) حيث تمثل اول قيمه عدد الصفوف وهي هنا =4 والقيمة الثانية عدد الاعمدة وهي هنا 3.

اما بالنسبة للمشكلة هنا تحديدا فهي بسبب استخدام الشكل * ، وهي تقوم بعملية ضرب المصفوفات فقط في حالة انها علي شكل numpy.matrix

وبشكل عام تقوم العلامة * بعمل ضرب القيم سويا او ما يسمي element wise multiplication وهذا يجعل عملية الضرب المطلوبة غير ملاءمة لانة يجب ان تكون كلتا المصفوفتين من نفس الشكل تماما.

لكن المطورين ابتعدوا عن هذا الشكل وعوضا عنها استخدموا العلامة . والتي تمثل dot product .

فيمكنك هنا اما تحويل المصفوفتين الي Numpy.matrix وضربهما او استخدام x.y للضرب مباشرة.

يمكنك كذلك استخدام numpy.dot، والتي تقوم بعملية الضرب المعتادة للمصفوفات، انظر المثال التالي:

In [1]: import numpy

In [2]: numpy.dot(numpy.ones([97, 2]), numpy.ones([2, 1])).shape
Out[2]: (97, 1)

 

تم التعديل في بواسطة Ahmed Sharshar
رابط هذا التعليق
شارك على الشبكات الإجتماعية

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...