मैं Numpy का उपयोग करके व्युत्पन्न की गणना कैसे करूं?


95

मैं एक फ़ंक्शन के व्युत्पन्न की गणना कैसे करता हूं, उदाहरण के लिए

y = x 2 +1

का उपयोग कर numpy?

मान लीजिए, मैं x = 5 पर व्युत्पन्न का मूल्य चाहता हूं ...


5
आपको सिम्पी का उपयोग करने की आवश्यकता है: sympy.org/en/index.html Numpy पायथन के लिए एक संख्यात्मक संगणना पुस्तकालय है
prrao

वैकल्पिक रूप से, क्या आप व्युत्पन्न के संख्यात्मक मूल्य का आकलन करने के लिए एक विधि चाहते हैं? इसके लिए आप एक बारीक अंतर विधि का उपयोग कर सकते हैं, लेकिन ध्यान रखें कि वे बुरी तरह से शोर करते हैं।
हेनरी गोमर्सल

जवाबों:


145

आपके पास चार विकल्प हैं

  1. परिमित अंतर
  2. स्वचालित डेरिवेटिव
  3. प्रतीकात्मक भेदभाव
  4. गणना डेरिवेटिव हाथ से।

परिमित अंतरों के लिए किसी बाहरी उपकरण की आवश्यकता नहीं होती है, लेकिन संख्यात्मक त्रुटि की संभावना होती है और, यदि आप एक बहुभिन्नरूपी स्थिति में हैं, तो आपको कुछ समय लग सकता है।

यदि आपकी समस्या काफी सरल है तो प्रतीकात्मक भेदभाव आदर्श है। इन दिनों प्रतीकात्मक तरीके काफी मजबूत हो रहे हैं। SymPy इसके लिए एक उत्कृष्ट परियोजना है जो NumPy के साथ अच्छी तरह से एकीकृत है। ऑटोप्रेप या लैम्बडिफाइ कार्यों को देखें या एक समान प्रश्न के बारे में जेन्सेन के ब्लॉगपोस्ट को देखें

स्वचालित व्युत्पन्न बहुत शांत हैं, संख्यात्मक त्रुटियों से ग्रस्त नहीं हैं, लेकिन इसके लिए कुछ अतिरिक्त पुस्तकालयों की आवश्यकता है (इसके लिए कुछ अच्छे विकल्प हैं)। यह सबसे मजबूत है, लेकिन चुनाव को सेट करने के लिए सबसे अधिक परिष्कृत / कठिन है। यदि आप अपने आप को numpyवाक्य रचना में सीमित कर रहे हैं तो थीनो एक अच्छा विकल्प हो सकता है।

यहाँ SymPy का उपयोग करके एक उदाहरण दिया गया है

In [1]: from sympy import *
In [2]: import numpy as np
In [3]: x = Symbol('x')
In [4]: y = x**2 + 1
In [5]: yprime = y.diff(x)
In [6]: yprime
Out[6]: 2⋅x

In [7]: f = lambdify(x, yprime, 'numpy')
In [8]: f(np.ones(5))
Out[8]: [ 2.  2.  2.  2.  2.]

क्षमा करें, अगर यह बेवकूफी लगती है, तो 3.Symbolic विभेदन और 4.by hand भेदभाव के बीच अंतर क्या है ??
DrStrangeLove

11
जब मैंने कहा कि "प्रतीकात्मक विभेदीकरण" का मेरा मतलब है कि इस प्रक्रिया को कंप्यूटर द्वारा नियंत्रित किया जाना था। सिद्धांत 3 और 4 में केवल वही होता है जो काम करता है, कंप्यूटर या प्रोग्रामर। 3 को संगतता, स्केलेबिलिटी और आलस्य के कारण 4 से अधिक पसंद किया जाता है। 4 आवश्यक है यदि 3 एक समाधान खोजने में विफल रहता है।
16

4
पंक्ति 7 में हमने f बनाया, एक फ़ंक्शन जो y wrt x के व्युत्पन्न की गणना करता है। 8 में हम इस व्युत्पन्न फ़ंक्शन को सभी लोगों के वेक्टर में लागू करते हैं और सभी जुड़वाओं के वेक्टर प्राप्त करते हैं। ऐसा इसलिए है, क्योंकि पंक्ति 6 ​​में कहा गया है, yprime = 2 * x।
MRocklin

पूर्णता के लिए, आप एकीकरण द्वारा भेदभाव भी कर सकते हैं (कैची के अभिन्न सूत्र देखें), यह उदाहरण के लिए लागू किया जाता है mpmath(निश्चित रूप से हालांकि वे वास्तव में क्या करते हैं)।
डेरिह

क्या ख़ुद को लागू किए बिना खाँसी में अंतर करने का एक आसान तरीका है? उदाहरण के लिए, मैं पूर्वनिर्धारित बिंदुओं पर एक फ़ंक्शन का ग्रेडिएंट ढूंढना चाहता हूं।
एलेक्स

42

