乐趣区

关于人工智能:深度学习RNN

[TOC]

I. 前言

介绍 RNN 的概念和利用

RNN(Recurrent Neural Network,循环神经网络)是一类可能解决序列数据的神经网络,它在解决时思考了之前的状态,因而可能对序列数据中的每个元素进行建模和预测。
RNN 的利用十分宽泛,特地是在自然语言解决和工夫序列剖析方面。以下是 RNN 在各个领域的利用:
自然语言解决(NLP)
文本分类:将文本归类到不同的类别中,如情感剖析、垃圾邮件过滤、新闻分类等。
机器翻译:将一种语言的文本翻译成另一种语言的文本。
语音辨认:将人类语音转化为文本。
文本生成:依据给定的文本生成新的文本,如对话生成、诗歌生成等。
问答零碎:答复用户的自然语言问题。
工夫序列剖析
时序预测:依据过来的数据预测将来的数据,如股票价格预测、气温预测等。
行为辨认:依据传感器数据辨认人的行为,如健身追踪、手势辨认等。
异样检测:辨认与失常行为不同的行为或异样行为,如网络入侵检测、设施故障检测等。
除此之外,RNN 还能够用于图像和视频解决等畛域。

II. RNN 根底

RNN 的概念和构造

RNN(Recurrent Neural Network,循环神经网络)是一种能够对序列数据进行建模的神经网络。相比于传统神经网络,RNN 减少了循环连贯,使得网络能够解决序列数据中的时序信息。

RNN 的构造蕴含了一个循环单元,能够看做是对于前一时刻的状态 $h_{t-1}$ 和以后时刻的输出 $x_t$ 的函数,即 $h_t=f(h_{t-1},x_t)$,其中 $f$ 为非线性的激活函数。通过这种形式,RNN 能够在解决以后输出的同时,记忆之前输出的信息,行将上一时刻的状态作为以后时刻的输出。

下图是一个简略的 RNN 构造示意图,其中 $x_t$ 为输出,$h_t$ 为以后时刻的状态,$y_t$ 为输入:

在每个工夫步中,输出 $x_t$ 会与上一时刻的状态 $h_{t-1}$ 通过一个带有权重矩阵 $U$ 和 $W$ 的线性变换,而后通过激活函数 $f$ 失去以后时刻的状态 $h_t$。接下来,$h_t$ 会作为下一时刻的输出状态 $h_{t+1}$,并与下一时刻的输出 $x_{t+1}$ 通过雷同的变换和激活函数,直到所有时刻的输出都解决实现。

最终,咱们能够通过将所有时刻的状态 $h_1,h_2,…,h_T$ 通过一个带有权重矩阵 $V$ 的线性变换,再通过激活函数失去每个时刻的输入 $y_1,y_2,…,y_T$。输入的具体模式取决于具体的工作,如分类工作通常应用 Softmax 激活函数,而回归工作则应用线性激活函数。

RNN 的前向流传和反向流传算法

RNN 的前向流传和反向流传算法是神经网络训练的外围。在前向流传算法中,咱们将输出序列逐渐输出到网络中,并计算每个时刻的输入;在反向流传算法中,咱们通过比拟网络输入和实在标签之间的误差,计算每个参数对误差的奉献,并应用梯度降落算法来更新参数。

前向流传算法

假如咱们的输出序列为 $x_{1:T}={x_1,x_2,…,x_T}$,其中 $x_t$ 示意第 $t$ 个时刻的输出向量。咱们应用 $h_t$ 示意第 $t$ 个时刻的暗藏状态向量,$y_t$ 示意第 $t$ 个时刻的输入向量。

在前向流传算法中,咱们首先将第一个时刻的输出向量 $x_1$ 与初始状态 $h_0$ 输出到网络中,通过一个线性变换和激活函数计算出第一个时刻的暗藏状态 $h_1$,而后再将 $h_1$ 和第二个时刻的输出向量 $x_2$ 输出到网络中,顺次计算出第二个时刻到第 $T$ 个时刻的暗藏状态 $h_2,h_3,…,h_T$ 和输入向量 $y_1,y_2,…,y_T$。具体的计算形式如下:

$h_t = f(U_{xt} + Wh_{t-1}+b_h)$

$y_t=g(Vh_t + b_y)$

