Keras

时间:2018-04-26 09:56:56

标签: python tensorflow neural-network keras

假设我有一个双变量函数,例如:z = x ^ 2 + y ^ 2。 I learned在Keras上我可以使用Lambda图层计算n阶导数:

def bivariate_function(x, y):

    x2 = Lambda(lambda u: K.pow(u,2))(x)
    y3 = Lambda(lambda u: K.pow(u,2))(y)

    return Add()([x2,y3])

def derivative(y,x):
    return Lambda(lambda u: K.gradients(u[0],u[1]))([y,x])

f = bivariate_function(x,y)
df_dx = grad(f,x)      # 1st derivative wrt to x
df_dy = grad(f,y)      # 1st derivative wrt to y
df_dx2 = grad(df_dx,x) # 2nd derivative wrt to x
df_dy2 = grad(df_dy,y) # 2nd derivative wrt to y

但是,如何将此方法应用于NN输出的导数以及损失函数中的输入?我不能(?)只是简单地将两个输入馈送到密集层(如上面创建的那样)。

例如,尝试使用Input(shape=(2,))作为损失,使用import tensorflow as tf from keras.models import * from keras.layers import * from keras import backend as K def grad(f, x): return Lambda(lambda u: K.gradients(u[0], u[1]), output_shape=[2])([f, x]) def custom_loss(input_tensor,output_tensor): def loss(y_true, y_pred): df1 = grad(output_tensor,input_tensor) df2 = grad(df1,input_tensor) df = tf.add(df1[0,0],df2[0,1]) return df return loss input_tensor = Input(shape=(2,)) hidden_layer = Dense(100, activation='relu')(input_tensor) output_tensor = Dense(1, activation='softplus')(hidden_layer) model = Model(input_tensor, output_tensor) model.compile(loss=custom_loss(input_tensor,output_tensor), optimizer='sgd') xy = np.mgrid[-3.0:3.0:0.1, -3.0:3.0:0.1].reshape(2,-1).T model.fit(x=xy,y=xy, batch_size=10, epochs=100, verbose=2) 作为第一个变量和第二个导数wrt到第二个变量(即d / dx +d²/dy²)的总和,我管理到达这里:

nan

但感觉就像我没有以正确的方式做到这一点。更糟糕的是,在第一个时代之后我才刚刚获得<?php function () { }

1 个答案:

答案 0 :(得分:1)

这里的主要问题是理论上的。

您正在尝试最小化d output_tensor / d x + d 2 output_tensor / d 2 X 即可。您的网络只是线性地组合输入 x -s,但是,relusoftplus激活。嗯,softplus给它带来了一点点扭曲,但它也有一个单调增加的衍生物。因此,为了使导数尽可能小,网络将只使用负权重尽可能地扩大输入,以使导数尽可能小(即,一个非常大的负数),在某些时候达到的 NaN的即可。我已经将第一层减少到5个神经元并将模型运行了2个时期,并且权重变为:

  

( 'dense_1',
  [array([[1.0536456,-0.32706773,0.0072904,0.01986691,0.9854533],
         [-0.3242108,-0.56753945,0.8098554,-0.7545874,0.2716419]],
        D型= FLOAT32),
  阵列([0.01207507,0.09927677,-0.01768671,-0.12874101,0.0210707],         dtype = float32)])

     

( 'dense_2',   [array([[ - 0.4332278],[0.6621602],[ - 0.080802075],[ - 0.5798264],[ - 0.40561703]],
  D型= FLOAT32),
  数组([0.11167384],dtype = float32)])

您可以看到第二层保留负号,第一层保持正数,反之亦然。 (偏差不会得到任何梯度,因为它们对衍生物没有贡献。嗯,由于softplus而不是更多或更少,因此不完全正确。)

所以你必须提出一个与极端参数值没有分歧的损失函数,因为这不会是可训练的,它只会增加权重值,直到它们 NaN

这是我跑的版本:

import tensorflow as tf
from keras.models import *
from keras.layers import *
from keras import backend as K

def grad(f, x):
    return Lambda(lambda u: K.gradients(u[0], u[1]), output_shape=[2])([f, x])

def ngrad(f, x, n):
    if 0 == n:
        return f
    else:
        return Lambda(lambda u: K.gradients(u[0], u[1]), output_shape=[2])([ngrad( f, x, n - 1 ), x])

def custom_loss(input_tensor,output_tensor):
    def loss(y_true, y_pred):

        _df1 = grad(output_tensor,input_tensor)
        df1 = tf.Print( _df1, [ _df1 ], message = "df1" )
        _df2 = grad(df1,input_tensor)
        df2 = tf.Print( _df2, [ _df2 ], message = "df2" )
        df = tf.add(df1,df2)      

        return df
    return loss

input_tensor = Input(shape=(2,))
hidden_layer = Dense(5, activation='softplus')(input_tensor)
output_tensor = Dense(1, activation='softplus')(hidden_layer)

model = Model(input_tensor, output_tensor)
model.compile(loss=custom_loss(input_tensor,output_tensor), optimizer='sgd')

xy = np.mgrid[-3.0:3.0:0.1, -3.0:3.0:0.1].reshape( 2, -1 ).T
#print( xy )
model.fit(x=xy,y=xy, batch_size=10, epochs=2, verbose=2)
for layer in model.layers: print(layer.get_config()['name'], layer.get_weights())