सबसे सीधा-सीधा तरीका, जिसके बारे में मैं सोच सकता हूं, वह है खसखस का ढाल कार्य :

x = numpy.linspace(0,10,1000)
dx = x[1]-x[0]
y = x**2 + 1
dydx = numpy.gradient(y, dx)

इस तरह, dydx को केंद्रीय अंतरों का उपयोग करके गणना की जाएगी और numpy.diff के विपरीत y की समान लंबाई होगी, जो आगे के मतभेदों का उपयोग करता है और वापस (n-1) आकार वेक्टर होगा।


2
यदि dx स्थिर नहीं है तो क्या होगा?
weberc2

3
@ weberc2, उस स्थिति में आपको एक वेक्टर को दूसरे से विभाजित करना चाहिए, लेकिन किनारों को आगे और पीछे के डेरिवेटिव के साथ मैन्युअल रूप से व्यवहार करना चाहिए।
स्पार्कलर

2
या आप एक निरंतर dx के साथ y को प्रक्षेपित कर सकते हैं, फिर ढाल की गणना करें।
आइसअडोर

@ स्पार्कलर आपके सुझाव के लिए धन्यवाद। अगर मैं 2 छोटे सवाल पूछ सकते हैं, (i) कारण है कि हम पारित करते dxकरने numpy.gradientके बजाय x? (ii) क्या हम आपकी अंतिम पंक्ति इस प्रकार कर सकते हैं dydx = numpy.gradient(y, numpy.gradient(x)):?
user929304

2
V1.13 के अनुसार, गैर-समान रिक्ति को दूसरे तर्क के रूप में एक सरणी का उपयोग करके निर्दिष्ट किया जा सकता है। इस पृष्ठ के उदाहरण अनुभाग देखें ।
नथानिएल जोन्स

27

NumPy डेरिवेटिव की गणना करने के लिए सामान्य कार्यक्षमता प्रदान नहीं करता है। यह बहुपद के साधारण विशेष मामले को संभाल सकता है:

>>> p = numpy.poly1d([1, 0, 1])
>>> print p
   2
1 x + 1
>>> q = p.deriv()
>>> print q
2 x
>>> q(5)
10

यदि आप व्युत्पन्न की गणना संख्यात्मक रूप से करना चाहते हैं, तो आप बहुसंख्य अनुप्रयोगों के लिए केंद्रीय अंतर उद्धरणों का उपयोग करके दूर हो सकते हैं। किसी एक बिंदु में व्युत्पन्न के लिए, सूत्र कुछ इस तरह होगा

x = 5.0
eps = numpy.sqrt(numpy.finfo(float).eps) * (1.0 + x)
print (p(x + eps) - p(x - eps)) / (2.0 * eps * x)

यदि आपके पास फ़ंक्शन मानों की xएक समान सरणी yके साथ एब्सिस्से का एक सरणी है, तो आप डेरिवेटिव के सन्निकटन के साथ गणना कर सकते हैं

numpy.diff(y) / numpy.diff(x)

2
'अधिक सामान्य मामले के लिए संख्यात्मक व्युत्पन्न की गणना करना आसान है' - मैं अलग-अलग हूं, सामान्य मामलों के लिए संख्यात्मक व्युत्पन्न की गणना करना काफी कठिन है। आपने अभी-अभी अच्छा व्यवहार किया है।
उच्च प्रदर्शन मार्क

>>> प्रिंट पी के बाद 2 का क्या मतलब है ?? (दूसरी पंक्ति में)
DrStrangeLove

@DrStrangeLove: वह प्रतिपादक है। यह गणितीय संकेतन का अनुकरण करने के लिए है।
स्वेन मार्नाच

@SvenMarnach क्या यह अधिकतम प्रतिपादक है ?? और क्या?? क्यों लगता है कि घातांक 2 है ?? हमने केवल गुणांक का इनपुट किया ...
DrStrangeLove

2
@DrStrangeLove: आउटपुट के रूप में पढ़ा जाना चाहिए है 1 * x**2 + 1। वे 2ऊपर की लाइन में हैं क्योंकि यह एक घातांक है। इसे दूर से देखो।
स्वेन मार्नाच

15

यह मानते हुए कि आप उपयोग करना चाहते हैं numpy, आप कठोर परिभाषा का उपयोग करके किसी भी बिंदु पर किसी फ़ंक्शन के व्युत्पन्न की गणना कर सकते हैं :

def d_fun(x):
    h = 1e-5 #in theory h is an infinitesimal
    return (fun(x+h)-fun(x))/h

बेहतर परिणाम के लिए आप सिमेट्रिक व्युत्पन्न का भी उपयोग कर सकते हैं :

def d_fun(x):
    h = 1e-5
    return (fun(x+h)-fun(x-h))/(2*h)

अपने उदाहरण का उपयोग करते हुए, पूर्ण कोड कुछ इस तरह दिखना चाहिए:

def fun(x):
    return x**2 + 1

def d_fun(x):
    h = 1e-5
    return (fun(x+h)-fun(x-h))/(2*h)