其中,$U$、$W$、$V$ 别离为输出、暗藏状态和输入的权重矩阵,$b_h$ 和 $b_y$ 别离为暗藏状态和输入的偏置向量,$f$ 和 $g$ 别离为暗藏状态和输入的激活函数。

反向流传

首先,咱们须要依据以后时刻的输入向量 $y_t$ 和实在标签 $y_t^\prime$ 计算输入向量的梯度 $\frac{\partial L}{\partial y_t}$,其中 $L$ 示意损失函数。具体来说,如果咱们应用平方损失函数,那么输入向量的梯度能够示意为:

$$\frac{\partial L}{\partial y_t} = 2(y_t – y_t^\prime)$$

接下来,咱们须要利用反向流传算法顺次计算每个时刻的暗藏状态向量 $h_t$ 和输出向量 $x_t$ 的梯度 $\frac{\partial L}{\partial h_t}$、$\frac{\partial L}{\partial x_t}$。具体来说,对于某个时刻 $t$,咱们能够通过上面的公式计算暗藏状态向量 $h_t$ 的梯度:

$$\frac{\partial L}{\partial h_t} = \frac{\partial L}{\partial y_t} \cdot W_{hy}^T + \frac{\partial L}{\partial h_{t+1}} \cdot W_{hh}^T$$

其中 $W_{hy}$ 和 $W_{hh}$ 别离示意输入层到暗藏层和暗藏层到暗藏层的权重矩阵。须要留神的是,在最初一个时刻 $T$,咱们须要将 $\frac{\partial L}{\partial h_{T+1}}$ 设置为零向量。

接着,咱们能够利用暗藏状态向量的梯度 $\frac{\partial L}{\partial h_t}$ 计算输出向量 $x_t$ 的梯度 $\frac{\partial L}{\partial x_t}$。具体来说,对于某个时刻 $t$,咱们能够通过上面的公式计算输出向量 $x_t$ 的梯度:

$$\frac{\partial L}{\partial x_t} = \frac{\partial L}{\partial h_t} \cdot W_{xh}^T$$

其中 $W_{xh}$ 示意输出层到暗藏层的权重矩阵。

最初,咱们能够利用输入向量的梯度 $\frac{\partial L}{\partial y_t}$、暗藏状态向量的梯度 $\frac{\partial L}{\partial h_t}$ 和输出向量的梯度 $\frac{\partial L}{\partial x_t}$ 对模型参数进行更新。具体来说,咱们能够采纳梯度降落算法或者其余优化算法来更新权重矩阵和偏置向量,以便更好地训练模型。

须要留神的是,在理论利用中,咱们可能须要对学习率进行动静调整,以便更好地训练模型。此外,在实现反向流传算法时,咱们通常须要采纳递归或者循环的形式进行计算,以便无效地利用历史信息。

RNN 的变种:LSTM 和 GRU

除了规范的 RNN,还有两种常见的变种 RNN,别离是长短期记忆网络(LSTM)和门控循环单元(GRU)。这两种变种网络都是在规范 RNN 的根底上进行改良,旨在解决规范 RNN 中呈现的梯度隐没或爆炸问题,并可能更好地捕获序列中的长期依赖关系。

LSTM

长短期记忆网络(LSTM)是由 Hochreiter 和 Schmidhuber 在 1997 年提出的。LSTM 的次要改良在于引入了三个门机制:输出门、忘记门和输入门。LSTM 的核心思想是通过这三个门管制信息的流动,从而更好地保护序列中的长期依赖关系。

具体来说,输出门管制新信息的输出,忘记门管制之前的信息是否须要被忘记,输入门管制输入的信息。这三个门的计算形式都蕴含了一个 sigmoid 函数,用于将输出映射到 0 - 1 之间的范畴。LSTM 的构造如下图所示:

其中,圆圈示意神经元,箭头示意信息的传递。绿色方框示意输出门,红色方框示意忘记门,黄色方框示意输入门。

LSTM 的前向流传和反向流传算法与规范 RNN 相似,只是在计算中要加上门机制的计算。

GRU

门控循环单元(GRU)是由 Cho 等人在 2014 年提出的。相比于 LSTM,GRU 更为简略,只蕴含了两个门机制:重置门和更新门。GRU 的计算复杂度较低,训练速度也更快,而且在某些工作中性能体现与 LSTM 相当甚至更好。

