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


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

Я изучаю "Python Machine Learning" от Себастьяна Рашки, и он использует его для построения границ решения. См. ввод 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 136

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. Здесь np.mgrid представляет 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 помогает в создании прямоугольной сетки из двух одномерных массивов всех пар точек из двух массивов.

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))

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

ссылка здесь