Bohrium
robot
新建

空间站广场

论文
Notebooks
比赛
课程
Apps
我的主页
我的Notebooks
我的论文库
我的足迹

我的工作空间

任务
节点
文件
数据集
镜像
项目
数据库
公开
电化学阻抗谱EIS预测 —— 使用四个特征频率下的阻抗预测全频段EIS
电化学阻抗谱EIS
EIS
Deep Learning
AI4S
中文
电化学阻抗谱EISEISDeep LearningAI4S中文
JiaweiMiao
发布于 2024-04-14
推荐镜像 :Basic Image:bohrium-notebook:2023-03-26
推荐机型 :c12_m92_1 * NVIDIA V100
赞 2
1
5
EIS_public(v5)

Data-driven EIS Prediction

Few Characteristic frequencies impedance predict full EIS

©️Copyright @ Authors
日期:2024-04-014
共享协议:本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
代码
文本

Abstract

电化学阻抗谱(EIS)作为一种测试方法和表征手段,包含着丰富的电池动力学和老化信息,可被用作监测电池状态(如拟合等效电路模型和预测剩余寿命)。然而,其收集成本高、时间久和车载收集困难限制了广泛了应用。目前,已有一些工作通过脉冲电流、充放电信号等预测EIS。同时,由于EIS测试过程中扫频的特点,使得使用部分频率下的阻抗,预测全频率阻抗成为了一个自然的思路。在这种情况下,测试的时间将大大缩短。本文基于这种思路,使用在几个特征频率下测量的阻抗作为输入。 根据弛豫时间分布中接触极化和固体电解质相间生长过程的特征峰和谷对应的时间常数来确定特征频率。使用两种模型(基于卷积神经网络和注意力模型)对公开数据集[1]中同一温度下的7个电池进行了实验,结果显示,两种模型在使用4个特征频率数据的情况下,预测的平均RMSE均小于10mΩ,其中基于注意力的模型比基于CNN的模型精度提高了40%。

本文分为两个部分,第一个部分为背景介绍和关于EIS的DRT分析,第二个部分为两个模型的代码实现,第一个模型为参考文章中的CNN模型,第二个模型为一个Transformer encoder模型。 完整运行代码只需要几分钟。

关于几个特征频率点下的阻抗预测全EIS谱的文章参考:Journal of Power Sources

代码
文本

Introduction

关于EIS以及使用特征频率下阻抗预测全谱EIS有以下背景需要了解:

  • 电化学阻抗谱(EIS)是一种常用于表征电池的非破坏性方法,它揭示了LiB内部的动态电极动力学过程。基于不同电化学过程表现出的时间常数,可以通过将阻抗谱的变化与固体电解质界面(SEI)生长电荷转移锂离子扩散等内部机制联系起来来表征电池性能。辅助研究工具包括等效电路模型(ECM)、弛豫时间分布(DRT)、阻抗机制模型等。 可以区分和量化多时间尺度特征,以更好地了解电池状态。已有工作显示2,借助机器学习方法,在电芯筛选和老化监测这两种情况下,根据阻抗可以可靠地量化关键的物理化学参数。 结果表明,电芯筛选时可以EIS准确估算电池电极的弯曲度、孔隙率和活性物质含量,误差小于2%;在老化监测方面,SEI电阻和电荷转移电阻可以准确估计,误差小于5% 。 上述应用表明EIS提供了对电池更全面的理解。

  • DRT可以实现频域EIS的解释并区分不同时间常数的电化学过程。与 ECM 的预建模不同,DRT 方法的思想是将阻抗响应表示为无限个差分 RC 分量。如下图所示,EIS的DRT结果可以通过DRTtools基于Tikhonov正则化来计算:

上图来自参考文章

