【theano-windows】学习笔记十五——受限玻尔兹曼机

前言

终于到了最喜欢的模型: 受限玻尔兹曼机(RBM)了, 发现关于RBM是如何从能量模型发展过来的介绍非常不错, 而关于详细理论证明, 可以去看我前面的受限玻尔兹曼机的一系列博客.

国际惯例, 参考博客,超级强推第二个博客, 证明过程很给力:

Restricted Boltzmann Machines (RBM)

Contrastive divergence multi-layer RBMs

理论

基于能量的模型EBM

这个强烈去看看我前面的两篇关于概率有向图和概率无向图模型的博客, 很简短. 基于能量的模型是将所有的感兴趣变量与一个标量能量关联起来. 学习对应着修改能量函数, 而使其具有应有的结构. 我们也经常希望这个模型具有很低的能量. 至于为什么? 我们经常举的一个例子, 将一个小球放到碗里, 这个球最终基本都会停留在碗底, 为什么?当然是势能最低啦,这就是我们说的最小化能量函数。

基于能量的概率模型通过能量函数定义了一个概率分布:

p(x)=eE(x)Z

其中分母是归一化因子,与概率模型中的归一化因子意义相同
Z=xeE(x)

优化过程就是针对训练集上的负对数似然进行随机梯度下降法训练, 和logistics回归一样,我们先定义一个对数似然, 然后损失函数就是负对数似然
L(θ,D)=1Nx(i)Dlogp(x(i))loss=L(θ,D)

其中 θ是模型参数, D是训练集,最终更新方法依旧是梯度下降,针对模型参数求解logp(x(i))θ

具有隐层的能量模型

你以为所有的模型都有隐层么?想想马尔科夫模型是怎么发展到隐马尔科夫模型的吧. 千万不要有这个错误的想法:所有的模型都有隐层。

上面说过能量模型是定义一个概率分布, 与所有的感兴趣变量相关, 当我们加入了除了输入单元x之外的隐单元后, 整个模型的关于输入单元的概率分布就变成了关于所有隐单元的边缘分布了

p(x)=hp(x,h)=heE(x,h)Z

为了看起来与能量模型中的第一个式子看起来像是双胞胎, 引入了一个自由能函数

F(x)=logh(eE(x,h))

这样 p(x)就可以写成:
p(x)=eF(x)Z

其中 Z=xeF(x)

然后我们求一波导数:

logp(x)θ=(logeF(x)logZ)θ=(F(x)+logZ)θ=F(x)θeF(x^)ZF(x^)θ=F(x)θx^p(x^)F(x^)θ

注意这里为什么第一项是 x, 而第二项是x^ ?可以看上面第二个博客的证明, 也可以去看看我前面关于概率无向图模型的简介, 它是输入样本所有可能的情况. 这两项经常被称为 positive phasenegative phase, 我经常称作正向推断和反向重构, 它们反应的是对模型概率密度的影响. 第一项通过降低对应自由能量去增加训练集的概率, 而第二项降低了模型生成样本的概率.

由于第二项的存在, 我们很难直接去计算梯度, 它是关于输入的所有可能组合情况的期望, 第二项的简写表达式为Ep(F(x)θ), 这个其实就是期望的另外种表示. 既然无法知道所有的情况, 就可以利用采样的方法, 选取固定数量的模型样本估计这个期望值, 用于估计负相位梯度的样本称为负颗粒(negative particles),记为, 梯度的新写法就是:

logp(x)θF(x)θ1x^F(x^)θ

而这个固定数量的样本是如何选取的?一般来说用的是蒙特卡洛方法. 我前面有博客介绍过这个采样方法. 后面我们说的吉布斯采样也是属于马尔科夫链蒙特卡洛方法的一种.

玻尔兹曼机

随机变量X(观测变量)和隐变量H, 它们的联合分布是与能量函数有关的玻尔兹曼分布:

P(X=x,H=h)=eE(x,h)Z

其中归一化常量是:
Z=x,heE(x,h)

在一般的玻尔兹曼机中,能量函数是一个二次多项式( quadratic polynomial),因为模型中隐层和可见层之间, 以及它们各自的单元都互相连接, 说明它们被同等对待了, 那么假设 z=(x,h),那么,能量函数为
E(z)=E(x,h)=ibiziijziwijzjs.t.zi{0,1}

