TensorFlow - 求导

从函数开始说明TensorFlow是如何求导的

flyfish

函数
定义域是关于输入的

上域是关于输出的

值域实际上是上域的一个子集

上域是可能输出的集合

值域则是实际输出的集合.

[a, b] 这种形式表示的区间我们称作闭区间.
(a, b) 这种形式表示的区间称作开区间.
(a, b] 包括 b, 但不包括 a.像这样的区间称作半开区间.

反函数
如果f(x)=y,那么 f1(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));

极限

limx2f(x)=1

读作“当x趋于2,f(x)的极限等于1”。
平局速率
平均速率是行使距离除以行驶时间
v=s/t

瞬时速度

v=change in schange in t=ΔsΔt

Δt=t1t0
由于t1非常靠近t0,两时刻的差值 h

v=Δf(t)Δt=f(t+h)f(t)(t+h)(t)=f(t+h)f(t)h

v=limΔt0Δ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

f(a)=limh0f(a+h)f(a)h=limh0(a+h)2a2h=limh0a2+2ah+h2a2h=limh02ah+h2h=limh0(2a+h)=2a

链式求导(Chain rule) 复合函数

在函数的复合中描述
(fg)=(fg)g

当z=f(y), y=g(x)

dzdx=dzdydydx=f(y)g(x)=f(g(x))g(x).

利用公式1求导

f(x)=limh0f(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)=limh0f(x+h)f(xh)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

f(10+ε)=(10+ε)2=100+210ε+ε2=100+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+vu,uv,v=uv,uvu,uv,v=uv,uv+uvu,u/v,v=uv,uvuvv2(v0)sinu,u=sin(u),ucos(u)cosu,u=cos(u),usin(u)expu,u=expu,uexpulogu,u=log(u),u/u(u>0)u,uk=uk,kuk1u(u0)u,u=|u|,usignu(u0)"

根据上述式子一共实现了以下几种函数的一阶导数
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的偏导用以下符号表示

fx, fx, xf, Dxf, D1f, xf, or fx.

假设
f(x,y)=y3x2 .

要计算 fx(x,y)
我们只是把y看成是一个固定的数,然后计算对x的普通导数

fx(x,y)
g(x)=b3x2 类似

dfdx(x)=2b3x

替换字母之后
fx(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+2e+3+3e
=4+5e

结果
dfdx=5

计算 dfdy

f(1,3+e)=12+1(3+e)

=1+3+e

=4+e
结果
dfdy=1

你可能感兴趣的:(深度学习,TensorFlow)