取id这种事情能不能消失 2024-04-25 18:00 采纳率: 0%
浏览 6

自定义损失函数无梯度

最近在自定义损失函数来优化LSTM模型,想预测未来五天的股票收盘价格,然后根据预测的价格确定这五天什么时候买入,什么时候卖出,比如未来五天是[1,2,3,2,5]那么就是在第一天买入,第三天卖出,在第四天买入,第五天卖出,这样能获得最大的收益。那么根据预测的价格就确定了具体的买入卖出时间,然后根据这个时间在真实价格上进行操作,就计算得到预测的最大收益。那么真实的收益就自然是根据相同的策略在真实价格上进行操作。
具体代码如下

def strategy(fivedayprice):    
    actlist=[]
    label=False
    for i in range(4):
        if fivedayprice[i+1]>fivedayprice[i] and label==False:
            actlist.append(1)
            label=True
            
        elif fivedayprice[i+1]<fivedayprice[i] and label==True:
            actlist.append(-1)
            label=False
            
        elif fivedayprice[i+1]<fivedayprice[i] and label==False:
            actlist.append(0)
            
        elif fivedayprice[i+1]>fivedayprice[i] and label==True:
            actlist.append(0)           
    if  label ==True:
        actlist.append(-1)
    if  label ==False:
        actlist.append(0)
    return actlist

def get_profit(y_pred,y_true):
    labellist=[]
    profitlist=[]
    num=len(y_pred)
    for i in range(num):
        labellist.append(strategy(y_pred[i]))
    for j in range(len(labellist)):
        profit=0
        for n in range(5):
            if labellist[j][n]==1:
                profit=profit-y_true[j][n]
            elif labellist[j][n]==0:
                pass
            elif labellist[j][n]==-1:
                profit =profit+y_true[j][n]
        profitlist.append(profit)
    return profitlist

import tensorflow.keras.backend as K
def profitloss(y_true, y_pred):
    y_true = tf.convert_to_tensor(y_true)
    y_pred = tf.convert_to_tensor(y_pred)
    trueprofitlist = tf.convert_to_tensor(get_profit(y_true, y_true))
    predprofitlist = tf.convert_to_tensor(get_profit(y_pred, y_true))
    loss=K.mean(K.square(trueprofitlist-predprofitlist))           
    return loss

最后在训练模型的时候报错没有梯度

ValueError: No gradients provided for any variable: (['lstm_62/lstm_cell/kernel:0', 'lstm_62/lstm_cell/recurrent_kernel:0', 'lstm_62/lstm_cell/bias:0', 'lstm_63/lstm_cell/kernel:0', 'lstm_63/lstm_cell/recurrent_kernel:0', 'lstm_63/lstm_cell/bias:0', 'dense_62/kernel:0', 'dense_62/bias:0', 'dense_63/kernel:0', 'dense_63/bias:0'],). Provided `grads_and_vars` is ((None, <tf.Variable 'lstm_62/lstm_cell/kernel:0' shape=(9, 512) dtype=float32>), (None, <tf.Variable 'lstm_62/lstm_cell/recurrent_kernel:0' shape=(128, 512) dtype=float32>), (None, <tf.Variable 'lstm_62/lstm_cell/bias:0' shape=(512,) dtype=float32>), (None, <tf.Variable 'lstm_63/lstm_cell/kernel:0' shape=(128, 512) dtype=float32>), (None, <tf.Variable 'lstm_63/lstm_cell/recurrent_kernel:0' shape=(128, 512) dtype=float32>), (None, <tf.Variable 'lstm_63/lstm_cell/bias:0' shape=(512,) dtype=float32>), (None, <tf.Variable 'dense_62/kernel:0' shape=(128, 10) dtype=float32>), (None, <tf.Variable 'dense_62/bias:0' shape=(10,) dtype=float32>), (None, <tf.Variable 'dense_63/kernel:0' shape=(10, 5) dtype=float32>), (None, <tf.Variable 'dense_63/bias:0' shape=(5,) dtype=float32>)).

