首页 > 其他分享 >SamOut v3 发布-感叹转义词表能力太强【用em(voc_size=8000多,h)表达2000w 词汇 竟然还能,表达5000w词汇,怎一个愁字了得】

SamOut v3 发布-感叹转义词表能力太强【用em(voc_size=8000多,h)表达2000w 词汇 竟然还能,表达5000w词汇,怎一个愁字了得】

时间:2025-01-12 17:03:28浏览次数:3  
标签:词汇 表达 voc list 词表 len score voc1 net

项目地址

说明

  • v3 主要更换了sky-pile 数据集
  • v3 使用了转义词表技术,使得8000 多的em size 能够表达 2000 多w 的词表
  • v3 由于词表是使用jieaba 分词 ,自然在相同token_id 数量的情况下信息量更多(更多的字符)
  • v3 解码速度保持不变,同样训练消耗算力不变
  • v3 幻觉不变
  • v3 解码消耗显存不变
  • v3 上下文长度不变
  • v3 同样算力输出信息量更多(转义大词表的功劳)
  • v3 目前只是给词表扩为了2000 多倍,理论上该em size 能将词表 放大到该em size 的平方倍数
  • v3 目前没想到更好的能获得更大词表的方案,转义词表能力太强也有烦恼,感叹啊
  • v3 提供了转义词表技术的全流程用法,可以将其使用在其他模型上,要是太模型用上后估计 voc-size 就剩1024 大小了

推理代码展示


import torch

import pandas as pd
import polars as pl
import numpy as np
from jieba import lcut
from tqdm import tqdm

from infer_model import SamOut


def load_model_and_voc(device="cpu"):
    voc = pd.read_pickle("total_voc_new.pkl")["voc"]
    voc = ["<|sos|>", "<|user|>", "<|agent|>", "<|pad|>", "<|history|>", "<|unk|>", "<|end|>", "<|next|>"] + sorted(
        set(voc))
    voc_size = len(voc) - 8
    voc1 = pd.read_pickle("total_voc_new.pkl")["voc1"]
    voc1 = pd.DataFrame({"voc": voc1.keys(), "count": voc1.values()})
    voc1 = voc1[~voc1["voc"].isin(voc)]
    voc1 = voc1.sort_values("count", ascending=False)
    voc1["voc_id"] = np.array(list(range(len(voc1)))) % voc_size + 8
    voc1["voc_num"] = np.array(list(range(len(voc1)))) // voc_size + 9

    dl = pl.DataFrame(
        {"voc": voc + voc1["voc"].values.tolist(), "voc_id": list(range(len(voc))) + voc1["voc_id"].values.tolist(),
         "voc_num": [8] * len(voc) + voc1["voc_num"].values.tolist()})

    net = SamOut(len(voc), 1024 + 512, 64, 16)
    # net = SamOut(len(voc["voc"]), 512, 32, 8)
    print(sum([i.shape[0] * i.shape[1] for i in net.parameters() if len(i.shape) > 1]) + sum(
        [i.shape[0] for i in net.parameters() if len(i.shape) == 1]))

    # net.load_state_dict(torch.load("pretrain_768.pth", map_location=device))
    # net.load_state_dict(torch.load("pretrain_sft_single.pth", map_location=device))
    net.load_state_dict(torch.load("pretrain_sft_single_1024.pth", map_location=device))
    # net.load_state_dict(torch.load("pretrain.pth", map_location=device))
    net.to(device)
    net.eval()
    return net, dl


def gen_token(voc, voc_dict, model, prompt, max_len, rp=1.2, temp=0.13, top_k=16, device="cuda"):
    voc_list = pl.DataFrame({"voc": prompt}).join(voc, on="voc", how="left").to_numpy()
    prompt_list = voc_list[:, 1].tolist()
    print("agent:", end="", flush=True)
    model.to(device)
    current_voc = 8

    state = None
    for _ in tqdm(range(max_len)):
        # for _ in range(max_len):

        if state is None:

            out, state = model(torch.Tensor([prompt_list]).to(device).long())
        else:
            out, state = model(torch.Tensor([prompt_list[-1:]]).to(device).long(), state)

        out = out[:, -1:]
        # 重复抑制
        for token_id in enumerate(prompt_list):
            out[:, :, token_id] /= rp
        score = torch.softmax(out, -1)[0, 0]

        score, score_index = torch.sort(score, descending=True)
        if device == "cpu":

            score = score.detach().numpy()
            score_index = score_index.detach().numpy()
        else:
            score = score.cpu().detach().numpy()
            score_index = score_index.cpu().detach().numpy()
        score_sum = np.cumsum(score)

        score1 = score[score_sum < 0.9]
        if score1.size == 0:
            score = score[:1]
        else:
            score = score1

        score_index = score_index[:min(top_k, score.size)]

        out = score / temp

        v = out[:min(top_k, score.size)]
        # top  中限制词表大小方可 ok

        idx_next = torch.multinomial(torch.Tensor(v), num_samples=1, generator=None)
        idx_next = score_index[idx_next.item()]
        if prompt_list[-1] == 7:
            current_voc = idx_next
        if idx_next != 7:
            if idx_next == 6:
                break

            # out_item = voc["voc"].filter(
            #     voc["voc_id"].is_in([idx_next]) & voc["voc_num"].is_in([current_voc])).to_numpy().tolist()

            out_item = voc_dict.get("{}_{}".format(idx_next, current_voc))
            if len(out_item):
                prompt += [out_item[0]]
                prompt_list.append(idx_next)

        else:
            prompt += ["<|next|>"]
            prompt_list.append(7)
            continue
        if prompt_list[-1] == 7 or prompt_list[-2] == 7:
            continue

        print(prompt[-1], end="", flush=True)


