神经网络-在Theano中训练MLP



我在尝试使用Theano训练一个非常标准的MLP模型时遇到了一些困难。我的型号代码看起来像这个

类层(对象):def __init__(self,inputs,n_in,n_out,activation=T.nnet.softmax):def权重(形状):返回np.array(np.arandom.uniform(size=shape),dtype='float64')def偏差(大小):返回np.zeros((大小),dtype='float64')自己W=无共享(值=权重((n_in,n_out)),名称="权重",借位=True)self.b=theano.shared(value=bias(n_out),name='biase',borrow=True)self.output=激活(T.dot(输入,self.W)+self.b)self.prod=T.argmax(self.out,轴=1)self.params=[self.W,self.b]MLP类(对象):def __init__(self,inputs,n_in,n_hidden,n_out):""现在让我们使用一个隐藏层""自我_hidden=层(输入,n_in,n_hidden,激活=T.tanh)自我_output=层(self._hidden.output,n_hidden,n_out)默认情况下#softmaxdef丢失(self,one_hot):返回T.mean(T.sqr(one_hot-self.output.output)def精度(self,y):返回T.mean(T.eq(self.output.pred,y))def更新(self,loss,rate=0.01):更新=[]updates.append((self._hidden.W,self._hididen.W-费率*T.grad(cost=loss,wrt=self._hiden.W))updates.append((self._hidden.b,self..hidden.b-速率*T.grad(cost=loss,wrt=self._hididen.b))updates.append((self.output.W,self.outoutput.W-费率*T.grad(cost=损失,wrt=self.output.W))updates.append((self.output.b,self.output.b-费率*T.grad(cost=损失,wrt=self.oututput.b))返回更新

然后我试着像这个一样训练它

x=T矩阵('x',dtype='float64')y=T矢量('y',dtype='t32')#基本物流模型#model=层(x,784,10,激活=T.nnet.softmax)#基本多层感知器模型=MLP(x,784,128,10)labels=T.extra_ops.to_one_hot(y,10)#损失函数#损失=T.mean(T.sqr(标签-型号输出))loss=型号损失(标签)#一批中正确预测的平均数#精度=T.mean(T.eq(model.pred,y))精度=模型精度(y)#更新#比率=0.05#g_W=T.grad(成本=损失,wrt=型号.W)#g_b=T.grad(成本=损失,wrt=模型.b)#updates=[(model.W,model.W-速率*g_W),#(model.b,model.b-速率*g_b)]updates=型号更新(损失,比率=0.3)#批处理索引index=T标量("匹配索引",dtype="t32")size=T标量("批量大小",dtype="t32")train=函数([索引,大小],[损失,准确性],updates=更新,givens={x:train_set[0][index*size:(index+1)*size],y: train_set[1][index*size:(index+1)*size]})valid=无函数([index,size],[损失,准确性],givens={x:valid_set[0][index*size:(index+1)*size],y: valid_set[1][index*size:(index+1)*size]})test=无函数([索引,大小],[准确度],givens={x:testronget[0][index*size:(index+1)*size],y: testronget[1][index*size:(index+1)*size]})n_历元=10batch_size=500#训练数据集中的项目数/批次大小batches_in_epoch=数据集[0][0].shape[0]//batch_size损耗=np.空(0)errors=np。empty(0)对于范围(1,n_epochs+1)中的epoch:划时代通行证=np.empty(0)划时代错误=np。空(0)对于范围内的batch_n(batches_in_epoch):l、 e=列车(batch_n,batch_size)划时代_长度=np.append(划时代_宽度,l)划时代错误=np.append(划时代错误,e)print('[%s]'%time.ctime(),'epoch:',epoch,'batch:',batch_n,'loss:',np.圆形(l,4),'精度:',np.圆(e,4))#每个历元打乱训练集shuffle=np.arange(数据集[0][1].shape[0])np.rrandom.shuffle(shuffle)train_set[0]=train_set[0][shuffle]train_set[1]=train_set[1][shuffle]loss=np.contenate([损失,划时代_损失])errors=np.contenate([errors,划时代错误])valid_l,valid_e=有效(0,数据集[1][0]。shape[0])print("[%s]"%time.ctime(),"epoch:",epoch,"验证丢失:",valid_l,"验证精度:",valid_e)acc=测试(0,数据集[2][0].shape[0])打印()print('最终精度:',np.圆形(acc,4)[0])

现在,如果你看看评论,我用一个基本的逻辑回归模型进行了尝试,它奏效了,我得到了大约80%的准确率。但当我用MLP模型替换它时,它就不起作用了。它不会收敛到任何东西,我得到10%的准确率随机猜测。我做错了什么?我使用的数据是像Theano教程那样加载到共享变量中的MNIST数据集。

问题似乎在于权重初始化。您是如何在tensorflow实现中做到这一点的?

我现在对底层数学不太确定,所以如果我错了,请纠正我,但我喜欢把它解释为,如果所有权重都是正的,那么模型就无法学习负特征。

您可以尝试将low=-1, high=1添加到初始化中(np.random.uniform的默认值介于0和1之间)。在我的测试中,这花了很长时间才收敛(大约100个时代),但至少它做到了。

使用更智能的glorot初始化,如下所示:

def weights(shape):
    return np.random.uniform(low=-np.sqrt(6. / sum(shape)),
                             high=np.sqrt(6. / sum(shape)),
                             size=shape)

使训练更快。在将其添加到您的代码中5个时期后,我获得了大约90%的验证准确率。

这也是非MLP示例中初始化权重的方式。

最新更新