DJProject_備忘録_6

## 2024-11-28
次はTransformerを作るために、Affine,LeLU,Softmax,Normalization(逆伝播難しいんだよね…),AttentionWeight,WeightSum,CrossEntropyLoss
、、ぐらいかな。作っていこう。

えっと、前に書いた簡易Transformerの写真、写真、、、あった
あったけど、これAttentionLayerに1つ前のポジションのhs渡す矢印が足りない
![IMG_0102.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/8f860155-68f1-6213-a28a-731f145e7a2c.jpeg)
ここで言う、FeedforwardLayerはAffineLayerとやってる事全く一緒らしい。
…ほんとに？
でもとりあえず、xW + bで良いってさ。
SigmoidLayerはReLULayerに置き換えよう。
そして、全てのLayerの手前にNormalizationLayerを挟み、爆発消失避けよう。


ちよっとまって、SwishLayerを過去の自分がUdonSharpで用意してくれてる。
ここのディレクトリ素敵、、。これ、今回使おう。
![IMG_0103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/a99e7e0f-eb78-1e44-94a4-d11e1dacb20e.png)
中身が少し特殊だったので、それを訂正する形で、バージョンをアップさせよう。

![IMG_0107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/adf08111-ada1-b201-bf69-756b1a4da43c.png)

ここまで
用意できた。
CrossEntropyLossはSoftmaxWithLossとしてまとめた。

そしたら、、サーバー側のPythonにも同じレイヤーを作りましょうか…。

Pythonの方もできた。

## 2024-11-29
- LiONにスケールダウン機能を加える。
勾配爆発、消失した場合に、重み、バイアス全体のスケールダウンをすることで、限りなく勾配爆発、消失を教える試み。

- スケジュールを作ろう


## 2024-11-30
スケジュールをつくろうと思ったけど、Layerを作っただけなので、各全てほLayerのPlayerを作ろう。

…土曜12時間出勤だるい今日、、、
とりあえずテンプレ…
```
using UdonSharp;
using UnityEngine;

public class AffinePlayer : SuperPlayer
{
    public string myName;
    public AffineLayer affineLayer;
    public InitAiTypesPlayer initAiTypesPlayer;
    
    // 初期化メソッド (Pythonの__init__に相当)
    public bool AffinePlayerReset()
    {
        myName = "AffinePlayer";
        return true;
    }

    // プレイヤーの名前を返すメソッド
    public override string ReturnMyName()
    {
        return "AffinePlayer";
    }

    public float[] Forward(float[] x)
    {
        float[] y = affineLayer.Forward(x);
        
        return y;
    }

    public float[] Backward(float[] dx)
    {
        float[] dout = affineLayer.Backward(dx)

        return dout;
    }
    
    // メイン処理を行うメソッド
    public override string ExecuteMain()
    {
        // ForwardPlayerでライブラリ的に使用するので
        // 実装今のところ不要
        return "Completed";
    }
}

```
レイヤーすべてにPlayerを用意した。LiON、もっと早い処理になるように改良できないかな、、
もう電池無くなる、、さよなら

## 2024-12-02
レイヤーのオブジェクト数は
UdonSharpの処理力的に、
各レイヤ1つずつとするため、
重み、バイアス、ベータ値
そして、それぞれの微分値は、
各ポジション分用意する必要がある。
![IMG_0115.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/430e598a-10d5-b313-c140-229ba9c1de74.jpeg)
- レイヤーの作成
    - Params,DParamsLayerの作成
    - Xs,DXsLayerの作成

## 2024-12-05,2024-12-06
日付けが空いた。
なにしてたんだっけ、、
ああ、前回の画像みて思い出した。
- レイヤーの作成
    - Params,DParamsLayerの作成
    さて、必要としてるのは…
    ・4次元arrayを持ったparams
    ・4次元arrayを持ったdparams
    ね。

…これじゃダメだ。C#知識不足の私に組み込めない。
パラメータ群は、ひとつの行列に収めることにした。
![IMG_0146.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/36f1db2c-2e29-e790-673e-3cfb7176dd8d.jpeg)
3行をひとつのLayer分の情報とし、
各重み、バイアス、ベータ値はフラットに…って、
あ、フラットにするのは重みだけで良いのか。
Layerでパラメータを呼び出す時は、reshapeして使うことにした。
これなら4次元データにならず、2次元行列で済む！

