神经网络求解偏微分方程时遇到的一些问题

  1. 方程的选择与处理

首先,选取的偏微分方程参考了如下博客

神经网络学习(三):解偏微分方程_LusinLee的博客-CSDN博客_神经网络求解偏微分方程

这里的偏微分方程为:

在设计损失函数时,我选择了通过改变网络输出函数,使得在计算损失函数时不需要考虑边界条件,相关公式如下:

其中,NN(x,t)为神经网络输出。不难验证,此时的g(x,t)无论NN(x,t)为何值,都必然满足边界条件。只需要:

  1. 优化器的选择

在选取优化器时,我遇到了这样的问题:使用SGD得到的结果都比较糟糕,而选择Adam则会得到不错的结果。原因我并不清楚。

  1. 网络结构

通常情况下,我们是不知道原函数的值域的。因此在输出层设置激活函数可能会使得网络输出的值永

远无法接近真实值。因此我输出层没有设置激活函数(也许RReLU可以?)。同时,由于不知道原函数的值域,因此输出层前一层的神经元需要多一些,便于拟合值域跨度较大的函数。

  1. 反向传播

pytorch在进行反向传播时,.backward()是不能对输入的自变量x,t使用的,此时要使用:

torch.autograd.grad(outputs,inputs,grad_outputs,create_graph=True)。其中,outputs为输出,inputs为输入,grad_outputs需要设置为形状与输出形状相同的全1的tensor。create_graph需设置为真,否则后续无法继续求导

同时需要注意,torch.autograd.grad的返回值不是tensor。torch.autograd.grad()[0]才是所需要的trensor。

最后附上pytorch代码:

#coding:gb2312
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d


#定义pde类
class pde(torch.nn.Module):
    def __init__(self,n_features):
        super(pde,self).__init__()
        self.main=nn.Sequential(
            nn.Linear(2,100),
            nn.Tanh(),
            nn.Linear(100,100),
            nn.Tanh(),
            nn.Linear(100,20),
            nn.Tanh(),
            nn.Linear(20,20),
            nn.Tanh(),
            nn.Linear(20,1),
            )
    def forward(self,inputs):
        inputs = inputs.to(torch.float32)
        out=self.main(inputs)
        out=out.reshape(10000)
        
        out=(inputs[:,0]**2-1)*inputs[:,1]*out-torch.sin(3.1415926*inputs[:,0])
        out=out.reshape(-1,1)
        
        return out

pdesolver=pde(1)#额,这个1似乎什么作用都没起到……
pdesolver=pdesolver.cuda()
optimizer=torch.optim.Adam(pdesolver.parameters(),lr=0.001)
loss_func=torch.nn.MSELoss()

#以下是在设置自变量x,t的值
xt=np.zeros(10000*2).reshape(10000,2)
temp_j=np.linspace(-1,1,100)
for i in range(100):
    xt[i*100:i*100+100,0]=temp_j[i]
    xt[i*100:i*100+100,1]=np.linspace(0,1,100)
    
xt=torch.tensor(xt,requires_grad=True).cuda()


p=1
i=0
while p>0.02:
    i+=1
    y_pre = pdesolver(xt)
    #以下是分别求出各个所需要的偏微分
    dy=torch.autograd.grad(outputs=y_pre,inputs=xt,grad_outputs=torch.ones_like(y_pre),create_graph=True)
    dyx=(dy[0][:,0]).reshape(-1,1)
    dyt=(dy[0][:,1]).reshape(-1,1)

    ddy=torch.autograd.grad(outputs=dyx,inputs=xt,grad_outputs=torch.ones_like(y_pre),create_graph=True)
    ddyx=ddy[0][:,0].reshape(-1,1)
    #偏微分方程的左右两侧
    left=dyt+y_pre*dyx
    right=0.01/3.1415926*ddyx

    loss = loss_func(left.float(),right.float())
    p=loss.item()
    print(i,p)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
 
    

#以下就全是可视化了
u=pdesolver(xt)
u=u.reshape(-1)
u=u.reshape(100,100)
u=u.cpu()
u=u.detach().numpy()

x=temp_j
t=np.linspace(0,1,100)
T ,X= np.meshgrid( t,x)
fig = plt.figure()
ax = plt.axes(projection='3d')
print(X)
print(T)
for i in u:
    print(i)
ax.plot_surface(X, T, u,cmap='rainbow', edgecolor='none')
plt.show()

结果:

神经网络求解偏微分方程时遇到的一些问题_第1张图片

你可能感兴趣的:(pytorch,神经网络)