赞
踩
- import torch
- import torch.nn as nn
- import torch.optim as optim
-
- # 定义全连接层
- fc = nn.Linear(10, 5) # 输入大小为10,输出大小为5
-
- # 定义损失函数
- criterion = nn.MSELoss()
-
- # 定义优化器
- optimizer = optim.SGD(fc.parameters(), lr=0.01)
-
- # 循环进行训练
- for epoch in range(num_epochs):
- # 前向传播
- output = fc(input_data)
-
- # 计算损失
- loss = criterion(output, target_data)
-
- # 反向传播
- optimizer.zero_grad()
- loss.backward()
-
- # 更新参数
- optimizer.step()
nn.Module
主要有以下用途:
定义神经网络的层:nn.Module
包含了很多常用的神经网络层,如全连接层、卷积层、池化层等。我们可以通过继承nn.Module
来自定义新的神经网络层,并将其组合成一个完整的神经网络模型。
管理模型的参数:nn.Module
可以跟踪并管理模型的所有参数,使得我们可以方便地进行参数更新和保存。
提供其他工具函数:nn.Module
还提供了一些其他的工具函数,如dropout、batch normalization等,以及一些辅助函数,如计算参数数量、移动模型到GPU等。
- import torch.nn as nn
- """
- 定义了一个Net类,并将nn.Module作为其父类。
- Net类包含了两个卷积层、三个全连接层和一个池化层。
- 在__init__()方法中,我们定义了所有的层,并将它们保存到模型的属性中。
- 在forward()方法中,我们定义了输入数据向前传播的过程。
- 当我们需要训练或测试模型时,只需要像调用普通函数一样调用该模型即可。
- """
- class Net(nn.Module):
- def __init__(self):
- super(Net, self).__init__()
- self.conv1 = nn.Conv2d(3, 6, 5)
- self.pool = nn.MaxPool2d(2, 2)
- self.conv2 = nn.Conv2d(6, 16, 5)
- self.fc1 = nn.Linear(16 * 5 * 5, 120)
- self.fc2 = nn.Linear(120, 84)
- self.fc3 = nn.Linear(84, 10)
-
- def forward(self, x):
- x = self.pool(F.relu(self.conv1(x)))
- x = self.pool(F.relu(self.conv2(x)))
- x = x.view(-1, 16 * 5 * 5)
- x = F.relu(self.fc1(x))
- x = F.relu(self.fc2(x))
- x = self.fc3(x)
- return x
链接:https://zhuanlan.zhihu.com/p/649756898
首先在了解Llama 2模型结构细节之前,我们先来看一看大语言模型通常的处理流程:
输入数据:LLM的输入数据是一段文本,可以是一个句子或一段话。文本通常被表示成单词或字符的序列。
[君不见黄河之水天上来,奔流到海不复回。君不见高堂明镜悲白发,朝如青丝暮成雪。...五花马、千金裘,呼儿将出换美酒,与尔同销万古愁]
Tokenization:之后需要将文本进行Tokenization,将其切分成单词或字符,形成Token序列。之后再将文本映射成模型可理解的输入形式,将文本序列转换为整数索引序列(这个索引就是单词或字符在语料库中的index),这个过程通常由一些开源的文本Tokenzier工具,如sentencepiece等来处理
- 序列化->
- ['BOS','君','不','见','黄','河','之','水','天','上','来',',' ,'奔','流','到'...'与','尔','同','销','万','古','愁','EOS']
-
- 假设语料库索引化->
- ['BOS','10','3','67','89','21','45','55','61','4','324','565' ,'789','6567','786'...'7869','9','3452','563','56','66','77','EOS']
Embedding:文本信息经过Tokenization之后变成了token序列,而Embedding则继续将每个Token映射为一个实数向量,为Embeding Vector
- 'BOS'-> [p_{00},p_{01},p_{02},...,p_{0d-1}]
- '10' -> [p_{10},p_{11},p_{12},...,p_{1d-1}]
- '3' -> [p_{20},p_{21},p_{22},...,p_{2d-1}]
- ...
- 'EOS'-> [p_{n0},p_{n1},p_{n2},...,p_{nd-1}]
位置编码:对于Token序列中的每个位置,添加位置编码(Positional Encoding)向量,以提供关于Token在序列中位置的信息。位置编码是为了区分不同位置的Token,并为模型提供上下文关系的信息。
- [p_{00},p_{01},p_{02},...,p_{0d-1}] [pe_{00},pe_{01},pe_{02},...,pe_{0d-1}]
- [p_{10},p_{11},p_{12},...,p_{1d-1}] [pe_{10},pe_{11},pe_{12},...,pe_{1d-1}]
- [p_{20},p_{21},p_{22},...,p_{2d-1}] + [pe_{20},pe_{21},pe_{22},...,pe_{2d-1}]
- ... ...
- [p_{n0},p_{n1},p_{n2},...,p_{nd-1}] [pe_{n0},pe_{n1},pe_{n2} ,...,pe_{nd-1}]
Transformer :在生成任务中,模型只需要用到Transformer 的decoder阶段,即Decoder-Only,比如GPT、LLaMA 都是。
自回归生成:在生成任务中,使用自回归(Autoregressive)方式,即逐个生成输出序列中的每个Token。在解码过程中,每次生成一个Token时,使用前面已生成的内容作为上下文,来帮助预测下一个Token。
输出处理:生成的Token序列通过一个输出层,通常是线性变换加上Softmax函数,将每个位置的概率分布转换为对应Token的概率。根据概率,选择概率最高的Token或者作为模型的预测结果。或者其他的的方法生成next token
在llama2模型中,当设置output_hidden_states=True
时,模型会返回每一层的隐藏状态。这些隐藏状态被称为"hidden_states"。
hidden_states[1:]
表示从第二层开始的所有隐藏状态。通常,索引0的隐藏状态是输入层的隐藏状态,而后续的隐藏状态对应于模型中的不同层。
每个隐藏状态是一个张量(tensor),可以看作是一个多维数组。其中,第一个维度表示批次大小(batch size),第二个维度表示输入序列长度(token sequence length),而剩余的维度则表示隐藏状态的维度。
以下是一个示例,假设我们使用llama2模型处理一个批次大小为2、输入序列长度为5的文本:
- hidden_states = [
- # 第一层隐藏状态(输入层)
- tensor([[[0.1, 0.2, 0.3, ...], # 第1个token的隐藏状态
- [0.4, 0.5, 0.6, ...], # 第2个token的隐藏状态
- ...
- [0.7, 0.8, 0.9, ...]], # 第5个token的隐藏状态
-
- [[0.2, 0.3, 0.4, ...], # 第1个token的隐藏状态
- [0.5, 0.6, 0.7, ...], # 第2个token的隐藏状态
- ...
- [0.8, 0.9, 1.0, ...]]]),# 第5个token的隐藏状态
-
- # 第二层隐藏状态
- tensor([[[0.2, 0.3, 0.4, ...],
- [0.5, 0.6, 0.7, ...],
- ...
- [0.8, 0.9, 1.0, ...]],
-
- [[0.3, 0.4, 0.5, ...],
- [0.6, 0.7, 0.8, ...],
- ...
- [0.9, 1.0, 1.1, ...]]]),
-
- # 其他层隐藏状态...
- ]
hidden_states[0]
表示输入层的隐藏状态,hidden_states[1]
表示第一层隐藏状态,以此类推。每个隐藏状态都是一个形状为(2, 5, d)
的张量,其中d
表示隐藏状态的维度。
- import numpy as np
-
- class FeedForwardNetwork:
- def __init__(self, input_size, hidden_size, output_size):
- self.weights1 = np.random.randn(input_size, hidden_size)
- self.bias1 = np.zeros(hidden_size)
- self.weights2 = np.random.randn(hidden_size, output_size)
- self.bias2 = np.zeros(output_size)
- def forward(self, x):
- self.hidden_output = np.dot(x, self.weights1) + self.bias1
- self.hidden_activation = self._sigmoid(self.hidden_output)
-
- output = np.dot(self.hidden_activation, self.weights2) + self.bias2
- return output
-
- def _sigmoid(self, x):
- return 1 / (1 + np.exp(-x))
-
- X = np.array([[0, 0,1], [0, 1,1], [1, 0,1], [1, 1,1]])
- y = np.array([[0], [1], [1], [0]])
-
- # 创建神经网络
- network = FeedForwardNetwork(input_size=3, hidden_size=2, output_size=2)
- print(network.weights1)
- print(network.weights2)
- print(network.bias1)
- # 训练参数设置
- epochs = 100
- learning_rate = 0.1
-
- for epoch in range(epochs):
- # 前向传播
- output = network.forward(X)
- print("hidden_activation:",network.hidden_activation)
- # 计算损失
- loss = np.mean((output - y) ** 2)
-
- # 打印损失
- if epoch % 100 == 0:
- print(f"Epoch {epoch}: Loss = {loss}")
-
- # 反向传播更新权重和偏置
- d_loss = 2 * (output - y)
- d_activation = network._sigmoid(output) * (1 - network._sigmoid(output))
- d_output = d_loss * d_activation
-
- d_weights2 = np.dot(network.hidden_activation.T, d_output)
- d_bias2 = np.sum(d_output, axis=0)
-
- d_hidden = np.dot(d_output, network.weights2.T)
- d_hidden_activation = network._sigmoid(network.hidden_output) * (1 - network._sigmoid(network.hidden_output))
- d_hidden_output = d_hidden * d_hidden_activation
-
- d_weights1 = np.dot(X.T, d_hidden_output)
- d_bias1 = np.sum(d_hidden_output, axis=0)
-
- network.weights2 -= learning_rate * d_weights2
- network.bias2 -= learning_rate * d_bias2
-
- network.weights1 -= learning_rate * d_weights1
- network.bias1 -= learning_rate * d_bias1
- # 预测
- output = network.forward(X)
- print("Predictions:", output)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。