如果 X=x是观测的, H是隐藏的, 那么对数似然就是所有可能的H组合的和
P(X=x)=hP(X=x,H=h)=heE(x,h)Z

在非限制玻尔兹曼机中分子中的 h和分母中的x的求和是无法解决的问题, 因而它们的梯度也无法求得:
logP(x)θ=logheE(x,h)Zθ=(logheE(x,h)+logZ)θ=logheE(x,h)θ+logZθ

然后我们分别求第一项和第二项
logheE(x,h)θ=(1heE(x,h)heE(x,h)θ)=(1heE(x,h)h(eE(x,h)E(x,h)θ))=h(eE(x,h)heE(x,h)E(x,h)θ)=h(P(x,h)P(x)E(x,h)θ)=h(P(h|x)E(x,h)θ)

同理求第二项
logZθ=1ZZθ=1Zx,heE(x,h)θ=1Zx,h(eE(x,h)E(x,h)θ)=x,h(eE(x,h)ZE(x,h)θ)=x,h(p(x,h)E(x,h)θ)

所以最终的
logP(x)θ=h(P(h|x)E(x,h)θ)x,h(p(x,h)E(x,h)θ)

玻尔兹曼机是对数线性马尔科夫随机场的特定形式, 参数在能量中是线性的, 为了足以强大以表示复杂分布, 为其添加了隐变量, 具有更多隐单元使得玻尔兹曼机的建模能力更强。

限制玻尔兹曼机

能量相关内容

前面那个玻尔兹曼机是隐层和可见层之间和各自内部的单元之间都有连接, 也就是说所有的神经元之间都有连接, 那么如果让隐单元自己内部和可见层自己内部的单元连接权重为0, 其实也就是没连接的时候, 就成了限制玻尔兹曼机了. 它的好处在于在可见层单元X给定的情况下,各个隐单元Hi是相互独立的,反之也成立, 给定隐单元的时候, 可见层单元也相互独立。

