训练数据的ML模型拟合优于生成器的模型拟合



我的最终目标是通过在keras API内的fit方法中输入数据生成器来适配ML自动编码器。然而,我发现用生成器拟合的模型不如用原始数据本身拟合的模型。

为了演示这一点,我采取了以下步骤:
  1. 定义一个数据生成器来创建一个可变阻尼集正弦波。重要的是,我将生成器的批处理大小定义为等于整个训练数据集。通过这种方式,我可以消除批大小作为模型与生成器拟合性能差的可能原因。
  2. 定义一个非常简单的ML自动编码器。注意自编码器的潜在空间大于原始数据所以要学会如何复制原始数据
  3. 使用生成器训练一个模型
  4. 使用生成器的__getitem__方法创建一组训练数据,并使用这些数据拟合相同的ML模型。

在生成器上训练的模型的结果远不如在数据本身上训练的结果。

我对发电机的公式肯定是错的,但是,我怎么也找不到我的错误。作为参考,我模拟了这里和这里讨论的生成器。

更新:

我简化了这个问题,使生成器不再产生一系列随机参数化的阻尼正弦波,而是产生一个1的向量(即np.ones(batch_size, 1000, 1))。我拟合我的自动编码器模型,和以前一样,与原始数据本身的模型拟合相比,与生成器的模型拟合仍然表现不佳。

旁注:我编辑了最初发布的代码以反映此更新。

import numpy as np
import matplotlib.pyplot as plt
import keras
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Conv1D, Conv1DTranspose, MaxPool1D
import tensorflow as tf

""" Generate training/testing data data (i.e., a vector of ones) """

class DataGenerator(keras.utils.Sequence):
def __init__(
self,
batch_size,
vector_length,
):
self.batch_size = batch_size
self.vector_length = vector_length
def __getitem__(self, index):
x = np.ones((self.batch_size, self.vector_length, 1))
y = np.ones((self.batch_size, self.vector_length, 1))
return x, y
def __len__(self):
return 1 #one batch of data

vector_length = 1000
train_gen = DataGenerator(800, vector_length)
test_gen = DataGenerator(200, vector_length)

""" Machine Learning Model and Training """
# Class to hold ML model
class MLModel:
def __init__(self, n_inputs):
self.n_inputs = n_inputs
visible = Input(shape=n_inputs)
encoder = Conv1D(
filters=1,
kernel_size=100,
padding="same",
strides=1,
activation="LeakyReLU",
)(visible)
encoder = MaxPool1D(pool_size=2)(encoder)
# decoder
decoder = Conv1DTranspose(
filters=1,
kernel_size=100,
padding="same",
strides=2,
activation="linear",
)(encoder)
model = Model(inputs=visible, outputs=decoder)
model.compile(optimizer="adam", loss="mse")
self.model = model

""" EXPERIMENT 1 """
# instantiate a model
n_inputs = (vector_length, 1)
model1 = MLModel(n_inputs).model
# train first model!
model1.fit(x=train_gen, epochs=10, validation_data=test_gen)
""" EXPERIMENT 2 """
# use the generator to create training and testing data
train_x, train_y = train_gen.__getitem__(0)
test_x, test_y = test_gen.__getitem__(0)
# instantiate a new model
model2 = MLModel(n_inputs).model
# train second model!
history = model2.fit(train_x, train_y, validation_data=(test_x, test_y), epochs=10)

""" Model evaluation and plotting """
pred_y1 = model1.predict(test_x)
pred_y2 = model2.predict(test_x)
plt.ion()
plt.clf()
n = 0
plt.plot(test_y[n, :, 0], label="True Signal")
plt.plot(pred_y1[n, :, 0], label="Model1 Prediction")
plt.plot(pred_y2[n, :, 0], label="Model2 Prediction")
plt.legend()

我犯了一个新手错误,忘记了model.fit默认为batch_size = 32。因此,上面发布的实验并不是"苹果对苹果"的研究。因为模型与生成器的拟合使用batch_size=800,而模型对数据本身的拟合使用batch_size=32。当为两个实验设置相同的批大小时,两个模型的表现相似。

注。如果这对任何人都有帮助:我没有意识到批大小作为一个超参数有多重要。当然,有一些警告、细微差别和例外,但显然较小的批大小有助于泛化模型。我不会详述这个主题,但这里有有趣的读物,这里,这里和这里

相关内容

  • 没有找到相关文章

最新更新