1 原則の概要
微分方程式は2 つの部分で書くことができます。
- 最初の部分は初期条件と境界条件を満たしており、調整できないパラメータが含まれています
- 2 番目の部分は、調整可能なパラメータ (重み) を含むフィードフォワード ニューラル ネットワークを扱う最初の部分には影響しません。
したがって、微分方程式の関数を作成する場合には、上記の 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