स्वचालित अवकलन

गणित और कंप्यूटर बीजगणित में, स्वचालित विभेदन (ऑटो-विभेदन, ऑटोडिफ़, या AD), जिसे एल्गोरिथम विभेदन, कम्प्यूटेशनल विभेदन भी कहा जाता है, कंप्यूटर प्रोग्राम द्वारा निर्दिष्ट फ़ंक्शन के आंशिक व्युत्पन्न का मूल्यांकन करने के लिए तकनीकों का एक सेट है।

स्वचालित विभेदन इस तथ्य का फायदा उठाता है कि प्रत्येक कंप्यूटर प्रोग्राम, चाहे कितना भी जटिल क्यों न हो, प्राथमिक अंकगणितीय संचालन (जोड़, घटाव, गुणा, भाग, आदि) और प्राथमिक कार्यों (घातीय फ़ंक्शन, प्राकृतिक लघुगणक, उन लोगों के,  कोज्या , आदि) के अनुक्रम को निष्पादित करता है। इन परिचालनों में श्रृंखला नियम को बार-बार लागू करने से, मनमाने ढंग से क्रम के आंशिक व्युत्पन्न की गणना स्वचालित रूप से, सटीकता से काम करने के लिए की जा सकती है, और मूल कार्यक्रम की तुलना में अधिक अंकगणितीय संचालन के एक छोटे स्थिर कारक का उपयोग किया जा सकता है।

अन्य विभेदीकरण विधियों से अंतर
स्वचालित विभेदन प्रतीकात्मक विभेदन और संख्यात्मक विभेदन से भिन्न है। प्रतीकात्मक विभेदन से कंप्यूटर प्रोग्राम को एकल गणितीय अभिव्यक्ति में परिवर्तित करने में कठिनाई का सामना करना पड़ता है और इससे अकुशल कोड हो सकता है। संख्यात्मक विभेदन (परिमित अंतर की विधि) विवेकीकरण प्रक्रिया और रद्दीकरण में राउंड-ऑफ त्रुटियां पेश कर सकता है। इन दोनों शास्त्रीय तरीकों में उच्च डेरिवेटिव की गणना करने में समस्याएं हैं, जहां जटिलता और त्रुटियां बढ़ जाती हैं। अंत में, ये दोनों शास्त्रीय विधियां कई इनपुट के संबंध में किसी फ़ंक्शन के आंशिक डेरिवेटिव की गणना करने में धीमी हैं, जैसा कि ढतला हुआ वंश -आधारित ऑप्टिमाइज़ेशन (गणित) एल्गोरिदम के लिए आवश्यक है। स्वचालित विभेदन इन सभी समस्याओं का समाधान करता है।

मिश्रित फलनों के आंशिक अवकलजों का श्रृंखला नियम
स्वचालित विभेदन के लिए मौलिक कार्य संरचना के आंशिक डेरिवेटिव के श्रृंखला नियम द्वारा प्रदान किए गए अंतर का अपघटन है। सरल रचना के लिए $$\begin{align} y &= f(g(h(x))) = f(g(h(w_0))) = f(g(w_1)) = f(w_2) = w_3 \\ w_0 &= x \\ w_1 &= h(w_0) \\ w_2 &= g(w_1) \\ w_3 &= f(w_2) = y \end{align}$$ श्रृंखला नियम देता है $$\frac{\partial y}{\partial x} = \frac{\partial y}{\partial w_2} \frac{\partial w_2}{\partial w_1} \frac{\partial w_1}{\partial x} = \frac{\partial f(w_2)}{\partial w_2} \frac{\partial g(w_1)}{\partial w_1} \frac{\partial h(w_0)}{\partial x}$$

दो प्रकार के स्वचालित विभेदन
आमतौर पर, स्वचालित विभेदन के दो अलग-अलग तरीके प्रस्तुत किए जाते हैं। फॉरवर्ड संचय निर्दिष्ट करता है कि कोई व्यक्ति श्रृंखला नियम को अंदर से बाहर तक पार करता है (अर्थात, पहले गणना करें $$\partial w_1/ \partial x$$ और तब $$\partial w_2/\partial w_1$$ और अंत में $$\partial y/\partial w_2$$), जबकि रिवर्स संचय में बाहर से अंदर तक ट्रैवर्सल होता है (पहले गणना करें)। $$\partial y/\partial w_2$$ और तब $$\partial w_2/\partial w_1$$ और अंत में $$\partial w_1/\partial x$$). अधिक संक्षेप में,
 * फॉरवर्ड संचयन (जिसे बॉटम-अप, फॉरवर्ड मोड या टैंगेंट मोड भी कहा जाता है)
 * रिवर्स संचयन (जिसे टॉप-डाउन, रिवर्स मोड या एडजॉइंट मोड भी कहा जाता है)
 * फॉरवर्ड संचय पुनरावर्ती संबंध की गणना करता है: $$\frac{\partial w_i}{\partial x} = \frac{\partial w_i}{\partial w_{i-1}} \frac{\partial w_{i-1}}{\partial x}$$ साथ $$w_3 = y$$, और,
 * रिवर्स संचय पुनरावर्ती संबंध की गणना करता है: $$\frac{\partial y}{\partial w_i} = \frac{\partial y}{\partial w_{i+1}} \frac{\partial w_{i+1}}{\partial w_{i}}$$ साथ $$w_0 = x$$.

