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

[万字解析]从零开始使用transformers微调huggingface格式的中文Bert模型的过程以及可能出现的问题

系列文章目录

使用transformers中的pipeline调用huggingface中模型过程中可能遇到的问题和修改建议

[万字解析]从零开始使用transformers微调huggingface格式的中文Bert模型的过程以及可能出现的问题


文章目录

  • 系列文章目录
  • 前言
  • 模型与数据集下载
    • 模型下载
    • 数据集下载
  • 数据加载、划分与保存
    • 数据加载
    • 数据集可能造成的问题
    • 数据集划分
    • 数据集保存和加载
  • 数据处理
    • 编码
    • 按文本长度筛选
  • 模型训练与评估
    • 模型加载
    • 加载评价指标
    • 定义评价函数
    • 定义训练参数
    • 定义训练器
    • 模型评估与训练
  • 模型保存与加载
  • 模型预测


前言

在使用huggingface的模型时,很多情况下已有的模型并不能完全满足实际的需求,这种情况下模型微调是常见的解决方式,在本篇文章中将使用transformers针对huggingface格式的中文Bert分类模型为例介绍微调的过程以及解决在微调过程中可能存在的一些问题。

模型与数据集下载

首要步骤是找到合适的模型及数据集,模型和数据集都可以直接在huggingface或者huggingface的镜像上直接搜索
huggingface链接地址:https://huggingface.co
镜像链接地址:https://hf-mirror.com

模型下载

首先在huggingface(或镜像)主页选择Models,然后输入chinese bert可以查询到很多适用于中文的bert模型,在本篇中选择第一个google-bert作为示例。
在这里插入图片描述
也可以直接访问https://huggingface.co/google-bert/bert-base-chinese或https://hf-mirror.com/google-bert/bert-base-chinese
点击进入后查看Model card可以查看chinese-bert的介绍,与之前文章中提到的过程相似,需要下载Files and versions中所有的文件。
在这里插入图片描述
下载完成后将所有内容放在同一个文件夹中,笔者的路径是'/huggingface_model/google-bert/bert-base-chinese',可做参考。

数据集下载

在本篇中以中文评价数据集为例,同理在主页上选择Datasets然后输入ChnSentiCorp,或者直接访问https://hf-mirror.com/datasets/XiangPan/ChnSentiCorp_htl_8k,随便选一个即可(为了防止出现额外的问题,请尽量与本篇保持一致)。
在这里插入图片描述
打开之后可以看到这个数据集是关于酒店的评价,并且数据是不均衡的,数据不均衡的问题在本篇中按下不表,本篇的重点在于跑通整个过程,读者可以自行查看解决数据不均衡的问题。
在这里插入图片描述
选择Files and versions下载数据集,在本篇中只需要下载ChnSentiCorp_htl_8k.csv文件即可,笔者下载到的路径为./datas/ChnSentiCorp_htl_8k/ChnSentiCorp_htl_8k.csv可以作为参考。
在这里插入图片描述

数据加载、划分与保存

数据加载

本篇中使用datasets中的load_dataset加载数据,在进行下一步操作前可以先观察一下数据。
数据加载代码:

from datasets import load_datasetdataset = load_dataset('csv', data_files='./datas/ChnSentiCorp_htl_8k/ChnSentiCorp_htl_8k.csv')
print(dataset)

运行结果:

DatasetDict({train: Dataset({features: ['label', 'review'],num_rows: 7765})
})

从展示效果上可以看到这是一个嵌套两层的字典,根据关键字进一步观察数据。

print(dataset['train']['label'][:2], dataset['train']['review'][:2])

运行结果:

[1, 1] ['距离川沙公路较近,但是公交指示不对,如果是"蔡陆线"的话,会非常麻烦.建议用别的路线.房间较为简单.', '商务大床房,房间很大,床有2M宽,整体感觉经济实惠不错!']

由此可见在本数据集中1表示的是好评,0表示的是差评。

数据集可能造成的问题

在本数据集中6376行中的数据为空,如果不加处理直接使用可能会引起报错,一般来讲,拿到数据集后要检查数据集并需要批量的处理掉空数据,在本篇中用到的数据集只有这一条空数据,可以直接在csv文件中删除后保存后重新读取数据即可。在这里插入图片描述

