【Need Help!】深層強化学習(DQNもどき)のNNにLSTMを組み込むもうまくいかず

※記事最下部に追記あり

DQNもどき*1でFXシステムトレードシミュレーションというのをやっているのですが(下の記事からはまた幾分変化しています)、
 
qiita.com

これに、LSTMを導入してみましたが、残念ながうまくいっていません。
以下はその問題についての記述です。
 
学習時は学習データである時系列データを1足ずつなめながら何周もして、一足ごとにランダムreplayをしていたのですが、当該replayの処理をいじって、要素数32で、過去の時系列上で連続した [state, reward, 他] を memory から引っ張ってきて、特徴量データのリストと、教師データのリストを同じ要素数で作るようにして、epoch=1、batch_size=32 で fit するってな感じにしたんですが、全然収束しません。。。
(元々バッチサイズ32で1epoch fitするというような実装でした)

LSTM導入前は、一分もしたら0.0xxxぐらいのlossになっていたのですが(今のパラメータだと、1イテレーション、つまりテストデータを一周なめるのに15分ぐらいかかってる感じです)、LSTM版は6時間ぐらい経ってもlossは30から20ぐらいをうろちょとするばかり。
 なお、loss functionは huber損失関数。オプティマイザはAdam。学習率は小さすぎると時間かかるかと思って0.01とかにしています*2
 
で、気になっているのはネットワーク構成の話と入力データ(特徴量、outputに対する教師データの両方を含む)で、そこの実装を説明すべく、少しコードも交えつつ今の実装について整理すると以下のような感じなのですが、

■前提
入力データは、 特徴量10個のリストを一要素とするリスト、教師データ: 3つのアクションの報酬値(実数値)のリストを一要素とするリスト

■ネットワーク構成
        self.model = Sequential()
        self.model.add(LSTM(32, activation='relu', input_shape=(state_size, 1))
        self.model.add(RepeatVector(1))
        self.model.add(LSTM(32, activation='relu', return_sequences=True))
        self.model.add(TimeDistributed(Dense(action_size, activation='linear'))
        self.optimizer = Adam(lr=learning_rate)
        self.model.compile(optimizer=self.optimizer, loss=huberloss)

■fitの呼び出し(batch_sizeは32)
self.model.fit(x, y, epochs=1, verbose=1, batch_size=batch_size)
xとyはfitに渡す前によろしくreshapeして

x -> (32, 10, 1)
y -> (32, 3, 1)

にしている。
シェイプから分かる通り、xとyの要素数は同じにしてある


replay時の1バッチで見ると、データは時系列で並んでいるのですが、ランダムreplayをベースに実装したのもあって、次のreplay(次の足で行われる)では、違う時点での時系列上で連続なデータという形になっています。
 
もしかして、そもそもLSTMって、このようなやり方ではダメで、(学習データの期間の終わりに到達しない限り)ずっと連続なデータを渡す必要があるという話があったりするのでしょうか?


LSTMのKerasでの実装としては、手元には↓のページを参考にさせて頂いて実装した、
sweng.web.fc2.com

 
為替データを使った予測プログラムがあり、そのコードは期待通りの動作をすることを確認しており、このプログラムでの実装を取り込んだという形です。
github.com


ただ、FXシステムトレードシミュレーションのプログラムは単純に、時系列データをずらして、よろしくするといった類のものではないである点と、出力が複数要素になっている点(参考記事を参照してもらうと分かるのですが、ベースとしているコードは、複数データが出力されはしますが、個々の要素はスカラか、スカラ 1個を含む1次元リスト)、ネットワーク構成はこれでいいのか・・・という感じで悩んでいます。
 
現状のコードはこんな感じです。
github.com
 
environmentが返す stateは 32 x 10(2次元配列のリストとしては data[0-31][0-9] 的な感じ)のリストになっていて、memoryに格納する際は、その処理の前の時点で、

state = np.reshape(state, [32, 10])

と reshapeしてあります。
 
fitするためのデータを作っている箇所は以下の行のあたりです。
github.com
 
また、学習がうまくいくかどうか以前に、一番腑に落ちないのは、今のネットワークだと、10個の特徴量が32個並んだリストを与えて predict すると1個の出力(3要素のリスト)が得られるだけなのですが、学習時には32個の出力に対応する教師データを渡していて(そうでないと、fitを呼び出したときに入力と出力の array の要素数が違うぞ、とエラーになる)、そうすると、どうやってlossを計算してるのか、というのが良く分からない点。
 
そこで、ネットワーク構成のパラメータをいじって、32個出力がされるようにしたろ、と思っていろいろ試したものの、Keras(Tensorflowバックエンド)がエラーを吐いてうまくいかず。。。
唯一、RepeatVectorの引数を 1 から、出力1つの要素数である 3 にした時だけは動作して3個の出力(action数3に対応する3要素のリストが3個)が出るようになりましたが、それもおかしな話だ、と思い、実装としては採用していません。
 
=========================

以上、つらつら書いてみました。
 
根本的にLSTMの理解が誤っている可能性も大ではあるのですが、識者の方のアドバイスが頂ければ幸いです。
よろしくお願いいたします。●刀乙

追記 (2020/02/24):
Reshpeレイヤを最後に追加して、テンソルのshapeをよろしく合わせてやることで、RepeatVectorの引数をバッチサイズにして、出力されるpredictの結果を入力した教師データの数と一致させることができました。学習結果も順調です!
fx_systrade/dqn_fx_trade_tensorflow_lstm.py at 9f43ae89002cfc773ace17c788271296b554384f · ryogrid/fx_systrade · GitHub
fx_systrade/agent_fx_environment_lstm.py at 9f43ae89002cfc773ace17c788271296b554384f · ryogrid/fx_systrade · GitHub

*1:Actionによる遷移先でのMax報酬を時間割引率ガンマをかけて、足すという、更新式を使わずに、脇から別の方法で未来の報酬を過去に波及させていくというようなことをしている

*2:0.001等のLSTM採用前に用いていたパラメータでは少なくとも数十分待っても収束してく気配がなかったので

同じ処理をしているコード(DDQN)のはずなのにタスクが解けるコードと解けないコードがあって混乱

Open AI gym の 倒立振り子の課題を DQN(DDQN)で解けるか確認しているのですが、以前、解けることを確認したコードでは解けるのに、WinMergeで差分を確認するまでした、開発中のFXトレードシミュレーション用のコードをベースにその課題を解くように修正したもの(元を辿れば先祖返りしてるんですが)だと解けない。パラメータやら何やらかんやらも同じにしたのに。
わけがわからないです・・・・。
 
・解ける方
https://github.com/ryogrid/fx_systrade/blob/165dc936a2877f9dde903f628ecb88cbecfc5f91/ddqn_cartpole_tensorflow_runnable_win10.py
・解けない方
https://github.com/ryogrid/fx_systrade/blob/165dc936a2877f9dde903f628ecb88cbecfc5f91/dqn_fx_trade_tensorflow_testing_with_cartpole.py
 
実行しているvirtualenvも同じ、というか、同じコマンドプロンプトで同じpythonコマンドで実行している。
ディレクトリも一緒。
なお、実行環境はWIndows10。
 
もう呪われているか、gymがローカルにソースファイルごとに何かのデータをキャッシュしてるか、とかしか思いつかないです・・・。

以前Unityで作った3D壁打ちゲームをOculus Quest & Rift, Rift S(VR)対応させました

以前Unityで作った↓の3D壁打ちゲームを、UnityのVR対応の設定等もろもろを行って、Oculus Quest対応させました。
unityroom.com


ちと手間ですが、↓の野良apkを開発者モードでPCからインストールしてやれば遊べます。
www.dropbox.com


インストール参考
vr-maniacs.com

 
【操作】
Aボタン: 球を発射。前のボールが生きてる時は出ません。また、ラケットが画面中央にあるとひっかかる場合があるのでラケットはよけといてください・・・。
ジョイスティック: 利き手の設定によって変わったりするようですが、右か左のジョイスティックでラケットを移動できます

よかったらお試しください。
 
なお、VR(Oculus Questのみ)対応ですが、Unity自体がVRのソフトウェアを作れるようになっていて、かつ、元々単純な3Dゲームだったので(2Dのものを3Dな感じに作り変えるような作業は本質的に必要ない)、実質一日弱程度の工数で対応させることができました。
 
しかし、Oculus Link出たし、Rift Sに対応させた方が試してもらえる人は増えるのかー。
でも、なんか、対応のための作業がそこそこ違うっぽいんだよな・・・。
 
補足:
ソースコード
github.com
 
追記:
Rift, Rift S 用のビルドも作れました。
(Oculus LinkでPCに接続したQuestでも動くので、Oculus Linkを使っている方はこちらのビルドを試す方がラクかと思います)

PCのOculus管理用ソフト(?)で以下のところの"提供元不明"というやつをONにして、

f:id:kanbayashi:20200128182641p:plain
Oculus PCアプリで提供元不明のプログラムを実行可に
 
以下のZipをPCにダウンロード・展開して実行すれば動くかと思います(Oculusの管理用ソフトは起動しておく)。
www.dropbox.com

強化学習を以前やっていたFXシステムトレーディングプログラムに取り込む方法について悩んでいる

以前、FXのシステムトレードのプログラムを書いたのだけど、

qiita.com

 
このプログラムは為替予測は機械学習によって作ったモデルで行うけれども、それに基づく売買ロジックは自分でなんかいい感じだったものにしていたりしました。
 
で、そこも機械学習の枠組みの中でやれたらいいなあと思っていたところで、少し前に株の売買を強化学習の手法でやる、という記事を読んで、
 
qiita.com

なるほど強化学習という手もあったか、と思い、ひとまず単純な設計はどんな感じになるか考えているが、N足後の為替を見た時に利益が出るようにポジションを持つようアクションしたら報酬を与える、とかしたら、自分がやった為替予測と同じようなモデルができるだけだろうし、それでポジションを買う時のモデルは作れたとしても、ポジションを決済する時のモデルの作り方が思いつかない。
  
どうするのがいいのかなー。
 
あとは元々やってた為替予測の結果を特徴量(環境の状態)として入力してやるという風に2段構成にするのか、一段で(ポジションを持っている状態と、持っていない状態で2つ作ることにはなるかもしれないが)全部やってしまうかも、どっちがいいのかよくわからん。
 
まあ、2段構成にするとして、為替の予測結果以外に何の特徴量を入れるのかって話もあるのだが・・・(為替予測のモデルに入力している特徴量を入れることはできるが、意味があるのか、とか)。
 
参考(に読もうかなと思っている記事):
www.ie110704.net
blog.takuya-andou.com

近い将来、覇権を握る言語はDart言語である !

はい。タイトルは誇張して書きました。
 
その筋の方々においては、既出の議論かもしれないですが、今後、ある程度広い用途で使われうる言語(Webフロントエンド、バックエンド、スタンドアロンアプリ、モバイル)として、Dartがワンチャンあるんじゃないかと思うんですけど、どうでしょう。

JSにコンパイルできるし、VM実行もできるし、ネイティブバイナリにもコンパイルできるし。静的型付けできるという意味では、TypeScriptもいいですが、Dartは、TypeScriptが(私が把握している限りJSのライブラリを使うしかないのに対して)自前で標準ライブラリ持ってるし。

ただ、流行りの機械学習や、その基盤である数値計算系の用途に今のところ手を伸ばす手段が無さそうなのは、いまいち。*1

Pythonライブラリを透過的に呼び出せるインタフェースを誰か、もしくは公式で作ってくれたらいいんですが。といっても、簡単な話ではないのも分かってはいます。JVM言語がJavaのライブラリを呼び出すのとはわけが違う。
(ネイティブコードを呼び出すことはやろうと思えば可能。また、Flutterだとchannelという仕組みを使って、Android側、iOS側のライブラリ関数を呼び出すようなコードが書けるようです。ただし、呼び出される側は、アプリケーションレベルでプラットフォーム固有の言語による呼び出し依頼を受けた時のコードを書かないとダメ)
 
なお、NumPy, SciPyの代替となるところを目指しているのであろうプロジェクトは既にあります。
scidart.org

これはこれで応援したいプロジェクトなのですが、Python機械学習ライブラリをDartから使いたい、となって、Dartにポートされたものを使うという形がとれるような状況にDart界隈がなるというひとまずのゴール(?)を達成するには、当たり前ではありますが、これだけでは解決しません。

ポートを行うにあたって、NumPy, SciPy (これらは SciDart で置き換えられると仮定)の利用箇所がどうにかなったとしても、ネイティブコード呼び出しを自前でしてたりすると、そこもよろしく対応しないといけないし、最近のライブラリは多くのライブラリに依存(pipモジュール間の依存関係および、Pythonの標準ライブラリ)しているので、それらについてもポートするか、もしくはDartのライブラリでの置き換えをしなくてはならない。
 
潔く、そういう用途はPythonで、とあきらめるのがいいのか。
もしくは、JRuby的な発想で、PDart言語(Pythonで書かれたDart処理系)が出てくればよいのか(他力本願寺)。
 
記事のタイトルと整合しなくなってきているので話を戻すと、機械学習系や数値計算系は現状辛いものの、それを除けばDartは覇権を握れるポテンシャルを持っているのではないかと個人的には思います!

*1:サーバサイドWebフレームワークはAqueduct( https://aqueduct.io/ )という基本的な機能が揃ったものが既にあります

pythonの協調フィルタリング実装ライブラリ implicit を動かしてみたら爆速だったという話(+α)

Qiitaの投稿をサジェストするシステムを開発するため(唐突ですが、作ろうと思っているのです)に利用を検討している、implicitというpython協調フィルタリングライブラリを試していて、以下のサンプルプログラムを動かしてみたのだが(--suggestとオプションをつけるとユーザへのサジェストのコードが走る)、

github.com

 
このサンプルプログラムはLast.fmという聴いている楽曲もしくはアーティスト(へのレーティング)に基づいておすすめのアーティスト(楽曲も、だったかも)をサジェストするサービスで得られた以下のデータセット
 
・約30万アイテム(アーティスト)x 約35万ユーザ、の行列データ(疎行列)
・要素数(レーティングの数)は約1700万
 
を、(デフォルトで利用されるimplicitではALSと呼んでいるモデルでは、)Matrix Factrazationか、Factorazation Machineかどちらか(どっちかは実装を読まないと分からん)で次元削減(して元に戻す)する前処理(fit関数)を行ってから、ユーザごとにサジェストの処理をするのだけど、使うモデルやパラメータにはよるものの、デフォルトのモデル・パラメータで、
 
・前処理: 約20sec
・サジェスト: 約5ms/user
*1
 
という処理時間だったので、サジェストするページのリストは夜間のバッチで作成しておくようにしようかと考えていたが、Webサーバの上のアプリケーションプロセス(というのが正しいのだろうか)の中で、hd5形式で用意しておいた疎行列データを最初にロードして、前処理(fit関数を呼ぶ)して(前処理した結果を保持しているモデルのオブジェクトがpickle等でシリアライズできるようなら、それをオブジェクトとしてロードする形にできるが、まだ調べてない)、リクエストのタイミングでサジェストするという設計でもいけるかなーとか考えているが、どうだろうなー。
 
WebフレームワークはDjango Frameworkを利用予定。
 
ただ、上記のデータセットをメモリに載せると700MB程度は食うようなので(※前処理・サジェスト処理はデータセットを置いておくメモリ以外はほとんどメモリ食わない)、Qiitaのデータセットは上記データセットより疎だろうし、同程度の行列サイズを想定しているものの、集められるユーザ・投稿の情報はもっと少ない気がする・・・ので、データセットのメモリ上でのデータサイズはもっと小さくなるだろう、ということを考慮しても、アプリケーションプロセスの数は1~3プロセス程度に制限する必要はありそう(運用予定の個人鯖はメモリ2GBしか積んでないので)。
 
で、Django Frameworkに限らんけども、その手のフレームワークって、1~3プロセス程度でそれなりの数のユーザをさばけるんだっけ。
(アプリケーションプロセスはGILを解放するネットワークI/OやDBアクセスのためのI/Oが多くを占めていて、なんちゃってマルチスレッドでも複数リクエストをさばける、という仕組みと認識しているが・・・)
 
なお、上に書いた実行結果は最近組みなおした自作デスクトップでの実行結果で、運用予定のマシンとはスペックが違います(自作デスクトップの方が上)・・・。
 
■自作デスクトップ(上記実行結果を得たマシン)
Ryzen 5 2600 3.4GHz 6core, 16GBメモリ
Windows10 64bit上の、WSL Ubuntu 16.04 (Windowsネイティブのpython環境では動作しなかった)
(今回の実行では利用されていないが、Radeon RX570 8GB GDDR5)
 
■運用予定の鯖(KVMを使っているっぽいVPS
Xeon Silver 4114 2.20GHz 仮想2コア, 2GBメモリ
CentOS 6 (x86_64)
 
以下は動作させている時の出力
gyazo.com

 
さて、この設計でいけるかなー
(まずはVPS環境での性能を見ろ、という話はある)
 
追記(19/11/25 6:30):
運用予定のVPSで実行してみたところ、下のようになった。
gyazo.com

行列分解なんかのマルチコアで並列化できるところはコア数が減っているのもあるのか、自作デスクトップ機と比べて7倍程度遅くなっているが、サジェスト処理自体は 200user/sec ぐらいだったのが、150user/sec に落ちたぐらいなので、単体コア性能で速度が決まるところは、75%程度までの速度低下(=1.3倍程度時間がかかるようになった)だけで済んだようだ。
前処理は一度やれば済む処理で、重要なのはサジェスト処理なので、この結果は悪くない。

*1:個人的には、くそ爆速やんけ!、と思った。ライブラリの主要な処理はネイティブバイナリで動作していて、マルチコア・マルチプロセッサのマシンで動作させるとよろしくマルチスレッドで並列処理してくれるらしいので、それが高速な理由の一つでもあるのだと思われる(モデルによっては、コードで利用する旨の明示は必要かもしれないが、GPUも使ってくれるらしい。なお CUDA・・・)。ただ前処理はマルチスレッドで動いているようだが、サジェスト処理自体はマルチスレッド化はされていない模様(マルチスレッド化してもオーバヘッドの方が大きくなるだけといった感じなのだろう)

VRChatってどんなアーキテクチャなのか探ってみる(1)

VRChat ( https://www.vrchat.com/ ) がどんな仕組みで動いているのか気になったので少し調べてみました(無料サービスでユーザー間の音声通話のデータをどうさばいているのか、と)。
※なお、VRChatはデスクトップ版もあってVRヘッドセットが無くてもプレイできます。
 
以下、自分のFBへの投稿の転載。
 

1つめ

VRChatってどんな通信をしてるのか気になって軽く眺めてみたが、Wiresharkとかでパケットキャプチャすると、STUN(NAT越えの時とかに使うサーバの名前だったりなんだり)のパケットが流れてるし、サーバっぽくないマシンとUDPのパケットのやりとしたりしてるので、ユーザ間はNAT越えでP2P通信をしている感じがする。
 
WindowsのパフォーマンスモニタでVRChatのプロセスのコネクション(TCPのみ)とか眺めてても、server-xx-xx・・・ みたいなアドレス(運営のサーバくさい)との通信は最初はあるがしばらくすると無くなったりしてたし。
 
WebRTCとか使ってるのかなあ。もしくは、ただSTUNサーバとか使ってNAT越えするところまでやってる?(STUNってWebRTCだけで使われる仕様じゃないよね?)
 
gyazo.com


 

2つめ

VRChatの仕組みを調べてみようその2。
 <1つ目の投稿へのリンク>
 
↑の投稿に続いて、VRChatがUPnPでルータのポートを開けに行ってないかパケットキャプチャしてみた。
で、結果としては、確実にUPnPでポートを空けると(私が)知っているソフトウェアの出してるパケットと異なり、自分の存在を advertise するようなメッセージはLAN内でブロードキャスト(かな)してるようだが、その後のルータへの notify (空けてくれやってメッセージだと思うのだけど)が無いので、どっちとも分からないという結果でした。
 前に使っていたルータはUPnPでポート開けるとルータのログにそれが記録されたのだけど、最近新しくしたものは、そのログを出さないようで、よう分らんかった。
 
話は変わって、前回の投稿でもコメント欄に貼ったのですが、もう5年前の投稿ですが、ver0.2.0のリリースノートが↓で、
 
www.reddit.com

 
どうも、改めて読むと、この時点ではユーザが今でいうワールドに対応するものをホストして、そのリストは運営側?で管理するか、もしくはホストしているユーザが登録して、他のユーザはリストにあるIPに接続しに行くというような作りだったみたい。
 
この初期の設計の話を踏まえて、昨日、WiresharkUDPパケットをキャプチャして眺めていた結果を考えてみると、ワールドに10を超えるユーザがいるのに、UDPで、VRChatに関するデータだろうと思われる通信をしているのは一つのホストとだけだったりしました(たまに別のホストと通信してるとかはあったかもだけど)。
WiresharkではCLASSIC-STUNと分類されるUDPパケットがあって、それはいろんなホストにrequestして、responseが来るってなことはしていた
 
さらに、VRChatの開発者コミュニティ用の掲示板?のようなものを見ると以下のような投稿がありました。
 
vrchat.canny.io

 
まだ、ちゃんと読んでいないのですが、要は複数のマシン(ホストと書くとややこしいのでここだけ表現を変えています)で一つのワールド(のインスタンス)をホストしたら、これこれの問題が解決されるんじゃね?という提案のようです。
 
で、以上のことを踏まえると、UPnPで穴開けてるかは確実ではないけれど、グローバルIPで外部からアクセス可能になっている状態のマシン(普通のユーザの使っているマシン)を、運営鯖が何らかの基準で選択して、ワールド(の1つのインスタンス)をホストさせて、他のユーザはワールド固有の情報(マップやら造形の情報等々)を運営鯖からダウンロードさせた上で、そこに接続しに行かせる。それらのユーザは、音声チャットや、各ユーザの移動、アバターの変更などのデータはワールド(のインスタンス)をホストしているサーバ経由で受け取ると。
 
そんな作りになっているんじゃないかな、と推測しました。
 
音声もしゃべってなければ、そのための通信は発生しないし(喋っているユーザは喋っていることを表す表示が行われるので、喋っているかいないかを判定していることは間違いない)、ユーザの位置関係によって音声が聞こえる聞こえないとかもあるので、それによって、同じワールドにいたとしても、音声を中継する相手を絞ることも可能なはず。
 
ホストしてるマシンが突然VRChatを終了させてしまったとしても、他のユーザが当該マシンがホストしていたワールドにいたのであれば、他のユーザがどこにいたかとかは知っているはずなので、"新しくホストしてくれるマシン"を運営が割り当てたら、ワールドにいたユーザが持っている情報を元にほぼ完全な形で前サーバがホストしていた状態に復旧?できるはず。(ホストしているマシンの離脱により、0人になったらどっちにしろ復旧する必要が無いので問題なし)
 
まあ、考え方としては、MSに買収された後、いくらか経ってアーキテクチャが変わってしまう(しまった)前のSkypeが採用していたスーパーノードという考え方と近いのではないかと。
 
と、いい加減な根拠で推測してみましたが、実際のとこどうなんでしょうねー。

PONG風 3D壁打ちゲームをUnityで作ってみた

お盆休みに「砦の攻防」というレトロゲームにインスパイアされた、2DゲームをUnityで作ったのですが、
 
ryogrid.hatenablog.com

 
折角Unityをいじったのなら、3Dもやっておかなきゃじゃね?
と思い、「PONG風 3D壁打ちゲーム」を同じくUnityで作ってみました。
 
※確認無く音がでるのでご注意ください
Unity WebGL Player | 3DPONG
 
まだ作りかけですが、一応動くものができたので、アーリーなんたらの精神で公開してみます。
 
githubリポジトリはこちら (masterは別のゲームなので注意)
GitHub - ryogrid/ryogridGamesByUnity at 3dpong

 

操作方法

・マウスで透明なラケット?板?を移動
・スペースキーで弾を前面に向かって射出(一個画面に出ている間はもう一度押しても次の弾は出ません)
・青いラケットで跳ね返ってきた弾をブロックすると跳ね返せる
・ブロックできずに後方に弾がいってしまったらその弾の回?はおしまいで、スペースキーで次の弾を射出する
 
ちなみに、PONGというのはコレです。皆さん一度は見たことやったことあると思います。
Atariのオリジナル版をやった人は少ないと思いますが)
 
www.youtube.com

 

残TODO

・【済】ラケットで弾が見えなくなることが多いので、ラケットを透明にした
・【済】跳ね返せた回数ぐらいは出したい
・【済】弾とラケットの位置関係が分かりにくいので、弾の中心からZ方向に水平にビームみたいなのを出すようにする
・【済】弾の移動方向のX, Y, Z 成分のバランスが適切な範囲に収まるようによろしく調整されるような仕組みを入れる
・【済】ラケットをもっとスムーズに動かせるようにしたい
・【済】マウスで操作できるようにしたい
・【済】ラケットに当たったタイミングが分からないので、当たった時に音を出すようにする
・【済】壁でバウンドした時にも音を鳴らす
・【済】ずっと同じスピードだといつになっても終わらない可能性があるので、だんだんスピードアップするようにしたい
・【済】弾がバウンドした箇所に跡を残す演出
・【済】弾がバウンドした箇所に煙を出す演出
・ラケットがステージをはみ出さないようにしたい

 

謝辞

最初は普通にRigibodyコンポーネントで反発を実装していたのですが、そうすると想定と異なった動作をしてしまう問題が発生して困っていたのですが(入射角が無視されて面に対して垂直に弾道が変わるとか)、以下の記事を参考に修正することで解決することができました。
有益な情報の共有に感謝いたします。
 
www.unipafu.com

筑波大のOB・OGはGoogle Driveを容量無制限で使えるらしい

なんか筑波大OB・OGはGoogle Driveを容量無制限で使えるらしい。
嘘のような本当の話。
 
同窓の友人が試して実際にアカウント発行してもらえたらしい(そもそも、その友人がこの情報のネタ元)ので、事実であることは確認済み。
 
では、なぜ、掲題のようなうまい話があるのか、という理由なのですが、
"交流広場"という現役生・OB・OG・教職員・教職員のOB・OG等が交流できる筑波大学が運営しているSNSがあって、

筑波大学交流広場

その利用アカウントとしてG Suite for Educationでメールアドレスを発行していて(発行する側は、生涯メールアドレス、と呼称しているので、基本的にはずっと使えるようにしておくことを想定しているのでしょう。しかし、生涯というキーワードはインパクトあるなあ)、そのメールアドレスにはGoogleアカウントがくっついてるので、それでGoogle Driveが使える、という話のようです。
 
mast在学中に使えるソフトウェアライセンスを紹介!Microsoft Office 365, Google Drive, Windows - MAST Web

f:id:kanbayashi:20190824091236p:plain
Gmail, Google Drive等についての記述
 
で、SNS利用規約を確認すると、
https://alumni.tsukuba.ac.jp/openpne/web/default/userAgreement
===
(会員)
第4条 次の各号に掲げる者は、別に定める本サービスの会員登録の申請をし、認められた場合、会員として本サービスを利用することができる。
(1) 本学(前身校を含む。)の卒業生、修了生及び元教職員
(2) 本学に在籍する学生及び教職員
(3) その他本学が認めた者
=== 
 
とあり、在学中から利用していること、という要件は別項でも書かれていないので、卒業済みでもアカウントを発行してもらえるというのは、間違いないようです。
 
ちなみに、申請にあたっては、入学年度と在籍した学群と学類もしくは、研究科と専攻をちゃんと覚えていれば大丈夫なのでご安心を(学生番号とかは求められない)。
 
ま、難しい話はさておき、交流広場ってなんか面白そうだから使ってみよー。
 

Unityでお盆に作っていたレトロゲームモドキが完成した

Unityで作っている「砦の攻防」モドキですが、もうこれは完成と言ってもいいのでは?なところまでできたっす。
操作は十字キーの左右で射出パワーを調整、上下で角度調整、スペースキーで発射。
一回発射すると相手のターン。ターンは画面左上、右上の射出時のパラメータの表示のところの左に@マークがあるかで判断します(@がある方がターン中)。
障害物は弾が何度か当たると消えます。
弾の速度が速いと、一発でぶち抜かれます。
 
基本は2人で遊ぶようにできていますが、一緒に遊ぶ人がいない人が一人でも遊べるように数字の1を押すことで1Playerモードと2Playerモードを切り替えられるようにしてあります(1回押しただけでは切り替わらないことがあるので、その時は何度か押してみて下さい)。
 
※特に確認とか出ずに、音が流れるのでご注意下さい
ryogrid.net


 
※PCブラウザ用に作ってあるのでスマホだと動かない場合も多いと思います。
また、キーボードで操作するように作ってあるので、Bluetoothスマホにキーボードを接続して操作するとかしないと、そもそも動作しても操作できません。
 
・残TODO

  • 【済】勝負がついたときの残存障害物のクリアが実装されてないので、一回勝負がついても、残っている障害物は次の回も持ち越しで、新たに障害物が追加で生成されてしまう
  • 【済】砲身を角度に合わせて出したい(分かりにくいので)
  • 【済】砲身の角度調整処理がたまにおかしくなるというのが、利用している方法の都合で起きていたので、それを回避するためにiTweenというアセットを利用して、書き直した。
  • 【済】障害物に耐久度を設けて、耐久度に応じてだんだん色が透明に近づいていくとかしたい。残耐久度の更新は、弾が当たった時の弾の速度を得る方法は分かっているので、それで力積とか求めてよろしくやってやればいいはず
  • 【済】セルフキルが起きないようにした
  • 【済】弾の運動エネルギーがブロックを破壊しても残っている場合はそのまま突き進むようにした
  • 【済】弾がブロックの上で停止してしまった場合に、よろしく消えるようにした
  • 【済】BGM と 各種サウンドを実装した
  • 【済】1Playerモードを実装した

  
githubリポジトリ
github.com
 
ものほんではないが、かなり再現度の高い「砦の攻防」クローン
www.nicovideo.jp
 
Unityは今回はじめて、それなりにまともに使いましたが、今回のプログラムだと、物理計算とか全部Unityにお任せするとやってくれたりするのは楽ですなー(弾道計算とか)。

プログラマのコードの生産性は何によって決まるのか

タイトルはいくらか誇大に書いてますw

以下では、もう少し因子?を絞って書きます。
要は地頭(頭の良さ)の部分ですね。

前提

・知識や経験は同じものとする

本論

ぶっちゃけて言ってしまうと私はコード書くのは遅い方だと思います(同じだけの経験・蓄積のある人間で比べれば)。

じゃあ、その差はなんで生まれるのか自分なりに分析してみたことがあるのですが(論文とかまで調べたわけではないです)、大雑把にくくれば地頭の出来とかになるのかなと思うのですが、それだと大雑把過ぎるし、地頭といってもいろんな要素があるし、IQが高ければ生産性が高いの?って言うと、なんか違うような気がしたんですよね。まあ、他の人のIQなんて知らないので、気がしたってのもいい加減な話なのですが。

で、結局、私が考えた限りでは、ワーキングメモリの量が、生産性を決める因子?として大きいのではないかとという結論に至りました。

ja.wikipedia.org

なお、この記事を書く時にぐぐってみましたが、日本語圏だと、以下のQiita記事でもワーキングメモリに言及しているのを見つけました。

qiita.com
 
自分の場合、おそらくワーキングメモリがあまり大きくないので、コード書く時に定義済みの関数や変数をいちいち見返したりするのに結構時間を食っている気がします。
また、コードベースがそれなりに大きいとソースファイルの数も多くなってると思うのですが、さっき確認したソースファイルの中身、どんなだったっけな、とか忘れて、読み返したりも多い気がします。

プログラマって、実はコード書いてる時間より、他人のコードを読んでる時間の方が多かったりする、とかいう話もあったりしますが(要出典)、上記と同じようなことが起きるので、これもやはりワーキングメモリの多寡でパフォーマンスが変わるのではないかと思います。
(なお、ワーキングメモリは鍛えることが一応でき、Qiita記事で言及されているNバック課題とかいうが一つの方法で、私もそれができるソフトだかサイトだかで1-2週間ほどトレーニングを試みたことがありますが、面倒くさくなってやらなくなってしまいました)

しかし、そういう人間を助けてくれる強い味方もいて、まあ、IDEってやつですね。
クラスやオブジェクトのメンバ補完であるとか、開いているファイル内で定義されている関数や変数を脇のペイン?とかに出してくれるのも助かりますね。
変数名・関数名の補完もしてくれますし(IDEじゃなくても、できますけど)。
標準ライブラリや、import することで(importというキーワードを利用しない言語は読みかえて下さい)使えるクラス名や関数名なんかも最近は補完して、よろしくimportしてくれたりします(確か)。

ただ、この手のIDEでのサポートって静的型付け言語の方がやりやすくて(IDEがコード解析やらなんやらしやすい)、動的型付けだと例えばPythonIDEの PyCharm とかかなり良くできていますが、静的型付け言語と比べるといくらか(結構?)落ちます。
私はどちらかというと静的型付け言語の方が好きなのですが、IDEでのサポートの受けやすさってのも、あまり意識したことなかったですが、理由としてあるのかもしれません。

あと、知名度の高いようなトッププログラマ(?)が、IDEとかあまり使ってなくて、EmacsVimとかにこだわるのは、そもそもIDEによるサポートとかあまり必要のないワーキングメモリの持ち主だから、なんてこともあるのかなとか思いました。

特に良いオチはないのですが、以上です。

いや違うだろ!などコメントあればどしどしお寄せください!

余談:
IQ値の多寡とワーキングメモリの多寡って相関はありそうですが、どれぐらいあるんでしょうねー

追記:
ちゃんとぐぐったら日本語のWebページでもこの手の話が既にいくつかあったので関連ページとして貼っておきます
プログラミングの効率アップの鍵はワーキングメモリだった | リバティドック
プログラムのアルゴリズムを理解するのって脳のワーキングメモリが結構重... - Yahoo!知恵袋
プログラミング学習と脳の使い方~本当に正しい学習してるのか?