在keras中复制sklearn的MLPClassifier()
Posted
技术标签:
【中文标题】在keras中复制sklearn的MLPClassifier()【英文标题】:Replicate MLPClassifier() of sklearn in keras 【发布时间】:2017-11-22 05:21:42 【问题描述】:我是 keras 的新手。我正在尝试 ML 问题。 关于数据:
它有 5 个输入特征,4 个输出类和大约 26000 条记录。
我首先尝试使用 MLPClassifier() 如下:
clf = MLPClassifier(verbose=True, tol=1e-6, batch_size=300, hidden_layer_sizes=(200,100,100,100), max_iter=500, learning_rate_init= 0.095, solver='sgd', learning_rate='adaptive', alpha = 0.002)
clf.fit(train, y_train)
经过测试,我的 LB 分数通常在 99.90 左右。为了在模型上获得更大的灵活性,我决定在 Keras 中实现相同的模型,然后对其进行更改以尝试提高 LB 分数。我想出了以下几点:
model = Sequential()
model.add(Dense(200, input_dim=5, init='uniform', activation = 'relu'))
model.add(Dense(100, init='uniform', activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(100, init='uniform', activation='relu'))
model.add(Dense(100, init='uniform', activation='relu'))
model.add(Dense(4, init='uniform', activation='softmax'))
lrate = 0.095
decay = lrate/125
sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
hist = model.fit(train, categorical_labels, nb_epoch=125, batch_size=256, shuffle=True, verbose=2)
该模型看起来与 MLPClassifier() 模型非常相似,但 LB 分数在 97 左右时非常令人失望。 有人可以告诉这个模型到底有什么问题吗?或者我们如何在 keras 中复制 MLPClassifier 模型。我认为正则化可能是这里出错的因素之一。
编辑1:损失曲线:
编辑 2: 代码如下:
#import libraries
import pandas as pd
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import log_loss
from sklearn.preprocessing import MinMaxScaler, scale, StandardScaler, Normalizer
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras import regularizers
from keras.optimizers import SGD
#load data
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")
#generic preprocessing
#encode as integer
mapping = 'Front':0, 'Right':1, 'Left':2, 'Rear':3
train = train.replace('DetectedCamera':mapping)
test = test.replace('DetectedCamera':mapping)
#renaming column
train.rename(columns = 'SignFacing (Target)': 'Target', inplace=True)
mapping = 'Front':0, 'Left':1, 'Rear':2, 'Right':3
train = train.replace('Target':mapping)
#split data
y_train = train['Target']
test_id = test['Id']
train.drop(['Target','Id'], inplace=True, axis=1)
test.drop('Id',inplace=True,axis=1)
train_train, train_test, y_train_train, y_train_test = train_test_split(train, y_train)
scaler = StandardScaler()
scaler.fit(train_train)
train_train = scaler.transform(train_train)
train_test = scaler.transform(train_test)
test = scaler.transform(test)
#training and modelling
model = Sequential()
model.add(Dense(200, input_dim=5, kernel_initializer='uniform', activation = 'relu'))
model.add(Dense(100, kernel_initializer='uniform', activation='relu'))
# model.add(Dropout(0.2))
# model.add(Dense(100, init='uniform', activation='relu'))
# model.add(Dense(100, init='uniform', activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(100, kernel_initializer='uniform', activation='relu'))
model.add(Dense(100, kernel_initializer='uniform', activation='relu'))
model.add(Dense(4, kernel_initializer='uniform', activation='softmax'))
lrate = 0.095
decay = lrate/250
sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
hist = model.fit(train_train, categorical_labels, validation_data=(train_test, categorical_labels_test), nb_epoch=100, batch_size=256, shuffle=True, verbose=2)
编辑 3:这些是文件: train.csv test.csv
【问题讨论】:
添加剧情。上图是我将训练数据分为训练和测试并在同一模型上运行时获得的。无法访问获得 LB 分数的测试数据的实际标签。在最初的 25 个 epoch 之后,准确率保持在 96 左右,损失保持在 0.10 左右。 想到的一些事情:删除 dropout 层,因为您似乎没有过度拟合。训练更长的时间或至少在 Keras 中添加一个 EarlyStopping,耐心大约为 15,以确保您的模型真的不再改进(您的 MLP 最多有 500 个 epoch)。尝试adam
或 rmsprop
作为优化器。为了进一步的实验,您可以在 fit( … )
函数中添加 validation_split
并对 Tensorboard 进行回调。这可以在培训期间为您提供近乎实时的反馈。
还有一件事:训练和测试损失并行运行如此顺利似乎很奇怪。您确定这两个数据集已正确分离吗?您是否在 Kaggle 或本地使用 sklearn 分类器获得了 Kaggle 排行榜分数?
它似乎没有过度拟合,这就是令人困惑的地方。因为当我在最终的测试数据上运行相同的模型时,损失比本地训练和验证期间的损失要大得多。在没有 dropout 的情况下,损失在本地是相似的,但在提交时,LB 分数约为 92!提到的分数不是本地分数,而是提交时获得的分数。使用 sklearn 的 train_test_split 以 0.75:.25 的比例拆分数据。我已经使用validation_data() 在fit(...) 函数中发送了验证数据。没有尝试亚当。我一试就会告诉你!
@PriyanshuGoyal 你在哪里定义分类标签?我尝试运行您的代码,但未定义 categorical_labels。
【参考方案1】:
要获得真正的 scikit estimator,您可以使用来自 tensorflow.keras.wrappers.scikit_learn
的 KerasClassifier
。例如:
from sklearn.datasets import make_classification
from tensorflow import keras
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
from tensorflow.keras.wrappers.scikit_learn import KerasClassifier
X, y = make_classification(
n_samples=26000, n_features=5, n_classes=4, n_informative=3, random_state=0
)
def build_fn(optimizer):
model = Sequential()
model.add(
Dense(200, input_dim=5, kernel_initializer="he_normal", activation="relu")
)
model.add(Dense(100, kernel_initializer="he_normal", activation="relu"))
model.add(Dense(100, kernel_initializer="he_normal", activation="relu"))
model.add(Dense(100, kernel_initializer="he_normal", activation="relu"))
model.add(Dense(4, kernel_initializer="he_normal", activation="softmax"))
model.compile(
loss="categorical_crossentropy",
optimizer=optimizer,
metrics=[
keras.metrics.Precision(name="precision"),
keras.metrics.Recall(name="recall"),
keras.metrics.AUC(name="auc"),
],
)
return model
clf = KerasClassifier(build_fn, optimizer="rmsprop", epochs=500, batch_size=300)
clf.fit(X, y)
clf.predict(X)
【讨论】:
以上是关于在keras中复制sklearn的MLPClassifier()的主要内容,如果未能解决你的问题,请参考以下文章
在“Keras”分类中使用“sklearn”库中计算类权重函数问题(Python 3.8,仅在 VS 代码中)