当前位置:   article > 正文

PINN学习教程

pinn

首先给出数学上的知识。

1.eq?%5Cleft%20%28%20%5Csin%20x%20%5Cright%20%29%7B%7D%27%3D%5Ccos%20x

2.eq?%5Csin%20%5Cleft%20%28%200%20%5Cright%20%29%3D%5Csin%20%5Cleft%20%28%203.14%20%5Cright%20%29%3D%5Csin%20%5Cleft%20%28%20-3.14%20%5Cright%20%29%3D0

3.eq?%5Csin%20%5E%7B%5E2%7D%5Cleft%20%28%20x%20%5Cright%20%29+%5Ccos%20%5E%7B%5E2%7D%5Cleft%20%28%20x%20%5Cright%20%29-1%3D0

其次给出PINN最基础的理解与应用说明。

1.PINN中的MLP多层感知机的作用?

答:目的是用来拟合出我们需要的那个 常微分方程,即函数逼近器。

2.PINN中物理信息的作用?

答:用于约束MLP反向传播梯度下降求解时的解空间。所以PINN只需要更少的数据就能完成任务。

拟合sin(x)时的边界条件。

1. eq?%5Csin%20%5Cleft%20%28%200%20%5Cright%20%29%3D0

2.参照上面的数学式子。

PINN最容易入手的就是根据各种边界条件设计出不同的损失函数(loss function),让MLP最小化这些损失函数的和或者加权和。

下面是代码部分:

  1. import torch
  2. import torch.nn as nn
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. from torch import autograd
  6. class Net(nn.Module):
  7. def __init__(self, NN): # NN决定全连接层的神经元个数,对拟合快慢直接相关
  8. super(Net, self).__init__()
  9. self.input_layer = nn.Linear(1, NN)
  10. self.hidden_layer = nn.Linear(NN,int(NN/2))
  11. self.output_layer = nn.Linear(int(NN/2), 1)
  12. def forward(self, x):
  13. out = torch.tanh(self.input_layer(x))
  14. out = torch.tanh(self.hidden_layer(out))
  15. out_final = self.output_layer(out)
  16. return out_final
  17. net=Net(6) # 6个
  18. mse_cost_function = torch.nn.MSELoss(reduction='mean') # 最小化L2范数
  19. optimizer = torch.optim.Adam(net.parameters(),lr=1e-4) # 优化器
  20. def ode_01(x,net):
  21. # 使用神经网络net(x)作为偏微分方程的函数逼近器,每经过一次梯度更新就对对net(x)求一次导,代码中net(x)需要去逼近sin(x)
  22. y=net(x)
  23. # 求net(x)在0点的导数
  24. y_x = autograd.grad(y, x,grad_outputs=torch.ones_like(net(x)),create_graph=True)[0]
  25. # sin**2 + cos**2 - 1 = 0
  26. return torch.pow(y, 2)+torch.pow(y_x, 2)-1
  27. # 动态图
  28. plt.ion()
  29. # 总的迭代次数
  30. iterations=20000
  31. # 粒度N_,决定将区间分为多少个间隔
  32. N_ = 200
  33. for epoch in range(iterations):
  34. optimizer.zero_grad() # 梯度归0
  35. # sin(0) - 0 = 0
  36. x_0 = torch.zeros(N_, 1)
  37. y_0 = net(x_0)
  38. mse_i = mse_cost_function(y_0, torch.zeros(N_, 1))
  39. # sin(-3.14) - 0 = 0
  40. x_n314= torch.full((N_,1), -3.14)
  41. y_n = net(x_n314)
  42. mse_n = mse_cost_function(y_n, torch.zeros(N_, 1))
  43. # sin(3.14) - 0 = 0
  44. x_p314 = torch.full((N_,1), 3.14)
  45. y_p = net(x_p314)
  46. mse_p = mse_cost_function(y_p, torch.zeros(N_, 1))
  47. # 输入数据,-pi到+pi之间
  48. x_in = np.random.uniform(low=-3.14, high=3.14, size=(N_, 1))
  49. # 将输入数据转为torch张量
  50. pt_x_in = autograd.Variable(torch.from_numpy(x_in).float(), requires_grad=True)
  51. # pt_y_colection 是 sin**2 + cos**2 - 1 = 0 的值
  52. pt_y_colection=ode_01(pt_x_in,net)
  53. # 全是0
  54. pt_all_zeros= autograd.Variable(torch.from_numpy(np.zeros((N_,1))).float(), requires_grad=False)
  55. # sin**2 + cos**2 - 1 与 0 之间的误差
  56. mse_f=mse_cost_function(pt_y_colection, pt_all_zeros)
  57. # 各种误差之和
  58. loss = mse_i + mse_f +mse_n + mse_p
  59. # 反向传播
  60. loss.backward()
  61. # 优化下一步
  62. optimizer.step()
  63. if epoch%1000==0:
  64. y = torch.sin(pt_x_in) # y 真实值
  65. y_train0 = net(pt_x_in) # y 预测值,只用于画图,不输入模型,注意区分本代码的PINN与使用MLP进行有监督回归的差别
  66. print(epoch, "Traning Loss:", loss.data)
  67. plt.cla()
  68. plt.scatter(pt_x_in.detach().numpy(), y.detach().numpy())
  69. plt.scatter(pt_x_in.detach().numpy(), y_train0.detach().numpy(),c='red')
  70. plt.pause(0.1)

结果展示部分: 

1000次迭代:

e247c39e7db04211b37a27b4c0bcd66b.png

3000次迭代:

1419ab9ba0bd424ca6d90c7b987cb0b2.png

8000次迭代:

c2d6179c1a754d3c84c6a2e0acbc1a04.png

20000次迭代:

a8be1a0c1fbb47038cb648ac5567f659.png

        可以看到,20000次迭代之后,MLP完美逼近了sin(x)。而且不是通过有监督回归得到的。参考博客如下:PINN学习与实验(一)__刘文凯_的博客-CSDN博客

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/831333
推荐阅读
相关标签
  

闽ICP备14008679号