聊聊语言模型transformer
通常语言模型是用来预测一段文本序列的下一个词或句子的概率分布的模型。计算概率是语言模型的核心任务之一,因为语言模型需要根据历史文本序列来预测下一个词的概率。通过计算每个可能的下一个词的概率,语言模型可以选择最可能的词作为预测结果。计算概率密切相关的是词嵌入(embedding)技术。词嵌入是将词语映射到低维稠密向量空间的技术,可以将词语之间的语义和语法信息编码为向量表示。在语言模型中,词嵌入可以帮助模型更好地理解词语之间的关系,从而提高模型的预测准确性。
Transformer是一种基于注意力机制的深度学习模型,最初由Google提出用于自然语言处理任务。它在处理序列数据时表现出色,特别适用于机器翻译、文本生成和语言建模等任务。Transformer模型的核心是自注意力机制(self-attention),它能够在输入语言序列中的每个位置上计算注意力权重,从而捕捉输入序列中不同位置之间的依赖关系。
详细介绍transformer的模型结构
Transformer是一种基于注意力机制的深度学习模型。Transformer模型结构主要包括编码器(Encoder)和解码器(Decoder)两部分。而编码器喝解码器都是包涵多个相同的层。Encoder的输出是一个包含输入序列信息的上下文向量,Decoder的输出的也是一个包含输出序列信息的上下文向量。
编码器(Encoder): 编码器由多个相同的层堆叠而成,每个层包括两个子层:
多头自注意力机制(Multi-Head Self-Attention):通过计算输入序列中每个位置的注意力权重,使模型能够关注输入序列中不同位置之间的依赖关系。
前馈神经网络(Feed-Forward Neural Network):对每个位置的隐藏表示进行线性变换和激活函数处理,从而学习位置之间的非线性关系。
解码器(Decoder): 解码器也由多个相同的层堆叠而成,每个层包括三个子层:
多头自注意力机制(Multi-Head Self-Attention):与编码器中的自注意力机制类似,但在解码器中需要避免未来信息泄露,因此在计算注意力权重时需要屏蔽未来位置的信息。
编码器-解码器注意力机制(Encoder-Decoder Attention):将编码器的输出作为查询向量,解码器的自注意力输出作为键值对,计算解码器每个位置对编码器输出的注意力权重。
前馈神经网络(Feed-Forward Neural Network):与编码器中的前馈神经网络相同。
在训练过程中,Transformer模型通过最小化损失函数(如交叉熵损失)来优化模型参数,使模型能够更好地学习输入序列和输出序列之间的对应关系。在推理过程中,解码器通过贪婪搜索或束搜索等方法生成输出序列。
总的来说,Transformer模型结构的创新之处在于引入了自注意力机制和位置编码,使得模型能够更好地处理长距离依赖关系和位置信息,从而在自然语言处理任务中取得了很好的效果。
自注意力的计算详情大家可以参考我附在后面的论文地址。我们show一些code来实践以下模型。这段代码实现了一个简单的情感分类任务,使用了一个包含两个Transformer block的Transformer模型。代码架构设计模型在训练集上进行了训练,并在测试集上进行了评估。
# code using pytorch
import torch
import torch.nn as nn
import torch.optim as optim
import torchtext
from torchtext.data.utils import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator
from torchtext.datasets import AG_NEWS
from torchtext.data.utils import get_tokenizer
from torchtext.vocab import Vocab
from torchtext.data.functional import to_map_style_dataset
# 定义Transformer block
class TransformerBlock(nn.Module):
def __init__(self, input_dim, hidden_dim, num_heads, feedforward_dim, dropout):
super(TransformerBlock, self).__init__()
self.attention = nn.MultiheadAttention(input_dim, num_heads, dropout=dropout)
self.norm1 = nn.LayerNorm(input_dim)
self.feedforward = nn.Sequential(
nn.Linear(input_dim, feedforward_dim),
nn.ReLU(),
nn.Linear(feedforward_dim, input_dim)
)
self.norm2 = nn.LayerNorm(input_dim)
self.dropout = nn.Dropout(dropout)
def forward(self, x):
x = x + self.dropout(self.attention(x, x, x)[0])
x = self.norm1(x)
x = x + self.dropout(self.feedforward(x))
x = self.norm2(x)
return x
# 定义Transformer模型
class Transformer(nn.Module):
def __init__(self, vocab_size, embedding_dim, num_classes, num_layers, hidden_dim, num_heads, feedforward_dim, dropout):
super(Transformer, self).__init__()
self.embedding = nn.Embedding(vocab_size, embedding_dim)
self.transformer_blocks = nn.ModuleList([
TransformerBlock(embedding_dim, hidden_dim, num_heads, feedforward_dim, dropout) for _ in range(num_layers)
])
self.fc = nn.Linear(embedding_dim, num_classes)
def forward(self, x):
x = self.embedding(x)
for transformer_block in self.transformer_blocks:
x = transformer_block(x)
x = x.mean(dim=1)
x = self.fc(x)
return x
# 数据预处理
tokenizer = get_tokenizer("basic_english")
train_iter = AG_NEWS(split='train')
vocab = build_vocab_from_iterator(map(tokenizer, train_iter), specials=["<unk>"])
vocab.set_default_index(vocab["<unk>"])
def collate_batch(batch):
label = torch.tensor([entry[0] for entry in batch])
text = [entry[1] for entry in batch]
text = [torch.tensor([vocab[token] for token in tokenizer(entry)]) for entry in text]
text = nn.utils.rnn.pad_sequence(text, padding_value=vocab["<pad>"])
return label, text
train_iter = AG_NEWS(split='train')
train_dataset = to_map_style_dataset(train_iter)
train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True, collate_fn=collate_batch)
# 训练模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = Transformer(len(vocab), 128, 4, 2, 256, 8, 512, 0.1).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(5):
model.train()
for i, (label, text) in enumerate(train_dataloader):
label, text = label.to(device), text.to(device)
optimizer.zero_grad()
output = model(text)
loss = criterion(output, label)
loss.backward()
optimizer.step()
if i % 100 == 0:
print(f"Epoch {epoch}, Iteration {i}, Loss: {loss.item()}")
# 测试模型
test_iter = AG_NEWS(split='test')
test_dataset = to_map_style_dataset(test_iter)
test_dataloader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=False, collate_fn=collate_batch)
model.eval()
correct = 0
total = 0
with torch.no_grad():
for label, text in test_dataloader:
label, text = label.to(device), text.to(device)
output = model(text)
_, predicted = torch.max(output, 1)
total += label.size(0)
correct += (predicted == label).sum().item()
print(f"Accuracy: {100 * correct / total}%")
推荐几个link
尝试:http://boxes.box.devops-link.online/similarities
Transformer官方论文:https://arxiv.org/abs/1706.03762
Transformer代码实现:https://github.com/tensorflow/tensor2tensor