GRU 的构造如下图所示:

其中,绿色方框示意重置门,蓝色方框示意更新门。GRU 的前向流传和反向流传算法也与规范 RNN 相似,只是在计算中要加上门机制的计算。

总的来说,LSTM 和 GRU 都是为了解决规范 RNN 中的梯度隐没或爆炸问题,并可能更好地捕获序列中的长期依赖关系而提出的。两者的计算复杂度都比规范 RNN 高,但在某些

III. RNN 的利用

自然语言解决中的 RNN 利用:文本分类、情感剖析、机器翻译等

  1. 文本分类

文本分类是将文本分为不同类别的工作,例如将新闻文章分为体育、政治、娱乐等类别。RNN 能够通过学习文本的序列信息,对文本进行分类。具体地,能够将文本的每个单词或字符顺次输出到 RNN 中,最初通过全连贯层进行分类。

  1. 情感剖析

情感剖析是对文本进行情感判断的工作,例如判断一篇文章是侧面的、负面的还是中性的。RNN 能够通过学习文本的上下文信息,对文本中的情感进行剖析。具体地,能够将文本的每个单词或字符顺次输出到 RNN 中,最初通过全连贯层输入情感分类后果。

  1. 机器翻译

机器翻译是将一种语言的文本主动翻译成另一种语言的工作。RNN 在机器翻译中的利用次要是 seq2seq 模型,它将源语言文本编码成一个向量,而后将该向量作为目标语言文本的初始状态,并逐渐生成目标语言的词语序列。具体地,seq2seq 模型蕴含编码器和解码器两个局部,其中编码器是一个 RNN,用于编码源语言文本,而解码器也是一个 RNN,用于生成目标语言的词语序列。

工夫序列剖析中的 RNN 利用:时序预测、异样检测、行为辨认等

  1. 时序预测

时序预测是依据历史数据预测将来数据的工作。RNN 能够通过学习历史时序数据的序列信息,对将来时序数据进行预测。具体地,能够将历史时序数据作为输出序列,将将来时序数据作为输入序列,通过训练 RNN 模型,使得模型可能对将来时序数据进行预测。

  1. 异样检测

异样检测是辨认工夫序列中不同于失常模式的数据点的工作。RNN 能够通过学习工夫序列数据的模式,对异样点进行辨认。具体地,能够将工夫序列数据输出到 RNN 中,通过训练模型,使得模型可能对失常模式进行建模,从而辨认不同于失常模式的数据点。

  1. 行为辨认

行为辨认是辨认工夫序列数据中的行为或动作的工作。RNN 能够通过学习工夫序列数据的序列信息,对不同的行为或动作进行辨认。具体地,能够将工夫序列数据作为输出序列,通过训练 RNN 模型,使得模型可能对不同的行为或动作进行分类。

IV. RNN 的进阶利用

注意力机制和 Seq2Seq 模型

注意力机制和 Seq2Seq 模型是 RNN 在自然语言解决中利用的两个重要畛域。

  1. 注意力机制

在解决长序列输出时,传统的 RNN 模型往往会呈现梯度隐没或梯度爆炸的问题,导致模型难以学习到长期依赖关系。为了解决这个问题,注意力机制被引入到 RNN 中。注意力机制能够让模型在解决长序列输出时,将注意力集中在与当前任务相干的局部,从而进步模型的性能。

具体地,注意力机制通过对输出序列中不同地位的信息进行加权,来构建一个加权和向量,使得模型可能关注与当前任务相干的信息。在 RNN 中,通常应用双向 RNN 或者门控 RNN 构造与注意力机制相结合,从而可能更好地解决长序列输出。

  1. Seq2Seq 模型

Seq2Seq 模型是一种用于序列到序列转换工作的模型,如机器翻译、对话零碎等。它由两个 RNN 模型组成,别离是编码器和解码器。编码器将源语言的序列输出,输入一个固定维度的向量作为上下文信息,解码器依据上下文信息以及目标语言的上一个单词,逐渐生成目标语言的序列。

在 Seq2Seq 模型中,编码器和解码器通常采纳门控 RNN 构造,如 LSTM 和 GRU。同时,注意力机制也被广泛应用于 Seq2Seq 模型中,用于进步模型的性能。通过注意力机制,模型可能在解码过程中动静地将注意力集中在输出序列的不同局部,从而可能更好地解决长序列输出。

