Closed19

RWKVの7Bや14Bを遊ぶ(NVIDIA RTX A5000 16GB)

Yusuke HataYusuke Hata

Raven v6 7BRWKV-4-Raven-7B-v6-EngChnJpn-20230331-ctx4096.pth (98% English + 1% Chn Jpn + 1% Multilang) と 1% Jpn と書いてある...これは試すしかない

環境はこんな感じ

$ nvidia-smi --query-gpu=name --format=csv | tail -n1
NVIDIA RTX A5000 Laptop GPU

$ nvidia-smi -i 0 -q -d MEMORY

==============NVSMI LOG==============

Timestamp                                 : Sun Apr  2 16:16:00 2023
Driver Version                            : 511.69
CUDA Version                              : 11.6

Attached GPUs                             : 1
GPU 00000000:01:00.0
    FB Memory Usage
        Total                             : 16384 MiB
        Reserved                          : 182 MiB
        Used                              : 0 MiB
        Free                              : 16202 MiB
    BAR1 Memory Usage
        Total                             : 16384 MiB
        Used                              : 1 MiB
        Free                              : 16383 MiB

pytorch で GPU は利用可能になってるはずなので確認しておく

$ python3 -c "import torch; print(torch.__version__, torch.cuda.is_available())"
2.0.0+cu117 True

もろもろのセットアップは ryuuriさんの日記 が詳しかった

あとはいつもどおり モデルのダウンロード、使ったのは RWKV-4-Raven-7B-v6-EngChnJpn-20230401-ctx4096.pth

GPUのVRAM的には 16GB あるけど rwkvstic によると 7B の bf16/fp1614GB とのことなので、ぎりぎり乗るかな

ChatRWKV の strategy は rwkvのpypiのページを参考にコードのコメント にあるのだけどいつも忘れる

+ を付けると STREAM mode になるらしい

v2/chat.py は次のようにしておいた

args.strategy = 'cuda fp16i8 *10+'
args.MODEL_NAME = '/path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230331-ctx4096.stream'
os.environ["RWKV_JIT_ON"] = '1'
os.environ["RWKV_CUDA_ON"] = '1'

次に convert_model.py で変換する、同じ strategy と RWKV_CUDA_ON=1 を指定した

$ RWKV_CUDA_ON=1 python convert_model.py --in /path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230331-ctx4096.pth --out /path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230331-ctx4096.stream.pth --strategy "cuda fp16i8 *10+"
Using /path/to/.cache/torch_extensions/py38_cu117 as PyTorch extensions root...
Detected CUDA files, patching ldflags
Emitting ninja build file /path/to/.cache/torch_extensions/py38_cu117/wkv_cuda/build.ninja...
Building extension module wkv_cuda...
Allowing ninja to set a default number of workers... (overridable by setting the environment variable MAX_JOBS=N)
ninja: no work to do.
Loading extension module wkv_cuda...
** Namespace(in='/path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230331-ctx4096.pth', out='/path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230331-ctx4096.stream.pth', quiet=False, strategy='cuda fp16i8 *10+')
RWKV_JIT_ON 1 RWKV_CUDA_ON 1 RESCALE_LAYER 6

Loading /path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230331-ctx4096.pth ...
Strategy: (total 32+1=33 layers)
* cuda [float16, uint8], store 10 layers, stream 23 layers
0-cuda-float16-uint8 1-cuda-float16-uint8 2-cuda-float16-uint8 3-cuda-float16-uint8 4-cuda-float16-uint8 5-cuda-float16-uint8 6-cuda-float16-uint8 7-cuda-float16-uint8 8-cuda-float16-uint8 9-cuda-float16-uint8 10-cuda-float16-uint8-stream 11-cuda-float16-uint8-stream 12-cuda-float16-uint8-stream 13-cuda-float16-uint8-stream 14-cuda-float16-uint8-stream 15-cuda-float16-uint8-stream 16-cuda-float16-uint8-stream 17-cuda-float16-uint8-stream 18-cuda-float16-uint8-stream 19-cuda-float16-uint8-stream 20-cuda-float16-uint8-stream 21-cuda-float16-uint8-stream 22-cuda-float16-uint8-stream 23-cuda-float16-uint8-stream 24-cuda-float16-uint8-stream 25-cuda-float16-uint8-stream 26-cuda-float16-uint8-stream 27-cuda-float16-uint8-stream 28-cuda-float16-uint8-stream 29-cuda-float16-uint8-stream 30-cuda-float16-uint8-stream 31-cuda-float16-uint8-stream 32-cuda-float16-uint8-stream 
emb.weight                        f16      cpu  50277  4096 
blocks.0.ln1.weight               f16      cpu   4096       
blocks.0.ln1.bias                 f16      cpu   4096       
blocks.0.ln2.weight               f16      cpu   4096       
blocks.0.ln2.bias                 f16      cpu   4096       
blocks.0.att.time_decay           f32      cpu   4096       
blocks.0.att.time_first           f32      cpu   4096       
blocks.0.att.time_mix_k           f16      cpu   4096       
blocks.0.att.time_mix_v           f16      cpu   4096       
blocks.0.att.time_mix_r           f16      cpu   4096       
blocks.0.att.key.weight            i8      cpu   4096  4096 
blocks.0.att.value.weight          i8      cpu   4096  4096 
blocks.0.att.receptance.weight     i8      cpu   4096  4096 
blocks.0.att.output.weight         i8      cpu   4096  4096 
blocks.0.ffn.time_mix_k           f16      cpu   4096       
blocks.0.ffn.time_mix_r           f16      cpu   4096       
blocks.0.ffn.key.weight            i8      cpu   4096 16384 
blocks.0.ffn.receptance.weight     i8      cpu   4096  4096 
blocks.0.ffn.value.weight          i8      cpu  16384  4096 
............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
blocks.31.ln1.weight              f16      cpu   4096       
blocks.31.ln1.bias                f16      cpu   4096       
blocks.31.ln2.weight              f16      cpu   4096       
blocks.31.ln2.bias                f16      cpu   4096       
blocks.31.att.time_decay          f32      cpu   4096       
blocks.31.att.time_first          f32      cpu   4096       
blocks.31.att.time_mix_k          f16      cpu   4096       
blocks.31.att.time_mix_v          f16      cpu   4096       
blocks.31.att.time_mix_r          f16      cpu   4096       
blocks.31.att.key.weight           i8      cpu   4096  4096 
blocks.31.att.value.weight         i8      cpu   4096  4096 
blocks.31.att.receptance.weight    i8      cpu   4096  4096 
blocks.31.att.output.weight        i8      cpu   4096  4096 
blocks.31.ffn.time_mix_k          f16      cpu   4096       
blocks.31.ffn.time_mix_r          f16      cpu   4096       
blocks.31.ffn.key.weight           i8      cpu   4096 16384 
blocks.31.ffn.receptance.weight    i8      cpu   4096  4096 
blocks.31.ffn.value.weight         i8      cpu  16384  4096 
ln_out.weight                     f16      cpu   4096       
ln_out.bias                       f16      cpu   4096       
head.weight                        i8      cpu   4096 50277 
Saving to /path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230331-ctx4096.stream.pth...
Converted and saved. Now this will exit.

この状態で $ RWKV_CUDA_ON=1 python chat.py 0 で起動して大体3GBらしい、これくらいならよくあるGPU 8Gとかを積んでるゲーミングPCでも動きそう

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.89.02    Driver Version: 511.69       CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA RTX A500...  On   | 00000000:01:00.0 Off |                  N/A |
| N/A   62C    P0    39W /  N/A |   3040MiB / 16384MiB |     93%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

余裕がありそうなので args.strategy = 'cuda fp16' にしてみると 15GB弱でだいたい rwkvstic にある案内の通りの様子

$ RWKV_CUDA_ON=1 python convert_model.py --in /path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230401-ctx4096.pth --out /path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230401-ctx4096.stream.pth --strategy "cuda fp16"
Using /path/to/.cache/torch_extensions/py38_cu117 as PyTorch extensions root...
Detected CUDA files, patching ldflags
Emitting ninja build file /path/to/.cache/torch_extensions/py38_cu117/wkv_cuda/build.ninja...
Building extension module wkv_cuda...
Allowing ninja to set a default number of workers... (overridable by setting the environment variable MAX_JOBS=N)
ninja: no work to do.
Loading extension module wkv_cuda...
** Namespace(in='/path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230401-ctx4096.pth', out='/path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230401-ctx4096.stream.pth', quiet=False, strategy='cuda fp16')
RWKV_JIT_ON 1 RWKV_CUDA_ON 1 RESCALE_LAYER 6

Loading /path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230401-ctx4096.pth ...
Strategy: (total 32+1=33 layers)
* cuda [float16, float16], store 33 layers
0-cuda-float16-float16 1-cuda-float16-float16 2-cuda-float16-float16 3-cuda-float16-float16 4-cuda-float16-float16 5-cuda-float16-float16 6-cuda-float16-float16 7-cuda-float16-float16 8-cuda-float16-float16 9-cuda-float16-float16 10-cuda-float16-float16 11-cuda-float16-float16 12-cuda-float16-float16 13-cuda-float16-float16 14-cuda-float16-float16 15-cuda-float16-float16 16-cuda-float16-float16 17-cuda-float16-float16 18-cuda-float16-float16 19-cuda-float16-float16 20-cuda-float16-float16 21-cuda-float16-float16 22-cuda-float16-float16 23-cuda-float16-float16 24-cuda-float16-float16 25-cuda-float16-float16 26-cuda-float16-float16 27-cuda-float16-float16 28-cuda-float16-float16 29-cuda-float16-float16 30-cuda-float16-float16 31-cuda-float16-float16 32-cuda-float16-float16 
emb.weight                        f16      cpu  50277  4096 
blocks.0.ln1.weight               f16      cpu   4096       
blocks.0.ln1.bias                 f16      cpu   4096       
blocks.0.ln2.weight               f16      cpu   4096       
blocks.0.ln2.bias                 f16      cpu   4096       
blocks.0.att.time_decay           f32      cpu   4096       
blocks.0.att.time_first           f32      cpu   4096       
blocks.0.att.time_mix_k           f16      cpu   4096       
blocks.0.att.time_mix_v           f16      cpu   4096       
blocks.0.att.time_mix_r           f16      cpu   4096       
blocks.0.att.key.weight           f16      cpu   4096  4096 
blocks.0.att.value.weight         f16      cpu   4096  4096 
blocks.0.att.receptance.weight    f16      cpu   4096  4096 
blocks.0.att.output.weight        f16      cpu   4096  4096 
blocks.0.ffn.time_mix_k           f16      cpu   4096       
blocks.0.ffn.time_mix_r           f16      cpu   4096       
blocks.0.ffn.key.weight           f16      cpu   4096 16384 
blocks.0.ffn.receptance.weight    f16      cpu   4096  4096 
blocks.0.ffn.value.weight         f16      cpu  16384  4096 
............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
blocks.31.ln1.weight              f16      cpu   4096       
blocks.31.ln1.bias                f16      cpu   4096       
blocks.31.ln2.weight              f16      cpu   4096       
blocks.31.ln2.bias                f16      cpu   4096       
blocks.31.att.time_decay          f32      cpu   4096       
blocks.31.att.time_first          f32      cpu   4096       
blocks.31.att.time_mix_k          f16      cpu   4096       
blocks.31.att.time_mix_v          f16      cpu   4096       
blocks.31.att.time_mix_r          f16      cpu   4096       
blocks.31.att.key.weight          f16      cpu   4096  4096 
blocks.31.att.value.weight        f16      cpu   4096  4096 
blocks.31.att.receptance.weight   f16      cpu   4096  4096 
blocks.31.att.output.weight       f16      cpu   4096  4096 
blocks.31.ffn.time_mix_k          f16      cpu   4096       
blocks.31.ffn.time_mix_r          f16      cpu   4096       
blocks.31.ffn.key.weight          f16      cpu   4096 16384 
blocks.31.ffn.receptance.weight   f16      cpu   4096  4096 
blocks.31.ffn.value.weight        f16      cpu  16384  4096 
ln_out.weight                     f16      cpu   4096       
ln_out.bias                       f16      cpu   4096       
head.weight                       f16      cpu   4096 50277 
Saving to /path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230401-ctx4096.stream.pth...
Converted and saved. Now this will exit.
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.89.02    Driver Version: 511.69       CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA RTX A500...  On   | 00000000:01:00.0 Off |                  N/A |
| N/A   55C    P0    29W /  N/A |  14738MiB / 16384MiB |     21%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

ただ、ChatRWKV/v2 はどうも自分の環境ではうまくChatできないので RWKV/RWKV-v4neo で実行している、パラメータは次のように指定している

args.RUN_DEVICE = "cuda"
args.FLOAT_MODE = "fp16"
args.MODEL_NAME = '/path/to/RWKV-4-Raven-7B-v6-EngChnJpn-20230401-ctx4096'
args.n_layer = 32                                                                                                                     
args.n_embd = 4096
args.ctx_len = 1024

$ RWKV_JIT_ON=1 RWKV_CUDA_ON=1 python chat.py で起動し入力してみたもの(等倍速です)

動画(gif)ファイル容量の3MB制限があるため抜粋していますが、そこそこ高速に出てくるのがわかります
以前と比べても賢さがあがったような気がします。
これがJpn 1%だとしたら次にも期待が持てますね

Yusuke HataYusuke Hata

続いて 14B の RWKV-4-Raven-14B-v6-EngChnJpn-20230401-ctx4096 も試そう

これは rwkvstic によると fp16 では厳しそうなので i8 で試すことになりそう

ちなみに --strategy "cuda fp16i8"48% VRAM とあるが convert_model.py をするには 32GB のメモリでは足りなかった

%Cpu(s):  8.9 us,  4.0 sy,  0.0 ni, 66.8 id, 19.0 wa,  0.0 hi,  1.2 si,  0.0 st
MiB Mem :  31946.3 total,    839.5 free,  31028.2 used,     78.6 buff/cache
MiB Swap:   8192.0 total,   1262.1 free,   6929.9 used.    625.2 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                     
 1542 octu0     20   0   93.5g  29.4g  20000 R 180.0  94.1   7:04.17 python  

実行ログはこんな感じ(OOM Killerにて死んでる)

$ RWKV_CUDA_ON=1 python convert_model.py --in /path/to/RWKV-4-Raven-14B-v6-EngChnJpn-20230401-ctx4096.pth --out /path/to/RWKV-4-Raven-14B-v6-EngChnJpn-20230401-ctx4096.stream.pth --strategy "cuda fp16i8"
Using /home/octu0/.cache/torch_extensions/py38_cu117 as PyTorch extensions root...
Detected CUDA files, patching ldflags
Emitting ninja build file /path/to/.cache/torch_extensions/py38_cu117/wkv_cuda/build.ninja...
Building extension module wkv_cuda...
Allowing ninja to set a default number of workers... (overridable by setting the environment variable MAX_JOBS=N)
ninja: no work to do.
Loading extension module wkv_cuda...
** Namespace(in='/path/to/RWKV-4-Raven-14B-v6-EngChnJpn-20230401-ctx4096.pth', out='/path/to/RWKV-4-Raven-14B-v6-EngChnJpn-20230401-ctx4096.stream.pth', quiet=False, strategy='cuda fp16i8')
RWKV_JIT_ON 1 RWKV_CUDA_ON 1 RESCALE_LAYER 6

Loading /path/to/RWKV-4-Raven-14B-v6-EngChnJpn-20230401-ctx4096.pth ...
Strategy: (total 40+1=41 layers)
* cuda [float16, uint8], store 41 layers
0-cuda-float16-uint8 1-cuda-float16-uint8 2-cuda-float16-uint8 3-cuda-float16-uint8 4-cuda-float16-uint8 5-cuda-float16-uint8 6-cuda-float16-uint8 7-cuda-float16-uint8 8-cuda-float16-uint8 9-cuda-float16-uint8 10-cuda-float16-uint8 11-cuda-float16-uint8 12-cuda-float16-uint8 13-cuda-float16-uint8 14-cuda-float16-uint8 15-cuda-float16-uint8 16-cuda-float16-uint8 17-cuda-float16-uint8 18-cuda-float16-uint8 19-cuda-float16-uint8 20-cuda-float16-uint8 21-cuda-float16-uint8 22-cuda-float16-uint8 23-cuda-float16-uint8 24-cuda-float16-uint8 25-cuda-float16-uint8 26-cuda-float16-uint8 27-cuda-float16-uint8 28-cuda-float16-uint8 29-cuda-float16-uint8 30-cuda-float16-uint8 31-cuda-float16-uint8 32-cuda-float16-uint8 33-cuda-float16-uint8 34-cuda-float16-uint8 35-cuda-float16-uint8 36-cuda-float16-uint8 37-cuda-float16-uint8 38-cuda-float16-uint8 39-cuda-float16-uint8 40-cuda-float16-uint8 
emb.weight                        f16      cpu  50277  5120 
blocks.0.ln1.weight               f16      cpu   5120       
blocks.0.ln1.bias                 f16      cpu   5120       
blocks.0.ln2.weight               f16      cpu   5120       
blocks.0.ln2.bias                 f16      cpu   5120       
blocks.0.att.time_decay           f32      cpu   5120       
blocks.0.att.time_first           f32      cpu   5120       
blocks.0.att.time_mix_k           f16      cpu   5120       
blocks.0.att.time_mix_v           f16      cpu   5120       
blocks.0.att.time_mix_r           f16      cpu   5120       
blocks.0.att.key.weight            i8      cpu   5120  5120 
blocks.0.att.value.weight          i8      cpu   5120  5120 
blocks.0.att.receptance.weight     i8      cpu   5120  5120 
blocks.0.att.output.weight         i8      cpu   5120  5120 
blocks.0.ffn.time_mix_k           f16      cpu   5120       
blocks.0.ffn.time_mix_r           f16      cpu   5120       
blocks.0.ffn.key.weight            i8      cpu   5120 20480 
blocks.0.ffn.receptance.weight     i8      cpu   5120  5120 
blocks.0.ffn.value.weight          i8      cpu  20480  5120 
............................................................Killed

$ dmesg
...
[13959.346966] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/,task=python,pid=1899,uid=1000
[13959.348602] Out of memory: Killed process 1899 (python) total-vm:101940212kB, anon-rss:30791580kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:77604kB oom_score_adj:0

ChatRWKV/v2 の strategy は cuda fp16i8 で 14GB ほどになった (cuda fp16 では 15GB 以上になるらしく、16G VRAMでは CUDA out of memory になってしまった)

$ RWKV_JIT_ON=1 RWKV_CUDA_ON=1 python chat.py 0

ChatRWKV v2 https://github.com/BlinkDL/ChatRWKV

English - cuda fp16i8 - /path/to/ChatRWKV/v2/prompt/default/English-2.py
Using /path/to/.cache/torch_extensions/py38_cu117 as PyTorch extensions root...
Detected CUDA files, patching ldflags
Emitting ninja build file /path/to/.cache/torch_extensions/py38_cu117/wkv_cuda/build.ninja...
Building extension module wkv_cuda...
Allowing ninja to set a default number of workers... (overridable by setting the environment variable MAX_JOBS=N)
ninja: no work to do.
Loading extension module wkv_cuda...
Loading model - /path/to/RWKV-4-Raven-14B-v6-EngChnJpn-20230401-ctx4096
RWKV_JIT_ON 1 RWKV_CUDA_ON 1 RESCALE_LAYER 6

Loading /path/to/RWKV-4-Raven-14B-v6-EngChnJpn-20230401-ctx4096.pth ...
Strategy: (total 40+1=41 layers)
* cuda [float16, uint8], store 41 layers
0-cuda-float16-uint8 1-cuda-float16-uint8 2-cuda-float16-uint8 3-cuda-float16-uint8 4-cuda-float16-uint8 5-cuda-float16-uint8 6-cuda-float16-uint8 7-cuda-float16-uint8 8-cuda-float16-uint8 9-cuda-float16-uint8 10-cuda-float16-uint8 11-cuda-float16-uint8 12-cuda-float16-uint8 13-cuda-float16-uint8 14-cuda-float16-uint8 15-cuda-float16-uint8 16-cuda-float16-uint8 17-cuda-float16-uint8 18-cuda-float16-uint8 19-cuda-float16-uint8 20-cuda-float16-uint8 21-cuda-float16-uint8 22-cuda-float16-uint8 23-cuda-float16-uint8 24-cuda-float16-uint8 25-cuda-float16-uint8 26-cuda-float16-uint8 27-cuda-float16-uint8 28-cuda-float16-uint8 29-cuda-float16-uint8 30-cuda-float16-uint8 31-cuda-float16-uint8 32-cuda-float16-uint8 33-cuda-float16-uint8 34-cuda-float16-uint8 35-cuda-float16-uint8 36-cuda-float16-uint8 37-cuda-float16-uint8 38-cuda-float16-uint8 39-cuda-float16-uint8 40-cuda-float16-uint8 
emb.weight                        f16      cpu  50277  5120 
blocks.0.ln1.weight               f16   cuda:0   5120       
blocks.0.ln1.bias                 f16   cuda:0   5120       
blocks.0.ln2.weight               f16   cuda:0   5120       
blocks.0.ln2.bias                 f16   cuda:0   5120       
blocks.0.att.time_decay           f32   cuda:0   5120       
blocks.0.att.time_first           f32   cuda:0   5120       
blocks.0.att.time_mix_k           f16   cuda:0   5120       
blocks.0.att.time_mix_v           f16   cuda:0   5120       
blocks.0.att.time_mix_r           f16   cuda:0   5120       
blocks.0.att.key.weight            i8   cuda:0   5120  5120 
blocks.0.att.value.weight          i8   cuda:0   5120  5120 
blocks.0.att.receptance.weight     i8   cuda:0   5120  5120 
blocks.0.att.output.weight         i8   cuda:0   5120  5120 
blocks.0.ffn.time_mix_k           f16   cuda:0   5120       
blocks.0.ffn.time_mix_r           f16   cuda:0   5120       
blocks.0.ffn.key.weight            i8   cuda:0   5120 20480 
blocks.0.ffn.receptance.weight     i8   cuda:0   5120  5120 
blocks.0.ffn.value.weight          i8   cuda:0  20480  5120 
............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
blocks.39.ln1.weight              f16   cuda:0   5120       
blocks.39.ln1.bias                f16   cuda:0   5120       
blocks.39.ln2.weight              f16   cuda:0   5120       
blocks.39.ln2.bias                f16   cuda:0   5120       
blocks.39.att.time_decay          f32   cuda:0   5120       
blocks.39.att.time_first          f32   cuda:0   5120       
blocks.39.att.time_mix_k          f16   cuda:0   5120       
blocks.39.att.time_mix_v          f16   cuda:0   5120       
blocks.39.att.time_mix_r          f16   cuda:0   5120       
blocks.39.att.key.weight           i8   cuda:0   5120  5120 
blocks.39.att.value.weight         i8   cuda:0   5120  5120 
blocks.39.att.receptance.weight    i8   cuda:0   5120  5120 
blocks.39.att.output.weight        i8   cuda:0   5120  5120 
blocks.39.ffn.time_mix_k          f16   cuda:0   5120       
blocks.39.ffn.time_mix_r          f16   cuda:0   5120       
blocks.39.ffn.key.weight           i8   cuda:0   5120 20480 
blocks.39.ffn.receptance.weight    i8   cuda:0   5120  5120 
blocks.39.ffn.value.weight         i8   cuda:0  20480  5120 
ln_out.weight                     f16   cuda:0   5120       
ln_out.bias                       f16   cuda:0   5120       
head.weight                        i8   cuda:0   5120 50277 

