This project predicts the State of Charge (SOC) of a lithium-ion battery using a Random Forest Regression model implemented in Python.
The model is trained using battery operating parameters such as voltage, current, elapsed time, energy, and remaining capacity. The reference SOC is calculated from the remaining battery capacity and nominal battery capacity.
The objective of this project is to develop a machine learning model that predicts battery SOC from charge or discharge data.
The project includes:
- Reading battery data from an Excel file
- Calculating reference SOC
- Selecting input features
- Splitting the data into training and testing datasets
- Training a Random Forest Regression model
- Evaluating the model using RMSE and R² score
- Comparing actual and predicted SOC
- Exporting prediction results to Excel
- Visualizing the results using Matplotlib
The reference SOC is calculated using:
[ SOC(%) = \frac{\text{Remaining Capacity (Ah)}}{\text{Nominal Capacity (Ah)}} \times 100 ]
In this project, the nominal capacity is defined as:
nominal_capacity = 30Therefore:
[ SOC(%) = \frac{\text{Remaining Capacity (Ah)}}{30} \times 100 ]
The input Excel file is expected to contain the following columns:
Voltage (V)
Current (A)
Time (Sec)
Energy (Wh)
Remaining Capacity (Ah)
A new target column is created in the program:
SOC(%)
The Random Forest model uses the following input features:
x = df[
[
'Voltage (V)',
'Current (A)',
'Time (Sec)',
'Energy (Wh)',
'Remaining Capacity (Ah)'
]
]The prediction target is:
y = df['SOC(%)']The project uses the RandomForestRegressor algorithm from Scikit-learn.
Random Forest is an ensemble machine learning method that trains multiple decision trees. Each decision tree generates an SOC prediction, and the final prediction is obtained by averaging the outputs of all trees.
The model is configured as:
model = RandomForestRegressor(
n_estimators=100,
random_state=42
)Where:
n_estimators=100creates 100 decision trees.random_state=42ensures reproducible results.
The dataset is divided into:
- 80% training data
- 20% testing data
x_train, x_test, y_train, y_test = train_test_split(
x,
y,
test_size=0.2,
random_state=42
)The training dataset is used to teach the model, while the testing dataset is used to evaluate its prediction performance.
The Random Forest model is trained using:
model.fit(x_train, y_train)During training, the model learns the relationship between the battery parameters and the calculated SOC.
After training, SOC is predicted for the test dataset:
y_pred = model.predict(x_test)The predicted SOC values are compared with the actual SOC values calculated from remaining capacity.
The model is evaluated using:
- Root Mean Squared Error
- Coefficient of Determination
[ RMSE = \sqrt{ \frac{1}{n} \sum_{i=1}^{n} (y_i-\hat{y}_i)^2 } ]
RMSE measures the average prediction error. A lower RMSE indicates better model performance.
The code calculates RMSE using:
rmse = np.sqrt(
mean_squared_error(y_test, y_pred)
)[ R^2 = 1 - \frac{ \sum(y_i-\hat{y}_i)^2 }{ \sum(y_i-\bar{y})^2 } ]
The R² score measures how well the model explains the variation in SOC.
Typical interpretation:
R² close to 1.0 → Very strong prediction
R² close to 0.0 → Poor predictive performance
R² below 0.0 → Worse than predicting the mean SOC
The evaluation results are printed as:
print(f"RMSE: {rmse:.2f}")
print(f"R2: {r2:.2f}")The program creates an output Excel file containing:
Voltage (V)
Current (A)
Time (Sec)
Energy (Wh)
Remaining Capacity (Ah)
Actual SOC
Predicted SOC
The results are sorted by elapsed time:
results_sorted = results.sort_values(
by='Time (Sec)'
)The output file is saved as:
SOC_predictions_sorted_9.xlsx
The program generates a line plot comparing:
- Actual SOC
- Random Forest predicted SOC
The results are sorted by time before plotting.
plt.plot(
results_sorted['Actual SOC'],
label='Actual SOC',
marker='o'
)
plt.plot(
results_sorted['Predicted SOC'],
label='Predicted SOC',
linestyle='--',
marker='x'
)The graph helps visually evaluate how closely the predicted SOC follows the actual SOC.
- Python
- Pandas
- NumPy
- Scikit-learn
- Matplotlib
- OpenPyXL
- Joblib
Clone the repository:
git clone https://github.com/your-username/SOC-estimation.gitNavigate to the project folder:
cd SOC-estimationCreate a virtual environment:
python -m venv .venvActivate the environment on Windows:
.venv\Scripts\activateInstall the required libraries:
pip install pandas numpy scikit-learn matplotlib openpyxl joblibUpdate the Excel file path in the Python code:
df = pd.read_excel(
'path/to/your/battery_dataset.xlsx'
)Run the program:
python soc_estimation.pyThe program will:
- Read the Excel dataset.
- Display the first five rows.
- Calculate actual SOC.
- Split the data into training and testing datasets.
- Train the Random Forest model.
- Predict SOC for the test dataset.
- Print RMSE and R².
- Export prediction results to Excel.
- Display the actual-versus-predicted SOC graph.
The model-saving section is currently commented out:
# from joblib import dump, load
# dump(
# model,
# 'SOC_predictor_Shriram_Kumar_6.joblib'
# )To save the trained model, remove the comment symbols:
from joblib import dump
dump(
model,
'SOC_predictor_Shriram_Kumar_6.joblib'
)The saved model can later be loaded using:
from joblib import load
model = load(
'SOC_predictor_Shriram_Kumar_6.joblib'
)For an independent SOC estimator, the following features can be used:
x = df[
[
'Voltage (V)',
'Current (A)',
'Time (Sec)',
'Energy (Wh)'
]
]SOC-estimation/
│
├── data/
│ └── SOC_predictions_sorted_1.xlsx
│
├── results/
│ └── SOC_predictions_sorted_9.xlsx
│
├── models/
│ └── SOC_predictor_Shriram_Kumar_6.joblib
│
├── soc_estimation.py
├── requirements.txt
├── .gitignore
└── README.md
Shrinithi Sellam
MSc Data Science student with hands-on professional and project experience in data pipelines, machine learning and business intelligence. Proficient in detecting anomalies, building forecasting models and delivering structured analyses.