使用网格搜索(Grid Search)进行机器学习模型调整
模型超参数是模型外部的一个特征,它的值不能从数据中估计。超参数的值必须在学习过程开始之前设置。例如,支持向量机中的c,最近邻中的k,神经网络中的隐藏层数。
与此相反,参数是模型的一个内在特征,它的值可以通过数据来估计。例如,线性/逻辑回归的beta系数或者支持向量机的支持向量。
网格搜索用于查找模型的最佳 超参数,从而产生最“准确”的预测。
让我们通过在 Breast Cancer数据集上构建机器学习分类模型来查看网格搜索(https://archive.ics.uci.edu/ml/datasets/breast+cancer+wisconsin+%28original%29)。
1.导入机器学习数据集并查看前10行,Python实现如下:
#import libraries import warnings warnings.filterwarnings('ignore') import pandas as pd import numpy as np import matplotlib.pyplot as plt import os os.chdir('C:\Users\rohan\Documents\Analytics\Data') #import data data = pd.read_csv('breast-cancer-wisconsin.csv',header=None) #set column names data.columns = ['Sample Code Number','Clump Thickness','Uniformity of Cell Size', 'Uniformity of Cell Shape','Marginal Adhesion','Single Epithelial Cell Size', 'Bare Nuclei','Bland Chromatin','Normal Nucleoli','Mitoses','Class'] #view top rows data.head(10)
输出:
数据集中的每一行都有两个可能的类别之一:良性(由2表示)和恶性(由4表示)。此外,此机器学习数据集中有10个属性(如上所示)将用于预测,但代码编号(id number)除外。
2. 清理数据并将类值重命名为0/1,以便进行机器学习模型构建(其中1表示恶性情况)。同时,让我们观察类的分布。Python实现如下:
#Data cleaning data = data.drop(['Sample Code Number'],axis=1) #Drop 1st column data = data[data['Bare Nuclei'] != '?'] #Remove rows with missing data data['Class'] = np.where(data['Class'] ==2,0,1) #Change the Class representation #Distribution of Class data['Class'].value_counts()
输出:
良性病例444例,恶性病例239例。
3.在构建分类模型之前,我们先构建一个虚拟分类器来确定“基线”性能。
#Split data into attributes and class X = data.drop(['Class'],axis=1) y = data['Class'] #perform training and test split from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42) #Dummy Classifier from sklearn.dummy import DummyClassifier clf = DummyClassifier(strategy= 'most_frequent').fit(X_train,y_train) y_pred = clf.predict(X_test) #Distribution of y test print('y actual : ' + str(y_test.value_counts())) #Distribution of y predicted print('y predicted : ' + str(pd.Series(y_pred).value_counts()))
输出:
从输出中,我们可以观察到测试数据集中有68个恶性病例和103个良性病例。但是,我们的分类器将所有情况预测为良性(因为它是多数类)。
4.计算此机器学习模型的评估指标,Python代码如下:
# Model Evaluation metrics from sklearn.metrics import accuracy_score,recall_score,precision_score,f1_score print('Accuracy Score : ' + str(accuracy_score(y_test,y_pred))) print('Precision Score : ' + str(precision_score(y_test,y_pred))) print('Recall Score : ' + str(recall_score(y_test,y_pred))) print('F1 Score : ' + str(f1_score(y_test,y_pred))) #Dummy Classifier Confusion matrix from sklearn.metrics import confusion_matrix print('Confusion Matrix : ' + str(confusion_matrix(y_test,y_pred)))
输出:
模型的准确度为60.2%,但这种情况下,准确度可能不是评估模型的最佳指标。那么,我们来看看其他评估指标。
上图是混淆矩阵,添加了标签和颜色以获得更好的直觉。总结混淆矩阵:TRUE POSITIVES(TP)= 0,TRUE NEGATIVES(TN)= 103,FALSE POSITIVES(FP)= 0,FALSE NEGATIVES(FN)= 68.评估指标的公式如下:
由于该模型没有正确地对任何恶性病例进行分类,因此召回和精度指标为0。
5.现在我们已经有了基准精度,让我们用默认参数构建Logistic回归模型并评估模型。Python实现如下:
#Logistic regression from sklearn.linear_model import LogisticRegression clf = LogisticRegression().fit(X_train,y_train) y_pred = clf.predict(X_test) # Model Evaluation metrics from sklearn.metrics import accuracy_score,recall_score,precision_score,f1_score print('Accuracy Score : ' + str(accuracy_score(y_test,y_pred))) print('Precision Score : ' + str(precision_score(y_test,y_pred))) print('Recall Score : ' + str(recall_score(y_test,y_pred))) print('F1 Score : ' + str(f1_score(y_test,y_pred))) #Logistic Regression Classifier Confusion matrix from sklearn.metrics import confusion_matrix print('Confusion Matrix : ' + str(confusion_matrix(y_test,y_pred)))
输出:
通过使用默认参数拟合Logistic回归模型,我们得到了一个“更好”的模型。准确度为94.7%,同时精度达到惊人的98.3%。现在,让我们再次看一下这个模型结果的混淆矩阵:
观察错误分类的情况,我们可以观察到8例恶性病例被错误地归类为良性(假阴性)。此外,只有一个良性病例被归类为恶性病例(假阳性)。
让我们尝试使用网格搜索来最小化错误否定,以找到最佳参数。网格搜索可用于改进任何特定的评估指标。
我们需要关注的减少漏报的指标是 召回。
6.网格搜索以最大化Recall
from sklearn.model_selection import GridSearchCV clf = LogisticRegression() grid_values = {'penalty': ['l1', 'l2'],'C':[0.001,.009,0.01,.09,1,5,10,25]} grid_clf_acc = GridSearchCV(clf, param_grid = grid_values,scoring = 'recall') grid_clf_acc.fit(X_train, y_train) print(grid_clf_acc.best_estimator_) y_pred_acc = grid_clf_acc.predict(X_test) # Model Evaluation metrics from sklearn.metrics import accuracy_score,recall_score,precision_score,f1_score print('Accuracy Score : ' + str(accuracy_score(y_test,y_pred_acc))) print('Precision Score : ' + str(precision_score(y_test,y_pred_acc))) print('Recall Score : ' + str(recall_score(y_test,y_pred_acc))) print('F1 Score : ' + str(f1_score(y_test,y_pred_acc))) #Dummy Classifier Confusion matrix from sklearn.metrics import confusion_matrix print('Confusion Matrix : ' + str(confusion_matrix(y_test,y_pred_acc)))
输出:
我们调整的超参数是:
- Penalty:l1或l2是惩罚中使用的规范。
- C:正则化强度的反向 - 较小的C值指定更强的正则化。
此外,在网格搜索功能中,我们有评分参数,我们可以在其中指定评估模型的指标(我们选择召回作为指标)。从下面的混淆矩阵中,我们可以看到假阴性的数量已经减少,但是,这是以增加误报为代价的。网格搜索后的召回率从88.2%跃升至91.1%,而精确度则从98.3%下降至87.3%。python代码如下:
#Function to plot intuitive confusion matrix import itertools def plot_confusion_matrix(cm, classes, normalize=False, title='Confusion matrix', cmap=plt.cm.Blues): """ This function prints and plots the confusion matrix. Normalization can be applied by setting `normalize=True`. """ if normalize: cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis] print("Normalized confusion matrix") else: print('Confusion matrix, without normalization') print(cm) plt.imshow(cm, interpolation='nearest', cmap=cmap) plt.title(title) plt.colorbar() tick_marks = np.arange(len(classes)) plt.xticks(tick_marks, classes, rotation=45) plt.yticks(tick_marks, classes) fmt = '.2f' if normalize else 'd' thresh = cm.max() / 2. for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])): plt.text(j, i, format(cm[i, j], fmt), horizontalalignment="center", color="white" if cm[i, j] > thresh else "black") plt.ylabel('True label') plt.xlabel('Predicted label') plt.tight_layout() # Compute confusion matrix cnf_matrix = confusion_matrix(y_test, y_pred_acc) np.set_printoptions(precision=2) # Plot non-normalized confusion matrix plt.figure() class_names = [0,1] plot_confusion_matrix(cnf_matrix, classes=class_names, title='Confusion matrix - Logistic Regression + Grid Search') a = plt.gcf() a.set_size_inches(8,4) plt.show()
Confusion matrix, without normalization
[[94 9]
[ 6 62]]
您可以使用“f1”得分作为评估指标,进一步调整模型以在精确度和召回之间取得平衡。
网格搜索为指定的每个超参数组合构建模型,并评估每个机器学习模型。用于超参数调整的更有效的技术是随机化搜索 - 其中使用超参数的随机组合来找到最佳解决方案。