Почему мой расчет np.gradient в R^2 не соответствует аналитическому расчету градиента?

Я пытаюсь вычислить градиент на карте, используя np.gradient, но столкнулся с проблемами. Чтобы упростить мою проблему, я пытаюсь использовать аналитическую функцию

z = f(x,y) = -(x - 2)**2 - (y - 2)**2

np.gradient не дает ожидаемых результатов; векторы должны указывать к центру. Что я делаю не так?

Вот код, который я запускаю:

import numpy as np
import matplotlib.pyplot as plt

# Define the grids for x and y
x = np.linspace(0, 4, 100)  # 100 points between 0 and 4
y = np.linspace(0, 4, 100)  # 100 points between 0 and 4
X, Y = np.meshgrid(x, y)  # Create a 2D grid

# Define the function f(x, y)
Z = -(X - 2)**2 - (Y - 2)**2

# Compute gradients numerically
dz_dx, dz_dy = np.gradient(Z, x, y)


# Downsampling to reduce the density of arrows
step = 10

plt.figure(figsize=(10, 8))
contour = plt.contourf(X, Y, Z, cmap='viridis', levels=50, alpha=0.8)
plt.colorbar(contour, label='f(x, y)')
plt.quiver(X[::step, ::step], Y[::step, ::step], dz_dx[::step, ::step], dz_dy[::step, ::step], 
           color='r', headlength=3, headwidth=4)
plt.title('Function $f(x, y) = -(x - 2)^2 - (y - 2)^2$ and its gradients (numerical)')
plt.xlabel('x')
plt.ylabel('y')
plt.grid(True)

plt.show()

Не могли бы вы приложить изображение получившегося сюжета, а также эскиз или изображение того, что вы ожидаете?

tripleee 25.07.2024 15:46
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
1
57
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я не уверен, почему np.gradient не работает так, как вы ожидаете, но вместо этого вы можете вручную рассчитать градиенты, например,

import numpy as np
import matplotlib.pyplot as plt

# Define the grids for x and y
x = np.linspace(0, 4, 100)  # 100 points between 0 and 4
y = np.linspace(0, 4, 100)  # 100 points between 0 and 4
X, Y = np.meshgrid(x, y)  # Create a 2D grid

# Define the function f(x, y)
def func(X, Y):
    return -(X - 2)**2 - (Y - 2)**2

def grad(func, X, Y, delta=0.01):
    """
    Calculate gradients of a function.
    """

    dp = delta / 2
    df_dx = (func(X + dp, Y) - func(X - dp, Y)) / delta
    df_dy = (func(X, Y + dp) - func(X, Y - dp)) / delta

    return df_dx, df_dy

Z = func(X, Y)
dz_dx, dz_dy = grad(func, X, Y)

# Downsampling to reduce the density of arrows
step = 10
start = step // 2

plt.figure(figsize=(10, 8))
contour = plt.contourf(X, Y, Z, cmap='viridis', levels=50, alpha=0.8)
plt.colorbar(contour, label='f(x, y)')
plt.quiver(X[start::step, start::step], Y[start::step, start::step], dz_dx[start::step, start::step], dz_dy[start::step, start::step], 
           color='r', headlength=3, headwidth=4)
plt.title('Function $f(x, y) = -(x - 2)^2 - (y - 2)^2$ and its gradients (numerical)')
plt.xlabel('x')
plt.ylabel('y')
plt.grid(True)

plt.show()

Спасибо за ваш сценарий, но я искал бесчисленное решение. Я вычисляю градиент на большом массиве. хорошего дня

rthgtr Gaehgq 25.07.2024 16:34
Ответ принят как подходящий

проблема не в функции градиента, а в разном порядке индексации np.meshgrid и np.gradient.

по умолчанию np.gradient предполагает, что индексация имеет тот же порядок, что и аргументы, т.е.:

Z[x,y] -> np.gradient(Z, x, y)

тогда как np.meshgrid индексация по умолчанию приводит к противоположной индексации,

Z[y,x] -> np.meshgrid(x,y)  # default indexing = 'xy'

вы не заметили эту ошибку, потому что X и Y идентичны. Если бы вы сделали X и Y с разным количеством точек, вы получили бы ошибку.

Мне нравится использовать Z[y,x], поэтому просто поменяйте порядок аргументов и возврат np.gradient, и вы получите правильный результат.

dz_dy, dz_dx = np.gradient(Z, y, x)  # Z[y,x]

Вместо этого вы можете изменить индексацию сетки. Смотрите мой ответ для получения дополнительной информации.

jared 25.07.2024 18:42

Как объяснил Ахмед АЕК в своем ответе, проблема в заказах. Вместо того, чтобы менять способ звонка np.gradient, вам следует изменить способ звонка np.meshgrid.

Если вы посмотрите документацию np.meshgrid, вы увидите это по умолчанию indexing = "xy". Другой вариант indexing = "ij". Это контролирует, как определяются/упорядочиваются точки в сетке.

Для "xy" упорядочения вы можете представить массив как декартову координатную плоскость. Внизу слева — (0,0), значение x увеличивается при движении вправо, а значение y увеличивается при движении вверх.

Для порядка "ij" индексация аналогична координатам декартовой плоскости. Это означает, что (0,0), когда он используется в качестве индекса массива, находится вверху слева, увеличение значения x будет означать увеличение первого значения в индексе массива, поэтому перемещение вниз (построчно) увеличивает значение x. Второй индекс — это «координата» y, поэтому перемещение по столбцу (столбец за столбцом) увеличивает значение y.

Итак, все, что вам нужно сделать, это изменить вызов сетки на:

X, Y = np.meshgrid(x, y, indexing = "ij")

Другие вопросы по теме

Numpy: применить маску к значениям, затем принять среднее значение, но параллельно
Почему скаляры NumPy умножаются с помощью пользовательских последовательностей, а не со списками?
Как объединить подсказку типа с использованием переменной связанного типа и статических типов для максимальной гибкости?
Индексирование словаря с помощью Numpy/Jax
Python numpy, математика: каким-либо образом возвести отрицательное число в десятичную степень, не получив при этом Нэн?
Сгенерируйте n случайных 2D-точек в допустимом регионе
Почему добавление массива float32 и скаляра float64 является массивом float32 в Numpy?
Как эффективно вычислять парные количества в numpy?
Что означает: приведение данных Pandas к numpy dtype объекта. Проверьте входные данные с помощью np.asarray(data) и как это можно решить?
Эффективное стохастическое численное интегрирование по многим траекториям