为啥我使用 Keras 与随机森林或 knn 的结果很差?

Posted

技术标签:

【中文标题】为啥我使用 Keras 与随机森林或 knn 的结果很差?【英文标题】:Why I'm getting bad result with Keras vs random forest or knn?为什么我使用 Keras 与随机森林或 knn 的结果很差? 【发布时间】:2020-07-28 18:06:18 【问题描述】:

我正在使用keras 学习深度学习,并尝试将结果(准确性)与机器学习算法(sklearn)(即random forestk_neighbors)进行比较

似乎使用keras 我得到的结果最差。 我正在研究简单的分类问题:iris dataset 我的 keras 代码看起来:

samples = datasets.load_iris()
X = samples.data
y = samples.target
df = pd.DataFrame(data=X)
df.columns = samples.feature_names
df['Target'] = y

# prepare data
X = df[df.columns[:-1]]
y = df[df.columns[-1]]

# hot encoding
encoder = LabelEncoder()
y1 = encoder.fit_transform(y)
y = pd.get_dummies(y1).values

# split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3)

# build model
model = Sequential()
model.add(Dense(1000, activation='tanh', input_shape = ((df.shape[1]-1),)))
model.add(Dense(500, activation='tanh'))
model.add(Dense(250, activation='tanh'))
model.add(Dense(125, activation='tanh'))
model.add(Dense(64, activation='tanh'))
model.add(Dense(32, activation='tanh'))
model.add(Dense(9, activation='tanh'))
model.add(Dense(y.shape[1], activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train)
score, acc = model.evaluate(X_test, y_test, verbose=0)

#results:
#score = 0.77
#acc = 0.711

我已经厌倦了添加层和/或更改每层的单元数和/或更改激活函数(到 relu),结果似乎不高于 0.85。

使用 sklearn random forestk_neighbors 我得到的结果(在同一数据集上)高于 0.95。

    我错过了什么?

    使用sklearn 时,我几乎没有付出任何努力并获得了不错的结果,使用keras,我进行了很多升级,但不如sklearn 的结果。这是为什么呢?

    如何使用keras 获得相同的结果?

【问题讨论】:

【参考方案1】:

简而言之,你需要:

    ReLU 激活 更简单的模型 数据规范化 更多纪元

详细说明:

这里的第一个问题是,现在我们从不activation='tanh' 用于中间网络层。在此类问题中,我们实际上总是使用activation='relu'

第二个问题是您已经构建了一个相当大的 Keras 模型,很可能在您的训练集中只有 100 个虹膜样本时,您的数据太少 无法有效训练这么大的模型。尝试大幅减少层数和每层的节点数。开始更简单

当我们拥有大量数据时,大型神经网络确实会蓬勃发展,但在像这里这样的小型数据集的情况下,与更简单的算法(如 RF 或k-nn。

第三个问题是,与基于树的模型(如随机森林)相比,神经网络通常需要对数据进行归一化,而您不会这样做。事实上,knn 也需要归一化的数据,但在这种特殊情况下,由于所有 iris 特征都处于相同的尺度,因此不会对性能产生负面影响。

最后但同样重要的是,您似乎只运行了一个时期的 Keras 模型(如果您没有在 model.fit 中指定任何内容,则为默认值);这有点相当于用一棵树构建一个随机森林(顺便说一句,它仍然是much better than a single decision tree)。

总而言之,您的代码有以下更改:

from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

model = Sequential()
model.add(Dense(150, activation='relu', input_shape = ((df.shape[1]-1),)))
model.add(Dense(150, activation='relu'))
model.add(Dense(y.shape[1], activation='softmax'))

model.fit(X_train, y_train, epochs=100)

其他一切照原样,我们得到:

score, acc = model.evaluate(X_test, y_test, verbose=0)
acc
# 0.9333333373069763

我们可以做得更好:使用稍微更多的训练数据并将它们分层,即

X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    test_size = 0.20, # a few more samples for training
                                                    stratify=y)

使用相同的模型和训练时期,您可以在测试集中获得 1.0 的完美准确度:

score, acc = model.evaluate(X_test, y_test, verbose=0)
acc
# 1.0

(由于此类实验中默认施加的一些随机性,细节可能会有所不同)。

【讨论】:

【参考方案2】:

添加一些 dropout 可能会帮助您提高准确性。请参阅Tensorflow's documentation 了解更多信息。

本质上,添加 Dropout 层的方式与添加那些 Dense() 层的方式非常相似。

model.add(Dropout(0.2)

注意:参数'0.2意味着随机省略层中20%的连接以减少它们之间的相互依赖关系,从而减少过拟合。

【讨论】:

以上是关于为啥我使用 Keras 与随机森林或 knn 的结果很差?的主要内容,如果未能解决你的问题,请参考以下文章

R缺失值识别过滤填充(中位数KNN随机森林)

为啥在使用 PCA 减少后拟合随机森林模型时性能会受到影响?

为啥与 MSE 相比,使用 MAE 标准训练随机森林回归器如此缓慢?

为啥随机森林并行化后重要性会受到影响?

随机森林 {Keras 由浅入深}

OpenCV3 SVM ANN Adaboost KNN 随机森林等机器学习方法对OCR分类