第8章 用声音和传感数据发现异常

工作阶段: 把连续现场信号变成可观察、可比较的低风险提醒。
公共核心项目: 与AI协同开发“设备声音异常观察站”。
核心技术: 采样、时间窗口、会话级划分、波形、FFT频谱、时频统计特征、RMS基线、Keras二分类、漂移门与双阈值。
输入输出链: 1秒WAV → 采样/静音/削波检查 → 七维时频特征 → RMS基线/Keras模型 → 正常候选、低风险提醒或人工接管。
应用中的AI: 根据已登记正常与异常声音的时频特征输出异常候选分数的本地Keras分类模型。
协助开发的AI: 帮助学生审查采集情境、解释波形与频谱、生成和修改完整代码、分析误报漏报的大语言模型。
人的责任: 确认设备、负载、位置、会话与标签,处理声音授权,审查漂移和错例,决定是否检查设备以及任何现场动作。
主要交付物: 168个离线WAV、会话清单、RMS基线、时频Keras模型、完整Notebook与.py工程、漂移测试、真实报告和模型卡。
明确边界: 输出只表示声音接近已知异常候选,不诊断故障,不自动停机、断电、维修或调整生产。
跨章关系: 延续第7章的分组隔离、基线和模型卡;第9章可把特征和模型部署到离线终端,但安全动作仍由规则和人决定。

学习目标

完成本章学习后,你将能够:

  1. 说明采样率、1秒窗口、录制会话和工况记录怎样定义一条声音样本;
  2. 从波形提取RMS、峰值、过零率、频谱中心和频带能量比例;
  3. 按会话隔离训练、验证和测试,避免相邻窗口泄漏;
  4. 比较RMS阈值、Keras有标签分类和异常检测三种思路的适用条件;
  5. 用误报、漏报、双阈值、漂移和故障测试评价低风险提醒;
  6. 与AI协同完成一项限定修改、固定回归、模型卡和复现交付。

项目导入

设备声音包含转动、摩擦、冲击、环境噪声和人的活动。人有时能听出变化,但“听起来不对”很难批量记录和比较。人工智能可以把声音窗口变成数值特征,学习已确认的正常与异常模式,再给人员一个候选提醒。

这个任务不能写成“AI听声音判断设备故障”。一个异常分数只说明声音与训练中的已知模式相似,不能指出轴承、皮带或电机具体故障。麦克风位置、增益、转速和负载变化都可能改变声音。系统只能提示人员查看原始声音与工况,停机和维修必须走正式规程。

本章用可离线生成的教学声音跑通完整项目。每个文件为1秒、8 kHz、16位单声道WAV。登记数据有10个录制会话,每个会话16个窗口;S01—S06训练,S07—S08验证,S09—S10冻结测试。另有D01的8个不同基础频率窗口模拟未登记设备或工况漂移。

声音生成器刻意让正常和异常整体RMS接近:异常主要多出1250 Hz成分和7 Hz幅度调制。这样透明RMS规则会暴露“只看响度”的局限,时频模型才有机会通过频谱结构带来增益。数据设计与真实运行均公开,100%测试分也不会被包装成现实准确率。

连续设备声音
     ↓ 切成1秒窗口并记录会话/设备/负载
WAV格式、采样率、长度、静音、削波检查
     ↓
RMS、峰值、过零率、频谱中心、低/中/高频比例
     ├─ RMS阈值基线 ─────────────┐
     └─ 归一化→Keras二分类分数 ──┼→ 未见会话比较
                     漂移门 ──────┘
            ↓
正常候选 / 低风险提醒 / 人工复核
            ↓
人员结合原声、工况和正式规程决定

建议用7—9学时。学生先试听或查看几个合成WAV及其特征,再运行参考模型;随后在Notebook中逐格执行会话检查、FFT特征、RMS基线和Keras训练;最后改变一个提醒阈值、检查漂移与故障,形成模型卡。Python和Keras是实现材料,学习重点是信号如何变成样本、证据如何受情境限制。

本章成果

AI协同开发路线

先向协助开发的AI提交采集条件:“我们只在登记设备、固定麦克风位置和稳态负载下观察1秒声音。请先追问采样率、会话编号、标签来源、声音隐私、异常提醒后谁处理;不要先写分类代码。”学生依据设备人员和数据授权回答,把未知条件写入合同,不让AI假设“声音更响就是故障”。

条件冻结后,要求AI先列出生成/采集、WAV校验、特征、会话划分、RMS基线、Keras训练、漂移门、统一推理、评价、Notebook和测试文件。约束依赖只用Python标准库、NumPy与Keras/TensorFlow,不引用多个音频框架。学生确认文件关系后再生成完整代码。

