复习了一下离散卷积,主要的步骤就是翻转、平移、相乘
复习了一下CNN的简单过程,并且看了一些卷机神经网络(CNN)反向传播算法,这个反向传播确实要比DNN的复杂一些,等过段时间写个博客总结一下吧。
基于numpy实现离散卷积
def conv(lst1, lst2):
res = []
lst1.reverse()
len1 = len(lst1)
len2 = len(lst2)
for i in range(1, len1+1): # 移入翻转后的第一个信号
tmp = lst1[len1-i:]
sum_area = sum((i*j for i, j in zip(tmp, lst2)))
res.append(sum_area)
for i in range(1, len2): #移出翻转后的第一个信号
tmp = lst2[i:]
sum_area = sum(((i*j for i, j in zip(tmp, lst1))))
res.append(sum_area)
return res
if __name__ == '__main__':
lst1 = [1, 2, 3]
lst2 = [4, 5]
print(conv(lst1, lst2))
基于numpy实现CNN
这部分代码是参考吴恩达 深度学习 编程作业 CNN4-1,没有写反向传播的部份了。
import numpy as np
import h5py
import matplotlib.pyplot as plt
# matplotlib inline
plt.rcParams['figure.figsize'] = (5.0, 4.0) # set default size of plots
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'
# load_ext autoreload
# autoreload 2
np.random.seed(1)
def zeros_pad(X, pad):
X_pad = np.pad(X, ((0,0), (pad,pad), (pad,pad), (0,0)), 'constant')
return X_pad
def conv_singl_step(a_slice_prev, W, b):
# a_slice_prev:(f, f, n_C_prev) W:(f, f, n_C_prev)
# b: (1, 1, 1)
s = a_slice_prev*W
z = np.sum(s)
z = z+b
return z
def conv_forward(A_prev, W, b, hparameters):
# A_prev: (m, n_H_prev, n_W_prev, n_C_prev)
# W: (f, f, n_C_prev, n_C)
# b: (1, 1, 1, n_C)
# hparameters: python dictionary containing "stride" and "pad"
(m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape
(f, f, n_C_prev, n_C) = W.shape
stride = hparameters["stride"]
pad = hparameters["pad"]
n_H = int((n_H_prev-f+2*pad)/stride+1)
n_W = int((n_W_prev-f+2*pad)/stride+1)
Z = np.zeors((m, n_H, n_W, n_C))
A_prev_pad = zeros_pad(A_prev, pad)
for i in range(m):
a_prev_pad = A_prev_pad[i, :, :, :]
for h in range(n_H):
for w in range(n_W):
for c in range(n_C):
h_start = stride*h
h_end = h_start+f
w_start = stride*w
w_end = w_start+f
a_slice_prev = a_prev_pad[h_start:h_end, w_start:w_end, :]
Z[i, h, w, c] = conv_singl_step(a_slice_prev, W[:,:,:,c], b[:,:,:,c])
assert Z.shape == (m, n_H, n_W, n_C)
cache = (A_prev, W, b, hparameters)
return Z, cache
def pool_forward(A_prev, hparameters, mode='max'):
# A_prev : (m, n_H_prev, n_W_prev, n_C_prev)
# hparameters : dictionary containing "f" and "stride"
# mode : the pooling mode including "max" or "average"
(m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape
f = hparameters['f']
stride = hparameters['stride']
n_H = int((n_H_prev-f)/stride+1)
n_W = int((n_W_prev-f)/stride+1)
n_C = n_C_prev
A = np.zeros((m, n_H, n_W, n_C))
for i in range(m):
for h in range(n_H):
for w in range(n_W):
for c in range(n_C):
h_start = h*stride
h_end = h_start+f
w_start = w*stride
w_end = w_start+f
a_prev_slice = A_prev[i, h_start:h_end, w_start:w_end, :]
if mode == 'max':
A[i, h, w, c] = np.max(a_prev_slice)
elif mode == 'average':
A[i, h, w, c] = np.mean(a_prev_slice)
cache = (A_prev, hparameters)
assert A.shape == (m, n_H, n_W, n_C)
return A, cache