第三章 特征工程(上):从充放电曲线提取健康特征

好,咱们进入正题。上一章我们聊了数据清洗,把那些脏数据、异常数据都处理干净了。但光有干净数据还不够,你想想看,原始电压电流曲线直接扔给模型,它根本看不懂。我们需要把这些原始信号翻译成模型能理解的「健康特征」。

这一章,我重点讲两个最经典的特征提取方法:IC曲线(增量容量分析)DV曲线(差分电压分析)。这两个方法,说白了就是把充放电曲线上的微小变化放大,让电池的老化痕迹无处遁形。

核心观点:IC/DV曲线是电池健康状态的「指纹」。不同老化程度下,曲线的峰位、峰高、峰面积都会发生规律性变化。抓住这些变化,就能预测SOH。

3.1 为什么需要IC/DV曲线?

直接看电压-容量曲线,你能看出什么?

嗯,一条平滑的曲线,随着充放电进行,电压缓慢变化。新电池和旧电池的曲线看起来差不多,只是稍微偏移了一点。这点偏移量,肉眼很难分辨,模型也很难学到有效特征。

但如果我们对容量求微分呢?

dQ/dV,也就是IC曲线。它把电压平台上那些微小的容量变化放大成明显的峰值。每个峰值对应一个电化学反应阶段。电池老化后,活性物质损失、内阻增加,这些峰值就会变矮、变宽、甚至移位。

我在项目中遇到过这样的情况:用原始电压曲线做特征,模型精度只有85%左右。换成IC曲线特征后,直接跳到93%。差别就这么大。

3.2 增量容量分析(IC曲线)

3.2.1 数学原理

IC曲线的定义很简单:

IC = dQ / dV ≈ ΔQ / ΔV

其中Q是容量,V是电压。我们取相邻两个采样点的容量差除以电压差,就得到IC值。

但这里有个坑——噪声放大。微分操作对噪声极其敏感。原始数据里哪怕有1mV的波动,微分后可能变成一个大尖峰。所以,计算IC曲线前,必须做平滑处理。

我曾经踩过的坑:第一次做IC曲线时,没做平滑,直接微分。结果出来的曲线像心电图一样,全是毛刺,根本没法用。后来花了整整两天调平滑参数才搞定。记住:先平滑,再微分

3.2.2 计算步骤与代码

我个人的习惯是分三步走:

  1. 数据重采样:把充放电数据按电压间隔均匀采样,比如每10mV取一个点
  2. 平滑滤波:用Savitzky-Golay滤波器或移动平均,去除高频噪声
  3. 数值微分:用中心差分法计算dQ/dV

来看代码:

import numpy as np
import pandas as pd
from scipy.signal import savgol_filter

def compute_ic_curve(voltage, capacity, voltage_step=0.01, window_length=11, polyorder=3):
    """
    计算IC曲线
    voltage: 电压序列 (V)
    capacity: 容量序列 (Ah)
    voltage_step: 重采样电压间隔 (V)
    window_length: SG滤波器窗口长度(必须为奇数)
    polyorder: SG滤波器多项式阶数
    """
    # 1. 按电压间隔重采样
    v_min = np.floor(voltage.min() / voltage_step) * voltage_step
    v_max = np.ceil(voltage.max() / voltage_step) * voltage_step
    v_bins = np.arange(v_min, v_max + voltage_step, voltage_step)
    
    # 用插值法获取等电压间隔的容量
    v_resampled = v_bins
    cap_resampled = np.interp(v_resampled, voltage, capacity)
    
    # 2. 平滑处理
    cap_smooth = savgol_filter(cap_resampled, window_length, polyorder)
    
    # 3. 计算微分
    dq = np.diff(cap_smooth)
    dv = np.diff(v_resampled)
    ic = dq / dv
    
    # 返回IC曲线(电压取中点)
    v_ic = (v_resampled[:-1] + v_resampled[1:]) / 2
    
    return v_ic, ic

小技巧:window_length和polyorder怎么选?我一般先用window_length=11, polyorder=3试跑。如果曲线还有毛刺,就增大window_length;如果曲线过于平滑丢失了峰值,就减小window_length或增大polyorder。多试几次就有手感了。

3.2.3 从IC曲线提取特征

IC曲线出来后,我们要从中提取量化特征。常用的有:

特征名称 物理含义 与老化的关系
峰值位置(电压) 电化学反应发生的电压 随老化向右偏移(内阻增加)
峰值高度 反应速率/容量贡献 随老化降低(活性物质损失)
峰值半高宽 反应均匀性 随老化变宽(反应不均匀)
峰面积 该阶段贡献的容量 随老化减小

