深度学习之视频基础(五):神经网络的学习中的重要观点

5.1 参数的更新

**最优化(optimization):**神经网络的学习的目的是找到使损失函数的值尽可能小的参数。这是寻找最优参数的问题,解决这个问题的过程称为最优化(optimization)。
为了找到最优参数,我们将参数的梯度(导数)作为了线索。
**随机梯度下降法(stochastic gradient descent):**使用参数的梯度,沿梯度方向更新参数,并重复这个步骤多次,从而逐渐靠近最优参数,这个过程称为随机梯度下降法(stochastic gradient descent),简称SGD。

5.1.1 举例

在这里插入图片描述
在这里插入图片描述

5.1.2 SGD

用数学式可以将SGD写成如下的式:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
进行初始化时的参数 lr 表示learning rate(学习率)。这个学习率会保存为实例变量。此外,代码段中还定义了 update(params, grads) 方法,这个方法在SGD中会被反复调用。参数 params 和 grads (与之前的神经网络的实现一样)是字典型变量,按 params[‘W1’] 、grads[‘W1’] 的形式,分别保存了权重参数和它们的梯度。
例如:使用这个 SGD 类,可以按如下方式进行神经网络的参数的更新
在这里插入图片描述
这里首次出现的变量名 optimizer 表示“进行最优化的人”的意思,这里由SGD承担这个角色。参数的更新由optimizer 负责完成。我们在这里需要做的只是将参数和梯度的信息传给 optimizer 。

5.1.3 SGD的缺点

如果函数的形状非均向(anisotropic),比如呈延伸状,搜索的路径就会非常低效。因此,我们需要比单纯朝梯度方向前进的SGD更聪明的方法。SGD低效的根本原因是,梯度的方向并没有指向最小值的方向。
在这里插入图片描述

5.1.4 Momentum

Momentum是“动量”的意思,和物理有关。用数学式表示Momentum方法,如下所示:
在这里插入图片描述
在这里插入图片描述
式(6.3)表示了物体在梯度方向上受力,在这个力的作用下,物体的速度增加这一物理法则。如图6-4所示,Momentum方法给人的感觉就像是小球在地面上滚动。
在这里插入图片描述
式(6.3)中有αv这一项。在物体不受任何力时,该项承担使物体逐渐减速的任务(α设定为0.9之类的值),对应物理上的地面摩擦或空气阻力。
下面是Momentum的代码实现:

class Momentum:

    """Momentum SGD"""

    def __init__(self, lr=0.01, momentum=0.9):
        self.lr = lr
        self.momentum = momentum
        self.v = None
        
    def update(self, params, grads):
        if self.v is None:
            self.v = {}
            for key, val in params.items():                                
                self.v[key] = np.zeros_like(val)
                
        for key in params.keys():
            self.v[key] = self.momentum*self.v[key] - self.lr*grads[key] 
            params[key] += self.v[key]

实例变量 v 会保存物体的速度。初始化时, v 中什么都不保存,但当第一次调用 update() 时, v 会以字典型变量的形式保存与参数结构相同的数据。
和SGD时的情形相比,
可以更快地朝x轴方向靠近,减弱“之”字形的变动程度。
在这里插入图片描述

5.1.5 AdaGrad

学习率(数学式中记为η)的值很重要。学习率过小,会导致学习花费过多时间;反过来,学习率过大,则会导致学习发散而不能正确进行。
学习率衰减(learningrate decay)的方法,即随着学习的进行,使学习率逐渐减小。逐渐减小学习率的想法,相当于将“全体”参数的学习率值一起降低。
AdaGrad会为参数的每个元素适当地调整学习率,与此同时进行学习(AdaGrad的Ada来自英文单词Adaptive,即“适当的”的意思)。下面,让我们用数学式表示AdaGrad的更新方法。
在这里插入图片描述
在这里插入图片描述

class AdaGrad:

    """AdaGrad"""

    def __init__(self, lr=0.01):
        self.lr = lr
        self.h = None
        
    def update(self, params, grads):
        if self.h is None:
            self.h = {}
            for key, val in params.items():
                self.h[key] = np.zeros_like(val)
            
        for key in params.keys():
            self.h[key] += grads[key] * grads[key]
            params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7)

