使用sklearn实现管道和复合估计器
我们在学习机器学习的过程中会发现我们跑代码经常是首先对数据预处理标准化、降维这些,然后用模型评估,就是感觉有一个大体的步骤,所以scikit开发了一种库,里面有一个管道功能,它就可以将我们所有的步骤放到同一的管道,一并执行,类似于生产线一样,第一步的产品交给第二道部门进行处理。
1.管道(Pipline)
刚才说了管道可以将一些基本功能进行封装,他还有一些别的功能,如果我们在封装转化器的时候,有模型参与且作为最后一个,那么整个管道就可以作为一个大的评估器,也就具有fit和predict方法,既然作为了一个模型,那么我们就可以对他进行网格搜索。
下面我们用代码简单构造一个管道:
from sklearn.svm import SVC from sklearn.pipeline import Pipeline from sklearn import datasets from sklearn.model_selection import GridSearchCV from sklearn.preprocessing import MinMaxScaler X,y=datasets.load_iris(return_X_y=True) estimator=[('MinMax',MinMaxScaler()),('clf',SVC())] pipe=Pipeline(estimator) pipe.fit(X,y) pipe.score(X,y)
>>>pipe Pipeline(memory=None, steps=[('MinMax', MinMaxScaler(copy=True, feature_range=(0, 1))), ('clf', SVC(C=1.0, break_ties=False, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape='ovr', degree=3, gamma='scale', kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False))], verbose=False) >>>pipe.score(X,y) 0.98 >>>pipe.steps [('MinMax', MinMaxScaler(copy=True, feature_range=(0, 1))), ('clf', SVC(C=1.0, break_ties=False, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape='ovr', degree=3, gamma='scale', kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False))] >>>pipe['MinMax'] MinMaxScaler(copy=True, feature_range=(0, 1))
构造成功管道之后,我们可以用它来进行评分等,而且还可以通过索引或者字典方式进行访问。
我们封住好管道后,我们可以利用方法对内部的实类更换参数:
>>>pipe.set_params(clf__C=100) Pipeline(memory=None, steps=[('MinMax', MinMaxScaler(copy=True, feature_range=(0, 1))), ('clf', SVC(C=100, break_ties=False, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape='ovr', degree=3, gamma='scale', kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False))], verbose=False)
通过set_params()函数就可以对管道内部进行更改参数,参数名注意,要用管道每个部分的名字+“__”+参数+值
上面代码的意思就是将clf的c参数更改为100
之前我们说管道是一个模型,那么就可以对他进行网格搜索,用代码演示一下:
param_grid={'clf__C':[0.1,1,10], 'clf__kernel':['linear','rbf']} grid_search=GridSearchCV(pipe,param_grid,cv=3) grid_search.fit(X,y) grid_search.best_score_
我们不仅可以搜索现有的参数,我们还可以直接将模型替换,搜索不同模型。
from sklearn.linear_model import LogisticRegression param_grid = dict(clf=[SVC(), LogisticRegression()], clf__C=[99]) grid_search = GridSearchCV(pipe, param_grid=param_grid) grid_search.fit(X,y) grid_search.best_params_ {'clf': LogisticRegression(C=99, class_weight=None, dual=False, fit_intercept=True, intercept_scaling=1, l1_ratio=None, max_iter=100, multi_class='auto', n_jobs=None, penalty='l2', random_state=None, solver='lbfgs', tol=0.0001, verbose=0, warm_start=False), 'clf__C': 99}
这样我们可以用不同的模型替换clf部分,但是这么写也会存在问题,需要调整的参数必须两者共有,否则就会报错某一方缺少该参数,上述代码可以是因为svc和逻辑回归中都存在C这个参数所以说没问题。
2.特征组合(FeatureUnion)
我们有时候会进行联合特征,什么意思?就是不如一组数据我们将其标准化,然后又将原始数据进行了PCA降维,我们想联合两组处理后的特征,将它们进行按列拼接,形成多个特征列,这是我们可以使用FeatureUnion来进行操作。
其实他也类似与管道,只不过是它内部的每一种操作是并行,而管道是串行,它会将每个部分处理的数据进行拼接形成一个大的特征矩阵。
用代码演示一下:
from sklearn.pipeline import FeatureUnion from sklearn.decomposition import PCA from sklearn.preprocessing import MinMaxScaler estimator=[('pca',PCA()),('minmax',MinMaxScaler())] combined=FeatureUnion(estimator) combined.fit(X,y) >>>combined.fit_transform(X).shape (150, 7) >>>X.shape (150, 4)
FeatureUnion内部的PCA和MinMax会分别进行处理数据,PCA将原始数据将为3维,MinMax处理后与原数据等维度,所以拼接后是7维,原数据是4维。