返回文章列表

線性模型可解釋性分析與最佳化

本文探討線性模型的可解釋性分析,涵蓋相關係數矩陣、統計顯著性檢驗、虛擬變數建立、模型建立與評估、多重共線性檢測與處理、模型最佳化、係數分析、調整後的 R 平方值計算、p 值計算以及錯誤指標計算等關鍵步驟。透過 Python 程式碼和統計方法,演示如何提升線性模型的可靠性和解讀能力,並提供實際操作案例與程式碼說

機器學習 資料分析

線性迴歸模型在機器學習中應用廣泛,其可解釋性對於理解預測結果至關重要。本篇著重於提升線性模型的可靠性和解讀能力,涵蓋資料預處理、模型訓練、多重共線性處理、模型評估以及模型解釋等方面。首先,透過相關係數矩陣分析變數間的線性關係,並進行統計顯著性檢驗。接著,將類別變數轉換為虛擬變數,避免多重共線性問題。然後,使用訓練集和測試集評估模型效能,並透過 VIF 檢測和處理多重共線性。最後,分析模型係數、計算調整後的 R 平方值和 p 值,深入理解各個特徵對目標變數的影響,並使用 MAPE 和 MSSE 等指標評估模型的預測誤差。

線性模型的可解釋性分析

在進行線性迴歸分析之前,瞭解變數之間的相關性是非常重要的。相關係數可以用來衡量兩個變數之間的線性關係強度。

相關係數矩陣的建立與分析

首先,我們需要計算資料集中各個數值變數之間的相關係數。相關係數的取值範圍在-1到1之間,其中1表示完全正相關,-1表示完全負相關,0表示無相關性。

corrl = df[['Price','Age','Odometer','mileage','engineCC','powerBhp']].corr()
corrl.style.background_gradient(cmap='coolwarm')

內容解密:

  1. df[['Price','Age','Odometer','mileage','engineCC','powerBhp']]:選取資料集中與價格相關的數值變數。
  2. .corr():計算這些變數之間的相關係數矩陣。
  3. .style.background_gradient(cmap='coolwarm'):使用漸層色彩來視覺化相關係數矩陣,正相關以暖色表示,負相關以冷色表示。

相關係數的統計顯著性檢驗

為了驗證相關係數是否具有統計顯著性,我們可以使用統計檢驗方法。

np.where((df[['Price','Age','Odometer','mileage','engineCC','powerBhp']]).corr()>0.6,'Yes','No')

內容解密:

  1. (df[['Price','Age','Odometer','mileage','engineCC','powerBhp']]).corr():計算相關係數矩陣。
  2. np.where(..., >0.6, 'Yes', 'No'):找出相關係數大於0.6的變數對,並標記為’Yes’,否則標記為’No’。

虛擬變數的建立

由於資料集中存在類別變數(Location、FuelType、Transmission、OwnerType),我們需要將這些變數轉換為虛擬變數,以便進行線性迴歸分析。

Location_dummy = pd.get_dummies(df.Location, prefix='Location', drop_first=True)
FuelType_dummy = pd.get_dummies(df.FuelType, prefix='FuelType', drop_first=True)
Transmission_dummy = pd.get_dummies(df.Transmission, prefix='Transmission', drop_first=True)
OwnerType_dummy = pd.get_dummies(df.OwnerType, prefix='OwnerType', drop_first=True)

combine_all_dummy = pd.concat([df, Location_dummy, FuelType_dummy, Transmission_dummy, OwnerType_dummy], axis=1)
clean_df = combine_all_dummy.drop(columns=['Make', 'Location', 'FuelType', 'Transmission', 'OwnerType', 'Mileage', 'EngineCC', 'PowerBhp'])

內容解密:

  1. pd.get_dummies():將類別變數轉換為虛擬變數。
  2. prefix引數:指定虛擬變數的字首。
  3. drop_first=True:丟棄第一個類別,以避免多重共線性。
  4. pd.concat():將原始資料集與虛擬變數合併。
  5. drop(columns=...):丟棄原始的類別變數和不需要的變數。

線性迴歸模型的建立與評估

建立線性迴歸模型之前,需要將資料集分割為訓練集和測試集。

data_train, data_test = train_test_split(clean_df, test_size=0.25, random_state=1234)
XTrain = np.array(data_train.iloc[:, 0:(clean_df.shape[1]-1)])
YTrain = np.array(data_train['Price'])
XTest = np.array(data_test.iloc[:, 0:(clean_df.shape[1]-1)])
YTest = np.array(data_test['Price'])

reg = linear_model.LinearRegression()
reg.fit(XTrain, YTrain)
print('Coefficients: \n', np.round(reg.coef_, 4))
print('Intercept: \n', np.round(reg.intercept_, 0))

內容解密:

  1. train_test_split():將資料集分割為訓練集和測試集。
  2. linear_model.LinearRegression():建立線性迴歸模型。
  3. reg.fit():訓練模型。
  4. reg.coef_:取得模型的係數。
  5. reg.intercept_:取得模型的截距。

