Open
Description
我希望在android & IOS上運行ASRT,我使用python進行後續的測試
首先我將音檔讀入是使用:
import librosa
wav_signal, sample_rate = librosa.load(audio_path, sr=None)
接下來我讀取ASRT的模型參數(這個模型除了原始數據外,還加入了CV的TW數據。
from model_zoo.speech_model.keras_backend import SpeechModel251BN
def load_tf_model(model_path):
AUDIO_LENGTH = 1600
AUDIO_FEATURE_LENGTH = 200
CHANNELS = 1
# 原始拼音=1427、cv-TW=3、空白=1
OUTPUT_SIZE = 1431
sm251bn = SpeechModel251BN(
input_shape=(AUDIO_LENGTH, AUDIO_FEATURE_LENGTH, CHANNELS),
output_size=OUTPUT_SIZE
)
sm251bn.load_weights('./save_models/SpeechModel251bn/SpeechModel251bn_epoch40.model.h5')
trained_model, base_model = sm251bn.get_model()
return trained_model, base_model
我透過上述的代碼取得欲訓練的模型,trained_model是包含CTC loss的,因此我使用base_model 進行轉換。我共使用了ONNX與TF_lite進行測試:
TF_lite:
def convert_tf_lite(tf_model, save_path):
# 轉換为 TensorFlow Lite 模型
converter = tf.lite.TFLiteConverter.from_keras_model(tf_model)
tflite_model = converter.convert()
# 保存 TensorFlow Lite 模型
with open(save_path, 'wb') as f:
f.write(tflite_model)
return os.path.isfile(save_path)
ONNX:
def convert_tf_onnx(tf_model, save_path, opset):
import tensorflow as tf
import tf2onnx
# 轉換為 ONNX 格式
onnx_model, _ = tf2onnx.convert.from_keras(tf_model, opset=opset)
# 保存 ONNX 模型
with open(save_path, 'wb') as f:
f.write(onnx_model.SerializeToString())
return os.path.isfile(save_path)
接下來我使用了修改過的Spectrogram進行特徵提取
from speech_features import Spectrogram
data_pre = Spectrogram()
audio_features = data_pre.onnx_run(wavsignal=wav_signal, fs=sample_rate)
audio_features = adaptive_padding(input_data=audio_features, target_length=1600)
我在原始的Spectrogram類參考run創建了onnx_run,實際上只是匹配輸入參數的維度等資訊。
def onnx_run(self, wavsignal, fs=16000):
if fs != 16000:
raise ValueError(
f"[Error] ASRT currently only supports wav audio files with a sampling rate of 16000 Hz, but this "
f"audio is {fs} Hz.")
# wav波形 加时间窗以及时移10ms
time_window = 25 # 单位ms
window_length = int(fs / 1000 * time_window) # 计算窗长度的公式,目前全部为400固定值
wav_arr = np.array(wavsignal)
range0_end = int(len(wavsignal) / fs * 1000 - time_window) // 10 + 1 # 计算循环终止的位置,也就是最终生成的窗数
data_input = np.zeros((range0_end, window_length // 2), dtype=np.float64) # 用于存放最终的频率特征数据
data_line = np.zeros((1, window_length), dtype=np.float64)
for i in range(0, range0_end):
p_start = i * 160
p_end = p_start + 400
data_line = wav_arr[p_start:p_end]
data_line = data_line * self.w # 加窗
data_line = np.abs(fft(data_line))
data_input[i] = data_line[0: window_length // 2] # 设置为400除以2的值(即200)是取一半数据,因为是对称的
data_input = np.log(data_input + 1)
return data_input
接下來透過adaptive_padding將輸入的特徵轉換成跟原始輸入相同的尺寸
def adaptive_padding(input_data, target_length=1600):
input_data = input_data.astype(np.float32)
input_data = np.expand_dims(input_data, axis=0) # 添加批量维度
input_data = np.expand_dims(input_data, axis=-1) # 添加通道维度
# 计算需要填充的长度
current_length = input_data.shape[1]
padding_length = max(0, target_length - current_length)
# 计算填充宽度
left_padding = padding_length // 2
right_padding = padding_length - left_padding
pad_width = [(0, 0), (left_padding, right_padding), (0, 0), (0, 0)]
# 进行填充
padded_data = np.pad(input_data, pad_width, mode='constant').astype(np.float32)
return padded_data
經由上述轉換後的模型輸出結果,都是空白塊分數最高,後續調用tf.nn.ctc_beam_search_decoder與K.ctc_decode就沒有意義了。
想請問是否有相關的研究或實踐方法可以推薦?又或者我需要提供更多的測試或特定文件?
感謝
Metadata
Assignees
Labels
No labels
Activity
Evanston0624 commentedon May 6, 2024
補充:
相同的模型使用predict_speech_file.py是可以正確預測輸出的
Evanston0624 commentedon May 6, 2024
更新:
我透過原始的from utils.ops import read_wav_data來讀取音檔就可以了
轉頻譜的部分目前改回原本Spectrogram類下的run
nl8590687 commentedon May 6, 2024
不建议直接在手机端运行,否则计算性能和依赖环境的安装配置都较为复杂,最佳方案是模型部署于服务器,手机通过API接口调用。具体讲解可以看AI柠檬博客相关文章。
nl8590687 commentedon May 6, 2024
如果实在要在手机端部署也可以,那就需要你自行用对应平台支持的框架重写一遍推理能力了
Evanston0624 commentedon May 6, 2024
您好,我們的服務器在多用戶調用時的響應速度與不如預期,後續我有自己編寫一套透過socket的TCP+UDP實踐註冊與傳遞語音包的多進程程序,但在多用戶組的情況下響應也是不如預期。(上述問題可能是存在我們的硬體配置或網路等)
因此我想透過ONNX與TF-Lite來實現移動設備推理,我剛剛實際測試已經可以生成結果了,稍晚會把代碼發上來(python的測試代碼)。後續應該會使用java開發app程序,那這部分的工作應該如下:
我認為如果可以確定python的數據格式與java上的差異,應該可以正確運行
nl8590687 commentedon May 6, 2024
单进程因为只有一个计算图资源,多用户并发调用响应速度慢是很正常的,你需要做的是多实例集群部署,负载均衡,而不是单纯的改通信协议。AI模型部署本身就是很耗费资源的。
Evanston0624 commentedon May 16, 2024
感謝nl8590687對於製作ASR服務的意見與提點,對於TF-lite,模型只要可以轉換,在android有支援的版本下有硬體加速。我認為coreML也是如此(我還沒有了解此部分)。
我已經實踐了在Android上使用ASRT訓練的模型(轉為TF-lite)進行推理。
https://github.com/Evanston0624/ASRT_model_Android/tree/main
README 稍晚會創建,主要代碼在:
https://github.com/Evanston0624/ASRT_model_Android/tree/main/app/src/main/java/com/example/myapplication
上述的庫主要實踐了:
**在前三個階段在小樣本時的輸出數值跟python上相同。
**對於buffer的資料流傳遞可能存在問題,防呆可能也不完善。
尚未實踐
將ASRT訓練的模型轉為TF-lite的代碼後續會補上
Evanston0624 commentedon Jun 13, 2024
更新了ASRT模型轉換為onnx、tf-lite與core-ml的代碼:
子專案
這個子專案包含了一個ASRT的預訓練模型(比ASRT提供的數據集多了CV14.0,發音多了三個),還有三個轉換好的模型。子專案可以使用python進行onnx、tf-lite的轉換與推理,後續會完善量化評估等資訊。
對於手機運行的效能(android & ios),因為我不擅長編寫手機端 因此我有合作的工程師會一起完善這部分,對於手機版本支援與效能評估會在後續進行完整測試後補上。