নমপি অ্যারে ফাংশন ম্যাপ করার সর্বাধিক দক্ষ উপায়


337

একটি নমপি অ্যারে উপর ফাংশন মানচিত্র করার সবচেয়ে কার্যকর উপায় কি? আমার বর্তমান প্রকল্পে আমি যেভাবে এটি করছি তা হ'ল:

import numpy as np 

x = np.array([1, 2, 3, 4, 5])

# Obtain array of square of each element in x
squarer = lambda t: t ** 2
squares = np.array([squarer(xi) for xi in x])

তবে এটি সম্ভবত খুব অদক্ষ বলে মনে হচ্ছে, যেহেতু আমি একটি অ্যারি অ্যারেতে রূপান্তর করার আগে পাইথন তালিকা হিসাবে নতুন অ্যারে তৈরি করতে একটি তালিকা বোঝার ব্যবহার করছি।

আমরা কি আরও ভাল করতে পারি?


10
"স্কোয়ার = x ** 2" কেন নয়? আপনার মূল্যায়নের জন্য আরও জটিল কিছু কাজ করতে হবে?
22 ডিগ্রি

4
শুধু কিভাবে squarer(x)?
জীবন 16

1
হয়তো এটি সরাসরি প্রশ্নের উত্তর দিচ্ছে না, তবে আমি শুনেছি যে নাম্বা বিদ্যমান পাইথন কোডটিকে সমান্তরাল মেশিনের নির্দেশাবলীতে সংকলন করতে পারে। আমি যখন এই পোস্টটি ব্যবহার করার সুযোগ পাই তখন আমি এই পোস্টটি পুনরায় দেখা এবং সংশোধন করব।
友情 留 在 无 盐

x = np.array([1, 2, 3, 4, 5]); x**2কাজ করে
শার্ক দেং

উত্তর:


281

আমি সব প্রস্তাব পদ্ধতি প্লাস পরীক্ষিত থাকেন np.array(map(f, x))সঙ্গে perfplot(খনি একটি ছোট প্রকল্প)।

বার্তা # 1: আপনি যদি নমপির নেটিভ ফাংশন ব্যবহার করতে পারেন তবে এটি করুন।

যদি ফাংশনটি আপনি ইতিমধ্যে ভেক্টরাইজ করার চেষ্টা করছেন হয় (যেমন ভেক্টরকৃত x**2মূল পোস্টে উদাহরণস্বরূপ), ব্যবহার করে অনেক অন্য কিছু তুলনায় দ্রুততর (নোট লগ স্কেলের):

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

আপনার যদি প্রকৃতপক্ষে ভেক্টরাইজেশন দরকার হয় তবে আপনি কোন বৈকল্পিক ব্যবহার করেন তা আসলেই কিছু যায় আসে না।

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


প্লটগুলি পুনরুত্পাদন করার কোড:

import numpy as np
import perfplot
import math


def f(x):
    # return math.sqrt(x)
    return np.sqrt(x)


vf = np.vectorize(f)


def array_for(x):
    return np.array([f(xi) for xi in x])


def array_map(x):
    return np.array(list(map(f, x)))


def fromiter(x):
    return np.fromiter((f(xi) for xi in x), x.dtype)


def vectorize(x):
    return np.vectorize(f)(x)


def vectorize_without_init(x):
    return vf(x)


perfplot.show(
    setup=lambda n: np.random.rand(n),
    n_range=[2 ** k for k in range(20)],
    kernels=[f, array_for, array_map, fromiter, vectorize, vectorize_without_init],
    xlabel="len(x)",
)

7
আপনি f(x)আপনার চক্রান্ত থেকে বাদ পড়েছেন বলে মনে হচ্ছে । এটি সবার জন্য প্রযোজ্য নাও হতে পারে fতবে এটি এখানে প্রযোজ্য এবং প্রযোজ্য ক্ষেত্রে এটি সহজেই দ্রুততম সমাধান solution
ব্যবহারকারী 2357112 23

2
এছাড়াও, আপনার প্লটটি আপনার দাবিকে সমর্থন করে না যে vf = np.vectorize(f); y = vf(x)সংক্ষিপ্ত ইনপুটগুলির জন্য জিতবে।
ব্যবহারকারীর 2357112 মনিকা 23

পাইপ () এর মাধ্যমে পারফ্লট (v0.3.2) ইনস্টল করার পরে pip install -U perfplot, আমি বার্তাটি দেখছি: AttributeError: 'module' object has no attribute 'save'উদাহরণ কোডটি আটকানোর সময়।
tsherwen

লুপের জন্য একটি ভ্যানিলা সম্পর্কে কী?
ক্যাটিগার 3331

1
@ ভ্লাদ মন্তব্য হিসাবে math.sqrt কেবল ব্যবহার করুন।
নিকো Schlömer

138

কিভাবে ব্যবহার সম্পর্কে numpy.vectorize

import numpy as np
x = np.array([1, 2, 3, 4, 5])
squarer = lambda t: t ** 2
vfunc = np.vectorize(squarer)
vfunc(x)
# Output : array([ 1,  4,  9, 16, 25])

36
এটি আর দক্ষ নয়।
ব্যবহারকারী 2357112

78
সেই দস্তাবেজ থেকে: The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop. অন্যান্য প্রশ্নের মধ্যে আমি দেখতে পেয়েছি যা vectorizeব্যবহারকারীর পুনরাবৃত্তির গতি দ্বিগুণ করে। তবে আসল স্পিডআপটি বাস্তব numpyঅ্যারে অপারেশনগুলির সাথে।
hpulj

2
নোট করুন যে ভেক্টরাইজ কমপক্ষে 1-অ অ্যারেগুলির জন্য জিনিসগুলিকে কাজ করে তোলে
এরিক

তবে squarer(x)ইতিমধ্যে অ -1 ডি অ্যারেগুলির জন্য কাজ করবে। vectorizeকেবলমাত্র তালিকার বোঝার উপর কোনও সুবিধা আছে (প্রশ্নটির মতো), শেষ হয়নি squarer(x)
ব্যবহারকারী 2357112

79

টি এল; ডিআর

@ ব্যবহারকারী 2357112 দ্বারা উল্লিখিত হিসাবে , ফাংশনটি প্রয়োগের একটি "প্রত্যক্ষ" পদ্ধতি হ'ল নম্পি অ্যারেগুলির উপরে ফাংশনটি মানচিত্রের জন্য সর্বদা দ্রুত এবং সহজতম উপায়:

import numpy as np
x = np.array([1, 2, 3, 4, 5])
f = lambda x: x ** 2
squares = f(x)

সাধারণত এড়িয়ে চলুন np.vectorize, কারণ এটি ভাল সঞ্চালন করে না, এবং এর অনেকগুলি সমস্যা রয়েছে (বা ছিল) । আপনি যদি অন্য ডেটা প্রকারগুলি পরিচালনা করছেন তবে আপনি নীচে দেখানো অন্যান্য পদ্ধতিগুলি তদন্ত করতে চাইতে পারেন।

পদ্ধতির তুলনা

ফাংশন ম্যাপ করার জন্য তিনটি পদ্ধতির তুলনা করার জন্য এখানে কয়েকটি সাধারণ পরীক্ষা রয়েছে, উদাহরণস্বরূপ পাইথন ৩.6 এবং নুমপি ১.১15.৪ ব্যবহার করে। প্রথমত, পরীক্ষার জন্য সেট-আপ ফাংশন:

import timeit
import numpy as np

f = lambda x: x ** 2
vf = np.vectorize(f)

def test_array(x, n):
    t = timeit.timeit(
        'np.array([f(xi) for xi in x])',
        'from __main__ import np, x, f', number=n)
    print('array: {0:.3f}'.format(t))

def test_fromiter(x, n):
    t = timeit.timeit(
        'np.fromiter((f(xi) for xi in x), x.dtype, count=len(x))',
        'from __main__ import np, x, f', number=n)
    print('fromiter: {0:.3f}'.format(t))

