Какова цель meshgrid в Python / NumPy?

может кто-нибудь объяснить мне, в чем цель meshgrid функция в Numpy? Я знаю, что это создает какую-то сетку координат для построения графика, но я не вижу прямой выгоды от этого.

Я изучаю "машинное обучение Python" у Себастьяна Рашки, и он использует его для построения границ решения. Вижу вход 11 здесь.

Я также попробовал этот код из официальной документации, но, опять же, вывод не имеет смысла мне.

x = np.arange(-5, 5, 1)
y = np.arange(-5, 5, 1)
xx, yy = np.meshgrid(x, y, sparse=True)
z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2)
h = plt.contourf(x,y,z)

пожалуйста, если возможно, также покажите мне много реальных примеров.

5 ответов


цель meshgrid - это создание прямоугольной сетки из массива значений x и массива значений Y.

так, например, если мы хотим создать сетку, где у нас есть точка на каждом целочисленном значении между 0 и 4 в обоих направлениях x и y. Чтобы создать прямоугольную сетку, нам нужна каждая комбинация x и y очков.

это будет 25 очков, верно? Поэтому, если мы хотим создать массив x и y для всех этих точек, мы мог бы выполните следующие действия.

x[0,0] = 0    y[0,0] = 0
x[0,1] = 1    y[0,1] = 0
x[0,2] = 2    y[0,2] = 0
x[0,3] = 3    y[0,3] = 0
x[0,4] = 4    y[0,4] = 0
x[1,0] = 0    y[1,0] = 1
x[1,1] = 1    y[1,1] = 1
...
x[4,3] = 3    y[4,3] = 4
x[4,4] = 4    y[4,4] = 4

это приведет к следующим x и y матрицы, такие, что сопряжение соответствующего элемента в каждой матрице дает координаты x и y точки в сетке.

x =   0 1 2 3 4        y =   0 0 0 0 0
      0 1 2 3 4              1 1 1 1 1
      0 1 2 3 4              2 2 2 2 2
      0 1 2 3 4              3 3 3 3 3
      0 1 2 3 4              4 4 4 4 4

затем мы можем построить их, чтобы убедиться, что они являются сеткой:

plt.plot(x,y, marker='.', color='k', linestyle='none')

enter image description here

очевидно, это становится очень утомительным, особенно для больших диапазонов x и y. Вместо meshgrid может фактически генерировать это для нас: все, что мы должны указать, это уникальный x и y значения.

xvalues = np.array([0, 1, 2, 3, 4]);
yvalues = np.array([0, 1, 2, 3, 4]);

теперь, когда мы называем meshgrid, мы получаем предыдущий выход автоматически.

xx, yy = np.meshgrid(xvalues, yvalues)

plt.plot(xx, yy, marker='.', color='k', linestyle='none')

enter image description here

создание этих прямоугольных сеток полезно для ряда задач. В Примере, который вы предоставили в своем посте, это просто способ попробовать функцию (sin(x**2 + y**2) / (x**2 + y**2)) в диапазоне значения x и y.

поскольку эта функция была выбрана на прямоугольной сетке, функция теперь может быть визуализирована как "изображение".

enter image description here

кроме того, результат теперь может быть передан функциям, которые ожидают данные на прямоугольной сетке (т. е. contourf)


любезно предоставлено Microsoft Excelle:

enter image description here


Предположим, у вас есть функция:

def sinus2d(x, y):
    return np.sin(x) + np.sin(y)

и вы хотите, например, увидеть, как это выглядит в диапазоне от 0 до 2*pi. Как бы вы это сделали? Там np.meshgrid поставляется в:

xx, yy = np.meshgrid(np.linspace(0,2*np.pi,100), np.linspace(0,2*np.pi,100))
z = sinus2d(xx, yy) # Create the image on this grid

и такой сюжет будет выглядеть так:

import matplotlib.pyplot as plt
plt.imshow(z, origin='lower', interpolation='none')
plt.show()

enter image description here

так np.meshgrid - это просто удобство. В принципе то же самое можно было бы сделать с помощью:

z2 = sinus2d(np.linspace(0,2*np.pi,100)[:,None], np.linspace(0,2*np.pi,100)[None,:])

но там вам нужно знать о ваших размерах (предположим, вы больше двух ...) и правильное вещание. np.meshgrid делает все это для вас.

также meshgrid позволяет удалять координаты вместе с данными, если вы, например, хотите сделать интерполяцию, но исключаете определенные значения:

condition = z>0.6
z_new = z[condition] # This will make your array 1D

Итак, как бы вы сделали интерполяцию сейчас? Вы можете дать x и y к функции интерполяции, такой как scipy.interpolate.interp2d таким образом, вам нужен способ узнать, какие координаты были удалены:

x_new = xx[condition]
y_new = yy[condition]

и тогда вы все равно можете интерполировать" правильные " координаты (попробуйте без meshgrid, и у вас будет много дополнительного кода):

from scipy.interpolate import interp2d
interpolated = interp2(x_new, y_new, z_new)

и оригинальный meshgrid позволяет получить интерполяцию на исходной сетке снова:

interpolated_grid = interpolated(xx, yy)

это лишь некоторые примеры, где я использовал meshgrid может быть намного больше.


собственно цель np.meshgrid уже упоминается в документации:

np.meshgrid

возврат координатных матриц из координатных векторов.

сделайте N-D координатные массивы для векторизованных оценок N-D скалярных / векторных полей над N-D сетками, учитывая одномерные координатные массивы x1, x2,..., xn.

таким образом, основная цель-создать координаты матрицы.

Вы, наверное, просто спросил себя:

зачем нам создавать координатные матрицы?

причина, по которой вам нужны координатные матрицы с Python/NumPy, заключается в том, что нет прямого отношения от координат к значениям, за исключением случаев, когда ваши координаты начинаются с нуля и являются чисто положительными целыми числами. Затем вы можете просто использовать индексы массива в качестве индекса. Однако, когда это не так, вам как-то нужно хранить координаты рядом с вашими данными. Вот где решетки войти.

предположим, что ваши данные:

1  2  1
2  5  2
1  2  1

однако каждое значение представляет собой область шириной 2 километра по горизонтали и 3 километра по вертикали. Предположим, ваше происхождение-верхний левый угол, и вам нужны массивы, которые представляют расстояние, которое вы могли бы использовать:

import numpy as np
h, v = np.meshgrid(np.arange(3)*3, np.arange(3)*2)

здесь h - это:

0  2  4
0  2  4
0  2  4

и h:

0  0  0
3  3  3
6  6  6

Итак, если у вас есть два индекса, скажем x и y (вот почему возвращаемое значение meshgrid обычно xx или xs вместо x в этом случае я выбрал h для горизонтально!) затем вы можете получить координату x точки, координату y точки и значение в этой точке, используя:

h[x, y]    # horizontal coordinate
v[x, y]    # vertical coordinate
data[x, y]  # value

это значительно упрощает отслеживание координат и (что еще более важно) вы можете передать их функциям, которые должны знать координаты.

немного больше объяснение

, np.meshgrid сам часто не используется напрямую, в основном используется только один из как объекты np.mgrid или np.ogrid. Вот!--30--> представляет sparse=False и np.ogrid the sparse=True case (я имею в виду он также поддерживает step аргумент (даже сложные шаги, которые представляют количество шагов):
>>> x1, x2 = np.mgrid[1:10:2, 1:10:4j]
>>> x1  # The dimension with the explicit step width of 2
array([[1., 1., 1., 1.],
       [3., 3., 3., 3.],
       [5., 5., 5., 5.],
       [7., 7., 7., 7.],
       [9., 9., 9., 9.]])
>>> x2  # The dimension with the "number of steps"
array([[ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.],
       [ 1.,  4.,  7., 10.]])

приложения

вы специально спросили о цели, и на самом деле эти сетки чрезвычайно полезны, если вам нужна система координат.

для пример, если у вас есть функция NumPy, которая вычисляет расстояние в двух измерениях:

def distance_2d(x_point, y_point, x, y):
    return np.hypot(x-x_point, y-y_point)

и вы хотите знать расстояние каждой точки:

>>> ys, xs = np.ogrid[-5:5, -5:5]
>>> distances = distance_2d(1, 2, xs, ys)  # distance to point (1, 2)
>>> distances
array([[9.21954446, 8.60232527, 8.06225775, 7.61577311, 7.28010989,
        7.07106781, 7.        , 7.07106781, 7.28010989, 7.61577311],
       [8.48528137, 7.81024968, 7.21110255, 6.70820393, 6.32455532,
        6.08276253, 6.        , 6.08276253, 6.32455532, 6.70820393],
       [7.81024968, 7.07106781, 6.40312424, 5.83095189, 5.38516481,
        5.09901951, 5.        , 5.09901951, 5.38516481, 5.83095189],
       [7.21110255, 6.40312424, 5.65685425, 5.        , 4.47213595,
        4.12310563, 4.        , 4.12310563, 4.47213595, 5.        ],
       [6.70820393, 5.83095189, 5.        , 4.24264069, 3.60555128,
        3.16227766, 3.        , 3.16227766, 3.60555128, 4.24264069],
       [6.32455532, 5.38516481, 4.47213595, 3.60555128, 2.82842712,
        2.23606798, 2.        , 2.23606798, 2.82842712, 3.60555128],
       [6.08276253, 5.09901951, 4.12310563, 3.16227766, 2.23606798,
        1.41421356, 1.        , 1.41421356, 2.23606798, 3.16227766],
       [6.        , 5.        , 4.        , 3.        , 2.        ,
        1.        , 0.        , 1.        , 2.        , 3.        ],
       [6.08276253, 5.09901951, 4.12310563, 3.16227766, 2.23606798,
        1.41421356, 1.        , 1.41421356, 2.23606798, 3.16227766],
       [6.32455532, 5.38516481, 4.47213595, 3.60555128, 2.82842712,
        2.23606798, 2.        , 2.23606798, 2.82842712, 3.60555128]])

выход был бы идентичен, если бы он проходил в плотной сетке вместо открытой сетки. NumPys вещание делает это возможным!

давайте визуализируем результат:

plt.figure()
plt.title('distance to point (1, 2)')
plt.imshow(distances, origin='lower', interpolation="none")
plt.xticks(np.arange(xs.shape[1]), xs.ravel())  # need to set the ticks manually
plt.yticks(np.arange(ys.shape[0]), ys.ravel())
plt.colorbar()

enter image description here

и это также когда NumPys mgrid и ogrid стать очень удобно, ведь это позволяет легко менять разрешение ваших сеток:

ys, xs = np.ogrid[-5:5:200j, -5:5:200j]
# otherwise same code as above

enter image description here

вместе с imshow не поддерживает x и y входы нужно менять вручную. Было бы очень удобно, если бы он принял x и y координаты, верно?

легко писать функции с NumPy, которые имеют дело естественно с сетками. Кроме того, существует несколько функции в NumPy, SciPy, MatPlotLib, которые ожидают, что вы передадите в сетке.

мне нравятся изображения, поэтому давайте исследуем matplotlib.pyplot.contour:

ys, xs = np.mgrid[-5:5:200j, -5:5:200j]
density = np.sin(ys)-np.cos(xs)
plt.figure()
plt.contour(xs, ys, density)

enter image description here

обратите внимание, как координаты уже установлены правильно! Это не было бы так, если бы вы просто прошли в density.

или дать другой интересный пример, используя модели astropy (на этот раз меня не очень волнуют координаты, я просто используйте их для создания некоторые сетка):

from astropy.modeling import models
z = np.zeros((100, 100))
y, x = np.mgrid[0:100, 0:100]
for _ in range(10):
    g2d = models.Gaussian2D(amplitude=100, 
                           x_mean=np.random.randint(0, 100), 
                           y_mean=np.random.randint(0, 100), 
                           x_stddev=3, 
                           y_stddev=3)
    z += g2d(x, y)
    a2d = models.AiryDisk2D(amplitude=70, 
                            x_0=np.random.randint(0, 100), 
                            y_0=np.random.randint(0, 100), 
                            radius=5)
    z += a2d(x, y)

enter image description here

хотя это просто "для внешнего вида" несколько функций, связанных с функциональными моделями и подгонкой (например scipy.interpolate.interp2d, scipy.interpolate.griddata даже показать примеры, используя np.mgrid) в Scipy и т. д. требуется сетка. Большинство из них работают с открытыми сетками и плотной сетки, однако некоторые работают только с одной из них.


meshgrid помогает в создании прямоугольной сетки из двух 1-D массивов всех пар точек из двух массивов.

x = np.array([0, 1, 2, 3, 4])
y = np.array([0, 1, 2, 3, 4])

теперь, если вы определили функцию f (x,y) и хотите применить эту функцию ко всем возможным комбинациям точек из массивов " x " и "y", то вы можете сделать следующее:

f(*np.meshgrid(x, y))

скажем, если ваша функция просто производит произведение двух элементов, то это, как декартово произведение может быть достигнуто, эффективно для больших матрицы.

ссылка здесь