给定输入vi和二项隐单元(binomial unit)hj,参数是(bj,Wj),分别代表隐单元的偏置和连接到隐单元j的权重向量, 那么就可以得到:

  • 能量函数:bjhjiviWijhj

    • P(hj=1|v)=ebj+iWijvi1+ebj+iWijvi=sigmoid(bj+iWijvi)
    • 如果给定的是固定方差的高斯单元hj, 参数为(aj,bj,Wj), 那么也可以得到

      • 能量函数: a2jh2jbjhjiviWijhj
      • P(hj|v)=1Zea2jh2j+bjhj+iviWijhj=1Ze(bjμ)22σ2
        P(hj|v)=N(hj;μ,σ2) with σ2=12a2j,μ=bj+iviWij2a2j

      a特别小的时候, 会容易崩掉(blow up), 因而经常使用a+ϵ代替a

      对于softmax输出单元hj,参数为(Wij,bj):

      • 能量函数: bjhjiviWijhj
      • P(hj=1|v)=ebj+iWijvijebj+iWijvi=softmax(bj+iWijvi)

      参数更新方法如下:

      假设归一化常量为Z=x,yeE(x,y), 那么

      P(x,y)P(y|x)=eE(x,y)Z=eE(x,y)yeE(x,y)

      对于任意的能量函数,我们都可以推导出:
      logP(x)θ=logyP(x,y)θ=logyeE(x,y)Zθ=ZyeE(x,y)yeE(x,y)Zθ=ZyeE(x,y)y(eE(x,y)E(x,y)θZ)yeE(x,y)ZθZ2=y(eE(x,y)yeE(x,y)E(x,y)θ)+1ZZθ=yP(y|x)E(x,y)θxyP(x,y)E(x,y)θ=E[E(x,y)θx]E[E(x,y)θ]

      在使用对比散度算法做梯度更新的时候:

      二值输入与二值输出的时候:

      • 权重更新
        • 正向阶段贡献: P(y0j=1|x0)×1×x0i+(1P(y0j=1|x0))×0×x0i=P(y0j=1|x0)x0i
        • 反向阶段共享:P(y1j=1|x1)×1×x1i+(1P(y1j=1|x1))×0×x1i=P(y1j=1|x1i)x1i
      • 偏置更新
        • 正向阶段贡献:P(y0i=1|x0)
        • 反向阶段贡献:P(y1i=1|x1)

      高斯输入与二值输出的时候:

      • 权重和偏置更新同上
      • 参数aj:
        • 正向阶段贡献:2ai(x0i)2
        • 反向阶段贡献:2ai(x1i)2

      二值输入和softmax输出的时候:

      • 与二值情况相同, 只不过P(yi=1|x)使用的是softmax而非sigmoid

      理论梳理

      前面可能说的有点乱, 下面直接按照教程梳理一下玻尔兹曼机的参数更新过程. 假设:

      • 可见层V={v0,v1,,vj,},偏置b={b1,b2,,bj,}
      • 隐藏层H={h1,h2,,hi,}, 偏置c=c1,c2,,ci,
      • 连接权重为W={w11,w12,,wji,}

      那么能量函数为:

      E(v,h)=bvchhWv

      自由能函数为
      F(v)=loghieE(v,h)=bviloghiehi(ci+wiv)

      特别地, 在二值RBM中, 经常通过以下激活函数得到神经元的激活概率:
      P(hi=1|v)=sigmoid(ci+Wiv)P(vj=1|h)=sigmoid(bj+Wjh)

      然后自由能函数简化为:
      F(v)=bviloghiehi(ci+wiv)=bvilog{e0(ci+wiv)+e1(ci+wiv)}=bvilog(1+e(ci+wiv))

      梯度更新方法为:
      logP(v)WijlogP(v)bjlogP(v)ci=Ev[p(hi|v)vj]v(i)jsigmoid(Wiv(i)+ci)=Ev[p(vj|h)v(i)j]=Ev[p(hi|v)]sigmoid(Wiv(i))

      判别式玻尔兹曼机

      当玻尔兹曼机用于分类的时候,假设:

      • 输入单元为P,索引j
      • 隐单元为L,索引i,偏置为C
      • 标签单元为Y,索引k, 偏置为B
      • 输入单元和隐单元的连接权重为V
      • 输出单元和隐单元的连接权重为W

      那么输入单元与隐单元的能量函数为VijPjLiCiLi,

      输出单元和隐单元的能量函数为WikYkLiBkYk

      标签y的计算与输入P相关, 而非隐单元L

      active(Yk)=Bk+isoftplus(Wki+Ci+j(Vijp(Pj))

      其中softplus(x)=log(1+ex)

      那么输出

      P(Yinputs)=softmax(active(Y))

      训练过程:

      第一种方法是直接梯度下降:

      • 计算cost=logP(Y=onehot(k)inputs)

      第二种方法是对比散度(contrastive divergence):

      • X=[Y,P]当做一个大的层
      • x=[onehot(k),p(P)]作为隐层的输入
      • (X,L)当做RBM训练

      关于这一部分可以看前面的一个博客判别模型的玻尔兹曼机论文源码解读

      代码

      训练

      【注】此代码是为了更加方便理解而对官方教程代码进行了理解后的修改, 建议看完以后立即去看标准的官方教程

      首先引入必要的库文件

      import numpy as np
      import theano
      import theano.tensor as T
      from theano.tensor.shared_randomstreams import RandomStreams
      import cPickle,gzip
      from PIL import Image
      import pylab
      import os

      随后是读数据集的函数

      #定义读数据的函数,把数据丢入到共享区域
      def load_data(dataset):data_dir,data_file=os.path.split(dataset)if os.path.isfile(dataset):with gzip.open(dataset,'rb') as f:train_set,valid_set,test_set=cPickle.load(f)#共享数据集def shared_dataset(data_xy,borrow=True):data_x,data_y=data_xyshared_x=theano.shared(np.asarray(data_x,dtype=theano.config.floatX),borrow=borrow)shared_y=theano.shared(np.asarray(data_y,dtype=theano.config.floatX),borrow=borrow)return shared_x,T.cast(shared_y,'int32')#定义三个元组分别存储训练集,验证集,测试集train_set_x,train_set_y=shared_dataset(train_set)valid_set_x,valid_set_y=shared_dataset(valid_set)test_set_x,test_set_y=shared_dataset(test_set)rval=[(train_set_x,train_set_y),(valid_set_x,valid_set_y),(test_set_x,test_set_y)]return rval

      接下来就是定义整个RBM模型:

      • 首先是初始化该有的权重和偏置,一个权重两个偏置, numpy的随机函数用于初始化权重和偏置, theano的随机函数用于将神经元按照概率激活为二值单元

        
        #定义RBMclass RBM(object):def __init__(self,rng=None,trng=None,input=None,n_visible=784,n_hidden=500,W=None,hbias=None,vbias=None):self.n_visible=n_visibleself.n_hidden=n_hiddenif rng is None:rng=np.random.RandomState(1234)if trng is None:trng=RandomStreams(rng.randint(2**30))#初始化权重和偏置    if W is None:initW=np.asarray(rng.uniform(low=-4*np.sqrt(6./(n_hidden+n_visible)),high=4*np.sqrt(6./(n_hidden+n_visible)),size=(n_visible,n_hidden)),dtype=theano.config.floatX)W=theano.shared(value=initW,name='W',borrow=True)if hbias is None:inithbias=np.zeros(n_hidden,dtype=theano.config.floatX)hbias=theano.shared(value=inithbias,name='hbias',borrow=True)if vbias is None:initvbias=np.zeros(n_visible,dtype=theano.config.floatX)vbias=theano.shared(value=initvbias,name='vbias',borrow=True)self.input=inputif not input:self.input=T.matrix('input')self.W=Wself.hbias=hbiasself.vbias=vbiasself.trng=trngself.params=[self.W,self.hbias,self.vbias]
      • 为了进行吉布斯采样, 我们需要定义positive phasenegative phase
        前向计算过程: 可见层->隐层

          ##########前向计算,从可见层到隐层#################激活概率def propup(self,vis):pre_sigmoid_activation=T.dot(vis,self.W)+self.hbiasreturn [pre_sigmoid_activation,T.nnet.sigmoid(pre_sigmoid_activation)]#二值激活def sample_h_given_v(self,v0_samples):pre_sigmoid_h1,h1_mean=self.propup(v0_samples)h1_sample=self.trng.binomial(size=h1_mean.shape,n=1,p=h1_mean,dtype=theano.config.floatX)return [pre_sigmoid_h1,h1_mean,h1_sample]
      • 反向计算:隐层->可见层

          ##########反向计算,从隐层到可见层#################激活概率def propdown(self,hid):pre_sigmoid_activation=T.dot(hid,self.W.T)+self.vbiasreturn [pre_sigmoid_activation,T.nnet.sigmoid(pre_sigmoid_activation)]#二值激活def sample_v_given_h(self,h0_samples):pre_sigmoid_v1,v1_mean=self.propdown(h0_samples)v1_sample=self.trng.binomial(size=v1_mean.shape,n=1,p=v1_mean,dtype=theano.config.floatX)return [pre_sigmoid_v1,v1_mean,v1_sample]
      • 一次吉布斯采样: 可见层->隐层->可见层

          ##########吉布斯采样#################可见层->隐层->可见层def gibbs_vhv(self,v0_samples):pre_sigmoid_h1,h1_mean,h1_sample=self.sample_h_given_v(v0_samples)pre_sigmoid_v1,v1_mean,v1_sample=self.sample_v_given_h(h1_sample)return [pre_sigmoid_v1,v1_mean,v1_sample,pre_sigmoid_h1,h1_mean,h1_sample]
      • 从第二章节: 具有隐层的能量模型来看, 梯度更新就是对自由能量函数球梯度, 当然如果我们自己写梯度的话,可以按照RBM理论梳理中来做, 事实上在matlab就是这样玩的, 手动写梯度更新方法, 而theano提供了自动求导方法, 所以我们就直接定义自由能函数, 然后对其求导即可
        自由能量函数的定义:

        
        ############自由能量函数###############def free_energy(self,v_samples):wx_b=T.dot(v_samples,self.W)+self.hbiasvbias_term=T.dot(v_samples,self.vbias)#第一项hidden_term=T.sum(T.log(1+T.exp(wx_b)),axis=1)#第二项return -hidden_term-vbias_term

        然后是梯度更新

          ############梯度更新#################def get_cost_updates(self,lr=0.1,k=1):([pre_sigmoid_nvs,nv_means,nv_samples,pre_sigmoid_nhs,nh_means,nh_samples],updates)=\theano.scan(self.gibbs_vhv,outputs_info=[None,None,self.input,None,None,None],n_steps=k,name='gibbs_vhv')chain_end=nv_samples[-1]cost=T.mean(self.free_energy(self.input))-T.mean(self.free_energy(chain_end))gparams=T.grad(cost,self.params,consider_constant=[chain_end])for gparam,param in zip(gparams,self.params):updates[param]=param-gparam*T.cast(lr,dtype=theano.config.floatX)##################期望看到交叉熵损失##############monitor_cost=self.get_reconstruction_cost(pre_sigmoid_nvs[-1])return monitor_cost,updates

        当然我们看到了一个函数叫get_reconstruction_cost, 想想RBM是干什么? 是模型的估计出来的样本分布和真实样本分布更加接近, 而度量这个的最好方法就是交叉熵了, 这就是我们在更新的时候希望看到的类似于loss的东东:

          ########非持续性对比散度,重构误差#########def get_reconstruction_cost(self,pre_sigmoid_nv):cross_entropy=T.mean(T.sum(self.input*T.log(T.nnet.sigmoid(pre_sigmoid_nv))+\(1-self.input)*T.log(1-T.nnet.sigmoid(pre_sigmoid_nv)),axis=1))return cross_entropy

        接下来我们就可以训练了, 一下采用15次CD算法训练(虽然一次就已经足够了)

        
        #初始化并训练玻尔兹曼机def test_rbm(learning_rate=0.1,training_epochs=15,dataset='mnist.pkl.gz',batch_size=20,n_chains=20,n_samples=10,n_hidden=500):#读取数据集datasets=load_data(dataset)train_set_x,train_set_y=datasets[0]test_set_x,test_set_y=datasets[2]n_train_batches=train_set_x.get_value(borrow=True).shape[0]//batch_sizeindex=T.lscalar()x=T.matrix('x')rng=np.random.RandomState(1234)trng=RandomStreams(rng.randint(2**30))#初始化一个RBM实例rbm=RBM(input=x,n_visible=28*28,n_hidden=n_hidden,rng=rng,trng=trng)#更新参数cost,updates=rbm.get_cost_updates(lr=learning_rate,k=15)#训练RBMtrain_rbm=theano.function([index],cost,updates=updates,givens={x:train_set_x[index*batch_size:(index+1)*batch_size]},name='train_rbm')for epoch in range(training_epochs):mean_cost=[]for batch_index in range(n_train_batches):mean_cost+=[train_rbm(batch_index)]print ('Training epoch %d,cost is ' % epoch,np.mean(mean_cost))save_file=open('best_model_rbm.pkl','wb')model=rbm.paramsl=[model[0].get_value(),model[1].get_value(),model[2].get_value()]cPickle.dump(l,save_file)

        接下来看看训练及结果

        test_rbm()
        '''
        ('Training epoch 0,cost is ', -221.54436)
        ('Training epoch 1,cost is ', -193.33549)
        ('Training epoch 2,cost is ', -188.36243)
        ('Training epoch 3,cost is ', -185.52127)
        ('Training epoch 4,cost is ', -183.83319)
        ('Training epoch 5,cost is ', -182.85869)
        ('Training epoch 6,cost is ', -181.76605)
        ('Training epoch 7,cost is ', -180.4059)
        ('Training epoch 8,cost is ', -179.306)
        ('Training epoch 9,cost is ', -178.59416)
        ('Training epoch 10,cost is ', -178.47371)
        ('Training epoch 11,cost is ', -177.25623)
        ('Training epoch 12,cost is ', -177.09161)
        ('Training epoch 13,cost is ', -176.70366)
        ('Training epoch 14,cost is ', -175.92307)
        '''

      测试

      先读一张图片, 还是使用之前教程用过的代码

      #取一张图片预测
      from PIL import Image
      import pylabdataset='mnist.pkl.gz'
      datasets=load_data(dataset)
      test_set_x,test_set_y=datasets[2]
      test_set_x=test_set_x.get_value()
      test_data=test_set_x[12:13]img=test_data.reshape(28,28)
      pylab.imshow(img)
      pylab.show()

      这里写图片描述

      初始化一个RBM, 并对参数赋值

      a=cPickle.load(open('best_model_rbm.pkl'))
      x=T.matrix('x')
      rbm_test=RBM(input=x,n_visible=28*28,n_hidden=500)
      rbm_test.params[0].set_value(a[0])
      rbm_test.params[1].set_value(a[1])
      rbm_test.params[2].set_value(a[2])

      执行1000次的吉布斯采样

      ([pre_sigmoid_nvs,nv_means,nv_samples,pre_sigmoid_nhs,nh_means,nh_samples],updates)=\theano.scan(rbm_test.gibbs_vhv,outputs_info=[None,None,x,None,None,None],n_steps=1000,name='gibbs_vhv')
      recon=nv_samples[-1]
      recon_fn=theano.function([x],recon,updates=updates)

      可视化看看结果

      b=recon_fn(test_data)
      b=b.reshape(28,28)
      pylab.imshow(b)
      pylab.show()

      这里写图片描述

      【注】若感觉程序有问题, 请反馈在评论区, 毕竟我是python
      code链接:链接: https://pan.baidu.com/s/1hsiYqNi 密码: wu2d

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246627.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Ogre-windows】环境配置

前言 由于工程原因, 学习一下Ogre面向对象图形渲染开源引擎, 慢慢爬坑吧。首先还是环境的配置问题哎. 其实最重要的是要预先编译三方库, 虽然官方说可以自动编译, 但是在自己电脑上还是出现了无法解析外部符号之类的问题, 正常情况下我就认为是三方库的lib出现了问题, 最后额外…

【theano-windows】学习笔记十六——深度信念网络DBN

前言 前面学习了受限玻尔兹曼机(RBM)的理论和搭建方法, 如果稍微了解过的人, 肯定知道利用RBM可以堆叠构成深度信念网络(deep belief network, DBN)和深度玻尔兹曼机(deep Boltzmann machine), 这里就先学习一下DBN. 国际惯例, 参考博文: Deep Belief Networks A fast lear…

【Ogre-windows】实例配置

前言 折腾了好久才搞定教程实例, 主要是因为上一篇博客安装的具体版本是Ogre1.10.9, 而官方的Ogre Wiki Tutorial Framework没有指定具体版本, 如果单纯下载Ogre Wiki Tutorial Framework 1.10 - (Windows line endings, updated 2015-10-15) 运行, 基本会血崩. 所以, 在经过仔…

【Ogre-windows】旋转矩阵及位置解析

前言 这篇博客主要针对三种问题 如何创建动画帧如何获取全局位置如何计算全局旋转矩阵 仿真环境为VS2013Ogre1.10.9与matlab验证 创建动画帧 这里只做一个简单的实验: 将自带的人物模型Jaiqua的run运动给新创建的运动myrun中并播放,直接贴代码了 void JaiQua:…

BP推导——续

前言 之前有证明过一次人工神经网络——【BP】反向传播算法证明 ,但是回头看的时候,有很多地方非常不严谨,特此拿出来再单独证明一次BP,并严格保证其严谨性。如果想看看粗略的证明,可以去看我之前的博客,毕…

matlab学习——强连通分量

前言 最近motion graph相关实验,发现实现运动过渡需要构建运动图,而为了避免运动过渡陷入死胡同,需要对图结构进行裁剪,方法就是计算图模型的极大强联通分量,但是自己懒得去实现,所以就去搜了一下matlab中…

【音频处理】离散傅里叶变换

前言 最近复现音乐驱动舞蹈的文章《Dancing-to-Music Character Animation》,用到了与傅里叶变换很相似的称为常Q变换的方法去分割音乐,所以对傅里叶变换做了一个小了解,本文不深入各种乱糟糟的理论,比如什么蝶形算法啥的&#x…

【音频处理】短时傅里叶变换

前言 上一篇博客讲了离散傅里叶变换,里面的实例是对整个信号进行计算,虽然理论上有N点傅里叶变换(本博客就不区分FFT和DFT了,因为它俩就是一个东东,只不过复杂度不同),但是我个人理解是这个N点是信号前面连续的N个数值…

【theano-windows】学习笔记十九——循环神经网络

前言 前面已经介绍了RBM和CNN了,就剩最后一个RNN了,抽了一天时间简单看了一下原理,但是没细推RNN的参数更新算法BPTT,全名是Backpropagation Through Time。 【注】严谨来说RNN有两个称呼:①结构上递归的recursive n…

【theano-windows】学习笔记二十——LSTM理论及实现

前言 上一篇学习了RNN,也知道了在沿着时间线对上下文权重求梯度的时候,可能会导致梯度消失或者梯度爆炸,然后我们就得学习一波比较常见的优化方法之LSTM 国际惯例,参考网址: LSTM Networks for Sentiment Analysis …

刚体运动学——欧拉角、四元数、旋转矩阵

前言 刚体运动旋转一般用:欧拉角、四元数、轴角对等表示,在对某个坐标旋转的时候,只需将欧拉角或四元数转换为旋转矩阵,并与原始坐标相乘,便可得到旋转以后的坐标。这里主要看看欧拉角、四元数和旋转矩阵。 国际惯例…

刚体运动学-四元数插值

前言 之前对写了一篇关于刚体运动学相关知识博客:刚体运动学——欧拉角、四元数、旋转矩阵,本篇博客就举例来说明,如何在运动捕捉数据中进行四元数插值。 国际惯例,参考博客: 探讨:向量(方向…

【TensorFlow-windows】学习笔记一——基础理解

前言 因为Theano已经停止更新了,所以在前面学完Theano搭建RBM,CNN,RNN相关结构以后,还是得选择一个主流框架的,由于我自身的学习最终是向强化学习靠近,可能用到的仿真环境是openai gym,所以选择了继续学习TensorFlow&…

【TensorFlow-windows】学习笔记二——低级API

前言 上一篇博客初步了解了tensorflow中建立机器学习模型的方法:可以使用eager execution和graph execution两种模式,可以使用高级API estimator中已经封装好的模型,也可以自己创建estimator,更重要的是我们也可以使用低级API自行…

【TensorFlow-windows】学习笔记五——自编码器

前言 上一篇博客介绍的是构建简单的CNN去识别手写数字,这一篇博客折腾一下自编码,理论很简单,就是实现对输入数据的重构,具体理论可以看我前面的【theano-windows】学习笔记十三——去噪自编码器 国际惯例,参考博客&…

【TensorFlow-windows】学习笔记六——变分自编码器

#前言 对理论没兴趣的直接看代码吧,理论一堆,而且还有点复杂,我自己的描述也不一定准确,但是代码就两三句话搞定了。 国际惯例,参考博文 论文:Tutorial on Variational Autoencoders 【干货】一文读懂…

【TensorFlow-windows】学习笔记七——生成对抗网络

前言 既然学习了变分自编码(VAE),那也必须来一波生成对抗网络(GAN)。 国际惯例,参考网址: 论文: Generative Adversarial Nets PPT:Generative Adversarial Networks (GANs) Generative Adversarial Nets in TensorFlow GAN原理学习笔记…

Openpose——windows编译(炒鸡简单)

前言 最近准备看看rtpose的代码,发现已经由openpose这个项目维护着了,由于经常在windows下调试代码,所以尝试了一下如何在windows下编译openpose源码,整体来说非常简单的。 国际惯例,参考博客: [OpenPos…

强化学习——Qlearning

前言 在控制决策领域里面强化学习还是占很重比例的,最近出了几篇角色控制的论文需要研究,其中部分涉及到强化学习,都有开源,有兴趣可以点开看看: A Deep Learning Framework For Character Motion Synthesis and Edit…

【TensorFlow-windows】keras接口学习——线性回归与简单的分类

前言 之前有写过几篇TensorFlow相关文章,但是用的比较底层的写法,比如tf.nn和tf.layers,也写了部分基本模型如自编码和对抗网络等,感觉写起来不太舒服,最近看官方文档发现它的教程基本都使用的keras API,这…