这里需要注意的是,最后一行加上了微小值 1e-7 。这是为了防止当self.h[key] 中有0时,将0用作除数的情况。在很多深度学习的框架中,这个微小值也可以设定为参数,但这里我们用的是 1e-7 这个固定值。
在这里插入图片描述

5.1.6 Adam

Momentum参照小球在碗中滚动的物理规则进行移动,AdaGrad为参数的每个元素适当地调整更新步伐。如果将这两个方法融合在一起会怎么样?
am是2015年提出的新方法。它的理论有些复杂,直观地讲,就是融合了Momentum和AdaGrad的方法。通过组合前面两个方法的优点,有望实现参数空间的高效搜索。
在这里插入图片描述

class Adam:

    """Adam (http://arxiv.org/abs/1412.6980v8)"""

    def __init__(self, lr=0.001, beta1=0.9, beta2=0.999):
        self.lr = lr
        self.beta1 = beta1
        self.beta2 = beta2
        self.iter = 0
        self.m = None
        self.v = None
        
    def update(self, params, grads):
        if self.m is None:
            self.m, self.v = {}, {}
            for key, val in params.items():
                self.m[key] = np.zeros_like(val)
                self.v[key] = np.zeros_like(val)
        
        self.iter += 1
        lr_t  = self.lr * np.sqrt(1.0 - self.beta2**self.iter) / (1.0 - self.beta1**self.iter)         
        
        for key in params.keys():
            #self.m[key] = self.beta1*self.m[key] + (1-self.beta1)*grads[key]
            #self.v[key] = self.beta2*self.v[key] + (1-self.beta2)*(grads[key]**2)
            self.m[key] += (1 - self.beta1) * (grads[key] - self.m[key])
            self.v[key] += (1 - self.beta2) * (grads[key]**2 - self.v[key])
            
            params[key] -= lr_t * self.m[key] / (np.sqrt(self.v[key]) + 1e-7)
            
            #unbias_m += (1 - self.beta1) * (grads[key] - self.m[key]) # correct bias
            #unbisa_b += (1 - self.beta2) * (grads[key]*grads[key] - self.v[key]) # correct bias
            #params[key] += self.lr * unbias_m / (np.sqrt(unbisa_b) + 1e-7)

5.1.7 使用哪种更新方法呢

多研究中至今仍在使用SGD。Momentum和AdaGrad也是值得一试的方法。最近,很多研究人员和技术人员都喜欢用Adam。
在这里插入图片描述

5.2 权重的初始值

5.2.1可以将权重初始值设为0吗

从结论来说,将权重初始值设为0不是一个好主意。事实上,将权重初始值设为0的话,将无法正确进行学习。
什么不能将权重初始值设成一样的值呢?这是因为在误差反向传播法中,所有的权重值都会进行相同的更新。比如,在2层神经网络中,假设第1层和第2层的权重为0。这样一来,正向传播时,因为输入层的权重为0,所以第2层的神经元全部会被传递相同的值。第2层的神经元中全部输入相同的值,这意味着反向传播时第2层的权重全部都会进行相同的更新。

5.2.2隐藏层的激活值的分布

观察隐藏层的激活值(将激活函数的输出数据称为“激活值”)的分布,实验:向一个5层神经网络(激活函数使用sigmoid函数)传入随机生成的输入数据,用直方图绘制各层激活值的数据分布。
这里假设神经网络有5层,每层有100个神经元。然后,用高斯分布随机生成1000个数据作为输入数据,并把它们传给5层神经网络。激活函数使用sigmoid函数,各层的激活值的结果保存在 activations 变量中。这个代码段中需要注意的是权重的尺度。虽然这次我们使用的是标准差为1的高斯分布,但实验的目的是通过改变这个尺度(标准差),观察激活值的分布如何变化。现在,我们将保存在 activations 中的各层数据画成直方图。

# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt


def sigmoid(x):
    return 1 / (1 + np.exp(-x))


def ReLU(x):
    return np.maximum(0, x)


def tanh(x):
    return np.tanh(x)
    
input_data = np.random.randn(1000, 100)  # 1000个数据
node_num = 100  # 各隐藏层的节点(神经元)数
hidden_layer_size = 5  # 隐藏层有5层
activations = {}  # 激活值的结果保存在这里

