基于机器学习的SOC预测

1.静止状态

  由前面的分析可以知道静止状态下SOC与总电压、最高电池值、最小电池值、最大温度、最小温度相关性较高,采用knn算法对SOC进行预测回归。

1.1数据处理

  读取文件

# 读取数据
csv_name = './data/static.csv'
with open(csv_name) as csvfile:
    data = pd.read_csv(csvfile, header=1)  # header=1默然不读取表头

  删除缺失值

# 输出缺失值
data.dropna(inplace=True)

  索引重命名

data = data.rename(
            columns={'车速 km/h': 'velocity', '总电压 V': 'voltage', '总电流 A': 'current',
                     '最高电池值': 'maximum voltage', '最低电池值': 'minimum voltage', '最高温度值': 'max. tem.',
                     '最低温度值': 'min. tem.'})
x = data.loc[:, ['voltage', 'current', 'maximum voltage', 'maximum voltage', 'max. tem.', 'min. tem.']]
y = data.loc[:, ['SOC']]

  数据清洗与划分

# 数据清洗
data = shuffle(data)
data.reset_index(drop=True, inplace=True)
# 划分数据集
x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.8, random_state=6)

  标准化处理

# 标准化处理
x_stand = StandardScaler()
x_train = x_stand.fit_transform(x_train)
x_test = x_stand.transform(x_test)

1.2网格搜索

  网格搜索,寻找最优参数

# 超参数
params = {
    'n_neighbors': [k for k in range(3, 18)],
    'weights': ['uniform', 'distance'],
    'p': [ps for ps in range(2, 8)]
}
kr = KNeighborsRegressor()
# 网格搜索--获取最优参数以及最好的比分
grid_knn = GridSearchCV(estimator=kr, param_grid=params, cv=10)
grid_knn.fit(x_train, y_train)
print('最优参数:', grid_knn.best_params_)
print('最优算法:', grid_knn.best_estimator_)
print('最优评分:', grid_knn.best_score_)
print('测试集评分:', grid_knn.score(x_test, y_test))

在这里插入图片描述
  可以得到以上最佳参数,测试集和验证集评分能够达到99%以上。

1.3KNN预测算法

  构造模型

kr = KNeighborsRegressor(n_neighbors=3, p=2, weights='distance')
kr.fit(x_train, y_train)
y_pre = kr.predict(x_test)
mse = np.sqrt(mean_squared_error(y_test, y_pre))
print('均方误差:', mse)
print('测试集评分:', r2_score(y_test, y_pre))
x_index = [i for i in range(x_test.shape[0])]
plt.figure()
plt.title('predict SoC')
plt.scatter(x_index, y_test, c='r', label="True value")
plt.scatter(x_index, y_pre, c='g', label="Predict value")
plt.xlabel('sample')
plt.ylabel('SoC')
plt.legend(loc="best")
plt.show()

在这里插入图片描述
在这里插入图片描述
  最终结果均方误差为0.412,测试集评分达到0.993。不难得出,在静止状态,可以根据总电压、最高电池值、最小电池值、最大温度、最小温度准确的预测出电动汽车的SOC值。另外,总电压又跟最高电池值和最小电池值相关,最大温度和最小温度线性相关,所以只需要根据最高电池值、最小电池值、最高温度或者最高电池值、最小电池值、最低温度预测SOC即可。

2.运动状态

  由前面的分析可以知道,运动状态下SOC与最大温度、最小温度相关性较高;速度与总电压、最小电池值相关性较高。接下来我们根据最大最小温度预测SOC,总电压、最小电池值预测速度。

2.1KNN算法预测SOC

from sklearn.ensemble import BaggingRegressor
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.utils import shuffle
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 读取数据
csv_name = '../data/static.csv'
with open(csv_name) as csvfile:
    data = pd.read_csv(csvfile, header=1)  # header=1默然不读取表头
# 输出缺失值
data.dropna(inplace=True)

# 重命名
data = data.rename(
            columns={'最高温度值': 'max. tem.',
                     '最低温度值': 'min. tem.'})
x = data.loc[:, ['max. tem.', 'min. tem.']]
y = data.loc[:, ['SOC']]



# 数据清洗
data = shuffle(data)
data.reset_index(drop=True, inplace=True)
# 划分数据集
x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.8, random_state=6)
# 标准化处理
x_stand = StandardScaler()
x_train = x_stand.fit_transform(x_train)
x_test = x_stand.transform(x_test)
# 超参数
# params = {
#     'n_neighbors': [k for k in range(3, 18)],
#     'weights': ['uniform', 'distance'],
#     'p': [ps for ps in range(2, 8)]
# }
# kr = KNeighborsRegressor()
# # 网格搜索--获取最优参数以及最好的比分
# grid_knn = GridSearchCV(estimator=kr, param_grid=params, cv=10)
# grid_knn.fit(x_train, y_train)
# print('最优参数:', grid_knn.best_params_)
# print('最优算法:', grid_knn.best_estimator_)
# print('最优评分:', grid_knn.best_score_)
# print('测试集评分:', grid_knn.score(x_test, y_test))
kr = KNeighborsRegressor(n_neighbors=3, p=2, weights='distance')
kr.fit(x_train, y_train)
y_pre = kr.predict(x_test)
mse = np.sqrt(mean_squared_error(y_test, y_pre))
print('均方误差:', mse)
print('测试集评分:', r2_score(y_test, y_pre))
x_index = [i for i in range(x_test.shape[0])]
plt.figure()
plt.title('predict SoC')
plt.scatter(x_index, y_test, c='r', label="True value")
plt.scatter(x_index, y_pre, c='g', label="Predict value")
plt.xlabel('sample')
plt.ylabel('SoC')
plt.legend(loc="best")
plt.show()

