机器学习的本质就是在利用数据、样本去拟合一个函数关系。线性回归函数关系就是线性函数。非线性模型则是拟合非线性函数。但作为一个调包侠,关心的不外乎两个问题:模型如何进行拟合和如何进行预测。
在调用线性回归时,我们找到具体的class,调用fit和predict两个函数即可完成拟合和预测。幸运的是,在sklearn中大部分的模型都是这样封装的。
例如:支持向量机(svm)
什么是支持向量机?
好吧,故事是这样子的:
在很久以前的情人节,大侠要去救他的爱人,但魔鬼和他玩了一个游戏。
魔鬼在桌子上似乎有规律放了两种颜色的球,说:“你用一根棍分开它们?要求:尽量在放更多球之后,仍然适用。”
于是大侠这样放,干的不错?
然后魔鬼,又在桌上放了更多的球,似乎有一个球站错了阵营。
SVM就是试图把棍放在最佳位置,好让在棍的两边有尽可能大的间隙。
现在即使魔鬼放了更多的球,棍仍然是一个好的分界线。
然后,在SVM 工具箱中有另一个更加重要的 trick。 魔鬼看到大侠已经学会了一个trick,于是魔鬼给了大侠一个新的挑战。
现在,大侠没有棍可以很好帮他分开两种球了,现在怎么办呢?当然像所有武侠片中一样大侠桌子一拍,球飞到空中。然后,凭借大侠的轻功,大侠抓起一张纸,插到了两种球的中间。
现在,从魔鬼的角度看这些球,这些球看起来像是被一条曲线分开了。
再之后,无聊的大人们,把这些球叫做 「data」,把棍子 叫做 「classifier」, 最大间隙trick 叫做「optimization」, 拍桌子叫做「kernelling」, 那张纸叫做「hyperplane」。
来源链接:https://www.zhihu.com/question/21094489/answer/86273196
代码展示:
import numpy as np
from sklearn.svm import SVR
X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])
# y = 1 * x_0 + 2 * x_1 + 3
y = np.dot(X, np.array([1, 2])) + 3
model = SVR()
model.fit(X, y)
model.predict(X)
上述代码调用与线性回归一模一样,但实际运行会发现上述代码的精度不如线性回归。这里涉及到的主要问题:超参数。在大部分的非线性模型中,一部分参数是无法通过训练直接获得的。需要预先设定,反复调整使模型达到最优状态。这一过程叫做“调参”。
基于此,公式表示应为:y=f(h,w;x)
与线性回归公式:y=f(w;x)不同,h表示我们的超参数,可有多个超参数,但均需预先设定。w是可以通过训练出的参数。已SVR来说,它的超参数包括:核函数及其参数、惩罚系数。
代码修改如下:
#核函数:高斯核 核参数:1、惩罚系数:100
model = SVR(kernel='rbf',gamma= 1, C = 100)
model.fit(X,y)
model.predict(X)
部分符合通用模式的常用模型:
线性模型:LinearModels
神经网络:trtneural_network
支持向量机:SVM
高斯过程:gaussian_process
决策树:tree
随机森林:ensemble.RandomForestRegressor
模型调参:
sklearn调用及其学习模型非常简单,但要获得好的预测效果还需要选取合适的超参数。sklearn提供了十分简单的调参方法,可以实现对各类模型的调参。
基本思想:交叉验证
将样本拆分为 k个子集,用其中 k − 1个子集的数据训练模型,再在剩下的一个子集上验证模型的性能。当所有子集都被作为测试集轮完一圈之后,计算模型在所有子集上的平均性能。
对每一组超参数对应模型执行上述操作,选出平均性能最好的一组参数作为最优参数。
其根本目的即是寻找出一组最优超参数,使其在各种样本组合下的平均性能都能达到最优,从而认为这组参数能够使得模型具有最强的泛化性能。
思考问题:
子集划分:
- k-fold: 随机将训练集划分为k个
- leave-one-out: 将子集划分为n个,即每个子集只有一个样本
- hold-out: 将n个样本中的m个随机挑出作为测试集(也可以指定测试集)
备选参数:
- grid-search: 即给出每个超参数的备选范围,对所有组合进行穷举
- random search: 以某种方式生成多种超参数的组合,穷举所有随机生成的结果
评级模型(评价指标):
- 分类问题:分类精度、平衡精度、平均精度等
- 回归问题:最大误差、均方误差、均方根误差等
代码实现(GridSearchCV和SVR):
from sklearn import svm, datasets
from sklearn.model_selection import GridSearchCV
iris = datasets.load_iris()#鸢尾花数据集
#定义字典 key为核函数 vlaue为linear和rbf key为惩罚系数 value为1和10
parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]}
#SVC:数量少于10000时的二元和多元分类
svc = svm.SVC()
#初始化模型,函数将自动根据设定的范围对parameters中每种组合进行穷举
clf = GridSearchCV(svc, parameters)
#训练模型、拟合
clf.fit(iris.data, iris.target)
#GridSearchCV(estimator=SVC(),param_grid={'C': [1, 10], 'kernel': ('linear', 'rbf')})
print(clf.best_params_)#查看最优参数
print(clf.best_estimator_)#查看最优模型 前面调用的事SVC最优模型则反馈SVC
除了GridSearchCV之外还有RandomizedSearchCV,基本用法和参数设定几乎一样。
并行计算:
并行计算是sklearn中的另一个亮点,它对一些能够并行的方法提前进行了封装,在使用的时候只需要简单一个参数即可。在使用GridSearchCV时,添加参数:n_jobs大于等于2,代表并行核心数量。
代码修改为:
# 使用两个核心并行
clf = GridSearchCV(svc, parameters,n_jobs=2)
# 使用所有核心并行
clf = GridSearchCV(svc, parameters,n_jobs=-1)