使用y_pred和y_true以外的其他参数的Keras自定义损失函数

2024-05-13 23:48:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我想用一个类似感知器的神经网络来解决我的问题。为了简单起见,我有一个数据集,如下所示:

id entryWoodLength entryWoodThickness cuttingToolPos1 cuttingToolPos2 exitWoodLength exitWoodThickness
1        5.5              1.6               2.1             2.2             4.2            1.6
2        5.7              1.5               2.2             2.6             4.2            1.5
3        6.5              1.8               2.6             2.7             4.3            1.6
4        5.9              1.7               2.4             2.9             4.2            1.5
5        5.8              1.5               2.2             2.6             4.1            1.5

我想尝试一个前馈神经网络,输入是木材尺寸(entryWoodLenth和entryWoodThickness),输出是切割工具的位置(cuttingToolPos1和cuttingToolPos2)。我们已经知道出口木材的理想尺寸应该是什么(比如长度为4.2,厚度为1.5)。因此,从技术上讲,我们希望我们的网络能够根据木材的实际值(exitWoodLength和exitWoodThickness)进行自我优化。这意味着使用参考值为4.2和1.5的exitWoodLength和exitWoodThickness的MSE,如下所示:

mean_squared_error(exitWoodLength, 4.2) + mean_squared_error(exitWoodThickness, 1.5)

但是,Keras只允许使用y_predy_true参数的自定义loss函数,在我们的例子中,这些参数是cuttingToolPos1和cuttingToolPos2,而不是我们想要的loss函数的值。我在考虑使用闭包函数,并简单地忽略y_predy_true参数,即:

def custom_loss(exitWoodLength, exitWoodThickness):

    def loss(y_pred, y_true):

        mean_squared_error(exitWoodLength, 4.2) + mean_squared_error(exitWoodThickness, 1.5)

        return loss

但我担心指数,以及它是否可行

有没有人经历过类似的事情?我使用神经网络的方法是正确的还是完全错误的


Tags: 函数true参数神经网络errormeanlosspred
3条回答

据我所知,以你目前的损失函数,你将无法训练神经网络。损耗函数的电流输入不是神经网络的输出。确保y_true是您的目标变量,y_pred是神经网络的预测(输出)

如果我错了,请纠正我:根据一些入口木材长度/厚度,您希望预测获得最佳结果的切割位置(现有木材长度/厚度)?所以在“现实生活”中,你会从只有entryWood值开始吗

此选项可能不令人满意,但第一步可能是使用entryWood和cuttingPos作为输入,使用exitWood作为目标变量。通过这种方式,神经网络可以学习根据特定的入口木材/切割位置预测现有木材。然后,对于第二步,[基于一些entryWood值],您可以搜索提供4.2/1.5 existWood的cuttingPos。此时此刻,我不太确定您如何[优雅地]将其制作成单个(端到端)模型

例如:

import pandas as pd
import numpy as np
import tensorflow as tf # (TensorFlow version 2.2)

# define dataset
df = pd.DataFrame(
    {'entryWoodLength':    [5.5, 5.7, 6.5, 5.9, 5.8],
     'entryWoodThickness': [1.6, 1.5, 1.8, 1.7, 1.5],
     'cuttingToolPos1':    [2.1, 2.2, 2.6, 2.4, 2.2],
     'cuttingToolPos2':    [2.2, 2.6, 2.7, 2.9, 2.6],
     'exitWoodLength':     [4.2, 4.2, 4.3, 4.2, 4.1],
     'exitWoodThickness':  [1.6, 1.5, 1.6, 1.5, 1.5]}
)

# STEP 1
# create and compile model
model = tf.keras.Sequential([
    tf.keras.layers.Dense(8, activation='relu', dtype='float32'), # hidden layer
    tf.keras.layers.Dense(2, activation='linear', dtype='float32'), # output layer
])
# mse = (exitWood_pred - exitWood_true)^2
model.compile(loss='mse', optimizer='sgd')

X = df.iloc[:, :4] # entryWoodLength, entryWoodThickness, cuttingToolPos1, cuttingToolPos2
y = df.iloc[:, 4:] # exitWoodLength, exitWoodThickness

# fit to the data, find a relationship between X and y
history = model.fit(X, y, epochs=100, verbose=0)


# STEP 2
# dummy example 
entry_wood_dimemsions = [6.0, 1.8]
# let's try some "random" tool_position (this has to be searched for)
cut_tool_position = [2.1, 2.7]
# model input
x = np.array([[entry_wood_dimemsions + cut_tool_position]])
# predict based on entry_wood_dimemsions and [manually selected] cut_tool_position
exitWood_pred = model.predict(x)

print("existWood pred =", np.squeeze(exitWood_pred))

>> existWood pred = [4.078477  1.4972893]

请记住[特别是在这个虚拟案例中],模型(神经网络)描述输入和输出之间的关系非常糟糕(因此我不相信此时的预测)。但是有了更多的数据,这个模型(可能)会变得更好。还请记住,我不知道您正在处理的主题/数据,因此这些只是一些想法/示例,可能会帮助您开始/指导您

根据我的理解,您可能希望您的机器将入口块切割到接近所需尺寸(出口块)的位置,因为您试图预测所需的刀具位置,或者反过来(您的问题中不清楚)。你可以用两种方法来模拟这个问题

选项1:预测最佳刀具位置,为具有特定尺寸的输入块生成具有所需尺寸的输出块。输入:入口块(厚度和长度)和出口块(厚度和长度);输出:最佳刀具位置

选项2:预测给定输入块尺寸和刀具位置的输出块尺寸。输入:输入块(厚度和长度)和刀具位置;输出:出口块(厚度和长度)

这两种方法都是对系统建模的有效方法,您可以根据应用选择一种,即,根据您想要预测的内容,是出口块的尺寸,还是给定输入和期望输出的最佳刀具位置

这两个选项都可以通过MSE损耗函数轻松建模

从你的问题陈述来看,似乎你需要首先训练你的神经网络并找到优化的输入变量。然而,从您的代码来看,您似乎在定义自定义丢失时遇到了问题。虽然我不清楚您的问题陈述,但您可以这样做以创建自定义损失函数(从akensert的答案扩展):

from keras import backend as K 
#custom loss
def custom_error(y_true, y_pred):
        return K.mean(K.square(y_pred[:,0] - 4.2)) +K.mean(K.square(y_pred[:,1] - 1.5))

model.compile(loss=custom_error, optimizer='sgd')

history = model.fit(X, y, epochs=100, verbose=1)

相关问题 更多 >