我有一个mxn
矩阵A,有很小或很大的元素。举例来说:
A = -1e4*randn(10,20);
我想创建一个相同大小的新矩阵C,如下所示:
首先,定义一个矩阵B,它的元素是A的元素的指数:
B = exp(A)
然后,矩阵C被定义为使得C的每一列与B的对应列成比例,并且C的每一列的和等于1。换句话说,如果我们取B的一个元素,并将其除以相同列的所有元素之和,则我们获得C的相应元素:
C = bsxfun(@rdivide,B,sum(B));
数学上:
显然,C的所有元素都在0和1之间。然而,当使用以下代码进行计算时,所获得的矩阵包含许多NaN:
A = -1e4*randn(10,20);
B = exp(A);
C = bsxfun(@rdivide,B,sum(B));
sum(sum(isnan(ee)))
我希望有人能提出解决这个问题的方法。先谢谢你。
**更新:**请注意,目标是矩阵C。我定义矩阵B只是为了解释,我们可能不需要计算它。(其实我们不应该。正如@EJG89指出的,B只包含Inf和0)。
**更新2:**感谢@EJG89提供Log Sum of Exponentials technique的链接,可能会有用。我正在为我的问题寻找类似的分析技巧。
**更新3:**正如@Dan和@EJG89所建议的,我们可以用一个常数减去每一列,以获得一个合理范围内的新矩阵。很明显,我们有
对于任何常数C。我们可以选择C作为每列的最大值:
(a_{max,j}是第j列的最大值),则
我觉得这个选择可能会给给予一个很好的近似,但我不知道它有多好:|
新代码为:
A = bsxfun(@minus,A,max(A));
B = exp(A);
C = bsxfun(@rdivide,B,sum(B));
4条答案
按热度按时间qmb5sa221#
你想把 A 调整为新的 A',使得 eA = CeA',其中 C 是一个常数(远小于1)。换句话说,你要找一个 k,使得 k.eA 足够小,不会突破
ndoublemax
或eps
。但是我们想把 k 应用到 A 上,所以我们需要把它代入指数。k = eln(k) 和eln(k).eA =**eA + ln(k)**因此,如果我们从A
中增加或减少一个数,eA 会按比例影响。或 A' = A + ln(k)不幸的是,我认为你的范围对于任何 ln(k) 来说都太大了,无法阻止你违反Matlab双精度的限制。如果你加上一个大的数字,你会得到所有的
B
等于inf
,如果你减去一个大的数字,你会得到所有的B
等于零。所以你需要找到一些方法来同时处理大量的数字和分钟的数字。
lyfkaqu12#
在@EJG89的讨论之后,您可以用最大可表示数替换无限值,然后将
eps
添加到分母中的所有数字。这样就避免了Inf
。cnjp1d6j3#
一种方法可以是诉诸符号计算:
结果
C
以符号形式给出。例如,第一列将类似于但请注意,即使使用符号计算,最大的项也被给定为1,而实际上它(稍微)更小。当然,如果你转换成double,你只会得到0或1的值:
jvlzgdj94#
直接的方法是不可能的。
问题是B已经产生Inf或0。
投降是不可能的。
产生:
ndoublemax =
1.7977e+308
nsinglemax =
3.4028e+038
ndoublemin =
2.2251e-308
nsinglemin =
1.1755e-038
所以你对B的价值显然超过了那些价值。
可以通过重写指数using this blog post来进行近似
所以首先重写为:log(Cij)= log(exp(Aij)/sumk(exp(A(kj)
log(Cij)= Aij - log(sumk(exp(A(kj)
其中最后一项可以近似为:m = maxk(A(kj))
log(sumk(exp(A(kj)= m + log(exp(A(kj)-m))
这导致MatLab能够处理更小的值,即可以说是正常化。但仍然没有确切的答案,因为有些值变为零,消除了它们有时的重要贡献。