SilyaSophie 2024-10-28 23:17 采纳率: 36.8%
浏览 147
已结题

VAE模型编程报错无法解决

python代码,VAE架构加入了CNN,处理物联网2023数据集,decoder维度有问题,输出一直报错。

import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Lambda,Conv1D,Flatten,Activation, SpatialDropout1D,Reshape
from tensorflow.keras.models import Model,Sequential
from tensorflow.keras import backend as K
from tensorflow.keras.datasets import mnist
from sklearn.preprocessing import MinMaxScaler, StandardScaler

import numpy as np
import pandas as pd
import time

# Load the dataset
# csv文件路径
csv_path_train = 'CICIoT2023/CICIoT2023/benign.csv'
# 读取数据
X_train = pd.read_csv(csv_path_train)
X_train = X_train.values
X_train = np.nan_to_num(MinMaxScaler().fit_transform(StandardScaler().fit_transform(X_train)))

X_train = np.reshape(X_train, (-1, 100, 46))
print(f"train:{X_train.shape}")
idx = np.random.randint(0, X_train.shape[0], 16)
imgs = X_train[idx]
# print(imgs.shape)
print(f"imgs:{imgs.shape}")
# noise = np.random.normal(0, 1, (16, 100, 1))
# # print(noise.shape)
# print(f"noise:{noise.shape}")

# csv文件路径
csv_path_test = 'CICIoT2023/CICIoT2023/ceshi.csv'
Y_test = pd.read_csv(csv_path_test)
Y_test_normal = Y_test[Y_test.label == 'BenignTraffic'].drop(labels='label', axis=1).values
Y_test_normal = np.nan_to_num(MinMaxScaler().fit_transform(StandardScaler().fit_transform(Y_test_normal)))
Y_test_abnormal = Y_test[Y_test.label != 'BenignTraffic'].drop(labels='label', axis=1).values
Y_test_abnormal = np.nan_to_num(MinMaxScaler().fit_transform(StandardScaler().fit_transform(Y_test_abnormal)))
Y_test_normal = np.reshape(Y_test_normal, (-1, 100, 46))
Y_test_abnormal = np.reshape(Y_test_abnormal, (-1, 100, 46))

# Define VAE architecture
#original_dim = X_train.shape[1]
#latent_dim = 2
batch_size=100
#original_dim=784
original_dim=46
latent_dim=2
intermediate_dim = 256
epochs=50

def sampling(args):
    z_mean, z_log_var = args
    print(f"z_mean:{z_mean.shape}")
    batch = K.shape(z_mean)[0]
    dim = K.int_shape(z_mean)[1]
    epsilon = K.random_normal(shape=(batch, dim, 1))
    return z_mean + K.exp(0.5 * z_log_var) * epsilon
    #epsilon_reshaped = tf.reshape(epsilon, [-1, 392, 512])
    #return z_mean + K.exp(0.5 * z_log_var) * epsilon_reshaped


inputs = Input(shape=(original_dim,100))# 这里应该是原始数据的维度
#h_inputs= Input(shape=(batch_size,original_dim))
h = Conv1D(1024, kernel_size=3, strides=2, padding='same', activation='relu')(inputs)#卷积层定义
# 均值输出层,输出的维度应与潜在空间的维度匹配
z_mean=Dense(512, activation='relu')(h)
# 对数方差输出层,同上
z_log_var=Dense(512, activation='relu')(h)
# 采样层,生成潜在空间的样本
z = Lambda(sampling)([z_mean, z_log_var])

#def tcn_layer(x1, dilation_rate):
x1 = Conv1D(filters=64, kernel_size=2, dilation_rate=2, padding='causal')(inputs)
    #x1 = Activation('relu')(x1)
    #x1 = SpatialDropout1D(0.2)(x1)
    #return x1

#encoder = Model(inputs, [z_mean, z_log_var,z], name='encoder')
def build_encoder():
    model=Sequential()
    model.add(inputs)
    model.add(Conv1D(filters=64, kernel_size=2, activation='relu'))
    model.add(SpatialDropout1D(0.2))
    model.add(Flatten())
    model.add(Dense(2, activation='softmax'))
    #model.outputs=outputs
    model.summary()
    return model

