特征工程以及transformer基础框架学习


前面一篇已提及特征抽取
本篇继续学习剩下的部分

摘要

本周学习了特征预处理技术,例如规范化和标准化,这些技术对于为机器学习模型准备数据至关重要。还深入研究了 Transformer 架构,解释了嵌入、注意力机制等组件,以及使用残差连接和层归一化来提高模型性能。

abstract

This week learned about feature preprocessing techniques such as normalization and standardization, crucial for preparing data for machine learning models. It also delves into the Transformer architecture, explaining components like embeddings, attention mechanisms, and the use of residual connections and layer normalization to improve model performance.

1.特征预处理

通过一些转换函数及那个特征数据转换成更加适合算法模型的特征数据过程。

1.1 特征预处理API

sklearn.preprocessing

1.2 进行归一化/标准化

特征的单位或大小相差较大,或者某特征的方差相比其他的特征要大出几个数量级,容易影响(支配)目标结果。同时也需要一些方法进行无量钢化,使不同规格的数据转换到同一规格。

1.2.1 归一化

定义
通过对原始数据进行变换把数据映射到(默认[0,1])之间。
公式
X ′ = x − m i n m a x − m i n X ′ ′ = X ′ ∗ ( m x − m i ) + m i X^{\prime}=\frac{x-min}{max-min}\quad X^{\prime\prime}=X^{\prime}*(mx-mi)+mi X=maxminxminX′′=X(mxmi)+mi
公式应用:
在这里插入图片描述

API

sklearn.preprocessing.MinMaxScaler(feature_range=(0,1)...)
# X:numpy array格式的数据[n_samples,n_features]
MinMaxScalar.fit_transform(X)

使用 MinMaxScaler 类进行归一化处理:

def minmax_demo():  
	
    """  
  归一化示例  
 :return: """  # 1. 获取数据  
	 data = pd.read_csv("dating.txt")  
	 data = data.iloc[:3]  
	 print("data:\n", data)  
  
    # 2. 实例化一个转换器类  
  	transfer = MinMaxScaler(feature_range=[2, 3])  
  
    # 3. 调用 fit_transform  
    data_new = transfer.fit_transform(data)  
    print("data_new:\n", data_new)  
    
    return None  
    
if __name__ == "__main__":  
    minmax_demo()

缺点:归一化稳定性较差,只适合传统精确小数据场景。(最大值和最小值非常容易受异常点影响)

1.2.2 标准化

对于归一化中若存在异常值时(max/min)会使结果受到影响。
定义:通过对原始数据进行变换将数据变换成均值为0,标准差为1范围内。
公式
X ′ = x − m e a n σ X^{\prime}=\frac{x-\mathrm{mean}}{\sigma} X=σxmean
标准差:反应数据离散程度。

  • 对于标准化来说,如果出现异常值,由于具有一定的数据量,少量的异常点对于平均值的影响并不大,从而方差改变较小。
    API
sklearn.preprocessing.StandardScaler()
  • 处理后对每列来说,所有数据都聚集在均值为0附近,标准差为1。
  • StandardScaler.fit_transform(X) X为numpy array 格式的数据
  • 返回值:转换后的形状相同的array。
def standard_demo():  
    """  
  标准化示例  
 :return: """  # 1. 获取数据  
  data = pd.read_csv("dating.txt")  
  print("data:\n", data)  
  
    # 2. 实例化一个转换器类  
  transfer = StandardScaler()  
  
    # 3. 调用 fit_transform  
    data = transfer.fit_transform(data)  
    print("标准化结果:\n", data)
    print("每一列特征的平均值: \n",transfer.mean_)
    print("每一列特征的方差:\n",transfer.var_)
   
    return None  

2.transformer基础框架学习

如下是transformer在论文中的模型结构:


transformer模型结构图
在这里插入图片描述

2.1 输入部分

2.1.1 Embedding

词嵌入:一种将词汇映射到多维空间中的向量表示的方法。每个单词都被表示为一个固定长度的向量,这些向量捕捉了单词之间的语义和语法关系。
词嵌入目的:将离散的文本数据(单词或字符)转换为连续的数值向量,以便机器学习模型能够处理。
例下图:
在这里插入图片描述

