Как я могу предварительно вычислить маску для каждого входа и настроить веса в соответствии с этой маской?

Я хочу предоставить маску того же размера, что и входное изображение, и настроить веса, полученные из изображения, в соответствии с этой маской (аналогично вниманию, но предварительно вычисляемому для каждого входного изображения). Как я могу сделать это с помощью Keras (или TensorFlow)?


person dusa    schedule 27.02.2019    source источник
comment
Можете ли вы включить архитектуру вашей модели? Какие именно веса вы хотите отрегулировать?   -  person sdcbr    schedule 25.03.2019
comment
Я использую модель здесь github.com/SunnerLi/RAM, и у меня есть отдельная программа, в которой я вычисляю пространственная точка (или их несколько) на изображении, показывающая вероятность того, что объект находится там - хотя это не карта вероятностей, но я локализую ее, используя некоторые функции -   -  person dusa    schedule 25.03.2019
comment
Я не хочу просто маскировать входное изображение, но я хочу скорее настроить веса изученных функций в конверсионных слоях (например, придать более высокий вес, если он находится вокруг пространственных точек, где я думаю, что объект, вероятно, находится там и ниже или ниже). ноль баллов по остальным частям - в зависимости от вероятности   -  person dusa    schedule 25.03.2019
comment
Так эти маски исправлены заранее? Или вы хотите рассчитать их динамически?   -  person sdcbr    schedule 25.03.2019
comment
В настоящее время они фиксированы, вычисляются заранее   -  person dusa    schedule 25.03.2019
comment
Я имею в виду, конечно, начальные точки, часть внимания, например, в примере кода начинается с фиксированной точки, но затем выясняет, на что обращать внимание (например, взгляд).   -  person dusa    schedule 25.03.2019
comment
Я хочу иметь возможность просто настроить веса, чтобы это был другой способ внимания, не обязательно идентичный коду примера.   -  person dusa    schedule 25.03.2019
comment
@dusa Интересно, нашли ли вы решение или способ решить эту проблему - если да, не могли бы вы уточнить?   -  person Yuval    schedule 23.01.2020


Ответы (1)


Вопрос

Как я могу добавить к изображению еще один векторный слой, например маску, и заставить нейронную сеть учитывать этот новый векторный слой?

Отвечать

Короткий ответ — добавить его в качестве еще одного цветового канала к изображению. Если ваше изображение уже имеет 3 цветовых канала; красный, синий, зеленый, а затем добавление еще одного канала маски 1 и 0 дает нейронной сети гораздо больше информации, которую можно использовать для принятия решений.

Мысленный эксперимент

В качестве мысленного эксперимента возьмем MNIST. Изображения MNIST имеют размер 28x28. Давайте возьмем 1 изображение, «истинное» изображение, и 3 других изображения, «отвлечения внимания», и сформируем изображение 56x56 из 4 изображений 28x28. MNIST черно-белый, поэтому он имеет только 1 цветовой канал, яркость. Давайте теперь добавим еще один цветовой канал, который является маской, 1 в области изображения 56x56, где находится «истинное» изображение, и 0 в остальных местах.

Если мы используем ту же архитектуру, что и обычно, для решения MNIST, свертки на всем пути вниз, мы можем представить, что он может использовать эту новую информацию, чтобы научиться обращать внимание только на «истинную» область и правильно классифицировать изображение.

Пример кода

В этом примере мы пытаемся решить проблему XOR. Мы берем классический XOR и удваиваем входные данные с шумом и добавляем канал, который имеет 1 для отсутствия шума и 0 для шума.


# Adapted from https://github.com/panchishin/learn-to-tensorflow/blob/master/solutions/04-xor-2d.py

# -- The xor problem --
x = np.array([[0., 0.], [1., 1.], [1., 0.], [0., 1.]])
y_ = [[1., 0.], [1., 0.], [0., 1.], [0., 1.]]


def makeBatch() :
    # Add an additional 2 channels of noise
    # either before or after the two real 'x's.
    global x
    rx = np.random.rand(4,4,2) > 0.5
    # set the mask to 0 for all items
    rx[:,:,1] = 0
    index = int(np.random.random()*3)
    rx[:,index:index+2,0] = x
    # set the mask to 1 for 'real' values
    rx[:,index:index+2,1] = 1
    return rx

# -- imports --
import tensorflow as tf

# np.set_printoptions(precision=1) reduces np precision output to 1 digit
np.set_printoptions(precision=2, suppress=True)


# -- induction --

# Layer 0
x0 = tf.placeholder(dtype=tf.float32, shape=[None, 4, 2])
y0 = tf.placeholder(dtype=tf.float32, shape=[None, 2])

# Layer 1
f1 = tf.reshape(x0,shape=[-1,8])
m1 = tf.Variable(tf.random_uniform([8, 9], minval=0.1, maxval=0.9, dtype=tf.float32))
b1 = tf.Variable(tf.random_uniform([9], minval=0.1, maxval=0.9, dtype=tf.float32))
h1 = tf.sigmoid(tf.matmul(f1, m1) + b1)

# Layer 2
m2 = tf.Variable(tf.random_uniform([9, 2], minval=0.1, maxval=0.9, dtype=tf.float32))
b2 = tf.Variable(tf.random_uniform([2], minval=0.1, maxval=0.9, dtype=tf.float32))
y_out = tf.nn.softmax(tf.matmul(h1, m2) + b2)


# -- loss --

# loss : sum of the squares of y0 - y_out
loss = tf.reduce_sum(tf.square(y0 - y_out))

# training step : gradient descent (1.0) to minimize loss
train = tf.train.GradientDescentOptimizer(1.0).minimize(loss)



# -- training --
# run 500 times using all the X and Y
# print out the loss and any other interesting info
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    print("\nloss")
    for step in range(5000):
        sess.run(train, feed_dict={x0: makeBatch(), y0: y_})
        if (step + 1) % 1000 == 0:
            print(sess.run(loss, feed_dict={x0: makeBatch(), y0: y_}))

    results = sess.run([m1, b1, m2, b2, y_out, loss], feed_dict={x0: makeBatch(), y0: y_})
    labels = "m1,b1,m2,b2,y_out,loss".split(",")
    for label, result in zip(*(labels, results)):
        print("")
        print(label)
        print(result)

print("")

Выход

Мы видим, что сеть правильно решает задачу и дает правильный результат с высокой степенью достоверности.

у_ (истина) = [[1., 0.], [1., 0.], [0., 1.], [0., 1.]]

y_out
[[0.99 0.01]
 [0.99 0.01]
 [0.01 0.99]
 [0.01 0.99]]

loss
0.00056630466

Подтверждение того, что маска что-то делает

Давайте изменим функцию маски так, чтобы она была случайной, закомментировав строки, которые устанавливают 0 для шума и 1 для сигнала.

def makeBatch() :
    global x
    rx = np.random.rand(4,4,2) > 0.5
    #rx[:,:,1] = 0
    index = int(np.random.random()*3)
    rx[:,index:index+2,0] = x
    #rx[:,index:index+2,1] = 1
    return rx

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

y_out
[[0.99 0.01]
 [0.76 0.24]
 [0.09 0.91]
 [0.58 0.42]]

loss
0.8080765

Вывод

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

person Anton Codes    schedule 29.03.2019
comment
Это не совсем то, что я ищу, но спасибо за новую интересную точку зрения и попытку оправдаться. - person dusa; 30.03.2019
comment
Я попробую и сообщу вам, как это работает в конце :) - person dusa; 30.03.2019
comment
Пожалуйста, сделай! Меня интересует, как это работает в вашем конкретном случае. - person Anton Codes; 31.03.2019