我正在学习这个Keras教程,发现了有趣的事情。
我使用sklearn训练了我的逻辑回归模型,表现相当不错:
import seaborn as snsimport numpy as npfrom sklearn.cross_validation import train_test_splitfrom sklearn.linear_model import LogisticRegressionCVfrom keras.models import Sequentialfrom keras.layers.core import Dense, Activationfrom keras.utils import np_utils# 从seaborn加载iris数据集。iris = sns.load_dataset("iris")# 使用前四个变量来预测物种。X, y = iris.values[:, 0:4], iris.values[:, 4]# 将自变量和因变量分成两半# 用于交叉验证train_X, test_X, train_y, test_y = train_test_split(X, y, train_size=0.5, random_state=0)# 训练一个scikit-learn逻辑回归模型lr = LogisticRegressionCV()lr.fit(train_X, train_y)# 测试模型。在测试数据上打印准确率pred_y = lr.predict(test_X)print("准确率是 {:.2f}".format(lr.score(test_X, test_y))) # 准确率是 0.83
83%已经相当不错了,但使用深度学习我们应该能做得更好。我训练了一个Keras模型…
# 定义一个对数组中的变量进行独热编码的函数def one_hot_encode_object_array(arr): '''对numpy对象数组(例如字符串)进行独热编码''' uniques, ids = np.unique(arr, return_inverse=True) return np_utils.to_categorical(ids, len(uniques))# 对训练和测试的y值进行独热编码train_y_ohe = one_hot_encode_object_array(train_y)test_y_ohe = one_hot_encode_object_array(test_y)# 构建keras模型model = Sequential()# 输入层有4个特征(四种花的测量值)# 16个隐藏单元model.add(Dense(16, input_shape=(4,)))model.add(Activation('sigmoid'))# 输出层有3个类别(对应于3个物种)model.add(Dense(3))model.add(Activation('softmax'))model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])# 训练keras模型model.fit(train_X, train_y_ohe, verbose=0, batch_size=1)# 测试模型。在测试数据上打印准确率loss, accuracy = model.evaluate(test_X, test_y_ohe, verbose=0)print("准确率是 {:.2f}".format(accuracy)) # 准确率是 0.60????
当我训练Keras模型时,我的准确率实际上比我的逻辑回归模型还要差。
虽然这对某些数据来说是有道理的,但对于像iris这样极其线性可分的数据,Keras顺序模型应该很容易学习。我尝试增加隐藏层的数量到32、64和128,但准确率没有改善。
下图显示了Iris数据(具体来说是自变量)作为物种(因变量)的函数:
为什么我的模型表现如此差?
回答:
我已经替换了独热编码,直接使用了keras的sparse_categorical_crossentropy
。
尝试的显而易见的方法是:增加学习的epoch数量(默认10,我们试试100)。
代码
from sklearn.datasets import load_irisfrom sklearn.cross_validation import train_test_splitfrom sklearn.linear_model import LogisticRegressionCVimport numpy as npfrom keras.models import Sequentialfrom keras.layers import Dense, Activation# 从seaborn加载iris数据集。iris = load_iris()# 使用前四个变量来预测物种。X, y = iris.data[:, :4], iris.target# 将自变量和因变量分成两半# 用于交叉验证train_X, test_X, train_y, test_y = train_test_split(X, y, train_size=0.5, random_state=0)# 训练一个scikit-learn逻辑回归模型lr = LogisticRegressionCV()lr.fit(train_X, train_y)# 测试模型。在测试数据上打印准确率pred_y = lr.predict(test_X)print("准确率是 {:.2f}".format(lr.score(test_X, test_y))) # 准确率是 0.83# 构建keras模型model = Sequential()# 输入层有4个特征(四种花的测量值)# 16个隐藏单元model.add(Dense(16, input_shape=(4,)))model.add(Activation('sigmoid'))# 输出层有3个类别(对应于3个物种)model.add(Dense(3))model.add(Activation('softmax'))model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])# 训练keras模型model.fit(train_X, train_y, verbose=1, batch_size=1, nb_epoch=100)# 测试模型。在测试数据上打印准确率loss, accuracy = model.evaluate(test_X, test_y, verbose=0)print("准确率是 {:.2f}".format(accuracy))
输出
准确率是 0.83准确率是 0.99