You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用KerasClassifier拟合含字符串X的Keras模型时出现2D/1D数组错误

问题:KerasClassifier结合TextVectorization层模型时触发ValueError: Expected 2D array, got 1D array

问题描述

直接拟合含TextVectorization层的自定义Keras模型时正常,但用KerasClassifier包装后拟合,传入字符串列表作为训练数据X时触发该错误。已使用官方推荐的TextVectorization层(拒绝使用已废弃的Tokenizer类),且该层已适配训练数据,核心需求是将output_sequence_length设为超参数。

相关代码

def Build_Model(X_train, nodes=10, nLayers=1, epochs=10, batch_size=32, dropout=0.5,       
                act_h='relu', act_o='sigmoid', optimizer='adam', verbose=2, emb_matrix=None, vocab=None,   
                sequence_length=200):

    vectorize_layer = TextVec_Layer(vocab, sequence_length)
    embedding_layer = Emb_Layer(emb_matrix, sequence_length)
    model.add(InputLayer(input_shape=(1,), dtype=tf.string))  # 注意:原代码未初始化model
    vectorize_layer.adapt(X_train)
    model.add(vectorize_layer)
    model.add(embedding_layer)
    model.add(Flatten())
    model.add(Dense(nodes, activation=act_h))
    model.add(Dropout(dropout))

    model.add(Dense(nClasses, activation=act_o))                 
    model.compile(optimizer=optimizer,                                 
                loss= 'binary_crossentropy',
                metrics=['accuracy'])

    return model


emb_model = KerasClassifier(build_fn=Build_Model, X_train=X_train, nodes=10, nLayers=1, epochs=10,    
                            batch_size=100, dropout=0.5, act_h='relu', act_o='sigmoid', optimizer='adam', 
                            emb_matrix=emb_matrix, vocab=vocab, sequence_length=100,verbose=2, random_state=42)

model = emb_model.fit(X_train, y_train)

报错栈信息

ValueError   Traceback (most recent call last)
...\Temp/ipykernel_18552/393945425.py in <module>
----> 1 emb_model.fit(X_train, y_train)#, , validation_data=(X_test_t, y_test)

...\wrappers.py in fit(self, X, y, sample_weight, **kwargs)
   1492             sample_weight = 1 if sample_weight is None else sample_weight
   1493             sample_weight *= compute_sample_weight(class_weight=self.class_weight, y=y)
-> 1494         super().fit(X=X, y=y, sample_weight=sample_weight, **kwargs)
   1495         return self
   1496 

...\wrappers.py in fit(self, X, y, sample_weight, **kwargs)
    760         kwargs["initial_epoch"] = kwargs.get("initial_epoch", 0)
    761 
-> 762         self._fit(
    763             X=X,
    764             y=y,

...\wrappers.py in _fit(self, X, y, sample_weight, warm_start, epochs, initial_epoch, **kwargs)
    916         # Data checks
    917         if not ((self.warm_start or warm_start) and self.initialized_):
-> 918             X, y = self._initialize(X, y)
    919         else:
    920             X, y = self._validate_data(X, y)

解决方案

原因分析

KerasClassifier继承自scikit-learn的Estimator接口,默认会对输入数据执行scikit-learn风格的维度验证,它期望输入是2D数组,但你的X是1D字符串列表,触发了维度检查错误。而直接使用Keras模型时,模型的InputLayer明确接受(1,)形状的字符串输入,因此不会有该问题。

修复方案1:跳过KerasClassifier的数据验证

在初始化KerasClassifier时添加validate_data=False参数,跳过scikit-learn风格的数据验证,让数据直接传入Keras模型处理:

emb_model = KerasClassifier(
    build_fn=Build_Model, 
    X_train=X_train, 
    nodes=10, 
    nLayers=1, 
    epochs=10,    
    batch_size=100, 
    dropout=0.5, 
    act_h='relu', 
    act_o='sigmoid', 
    optimizer='adam', 
    emb_matrix=emb_matrix, 
    vocab=vocab, 
    sequence_length=100,
    verbose=2, 
    random_state=42,
    validate_data=False  # 新增:关闭数据验证
)

修复方案2:规范模型构建逻辑(推荐)

  1. 补全模型初始化:原Build_Model函数未初始化model对象,需添加model = tf.keras.Sequential()。
  2. 提前适配TextVectorization层:不要在模型构建函数内调用vectorize_layer.adapt(X_train),避免KerasClassifier重复构建模型时重复适配(比如交叉验证场景)。
  3. 传递已适配的向量层:将提前适配好的vectorize_layer作为参数传入模型构建函数。

修改后代码示例:

# 定义TextVectorization层封装函数
def TextVec_Layer(vocab, sequence_length):
    return tf.keras.layers.TextVectorization(
        vocabulary=vocab,
        output_sequence_length=sequence_length,
        output_mode='int'
    )

# 提前适配向量层
sequence_length = 100
vectorize_layer = TextVec_Layer(vocab, sequence_length)
vectorize_layer.adapt(X_train)

# 修改模型构建函数,移除X_train参数和内部adapt逻辑
def Build_Model(nodes=10, nLayers=1, epochs=10, batch_size=32, dropout=0.5, 
                act_h='relu', act_o='sigmoid', optimizer='adam', verbose=2, 
                emb_matrix=None, vectorize_layer=None, sequence_length=200):
    # 补全模型初始化
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.InputLayer(input_shape=(1,), dtype=tf.string))
    model.add(vectorize_layer)
    embedding_layer = Emb_Layer(emb_matrix, sequence_length)
    model.add(embedding_layer)
    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.Dense(nodes, activation=act_h))
    model.add(tf.keras.layers.Dropout(dropout))
    model.add(tf.keras.layers.Dense(nClasses, activation=act_o))                 
    model.compile(optimizer=optimizer,                                 
                loss= 'binary_crossentropy',
                metrics=['accuracy'])
    return model

# 初始化KerasClassifier,传入已适配的vectorize_layer
emb_model = KerasClassifier(
    build_fn=Build_Model, 
    nodes=10, 
    nLayers=1, 
    epochs=10,    
    batch_size=100, 
    dropout=0.5, 
    act_h='relu', 
    act_o='sigmoid', 
    optimizer='adam', 
    emb_matrix=emb_matrix, 
    vectorize_layer=vectorize_layer, 
    sequence_length=sequence_length,
    verbose=2, 
    random_state=42,
    validate_data=False
)

额外提示

如果使用新版scikeras(替代旧版keras.wrappers.scikit_learn),建议使用scikeras.wrappers.KerasClassifier,并通过model__前缀传递模型参数,更符合scikit-learn的参数传递规范。

内容的提问来源于stack exchange,提问作者Dython

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 22:14:56