Why Is Deep Learning Better than Traditional Machine Le
作者:禅与计算机程序设计艺术
1.简介
在自然语言处理领域内,默认情况下是两种主要的研究方向:传统机器学习算法与深度学习算法。近来,在多个实际应用领域中(如图像识别、语音识别等技术),深度学习展现出显著的应用价值与广泛的研究成果。然而这些方法仍占据绝对优势地位那么哪种方法更为优秀?或者机器学习算法的发展到底有没有给自然语言处理带来什么变化呢?本文将深入探讨这一核心议题
2. 基本概念术语说明
为了更好地理解机器学习、深度学习以及自然语言处理的基础概念与核心术语,我们需要进行初步阐述。
2.1 机器学习
机器学习(ML)是一类通过训练算法来提高计算机处理数据能力的方法。具体而言:
- 该方法主要用于从大数据集中提取知识
- 机器学习主要包括以下三项核心任务:
- 分类与判别分析主要用于根据已知类别对新数据进行分类
- 回归分析则用于建模连续型变量之间的关系
- 聚类分析旨在发现数据中的自然群组
Learning task: Based on the input data's features and target values, analyze the dataset's samples to train a model or function that can predict the output results of new input samples. This process can be considered a form of supervised learning, which involves using input samples and their true labels to train a model. For example, classification and regression tasks are common applications of this approach.
-
概念发现:输入数据的特征间存在关联性 通过自动生成潜在的关系并选择合适的表达形式来完成这一目标称之为概念发现 这种方法通常依赖于人工设定特定规则来引导模型构建 例如聚类分析因子分解关联规则挖掘等方法常被采用。
-
非监督学习方法旨在识别数据内在的结构:它不依赖于预设的目标变量而是通过分析数据分布特征来进行研究。该方法主要依赖于识别数据中的潜在模式和内部规律来提取有用信息。例如降维技术、可视化方法以及用于异常检测的各种统计工具。
2.2 深度学习
深度学习(Deep Learning)是机器学习的重要组成部分。它主要通过构建多层次的神经网络结构,并利用非线性变换和优化算法(如梯度下降法)来训练神经网络以实现对复杂数据模式的分析与预测目标。在自然语言处理领域中,深度学习方法已经被广泛应用于各个关键环节,并取得了显著成效。
深度学习包括以下几个关键技术:
多层次人工神经网络系统:深度学习体系的关键在于多层次人工神经网络系统的构建。每个层次都包含大量人工神经元节点,并通过激活函数实现数据的非线性变换过程。
-
在训练阶段,在反向传播的过程中,
该算法被用来计算神经网络各层权重的变化量,
而梯度下降法则通过迭代优化找到最佳模型参数。 -
训练策略:训练策略主要采用随机梯度下降(Stochastic Gradient Descent, SGD)、批处理随机梯度下降(Mini-batch Stochastic Gradient Descent, Mini-batch SGD)以及带动量的随机梯度下降(Momentum SGD)等。该算法仅更新一次参数;相比之下,另外两种方法则有助于降低过度拟合的风险。
-
Dropout:Dropout是一种防止过拟合的方法,在深度学习模型训练中被广泛应用。其核心理念在于,在每一次参数更新的过程中随机抑制部分神经元的活性(即置零),从而模拟部分神经元失效的情况。通过这种方式的应用,“整个网络的表现能力”得以显著提升。
-
数据增强:其手段是对原始数据进行一系列处理或调整,并通过平移、旋转和缩放等方式以提升模型的泛化能力。
2.3 自然语言处理
机器理解人类语言的技术(Natural Language Processing, NLP)作为一门核心学科之一,在计算机科学与技术领域发挥着关键作用。该技术致力于探索有效理解和生成自然语言的方法,并通过创造能够模仿人类交流的人工智能系统来推动发展。近年来,在深度学习技术的支持下,NLP领域的创新已经取得了令人瞩目的进展
自然语言处理的基本任务是:
进行分词和词性标注即为将自然语言文本划分为一系列的词语,并给每个词语分配相应的词性标签,包括名词、代词和动 verb 等基本类别。
Extracting Named Entity: From a given text, identify the named entities such as person names, location names, organization names, and other entities within the text.
- 文本提炼与情感倾向判定:自动化生成一个精炼明确的文本摘要,并对每个句子的情感倾向进行分类。
智能对话系统将具备智能机器翻译能力,并提供智能对话支持以满足日常交流和查询的需求
3. 核心算法原理和具体操作步骤以及数学公式讲解
本节旨在阐述深度学习算法在自然语言处理任务中的具体实施流程,并对相关的数学模型推导过程进行深入解析。
3.1 词嵌入Word Embedding
词嵌入(Word Embedding)是自然语言处理中的核心技术之一,在将词语转换为数值形式的过程中体现出了语义关联程度或语境信息的作用
传统的词嵌入方法是基于全局统计信息
3.1.1 概念
现有词嵌入方法是基于词典中的词语集合,在计算任意一对词语同时出现频率的基础上构建了一个数学模型来表示它们的意义。这种算法虽然简洁直接易于理解,在实际应用中往往未能充分考虑到语境关系的影响。
基于深度学习的方法能够生成具有高阶语义表示的模型,并且不仅考虑到词语本身及其周围环境,还利用神经网络模型构建词向量来捕捉复杂的语义关联。其核心优势在于能够有效提取并整合各领域关键词的信息特征以形成全面的理解能力。
3.1.2 操作步骤
假设有一组文本,将其中的词语组成集合V={w_i}_{i=1}^{n},其中第i个词w_i用one-hot编码表示为x_i \in R^d,其中d为词向量维度。假设词嵌入的维度为k,那么每个词向量z_i可以表示如下:
其中f(\cdot)是一个非线性函数,在本研究中具体来说可以是多层神经网络。假设词嵌入的矩阵W和偏置b能够被表示如下:
则上式可以改写为:
其中z_i的第j个元素为:
其中w_{i+j}和w_{i-j}分别是文本中第i个词前j个词、后j个词的词向量。
在当前讨论中提到的词嵌入公式仅是其中一种基础实现方案, 此外还有其他不同的算法模型可供选择. 特别关注一个核心问题, 为什么需要引入偏置项b, 以及如何训练得到词嵌入矩阵W.
3.1.3 学习词嵌入矩阵
学习词嵌入矩阵的问题可以分为两步:
基于训练数据集推导出权重矩阵 W :为了避免初始值的大小可能导致计算资源不足,在实际应用中通常会使用小号矩阵作为初始化方案;随后通过反向传播算法优化模型参数以降低训练损失。
- 重新计算偏置项b的值:考虑到词嵌入矩阵W已经达到了优化状态,在这一基础上进行参数更新可能会产生一定的偏差影响。由此可知,在优化过程中必须持续关注并调整参数间的相互作用关系。通过采用梯度下降算法能够有效地降低偏差相关损失函数,并且这种方法能够在一定程度上提高模型的整体性能表现
3.1.4 负采样Negative Sampling
负采样(Negative Sampling)是一种旨在提高词嵌入训练速度的方法。具体来说,它通过降低负样本的比例来优化模型的学习效果。该方法详细说明了具体的实现过程,并在实际应用中取得了显著的效果提升。
对于一个给定的中心词c以及预先设定的数量级k=K(其中k∈N^+),能够从整个词汇表中均匀地随机选取k=K`个反例v'={\bar v'_1,\cdots,\bar v'_k}$。
- 构造损失函数:最大化词嵌入向量的概率分布:
其中\sigma(\cdot)是一个sigmoid函数,\theta是参数。
- 使用负采样算法迭代更新参数\theta:
其中\alpha是学习率。
3.2 循环神经网络RNN
循环神经网络(Recurrent Neural Network, RNN)作为深度学习中的一个重要模型,在处理序列数据方面展现出独特优势。其核心组件由时间序列中的某个时刻输入变量Xt和对应的状态变量Ht构成,在每个时刻点上通过动态机制不断更新状态信息,并借助非线性激活函数来调控信息传递路径。这种架构设计使其显著的特点是能够保持长期记忆能力,并在此基础上有效地解决序列数据中的长期依赖问题。
3.2.1 概念
循环神经网络有能力学习长期依赖的问题,在于其内部状态能够保存先前时间步的信息并通过传递实现学习。假设某个词的词嵌入向量为z_i,前j个时间步长的状态可表示为h_{t-j}:=(h_{t-j:t})^T其中t-j:t表示t-j至t时间段的状态。假设状态由两个隐含层网络g和h来控制即:
其中softmax(\cdot)是一个Softmax函数,W_hy_t和b_y是输出层的参数。
3.2.2 操作步骤
给定输入序列X=[x_1,x_2,\cdots,x_T]。根据每个时间点t=1,2,\cdots,T,通过应用状态更新方程计算新的状态值h_t。
最后,将所有状态连接起来,送入输出层:
其中W_ho, U_hh, 和b_o是输出层的参数。
3.3 卷积神经网络CNN
卷状神经网络(Convolutional Neural Network, CNN)是一种深度学习模型。基于输入图片的数据处理机制下执行特征提取操作,并能实现多种图像识别和目标检测任务。其核心组件通常包括一个卷积层。由多个滤波器及其对应的响应矩阵构成。
3.3.1 概念
CNN 识别出的特征通常被视为图像中的局部结构特征。假设输入图像尺寸为h\times w,经过多层卷积运算后,每层卷积操作会使输出尺寸按比例缩小为h/s\times w/s(其中s为卷积核步长参数),这种缩减有助于减少计算复杂度并提升特征提取效率。
为了主要目的是提取图像的全局特征,在经过池化层后设置一个全连接层(FC)或直接在卷积层之后设置一个softmax(SOFTMAX)层以完成分类任务
3.3.2 操作步骤
CNN 包括多种卷积层、池化层和全连接层等多种结构,在每种结构中都包含了一系列滤波器(Filter)。在训练过程中,在每一步迭代中都会应用梯度下降算法来优化和更新滤波器参数。
3.4 生成式模型Seq2seq
生成式模型(Generative Model)基于对语法和语义信息的学习来生成目标内容;其核心机制在于通过训练数据提取语言模式并利用这些模式进行内容创作。序贯到序贯模型(Sequence to Sequence model,(Seq2seq)),其功能是将一段输入文本映射至另一段相应长度的目标文本内容。
3.4.1 概念
该模型可被视为一种编码与解码结合的架构,在信息处理领域具有重要地位。它通过将输入数据进行编码转换,并借助解码过程实现对目标数据的准确重构与再生。传统的 Seq2seq 模型由 Encoder 和 Decoder 两个关键组件构成:其中 Encoder 部分负责对输入数据进行编码并提取其深层特征;而 Decoder 部分则负责对已产生的内容进行解码并最终推导出目标输出结果。具体而言,在 Encoder 部分中接收一段输入文本后,在经过多层神经网络处理后会得到一个固定的长度向量表示;随后在 Decoder 部分中根据已产生的字符或对应的词向量,在进一步推导的基础上完成整个目标语句或段落的内容构建工作。这一架构设计使得该模型具备了高度灵活与适应性强的特点,并被广泛应用于自然语言处理领域中的多种任务类型中
3.4.2 操作步骤
为了解决将英文句子翻译成中文的问题,在机器学习领域中需要用到Seq2seq模型进行建模与学习。具体而言,Seq2seq模型的学习过程包含以下几个步骤:第一步是进行数据采集与预处理;第二步是构建并优化模型;第三步是利用训练好的模型进行实际的翻译任务。
对Seq2seq体系进行具体说明:该体系由编码器、解码器以及其中间环节组成。
准备训练数据:对 Seq2seq 模型的输入和输出进行预处理,并将其转换为模型可接受的数据格式;接着将转换后的数据导入模型中进行训练。
采用标准的BP算法进行Seq2seq模型参数训练,并使模型损失最小化。
4. 具体代码实例和解释说明
在上一章中介绍了自然语言处理相关的概念、术语和算法,在此基础上通过示例代码进行详细展示。
4.1 word embedding
import tensorflow as tf
embedding_dim = 10 #词向量维度
num_embeddings = len(word_to_id) #词汇量
embedding_matrix = np.zeros((num_embeddings, embedding_dim))
for i in range(len(vocab)):
embedding_vector = embeddings_index.get(word_to_id[vocab[i]])
if embedding_vector is not None:
# words not found in embedding index will be all zeros.
embedding_matrix[i] = embedding_vector
model = tf.keras.Sequential()
model.add(tf.keras.layers.Embedding(input_dim=num_embeddings, output_dim=embedding_dim, input_length=MAX_SEQUENCE_LENGTH, weights=[embedding_matrix], trainable=False))
...
代码解读
在自然语言处理中,
word_to_id 是将词语映射到唯一标识符的过程,
而 vocab 则代表所有可能词语的集合。
为了构建词嵌入矩阵,
我们通常会预先加载好 embeddings_index
以利用其权重信息。
当词汇规模较小时,
可采用简单的初始化方式,
将词嵌入矩阵直接设置为零向量;
而对于较大的词汇规模,
则建议使用预训练好的词向量进行初始化。
4.2 rnn
def create_rnn():
model = tf.keras.Sequential()
# 添加LSTM层
model.add(tf.keras.layers.LSTM(units=HIDDEN_UNITS, return_sequences=True, input_shape=(MAX_SEQUENCE_LENGTH, EMBEDDING_DIM)))
model.add(tf.keras.layers.Dropout(rate=DROPOUT_RATE))
# 添加全连接层
model.add(tf.keras.layers.Dense(units=NUM_CLASSES, activation='softmax'))
optimizer = tf.keras.optimizers.Adam(lr=LEARNING_RATE)
loss = 'categorical_crossentropy'
metric = 'accuracy'
model.compile(optimizer=optimizer, loss=loss, metrics=[metric])
return model
代码解读
在示例中使用create_rnn()函数生成了一个简单的 LSTM 模型。LSTM 层配置了返回序列属性为True,则其输出结果构成序列。输入数据的形状设定为(batch\_size, sequence\_length, feature\_dimension),其中feature\_dimension表示词嵌入的空间维度。为了防止过拟合,在该层应用了Dropout机制,并随机跳过一定比例的神经元进行处理。全连接层采用了Softmax激活函数以应对多分类任务。
4.3 cnn
def create_cnn():
model = tf.keras.Sequential()
# 添加卷积层
model.add(tf.keras.layers.Conv2D(filters=FILTERS, kernel_size=(WINDOW_SIZE, EMBEDDING_DIM), padding="valid", strides=(1,1), data_format="channels_last", input_shape=(MAX_SEQUENCE_LENGTH, EMBEDDING_DIM)))
model.add(tf.keras.layers.BatchNormalization())
model.add(tf.keras.layers.Activation('relu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(MAX_SEQUENCE_LENGTH - WINDOW_SIZE + 1, 1),strides=(1,1),padding="valid"))
# 添加全连接层
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(units=NUM_CLASSES,activation='softmax'))
optimizer = tf.keras.optimizers.Adam(lr=LEARNING_RATE)
loss = 'categorical_crossentropy'
metric = 'accuracy'
model.compile(optimizer=optimizer, loss=loss, metrics=[metric])
return model
代码解读
create_cnn() 函数构建了一个简单的卷积神经网络模型。该模型由两个卷积模块和一个全连接层构成。每个卷积模块的输入维度为 (batch大小, 序列长度, 特征维度) ,其中 序列长度 表示输入序列的最大长度,“特征维度”指的是词嵌入的空间维度;采用批规范化处理以标准化激活值,并选用 Rectified Linear Unit 激活函数;最大值池化机制用于降低输出空间尺寸。全连接层的输入维度为 (batch大小, 神经元数量) ,其中 神经元数量 代表所有卷积特征的数量;选用 softmax 作为激活函数进行分类任务。
4.4 seq2seq
class Encoder(tf.keras.Model):
def __init__(self, vocab_size, embedding_dim, enc_units, batch_sz):
super(Encoder, self).__init__()
self.batch_sz = batch_sz
self.enc_units = enc_units
self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim, name='encoder_embedding')
self.gru = tf.keras.layers.GRU(self.enc_units,
return_sequences=True,
return_state=True,
recurrent_initializer='glorot_uniform')
def call(self, x, hidden):
x = self.embedding(x)
output, state = self.gru(x, initial_state = hidden)
return output, state
def initialize_hidden_state(self):
return tf.zeros((self.batch_sz, self.enc_units))
class Decoder(tf.keras.Model):
def __init__(self, vocab_size, embedding_dim, dec_units, batch_sz):
super(Decoder, self).__init__()
self.batch_sz = batch_sz
self.dec_units = dec_units
self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim, name='decoder_embedding')
self.gru = tf.keras.layers.GRU(self.dec_units,
return_sequences=True,
return_state=True,
recurrent_initializer='glorot_uniform')
self.fc = tf.keras.layers.Dense(vocab_size)
# used for attention
self.attention = BahdanauAttention(self.dec_units)
def call(self, x, hidden, enc_output):
context_vector, attention_weights = self.attention(hidden, enc_output)
x = self.embedding(x)
x = tf.concat([tf.expand_dims(context_vector, 1), x], axis=-1)
output, state = self.gru(x)
output = tf.reshape(output, (-1, output.shape[2]))
x = self.fc(output)
return x, state, attention_weights
def create_seq2seq(vocab_inp_size, vocab_tar_size, max_length_inp, max_length_tar,
embedding_dim, units, bidirectional=False, dropout=0.3):
encoder = Encoder(vocab_inp_size, embedding_dim, units, BATCH_SIZE)
decoder = Decoder(vocab_tar_size, embedding_dim, units * (2 if bidirectional else 1), BATCH_SIZE)
optimizer = tf.keras.optimizers.Adam(learning_rate=LR)
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True, reduction='none')
def loss_function(real, pred):
mask = tf.math.logical_not(tf.math.equal(real, 0))
loss_ = loss_object(real, pred)
mask = tf.cast(mask, dtype=loss_.dtype)
loss_ *= mask
return tf.reduce_mean(loss_)
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')
checkpoint_path = "./checkpoints"
ckpt = tf.train.Checkpoint(encoder=encoder, decoder=decoder, optimizer=optimizer)
ckpt_manager = tf.train.CheckpointManager(ckpt, checkpoint_path, max_to_keep=5)
@tf.function
def train_step(inp, targ, enc_hidden):
loss = 0
with tf.GradientTape() as tape:
enc_output, enc_hidden = encoder(inp, enc_hidden)
dec_hidden = enc_hidden
dec_input = tf.expand_dims([targ_lang.word_index['<start>']] * BATCH_SIZE, 1)
result = []
for t in range(1, targ.shape[1]):
predictions, dec_hidden, _ = decoder(dec_input, dec_hidden, enc_output)
predicted_id = tf.argmax(predictions[0]).numpy()
result.append(predicted_id)
if targ[0][t]!= 0:
loss += loss_function(targ[:, t], predictions)
dec_input = tf.expand_dims([predicted_id], 1)
total_loss = (loss / int(targ.shape[1]))
train_loss(total_loss)
train_accuracy(targ, predictions)
variables = encoder.trainable_variables + decoder.trainable_variables
gradients = tape.gradient(loss, variables)
optimizer.apply_gradients(zip(gradients, variables))
return encoder, decoder, train_step, train_loss, train_accuracy, ckpt, ckpt_manager
代码解读
create_seq2seq() 函数负责构建一个 Seq2seq 模型体系结构。该函数通过搭建 Encoder 和 Decoder 组件,并整合了完整的训练流程功能。
