实现文本数据ResNet遇TypeError与ValueError,寻求解决方法
文本数据ResNet实现中的错误排查
错误详情
初始错误
运行代码触发TypeError: __init__() missing 1 required positional argument: 'kernel_size',报错位置在ResNet50函数的Stage 1中X = Conv1D(64)(X_input)行。修改后新错误
将该行改为X = Conv1D(64, kernel_size=(3))(X)后,出现ValueError: Input 0 of layer "conv1d" is incompatible with the layer: expected min_ndim=3, found ndim=2. Full shape received: (None, 53)。
完整实现代码
导入依赖
from scipy.stats import zscore import pandas as pd from sklearn.model_selection import KFold from keras.layers import Input, Add, Dense, Activation, BatchNormalization, Flatten, Conv1D from keras.models import Model CLASSES = 2 def read_pdf(): df = pd.read_csv("https://data.heatonresearch.com/data/t81-558/jh-simple-dataset.csv", na_values=['NA', '?']) return df def k_fold(): # 交叉验证 no_of_folds = int(input('输入K折数量: ')) kf = KFold(no_of_folds, shuffle=True, random_state=42) # 用于分类任务的KFold return kf def epochs_fun(): EPOCHS = int(input('输入训练轮数: ')) return EPOCHS
数据清洗与K折交叉验证
def prepare_data(): kf = k_fold() df = read_pdf() # 为job生成独热编码 df = pd.concat([df, pd.get_dummies(df['job'], prefix="job")], axis=1) df.drop('job', axis=1, inplace=True) # 为area生成独热编码 df = pd.concat([df, pd.get_dummies(df['area'], prefix="area")], axis=1) df.drop('area', axis=1, inplace=True) # 为product生成独热编码 df = pd.concat([df, pd.get_dummies(df['product'], prefix="product")], axis=1) df.drop('product', axis=1, inplace=True) # 填充income的缺失值 med = df['income'].median() df['income'] = df['income'].fillna(med) # 标准化数值特征 df['income'] = zscore(df['income']) df['aspect'] = zscore(df['aspect']) df['save_rate'] = zscore(df['save_rate']) df['subscriptions'] = zscore(df['subscriptions']) # 转换为numpy数组 - 分类任务 x_columns = df.columns.drop('age').drop('id') x = df[x_columns].values y = df['age'].values fold = 0 for train, test in kf.split(x): fold += 1 print(f"第{fold}折") x_train = x[train] y_train = y[train] x_test = x[test] y_test = y[test] print(x_train) print(y_train) print(x_test) print(y_test) return [x_train,y_train,x_test,y_test,x]
恒等模块(Identity Block)
def identity_block(X, filters): # 获取滤波器数量 F1 = filters # 保存输入值,后续需要加回到主路径 X_shortcut = X # 主路径第一部分 X = Conv1D(filters = F1)(X) X = BatchNormalization()(X) X = Activation('relu')(X) # 主路径第二部分 X = Conv1D(filters = F1, kernel_size = 3)(X) X = BatchNormalization()(X) X = Activation('relu')(X) # 主路径第三部分 X = Conv1D()(X) X = BatchNormalization()(X) # 最后一步:将 shortcut 值与主路径相加,然后通过RELU激活 X = Add()([X, X_shortcut]) X = Activation('relu')(X) return X
卷积模块(convolutional_block)
def convolutional_block(X, filters): # 获取滤波器数量 F1 = filters ##### 主路径 ##### # 主路径第一部分 X = Conv1D(F1)(X) X = BatchNormalization()(X) X = Activation('relu')(X) # 主路径第二部分 X = Conv1D(filters=F1, kernel_size=(3))(X) X = BatchNormalization()(X) X = Activation('relu')(X) # 主路径第三部分 X = Conv1D(filters=F1, kernel_size=(3))(X) X = BatchNormalization()(X) ##### 捷径路径 #### X_shortcut = BatchNormalization() # 最后一步:将 shortcut 值与主路径相加,然后通过RELU激活 X = Add()([X, X_shortcut]) X = Activation('relu')(X) return X
ResNet模型定义
def ResNet50(input_shape, classes=2): # 定义输入张量,形状为input_shape X_input = Input(input_shape) # Zero-Padding # X = ZeroPadding2D()(X_input) # Stage 1 X = Conv1D(64)(X_input) X = BatchNormalization()(X) X = Activation('relu')(X) # Stage 2 X = convolutional_block(X) X = identity_block(X) # Stage 3 X = convolutional_block(X) X = identity_block(X) # 输出层 X = Flatten()(X) X = Dense(classes, activation='softmax')(X) # 创建模型 model = Model(inputs=X_input, outputs=X, name='ResNet50') return model
模型训练
def model_check(): data = prepare_data() X_train = data[0] Y_train = data[1] x = data[4] epochs = epochs_fun() model = ResNet50(input_shape = x.shape[1], classes = CLASSES) model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) model.fit(X_train, Y_train, epochs = epochs, batch_size = 64) model_check()
错误原因及修复建议
第一个错误(缺少kernel_size)
Conv1D必须指定kernel_size参数,所有未传该参数的Conv1D调用都需要补充,比如:identity_block中X = Conv1D(filters = F1)(X)改为X = Conv1D(filters=F1, kernel_size=3)(X)identity_block中X = Conv1D()(X)改为X = Conv1D(filters=F1, kernel_size=3)(X)convolutional_block中X = Conv1D(F1)(X)改为X = Conv1D(filters=F1, kernel_size=3)(X)
第二个错误(输入维度不匹配)
Conv1D要求输入为3维张量:(batch_size, timesteps, input_dim),当前输入是2维(None,53),需增加维度:- 在
prepare_data中,将x = df[x_columns].values改为x = df[x_columns].values.reshape(-1, x_columns.shape[0], 1) - 同时将
ResNet50的input_shape参数改为(x.shape[1], 1)
- 在
其他潜在问题
convolutional_block中X_shortcut = BatchNormalization()错误,需对输入X做卷积+BN处理,保证维度与主路径输出一致才能相加- 当前标签
y = df['age'].values是连续值,若为分类任务需将其转为类别,或改用回归损失函数 categorical_crossentropy要求标签为独热编码,若使用原始类别标签需改用sparse_categorical_crossentropy
内容的提问来源于stack exchange,提问作者Python
相关产品推荐
相关产品推荐

