Рубрики
Без рубрики

Две интересные функции Python NumPy: мутирование путем нарезки и трансляции

NumPy-это чистое золото. Он быстр, прост в освоении, многофункциональен и, следовательно, лежит в основе почти всех научно-популярных пакетов во вселенной Python (включая SciPy и Pandas, два наиболее широко используемых пакета для науки о данных и статистического моделирования). В этой статье давайте кратко обсудим две интересные особенности NumPy, а именно: мутация путем нарезки и трансляции.

Автор оригинала: Tirthajyoti Sarkar.

NumPy-это чистое золото. Он быстр, прост в освоении, многофункциональен и, следовательно, лежит в основе почти всех научно-популярных пакетов во вселенной Python (включая SciPy и Pandas, два наиболее широко используемых пакета для науки о данных и статистического моделирования). В этой статье давайте кратко обсудим две интересные особенности NumPy, а именно: мутация путем нарезки и трансляции.

Мутация путем нарезки

Оказывается, что если вы используете простое срезание/индексирование с помощью NumPy для создания подмассива, подмассив фактически указывает на основной массив. Проще говоря, диаграмма в памяти выглядит следующим образом,

Поэтому, если срезанный массив изменяется, это влияет и на родительский массив. Это может быть полезной функцией для распространения желаемой цепочки вверх по пищевой цепочке, но иногда также может быть неприятностью, когда вы сохраняете неизменным основной набор данных и вносите изменения только в подмножество. В этих случаях вам необходимо явно вызвать метод np.array , чтобы определить срезанный массив, а не просто срезать его путем индексации. Следующий код иллюстрирует этот момент,

Иллюстративный код

mat = np.array([[11,12,13],[21,22,23],[31,32,33]])
print("Original matrix")
print(mat)

# Simple Indexing
mat_slice = mat[:2,:2]

print ("\nSliced matrix")
print(mat_slice)
print ("\nChange the sliced matrix")
mat_slice[0,0] = 1000
print (mat_slice)
print("\nBut the original matrix? WHOA! It got changed too!")
print(mat)

Результат выглядит следующим образом,

Original matrix
[[11 12 13]
 [21 22 23]
 [31 32 33]]

Sliced matrix
[[11 12]
 [21 22]]

Change the sliced matrix
[[1000 12]
 [21 22]]

But the original matrix? WHOA! It got changed too!
[[1000 12 13]
 [21 22 23]
 [31 32 33]]

Чтобы этого не произошло, вот что вы должны сделать,

# Little different way to create a copy of the sliced matrix
print ("\nDoing it again little differently now...\n")
mat = np.array([[11,12,13],[21,22,23],[31,32,33]])
print("Original matrix")
print(mat)

# Notice the np.array method
mat_slice = np.array(mat[:2,:2])

print ("\nSliced matrix")
print(mat_slice)
print ("\nChange the sliced matrix")
mat_slice[0,0] = 1000
print (mat_slice)
print("\nBut the original matrix? NO CHANGE this time:)")
print(mat)

Теперь исходная матрица не мутирует из-за каких-либо изменений в подматрице,

Original matrix
[[11 12 13]
 [21 22 23]
 [31 32 33]]

Sliced matrix
[[11 12]
 [21 22]]

Change the sliced matrix
[[1000 12]
 [21 22]]

But the original matrix? NO CHANGE this time:)
[[11 12 13]
 [21 22 23]
 [31 32 33]]

Трансляция

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

Правило вещания NumPy ослабляет это ограничение, когда формы массивов удовлетворяют определенным ограничениям . При работе с двумя массивами NumPy сравнивает их формы по элементам. Он начинается с конечных размеров и продвигается вперед. Два измерения совместимы, когда

  • они равны, или
  • один из них-1

Если эти условия не выполняются, возникает исключение ValueError: кадры не выровнены , указывающее, что массивы имеют несовместимые формы. Размер результирующего массива-это максимальный размер по каждому измерению входных массивов.

Для получения более подробной информации, пожалуйста, посмотрите: https://docs.scipy.org/doc/numpy-1.10.1/user/basics.broadcasting.html .

Следующий блок кода иллюстрирует идею шаг за шагом,

Инициализируйте матрицу “старт” с нулями

start = np.zeros((4,3))
print(start)

[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]]

Создайте матрицу строк (вектор),

# create a rank 1 ndarray with 3 values
add_rows = np.array([1, 0, 2])
print(add_rows)

[1 0 2]

Добавьте нулевую матрицу (4×3) к вектору (1×3). Автоматически вектор 1×3 дублируется 4 раза, чтобы соответствовать размеру строки нулевой матрицы , и эти значения добавляются в матрицу 4×3.

y = start + add_rows # add to each row of 'start'
print(y)

[[1. 0. 2.]
 [1. 0. 2.]
 [1. 0. 2.]
 [1. 0. 2.]]

Создайте матрицу столбцов (вектор),

# create an ndarray which is 4 x 1 to broadcast across columns
add_cols = np.array([[0,1,2,3]])
add_cols = add_cols.T
print(add_cols)

[[0]
 [1]
 [2]
 [3]]

Добавьте нулевую матрицу (4×3) к вектору (4×1). Автоматически вектор 4×1 дублируется 3 раза, чтобы соответствовать размеру столбца нулевой матрицы , и эти значения добавляются в матрицу 4×3.

# add to each column of 'start' using broadcasting
y = start + add_cols 
print(y)

[[0. 0. 0.]
 [1. 1. 1.]
 [2. 2. 2.]
 [3. 3. 3.]]

Наконец, скаляр обрабатывается как матрица 1×1 и дублируется точно до размера аддитивной матрицы для выполнения операции.

# this will just broadcast in both dimensions
add_scalar = np.array([100])  
print(start+add_scalar)

[[100. 100. 100.]
 [100. 100. 100.]
 [100. 100. 100.]
 [100. 100. 100.]]

Полезность широковещания лучше всего реализуется, когда вы используете массивы NumPy для написания векторизованного кода для алгоритма, такого как градиентный спуск . Эндрю Нг |/проводит полную видеолекцию |/объясняя концепцию вещания на Python в своем новом курсе глубокого обучения. Это делает реализацию алгоритма прямого и обратного распространения для глубокой нейронной сети относительно безболезненной.

Вы также можете посмотреть это видео о демонстрации функции вещания…

Видео с объяснением трансляции Numpy

Если у вас есть какие-либо вопросы или идеи, которыми вы хотите поделиться, пожалуйста, свяжитесь с автором по адресу tirthajyoti[AT]gmail.com . Также вы можете проверить репозитории автора GitHub на наличие других интересных фрагментов кода в Python, R или MATLAB и ресурсах машинного обучения. Вы также можете следовать за мной в LinkedIn .