训练 CNN 来预测函数的参数

问题描述 投票:0回答:1

我正在尝试使用 TensorFlow 构建 CNN 来解决以下类型的回归任务。这个想法是有一些未知的函数,我们有兴趣知道该函数的一些参数。作为特征,我们有一个 x 值向量和一个向量 y,其中包含相应 x 值处的函数值。相应的标签就是函数参数。 CNN 将获取 x 和 y 值并预测参数值。但是,我的 CNN 模型无法达到足够的准确度。

更具体地说,请考虑以下简单示例。所有函数都是简单的线性函数 y = kx,任务是预测斜率 k。为了获取数据,我们可以使用以下Python代码:

N_data = 50000 # number of data points

X = [] # features (x and y values)
y = [] # labels (slopes)

for k in range(N_data):
    # Randomly choose the x values:
    x_min = 200*random.random()-100
    xs = np.linspace(x_min, x_min + 10)

    # Randomly choose the slope:
    k = 200*random.random()-100

    # Calculate the function values:
    ys = k*xs
    
    # Store the data:
    X.append(xs.tolist() + ys.tolist())
    y.append(k)
    
X = np.array(X)
y = np.array(y)

tf.random.set_seed(41)

# Split the data into training, validation and test sets:
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.2, random_state=41)

# Split the temporary set into validation and test sets:
X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=41)

这是我的 CNN 模型:

model = models.Sequential()

# Data normalization layer
model.add(layers.InputLayer(input_shape=(X[0].shape[0], 1)))
model.add(layers.BatchNormalization())

# Convolutional block 1:
model.add(layers.Conv1D(32, 3, activation='relu'))
model.add(layers.AveragePooling1D(2))

# Convolutional block 2:
model.add(layers.Conv1D(64, 3, activation='relu'))
model.add(layers.AveragePooling1D(2))

# Convolutional block 3:
model.add(layers.Conv1D(128, 3, activation='relu'))
model.add(layers.MaxPooling1D(2))

model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(1))

以下代码适合该模型:

model.compile(optimizer=Adam(learning_rate=0.01),
              loss='mean_squared_error',
              metrics=['mae'])

history = model.fit(X_train, y_train, epochs=50, batch_size = 16, 
                    validation_data=(X_val, y_val))

训练和验证平均绝对误差如下图所示:

我不确定如何解释验证误差始终小于训练误差。对于测试集(总数据的 10%,即 5000 个样本),平均绝对误差为 3.37,对于这个简单的问题和如此大量的数据点来说,这个误差相当高。我可以做些什么来改进模型?我不确定问题是否出在数据点数量、CNN 架构或输入数据的格式化方式上。任何建议将不胜感激。

tensorflow deep-learning neural-network conv-neural-network regression
1个回答
0
投票

考虑输入为 [xi,yi] 和输出 [ki] 其中 xi*ki = yi。

用于标准输入/激活。

A(zi - (xi*wxj + yi*wyj))

你不能让这个激活函数的结果是 k。

不过你可以对 k 进行分类。这个想法是对 k 进行足够的分类,使得该值可以是标量。只考虑正 x、y 和 k。

sigmoid( - xi*10 + yi )

因此当 k > 10 时交叉。

有了这个想法,您可以构建足够的输出来将 k 分类为一系列值。

如果我们使用两个点,则不必进行除法。

(x0, y0, x0 + 1, y1)

现在我们可以看到斜率是 x[3] - x[1]。这是我们应该从您的示例中看到的,因为您始终使用相同的 linspec。我怀疑从你的池化/卷积中你已经以某种方式消除了这条训练路线的可能性。

我输入了:

X.append( np.array((xs[i], xs[i+1], ys[i], ys[i+1])) )

我改变了模型:

model = models.Sequential()

model.add(layers.InputLayer(input_shape=(X[0].shape[0], 1)))
nn = 32
nl = 4
act = 'relu'
model.add(layers.Flatten())
for i in range(nl):
    model.add(layers.Dense(nn, activation=act))
    model.add(layers.Dense(1, activation='linear'))
model.add(layers.Dense(1, activation='linear'))

模型和数据学习预测 k。

© www.soinside.com 2019 - 2024. All rights reserved.