万字长文总结机器学习的模型评价与调参 | 附代码下载
作者头像
  • 2020-08-17 19:41:19 3

目录

一、工作流与数据导入

1.1 数据导入与预处理

1.2 工作流的创建

二、K折交叉验证

2.1 K折交叉验证原理

2.2 K折交叉验证实现

三、参数调优

3.1 模型准确率

3.2 学习曲线

3.3 验证曲线

四、网格搜索

4.1 穷举搜索

4.2 字典搜索

五、嵌套交叉验证

六、评估指标

6.1 混淆矩阵

6.2 准确率、召回率和F1得分

6.3 ROC曲线


工作流与数据导入

在本章节中,我们将介绍如何创建一个数据处理和模型训练的工作流。

1.1 数据导入与预处理

我们首先导入一个名为“Wisconsin乳腺癌”的二分类数据集,该数据集包含569个样本。数据集的第一列是唯一的标识符(ID),第二列是目标值(M表示恶性肿瘤,B表示良性肿瘤),第三至第三十二列则是数值特征。

接下来,我们使用Python代码导入数据集:

```python import pandas as pd import urllib

try: df = pd.readcsv('https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data', header=None) except urllib.error.URLError: df = pd.readcsv('https://raw.githubusercontent.com/rasbt/python-machine-learning-book/master/code/datasets/wdbc/wdbc.data', header=None)

print('Rows, Columns:', df.shape) ```

随后,我们利用LabelEncoder将目标变量转化为数值形式:

```python from sklearn.preprocessing import LabelEncoder

X = df.iloc[:, 2:].values y = df.iloc[:, 1].values le = LabelEncoder() y = le.fit_transform(y) ```

接下来,我们将数据集划分为训练集和测试集:

```python from sklearn.modelselection import traintest_split

Xtrain, Xtest, ytrain, ytest = traintestsplit(X, y, testsize=0.20, randomstate=1) ```

1.2 工作流的创建

为了简化特征处理和模型训练过程,我们采用管道(Pipeline)技术。管道允许我们将多个数据处理步骤和模型训练步骤串联起来,形成一个完整的工作流程。

在这个示例中,我们定义了一个管道,包含以下步骤: 1. 标准化特征值 2. 使用主成分分析(PCA)降维 3. 使用逻辑回归进行分类

代码如下:

```python from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline

pipelr = Pipeline([('scl', StandardScaler()), ('pca', PCA(ncomponents=2)), ('clf', LogisticRegression(random_state=1))])

pipelr.fit(Xtrain, ytrain) print('Test Accuracy: %.3f' % pipelr.score(Xtest, ytest)) ```

K折交叉验证

K折交叉验证是一种常见的模型评估方法,它通过多次训练和测试模型来提高评估结果的可靠性。

2.1 K折交叉验证原理

K折交叉验证的基本思想是将数据集划分为K个互不重叠的子集,每次用K-1个子集作为训练集,剩余的一个子集作为测试集。重复这一过程K次,每次选取不同的子集作为测试集。最终,我们计算K次测试结果的平均值作为模型的评估结果。

2.2 K折交叉验证实现

在Scikit-Learn中,我们可以使用StratifiedKFold类来实现K折交叉验证。以下是具体的代码示例:

```python import numpy as np from sklearn.model_selection import StratifiedKFold

kfold = StratifiedKFold(nsplits=10, randomstate=1).split(Xtrain, ytrain)

scores = [] for k, (train, test) in enumerate(kfold): pipelr.fit(Xtrain[train], ytrain[train]) score = pipelr.score(Xtrain[test], ytrain[test]) scores.append(score) print('Fold: %s, Class dist.: %s, Acc: %.3f' % (k+1, np.bincount(y_train[train]), score))

print('nCV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores))) ```

我们也可以使用cross_val_score函数简化上述过程:

```python from sklearn.modelselection import crossval_score

scores = crossvalscore(estimator=pipelr, X=Xtrain, y=ytrain, cv=10, njobs=1) print('CV accuracy scores: %s' % scores) print('CV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores))) ```

参数调优

为了优化模型性能,我们需要对模型的超参数进行调整。常用的方法包括绘制学习曲线和验证曲线。

3.1 模型准确率

模型的准确率反映了模型的整体性能。准确率较高的模型可能面临过拟合或欠拟合的问题。

3.2 学习曲线

学习曲线展示了训练样本数量与模型准确率之间的关系。通过观察学习曲线,我们可以判断模型是否存在欠拟合或过拟合的情况。

