[英]no method matching logpdf when sampling from uniform distribution
我正在尝试在 julia 中使用强化学习来教一辆不断向后加速(但初始速度为正)的汽车应用刹车,以便在向后移动之前尽可能接近目标距离。
为此,我正在使用具有许多求解器的POMDPs.jl
和crux.jl
(我正在使用 DQN)。 我将首先列出我认为是脚本的相关部分,然后在最后列出更多内容。
为了定义 MDP,我将初始 position、速度和刹车力设置为在某些值上的均匀分布。
@with_kw struct SliderMDP <: MDP{Array{Float32}, Array{Float32}}
x0 = Distributions.Uniform(0., 80.)# Distribution to sample initial position
v0 = Distributions.Uniform(0., 25.) # Distribution to sample initial velocity
d0 = Distributions.Uniform(0., 2.) # Distribution to sample brake force
...
end
我的 state 保存的值是(position, velocity, brake force)
,初始 state 给出为:
function POMDPs.initialstate(mdp::SliderMDP)
ImplicitDistribution((rng) -> Float32.([rand(rng, mdp.x0), rand(rng, mdp.v0), rand(rng, mdp.d0)]))
end
然后,我使用crux.jl
设置我的 DQN 求解器并调用 function 来求解策略
solver_dqn = DQN(π=Q_network(), S=s, N=30000)
policy_dqn = solve(solver_dqn, mdp)
调用solve()
给我错误MethodError: no method matching logpdf(::Distributions.Categorical{Float64, Vector{Float64}}, ::Nothing)
。 我很确定这来自最初的 state 采样,但我不确定为什么或如何修复它。 我只是在很短的时间内从各种书籍和在线讲座中学习 RL,因此对于错误或我设置的 model(或其他我没有注意到的任何东西)的任何帮助将不胜感激。
更全面的代码:
套餐:
using POMDPs
using POMDPModelTools
using POMDPPolicies
using POMDPSimulators
using Parameters
using Random
using Crux
using Flux
using Distributions
它的Rest:
@with_kw struct SliderMDP <: MDP{Array{Float32}, Array{Float32}}
x0 = Distributions.Uniform(0., 80.)# Distribution to sample initial position
v0 = Distributions.Uniform(0., 25.) # Distribution to sample initial velocity
d0 = Distributions.Uniform(0., 2.) # Distribution to sample brake force
m::Float64 = 1.
tension::Float64 = 3.
dmax::Float64 = 2.
target::Float64 = 80.
dt::Float64 = .05
γ::Float32 = 1.
actions::Vector{Float64} = [-.1, 0., .1]
end
function POMDPs.gen(env::SliderMDP, s, a, rng::AbstractRNG = Random.GLOBAL_RNG)
x, ẋ, d = s
if x >= env.target
a = .1
end
if d+a >= env.dmax || d+a <= 0
a = 0.
end
force = (d + env.tension) * -1
ẍ = force/env.m
# Simulation
x_ = x + env.dt * ẋ
ẋ_ = ẋ + env.dt * ẍ
d_ = d + a
sp = vcat(x_, ẋ_, d_)
reward = abs(env.target - x) * -1
return (sp=sp, r=reward)
end
function POMDPs.initialstate(mdp::SliderMDP)
ImplicitDistribution((rng) -> Float32.([rand(rng, mdp.x0), rand(rng, mdp.v0), rand(rng, mdp.d0)]))
end
POMDPs.isterminal(mdp::SliderMDP, s) = s[2] <= 0
POMDPs.discount(mdp::SliderMDP) = mdp.γ
mdp = SliderMDP();
s = state_space(mdp); # Using Crux.jl
function Q_network()
layer1 = Dense(3, 64, relu)
layer2 = Dense(64, 64, relu)
layer3 = Dense(64, length(3))
return DiscreteNetwork(Chain(layer1, layer2, layer3), [-.1, 0, .1])
end
solver_dqn = DQN(π=Q_network(), S=s, N=30000) # Using Crux.jl
policy_dqn = solve(solver_dqn, mdp) # Error comes here
简短的回答:
将您的 output 向量更改为Float32
即Float32[-.1, 0, .1]
。
长答案:
Crux 在您的网络的 output 值上创建一个Distribution
,并在某些时候 (policies.jl:298) 从中采样一个随机值。 然后它将这个值转换为Float32
。 后来 (utils.jl:15) 它执行findfirst
以在原始 output 数组(在分发中存储为objs
)中找到此值的索引,但由于原始数组仍然是Float64
,因此失败并返回nothing
。 因此错误。
我相信这(转换采样值而不是objs
数组)是一个错误,并鼓励您在 Github 上将此作为问题提出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.