深度学习算法学习(六):深度学习-处理文本:神经网络处理文本、Embedding层

深度学习-处理文本

NLP任务

任务:字符串分类 -- 判断字符串中是否出现了指定字符

  • 指定字符:a
  • abcd 为正样本
  • bcde 为负样本

神经网络处理文本

第一步:字符数值化

我们需要把字符转换为数学上的东西才能进入模型

单个字符转换为标量 ❌

把单个字符转换为标量,这样合理么?

a -> 1, b -> 2, c -> 3 .... z -> 26

不合理,如果这样的话,会引入一些本不存在的关系,比如,a+b=c,a+a=b

单个字符转换为向量 ✅

把单个字符转换为同维度向量,这样就合理了

a -> [0.32618175 0.20962898 0.43550067 0.07120884 0.58215387]

b -> [0.21841921 0.97431001 0.43676452 0.77925024 0.7307891]

...z -> [0.72847746 0.72803551 0.43888069 0.09266955 0.65148562]

多个字符-字符串转换为矩阵

"abcd" -> 4 * 5 的矩阵

矩阵形状 = 文本长度 * 向量长度

\[0.32618175 0.20962898 0.43550067 0.07120884 0.58215387

0.21841921 0.97431001 0.43676452 0.77925024 0.7307891

0.95035602 0.45280039 0.06675379 0.72238734 0.02466642

0.86751814 0.97157839 0.0127658 0.98910503 0.92606296\]

第二步:矩阵转化为向量

求平均

\[0.32618175 0.20962898 0.43550067 0.07120884 0.58215387

0.21841921 0.97431001 0.43676452 0.77925024 0.7307891

0.95035602 0.45280039 0.06675379 0.72238734 0.02466642

0.86751814 0.97157839 0.0127658 0.98910503 0.92606296\]

列的每个值相加除以4

0.59061878 0.65207944 0.2379462 0.64048786 0.56591809

由4 * 5 矩阵 -> 1* 5 向量 (这称之为pooling池化)

第三步:向量到实数

采取最简单的线性公式 y = w * x + b

w 维度为1*向量维度 b为实数

例:

第四步:实数归一化

通过sigmoid函数

例:x = 2 σ(x) = 0.8808

整体流程

"abcd" ----每个字符转化成向量----> 4 * 5矩阵

4 * 5矩阵 ----向量求平均----> 1 * 5向量

1 * 5向量 ----w * x + b线性公式 ---> 实数

实数 ----sigmoid归一化函数---> 0-1之间实数

加粗部分需要通过训练优化

Embedding

定义

Embedding矩阵是可训练的参数,一般会在模型构建时随机初始化

也可以使用预训练的词向量来做初始化,此时也可以选择不训练Embedding层中的参数

输入的整数序列可以有重复,但取值不能超过Embedding矩阵的列数

核心价值:将离散值 转化为向量

代码

python 复制代码
import torch
import torch.nn as nn

'''
embedding层的处理
'''
# 通常对于nlp任务,此参数为字符集字符总数
# 词汇表大小,表示有8个不同的字符
num_embeddings = 8
# 每个字符将被映射为4维的向量
embedding_dim = 4
# 创建一个Embedding层,形状为{8, 4}
# 内部维护一个可训练的权重矩阵,随机初始化
# padding_idx = 0 表示0索引对应的字符为填充字符,填充字符的向量全为0(不进行运算)
embedding_layer = nn.Embedding(num_embeddings, embedding_dim, padding_idx =0)
print("随机初始化权重")
print("embedding_layer.weight:", embedding_layer.weight)
print("################")

# 字符表
vocab = {
    "pad" : 0,
    "a" : 1,
    "b" : 2,
    "c" : 3,
    "d" : 4,
    "e" : 5,
    "f" : 6,
    "unk": 7
}

# 将输入字符串中的每个字符转换为对应字符表的索引值
# 例如:"abc" → [1, 2, 3]
def str_to_sequence(string, vocab):
    return [vocab[s] for s in string]

# 创建3个示例字符串并转换为3个对应字符表索引list
string1 = "abcde"
string2 = "ddccb"
string3 = "fedab"

list1 = str_to_sequence(string1, vocab)
list2 = str_to_sequence(string2, vocab)
list3 = str_to_sequence(string3, vocab)

print("list1:", list1)
print("list2:", list2)
print("list3:", list3)
print("\n")

