3. 特征工程(上):从充放电曲线中提取健康特征
各位同学,欢迎来到特征工程部分。说实话,在电池寿命预测这个领域,我见过太多人一上来就扔模型、调参数,结果效果惨不忍睹。为什么?因为特征没做好。你想想看,模型再厉害,喂进去的是垃圾,出来的还是垃圾。
这一章,我们聊聊怎么从最原始的充放电曲线里,挖出那些真正能反映电池健康状态的特征。我个人习惯把这部分叫做「黄金特征」,因为它们直接和电池的老化机制挂钩。
3.1 恒流充电时间:最直观的退化信号
先说说恒流充电时间。这个特征简单到让人容易忽略,但它真的很有用。我参与过一个电动大巴的项目,当时就是靠这个特征提前两周预警了电池组的异常。
恒流充电时间,就是电池在 CC 阶段从起始电压充到截止电压所花的时间。随着电池老化,内阻增加,这个时间会明显缩短。为什么?因为老电池更容易达到电压上限,提前进入恒压阶段。
提取方法很简单,直接从充电曲线里找 CC 阶段的起止点就行:
import pandas as pd
import numpy as np
def extract_cct(charge_data):
"""
提取恒流充电时间
charge_data: DataFrame, 包含 'time', 'current', 'voltage' 列
"""
# 找到电流稳定的 CC 阶段
cc_mask = (charge_data['current'] > 0.9 * charge_data['current'].max())
# 计算 CC 阶段时长
cc_start = charge_data[cc_mask]['time'].iloc[0]
cc_end = charge_data[cc_mask]['time'].iloc[-1]
cct = cc_end - cc_start
return cct
3.2 恒压充电容量:隐藏的内阻探针
接下来是恒压充电容量。这个特征很有意思——它反映的是电池在 CV 阶段还能「吃」进去多少电。
新电池内阻小,CC 阶段就能充进去大部分容量,CV 阶段很短。老电池呢?内阻大了,CC 阶段充不满,只能靠 CV 阶段慢慢补。所以 CV 容量会随着老化逐渐增加。
我记得有一次做数据分析,发现某批电池的 CV 容量突然飙升。当时就觉得不对劲,一查果然是电解液出了问题。这个特征就像个探针,能帮你提前发现内部异常。
| 健康状态 | CC 时间 | CV 容量 | 物理含义 |
|---|---|---|---|
| 新电池 | 长(~45min) | 小(<5% 总容量) | 内阻小,离子传输顺畅 |
| 中度老化 | 中等(~35min) | 中等(~10% 总容量) | 内阻增加,SEI 膜增厚 |
| 严重老化 | 短(<25min) | 大(>15% 总容量) | 活性锂损失,结构退化 |
def extract_cv_capacity(charge_data):
"""
提取恒压充电容量
"""
# 找到 CV 阶段(电流下降阶段)
cv_mask = (charge_data['current'] < 0.1 * charge_data['current'].max()) & \
(charge_data['voltage'] >= charge_data['voltage'].max() * 0.99)
# 积分计算 CV 容量
cv_capacity = np.trapz(charge_data[cv_mask]['current'],
charge_data[cv_mask]['time'])
return cv_capacity
3.3 电压平台变化:电池的「心电图」
电压平台,说白了就是电池在充放电过程中电压相对平稳的那段区间。新电池的电压平台很平坦,老电池的平台会逐渐倾斜、缩短。
我个人喜欢用中值电压来量化这个变化。中值电压就是充到一半容量时的电压值。随着老化,这个值会逐渐下降。你可以把它想象成电池的「血压」——数值变了,说明内部出问题了。
def extract_median_voltage(charge_data):
"""
提取中值电压
"""
# 计算累计容量
capacity = np.cumsum(np.gradient(charge_data['time']) * charge_data['current'])
capacity_normalized = capacity / capacity.max()
# 找到 50% SOC 对应的电压
median_voltage = np.interp(0.5, capacity_normalized, charge_data['voltage'])
return median_voltage
3.4 差分电压分析(DVA):看透电池的「内脏」
终于到了 DVA。这个技术是我最想安利给各位的。它就像给电池做 CT 扫描,能让你看到正负极材料相变的过程。
DVA 的核心思想很简单:计算 dV/dQ,也就是电压对容量的导数。每个峰值对应一个相变反应。随着老化,这些峰值的位置、高度、宽度都会变化。
嗯,这里要注意一点:DVA 对噪声非常敏感。原始数据直接求导,出来的曲线跟心电图似的,根本没法看。所以一定要先做平滑处理。
from scipy.signal import savgol_filter
def compute_dva(charge_data, window_length=21, polyorder=3):
"""
计算差分电压曲线
"""
# 先对电压做平滑
voltage_smooth = savgol_filter(charge_data['voltage'],
window_length, polyorder)
# 计算容量增量
dq = np.gradient(charge_data['capacity'])
dv = np.gradient(voltage_smooth)
# 避免除零
dv[dv == 0] = np.nan
dva = dq / dv
return charge_data['capacity'], dva
- 峰值位置: 反映相变反应的起始点,老化后向右偏移
- 峰值高度: 反映反应活性,老化后降低
- 峰值宽度: 反映反应均匀性,老化后变宽
我在实际项目中,通常会把 DVA 曲线的峰值位置和高度作为特征输入到模型中。效果比直接用原始电压曲线好得多。说白了,DVA 帮你把复杂的电化学过程浓缩成了几个关键数字,模型学起来自然更轻松。
好了,这一章的内容就到这里。我们讲了恒流充电时间、恒压充电容量、电压平台变化和 DVA 这四个核心特征。下一章我们会继续聊剩下的特征提取方法,包括 IC 曲线、增量容量分析等更高级的技术。
公众号:蓝海资料掘金营,微信deep3321