JavaScript 中的声音活动识别
对于我的个人项目,我经常从阅读的有关人机交互的研究论文中获得灵感。
最近,我一直在研究一种名为“ Ubicoustics - 即插即用声学活动识别”的技术,它是由美国 CMU(卡内基梅隆大学)的研究团队开发的。
声学活动识别利用声音的丰富特性来深入了解环境或活动。
这可用于增强智能系统并构建更加个性化的互联家居。
CMU 的研究人员使用 Python 制作了他们的实验原型,并将他们的项目开源到 Github 上,如果你想看看的话。但我想看看是否可以使用 Web 技术复现类似的功能,结果成功了!😃
最终结果是一个基于浏览器的声学活动识别系统的原型,可以对说话、咳嗽、打字、刷牙和手机铃声进行分类:
我的探索还处于早期阶段,但我想分享我迄今为止学到的知识。
为什么要使用声音?
我们身边的很多设备都内置了麦克风;比如笔记本电脑、手机、平板电脑、智能手表、家庭助理等等……然而,它们并没有真正利用声音的丰富属性。
通常情况下,应用程序会监听某个词来触发诸如“Ok,Google”或“Alexa”之类的操作,但词并非唯一能产生可辨别声音的东西;我们周围的一切都会产生声音。
如果你花一点时间想一想,你就会知道雨的声音是什么,你知道打开冰箱和微波炉时的声音有什么区别,你能认出门铃的声音,即使它不是你的,等等......
我喜欢这样想:如果你的大脑能够接受声音输入并对其进行分类,那么使用机器学习也应该可以实现类似的事情;所以让我们看看它是如何工作的。
技术栈
对于这个原型,我使用Web Audio API将麦克风作为输入,使用Canvas用声音数据构建频谱图,并使用Tensorflow.js训练模型来识别活动。
为了使其更容易,我使用了Google 的Teachable 机器实验来录制我的声音样本,训练机器学习模型并将其导出。
现在,让我们来看看我构建它所采取的一些步骤。
可视化声音数据
当您使用 Web Audio API 检查从麦克风输入获取的数据时,您会得到如下内容:
从这个角度来看,作为数字数组,我们很难找到任何特定的模式来区分拍手和打响指。
为了帮助我们,我们通常会将这些数据可视化。两种标准方法是将其转换为波形图或频率条形图,如下所示:
波形表示声波随时间变化的位移。
声音是空气分子的振动,这张图显示的是声波的振荡。但是,即使通过这种方式进行可视化,我们仍然无法得出任何结论。
频率条形图展示了声音数据,衡量了波形在给定时间内重复的次数。
通过这种可视化方式,我们或许可以开始获得一些见解,识别出某种“节拍”,但我们还远未达到那种程度。
表示这些数据以找到模式的更好方法是所谓的频谱图。
频谱图是信号频率随时间变化的频谱的直观表示。你可以把它想象成声音的热图。
使用 Canvas 将我的麦克风输入可视化为声谱图,我可以很容易地识别说话和拍手之间的区别。
到目前为止,这些都没有用到机器学习。我只是用了 Web Audio API 从麦克风获取数据,然后用 Canvas 将其转换成声谱图。
现在我们可以观察到某些活动产生的数据“看起来”不同,我们可以继续使用机器学习和 Tensorflow.js 来构建分类模型。
使用机器学习对声音数据进行分类
如上所述,为了使其更容易,我使用 Teachable 机器实验来记录我的声音样本,运行训练并生成模型。
到目前为止,我的主要目标是验证我的想法是否可行,所以我更喜欢使用已经构建好的东西,但是,你绝对可以从头开始创建自己的声音分类系统(我希望这是我潜在的下一步之一)。
目前,我的训练过程如下:
首先,你需要录制20秒的背景噪音。这是必要的步骤,这样算法才能识别出你没有进行任何活动时的某种中性状态。
然后,您可以添加不同的“类别”,即不同的活动。每个活动至少需要记录 8 个样本,但越多越好。
在上面的例子中,我只记录了弹指的样本,然后运行训练并在最后实时检查预测结果。
根据你想要构建的内容,你可能会添加更多类别,但检查预测是否准确非常重要,这样你就可以记录更多样本,并在必要时重新训练。
如果您对输出感到满意,您可以下载该模型并将其用于您的项目中。
使用机器学习模型
一旦训练过程完成,您就可以使用生成的模型对以前从未“见过”的新声音样本进行一些实时预测。
为此,您需要首先导入框架和另一个模型:
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.3.1/dist/tf.min.js">
</script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/speech-commands@0.4.0/dist/speech-commands.min.js">
</script>
在上面的代码示例中,我们导入了 Tensorflow.js 和语音命令模型。
我们需要这样做,因为我们预测新声音样本的方式是使用迁移学习。
迁移学习意味着我们使用针对特定输入进行优化的预训练模型,向其中添加我们自己的样本并重新训练所有内容。
语音命令模型是 Tensorflow.js 中唯一一个使用声音样本进行训练的预训练模型。
它针对语音单词的分类进行了优化,但我想看看它在输入活动的声音样本后是否仍然准确。
导入工具后,您需要加载自定义模型:
let model;
async function setupModel(URL, predictionCB) {
//store the prediction and audio callback functions
predictionCallback = predictionCB;
const modelURL = 'model.json';
const metadataURL = 'metadata.json';
model = window.speechCommands.create('BROWSER_FFT', undefined, modelURL, metadataURL);
await model.ensureModelLoaded();
const modelParameters = {
invokeCallbackOnNoiseAndUnknown: true, // run even when only background noise is detected
includeSpectrogram: true, // give us access to numerical audio data
overlapFactor: 0.5 // how often per second to sample audio, 0.5 means twice per second
};
model.listen(
//This callback function is invoked each time the model has a prediction.
prediction => {
predictionCallback(prediction.scores);
},
modelParameters
);
}
从 Teachable Machine 下载模型后,您会获得一个model.json
和两个metadata.json
文件。这两个文件都需要用到才能正常工作。metadata.json 文件包含有关类名等信息……
然后,您需要调用speechCommands
模型并将模型变量传递给它。
模型加载后,您可以定义一些额外的参数,调用该listen
方法,每次从来自麦克风的实时音频数据中预测某些内容时都会触发回调。
一旦设置了函数,就可以这样调用它:
let labels = ["Clapping","Speaking","_background_noise_"];
setupModel(URL, data => {
// data will look like this [0.87689, 0.21456, 0.56789]
switch(Math.max(...data)){
case data[0]:
currentPrediction = labels[0];
break;
case data[1]:
currentPrediction = labels[1];
break;
default:
currentPrediction = "";
break;
}
}
return currentPrediction;
});
我定义了一个包含我训练过的类别的数组,当发生预测时,结果将以 0 到 1 之间的浮点数数组的形式返回,表示每个类别被预测的概率;如果最大数字是概率数组中的第一个,那么我们识别的活动将是上面定义的标签数组中的第一个。
演示
最后,我的原型看起来像这样:
如果您想亲自尝试一下,这里是演示的链接。
我在安静的环境中测试会更准确,因为我的样本是在家里录制的。如果在火车或咖啡馆测试,背景噪音与训练时的背景噪音差别太大,准确率会下降。
目前,由于时间限制,它主要针对桌面版 Chrome 进行了优化。为了使其在其他浏览器和移动设备上也能正常运行,还需要修复一些问题。😞
应用
目前,该原型还只是探索性的,但我相信这种技术具有潜力。
我们不用购买多个昂贵的智能设备,例如冰箱、咖啡机和微波炉,这些设备只能知道自己在做什么(智能冰箱不知道咖啡机是否打开了,等等),而是可以用一个具有更多情境理解能力的设备来代替它们,不仅可以理解其他设备,还可以理解设备所在的房间以及用户的活动。
这可能对以下应用程序有帮助。
情境感知视频服务
烹饪
如果你一边做饭一边跟着 YouTube 上的菜谱做菜,当你需要切蔬菜、用微波炉加热一分钟、使用打蛋器等等时,视频会自动暂停,通过监听你的动作。这样,你就不用在做饭时在笔记本电脑、平板电脑或手机之间来回切换了。
观看你最喜欢的电视剧
如果您正在观看 Netflix,这时您的手机或门铃响了,视频可能会暂停,而您无需寻找遥控器,因为门铃或电话响起通常意味着您将离开电视几分钟。
互动故事讲述
如果你在创意机构或媒体公司工作,线上内容的互动性至关重要,那么这类技术或许能带来一种更具互动性和娱乐性的内容消费方式。通过让你以不同的方式参与其中,比如拍手、模仿声音等等,故事的沉浸感会大大增强。
健康追踪
正如您在我的快速演示中看到的,您可以对咳嗽和刷牙的声音进行分类,因此您还可以训练您的系统识别打喷嚏、打鼾等......并建立某种健康跟踪系统。
肯定还有更多的应用程序,但这只是为了让您了解它可以在哪里使用。
限制
主要限制之一在于隐私问题。你肯定不希望你的 Google Home 或 Amazon Alexa 不仅监听你的对话,还能通过监听你的所有活动来了解你的一举一动吧……对吧?!😢
有一种方法可以构建您自己的私人离线系统,但这绝对不是大多数人可以访问的。
目前另一个主要限制是无法同时理解多项活动。如果你在刷牙时有人和你说话,这个系统一次只能预测一项活动。
然而,这正是另一个令人兴奋的项目发挥作用的地方,它被称为“通用合成传感器”😍,接下来我将简要讨论一下。
后续步骤Next steps
我还有很多东西要学,我希望有时间在 2020 年探索这个领域,但我的下一步是构建通用合成传感器。
卡内基梅隆大学的研究人员不仅使用声音数据来识别活动,还致力于开发一个集成多个传感器(麦克风、温度传感器、加速度计、运动传感器、光传感器等)的小型设备,以组合多个频谱图,从而监控更大的环境并构建更强大的活动识别系统。
现在就这样了!
我知道人们可能会对这个实验持怀疑态度,特别是在 JavaScript 方面,但我知道这个实验不需要硬件升级,这意味着我们正在等待的主要事情可能是找到正确的应用程序。
就我个人而言,我总是非常高兴地知道,作为开发人员,我们可以通过使用 JavaScript 构建原型来参与此类研究,并探索交互的未来。
希望有帮助!🙂
文章来源:https://dev.to/devdevcharlie/acoustic-activity-recognition-in-javascript-2go4