sklearn SGDClassifier的decision_function奇怪的行为

时间:2017-08-26 22:56:53

标签: python numpy scikit-learn

所以我在MNIST数据集上使用一个简单的SGDClassifier(根据动手ML书),我似乎无法弄清楚其decision_function的行为。

我更改了original_decision函数的最后一行,专门检查是否有任何不同。带后缀"检查"的变量是这里的decision_function返回的那些。代码:

from sklearn.datasets import fetch_mldata
mnist = fetch_mldata("MNIST original")
import numpy as np
from sklearn.linear_model import SGDClassifier
from sklearn.utils.extmath import safe_sparse_dot
from sklearn.utils import check_array

X, y = mnist["data"], mnist["target"]
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]

shuffle_index = np.random.permutation(60000)
X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]

# converting the problem into a binary classification problem. 
y_train_5 = (y_train == 5)
y_test_5 = (y_test == 5)

sgd_clf = SGDClassifier(random_state=42)
sgd_clf.fit(X_train, y_train_5)

# modified decision_func to ouput vars
X_check, coef_check, intcpt_check = sgd_clf.decision_function([X_train[36000]])

print((X_check == X_train[36000]).all())
print((coef_check == sgd_clf.coef_).all())
print((intcpt_check == sgd_clf.intercept_).all())

# using same funcs as used by decision_function to calc. 
# i.e. check_array safe_sparse_dot
X_mod = check_array(X[36000].reshape(1,-1), "csr")
my_score = safe_sparse_dot(X_mod,sgd_clf.coef_.T) + sgd_clf.intercept_
sk_score = safe_sparse_dot(X_check, coef_check.T) + intcpt_check

print(my_score)
print(sk_score)

这是输出(单次运行):

True
True
True
[[ 49505.1725926]]
[[-347904.18757136]]

这是我对decision_function的修改(在注释掉原始版本之前的第二行):

scores = safe_sparse_dot(X, self.coef_.T,
                                 dense_output=True) + self.intercept_
return X, self.coef_, self.intercept_
#return scores.ravel() if scores.shape[1] == 1 else scores

即使涉及的3个实体(实例X,系数,截距)都与我的变量匹配,但乘法仍会导致截然不同的结果。

为什么会这样?

编辑:奇怪的是我发现如果我注释掉负责改组数据集的两条线:

shuffle_index = np.random.permutation(60000)
X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]

问题消失了......

2 个答案:

答案 0 :(得分:0)

这可能是由于X_mod使用的原始" X" (非抽动)矩阵,而X_check使用X_train(混洗)索引。

即。 X_train [36000]!= X [36000]当然,你的分数应该不一样。

答案 1 :(得分:0)

也许可以原因是由于缺席线:

np.random.seed(42)

您为模型使用了随机状态,但没有使用任何替换状态

import numpy as np
np.random.seed(42)
shuffle_index = np.random.permutation(60000)
X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]