作者|Ruben Winastwan
編譯|VK
來源|Towards Data Science

當你學習資料科學和機器學習時,線性回歸可能是你遇到的第一個統計方法,我猜這不是你們第一次使用線性回歸了,因此,在本文中,我想討論概率線性回歸,而不是典型的/確定性線性回歸,
但在此之前,讓我們簡要討論一下確定性線性回歸的概念,以便快速了解本文的主要討論要點,
線性回歸是一種基本的統計方法,用來建立一個或多個輸入變數(或自變數)與一個或多個輸出變數(或因變數)之間的線性關系,

上式中,a為截距,b為斜率,x是自變數,y是因變數,也就是我們要預測的值,
a和b的值需要用梯度下降演算法進行優化,然后,我們得到了一條自變數和因變數之間最合適的回歸直線,通過回歸線,我們可以預測任意輸入x的y的值,這些是如何建立典型的或確定性的線性回歸演算法的步驟,

然而,這種確定性的線性回歸演算法并不能真正描述資料,這是為什么呢?
實際上,當我們進行線性回歸分析時,會出現兩種不確定性:
- 任意不確定性,即由資料產生的不確定性,
- 認知的不確定性,這是從回歸模型中產生的不確定性,
我將在文章中詳細闡述這些不確定性,考慮到這些不確定性,應采用概率線性回歸代替確定性線性回歸,
在本文中,我們將討論概率線性回歸以及它與確定性線性回歸的區別,我們將首先看到確定性線性回歸是如何在TensorFlow中構建的,然后我們將繼續構建一個包含TensorFlow概率的概率線性回歸模型,
首先,讓我們從加載本文將使用的資料集開始,
加載和預處理資料
本文將使用的資料集是car的MPG資料集,像往常一樣,我們可以用pandas加載資料,
import pandas as pd
auto_data = https://www.cnblogs.com/panchuangai/archive/2020/11/03/pd.read_csv('auto-mpg.csv')
auto_data.head()

以下是資料的統計匯總,

接下來,我們可以使用下面的代碼查看資料集中變數之間的相關性,
import matplotlib.pyplot as plt
import seaborn as sns
corr_df = auto_data.corr()
sns.heatmap(corr_df, cmap="YlGnBu", annot = True)
plt.show()

現在如果我們看一下相關性,汽車的每加侖英里數(MPG)和汽車的重量有很強的負相關性,
在本文中,為了可視化的目的,我將做一個簡單的線性回歸分析,自變數是車的重量,因變數是車的MPG,
現在,讓我們用Scikit-learn將資料分解為訓練資料和測驗資料,拆分資料后,我們現在可以縮放因變數和自變數,這是為了確保兩個變數在相同的范圍內這也將提高線性回歸模型的收斂速度,
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
x = auto_data['weight']
y = auto_data['mpg']
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state=5)
min_max_scaler = preprocessing.MinMaxScaler()
x_train_minmax = min_max_scaler.fit_transform(x_train.values.reshape(len(x_train),1))
y_train_minmax = min_max_scaler.fit_transform(y_train.values.reshape(len(y_train),1))
x_test_minmax = min_max_scaler.fit_transform(x_test.values.reshape(len(x_test),1))
y_test_minmax = min_max_scaler.fit_transform(y_test.values.reshape(len(y_test),1))
現在如果我們將訓練資料可視化,我們得到如下可視化:

太棒了!接下來,讓我們繼續使用TensorFlow構建我們的確定性線性回歸模型,
基于TensorFlow的確定性線性回歸
用TensorFlow建立一個簡單的線性回歸模型是非常容易的,我們所需要做的就是建立一個沒有任何激活函式的單一全連接層模型,對于成本函式,通常使用均方誤差,在本例中,我將使用RMSprop作為優化器,模型將在100個epoch內進行訓練,我們可以用下面的幾行代碼構建和訓練模型,
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.losses import MeanSquaredError
model = Sequential([
Dense(units=1, input_shape=(1,))
])
model.compile(loss=MeanSquaredError(), optimizer=RMSprop(learning_rate=0.01))
history = model.fit(x_train_minmax, y_train_minmax, epochs=100, verbose=False)
在我們訓練了模型之后,讓我們看看模型的損失來檢查損失的收斂性,
def plot_loss(history):
plt.plot(history.history['loss'], label='loss')
plt.xlabel('Epoch')
plt.ylabel('Error')
plt.legend()
plt.grid(True)
plot_loss(history)

