第1章:特征工程——让数据“开口说话”
大家好,我是你们这堂课的主讲人。做了这么多年储能系统,我最大的感触就是:数据本身不会骗人,但原始数据也不会“说话”。你得用对方法,它才会告诉你电池哪里不对劲。
这一章,咱们就聊聊特征工程。说白了,就是把传感器采集的那些乱七八糟的电压、电流、温度数据,变成能用来做AI判断的“特征”。我个人习惯把这一步叫做“数据提纯”——去掉杂质,留下精华。
核心观点:特征工程做得好,模型训练事半功倍;做得不好,再牛的算法也白搭。
1.1 时域特征提取:看数据在时间轴上的“表情”
时域分析,就是直接看信号随时间怎么变化。我在项目中遇到过很多次,电池热失控前,电压的波动会突然变得很“暴躁”。这些信息,就藏在时域特征里。
1.1.1 均值(Mean)
均值是最基础的特征。它告诉你一段时间内,信号的中心趋势在哪。比如电池的稳态电压,正常情况下应该在一个小范围内波动。如果均值突然偏移,嗯,那就要警惕了。
import numpy as np
def extract_mean(data):
"""计算时域均值"""
return np.mean(data)
# 示例:某电池10秒内的电压采样(单位:V)
voltage_samples = [3.701, 3.702, 3.699, 3.700, 3.701, 3.698, 3.702, 3.700, 3.699, 3.701]
mean_voltage = extract_mean(voltage_samples)
print(f"均值电压: {mean_voltage:.3f} V")
1.1.2 方差(Variance)
方差衡量数据的离散程度。你想想看,如果电池内部开始短路,电压的抖动会明显加剧。方差就是捕捉这种“抖动”的利器。
def extract_variance(data):
"""计算时域方差"""
return np.var(data)
variance = extract_variance(voltage_samples)
print(f"电压方差: {variance:.6f} V²")
避坑指南:我曾经在某个项目中,直接用原始方差做特征,结果模型训练效果很差。后来发现,方差对量纲太敏感。建议先做归一化,或者用标准差代替方差。
1.1.3 峰值(Peak Value)
峰值就是信号的最大值和最小值。在储能场景里,电流的峰值往往对应着负载突变或者电池内阻变化。我记得有一次,一个电芯的电压峰值突然比正常值高了0.2V,结果第二天就出问题了。
def extract_peak(data):
"""提取峰值特征"""
return np.max(data), np.min(data)
peak_max, peak_min = extract_peak(voltage_samples)
print(f"峰值: {peak_max:.3f} V, 谷值: {peak_min:.3f} V")
1.2 频域特征提取:用FFT看数据的“频谱指纹”
时域特征看的是“表面”,频域特征看的是“内在”。为什么这么说?因为很多故障信号,在时域里看起来只是轻微抖动,但一转到频域,特征就非常明显了。
快速傅里叶变换(FFT)就是做这个的。它把时间信号拆解成不同频率的正弦波组合。每个频率的幅值,就是那个频率的“能量”。
import numpy as np
from scipy.fft import fft
def extract_fft_features(data, sampling_rate=100):
"""提取频域特征:主要频率分量及其幅值"""
n = len(data)
fft_values = fft(data)
fft_magnitude = np.abs(fft_values[:n//2]) # 取正频率部分
frequencies = np.fft.fftfreq(n, d=1/sampling_rate)[:n//2]
# 找到幅值最大的前3个频率
top_indices = np.argsort(fft_magnitude)[-3:][::-1]
top_freqs = frequencies[top_indices]
top_mags = fft_magnitude[top_indices]
return top_freqs, top_mags
# 示例:模拟一个50Hz工频干扰信号
t = np.linspace(0, 1, 100)
signal = 3.7 + 0.05 * np.sin(2 * np.pi * 50 * t) # 50Hz干扰
freqs, mags = extract_fft_features(signal)
print(f"主要频率: {freqs[0]:.1f} Hz, 幅值: {mags[0]:.4f}")
注意:FFT对采样率有要求。采样率必须满足奈奎斯特定理,否则会出现频率混叠。我建议储能系统的采样率至少设到200Hz以上,才能覆盖到100Hz以内的故障特征。
1.3 特征选择与降维:别让“噪音”干扰判断
特征提取完了,你可能得到几十甚至上百个特征。但特征不是越多越好。你想想看,如果混进去一堆无关特征,模型反而会“学歪”。
主成分分析(PCA)是我最常用的降维方法。它的核心思想很简单:找到数据变化最大的几个方向,把数据投影到这些方向上。这样既保留了主要信息,又去掉了冗余。
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
def apply_pca(feature_matrix, n_components=3):
"""使用PCA进行降维"""
# 先标准化,这一步很重要
scaler = StandardScaler()
scaled_features = scaler.fit_transform(feature_matrix)
# PCA降维
pca = PCA(n_components=n_components)
reduced_features = pca.fit_transform(scaled_features)
# 查看各主成分的方差解释率
explained_variance = pca.explained_variance_ratio_
return reduced_features, explained_variance
# 示例:假设我们有100个样本,每个样本有10个特征
import numpy as np
X = np.random.randn(100, 10)
X_reduced, variance_ratio = apply_pca(X, n_components=3)
print(f"前3个主成分解释了 {sum(variance_ratio)*100:.1f}% 的方差")
个人经验:PCA降维后,我通常会保留能解释85%以上方差的主成分。但不要死守这个数字。我在一个项目中,保留95%方差时模型效果反而更好。具体问题具体分析。
1.4 本章知识体系总览
下面这张图,是我自己梳理的特征工程整体流程。你可以把它当作一个“路线图”,做项目时对照着来。
1.5 实战要点总结
| 特征类型 | 核心方法 | 适用场景 | 注意事项 |
|---|---|---|---|
| 时域特征 | 均值、方差、峰值 | 稳态监测、突变检测 | 对噪声敏感,建议先滤波 |
| 频域特征 | FFT、功率谱密度 | 周期性故障、谐波分析 | 采样率需满足奈奎斯特定理 |
| 降维 | PCA | 高维特征压缩、去冗余 | 需先标准化,保留85%以上方差 |
最后说一句:特征工程没有标准答案。我做了这么多年,每个项目都要重新调参、重新试。别怕麻烦,多试几次,你就能找到最适合自己数据的那套方案。