নম্পপি-তে ন্যানের জন্য দ্রুত চেক করুন


120

আমি np.nanনুমপি অ্যারেতে এনএএন ( ) এর উপস্থিতি পরীক্ষা করার দ্রুততম উপায়টি সন্ধান করছিXnp.isnan(X)এটি প্রশ্নের বাইরে নয়, যেহেতু এটি একটি বুলিয়ান অ্যারের আকার তৈরি করে X.shape, যা সম্ভবত সম্ভাব্য।

আমি চেষ্টা করেছিলাম np.nan in X , তবে মনে হচ্ছে এটি কাজ করে না np.nan != np.nan। এটি আদৌ করার জন্য কি কোনও দ্রুত এবং মেমরির দক্ষ উপায় আছে?

(যারা "কীভাবে বিশাল" জিজ্ঞাসা করবেন তাদের কাছে: আমি বলতে পারি না This এটি লাইব্রেরি কোডের জন্য ইনপুট বৈধতা))


ব্যবহারকারীর ইনপুটটি বৈধ করা এই দৃশ্যে কাজ করে না? সন্নিবেশের আগে NaN এর জন্য যাচাই করা হয়েছে
Wood4Moo

@ Woot4Moo: না, গ্রন্থাগারটি NumPy অ্যারে বা scipy.sparseম্যাট্রিককে ইনপুট হিসাবে নেয় takes
ফ্রেড ফু

2
আপনি যদি এটি অনেক কিছু করে থাকেন তবে আমি বোতলেনেক ( পিপিপিপিথন.আর.পিপি / বোতলনেক ) সম্পর্কে ভাল জিনিস শুনেছি
ম্যাট

উত্তর:


160

রায় এর সমাধান ভাল। তবে কি আমার মেশিনে এটি 2.5x সম্পর্কে দ্রুত ব্যবহার করা numpy.sumস্থানেnumpy.min :

In [13]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 244 us per loop

In [14]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 97.3 us per loop

বিপরীতে min, sumশাখার প্রয়োজন হয় না, যা আধুনিক হার্ডওয়্যারটিতে বেশ ব্যয়বহুল হয়ে থাকে। এই কারণ সম্ভবত sumদ্রুত হয়।

সম্পাদনা করুন উপরের পরীক্ষাটি অ্যারের ঠিক মাঝখানে একক NaN দিয়ে সম্পাদিত হয়েছিল।

এটি মনে রাখা আকর্ষণীয় যে minতাদের অনুপস্থিতির চেয়ে NaN- এর উপস্থিতিতে ধীর than এটি এনএএনগুলি অ্যারের শুরুর কাছাকাছি আসায় ধীর হয়ে গেছে বলে মনে হয়। অন্যদিকে, sumএনএএন আছে এবং তারা কোথায় রয়েছে তা নির্বিশেষে এর থ্রুপুট স্থির মনে হয়:

In [40]: x = np.random.rand(100000)

In [41]: %timeit np.isnan(np.min(x))
10000 loops, best of 3: 153 us per loop

In [42]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.9 us per loop

In [43]: x[50000] = np.nan

In [44]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 239 us per loop

In [45]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.8 us per loop

In [46]: x[0] = np.nan

In [47]: %timeit np.isnan(np.min(x))
1000 loops, best of 3: 326 us per loop

In [48]: %timeit np.isnan(np.sum(x))
10000 loops, best of 3: 95.9 us per loop

1
np.minঅ্যারেতে কোনও NaN থাকে না এমনটি দ্রুত হয় এটি আমার প্রত্যাশিত ইনপুট। তবে আমি এটিকে যাইহোক গ্রহণ করার সিদ্ধান্ত নিয়েছি কারণ এটি ধরা পড়ে infএবং neginfপাশাপাশি।
ফ্রেড ফু

2
এটি কেবল ক্যাচ করে infবা ইনপুটটিতে -infউভয়ই থাকে এবং যদি ইনপুটটিতে বৃহত্তর তবে সীমাবদ্ধ মান থাকে যা একসাথে যুক্ত হওয়ার পরে ওভারফ্লো হয় it
ব্যবহারকারীর 2357112 মনিকা