** 位置嵌入**:在词嵌入的基础上添加一种特殊类型的嵌入,用于向模型提供关于输入序列中单词位置的信息。
位置嵌入目的:Transformer模型没有内置的位置感知机制,因此需要位置嵌入来帮助模型理解单词之间的相对位置或序列信息。
实现:位置嵌入通过预定义的函数或者训练得到的向量来实现。在Transformer中位置嵌入通常是固定的,并且可以通过正弦或者余弦函数来计算,以保持周期性特征,使得模型能够更好地泛化到不同地序列长度上。
位置编码
在这里插入图片描述

位置编码公式
P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 2 i / d m o d e l ) P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1000 0 2 i / d m o d e l ) PE_{(pos,2i)}=sin(pos/10000^{2i/d_{\mathrm{model}}})\\PE_{(pos,2i+1)}=cos(pos/10000^{2i/d_{\mathrm{model}}}) PE(pos,2i)=sin(pos/100002i/dmodel)PE(pos,2i+1)=cos(pos/100002i/dmodel)
例如对于单词:
在这里插入图片描述
结果相加:
在这里插入图片描述
以上可以得到一个重要的公式:
{ P E ( p o s + k , 2 i ) = P E ( p o s , 2 i ) × P E ( k , 2 i + 1 ) + P E ( p o s , 2 i + 1 ) × P E ( k , 2 i ) P E ( p o s + k , 2 i + 1 ) = P E ( p o s , 2 i + 1 ) × P E ( k , 2 i + 1 ) − P E ( p o s , 2 i ) × P E ( k , 2 i ) \left.\left\{\begin{matrix}PE(pos+k,2i)=PE(pos,2i)\times PE(k,2i+1)+PE(pos,2i+1)\times PE(k,2i)\\PE(pos+k,2i+1)=PE(pos,2i+1)\times PE(k,2i+1)-PE(pos,2i)\times PE(k,2i)\end{matrix}\right.\right. {PE(pos+k,2i)=PE(pos,2i)×PE(k,2i+1)+PE(pos,2i+1)×PE(k,2i)PE(pos+k,2i+1)=PE(pos,2i+1)×PE(k,2i+1)PE(pos,2i)×PE(k,2i)
对于pos+k位置向量某一维2i或2i+1 ,可以表示为pos位置与k位置的位置向量的2i与2i+1维的线性组合,这样的线性组合意味着位置向量中蕴含了相对位置信息。
注意:这种相对位置信息会这注意力机制那里消失。

输入嵌入在Transformer架构中的作用

  • 输入嵌入将文本数据转换为数值向量,这使得模型能够处理这些数据。
  • 词嵌入捕获了词汇之间的语义关系,而位置嵌入则提供了序列中单词的位置信息,这对于理解句子结构至关重要。
  • 这两种嵌入通常被相加以形成最终的输入向量,然后这个向量被传递给Transformer的编码器层进行进一步的处理。

2.2 注意力机制

本质
1.计算注意力分数:对于每个输入元素,计算一个分数,这个分数反映了该元素与当前任务的相关性。
2.权重分配:将计算的分数通过softmax函数转换为概率分布,作为注意力权重。表示当前上下文中的重要性。
3.加权求和:使用权重对输入进行加权求和,生成一个加权的上下文向量。上下文向量包含了当前任务所需的关键信息。
4.利用上下文向量:将生成的上下文向量用作后续处理的输入,如解码器中的状态向量。
应用
在Transformer模型中,注意力机制是核心组件之一,通过自注意力机制,使得模型能够直接从输入序列中学习依赖关系,而不需要基于循环神经网络(RNN)或其他递归结构。自注意力机制允许模型并行处理输出序列的所有位置,显著加快了训练速度,并且能够更好地捕捉长距离依赖关系。
例子
假设有一个英文句子:The cat sat on the mat.
这个句子由7个单词组成,每个单词可以表示一个词嵌入向量。
1.将每个单词转换成词嵌入向量。如“the”可以表示为[0.1,0.2,…,0.5]。将词嵌入添加有一个位置编码。
2.将词嵌入向量分别于三个不同的权重矩阵相乘,得到查询向量Q、键向量K和值向量V
3.使用点积注意力机制计算注意力得分。对于每个查询向量Qi,计算它与其他所有键向量Kj的点积,然后除以一个缩放因子根号dk。 S c o r e ( Q i , K j ) = Q i ⋅ K j T d k \mathrm{Score}(Q_i,K_j)=\frac{Q_i\cdot K_j^T}{\sqrt{d_k}} Score(Qi,Kj)=dk QiKjT
将所得分数通过softmax函数,得到注意力权重
α i j = s o f t m a x ( S c o r e ( Q i , K j ) ) \alpha_{ij}=\mathrm{softmax}(\mathrm{Score}(Q_i,K_j)) αij=softmax(Score(Qi,Kj))
​4.计算加权和,得到最终注意力输出
Attention ( Q i ) = ∑ j α i j V j \text{Attention}(Q_i)=\sum_j\alpha_{ij}V_j Attention(Qi)=jαijVj
5.将注意力机制的输出传递给一个前馈神经网络,进一步处理和生成最终的输出。

import numpy as np

# 假设的词嵌入矩阵
embeddings = np.random.rand(7, 512)  # 7 words, each with a 512-dimensional embedding

# 定义权重矩阵
W_Q = np.random.rand(512, 64)  # Query matrix (512 is the embedding size, 64 is the key size)
W_K = np.random.rand(512, 64)  # Key matrix
W_V = np.random.rand(512, 64)  # Value matrix

# 计算查询、键和值向量
Q = np.dot(embeddings, W_Q)
K = np.dot(embeddings, W_K)
V = np.dot(embeddings, W_V)

# 计算注意力得分
scores = np.matmul(Q, K.T) / np.sqrt(64)

# 应用softmax
attention_weights = np.exp(scores) / np.sum(np.exp(scores), axis=-1, keepdims=True)

# 计算加权和
output = np.matmul(attention_weights, V)

# 输出结果
print(output.shape)  # 应该是 (7, 64)

2.3 残差和LayNorm

在这里插入图片描述
上述图片是从输入到输出的过程,图片中词向量X1通过自注意力机制后需要进行标准化LayerNorm。

2.3.1 残差

在这里插入图片描述
残差块的作用:
1.缓解梯度消失问题

  • 在深度网络中,随着网络层数的增加,反向传播过程中梯度可能会逐渐减小,导致靠近输入层的权重更新非常缓慢,即梯度消失问题。
  • 残差块通过添加跳过连接(skip connections)的方式,允许梯度更直接地从输出层传递到前面的层,从而有助于缓解梯度消失问题。

2.简化学习任务

  • 残差块让网络学习残差映射,而非完整的映射。这通常比学习一个复杂的映射更简单,因为残差映射往往比较平滑。
  • 残差块学习的是输入到输出之间的差异,这使得网络更容易学习恒等映射(即输入和输出相同),从而避免了深层网络的退化问题。

3.提升模型表现

  • 由于残差块可以更容易地训练更深的网络,因此可以利用更多的参数来捕捉更复杂的数据特征,从而提高模型的性能。

4.加速收敛

  • 加入残差块后,网络可以更快地收敛,因为残差学习框架减少了训练深层网络时的困难。

2.3.2 Batch Normalization(BN)

工作原理

  • BN 主要在训练阶段对每个 mini-batch 的数据进行规范化。
  • 它计算 mini-batch 的均值和方差,并据此规范化数据。
  • 规范化后的数据再通过可学习的参数 γ 和 β进行缩放和平移。
    特点
  • BN 可以看作是对每个 mini-batch 的数据进行规范化。
  • 它依赖于 mini-batch 的统计信息(均值和方差),因此其效果受 mini-batch 大小的影响。
  • BN 在训练阶段和推理阶段使用不同的统计信息(训练阶段使用 mini-batch 的统计信息,推理阶段使用整个训练集的统计信息的移动平均)。
    优点
  • 减少内部协变量移位,加速训练。
  • 具有一定的正则化效果,有助于提高模型的泛化能力。
  • 允许使用较高的学习率,加速训练过程。
    缺点
  • 对于较小的 mini-batch 大小可能不太稳定。
  • 在某些情况下,BN 可能会导致梯度消失或梯度爆炸。
    对于一些序列模型(如 RNN),BN 的效果不如 LN。

2.3.3 Layer Normalization(LN)

工作原理

  • LN 是针对单个样本的特征维度进行规范化。
  • 它计算每个样本在特定层的特征维度上的均值和方差,并据此规范化数据。
  • 规范化后的数据再通过可学习的参数γ 和 β 进行缩放和平移。
    特点
  • LN 不依赖于 mini-batch 的大小,而是针对每个样本的特征维度进行规范化。
  • LN 更适合处理序列数据和变长输入数据,如 RNN 和 Transformer 模型。
    优点
  • 不受 mini-batch 大小的影响。
  • 适用于各种类型的输入数据,包括变长序列。
    在某些情况下(如 RNN 和 Transformer),LN 的效果优于 BN。
    缺点
  • 相对于 BN,LN 可能需要更多的计算资源。

下面的例子是tensorflow深度学习框架中分别加入BN层和LN层,并对比两个模型效果。

import tensorflow as tf
from tensorflow.keras import layers, models
import numpy as np

def create_bn_model():
    model = models.Sequential([
        layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
        layers.BatchNormalization(),
        layers.MaxPooling2D((2, 2)),
        layers.Flatten(),
        layers.Dense(64, activation='relu'),
        layers.BatchNormalization(),
        layers.Dense(10, activation='softmax')
    ])
    return model
   
class LayerNormalization(layers.Layer):
    def __init__(self, axis=-1, epsilon=1e-6, **kwargs):
        super(LayerNormalization, self).__init__(**kwargs)
        self.axis = axis
        self.epsilon = epsilon

    def build(self, input_shape):
        self.gamma = self.add_weight(shape=input_shape[-1:], initializer='ones', name='gamma')
        self.beta = self.add_weight(shape=input_shape[-1:], initializer='zeros', name='beta')
        super(LayerNormalization, self).build(input_shape)

    def call(self, inputs):
        mean = tf.reduce_mean(inputs, axis=self.axis, keepdims=True)
        variance = tf.reduce_variance(inputs, axis=self.axis, keepdims=True)
        normed = (inputs - mean) / tf.sqrt(variance + self.epsilon)
        return normed * self.gamma + self.beta

    def get_config(self):
        config = super(LayerNormalization, self).get_config()
        config.update({'axis': self.axis, 'epsilon': self.epsilon})
        return config
        
def create_ln_model():
    model = models.Sequential([
        layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
        LayerNormalization(),
        layers.MaxPooling2D((2, 2)),
        layers.Flatten(),
        layers.Dense(64, activation='relu'),
        LayerNormalization(),
        layers.Dense(10, activation='softmax')
    ])
    return model

# 准备数据
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = x_train.reshape(-1, 28, 28, 1).astype('float32') / 255.
x_test = x_test.reshape(-1, 28, 28, 1).astype('float32') / 255.

# 创建模型
bn_model = create_bn_model()
ln_model = create_ln_model()

# 编译模型
bn_model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
ln_model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

# 训练模型
history_bn = bn_model.fit(x_train, y_train, epochs=5, batch_size=64, validation_split=0.2)
history_ln = ln_model.fit(x_train, y_train, epochs=5, batch_size=64, validation_split=0.2)

# 评估模型
loss_bn, accuracy_bn = bn_model.evaluate(x_test, y_test)
loss_ln, accuracy_ln = ln_model.evaluate(x_test, y_test)

# 打印结果
print(f"BN Model Test Loss: {loss_bn:.4f}, Test Accuracy: {accuracy_bn:.4f}")
print(f"LN Model Test Loss: {loss_ln:.4f}, Test Accuracy: {accuracy_ln:.4f}")

3. 总结

在本周中,学习了特征预处理方法,包括归一化和标准化,用于为机器学习算法准备数据。然后,详细介绍了 Transformer 架构,重点学习了它通过词和位置嵌入的输入处理。注意力机制被解释为一个核心组件,它允许模型对输入序列的不同部分进行加权。引入残差连接是为了缓解梯度消失问题并提高训练稳定性,而LN层被证明可以标准化单个样本特征维度的激活,从而提高模型性能,尤其是在序列建模任务中。列举了使用 Python 库实现这些概念的实际示例。总的来说,这些技术对于传统机器学习和深度学习应用程序都是基础,尤其是在自然语言处理任务中。

  • 21
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值