为什么在 python 中获取 sklearn 中的顶级预测结果不同?
Why is the results different in getting the top predications in sklearn in python?
我有一个包含 1000 个数据点的数据集。每个数据点都分配了标签 1
或 0
,如下所示。
我的数据集:
node, feature1, feature2, ........, Label
x1, 0.8, 0.9, ........, 1
x2, 0.2, 0.6, ........, 1
...
x999, 0.1, 0.1, ........, 0
x1000,0.8, 0.9, ........, 1
我想执行二进制 class 化并根据 class 1
的预测概率对我的数据点进行排名。为此,我目前在 sklearn 中使用 predict_proba
函数。所以我的输出应该如下所示。
我的预期输出:
node prediction_probability_of_class_1
x8, 1.0
x5, 1.0
x990,0.95
x78, 0.92
x85, 0.91
x6, 0.90
and so on ........
一段时间以来,我一直在尝试使用以下两种方法来做到这一点。但是,我得到的结果彼此不匹配。所以,我认为我的一种方法(或两种方法)都是不正确的。
由于我的数据集属于我的公司并且包含敏感数据,我将使用具有 150 个数据点的 iris dataset
展示我的两种方法。
from sklearn import datasets
iris = datasets.load_iris()
X = iris.data
y = iris.target
我的做法一:
#random forest classifier
clf=RandomForestClassifier(n_estimators=10, random_state = 42, class_weight="balanced")
#perform 10 fold cross validation
k_fold = StratifiedKFold(n_splits=10, shuffle=True, random_state=0)
#get predict_proba for each instance
proba = cross_val_predict(clf, X, y, cv=k_fold, method='predict_proba')
#get the probability of class 1
print(proba[:,1])
#get the datapoint index of each probaility
print(np.argsort(proba[:,1]))
所以我的结果如下所示。
#probaility of each data point for class 1
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.1 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0.2 0. 0. 0. 0. 0.1 0. 0. 0. 0. 0. 0. 0. 0. 0.9 1. 0.7 1.
1. 1. 1. 0.7 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0.9 0.9 0.1 1.
0.6 1. 1. 1. 0.9 0. 1. 1. 1. 1. 1. 0.4 0.9 0.9 1. 1. 1. 0.9
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0.9 0.
0.1 0. 0. 0. 0. 0. 0. 0. 0.1 0. 0. 0.8 0. 0.1 0. 0.1 0. 0.1
0.3 0.2 0. 0.6 0. 0. 0. 0.6 0.4 0. 0. 0. 0.8 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. ]
#corresponding index of the above data points
[ 0 113 112 111 110 109 107 105 104 114 103 101 100 77 148 49 48 47
46 102 115 117 118 147 146 145 144 143 142 141 140 139 137 136 135 132
131 130 128 124 122 120 45 44 149 42 15 26 16 17 18 19 20 21
22 43 23 24 35 34 33 32 31 30 29 28 27 37 13 25 9 10
7 6 5 4 3 8 11 2 1 38 39 40 12 108 116 41 121 70
14 123 125 36 127 126 134 83 72 133 129 52 57 119 138 89 76 50
84 106 85 69 68 97 98 66 65 64 63 62 61 67 60 58 56 55
54 53 51 59 71 73 75 96 95 94 93 92 91 90 88 87 86 82
81 80 79 78 99 74]
我的方法二:
由于cross_val_predict
我使用的上面没有fit
方法,所以我无法访问clf.classes_
等数据。因此,我使用下面的代码。
cv_1 = cross_val_score(clf, X, y, cv=k_fold)
clf.fit(X, y)
probabilities = pd.DataFrame(clf.predict_proba(X), columns=clf.classes_)
probabilities['Y'] = y
probabilities.columns.name = 'Classes'
print(probabilities.sort_values(1))
我的结果如下
Classes 0 1 2 Y
0 1.0 0.0 0.0 0
115 0.0 0.0 1.0 2
114 0.0 0.0 1.0 2
113 0.0 0.0 1.0 2
112 0.0 0.0 1.0 2
111 0.0 0.0 1.0 2
110 0.0 0.0 1.0 2
109 0.0 0.0 1.0 2
108 0.0 0.0 1.0 2
107 0.0 0.0 1.0 2
105 0.0 0.0 1.0 2
104 0.0 0.0 1.0 2
103 0.0 0.0 1.0 2
102 0.0 0.0 1.0 2
101 0.0 0.0 1.0 2
100 0.0 0.0 1.0 2
148 0.0 0.0 1.0 2
49 1.0 0.0 0.0 0
48 1.0 0.0 0.0 0
47 1.0 0.0 0.0 0
116 0.0 0.0 1.0 2
46 1.0 0.0 0.0 0
117 0.0 0.0 1.0 2
120 0.0 0.0 1.0 2
147 0.0 0.0 1.0 2
146 0.0 0.0 1.0 2
145 0.0 0.0 1.0 2
144 0.0 0.0 1.0 2
143 0.0 0.0 1.0 2
142 0.0 0.0 1.0 2
.. ... ... ... ..
63 0.0 1.0 0.0 1
59 0.0 1.0 0.0 1
58 0.0 1.0 0.0 1
55 0.0 1.0 0.0 1
54 0.0 1.0 0.0 1
53 0.0 1.0 0.0 1
51 0.0 1.0 0.0 1
50 0.0 1.0 0.0 1
61 0.0 1.0 0.0 1
99 0.0 1.0 0.0 1
76 0.0 1.0 0.0 1
79 0.0 1.0 0.0 1
96 0.0 1.0 0.0 1
95 0.0 1.0 0.0 1
94 0.0 1.0 0.0 1
93 0.0 1.0 0.0 1
92 0.0 1.0 0.0 1
91 0.0 1.0 0.0 1
90 0.0 1.0 0.0 1
78 0.0 1.0 0.0 1
89 0.0 1.0 0.0 1
87 0.0 1.0 0.0 1
86 0.0 1.0 0.0 1
85 0.0 1.0 0.0 1
84 0.0 1.0 0.0 1
82 0.0 1.0 0.0 1
81 0.0 1.0 0.0 1
80 0.0 1.0 0.0 1
88 0.0 1.0 0.0 1
74 0.0 1.0 0.0 1
如您所见,两种方法中每个数据点的 class 1
概率值并不相等。考虑数据点 88
,在方法 1 中为 0
,在方法 2 中为 1
。
因此,我想知道在 python 中执行此操作的正确方法是什么。注意:我想执行 10-fold cross validation
以获得我的概率值。
如果需要,我很乐意提供更多详细信息。
我已经为您添加了一小部分代码。擦除最后的打印,可以添加以下代码来查看两个预测的区别:
probabilities['other methode'] = proba[:,1]
probabilities['diff'] = probabilities[1]-probabilities['other method']
probabilities[probabilities['diff'] != 0]
结果如下:
Classes 0 1 2 Y other method diff
20 1.0 0.0 0.0 0 0.1 -0.1
36 1.0 0.0 0.0 0 0.1 -0.1
41 1.0 0.0 0.0 0 0.1 -0.1
50 0.0 1.0 0.0 1 0.9 0.1
52 0.0 0.9 0.1 1 1.0 -0.1
56 0.0 0.9 0.1 1 1.0 -0.1
57 0.0 0.9 0.1 1 1.0 -0.1
59 0.0 1.0 0.0 1 0.9 0.1
60 0.0 0.9 0.1 1 1.0 -0.1
68 0.0 0.9 0.1 1 1.0 -0.1
... ... ... ... ... ... ...
123 0.0 0.2 0.8 2 0.4 -0.2
127 0.0 0.2 0.8 2 0.1 0.1
129 0.0 0.1 0.9 2 0.6 -0.5
133 0.0 0.1 0.9 2 0.9 -0.8
134 0.0 0.2 0.8 2 0.6 -0.4
137 0.0 0.0 1.0 2 0.1 -0.1
138 0.0 0.3 0.7 2 0.6 -0.3
141 0.0 0.0 1.0 2 0.1 -0.1
142 0.0 0.0 1.0 2 0.1 -0.1
146 0.0 0.0 1.0 2 0.1 -0.1
您会发现这两者之间确实存在 29 个元素的差异。
那你为什么要问?嗯,这是因为你没有以同样的方式训练算法:
clf.fit(X, y)
clf.predict_proba(X)
和
cross_val_predict(clf, X, y, cv=k_fold, method='predict_proba')
不一样。对于一个,您使用交叉验证方法来确保稳健性,而在另一个中,您只训练一次。
结果会有所不同,但在大多数情况下相差不大。例如,如果我们删除 diff <0.1 的所有元素,那么我们只会得到 12 个元素。
CVkfold 正在帮助处理不明确的术语,它必须是它们。
希望能帮助到你。如果您有疑问,请告诉我。
编辑
回答评论是的,简历是个更好的主意。
在你更新之后,我认为最好的方法是使用你在开始时已有的数据框,然后对其进行排序:
df = pd.DataFrame(index=['x1','x2',...,'x1000'],columns=['prediction_class_1']).fillna(0)
df['prediction_class_1'] = clf.predict(X) #clf trained and X the features values
print(df.sort_values('prediction_class_1'))
X = train[['feature1','feature2', ........,'featuren']].values
我有一个包含 1000 个数据点的数据集。每个数据点都分配了标签 1
或 0
,如下所示。
我的数据集:
node, feature1, feature2, ........, Label
x1, 0.8, 0.9, ........, 1
x2, 0.2, 0.6, ........, 1
...
x999, 0.1, 0.1, ........, 0
x1000,0.8, 0.9, ........, 1
我想执行二进制 class 化并根据 class 1
的预测概率对我的数据点进行排名。为此,我目前在 sklearn 中使用 predict_proba
函数。所以我的输出应该如下所示。
我的预期输出:
node prediction_probability_of_class_1
x8, 1.0
x5, 1.0
x990,0.95
x78, 0.92
x85, 0.91
x6, 0.90
and so on ........
一段时间以来,我一直在尝试使用以下两种方法来做到这一点。但是,我得到的结果彼此不匹配。所以,我认为我的一种方法(或两种方法)都是不正确的。
由于我的数据集属于我的公司并且包含敏感数据,我将使用具有 150 个数据点的 iris dataset
展示我的两种方法。
from sklearn import datasets
iris = datasets.load_iris()
X = iris.data
y = iris.target
我的做法一:
#random forest classifier
clf=RandomForestClassifier(n_estimators=10, random_state = 42, class_weight="balanced")
#perform 10 fold cross validation
k_fold = StratifiedKFold(n_splits=10, shuffle=True, random_state=0)
#get predict_proba for each instance
proba = cross_val_predict(clf, X, y, cv=k_fold, method='predict_proba')
#get the probability of class 1
print(proba[:,1])
#get the datapoint index of each probaility
print(np.argsort(proba[:,1]))
所以我的结果如下所示。
#probaility of each data point for class 1
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.1 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0.2 0. 0. 0. 0. 0.1 0. 0. 0. 0. 0. 0. 0. 0. 0.9 1. 0.7 1.
1. 1. 1. 0.7 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0.9 0.9 0.1 1.
0.6 1. 1. 1. 0.9 0. 1. 1. 1. 1. 1. 0.4 0.9 0.9 1. 1. 1. 0.9
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0.9 0.
0.1 0. 0. 0. 0. 0. 0. 0. 0.1 0. 0. 0.8 0. 0.1 0. 0.1 0. 0.1
0.3 0.2 0. 0.6 0. 0. 0. 0.6 0.4 0. 0. 0. 0.8 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. ]
#corresponding index of the above data points
[ 0 113 112 111 110 109 107 105 104 114 103 101 100 77 148 49 48 47
46 102 115 117 118 147 146 145 144 143 142 141 140 139 137 136 135 132
131 130 128 124 122 120 45 44 149 42 15 26 16 17 18 19 20 21
22 43 23 24 35 34 33 32 31 30 29 28 27 37 13 25 9 10
7 6 5 4 3 8 11 2 1 38 39 40 12 108 116 41 121 70
14 123 125 36 127 126 134 83 72 133 129 52 57 119 138 89 76 50
84 106 85 69 68 97 98 66 65 64 63 62 61 67 60 58 56 55
54 53 51 59 71 73 75 96 95 94 93 92 91 90 88 87 86 82
81 80 79 78 99 74]
我的方法二:
由于cross_val_predict
我使用的上面没有fit
方法,所以我无法访问clf.classes_
等数据。因此,我使用下面的代码。
cv_1 = cross_val_score(clf, X, y, cv=k_fold)
clf.fit(X, y)
probabilities = pd.DataFrame(clf.predict_proba(X), columns=clf.classes_)
probabilities['Y'] = y
probabilities.columns.name = 'Classes'
print(probabilities.sort_values(1))
我的结果如下
Classes 0 1 2 Y
0 1.0 0.0 0.0 0
115 0.0 0.0 1.0 2
114 0.0 0.0 1.0 2
113 0.0 0.0 1.0 2
112 0.0 0.0 1.0 2
111 0.0 0.0 1.0 2
110 0.0 0.0 1.0 2
109 0.0 0.0 1.0 2
108 0.0 0.0 1.0 2
107 0.0 0.0 1.0 2
105 0.0 0.0 1.0 2
104 0.0 0.0 1.0 2
103 0.0 0.0 1.0 2
102 0.0 0.0 1.0 2
101 0.0 0.0 1.0 2
100 0.0 0.0 1.0 2
148 0.0 0.0 1.0 2
49 1.0 0.0 0.0 0
48 1.0 0.0 0.0 0
47 1.0 0.0 0.0 0
116 0.0 0.0 1.0 2
46 1.0 0.0 0.0 0
117 0.0 0.0 1.0 2
120 0.0 0.0 1.0 2
147 0.0 0.0 1.0 2
146 0.0 0.0 1.0 2
145 0.0 0.0 1.0 2
144 0.0 0.0 1.0 2
143 0.0 0.0 1.0 2
142 0.0 0.0 1.0 2
.. ... ... ... ..
63 0.0 1.0 0.0 1
59 0.0 1.0 0.0 1
58 0.0 1.0 0.0 1
55 0.0 1.0 0.0 1
54 0.0 1.0 0.0 1
53 0.0 1.0 0.0 1
51 0.0 1.0 0.0 1
50 0.0 1.0 0.0 1
61 0.0 1.0 0.0 1
99 0.0 1.0 0.0 1
76 0.0 1.0 0.0 1
79 0.0 1.0 0.0 1
96 0.0 1.0 0.0 1
95 0.0 1.0 0.0 1
94 0.0 1.0 0.0 1
93 0.0 1.0 0.0 1
92 0.0 1.0 0.0 1
91 0.0 1.0 0.0 1
90 0.0 1.0 0.0 1
78 0.0 1.0 0.0 1
89 0.0 1.0 0.0 1
87 0.0 1.0 0.0 1
86 0.0 1.0 0.0 1
85 0.0 1.0 0.0 1
84 0.0 1.0 0.0 1
82 0.0 1.0 0.0 1
81 0.0 1.0 0.0 1
80 0.0 1.0 0.0 1
88 0.0 1.0 0.0 1
74 0.0 1.0 0.0 1
如您所见,两种方法中每个数据点的 class 1
概率值并不相等。考虑数据点 88
,在方法 1 中为 0
,在方法 2 中为 1
。
因此,我想知道在 python 中执行此操作的正确方法是什么。注意:我想执行 10-fold cross validation
以获得我的概率值。
如果需要,我很乐意提供更多详细信息。
我已经为您添加了一小部分代码。擦除最后的打印,可以添加以下代码来查看两个预测的区别:
probabilities['other methode'] = proba[:,1]
probabilities['diff'] = probabilities[1]-probabilities['other method']
probabilities[probabilities['diff'] != 0]
结果如下:
Classes 0 1 2 Y other method diff
20 1.0 0.0 0.0 0 0.1 -0.1
36 1.0 0.0 0.0 0 0.1 -0.1
41 1.0 0.0 0.0 0 0.1 -0.1
50 0.0 1.0 0.0 1 0.9 0.1
52 0.0 0.9 0.1 1 1.0 -0.1
56 0.0 0.9 0.1 1 1.0 -0.1
57 0.0 0.9 0.1 1 1.0 -0.1
59 0.0 1.0 0.0 1 0.9 0.1
60 0.0 0.9 0.1 1 1.0 -0.1
68 0.0 0.9 0.1 1 1.0 -0.1
... ... ... ... ... ... ...
123 0.0 0.2 0.8 2 0.4 -0.2
127 0.0 0.2 0.8 2 0.1 0.1
129 0.0 0.1 0.9 2 0.6 -0.5
133 0.0 0.1 0.9 2 0.9 -0.8
134 0.0 0.2 0.8 2 0.6 -0.4
137 0.0 0.0 1.0 2 0.1 -0.1
138 0.0 0.3 0.7 2 0.6 -0.3
141 0.0 0.0 1.0 2 0.1 -0.1
142 0.0 0.0 1.0 2 0.1 -0.1
146 0.0 0.0 1.0 2 0.1 -0.1
您会发现这两者之间确实存在 29 个元素的差异。 那你为什么要问?嗯,这是因为你没有以同样的方式训练算法:
clf.fit(X, y)
clf.predict_proba(X)
和
cross_val_predict(clf, X, y, cv=k_fold, method='predict_proba')
不一样。对于一个,您使用交叉验证方法来确保稳健性,而在另一个中,您只训练一次。
结果会有所不同,但在大多数情况下相差不大。例如,如果我们删除 diff <0.1 的所有元素,那么我们只会得到 12 个元素。 CVkfold 正在帮助处理不明确的术语,它必须是它们。 希望能帮助到你。如果您有疑问,请告诉我。
编辑
回答评论是的,简历是个更好的主意。 在你更新之后,我认为最好的方法是使用你在开始时已有的数据框,然后对其进行排序:
df = pd.DataFrame(index=['x1','x2',...,'x1000'],columns=['prediction_class_1']).fillna(0)
df['prediction_class_1'] = clf.predict(X) #clf trained and X the features values
print(df.sort_values('prediction_class_1'))
X = train[['feature1','feature2', ........,'featuren']].values