आंशिक व्युत्पन्न का मूल्य, जिसे बीज कहा जाता है, आगे या पीछे प्रचारित होता है और प्रारंभ में होता है $$\frac{\partial x}{\partial x}=1$$ या $$\frac{\partial y}{\partial y}=1$$. फॉरवर्ड संचय फ़ंक्शन का मूल्यांकन करता है और एक पास में एक स्वतंत्र चर के संबंध में व्युत्पन्न की गणना करता है। प्रत्येक स्वतंत्र चर के लिए $$x_1,x_2,\dots,x_n$$ इसलिए एक अलग पास आवश्यक है जिसमें उस स्वतंत्र चर के संबंध में व्युत्पन्न को एक पर सेट किया गया है ($$\frac{\partial x_1}{\partial x_1}=1$$) और अन्य सभी को शून्य ($$\frac{\partial x_2}{\partial x_1}= \dots = \frac{\partial x_n}{\partial x_1} = 0$$). इसके विपरीत, रिवर्स संचय के लिए आंशिक डेरिवेटिव के लिए मूल्यांकन किए गए आंशिक कार्यों की आवश्यकता होती है। इसलिए रिवर्स संचय पहले फ़ंक्शन का मूल्यांकन करता है और एक अतिरिक्त पास में सभी स्वतंत्र चर के संबंध में डेरिवेटिव की गणना करता है।

इन दोनों प्रकारों में से किसका उपयोग किया जाना चाहिए यह स्वीप गिनती पर निर्भर करता है। एक स्वीप का कम्प्यूटेशनल जटिलता सिद्धांत मूल कोड की जटिलता के समानुपाती होता है। मल्टीलेयर परसेप्ट्रॉन में त्रुटियों का पश्चप्रचार,  यंत्र अधिगम  में उपयोग की जाने वाली तकनीक, रिवर्स संचय का एक विशेष मामला है।
 * कार्यों के लिए रिवर्स संचय की तुलना में फॉरवर्ड संचय अधिक कुशल है $f : R^{n} → R^{m}$ साथ $n ≪ m$ केवल $n$ की तुलना में स्वीप आवश्यक हैं $m$रिवर्स संचय के लिए स्वीप।
 * कार्यों के लिए फॉरवर्ड संचय की तुलना में रिवर्स संचय अधिक कुशल है $f : R^{n} → R^{m}$ साथ $n ≫ m$ केवल $m$ की तुलना में स्वीप आवश्यक हैं $n$ आगे संचय के लिए स्वीप।

फॉरवर्ड संचय की शुरुआत आर.ई. द्वारा की गई थी। 1964 में वेंगर्ट। एंड्रियास ग्रिवैंक के अनुसार, 1960 के दशक के उत्तरार्ध से रिवर्स संचय का सुझाव दिया गया है, लेकिन आविष्कारक अज्ञात है। सेप्पो लिन्नैनमा ने 1976 में रिवर्स एक्युमुलेशन प्रकाशित किया।

आगे संचय
आगे संचय एडी में, व्यक्ति पहले स्वतंत्र चर को ठीक करता है जिसके संबंध में भेदभाव किया जाता है और प्रत्येक उप-अभिव्यक्ति (गणित) के व्युत्पन्न की पुनरावर्ती गणना करता है। कलम और कागज की गणना में, इसमें श्रृंखला नियम में आंतरिक कार्यों के व्युत्पन्न को बार-बार प्रतिस्थापित करना शामिल है: $$\begin{align} \frac{\partial y}{\partial x} &= \frac{\partial y}{\partial w_{n-1}} \frac{\partial w_{n-1}}{\partial x} \\[6pt] &= \frac{\partial y}{\partial w_{n-1}} \left(\frac{\partial w_{n-1}}{\partial w_{n-2}} \frac{\partial w_{n-2}}{\partial x}\right) \\[6pt] &= \frac{\partial y}{\partial w_{n-1}} \left(\frac{\partial w_{n-1}}{\partial w_{n-2}} \left(\frac{\partial w_{n-2}}{\partial w_{n-3}} \frac{\partial w_{n-3}}{\partial x}\right)\right) \\[6pt] &= \cdots \end{align}$$ इसे जैकोबियन मैट्रिक्स और निर्धारकों के मैट्रिक्स उत्पाद के रूप में कई चर के लिए सामान्यीकृत किया जा सकता है।

रिवर्स संचय की तुलना में, आगे संचय स्वाभाविक और लागू करना आसान है क्योंकि व्युत्पन्न जानकारी का प्रवाह मूल्यांकन के क्रम के साथ मेल खाता है। प्रत्येक चर $$w_i$$ इसके व्युत्पन्न के साथ संवर्धित किया गया है $$\dot w_i$$ (संख्यात्मक मान के रूप में संग्रहीत, प्रतीकात्मक अभिव्यक्ति नहीं), $$\dot w_i = \frac{\partial w_i}{\partial x}$$ जैसा कि बिंदु द्वारा दर्शाया गया है। फिर मूल्यांकन चरणों के साथ डेरिवेटिव की गणना की जाती है और श्रृंखला नियम के माध्यम से अन्य डेरिवेटिव के साथ जोड़ा जाता है।

