tf.model.fit中的惯常损失函数

问题描述

我想使用keras实现具有自定义损失函数的模型。

我将根据以下函数对数据集进行采样进行模拟:

def sampler(N1,N2,N3):
    np.random.seed(42)
    # Sampler #1: PDE domain
    t1 = np.random.uniform(low=T0,high=T,size=[N1,1])
    s1 = np.random.uniform(low=S1,high=S2,1])

    # Sampler #2: boundary condition
    t2 = np.random.uniform(low=T0,size=[N2,1])
    s2 = np.zeros(shape=(N2,1))
    
    # Sampler #3: initial/terminal condition
    t3 = T * np.ones((N3,1)) #Terminal condition
    s3 = np.random.uniform(low=S1,size=[N3,1])
    
    return (t1,s1,t2,s2,t3,s3)

在损失函数中,每个子集(t1,s1)(t2,s2)(t3,s3)应该用唯一的项求值:

def loss(model,t1,x1,x2,x3):
    # Loss term #1: PDE
    V = model(t1,x1)
    V_t = tf.gradients(V,t1)[0]
    V_x = tf.gradients(V,x1)[0]
    V_xx = tf.gradients(V_x,x1)[0]
    f = V_t + r*x1*V_x + 0.5*sigma**2*x1**2*V_xx - r*V 

    L1 = tf.reduce_mean(tf.square(f))

    #Loss term #2: boundary condition
    L2 = tf.reduce_mean(tf.square(model(t2,x2) - 0)) 
    
    # Loss term #3: initial/terminal condition
    L3 = tf.reduce_mean(tf.square(model(t3,x3) - tf.math.maximum(x3-K,0)))

我已经建立了以下参数:

# Set random seeds
np.random.seed(123)
tf.random.set_seed(123)

# Strike price

K = 0.5

# PDE parameters
r = 0.02            # Interest rate
sigma = 0.18        # Volatility

# Time limits
T0 = 0.0 + 1e-10    # Initial time
T  = 1.0            # Terminal time

# Space limits
S1 = 0.0 + 1e-10    # Low boundary
S2 = 1.0            # High boundary

# Number of samples
NS_1 = 1000
NS_2 = 100
NS_3 = 100

模型

class DGM(tf.keras.Model):
    
    def __init__(self,n_layers,n_nodes,dimensions=1):
        """
        Parameters:
            - n_layers:     number of layers
            - n_nodes:      number of nodes in (inner) layers
            - dimensions:   number of spacial dimensions
        """
        super().__init__()
        
        self.n_layers = n_layers

        self.initial_layer = DenseLayer(dimensions + 1,activation="relu")
        self.lstmlikelist = []
        for _ in range(self.n_layers):
            self.lstmlikelist.append(LSTMLikeLayer(dimensions + 1,activation="relu"))
        self.final_layer = DenseLayer(n_nodes,1,activation=None)


    def call(self,t,x):
        X = tf.concat([t,x],1)

        S = self.initial_layer.call(X)
        for i in range(self.n_layers):
            S = self.lstmlikelist[i].call({'S': S,'X': X})
        result = self.final_layer.call(S)

        return result
    


# Neural network layers

