機器學習技術在應用以前使用「訓練+檢驗」的模式(一般被稱做」交叉驗證「)。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