小案例jieba分词(词嵌入层)
"""
案例:
RNN
全称叫: Recurrent neural network, 循环神经网络, 包含: 词嵌入层 + 循环层 + 全连接层(输出层)
其中:
词嵌入层: 把词转成词向量矩阵, 即: word_to_vector(word_2_vector, word_vec, word2vec)
思路:
语料(句子,文本) -> 切词,去重, 得到: 词汇表 -> 词向量矩阵.
"""
# 导包
import torch
import torch.nn as nn
import jieba
# 1. 创建文本(语料)
text = "北京冬奥的进度条已经过半,不少外国运动员在完成自己的比赛后踏上归途。"
# 2. 使用jieba进行分词, 得到: 词汇表.
words = jieba.lcut(text)
print(f'words: {words}') # ['北京', '冬奥', '的', '进度条', '已经', '过半', ',', '不少', '外国', '运动员', '在', '完成', '自己', '的', '比赛', '后', '踏上', '归途', '。']
# 扩展: 词汇表去重.
words = list(set(words))
print(f'words: {words}, 个数: {len(words)}') # [去重后的内容], 18个
# 3. 创建词嵌入层.
# 参1: 词汇表大小(即: 词汇表中单词的数量), 参2: 词向量的维度(即: 用几个数字表示一个单词)
embed = nn.Embedding(num_embeddings=len(words), embedding_dim=4)
# 4. 获取每个词的下标索引. [0, 1, 2, 3, ....]
# enumerate(words): 返回 词汇表及其对应的下标形式, 即: (词的索引, 词)
for i, word in enumerate(words):
# i: 词对应的下标索引, word: 词, 例如: 0 -> 北京, 1 -> 东奥...
# print(f'{i} -> {word}')
# 5. 将词索引 转成 词向量. 细节: 要把i(词索引) 转成 tensor
word_vector = embed(torch.tensor([i]))
# 6. 输出结果.
print(f'{word} -> {i} -> {word_vector}')
rnn介绍
Wih 表示输入数据的权重
bih 表示输入数据的偏置
Whh 表示输入隐藏状态的权重
bhh 表示输入隐藏状态的偏置
ht-1 表示输入隐藏状态
ht 表示输出隐藏状态
最后对输出的结果使用 tanh 激活函数进行计算,得到该神经元你的输出隐藏状态。
首先初始化出第一个隐藏状态h0,一般都是全0的一个向量,然后将 "我" 进行词嵌入,转换为向量的表示形式,送入到第一个时间步,然后输出隐藏状态 h1,然后将 h1 和 "爱" 输入到第二个时间步,得到隐藏状态 h2, 将 h2 送入到全连接网络,得到 "你" 的预测概率
h0加权求和+本次录入加权求和经过tanh激活函数得到h1
上述公式中:
yt 是当前时刻的输出(通常是一个向量,表示当前时刻的预测值,RNN层的预测值
ht 是当前时刻的隐藏状态
Why 是从隐藏状态到输出的权重矩阵
by 是输出层的偏置项
隐藏状态用tanh,输出用softmax
词汇表映射:
输出yt是一个向量,该向量经过全连接层后输出得到最终预测结果Ypred,Ypred中每个元素代表当前时刻生成词汇表中某个词的得分(或概率,通过激活函数如softmax)。词汇表有多少个词,Ypred就有多少个元素值,最大元素值对应的词就是当前时刻预测生成的词。
代码实现
下面这个很重要
假如输入:每批32个句子,每个句子5个词,每个词128个维度
可推出
隐藏层层数=神经元个数(默认为一)
循环网络层
"""
RNN层解释:
概述:
它属于循环神经网络的 循环网络层, 目的是: 基于当前时刻的输入(x) 和 上一时刻的隐藏状态(ht-1) 推测出: 当前时刻的输出(y) 和 当前时刻的隐藏状态(ht)
API:
1. 创建 循环网络层对象(即: RNN对象)
rnn = nn.RNN(输入数据的维度, 隐藏层的维度, 隐藏层的层数 -> 默认是1)
2. 通过 RNN处理数据.
output, hn = rnn(x, h0)
"""
# 导包
import torch
import torch.nn as nn
# 在main函数中测试.
if __name__ == '__main__':
# 1.创建RNN层.
# 参1: 词向量维度(即: 输入的维度), 参2: 隐藏层的维度(即: 输出的维度), 参3: 隐藏层的层数, 默认是: 1
rnn = nn.RNN(input_size=128, hidden_size=256, num_layers=1)
# 2.定义变量, 记录: 输入数据.
# 参1: 每个句子的长度(词的个数), 参2: 批次大小(即: 句子的个数), 参3: 词向量维度(即: 输入的维度)
x = torch.randn(5, 32, 128)
# 3. 定义变量, 记录: 上一时刻(上一时间步)的隐藏状态.
# 参1: 隐藏层的层数, 参2: 批次大小, 参3: 隐藏层的维度(即: 输出的维度)
h0 = torch.randn(1, 32, 256)
# 4. 调用RNN层, 获取: 当前(本次)预测值 和 当前的隐藏状态h1
output, h1 = rnn(x, h0)
# 5. 输出结果.
print(f'x(本次的输入): {x.shape}, {x}') # shape: [5, 32, 128]
print(f'h0(上一时刻的隐藏状态): {h0.shape}, {h0}') # shape: [1, 32, 256]
print(f'h1(当前的隐藏状态): {h1.shape}, {h1}') # shape: [1, 32, 256]
print(f'output(本次的预测值): {output.shape}, {output}') # shape: [5, 32, 256]