多层 RNN 和双向 RNN

  1. 多层 RNN

多层 RNN 由多个 RNN 层重叠而成,每个 RNN 层的输入都作为下一层 RNN 的输出。多层 RNN 能够减少模型的复杂度,进步模型的表达能力。在解决简单的工作时,多层 RNN 往往可能比单层 RNN 获得更好的性能。

在多层 RNN 中,能够应用不同的 RNN 变种,如 LSTM 和 GRU 等。同时,为了避免梯度隐没或梯度爆炸的问题,能够采纳梯度裁剪等办法来调整梯度大小。

  1. 双向 RNN

双向 RNN 是由两个 RNN 组成的模型,别离是前向 RNN 和后向 RNN。前向 RNN 从输出序列的第一个元素开始,逐渐向后处理;后向 RNN 则从输出序列的最初一个元素开始,逐渐向前解决。最初,前向 RNN 和后向 RNN 的输入会被合并起来,造成最终的输入。

双向 RNN 可能更好地捕获输出序列中的上下文信息,从而进步模型的性能。在自然语言解决中,双向 RNN 常常被用于词性标注、命名实体辨认等工作。

RNN 和 CNN 的联合

RNN 和 CNN 是两种常见的神经网络模型,别离在自然语言解决和图像处理等畛域中失去广泛应用。为了更好地利用它们各自的劣势,钻研人员开始摸索将它们联合起来的办法。

一种常见的 RNN 和 CNN 联合的办法是应用卷积神经网络 (Convolutional Neural Network, CNN) 提取文本或图像的部分特色,再应用循环神经网络 (Recurrent Neural Network, RNN) 对这些特色进行全局建模。

具体来说,在文本处理中,能够先应用 CNN 提取出文本中的 n -gram 特色,并将这些特色转换成定长的向量示意。而后,将这些向量输出到 RNN 中,让 RNN 学习文本中的长期依赖关系。

在图像处理中,能够应用 CNN 提取图像的部分特色,失去一系列的卷积特色图。而后,将这些特色图输出到 RNN 中,让 RNN 学习图像中的长期依赖关系。

RNN 和 CNN 的联合可能更好地解决序列数据和部分特色,从而进步模型的性能。在理论利用中,须要依据具体的工作和数据状况抉择适合的模型构造和参数设置。

V. RNN 的调参和优化

学习率、正则化和抛弃等技术

  1. 学习率(Learning Rate)

学习率是指在每次迭代中更新模型参数时所采纳的步长大小。过大的学习率可能导致模型参数在迭代过程中来回摆动,收敛速度慢或不收敛;过小的学习率则可能导致模型收敛速度过慢。通常须要对学习率进行适当的调整,能够应用学习率衰减等技术。

  1. 正则化(Regularization)

正则化是指在损失函数中退出一些惩办项,以防止过拟合。常见的正则化办法包含 L1 正则化、L2 正则化和 dropout 等。

L1 正则化通过在损失函数中增加权重系数的绝对值之和来惩办过大的权重,能够促使模型学习到更稠密的特色。

L2 正则化通过在损失函数中增加权重系数的平方和来惩办过大的权重,能够促使模型学习到较小的权重,从而防止过拟合。

dropout 是一种在网络层之间随机抛弃一些节点的技术,能够使得模型在训练过程中不依赖于特定的节点,从而进步模型的鲁棒性。

  1. 抛弃(Dropout)

抛弃是一种在神经网络中随机抛弃一些神经元的技术,能够加重过拟合的问题。在训练过程中,每个神经元都有肯定的概率被抛弃,这样能够强制模型学习到更加鲁棒的特色,从而进步模型的泛化能力。

梯度隐没和梯度爆炸问题

在训练深度神经网络(DNN)时,梯度隐没和梯度爆炸问题是常见的挑战之一。这些问题同样存在于 RNN 中,因为 RNN 的网络结构导致了梯度在反向流传时会重复相乘。这可能导致在网络深度减少时,梯度变得十分小(梯度隐没)或十分大(梯度爆炸),从而使网络难以训练。