开发阶段提交S07—S08验证混淆矩阵与具体窗口,而不是问“模型好不好”。修改时限定:“只在验证会话把提醒阈值从0.50改为0.70,保持模型分数、特征和漂移门不变,不读取S09—S10。”学生冻结模型、RMS门槛和运行阈值后,最终评价才一次性打开S09—S10;最终结果用于交付判断,不再反向选参。

第一节 把连续信号切分成带情境的学习样本

一、采样率决定每秒记录多少点

声音是连续变化的空气振动,数字设备按固定时间间隔记录幅度。8 kHz表示每秒8000个采样点;本项目每个文件恰好1秒,因此数组长度为8000。16位PCM把幅度保存为整数,程序再缩放到约-1到1。

采样率决定能表示的最高频率和文件大小。若训练都用8 kHz、运行却收到16 kHz文件,直接提取同样索引的频带会改变含义。本项目不静默重采样,采样率不符直接报错并转人工准备数据。真实工程可增加明确重采样模块,但必须固定参数并测试。

read_wav还检查单声道、16位、长度。损坏文件、立体声或窗口不足不是正常类别,不能用零填补后交给模型。输入检查属于确定性程序,模型不需要学习文件头规则。

二、时间窗口把长记录变成样本

连续录音不能直接对应一个标签。本项目把它切成1秒窗口,每个窗口计算特征并赋予经确认的正常或异常标签。窗口越短,响应可能更快,却可能看不到完整周期;窗口越长,特征更稳定,但提醒延迟和数据量增加。

窗口标签必须与设备状态和时间对应。如果一段会话前半正常、后半发生变化,不能只按整个文件名批量贴标签。真实采集要记录设备编号、负载、转速、麦克风位置、维护状态、开始时间和操作人员确认。没有情境的声音很难解释,模型也可能把环境声当设备特征。

配套生成器每个会话含8个正常与8个异常窗口,共10个登记会话160个窗口。D01的8个窗口使用另一基础频率并标记unknown,只测试漂移接管。清单不含真实谈话和个人信息。

三、按录制会话隔离数据

同一会话相邻窗口共享设备、房间、增益和背景,彼此高度相似。把窗口随机分到训练与测试,会让模型在测试中看到训练会话的近邻,得到虚高分。正确做法是先按session_id分组,再把整个会话放进一个集合。

sessions = {}
for row in rows:
    sessions.setdefault(row["session_id"], set()).add(row["split"])
leaked = [session for session, splits in sessions.items()
          if len(splits) > 1]
if leaked:
    raise ValueError(f"录制会话跨集合泄漏: {leaked}")

训练会话S01—S06有96个窗口,验证S07—S08有32个,冻结测试S09—S10有32个。测试基础频率与训练略有变化但仍属于登记设备范围。真实部署还应把不同日期、设备和位置作为更严格的现场测试,不因本章按会话隔离就声称解决全部泛化问题。

专业迁移卡:智能制造与交通
制造方向可采集电机、泵或风机声,必须记录负载、转速、传感器和维护状态;交通方向可观察车辆部件或轨旁声音,但位置、天气和速度是关键情境。声音模型只作低风险候选,设备或交通安全动作由正式制度和专业人员决定。

第二节 从波形、频谱和时间变化建立正常基线

一、波形描述幅度随时间变化

波形是8000个幅度随时间排列的数组。RMS等于平方平均后开方,用一个数概括整体能量;峰值是最大绝对幅度,可发现削波。持续近似零可能表示传感器断开或录制失败,不能当作“特别安静的正常设备”。

rms = float(np.sqrt(np.mean(samples ** 2)))
peak = float(np.max(np.abs(samples)))
if rms < 0.005:
    return {"accepted": False,
            "reason": "近似静音,传感器或录制疑似失效"}
if peak >= 0.98:
    return {"accepted": False,
            "reason": "波形削波,需重新采集"}

RMS规则基线只使用正常训练窗口:阈值=正常RMS平均值+1.5倍标准差。超过阈值给异常候选,否则正常候选。它透明、计算快,却只看到能量。异常如果音量相近而频率结构不同,RMS会漏掉。

二、频谱描述能量分布在哪些频率

快速傅里叶变换把加窗波形转换为各频率的能量。频谱中心是频率按能量加权的平均位置;低频、中频和高频比例分别统计400 Hz以下、400—1000 Hz和1000 Hz以上的能量。异常合成信号增加1250 Hz成分,因此高频比例和频谱中心会变化,即使RMS相近。

