2 ডি অ্যারেতে তির্যক প্রতি সর্বাধিক মান


9

আমার অ্যারে রয়েছে এবং ডায়নামিক উইন্ডোতে সর্বাধিক ঘূর্ণায়মান পার্থক্য দরকার।

a = np.array([8, 18, 5,15,12])
print (a)
[ 8 18  5 15 12]

তাই প্রথমে আমি নিজেই পার্থক্য তৈরি করেছি:

b = a - a[:, None]
print (b)
[[  0  10  -3   7   4]
 [-10   0 -13  -3  -6]
 [  3  13   0  10   7]
 [ -7   3 -10   0  -3]
 [ -4   6  -7   3   0]]

তারপরে উপরের ত্রিভুজ ম্যাট্রিক্সকে 0 এ প্রতিস্থাপন করুন:

c = np.tril(b)
print (c)
[[  0   0   0   0   0]
 [-10   0   0   0   0]
 [  3  13   0   0   0]
 [ -7   3 -10   0   0]
 [ -4   6  -7   3   0]]

সর্বশেষে তির্যক প্রতি সর্বাধিক মান প্রয়োজন, সুতরাং এর অর্থ:

max([0,0,0,0,0]) = 0  
max([-10,13,-10,3]) = 13
max([3,3,-7]) = 3
max([-7,6]) = 6
max([-4]) = -4

সুতরাং প্রত্যাশিত আউটপুট:

[0, 13, 3, 6, -4]

কিছু ভাল ভেক্টরাইজড সমাধান কি? বা প্রত্যাশিত আউটপুট জন্য অন্য কোন উপায় সম্ভব?

উত্তর:


3

জড়িত অ্যাডভান্সিংকে বিবেচনা করার ক্ষেত্রে এটি ঠিক কতটা দক্ষ তা নিশ্চিত নয়, তবে এটি করার একটি উপায় এটি:

import numpy as np

a = np.array([8, 18, 5, 15, 12])
b = a[:, None] - a
# Fill lower triangle with largest negative
b[np.tril_indices(len(a))] = np.iinfo(b.dtype).min  # np.finfo for float
# Put diagonals as rows
s = b.strides[1]
diags = np.ndarray((len(a) - 1, len(a) - 1), b.dtype, b, offset=s, strides=(s, (len(a) + 1) * s))
# Get maximum from each row and add initial zero
c = np.r_[0, diags.max(1)]
print(c)
# [ 0 13  3  6 -4]

সম্পাদনা করুন:

আরেকটি বিকল্প, যা আপনি যা খুঁজছিলেন তা নাও হতে পারে, কেবল নুমবা ব্যবহার করা হচ্ছে, উদাহরণস্বরূপ:

import numpy as np
import numba as nb

def max_window_diffs_jdehesa(a):
    a = np.asarray(a)
    dtinf = np.iinfo(b.dtype) if np.issubdtype(b.dtype, np.integer) else np.finfo(b.dtype)
    out = np.full_like(a, dtinf.min)
    _pwise_diffs(a, out)
    return out

@nb.njit(parallel=True)
def _pwise_diffs(a, out):
    out[0] = 0
    for w in nb.prange(1, len(a)):
        for i in range(len(a) - w):
            out[w] = max(a[i] - a[i + w], out[w])

a = np.array([8, 18, 5, 15, 12])
print(max_window_diffs(a))
# [ 0 13  3  6 -4]

এই পদ্ধতিগুলির সাথে মূলের সাথে তুলনা করা:

import numpy as np
import numba as nb

def max_window_diffs_orig(a):
    a = np.asarray(a)
    b = a - a[:, None]
    out = np.zeros(len(a), b.dtype)
    out[-1] = b[-1, 0]
    for i in range(1, len(a) - 1):
        out[i] = np.diag(b, -i).max()
    return out

def max_window_diffs_jdehesa_np(a):
    a = np.asarray(a)
    b = a[:, None] - a
    dtinf = np.iinfo(b.dtype) if np.issubdtype(b.dtype, np.integer) else np.finfo(b.dtype)
    b[np.tril_indices(len(a))] = dtinf.min
    s = b.strides[1]
    diags = np.ndarray((len(a) - 1, len(a) - 1), b.dtype, b, offset=s, strides=(s, (len(a) + 1) * s))
    return np.concatenate([[0], diags.max(1)])

def max_window_diffs_jdehesa_nb(a):
    a = np.asarray(a)
    dtinf = np.iinfo(b.dtype) if np.issubdtype(b.dtype, np.integer) else np.finfo(b.dtype)
    out = np.full_like(a, dtinf.min)
    _pwise_diffs(a, out)
    return out

@nb.njit(parallel=True)
def _pwise_diffs(a, out):
    out[0] = 0
    for w in nb.prange(1, len(a)):
        for i in range(len(a) - w):
            out[w] = max(a[i] - a[i + w], out[w])

np.random.seed(0)
a = np.random.randint(0, 100, size=100)
r = max_window_diffs_orig(a)
print((max_window_diffs_jdehesa_np(a) == r).all())
# True
print((max_window_diffs_jdehesa_nb(a) == r).all())
# True

%timeit max_window_diffs_orig(a)
# 348 µs ± 986 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit max_window_diffs_jdehesa_np(a)
# 91.7 µs ± 1.3 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit max_window_diffs_jdehesa_nb(a)
# 19.7 µs ± 88.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

np.random.seed(0)
a = np.random.randint(0, 100, size=10000)
%timeit max_window_diffs_orig(a)
# 651 ms ± 26 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit max_window_diffs_jdehesa_np(a)
# 1.61 s ± 6.19 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit max_window_diffs_jdehesa_nb(a)
# 22 ms ± 967 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

প্রথমটি ছোট অ্যারেগুলির জন্য কিছুটা ভাল হতে পারে তবে বড়দের জন্য ভাল কাজ করে না। অন্যদিকে নুম্বা সব ক্ষেত্রেই বেশ ভাল।


আপনি কি উত্তর দেওয়ার জন্য কিছু সময় যুক্ত করতে পারেন, যেমন 10, 100, 1000 মানগুলিতে a?
jezrael

1
@ জেজরেল একটি সম্ভাব্য নুম্বা সমাধান এবং কিছু সময়ের ব্যবস্থা যুক্ত করেছে। আমার NumPy সমাধানটি সত্যিই ভাল স্কেল করে না, নুম্বা ভাল, যদিও এটি আপনার পক্ষে কার্যকর কিনা তা আমি নিশ্চিত নই।
jdehesa

4

ব্যবহার ndarray.diagonal

v = [max(c.diagonal(-i)) for i in range(b.shape[0])]
print(v) # [0, 13, 3, 6, -4]


1

এখানে একটি ভেক্টরাইজড সমাধান রয়েছে strides-

from skimage.util import view_as_windows

n = len(a)
z = np.zeros(n-1,dtype=a.dtype)
p = np.concatenate((a,z))

s = view_as_windows(p,n)
mask = np.tri(n,k=-1,dtype=bool)[:,::-1]
v = s[0]-s
out = np.where(mask,v.min()-1,v).max(1)

স্মৃতিশক্তি-দক্ষতার জন্য এক-লুপ সহ -

n = len(a)
out = [max(a[:-i+n]-a[i:]) for i in range(n)]

অ্যারে-মেমরির আরও ভাল ব্যবহারের জন্য np.maxজায়গায় ব্যবহার করুন max


1
@ জিজরেল আমার মনে হবে এমন ডেটা আকারে নির্ভর করে end বড় আকারের জন্য, আমি মনে করব স্মৃতি দক্ষতার কারণে স্লাইসিং + ম্যাক্স সহ লুপটি জিততে পারে।
দিবাকর

1

আপনি এই সত্যটি আপত্তিজনক ব্যবহার করতে পারেন যে আকারের অ-বর্গাকার অ্যারেগুলি পুনরায় আকার (N+1, N)দেওয়ার (N, N+1)ফলে তির্যকগুলি কলাম হিসাবে প্রদর্শিত হবে

from scipy.linalg import toeplitz
a = toeplitz([1,2,3,4], [1,4,3])
# array([[1, 4, 3],
#        [2, 1, 4],
#        [3, 2, 1],
#        [4, 3, 2]])
a.reshape(3, 4)
# array([[1, 4, 3, 2],
#        [1, 4, 3, 2],
#        [1, 4, 3, 2]])

যা আপনি এর পরে ব্যবহার করতে পারেন (মনে রাখবেন যে আমি সাইনটি সরিয়ে নিয়েছি এবং নীচের ত্রিভুজটি শূন্যে সেট করেছি)

smallv = -10000  # replace this with np.nan if you have floats

a = np.array([8, 18, 5,15,12])
b = a[:, None] - a

b[np.tril_indices(len(b), -1)] = smallv
d = np.vstack((b, np.full(len(b), smallv)))

d.reshape(len(d) - 1, -1).max(0)[:-1]
# array([ 0, 13,  3,  6, -4])
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.