训练1D CNN时model.fit()出现形状不兼容错误求助
问题描述
尝试在表格数据上训练1D CNN,后续用于LRP分析,但在model.fit()环节报错,此前步骤均正常运行。
报错信息
model_history = model.fit(X_train_smote, y_train_smote, batch_size=100, epochs=100, validation_split = 0.2) Epoch 1/100 --------------------------------------------------------------------------- ValueError Traceback (most recent call last) Input In [60], in <cell line: 1>() ----> 1 model_history = model.fit(X_train_smote, y_train_smote, batch_size=100, epochs=100, validation_split = 0.2) File D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\utils\traceback_utils.py:67, in filter_traceback.<locals>.error_handler(*args, **kwargs) 65 except Exception as e: # pylint: disable=broad-except 66 filtered_tb = _process_traceback_frames(e.__traceback__) ---> 67 raise e.with_traceback(filtered_tb) from None 68 finally: 69 del filtered_tb File ~\AppData\Local\Temp\__autograph_generated_filelswqetod.py:15, in outer_factory.<locals>.inner_factory.<locals>.tf__train_function(iterator) 13 try: 14 do_return = True ---> 15 retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope) 16 except: 17 do_return = False ValueError: in user code: File "D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\engine\training.py", line 1051, in train_function * return step_function(self, iterator) File "D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\engine\training.py", line 1040, in step_function ** outputs = model.distribute_strategy.run(run_step, args=(data,)) File "D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\engine\training.py", line 1030, in run_step ** outputs = model.train_step(data) File "D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\engine\training.py", line 890, in train_step loss = self.compute_loss(x, y, y_pred, sample_weight) File "D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\engine\training.py", line 948, in compute_loss return self.compiled_loss( File "D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\engine\compile_utils.py", line 201, in __call__ loss_value = loss_obj(y_t, y_p, sample_weight=sw) File "D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\losses.py", line 139, in __call__ losses = call_fn(y_true, y_pred) File "D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\losses.py", line 243, in call ** return ag_fn(y_true, y_pred, **self._fn_kwargs) File "D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\losses.py", line 1787, in categorical_crossentropy return backend.categorical_crossentropy( File "D:\Programme\Anaconda\envs\LRP_innvestigate\lib\site-packages\keras\backend.py", line 5119, in categorical_crossentropy target.shape.assert_is_compatible_with(output.shape) ValueError: Shapes (None,) and (None, 6, 2) are incompatible
完整实现代码
import matplotlib.pyplot as plt import matplotlib.pyplot as plt import numpy as np import pandas as pd import seaborn as sns from matplotlib.colors import ListedColormap from sklearn.metrics import plot_confusion_matrix from scipy.stats import norm, boxcox from sklearn.metrics import confusion_matrix, classification_report, accuracy_score from collections import Counter from scipy import stats import tensorflow as tf import warnings warnings.simplefilter(action='ignore', category=Warning) dataset = pd.read_csv('F:/Programmieren/this_one/data/Churn_Modelling.csv') # split into variables and target X = dataset.iloc[:, 3:-1].values y = dataset.iloc[:, -1].values # here gender is encoded from sklearn.preprocessing import LabelEncoder le = LabelEncoder() X[:, 2] = le.fit_transform(X[:, 2]) # one hot encoding the country (as explained in Ullah et al.) from sklearn.compose import ColumnTransformer from sklearn.preprocessing import OneHotEncoder ct = ColumnTransformer(transformers=[('encoder', OneHotEncoder(), [1])], remainder='passthrough') X = np.array(ct.fit_transform(X)) # split the data from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size= .2) # upsample minority class with SMOTE import imblearn from imblearn.over_sampling import SMOTENC #get original class distribution counter = Counter(y) print(counter) #SMOTENC is used instead of SMOTE because there are multiple categorical features in the dataset oversample = SMOTENC(categorical_features=[0, 1, 2, 4, 9, 10]) X_train_smote, y_train_smote = oversample.fit_resample(X_train, y_train) #get new class distribution counter = Counter(y_train_smote) print(counter) # normalize values to range 0-1 as explained in Ullah et al. from sklearn.preprocessing import MinMaxScaler mms = MinMaxScaler() X_train_smote = mms.fit_transform(X_train_smote) X_test = mms.transform(X_test) #record-wise normalization for relative value comparison as stated by one of the authors I was in contact with from sklearn.preprocessing import normalize X_train_smote = normalize(X_train_smote, axis=1, norm='l1') X_test = normalize(X_test, axis=1, norm='l1') #reshape data for CNN sample_size = X_train_smote.shape[0] # number of samples in train set time_steps = X_train_smote.shape[1] # number of features in train set input_dimension = 1 train_data_reshaped = X_train_smote.reshape(sample_size,time_steps,input_dimension) print("After reshape train data set shape:\n", train_data_reshaped.shape) print("1 Sample shape:\n",train_data_reshaped[0].shape) print("An example sample:\n", train_data_reshaped[0]) #reshape test data as well test_data_reshaped = X_test.reshape(X_test.shape[0],X_test.shape[1],1) import keras from keras.models import Sequential from keras.layers import Dense, Conv1D #create model as explained in the paper model = Sequential() model.add(Conv1D(filters=25, kernel_size=3, activation='relu', input_shape=(12,1))) model.add(Conv1D(50, 3)) model.add(Conv1D(100, 3)) model.add(Dense(2200, activation='relu')) model.add(Dense(2, activation='relu')) model.add(Dense(2, activation='softmax')) model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy']) model.summary() #output of model.summary() Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv1d (Conv1D) (None, 10, 25) 100 conv1d_1 (Conv1D) (None, 8, 50) 3800 conv1d_2 (Conv1D) (None, 6, 100) 15100 dense (Dense) (None, 6, 2200) 222200 dense_1 (Dense) (None, 6, 2) 4402 dense_2 (Dense) (None, 6, 2) 6 ================================================================= Total params: 245,608 Trainable params: 245,608 Non-trainable params: 0 _________________________________________________________________
请问当前方法是否存在未察觉的重大缺陷?
问题解决与分析
核心错误原因
报错Shapes (None,) and (None, 6, 2) are incompatible明确指出两个关键问题:
- 模型输出形状不符合二分类任务要求:从模型summary可见,最终输出是
(None,6,2),即每个样本输出6组二元分类结果,但你的任务是单样本二分类,仅需1组结果。 - 标签格式不匹配损失函数要求:
y_train_smote是一维数组(None,),而categorical_crossentropy损失要求标签为独热编码后的二维数组(None,2)。
具体修正方案
1. 调整模型结构,压缩序列维度
在Conv1D层之后添加全局池化层或Flatten层,将序列维度转为一维,再连接全连接层输出最终分类结果:
model = Sequential() model.add(Conv1D(filters=25, kernel_size=3, activation='relu', input_shape=(12,1))) model.add(Conv1D(50, 3, activation='relu')) model.add(Conv1D(100, 3, activation='relu')) # 全局平均池化,将(None,6,100)转为(None,100) model.add(tf.keras.layers.GlobalAveragePooling1D()) # 或使用Flatten层:model.add(tf.keras.layers.Flatten()) model.add(Dense(2200, activation='relu')) model.add(Dense(2, activation='relu')) model.add(Dense(2, activation='softmax'))
调整后模型最终输出变为(None,2),符合二分类任务要求。
2. 对标签进行独热编码
使用tf.keras.utils.to_categorical处理训练和测试标签:
from tensorflow.keras.utils import to_categorical y_train_smote = to_categorical(y_train_smote, num_classes=2) y_test = to_categorical(y_test, num_classes=2)
3. 传入正确的训练数据
训练时需传入reshape后的train_data_reshaped,而非原始的X_train_smote:
model_history = model.fit(train_data_reshaped, y_train_smote, batch_size=100, epochs=100, validation_split = 0.2)
其他潜在问题
- Conv1D层缺少激活函数:后两个Conv1D层未指定激活函数,默认线性激活会降低模型表达能力,建议添加
activation='relu'。 - 全连接层参数冗余:
Dense(2200)参数数量过大,易导致过拟合,可根据样本量调整为256或512。 - LRP适配性:调整模型结构后,需确认后续LRP工具兼容修改后的标准CNN+全连接结构(主流LRP库均支持此类结构)。
内容的提问来源于stack exchange,提问作者user19534996
相关产品推荐
相关产品推荐