encoder=build_encoder()

latent_inputs = Input(shape=(latent_dim,100))
x = Dense(intermediate_dim, activation='relu')(latent_inputs)
outputs = Dense(original_dim, activation='sigmoid')(x)

#decoder = Model(latent_inputs, outputs, name='decoder')
def build_decoder():
    model = Sequential()
    model.add(latent_inputs)
    model.add(Conv1D(filters=64, kernel_size=2, activation='relu'))
    model.add(SpatialDropout1D(0.2))
    model.add(Dense(784, activation='sigmoid'))  # 添加一个全连接层,输出维度为 784
    model.add(Dense(units=2 * 784, activation='sigmoid'))
    model.add(Flatten())
    model.add(Reshape((1, 1)))
    model.add(Dense(2, activation='softmax'))
    model.summary()
    return model

decoder=build_decoder()
print(f"encoder(inputs):{encoder(inputs)}")
encoded_output = encoder(inputs)# 首先,获取编码器的输出
print(encoded_output.shape)  # 这将显示编码器的输出形状

# 假设 encoded_output 是你的二维张量
encoded_output = tf.expand_dims(encoded_output, axis=-1)# 或者 axis=1,取决于你的需求
#encoded_output.layers[0] = encoded_output.reshape(2,100)
encoded_output = tf.reshape(encoded_output, [2, 100, 100])

outputs = decoder(encoded_output)#再获取译码器的输出

vae = Model(inputs, outputs, name='vae')

# Define VAE loss
reconstruction_loss = tf.keras.losses.binary_crossentropy(inputs, outputs)
reconstruction_loss *= original_dim
kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)
vae.add_loss(vae_loss)
vae.compile(optimizer='adam')

# Train VAE
vae.fit(X_train, epochs=10, batch_size=32, validation_data=(Y_test))

打印模型信息如下:

img

img

报错如下:

img

img

  • 写回答