模型評估與可解釋性分析

模型的評估結果顯示,訓練準確度和測試準確度均為100%,但模型的係數均為0,截距為1,表明模型存在問題。這時就需要使用可解釋性AI技術來瞭解模型出了什麼問題。

reg.score(XTrain, YTrain)
reg.score(XTest, YTest)

內容解密:

  1. reg.score():計算模型的R平方值。

使用統計API進行驗證

為了驗證結果,我們可以使用統計API來進行驗證。

import statsmodels.api as sm
y = np.array(clean_df['Price'])
xx = np.array(clean_df.drop('Price', axis=1))
sm.OLS(y, xx).fit().summary()

內容解密:

  1. sm.OLS():建立普通最小二乘法模型。
  2. .fit():訓練模型。
  3. .summary():輸出模型的摘要資訊。

線性模型的可解釋性分析

線性迴歸模型是機器學習中最基礎也是最重要的模型之一,其可解釋性對於理解模型的預測結果至關重要。在本章中,我們將探討線性模型的可解釋性,並透過具體的例項來分析如何提升模型的可靠性和解讀能力。

OLS 迴歸結果分析

首先,我們使用 statsmodels 套件進行 OLS(普通最小二乘法)迴歸分析,並輸出迴歸結果的摘要。

y = clean_df['Price']
x = clean_df.drop(['Price'], axis=1)
mod = sm.OLS(y, x)
results = mod.fit()
print(results.summary())

內容解密:

  • 使用 sm.OLS 建立 OLS 迴歸模型,其中 y 是因變數(目標變數),x 是自變數(特徵變數)。
  • results.summary() 輸出迴歸分析的詳細結果,包括 R 平方值、係數、標準誤差等重要指標。
  • R 平方值為 1.0,表示模型能夠完美解釋因變數的變異,但這通常不現實,可能存在多重共線性問題。

多重共線性的檢測與處理

多重共線性是指多個自變數之間存在高度相關性,這會影響模型的穩定性和解釋力。我們使用 VIF(變異數膨脹因子)來檢測多重共線性。

from statsmodels.stats.outliers_influence import variance_inflation_factor

def calc_vif(X):
    vif = pd.DataFrame()
    vif["variables"] = X.columns
    vif["VIF"] = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
    return vif

X = clean_df.drop('Price', axis=1)
vif_df = calc_vif(X)
vif_df.sort_values(by='VIF', ascending=False).head()

內容解密:

  • variance_inflation_factor 函式用於計算每個特徵的 VIF 值。
  • VIF 值大於 10 表示存在嚴重的多重共線性,需要對相關變數進行處理。
  • 透過逐步刪除高 VIF 值的變數,重複計算 VIF,直到所有變數的 VIF 值均小於 10。

模型最佳化與評估

經過多重共線性處理後,我們重新訓練模型並評估其效能。

y = clean_df['Price']
x = clean_df.drop(['Price', 'engineCC', 'FuelType_Diesel', 'mileage'], axis=1)
xtrain, xtest, ytrain, ytest = train_test_split(x, y, test_size=0.25, random_state=1234)

new_model = LinearRegression()
new_model.fit(xtrain, ytrain)
print(new_model.score(xtrain, ytrain))
print(new_model.score(xtest, ytest))

內容解密:

  • 刪除高 VIF 值的變數後,重新進行訓練集和測試集的劃分。
  • 使用 LinearRegression 重新訓練模型,並計算訓練集和測試集上的 R 平方值。
  • 最終模型的訓練集 R 平方值為 0.70,測試集 R 平方值為 0.69,表示模型具有良好的泛化能力。

模型係數分析

最後,我們分析模型的係數,以瞭解各個特徵對目標變數的影響。

resultsDF = pd.DataFrame()
resultsDF['Variables'] = pd.Series(xtrain.columns)
resultsDF['coefficients'] = pd.Series(np.round(new_model.coef_, 2))
resultsDF.sort_values(by='coefficients', ascending=False)

內容解密:

  • 將模型的係數與對應的變數名稱整理成 DataFrame。
  • 按係數大小排序,以直觀地觀察哪些變數對目標變數有較大的正向或負向影響。

調整後的 R 平方值計算

為了更準確地評估模型的擬合優度,我們計算調整後的 R 平方值。

def AdjustedRSquare(model, X, Y):
    YHat = model.predict(X)
    n, k = X.shape
    # 公式實作

內容解密:

  • 調整後的 R 平方值考慮了模型中變數的數量,能夠更真實地反映模型的解釋能力。
  • 實作調整後的 R 平方值計算函式,有助於更全面地評估模型效能。

透過上述步驟,我們不僅提高了線性模型的可靠性,也增強了對模型結果的解讀能力。這對於實際應用中的決策支援具有重要意義。