过零率统计相邻采样正负号变化比例,对高频和噪声较敏感。本项目最终七个特征为RMS、峰值、过零率、频谱中心、低频比例、中频比例和高频比例。特征压缩使模型容易观察和运行,却也丢掉瞬态顺序,不能捕捉所有真实异常。

课堂观察时,每组各取一个正常和异常窗口,先只看RMS,再看七维特征。两类RMS都接近0.225,学生应预测RMS规则难以区分;异常窗口的频谱中心和高频比例则更明显。随后换到另一个会话,检查结论是否仍成立。这个过程让学生看到“特征是为任务选取的表示”,模型并没有直接听懂声音含义。

特征名称、单位和计算参数必须随模型保存。频谱中心单位为Hz,三个比例无单位,过零率是0到1之间的比例。若后续把采样率或频带边界改变,七个数字即使列名相同,含义也已经变化,应建立新版本并重新训练,不能继续加载旧模型。

windowed = samples * np.hanning(len(samples))
spectrum = np.abs(np.fft.rfft(windowed)) ** 2
freqs = np.fft.rfftfreq(len(samples), 1 / 8000)
total = float(spectrum.sum()) + 1e-12
centroid = float((freqs * spectrum).sum() / total)
low = float(spectrum[freqs < 400].sum() / total)
mid = float(spectrum[(freqs >= 400) & (freqs < 1000)].sum() / total)
high = float(spectrum[freqs >= 1000].sum() / total)

三、控制变量:只调整窗口长度作观察

可把1秒窗口改为0.5秒,保持同一录音、特征定义、模型暂不训练,只观察RMS和频谱中心的稳定性。预测:窗口缩短会增加样本数和响应速度,但统计波动可能更大;若异常是短冲击,短窗口也可能更容易定位。

改变窗口会同时改变样本数和相邻性,必须重新按原始会话分组,不能把新的半秒窗口随机切分。学生记录每个会话的特征均值、标准差和计算时间,再决定是否值得进入下一模型版本。控制变量活动不是为了选一个万能长度,而是看清时间尺度如何改变证据。

第三节 比较规则、分类模型和异常检测

一、三条路径的条件不同

规则适合专业阈值能清楚表达的情况,例如输入静音或整体能量超过已确认边界。有标签分类要求正常和已知异常都有可靠样本,本章采用这条路径。异常检测通常只用正常数据建立正常范围,适合异常稀少且类型不断变化的场景,但“偏离正常”仍不等于故障。

三条路径不能只比名称。应看可用数据、标签可信度、错误后果和维护能力。本章既有正常也有明确生成的已知异常,因此训练二分类;RMS保留为基线;异常检测作为机制比较,不在同一章再引入第二套模型,以免学生把不同任务混成“异常AI”。

二、完整最小二分类链

七个特征量纲不同,归一化均值和标准差只从训练会话计算并随模型保存。Keras模型使用16和8个ReLU单元,Sigmoid输出异常相对分数:

mean = x_train.mean(axis=0)
std = x_train.std(axis=0)
std[std == 0] = 1.0

inputs = keras.Input(
    shape=(7,), name="time_frequency_features"
)
x = keras.layers.Dense(16, activation="relu")(inputs)
x = keras.layers.Dense(8, activation="relu")(x)
outputs = keras.layers.Dense(
    1, activation="sigmoid", name="abnormal_score"
)(x)
model = keras.Model(inputs, outputs,
                    name="sound_anomaly_observer")
model.compile(
    optimizer=keras.optimizers.Adam(0.01),
    loss="binary_crossentropy", metrics=["accuracy"],
)
model.fit(
    (x_train - mean) / std, y_train,
    validation_data=((x_val - mean) / std, y_val),
    epochs=100, batch_size=16,
    callbacks=[keras.callbacks.EarlyStopping(
        monitor="val_loss", patience=14,
        restore_best_weights=True,
    )],
)

完整Notebook在resources/ch08/project/notebooks/ch08_sound_observer.ipynb,权威工程为sound.py、train.py、evaluate.py与observe_sound.py。学生要能指出WAV在哪里验证、特征在哪里计算、归一化状态怎样保存、分数在哪里转路由。

三、读取本次真实比较

参考环境为Windows、Python 3.12.13、TensorFlow 2.21.0、Keras 3.15.1、CPU。实际训练使用96个窗口、32个验证窗口,26轮后恢复验证损失较好的权重;固定测试为未见会话S09—S10的32个窗口。