数据集划分

从csv文件的内容来看数据没有打乱,所以首先需要打乱并显示打乱结果。

dataset['train']= dataset['train'].shuffle()
print(dataset['train']['label'][:5])
print(dataset['train']['review'][:5])

运行结果:

[1, 1, 0, 0, 0]
['酒店地理位置还不错,离外滩、步行街都满近的。我住的是单间,不靠马路,以为会比较安静,哪知窗子外面是酒店内部的一个铁制楼梯,夜晚常有人走过,咣当直响,还有边走边唱歌的,受不了。除了前台小姐面无表情,其它都还行。', '定了高级湖景房,前台给了最高的23层。房间非常舒服,而且早餐也很丰盛。只是看出去的白鹭洲公园景色一般。可能住标准客房更实惠些。', '后悔看了评价。上面老兄的要求也够低的。1)隔音太差2)早餐太差3)卫生间太小4)房间装修太差总的来说就是一经济性酒店。', '总台服务员从我来到走,一直没笑过,很酷!宽带慢的让我想起"猫"的时代!中央空调的声音轰隆隆,热闹!要总台安排第2天一早车去机场,满口答应,退房时没人和我落实,我看着酷酷的成都MM,没问,还是自己拉着箱子走到100米外的路口打车!', '很不怎么样的酒店,根本不象三星级。1、大堂:受理很慢,且服务员连你好都不会说;2、房间:我订的是大床房间,电视机很旧,卫生间里洗澡的地方是用玻璃隔起来的,空间很狭小,而且热水放出来的里面全是棕红色的铁锈,洗澡时水温忽冷忽热;比较变态的是,房间里没有预备网线,你得打电话要,而且电源插座很不合理,如果要插笔记本电源,需要把电视柜往前搬至少50厘米,否则你是找不到插孔的;3、订餐:按照《服务指南》,我打了8003,提示无此号码,于是拨打8006查询,告知我打8033,打过去以后又让我打8031,订个餐有这么麻烦吗?好不容易打通了,要了红烧草鱼、清炒土豆丝和紫菜汤,结果巨难吃,还不如外边随便一个小餐馆做的好吃,反而花了70多元,根本不是三星级酒店厨师做的,让人愤慨!紫菜汤的颜色就像是刷锅水!紫菜也是大片大片的!3、服务:打电话要了网线,过了很久,难道绿洲饭店很大吗?要走那么久?!绿洲饭店我已经住过好几次了,这次是最差劲的!!!给各位推荐立达宾馆,性价比很好,服务也特别好,而且做的菜很有家常口味,吃起来很可口!虽然远了一点,但是打车到市中心,也不过7元钱而已。唯一不足的就是没有宽带连接。补充点评2007年8月16日:还有一点最让人无法忍受:隔音太差了!我的房间隔壁住了个醉汉,那个呻吟声和鼾声,简直就像在同一个房间一样,而且看电视的声音和说话的声音都很清晰!']

在打乱的基础上根据数据集的长度按比例划分训练集和测试集。

length = len(dataset['train'])
train_len = int(length * 0.8)
test_len = int(length * 0.2)
train_dataset = dataset['train'].select(range(train_len))
test_dataset = dataset['train'].select(range(train_len, length))

数据集保存和加载

根据划分好的训练数据和测试数据重新构建数据,将训练数据和测试数据使用datasets.DatasetDict构建成新的数据集。

from datasets import DatasetDictdataset_dict = DatasetDict({  'train': train_dataset,  'test': test_dataset  
}) 
print(dataset_dict)

运行结果:

DatasetDict({train: Dataset({features: ['label', 'review'],num_rows: 6212})test: Dataset({features: ['label', 'review'],num_rows: 1553})
})

使用save_to_disk将处理过的数据保存

dataset_dict.save_to_disk('ChnSentiCorp')

保存好的数据在ChnSentiCorp文件夹中的本地结构如下:
在这里插入图片描述
使用load_from_disk可以加载保存好的数据

from datasets import load_from_diskdataset = load_from_disk('ChnSentiCorp')
print(dataset)