27条回答 默认 最新

  • 才华横溢caozy 2024-10-29 10:59
    关注
    获得0.15元问题酬金

    以下答案是由GPT4-pro回答,本人整理后的结果,如有帮助,还请采纳!
    在处理变分自编码器(VAE)模型时,尤其是结合卷积神经网络(CNN)来处理数据时,常见的报错往往与输入和输出维度的不匹配有关。根据你提供的代码和图片链接,下面我将对可能的问题进行分析,并给出改进建议。

    问题分析

    1. 输入维度不匹配

      • 从你的代码来看,inputs的形状是(original_dim, 100),而在卷积层之后,输出的维度可能发生变化,导致后续层无法接收到正确的输入形状。
    2. 编码器和解码器结构问题

      • 在你的编码器部分,Conv1D层之后的Dense层输入形状需要匹配,而你在创建解码器时,也需要注意其输入的形状。特别是你在采样层后的z与解码器的输入之间可能存在维度不匹配。
    3. 模型的创建和连接问题

      • build_encoderbuild_decoder函数中,可能没有正确返回编码器和解码器的模型结构,导致在使用时出现错误。
    4. 重构损失与KL散度

      • VAE的损失函数需要根据输出和输入的形状一致性进行调整。根据你使用的binary_crossentropy,它要求两个输入的形状必须相同。

    改进建议

    下面是一个改进后的代码示例,调整了输入输出维度、网络结构及训练过程。代码分为几个部分,每个部分都有详细的注释。

    1. 数据预处理

    确保数据的预处理部分保持一致,以便后续的模型训练。

    import numpy as np
    import pandas as pd
    from sklearn.preprocessing import MinMaxScaler, StandardScaler
    
    # 读取数据
    csv_path_train = 'CICIoT2023/CICIoT2023/benign.csv'
    X_train = pd.read_csv(csv_path_train).values
    X_train = np.nan_to_num(MinMaxScaler().fit_transform(StandardScaler().fit_transform(X_train)))
    X_train = np.reshape(X_train, (-1, 100, 46))
    
    csv_path_test = 'CICIoT2023/CICIoT2023/ceshi.csv'
    Y_test = pd.read_csv(csv_path_test)
    Y_test_normal = Y_test[Y_test.label == 'BenignTraffic'].drop(labels='label', axis=1).values
    Y_test_normal = np.nan_to_num(MinMaxScaler().fit_transform(StandardScaler().fit_transform(Y_test_normal)))
    Y_test_normal = np.reshape(Y_test_normal, (-1, 100, 46))
    

    2. VAE模型架构

    确保编码器和解码器的连接正确,下面是改进后的VAE架构代码:

    import tensorflow as tf
    from tensorflow.keras.layers import Input, Dense, Lambda, Conv1D, Flatten, Reshape
    from tensorflow.keras.models import Model
    from tensorflow.keras import backend as K
    
    original_dim = 46  # 特征维度
    latent_dim = 2     # 潜在空间维度
    intermediate_dim = 256
    batch_size = 100
    
    # 采样函数
    def sampling(args):
        z_mean, z_log_var = args
        batch = K.shape(z_mean)[0]
        dim = K.int_shape(z_mean)[1]
        epsilon = K.random_normal(shape=(batch, dim))
        return z_mean + K.exp(0.5 * z_log_var) * epsilon
    
    # 编码器
    inputs = Input(shape=(100, original_dim))
    x = Conv1D(64, kernel_size=3, activation='relu', padding='same')(inputs)
    x = Flatten()(x)
    z_mean = Dense(latent_dim)(x)
    z_log_var = Dense(latent_dim)(x)
    z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var])
    encoder = Model(inputs, [z_mean, z_log_var, z], name='encoder')
    
    # 解码器
    latent_inputs = Input(shape=(latent_dim,))
    x = Dense(100 * 64, activation='relu')(latent_inputs)
    x = Reshape((100, 64))(x)  # 将展平的层重新调整为三维
    x = Conv1D(64, kernel_size=3, activation='relu', padding='same')(x)
    outputs = Conv1D(original_dim, kernel_size=3, activation='sigmoid', padding='same')(x)
    decoder = Model(latent_inputs, outputs, name='decoder')
    
    # VAE模型
    outputs = decoder(encoder(inputs)[2])  # 连接编码器和解码器
    vae = Model(inputs, outputs, name='vae')
    
    # 定义损失函数
    reconstruction_loss = tf.keras.losses.binary_crossentropy(K.flatten(inputs), K.flatten(outputs))
    reconstruction_loss *= 100  # 对应维度
    kl_loss = 1 + z_log_var - K.square(z_mean) - K.exp(z_log_var)
    kl_loss = K.sum(kl_loss, axis=-1) * -0.5
    vae_loss = K.mean(reconstruction_loss + kl_loss)
    vae.add_loss(vae_loss)
    vae.compile(optimizer='adam')
    

    3. 训练模型

    最后,确保在训练模型时,输入数据的形状与模型匹配。

    # 训练VAE
    vae.fit(X_train, epochs=50, batch_size=batch_size, validation_data=(Y_test_normal, None))
    

    代码总结

    1. 输入和输出维度:在构建编码器和解码器时,确保每一层的输入输出维度匹配。
    2. 连接编码器和解码器:在创建VAE时,使用编码器的输出作为解码器的输入。
    3. 损失函数:根据VAE的定义计算重构损失和KL散度。

    额外建议

    • 调试:使用model.summary()检查每一层的输出形状,以确保它们符合预期。
    • 数据维度:确认输入数据的形状与模型的要求一致,必要时进行reshape。
    • 学习率和批量大小:可以尝试不同的学习率和批量大小,可能会影响训练的收敛性。

    通过以上修改和建议,相信你能够解决VAE模型在编程时出现的维度问题,并顺利训练出期望的模型。如果还有其他具体的报错信息,请提供详细信息,我将更进一步帮助你解决问题。

    评论

报告相同问题?

问题事件

  • 系统已结题 11月5日
  • 创建了问题 10月28日