为啥我使用 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 forest
,k_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 forest
或 k_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 的结果很差?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在使用 PCA 减少后拟合随机森林模型时性能会受到影响?