【问题标题】:Creating a custom piecewise loss function in tf.keras with three variables在 tf.keras 中使用三个变量创建自定义分段损失函数
【发布时间】:2021-05-29 20:52:03
【问题描述】:

我正在使用以下代码尝试使用包含三个变量的自定义分段损失函数来训练模型,但我无法让它工作。我是 tensorflow 的新手,所以如果有人有任何有用的建议。

我想将第三个变量“p”合并到损失函数中,其中“p”随每个 y_true/y_pred 对而变化。 “p”代表原始数据框中的一列。对于这个问题,“p”对于确定模型是否正确至关重要。如果模型正确,我分配零损失,如果模型不正确,我分配损失一。我将损失值相加并除以批次大小以确定该批次的损失值。我想要做的甚至可能吗?如果没有,有什么替代方法可以实现我的预期结果。

import tensorflow as tf
import pandas as pd

from tensorflow.keras import layers

# Read in statistics and outcomes dataframe
df = pd.read_csv(r'gs.csv')
df = df.drop(['prediction_ou'], axis=1)

# Change categorical columns to numeric
df['date'] = pd.Categorical(df['date'])
df['date'] = df.date.cat.codes

df['away_team'] = pd.Categorical(df['away_team'])
df['away_team'] = df.away_team.cat.codes

df['away_conf'] = pd.Categorical(df['away_conf'])
df['away_conf'] = df.away_conf.cat.codes

df['home_team'] = pd.Categorical(df['home_team'])
df['home_team'] = df.home_team.cat.codes

df['home_conf'] = pd.Categorical(df['home_conf'])
df['home_conf'] = df.home_conf.cat.codes

# Create target data
target = df.pop('actual_spread')

# Create tensorflow dataset
dataset = tf.data.Dataset.from_tensor_slices((df.values, target.values))

# Shuffle and batch
train_dataset = dataset.shuffle(len(df)).batch(32)

# Model
model = tf.keras.Sequential([
  layers.Dense(128, activation='relu'),
  layers.Dense(128, activation='relu'),
  layers.Dense(1)
])
  


#  Custom loss function  
def cbb_loss_higher(p):
    
    def cbb_loss(y_true,y_pred):
        c=0
        
        for i in range(len(y_true)):
            if ((y_true[i]>p[i]) and (y_pred[i]<p[i])) or ((y_true[i]<p[i]) and (y_pred[i]>p[i])):
                c+=1
            elif ((y_true[i]>p[i]) and (y_pred[i]>p[i])) or ((y_true[i]<p[i]) and (y_pred[i]<p[i])):
                c+=0
            else:
                c+=0.5
                
        cbb_loss = c/len(y_true)
        return cbb_loss
   

model.compile(optimizer='adam',
          loss=cbb_loss_higher(p = df.prediction_spread),
          metrics=['accuracy'])

model.fit(train_dataset,
          epochs=10)

当代码按原样运行时,我收到以下错误:

File "cbb_ml.py", line 129, in <module>
    epochs=10)
...
ValueError: No gradients provided for any variable: ['dense/kernel:0', 'dense/bias:0', 'dense_1/kernel:0', 'dense_1/bias:0', 'dense_2/kernel:0', 'dense_2/bias:0'].

【问题讨论】:

  • 这能回答你的问题吗? Gradients of Logical Operators in Tensorflow
  • 您的问题是您的自定义损失函数不可微。尝试为您的数据创建标签。将您的三个案例映射到标签(0、1、2)。然后让您的网络在密集层中输出 3 个单位,并使用 cross_entropy 作为损失。

标签: tensorflow keras loss-function


【解决方案1】:

损失函数是 keras 构建的计算图的一部分。您不能在其中使用 python len() 函数。此函数不支持梯度的反向传播。将其替换为tf.shape()

【讨论】:

    【解决方案2】:

    我刚刚稍微重新安排了您的成本函数。因为我没有你的 csv 文件,所以我模拟了一些输入和一个简单的模型。

    p = tf.random.normal(shape=[10])
    
    #  Custom loss function  
    
    def cbb_loss(y_true,y_pred):
            c=0.0
            
            for i in range(len(y_true)):
                if ((y_true[i]>p[i]) and (y_pred[i]<p[i])) or ((y_true[i]<p[i]) and (y_pred[i]>p[i])):
                    c+=1.0
                elif ((y_true[i]>p[i]) and (y_pred[i]>p[i])) or ((y_true[i]<p[i]) and (y_pred[i]<p[i])):
                    c+=0.0
                else:
                    c+=0.5
                    
            cbb_loss = c/tf.cast(len(y_true),dtype=tf.float32)
            return cbb_loss
    
    x = tf.random.normal(shape=(10,10))
    y = tf.random.normal(shape=(10,1))
    
    model = tf.keras.Sequential([
        layers.Dense(units=1)
    ])
    
    
    model.compile(optimizer='adam',
              loss=cbb_loss,
              metrics=['accuracy'])    
    
    
    model.fit(x=x, y=y, epochs=100,verbose=1)
    
    

    【讨论】:

      猜你喜欢
      • 2019-10-29
      • 2021-12-08
      • 2019-10-23
      • 2022-01-04
      • 1970-01-01
      • 2021-02-08
      • 1970-01-01
      • 2020-02-20
      • 2020-06-03
      相关资源
      最近更新 更多