線性模型的解釋能力

調整後的R平方值計算函式

在評估線性迴歸模型的表現時,R平方值($R^2$)是一個重要的指標。然而,$R^2$會隨著模型中預測變數的增加而增加,即使這些變數並不具有統計顯著性。因此,引入了調整後的R平方值($adjR^2$)來糾正這個問題。

def AdjustedRSquare(model, X, Y):
    YHat = model.predict(X)
    n, k = X.shape
    sse = np.sum(np.square(YHat - Y), axis=0)  # 殘差平方和
    sst = np.sum(np.square(Y - np.mean(Y)), axis=0)  # 總平方和
    R2 = 1 - sse / sst  # R平方值
    adjR2 = R2 - (1 - R2) * (float(k) / (n - k - 1))  # 調整後的R平方值
    return adjR2, R2

內容解密:

  1. YHat = model.predict(X):使用模型對輸入資料X進行預測,得到預測值YHat
  2. n, k = X.shape:取得樣本數量n和特徵數量k
  3. sse = np.sum(np.square(YHat - Y), axis=0):計算殘差平方和,即預測值與實際值之間的差異的平方和。
  4. sst = np.sum(np.square(Y - np.mean(Y)), axis=0):計算總平方和,即實際值與其均值之間的差異的平方和。
  5. R2 = 1 - sse / sst:計算R平方值,表示模型能夠解釋的變異比例。
  6. adjR2 = R2 - (1 - R2) * (float(k) / (n - k - 1)):計算調整後的R平方值,對R平方值進行調整以考慮模型的複雜度。

計算p值的函式

p值是用於評估模型中每個預測變數統計顯著性的指標。

from scipy import stats

def ReturnPValue(model, X, Y):
    YHat = model.predict(X)
    n, k = X.shape
    sse = np.sum(np.square(YHat - Y), axis=0)
    x = np.hstack((np.ones((n, 1)), np.matrix(X)))
    df = float(n - k - 1)
    sampleVar = sse / df
    sampleVarianceX = x.T * x
    covarianceMatrix = linalg.sqrtm(sampleVar * sampleVarianceX.I)
    se = covarianceMatrix.diagonal()[1:]
    betasTstat = np.zeros(len(se))
    for i in range(len(se)):
        betasTstat[i] = model.coef_[i] / se[i]
    betasPvalue = 1 - stats.t.cdf(abs(betasTstat), df)
    return betasPvalue

內容解密:

  1. YHat = model.predict(X):使用模型對輸入資料X進行預測,得到預測值YHat
  2. sse = np.sum(np.square(YHat - Y), axis=0):計算殘差平方和。
  3. x = np.hstack((np.ones((n, 1)), np.matrix(X))):在資料矩陣X前新增一列全為1的列,以表示截距項。
  4. df = float(n - k - 1):計算自由度。
  5. sampleVar = sse / df:計算樣本變異數。
  6. covarianceMatrix = linalg.sqrtm(sampleVar * sampleVarianceX.I):計算迴歸係數的協方差矩陣。
  7. betasTstat = model.coef_ / se:計算迴歸係數的t統計量。
  8. betasPvalue = 1 - stats.t.cdf(abs(betasTstat), df):計算迴歸係數的p值。

模型評估與變數篩選

透過計算調整後的R平方值和p值,可以評估模型的表現和篩選具有統計顯著性的變數。

resultsDF['p_value'] = pd.Series(np.round(ReturnPValue(new_model, xtrain, ytrain), 2))
resultsDF.sort_values(by='coefficients', ascending=False)

最終模型

在移除多重共線性變數和統計上不顯著的變數後,模型的準確度仍然保持在訓練集上的70%和測試集上的69%左右。

模型解釋能力

線性迴歸模型的優勢在於其簡單性和線性,使得模型解釋變得容易。透過檢視模型的beta係數,可以瞭解每個變數對預測結果的影響。

reg.adjR2, reg.R2 = AdjustedRSquare(new_model, xtrain, ytrain)
print(reg.adjR2, reg.R2)

此圖示說明模型的擬合優度。

錯誤指標計算函式

def ErrorMetric(model, X, Y):
    Yhat = model.predict(X)
    MAPE = np.mean(abs(Y - Yhat) / Y) * 100
    MSSE = np.mean(np.square(Y - Yhat))
    Error = sns.distplot(Y - Yhat)
    return MAPE, MSSE, Error

內容解密:

  1. Yhat = model.predict(X):使用模型對輸入資料X進行預測,得到預測值Yhat
  2. MAPE = np.mean(abs(Y - Yhat) / Y) * 100:計算平均絕對百分比誤差,表示預測誤差的平均大小。
  3. MSSE = np.mean(np.square(Y - Yhat)):計算均方誤差,表示預測誤差的平方的平均值。
  4. Error = sns.distplot(Y - Yhat):繪製殘差的分佈圖,用於檢查殘差是否呈現正態分佈。