# 2-3,自动微分机制

### 一，利用梯度磁带求导数

``````import tensorflow as tf
import numpy as np

# f(x) = a*x**2 + b*x + c的导数

x = tf.Variable(0.0,name = "x",dtype = tf.float32)
a = tf.constant(1.0)
b = tf.constant(-2.0)
c = tf.constant(1.0)

y = a*tf.pow(x,2) + b*x + c

print(dy_dx)
``````
``````tf.Tensor(-2.0, shape=(), dtype=float32)
``````
``````
``````
``````# 对常量张量也可以求导，需要增加watch

tape.watch([a,b,c])
y = a*tf.pow(x,2) + b*x + c

print(dy_da)
print(dy_dc)

``````
``````tf.Tensor(0.0, shape=(), dtype=float32)
tf.Tensor(1.0, shape=(), dtype=float32)
``````
``````
``````
``````# 可以求二阶导数
y = a*tf.pow(x,2) + b*x + c

print(dy2_dx2)
``````
``````tf.Tensor(2.0, shape=(), dtype=float32)
``````
``````
``````
``````# 可以在autograph中使用

@tf.function
def f(x):
a = tf.constant(1.0)
b = tf.constant(-2.0)
c = tf.constant(1.0)

# 自变量转换成tf.float32
x = tf.cast(x,tf.float32)
tape.watch(x)
y = a*tf.pow(x,2)+b*x+c

return((dy_dx,y))

tf.print(f(tf.constant(0.0)))
tf.print(f(tf.constant(1.0)))
``````
``````(-2, 1)
(0, 0)
``````
``````
``````

### 二，利用梯度磁带和优化器求最小值

``````# 求f(x) = a*x**2 + b*x + c的最小值

x = tf.Variable(0.0,name = "x",dtype = tf.float32)
a = tf.constant(1.0)
b = tf.constant(-2.0)
c = tf.constant(1.0)

optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
for _ in range(1000):
y = a*tf.pow(x,2) + b*x + c

tf.print("y =",y,"; x =",x)
``````
``````y = 0 ; x = 0.999998569
``````
``````
``````
``````# 求f(x) = a*x**2 + b*x + c的最小值
# 使用optimizer.minimize

x = tf.Variable(0.0,name = "x",dtype = tf.float32)

#注意f()无参数
def f():
a = tf.constant(1.0)
b = tf.constant(-2.0)
c = tf.constant(1.0)
y = a*tf.pow(x,2)+b*x+c
return(y)

optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
for _ in range(1000):
optimizer.minimize(f,[x])

tf.print("y =",f(),"; x =",x)
``````
``````y = 0 ; x = 0.999998569
``````
``````
``````
``````# 在autograph中完成最小值求解

x = tf.Variable(0.0,name = "x",dtype = tf.float32)
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)

@tf.function
def minimizef():
a = tf.constant(1.0)
b = tf.constant(-2.0)
c = tf.constant(1.0)

for _ in tf.range(1000): #注意autograph时使用tf.range(1000)而不是range(1000)
y = a*tf.pow(x,2) + b*x + c

y = a*tf.pow(x,2) + b*x + c
return y

tf.print(minimizef())
tf.print(x)
``````
``````0
0.999998569
``````
``````
``````
``````# 在autograph中完成最小值求解
# 使用optimizer.minimize

x = tf.Variable(0.0,name = "x",dtype = tf.float32)
optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)

@tf.function
def f():
a = tf.constant(1.0)
b = tf.constant(-2.0)
c = tf.constant(1.0)
y = a*tf.pow(x,2)+b*x+c
return(y)

@tf.function
def train(epoch):
for _ in tf.range(epoch):
optimizer.minimize(f,[x])
return(f())

tf.print(train(1000))
tf.print(x)

``````
``````0
0.999998569
``````
``````
``````