def test_direct(x, n):
    t = timeit.timeit(
        'f(x)',
        'from __main__ import x, f', number=n)
    print('direct: {0:.3f}'.format(t))

def test_vectorized(x, n):
    t = timeit.timeit(
        'vf(x)',
        'from __main__ import x, vf', number=n)
    print('vectorized: {0:.3f}'.format(t))

পাঁচটি উপাদান দিয়ে পরীক্ষা করা (দ্রুত থেকে ধীরে ধীরে সাজানো):

x = np.array([1, 2, 3, 4, 5])
n = 100000
test_direct(x, n)      # 0.265
test_fromiter(x, n)    # 0.479
test_array(x, n)       # 0.865
test_vectorized(x, n)  # 2.906

100 টি উপাদান সহ:

x = np.arange(100)
n = 10000
test_direct(x, n)      # 0.030
test_array(x, n)       # 0.501
test_vectorized(x, n)  # 0.670
test_fromiter(x, n)    # 0.883

এবং অ্যারের উপাদান বা আরও অনেকের সাথে:

x = np.arange(1000)
n = 1000
test_direct(x, n)      # 0.007
test_fromiter(x, n)    # 0.479
test_array(x, n)       # 0.516
test_vectorized(x, n)  # 0.945

পাইথন / নম্পপি এবং সংকলক অপ্টিমাইজেশনের বিভিন্ন সংস্করণের বিভিন্ন ফলাফল থাকবে, তাই আপনার পরিবেশের জন্য একই পরীক্ষা করুন a


2
আপনি যদি countযুক্তি এবং একটি জেনারেটর এক্সপ্রেশন ব্যবহার করেন তবে np.fromiterতা উল্লেখযোগ্যভাবে দ্রুত।
juanpa.arrivillaga

3
সুতরাং, উদাহরণস্বরূপ, ব্যবহার করুন'np.fromiter((f(xi) for xi in x), x.dtype, count=len(x))'
juanpa.arrivillaga


4
যদি f2 ভেরিয়েবল থাকে এবং অ্যারে 2 ডি হয় তবে কী হবে?
সিগুর

2
আমি বিভ্রান্ত হয়ে পড়েছি যে যখন ওপি একটি অ্যারে জুড়ে কোনও ফাংশন "মানচিত্র" কীভাবে জিজ্ঞাসা করছিল তখন 'চ (এক্স)' সংস্করণ ("প্রত্যক্ষ") আসলে তুলনীয় হিসাবে বিবেচিত হবে? F (x) = x ** 2 এর ক্ষেত্রে ** অ্যালপি দ্বারা সম্পূর্ণ অ্যারেতে প্রতি উপাদান ভিত্তিতে না করে সম্পাদিত হচ্ছে। উদাহরণস্বরূপ, যদি চ (x) এর হল 'ল্যামডা X:।। এক্স + X "তাহলে উত্তর ভিন্ন কারণ numpy যোগসূত্র অ্যারে পরিবর্তে উপাদান ছাড়াও প্রতি করছে এই সত্যিই অভিপ্রেত তুলনা হয় দয়া করে ব্যাখ্যা
অ্যান্ড্রু Mellinger

49

আছে numexpr , numba এবং cython চারপাশে, এই উত্তর লক্ষ্য বিবেচনা এই সম্ভাবনার নিতে হয়।

তবে প্রথমে সুস্পষ্টভাবে বলা যাক: আপনি অজস্র-অ্যারেতে পাইথন-ফাংশনটিকে কীভাবে ম্যাপ করবেন না কেন, এটি পাইথন ফাংশনটি স্থির করে রাখে যার অর্থ প্রতিটি মূল্যায়নের জন্য:

  • নম্পি-অ্যারে উপাদানটি অবশ্যই পাইথন-অবজেক্টে রূপান্তর করতে হবে (উদাঃ a Float )।
  • সমস্ত গণনা পাইথন-অবজেক্টস দিয়ে সম্পন্ন হয় যার অর্থ দোভাষী, গতিশীল প্রেরণ এবং অপরিবর্তনীয় বস্তুর ওভারহেড থাকে।