```python import matplotlib.pyplot as plt from sklearn.modelselection import learningcurve

pipelr = Pipeline([('scl', StandardScaler()), ('clf', LogisticRegression(penalty='l2', randomstate=0))])

trainsizes, trainscores, testscores = learningcurve(estimator=pipelr, X=Xtrain, y=ytrain, trainsizes=np.linspace(0.1, 1.0, 10), cv=10, n_jobs=1)

trainmean = np.mean(trainscores, axis=1) trainstd = np.std(trainscores, axis=1) testmean = np.mean(testscores, axis=1) teststd = np.std(testscores, axis=1)

plt.plot(trainsizes, trainmean, color='blue', marker='o', markersize=5, label='training accuracy') plt.fillbetween(trainsizes, trainmean + trainstd, trainmean - trainstd, alpha=0.15, color='blue') plt.plot(trainsizes, testmean, color='green', linestyle='--', marker='s', markersize=5, label='validation accuracy') plt.fillbetween(trainsizes, testmean + teststd, testmean - teststd, alpha=0.15, color='green') plt.grid() plt.xlabel('Number of training samples') plt.ylabel('Accuracy') plt.legend(loc='lower right') plt.ylim([0.8, 1.0]) plt.tight_layout() plt.show() ```

3.3 验证曲线

验证曲线用于评估不同超参数值对模型性能的影响。例如,我们可以通过改变逻辑回归的正则化参数C来观察其对模型准确率的影响。

```python from sklearn.modelselection import validationcurve

paramrange = [0.001, 0.01, 0.1, 1.0, 10.0, 100.0] trainscores, testscores = validationcurve( estimator=pipelr, X=Xtrain, y=ytrain, paramname='clf_C', paramrange=param_range, cv=10)

trainmean = np.mean(trainscores, axis=1) trainstd = np.std(trainscores, axis=1) testmean = np.mean(testscores, axis=1) teststd = np.std(testscores, axis=1)

plt.plot(paramrange, trainmean, color='blue', marker='o', markersize=5, label='training accuracy') plt.fillbetween(paramrange, trainmean + trainstd, trainmean - trainstd, alpha=0.15, color='blue') plt.plot(paramrange, testmean, color='green', linestyle='--', marker='s', markersize=5, label='validation accuracy') plt.fillbetween(paramrange, testmean + teststd, testmean - teststd, alpha=0.15, color='green') plt.grid() plt.xscale('log') plt.legend(loc='lower right') plt.xlabel('Parameter C') plt.ylabel('Accuracy') plt.ylim([0.8, 1.0]) plt.tight_layout() plt.show() ```

网格搜索

网格搜索是一种系统地寻找最优超参数组合的方法。通过定义参数空间并穷举所有可能的组合,我们可以找到使模型性能最优的一组参数。

4.1 穷举搜索

```python from sklearn.datasets import loadiris from sklearn.svm import SVC from sklearn.modelselection import traintestsplit

iris = loadiris() Xtrain, Xtest, ytrain, ytest = traintestsplit(iris.data, iris.target, randomstate=0)

bestscore = 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]: svm = SVC(gamma=gamma, C=C) svm.fit(Xtrain, ytrain) score = svm.score(Xtest, ytest) if score > bestscore: bestscore = score bestparameters = {'C': C, 'gamma': gamma}

print("Best score: ", bestscore) print("Best parameters: ", bestparameters) ```

4.2 字典搜索

```python from sklearn.svm import SVC from sklearn.model_selection import GridSearchCV

pipesvc = Pipeline([('scl', StandardScaler()), ('clf', SVC(randomstate=1))])

paramrange = [0.0001, 0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0] paramgrid = [{'clfC': paramrange, 'clfkernel': ['linear']}, {'clfC': paramrange, 'clfgamma': paramrange, 'clf_kernel': ['rbf']}]

gs = GridSearchCV(estimator=pipesvc, paramgrid=paramgrid, scoring='accuracy', cv=10, njobs=-1)

gs.fit(Xtrain, ytrain) print(gs.bestscore) print(gs.bestparams) ```

嵌套交叉验证

嵌套交叉验证是一种更复杂的模型选择方法,它结合了外部交叉验证和内部交叉验证。外部交叉验证用于评估模型的整体性能,而内部交叉验证用于选择最佳的超参数组合。

