Skip to content

Commit 8f877a7

Browse files
author
neuropilot-captain
committed
add oss model
1 parent 7587ad7 commit 8f877a7

File tree

15 files changed

+1714
-0
lines changed

15 files changed

+1714
-0
lines changed

examples/mediatek/CMakeLists.txt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,44 @@ if(${ANDROID})
9393
${_common_compile_options}
9494
)
9595

96+
set(_mtk_oss_executor_runner__srcs ${_executor_runner__srcs})
97+
list(
98+
TRANSFORM
99+
_mtk_oss_executor_runner__srcs
100+
PREPEND
101+
"${EXECUTORCH_SOURCE_DIR}/"
102+
)
103+
list(
104+
FILTER
105+
_mtk_oss_executor_runner__srcs
106+
EXCLUDE REGEX
107+
".*executor_runner.cpp$"
108+
)
109+
list(
110+
PREPEND
111+
_mtk_oss_executor_runner__srcs
112+
${CMAKE_CURRENT_LIST_DIR}/executor_runner/mtk_oss_executor_runner.cpp
113+
)
114+
115+
add_executable(mtk_oss_executor_runner ${_mtk_oss_executor_runner__srcs})
116+
117+
target_include_directories(mtk_oss_executor_runner
118+
PUBLIC
119+
${_common_include_directories}
120+
${EXECUTORCH_ROOT}/cmake-android-out/third-party/gflags/include
121+
)
122+
123+
target_link_libraries(mtk_oss_executor_runner
124+
${_executor_runner_libs}
125+
executorch
126+
neuron_backend
127+
gflags
128+
)
129+
target_compile_options(mtk_oss_executor_runner
130+
PUBLIC
131+
${_common_compile_options}
132+
)
133+
96134
set(_mtk_llama_executor_runner__srcs ${_mtk_executor_runner__srcs})
97135
list(
98136
FILTER

examples/mediatek/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ examples/mediatek
99
├── preformatter_templates # Model specific prompt preformatter templates
1010
├── prompts # Calibration Prompts
1111
├── tokenizers_ # Model tokenizer scripts
12+
├── oss_utils # Utils for oss models
13+
├── eval_utils # Utils for eval oss models
1214
├── model_export_scripts # Model specifc export scripts
1315
├── models # Model definitions
1416
├── llm_models # LLM model definitions
@@ -44,6 +46,7 @@ pip3 install mtk_converter-8.8.0.dev20240723+public.d1467db9-cp310-cp310-manylin
4446
```
4547

4648
## AoT Flow
49+
### llama
4750
##### Note: Verify that localhost connection is available before running AoT Flow
4851
1. Exporting Models to `.pte`
4952
- In the `examples/mediatek directory`, run:
@@ -72,6 +75,14 @@ source shell_scripts/export_llama.sh <model_name> <num_chunks> <prompt_num_token
7275
- eg. For `llama3-8B-instruct`, embedding bin generated in `examples/mediatek/models/llm_models/weights/llama3-8B-instruct/`
7376
- AoT flow will take roughly 2.5 hours (114GB RAM for `num_chunks=4`) to complete (Results will vary by device/hardware configurations)
7477

78+
### oss
79+
1. Exporting Model to `.pte`
80+
```bash
81+
bash shell_scripts/export_oss.sh <model_name>
82+
```
83+
- Argument Options:
84+
- `model_name`: deeplabv3/edsr/inceptionv3/inceptionv4/mobilenetv2/mobilenetv3/resnet18/resnet50
85+
7586
# Runtime
7687
## Supported Chips
7788

@@ -100,6 +111,13 @@ adb push <MODEL_NAME>.pte <PHONE_PATH, e.g. /data/local/tmp>
100111

101112
Make sure to replace `<MODEL_NAME>` with the actual name of your model file. And, replace the `<PHONE_PATH>` with the desired detination on the device.
102113

114+
##### Note: For oss models, please push additional files to your Android device
115+
```bash
116+
adb push mtk_oss_executor_runner <PHONE_PATH, e.g. /data/local/tmp>
117+
adb push input_list.txt <PHONE_PATH, e.g. /data/local/tmp>
118+
for i in input*bin; do adb push "$i" <PHONE_PATH, e.g. /data/local/tmp>; done;
119+
```
120+
103121
### Executing the Model
104122

105123
Execute the model on your Android device by running:
@@ -111,3 +129,22 @@ adb shell "/data/local/tmp/mtk_executor_runner --model_path /data/local/tmp/<MOD
111129
In the command above, replace `<MODEL_NAME>` with the name of your model file and `<ITER_TIMES>` with the desired number of iterations to run the model.
112130

113131
##### Note: For llama models, please use `mtk_llama_executor_runner`. Refer to `examples/mediatek/executor_runner/run_llama3_sample.sh` for reference.
132+
##### Note: For oss models, please use `mtk_oss_executor_runner`.
133+
```bash
134+
adb shell "/data/local/tmp/mtk_oss_executor_runner --model_path /data/local/tmp/<MODEL_NAME>.pte --input_list /data/local/tmp/input_list.txt --output_folder /data/local/tmp/output_<MODEL_NAME>"
135+
adb pull "/data/local/tmp/output_<MODEL_NAME> ./"
136+
```
137+
138+
### Check oss result on PC
139+
```bash
140+
python3 eval_utils/eval_oss_result.py --eval_type <eval_type> --target_f <golden_folder> --output_f <prediction_folder>
141+
```
142+
For example:
143+
```
144+
python3 eval_utils/eval_oss_result.py --eval_type piq --target_f edsr --output_f output_edsr
145+
```
146+
- Argument Options:
147+
- `eval_type`: topk/piq/segmentation
148+
- `target_f`: folder contain golden data files. file name is `golden_<data_idx>_0.bin`
149+
- `output_f`: folder contain model output data files. file name is `output_<data_idx>_0.bin`
150+
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Copyright (c) MediaTek Inc.
2+
# All rights reserved
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
import os
8+
from typing import Optional
9+
import numpy as np
10+
11+
import torch
12+
from executorch import exir
13+
from executorch.backends.mediatek import NeuropilotPartitioner, NeuropilotQuantizer, Precision
14+
from torch.ao.quantization.quantize_pt2e import convert_pt2e, prepare_pt2e
15+
16+
17+
def build_executorch_binary(
18+
model,
19+
inputs,
20+
file_name,
21+
dataset,
22+
quant_dtype: Optional[Precision] = None,
23+
):
24+
if quant_dtype is not None:
25+
quantizer = NeuropilotQuantizer()
26+
quantizer.setup_precision(quant_dtype)
27+
if quant_dtype not in Precision:
28+
raise AssertionError(f"No support for Precision {quant_dtype}.")
29+
30+
captured_model = torch._export.capture_pre_autograd_graph(model, inputs)
31+
annotated_model = prepare_pt2e(captured_model, quantizer)
32+
print("Quantizing the model...")
33+
# calibration
34+
for data in dataset:
35+
annotated_model(*data)
36+
quantized_model = convert_pt2e(annotated_model, fold_quantize=False)
37+
aten_dialect = torch.export.export(quantized_model, inputs)
38+
else:
39+
aten_dialect = torch.export.export(model, inputs)
40+
41+
from executorch.exir.program._program import to_edge_transform_and_lower
42+
43+
edge_compile_config = exir.EdgeCompileConfig(_check_ir_validity=False)
44+
# skipped op names are used for deeplabV3 model
45+
neuro_partitioner = NeuropilotPartitioner([], op_names_to_skip={'aten_convolution_default_106', 'aten_convolution_default_107'})
46+
edge_prog = to_edge_transform_and_lower(
47+
aten_dialect,
48+
compile_config=edge_compile_config,
49+
partitioner=[neuro_partitioner],
50+
)
51+
52+
exec_prog = edge_prog.to_executorch(
53+
config=exir.ExecutorchBackendConfig(extract_constant_segment=False)
54+
)
55+
with open(f"{file_name}.pte", "wb") as file:
56+
file.write(exec_prog.buffer)
57+
58+
59+
def make_output_dir(path: str):
60+
if os.path.exists(path):
61+
for f in os.listdir(path):
62+
os.remove(os.path.join(path, f))
63+
os.removedirs(path)
64+
os.makedirs(path)
65+
66+
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# Copyright (c) MediaTek Inc.
2+
# All rights reserved
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
7+
import sys
8+
import os
9+
import piq
10+
import numpy as np
11+
import argparse
12+
import torch
13+
import json
14+
15+
16+
def check_data(target_f, predict_f):
17+
target_files = os.listdir(target_f)
18+
predict_files = os.listdir(predict_f)
19+
if len(target_files) != len(predict_files):
20+
raise RuntimeError("Data number in target folder and prediction folder must be same")
21+
22+
predict_set = set(predict_files)
23+
for f in target_files:
24+
# target file naming rule is golden_sampleId_outId.bin
25+
# predict file naming rule is output_sampleId_outId.bin
26+
pred_name = f.replace("golden", "output")
27+
try:
28+
predict_set.remove(pred_name)
29+
except KeyError:
30+
raise RuntimeError(f"Cannot find {pred_name} in {predict_f}")
31+
32+
if predict_set:
33+
target_name = next(predict_set).replace("output", "golden")
34+
raise RuntimeError(f"Cannot find {target_name} in {target_f}")
35+
36+
37+
def eval_topk(target_f, predict_f):
38+
def solve(prob, target, k):
39+
_, indices = torch.topk(prob, k=k, sorted=True)
40+
golden = torch.reshape(target, [-1, 1])
41+
correct = (golden == indices)
42+
if torch.any(correct):
43+
return 1
44+
else:
45+
return 0
46+
47+
target_files = os.listdir(target_f)
48+
49+
cnt10 = 0
50+
cnt50 = 0
51+
for target_name in target_files:
52+
pred_name = target_name.replace("golden", "output")
53+
54+
pred_npy = np.fromfile(os.path.join(predict_f, pred_name), dtype=np.float32)
55+
target_npy = np.fromfile(os.path.join(target_f, target_name), dtype=np.int64)[0]
56+
cnt10 += solve(torch.from_numpy(pred_npy), torch.from_numpy(target_npy), 10)
57+
cnt50 += solve(torch.from_numpy(pred_npy), torch.from_numpy(target_npy), 50)
58+
59+
print("Top10 acc:", cnt10 * 100.0 / len(target_files))
60+
print("Top50 acc:", cnt50 * 100.0 / len(target_files))
61+
62+
63+
def eval_piq(target_f, predict_f):
64+
target_files = os.listdir(target_f)
65+
66+
psnr_list = []
67+
ssim_list = []
68+
for target_name in target_files:
69+
pred_name = target_name.replace("golden", "output")
70+
hr = np.fromfile(os.path.join(target_f, target_name), dtype=np.float32)
71+
hr = hr.reshape((1,448,448,3))
72+
hr = np.moveaxis(hr, 3, 1)
73+
hr = torch.from_numpy(hr)
74+
75+
sr = np.fromfile(os.path.join(predict_f, pred_name), dtype=np.float32)
76+
sr = sr.reshape((1,448,448,3))
77+
sr = np.moveaxis(sr, 3, 1)
78+
sr = torch.from_numpy(sr).clamp(0, 1)
79+
80+
psnr_list.append(piq.psnr(hr, sr))
81+
ssim_list.append(piq.ssim(hr, sr))
82+
83+
avg_psnr = sum(psnr_list).item() / len(psnr_list)
84+
avg_ssim = sum(ssim_list).item() / len(ssim_list)
85+
86+
print(f"Avg of PSNR is: {avg_psnr}")
87+
print(f"Avg of SSIM is: {avg_ssim}")
88+
89+
90+
def eval_segmentation(target_f, predict_f):
91+
classes = [
92+
"Backround",
93+
"Aeroplane",
94+
"Bicycle",
95+
"Bird",
96+
"Boat",
97+
"Bottle",
98+
"Bus",
99+
"Car",
100+
"Cat",
101+
"Chair",
102+
"Cow",
103+
"DiningTable",
104+
"Dog",
105+
"Horse",
106+
"MotorBike",
107+
"Person",
108+
"PottedPlant",
109+
"Sheep",
110+
"Sofa",
111+
"Train",
112+
"TvMonitor",
113+
]
114+
115+
target_files = os.listdir(target_f)
116+
117+
def make_confusion(goldens, predictions, num_classes):
118+
def histogram(golden, predict):
119+
mask = golden < num_classes
120+
hist = np.bincount(
121+
num_classes * golden[mask].astype(int) + predict[mask],
122+
minlength=num_classes**2,
123+
).reshape(num_classes, num_classes)
124+
return hist
125+
126+
confusion = np.zeros((num_classes, num_classes))
127+
for g, p in zip(goldens, predictions):
128+
confusion += histogram(g.flatten(), p.flatten())
129+
130+
return confusion
131+
132+
pred_list = []
133+
target_list = []
134+
for target_name in target_files:
135+
pred_name = target_name.replace("golden", "output")
136+
target_npy = np.fromfile(os.path.join(target_f, target_name), dtype=np.uint8)
137+
target_npy = target_npy.reshape((224, 224))
138+
target_list.append(target_npy)
139+
140+
pred_npy = np.fromfile(os.path.join(predict_f, pred_name), dtype=np.float32)
141+
pred_npy = pred_npy.reshape((224, 224, len(classes)))
142+
pred_npy = pred_npy.argmax(2).astype(np.uint8)
143+
pred_list.append(pred_npy)
144+
145+
eps = 1e-6
146+
confusion = make_confusion(target_list, pred_list, len(classes))
147+
148+
pa = np.diag(confusion).sum() / (confusion.sum() + eps)
149+
mpa = np.mean(np.diag(confusion) / (confusion.sum(axis=1) + eps))
150+
iou = np.diag(confusion) / (
151+
confusion.sum(axis=1) + confusion.sum(axis=0) - np.diag(confusion) + eps
152+
)
153+
miou = np.mean(iou)
154+
cls_iou = dict(zip(classes, iou))
155+
156+
print(f"PA : {pa}")
157+
print(f"MPA : {mpa}")
158+
print(f"MIoU : {miou}")
159+
print(f"CIoU : \n{json.dumps(cls_iou, indent=2)}")
160+
161+
162+
if __name__ == "__main__":
163+
parser = argparse.ArgumentParser()
164+
165+
parser.add_argument(
166+
"--target_f",
167+
help="folder of target data",
168+
type=str,
169+
required=True,
170+
)
171+
172+
parser.add_argument(
173+
"--out_f",
174+
help="folder of model prediction data",
175+
type=str,
176+
required=True,
177+
)
178+
179+
parser.add_argument(
180+
"--eval_type",
181+
help="Choose eval type from: topk, piq, segmentation",
182+
type=str,
183+
choices=["topk", "piq", "segmentation"],
184+
required=True,
185+
)
186+
187+
args = parser.parse_args()
188+
189+
check_data(args.target_f, args.out_f)
190+
191+
if args.eval_type == 'topk':
192+
eval_topk(args.target_f, args.out_f)
193+
elif args.eval_type == 'piq':
194+
eval_piq(args.target_f, args.out_f)
195+
elif args.eval_type == 'segmentation':
196+
eval_segmentation(args.target_f, args.out_f)
197+
198+

0 commit comments

Comments
 (0)