Android应用能否同时运行输入张量不同的YAMNet与speech音频分类TFLite模型?
双模型输入不兼容的解决办法
1. 给两个模型分别创建独立的分类器实例
原Demo里应该是共用了一个AudioClassifier类,你得给YAMNet和speech模型各搞一个独立的实例,分别加载对应的模型文件,各自初始化输入输出的配置。比如:
// 初始化YAMNet分类器 AudioClassifier yamNetClassifier = AudioClassifier.createFromFile(this, "YAMNet.tflite"); // 初始化语音指令分类器 AudioClassifier speechClassifier = AudioClassifier.createFromFile(this, "speech.tflite");
记得让AudioClassifier类暴露获取输入要求的方法,比如getRequiredInputLength(),这样后面能明确每个模型需要多少采样点的音频。
2. 调整音频采集和预处理逻辑
两个模型需要的音频长度不一样,不能用同一批原始音频直接喂,得这么处理:
- 统一采样率:先确认两个模型的采样率(YAMNet一般是16kHz,speech模型如果是44.1kHz的话,得把采集到的音频转成对应采样率)。
- 缓存切片音频:
- 给YAMNet整个固定长度的缓存队列,每次采集到新音频就追加进去,缓存够16000个采样点时,取最后16000个作为输入。
- speech模型同理,维护一个44032长度的缓存,每次取最后44032个采样点。
- 并行预处理:把原始音频分别处理成两个模型需要的格式(比如归一化、转浮点数组),这部分放在子线程并行执行,避免阻塞主线程。
3. 分开执行两个模型的推理
原Demo可能在同一个线程里做推理,现在把两个模型的推理放到独立线程(或者用ExecutorService)里并行跑,互不干扰。比如:
ExecutorService executor = Executors.newFixedThreadPool(2); // 执行YAMNet推理任务 executor.submit(() -> { float[] yamNetInput = prepareYamNetInput(rawAudioData); List<ClassificationResult> yamNetResults = yamNetClassifier.classify(yamNetInput); // 判断是否检测到语音 boolean isSpeech = checkSpeech(yamNetResults); // 更新UI切回主线程 runOnUiThread(() -> updateYamNetStatus(isSpeech)); }); // 执行speech模型推理任务 executor.submit(() -> { float[] speechInput = prepareSpeechInput(rawAudioData); List<ClassificationResult> speechResults = speechClassifier.classify(speechInput); // 判断是否是目标指令 String command = checkTargetCommand(speechResults); runOnUiThread(() -> updateSpeechCommand(command)); });
4. 联动两个模型的结果
在主线程里维护两个模型的最新结果,每次有新结果就检查:如果YAMNet检测到语音,同时speech模型识别出up/down/left/right里的一个,就触发应用的响应操作(比如页面跳转、执行指令)。注意要处理好结果的时序,别拿旧结果和新结果凑在一起判断。
更优方案:模型融合(可选)
如果不想维护两套推理逻辑,且对性能有要求,可以把两个模型合并成一个TFLite模型:
- 用TensorFlow把YAMNet和speech模型串联起来,先让音频经过YAMNet的特征提取层,再把特征(或者直接把语音检测结果作为开关)喂给speech模型。
- 或者训练speech模型时加一个语音检测分支,让一个模型同时完成两个任务,这样输入只需要处理一次,推理效率更高。不过这个方案需要有TensorFlow建模和训练的基础。
内容的提问来源于stack exchange,提问作者zheng
相关产品推荐
相关产品推荐

