我尝试用一个阈值来应用softmax。就像,给定一个阈值,输出的总和仍然是1,但是每个值都低于阈值。
这是我当前的代码-我构建了剪辑模块来处理Softmax输出。然而,我收到下面的错误。我该怎么做才能让它工作?
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [200, 31]], which is output 0 of SoftmaxBackward0, is at version 3; expected version 0 instead. Hint: the backtrace further above shows the operation that failed to compute its gradient. The variable in question was changed in there or anywhere later. Good luck
个字符
2条答案
按热度按时间8cdiaqws1#
您在PyTorch中遇到的RuntimeError是由于
Clip
类中的一个inplace操作,特别是x[i] = new_x_i
。该操作修改了原始Tensorx
,PyTorch要求通过其计算图进行梯度计算时保持不变。要解决这个问题,请避免对
x
进行inplace修改;相反,使用一个新的Tensor并返回它。下面修改后的Clip类避免了inplace操作,从而防止了错误:字符串
ax6ht2ek2#
首先,检查你自己的代码。当你的代码发现一个值超过阈值的行时,它会替换阈值的值,但也会将所有其他值清零,我认为这不是你的意图。
你所描述的任务实际上很难有效地完成。也许如果你能提供更多关于为什么你需要这个的信息,我可以想出一个更好的解决方案。
为了说明为什么这是困难的,采取下面的代码。
给定一个输入
x
和一个threshold
,我们:1.计算原始softmax值
1.为
threshold
下的值创建threshold_mask
1.计算
under_threshold_sums
和over_threshold_sums
。under_threshold_sums
是我们要放大的低于阈值的当前总和。over_threshold_sums
将是在我们将它们裁剪到阈值之后的超过阈值的总和值1.将
rescale_values
计算为(1-over_threshold_sums)/(under_threshold_sums)
。假设我们有两个值超过0.3
的threshold
。这意味着这两个值将被裁剪为0.3
。裁剪后的两个超过阈值的值将0.6
贡献到总数中。这意味着我们希望缩放后的低于阈值的值之和为0.4
。因此形式为(1-over_threshold_sums)/(under_threshold_sums)
个1.计算
rescale_mask
。这个掩码在所有位置都有我们的rescale_values
,除了超过阈值的位置1.计算
scaled_softmax_vals
,方法是将阈值裁剪到threshold
,并按比例放大低于阈值的值,以便这些值的总和仍然为1。字符串
这一方法实现了:
1.将阈值限幅到阈值
1.缩放低于阈值的值,使得总softmax值的总和仍然为1
然而有一个问题。放大一个低于阈值的值可能会导致创建一个新的超过阈值的值。这就是为什么你的问题特别具有挑战性。你必须迭代地应用上面的代码,直到所有值都低于阈值,这可能没有收敛保证。
还有另一个问题,在softmax输出中有很多非常小的值(即0.99999...对于一个值,其他值都很小)将导致这种重新缩放产生nan。
我建议询问 * 为什么 * 你需要这种特定类型的softmax重新缩放,以及为什么更传统的方法,如温度缩放或标签平滑不适合你的需要。