mlboydaisuke commited on
Commit
c5f79d9
·
verified ·
1 Parent(s): eb96844

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +107 -0
README.md ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ library_name: litert
4
+ pipeline_tag: image-classification
5
+ tags:
6
+ - litert
7
+ - tflite
8
+ - android
9
+ - on-device
10
+ - gpu
11
+ - rwkv
12
+ - vision-rwkv
13
+ - image-classification
14
+ ---
15
+
16
+ # Vision-RWKV (VRWKV-S) — ImageNet classification on LiteRT GPU
17
+
18
+ The first **RWKV-style vision backbone running its full forward pass on the LiteRT
19
+ `CompiledModel` GPU delegate** (no CPU fallback). [Vision-RWKV](https://github.com/OpenGVLab/Vision-RWKV)
20
+ (ICLR 2025, Apache-2.0) replaces softmax self-attention with a **bidirectional WKV**
21
+ linear-attention scan — the vision counterpart of the RWKV language model. This is the
22
+ VRWKV-S ImageNet-1K classifier (80.1% top-1); it is the vision companion to
23
+ [RWKV-7-World-0.1B-LiteRT](https://huggingface.co/litert-community/RWKV-7-World-0.1B-LiteRT).
24
+
25
+ - **Architecture:** VRWKV-S — 12 blocks, dim 384, patch 16, 14×14 = 196 tokens.
26
+ - **Weights:** [OpenGVLab/Vision-RWKV](https://huggingface.co/OpenGVLab/Vision-RWKV) · Apache-2.0.
27
+ - **Size:** 48 MB (fp16).
28
+
29
+ ![Vision-RWKV on-device classification](hero.png)
30
+
31
+ *Top-5 ImageNet predictions on a Pixel 8a; the whole VRWKV-S backbone runs on the GPU.*
32
+
33
+ ## I/O
34
+
35
+ - **Inputs:** `image[1,3,224,224]` NCHW (ImageNet-normalized, resize-256 → center-crop-224)
36
+ and `dist[1,1,196,196]`, the constant token-distance matrix `dist[t,i] = |t−i|`.
37
+ - **Output:** `logits[1,1000]` (ImageNet-1K).
38
+
39
+ ## GPU conversion
40
+
41
+ VRWKV's token mixer is a CUDA `bi_wkv` kernel. Because the token count is fixed (196),
42
+ the bidirectional WKV is exactly a **per-channel decay-biased attention**:
43
+
44
+ ```
45
+ L[c,t,i] = k[c,i] − (spatial_decay[c]/T)·|t−i| + (spatial_first[c]/T)·δ(t,i)
46
+ y[c,t] = Σ_i softmax_i(L[c,t,·]) · v[c,i]
47
+ ```
48
+
49
+ — C independent `[T,T]` attention matrices → plain 4D `softmax` + `matmul`, **no
50
+ sequential scan**. Two things make it GPU-clean and small:
51
+
52
+ - The `[C,T,T]` decay bias `w·dist` (frozen `w` × constant `dist`) would be
53
+ **const-folded** into a 59 MB-per-block flatbuffer constant — an unshippable 1.5 GB
54
+ model that fp16 cannot shrink. Feeding the token-distance matrix as a **runtime input**
55
+ (`eye = relu(1 − dist)`) keeps the bias a transient live tensor → 48 MB.
56
+ - VRWKV-S is **post-norm** (norm after the mixer); the LayerScale gamma is baked into
57
+ the following norm's affine params; q-shift is pad+slice+concat (≤4D).
58
+
59
+ Pixel 8a: **1371/1371 nodes on the GPU delegate, 1 partition**, ~28 ms/inference (fp16).
60
+ Device fp16 top-1 matches desktop fp32 (bundled Samoyed sample: `Samoyed` 79%, top-5
61
+ identical; logits corr 0.9989). The Bi-WKV re-authoring is oracle-exact (matrix form vs
62
+ the explicit bidirectional sum, corr 1.0000000).
63
+
64
+ ## Minimal usage
65
+
66
+ ### Kotlin (Android, LiteRT CompiledModel GPU)
67
+
68
+ ```kotlin
69
+ val model = CompiledModel.create(context.assets, "vrwkv_s_fp16.tflite",
70
+ CompiledModel.Options(Accelerator.GPU), null)
71
+ val inputs = model.createInputBuffers()
72
+ val outputs = model.createOutputBuffers()
73
+
74
+ inputs[0].writeFloat(imageNchw) // [1,3,224,224] ImageNet-normalized
75
+ inputs[1].writeFloat(dist) // [1,1,196,196], dist[t*196+i] = |t-i|
76
+ model.run(inputs, outputs)
77
+ val logits = outputs[0].readFloat() // [1000] -> softmax + argmax
78
+ ```
79
+
80
+ ### Python (LiteRT CompiledModel API)
81
+
82
+ ```python
83
+ import numpy as np
84
+ from ai_edge_litert.compiled_model import CompiledModel
85
+
86
+ model = CompiledModel.from_file("vrwkv_s_fp16.tflite")
87
+ inputs = model.create_input_buffers(0)
88
+ outputs = model.create_output_buffers(0)
89
+
90
+ idx = np.arange(196, dtype=np.float32)
91
+ dist = np.abs(idx[:, None] - idx[None, :]).reshape(1, 1, 196, 196)
92
+ inputs[0].write(np.ascontiguousarray(image, np.float32)) # [1,3,224,224]
93
+ inputs[1].write(np.ascontiguousarray(dist, np.float32))
94
+ model.run_by_index(0, inputs, outputs)
95
+ logits = outputs[0].read(1000, np.float32) # argmax -> class
96
+ ```
97
+
98
+ ## Files
99
+
100
+ | File | Role |
101
+ |------|------|
102
+ | `vrwkv_s_fp16.tflite` | VRWKV-S step graph (fp16), 48 MB |
103
+ | `imagenet_classes.txt` | 1000 ImageNet-1K labels |
104
+
105
+ ## License
106
+
107
+ Apache-2.0 (Vision-RWKV / OpenGVLab). Converted with litert-torch.