Это зависит от того, как вы генерируете указанное изображение. Поскольку нейронные сети должны обучаться путем обратного распространения, я уверен, что ваше двоичное изображение не является прямым выходом вашей нейронной сети (ie не то, к чему вы применяете потери), потому что градиент не может пройти через двоичный файл (дискретные) переменные. Я подозреваю, что вы делаете что-то вроде попиксельной двоичной кросс-энтропии или подобного, а затем пороговое значение.
Я предполагаю, что ваш код работает так: вы плотно регрессируете вещественные числа, а затем применяете пороговое значение, вероятно, используя sigmoid
для отображения от [-inf, inf]
до [0, 1]
. Если это так, вы можете сделать следующее. Создайте ядро свертки, которое будет 0
в центре и 1
в другом месте, размером, связанным с тем, насколько велики вы хотите, чтобы ваши "промежутки" невелики.
kernel = [
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1]
[1, 1, 0, 1, 1]
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1]
]
Затем вы применяете sigmoid
к ваш действительный выходной результат в squa sh это в [0, 1]
:
squashed = torch.sigmoid(nn_output)
, затем вы сворачиваете squashed
с kernel
, что дает вам ослабленное число ненулевых соседей.
neighborhood = nn.functional.conv2d(squashed, kernel, padding=2)
и ваша потеря будет произведена как значение каждого пикселя в squashed
с соответствующим значением в neighborhood
:
sparsity_loss = (squashed * neighborhood).mean()
Если вы думаете, что эта потеря применяется к вашему двоичному файлу image, для данного пикселя p
это будет 1, если и только если оба p
и хотя бы один из его соседей имеют значения 1 и 0 в противном случае. Поскольку мы применяем его к недвоичным числам в диапазоне [0, 1]
, это будет дифференцируемой аппроксимацией этого.
Обратите внимание, что я пропустил некоторые детали из кода выше (например, правильное изменение формы * 1035) * для работы с nn.functional.conv2d
).