关于人工智能:权重不确定的概率线性回归

3次阅读

共计 7937 个字符,预计需要花费 20 分钟才能阅读完成。

作者 |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 = 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.co…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

正文完
 0