机器学习技术在应用以前使用“训练+检验”的模式(一般被称做”交叉验证“)。html

预测模型为什么没法保持稳定?
让咱们经过如下几幅图来理解这个问题:python

此处咱们试图找到尺寸(size)和价格(price)的关系。三个模型各自作了以下工做:算法
- 第一个模型使用了线性等式。对于训练用的数据点,此模型有很大偏差。这样的模型在初期排行榜和最终排行榜都会表现很差。这是“拟合不足”(“Under fitting”)的一个例子。此模型不足以发掘数据背后的趋势。
- 第二个模型发现了价格和尺寸的正确关系,此模型偏差低/归纳程度高。
- 第三个模型对于训练数据几乎是零偏差。这是由于此关系模型把每一个数据点的误差(包括噪声)都归入了考虑范围,也就是说,这个模型太过敏感,甚至会捕捉到只在当前数据训练集出现的一些随机模式。这是“过分拟合”(“Over fitting”)的一个例子。这个关系模型可能在初榜和终榜成绩变化很大。
在应用中,一个常见的作法是对多个模型进行迭代,从中选择表现更好的。然而,最终的分数是否会有改善依然未知,由于咱们不知道这个模型是更好的发掘潜在关系了,仍是过分拟合了。为了解答这个难题,咱们应该使用交叉验证(cross validation)技术。它能帮咱们获得更有归纳性的关系模型。app
实际上,机器学习关注的是经过训练集训练事后的模型对测试样本的分类效果,咱们称之为泛化能力。左右两图的泛化能力就很差。在机器学习中,对误差和方差的权衡是机器学习理论着重解决的问题。dom
什么是交叉验证?
交叉验证意味着须要保留一个样本数据集,不用来训练模型。在最终完成模型前,用这个数据集验证模型。机器学习
交叉验证包含如下步骤:函数
- 保留一个样本数据集。--测试集
- 用剩余部分训练模型。--训练集
- 用保留的数据集(测试集)验证模型。
这样作有助于了解模型的有效性。若是当前的模型在此数据集也表现良好,那就带着你的模型继续前进吧!它棒极了! 学习
交叉验证的经常使用方法是什么?
交叉验证有不少方法。下面介绍其中几种:测试
1. “验证集”法spa
保留 50% 的数据集用做验证,剩下 50% 训练模型。以后用验证集测试模型表现。不过,这个方法的主要缺陷是,因为只使用了 50% 数据训练模型,原数据中一些重要的信息可能被忽略。也就是说,会有较大偏误。
2. 留一法交叉验证 ( LOOCV )
这种方法只保留一个数据点用做验证,用剩余的数据集训练模型。而后对每一个数据点重复这个过程。这个方法有利有弊:
- 因为使用了全部数据点,因此误差较低。
- 验证过程重复了 n 次( n 为数据点个数),致使执行时间很长。
- 因为只使用一个数据点验证,这个方法致使模型有效性的差别更大。获得的估计结果深受此点的影响。若是这是个离群点,会引发较大误差。
3. K 层交叉验证 (K- fold cross validation)
从以上两个验证方法中,咱们学到了:
- 应该使用较大比例的数据集来训练模型,不然会致使失败,最终获得偏误很大的模型。
- 验证用的数据点,其比例应该恰到好处。若是太少,会致使验证模型有效性时,获得的结果波动较大。
- 训练和验证过程应该重复屡次(迭代)。训练集和验证集不能一成不变。这样有助于验证模型有效性。
是否有一种方法能够兼顾这三个方面?
答案是确定的!这种方法就是“ K 层交叉验证”这种方法简单易行。简要步骤以下:
- 把整个数据集随机分红 K“层”
- 用其中 K-1 层训练模型,而后用第K层验证。
- 记录从每一个预测结果得到的偏差。
- 重复这个过程,直到每“层”数据都做过验证集。
- 记录下的 k 个偏差的平均值,被称为交叉验证偏差(cross-validation error)。能够被用作衡量模型表现的标准。
-
把整个数据集随机分红 K“层”
-
对于每一份来讲:
1).以该份做为测试集,其他做为训练集; (用其中 K-1 层训练模型,而后用第K层验证)
2).在训练集上获得模型;
3).在测试集上获得生成偏差,这样对每一份数据都有一个预测结果;(记录从每一个预测结果得到的偏差)
-
记录下的 k 个偏差的平均值,被称为交叉验证偏差(cross-validation error)。能够被用作衡量模型表现的标准
-
取偏差最小的那一个模型。
一般。此算法的缺点是计算量较大。
当 k=10 时,k 层交叉验证示意图以下:

这里一个常见的问题是:“如何肯定合适的k值?”
记住,K 值越小,偏误越大,因此越不推荐。另外一方面,K 值太大,所得结果会变化无穷。K 值小,则会变得像“验证集法”;K 值大,则会变得像“留一法”(LOOCV)。因此一般建议的值是 k=10 。
如何衡量模型的偏误/变化程度?
K 层交叉检验以后,咱们获得 K 个不一样的模型偏差估算值(e1, e2 …..ek)。理想的状况是,这些偏差值相加得 0 。要计算模型的偏误,咱们把全部这些偏差值相加。平均值越低,模型越优秀。
模型表现变化程度的计算与之相似。取全部偏差值的标准差,标准差越小说明模型随训练数据的变化越小。
咱们应该试图在偏误和变化程度间找到一种平衡。下降变化程度、控制偏误能够达到这个目的。这样会获得更好的预测模型。进行这个取舍,一般会得出复杂程度较低的预测模型。
Python Code
from sklearn import cross_validation
model = RandomForestClassifier(n_estimators=100)
#简单K层交叉验证,10层。
cv = cross_validation.KFold(len(train), n_folds=10, indices=False)
results = []
# "Error_function" 可由你的分析所需的error function替代
for traincv, testcv in cv:
probas = model.fit(train[traincv], target[traincv]).predict_proba(train[testcv])
results.append( Error_function )
print "Results: " + str( np.array(results).mean() )
R Code
library(data.table)
library(randomForest)
data <- iris
str(data)
#交叉验证,使用rf预测sepal.length
k = 5
data$id <- sample(1:k, nrow(data), replace = TRUE)
list <- 1:k
# 每次迭代的预测用数据框,测试用数据框
# the folds
prediction <- data.table()
testsetCopy <- data.table()
# 写一个进度条,用来了解CV的进度
progress.bar <- create_progress_bar("text")
progress.bar$init(k)
#k层的函数
for(i in 1:k){
# 删除id为i的行,建立训练集
# 选id为i的行,建立训练集
trainingset <- subset(data, id %in% list[-i])
testset <- subset(data, id %in% c(i))
#运行一个随机森林模型
mymodel <- randomForest(trainingset$Sepal.Length ~ ., data = trainingset, ntree = 100)
#去掉回应列1, Sepal.Length
temp <- as.data.frame(predict(mymodel, testset[,-1]))
# 将迭代出的预测结果添加到预测数据框的末尾
prediction <- rbind(prediction, temp)
# 将迭代出的测试集结果添加到测试集数据框的末尾
# 只保留Sepal Length一列
testsetCopy <- rbind(testsetCopy, as.data.frame(testset[,1]))
progress.bar$step()
}
# 将预测和实际值放在一块儿
result <- cbind(prediction, testsetCopy[, 1])
names(result) <- c("Predicted", "Actual")
result$Difference <- abs(result$Actual - result$Predicted)
# 用偏差的绝对平均值做为评估
summary(result$Difference)
原文连接:
http://www.analyticsvidhya.com/blog/2015/11/improve-model-performance-cross-validation-in-python-r/
http://datartisan.com/article/detail/62.html