Sklearn 自定义内核给出了错误的决策函数
Sklearn custom kernel gives wrong decision function
我已经成功地实现了我自己的自定义线性内核,它使用 clf.predict
完全可以正常工作。但是,当我想使用 clf.decision_function
时,它会为所有点提供常数值。
这是自定义内核的代码:
```
def linear_basis(x, y):
return np.dot(x.T, y)
def linear_kernel(X, Y, K=linear_basis):
gram_matrix = np.zeros((X.shape[0], Y.shape[0]))
for i, x in enumerate(X):
for j, y in enumerate(Y):
gram_matrix[i,j] = K(x,y)
return gram_matrix
```
现在将此内核用于小型线性训练集。
```
#creating random 2D points
sample_size = 100
dat = {
'x': [random.uniform(-2,2) for i in range(sample_size)],
'y': [random.uniform(-2,2) for i in range(sample_size)]
}
data = pd.DataFrame(dat)
# giving the random points a linear structure
f_lin = np.vectorize(lambda x, y: 1 if x > y else 0)
data['z_lin'] = f_lin(data['x'].values, data['y'].values)
data_pos = data[data.z_lin == 1.]
data_neg = data[data.z_lin == 0.]
X_train = data[['x', 'y']]
y_train = data[['z_lin']]
clf_custom_lin = svm.SVC(kernel=linear_kernel) # using my custom kernel here
clf_custom_lin.fit(X_train.values,y_train.values)
# creating a 100x100 grid to manually predict each point in 2D
gridpoints = np.array([[i,j] for i in np.linspace(-2,2,100) for j in np.linspace(-2,2,100)])
gridresults = np.array([clf.predict([gridpoints[k]]) for k in range(len(gridpoints))])
# now plotting each point and the training samples
plt.scatter(gridpoints[:,0], gridpoints[:,1], c=gridresults, cmap='RdYlGn')
plt.scatter(data_pos['x'], data_pos['y'], color='green', marker='o', edgecolors='black')
plt.scatter(data_neg['x'], data_neg['y'], color='red', marker='o', edgecolors='black')
plt.show()
```
结果如下:
现在我想使用clf.decision_function
重现情节:
(!请注意,我不小心在这里切换了颜色!)
```
h = .02
xx, yy = np.meshgrid(np.arange(-2 - .5, 2 + .5, h),
np.arange(-2 - .5, 2 + .5, h))
# using the .decision_function here
Z = clf_custom_lin.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.RdBu, alpha=.8)
plt.scatter(data_pos['x'], data_pos['y'], color='blue', marker='o', edgecolors='black')
plt.scatter(data_neg['x'], data_neg['y'], color='red', marker='o', edgecolors='black')
plt.show()
```
这给出了以下情节:
这是使用集成线性内核 (kernel="linear") 绘制相同数据的示例:
既然自定义内核的预测函数刚刚起作用,它应该给出与这里的决策函数相同的工作图,对吧?
我不知道为什么这适用于集成线性函数,但不适用于自定义线性函数,自定义线性函数也仅适用于没有决策函数的预测点。
实际问题确实很傻,但由于花了一些时间来查找,我将分享我调试的概要。
首先,打印 decision_function
的实际值而不是绘图:您会发现第一个结果是独一无二的,但之后的一切都是不变的。 运行 在数据集的各个切片上相同,这种模式仍然存在。所以我想也许有些值被覆盖了,于是我深入研究了 SVC
代码。这导致一些有用的内部 functions/attributes,例如包含训练数据的 ._BaseLibSVM__Xfit
,_decision_function
和 _dense_decision_function
,以及 _compute_kernel
。但是 none 的代码表明有问题,而 运行 它们只是表明了同样的问题。 运行 _compute_kernel
给出的结果在第一行之后全为零,然后回到您的代码,运行 linear_kernel
已经做到了。所以,最后,它回到了你的 linear_kernel
函数。
您 return 在 外部 for 循环中,因此您只使用 X
的第一行,从不计算矩阵的其余部分。 (这带来了一个惊喜:为什么预测看起来不错?这似乎是侥幸。改变 f_lin
的定义,改变 类,模型仍然学习 slope-1 线.)
我已经成功地实现了我自己的自定义线性内核,它使用 clf.predict
完全可以正常工作。但是,当我想使用 clf.decision_function
时,它会为所有点提供常数值。
这是自定义内核的代码:
```
def linear_basis(x, y):
return np.dot(x.T, y)
def linear_kernel(X, Y, K=linear_basis):
gram_matrix = np.zeros((X.shape[0], Y.shape[0]))
for i, x in enumerate(X):
for j, y in enumerate(Y):
gram_matrix[i,j] = K(x,y)
return gram_matrix
```
现在将此内核用于小型线性训练集。
```
#creating random 2D points
sample_size = 100
dat = {
'x': [random.uniform(-2,2) for i in range(sample_size)],
'y': [random.uniform(-2,2) for i in range(sample_size)]
}
data = pd.DataFrame(dat)
# giving the random points a linear structure
f_lin = np.vectorize(lambda x, y: 1 if x > y else 0)
data['z_lin'] = f_lin(data['x'].values, data['y'].values)
data_pos = data[data.z_lin == 1.]
data_neg = data[data.z_lin == 0.]
X_train = data[['x', 'y']]
y_train = data[['z_lin']]
clf_custom_lin = svm.SVC(kernel=linear_kernel) # using my custom kernel here
clf_custom_lin.fit(X_train.values,y_train.values)
# creating a 100x100 grid to manually predict each point in 2D
gridpoints = np.array([[i,j] for i in np.linspace(-2,2,100) for j in np.linspace(-2,2,100)])
gridresults = np.array([clf.predict([gridpoints[k]]) for k in range(len(gridpoints))])
# now plotting each point and the training samples
plt.scatter(gridpoints[:,0], gridpoints[:,1], c=gridresults, cmap='RdYlGn')
plt.scatter(data_pos['x'], data_pos['y'], color='green', marker='o', edgecolors='black')
plt.scatter(data_neg['x'], data_neg['y'], color='red', marker='o', edgecolors='black')
plt.show()
```
结果如下:
现在我想使用clf.decision_function
重现情节:
(!请注意,我不小心在这里切换了颜色!)
```
h = .02
xx, yy = np.meshgrid(np.arange(-2 - .5, 2 + .5, h),
np.arange(-2 - .5, 2 + .5, h))
# using the .decision_function here
Z = clf_custom_lin.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.RdBu, alpha=.8)
plt.scatter(data_pos['x'], data_pos['y'], color='blue', marker='o', edgecolors='black')
plt.scatter(data_neg['x'], data_neg['y'], color='red', marker='o', edgecolors='black')
plt.show()
```
这给出了以下情节:
这是使用集成线性内核 (kernel="linear") 绘制相同数据的示例:
既然自定义内核的预测函数刚刚起作用,它应该给出与这里的决策函数相同的工作图,对吧? 我不知道为什么这适用于集成线性函数,但不适用于自定义线性函数,自定义线性函数也仅适用于没有决策函数的预测点。
实际问题确实很傻,但由于花了一些时间来查找,我将分享我调试的概要。
首先,打印 decision_function
的实际值而不是绘图:您会发现第一个结果是独一无二的,但之后的一切都是不变的。 运行 在数据集的各个切片上相同,这种模式仍然存在。所以我想也许有些值被覆盖了,于是我深入研究了 SVC
代码。这导致一些有用的内部 functions/attributes,例如包含训练数据的 ._BaseLibSVM__Xfit
,_decision_function
和 _dense_decision_function
,以及 _compute_kernel
。但是 none 的代码表明有问题,而 运行 它们只是表明了同样的问题。 运行 _compute_kernel
给出的结果在第一行之后全为零,然后回到您的代码,运行 linear_kernel
已经做到了。所以,最后,它回到了你的 linear_kernel
函数。
您 return 在 外部 for 循环中,因此您只使用 X
的第一行,从不计算矩阵的其余部分。 (这带来了一个惊喜:为什么预测看起来不错?这似乎是侥幸。改变 f_lin
的定义,改变 类,模型仍然学习 slope-1 线.)