可以注意到,在不同的时间常数下可以清楚地识别出四个动力学过程 P1∼P4。 过程P1表示由于集电器腐蚀而导致的接触极化。 过程P2表明SEI的生长。 同时,P1和P2与电池SOC无关。 过程P3和P4表示电荷转移和扩散,它们都与锂离子浓度即SOC有关。在实际应用中,电池工作条件和状态的变化使得阻抗谱的实时测量变得困难。阻抗谱随电池内部状态的变化而显着变化。 为了保证测量的有效性而不影响电池在充放电过程中的正常工作状态,测量需要在很短的时间内完成。 因此,特征频率由中频和高频区域确定,对应于 DRT 曲线中 P1(接触极化)和 P2(SEI 生长)的波峰和波谷。 得到时间常数τ后,可以计算出相应的频率f。值得注意的是,参考文章中提到:“当电池类型或温度发生变化时,需要重新确定特征频率。 在电池老化过程中,特征频率对应的时间常数没有明显变化,但特征频率处的峰、谷和峰面积有所不同,这使得基于电池老化过程中特征频率的预测方法具有可行性。”

下图是在我们使用的公开数据集中,1号电池在25°C不同循环下SOC=0时EIS的DRT结果:

其中左图横轴为时间常数,右图横轴为频率。从两张图中我们都可以发现,随着电池的老化,P1和P2阶段对应波峰波谷的特征频率和时间常数是会出现一些偏移的。关于这一点,笔者也与参考文章的作者确认过。因此,虽然在我们后续的建模计算中,使用初始特征频率的预测精度很高,但关于如何处理EIS数据、选择特征,还是一个值得思考和研究的问题。

注:

  1. 为了与参考文章中的结果比对,本文选择的四个特征频率与参考文章中提取的公开数据集特征频率相同。上右图中的灰线对应着四个特征频率的位置。
  2. DRTtools: https://github.com/ciuccislab/pyDRTtools
代码
文本
已隐藏单元格
代码
文本

Data Load and Process

这里我们使用公开数据集中,测试温度为25℃下的七颗电池,使用的SOC状态为0%。测试电池为LCO体系纽扣电池,循环次数从几十到三百不等,共1350个循环。

代码
文本
[28]
EIS_data = []
data_path = '/bohr/eisp-q8by/v5/public_data_camb'
for file in os.listdir(data_path):
if file.endswith('.csv'):
sample_name = file.split('_')[-1].split('.')[0]
data = pd.read_csv(os.path.join(data_path, file))
data = pd.DataFrame(data)
cycle = sorted(set(data['cycle number']))
data_cycle = [[f'{sample_name}-cyc{i}', data[data['cycle number'] == i]] for i in cycle]
data_eis = [(i[0], torch.tensor(i[1]['freq/Hz'].to_numpy()), torch.tensor(i[1]['Re(Z)/Ohm'].to_numpy()),
torch.tensor(i[1]['-Im(Z)/Ohm'].to_numpy())) for i in data_cycle]
EIS_data += data_eis

print('Total samples:', len(EIS_data))
Total samples: 1350
代码
文本
[29]
print('Data Sample Name:',EIS_data[66][0])
print('Data Sample Shape:',len(EIS_data[66][1]))
Data Sample Name: 25C01-cyc67

Data Sample Shape: 60
代码
文本
已隐藏单元格
代码
文本

将数据集随机划分为训练集验证集。比例为8/2.

代码
文本
[32]
# Set Random Seed
seed = 414
random.seed(seed)
random.shuffle(EIS_data)
split_valid_ratio = 0.2
train_data, valid_data = EIS_data[int(len(EIS_data)*split_valid_ratio):], EIS_data[:int(len(EIS_data)*split_valid_ratio)]
print('Train samples:', len(train_data), '\nValid samples:', len(valid_data))
Train samples: 1080 

Valid samples: 270
代码
文本

这里列出参考文章中给出的特征频率[115.78, 35.93, 7.76, 1.42] Hz。可以发现,和参考文章中NMC数据集相比,公开数据集选择的频率集中在中频段甚至靠近低频段。

代码
文本
[33]
CHAR_F = [115.78, 35.93, 7.76, 1.42]

def dataset_gen(dataset):
data_name, data_input, data_output = [], [], []
for name, freq, re, im in dataset:
data_name.append(name)
char_r = [re[torch.abs(freq - f).argmin()] for f in CHAR_F]
char_i = [im[torch.abs(freq - f).argmin()] for f in CHAR_F]
data_input.append(torch.stack([torch.tensor(char_r), torch.tensor(char_i)], dim=-1))
data_output.append(torch.stack([re, im], dim=-1))
return data_name, data_input, data_output, freq
代码
文本

