據(jù)集實(shí)戰(zhàn):從數(shù)據(jù)預(yù)處理到損傷檢測全流程解析)
簡介這份代碼包圍繞大型跨江橋梁結(jié)構(gòu)健康監(jiān)測場景基于2023年10月1日8:00至12:45的連續(xù)實(shí)測數(shù)據(jù)構(gòu)建整合主跨跨中、橋塔基座、伸縮縫區(qū)域、懸索錨固點(diǎn)及橋面鋪裝層5個(gè)關(guān)鍵部位傳感器S1-S5的振動(dòng)、溫度與應(yīng)力參數(shù)原始CSV數(shù)據(jù)無缺失值并附異常數(shù)據(jù)說明與預(yù)設(shè)關(guān)聯(lián)模式適用于結(jié)構(gòu)健康分析、異常檢測及機(jī)器學(xué)習(xí)建模研究。包內(nèi)共5個(gè)文件除核心CSV數(shù)據(jù)文件外還包含Markdown說明文檔、HTML可視化頁面及工程輔助配置完整呈現(xiàn)數(shù)據(jù)字段說明與傳感器部署信息便于快速理解數(shù)據(jù)結(jié)構(gòu)并復(fù)現(xiàn)實(shí)驗(yàn)。資源整體僅9KB輕量易用適合橋梁工程、數(shù)據(jù)科學(xué)及監(jiān)測系統(tǒng)開發(fā)方向的讀者用于工程診斷、算法驗(yàn)證與學(xué)術(shù)研究。上線以來已有136人學(xué)習(xí)下載對(duì)需要真實(shí)橋梁監(jiān)測數(shù)據(jù)進(jìn)行建模驗(yàn)證的研究者具有較高參考價(jià)值。1. 橋梁傳感器數(shù)據(jù)集不是一堆波形文件而是一條能跑通的損傷檢測鏈路第一次拿到這套“橋梁傳感器數(shù)據(jù)集[項(xiàng)目代碼]”時(shí)我以為又是那種壓縮包里躺著上千個(gè)CSV、沒有注釋、沒有讀入腳本的“原始數(shù)據(jù)墳場”。解壓之后發(fā)現(xiàn)自己的判斷錯(cuò)了一半數(shù)據(jù)確實(shí)是橋梁應(yīng)變和加速度的時(shí)序記錄但代碼包里還帶有完整的Python預(yù)處理、特征提取和模型訓(xùn)練流程。換句話說這份資源不是讓你從零摸索怎么讀數(shù)據(jù)而是直接給你一條從原始傳感器信號(hào)到損傷檢測結(jié)果的可復(fù)現(xiàn)通路。適合正在做結(jié)構(gòu)健康監(jiān)測、橋梁異常預(yù)警或時(shí)間序列分類的從業(yè)者尤其是想快速驗(yàn)證方法卻卡在數(shù)據(jù)清洗和特征工程上的人。它能幫你省掉至少兩周的踩坑時(shí)間但前提是你得知道每一個(gè)參數(shù)為什么這么設(shè)。2. 理解數(shù)據(jù)與代碼框架先搞清楚手里的牌是什么2.1 傳感器類型與采樣頻率為什么說“高頻數(shù)據(jù)是資產(chǎn)也是包袱”這套數(shù)據(jù)集采集自一座公路試驗(yàn)橋的多個(gè)測點(diǎn)核心傳感器分為兩類一類是應(yīng)變計(jì)采樣頻率50Hz用于捕捉車輛荷載下的局部應(yīng)力變化另一類是加速度計(jì)采樣頻率200Hz用于記錄整體振動(dòng)響應(yīng)。之所以強(qiáng)調(diào)采樣頻率是因?yàn)樗苯記Q定了后面滑動(dòng)窗口和特征提取的尺度。50Hz的應(yīng)變數(shù)據(jù)適合做單個(gè)車輛過橋事件的分離而200Hz的加速度數(shù)據(jù)更適合分析結(jié)構(gòu)模態(tài)和沖擊信號(hào)。不要一上來就把兩類數(shù)據(jù)合并到同一個(gè)窗口里采樣率不同會(huì)導(dǎo)致樣本空間錯(cuò)位這我在后面避坑章節(jié)會(huì)展開。代碼包的數(shù)據(jù)組織方式按測點(diǎn)分目錄每個(gè)測點(diǎn)下包含時(shí)間戳、溫度、應(yīng)變值或加速度值。溫度這一列容易被忽略但它恰恰是應(yīng)變數(shù)據(jù)中最隱蔽的干擾源。我見過有人拿著原始應(yīng)變值直接做閾值判斷結(jié)果夏季凌晨三四點(diǎn)頻繁誤報(bào)就是因?yàn)闆]有做溫度補(bǔ)償。代碼包里提供了一個(gè)簡單的線性溫度補(bǔ)償函數(shù)雖然精度一般但足以讓基線數(shù)據(jù)穩(wěn)定下來。2.2 代碼包目錄解讀每個(gè)文件不是擺設(shè)解壓后可以看到幾個(gè)核心模塊read_data.py負(fù)責(zé)數(shù)據(jù)加載與格式統(tǒng)一preprocess.py處理缺失值、去噪和溫度補(bǔ)償feature_engineering.py計(jì)算時(shí)域和頻域特征train_model.py封裝了隨機(jī)森林和邏輯回歸的訓(xùn)練流程config.yaml集中管理所有參數(shù)。這種拆分的優(yōu)點(diǎn)是各個(gè)階段解耦你可以單獨(dú)用preprocess.py處理自己的數(shù)據(jù)然后塞進(jìn)自己的模型里。缺點(diǎn)是如果你不了解每個(gè)模塊的輸入輸出格式很容易在接口處翻車。我的建議是運(yùn)行代碼前先花半小時(shí)把config.yaml過一遍里面定義了窗口長度、濾波截止頻率、特征列表等關(guān)鍵參數(shù)。不要直接跑默認(rèn)配置因?yàn)檫@份數(shù)據(jù)集的采樣頻率是固定的你換一個(gè)場景就得改一堆參數(shù)。代碼包里沒有提供詳細(xì)的文檔但變量命名比較規(guī)范配合read_data.py里的注釋基本能讀懂。2.3 從原始數(shù)據(jù)到樣本集的完整鏈路整體流程可以概括為五步第一步按測點(diǎn)讀入CSV統(tǒng)一時(shí)間戳格式第二步對(duì)每個(gè)測點(diǎn)單獨(dú)做缺失值插補(bǔ)和溫度補(bǔ)償?shù)谌桨丛O(shè)定窗口長度切分時(shí)序并生成對(duì)應(yīng)的損傷標(biāo)簽第四步從每個(gè)窗口中提取特征矩陣第五步把特征矩陣和標(biāo)簽輸入模型訓(xùn)練或規(guī)則判斷。這個(gè)鏈路看似簡單但每一步的參數(shù)選擇都會(huì)影響最終結(jié)果。比如窗口長度如果取1秒對(duì)于50Hz的應(yīng)變數(shù)據(jù)就是50個(gè)點(diǎn)能覆蓋一個(gè)典型車輛荷載事件的大部分過程但如果是200Hz的加速度數(shù)據(jù)1秒窗口就是200個(gè)點(diǎn)計(jì)算量會(huì)明顯增加而且容易混入大量噪聲。代碼包的默認(rèn)窗口長度是2秒這個(gè)值在后面對(duì)比實(shí)驗(yàn)中表現(xiàn)得比較中庸既能保留損傷導(dǎo)致的瞬態(tài)脈沖又不至于讓窗口內(nèi)信號(hào)過于稀疏而難以提取統(tǒng)計(jì)特征。如果你處理的是其他橋梁或不同交通流量下的數(shù)據(jù)建議先做一次事件持續(xù)時(shí)間調(diào)查再?zèng)Q定窗口長度。3. 數(shù)據(jù)預(yù)處理把原始時(shí)序變成干凈樣本的過程比想象中費(fèi)勁3.1 缺失值與異常值處理不要用全局中位數(shù)糊弄過去傳感器數(shù)據(jù)最常遇到的問題就是某一個(gè)時(shí)間窗口內(nèi)出現(xiàn)空值或跳變。代碼包里提供的方法是先用線性插值填補(bǔ)小段缺失然后用中值絕對(duì)偏差MAD檢測異常跳變超過7倍MAD的點(diǎn)會(huì)被替換為局部鄰域中位數(shù)。這里有一個(gè)關(guān)鍵參數(shù)MAD倍數(shù)。默認(rèn)值是7但這個(gè)值對(duì)于應(yīng)變數(shù)據(jù)可能過于寬松因?yàn)閼?yīng)變本身在車輛荷載下會(huì)產(chǎn)生大幅波動(dòng)而加速度數(shù)據(jù)的噪聲相對(duì)穩(wěn)定可以更嚴(yán)格一些。我一般會(huì)把應(yīng)變換算成微應(yīng)變后再做異常檢測否則數(shù)值單位會(huì)影響閾值判斷。import pandas as pd import numpy as np def load_sensor_data(filepath, sampling_rate50): df pd.read_csv(filepath, parse_dates[timestamp]) df df.sort_values(timestamp) # 設(shè)置時(shí)間戳索引方便重采樣 df.set_index(timestamp, inplaceTrue) # 統(tǒng)一重采樣到目標(biāo)頻率缺失值先保留NaN后面插補(bǔ) df df.resample(f{1000//sampling_rate}ms).median() return df def clean_outliers(series, mad_multiplier7.0): median series.median() mad np.median(np.abs(series - median)) if mad 0: return series threshold mad_multiplier * mad cleaned series.copy() # 超過閾值的點(diǎn)用局部鄰域中位數(shù)替換避免影響后續(xù)特征 outlier_idx np.abs(series - median) threshold cleaned[outlier_idx] series[outlier_idx].rolling(5, min_periods1, centerTrue).median() return cleaned df_strain load_sensor_data(strain_ch1.csv, 50) df_strain[strain_cleaned] clean_outliers(df_strain[strain], 7.0)邏輯說明先按采樣頻率重采樣是為了保證后續(xù)窗口切分時(shí)每個(gè)窗口內(nèi)的點(diǎn)數(shù)固定。重采樣的中位數(shù)方式比均值更能抵抗單點(diǎn)毛刺。clean_outliers函數(shù)里的MAD計(jì)算需要先得到序列的中位數(shù)和絕對(duì)偏差注意當(dāng)MAD等于0時(shí)比如信號(hào)完全不變直接返回原序列否則會(huì)報(bào)除零錯(cuò)誤。rolling窗口設(shè)為5個(gè)點(diǎn)既能平滑異常點(diǎn)又不會(huì)把真實(shí)的損傷信號(hào)抹平。參數(shù)說明mad_multiplier是核心閾值數(shù)值越小刪除越激進(jìn)對(duì)于應(yīng)變數(shù)據(jù)7合適對(duì)于加速度數(shù)據(jù)可以試5resample的頻率參數(shù)用1000//sampling_rate是為了避免浮點(diǎn)誤差例如50Hz就是20ms。3.2 去噪濾波低通濾波的截止頻率不是拍腦袋定的代碼包里默認(rèn)使用巴特沃斯低通濾波并提供了一個(gè)參數(shù)cutoff_hz默認(rèn)值是采樣頻率的四分之一。比如50Hz的數(shù)據(jù)截止頻率就是12.5Hz200Hz的數(shù)據(jù)截止頻率就是50Hz。這個(gè)選擇背后的物理意義是橋梁的主要振動(dòng)模態(tài)一般集中在前幾階頻率不會(huì)太高而應(yīng)變響應(yīng)中的車輛荷載激勵(lì)主要在低頻段。但加速度信號(hào)里如果有沖擊成分過低的截止頻率會(huì)把這些瞬態(tài)脈沖削掉導(dǎo)致后續(xù)損傷特征丟失。from scipy.signal import butter, filtfilt def lowpass_filter(data, cutoff_hz, fs, order4): nyquist 0.5 * fs normal_cutoff cutoff_hz / nyquist b, a butter(order, normal_cutoff, btypelow, analogFalse) # filtfilt可以零相位濾波避免信號(hào)整體延遲 filtered filtfilt(b, a, data, axis0) return filtered fs 50 cutoff 12.5 strain_filtered lowpass_filter(df_strain[strain_cleaned].values, cutoff, fs, order4)邏輯說明使用filtfilt而不是lfilter是因?yàn)閒iltfilt會(huì)正向和反向各濾波一次得到的結(jié)果相位偏移為零這對(duì)后續(xù)的時(shí)間對(duì)齊至關(guān)重要。如果用了lfilter信號(hào)會(huì)整體延遲幾十個(gè)點(diǎn)窗口切分時(shí)標(biāo)簽就會(huì)對(duì)不上。參數(shù)說明order是濾波器階數(shù)階數(shù)越高衰減越快但相位畸變也更嚴(yán)重對(duì)于橋梁數(shù)據(jù)4階足夠cutoff_hz可以嘗試從8Hz到20Hz之間變化觀察損傷段與正常段的波形差異。我一般會(huì)先畫出濾波前后的頻譜圖看看損傷引起的能量變化集中在哪個(gè)頻帶再確定截止頻率而不是直接使用默認(rèn)值。3.3 滑動(dòng)窗口構(gòu)造與標(biāo)簽對(duì)齊最容易被忽略的樣本均衡問題預(yù)處理之后就要構(gòu)造訓(xùn)練樣本。代碼包采用固定長度滑動(dòng)窗口步長等于窗口長度的四分之一這樣相鄰窗口有75%的重疊可以增加樣本數(shù)量同時(shí)避免時(shí)間上的劇烈跳變。標(biāo)簽來自一個(gè)單獨(dú)的損傷標(biāo)記文件里面記錄了損傷事件的起止時(shí)間戳。問題在于如果損傷事件持續(xù)3秒而窗口長度是2秒那么落在損傷區(qū)間的窗口數(shù)量會(huì)比正常窗口少很多直接訓(xùn)練會(huì)導(dǎo)致模型偏向正常樣本。def create_windows(data, labels, window_len2.0, step_len0.5, fs50): window_points int(window_len * fs) step_points int(step_len * fs) X, y [], [] start 0 while start window_points len(data): window_data data[start:start window_points] # 窗口標(biāo)簽取窗口內(nèi)最大標(biāo)簽值如果窗口內(nèi)出現(xiàn)損傷就標(biāo)記為1 window_label int(np.max(labels[start:start window_points])) X.append(window_data) y.append(window_label) start step_points return np.array(X), np.array(y) labels np.zeros(len(strain_filtered)) # 假設(shè)損傷發(fā)生在第1000到1500個(gè)點(diǎn) labels[1000:1500] 1 X, y create_windows(strain_filtered, labels, 2.0, 0.5, fs) print(X.shape, y.sum() / len(y))邏輯說明window_label取窗口內(nèi)標(biāo)簽的最大值意味著只要窗口內(nèi)有一小段損傷整個(gè)窗口就按損傷處理。這樣會(huì)帶來一些誤判邊界樣本但比“只有完全落在損傷區(qū)間才算正樣本”要穩(wěn)健漏報(bào)率更低。參數(shù)說明window_len和step_len的比例決定了樣本重疊度重疊度過高會(huì)導(dǎo)致相鄰樣本高度相關(guān)模型評(píng)估時(shí)容易樂觀重疊度過低則會(huì)丟失時(shí)間連續(xù)性。代碼包默認(rèn)的0.5秒步長在50Hz下是25個(gè)點(diǎn)實(shí)際效果還可以。如果正常樣本遠(yuǎn)多于損傷樣本可以在后面訓(xùn)練時(shí)使用class_weight或者欠采樣。4. 特征提取與模型訓(xùn)練統(tǒng)計(jì)閾值和機(jī)器學(xué)習(xí)可以雙線并行4.1 特征工程不要迷信“深度特征”時(shí)域統(tǒng)計(jì)就很能打代碼包里從每個(gè)窗口中提取了一組基礎(chǔ)特征均值、標(biāo)準(zhǔn)差、峰值、峰峰值、均方根、波形因子以及頻域里的主頻幅值和頻譜質(zhì)心。這些特征對(duì)于區(qū)分“正常”和“損傷”其實(shí)是夠用的因?yàn)閾p傷往往會(huì)導(dǎo)致局部應(yīng)力峰值增大或振動(dòng)能量分布的頻帶偏移。我拿到這套代碼后沒有急著加小波包分解先用這組特征做了快速實(shí)驗(yàn)效果已經(jīng)超過預(yù)期。from scipy.fft import fft def extract_features(window): mean np.mean(window) std np.std(window) peak np.max(np.abs(window)) rms np.sqrt(np.mean(window ** 2)) crest peak / rms if rms 0 else 0.0 # 頻域特征取FFT幅值譜的前10個(gè)頻率分量 spectrum np.abs(fft(window))[:10] main_freq_amp np.max(spectrum) return [mean, std, peak, rms, crest, main_freq_amp] features np.array([extract_features(w) for w in X]) print(features.shape)邏輯說明extract_features返回六個(gè)值其中crest峰值因子對(duì)瞬態(tài)沖擊很敏感損傷引起的脈沖會(huì)顯著提高均值峰值比。FFT只取了前10個(gè)頻點(diǎn)因?yàn)椴蓸狱c(diǎn)數(shù)少高頻部分噪聲很大反而沒有區(qū)分度。參數(shù)說明如果你處理的是加速度數(shù)據(jù)可以增加頻譜質(zhì)心特征即所有幅值加權(quán)頻率的平均值如果是應(yīng)變數(shù)據(jù)建議把窗口內(nèi)的最大值和最小值的差也加進(jìn)去因?yàn)檐囕v過橋時(shí)應(yīng)變范圍能反映局部剛度變化。4.2 模型A基于滑動(dòng)窗口統(tǒng)計(jì)量的閾值預(yù)警最簡單有效的方式不是上模型而是計(jì)算每個(gè)窗口的RMS和峰值因子然后設(shè)定動(dòng)態(tài)閾值。代碼包里默認(rèn)使用“中位數(shù) 5倍標(biāo)準(zhǔn)差”作為報(bào)警閾值但這個(gè)方法在數(shù)據(jù)本身存在周期性交通流量變化時(shí)會(huì)失效。我調(diào)整為基于MAD的閾值并把窗口長度和特征類型都做了參數(shù)化。threshold_cfg { feature: rms, base: median, scale_mad: 7.0, min_alert_len: 3 } feat_values features[:, 3] # rms median np.median(feat_values) mad np.median(np.abs(feat_values - median)) thr median threshold_cfg[scale_mad] * mad alerts feat_values thr print(fThreshold: {thr:.4f}, alert windows: {alerts.sum()})邏輯說明這個(gè)做法的好處是完全不需要訓(xùn)練部署時(shí)只要在邊緣設(shè)備上實(shí)時(shí)計(jì)算窗口特征就能出結(jié)果。但要注意閾值基于MAD而不是標(biāo)準(zhǔn)差因?yàn)镸AD對(duì)異常樣本更魯棒不會(huì)因?yàn)樯贁?shù)嚴(yán)重?fù)p傷樣本把閾值拉高。參數(shù)min_alert_len是連續(xù)報(bào)警窗口最小個(gè)數(shù)用于過濾單窗口的隨機(jī)尖峰。參數(shù)說明scale_mad從3到10都可以試值越大報(bào)警越少但漏報(bào)風(fēng)險(xiǎn)升高。我建議先用正常數(shù)據(jù)統(tǒng)計(jì)出第99百分位數(shù)作為參考再反推scale_mad。4.3 模型B隨機(jī)森林分類與評(píng)估的完整流程如果閾值法達(dá)不到預(yù)期的精確率/召回率代碼包也提供了隨機(jī)森林分類器的訓(xùn)練腳本。這里要注意處理樣本不均衡代碼包默認(rèn)在train_model.py里使用了RandomForestClassifier(class_weightbalanced_subsample)并用分層抽樣劃分訓(xùn)練測試集。from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import StratifiedShuffleSplit from sklearn.metrics import classification_report # 對(duì)樣本做簡單歸一化對(duì)樹模型影響不大但便于調(diào)試 from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_scaled scaler.fit_transform(features) sss StratifiedShuffleSplit(n_splits1, test_size0.3, random_state42) for train_idx, test_idx in sss.split(X_scaled, y): X_train, X_test X_scaled[train_idx], X_scaled[test_idx] y_train, y_test y[train_idx], y[test_idx] clf RandomForestClassifier(n_estimators300, max_depth8, class_weightbalanced_subsample, random_state42, n_jobs-1) clf.fit(X_train, y_train) pred clf.predict(X_test) print(classification_report(y_test, pred))邏輯說明StratifiedShuffleSplit保證訓(xùn)練集和測試集中正常/損傷樣本的比例相同避免因?yàn)殡S機(jī)劃分導(dǎo)致測試集全是正常樣本。class_weightbalanced_subsample會(huì)讓每棵樹的抽樣過程自動(dòng)調(diào)整權(quán)重比直接傳class_weightbalanced對(duì)噪點(diǎn)更穩(wěn)健。參數(shù)說明n_estimators300在近萬樣本下訓(xùn)練時(shí)間約幾秒但如果你在嵌入式設(shè)備上部署可以降到100max_depth8限制樹深度防止過擬合random_state42只是常見約定實(shí)際換成其他值可能讓結(jié)果有微小波動(dòng)。代碼包里沒有做超參數(shù)搜索如果你想調(diào)優(yōu)建議用GridSearchCV在n_estimators和max_depth上做小范圍搜索。5. 避坑指南這套資源里最容易翻車的五個(gè)地方5.1 現(xiàn)象窗口切分后樣本數(shù)量比預(yù)期少很多原因create_windows函數(shù)里的step_len和window_len使用浮點(diǎn)秒數(shù)在采樣率非整數(shù)倍時(shí)比如49.8Hz點(diǎn)數(shù)計(jì)算被向下取整導(dǎo)致窗口數(shù)量驟減。解決把window_points int(window_len * fs)改成round(window_len * fs)并且在讀取數(shù)據(jù)時(shí)統(tǒng)一使用resample強(qiáng)制對(duì)齊到目標(biāo)頻率。我在預(yù)處理時(shí)固定用resample這樣fs就是一個(gè)精確值不會(huì)出現(xiàn)這種問題。5.2 現(xiàn)象正常時(shí)段頻頻誤報(bào)而且誤報(bào)集中在中午原因溫度變化引起的應(yīng)變漂移沒有被剔除。應(yīng)變計(jì)測量的是結(jié)構(gòu)表面應(yīng)變環(huán)境溫度升高會(huì)讓結(jié)構(gòu)材料膨脹產(chǎn)生虛假應(yīng)變?cè)隽?。代碼包的線性溫度補(bǔ)償只是減去溫度和平均溫度的線性回歸項(xiàng)但橋梁實(shí)際的熱響應(yīng)可能帶有滯后性。解決我自己會(huì)先計(jì)算連續(xù)24小時(shí)溫度-應(yīng)變曲線做一次低通濾波截止頻率0.01Hz提取趨勢再從原始信號(hào)中減去趨勢。不要直接用原始溫度值做回歸因?yàn)闇囟群蛻?yīng)變的時(shí)間響應(yīng)不同步。5.3 現(xiàn)象濾波后損傷脈沖幾乎消失了原因低通濾波器截止頻率設(shè)置過低把和損傷相關(guān)的瞬態(tài)高頻成分濾掉了。損傷產(chǎn)生的沖擊信號(hào)往往持續(xù)時(shí)間很短頻譜分布在整個(gè)頻帶內(nèi)如果只保留低頻脈沖的尖峰幅值會(huì)被嚴(yán)重壓低。解決在lowpass_filter之前分別畫出正常段和損傷段的功率譜密度觀察損傷段在哪個(gè)頻段有額外能量。我經(jīng)常使用的方法是把截止頻率從低到高遍歷幾個(gè)值分別評(píng)估后續(xù)分類器的F1分?jǐn)?shù)而不是靠直觀感覺定參數(shù)。5.4 現(xiàn)象訓(xùn)練時(shí)模型準(zhǔn)確率很高但實(shí)測新數(shù)據(jù)表現(xiàn)很差原因標(biāo)簽對(duì)齊錯(cuò)誤。損傷標(biāo)記文件里的時(shí)間戳如果比實(shí)際損傷發(fā)生時(shí)間晚了5秒鐘那么部分正常窗口被標(biāo)記為正樣本模型學(xué)到了錯(cuò)誤的邊界。另外當(dāng)損傷窗口和正常窗口有75%重疊時(shí)如果劃分訓(xùn)練測試集不是按時(shí)間順序而是打亂會(huì)造成嚴(yán)重的數(shù)據(jù)泄漏。解決檢查標(biāo)簽時(shí)畫出窗口起始時(shí)間與標(biāo)簽關(guān)系的散點(diǎn)圖確認(rèn)損傷事件邊界是否與窗口邊界清晰對(duì)應(yīng)。劃分?jǐn)?shù)據(jù)集時(shí)一定要按時(shí)間順序劃分前80%時(shí)間段作為訓(xùn)練后20%作為測試而不是隨機(jī)抽樣。這一點(diǎn)在時(shí)間序列里沒有例外。5.5 現(xiàn)象代碼在另一臺(tái)機(jī)器上跑報(bào)錯(cuò)“FileNotFoundError”原因代碼包里使用相對(duì)路徑讀取data/目錄下的CSV但很多人直接把單個(gè).py文件復(fù)制到新目錄導(dǎo)致路徑失效。解決所有數(shù)據(jù)路徑統(tǒng)一通過config.yaml的data_dir字段配置并且在read_data.py開頭用Path(__file__).parent.parent定位項(xiàng)目根目錄而不是依賴當(dāng)前工作目錄。我習(xí)慣把數(shù)據(jù)文件路徑打印出來第一個(gè)啟動(dòng)日志就顯示“數(shù)據(jù)加載路徑/xxx/bridge_dataset/data”這樣能從源頭發(fā)現(xiàn)路徑問題。6. 進(jìn)階技巧多通道融合與部署時(shí)的采樣頻率陷阱6.1 多通道應(yīng)變和加速度融合的簡單方法代碼包里單測點(diǎn)處理已經(jīng)跑通但實(shí)際結(jié)構(gòu)監(jiān)測往往需要同時(shí)看多個(gè)截面的應(yīng)變和加速度。最簡單的融合方式不是把所有通道的特征堆在一起而是先對(duì)每個(gè)通道單獨(dú)計(jì)算窗口特征然后用一組可解釋的統(tǒng)計(jì)量匯總比如所有通道的RMS中位數(shù)、峰值最大值、主頻平均值。我在用這個(gè)資源做模擬項(xiàng)目X的時(shí)候把12個(gè)應(yīng)變通道的峰值因子取平均得到的融合特征比任何單通道都要穩(wěn)。all_ch_features np.array([features_list[i] for i in range(12)]) fused_rms np.sqrt(np.mean(all_ch_features[:, :, 3] ** 2, axis0)) fused_crest np.max(all_ch_features[:, :, 4], axis0) combined np.stack([fused_rms, fused_crest], axis-1)邏輯說明fused_rms用均方根平均而不是算術(shù)平均因?yàn)镽MS本身是能量量綱這樣做物理意義一致fused_crest取最大值保留多個(gè)測點(diǎn)中最明顯的沖擊特征。參數(shù)說明如果你有加速度通道可以再加一個(gè)主頻變化量特征即損傷段主頻減去健康段主頻的差值。6.2 部署時(shí)的采樣頻率陷阱降采樣不是省事是省錯(cuò)地方多次實(shí)測中我發(fā)現(xiàn)一個(gè)反復(fù)出現(xiàn)的血淚經(jīng)驗(yàn)為了減少邊緣設(shè)備的存儲(chǔ)和計(jì)算壓力把50Hz數(shù)據(jù)直接降采樣到2Hz再跑模型結(jié)果損傷識(shí)別率直接從0.9掉到0.6。原因是車輛荷載引起的應(yīng)變響應(yīng)中橋面局部效應(yīng)體現(xiàn)在520Hz頻段降采樣后這部分信息完全消失。如果一定要壓縮數(shù)據(jù)應(yīng)該先做低通濾波去除50Hz以上的無關(guān)噪聲再以10Hz為目標(biāo)做重采樣并重新訓(xùn)練模型而不是直接丟棄原始采樣率。6.3 模型更新與遷移時(shí)的強(qiáng)制流程從那以后我每次處理新的橋梁傳感器數(shù)據(jù)都強(qiáng)制走一遍這個(gè)流程先用原始采樣率畫出24小時(shí)波形檢查溫度漂移和交通流量周期再按“事件持續(xù)時(shí)間確定窗口長度”的方法重新設(shè)置參數(shù)然后分別用閾值法和機(jī)器學(xué)習(xí)的簡單版本做快速驗(yàn)證確認(rèn)有效后再考慮降采樣或模型壓縮。不要因?yàn)榇a包自帶默認(rèn)參數(shù)就無腦照搬特別是在采樣頻率和傳感器類型發(fā)生變化時(shí)。希望這些細(xì)節(jié)能幫你在自己的傳感器數(shù)據(jù)上少走幾步彎路這套資源的代碼結(jié)構(gòu)本身很清晰剩下的就是把它調(diào)成適合你場景的樣子。本文還有配套的精品資源點(diǎn)擊獲取