用于多项逻辑回归的 Scikit-Learn 与 Keras (Tensorflow)

Scikit-Learn vs Keras (Tensorflow) for multinomial logistic regression

我正在尝试使用 Keras 进行简单的多项式逻辑回归,但结果与标准的 scikit-learn 方法相比有很大不同。

例如虹膜数据:

import numpy as np
import pandas as pd
df = pd.read_csv("./data/iris.data", header=None)

from sklearn.model_selection import train_test_split
df_train, df_test = train_test_split(df, test_size=0.3, random_state=52)

X_train = df_train.drop(4, axis=1)
y_train = df_train[4]

X_test = df_test.drop(4, axis=1)
y_test = df_test[4]

使用 scikit-learn:

from sklearn.linear_model import LogisticRegression

scikit_model = LogisticRegression(multi_class='multinomial', solver ='saga', max_iter=500)
scikit_model.fit(X_train, y_train)

测试集上的平均加权 f1 分数:

y_test_pred = scikit_model.predict(X_test)

from sklearn.metrics import classification_report
print(classification_report(y_test, y_test_pred, scikit_model.classes_))

0.96

然后使用 Keras:

from sklearn.preprocessing import LabelEncoder
from keras.utils import np_utils

# first we have to encode class values as integers
encoder = LabelEncoder()
encoder.fit(y_train)
y_train_encoded = encoder.transform(y_train)
Y_train = np_utils.to_categorical(y_train_encoded)
y_test_encoded = encoder.transform(y_test)
Y_test = np_utils.to_categorical(y_test_encoded)

from tensorflow import keras
from tensorflow.keras.models import Sequential 
from tensorflow.keras.layers import Dense, Activation
from keras.regularizers import l2

#model construction
input_dim = 4 # 4 variables
output_dim = 3 # 3 possible outputs

def classification_model():
    model = Sequential()
    model.add(Dense(output_dim, input_dim=input_dim, activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
    return model

#training
keras_model = classification_model()
keras_model.fit(X_train, Y_train, epochs=500, verbose=0)

测试集上的平均加权 f1 分数:

classes = np.argmax(keras_model.predict(X_test), axis = 1)
y_test_pred = encoder.inverse_transform(classes)

from sklearn.metrics import classification_report
print(classification_report(y_test, y_test_pred, encoder.classes_))

0.89

是否可以使用 Keras 执行与 scikit-learn 相同(或至少尽可能多)的逻辑回归?

一个明显的区别是 sagaSAG) is used in LogisticRegression while SGD is used in your NN. As far as I know, LogisticRegression doesn't support SGD. Alternatively you can use SGDRegressor or SGDClassifier instead of LogisticRegression. And here is a blog 的一种变体,讨论了它们之间的区别。

我尝试 运行 你的例子并注意到了几个潜在的来源:

  • 测试集非常小,只有 45 个实例。这意味着要将准确度从 0.89 提高到 0.96,该模型只需要再正确预测三个实例。由于训练的随机性,您的 Keras 结果可能会出现相当大的波动。
  • 正如@meowongac 所解释的那样,您正在使用不同的优化器。一点是 scikit 的算法会自动设置它的学习率。对于 Keras 中的 SGD,调整学习率 and/or 轮数可能会带来改进。
  • Scikit learn 默认使用 L2 正则化。

使用你的代码,我能够通过 运行 学习率设置为 .05 的 SGD 获得 0.89 到 .96 的精度。当切换到 Adam(同样具有相当高的学习率)时,我得到了更稳定的结果,范围从 .92 到 .96(尽管这更像是一种印象,因为我没有 运行 太多次试验)。