提取这些特征,可以用scipy.signal的find_peaks函数:

from scipy.signal import find_peaks

def extract_ic_features(v_ic, ic):
    """从IC曲线提取峰值特征"""
    # 找峰值(只找正峰值)
    peaks, properties = find_peaks(ic, prominence=0.1, width=5)
    
    features = {}
    for i, peak_idx in enumerate(peaks):
        features[f'peak_{i+1}_voltage'] = v_ic[peak_idx]
        features[f'peak_{i+1}_height'] = ic[peak_idx]
        features[f'peak_{i+1}_width'] = properties['widths'][i] * (v_ic[1] - v_ic[0])
        # 峰面积用梯形法近似
        left = int(properties['left_bases'][i])
        right = int(properties['right_bases'][i])
        features[f'peak_{i+1}_area'] = np.trapz(ic[left:right], v_ic[left:right])
    
    return features

3.3 差分电压分析(DV曲线)

3.3.1 DV曲线与IC曲线的关系

DV曲线是IC曲线的倒数:DV = dV/dQ。它反映的是电压随容量变化的速率。

说白了,IC曲线看的是「容量对电压的敏感度」,DV曲线看的是「电压对容量的敏感度」。两者是互补的。

我个人更喜欢用IC曲线,因为它的峰值更明显。但有些场景下,DV曲线也有独特优势——比如在充电末期,电压快速上升,DV曲线能更清晰地反映极化内阻的变化。

3.3.2 计算DV曲线

计算方法和IC曲线类似,只是微分方向反过来:

def compute_dv_curve(voltage, capacity, capacity_step=0.01, window_length=11, polyorder=3):
    """计算DV曲线"""
    # 按容量间隔重采样
    c_min = np.floor(capacity.min() / capacity_step) * capacity_step
    c_max = np.ceil(capacity.max() / capacity_step) * capacity_step
    c_bins = np.arange(c_min, c_max + capacity_step, capacity_step)
    
    v_resampled = np.interp(c_bins, capacity, voltage)
    v_smooth = savgol_filter(v_resampled, window_length, polyorder)
    
    dv = np.diff(v_smooth)
    dq = np.diff(c_bins)
    dv_curve = dv / dq
    
    c_dv = (c_bins[:-1] + c_bins[1:]) / 2
    return c_dv, dv_curve

3.3.3 DV曲线的特征提取

DV曲线的特征和IC曲线类似,但关注点不同:

  • 谷值位置:对应IC曲线的峰值位置,反映反应阶段
  • 谷值深度:反映该阶段的电压变化速率
  • 曲线斜率:在充电末期,斜率急剧增大,反映极化加剧

实战经验:我一般同时计算IC和DV曲线,然后取两者的特征做融合。IC曲线对活性物质损失敏感,DV曲线对内阻变化敏感。两者结合,能更全面地刻画电池老化状态。

3.4 实操中的注意事项

嗯,这里要重点说几个坑:

  1. 数据质量是第一位的:如果原始数据有缺失或异常,IC/DV曲线会一塌糊涂。先做好数据清洗再提取特征。
  2. 平滑参数要调优:不同电池、不同倍率下,最优的平滑参数不同。我建议做一个参数扫描,选使曲线峰值最清晰的参数。
  3. 注意充放电倍率的影响:大倍率充放电时,极化效应会扭曲IC/DV曲线。最好用同一倍率的数据做对比。
  4. 温度补偿:温度对IC/DV曲线影响很大。如果数据来自不同温度,建议先做温度归一化。

我曾经犯过的错:有一次用不同温度下的数据直接提取IC特征,结果模型训练出来完全不准。后来发现,25°C和45°C下的IC峰值位置差了将近50mV。从那以后,我每次都会检查数据温度是否一致,或者做温度补偿。

3.5 本章小结

这一章我们讲了:

  • 为什么需要IC/DV曲线——放大老化信号
  • IC曲线的计算方法和特征提取
  • DV曲线的计算方法和特征提取
  • 实操中的注意事项和避坑指南

下一章,我们会继续讲特征工程的下半部分——从统计特征和频域特征入手,进一步挖掘电池健康信息。到时候你会看到,同样的数据,换个角度分析,又能挖出新的宝藏。

课后练习:找一组电池老化数据,分别用IC和DV曲线提取特征。然后对比一下,哪些特征对SOH的预测能力最强?试试用相关性分析或者特征重要性排序来找答案。

好,这一章就到这里。有问题随时交流。