【问题标题】:Consistent weighted mapping in RubyRuby 中的一致加权映射
【发布时间】:2017-07-22 06:48:48
【问题描述】:

所以我目前有以下方法,它根据加权概率(based on this)随机返回一个字符串(一组已知字符串):

def get_response(request)
  responses = ['text1', 'text2', 'text3', 'text4', 'text5', 'text6']
  weights = [5, 5, 10, 10, 20, 50]
  ps = weights.map { |w| (Float w) / weights.reduce(:+) }
  # => [0.05, 0.05, 0.1, 0.1, 0.2, 0.5]

  weighted_response_hash = responses.zip(ps).to_h
  # => {"text1"=>0.05, "text2"=>0.05, "text3"=>0.1, "text4"=>0.1, "text5"=>0.2, "text6"=>0.5}

  response = weighted_response_hash.max_by { |_, weight| rand ** (1.0 / weight) }.first

  response
end

现在,我希望输出基于输入字符串保持一致,同时保持响应的加权概率,而不是随机加权输出。因此,例如,这样的调用:

get_response("This is my request")

应该始终产生相同的输出,同时保持输出文本的加权概率。

我认为 Modulo 可以以某种方式在这里使用,哈希映射到相同的结果,但我有点迷路了。

【问题讨论】:

  • 你看过srand吗?
  • @maxpleaner 我不是想播种随机函数。我正在尝试根据字符串输入获得一致的加权输出。
  • 我很难理解你的问题。您的方法get_response 接受一个参数request,该参数未在方法主体中使用。你能解决这个问题吗?

标签: ruby random


【解决方案1】:

@maxpleaner 试图用srand 表达的是

srand 可用于确保程序不同运行之间的伪随机数序列可重复。

因此,如果您播种随机生成器,您将始终得到相同的结果。

例如,如果你这样做

random = Random.new(request.hash)
response = weighted_response_hash.max_by { |_, weight| random.rand ** (1.0 / weight) }.first

每当您传入相同的request 时,您总是会得到相同的response

旧代码

3.times.collect { get_response('This is my Request') }
# => ["text6", "text1", "text6"]
3.times.collect { get_response('This is my Request 2') }
# => ["text6", "text4", "text5"]

新代码,随机播种

3.times.collect { get_response('This is my Request') }
# => ["text4", "text4", "text4"]
3.times.collect { get_response('This is my Request 2') }
# => ["text1", "text1", "text1"]

输出还是加权的,刚才有一些可预测性:

randoms = 100.times.collect { |x| get_response("#{x}") }
randoms.group_by { |item| item }.collect { |key, values| [key, values.length / 100.0] }.sort_by(&:first)
# => [["text1", 0.03], ["text2", 0.03], ["text3", 0.08], ["text4", 0.11], ["text5", 0.27], ["text6", 0.48]]

【讨论】:

  • @hash 在我的情况下是有缺陷且不可靠的。看到这个:stackoverflow.com/questions/6536885/…
  • 啊,有趣,从未注意到,正如您链接中的答案所暗示的,您还可以使用 Digest::SHA1 (Digest::SHA1.hex_digest(request).to_i(16) 似乎可以在 3 个 irb 会话中使用),或者以任何适合的方式您需要可靠地将字符串转换为整数。
猜你喜欢
  • 2014-12-02
  • 1970-01-01
  • 1970-01-01
  • 2014-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多