Мы можем найти множество применений нейронных сетей в бизнесе, розничной торговле, компьютерном зрении и НЛП, но как насчет инженерных областей, которые не управляются данными, а сильно зависят от решения дифференциальных уравнений. Благодаря революционной статье «Глубокое обучение с учетом физики (часть 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 для реализации кода.