x = input_data

for i in range(hidden_layer_size):
    if i != 0:
        x = activations[i-1]

    # 改变初始值进行实验!
    w = np.random.randn(node_num, node_num) * 1
    # w = np.random.randn(node_num, node_num) * 0.01
    # w = np.random.randn(node_num, node_num) * np.sqrt(1.0 / node_num)
    # w = np.random.randn(node_num, node_num) * np.sqrt(2.0 / node_num)


    a = np.dot(x, w)


    # 将激活函数的种类也改变,来进行实验!
    z = sigmoid(a)
    # z = ReLU(a)
    # z = tanh(a)

    activations[i] = z

# 绘制直方图
for i, a in activations.items():
    plt.subplot(1, len(activations), i+1)
    plt.title(str(i+1) + "-layer")
    if i != 0: plt.yticks([], [])
    # plt.xlim(0.1, 1)
    # plt.ylim(0, 7000)
    plt.hist(a.flatten(), 30, range=(0,1))
plt.show()

在这里插入图片描述
从上图可以看出,各层的激活值呈偏向0和1的分布。这里使用的sigmoid函数是S型函数,随着输出不断地靠近0(或者靠近1),它的导数的值逐渐接近0。因此,偏向0和1的数据分布会造成反向传播中梯度的值不断变小,最后消失。这个问题称为梯度消(gradient vanishing)。层次加深的深度学习中,梯度消失的问题可能会更加严重。
将权重的标准差设为0.01,进行相同的实验。
在这里插入图片描述
这次呈集中在0.5附近的分布。因为不像刚才的例子那样偏向0和1,所以不会发生梯度消失的问题。但是,激活值的分布有所偏向,说明在表现力上会有很大问题。因为如果有多个神经元都输出几乎相同的值,那它们就没有存在的意义了。比如,如果100个神经元都输出几乎相同的值,那么也可以由1个神经元来表达基本相同的事情。因此,激活值在分布上有所偏向会出现“表现力受限”的问题。
各层的激活值的分布都要求有适当的广度。为什么呢?因为通过在各层间传递多样性的数据,神经网络可以进行高效的学习。反过来,如果传递的是有所偏向的数据,就会出现梯度消失或者“表现力受限”的问题,导致学习可能无法顺利进行。
尝试使用Xavier Glorot等人的论文中推荐的权重初始值(俗称“Xavier初始值”)。
Xavier的论文中,为了使各层的激活值呈现出具有相同广度的分布,推导了合适的权重尺度。
推导出的结论是:
在这里插入图片描述
在这里插入图片描述
使用Xavier初始值后,前一层的节点数越多,要设定为目标节点的初始值的权重尺度就越小。
我们使用Xavier初始值进行实验:
在这里插入图片描述
从这个结果可知,越是后面的层,图像变得越歪斜,但是呈现了比之前更有广度的分布。因为各层间传递的数据有适当的广度,所以sigmoid函数的表现力不受限制,有望进行高效的学习。
后面的层的分布呈稍微歪斜的形状。如果用 tanh函数(双曲线函数)代替 sigmoid 函数,这个稍微歪斜的问题就能得到改善。实际上,使用 tanh 函数后,会呈漂亮的吊钟型分布。 tanh函数和 sigmoid 函数同是S型曲线函数,但 tanh 函数是关于原点(0, 0)对称的S型曲线,而 sigmoid 函数是关于(x, y)=(0, 0.5)对称的S型曲线。众所周知,用作激活函数的函数最好具有关于原点对称的性质。

5.2.3 ReLU的权重初始值

Xavier初始值是以激活函数是线性函数为前提而推导出来的。因为sigmoid 函数和 tanh 函数左右对称,且中央附近可以视作线性函数,所以适合使用Xavier初始值.
当激活函数使用ReLU时,一般推荐使用ReLU专用的初始值,也就是Kaiming He等人推荐的初始值,也称为“He初始值”。
在这里插入图片描述
现在来看一下激活函数使用ReLU时激活值的分布。实验的结果如图,依次是权重初始值为标准差是0.01的高斯分布(下文简写为“std = 0.01”)时、初始值为Xavier初始值时、初始值为ReLU专用的“He初始值”时的结果。
在这里插入图片描述
察实验结果可知,当“std = 0.01”时,各层的激活值非常小(各层激活值的分布平均值如下。1层: 0.0396,2层: 0.00290,3层: 0.000197,4层: 1.32e-5,5层: 9.46e-7)。神经网络上传递的是非常小的值,说明逆向传播时权重的梯度也同样很小。这是很严重的问题,实际上学习基本上没有进展。
接下来是初始值为Xavier初始值时的结果。在这种情况下,随着层的加深,偏向一点点变大。实际上,层加深后,激活值的偏向变大,学习时会出现梯度消失的问题。而当初始值为He初始值时,各层中分布的广度相同。由于即便层加深,数据的广度也能保持不变,因此逆向传播时,也会传递合适的值。
**当激活函数使用ReLU时,权重初始值使用He初始值。当激活函数为 sigmoid 或 tanh 等S型曲线函数时,初始值使用Xavier初始值。**这是目前的最佳实践。

5.3 Batch Normalization

如果设定了合适的权重初始值,则各层的激活值分布会有适当的广度,从而可以顺利地进行学习。那么,为了使各层拥有适当的广度,“强制性”地调整激活值的分布会怎样呢?Batch Normalization 方法就是基于这个想法而产生的。

5.3.1 Batch Normalization 的算法

Batch Normalization(下文简称Batch Norm)是2015年提出的方法。
Batch Norm有以下优点:
• 可以使学习快速进行(可以增大学习率)。
• 不那么依赖初始值(对于初始值不用那么神经质)。
• 抑制过拟合(降低Dropout等的必要性)。
Batch Norm的思路是调整各层的激活值分布使其拥有适当的广度。为此,要向神经网络中插入对数据分布进行正规化的层,即BatchNormalization层(下文简称Batch Norm层),如图所示。
在这里插入图片描述
Batch Norm,顾名思义,以进行学习时的mini-batch为单位,按mini-batch进行正规化。具体而言,就是进行使数据分布的均值为0、方差为1的正规化。用数学式表示的话,如下所示。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上面就是Batch Norm的算法。这个算法是神经网络上的正向传播。如果使用计算图,Batch Norm可以表示为
在这里插入图片描述

5.4 正则化

机器学习的问题中,过拟合是一个很常见的问题。过拟合指的是只能拟合训练数据,但不能很好地拟合不包含在训练数据中的其他数据的状态。

5.4.1 过拟合

发生过拟合的原因,主要有以下两个:
• 模型拥有大量参数、表现力强。
• 训练数据少。

MNIST数据集原本的60000个训练数据中只选定300个,并且,为了增加网络的复杂度,使用7层网络(每层有100个神经元,激活函数为ReLU)。

# coding: utf-8
import os
import sys

sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from common.multi_layer_net import MultiLayerNet
from common.optimizer import SGD

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)

# 为了再现过拟合,减少学习数据
x_train = x_train[:300]
t_train = t_train[:300]

# weight decay(权值衰减)的设定 =======================
#weight_decay_lambda = 0 # 不使用权值衰减的情况
weight_decay_lambda = 0.1
# ====================================================

network = MultiLayerNet(input_size=784, hidden_size_list=[100, 100, 100, 100, 100, 100], output_size=10,
                        weight_decay_lambda=weight_decay_lambda)
optimizer = SGD(lr=0.01)

max_epochs = 201
train_size = x_train.shape[0]
batch_size = 100

train_loss_list = []
train_acc_list = []
test_acc_list = []

iter_per_epoch = max(train_size / batch_size, 1)
epoch_cnt = 0

for i in range(1000000000):
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]

    grads = network.gradient(x_batch, t_batch)
    optimizer.update(network.params, grads)

    if i % iter_per_epoch == 0:
        train_acc = network.accuracy(x_train, t_train)
        test_acc = network.accuracy(x_test, t_test)
        train_acc_list.append(train_acc)
        test_acc_list.append(test_acc)

        print("epoch:" + str(epoch_cnt) + ", train acc:" + str(train_acc) + ", test acc:" + str(test_acc))

        epoch_cnt += 1
        if epoch_cnt >= max_epochs:
            break


# 3.绘制图形==========
markers = {'train': 'o', 'test': 's'}
x = np.arange(max_epochs)
plt.plot(x, train_acc_list, marker='o', label='train', markevery=10)
plt.plot(x, test_acc_list, marker='s', label='test', markevery=10)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()

在这里插入图片描述
过了100个epoch左右后,用训练数据测量到的识别精度几乎都为100%。但是,对于测试数据,离100%的识别精度还有较大的差距。如此大的识别精度差距,是只拟合了训练数据的结果。从图中可知,模型对训练时没有使用的一般数据(测试数据)拟合得不是很好。

5.4.2 权值衰减

权值衰减是一直以来经常被使用的一种抑制过拟合的方法。该方法通过在学习的过程中对大的权重进行惩罚,来抑制过拟合。很多过拟合原本就是因为权重参数取值过大才发生的。
在这里插入图片描述
在这里插入图片描述
对于刚刚进行的实验,应用λ = 0.1的权值衰减

# coding: utf-8
import os
import sys

sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from common.multi_layer_net import MultiLayerNet
from common.optimizer import SGD

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)

# 为了再现过拟合,减少学习数据
x_train = x_train[:300]
t_train = t_train[:300]

# weight decay(权值衰减)的设定 =======================
#weight_decay_lambda = 0 # 不使用权值衰减的情况
weight_decay_lambda = 0.1
# ====================================================

network = MultiLayerNet(input_size=784, hidden_size_list=[100, 100, 100, 100, 100, 100], output_size=10,
                        weight_decay_lambda=weight_decay_lambda)
optimizer = SGD(lr=0.01)

max_epochs = 201
train_size = x_train.shape[0]
batch_size = 100

train_loss_list = []
train_acc_list = []
test_acc_list = []

iter_per_epoch = max(train_size / batch_size, 1)
epoch_cnt = 0

for i in range(1000000000):
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]

    grads = network.gradient(x_batch, t_batch)
    optimizer.update(network.params, grads)

    if i % iter_per_epoch == 0:
        train_acc = network.accuracy(x_train, t_train)
        test_acc = network.accuracy(x_test, t_test)
        train_acc_list.append(train_acc)
        test_acc_list.append(test_acc)

        print("epoch:" + str(epoch_cnt) + ", train acc:" + str(train_acc) + ", test acc:" + str(test_acc))

        epoch_cnt += 1
        if epoch_cnt >= max_epochs:
            break


# 3.绘制图形==========
markers = {'train': 'o', 'test': 's'}
x = np.arange(max_epochs)
plt.plot(x, train_acc_list, marker='o', label='train', markevery=10)
plt.plot(x, test_acc_list, marker='s', label='test', markevery=10)
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()

在这里插入图片描述

5.4.3DroPout

果网络的模型变得很复杂,只用权值衰减就难以应对了。在这种情况下,我们经常会使用Dropout方法。

Dropout是一种在学习的过程中随机删除神经元的方法。训练时,随机选出隐藏层的神经元,然后将其删除。被删除的神经元不再进行信号的传递,如图6-22所示。训练时,每传递一次数据,就会随机选择要删除的神经元。然后,测试时,虽然会传递所有的神经元信号,但是对于各个神经元的输出,要乘上训练时的删除比例后再输出。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.5超参数的验证

神经网络中,除了权重和偏置等参数,超参数(hyper-parameter)也经常出现。这里所说的超参数是指,比如各层的神经元数量、batch大小、参数更新时的学习率或权值衰减等。如果这些超参数没有设置合适的值,模型的性能就会很差。

5.5.1 验证数据

对超参数设置各种各样的值以进行验证。不能使用测试数据评估超参数的性能。这一点非常重要,但也容易被忽视。
调整超参数时,必须使用超参数专用的确认数据。用于调整超参数的数据,一般称为验证数据(validation data)。我们使用这个验证数据来评估超参数的好坏。

训练数据用于参数(权重和偏置)的学习,验证数据用于超参数的性能评估。为了确认泛化能力,要在最后使用(比较理想的是只用一次)测试数据。

5.5.2 超参数的最优化

进行超参数的最优化时,逐渐缩小超参数的“好值”的存在范围非常重要。所谓逐渐缩小范围,是指一开始先大致设定一个范围,从这个范围中随机选出一个超参数(采样),用这个采样到的值进行识别精度的评估;然后,多次重复该操作,观察识别精度的结果,根据这个结果缩小超参数的“好值”的范围。通过重复这一操作,就可以逐渐确定超参数的合适范围。
在这里插入图片描述

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from common.multi_layer_net import MultiLayerNet
from common.util import shuffle_dataset
from common.trainer import Trainer

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)

# 为了实现高速化,减少训练数据
x_train = x_train[:500]
t_train = t_train[:500]

# 分割验证数据
validation_rate = 0.20
validation_num = int(x_train.shape[0] * validation_rate)
x_train, t_train = shuffle_dataset(x_train, t_train)
x_val = x_train[:validation_num]
t_val = t_train[:validation_num]
x_train = x_train[validation_num:]
t_train = t_train[validation_num:]


def __train(lr, weight_decay, epocs=50):
    network = MultiLayerNet(input_size=784, hidden_size_list=[100, 100, 100, 100, 100, 100],
                            output_size=10, weight_decay_lambda=weight_decay)
    trainer = Trainer(network, x_train, t_train, x_val, t_val,
                      epochs=epocs, mini_batch_size=100,
                      optimizer='sgd', optimizer_param={'lr': lr}, verbose=False)
    trainer.train()

    return trainer.test_acc_list, trainer.train_acc_list


# 超参数的随机搜索======================================
optimization_trial = 100
results_val = {}
results_train = {}
for _ in range(optimization_trial):
    # 指定搜索的超参数的范围===============
    weight_decay = 10 ** np.random.uniform(-8, -4)
    lr = 10 ** np.random.uniform(-6, -2)
    # ================================================

    val_acc_list, train_acc_list = __train(lr, weight_decay)
    print("val acc:" + str(val_acc_list[-1]) + " | lr:" + str(lr) + ", weight decay:" + str(weight_decay))
    key = "lr:" + str(lr) + ", weight decay:" + str(weight_decay)
    results_val[key] = val_acc_list
    results_train[key] = train_acc_list

# 绘制图形========================================================
print("=========== Hyper-Parameter Optimization Result ===========")
graph_draw_num = 20
col_num = 5
row_num = int(np.ceil(graph_draw_num / col_num))
i = 0

for key, val_acc_list in sorted(results_val.items(), key=lambda x:x[1][-1], reverse=True):
    print("Best-" + str(i+1) + "(val acc:" + str(val_acc_list[-1]) + ") | " + key)

    plt.subplot(row_num, col_num, i+1)
    plt.title("Best-" + str(i+1))
    plt.ylim(0.0, 1.0)
    if i % 5: plt.yticks([])
    plt.xticks([])
    x = np.arange(len(val_acc_list))
    plt.plot(x, val_acc_list)
    plt.plot(x, results_train[key], "--")
    i += 1

    if i >= graph_draw_num:
        break

plt.show()

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《图解深度学习神经网络:从张量到tensorflow实现》是一本介绍深度学习神经网络的图书,主要通过图解和实例展示了相关概念和实现方法。 首先,深度学习是一种机器学习方法,它通过构建多层神经网络来模拟人脑的工作原理,并通过大数据的学习来进行模型的训练和优化。深度学习在图像识别、语音识别、自然语言处理等领域有着广泛的应用。 该书从图解的角度出发,通过生动的插图和可视化的方式,向读者介绍了深度学习的基本概念。例如,它解释了神经元和神经网络的概念,展示了神经网络的结构和工作原理,并深入讲解了前向传播和反向传播的过程。 除了介绍基本概念,该书还通过具体的实例和代码示例,教读者如何使用tensorflow框架来实现深度学习模型。通过该书的学习,读者可以了解如何使用张量(tensor)这一基本数据结构,在tensorflow构建神经网络模型,并通过优化算法进行训练和调优。同时,该书还涵盖了一些常见的深度学习模型,如卷积神经网络(CNN)和循环神经网络(RNN)等的实现方法。 总体而言,《图解深度学习神经网络:从张量到tensorflow实现》是一本适合初学者的入门教材。它通过图示和实例,直观地展示了深度学习神经网络的基本概念和实现方法。读者可以通过学习该书,初步掌握深度学习基础知识,并能够使用tensorflow框架实现简单的深度学习模型。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值