श्रृंखला नियम का उपयोग करना, यदि $$w_i$$ कम्प्यूटेशनल ग्राफ़ में पूर्ववर्ती हैं:
 * $$\dot w_i = \sum_{j \in \{\text{predecessors of i}\}} \frac{\partial w_i}{\partial w_j} \dot w_j$$

उदाहरण के तौर पर, फ़ंक्शन पर विचार करें: $$\begin{align} y &= f(x_1, x_2) \\ &= x_1 x_2 + \sin x_1 \\ &= w_1 w_2 + \sin w_1 \\ &= w_3 + w_4 \\ &= w_5 \end{align}$$ स्पष्टता के लिए, व्यक्तिगत उप-अभिव्यक्तियों को चर के साथ लेबल किया गया है $$w_i$$.

जिस स्वतंत्र चर का विभेदीकरण किया जाता है उसका चुनाव बीज मूल्यों को प्रभावित करता है $ẇ_{1}$ और $ẇ_{2}$. के संबंध में इस फ़ंक्शन के व्युत्पन्न में रुचि दी गई है $x_{1}$, बीज मान इस पर सेट किया जाना चाहिए: $$\begin{align} \dot w_1 = \frac{\partial w_1}{\partial x_1} = \frac{\partial x_1}{\partial x_1} = 1 \\ \dot w_2 = \frac{\partial w_2}{\partial x_1} = \frac{\partial x_2}{\partial x_1} = 0 \end{align}$$ बीज मान सेट होने के साथ, मान दिखाए गए अनुसार श्रृंखला नियम का उपयोग करके प्रसारित होते हैं। चित्र 2 एक कम्प्यूटेशनल ग्राफ़ के रूप में इस प्रक्रिया का सचित्र चित्रण दिखाता है।
 * {| class="wikitable"

!Operations to compute value !!Operations to compute derivative इस उदाहरण फ़ंक्शन के ग्रेडियेंट  की गणना करने के लिए, जिसकी न केवल आवश्यकता है $$\tfrac{\partial y}{\partial x_1}$$ लेकिन $$\tfrac{\partial y}{\partial x_2}$$, बीज मानों का उपयोग करके कम्प्यूटेशनल ग्राफ़ पर एक अतिरिक्त स्वीप किया जाता है $$\dot w_1 = 0; \dot w_2 = 1$$.
 * $$w_1 = x_1$$ || $$\dot w_1 = 1$$ (seed)
 * $$w_2 = x_2$$ || $$\dot w_2 = 0$$ (seed)
 * $$w_3 = w_1 \cdot w_2$$ || $$\dot w_3 = w_2 \cdot \dot w_1 + w_1 \cdot \dot w_2$$
 * $$w_4 = \sin w_1$$ || $$\dot w_4 = \cos w_1 \cdot \dot w_1$$
 * $$w_5 = w_3 + w_4$$ || $$\dot w_5 = 1 \cdot \dot w_3 + 1 \cdot \dot w_4$$
 * }
 * $$w_4 = \sin w_1$$ || $$\dot w_4 = \cos w_1 \cdot \dot w_1$$
 * $$w_5 = w_3 + w_4$$ || $$\dot w_5 = 1 \cdot \dot w_3 + 1 \cdot \dot w_4$$
 * }
 * $$w_5 = w_3 + w_4$$ || $$\dot w_5 = 1 \cdot \dot w_3 + 1 \cdot \dot w_4$$
 * }

छद्म कोड
फॉरवर्ड संचयन एक पास में फ़ंक्शन और व्युत्पन्न (लेकिन केवल एक स्वतंत्र चर के लिए) की गणना करता है। संबंधित विधि कॉल एक चर V के संबंध में अभिव्यक्ति Z को प्राप्त करने की अपेक्षा करती है। विधि मूल्यांकन किए गए फ़ंक्शन और इसकी व्युत्पत्ति की एक जोड़ी लौटाती है। यह विधि एक चर तक पहुंचने तक अभिव्यक्ति वृक्ष को पुनरावर्ती रूप से पार करती है। यदि इस चर के संबंध में व्युत्पन्न का अनुरोध किया जाता है, तो इसका व्युत्पन्न 1, 0 है अन्यथा। फिर आंशिक फ़ंक्शन के साथ-साथ आंशिक व्युत्पन्न का मूल्यांकन किया जाता है।  टपल<फ्लोट,फ्लोट> eval(अभिव्यक्ति Z, अभिव्यक्ति V) { यदि चर(Z) है यदि (Z=V) वापसी {valueOf(Z),1}; अन्यथा वापसी {valueOf(Z),0}; अन्यथा यदि (Z = X + Y)     {x,x'} = eval(X,V); {y,y'} = eval(Y,V); वापसी {x+y, x'+y'}; अन्यथा यदि (Z = X - Y)     {x,x'} = eval(X,V); {y,y'} = eval(Y,V); वापसी {x-y, x'-y'}; अन्यथा यदि (Z = X * Y)     {x,x'} = eval(X,V); {y,y'} = eval(Y,V); वापसी {x*y, x'*y+x*y'}; } 

