動手學深度學習TF2.0第九課: 二維卷積神經網絡

卷積神經網絡: 含卷積層,有寬和高兩個維度,常用來處理圖像數據。

1.二維卷積(互相關運算)

'''
二維互相關運算: 
1. 卷積窗口(又被稱卷積核或過濾器(filter))從輸入數組的最左上方開始,按從左往右、從上往下的順序, 依次在輸入數組上滑動;
2. 當卷積窗口滑動到某一位置時,窗口中的輸入子數組與核數組按元素相乘並求和,得到輸出數組中相應位置的元素;

實現二維互相關運算函數如下:
'''
def corr2d(X,K):
	h,w = K.shape ## 獲取卷積核的尺寸(寬,高)
	Y = tf.Variable(tf.zeros((X.shape[0] - h + 1, X.shape[1] - w +1)))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i,j].assign(tf.cast(tf.reduce_sum(X[i:i+h, j:j+w] * K), dtype=tf.float32))
    return Y

'''測試實例: '''
X = tf.constant([[0,1,2], [3,4,5], [6,7,8]])
K = tf.constant([[0,1], [2,3]])
corr2d(X, K)

2. 二維卷積核+標量偏差(權重weight + 偏差bias)

類似於: Y = K*X+b (K–卷積核, b–偏差)

卷積層的一個應用: 檢測圖像中物體的邊緣,即找到像素變化的位置;

'''
爲實現檢測圖像的中物體的邊緣,需要構造一個頁數的卷積核K;
當它與輸入做互相關運算時,如果橫向相鄰元素相同,輸出爲0; 否則輸出爲非0;
'''

K = tf.constrant([[-1,1]], dtype=tf.float32)

3. 實例測試: 通過給出輸入X和輸出Y,獲取兩者之間的係數權重

在這裏使用卷積的方式來獲取權重係數,但忽略偏差.

#!/bin/bash
# -*-coding:utf-8-*-

import tensorflow as tf
print(tf.__version__)

# 二維卷積計算函數
def corr2d(X, K):
    h, w = K.shape
    Y = tf.Variable(tf.zeros((X.shape[0] - h + 1, X.shape[1] - w +1)))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j].assign(tf.cast(tf.reduce_sum(X[i:i+h, j:j+w] * K), dtype=tf.float32))
    return Y

X = tf.Variable(tf.ones((6, 8)))
X[:, 2:6].assign(tf.zeros(X[:, 2:6].shape))  # 輸入數據
K = tf.constant([[1,-1]], dtype = tf.float32) # 卷積核

Y= corr2d(X, K) # 輸出數據

X = tf.reshape(X, (1, 6, 8, 1))  # 重置尺寸
Y = tf.reshape(Y, (1, 6, 7, 1))  # 重置尺寸

# print("X = ", X)
# 根據上一步測試中獲取的X-Y值, 從而反推算其內核K;

conv2d = tf.keras.layers.Conv2D(1, (1, 2))
# print(tf.reshape(conv2d.get_weights()[0], (1, 2)))
print('Y.shape = ', Y.shape)
Y_hat = conv2d(X)
# print(Y_hat)
for i in range(10):
    with tf.GradientTape(watch_accessed_variables=False) as tt:
        tt.watch(conv2d.weights[0])
        Y_hat = conv2d(X)
        m_error = (abs(Y_hat - Y)) ** 2
        dl = tt.gradient(m_error, conv2d.weights[0])
        lr = 3e-2
        update = tf.multiply(lr, dl)
        update_weights = conv2d.get_weights()
        update_weights[0] = conv2d.weights[0] - update
        conv2d.set_weights(update_weights)

        if(i + 1) % 2 == 0:
            print('batch %d, loss %.4f' % (i + 1, tf.reduce_sum(m_error)))


print(tf.reshape(conv2d.get_weights()[0], (1, 2)))
  • 互相關運算+卷積運算
問: 卷積層爲何能使用互相關運算替代卷積運算?
答: 在深度學習中核數組都是學出來的:卷積層無論使用互相關運算或卷積運算都不影響模型預測時的輸出;

  • 特徵圖+感受野
`特徵圖:`  二維卷積層輸出的二維數組可以看作是輸入在空間維度(寬和高)上某一級的表徵,也叫特徵圖(feature map);

'感受野:' 影響元素x(數組)的前向計算的所有可能輸入區域(可能大於輸入的實際尺寸)叫做x的感受野(receptive field)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章