运行结果:

DatasetDict({train: Dataset({features: ['label', 'review'],num_rows: 6212})test: Dataset({features: ['label', 'review'],num_rows: 1553})
})

数据处理

在DatasetDict对象中,可以采用map来批量的处理数据,采用filter来批量的筛选数据。

编码

不同模型间的编码方式可以也不同,所以编码的过程需要用到下载好的模型,在transformers中提供了一个自动获取Tokenizer的函数AutoTokenizer。在上文中观察到关键字review是数据中文本部分,所以需要对review字段进行编码。

其中truncation=True指定如果输入的文本长度超过了模型处理的最大长度(这个长度通常在tokenizer初始化时设置),则文本将被截断以适应这个长度。这对于保持批处理的一致性非常重要,因为模型通常要求所有输入具有相同的长度。

在使用map处理数据时最好使用批处理(设置参数batched=True),通过设置batch_size来调整每批的大小,num_proc来设置运行的进程,读者可以根据设备内存适当调整。

def f(data):from transformers import AutoTokenizertokenizer = AutoTokenizer.from_pretrained('../huggingface_model/google-bert/bert-base-chinese')return tokenizer.batch_encode_plus(data['review'], truncation=True)dataset = dataset.map(f, batched=True, batch_size=1000, num_proc=4, remove_columns=['review'])
print(dataset)

运行结果:

DatasetDict({train: Dataset({features: ['label', 'input_ids', 'token_type_ids', 'attention_mask'],num_rows: 6212})test: Dataset({features: ['label', 'input_ids', 'token_type_ids', 'attention_mask'],num_rows: 1553})
})

按文本长度筛选

通常情况下序列长度越长,获取到的信息也就越多,但是随着序列长度的增加,运算代价也在增加,但对于本任务中仅需要部分文本信息就可以得出对于旅店的好评或者差评,并且数据量足够大,所以在此可以选择筛选掉超过一定长度的文本(这相当于直接舍弃了超过整个长度的数据,但是在数据量不足的情况下一般会选择截断或者将一整段话拆成几段)。

def f(data):return [len(i)<=512 for i in data['input_ids']]dataset=dataset.filter(f, batched=True, batch_size=1000, num_proc=4)
print(dataset)

运行结果:

DatasetDict({train: Dataset({features: ['label', 'input_ids', 'token_type_ids', 'attention_mask'],num_rows: 6054})test: Dataset({features: ['label', 'input_ids', 'token_type_ids', 'attention_mask'],num_rows: 1508})
})

filter后的效果可以看出整个过程就是按照条件筛选出符合条件的数据,不符合条件的数据会被直接删掉。

模型训练与评估

模型加载

from transformers import AutoModelForSequenceClassification
import torchmodel=AutoModelForSequenceClassification.from_pretrained('../huggingface_model/google-bert/bert-base-chinese', num_labels=2)
#统计模型参数量
print(sum([i.nelement() for i in model.parameters()]))

运行结果:

102269186

加载评价指标

如果能够很顺利的访问github,直接使用以下代码会自动下载用于评价精度的accuracy.py,等待下载成功后即可正常运行。

from datasets import load_metric
metric = load_metric('accuracy')

但是如果不能正常访问github或是有在断网情况下使用的应用场景,就会有如下报错。
在这里插入图片描述
出现报错后将报错中的链接复制到浏览器
在这里插入图片描述
这个文件就是所需的accuracy.py,下载后记录下所在地址,笔者的地址是/metrics/accuracy。然后使用下述代码即可执行。特别注意trust_remote_code=True这一参数的设置,这是因为直接加载一个.py文件会存在安全风险,在直接加载.py文件时将会直接不设防的执行其中的代码,所以一般情况下这一行为将会被阻止。所以需要额外的设置这一参数,需要注意的是,这一参数设置为True时需要确保.py文件足够被信任。

from datasets import load_metric
metric = load_metric('./metrics/accuracy', trust_remote_code=True)

定义评价函数

在评价函数中,eval_pred包含预测结果(概率格式)和实际标签,所以运算过程就是先根据预测结果的概率获取预测的标签,再对比预测标签和实际标签获取的模型的精度。

import numpy as np
from transformers.trainer_utils import EvalPrediction
def compute_metrics(eval_pred):logits, labels = eval_predlogits = logits.argmax(axis=1)return metric.compute(predictions=logits, references=labels)

定义训练参数

参数的定义比较简单,对照的注释很好理解。

from transformers import TrainingArgumentsargs = TrainingArguments(output_dir='./output_dir', #定义临时数据保存路径evaluation_strategy='steps', #定义测试执行的策略,可取值为no、epoch、steps   eval_steps=50, #定义每隔多少个step执行一次测试  save_strategy='steps', #定义模型保存策略,可取值为no、epoch、steps save_steps=50, #定义每隔多少个step保存一次num_train_epochs=1, #定义共训练几个轮次learning_rate=1e-4, #定义学习率logging_dir='./logs',            # 日志文件夹  logging_steps=50, weight_decay=1e-2, #加入参数权重衰减,防止过拟合per_device_eval_batch_size=32, #定义测试和训练时的批次大小per_device_train_batch_size=32,
)

定义训练器

训练器的定义只是把前面设置的参数直接传入,容易出问题的是有可能会因为各种包版本不匹配导致评估过程(trainer.evaluate)和训练过程(trainer.train)出现一些奇怪的报错。

from transformers import Trainer
from transformers.data.data_collator import DataCollatorWithPadding
from transformers import AutoTokenizertokenizer = AutoTokenizer.from_pretrained('../huggingface_model/google-bert/bert-base-chinese')trainer = Trainer(model=model,args=args,train_dataset=dataset['train'],eval_dataset=dataset['test'],compute_metrics=compute_metrics,data_collator=DataCollatorWithPadding(tokenizer),
)

可能出现的报错为
在这里插入图片描述
实际上这个完全是因为版本没有对应上,可以通过更新包来实现

pip install --upgrade accelerate
pip install --upgrade transformers
pip install --upgrade torch torchvision torchaudio

如果仍然没有解决,可以参考笔者包的版本组合。

包名版本
accelerate0.34.2
torch2.3.1+cu121
torchaudio2.3.1+cu121
torchvision0.18.1+cu121
transformers4.45.1

模型评估与训练

在训练之前先观察一下如果不进行训练,直接使用模型会有怎样的效果
模型评估:

trainer.evaluate()

运行结果:

{'eval_loss': 0.888075590133667,'eval_model_preparation_time': 0.0,'eval_accuracy': 0.3103448275862069,'eval_runtime': 21.5519,'eval_samples_per_second': 69.971,'eval_steps_per_second': 2.227}

从运行结果上来看,精度还没有到50%,比随机分的效果还要差一点。所以训练是有必要的(有些情况下,比如可以找到类似任务的模型的情况下,如果在自己的数据集上能有较好的效果就可以不进行训练而直接使用)
模型训练:

trainer.train()

运行结果:
在这里插入图片描述
由于我们设置了每隔50个step保存一次,并且保存路径为./output_dir,所以每次的检查点将保存至这个文件夹中。
在这里插入图片描述
训练结束后再进行评估

trainer.evaluate()

运行结果:

{'eval_loss': 0.48144271969795227,'eval_model_preparation_time': 0.0,'eval_accuracy': 0.7360742705570292,'eval_runtime': 153.5957,'eval_samples_per_second': 9.818,'eval_steps_per_second': 0.313,'epoch': 1.0}

可以看到在训练后精度得到了显著提高,虽然仍然不算特别高,但由于我们只训练了一轮,这样的结果已经足够令人满意了,如果想得到更高的精度需要更多的训练轮数。

模型保存与加载

模型的保存直接调用save_model,传入的参数是输出目录
模型保存

trainer.save_model(output_dir='./output_dir/save_model')

模型加载
在加载模型前要注意,需要从原模型文件夹中将词表复制到保存的模型的文件夹中,即把'../huggingface_model/google-bert/bert-base-chinese'目录下的vocab.txt复制到'./output_dir/save_model'

