• Python深度学习笔记01--神经网络的数学基础


    2.1初识神经网络

    使用Python的Keras库,编写手写数字识别(MNIST)的代码如下:

     1 import tensorflow as tf
     2 from keras import models
     3 from keras import layers
     4 
     5 from keras.datasets import mnist
     6 from keras.utils import to_categorical
     7 
     8 #1. 获取数据集
     9 (train_images, train_labels), (test_images, test_labels) = mnist.load_data()
    10 
    11 #2. 处理数据集
    12 train_images = train_images.reshape((60000, 28 * 28))
    13 train_images = train_images.astype('float32') / 255
    14 
    15 test_images = test_images.reshape((10000, 28 * 28))
    16 test_images = test_images.astype('float32') / 255
    17 
    18 train_labels = to_categorical(train_labels)
    19 test_labels = to_categorical(test_labels)
    20 
    21 #3. 建立网络模型
    22 network = models.Sequential()
    23 network.add(layers.Dense(512,activation='relu',input_shape=(28 * 28,)))
    24 network.add(layers.Dense(10,activation='softmax'))
    25 
    26 #4. 设置编译三参数
    27 network.compile(optimizer='rmsprop',
    28 loss='categorical_crossentropy',metrics=['accuracy'])
    29 
    30 #5. 设置训练条件
    31 network.fit(train_images, train_labels, epochs=5, batch_size=128)
    32 
    33 #6. 训练模型并评估模型
    34 test_loss, test_acc = network.evaluate(test_images, test_labels)
    35 print('test_acc', test_acc)

    2.2神经网络的数据表示

    张量(Tensor):numpy的ndarray数据类型中存储的是张量。张量的维度叫做轴,轴从0开始计数。

    标量(0D 张量):仅包含一个数字的张量叫做标量,标量有0个轴。

    1 import numpy as np
    2 
    3 x1 = np.array(1)
    4 print(type(x1)) # <class 'numpy.ndarray'>
    5 print(x1.shape) # ()
    6 print(x1.ndim) # 0

    向量(1D 张量):数字组成的数组叫做向量,向量有1个轴。

    1 import numpy as np
    2 
    3 x2 = np.array([1, 2,3,4,5])
    4 print(x2.shape) # (5,)
    5 print(x2.ndim) # 1

    x2是一个5D向量,但它是一个1D的张量。它只有1个轴,但是这个轴上有5个维度。

    矩阵(2D张量):向量组成的数组叫矩阵,矩阵有2个轴。

    1 import numpy as np
    2 
    3 x3 = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]])
    4 print(x3.shape) # (3, 5)
    5 print(x3.ndim) # 2

    x3是一个3行2列的矩阵。

    3D张量与更高维张量:将多个矩阵组合成一个新的数组,就是3D张量。3D张量有3个轴。

    shape值为:(矩阵个数, 矩阵的行数, 矩阵的列数)

    张量的数据类型(dtype),一般情况下是:float32、uint8、float64,也可能是char类型。但不能是字符串张量。

    注:一般在深度学习中使用的张量,其第一个轴(0轴)都是批量轴,因此张量的维度比数据本身,要多一维。

    2.3 神经网络的“齿轮”:张量运算

    逐元素运算:常见的有逐元素的加法,逐元素的乘法,relu()运算等。

    在numpy底层,逐元素运算使用BLAS实现(一般由C编写的函数库),而不是普通的循环遍历。

    广播:

    (1)向较小的张量添加轴,使其ndim与较大的张量相同。

    (2)将较小的张量沿着新轴重复,使其形状与较大的张量相同。

    张量点积:点积运算也叫张量积。

    两个向量的点积:对应维度的元素相乘,再相加,最终结果是一个标量。

    1 import numpy as np
    2 
    3 x = np.array([1,2,3])
    4 y = np.array([4,5,6])
    5 
    6 z = x.dot(y)
    7 print(z) # 32

    计算方式如下:(1 * 4 ) + (2 * 5) + (3 * 6)= 4 + 10 + 18 = 32

    矩阵与向量的点积,返回一个向量。注意:“矩阵点积向量”的结果与“向量点积矩阵”的结果是不同的。

     1 import numpy as np
     2 
     3 A = np.array([[1,2],[3,4]])
     4 x = np.array([5,6])
     5 
     6 y1 = A.dot(x)
     7 print(y1) # [17 39]
     8 
     9 y2 = x.dot(A)
    10 print(y2) # [23 34]

    A.dot(x)的计算方式:[(1 * 5) + (2 * 6) , (3 * 5) + (4 * 6)] = [17, 39]

    而x.dot(A)的计算方式:[(1 * 5) + (3 * 6),(2 * 5) + (4 * 6)] = [23, 34]

    两个矩阵的点积(矩阵乘法),假设A和B是两个矩阵,A.dot(B)要需要满足条件:A的1轴的维度 = B的0轴的维度,也就是A的列数 = B的行数。

    其结果是一个(A.shape[0], B.shape[1])形状的矩阵(A的行数,B的列数)。

    张量变形:是指改变张量的行和列,以得到想要的形状,变形后的张量的元素总个数与初始张量相同。

    例如shape=(2,3)的格式变为:shape(3,2)的,也可以变成shape(1,6)或shape(6,1)的张量。

    1 import numpy as np
    2 
    3 A = np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
    4 print(A.shape) # (2, 2, 2)
    5 
    6 B = A.reshape((2,4))
    7 print(B) # [[1 2 3 4] [5 6 7 8]]

    张量变形可以改变张量的维度。

    2.4 神经网络的“引擎”:基于梯度的优化

    一个训练循环的步骤如下:

    (1) 抽取训练样本x和对应目标y组成的数据批量。

    (2) 在x上运行网络[这一步叫做前向传播],得到预测值y_pred。

    (3) 计算网络在这批数据上的损失,用于衡量y_pred和y之间的距离。

    (4) 更新网络的所有权重,使网络在这批数据上的损失略微下降。

    什么是导数

    “导数完全描述了改变x后f(x)会如何变化。如果你希望减小f(x)的值,只需将x沿着导数的反方向移动一小步。”这句话的解释:

    反方向就是符号相反的意思。

    见上图,根据数学知识可知,函数y=f(x)在当前点p的斜率为负值。要想使得f(x)的值减小,则需要让p点"向右"移动,也就是增大x的值。

    也就是x需要加上一个正数。而p点的斜率(导数)是负数。这两个数字的符号相反,也就是方向相反。

    张量运算的导数:梯度

    梯度是张量运算的导数。它是导数这一概念向多元函数导数的推广。多元函数是以张量作为输入的函数。

    假设有一个输入向量x、一个矩阵(2D导数)W、一个目标y和一个损失函数loss。你可以用W来计算预测值y_pred,然后计算损失。

    1 y_pred = dot(W, x)
    2 loss_value = loss(y_pred, y)

    这里x和y是样本的属性及其标签,虽然这里用的是x和y,但这两个向量在训练模型时都是已知的数值,而可以其看作是W映射到损失值得函数。

    1 loss_value = f(W)

    这里自变量W不再是一个标量(0D张量),而是一个矩阵(2D张量)。假设这个矩阵W有m行和n列。那么这就是一个m * n元的函数。

    假设W的当前值是W0 它是一个矩阵在W0 的导数是一个与W形状相同的矩阵(2D张量)表示为gradient(f)(W0),

    grandient(f)(W0)的每一个值grandient(f)(W0)[i, j] ,都表示改变W0[i,j]时loss_value变化的方向和大小,也就是偏导数。

    这个gradient(f)(W0)可以看作f(W)在W0附近的曲率的矩阵,这个矩阵就是梯度

    与标量类似,矩阵也是有“方向”的,只是这个方向不能在三维的空间中展示出来。

    可以通过将W向梯度的反方向移动一小步来减小f(W)的值。

    随机梯度下降

    小批量随机梯度下降(MBGD):每次抽取训样本集中的一个小批次的数据进行训练。

    真随机梯度下降(SGD):每次抽取单一的一个样本进行训练。

    批量随机梯度下降(BGD):每次选用全部的样本进行训练。

    优化器时使用损失梯度更新参数的具体方式。

    常见的优化器:带动量SGD、Adagrad、RMSProp等。

    动量解决了SGD两个问题:收敛速度和局部最小点。

    链式求导:反向传播算法

    根据微积分的知识,可以通过“链式法则”对函数链求导:(f(g(x)))' = f'(g(x)) * g'(x)。

    链式法则应用于神经网络梯度值得计算,得到得算法叫反向传播

    Tensorflow等框架可以进行符号微分,给定一个运算链,并且已知每个运算的导数,这些框架就可以利用链式法则来计算这个运算链的梯度函数。

    将网络参数值映射为梯度值。而无需手动实现反向传播算法。

  • 相关阅读:
    [leetcode-604-Design Compressed String Iterator]
    [leetcode-617-Merge Two Binary Trees]
    OpenCV学习1-----打开摄像头并在画面上添加水印
    cvCvtColor与cvtColor区别
    [leetcode-547-Friend Circles]
    [leetcode-260-Single Number III]
    复位电路
    单片机特殊功能寄存器
    单片机的定时器与计数器
    单片机定时/计数工作方式
  • 原文地址:https://www.cnblogs.com/asenyang/p/14304703.html
Copyright © 2020-2023  润新知