提交 b8fd8884 编写于 作者: W wizardforcel

14-15

上级 fe652345
十四、K 最近邻
> 作者:[Chris Albon](https://chrisalbon.com/)
>
> 译者:[飞龙](https://github.com/wizardforcel)
>
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
## 确定 K 的最佳值
![](img/cd28dcfca524b96afc6ddf81d6f0c298.jpg)
```py
# 加载库
from sklearn.neighbors import KNeighborsClassifier
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.model_selection import GridSearchCV
# 加载数据
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 创建标准化器
standardizer = StandardScaler()
# 标准化特征
X_std = standardizer.fit_transform(X)
# 拟合 5 个邻居的 KNN 分类器
knn = KNeighborsClassifier(n_neighbors=5, metric='euclidean', n_jobs=-1).fit(X_std, y)
# 创建流水线
pipe = Pipeline([('standardizer', standardizer), ('knn', knn)])
# 创建候选值空间
search_space = [{'knn__n_neighbors': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}]
# 创建网格搜索
clf = GridSearchCV(pipe, search_space, cv=5, verbose=0).fit(X_std, y)
# 最佳邻居大小(K)
clf.best_estimator_.get_params()['knn__n_neighbors']
# 6
```
## KNN 分类
K 最近邻分类器(KNN)是一种简单而强大的分类学习器。
KNN 有三个基本部分
* $y_i$: 观测的类别(我们试图在测试数据中预测的东西)。
* $X_i$: 观察的预测因子/ IV /属性。
* $K$: 研究者指定的正数。 K 表示最接近特定观测的观测数,它定义了“邻域”。 例如,`K = 2`意味着每个观测都有一个邻域,包含最接近它的另外两个观测。
想象一下,我们有一个观测,我们知道它的自变量 $x_{test}$,但不知道它的类别 $y_{test}$。 KNN 学习器找到最接近 $x_{test}$ 的K个其他观测,并使用他们已知的类别,将类别分配给 $x_{test}$。
```py
import pandas as pd
from sklearn import neighbors
import numpy as np
%matplotlib inline
import seaborn
```
这里我们创建三个变量,`test_1``test_2`是我们的自变量,`outcome`是我们的因变量。 我们将使用这些数据来训练我们的学习器。
```py
training_data = pd.DataFrame()
training_data['test_1'] = [0.3051,0.4949,0.6974,0.3769,0.2231,0.341,0.4436,0.5897,0.6308,0.5]
training_data['test_2'] = [0.5846,0.2654,0.2615,0.4538,0.4615,0.8308,0.4962,0.3269,0.5346,0.6731]
training_data['outcome'] = ['win','win','win','win','win','loss','loss','loss','loss','loss']
training_data.head()
```
| | test_1 | test_2 | outcome |
| --- | --- | --- | --- |
| 0 | 0.3051 | 0.5846 | win |
| 1 | 0.4949 | 0.2654 | win |
| 2 | 0.6974 | 0.2615 | win |
| 3 | 0.3769 | 0.4538 | win |
| 4 | 0.2231 | 0.4615 | win |
这不是必需的,但因为我们只有三个变量,所以我们可以绘制训练数据集。 X 轴和 Y 轴是自变量,而点的颜色是它们的类别。
```py
seaborn.lmplot('test_1', 'test_2', data=training_data, fit_reg=False,hue="outcome", scatter_kws={"marker": "D","s": 100})
# <seaborn.axisgrid.FacetGrid at 0x11008aeb8>
```
![png](https://chrisalbon.com/machine_learning/nearest_neighbors/k-nearest_neighbors_classifer/k-nearest_neighbors_classifer_9_1.png)
`scikit-learn`库需要将数据格式化为`numpy`数组。 这是重新格式化的代码。
```py
X = training_data.as_matrix(columns=['test_1', 'test_2'])
y = np.array(training_data['outcome'])
```
这是我们的重点。 我们使用“观测的邻域是其三个最近的邻居”的参数来训练 KNN 学习器。 `weights ='uniform'`可以当做所用的投票系统。 例如,`uniform`意味着所有邻居对观测的类别进行同等权重的“投票”,而`weight ='distance'`则告诉学习器根据到我们正在分类的观测的距离,来调整每个观测的“投票”。
```py
clf = neighbors.KNeighborsClassifier(3, weights = 'uniform')
trained_model = clf.fit(X, y)
```
与训练数据相比,我们训练的模型有多好?
```py
trained_model.score(X, y)
# 0.80000000000000004
```
我们的模型准确率达 80%!
注:在任何现实世界的例子中,我们都希望将训练的模型与一些保留的测试数据进行比较。 但由于这是一个玩具示例,我使用了训练数据。
现在我们已经训练了我们的模型,我们可以预测班级的任何新观测,$y_{test}$。 我们现在就这样做吧!
```py
# 使用 'test_1' 第一个和第二个自变量的值
# 创建一个新观测,为 .4 和 .6
x_test = np.array([[.4,.6]])
# 将学习者应用于新的未分类的观测。
trained_model.predict(x_test)
# array(['loss'], dtype=object)
```
好哇! 我们可以看到学习器预测的新观测的类是“输”。
我们甚至可以查看学习器分配给每个分类的概率:
```py
trained_model.predict_proba(x_test)
# array([[ 0.66666667, 0.33333333]])
```
根据这个结果,模型预测观测结果是“输”的概率约为 67%,“赢”的概率为 33%。 因为观测有更大的“输”的概率,所以它预测为这个分类。
## 注
* K 的选择对创建的分类器有重大影响。
* K 越大,决策边界越线性(高偏差和低方差)。
* 有多种方法可以测量距离,两种流行的方法是简单的欧几里德距离和余弦相似度。
# 基于半径的 KNN 分类器
![](img/371afefc20188fb5874a852c50bce6c5.jpg)
```py
# 加载库
from sklearn.neighbors import RadiusNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn import datasets
# 加载数据
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 创建标准化器
standardizer = StandardScaler()
# 标准化特征
X_std = standardizer.fit_transform(X)
```
在 scikit-learn 中,`RadiusNeighborsClassifier``KNeighborsClassifier`非常相似,但有两个参数除外。 首先,在`RadiusNeighborsClassifier`中,我们需要指定固定区域的半径,用于确定观测是否是半径内的邻居。 将半径设置为某个值,最好将其视为任何其他超参数,并在模型选择期间对其进行调整。 第二个有用的参数是`outlier_label`,它表示半径内没有观测的观测的标签 - 这本身通常可以是识别异常值的有用工具。
```py
# 训练半径邻居分类器
rnn = RadiusNeighborsClassifier(radius=.5, n_jobs=-1).fit(X_std, y)
# 创建两个观测
new_observations = [[ 1, 1, 1, 1]]
# 预测两个观测的类别
rnn.predict(new_observations)
# array([2])
```
\ No newline at end of file
# 十五、支持向量机
> 作者:[Chris Albon](https://chrisalbon.com/)
>
> 译者:[飞龙](https://github.com/wizardforcel)
>
> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/)
## 校准 SVC 中的预测概率
SVC 使用超平面来创建决策区域,不会自然输出观察是某一类成员的概率估计。 但是,我们实际上可以通过一些技巧输出校准的类概率。 在 SVC 中,可以使用 Platt 缩放,其中首先训练 SVC,然后训练单独的交叉验证逻辑回归来将 SVC 输出映射到概率:
$P(y=1 \mid x)={\frac {1}{1+e^{(A*f(x)+B)}}}$
其中 $A$ 和 $B$ 是参数向量,$f$ 是第 $i$ 个观测点与超平面的有符号距离。 当我们有两个以上的类时,使用 Platt 缩放的扩展。
在 scikit-learn 中,必须在训练模型时生成预测概率。 这可以通过将`SVC``probability`设置为`True`来完成。 在训练模型之后,我们可以使用`predict_proba`输出每个类的估计概率。
```py
# 加载库
from sklearn.svm import SVC
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np
# 加载数据
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 标准化特征
scaler = StandardScaler()
X_std = scaler.fit_transform(X)
# 创建支持向量分类器对象
svc = SVC(kernel='linear', probability=True, random_state=0)
# 训练分类器
model = svc.fit(X_std, y)
# 创建新的观测
new_observation = [[.4, .4, .4, .4]]
# 查看预测的概率
model.predict_proba(new_observation)
# array([[ 0.00588822, 0.96874828, 0.0253635 ]])
```
## 寻找最近邻
```py
# 加载库
from sklearn.neighbors import NearestNeighbors
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np
# 加载数据
iris = datasets.load_iris()
X = iris.data
y = iris.target
```
在计算任何距离之前标准化我们的数据非常重要。
```py
# 创建标准化器
standardizer = StandardScaler()
# 标准化特征
X_std = standardizer.fit_transform(X)
# 根据欧氏距离找到三个最近邻居(包括其自身)
nn_euclidean = NearestNeighbors(n_neighbors=3, metric='euclidean').fit(X)
# 列表的列表,表示每个观测的 3 个最近邻
nearest_neighbors_with_self = nn_euclidean.kneighbors_graph(X).toarray()
# 删除距离自身最近的一个观测
for i, x in enumerate(nearest_neighbors_with_self):
x[i] = 0
# 查看第一个观测的两个最近邻
nearest_neighbors_with_self[0]
'''
array([ 0., 0., 0., 0., 1., 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., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0.])
'''
```
## 寻找支持向量
![](img/3c3fec0241cfa4c4f5bb78c571a0f884.jpg)
```py
# 加载库
from sklearn.svm import SVC
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np
# 加载只有两个分类的数据
iris = datasets.load_iris()
X = iris.data[:100,:]
y = iris.target[:100]
# 标准化特征
scaler = StandardScaler()
X_std = scaler.fit_transform(X)
# 创建支持向量对象
svc = SVC(kernel='linear', random_state=0)
# 训练分类器
model = svc.fit(X_std, y)
# 查看支持向量
model.support_vectors_
'''
array([[-0.5810659 , 0.43490123, -0.80621461, -0.50581312],
[-1.52079513, -1.67626978, -1.08374115, -0.8607697 ],
[-0.89430898, -1.46515268, 0.30389157, 0.38157832],
[-0.5810659 , -1.25403558, 0.09574666, 0.55905661]])
'''
# 查看支持向量的下标
model.support_
# array([23, 41, 57, 98], dtype=int32)
# 查看每个分类的支持向量数
model.n_support_
# array([2, 2], dtype=int32)
```
## SVM 不平衡分类
在支持向量机中,$C$ 是一个超参数,用于确定对观测的错误分类的惩罚。 处理支持向量机中处理不平衡类的一种方法是按类加权 $C$。
$C_k = C * w_j$
其中 $C$ 是错误分类的惩罚,$w_j$ 是与类 $j$ 频率成反比的权重,$C_j$ 是类 $j$ 的 $C$ 值。 一般的想法是,增加对少数类的错误分类的惩罚,来防止他们被多数类“淹没”。
在 scikit-learn 中,当使用`SVC`时,我们可以通过设置`class_weight ='balanced'`来自动设置 $C_j$ 的值.`balance`参数自动对类进行加权,使得:
$w_j = \frac{n}{kn_{j}}$
其中 $w_j$ 是类 $j$ 的权重,$n$ 是观察数,$n_j$ 是类 $j$ 中的观测数,$k$ 是类的总数。
```py
# 加载库
from sklearn.svm import SVC
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np
# 加载只有两个类别的数据
iris = datasets.load_iris()
X = iris.data[:100,:]
y = iris.target[:100]
# 通过删除前 40 个观察值使类高度不平衡
X = X[40:,:]
y = y[40:]
# 创建目标向量,表示类别是否为 0
y = np.where((y == 0), 0, 1)
# 标准化特征
scaler = StandardScaler()
X_std = scaler.fit_transform(X)
# 创建支持向量分类器
svc = SVC(kernel='linear', class_weight='balanced', C=1.0, random_state=0)
# 训练分类器
model = svc.fit(X_std, y)
```
## 绘制支持向量分类器超平面
![](img/3f0ca2e88676e335b8b20523ff94fec7.jpg)
```py
# 加载库
from sklearn.svm import LinearSVC
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np
from matplotlib import pyplot as plt
# 加载只有两个分类和两个特征数据
iris = datasets.load_iris()
X = iris.data[:100,:2]
y = iris.target[:100]
# 标准化特征
scaler = StandardScaler()
X_std = scaler.fit_transform(X)
# 创建支持向量分类器
svc = LinearSVC(C=1.0)
# 训练模型
model = svc.fit(X_std, y)
```
在该可视化中,类 0 的所有观测都是黑色的,类 1 的观测是浅灰色的。 超平面是决定新观测如何分类的决策边界。 具体而言,直线上方的任何观察将分为类 0,而下方的任何观测将分为类 1。
```py
# 使用他们的类别绘制数据点和颜色
color = ['black' if c == 0 else 'lightgrey' for c in y]
plt.scatter(X_std[:,0], X_std[:,1], c=color)
# 创建超平面
w = svc.coef_[0]
a = -w[0] / w[1]
xx = np.linspace(-2.5, 2.5)
yy = a * xx - (svc.intercept_[0]) / w[1]
# 绘制超平面
plt.plot(xx, yy)
plt.axis("off"), plt.show();
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/plot_support_vector_classifier_hyperplane/plot_support_vector_classifier_hyperplane_11_0.png)
## 使用 RBF 核时的 SVM 参数
在本教程中,我们将使用径向基函数核(RBF)直观地探索支持向量分类器(SVC)中两个参数的影响。 本教程主要依据 Sebastian Raschka 的书 [Python Machine Learning](http://amzn.to/2iyMbpA) 中使用的代码。
```py
# 导入可视化分类器的包
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
import warnings
# 导入执行分类的包
import numpy as np
from sklearn.svm import SVC
```
您可以忽略以下代码。 它用于可视化分类器的决策区域。 但是,本教程中,不了解函数的工作原理并不重要。
```py
def versiontuple(v):
return tuple(map(int, (v.split("."))))
def plot_decision_regions(X, y, classifier, test_idx=None, resolution=0.02):
# 配置标记生成器和颜色表
markers = ('s', 'x', 'o', '^', 'v')
colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
cmap = ListedColormap(colors[:len(np.unique(y))])
# 绘制决策平面
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.8, c=cmap(idx),
marker=markers[idx], label=cl)
# 高亮测试样本
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,
linewidths=1,
marker='o',
s=55, label='test set')
```
在这里,我们生成一些非线性可分的数据,我们将用它们训练我们的分类器。 此数据类似于您的训练数据集。 我们的`y`向量中有两个类:蓝色`x`和红色方块。
```py
np.random.seed(0)
X_xor = np.random.randn(200, 2)
y_xor = np.logical_xor(X_xor[:, 0] > 0,
X_xor[:, 1] > 0)
y_xor = np.where(y_xor, 1, -1)
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.show()
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/svc_parameters_using_rbf_kernel/svc_parameters_using_rbf_kernel_9_0.png)
使用 SVC 的最基本方法是使用线性核,这意味着决策边界是一条直线(或更高维度的超平面)。 线性核在实践中很少使用,但我想在此处显示它,因为它是 SVC 的最基本版本。 如下所示,它在分类方面不是很好(从红色区域中的所有蓝色`X`,可以看出来)因为数据不是线性的。
```py
# 使用线性核创建SVC分类器
svm = SVC(kernel='linear', C=1, random_state=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()
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/svc_parameters_using_rbf_kernel/svc_parameters_using_rbf_kernel_11_0.png)
径向基函数是 SVC 中常用的核:
$K(\mathbf {x} ,\mathbf {x’} )=\exp \left(-{\frac {||\mathbf {x} -\mathbf {x’} ||^{2}}{2\sigma ^{2}}}\right)$
其中 $||\mathbf {x} -\mathbf {x’} ||^{2}$ 是两个数据点 $\mathbf{x}$ 和 $\mathbf{x'}$ 之间的欧几里德距离的平方。 如果你不了解,塞巴斯蒂安的书有完整的描述。 但是,对于本教程,重要的是要知道,使用 RBF 核的 SVC 分类器有两个参数:`gamma``C`
### Gamma
`gamma`是 RBF 核的一个参数,可以被认为是核的“扩展”,因此也就是决策区域。 当`gamma`较低时,决策边界的“曲线”非常低,因此决策区域非常宽。 当`gamma`较高时,决策边界的“曲线”很高,这会在数据点周围创建决策边界的孤岛。 我们将在下面非常清楚地看到它。
### C
`C`是 SVC 学习器的参数,是对数据点的错误分类的惩罚。 当`C`很小时,分类器可以使用错误分类的数据点(高偏差,低方差)。 当`C`很大时,分类器因错误分类的数据而受到严重惩罚,因此与之相反来避免任何错误分类的数据点(低偏差,高方差)。
## Gamma
在下面的四个图表中,我们将相同的 SVC-RBF 分类器应用于相同的数据,同时保持`C`不变。 每个图表之间的唯一区别是每次我们都会增加`gamma`的值。 通过这样做,我们可以直观地看到`gamma`对决策边界的影响。
### `Gamma = 0.01`
在我们的 SVC 分类器和数据的情况下,当使用像 0.01 这样的低`gamma`时,决策边界不是非常“曲线”,它只是一个巨大的拱门。
```py
# 使用 RBF 核创建 SVC 分类器
svm = SVC(kernel='rbf', random_state=0, gamma=.01, C=1)
# 训练分类器
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()
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/svc_parameters_using_rbf_kernel/svc_parameters_using_rbf_kernel_15_0.png)
### `Gamma = 1.0`
当我们将`gamma`增加到 1 时,你会发现很大的不同。 现在,决策边界开始更好地覆盖数据的延展。
```py
# 使用 RBF 核创建 SVC 分类器
svm = SVC(kernel='rbf', random_state=0, gamma=1, C=1)
# 训练分类器
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()
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/svc_parameters_using_rbf_kernel/svc_parameters_using_rbf_kernel_17_0.png)
### `Gamma = 10.0`
`gamma = 10`时,核的延展不太明显。 决策边界开始极大地受到各个数据点(即方差)的影响。
```py
# 使用 RBF 核创建 SVC 分类器
svm = SVC(kernel='rbf', random_state=0, gamma=10, C=1)
# 训练分类器
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()
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/svc_parameters_using_rbf_kernel/svc_parameters_using_rbf_kernel_19_0.png)
### `Gamma = 100.0`
对于高“伽玛”,决策边界几乎完全依赖于各个数据点,从而形成“孤岛”。 这些数据显然过拟合了。
```py
# 使用 RBF 核创建 SVC 分类器
svm = SVC(kernel='rbf', random_state=0, gamma=100, C=1)
# 训练分类器
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()
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/svc_parameters_using_rbf_kernel/svc_parameters_using_rbf_kernel_21_0.png)
## C - 惩罚参数
现在我们将对`C`重复这个过程:我们将使用相同的分类器,相同的数据,并保持`gamma`常量不变。 我们唯一要改变的是`C`,错误分类的惩罚。
### `C = 1`
使用“C = 1”,分类器明显容忍错误分类的数据点。 蓝色区域有许多红点,红色区域有蓝点。
```py
# 使用 RBF 核创建 SVC 分类器
svm = SVC(kernel='rbf', random_state=0, gamma=.01, C=1)
# 训练分类器
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()
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/svc_parameters_using_rbf_kernel/svc_parameters_using_rbf_kernel_24_0.png)
### `C = 10`
`C = 10`时,分类器对错误分类的数据点的容忍度较低,因此决策边界更严格。
```py
# 使用 RBF 核创建 SVC 分类器
svm = SVC(kernel='rbf', random_state=0, gamma=.01, C=10)
# 训练分类器
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()
```
![png](svc_parameters_using_rbf_kernel_26_0.png)
### C = 1000
When `C = 1000`, the classifier starts to become very intolerant to misclassified data points and thus the decision boundary becomes less biased and has more variance (i.e. more dependent on the individual data points).
```py
# 使用 RBF 核创建 SVC 分类器
svm = SVC(kernel='rbf', random_state=0, gamma=.01, C=1000)
# 训练分类器
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()
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/svc_parameters_using_rbf_kernel/svc_parameters_using_rbf_kernel_26_0.png)
### `C = 10000`
`C = 10000`时,分类器“非常努力”,不会对数据点进行错误分类,我们会看到过拟合的迹象。
```py
# 使用 RBF 核创建 SVC 分类器
svm = SVC(kernel='rbf', random_state=0, gamma=.01, C=10000)
# 训练分类器
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()
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/svc_parameters_using_rbf_kernel/svc_parameters_using_rbf_kernel_28_0.png)
### `C = 100000`
`C = 100000`时,对于任何错误分类的数据点,分类器都会受到严重惩罚,因此边距很小。
```py
# 使用 RBF 核创建 SVC 分类器
svm = SVC(kernel='rbf', random_state=0, gamma=.01, C=100000)
# 训练分类器
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()
```
![png](https://chrisalbon.com/machine_learning/support_vector_machines/svc_parameters_using_rbf_kernel/svc_parameters_using_rbf_kernel_30_0.png)
## 支持向量分类器
![](img/3f0ca2e88676e335b8b20523ff94fec7.jpg)
SVC 在最大化超平面边距和最小化错误分类之间取得平衡。 在 SVC 中,后者由超参数 $C$ 控制,对错误施加惩罚。`C`是 SVC 学习器的参数,是对数据点进行错误分类的惩罚。 当`C`很小时,分类器可以使用错误分类的数据点(高偏差但低方差)。 当`C`很大时,分类器因错误分类的数据而受到严重惩罚,因此向后弯曲避免任何错误分类的数据点(低偏差但高方差)。
在 scikit-learn 中,$C$ 由参数`C`确定,默认为`C = 1.0`。 我们应该将 $C$ 看做我们应该学习的算法的超参数,我们使用模型选择技术调整它。
```py
# 加载库
from sklearn.svm import LinearSVC
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
import numpy as np
# 加载特征和目标数据
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 标准化特征
scaler = StandardScaler()
X_std = scaler.fit_transform(X)
# 创建支持向量分类器
svc = LinearSVC(C=1.0)
# 训练模型
model = svc.fit(X_std, y)
# 创建新的观测
new_observation = [[-0.7, 1.1, -1.1 , -1.7]]
# 预测新观测的类别
svc.predict(new_observation)
# array([0])
```
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册