我成功实现了自己的自定义线性核函数,使用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```
现在使用这个核函数在一个小的线性训练集上进行测试。
```#创建随机二维点sample_size = 100dat = { '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)#为随机点赋予线性结构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) #在这里使用我的自定义核函数clf_custom_lin.fit(X_train.values,y_train.values)#创建一个100x100的网格以手动预测二维中的每个点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))])#现在绘制每个点和训练样本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 = .02xx, yy = np.meshgrid(np.arange(-2 - .5, 2 + .5, h), np.arange(-2 - .5, 2 + .5, h))#在这里使用.decision_functionZ = 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
代码。这导致了一些有用的内部函数/属性,比如._BaseLibSVM__Xfit
包含训练数据,_decision_function
和_dense_decision_function
,以及_compute_kernel
。但代码中没有任何迹象表明有问题,运行它们只是显示了相同的问题。运行_compute_kernel
得到的结果在第一行之后都是零,然后回到你的代码,运行linear_kernel
已经这样做了。所以,最后,它回到了你的linear_kernel
函数。
你在外部for循环的内部返回,所以你只使用了X
的第一行,从未计算矩阵的其余部分。(这带来了一个惊喜:为什么预测看起来不错?那似乎是一个侥幸。改变f_lin
的定义,以改变类别,模型仍然学会了斜率为1的线。)