在 numpy 中乘以对数概率矩阵的数值稳定方法

2024-02-17

我需要获取包含对数概率的两个 NumPy 矩阵(或其他二维数组)的矩阵乘积。天真的方式np.log(np.dot(np.exp(a), np.exp(b)))由于明显的原因而不是首选。

Using

from scipy.misc import logsumexp
res = np.zeros((a.shape[0], b.shape[1]))
for n in range(b.shape[1]):
    # broadcast b[:,n] over rows of a, sum columns
    res[:, n] = logsumexp(a + b[:, n].T, axis=1) 

可以工作,但运行速度比np.log(np.dot(np.exp(a), np.exp(b)))

Using

logsumexp((tile(a, (b.shape[1],1)) + repeat(b.T, a.shape[0], axis=0)).reshape(b.shape[1],a.shape[0],a.shape[1]), 2).T

或者其他平铺和重塑的组合也可以工作,但运行速度甚至比上面的循环还要慢,因为实际大小的输入矩阵需要大量的内存。

我目前正在考虑用 C 编写一个 NumPy 扩展来计算这个,但我当然宁愿避免这种情况。是否有一种既定的方法可以做到这一点,或者有人知道执行此计算的内存密集程度较低的方法吗?

EDIT:感谢 larsmans 提供的这个解决方案(推导见下文):

def logdot(a, b):
    max_a, max_b = np.max(a), np.max(b)
    exp_a, exp_b = a - max_a, b - max_b
    np.exp(exp_a, out=exp_a)
    np.exp(exp_b, out=exp_b)
    c = np.dot(exp_a, exp_b)
    np.log(c, out=c)
    c += max_a + max_b
    return c

将此方法与上面发布的方法进行快速比较(logdot_old)使用 iPython 的魔力%timeit函数产生以下结果:

In  [1] a = np.log(np.random.rand(1000,2000))

In  [2] b = np.log(np.random.rand(2000,1500))

In  [3] x = logdot(a, b)

In  [4] y = logdot_old(a, b) # this takes a while

In  [5] np.any(np.abs(x-y) > 1e-14)
Out [5] False

In  [6] %timeit logdot_old(a, b)
1 loops, best of 3: 1min 18s per loop

In  [6] %timeit logdot(a, b)
1 loops, best of 3: 264 ms per loop

显然拉斯曼的方法抹杀了我的方法!


logsumexp通过计算等式右侧的值来工作

log(∑ exp[a]) = max(a) + log(∑ exp[a - max(a)])

即,它在开始求和之前取出最大值,以防止溢出exp。在进行向量点积之前也可以应用同样的方法:

log(exp[a] ⋅ exp[b])
 = log(∑ exp[a] × exp[b])
 = log(∑ exp[a + b])
 = max(a + b) + log(∑ exp[a + b - max(a + b)])     { this is logsumexp(a + b) }

但通过在推导中采取不同的方式,我们得到

log(∑ exp[a] × exp[b])
 = max(a) + max(b) + log(∑ exp[a - max(a)] × exp[b - max(b)])
 = max(a) + max(b) + log(exp[a - max(a)] ⋅ exp[b - max(b)])

最终形式的内部有一个向量点积。它也很容易扩展到矩阵乘法,所以我们得到了算法

def logdotexp(A, B):
    max_A = np.max(A)
    max_B = np.max(B)
    C = np.dot(np.exp(A - max_A), np.exp(B - max_B))
    np.log(C, out=C)
    C += max_A + max_B
    return C

这创建了两个A大小的临时体和两个B- 大小的,但每一个都可以通过以下方式消除

exp_A = A - max_A
np.exp(exp_A, out=exp_A)

