C4_week1

import numpy as np
import h5py
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize']=(5.0,4.0)
plt.rcParams['image.interpolation']='nearest'
plt.rcParams['image.cmap']='gray'
np.random.seed(1)
#用0填充边界
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[1, 1] =", x[1, 1])
print ("x_paded[1, 1] =", X_paded[1, 1])
#绘制图
fig , axarr = plt.subplots(1,2)  #一行两列
axarr[0].set_title('x')
axarr[0].imshow(x[0,:,:,0])
axarr[1].set_title('x_paded')
axarr[1].imshow(X_paded[0,:,:,0])
plt.show()
#实现第一步卷积,使用一个过滤器来卷积输入的数据
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)+b
    Z=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)
Z=conv_single_step(a_slice_prev,W,b)
print("Z="+str(Z))
#卷积神经网络,向前传播
#用for循环来实现
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)+1
    n_W=int((n_W_prev-f+2*pad)/stride)+1
    #使用0来初始化卷积输出Z
    Z=np.zeros((m,n_H,n_W,n_C))
    #通过A_prev创建填充了的A_prev_pad
    A_prev_pad=zero_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):
                    #定位当前的切片位置
                    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])
#池化层
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)+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): #循环遍历输出的通道
                    #定位当前的切片位置
                    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)
#神经网络的应用
#用tensorflow实现神经网络,然后应用到手势识别中
import math
import numpy as np
import h5py
import matplotlib.pyplot as plt
import matplotlib.image as mping
import tensorflow as tf
from tensorflow.python.framework import ops
import cnn_utils
np.random.seed(1)
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))
#初始化参数
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()
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()
#计算成本函数
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()
#加载数据集
X_train_orig,Y_train_orig,X_test_orig,Y_test_orig,classes=cnn_utils.load_dataset()
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 = {}
#构建模型
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 #指定随机种子
    (m,n_H0,n_W0,n_C0)=X_train.shape
    n_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=0
            num_minibatches=int(m/minibatch_size) #获取数据块的数量
            seed=seed+1
            minibatches=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('iteration(per tens)')
                plt.title("learning_rate="+str(learning_rate))
                plt.show()
            #开始预测函数
            ##计算当前的预测情况
            predict_op=tf.math.argmax(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_accuracy=accuracy.eval({X:X_test,Y:Y_test})
            print("训练集准确度:"+str(train_accuracy))
            print("训练集准确度:"+str(test_accuracy))
            return (train_accuracy,test_accuracy,parameters)
#启动模型
_,_,parameters=model(X_train,Y_train,X_test,Y_test,num_epochs=150)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值