সুতরাং উপরে উল্লিখিত ওভারহেডের কারণে অ্যারে দিয়ে লুপটি ব্যবহার করতে কোন যন্ত্রপাতি ব্যবহৃত হয় তা বড় ভূমিকা রাখে না - এটি নম্পির অন্তর্নির্মিত কার্যকারিতা ব্যবহারের চেয়ে অনেক ধীর থাকে।

আসুন নীচের উদাহরণটি একবার দেখুন:

# numpy-functionality
def f(x):
    return x+2*x*x+4*x*x*x

# python-function as ufunc
import numpy as np
vf=np.vectorize(f)
vf.__name__="vf"

np.vectorizeখাঁটি-পাইথন ফাংশন ক্লাসের পদ্ধতির প্রতিনিধি হিসাবে নেওয়া হয়। ব্যবহার perfplot(এই উত্তর পরিশিষ্ট কোড দেখুন) আমরা নিম্নলিখিত চলমান বার পাবেন:

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

আমরা দেখতে পাচ্ছি, খাঁটি পাইথন সংস্করণটির চেয়ে ন্যাক্পি-অ্যাপ্রোচ 10x-100x দ্রুত। বড় অ্যারে-আকারগুলির জন্য কর্মক্ষমতা হ্রাস সম্ভবত ডেটা আর ক্যাশে ফিট করে না কারণ।

এটিও উল্লেখ করার মতো, এটি vectorizeপ্রচুর স্মৃতিও ব্যবহার করে, তাই প্রায়শই স্মৃতি-ব্যবহার হ'ল বোতল-ঘাড় (সম্পর্কিত এসও-প্রশ্ন দেখুন )। এছাড়াও নোট করুন, যে নাম্পির ডকুমেন্টেশন এতে np.vectorizeউল্লেখ করেছে যে এটি "প্রাথমিকভাবে সুবিধার জন্য সরবরাহ করা হয়, পারফরম্যান্সের জন্য নয়"।

স্ক্র্যাচ থেকে সি-এক্সটেনশন লেখার পাশাপাশি অন্যান্য সরঞ্জামগুলি ব্যবহার করা উচিত, যখন পারফরম্যান্স পছন্দ হয় following


একজন প্রায়শই শুনেন যে, নিম্পি-পারফরম্যান্স যতটা ভাল হয় ততই ভাল, কারণ এটি হুডের নীচে খাঁটি সি। তবুও উন্নতির অনেক জায়গা আছে!

ভেক্টরাইজড নম্পি-সংস্করণে প্রচুর অতিরিক্ত মেমরি এবং মেমরি-অ্যাক্সেস ব্যবহার করা হয়। নিউমএক্সপ্যাক-লাইব্রেরি নম্পি-অ্যারে টাইল করার চেষ্টা করে এবং এর ফলে আরও ভাল ক্যাশে ব্যবহার পেতে পারে:

# less cache misses than numpy-functionality
import numexpr as ne
def ne_f(x):
    return ne.evaluate("x+2*x*x+4*x*x*x")

নিম্নলিখিত তুলনা বাড়ে:

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

আমি উপরের চক্রান্তের সমস্ত কিছু ব্যাখ্যা করতে পারি না: আমরা শুরুতে numexpr-গ্রন্থাগারের জন্য আরও বড় ওভারহেড দেখতে পারি, তবে এটি ক্যাশে আরও ভালভাবে ব্যবহার করার কারণে এটি বড় অ্যারেগুলির জন্য প্রায় 10 বার দ্রুত!


আর একটি পদ্ধতি হ'ল ফাংশনটি জিট-সংকলন করা এবং এইভাবে সত্যিকারের খাঁটি সি ইউফুঙ্ক পাওয়া। এটি নাম্বার পদ্ধতি:

# runtime generated C-function as ufunc
import numba as nb
@nb.vectorize(target="cpu")
def nb_vf(x):
    return x+2*x*x+4*x*x*x