下面是evaluate.py --write-reference生成的本次实际结果。数据数量、环境、训练轮数与混淆矩阵同时写入reports/reference_evaluation.json,不是根据模型结构推测,也没有用训练集成绩替代未见会话测试。

方法 正常正确 误报 漏报异常 异常正确 准确率
RMS阈值0.232268 16 0 16 0 50.00%
Keras时频分类(0.5) 16 0 0 16 100.00%

RMS漏掉全部异常,说明这批异常不是简单变响;时频模型识别了生成器中明确的高频和调制模式。100%不代表现实设备性能。测试只有两个会话,信号由同一公式生成,异常类型单一,真实噪声与设备差异远复杂。正确结论是“模型在合成已知模式上证明了时频特征相对RMS的价值”,不是“AI能够准确诊断设备”。

学生要特别练习拆解这个100%。它不是160个登记窗口的总体成绩,不包含D01漂移,也没有覆盖新故障;它只是冻结S09—S10的32个合成窗口在0.5阈值下的分类结果。模型能够识别生成器写入的1250 Hz成分,与它能否识别真实轴承磨损是两个不同命题。报告同时写样本来源、会话数量、信号机制和禁止用途,才能防止指标脱离条件传播。

运行时采用≤0.35正常候选、≥0.65低风险提醒、中间人工的双阈值。本次32个冻结窗口都进入明确候选且正确;仍要保留人工确认和漂移门,因为高分模型对陌生输入也可能自信。

四、从特征回到声音情境

错例分析不能只看七个数字。RMS受距离和增益影响,频谱中心随转速变化,高频比例可能来自环境蜂鸣或谈话。学生要把分数、波形、频谱、原WAV、设备与负载记录放在一起。如果模型只在固定增益下正确,移动麦克风就可能导致漂移。

向协助开发的AI提交具体窗口、真实标签、特征、分数和会话,不只问“如何优化模型”。要求它区分输入质量、会话分布、特征表示和模型四类原因,并一次只建议一项实验。若AI建议把S09—S10测试窗口加入训练后继续报告原成绩,应拒绝。

图示规划: 绘制“1秒波形—加窗FFT—七维特征—RMS规则/Keras分类—漂移门—低风险提醒—人工复核”,并在会话划分处标出相邻窗口不可跨集合。

第四节 测量误报、漏报、漂移和响应时间

一、只改变提醒阈值

固定模型分数和S07—S08验证会话,分别用0.50与0.70作为异常提醒阈值。提高阈值通常减少误报,却可能增加漏报;降低阈值相反。两个版本都在验证集统计真正正常、误报、漏报和真正异常,并记录进入人工区的数量。

阈值改变不等于重新训练,也不会让陌生异常变成已知。学生先预测哪些验证窗口会变化,再让AI只修改开发配置,审查差异并冻结阈值;S09—S10只在最终评价运行一次。如果验证分数都远离0.5和0.7,结果可能不变,这也是有效观察。

二、四类测试和响应时间

正常测试使用未见会话S09—S10中已登记正常与异常窗口。边界测试包含分数接近双阈值、轻微增益变化和允许范围内的基础频率变化,预期低信心时转人工。陌生测试使用D01不同设备频率,系统计算特征与训练标准化距离;任一绝对标准化值超过6就不运行模型。本次8/8漂移窗口全部在模型前转人工。

故障测试包含静音、削波、16 kHz错误采样、长度不是1秒、损坏WAV、模型或元数据缺失。静音明确提示传感器疑似失效,不能判正常;错误采样率不静默变换;模型故障默认人工。tests/test_project.py实际运行8项检查。

cd resources\ch08\project
python acceptance.py
python acceptance.py --require-model
python observe_sound.py data\wav\S09-01.wav
python observe_sound.py data\wav\D01-01.wav

默认验收检查必需文件、Python语法、8项测试、Notebook冻结隔离,以及报告中的固定测试、模型、配置与元数据摘要;--require-model加载模型,将32个冻结窗口的现场评价与正式参考结果逐项比较,只排除明确不稳定的环境版本字段。模型训练另用python train.py。

响应时间从声音窗口开始形成就应计算。1秒窗口至少需要接近1秒观察,特征和推理再增加处理时间;如果连续三个窗口达到阈值才提醒,稳定性可能提高,延迟也至少增加到约3秒。报告要写清窗口时长、计算时延和连续策略,不能只报模型推理几毫秒。

三、发现漂移并规定低风险响应