复制后'./output_dir/save_model'路径下应该存在以下四个文件
在这里插入图片描述
模型加载:
加载过程和加载原模型一致,尤其要注意的是执行这一步是必须的 model.to('cuda'),因为数据和模型必须在同一个设备上,如果没有GPU可用可以去掉或者改为 model.to('cpu')

model_name = './output_dir/save_model'tokenizer = AutoTokenizer.from_pretrained(model_name)  
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)model.to('cuda')

模型预测

model.eval()for i, data in enumerate(trainer.get_eval_dataloader()): out = model(**data)out = out['logits'].argmax(dim=1)for i in range(8):print(tokenizer.decode(data['input_ids'][i], skip_special_tokens =True))print(tokenizer.decode(data['input_ids'][i], skip_special_tokens =False))print('label=', data['labels'][i].item())print('predict=', out[i].item())break

运行结果:
在这里插入图片描述

相关文章:

[万字解析]从零开始使用transformers微调huggingface格式的中文Bert模型的过程以及可能出现的问题

系列文章目录 使用transformers中的pipeline调用huggingface中模型过程中可能遇到的问题和修改建议 [万字解析]从零开始使用transformers微调huggingface格式的中文Bert模型的过程以及可能出现的问题 文章目录 系列文章目录前言模型与数据集下载模型下载数据集下载 数据加载、…...

K8s简介及环境搭建

一、Kubernetes简介 kubernetes 的本质是一组服务器集群&#xff0c;它可以在集群的每个节点上运行特定的程序&#xff0c;来对节点中的容器进行管理。目的是实现资源管理的自动化&#xff0c;主要提供了如下的主要功能&#xff1a; 自我修复&#xff1a;一旦某一个容器崩溃&a…...

Python对PDF文件页面的旋转和切割

Python对PDF文件页面的旋转和切割 利用Python的.rotate()方法和.mediabox属性对PDF页面进行旋转和切割&#xff0c;最终生成一个PDF。下面结合案例进行说明&#xff0c;本示例中的名为split_and_rotate.pdf文件在practice_files文件夹中&#xff0c; 示例&#xff08;1&#…...

Android 10.0 修改Systemui三键导航栏虚拟按键颜色功能实现

1.前言 在10.0的系统ROM定制化开发中,在对systemui的相关定制化开发中,在某些产品中,需要修改相关的 导航栏三键导航的虚拟按键的颜色,修改掉原来默认的虚拟按键的黑白色,接下来就来实现相关的功能 2.修改Systemui三键导航栏虚拟按键颜色功能实现的核心类 frameworks\ba…...

『网络游戏』客户端使用PESorket发送消息到服务器【14】

上一章服务器已经完成使用PESorket 现在我们将其导出在客户端中使用 生成成功后复制 粘贴到Unity项目中 进入Assets文件夹 粘贴两个.dll 创建脚本:ClientSession.cs 编写脚本: ClientSession.cs 编写脚本:GameStart.cs 将GameStart.cs脚本绑定在摄像机上 运行服务器 运行客户端…...

JVM(学习预热 - 走进Java)(持续更新迭代)

目录 一、彻底认识Java虚拟机 开创世纪&#xff1a;Sun Classic 开创世纪&#xff1a;Exact VM 武林霸主&#xff1a;HotSpot VM 移动端虚拟机&#xff1a;Mobile/Embedded VM “三大”其二&#xff1a;BEA JRockit/IBM J9 VM 软硬结合&#xff1a;BEA Liquid VM/Azul VM…...

43 C 程序动态内存分配:内存区域划分、void 指针、内存分配相关函数(malloc、calloc、realloc、_msize、free)、内存泄漏

目录 1 C 程序内存区域划分 1.1 代码区 (Code Section) 1.2 全局/静态区 (Global/Static Section) 1.3 栈区 (Stack Section) 1.4 堆区 (Heap Section) 1.5 动态内存分配 2 void 指针&#xff08;无类型指针&#xff09; 2.1 void 指针介绍 2.2 void 指针的作用 2.3 …...

编译链接的过程发生了什么?

一&#xff1a;程序的翻译环境和执行环境 在 ANSI C 的任何一种实现中&#xff0c;存在两个不同的环境。 第 1 种是翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令。 第 2 种是执行环境&#xff0c;它用于实际执行代码 也就是说&#xff1a;↓ 1&#xff1…...