def t_infre():
    model, voc = load_model_and_voc()
    voc_dict = {"{}_{}".format(k, v): i for i, k, v in voc.to_numpy().tolist()}

    while True:
        text = input("user:")

        gen_token(voc, voc_dict, model,
                  ["<|next|>"] + ["\x00"] + ["<|user|>"] + lcut("{}".format(text)) + ["<|agent|>"], 256)
        print()


if __name__ == '__main__':
    t_infre()

AI 代码解释

这段代码定义了一个基于PyTorch的文本生成模型,它使用了Pandas、Polars、NumPy、jieba和tqdm库来处理数据、分词以及展示进度条。下面我将逐步解析代码的功能,并解释各个部分的作用。

加载模型和词汇表

首先,load_model_and_voc函数负责加载预训练好的神经网络模型(SamOut)和词汇表。这里用到了Pandas读取并处理存储在文件中的词汇表,同时利用Polars创建一个新的DataFrame dl 来保存扩展后的词汇信息。此外,该函数还会实例化一个SamOut模型,并尝试加载预训练权重到这个模型中。最后,将模型设置为评估模式,并返回模型和词汇表的数据结构。

def load_model_and_voc(device="cpu"):
    # Load vocabulary from pickle file using pandas
    voc = pd.read_pickle("total_voc_new.pkl")["voc"]
    voc = ["<|sos|>", "<|user|>", "<|agent|>", "<|pad|>", "<|history|>", "<|unk|>", "<|end|>", "<|next|>"] + sorted(set(voc))
    voc_size = len(voc) - 8
    
    # Process additional vocabulary items with pandas
    voc1 = pd.read_pickle("total_voc_new.pkl")["voc1"]
    voc1 = pd.DataFrame({"voc": voc1.keys(), "count": voc1.values()})
    voc1 = voc1[~voc1["voc"].isin(voc)]
    voc1 = voc1.sort_values("count", ascending=False)
    voc1["voc_id"] = np.array(list(range(len(voc1)))) % voc_size + 8
    voc1["voc_num"] = np.array(list(range(len(voc1)))) // voc_size + 9

    # Create a Polars DataFrame for the final vocabulary
    dl = pl.DataFrame(
        {"voc": voc + voc1["voc"].values.tolist(),
         "voc_id": list(range(len(voc))) + voc1["voc_id"].values.tolist(),
         "voc_num": [8] * len(voc) + voc1["voc_num"].values.tolist()}
    )

    # Initialize the neural network model SamOut and load pre-trained weights
    net = SamOut(len(voc), 1024 + 512, 64, 16)
    print(sum([i.shape[0] * i.shape[1] for i in net.parameters() if len(i.shape) > 1]) + sum([i.shape[0] for i in net.parameters() if len(i.shape) == 1]))

    net.load_state_dict(torch.load("pretrain_sft_single_1024.pth", map_location=device))
    net.to(device)
    net.eval()
    return net, dl

生成token序列

接下来是gen_token函数,它的目的是根据给定的提示生成新的token序列。此过程中会用到之前加载的模型以及词汇表。每当需要生成下一个token时,就会调用模型预测最有可能出现的下一个字符或单词,并通过一些策略(如温度采样、top-k采样等)选择最终输出的token。为了显示进度,这里引入了tqdm库来构建一个进度条。