从数据集中取出输入数据,即四个特征频率下的阻抗实虚部。

代码
文本
[34]
_, train_src, train_tgt, freq = dataset_gen(train_data)
valid_name, valid_src, valid_tgt, _ = dataset_gen(valid_data)
print('Shape of Input:',train_src[0].shape)
print('Shape of Output:',train_tgt[0].shape)
Shape of Input: torch.Size([4, 2])

Shape of Output: torch.Size([60, 2])
代码
文本

CNN Model

复现参考文章中的CNN模型。注意这里输入给模型的Channels是2,对应是阻抗的实部与虚部,可以看作输入的两个feature。而频率维度为4,对应序列长度4。这种设计还是比较make sense的。

代码
文本
[35]
class EISConvNet(nn.Module):
def __init__(self):
super(EISConvNet, self).__init__()
self.conv1 = nn.Conv1d(2, 16, kernel_size=2, stride=1, padding=1)
self.pool1 = nn.MaxPool1d(2)
self.conv2 = nn.Conv1d(16, 32, kernel_size=2, stride=1, padding=1)
self.pool2 = nn.MaxPool1d(2)
self.conv3 = nn.Conv1d(32, 16, kernel_size=2, stride=1, padding=1)
self.global_pool = nn.AdaptiveMaxPool1d(1)
self.fc1 = nn.Linear(16, 120)
self.dropout = nn.Dropout(0.1)
self.fc2 = nn.Linear(120, 120)
self.relu = nn.ReLU()

def forward(self, x):
x = x.permute(0, 2, 1) # [batch, 4, 2] -> [batch, 2, 4]
x = self.relu(self.conv1(x))
x = self.pool1(x)
x = self.relu(self.conv2(x))
x = self.pool2(x)
x = self.relu(self.conv3(x))
x = self.global_pool(x)
x = x.view(x.size(0), -1)
x = self.relu(self.fc1(x))
x = self.dropout(x)
x = self.fc2(x)
return x
代码
文本

考虑到文章中最后有一步flatten的操作,因此这里把target的数据拉平,和模型输出保持一致。

代码
文本
[36]
def convert_data_output(data_output):
new_data_output = []
for output in data_output:
re, im = output.unbind(dim=-1)
new_output = torch.cat([re, im], dim=-1)
new_data_output.append(new_output)
return new_data_output
代码
文本
[37]
train_tgt_cnn = convert_data_output(train_tgt)
valid_tgt_cnn = convert_data_output(valid_tgt)
代码
文本
已隐藏单元格
CNN Model: EISConvNet(

  (conv1): Conv1d(2, 16, kernel_size=(2,), stride=(1,), padding=(1,))

  (pool1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)

  (conv2): Conv1d(16, 32, kernel_size=(2,), stride=(1,), padding=(1,))

  (pool2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)

  (conv3): Conv1d(32, 16, kernel_size=(2,), stride=(1,), padding=(1,))

  (global_pool): AdaptiveMaxPool1d(output_size=1)

  (fc1): Linear(in_features=16, out_features=120, bias=True)

  (dropout): Dropout(p=0.1, inplace=False)

  (fc2): Linear(in_features=120, out_features=120, bias=True)

  (relu): ReLU()

)
代码
文本
[39]
max_epoch = 1000
batch_size = 32

criterion = nn.MSELoss() # nn.L1Loss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.4, patience=30, verbose=True)
print_interval = 50
代码
文本
[40]
train_loss_list, valid_loss_list = [], []
valid_rmse_list, valid_rmspe_list = [], []

# create dataset and loader
train_dataset = TensorDataset(torch.stack(train_src), torch.stack(train_tgt_cnn))
valid_dataset = TensorDataset(torch.stack(valid_src), torch.stack(valid_tgt_cnn))

train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
valid_loader = DataLoader(valid_dataset, batch_size=batch_size)
代码
文本
[41]
for epoch in range(max_epoch):
model.train()
train_loss = 0.0
for batch_input, batch_output in train_loader:
batch_input, batch_output = batch_input.to(device), batch_output.to(device)
optimizer.zero_grad()
output = model(batch_input)
loss = criterion(output, batch_output)#*1000
loss.backward()
optimizer.step()
train_loss += loss.item() * batch_input.size(0)
train_loss /= len(train_loader.dataset)
train_loss_list.append(train_loss)
model.eval()
valid_loss = 0.0
valid_rmse = 0.0
valid_rmspe = 0.0
with torch.no_grad():
for batch_input, batch_output in valid_loader:
batch_input, batch_output = batch_input.to(device), batch_output.to(device)
output = model(batch_input)
loss = criterion(output, batch_output)#*1000
valid_loss += loss.item() * batch_input.size(0)
# Calculate RMSE
# mse = nn.MSELoss()(output, batch_output)
rmse = torch.sqrt(loss)
valid_rmse += rmse.item() * batch_input.size(0)

# Calculate RMSPE
relative_error = (output - batch_output) / (torch.abs(batch_output) + 1e-8) # 添加一个小的常数以避免除以零
squared_relative_error = torch.square(relative_error)
rmspe = torch.sqrt(torch.mean(squared_relative_error)) * 100
valid_rmspe += rmspe.item() * batch_input.size(0)
valid_loss /= len(valid_loader.dataset)
valid_rmse /= len(valid_loader.dataset)
valid_rmspe /= len(valid_loader.dataset)
valid_loss_list.append(valid_loss)
valid_rmse_list.append(valid_rmse)
valid_rmspe_list.append(valid_rmspe)
if (epoch+1) % print_interval == 0:
print(f"Epoch [{epoch+1}/{max_epoch}], Train Loss: {train_loss:.6f}, Valid Loss: {valid_loss:.6f}, Valid RMSE: {valid_rmse:.4f}, Valid RMSPE: {valid_rmspe:.4f}")
scheduler.step(valid_loss)
Epoch [50/1000], Train Loss: 0.002518, Valid Loss: 0.000802, Valid RMSE: 0.0283, Valid RMSPE: 285.3956

Epoch [100/1000], Train Loss: 0.001763, Valid Loss: 0.000616, Valid RMSE: 0.0247, Valid RMSPE: 181.2080

Epoch [150/1000], Train Loss: 0.001380, Valid Loss: 0.000351, Valid RMSE: 0.0187, Valid RMSPE: 218.0271

Epoch [200/1000], Train Loss: 0.001046, Valid Loss: 0.000167, Valid RMSE: 0.0129, Valid RMSPE: 141.5312

Epoch [250/1000], Train Loss: 0.000802, Valid Loss: 0.000197, Valid RMSE: 0.0140, Valid RMSPE: 248.3659

Epoch [300/1000], Train Loss: 0.000580, Valid Loss: 0.000262, Valid RMSE: 0.0162, Valid RMSPE: 196.1105

Epoch [350/1000], Train Loss: 0.000435, Valid Loss: 0.000079, Valid RMSE: 0.0089, Valid RMSPE: 218.4360

Epoch [400/1000], Train Loss: 0.000350, Valid Loss: 0.000093, Valid RMSE: 0.0096, Valid RMSPE: 168.3522

Epoch [450/1000], Train Loss: 0.000259, Valid Loss: 0.000147, Valid RMSE: 0.0121, Valid RMSPE: 172.9470

Epoch 00467: reducing learning rate of group 0 to 4.0000e-04.

Epoch [500/1000], Train Loss: 0.000223, Valid Loss: 0.000051, Valid RMSE: 0.0071, Valid RMSPE: 176.5252

Epoch 00519: reducing learning rate of group 0 to 1.6000e-04.

Epoch [550/1000], Train Loss: 0.000202, Valid Loss: 0.000042, Valid RMSE: 0.0065, Valid RMSPE: 183.4119

Epoch [600/1000], Train Loss: 0.000201, Valid Loss: 0.000056, Valid RMSE: 0.0075, Valid RMSPE: 198.8764

Epoch [650/1000], Train Loss: 0.000185, Valid Loss: 0.000039, Valid RMSE: 0.0062, Valid RMSPE: 177.5421

Epoch [700/1000], Train Loss: 0.000179, Valid Loss: 0.000036, Valid RMSE: 0.0060, Valid RMSPE: 172.6961

Epoch 00736: reducing learning rate of group 0 to 6.4000e-05.

Epoch [750/1000], Train Loss: 0.000165, Valid Loss: 0.000036, Valid RMSE: 0.0060, Valid RMSPE: 154.4047

Epoch [800/1000], Train Loss: 0.000172, Valid Loss: 0.000036, Valid RMSE: 0.0060, Valid RMSPE: 166.8874

Epoch 00807: reducing learning rate of group 0 to 2.5600e-05.

Epoch [850/1000], Train Loss: 0.000168, Valid Loss: 0.000034, Valid RMSE: 0.0058, Valid RMSPE: 155.5290

Epoch [900/1000], Train Loss: 0.000177, Valid Loss: 0.000034, Valid RMSE: 0.0058, Valid RMSPE: 151.3917

Epoch 00906: reducing learning rate of group 0 to 1.0240e-05.

Epoch 00937: reducing learning rate of group 0 to 4.0960e-06.

Epoch [950/1000], Train Loss: 0.000173, Valid Loss: 0.000034, Valid RMSE: 0.0058, Valid RMSPE: 151.8588

Epoch 00968: reducing learning rate of group 0 to 1.6384e-06.

Epoch 00999: reducing learning rate of group 0 to 6.5536e-07.

Epoch [1000/1000], Train Loss: 0.000165, Valid Loss: 0.000034, Valid RMSE: 0.0058, Valid RMSPE: 152.2056
代码
文本

笔者尝试了多个随机数种子,CNN模型的结果均在6~7mΩ左右,这个结果略好于参考文章中公开数据集的最优结果。考虑到参考文章是在第一个数据集上预训练后transfer learning到公开数据集,这样的结果也还算合理。值得一提的是RMSPE的值,由于EIS虚部在高频段可能非常接近与0,所以百分比误差在这里会出现爆炸的情况,着也是为什么用百分比误差衡量EIS预测不太合理的地方。

代码
文本
已隐藏单元格
代码
文本
已隐藏单元格
代码
文本

选择几个验证集中的数据绘图展示。可以看到,拟合的精度还是很好的。

代码
文本
[44]
model_cnn = model
predictions = inference(model_cnn, valid_loader, device)
true_values = [tgt.cpu().numpy() for tgt in valid_tgt_cnn]

# True EIS - CNN predicted EIS
num_samples_to_plot = 4
plt.figure(figsize=(10, 12))

for i in range(num_samples_to_plot):
mse = np.mean((true_values[i] - predictions[i])**2)
rmse = np.sqrt(mse)
abs_diff = np.abs(true_values[i] - predictions[i])
abs_true = np.abs(true_values[i])
rmspe = np.sqrt(np.mean(np.square(abs_diff / abs_true))) * 100
plt.subplot(num_samples_to_plot, 2, i + 1)
plt.plot(true_values[i][:60], true_values[i][60:], 'o', label=f'True EIS', markersize=4)
plt.plot(predictions[i][:60], predictions[i][60:], 'o', label=f'Predicted EIS', markersize=4)
plt.legend()
plt.xlabel('Re(Ω)')
plt.ylabel('Im(Ω)')
plt.title(f'{valid_name[i]} - EIS (RMSE: {rmse:.4f})') # , RMSPE: {rmspe:.2f}%
plt.tight_layout()
plt.show()
代码
文本
已隐藏单元格
已隐藏输出
代码
文本

Transformer Model

然后是我们的Transformer模型。这里我只使用了Encoder的部分。由于模型对数据处理的不同,这个模型的输入为[batch_size, 4, 2]。从思路上来说,和CNN模型的设计较为类似,都是将频率看作一个序列。只不过Attention会通过自注意力机制捕捉不同位置的依赖关系,同时这些不同频率间的顺序关系可能也并没有那么强,这也是使用注意力模型的一个原因。

注:笔者也尝试使用了包含encoder+decoder结构的transformer。并将频率作为输入。似乎精度并没有前一个模型好。

代码
文本
[53]
class EISTFMNet(nn.Module):
def __init__(self, d_model, nhead, num_layers, dim_feedforward, dropout=0.1):
super(EISTFMNet, self).__init__()
self.feature_embedding = nn.Linear(2, d_model)
self.freq_embedding = nn.Embedding(4, d_model)
encoder_layer = nn.TransformerEncoderLayer(d_model, nhead, dim_feedforward, dropout, batch_first=True)
self.transformer_encoder = nn.TransformerEncoder(encoder_layer, num_layers)
self.decoder = nn.Sequential(
nn.Linear(4 * d_model, dim_feedforward),
nn.ReLU(),
nn.Linear(dim_feedforward, 60 * 2)
)

def forward(self, src):
# src: [batch_size, 4, 2]
batch_size, num_freqs, _ = src.size()
src = self.feature_embedding(src) # [batch_size, 4, d_model]
freq_indices = torch.arange(num_freqs, dtype=torch.long, device=src.device)
freq_indices = freq_indices.unsqueeze(0).expand(batch_size, -1) # [batch_size, 4]
freq_embedding = self.freq_embedding(freq_indices) # [batch_size, 4, d_model]
src = src + freq_embedding
output = self.transformer_encoder(src) # [batch_size, 4, d_model]
# output = output.mean(dim=1) # [batch_size, d_model]
output = output.view(batch_size, -1)
output = self.decoder(output) # [batch_size, 60 * 2]
output = output.view(batch_size, 60, 2) # [batch_size, 60, 2]
return output
代码
文本
已隐藏单元格
代码
文本
[47]
train_tgt_tfm = [data.float().to(device) for data in train_tgt]
valid_tgt_tfm = [data.float().to(device) for data in valid_tgt]
freq = freq.float().to(device)
model = EISTFMNet(d_model=128, nhead=8, num_layers=3, dim_feedforward=512, dropout=0.1).to(device)
print('Transformer Model:', model)
Transformer Model: EISTFMNet(

  (feature_embedding): Linear(in_features=2, out_features=128, bias=True)

  (freq_embedding): Embedding(4, 128)

  (transformer_encoder): TransformerEncoder(

    (layers): ModuleList(

      (0-2): 3 x TransformerEncoderLayer(

        (self_attn): MultiheadAttention(

          (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)

        )

        (linear1): Linear(in_features=128, out_features=512, bias=True)

        (dropout): Dropout(p=0.1, inplace=False)

        (linear2): Linear(in_features=512, out_features=128, bias=True)

        (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)

        (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)

        (dropout1): Dropout(p=0.1, inplace=False)

        (dropout2): Dropout(p=0.1, inplace=False)

      )

    )

  )

  (decoder): Sequential(

    (0): Linear(in_features=512, out_features=512, bias=True)

    (1): ReLU()

    (2): Linear(in_features=512, out_features=120, bias=True)

  )

)
代码
文本
[48]
max_epoch = 1000
batch_size = 32
criterion = nn.MSELoss() # nn.L1Loss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.4, patience=30, verbose=True)
print_interval = 50
代码
文本
已隐藏单元格
代码
文本
已隐藏单元格
Epoch [50/1000], Train Loss: 0.000369, Valid Loss: 0.001126, Valid RMSE: 0.0335, Valid RMSPE: 202.5800

Epoch [100/1000], Train Loss: 0.000129, Valid Loss: 0.000108, Valid RMSE: 0.0104, Valid RMSPE: 225.9618

Epoch [150/1000], Train Loss: 0.000216, Valid Loss: 0.001112, Valid RMSE: 0.0333, Valid RMSPE: 199.0048

Epoch 00154: reducing learning rate of group 0 to 4.0000e-04.

Epoch 00192: reducing learning rate of group 0 to 1.6000e-04.

Epoch [200/1000], Train Loss: 0.000037, Valid Loss: 0.000022, Valid RMSE: 0.0047, Valid RMSPE: 45.4253

Epoch 00227: reducing learning rate of group 0 to 6.4000e-05.

Epoch [250/1000], Train Loss: 0.000031, Valid Loss: 0.000016, Valid RMSE: 0.0039, Valid RMSPE: 37.1611

Epoch [300/1000], Train Loss: 0.000034, Valid Loss: 0.000017, Valid RMSE: 0.0041, Valid RMSPE: 57.1627

Epoch 00345: reducing learning rate of group 0 to 2.5600e-05.

Epoch [350/1000], Train Loss: 0.000025, Valid Loss: 0.000014, Valid RMSE: 0.0037, Valid RMSPE: 47.1046

Epoch [400/1000], Train Loss: 0.000023, Valid Loss: 0.000013, Valid RMSE: 0.0036, Valid RMSPE: 51.2888

Epoch 00411: reducing learning rate of group 0 to 1.0240e-05.

Epoch [450/1000], Train Loss: 0.000022, Valid Loss: 0.000015, Valid RMSE: 0.0039, Valid RMSPE: 31.2402

Epoch 00464: reducing learning rate of group 0 to 4.0960e-06.

Epoch [500/1000], Train Loss: 0.000022, Valid Loss: 0.000013, Valid RMSE: 0.0036, Valid RMSPE: 30.3990

Epoch 00506: reducing learning rate of group 0 to 1.6384e-06.

Epoch 00537: reducing learning rate of group 0 to 6.5536e-07.

Epoch [550/1000], Train Loss: 0.000022, Valid Loss: 0.000013, Valid RMSE: 0.0035, Valid RMSPE: 44.7057

Epoch 00568: reducing learning rate of group 0 to 2.6214e-07.

Epoch 00599: reducing learning rate of group 0 to 1.0486e-07.

Epoch [600/1000], Train Loss: 0.000020, Valid Loss: 0.000013, Valid RMSE: 0.0035, Valid RMSPE: 40.1145

Epoch 00630: reducing learning rate of group 0 to 4.1943e-08.

Epoch [650/1000], Train Loss: 0.000021, Valid Loss: 0.000013, Valid RMSE: 0.0036, Valid RMSPE: 40.0683

Epoch 00661: reducing learning rate of group 0 to 1.6777e-08.

Epoch 00692: reducing learning rate of group 0 to 6.7109e-09.

Epoch [700/1000], Train Loss: 0.000021, Valid Loss: 0.000013, Valid RMSE: 0.0036, Valid RMSPE: 40.6533

Epoch [750/1000], Train Loss: 0.000021, Valid Loss: 0.000013, Valid RMSE: 0.0035, Valid RMSPE: 40.5638

Epoch [800/1000], Train Loss: 0.000021, Valid Loss: 0.000013, Valid RMSE: 0.0036, Valid RMSPE: 40.3486

Epoch [850/1000], Train Loss: 0.000021, Valid Loss: 0.000013, Valid RMSE: 0.0036, Valid RMSPE: 40.7708

Epoch [900/1000], Train Loss: 0.000021, Valid Loss: 0.000013, Valid RMSE: 0.0036, Valid RMSPE: 40.8356

Epoch [950/1000], Train Loss: 0.000020, Valid Loss: 0.000013, Valid RMSE: 0.0035, Valid RMSPE: 40.2205

Epoch [1000/1000], Train Loss: 0.000021, Valid Loss: 0.000013, Valid RMSE: 0.0036, Valid RMSPE: 40.3683
代码
文本

将RMSE结果与CNN的比较,Attention based模型的精度平均要比CNN模型高40%。

代码
文本
已隐藏单元格
代码
文本
已隐藏单元格
代码
文本

从比较图中我们也可以发现,Valid Sample 2在中频段的预测效果,Transformer模型要明显好于CNN模型。

代码
文本

Conclusion

  • 我们在公开数据集上实验了通过特征频率阻抗预测EIS。预测的精度RMSE目前可以低于4mΩ。这代表特征频率下的EIS可以很大程度上包含全频段的EIS信息。
  • 关于特征频率的选择依然有研究的空间。
代码
文本
电化学阻抗谱EIS
EIS
Deep Learning
AI4S
中文
电化学阻抗谱EISEISDeep LearningAI4S中文
已赞2
本文被以下合集收录
电芯
Piloteye
更新于 2024-07-22
17 篇3 人关注
推荐阅读
公开
EIS 自动化拟合等效电路模型 ECM
EISMachine Learning
EISMachine Learning
JiaweiMiao
更新于 2024-07-21
公开
AI+电芯 | 基于LSTM模型和脉冲电信号的电芯EIS预测
AI4SEISAI4SCUP-EIS
AI4SEISAI4SCUP-EIS
JiaweiMiao
发布于 2023-10-22
5 赞40 转存文件