【D3.js in Action 3 精译_028】3.4 小节 DIY 实战:使用 Observable 在线绘制 D3 条形图

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可…...

【Linux】 TCP短服务编写和守护进程

文章目录 TCP 短服务编写流程进程组和会话和守护进程 TCP 短服务编写流程 TCP服务器是面向连接的&#xff0c;客户端在发送数据之前需要先与服务器建立连接。 因此&#xff0c;TCP服务器需要能够监听客户端的连接请求。为了实现这一功能&#xff0c;需要将TCP服务器创建的套接字…...

自学数据库-MYSQL

自学数据库-MYSQL 一.表和视图1.表1.1 表创建1.2 索引1.2.1 这里是废话,不感兴趣的可以直接更具目录的跳过这里的内容1.2.1.1 索引是什么1.2.1.2 相关数据结构&#xff1a;二叉树、红黑树、B-Tree、BTree、Hash…①普通索引②唯一索引③全文索引④组合索引 1.3 表数据操作(更新…...

机器学习——多模态学习

多模态学习&#xff1a;机器学习领域的新视野 引言 多模态学习&#xff08;Multimodal Learning&#xff09;是机器学习中的一个前沿领域&#xff0c;它涉及处理和整合来自多个数据模式&#xff08;如图像、文本、音频等&#xff09;的信息。随着深度学习的蓬勃发展&#xff0…...

​ceph掉电后无法启动osd,pgs unknown

处理办法&#xff1a; 只有1个osd,单副本&#xff0c;掉电损坏osd&#xff0c;只能考虑重建pg&#xff0c;丢失部分数据了。生产环境务必考虑2&#xff0c;3副本设计。避免掉电故障风险。 掉电后osdmap丢失无法启动osd的解决方案 - 武汉-磨渣 - 博客园 https://zhuanlan.zhih…...

HTML5实现古典音乐网站源码模板1

文章目录 1.设计来源1.1 网站首页1.2 古典音乐界面1.3 著名人物界面1.4 古典乐器界面1.5 历史起源界面2.效果和源码2.1 动态效果2.2 源代码源码下载万套模板,程序开发,在线开发,在线沟通作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/142…...

快速生成单元测试

1. Squaretest插件 2. 依赖 <dependency><groupId>junit</groupId>...

WebGL系列教程十一(光照原理及Blinn Phong着色模型)

快速导航&#xff08;持续更新中&#xff09; WebGL系列教程一&#xff08;开篇&#xff09; WebGL系列教程二&#xff08;环境搭建及着色器初始化&#xff09; WebGL系列教程三&#xff08;使用缓冲区绘制三角形&#xff09; WebGL系列教程四&#xff08;绘制彩色三角形&…...

《ASP.NET Web Forms 实现短视频点赞功能的完整示例》

在现代Web开发中&#xff0c;实现一个动态的点赞功能是非常常见的需求。本文将详细介绍如何在ASP.NET Web Forms中实现一个视频点赞功能&#xff0c;包括前端页面的展示和后端的处理逻辑。我们将确保点赞数量能够实时更新&#xff0c;而无需刷新整个页面。 技术栈 ASP.NET We…...

Linux SSH服务

Linux SSH&#xff08;Secure Shell&#xff09;服务是一种安全的远程登录协议&#xff0c;用于在Linux操作系统上远程登录和执行命令。它提供了加密的通信通道&#xff0c;可以在不安全的网络环境中安全地进行远程访问。 SSH服务在Linux系统中通常使用OpenSSH软件包来实现。它…...

MySQL--视图(详解)

目录 一、前言二、视图2.1概念2.2语法2.3创建视图2.3.1目的 2.4查看视图2.5修改数据2.5.1通过真实表修改数据&#xff0c;会影响视图2.5.2通过修改视图&#xff0c;会影响基表 2.6注意2.7 删除视图2.8 视图的优点 一、前言 欢迎大家来到权权的博客~欢迎大家对我的博客进行指导&…...

Javascript 普通非async函数调用async函数

