• 受限玻尔兹曼机及实现


    Energy-Based Models(EBM)

      基于能量的概率模型将一个标量能量与相关变量的每个配置相关联。学习相当于修改能量函数,能量达到最佳性质 。例如,我们希望合理的或理想的结构具有低能量。基于能量的概率模型通过能量函数定义概率分布,如下:

     Z是正则化系数,也叫做配分函数:

    基于能量的模型可以通过对训练数据的经验负对数似然进行(随机)梯度下降来学习。对于逻辑回归,我们首先将对数似然定义为负对数似然,然后将损失函数定义为负对数似然。

    $ heta$是模型的参数,使用随机梯度下降可以对损失函数进行优化:$frac{partial logp(x^{(i)})}{partial heta}$

    # 实现受限玻尔兹曼机,暂仅考虑可视层、隐藏神经元取值均为二进制的情况
    import numpy as np
    import os
    
    
    def sigmoid(z):
        return 1 / (1 + np.exp(-z))
    
    
    class RBM:
        def __init__(self, n_visible, n_hidden):
            self.n_visible = n_visible #可见层节点数量
            self.n_hidden = n_hidden #隐藏层节点数量
            self.bias_a = np.zeros(self.n_visible)  #可视层偏移量
            self.bias_b = np.zeros(self.n_hidden)  #隐藏层偏移量
            self.weights = np.random.normal(0, 0.01, size=(self.n_visible, self.n_hidden))
            self.n_sample = None
    
         # 编码,即基于v计算h的条件概率:p(h=1|v)
        def encode(self, v):
            return sigmoid(self.bias_b + v @ self.weights)
    
         # 解码(重构):即基于h计算v的条件概率:p(v=1|h)
        def decode(self, h):
            return sigmoid(self.bias_a + h @ self.weights.T)
    
        # gibbs采样, 返回max_cd采样后的v以及h值
        def gibbs_sample(self, v0, max_cd):       
            v = v0
            for _ in range(max_cd):
                # 首先根据输入样本对每个隐藏层神经元采样。二项分布采样,决定神经元是否激活
                ph = self.encode(v)
                h = np.random.binomial(1, ph, (self.n_sample, self.n_hidden))
                # 根据采样后隐藏层神经元取值对每个可视层神经元采样
                pv = self.decode(h)
                # print(h)
                # print(pv)
                # print(max_cd)
                # os.system("pause")
                v = np.random.binomial(1, pv, (self.n_sample, self.n_visible))
            return v
    
        # 根据Gibbs采样得到的可视层取值(解码或重构),更新参数
        def update(self, v0, v_cd, eta):
            # print(v0)
            # os.system("pause")
            ph = self.encode(v0)
            ph_cd = self.encode(v_cd)
            # print(v0.T)
            # print(ph)
            # os.system("pause")
            self.weights += eta * (v0.T @ ph - v_cd.T @ ph)  # 更新连接权重参数
            self.bias_b += eta * np.mean(ph - ph_cd, axis=0)  # 更新隐藏层偏移量b
            self.bias_a += eta * np.mean(v0 - v_cd, axis=0)  # 更新可视层偏移量a
            return
    
    
        """
            训练主函数,采用对比散度算法(CD算法)更新参数
            :param data: 训练数据集, (n_sample, n_input)
            :param max_step: 最大迭代步数
            :param max_cd: 采样步数
            :param eta: 学习率
            :return:
        """
        def fit(self, data, max_step=100, max_cd=2, eta=0.1):
            assert data.shape[1] == self.n_visible, "输入数据维度与可视层神经元数目不相等"
            self.n_sample = data.shape[0]
            for i in range(max_step):
                #v_cd 是反采样后的输入样本
                v_cd = self.gibbs_sample(data, max_cd)
                self.update(data, v_cd, eta)
                error = np.sum((data - v_cd) ** 2) / self.n_sample / self.n_visible * 100
                if not i % 100:  # 将重构后的样本与原始样本对比计算误差
                    print("可视层状态误差比例:{0}%".format(round(error, 2)))
            return
    
    
    
        def predict(self, v):
            # 输入训练数据,预测隐藏层输出
            ph = self.encode(v)[0]
            states = ph >= np.random.rand(len(ph))
            return states.astype(int)
    
    
    if __name__ == '__main__':
        rbm_model = RBM(n_visible=6, n_hidden=2)
        train_data = np.array([[1, 1, 1, 0, 0, 0], [1, 0, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0],
                               [0, 0, 1, 1, 1, 0], [0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0]]) 
        rbm_model.fit(train_data, max_step=1000, max_cd=1, eta=0.1)
        print(rbm_model.weights, rbm_model.bias_a, rbm_model.bias_b)
        user = np.array([[0, 0, 0, 1, 1, 0]])
        print(rbm_model.predict(user))
    """
    该数据的含义:
    每个样本对应一个用户对6部电影的评分,简化为0(不好看)和1(好看),
    6部电影分别属于奥斯卡获奖影片和奇幻影片,对应两个潜在因子,即2个隐藏层神经元,
    据此可以判定用户的电影喜好类别。
    """
  • 相关阅读:
    Markdown自动生成目录
    defer使用小结
    RESTful API设计的点
    总结下数据库的命名规范
    go module学习笔记
    golang环境安装和配置
    jenkins环境搭建&配置(二)
    mac环境搭建selenium
    sed命令
    测试工作遇到的自动补0
  • 原文地址:https://www.cnblogs.com/xiaochi/p/12576120.html
Copyright © 2020-2023  润新知