在机器学习与数据挖掘中进行模型验证的一个重要目的是要选出一个最合适的模型。对于有监督学习而言,我们希望模型对于未知数据具有很强的泛化能力,所以就需要模型验证这一过程来评估不同的模型对于未知数据的表现效果。
最先我们用训练准确度(用全部数据进行训练和测试)来衡量模型的效果,这种方法容易导致模型过拟合。最初,为了解决这个问题,我们将所有数据分成两部分:训练集 和 测试集。我们用训练集进行模型训练,得到的模型再用测试集来衡量模型的预测表现能力,这种度量方式叫测试准确度,这种方式可以有效避免过拟合。 测试准确度的一个缺点是其样本准确度是一个高方差估计(high variance estimate),所以该样本准确度会依赖不同的测试集,其表现效果不尽相同。
例如,如上图所示,我们可以将蓝色部分的数据作为训练集(包含7、22、13等数据),将右侧的数据作为测试集(包含91等),这样通过在蓝色的训练集上训练模型,在测试集上观察不同模型不同参数对应的MSE的大小,就可以合适选择模型和参数了。
最终模型与参数的选取将极大程度依赖于你对训练集和测试集的划分方法。
from sklearn.datasets import load_iris from sklearn.cross_validation import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn import metrics # read in the iris data iris = load_iris() X = iris.data y = iris.target for i in range(1, 5): print(“Random times”, i, “, accuracy score is:”,end= ) X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=i) knn = KNeighborsClassifier(n_neighbors=5) knn.fit(X_train, y_train) y_pred = knn.predict(X_test) print(metrics.accuracy_score(y_test, y_pred),\n)上面的测试准确率可以看出,不同的训练集、测试集分割的方法导致其准确率不同,而交叉验证的基本思想是:将数据集进行一系列分割,生成一组不同的训练测试集,然后分别训练模型并计算测试准确率,最后对结果进行平均处理。这样来有效降低测试准确率的差异。
2 交叉验证方法2.1 简单的交叉验证
1、 从全部的训练数据 S中随机选择 中随机选择 s的样例作为训练集 train,剩余的 作为测试集 作为测试集 test。
2、 通过对测试集训练 ,得到假设函数或者模型 。 3、 在测试集对每一个样本根据假设函数或者模型,得到训练集的类标,求出分类正确率。 4,选择具有最大分类率的模型或者假设。 这种方法称为 hold -out cross validation 或者称为简单交叉验证。由于测试集和训练集是分开的,就避免了过拟合的现象
2.2 k折交叉验证 k-fold cross validation
1、 将全部训练集 S分成 k个不相交的子集,假设 S中的训练样例个数为 m,那么每一个子 集有 m/k 个训练样例,,相应的子集称作 {s1,s2,…,sk}。 2、每次从分好的子集中里面,拿出一个作为测试集,其它k-1个作为训练集
3、根据训练训练出模型或者假设函数。 4、 把这个模型放到测试集上,得到分类率。
5、计算k次求得的分类率的平均值,作为该模型或者假设函数的真实分类率。
这个方法充分利用了所有样本。但计算比较繁琐,需要训练k次,测试k次。
2.3 代码
用sklearn中的数据集iris 导入需要的包
from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.metrics import (brier_score_loss, precision_score, recall_score,f1_score) from sklearn.model_selection import learning_curve import numpy as np import matplotlib.pyplot as plt #取出需要的数据,其中iris_X有4个属性,共有150个样本点,iris_y的取值有3个,分别是0,1,2 iris = load_iris() iris_X = iris.data iris_y = iris.target print(iris_X.size) print(iris_X) print(iris_y) X_train, X_test, y_train, y_test = train_test_split(iris_X, iris_y, test_size=0.3) print(X_train.size) clf = LogisticRegression(random_state=0, solver=newton-cg, multi_class=multinomial) #训练模型,这里计算出参数w和b clf.fit(X_train, y_train) print(clf.coef_) print(clf.intercept_) y_pred = clf.predict(X_test) print(clf.predict(X_test)) print(y_test) print(“\tPrecision: %1.3f” % precision_score(y_test, y_pred, average=”micro”)) print(“\tRecall: %1.3f” % recall_score(y_test, y_pred, average=”micro”)) print(“\tF1: %1.3f\n” % f1_score(y_test, y_pred, average=”micro”)) X_train, X_test, y_train, y_test = train_test_split(iris_X, iris_y, test_size=0.0) train_sizes, train_loss, test_loss = learning_curve( clf, X_train, y_train, cv=10, train_sizes=[0.1, 0.25, 0.5, 0.75, 1]) 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=”Training”) 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()留一法就是每次只留下一个样本做测试集,其它样本做训练集,如果有k个样本,则需要训练k次,测试k次。
留一发计算最繁琐,但样本利用率最高。适合于小样本的情况。
就是将样本集中的样本每次抽取一个不同的样本作为测试集,剩余的样本作为训练集。需要进行原样本个数次抽取,以进行后续的操作。假设一个.mat文件有310个样本,那么每次抽取一个不同的样本做测试,剩余的299个样本做训练。需要进行310次这样的过程,但是每次选取的做测试的样本是不同的,那么每次训练集的样本也是不同的。由于留一交叉验证的操作的次数十分多,这样选取出来的主成分更具普遍性,可以避免一些不必要的波动,避免一些数据分析时出现有时效果好,有时效果差,这样摇摆不定的情况。因此广受青睐,但是留一交叉验证也有其弊端,样本过多运算时间过长。 适用于小样本。
3.1 测试代码
from sklearn import model_selection import numpy as np X=np.array([[1,2],[3,4],[5,6],[7,8]]) labels=np.array([1,2,3,4]) lol=model_selection.LeaveOneOut() print(*******************origin***********************) for train_index,test_index in lol.split(X): print(TRAIN_index,train_index,Test_index,test_index) X_train,X_test=X[train_index],X[test_index] print(TRAIN data,X_train,Test data,X_test,sep= ) print(*******************labels***********************) for labels_train_index,labels_test_index in lol.split(labels): print(TRAIN_index,labels_train_index,Test_index,labels_test_index) labels_X_train,labels_X_test=labels[labels_train_index],labels[labels_test_index] print(TRAIN data,labels_X_train,Test data,labels_X_test,sep= )3.2 输出结果
免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:机器学习之交叉验证方法详解【基于Scikit-Learn】 https://www.yhzz.com.cn/a/12688.html