You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Equinox模块结合jax.lax.scan时遇ArrayImpl不可哈希错误

问题:Equinox模块传入jax.lax.scan时出现TypeError: unhashable type: 'ArrayImpl'

我是Equinox和JAX的新手,想用它们模拟动态系统。但把系统模型作为Equinox模块传入jax.lax.scan时,出现了TypeError: unhashable type: 'ArrayImpl'错误。我知道JAX要求函数参数为纯函数,原本以为Equinox模块能满足这个特性。以下是复现错误的测试脚本:

import equinox as eqx
import jax
import jax.numpy as jnp


class EqxModel(eqx.Module):
    A: jax.Array
    B: jax.Array
    C: jax.Array
    D: jax.Array

    def __call__(self, states, inputs):
        x = states.reshape(-1, 1)
        u = inputs.reshape(-1, 1)
        x_next = self.A @ x + self.B @ u
        y = self.C @ x + self.D @ u
        return x_next.reshape(-1), y.reshape(-1)


def simulate(model, inputs, x0):
    xk = x0
    outputs = []
    for uk in inputs:
        xk, yk = model(xk, uk)
        outputs.append(yk)
    outputs = jnp.stack(outputs)
    return xk, outputs


A = jnp.array([[0.7, 1.0], [0.0, 1.0]])
B = jnp.array([[0.0], [1.0]])
C = jnp.array([[0.3, 0.0]])
D = jnp.array([[0.0]])
model = EqxModel(A, B, C, D)

# 测试仿真,这部分正常运行
inputs = jnp.array([[0.0], [1.0], [1.0], [1.0]])
x0 = jnp.zeros(2)
xk, outputs = simulate(model, inputs, x0)
assert jnp.allclose(xk, jnp.array([2.7, 3.0]))
assert jnp.allclose(outputs, jnp.array([[0.0], [0.0], [0.0], [0.3]]))

# 这一行会抛出TypeError
xk, outputs = jax.lax.scan(model, x0, inputs)

问题答疑

1. unhashable type: 'ArrayImpl'指的是什么?

是的,这个错误里的ArrayImpl就是你定义的A、B、C、D这些JAX数组。JAX数组属于不可哈希类型,而jax.lax.scan要求传入的函数必须是纯函数,且函数依赖的闭包变量必须可哈希。直接把Equinox模块传给scan时,模块内的数组会被当作闭包变量处理,因为数组不可哈希,所以触发了这个错误。

2. 解决方法

因为你的模型参数(A/B/C/D)在仿真时是静态的,推荐用以下两种方法解决:

方法一:使用eqx.filter_scan(Equinox专门适配的scan)

Equinox提供了eqx.filter_scan,可以直接处理带参数的模块,不需要额外包装:

# 替换报错的scan调用为以下代码
xk, outputs = eqx.filter_scan(model, x0, inputs)
方法二:用lambda或partial包装函数,把模块作为参数传入

如果坚持用jax.lax.scan,可以把模块作为额外参数传入,避免闭包捕获不可哈希的数组:

from functools import partial

# 定义包装函数
def scan_step(model, states, inputs):
    return model(states, inputs)

# 使用partial绑定模型,再传入scan
xk, outputs = jax.lax.scan(partial(scan_step, model), x0, inputs)

或者用lambda简化:

xk, outputs = jax.lax.scan(lambda s, u: model(s, u), x0, inputs)

内容的提问来源于stack exchange,提问作者Bill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 23:48:12