1 数据集的划分
训练集、验证集和测试集这三个名词在机器学习领域极其常见,但很多人并不是特别清楚,尤其是后两个经常被人混用。
在有监督(supervise)的机器学习中,数据集常被分成2~3个,即:训练集(train set),验证集(validation set),测试集(test set)。
那为什么要进行数据集划分呢?
这是为了防止模型的过拟合,如果我们把所有数据都用来训练模型的话,建立的模型自然是最契合这些数据的,测试表现也好。但换了其它数据集测试这个模型效果可能就没那么好了。以分类问题举个栗子~
训练集
作用:估计模型
学习样本数据集,通过匹配一些参数来建立一个分类器。建立一种分类的方式,主要是用来训练模型的。
验证集
作用:确定网络结构或者控制模型复杂程度的参数
对学习出来的模型,调整分类器的参数,如在神经网络中选择隐藏单元数。验证集还用来确定网络结构或者控制模型复杂程度的参数。
测试集
作用:检验最终选择最优的模型的性能如何
主要是测试训练好的模型的分辨能力(识别率等)
2 划分方法
2.1 Hold-Out Method
将原始数据随机分为两组,一组做为训练集,一组做为验证集,利用训练集训练分类器,然后利用验证集验证模型,记录最后的分类准确率为此分类器的性能指标。此种方法的好处的处理简单,只需随机把原始数据分为两组即可,其实严格意义来说Hold-Out Method并不能算是CV,因为这种方法没有达到交叉的思想,由于是随机的将原始数据分组,所以最后验证集分类准确率的高低与原始数据的分组有很大的关系,所以这种方法得到的结果其实并不具有说服性。通常的划分比例为28分或37分。
from sklearn.model_selection import train_test_split
data=load_iris()
X=data.data
y=data.target
X_trian,y_train,X_test,y_test=train_test_split(X,y,test_size=0.2,random_state=1)
2.2 K-fold Cross Validation(K-折交叉验证,记为K-CV)
将原始数据分成K组(一般是均分),将每个子集数据分别做一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型,用这K个模型最终的验证集的分类准确率的平均数作为此K-CV下分类器的性能指标。K一般大于等于2,实际操作时一般从3开始取,只有在原始数据集合数据量小的时候才会尝试取2。K-CV可以有效的避免过学习以及欠学习状态的发生,最后得到的结果也比较具有说服性。
本文主要讲的就是sklearn中的cross_val_score方法
(1)这个方法是对数据进行多次分割,然后训练多个模型并评分,每次分割不一样。之后我们用评分的均值来代表这个模型的得分。方法重要参数是:cv代表计算多少次,分割次数;scoring代表评估方法。
from sklearn.model_selection import cross_val_score
data=load_iris()
X=data.data
y=data.target
knn = KNeighborsClassifier(n_neighbors=5)
score = cross_val_score(knn,X,y,cv=5,scoring='accuracy')
print(score)
print(score.mean())
scoring可用方法如下所示:
Scoring | Function | Comment |
---|---|---|
Classification | ||
‘accuracy’ | metrics.accuracy_score | |
‘balanced_accuracy’ | metrics.balanced_accuracy_score | for binary targets |
‘average_precision’ | metrics.average_precision_score | |
‘brier_score_loss’ | metrics.brier_score_loss | |
‘f1’ | metrics.f1_score | for binary targets |
‘f1_micro’ | metrics.f1_score | micro-averaged |
‘f1_macro’ | metrics.f1_score | macro-averaged |
‘f1_weighted’ | metrics.f1_score | weighted average |
‘f1_samples’ | metrics.f1_score | by multilabel sample |
‘neg_log_loss’ | metrics.log_loss | requires predict_proba support |
‘precision’ etc. | metrics.precision_score | suffixes apply as with ‘f1’ |
‘recall’ etc. | metrics.recall_score | suffixes apply as with ‘f1’ |
‘roc_auc’ | metrics.roc_auc_score | |
Clustering | ||
‘adjusted_mutual_info_score’ | metrics.adjusted_mutual_info_score | |
‘adjusted_rand_score’ | metrics.adjusted_rand_score | |
‘completeness_score’ | metrics.completeness_score | |
‘fowlkes_mallows_score’ | metrics.fowlkes_mallows_score | |
‘homogeneity_score’ | metrics.homogeneity_score | |
‘mutual_info_score’ | metrics.mutual_info_score | |
‘normalized_mutual_info_score’ | metrics.normalized_mutual_info_score | |
‘v_measure_score’ | metrics.v_measure_score | |
Regression | ||
‘explained_variance’ | metrics.explained_variance_score | |
‘neg_mean_absolute_error’ | metrics.mean_absolute_error | |
‘neg_mean_squared_error’ | metrics.mean_squared_error | |
‘neg_mean_squared_log_error’ | metrics.mean_squared_log_error | |
‘neg_median_absolute_error’ | metrics.median_absolute_error | |
‘r2’ | metrics.r2_score |
(2)我们可以用这个方法,改变超参数n_neighbors的值,对不同模型进行准确评分,进行参数选择。(代码比较简单,看注释应该可以理解)
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score
iris=load_iris()
X=iris.data
y=iris.target
#交叉验证对参数进行选择
k_range = range(1,31)
k_loss = []
k_accuracy = []
for k in k_range:#对参数进行控制,选择参数表现好的,可视化展示
knn = KNeighborsClassifier(n_neighbors=k)
accuracy = cross_val_score(knn,X,y,cv=10,scoring='accuracy')#for classification 精度
loss = -cross_val_score(knn,X,y,cv=10,scoring='neg_mean_squared_error')#for regression 损失函数
k_accuracy.append(accuracy.mean())#计算均值得分
k_loss.append(loss.mean())
#绘图
plt.figure()
plt.plot(k_range,k_accuracy)
plt.xlabel("Value of K for KNN")
plt.ylabel("Cross-validates Accuracy")
plt.show()
plt.plot(k_range,k_loss)
plt.xlabel("Value of K for KNN")
plt.ylabel("Cross-validates Loss")
plt.show()
结果如下,
(3)cv可以传入数据的分割方法:分割方法用ShuffleSplit(还有其他的类)类来定义
from sklearn.model_selection import ShuffleSplit
n_samples = iris.data.shape[0]
cv = ShuffleSplit(n_splits=3, test_size=0.3, random_state=0)
cross_val_score(clf, iris.data, iris.target, cv=cv)
3 相关方法
3.1 cross_validate方法
这个就是可以设置多个评分输出,其他一样
from sklearn.model_selection import cross_validate
scoring = ['precision_macro', 'recall_macro']#设置评分项
clf = KNeighborsClassifier(n_neighbors=5)
scores = cross_validate(clf,X,y, scoring=scoring, cv=5, return_train_score=False)
sorted(scores.keys())
print(scores['test_recall_macro'])
print(scores['test_precision_macro'])
输出结果如下,
[ 0.96666667 1. 0.93333333 0.96666667 1. ]
[ 0.96969697 1. 0.94444444 0.96969697 1. ]
3.2 cross_val_predict方法
这个是对计算预测值,然后我们可以根据预测值计算得分。
from sklearn import metrics
from sklearn.model_selection import cross_val_predict
clf = KNeighborsClassifier(n_neighbors=5)
predicted = cross_val_predict(clf,X,y, cv=10)
score = metrics.accuracy_score(y, predicted)#计算得分
print(score)
输出结果如下,
0.966666666667
3.3 Validation curves验证曲线
前面主要讲的是模型的评估,主要思想就是采用多次数据分割的思想进行交叉验证,用每次分割的得分均值评估模型。这里主要讲通过可视化了解模型的训练过程,判断模型是否过拟合,并进行参数选择。
1、validation_curve验证曲线方法:这个方法是用来测试模型不同参数(不同模型)的得分情况。重要参数为:param_name代表要控制的参数;param_range代表参数的取值列表。其他参数都一样。返回训练和测试集上的得分。
(根据模型在训练集合测试集上,不同参数取值的结果,判断模型是否过拟合,并进行参数选择;每次针对一个参数)
from sklearn.model_selection import validation_curve #可视化学习的整个过程
from sklearn.datasets import load_digits
from sklearn.svm import SVC
import matplotlib.pyplot as plt
import numpy as np
digits=load_digits()
X=digits.data
y=digits.target
gamma_range=np.logspace(-6,-2.3,5)#从-6到-2.3取5个点
train_loss,test_loss=validation_curve(
SVC(),X,y,param_name="gamma",param_range=gamma_range,cv=10,scoring="neg_mean_squared_error")
train_loss_mean= (-1)*np.mean(train_loss,axis=1)
test_loss_mean= (-1)*np.mean(test_loss,axis=1)
plt.plot(gamma_range,train_loss_mean,"o-",color="r",label="Training")
plt.plot(gamma_range,test_loss_mean,"o-",color="g",label="Cross-validation")
plt.xlabel("gamma")
plt.ylabel("Loss")
plt.legend(loc="best")
plt.show()
结果如下,
2、learning_curve学习曲线方法:这个方法显示了对于不同数量的训练样本的模型的验证和训练评分。 这是一个工具,可以找出我们从添加更多的训练数据中受益多少,以及估计器是否因方差错误或偏差错误而受到更多的影响。 如果验证分数和训练分数都随着训练集规模的增加而收敛到一个太低的值,那么我们就不会从更多的训练数据中受益。 在下面的情节中,你可以看到一个例子:朴素贝叶斯大致收敛到一个低分。
方法重要参数:train_sizes代表每次选择进行训练的数据大小。
方法返回:训练数据大小列表,训练集,测试集上的得分列表
from sklearn.model_selection import learning_curve #可视化学习的整个过程
from sklearn.datasets import load_digits
from sklearn.svm import SVC
import matplotlib.pyplot as plt
import numpy as np
digits=load_digits()
X=digits.data
y=digits.target
#交叉验证测试
train_sizes,train_loss,test_loss = learning_curve(SVC(gamma=0.1),X,y,cv=10,scoring='neg_mean_squared_error',train_sizes=[0.1,0.25,0.5,0.75,1]) #记录的点是学习过程中的10%,25%等等的点
train_loss_mean = -1 * np.mean(train_loss,axis=1)
test_loss_mean = -1 * np.mean(test_loss,axis=1)
#可视化展示
plt.plot(train_sizes,train_loss_mean,'o-',color='r',label='train')
plt.plot(train_sizes,test_loss_mean,'o-',color='g',label='cross_validation')
plt.xlabel("Training examples")
plt.ylabel("Loss")
plt.legend(loc="best")
plt.show()
#交叉验证测试
train_sizes,train_loss,test_loss = learning_curve(SVC(gamma=0.001),X,y,cv=10,scoring='neg_mean_squared_error',train_sizes=[0.1,0.25,0.5,0.75,1]) #记录的点是学习过程中的10%,25%等等的点
train_loss_mean = 1 * np.mean(train_loss,axis=1)
test_loss_mean = 1 * np.mean(test_loss,axis=1)
#可视化展示
plt.plot(train_sizes,train_loss_mean,'o-',color='r',label='train')
plt.plot(train_sizes,test_loss_mean,'o-',color='g',label='cross_validation')
plt.xlabel("Training examples")
plt.ylabel("Loss")
plt.legend(loc="best")
plt.show()
结果如下,
4 参考
https://scikit-learn.org/stable/modules/model_evaluation.html
https://scikit-learn.org/stable/modules/classes.html#model-validation
https://blog.csdn.net/u014248127/article/details/78899195