सी++
 टाइपडिफ स्ट्रक्चर डुअल {फ्लोट वी,डी; } दोहरा; संरचना अभिव्यक्ति { वर्चुअल डुअल इवल(std::map &vals, Expression *v) { return {0,0}; }; }; स्ट्रक्चर प्लस: सार्वजनिक अभिव्यक्ति { अभिव्यक्ति *ए, *बी; प्लस(अभिव्यक्ति *ए, अभिव्यक्ति *बी): ए{ए}, बी{बी} {} दोहरी eval(std::map &vals, अभिव्यक्ति *v) { दोहरी x=a->eval(vals,v); दोहरी y=b->eval(vals,v); वापसी {x.v+y.v, x.d+y.d}; } }; संरचना मूल: सार्वजनिक अभिव्यक्ति { अभिव्यक्ति *ए, *बी; मूल(अभिव्यक्ति *ए, अभिव्यक्ति *बी): ए{ए}, बी{बी} {} दोहरी eval(std::map &vals, अभिव्यक्ति *v) { दोहरी x=a->eval(vals,v); दोहरी y=b->eval(vals,v); वापसी {x.v*y.v, x.d*y.v+x.v*y.d}; } }; संरचना वार: सार्वजनिक अभिव्यक्ति { एसटीडी::स्ट्रिंग एस; Var(std::string s) : s{s} {} दोहरी eval(std::map &vals, अभिव्यक्ति *v) { वापसी {vals[s], this==v?1.0f:0.0f}; } }; मुख्य प्रवेश बिंदु { std::map dict; dict.insert(std::pair( x ,1)); dict.insert(std::pair( y ,-3)); dict.insert(std::pair( z ,4)); वर x( x ), y( y ), z( z ); मूल m1(&x,&z); मूल m2(&y,&z); प्लस p(&m1,&m2); // x*z+y*z std::cout << x: << p.eval(dict,&x).d <<, << y: << p.eval(dict,&y).d << , << z: << p. eval(dict,&z).d << std::endl; वापसी 0; } 
 * 1) शामिल करें
 * 2) शामिल <स्ट्रिंग>
 * 3) शामिल <मानचित्र>

विपरीत संचय
फ़ाइल:AutoDiff.webp|अंगूठा रिवर्स संचय एडी में, विभेदित किए जाने वाले आश्रित चर को तय किया जाता है और व्युत्पन्न की गणना प्रत्येक उप-अभिव्यक्ति (गणित) के संबंध में पुनरावर्ती रूप से की जाती है। कलम और कागज की गणना में, बाहरी कार्यों के व्युत्पन्न को श्रृंखला नियम में बार-बार प्रतिस्थापित किया जाता है: $$\begin{align} \frac{\partial y}{\partial x} &= \frac{\partial y}{\partial w_1} \frac{\partial w_1}{\partial x}\\ &= \left(\frac{\partial y}{\partial w_2} \frac{\partial w_2}{\partial w_1}\right) \frac{\partial w_1}{\partial x}\\ &= \left(\left(\frac{\partial y}{\partial w_3} \frac{\partial w_3}{\partial w_2}\right) \frac{\partial w_2}{\partial w_1}\right) \frac{\partial w_1}{\partial x}\\ &= \cdots \end{align}$$ विपरीत संचय में, ब्याज की मात्रा सहायक होती है, जिसे एक बार से दर्शाया जाता है $$\bar w_i$$; यह उपअभिव्यक्ति के संबंध में चुने गए आश्रित चर का व्युत्पन्न है $$w_i$$: $$\bar w_i = \frac{\partial y}{\partial w_i}$$ श्रृंखला नियम का उपयोग करना, यदि $$w_i$$ कम्प्यूटेशनल ग्राफ़ में उत्तराधिकारी हैं:
 * $$\bar w_i = \sum_{j \in \{\text{successors of i}\}} \bar w_j \frac{\partial w_j}{\partial w_i}$$

रिवर्स संचय श्रृंखला नियम को बाहर से अंदर तक, या चित्र 3 में कम्प्यूटेशनल ग्राफ के मामले में, ऊपर से नीचे तक पार करता है। उदाहरण फ़ंक्शन स्केलर-मूल्यवान है, और इस प्रकार व्युत्पन्न गणना के लिए केवल एक बीज है, और (दो-घटक) ग्रेडिएंट की गणना करने के लिए कम्प्यूटेशनल ग्राफ के केवल एक स्वीप की आवश्यकता होती है। फॉरवर्ड संचय की तुलना में यह केवल स्पेस-टाइम ट्रेडऑफ़ है, लेकिन रिवर्स संचय के लिए मध्यवर्ती चर के भंडारण की आवश्यकता होती है $w_{i}$ साथ ही वे निर्देश जो उन्हें डेटा संरचना में उत्पादित करते हैं जिन्हें टेप या वेंगर्ट सूची के रूप में जाना जाता है (हालाँकि, वेंगर्ट ने आगे संचय प्रकाशित किया, न कि रिवर्स संचय ), जो कम्प्यूटेशनल ग्राफ़ बड़ा होने पर महत्वपूर्ण मेमोरी का उपभोग कर सकता है। मध्यवर्ती चरों के केवल एक उपसमूह को संग्रहीत करके और फिर मूल्यांकन को दोहराकर आवश्यक कार्य चरों का पुनर्निर्माण करके इसे कुछ हद तक कम किया जा सकता है, एक तकनीक जिसे पुनर्भौतिकीकरण के रूप में जाना जाता है। चेकपॉइंटिंग योजना का उपयोग मध्यस्थ राज्यों को बचाने के लिए भी किया जाता है।

