天天看點

模型泛化

模型泛化

目錄

    • 一、交叉驗證
    • 二、偏差方差權衡
    • 三、模型正則化
      • 1、嶺回歸(Ridege Regression)
      • 2、LASSO Regularization
      • 3、解釋Ridge和LASSO
      • 4、比較Ridge和Lasso
      • 5、彈性網
    • 我是尾巴
泛化即是,機器學習模型學習到的概念在它處于學習的過程中時模型沒有遇見過的樣本時候的表現。

​ 類似于考試前瘋狂刷題不管這些題做的都好都沒用,隻有在下次考試中才有效果,而下次考試的那些題可能從來沒見過,隻有學會這些基礎的東西,無論怎麼變都能認出來。模型也是一樣,不管訓練集上表現如何,隻有在新的未知的樣本集上有較好的表現,模型才是真的好,這就是模型的泛化能力。

  1. 首先讨論一下測試資料集的意義。假如将所有的訓練資料進行訓練處一個模型,此時如果模型發生了過拟合卻不自知,在訓練集上的表現誤差很小,但是很有可能模型的泛化能力不足,産生了過拟合。是以相應的我們就要把資料分為訓練資料和測試資料,通過測試資料集來判斷模型的好壞。
  2. 針對特定的測試資料集過拟合。

​ 通常情況下如果将資料分為訓練資料和測試資料,通過測試資料對模型的驗證進而調整訓練模型,也就說我們在圍繞着測試集進行打轉,設法在訓練資料中找到一組參數,在測試資料上表現最好,既然是這樣,就很有可能針對特定的測試資料集産生了過拟合。由此就引出了驗證集。

  1. 驗證集。

​ 測試資料集作為衡量最終模型性能的資料集。測試資料不參與模型建立,而訓練資料參與模型的訓練,驗證資料集參與模型評判,一旦效果不好就進行相應的調整重新訓練,這兩者都參與了模型的建立。驗證資料集用來調整超參數。其實,這麼做還是存在一定的問題,那就是這個驗證資料集的随機性,因為很有可能對這一份驗證集産生了過拟合。是以就有了交叉驗證(Cross Validation)。

​ 我們将訓練資料随機分為k份,上圖中分為k=3份,将任意兩種組合作為訓練集,剩下的一組作為驗證集,這樣就得到k個模型,然後在将k個模型的均值作為結果調參。顯然這種方式要比随機隻用一份資料作為驗證要靠譜的多。

接下裡就用實際的例子,來了解一下如何使用交叉驗證進行調參:

  • 第一種情況:隻使用訓練集測試集測試:
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier

digits = datasets.load_digits()
x = digits.data
y = digits.target

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4, random_state=666)

best_score, best_p, best_k = 0, 0, 0 
for k in range(2, 11):
    for  p in range(1, 6):
        knn_clf = KNeighborsClassifier(weights="distance", n_neighbors=k, p=p)
        knn_clf.fit(x_train, y_train)
        score = knn_clf.score(x_test, y_test)
        if score > best_score:
            best_score, best_p, best_k = score, p, k

print("Best K=", best_k)
print("Best P=", best_p)
print("Best score=", best_score)
           

輸出結果:

Best K= 3
Best P= 4
Best score= 0.9860917941585535
           
  • 第二種情況:
from sklearn.model_selection import cross_val_score

knn_clf = KNeighborsClassifier()
cross_val_score(knn_clf, x_train, y_train)
# array([0.98895028, 0.97777778, 0.96629213])
           

根據輸出結果,可以看出在sklearn中封裝的交叉驗證預設情況下分成三份。

best_score, best_p, best_k = 0, 0, 0 
for k in range(2, 11):
    for  p in range(1, 6):
        knn_clf = KNeighborsClassifier(weights="distance", n_neighbors=k, p=p)
        scores = cross_val_score(knn_clf, x_train, y_train)
        score = np.mean(scores)
        if score > best_score:
            best_score, best_p, best_k = score, p, k

print("Best K=", best_k)
print("Best P=", best_p)
print("Best score=", best_score)
           
Best K= 2
Best P= 2
Best score= 0.9823599874006478
           

對比第一種情況,我們發現得到的最優超參數是不一樣的,雖然score會稍微低一些,但是一般第二種情況更加可信。但是這個score隻是說明這組參數最優,并不是指的是模型對于測試集的準确率,是以接下來看一下準确率。

best_knn_clf = KNeighborsClassifier(weights='distance', n_neighbors=2, p=2)
best_knn_clf.fit(x_train, y_train)
best_knn_clf.score(x_test, y_test)
           

輸出結果:0.980528511821975,這才是模型的準确度。

如果想要修改預設的三份,再傳入一個參數就可以了。同樣地,下面的網格搜尋中的cv也是可以調整的。

cross_val_score(knn_clf, x_train, y_train, cv=5)
           

輸出結果:array([0.99543379, 0.97716895, 0.97685185, 0.98130841, 0.97142857])

  • 網格搜尋中的交叉驗證。

其實回顧網格搜尋的過程就使用了交叉驗證的手段。

from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier

param_grid = [
    {
        'weights':['distance'],
         'n_neighbors':[i for i in range(2, 11)],
        'p':[i for i in range(1, 6)]
    }
]
knn_clf = KNeighborsClassifier()
grid_search = GridSearchCV(knn_clf, param_grid, verbose=1)
grid_search.fit(x_train, y_train)
           
Fitting 3 folds for each of 45 candidates, totalling 135 fits
           
[Parallel(n_jobs=1)]: Done 135 out of 135 | elapsed:  1.3min finished
           
GridSearchCV(cv='warn', error_score='raise-deprecating',
       estimator=KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=None, n_neighbors=5, p=2,
           weights='uniform'),
       fit_params=None, iid='warn', n_jobs=None,
       param_grid=[{'weights': ['distance'], 'n_neighbors': [2, 3, 4, 5, 6, 7, 8, 9, 10], 'p': [1, 2, 3, 4, 5]}],
       pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',
       scoring=None, verbose=1)
           
grid_search.best_score_
# 0.9823747680890538
grid_search.best_params_
# {'n_neighbors': 2, 'p': 2, 'weights': 'distance'}
best_knn_clf = grid_search.best_estimator_
best_knn_clf.score(x_test, y_test)
# 0.980528511821975
           

這跟上面使用交叉驗證的到結果一緻。

  • k-折交叉驗證

    把訓練集分成k份,稱為k-folds cross validation,缺點就是,每次訓練k個模型,相當于整體性能慢了k倍。不過通常這種方法是最值得信賴的。

  • 留一法LOO-CV

    在極端情況下。假設資料集中有m個樣本,我們就把資料集分為m份,稱為留一法。(Leave-One-Out Cross Validation),這樣做的話,完全不受随機的影響,最接近模型真正的性能名額,缺點就是計算量巨大。

偏差方差權衡(Bias Variance Trade off),當我們的模型表現不佳時,通常是出現兩種問題,一種是 高偏差 問題,另一種是 高方差 問題。識别它們有助于選擇正确的優化方式,是以我們先來看下 偏差 與 方差 的意義。
  • 偏差: 描述模型輸出結果的期望與樣本真實結果的差距。
  • 方差: 描述模型對于給定值的輸出穩定性。 方差越大模型的泛華能力越弱。

​ 就像打靶一樣,偏差描述了我們的射擊總體是否偏離了我們的目标,而方差描述了射擊準不準。左一是方差跟偏差都很小,都比較靠近中心且集中,右一分散在中心附近,但比較散,是以方差較大。這樣結合下面這兩幅圖就可以大概了解,偏差描述的是描述模型輸出結果的期望與樣本真實結果的差距。而方差則是對于輸出結果是否集中,描述模型對于給定值的輸出穩定性。