类似地对于B。 (如果函数可以修改输入矩阵,则可以消除所有临时矩阵。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 numpy 中乘以对数概率矩阵的数值稳定方法 的相关文章

随机推荐

  • Jquery Datepicker 更改月份后触发(月份渲染后)

    我想强调一下本月的一些日子 我可以在第一个月执行此操作 但不能在单击 下个月 或 上个月 后的新月份执行此操作 我尝试使用 onChangeMonthYear 事件 但这在新的 或上一个 月份呈现之前执行 有任何想法吗 也许你最好的选择是b
  • Windbg:psscor4 不起作用

    我搜索并尝试了很多东西 但无法让 psscor4 正常工作 当我调用 threads 我总是得到 请求ThreadStore失败 我检查的内容如下 我有一个为 X86 平台编译的 NET 4 应用程序 我使用的是Windbg版本6 2 92
  • 两组之间均匀分布的数字 (Vectorize LINSPACE) - MATLAB

    如何定义矩阵M根据M a b a 5 b from a to b分 5 步 当a and b是向量或集合 更具体地说 每一行i in M第一个值应该等于a i 和最后的值b i 其间有 5 个相等的步骤 例如 如果我有 a 0 b 10 0
  • 如何将两个 PDF 页面拼接在一起成为一张大页面?

    我有两张 36 x 48 海报 LaTeX 我想将其附加到一张 72 x 48 海报中 垂直堆叠 浏览 SO 和 GS 文档 我没有任何线索 我不是 CLI 向导 我怎样才能做到这一点 此外 该过程不应有损地压缩光栅图像 因为这将以 240
  • switch 似乎比 if 慢

    我很好奇速度switch 相信它 非常 快 但我有一个测试用例 似乎表明单个开关的速度大约与 4 一样快if测试 当我预期 没有充分的理由 它会像 1 次测试一样快 这是我写的两个方法来比较switch with if public sta
  • 挑选一个删除文件的提交

    我需要合并几个存储库 每个存储库都是从TFS http en wikipedia org wiki Team Foundation Server 合而为一 为此 我使用 gitcherry pick 命令 该命令适用于某些提交 但不适用于其
  • 缺少 Google 地图 API V2 google-play-services_lib.jar

    I just imported an example of the google map api V2 for android to test It s missing the google play services lib jar I
  • 按 xml 字母顺序对数据进行排序

    输入 XML
  • 如何配置 django-uploadify 仅用于视频上传?

    我想用django uploadify https github com tstone django uploadify仅上传视频 我只希望它仅上传视频 所有类型的视频 或至少所有类型的流行视频格式 到目前为止 我添加了uploadify
  • 为什么将 (Object)null 结果转换为非空?

    我使用 java 7 并创建一个 varargs 方法 public class JavaApplicationTest param args the command line arguments public static void ma
  • R Markdown pdf部分彩色单元格背景(数据栏)

    Excel 有一个称为 数据栏 的功能 它允许根据具有相应长度的单元格值进行条件格式设置 此功能可以通过 R 中的 formattable 使用格式化程序和 color bar 来完成 然而 这样做的结果是一个 html 小部件 无法在 p
  • 为什么在目录上调用 File.listFiles 时可以返回 null?

    我正在创建一个 Android 应用程序 我想列出目录中的文件 我通过调用来做到这一点 File files path listFiles new CustomFileFilter path is a File对象 通过调用创建 File
  • 在三星设备上继续运行时异常:android.view.DisplayListCanvas.throwIfCannotDraw

    我在 Play 商店控制台上发生多次崩溃 我已经检查了可绘制文件夹中的所有图像 这对我来说似乎没问题 因为我怀疑这可能会导致问题 据报道 它主要在三星设备上崩溃 请指出发生了什么错误 对于背景图像 我也使用这个尺寸 高清 480 800 x
  • ngAnimate CSS 动画不适用于 ng-show 和 ng-hide

    DEMO http plnkr co edit cPDUWO p preview http plnkr co edit cPDUWO p preview 我在页面上显示了 2 个选中的复选框和 2 个小部件 单击复选框将使用ng show
  • 签署 F# 程序集(强名称组件)

    我在 CodeProject 上找到了这篇文章 http www codeproject com Articles 512956 NET Shell Extensions Shell Context Menus http www codep
  • python 中的“is”是如何工作的?

    请有人解释一下如何在 if 条件下使用 is 我正在使用分数模块 但遇到了一些麻烦 gt gt gt Fraction 0 1 is 0 False gt gt gt float Fraction 0 1 0 0 gt gt gt floa
  • 如何使用 IDisposable 修复内存泄漏

    我有一个 net 应用程序似乎存在内存泄漏问题 net 服务启动时大约需要 100MB 内存 但在负载下它会达到大约 400 500MB 我的大多数类都没有非托管资源 并且那些已经实现了 IDisposable 的类 所以我的问题是在我的课
  • 延迟加载加载图像后如何触发事件?

    我有需要绝对定位的图像 以便图像的中心位于其父 div 的中心 我已经有执行此操作的代码 我最近添加了延迟加载插件 它按预期工作 但我需要一种触发图像居中代码的方法after延迟加载已加载and图像淡入 我当前的代码基本上是这样的 jQue
  • 更改现有应用程序的证书指纹

    我有一个已发布到 Google Play 的现有应用程序 一切都很好 直到我换了一台电脑并且我的 sha1 指纹发生了变化 有没有可能的方法来更改 google play 开发者控制台中现有应用程序的 sha1 如果没有 我该如何处理 谢谢
  • 在 numpy 中乘以对数概率矩阵的数值稳定方法

    我需要获取包含对数概率的两个 NumPy 矩阵 或其他二维数组 的矩阵乘积 天真的方式np log np dot np exp a np exp b 由于明显的原因而不是首选 Using from scipy misc import log