ReLU производная с NumPy

import numpy as np

def relu(z):
    return np.maximum(0,z)

def d_relu(z):
    z[z>0]=1
    z[z<=0]=0
    return z

x=np.array([5,1,-4,0])
y=relu(x)
z=d_relu(y)
print("y = {}".format(y))
print("z = {}".format(z))

Код выше распечатывает:

y = [1 1 0 0]
z = [1 1 0 0]

вместо

y = [5 1 0 0]
z = [1 1 0 0]

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

Почему моя функция d_relu влияет на переменную y?

1 ответ

Решение

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

Вы не должны иметь d_relu модифицировать z на месте, потому что это то, что он делает сейчас, через z[...] = ... синтаксис. Вместо этого попробуйте создать маску с использованием переданного сравнения и вернуть ее.

def d_relu(z):
    return (z > 0).astype(int)

Это возвращает новый массив вместо изменения z на месте, и ваш код печатается

y = [5 1 0 0]
z = [1 1 0 0]

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

class relu:
    def __init__(self):
        self.mask = None

    def forward(self, x):
        self.mask = x > 0
        return x * self.mask

    def backward(self, x):
        return self.mask

Где производная просто 1, если вход во время прямой связи, если> 0, иначе 0.

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