এটি আসল নম্পী-পদ্ধতির চেয়ে 10 গুণ দ্রুত:

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


তবে, কাজটি বিব্রতকরভাবে সমান্তরাল, সুতরাং আমরা prangeসমান্তরালভাবে লুপটি গণনা করতে ব্যবহার করতে পারি :

@nb.njit(parallel=True)
def nb_par_jitf(x):
    y=np.empty(x.shape)
    for i in nb.prange(len(x)):
        y[i]=x[i]+2*x[i]*x[i]+4*x[i]*x[i]*x[i]
    return y

প্রত্যাশিত হিসাবে, সমান্তরাল ফাংশন ছোট ইনপুটগুলির জন্য ধীর, তবে বৃহত আকারের জন্য দ্রুত (প্রায় 2 গুণনীয়):

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


নাম্বা যখন নিম্পি-অ্যারেগুলির সাথে অপারেশনগুলি অনুকূল করতে বিশেষীকরণ করে তবে সাইথন আরও সাধারণ সরঞ্জাম। নাম্বার মতো একই পারফরম্যান্সটি বের করা আরও জটিল - প্রায়শই এটি এলএলভিএম (নাম্বা) বনাম স্থানীয় সংকলক (জিসিসি / এমএসভিসি) এর নীচে থাকে:

%%cython -c=/openmp -a
import numpy as np
import cython

#single core:
@cython.boundscheck(False) 
@cython.wraparound(False) 
def cy_f(double[::1] x):
    y_out=np.empty(len(x))
    cdef Py_ssize_t i
    cdef double[::1] y=y_out
    for i in range(len(x)):
        y[i] = x[i]+2*x[i]*x[i]+4*x[i]*x[i]*x[i]
    return y_out

#parallel:
from cython.parallel import prange
@cython.boundscheck(False) 
@cython.wraparound(False)  
def cy_par_f(double[::1] x):
    y_out=np.empty(len(x))
    cdef double[::1] y=y_out
    cdef Py_ssize_t i
    cdef Py_ssize_t n = len(x)
    for i in prange(n, nogil=True):
        y[i] = x[i]+2*x[i]*x[i]+4*x[i]*x[i]*x[i]
    return y_out

সাইথনের ফলাফল কিছুটা ধীর গতিতে:

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


উপসংহার

স্পষ্টতই, শুধুমাত্র একটি ফাংশনের জন্য পরীক্ষা করা কিছুই প্রমাণ করে না। এছাড়াও একটি মনে রাখা উচিত, যে চুসেন ফাংশন-উদাহরণস্বরূপ, মেমরির ব্যান্ডউইথ ছিল 10 ^ 5 উপাদানগুলির চেয়ে বড় আকারের বোতল ঘাড় - এইভাবে আমরা এই অঞ্চলে নাম্বা, নিউমেক্সপ্রে এবং সিথনের ক্ষেত্রে একই পারফরম্যান্স পেয়েছি।

শেষ পর্যন্ত, আলটিমেটিভ উত্তরটি ফাংশন, হার্ডওয়্যার, পাইথন-বিতরণ এবং অন্যান্য কারণগুলির ধরণের উপর নির্ভর করে। উদাহরণস্বরূপ Anaconda- র-বিতরণের জন্য numpy এর কাজকর্মের জন্য ইন্টেলের VML ব্যবহার করে এবং এইভাবে numba তূলনায় (যদি না তা SVML ব্যবহার করে, এই দেখুন তাই-পোস্ট তুরীয় ফাংশন পছন্দ সহজে জন্য) exp, sin, cosএবং অনুরূপ - যেমন নিম্নলিখিত দেখতে তাই-পোস্ট

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


পারফেল্লট- প্যাকেজ সহ চলমান সময় প্লট করা:

import perfplot
perfplot.show(
    setup=lambda n: np.random.rand(n),
    n_range=[2**k for k in range(0,24)],
    kernels=[
        f, 
        vf,
        ne_f, 
        nb_vf, nb_par_jitf,
        cy_f, cy_par_f,
        ],
    logx=True,
    logy=True,
    xlabel='len(x)'
    )

