Ricerca…


introduzione

La convoluzione 2D è calcolata in un modo simile per calcolare la convoluzione 1D : si scorre il kernel sull'input, si calcolano le moltiplicazioni elementali e si sommano. Ma invece del tuo kernel / input è un array, qui sono matrici.

Nessuna spaziatura, passi = 1

Questo è l'esempio più semplice, con i calcoli più semplici. Supponiamo che il tuo input e il tuo kernel siano: inserisci la descrizione dell'immagine qui

Al tuo kernel riceverai il seguente output: inserisci la descrizione dell'immagine qui , che viene calcolato nel modo seguente:

  • 14 = 4 * 1 + 3 * 0 + 1 * 1 + 2 * 2 + 1 * 1 + 0 * 0 + 1 * 0 + 2 * 0 + 4 * 1
  • 6 = 3 * 1 + 1 * 0 + 0 * 1 + 1 * 2 + 0 * 1 + 1 * 0 + 2 * 0 + 4 * 0 + 1 * 1
  • 6 = 2 * 1 + 1 * 0 + 0 * 1 + 1 * 2 + 2 * 1 + 4 * 0 + 3 * 0 + 1 * 0 + 0 * 1
  • 12 = 1 * 1 + 0 * 0 + 1 * 1 + 2 * 2 + 4 * 1 + 1 * 0 + 1 * 0 + 0 * 0 + 2 * 1

La funzione conv2d di TF calcola le convoluzioni in lotti e utilizza un formato leggermente diverso. Per un input è [batch, in_height, in_width, in_channels] per il kernel è [filter_height, filter_width, in_channels, out_channels] . Quindi dobbiamo fornire i dati nel formato corretto:

import tensorflow as tf
k = tf.constant([
    [1, 0, 1],
    [2, 1, 0],
    [0, 0, 1]
], dtype=tf.float32, name='k')
i = tf.constant([
    [4, 3, 1, 0],
    [2, 1, 0, 1],
    [1, 2, 4, 1],
    [3, 1, 0, 2]
], dtype=tf.float32, name='i')
kernel = tf.reshape(k, [3, 3, 1, 1], name='kernel')
image  = tf.reshape(i, [1, 4, 4, 1], name='image')

Successivamente la convoluzione è calcolata con:

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 1, 1, 1], "VALID"))
# VALID means no padding
with tf.Session() as sess:
   print sess.run(res)

E sarà equivalente a quello che abbiamo calcolato a mano.

Alcuni padding, passi = 1

Padding è solo un nome di fantasia: racchiudi la tua matrice di input con una certa costante. Nella maggior parte dei casi la costante è zero ed è per questo che la gente lo chiama zero padding. Quindi se vuoi usare un padding di 1 nel nostro input originale (controlla il primo esempio con padding=0, strides=1 ), la matrice sarà simile a questa:

inserisci la descrizione dell'immagine qui

Per calcolare i valori della convoluzione fai lo stesso scorrimento. Si noti che nel nostro caso molti valori nel mezzo non devono essere ricalcolati (saranno uguali a quelli dell'esempio precedente. Inoltre non mostrerò tutti i calcoli qui, perché l'idea è diretta.

inserisci la descrizione dell'immagine qui

dove

  • 5 = 0 * 1 + 0 * 0 + 0 * 1 + 0 * 2 + 4 * 1 + 3 * 0 + 0 * 0 + 0 * 1 + 1 * 1
  • ...
  • 6 = 4 * 1 + 1 * 0 + 0 * 1 + 0 * 2 + 2 * 1 + 0 * 0 + 0 * 0 + 0 * 0 + 0 * 1

TF non supporta un padding arbitrario nella funzione conv2d , quindi se hai bisogno di un padding che non è supportato, usa tf.pad () . Fortunatamente per il nostro input il padding "SAME" sarà uguale a padding = 1. Quindi, nel nostro esempio precedente, non dobbiamo cambiare quasi nulla:

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 1, 1, 1], "SAME"))
# 'SAME' makes sure that our output has the same size as input and 
# uses appropriate padding. In our case it is 1.
with tf.Session() as sess:
   print sess.run(res)

Puoi verificare che la risposta sia la stessa calcolata a mano.

Imbottitura e falcate (il caso più generale)

Ora applicheremo una convoluzione scalata al nostro esempio imbottito precedentemente descritto e calcoleremo la convoluzione dove p = 1, s = 2

inserisci la descrizione dell'immagine qui

Precedentemente, quando abbiamo usato strides = 1 , la nostra finestra slitta si sposta di 1 posizione, con strides = s si muove per le posizioni s (devi calcolare s^2 elementi in meno. Ma nel nostro caso possiamo prendere una scorciatoia e non eseguire alcuna Computations affatto. Perché abbiamo già calcolato i valori per s = 1 , nel nostro caso possiamo semplicemente prendere ogni secondo elemento.

Quindi se la soluzione è caso di s = 1 era

inserisci la descrizione dell'immagine qui

in caso di s = 2 sarà:

inserisci la descrizione dell'immagine qui

Controllare le posizioni dei valori 14, 2, 12, 6 nella matrice precedente. L'unico cambiamento che dobbiamo eseguire nel nostro codice è quello di modificare le falcate da 1 a 2 per la larghezza e la quota (2-nd, 3-rd).

res = tf.squeeze(tf.nn.conv2d(image, kernel, [1, 2, 2, 1], "SAME"))
with tf.Session() as sess:
   print sess.run(res)

A proposito, non c'è nulla che ci impedisca di usare passi diversi per dimensioni diverse.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow