Implementieren Sie Physik informiertes neuronales Netzwerk mit Pytorch
Posted: 18 Mar 2025, 18:42
Ich fand ein sehr interessantes Papier, Physik, informiert Deep Learning (Teil I): datengesteuerte Lösungen nichtlinearer partieller Differentialgleichungen und möchten ihm einen Versuch vorstellen. Dafür erstelle ich ein Dummy -Problem und implementiere das, was ich aus dem Papier verstehe. Tatsächlich können wir die analytische Lösung y (x) = sin (x) leicht erraten. Aber ich möchte sehen, wie das Modell die Lösung mit Pinn.
Aber das Endergebnis war so enttäuschend. Das Modell konnte die einfache ODE nicht lernen. Ich habe mich gefragt, dass die Modellarchitektur von mir einige Probleme hat, die ich selbst nicht herausfinden konnte. Kann jemand eine Verbesserung vorschlagen?
Code: Select all
# import libraries
import torch
import torch.autograd as autograd # computation graph
import torch.nn as nn # neural networks
import torch.optim as optim # optimizers e.g. gradient descent, ADAM, etc.
import matplotlib.pyplot as plt
import numpy as np
#Set default dtype to float32
torch.set_default_dtype(torch.float)
#PyTorch random number generator
torch.manual_seed(1234)
# Device configuration
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(device)
< /code>
Modellarchitektur < /h3>
## Model Architecture
class FCN(nn.Module):
##Neural Network
def __init__(self,layers):
super().__init__() #call __init__ from parent class
# activation function
self.activation = nn.Tanh()
# loss function
self.loss_function = nn.MSELoss(reduction ='mean')
# Initialise neural network as a list using nn.Modulelist
self.linears = nn.ModuleList([nn.Linear(layers[i], layers[i+1]) for i in range(len(layers)-1)])
self.iter = 0
# Xavier Normal Initialization
for i in range(len(layers)-1):
nn.init.xavier_normal_(self.linears[i].weight.data, gain=1.0)
# set biases to zero
nn.init.zeros_(self.linears[i].bias.data)
# foward pass
def forward(self,x):
if torch.is_tensor(x) != True:
x = torch.from_numpy(x)
a = x.float()
for i in range(len(layers)-2):
z = self.linears[i](a)
a = self.activation(z)
a = self.linears[-1](a)
return a
# Loss Functions
#Loss PDE
def lossPDE(self,x_PDE):
g=x_PDE.clone()
g.requires_grad=True #Enable differentiation
f=self.forward(g)
f_x=autograd.grad(f,g,torch.ones([x_PDE.shape[0],1]).to(device),\
retain_graph=True, create_graph=True)[0]
loss_PDE=self.loss_function(f_x,PDE(g))
return loss_PDE
< /code>
Daten generieren < /h2>
# generate training and evaluation points
x = torch.linspace(min,max,total_points).view(-1,1)
y = torch.sin(x)
print(x.shape, y.shape)
# Set Boundary conditions:
# Actually for this problem
# we don't need extra boundary constraint
# as it was concided with x_PDE point & value
# BC_1=x[0,:]
# BC_2=x[-1,:]
# print(BC_1,BC_2)
# x_BC=torch.vstack([BC_1,BC_2])
# print(x_BC)
x_PDE = x[1:-1,:]
print(x_PDE.shape)
x_PDE=x_PDE.float().to(device)
# x_BC=x_BC.to(device)
#Create Model
layers = np.array([1,50,50,50,50,1])
model = FCN(layers)
print(model)
model.to(device)
params = list(model.parameters())
optimizer = torch.optim.Adam(model.parameters(),lr=lr,amsgrad=False)
< /code>
Zuges neuronales Netzwerk < /h2>
for i in range(500):
yh = model(x_PDE)
loss = model.loss_PDE(x_PDE) # use mean squared error
optimizer.zero_grad()
loss.backward()
optimizer.step()
if i%(500/10)==0:
print(loss)
< /code>
Vorhersage die Lösung mit Pinn < /h2>
# predict the solution beyond training set
x = torch.linspace(0,max+max,total_points).view(-1,1)
yh=model(x.to(device))
y=torch.sin(x)
#Error
print(model.lossBC(x.to(device)))
y_plot=y.detach().numpy()
yh_plot=yh.detach().cpu().numpy()
fig, ax1 = plt.subplots()
ax1.plot(x,y_plot,color='blue',label='Real')
ax1.plot(x,yh_plot,color='red',label='Predicted')
ax1.set_xlabel('x',color='black')
ax1.set_ylabel('f(x)',color='black')
ax1.tick_params(axis='y', color='black')
ax1.legend(loc = 'upper left')