梯度隐没问题通常是因为在反向流传中重复相乘的梯度很小,导致在晚期层的参数更新简直不起作用。为了解决这个问题,能够应用不同的激活函数(例如 ReLU、LeakyReLU、ELU 等)来代替传统的 sigmoid 函数,因为这些函数在输出的某些范畴内有更大的梯度。此外,能够应用 LSTM 或 GRU 等具备更少参数的 RNN 变体,以防止在长时间序列上的梯度隐没问题。

梯度爆炸问题通常是因为在反向流传中梯度重复相乘的后果变得十分大,导致权重更新十分大,网络无奈收敛。为了解决这个问题,能够应用梯度截断技术,通过设置阈值来限度梯度的最大值。

此外,正则化和 dropout 等技术也能够用于防止过拟合和缩小梯度隐没问题的影响。

RNN 的优化算法:Adam、Adagrad、RMSprop 等

  1. AdaGrad 算法是梯度降落法的改良算法,其长处是能够自适应学习率。该优化算法在较为平缓处学习速率大,有比拟高的学习效率,在平缓处学习率小,在肯定水平上能够防止越过极小值点。
  2. AdaGrad 算法尽管解决了学习率无奈依据以后梯度主动调整的问题,然而过于依赖之前的梯度,在梯度忽然变动无奈疾速响应。RMSProp 算法为了解决这一问题,在 AdaGrad 的根底上增加了衰减速率参数。也就是说在以后梯度与之前梯度之间增加了权重,如果以后梯度的权重较大,那么响应速度也就更快
  3. Adam 优化算法是在 RMSProp 的根底上减少了动量。有时候通过 RMSProp 优化算法失去的值不是最优解,有可能是部分最优解,引入动量的概念时,求最小值就像一个球从高处落下,落到部分最低点时会持续向前摸索,有可能失去更小的值

VI. 实际:用 Python 实现 RNN

应用 PyTorch 实现一个简略的 RNN 模型

  1. 导入 PyTorch 和其余必要的库
import torch
import torch.nn as nn
import numpy as np
  1. 定义 RNN 模型
class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(RNN, self).__init__()

        self.hidden_size = hidden_size
        self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
        self.i2o = nn.Linear(input_size + hidden_size, output_size)
        self.softmax = nn.LogSoftmax(dim=1)

    def forward(self, input, hidden):
        combined = torch.cat((input, hidden), 1)
        hidden = self.i2h(combined)
        output = self.i2o(combined)
        output = self.softmax(output)
        return output, hidden

    def initHidden(self):
        return torch.zeros(1, self.hidden_size)

下面的代码定义了一个简略的 RNN 模型,该模型承受一个输出向量和一个暗藏状态向量,并输入一个预测向量和一个更新后的暗藏状态向量。

在 init 函数中,咱们定义了输出到暗藏层和输出到输入层的线性变换,并将输入层的输入通过 LogSoftmax 进行归一化解决。

在 forward 函数中,咱们首先将输出和暗藏状态向量进行拼接,而后将拼接后的向量传递给线性变换,并通过 LogSoftmax 输入预测后果。

在 initHidden 函数中,咱们初始化暗藏状态向量为全 0 向量。

  1. 定义训练函数
def train(inputs, targets, rnn):
    hidden = rnn.initHidden()

    rnn.zero_grad()

    loss = 0

    for i in range(len(inputs)):
        output, hidden = rnn(inputs[i], hidden)
        loss += criterion(output, targets[i])

    loss.backward()

    for p in rnn.parameters():
        p.data.add_(-learning_rate, p.grad.data)

    return output, loss.item()

下面的代码定义了一个训练函数,该函数承受输出和指标序列以及 RNN 模型作为参数,并返回模型的输入和损失。

在训练过程中,咱们首先初始化暗藏状态向量,并将模型的梯度清零。而后咱们遍历输出序列,并将每个输出向量和暗藏状态向量传递给 RNN 模型,计算预测后果并累加损失。最初,咱们计算损失的梯度,并应用随机梯度降落更新模型的参数。

  1. 定义数据集和超参数
pythonCopy codeinput_size = 4
hidden_size = 10
output_size = 3
learning_rate = 0.1

inputs = [torch.randn(1, input_size) for _ in range(5)]
targets = [torch.randint(0, output_size, (1,)).long() for _ in range(5)]

criterion = nn.NLLLoss()
rnn = RNN(input_size, hidden_size, output_size)
  1. 定义优化器和损失函数

咱们应用 Adam 优化器来更新模型的参数,并应用穿插熵损失函数作为模型的损失函数。在 PyTorch 中,能够通过 torch.optim.Adamnn.CrossEntropyLoss别离定义优化器和损失函数。

import torch.optim as optim
import torch.nn as nn

# 定义优化器和损失函数
optimizer = optim.Adam(model.parameters(), lr=0.01)
criterion = nn.CrossEntropyLoss()
  1. 训练模型

在训练模型之前,咱们须要先定义一些超参数,例如训练轮数、批次大小等。咱们还须要在每个训练轮次完结后计算模型在验证集上的准确率,以便及时发现过拟合的状况。

# 定义超参数
num_epochs = 10
batch_size = 64
learning_rate = 0.01

# 训练模型
for epoch in range(num_epochs):
    # 训练集迭代器
    train_iter.init_epoch()
    for batch_idx, batch in enumerate(train_iter):
        # 获取数据和标签
        data = batch.text
        target = batch.label - 1

        # 前向流传
        output = model(data)

        # 计算损失
        loss = criterion(output, target)

        # 反向流传
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # 打印训练信息
        if batch_idx % 100 == 0:
            print('Epoch: {}, Batch: {}, Loss: {:.4f}'.format(epoch+1, batch_idx+1, loss.item()))

    # 验证集迭代器
    val_iter.init_epoch()

    # 计算验证集准确率
    correct = 0
    total = 0
    with torch.no_grad():
        for batch in val_iter:
            data = batch.text
            target = batch.label - 1

            output = model(data)

            _, predicted = torch.max(output.data, 1)

            total += target.size(0)
            correct += (predicted == target).sum().item()

    accuracy = correct / total
    print('Validation Accuracy: {:.2f}%'.format(accuracy*100))
  1. 测试模型

训练实现后,咱们能够应用测试集来测试模型的性能。

# 测试集迭代器
test_iter.init_epoch()

# 计算测试集准确率
correct = 0
total = 0
with torch.no_grad():
    for batch in test_iter:
        data = batch.text
        target = batch.label - 1

        output = model(data)

        _, predicted = torch.max(output.data, 1)

        total += target.size(0)
        correct += (predicted == target).sum().item()

accuracy = correct / total
print('Test Accuracy: {:.2f}%'.format(accuracy*100))

至此,咱们应用 PyTorch 实现了一个简略的 RNN 模型,用于文本分类工作。在理论利用中,咱们能够通过扭转模型构造和超参数的设置来进一步优化模型的性能。

VII. 总结

RNN 的优缺点

长处:

  • 能够解决变长输出序列,实用于序列数据建模。
  • 具备记忆性,能够利用过来的信息对以后的输入进行预测。
  • 能够实现共享参数,缩小模型参数数量,节俭计算资源。
  • 能够通过重叠多层 RNN 来减少模型深度,进步模型的表达能力。

毛病:

  • 训练过程中容易呈现梯度隐没或梯度爆炸问题,导致模型无奈学习长期依赖关系。
  • 训练速度较慢,计算量较大,须要更多的计算资源和工夫。
  • 对于简单的序列数据,可能须要应用更简单的变种模型来解决,如 LSTM 和 GRU。

总的来说,RNN 适宜解决序列数据,能够通过记忆历史信息来预测将来数据。然而它也存在着训练艰难和计算资源耗费较大等问题,须要依据具体情况进行抉择和优化。

VIII. 参考资料

书籍:

  • Deep Learning by Goodfellow, Bengio, and Courville
  • Neural Networks and Deep Learning by Michael Nielsen
  • Hands-On Machine Learning with Scikit-Learn and TensorFlow by Aurélien Géron
  • Recurrent Neural Networks with Python Quick Start Guide by Daniel Pyrathon
  • Natural Language Processing with Python by Steven Bird, Ewan Klein, and Edward Loper

代码库:

  • PyTorch 官网文档:https://pytorch.org/docs/stab…
  • TensorFlow 官网文档:https://www.tensorflow.org/ap…
  • Keras 官网文档:https://keras.io/api/layers/r…
退出移动版