質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
強化学習

強化学習とは、ある環境下のエージェントが現状を推測し行動を決定することで報酬を獲得するという見解から、その報酬を最大限に得る方策を学ぶ機械学習のことを指します。問題解決時に得る報酬が選択結果によって変化することで、より良い行動を選択しようと学習する点が特徴です。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

1回答

1115閲覧

undefined method `+' for nil:NilClass (NoMethodError)の原因がわからない。

nori0519

総合スコア16

強化学習

強化学習とは、ある環境下のエージェントが現状を推測し行動を決定することで報酬を獲得するという見解から、その報酬を最大限に得る方策を学ぶ機械学習のことを指します。問題解決時に得る報酬が選択結果によって変化することで、より良い行動を選択しようと学習する点が特徴です。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2019/12/04 10:46

編集2019/12/04 11:08

###概要
Rubyでグリッドワールドにおけるエージェントの強化学習システムを作っています。
矢印の長さ(u[][]上方向,d[][]下方向,l[][]左方向.r[][]右方向)の値をもとにしてエージェントの次のグリッドに確率的に移動するという機能を実装するために、ra(0~999の範囲の乱数値を最大値(999)で割ったもの)とu[][]/sum,(u[][]+d[][])/sum,(u[][]+d[][]+r[][])/sumあるいは、1の値と比較することで上記の確率で移動する機能を実装中に以下のエラーメッセージが発生しました。

発生している問題・エラーメッセージ

Traceback (most recent call last): 4: from learning.rb:155:in `<main>' 3: from learning.rb:155:in `each' 2: from learning.rb:167:in `block in <main>' 1: from learning.rb:167:in `each' learning.rb:168:in `block (2 levels) in <main>': undefined method `+' for nil:NilClass (NoMethodError)

該当のソースコード

Ruby

1sum = u[ey][ex] + d[ey][ex] + r[ey][ex] + l[ey][ex] 2 ra =rand(0..999)/999.to_f 3 puts"移動前のエージェントの座補(x,y)=(#{ex},#{ey})" 4 puts"sum:#{sum}" 5 puts"ra:#{ra}" 6 puts"u:#{u[ey][ex]}" 7 puts"d:#{d[ey][ex]}" 8 puts"l:#{l[ey][ex]}" 9 puts"r:#{r[ey][ex]}" 10 11 if ex==gx && ey==gy#スタート地点とゴール地点が同じ場合、終了する。(そのエージェントはゴールする。ただし、報酬なし) 12 e_g+=1#ゴールしたエージェントのカウント 13 14 break 15 puts"_________________________________エージェント#{enum}人目ゴール" 16 end 17=begin 18 u_c =u[ey][ex] / sum 19 puts "u_c:#{u_c}" 20=end 21 if ra<u[ey][ex]/sum 22 history_x[h] =ex 23 history_y[h] =ey #エージェントの経路記録 24 25 #u_h[h]=1#エージェントがどちらに行ったのかの軌跡の記録 26 27 ey =ey-1 28 elsif ra < (u[ey][ex]+d[ey][ex]) / sum 29 history_x[h] =ex 30 history_y[h] =ey 31 32 #d_h[h]=1 33 ey =ey+1 34 elsif ra < (u[ey][ex]+d[ey][ex]+r[ey][ex]) / sum 35 history_x[h] =ex 36 history_y[h] =ey 37 38 #r_h[h]=1 39 40 ex =ex-1 41 else 42 history_x[h] =ex 43 history_y[h] =ey 44 45 #l_h[h]=1 46 47 ex =ex+1 48 end

###全ソースコード

#1.環境の設計 puts"グリッドワールドの大きさを教えてください。(n×n)" n = gets.to_i puts"n:#{n}" #グリッドワールドの大きさを取得する。 puts"エージェントの人数を教えてください。" enum =gets.to_i #エージェントがスタートに設置されて、矢印の長さを更新されるまでの過程を何回くりかえすか。(エージェントの個数) puts"エージェントの寿命は何ステップですか。" elife =gets.to_i #エージェントの寿命の指定 x =0 y =0 #現在座標 gx_h =[] gy_h =[] #ゴールの座標の記録 arrow =Array.new(n).map {Array.new(n,0)} #グリッドワー ルド作成 gx =rand(0..n-1) gy =rand(0..n-1) puts"goal(x,y):(#{gx},#{gy})" #グリッドワールドの任意の位置にゴールを設置 #gx_h[k]=gx #gy_h[k]=gy #ゴールの座標を記録 u =Array.new(n).map{Array.new(n,0)} d =Array.new(n).map{Array.new(n,0)} r =Array.new(n).map{Array.new(n,0)} l =Array.new(n).map{Array.new(n,0)} #上下左右の矢印の長さを格納 history_x =[] history_y =[] =begin u_h =[] d_h =[] r_h =[] l_h =[] =end #エージェントの過去の移動履歴 p =1 #エージェントがゴールに到達した際の総報酬 t =1 #ゴールからさかのぼったエージェントのステップ数(ゴールからtステップ前) e_g =0 #ゴールしたエージェントの数 puts"n-1:#{n-1}" u[0][0]=0 #(0,0) l[0][0]=0 d[0][0]=0.5 r[0][0]=0.5 puts"四つ角" puts"u[0][0]:#{u[0][0]}" puts"d[0][0]:#{d[0][0]}" puts"r[0][0]:#{r[0][0]}" puts"l[0][0]:#{l[0][0]}" d[n-1][0]=0 #(0,n-1) l[n-1][0]=0 u[n-1][0]=0.5 r[n-1][0]=0.5 puts"u[#{n-1}][0]:#{u[n-1][0]}" puts"d[n-1][0]:#{d[n-1][0]}" puts"r[n-1][0]:#{r[n-1][0]}" puts"l[n-1][0]:#{l[n-1][0]}" u[0][n-1]=0 #(n-1,0) r[0][n-1]=0 d[0][n-1]=0.5 l[0][n-1]=0.5 puts"u[0][#{n-1}]:#{u[0][n-1]}" puts"d[0][n-1]:#{d[0][n-1]}" puts"r[0][n-1]:#{r[0][n-1]}" puts"l[0][n-1]:#{l[0][n-1]}" d[n-1][n-1]=0 #(n-1,n-1) r[n-1][n-1]=0 u[n-1][n-1]=0.5 l[n-1][n-1]=0.5 puts "u[#{n-1}][#{n-1}]:#{u[n-1][n-1]}" puts "d[n-1][n-1]:#{d[n-1][n-1]}" puts "r[n-1][n-1]:#{r[n-1][n-1]}" puts "l[n-1][n-1]:#{l[n-1][n-1]}" puts"__________________________________" #四つ角 for i in 1..n-2 do u[0][i] =0 #上側 d[0][i] =0.3 r[0][i] =0.3 l[0][i] =0.4 puts"上側" puts"u(#{i},0):#{u[0][i]}" puts"d(#{i},0):#{d[0][i]}" puts"r(#{i},0):#{r[0][i]}" puts"l(#{i},0):#{l[0][i]}" puts"__________________________________" d[n-1][i] =0 #下側 u[n-1][i] =0.3 r[n-1][i] =0.3 l[n-1][i] =0.4 puts"下側" puts"u(#{i},#{n-1}):#{u[n-1][i]}" puts"d(#{i},#{n-1}):#{d[n-1][i]}" puts"r(#{i},#{n-1}):#{r[n-1][i]}" puts"l(#{i},#{n-1}):#{l[n-1][i]}" puts"__________________________________" l[i][0]=0 #左側 u[i][0]=0.3 d[i][0]=0.3 r[i][0]=0.4 puts"左側" puts"u(0,#{i}):#{u[i][0]}" puts"d(0,#{i}):#{d[i][0]}" puts"r(0,#{i}):#{r[i][0]}" puts"l(0,#{i}):#{l[i][0]}" puts"__________________________________" r[i][n-1]=0 #右側 u[i][n-1]=0.3 d[i][n-1]=0.3 l[i][n-1]=0.4 puts"右側" puts"u(#{n-1},#{i}):#{u[i][n-1]}" puts"d(#{n-1},#{i}):#{d[i][n-1]}" puts"r(#{n-1},#{i}):#{r[i][n-1]}" puts"l(#{n-1},#{i}):#{l[i][n-1]}" puts"__________________________________" end #残りの壁 #境界線の作成(確率を0にする。)ついでに他の方向の矢印にも確立を格納する。(環境の初期化) for i in 1..n-2 do for j in 1..n-2 do u[i][j]=0.25 d[i][j]=0.25 r[i][j]=0.25 l[i][j]=0.25 puts"他のグリッド" puts"u(#{j},#{i}):#{u[i][j]}" puts"d(#{j},#{i}):#{d[i][j]}" puts"r(#{j},#{i}):#{r[i][j]}" puts"l(#{j},#{i}):#{l[i][j]}" puts"__________________________________" end end #他のグリッドに確率を格納(等確立の0.25) #_________________________________________________________________________________________________________________________ #2.学習 for k in 1..enum do #エージェントの個数分繰り返す。 sx =rand(0..n-1) sy =rand(0..n-1) puts"start(x,y):(#{sx},#{sy})" #startを,グリッドワールドにランダムに格納 ex =sx ey =sy puts"エージェントの座標(ex,ey):(#{ex},#{ey})" #エージェントの作成(スタート地点に設置) for h in 0..elife-1 do #hはエージェント寿命である。四つの矢印の長さを使って確率的に移動する。もしゴールについたらforから脱出する。 sum = u[ey][ex] + d[ey][ex] + r[ey][ex] + l[ey][ex] ra =rand(0..999)/999.to_f puts"移動前のエージェントの座補(x,y)=(#{ex},#{ey})" puts"sum:#{sum}" puts"ra:#{ra}" puts"u:#{u[ey][ex]}" puts"d:#{d[ey][ex]}" puts"l:#{l[ey][ex]}" puts"r:#{r[ey][ex]}" if ex==gx && ey==gy#スタート地点とゴール地点が同じ場合、終了する。(そのエージェントはゴールする。ただし、報酬なし) e_g+=1#ゴールしたエージェントのカウント break puts"_________________________________エージェント#{enum}人目ゴール" end =begin u_c =u[ey][ex] / sum puts "u_c:#{u_c}" =end if ra<u[ey][ex]/sum history_x[h] =ex history_y[h] =ey #エージェントの経路記録 #u_h[h]=1#エージェントがどちらに行ったのかの軌跡の記録 ey =ey-1 elsif ra < (u[ey][ex]+d[ey][ex]) / sum history_x[h] =ex history_y[h] =ey #d_h[h]=1 ey =ey+1 elsif ra < (u[ey][ex]+d[ey][ex]+r[ey][ex]) / sum history_x[h] =ex history_y[h] =ey #r_h[h]=1 ex =ex-1 else history_x[h] =ex history_y[h] =ey #l_h[h]=1 ex =ex+1 end puts"移動前のエージェントの座標(x,y):(#{history_x[h]},#{history_y[h]})(履歴から引用)" puts"移動後のエージェントの座標(x,y):(#{ex},#{ey})" puts"________*________*____________*_______________*__________" if ex==gx && ey==gy T =h#エージェントの移動距離(エージェントの寿命) puts"逆順前"#配列を逆順にする(先入先出法の実現) p history_x p history_y history_x.reverse history_y.reverse puts"逆順後" p history_x p history_y for rb in 0..h do #rollback(ここで報酬を分配する。) e_g+=1#ゴールしたエージェントのカウント if history_x[h] ==history_x[h-1]&&history_y[h]>history_y[h-1] u[history_x[h-1]][history_y[h-1]] = u[history_x[h-1]][history_y[h-1]]+p*(T-t+1/T) elsif history_x[h]==history_x[h-1]&&history_y[h]<history_y[h-1] d[history_x[h-1]][history_y[h-1]] = d[history_x[h-1]][history_y[h-1]]+p*(T-t+1/T) elsif history_x[h]>history_x[h-1]&&history_y[h]==history_y[h-1] r[history_x[h-1]][history_y[h-1]] = r[history_x[h-1]][history_y[h-1]]+p*(T-t+1/T) else l[history_x[h-1]][history_y[h-1]] = l[history_x[h-1]][history_y[h-1]]+p*(T-t+1/T) end t+=1#エージェントのtステップ前の更新 =begin u_h[h]=nil d_h[h]=nil r_h[h]=nil l_h[h]=nil =end end history_x.clear #エージェントの履歴をリセットする。 history_y.clear break end end end puts"ゴールしたエージェントの数:#{e_g}"

試したこと

恐らく、sum以下の部分が原因だと思いましたので、+の前後に空白など入れてみましたが結果は変わりませんでした.

補足情報(FW/ツールのバージョンなど)

ruby 2.6.3p62 (2019-04-16 revision 67580) [x64-mingw32]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

2KOH

2019/12/04 10:58

learning.rb の 168行目はどの行ですか?
nori0519

2019/12/04 11:00

sum = u[ey][ex] + d[ey][ex] + r[ey][ex] + l[ey][ex] です。
2KOH

2019/12/04 11:20

https://teratail.com/help/avoid-asking 「デバッグしてください」という質問のように見受けられるのですが、そういう質問は丸投げの質問とみなされ、このサイトでは推奨されていない質問に該当するというのはご存知ですか?
2KOH

2019/12/04 11:23

それと、つい今しがたまで気づかなかったのですが、同じ質問を過去に投稿しているようですが、これも推奨されていない質問です。
nori0519

2019/12/04 11:25

なるほど。 わたしは純粋に原因が知りたかったのですが、そうだったのですね。 気を付けます。 ありがとうございました。
guest

回答1

0

ベストアンサー

u[ey][ex]d[ey][ex]r[ey][ex]l[ey][ex] のどれかが nil であるのが原因です。
このコードだとそれ以上はわかりません。

投稿2019/12/04 11:04

編集2019/12/04 12:01
2KOH

総合スコア999

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nori0519

2019/12/04 11:06

なるほどありがとうございます。
winterboum

2019/12/04 11:44

このエラーに関しては l[ey][ex] は無実です。 そいつだけがnilのときは nil can't be coerced into Integer ですね
nori0519

2019/12/04 11:47

どういうことでしょうか。
winterboum

2019/12/04 11:51

nil + 1 だと質問のエラー 1 + nil だとコメントのエラー
nori0519

2019/12/04 11:58

なるほど。 r[ey][ex]+l[ey][ex]=nil+1→前者 r[ey][ex]+l[ey][ex]=1+nil→後者 ということですね。 ありがとうございます。
2KOH

2019/12/04 11:59

> winterboum さん ですね。 最初は「NoMethodError について調べてください」と回答するつもりだったのですが、まあこれくらいなら答えを書いてしまってもかまわないかと途中で方針転換したので、雑に回答してしまっていました。
nori0519

2019/12/04 12:00

もしすべてがnilの場合はどうなるのでしょうか。 何度もすみません。
nori0519

2019/12/04 12:01

なるほど。 ありがとうございます。 勉強になります。
nori0519

2019/12/04 13:09

エージェントが壁の外に行っていたようで、u[ey][ex],d[ey][ex],l[ey][ex],r[ey][ex]がnilになっておりました。 こちらを行かないように修正したところ直りました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問