手撕embedding量化

 embedding默认存储类型是float32,4B。当文本量非常大的时候,其存储量和计算量都相当大。量化将float32数据转换为低精度的数据,int8或者二进制。

数据准备

 在量化前,先展示下原始数据的量级,包含形状和大小

import csv
import numpy as np
from typing import Literal
from sentence_transformers import SentenceTransformer
from sentence_transformers.quantization import quantize_embeddings

def calculate_data_storage_size(var):
    return var.dtype.itemsize * np.prod(var.shape)

model = SentenceTransformer("../../../DataCollection/officials/all-MiniLM-L6-v2",
                            device='cuda:7')

dataset_path = "../../../DataCollection/embedding_data/quora_duplicate_questions.tsv"
max_corpus_size = 500  # We limit our corpus to only the first 50k questions
corpus_sentences = set()
with open(dataset_path, encoding="utf8") as fIn:
    reader = csv.DictReader(fIn, delimiter="\t", quoting=csv.QUOTE_MINIMAL)
    for row in reader:
        corpus_sentences.add(row["question1"])
        corpus_sentences.add(row["question2"])
        if len(corpus_sentences) >= max_corpus_size:
            break
corpus_sentences = list(corpus_sentences)

# corpus_sentences = ["I am driving to the lake.", "It is a beautiful day."]

normal_embeddings = model.encode(corpus_sentences)
print(f'normal_embeddings shape: {normal_embeddings.shape}')
print(f'normal_embeddings size: {calculate_data_storage_size(normal_embeddings)}')

 输出如下,float32的存储大小为768000B

normal_embeddings shape: (500, 384)
normal_embeddings size: 768000

二进制量化 binary

指将嵌入向量中的 float32 值转换为 1 bit 值,从而使内存和存储使用量减少 32 倍。

这是sentence transformers的官方函数

embeddings_binary = quantize_embeddings(normal_embeddings, precision="binary")
print(f'embeddings_binary shape: {embeddings_binary.shape}')
print(f'embeddings_binary size: {calculate_data_storage_size(embeddings_binary)}')
embeddings_binary shape: (500, 48)
embeddings_binary size: 24000

这是手撕代码,只是以0为阈值转换为bit,再将bit拼成uint8,如果要返回int8则减去128

from typing import Literal

def to_binary(embeddings, type:Literal["binary", "ubinary"]="binary"):
    binary_mat 
### 动实现Transformer中的位置编码 #### 1. 原理概述 位置编码是一种用于向序列数据引入顺序信息的方法。由于Transformer模型本身不具有处理序列顺序的能力,因此需要显式地加入位置信息以便于模型能够区分不同位置上的输入[^1]。 位置编码的核心思想是为每个词的位置分配一组唯一的数值表示,并将其与词嵌入相加作为最终的输入。这种编码可以采用固定的方式预先计算好,也可以通过可学习参数动态调整。 #### 2. 数学表达 对于长度为 `L` 的序列和维度大小为 `d_model` 的嵌入空间,位置编码可以通过如下公式定义: \[ PE_{(pos, 2i)} = \sin(pos / 10000^{2i/d_{model}}) \] \[ PE_{(pos, 2i+1)} = \cos(pos / 10000^{2i/d_{model}}) \] 其中: - \( pos \) 表示单词在序列中的绝对位置; - \( i \) 是嵌入向量的维度索引; - \( d_{model} \) 是嵌入层的总维度。 该方法利用正弦函数和余弦函数的不同频率特性来捕捉相对距离的信息[^4]。 #### 3. 实现代码 以下是基于PyTorch的一个简单实现例子,展示如何构建并应用位置编码: ```python import torch import math class PositionalEncoding(torch.nn.Module): def __init__(self, d_model: int, max_len: int = 5000): super().__init__() position = torch.arange(max_len).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model)) pe = torch.zeros(max_len, 1, d_model) pe[:, 0, 0::2] = torch.sin(position * div_term) pe[:, 0, 1::2] = torch.cos(position * div_term) self.register_buffer('pe', pe) def forward(self, x: torch.Tensor) -> torch.Tensor: """ Args: x: Tensor, shape [seq_len, batch_size, embedding_dim] """ seq_len = x.size(0) x = x + self.pe[:seq_len] return x ``` 上述代码中,我们创建了一个名为 `PositionalEncoding` 的类继承自 `torch.nn.Module` 。它初始化时会生成一个最大长度为 `max_len` 的位置编码矩阵,并存储起来供后续调用[^2]。 #### 4. 使用说明 要使用此模块,只需实例化对象并将您的输入张量传递给它的前馈方法即可。例如: ```python # 设定超参 embedding_dim = 512 sequence_length = 10 batch_size = 32 # 创建随机输入 input_tensor = torch.randn(sequence_length, batch_size, embedding_dim) # 初始化位置编码器 position_encoder = PositionalEncoding(d_model=embedding_dim) # 添加位置编码 output_with_position_encoding = position_encoder(input_tensor) print(output_with_position_encoding.shape) # 输出应保持原形状不变 ``` 这将返回一个新的张量,其包含了原始输入加上相应位置编码后的结果。 --- #### 总结 以上就是关于Transformer模型中位置编码的基本原理及其Python实现方式。这种方法不仅适用于自然语言处理领域,在其他涉及时间序列建模的任务上也有广泛应用价值[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值