sklearn中svm.SVC()有比较重要的参数C和gamma,默认使用径向基核(kernel=‘rbf’)。
RBF的核函数:
高斯核的RBF时,核函数:
直觉上来看,RBF核函数的参数 (gamma),效果等同于 ,决定了数据映射到新的特征空间后的分布(正态分布)。
gamma较大时,相当于正态分布中的
较小,映射出的高斯分布又高又瘦较为集中,那么单个样本对周围样本的影响力度大,范围窄,比较容易被选为支持向量,或者说整个模型的支持向量也会多,更容易过拟合。
反之,当gamma比较小时,单个样本对整个分类超平面的影响比较小,不容易被选择为支持向量,整个模型的支持向量较少。
scikit-learn中默认值是: 1 / (样本特征数*样本方差)
- if gamma=‘scale’ (default) is passed then it uses 1 / (n_features * X.var()) as value of gamma
- if ‘auto’, uses 1 / n_features.
C是惩罚系数,即对误差的宽容度。C越高,说明越不能容忍出现误差,容易过拟合。C越小,容易欠拟合。不管是 SVC(分类)还是 SVR(回归),参数C都是为了在模型准确率与模型复杂度之间取得一个平衡。sklearn中默认值是1.0。
SVC的优化目标:
模型误差的部分
被乘以一个系数 C 以后(可以看作正则项),如果 C 比较大,那么要想达到最小化的目标,模型误差就会被逼迫着尽量减小,此时模型对异常值的容忍度降低,
会尽可能多地拟合训练样本,泛化能力较差。
如果 C 比较小,那么就会鼓励模型去寻找一个较大间隔的决策边界,不强求对于训练数据完美得拟合,对极端值的容忍度比较高。此时,会牺牲一定的准确性。
SVM的网格搜索耗时太久,下面代码不要轻易尝试。
from sklearn import svm, metrics
from sklearn.datasets import fetch_mldata
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
import matplotlib.pyplot as plt
import numpy as np
import datetime as dt
if __name__ == "__main__":
mnist = fetch_mldata('MNIST original')
# dict_keys(['DESCR', 'COL_NAMES', 'target', 'data'])
print(mnist.keys())
# data field is 70k x 784 array, each row represents pixels from 28x28=784 image
images = mnist.data
targets = mnist.target
print(images.shape)
X_data = images/255.0
Y = targets
X_train, X_test, y_train, y_test = train_test_split(X_data, Y, test_size=0.15, random_state=13)
################ Classifier with Grid Search ###########
param_grid = {"gamma":[0.01, 0.05, 0.1],
"C":[1, 3.8, 5]}
print("Parameters:{}".format(param_grid))
# 开始计时
start_time = dt.datetime.now()
print('Start training at {}'.format(str(start_time)))
# 交叉验证和训练
model = GridSearchCV(svm.SVC(), param_grid, n_jobs=-1, cv=3)
model.fit(X_train,y_train)
print("Test set score:{:.2f}".format(model.score(X_test,y_test)))
print("Best parameters:{}".format(model.best_params_))
print("Best score on train set:{:.2f}".format(model.best_score_))
# 计时结束
end_time = dt.datetime.now()
elapsed_time= end_time - start_time
print('Elapsed training {}'.format(str(elapsed_time)))
################ predict ###########
predicted = model.predict(X_test)
# y_test is the True value
cm = metrics.confusion_matrix(y_test, predicted)
print("Confusion matrix:\n%s" % cm)
print("\nAccuracy={}".format(metrics.accuracy_score(y_test, predicted)))