模型誤差 = 偏差 + 方差 + 不可避免的誤差

  • 導緻偏差大的原因:對問題本身的假設不正确!如非線性資料使用線性回歸。或者特征對應标記高度不相關也會導緻高偏差,不過這是對應着特征選擇,跟算法沒有關系,對于算法而言基本屬于欠拟合問題underfitting。
  • 導緻方差大的原因:資料的一點點擾動都會極大地影響模型。通常原因就是使用的模型太複雜,如高階多項式回歸。這就是所說的過拟合(overfitting)
  • 總結:有些算法天生就是高方差的算法,如KNN,非參數學習的算法通常都是高方差的,因為不對資料進行任何假設。還有一些算法天生就是高偏差的,如線性回歸。參數學習通常都是高偏差算法,因為對資料具有極強的假設。大多數算法具有相應的算法可以調整偏差和方差,如KNN中的k,如線性回歸中使用多項式回歸中的degree,偏差和方差通常是沖突的,降低偏差,會提高方差,降低方差,會提高偏差,是以在實際應用中需要進行權衡。機器學習的主要挑戰,在于方差。這句話隻針對算法,并不針對實際問題。因為大多數機器學習需要解決過拟合問題。
  • 解決手段:
    • 降低模型複雜度
    • 減少資料次元;降噪
    • 增加樣本數量
    • 使用驗證集
    • 模型正則化

​ 模型正則化(Regularization):限制參數的大小。常常用來解決過拟合問題。接下來具體看一下:

先看一下多項式回歸過拟合的情況:

from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
import numpy as np
import matplotlib.pyplot as plt

def PolynomiaRegression(degree):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('lin_reg', LinearRegression()),
    ])

np.random.seed(666)
x = np.random.uniform(-3.0, 3.0, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x**2 + x + 2 + np.random.normal(0, 1, size=100)

poly100_reg = PolynomiaRegression(degree=100)
poly100_reg.fit(X, y)
y100_predict = poly100_reg.predict(X)
mean_squared_error(y, y100_predict)
# 0.687293250556113
x_plot = np.linspace(-3, 3, 100).reshape(100, 1)
y_plot = poly100_reg.predict(x_plot)

plt.scatter(x, y)
plt.plot(x_plot[:,0], y_plot, color='r')
plt.axis([-3, 3, 0, 10])
plt.show()
           
lin_reg.coef_
           
array([ 1.21093453e+12,  1.19203091e+01,  1.78867645e+02, -2.95982349e+02,
       -1.79531458e+04, -1.54155027e+04,  8.34383276e+05,  8.19774042e+05,
       -2.23627851e+07, -1.44771550e+07,  3.87211418e+08,  1.13421075e+08,
       -4.61600312e+09, -1.25081501e+08,  3.93150405e+10, -5.47576783e+09,
       -2.44176251e+11,  5.46288687e+10,  1.11421043e+12, -2.76406464e+11,
       -3.71329259e+12,  8.55454910e+11,  8.80960804e+12, -1.60748867e+12,
       -1.39204160e+13,  1.49444708e+12,  1.19236879e+13,  2.47473079e+11,
        4.42409192e+11, -1.64280931e+12, -1.05153597e+13, -1.80898849e+11,
        3.00205050e+12,  2.75573418e+12,  8.74124346e+12, -1.36695399e+12,
       -1.22671920e+12, -7.00432918e+11, -8.24895441e+12, -8.66296096e+11,
       -2.75689092e+12,  1.39625207e+12,  6.26145077e+12, -3.47996080e+11,
        6.29123725e+12,  1.33768276e+12, -6.11902468e+11,  2.92339251e+11,
       -6.59758587e+12, -1.85663192e+12, -4.13408727e+12, -9.72012430e+11,
       -3.99030817e+11, -7.53702123e+11,  5.49214630e+12,  2.18518119e+12,
        5.24341931e+12,  7.50251523e+11,  5.50252585e+11,  1.70649474e+12,
       -2.26789998e+12, -1.84570078e+11, -5.47302714e+12, -2.86219945e+12,
       -3.88076411e+12, -1.19593780e+12,  1.16315909e+12, -1.41082803e+12,
        3.56349186e+12,  7.12308678e+11,  4.76397106e+12,  2.60002465e+12,
        1.84222952e+12,  3.06319895e+12, -1.33316498e+12,  6.18544545e+11,
       -2.64567691e+12, -1.01424838e+12, -4.76743525e+12, -3.59230293e+12,
       -1.68055178e+12, -3.57480827e+12,  2.06629318e+12, -6.07564696e+11,
        3.40446395e+12,  3.42181387e+12,  3.31399498e+12,  4.92290870e+12,
        3.79985951e+11,  1.34189037e+12, -3.34878352e+12, -2.07865615e+12,
       -3.24634078e+12, -5.48903768e+12,  5.87242630e+11, -2.27318874e+12,
        2.60023097e+12,  8.21820883e+12,  4.79532121e+10, -3.11436610e+12,
       -6.27736909e+11])
           

通過檢視多項式回歸的系數可以發現,有些系數能差13個數量級,其實這就是過拟合了!而模型正則化就是為了解決這個問題。先來回顧一下多項式回歸的目标。

  • 加入正則項之前

    目标:使\sum_{i=1}m(y{(i)} - \theta_{0} - \theta_{1}X_{1}^{(i)} - \theta_{2}X_{2}^{(i)} - \dots - \theta_{n}X_{n}{(i)})2盡可能的小,

    目标:使J(\theta) = MSE(y, \haty, \theta)盡可能地小

  • 加入正則項之後

    目标:J(\theta) = MSE(y, \haty, \theta) + \alpha \frac{1}{2} \sum_{i=1}^n \theta_{i}^2盡可能小

    通過加入的正則項來控制系數不要太大,進而使曲線不要那麼陡峭,變化的那麼劇烈。在這裡有幾個細節需要注意。

    • 第一點:\theta從1開始,隻包含系數不包括截距,這是因為截距隻決定曲線的高低,并不會影響曲線的陡峭和緩和。
    • 第2點:就是這個\frac{1}{2},是為了求導之後能夠将2消去,為了友善計算。不過其實這個有沒有都是可以的,因為在正則化前有一個系數,我們可以把這個\frac{1}{2}可以考慮到\alpha中去。
    • 第3點:系數\alpha,它表示正則化項在整個損失函數中所占的比例。極端一下,\alpha=0時,相當于模型沒有加入正則化,但如果\alpha = 正無窮,此時其實主要的優化任務就變成了需要所有的\theta都盡可能的小,最優的情況就是全為0。至于\alpha的取值就需要嘗試了。

測試用例:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)
x = np.random.uniform(-3.0, 3.0, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x + 3 + np.random.normal(0, 1, size=100)

plt.scatter(x, y)
plt.show()
           
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

def PolynomiaRegression(degree):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('lin_reg', LinearRegression()),
    ])


