DNN(Deep Neural Nework):深层神经网络Python实践

DNN(Deep Neural Nework):深层神经网络Python实践

完整代码:可参见我的github项目:https://github.com/RaySunWHUT/NeuralNetwork/blob/master/NerualNetwork/neural_network/week4/L_NN.py
欢迎star、fork。

此处,将结合吴恩达老师在Coursera上的Deep Learning and Neural Nework课程以及MIT的IntroduceToDeeplearning的课程讲义,讲述基本DNN的实现过程。(拖了这么久,没时间,可奈何~ ~😜)

好,废话不多说,Let’s go:
在这篇Blog中,我们将利用Python Numpy设计实现一个针对图片分类(Image Classification)问题的深层神经网络(Deep Neural Network);

DNN实现的主要步骤如下:

  1. 加载数据集

  2. 预处理数据

  3. 随机初始化

  4. 前向传播

  5. 计算代价损失(loss + optimizer)

  6. 反向传播

  7. 预测

以下将从这7个部分分别阐述:

  1. 加载数据集

    catvnoncat.h5是一个包含各个种类的和其他事务的数据集。
    明确任务,搭建的图片分类神经网络是要正确的将与其他图片分类出来。
    首先查看数据维度,并对数据进行可视化。
    在这里插入图片描述
    数据维度
    在这里插入图片描述
    可视化数据:

Cat

Other

加载数据(load_dataset):


# 加载数据集
def load_dataset():

    train_dataset = h5py.File('../../datasets/train_catvnoncat.h5', "r")

    # print(train_dataset.keys())

    # 可以通过train_dataset.keys()查看键值的集合;
    # [:]: 表示除当前维度以外的所有
    train_set_x_orig = np.array(train_dataset["train_set_x"][:])

    # print("train_set元素个数: " + str(len(train_set_x_orig)))
    # print("train_set图片尺寸: " + str(train_set_x_orig[89].shape))

    # 训练集标签
    train_set_y_orig = np.array(train_dataset["train_set_y"][:])

    test_dataset = h5py.File('../../datasets/test_catvnoncat.h5', "r")

    # 测试集特征
    test_set_x_orig = np.array(test_dataset["test_set_x"][:])

    # print("test_set元素个数: " + str(len(test_set_x_orig)))
    # print("test_set图片尺寸: " + str(test_set_x_orig[2].shape))

    # 测试集标签
    test_set_y_orig = np.array(test_dataset["test_set_y"][:])

    # 类别
    classes = np.array(test_dataset["list_classes"][:])

    # 完善数据维度:由(209, ) ---> (1, 209)
    train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0]))
    test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0]))

    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes
  1. 预处理数据

    对数据进行扁平化处理(Image2Vector)、标准化(Standardization)处理。
# 预处理数据函数
def pre_process_data():

    # 加载数据
    train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()

    # 数据扁平化
    train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1).T

    # test_set_x_flatten = test_set_x_orig.reshape(shapes[0], shapes[1] * shapes[2] * shapes[3]).T
    # 与下面的形式等价, 但更贴近于理解, 即:examples_num * Vector; 转置后: 易于输入神经网络中
    test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1).T

    # 标准化
    train_set_x = train_set_x_flatten / 255.0
    test_set_x = test_set_x_flatten / 255.0

    return train_set_x, train_set_y, test_set_x, test_set_y

设计神经网络架构:

神经网络结构大致如下:X → \rightarrow [Linear → \rightarrow ReLU] * (L - 1) → \rightarrow Linear → \rightarrow Sigmoid
此处,设置layers_dims = [12288, 20, 7, 5, 1];
在这里插入图片描述

3. 随机初始化

# 随机初始化
def initialize_parameters_deep(layer_dims):
    """
    layer_dims -- 网络维度
    """
    # seed值固定, 则生成的随机数固定
    np.random.seed(1)

    parameters = {}

    # 网络层数
    layers = len(layer_dims)

    for l in range(1, layers):
        parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l - 1]) / np.sqrt(layer_dims[l - 1])

        # 初始化为0的原因: 方便算法自我调节截距的移动方向
        parameters['b' + str(l)] = np.zeros((layer_dims[l], 1))

    return parameters

4. 前向传播

下图为感知机(Perceptron)的原理:
在这里插入图片描述
此处,需要说下 偏置单元(bias units) 的作用 / 实质:其实质是函数关于y轴的截距,若没有偏置单元,则函数将会始终经过原点(0, 0),将无法很好的拟合数据。
bias 在通常初始化为0,因为初始状态处于 原点(0, 0)bias可以更容易的结合数据,进行调节(上移/下移)。
在这里插入图片描述

以下为神经网络 前向传播(forward propagation) 的基本计算方法。
在这里插入图片描述
在这里插入图片描述
下图为,DNN的基础架构:
在这里插入图片描述
前向传播(forward propagation) 核心逻辑代码:

def L_model_forward(x, parameters):
    """
    forward propagation for the [LINEAR -> RELU] * (layers - 1) -> LINEAR -> SIGMOID computation

    X -- data (input size, number of examples)
    parameters -- output of initialize_parameters_deep()

    AL -- last post-activation value
    caches -- : every cache of linear_relu_forward() (there are layers - 1 of them, indexed from 0 to layers - 2)
                the cache of linear_sigmoid_forward() (there is one, indexed layers - 1)
    """

    caches = []
    a = x

    # 网络层数: 由于有b和w, 所以, // 2
    layers = len(parameters) // 2

    # [LINEAR -> RELU] * (layers - 1)
    for l in range(1, layers):
        a_prev = a
        a, cache = linear_activation_forward(a_prev, parameters['W' + str(l)], parameters['b' + str(l)],
                                             activation="relu")
        caches.append(cache)

    # LINEAR -> SIGMOID
    AL, cache = linear_activation_forward(a, parameters['W' + str(layers)], parameters['b' + str(layers)],
                                          activation="sigmoid")
    caches.append(cache)

    return AL, caches

5. 计算代价损失(梯度)

首先,需要明确代价损失函数(loss function)优化算法(optimization algorithm) 的概念。

代价损失函数(loss function): 代价损失函数是指用于计算标签值y和预测值 y ^ \hat{y} y^ 之间差异的函数。

例,下图为二元交叉熵损失函数(binary cross entropy loss); 目前,有很多种代价损失函数,具体使用哪种,需要结合具体问题数据集的特点来决定。
在这里插入图片描述
优化算法(Optimization Algorithm):确定了代价损失函数后,接下来的工作就是求最优化的参数W,让代价损失函数达到最优值。即,
在这里插入图片描述

下图为代价损失函数(loss function)的二维空间图像:
在这里插入图片描述

可以采用诸如梯度下降(Gradient Descent)等优化算法寻找可以收敛到的loss最低点。
在这里插入图片描述

常见的 优化算法(Optimization Algorithm) 有很多,如:
在这里插入图片描述

下图为 梯度下降(Gradient Descent) 的一般执行过程:
在这里插入图片描述

def compute_cost(AL, y):
    # 标签y数量
    m = y.shape[1]

    # 计算AL, y
    cost = (1.0 / m) * (-np.dot(y, np.log(AL).T) - np.dot(1 - y, np.log(1 - AL).T))

    # 将矩阵转化为数字
    # (e.g. turns [[17]] into 17)
    cost = np.squeeze(cost)

    return cost

6. 反向传播

反向传播,即是应用链式法则(chain rule) 计算梯度(Gradient)
在这里插入图片描述
下图为SGD算法的执行过程,step4进行反向传播,计算梯度。
在这里插入图片描述

反向传播核心逻辑:

def L_model_backward(AL, y, caches):

    grads = {}

    # 网络层数: 由于有b和w, 所以, // 2
    layers = len(caches)

    # 重塑y
    y = y.reshape(AL.shape)

    # 初始化反向传播
    # 对应位置元素相除
    dAL = - (np.divide(y, AL) - np.divide(1 - y, 1 - AL))

    # Lth layer (SIGMOID -> LINEAR) gradients
    # "AL, Y, caches"
    current_cache = caches[layers - 1]

    # "grads["dAL"], grads["dWL"], grads["dbL"]
    grads["dA" + str(layers - 1)], grads["dW" + str(layers)], \
    grads["db" + str(layers)] = linear_activation_backward(dAL, current_cache, activation="sigmoid")

    for l in reversed(range(layers - 1)):
        # lth layer: (RELU -> LINEAR) gradients

        current_cache = caches[l]

        dA_prev_temp, dW_temp, db_temp = linear_activation_backward(grads["dA" + str(l + 1)], current_cache,
                                                                    activation="relu")
        grads["dA" + str(l)] = dA_prev_temp
        grads["dW" + str(l + 1)] = dW_temp
        grads["db" + str(l + 1)] = db_temp

    return grads

更新参数

def update_parameters(parameters, grads, learning_rate):
    # 网络层数: 由于有b和w, 所以, // 2
    layers = len(parameters) // 2

    # 更新参数w, b
    for l in range(layers):
        parameters["W" + str(l + 1)] = parameters["W" + str(l + 1)] - learning_rate * grads["dW" + str(l + 1)]

        parameters["b" + str(l + 1)] = parameters["b" + str(l + 1)] - learning_rate * grads["db" + str(l + 1)]

    return parameters

集成网络结构

# L_layer_model
def L_layer_model(X, Y, layers_dims, learning_rate=0.0075, num_iterations=3000, print_cost=False):  # lr was 0.009

    np.random.seed(1)
    costs = []  # keep track of cost

    # 随机初始化
    parameters = initialize_parameters_deep(layers_dims)

    # 梯度下降
    for i in range(0, num_iterations):

        # 前向传播: [LINEAR -> RELU] * (L - 1) -> LINEAR -> SIGMOID
        AL, caches = L_model_forward(X, parameters)

        # 计算代价
        cost = compute_cost(AL, Y)

        # 反向传播
        grads = L_model_backward(AL, Y, caches)

        # 更新参数
        parameters = update_parameters(parameters, grads, learning_rate)

        # print
        if print_cost and i % 100 == 0:
            print("Cost after iteration %i: %f" % (i, cost))

        if print_cost and i % 100 == 0:
            costs.append(cost)

    # 绘制学习曲线
    plot.plot(np.squeeze(costs))
    plot.ylabel('cost')
    plot.xlabel('iterations (per hundreds)')
    plot.title("Learning rate =" + str(learning_rate))

    plot.show()

    return parameters

7. 预测

def predict(x, y, parameters):

    # X的数量
    m = x.shape[1]

    # 数据集X的对应的prediction的维度
    p = np.zeros((1, m))

    # 前向传播
    probas, caches = L_model_forward(x, parameters)

    # 将0 ~ 1 -- 映射 --> 0, 1
    for i in range(0, probas.shape[1]):
        if probas[0, i] > 0.5:
            p[0, i] = 1
        else:
            p[0, i] = 0

    print("Accuracy: " + str(np.sum((p == y) / m)))

Appendix

DNN的训练技巧(Training skills)

  1. 设置min-batches。
  2. 应对 过拟合(overfitting) 问题: 采用 正则化(regularization) 技术。
    1. Dropout:在训练过程中,将一半的激活函数随机设置为0,使神经网络不依赖于任何一个单独的结点(Node)。
      在这里插入图片描述

    2. Early Stopping: 在模型对数据产生过拟合之前停止训练。
      在这里插入图片描述

References:

  1. https://www.coursera.org/learn/neural-networks-deep-learning
  2. https://www.cnblogs.com/henuliulei/p/11273264.html
  3. http://introtodeeplearning.com
  • 7
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深度神经网络DNN)是一种基于神经网络的机器学习算法,用于处理输入和输出之间复杂的非线性关系。它通过多个隐藏层来构建网络结构,每个隐藏层都包含多个神经元,通过学习权重和偏置参数来实现从输入到输出的映射。 在Python中,我们可以使用各种深度学习框架来实现DNN,例如TensorFlow、PyTorch和Keras等。这些框架提供了高级的API和丰富的工具,使得构建和训练DNN变得更加简单和高效。 在Python中实现DNN的步骤包括数据准备、网络构建、训练和评估等。 首先,我们需要准备用于训练和测试的数据集。通常,我们会将数据集划分为训练集和测试集,其中训练集用于训练网络参数,测试集用于评估网络性能。 接下来,我们可以使用Python中的深度学习框架构建DNN网络结构。通过选择合适的层数、神经元数量和激活函数等参数,可以设计出适合特定问题的网络结构。 然后,我们可以使用训练集对网络进行训练。在训练过程中,DNN通过反向传播算法来更新权重和偏置参数,不断优化网络的性能。可以根据需要调整学习率、批处理大小和迭代次数等参数来控制训练过程。 最后,我们可以使用测试集来评估已训练好的DNN网络的性能。通过计算准确度、精确度、召回率和F1值等指标,可以评估网络在分类、回归或其他任务上的表现。 总之,DNN深度神经网络是一种强大的机器学习算法,通过Python中的深度学习框架实现它可以帮助我们解决各种复杂的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值