
简介这份资源面向具备一定MATLAB基础、希望将深度学习应用于地震信号分析的学生与研究人员提供了一套用卷积神经网络完成地震等级预测的完整代码实现。包内共33个文件以30个m脚本为核心辅以2个mat数据文件和1个xlsx表格压缩包约370KB涵盖网络搭建、前向与反向传播、梯度校验、数据预处理及超参数组合搜索等模块结构紧凑便于逐层阅读。已有351人学习下载说明其在同类小众方向中具备一定参考价值。读者可借此理解CNN从滤波器初始化、卷积池化到全连接分类的完整链路掌握地震时间序列的标准化、降噪与时频特征提取思路并借助数值梯度检查与随机种子设定保证实验可复现进而迁移到自身的地震风险评估或信号分类任务中。1. 地震等级预测为什么值得用 CNN 做一遍地震等级预测在工程地震学和台网日常运维里是个老问题。传统做法要么走 Gutenberg-Richter 经验关系要么用震级-频度统计外推能给出一个大致范围但对单台站、短窗口、早期波形这类信息量有限的场景误差经常大到没法直接用。近几年台网密度上来了三分量波形采样率普遍到 100 Hz 甚至更高单事件可用的时序点数从几百涨到几千这就给数据驱动方法留出了空间。卷积神经网络 CNN 最擅长的恰好是从这种高维时序里自动抽局部模式——P 波初动、S 波到时、尾波衰减这些特征人工设计滤波器要反复调CNN 靠卷积核自己学。MATLAB 在这条链路上有天然优势信号处理工具箱、深度学习工具箱、Wavelet 工具箱都在一个环境里读 miniSEED、做带通滤波、切窗、归一化、搭网络、训练、导出不用在 Python 和 C 之间来回倒。这篇面向的是手里有台网波形、想用 MATLAB 把 CNN 地震等级预测跑通的从业者从数据准备一路讲到调参和踩坑新手能照着复现熟手能直接看边界条件。2. 从波形到标签地震数据集怎么切、怎么标、怎么存2.1 地震波形数据的来源与筛选标准做地震等级预测第一步不是搭网络是把数据搞干净。常见来源有三类IRIS 等公开台网下载的 miniSEED本地台网归档的连续波形以及已经切好的事件波形库。我一般优先用事件波形库因为连续波形切事件这一步本身就容易引入偏差——STA/LTA 触发阈值设高了漏掉小震设低了把噪声当事件。筛选标准要卡死几条。第一震中距控制在 0 到 200 km太远的高频衰减严重P 波信噪比撑不住。第二震级范围按你的目标定如果做 3.0 到 6.0 的等级预测两端各留 0.2 的缓冲避免边界样本把回归拉偏。第三每个事件至少三个台站有记录单台站样本对 CNN 来说信息太单薄。第四采样率统一重采样到 100 Hz不统一的话卷积核感受野对应的物理时间就不一致训练出来的模型换个台网就废。% 读取 miniSEED 并做基本筛选 cfg struct(fs, 100, distMax, 200, magMin, 3.0, magMax, 6.0); evtList dir(fullfile(dataRoot, *.mseed)); validEvt {}; for k 1:numel(evtList) [w, meta] readseis(fullfile(dataRoot, evtList(k).name)); if meta.dist cfg.distMax || meta.mag cfg.magMin || meta.mag cfg.magMax continue; end if meta.fs ~ cfg.fs w resample(w, cfg.fs, meta.fs); end validEvt{end1} struct(wave, w, mag, meta.mag, dist, meta.dist); end这段逻辑的核心是先把物理约束卡住再做重采样。distMax和震级范围是硬门槛resample放在筛选之后是为了省算力。注意readseis是示意函数名实际用rdsac、irisFetch或自己写的 miniSEED 解析都行关键是拿到波形矩阵和元数据。2.2 三分量切窗与标签构造CNN 的输入张量一般是[时间点 × 通道 × 1]或者[时间点 × 1 × 通道]MATLAB 深度学习工具箱习惯把通道放最后一维所以推荐[N × 3 × 1]N 是窗口长度。窗口怎么切有讲究以 P 波到时为基准往前取 1 秒做前置噪声往后取 9 秒覆盖 S 波和部分尾波总长 10 秒100 Hz 下就是 1000 个点。这个 19 的分配不是拍脑袋前置噪声给网络一个信噪比参照后段尾波携带震级信息。标签构造有两种路线。一是直接回归震级数值输出一个标量损失用 MSE。二是把震级离散成等级比如 3.0-3.9、4.0-4.9、5.0-5.9 三档做分类。回归对连续预测更友好分类在样本不均衡时更稳。我一般先做回归因为地震等级本质是连续量硬切等级会丢信息。winPre 1 * cfg.fs; % P 波前 1 秒 winPost 9 * cfg.fs; % P 波后 9 秒 X zeros(numel(validEvt), winPrewinPost, 3, single); Y zeros(numel(validEvt), 1, single); for i 1:numel(validEvt) pIdx validEvt{i}.pIndex; seg validEvt{i}.wave(pIdx-winPre1 : pIdxwinPost, :); seg seg - mean(seg, 1); % 去均值 seg seg ./ (max(abs(seg), [], 1) eps); % 逐通道归一化 X(i,:,:) seg; Y(i) validEvt{i}.mag; end去均值和逐通道归一化是必须的不同台站的仪器响应和增益差异很大不归一化网络会先学台站特征而不是震源特征。eps防止除零。归一化用max(abs())而不是标准差是因为地震波形有尖脉冲标准差会被异常值拉大。2.3 训练集、验证集、测试集怎么分才不泄漏随机划分是新手最容易翻车的地方。同一个地震事件被多个台站记录如果按样本随机分同一事件的不同台站样本可能同时进训练集和测试集模型等于见过答案测试精度虚高。正确做法是按事件 ID 分组划分同一事件的所有台站样本要么全在训练集要么全在测试集。evtIds unique({validEvt.eventId}); rng(42); idx randperm(numel(evtIds)); nTrain round(0.7 * numel(evtIds)); nVal round(0.15 * numel(evtIds)); trainEvt evtIds(idx(1:nTrain)); valEvt evtIds(idx(nTrain1:nTrainnVal)); testEvt evtIds(idx(nTrainnVal1:end));比例我一般用 70/15/15。验证集用来早停和调参测试集只在最后跑一次。rng(42)固定随机种子保证复现。如果事件数少于 500建议用 5 折交叉验证代替单次划分否则测试集太小指标波动大。3. 在 MATLAB 里搭一个能用的 CNN 回归网络3.1 网络结构选型为什么不用现成的 ResNet地震波形是一维时序直接套二维图像网络ResNet、VGG是常见误用。二维卷积核在图像上抓的是空间局部性地震波形只有时间一维硬把[1000×3]当图像处理卷积核会在通道维度上乱滑学到的特征没有物理意义。正确做法是用convolution1dLayer卷积核只在时间轴上滑动。网络深度不用太深。我一般用 4 到 6 个卷积块每块是conv1d batchNorm relu maxPool。第一层卷积核设大一点比如 15 到 31感受野覆盖 P 波初动的几个周期后面逐层减小到 3 到 5抓更细的尾波衰减模式。通道数从 32 起步每池化一次翻倍到 256 封顶。再深就容易过拟合地震样本量通常撑不住。layers [ sequenceInputLayer(3, Name, input) % 3 通道输入 convolution1dLayer(31, 32, Padding, same, Name, conv1) batchNormalizationLayer(Name, bn1) reluLayer(Name, relu1) maxPooling1dLayer(4, Stride, 4, Name, pool1) convolution1dLayer(15, 64, Padding, same, Name, conv2) batchNormalizationLayer(Name, bn2) reluLayer(Name, relu2) maxPooling1dLayer(4, Stride, 4, Name, pool2) convolution1dLayer(7, 128, Padding, same, Name, conv3) batchNormalizationLayer(Name, bn3) reluLayer(Name, relu3) maxPooling1dLayer(4, Stride, 4, Name, pool3) convolution1dLayer(3, 256, Padding, same, Name, conv4) batchNormalizationLayer(Name, bn4) reluLayer(Name, relu4) globalAveragePooling1dLayer(Name, gap) dropoutLayer(0.3, Name, drop) fullyConnectedLayer(64, Name, fc1) reluLayer(Name, relu5) fullyConnectedLayer(1, Name, fcOut) % 回归输出标量 regressionLayer(Name, reg) ];sequenceInputLayer(3)对应三分量。Paddingsame保证卷积不改变时间长度池化负责降维。globalAveragePooling1dLayer替代全连接展平参数量小很多抗过拟合。最后fullyConnectedLayer(1)加regressionLayer是回归标配。如果做分类把最后两层换成fullyConnectedLayer(numClasses)和classificationLayer。3.2 训练参数怎么设学习率、批大小、早停训练用trainingOptions配。优化器选adam学习率初始 1e-3每 10 个 epoch 降一半。批大小 32 到 64取决于显存地震样本 1000 点不算大64 一般够。epoch 上限设 100但一定要开验证早停ValidationPatience设 10验证损失 10 轮不降就停。opts trainingOptions(adam, ... InitialLearnRate, 1e-3, ... LearnRateSchedule, piecewise, ... LearnRateDropPeriod, 10, ... LearnRateDropFactor, 0.5, ... MaxEpochs, 100, ... MiniBatchSize, 64, ... Shuffle, every-epoch, ... ValidationData, {XVal, YVal}, ... ValidationFrequency, 20, ... ValidationPatience, 10, ... OutputNetwork, best-validation-loss, ... Plots, training-progress, ... Verbose, false);OutputNetworkbest-validation-loss是关键训练结束时返回验证损失最低的那版网络而不是最后一版。Shuffleevery-epoch打乱样本顺序避免批次间相关性。学习率衰减用 piecewise比 cosine 更直观调起来好控制。3.3 训练、验证与指标解读net trainNetwork(XTrain, YTrain, layers, opts); YPred predict(net, XTest); rmse sqrt(mean((YPred - YTest).^2)); mae mean(abs(YPred - YTest)); r2 1 - sum((YTest - YPred).^2) / sum((YTest - mean(YTest)).^2); fprintf(RMSE%.3f MAE%.3f R2%.3f\n, rmse, mae, r2);震级预测里 RMSE 到 0.3 以下算能用0.2 以下算好。R2 低于 0.7 说明模型没学到东西先查数据泄漏和归一化。MAE 比 RMSE 抗异常值两个一起看。如果 RMSE 正常但 MAE 很大说明有个别样本预测偏得离谱回去查那些样本的 P 波拾取是不是错了。4. 避坑与排查地震 CNN 训练里最容易翻车的五件事4.1 损失不下降先查标签和归一化现象训练几个 epoch 后 loss 卡在某个值不动验证 loss 还往上走。原因通常是标签没对齐或者归一化做错了。比如 P 波到时索引偏移了一位切出来的窗口全是噪声或者归一化时对整个数据集算了一个全局均值而不是逐样本逐通道。解决随机抽 10 个样本画波形图肉眼确认 P 波在窗口内的位置归一化改成逐样本逐通道代码里mean(seg,1)的维度别写错。4.2 验证集精度远高于测试集现象验证 RMSE 0.15测试 RMSE 0.45。原因几乎都是数据泄漏——按样本随机划分同一事件的不同台站样本跨了集合。解决改成按事件 ID 分组划分代码见 2.3 节。如果已经分组还这样检查验证集和测试集的事件有没有重叠用intersect查一下。4.3 模型对远震预测系统性偏大现象震中距大于 150 km 的样本预测震级普遍比真实值高 0.3 到 0.5。原因是远震高频衰减波形幅度小归一化后噪声被放大网络把噪声当成了大震的尾波。解决在输入里加一个震中距通道让网络知道距离信息或者对远震样本单独做增益补偿。我一般加距离通道简单有效。4.4 训练到一半 loss 突然变 NaN现象第 30 个 epoch 左右 loss 变 NaN训练中断。原因是学习率太大梯度爆炸。解决把初始学习率降到 1e-4加梯度裁剪。MATLAB 的trainingOptions没有直接的梯度裁剪参数可以在自定义训练循环里用dlupdate裁剪或者干脆把学习率调小、批大小调大。4.5 换个台网模型就废现象在 A 台网训练 R2 0.85拿到 B 台网测试 R2 掉到 0.4。原因是仪器响应和台基条件不同模型学到了台站特征。解决训练时做台站增广随机给波形乘一个 0.8 到 1.2 的增益因子模拟不同台站响应或者用更多台网的数据一起训练让网络学会忽略台站差异。5. 把震级预测精度再压 0.05几个我常用的进阶技巧第一个技巧是加物理约束特征。纯波形输入网络要自己学 P 波到时但到时拾取本身有成熟算法把 STA/LTA 触发点、P 波初动极性、S-P 时差这三个特征拼到全连接层前面比让卷积核硬学要快。具体做法是在globalAveragePooling1dLayer后面接一个concatenationLayer把三个标量特征和池化输出拼起来再进全连接。% 在 gap 后拼接物理特征 featLayer [ globalAveragePooling1dLayer(Name,gap) concatenationLayer(1, 2, Name, concat) fullyConnectedLayer(64, Name, fc1) reluLayer(Name, relu5) fullyConnectedLayer(1, Name, fcOut) regressionLayer(Name, reg) ]; % 需要把 layers 里 gap 之后的部分替换掉并用 dlnetwork 手动前向拼接层要求两个输入维度匹配物理特征要归一化到和池化输出同量级。这个改动在样本量大于 2000 时提升明显小于 1000 时可能过拟合慎用。第二个技巧是测试时增强TTA。对同一个测试样本做三次微小扰动——时间轴平移 ±50 ms、加 1% 高斯噪声——分别预测取三次均值。这个操作不增加训练成本测试阶段多跑两遍RMSE 一般能降 0.02 到 0.04。代价是推理时间翻三倍实时场景要权衡。技巧预期 RMSE 降幅适用样本量推理开销物理特征拼接0.03-0.062000无测试时增强0.02-0.04任意3 倍多台网联合训练0.05-0.105000无震级分层加权采样0.02-0.05不均衡时无第三个技巧是震级分层加权采样。地震样本天然不均衡小震多、大震少回归模型会偏向预测中间值。在trainingOptions里没有直接的样本权重参数我一般用自定义训练循环在计算损失时给大震样本乘一个权重权重取1/sqrt(freq)freq 是该震级档的样本频率。这个改动对 5.0 以上样本的预测精度提升最明显。最后一个习惯每次训练完把测试集预测值和真实值画散点图看残差分布。如果残差在某个震级段系统性偏正或偏负说明模型在那个段有偏差回去查那段样本的 P 波拾取质量。我踩过最深的坑就是一批 4.5 级样本的 P 波拾取用了错误的到时模型怎么调都差 0.1换掉那批标签后直接达标。数据质量永远比网络结构重要希望帮到你。本文还有配套的精品资源点击获取