Numpy: ENH: بديل لـ "random.shuffle" ، باستخدام وسيطة "المحور".

تم إنشاؤها على ١١ أكتوبر ٢٠١٤  ·  35تعليقات  ·  مصدر: numpy/numpy

سيكون من الجيد أن يكون لديك بديل لـ numpy.random.shuffle يقبل وسيطة axis ، وهذا يخلط الشرائح أحادية البعد بشكل مستقل. إليك تطبيق سأسميه disarrange . إنه يعمل ، ولكن سيكون من الجيد أن يكون لديك تطبيق C أكثر كفاءة.

def disarrange(a, axis=-1):
    """
    Shuffle `a` in-place along the given axis.

    Apply numpy.random.shuffle to the given axis of `a`.
    Each one-dimensional slice is shuffled independently.
    """
    b = a.swapaxes(axis, -1)
    # Shuffle `b` in-place along the last axis.  `b` is a view of `a`,
    # so `a` is shuffled in place, too.
    shp = b.shape[:-1]
    for ndx in np.ndindex(shp):
        np.random.shuffle(b[ndx])
    return

مثال:

In [156]: a = np.arange(20).reshape(4,5)

In [157]: a
Out[157]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])

In [158]: disarrange(a, axis=-1)

In [159]: a
Out[159]: 
array([[ 2,  0,  4,  3,  1],
       [ 8,  6,  7,  9,  5],
       [11, 14, 13, 10, 12],
       [19, 18, 16, 17, 15]])

In [160]: a = np.arange(20).reshape(4,5)

In [161]: disarrange(a, axis=0)

In [162]: a
Out[162]: 
array([[ 5, 11,  7, 13, 14],
       [ 0,  6,  2,  3,  4],
       [10,  1, 17, 18, 19],
       [15, 16, 12,  8,  9]])

كان هذا الطلب مدفوعًا بهذا السؤال حول تدفق المكدس: http://stackoverflow.com/questions/26310346/quickly-calculate-randomized-3d-numpy-array-from-2d-numpy-array/

01 - Enhancement numpy.random

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

أي أخبار عن هذا؟ لقد فوجئت بعدم وجود هذه الوظيفة. في الوقت الحالي ، أستخدم np.apply_along_axis مع np.random.permutation كحل بديل.

ال 35 كومينتر

لا ترى لماذا يجب أن يكون هذا بديلاً - لماذا لا تضيف فقط امتداد
حجة المحور لخلط؟ التقصير إلى لا شيء ، مثل np.sum.

يوم السبت 11 أكتوبر 2014 الساعة 9:36 مساءً ، Warren Weckesser [email protected]
كتب:

سيكون من الجيد أن يكون لديك بديل لـ numpy.random.shuffle
يقبل وسيطة المحور ، وهذا يخلط بشكل مستقل
شرائح أحادية البعد. إليك تطبيق سأسميه غير مرتبك.
إنه يعمل ، ولكن سيكون من الجيد أن يكون لديك تطبيق C أكثر كفاءة.

تعطيل def (أ ، المحور = -1):
""
تبديل a في المكان على طول المحور المحدد.

