Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additions to #177 #198

Merged
merged 26 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a00a2be
Update subplot widths, test_plotting dataset access, remove square br…
BradyPlanden Feb 16, 2024
89e2932
Add plotting support for notebook rendering, adds kaleido as dependancy
BradyPlanden Feb 22, 2024
f853af9
+ diffevolution notebook
BradyPlanden Feb 22, 2024
fc06f1f
Merge branch '177-plotting-capabilities' into 177b-plotting-capabilities
BradyPlanden Feb 22, 2024
d7a71a7
fix missed deletion during merge
BradyPlanden Feb 22, 2024
4f5dbe6
Merge branch '177-plotting-capabilities' into 177b-plotting-capabilities
BradyPlanden Feb 23, 2024
ed2bf7c
Merge branch '177-plotting-capabilities' into 177b-plotting-capabilities
BradyPlanden Feb 23, 2024
4cf9108
Revamp model, problem, and cost object from numpy arrays to dictionar…
BradyPlanden Mar 1, 2024
3428c97
Fix ukf examples, temporarily limits ukf to signal output model
BradyPlanden Mar 1, 2024
43521da
default_variables to additional_variables w/ docstrings, updt. observ…
BradyPlanden Mar 2, 2024
67d2887
Fix integration test logic, add gradient landscape plots, pin pytest …
BradyPlanden Mar 4, 2024
b6a073b
Add tests for gradient plots, up coverage
BradyPlanden Mar 4, 2024
ee4cdff
Set default SciPyMinimize method to Nelder-Mead, clean-up repo
BradyPlanden Mar 4, 2024
66efaba
unicode fix for win notebooks, update prediction shape checks, remove…
BradyPlanden Mar 8, 2024
9b03734
Updt. cost2d/optim2d x0 shape/colour, revert conftest win platform un…
BradyPlanden Mar 13, 2024
e7aef79
Updt SciPy & BaseOptimiser for maximum iterations limit - fixes #237
BradyPlanden Mar 13, 2024
afd4990
add infeasible cost tests, remove redundant scipyminimise maxiter opt…
BradyPlanden Mar 13, 2024
a9ea84c
Merge pull request #224 from pybop-team/177c-plotting-capabilities
BradyPlanden Mar 13, 2024
05c7f20
Merge branch '177-plotting-capabilities' into 177b-plotting-capabilities
BradyPlanden Mar 14, 2024
db28440
Updt grad descent hypers for likelihood tests, add tol arg to scipy o…
BradyPlanden Mar 15, 2024
61d7d7a
Split kaleido dependancy to avoid windows hang
BradyPlanden Mar 15, 2024
744d166
small refactors and cleanup
BradyPlanden Mar 15, 2024
c1b3854
Updt changelog
BradyPlanden Mar 15, 2024
716c671
updt coverage, bugfix sigma check/wrap
BradyPlanden Mar 19, 2024
41cf0f8
Merge branch '177-plotting-capabilities' into 177b-plotting-capabilities
BradyPlanden Mar 19, 2024
a479136
coverage, bugfix model.simulateS1
BradyPlanden Mar 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix integration test logic, add gradient landscape plots, pin pytest …
…version due to breaking change in 8.1.0
  • Loading branch information
BradyPlanden committed Mar 4, 2024
commit 67d28876c50e303eb359707f80023f38fbbc0a74
5 changes: 3 additions & 2 deletions examples/scripts/exp_UKF.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@

# Verification step: Find the maximum likelihood estimate given the true parameters
estimation = observer.evaluate(x0)
estimation = estimation["2y"]

# Verification step: Add the estimate to the plot
line4 = go.Scatter(x=t_eval, y=estimation, name="Estimated trajectory", mode="lines")
line4 = go.Scatter(
x=t_eval, y=estimation["2y"], name="Estimated trajectory", mode="lines"
)
fig.add_trace(line4)
fig.show()

Expand Down
39 changes: 29 additions & 10 deletions examples/scripts/spm_adam.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,50 @@
]

# Generate data
sigma = 0.01
t_eval = np.arange(0, 900, 2)
values = model.predict(t_eval=t_eval)
corrupt_values = values["Voltage [V]"].data + np.random.normal(0, sigma, len(t_eval))
init_soc = 0.5
sigma = 0.003
experiment = pybop.Experiment(
[
(
"Discharge at 0.5C for 3 minutes (1 second period)",
"Charge at 0.5C for 3 minutes (1 second period)",
),
]
* 2
)
values = model.predict(init_soc=init_soc, experiment=experiment)


def noise(sigma):
return np.random.normal(0, sigma, len(values["Voltage [V]"].data))


# Form dataset
dataset = pybop.Dataset(
{
"Time [s]": t_eval,
"Time [s]": values["Time [s]"].data,
"Current function [A]": values["Current [A]"].data,
"Voltage [V]": corrupt_values,
"Bulk open-circuit voltage [V]": values["Bulk open-circuit voltage [V]"].data,
"Voltage [V]": values["Voltage [V]"].data + noise(sigma),
"Bulk open-circuit voltage [V]": values["Bulk open-circuit voltage [V]"].data
+ noise(sigma),
}
)

signal = ["Voltage [V]", "Bulk open-circuit voltage [V]"]
# Generate problem, cost function, and optimisation class
problem = pybop.FittingProblem(model, parameters, dataset, signal=signal)
problem = pybop.FittingProblem(
model, parameters, dataset, signal=signal, init_soc=init_soc
)
cost = pybop.RootMeanSquaredError(problem)
optim = pybop.Optimisation(
cost,
optimiser=pybop.Adam,
verbose=True,
allow_infeasible_solutions=True,
sigma0=sigma,
sigma0=0.05,
)
optim.set_max_iterations(100)
optim.set_max_unchanged_iterations(20)
optim.set_max_unchanged_iterations(45)

# Run optimisation
x, final_cost = optim.run()
Expand All @@ -64,3 +80,6 @@

# Plot the cost landscape with optimisation path
pybop.plot_optim2d(optim, steps=15)

# Plot the cost and gradient landscapes
pybop.plot_cost2d(cost, gradient=True, steps=3)
2 changes: 1 addition & 1 deletion noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def coverage(session):
"--cov-report=xml",
)
session.run(
"pytest", "--plots", "--cov", "--cov-append", "--cov-report=xml", "-n", "1"
"pytest", "--plots", "--cov", "--cov-append", "--cov-report=xml", "-n", "0"
)


Expand Down
13 changes: 7 additions & 6 deletions pybop/costs/fitting_costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@
for key in y:
if key not in ["Time [s]", "Discharge capacity [A.h]"]:
if len(y.get(key, [])) != len(self._target.get(key, [])):
e = np.float64(np.inf)
de = self._de * np.ones(self.n_parameters)
return e, de

Check warning on line 87 in pybop/costs/fitting_costs.py

View check run for this annotation

Codecov / codecov/patch

pybop/costs/fitting_costs.py#L85-L87

Added lines #L85 - L87 were not covered by tests

r = np.array(
[
Expand All @@ -98,16 +98,17 @@
r = r.reshape(self.problem.n_time_data)
dy = dy.reshape(self.n_parameters, self.problem.n_time_data)
e = np.sqrt(np.mean(r**2))
de = np.mean((r * dy), axis=1) / np.sqrt(
np.mean((r * dy) ** 2, axis=1) + np.finfo(float).eps
de = np.mean((r * dy), axis=1) / (
np.sqrt(np.mean((r * dy) ** 2, axis=1) + np.finfo(float).eps)
)
return e.item(), de.flatten()

else:
r = r.reshape(self.n_outputs, self.problem.n_time_data)
e = np.sqrt(np.mean(r**2, axis=1))
de = np.mean((r[:, :, np.newaxis] * dy), axis=1) / np.sqrt(
np.mean((r[:, :, np.newaxis] * dy) ** 2, axis=1) + np.finfo(float).eps
de = np.mean((r[:, :, np.newaxis] * dy), axis=1) / (
np.sqrt(np.mean((r[:, :, np.newaxis] * dy) ** 2, axis=1))
+ np.finfo(float).eps
)
return np.sum(e), np.sum(de, axis=1)

Expand Down Expand Up @@ -162,7 +163,7 @@

e = np.array(
[
np.sum(((prediction[signal] - self._target[signal]) ** 2), axis=0)
np.sum(((prediction[signal] - self._target[signal]) ** 2))
for signal in prediction
if signal not in ["Time [s]", "Discharge capacity [A.h]"]
]
Expand Down Expand Up @@ -196,9 +197,9 @@
for key in y:
if key not in ["Time [s]", "Discharge capacity [A.h]"]:
if len(y.get(key, [])) != len(self._target.get(key, [])):
e = np.float64(np.inf)
de = self._de * np.ones(self.n_parameters)
return e, de

Check warning on line 202 in pybop/costs/fitting_costs.py

View check run for this annotation

Codecov / codecov/patch

pybop/costs/fitting_costs.py#L200-L202

Added lines #L200 - L202 were not covered by tests

r = np.array(
[
Expand All @@ -217,7 +218,7 @@

else:
r = r.reshape(self.n_outputs, self.problem.n_time_data)
e = np.sum(r**2, axis=0)
e = np.sum(r**2, axis=1)
de = 2 * np.sum((r[:, :, np.newaxis] * dy), axis=1)
return np.sum(e), np.sum(de, axis=1)

Expand Down
47 changes: 46 additions & 1 deletion pybop/plotting/plot_cost2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import numpy as np


def plot_cost2d(cost, bounds=None, steps=10, show=True, **layout_kwargs):
def plot_cost2d(
cost, gradient=False, bounds=None, steps=10, show=True, **layout_kwargs
):
"""
Plot a 2D visualisation of a cost landscape using Plotly.

Expand Down Expand Up @@ -54,6 +56,23 @@
for j, yj in enumerate(y):
costs[j, i] = cost(np.array([xi, yj]))

if gradient:
grad_parameter_costs = []

Check warning on line 60 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L60

Added line #L60 was not covered by tests

# Determine the number of gradient outputs from cost.evaluateS1
num_gradients = len(cost.evaluateS1(np.array([x[0], y[0]]))[1])

Check warning on line 63 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L63

Added line #L63 was not covered by tests

# Create an array to hold each gradient output & populate
grads = [np.zeros((len(y), len(x))) for _ in range(num_gradients)]
for i, xi in enumerate(x):
for j, yj in enumerate(y):
(*current_grads,) = cost.evaluateS1(np.array([xi, yj]))[1]
for k, grad_output in enumerate(current_grads):
grads[k][j, i] = grad_output

Check warning on line 71 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L66-L71

Added lines #L66 - L71 were not covered by tests

# Append the arrays to the grad_parameter_costs list
grad_parameter_costs.extend(grads)

Check warning on line 74 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L74

Added line #L74 was not covered by tests

# Import plotly only when needed
go = pybop.PlotlyManager().go

Expand All @@ -80,6 +99,32 @@
elif show:
fig.show()

if gradient:
grad_figs = []
for i, grad_costs in enumerate(grad_parameter_costs):

Check warning on line 104 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L103-L104

Added lines #L103 - L104 were not covered by tests
# Update title for gradient plots
updated_layout_options = layout_options.copy()
updated_layout_options["title"] = f"Gradient for Parameter: {i+1}"

Check warning on line 107 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L106-L107

Added lines #L106 - L107 were not covered by tests

# Create contour plot with updated layout options
grad_layout = go.Layout(updated_layout_options)

Check warning on line 110 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L110

Added line #L110 was not covered by tests

# Create fig
grad_fig = go.Figure(

Check warning on line 113 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L113

Added line #L113 was not covered by tests
data=[go.Contour(x=x, y=y, z=grad_costs)], layout=grad_layout
)
grad_fig.update_layout(**layout_kwargs)

Check warning on line 116 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L116

Added line #L116 was not covered by tests

if "ipykernel" in sys.modules and show:
grad_fig.show("svg")
elif show:
grad_fig.show()

Check warning on line 121 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L118-L121

Added lines #L118 - L121 were not covered by tests

# append grad_fig to list
grad_figs.append(grad_fig)

Check warning on line 124 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L124

Added line #L124 was not covered by tests

return fig, grad_figs

Check warning on line 126 in pybop/plotting/plot_cost2d.py

View check run for this annotation

Codecov / codecov/patch

pybop/plotting/plot_cost2d.py#L126

Added line #L126 was not covered by tests

return fig


Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ dev = [
"nox",
"nbmake",
"pre-commit",
"pytest>=6",
"pytest<=8",
"pytest-cov",
"pytest-mock",
"pytest-xdist",
Expand Down
Loading
Loading