4、特征工程(上):从充放电曲线提取特征
各位同学,咱们今天聊聊特征工程。说实话,在BMS算法里,特征工程比模型本身更吃功夫。我见过太多人拿着原始电压电流数据就往模型里塞,结果效果惨不忍睹。说白了,你给模型喂什么,它就学什么——喂的是垃圾,吐出来的也是垃圾。
这一章,咱们重点讲三个最常用的特征:恒流充电时间、电压平台斜率、增量容量分析(ICA)。这三个特征,是我在项目里用得最多的,也是最能反映电池老化状态的。
4.1 恒流充电时间(CC Charging Time)
先说说最简单的——恒流充电时间。你想想看,电池在恒流充电阶段,从起始电压充到截止电压,需要多长时间?这个时间会随着电池老化而缩短。
为什么?因为内阻增大了,极化电压升高了,电池更快地达到了截止电压。我在某车企的项目里遇到过,同一款电池,新电池恒流充电时间约45分钟,老化到80% SOH时,只剩32分钟。这个特征非常敏感。
提取方法很简单:
# 提取恒流充电时间
def extract_cc_time(df):
"""
df: 包含时间、电流、电压的DataFrame
返回:恒流充电时长(秒)
"""
# 找到恒流充电阶段(电流稳定在某个正值)
cc_mask = (df['current'] > 0.5) # 假设恒流充电电流 > 0.5A
cc_periods = df[cc_mask]
if len(cc_periods) == 0:
return 0
# 计算持续时间
start_time = cc_periods['time'].iloc[0]
end_time = cc_periods['time'].iloc[-1]
cc_duration = end_time - start_time
return cc_duration
这里有个坑——起始电压不一致。如果两次充电的起始电压不同,恒流充电时间就没法直接比较。我建议统一归一化到相同的SOC区间,比如从20% SOC充到80% SOC。
4.2 电压平台斜率(Voltage Plateau Slope)
接下来是电压平台斜率。这个特征主要针对磷酸铁锂(LFP)电池。LFP电池的电压曲线有个特点——中间有一段很平的平台区。随着老化,这个平台会逐渐倾斜。
说白了,新电池的电压平台几乎是平的,斜率接近0。老电池的平台会向上翘或者向下弯。我测量的是平台区中间段的电压变化率。
提取步骤:
- 找到恒流充电的电压曲线
- 确定平台区范围(通常是SOC 20%-80%之间)
- 对平台区做线性拟合,斜率就是特征值
import numpy as np
from sklearn.linear_model import LinearRegression
def extract_plateau_slope(df, soc_min=20, soc_max=80):
"""
提取电压平台斜率
"""
# 假设已有SOC列
plateau_mask = (df['soc'] >= soc_min) & (df['soc'] <= soc_max)
plateau_data = df[plateau_mask]
# 用容量(或时间)作为x,电压作为y
x = plateau_data['capacity'].values.reshape(-1, 1) # 累计容量
y = plateau_data['voltage'].values
# 线性拟合
model = LinearRegression()
model.fit(x, y)
slope = model.coef_[0] # 斜率,单位 V/Ah
return slope
嗯,这里要注意——平台区的定义。不同电池的平台区范围不一样。三元锂电池的平台区就很短,甚至没有明显的平台。所以这个特征主要针对LFP电池。我在做三元电池项目时,基本不用这个特征。
4.3 增量容量分析(ICA)
终于到了重头戏——ICA。这是我最喜欢的特征提取方法,没有之一。ICA的全称是Incremental Capacity Analysis,说白了就是看dQ/dV曲线。
为什么ICA这么牛?因为电压曲线上的微小变化,在dQ/dV曲线上会被放大。电池内部的相变过程、活性物质损失、锂离子消耗,都会在ICA曲线上留下明显的峰和谷。
我举个例子:新电池的ICA曲线有三个明显的峰,分别对应不同的电化学反应。随着老化,这些峰会降低、变宽、甚至消失。通过追踪这些峰的变化,就能判断电池的失效模式。
计算步骤:
- 获取恒流充电的电压-容量曲线
- 对电压进行等间隔采样(比如每10mV一个点)
- 计算dQ/dV = 容量变化量 / 电压变化量
- 平滑处理,去除噪声
def compute_ica(voltage, capacity, voltage_step=0.01):
"""
计算ICA曲线
voltage: 电压数组 (V)
capacity: 容量数组 (Ah)
voltage_step: 电压步长 (V)
"""
# 对电压进行等间隔插值
v_min = np.floor(voltage.min() * 100) / 100
v_max = np.ceil(voltage.max() * 100) / 100
v_grid = np.arange(v_min, v_max, voltage_step)
# 插值得到对应容量
cap_interp = np.interp(v_grid, voltage, capacity)
# 计算dQ/dV
dq = np.diff(cap_interp)
dv = np.diff(v_grid)
ica = dq / dv
# 返回电压中点和ICA值
v_mid = (v_grid[:-1] + v_grid[1:]) / 2
return v_mid, ica
从ICA曲线中,我们可以提取以下特征:
| 特征名称 | 物理含义 | 老化趋势 |
|---|---|---|
| 峰1位置(电压) | 对应负极石墨的嵌锂阶段 | 向高电压方向移动 |
| 峰1高度(dQ/dV值) | 该阶段的容量贡献 | 逐渐降低 |
| 峰2位置(电压) | 对应正极的相变过程 | 基本不变 |
| 峰2高度(dQ/dV值) | 该阶段的容量贡献 | 逐渐降低 |
| 峰谷差值 | 反映极化内阻变化 | 差值增大 |
另外,ICA对数据质量要求很高。如果充电电流不稳定,或者温度波动大,ICA曲线会严重失真。我一般只使用恒流充电段的数据,而且要求电流波动在±1%以内。
4.4 三个特征的对比与选择
最后,我给大家总结一下这三个特征的适用场景:
- 恒流充电时间:简单粗暴,适合快速评估。但受温度和起始SOC影响大,需要做归一化。
- 电压平台斜率:专门针对LFP电池。如果做三元电池项目,可以跳过这个特征。
- ICA特征:信息量最大,能反映失效模式。但计算复杂,对数据质量要求高。
我个人习惯是:先用恒流充电时间做快速筛选,再用ICA做深度分析。如果项目时间紧,只提取恒流充电时间也能达到80%的效果。但如果你想发论文或者做高精度预测,ICA是绕不开的。
好了,这一章就到这里。下一章咱们继续讲特征工程的下半部分——从电压弛豫曲线和阻抗谱中提取特征。到时候我会分享一些我在实际项目中踩过的坑,保证让你少走弯路。