我在使用Keras构建神经网络时遇到了一个问题,基本上网络学会了总是预测训练集中实例更多的类别。
我将代码分为几个部分:
数据预处理
data = purchase_data.copy()
labelencoder = LabelEncoder()
target_sum = 120
data.loc[data['sales'] <= target_sum, 'sales'] = False
data.loc[data['sales'] > target_sum, 'sales'] = True
print("\n\n列名与格式化:\n")
for col in data.columns.values.tolist():
if data[col].dtype == "object" or data[col].dtype == "bool":
print("{:<30}".format(col), ":", "{:<30}".format(str(data[col].dtype)) , "格式转换为LabelEncoding")
data[col] = labelencoder.fit_transform(data[col])
else:
print("{:<30}".format(col), ":", "{:<30}".format(str(data[col].dtype)) , "无需格式化。")
# 将datetime转换为浮点数
data['accessed_date'] = data['accessed_date'].apply(lambda x: x.timestamp())
array = data.values
class_column = 'sales' # 我想预测的列
X = np.delete(array, data.columns.get_loc(class_column), axis=1) # 移除class_column列
Y = array[:,data.columns.get_loc(class_column)] # 选择class_column列
Y = Y[:, np.newaxis] # 调整形状值
# 对输入值(不包括类别值)进行归一化
scaler = preprocessing.Normalizer().fit(X)
X = scaler.transform(X)
数据集拆分
seed = 1
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.33, random_state=seed, shuffle=True, stratify=(Y))
神经网络
tf.random.set_seed(seed)
# 构建神经网络
modeldl = Sequential()
modeldl.add(Dense(64, input_dim=X.shape[1], activation='relu', kernel_initializer=he_normal()))
modeldl.add(Dropout(0.2))
modeldl.add(Dense(32, activation='relu', kernel_initializer=he_normal()))
modeldl.add(Dropout(0.2))
modeldl.add(Dense(1, activation='sigmoid', kernel_initializer=he_normal()))
# 编译模型
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-04)
modeldl.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=['acc'])
results = modeldl.fit(X_train, Y_train, epochs=80, batch_size=1000, verbose=1)
混淆矩阵
训练结束时得到以下混淆矩阵:
|| 正类 | 负类 |
|---|---|---|
|正类| 0 (TP)| 21719 (FN)|
|负类| 0 (FP)| 22620 (TN)|
问题
如何解决这个问题?
我已经尝试了:
- 调整超参数
- 预测“sales”之外的另一列
- 改变网络规模
- 固定学习率
- 更改激活函数
- 添加/移除Dropout层
其他信息
数据集中大约50%是类别'0',50%是类别'1'。我使用的数据集来源于这个链接,但我已移除了与退货相关的列和行。