引言
机器学习是如今人工智能时代背景下一个重要的领域。这个“Python快速实战机器学习”系列,用Python代码实践机器学习里面的算法,旨在理论和实践同时进行,快速掌握知识。
概要
1、认识非线性问题,并理解采用更高维度解决的思路;
2、初步理解核函数,并记住高斯核的表达式;
3、学会sklearn中的非线性SVM方法。
非线性问题
SVM之所以受欢迎度这么高,另一个重要的原因是它很容易核化(kernelized),能够解决非线性分类问题。
在讨论核SVM细节之前,我们先自己创造一个非线性数据集,看看他长什么样子。
import matplotlib.pyplot as pltimport numpy as np
np.random.seed(0)X_xor = np.random.randn(200, 2)y_xor = np.logical_xor(X_xor[:, 0] > 0, X_xor[:, 1] > 0)print (y_xor)y_xor = np.where(y_xor, 1, -1)print (y_xor)
plt.scatter(X_xor[y_xor == 1, 0], X_xor[y_xor == 1, 1], c='b', marker='x', label='1')plt.scatter(X_xor[y_xor == -1, 0], X_xor[y_xor == -1, 1], c='r', marker='s', label='-1')
plt.xlim([-3, 3])plt.ylim([-3, 3])plt.legend(loc='best')plt.tight_layout()# plt.savefig('./figures/xor.png', dpi=300)plt.show()
其中数据为X_xor,一共200个二维的数据点,我们根据两个维度是否大于0来分类,如下图所示。我们把X_xor分成两类,红色类为第一和第三象限数据,两个坐标全部大于0或者全部小于0;另外一类蓝色类在第二和第四象限。
显然,如果要用线性超平面将正负类分开是不可能的,所以前面介绍的线性逻辑回归和线性SVM都鞭长莫及。
核方法的idea是为了解决线性不可分数据,在原来特征基础上创造出非线性的组合,然后利用映射函数将现有特征维度映射到更高维的特征空间,并且这个高维度特征空间能够使得原来线性不可分数据变成了线性可分的。
举个例子,下图中,我们将两维的数据映射到三维特征空间,数据集也有线性不可分变成了线性可分,
使用的映射为:
注意看右上角子图到右下角子图的转变,高维空间中的线性决策界实际上是低维空间的非线性决策界,这个非线性决策界是线性分类器找不到的,而核方法找到了。
核方法
使用SVM解决非线性问题,我们通过映射函数将训练集映射到高维特征空间,然后训练一个线性SVM模型在新特征空间将数据分类。然后,我们可以使用相同的映射函数对测试集数据分类。
上面的想法很不错,但是如何构建新特征是非常困难的,尤其是数据本身就是高维数据时。因此,我们就要介绍核技巧了。我们直接定义核函数:
常用的一个核函数是Radial Basis Function kernel(RBF核),也称为高斯核:
通俗地讲,核(kernel)可以被解释为两个样本之间的相似形函数。高斯核中e的指数范围<=0,因此高斯核值域范围为[0,1],特别地,当两个样本完全一样时,值为1,两个样本完全不同时,值为0.
在第一节的例子中,我们手动找到了一个可以精确表达的映射函数成功,而核函数的引入是为了让程序自己找到合适的参数来构建一个不是人为选择的核来完成分类。
sklearn非线性SVM
有了核函数的概念,我们就动手训练一个核SVM,看看是否能够对线性不可分数据集正确分类:
from matplotlib.colors import ListedColormapimport matplotlib.pyplot as pltimport warnings
def versiontuple(v): return tuple(map(int, (v.split("."))))
def plot_decision_regions(X, y, classifier, test_idx=None, resolution=0.02):
# setup marker generator and color map markers = ('s', 'x', 'o', '^', 'v') colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan') cmap = ListedColormap(colors[:len(np.unique(y))])
# plot the decision surface x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution)) Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) Z = Z.reshape(xx1.shape) plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap) plt.xlim(xx1.min(), xx1.max()) plt.ylim(xx2.min(), xx2.max())
for idx, cl in enumerate(np.unique(y)): plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], alpha=0.6, c=cmap(idx), edgecolor='black', marker=markers[idx], label=cl)
# highlight test samples if test_idx: # plot all samples if not versiontuple(np.__version__) >= versiontuple('1.9.0'): X_test, y_test = X[list(test_idx), :], y[list(test_idx)] warnings.warn('Please update to NumPy 1.9.0 or newer') else: X_test, y_test = X[test_idx, :], y[test_idx]
plt.scatter(X_test[:, 0], X_test[:, 1], c='', alpha=1.0, edgecolor='black', linewidths=1, marker='o', s=55, label='test set')
from sklearn.svm import SVCsvm = SVC(kernel='rbf', random_state=0, gamma=0.10, C=10.0)svm.fit(X_xor, y_xor)plot_decision_regions(X_xor, y_xor, classifier=svm)
plt.legend(loc='upper left')plt.tight_layout()plt.show()
其中参数gamma可以被理解为高斯球面的阶段参数,如果我们增大gamma值,会产生更加柔软的决策界。
运行结果:
前面的课程:
本文分享自 Python与机器学习之路 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!