看來損失已經收斂了,現在,如果我們使用訓練過的模型來預測測驗集,我們可以看到下面的回歸線,

就是這樣,我們完成了!
正如我前面提到的,使用TensorFlow構建一個簡單的線性回歸模型是非常容易的,有了回歸線,我們現在可以在任何給定的汽車的重量輸入來近似的汽車的MPG,舉個例子,假設特征縮放后的汽車重量是0.64,通過將該值傳遞給訓練過的模型,我們可以得到相應的汽車MPG值,如下所示,

現在你可以看到,模型預測汽車的MPG是0.21,簡單地說,對于任何給定的汽車重量,我們得到一個確定的汽車MPG值
然而,輸出并不能說明全部問題,這里我們應該注意兩件事,首先,我們只有有限的資料點,第二,正如我們從線性回歸圖中看到的,大多數資料點并不是真的在回歸線上,
雖然我們得到的輸出值是0.21,但我們知道實際汽車的MPG不是確切的0.21,它可以略低于這個值,也可以略高于這個值,換句話說,需要考慮到不確定性,這種不確定性稱為任意不確定性,
確定性線性回歸不能捕捉資料的任意不確定性,為了捕捉這種任意的不確定性,可以使用概率線性回歸代替,
TensorFlow概率的概率線性回歸
由于有了TensorFlow概率,建立概率線性回歸模型也非常容易,但是,你需要首先安裝tensorflow_probability庫,你可以使用pip命令安裝它,如下所示:
pip install tensorflow_probability
安裝此庫的先決條件是你需要擁有TensorFlow 2.3.0版本,因此,請確保在安裝TensorFlow Probability之前升級你的TensorFlow版本,
針對不確定性建立概率線性回歸模型
在本節中,我們將建立一個考慮不確定性的概率線性回歸模型,
這個模型與確定性線性回歸非常相似,但是,與之前只使用一個單一的全連接層不同,我們需要再添加一個層作為最后一層,最后一層將最終輸出值從確定性轉換為概率分布,
在本例中,我們將創建最后一層,它將輸出值轉換為正態分布的概率值,下面是它的實作,
import tensorflow_probability as tfp
import tensorflow as tf
tfd = tfp.distributions
tfpl = tfp.layers
model = Sequential([
Dense(units=1+1, input_shape=(1,)),
tfpl.DistributionLambda(
lambda t: tfd.Normal(loc=t[..., :1],
scale=tf.math.softplus(t[...,1:]))),
])
注意,我們在最后應用了一個額外的層TensorFlow概率層,該層將前一個全連接層的兩個輸出(一個為均值,一個為標準差)轉化為具有可訓練均值(loc)和標準差(scale)正態分布的概率值,
我們可以使用RMSprop作為優化器,但是如果你愿意,你也可以使用其他優化器,對于損失函式,我們需要使用負對數似然,
但是為什么我們使用負對數似然作為損失函式呢
負對數似然作為成本函式
為了對一些資料擬合一個分布,我們需要使用似然函式,通過似然函式,我們在給定我們在資料中嘗試估計未知的引數(例如,正態分布資料的平均值和標準差),

在我們的概率回歸模型中,優化器的作業是找到未知引數的最大似然估計,換句話說,我們訓練模型從我們的資料中找到最有可能的引數值,