np.random.seed(666)
x_train, x_test, y_train, y_test = train_test_split(X, y)

poly_reg = PolynomiaRegression(degree=20)
poly_reg.fit(x_train, y_train)

y_poly_predict = poly_reg.predict(x_test)
mean_squared_error(y_test, y_poly_predict)
# 167.9401085999025
           
import matplotlib.pyplot as plt
x_plot = np.linspace(-3, 3, 100).reshape(100, 1)
y_plot = poly_reg.predict(x_plot)

plt.scatter(x, y)
plt.plot(x_plot[:,0], y_plot, color='r')
plt.axis([-3, 3, 0, 6])
plt.show()
           

把畫圖這些操作封裝成一個函數,友善後面調用:

def plot_model(model):
    x_plot = np.linspace(-3, 3, 100).reshape(100, 1)
    y_plot = model.predict(x_plot)

    plt.scatter(x, y)
    plt.plot(x_plot[:,0], y_plot, color='r')
    plt.axis([-3, 3, 0, 6])
    plt.show()
           

使用嶺回歸:

from sklearn.linear_model import Ridge

def RidgeRegression(degree, alpha):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('lin_reg', Ridge(alpha=alpha)),
    ])

ridege1_reg = RidgeRegression(20, alpha=0.0001)
ridege1_reg.fit(x_train, y_train)

y1_predict = ridege1_reg.predict(x_test)
mean_squared_error(y_test, y1_predict)
# 1.3233492754136291
# 跟之前的136.相比小了很多
plot_model(ridege1_reg)	
           

調整\alpha

ridege2_reg = RidgeRegression(20, alpha=1)
ridege2_reg.fit(x_train, y_train)

y2_predict = ridege2_reg.predict(x_test)
mean_squared_error(y_test, y2_predict)
# 1.1888759304218461
plot_model(ridege2_reg)	
           
ridege3_reg = RidgeRegression(20, alpha=100)
ridege3_reg.fit(x_train, y_train)

