Una red neuronal informada por física (PINN) se parece mucho a darle a una red neuronal regular una hoja de trucos. Sin una hoja de trucos, podríamos estimar las soluciones a un sistema físico utilizando solo una red neuronal. Posición (incógnita) y tiempo
Los PINN ofrecen un método para combinar la física conocida sobre un sistema y una estimación de la red neuronal. Esto se logra ingeniosamente utilizando la diferenciación automática y una función de pérdida basada en la física. Como resultado, podemos lograr mejores resultados con menos datos.
Orden del día
- Proporcionar una interpretación de la ecuación de calor
- Simular datos utilizando datos de temperatura
- Codifique una solución para la difusividad térmica κ y fuente de calor Q (x, t) Usando Deepxde
- Explicar la diferencia entre problemas hacia adelante e inverso en la teoría de PDE
Estos son los datos con los que trabajaremos. Fingeremos que usamos sensores para recolectar temperaturas de una barra de 1 metro durante 5 segundos.
Ilustración del autor
En pocas palabras, los PINN proporcionan una nueva forma de aproximar las soluciones a las ecuaciones físicas (ODES, PDE, SDE) mediante el uso de datos del sistema subyacente y nuestra ecuación física.
Interpretando la ecuación de calor
Ilustración del autor
El derivado parcial de la izquierda representa cómo cambia la temperatura con el tiempo. Esta es una función de posición (x) y tiempo
Este término se multiplica por la difusividad térmica (κ), que depende de las propiedades del material. Esperamos que algo conductivo, como los metales, se calienta más rápido. Cuando ∇²u es positiva, la temperatura en ese punto es menor que el promedio de sus vecinos, por lo que el calor tiende a fluir hacia el punto. Cuando ∇²u es negativo, el punto es más caliente que su entorno, y el calor tiende a fluir. Cuando ∇²u es cero, el punto está en equilibrio térmico con su vecindario inmediato.
En la imagen a continuación, la parte superior de nuestra función podría representar un punto muy caliente. Observe cómo el laplaciano es negativo, lo que indica que el calor fluirá de este punto caliente a los puntos circundantes más fríos. El laplaciano es una medida de curvatura alrededor de un punto. En la ecuación de calor, esa es la curvatura del perfil de temperatura.
Ilustración del autor
Generando los datos
Debo admitir que en realidad no quemé una barra y medí sus cambios de temperatura con el tiempo. Simulé los datos utilizando la ecuación de calor. Este es el código que usamos para simular los datos. Todo se puede encontrar en mi Github.
#--- Generating Data ---
L = 1.0 # Rod Length (m)
Nx = 51 # Number of spatial points
dx = L / (Nx - 1) # Spatial step
T_total = 5.0 # Total time (s)
Nt = 5000 # Number of time steps
dt = T_total / Nt # Time step
kappa = 0.01 # Thermal diffusivity (m^2/s)
q = 1.0 # Constant heat source term (C/s)
u = np.zeros(Nx)
x_coords = np.linspace(0, L, Nx)
temperature_data_raw = []
header = ["Time (s)"] + [f"x={x:.2f}m" for x in x_coords]
temperature_data_raw.append(header)
temperature_data_raw.append([0.0] + u.tolist())
for n in range(1, Nt + 1):
u_new = np.copy(u)
for i in range(1, Nx - 1):
u_new[i] = u[i] + dt * (kappa * (u[i+1] - 2*u[i] + u[i-1]) / (dx**2) + q)
u_new[0] = 0.0
u_new[Nx-1] = 0.0
u = u_new
if n % 50 == 0 or n == Nt:
temperature_data_raw.append([n * dt] + u.tolist())
Para generar estos datos, utilizamos κ = 0.01 y q = 1, Pero solo x, t, y u se utilizará para estimar κ y q. En otras palabras, fingimos no saber κ y Q y busca estiAjustarlos solo con x, t, y u. Esta superficie es tridimensional, pero representa la temperatura de un Varilla con el tiempo.
Ilustración del autor
Organizar y dividir datos
Aquí, simplemente reorganizamos nuestros datos en columnas para su posición. (incógnita)tiempo
# --- Prepare (x, t, u) triplet data ---
data_triplets = []
for _, row in df.iterrows():
t = row["Time (s)"]
for col in df.columns[1:]:
x = float(col.split('=')[1][:-1])
u_val = row[col]
data_triplets.append([x, t, u_val])
data_array = np.array(data_triplets)
X_data = data_array[:, 0:2] # X position (x), time
y_data = data_array[:, 2:3] # Y temperature (u)
Mantenemos el tamaño de nuestra prueba (20%)
# --- Train/test split ---
from sklearn.model_selection import train_test_split
x_train, x_test, u_train, u_test = train_test_split(X_data, y_data, test_size=0.2, random_state=42)
Train Test Split
Debido a que nuestro PINN recibe posición (x) y tiempo
\[
\frac{\partial u}{\partial t}, \quad
\frac{\partial u}{\partial x}, \quad
\frac{\partial^2 u}{\partial x^2}, \quad
\nabla^2 u
\]
Entonces, encontrar las constantes se convierte en un problema de probar diferentes valores para κ y Q (x, t)minimizando el residual dado por la función de pérdida.
Paquetes y semillas y backends de conexión
No olvides instalar Profundo Si aún no lo has hecho.
!pip install --upgrade deepxde
Estas son todas las bibliotecas que usaremos. Para que esto funcione, asegúrese de estar usando TensorFlow 2 Como el backend de Deepxde.
# --- Imports and Connecting Backends ---
import os
os.environ["DDE_BACKEND"] = "tensorflow" # Set to TF2 backend
import deepxde as dde
print("Backend:", dde.backend.__name__) # Should now say: deepxde.backend.tensorflow
import tensorflow as tf
print("TensorFlow version:", tf.__version__)
print("Is eager execution enabled?", tf.executing_eagerly())
import deepxde as dde
print("DeepXDE version:", dde.__version__)
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from deepxde.backend import tf
import random
import torch
Para replicabilidad, estableceremos nuestro semillas a 42. Puede usar este código en varias bibliotecas.
# --- Setting Seeds ---
SEED = 42
random.seed(SEED)
np.random.seed(SEED)
os.environ['PYTHONHASHSEED'] = str(SEED)
tf.random.set_seed(SEED)
torch.manual_seed(SEED)
torch.cuda.manual_seed(SEED)
torch.cuda.manual_seed_all(SEED)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
Codificando el pinn
Ambiente
Debido a que la ecuación de calor modela la temperatura tanto en espacio como en el tiempo, debemos considerar el dominio espacial y el dominio temporal.
- Espacio (0, 1) para una barra de 1 metro
- Tiempo (0,5) durante 5 segundos de observación
- Geomtime combina estas dimensiones
# --- Geometry and domain ---
geom = dde.geometry.Interval(0, 1)
timedomain = dde.geometry.TimeDomain(0, 5.0)
geomtime = dde.geometry.GeometryXTime(geom, timedomain)
Seleccione los valores en el PDE que desea inferir de los datos. Aquí elegimos Kappa (κ) y fuente de calor Q
# --- Trainable variables ---
raw_kappa = tf.Variable(0.0)
raw_q = tf.Variable(0.0)
La pérdida de física
Nuestra pérdida de física es simple: todos los elementos de la ecuación de calor en un lado. Cuando esto es cero, nuestra ecuación se mantiene. La pérdida de física se minimizará, por lo que nuestra estimación para κ y Q Mejor se adapta a la física. Si tuviéramos una ecuación física A = Bsimplemente moveríamos todos los elementos a un lado y definiríamos nuestro residuo como A – B = 0. Cuanto más cerca A – B es cero cuanto mejor nuestro pinn captura la dinámica de A = B.
def pde(x, u):
du_t = dde.grad.jacobian(u, x, j=1)
du_xx = dde.grad.hessian(u, x, i=0, j=0)
kappa = tf.nn.softplus(raw_kappa)
q = raw_q
return du_t - kappa * du_xx - q
\[
\text{Residual}(x, t) = \frac{\partial u}{\partial t} – \kappa \frac{\partial^2 u}{\partial x^2} – q
\]
Pinos
Las derivadas presentes en el residual se calculan aplicando la regla de la cadena a través del gráfico computacional durante backpropagation. Estos derivados permiten que el PINN evalúe el residual de la PDE.
Opcionalmente, también podríamos agregar una pérdida de datos, también conocida como pérdida de nuestra red neuronal estándar, que minimiza la diferencia entre la predicción y los valores conocidos.
# --- Adding Data Loss ---
def custom_loss(y_true, y_pred):
base_loss = tf.reduce_mean(tf.square(y_true - y_pred))
reg = 10.0 * (tf.square(tf.nn.softplus(raw_kappa) - 0.01) + tf.square(raw_q - 1.0))
return base_loss + reg #Loss from Data + Loss from PDE
A continuación, creamos un Tiempo de tiempo Objeto de datos, que es un tipo de conjunto de datos en Deepxde para resolver PDE dependientes del tiempo. Prepara la geometría, la física, las condiciones de contorno y las condiciones iniciales para capacitar un pinn.
# --- DeepXDE Data object ---
data = dde.data.TimePDE(
geomtime,
pde, #loss function
[dde.PointSetBC(x_train, u_train)], # Observed values as pseudo-BC
num_domain=10000,
num_boundary=0,
num_initial=0,
anchors=x_test,
)
La arquitectura [2] + + [64]*3 + [1] se usa. Obtenemos esto de dos entradas (x, t)64 neuronas, 3 capas ocultas y 1 salida (u).
[2] + + [64]*3 + [1] = [2, 64, 64, 64, 1]
A tangente hiperbólico La función de activación se usa para capturar el comportamiento lineal y no lineal en la solución PDE. El inicializador de peso “Glorot Normal” se usa para evitar gradientes de desaparición o explosión en el entrenamiento.
# --- Neural Network ---
net = dde.maps.FNN([2] + [64]*3 + [1], "tanh", "Glorot normal")
model = dde.Model(data, net)
Podemos usar diferentes optimizadores. Para mí, L-BFGS-B funcionó mejor.
# --- Train with Adam ---
model.compile("adam", lr=1e-4, loss=custom_loss,
external_trainable_variables=[raw_kappa, raw_q])
losshistory, train_state = model.train(iterations=100000)
# --- Optional L-BFGS-B fine-tuning ---
model.compile("L-BFGS-B", loss=custom_loss,
external_trainable_variables=[raw_kappa, raw_q])
El entrenamiento podría llevar un tiempo …
Ilustración del autor
…
Ilustración del autor
Pérdida de modelo
Monitorear la pérdida del modelo a lo largo del tiempo es una buena manera de observar el sobreajuste. Debido a que solo usamos la pérdida de física, no vemos el componente 2, que de otro modo sería la pérdida de datos. Dado que todo el código está en mi Githubsiéntete libre de ejecutarlo y ver cómo cambiar el tasa de aprendizaje cambiará la varianza en la pérdida del modelo.
# --- Plot loss ---
dde.utils.plot_loss_history(losshistory)
plt.yscale("log")
plt.title("Training Loss (log scale)")
plt.xlabel("Iteration")
plt.ylabel("Loss")
plt.grid(True)
plt.show()
# --- Detailed loss plotting ---
losses = np.array(losshistory.loss_train) # shape: (iterations, num_components)
iterations = np.arange(1, len(losses) + 1)
plt.figure(figsize=(10, 6))
plt.plot(iterations, losses[:, 0], label="Train Total Loss")
# If there are multiple components (e.g., PDE + BC + data), plot them
if losses.shape[1] > 1:
for i in range(1, losses.shape[1]):
plt.plot(iterations, losses[:, i], label=f"Train Loss Component {i}")
# Plot validation loss if available
if losshistory.loss_test:
val_losses = np.array(losshistory.loss_test)
plt.plot(iterations, val_losses[:, 0], '--', label="Validation Loss", color="black")
# Optionally: plot validation loss components
if val_losses.shape[1] > 1:
for i in range(1, val_losses.shape[1]):
plt.plot(iterations, val_losses[:, i], '--', label=f"Validation Loss Component {i}", alpha=0.6)
plt.xlabel("Iteration")
plt.ylabel("Loss")
plt.yscale("log")
plt.title("Training and Validation Loss Over Time")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
Resultados
Podemos inferir estas constantes con gran precisión. Parte del éxito se debe a centrarse solo en la pérdida de física y no incorporar nuestra pérdida de datos. Esta es una opción en PINNS. La precisión aquí también se atribuye a la ausencia de ruido En el proceso de generación de datos.
# --- Results ---
learned_kappa = tf.nn.softplus(raw_kappa).numpy()
learned_q = raw_q.numpy()
print("\n--- Results ---")
print(f"True kappa: 0.01, Learned kappa: {learned_kappa:.6f}")
print(f"True q: 1.0, Learned q: {learned_q:.6f}")
Problemas hacia adelante e inverso:
En este artículo, resolvimos el problema inverso del PDE. Esto implica resolver las dos constantes rojas.
Ilustración del autor
El problema delantero se caracteriza de la siguiente manera: dado el PDE, los parámetros subyacentes, las condiciones de contorno y las condiciones de forzamiento, nos gustaría calcular el estado del sistema. En este caso, temperatura (u). Este problema implica predecir el sistema. Los problemas de avance son generalmente bien plenado; a La solución existe y es única. Estas soluciones dependen continuamente de las entradas.
El problema inverso se caracteriza como tal: dado que el estado del sistema (temperatura) infiere los parámetros subyacentes, las condiciones de contorno o los términos de forzamiento que mejor explican los datos observados. Aquí, estimamos los parámetros desconocidos. Los problemas inversos son a menudo mal plenadosin singularidad o estabilidad.
Adelante: Predecir el resultado cuando conoce las causas.
Inverso: Calcule las causas (o las mejores entradas) del resultado observado.
Inintuitivamente, el problema inverso generalmente se resuelve primero. Conocer los parámetros ayuda enormemente a descubrir el problema de avance. Si pudiéramos averiguar Kappa (κ) y Q (x, t)Resolver la temperatura u (x, t) sería mucho más fácil.
Conclusión
Los PINN proporcionan un enfoque novedoso para resolver los problemas inversos y avanzados en las ecuaciones de física. Su ventaja sobre las redes neuronales es que nos permiten resolver mejor estos problemas con menos datos, ya que incorporan el conocimiento existente sobre la física en la red neuronal. Esto también tiene el beneficio adicional de una mejor generalización. Los pinns son particularmente buenos para resolver problemas inversos.
Referencias
- Raissi, M., Perdikaris, P. y Karnidakis, GE (2019). Redes neuronales informadas por física: un marco de aprendizaje profundo para resolver problemas hacia adelante e inversos que involucran ecuaciones diferenciales parciales no lineales. Journal of Computational Physics, 378686–707. https://doi.org/10.1016/j.jcp.2018.10.045
- Raissi, M. (2018). Modelos de física oculta profunda: aprendizaje profundo de ecuaciones diferenciales parciales no lineales. Journal of Machine Learning Research, 19(25), 1–24. https://arxiv.org/abs/1801.06637
- Lu, L., Meng, X., Mao, Z. y Karnidakis, GE (2021). Deepxde: una biblioteca de aprendizaje profundo para resolver ecuaciones diferenciales. Siam Review, 63(1), 208–228. https://doi.org/10.1137/19m1274067
- Deepxde desarrolladores. (Dakota del Norte). Deepxde: una biblioteca de aprendizaje profundo para resolver ecuaciones diferenciales [Computer software documentation]. Recuperado 25 de julio de 2025de https://deepxde.readthedocs.io/en/latest/
- Ren, Z., Zhou, S., Liu, D. y Liu, Q. (2025). Redes neuronales informadas por física: una revisión de la evolución metodológica, los fundamentos teóricos y las fronteras interdisciplinarias hacia la computación científica a continuación. Ciencias aplicadas, 15(14), Artículo 8092. https://doi.org/10.3390/app15148092 MDPI
- Torres, E., Schiefer, J. y Niepert, M. (2025). Redes neuronales informadas por física adaptativa: una encuesta. arxiv. https://arxiv.org/abs/2503.18181 ARXIV+1openReview+1