请问怎么解决啊

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-25 18:01
    关注

    引自免费微信小程序:皆我百晓生

    您遇到的问题在于自定义损失函数profitloss 中的非线性部分(即get_profit 函数)不支持自动微分,导致梯度无法通过反向传播传递给模型的权重。为了解决这个问题,您可以尝试将整个过程转换成 TensorFlow 的张量操作,使得整个流程都是可微分的。这里我会逐步引导您修改代码,使其可以计算梯度并训练模型。

    首先,让我们重构strategy函数,将其转换为TensorFlow操作。我们将创建一个名为compute_actions的函数,它接受预测值和真实值作为输入,并返回动作列表(买卖信号)。

    import tensorflow as tf
    
    @tf.function
    def compute_actions(fivedayprice):
        actions = tf.zeros((tf.shape(fivedayprice)[0], 5), dtype=tf.int32)
    
        # 初始化标记变量
        buy_signal = tf.fill(tf.shape(actions), False)
        sell_signal = tf.fill(tf.shape(actions), False)
    
        # 对于每一步,检查是否满足买入或卖出条件
        for i in tf.range(4):
            next_price = fivedayprice[:, i + 1]
            current_price = fivedayprice[:, i]
    
            # 检查买入条件
            buy_mask = tf.logical_and(next_price > current_price, tf.math.logical_not(buy_signal))
            actions[buy_mask, i] = 1
            buy_signal = tf.math.logical_or(buy_signal, buy_mask)
    
            # 检查卖出条件
            sell_mask = tf.logical_and(next_price < current_price, buy_signal)
            actions[sell_mask, i] = -1
            buy_signal = tf.math.logical_and(tf.math.logical_not(sell_mask), buy_signal)
            
            # 更新sell_signal
            sell_signal = tf.math.logical_or(sell_signal, sell_mask)
    
        # 处理最后一日的卖出情况
        sell_signal = tf.math.logical_or(sell_signal, tf.math.logical_not(buy_signal))
        actions[:, -1] = tf.where(sell_signal, -1, 0)
    
        return actions
    

    接下来,我们重新定义get_profit函数,使用刚刚创建的compute_actions函数,同时确保所有操作都在TensorFlow环境中完成。

    @tf.function
    def get_profit(y_pred, y_true):
        actions = compute_actions(y_pred)
        profits = tf.zeros_like(y_true)
    
        # 计算每个交易日的利润
        for i in tf.range(5):
            profits += tf.reduce_sum(y_true * actions[:, i, tf.newaxis], axis=-1)
    
        return profits
    

    现在我们可以重写profitloss函数,只包含可微分的操作。

    def profitloss(y_true, y_pred):
        y_true = tf.convert_to_tensor(y_true)
        y_pred = tf.convert_to_tensor(y_pred)
    
        trueprofits = get_profit(y_true, y_true)
        predprofits = get_profit(y_pred, y_true)
    
        loss = tf.reduce_mean(tf.square(trueprofits - predprofits))
    
        return loss
    

    现在您的损失函数应该可以正常工作并且支持梯度计算。您可以使用这个新定义的损失函数进行模型训练。例如,如果您有一个名为model的模型,训练过程可能如下所示:

    # 假设X_train、y_train是您的训练数据
    model.compile(optimizer='adam', loss=profitloss)
    model.fit(X_train, y_train, epochs=10, batch_size=32)
    

    这样,模型就可以学习如何最大化预测收益,从而改进其对未来股价的预测。注意,这种方法可能会很复杂且难以收敛,因为它涉及复杂的离散决策。您可能需要调整模型结构和训练参数,以便更好地适应这种类型的损失函数。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 4月25日

悬赏问题

  • ¥60 pb数据库修改或者求完整pb库存系统,需为pb自带数据库
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上
  • ¥20 关于#anlogic#sdram#的问题,如何解决?(关键词-performance)
  • ¥15 相敏解调 matlab
  • ¥15 求lingo代码和思路