当前位置: 首页 > news >正文

Hugging face Transformers(3)—— Tokenizer

  • Hugging Face 是一家在 NLP 和 AI 领域具有重要影响力的科技公司,他们的开源工具和社区建设为NLP研究和开发提供了强大的支持。它们拥有当前最活跃、最受关注、影响力最大的 NLP 社区,最新最强的 NLP 模型大多在这里发布和开源。该社区也提供了丰富的教程、文档和示例代码,帮助用户快速上手并深入理解各类 Transformer 模型和 NLP 技术
  • Transformers 库是 Hugging Face 最著名的贡献之一,它最初是 Transformer 模型的 pytorch 复现库,随着不断建设,至今已经成为 NLP 领域最重要,影响最大的基础设施之一。该库提供了大量预训练的模型,涵盖了多种语言和任务,成为当今大模型工程实现的主流标准,换句话说,如果你正在开发一个大模型,那么按 Transformer 库的代码格式进行工程实现、将 check point 打包成 hugging face 格式开源到社区,对于推广你的工作有很大的助力作用。本系列文章将介绍 Transformers库 的基本使用方法
  • 前文:Hugging face Transformers(2)—— Pipeline

文章目录

  • 1. Tokenizer 及其基本使用
    • 1.1 保存与加载
    • 1.2 句子分词
    • 1.3 索引转换
    • 1.4 截断和填充
    • 1.5 附加输入信息
    • 1.6 处理 batch 数据
  • 2. Fast/Slow Tokenizer
  • 3. 加载特殊 Tokenizer

1. Tokenizer 及其基本使用

  • Tokenizer 是将原始字符串转换为模型可以计算的数值形式(通常是 token IDs)的工具。不同的模型可能需要不同的 tokenizer,因为不同的预训练任务和数据集可能会导致不同的词汇表(vocabulary)和 tokenization 策略。
  • Tokenizer 用于数据预处理,其作用包括
    1. 分词:使用分词器对文本数据进行分词 (字、字词)
    2. 构建词典:根据数据集分词的结果,构建词典映射 (这步并不绝对,如果采用预训练词向量,词典映射要根据词向量文件进行处理)
    3. 数据转换:根据构建好的词典,将分词处理后的数据做映射,将文本序列转换为数字序列。其中可能涉及添加特殊标记(如 [CLS][SEP][MASK] 等),以便模型能够识别文本的不同部分或执行特定的任务(如分类、问答等)
    4. 数据填充与截断:在以batch输入到模型的方式中,需要对过短的数据进行填充,过长的数据进行截断,保证数据长度符合模型能接受的范围,同时batch内的数据维度大小一致

