什么網(wǎng)站可以看女人唔易做網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃書(shū)1500字
🎯要點(diǎn)
🎯漂移擴(kuò)散方程計(jì)算微分 | 🎯期權(quán)無(wú)風(fēng)險(xiǎn)套利公式計(jì)算微分 | 🎯實(shí)現(xiàn)圖結(jié)構(gòu)算法微分 | 🎯實(shí)現(xiàn)簡(jiǎn)單正向和反向計(jì)算微分 | 🎯實(shí)現(xiàn)簡(jiǎn)單回歸分類(lèi)和生成對(duì)抗網(wǎng)絡(luò)計(jì)算微分 | 🎯幾何網(wǎng)格計(jì)算微分
🍇Python和C++計(jì)算微分正反向累積
算法微分在機(jī)器學(xué)習(xí)領(lǐng)域尤為重要。例如,它允許人們?cè)谏窠?jīng)網(wǎng)絡(luò)中實(shí)現(xiàn)反向傳播,而無(wú)需手動(dòng)計(jì)算導(dǎo)數(shù)。
計(jì)算微分的基礎(chǔ)是復(fù)合函數(shù)偏導(dǎo)數(shù)鏈?zhǔn)椒▌t提供的微分分解。簡(jiǎn)單結(jié)構(gòu)如:
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 \begin{aligned} y & =f(g(h(x)))=f\left(g\left(h\left(w_0\right)\right)\right)=f\left(g\left(w_1\right)\right)=f\left(w_2\right)=w_3 \\ w_0 & =x \\ w_1 & =h\left(w_0\right) \\ w_2 & =g\left(w_1\right) \\ w_3 & =f\left(w_2\right)=y \end{aligned} yw0?w1?w2?w3??=f(g(h(x)))=f(g(h(w0?)))=f(g(w1?))=f(w2?)=w3?=x=h(w0?)=g(w1?)=f(w2?)=y?
由鏈?zhǔn)椒▌t得出:
? y ? x = ? y ? w 2 ? w 2 ? w 1 ? w 1 ? x = ? f ( w 2 ) ? w 2 ? g ( w 1 ) ? w 1 ? h ( w 0 ) ? x \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\left(w_2\right)}{\partial w_2} \frac{\partial g\left(w_1\right)}{\partial w_1} \frac{\partial h\left(w_0\right)}{\partial x} ?x?y?=?w2??y??w1??w2???x?w1??=?w2??f(w2?)??w1??g(w1?)??x?h(w0?)?
通常,存在兩種不同的計(jì)算微分模式:正向累積和反向累積。
正向累積指定從內(nèi)到外遍歷鏈?zhǔn)椒▌t(即首先計(jì)算 ? w 1 / ? x \partial w_1 / \partial x ?w1?/?x,然后計(jì)算 ? w 2 / ? w 1 \partial w_2 / \partial w_1 ?w2?/?w1?,最后計(jì)算 ? y / ? w 2 \partial y / \partial w_2 ?y/?w2? ),而反向累積是從外到內(nèi)的遍歷(首先計(jì)算 ? y / ? w 2 \partial y / \partial w_2 ?y/?w2?,然后計(jì)算 ? w 2 / ? w 1 \partial w_2 / \partial w_1 ?w2?/?w1?,最后計(jì)算 ? w 1 / ? x \partial w_1 / \partial x ?w1?/?x?)。更簡(jiǎn)潔地說(shuō),
正向累積計(jì)算遞歸關(guān)系: ? w i ? x = ? w i ? w i ? 1 ? w i ? 1 ? x \frac{\partial w_i}{\partial x}=\frac{\partial w_i}{\partial w_{i-1}} \frac{\partial w_{i-1}}{\partial x} ?x?wi??=?wi?1??wi???x?wi?1?? 且 w 3 = y w_3=y w3?=y
反向累積計(jì)算遞歸關(guān)系: ? y ? w i = ? y ? w i + 1 ? w i + 1 ? w i \frac{\partial y}{\partial w_i}=\frac{\partial y}{\partial w_{i+1}} \frac{\partial w_{i+1}}{\partial w_i} ?wi??y?=?wi+1??y??wi??wi+1?? 且 w 0 = x w_0=x w0?=x
正向累積在一次傳遞中計(jì)算函數(shù)和導(dǎo)數(shù)(但每個(gè)僅針對(duì)一個(gè)獨(dú)立變量)。相關(guān)方法調(diào)用期望表達(dá)式 Z 相對(duì)于變量 V 導(dǎo)出。該方法返回一對(duì)已求值的函數(shù)及其導(dǎo)數(shù)。該方法遞歸遍歷表達(dá)式樹(shù),直到到達(dá)變量。如果請(qǐng)求相對(duì)于此變量的導(dǎo)數(shù),則其導(dǎo)數(shù)為 1,否則為 0。然后求偏函數(shù)以及偏導(dǎo)數(shù)。
偽代碼:
tuple<float,float> evaluateAndDerive(Expression Z, Variable V) {if isVariable(Z)if (Z = V) return {valueOf(Z), 1};else return {valueOf(Z), 0};else if (Z = A + B){a, a'} = evaluateAndDerive(A, V);{b, b'} = evaluateAndDerive(B, V);return {a + b, a' + b'};else if (Z = A - B){a, a'} = evaluateAndDerive(A, V);{b, b'} = evaluateAndDerive(B, V);return {a - b, a' - b'};else if (Z = A * B){a, a'} = evaluateAndDerive(A, V);{b, b'} = evaluateAndDerive(B, V);return {a * b, b * a' + a * b'};
}
Python實(shí)現(xiàn)正向累積:
class ValueAndPartial:def __init__(self, value, partial):self.value = valueself.partial = partialdef toList(self):return [self.value, self.partial]class Expression:def __add__(self, other):return Plus(self, other)def __mul__(self, other):return Multiply(self, other)class Variable(Expression):def __init__(self, value):self.value = valuedef evaluateAndDerive(self, variable):partial = 1 if self == variable else 0return ValueAndPartial(self.value, partial)class Plus(Expression):def __init__(self, expressionA, expressionB):self.expressionA = expressionAself.expressionB = expressionBdef evaluateAndDerive(self, variable):valueA, partialA = self.expressionA.evaluateAndDerive(variable).toList()valueB, partialB = self.expressionB.evaluateAndDerive(variable).toList()return ValueAndPartial(valueA + valueB, partialA + partialB)class Multiply(Expression):def __init__(self, expressionA, expressionB):self.expressionA = expressionAself.expressionB = expressionBdef evaluateAndDerive(self, variable):valueA, partialA = self.expressionA.evaluateAndDerive(variable).toList()valueB, partialB = self.expressionB.evaluateAndDerive(variable).toList()return ValueAndPartial(valueA * valueB, valueB * partialA + valueA * partialB)# Example: Finding the partials of z = x * (x + y) + y * y at (x, y) = (2, 3)
x = Variable(2)
y = Variable(3)
z = x * (x + y) + y * y
xPartial = z.evaluateAndDerive(x).partial
yPartial = z.evaluateAndDerive(y).partial
print("?z/?x =", xPartial) # Output: ?z/?x = 7
print("?z/?y =", yPartial) # Output: ?z/?y = 8
C++實(shí)現(xiàn)正向累積:
#include <iostream>
struct ValueAndPartial { float value, partial; };
struct Variable;
struct Expression {virtual ValueAndPartial evaluateAndDerive(Variable *variable) = 0;
};
struct Variable: public Expression {float value;Variable(float value): value(value) {}ValueAndPartial evaluateAndDerive(Variable *variable) {float partial = (this == variable) ? 1.0f : 0.0f;return {value, partial};}
};
struct Plus: public Expression {Expression *a, *b;Plus(Expression *a, Expression *b): a(a), b(b) {}ValueAndPartial evaluateAndDerive(Variable *variable) {auto [valueA, partialA] = a->evaluateAndDerive(variable);auto [valueB, partialB] = b->evaluateAndDerive(variable);return {valueA + valueB, partialA + partialB};}
};
struct Multiply: public Expression {Expression *a, *b;Multiply(Expression *a, Expression *b): a(a), b(b) {}ValueAndPartial evaluateAndDerive(Variable *variable) {auto [valueA, partialA] = a->evaluateAndDerive(variable);auto [valueB, partialB] = b->evaluateAndDerive(variable);return {valueA * valueB, valueB * partialA + valueA * partialB};}
};
int main () {// Example: Finding the partials of z = x * (x + y) + y * y at (x, y) = (2, 3)Variable x(2), y(3);Plus p1(&x, &y); Multiply m1(&x, &p1); Multiply m2(&y, &y); Plus z(&m1, &m2);float xPartial = z.evaluateAndDerive(&x).partial;float yPartial = z.evaluateAndDerive(&y).partial;std::cout << "?z/?x = " << xPartial << ", "<< "?z/?y = " << yPartial << std::endl;// Output: ?z/?x = 7, ?z/?y = 8return 0;
}
反向累積需要兩次傳遞:在正向傳遞中,首先評(píng)估函數(shù)并緩存部分結(jié)果。在反向傳遞中,計(jì)算偏導(dǎo)數(shù)并反向傳播先前導(dǎo)出的值。相應(yīng)的方法調(diào)用期望表達(dá)式 Z 被導(dǎo)出,并以父表達(dá)式的導(dǎo)出值為種子。對(duì)于頂部表達(dá)式 Z 相對(duì)于 Z 導(dǎo)出,這是 1。該方法遞歸遍歷表達(dá)式樹(shù),直到到達(dá)變量并將當(dāng)前種子值添加到導(dǎo)數(shù)表達(dá)式。
偽代碼:
void derive(Expression Z, float seed) {if isVariable(Z)partialDerivativeOf(Z) += seed;else if (Z = A + B)derive(A, seed);derive(B, seed);else if (Z = A - B)derive(A, seed);derive(B, -seed);else if (Z = A * B)derive(A, valueOf(B) * seed);derive(B, valueOf(A) * seed);
}
Python實(shí)現(xiàn)反向累積:
class Expression:def __add__(self, other):return Plus(self, other)def __mul__(self, other):return Multiply(self, other)class Variable(Expression):def __init__(self, value):self.value = valueself.partial = 0def evaluate(self):passdef derive(self, seed):self.partial += seedclass Plus(Expression):def __init__(self, expressionA, expressionB):self.expressionA = expressionAself.expressionB = expressionBself.value = Nonedef evaluate(self):self.expressionA.evaluate()self.expressionB.evaluate()self.value = self.expressionA.value + self.expressionB.valuedef derive(self, seed):self.expressionA.derive(seed)self.expressionB.derive(seed)class Multiply(Expression):def __init__(self, expressionA, expressionB):self.expressionA = expressionAself.expressionB = expressionBself.value = Nonedef evaluate(self):self.expressionA.evaluate()self.expressionB.evaluate()self.value = self.expressionA.value * self.expressionB.valuedef derive(self, seed):self.expressionA.derive(self.expressionB.value * seed)self.expressionB.derive(self.expressionA.value * seed)# Example: Finding the partials of z = x * (x + y) + y * y at (x, y) = (2, 3)
x = Variable(2)
y = Variable(3)
z = x * (x + y) + y * y
z.evaluate()
print("z =", z.value) # Output: z = 19
z.derive(1)
print("?z/?x =", x.partial) # Output: ?z/?x = 7
print("?z/?y =", y.partial) # Output: ?z/?y = 8
C++實(shí)現(xiàn)反向累積:
#include <iostream>
struct Expression {float value;virtual void evaluate() = 0;virtual void derive(float seed) = 0;
};
struct Variable: public Expression {float partial;Variable(float _value) {value = _value;partial = 0;}void evaluate() {}void derive(float seed) {partial += seed;}
};
struct Plus: public Expression {Expression *a, *b;Plus(Expression *a, Expression *b): a(a), b(b) {}void evaluate() {a->evaluate();b->evaluate();value = a->value + b->value;}void derive(float seed) {a->derive(seed);b->derive(seed);}
};
struct Multiply: public Expression {Expression *a, *b;Multiply(Expression *a, Expression *b): a(a), b(b) {}void evaluate() {a->evaluate();b->evaluate();value = a->value * b->value;}void derive(float seed) {a->derive(b->value * seed);b->derive(a->value * seed);}
};
int main () {// Example: Finding the partials of z = x * (x + y) + y * y at (x, y) = (2, 3)Variable x(2), y(3);Plus p1(&x, &y); Multiply m1(&x, &p1); Multiply m2(&y, &y); Plus z(&m1, &m2);z.evaluate();std::cout << "z = " << z.value << std::endl;// Output: z = 19z.derive(1);std::cout << "?z/?x = " << x.partial << ", "<< "?z/?y = " << y.partial << std::endl;// Output: ?z/?x = 7, ?z/?y = 8return 0;
}