Apply numpy.random.shuffle to the given axis of `a`.
Each one-dimensional slice is shuffled independently.
"""
b = a.swapaxes(axis, -1)
# Shuffle `b` in-place along the last axis.  `b` is a view of `a`,
# so `a` is shuffled in place, too.
shp = b.shape[:-1]
for ndx in np.ndindex(shp):
    np.random.shuffle(b[ndx])
return

مثال:

في [156]: a = np.arange (20) .reshape (4،5)

في [157]: أ
الخارج [157]:
مجموعة ([0 ، 1 ، 2 ، 3 ، 4] ،
[5 ، 6 ، 7 ، 8 ، 9] ،
[10 ، 11 ، 12 ، 13 ، 14] ،
[15 ، 16 ، 17 ، 18 ، 19]])

في [158]: عدم الترتيب (أ ، المحور = -1)

في [159]: أ
الخارج [159]:
مجموعة ([2 ، 0 ، 4 ، 3 ، 1] ،
[8 ، 6 ، 7 ، 9 ، 5] ،
[11 ، 14 ، 13 ، 10 ، 12] ،
[19 ، 18 ، 16 ، 17 ، 15]])

في [160]: a = np.arange (20) .reshape (4،5)

في [161]: عدم الترتيب (أ ، المحور = 0)

في [162]: أ
الخارج [162]:
مجموعة ([[5 ، 11 ، 7 ، 13 ، 14] ،
[0 ، 6 ، 2 ، 3 ، 4] ،
[10 ، 1 ، 17 ، 18 ، 19] ،
[15 ، 16 ، 12 ، 8 ، 9]])

كان هذا الطلب مدفوعًا بهذا السؤال حول Stackoverflow:
http://stackoverflow.com/questions/26310346/quickly-calculate-randomized-3d-numpy-array-from-2d-numpy-array/

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/numpy/numpy/issues/5173.

ناثانيال ج. سميث
باحث ما بعد الدكتوراه - المعلوماتية - جامعة ادنبره
http://vorpus.org

السلوك الحالي لـ shuffle ليس مثل axis=None . يتعامل مع حجته على أنها تسلسل أحادي البعد.

In [181]: a = np.arange(20).reshape(4,5)

In [182]: np.random.shuffle(a)

In [183]: a
Out[183]: 
array([[ 0,  1,  2,  3,  4],
       [15, 16, 17, 18, 19],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])

يمكنك تفسير ذلك على أنه axis=0 ، لكن الميزة المفقودة هي الخلط المستقل للشرائح أحادية الأبعاد.

بالنسبة إلى مصفوفة ثنائية الأبعاد ، يمكنك تبديل a.T عشوائيًا لمحاكاة axis=1 ، لكن هذا لن يؤدي إلى خلط مستقل:

In [184]: a = np.arange(20).reshape(4,5)

In [185]: np.random.shuffle(a.T)

In [186]: a
Out[186]: 
array([[ 4,  1,  0,  3,  2],
       [ 9,  6,  5,  8,  7],
       [14, 11, 10, 13, 12],
       [19, 16, 15, 18, 17]])

في disarrange ، أتوقع أن يتصرف axis=None مثل np.random.shuffle(a.flat) .

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

ربما يمكن إضافة وسيطتين إلى shuffle : axis و independent (أو شيء من هذا القبيل). سيكون التوقيع الجديد:

def shuffle(a, independent=False, axis=0)

عندما يكون independent خطأ ، فإنه يتصرف مثل shuffle . عندما يكون True ، فإنه يتصرف مثل disarrange .

أوه ، آه ، لقد افترضت للتو أنها كانت أكثر اتساقًا مع نظيرها
وظائف مثل الفرز :- (. سيكون أجمل لو كان هذا النوع من
تمت كتابة خلط الشرائح مثل idx = arange (...) ؛ المراوغة (idx) ؛
multi_dim_array [معرف ، ...] ؛ لكن لم يسألني أحد :-)

أقوم بإجراء 1+ على إصدار عشوائي يحتوي على اصطلاحات استدعاء مطابقة
np.sort ، على الرغم من أنه كقاعدة يجب أن نتحقق من القائمة. قد يكون لديهم
اقتراحات حول قضايا مهمة مثل أفضل اسم أيضًا :-)

(ربما "التدافع"؟)

يوم السبت ، 11 تشرين الأول (أكتوبر) 2014 الساعة 10:31 مساءً ، Warren Weckesser < [email protected]

كتب:

السلوك الحالي للخلط العشوائي ليس في الحقيقة مثل المحور = لا شيء. يعامل
حجته كتسلسل أحادي البعد.

في [181]: a = np.arange (20) .reshape (4،5)

في [182]: np.random.shuffle (أ)

في [183]: أ
الخارج [183]:
مجموعة ([0 ، 1 ، 2 ، 3 ، 4] ،
[15 ، 16 ، 17 ، 18 ، 19] ،
[5 ، 6 ، 7 ، 8 ، 9] ،
[10 ، 11 ، 12 ، 13 ، 14]])

يمكنك تفسير ذلك على أنه محور = 0 ، لكن الميزة المفقودة هي
خلط مستقل للشرائح 1-D.

بالنسبة إلى صفيف ثنائي الأبعاد ، يمكنك تبديل aT لمحاكاة المحور = 1 ، لكن هذا لن يحدث
تحصل على خلط مستقل:

في [184]: a = np.arange (20) .reshape (4،5)

في [185]: np.random.shuffle (aT)

في [186]: أ
الخارج [186]:
مجموعة ([4 ، 1 ، 0 ، 3 ، 2] ،
[9 ، 6 ، 5 ، 8 ، 7] ،
[14 ، 11 ، 10 ، 13 ، 12] ،
[19 ، 16 ، 15 ، 18 ، 17]])

في حالة من الفوضى ، أتوقع أن يكون المحور = لا شيء يتصرف مثل
np.random.shuffle (مسطح).

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

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/numpy/numpy/issues/5173#issuecomment -58765220.

ناثانيال ج. سميث
باحث ما بعد الدكتوراه - المعلوماتية - جامعة ادنبره
http://vorpus.org

آه ، وصف السلوك المطلوب باعتباره تناظريًا لـ sort هو فكرة جيدة.

أوه ، آه ، لقد افترضت للتو أنها كانت أكثر اتساقًا مع الوظائف المماثلة مثل التصنيف

لقد فوجئت أيضًا ، وبناءً على التعليقات على سؤال stackoverflow ، فوجئ اثنان على الأقل من المستخدمين ذوي الخبرة. سأبدأ مناقشة على القائمة البريدية.

أعتقد أنه إذا كان المستخدم العادي يخطئ حاليًا ، فهذا يستحق
بذكر الخيار الآخر - يمكننا إضافة وسيطة للاختيار من بينها
السلوكين اللذين يبدأان في التقصير في السلوك الحالي ،
وفي مرحلة ما ، قم بتبديل الوضع الافتراضي بعد الكثير من التحذير من المستقبل والصراخ
لتحذير الناس. لكن هذا تحول قبيح للقيام ...

يوم السبت 11 تشرين الأول (أكتوبر) 2014 الساعة 11:00 مساءً ، Warren Weckesser < [email protected]

كتب:

أوه ، آه ، لقد افترضت للتو أنها كانت أكثر اتساقًا مع نظيرها
وظائف مثل الفرز

لقد فوجئت أيضًا ، وبناءً على التعليقات على نظام Stackoverflow
سؤال ، فوجئ اثنان على الأقل من المستخدمين الآخرين ذوي الخبرة. مريض
بدء مناقشة على القائمة البريدية.

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/numpy/numpy/issues/5173#issuecomment -58766099.

ناثانيال ج. سميث
باحث ما بعد الدكتوراه - المعلوماتية - جامعة ادنبره
http://vorpus.org

قد يكون لديهم اقتراحات بشأن قضايا مهمة مثل أفضل اسم أيضًا.

نحتاج إلى وظيفة تسمى سو.

أردت فقط إجراء 1+ لهذه الميزة ، كما كنت أتوقع وجودها ، بشكل مماثل للفرز (المحور = N). هل تم اتخاذ أي قرار بشأن القائمة البريدية؟

موضوع القائمة البريدية موجود هنا:
http://thread.gmane.org/gmane.comp.python.numeric.general/59014

سيكون هذا مفيدا حقا!

كما أنني أقدر ذلك!

وفقًا لـ https://stackoverflow.com/a/35647011/3401634 ، للمصفوفات متعددة الأبعاد X

np.random.shuffle(X)

بالضبط مثل

np.take(X, np.random.permutation(X.shape[0]), axis=0, out=X)

فلماذا لا تنفذ

np.random.shuffle(X, axis=axis)

كما

np.take(X, np.random.permutation(X.shape[axis]), axis=axis, out=X)

باستخدام الافتراضي axis=0 ؟

أي أخبار عن هذا؟ لقد فوجئت بعدم وجود هذه الوظيفة. في الوقت الحالي ، أستخدم np.apply_along_axis مع np.random.permutation كحل بديل.

هل يمكن إغلاق هذا الآن بسبب # 13829؟

(لاحظ أنه أثناء العمل على الأمثلة هنا ، وجدت خطأ في التعليمات البرمجية العشوائية الجديدة. في ما يلي ، أستخدم الإصلاح المقترح في https://github.com/numpy/numpy/pull/14662 ، والذي تم مدمجة.)

wkschwartz ، التغيير في # 13829 مفيد ، لكنه ليس التحسين المطلوب هنا. لا يزال المحور المضاف في # 13829 يتعامل مع المصفوفة على أنها تسلسل أحادي الأبعاد ليتم تبديله عشوائيًا. تسمح وسيطة المحور الجديدة للمستخدم بتحديد المحور الذي يتم عرضه على أنه المحور أحادي الأبعاد ، ولكنه لا يقوم بتبديل عشوائي داخل المحور.

فمثلا،

In [1]: import numpy as np                                                      

In [2]: rng = np.random.default_rng()                                           

In [3]: x = np.arange(20).reshape(2, 10)                                        

In [4]: x                                                                       
Out[4]: 
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])

In [5]: rng.shuffle(x, axis=1)                                                  

In [6]: x                                                                       
Out[6]: 
array([[ 5,  9,  6,  4,  7,  0,  3,  2,  1,  8],
       [15, 19, 16, 14, 17, 10, 13, 12, 11, 18]])

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

السلوك المطلوب في هذه المشكلة هو الترتيب العشوائي بشكل مستقل ، كما في الكود disarrange الذي قدمته أعلاه:

In [10]: x = np.arange(20).reshape(2, 10)                                       

In [11]: x                                                                      
Out[11]: 
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])

In [12]: disarrange(x, axis=1)                                                  

In [13]: x                                                                      
Out[13]: 
array([[ 4,  3,  7,  8,  0,  6,  5,  2,  9,  1],
       [12, 15, 19, 17, 18, 14, 10, 13, 11, 16]])

أود أن أطفو هذا مرة أخرى ، ربما أيضًا في اجتماع الأربعاء. لقد أضفنا للتو إمكانات أبعاد أعلى إلى choice و permutation وفي 1.18 حتى وسيطة المحور (وبالتالي فهي علامة تجارية جديدة).

كل هؤلاء يستخدمون منطق خلط ورق اللعب الحالي وهو shuffle the subarrays along this axis ، بدلاً من shuffle along (individual) axis والذي أعتقد أنه يمكن القول إنه ما يجب أن يحدث. أي أنه يتنقل "فوق" بدلاً من "على طول" أو داخل المحور المحدد.

ولكن ، في جميع المناسبات تقريبًا ، يعني axis على طول المحور في NumPy ، مع وجود استثناءات قليلة جدًا ، مثل apply_over_axes الذي يحتوي على "over" في الاسم. لذلك سأكون جريئًا وأدعي أنه حتى إعادة تسمية الوسيطة إلى over_axis=0 سيكون من الأفضل تجنب الالتباس! خاصة بالنسبة للأرقام العشوائية حيث قد يكون من الصعب جدًا ملاحظة الخلط غير الصحيح.

كما هو مذكور في مرجع github الترافقي أعلاه ، لديّ علاقات عامة قيد العمل على https://github.com/numpy/numpy/pull/15121. لقد تلقيت بعض التعليقات الجيدة بعد تقديم العرض العام ، لكنني لم أخصص وقتًا لمعالجة جميع المشكلات التي أثيرت.

WarrenWeckesser هذا رائع ، ما أشعر بقلق أكثر إلحاحًا بشأنه شخصيًا هو أننا قمنا بتوسيع المعنى الزائد في واجهة برمجة التطبيقات الجديدة ومؤخرًا في ذلك.
وأنا أتساءل عما إذا كان يجب ألا نتراجع عن ذلك جزئيًا ، على سبيل المثال بإعادة تسمية الوسيطة axis على الأقل. أو حتى التخلص من السلوك متعدد الأبعاد تمامًا مرة أخرى في الوقت الحالي ...

ربما أبالغ في رد فعلي الآن ، لأنني منزعج قليلاً لأنني فاتني هذا أو لم أفكر في ذلك حتى النهاية من قبل ... لكنني بصراحة أعتقد أن المنطق الحالي خطير للغاية. من السهل أن نفوت أنه لا يوفر المعنى الكامل المتوقع. وهذا ليس المعنى الذي يستخدمه np.sort .

seberg ، شكرًا لك على بحث هذه المشكلة. أعتقد أننا ما زلنا بحاجة إلى التوصل إلى توافق في الآراء بشأن API. سأحاول تقديم ملخص موجز للأفكار السابقة هنا. سأتبع تقليدك في استخدام "over" و "along" لتفسيراتين لـ axis . لا أعرف ما إذا كان بإمكاننا ، في هذه المرحلة ، التراجع تمامًا عن التفسير "الطويل" الحالي لـ axis لـ shuffle و permutation ، لكن أعتقد أن الكثير من الناس سنكون سعداء إذا اتضح أننا نستطيع. :)

في نهاية مناقشة القائمة البريدية منذ عدة سنوات ، انتهى بي الأمر إلى التفكير في أن الحل هو عدم تغيير واجهات برمجة التطبيقات لـ shuffle و permutation ، وبدلاً من ذلك أدخل طريقتين جديدتين عشوائيتين على طول المحور بدلا من تجاوزها. ستعمل إحدى الطرق في مكانها ، بينما تعيد الطريقة الأخرى نسخة. كان تفضيلي في ذلك الوقت هو الأسماء permute و permuted ، لكن كانت هناك بعض الاعتراضات على هذه الأسماء. في العلاقات العامة من ديسمبر الماضي ، اتصلت بهم randomly_permute و randomly_permuted ، لكن يجب اعتبار هذه الأسماء أسماء نائبة. قبل محاولة اتخاذ قرار بشأن هذه الأسماء ، علينا أن نقرر ما إذا كانت إضافة وظيفتين جديدتين هي الطريقة الصحيحة. من الآن فصاعدًا ، للإيجاز ، سأشير إلى الطرق الجديدة المقترحة كـ permute و permuted .

باستخدام الوظائف الجديدة ، سيكون لدينا طرق Generator التالية ذات الصلة:

meaning    operate     return
of axis    in-place     copy
-------    --------  -----------
"over"     shuffle   permutation
"along"    permute   permuted

(الطرق التي تعمل "فوق" المحور ، shuffle و permutation ، موجودة بالفعل.)

بدلاً من طريقتين جديدتين ، تم اقتراح أن لدينا طريقة واحدة فقط ، مع معلمة تتحكم في السلوك الموضعي مقابل سلوك النسخ. تم طرح اقتراحين لهذا:

(أ) أضف معلمة out . للعمل في نفس المكان ، قم بتمرير مصفوفة الإدخال كـ out . إذا لم يتم توفير out ، فقم بإرجاع نسخة مختلطة.
(ب) أضف علامة منطقية مثل copy أو inplace ، والتي تحدد السلوك المطلوب.

البديل الرئيسي لإنشاء طرق جديدة هو إضافة معامل جديد إلى الطرق الحالية التي تغير كيفية تفسير axis . قبل إدراجها ، سأكرر تعليقًا أدلى به روبرت كيرن في سلسلة الرسائل البريدية حول كيفية استخدام الوسيطة الإضافية في الممارسة العملية (هنا بالإشارة إلى المعلمة independent الموضحة أدناه):

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

( الاستطراد التحريري : حتماً في مناقشة مثل هذه ، تظهر مسألة زيادة مساحة الاسم (في هذه الحالة ، مساحة الاسم Generator ) (يشار إليها أحيانًا باسم "تلوث مساحة الاسم"). دعنا نتفق على ذلك ، نعم ، الكل عند تساوي الأشياء ، يكون مساحة الاسم الأصغر أفضل. ولكن ، مثل معظم قرارات تصميم واجهة برمجة التطبيقات ، هناك مقايضات يجب مراعاتها. إذا أبقينا مساحة الاسم أصغر ولكن أنشأنا طرقًا باستخدام واجهات برمجة تطبيقات محرجة أو معقدة للغاية ، فلن نربح.)

بعد قولي هذا كله ، إليك إضافتان إلى التوقيع الحالي shuffle التي تم اقتراحها.

(1) shuffle(x, axis=0, independent=False) : العلم المنطقي independent يحدد كيف يتم تفسير axis : False -> "over"، True -> "along". (ربما توجد أسماء أفضل من independent .)
(2) shuffle(x, axis=0, iaxis=???) : الوسيطة الثانية ، iaxis ، تعطي محور السلوك "على طول". (كيف يتفاعل هذا مع axis يحتاج إلى مواصفات واضحة. من المفترض أن يؤدي إعطاء قيمة iaxis axis إلى تجاهل

أعتقد أنني غطيت جميع أفكار API المختلفة التي ظهرت. إذا كان أي شخص يعرف الآخرين ، فأخبرنا بذلك.

أنا سعيد بزيادة API هنا. لست متأكدًا من وجود أسباب كثيرة لأعارضها:

  • ربما يمكننا أن نتفق على أنه مفيد
  • لا توجد طريقة جيدة لتحقيق ذلك باستخدام الميزات الموجودة
  • يبدو أن استخدام kwarg لتبديل السلوك الإجمالي ليس نمطًا عاديًا ، أعتقد أن Rober Kern كان هناك تمامًا.

أفترض أن ما يحدث هنا هو أنه يمكن مقارنة shuffle و permutation (وربما choice ) بعمليات الفهرسة (أي take ) ، والتي يستخدم نفس المعنى لـ axis . والسبب الذي يجعلني أشعر بغرابة بعض الشيء ، ربما يكون الجانب السلبي لهذا التعريف أنه لا يمكن أبدًا تعميمه على ND على عكس وظائف إدراك الصفيف النموذجية (حتى الفهرسة نفسها تفعل إذا كنت تستخدم arr[..., index] . هذا هو كل شيء التعميم على حزم المصفوفات والقيام بنفس العملية كما في السابق لكل واحد على حدة).
لاحظ أن take_along_axis يوفر المعنى ND القابل للتعميم "على طول" لـ take إلى ND بشكل صحيح (حتى لو بدا معقدًا). apply_along_axis و apply_over_axis هما المكان الذي حصلت فيه على "over" ، على الرغم من أنني لست متأكدًا من أن "over" هي الكلمة الصحيحة ...

أجد أن permutation (والذي لا يمكن تغييره بسهولة ولكن يجب أن يكون shuffled ) ليكون الخارج الحقيقي هنا. لقد كان shuffle - shuffled ، permute - permuted ثم أعتقد أن الأمور بدأت تبدو واضحة جدًا ومعقولة. أي شخص يرغب في إضافة shuffled وبدء إهمال على permutation ؟ permutation أيضًا ليس ثابتًا جدًا في سلوكه مع itertools.permutations ، FWIW.

أعتقد أن permutation ، permute ، permuted عبارة عن ثلاثية مربكة من الأسماء المتشابهة ذات السلوكيات المختلفة. سيكون من الجيد (ربما على المدى الطويل) تجنب ذلك.

بينما يبدو من السهل توسيع واجهة برمجة التطبيقات الحالية ، أعتقد أن نقطة rkern حول عدم وجود كلمات رئيسية تغير السلوك بشكل جذري هي أفضل مسار.

أفترض أنه بالنسبة إلى التهجئة الموضعية في مقابل عدم التواجد في المكان ، فلدينا البديل out= في الهجاء NumPy. ولكن نظرًا لأن الخلط في مكانه ، فهذا ليس حلاً وخلطًا أمرًا رائعًا. يمكن أن يكون لـ permuted (على سبيل المثال ، يعني permuted(arr, out=arr) نفس الشيء مثل permute(arr) ، باستثناء - على عكس التبديل العشوائي - سيتم التحويل إلى ndarray ).
على أي حال ، أحب خطة إهمال permutation لصالح shuffled لتنظيف مساحة الاسم الجديدة!

أعود إلى هذه المشكلة (والعلاقات العامة ذات الصلة على https://github.com/numpy/numpy/pull/15121).

عندما قمت بإنشاء الإصدار الأصلي ، وحاولت وصف المشكلة في واجهة برمجة التطبيقات الحالية shuffle API ، تمت الإشارة إلى أن إحدى طرق شرح المشكلة هي أن معظم الناس يتوقعون الوسيطة axis من shuffle للعمل بنفس طريقة axis وسيطة sort . إن القياس مع sort جيد جدًا ، لذلك قد يكون من المفيد أيضًا النظر في كيفية تعاملنا مع مسألة العملية الموضعية مقابل النسخ من أجل الفرز. تقبل الدالة numpy.sort() وسيطة تشبه المصفوفة وتقوم بإرجاع نسخة مرتبة. بالنسبة إلى الفرز الموضعي ، يستخدم المرء طريقة يجب أن تكون وسيطة الدالة الموضعية التي تتناوب مع وسيطتها بشكل عشوائي عبارة عن مصفوفة ndarray وليست شبيهة بمصفوفة عشوائية. بخلاف ذلك ، سيتعين على الوظيفة القيام بكل اكتشافات الأشكال التي يقوم بها np.array ، وكذلك رفض المدخلات التي تبين أنها غير قابلة للتغيير (على سبيل المثال ، لا يمكننا إجراء تبديل موضعي [(1, 2, 3, 4), (5, 6, 7, 8)] ).

سيكون أمرا رائعا لو تمكنا من تكرار حقا sort API، مع وظيفة أن عوائد نسخة تعديلا، و ndarray الأسلوب الذي المراوغات في نفس المكان، لكنني لا أعتقد مضيفا مثل أي طريقة لفئة ndarray لديها أي فرصة لقبولها.

و ndarray _method_ الذي يتم تبديله في نفس المكان ، لكن لا أعتقد أن إضافة مثل هذه الطريقة إلى فئة ndarray لديها أي فرصة لقبولها.

بدون مولد أحادي أعتقد أنه سيكون من المستحيل تحقيق ذلك.

bashtage كتب

أجد أن permutation (والذي لا يمكن تغييره بسهولة ولكن يجب أن يكون shuffled ) ليكون الخارج الحقيقي هنا. [إذا كان] كان shuffle-shuffled ، permute-permuted إذن أعتقد أن الأمور بدأت تبدو واضحة جدًا ومعقولة. أي شخص يرغب في إضافة shuffled وبدء إهمال على permutation ؟

هذا ما تلاقت مناقشة القائمة البريدية (نوعًا ما) للعودة إليه في عام 2014. إليك رابطًا لاقتراح ناثانييلز: https://mail.python.org/pipermail/numpy-discussion/2014-October/071364.html

scramble[d] هو ما أسميته randomly_permute[d] في https://github.com/numpy/numpy/pull/15121.

إذا أضفنا shuffled كبديل لـ permutation ، واستدعينا الطرق الجديدة التي تعمل على طول المحور permute[d] ، فإن جدول الوظائف ذات الصلة هو

meaning    operate
of axis    in-place   return copy
-------    ---------  -----------
"over"     shuffle    shuffled
"along"    permute    permuted

الذي لديه تناسق لطيف. في هذا الإصدار من API ، لا تحتوي أي من الطرق على معلمة out .

في https://github.com/numpy/numpy/pull/15121 ، أضفت مؤخرًا طريقة أخرى ، مع الاسم المؤقت الواضح وغير المألوف permuted_with_out الذي يوضح كيف يمكن أن تكون الوسيطة out تستخدم. إذا استخدمنا المعلمة out ، والتزمنا بأسماء الطرق الحالية shuffle و permutation ، يبدو الجدول مثل

meaning    operate
of axis    in-place                           return copy
-------    ---------------------------------  --------------------
"over"     shuffle(x, axis)                   permutation(x, axis)
"along"    permuted_with_out(x, axis, out=x)  permuted_with_out(x, axis)

ولكن إذا كنا سنقدم معلمة out ، فيجب أن نكون متسقين ونستخدمها في permutation أيضًا. ولا يزال بإمكاننا التفكير في استبدال permutation بـ shuffled . ونظرًا لأن طريقة shuffled تحتوي على معلمة out ، والتي تسمح بالتشغيل الموضعي ، يصبح shuffle زائداً عن الحاجة ويمكن إهماله مع permutation . بعد ذلك ، بالتبديل إلى الأسماء "الجميلة" وهي shuffled و permuted ، يكون الجدول

    meaning    operate
    of axis    in-place                  return copy
    -------    ------------------------  -----------------
    "over"     shuffled(x, axis, out=x)  shuffled(x, axis)
    "along"    permuted(x, axis, out=x)  permuted(x, axis)

لاحظ أن المعلمة out ليست فقط للتشغيل في نفس المكان. يسمح بإعادة استخدام مصفوفة الإخراج ، مما قد يؤدي إلى تجنب إنشاء مصفوفة مؤقتة. هذه ميزة لواجهة برمجة التطبيقات هذه على واجهة برمجة تطبيقات shuffle/shuffled/permute/permuted ، لكنني لست متأكدًا من مدى أهمية هذه الميزة حقًا. وعيب هذا API هو انتقاص من طريقتين، shuffle و permutation . يمكن أن تكون هذه عمليات إهمال "ناعمة" لبعض الوقت (على سبيل المثال ، قم بإلغاء التأكيد على استخدامها في المستندات ، ولكن لا تضيف في الواقع تحذيرًا بالإيقاف لفترة من الوقت) لتقليل التأثير الفوري.

هذا هو ملخصي للمتنافسين الرئيسيين للتغيير. لدينا الإصدار shuffle/shuffled/permute/permuted ، أو الإصدار الذي يحتوي على shuffled/permuted مع المعلمة out . إذا ، في عام 2014 ، قفز شخص ما لتنفيذ التغييرات التي تمت مناقشتها ، فمن المحتمل أن يكون لدينا الإصدار shuffle/shuffled/permute/permuted بالفعل. لكن الإصدار الذي يستخدم out له مزايا (صغيرة؟ غير مهمة؟): اسمان بدلاً من أربعة ، و out المحتمل أن يسمح للمستخدم بالحصول على متغيرات مؤقتة أقل. سأكون سعيدا مع أي منهما.

ماذا يعتقد الناس؟

من بين السيناريوهات الثلاثة التي قمت بإدراجها ، بالترتيب ، سأقوم بترتيبها 1 ، 3 ، وخلفها بعيدًا جدًا 2. يبدو أن التباديلان اللذان يقومان بأشياء مختلفة تمامًا يمثلان مصدرًا كبيرًا للارتباك. أفضّل شخصيًا هو تجنب الاستخدام الإلزامي للخارج للوصول إلى ميزة ؛ أفكر دائمًا في ذلك كخيار أداء يمكن أن يكون منطقيًا في بعض السيناريوهات. لا أرغب حقًا في تعليم الطلاب لاستخدامها فقط للوصول إلى ميزة. أفترض أيضًا أنه في حالة 3 x = shuffled(x, axis, out=x) سيكون أيضًا return x بدلاً من return None ، لذلك أثناء وجوده في مكانه ، قد ينتهي الأمر بـ x تظهر 3 مرات.

أفضّل شخصيًا هو تجنب الاستخدام الإلزامي للخارج للوصول إلى ميزة ؛ أفكر دائمًا في ذلك كخيار أداء يمكن أن يكون منطقيًا في بعض السيناريوهات.

لكن الخلط في المكان _ هو اختيار أداء ، أليس كذلك؟

لكن الخلط في المكان _ هو اختيار أداء ، أليس كذلك؟

يمكن أيضًا أن يكون الوضع الموضعي اختيارًا لنمط الترميز ، عند توفره. ربما يكون محيرًا ، وربما عرضة للخطأ.

رأيي الشخصي هو أنه عندما تكون f (x، out = x) دائمًا ما تشعر ببعض السحر لأنها تستخدم أحيانًا كطريقة غير واضحة لتحقيق شيء سريع. تبدو f (x، inplace = True) أكثر وضوحًا على الرغم من أنها لا تشبه أي شيء آخر (تشبه إلى حد ما نمط الباندا القديم الذي تمت إزالته في الغالب).

صحيح ، لكنه اختيار نمط ترميز يبدو أنه في NumPy يتم تهجئته عادةً باستخدام out=... (إلا إذا كنت تستخدم عامل تشغيل موضعي أو طريقة). أو ربما يكون اختيار أسلوب الترميز الذي لا تحاول NumPy تسهيله في معظم الحالات حاليًا ...

أعترف أنها سحرية بعض الشيء وقد تكون kwarg inplace= أقل سحرية ، ولكن أيضًا بدون أسبقية حقيقية؟ ولست متأكدًا مما إذا كان السبب الرئيسي الذي يجعل الأمر يبدو أقل سحرية هو أن التبديل الموضعي هو جوهر الخوارزمية هنا. لا ينبغي أن تهم تفاصيل الخوارزمية كثيرًا لمعظم الطلاب ، وفي النهاية ، فإن استخدام out= يخزن أيضًا نسخة واحدة تقريبًا + عرض النطاق الترددي للذاكرة المرتبطة ، ويمكن مقارنته بـ ufuncs. (مقبول بما يكفي ، بالنسبة إلى ufuncs out=input ربما يكون سحريًا إلى حد ما ، لكن سحره الشائع ونمطه المعروف - للمستخدمين المتقدمين.)

في حين أنه من الممكن أن تكون الكتابة مملة بعض الشيء ، وأقل سرعة في القراءة إلى حد ما ، إلا أن np.shuffled(x, out=x) يبدو واضحًا جدًا فيما يتعلق بسلوكك. يبدو أن الجزء غير الواضح هو تأثير الأداء فقط ، والذي يبدو لي وكأنه مشكلة مخصصة للمستخدمين المتقدمين للقلق بشأنها.

سؤال افتراضي لمن يدافعون عن استخدام out : إذا لم تكن لدينا الوظائف الحالية numpy.sort و ndarray.sort ، وكنا نضيف وظيفة الفرز الآن ، فهل سيكون واجهة برمجة التطبيقات المفضلة هي numpy.sorted(a, axis=-1, kind=None, order=None, out=None) (دون الحاجة إلى تنفيذ الطريقة ndarray.sort للفرز الموضعي)؟

ndarray.sort على غرار list.sort ، لذا فمن المحتمل أنه اختيار معقول لواجهة برمجة التطبيقات بغض النظر. ومع ذلك ، كنت سأؤيد np.sort غير موجود ، و np.sorted(..., out=...) بدلاً من ذلك.

نعم ، أعتقد أنه يجب تسمية np.sort np.sorted (تمامًا مثل python sorted() بعد كل شيء). نظرًا لأن الطريقة فقط لها السلوك الموضعي ، فلا أرى الكثير من القلق على الرغم من ذلك.

لست متأكدًا من "دون الحاجة إلى تنفيذ الطريقة ndarray.sort ". لا أرى أي خطأ في الطريقة (أو سلوكها الموضعي). السؤال حول الطريقة هو مجرد ما إذا كنا نشعر أنه مهم بما يكفي لتوفير طريقة مناسبة في متناول اليد.
أفترض أنه لا حرج أيضًا في وجود إصدار وظيفي موضعي. يبدو الإصدار غير الموجود في المكان أجمل للمستخدمين الجدد ونمط out= شائع بدرجة كافية بالنسبة لي بحيث يتم تقديم المستخدمين المتقدمين بشكل جيد.

لست متأكدًا من "دون الحاجة إلى تنفيذ الأسلوب ndarray.sort". لا أرى أي خطأ في الطريقة (أو سلوكها الموضعي).

كان ذلك جزءًا من تجربتي الفكرية في API. لم أقصد الإيحاء بأنه لا يوجد أي خطأ فيما لدينا الآن. كنت أقول ذلك فقط ، إذا بدأنا من الصفر - وسأضيف إلى مقدماتي الافتراضية أننا لسنا معنيين بمطابقة Python API للقوائم - فإن واجهة برمجة التطبيقات المفضلة للفرز ستكون numpy.sorted(..., out=...) ، ولن نحتاج إلى أي شيء آخر.

سؤال آخر ، ليس افتراضيًا: إذا كان استخدام out هو الخيار المفضل هنا ، إذن ، من أجل تناسق API عبر NumPy ، هل يجب أن نخطط لإضافة out إلى numpy.sort ، numpy.partition في النهاية numpy.argsort ، حسنًا ، كل شيء آخر لا يتوفر به حاليًا؟

نعم ، في رأيي ، فإن إضافة out= kwarg بنفس دلالات ufuncs يعد اختيارًا جيدًا لجميع وظائف NumPy API عمليًا. أي نقص في الوسيطة out بشكل عام هو تحسين ينتظر إجراؤه (على الرغم من أنني أعتقد أنه من الناحية العملية قد يكون تحسينًا صغيرًا وفي حالات نادرة ربما لا يستحق الكثير من التعقيد الإضافي للكود).

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