1
নুম্বা সাধারণত ইন্টেল এসভিএমএল ব্যবহার করতে পারে যার ফলস্বরূপ ইনটেল ভিএমএলের তুলনায় বেশ তুলনামূলক সময় আসে তবে বাস্তবায়নটি (0.43-0.47) সংস্করণে কিছুটা বগি। আমি একটি কার্যকারিতা চক্রান্ত যুক্ত করেছেন stackoverflow.com/a/56939240/4045774 আপনার cy_expsum করার comparsion জন্য।
সর্বাধিক 11111

29
squares = squarer(x)

অ্যারেগুলিতে গাণিতিক ক্রিয়াকলাপগুলি স্বয়ংক্রিয়ভাবে মৌলিক দিকে প্রয়োগ করা হয়, দক্ষ সি-লেভেল লুপগুলি দিয়ে যা সমস্ত দোভাষী ওভারহেড এড়িয়ে যায় যা পাইথন-স্তরীয় লুপ বা বোধগম্যতার জন্য প্রযোজ্য।

আপনি NumPy অ্যারেতে এলিমেন্টওয়াইজের জন্য প্রয়োগ করতে চান এমন বেশিরভাগ ফাংশন কেবলমাত্র কাজ করবে, যদিও কিছুটির পরিবর্তনের প্রয়োজন হতে পারে। উদাহরণস্বরূপ, ifউপাদান হিসাবে কাজ করে না। আপনি এগুলিকে কনস্ট্রাক্ট ব্যবহার করতে রূপান্তর করতে চান যেমন numpy.where:

def using_if(x):
    if x < 5:
        return x
    else:
        return x**2

হয়ে

def using_where(x):
    return numpy.where(x < 5, x, x**2)

8

আমি নম্পির নতুন সংস্করণে (আমি 1.13 ব্যবহার করি) বিশ্বাস করি আপনি স্কেলার টাইপের জন্য যে লিখনটি লিখেছেন সেটির জন্য নিম্পি অ্যারেটি পাস করে কেবল ফাংশনটি কল করতে পারেন, এটি স্বয়ংক্রিয়ভাবে অলপ অ্যারের উপরে প্রতিটি উপাদানকে ফাংশন কল প্রয়োগ করবে এবং আপনাকে ফিরিয়ে দেবে আরেকটি নপি অ্যারে

>>> import numpy as np
>>> squarer = lambda t: t ** 2
>>> x = np.array([1, 2, 3, 4, 5])
>>> squarer(x)
array([ 1,  4,  9, 16, 25])

3
এটি দূরবর্তী দিক থেকে নতুন নয় - এটি সর্বদা ক্ষেত্রে ছিল - এটি শূন্যতার অন্যতম প্রধান বৈশিষ্ট্য।
এরিক

8
এটি **অপারেটর যা প্রতিটি উপাদান t এর গণনা প্রয়োগ করে t। এটাই সাধারণ এটিকে মোড়ানো lambdaঅতিরিক্ত কিছু করে না।
এইচপলজ

এটি বর্তমানে প্রদর্শিত বিবৃতি হিসাবে প্রদর্শিত হয় যদি এটি সঙ্গে কাজ করে না।
ট্রিহার্ড

8

অনেক ক্ষেত্রে, numpy.apply_along_axis সেরা পছন্দ হবে। এটি অন্যান্য পদ্ধতির তুলনায় প্রায় 100x দ্বারা কার্যকারিতা বাড়িয়ে তোলে - এবং কেবল তুচ্ছ পরীক্ষামূলক ক্রিয়াকলাপের জন্যই নয়, আঙ্গুল এবং স্কিপি থেকে আরও জটিল ফাংশন রচনাগুলির জন্যও।

আমি যখন পদ্ধতিটি যুক্ত করব:

def along_axis(x):
    return np.apply_along_axis(f, 0, x)

পারফ্লট কোডটিতে আমি নিম্নলিখিত ফলাফলগুলি পেয়েছি: এখানে চিত্র বর্ণনা লিখুন