4
মিনিট এবং ম্যাক্সের এসএস সক্ষম x86 চিপগুলিতে ভাসমান পয়েন্টের ডেটাগুলির জন্য ব্রাঞ্চ করার দরকার নেই। তাই নির্লিপ্ত হিসাবে 1.8 মিনিট যোগফলের চেয়ে ধীর হবে না, আমার এএমডি ফেনোমে এটি আরও 20% দ্রুত।
jtaylor

1
আমার ইনটেল কোর আই 5 এ, ওএসএক্সে ন্যালি 1.9.2 সহ, np.sumএখনও তুলনায় প্রায় 30% দ্রুত np.min
ম্যাথু ব্রেট

np.isnan(x).any(0)আমার মেশিনের থেকে np.sumএবং এর চেয়ে সামান্য দ্রুত np.min, যদিও সেখানে কিছু অযাচিত ক্যাশে থাকতে পারে।
jsignell

28

আমার মনে হয় np.isnan(np.min(X))আপনার যা করা উচিত তা করা উচিত।


হুমমম ... এটি সর্বদা ও (এন) থাকে যখন ও (1) হতে পারে (কিছু অ্যারের জন্য)।
ব্যবহারকারী 48956

17

এমনকি সেখানে একটি স্বীকৃত উত্তরও রয়েছে, আমি নিম্নলিখিতগুলি প্রদর্শন করতে চাই (পাইথন ২..2.২ এবং ভিস্তার উপর নম্পি ১.০.০ সহ):

In []: x= rand(1e5)
In []: %timeit isnan(x.min())
10000 loops, best of 3: 200 us per loop
In []: %timeit isnan(x.sum())
10000 loops, best of 3: 169 us per loop
In []: %timeit isnan(dot(x, x))
10000 loops, best of 3: 134 us per loop

In []: x[5e4]= NaN
In []: %timeit isnan(x.min())
100 loops, best of 3: 4.47 ms per loop
In []: %timeit isnan(x.sum())
100 loops, best of 3: 6.44 ms per loop
In []: %timeit isnan(dot(x, x))
10000 loops, best of 3: 138 us per loop

সুতরাং, প্রকৃতপক্ষে কার্যকর উপায় অপারেটিং সিস্টেমের উপর খুব বেশি নির্ভরশীল হতে পারে। যাইহোক dot(.)ভিত্তিক এটি সবচেয়ে স্থিতিশীল বলে মনে হচ্ছে।


1
আমি সন্দেহ করি এটি ওএসের উপর এতটা নির্ভর করে না, যেমন অন্তর্নিহিত বিএলএএস বাস্তবায়ন এবং সি সংকলক হিসাবে। ধন্যবাদ, তবে একটি বিন্দু পণ্য হ'ল কেবলমাত্র একটি টডের বেশি xপরিমাণে প্রবাহিত হওয়ার সম্ভাবনা থাকে যখন বড় মান থাকে এবং আমি ইনফের জন্যও পরীক্ষা করতে চাই।
ফ্রেড ফু

1
ঠিক আছে, আপনি সর্বদা একটি এবং ব্যবহার করে বিন্দু পণ্য করতে পারেন isfinite(.)। আমি কেবল বিশাল পারফরম্যান্সের ফাঁকটি চিহ্নিত করতে চেয়েছিলাম। ধন্যবাদ
খাওয়া

আমার মেশিনে একই।
কাওয়িং-চিউ

1
চতুর, না? ফ্রেড ফু যেমন পরামর্শ দিয়েছেন, ডট পণ্য ভিত্তিক পদ্ধতির কোনও দক্ষতা অর্জন এটি অবশ্যই আটলাস, এমকেএল বা ওপেনবিএলএসের মতো অপ্টিমাইজড বিএলএএস বাস্তবায়নের সাথে সংযুক্ত একটি স্থানীয় নম্পপি ইনস্টলেশনকে ধন্যবাদ জানায়। উদাহরণস্বরূপ এটি অ্যানাকোন্ডার ক্ষেত্রে। যে দেওয়া, এই বিন্দু পণ্য সমস্ত উপলব্ধ কোর জুড়ে সমান্তরাল করা হবে । - বা- ভিত্তিক পদ্ধতির জন্য একই কথা বলা যায় না , যা একক কোরতে সীমাবদ্ধ থাকে। কিন্তু, যে পারফরম্যান্স ফাঁক। minsum
সিসিল কারি

