Как сопоставить входное изображение с нейронами в первом слое конвоя в CNN? - PullRequest
1 голос
/ 15 марта 2020

Я только что закончил курс ANN и начал изучать CNN. У меня есть базовое c понимание работы операций заполнения и шага в CNN.

Но мне сложно сопоставить входное изображение с нейронами в первом конвекционном слое, но у меня есть базовое c понимание того, как входные объекты отображаются на Первый скрытый слой в ANN.

Каков наилучший способ понимания сопоставления входного изображения с нейронами в первом слое конвоя?

Как я могу прояснить мои сомнения относительно приведенного ниже примера кода? Код взят из курса DL в Coursera.

    def initialize_parameters():
        """
        Initializes weight parameters to build a neural network with tensorflow. The shapes are:
                            W1 : [4, 4, 3, 8]
                            W2 : [2, 2, 8, 16]
        Returns:
        parameters -- a dictionary of tensors containing W1, W2
        """

        tf.set_random_seed(1)                              # so that your "random" numbers match ours

        ### START CODE HERE ### (approx. 2 lines of code)
        W1 = tf.get_variable("W1",[4,4,3,8],initializer = tf.contrib.layers.xavier_initializer(seed = 0))
        W2 = tf.get_variable("W2",[2,2,8,16],initializer = tf.contrib.layers.xavier_initializer(seed = 0))
        ### END CODE HERE ###

        parameters = {"W1": W1,
                      "W2": W2}

        return parameters


     def forward_propagation(X, parameters):
        """
        Implements the forward propagation for the model:
        CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED

        Arguments:
        X -- input dataset placeholder, of shape (input size, number of examples)
        parameters -- python dictionary containing your parameters "W1", "W2"
                      the shapes are given in initialize_parameters

        Returns:
        Z3 -- the output of the last LINEAR unit
        """

        # Retrieve the parameters from the dictionary "parameters" 
        W1 = parameters['W1']
        W2 = parameters['W2']

        ### START CODE HERE ###
        # CONV2D: stride of 1, padding 'SAME'
        Z1 = tf.nn.conv2d(X,W1, strides = [1,1,1,1], padding = 'SAME')
        # RELU
        A1 = tf.nn.relu(Z1)
        # MAXPOOL: window 8x8, sride 8, padding 'SAME'
        P1 = tf.nn.max_pool(A1, ksize = [1,8,8,1], strides = [1,8,8,1], padding = 'SAME')
        # CONV2D: filters W2, stride 1, padding 'SAME'
        Z2 = tf.nn.conv2d(P1,W2, strides = [1,1,1,1], padding = 'SAME')
        # RELU
        A2 = tf.nn.relu(Z2)
        # MAXPOOL: window 4x4, stride 4, padding 'SAME'
        P2 = tf.nn.max_pool(A2, ksize = [1,4,4,1], strides = [1,4,4,1], padding = 'SAME')
        # FLATTEN
        P2 = tf.contrib.layers.flatten(P2)
        # FULLY-CONNECTED without non-linear activation function (not not call softmax).
        # 6 neurons in output layer. Hint: one of the arguments should be "activation_fn=None" 
        Z3 = tf.contrib.layers.fully_connected(P2, 6,activation_fn=None)
        ### END CODE HERE ###

        return Z3

    with tf.Session() as sess:
        np.random.seed(1)
        X, Y = create_placeholders(64, 64, 3, 6)
        parameters = initialize_parameters()
        Z3 = forward_propagation(X, parameters)
        init = tf.global_variables_initializer()
        sess.run(init)
        a = sess.run(Z3, {X: np.random.randn(1,64,64,3), Y: np.random.randn(1,6)})
        print("Z3 = " + str(a))

Как это входное изображение размером 64 * 64 * 3 обрабатывается 8 фильтрами каждого размера 4 * 4 * 3?

stride = 1, padding = same и batch_size = 1.

Что я понял до сих пор, так это то, что каждый нейрон в первом слое конвоя будет иметь 8 фильтров, и каждый из них будет иметь размер 4 * 4 * 3. Каждый нейрон в первом слое свертки будет брать часть входного изображения, которая равна размеру фильтра (который здесь равен 4 * 4 * 3), и применяет операцию свертки и производит восемь отображений 64 * 64 объектов.

Если тогда мое понимание правильное:

1> Зачем нам нужна операция шага, поскольку размер ядра и часть входного изображения, проходящего через каждый нейрон, одинакова. Если мы применяем шаг = 1 (или 2), тогда граница части входного изображения крест, что нам не нужно, верно?

2> Как мы узнаем, какая часть входного изображения (такая же, как размер ядра) отображается, какой нейрон в первом слое конвоя?

Если нет, то:

3> Как входное изображение передается по нейронам в первом слое свертки, Is is complete входное изображение передается каждому нейрону (Как в полностью подключенном ANN, где все входные объекты отображаются на каждый нейрон в первом скрытом слое)?

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

4> Номер ядра, указанного выше в примере (W1 = [4, 4, 3, 8]), для каждого нейрона или всего число ядер в первом слое свертки?

5> как мы узнаем, как могут использоваться нейроны, использованные в приведенном выше примере в первом слое свертки.

6> Существует ли какая-либо связь между числом нейронов и числом первого слоя ядра ядра.

1 Ответ

0 голосов
/ 16 марта 2020

Я нашел релевантные ответы на свои вопросы и разместил их здесь.

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

Каждый нейрон будет фокусироваться только на определенной части входного изображения (где в полностью подключенном ANN каждый нейрон фокусируется на всем изображении), и каждый нейрон использует n фильтров / ядер, чтобы лучше понять конкретную часть изображения ,

Эти n фильтров / ядер, общих для всех нейронов в данном слое конв. Из-за этих весов (ядро / фильтр) общий характер у слоя conv будет меньше параметров для изучения. Где, как и в полностью подключенной сети ANN, каждый нейрон в виде своей собственной весовой матрицы и, следовательно, количества изучаемых параметров больше.

Теперь количество нейронов в данном конвильском слое 'L' зависит от input_size (выход предыдущего слой L-1), Kernel_size используется в слое L, Padding используется в слое L и Stride используется в слое L.

Теперь давайте ответим на каждый из вопросов, указанных выше.

1 > Как мы узнаем, какая часть входного изображения (такая же, как размер ядра) отображается, какой нейрон в первом слое конвекции?

    From above code example for conv layer 1:
    Batch size = 1
    Input image size = 64*64*3  
    Kernel size = 4*4*3 ==> Taken from W1
    Number of kernel = 8 ==> Taken from W1
    Padding = same
    stride = 1

    Stride = 1 means that you are sliding the kernel one pixel at a time. Let's consider x axis and number pixels 1, 2, 3 4 ... and 64. 

    The first neuron will see pixels 1 2,3 and 4, then the kernel is shifted by one pixel and the next neuron will see pixels 2 3, 4 and 5 and last neuron will see pixels 61, 62, 63 and 64 This happens if you use valid padding. 

    In case of same padding, first neuron will see pixels 0, 1, 2, and 3, the second neuron will see pixels 1, 2, 3 and 4, the last neuron will see pixels 62,63, 64 and (one zero padded). 

    In case the same padding case, you end up with the output of the same size as the image (64 x 64 x 8). In the case of valid padding, the output is (61 x 61 x 8).

    Where 8 in output represent the number of filters.

2> Как входное изображение передается по нейронам в Первый сверточный слой, Является ли завершенным входное изображение, которое передается каждому нейрону (как в полностью подключенном ANN, где все входные объекты отображаются на каждый нейрон в первом скрытом слое)?

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

3> Номер ядра, указанный в приведенном выше примере (W1 = [4, 4, 3, 8]), - на каждый нейрон или общее количество ядра в первом слое конвона?

Это общее количество ядер для этого слоя, и все нейроны этого слоя будут использовать одно и то же ядро ​​для изучения разных частей входного изображения. Следовательно, в con vnet число изучаемых параметров меньше по сравнению с полностью подключенным ANN.

4> Как мы узнаем, как могут использоваться нейроны, использованные в приведенном выше примере, в первом слое свертки?

Это зависит от input_size (выход предыдущего уровня L-1), Kernel_size, используемого в слое L, отступов, используемых в слое L, и Stride, используемых в слое L. Пожалуйста, обратитесь к первому ответу на вопрос выше для получения дополнительной информации.

5> Существует ли какая-либо связь между числом нейронов и числом первого слоя ядра ядра

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

Ниже пример кода поможет нам уточнить внутреннюю реализацию операции свертки.

def conv_forward(A_prev, W, b, hparameters):
    """
    Implements the forward propagation for a convolution function

    Arguments:
    A_prev -- output activations of the previous layer, numpy array of shape (m, n_H_prev, n_W_prev, n_C_prev)
    W -- Weights, numpy array of shape (f, f, n_C_prev, n_C)
    b -- Biases, numpy array of shape (1, 1, 1, n_C)
    hparameters -- python dictionary containing "stride" and "pad"

    Returns:
    Z -- conv output, numpy array of shape (m, n_H, n_W, n_C)
    cache -- cache of values needed for the conv_backward() function
    """

    # Retrieve dimensions from A_prev's shape (≈1 line)  
    (m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape

    # Retrieve dimensions from W's shape (≈1 line)
    (f, f, n_C_prev, n_C) = W.shape

    # Retrieve information from "hparameters" (≈2 lines)
    stride = hparameters['stride']
    pad = hparameters['pad']

    # Compute the dimensions of the CONV output volume using the formula given above. Hint: use int() to floor. (≈2 lines)
    n_H = int(np.floor((n_H_prev-f+2*pad)/stride)) + 1
    n_W = int(np.floor((n_W_prev-f+2*pad)/stride)) + 1

    # Initialize the output volume Z with zeros. (≈1 line)
    Z = np.zeros((m,n_H,n_W,n_C))

    # Create A_prev_pad by padding A_prev
    A_prev_pad = zero_pad(A_prev,pad)

    for i in range(m):                               # loop over the batch of training examples
        a_prev_pad = A_prev_pad[i]                               # Select ith training example's padded activation
        for h in range(n_H):                           # loop over vertical axis of the output volume
            for w in range(n_W):                       # loop over horizontal axis of the output volume
                for c in range(n_C):                   # loop over channels (= #filters) of the output volume

                    # Find the corners of the current "slice" (≈4 lines)
                    vert_start = h*stride
                    vert_end = vert_start+f
                    horiz_start = w*stride
                    horiz_end = horiz_start+f

                    # Use the corners to define the (3D) slice of a_prev_pad (See Hint above the cell). (≈1 line)
                    a_slice_prev = a_prev_pad[vert_start:vert_end,horiz_start:horiz_end,:]

                    # Convolve the (3D) slice with the correct filter W and bias b, to get back one output neuron. (≈1 line)
                    Z[i, h, w, c] = conv_single_step(a_slice_prev,W[:,:,:,c],b[:,:,:,c])                                      

    return Z



A_prev = np.random.randn(1,64,64,3)
W = np.random.randn(4,4,3,8)
#Don't worry about bias , tensorflow will take care of this.
b = np.random.randn(1,1,1,8)
hparameters = {"pad" : 1,
               "stride": 1}

Z = conv_forward(A_prev, W, b, hparameters)
...