智能问答是自然语言处理(NLP) 中很重要的一个领域,此应用的功能是在段落或文章中找到所需的答案。本文主要介绍一个基于高通Snapdragon Neural Processing Engine SDK和ICLR 2020 Electra Transformer模型的智能问答Android应用程序,该应用的所有源代码都可以在https://github.com/quic/qidk/tree/master/Solutions/NLPSolution1-QuestionAnswering 上获得。
使用模型为Electra-small:https://huggingface.co/mrm8488/electra-small-finetuned-squadv2,是一款小型、高效、方便的Transformer模型,在SQUAD v2.0数据集上进行了微调,用于智能问答。我们将展示如何在Snapdragon 8 Gen 2的手机上高效转换、部署和加速Electra-small模型,来执行设备上的智能问答应用。
相关步骤参考https://developer.qualcomm.com/sites/default/files/docs/snpe/setup.html
(上面提到的Python软件包版本和Android Studio版本只是一个建议,不是硬性要求。请在Python 3.6虚拟环境中安装SDK依赖项,在本教程的开发过程中,AI SDK推荐Python 3.6版本,可能会随着未来SDK版本的变化而变化。请参阅SDK发行说明。)
python scripts/qa_model_gen.py
source
snpe-tensorflow-to-dlc -i frozen_models/electra_small_squad2.pb -d input_ids 1,384 -d attention_mask 1,384 -d token_type_ids 1,384 --out_node Identity --out_node Identity_1 -o frozen_models/electra_small_squad2.dlc
其中“input_ids,attention\ymask,token_type_ids”是模型的输入,“Identity,Identity_1”是其输出。
该命令将Tensorflow frozen graph转换为DLC格式,DSP、GPU和CPU的加速器可以理解该格式以推理运行。DLC将保存在“frozen_models”目录中,名称为electra_small_squad2.DLC。
(如果您使用不同的Tensorflow版本来生成PB文件,则可能是输出层名称发生了更改。请使用Netron查看器或任何其他可视化工具通过可视化图形进行一次检查)
snpe-dlc-graph-prepare --input_dlc frozen_models/electra_small_squad2.dlc --use_float_io --htp_archs v73 --set_output_tensors Identity:0,Identity_1:0
生成的DLC将保存在frozen_models目录中,名称为electra_small_squad2_cached.DLC。
如果您想跳过以下可选的第2节和第3节的性能评测,那么,可以跳到第4节。直接使用Android Studio构建并运行
mkdir -p validation_set
cd validation_set/
python ../scripts/generate_representative_dataset_squadv2.py mrm8488/electra-small-finetuned-squadv2 50 384
该脚本使用Golden Answers从SQUAD-v2验证数据集中保存50个样本,其中每个输入的序列长度为384。
如果您在终端上遇到 “UnicodeEncodeError”提示
import sys, io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
然后在python脚本中添加/取消注释上面的代码段。
python ../scripts/gen_raw_list.py 50
该脚本生成两个文本文件tf_raw_list.txt和snpe_raw_list.txt,其中包含输入文件的位置,这将有助于运行推理。
python ../scripts/batch_tf_inf.py ../frozen_models/electra_small_squad2.pb tf_raw_list.txt input_ids:0,attention_mask:0,token_type_ids:0 Identity:0,Identity_1:0
此脚本在“electra_small_squad2.pb”上运行推理,并将结果存储在tf_out目录中。请仅从validation_set目录运行此推理脚本,因为tf_raw_list.txt包含相对路径。
python ../scripts/logits_to_F1_score.py --model_name mrm8488/electra-small-finetuned-squadv2 --sequence_len 384 --logits_dir tf_out --golden_answers_dir golden_answers --top_k 1
此脚本评估模型输出并生成F1和EM(Exact Match score)。输出如下:
Metrics report
===============================================================
exact = 68.0
f1 = 71.33333333333334
total = 50
HasAns_exact = 71.42857142857143
HasAns_f1 = 77.38095238095238
HasAns_total = 28
NoAns_exact = 63.63636363636363
NoAns_f1 = 63.63636363636363
NoAns_total = 22
best_exact = 68.0
best_exact_thresh = 0.0
best_f1 = 71.33333333333333
best_f1_thresh = 0.0
NOTE:这是使用“generate_erepresentative _dataset_squadv2.py”脚本生成的SQUAD-V2数据集的50个样本的结果
python $SNPE_ROOT/benchmarks/snpe_bench.py -c dsp_accuracy_test.json -t android-aarch64 -p burst -z
该命令将在连接的设备上推送DLC、SDK assets和Input artifacts,并在DSP运行时自动运行推理。
adb pull /data/local/tmp/8550snpeQA/dOut/output snpe_dsp_out
此命令将提取snpe_dsp_out目录中的所有推理输出。
tree snpe_dsp_out
The directory structure will be like :
snpe_dsp_out/Result_0/Identity:0.raw
snpe_dsp_out/Result_0/Identity_1:0.raw
snpe_dsp_out/Result_1/Identity:0.raw
snpe_dsp_out/Result_1/Identity_1:0.raw
...
python ../scripts/logits_to_F1_score.py --model_name mrm8488/electra-small-finetuned-squadv2 --sequence_len 384 --logits_dir snpe_dsp_out --golden_answers_dir golden_answers --top_k 1
此脚本评估模型输出并生成F1和EM(Exact Match)分数。输出将与上面提到的TF Frozen graph相同:
Metrics report
===============================================================
exact = 68.0
f1 = 71.33333333333334
total = 50
python $SNPE_ROOT/benchmarks/snpe_bench.py -c ondevice_perf_test.json -t android-aarch64 -p burst -z
该命令将在连接的设备上推送DLC、SDK assets和Input artifacts,并在DSP、GPU_FP16和CPU运行时自动运行推理。
完成后,基准测试结果将存储在:dOut/results/latest_results/beachmark_stats_dOut.csv请参阅csv文件中的“总推断时间”字段,该字段显示模型执行时间(以微秒(us)为单位)
性能结果(越低越好):
DSP_FP16 |
GPU_FP16 |
CPU_FP32 |
|
Inference time (ms) |
99.302 ms |
574.111 ms |
885.543 ms |
注意:性能可能会根据SDK版本和device meta build而变化。
确保已设置SNPE_ROOT env变量
./scripts/fetch_snpe_assets.sh
在打开项目时,Android Studio可能会要求您下载构建AI SDK C++Native API所需的Android NDK。成功完成项目同步和构建过程后,按播放图标在连接的设备上安装并运行应用程序。
如果构建过程因libSNPE.so而失败,则出现重复错误,请将其路径从“jniLibs”更改为“cmakeLibs”,如下所示:在QuestionAnswering/bert/src/main/cpp/CMakeList.txt中的target_link_libraries开启${CMAKE_CURRENT_SOURCE_DIR}//cmakeLibs/arm64-v8a/libSNPE.so,并注释“jniLibs”目录中的libSNPE.so。
如果Android Studio无法检测到设备,或者设备位于远程位置并将APK复制到当前目录:
cp ./QuestionAnswering/app/build/outputs/apk/debug/app-debug.apk ./qa-app.apk
adb install -r -t qa-app.apk
安装应用程序后,如果crash,请尝试从QIDK设备收集日志。
要收集日志,请运行以下命令。
打开应用程序时,如果未检测到未签名或已签名的DSP运行时,请使用关键字 DSP搜索logcat日志以查找FastRPC错误。由于某些Android版本中的SE Linux安全策略,可能无法检测到DSP运行时。请尝试以下命令来设置允许的SE Linux策略。
以下是基本的Android智能问答应用程序操作。
演示视频和性能细节如下所示:
作者:戴忠忠 (Zhongzhong Dai),高通工程师