16

এখানে দুটি সাধারণ পন্থা রয়েছে:

  • প্রতিটি অ্যারে আইটেম পরীক্ষা করুন nanএবং নিন any
  • কিছু সংক্ষিপ্ত ক্রিয়াকলাপ প্রয়োগ করুন যা nan(যেমন sum) সংরক্ষণ করে এবং এর ফলাফলটি পরীক্ষা করে।

যদিও প্রথম পদ্ধতিরটি অবশ্যই সবচেয়ে পরিষ্কার, কিছু সংশ্লেষমূলক ক্রিয়াকলাপগুলির (বিশেষত যেগুলি বিএলএএস-তে কার্যকর করা হয় dot) এর ভারী অনুকূলিতকরণগুলি এগুলিকে দ্রুততর করতে পারে। মনে রাখবেন যে dotঅন্যান্য কিছু বিএলএএস অপারেশনের মতো কিছু শর্তে মাল্টথ্রেড করা হয়েছে। এটি বিভিন্ন মেশিনের মধ্যে গতির পার্থক্য ব্যাখ্যা করে।

এখানে চিত্র বর্ণনা লিখুন

import numpy
import perfplot


def min(a):
    return numpy.isnan(numpy.min(a))


def sum(a):
    return numpy.isnan(numpy.sum(a))


def dot(a):
    return numpy.isnan(numpy.dot(a, a))


def any(a):
    return numpy.any(numpy.isnan(a))


def einsum(a):
    return numpy.isnan(numpy.einsum("i->", a))


perfplot.show(
    setup=lambda n: numpy.random.rand(n),
    kernels=[min, sum, dot, any, einsum],
    n_range=[2 ** k for k in range(20)],
    logx=True,
    logy=True,
    xlabel="len(a)",
)

4
  1. ব্যবহার করুন।

    if numpy.isnan(myarray).any()

  2. numpy.isfinite চেক করার জন্য isnan চেয়ে ভাল হতে পারে

    if not np.isfinite(prop).all()


3

আপনি যদি আরামদায়ক হন এটি একটি দ্রুত শর্ট সার্কিট তৈরি করতে দেয় (কোনও NaN পাওয়া মাত্রই থামবে) ফাংশন:

import numba as nb
import math

@nb.njit
def anynan(array):
    array = array.ravel()
    for i in range(array.size):
        if math.isnan(array[i]):
            return True
    return False

যদি NaNফাংশনটি না থাকে তবে এটি সম্ভবত ধীর হতে পারে np.min, আমি মনে করি এটি কারণ np.minবড় অ্যারেগুলির জন্য মাল্টিপ্রসেসিং ব্যবহার করে:

import numpy as np
array = np.random.random(2000000)

%timeit anynan(array)          # 100 loops, best of 3: 2.21 ms per loop
%timeit np.isnan(array.sum())  # 100 loops, best of 3: 4.45 ms per loop
%timeit np.isnan(array.min())  # 1000 loops, best of 3: 1.64 ms per loop

তবে অ্যারেতে যদি কোনও এনএএন থাকে, বিশেষত যদি এটির অবস্থানটি নিম্ন সূচকগুলিতে থাকে তবে এটি আরও দ্রুত:

array = np.random.random(2000000)
array[100] = np.nan

%timeit anynan(array)          # 1000000 loops, best of 3: 1.93 µs per loop
%timeit np.isnan(array.sum())  # 100 loops, best of 3: 4.57 ms per loop
%timeit np.isnan(array.min())  # 1000 loops, best of 3: 1.65 ms per loop

সিথন বা সি এক্সটেনশনের সাথে অনুরূপ ফলাফল অর্জন করা যেতে পারে, এগুলি কিছুটা জটিল (বা সহজেই সহজলভ্য bottleneck.anynan) তবে আলটিমেটিকভাবে আমার anynanফাংশনের মতোই হয় do


1

এর সাথে সম্পর্কিত কীভাবে এনএএন-এর প্রথম ঘটনাটি খুঁজে পাওয়া যায় of এটি যে আমি জানি এটি পরিচালনা করার দ্রুততম উপায়:

index = next((i for (i,n) in enumerate(iterable) if n!=n), None)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.