रिवर्स संचय का उपयोग करके व्युत्पन्न की गणना करने के संचालन को नीचे दी गई तालिका में दिखाया गया है (उल्टे क्रम पर ध्यान दें):

किसी गणना के डेटा प्रवाह ग्राफ़ को उसकी मूल गणना के ग्रेडिएंट की गणना करने के लिए हेरफेर किया जा सकता है। यह प्रत्येक प्राइमल नोड के लिए एक एडजॉइंट नोड जोड़कर किया जाता है, जो एडजॉइंट किनारों से जुड़ा होता है जो कि प्राइमल किनारों के समानांतर होता है लेकिन विपरीत दिशा में बहता है। निकटवर्ती ग्राफ में नोड्स प्रारंभिक में नोड्स द्वारा गणना किए गए कार्यों के डेरिवेटिव द्वारा गुणा का प्रतिनिधित्व करते हैं। उदाहरण के लिए, मूल में जोड़ के कारण जोड़ में फैनआउट हो जाता है; मूल में फ़ैनआउट के कारण जोड़ में वृद्धि होती है; एक यूनरी ऑपरेशन फ़ंक्शन $y = f(x)$ मौलिक कारणों में $x̄ = ȳ f′(x)$ सन्निकट में; वगैरह।

छद्म कोड
रिवर्स संचय के लिए दो पास की आवश्यकता होती है: फॉरवर्ड पास में, फ़ंक्शन का पहले मूल्यांकन किया जाता है और आंशिक परिणाम कैश किए जाते हैं। रिवर्स पास में, आंशिक डेरिवेटिव की गणना की जाती है और पहले से प्राप्त मूल्य को बैकप्रोपेगेट किया जाता है। संबंधित विधि कॉल से अपेक्षा की जाती है कि अभिव्यक्ति Z को व्युत्पन्न किया जाए और मूल अभिव्यक्ति के व्युत्पन्न मूल्य के साथ बीजित किया जाए। शीर्ष अभिव्यक्ति के लिए, Z, Z के संबंध में व्युत्पन्न, यह 1 है। विधि अभिव्यक्ति वृक्ष को पुनरावर्ती रूप से पार करती है जब तक कि एक चर तक नहीं पहुंच जाता है और व्युत्पन्न अभिव्यक्ति में वर्तमान बीज मान जोड़ता है।  शून्य व्युत्पन्न (अभिव्यक्ति Z, फ्लोट बीज) { यदि (Z = X + Y)     व्युत्पन्न (एक्स, बीज); व्युत्पन्न (वाई, बीज); अन्यथा यदि (Z = X - Y)     व्युत्पन्न (एक्स, बीज); व्युत्पन्न(Y,-बीज); अन्यथा यदि (Z = X * Y)     व्युत्पन्न(X,valueOf(X)*seed); व्युत्पन्न(Y,seed*valueOf(Y)); अन्यथा यदि वैरिएबल (जेड) है आंशिकDerivativeOf(Z) += बीज; } 

पायथन
टेप के बिना पायथन (प्रोग्रामिंग भाषा) में कार्यान्वयन।

सी++
 संरचना अभिव्यक्ति { आगे तैरना = 0, पीछे = 0; वर्चुअल फ्लोट eval(std::map &vals) = 0; आभासी शून्य वापस(फ्लोट बीज) {पिछड़ा+=बीज; }; }; स्ट्रक्चर प्लस: सार्वजनिक अभिव्यक्ति { अभिव्यक्ति *ए, *बी; प्लस(अभिव्यक्ति *ए, अभिव्यक्ति *बी): ए{ए}, बी{बी} {} फ्लोट eval(std::map &vals) { पिछड़ा=0; फॉरवर्ड=a->eval(vals); फॉरवर्ड+=बी->ईवल(वैल); आगे लौटें; }  शून्य वापस (फ्लोट बीज) { अभिव्यक्ति::वापस(बीज); ए->वापस(बीज); बी->वापस(बीज); } }; संरचना मूल: सार्वजनिक अभिव्यक्ति { अभिव्यक्ति *ए, *बी; मूल(अभिव्यक्ति *ए, अभिव्यक्ति *बी): ए{ए}, बी{बी} {} फ्लोट eval(std::map &vals) { पिछड़ा=0; फॉरवर्ड=a->eval(vals); आगे*=b->eval(vals); आगे लौटें; }  शून्य वापस (फ्लोट बीज) { अभिव्यक्ति::वापस(बीज); a->पीछे(बीज * b->आगे); बी->पीछे(बीज * ए->आगे); } }; संरचना वार: सार्वजनिक अभिव्यक्ति { एसटीडी::स्ट्रिंग एस; Var(std::string s) : s{s} {} फ्लोट eval(std::map &vals) { फॉरवर्ड=वैल्स[एस]; पिछड़ा=0; आगे लौटें; }  शून्य वापस (फ्लोट बीज) { अभिव्यक्ति::वापस(बीज); std::cout << s << : << पिछड़ा <<, ; } }; मुख्य प्रवेश बिंदु { std::map dict; dict.insert(std::pair<std::string,int>( x ,1)); dict.insert(std::pair<std::string,int>( y ,-3)); dict.insert(std::pair<std::string,int>( z ,4)); वर x( x ), y( y ), z( z ); मूल m1(&x,&z); मूल m2(&y,&z); प्लस p(&m1,&m2); // x*z+y*z std::cout << p.eval(dict) << std::endl; पी.बैक(1); std::cout << std::endl; वापसी 0; } </सिंटैक्सहाइलाइट>
 * 1) शामिल करें
 * 2) शामिल <स्ट्रिंग>
 * 3) शामिल <मानचित्र>

