多模态大语言模型中的基础学习记录

1.训练一个线性投影层

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()

2 nn.module类

nn.Module主要有以下用途:

  1. 定义神经网络的层:nn.Module包含了很多常用的神经网络层,如全连接层、卷积层、池化层等。我们可以通过继承nn.Module来自定义新的神经网络层,并将其组合成一个完整的神经网络模型。

  2. 管理模型的参数:nn.Module可以跟踪并管理模型的所有参数,使得我们可以方便地进行参数更新和保存。

  3. 提供其他工具函数: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
    

3 llama模型

链接:https://zhuanlan.zhihu.com/p/649756898

1 处理流程

首先在了解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表示隐藏状态的维度。

4 FeedForward实现训练

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)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值