最大化似然估計和最小化負對數似然是一樣的,在優化領域,通常目標是最小化成本而不是最大化成本,這就是為什么我們使用負對數似然作為代價函式,
下面是實作的負對數似然作為我們的自定義損失函式,
def negative_log_likelihood(y_true, y_pred):
return -y_pred.log_prob(y_true)
隨機不確定性概率線性回歸模型的訓練與預測結果
現在我們已經構建了模型并定義了優化器以及loss函式,接下來讓我們編譯并訓練這個模型,
model.compile(optimizer=RMSprop(learning_rate=0.01), loss=negative_log_likelihood)
history = model.fit(x_train_minmax, y_train_minmax, epochs=200, verbose=False);
現在我們可以從訓練好的模型中抽取樣本,我們可以通過下面的代碼可視化測驗集和從模型生成的示例之間的比較,
y_model = model(x_test_minmax)
y_sample = y_model.sample()
plt.scatter(x_test_minmax, y_test_minmax, alpha=0.5, label='test data')
plt.scatter(x_test_minmax, y_sample, alpha=0.5, color='green', label='model sample')
plt.xlabel('Weight')
plt.ylabel('MPG')
plt.legend()
plt.show()

正如你從上面的可視化中看到的,現在對于任何給定的輸入值,模型都不會回傳確定性值,相反,它將回傳一個分布,并基于該分布繪制一個樣本,
如果你比較測驗集的資料點(藍點)和訓練模型預測的資料點(綠點),你可能會認為綠點和藍點來自相同的分布,
接下來,我們還可以可視化訓練模型生成的分布的均值和標準差,給定訓練集中的資料,我們可以通過應用以下代碼來實作這一點,
y_mean = y_model.mean()
y_sd = y_model.stddev()
y_mean_m2sd = y_mean - 2 * y_sd
y_mean_p2sd = y_mean + 2 * y_sd
plt.scatter(x_test_minmax, y_test_minmax, alpha=0.4, label='data')
plt.plot(x_test_minmax, y_mean, color='red', alpha=0.8, label='model $\mu$')
plt.plot(x_test_minmax, y_mean_m2sd, color='green', alpha=0.8, label='model $\mu \pm 2 \sigma$')
plt.plot(x_test_minmax, y_mean_p2sd, color='green', alpha=0.8)
plt.xlabel('Weight')
plt.ylabel('MPG')
plt.legend()
plt.show()