工程用训练特征均值和标准差计算最大标准化距离,作为教学漂移门。它只能发现明显数值偏离,不能保证分布内输入就是已知。真实运行还应按设备、负载和位置登记,定期比较近期特征、模型分数、误报和漏报。

漂移提示原证据变弱,不等于设备故障,也不应让新数据自动进入训练。运行日志保存时间、会话/设备、工况、模型与阈值版本、特征、分数、路由、人员确认和响应时间;声音隐私要求只保留必要片段,明确访问和删除。

声音采集还有容易被忽略的隐私问题。设备旁可能有人谈话,原始WAV可能包含与任务无关的语音。真实项目应选择合适位置和时段,明确告知与授权,尽量在设备端提取必要特征,并设置原声保存期限与访问权限。不能因为模型只输出七个特征,就假设采集过程天然匿名;学生与责任人要审查原始数据链。

一次完整课堂演练应由四个角色完成:采集角色确认会话与工况,开发角色运行特征和模型,复核角色听原声并查看频谱,责任角色决定是否发出低风险检查请求。角色互换后再运行一遍,可以暴露哪些结论依赖某个人的口头经验。AI可以整理日志和提出问题,却不能签署设备安全决定。

课堂结束前,每组还要完成一次“证据反向核对”:从一条低风险提醒出发,依次找到异常分数、七维特征、原始WAV、会话与工况、模型和阈值版本,再找到人员的最终确认。任何一环缺失,都不能把提醒作为可追溯成果。另一组应只依据交付目录复现这一条链,并故意移走模型文件,确认系统会转人工而不是继续显示旧结果。这个练习把声音模型从演示程序变成可交接的小工程,也让学生理解运行记录、版本和人工责任为何属于人工智能系统的一部分。

低风险响应只能是页面提示、日志或请值班人员查看。停机、断电、维修和生产调整必须由设备安全规则与有权限人员决定。连续误报、传感器故障、模型文件不一致或输入范围变化时,系统退回人工巡检。

交付包含README、任务合同、数据生成器、168个WAV、清单、数据卡、完整Notebook、.py工程、模型与元数据、训练历史、真实报告、模型卡和验收。另一组应能复现RMS 50%、Keras 100%和漂移8/8接管,同时解释为何最终仍只是登记业务设备范围的低风险提醒。

专业迁移卡:生物与风景园林
生物方向可把声音换成培养箱温湿度序列,按实验批次隔离,异常标签由实验人员依据规程确认;园林方向可输入土壤水分或光照,窗口改为小时或天,传感器校准和季节是关键情境。提醒只触发人工检查,不直接启动水泵、药剂或生物安全动作。

本章小结

本章完成了“声音—窗口—情境—特征—基线—模型—漂移—提醒—交付”的完整项目。连续信号必须按会话切分,WAV质量和静音由规则检查,RMS是透明能量基线,时频特征让Keras模型学习已知频率结构。

真实运行中,RMS在冻结会话仅16/32并漏掉全部异常,时频模型32/32;8个漂移窗口均在模型前接管。这些数字如实说明生成数据上的机制,同时也暴露其简单性。应用中的AI只给候选,协助开发的AI帮助学生理解与修改,专业人员承担设备判断和现场动作。

关键术语

目标测试

  1. 把同一长录音的相邻窗口随机分到训练和测试,主要风险是( )。A.会话泄漏 B.容量超限 C.文本幻觉 D.排程无解
  2. RMS规则最直接反映的是( )。A.故障部件 B.整体声音能量 C.全部设备状态 D.维修方案
  3. 本次RMS准确率50%且漏掉16个异常,主要说明( )。A.异常不存在 B.只看响度无法识别这批频率结构变化 C.测试应删除 D.Keras自动诊断故障
  4. D01漂移窗口最合适的处理是( )。A.相信最高分 B.模型前转人工并核对设备工况 C.自动停机 D.加入训练覆盖测试
  5. 判断并改错:“Keras在32个合成测试窗口上100%,因此可以诊断真实设备故障。”
  6. 判断并改错:“为了适应现场,应把每次运行声音未经审核自动加入训练。”
  7. 说明为什么声音必须按录制会话而不是按窗口随机划分。
  8. 设计0.50与0.70提醒阈值的控制变量实验,写出保持项和四类数量。
  9. 各设计一条边界、陌生和故障测试,说明模型是否运行以及预期动作。
  10. 比较RMS规则、有标签分类和只用正常数据的异常检测的适用条件,并说明本章为何只实现分类路径。

答案编号:A3-8-01—A3-8-10。完整答案和评分要点统一放入书后“目标测试参考答案”。