第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 本章知识体系总览

下面这张图,是我自己梳理的特征工程整体流程。你可以把它当作一个“路线图”,做项目时对照着来。

特征工程知识体系 原始传感器数据 时域特征提取 频域特征提取 其他统计特征 特征融合与标准化 PCA降维(特征选择) 最终特征向量 均值、方差、峰值 FFT、主要频率分量 峰峰值、均方根等

1.5 实战要点总结

特征类型 核心方法 适用场景 注意事项
时域特征 均值、方差、峰值 稳态监测、突变检测 对噪声敏感,建议先滤波
频域特征 FFT、功率谱密度 周期性故障、谐波分析 采样率需满足奈奎斯特定理
降维 PCA 高维特征压缩、去冗余 需先标准化,保留85%以上方差

最后说一句:特征工程没有标准答案。我做了这么多年,每个项目都要重新调参、重新试。别怕麻烦,多试几次,你就能找到最适合自己数据的那套方案。


专注资料整理