从函数开始说明TensorFlow是如何求导的
flyfish
函数
定义域是关于输入的
上域是关于输出的
值域实际上是上域的一个子集
上域是可能输出的集合
值域则是实际输出的集合.
[a, b] 这种形式表示的区间我们称作闭区间.
(a, b) 这种形式表示的区间称作开区间.
(a, b] 包括 b, 但不包括 a.像这样的区间称作半开区间.
反函数
如果f(x)=y,那么 f−1(y)=x
变换f−1就像是f的撤销按钮。
类似Ctrl+Z的撤销操作
函数的复合(Function composition)
对于函数 f(x)=cos(x2) ,我们令 g(x)=x2 ,h(x)=cos(x),那么f(x)=h(g(x)),也可表示为f=h 。g,这里的圈是复合符号,表示“与……的复合”,即f是g与h的复合。
读法
The notation g ∘ f is read as
“g circle f “,
“g round f “,
“g composed with f “,
“g after f “,
“g following f “,
“g of f”,
“g on f “.
用C++表达类似
有两个函数g和f
float x, y, z;
// ...
y = g(x);
z = f(y);
或者
z = f(g(x));
极限
limx→2f(x)=1
读作“当x趋于2,f(x)的极限等于1”。
平局速率
平均速率是行使距离除以行驶时间
v=s/t
瞬时速度
v=change in schange in t=ΔsΔt
Δt=t1−t0
由于t1非常靠近t0,两时刻的差值 h
v=Δf(t)Δt=f(t+h)−f(t)(t+h)−(t)=f(t+h)−f(t)h
v=limΔt→0ΔsΔt=dsdt
解释
Distinction between speed and velocity(速率和速度之间的区别)
Speed describes only how fast an object is moving, whereas velocity gives both how fast it is and in which direction the object is moving.
速率只描述物体运动的快慢,而速度则给出物体运动的快慢和方向。
求导例子 f(a)=a2
链式求导(Chain rule) 复合函数
在函数的复合中描述
(f∘g)′=(f′∘g)⋅g′
当z=f(y), y=g(x)
dzdx=dzdy⋅dydx=f′(y)g′(x)=f′(g(x))g′(x).
利用公式1求导
f′(x)=limh→0f(x+h)−f(x)h
int main()
{
double h = 0.000001;
double x = 10.0;
double v = ((x + h) * (x + h) - x * x) / h;
std::cout << std::setprecision(20) << v << std::endl;
system("pause");
return 0;
}
利用公式2求导
f′(x)=limh→0f(x+h)−f(x−h)2h
int main()
{
double h = 0.000001;
double x = 10.0;
double v = ((x + h) * (x + h) - (x-h) * (x-h)) /(2*h);
std::cout << std::setprecision(20) << v << std::endl;
system("pause");
return 0;
}
dual number
线性代数中dual number是实数的扩展。单位 ε ,它的平方是0
类似复数
复数(complex number)
x=a+bi(i2=−1)
其中a,b是任意实数,b称为复数x的虚部,i称为虚数单位
dual number
x=x+xε(ε2=0)
以 f(x)=x2 ,x=10 为例求导
f(10) = 100,df/dx(10) = 20
代码如下
typedef struct
{
double real;
double epsilon;
} DualNumber;
DualNumber DerivationPower(DualNumber d, double e)
{
DualNumber dual = { std::pow(d.real, e), d.epsilon * e * std::pow(d.real, e - 1) };
return dual;
}
int main()
{
double x = 10;
DualNumber v = { x,1 };//variable
DualNumber d1 = DerivationPower(v, 2);
std::cout << d1.real <<std::endl << d1.epsilon<<std::endl;
system("pause");
return 0;
}
⟨u,u′⟩+⟨v,v′⟩=⟨u+v,u′+v′⟩⟨u,u′⟩−⟨v,v′⟩=⟨u−v,u′−v′⟩⟨u,u′⟩∗⟨v,v′⟩=⟨uv,u′v+uv′⟩⟨u,u′⟩/⟨v,v′⟩=⟨uv,u′v−uv′v2⟩(v≠0)sin⟨u,u′⟩=⟨sin(u),u′cos(u)⟩cos⟨u,u′⟩=⟨cos(u),−u′sin(u)⟩exp⟨u,u′⟩=⟨expu,u′expu⟩log⟨u,u′⟩=⟨log(u),u′/u⟩(u>0)⟨u,u′⟩k=⟨uk,kuk−1u′⟩(u≠0)∣∣⟨u,u′⟩∣∣=⟨|u|,u′signu⟩(u≠0)"
根据上述式子一共实现了以下几种函数的一阶导数
Add, Sub, Mul, Div, Sin, Cos, Exp, Log, Power, Abs
real是函数的值,epsilon是函数的一阶导数
typedef struct
{
double real;
double epsilon;
} DualNumber;
DualNumber Dual(double r, double e)
{
DualNumber epsilon = { r, e };
return epsilon;
}
DualNumber SetConstant(double r)
{
return Dual(r, 0);
}
DualNumber SetVariable(double d)
{
return Dual(d, 1);
}
DualNumber Add(DualNumber U, DualNumber V)
{
return Dual(U.real + V.real, U.epsilon + V.epsilon);
}
DualNumber Sub(DualNumber U, DualNumber V)
{
return Dual(U.real - V.real, U.epsilon - V.epsilon);
}
DualNumber Mul(DualNumber U, DualNumber V)
{
return Dual(U.real * V.real, U.real * V.epsilon + U.epsilon * V.real);
}
DualNumber Div(DualNumber U, DualNumber V)
{
if (V.real == 0) return { 0,0 };
return Dual(U.real / V.real, (U.epsilon - (U.real / V.real) * V.epsilon) / V.real);
}
DualNumber Sin(DualNumber U)
{
return Dual(sin(U.real), U.epsilon * cos(U.real));
}
DualNumber Cos(DualNumber U)
{
return Dual(cos(U.real), -U.epsilon * sin(U.real));
}
DualNumber Exp(DualNumber U)
{
return Dual(exp(U.real), U.epsilon * exp(U.real));
}
DualNumber Log(DualNumber U)
{
assert(U.real > 0);
return Dual(log(U.real), U.epsilon / U.real);
}
DualNumber Power(DualNumber U, double e)
{
return Dual(pow(U.real, e), U.epsilon * e * pow(U.real, e - 1));
}
DualNumber Abs(DualNumber U)
{
assert(U.real != 0);
return Dual(abs(U.real), U.epsilon * ((U.real > 0) ? 1 : -1));
}
int main(void) {
double x = 10;
DualNumber v = SetVariable(x);
DualNumber d1 = Power(v, 2);
std::cout << d1.real <"pause");
return 0;
}
偏导
偏导数的符号∂
一个多变量函数的偏导数,就是它关于其中一个变量的导数而保持其他变量不变,函数f(x, y, …) 关于变量x的偏导用以下符号表示
假设
f(x,y)=y3x2 .
要计算 ∂f∂x(x,y)
我们只是把y看成是一个固定的数,然后计算对x的普通导数
∂f∂x(x,y) 与
g(x)=b3x2 类似
dfdx(x)=2b3x
替换字母之后
∂f∂x(x,y)=2y3x
dual number 计算偏导示例
f(x,y)=x2+xy
f(1,3)
计算 dfdx
f(1+e,y)=(1+e)2+3(1+e)
=1+2∗e+3+3∗e
=4+5∗e
结果
dfdx=5
计算 dfdy
f(1,3+e)=12+1∗(3+e)
=1+3+e
=4+e
结果
dfdy=1