一般學機器學習的都知道有個定理,就是說整體誤差Mean Square Error(MSE)包括了Bias(偏差)和Variance(方差)兩個部分,如果參數越來越多,那么Bias會越小,而Variance會越大。道理也很簡單,因為參數越多,越容易擬合真實的向量,但每個參數的估計都帶來一點隨機性,整體方差當然就大了。
一般的最小二乘是無偏估計,為了降低方差,提高泛化能力,一般會犧牲精度,比如各種正則化方法都可以降低方差,但都會引入Bias。
但所有以上這些,都是在低維統(tǒng)計眾的結論,也就是默認參數的個數p小于樣本的數量n。
但到了高維統(tǒng)計,也就是p>n甚至p>>n的時候,也就是p遠大于n的時候,以上結論有時候并不成立。
就好像牛頓力學,只在低速宏觀物體運動中成立,但在高速微觀運動中并不成立。機器學習、統(tǒng)計學其實跟統(tǒng)計物理有類似的地方。
比如現在的機器學習中有個詞叫做double descent,也就是所謂“雙重下降”,指的測試誤差隨著參數個數的增加,一開始先下降,然后上升,這是傳統(tǒng)機器學習的情況;但到了高維機器學習,某些情況下,隨著參數的增加,它還會繼續(xù)下降。
比如這是一幅比較經典的double descent的圖:
還有一些簡化實驗的圖
都可以看到,隨著features(特征)的數目逐漸增加,測試誤差先下降,然后增加,最后繼續(xù)下降。
這個就具有很強大的現實意義,意味著人們不用擔心訓練集過度優(yōu)化,不用擔心大力出奇跡,不用擔心過度擬合,只要成本可以支持,比如超級計算機夠強大,內存足夠大,完全可以擬合超級復雜的模型,參數越多越好,反正最后測試集誤差也是會下降的。
主要的原因在于,比如p>>n,這里n=200,如果p=400,也就是特征數目是400,遠大于樣本數量。進一步假設,其中只有200個特征是有意義的,其它都是噪音;那么噪聲變量越多,有意義的那部分特征只是一個更小的子空間,預測將越來越不準確,bias會越大,因為預測會越來越不準確;但同時,由于噪聲多了,如果加入一定的正則化條件,那么分配給每個特征的系數絕對值會更小,也就是variance會更小,反而不容易過度擬合。
比如我找一篇雄文來說明一下,美國統(tǒng)計學總統(tǒng)獎得主、斯坦福統(tǒng)計系的大佬、統(tǒng)計學習圣經Elements of Statistical Learning的作者Tibshirani,他兒子小Tibshirani在一篇論文是這么寫的:
看來美國也是階層固化啊,統(tǒng)計學大佬的兒子繼續(xù)搞統(tǒng)計,說不定未來也拿總統(tǒng)獎。學術壟斷,世風日下。
回到正題,反正也說明我說的沒錯,還真有這事。因此,繼續(xù)可以得到一些反直覺的結論:
-
數據不要太多。比如有200個特征,如果用1000個數據,那么是p>n,普通的低維統(tǒng)計;但如果用100個數據,就是p>n,變成高維統(tǒng)計了,高維統(tǒng)計就不怕過度擬合了。
-
可以盡情使用更多的參數和更復雜的模型。因為貌似大佬說最后測試誤差還是會下降的,那么只要參數越來越多,大力出奇跡就可以的。
-
double descent不是深度學習特有。
上面例子可以看出,普通的線性回歸也會有這樣的特性,所以也不要太迷信深度學習。結構太復雜,反而掩蓋了事情的本質。
最后簡單用R語言做一個實驗來驗證一下:
random_features <- function(n=100, d=100, num_informative_features=20) {
y <- rnorm(n)
X <- matrix(rnorm(n*min(d, num_informative_features)), nrow=n) + y
if (d>num_informative_features)
X <- cbind(X, matrix(rnorm(n*(d-num_informative_features)), nrow=n))
return (list(X=X,y=y))
library(lmeVarComp)
set.seed(200)
n <- 200
ds <- seq(from=20, to=2*n, by=20)[-10]
num_informative_features <- 1000
nreps <- 10
mses <- matrix(0, nrow=length(ds), nreps)
train_errors <- matrix(0, nrow=length(ds), nreps)
for (rep in 1:nreps) {
mse <- c()
train_error <- c()
for (d in ds) {
aa <- random_features(n,d,num_informative_features)
Xtrain <- aa$X
ytrain <- aa$y
w <- mnls(Xtrain, ytrain)
bb <- random_features(round(n/10),d,num_informative_features)
Xtest <- bb$X
ytest <- bb$y
mse <- c(mse, sum((ytest-Xtest%*%w)^2))
train_error <- sum((ytrain-Xtrain%*%w)^2)
}
mses[,rep] <- mse
train_errors[,rep] <- train_error
}
mean_mse <- apply(mses, 1, mean)
plot(ds,mean_mse, type="l")
最后上圖:
很明顯看到了double descent,測試誤差先下降后上升,在p=n會爆炸,這里圖刪除了那個點,否則會壓縮的太厲害;然后p>n之后又繼續(xù)下降了。
另外還可以看到訓練集的誤差是零,高維統(tǒng)計一般可以在訓練集做到完美擬合:
mean_te <- apply(train_errors, 1, mean)
plot(mean_te, type="l")
值得注意的是,這里求解使用了minimum norm least squres(mnls),這個不同于lasso,ridge和least squares,需要用到專門的包求解。由于p>n,普通的最小二乘無法求解,如果是lasso、ridge,似乎沒有類似的效果。不清楚python有沒有類似的包,Julia會更方便,直接就行。
對于量化交易的啟示也類似,如果不怕過度擬合,那么建模是很容易的事情。當然,交易有風險,入行需謹慎,我也只是拋磚引玉。