【问题标题】:Very simple Keras binary classification doesn't work非常简单的 Keras 二进制分类不起作用
【发布时间】:2018-09-24 15:27:46
【问题描述】:

有人能解释一下为什么下面的代码只能达到大约 50% 的分类准确率吗?

我正在尝试将 20 个项目的列表分类为 0 或 1。这些列表都是 5 或所有 6。

import numpy as np
import keras
from sklearn.model_selection import train_test_split

positive_samples = [[5]*20]*100
negative_samples = [[6]*20]*100

x_list = np.array(positive_samples+negative_samples, dtype=np.float32)
y_list = np.array([1]*len(positive_samples)+[0]*len(negative_samples), dtype=np.float32)

x_train, x_test, y_train, y_test = train_test_split(x_list, y_list, test_size=0.20, random_state=42)

y_train = keras.utils.to_categorical(y_train, 2)
y_test = keras.utils.to_categorical(y_test, 2)

model = keras.models.Sequential()
model.add(keras.layers.Dense(10, input_dim=x_train.shape[1], kernel_initializer='normal', activation='relu'))
model.add(keras.layers.Dense(5, kernel_initializer='normal', activation='relu'))
model.add(keras.layers.Dense(2, kernel_initializer='normal', activation='sigmoid'))

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

model.fit(x_train, y_train, batch_size=10, epochs=20, verbose=2, validation_data=(x_test, y_test))
print (model.evaluate(x_test, y_test, verbose=0))

【问题讨论】:

    标签: python keras


    【解决方案1】:

    由于最后一个输出层每个样本都有2 值,因此您需要使用softmax 激活而不是sigmoid

    另外,这意味着binary_crossentropy不能使用,你必须使用categorical_crossentropy

    我还通过除以最大值 (6) 对数据集 x_list 进行了标准化。

    x_list /= x_list.max()
    

    另外,您需要通过在train_test_split 中传递shuffle=True 来打乱数据集。

    import numpy as np
    import keras
    from sklearn.model_selection import train_test_split
    
    positive_samples = [[5]*20]*100
    negative_samples = [[6]*20]*100
    
    x_list = np.array(positive_samples+negative_samples, dtype=np.float32)
    y_list = np.array([1]*len(positive_samples)+[0]*len(negative_samples), dtype=np.float32)
    
    x_list /= x_list.max()
    
    x_train, x_test, y_train, y_test = train_test_split(x_list, y_list, test_size=0.20, shuffle=True, random_state=42)
    
    y_train = keras.utils.to_categorical(y_train, 2)
    y_test = keras.utils.to_categorical(y_test, 2)
    
    model = keras.models.Sequential()
    model.add(keras.layers.Dense(10, input_dim=x_train.shape[1], kernel_initializer='normal', activation='relu'))
    model.add(keras.layers.Dense(5, kernel_initializer='normal', activation='relu'))
    model.add(keras.layers.Dense(2, kernel_initializer='normal', activation='softmax'))
    
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    
    model.fit(x_train, y_train, batch_size=10, epochs=100, verbose=2, validation_data=(x_test, y_test))
    print (model.evaluate(x_test, y_test, verbose=0))
    

    只有当有1 输出时,输出中的 sigmoid 激活才有意义,其中值将在[0, 1] 范围内,表示实例为1 的概率。

    2(或更多)输出神经元的情况下,我们有必要将概率归一化以使之和为 1,因此我们使用softmax 层代替。

    【讨论】:

      【解决方案2】:

      在将数据输入网络之前应该对其进行标准化,这通常通过将值更改为 0 和 1 或 -1 和 1 之间来完成。将输入设置为;

      positive_samples = [[1]*20]*100
      negative_samples = [[-1]*20]*100
      

      工作或模型可以更改为:

      model = keras.models.Sequential()
      model.add(BatchNormalization())
      model.add(keras.layers.Dense(10, kernel_initializer='normal', activation='relu'))
      model.add(keras.layers.Dense(5, kernel_initializer='normal', activation='relu'))
      model.add(keras.layers.Dense(2, kernel_initializer='normal', activation='sigmoid'))
      

      【讨论】:

        猜你喜欢
        • 2019-05-18
        • 2020-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-17
        • 1970-01-01
        • 1970-01-01
        • 2017-04-08
        相关资源
        最近更新 更多