1. 知识点

  • 计算机视觉:图片分类、目标检测、图片风格迁移等

对于小尺寸图片,可以用深度神经网络模型学习预测。但对于大尺寸图片,输入数据规模大,用深度神经网络会有非常多的参数需要学习,不再合适。

卷积神经网络,在计算机视觉上是个很好的网络结构。

  • 边缘检测:垂直边缘检测、水平边缘检测和更复杂的边缘检测filter

垂直边缘检测:用filter依次对输入图片和filter相同大小的块内各元素进行运算,对应元素相乘后求和。所得结果为输出图片元素。由例图可以看出,垂直边缘检测filter能运算出输入图像人在垂直方向上的轮廓。

多种边缘检测:垂直边缘检测、水平边缘检测、更复杂的边缘检测(将fliter看作需要学习的参数)

数学上的卷积和深度学习的卷积:数学上,卷积操作需要先将卷积核filter在水平和垂直方向上进行翻转,构成一个卷积核的镜像,然后使用该镜像再和前面的矩阵进行移动相乘求和操作。深度学习上,没有卷积核变换为镜像的这一步。

  • Padding:

没有Padding存在的问题:每次卷积操作图片会缩小。角落和边缘位置的像素进行运算的次数少,信息会丢失。

加Padding:输入图片n*n大小,Padding大小为p,filter大小为f,输出图片为(n+2p-f+1)*(n+2p-f+1)

不加Padding:输入图片大小为n*n,输出图片大小(n-f+1)*(n-f+1)

输出图片和输入图片大小相同:n+2p-f+1=n,即p=(f-1)/2

  • 卷积步长(s):即两个运算之间移动的步数 

输入图片大小为n*n,输出图片大小[(n+2p-f)/s+1]*[(n+2p-f)/s+1]

  • 立体卷积

卷积核的通道数:R、G、B三个颜色通道 

多卷积核:不同的filter分别提取图片的不同特征,比如垂直边缘和水平边缘

多卷积核输入图片和输出图片大小:

(n*n*nc)*(f*f*nc)——>(n-f+1)*(n-f+1)*nc',其中nc'是下一层通道数,也是本层filter的个数。

  • 简单卷积网络:卷积核相当于深度网络中的参数W

其中,参数W的个数为3*3*3=27,加上偏置,参数个数为28个,假设有10个卷积核,参数个数共280个。相对于普通神经网络,卷积神经网络的参数个数少了很多。

  • 简单卷积网络示例:三层卷积,和一层全连接层

  • 池化层:最大池化和平均池化,输入图片维度和输出图片维度之间的关系和卷积相运算相同

  • 卷积神经网络示例:卷积-池化-卷积-池化-线性运算-激活。卷积层参数较少,线性运算层参数很多。

2. 应用实例:用卷积预测手势图片是几

实现思路:

1)进行zero_pad()运算,用0对图片上下左右进行扩展。
2)根据输入图片的维度n_H_prev、n_W_prev,通道数n_C_prev,过滤器维度f,步长Stride,计算卷积输出的维度,
n_H=int((n_H_prev-f+2*pad)/Stride)+1,n_w同理。过滤器个数为卷积输出的通道数。
3)依次用输入图片切片与过滤器filter进行运算,输出图片的维度为(m,n_H,n_W,n_C)。
4)对卷积输出进行激活运算。
5)对激活运算输出进行池化运算。
6)将运算结果降维至一维。
7)对一维数据进行全连接运算。
8)对全连接结果进行softmax运算,并计算成本。

tensorflow:
1)加载数据。
2)创建X、Y占位符。
3)初始化参数W1、W2,为过滤器参数。
4)用W1进行卷积运算。
5)对卷积结果进行激活运算,relu()。
6)对激活结果进行池化运算。
7)重复4)至6),用W2进行第二层卷积、池化运算。
8)将池化结果降维至一维。
9)对结果进行全连接运算。
10)对全连接结果进行softmax运算,并计算成本。
11)用tf反向传播优化器AdamOptimizer计算参数和成本。

import numpy as np
import h5py
import matplotlib.pyplot as plt%matplotlib inline
plt.rcParams['figure.figsize'] = (5.0, 4.0)
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'#ipython很好用,但是如果在ipython里已经import过的模块修改后需要重新reload就需要这样
#在执行用户代码前,重新装入软件的扩展和模块。
%load_ext autoreload
#autoreload 2:装入所有 %aimport 不包含的模块。
%autoreload 2          np.random.seed(1)      #指定随机种子
def zero_pad(X,pad):"""把数据集X的图像边界全部使用0来扩充pad个宽度和高度。参数:X - 图像数据集,维度为(样本数,图像高度,图像宽度,图像通道数)pad - 整数,每个图像在垂直和水平维度上的填充量返回:X_paded - 扩充后的图像数据集,维度为(样本数,图像高度 + 2*pad,图像宽度 + 2*pad,图像通道数)"""X_paded = np.pad(X,((0,0),       #样本数,不填充(pad,pad),   #图像高度,你可以视为上面填充x个,下面填充y个(x,y)(pad,pad),   #图像宽度,你可以视为左边填充x个,右边填充y个(x,y)(0,0)),      #通道数,不填充'constant', constant_values=0)      #连续一样的值填充return X_paded
np.random.seed(1)
x = np.random.randn(4,3,3,2)
x_paded = zero_pad(x,2)
#查看信息
print ("x.shape =", x.shape)
print ("x_paded.shape =", x_paded.shape)
#print("x=",x)
#print("x_paded=",x_paded)
print ("x[1, 1] =", x[1, 1])
print ("x_paded[1, 1] =", x_paded[1, 1])#print("x=",x)
print("x[0,:,:,:]=",x[0,:,:,:])
print("x[0,:,:,0]=",x[0,:,:,0])
print("x[0,:,:,1]=",x[0,:,:,1])  #绘制图
fig , axarr = plt.subplots(1,4)  #一行两列
axarr[0].set_title('x')
axarr[0].imshow(x[0,:,:,0])axarr[1].set_title('x')
axarr[1].imshow(x[0,:,:,1])#axarr[0].imshow(x[0,:,:,1])
axarr[2].set_title('x_paded')
axarr[2].imshow(x_paded[0,:,:,0])axarr[3].set_title('x')
axarr[3].imshow(x[2,:,:,0])
#axarr[0].imshow(x[0,:,:,1])
#axarr[2].set_title('x')
#axarr[2].imshow(x[2,:,:,1])
x.shape = (4, 3, 3, 2)
x_paded.shape = (4, 7, 7, 2)
x[1, 1] = [[ 0.90085595 -0.68372786][-0.12289023 -0.93576943][-0.26788808  0.53035547]]
x_paded[1, 1] = [[0. 0.][0. 0.][0. 0.][0. 0.][0. 0.][0. 0.][0. 0.]]
x[0,:,:,:]= [[[ 1.62434536 -0.61175641][-0.52817175 -1.07296862][ 0.86540763 -2.3015387 ]][[ 1.74481176 -0.7612069 ][ 0.3190391  -0.24937038][ 1.46210794 -2.06014071]][[-0.3224172  -0.38405435][ 1.13376944 -1.09989127][-0.17242821 -0.87785842]]]
x[0,:,:,0]= [[ 1.62434536 -0.52817175  0.86540763][ 1.74481176  0.3190391   1.46210794][-0.3224172   1.13376944 -0.17242821]]
x[0,:,:,1]= [[-0.61175641 -1.07296862 -2.3015387 ][-0.7612069  -0.24937038 -2.06014071][-0.38405435 -1.09989127 -0.87785842]]

Out[34]:

<matplotlib.image.AxesImage at 0x1334eb450>
def conv_single_step(a_slice_prev,W,b):"""在前一层的激活输出的一个片段上应用一个由参数W定义的过滤器。这里切片大小和过滤器大小相同参数:a_slice_prev - 输入数据的一个片段,维度为(过滤器大小,过滤器大小,上一通道数)W - 权重参数,包含在了一个矩阵中,维度为(过滤器大小,过滤器大小,上一通道数)b - 偏置参数,包含在了一个矩阵中,维度为(1,1,1)返回:Z - 在输入数据的片X上卷积滑动窗口(w,b)的结果。"""s = np.multiply(a_slice_prev,W) + bZ = np.sum(s)return Z
np.random.seed(1)#这里切片大小和过滤器大小相同
a_slice_prev = np.random.randn(4,4,3)
W = np.random.randn(4,4,3)
b = np.random.randn(1,1,1)
print("W=",W)
print("a=",a_slice_prev)
print("b=",b)Z = conv_single_step(a_slice_prev,W,b)print("Z = " + str(Z))
W= [[[ 0.12015895  0.61720311  0.30017032][-0.35224985 -1.1425182  -0.34934272][-0.20889423  0.58662319  0.83898341][ 0.93110208  0.28558733  0.88514116]][[-0.75439794  1.25286816  0.51292982][-0.29809284  0.48851815 -0.07557171][ 1.13162939  1.51981682  2.18557541][-1.39649634 -1.44411381 -0.50446586]][[ 0.16003707  0.87616892  0.31563495][-2.02220122 -0.30620401  0.82797464][ 0.23009474  0.76201118 -0.22232814][-0.20075807  0.18656139  0.41005165]][[ 0.19829972  0.11900865 -0.67066229][ 0.37756379  0.12182127  1.12948391][ 1.19891788  0.18515642 -0.37528495][-0.63873041  0.42349435  0.07734007]]]
a= [[[ 1.62434536 -0.61175641 -0.52817175][-1.07296862  0.86540763 -2.3015387 ][ 1.74481176 -0.7612069   0.3190391 ][-0.24937038  1.46210794 -2.06014071]][[-0.3224172  -0.38405435  1.13376944][-1.09989127 -0.17242821 -0.87785842][ 0.04221375  0.58281521 -1.10061918][ 1.14472371  0.90159072  0.50249434]][[ 0.90085595 -0.68372786 -0.12289023][-0.93576943 -0.26788808  0.53035547][-0.69166075 -0.39675353 -0.6871727 ][-0.84520564 -0.67124613 -0.0126646 ]][[-1.11731035  0.2344157   1.65980218][ 0.74204416 -0.19183555 -0.88762896][-0.74715829  1.6924546   0.05080775][-0.63699565  0.19091548  2.10025514]]]
b= [[[-0.34385368]]]
Z = -23.16021220252078
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),(1,1,1,这一层的过滤器数量)hparameters - 包含了"stride"与 "pad"的超参数字典。返回:Z - 卷积输出,维度为(m, n_H, n_W, n_C),(样本数,图像的高度,图像的宽度,过滤器数量)cache - 缓存了一些反向传播函数conv_backward()需要的一些数据"""#获取来自上一层数据的基本信息(m , n_H_prev , n_W_prev , n_C_prev) = A_prev.shape#获取权重矩阵的基本信息( f , f ,n_C_prev , n_C ) = W.shape#获取超参数hparameters的值stride = hparameters["stride"]pad = hparameters["pad"]#计算卷积后的图像的宽度高度,参考上面的公式,使用int()来进行板除n_H = int(( n_H_prev - f + 2 * pad )/ stride) + 1n_W = int(( n_W_prev - f + 2 * pad )/ stride) + 1#使用0来初始化卷积输出ZZ = np.zeros((m,n_H,n_W,n_C))#通过A_prev创建填充过了的A_prev_padA_prev_pad = zero_pad(A_prev,pad)for i in range(m):                              #遍历样本a_prev_pad = A_prev_pad[i]                  #选择第i个样本的扩充后的激活矩阵for h in range(n_H):                        #在输出的垂直轴上循环for w in range(n_W):                    #在输出的水平轴上循环for c in range(n_C):                #循环遍历输出的通道#定位当前的切片位置vert_start = h * stride         #竖向,开始的位置vert_end = vert_start + f       #竖向,结束的位置horiz_start = w * stride        #横向,开始的位置horiz_end = horiz_start + f     #横向,结束的位置#切片位置定位好了我们就把它取出来,需要注意的是我们是“穿透”取出来的,#自行脑补一下吸管插入一层层的橡皮泥就明白了a_slice_prev = a_prev_pad[vert_start:vert_end,horiz_start:horiz_end,:]#执行单步卷积Z[i,h,w,c] = conv_single_step(a_slice_prev,W[: ,: ,: ,c],b[0,0,0,c])#数据处理完毕,验证数据格式是否正确assert(Z.shape == (m , n_H , n_W , n_C ))#存储一些缓存值,以便于反向传播使用cache = (A_prev,W,b,hparameters)return (Z , cache)
np.random.seed(1)A_prev = np.random.randn(10,4,4,3)
W = np.random.randn(2,2,3,8)
b = np.random.randn(1,1,1,8)hparameters = {"pad" : 2, "stride": 1}Z , cache_conv = conv_forward(A_prev,W,b,hparameters)print("np.mean(Z) = ", np.mean(Z))
print("cache_conv[0][1][2][3] =", cache_conv[0][1][2][3])
np.mean(Z) =  0.15585932488906465
cache_conv[0][1][2][3] = [-0.20075807  0.18656139  0.41005165]
def pool_forward(A_prev,hparameters,mode="max"):"""实现池化层的前向传播参数:A_prev - 输入数据,维度为(m, n_H_prev, n_W_prev, n_C_prev)hparameters - 包含了 "f" 和 "stride"的超参数字典mode - 模式选择【"max" | "average"】返回:A - 池化层的输出,维度为 (m, n_H, n_W, n_C)cache - 存储了一些反向传播需要用到的值,包含了输入和超参数的字典。"""#获取输入数据的基本信息(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 ) + 1n_W = int((n_W_prev - f) / stride ) + 1n_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):                #循环遍历输出的通道#定位当前的切片位置vert_start = h * stride         #竖向,开始的位置vert_end = vert_start + f       #竖向,结束的位置horiz_start = w * stride        #横向,开始的位置horiz_end = horiz_start + f     #横向,结束的位置#定位完毕,开始切割a_slice_prev = A_prev[i,vert_start:vert_end,horiz_start:horiz_end,c]#对切片进行池化操作if mode == "max":A[ i , h , w , c ] = np.max(a_slice_prev)elif mode == "average":A[ i , h , w , c ] = np.mean(a_slice_prev)#池化完毕,校验数据格式assert(A.shape == (m , n_H , n_W , n_C))#校验完毕,开始存储用于反向传播的值cache = (A_prev,hparameters)return A,cache
np.random.seed(1)
A_prev = np.random.randn(2,4,4,3)
hparameters = {"f":4 , "stride":1}A , cache = pool_forward(A_prev,hparameters,mode="max")
A, cache = pool_forward(A_prev, hparameters)
print("mode = max")
print("A =", A)
print("----------------------------")
A, cache = pool_forward(A_prev, hparameters, mode = "average")
print("mode = average")
print("A =", A)
mode = max
A = [[[[1.74481176 1.6924546  2.10025514]]][[[1.19891788 1.51981682 2.18557541]]]]
----------------------------
mode = average
A = [[[[-0.09498456  0.11180064 -0.14263511]]][[[-0.09525108  0.28325018  0.33035185]]]]
def conv_backward(dZ,cache):"""实现卷积层的反向传播参数:dZ - 卷积层的输出Z的 梯度,维度为(m, n_H, n_W, n_C)cache - 反向传播所需要的参数,conv_forward()的输出之一返回:dA_prev - 卷积层的输入(A_prev)的梯度值,维度为(m, n_H_prev, n_W_prev, n_C_prev)dW - 卷积层的权值的梯度,维度为(f,f,n_C_prev,n_C)db - 卷积层的偏置的梯度,维度为(1,1,1,n_C)"""#获取cache的值(A_prev, W, b, hparameters) = cache#获取A_prev的基本信息(m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape#获取dZ的基本信息(m,n_H,n_W,n_C) = dZ.shape#获取权值的基本信息(f, f, n_C_prev, n_C) = W.shape#获取hparaeters的值pad = hparameters["pad"]stride = hparameters["stride"]#初始化各个梯度的结构dA_prev = np.zeros((m,n_H_prev,n_W_prev,n_C_prev))dW = np.zeros((f,f,n_C_prev,n_C))db = np.zeros((1,1,1,n_C))#前向传播中我们使用了pad,反向传播也需要使用,这是为了保证数据结构一致A_prev_pad = zero_pad(A_prev,pad)dA_prev_pad = zero_pad(dA_prev,pad)#现在处理数据for i in range(m):#选择第i个扩充了的数据的样本,降了一维。a_prev_pad = A_prev_pad[i]da_prev_pad = dA_prev_pad[i]for h in range(n_H):for w in range(n_W):for c in range(n_C):#定位切片位置vert_start = hvert_end = vert_start + fhoriz_start = whoriz_end = horiz_start + f#定位完毕,开始切片a_slice = a_prev_pad[vert_start:vert_end,horiz_start:horiz_end,:]#切片完毕,使用上面的公式计算梯度da_prev_pad[vert_start:vert_end, horiz_start:horiz_end,:] += W[:,:,:,c] * dZ[i, h, w, c]dW[:,:,:,c] += a_slice * dZ[i,h,w,c]db[:,:,:,c] += dZ[i,h,w,c]#设置第i个样本最终的dA_prev,即把非填充的数据取出来。dA_prev[i,:,:,:] = da_prev_pad[pad:-pad, pad:-pad, :]#数据处理完毕,验证数据格式是否正确assert(dA_prev.shape == (m, n_H_prev, n_W_prev, n_C_prev))return (dA_prev,dW,db)
np.random.seed(1)
#初始化参数
A_prev = np.random.randn(10,4,4,3)
W = np.random.randn(2,2,3,8)
b = np.random.randn(1,1,1,8)
hparameters = {"pad" : 2, "stride": 1}#前向传播
Z , cache_conv = conv_forward(A_prev,W,b,hparameters)
#反向传播
dA , dW , db = conv_backward(Z,cache_conv)
print("dA_mean =", np.mean(dA))
print("dW_mean =", np.mean(dW))
print("db_mean =", np.mean(db))
dA_mean = 9.608990675868995
dW_mean = 10.581741275547566
db_mean = 76.37106919563735
def create_mask_from_window(x):"""从输入矩阵中创建掩码,以保存最大值的矩阵的位置。参数:x - 一个维度为(f,f)的矩阵返回:mask - 包含x的最大值的位置的矩阵"""mask = x == np.max(x)return mask
np.random.seed(1)x = np.random.randn(2,3)mask = create_mask_from_window(x)print("x = " + str(x))
print("mask = " + str(mask))
x = [[ 1.62434536 -0.61175641 -0.52817175][-1.07296862  0.86540763 -2.3015387 ]]
mask = [[ True False False][False False False]]
def distribute_value(dz,shape):"""给定一个值,为按矩阵大小平均分配到每一个矩阵位置中。参数:dz - 输入的实数shape - 元组,两个值,分别为n_H , n_W返回:a - 已经分配好了值的矩阵,里面的值全部一样。"""#获取矩阵的大小(n_H , n_W) = shape#计算平均值average = dz / (n_H * n_W)#填充入矩阵a = np.ones(shape) * averagereturn a
dz = 2
shape = (2,2)a = distribute_value(dz,shape)
print("a = " + str(a))
a = [[0.5 0.5][0.5 0.5]]
def pool_backward(dA,cache,mode = "max"):"""实现池化层的反向传播参数:dA - 池化层的输出的梯度,和池化层的输出的维度一样cache - 池化层前向传播时所存储的参数。mode - 模式选择,【"max" | "average"】返回:dA_prev - 池化层的输入的梯度,和A_prev的维度相同"""#获取cache中的值(A_prev , hparaeters) = cache#获取hparaeters的值f = hparaeters["f"]stride = hparaeters["stride"]#获取A_prev和dA的基本信息(m , n_H_prev , n_W_prev , n_C_prev) = A_prev.shape(m , n_H , n_W , n_C) = dA.shape#初始化输出的结构dA_prev = np.zeros_like(A_prev)#开始处理数据for i in range(m):a_prev = A_prev[i]      for h in range(n_H):for w in range(n_W):for c in range(n_C):#定位切片位置vert_start = hvert_end = vert_start + fhoriz_start = whoriz_end = horiz_start + f#选择反向传播的计算方式if mode == "max":#开始切片a_prev_slice = a_prev[vert_start:vert_end,horiz_start:horiz_end,c]#创建掩码mask = create_mask_from_window(a_prev_slice)#计算dA_prevdA_prev[i,vert_start:vert_end,horiz_start:horiz_end,c] += np.multiply(mask,dA[i,h,w,c])elif mode == "average":#获取dA的值da = dA[i,h,w,c]#定义过滤器大小shape = (f,f)#平均分配dA_prev[i,vert_start:vert_end, horiz_start:horiz_end ,c] += distribute_value(da,shape)#数据处理完毕,开始验证格式assert(dA_prev.shape == A_prev.shape)return dA_prev
np.random.seed(1)
A_prev = np.random.randn(5, 5, 3, 2)
hparameters = {"stride" : 1, "f": 2}
A, cache = pool_forward(A_prev, hparameters)
dA = np.random.randn(5, 4, 2, 2)dA_prev = pool_backward(dA, cache, mode = "max")
print("mode = max")
print('mean of dA = ', np.mean(dA))
print('dA_prev[1,1] = ', dA_prev[1,1])
print()
dA_prev = pool_backward(dA, cache, mode = "average")
print("mode = average")
print('mean of dA = ', np.mean(dA))
print('dA_prev[1,1] = ', dA_prev[1,1]) 
mode = max
mean of dA =  0.14571390272918056
dA_prev[1,1] =  [[ 0.          0.        ][ 5.05844394 -1.68282702][ 0.          0.        ]]mode = average
mean of dA =  0.14571390272918056
dA_prev[1,1] =  [[ 0.08485462  0.2787552 ][ 1.26461098 -0.25749373][ 1.17975636 -0.53624893]]
import math
import numpy as np
import h5py
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import tensorflow as tf
from tensorflow.python.framework import opsimport cnn_utils%matplotlib inline
np.random.seed(1)
index = 6
plt.imshow(X_train_orig[index])
print ("y = " + str(np.squeeze(Y_train_orig[:, index])))
y = 2

X_train = X_train_orig/255.
X_test = X_test_orig/255.
Y_train = cnn_utils.convert_to_one_hot(Y_train_orig, 6).T
Y_test = cnn_utils.convert_to_one_hot(Y_test_orig, 6).T
print ("number of training examples = " + str(X_train.shape[0]))
print ("number of test examples = " + str(X_test.shape[0]))
print ("X_train shape: " + str(X_train.shape))
print ("Y_train shape: " + str(Y_train.shape))
print ("X_test shape: " + str(X_test.shape))
print ("Y_test shape: " + str(Y_test.shape))
conv_layers = {}
number of training examples = 1080
number of test examples = 120
X_train shape: (1080, 64, 64, 3)
Y_train shape: (1080, 6)
X_test shape: (120, 64, 64, 3)
Y_test shape: (120, 6)
def create_placeholders(n_H0, n_W0, n_C0, n_y):"""为session创建占位符参数:n_H0 - 实数,输入图像的高度n_W0 - 实数,输入图像的宽度n_C0 - 实数,输入的通道数n_y  - 实数,分类数输出:X - 输入数据的占位符,维度为[None, n_H0, n_W0, n_C0],类型为"float"Y - 输入数据的标签的占位符,维度为[None, n_y],维度为"float""""X = tf.placeholder(tf.float32,[None, n_H0, n_W0, n_C0])Y = tf.placeholder(tf.float32,[None, n_y])return X,Y
X , Y = create_placeholders(64,64,3,6)
print ("X = " + str(X))
print ("Y = " + str(Y))
X = Tensor("Placeholder_5:0", shape=(?, 64, 64, 3), dtype=float32)
Y = Tensor("Placeholder_6:0", shape=(?, 6), dtype=float32)
def initialize_parameters():"""初始化权值矩阵,这里我们把权值矩阵硬编码:W1 : [4, 4, 3, 8]W2 : [2, 2, 8, 16]返回:包含了tensor类型的W1、W2的字典"""tf.set_random_seed(1)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))parameters = {"W1": W1,"W2": W2}return parameters
tf.reset_default_graph()
with tf.Session() as sess_test:parameters = initialize_parameters()init = tf.global_variables_initializer()sess_test.run(init)print("W1 = " + str(parameters["W1"].eval()[1,1,1]))print("W2 = " + str(parameters["W2"].eval()[1,1,1]))sess_test.close()
W1 = [ 0.00131723  0.1417614  -0.04434952  0.09197326  0.14984085 -0.03514394-0.06847463  0.05245192]
W2 = [-0.08566415  0.17750949  0.11974221  0.16773748 -0.0830943  -0.08058-0.00577033 -0.14643836  0.24162132 -0.05857408 -0.19055021  0.1345228-0.22779644 -0.1601823  -0.16117483 -0.10286498]
def forward_propagation(X,parameters):"""实现前向传播CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED参数:X - 输入数据的placeholder,维度为(输入节点数量,样本数量)parameters - 包含了“W1”和“W2”的python字典。返回:Z3 - 最后一个LINEAR节点的输出"""W1 = parameters['W1']W2 = parameters['W2']#Conv2d : 步伐:1,填充方式:“SAME”Z1 = tf.nn.conv2d(X,W1,strides=[1,1,1,1],padding="SAME")#ReLU :A1 = tf.nn.relu(Z1)#Max pool : 窗口大小:8x8,步伐:8x8,填充方式:“SAME”P1 = tf.nn.max_pool(A1,ksize=[1,8,8,1],strides=[1,8,8,1],padding="SAME")#Conv2d : 步伐:1,填充方式:“SAME”Z2 = tf.nn.conv2d(P1,W2,strides=[1,1,1,1],padding="SAME")#ReLU :A2 = tf.nn.relu(Z2)#Max pool : 过滤器大小:4x4,步伐:4x4,填充方式:“SAME”P2 = tf.nn.max_pool(A2,ksize=[1,4,4,1],strides=[1,4,4,1],padding="SAME")#一维化上一层的输出P = tf.contrib.layers.flatten(P2)#全连接层(FC):使用没有非线性激活函数的全连接层Z3 = tf.contrib.layers.fully_connected(P,6,activation_fn=None)return Z3
tf.reset_default_graph()
np.random.seed(1)with tf.Session() as sess_test:X,Y = create_placeholders(64,64,3,6)parameters = initialize_parameters()Z3 = forward_propagation(X,parameters)init = tf.global_variables_initializer()sess_test.run(init)a = sess_test.run(Z3,{X: np.random.randn(2,64,64,3), Y: np.random.randn(2,6)})print("Z3 = " + str(a))sess_test.close()
WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/tensorflow/contrib/layers/python/layers/layers.py:1634: flatten (from tensorflow.python.layers.core) is deprecated and will be removed in a future version.
Instructions for updating:
Use keras.layers.flatten instead.
Z3 = [[ 1.4416982  -0.24909668  5.4504995  -0.2618962  -0.20669872  1.3654671 ][ 1.4070847  -0.02573182  5.08928    -0.4866991  -0.4094069   1.2624853 ]]
def compute_cost(Z3,Y):"""计算成本参数:Z3 - 正向传播最后一个LINEAR节点的输出,维度为(6,样本数)。Y - 标签向量的placeholder,和Z3的维度相同返回:cost - 计算后的成本"""cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=Z3,labels=Y))return cost
tf.reset_default_graph()with tf.Session() as sess_test:np.random.seed(1)X,Y = create_placeholders(64,64,3,6)parameters = initialize_parameters()Z3 = forward_propagation(X,parameters)cost = compute_cost(Z3,Y)init = tf.global_variables_initializer()sess_test.run(init)a = sess_test.run(cost,{X: np.random.randn(4,64,64,3), Y: np.random.randn(4,6)})print("cost = " + str(a))sess_test.close()
cost = 4.6648703
def model(X_train, Y_train, X_test, Y_test, learning_rate=0.009, num_epochs=100,minibatch_size=64,print_cost=True,isPlot=True):"""使用TensorFlow实现三层的卷积神经网络CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED参数:X_train - 训练数据,维度为(None, 64, 64, 3)Y_train - 训练数据对应的标签,维度为(None, n_y = 6)X_test - 测试数据,维度为(None, 64, 64, 3)Y_test - 训练数据对应的标签,维度为(None, n_y = 6)learning_rate - 学习率num_epochs - 遍历整个数据集的次数minibatch_size - 每个小批量数据块的大小print_cost - 是否打印成本值,每遍历100次整个数据集打印一次isPlot - 是否绘制图谱返回:train_accuracy - 实数,训练集的准确度test_accuracy - 实数,测试集的准确度parameters - 学习后的参数"""ops.reset_default_graph()  #能够重新运行模型而不覆盖tf变量tf.set_random_seed(1)    #确保你的数据和我一样seed = 3                 #指定numpy的随机种子(m , n_H0, n_W0, n_C0) = X_train.shapen_y = Y_train.shape[1]costs = []#为当前维度创建占位符X , Y = create_placeholders(n_H0, n_W0, n_C0, n_y)#初始化参数parameters = initialize_parameters()#前向传播Z3 = forward_propagation(X,parameters)#计算成本cost = compute_cost(Z3,Y)#反向传播,由于框架已经实现了反向传播,我们只需要选择一个优化器就行了optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)#全局初始化所有变量init = tf.global_variables_initializer()#开始运行with tf.Session() as sess:#初始化参数sess.run(init)#开始遍历数据集for epoch in range(num_epochs):minibatch_cost = 0num_minibatches = int(m / minibatch_size) #获取数据块的数量seed = seed + 1minibatches = cnn_utils.random_mini_batches(X_train,Y_train,minibatch_size,seed) #对每个数据块进行处理for minibatch in minibatches:#选择一个数据块(minibatch_X,minibatch_Y) = minibatch#最小化这个数据块的成本_ , temp_cost = sess.run([optimizer,cost],feed_dict={X:minibatch_X, Y:minibatch_Y})#累加数据块的成本值minibatch_cost += temp_cost / num_minibatches#是否打印成本if print_cost:#每5代打印一次if epoch % 5 == 0:print("当前是第 " + str(epoch) + " 代,成本值为:" + str(minibatch_cost))#记录成本if epoch % 1 == 0:costs.append(minibatch_cost)#数据处理完毕,绘制成本曲线if isPlot:plt.plot(np.squeeze(costs))plt.ylabel('cost')plt.xlabel('iterations (per tens)')plt.title("Learning rate =" + str(learning_rate))plt.show()#开始预测数据## 计算当前的预测情况predict_op = tf.arg_max(Z3,1)corrent_prediction = tf.equal(predict_op , tf.arg_max(Y,1))##计算准确度accuracy = tf.reduce_mean(tf.cast(corrent_prediction,"float"))print("corrent_prediction accuracy= " + str(accuracy))train_accuracy = accuracy.eval({X: X_train, Y: Y_train})test_accuary = accuracy.eval({X: X_test, Y: Y_test})print("训练集准确度:" + str(train_accuracy))print("测试集准确度:" + str(test_accuary))return (train_accuracy,test_accuary,parameters)
_, _, parameters = model(X_train, Y_train, X_test, Y_test,num_epochs=150)
当前是第 0 代,成本值为:1.9213323891162872
当前是第 5 代,成本值为:1.9041557759046555
当前是第 10 代,成本值为:1.9043088406324387
当前是第 15 代,成本值为:1.904477171599865
当前是第 20 代,成本值为:1.9018685296177864
当前是第 25 代,成本值为:1.7401807010173798
当前是第 30 代,成本值为:1.664649449288845
当前是第 35 代,成本值为:1.6262611597776413
当前是第 40 代,成本值为:1.6200454533100128
当前是第 45 代,成本值为:1.5801729559898376
当前是第 50 代,成本值为:1.5507072806358337
当前是第 55 代,成本值为:1.4860153570771217
当前是第 60 代,成本值为:1.3735136315226555
当前是第 65 代,成本值为:1.266873374581337
当前是第 70 代,成本值为:1.1810551509261131
当前是第 75 代,成本值为:1.1320813447237015
当前是第 80 代,成本值为:1.0706271640956402
当前是第 85 代,成本值为:1.0660263299942017
当前是第 90 代,成本值为:1.0115427523851395
当前是第 95 代,成本值为:0.985688503831625
当前是第 100 代,成本值为:1.0073445439338684
当前是第 105 代,成本值为:0.9434673264622688
当前是第 110 代,成本值为:0.9779011532664299
当前是第 115 代,成本值为:0.9618405252695084
当前是第 120 代,成本值为:0.9396611452102661
当前是第 125 代,成本值为:0.8901512138545513
当前是第 130 代,成本值为:0.8897779397666454
当前是第 135 代,成本值为:0.8981903865933418
当前是第 140 代,成本值为:0.8504592441022396
当前是第 145 代,成本值为:0.8556553609669209

​​​​​​​

corrent_prediction accuracy= Tensor("Mean_1:0", shape=(), dtype=float32)
训练集准确度:0.71944445
测试集准确度:0.55833334
import matplotlib.pyplot as plt # plt 用于显示图片
import matplotlib.image as mpimg # mpimg 用于读取图片
import numpy as np#预测代码有问题
#这是博主自己拍的图片
my_image1 = "1.png"                                            #定义图片名称
fileName1 = "datasets/fingers/" + my_image1                      #图片地址
image1 = mpimg.imread(fileName1)                               #读取图片
plt.imshow(image1)                                             #显示图片
my_image1 = image1.reshape(1,64,64,3)                  #重构图片
Z3 = forward_propagation(X,parameters)
#my_image_prediction = tf_utils.predict(my_image1, parameters)  #开始预测
#print("预测结果: y = " + str(np.squeeze(my_image_prediction)))
print("Z3=",Z3)
print("parameters=",parameters)W1 = tf.compat.v1.convert_to_tensor(parameters['W1'])
W2 = tf.compat.v1.convert_to_tensor(parameters['W2'])params = {'W1': W1,'W2': W2
}
#x = tf.compat.v1.placeholder(tf.float32, [1, 64, 64, 3], name='x')z3 = forward_propagation(x, params)
sess = tf.Session()#sess.run(tf.initialize_all_variables())
prediction = sess.run(z3, feed_dict={x: my_image1})sess.close()#session = tf.compat.v1.Session()
#prediction = session.run(z3, feed_dict={x: my_image1})#session.close()#predict_op = tf.arg_max(Z3,1)#with tf.Session() as sess_test:#X,Y = create_placeholders(64,64,3,6)#parameters = initialize_parameters()#Z3 = forward_propagation(X,parameters)#predict_op = tf.arg_max(Z3,1#Z3 = forward_propagation(X,parameters)#init = tf.global_variables_initializer()#sess_test.run(init)#a = sess_test.run(Z3,{X: my_image1 , Y: np.random.randn(1,6)})#print("Z3 = " + str(a))#sess_test.close()""

吴恩达深度学习 4.1 卷积神经网络-卷积神经网络基础相关推荐

  1. 花书+吴恩达深度学习(十四)卷积神经网络 CNN 之经典案例(LetNet-5, AlexNet, VGG-16, ResNet, Inception Network)

    目录 0. 前言 1. LeNet-5 2. AlexNet 3. VGG-16 4. ResNet 残差网络 5. Inception Network 如果这篇文章对你有一点小小的帮助,请给个关注, ...

  2. 花书+吴恩达深度学习(十二)卷积神经网络 CNN 之全连接层

    目录 0. 前言 1. 全连接层(fully connected layer) 如果这篇文章对你有一点小小的帮助,请给个关注,点个赞喔~我会非常开心的~ 花书+吴恩达深度学习(十)卷积神经网络 CNN ...

  3. 吴恩达深度学习课程笔记(初步认识神经网络)

    吴恩达深度学习课程笔记1 课程主要内容 1.神经网络与深度学习介绍 2.Improving Deep Neural Networks:超参数调整,正则化,优化方法 3.结构化机器学习工程:比如如何分割 ...

  4. 吴恩达深度学习之二《改善深层神经网络:超参数调试、正则化以及优化》学习笔记

    一.深度学习的实用层面 1.1 训练/开发/测试集 机器学习时代,数据集很小,可能100.1000.10000条,这种级别.可以按 70%.30% 划分训练集和测试集,训练后直接用测试集评估.或者按 ...

  5. 吴恩达深度学习课程-Course 2 改善深层神经网络 第三周 TensorFlow入门编程作业

    虽然申请书的ddl临近,但还是先写写编程作业- 编程作业的代码用的是tf1,而我的环境为tf2,所以 TensorFlow入门 TensorFlow教程 1 - 探索Tensorflow库 1.1 - ...

  6. 吴恩达深度学习笔记3-Course1-Week3【浅层神经网络】

    浅层神经网络: 一.浅层神经网络的表示 本文中的浅层神经网络指的是 two layer nn 即 one input layer + one hidden layer + one output lay ...

  7. 花书+吴恩达深度学习(十三)卷积神经网络 CNN 之运算过程(前向传播、反向传播)

    目录 0. 前言 1. 单层卷积网络 2. 各参数维度 3. CNN 前向传播反向传播 如果这篇文章对你有一点小小的帮助,请给个关注,点个赞喔~我会非常开心的~ 花书+吴恩达深度学习(十)卷积神经网络 ...

  8. 花书+吴恩达深度学习(十一)卷积神经网络 CNN 之池化层

    目录 0. 前言 1. 最大池化(max pooling) 2. 平移不变形 3. 其他池化函数 4. 卷积和池化作为一种无限强的先验 如果这篇文章对你有一点小小的帮助,请给个关注,点个赞喔~我会非常 ...

  9. 花书+吴恩达深度学习(十)卷积神经网络 CNN 之卷积层

    目录 0. 前言 1. 2D 图像卷积 2. 3D 图像卷积 3. 过滤器(核函数) 4. 过滤器应用于边缘检测 5. padding 填充 6. stride 步长 7. 使用卷积的动机 8. 1乘 ...

  10. 吴恩达深度学习课程笔记之卷积神经网络(2nd week)

    0 参考资料 [1]  大大鹏/Bilibili资料 - Gitee.com [2] [中英字幕]吴恩达深度学习课程第四课 - 卷积神经网络_哔哩哔哩_bilibili [3]  深度学习笔记-目录 ...

最新文章

  1. HDU2108(凹多边形还是凸多边形)
  2. 石油污染土壤微生物群落构建与生物多样性研究
  3. [JVM-1]Java运行时数据区域
  4. div+css+theme
  5. 项目开发中关于jquery中出现问题小结(textarea,disabled,关键字等)
  6. Ubuntu的中文是哪种字体?python的词云分析和 三国演义人物出场统计
  7. 前端学习(1752):前端调试值之网络请求的监控
  8. php 获取警告信息,获取PHP警告错误信息的解决方法_PHP教程
  9. 摘抄自知乎的redis相关
  10. 一个服务器多个网站多个域名,多个域名一个服务器吗
  11. 手写一个promise用法_手写一个自己的 JavaScript Promise 类库
  12. 嵌入式 IOT 汽车 航空 AI 领域从IP到片上系统SOC信息检索网站 DR
  13. 【数据结构(C语言)】数据结构-图
  14. 谢谢有你【我与51CTO一“七”成长】
  15. 用python文本挖掘分析_文本挖掘和文本分析的九大应用场景
  16. 游戏开发中常见的10种编程语言
  17. html打开lync客户端,在 Skype for Business 与 Lync 客户端用户界面之间切换
  18. 什麼是SWOT分析?示例和模板
  19. springnbsp;contextnbsp;初始化两次导致dub…
  20. 如何将英文文献转中文?

热门文章

  1. 什么是docker –rm选项
  2. 做什么样的人最开心呢?
  3. 小技巧:absolute 元素的宽度问题
  4. BZOJ 4716 假摔
  5. Shamir 门限秘密共享
  6. 连接数据库报Java::ComMysqlCjJdbcExceptions::CommunicationsException: Communications link failure
  7. 揭秘浏览器远程调试技术
  8. R语言1-面板数据分析全过程 附代码
  9. 爱尔威火星车 AirWheel 电动独轮车
  10. 如何提升对编程的兴趣,在编程中找到快乐?