RBFN

下面我们详细讲解这个实现径向基函数神经网络(RBFN)的代码,并结合数学公式来说明每个部分的作用。

一、RBFN简介

径向基函数神经网络(RBFN)是一种前馈神经网络,通常包含三层:

  1. 输入层:直接将输入数据传递到隐藏层。
  2. 隐藏层:由一组径向基函数组成,每个函数都有一个中心(centers)和宽度(sigma)。
  3. 输出层:线性组合隐藏层的输出,得到最终预测结果。

RBFN的训练过程主要包括:

  • 确定径向基函数的中心(通常使用K均值聚类)。
  • 计算每个径向基函数的宽度(sigma)。
  • 使用最小二乘法或伪逆求解输出层的权重。

二、代码详解

1. 初始化方法 __init__

def __init__(
    self,
    hidden_shape,
    norm_func=functools.partial(np.linalg.norm, ord=2, axis=-1),
):
    self.hidden_shape = hidden_shape
    self.norm_func = norm_func
    self.w = None
    self.sigmas = None
    self.centers = None
    self.proc_id = None

解释:

  • hidden_shape:隐藏层的神经元数量,即径向基函数的数量。
  • norm_func:计算距离的函数,默认为欧氏距离(2-范数)。

2. 计算sigma的函数 _calc_sigmas

def _calc_sigmas(self):
    c_ = np.expand_dims(self.centers, 1)
    ds = self.norm_func(c_ - self.centers)
    sigma = 2 * np.mean(ds, axis=1)
    sigma = np.sqrt(0.5) / sigma
    return sigma

解释:

  • 目的:计算每个径向基函数的宽度(sigma)。
  • 步骤
    1. 计算中心点之间的距离矩阵

      \[\text{ds}_{ij} = \| \text{centers}_i - \text{centers}_j \| \]

    2. 计算每个中心的平均距离

      \[\sigma_i = 2 \times \text{mean}(\text{ds}_{i}) \]

    3. 调整sigma

      \[\sigma_i = \frac{\sqrt{0.5}}{\sigma_i} \]

注意:这里的sigma实际上是高斯函数中的系数,通常高斯函数为:

\[\phi(x) = \exp\left(-\frac{\| x - c \|^2}{2\sigma^2}\right) \]

但在代码中,高斯函数被实现为:

\[\phi(x) = \exp\left(-(\| x - c \| \cdot \sigma)^2\right) \]

因此,sigma的计算方式有所不同。

3. 计算插值矩阵的函数 _calc_interpolation_mat

def _calc_interpolation_mat(self, X):
    x = np.expand_dims(X, 1)
    r = self.norm_func(x - self.centers)
    r =  r * self.sigmas
    return np.exp(-(r**2))

解释:

  • 目的:计算隐藏层的输出,即径向基函数的响应。
  • 步骤
    1. 计算输入数据与每个中心的距离

      \[r_{ij} = \| X_i - \text{centers}_j \| \]

    2. 调整距离

      \[r_{ij} = r_{ij} \times \sigma_j \]

    3. 计算径向基函数的输出

      \[\Phi_{ij} = \exp\left(-r_{ij}^2\right) \]

4. 训练模型的函数 fit

def fit(self, X, y):
    self.centers = KMeans(n_clusters=self.hidden_shape).fit(X).cluster_centers_
    self.sigmas = self._calc_sigmas()
    tmp = self._calc_interpolation_mat(X)
    X_ = np.c_[np.ones(len(tmp)), tmp]
    y = y.reshape((-1, 1))
    self.w = np.linalg.pinv(X_) @ y

解释:

  • 步骤
    1. 使用K均值聚类确定径向基函数的中心
      • \(\text{centers} = \text{KMeans}(n\_clusters=\text{hidden\_shape}).\text{fit}(X).\text{cluster\_centers\_}\)
    2. 计算每个径向基函数的宽度(sigma)
      • 调用_calc_sigmas函数。
    3. 计算插值矩阵(隐藏层的输出)
      • \(\Phi = \text{\_calc\_interpolation\_mat}(X)\)
    4. 在插值矩阵前添加偏置项(1列)
      • \(X\_ = [\mathbf{1}, \Phi]\)
    5. 使用最小二乘法计算输出层的权重
      • \(w = (X\_^T X\_)^{-1} X\_^T y\)
      • 在代码中使用伪逆求解:

        \[w = X\_^{+} y \]

5. 预测函数 predict

def predict(self, X):
    if X.ndim == 1:
       X = X.reshape((1, -1)) 
    tmp = self._calc_interpolation_mat(X)
    X_ = np.c_[np.ones(len(tmp)), tmp]
    pre = X_ @ self.w
    return pre.reshape((-1, ))

解释:

  • 步骤
    1. 确保输入数据的维度正确
    2. 计算插值矩阵(隐藏层的输出)
      • \(\Phi = \text{ \_calc\_interpolation\_mat}(X)\)
    3. 在插值矩阵前添加偏置项(1列)
      • \(X\_ = [\mathbf{1}, \Phi]\)
    4. 计算输出
      • \(\text{pre} = X\_ w\)
    5. 返回预测结果

三、数学公式总结

  1. 径向基函数的形式

    \[\phi_j(x) = \exp\left(-(\| x - c_j \| \cdot \sigma_j)^2\right) \]

  2. 隐藏层的输出矩阵(插值矩阵)

    \[\Phi_{ij} = \phi_j(X_i) \]

  3. 输出层的计算(线性回归)

    \[y = X\_ w = [\mathbf{1}, \Phi] w \]

  4. 权重的求解(最小二乘法)

    \[w = (X\_^T X\_)^{-1} X\_^T y \]

    或者使用伪逆:

    \[w = X\_^{+} y \]

四、总结

该代码实现了一个简单的径向基函数神经网络,主要步骤包括:

  • 使用K均值聚类确定径向基函数的中心。
  • 计算每个径向基函数的宽度(sigma)。
  • 构建插值矩阵,计算隐藏层的输出。
  • 使用伪逆求解输出层的权重,实现线性回归。
  • 预测时,计算新的输入数据经过隐藏层和输出层后的结果。

通过以上步骤,我们可以使用RBFN对数据进行拟合和预测。

posted @ 2024-10-21 14:43  jasonzhangxianrong  阅读(34)  评论(0编辑  收藏  举报