在这里插入图片描述
在这里插入图片描述
  最终结果均方误差为0.50,测试集评分达到0.989。不难得出,在运动状态,可以根据最大温度、最小温度准确的预测出电动汽车的SOC值。

2.2KNN算法预测速度

  在实验的过程中,我发现利用总电压、最小电池值预测速度取得的效果并不好,误差较大,并不能反映出实时的速度。分析后发现可能是因为在城市道路上,电动汽车反复减速加速,总电压变化并不是很明显。(有待研究
在这里插入图片描述

3.充电状态

  充电状态下SOC与总电压、最小电池值、最大电池值、总电流、最大温度、最小温度相关性较高,可以利用这些特征对SOC进行预测。

3.1KNN算法预测SOC

from sklearn.ensemble import BaggingRegressor
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.utils import shuffle
from data_process_model import Data
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 读取数据
csv_name = '../data/charge.csv'
with open(csv_name) as csvfile:
    data = pd.read_csv(csvfile, header=1)  # header=1默然不读取表头
# 输出缺失值
data.dropna(inplace=True)

# 重命名
data = data.rename(
            columns={'车速 km/h': 'velocity', '总电压 V': 'voltage', '总电流 A': 'current',
                     '最高电池值': 'maximum voltage', '最低电池值': 'minimum voltage', '最高温度值': 'max. tem.',
                     '最低温度值': 'min. tem.'})
x = data.loc[:, ['voltage', 'maximum voltage', 'maximum voltage', 'max. tem.', 'min. tem.']]
y = data.loc[:, ['SOC']]



# 数据清洗
data = shuffle(data)
data.reset_index(drop=True, inplace=True)
# 划分数据集
x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.8, random_state=6)
# 标准化处理
x_stand = StandardScaler()
x_train = x_stand.fit_transform(x_train)
x_test = x_stand.transform(x_test)
# # 超参数
# params = {
#     'n_neighbors': [k for k in range(3, 18)],
#     'weights': ['uniform', 'distance'],
#     'p': [ps for ps in range(2, 8)]
# }
# kr = KNeighborsRegressor()
# # 网格搜索--获取最优参数以及最好的比分
# grid_knn = GridSearchCV(estimator=kr, param_grid=params, cv=10)
# grid_knn.fit(x_train, y_train)
# print('最优参数:', grid_knn.best_params_)
# print('最优算法:', grid_knn.best_estimator_)
# print('最优评分:', grid_knn.best_score_)
# print('测试集评分:', grid_knn.score(x_test, y_test))
kr = KNeighborsRegressor(n_neighbors=3, p=2, weights='distance')
kr.fit(x_train, y_train)
y_pre = kr.predict(x_test)
mse = np.sqrt(mean_squared_error(y_test, y_pre))
print('均方误差:', mse)
print('测试集评分:', r2_score(y_test, y_pre))
x_index = [i for i in range(x_test.shape[0])]
plt.figure()
plt.title('predict SoC')
plt.scatter(x_index, y_test, c='r', label="True value")
plt.scatter(x_index, y_pre, c='g', label="Predict value")
plt.xlabel('sample')
plt.ylabel('SoC')
plt.legend(loc="best")
plt.show()

在这里插入图片描述
在这里插入图片描述
  最终结果均方误差为0.494,测试集评分达到0.998。不难得出,在充电状态,可以根据总电压、最高电池值、最小电池值、最大温度、最小温度准确的预测出电动汽车的SOC值。为了达到省钱的目的,可以根据最高温度、最小温度对SOC进行预测。但是充电过程分为快充和慢充,该数据集并不是很完善,没有反映出慢充的状态,所以预测过程中可能存在一定的误差。

4.总结

  对电动汽车整体状态进行一个分析,预测出SOC,结果如下:在这里插入图片描述

状态msescore
静止0.4120.933
运动0.50.989
充电0.4940.998
整体1.3550.977

  可以看出,针对三种状态进行分析是话,均方误差下降了63%左右,而评分提高了1%左右,效果还是很显著的。

5.数据扩展

5.1电压、SOC随时间变化关系

csv_name = '../data/new_data.csv'
with open(csv_name) as csvfile:
    csv_data = pd.read_csv(csvfile)  # header=1默然不读取表头
    print(csv_data.head())
csv_data.dropna(inplace=True, subset=['SOC']) #删除SOC为缺失值的行
plt.subplot(211)
plt.plot(np.arange(0,csv_data.shape[0]), csv_data['总电压'])
plt.xlabel('time')
plt.ylabel('总电压')

plt.subplot(212)
plt.plot(np.arange(0,csv_data.shape[0]), csv_data['SOC'])
plt.xlabel('time')
plt.ylabel('SOC')
plt.show()

在这里插入图片描述
  由于数据量大,只针对了某一天的数据进行了分析。可以很容易看出在一天时间内,该电动公交车进行了多次充电,并且SOC与总电压之间存在某一种线性的关系。

5.2电压与电流之间的关系

csv_name = '../data/new_data.csv'
with open(csv_name) as csvfile:
    csv_data = pd.read_csv(csvfile)  # header=1默然不读取表头
    print(csv_data.head())
csv_data.dropna(inplace=True, subset=['SOC']) #删除SOC为缺失值的行
plt.subplot(211)
plt.plot(np.arange(0,csv_data.shape[0]), csv_data['总电压'])
plt.xlabel('time')
plt.ylabel('总电压')
plt.subplot(212)
plt.plot(np.arange(0,csv_data.shape[0]), csv_data['总电流'])
plt.xlabel('time')
plt.ylabel('总电流')
plt.show()

在这里插入图片描述
  从物理学角度来看U=IR,当电阻恒定,电压越大,电流越大。从上面的结果来看,在充电状态下电压和电流的随时间变化趋势大致呈现相反的现象,但是在未充电状态下两者之间的关系有待研究。

5.3热力图

csv_name='../data/new_data.csv'
with open(csv_name) as csvfile:
    csv_data = pd.read_csv(csvfile)  # header=1默然不读取表头
# 删除SOC为缺失值的行
csv_data.dropna(inplace=True, subset=['SOC'])
# 索引从大到小排序
csv_data.reset_index(drop=True, inplace=True)
# 获取需要的数据
data = csv_data.loc[:, ['车速', '总电压', '累计里程', '总电流', 'SOC', '电池单体电压最高值', '电池单体电压最低值', '最高温度值', '最低温度值']]
# 累计里程为空表示充电状态
list_index = data[['累计里程']].any(axis=1).tolist()
# 分别获取充电状态和未充电状态的行
index_charge = [i for i in range(len(list_index)) if list_index[i] == False]
index_drive = [i for i in range(len(list_index)) if list_index[i] == True]
# 获取数据
data_charge = data.iloc[index_charge, :]
data_drive = data.iloc[index_drive, :]
data_charge = data.loc[:, ['总电压', '总电流', 'SOC', '电池单体电压最高值', '电池单体电压最低值', '最高温度值', '最低温度值']]
# 这两行代码没有会报错
data_charge.dropna(inplace=True)
data_drive.dropna(inplace=True)

print('一共有{}行有缺失值'.format(data_drive.isnull().any(axis=1).sum()))
print('一共有{}行有缺失值'.format(data_charge.isnull().any(axis=1).sum()))
# 热力图
def correlation(data, feature_names):
    corr = np.corrcoef(data.values.T)
    print(corr)
    # 图的准备
    plt.figure(figsize=(12, 12))
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.rcParams['axes.unicode_minus'] = False
    sn.heatmap(corr, cbar=True, square=True, xticklabels=feature_names, yticklabels=feature_names, fmt='.2f',
               annot=True)
    plt.show()
correlation(data_charge, list(data_charge.columns.values))
correlation(data_drive, list(data_drive.columns.values))

  未充电状态下
在这里插入图片描述
  充电状态下
在这里插入图片描述
  不难看出,其结果与前面的研究还是存在很大的区别,不管是充电状态还是未充电状态,SOC与温度的相关性都很低。

状态SOC相关性
充电总电压0.93 电池单体电压最高值0.94 电池单体电压最低值0.86
未充电总电压0.82 电池单体电压最高值0.80 电池单体电压最低值0.79

  进一步对温度随时间变化的关系分析

csv_name = '../data/new_data.csv'
with open(csv_name) as csvfile:
    csv_data = pd.read_csv(csvfile)  # header=1默然不读取表头
    print(csv_data.head())
csv_data.dropna(inplace=True, subset=['SOC']) #删除SOC为缺失值的行
plt.plot(np.arange(0,csv_data.shape[0]), csv_data['最高温度值'], label='最高温度值')
plt.plot(np.arange(0,csv_data.shape[0]), csv_data['最低温度值'], label='最低温度值')
plt.xlabel('time')
plt.ylabel('温度值')
plt.legend()
plt.show()

在这里插入图片描述
  可以看出,最大最小温度之间的相关性还是蛮高的,但其总体变化趋势不是很明显,并没有SOC变化剧烈,所以不难理解两者之间相关性较低。另外温度受其他环境因素的影响,对实验研究也会产生一定的误差,需要进一步的分析。

  • 3
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

being蓓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值