通过理解代码,加深对电池寿命预测方面的理解。
本文中获取的实验数据图片mat文件转换在博客中,或直接通过链接获取。
导入需要的库:
import numpy as np
import scipy.io
from datetime import datetime
import matplotlib.pyplot as plt
%matplotlib inline
函数库以及编程环境介绍:
scipy.io:
scipy.io
是 SciPy 库中的一个子模块,主要用于数据输入输出操作,特别是针对科学计算和工程应用中常见的数据格式。通过 scipy.io
,用户能够方便地在 Python 中读取和写入多种类型的文件,如 MATLAB .mat 文件、WAV 音频文件、以及某些特定的科学仪器产生的数据格式等。
scipy.io.loadmat()
和 scipy.io.savemat()
可以用来读取和保存 MATLAB 格式的 .mat
文件,这些文件通常用于存储 MATLAB 工作空间中的变量和数据结构。
由于 SciPy 建立在 NumPy 数组基础上,因此 scipy.io
在读取或写入数据时,通常会将数据转换成或从 NumPy 数组格式进行操作。这个很重要,为待会解释col = col[0][0][0][0]做铺垫。
%matplotlib inline:
是 IPython 和 Jupyter Notebook 环境中的一个魔术命令(magic command),它用于设置 Matplotlib 图形的显示方式。当在 Jupyter Notebook 中执行这一命令后,所有随后创建的 Matplotlib 图像将会以内联(inline)的方式直接嵌入到 Notebook 的输出单元格中,而不是弹出一个新的窗口来显示图形。
这意味着每次调用 plt.plot()
、plt.show()
等绘图函数时,图表会立即出现在 Notebook 相应的代码单元格下方,便于交互式查看和文档化分析。
在非 Jupyter Notebook 环境中执行 %matplotlib inline
命令可能会导致错误,因为其他环境通常不支持这种内联显示的功能。
对函数进行定义:
# 转换时间格式,将字符串转换成 datetime 格式
def convert_to_time(hmm):
year, month, day, hour, minute, second = int(hmm[0]), int(hmm[1]), int(hmm[2]), int(hmm[3]), int(hmm[4]), int(hmm[5])
return datetime(year=year, month=month, day=day, hour=hour, minute=minute, second=second)
# 加载 mat 文件
def loadMat(matfile):
data = scipy.io.loadmat(matfile)
filename = matfile.split('/')[-1].split('.')[0]#先分隔并取出最后一个元素,即B0005.mat,然后再分隔取出B0005
col = data[filename]
col = col[0][0][0][0]
size = col.shape[0]#获取数据的行数616
data = []
for i in range(size):
k = list(col[i][3][0].dtype.fields.keys())#.dtype.fields ,它返回一个字典;.keys() 方法则用于获取这个字典的所有键,即结构化数组中的字段名。
d1, d2 = {}, {}#建立空字典
if str(col[i][0][0]) != 'impedance':
for j in range(len(k)):
t = col[i][3][0][0][j][0];#得到键值的具体数据集
l = [t[m] for m in range(len(t))]
d2[k[j]] = l#将数据存入d2中
d1['type'], d1['temp'], d1['time'], d1['data'] = str(col[i][0][0]), int(col[i][1][0]), str(convert_to_time(col[i][2][0])), d2
data.append(d1)
return data
# 提取锂电池容量
def getBatteryCapacity(Battery):
cycle, capacity = [], []
i = 1
for Bat in Battery:
if Bat['type'] == 'discharge':
capacity.append(Bat['data']['Capacity'][0])
cycle.append(i)
i += 1
return [cycle, capacity]
# 获取锂电池充电或放电时的测试数据
def getBatteryValues(Battery, Type='charge'):
data=[]
for Bat in Battery:
if Bat['type'] == Type:
data.append(Bat['data'])
return data
关于datetime的介绍,请参考另一篇博客datetime。
关于mat文件转换的细节请参考另一篇博客,这里不再赘述。
从matlab文件中读取数据:
Battery_list = ['B0005', 'B0006', 'B0007', 'B0018'] # 4 个数据集的名字
dir_path = 'dataset/'
capacity, charge, discharge = {}, {}, {}
for name in Battery_list:
print('Load Dataset ' + name + '.mat ...')
path = dir_path + name + '.mat'
data = loadMat(path)
capacity[name] = getBatteryCapacity(data) # 放电时的容量数据
charge[name] = getBatteryValues(data, 'charge') # 充电数据
discharge[name] = getBatteryValues(data, 'discharge') # 放电数据
如果上面的数据集读取失败,可以通过下面的方式加载已提取出来的数据:
Battery_list = ['B0005', 'B0006', 'B0007', 'B0018'] # 4 个数据集的名字
Battery = np.load('dataset/NASA.npy', allow_pickle=True)
Battery = Battery.item()
图像绘制:
容量-充放电次数曲线绘制:
fig, ax = plt.subplots(1, figsize=(12, 8))
color_list = ['b:', 'g--', 'r-.', 'c.']
c = 0
for name in Battery_list:
data = capacity[name]
color = color_list[c]
ax.plot(data[0], data[1], color, label=name)
c += 1
plt.plot([-1,170],[2.0*0.7,2.0*0.7],c='black',lw=1,ls='--') # 临界点直线
ax.set(xlabel='Discharge cycles', ylabel='Capacity (Ah)', title='Capacity degradation at ambient temperature of 24°C')
plt.legend()
充电电流-充电时间曲线绘制:
name = 'B0005' #查看的电池号
time = [0, 50, 100] #查看的充电次数
# 画图
fig, ax = plt.subplots(1, figsize=(12, 8))
color_list = ['b', 'g', 'r']
c = 0
for t in time:
Battery = charge[name][t]
color = color_list[c]
ax.plot(Battery['Time'], Battery['Current_measured'], color, label='charge time: '+str(t))
c += 1
ax.set(xlabel='Time', ylabel='Current (A)', title='Charging Curve')
plt.legend()
放电电压-充电时间曲线绘制:
name = 'B0005' #查看的电池号
time = [0, 50, 100] #查看的放电次数
# 画图
fig, ax = plt.subplots(1, figsize=(12, 8))
color_list = ['b', 'g', 'r']
c = 0
for t in time:
Battery = discharge[name][t]
color = color_list[c]
ax.plot(Battery['Time'], Battery['Voltage_measured'], color, label='discharge time: '+str(t))
c += 1
ax.set(xlabel='Time', ylabel='Voltage (V)', title='Discharging Curve')
plt.legend()
参考资料:NASA 锂电池数据集,基于 Python 的锂电池寿命预测(Remaining Useful Life,RUL)& (End Of Life,EOF) - 倔强的小蜗牛