なので、えっと、次することは、、
- Paramsプレイヤーは2次元ジャグ配列をもつオブジェクトとして作り直す。
- DParamsプレイヤーも同様に。
 
その後で、どのようにForwardPlayerでの処理をするか、考えよう。流れは大まかに出来てる…
![IMG_0147.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/fad2b17e-8dd5-3ac8-84f0-dbfe07150c9e.jpeg)

…ので、後で考えても大丈夫。

- AiSettingsPlayer の作成
このプレイヤーに、HiddenSizeやXSizeのパラメータ設定をメンバ変数として持たせよう。

## 2024-12-09
- ParamsPlayer を作らなきゃ

## 2024-12-11
まってまず、EmbeddingLayerの改良から始めよう。

殴り書き紙の備忘録
大まかな流れ
![IMG_0173.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/75a7e4ea-9c80-13ee-61b5-c14dcf77c5e4.jpeg)
![IMG_0172.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/d9fd0566-6b8c-0bcd-008e-88b08764e103.jpeg)

なので、
- EmbeddingPlayerの改良
    あ、Tokenizerクラス作らなきゃ
    EmbeddingLayerの重み定義できないや。
    あいや、設定パラメータは全てAiSettingsPlayerから取得するようにしよう。仮定義としてEmbeddingLayerを先に作ろう。
    - RinaNumpyに
        - Append_FloatArray()
        - Append_StringArray()
        を追加。
        - …あと色々追加。

## 2024-12-12
EmbeddingLayerあとBackwardだけ
えっとEmbeddingLayerの次のレイヤーは、レイヤー群になる。
なので、レイヤー群の最初のレイヤー(LayerNormalizationPlayer)は、
なので、次のレイヤーはEmbeddingのthis.SampleIdVerをforで回して取得することになる。

そのため、AiFlagsPlayerを作成し、その時学習中のポジションのインデックスをこのプレイヤーに保持させることにした。
ほか、ほかの処理でフラグが必要になった場合、このプレイヤーに書き込み使用していく。

EmbeddingPlayerできた。
ついでに、「予定スケジュール.md」も作成した。中身は次の通り。
```
# Forward
## Xのフロートベクトル化まで
- InitAiTypesPlayer # モード変数の初期化
- ChangeAiModePlayer # TrainまたはPredictのトグルスイッチ
- ChangeTravelModePlayer # ForwardまたはBackwardのトグルスイッチ
- AiSettingsPlayer # 入力データ、隠れ層等の設定
- EmbeddingPlayer # Xを1次元ベクトル化
## フロートベクトルをlossに変換するまで
- PositionsParamsPlayer # このポジションのパラメータを、各レイヤーにペーストする
- NormalizationPlayer # 各ポジション毎回、EmbeddingPlayerのSampleVecVerから取り出してくる。
- SkipAddPlayer
- AffinPlayer
- NormalizationPlayer
- SwishPlayer
- NormalizationPlayer
- AttentionWeightPlayer
- NormalizationPlayer
- WeightSumPlayer
- NormalizationPlayer
- AffinPlayer
- NormalizationPlayer
- SoftmaxWithLossPlayer
---
# Backward
## Backwardモードに移行
- ChangeTravelModePlayer # ForwardまたはBackwardのトグルスイッチ
## EmbeddingPlayer直前まで逆伝播
- SoftmaxWithLossPlayer
- NormalizationPlayer
- AffinPlayer
- NormalizationPlayer
- WeightSumPlayer
- NormalizationPlayer
- AttentionWeightPlayer
- NormalizationPlayer
- SwishPlayer
- NormalizationPlayer
- AffinPlayer
- SkipAddPlayer
- NormalizationPlayer # 各ポジション毎回、EmbeddingPlayerのdSampleVecVerに入れ込んでいく。
- PositionsParamsPlayer # Layerのパラメータを、自身の変数に保持
## EmbeddingPlayerのbackwardで、dWの完成
- EmbeddingPlayer

```
プレイヤーの実行順番が記載されている。新しいプレイヤーも定義した。