দুর্দান্ত কৌশল!
ফিলিপ এসএস স্নাইডার

আমি এই বিষয়টি নিয়ে অত্যন্ত অবাক হয়েছি যে বেশিরভাগ লোক এত বছর ধরে এই সাধারণ, স্কেলযোগ্য এবং অন্তর্নিহিত কোনও মস্তিষ্ক সম্পর্কে সচেতন বলে মনে হয় না ....
বিল হুয়াং

7

দেখে মনে হচ্ছে কেউ ufuncনামী প্যাকেজে উত্পাদন করার জন্য বিল্ট-ইন কারখানার পদ্ধতির উল্লেখ করেনি : np.frompyfuncযা আমি আবার পরীক্ষা করে দেখেছি np.vectorizeএবং প্রায় 20 ~ 30% দ্বারা পেরেছি। অবশ্যই এটি নির্ধারিত সি কোড বা এমনকি numba(যা আমি পরীক্ষা করিনি) হিসাবে ভাল সম্পাদন করবে , তবে এটি এর চেয়ে ভাল বিকল্প হতে পারেnp.vectorize

f = lambda x, y: x * y
f_arr = np.frompyfunc(f, 2, 1)
vf = np.vectorize(f)
arr = np.linspace(0, 1, 10000)

%timeit f_arr(arr, arr) # 307ms
%timeit vf(arr, arr) # 450ms

আমি আরও বড় নমুনাগুলি পরীক্ষা করেছি এবং উন্নতি আনুপাতিক। এখানে ডকুমেন্টেশন দেখুন


1
আমি উপরের সময় পরীক্ষাগুলির পুনরাবৃত্তি করেছি এবং প্রায় 30%
জুলিয়ান - ব্রেইনএএনএক্স.কম

2

এই পোস্টে উল্লিখিত হিসাবে , ঠিক যেমন জেনারেটর এক্সপ্রেশন ব্যবহার করুন:

numpy.fromiter((<some_func>(x) for x in <something>),<dtype>,<size of something>)

2

উপরের সমস্ত উত্তরগুলির সাথে তুলনা করা ভাল, তবে যদি আপনাকে ম্যাপিংয়ের জন্য কাস্টম ফাংশন ব্যবহার করতে হয় এবং আপনার কাছে থাকে numpy.ndarray এবং আপনার অ্যারের আকার ধরে রাখতে হবে।

আমি মাত্র দুটি তুলনা করেছি, তবে এটি আকারটি ধরে রাখবে ndarray। তুলনা করার জন্য আমি 1 মিলিয়ন এন্ট্রি সহ অ্যারে ব্যবহার করেছি। এখানে আমি বর্গক্ষেত্রের ফাংশনটি ব্যবহার করি, এটিও নিম্পে অন্তর্নির্মিত এবং দুর্দান্ত পারফরম্যান্সের উত্সাহ দেয়, কারণ যেহেতু কোনও কিছুর প্রয়োজন ছিল তাই আপনি আপনার পছন্দের ফাংশনটি ব্যবহার করতে পারেন।

import numpy, time
def timeit():
    y = numpy.arange(1000000)
    now = time.time()
    numpy.array([x * x for x in y.reshape(-1)]).reshape(y.shape)        
    print(time.time() - now)
    now = time.time()
    numpy.fromiter((x * x for x in y.reshape(-1)), y.dtype).reshape(y.shape)
    print(time.time() - now)
    now = time.time()
    numpy.square(y)  
    print(time.time() - now)

আউটপুট

>>> timeit()
1.162431240081787    # list comprehension and then building numpy array
1.0775556564331055   # from numpy.fromiter
0.002948284149169922 # using inbuilt function

এখানে আপনি পরিষ্কারভাবে দেখতে পারেন numpy.fromiterসহজ পদ্ধতির বিবেচনা করে দুর্দান্ত কাজ করে এবং যদি ইনবিল্ট ফাংশন উপলব্ধ থাকে তবে দয়া করে এটি ব্যবহার করুন।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.