一、工作流与数据导入
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曲线
在本章节中,我们将介绍如何创建一个数据处理和模型训练的工作流。
我们首先导入一个名为“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) ```
为了简化特征处理和模型训练过程,我们采用管道(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折交叉验证的基本思想是将数据集划分为K个互不重叠的子集,每次用K-1个子集作为训练集,剩余的一个子集作为测试集。重复这一过程K次,每次选取不同的子集作为测试集。最终,我们计算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))) ```
为了优化模型性能,我们需要对模型的超参数进行调整。常用的方法包括绘制学习曲线和验证曲线。
模型的准确率反映了模型的整体性能。准确率较高的模型可能面临过拟合或欠拟合的问题。
学习曲线展示了训练样本数量与模型准确率之间的关系。通过观察学习曲线,我们可以判断模型是否存在欠拟合或过拟合的情况。
```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() ```
验证曲线用于评估不同超参数值对模型性能的影响。例如,我们可以通过改变逻辑回归的正则化参数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() ```
网格搜索是一种系统地寻找最优超参数组合的方法。通过定义参数空间并穷举所有可能的组合,我们可以找到使模型性能最优的一组参数。
```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) ```
```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曲线。
混淆矩阵是评估分类模型性能的重要工具。它展示了模型在各个类别上的预测准确性。
```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() ```
除了混淆矩阵,我们还可以计算其他重要的评估指标,如准确率、召回率和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)) ```
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)) ```
以上是改写后的内容,确保了文章的紧凑性和可读性,同时保留了关键信息和价值点。