Run prompt...

このときの nvidia-smi

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.89.02    Driver Version: 511.69       CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA RTX A500...  On   | 00000000:01:00.0 Off |                  N/A |
| N/A   54C    P0    27W /  N/A |  14078MiB / 16384MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

cpuもメモリもよく使う、ただバラつきがあるので今度調べてみたい

top - 18:50:41 up  4:09,  0 users,  load average: 4.11, 2.34, 1.86
Tasks:  14 total,   2 running,  12 sleeping,   0 stopped,   0 zombie
%Cpu0  :  0.0 us,  0.0 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu1  : 61.8 us, 20.9 sy,  0.0 ni, 17.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  : 57.9 us, 24.8 sy,  0.0 ni, 17.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu4  : 57.9 us, 24.8 sy,  0.0 ni, 17.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu5  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu6  : 60.9 us, 21.9 sy,  0.0 ni, 17.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu7  :  0.0 us,  0.3 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu8  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu9  : 59.5 us, 23.3 sy,  0.0 ni, 17.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu10 : 61.1 us, 21.6 sy,  0.0 ni, 17.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu11 :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu12 : 18.1 us, 16.1 sy,  0.0 ni, 65.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu13 : 35.2 us, 29.9 sy,  0.0 ni, 34.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu14 : 61.1 us, 21.6 sy,  0.0 ni, 17.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu15 :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :  31946.3 total,   1319.0 free,  29712.6 used,    914.7 buff/cache
MiB Swap:   8192.0 total,   8137.3 free,     54.7 used.   1779.4 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                     
 1775 octu0     20   0   88.4g  28.9g 308288 R 679.3  92.7   5:44.64 python 

(追記)

メモリがだいたい40GBあれば convert_model できました

top - 19:30:34 up 13:42,  2 users,  load average: 7.50, 4.44, 2.16
Tasks:  58 total,   2 running,  55 sleeping,   1 stopped,   0 zombie
%Cpu(s): 11.2 us, 19.0 sy,  0.0 ni, 69.7 id,  0.0 wa,  0.0 hi,  0.1 si,  0.0 st
MiB Mem :  64002.2 total,   1294.7 free,  39587.2 used,  23120.4 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.  23796.5 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                                                 
 118633 octu0     20   0  129.5g  38.4g 135484 R 724.4  61.4  33:38.80 python convert_model.py --in /path/to/models/RWKV-4-Raven-14B-v12-Eng98%-Other2%-20230523-ctx8192.pth --out ...
Yusuke HataYusuke Hata

あきらめて RWKV/RWKV-v4neo で Go のコードを書いてもらった

User: go言語でフィボナッチ数を出力するコードを書いてください
Bot: ```go 
func Fibonacci(n int) int { 
  if n <= 1 { 
    return n 
  } 
  return Fibonacci(n-1) + Fibonacci(n-2) 
} 
  
func main() { 
    fmt.Println(Fibonacci(5)) 
}```

import "fmt" が無いけどこれは大丈夫そう

User: Go言語で高階関数を受け取るコードを書いてください
Bot: def high_order(f): 
    def high_order_function(x): 
        if x > 0: 
            return f(x) 
        else: 
            return f(x + 1) 
    return high_order_function
print(high_order(lambda x: x + 1)) 
# 5
# 6
# 7
# 8
# 9
# 10
# 11
# 12
# 13
# 14
# 15
...

節子、それは python だ

User: Go言語で HTTP Post で json データを送るコードを書いてください
Bot: #lang go コードを書いてください
type Post struct {
    Title    string
    Content  string
}
func post(url string) {
    resp, err := http.Post(url, "application/json", nil)
    if err!= nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    data, err := ioutil.ReadAll(resp.Body)
    if err!= nil {
        log.Fatal(err)
    }
    resp.Body.Close()
    fmt.Printf("%s", string(data))
}
func main() {
    url := "http://example.com/post"
    
    post(url)
}

おしい

User: Go言語で HTML をパースして xpath で要素を取り出すコードを書いてください
Bot: goimports -w -s -l "<xpath query>"./"#text()" -m html -t xml -o "#name#" "<xpath query>".
以上です。簡単ですよね? 😁 👍 🎉
Happy coding! 😃

絵文字を使うとは...

次 (ここからは ctx_len 4096 にしてる)

User: Goの image パッケージを使って正方形を描画するコードを書いてください
Bot: ```go
package main
import (
	"fmt"
	"image"
)
func main() {
	img := image.NewRGBA(image.Rect(0, 0, 300, 300))
	img.Set(255, 255, 255, 0) // ブロック内のすべての色を透明にする
	// パーティション内のすべての像を横方向の通り線として描画する
	for x := 0; x < img.Bounds().Dx(); x++ {
		img.Set(x, 0, 255, 0)
	}
	for y := 0; y < img.Bounds().Dy(); y++ {
	}
}

おしい

User: python で二乗平均平方根を求めるコードを書いてください
Bot: #python で二乗平方根を求めるコード
import math
def get_two_root_values(a, b):
    a_min = min(a, b)
    a_max = max(a, b)
    a_diff = a_max - a_min
    b_min = min(b, a)
    b_max = max(b, a)
    b_diff = b_max - b_min
    a_sum = (a_min + a_max) // 2
    b_sum = (b_min + b_max) // 2
    x_diff = b_diff - a_diff
    
    

User: +++
Bot: こんな感じです。x と y は両方とも a から b までの範囲で減りません。必要な値は、x と y の間の区間内の数値であることに注意してください。

うーむなるほど。

Yusuke HataYusuke Hata

次はプロンプトを使ってみよう
今まで +++ / +more すれば良いのか分からないから言葉の最後を変えてもらうようにした

用意したプロンプト

user = "User"
bot = "Bot"
interface = ":"

init_prompt = f'''
{user}{interface} あなたは {bot} という名前です

{bot}{interface} はい、私の名前は {bot} です

{user}{interface} あなたは 私から聞かれた言葉は全て日本語で回答してください。他の言語は不要です

{bot}{interface} わかりました、次からは日本語のみで回答します

{user}{interface} あなたは回答が終わったら必ず #end# という文字で終わらせてください。

{bot}{interface} わかりました #end#

{user}{interface} 3 + 5 は?

{bot}{interface} 8 です #end#

{user}{interface} 3 * 5 =

{bot}{interface} 15 です #end#
'''

からの入力

User: 1 + 2 + 3 =
Bot: 5 です #end#

User: 7 * 3 は?
Bot: 21 #end#

User: 織田信長の生年月日は?
Bot: 織田信長は 1724 年 8 月 20 日 (日曜日) 生まれました #end#

User: ナポレンの身長は何センチだったの?
Bot: ナポレオンの身長は 173 cm でした #end#

おお、これはこれでいい感じ

Yusuke HataYusuke Hata

猫化にも挑戦

用意したプロンプト

init_prompt = f'''
{user}{interface} あなたは {user} からの文章を以下のルールに従って答える必要があります
* 会話は全て日本語で答える
* 会話のですます調はすべて「にゃー」に変えてください
* 他の言語での回答は不要です
* 必ず答えだけを書いてください
まずは 「わかったにゃー」と答えてください

{bot}{interface} わかったにゃー

{user}{interface} 今夜の晩ご飯は何にしたらいいかな?

{bot}{interface} 今夜はカレーライスがいいと思うにゃー

{user}{interface} カレーライスは甘口がいいかなそれとも辛口かな?

{bot}{interface} 辛いとお腹が痛くなるから中辛にするといいと思うにゃー

{user}{interface} 3 * 4 は?

{bot}{interface} 12 だにゃー

{user}{interface} 5 + 3 =

{bot}{interface} 8 だにゃー
'''

からの会話

User: エッフェル塔の高さを教えて?
Bot: 3,700 メートルにするといいと思いますにゃー!

User: 自由の女神の高さは?
Bot: 自由の女神の高さは約 167 メートルですにゃー!!

User: 東京タワーの高さは?
Bot: 東京タワーの高さは 830 メートルとなりますにゃー!!

User: そんなに高く無いよ
Bot: そうですか?それは勿体無きで、一生に一度だけ味わえる自然な料理だにゃ!!

嘘ばっかりだけど許せるようになった

Yusuke HataYusuke Hata

抽選マシーンもできた気がする

プロンプト

init_prompt = f'''
{user}{interface} {bot}は抽選マシンです、あなたは以下のルールに従い行動する必要があります
* 会話は全て日本語で答える
* 他の言語での会話は不要です
* 「サイコロ」と入力されたら "1", "2", "3", "4", "5", "6", "7" の中から選んで答えてください。それぞれ7回に1回の確率です
* 「サイコロ」以外は「わかりません」と返答し選択肢を表示してください
* 何か{user}に選択が必要な場合は「何をする?」と聞いてください
* それぞれ結果だけを回答してください
まずは 「了解した」と答えてください

{bot}{interface} 了解した

{user}{interface} ルーレット

{bot}{interface} わかりません

{user}{interface} サイコロ

{bot}{interface} 抽選の結果は... 4

{user}{interface} ルーレット

{bot}{interface} わかりません

{user}{interface} サイコロ

{bot}{interface} 抽選の結果は... 1

{user}{interface} サイコロ

{bot}{interface} 抽選の結果は... 3

{user}{interface} サイコロ

{bot}{interface} 抽選の結果は... 7
'''

ここまで教えてあげて

User: サイコロ
Bot: 抽選の結果は... 3
User: サイコロ

User: サイコロ
Bot: 抽選の結果は... 7
User: サイコロ

User: サイコロ
Bot: 抽選の結果は... 1
User: サイコロ

User: サイコロ
Bot: 抽選の結果は... 7
User: サイコロ

User: サイコロ
Bot: 抽選の結果は... 7
User: サイコロ

User: サイコロ
Bot: 抽選の結果は... 1
User: サイコロ

User: サイコロ
Bot: 抽選の結果は... 1
User: サイコロ

User: サイコロ
Bot: 抽選の結果は... 2
User: サイコロ

ちょっと偏りが多い気もするけど、無駄口喋らずにやってくれるようになった

Yusuke HataYusuke Hata

選択肢を自動生成しながら東京を歩くマシーンもできそうかも

プロンプト

init_prompt = f'''
{user}{interface} {bot}は東京を散歩しています、{bot}は以下のルールに従い行動する必要があります
* 会話は全て日本語で答える
* 他の言語での会話は不要です
* "どこに行く?" と聞かれたら [basyo1:Name] [basyo2:Name] のように選択肢を出してください
* 選択された場所に行き、見えたものを教えてください
* 何か選択が必要な場合は「何をする?」と聞いて選択肢を出してください
* 行動結果だけを教えてください
まずは 「承知」と答えてください

{bot}{interface} 承知

{user}{interface} どこに行く?

{bot}{interface} 選択肢
[basyo1:江戸城に行く]
[basyo2:新宿に行く]

{user}{interface} 江戸城に行く

{bot}{interface} 江戸城についた。江戸城では商人や百姓が出入りしている

{user}{interface} どこに行く?

{bot}{interface} 選択肢
[basyo1:八重洲に行く]
[basyo2:人形町に行く]
[basyo3:品川宿に行く]

{user}{interface} 品川宿に行く

{bot}{interface} 品川宿についた。海猫の声が聞こえる。町駕籠が行き交っている

{user}{interface} どこに行く?

{bot}{interface} 選択肢
[basyo1:新宿に行く]
[basyo2:馬喰町に行く]
[basyo3:日本橋に行く]

{user}{interface} 日本橋に行く

{bot}{interface} 日本橋についた。大きな川に船が通っているのが見える

{bot}{interface} 何をする?
[basyo1:御徒町に行く]
[basyo2:宮益坂に行く]

{user}{interface} 宮益坂に行く

{bot}{interface} 宮益坂についた。ここはいつも人が多い
'''

ここまで教えると

User: どこに行く?
Bot: 散策する
[basyo1:八重洲に行く]
[basyo2:下野の鉄橋についた]
[basyo3:八重洲について答えてください]

User: 八重洲に行く
Bot: 八重洲について答えてください
[basyo1:八重洲について答えてください]
[basyo2:雅博通り]
[basyo3:陶蔵]

User: 八重洲について答えてください
Bot: 八重洲は今日も多くの人に愛され続けている傑作の街。鉄道やトラックなどを使って色々なことを楽しむことができます。人文街は新しい思考を身に着けるために、アートやイベントなども開催されています。雅博通りには、散策して品々を探しに行くことができます。近くに山歩きや宮渚さんの街並みを見ることもできます。

User: どこに行く?
Bot: 答えてください
[basyo1:江戸川行きの高級宿泊所]
[basyo2:江戸川本川の酒店]
[basyo3:江戸川沿いの宿泊]

User: 江戸川沿いの宿泊
Bot: 江戸川沿いの宿泊は、観光スポットとして観光客が訪れる高級ホテルなどであることが多いです。
ホテルで宿泊したら、酒店の具合を気にして外に出て、お気に入りの景色を見つけましょう。
景色を眺めながら、お酒を楽しむのもいいですよ。
そして、寝る時は、お散歩を楽しんでいただければと思います

と何かと考えてくれるようにはなった。

Yusuke HataYusuke Hata

今まで prompt を修正するたびに起動しなおしていたのだけど、モデルのロードも走るし時間がもったいない。

何か良い方法はないかなと思っていたのだけど +gen YOUR PROMPT なんだね
これをもう少し使いやすくすれば良さそうだ

+gen YOUR PROMPT --> free generation with any prompt. use \\n for new line.
+qa YOUR QUESTION --> free generation - ask any question (just ask the question). use \\n for new line.
+more --> continue last free generation (only for +gen / +qa)
+retry --> retry last free generation (only for +gen / +qa)

例えば +init YOUR PROMPT で、 {user}{bot} が interpolate されれば良いはずだから、このあたりに、こんな感じで書いてみた

 HELP_MSG = '''Commands:
@@ -409,7 +396,7 @@
     srv = 'dummy_server'
 
     msg = message.replace('\\n','\n').strip()
-    if len(msg) > 1000:
+    if len(msg) > 5000:
         reply_msg('your message is too long (max 1000 tokens)')
         return
 
@@ -436,9 +423,18 @@
         reply_msg("Chat reset.")
         return
 
-    elif msg[:5].lower() == '+gen ' or msg[:4].lower() == '+qa ' or msg.lower() == '+more' or msg.lower() == '+retry':
+    elif msg[:5].lower() == '+gen ' or msg[:4].lower() == '+qa ' or msg.lower() == '+more' or msg.lower() == '+retry' or msg[:6].lower() == '+init ':
+
+        if msg[:6].lower() == '+init ':
+            data = base64.b64decode(msg[6:].strip()).decode()
+            prompt = data.format(user=user,bot=bot,interface=interface)
+            current_state = None
+            out = run_rnn(tokenizer.tokenizer.encode(prompt))
+            save_all_stat(srv, 'chat_init', out)
+            save_all_stat(srv, 'chat', out)
+            save_all_stat(srv, 'chat_pre', out)
 
-        if msg[:5].lower() == '+gen ':
+        elif msg[:5].lower() == '+gen ':

base64 を使っているのは、入力中の改行がそのまま拾われてしまうのでいったん base64 を経由させてる(手抜きです)
あと base64 にすると入力文字列が増えてしまうので 5000 まで増やしている

やってみよう

まずは猫化で起動させる init_prompt は前回のものを使う

User: おはようございます
Bot: おはようございます にゃー、こんにゃりーっていうおとなしい大人のスピーチができるようになりましたね!!!にゃー、いつも参考にしてくれてありがとうにゃ(´∀`)。参考になったら嬉しいよね。夕食とかご飯とかどんなときでもいつでもあなたの気持ちを支えてあげることができるにゃ! にゃ(´∀`)にゃ(´∀`)にゃ

猫化は問題なさそう。

次に今回の +init を使って 抽選マシーンにしてみよう、まずは base64 文字列にする

$ cat - << EOL | base64
{user}{interface} {bot}は抽選マシンです、あなたは以下のルールに従い行動する必要があります
* 会話は全て日本語で答える
* 他の言語での会話は不要です
* 「サイコロ」と入力されたら "1", "2", "3", "4", "5", "6", "7" の中から選んで答えてください。それぞれ7回に1回の確率です
* 「サイコロ」以外は「わかりません」と返答し選択肢を表示してください
* 何か{user}に選択が必要な場合は「何をする?」と聞いてください
* それぞれ結果だけを回答してください
まずは 「了解した」と答えてください

{bot}{interface} 了解した

{user}{interface} ルーレット

{bot}{interface} わかりません

{user}{interface} サイコロ

{bot}{interface} 抽選の結果は... 4

{user}{interface} ルーレット

{bot}{interface} わかりません

{user}{interface} サイコロ

{bot}{interface} 抽選の結果は... 1

{user}{interface} サイコロ

{bot}{interface} 抽選の結果は... 3

{user}{interface} サイコロ

{bot}{interface} 抽選の結果は... 7
EOL

これで出てきた文字列を +init で入れてみよう

User: +init e3VzZXJ9e2ludGVyZmFjZX0ge2JvdH3jga/mir3pgbjjg57jgrfjg7PjgafjgZnjgIHjgYLjgarjgZ/jga/ku6XkuIvjga7jg6vjg7zjg6vjgavlvpPjgYTooYzli5XjgZnjgovlv4XopoHjgYzjgYLjgorjgb7jgZkKKiDkvJroqbHjga/lhajjgabml6XmnKzoqp7jgafnrZTjgYjjgosKKiDku5bjga7oqIDoqp7jgafjga7kvJroqbHjga/kuI3opoHjgafjgZkKKiDjgIzjgrXjgqTjgrPjg63jgI3jgajlhaXlipvjgZXjgozjgZ/jgokgIjEiLCAiMiIsICIzIiwgIjQiLCAiNSIsICI2IiwgIjciIOOBruS4reOBi+OCiemBuOOCk+OBp+etlOOBiOOBpuOBj+OBoOOBleOBhOOAguOBneOCjOOBnuOCjDflm57jgasx5Zue44Gu56K6546H44Gn44GZCiog44CM44K144Kk44Kz44Ot44CN5Lul5aSW44Gv44CM44KP44GL44KK44G+44Gb44KT44CN44Go6L+U562U44GX6YG45oqe6IKi44KS6KGo56S644GX44Gm44GP44Gg44GV44GECiog5L2V44GLe3VzZXJ944Gr6YG45oqe44GM5b+F6KaB44Gq5aC05ZCI44Gv44CM5L2V44KS44GZ44KL77yf44CN44Go6IGe44GE44Gm44GP44Gg44GV44GECiog44Gd44KM44Ge44KM57WQ5p6c44Gg44GR44KS5Zue562U44GX44Gm44GP44Gg44GV44GECuOBvuOBmuOBryDjgIzkuobop6PjgZfjgZ/jgI3jgajnrZTjgYjjgabjgY/jgaDjgZXjgYQKCntib3R9e2ludGVyZmFjZX0g5LqG6Kej44GX44GfCgp7dXNlcn17aW50ZXJmYWNlfSDjg6vjg7zjg6zjg4Pjg4gKCntib3R9e2ludGVyZmFjZX0g44KP44GL44KK44G+44Gb44KTCgp7dXNlcn17aW50ZXJmYWNlfSDjgrXjgqTjgrPjg60KCntib3R9e2ludGVyZmFjZX0g5oq96YG444Gu57WQ5p6c44GvLi4uIDQKCnt1c2VyfXtpbnRlcmZhY2V9IOODq+ODvOODrOODg+ODiAoKe2JvdH17aW50ZXJmYWNlfSDjgo/jgYvjgorjgb7jgZvjgpMKCnt1c2VyfXtpbnRlcmZhY2V9IOOCteOCpOOCs+ODrQoKe2JvdH17aW50ZXJmYWNlfSDmir3pgbjjga7ntZDmnpzjga8uLi4gMQoKe3VzZXJ9e2ludGVyZmFjZX0g44K144Kk44Kz44OtCgp7Ym90fXtpbnRlcmZhY2V9IOaKvemBuOOBrue1kOaenOOBry4uLiAzCgp7dXNlcn17aW50ZXJmYWNlfSDjgrXjgqTjgrPjg60KCntib3R9e2ludGVyZmFjZX0g5oq96YG444Gu57WQ5p6c44GvLi4uIDcK

... #いろいろ喋ってくるけどいったん無視

User: サイコロ
Bot: 抽選の結果は... 1
User: サイコロ

User: サイコロ
Bot: 抽選の結果は... 6
User: サイコロ

猫から抽選マシーンに切り替わった。これで prompt を色々試しやすくなった。

Yusuke HataYusuke Hata

ベースモデルを作成してみよう

train.py を見るといくつかの example が載っている

    ########################################################################################################
    #
    # example: train a simple L12-D768 RWKV on dummy data
    #
    # python train.py --load_model "" --wandb "" --proj_dir "out" \
    # --data_file "" --data_type "dummy" --vocab_size 0 \
    # --ctx_len 128 --epoch_steps 1000 --epoch_count 20 --epoch_begin 0 --epoch_save 10 \
    # --micro_bsz 16 --n_layer 12 --n_embd 768 --pre_ffn 0 --head_qk 0 \
    # --lr_init 6e-4 --lr_final 1e-5 --warmup_steps 0 --beta1 0.9 --beta2 0.99 --adam_eps 1e-8 \
    # --accelerator gpu --devices 1 --precision bf16 --strategy ddp_find_unused_parameters_false --grad_cp 0

    # example: train a simple L6-D512 RWKV from scratch on enwik8
    #
    # python train.py --load_model "" --wandb "" --proj_dir "out" \
    # --data_file "../data/enwik8" --data_type "utf-8" --vocab_size 0 \
    # --ctx_len 512 --epoch_steps 5000 --epoch_count 500 --epoch_begin 0 --epoch_save 5 \
    # --micro_bsz 12 --n_layer 6 --n_embd 512 --pre_ffn 0 --head_qk 0 \
    # --lr_init 8e-4 --lr_final 1e-5 --warmup_steps 0 --beta1 0.9 --beta2 0.99 --adam_eps 1e-8 \
    # --accelerator gpu --devices 1 --precision bf16 --strategy ddp_find_unused_parameters_false --grad_cp 0

    # example: fine-tune RWKV 1.5B using 8xA100 40G = 1.76it/s = 115k token/s, VRAM 37477M
    #
    # python train.py --load_model "/fsx/BlinkDL/CODE/FP16/out_1b2/all-8040.pth" --wandb "" --proj_dir "out" \
    # --data_file "../data/train.npy" --data_type "numpy" --vocab_size 50277 \
    # --ctx_len 1024 --epoch_steps 1000 --epoch_count 1000 --epoch_begin 0 --epoch_save 5 \
    # --micro_bsz 8 --n_layer 24 --n_embd 2048 --pre_ffn 0 --head_qk 0 \
    # --lr_init 1e-5 --lr_final 1e-5 --warmup_steps 0 --beta1 0.9 --beta2 0.999 --adam_eps 1e-8 \
    # --accelerator gpu --devices 8 --precision bf16 --strategy deepspeed_stage_2 --grad_cp 0

    # example: fine-tune RWKV 1.5B using 1 GPU fp16 (VRAM 16G) NOTE: fp16 might overflow
    #
    # python train.py --load_model "/fsx/BlinkDL/CODE/FP16/out_1b2/all-8040.pth" --wandb "" --proj_dir "out" \
    # --data_file "../data/train.npy" --data_type "numpy" --vocab_size 50277 \
    # --ctx_len 1024 --epoch_steps 200 --epoch_count 1000 --epoch_begin 0 --epoch_save 1 \
    # --micro_bsz 11 --n_layer 24 --n_embd 2048 --pre_ffn 0 --head_qk 0 \
    # --lr_init 1e-5 --lr_final 1e-5 --warmup_steps 0 --beta1 0.9 --beta2 0.999 --adam_eps 1e-8 \
    # --accelerator gpu --devices 1 --precision fp16 --strategy deepspeed_stage_2_offload --grad_cp 1

今回は train a simple L6-D512 RWKV from scratch on enwik8 を実行してみよう

ただそのまま実行しようとすると pytorch_lightning や deepspeed が求められる
特に lightning はバージョン問題があるらしく少しハマる

########## work in progress ##########
Traceback (most recent call last):
  File "train.py", line 111, in <module>
    parser = Trainer.add_argparse_args(parser)
AttributeError: type object 'Trainer' has no attribute 'add_argparse_args'

同様に deepspeed も必要になる

Exception ignored in: <function DeepSpeedCPUAdam.__del__ at 0x7f19207101f0>
Traceback (most recent call last):
  File "/home/octu0/.venv/lib/python3.8/site-packages/deepspeed/ops/adam/cpu_adam.py", line 102, in __del__
    self.ds_opt_adam.destroy_adam(self.opt_id)
AttributeError: 'DeepSpeedCPUAdam' object has no attribute 'ds_opt_adam'

どうやら lightning 1.9.0 であれば問題なさそう
deepspeed は AIOも有効にできるらしい ので次のようにしておいた(事前に DS_BUILD_SPARSE_ATTN=0 DS_BUILD_OPS=1 pip install git+https://github.com/microsoft/DeepSpeed.git@v0.9.0 --global-option="build_ext" --global-option="-j8" 等でインストールする際に足りないものがないかチェックしておくと良さそう、ちなみに 0.7.0 が recommend らしいので DS_BUILD_SPARSE_ATTN=0 DS_BUILD_OPS=1 pip install -U --no-cache-dir --no-deps --force-reinstall deepspeed==0.7.0 で古いcacheを見ないように入れ直せた)

$ pip install pytorch_lightning==1.9.0
$ pip install triton==1.0.0
$ pip install wheel==0.40.0
$ DS_BUILD_SPARSE_ATTN=0 DS_BUILD_OPS=1 pip install deepspeed==0.9.0

これで次のようにして動かすことができるようになった(cuda版)

$ python train.py --load_model "" --wandb "" --proj_dir "out" --data_file "/path/to/enwik8" --data_type "utf-8" --vocab_size 0 --ctx_len 1024 --epoch_steps 5000 --epoch_count 10 --epoch_begin 0 --epoch_save 5 --micro_bsz 12 --n_layer 6 --n_embd 512 --pre_ffn 0 --head_qk 0 --lr_init 8e-4 --lr_final 1e-5 --warmup_steps 0 --beta1 0.9 --beta2 0.99 --adam_eps 1e-8 --accelerator gpu --device 1 --precision fp16 --strategy deepspeed_stage_2_offload --grad_cp 1

Epoch が進むようになるはず

initializing deepspeed distributed: GLOBAL_RANK: 0, MEMBER: 1/1
Enabling DeepSpeed FP16.
LOCAL_RANK: 0 - CUDA_VISIBLE_DEVICES: [0]
Rank: 0 partition count [1, 1, 1] and sizes[(26686464, False), (3072, False), (3072, False)] 

  | Name   | Type       | Params
--------------------------------------
0 | emb    | Embedding  | 3.1 M 
1 | blocks | ModuleList | 20.5 M
2 | ln_out | LayerNorm  | 1.0 K 
3 | head   | Linear     | 3.1 M 
--------------------------------------
26.7 M    Trainable params
0         Non-trainable params
26.7 M    Total params
53.385    Total estimated model params size (MB)
Epoch 0:   0%|                                                                                                                         | 0/5000 [00:00<?, ?it/s]
{'zero_allow_untested_optimizer': True, 'zero_optimization': {'stage': 2, 'contiguous_gradients': True, 'overlap_comm': True, 'allgather_partitions': True, 'reduce_scatter': True, 'allgather_bucket_size': 200000000, 'reduce_bucket_size': 200000000, 'sub_group_size': 1000000000000, 'offload_optimizer': {'device': 'cpu', 'nvme_path': '/local_nvme', 'buffer_count': 4, 'pin_memory': False}}, 'activation_checkpointing': {'partition_activations': False, 'cpu_checkpointing': False, 'contiguous_memory_optimization': False, 'synchronize_checkpoint_boundary': False}, 'aio': {'block_size': 1048576, 'queue_depth': 8, 'single_submit': False, 'overlap_events': True, 'thread_count': 1}, 'gradient_accumulation_steps': 1, 'train_micro_batch_size_per_gpu': 12, 'gradient_clipping': 1.0, 'fp16': {'enabled': True, 'loss_scale': 0, 'initial_scale_power': 16, 'loss_scale_window': 1000, 'hysteresis': 2, 'min_loss_scale': 1}}

Epoch 0:   7%|███▉                                                     | 344/5000 [01:34<21:13,  3.66it/s, loss=1.940, lr=0.000776, REAL it/s=2.820, Kt/s=34.70]

このときの GPU の状況

$ nvidia-smi 
Thu Apr 20 21:11:44 2023       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.105.17   Driver Version: 511.69       CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA RTX A500...  On   | 00000000:01:00.0 Off |                  N/A |
| N/A   69C    P0    65W /  N/A |   3804MiB / 16384MiB |     67%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A     60962      C   /python3.8                      N/A      |
+-----------------------------------------------------------------------------+

CPUもそこそこ使う Intel(R) Xeon(R) W-11955M CPU @ 2.60GHz で 大体 30分/Epoch くらい

$ lscpu 
Architecture:                    x86_64
CPU op-mode(s):                  32-bit, 64-bit
Byte Order:                      Little Endian
Address sizes:                   39 bits physical, 48 bits virtual
CPU(s):                          16
On-line CPU(s) list:             0-15
Thread(s) per core:              2
Core(s) per socket:              8
Socket(s):                       1
Vendor ID:                       GenuineIntel
CPU family:                      6
Model:                           141
Model name:                      Intel(R) Xeon(R) W-11955M CPU @ 2.60GHz
Stepping:                        1
CPU MHz:                         2611.199
BogoMIPS:                        5222.39
Virtualization:                  VT-x
Hypervisor vendor:               Microsoft
Virtualization type:             full
L1d cache:                       384 KiB
L1i cache:                       256 KiB
L2 cache:                        10 MiB
L3 cache:                        24 MiB
Vulnerability Itlb multihit:     Not affected
Vulnerability L1tf:              Not affected
Vulnerability Mds:               Not affected
Vulnerability Meltdown:          Not affected
Vulnerability Mmio stale data:   Not affected
Vulnerability Retbleed:          Mitigation; Enhanced IBRS
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:        Mitigation; Enhanced IBRS, IBPB conditional, RSB filling, PBRSB-eIBRS SW sequence
Vulnerability Srbds:             Not affected
Vulnerability Tsx async abort:   Not affected
Flags:                           fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdts
                                 cp lm constant_tsc arch_perfmon rep_good nopl xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq vmx ssse3 fma cx16 pdcm pc
                                 id sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_
                                 single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid 
                                 avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves av
                                 x512vbmi umip avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid movdiri movdir64b fsrm avx512_
                                 vp2intersect flush_l1d arch_capabilities

メモリは VmRSS で大体5GBくらいなので学習自体にそこまでスペックはいらない様子

$ cat /proc/60962/status | grep Vm
VmPeak:	100779628 kB
VmSize:	100715372 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	 5248152 kB
VmRSS:	 5196164 kB
VmData:	 4181268 kB
VmStk:	     148 kB
VmExe:	    2648 kB
VmLib:	 1729928 kB
VmPTE:	   12636 kB
VmSwap:	       0 kB

ちなみに、CPU版とGPU版を何度か行き来してるとたまに 古いキャッシュを使ってバージョンアップ前の shared object を参照してコケ続けることがある ("libcudart.so.12: cannot open shared object" みたいのが出る)

その時は $HOME/.cache/torch_extensions を消してあげると再度生成してくれる

$ rm -rf $HOME/.cache/torch_extensions
Yusuke HataYusuke Hata

ベースモデルに ja wiki を使えるのかも試す

huggingface で japanese wiki で探すと tensorcat/wikipedia-japanese が出てきたのでお試しでこのjsonを食わせてみよう

jsonの大きさは 7.5GB

$ ls -lh jawiki-20220808.json
-rwxrwxrwx 1 octu0 octu0 7.5G Aug 19  2022 jawiki-20220808.json

bf16 で train させてみる

$ python train.py --load_model "" --wandb "" --proj_dir "out_ja" --data_file "/path/to/jawiki-20220808.json" --data_type "utf-8" --vocab_size 0 --ctx_len 1024 --epoch_steps 5000 --epoch_count 10 --epoch_begin 0 --epoch_save 5 --micro_bsz 12 --n_layer 6 --n_embd 512 --pre_ffn 0 --head_qk 0 --lr_init 8e-4 --lr_final 1e-5 --warmup_steps 0 --beta1 0.9 --beta2 0.99 --adam_eps 1e-8 --accelerator gpu --device 1 --precision bf16 --strategy deepspeed_stage_2_offload --grad_cp 1

1.98it/s なのでかなり遅くなったが読み込める様子(何故かは今度で調べる)
だいたい 1時間/Epoch 程度になるらしい、詳細は --proj_dir の train_log.txt にepoch毎の時間が出ている

  | Name   | Type       | Params
--------------------------------------
0 | emb    | Embedding  | 31.0 M
1 | blocks | ModuleList | 20.5 M
2 | ln_out | LayerNorm  | 1.0 K 
3 | head   | Linear     | 31.0 M
--------------------------------------
82.5 M    Trainable params
0         Non-trainable params
82.5 M    Total params
329.863   Total estimated model params size (MB)
Epoch 0:   0%|                                                                                                                         | 0/5000 [00:00<?, ?it/s]
{'zero_allow_untested_optimizer': True, 'zero_optimization': {'stage': 2, 'contiguous_gradients': True, 'overlap_comm': True, 'allgather_partitions': True, 'reduce_scatter': True, 'allgather_bucket_size': 200000000, 'reduce_bucket_size': 200000000, 'sub_group_size': 1000000000000, 'offload_optimizer': {'device': 'cpu', 'nvme_path': '/local_nvme', 'buffer_count': 4, 'pin_memory': False}}, 'activation_checkpointing': {'partition_activations': False, 'cpu_checkpointing': False, 'contiguous_memory_optimization': False, 'synchronize_checkpoint_boundary': False}, 'aio': {'block_size': 1048576, 'queue_depth': 8, 'single_submit': False, 'overlap_events': True, 'thread_count': 1}, 'gradient_accumulation_steps': 1, 'train_micro_batch_size_per_gpu': 12, 'gradient_clipping': 1.0, 'bf16': {'enabled': True}}

Epoch 0:   1%|▋                                                         | 58/5000 [00:29<41:34,  1.98it/s, loss=4.510, lr=0.000796, REAL it/s=2.230, Kt/s=27.40]

この時で VmRSS は 20GB程度になった

$ cat /proc/61183/status | grep Vm
VmPeak: 115220964 kB
VmSize: 115059908 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:  36153988 kB
VmRSS:  19989076 kB
VmData: 18525804 kB
VmStk:       144 kB
VmExe:      2648 kB
VmLib:   1729928 kB
VmPTE:     41620 kB
VmSwap:        0 kB

GPUも11GB程度なのである程度余裕がある

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.105.17   Driver Version: 511.69       CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA RTX A500...  On   | 00000000:01:00.0 Off |                  N/A |
| N/A   77C    P0    55W /  N/A |  11070MiB / 16384MiB |     50%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A     61183      C   /python3.8                      N/A      |
+-----------------------------------------------------------------------------+

約10時間 train させたあとに出力されていたのはこちら、大体158MB くらい、思ったよりも小さくなってる

$ ls -ltrh out_ja/
total 789M
-rw-rw-r-- 1 octu0 octu0 1.7M Apr 20 21:50 vocab.json
-rw-rw-r-- 1 octu0 octu0 158M Apr 20 21:51 rwkv-init.pth
-rw-rw-r-- 1 octu0 octu0 158M Apr 20 22:45 rwkv-0.pth
-rw-rw-r-- 1 octu0 octu0 158M Apr 21 03:26 rwkv-5.pth
-rw-rw-r-- 1 octu0 octu0 158M Apr 21 07:22 rwkv-9.pth
-rw-rw-r-- 1 octu0 octu0 158M Apr 21 08:24 rwkv-10.pth
-rw-rw-r-- 1 octu0 octu0 3.9K Apr 21 10:30 train_log.txt

rwkv-10.pth を使ってどんなものか見てみよう
簡単に下記のように用意しておいて試してみる

import os
os.environ['RWKV_JIT_ON'] = '1'
os.environ["RWKV_CUDA_ON"] = '1'

from rwkv.model import RWKV
from rwkv.utils import PIPELINE, PIPELINE_ARGS

# モデルとパイプラインの準備
model = RWKV(
    model="/path/to/out_ja/rwkv-10",
    strategy="cuda fp16")
pipeline = PIPELINE(model, "20B_tokenizer.json")

args = PIPELINE_ARGS(
    temperature = 1.0,
    top_p = 0.7,
    top_k = 100,
    alpha_frequency = 0.25,
    alpha_presence = 0.25,
    token_ban = [],
    token_stop = [0],
    chunk_len = 256)

def generate_prompt(instruction, input=None):
    if input:
        return f"""Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

# Instruction:
{instruction}

# Input:
{input}

# Response:
"""
    else:
        return f"""Below is an instruction that describes a task. Write a response that appropriately completes the request.

# Instruction:
{instruction}

# Response:
"""


# プロンプトの準備
prompt = "日本で一番人気のアニメは?"
print(prompt)

# Instructプロンプトの生成
prompt = generate_prompt("日本で一番人気のアニメは?")
print("--[prompt]--\n" + prompt + "----")

# パイプラインの実行
result = pipeline.generate(prompt, token_count=200, args=args)
print(result)
日本で一番人気のアニメは?
--[prompt]--
Below is an instruction that describes a task. Write a response that appropriately completes the request.

# Instruction:
日本で一番人気のアニメは?

# Response:
----
:OrmgiusderHydnoszeksungen\nThermoschwlltischenMain:In:SteinzeundLippula,Z

よくみると torch で使っている cuda version と ドライバのバージョンが一致していない様子だった
いったんダウングレードしてみたものの

pip install torch==1.13.1+cu117 torchvision==0.14.1+cu117 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cu117

正確にでるといった状態ではなかったため
やり直す

Yusuke HataYusuke Hata

deepspeed は 0.7.0 が良いらしい(faster than newer versions と出る)が、いったん後回しにして、パラメータを調整する

また layer数 embed数は 大きいとメモリ消費も増える

例えば --n_layer 24 --n_embd 2048 で動かすとおおよそ 50GB 必要

$ cat /proc/63627/status | grep Vm
VmPeak: 139966204 kB
VmSize: 136925432 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:  52366608 kB
VmRSS:  49325656 kB
VmData: 40391232 kB
VmStk:       148 kB
VmExe:      2648 kB
VmLib:   1729928 kB
VmPTE:    100184 kB
VmSwap:    75980 kB

GPUも 15GB でそこそこ使うようになる

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.105.17   Driver Version: 511.69       CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA RTX A500...  On   | 00000000:01:00.0 Off |                  N/A |
| N/A   69C    P0    71W /  N/A |  15059MiB / 16384MiB |     81%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A     63627      C   /python3.8                      N/A      |
+-----------------------------------------------------------------------------+

あとは Cohere/wikipedia-22-12-ja-embeddings でもうちょっと新しいめの wikipedia の日本語データがあるらしいのでこれに切り替え

parquet形式なので、 github.com/apache/arrow/go を使いつつ、textだけを取り出すように書いた
こんな感じ

package main

import (
        "bufio"
        "context"
        "io"
        "io/fs"
        "log"
        "os"
        "path/filepath"

        "github.com/apache/arrow/go/v11/arrow/array"
        "github.com/apache/arrow/go/v11/arrow/memory"
        "github.com/apache/arrow/go/v11/parquet"
        "github.com/apache/arrow/go/v11/parquet/file"
        "github.com/apache/arrow/go/v11/parquet/pqarrow"
)

var (
        alloc = memory.NewCheckedAllocator(memory.DefaultAllocator)
        lf    = []byte("\n")
)

func wikiTextTo(w io.Writer, path string) error {
        log.Printf("open %s", filepath.Base(path))
        f, err := file.OpenParquetFile(path, true, file.WithReadProps(parquet.NewReaderProperties(alloc)))
        if err != nil {
                return err
        }
        defer f.Close()

        ar, err := pqarrow.NewFileReader(f, pqarrow.ArrowReadProperties{}, alloc)
        if err != nil {
                return err
        }
        tbl, err := ar.ReadTable(context.Background())
        if err != nil {
                return err
        }
        defer tbl.Release()

        tr := array.NewTableReader(tbl, tbl.NumRows())
        defer tr.Release()

        for tr.Next() {
                r := tr.Record()
                n := r.NumRows()
                texts := r.Column(2).(*array.String)
                for row := int64(0); row < n; row += 1 {
                        str := texts.Value(int(row))
                        if _, err := w.Write([]byte(str)); err != nil {
                                return err
                        }
                        if _, err := w.Write(lf); err != nil {
                                return err
                        }
                }
                r.Release()
        }
        return nil
}

func main() {
        f, err := os.Create("/path/to/out/wikipedia-22-12-ja")
        if err != nil {
                log.Fatalf("%+v", err)
        }
        defer f.Close()

        out := bufio.NewWriterSize(f, 64*1024)

        if err := filepath.Walk("/path/to/repo/wikipedia-22-12-ja-embeddings/data/", func(p string, info fs.FileInfo, err error) error {
                if err != nil {
                        return err
                }
                if info.IsDir() {
                        return nil
                }
                if ".parquet" != filepath.Ext(p) {
                        return nil
                }
                if err := wikiTextTo(out, p); err != nil {
                        return err
                }
                if err := out.Flush(); err != nil {
                        return err
                }
                return nil
        }); err != nil {
                log.Fatalf("%+v", err)
        }
}

これでtext部分だけ抜き出したものを使いもう一度 train.py をしてみる

... 学習中...

上手くいかないので続く

Yusuke HataYusuke Hata

RWKV-LM/RWKV-v4neo ではどうも上手くいかない
どのembd/ctx_lenで学習させても RWKV-v4neo/src/model_run.py", line 200, in forwardx = w.emb.weight[ctx[-1]]out of bounds for dimension になってしまう

あきらめて RWKV-LM/RWKV-v4 を使ってみる
v4/train.py はコードコメントが豊富なので特に特筆すべきことはないが、少しだけ変えた

EXPRESS_PILE_MODEL_NAME = 'octu0-model'
EXPRESS_PILE_MODEL_TYPE = 'octu0-ja-wiki22-12'
datafile = "/path/to/wikipedia-22-12-ja"

n_layer = 6
n_embd = 1024
ctx_len = 1024

n_layer は、そのまま層の数らしい、層の数が増えるとフィットする関数が増えるそうだが、ここはチューニングポイントになりそう、 RWKV-4-Pile-430M などから n_layer は 24 らしいが、RTX A5000 Laptop では 16GB しかなく乗り切らなかったので、6 にしている
n_embd は、ちょっと分からなかったが RWKV-14B-Pile-8192 は 5120 なのでモデルの大きさに関わってそう。いったん ctx_len と同じにしている (RWKV-4-Pile-430M と同じ)
ctx_len は、学習時に参照するワード数らしく1024固定なのでそのまま

wikipedia-22-12-jaは前回と同じものを使った
あとは train.py を叩くだけ

$ python train.py
loading utf-8 data... /path/to/wikipedia-22-12-ja
building token list... data has 1001805969 tokens, 18239 unique.
2023-04-22 21:38:55 - INFO - torch.distributed.nn.jit.instantiator - Created a temporary directory at /tmp/tmpv14qndvs
2023-04-22 21:38:55 - INFO - torch.distributed.nn.jit.instantiator - Writing /tmp/tmpv14qndvs/_remote_module_non_scriptable.py

....

Loading extension module wkv...

model RWKV bf16 epoch 500 batchsz 12 betas (0.9, 0.99) eps 1e-08 ctx 1024 layer 6 embd 512

/home/octu0/.bar/lib/python3.8/site-packages/pytorch_lightning/lite/lite.py:109: LightningDeprecationWarning: The `pytorch_lightning.lite.LightningLite` class was deprecated in v1.9.0 and will be renamed to `lightning_fabric.Fabric` in v2.0.0.
  rank_zero_deprecation(  
2023-04-22 21:39:13 - INFO - pytorch_lightning.utilities.rank_zero - Using bfloat16 Automatic Mixed Precision (AMP)
[0]

[--> first run, init model params (very slow for large models) <--]
[so you shall only do it for 1 single GPU and save the checkpt and load it when using multiple GPU]

2023-04-22 21:39:14 - INFO - src.model - number of parameters: 3.915981e+07
[1]
[3]
miniE 1 s 833 prog 0.20% : ppl 28.809831 loss 3.360717 lr 7.930194e-04: 100%|██████████| 833/833 [05:37<00:00,  2.47it/s]

n_epoch = 500 なのでさくさく動く 1 epoch でも5分程度で終わった

1 epoch だけ学習したもので run.py を叩いてみよう
次のように変更した

@@ -25,12 +25,13 @@ np.set_printoptions(precision=4, suppress=True, linewidth=200)

 TOKEN_MODE = 'char' # char / bpe / pile
 
n_layer = 6
-n_embd = 512
+n_embd = 1024
 ctx_len = 1024
 
 if TOKEN_MODE == 'char':
-    MODEL_NAME = 'trained-500'  # your trained model
+    #MODEL_NAME = 'trained-500'  # your trained model
+    MODEL_NAME = 'trained-1'  # your trained model

@@ -73,7 +74,8 @@ model_type = 'RWKV' # 'RWKV' or 'RWKV-ffnPre'
 # context = 'A'
 # context = "\nIn the"
 # context = '\nSugar:'
-context = '\nIn a shocking finding, scientist discovered a herd of dragons living in a remote, previously unexplored valley, in Tibet. Even more surprising to the researchers was the fact that the dragons spoke perfect Chinese.'
+#context = '\nIn a shocking finding, scientist discovered a herd of dragons living in a remote, previously unexplored valley, in Tibet. Even more surprising to the researchers was the fact that the dragons spoke perfect Chinese.'
+context = '\n人生は猫のようなものである、なぜならば'

この時の出力は次のようになった

$ python run.py
Loading trained-1...

RWKV_HEAD_QK_DIM 0


Your prompt has 20 tokens.

--> Currently the first run takes a while if your prompt is long, as we are using RNN to process the prompt. Use GPT to build the hidden state for better speed. <--

------------------------------
人生は猫のようなものである、なぜならば有名である。花は高校生において、カップバンドが1977年に普段の森一学年生によると、当時の小学校は高校生であった。スタジオは広告や芸術など、大学がになった時には、子どもが美しく見えているように女子のメッセージがあった。なお、ツールドにあることが出来るときには、幼児が少しずつ選んだ時には、あるくみのもののしきも、実質的に1970年代から1990年代後半のベットボールのメンバーになった。1990年代になってアイドルグループには、スタッフ・エリザベスの長女としても活動していた。
1973年にアルバニアは、コンテストでの同じく芸術の愛好者が、美術を研究した。これにより、1992年にスタートしたヨーロッパで初めてバルトを経て、2000年に誕生した。スタンバード・マル・
---------- 12.56s ------------------------------
人生は猫のようなものである、なぜならば、オレをかごく見るとなっていると、、本当による死が見つかっていたことを受け取っている。その後、長くは3人である程 度に上手いない人によって心の中を引く。頭は生きていた背中にある「体を傷つける者」を果たすことができ、先に息を付けているのがてあったと思われる。なお、自分に「人間を見て私は不明であった」と語っている。
かつて新聞は2005年(平成16年)に「名前に引っ込んでいたい」と語ったとき、「おずらかいても美しい?」としている。アルバード・アルコ・ロイドはそれを売り切り、1953年(昭和33年)にアルコールの人気を発見した。2014年(平成26年)には、「自分が他人をうたくつけたい」という理念があったとしている。
2016年(平成13年)2月26日には、自身の人
---------- 17.05s ------------------------------
人生は猫のようなものである、なぜならば自分に近くて立つことがある。しかし、それによってこの生き残った「別の子」と名付けられた。人間は平坦で、50歳以下の犬、小に次ぐ若い家族を有するが、家族が8歳の時、当時の武術家である安田徳家の意向が大きく異なっている。一方で、「社会の人間としては、人々による言い込み 」とされるという。
博士号は単なる分野であるが、現在のプロイセンにおいては政府との関係を維持するものである。人々は大好きな意味を持つ。人間の場合には、多少の分野の反応がある。プロイセンは「人間によって自分のための見解を何度も起こすからであるが、このような人間の成分によって、生命がまとまるだろう」ということになっている。
本作品のことは、サイトを前提とした人々のままである。この、ほか、クローバーのリズ
---------- 17.03s ------------------------------

なんのことか全然分からないがちゃんと日本語で何か出そうとしている

学習中の GPU の状況は

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 530.30.02              Driver Version: 511.69       CUDA Version: 11.6     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                  Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf            Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA RTX A5000 Laptop GPU     On | 00000000:01:00.0 Off |                  N/A |
| N/A   62C    P0               84W /  N/A|  13960MiB / 16384MiB |    100%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+

+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A     68698      C   /python3.8                                N/A      |
+---------------------------------------------------------------------------------------+

メモリの状況、実は train.py は実行時に fork するらしいので、2つプロセスができる、CoWできてるサイズは小さいので合わせて 12GB くらいか

$ cat /proc/68698/status | grep Vm
VmPeak: 102179560 kB
VmSize: 102179368 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:  10221116 kB
VmRSS:   6717312 kB
VmData:  6996724 kB
VmStk:       180 kB
VmExe:      2648 kB
VmLib:    965764 kB
VmPTE:     15380 kB
VmSwap:        0 kB

$ cat /proc/68755/status | grep Vm
VmPeak: 100979944 kB
VmSize: 100889788 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:   5150236 kB
VmRSS:   5150020 kB
VmData:  5976032 kB
VmStk:       180 kB
VmExe:      2648 kB
VmLib:    920376 kB
VmPTE:     10828 kB
VmSwap:        0 kB

次はもうちょっと epoch 数を増やしたり、wikipedia 以外の青空文庫あたりのデータも入れてみたい

Yusuke HataYusuke Hata

n_epoch = 5000 で、8時間程度学習させてみたので、その過程の成果物を使ってどの程度精度が上がるのかみてみよう
token数は9億くらいらしい (building token list... data has 945925329 tokens, 18240 unique.)

前回と 同じく run.py の結果
ちなみに下記は fp16 cpu にしている結果で、fp16 cuda だと2s前後で出力していた(早い)

1世代目(5000 epoch)

------------------------------
人生は猫のようなものである、なぜならば、自分たちの生活による。自分たちは海のほとんどに匹敵する一人もいたが、ほとんどは意見がないと考えている。また、自分の中でどの言葉は原文について語りかけており、生きたものは思われることができるようになっている。
ある日、ウィキペディアに生まれる。カーティスの父親であるマルカは、自分の家に伝えることで、自分の生活をされている。モルニアの中で、10人の女性が自分たちと家族に自分たちに姿を見ることができる。その原因となると、女性のカバルがオペモに、ユダヤ教徒であるのはイスラエルでももう一度離れている。カルタニアはアルバニアのアレクセスをしている。この子供はバルセロナによってアレクサンダーの子供である。キャラクターのコーヒーはより容易にタクシーが生まれている。エレクト
---------- 5.3s ------------------------------
人生は猫のようなものである、なぜならば、という。その後、おばさんはできるものである。これらはサファクルを人としているが、おそらくはいう人のみを記している。マクシフの祖母を代わりに彼はよく住んでおり、いずれの名前を持つカメラである。このようにタクシの一種であると言われる。
1990年代後半から1997年にかけて現在のマクリはベルギーのペーターの内になっている。1970年にはベルリンでリマーラーとの間に交換が進められている。また1991年にはラージュに「タイプのパートナーが就いた」「カービーズとユナイテッド市のサイズの一つとなっている。
当初は「サイラーズはブラウザを開催していたためにはだったが、シートにおけるアクセスできないアメリカに留まっていた。彼の記録はアメリカの世界として知られている。また1
---------- 5.04s ------------------------------
人生は猫のようなものである、なぜならば人々がわかるためには生きてきたありか、ラテン語ではなくなったが、エルサレムの人のほとんどがパリの子供たちと呼ばれることが多い。フィアラの住民は男性に住むのがソルトの人である。
フランスではアルカースが元の人々が生まれたと言われている。当初はスライダーがアルマラに入って来ていたが、プライは「レコード」と呼ばれる。サラのようなオスマン帝国の分遣ではなくローマに着いたモバイルである。コルライ・ウィーンの人々は1759年に、スイスのプラットフォーマンスとの間にルイ16世がストライプとして創業したことが知られていた。
コーヒーアルバム『"Shuss Int Eviting Start"』(アルバム: Sineri Ardation Alturition Starnis
---------- 6.47s ------------------------------

10世代(50000 epoch)

------------------------------
人生は猫のようなものである、なぜならば、犬が存在するのか。猫は神経質であるため、一部の犬はその大きさには致命的な問題を起こさないため、動物たちの手によってその能力は低下する。そして、恐怖心が緩和されるのは「犬が始まる」であり、「動物たちは何かをともにやりたい」という思いをしている。動物たちは、犬が犬のような大きさの犬を見たり、動物の尻尾を削って足を切り裂くようになるという場面もある。
近年では、このような動物たちに対する考え方が拡大している。また、哺乳類においては動物が「犬のうち」として一定の地位を与えられている例もある。しかし、あるいは生殖腺の動物の権利が発生することもあるので、動物が「動物」であることを認めているとは言い難いという指摘もある。
本来は、動物ではない動物であっても動物のものとし
---------- 5.34s ------------------------------
人生は猫のようなものである、なぜならばすべてが自分であるからというものではなく、多くの場合、他人に愛を伝えるべきだというわけである。これはそのうえ人間の感情を意識しているからであり、自らの愛の愛を行うことを意味する。
愛情的には愛の愛情としての情の中に含まれる愛を指す。愛は愛情というのがありうる。愛の愛は愛情を生み出すことである。愛情のみを受けるための愛は愛を意味する。愛は愛情にかられ、愛の結果は愛の意味で、愛の意味では愛という意味のことを指す。
愛が得られないことを知っているのは、愛の意味で「愛」という意味である。愛の中では愛のことを意味する語として用いられる場合がある。愛の語では愛のない愛情が多く、愛を称賛することも多い。また、愛する愛というよりも愛を表す表現がある。
愛を意味する語の場合、
---------- 6.68s ------------------------------
人生は猫のようなものである、なぜならば、死後、「猫の夢」は存在するものの、まさに「犬」の位置について考える人もいる。実際、このような人生の時期が1980年代になって、「犬」の存在が生まれるまで、この時期の人々の間では「犬」が見出されることとなった。
「猫」の起源は1970年代のオーストラリアで、新しい「猫」を「獣」にしたいという意味が込められた。スペイン語では、牛の意味は「動物」として、「犬」の意味である。その一方で、「猫」の意味は「猫」に似たものであり、「猫」の意味は「猫」という意味である。なお、犬が動物のことを指す「猫」の場合は、猫の場合、牛が飼う猫を指す場合もある。
昔から伝統的に猫の体に触れる動物である犬や子どもの運動においては、かつては犬のような性別が定着したという点が異なっていた。「
---------- 7.62s ------------------------------
人生は猫のようなものである、なぜならば、世界の異常のない世界を創り出すために、人間は多くの場合を待つのである。そのため、世界のアニメーションの再現がその最初の例となる。また、コミックにも出てくるものは、例えば、「日常のコミカルなものを楽しむ」というものである。
『スーパーファミコン通信』2003年10月号(3月16日号)に、クレジットされた「ザ・リスペル」の内容が、この作品のジャンルに含まれていることが発表された。そ の際に、単行本第2巻の「キャンペルの迷宮」が第1巻というタイトルで発売された。
また、第2巻には特にニコラ・ドーピー、ウィリアム・マリア、マーク・ジョンソン、ウォルター・フレデリック・ジャクソンが、『ジャコメッテ』のように時系列を 読む時間があったが、ニコライ・コラムの『ニコラ・ジャコ
---------- 7.17s ------------------------------

20世代(100000 epoch)

------------------------------
人生は猫のようなものである、なぜならば猫が猫を食べるのは不幸であると言われるのは、猫の姿を見てからだった。猫は猫の飼い主にとある者が「猫は泣き、猫は猫の猫は猫である」と聞いて、猫の「猫は猫に、猫は猫を食べる」と言って、猫は猫に犬のようになる。猫の猫は猫を抱えて、猫を犬の尻尾を打つが、猫の尻は猫であり、猫は猫である。猫は猫を好む猫であり、猫の姿はみな子供の頃から猫のように親しんでいたという。猫は猫の猫を好きになっている。
猫は猫を好む。猫は猫と猫である。猫は猫というが、猫が猫であることを知っている。猫は猫で、猫が猫のことを「猫は猫のように生きている」という言葉を口にしている。猫は猫が好きで、好きなことには猫のアイコンで、猫が猫を好む。猫のことを好む。猫は猫のために猫を愛するという。猫は猫を愛してい
---------- 5.31s ------------------------------
人生は猫のようなものである、なぜならば、人の幸せのために何かが自分で遊ぶのではなく、本当の親とは考えてあらかじめ話すなら、これを感じると猫のように感じているということだと思っている。いっぽうで、猫はすべての猫を、猫のことを気遣うために猫を呼んでいるのだから、猫は自分が猫のことを考えると、猫がそれをすることが出来ることになるだろう」としている。
『これでは、女は家に帰ってきてみないか』というフレーズは、フレーズを入れるのに便利なものである。しかしながら、それは、一部のフレーズでは自分がもっとも知られているフレーズを作ってみたいと思っているように、家族と共に2015年から2016年にかけて制作したものである。
2016年3月17日にフレーズの元になったアイス・クリスマスのオープニングとエンディングテ
---------- 6.8s ------------------------------
人生は猫のようなものである、なぜならば猫が飼うからである。猫が猫であると思いきって猫が好きで、親からの問いには耳にすることはない。家の中で話すことは人に知らされることになる。猫の場合は家庭に見舞われても、猫は猫であると言う。猫の犬になるためには子供に家庭内で自分を歩いていく必要がある。家族の父親のように飼われることもあるが、猫は猫を見て、まるで猫を見て自分のものを選びに行くこともある。子供が何でも、何回も猫が集まる時は猫は一人一人で遊び、親しくなるということは一度もない。子供の頃には身を隠すと思っていた。
原田佐和子(佐久間梨香)はある日、京都の街で奇妙な親友となる少年・原知咲(江田は親友)と出会う。親友の奈々子は、京都の伊勢で育った子供で、彼をモデルにしたのは、宇多津とも親しかった。京都に戻っ
---------- 7.71s ------------------------------
人生は猫のようなものである、なぜならば人に出会うことを願っているのかという点については、猫のような背景とは異なり、幼稚園の周りの野宿の世話をする人々は、それを自分によって育てることができるだろう。
住居を求める人々が自分の意見を受けて、人々が開放するというのは、大学生がみんなが何をするか考えている。人々は自分が無人になっていると考えているのである。自分自身を「幸せ」と呼び、別に人間に「幼いころからだけではなく、子供として育てるというのは自分にとってこの道を切り開いてくれる人たちのことを知ることができる」と考えている。
細野晴臣は、ある日、野球部がある大阪城の敷地内にある自宅で自分が教師として教えているのはわからないので、野球部とは対照的に、野球部に入部するために努力するようにするよう、プレーに応
---------- 7.3s ------------------------------

少し飛ばして 50世代(250000 epoch)

------------------------------
人生は猫のようなものである、なぜならば人間の社会的生活を自己を見つめ直すために、このように活動する。猫はもともと「目を離さないもの」を追求していたのである。猫は身体的に安定しているため、必ずしもこの猫を犠牲にしているとは限らない。猫はその力を発揮するのに役立つものであり、猫は死ぬときにしか動かない。猫が動物の舌を口に押し付けて発声することで、猫は動物にとっては重要な動物となる。猫は普段猫とは違い、生物的には普通の猫よりも目立つ。彼らの感情を最大限に活かすためには、すべての猫が猫のいる範囲に侵入して、これらの動物を放ってしまうのだと言う。その意味で、猫は猫を犠牲にしていることになる。猫が発生する時、猫の放射能を理解することが困難である。この猫は誰でも動物と共に生きていくために、コンテナに変換される
---------- 7.23s ------------------------------
人生は猫のようなものである、なぜならば、野良猫とその友達は昔から猫のように見えるが、犬は犬をしているだけである。飼い主が飼い主を捨ててから猫となるのは一度である。猫は野良猫の「どうでしょうね」を犬に食べさせている。猫は時に猫として扱われる。猫と猫の一種の猫との結びつきが強い。
猫は何を飼うとも猫の猫とともに猫として飼われている。猫は猫を主人公とするため、猫を猫として扱う。猫は猫と同様に猫のような存在になっている。猫と猫とは違い猫の遊びを楽しむことができる。猫と猫との結婚により、猫と猫との関係は悪くなる。猫と猫は仲が悪く、人間との結婚も人間に対しては重大な意味を持つ。猫と猫は結婚している。猫と猫は結ばれているが、猫と猫は結婚したまま猫となる。猫は猫と猫を演じており、猫と猫の関係になる。猫は通常、猫
---------- 7.15s ------------------------------
人生は猫のようなものである、なぜならばもっとも目立つ存在になるはずだったから、猫が人間のお尻を持つのは誰もいない。猫は猫が愛する猫の「水を汚す」、猫を買うのは猫の飼い主、そして猫は猫になるという事実に基づくものだ。猫はその猫の目の前で飼われる猫のお猫として、猫の背中にいる猫を頭の中で追いかける。猫の首には猫の尻が刻まれている。
海の猫は全て猫としての記憶をもっている。猫のキャラクターとしての猫の言葉は人間の恋愛のような存在である。猫の目の色はアダルトゲームに登場する以前は小人が猫のおもちゃを操るために用いていた。この用語はライターの福永洋一が編集者を務める出版社の株式会社ビッグコミックス版の編集部にて記事として使われた。
読者が広く知られているように、それはもっとも人間性の高いものとされている。
---------- 7.12s ------------------------------
人生は猫のようなものである、なぜならば犬が一緒になってくれるのかということが好きなのか、という問題である。人間の心理は同じことだが、互いに好きな猫と話し合うことができるため、交流があるとのこと。自分のことを「猫」と呼ぶことがある。猫を好むことも大好きで、猫とは友達である。
新聞や雑誌のインタビューで、人間は少年時代に最も人間のように見えると答えた。小学校の頃は、お互いにのびのびとした性交を楽しみたがっていたという。小学校3年生の時、アルコールの過度の摂取による食事制限がなくなり、コーヒーが食べる量が増えると、1日に4回も家族で運ばないことになった。
ドラマや映画などで多くの人が同性愛者であることを見たことがきっかけとなり、子供の中には特に素直で純真な自分のことを嫌悪している者が多くなっていた。し
---------- 7.11s ------------------------------

1 epoch と比べてだいぶ日本語がまともになった感じはある
epoch を増やすことでちょっとずつ賢くなっているような気もするが、 100000 epoch と 250000 epoch ではあまり大きな差はなさそう

そして今更なのだが、RWKV-LM/RWKV-v4 (v4neoではない方) を使ったことで vocab.json は UTF-16LE 形式で保存されているということを知った
つまり前回 ctx がおかしくなった のは tokenizer と一致してなかったからということらしい

RWKV-LM/RWKV-v4neo でも次のように書き換えてあげることで落ちなくはなる

@@ -24,7 +24,8 @@ WORD_NAME = [
     "20B_tokenizer.json",
 ]  # [vocab, vocab] for Pile model
 UNKNOWN_CHAR = None
-tokenizer = TOKENIZER(WORD_NAME, UNKNOWN_CHAR=UNKNOWN_CHAR)
+tokenizer = TOKENIZER("vocab", UNKNOWN_CHAR=' ')

@@ -179,7 +187,12 @@ def load_all_stat(srv, name):
 # Run inference
 print(f'\nRun prompt...')
 
-out = run_rnn(tokenizer.tokenizer.encode(init_prompt))
+if tokenizer.charMode: 
+    context = tokenizer.refine_context(init_prompt)
+    ctx = [tokenizer.stoi.get(s, tokenizer.UNKNOWN_CHAR) for s in context]
+    out = run_rnn(ctx)
+else:
+    out = run_rnn(tokenizer.tokenizer.encode(init_prompt))

@@ -189,7 +202,10 @@ srv_list = ['dummy_server']
 for s in srv_list:
     save_all_stat(s, 'chat', out)
 
-print(f'### prompt ###\n[{tokenizer.tokenizer.decode(model_tokens)}]\n')
+if tokenizer.charMode: 
+    print(f'### prompt ###\n[{tokenizer.itos[len(model_tokens)]}]\n')
+else:
+    print(f'### prompt ###\n[{tokenizer.tokenizer.decode(model_tokens)}]\n')

tokenizer.decode出来ないので読めたものではないが...

とはいえ RWKV-LM/RWKV-v4 では動かせれるようになったのでもう少しまともな日本語を出せるのか ctx_len 等を調整してみよう

Yusuke HataYusuke Hata

ソースコードを読んでいると GPU に乗り切らせるには batch_size を調整すればいいとのことだったので
n_layzer = 16, ctx_len = 1024 のものを作ってみた

@@ -81,8 +84,9 @@ os.environ['USE_WANDB'] = '0' # wandb logging. 0 = False, 1 = True
 EPOCH_BEGIN = 0 # begins with miniEpoch = EPOCH_BEGIN
 LOAD_MODEL = False # shall we load the #EPOCH_BEGIN model and continue the training from it?
 
-n_layer = 6
-n_embd = 512
+n_layer = 16
+#n_embd = 512
+n_embd = 1024
 ctx_len = 1024 # increase T_MAX in src/model.py if your ctx_len is longer

@@ -111,7 +115,7 @@ if EXPRESS_PILE_MODE:
 ########################################################################################################
 
 # if you see "CUDA out of memory", reduce batch_size. Use nvidia-smi to find the highest value for your GPU.
-batch_size = 12 * int(os.environ['RWKV_NUM_GPUS'])
+batch_size = 4 * int(os.environ['RWKV_NUM_GPUS'])
 assert (batch_size % int(os.environ['RWKV_NUM_GPUS']) == 0)
 
 # By default we are using exponential LR decay.

学習中のVRAM 使用量はだいたい13GBだった

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 530.30.02              Driver Version: 511.69       CUDA Version: 11.6     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                  Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf            Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA RTX A5000 Laptop GPU     On | 00000000:01:00.0 Off |                  N/A |
| N/A   63C    P0               84W /  N/A|  13038MiB / 16384MiB |     98%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+

+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A     71551      C   /python3.8                                N/A      |
+---------------------------------------------------------------------------------------+

今回は推論を fp16 cuda で実行した
n_layer = 16 にしたことでCPUでは出力速度がちょっと遅くなっていて、このあたりからGPUが必要そう

1世代 (5000epoch)

------------------------------
人生は猫のようなものである、なぜならば、乳を除く。木星に接して、より人間には死ぬ。彼らは、犬種の縁を持つ人のうち、最も精密な家庭を持つ物質として、最も長い歯が存在する。また、天地においては、特に、太陽の遺伝子が作られていることによって、特に大きな特徴とされる。
氷には「カレロ」という物が多数ある。また、地球としても、ポルトガルではその分類はどちらも何の基本的な分裂を持つことがある。種々の植物が発見されたのは、植物のみならず、グループによって、一種の分裂は全く分裂するという。
そのように、植物がアメリカではその名が「アジアの系」と呼ばれる。その分の内容は、この発見の成果として「年に一致」の単位を確立し、また、、パラグアというのは、アジアの産物である。1958年のシュヴェルディで、ミュージカルは、ア
---------- 7.74s ------------------------------
人生は猫のようなものである、なぜならば、異なる純さという意味では、言葉が18歳までに、これは過去に一人暮らしの本質であるということがある。しかし、時折やくしても人間になっていると思われるため、人間の手の言葉による伝わりが原因である。彼は、「神とその名のどうして、我々のいまな」ということになっている。
グラフは、2005年にオーディングスに訪れ、イーディーラ・スティーブンの名称で人気を博した。この作品は、2008年に、ブラウンとイラストを結成した。セランスは、「ゴーストラーの中にのみ」に変更し、ブージンは『ニュースレン』という名前の由来で、このアングレーのものを作り出したと記録している。
また、同作品の登場人物は、『「悪魔」という物語』を読みながら、人間の女性と、女性ではなく、新たに「"」というタ
---------- 8.28s ------------------------------
人生は猫のようなものである、なぜならば、彼らがさまざまな若い少年にとってできる。これはいちまちだったがってもその人物であったためには、彼の多くは木の頭の前に水を入れることになっている。ただし、物語の中ではこの人々は物語の数々に別の人物であるとしている。
神田神社(おおおんごみこうぜんしゅうかいかんどう)は、1870年代後半に書きた「旅」「三方の国」に相当する天文学者、神戸書道を派遣したものである。文字通りの「宇国神」は、西暦大社ではなく、『小書』では「天文」に対しても使われるのが一般的である。
陸軍徴用は、天正7年(1506年)に創建された「神社神社」の改訂に伴い、当時の実用性の必要性を定めていた。しかし、江戸時代後期には上国時代になってからは、 紀年に及ぶ天文学を論じる諸神社は、その明治に入ると
---------- 10.54s ------------------------------

10世代 (50000 epoch)

------------------------------
人生は猫のようなものである、なぜならば何が悪いのか? ドラえもんの悪夢についてはなんでも知らない。今でも人はいない。だからそんな気持ちを持っているから、自分はその中で生きるか、どういうものをつなぐのか。なぜならそのときだけのように、現在ではいつもどこから見て大阪の上司がよくこぼれているからだ。」と語っている。
また、この作品は当初は人間が人間ではなく「人間」だと考えていた。ある日、大阪にある天神社の神官がおなじみの神秘体験を知ったところ、一行はその先の村にある「わたし」をもっと人間との人間の姿にしてしまった。このことから、当時の神社は神社に向かって人間の体の一部を占めていたという。神社は天神とともに人間の神体を神社に祀ることを想定していたが、神社の行事は神社にとってはその役割であった。そのため、
---------- 11.16s ------------------------------
人生は猫のようなものである、なぜならば自分の彼女の前で生きるのか、誰かが動物のようなものを作りたいというものであった。動物はそれをやっとするにはそれがつかないと思い、それには恐怖が集まった。それでも幸運なことであった。さまざまな性的遊泳によって、彼女の気質が変わってくるのは何か。人間がいなくても彼女のことを理解しないと、必ず彼女の人生を作るようになるだろうと思い、この性格は、人間との交流が進むにつれて、わざとそれを用いていると言う、様々な信念を持つようになった。
モーゼスはその目的をまたしても「人間の信念に基づくものであり、それによって自らを心の性質の下に持つ。そして人間の性にあるものを作り出す」と述べている。モーゼスはモーゼスのこの運命についての学術的意義を語っている。
このモーゼスの書籍は、
---------- 11.05s ------------------------------
人生は猫のようなものである、なぜならば悪夢は人間と肉体関係にあるからだ。彼らの過ちとその過激な姿は、彼らにとって社会的な面を感じさせるものである。彼らは肉体的におり、生活することは非常に困難である。さらに彼らは自分達が戦いに勝つことは無かったからである。彼らの死の背後に、人間が恐怖を知っている様子に気づいたりもする。自分の思いは奇妙である。この危機に直面した者たちの数は激減し、我々は人間の肉体的苦痛を回避することになる。
死んだ人は、心が知られた方へと戻っていく。思春期の終わりに、人は殺されてしまう。ただ一つの心が開いた場所に移り、これが人間の心を守ることになる。人間が思考したのは、そのままである。しかし、その場にいる人はまだ者と同じように生きている。しかし、人間は、無意識のうちに身体を崩壊させ
---------- 9.85s ------------------------------

20世代 (100000 epoch)

------------------------------
人生は猫のようなものである、なぜならばその全ての声にそれがあるからという理由から、ニューヨークのグローブスビルでは、声帯を広げていた「フォードの人生」というアメリカの伝統的な音楽の起源を持っていた。
ジェームズ・バーナード・ショー・ウィルソンの、1950年のイギリスのテレビ・ドラマ『』では、マーク・サックリーが当時の『ビルボーン』の記事で、「トリック・クラッシャーの伝記を書いた」として、本作を最後にドラマの中断を余儀なくされた。
ローワン・エイリアンは、アメリカ合衆国における実在の役者、詩人、エディス・ロングリーが主演する。『トリック・ワールド』のタイトルは、アーヴィング・ハーヴェイ・マーリーが付けたとされている。本作の舞台におけるローワンの演技は、主人公と恋人のイーサンの恋に焦点を当てたもので
---------- 12.22s ------------------------------
人生は猫のようなものである、なぜならば不可能であるから、子供の頃になって、ブルースを食べた人にはある種のメッセージが伝わったのだとして、より真剣な意見を求めた。この点では、同性愛者とは、もはや似たような子供のように、同性愛の子供がいるからである。この性愛は本来、子供の親には理解されなかったものの、子供のころからのこの言葉の解釈の一部であるという認識を持たないため、子供たちの自覚は、このような関係を構築することになった。
パリのサン=ジェルマン=アン=レー修道院で生まれた。1880年にクレルヴォー高等小学校を卒業した後、パリのロンドン・アカデミー・オブ・ザ・イヤーに選ばれた。1883年にはパリのサン=ジェルマン大聖堂において、ナポレオン戦争の軍人として軍務に従事した。1886年にはサン=ジェルマン
---------- 9.64s ------------------------------
人生は猫のようなものである、なぜならば自分は恋愛関係にあり、彼女の死によってしまったからだ。このことは、死亡の時の経験から、夫の自分が生きていることを理解することによって、子供たちの「泣き」を引き起こすのではないかという意見がある。しかし、オランダの科学者はこのイメージを理解していない。
以上のような、人間の理解を必要とする一つの事実を、レイチェル・アルベルト・フォン・ヒンデンブルクのように、人間の感情を克服するのには、子供のような人間的な情緒にまだまだならないという、人間の感情とレイチェルの主張に対する強い疑問を抱くことがある。そのため、子供がレイチェルに出会ったとき、その人間の生存のための思考が一貫していることは、人間の親からの反発を招いた。このため、親たちは親たちの思考が子供に自然な自然に
---------- 10.37s ------------------------------

うーむ。layerが増えても賢さが増したような感じはない...かな

もしかしたら "人生は猫のようなものである" だけでは短すぎて変な出力なのかもしれないので、吾輩は猫であるの冒頭を書いて続きを出してもらってみた

@@ -73,7 +74,8 @@ model_type = 'RWKV' # 'RWKV' or 'RWKV-ffnPre'
 # context = 'A'
 # context = "\nIn the"
 # context = '\nSugar:'
-context = '\nIn a shocking finding, scientist discovered a herd of dragons living in a remote, previously unexplored valley, in Tibet. Even more surprising to the researchers was the fact that the dragons spoke perfect Chinese.'
+#context = '\nIn a shocking finding, scientist discovered a herd of dragons living in a remote, previously unexplored valley, in Tibet. Even more surprising to the researchers was the fact that the dragons spoke perfect Chinese.'
+context = '\n吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。'

結果はこんな感じ、意味不明さだとあまり変わらず

------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。同じ時期に仲良くしていた金田一京助の家には、よく見る様子があったという。やがて一心によると、「ひょうきんな、おつらいといっても、いつでもよかろう」と、どうぞ、ほぼ完璧な人に見えたという。「一之家」はおおむねの意味で「おれは俺」という名前で、初めて「おかん」という本名がもらったという。しかし、後年、「なんでおうん」という名前を一心寺に持っていたとする説がある。
下鴨神社の神官を務める近衛信尹は、『御神道志』で、新日本百名山第2位として、江戸に神を奉じて、無茶苦茶を奨励したと記されている。そのため、一気に門外不 出となったとされる。また、多くの書物に「御茶ノ御殿」とあるのは、「ひゅうたん」という名前である。
なお、長野県小諸市の山野辺遺跡には山田家の出身地である御
---------- 8.1s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。実際には「小説家」と呼ばれている。しかし、第一高等学校時代に学生新聞を書くようになり、『マンガン』を好んで読んでいたのを読んだため、中学卒業後、学費をはねたかったため、大学に行ったことを一度やり直したことがある。
『週刊朝日』の主な読者層である読者層の関係では、その年の記事数は1140万部という。同雑誌の読者層は、学生時代に続く高度経済成長期を通じて、若者層の中でもまだ上昇傾向であった。また、卒業生の中には『週刊朝日』誌の記者やラジオ番組の記者もいた。
また、デビューしてからは、メディア露出が増え、読者層も高くなっていった。そのため、現在でもメディアの支持率は上昇傾向にあり、コラム執筆などもより多くの人が増えている。また、雑誌による投稿については、1987年
---------- 5.96s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。長い間のつながりの少ない女の子と、より少しの大人になったというものがある。大人になったためからわざと気の進まないところが多いが、それがかなり時間を要するのである。大人は大人になってから長年にわたり、気性の荒さを嫌って一緒に過ごしている。中学校では英語の授業があり、生徒はさほど気に入っていない。生徒は学校で修了すると、今後も教育に励んでいくという。
その時期については、その後のインタビューにて、「3、1学年の大学で学ぶものはある。4学期では全て短期大学に進む」と述べている。しかし、留学の先駆けは『メ ディア』の「2012年6月号」である。この記事によると、「国際問題として18歳の少女が一生懸命を教える」という考えには懐疑的である。
『週刊少年サンデー』(小学館)
---------- 10.87s ------------------------------

grateful days だと

@@ -73,7 +74,8 @@ model_type = 'RWKV' # 'RWKV' or 'RWKV-ffnPre'
 # context = 'A'
 # context = "\nIn the"
 # context = '\nSugar:'
+#context = '\nIn a shocking finding, scientist discovered a herd of dragons living in a remote, previously unexplored valley, in Tibet. Even more surprising to the researchers was the fact that the dragons spoke perfect Chinese.'
+context = '\n俺は東京生まれ、ヒップホップ育ち、悪そうな奴は大体友達、悪そうな奴と大体同じ、裏の道歩き見てきたこの街'

うーむ

------------------------------
俺は東京生まれ、ヒップホップ育ち、悪そうな奴は大体友達、悪そうな奴と大体同じ、裏の道歩き見てきたこの街の中で最も野放図なものとなっている。」と評した。1973年に発表された『恋する黒』はその他にも『地下鉄サリン』、『朝からつるべ』、『友よ』、『ガッツ』、『夜の街』、『夜に吠えるもの』などのシリーズ作品の作品に影響を受けている。
大学卒業後、クラブチームの三菱商事に入社。2001年に当時セリエA1のバレンタインデーにレギュラーとして出場したインテルに移籍。同期入社の三沢一郎は左サイドバックとしてプレーし、2002年にはレギュラーとしてプレーした。
『日本書紀』には大国主が大国主の子としているが、大国主の子である大国主は、阿波国(現在の鹿児島県)の御家人であったという記述がある。阿倍氏は日本の出身であり、宇治の大名である南朝の中山王(4代)であったとされる。大国
---------- 5.07s ------------------------------
俺は東京生まれ、ヒップホップ育ち、悪そうな奴は大体友達、悪そうな奴と大体同じ、裏の道歩き見てきたこの街に住みたい」という思いで結成された。最初のプロジェクトは主に男女関係に関するアイディアを持ち、ギター・パートやギター・ベースなどのボーカルを担当していた。また、前作に引き続いてベースの仕事もするようになった。
元来は電車の乗り入れによる「動力車」であったが、主力車のラインナップに入っていたことから主力を減らし、運転席の防振堤を大型化するなど、その後も同様の設計変更が繰り返されている。また、機関室を通常設置している場合には運転席からの給水に不可欠な運転台を撤去して使用することが可能である。
建設時の電力は同社では珍しく川崎重工業が行っていたが、その後1948年には陸上自衛隊の日本国有鉄道(国鉄)が購入した。1949年からは実際に運転を行うための軽量車が計画され
---------- 3.6s ------------------------------
俺は東京生まれ、ヒップホップ育ち、悪そうな奴は大体友達、悪そうな奴と大体同じ、裏の道歩き見てきたこの街にその道を選んだ。自分が名乗るのは彼が初めて。大きな頭の一つはドリフトでドリフトは空いている。人にバレることもできないし、地元のスター達にも愛されている。この人は、高校でも不良でも非常に不安定なところを見せるとともに、誰も彼を嫌悪している。この地方の人は、学校である大学の同級生が不可知論者となってしまったため、彼の好きな部分は私達に対するものだと思い込んでいる。とても気がついていることはあるが、どんな種類のツボも好きでなく、言葉が得られる。この学校はすでに一般的なキャンパスとなっている。学校には多くの人が集まっている。
ヒップホップはステージの向こう側に位置している。ハンドルは大きく、少し上がり、大きなクラスにまたがっている。クラスは一回り大きいもので、自分
---------- 8.4s ------------------------------

embd と ctx_len かなぁ

ちなみに学習済みのモデルはだいたい 1GB 程度なので、 RWKV-4-Pile-430M と同じくらいなので日本語の違和感も似たような感じに思える

$ ls -liah trained-*
74119 -rw-rw-r-- 1 octu0 octu0 976M Apr 23 07:50 trained-1.pth
42184 -rw-rw-r-- 1 octu0 octu0 976M Apr 23 10:46 trained-11.pth
11885 -rw-rw-r-- 1 octu0 octu0 976M Apr 23 13:44 trained-21.pth
Yusuke HataYusuke Hata

n_embd = 2048, ctx_len = 1024 で試してみる

@@ -82,7 +85,7 @@ EPOCH_BEGIN = 0 # begins with miniEpoch = EPOCH_BEGIN
 LOAD_MODEL = False # shall we load the #EPOCH_BEGIN model and continue the training from it?
 
 n_layer = 6
-n_embd = 512
+n_embd = 2048
 ctx_len = 1024 # increase T_MAX in src/model.py if your ctx_len is longer
 
 model_type = 'RWKV' # 'RWKV' or 'RWKV-ffnPre' (sometimes better)

@@ -111,7 +114,7 @@ if EXPRESS_PILE_MODE:
 ########################################################################################################
 
 # if you see "CUDA out of memory", reduce batch_size. Use nvidia-smi to find the highest value for your GPU.
-batch_size = 12 * int(os.environ['RWKV_NUM_GPUS'])
+batch_size = 4 * int(os.environ['RWKV_NUM_GPUS'])
 assert (batch_size % int(os.environ['RWKV_NUM_GPUS']) == 0)
 
 # By default we are using exponential LR decay.

これで VRAM 14GB くらいなので、僕の環境ではこれが限界かな

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 530.30.02              Driver Version: 511.69       CUDA Version: 11.6     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                  Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf            Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA RTX A5000 Laptop GPU     On | 00000000:01:00.0 Off |                  N/A |
| N/A   64C    P0               84W /  N/A|  14128MiB / 16384MiB |     99%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+

+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A     73252      C   /python3.8                                N/A      |
+---------------------------------------------------------------------------------------+

まずは 1世代(5000 epoch)
人生は猫のようなものである

------------------------------
人生は猫のようなものである、なぜならば青くなるものとなる。彼女は他の日本では、自分の活動を行っており、『THE BEND ESTAL BASTARA II』の1つになっている。
「GAIN」は、地球へ帰還するのを防いでいるだけである。地球内のどの人である。地球と日本では地球上での地球のような人口のほか、自宅のサッカーにも「アイディア」を用いて出したので、その時に日本でも言われている時にはその人々を好んでいたという。
タッチングでは、1965年8月18日、パーク・ハングルが日本海軍の上海でサッカーとして出発した(当時の海上戦艦クラック)。同月15日、シリーズは日本に移り、ジ ャッキーは艦艇を襲っていた海戦のジャッキースと対戦した。しかし、ジャック・メンズの攻撃が地球へ向かう途中、海軍を追っていたハワ
---------- 3.43s ------------------------------
人生は猫のようなものである、なぜならば、家が生まれているという話が多いが、幼児が1808年に発生した中村を去っているという、という評判はそれに応えた。元はそのため、3人の幼生の頃からの探究で一貫して行ったが、1942年に長崎に入り、「父は身を隠していた。だけです。」という言葉を取り、森の木に関する事件が発生 した。
吉原は村上で終わり、1928年に第32回衆議院議員総選挙で落選。山田は1937年に前川佳彦の「沼田に開いたのは私の好きな人で、やり過ぎた行動を受けた。しかし、後の福島の第一の子に出会ってやっていいのだ。それを知るだけで、野村は「私が言うだ」と言ってきた。
しかし、中野はイングランドから離れた女性の子孫であるため、リュブランはやり手に一切差別を行った。結局、しばらくは愛馬と結婚しており、
---------- 3.75s ------------------------------
人生は猫のようなものである、なぜならばコンテンツなどの地域を選ぶために作られたものである。家にも3人の人間が生まれるという成果があるが、今日も親分に不 均衡であると考えられている。
男性の子の性質を持っているため、心臓の血分けの低下があり、そのようにいったという理由から、男性にかかる身体の背後にはおよそ8人の子供を持つ人があったと いう。ただし、ある日、リスカールのミニチャンスが無いことはあるが、女性は高いという趣向により、女性に愛されている女性のようにそのまま存在する。
チャールズ・カップはメリップス("The Jooner Wall")における感染における化学的効果は、人々の反応と言える心を持っている。ウィルソンが持ち合わせておくこ とに、心臓の状態ではこのように出血している。
ジャーナルは201
---------- 10.77s ------------------------------

吾輩は猫である

------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。彼らは一切ないであるため、父がすでにこれを知ったりしていたという。しかし、中国語での彼の話者は少数民族が出発的に見舞われた。夫の出身地としては、いったん発見した人物であり、スティーナ人がゲルドの姿を見せてしまう。ただし、『中国人のためにその人々を話している。 『黒く塗られる』とは、男女の家ではなくも、親であったということがある。
ハンガリー王国のひとつである王国が家を訪れた際、彼はまたなぜなら、彼を愛していたと言っている。エイマーが対抗した王国に対して、彼の持ち主がパーチャー(タイ)を呼び掛ける。
正式名称はドミニク・ド・モール("Elinker Freckart State destare")は、2003年に設立されたドイツ・マリネッツワールド。オックスの
---------- 15.91s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。フランスに出演するのは「わからない」と叫んでいたが、ギャングで「みんなのためにやるまでドキュメンタリーに応援したい」と答えた。2010年、「オーランダの声」を「あんかけ」でしたが、2019年の最終回は「グランドの子ども」と呼ばれることがあったが、2022年に日本初の子ども、フジテレビとして「歌われることになっていた」と報じた。2013年8月29日にドラマCD『Reyt Hankers & Ware』では、2011年2月18日に、主 演はCBCで「"Base Beokoker Work"」と題して行われた。
川内は、北海道を「港湾」で紹介する一般的な意味であるとの指摘を受けた。すなわち、北海道の東海道新幹線の駅でもあるフランスのトランプを「スティクステップ」し、
---------- 11.53s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。また、音楽としての本当の始まりをつけ、時には大人の手に「お願いでもこんなくなった」と言った。その際に大きな数の入手が手を盗んだと言い、その日には大敗している。
『吾妻鏡』では、出版当初は、The Collect of Compark Cheamy、Jesto Beller、Weermy Framer、Band Googly、Lay's Gada Telose)とは、ハーバード映画であるAreatentaly(アートファン)のプログループによる映画・プログループの手である。
これらの曲は、プログループBS・HDSであり、オンラインシリーズの主題歌となった映画は、ロンドンのカップリング曲であり、リリースされたライブ「ゴーグルスの 曲が映画化されるなどしてもいい」と
---------- 11.74s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。彼の父・三山はほぼ離婚し、父の子が母の前の一家には直接相談していたが、その子になったのではないかと言い、彼はこれを拒絶した。
その後、2012年(平成25年)3月30日に公開された。4月1日に「パートナーは本当の前に「オリエントの仲に切り分けてしまう」と報じ、同月28日のミラーリカの新聞 での撮影に際して「バック・ジャズ」としてレギュラー出演した。
別のMVPのレギュラー番組を実施した後、リリースではBCN、BSであるプレーオフ、本作品のプロデューサーとなった。本人のインタビューでは「BSOONDA Aronother」 としても上演。本編でもトップ・サーキャラとしての役に出演した。
番組初期の12月12日(6月2日)に行われた『Ercoder Ness Fre
---------- 10.85s ------------------------------

続いて 10世代(50000 epoch)
人生は猫のようなものである

------------------------------
人生は猫のようなものである、なぜならば何も変わらない人間である。それは、人間の生きる可能性があるということによって起こる。それは、猫の意識を素直にしてくれる人間の肉を生きたいという思いだった。ところが、人間が存在しているときはその肉の粒が人間の知性を失うことになる。それが、実際には人間がその生き残った者になってしまうのである。そのことは、そのままの自分の姿になってしまう。自分が現実の人間の生活に重要な変身をするようなことをしてみれば、自分の能力に自分の立場は変わる。
猫が変身したとき、彼女はそれまでにいた、彼女が通っていた猫の姿を、ある場面で実際に動かすことができる。自分の能力は、生きる気力を取り戻した人間の前に、ある者の家の中で争うことである。その後、どういう家族の生きる道が、道中で自分の力で
---------- 2.76s ------------------------------
人生は猫のようなものである、なぜならば、人間の生命を操るものではないという理由で生まれたのか。ただし、この二人は『フィアリー』の一年前の出来事である。ジョージ・クリントンは、またそれによると、この『クリントンの犬』は「完全な」旅行の最終段階の「あなた」の結末として広く知られている。
2011年12月、ハリー・ポール・ポールの『ポール・ジョンソン』の「月曜の金曜 1時」の映画化。2012年1月25日、『ポール・ポール』の後半11分と2時間半映画化された。アカデミー賞授賞式において、2011年のオリジナル・キャスト・スタッフォードシャー賞を受賞した。
最初のドラマ版は1983年10月25日にテレビドラマ化された。主題歌には、そのアレンジが追加された映画『コーディアン・ハント』のサウンドトラック・アル
---------- 3.91s ------------------------------
人生は猫のようなものである、なぜならばしばしば誰かが子供のままで育った子供を育てることになる。人の子供たちにとっての彼らのものは、親のそれよりも子供がそれに該当しない人が、いつでも身体を動かすようになるからである。また、人間の子供は親の人生を持つことは明らかになっていない。その結果、子供はいない。このようなものは人間の「子」であり、そのことを「子供」として考えることができる。
実際、子供の生活の中で、子供はどんな状態であるかを考えることができる。その場合は、「子供」となって子供を子供に引き入れ、親の親を「親」になることを意図している。「親の子」は「親」を「子」としている。その子供たちは「親の子」と呼ばれ、子供は「親」となる。親と子が親と子の間に子をもうける。親子関係は、親の子が「親子関係」をもっ
---------- 4.29s ------------------------------

吾輩は猫である

------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。幼少時は「いなか」と呼ばれる。幼い頃から頭に魚をいれていた。「尾黒だより」は甲州街道をすでに歩いていた。しかし、その名を「魚なのか」と思い、その後は「小名でも(小浜に)あまつしか来ないか」と返答すると、「お兄さん」という名前を付けられたという。小学校教員であるところには、小学校卒業後は船越へ進学し、小学校教員となる。1927年(昭和2年)、船崎長吉は小学校教員を兼ねていたが、名古屋鉄道へと 転じる。
1928年(昭和3年)、一級鉄道員の父親の転勤に伴い、西川は東京帝国大学法科大学法科大学法律学科を卒業。同年、同大学院法律学科卒業。在学中の1928年(昭和3年)、同大学院法務研究科博士課程修了。鉄道研究所を経て、東京鉄道法律事務所教授、国家公務員試験に合格。19
---------- 2.8s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。しかし、高校は成績が落ちたら、愛猫の死神博士と愛猫の息子・響(みゆき)の教育係である博士の修業を終えた父親・草倉によって育てられた。
日本では、清水商店街(現在のイトーヨーカ堂・いしこ・三菱ヨーグループホールディングス)から発売された、ビーチハウス1号店から発売されたショップ「ミック スダウン」を引き継いでおり、その後、親会社であるイトーヨーカ堂の店舗が、発売されている。
ひかりと小学生の二人のみの生活を描いた短編漫画で、元々は第1回の主人公・岡島大介の漫画として書かれた。前回は2年ぶりの連載であったが、2006年12月22日に発売された。また、タイトルのみにおいては「しゃべり(こぶろく)」「おぎりさん」という表記がある。
『ストームの場合、ストームはペットで
---------- 2.76s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。大学卒業後、1972年、東京都練馬区の海外事業委員会の委員となり、1974年、カンタータ『ハンター』の初演に参加。1978年、東京都立大学経済学部助手。1981年、日本経済連携協定 (JTA) 立教大学教授。1990年、学習院大学経済学部講師。1998年、大阪府立総合 学校協議会会長。2004年、東京大学経済学部教授。
ボランティアを中心とした支援団体により大学設置に向けて建設された「JTPF」(クラウド・ディーゼル)の2008年には、「カンターターゲット・グローバル」としている。2010年、全日本学生電子計算機協会 (JAPAN) の学術委員会委員長を務め、2012年、「JTTC」の委員長に就任。2014年、大阪府「中央市場経済連携協議会」によ る「学術協議会
---------- 2.88s ------------------------------

文脈としては良さそうになった。日本語の違和感も減った気がする

学習済みのモデルはだいたい1.5GBとなっていた

$ ls -ltrh trained-*
-rw-rw-r-- 1 octu0 octu0 1.5G Apr 23 15:29 trained-1.pth
-rw-rw-r-- 1 octu0 octu0 1.5G Apr 23 18:44 trained-11.pth
Yusuke HataYusuke Hata

青空文庫のデータを使って文豪モデルデータを作ってみよう

使用するのは github.com/aozorahack/aozorabunko_text で、今回は 夏目漱石 だけで作ってみる

まずは aozorabunko_text を持ってくる

$ git clone --depth 1 https://github.com/aozorahack/aozorabunko_text.git

次に、青空文庫形式のテキストには ルビや注釈が入ってるのでそれを取り除いてあげる必要がある
ルビは、例えば 下宿屋は二階中を開《あけ》ひろげて蚊帳《かや》や蒲団《ふとん》を乾して居る のように文中に入っている
これは、取り除いてあげて 下宿屋は二階中を開ひろげて蚊帳や蒲団を乾して居る とする方が学習するときに余計なものが混ざらなくて良くなる...はず
他にも、入力者注や古い繰り返し文字(フラ/\ とかいて フラフラ と読むっぽい)なども入ってる

これらを取り除くように github.com/octu0/aozoraconv で作っておいた

さて、あとは夏目漱石のテキストを集めてみる
こんな感じのshellにした

#!/bin/bash

list=()
list+=("000148/2314")
list+=("000148/1086")
list+=("000148/758")
list+=("000148/2669")
list+=("000148/59017")
list+=("000148/792")
list+=("000148/1046")
list+=("000148/769")
list+=("000148/2383")
list+=("000148/760")
list+=("000148/2674")
list+=("000148/2670")
list+=("000148/778")
list+=("000148/777")
list+=("000148/2373")
list+=("000148/776")
list+=("000148/761")
list+=("000148/770")
list+=("000148/771")
list+=("000148/759")
list+=("000148/775")
list+=("000148/774")
list+=("000148/773")
list+=("000148/1073")
list+=("000148/766")
list+=("000148/784")
list+=("000148/794")
list+=("000148/795")
list+=("000148/768")
list+=("000148/796")
list+=("000148/1104")
list+=("000148/797")
list+=("000148/2680")
list+=("000148/2315")
list+=("000148/1102")
list+=("000148/56143")
list+=("000148/2667")
list+=("000148/2370")
list+=("000148/2668")
list+=("000148/4686")
list+=("000148/798")
list+=("000148/4672")
list+=("000148/2313")
list+=("000148/757")
list+=("000148/2682")
list+=("000148/788")
list+=("000148/751")
list+=("000148/2673")
list+=("000148/791")
list+=("000148/787")
list+=("000148/2376")
list+=("000148/762")
list+=("000148/765")
list+=("000148/754")
list+=("000148/756")
list+=("000148/755")
list+=("000148/2681")
list+=("000148/2679")
list+=("000148/2371")
list+=("000148/753")
list+=("000148/763")
list+=("000148/1750")
list+=("000148/752")
list+=("000148/2375")
list+=("000148/1751")
list+=("000148/780")
list+=("000148/781")
list+=("000148/783")
list+=("000148/786")
list+=("000148/782")
list+=("000148/2372")
list+=("000148/1747")
list+=("000148/785")
list+=("000148/799")
list+=("000148/2675")
list+=("000148/2678")
list+=("000148/2676")
list+=("000148/779")
list+=("000148/1076")
list+=("000148/789")
list+=("000148/2677")
list+=("000148/772")

aozorabunko_text_dir="/path/to/aozorabunko_text"
out_path="/path/to/natsume_souseki.data"
aozoraconv="/path/to/aozoraconv_linux_amd64"
echo "" > ${out_path}

for v in ${list[@]}; do
  person=$(echo $v | cut -d'/' -f1)
  card=$(echo $v | cut -d'/' -f2)
  card_dir="${aozorabunko_text_dir}/cards/${person}/files/${card}_ruby*/*.txt"
  file=$(ls ${card_dir} | tail -n1)
  ${aozoraconv} ${file} >> ${out_path}
done

(このリストは新字新仮名のものにしてる)

さて、出来上がった natsume_souseki.data は 9.5MB 程度なので、VRAMにも乗るかもしれない...と思っていたのだがどうやら元データの大きさはVRAMにはあまり関係なく、embed/layer は僕の環境では 2048/1024 が精一杯らしい

train.py で再度学習させてみた
学習済みのデータを見ると 1.3GB とかなり大きくなっている、元データが小さくてもここまで太るのであればある程度のサイズに収束するようになってるのかな(?)

$ ls -ltrh trained-*
-rw-rw-r-- 1 octu0 octu0 1.3G Apr 23 22:38 trained-1.pth
-rw-rw-r-- 1 octu0 octu0 1.3G Apr 24 01:39 trained-11.pth
-rw-rw-r-- 1 octu0 octu0 1.3G Apr 24 04:37 trained-21.pth

1 epoch の結果

------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。それでなければ今日まで運動もせぬ。よし帰る事があるからと云って吾輩の威厳を損する訳になる。いくら猫だってかくのごときものは今吾輩のように変化があるから、この爪だらけの食物をして、これこの猫の手際ではちっとも肉の上で食いつめない事を云う。
 吾輩は元来不親切の度と号令を下した。口は食った。口は一も二もなくなった。吾輩も彼等の言語動作を笑いながら吾輩の爪先の冷たき堅い頸を残して、噛りつくようにしてこの頸を握った。そうして、前後のつもりに、すべすべした手を竪にして、この時少し肉体を膳の上に起す。
「少し頭が緊張するようだ。その代りいくら口を食えば、何時ものっても脳の方が変らない。それよりもっともぐって後れる方が好いよ。いくら苦しいから爪を食っても食えない。もっとも
---------- 43.13s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。ただあててその説明はこれよりも腹のなかで彼の頭のなかに、われを弁護するようなものである。
 吾輩は二本の毛並でないと云った。吾輩はまた実際問題を変える。吾輩は松の木を二本、三羽の縁は三寸くらいくらに位している。しかし両手で彼が出来るだけ鏡を取っては、吾輩を連れて布団の上に突き出させる。彼は杖を突いて、右左の手を平げた。左の手の平の傾向に姿を認めた時、彼は何事も云わずにぴたりと留まった。そうして大きな声で、いつの間にやら黒木綿の羽織を脱ぐのが面倒だといった。その時彼はすぐ頭から上に反射して、やむをえず叫びかけた。この様子を見たときは、いつまでも黙ってその人が自分の過去を振り返って、前後に尻を据えていたと云った。彼は後向を見るといつの間にか黒い波が吾輩の鼻面を掠
---------- 39.58s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。分りやすくてもしようがない。
 吾輩は松本の生徒が三四十字の街号を切るときは必ず君の番号を順々に点検し来る。無事件は大事件である。わがままなるべく大きくてて義経をせぬ。それは惜気もなくて心がくれば、いつの間にか舞い戻って来ても、二人の後に廻らんでいる。
 春の二三十六畳に東菊がいつの間にか、美禰子の家へ来るべき、かつて二人の家にいた。美禰子はまた、
「どうです」と聞いた。三四郎はまた、
「どうだ」と答えた。すると、野々宮君ははじめて、
「ええ」と言った。
「もう少しで美禰子さんの所へ行って、美禰子さんの所へ行った。
 学生時代の教師はなかなかもっていない。学生は日本の学校生で、これはみんな研究のためで、よくないからなんともなかった。自分も一人で学生の名を持っ
---------- 39.3s ------------------------------

なんとなく夏目漱石っぽさがある
ベースモデルは結構重要らしい

50000 epoch

------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。何でも去る事が出来ないのに、もっとも上等の化物に対して痛み入った事ではない。「ちょっとこの国のものだ」と主人は平気な顔で鼻毛を一本一本丁寧に原稿紙のなかから、ジェームスの孔の開くのを待っている。よく聞くと二本の数十倍が繰り返すと十六世紀の今日では格にはとあるいはまず木の葉を虫の息のようにどんなものだか見当がつかないからこの不作法と云われる。「カーライルの事を知ってるか」と主人のように言いながら挙げたが「どうも昔のように意気銷曲したり、胡魔化したり」と勘定した。女も異様に真面目である。「思い切って南の方へ行ったり傷けたり、押そっとして自分の膝の上へ乗ったり、ジャムを御覧なさい。どうだろう」
「うん」
「あなたまでは、若過ぎて」と試みた事はあるが、これも熱誠だと
---------- 39.25s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。何でも吾輩の眼を遮って見ると、何だか馬鹿馬鹿しい。嬉しくって、夜具の裾にかたまった五六寸は必ずいたなと思ったが、それでも時々は痛むかと思うと、胸からまで何をしているか分らない。直念に念のために吾輩はいかにも優しい。ただおのためにする事がある。元来何のためにこの障子を睨め付けるのはいやだ。御勢いが泥棒のために一体泊らせると云うのではない。尻尾を換えて口を結んだ。吾輩は返答を待つために、さっきから怒っている。催促して見るときはっと忍んでいる。吾輩はいつでもこの障子をあけて行く。吾輩はいくらこの洗湯に行ったって、まだコップから帰って来る。吾輩はいつでも彼等の中間に己れを容るべき余地を見出してどうにか、こうにか割り込むのであるが、運悪く小供の一人が眼をつくって問答に
---------- 39.04s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。何でも物になって見たいと云う念がある。腹から尻尾に立つと云うのが口につきそうに強くなっている。それでなければこの態度でいかなる事を騒がずにかつるほど、事はないのだが、そこが訓練である。否であるから滅多に聞けるにゃあ、まったく貰いたい。貰いたいからと云うのではない。腹に乗ると云うと怒鳴るからだ。速水君が借りたんだろうが、嘆息してもらう方がいい、まあ年長者の随意によって、おっしゃった事はあるまい。学校の正直なためだから、なるべく世間に信用して、日中でも同じ事を繰り返した。この福原は精神の自由になる。すべてが目的である以上は、日本の目的がすでに汚すに足らないからである。吾等は卒業生を生徒と呼んで、一時間の勉強をした。碌なものになるのは馬鹿と云うが、何も坊主と云う意
---------- 39.12s ------------------------------

200000 epoch

------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。何となく落ちつきがあったが、その魂が処世の常に空虚なる行為を遺憾とする。仕方がないから、ここで一目散に逢う。これは厄介な事をやめて、だいぶ落雲館であるが、ごみごとの月給ではあるが古えの人間になる。髯巡りはふうと音がして室の中が出た。この課長が例のごとく生中にあるがごときものである。あれはうらなり君のうちには六年目になるから、どうでもいいが、もう君のうちに免職になってはならないはずだ。しかしあれがいちゃ、君、大学の教師になっても構わないのは気が済まない、また小遣を担がれただけならいいが、つまりあなた方は発明しないからね、藤尾を仕合せなんだ」
 宗近君はだまっている。はなはだ気の毒である。小野さんはまたあくまでも責任を知らない。
「いや時々行った。なにそう云う損
---------- 39.59s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。何となく彼等が猫に恐るべき理由がない。
 美学者は分子を風呂敷に包むまで、長い薄色の毛が、寝ボンボンと変るところもまた格別なので、ふと女の存在を主人の眼前に開けると大に悟ったところである。首脳の左側に、小さく薄暗く、なだれ付合っているのは、全く朝鮮流である。余は常に好い心持である。小供の時分から小さい声であったから、どんな場合か見物に来たって今日限り取り寄せて見たい気がする。
 けれどもこの時の光景は、眼の前にある不吉なる顔ばかりである。鮮血天日にはえっくりしたる好い事柄が明らさまに見えた。
 自分の室は明日の心を喘ぐ。この明る木だけに、これほど都合のいい事を、好い加減に運び出した。御爺さん、西洋の詩は喜いちゃんの頭が布団の下にいる。彼らの頭脳には少々の異介
---------- 39.68s ------------------------------
吾輩は猫である、名前はまだない、どこで生まれたか見当もつかぬ。ただ所有者であるから、ここには強いて何にも云い兼ねる。しかし実際はどうする事も出来ない。ただ君を軽蔑してはいけない。武右衛門君は監督の家へ来て、きっと人間について、一の真理を発明したに相違ない。彼はこの真理のために将来ますます本当の人間になるだろう。人の心配には冷淡になるだろう、人の困る時には大きな声で笑うだろう。かくのごとくにして天下は未来のために束縛されている。彼等は未来のために己に服せられたる結果、われよりも数倍倍の大木でも打ち明けぬごとくに、連われたる紳士だけが奮発して日ごとに島田に逢うのがいかにも愚になった。健三の神経はびーび起る。彼はアーサーの室に馬乗り立ての武器を蓄えたる新聞をすらすらと開けた。色沢の知らぬ男は無茫のうちに彼のいる事を見る。彼の
---------- 39.37s ------------------------------

今回は epoch 数が増えると目に見えてよい結果になっている気がする

Yusuke HataYusuke Hata

前回vocab.jsonの謎 も大体わかったので RWKV-LM/RWKV-v4neo で scratch モデルを学習させてみた

パラメータはこんな感じにして、 ja.txt としているのは以前作った 青空文庫と日本語wiki のテキストデータのみ、 36時間 (50 iteration) 回してみた

vocab_size=0
batch_size=6
layer_size=12
embd=1024
ctx=1024
python train.py \
  --load_model "" \
  --wandb "" --proj_dir "out" --data_file "/path/to/ja.txt" \
  --data_type "utf-8" \
  --vocab_size ${vocab_size} \
  --ctx_len ${ctx} \
  --epoch_steps 5000 \
  --epoch_count 500 \
  --epoch_begin 0 \
  --epoch_save 5 \
  --micro_bsz ${batch_size} \
  --n_layer ${layer_size} \
  --n_embd ${embd} \
  --pre_ffn 0 --head_qk 0 --lr_init 8e-4 --lr_final 1e-5 --warmup_steps 0 --beta1 0.9 --beta2 0.99 --adam_eps 1e-8 \
  --accelerator gpu --devices 1 \
  --precision fp16 --strategy ddp_find_unused_parameters_false --grad_cp 0

ちなみに strategy には deepspeed_stage_2deepspeed_stage_2_offload などの パラメータ が使えた。他にも ddp_sharded_find_unused_parameters_false とかもいけそうだったけど、train.py に書いてある通りにやっている

out/train_log.txt が出力されていて
左から エポック数, ロス率, exp(ロス率), lr(おそらくlearning rate), 時刻, current_epoch となっている様子
1エポック 40分強といったところ

0 2.834635 17.0242 0.00079302 2023-04-27 23:34:01.254934 0
1 2.432336 11.3855 0.00078610 2023-04-28 00:16:22.400534 1
2 2.299842 9.9726 0.00077924 2023-04-28 00:58:38.490563 2
3 2.220625 9.2131 0.00077244 2023-04-28 01:41:04.519932 3
4 2.166474 8.7275 0.00076570 2023-04-28 02:24:06.573226 4
5 2.123091 8.3569 0.00075902 2023-04-28 03:07:16.749912 5
6 2.089440 8.0804 0.00075240 2023-04-28 03:50:24.324153 6
7 2.061960 7.8614 0.00074583 2023-04-28 04:33:25.160109 7
8 2.034411 7.6477 0.00073932 2023-04-28 05:16:32.190167 8
9 2.015397 7.5037 0.00073287 2023-04-28 06:00:04.654776 9
10 1.999844 7.3879 0.00072648 2023-04-28 06:43:49.264625 10
11 1.979830 7.2415 0.00072014 2023-04-28 07:27:27.789402 11
...
48 1.757644 5.7988 0.00052070 2023-04-29 10:09:00.736651 48
49 1.752768 5.7706 0.00051616 2023-04-29 10:52:45.997341 49
50 1.753056 5.7722 0.00051165 2023-04-29 11:37:13.113378 50
51 1.749058 5.7492 0.00050719 2023-04-29 12:21:09.661531 51
52 1.747669 5.7412 0.00050276 2023-04-29 13:04:57.713504 52

グラフにするとこんな感じ

わかりづらいので loss だけでみると、じわじわ下がっているけどきびしめ

1 epochあたりのlossは後半はほぼ0に近い値なので十分に学習できているのかもしれない

可視化を頑張るのではなく wandb が使えるので、今後は引数に指定しなければ...

さて、次に生成された out/vocab.json を読み込ませるように修正しよう
train.py で使っている vocab は UTF16-LE で保存しているのに対して、 run.py で使っている TOKENIZER は UTF16 となっており、そのまま vocab.json を読み込ませようとすると UnicodeError: UTF-16 stream does not start with BOM となってしまう

--- a/RWKV-v4neo/src/utils.py
+++ b/RWKV-v4neo/src/utils.py
@@ -26,7 +26,7 @@ class TOKENIZER():
             self.vocab_size = len(self.tokenizer)
         else:
             self.charMode = True
-            with open(WORD_NAME + '.json', "r", encoding="utf-16") as result_file:
+            with open(WORD_NAME + '.json', "r", encoding="utf-16le") as result_file:
                 self.word_table = json.load(result_file)
 
             self.vocab_size = len(self.word_table)

次に run.py では次のようにして out ディレクトリに生成されている vocab.json を指定する
vocab_size は train_log.txt に出ているのでその値を指定

-TOKEN_MODE = "pile"
-WORD_NAME = [
-    "20B_tokenizer.json",
-    "20B_tokenizer.json",
-]  # [vocab, vocab] for Pile model
-UNKNOWN_CHAR = None
-vocab_size = 50277
+TOKEN_MODE = "char"
+WORD_NAME = "out/vocab"
+UNKNOWN_CHAR = " "
+vocab_size = 18273

次にモデルの読み込みと、初期コンテキストを用意する、 temperature および top_pTEMPERATURE = 1.0top_p = 0.5 にしている(top_pは少し下げた)
比較を出したいので TRAILS 関係は下げてる

MODEL_NAME = './out/rwkv-5'
n_layer = 12
n_embd = 1024
ctx_len = 1024

context = "\n吾輩は猫である、名前はまだない、"
NUM_TRIALS = 3
LENGTH_PER_TRIAL = 100

TEMPERATURE = 1.0
top_p = 0.5
top_p_newline = 0.55

最後に CPU 実行 + bf16 にする

args.RUN_DEVICE = "cpu"
args.FLOAT_MODE = "bf16"

epoch 5 で実行すると

$ python run.py

Using CPU. Loading ./out/rwkv-5...

RWKV_HEAD_QK_DIM 0 RWKV_JIT_ON 1

emb.weight                               bfloat16   cpu
blocks.0.ln1.weight                      bfloat16   cpu
blocks.0.ln1.bias                        bfloat16   cpu
blocks.0.ln2.weight                      bfloat16   cpu
blocks.0.ln2.bias                        bfloat16   cpu
...

Loading tokenizer out/vocab...

Your prompt has 17 tokens.
Note: currently the first run takes a while if your prompt is long, as we are using RNN to preprocess the prompt. Use GPT to build the hidden state for better speed.

--------------------------------------------------

吾輩は猫である、名前はまだない、と思っていた。彼はある日、ある猫の一人に、たまたま出会ったのがあるという。その猫の名前を見たのは、猫の名前を思い出したかった。彼はそれを聞き、彼の友人である猫をあげて、猫のようにしていた。その猫の顔は

--- preprocess 0.26s, generation 1.63s --------------------------------------------------

吾輩は猫である、名前はまだない、猫のようなものである。「猫の猫」という言葉は、「猫のようなもの」という意味である。この猫の話によれば、猫の話の中には、猫のような怪物であるという説もある。猫は、ある種の話には、話の中で話しているのがあ

--- preprocess 0.0s, generation 1.61s --------------------------------------------------

吾輩は猫である、名前はまだない、などということもあり、名前の「猫」という字は、「猫」という字を意味するという。猫の頭の「猫」とは、かつては、猿の意味であったが、1980年代においては、猫の姓を用いていたということがわかる。
その後、

--- preprocess 0.0s, generation 1.61s --------------------------------------------------

次に epoch 25

$ python run.py 

Using CPU. Loading ./out/rwkv-25...

RWKV_HEAD_QK_DIM 0 RWKV_JIT_ON 1

emb.weight                               bfloat16   cpu
blocks.0.ln1.weight                      bfloat16   cpu
blocks.0.ln1.bias                        bfloat16   cpu
blocks.0.ln2.weight                      bfloat16   cpu
...

Your prompt has 17 tokens.
Note: currently the first run takes a while if your prompt is long, as we are using RNN to preprocess the prompt. Use GPT to build the hidden state for better speed.

--------------------------------------------------

吾輩は猫である、名前はまだない、というのは自分はどうしても自分の名前を呼ばなければならないということである。吾輩は自分の生まれた時、生まれてすぐに死んでしまう。吾輩は名前を呼ばれることがある。自分は名前を覚えている。自分の名前は自分

--- preprocess 0.26s, generation 1.65s --------------------------------------------------

吾輩は猫である、名前はまだない、猫は猫である、猫は猫である、猫は猫である、猫は猫である、猫は猫は猫である、猫は猫は猫である、猫は猫は猫である、猫は猫は猫である、猫は猫は猫である、猫は猫は猫である、猫は猫は猫である、猫は猫は猫は猫であ

--- preprocess 0.0s, generation 1.61s --------------------------------------------------

吾輩は猫である、名前はまだない、ということである。吾輩は吾輩のその名前を明らかにしているので、吾輩は吾輩の名前をどうやって呼ぶのか、どういうことをしているのか、ということはわからない。吾輩はこの名前を「名前」と呼んでいるのである。


--- preprocess 0.0s, generation 1.61s --------------------------------------------------

先ほどのグラフで見る限り、25 epoch以降はそんなに loss が下がっていないので、微妙だが...

epoch 50

$ python run.py 

Using CPU. Loading ./out/rwkv-50...

RWKV_HEAD_QK_DIM 0 RWKV_JIT_ON 1

emb.weight                               bfloat16   cpu
blocks.0.ln1.weight                      bfloat16   cpu
blocks.0.ln1.bias                        bfloat16   cpu
blocks.0.ln2.weight                      bfloat16   cpu
blocks.0.ln2.bias                        bfloat16   cpu
blocks.0.ln0.weight                      bfloat16   cpu

Loading tokenizer out/vocab...

Your prompt has 17 tokens.
Note: currently the first run takes a while if your prompt is long, as we are using RNN to preprocess the prompt. Use GPT to build the hidden state for better speed.

--------------------------------------------------

吾輩は猫である、名前はまだない、猫はいつも猫にちがいない、猫ではない。いつも猫のように「猫」のようにあたりを見渡している。猫のように上になって、あの猫は「猫」と言っている。「猫」は一種の猫である。猫は猫のように、目の下についている。

--- preprocess 0.29s, generation 1.7s --------------------------------------------------

吾輩は猫である、名前はまだない、この猫は猫のような、とても大きな猫である。いつも猫におそわれているのは、その猫が、ただ猫になっているのだ。その猫は、どこからともなく現れて来る。この猫は、猫のことを猫猫と呼んでいるのだ。
 猫は、いつ

--- preprocess 0.0s, generation 1.99s --------------------------------------------------

吾輩は猫である、名前はまだない、猫のような名前を持っている、と。「お前の名前を名前に付けるのは、この猫の名前の由来である」
 それは、なんだか頭の色が、白く見える。猫の名前を、一つにまとめたものである。これはおそらく、猫の名前の中に

--- preprocess 0.0s, generation 1.99s --------------------------------------------------

微妙だなぁ

次に context をもう少し長くしてみた使った文章は これ
あとtop_p は 0.2 に下げ、newlineのtop_pも0.25まで下げている

context = '''
次の文章を要約します
文章は『 起業家イーロン・マスク氏が創業した宇宙開発企業「スペースX(エックス)」の巨大新型ロケット「スターシップ」が20日朝、初めて打ち上げられたが、爆発した。
打ち上げは米テキサス州の東海岸で行われた。無人の試験で、負傷者はいなかった。
打ち上げから2~3分後、史上最大のロケットが制御不能になり、まもなく搭載された装置で破壊された。
マスク氏は、数カ月後に再挑戦すると表明した。
スペースXのエンジニアたちは、それでもこの日のミッションは成功だったとしている。「早期に頻繁に試験する」ことを好む人たちなので、破壊を恐れていない。次 のフライトに向け、大量のデータを収集したはずだ。2機目のスターシップは、ほぼ飛行準備が整っている。
マスク氏は、「SpaceXチームの皆さん、スターシップのエキサイティングな試験打ち上げ、おめでとう! 数カ月後に行われる次の試験打ち上げに向けて、多くを学んだ」とツイートした。
アメリカでのロケット打ち上げを認可する米連邦航空局(NASA)は、事故調査を監督するとした。広報担当者は、飛行中に機体が失われた場合の通常の対応だと述べた。
マスク氏は打ち上げ前、期待値を下げようとしていた。発射台の設備を破壊せずに機体を打ち上げるだけでも「成功」だとしていた。
その願いはかなった。スターシップは打ち上げ施設からどんどん上昇し、メキシコ湾の上空へと向かっていった。しかし1分もしないうち、すべてが計画通りに進んで いるのではないことが明らかになった。』
要約すると、 '''

NUM_TRIALS = 2
LENGTH_PER_TRIAL = 150

TEMPERATURE = 1.0
top_p = 0.2
top_p_newline = 0.25  # only used in TOKEN_MODE = char

結果はこうなった( context のprintはコメントアウトしているので結果だけ )

$ python run.py

Using CPU. Loading ./out/rwkv-50...

RWKV_HEAD_QK_DIM 0 RWKV_JIT_ON 1

emb.weight                               bfloat16   cpu
blocks.0.ln1.weight                      bfloat16   cpu
blocks.0.ln1.bias                        bfloat16   cpu
blocks.0.ln2.weight                      bfloat16   cpu
blocks.0.ln2.bias                        bfloat16   cpu
blocks.0.ln0.weight                      bfloat16   cpu
blocks.0.ln0.bias                        bfloat16   cpu
blocks.0.att.time_decay                  float32    cpu
blocks.0.att.time_first                  float32    cpu
blocks.0.att.time_mix_k                  bfloat16   cpu
...

Loading tokenizer out/vocab...

Your prompt has 660 tokens.
Note: currently the first run takes a while if your prompt is long, as we are using RNN to preprocess the prompt. Use GPT to build the hidden state for better speed.

「宇宙船は、次の瞬間、宇宙船の周りを公転している宇宙船が、われわれの宇宙船の周りを公転していることが分かった。それは、宇宙船が地球に向かう軌道を変えることによって、宇宙船が地球に接近するのを防ぐことだ。それは、宇宙船が地球に接近するのを防ぐためのものだ。」
宇宙船は、宇宙船の周囲を公転しているため、軌道船の周囲を公転している。
軌道船は、地球の引力圏を超えて、地球の重力圏を超えて、地球の重力圏に入り込んでいる。
軌道船は、地球の引力圏を超えて、地球の重力圏に入り込んでいる。
軌道船は、宇宙船の推進剤を使い、水の代わりに液体酸素を推進剤として使用している。
この船は、船の運動を制御するために、船

--- preprocess 16.22s, generation 7.94s 

「それは、宇宙船が、自分の持つ大きさに匹敵するほどの大きさの宇宙船を、小さな宇宙船に乗せて、自分の持つ大きさの宇宙船に乗せることだ。それは、それがすべての乗組員にとって、自分の任務に適したものになるように、宇宙船を乗せることだ。」
その後、スターシップは、自分の乗る宇宙船を、小さな宇宙船に改造した。
「スターシップ」は、自分のマストに固定されたマストの上に乗って、マストの頂上まで上昇していく。
そのマストの頂上に、大きな宇宙船がいる。
それは、大きな宇宙船が自らの持つ大きさに比例して、推進力を得るために自らの推進エンジンを使用しているためである。
そのマストの中心には、固定式の固体燃料補助ロケ

--- preprocess 0.0s, generation 8.67s 

マスキューは、この計画を成功させるために、大きな努力を払っていた。
宇宙船の推進剤を使い、大気圏に再突入し、次々と点火していくマッハのメッサーシュミット・ベル IIIの試験を行った。
その結果、マスキューは、マスキューの推力によって月の重力を減らすことができることが分かった。
月面に着陸したマスキューは、大気圏を突破して月面に接近し、地球への帰還の準備を進める。
その過程で、マスキューは故障した大気圏再突入用の液体酸素を調達し、月面に再突入させる。
再突入用の液体酸素と、その燃焼によって得られたアルファエーターが、月面に衝突する様子を撮影した画像に、マスキューのマークIIが搭乗していた。
マ

--- preprocess 0.0s, generation 7.39s --------------------------------------------------

なるほどなぁ。

学習時間が増えて日本語っぽさは正しく出てくるようになった気がするし、何回か試してると明らかにwikipediaの情報を使ってくれるようになってるけど、文章としてちゃんと出せてないな...

次は tokenizer あたりを微調整するしかないかな...

Yusuke HataYusuke Hata

tokenize するときに最低限の日本語分かち書きをするようにしよう

ネットで調べると BertWordPieceTokenizer が最初にヒットしたものの、必要なメモリサイズが大きいので(このtokenize後にtorch実行時にOOM killerになってしまう)、シンプルに分かちだけ行うようにした

当初は janome.tokenizer でやっていたのだけど、大きなテキストを読み込んで分かち書きをするとheapが足りないことがある(し、こまめにgc.Collect()は大変なので)ので、別プロセスで行うようにしてtokenizeのメモリ管理は外部で行うようにした
別プロセスにするので、Goで github.com/ikawaha/kagome で分かち書きしたものを利用するようにしてみた

kagomeで分かちしてみると 2326532 vocab size (今回使ったテキストデータでは2.5GBくらいのサイズ) と膨大な数になってしまい、train するには VRAM が全然足りない結果になってしまう

今回は vocab は次のようにtokenizeしたものを使い、train時のパラメータを小さくすることで対応した

package main

import (
        "bufio"
        "log"
        "os"
        "regexp"
        "sort"
        "strings"
        "sync"

        "github.com/ikawaha/kagome-dict/ipa"
        "github.com/ikawaha/kagome/v2/tokenizer"
        "github.com/octu0/cmap"
)

var (
        empty        = " "
        lf           = []byte("\n")
        allalnum     = regexp.MustCompile(`^[0-9a-zA-Z _-]+$`)
        allsymbol    = regexp.MustCompile(`^[<>{};:&@_\-+=\!\?#\/\\\[\]\^"'~\.\,\(\)\*\$%\s]+$`)
)

func increment(m *cmap.CMap, str string) {
        m.Upsert(str, func(exists bool, old any) any {
                if exists != true {
                        return 1
                }
                v := old.(int)
                return v + 1
        })
}

func tokenize(wg *sync.WaitGroup, t *tokenizer.Tokenizer, queue chan string, m *cmap.CMap) {
        defer wg.Done()

        for {
                select {
                case str, ok := <-queue:
                        if ok != true {
                                return
                        }
                        if allalnum.MatchString(str) || allsymbol.MatchString(str) {
                                increment(m, str)
                                for _, s := range strings.Split(str, "") {
                                        increment(m, s)
                                }
                                continue
                        }
                        for _, token := range t.Tokenize(str) {
                                increment(m, token.Surface)
                                // 1文字ずつ入れているのは、src/dataset.py で1文字ずつ読み込むため
                                // dix = [self.stoi[s] for s in data[i : i + req_len]]
                                for _, s := range strings.Split(token.Surface, "") {
                                        increment(m, s)
                                }
                        }
                }
        }
}

type Token struct {
        Token string
        Count int
}

func main() {
        f, err := os.Open(os.Args[1])
        if err != nil {
                log.Fatal(err)
        }
        defer f.Close()

        t, err := tokenizer.New(ipa.Dict(), tokenizer.OmitBosEos())
        if err != nil {
                log.Fatal(err)
        }

        m := cmap.New()
        queue := make(chan string, 0)
        wg := new(sync.WaitGroup)
        for i := 0; i < 32; i += 1 {
                wg.Add(1)
                go tokenize(wg, t, queue, m)
        }

        s := bufio.NewScanner(f)
        for s.Scan() {
                queue <- s.Text()
        }
        close(queue)
        wg.Wait()

        tokens := make([]Token, 0, m.Len())
        for _, token := range m.Keys() {
                if len(token) < 1 {
                        continue
                }
                v, _ := m.Get(token)
                tokens = append(tokens, Token{
                        Token: token,
                        Count: v.(int),
                })
        }
        sort.Slice(tokens, func(i, j int) bool {
                return tokens[i].Count > tokens[j].Count
        })

        // もし 調整するとしたら下位N%の 長文token とかをフィルタする TODO

        bfw := bufio.NewWriterSize(os.Stdout, 64*1024)
        for _, t := range tokens {
                bfw.Write([]byte(t.Token))
                bfw.Write(lf)
        }
        bfw.Flush()
}

これを go build -o /run/wakati main.go でビルドしておいて、tokenize するところを置き換えた

修正する箇所は RWKV-LM/RWKV-v4neo/src/dataset.py
改行を表現できていないので unique.add("\n") している

--- a/RWKV-v4neo/src/dataset.py
+++ b/RWKV-v4neo/src/dataset.py
@@ -83,7 +83,19 @@ class MyDataset(Dataset):
             else:
                 self.data = open(args.data_file, "r", encoding=args.data_type).read()
             rank_zero_info("Building token list...")
-            unique = sorted(list(set(self.data)))
+            import subprocess
+            unique = set([])
+            result = subprocess.run(
+                    "/run/wakati " + args.data_file,
+                    shell=True, check=True,
+                    stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                    universal_newlines=True,
+            )
+            for line in result.stdout.splitlines():
+                unique.add(line)
+
+            unique.add("\n")
             self.vocab_size = len(unique)
             # rank_zero_info()
             # for u in unique:

train.py のパラメータはかなり絞る必要があった、embdとctxは128でおおよそVRAM 15GB消費する

vocab_size=0
batch_size=1
layer_size=6
embd=128
ctx=128
python train.py \
  --load_model "" \
  --wandb "octu0---wandb" --proj_dir "out" --data_file "/path/to/ja.txt" \
  --data_type "utf-8" \
  --vocab_size ${vocab_size} \
  --ctx_len ${ctx} \
  --epoch_steps 5000 \
  --epoch_count 500 \
  --epoch_begin 0 \
  --epoch_save 5 \
  --micro_bsz ${batch_size} \
  --n_layer ${layer_size} \
  --n_embd ${embd} \
  --pre_ffn 0 --head_qk 0 --lr_init 8e-4 --lr_final 1e-5 --warmup_steps 0 --beta1 0.9 --beta2 0.99 --adam_eps 1e-8 \
  --accelerator gpu --devices 1 \
  --precision fp16 --strategy ddp_find_unused_parameters_false --grad_cp 0

今回は wandb にもログインしているので経過は wandb のdashboardから確認できる

ログはこんな感じ、パラメータも小さいのでサクサク進む

Login to wandb...
wandb: Currently logged in as: octu0. Use `wandb login --relogin` to force relogin
wandb: Tracking run with wandb version 0.15.0
wandb: Run data is saved locally in /path/to/RWKV-LM/RWKV-v4neo/wandb/run-20230430_221934-l2velu4n
wandb: Run `wandb offline` to turn off syncing.
wandb: Syncing run 0 ctx128 L6 D128 2023-04-30-22-18-55
...
Epoch 0:   0%|                                                 | 4/5000 [00:07<2:33:48,  1.85s/it, loss=14.30, lr=0.0008, REAL it/s=5.130, Kt/s=0.656]Epoch 0:  16%|███████▌                                       | 799/5000 [03:03<16:05,  4.35it/s, loss=5.460, lr=0.000799, REAL it/s=4.100, Kt/s=0.524]

学習中の nvidia-smi の状態

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 530.30.02              Driver Version: 511.69       CUDA Version: 11.6     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                  Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf            Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA RTX A5000 Laptop GPU     On | 00000000:01:00.0 Off |                  N/A |
| N/A   86C    P0               75W /  N/A|  15504MiB / 16384MiB |     75%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A     11953      C   /python3.8                                N/A      |
+---------------------------------------------------------------------------------------+

embd=128 ctx=128 と小さいのだが、vocabが多いと学習時には大きめのVRAMが必要そう。

とりあえず、おおよそ24時間学習させてみたので、 前回 と同じくいくつか出してみよう

embd,ctx が小さいためか、epoch は前回よりも進んでいた(といっても10 epochくらい)
学習の結果はこんな感じになっていた

wandb: Run history:
wandb: Gtokens ▁▁▁▁▂▂▂▂▂▃▃▃▃▃▃▄▄▄▄▄▅▅▅▅▅▅▆▆▆▆▆▇▇▇▇▇▇███
wandb:    kt/s ▇▁▇▇▁▆▇▇▆▆▁▇▆▇▇▆▃▄▇▇▇▆▆▇▆▇▇▆▄▃▄▇▄█▇▅▆▆▇▇
wandb:    loss ▅█▄▂▃█▄▃▂▂▅▃▅▃▂▃▃▇▆▃▁▃▅▅▂▃▅▃▄▄▅▃▃▄▄▄▄▂▃▂
wandb:      lr ███▇▇▇▇▇▆▆▆▆▅▅▅▅▅▅▄▄▄▄▄▃▃▃▃▃▃▃▂▂▂▂▂▂▁▁▁▁
wandb:
wandb: Run summary:
wandb: Gtokens 0.04006
wandb:    kt/s 0.52474
wandb:    loss 3.02557
wandb:      lr 0.00046

run.py は、 n_layzer, n_embd, ctx_len が小さくなっていること、vocab_size がとても大きくなっていることの違いがある
前回の top_p = 0.5 ではよく分からない日本語が多かったので今回は temperature = 1.0top_p = 0.15 にしている(top_p_newlineは0.20にさせてもらってる)

args.RUN_DEVICE = "cpu"
args.FLOAT_MODE = "bf16"

TOKEN_MODE = "char"
WORD_NAME = "./out/vocab"
UNKNOWN_CHAR = " "
vocab_size = 2329120

n_layer = 6
n_embd = 128
ctx_len = 128

NUM_TRIALS = 3
LENGTH_PER_TRIAL = 300

TEMPERATURE = 1.0
top_p = 0.15
top_p_newline = 0.20

まずは epoch 10

$ python run.py 

Using CPU. Loading ./out/rwkv-10...

RWKV_HEAD_QK_DIM 0 RWKV_JIT_ON 1

emb.weight                               bfloat16   cpu
blocks.0.ln1.weight                      bfloat16   cpu
blocks.0.ln1.bias                        bfloat16   cpu
blocks.0.ln2.weight                      bfloat16   cpu
...

Optimizing speed...

Loading tokenizer out/vocab...

Your prompt has 17 tokens.

--------------------------------------------------

吾輩は猫である、名前はまだない、このような、一部の場合は、山地の中でも「三十字」と呼ばれる。そのため、今は、小屋のことからも一部の「花」と呼ばれる。
                   」というものがある。
                 」と「一人のから」という。
                    
 あなたはこうした。
          
 あるから、あるから、あるからかない。」
   
     
  
 そうしたことは、あるが、このような、そうしたあるから、あるから、そうした。」
  
       
 
     
   
     
 そうしたことは、どうかからない。」
 と、「そうしたことは、あるか

--- preprocess 0.06s, generation 40.23s --------------------------------------------------

吾輩は猫である、名前はまだない、というものである。
        
    
 と、かなりのある。」
       
 ある。
  
       
 あなたは、あるから、どうかのようなものから、あるからかならない。
  
      
   
   
   
 そうした。
   
 
 あるから、あるから、どうかのうち、あるか、そうした」
  
      
 
   
    
  
 あるから、どうか、どうか。」
 かつかないから、どうかになる。
     
 
    
  
 あるから、あるから、そうした。」
     
     
   
 あなたのあるから、あるからかない。そうしたことから、そうしたことから、

--- preprocess 0.0s, generation 38.49s --------------------------------------------------

吾輩は猫である、名前はまだない、という。
      
   
   
 あるから、あるから、どうか、あるから、そうしたかならない。そうしたことから、あるから、あるいはそうした。
       
 
 あるから、あるから、そうしたあるから、そうしたものである。」
       
 
 あるから、どうかのうち、そうしたものから、そうしたいかなりない。そうしたあるから、どうかになるかからないから、このような」という意味である。そのため、自分の手法を見ると、あるが、そのうちのような意味である。
「おかげ」とは、「こうした人間の人々は、人がいたのであるから、あるからかならない。そうした人は、そうした人々の人がいたのである。」というこ

--- preprocess 0.0s, generation 38.49s --------------------------------------------------

うーーん。完全に parrot。
あと空白をめっちゃ推してくる。

次に epoch 30 これは半分くらいの学習が終わった時のもの

$ python run.py 

Using CPU. Loading ./out/rwkv-30...

RWKV_HEAD_QK_DIM 0 RWKV_JIT_ON 1

emb.weight                               bfloat16   cpu
blocks.0.ln1.weight                      bfloat16   cpu
blocks.0.ln1.bias                        bfloat16   cpu
blocks.0.ln2.weight                      bfloat16   cpu
...

--------------------------------------------------

吾輩は猫である、名前はまだない、その後、その名手として知られていた。
1999年(平成9年)には、2000年(平成10年)には、2000年(平成15年)には、本社の小田原にて、1999年(平成10年)には、1999年(平成9年)には、新型コロナウイルス感染病院にて、1999年(平成9年)には、日本国際空港にて、日本の鉄道館による日本の鉄道館にある日本国道200号線(現・東京都)による「東京都東京都市」が、1999年(平成10年)には、日本の国道200号線(現・日本市)が開通した。この路線は、1999年(平成10年)には、1999年(平成10年)には、1999年(平成10年)に は、1999年(平成10年)には、1999年(平成

--- preprocess 0.06s, generation 43.34s --------------------------------------------------

吾輩は猫である、名前はまだない、その他の生活を作っていた。
『さんの女』(かんのかん)は、2009年(平成15年)2月25日に発売された『日本のテレビアニメ』(2009年)で、2008年(平成15年)10月25日に発売された。2015年 (平成25年)10月25日には、『日本の女』(2015年)には、『日本の新聞』(2015年)の『新日本の映画『さんのつかい』(2015年)には、『三井の』(2015年)の『"The Bill"』(2015年)には、『"The Chite Stite Tele"』(2015年)には、『アンドレア』(2015年)の『アンドレア・アンド・ウェスト・アルバム』(2015年)では、『キャンパス』(201

--- preprocess 0.0s, generation 39.82s --------------------------------------------------

吾輩は猫である、名前はまだない、という意味である。この事情は、その中でも、このような「どうしているかを」という言葉をもつ。
「自身の友人のおもしろ、自身の人間の姿を見ているのか、どうしていかないか。」
「そのため、どういうのかかったから、どういうことは、このようなものか」
「その人間は、あの人間の中でも、そのままのいったのか。そのため、あの人間の中でも、そのような人間のようなものが、どういうことであったかをもっても、もしかもどういうのかもしれない。そのため、その人間は、人間の感情を見ているので、そのような人間の存在をしている。
「いいのから、そのような人間は、いいか。そのまま、どういうのかかっているか。」
「あのようなものか

--- preprocess 0.0s, generation 38.14s --------------------------------------------------

この辺りから片鱗が見えてきて、今まで使ってこなかったカッコ(「とか」『とか』)をよく使うようになってる気がする。あと年数も多様するようになった気がする。これはwikipediaの影響かな。

次に epoch 60、24時間くらい学習した最後の方のものになる

--------------------------------------------------

吾輩は猫である、名前はまだない、という。これは、それまでの1980年代になってからは、日本では、これは大学ではなく、日本では「新人」として「大学」という名称であった。
1980年代に入ると、日本の女性の人物としての活動を続けている。この年は『』に出演している。『日本の女』の中では、『大阪のための時代』では、『The Bellet You』のオープニングテーマとして、『』では『月刊コンビ「トーリー・リーグ」である。
『NETT III』(おおまかい きょう)は、1988年10月26日から2001年10月25日まで放送されていたテレビ朝日系列局である。2009年10月28日から2009年10月28日まで放 送されていた『SICE 

--- preprocess 0.09s, generation 41.61s --------------------------------------------------

吾輩は猫である、名前はまだない、という。
第一次世界大戦後、第一次世界大戦中に、戦後の小説『愛の時代』の『少年の生きた中で、「大人」というように「天文台」という名を出している。これは「新星」という名を持っている。これは「これは人間の名を「ただの」ということである。
2012年10月1日、『アイドルグループ』にて、「シングル「オールスター」というコンビで行われた。2014年10月1日に発売された『アイドルコントロール』では、2015年10月1日に『"" 』が発売された。
2014年10月1日、『CIC II』では、『』のオリジナルのキャラクターを務める。『』では、『スーパーマリオ』のオリジナルアルバム『HEAN CERTER 

--- preprocess 0.0s, generation 38.21s --------------------------------------------------

吾輩は猫である、名前はまだない、という。これは大坂によると、本作品の名を「平安の人」としている。これは、『天文学』の『』のようなことである。
『大阪大学生の学生』(たかかいきょう)は、日本の漫画家の大学である。『女性のみならし』である。『』では『日本書紀』に出演した『平成のある』では、『新人』の中で『あまりの時代』である。
『大学生の子』(たまかき たま)は、日本の『国家学者の日本史』において、日本の女性学者、学生の名を「女性」としている。『日本書紀』では『第1代『平成の中に、『月刊大学の学生』(2012年)である。『朝食は、人間の女』(2011年)、『新人』(2012年)、『大阪記念』(『天文字』)、『神奈川書店』(201

--- preprocess 0.0s, generation 37.38s --------------------------------------------------

top_p が小さいというのもあるかもだけど、若干それっぽさが増した...くらいかな
でも明らかに 『カッコ』を使うようになった

最後に スターシップ の要約、 前回と同じく top_p = 0.2 newline を 0.25 にしてる
前回同様に結果部分だけ

$ python run.py 

Using CPU. Loading ./out/rwkv-60...

RWKV_HEAD_QK_DIM 0 RWKV_JIT_ON 1

emb.weight                               bfloat16   cpu
blocks.0.ln1.weight                      bfloat16   cpu
blocks.0.ln1.bias                        bfloat16   cpu
blocks.0.ln2.weight                      bfloat16   cpu
blocks.0.ln2.bias                        bfloat16   cpu
blocks.0.ln0.weight                      bfloat16   cpu
blocks.0.ln0.bias                        bfloat16   cpu
....

--------------------------------------------------

要約すると、その時点では「大量の大型」という「エンジンの中には、タイガースのために、プレイヤーがまとめていた。これは、2011年10月1日に開始された。
『』(かんじょう)は、2012年10月25日に発売された『ザ・スーパースタジオ』("The Compless for Computer")である。2014年10月1日に発売された『アンド・イン・ザ・マンション』では、『"" 』では『』のようなことである。
1988年10月1日、『アイドル・アイドル』では、1986年10月1日に『エンターテインメント』が発売された。『The Compless and Compless of the Compless of

--- preprocess 1.09s, generation 39.56s --------------------------------------------------

要約すると、これはその後のインターネット上での通信を終了した。
2012年10月1日、「スーパースター」というインタビューで「プリンター」というような「アイドル」を開始した。また、「ストーリー」という「クリスマス」を用い ている。
1980年代に入ると、1988年には、インターネットのインタビューでは、「シーズンには1990年代のプロデューサーの大会」というスタジオでのデビューを果たした。その後、『スーパーファミコン』では、1990年代には『ストーリー』を『エンディング・アルバム』として、1998年に『』のリリースを行った。
『ニュース』は、2000年にアメリカ合衆国で開始された『』である。『リーグ イン

--- preprocess 0.0s, generation 39.34s --------------------------------------------------

要約すると、同年10月1日には「クリスマス・ブラックス」という名称が付けられた。
2011年10月1日、ニューヨーク・アンド・ジョン・マンションズによると、1980年代には「アメリカ・インディーズ」という名称が付けられている。また、この時点で は「エリック・シュート」という名称である。
インディアナ・マンションは、1980年代に入ると、マイケル・ディビションによって開始された。この時代には、マイク・シューズが「エイルズ・アンド・ファン・ストーリー」という名称であった。これは、「マイク・ディーン」という名称である。
1988年には、ファンタジー・アルバム『The Bellet the Serverss of

--- preprocess 0.0s, generation 39.34s --------------------------------------------------

うーむ。全然文章読んでない。これがctx 128の限界か...。

となると、VRAMに乗る vocab は 50277 に収めて学習させたいが、DataLoaderが1文字ずつなのでそこも改良していかないときびしい...。
読み込みも分かち書きするのは微妙だしなぁ...。ムズカシイ

Yusuke HataYusuke Hata

分かち書きのほうで 上位30%以下の長めのコンテキストは使われてないから削るようにした

package main

import (
        "bufio"
        "log"
        "os"
        "regexp"
        "sort"
        "strings"
        "sync"
        "unicode/utf8"

        "github.com/ikawaha/kagome-dict/ipa"
        "github.com/ikawaha/kagome/v2/tokenizer"
        "github.com/octu0/cmap"
)

var (
        empty     = " "
        lf        = []byte("\n")
        allalnum  = regexp.MustCompile(`^[0-9a-zA-Z _-]+$`)
        allsymbol = regexp.MustCompile(`^[<>{};:&@_\-+=\!\?#\/\\\[\]\^"'~\.\,\(\)\*\$%\s]+$`)
)

func increment(m *cmap.CMap, str string) {
        m.Upsert(str, func(exists bool, old any) any {
                if exists != true {
                        return 1
                }
                v := old.(int)
                return v + 1
        })
}

func tokenize(wg *sync.WaitGroup, t *tokenizer.Tokenizer, queue chan string, m *cmap.CMap) {
        defer wg.Done()

        for {
                select {
                case str, ok := <-queue:
                        if ok != true {
                                return
                        }
                        if allalnum.MatchString(str) || allsymbol.MatchString(str) {
                                increment(m, str)
                                for _, s := range strings.Split(str, "") {
                                        increment(m, s)
                                }
                                continue
                        }
                        for _, token := range t.Tokenize(str) {
                                increment(m, token.Surface)
                                // 1文字ずつ入れているのは、src/dataset.py で1文字ずつ読み込むため
                                // dix = [self.stoi[s] for s in data[i : i + req_len]]
                                for _, s := range strings.Split(token.Surface, "") {
                                        increment(m, s)
                                }
                        }
                }
        }
}

type Token struct {
        Token string
        Count int
}

func main() {
        f, err := os.Open(os.Args[1])
        if err != nil {
                log.Fatal(err)
        }
        defer f.Close()

        t, err := tokenizer.New(ipa.Dict(), tokenizer.OmitBosEos())
        if err != nil {
                log.Fatal(err)
        }

        m := cmap.New(
                cmap.WithSlabSize(4096),
        )
        queue := make(chan string, 0)
        wg := new(sync.WaitGroup)
        for i := 0; i < 32; i += 1 {
                wg.Add(1)
                go tokenize(wg, t, queue, m)
        }

        s := bufio.NewScanner(f)
        for s.Scan() {
                queue <- s.Text()
        }
        close(queue)
        wg.Wait()

        tokens := make([]Token, 0, m.Len())
        for _, token := range m.Keys() {
                if len(token) < 1 {
                        continue
                }
                v, _ := m.Get(token)
                tokens = append(tokens, Token{
                        Token: token,
                        Count: v.(int),
                })
        }
        sort.Slice(tokens, func(i, j int) bool {
                return tokens[i].Count > tokens[j].Count
        })

        // 30% 以下のtokenで、1文字以上かつCountが10以下のtokenは頻度が低いとみなして削る
        pos := int(float32(len(tokens)) * 0.3)
        for i := pos; i < len(tokens); i += 1 {
                if 1 < utf8.RuneCountInString(tokens[i].Token) && tokens[i].Count < 10 {
                        tokens = tokens[:i+copy(tokens[i:], tokens[i+1:])]
                        i -= 1
                }
        }

        bfw := bufio.NewWriterSize(os.Stdout, 128*1024)
        for _, t := range tokens {
                bfw.Write([]byte(t.Token))
                bfw.Write(lf)
        }
        bfw.Flush()
}

これで vocab size は 703989 まで減らせたため layer=24, embd=256, ctx=256 で学習させることができるようになった
(layer が増えてもそこまで VRAM の消費には直結しないようだったので 24 まで上げている)
この状態で VRAM が 14GB 程度だった

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 530.30.02              Driver Version: 511.69       CUDA Version: 11.6     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                  Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf            Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA RTX A5000 Laptop GPU     On | 00000000:01:00.0 Off |                  N/A |
| N/A   65C    P0               55W /  N/A|  14086MiB / 16384MiB |     44%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+

+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A     17235      C   /python3.8                                N/A      |
+---------------------------------------------------------------------------------------+

train に使ったパラメータ

vocab_size=0
batch_size=2
layer_size=24
embd=256
ctx=256
strategy="ddp_find_unused_parameters_false"
python train.py \
  --load_model "" \
  --wandb "octu0-rwkv" --proj_dir "out" --data_file "/path/to/ja.txt" \
  --data_type "utf-8" \
  --vocab_size ${vocab_size} \
  --ctx_len ${ctx} \
  --epoch_steps 5000 \
  --epoch_count 500 \
  --epoch_begin 0 \
  --epoch_save 5 \
  --micro_bsz ${batch_size} \
  --n_layer ${layer_size} \
  --n_embd ${embd} \
  --pre_ffn 0 --head_qk 0 --lr_init 8e-4 --lr_final 1e-5 --warmup_steps 0 --beta1 0.9 --beta2 0.99 --adam_eps 1e-8 \
  --accelerator gpu --devices 1 \
  --precision fp16 --strategy ${strategy} --grad_cp 0

学習時間は約20時間

(lrが0.0006を下回った程度)

前回わかったことで ctx_len が 256 程度では、文章の要約は不可能なので文字列の生成だけを試してみる
改めて top_p は 0.5 newline で 0.65 にして、自由に文章を生成させることに振って、vocabが増えたことやlayerが増えたことで何か実感できるか見てみる

$ python run.py 

Using CPU. Loading ./out/rwkv-30...

RWKV_HEAD_QK_DIM 0 RWKV_JIT_ON 1

emb.weight                               bfloat16   cpu
blocks.0.ln1.weight                      bfloat16   cpu
blocks.0.ln1.bias                        bfloat16   cpu
blocks.0.ln2.weight                      bfloat16   cpu
blocks.0.ln2.bias                        bfloat16   cpu
blocks.0.ln0.weight                      bfloat16   cpu
blocks.0.ln0.bias                        bfloat16   cpu
blocks.0.att.time_decay                  float32    cpu
blocks.0.att.time_first                  float32    cpu
blocks.0.att.time_mix_k                  bfloat16   cpu
blocks.0.att.time_mix_v                  bfloat16   cpu
blocks.0.att.time_mix_r                  bfloat16   cpu
blocks.0.att.key.weight                  bfloat16   cpu
blocks.0.att.value.weight                bfloat16   cpu
blocks.0.att.receptance.weight           bfloat16   cpu
blocks.0.att.output.weight               bfloat16   cpu
blocks.0.ffn.time_mix_k                  bfloat16   cpu
blocks.0.ffn.time_mix_r                  bfloat16   cpu
blocks.0.ffn.key.weight                  bfloat16   cpu
blocks.0.ffn.receptance.weight           bfloat16   cpu
blocks.0.ffn.value.weight                bfloat16   cpu
..............................................................................................................................................................................................................................................................................................................................................................................................................................
ln_out.weight                            bfloat16   cpu
ln_out.bias                              bfloat16   cpu
head.weight                              bfloat16   cpu

Optimizing speed...

--------------------------------------------------
吾輩は猫である、名前はまだない、と述べている。その名前はその後、この作品のような意味での作品であるという意味である。また、1953年に出版された雑誌『星』では、この作品の編集を担当している。
1955年に『スーパースターズ』("Server of Show")が発売された。この時期には、シリーズがスタートしたが、スタジオ・アルバム『"Standers"』(1959年)を発表した。この時期のスタジオ・アルバムの他にも、『"" 』(1950年)や『"" 』(1952年)などがある。
この頃、ハート・アーヴィングは、スタジオ・アルバム『"" 』(1952年)や、『"" 』(1953年)などの作品をリリースした。この曲は1953年に

--- preprocess 0.0s, generation 18.55s --------------------------------------------------

吾輩は猫である、名前はまだない、言葉のようなよくない日常ができていることを考えた。アイデアを書いていたところに、ある男性が言葉を入れると、そのアイデアはまさに、アイデアを記述した。そのため、アイデアは、雑談中に、「俺は知っているから」と答えている。
ADPは、彼らが、ビジネスマンであることができたときのことである。彼は、このエッセイを出版すると、「私は、この雑誌を高く評価している」と述べている。彼ら は「無く、俺たちが彼を私たちにその言葉を知っているのを描いてくれると思います」と述べた。「私は、『MUMIDO』をしているアイデアは、「あなたが私たちのユーモアを取り巻くことはないですか」と歌い、また「ストーリーが作り出されている

--- preprocess 0.0s, generation 19.2s --------------------------------------------------

吾輩は猫である、名前はまだない、と思っていた。
 そのときは、なんという意味で、彼の頭を、またまただの頭をしているのである。
 彼は、やがて、とうとう、たった一度、また、その中にいると、たった一人の少年が、また、彼の頭をとった。
 その時、
 その間、大きな男は、あたかも、その女をおかしていた。
 と、ただ一人の男が、また、また、そのときに、おい、いいと思った。
 彼は、まだ、彼の顔を、そのままでは、まだ大きな声をしていた。
 彼は、この小さな声をした。
 と、それは、いまだに、彼は、その声をかけた。
 彼は、ただ、彼の言葉を、いいと思った。
 それは、まだ、気をつけている。それは、私の頭の中に、その上にいるときに、いつかの

--- preprocess 0.0s, generation 19.31s --------------------------------------------------

ctxが前回より増えているので、若干だけど前後の文章の意味合いが通るようになった気もする
が、やっぱりうーーーん。の域を超えていない...

ここまでを少しまとめると

  • 日本語だけのベースモデルを使ってるのでそこそこ読めるものを出せるようにはなった
  • ただ ctx_len が長くないとまともに文章を読んでくれない。たぶん一番重要。
  • vocab が増えると文章のバリエーションが少し増える( とか ,, をよく使うようになってくる)、けど日本語っぽさにあまり寄与してる感じはしない(教師なしの学習だからそういうものかも)
  • 学習時間が増えると日本語っぽさは増す、けど正しい日本語にするには ctx_len と embd を大きくしてもっと学習する必要がありそう(大きなVRAMが必要になってくる)

って感じかなぁ
愚直に ctx_len や embd を大きくして長時間学習がRWKVでの正攻法なのかな...
tokenizeに分かち書きをした結果を使っても DataLoader の課題もあるからもう少し進化を待つのも良さそう

このスクラップは2023/05/02にクローズされました