```python gs = GridSearchCV(estimator=pipesvc, paramgrid=param_grid, scoring='accuracy', cv=2)

scores = crossvalscore(gs, Xtrain, ytrain, scoring='accuracy', cv=5) print('CV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores))) ```

评估指标

在评估模型性能时,我们需要关注多种指标,如准确率、召回率、F1得分和ROC曲线。

6.1 混淆矩阵

混淆矩阵是评估分类模型性能的重要工具。它展示了模型在各个类别上的预测准确性。

```python from sklearn.metrics import confusion_matrix

pipesvc.fit(Xtrain, ytrain) ypred = pipesvc.predict(Xtest) confmat = confusionmatrix(ytrue=ytest, ypred=y_pred) print(confmat)

fig, ax = plt.subplots(figsize=(2.5, 2.5)) ax.matshow(confmat, cmap=plt.cm.Blues, alpha=0.3) for i in range(confmat.shape[0]): for j in range(confmat.shape[1]): ax.text(x=j, y=i, s=confmat[i, j], va='center', ha='center') plt.xlabel('Predicted label') plt.ylabel('True label') plt.tight_layout() plt.show() ```

6.2 准确率、召回率和F1得分

除了混淆矩阵,我们还可以计算其他重要的评估指标,如准确率、召回率和F1得分。

```python from sklearn.metrics import precisionscore, recallscore, f1_score

print('Precision: %.3f' % precisionscore(ytrue=ytest, ypred=ypred)) print('Recall: %.3f' % recallscore(ytrue=ytest, ypred=ypred)) print('F1: %.3f' % f1score(ytrue=ytest, ypred=y_pred)) ```

6.3 ROC曲线

ROC曲线是一种常用的评估分类器性能的图形化方法。它展示了真正率和假正率之间的关系。

```python from sklearn.metrics import roc_curve, auc from scipy import interp

pipelr = Pipeline([('scl', StandardScaler()), ('pca', PCA(ncomponents=2)), ('clf', LogisticRegression(penalty='l2', random_state=0, C=100.0))])

Xtrain2 = Xtrain[:, [4, 14]]

cv = list(StratifiedKFold(nsplits=3, randomstate=1).split(Xtrain, ytrain))

fig = plt.figure(figsize=(7, 5))

meantpr = 0.0 meanfpr = np.linspace(0, 1, 100) all_tpr = []

for i, (train, test) in enumerate(cv): probas = pipelr.fit(Xtrain2[train], ytrain[train]).predictproba(Xtrain2[test]) fpr, tpr, thresholds = roccurve(ytrain[test], probas[:, 1], poslabel=1) meantpr += interp(meanfpr, fpr, tpr) meantpr[0] = 0.0 rocauc = auc(fpr, tpr) plt.plot(fpr, tpr, lw=1, label='ROC fold %d (area = %0.2f)' % (i+1, roc_auc))

plt.plot([0, 1], [0, 1], linestyle='--', color=(0.6, 0.6, 0.6), label='random guessing') meantpr /= len(cv) meantpr[-1] = 1.0 meanauc = auc(meanfpr, meantpr) plt.plot(meanfpr, meantpr, 'k--', label='mean ROC (area = %0.2f)' % meanauc, lw=2) plt.plot([0, 0, 1], [0, 1, 1], lw=2, linestyle=':', color='black', label='perfect performance') plt.xlim([-0.05, 1.05]) plt.ylim([-0.05, 1.05]) plt.xlabel('False Positive Rate') plt.ylabel('True Positive Rate') plt.title('Receiver Operating Characteristic') plt.legend(loc="lower right") plt.tight_layout() plt.show()

pipelr = pipelr.fit(Xtrain2, ytrain) ylabels = pipelr.predict(Xtest[:, [4, 14]]) yprobas = pipelr.predictproba(X_test[:, [4, 14]])[:, 1]

print('ROC AUC: %.3f' % rocaucscore(ytrue=ytest, yscore=yprobas)) print('Accuracy: %.3f' % accuracyscore(ytrue=ytest, ypred=y_labels)) ```

以上是改写后的内容,确保了文章的紧凑性和可读性,同时保留了关键信息和价值点。

    本文来源:图灵汇
责任编辑: :
声明:本文系图灵汇原创稿件,版权属图灵汇所有,未经授权不得转载,已经协议授权的媒体下载使用时须注明"稿件来源:图灵汇",违者将依法追究责任。
    分享
长文代码下载模型机器评价总结学习万字
    下一篇