目录html
更新、更全的《机器学习》的更新网站,更有python、go、数据结构与算法、爬虫、人工智能教学等着你:http://www.javashuo.com/article/p-vozphyqp-cm.htmlpython
对于分类问题,咱们可能会使用k近邻算法、决策树、逻辑回归、朴素贝叶斯法、支持向量机、随机森林;对于回归问题,咱们可能会使用线性回归、决策树、随机森林。在工业上,咱们不可能会对客户说,这是我训练的几个模型,你想用哪一个我就给你哪一个。通常而言这是不可能的,一般对于这几个模型,咱们会经过某种度量模型的工具,选择一个最优的模型推给客户。算法
在训练模型那一章节,对于每一个模型咱们都使用了模型自带的score()方法对模型的性能进行了一个度量,可是score()方法对于分类模型,只是简单的度量了模型的性能;对于回归模型,score()方法只是计算了R2报告分数。这样的度量是很片面的,一般咱们会使用sklearn.metics和sklearn.model_selection库下的模块对度量模型性能。bootstrap
模块提供了各类评估指标,而且用户能够自定义评估指标,对于metrics评估指标,主要分为如下两种类型:数据结构
* 以_score结尾的为模型得分,通常状况越大越好 * 以_error或_loss结尾的为模型的误差,通常状况越小越好
接下来咱们将经过分类模型、回归模型来详细讲解metrics评估指标。dom
import numpy as np import pandas as pd import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties from sklearn import datasets %matplotlib inline font = FontProperties(fname='/Library/Fonts/Heiti.ttc')
/Applications/anaconda3/lib/python3.7/importlib/_bootstrap.py:219: RuntimeWarning: numpy.dtype size changed, may indicate binary incompatibility. Expected 96, got 88 return f(*args, **kwds) /Applications/anaconda3/lib/python3.7/importlib/_bootstrap.py:219: RuntimeWarning: numpy.dtype size changed, may indicate binary incompatibility. Expected 96, got 88 return f(*args, **kwds)
回归模型经常使用的metrics评估指标有:r2_score、explained_variance_score等机器学习
* explained_variance_score(y_true, y_pred, sample_weight=None, multioutput='uniform_average'):回归方差(反应自变量与因变量之间的相关程度) * mean_absolute_error(y_true, y_pred, sample_weight=None, multioutput='uniform_average'):平均绝对值偏差 * mean_squared_error(y_true, y_pred, sample_weight=None, multioutput='uniform_average'):均方差 * median_absolute_error(y_true, y_pred):中值绝对偏差 * r2_score(y_true, y_pred, sample_weight=None, multioutput='uniform_average'):R平方值
r2_score即报告决定系数\((R^2)\),能够理解成MSE的标准版,\(R^2\)的公式为
\[ R^2 = 1-{\frac {{\frac{1}{n}\sum_{i=1}^n(y^{(i)}-\hat{y^{(i)}})^2}} {{\frac{1}{n}}\sum_{i=1}^n(y^{(i)}-\mu_{(y)})^2} } \]
其中\(\mu_{(y)}\)是\(y\)的平均值,即\({{\frac{1}{n}}\sum_{i=1}^n(y^{(i)}-\mu_{(y)})^2}\)为\(y\)的方差,公式能够写成
\[ R^2 = 1-{\frac{MSE}{Var(y)}} \]
\(R^2\)的取值范围在\(0-1\)之间,若是\(R^2=1\),则均方偏差\(MSE=0\),即模型完美的拟合数据。工具
# 报告决定系数得分 from sklearn.linear_model import LinearRegression from sklearn.metrics import r2_score boston = datasets.load_boston() X = boston.data y = boston.target lr = LinearRegression() lr.fit(X, y) lr_predict = lr.predict(X) lr_r2 = r2_score(y, lr_predict) print('报告决定系数:{:.2f}'.format(lr_r2))
报告决定系数:0.74
# 解释方差示例 from sklearn.linear_model import LinearRegression from sklearn.metrics import explained_variance_score boston = datasets.load_boston() X = boston.data y = boston.target lr = LinearRegression() lr.fit(X, y) lr_predict = lr.predict(X) ex_var = explained_variance_score(y, lr_predict) print('解释方差:{:.2f}'.format(ex_var))
解释方差:0.74
回归模型经常使用的metrics评估指标有:accuracy_socre、precision_score、recall_score、f1_score等性能
* accuracy_score(y_true,y_pre): 精度 * auc(x, y, reorder=False): ROC曲线下的面积;较大的AUC表明了较好的performance。 * average_precision_score(y_true, y_score, average='macro', sample_weight=None):根据预测得分计算平均精度(AP) * brier_score_loss(y_true, y_prob, sample_weight=None, pos_label=None):越小的brier_score,模型效果越好 * confusion_matrix(y_true, y_pred, labels=None, sample_weight=None):经过计算混淆矩阵来评估分类的准确性 返回混淆矩阵 * f1_score(y_true, y_pred, labels=None, pos_label=1, average='binary', sample_weight=None): F1值 * log_loss(y_true, y_pred, eps=1e-15, normalize=True, sample_weight=None, labels=None):对数损耗,又称逻辑损耗或交叉熵损耗 * precision_score(y_true, y_pred, labels=None, pos_label=1, average='binary',):查准率或者精度; precision(查准率)=TP/(TP+FP) * recall_score(y_true, y_pred, labels=None, pos_label=1, average='binary', sample_weight=None):查全率 ;recall(查全率)=TP/(TP+FN) * roc_auc_score(y_true, y_score, average='macro', sample_weight=None):计算ROC曲线下的面积就是AUC的值,the larger the better * roc_curve(y_true, y_score, pos_label=None, sample_weight=None, drop_intermediate=True);计算ROC曲线的横纵坐标值,TPR,FPR
二分类问题中根据样例的真实类别和模型预测类别的组合划分为真正例(true positive)、假正例(false positive)、真反例(true negative)、假反例(false negative)四种情形,令TP、FP、TN、FN分别表示对应的样例数,\(样例总数 = TP+FP+TN+FN\)。学习
偏差矩阵 | - | - | - |
---|---|---|---|
- | - | 真实值 | 真实值 |
- | - | 1 | 0 |
预测值 | 1 | True Positive(TP) | False Positive(FP) |
预测值 | 0 | True Negative(TN) | False Negative(FN) |
准确度(accuracy_socre)定义为
\[ P = {\frac{TP+FN}{TP+FP+TN+FN}} = \frac{正确预测的样本数}{样本总数} \]
# 查准率示例 from sklearn import datasets from sklearn.metrics import accuracy_score from sklearn.linear_model import LogisticRegression iris_data = datasets.load_iris() X = iris_data.data y = iris_data.target lr = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=200) lr = lr.fit(X, y) y_pred = lr.predict(X) print('准确度:{:.2f}'.format( accuracy_score(y, y_pred)))
准确度:0.97
查准率(precision_score)定义为
\[ P = {\frac{TP}{TP+FP}} = \frac{正确预测为正类的样本数}{预测为正类的样本总数} \]
# 查准率示例 from sklearn import datasets from sklearn.metrics import precision_score from sklearn.linear_model import LogisticRegression iris_data = datasets.load_iris() X = iris_data.data y = iris_data.target lr = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=200) lr = lr.fit(X, y) y_pred = lr.predict(X) print('查准率:{:.2f}'.format( precision_score(y, y_pred, average='weighted')))
查准率:0.97
查全率(recall_score等)定义为
\[ R = {\frac{TP}{TP+FN}} = \frac{正确预测为正类的样本数}{正类总样本数} \]
# 查全率示例 from sklearn.metrics import recall_score from sklearn import datasets from sklearn.linear_model import LogisticRegression iris_data = datasets.load_iris() X = iris_data.data y = iris_data.target lr = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=200) lr = lr.fit(X, y) y_pred = lr.predict(X) print('查全率:{:.2f}'.format(recall_score(y, y_pred, average='weighted')))
查全率:0.97
一般状况下经过查准率和查全率度量模型的好坏,可是查准率和查全率是一对矛盾的度量工具,查准率高的时候查全率低;查全率高的时候查准率低,所以工业上对不不一样的问题对查准率和查全率的侧重点会有所不一样。
例如癌症的预测中,正类是健康,反类是患有癌症。较高的查准率可能会致使健康的人被告知患有癌症;较高的查全率可能会致使患有癌症的患者会被告知健康。
\(F_1\)值(f1_score等)定义为
\[ F_1 = {\frac{2*P*R}{P+R}} = {\frac{2*TP}{2TP+FP+FN}} = {\frac{2*TP}{样例总数+TP-TN}} \]
\(F_\beta\)定义为:
\[ F_\beta = {\frac{(1+\beta^2)*P*R}{\beta^2*P+R}} \]
\(F_\beta\)是在\(F_1\)值的基础上加权获得的,它能够更好的权衡查准率和查全率。
# F1值示例 from sklearn import datasets from sklearn.metrics import f1_score from sklearn.linear_model import LogisticRegression iris_data = datasets.load_iris() X = iris_data.data y = iris_data.target lr = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=200) lr = lr.fit(X, y) y_pred = lr.predict(X) print('F1值:{:.2f}'.format(f1_score(y, y_pred, average='weighted')))
F1值:0.97
ROC(receiver operating characteristic,ROC)曲线也能够度量模型性能的好坏,ROC曲线顾名思义是一条曲线,它的横轴是假正例率(false positive rate,FPR),纵轴是真正例率(true positive rate,TPR),假正例率和真正例率分别定义为:
\[ FPR = {\frac{FP}{FP+TN}} \text{假正例率} \\ TPR = {\frac{TP}{TP+FN}} \text{真正例率} \]
# ROC示例 from sklearn import datasets from sklearn.metrics import roc_curve from sklearn.linear_model import LogisticRegression iris_data = datasets.load_iris() X = iris_data.data[0:100, :] y = iris_data.target[0:100] lr = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=200) lr = lr.fit(X, y) y_pred = lr.predict(X) fpr, tpr, thresholds = roc_curve(y, y_pred) plt.xlabel('FPR', fontsize=15) plt.ylabel('TPR', fontsize=15) plt.title('FPR-TPR', fontsize=20) plt.plot(fpr, tpr) plt.show()
因为ROC曲线有时候没法精准度量模型的好坏,所以会使用ROC曲线关于横纵轴围成的面积称为AUC(area under ROC curve,AUC)来度量模型的好坏,AUC值越大的模型,则模型越优。
# AUC示例 from sklearn import datasets from sklearn.metrics import roc_auc_score from sklearn.linear_model import LogisticRegression iris_data = datasets.load_iris() X = iris_data.data[0:100, :] y = iris_data.target[0:100] lr = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=200) lr = lr.fit(X, y) y_pred = lr.predict(X) # 计算AUC值 print('AUC值:{:.2f}'.format(roc_auc_score(y, y_pred, average='weighted')))
AUC值:1.00
第二部分讲解线性回归时讲到,\(0\)偏差的模型也许并非最好的,由于模型是经过训练集获得的,因为训练集可能存在噪声,所以训练集并不必定能表明测试集,更不必定能表明将来新数据。虽然这样的模型可能很好的拟合训练数据,可是对将来数据可能并无较好的拟合能力,这种现象成为过拟合。
# 过拟合图例 import pandas as pd import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties from sklearn.preprocessing import PolynomialFeatures from sklearn.linear_model import LinearRegression font = FontProperties(fname='/Library/Fonts/Heiti.ttc') %matplotlib inline # 自定义数据并处理数据 data_frame = {'x': [2, 1.5, 3, 3.2, 4.22, 5.2, 6, 6.7], 'y': [0.5, 3.5, 5.5, 5.2, 5.5, 5.7, 5.5, 6.25]} df = pd.DataFrame(data_frame) X, y = df.iloc[:, 0].values.reshape(-1, 1), df.iloc[:, 1].values.reshape(-1, 1) # 线性回归 lr = LinearRegression() lr.fit(X, y) def poly_lr(degree): """多项式回归""" poly = PolynomialFeatures(degree=degree) X_poly = poly.fit_transform(X) lr_poly = LinearRegression() lr_poly.fit(X_poly, y) y_pred_poly = lr_poly.predict(X_poly) return y_pred_poly def plot_lr(): """对线性回归生成的图线画图""" plt.scatter(X, y, c='k', edgecolors='white', s=50) plt.plot(X, lr.predict(X), color='r', label='lr') # 噪声 plt.scatter(2, 0.5, c='r') plt.text(2, 0.5, s='$(2,0.5)$') plt.xlim(0, 7) plt.ylim(0, 8) plt.xlabel('x') plt.ylabel('y') plt.legend() def plot_poly(degree, color): """对多项式回归生成的图线画图""" plt.scatter(X, y, c='k', edgecolors='white', s=50) plt.plot(X, poly_lr(degree), color=color, label='m={}'.format(degree)) # 噪声 plt.scatter(2, 0.5, c='r') plt.text(2, 0.5, s='$(2,0.5)$') plt.xlim(0, 7) plt.ylim(0, 8) plt.xlabel('x') plt.ylabel('y') plt.legend() def run(): plt.figure() plt.subplot(231) plt.title('图1(线性回归)', fontproperties=font, color='r', fontsize=12) plot_lr() plt.subplot(232) plt.title('图2(一阶多项式回归)', fontproperties=font, color='r', fontsize=12) plot_poly(1, 'orange') plt.subplot(233) plt.title('图3(三阶多项式回归)', fontproperties=font, color='r', fontsize=12) plot_poly(3, 'gold') plt.subplot(234) plt.title('图4(五阶多项式回归)', fontproperties=font, color='r', fontsize=12) plot_poly(5, 'green') plt.subplot(235) plt.title('图5(七阶多项式回归)', fontproperties=font, color='r', fontsize=12) plot_poly(7, 'blue') plt.subplot(236) plt.title('图6(十阶多项式回归)', fontproperties=font, color='r', fontsize=12) plot_poly(10, 'violet') plt.show() run()
如上图所示每张图都有相同分布的8个样本点,红点明显是一个噪声点,接下来将讲解上述8张图。暂时不用太关心线性回归和多项式回归是什么,这两个之后你都会学习到,此处引用只是为了方便举例。
从上图能够看出,过拟合模型将会变得复杂,对于线性回归而言,它可能须要更高阶的多项式去拟合样本点,对于其余机器学习算法,也是如此。这个时候你也能够想象,过拟合虽然对拟合的样本点的偏差接近0,可是对于将来新数据而言,若是新数据的\(x=2\),若是使用过拟合的曲线进行拟合新数据,那么会给出\(y=0.5\)的预测值,也就是说把噪声的值给了新数据,这样明显是不合理的。
对训练数据集切割作交叉验证也是防止模型过拟合的一个很好的方法。
通常会把数据按照某种比例分为训练集、测试集。训练集用来训练模型,把测试集当作将来新样本的样本集用来评估模型。而后交叉验证能够认为就是不断地重复训练模型、测试模型。若是数据量较大的话,会把训练集按照某种比例分红训练集、验证集、测试集,使用训练集训练参数;使用验证集训练超参数;使用测试集测试模型性能。
把数据集按照某种比例,将数据集中的数据随机的分为训练集和测试集。而后不断的改变模型参数训练出一组模型,每训练完一个模型就用测试集测试,最后获得性能最好的模型。
# 简单交叉验证 import numpy as np from sklearn import datasets from sklearn.model_selection import train_test_split # 导入鸢尾花数据 iris_data = datasets.load_iris() X = iris_data.data[:, [0, 1]] y = iris_data.target # random_state=1能够确保结果不随机,stratify=y能够确保每一个分类的结果都有相同的比例 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=1, stratify=y) print('不一样类别全部样本数量:{}'.format(np.bincount(y))) print('不一样类别训练数据数量:{}'.format(np.bincount(y_train))) print('不一样类别测试数据数量:{}'.format(np.bincount(y_test)))
不一样类别全部样本数量:[50 50 50] 不一样类别训练数据数量:[35 35 35] 不一样类别测试数据数量:[15 15 15]
将数据随机的分为\(k\)个子集(\(k\)的取值范围通常在\([1-20]\)之间),而后取出\(k-1\)个子集进行训练,另外一个子集用做测试模型,重复\(k\)次这个过程,获得最优模型。
# k折交叉验证 import numpy as np from sklearn import datasets # StratifiedKFold会按照原有标签的分布状况对数据分层 from sklearn.model_selection import StratifiedKFold # 导入鸢尾花数据 iris_data = datasets.load_iris() X = iris_data.data[:, [0, 1]] y = iris_data.target # n_splits=10至关于k=10 kfold = StratifiedKFold(n_splits=3, random_state=1) kfold = kfold.split(X, y) for k, (train_data, test_data) in enumerate(kfold): print(train_data,test_data) print('迭代次数:{}'.format(k), '训练数据长度:{}'.format( len(train_data)), '测试数据长度:{}'.format(len(test_data)))
[ 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149] [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116] 迭代次数:0 训练数据长度:99 测试数据长度:51 [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149] [ 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133] 迭代次数:1 训练数据长度:99 测试数据长度:51 [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133] [ 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149] 迭代次数:2 训练数据长度:102 测试数据长度:48
# k折交叉验证 import numpy as np from sklearn import datasets # StratifiedKFold会按照原有标签的分布状况对数据分层 from sklearn.model_selection import ShuffleSplit # 导入鸢尾花数据 iris_data = datasets.load_iris() X = iris_data.data[:, [0, 1]] y = iris_data.target # n_splits=10至关于k=10 kfold = ShuffleSplit(n_splits=3, random_state=1) kfold = kfold.split(X) for k, (train_data, test_data) in enumerate(kfold): print(train_data,test_data) print('迭代次数:{}'.format(k), '训练数据长度:{}'.format( len(train_data)), '测试数据长度:{}'.format(len(test_data)))
[ 42 92 66 31 35 90 84 77 40 125 99 33 19 73 146 91 135 69 128 114 48 53 28 54 108 112 17 119 103 58 118 18 4 45 59 39 36 117 139 107 132 126 85 122 95 11 113 123 12 2 104 6 127 110 65 55 144 138 46 62 74 116 93 100 89 10 34 32 124 38 83 111 149 27 23 67 9 130 97 105 145 87 148 109 64 15 82 41 80 52 26 76 43 24 136 121 143 49 21 70 3 142 30 147 106 47 115 13 88 8 81 60 0 1 57 22 61 63 7 86 96 68 50 101 20 25 134 71 129 79 133 137 72 140 37] [ 14 98 75 16 131 56 141 44 29 120 94 5 102 51 78] 迭代次数:0 训练数据长度:135 测试数据长度:15 [ 18 37 59 111 65 119 127 102 121 118 90 146 3 51 100 133 105 23 57 123 49 9 72 126 124 145 68 143 6 13 120 89 135 22 99 92 130 39 58 81 52 117 4 17 138 97 70 109 148 42 73 115 5 76 38 86 122 80 95 34 60 129 112 7 26 19 14 30 15 44 20 137 107 64 41 79 50 131 108 144 104 8 74 94 103 31 82 55 125 32 54 48 83 149 2 33 93 136 35 75 63 29 0 46 78 66 140 67 128 106 28 16 87 45 47 113 77 40 21 101 69 53 24 134 43 116 141 142 25 147 56 61 96 10 84] [132 1 114 62 110 27 91 36 85 98 88 11 139 71 12] 迭代次数:1 训练数据长度:135 测试数据长度:15 [ 62 135 20 56 77 55 65 87 5 97 117 10 142 74 17 12 45 102 50 96 124 48 8 47 122 148 29 130 71 147 7 128 104 91 140 79 60 136 86 67 33 68 0 129 49 121 99 32 59 110 101 14 6 123 108 37 107 111 21 26 42 58 75 78 90 145 139 63 38 18 40 119 100 126 134 28 72 144 80 46 113 149 85 2 81 116 35 115 138 137 16 125 105 11 120 141 76 93 109 88 57 41 9 53 95 106 92 66 22 23 36 13 132 61 83 39 70 131 146 98 64 103 30 84 94 127 82 1 43 27 89 52 73 69 112] [ 51 133 19 31 24 34 114 54 143 4 15 25 118 3 44] 迭代次数:2 训练数据长度:135 测试数据长度:15
与\(k\)折交叉验证相似,属于\(k\)折交叉验证的特例,即一个数据集\(T\)中有\(n\)个数据,当\(k=n-1\)时,\(k\)折交叉验证即为留一法交叉验证。
# 留一法交叉验证 import numpy as np from sklearn import datasets from sklearn.model_selection import LeaveOneOut # 导入鸢尾花数据 iris_data = datasets.load_iris() X = iris_data.data[:, [0, 1]] y = iris_data.target loo = LeaveOneOut() loo
LeaveOneOut()
loo.get_n_splits(X)
150
count = 0 for train_index, test_index in loo.split(X): if count < 10: print("训练集长度:", len(train_index), "测试集长度:", len(test_index)) count += 1 if count == loo.get_n_splits(X)-1: print('...\n迭代次数:', count)
训练集长度: 149 测试集长度: 1 训练集长度: 149 测试集长度: 1 训练集长度: 149 测试集长度: 1 训练集长度: 149 测试集长度: 1 训练集长度: 149 测试集长度: 1 训练集长度: 149 测试集长度: 1 训练集长度: 149 测试集长度: 1 训练集长度: 149 测试集长度: 1 训练集长度: 149 测试集长度: 1 训练集长度: 149 测试集长度: 1 ... 迭代次数: 149
时间序列分割通常对时间序列算法作测试,他切割的原理是:测试集的数据和上几个数据会有必定的联系。
from sklearn.model_selection import TimeSeriesSplit X = np.array([[1, 2], [2, 4], [3, 2], [2, 4], [1, 2], [3, 2]]) y = np.array([1, 3, 3, 4, 5, 4]) # max_train_size指训练数据个数,n_splits指切割次数 tscv = TimeSeriesSplit(n_splits=5, max_train_size=3) tscv
TimeSeriesSplit(max_train_size=3, n_splits=5)
for train_index, test_index in tscv.split(X): print("训练数据索引:", train_index, "测试数索引:", test_index) X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index]
训练数据索引: [0] 测试数索引: [1] 训练数据索引: [0 1] 测试数索引: [2] 训练数据索引: [0 1 2] 测试数索引: [3] 训练数据索引: [1 2 3] 测试数索引: [4] 训练数据索引: [2 3 4] 测试数索引: [5]
若是只是对交叉验证有必定的了解,那么问题则是,咱们如何把使用交叉验证的思想,训练模型呢?使用for循环吗?不,咱们可使用sklearn自带的交叉验证评分方法。
交叉验证中的cross_val_score,即最普通的交叉验证和模型一块儿使用的方法,该方法须要指定模型、训练集数据和评分方法,而后能够得出每一次测试模型的分数。
from sklearn.metrics import SCORERS # 可使用的评分方法 SCORERS.keys()
dict_keys(['explained_variance', 'r2', 'neg_median_absolute_error', 'neg_mean_absolute_error', 'neg_mean_squared_error', 'neg_mean_squared_log_error', 'accuracy', 'roc_auc', 'balanced_accuracy', 'average_precision', 'neg_log_loss', 'brier_score_loss', 'adjusted_rand_score', 'homogeneity_score', 'completeness_score', 'v_measure_score', 'mutual_info_score', 'adjusted_mutual_info_score', 'normalized_mutual_info_score', 'fowlkes_mallows_score', 'precision', 'precision_macro', 'precision_micro', 'precision_samples', 'precision_weighted', 'recall', 'recall_macro', 'recall_micro', 'recall_samples', 'recall_weighted', 'f1', 'f1_macro', 'f1_micro', 'f1_samples', 'f1_weighted'])
from sklearn.model_selection import cross_val_score from sklearn.linear_model import LogisticRegression from sklearn import datasets iris = datasets.load_iris() X = iris.data y = iris.target clf = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=1000) scores = cross_val_score(clf, X, y, cv=10, scoring='accuracy') scores
array([1. , 0.93333333, 1. , 1. , 0.93333333, 0.93333333, 0.93333333, 1. , 1. , 1. ])
print('准确率:{:.4f}(+/-{:.4f})'.format(scores.mean(), scores.std()*2))
准确率:0.9733(+/-0.0653)
交叉验证中cross_validate方法,相比较cross_val_score方法能够指定多个指标,而且cross_validate方法会返回模型fit_time训练和score_time评分的时间。
from sklearn.model_selection import cross_validate from sklearn.linear_model import LogisticRegression from sklearn import datasets iris = datasets.load_iris() X = iris.data y = iris.target clf = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=1000) cross_validate(clf, X, y, cv=10, scoring=[ 'accuracy', 'recall_weighted'], return_train_score=True)
{'fit_time': array([0.04038572, 0.06277108, 0.07863808, 0.03404975, 0.03079391, 0.04499412, 0.04462409, 0.06048512, 0.05675983, 0.03511214]), 'score_time': array([0.00144005, 0.00148797, 0.00143886, 0.00105596, 0.00098372, 0.00138307, 0.00099993, 0.00111103, 0.0020051 , 0.00080705]), 'test_accuracy': array([1. , 0.93333333, 1. , 1. , 0.93333333, 0.93333333, 0.93333333, 1. , 1. , 1. ]), 'train_accuracy': array([0.97037037, 0.97777778, 0.97037037, 0.97037037, 0.97777778, 0.97777778, 0.98518519, 0.97037037, 0.97037037, 0.97777778]), 'test_recall_weighted': array([1. , 0.93333333, 1. , 1. , 0.93333333, 0.93333333, 0.93333333, 1. , 1. , 1. ]), 'train_recall_weighted': array([0.97037037, 0.97777778, 0.97037037, 0.97037037, 0.97777778, 0.97777778, 0.98518519, 0.97037037, 0.97037037, 0.97777778])}
交叉验证中的cross_val_predict方法能够获取每一个样本的预测结果,即每个样本都会被做为测试数据。
from sklearn.model_selection import cross_val_predict from sklearn.linear_model import LogisticRegression from sklearn import datasets iris = datasets.load_iris() X = iris.data y = iris.target clf = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=1000) per_sample = cross_val_predict(clf, X, y, cv=10) per_sample
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
from sklearn.metrics import accuracy_score accuracy_score(y, per_sample)
0.9733333333333334
sklearn构建的内部自带交叉验证优化的估计器,如LassoCV、RidgeCV等。
from sklearn import datasets from sklearn.metrics import r2_score from sklearn.linear_model import Lasso, LassoCV boston = datasets.load_boston() X = boston.data y = boston.target reg = Lasso() reg.fit(X, y)
Lasso(alpha=1.0, copy_X=True, fit_intercept=True, max_iter=1000, normalize=False, positive=False, precompute=False, random_state=None, selection='cyclic', tol=0.0001, warm_start=False)
y_pred = reg.predict(X) '报告决定系数:{:.2f}'.format(r2_score(y, y_pred))
'报告决定系数:0.68'
reg = LassoCV(cv=5) reg.fit(X, y)
LassoCV(alphas=None, copy_X=True, cv=5, eps=0.001, fit_intercept=True, max_iter=1000, n_alphas=100, n_jobs=None, normalize=False, positive=False, precompute='auto', random_state=None, selection='cyclic', tol=0.0001, verbose=False)
y_pred = reg.predict(X) '报告决定系数:{:.2f}'.format(r2_score(y, y_pred))
'报告决定系数:0.70'