y3_predict = ridege3_reg.predict(x_test)
mean_squared_error(y_test, y3_predict)
# 1.3196456113086197
# 此時相比alpha=1時均方誤差上升了,說明可能正則過頭了
plot_model(ridege3_reg)
           
ridege4_reg = RidgeRegression(20, alpha=1000000)
ridege4_reg.fit(x_train, y_train)

y4_predict = ridege4_reg.predict(x_test)
mean_squared_error(y_test, y4_predict)
# 1.8404103153255003
plot_model(ridege4_reg)
           

​ 這也跟之前分析,如果alpha=正無窮時,為了使損失函數最小,就需要所有的系數的平方和最小,即\theta都趨于0。通過上面幾種alpha的取值可以看出我們可以在1-100進行更加細緻的搜尋,找到最合适的一條相對比較平滑的曲線去拟合。這就是L2正則。

目标:J(\theta) = MSE(y, \haty, \theta) + \alpha \frac{1}{2} \sum_{i=1}^n \mid \theta_{i}盡可能小

LASSO: Least Absolute Shrinkage and Selection Operator Regression

Shrinkage:收縮,縮小,收縮量。特征縮減。重點在于Selection Operator

使用lasso回歸:

from sklearn.linear_model import Lasso

def LassoRegression(degree, alpha):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('lin_reg', Lasso(alpha=alpha)),
    ])

lasso1_reg = LassoRegression(20, 0.01) 
#這裡相比Ridge的alpha小了很多,這是因為在Ridge中是平方項
lasso1_reg.fit(x_train, y_train)

y1_predict = lasso1_reg.predict(x_test)
mean_squared_error(y_test, y1_predict)
# 1.149608084325997
plot_model(lasso1_reg)
           
lasso2_reg = LassoRegression(20, 0.1) 
lasso2_reg.fit(x_train, y_train)

y2_predict = lasso2_reg.predict(x_test)
mean_squared_error(y_test, y2_predict)
# 1.1213911351818648
plot_model(lasso2_reg)
           
lasso3_reg = LassoRegression(20, 1) 
lasso3_reg.fit(x_train, y_train)

y3_predict = lasso3_reg.predict(x_test)
mean_squared_error(y_test, y3_predict)
# 1.8408939659515595
plot_model(lasso3_reg)
           

  • Ridge:目标:J(\theta) = MSE(y, \haty, \theta) + \alpha \frac{1}{2} \sum_{i=1}^n \theta_{i}^2盡可能小
  • Lasso:目标:J(\theta) = MSE(y, \haty, \theta) + \alpha \frac{1}{2} \sum_{i=1}^n \mid \theta_{i}盡可能小

通過這兩幅圖進行對比發現,LASSO拟合的模型更傾向于是一條直線,而Ridge拟合的模型更趨向與一條曲線。這是因為兩個正則的本質不同,Ridge是趨向于使所有\theta的加和盡可能的小,而Lasso則是趨向于使得一部分\theta的值變為0,是以可作為特征選擇用,這也是為什麼叫Selection Operation的原因。

下面就對上面這兩句話嘗試着進行一下解釋:

  1. Ridge Regression:J(\theta) = MSE(y, \haty, \theta) + \alpha \frac{1}{2} \sum_{i=1}^n \theta_{i}^2

    當alpha趨近于無窮時,J(\theta) = \alpha \frac{1}{2} \sum_{i=1}^n \theta_{i}^2

    \bigtriangledown = \alpha \begin {bmatrix}

    \theta_{1} \\

    \theta_{2} \\

    \dots \\

    \theta_{n} \\

    \end {matrix}

假設從上圖一點開始,導數\bigtriangle中的\theta都是有值的,順着梯度方向下降。Ridge是趨向于使所有\theta的加和盡可能的小,而不是像lasso一樣直接為0。

  1. LASSO Regression:J(\theta) = MSE(y, \haty, \theta) + \alpha \frac{1}{2} \sum_{i=1}^n \mid \theta_{i}

    當alpha趨近于無窮時,J(\theta) = \alpha \frac{1}{2} \sum_{i=1}^n \mid \theta_{i}

    它其實是不可導的,不過也可以簡單地使用一個分類函數作為它的導數,

    \bigtrianlgedown = \alpha \begin {bmatrix}

    sign(\theta_{1}) \\

    sign(\theta_{2}) \\

    sign(\theta_{n}) \\

其中sign(x) = \begin {cases}

1, \quad x>0 \\

0,\quad x=0 \\

-1, \quad x<0 \\

\end {cases}

是以,當如果從上圖的一點開始進行梯度下降的話,就不能想Ridge一樣曲線地去逼近0,而是隻能使用這些非正常則的方式去逼近零點。在這種路徑的梯度下降中,就會達到某些軸的零點,Lasso則是趨向于使得一部分\theta的值變為0。是以可以作為特征選擇用。不過也正是因為這樣的特性,使得Lasso這種方法有可能會錯誤将原來有用的特征的系數變為0,是以相對Ridge來說,準确率還是Ridge相對較好一些,但是當特征特别大時候,此時使用Lasso也能将模型的特征變少的作用。

  • Rigde:\frac{1}{2}\sum_{i=1}^n \theta_{i}^2 \qquad \qquad Lasso: \sum_{i=1}^n \mid \theta_{i}
  • MSE: \frac{1}{n}\sum_{i=1}^n(y_{i} - \hat y_{i})^2 \qquad MAE: \frac{1}{n} \sum_{i=1}^n \mid (y_{i} - \hat y_{i})
  • 歐拉距離:\sqrt{\sum_{i=1}^n (x_{i}^{(1)} - x_{i}^{(2)} ^2} 曼哈頓距離:\sum_{i=1}^n \mid {(x_{i}^{(1)} - x_{i}^{(2)}

這三者背後的數學思想是非常相近的,隻是用在不同的背景下具有不同的效果。對比這三者之後,我們在進行一下拓展:

明可夫斯基距離:(Minkowski Distance) (\sum_{i=1}^n \mid {X_{i}^{(a)} - X_{i}{(b)}}p)^{\frac{1}{p}}

L1正則、L2正則:

\parallel {X_{p}} = (\sum_{i=1}^n \mid{X_{i}}p){\frac{1}{p}}這就是傳說中的p範數。

是以當p=1時,就是L1範數,對應着Lasso的L1正則項、MAE、曼哈頓距離

當p=2時就是L2範數,對應着Ridge的L2的正則項、MSE、歐拉距離

其實對應着還有L0正則:J(\theta) = MSE(y, \hat{y}; \theta) + min{number-of-non-zero-\theta}

就是讓\theta個數越少越好,進而對損失函數進行修正,不過很少使用,這是因為L0正則的優化是一個NP難問題,不能使用梯度下降法或者直接求出一個數學公式來直接找出最優解,這是一個離散最優化的問題,需要窮舉所有的\theta為0的組合,進而選出最優的。

範數:具有長度概念的函數,其為向量空間内的所有向量賦予非零的正常度或大小。它是實數的絕對值、複數的模、三維幾何空間R[^3]中向量長度的推廣。

範數具有三個性質:非負性、齊次性、三角不等式

NP問題:NP完全問題(NP-C問題),是世界七大數學難題之一。 NP的英文全稱是Non-deterministic Polynomial的問題,即多項式複雜程度的非确定性問題。簡單的寫法是 NP=P?,問題就在這個問号上,到底是NP等于P,還是NP不等于P。

J(\theta) = MSE(y, \hat{y}; \theta) + r \alpha \sum_{i=1}^n \mid{\theta_{i}} + \frac{1-r}{2} \alpha \sum_{i=1}^n ({\theta_{i})^2

這是一個将嶺回歸和Lasso回歸結合的一種變形。結合兩者的優勢,這就是彈性網(Elastic Net)。

其實這種思想跟之前提到的批量梯度下降法和随機梯度下降法的結合的小批量梯度下降法(mini-batch Gradient Descent)。

本節學習的主要内容就是如何提高模型的泛化能力,就是我們不僅關注模型在訓練集上的表現,還更加要關注模型對于未知的新的資料的預測的準确性,當然方法遠不止這些,後續繼續學習。

本次推薦:

好用的線上工具箱

毒雞湯:哪有什麼選擇恐懼症,還不是因為窮;哪有什麼優柔寡斷,還不是因為慫。

繼續加油!!!

堅持到無能為力,拼搏到感動自己!

繼續閱讀