Производные: diff делает дифференцирование за вас

Брать производные вручную — рутина, в которой легко ошибиться. SymPy дифференцирует любую функцию точно и мгновенно.

diff — функция SymPy для символьного дифференцирования: она возвращает производную выражения как точную формулу.

Зачем это нужно

Производная — скорость изменения, наклон касательной — встречается всюду: в физике (скорость, ускорение), оптимизации (минимум там, где производная ноль), экономике (предельные величины). Брать производные сложных функций руками по правилам (произведения, частного, цепочки) утомительно и чревато ошибками. SymPy применяет эти правила безошибочно.

Численная производная «руками»

Сначала вспомним определение: производная — это предел отношения приращений. Численно его приближают конечной разностью. Возьмём производную f(x) = x³ в точке x = 2 (точный ответ 3·2² = 12):

def f(x):
    return x ** 3

x0 = 2.0
h = 1e-6                         # маленький шаг
# центральная разность точнее односторонней
deriv = (f(x0 + h) - f(x0 - h)) / (2 * h)

print("Численно f'(2) :", round(deriv, 4))
print("Точно   f'(2)  :", 3 * x0**2)

Вывод:

Численно f'(2) : 12.0
Точно   f'(2)  : 12.0

Численный способ приближённый и требует подбирать h: слишком большой — груба формула, слишком маленький — съест точность float. SymPy свободен от этой головной боли — он даёт формулу.

Символьное дифференцирование в SymPy

import sympy as sp
x = sp.symbols("x")

print(sp.diff(x**3, x))              # 3*x**2 — формула, не число!
print(sp.diff(sp.sin(x), x))         # cos(x)
print(sp.diff(sp.exp(x**2), x))      # 2*x*exp(x**2) — цепное правило
print(sp.diff(x**3, x, 2))           # 6*x — вторая производная

# подставим точку:
d = sp.diff(x**3, x)
print(d.subs(x, 2))                  # 12 — точно

SymPy вернул формулу производной. Её можно дифференцировать снова, упрощать, подставлять значения — символьная мощь.

Частные производные

Для функций нескольких переменных diff берёт производную по указанной переменной (частную), считая остальные константами:

import sympy as sp
x, y = sp.symbols("x y")
f = x**2 * y + sp.sin(y)

print(sp.diff(f, x))    # 2*x*y       — по x
print(sp.diff(f, y))    # x**2 + cos(y) — по y

Как работает под капотом

SymPy дифференцирует, рекурсивно обходя дерево выражения и применяя правила дифференцирования к каждому узлу. Узел «сумма» → сумма производных. Узел «произведение u·v» → u'·v + u·v' (правило произведения). Узел «функция от функции» f(g(x)) → f'(g)·g' (цепное правило). Базовые производные (sin → cos, exp → exp, xⁿ → n·xⁿ⁻¹) зашиты в самих функциях. Поскольку правила локальны и однозначны, дифференцирование — алгоритмически простая операция (в отличие от интегрирования, о чём в следующем уроке). Поэтому SymPy дифференцирует быстро и всегда успешно.

Частые ошибки

  • Подбор шага в численной производной. При h=1e-15 вычитание близких чисел теряет все значащие цифры (катастрофическое сокращение). SymPy этой проблемы лишён.
  • Путать diff(f, x, 2) и diff(f, x, x). Оба дают вторую производную по x — это одно и то же, не пугайтесь двух форм записи.
  • Забыть, по какой переменной дифференцируем. Для функций многих переменных всегда указывайте переменную явно.

Итог

  • SymPy diff даёт точную формулу производной, а не число.
  • Работают высшие порядки (diff(f, x, 2)) и частные производные.
  • Численная производная (конечная разность) приближённа и требует подбора шага.
  • Дифференцирование алгоритмически просто — обход дерева с применением правил.
Проверьте себя
1. Что вернёт sp.diff(x**3, x) в SymPy?
A12
B3*x**2 — формулу производной
Cx**4/4
DЧисло в точке x=1
2. В чём недостаток численной производной через конечную разность?
AОна всегда неверна
BНужно подбирать шаг h: слишком большой груб, слишком малый теряет точность из-за вычитания близких чисел
CОна медленнее символьной
DОна работает только для многочленов
3. Почему дифференцирование в SymPy всегда успешно и быстро?
AИспользуется суперкомпьютер
BПравила дифференцирования локальны и однозначны — это простой рекурсивный обход дерева выражения
CSymPy угадывает ответ
DПроизводных не существует для сложных функций