class DenseLayer(tf.keras.layers.Layer):
        

  def __init__(self,n_inputs,n_outputs,activation):
      """
      Parameters:
      - n_inputs:     number of inputs
      - n_outputs:    number of outputs
      - activation:   activation function
      """
      super(DenseLayer,self).__init__()
      self.n_inputs = n_inputs
      self.n_outputs = n_outputs
      self.W = self.add_weight(shape=(self.n_inputs,self.n_outputs),initializer='random_normal',trainable=True)
      self.b = self.add_weight(shape=(1,trainable=True)
      self.activation = _get_function(activation)
      
  def call(self,inputs):
        S = tf.add(tf.matmul(inputs,self.W),self.b)
        S = self.activation(S)

        return S



class LSTMLikeLayer(tf.keras.layers.Layer):
    def __init__(self,activation):
        """
        Parameters:
            - n_inputs:     number of inputs
            - n_outputs:    number of outputs
            - activation:   activation function
        """
      
        super(LSTMLikeLayer,self).__init__()

        self.n_outputs = n_outputs
        self.n_inputs = n_inputs


        
        
        self.Uz = self.add_weight("Uz",shape=[self.n_inputs,self.n_outputs])
        self.Ug = self.add_weight("Ug",self.n_outputs])
        self.Ur = self.add_weight("Ur",self.n_outputs])
        self.Uh = self.add_weight("Uh",self.n_outputs])
        self.Wz = self.add_weight("Wz",shape=[self.n_outputs,self.n_outputs])
        self.Wg = self.add_weight("Wg",self.n_outputs])
        self.Wr = self.add_weight("Wr",self.n_outputs])
        self.Wh = self.add_weight("Wh",self.n_outputs])
        self.bz = self.add_weight("bz",shape=[1,self.n_outputs])
        self.bg = self.add_weight("bg",self.n_outputs])
        self.br = self.add_weight("br",self.n_outputs])
        self.bh = self.add_weight("bh",self.n_outputs])
        

        self.activation = _get_function(activation)


    
    def call(self,inputs):
        S = inputs['S']
        X = inputs['X']

        Z = self.activation(tf.add(tf.add(tf.matmul(X,self.Uz),tf.matmul(S,self.Wz)),self.bz))
        G = self.activation(tf.add(tf.add(tf.matmul(X,self.Ug),self.Wg)),self.bg))
        R = self.activation(tf.add(tf.add(tf.matmul(X,self.Ur),self.Wr)),self.br))
        H = self.activation(tf.add(tf.add(tf.matmul(X,self.Uh),tf.matmul(tf.multiply(S,R),self.Wh)),self.bh))
        Snew = tf.add(tf.multiply(tf.subtract(tf.ones_like(G),G),H),tf.multiply(Z,S))

        return Snew



def _get_function(name):
    f = None
    if name == "tanh":
        f = tf.nn.tanh
    elif name == "sigmoid":
        f = tf.nn.sigmoid
    elif name == "relu":
        f = tf.nn.relu
    elif not name:
        f = tf.identity
    
    assert f is not None
    
    return f

这将是我使用示例模型的方法

model = DGM(n_layers=2,n_nodes = 3)
model.compile(
    optimizer = "Adam",loss = loss
)
model.fit()

错误回溯:

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-12-f781fe65eb00> in <module>()
----> 1 model.fit()

2 frames

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in _method_wrapper(self,*args,**kwargs)
    106   def _method_wrapper(self,**kwargs):
    107     if not self._in_multi_worker_mode():  # pylint: disable=protected-access
--> 108       return method(self,**kwargs)
    109 
    110     # Running inside `run_distribute_coordinator` already.

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in fit(self,x,y,batch_size,epochs,verbose,callbacks,validation_split,validation_data,shuffle,class_weight,sample_weight,initial_epoch,steps_per_epoch,validation_steps,validation_batch_size,validation_freq,max_queue_size,workers,use_multiprocessing)
   1030     version_utils.disallow_legacy_graph('Model','fit')
   1031     self._assert_compile_was_called()
-> 1032     self._check_call_args('fit')
   1033     _disallow_inside_tf_function('fit')
   1034 

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in _check_call_args(self,method_name)
   2468           'Models passed to `' + method_name + '` can only have `training` '
   2469           'and the first argument in `call` as positional arguments,'
-> 2470           'found: ' + str(extra_args) + '.')
   2471 
   2472   def _validate_compile(self,optimizer,metrics,**kwargs):

ValueError: Models passed to `fit` can only have `training` and the first argument in `call` as positional arguments,found: ['x'].

现在如何根据已设置的惯常损失函数拟合模型?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)