假设我们有一个异步函数 async function asyncFunction() {console.log("开始执行异步函数");await new Promise(resolve > setTimeout(resolve, 1000)); // 模拟异步操作console.log("异步函数执行完毕"); } 我们在调用这个异步函数时&#xff0c;比…...

【LeetCode】修炼之路-0004-Median of Two Sorted Arrays【python】

题目 Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays. The overall run time complexity should be O(log (mn)). Example 1: Input: nums1 [1,3], nums2 [2] Output: 2.00000 Explanation: merged…...

C++面试速通宝典——10

177. #include <filename> 和 #include "filname.h" 有什么区别&#xff1f; ‌‌‌‌  对于 #include <filename> &#xff0c; 编译器从标准库路径开始搜索 filename.h。 ‌‌‌‌  对于 #include "filename.h&#xff0c;编译器从用户的工作…...

肺腺癌预后新指标:全切片图像中三级淋巴结构密度的自动化量化|文献精析·24-10-09

小罗碎碎念 本期这篇文章&#xff0c;我去年分享过一次。当时发表在知乎上&#xff0c;没有标记参考文献&#xff0c;配图的清晰度也不够&#xff0c;并且分析的还不透彻&#xff0c;所以趁着国庆假期重新分析一下。 这篇文章的标题为《Computerized tertiary lymphoid structu…...

基于jmeter+perfmon的稳定性测试记录

1. 引子 最近承接了项目中一些性能测试的任务&#xff0c;因此决定记录一下&#xff0c;将测试的过程和一些心得收录下来。 说起来性能测试算是软件测试行业内&#xff0c;有些特殊的部分。这部分的测试活动&#xff0c;与传统的测试任务差别是比较大的&#xff0c;也比较依赖…...

前沿论文 M5Product 组会 PPT

对比学习&#xff08;Contrast learning&#xff09;&#xff1a;对比学习是一种自监督学习方法&#xff0c;用于在没有标签的情况下&#xff0c;通过让模型学习哪些数据点相似或不同来学习数据集的一般特征。假设一个试图理解世界的新生婴儿。在家里&#xff0c;假设有两只猫和…...

navicat~导出数据库密码

当我们mysql密码忘记了&#xff0c;而在navicat里有记录&#xff0c;我们应该如何导出这个密码呢&#xff1f; 第一步:文件菜单&#xff0c;导出链接&#xff0c;导出连接获取到 connections.ncx 文件 这里需要勾选 导出密码&#xff01;&#xff01;&#xff01; 不然导出的文…...

【Java】 —— 数据结构与集合源码:Vector、LinkedList在JDK8中的源码剖析

目录 7.2.4 Vector部分源码分析 7.3 链表LinkedList 7.3.1 链表与动态数组的区别 7.3.2 LinkedList源码分析 启示与开发建议 7.2.4 Vector部分源码分析 jdk1.8.0_271中&#xff1a; //属性 protected Object[] elementData; protected int elementCount;//构造器 public …...

YOLOv5改进——添加SimAM注意力机制

目录 一、SimAM注意力机制核心代码 二、修改common.py 三、修改yolo.py ​三、建立yaml文件 四、验证 一、SimAM注意力机制核心代码 在models文件夹下新建modules文件夹&#xff0c;在modules文件夹下新建一个py文件。这里为simam.py。复制以下代码到文件里面。 import…...

SQL 自学:表别名的运用与对被联结表使用聚集函数

一、表别名的概念与作用 &#xff08;一&#xff09;表别名的定义 表别名是为表指定的临时名称&#xff0c;在 SQL 查询中使用别名可以简化表名&#xff0c;提高代码的可读性和可维护性。当表名较长或在复杂的查询中多次引用表时&#xff0c;使用表别名可以避免重复输入冗长的…...

jmeter学习(2)变量

1&#xff09;用户定义的变量 路径&#xff1a;添加-》配置元件-》用户定义的变量 用户定义的变量是全局变量&#xff0c;可以跨线程组被调用&#xff0c;但在启动运行时获取一次值&#xff0c;在运行过程中不再动态获取值。 注意的是&#xff0c;如果在某个线程组定义了全…...