# 将三个索引list堆叠成形状为{3, 5}的张量
x = torch.LongTensor([list1, list2, list2])
print("输入张量形状:", x)
print("\n")

"""
输入x的每个元素对应字符表索引,通过Embedding层进行映射,得到结果

例如:
embedding_layer.weight 权重矩阵为:
[0.1, 0.2, 0.3, 0.4]
[0.5, 0.6, 0.7, 0.8]
[0.9, 1.0, 1.1, 1.2]

"acb" 对应的字符表索引为 [1, 3, 2] 作为x输入 
输出为: [[0.1, 0.2, 0.3, 0.4],
        [0.9, 1.0, 1.1, 1.2],
        [0.5, 0.6, 0.7, 0.8]]
"""
embedding_out = embedding_layer(x)
print(embedding_out)

输出

python 复制代码
随机初始化权重
embedding_layer.weight: Parameter containing:
tensor([[ 0.0000,  0.0000,  0.0000,  0.0000],
        [-1.2829, -0.5944, -0.5828,  0.9199],
        [ 0.3016,  1.3304,  0.0693, -1.0530],
        [ 0.7432,  0.6106, -0.0946, -0.0349],
        [-0.2063, -1.2251,  0.7196,  0.8559],
        [-0.1538, -0.3300, -0.2811, -0.3768],
        [ 0.1613, -1.4955, -1.6733,  1.3582],
        [ 1.8100,  0.5757,  0.2786, -0.9209]], requires_grad=True)
################
list1: [1, 2, 3, 4, 5]
list2: [4, 4, 3, 3, 2]
list3: [6, 5, 4, 1, 2]


输入张量形状: tensor([[1, 2, 3, 4, 5],
        [4, 4, 3, 3, 2],
        [4, 4, 3, 3, 2]])


tensor([[[-1.2829, -0.5944, -0.5828,  0.9199],
         [ 0.3016,  1.3304,  0.0693, -1.0530],
         [ 0.7432,  0.6106, -0.0946, -0.0349],
         [-0.2063, -1.2251,  0.7196,  0.8559],
         [-0.1538, -0.3300, -0.2811, -0.3768]],

        [[-0.2063, -1.2251,  0.7196,  0.8559],
         [-0.2063, -1.2251,  0.7196,  0.8559],
         [ 0.7432,  0.6106, -0.0946, -0.0349],
         [ 0.7432,  0.6106, -0.0946, -0.0349],
         [ 0.3016,  1.3304,  0.0693, -1.0530]],

        [[-0.2063, -1.2251,  0.7196,  0.8559],
         [-0.2063, -1.2251,  0.7196,  0.8559],
         [ 0.7432,  0.6106, -0.0946, -0.0349],
         [ 0.7432,  0.6106, -0.0946, -0.0349],
         [ 0.3016,  1.3304,  0.0693, -1.0530]]], grad_fn=<EmbeddingBackward0>)

pad

看上面的代码流程,你会发现,字符串转换为对应字符表索引list后,需要堆叠为张量

例:

  • abc -> [1, 2, 3]

  • cdba -> [3, 4, 2, 1]

  • ac -> [1, 3]

这三个字符串长度不一致,没办法放到一个张量里进行训练,所以需要补齐 或者截断

比如我想要的长度是3

  • abc -> [1, 2, 3] 不动

  • cdba -> [3, 4, 2] 截断

  • ac -> [1, 3, 0] 补齐

unk

有一些没写在词表里的未知字符,会用unk来代替

相关推荐
hakuii2 小时前
3dgs学习有感
学习·3d
高洁012 小时前
AI智能体搭建(1)
人工智能·深度学习·机器学习·transformer·知识图谱
lixzest2 小时前
Transformer 零基础学习指南
人工智能·深度学习·transformer
QiZhang | UESTC2 小时前
学习日记day54
学习
ldccorpora2 小时前
Chinese Treebank 5.0数据集介绍,官网编号LDC2005T01
人工智能·深度学习·自然语言处理·动态规划·语音识别
玖日大大2 小时前
物理信息神经网络(PINN):AI与物理定律的融合新范式
人工智能·深度学习·神经网络
风送雨2 小时前
FastAPI 学习教程 · 第1部分
学习·fastapi
Francek Chen2 小时前
【自然语言处理】应用07:自然语言推断:微调BERT
人工智能·pytorch·深度学习·自然语言处理·bert
Codeking__2 小时前
Redis的value类型及编码方式介绍——hash
redis·算法·哈希算法