化學資訊學入門與實作:線性回歸模型的介紹與應用

Chemistry with data magic
14 min readMay 12, 2024

--

在本文中,我們將討論監督學習裡的重要概念-回歸問題。具體來說,我們將考慮一個機器學習模型,該模型稱為”線性模型”的演算法。我們會配合一個QSPR的例子來解說線性回歸模型。

本文會使用到多個之前介紹過的概念,以下是相關文章的回顧:

準備數據

我們將使用以下論文所附的數據集進行建模。

ESOL: Estimating Aqueous Solubility Directly from Molecular Structure
J. Chem. Inf. Comput. Sci. 2004, 44, 1000–1005.
(DOI: 10.1021/ci034243x)

什麼是線性模型?

線性模型是一種將預測作為輸入向量的線性函數的一種模型。換句話說,模型是在目標值可以表示為特徵量 (x) 的線性和的假設下建構的。它可以表達為如下的數學公式。 𝑦̂表示它是一個預測值/目標值。

儘管這個假設相當簡單,但線性模型有時候卻很有效。值得注意的地方是在特徵量比資料點多的資料上,線性模型很容易過度擬合 (over-fitting)。

  • 線形回帰

Ordinary Least Squares (OLS) 是最經典的線性模型。我們考慮 10 個二維資料點,在這種情況下其線性模型的公式如下:

OLS的擬合結果會是下圖黑色的線。

然而, OLS 是如何推算出常數 a 和 b 來得到黑色的線呢?

這條最準確的直線 (黑線) 可以被認為是「使預測值與真實值之間的差異總和最小的直線」。換句話說,我們可以將均方誤差視為 a 和 b 的函數,並找到給出最小值的組合。也就是將下列式子做最小化:

在機器學習中,我們經常需要尋找最佳的參數讓某個函數的誤差最小化的,這樣的函數稱為「損失函數」或「誤差函數」。

OLS 中損失函數的一般公式如下:

yi 是預測值/目標值,w 是包含截距的係數向量,,xi 是由特徵量 xki (i=1,2,,,n) 組成的向量。

或是

yk 是預測值/目標值,x 是由特徵量 xki (i=1,2,,,n) 組成的向量。

  • OLS 的過度擬合 (Overfitting) 問題

我們在先前提到的問題

儘管這個假設相當簡單,但線性模型有時候卻很有效。值得注意的地方是在特徵量比資料點多的資料上,線性模型很容易過度擬合 (over-fitting)。

這裡我們來解釋,為什麼資料點過少的情況下,OLS 容易過度擬合 (over-fitting)。我們假設一個極端的狀況,只用 2 個資料點當作 training data 進行建模,剩下的 8 個資料點則是驗證模型用的 test data。下圖則是會發生的情況:

由於 OLS 會企圖找到使預測值與真實值之間的差異總和最小的直線,在只有 2 個資料點的情況下,通過這兩個資料點會是預測值與真實值之間的差異總和最小的直線。但我們用 test data (綠色資料點) 來驗證 OLS 結果時,我們會發現不少資料點有極大的誤差,這個情況就被稱為過度擬合 (over-fitting)。換句話說,我們所建立的模型對 training data 的預測經度很高,但對 test data 的預測卻不準確,這也是一個過度擬合 (over-fitting)模型的常見問題。

  • 如何解決 OLS 的過度擬合 (Overfitting) 問題

有一個有趣的想法可以緩解 OLS 的過度擬合 (Overfitting) 問題。如果擬合 training data 的這條直線,沒有直接通過這兩個資料點的話,那麼對 test data 的預測精度不就會增加了!這個想法如下圖所示:

OLS 的的過度擬合 (Overfitting) 問題,是因為 OLS 損失函數 (Loss) 的定義所造成直線通過兩個資料點。如果我們在 Loss 的式子中加入一些誤差的話,直線就自然不會通過兩個資料點,進而提高了對 test data 的預測精度。因此,幾個 OLS 改良版線性模型就此出現了。

  • Ridge regression (Ridge回歸、嶺回歸)

