目录
在机器学习中,会遇到拉普拉斯方程问题。如
$$-\Delta u=f$$
这里 是一个关于多变量的函数,譬如 . 那么
$$\Delta u = \frac{\partial^2 u}{\partial x^2}+\frac{\partial^2 u}{\partial y^2}$$.
在tensorflow中单值输出关于多元变量的高阶导数是如何计算的呢? 本文为我的个人测试,如有不合适的地方,欢迎指正.
-
一阶偏导的计算
例一
$$u = 3(x^3+y^3)-6(x^2+y^2)$$
我们很显然知道:.那么程序结果呢?
def test_gradient0():
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x1 = tf.Variable(3, dtype=tf.float32, name='x_1')
x2 = tf.Variable(1, dtype=tf.float32, name='x_2')
y = 3 * (tf.pow(x1, 3)+tf.pow(x2, 3)) - 6*(tf.pow(x1, 2)+tf.pow(x2, 2))
dx1, dx2 = tf.gradients(y, [x1, x2]) # 一阶导数
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx11, dx22 = sess.run([dx1, dx2], feed_dict={x1: 1, x2: 1})
print(dx11)
print(dx22)
print('函数y在x_1=1, x_2=1处的关于x_1的一阶导数:dx1=', dx11, ',关于x_2的一阶导数:dx2=', dx22, sep='')
输出结果:
函数y在x_1=1, x_2=1处的关于x_1的一阶导数:dx1=-3.0,关于x_2的一阶导数:dx2=-3.0
例二
$$u = 3(x^3+y^3)-6(x^2+y^2)+xy$$
我们很显然知道:.那么程序结果呢?
def test_gradient1():
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x1 = tf.Variable(3, dtype=tf.float32, name='x_1')
x2 = tf.Variable(1, dtype=tf.float32, name='x_2')
y = 3 * (tf.pow(x1, 3)+tf.pow(x2, 3)) - 6*(tf.pow(x1, 2)+tf.pow(x2, 2)) + x1*x2
dx1, dx2 = tf.gradients(y, [x1, x2]) # 一阶导数
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx11, dx22 = sess.run([dx1, dx2], feed_dict={x1: 1, x2: 1})
print('函数y在x_1=1, x_2=1处的关于x_1的一阶导数:dx1=', dx11, ',关于x_2的一阶导数:dx2=', dx22, sep='')
输出结果:
函数y在x_1=1, x_2=1处的关于x_1的一阶导数:dx1=-2.0,关于x_2的一阶导数:dx2=-2.0
二阶偏导的计算
$$u = 3(x^3+y^3)-6(x^2+y^2)$$
我们很显然知道:.
def test_gradient2():
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x1 = tf.Variable(3, dtype=tf.float32, name='x_1')
x2 = tf.Variable(1, dtype=tf.float32, name='x_2')
y = 3 * (tf.pow(x1, 3)+tf.pow(x2, 3)) - 6*(tf.pow(x1, 2)+tf.pow(x2, 2))
dx1, dx2 = tf.gradients(y, [x1, x2]) # 一阶导数
ddx1, ddx2 = tf.gradients([dx1, dx2], [x1, x2]) # 二阶导数
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
ddx11, ddx22 = sess.run([ddx1, ddx2], feed_dict={x1: 1, x2: 1})
print('函数y在x_1=1, x_2=1处的关于x_1的一阶导数:dx1=', ddx11, ',关于x_2的一阶导数:dx2=', ddx22, sep='')
函数y在x_1=1, x_2=1处的关于x_1的一阶导数:dx1=6.0,关于x_2的一阶导数:dx2=6.0
$$u = 3(x^3+y^3)-6(x^2+y^2)+xy$$
我们很显然知道:.
def test_gradient3():
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x1 = tf.Variable(3, dtype=tf.float32, name='x_1')
x2 = tf.Variable(1, dtype=tf.float32, name='x_2')
y = 3 * (tf.pow(x1, 3)+tf.pow(x2, 3)) - 6*(tf.pow(x1, 2)+tf.pow(x2, 2))+x*y
dx1, dx2 = tf.gradients(y, [x1, x2]) # 一阶导数
ddx1, ddx2 = tf.gradients([dx1, dx2], [x1, x2]) # 二阶导数
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
ddx11, ddx22 = sess.run([ddx1, ddx2], feed_dict={x1: 1, x2: 1})
print('函数y在x_1=1, x_2=1处的关于x_1的二阶导数:ddx1=', ddx11, ',关于x_2的二阶导数:ddx2=', ddx22, sep='')
$$u = 3(x^3+y^3)-6(x^2+y^2)+x^2y^2$$
我们很显然知道:.
def test_gradient4():
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x1 = tf.Variable(3, dtype=tf.float32, name='x_1')
x2 = tf.Variable(1, dtype=tf.float32, name='x_2')
y = 3 * (tf.pow(x1, 3)+tf.pow(x2, 3)) - 6*(tf.pow(x1, 2)+tf.pow(x2, 2)) + (x1**2)*(x2**2)
dx1, dx2 = tf.gradients(y, [x1, x2]) # 一阶导数
ddx1, ddx2 = tf.gradients([dx1, dx2], [x1, x2]) # 二阶导数
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
ddx11, ddx22 = sess.run([ddx1, ddx2], feed_dict={x1: 1, x2: 1})
print('函数y在x_1=1, x_2=1处的关于x_1的二阶导数:ddx1=', ddx11, ',关于x_2的二阶导数:ddx2=', ddx22, sep='')
划重点的来了,以上的变量都是独立的。如果变量是向量呢?是什么样子的。我们首先看一下,函数对向量的求导机制. 这里 .那么
参考:机器学习中常用的矩阵求导公式 机器学习中常用的矩阵求导公式_jason的专栏-CSDN博客_常用矩阵求导
矩阵求导、几种重要的矩阵及常用的矩阵求导公式_青萍之末的博客-CSDN博客_矩阵求导
这里 代表激活函数,如Relu。并且
u的形式为(假设计算过程中值均为正值)
def test_gradient6():
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x = tf.Variable([[0.1], [0.1]], dtype=tf.float32, name='x')
W1 = np.array([[1, 2], [3, 4]], dtype=np.float32)
B1 = np.array([[1], [3]], dtype=np.float32)
W2 = np.array([[1, 2], [3, 4]], dtype=np.float32)
B2 = np.array([[2], [4]], dtype=np.float32)
W3 = np.array([[2, 1]], dtype=np.float32)
B3 = np.array([[2]], dtype=np.float32)
y = tf.nn.relu(tf.matmul(W1, x) + B1)
y = tf.nn.relu(tf.matmul(W2, y) + B2)
y = tf.nn.relu(tf.matmul(W3, y) + B3)
dx = tf.gradients(y, x) # 一阶导数
ddx = tf.gradients(dx, x) # 二阶导数
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx1, ddx1 = sess.run([dx, ddx], feed_dict={x: [[1], [1]]})
print('函数y在x=[1,1]处的一阶导数:dx=', dx1, ',关于x的二阶导数:ddx=', ddx1, sep='')
函数y在x=[1,1]处的一阶导数:dx=[array([[29.],
[42.]], dtype=float32)],关于x的二阶导数:ddx=[array([[0.],
[0.]], dtype=float32)]
向量对向量求导。
首先看一些概念。
例子
$$u = 3z^3-6z^2+z, z=(x,y)^T$$
我么有
记 。那么
这里需要注意, 是一个关于 的常量,所以是标量对向量求导。结果应该是, 分开的。最后排列成超向量或者矩阵都可以。如:
,
def test_gradient5():
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x = tf.Variable([[0.1], [0.1]], dtype=tf.float32, name='x')
y = 3*tf.pow(x, 3) - 6 * tf.pow(x, 2) + x
dx = tf.gradients(y, x) # 一阶导数
ddx = tf.gradients(dx, x) # 二阶导数
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx1, ddx1 = sess.run([dx, ddx], feed_dict={x: [[1], [1]]})
print('函数y在x=[1;1]处的一阶导数:dx=', dx1, ',关于x的二阶导数:ddx=', ddx1, sep='')
运行结果. 函数y在x=[1;1]处的一阶导数:dx=[array([[-2.],
[-2.]], dtype=float32)],关于x的二阶导数:ddx=[array([[6.],
[6.]], dtype=float32)]
这里有个问题,tensorflow中向量对向量求导(行对行,列对列)貌似有问题。留作慢慢研究。。。。。。。
下面看看如何实现 拉普拉斯 的二阶偏导。我们以简单的函数为例:
一阶导数为
二阶导数为
def test_gradient7():
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x = tf.Variable([[0.1], [0.1]], dtype=tf.float32, name='x')
W1 = np.array([[1, 2], [3, 4]], dtype=np.float32)
W2 = np.array([[1, 1]], dtype=np.float32)
y = x*tf.matmul(W1, x)
y = tf.matmul(W2, y)
Dx = tf.gradients(y, x)[0] # 一阶导数
Dx1 = tf.gather(Dx, [0], axis=0) # 将一阶导数关于x1的部分取出来
Dx2 = tf.gather(Dx, [1], axis=0) # 将一阶导数关于x2的部分取出来
DDx1 = tf.gradients(Dx1, x) # 对取出来额部分关于x求导,就可以得到关于x的二阶导数的向量
DDx1 = tf.squeeze(DDx1)
DDx1 = tf.gather(DDx1, [0]) # 将一阶导数关于x2的部分取出来
DDx2 = tf.gradients(Dx2, x) # 对取出来额部分关于x求导,就可以得到关于x的二阶导数的向量
DDx2 = tf.squeeze(DDx2)
DDx2 = tf.gather(DDx2, [1]) # 将一阶导数关于x1的部分取出来
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx, dx1, dx2, ddx1, ddx2 = sess.run([Dx, Dx1, Dx2, DDx1, DDx2], feed_dict={x: [[1], [1]]})
print('dx:', dx)
print('dx1:', dx1)
print('dx2:', dx2)
print('ddx1:', ddx1)
print('ddx2:', ddx2)
运行结果:
dx:
[[ 7.]
[13.]]
dx1: [[7.]]
dx2: [[13.]]
ddx1: [2.]
ddx2: [8.]
求二阶导数的另一种方式
def test_gradient8():
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x1 = tf.Variable([[0.1]], dtype=tf.float32, name='x1')
x2 = tf.Variable([[0.1]], dtype=tf.float32, name='x1')
x = tf.concat([x1, x2], axis=0)
W1 = np.array([[1, 2], [3, 4]], dtype=np.float32)
W2 = np.array([[1, 1]], dtype=np.float32)
y = x*tf.matmul(W1, x)
y = tf.matmul(W2, y)
Dx = tf.gradients(y, x)[0] # 一阶导数
Dx1 = tf.gradients(y, x1)[0]
DDx1 = tf.gradients(Dx1, x1)[0] # 对取出来额部分关于x求导,就可以得到关于x的二阶导数的向量
Dx2 = tf.gradients(y, x2)[0]
DDx2 = tf.gradients(Dx2, x2)[0] # 对取出来额部分关于x求导,就可以得到关于x的二阶导数的向量
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx, dx1, dx2, ddx1, ddx2 = sess.run([Dx, Dx1, Dx2, DDx1, DDx2], feed_dict={x: [[1], [1]]})
print('dx:\n', dx)
print('dx1:', dx1)
print('dx2:', dx2)
print('ddx1:', ddx1)
print('ddx2:', ddx2)
结果:
dx:
[[ 7.]
[13.]]
dx1: [[7.]]
dx2: [[13.]]
ddx1: [[2.]]
ddx2: [[8.]]
对于多维输入,结果也类似。代码如下:
def test_gradient9():
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x = tf.placeholder(tf.float32, name='X_it', shape=[2, 3])
# x = tf.Variable([[0.1, 0.1, 0,1], [0.1, 0.1, 0,1]], dtype=tf.float32, name='x')
W1 = np.array([[1, 2], [3, 4]], dtype=np.float32)
W2 = np.array([[1, 1]], dtype=np.float32)
y = x*tf.matmul(W1, x)
y = tf.matmul(W2, y)
Dx = tf.gradients(y, x)[0] # 一阶导数
Dx1 = tf.gather(Dx, [0], axis=0) # 将一阶导数关于x1的部分取出来
Dx2 = tf.gather(Dx, [1], axis=0) # 将一阶导数关于x2的部分取出来
DDx1 = tf.gradients(Dx1, x) # 对取出来额部分关于x求导,就可以得到关于x的二阶导数的向量
DDx1 = tf.squeeze(DDx1)
DDx1 = tf.gather(DDx1, [0], axis=0) # 将一阶导数关于x2的部分取出来
DDx2 = tf.gradients(Dx2, x) # 对取出来额部分关于x求导,就可以得到关于x的二阶导数的向量
DDx2 = tf.squeeze(DDx2)
DDx2 = tf.gather(DDx2, [1], axis=0) # 将一阶导数关于x1的部分取出来
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx, dx1, dx2, ddx1, ddx2 = sess.run([Dx, Dx1, Dx2, DDx1, DDx2], feed_dict={x: [[1, 1, 1], [1, 1, 1]]})
print('dx:\n', dx)
print('dx1:', dx1)
print('dx2:', dx2)
print('ddx1:', ddx1)
print('ddx2:', ddx2)
运行结果:
dx:
[[ 7. 7. 7.]
[13. 13. 13.]]
dx1: [[7. 7. 7.]]
dx2: [[13. 13. 13.]]
ddx1: [[2. 2. 2.]]
ddx2: [[8. 8. 8.]]
接下来,我们看如何求混合偏导数。=5
def test_gradient11(batch_size=3):
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
# 变量
x = tf.placeholder(tf.float32, name='X_it', shape=[None, 2])
W1 = np.array([[1, 2], [3, 4]], dtype=np.float32)
W2 = np.array([[1], [1]], dtype=np.float32)
y = x*tf.matmul(x, W1)
y = tf.matmul(y, W2)
Dx = tf.gradients(y, x)[0] # 一阶导数
DDx = tf.gradients(Dx, x)[0] # 二阶导数
Dx1 = tf.gather(Dx, [0], axis=-1) # 将一阶导数关于x1的部分取出来
Dx2 = tf.gather(Dx, [1], axis=-1) # 将一阶导数关于x2的部分取出来
DDx1x2 = tf.gradients(Dx1, x)[0] # 对取出来额部分关于x求导,就可以得到关于x的二阶导数的向量
DDx2x1 = tf.gradients(Dx2, x)[0]
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx, ddx, dx1, dx2, ddxy, ddyx= sess.run([Dx, DDx, Dx1, Dx2, DDx1x2, DDx2x1], feed_dict={x: [[1, 1], [1, 1], [1, 1]]})
print('dx:\n', dx)
print('ddx:\n', ddx)
print('dx1:\n', dx1)
print('dx2:\n', dx2)
print('ddxy:\n', ddxy)
print('ddyx:\n', ddyx)
运行结果:(根据之前的工作,很容易提取出来混合偏导的结果)
dx:
[[ 7. 13.]
[ 7. 13.]
[ 7. 13.]]
ddx:
[[ 7. 13.]
[ 7. 13.]
[ 7. 13.]]
dx1:
[[7.]
[7.]
[7.]]
dx2:
[[13.]
[13.]
[13.]]
ddxy:
[[2. 5.]
[2. 5.]
[2. 5.]]
ddyx:
[[5. 8.]
[5. 8.]
[5. 8.]]
最新的策略:当要解决的问题,维数比较大的时候,用以上方法计算高阶导数,计算量比较大。下面为一种新的计算高阶导数的方法。请参考:https://ins.sjtu.edu.cn/people/xuzhiqin/pub/laplaciancode.pdf
看一个例子:
代码中:
def test_gradient14(batch_size=3):
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
xit_unstack = []
# 注意类型必须均为浮点型,并且一致
x_it = tf.placeholder(tf.float32, name='X_it', shape=[batch_size, 2])
# 将x_it解耦,对解耦的扩维或者转置为[-1,1]的形状。然后拼接,这样x_it的分量就分开了,
# 解耦后的变量作为神经网络的输入,然后进行计算
unstack_xit = tf.unstack(x_it, axis=-1)
for x_tmp in unstack_xit:
xit_unstack.append(tf.expand_dims(x_tmp, axis=-1))
_x_it = tf.concat(xit_unstack, axis=-1)
W1 = np.array([[1, 2], [3, 4]], dtype=np.float32)
W2 = np.array([[1], [1]], dtype=np.float32)
ee = tf.matmul(_x_it, W1)
y1 = _x_it * tf.matmul(_x_it, W1)
y = tf.matmul(y1, W2)
Dx = tf.gradients(y, _x_it)[0] # 关于x=(x1,x2)一阶导数
Dx1 = tf.gather(Dx, [0], axis=-1) # 将一阶导数关于x1的部分取出来
Dx2 = tf.gather(Dx, [1], axis=-1) # 将一阶导数关于x2的部分取出来
DDx1 = tf.gradients(Dx1, xit_unstack[0])[0] # 关于x=(x1,x2)二阶导数
DDx2 = tf.gradients(Dx2, xit_unstack[1])[0] # 关于x=(x1,x2)二阶导数
DDx1x2 = tf.gradients(Dx1, xit_unstack[1])[0] # 关于x=(x1,x2)二阶偏导数
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx, dx1, dx2, ddx1, ddx2, ddx1x2= sess.run([Dx, Dx1, Dx2, DDx1, DDx2, DDx1x2], feed_dict={x_it: [[1, 1], [1, 1], [1, 1]]})
print('dx:\n', dx)
print('dx1:\n', dx1)
print('dx2:\n', dx2)
print('ddx1:\n', ddx1)
print('ddx2:\n', ddx2)
print('ddx1x2:\n', ddx1x2)
dx:
[array([[ 7., 13.],
[ 7., 13.],
[ 7., 13.]], dtype=float32)]
dx1:
[[[7.]
[7.]
[7.]]]
dx2:
[[[13.]
[13.]
[13.]]]
ddx1:
[[2.]
[2.]
[2.]]
ddx2:
[[8.]
[8.]
[8.]]
ddx1x2:
[[5.]
[5.]
[5.]]
下面看三阶导数的计算
def test_gradient15(batch_size=3):
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
xit_unstack = []
# 注意类型必须均为浮点型,并且一致
x_it = tf.placeholder(tf.float32, name='X_it', shape=[batch_size, 2])
# 将x_it解耦,对解耦的扩维或者转置为[-1,1]的形状。然后拼接,这样x_it的分量就分开了,
# 解耦后的变量作为神经网络的输入,然后进行计算
unstack_xit = tf.unstack(x_it, axis=-1)
for x_tmp in unstack_xit:
xit_unstack.append(tf.expand_dims(x_tmp, axis=-1))
_x_it = tf.concat(xit_unstack, axis=-1)
W1 = np.array([[1, 2], [3, 4]], dtype=np.float32)
W2 = np.array([[1], [1]], dtype=np.float32)
y1 = _x_it * tf.matmul(_x_it, W1)
y2 = _x_it * y1
y = tf.matmul(y2, W2)
Dx = tf.gradients(y, _x_it)[0] # 关于x=(x1,x2)一阶导数
DDx = tf.gradients(Dx, _x_it)[0] # 关于x=(x1,x2)一阶导数
Dx1 = tf.gather(Dx, [0], axis=-1) # 将一阶导数关于x1的部分取出来
Dx2 = tf.gather(Dx, [1], axis=-1) # 将一阶导数关于x2的部分取出来
DDx1 = tf.gradients(Dx1, xit_unstack[0])[0] # 关于x=(x1,x2)二阶导数
DDx2 = tf.gradients(Dx2, xit_unstack[1])[0] # 关于x=(x1,x2)二阶导数
DDx1x2 = tf.gradients(Dx1, xit_unstack[1])[0] # 关于x=(x1,x2)二阶导数
DDDx1 = tf.gradients(DDx1, xit_unstack[0])[0] # 关于x=(x1,x2)三阶导数
DDDx2 = tf.gradients(DDx2, xit_unstack[1])[0] # 关于x=(x1,x2)三阶导数
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx, dx1, dx2, ddx, ddx1, ddx2, ddx1x2, dddx1, dddx2 = sess.run(
[Dx, Dx1, Dx2, DDx, DDx1, DDx2, DDx1x2, DDDx1, DDDx2], feed_dict={x_it: [[1, 1], [1, 1], [1, 1]]})
print('dx:\n', dx)
print('dx1:\n', dx1)
print('dx2:\n', dx2)
print('ddx:\n', ddx)
print('ddx1:\n', ddx1)
print('ddx2:\n', ddx2)
print('ddx1x2:\n', ddx1x2)
print('dddx1:\n', dddx1)
print('dddx2:\n', dddx2)
dx:
[[11. 19.]
[11. 19.]
[11. 19.]]
dx1:
[[11.]
[11.]
[11.]]
dx2:
[[19.]
[19.]
[19.]]
ddx:
[[22. 38.]
[22. 38.]
[22. 38.]]
ddx1:
[[12.]
[12.]
[12.]]
ddx2:
[[28.]
[28.]
[28.]]
ddx1x2:
[[10.]
[10.]
[10.]]
dddx1:
[[6.]
[6.]
[6.]]
dddx2:
[[24.]
[24.]
[24.]]
def test_gradient16(batch_size=3, indim=2):
with tf.device('/gpu:%s' % 0):
with tf.variable_scope('vscope', reuse=tf.AUTO_REUSE):
# 注意类型必须均为浮点型,并且一致
x_it = tf.placeholder(tf.float32, name='X_it', shape=[None, indim])
# 将x_it解耦,对解耦的扩维或者转置为[-1,1]的形状。然后拼接,这样x_it的分量就分开了,
# 解耦后的变量作为神经网络的输入,然后进行计算
unstack_xit = tf.unstack(x_it, axis=-1)
_x_it = tf.stack(unstack_xit, axis=-1)
W1 = np.array([[1, 2], [3, 4]], dtype=np.float32)
W2 = np.array([[1], [1]], dtype=np.float32)
y1 = _x_it * tf.matmul(_x_it, W1)
y2 = _x_it * y1
y = tf.matmul(y2, W2)
Dx = tf.gradients(y, _x_it)[0] # 关于x=(x1,x2)一阶导数
DDx = tf.gradients(Dx, _x_it)[0] # 关于x=(x1,x2)一阶导数
Dx1 = tf.gather(Dx, [0], axis=-1) # 将一阶导数关于x1的部分取出来
Dx2 = tf.gather(Dx, [1], axis=-1) # 将一阶导数关于x2的部分取出来
DDx1 = tf.reshape(tf.gradients(Dx1, unstack_xit[0])[0], shape=[-1,1]) # 关于x=(x1,x2)二阶导数
DDx2 = tf.reshape(tf.gradients(Dx2, unstack_xit[1])[0], shape=[-1,1]) # 关于x=(x1,x2)二阶导数
DDx1x2 = tf.reshape(tf.gradients(Dx1, unstack_xit[1])[0], shape=[-1,1]) # 关于x=(x1,x2)二阶导数
DDDx1 = tf.reshape(tf.gradients(DDx1, unstack_xit[0])[0], shape=[-1,1]) # 关于x=(x1,x2)二阶导数
DDDx2 = tf.reshape(tf.gradients(DDx2, unstack_xit[1])[0], shape=[-1,1]) # 关于x=(x1,x2)二阶导数
# ConfigProto 加上allow_soft_placement=True就可以使用 gpu 了
config = tf.ConfigProto(allow_soft_placement=True) # 创建sess的时候对sess进行参数配置
config.gpu_options.allow_growth = True # True是让TensorFlow在运行过程中动态申请显存,避免过多的显存占用。
config.allow_soft_placement = True # 当指定的设备不存在时,允许选择一个存在的设备运行。比如gpu不存在,自动降到cpu上运行
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())
dx, dx1, dx2, ddx, ddx1, ddx2, ddx1x2, dddx1, dddx2 = sess.run(
[Dx, Dx1, Dx2, DDx, DDx1, DDx2, DDx1x2, DDDx1, DDDx2], feed_dict={x_it: [[1, 1], [1, 1], [1, 1]]})
print('dx:\n', dx)
print('dx1:\n', dx1)
print('dx2:\n', dx2)
print('ddx:\n', ddx)
print('ddx1:\n', ddx1)
print('ddx2:\n', ddx2)
print('ddx1x2:\n', ddx1x2)
print('dddx1:\n', dddx1)
print('dddx2:\n', dddx2)
dx:
[[11. 19.]
[11. 19.]
[11. 19.]]
dx1:
[[11.]
[11.]
[11.]]
dx2:
[[19.]
[19.]
[19.]]
ddx:
[[22. 38.]
[22. 38.]
[22. 38.]]
ddx1:
[[12.]
[12.]
[12.]]
ddx2:
[[28.]
[28.]
[28.]]
ddx1x2:
[[10.]
[10.]
[10.]]
dddx1:
[[6.]
[6.]
[6.]]
dddx2:
[[24.]
[24.]
[24.]]