Numpy: سلوك gufunc على شكل إخراج غير صحيح

تم إنشاؤها على ٢ يونيو ٢٠٢٠  ·  5تعليقات  ·  مصدر: numpy/numpy

من المناقشة هنا: https://github.com/numpy/numpy/pull/15162#discussion_r434122175

لا يبدو أن المثال التالي يرفع خطأ عندما يكون الشكل الخارجي غير صحيح أو يبث المدخلات إلى المخرجات ، لكنه يملأ المخرج بصمت بالنتيجة + قيم القمامة.

import numpy as np
from numpy.core import _umath_tests as umt
from numpy.testing import assert_raises
a = np.arange(6).reshape(3, 2)
b = np.ones(2)
out = np.empty((5, 3))
umt.inner1d(a, b, out)
print(out)

نتيجة:

[[ 1.00000000e+000  5.00000000e+000  9.00000000e+000]
 [ 6.91217735e-310 -1.45681599e+144 -1.45681599e+144]
 [-1.45681599e+144 -1.45681599e+144 -1.45681599e+144]
 [-1.45681599e+144 -1.45681599e+144 -1.45681599e+144]
 [-1.45681599e+144 -1.45681599e+144  6.32404027e-322]]
00 - Bug numpy.core numpy.ufunc

التعليق الأكثر فائدة

آه ، الأمر بسيط للغاية:

diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 19876d641..85820e3a0 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -2614,7 +2614,7 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
      * dimensions.
      */
     broadcast_ndim = 0;
-    for (i = 0; i < nin; ++i) {
+    for (i = 0; i < nop; ++i) {
         int n = PyArray_NDIM(op[i]) - op_core_num_dims[i];
         if (n > broadcast_ndim) {
             broadcast_ndim = n;

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

تحرير: بالإضافة إلى الاختيار الفارغ للعملية ...

ال 5 كومينتر

Hehe ، كان يفكر في هذا لفترة من الوقت .... أيضًا pingmhvk فقط في حالة.

يبدو أن العلامة NPY_ITER_NO_BROADCAST ، بشكل غريب بما فيه الكفاية ، تُستخدم دائمًا تقريبًا بطريقة يمكنك من خلالها ببساطة إخراج هذا المعامل بالكامل لاكتشاف الشكل (مثل مرجع الإخراج). ولكن ، سيكون انقطاعًا غير متوافق إذا استخدمناه فقط لمعالجة هذه المشكلة.

لذلك أنا أفكر في إضافة NPY_ITER_OUTPUT_OPERAND . أو أنشئ علامة NPY_ITER_OUTPUT_OPERAND وعلامة أخرى NPY_ITER_DOES_NOT_AFFECT_SHAPE بحيث يمكن أن تتضمن علامة معامل الإخراج كلاً من علامتي "التخصيص" و "عدم البث".

يبدو الأمر وكأنه مزيج من التخصيص وعدم البث ، وربما يعني ذلك إلى حد ما بالفعل. لكن السؤال هو ما إذا كنا نريد إجراء مثل هذا التغيير ، فمن الناحية النظرية يمكن أن يؤثر على المكتبات الخارجية باستخدام NpyIter. (ما لم نجعله إهمالًا مرئيًا ، تحذير عندما يبدأ ، لكن لست متأكدًا من أنه رائع للغاية في التنفيذ.)

أعتقد أن هذا يمكن أن يعالج المشكلة. هناك حالات جانبية مثيرة للاهتمام ، مثل المحاور التي يتم استخدامها فقط بواسطة مصفوفة إخراج واحدة (أو أكثر). يمكن للمرء أن يحاول دعم ذلك (في مرحلة ما؟) ، لكنه ربما يضيف الكثير من التعقيد دون تحقيق مكاسب حقيقية.
أنا ببساطة لا أرى الكثير من حالات الاستخدام لـ gufunc (),()->(k) . شيء مثل ليس (),()->(3,3) أو ->(3,3) منطقي بالطبع ، لكن ليس مشكلة.

مرتبك قليلاً حول جميع الأعلام ، يجب أن أعترف. لكن يمكن لـ gufunc moments بتوقيع ()->(k) أن يحسب لحظات تصل إلى k في المخرجات. بالطبع ، بعيد المنال بشكل لا يصدق ، لكن إحساسي لن أقوم باستبعاده صراحة (أو رمزًا للسماح به صراحة!).

الأمر الأكثر صلة بشكل مباشر بالمشكلة هنا ، حيث يكون للإخراج شكل خارجي غير متناسق ، هو أن هناك سابقة من ufuncs العادية:

np.add(1, 1, out=np.empty((3,)))
# array([2., 2., 2.])

هذا يشير أيضًا إلى Gufuncs ، يجب تحديد الشكل الخارجي من جميع المدخلات والمخرجات. من الواضح أنها ستسبب حسابات لا داعي لها ، ولكن فليكن ...

أوه ، بطريقة ما لم أكن أتوقع أن يعمل ذلك بالفعل. أفترض في هذه الحالة أنه يمكننا ببساطة السماح للإخراج بالتسبب في البث في المدخلات (وبالتالي ضبط الشكل). ببساطة الاحتفاظ بالسلوك الحالي.

لذلك ، لا تفعل شيئًا هنا ، باستثناء التأكد من استدعاء (g) ufunc عدة مرات (ستكون طريقة بطيئة بعض الشيء للحصول على النتيجة في كثير من الحالات ، ولكن هذه هي مشكلة المتصلين). على الرغم من أنني لا أعتقد أنه من المهم دعم هذا ، إلا أنني لا أرى أي مشاكل في القيام بذلك.

لكن من الواضح أننا ما زلنا بحاجة إلى إصلاح هذه المشكلة في Gufuncs!

آه ، الأمر بسيط للغاية:

diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 19876d641..85820e3a0 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -2614,7 +2614,7 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
      * dimensions.
      */
     broadcast_ndim = 0;
-    for (i = 0; i < nin; ++i) {
+    for (i = 0; i < nop; ++i) {
         int n = PyArray_NDIM(op[i]) - op_core_num_dims[i];
         if (n > broadcast_ndim) {
             broadcast_ndim = n;

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

تحرير: بالإضافة إلى الاختيار الفارغ للعملية ...

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات