Skip to content

Commit

Permalink
fix: functions.py fix based on given feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
lilpuzeen committed Jan 19, 2024
1 parent c70fa90 commit 1eab34d
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 75 deletions.
85 changes: 33 additions & 52 deletions functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,116 +4,97 @@
Also model creation and training.
"""

from numbers import Real
from scipy.integrate import odeint
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.layers import Dense, Input, Concatenate
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam


def system(y: Real, a: Real, b: Real, c: Real, d: Real) -> list[Real]:
"""Definition of a system of differential equations"""
# Определение системы дифференциальных уравнений
def system(y, t, a, b, c, d):
y1, y2 = y
dy1_dt = a * y1 + b * y2
dy2_dt = c * y1 + d * y2
return [dy1_dt, dy2_dt]


def calculate_mse(y_true: Real, y_pred: Real) -> Real:
"""Function for calculating MSE"""
# Функция для расчета MSE
def calculate_mse(y_true, y_pred):
return np.mean((y_true - y_pred) ** 2)


def build_neural_ode_model_system() -> Model:
"""Definition of the NeuralODE model for the system of equations"""
# Определение модели NeuralODE для системы уравнений
def build_neural_ode_model_system():
input_y = Input(shape=(2,))
input_t = Input(shape=(1,))
combined_input = Concatenate()([input_y, input_t])
x = Dense(units=64, activation='relu')(combined_input)
x = Dense(units=64, activation='relu')(x)
x = Dense(units=64, activation='relu')(x)
output_a = Dense(units=1, name='output_a')(x)
output_b = Dense(units=1, name='output_b')(x)
output_c = Dense(units=1, name='output_c')(x)
output_d = Dense(units=1, name='output_d')(x)
model = Model(inputs=[input_y, input_t], outputs=[output_a, output_b, output_c, output_d])
output_dy = Dense(units=2)(x) # Предсказание производных dy1_dt и dy2_dt
model = Model(inputs=[input_y, input_t], outputs=output_dy)
return model


neural_ode_model_system = build_neural_ode_model_system()
neural_ode_model_system.compile(optimizer='adam', loss='mse')


def conduct_experiment(a: Real, b: Real, c: Real, d: Real, experiment_id: int) -> None:
"""Function for a single experiment"""
# Initial conditions for all experiments
# Функция для проведения одного эксперимента
def conduct_experiment(a, b, c, d, experiment_id, time_points):
# Начальные условия для всех экспериментов
y0 = [1.0, 2.0]
time_points = np.linspace(0, 5, 100)

# Solving the system of equations and adding noise to the data
# Решение системы уравнений и добавление шума к данным
solution = odeint(system, y0, time_points, args=(a, b, c, d))
noise = np.random.normal(0, 0.5, solution.shape)
noisy_data = solution + noise

# Preparing data for training
x_train = [noisy_data, time_points.reshape(-1, 1)]
y_train = [np.full((len(time_points), 1), a),
np.full((len(time_points), 1), b),
np.full((len(time_points), 1), c),
np.full((len(time_points), 1), d)]
# Подготовка данных для обучения
X_train = [noisy_data, time_points.reshape(-1, 1)]
y_train = solution

# Model training
neural_ode_model_system.fit(x_train, y_train, epochs=200, verbose=1)
# Обучение модели
neural_ode_model_system.fit(X_train, y_train, epochs=200, verbose=1)

# Prediction of parameters
predicted_params = neural_ode_model_system.predict(x_train)
# Предсказание производных
predicted_derivatives = neural_ode_model_system.predict(X_train)

# Predicted parameters
predicted_a, predicted_b, predicted_c, predicted_d = [p.flatten()[0] for p in predicted_params]

# Results output
# Вывод результатов
print(f"Эксперимент {experiment_id}:")
print("Истинные параметры:", [a, b, c, d])
print("Предсказанные параметры (с шумом):", [predicted_a, predicted_b, predicted_c, predicted_d])

# Prediction of parameters based on true data (without noise)
predicted_params_clean = neural_ode_model_system.predict([solution, time_points.reshape(-1, 1)])
predicted_a_clean, predicted_b_clean, predicted_c_clean, predicted_d_clean = [p.flatten()[0] for p in
predicted_params_clean]
print("Предсказанные параметры (без шума):",
[predicted_a_clean, predicted_b_clean, predicted_c_clean, predicted_d_clean])

# Creating a predicted solution based on the predicted parameters
predicted_solution = odeint(system, y0, time_points, args=(predicted_a, predicted_b, predicted_c, predicted_d))

# MSE calculation for predicted parameters
mse = calculate_mse(solution, predicted_solution)
print("MSE:", mse)

# Visualization of results
# Визуализация
plt.figure(figsize=(10, 8))

# Subgraph for y1
# Подграфик для y1
plt.subplot(2, 1, 1)
plt.scatter(time_points, noisy_data[:, 0], label='Симулированные данные y1 с шумом', color='blue')
plt.scatter(time_points, solution[:, 0], label='Входные данные y1', color='orange')
plt.plot(time_points, predicted_solution[:, 0], label='Оптимизированные данные y1', color='red')
plt.plot(time_points, solution[:, 0], label='Истинные данные y1', color='green')
plt.plot(time_points, predicted_derivatives[:, 0], label='Предсказанные данные y1', color='red')
plt.xlabel('Время')
plt.ylabel('y1')
plt.title(f"Результаты эксперимента {experiment_id} для y1")
plt.legend()

# Subgraph for y2
# Подграфик для y2
plt.subplot(2, 1, 2)
plt.scatter(time_points, noisy_data[:, 1], label='Симулированные данные y2 с шумом', color='blue')
plt.scatter(time_points, solution[:, 1], label='Входные данные y2', color='orange')
plt.plot(time_points, predicted_solution[:, 1], label='Оптимизированные данные y2', color='red')
plt.plot(time_points, solution[:, 1], label='Истинные данные y2', color='blue')
plt.plot(time_points, solution[:, 1], label='Истинные данные y2', color='green')
plt.plot(time_points, predicted_derivatives[:, 1], label='Предсказанные данные y2', color='red')
plt.xlabel('Время')
plt.ylabel('y2')
plt.title(f"Результаты эксперимента {experiment_id} для y2")
plt.legend()
plt.tight_layout()
plt.show()

# Расчёт MSE для предсказанных производных
mse = calculate_mse(solution, predicted_derivatives)
print("MSE:", mse)

return solution, predicted_derivatives, mse
69 changes: 46 additions & 23 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,52 @@
Execution of the whole program should be done from here.
"""

import numpy as np
import matplotlib.pyplot as plt
from functions import conduct_experiment

# Параметры экспериментов
experiment_params = [
(-2, 1, 3, -4), # Эксперимент 1
(-1, 2, -3, 4), # Эксперимент 2
(0.5, -1.5, 2, -2.5), # Эксперимент 3
(1, -1, 1.5, -1.5), # Эксперимент 4
(-2.5, 2.5, -0.5, 0.5), # Эксперимент 5
(2, -2, 3, -3), # Эксперимент 6
(-1.5, 1, 2.5, -2), # Эксперимент 7
(1.5, -1, -2, 2), # Эксперимент 8
(-3, 3, -1, 1), # Эксперимент 9
(2.5, -2.5, 0.5, -0.5) # Эксперимент 10
]

def main():
"""Main function"""
# Experimental parameters
experiment_params = [
(-2, 1, 3, -4), # Experiment 1
(-1, 2, -3, 4), # Experiment 2
(0.5, -1.5, 2, -2.5), # Experiment 3
(1, -1, 1.5, -1.5), # Experiment 4
(-2.5, 2.5, -0.5, 0.5), # Experiment 5
(2, -2, 3, -3), # Experiment 6
(-1.5, 1, 2.5, -2), # Experiment 7
(1.5, -1, -2, 2), # Experiment 8
(-3, 3, -1, 1), # Experiment 9
(2.5, -2.5, 0.5, -0.5) # Experiment 10
]

# Running experiments
for i, params in enumerate(experiment_params, start=1):
conduct_experiment(*params, experiment_id=i)


if __name__ == '__main__':
main()
time_points = np.linspace(0, 5, 100)

# Переменные для хранения результатов
solutions = []
predicted_solutions = []
mse_values = []
max_derivatives = []

for i, params in enumerate(experiment_params, start=1):
solution, predicted_solution, mse = conduct_experiment(*params, experiment_id=i, time_points=time_points)

# Добавление результатов в массивы
mse_values.append(mse)

# Вычисление максимального значения производной для текущего решения
dy1_dt = np.gradient(solution[:, 0], time_points)
dy2_dt = np.gradient(solution[:, 1], time_points)
max_derivative = max(np.max(np.abs(dy1_dt)), np.max(np.abs(dy2_dt)))
max_derivatives.append(max_derivative)

print("Длина max_derivatives:", len(max_derivatives))
print("Длина mse_values:", len(mse_values))

# Визуализация зависимости погрешности от максимального значения производной
plt.figure(figsize=(10, 6))
plt.scatter(max_derivatives, mse_values, color='blue')
plt.xlabel('Максимальное значение производной')
plt.ylabel('MSE')
plt.title('Зависимость MSE от максимума производной на отрезке')
plt.grid(True)
plt.show()

0 comments on commit 1eab34d

Please sign in to comment.