目錄
k-折交叉驗證(k-fold crossValidation)
k-折交叉驗證(k-fold crossValidation)
在機器學習中,將數據集A分爲訓練集(training set)B和測試集(test set)C,在樣本量不充足的情況下,爲了充分利用數據集對算法效果進行測試。對一組n個樣本進行k-折交叉驗證,這些樣本被隨機分成k個大小几乎相同的不相交驗證集。這將生成長度約爲n*(1-1/k)的k個訓練子集,每次將其中一個包作爲測試集,剩下k-1個包作爲訓練集進行訓練.,交叉驗證法評估結果的穩定性和保真性在很大程度上取決於k的取值.k最常用的取值是10,其他常用的k值有5 20等。
主要目的:
通過多次訓練,得出偏差和方差,來衡量一個模型評估方法的好壞。
Error = Bias^2 + Variance+Noise
Bias(偏差):反映的是模型在樣本上的輸出與真實值之間的誤差,即模型本身的精準度,即算法本身的擬合能力。
Variance(方差):反映的是模型每一次輸出結果與模型輸出期望之間的誤差,即模型的穩定性。反應預測的波動情況。
Noise(噪聲):這就簡單了,就不是你想要的真正數據,你可以想象爲來破壞你實驗的元兇和造成你可能過擬合的原因之一,至於爲什麼是過擬合的原因,因爲模型過度追求Low Bias會導致訓練過度,對測試集判斷表現優秀,導致噪聲點也被擬合進去了。
Julia 中代碼實現
針對K -折差驗證,Julia 目前常用的兩個包分別是:MLBase.jl or ScikitLearn.jl,想要搞清楚拆分數據的模式,然後再看驗證方法。
KFold
劃分數據集的原理:根據n_split直接進行劃分k個子集,每個子集均做一次測試集,其餘的作爲訓練集。交叉驗證重複k次,每次選擇一個子集作爲測試集,並將k次的平均交叉驗證識別正確率作爲結果
Julia原生的函數中,MLBase庫有一個Kfold函數,可以用於交叉驗證,這裏給出部分僞代碼:
# 對於DataFrame 無法直接拆分數據集,需要使用其他方式
a = collect(Kfold(size(houses)[1], 5))
# 選用數據集
row = a[1]
houses[row,:]
詳細的實現可以參考:交叉驗證示例
StratifiedKFold
劃分數據集的原理:它是分層採樣,確保訓練集,劃分後的訓練集和驗證集中類別分佈儘量和原數據集一樣
實現方式一:
#Symbol相當於佔位符,但必須與數據的length相等 ,:b 或者:a的所佔比例對結果影響不大,但是數量都必須大於K
index_row = [i for i = 1:size(houses)[1]]
index_a = [:a for i = 1:size(houses)[1]*0.5]
index_b = [:b for i = 1:size(houses)[1]*0.5]
index = vcat(index_a,index_b)
rows = collect(StratifiedKfold(index, 10))
# 選用數據集
row = rows[1]
houses[row,:]
實現方式二:
#更傾向於選擇連續的數據,而不是隨機先擇,可能跟y 的生成方式有關
using ScikitLearn
f(i) = ifelse(i<size(houses)[1]*0.75, 1, 2)
y = [f(i) for i in 1:size(houses)[1]]
folds = ScikitLearn.CrossValidation.StratifiedKFold(y, n_folds=10)
LOOCV(留一交叉驗證)
留一交叉驗證是一個極端的例子,如果數據集D的大小爲N,那麼用N-1條數據進行訓練,用剩下的一條數據作爲驗證,用一條數據作爲驗證的壞處就是可能EvalEval和EoutEout相差很大,所以在留一交叉驗證裏,每次從D中取一組作爲驗證集,直到所有樣本都作過驗證集,共計算N次,最後對驗證誤差求平均,得到Eloocv(H,A),這種方法稱之爲留一法交叉驗證。
什麼時候使用LOOCV:LOOCV
rows = collect(LOOCV(floor(size(houses)[1])))
# 選用數據集
row = rows[1]
houses[row,:]
其它模式參考:折交叉驗證模式
交叉驗證的函數
實現方式一:
#自己寫
function cross_validation(train,k, learn)
a = collect(Kfold(size(train)[1], k))
for i in 1:k
row = a[i]
temp_train = train[row,:]
temp_test = train[setdiff(1:end, row),:]
#機器學習的函數learn 具體執行邏輯
end
end
#或者用手冊提供的
using MLBase
# functions
compute_center(X::Matrix{Float64}) = vec(mean(X, 2))
compute_rmse(c::Vector{Float64}, X::Matrix{Float64}) =
sqrt(mean(sum(abs2(X .- c),1)))
# data
const n = 200
const data = [2., 3.] .+ randn(2, n)
# cross validation
scores = cross_validate(
inds -> compute_center(data[:, inds]), # training function
(c, inds) -> compute_rmse(c, data[:, inds]), # evaluation function
n, # total number of samples
Kfold(n, 5)) # cross validation plan: 5-fold
# get the mean and std of the scores
(m, s) = mean_and_std(scores)
實現方式二:
using ScikitLearn
using PyCall
@sk_import model_selection : cross_val_score
@sk_import datasets: load_iris
@sk_import svm: SVC
#加載並返回鳶尾花數據集 (scikit-learn自帶的數據集)
iris = load_iris() # 返回
svc = SVC(kernel="linear", C=1)
scores = cross_val_score(svc, iris["data"], iris["target"], cv=5)
# 5-element Array{Float64,1}:
# 0.9666666666666667
# 1.0
# 0.9666666666666667
# 0.9666666666666667
# 1.0