def gen_token(voc, voc_dict, model, prompt, max_len, rp=1.2, temp=0.13, top_k=16, device="cuda"):
    # Convert prompt into token IDs using Polars join operation
    voc_list = pl.DataFrame({"voc": prompt}).join(voc, on="voc", how="left").to_numpy()
    prompt_list = voc_list[:, 1].tolist()

    print("agent:", end="", flush=True)

    state = None
    for _ in tqdm(range(max_len)):
        ...

交互式推理

最后是t_infre函数,它提供了一个简单的命令行界面让用户输入文本,然后调用gen_token函数来生成回复。循环将持续直到用户终止程序。

def t_infre():
    model, voc = load_model_and_voc()
    voc_dict = {"{}_{}".format(k, v): i for i, k, v in voc.to_numpy().tolist()}

    while True:
        text = input("user:")
        gen_token(voc, voc_dict, model,
                  ["<|next|>"] + ["\x00"] + ["<|user|>"] + lcut("{}".format(text)) + ["<|agent|>"], 256)
        print()

综上所述,这段代码实现了一个可以与用户对话的系统,能够接收用户的输入并根据上下文生成相应的回应。它结合了深度学习模型与多种Python库,以确保高效的数据处理和良好的用户体验。特别是通过使用Polars代替传统的Pandas进行更高效的内存管理和更快的数据操作,以及利用tqdm库为长时间运行的任务添加了直观的进度反馈机制。

标签:词汇,表达,voc,list,词表,len,score,voc1,net
From: https://blog.csdn.net/weixin_32759777/article/details/145094018

相关文章

  • 怎样区分Angular表达式和JavaScript表达式?
    Angular表达式和JavaScript表达式在语法和功能上有一些相似之处,但也有一些关键的区别。以下是一些区分Angular表达式和JavaScript表达式的方法:语法和格式:Angular表达式:通常包含在双大括号{{}}中,用于将数据绑定到HTML。例如:{{expression}}。JavaScript表达式:在JavaScrip......
  • 集智书童 | 清华大学/NVIDIA/斯坦福等在没有3D数据的情况下训练一个开放词汇的单目3D
    本文来源公众号“集智书童”,仅用于学术分享,侵权删,干货满满。原文链接:清华大学/NVIDIA/斯坦福等在没有3D数据的情况下训练一个开放词汇的单目3D物体检测模型!最近,由于其在自动驾驶和机器人领域的广泛应用,无词汇3D目标检测受到了广泛关注,该方法旨在有效识别以前未见过的领域......
  • CodeNavi的表达式节点和属性详解
    CodeNavi是一种用于代码检查的规则语言,能够帮助开发者定义复杂的检查规则,以检测代码中的潜在问题和违反编码规范的地方。本文将深入解读CodeNavi的表达式节点和属性,详细介绍其结构和用法。一、表达式节点表达式节点是CodeNavi规则语言中的基本构造块,用于表示代码中的不同元素和......
  • 150. 逆波兰表达式求值
    [题目链接](150.逆波兰表达式求值-力扣(LeetCode))解题思路:用一个栈,遇到数字压进去,遇到运算符则计算后压入栈代码classSolution:defevalRPN(self,tokens:List[str])->int:stack=[]ans=0forsintokens:ifs==......
  • IT 行业充斥着自己的行话。以下是当今技术词汇中一些大多数常用词和术语的定义。IT 术
    IT术语表IT行业充斥着自己的行话。以下是当今技术词汇中一些大多数常用词和术语的定义。定义简单描述我们提供的服务什么是访问控制列表?访问控制列表是用于分配角色和职责的权限列表。用于CiscoASA监控的NetworkInsight什么是ActiveDirectory?Ac......
  • 对于Lambda表达式的一些理解
    Lambda表达式一、Lambda表达式Lambda表达式的基本语法: [capture](parameters)->return_type{body}capture(捕获列表):定义了哪些外部变量会被捕获并在lambda表达式内部使用。它可以按值或按引用捕获。parameters(参数列表):与普通函数的参数列表相似,定义了传递给l......
  • 掌握正则表达式:从入门到精通的实战指南
    文章目录......
  • 正则表达式笔记
    一、校验数字的表达式1数字:^[0-9]*$  2n位的数字:^\d{n}$  3至少n位的数字:^\d{n,}$  4m-n位的数字:^\d{m,n}$  5零和非零开头的数字:^(0|[1-9][0-9]*)$  6非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$  7带1-2位小数的正数或负数:^(......
  • ssm英语词汇量测试系统f43q5(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、研究背景与意义随着全球化和信息化的发展,英语已成为国际交流的重要工具。在学习英语的过程中,词汇量是衡量学习者水平的重要指标。然而,传统的手......
  • 正则表达式{}和(),pyhton里的正则表达式,函数findall解析
    前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦......