keras 使用训练数据拟合的ML模型优于使用发生器拟合的模型

wfveoks0  于 2023-01-21  发布在  其他
关注(0)|答案(1)|浏览(116)

我的最终目标是通过将数据生成器输入keras API中的 * fit * 方法来拟合ML自动编码器,但是,我发现使用生成器拟合的模型不如使用原始数据拟合的模型。
为了证明这一点,我采取了以下步骤:
1.定义一个数据生成器来创建一组可变阻尼正弦波。重要的是,我定义生成器的批量大小等于整个训练数据集。通过这种方式,我可以消除批量大小作为模型与生成器拟合性能差的可能原因。
1.定义一个非常简单的ML自动编码器。注意自动编码器的潜在空间比原始数据的大小要大,所以它应该学会如何相对快速地重现原始信号。
1.使用发生器训练一个模型
1.使用发生器的__getitem__方法创建一组训练数据,并使用这些数据拟合相同的ML模型。
在发生器上训练的模型的结果远不如在数据本身上训练的结果。
我的发电机公式一定是错的,但是,为了我的生命,我找不到我的错误。作为参考,我模拟发电机讨论herehere

更新:

我简化了问题,使得发生器不是产生一系列随机参数化的阻尼正弦波,而是现在产生一个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()
aydmsdu9

aydmsdu91#

我犯了一个新手错误,忘记了model.fit默认为batch_size = 32。因此,上面发布的实验没有进行“苹果对苹果”的比较,因为与生成器拟合的模型使用了batch_size=800,而与数据本身拟合的模型使用了batch_size=32。当为两个实验设置相同的批量大小时,两个模型的性能相似。
p.s.如果对任何人有帮助:我没有意识到批量大小作为一个超参数有多么重要。当然,有一些警告、细微差别和例外,但显然较小的批量大小有助于概括模型。我不想赘述这个主题,但有一些有趣的阅读hereherehere

相关问题