研究

今年もオリジナルCDアルバム出します

こんにちは、GMAです。

KCS音楽班では10月29日(日)の音系・メディアミックス同人即売会M3に向けて準備を頑張っています。

というわけで(何かしらトラブルが起きない限りは)今年もオリジナルCDアルバムの新作を出します。
タイトルは「Flowers in the mirror」です。

Flowers in the mirror ジャケット(v1.1)

↑ジャケットはこちら!

今回のCDの収録曲は7曲。価格は300円予定。ボーカロイドRanaとIAによるのオリジナル曲です。
曲調は前作に比べるとだいぶRockに寄っている感じ。
販売当日は会場でトラック1~6を試聴可能です。M3にお越しの際は是非、聴いてみてくださいね!


~トラックリスト~
作詞作曲:GMA(track1-7)
ボーカル:Rana(track1-3)IA(track4-6)

1 ランドスケープ (3:32)
2 リリィ (4:32)
3 君を継ぐ (5:21)
4 Another Mirror (5:00)
5 Timeless World (3:43)
6 Egoistic Gears (4:25)
7 Bonus Track (Instrument)

※収録曲等は全て予定です。


CUDAのSurfaceを使ってみる

CUDAのTextureはreadonlyです. (唐突)
「なんでwriteできないんだ!HLSLにはRWTexture2Dがあるのに!」と思うかもしれませんが, Textureの特色はグローバルメモリからデータをフェッチしてくる際に利用されるキャッシュにあるため, そもそも書き込みではその恩恵を受けることができず, よって書き込みはできる必要がないと言えます. (書き込みの際には普通のメモリを使う).
SurfaceはCC2.0以上でしか利用できませんが, Textureと異なり書き込みも行うことができます. じゃあSurfaceには書き込みにもうま味があるんか?というと, 特にそういった記述はProgramming Guide中で見つけられませんでした. TextureとSurfaceは同列に語られているようなので, 単に書き込みの対象にも指定できるようになっただけなのかもしれません.
処理が一段だけであれば単純にTextureを使えばよいのですが, 処理が何段階もあり, 二つのTextureの間を行き来するようにして処理をしていく場合には少し不便なので(ほんまか?)Surfaceを利用してみました.

今回の知見ですが,

  • CUDAはバージョンによって結構仕様が変わっているっぽいのでちゃんと自分が使用しているバージョンの Programming Guide を読まないといけない(それはそう)
  • Textureの場合はバージョンの違いに加えて, Low-Level APIとHigh-Level APIの2種類のAPIが存在するため, 一方でうまくいかない場合は他方を試してみると良い

といったところでしょうか.

以下にSurfaceのサンプルコードを示します. cudaMallocPitchで確保した普通のバッファに入れてある, Webカメラから取得した色情報をSurfaceに移して(この時uchar->floatの変換とグレースケール化を行う), また戻すだけです. surfRef2は今後使う用で今は使っていないです. ガウス窓も今後使う用で今は使っていないです.

作業中に見た「イリヤの空、UFOの夏」がよかったです.
以上.

GolangでもOpenCVしたい!!!

人間の三大欲求の一つに「GolangでOpenCVをやりたい」というものがあります.
満たす必要があったので満たしました.

今回の環境はWindowsだったので, 基本的にはこちらで紹介されている通りにすればできました.
WindowsでgolangからOpenCVを呼び出してみた – ねずみとりんご

またWindowsでのGolang環境としてはVisual Studio Codeを使うといい感じです.
VSCodeでGoの開発環境を作成する方法まとめ

今回一点嵌ったのは, OpenCV3.0をGolangで使うことができないという点でした.
以前入れたOpenCVが3.0.0だったのでこれを流用しようと思ったのですが, gocはコンパイラとしてgccを利用するのに対し, OpenCV3.0以降ではgccでヘッダ周りをコンパイルできないため, GolangでOpenCVを用いるには適当に古いバージョンを持ってくる必要があります. 参考にしたサイトではOpenCV2.4.9を使用していたためこれを真似たところ, うまくいきました.
Opencv3 compilation issue with C API #6585

またこれ以外にも, C++のライブラリを使用する際には注意が必要です.
cgoでGolangとC++ライブラリをリンクするとき、何が起きているのか

以下はサンプルコードとなります. コードはこちらを参考にGoに移植しました.
カメラ画像を表示(C言語)

以上.

CUDA + OpenCVでWebカメラから取得した画像を変換

とりあえず簡単にグレースケールを作成.
実行すると画像の下の端が切れて悲しい. 理由は分からない.
実装した感想ですが, 「textureをつかえ」という感じなので, cudaBindTextureToArrayを使ってテクスチャを使っていきたい.
とりあえずミニマムで実装するとこんな感じになるんじゃないでしょうか.

参考 : http://fareastprogramming.hatenadiary.jp/entry/2016/11/10/181234
あとはCUDA落とした時に入ってるCUDA SamplesのsimpleTextureなども参考になるかと思います.

Visual StudioでOpenCVを使うメモ

開発環境をUnityからCUDAに移すときにWebカメラから取得した画像が欲しかったのでOpenCVと連携する必要があり, 長年忌避していたOpenCVを導入することになったのでメモ.
Visual Studioはこの辺の設定が難しいので苦手.
ちなみに試してみたのは昨日だけど記憶力が残念なので忘れている点がありそうなので注意.
今回落としたのはOpenCV 3.3.0, OSはWindows10

  1. このへんからソースを落としてきていい感じのディレクトリに移す(曖昧)
  2. [Project]->[Property]->[VC++ Directories]->[Include Directories]に”opencv\build\include”へのパスを追加する.
  3. [Project]->[Property]->[VC++ Directories]->[Library Directories]に”opencv\build\x64\vc14\lib”へのパスを追加する.
  4. ここまでやってビルドしてもリンカ周りで怒られる. かなしい.

  5. [Project]->[Property]->[Linker]->[General]->[Additional Library Directories]に”opencv\build\x64\vc14\lib”へのパスを追加する.
  6. [Project]->[Property]->[Linker]->[Input]->[Additional Dependencies]に”opencv\build\x64\vc14\lib”内の.libファイルの名前を追加.
    (今回はopencv_world330.lib, opencv_world330d.lib)の二つでした.
  7. ここまでやるとビルドは通るが.dllがないとキレられる. 厳しい世の中.

  8. “opencv\build\x64\vc14\bin”に先ほど追加した.libに対応する.dll(拡張子を除いた名前が同じ)があるのでこれを”C:\Windows\System32”, “C:\Windows\SysWOW64″にコピーする.
  9. 私の場合はこれで動きました.

上の作業は多分必要十分でなく, 冗長になっていると思います. 必要ない手順がどれなのかはわからない.
わかる人には自明だし, わからない人にはわからない. よってこの記事の情報量は0.
以上.

参考 : https://qiita.com/imura/items/d5fadbbcf1830019adce

REINFORCE Algorithm でジャンプアクションを学習させてみた

こんにちは. TRSasasusu です.今回は前回に引き続き強化学習の話です.

スクリーンショット 2017-08-07 4.17.50

前回のQ学習は行動価値関数を更新していくことで学習を進めましたが,今回の REINFORCE Algorithm は直接方策を更新していくことで学習を進める方策勾配に基づくアルゴリズムの一種です.

方策勾配に基づく強化学習は状態空間や行動空間が連続であっても取り扱うことができます.ですが,なんとなく連続な状態空間における離散的な行動空間を持つ問題をやってみました.具体的には,ジャンプで穴を飛び越えることを学習していきます.ジャンプするのが早すぎてもタイミングが合わず落ちますし,ジャンプしなくてももちろん落ちます.行動はジャンプするかしないかで,横方向への移動に関しては自動で右へ一定の早さで進ませます.穴との距離と方策の確率モデルのパラメータの関係式をソフトマックス関数に入れ,これを計算して勾配を求めてパラメータを更新しました.


$$ \nabla_{\theta}J(\theta) = \sum^M_{m=1}\sum^T_{t=1}(R^m_t – \overline{b})\nabla_{\theta}\log{\pi_{\theta}}(a^m_t|s^m_t) $$
$$ \theta_{t+1} = \theta_t + \eta\nabla_{\theta}J(\theta) $$

また,報酬については,ジャンプしたら減点(疲れるから),落ちたら大きく減点,穴を越えたら大きく加点という形にしました.

結果は以下のようになりました.

実際にプログラムを動かしてみると,パラメータとしては初期値に関わらずジャンプアクションができそうな値になるのですが,うまくいかない場合も散見されました.REINFORCE Algorithm よりも工夫された手法もあるのでそちらに変更するのも良さそうです.

ところで, REINFORCE Algorithm ってすごく調べづらいのですが… そもそも強化学習は Reinforcement Learning なのでこちらばかり出てきますね.

あと,未だに上に挙げた式でベースラインを引いて良い理由がわからないので,誰か教えてください.

迷路にQ学習を使ってみた

お久しぶりです.ユーザ名を今回から Twitter に合わせて TRSasasusu にしました.

スクリーンショット 2017-08-03 4.06.12

記事にできるような活動があまりできなかったため,気がついたら前回の何か作った系の投稿から7ヶ月も経ってしまいました.今回の投稿は去年UMU氏が投稿したものを大いに参考にしています.(というか,ほぼ同じ.違う点は迷路が大きくなったことくらい)

Q学習は


$$ Q(S_t, A_t) = Q(S_t, A_t) + \alpha(R_{t+1} + \gamma \max_{a’ \in A(s’)} Q(S_{t+1}, a’) – Q(S_t, A_t)) $$

に従って行動価値関数を更新します.そもそも行動価値関数とは,といったことはこちらもUMU氏がまとめてくださっています.ありがとうございます.

方策決定には ε を固定した ε-greedy 法を用いています.これにより局所解を抜け出せるようにします.パラメータについては,


$$ \varepsilon = 0.1 $$
$$ 学習率\ \alpha = 0.1 $$
$$ 割引率\ \gamma = 0.9 $$

としています.

やっぱり途中で戻ったりするようになってしまいますね…何ででしょうね.

あと,Pygame 便利ですね.

今回のスクリプト(q_maze2.py, moyf/ml/rl/q.py)

Assemblyコードの最小化(?)

どうも、チョコです。Assemblyちょっとやってたら調子に乗って記事書きました。誤りがあったら訂正お願いします。

この間、BootLoaderを書いていたが、ファイルサイズが1Sectorの512バイト(-署名2バイト)に入らなければいけなかったため、最適化を行った。(もちろん、ほかのSectorを呼び出して実行はできるが、それでは面白くないから。)

BootLoader#とは?

パソコンが起動したとき、BIOSが初めて実行する512バイトのプログラムをMBRと呼び、このコードがWindowsなどのOSの起動(Boot)をすればBootLoaderと呼ばれる。

最小化#とは?

ここでは、RAMとかStackの最適化とかせずに、実際にコードが保存されているバイト数の節約をする。512バイトしか使ってはいけないので、油断するとすぐ使えないプログラムになってしまう。なんでC++で書かないかのも、このためである。(gcc使えないからとかは黙っておこう)

(ただし、MBRはRealModeで実行するので、Registerは最大32ビットである。)

512バイトで何ができる?

例えば、テトリスのゲームを作ろう。こんな感じの。(最適化の話なので、実際のプログラムはどうでもいいかと)

DA0a29XVoAAfyv6

(作り方を詳しく聞きたい人は、これが完成したら記事を書くので、お楽しみに。)

ここで、移動の処理だけのコードを書くと、なんと100バイトくらい使った。ブロックを積み重ねる判定付けたら180バイト使った。残りのバイトでクレアとか回転とかを実装できそうにないなぁと。

では、プログラムのバイト数を削ってみよう(実際の処理内容は変わらない)。

1.一回しか使わない関数はinlineで書く。逆に、2回以上使う長い処理は関数にまとめる(こっちは常識だな)。call[address] … retは6バイト消化してしまうため、重複処理が6バイト以上であるときだけ関数を使うべき。またRegisterはGlobal変数なので、関数内で宣言もできる。

2.xorを使う(Assemblyでは常識かな)。Registerを0にしたいときにmov EAX,0を書くと4バイト使ってしまうが、xor EAX,EAXを書けば2バイトになる。

3.sub-registerを用いる。EAXの後半がAXで、AXがAHとALの合成など、必要な所を読み、変更できる。例えば、AXは最初が0であれば、mov AX,1とmov AL,1は両方1になるが、AXの場合は2バイトなので結局mov AX,0x0001となり、1バイト無駄になる。

いまは大体こんな感じ。使っている定数に対するregisterのバイト数を気にすると結構バイト数減らせた。以上のことをやるとなんと20バイト以上減らせた。わーい。

(まだ現在進行形ですが、)ソース

では。

BlenderでXray目の再現

どうも、チョコです。多く知られているMultipassのやり方を(今更)理解したので共有したいと思います。

BlenderではMultipassのことをRenderLayerといい、Compositorで組み合わせができる。

ラムのモデルでデモしよう。

Screenshot (1226)

 

髪の毛の前に目を出したいので、まず目と髪の毛を別のオブジェクトにして、髪の毛をレイヤ2にする。

RenderLayerを2個作り、それぞれのマスクを設定する(Hairはレイヤ2しかレンダしない)。

Screenshot (1221)

これをレンダすると、髪の毛が消えた。さて、Compositorで合成しよう。InputNodeを2個使えば両方のRenderLayer画像が入手できる。

 

レイヤ1から目の部分を切り取りたいので、ObjectIDマスクで分離する(目のObjectID1にした)。

Screenshot (1224)

最後に、二つのレイヤをCombineZで合成し、さらに上から切り取った目をAlphaOverする。

Screenshot (1225)

完成。では。

 

OpenGlでスポットライトを実装

チョコです。

エンジン作ってますが照明システムが必要となりました。そこでスポットライトが一番簡単なのでまずそれを実装しました。

Screenshot (1141)

プロセスを説明します。

Deferredなので、まずオブジェクトのパスを出します。zバッファーを使います。

Screenshot (792)
そして、光パスで画面スペース→世界スペースに変換し、光からの距離、角度を出します。割と簡単な数学演算なので省略。
そこで、影がないとおかしいので、影も実装しました。
光パスの前に、光を視点としたMVP行列をかけ、画面をもう一度レンダ―し、マップに保存します。
Screenshot (1142)

光の行列をシェーダーに渡し、世界スペース→陰スペースを算出します。そこのz値を出します。

Screenshot (1143)

陰スペースの自分のz位置と比べて、影かどうかを判断します。完成。biasなど全然かけてないのに割といい結果を出せました。

シェーダーコードも載せときます(フラグメントだけ)

 

これからはポイントライトやら一方向ライトやらの陰も実装しますが、意外と面倒なのでゆっくりやります。では。