आगे और पीछे संचय से परे
आगे और पीछे संचय श्रृंखला नियम को पार करने के केवल दो (चरम) तरीके हैं। संपूर्ण जैकोबियन की गणना करने की समस्या $f : R^{n} → R^{m}$ अंकगणितीय परिचालनों की न्यूनतम संख्या के साथ इष्टतम जैकोबियन संचय (ओजेए) समस्या के रूप में जाना जाता है, जो एनपी-पूर्ण है। इस प्रमाण के केंद्र में यह विचार है कि ग्राफ़ के किनारों को लेबल करने वाले स्थानीय आंशिक भागों के बीच बीजगणितीय निर्भरताएँ मौजूद हो सकती हैं। विशेष रूप से, दो या दो से अधिक एज लेबल को बराबर के रूप में पहचाना जा सकता है। समस्या की जटिलता अभी भी खुली है यदि यह मान लिया जाए कि सभी किनारे के लेबल अद्वितीय और बीजगणितीय रूप से स्वतंत्र हैं।

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

हर नंबर बदलें $$\,x$$ संख्या के साथ $$x + x'\varepsilon$$, कहाँ $$x'$$ एक वास्तविक संख्या है, लेकिन $$\varepsilon$$ संपत्ति के साथ एक अमूर्त संख्या है $$\varepsilon^2=0$$ (एक अतिसूक्ष्म; सहज अतिसूक्ष्म विश्लेषण देखें)। इसके प्रयोग से ही नियमित अंकगणित मिलता है $$\begin{align} (x + x'\varepsilon) + (y + y'\varepsilon) &= x + y + (x' + y')\varepsilon \\ (x + x'\varepsilon) - (y + y'\varepsilon) &= x - y + (x' - y')\varepsilon \\ (x + x'\varepsilon) \cdot (y + y'\varepsilon) &= xy + xy'\varepsilon + yx'\varepsilon + x'y'\varepsilon^2 = xy + (x y' + yx')\varepsilon \\ (x + x'\varepsilon) / (y + y'\varepsilon) &= (x/y + x'\varepsilon/y) / (1 + y'\varepsilon/y) = (x/y + x'\varepsilon/y) \cdot (1 - y'\varepsilon/y) = x/y + (x'/y - xy'/y^2)\varepsilon \end{align}$$ का उपयोग करते हुए $$(1 + y'\varepsilon/y) \cdot (1 - y'\varepsilon/y) = 1$$.

