如何在Keras生成器模型中对输出序列执行独热编码?
问题描述
我正在为特定GAN模型构建噪声生成器:
- 输入:100个浮点数组成的随机序列
- 输出要求:先得到809个取值范围为1至21的整数,最终独热编码为形状
(None, 809, 22)的张量
当前模型执行到tf$squeeze(axis=-1L)时运行正常,此时输出形状为(None, 809)。尝试用layer_integer_lookup实现独热编码:
one_int<- layer_integer_lookup(vocabulary=dicint, oov_token = 0, num_oov_indices = 1L, output_mode = "one_hot")
添加到模型末尾后触发报错:
RuntimeError: Evaluation error: ValueError: Exception encountered when calling layer "integer_lookup_4" (type IntegerLookup). When output_mode is not `'int'`, maximum supported output rank is 2. Received output_mode one_hot and input shape (None, 809), which would result in output rank 3. Call arguments received: • inputs=tf.Tensor(shape=(None, 809), dtype=float32)
附完整模型代码:
######################### Constants ######################### depth=809 kwidth=22 rnd_seq=100 bsize=8L noise=function(bsize,rnd_seq){tf$random$normal(c(bsize,rnd_seq))} flt=8 kernels=12 ######################### Model ########################## model_GAN = function(batch_size,flt,kernels,depth,rnd_seq) { prot_input2 = layer_input(shape = c(rnd_seq)) GAN= prot_input2 %>% layer_dense(depth) %>% layer_reshape(target_shape = c(depth,1)) %>% layer_conv_1d_transpose(filters=flt,kernel_size = c(kernels),strides = kernels/2 )%>% layer_activation_leaky_relu(alpha=0.2) %>% layer_flatten() %>% #layer_conv_1d(filters = flt, kernel_size = c(kernels), strides = (kernel_size/2), activation = 'sigmoid') %>% layer_dense(depth,activation="sigmoid") %>% layer_reshape(target_shape = c(depth,1)) %>% recode_aa() %>% tf$squeeze(axis=-1L) %>% ????????? my_conv() ###### here I need help!!! model=keras_model(inputs=prot_input2,outputs = GAN) summary(model) return(model) } #################### Build the model #################### modelGAN=model_GAN(batch_size,flt,kernels,depth,rnd_seq)
模型执行至tf$squeeze(axis=-1L)时的结构摘要:
Model: "model_1" ___________________________________________________________________________________________________________________________ Layer (type) Output Shape Param # =========================================================================================================================== input_12 (InputLayer) [(None, 100)] 0 dense_19 (Dense) (None, 809) 81709 reshape_19 (Reshape) (None, 809, 1) 0 conv1d_transpose_9 (Conv1DTranspose) (None, 4860, 8) 104 leaky_re_lu_9 (LeakyReLU) (None, 4860, 8) 0 flatten_9 (Flatten) (None, 38880) 0 dense_18 (Dense) (None, 809) 31454729 reshape_18 (Reshape) (None, 809, 1) 0 tf.math.add_9 (TFOpLambda) (None, 809, 1) 0 tf.math.truediv_9 (TFOpLambda) (None, 809, 1) 0 tf.math.round_9 (TFOpLambda) (None, 809, 1) 0 tf.compat.v1.squeeze_9 (TFOpLambda) (None, 809) 0 =========================================================================================================================== Total params: 31,536,542 Trainable params: 31,536,542 Non-trainable params: 0 ___________________________________________________________________________________________________________________________
解决方案
方法1:用Lambda层包装tf.one_hot
layer_integer_lookup在output_mode="one_hot"时仅支持输入rank≤1(输出rank≤2),而你的输入是rank2的(None,809),会导致输出rank3超出限制。直接用tf.one_hot更适配序列型独热编码需求:
# 定义独热编码Lambda层 one_hot_layer <- layer_lambda(function(x) { # 强制转换为整数类型(tf.one_hot要求输入为整数) x <- tf$cast(x, tf$int32) # depth=22对应0-21共22个类别(包含oov的0和1-21的有效值) tf$one_hot(x, depth = 22, axis = -1L) })
替换模型中需要修改的部分:
GAN= prot_input2 %>% # ... 保留前面所有层 ... tf$squeeze(axis=-1L) %>% one_hot_layer()
这样输出形状会直接变为(None,809,22),完全符合需求。
方法2:调整IntegerLookup的使用流程
如果一定要用layer_integer_lookup,可以先展平输入,处理后再重塑回目标形状:
one_int <- layer_integer_lookup( vocabulary = dicint, oov_token = 0, num_oov_indices = 1L, output_mode = "one_hot" ) # 修改模型流程 GAN= prot_input2 %>% # ... 保留前面所有层 ... tf$squeeze(axis=-1L) %>% layer_flatten() %>% one_int() %>% layer_reshape(target_shape = c(depth, 22)) # 重塑为(None,809,22)
注意要确保dicint包含1-21的所有值,oov_token=0会被映射到第一个独热位,最终输出的类别数为22。
额外注意事项
- 确认
recode_aa()层输出的整数确实在1-21范围内,避免过多OOV(未登录词)影响模型效果; - 若后续需要计算损失,独热编码后的输出可直接与目标张量计算交叉熵损失。
内容的提问来源于stack exchange,提问作者Davide
相关产品推荐
相关产品推荐