我們可以看到,概率線性回歸模型給我們比回歸線更多,它也給出了資料的標準差的近似值,可以看出,大約95%的測驗集資料點位于兩個標準差范圍內,
建立隨機和認知不確定性的概率線性回歸模型
到目前為止,我們已經建立了一個概率回歸模型,它考慮了來自資料的不確定性,或者我們稱之為任意不確定性,
然而,在現實中,我們還需要處理來自回歸模型本身的不確定性,由于資料的不完善,回歸引數的權重或斜率也存在不確定性,這種不確定性稱為認知不確定性,
到目前為止,我們建立的概率模型只考慮了一個確定的權重,正如你從可視化中看到的,模型只生成一潭訓歸線,而且這通常不是完全準確的,
在本節中,我們將改進同時考慮任意和認知不確定性的概率回歸模型,我們可以使用貝葉斯的觀點來引入回歸權值的不確定性,
首先,在我們看到資料之前,我們需要定義我們之前對權重分布的看法,通常,我們不知道會發生什么,對吧?為了簡單起見,我們假設權值的分布是正態分布均值為0,標準差為1,
def prior(kernel_size, bias_size, dtype=None):
n = kernel_size + bias_size
return Sequential([
tfpl.DistributionLambda(lambda t: tfd.Independent(
tfd.Normal(loc=tf.zeros(n), scale=tf.ones(n))))
])
由于我們硬編碼了平均值和標準差,這種先驗是不可訓練的,
接下來,我們需要定義回歸權重的后驗分布,后驗分布顯示了我們的信念在看到資料中的模式后發生了怎樣的變化,因此,該后驗分布中的引數是可訓練的,下面是定義后驗分布的代碼實作,
def posterior(kernel_size, bias_size, dtype=None):
n = kernel_size + bias_size
return Sequential([
tfpl.VariableLayer(2 * n, dtype=dtype),
tfpl.DistributionLambda(lambda t: tfd.Independent(
tfd.Normal(loc=t[..., :n],
scale=tf.nn.softplus(t[..., n:]))))
])
現在的問題是,這個后驗函式中的變數定義是什么?這個可變層背后的想法是我們試圖接近真實的后驗分布,一般情況下,不可能推匯出真正的后驗分布,因此我們需要對其進行近似,
在定義了先驗函式和后驗函式后,我們可以建立權重不確定性的概率線性回歸模型,下面是它的代碼實作,
model = Sequential([
tfpl.DenseVariational(units = 1 + 1,
make_prior_fn = prior,
make_posterior_fn = posterior,
kl_weight=1/x.shape[0]),
tfpl.DistributionLambda(
lambda t: tfd.Normal(loc=t[..., :1],
scale=tf.math.softplus(t[...,1:])))
])
正如你可能注意到的,此模型與前面的概率回歸模型之間的唯一區別只是第一層,我們用DenseVariational層代替了普通的全連接層,在這一層中,我們通過前面和后面的函式作為引數,第二層與前面的模型完全相同,
隨機不確定性和認知不確定性概率線性回歸模型的訓練和預測結果
現在是時候編譯和訓練模型了,
優化器和成本函式仍然與以前的模型相同,我們使用RMSprop作為優化器和負對數似然作為我們的成本函式,讓我們編譯和訓練,
model.compile(optimizer= RMSprop(learning_rate=0.01), loss=negative_log_likelihood)
history = model.fit(x_train_minmax, y_train_minmax, epochs=500, verbose=False);
現在是時候可視化回歸模型的權值或斜率的不確定性了,下面是可視化結果的代碼實作,
plt.scatter(x_test_minmax, y_test_minmax, marker='.', alpha=0.8, label='data')
for i in range(10):
y_model = model(x_test_minmax)
y_mean = y_model.mean()
y_mean_m2sd = y_mean - 2 * y_model.stddev()
y_mean_p2sd = y_mean + 2 * y_model.stddev()
if i == 0:
plt.plot(x_test_minmax, y_mean, color='red', alpha=0.8, label='model $\mu$')
plt.plot(x_test_minmax, y_mean_m2sd, color='green', alpha=0.8, label='model $\mu \pm 2 \sigma$')
plt.plot(x_test_minmax, y_mean_p2sd, color='green', alpha=0.8)
else:
plt.plot(x_test_minmax, y_mean, color='red', alpha=0.8)
plt.plot(x_test_minmax, y_mean_m2sd, color='green', alpha=0.8)
plt.plot(x_test_minmax, y_mean_p2sd, color='green', alpha=0.8)
plt.xlabel('Weight')
plt.ylabel('MPG')
plt.legend()
plt.show()

在上面的可視化圖中,你可以看到,經過訓練的模型的后驗分布產生的線性線(均值)和標準差在每次迭代中都是不同的,所有這些線都是擬合測驗集中資料點的合理解決方案,但是,由于認知的不確定性,我們不知道哪條線是最好的,
通常,我們擁有的資料點越多,我們看到的回歸線的不確定性就越小,
今晚
現在你已經看到了概率線性回歸與確定性線性回歸的不同之處,在概率線性回歸中,兩種不確定性產生于資料(任意)和回歸模型(認知)可以被考慮在內,
如果我們想建立一個深度學習模型,讓不準確的預測導致非常嚴重的負面后果,例如在自動駕駛和醫療診斷領域,考慮這些不確定性是非常重要的,
通常,當我們有更多的資料點時,模型的認知不確定性將會減少,
原文鏈接:https://towardsdatascience.com/probabilistic-linear-regression-with-weight-uncertainty-a649de11f52b
歡迎關注磐創AI博客站:
http://panchuang.net/
sklearn機器學習中文官方檔案:
http://sklearn123.com/
歡迎關注磐創博客資源匯總站:
http://docs.panchuang.net/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/201767.html
標籤:其他
上一篇:基于SVM的例外檢測方法