各レイヤーの中に、またプレイヤーとしてまとめていないもの、さらにレイヤーとして未完成なものがほとんどなので、1プレイヤー1プレイヤー、完成させていこう
- NormalizationPlayer,NormalizationLayer
    んー、、LayerとPlayerを交互に見て疲れる…しんどい…パソコンでやりたい…
    NormalizationPlayerは(NormalizationPlayerに限らず)何度か使用してるので、NormalizationPlayer2とか作ってかなきゃね。
    あ、、githubだと
    ![IMG_0182.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3910368/8c228122-2490-f18c-6f1f-f7786421bfe6.png)
    みたいに左しか見えないから
    2_Normalizationとかにしなきゃ、、。
    うーん、基本的にプレイヤーのExecuteMainは
    ```
    // メイン処理を行うメソッド
    public override string ExecuteMain()
    {

        if (initAiTypesPlayer. TravelMode == "Forward")
        {
            // 1つ前のレイヤから、xを取ってくる
            this.x = embeddingPlayer.SampleVecVer[aiFlagsPlayer.NowPositionIndex]
        
            // Forward処理
            this.y = normalizationLayer.Forward(this.x)
        }
        else if (initAiTypesPlayer. TravelMode == "Backward")
        {
            // ひとつ先のLayerから、doutを取ってくる
            this.dout = skipAddPlayer.dx
        
            // backward
            this.dx = normalizationLayer.Backward(this.dout)
            
            // このポジション終了したので+=1
            aiFlagsPlayer.NowPositionIndex += 1;
        }
    ```
    1つ前のプレイヤーから取って来る感じでいいかな、、。
    Pythonみたいにインスタンスをリストで管理できないから、if分岐で実行する処置をとった。U#はオブジェクト指向プログラミングがやりにくいですね…。
    
## 2024-12-13
- SkipAddPlayer, SkipAddLayer
    - Player
        - ExecuteMain
            ifでForward分岐
    - Layer
        ForwardとBackwardの機能がなんか逆だったから訂正。
        Skip先はAffineLayer2とし、AffineLayer2自身でSkipAddPlayerにアクセスしてyを取得して加算させることにする。
- AffinePlayer(1つ目)
    - プレイヤー

はい。
あ、PlayerのPlayerResetメソッドで
Layerの初期化してないや。
やろう。
(邪心発散：上京アフロ田中の次のシリーズってあるのかな…見たい)
(邪心発散：ぁぁ、、UdonSharpはふたつ先のスーパーレイヤ取れないっていう噂だし、、とりあえずハードコーディングするしかないよね…全部で10超過位のレイヤ数だし、すぐだよ、すぐ。)

…なんだっけ
ああ、初期かね。
いいや。

- NormalizationPlayer2
- SwishPlayer
- NormalizationPlayer3
## 2024-12-16
- NormalizationPlayer3
- AttentionWeightPlayer
    - AttentionLayer
    さて。そうですね、Forwardで、1つ前のポジションと、自身のhをまとめhsにしなければならない。
    ポジションの順伝逆伝が1つ終わると、レイヤのパラメータはParamsPlayerの2次元ベクトルに
わー、、
```
入力は、int型。
出力は、
って、、ああ、なんか出来ちゃったよ、笑

ちょっとベクトルの書き方が数学的にやったことないから（園芸科学科の専門高校だったから…線形代数習わなかったの…悔しい）あれだけど、
[y1,y2,y3] = 3x + [0,1,2]
で出来そうね。
y=ax+bで考えてみたよ。バイアスが個々のインデックスのズレだとすれば、あとは3かけるだけでいけるよね。傾きが3なのね、この式は。
```
だから、、
```
def result_index_of_paramssave(x=None):
    y = []
    bs = [0, 1, 2]
    a = self.LayersParamSize * self.LayerSize
    for b in bs:
        y.append(a * x + b)
    return y
```
として保存しよう
chatGPTに変換させて、さらに細かいところの修正、ほかプレイヤーからの引き継ぎ
```
    public int[] ResultIndexOfParamsSave(int x)
    // 引数：処理中のposition数
    // 戻値：このポジションが保存すべきParamsのIndexs
    {
        // 結果を格納する配列を初期化
        int[] y = new int[3];
        int[] bs = { 0, 1, 2 };
        int[] a = aiSettingsPlayer.LayerParamsSize * aiSettingsPlayer.LayerSize

        // bsの各要素に3 * xを加算してyに格納
        for (int bi = 0; bi < bs.Length;bi++)
        {
            y = rinaNumpy.Append_FloatArray(y, bs[bi] + 3 * x);
        }

        return y;
    }
```

じゃぁAttentionWeightPlayerでは、、
・現在のPositionをforで回す
・ResultIndexOfParamsSaveにiを入れて保存すべき