模型泛化


模型泛化


泛化即是,機器學習模型學習到的概念在它處於學習的過程中時模型沒有遇見過的樣本時候的表現。

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

一、交叉驗證

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

mark

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

  1. 驗證集。

mark

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

mark

​ 我們將訓練數據隨機分為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),當我們的模型表現不佳時,通常是出現兩種問題,一種是 高偏差 問題,另一種是 高方差 問題。識別它們有助於選擇正確的優化方式,所以我們先來看下 偏差方差 的意義。

  • 偏差: 描述模型輸出結果的期望與樣本真實結果的差距。
  • 方差: 描述模型對於給定值的輸出穩定性。 方差越大模型的泛華能力越弱。

mark

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

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

  • 導致偏差大的原因:對問題本身的假設不正確!如非線性數據使用線性回歸。或者特征對應標記高度不相關也會導致高偏差,不過這是對應着特征選擇,跟算法沒有關系,對於算法而言基本屬於欠擬合問題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()

1565518497608

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的取值就需要嘗試了。

1、嶺回歸(Ridege Regression)

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

測試用例:

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()

mark

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()

mark

把畫圖這些操作封裝成一個函數,方便后面調用:

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)	

mark

調整\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)	

mark

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)

mark

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)

mark

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

2、LASSO Regularization

目標: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)

mark

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)

mark

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)

mark

3、解釋Ridge和LASSO

  • 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}盡可能小

    mark

通過這兩幅圖進行對比發現,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}

    mark

假設從上圖一點開始,導數\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}) \\

    \dots \\

    sign(\theta_{n}) \\

    \end {matrix}

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

1, \quad x>0 \\

0,\quad x=0 \\

-1, \quad x<0 \\

\end {cases}

mark

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

4、比較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。

5、彈性網

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)。

我是尾巴

本節學習的主要內容就是如何提高模型的泛化能力,就是我們不僅關注模型在訓練集上的表現,還更加要關注模型對於未知的新的數據的預測的准確性,當然方法遠不止這些,后續繼續學習。

本次推薦:

好用的在線工具箱

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

mark

繼續加油!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM