2019年4月1日月曜日

ニューラルネットやってみてる

最近ニューラルネットやってみてる
理屈を学ぼうと思って、まずはオブジェクト的に作ってみてる
(ベクトル化とかは後回しで)

sigmoid, tanh, ReLU
MSE, cross entorpy
あたりを小規模にいじってみてます
でも今 soft max の逆伝搬ができなくて困ってる
ネットの説明みても数式がわからない感じ

数学は興味はあるけど、実際やろうとすると拒否感がすごい
分かると楽しいのではないかと思うんだけど、
記号の意味わからなさ(コードと違って識別子が説明的じゃないし)と
学校教育の初期でドロップアウトしたことで
どうもだめです
それでもなんとか3Dやるのに困らない感じには
(ベクトルとか行列とかテンソルとかイナーシャとか…)
カンを頼りにコードに起こしてるけど
苦手意識がはんぱない

ニューラルネットはものすごい昔に本とか読んだ
当時、なんというか脳内のホルモン的なものによる
感情的なものの簡易的なエミュレートとかやってみたいなと思ってた
んで今やってみようと

逆伝搬は個人的にあまり興味がないので、別の方法とかないかなと思ってて
最近金子勇氏の講演動画にいきあたったりして
すごい興味あるんだけども、もうこの世にはいない 残念だ

学習に浮動小数点数を使用するのも、もっとこう簡易的に byte とかで
済ませらんないのかな?とか
ごく簡単な方法とかないのかなとか 探してみたい

なんとなく俯瞰的に見て、ニューロンであるかないかはあまり関係なくて、
単体が非線形で、他の単体との関係性があるモデルであることが重要なのかなとか
思うのが、バードイドとか
あの辺、単体には簡単なルールしかないのに全体として面白い動きをするあたり、
ちょっと似た感じをうける
ライフゲームとかもそうだろうか
そのうち、この辺を一般化した考え方みたいなのが出てくるんじゃないだろうか
動物と生態系とか人間と都市社会とか
そのネスト関係とか

話がおかしくなったけど、
当面やりたいのは、ゲーム的な環境の中に自律したキャラクターを置いて、
仮想ペットみたいなのにしたりとか
そいういのがしたいかんじ

2018年12月9日日曜日

コンピューとシェーダー覚え

めも 時々書き換える

概要
http://neareal.com/2601/

長所短所、効率等
https://wlog.flatlib.jp/item/1425
DirectCompute だとどうなってるか
https://wlog.flatlib.jp/item/1411

構成要素
シェーダー
バッファ
カーネル カーネルID
スレッド スレッドグループ
定数バッファ

実行はグループ数を指定 (x,y,z)
1グループにつき (x,y,z) スレッドを実行

バッファは普通にランダムアクセスする
実行中のスレッドIDを得ることが可能、バッファアクセスに利用できる
グループIDも取得可能

定数バッファは他のシェーダと同じ

コンピュートバッファは1次元、テクスチャバッファは2次元、という感じ
RW は書き込み可能
StructuredBuffer
AppendStructuredBuffer/ConsumeStructuredBuffer

バッファタイプ
Default structured buffer
Raw byte address buffer
Append AppendStructuredBuffer/ConsumeStructuredBuffer
Counter よくわかんない、カウンタ付きの structured buffer
IndirectArguments DrawIndirect 系に渡すための引数バッファ(dword*5)


DX11では
リソースとその使用方法としてのビューという概念があるみたい
同じリソースを複数のビューから扱えるもよう
リソースはバッファとテクスチャに分けられるみたい
--------
リソース
Texture/RWTexture
Buffer/RWBuffer
ByteAdddressBuffer/RWByteAddressBuffer
StructuredBuffer/RWSturcturedBuffer
ConsumeStructuredBuffer/AppendSturctutedBuffer

ビュー
ShaderResourceView (SRV) R
UnorderedAccessView (UAV) R/W
RenderTargetView (RTV) W
DepthStencilView (DSV) W

この辺は Unity では隠されているかんじ?
-------

バッファ
CopyCount() バッファ間でカウントをコピーできる
・おそらくCPUを介せずにGPU内で可能なんだと思う
SetCounterValue() 
・カウンタをセットできる 定数バッファの SetXxxx() と同じ感じなんじゃないかな
・よくわからないが、たぶん内部がどうなってるとかは考えずに使用していける感じか?
・要素の追加/取得と現在状態(カウンタ)だけ管理すればいいみたいな
SetData( nativeArray, arrayStart, bufferStart, elementCount )
・任意の位置へのアクセス
・帯域も節約できるんだろうか
・複数個所に細かく SetData() した場合の転送効率はどうなんだろう








Linq を毎フレーム使うには

Linq で、オペレータのオブジェクトは全部クラスなわけで、Unity でフレーム内で使用するにはGC的にヤダなぁ、というのがあると思うんです(速度的な面はいいとして)

オペレータってのは遅延実行できて、使いまわすことができるのですが、
そうすると列挙ソースだけ変更したいなっていう要望が発生すると思います。
(もしくはもっといいやり方があるかもしれませんが)

そういう場合のために、ソースを差し替えできるようなクラスを作成してみました。
https://github.com/abarabone/EnumerableCache/blob/master/ConsoleApp1/EnumerableCache.cs?ts=4
絶賛試行錯誤中なんですが。

つうてもまぁ、なんか微妙なかんじです。
一番微妙なのが、struct enumerator ですよね。
Linq オペレータって、内部で foreach() yield return やってるじゃないですか。
そこで生成される enumerator は、class enumerator になりますよね?
んじゃあ結局、毎フレーム列挙する度にオペレータの深さだけGCゴミがたまっていくのは変わらないということなんじゃないかと。

まだ実際に Unity で試してないのであれなんですけど
(テストとかデバッグとかの機能をよく知らないので二の足を踏んでしまいます…)


ところで
Linq のオペレータとかイテレータのシグネチャ?を、

static IEnumerable<TResult> SelectIterator<TSource, TResult>
    (IEnumerable<TSource> source, Func<TSource, int, TResult> selector)

から

static IEnumerable<TResult> SelectIterator<TSource, TResult, TEnumerable>
    (TEnumerable source, Func<TSource, int, TResult> selector)
    where TEnumerable : IEnumerable<TSource>

みたいな感じに変えれば、内部の foreach() で専用の GetEnumerator() を呼ぶ感じになったりしますかね?
(あ、無意味…だって専用の struct enumerator を書かないとだめだし、そうすると foreach() yield return が使用できなくなって、選択的に struct enumerator を呼ぶことができなくなる…よね?)

selector ラムダとかはどうなんだろ、キャッシュされると思うんですけど。

あ、いや、Linq のソース全書き換えとかはさすがにやらないですが…


2018年11月14日水曜日

OneFrameEntityComponentChunk みたいの欲しくないですか

エンティティのコンポーネントデータを処理して、その中から選別されたデータを次の段階の処理へ進めたいとき、なんかのコンテナに詰め替えて処理していくけど、なんかECSっぽくないていうか。

なんかこう、一時的なチャンクみたいな仕組みみたいのが欲しい。
フレームが終われば破棄される、一時的に作成できるエンティティみたいの。
チャンク移動や削除みたいのはしない前提の、作られるだけのタイプ。
そういうのならエンティティ編集にかかる制限は緩くなりそうだけど、ならんかな。
そんで job process component 的なジョブにも対応してるようなやつ。

2018年11月13日火曜日

NativeQueue の Defer な Job を作れないかな

NativeQueue の Defer な Schedule() があるとうれしんだけど、なさそう
つくれないかな

Job の作り方
https://jacksondunstan.com/articles/4857
https://github.com/Unity-Technologies/UnityCsReference/blob/54dd67f09e090b1ad5ba1f55886f327106406b0c/Runtime/Jobs/Managed/IJobParallelFor.cs
https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Unity.Jobs.LowLevel.Unsafe.JobsUtility.html

じょぶは、おおまかにこんな感じでつくるっぽい
・基本となるインターフェースの定義( IJobXxx とかいうやつ)
・JobScheduleParameters と、ジョブの Execute() を実行しつづける関数の準備
・そいつを JobsUtility.ScheduleXxx() 系の関数に渡して、スケジュールしてやる


ユーザーがこさえるジョブのひな型たるインターフェースの定義は、こんな感じ
    [JobProducerType(typeof(IJobParallelForExtensions.ParallelForJobStruct < >))]
    public interface IJobParallelFor
    {
        void Execute(int index);
    }

JobScheduleParameters の準備として重要なのは、ReflectionData をセットすること
で、ReflectionData ってのは、JobsUtility.CreateJobReflectionData() で作成するみたい
その時、ジョブを制御するメソッドを渡してやる(ExecuteJobFunction みたいなデリゲートを定義してそいつにキャストして渡してるもよう)

そのジョブ制御メソッドの中では、基本てきにはループで「ユーザーがこさえたジョブ」の Execute() を実行し続けるんだけど、JobsUtility.GetWorkStealingRange() なるもので中断/終了判定をとっているみたいな気配


…と、そんな感じでじょぶ自体は作れそうなかんじなんだけど、肝心のスケジュールが
JobsUtility.Schedule()
JobsUtility.ScheduleParallelFor()
JobsUtility.ScheduleParallelForDeferArraySize() ←これが個数を後回しにできるやつ
JobsUtility.ScheduleParallelForTransform()
くらいしかない
そのうえ個数遅延は NativeList に対して行うものしか用意されていないっぽい

そういうわけで、なんか目論見は無理そう
あと残された手は NativeList 互換的なコンテナ(個数遅延に渡せるもの)の作成なんだけど、なんか難しそうでヤダな…
そういえば、IJobProcessComponent なんとかってのもあったな、あれもソースみてみるか

追記:キューの内部ブロックかスレッドIDに関する情報を詰めた NativeList を軽く作って Defer に渡し、それをもとにデキューしていく…みたいのってできないかな(やる気はない)

パラレルな読み書きができるネイティブコンテナはないの?

んーーーーーと、
NativeQueue は Concurrent によってパラレル書き込みができるけど、パラレル読み出しができない
NativeList はパラレル書き込みができないけど、JobsUtility.ScheduleParallelForDeferArraySize() を使用するとパラレル読み出しができる

なぜ、パラレル書き込みができてパラレル読み出しができるコンテナがないのか?
理由があるんだろうか?
それともそういうシチュエーションになることがそもそもおかしいのだろうか

そんなこんなで、では NativeList の Concurrent な構造体でも用意してやろうかと、
バッファ実体と長さフィールドへのポインタを格納して、Add() するとインターロックでカウントアップするようなものを作った。
そいつでパラレル書き込みを一応クリアとして、こんどは Defer な Schedule() を使用すると、
InvalidOperationException: The previously scheduled job MotionProgressJob reads from the NativeArray MotionProgressJob.srcEntities. You must call JobHandle.Complete() on the job MotionProgressJob, before you can write to the NativeArray safely.
って言われて、Complete() で待たないとエラー消えない

そんでもって、それを回避できるかなと考えて TempJob で NativeList を作りたいんだけど、
InvalidOperationException: DisposeJob.list uses [DeallocateOnJobCompletion] but the native container does not support deallocation of the memory from a job.
がでてしまう

自分でコンテナを作らないとダメなんだろうか…

2018年11月6日火曜日

Complete() は嫌だなぁ

ああーしまった
Job でカウントアップするなどした結果カウントを取得して、
そいつを .Schedule() の全長として渡したいなんてときは
Job の完了を待たないとだめなんだなぁ そりゃそうだー

OnUpdate( JobHandle inputDeps )
で渡される inputDeps はスケジュールのためのハンドルに過ぎないから、当然 Complete() 待ちはしないといけないんだ
以前のコードにも苦し紛れに Complete() 挟んであった
システムを分けるわけない関係ないな

でもメインスレッド上で待たせるのは嫌だなぁ
これブロックするんでしょ?
どうしたもんかな

ニューラルネットやってみてる

最近ニューラルネットやってみてる 理屈を学ぼうと思って、まずはオブジェクト的に作ってみてる (ベクトル化とかは後回しで) sigmoid, tanh, ReLU MSE, cross entorpy あたりを小規模にいじってみてます でも今 soft max の逆伝...