1.1 保存与加载

  • 如前文 Hugging face Transformers(2)—— Pipeline 3.2 节所述,可以用 AutoTokenizer 自动类,从模型地址直接识别、创建并初始化所需的 tokenizer 对象。这里我们还是使用前文的中文情感分类模型的 tokenizer
    # AutoTokenizer 包可以根据传入的参数(如模型名)自动判断所需的 tokenizer
    from transformers import AutoTokenizer# 样例字符串
    sen = "这是一段测试文本"# 从 hugging face 加载,输入模型名称即可加载对应的分词器
    tokenizer = AutoTokenizer.from_pretrained("uer/roberta-base-finetuned-dianping-chinese")
    tokenizer
    
    BertTokenizerFast(name_or_path='uer/roberta-base-finetuned-dianping-chinese', vocab_size=21128, model_max_length=1000000000000000019884624838656, is_fast=True, padding_side='right', truncation_side='right', special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}, clean_up_tokenization_spaces=True),  added_tokens_decoder={0: AddedToken("[PAD]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),100: AddedToken("[UNK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),101: AddedToken("[CLS]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),102: AddedToken("[SEP]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),103: AddedToken("[MASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
    }
    
    从打印信息可见,这是一个 BERT 模型的 Tokenizer,其中有五个特殊符号,在右侧进行填充或截断…
  • 第一次创建 Tokenizer 对象时,词表等相关配置文件会下载并保存至默认路径 C:\Users\username\.cache\huggingface\hub,之后会默认从此处重新加载。可以将构造的 tokenizer 对象手动保存到指定路径,并从指定路径加载
    # 自动下载的 model 和 tokenizer 等组件位于 C:\Users\username\.cache\huggingface\hub 中
    # 可以把 tokenizer 单独保存到指定路径
    tokenizer.save_pretrained("./roberta_tokenizer")# 可以从本地加载保存的 tokenizer
    tokenizer = AutoTokenizer.from_pretrained("./roberta_tokenizer")
    

1.2 句子分词

  • Tokenizer 工作的第一步是文本分割,即将原始输入字符串拆开成一系列字符、词、字节码或短句(称之为token。在中文自然语言处理中,分词尤为重要,因为中文的词与词之间没有空格这样明显的分隔符。

  • 根据分词方法不同,对应的词表也会有所区别。一般而言,较大的词表可以包含更多的词汇,有助于模型更好地理解和表达文本,提高模型性能,增强泛化能力。然而,随着词表尺寸的增加,模型的计算复杂度和内存需求也会相应增加。可以通过 Tokenizer 对象的 .vocab 属性查看词表

    tokenizer.vocab
    
    {'##净': 14169,'ま': 567,'##copyright': 13291,'疡': 4550,'抢': 2843,'枇': 3355,'##尘': 15269,'贺': 6590,'ne': 10564,'庸': 2435,'##馬': 20736,'臾': 5640,'勖': 1241,'##粱': 18175,'##⒋': 13574,'褥': 6191,'doc': 9656,'釁': 7022,'alex': 10179,'##フト': 10868,'屹': 2256,'yumi': 11697,'##nne': 12866,'莫': 5811,'816': 10937,
    ...'##躍': 19770,'皺': 4653,'##ろ': 10460,'##孪': 15169,...}
    
  • Transformers 库的 tokenizer 支持传入原始字符串或原始字符串列表,如下所示

    tokens = tokenizer.tokenize(sen)
    print(tokens)   # ['这', '是', '一', '段', '测', '试', '文', '本']tokens = tokenizer.tokenize([sen, sen])
    print(tokens)   # ['这', '是', '一', '段', '测', '试', '文', '本', '这', '是', '一', '段', '测', '试', '文', '本']
    

1.3 索引转换

  • 只进行分词,得到的还是一些字符串和字符对象,还需要进行一步索引转换才能变成可计算的数值数据。所谓索引转换,其实就是把分词结果一一替换为词表中的索引(称之为 token id),之后在做 embedding 的时候,这些 id 会先转换为 one-hot 向量,再通过线性层投影到嵌入空间(也称为 lookup table 操作),此后就可以在隐空间向量上进行注意力计算了
  • 结合 1.2 节的分词和索引转换,完整的 tokenize 过程如下
    # Tokenize流程:原始字符串 -> token 序列 -> id 序列
    tokens = tokenizer.tokenize(sen)
    ids = tokenizer.convert_tokens_to_ids(tokens)
    print(ids)		# [6821, 3221, 671, 3667, 3844, 6407, 3152, 3315]# 也可以逆向操作:id 序列-> token 序列
    tokens = tokenizer.convert_ids_to_tokens(ids)
    print(tokens)	# ['这', '是', '一', '段', '测', '试', '文', '本']# 也可以逆向操作:token 序列 -> 字符串
    str_sen = tokenizer.convert_tokens_to_string(tokens)
    print(str_sen)	# 这 是 一 段 测 试 文 本
    
  • Transformers 库还提供称为 “编码” 和 “解法” 的简便方法,实现从原始字符串到 id 序列相互转换的一步操作
    # “编码”: 原始字符串 -> id 序列
    ids = tokenizer.encode(sen, add_special_tokens=True)        # add_special_tokens 在 tokenize 时序列设置特殊 token
    print(ids)                                                  # 注意到首尾多了特殊 token [CLS](101) 和 [SEP](102)
    # “解码”:id 序列 -> 原始字符串
    str_sen = tokenizer.decode(ids, skip_special_tokens=False)  # skip_special_tokens 可以跳过可能存在的特殊 token
    print(str_sen)
    str_sen = tokenizer.decode(ids, skip_special_tokens=True)
    print(str_sen)'''
    [101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102]
    [CLS] 这 是 一 段 测 试 文 本 [SEP]
    这 是 一 段 测 试 文 本
    '''
    
    注意,在 encode 方法传入 add_special_tokens 参数;在 decode 方法传入 skip_special_tokens 参数,可以控制特殊 token 的引入和跳过

1.4 截断和填充

  • 通常使用 batch 形式训练 Transformer 类模型,这要求我们把序列数据长度全部处理成和模型输入一致的状态。为此,需要进行截断或填充操作
    # 填充
    ids = tokenizer.encode(sen, padding="max_length", max_length=15)
    print(ids)  # [101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102, 0, 0, 0, 0, 0]# 截断
    ids = tokenizer.encode(sen, max_length=5, truncation=True)
    print(ids)  # [101, 6821, 3221, 671, 102]
    ids = tokenizer.encode(sen, max_length=5, truncation=False)	# 禁止截断则正常做 tokenize
    print(ids)  # [101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102]
    
  • 如上所示,通过在 encode 方法传入 max_length 参数控制最终序列长度,通过 padding 参数控制填充类型。注意到该 tokenizer 是在右侧进行 zero-padding 的,该设置可以在 1.1 节的 tokenizer 信息中观察到。另外,可以通过 truncation 参数控制是否截断

1.5 附加输入信息

  • 通常,Transformer 类模型的前向过程不止需要 token id,还需要各个 token id 的一些附加信息。比如在 BERT 的上下句预训练任务中,需要明确各个 token 所属的上下句信息;还需要 attention_mask 遮盖 zero padding 的部分,这些信息我们可以手动构造
    ids = tokenizer.encode(sen, padding="max_length", max_length=15)# 除 token 外,Transformer 类模型的输入往往还有一些附加信息
    attention_mask = [1 if idx != 0 else 0 for idx in ids]  # attention_mask 用于遮盖 zero padding 部分
    token_type_ids = [0] * len(ids)                         # bert 有一个判断上下句任务,模型预训练时需要 token 所属句子 id 信息
    ids, attention_mask, token_type_ids
    
    ([101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102, 0, 0, 0, 0, 0],[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
    
  • Transformers 库中,这些附件信息的生成方法被集成到 tokenizer 的实现中,通过 tokenizer.encode_plus() 方法或直接 tokenizer() 形式调用
    # 附加信息无需手动编写,tokenizer 中已经提供
    inputs = tokenizer.encode_plus(sen, padding="max_length", max_length=15)
    print(inputs)	# {'input_ids': [101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102, 0, 0, 0, 0, 0], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]}# 另一种调用方法
    inputs = tokenizer(sen, padding="max_length", max_length=15)
    print(inputs)	# {'input_ids': [101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102, 0, 0, 0, 0, 0], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]}
    

1.6 处理 batch 数据

  • 前文 1.2 节提到过,tokenizer 支持字符串和字符串列表形式的输入,其中后者是为了 batch 数据而专门设计的,可以有效提高 tokenize 效率。基本使用如下

    sens = ["AABBCCDDEEFF","哈哈哈哈哈哈哈哈哈哈哈","你好你好你好你好"
    ]
    res = tokenizer(sens)	# batch tokenize 不要求各原始字符串长度一致
    res
    
    {'input_ids': [[101, 9563, 10214, 8860, 9879, 8854, 9049, 102], [101, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 102], [101, 872, 1962, 872, 1962, 872, 1962, 872, 1962, 102]], 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]}
    
  • 对比单条操作+循环和成批量操作的时间消耗

    %%time
    # 单条循环处理,慢
    for i in range(1000):tokenizer(sen)'''
    CPU times: total: 172 ms
    Wall time: 242 ms
    '''
    
    %%time
    # 成 batch 批量计算,快
    tokenizer([sen] * 1000)'''
    CPU times: total: 78.1 ms
    Wall time: 27.9 ms
    '''
    

2. Fast/Slow Tokenizer

  • Transformer 库提供了两种 tokenizer

    1. FastTokenizer: 基于 Rust 实现,速度快,可以提供更多附加信息,类型名有后缀 Fast
    2. SlowTokenizer: 基于 python 实现,速度慢
  • 直接创建的 Tokenizer,如果存在 Fast 类型,则默认都是 Fast 类型

    sen = "快慢Tokenizer测试"
    fast_tokenizer = AutoTokenizer.from_pretrained("uer/roberta-base-finetuned-dianping-chinese")
    fast_tokenizer # 类型名有后缀 Fast
    
    BertTokenizerFast(name_or_path='uer/roberta-base-finetuned-dianping-chinese', vocab_size=21128, model_max_length=1000000000000000019884624838656, is_fast=True, padding_side='right', truncation_side='right', special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}, clean_up_tokenization_spaces=True),  added_tokens_decoder={0: AddedToken("[PAD]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),100: AddedToken("[UNK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),101: AddedToken("[CLS]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),102: AddedToken("[SEP]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),103: AddedToken("[MASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
    }
    
  • 构造 Tokenizer 时,可以通过传入 use_fast=False 强制构造 Slow Tokenizer

    # 设置 use_fast=False 来构造 SlowTokenizer
    slow_tokenizer = AutoTokenizer.from_pretrained("uer/roberta-base-finetuned-dianping-chinese", use_fast=False)
    slow_tokenizer # 类型名无后缀 Fast
    
    BertTokenizer(name_or_path='uer/roberta-base-finetuned-dianping-chinese', vocab_size=21128, model_max_length=1000000000000000019884624838656, is_fast=False, padding_side='right', truncation_side='right', special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}, clean_up_tokenization_spaces=True),  added_tokens_decoder={0: AddedToken("[PAD]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),100: AddedToken("[UNK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),101: AddedToken("[CLS]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),102: AddedToken("[SEP]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),103: AddedToken("[MASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
    }
    

    注意到 Tokenizer 对象类型名没有 Fast 后缀了。两种 Tokenizer 具有明显的速度差距

    %%time
    fast_tokenizer([sen] * 10000)'''
    CPU times: total: 1.02 s
    Wall time: 349 ms
    '''
    
    %%time
    slow_tokenizer([sen] * 10000)'''
    CPU times: total: 2.89 s
    Wall time: 3.05 s
    '''
    
  • Fast Tokenizer 有时会返回一些额外信息,例如有时候原始输入字符串中的英文不会按字母分词,而是按词根词缀分词,这时相应的 token 会对应到原始字符串中的一个索引区域,Fast Tokenizer 可以通过设置 return_offsets_mapping=True 获取 token 和原始索引区域的对应信息

    sen = "快慢Tokenizer测试"
    inputs = fast_tokenizer(sen, return_offsets_mapping=True) # (只有 FastTokenizer 可以设置 return_offsets_mapping=True)
    print(sen)                       # 打印原始字符串
    print(inputs.word_ids())         # 打印各个 token 对应到原始字符串的 “词索引”,注意到原始字符串中 ”Tokenizer“ 这个词被拆成了4个token (只有 FastTokenizer 可以调用这个)
    print(inputs['offset_mapping'])  # offset_mapping 指示了各个 token 对应的原始字符串索引区域
    
    快慢Tokenizer测试
    [None, 0, 1, 2, 2, 2, 2, 3, 4, None]
    [(0, 0), (0, 1), (1, 2), (2, 4), (4, 7), (7, 10), (10, 11), (11, 12), (12, 13), (0, 0)]
    

3. 加载特殊 Tokenizer

  • 有些开源模型的 Tokenizer 没有嵌入到 Transformers 库中,而是由作者在开源时于其远程仓库中提供,这种情况下 Tokenizer 的行为可能和 Transformers 库中其他 Tokenizer 的一般行为有所不同,直接加载这些模型会报错

    tokenizer = AutoTokenizer.from_pretrained("Skywork/Skywork-13B-base", trust_remote_code=False)
    # ValueError: Loading Skywork/Skywork-13B-base requires you to execute the configuration file in that repo on your local machine. Make sure you have read the code there to avoid malicious use, then set the option `trust_remote_code=True` to remove this error.
    

    这时,需要在 .from_pretrained 方法中传入 trust_remote_code=True 对远程代码添加信任,才能正常下载目标 tokenizer

    tokenizer = AutoTokenizer.from_pretrained("Skywork/Skywork-13B-base", trust_remote_code=True)
    tokenizer
    
    You are using the legacy behaviour of the <class 'transformers_modules.Skywork.Skywork-13B-base.bc35915066fbbf15b77a1a4a74e9b574ab167816.tokenization_skywork.SkyworkTokenizer'>. This means that tokens that come after special tokens will not be properly handled. 
    SkyworkTokenizer(name_or_path='Skywork/Skywork-13B-base', vocab_size=65519, model_max_length=1000000000000000019884624838656, is_fast=False, padding_side='right', truncation_side='right', special_tokens={'bos_token': '<s>', 'eos_token': '</s>', 'unk_token': '<unk>'}, clean_up_tokenization_spaces=False),  added_tokens_decoder={0: AddedToken("<unk>", rstrip=False, lstrip=False, single_word=False, normalized=True, special=True),1: AddedToken("<s>", rstrip=False, lstrip=False, single_word=False, normalized=True, special=True),2: AddedToken("</s>", rstrip=False, lstrip=False, single_word=False, normalized=True, special=True),
    }
    
  • 下载之后,可以用前文 1.1 节方法将其保存到本地

相关文章:

Hugging face Transformers(3)—— Tokenizer

Hugging Face 是一家在 NLP 和 AI 领域具有重要影响力的科技公司&#xff0c;他们的开源工具和社区建设为NLP研究和开发提供了强大的支持。它们拥有当前最活跃、最受关注、影响力最大的 NLP 社区&#xff0c;最新最强的 NLP 模型大多在这里发布和开源。该社区也提供了丰富的教程…...

kubernetes集群部署:环境准备及master节点部署(二)

主机名IPv4地址IPv6地址角色安装组件操作系统k8s130-node190192.168.XX.190240a:XX::190masterkubeadm、kubelet、containerdAnolis OS 8.94.19.91-28.1.an8.x86_64k8s130-node191192.168.XX.191240a:XX::191nodekubeadm、kubelet、cri-oAnolis OS 8.94.19.91-28.1.an8.x86_64k…...

第8篇 智能合约的商业应用场景解析

一、引言 在区块链技术的众多应用中,智能合约无疑是其中的一颗璀璨明珠。它通过自动化、去中心化和不可篡改的特性,为商业世界带来了革命性的变革。今天,我们将一同探索智能合约在十个不同行业中的实际应用,感受其独特的魅力。 二、智能合约的商业应用案例 供应链管理:…...

Zabbix 配置grafana对接

zabbix对接grafana简介 Zabbix与Grafana对接可以实现更加丰富和美观的数据可视化&#xff0c;可以利用Grafana强大的可视化功能来展示Zabbix收集的数据。 Grafana 本身是提供了Zabbix的对接插件&#xff0c;开箱即用&#xff0c;安装好了之后点击 enable 一下就能启用。然后就…...

三相感应电机的建模仿真(2)基于ABC相坐标系S-Fun的仿真模型

1. 概述 2. 三相感应电动机状态方程式 3. 基于S-Function的仿真模型建立 4. 瞬态分析实例 5. 总结 6. 参考文献 1. 概述 前面建立的三相感应电机在ABC相坐标系下的数学模型是一组周期性变系数微分方程&#xff08;其电感矩阵是转子位置角的函数&#xff0c;转子位置角随时…...

开源全新H5充值系统源码/自定义首页+充值页面/灵活对接上游渠道接口

开源全新H5充值系统源码&#xff0c;系统基于thinkphp框架开发&#xff0c;功能已全完善&#xff0c;可灵活对接其他上游渠道接口&#xff0c;默认对接了大猿人接口&#xff0c;另外可无限制自定义创建充值页面&#xff0c;首页支持后台自定义修改&#xff0c;支持三级分销&…...

Linux查看文件的行数,字数,字节数

介绍 在Linux系统中这统计非常方便&#xff0c;只需要简单的几个命令就可以搞定&#xff0c;这个命令就是 wc。 wc --help 用法&#xff1a;wc [选项]... [文件]...或&#xff1a;wc [选项]... --files0-fromF 输出每个指定文件的行数、单词计数和字节数&#xff0c;如果指定…...

【IO】文件操作

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 文件1.1 认识文件1.2 分清操作的是内存还是硬盘1.3 路径1.3.1 目录结构1.3.2 相对和绝对路径 1.4 文本文件…...

代码随想录算法训练营第74天:路径总结[1]

代码随想录算法训练营第74天&#xff1a;路径总结 ‍ A * 算法精讲 &#xff08;A star算法&#xff09; 卡码网&#xff1a;126. 骑士的攻击(opens new window) 题目描述 在象棋中&#xff0c;马和象的移动规则分别是“马走日”和“象走田”。现给定骑士的起始坐标和目标…...

用 Emacs 写代码有哪些值得推荐的插件

以下是一些用于 Emacs 写代码的值得推荐的插件&#xff1a; Ido-mode&#xff1a;交互式操作模式&#xff0c;它用列出当前目录所有文件的列表来取代常规的打开文件提示符&#xff0c;能让操作更可视化&#xff0c;快速遍历文件。Smex&#xff1a;可替代普通的 M-x 提示符&…...

自定义注解-手机号验证注解

注解 package com.XX.assess.annotation;import com.XX.assess.util.MobileValidator;import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*;/*** 手机号校验注解* author super*/ Retention(RetentionPolicy.RUNTIME) Targe…...

华为od-C卷200分题目5 -项目排期

华为od-C卷200分题目5 -项目排期 题目描述 项目组共有N个开发人员&#xff0c;项目经理接到了M个独立的需求&#xff0c;每个需求的工作量不同&#xff0c;且每个需求只能由一个开发人员独立完成&#xff0c;不能多人合作。 假定各个需求之间无任何先后依赖关系&#xff0c;请…...

如何使用Pip从Git仓库安装Python包:深入探索远程依赖管理

如何使用Pip从Git仓库安装Python包&#xff1a;深入探索远程依赖管理 Python的包管理工具Pip使得安装和管理Python库变得非常简单。有时&#xff0c;我们需要安装那些尚未发布到PyPI的包&#xff0c;或者想要尝试最新的开发版本。这时&#xff0c;可以直接从Git仓库安装包。本…...

计算机专业怎么选择电脑

现在高考录取结果基本已经全部出来了&#xff0c;很多同学都如愿以偿的进入到了计算机类专业&#xff0c;现在大部分同学都在为自己的大学生活做准备了&#xff0c;其中第一件事就是买电脑&#xff0c;那计算机类专业该怎么选择电脑呢&#xff1f; 计算机专业是个一类学科&…...

当前国内可用的docker加速器搜集 —— 筑梦之路

可用镜像加速器 以下地址搜集自网络&#xff0c;仅供参考&#xff0c;请自行验证。 1、https://docker.m.daocloud.io2、https://dockerpull.com3、https://atomhub.openatom.cn4、https://docker.1panel.live5、https://dockerhub.jobcher.com6、https://hub.rat.dev7、http…...

【腾讯内推】腾讯2025校招/青云计划/社招——长期有效

及时跟进进度&#xff0c;保证不让简历石沉大海&#xff01; 涵盖NLP/CV/CG/ML/多模态/数据科学/多媒体等各方向! 定向匹配优质团队/竞争力薪酬/覆盖全球工作地点! 招聘对象: 本硕博:2024年1月-2025年12月毕业的同学 目前最热岗位: 技术研究-自然语言处理 技术研究-计算机视觉 …...

集群限流sentinel实践

参考&#xff1a; 集群模式 实践 集群流控规则 其中 用一个专门的 ClusterFlowConfig 代表集群限流相关配置项&#xff0c;以与现有规则配置项分开&#xff1a; // 全局唯一的规则 ID&#xff0c;由集群限流管控端分配. private Long flowId;// 阈值模式&#xff0c;默认&…...

Flutter-实现双向PK进度条

如何实现一个双向PK进度条 在Flutter应用中&#xff0c;进度条是一个非常常见的组件。而双向PK进度条则能够展示两个对立的数值&#xff0c;如对战中的双方得分对比等。本文将介绍如何实现一个具有双向PK效果的进度条&#xff0c;并支持竖直和斜角两种过渡效果。 1. 需求 我…...

unix高级编程系列之文件I/O

背景 作为linux 开发者&#xff0c;我们不可避免会接触到文件编程。比如通过文件记录程序配置参数&#xff0c;通过字符设备与外设进行通信。因此作为合格的linux开发者&#xff0c;一定要熟练掌握文件编程。在文件编程中&#xff0c;我们一般会有两类接口函数&#xff1a;标准…...

PySide(PyQt),记录最后一次访问文件的路径

1、在同目录下用文本编辑器创建JSON文件&#xff0c;命名为setting.json&#xff0c;并输入以下内容后保存&#xff1a; { "setting": { "last_file": [ "" ] } } 2、应用脚本&#xff1a; import json …...

wordpress企业网站模板免费下载

大气上档次的wordpress企业模板&#xff0c;可以直接免费下载&#xff0c;连注册都不需要&#xff0c;网盘就可以直接下载&#xff0c;是不是嘎嘎给力呢 演示 https://www.jianzhanpress.com/?p5857 下载 链接: https://pan.baidu.com/s/1et7uMYd6--NJEWx-srMG1Q 提取码:…...

[leetcode hot 150]第一百一十七题,填充每个节点的下一个右侧节点

题目&#xff1a; 给定一个二叉树&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点&#xff0c;则将 next 指针设置为 NULL 。 初始状态下&#x…...

Docker 入门篇(十 一)-- 网络配置总结

Docker 容器技术的核心优势之一是其轻量级的虚拟化和隔离性&#xff0c;而 Docker 网络则是实现容器间以及容器与外界通信的关键。以下是对 Docker 网络的关键知识点的总结。 一、 Docker 网络概述 Docker 网络允许容器进行相互通信以及与外部网络的连接。Docker 提供了多种网…...

【Android面试八股文】Android 有哪些存储数据的方式?

在Android平台上,有多种方式可以存储数据,每种方式都适合不同类型的数据和使用场景。以下是主要的存储数据方式: SharedPreferences(轻量级数据存储): SharedPreferences是用于存储简单键值对数据的最简单方法,适合存储用户偏好设置、配置信息等。数据以XML文件形式存储…...

3. train_encoder_decoder.py

train_encoder_decoder.py #__future__ 模块提供了一种方式&#xff0c;允许开发者在当前版本的 Python 中使用即将在将来版本中成为标准的功能和语法特性。此处为了确保代码同时兼容Python 2和Python 3版本中的print函数 from __future__ import print_function # 导入标准库…...

Hyper-V克隆虚拟机教程分享!

方法1. 使用导出导入功能克隆Hyper-V虚拟机 导出和导入是Hyper-V服务器备份和克隆的一种比较有效的方法。使用此功能&#xff0c;您可以创建Hyper-V虚拟机模板&#xff0c;其中包括软件、VM CPU、RAM和其他设备的配置&#xff0c;这有助于在Hyper-V中快速部署多个虚拟机。 在…...

QDockWidget类详解

一.QDockWidget类概述 1.QDockWidget类 QDockWidget类提供了一个特殊的窗口部件&#xff0c;它可以是被锁在QMainWindow窗口内部或者是作为顶级窗口悬浮在桌面上。 QDockWidget类提供了dock widget的概念&#xff0c;dock widget也就是我们熟悉的工具面板或者是工具窗口。Do…...

vue3.0(十六)axios详解以及完整封装方法

文章目录 axios简介1. promise2. axios特性3. 安装4. 请求方法5. 请求方法别名6. 浏览器支持情况7. 并发请求 Axios的config的配置信息1.浏览器控制台相关的请求信息&#xff1a;2.配置方法3.默认配置4.配置的优先级5.axios请求响应结果 Axios的拦截器1.请求拦截2.响应拦截3.移…...

Python用于处理 DNS 查询库之Dnspython 使用详解

概要 Dnspython 是一个开源的 Python 库,专门用于处理 DNS 查询。它被设计为既简单易用又功能强大,可以满足从简单到复杂的各种 DNS 相关需求。无论是进行基础的 DNS 查询还是进行高级的 DNS 服务器管理,dnspython 都能提供相应的功能。 这个库支持包括 A、AAAA、MX、TXT …...

Django ORM 中过滤 JSON 数据

简介 首先,我们假设您有一个名为 MyModel 的 Django 模型,它包含一个 JSONField 类型的字段,名为 data。这个 data 字段可以存储各种 JSON 格式的数据。 过滤 JSON 字段中的键值对 您可以使用双下划线 __ 语法来访问 JSON 字段中的嵌套键值对。例如: # 过滤 data 字段中 &qu…...

深入探索C语言中的结构体:定义、特性与应用

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 目录 结构体的介绍结构体定义结构成员的类型结构体变量的定义和初始化结构体成员的访问结构体传参 结构体的介绍 在C语言中&#xff0c;结构体是一种用户自定义的数据类型&#xff0c;它允许开发者将不同类型的变量组合在一起…...

EDEM-FLUENT耦合报错几大原因总结(持续更新)

写在前面,本篇内容主要是来源于自己做仿真时的个人总结,以及付费请教专业老师。每个人由于工况不一样,所以报错原因千奇百怪,不能一概而论,本篇内容主要是为本专栏读者在报错时提供大致的纠错方向,从而达到少走弯路的效果,debug的过程需要大家一点点试算。问题解答在文 …...

ctfshow sql注入 web234--web241

web234 $sql "update ctfshow_user set pass {$password} where username {$username};";这里被过滤了&#xff0c;所以我们用\转义使得变为普通字符 $sql "update ctfshow_user set pass \ where username {$username};";那么这里的话 pass\ where…...

Python的招聘数据分析与可视化管理系统-计算机毕业设计源码55218

摘要 随着互联网的迅速发展&#xff0c;招聘数据在规模和复杂性上呈现爆炸式增长&#xff0c;对数据的深入分析和有效可视化成为招聘决策和招聘管理的重要手段。本论文旨在构建一个基于Python的招聘数据分析与可视化管理系统。 该平台以主流招聘平台为数据源&#xff0c;利用Py…...

使用ChatGPT写学术论文的技巧和最佳实践指南

大家好&#xff0c;感谢关注。我是七哥&#xff0c;一个在高校里不务正业&#xff0c;折腾学术科研AI实操的学术人。关于使用ChatGPT等AI学术科研的相关问题可以和作者七哥&#xff08;yida985&#xff09;交流&#xff0c;多多交流&#xff0c;相互成就&#xff0c;共同进步&a…...

多模态图像引导手术导航进展

**摘要&#xff1a;**对多模态图像分割建模、手术方案决策、手术空间位姿标定与跟踪、多模态图像配准、图像融合与显示等多模态图像引导手术导航的关键技术进行总结和分析&#xff0c;提出其进一步发展面临的挑战并展望其未来发展趋势。 **外科手术的发展历程&#xff1a;**从最…...

小程序 全局数据共享 getApp()

在小程序中&#xff0c;可以通过 getApp() 方法获取到小程序全局唯一的App实例 因此在App() 方法中添加全局共享的数据、方法&#xff0c;从而实现页面、组件的数据传值 在 app.js 文件中定义 App({// 全局共享的数据globalData:{token:},// 全局共享的方法setToken(token){//…...

第一次面试的经历(java开发实习生)

面试官的问题 我想问一下你这边有做过什么项目吗?你方便讲一下你做过的那些项目吗&#xff0c;用了什么技术栈&#xff0c;包括你负责开发的内容是什么&#xff1f;&#xff08;项目经验&#xff09;八大基本数据类型是什么&#xff1f;&#xff08;基础&#xff09;你说一下…...

GitHub Copilot API

1. 引言 GitHub Copilot&#xff1a;智能编程的革新者 在软件开发的浩瀚宇宙中&#xff0c;GitHub Copilot犹如一颗璀璨的新星&#xff0c;以其独特的魅力引领着智能编程的新纪元。作为GitHub与OpenAI合作推出的革命性工具&#xff0c;Copilot不仅仅是一个简单的代码补全插件…...

CobaltStrike的内网安全

1.上线机器的Beacon的常用命令 2.信息收集和网站克隆 3.钓鱼邮件 4.CS传递会话到MSF 5.MSF会话传递到CS 1上线机器的Beacon的常用命令 介绍&#xff1a;CobaltStrike分为服务端和客户端&#xff0c;一般我们将服务端放在kali&#xff0c;客户端可以在物理机上面&#xff0…...

Linux之进程控制(下)

目录 进程替换的概念 进程替换的函数 execl​编辑 execlp execle execv execvp execve 上期&#xff0c;我们学习了进程创建&#xff0c;进程终止和进程等待&#xff0c;今天我们要学习的是进程控制中相对重要的板块------进程替换。 进程替换的概念 在进程创建时&…...

Mac搭建anaconda环境并安装深度学习库

1. 下载anaconda安装包 根据自己的操作系统不同&#xff0c;选择不同的安装包Anaconda3-2024.06-1-MacOSX-x86_64.pkg&#xff0c;我用的还是旧的intel所以下载这个&#xff0c;https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/&#xff0c;如果mac用的是M1&#xff0…...

Linux:文件系统与日志分析

一、block与inode 1.1、概述 文件是存储在硬盘上的&#xff0c;硬盘的最小存储单位叫做“扇区”(sector)&#xff0c;每个扇区存储512字节。 一般连续八个扇区组成一个"块”(block)&#xff0c;一个块是4K大小&#xff0c;是文件存取的最小单位。 文件数据包括实际数据…...

迈阿密色主题学科 HTML5静态导航源码

源码介绍 迈阿密色主题学科 HTML5静态导航源码&#xff0c;源码直接上传可用&#xff0c;有技术的可以拿去写个后端搜索调用百度接口&#xff0c;也可用于做引导页下面加你网址添加一个A标签就行了&#xff0c;很简单&#xff0c;需要的朋友就拿去吧 界面预览 源码下载 迈阿…...

Qt 基础组件速学 鼠标和键盘事件

学习目标&#xff1a; 鼠标事件和键盘事件应用 前置环境 运行环境:qt creator 4.12 学习内容和效果演示&#xff1a; 1.鼠标事件 根据鼠标的坐标位置&#xff0c;做出对应的事件。 2.键盘事件 根据键盘的输入做出对应操作 详细主要代码 1.鼠标事件 #include "main…...

【踩坑】解决undetected-chromedriver报错cannot connect to-chrome

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 更新&#xff1a; 发现一个非常好用的项目&#xff0c;直接内置uc&#xff1a; GitHub - seleniumbase/SeleniumBase: &#x1f4ca; Pythons all-in…...

PyCharm 2024.1 版本更新亮点:智能编程,高效协作

目录 1. 前言2. 更新内容2.1 智能编码体验2.1.1 Hugging Face 文档预览2.1.2 全行代码补全 2.2 提升编辑器体验2.2.1 粘性行功能2.2.2 编辑器内代码审查 2.3 全新终端体验&#xff08;测试版&#xff09;2.3.1 新终端 Beta 2.4 智能助手&#xff08;特定版本和专业用户&#xf…...

网络安全设备——蜜罐

网络安全设备蜜罐&#xff08;Honeypot&#xff09;是一种主动防御技术&#xff0c;它通过模拟真实网络环境中的易受攻击的目标&#xff0c;以吸引和监测攻击者的活动。具体来说&#xff0c;蜜罐是一种虚拟或实体的计算机系统&#xff0c;它模拟了一个真实的网络系统或应用程序…...

Java与Selenium配置及常见报错解决方法

Java与Selenium配置及常见报错解决方法 1. 简介 Java与Selenium是自动化测试中常用的工具和技术。正确配置开发环境并处理可能出现的问题&#xff0c;对于顺利开展测试工作至关重要。本文将为您详细介绍Java与Selenium的配置过程&#xff0c;并提供常见报错的解决方法。 2. …...

最新扣子(Coze)实战案例:使用图像流做超分,模糊图片秒变清晰,完全免费教程

&#x1f9d9;‍♂️ 大家好&#xff0c;我是斜杠君&#xff0c;手把手教你搭建扣子AI应用。 &#x1f4dc; 本教程是《AI应用开发系列教程之扣子(Coze)实战教程》&#xff0c;完全免费学习。 &#x1f440; 关注斜杠君&#xff0c;可获取完整版教程。&#x1f44d;&#x1f3f…...