引入
数据集创建
函数:sklearn.datasets.make_blobs()
x,y = sklearn.datasets.make_blobs(n_samples=100, n_features=2, centers=3, cluster_std=1.0, center_box=(-10.0, 10.0), shuffle=True, random_state=None)
# n_samples: (default=100) 样本数目
# n_features: (default=2) 每个样本的特征数
# center: (default=3) 样本的类别数
# cluster_std: (default=1.0) 每个类别的方差(限制每个类不同方差用列表存储)
# center_box: (default=(-10.0, 10.0)) 每个类别的边界
# shuffle:(default=True)
# random_state: (default=None) 随机数种子
数据集分组
函数:sklearn.model_selection.train_test_split()
X_train,X_test, y_train, y_test =cross_validation.train_test_split(train_data,train_target,test_size=0.3, random_state=0)
train_data:样本特征集
train_target:样本结果集
test_size:样本占比,整数是测试集的数量,浮点数(0,1)为测试集占比
random_state:是随机数的种子
简单练习
from sklearn.datasets import make_blobs
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
X,y = make_blobs(random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=0)
logreg = LogisticRegression().fit(X_train,y_train)
print("Test set score:{:.2f}".format(logreg.score(X_test,y_test)))
交叉验证
简单实现
概述:
交叉验证(cross-validation)是一种评估泛化性能的统计学方法,它比单次划分训练集和测试集的方法更加稳定、全面。在交叉验证中,数据被多次划分,并且需要训练多个模型。 最常用的交叉验证是 k 折交叉验证(k-fold cross-validation),其中 $k$ 是由用户指定的数字, 通常取 5 或 10。在执行 5 折交叉验证时,首先将数据划分为(大致)相等的 5 部分,每一 部分叫作折(fold)。接下来训练一系列模型。使用第 1 折作为测试集、其他折(2~5)作 为训练集来训练第一个模型。利用 2~5 折中的数据来构建模型,然后在 1 折上评估精度。 之后构建另一个模型,这次使用 2 折作为测试集,1、3、4、5 折中的数据作为训练集。利 用 3、4、5 折作为测试集继续重复这一过程。对于将数据划分为训练集和测试集的这 5 次 划分,每一次都要计算精度。最后我们得到了 5 个精度值。
函数:sklearn.model_selection.cross_val_score()
score = sklearn.model_selection.cross_val_score(estimator, X, y=None, groups=None, scoring=None, cv=None, n_jobs=1, verbose=0, fit_params=None, pre_dispatch=‘2*n_jobs’)
# estimator: 模型
# X: 样本特征集
# y: 样本结果集
# groups: 如果数据需要分组采样使用(后面优化第四部使用)
# scoring: 评价方法
# cv: 分层数,默认为3,推荐5或10
对k层的的评分求均值得最终评分。
score.mean()
简单练习
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
iris = load_iris()
logreg = LogisticRegression()
scores = cross_val_score(logreg,iris.data,iris.target,cv=5)
print("Cross-validation scores: {}".format(scores.mean()))
优化
1. 打乱顺序交叉验证
KFold分离器类: 将数据按照特定要求进行划分
函数:sklearn.model_selection.KFold()
sklearn.model_selection.KFold(n_splits=3, shuffle=False, random_state=None)
# n_splits: 数据划分几等份
# shuffle: 是否打乱顺序
# random_state: 随机数种子
简单练习
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
iris = load_iris()
logreg = LogisticRegression()
kfold = KFold(n_splits=3,shuffle=True,random_state=0)
scores = cross_val_score(logreg, iris.data, iris.target, cv=kfold)
print("Cross-validation scores:\n{}".format(scores))
2. 留一法交叉验证
留一法:每次只取样本中的一个作为测试集,当有 $K$ 个样本,即要训练 $k$ 次。
函数: sklearn.model_selection.LeaveOneOut()
简单练习
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import LeaveOneOut
iris = load_iris()
logreg = LogisticRegression()
loo = LeaveOneOut()
scores = cross_val_score(logreg, iris.data, iris.target, cv=loo)
print("Number of cv iterations: ", len(scores))
print("Mean accuracy: {:.2f}".format(scores.mean()))
3. 打乱顺序交叉验证
函数:sklearn.model_selection.ShuffleSplit()
sklearn.model_selection.ShuffleSplit(n_splits=10, test_size=’default’, train_size=None,random_state=None)
# n_splits: 划分组数
# test_size: 测试集的占比
# train_size: 验证集的占比
# random_state: 随机数种子
ShuffleSplit和KFold区别:
KFold是划分 $k$ 份取一份作为测试集,其余作为训练集。
ShuffleSplit是划分 $k$ 份取规定数目作为测试集和训练集,相对比KFold更为灵活。
简单练习
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import ShuffleSplit
iris = load_iris()
logreg = LogisticRegression()
shuffle_split = ShuffleSplit(test_size=.5, train_size=.5, n_splits=10)
scores = cross_val_score(logreg, iris.data, iris.target, cv=shuffle_split)
print("Cross-validation scores:\n{}".format(scores))
4.分组交叉验证
当样本中存在高度相关的数据,为了避免训练集和验证集存在相关性而误判模型的准确性,需要将相关的数据进行分组。
函数:sklearn.model_selection.GroupKFold()
sklearn.model_selection.GroupKFold(n_splits=3)
# n_splits: 划分折数
简单练习:
from sklearn.model_selection import GroupKFold
import mglearn
X, y = make_blobs(n_samples=12, random_state=0)
groups = [0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3]
scores = cross_val_score(logreg, X, y, groups, cv=GroupKFold(n_splits=3))
print("Cross-validation scores:\n{}".format(scores))
mglearn.plots.plot_group_kfold()
分组后,同一组的数据不可能同时出现在训练集和测试集中!
网格搜索
简单网格搜索
概述:
模型的拟合优性往往取决于在构建模型时人工设定的模型参数,为了训练出合适的模型,我们需要不断更改模型参数,选取评分最高的模型。
注意: 在验证不同参数的评分时,不能只将数据划分为训练集和测试集,因为通过比较测试集的分数来确定模型的拟合性存在数据泄露问题。
正确做法应该是将数据划分为训练集、验证集和测试集。
先用训练集和验证集找到合适的模型参数,再用训练集、验证集和模型参数重新建立模型,用测试集计算模型评分。
简单练习
from sklearn.model_selection import GroupKFold
import mglearn
X, y = make_blobs(n_samples=12, random_state=0)
groups = [0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3]
scores = cross_val_score(logreg, X, y, groups, cv=GroupKFold(n_splits=3))
print("Cross-validation scores:\n{}".format(scores))
mglearn.plots.plot_group_kfold()
#%%
from sklearn.datasets import load_iris
from sklearn.svm import SVC
iris = load_iris()
# 将数据划分为训练+验证集与测试集
X_trainval, X_test, y_trainval, y_test = train_test_split(iris.data, iris.target, random_state=0)
# 将训练+验证集划分为训练集与验证集
X_train, X_valid, y_train, y_valid = train_test_split(X_trainval, y_trainval, random_state=1)
print("Size of training set: {} size of validation set: {} size of test set:"
" {}\n".format(X_train.shape[0], X_valid.shape[0], X_test.shape[0]))
best_score = 0
for gamma in [0.001, 0.01, 0.1, 1, 10, 100]:
for C in [0.001, 0.01, 0.1, 1, 10, 100]:
# 对每种参数组合都训练一个SVC
svm = SVC(gamma=gamma, C=C)
svm.fit(X_train, y_train)
# 在验证集上评估SVC
score = svm.score(X_valid, y_valid)
# 如果我们得到了更高的分数,则保存该分数和对应的参数
if score > best_score:
best_score = score
best_parameters = {'C': C, 'gamma': gamma}
# 在训练+验证集上重新构建一个模型,并在测试集上进行评估
svm = SVC(**best_parameters)
svm.fit(X_trainval, y_trainval)
test_score = svm.score(X_test, y_test)
print("Best score on validation set: {:.2f}".format(best_score))
print("Best parameters: ", best_parameters)
print("Test set score with best parameters: {:.2f}".format(test_score))
交叉验证的网格搜索
函数:sklearn.model_selection.GridSearchCV()
class sklearn.model_selection.GridSearchCV(estimator, param_grid, scoring=None, fit_params=None, n_jobs=1, iid=True, refit=True, cv=None, verbose=0, pre_dispatch=‘2*n_jobs’, error_score=’raise’, return_train_score=’warn’)
# estimator: 训练的模型
# param_grid: 参数取值,值为字典类型或列表类型
# scoring:模型评判标准
# cv: 交叉验证对折数,默认为3
GridSearchCV()可以直接在训练集中通过交叉验证的方法直接寻找到最佳参数,所以只需将数据划分为训练集和测试集,将训练集数据放入GridSearchCV()即可拟合最优模型,再将测试集数据放入模型中进行评分。
函数方法:
grid_search = GridSearchCV()
grid_search.score(X_test, y_test) # 测试集对模型评分
grid_search.best_params_ # 模型最佳参数
grid_search.best_score_ # 模型训练集最佳参数下的评分
grid_search.best_estimator_ # 模型的所有参数
简单练习
from sklearn.datasets import load_iris
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
iris = load_iris()
# 构建不同参数的字典
param_grid = {'C': [0.001, 0.01, 0.1, 1, 10, 100],
'gamma': [0.001, 0.01, 0.1, 1, 10, 100]}
grid_search = GridSearchCV(SVC(), param_grid, cv=5)
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=0)
grid_search.fit(X_train, y_train)
print("Test set score: {:.2f}".format(grid_search.score(X_test, y_test)))
print("Best parameters: {}".format(grid_search.best_params_))
print("Best cross-validation score: {:.2f}".format(grid_search.best_score_))
print("Best estimator:\n{}".format(grid_search.best_estimator_))
评估指标与评分
二分类指标
真反率(TN):被模型预测为负的负样本
假反率(FN):被模型预测为负的正样本
真正率(TP):被模型预测为正的正样本
假正率(FP):被模型预测为正的负样本
混淆矩阵:
- | 预测为反 | 预测为正 |
反类 | TN | FP |
正类 | FN | TP |
函数: sklearn.metrics.confusion_matrix() 构造混淆矩阵
sklearn.metrics.confusion_matrix(y_true, y_pred, labels=None, sample_weight=None)
# y_true: 样本真实值
# y_pred: 样本预测值
# lebels: 类别
# sample_weight: 样本权重
精度: 正确预测的数量处以样本数
$$ Accuracy = \frac {TP+TN}{TP+TN+FP+FN} $$
准确率: 被预测为正的样本中,正样本的个数
$$ Precision = \frac {TP}{TP+FP} $$
召回率: 正样本中有有多少被成功预测
$$ Recall = \frac {TP}{TP+FN} $$
f-score: 准确率和召回率的调和平均
$$ F = 2 × \frac {Precision × Recall}{Precision + Recall} $$
函数: sklearn.metrics.classification_report() 输出分类指标信息
sklearn.metrics.classification_report()
y_true:样本真实值。
y_pred:样本估计值
labels:array,shape = [n_labels],报表中包含的标签索引的可选列表。
target_names:字符串列表,与标签匹配的可选显示名称(相同顺序)。
sample_weight:类似于shape = [n_samples]的数组,可选项,样本权重。
digits:int,输出浮点值的位数.
函数: sklearn.metrics.precision_recall_curve 构造准确性-召回曲线
from sklearn.metrics import precision_recall_curve
precision, recall, thresholds = precision_recall_curve(y_test, svc.decision_function(X_test))
# 返回一个列表
通过计算曲线下的面积即可计算平均准确率。