अब, आप संख्यात्मक रूप से व्युत्पन्न का पता लगा सकते हैं x=5:

In [1]: d_fun(5)
Out[1]: 9.999999999621423

8

मैं ढेर पर एक और विधि फेंक दूँगा ...

scipy.interpolateकई इंटरपोलिंग स्प्लिन्स व्युत्पन्न प्रदान करने में सक्षम हैं। तो, एक रैखिक k=1रेखा ( ) का उपयोग करते हुए, तख़्ता का व्युत्पन्न ( derivative()विधि का उपयोग करके ) आगे के अंतर के बराबर होना चाहिए। मुझे पूरी तरह से यकीन नहीं है, लेकिन मेरा मानना ​​है कि क्यूबिक स्लाइन व्युत्पन्न का उपयोग करना एक केंद्रीकृत अंतर व्युत्पन्न के समान होगा क्योंकि यह क्यूबलाइन के निर्माण से पहले और बाद के मूल्यों का उपयोग करता है।

from scipy.interpolate import InterpolatedUnivariateSpline

# Get a function that evaluates the linear spline at any x
f = InterpolatedUnivariateSpline(x, y, k=1)

# Get a function that evaluates the derivative of the linear spline at any x
dfdx = f.derivative()

# Evaluate the derivative dydx at each x location...
dydx = dfdx(x)

बस यह करने की कोशिश की, मैं इस समारोह से त्रुटियों को प्राप्त कर रहा हूँ AxisError: धुरी -1 आयाम 0 की सरणी के लिए सीमा से बाहर है और मैं इस समुदाय पर कोई जवाब नहीं देखता, या तो कोई मदद?
अयान मित्रा

अपनी समस्या को एक नए प्रश्न के रूप में पोस्ट करें और इसे यहां लिंक करें। एक उदाहरण प्रदान करना जिससे आपकी त्रुटि उत्पन्न होती है, संभवतः इसकी आवश्यकता होगी। मेरे पास इंटरप फ़ंक्शंस के साथ होने वाली त्रुटियां आमतौर पर होती हैं क्योंकि डेटा अच्छी तरह से नहीं बनता है - जैसे बार-बार मान, गलत संख्या में आयाम, सरणियों में से एक गलती से खाली है, डेटा को एक्स के खिलाफ सॉर्ट नहीं किया गया है या जब सॉर्ट नहीं किया गया है मान्य फ़ंक्शन, आदि यह संभव है कि गलत तरीके से गलत तरीके से कॉल किया जा रहा है, लेकिन बहुत संभावना नहीं है। X.shape और y.shape की जाँच करें। देखें कि क्या np.interp () काम करता है - यदि नहीं तो यह अधिक उपयोगी त्रुटि प्रदान कर सकता है।
flutefreak7

5

ग्रेडिएंट्स की गणना करने के लिए, मशीन लर्निंग समुदाय ऑटोग्राद का उपयोग करता है:

" पर्याप्त रूप से संख्यात्मक कोड के डेरिवेटिव की गणना करता है। "

स्थापित करने के लिए:

pip install autograd

यहाँ एक उदाहरण है:

import autograd.numpy as np
from autograd import grad

def fct(x):
    y = x**2+1
    return y

grad_fct = grad(fct)
print(grad_fct(1.0))

यह जटिल कार्यों, जैसे बहुभिन्नरूपी कार्यों के ग्रेडिएंट की गणना भी कर सकता है।


नमस्ते इस फ़ंक्शन का उपयोग डेटा के दो स्तंभों के बीच अंतर करने के लिए संख्यात्मक रूप से चरण लंबाई प्रदान करके किया जा सकता है? धन्यवाद
अयान मित्रा

3

विभेदन के सरल प्रमाण का उपयोग करते हुए, आपके द्वारा आवश्यक सटीकता के स्तर के आधार पर आप इसे स्वयं काम कर सकते हैं:

>>> (((5 + 0.1) ** 2 + 1) - ((5) ** 2 + 1)) / 0.1
10.09999999999998
>>> (((5 + 0.01) ** 2 + 1) - ((5) ** 2 + 1)) / 0.01
10.009999999999764
>>> (((5 + 0.0000000001) ** 2 + 1) - ((5) ** 2 + 1)) / 0.0000000001
10.00000082740371

हम वास्तव में ढाल की सीमा नहीं ले सकते हैं, लेकिन इसके थोड़े मज़ेदार हैं। आप क्योंकि बाहर देखना होगा

>>> (((5+0.0000000000000001)**2+1)-((5)**2+1))/0.0000000000000001
0.0

2

आप का उपयोग कर सकते हैं scipy, जो बहुत सीधे आगे है:

scipy.misc.derivative(func, x0, dx=1.0, n=1, args=(), order=3)

एक बिंदु पर एक समारोह के एनटी व्युत्पन्न का पता लगाएं।

आपके मामले में:

from scipy.misc import derivative

def f(x):
    return x**2 + 1

derivative(f, 5, dx=1e-6)
# 10.00000000139778
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.