अब, इस संवर्धित अंकगणित में बहुपदों की गणना की जा सकती है। अगर $$P(x) = p_0 + p_1 x + p_2x^2 + \cdots + p_n x^n$$, तब $$\begin{align} P(x + x'\varepsilon) &= p_0 + p_1(x + x'\varepsilon) + \cdots + p_n (x + x'\varepsilon)^n \\ &= p_0 + p_1 x + \cdots + p_n x^n + p_1x'\varepsilon + 2p_2xx'\varepsilon + \cdots + np_n x^{n-1} x'\varepsilon \\ &= P(x) + P^{(1)}(x)x'\varepsilon \end{align}$$ कहाँ $$P^{(1)}$$ के व्युत्पन्न को दर्शाता है $$P$$ इसके पहले तर्क के संबंध में, और $$x'$$, जिसे बीज कहा जाता है, मनमाने ढंग से चुना जा सकता है।

नए अंकगणित में क्रमित जोड़े, लिखे गए तत्व शामिल हैं $$\langle x, x' \rangle$$, जैसा कि ऊपर वर्णित है, पहले घटक पर सामान्य अंकगणित और दूसरे घटक पर प्रथम क्रम विभेदन अंकगणित के साथ। बहुपदों पर उपरोक्त परिणामों को विश्लेषणात्मक कार्यों तक विस्तारित करने से बुनियादी अंकगणित और नए अंकगणित के लिए कुछ मानक कार्यों की एक सूची मिलती है: $$\begin{align} \left\langle u,u'\right\rangle + \left\langle v,v'\right\rangle &= \left\langle u + v, u' + v' \right\rangle \\ \left\langle u,u'\right\rangle - \left\langle v,v'\right\rangle &= \left\langle u - v, u' - v' \right\rangle \\ \left\langle u,u'\right\rangle * \left\langle v,v'\right\rangle &= \left\langle u v, u'v + uv' \right\rangle \\ \left\langle u,u'\right\rangle / \left\langle v,v'\right\rangle &= \left\langle \frac{u}{v}, \frac{u'v - uv'}{v^2} \right\rangle \quad ( v\ne 0) \\ \sin\left\langle u,u'\right\rangle &= \left\langle \sin(u), u' \cos(u) \right\rangle \\ \cos\left\langle u,u'\right\rangle &= \left\langle \cos(u), -u' \sin(u) \right\rangle \\ \exp\left\langle u,u'\right\rangle &= \left\langle \exp u, u' \exp u \right\rangle \\ \log\left\langle u,u'\right\rangle &= \left\langle \log(u), u'/u \right\rangle \quad (u>0) \\ \left\langle u,u'\right\rangle^k &= \left\langle u^k, u' k u^{k - 1} \right\rangle \quad (u \ne 0) \\ \left| \left\langle u,u'\right\rangle \right| &= \left\langle \left| u \right|, u' \operatorname{sign} u \right\rangle \quad (u \ne 0) \end{align}$$ और सामान्य तौर पर आदिम कार्य के लिए $$g$$, $$g(\langle u,u' \rangle, \langle v,v' \rangle ) = \langle g(u,v) , g_u(u,v) u' + g_v(u,v) v' \rangle$$ कहाँ $$g_u$$ और $$g_v$$ के व्युत्पन्न हैं $$g$$ क्रमशः इसके पहले और दूसरे तर्क के संबंध में।

जब एक द्विआधारी बुनियादी अंकगणितीय ऑपरेशन को मिश्रित तर्कों पर लागू किया जाता है - जोड़ी $$\langle u, u' \rangle$$ और वास्तविक संख्या $$c$$-वास्तविक संख्या को पहले उठाया जाता है $$\langle c, 0 \rangle$$. किसी फ़ंक्शन का व्युत्पन्न $$f : \R\to\R$$ बिंदु पर $$x_0$$ अब गणना करके पाया जाता है $$f(\langle x_0, 1 \rangle)$$ उपरोक्त अंकगणित का उपयोग करते हुए, जो देता है $$\langle f ( x_0 ), f' ( x_0 ) \rangle $$ परिणाम के रूप में।

वेक्टर तर्क और कार्य
दिशात्मक व्युत्पन्न ऑपरेटर को अपनाकर बहुभिन्नरूपी कार्यों को अविभाज्य कार्यों के समान दक्षता और तंत्र के साथ संभाला जा सकता है। अर्थात्, यदि यह गणना करने के लिए पर्याप्त है $$y' = \nabla f(x)\cdot x'$$, दिशात्मक व्युत्पन्न $$y' \in \R^m$$ का $$f:\R^n\to\R^m$$ पर $$x \in \R^n$$ दिशा में $$x' \in \R^n$$ के रूप में गणना की जा सकती है $$(\langle y_1,y'_1\rangle, \ldots, \langle y_m,y'_m\rangle) = f(\langle x_1,x'_1\rangle, \ldots, \langle x_n,x'_n\rangle)$$ उपरोक्त के समान अंकगणित का उपयोग करना। यदि के सभी तत्व $$\nabla f$$ तो वांछित हैं $$n$$ फ़ंक्शन मूल्यांकन की आवश्यकता है. ध्यान दें कि कई अनुकूलन अनुप्रयोगों में, दिशात्मक व्युत्पन्न वास्तव में पर्याप्त है।

उच्च क्रम और कई चर
उपरोक्त अंकगणित को दूसरे क्रम और बहुभिन्नरूपी कार्यों के उच्च डेरिवेटिव की गणना करने के लिए सामान्यीकृत किया जा सकता है। हालाँकि, अंकगणित के नियम तेजी से जटिल हो जाते हैं: जटिलता उच्चतम व्युत्पन्न डिग्री में द्विघात है। इसके बजाय, काटे गए टेलर श्रृंखला बीजगणित का उपयोग किया जा सकता है। परिणामी अंकगणित, सामान्यीकृत दोहरी संख्याओं पर परिभाषित, कार्यों का उपयोग करके कुशल गणना की अनुमति देता है जैसे कि वे एक डेटा प्रकार थे। एक बार किसी फलन का टेलर बहुपद ज्ञात हो जाने पर, अवकलज आसानी से निकाले जा सकते हैं।

कार्यान्वयन
फॉरवर्ड-मोड AD को प्रोग्राम की एक गैर-मानक व्याख्या द्वारा कार्यान्वित किया जाता है जिसमें वास्तविक संख्याओं को दोहरी संख्याओं द्वारा प्रतिस्थापित किया जाता है, स्थिरांक को शून्य ईपीएसलॉन गुणांक के साथ दोहरी संख्याओं में उठाया जाता है, और संख्यात्मक प्राइमेटिव्स को दोहरी संख्याओं पर काम करने के लिए उठाया जाता है। यह गैरमानक व्याख्या आम तौर पर दो रणनीतियों में से एक का उपयोग करके कार्यान्वित की जाती है: स्रोत कोड परिवर्तन या ऑपरेटर ओवरलोडिंग।

स्रोत कोड परिवर्तन (एससीटी)
किसी फ़ंक्शन के स्रोत कोड को स्वचालित रूप से उत्पन्न स्रोत कोड द्वारा प्रतिस्थापित किया जाता है जिसमें मूल निर्देशों के साथ जुड़े डेरिवेटिव की गणना के लिए विवरण शामिल होते हैं।

स्रोत कोड परिवर्तन को सभी प्रोग्रामिंग भाषाओं के लिए लागू किया जा सकता है, और कंपाइलर के लिए संकलन समय अनुकूलन करना भी आसान है। हालाँकि, AD टूल का कार्यान्वयन स्वयं अधिक कठिन है और निर्माण प्रणाली अधिक जटिल है। स्रोत कोड परिवर्तन टूल के उदाहरणों में Enzyme टूल शामिल है एलएलवीएम/एमएलआईआर के लिए (और इस प्रकार सी/सी++, जूलिया, रस्ट, फोरट्रान, पायथन, आदि को अलग करता है) और टेपेनेड टूल फोरट्रान/सी के लिए.

ऑपरेटर ओवरलोडिंग (ओओ)
ऑपरेटर ओवरलोडिंग कर रहा है के कारण स्रोत कोड का समर्थन करने वाली भाषा में लिखे जाने की संभावना है। ऊपर दर्शाए गए संवर्धित अंकगणित को पूरा करने के लिए वास्तविक संख्याओं और प्राथमिक गणितीय परिचालनों के लिए वस्तुओं को अतिभारित किया जाना चाहिए। फ़ंक्शन को विभेदित करने के लिए मूल स्रोत कोड में संचालन के रूप या अनुक्रम में कोई बदलाव की आवश्यकता नहीं होती है, लेकिन अक्सर ओवरलोडिंग का समर्थन करने के लिए संख्याओं और वैक्टरों के लिए बुनियादी डेटा प्रकारों में बदलाव की आवश्यकता होती है और अक्सर विशेष फ़्लैगिंग संचालन को सम्मिलित करना भी शामिल होता है। प्रत्येक लूप पर अंतर्निहित ऑपरेटर ओवरहेड ओवरलोडिंग के कारण, यह दृष्टिकोण आमतौर पर कमजोर गति प्रदर्शन को प्रदर्शित करता है।

C++ में स्वचालित विभेदन के ऑपरेटर-ओवरलोडिंग कार्यान्वयन के उदाहरण हैं:
 * निपुण (सी++ लाइब्रेरी)
 * एनएजी की डीसीओ लाइब्रेरी
 * स्टेन (सॉफ्टवेयर) पुस्तकालय
 * XAD ओपन-सोर्स टूल

ऑपरेटर ओवरलोडिंग और स्रोत कोड परिवर्तन
ओवरलोडेड ऑपरेटर्स का उपयोग वैल्यूएशन ग्राफ़ निकालने के लिए किया जा सकता है, जिसके बाद रन-टाइम पर प्राइमल फ़ंक्शन के एडी-संस्करण की स्वचालित पीढ़ी होती है। क्लासिक OO AAD के विपरीत, ऐसा AD-फ़ंक्शन एक पुनरावृत्ति से अगले में नहीं बदलता है। इसलिए प्रति Xi नमूने में कोई OO या टेप व्याख्या रन-टाइम ओवरहेड है।

रनटाइम पर एडी-फ़ंक्शन उत्पन्न होने के साथ, इसे प्रोग्राम की वर्तमान स्थिति को ध्यान में रखने और कुछ मानों की पूर्व-गणना करने के लिए अनुकूलित किया जा सकता है। इसके अलावा, इसे उपयोगकर्ता डेटा के 4(8)-दोगुने टुकड़ों (AVX2\AVX512 गति x4-x8) को संसाधित करने के लिए देशी सीपीयू वेक्टराइजेशन का लगातार उपयोग करने के तरीके से उत्पन्न किया जा सकता है। मल्टीथ्रेडिंग को ध्यान में रखते हुए, इस तरह के दृष्टिकोण से पारंपरिक AAD टूल की तुलना में ऑर्डर 8 × #Cores का अंतिम त्वरण हो सकता है। GitHub पर एक संदर्भ कार्यान्वयन उपलब्ध है।

यह भी देखें

 * विभिन्न प्रोग्रामिंग

बाहरी संबंध

 * www.autodiff.org, An "entry site to everything you want to know about automatic differentiation"
 * Automatic Differentiation of Parallel OpenMP Programs
 * Automatic Differentiation, C++ Templates and Photogrammetry
 * Automatic Differentiation, Operator Overloading Approach
 * Compute analytic derivatives of any Fortran77, Fortran95, or C program through a web-based interface Automatic Differentiation of Fortran programs
 * Description and example code for forward Automatic Differentiation in Scala
 * finmath-lib stochastic automatic differentiation, Automatic differentiation for random variables (Java implementation of the stochastic automatic differentiation).
 * Adjoint Algorithmic Differentiation: Calibration and Implicit Function Theorem
 * C++ Template-based automatic differentiation article and implementation
 * Tangent Source-to-Source Debuggable Derivatives
 * Exact First- and Second-Order Greeks by Algorithmic Differentiation
 * Adjoint Algorithmic Differentiation of a GPU Accelerated Application
 * Adjoint Methods in Computational Finance Software Tool Support for Algorithmic Differentiationop
 * More than a Thousand Fold Speed Up for xVA Pricing Calculations with Intel Xeon Scalable Processors