今天,我遇到了Keras的一些非常奇怪的行为。当我尝试使用简单的模型对虹膜数据集进行分类时,keras版本1.2.2的准确性为+-95%,而keras版本2.0+则为每个训练示例预测了相同的类别(导致由于存在三种类型的光圈,因此准确度为+-35%)。使我的模型预测精度为+ -95%的唯一事情是将keras降级到2.0以下的版本:
我认为Keras遇到了问题,因为我尝试了以下操作,但都没有效果。
在最后一层切换激活功能(从Sigmoid到softmax)。
切换后端(Theano和Tensorflow都提供大致相同的性能)。
使用随机种子。
改变隐藏层中神经元的数量(在这个简单模型中,我只有1个隐藏层)。
开关损耗功能。
由于该模型非常简单并且可以独立运行(您只需要易于获取的iris.csv数据集),因此我决定包括整个代码。
import pandas as pd
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from keras.utils import np_utils
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold
from sklearn.preprocessing import LabelEncoder
#Load data
data_frame = pd.read_csv("iris.csv", header=None)
data_set = data_frame.values
X = data_set[:, 0:4].astype(float)
Y = data_set[:, 4]
#Encode class values as integers
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)
# convert integers to dummy variables (i.e. one hot encoded)
dummy_y = np_utils.to_categorical(encoded_Y)
def baseline_model():
#Create & Compile model
model = Sequential()
model.add(Dense(8, input_dim=4, init='normal', activation='relu'))
model.add(Dense(3, init='normal', activation='sigmoid'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
#Create Wrapper For Neural Network Model For Use in scikit-learn
estimator = KerasClassifier(build_fn=baseline_model, nb_epoch=200, batch_size=5, verbose=0)
#Create kfolds-cross validation
kfold = KFold(n_splits=10, shuffle=True)
#Evaluate our model (Estimator) on dataset (X and dummy_y) using a 10-fold cross-validation procedure (kfold).
results = cross_val_score(estimator, X, dummy_y, cv=kfold)
print("Accuracy: {:2f}% ({:2f}%)".format(results.mean()*100, results.std()*100))
如果有人想复制错误,这里是我用来观察问题的依赖项:
numpy=1.16.4
pandas=0.25.0
sk-learn=0.21.2
theano=1.0.4
tensorflow=1.14.0
最佳答案
在Keras 2.0中,许多参数都更改了名称,有一个兼容层可以使事情正常运行,但是在使用KerasClassifier
时它不适用。
在这部分代码中:
estimator = KerasClassifier(build_fn=baseline_model, nb_epoch=200, batch_size=5, verbose=0)
您使用的是旧名称
nb_epoch
而不是现代名称epochs
。默认值为epochs=1
,这意味着您的模型仅训练了一个时期,产生的质量预测非常低。还要注意这里:
model.add(Dense(3, init='normal', activation='sigmoid'))
您应该使用
softmax
激活而不是sigmoid
,因为您正在使用分类交叉熵损失:model.add(Dense(3, init='normal', activation='softmax'))