【问题标题】: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。

  1. 我错过了什么?

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

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

【问题讨论】:

    标签: tensorflow machine-learning keras scikit-learn neural-network


    【解决方案1】:

    简而言之,你需要:

    1. ReLU 激活
    2. 更简单的模型
    3. 数据规范化
    4. 更多纪元

    详细说明:

    这里的第一个问题是,现在我们从不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%的连接以减少它们之间的相互依赖关系,从而减少过拟合。

      【讨论】:

        猜你喜欢
        • 2018-04-04
        • 2014-09-28
        • 1970-01-01
        • 2023-04-04
        • 2017-03-15
        • 2016-08-10
        • 2019-01-27
        • 2018-06-13
        • 2020-03-30
        相关资源
        最近更新 更多