Machine learning 应用softmax后获得NAN

Machine learning 应用softmax后获得NAN,machine-learning,deep-learning,pytorch,Machine Learning,Deep Learning,Pytorch,我尝试使用以下教程开发一个深层马尔可夫模型: 该模型使用神经网络对跃迁和发射进行参数化,对于变分推理部分,他们使用RNN将可观测的“x”映射到潜在空间。为了确保他们的模型学习到一些东西,他们尝试最大化ELBO或最小化负ELBO。他们将负ELBO称为NLL 我基本上是将pyro代码转换为纯Pytork。我把几乎所有的东西都放在一起了。然而,现在我想在测试序列上得到一个重构错误。我的输入是序列的一个热编码,其形状为(5001900,4),其中4表示特征数量,1900表示序列长度,500表示示例总数

我尝试使用以下教程开发一个深层马尔可夫模型:

该模型使用神经网络对跃迁和发射进行参数化,对于变分推理部分,他们使用RNN将可观测的“x”映射到潜在空间。为了确保他们的模型学习到一些东西,他们尝试最大化ELBO或最小化负ELBO。他们将负ELBO称为NLL

我基本上是将pyro代码转换为纯Pytork。我把几乎所有的东西都放在一起了。然而,现在我想在测试序列上得到一个重构错误。我的输入是序列的一个热编码,其形状为(5001900,4),其中4表示特征数量,1900表示序列长度,500表示示例总数

我生成数据的方式是:

生成模型p(x_{1:T}z_{1:T})p(z_{1:T})
批次大小,u,x_dim=x.size()#我们需要在小批次中处理的时间步数
T_max=x_lens.max()
z_prev=self.z_0.expand(批处理大小,self.z_0.size(0))#设置z_prev=z_0以设置p(z_t|z_{t-1}中的递归条件
对于范围内的t(1,t_max+1):
#一次一个时间步长的样本z_t~p(z_t | z_{t-1})
z_t,z_mu,z_logvar=self.trans(z_prev)#p(z_t | z_{t-1})
p_x_t=F.softmax(self.emitter(z_t),dim=-1)#计算参数化伯努利似然的概率
安全张量=torch.where(torch.isnan(p_x_t),torch.zero_like(p_x_t),p_x_t)
打印('generate p_x_t:',safe_tensor)
x_t=火炬。伯努利(安全张量)#根据伯努利分布p(x_t | z|t)观察样本x_t
打印('generate x\u t:',x\u t)
z_prev=z_t
所以我的排放量是由伯努利分布定义的。我用softmax来计算概率,参数化伯努利概率。然后我根据伯努利分布对观测值x_t进行采样

起初,当我运行我的模型时,我有时会得到NaN,因此我引入了行(如下所示),以便将NaN转换为零:

safe_tensor=torch.where(torch.isnan(p_x_t),torch.zero_like(p_x_t),p_x_t)
然而,在我采样的1个历元左右的x_t之后,这个张量就是零。基本上,我想要的是,在应用softmax之后,我想要我的函数选择最高的概率,并给我相应的标签,这是4个特性中的一个。但我得到了NaN,然后当我把所有的NaN都转换成零时,我得到了所有张量中的所有零,大约在1个历元之后

另外,当我看p_x_t张量时,我得到的概率加起来是一。但当我看x_t张量时,它一直给我0。例如:

p_x_t:tensor([[0.2168,0.2309,0.2555,0.2967]
..…],device='cuda:0',
grad_fn=)
生成x_t:tensor([[0,0,0,0.]),。。。
],device='cuda:0',grad\u fn=)
这里的第四个标签/功能给了我最大的可能性。x_t张量在这个位置上不应该至少给我1吗,就像:

生成x_t:tensor([[0,0,0,1.]),。。。
],device='cuda:0',grad\u fn=)
我怎样才能解决这些问题

编辑

我的转换(在上述生成函数中称为self.trans):

类网关转换(nn.Module):
"""
参数化高斯潜跃迁概率`p(z_t | z_{t-1})`
比较请参见参考资料第5节。
"""
定义初始值(自、z尺寸、trans尺寸):
super(GatedTransition,self)。\uuuu init\uuuuu()
self.gate=nn.Sequential(
nn.线性(z_dim,trans_dim),
nn.ReLU(),
nn.线性(横向尺寸,z尺寸),
nn.Softmax(尺寸=-1)
)
自建议_平均值=nn.序贯(
nn.线性(z_dim,trans_dim),
nn.ReLU(),
nn.线性(横向尺寸,z尺寸)
)           
self.z_to_mu=nn.Linear(z_dim,z_dim)
#将z_的默认初始化修改为_mu,使其作为标识函数启动
self.z_to_mu.weight.data=火炬眼(z_dim)
self.z_to_mu.bias.data=火炬零点(z_dim)
self.z_to_logvar=nn.Linear(z_dim,z_dim)
self.relu=nn.relu()
def前进(自,z_t_1):
"""
给定对应于时间步长t-1的潜在'z_{t-1}'
我们返回参数化(对角)高斯分布`p(z_t|z_{t-1})的平均值和尺度向量`
"""        
gate=self.gate(z_t_1)#计算选通函数
建议的平均值=自我。建议的平均值(z_t_1)#计算“建议的平均值”
mu=(1-门)*self.z_to_mu(z_t_1)+门*建议的平均值#使用来自
logvar=self.z_to_logvar(self.relu(建议的平均值))
epsilon=torch.randn(z_t_1.size(),device=z_t_1.device)#通过重新参数化对z进行采样
z_t=mu+epsilon*torch.exp(0.5*logvar)#[batch_sz x z_sz]
如果torch.isinf(z_t).any().item():
打印(‘某物是无限的’)
打印('z_t:',z_t)
打印('logvar:',logvar)
打印('epsilon:',epsilon)
打印('mu:',mu)
返回z_t,mu,logvar
在进行培训和验证时,我没有得到z_t张量的任何信息。仅在测试期间。这就是我培训、验证和测试模型的方式:


对于范围内的历元(配置['epochs']):
train\u loader=torch.utils.data.DataLoader(dataset=train\u set,batch\u size=config['batch\u size'],shuffle=True,num\u workers=1)
列车数据iter=iter(列车装载机)
n_iters=列车数据_iter.uuu len_uu()
epoch_nll=0.0#累加器,用于我们对该epoch的负对数似然(或者更确切地说是-elbo)的估计
i_批次=1
n_切片=0
丢失记录={}
尽管如此:
try:x,x_rev,x_lens=train_data_iter.next()