十、模型选择

作者:Chris Albon

译者:飞龙

协议:CC BY-NC-SA 4.0

在模型选择期间寻找最佳预处理步骤

在进行模型选择时,我们必须小心正确处理预处理。 首先,GridSearchCV使用交叉验证来确定哪个模型表现最好。 然而,在交叉验证中,我们假装作为测试集被留出的一折是不可见的,因此不适合一些预处理步骤(例如缩放或标准化)。 出于这个原因,我们无法预处理数据然后运行GridSearchCV

其次,一些预处理方法有自己的参数,通常必须由用户提供。 通过在搜索空间中包括候选成分值,可以像对待任何想要搜索其他超参数一样对待它们。

  1. # 加载库
  2. import numpy as np
  3. from sklearn import datasets
  4. from sklearn.feature_selection import SelectKBest
  5. from sklearn.linear_model import LogisticRegression
  6. from sklearn.model_selection import GridSearchCV
  7. from sklearn.pipeline import Pipeline, FeatureUnion
  8. from sklearn.decomposition import PCA
  9. from sklearn.preprocessing import StandardScaler
  10. # 设置随机种子
  11. np.random.seed(0)
  12. # 加载数据
  13. iris = datasets.load_iris()
  14. X = iris.data
  15. y = iris.target

我们包括两个不同的预处理步骤:主成分分析和 k 最佳特征选择。

  1. # 创建组合预处理对象
  2. preprocess = FeatureUnion([('pca', PCA()), ("kbest", SelectKBest(k=1))])
  3. # 创建流水线
  4. pipe = Pipeline([('preprocess', preprocess), ('classifier', LogisticRegression())])
  5. # 创建候选值空间
  6. search_space = [{'preprocess__pca__n_components': [1, 2, 3],
  7. 'classifier__penalty': ['l1', 'l2'],
  8. 'classifier__C': np.logspace(0, 4, 10)}]
  9. # 创建网格搜索
  10. clf = GridSearchCV(pipe, search_space, cv=5, verbose=0, n_jobs=-1)
  11. # 拟合网格搜索
  12. best_model = clf.fit(X, y)
  13. # 查看最佳超参数
  14. print('Best Number Of Princpal Components:', best_model.best_estimator_.get_params()['preprocess__pca__n_components'])
  15. print('Best Penalty:', best_model.best_estimator_.get_params()['classifier__penalty'])
  16. print('Best C:', best_model.best_estimator_.get_params()['classifier__C'])
  17. '''
  18. Best Number Of Princpal Components: 3
  19. Best Penalty: l1
  20. Best C: 59.9484250319
  21. '''

使用网格搜索的超参数调优

十、模型选择 - 图1

  1. # 加载库
  2. import numpy as np
  3. from sklearn import linear_model, datasets
  4. from sklearn.model_selection import GridSearchCV
  5. # 加载数据
  6. iris = datasets.load_iris()
  7. X = iris.data
  8. y = iris.target
  9. # 创建逻辑回归
  10. logistic = linear_model.LogisticRegression()
  11. # 创建正则化惩罚空间
  12. penalty = ['l1', 'l2']
  13. # 创建正则化超参数空间
  14. C = np.logspace(0, 4, 10)
  15. # 创建超参数选项
  16. hyperparameters = dict(C=C, penalty=penalty)
  17. # 使用 5 折交叉验证创建网格搜索
  18. clf = GridSearchCV(logistic, hyperparameters, cv=5, verbose=0)
  19. # 拟合网格搜索
  20. best_model = clf.fit(X, y)
  21. # 查看最佳超参数
  22. print('Best Penalty:', best_model.best_estimator_.get_params()['penalty'])
  23. print('Best C:', best_model.best_estimator_.get_params()['C'])
  24. '''
  25. Best Penalty: l1
  26. Best C: 7.74263682681
  27. '''
  28. # 预测目标向量
  29. best_model.predict(X)
  30. '''
  31. array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  32. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  33. 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  34. 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
  35. 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  36. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
  37. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
  38. '''

使用随机搜索的超参数调优

  1. # 加载库
  2. from scipy.stats import uniform
  3. from sklearn import linear_model, datasets
  4. from sklearn.model_selection import RandomizedSearchCV
  5. # 加载数据
  6. iris = datasets.load_iris()
  7. X = iris.data
  8. y = iris.target
  9. # 创建逻辑回归
  10. logistic = linear_model.LogisticRegression()
  11. # 创建正则化惩罚空间
  12. penalty = ['l1', 'l2']
  13. # 使用均匀分布创建正则化超参数分布
  14. C = uniform(loc=0, scale=4)
  15. # 创建超参数选项
  16. hyperparameters = dict(C=C, penalty=penalty)
  17. # 使用 5 折交叉验证和 100 个迭代
  18. clf = RandomizedSearchCV(logistic, hyperparameters, random_state=1, n_iter=100, cv=5, verbose=0, n_jobs=-1)
  19. # 拟合随机搜索
  20. best_model = clf.fit(X, y)
  21. # 查看最佳超参数
  22. print('Best Penalty:', best_model.best_estimator_.get_params()['penalty'])
  23. print('Best C:', best_model.best_estimator_.get_params()['C'])
  24. '''
  25. Best Penalty: l1
  26. Best C: 1.66808801881
  27. '''
  28. # 预测目标向量
  29. best_model.predict(X)
  30. '''
  31. array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  32. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  33. 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  34. 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1,
  35. 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  36. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2,
  37. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
  38. '''

使用网格搜索的模型选择

十、模型选择 - 图2

  1. # 加载库
  2. import numpy as np
  3. from sklearn import datasets
  4. from sklearn.linear_model import LogisticRegression
  5. from sklearn.ensemble import RandomForestClassifier
  6. from sklearn.model_selection import GridSearchCV
  7. from sklearn.pipeline import Pipeline
  8. # 设置随机种子
  9. np.random.seed(0)
  10. # 加载数据
  11. iris = datasets.load_iris()
  12. X = iris.data
  13. y = iris.target

请注意,我们包括需要搜索的多个可能的学习算法和多个可能的超参数值。

  1. # 创建流水线
  2. pipe = Pipeline([('classifier', RandomForestClassifier())])
  3. # 创建候选学习算法和它们的超参数的空间
  4. search_space = [{'classifier': [LogisticRegression()],
  5. 'classifier__penalty': ['l1', 'l2'],
  6. 'classifier__C': np.logspace(0, 4, 10)},
  7. {'classifier': [RandomForestClassifier()],
  8. 'classifier__n_estimators': [10, 100, 1000],
  9. 'classifier__max_features': [1, 2, 3]}]
  10. # 创建网格搜索
  11. clf = GridSearchCV(pipe, search_space, cv=5, verbose=0)
  12. # 拟合网格搜索
  13. best_model = clf.fit(X, y)
  14. # 查看最佳模型
  15. best_model.best_estimator_.get_params()['classifier']
  16. '''
  17. LogisticRegression(C=7.7426368268112693, class_weight=None, dual=False,
  18. fit_intercept=True, intercept_scaling=1, max_iter=100,
  19. multi_class='ovr', n_jobs=1, penalty='l1', random_state=None,
  20. solver='liblinear', tol=0.0001, verbose=0, warm_start=False)
  21. '''
  22. # 预测目标向量
  23. best_model.predict(X)
  24. '''
  25. array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  26. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  27. 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  28. 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
  29. 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  30. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
  31. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
  32. '''

带有参数选项的流水线

  1. # 导入所需的包
  2. import numpy as np
  3. from sklearn import linear_model, decomposition, datasets
  4. from sklearn.pipeline import Pipeline
  5. from sklearn.model_selection import GridSearchCV, cross_val_score
  6. from sklearn.preprocessing import StandardScaler
  7. # 加载乳腺癌数据集
  8. dataset = datasets.load_breast_cancer()
  9. # 从数据集特征中创建 X
  10. X = dataset.data
  11. # 从数据集目标中创建 y
  12. y = dataset.target
  13. # 创建缩放器对象
  14. sc = StandardScaler()
  15. # 创建 PCA 对象
  16. pca = decomposition.PCA()
  17. # 创建逻辑回归对象,带有 L2 惩罚
  18. logistic = linear_model.LogisticRegression()
  19. # 创建三步流水线。首先,标准化数据。
  20. # 其次,使用 PCA 转换数据。
  21. # 然后在数据上训练逻辑回归。
  22. pipe = Pipeline(steps=[('sc', sc),
  23. ('pca', pca),
  24. ('logistic', logistic)])
  25. # 创建 1 到 30 的一列整数(X + 1,特征序号)
  26. n_components = list(range(1,X.shape[1]+1,1))
  27. # 创建正则化参数的一列值
  28. C = np.logspace(-4, 4, 50)
  29. # 为正则化乘法创建一列选项
  30. penalty = ['l1', 'l2']
  31. # 为所有参数选项创建字典
  32. # 注意,你可以使用 '__' 来访问流水线的步骤的参数
  33. parameters = dict(pca__n_components=n_components,
  34. logistic__C=C,
  35. logistic__penalty=penalty)
  36. # 创建网格搜索对象
  37. clf = GridSearchCV(pipe, parameters)
  38. # 拟合网格搜索
  39. clf.fit(X, y)
  40. # 查看超参数
  41. print('Best Penalty:', clf.best_estimator_.get_params()['logistic__penalty'])
  42. print('Best C:', clf.best_estimator_.get_params()['logistic__C'])
  43. print('Best Number Of Components:', clf.best_estimator_.get_params()['pca__n_components'])
  44. # 使用 3 折交叉验证拟合网格搜索
  45. cross_val_score(clf, X, y)