Мы можем найти множество применений нейронных сетей в бизнесе, розничной торговле, компьютерном зрении и НЛП, но как насчет инженерных областей, которые не управляются данными, а сильно зависят от решения дифференциальных уравнений. Благодаря революционной статье «Глубокое обучение с учетом физики (часть I): решения нелинейных дифференциальных уравнений в частных производных на основе данных» теперь мы можем использовать нейронную сеть для решения дифференциального уравнения. Авторы также щедро поделились кодом в своем репозитории Github, но этот код написан в предыдущей версии Tensorflow.
Давайте перейдем к пониманию и реализации их концепции. Для этого блога я выбрал простое дифференциальное уравнение.
Для тех, кто не знаком, это уравнение осевого смещения стержня при осевой нагрузке. А — площадь поперечного сечения, Е — модуль Юнга, q — сила. Тем, кто не знаком с этими словами, не стоит беспокоиться. Их можно рассматривать как константы уравнения. Это дифференциальное уравнение имеет два граничных условия, как показано на рисунке.
В этой статье используется уникальная концепция объединения дифференциального уравнения и граничного условия для формирования пользовательской функции стоимости, и эта функция стоимости дополнительно оптимизируется. Прежде чем написать окончательный термин, давайте определимся с терминологией.
Эта концепция хороша, но как реализовать это в программном обеспечении? Ответ заключается в использовании метода автоматического дифференцирования Tensorflow. Давайте посмотрим на фрагмент кода, чтобы понять
def f_model(self): with tf.GradientTape(persistent=True) as tape: tape.watch(self.x_f)#collocation points tape.watch(self.x_u_l)#boundary condition on u tape.watch(self.x_u_b)#boundary condition on ux # Packing together the inputs X_f = self.x_f X_b=self.x_b X_u=self.x_u # Getting the prediction u = self.u_model(X_f) u_b=self.u_model(X_b) u_u=self.u_model(X_u) # Deriving INSIDE the tape (since we’ll need the x derivative of this later, u_xx) u_x = tape.gradient(u, self.x_f) u_u_x = tape.gradient(u_u, self.x_u) # Getting the other derivatives u_xx = tape.gradient(u_x, self.x_f) # Letting the tape go del tape # Buidling the PINNs return tf.reduce_mean(tf.square(self.A*self.E*u_xx+self.q))+8*tf.reduce_mean(tf.square(u_u_x+u_b))
Лента — это обновление Tensorflow 2.0, которое помогает нам вычислять градиенты. Во фрагменте кода мы сначала вычислили u (смещение) по модели, затем с помощью ленты вычислили Ux (производную смещения по x). С помощью этого рассчитывается Uxx (двойная производная). Мы должны иметь в виду, что граничное условие также имеет члены U и Ux, поэтому эти условия необходимо вычислить снова для граничных точек.
После написания этой функции нам просто нужно сделать эту функцию цели или стоимости и минимизировать ее. В отличие от других проблем с нейронными сетями, здесь мы должны подгонять. Создайте глубокую нейронную сеть и запустите ее на достаточное количество эпох, чтобы получить минимальное значение целевой функции. Поскольку используются двойные производные, мы не можем использовать RELU, поскольку вторая производная RELU будет равна нулю. В рецензируемой статье в качестве функции активации использовалась Tanh.
См. https://github.com/pierremtb/PINNs-TF2.0 для реализации кода.