神经网络解常微分方程(ODE)

原文

1 原理简介

微分方程可以写成2部分

  • 第一部分满足初始和边界条件并包含不可调节参数
  • 第二部分不会影响第一部分,这部分涉及前馈神经网络,包含可调节参数(权重)

因此在构建微分方程的函数时,要满足上述两个条件,今天就来简单看下。

假设存在以下微分方程

上述微分方程f对应着一个函数u(t),同时满足初始条件u(0)=u_0,为此可以令:

NN(t)导数为:

根据以上等式,NN(t)导数近似于

可以把上式转换成损失函数

简而言之,就是已知微分函数,然后用神经网络去拟合该微分函数的原函数,然后用微分公式作为损失函数去逼近原微分函数

微分公式:

此外,还需要将初始条件考虑进去:

上述并不是一个好的方法,损失项越多会影响稳定性。为此会定义一个新函数,该函数要满足初始条件同时是t的函数:

损失函数为:

注意,神经微分网络目前主要是去近似一些简单的微分函数,复杂的比较消耗时间以及需要高算力

2 实践

假设存在下述微分函数和网络:

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np

np.random.seed(123)
tf.random.set_seed(123)

"""微分初始条件以及相应参数定义"""
f0 = 1 # 初始条件 u(0)=1

# 用于神经网络求导,无限小的小数
inf_s = np.sqrt(np.finfo(np.float32).eps) 

learning_rate = 0.01
training_steps = 500
batch_size = 100
display_step = training_steps/10

"""神经网络参数定义"""
n_input = 1     # 输入维度
n_hidden_1 = 32 # 第一层输出维度
n_hidden_2 = 32 # 第二层输出维度
n_output = 1    # 最后一层输出维度
weights = {
'h1': tf.Variable(tf.random.normal([n_input, n_hidden_1])),
'h2': tf.Variable(tf.random.normal([n_hidden_1, n_hidden_2])),
'out': tf.Variable(tf.random.normal([n_hidden_2, n_output]))
}
biases = {
'b1': tf.Variable(tf.random.normal([n_hidden_1])),
'b2': tf.Variable(tf.random.normal([n_hidden_2])),
'out': tf.Variable(tf.random.normal([n_output]))
}
"""优化器"""
optimizer = tf.optimizers.SGD(learning_rate)


"""定义模型和损失函数"""
"""多层感知机"""
def multilayer_perceptron(x):
  x = np.array([[[x]]],  dtype='float32')
  layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1'])
  layer_1 = tf.nn.sigmoid(layer_1)
  layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2'])
  layer_2 = tf.nn.sigmoid(layer_2)
  output = tf.matmul(layer_2, weights['out']) + biases['out']
  return output

"""近似原函数"""
def g(x):
  return x * multilayer_perceptron(x) + f0

"""微分函数"""
def f(x):
  return 2*x

"""定义损失函数逼近导数"""
def custom_loss():
  summation = []
  # 注意这里,没有定义数据,根据函数中t的范围选取了10个点进行计算
  for x in np.linspace(0,1,10):
    dNN = (g(x+inf_s)-g(x))/inf_s
    summation.append((dNN - f(x))**2)
  return tf.reduce_mean(tf.abs(summation))

"""训练函数"""
def train_step():
  with tf.GradientTape() as tape:
    loss = custom_loss()
  trainable_variables=list(weights.values())+list(biases.values())
  gradients = tape.gradient(loss, trainable_variables)
  optimizer.apply_gradients(zip(gradients, trainable_variables))

"""训练模型"""
for i in range(training_steps):
  train_step()
  if i % display_step == 0:
    print("loss: %f " % (custom_loss()))

"""绘图"""
from matplotlib.pyplot import figure
figure(figsize=(10,10))

# True Solution (found analitically)
def true_solution(x):
  return x**2 + 1
  
X = np.linspace(0, 1, 100)
result = []
for i in X:
  result.append(g(i).numpy()[0][0][0])
  
S = true_solution(X)
plt.plot(X, S, label="Original Function")
plt.plot(X, result, label="Neural Net Approximation")
plt.legend(loc=2, prop={'size': 20})
plt.show()

参考:
https://towardsdatascience.com/using-neural-networks-to-solve-ordinary-differential-equations-a7806de99cdd

  • 7
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
MATLAB提供了多种常微分方程(ODE)的函数,其中最常用的是ode45。ode45是一种基于Runge-Kutta法的求器,用于决非刚性和刚性的常微分方程组。它通过适应性时间步长控制和高阶插值方法来提供高精度的数值ode45适用于较为一般的ODE问题,并且在大多数情况下都能够给出较好的结果。 使用ode45求ODE通常需要两个输入参数:ODE函数和初始条件。ODE函数描述了ODE的形式,它接受独立变量和未知函数作为输入,并返回导数的值。初始条件是ODE在某个特定点上的。 下面是一个使用ode45求ODE的示例代码: ``` % 定义ODE函数 function dydt = myODE(t, y) dydt = -2*t*y; % 示例ODE为dy/dt = -2ty % 设置初始条件 t0 = 0; % 初始时间 y0 = 1; % 初始 % 求ODE [t, y = ode45(@myODE, [t0, t_end], y0); % 绘制结果 plot(t, y); xlabel('t'); ylabel('y'); title('Solution of ODE'); ``` 在这个示例中,myODE是用户自定义的ODE函数,描述了dy/dt = -2ty这个ODE的形式。ode45函数以myODE作为输入,给出了在指定时间范围内的,并将存储在变量t和y中。最后,利用plot函数绘制了的图像。 需要注意的是,使用ode45求ODE时还可以通过指定额外的选项来改变求器的行为,比如设置时间步长,终止条件等。详细的用法可以参考MATLAB的官方文档或者相关的教程。<span class="em">1</span> #### 引用[.reference_title] - *1* [Matlab微分方程(ODE+PDE).zip_MATLAB 微分方程_ODE-PDE_pde 偏微分方程_zooxya_偏](https://download.csdn.net/download/weixin_42651281/86536601)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatgptT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值