之前提到過,在損失函數 (Loss) 添加誤差的方法,其正確的說法是降低模型複雜度而執行的過程,又被稱為「正則化 (regularization)」。具體來說,我們將考慮一個向損失函數 (Loss) 添加正則化項的函數,並考慮尋找最小化該函數的參數。另外,這種「損失函數+正則化項」稱為成本函數。

Ridge regression 對線性模型中每一項的係數大小給予懲罰。 α 是調整正則化懲罰程度的參數;α 越大,模型的限制性越大;當 α 為0時,模型變得與 OLS 相同。

後面的正規化項是係數向量的L2範數:

因此,又稱為L2正則化。在 Ridge 回歸中,有些回歸係數由於 L2 正則化而變小。

  • Lasso regression (Lasso回歸、套索回歸)

Lasso 回歸也會懲罰線性模型中每一項係數的大小。在 Ridge 回歸中,進行了 L2 正規化,但使用係數向量的 L1 範數的正則化稱為 Lasso 回歸。類似地,α 是表示懲罰程度的參數。

在 Lasso 迴歸中,有些回歸係數由於 L1 正則化而變為零。

利用 RDKit 與 scikit-learn 中線性模型進行 QSPR 建模

  • 使用 RDKit 和 Pandas 讀取分子資料

先導入需要用到的一些 library :

from rdkit import rdBase, Chem
from rdkit.Chem import AllChem, Draw, PandasTools
from rdkit.Chem.Draw import IPythonConsole
import pandas as pd
import numpy as np

將 ESOL 數據集載入為pandas.DataFrame。

df = pd.read_csv('esol.csv')
df.head()

其輸出為:

再來是利用 PandasTools.AddMoleculeColumnToFrame 把 DataFrame 中 smiles 格式的分子轉換回 Mol 的形式。

PandasTools.AddMoleculeColumnToFrame(frame=df, smilesCol='smiles')

檢視一下輸出結果:

接著我們得將分子轉換成數值的形式,才能進行建模。我們利用 RDKit 來計算 Morgan fingerprint 。子構造範圍設定為 radius = 2,向量長度為 1024 位元。然後將資料分割成 training data 和 test data。

from sklearn.model_selection import train_test_split

morgan_fps = []
for mol in df.ROMol:
fp = [x for x in AllChem.GetMorganFingerprintAsBitVect(mol, 2, 1024)]
morgan_fps.append(fp)
morgan_fps = np.array(morgan_fps)
target = df['measured log solubility in mols per litre']

X_train, X_test, y_train, y_test = train_test_split(morgan_fps, target, random_state=0)

確認一下分子指紋結果:

確認一下數據的狀態:

Training data 資料量為 846 筆,特徵量的數量為 1,024,是個特徵量比資料點多的資料。Teat data 資料量為 282筆。

  • 使用 scikit-learn 中的線性回歸

首先,我們使用 OLS 來建構模型。

from sklearn.linear_model import LinearRegression
lr = LinearRegression().fit(X_train, y_train)
print('acc on train: {:.3f}'.format(lr.score(X_train, y_train)))
print('acc on test: {:.3f}'.format(lr.score(X_test, y_test)))

我們得到的模型精度為:

acc on train: 0.984
acc on test: -1653049730781467639808.000

Training data 的預測準確度很高,但對 test data 的預測準確度卻是為負。這就是我們在前面所提到的 OLS 的過度擬合 (Overfitting) 問題。

  • 使用 scikit-learn 中的 Ridge 回歸

接下來,我們將使用 L2 正則化的 Ridge 回歸來建構模型。Ridge 回歸可使回歸係數的絕對值保持在較小的狀態。

from sklearn.linear_model import Ridge
ridge = Ridge().fit(X_train, y_train)
print('acc on train: {:.3f}'.format(ridge.score(X_train, y_train)))
print('acc on test: {:.3f}'.format(ridge.score(X_test, y_test)))

acc on train: 0.940
acc on test: 0.509

Ridge 回歸的學習結果比較正常,但 training data 的準確度依然高於 test data 的準確度,然後有些過度擬合 (over-fitting) 的跡象。因此,我們可以調整不同的 α ,來抑制過度擬合的狀況。

for i in [0.0001, 0.001, 0.1, 1, 5, 10, 50, 100]:
r = Ridge(alpha=i).fit(X_train, y_train)
print('-- alpha = {} --'.format(i))
print('acc on train: {:.3f}'.format(r.score(X_train, y_train)))
print('acc on test: {:.3f}'.format(r.score(X_test, y_test)))

— alpha = 0.0001 —
acc on train: 0.984
acc on test: -1.529
— alpha = 0.001 —
acc on train: 0.984
acc on test: -1.409
— alpha = 0.1 —
acc on train: 0.976
acc on test: -0.106
— alpha = 1 —
acc on train: 0.940
acc on test: 0.509
— alpha = 5 —
acc on train: 0.876
acc on test: 0.630
— alpha = 10 —
acc on train: 0.834
acc on test: 0.638
— alpha = 50 —
acc on train: 0.694
acc on test: 0.570
— alpha = 100 —
acc on train: 0.608
acc on test: 0.504

在這種情況下,α 在 5 到 10 之間似乎是最佳解。重要的是要確認 α 的大小,如果 α 很小時,則模型容易過度擬合 (over-fitting),如果 α 很大,則模型會受到較強的侷限。

  • 使用 scikit-learn 中的 Lasso 回歸

接下來,讓我們來試試看 L1 正則化的 Lasso 迴歸。

from sklearn.linear_model import Lasso
lasso = Lasso().fit(X_train, y_train)
print('acc on train: {:.3f}'.format(lasso.score(X_train, y_train)))
print('acc on test: {:.3f}'.format(lasso.score(X_test, y_test)))

acc on train: 0.000
acc on test: -0.001

Lasso 回歸的表現非常的差,training data 和 test data 都沒有達到該有的預測精確度。這是因為 α 的預設值似乎對模型來說太大,對模型的限制較多。因此,我們可以透過減小 α 的值來使模型更加複雜。

for i in [0.00001, 0.0001, 0.001, 0.005, 0.01, 0.1, 1]:
l = Lasso(alpha=i, max_iter=100000).fit(X_train, y_train)
print('-- Lasso: alpha = {} --'.format(i))
print('acc on train: {:.3f}'.format(l.score(X_train, y_train)))
print('acc on test: {:.3f}'.format(l.score(X_test, y_test)))

— Lasso: alpha = 1e-05 —
acc on train: 0.983
acc on test: -1.590
— Lasso: alpha = 0.0001 —
acc on train: 0.977
acc on test: -0.304
— Lasso: alpha = 0.001 —
acc on train: 0.915
acc on test: 0.537
— Lasso: alpha = 0.005 —
acc on train: 0.778
acc on test: 0.600
— Lasso: alpha = 0.01 —
acc on train: 0.695
acc on test: 0.577
— Lasso: alpha = 0.1 —
acc on train: 0.245
acc on test: 0.184
— Lasso: alpha = 1 —
acc on train: 0.000
acc on test: -0.001

如果 α 太小 (α = 1e-05),Lasso回歸會接近 OLS 並過度擬合 (over-fitting),但隨著 α 逐漸增加,test data 的預測準確性會增加,但 α 超過某個大小後,預測準確度又會再次下降。在這種情況下,α 在 0.001 到 0.01之間似乎是最佳解。

結語

在本文中,我們簡單介紹了線性回歸的基本概念。然後用 ESOL 數據簡單地構築了 QSPR 模型。雖然線性回歸的概念很簡單,但實作上常常會遇到過度擬合 (over-fitting) 的現象,為了解決過度擬合的問題,我們需要謹慎的調整 Ridge 回歸和 Lasso 回歸的 α 值來找到較好的模型。在化學資訊學中,我們會常常遇到數據量不足的問題,進而造成過度擬合 (over-fitting) 的現象。之後,我們會慢慢介紹一些技巧來建構更好 QSAR/QSPR 模型。

在續篇中,我們會介紹另一種線性回歸模型 Elastic Net、交叉驗證和超參數調整。

--

--

Chemistry with data magic

I am working on improving material developments by creating machine learning analytical tools for chemical data to accelerate the material discovery.