迴歸or分類?線性or邏輯?一文掌握模型的不同之處
全文共7366字,預計學習時長30分鐘或更長
圖片來源:https://techdifferences.com/wp-content/uploads/2018/01/Untitled-2.jpg
迴歸 VS 分類
為確定使用迴歸還是分類模型,首先要問的問題是?
目標變數是一個量,一個二進位制分類的概率,還是一個標籤?
如果目標變數是一個量或概率,須應用迴歸模型。這意味著如果要推測量值,如高度、收入、價格和分數,使用的模型應該輸出一個連續數字。或者,如果目標變數是某一項二進位制標籤的概率(判斷好壞的概率除外),那麼也應該選擇迴歸模型,只是具體使用的模型略有不同。我們用均方差(MSE或其它誤差)和均方根誤差(RMSE或標準差)來評估此類模型,以量化模型中的誤差。
如果目標變數是一個標籤,則應該使用分類模型。分類有助於預測觀察標籤(好中差等標籤除外)。棘手之處在於判斷目標變數是否為標籤。比方說,如果目標變數是一個順序變數,表示1至5之間的不同等級,那麼它們即為標籤,但其同時具有數學意義。
這意味著資料的平均值和偏差仍有意義,但若要進行推測,應用分類模型是更為明智的選擇。我們通過F分數或精確度來評估這些模型,而非其誤差或標準差。下面的譜系可以幫助我們理解有多少觀察被正確標註,而通過混淆矩陣,這些觀察得到視覺化呈現。矩陣中,觀察被分為真陽性/真陰性/假陽性/假陰性。
混淆矩陣
執行模型做出預測之前,理解目標變數的特徵尤為重要。若應該使用分類模型卻誤用了迴歸模型,會得出一堆連續的預測,而非離散標籤。而因為大多數(或全部)預測並非你想得出的1或0值,會導致推測出一個較低的F分數(也可能為0)。如果使用得出概率的邏輯模型,有一個方法是設定一個邊界值。比如,假定任何大於0.9的值即為1,任何小於0.9的值為0,你仍然會得出一個F分數和混淆矩陣。但使用合適的模型通常可以避免這項額外的步驟。
一旦決定了要使用的方法,接下來就要選擇模型進行預測。
視覺化呈現:迴歸模型 vs. 分類模型
迴歸模型
迴歸模型中使用最普遍的是線性迴歸和邏輯迴歸。
基本的線性迴歸模型遵循這個眾所周知的等式y=mx+b,但通常實際應用中形式略有不同:
y=β₀+β₁x₁+…+βᵢxᵢ
該等式中,β₀代表縱軸截距,即全部解釋變數為0值時的y值。β₁到βᵢ是x₁到xᵢ變數的相關係數,若其它變數不變,x₁到xᵢ中有一項增加或減少,則y值隨之增減。比如,在y=1+2x₁+3x₂這個等式中,若x₁由0變為1,x₂不變,則y至由1變為3。
邏輯模型遵循的等式略有不同:
y= 1 / (1+e^-(β₀+β₁x₁+…+βᵢxᵢ))
其中y值在0到1之間。因此,邏輯模型通常被用來分析二進位制目標變數。此種情況下,目標變數值為0或1,或者目標變數是二進位制變數的概率。正如前面提到,此等式防止出現非邏輯預測,得出的概率低於0或高於1。
視覺化呈現:線性迴歸 vs. 邏輯迴歸
兩種標準模型均可被調整,以更好擬合數據。主要方法是包含懲罰引數。線性和邏輯迴歸模型對應的等式均包含全部輸入的變數,而這很可能會導致過度擬合。如果資料擬合過度,模型得出預測的可靠性會降低,並侷限於訓練樣本。為了避免此種情況的出現,可以進行特徵選擇,挑選出相對重要的特徵;或在模型中引入懲罰引數。
視覺化呈現:低度擬合與過度擬合
引入L2懲罰項會產生嶺迴歸模型。在此模型中,相對無關變數的係數較少,以限制其影響,但仍包含所有輸入的變數。如果想無視變數的相關性並把每一個變數包含進模型中,以上操作十分有效。但大多數情況下,你會傾向於儘可能簡化的模型。
引入L1懲罰項會產生拉索迴歸模型。拉索模型的機制與嶺迴歸模型相似,但會把不相關變數的係數縮減至0,完全消除其影響。而拉索模型的不足之處在於觀察數(n)比變數數(k)多,其最多可包含n個變數。同時,拉索模型對相關變數的處理有侷限,只能隨機保留其中一個變數。
彈性網路迴歸模型可以解決以上所有問題,它可以結合兩個懲罰項,更好地處理多維資料和多重共線性問題。因此,彈性網路模型通常會比拉索模型更精確,但這取決於其所選的L1懲罰項比例,即其超引數之一。
最後還有一個問題,即嚴格意義上目標變數可能不是解釋變數的線性功能。對此,有兩個解決方法:更高層級的迴歸模型或隨機森林迴歸模型。
比方說,在最初的資料探測階段,你發現要預測收入時,年齡與收入的關聯更偏向於二次關係,而非線性關係。在這種情況下,會對原來的線性等式中引入一個二階變數。等式就變成了這種形式:
y=β₀+β₁x+β₂x²
隨後你再次應用模型。你仍然可以應用線性迴歸模型或更高層級的模型。
一個常見的誤解是:線性迴歸模型僅能產生線性功能。但其實,線性迴歸模型中的“線性”是指相關係數之間的關係,而非變數本身。因此,在模型中包含更高的層級或互動有助於解釋變數之間的關係。但要注意的是,如果這樣做,必須保證最終等式中包含低層級和主要影響變數,無論它們是否重要。避免出現這樣的等式:
y=β+β₂x² 或y=β₀+β₁x₁*x₂
我們也可以使用隨機森林迴歸模型(如下圖所示),後文將會更詳細地介紹其替代模型——應用更廣泛的隨機森林分類。隨機森林迴歸的機制與邏輯迴歸相似,二者均可得出二進位制標籤的概率。簡單來說,隨機森林迴歸會產生大量決策樹。這些決策樹都會得出預測,而最終預測結果為最普遍的預測或平均預測。
泰坦尼克事件的隨機森林分類
現在你可能會想,難道不能用這些模型預測概率目標變數嗎?如果訓練組的y值在0到1之間,那麼模型的預測y值也在0到1之間,是吧?是,也不是。
大多數情況下,模型預測的y值都在0到1之間。但如果模型為線性,則低於0或高於1的概率值是非邏輯迴歸的。你可以在模型建構中付出110%的努力,但一個觀察被分為某一類的概率不可能達到110%。
而且,線上性模型中,診斷患病的概率分別為10%和15%的人群之間的不同就相當於診斷患病概率為95%和1%的人群之間的不同。顯然,如果某人100%患病,那麼這一點線上性模型中就不會體現,因為此資料對於低於50%的概率而言影響極小。
分類模型
如果分析是為了構建模型以預測觀察標籤,那麼就得使用分類模型。最簡單的分類模型就是邏輯模型。然而,通過建立假目標變數並對各變數應用邏輯模型,我們能夠訓練非二進位制目標變數的邏輯模型。你也可以對此邏輯模型匯入L1和L2懲罰項,從而執行拉索和嶺邏輯模型。
隨機森林分類則更有助於推測。和隨機森林迴歸一樣,隨機森林分類包含僅在特定情況下有影響的特徵。隨機森林分類的機制同上,其採取決策樹的概念以建立一個隨機森林,並隨機選擇變數,最終基於森林得出預測。在應用模型的編碼中,可以看到許多超引數,比如決策樹的數量、每一片樹葉上的最小觀察數、最大分裂數、決策樹的最大深度等。這些超引數有助於構建一個更為精準的模型,但隨機森林仍有可能過度擬合。如果決策樹太大,那麼它們很可能過於具體,因此無法應用於測試組。
視覺化呈現:隨機森林分類
最後,建立神經網路也有助於預測觀察標籤。這是最為複雜的方法,但相比其他方法的確有某些優勢。其主要優勢在於可促成無監督學習。這意味著無需先前標記的訓練資料,該演算法即可根據檢測到的相似點來聚合組別。儘管建立起來很複雜,神經網路在預測標籤方面更為精確,這一點對於利害關係重大的預測十分重要,如疾病診斷和詐騙檢測。
本質上,神經網路演算法的工作機制是引入一組資料,找到其中的模型和趨勢,然後做出預測(受監督)或聚合組別(無監督)。通過重複此流程並引入更大的訓練組,神經網路演算法愈加精確。但要注意避免建立過多網路層級導致訓練組過度擬合。
視覺化呈現:神經網路
總結
選擇預測模型時,首要考慮的問題是目標變數的特徵。目標變數是持續的還是離散的?變數是量還是標籤?變數是概率還是類別?變數與所有解釋變數存線上性相關性嗎?需要在預測中包含所有的變數嗎?思考這些問題的答案有助於你挑選出最佳預測模型。
原始碼及執行對比:
Regression
In [0]: import sklearn from sklearn.linear_model import ElasticNet, Lasso, Ridge, LogisticRegression, LinearRegression from sklearn.model_selection import train_test_sp lit from sklearn.metrics import mean_squared_error from sklearn.ensemble import RandomForestRegr essor import pandas as pd import matplotlib from matplotlib import pyplot def warn(*args, **kwargs): passimport warnings warnings.warn = warn
In[0] from google.colab import file suploaded = files.upload()
In [0]: data = pd.read_csv("avocado.csv") data = data.drop(['Unnamed: 0','Date', 'region','Total Volume','Total Bags'], axis = 1) data = pd.get_dummies(data, drop_first=True) y = data['AveragePrice'] X = data.drop('AveragePrice', axis=1) X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=.1)
In [250]: lm = LinearRegression() lm_fit = lm.fit(X_train, y_train)lm_predict = lm_fit.predict(X_test) #lr = LogisticRegression() #lr_fit = lr.fit(X_train,y_train) #lr_predict = lr_fit.predict(X_test) ## will not work because the range of y is 0 to 3.25, not 0 to 1 ridge = Ridge() ridge_fit = ridge.fit(X_train,y_train) r_predict = ridge_fit.predict(X_test) lasso = Lasso(max_iter=1000) lasso_fit = lasso.fit(X_train,y_train) l_predict = lasso_fit.predict(X_test) ENet = ElasticNet(l1_ratio=.01) ENet_fit = ENet.fit(X_train,y_train) en_predict = ENet_fit.predict(X_test) ## there are no higher order variables in this dataset, but for the sake of exemplifying the procedure, ## pretend there is a quadratic relationship between the number of 4225 avocados and the price data1 = data.head(500) data1['4225_sq'] = 0 for i in range(len(data1['4225'])): data1['4225_sq'][i] = (data1['4225'][i])**2 y2 = data1['AveragePrice'] X2 = data1.drop('AveragePrice', axis=1) X_train2, X_test2, y_train2, y_test2 = train_test_split(X2,y2, test_size=.1) lm_fit = lm.fit(X_train2, y_train2) ho_predict = lm_fit.predict(X_test2) rand = RandomForestRegressor() rand_fit = rand.fit(X_train,y_train) rf_predict = rand_fit.predict(X_test) /usr/local/lib/python3.6/dist- packages/sklearn/ensemble/forest.py:245: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22. "10 in version 0.20 to 100 in 0.22.", FutureWarning)
In [252]: print('Linear Model MSE:' , mean_squared_error(y_test,lm_predict)) #mean_squared_error(y_test,lr_predict) print('Ridge Model MSE:' , mean_squared_error(y_test,r_predict)) print('Lasso Model MSE:' , mean_squared_error(y_test,l_predict)) print('Elastic Net Model MSE:', mean_squared_error(y_test,en_predict)) print('Higher Order Model MSE:' , mean_squared_error(y_test2,ho_predict)) print('Random Forest MSE:' , mean_squared_error(y_test,rf_predict))
Linear Model MSE: 0.09792038897928204 Ridge Model MSE: 0.09791772364668704 Lasso Model MSE: 0.14654262570004578 Elastic Net Model MSE: 0.12919487097231586 Higher Order Model MSE: 0.015512612920132457 Random Forest MSE: 0.034497292054794515
Classification
In [0]:import sklearn from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.neural_network import MLPClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import f1_score, confusion_matriximport pandas as pd
In [0]: from google.colab import files uploaded = files.upload()
In [0]:data = pd.read_csv("train.csv") data = data.drop(['Name','Ticket','Cabin'], axis=1) data = pd.get_dummies(data) data = data.fillna(0) y = data['Survived'] X = data.drop('Survived', axis=1) X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=.1)
In [236]: data.head()
Out[236]:
In [0]: lr = LogisticRegression() lr_fit = lr.fit(X_train,y_train) lasso2 = LogisticRegression(penalty='l1') lasso2_fit = lasso2.fit(X_train,y_train) ridge2 = LogisticRegression(penalty='l2') ridge2_fit = ridge2.fit(X_train,y_train) rand_for = RandomForestClassifier(n_estimators = 500, random_state = 40) rand_for_fit = rand_for.fit(X_train,y_train) clf = MLPClassifier(activation='logistic', solver='lbfgs',learning_rate='adaptive', alpha=.0005)clf_fit = clf.fit(X_train, y_train)
In [273]: print('Logistic F Score:',lr_fit.score(X_test, y_test)) print('LASSO F Score:',lasso2_fit.score(X_test, y_test)) print('Ridge F Score:',ridge2_fit.score(X_test, y_test)) print('Random Forest Classifier F Score:',rand_for_fit.score(X_test, y_test)) print('Neural Net F Score:',clf_fit.score(X_test, y_test))
Logistic F Score: 0.8555555555555555 LASSO F Score: 0.8555555555555555 Ridge F Score: 0.8555555555555555 Random Forest Classifier F Score: 0.8777777777777778 Neural Net F Score: 0.7333333333333333
留言 點贊 關注
我們一起分享AI學習與發展的乾貨
歡迎關注全平臺AI垂類自媒體 “讀芯術”
(新增小編微信:dxsxbb,加入讀者圈,一起討論最新鮮的人工