HuggingFace-利用BERT预训练模型实现中文情感分类(下游任务)

news2025/3/3 18:26:31

准备数据集

使用编码工具

首先需要加载编码工具,编码工具可以将抽象的文字转成数字,便于神经网络后续的处理,其代码如下:

# 定义数据集
from transformers import BertTokenizer, BertModel, AdamW
# 加载tokenizer
token = BertTokenizer.from_pretrained('bert-base-chinese')
print('token', token)

out:
token BertTokenizer(name_or_path=‘bert-base-chinese’, vocab_size=21128, model_max_length=512, 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),
}

由上可知bert-base-chinese模型的字典中共有21128个词,编码器编码句子的最大长度为512个词,并且能够看到bert-base-chinese模型所使用的一些特殊符号,例如SEK,PAD等。

这里使用的编码工具是bert-base-chinese,编码工具和预训练模型往往是成对使用的,后续将使用同名的预训练语言模型作为backbone。

编码工具的试算

加载完成编码工具之后可以进行一次试算,观察编码工具的输入和输出,代码如下:

data = token.batch_encode_plus(batch_text_or_text_pairs=['关注博主,不迷路。','俺要带你上高速。'], truncation=True,
                                   padding='max_length',
                                   max_length=12,
                                   return_tensors='pt',
                                   return_length=True)
# 查看编码输出
for k,v in out.items():
	print(k,v.shape)
# 把编码还原成句子
print(token.decode(out['input_ids'][0]))

out:
input_ids torch.Size([2, 17])
token_type_ids torch.Size([2, 17])
length torch.Size([2])
attention_mask torch.Size([2, 17])
[CLS] 关 注 博 主 , 不 迷 路 。 [SEP] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]
[CLS] 俺 要 带 你 上 高 速 。 [SEP] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]

编码工具的参数说明

对于编码工具的使用,特别是参数值的含义可以参考下面的两段代码:

"""使用简单的编码"""
# 编码两个句子
out = tokenizer.encode(
    # 句子1
    text = sents[0],
    text_pair = sents[1],

    # 当句子长度大于max_length时进行截断
    truncation=True,

    # 一律补充pad到max_length长度
    padding = 'max_length',
    add_special_tokens = True,
    # 许多大模型的阶段也是使用512作为最终的max_length
    max_length=30,
    return_tensors=None,
)
"""增强的编码函数"""
# 增强的编码函数
out = tokenizer.encode_plus(
    text = sents[0],
    text_pair = sents[1],

    #当句子长度大于max_length时进行截断操作
    truncation = True,

    #一律补零到max_length长度
    padding='max_length',
    max_length=30,
    add_special_tokens=True,

    #可以取值tf,pt,np,默认返回list--->tensorflow,pytorch,numpy
    return_tensors=None,

    #返回token_type_ids
    return_token_type_ids=True,

    #返回attention_mask
    return_attention_mask=True,

    #返回special_tokens_mask 特殊符号标识
    return_special_tokens_mask=True,

    #返回offset_mapping标识每个词的起始和结束位置---》这个参数只能BertTokenizerFast使用
    #return_offsets_mapping=True,

    #返回length 标识长度
    return_length=True
)

从上面的代码中的参数max_length=500可以看出经过编码后的句子的长度一定是12个词的长度。如果源句子超出则会进行截断,如果源句子不足则会进行填充PAD,其运行结果如下:

{'input_ids': tensor([[ 101, 1068, 3800, 1300,  712, 8024,  679, 6837, 6662,  511,  102,    0],
        [ 101,  939, 6206, 2372,  872,  677, 7770, 6862,  511,  102,    0,    0]]), 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), 'length': tensor([11, 10]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0]])}
input_ids torch.Size([2, 12])
token_type_ids torch.Size([2, 12])
length torch.Size([2])
attention_mask torch.Size([2, 12])
[CLS] 关 注 博 主 , 不 迷 路 。 [SEP] [PAD]
[CLS] 俺 要 带 你 上 高 速 。 [SEP] [PAD] [PAD]

在这里插入图片描述
编码工具首先是对一条完整的句子进行了tokenizer,把句子分成了一个个token。同时,对于不同的编码工具,分词的结果也不一定一致。这里采用的bert-base-chinese编码工具中,它是以字为词,即把每个字当做一个词进行处理。
这些编码的结果对于预训练模型的计算十分重要,在后面将会使用编码器将所有的句子进行编码,用于输入到预训练模型中进行计算。

定义数据集

这里使用的数据集为ChnSentiCorp数据集,Dataset类如下:

# import torch
from datasets import load_dataset
class Dataset(torch.utils.data.Dataset):
    def __init__(self, split):
        self.dataset = load_dataset(path='lansinuote/ChnSentiCorp', split=split)
    def __len__(self):
        return len(self.dataset)
    def __getitem__(self, i):
        text = self.dataset[i]['text']
        label = self.dataset[i]['label']
        return text, label
dataset = Dataset('train')
print(len(dataset))
print(dataset[0])

在上述代码中加载了ChnSentiCorp数据集,并使用Pytorch中的Dataset对象进行封装,利用__getitem__()得到每一条数据,每条数据中包含textlabels两个字段,最后初始化训练数据集并查看训练数据集的长度和第一条数据样例。

out: 9600
('选择珠江花园的原因就是方便,有电动扶梯直接到达海边,周围餐馆、食廊、商场、超市、摊位一应俱全。酒店装修一般,但还算整洁。 泳池在大堂的屋顶,因此很小,不过女儿倒是喜欢。 包的早餐是西式的,还算丰富。 服务吗,一般', 1)

由上面的输出可知训练数据集包括9600条数据,每条数据包含一条评论文本和一个标识,表明这一条评论是好评还是差评。注意:这里的数据集是单纯的原始文本数据,并没有进行编码。

定义计算设备

这里将使用CUDA作为计算设备,这样可以极大加速模型的训练和测试的过程,代码如下:

device = 'cpu'
if torch.cuda.is_available():
  device = 'CUDA'
print('选用的计算设备:',device)

在该段代码中默认使用CPU进行计算,如果存在CUDA的话则选用CUDA作为计算设备。

定义数据整理函数

正如上面所述的那样,ChnSentiCorp数据集中的每一条数据是抽象的文本数据,并没有进行任何的编码操作,而预训练模型是需要编码之后的数据才能进行计算,所以需要一个将文本句子转成编码的过程。
另外,在训练模型时数据集往往很大,如果一条一条地处理则效率会太低,在现实中我们往往一批一批地处理数据,这样可以快速地处理数据集,同时从梯度下降的角度来讲,批数据的梯度方差相较于一条条数据的梯度小,可以让模型更加稳定地更新参数

# 定义批处理函数
def collate_fn(data):
    sents = [i[0] for i in data]
    labels = [i[1] for i in data]
    # 编码
    data = token.batch_encode_plus(batch_text_or_text_pairs=sents, truncation=True,
                                   padding='max_length',
                                   max_length=500,
                                   return_tensors='pt',
                                   return_length=True)
    # input_ids:编码之后的数字
    # attention_masks:补0的位置都是0,其他位置都是1
    input_ids = data['input_ids']
    attention_mask = data['attention_mask']
    token_type_ids = data['token_type_ids']
    labels = torch.LongTensor(labels)
    # print(data['length'],data['length'].max())
    return input_ids, attention_mask, token_type_ids, labels

在这段代码中,参数data表示一批数据,取出其中的句子和标识,它们都是list类型,在上述代码中会将两者分别赋给sentslabels,然后是使用编码器编码该批句子,在参数中将编码后的结果指定为固定的500个词的大小,与上面的例子同理超出500个词的部分会被截断(这里是通过truncation=True控制),同时少于500个词的句子会被[PAD]填充(这里主要是通过 padding='max_length'控制)。另外,在编码过程中通过 return_tensors='pt'参数,将编码后的结果返回torch中的tensor类型,免去了后面转换数据格式的麻烦(也就是说后面可以通过数据格式转换可以将‘tf’转成‘pt’格式)。
之后取出编码后的结果,并将labels也转成Pytorch中的Tensor格式,再把它们移动到之前已经定义好的计算设备device上,最后把这些数据全部返回,到这里数据整理函数的工作已经全部完成。

数据处理函数的例子

上述定义了数据处理函数,为了实验其效果也可使用下面的例子:(本用例已加狗头保命~)在这里插入图片描述

data = [
    ('选择新大的原因当然不是为了延毕。',1),
    ('笔记本的内存确实小。',0),
    ('宿舍没有风扇。其他都很好。',1),
    ('今天才知道这本书还有第10000卷,真是太屌了。',1),
    ('机器的背面似乎被撕了张什么标签,残胶还在。',0),
    ('为什么有人在校园里尖叫,是疯了还是giao。',0)
]

# 狗头保命版试算
input_ids,attention_mask,token_type_ids,labels = collate_fn(data)
print('input_ids.shape',input_ids.shape)
print('attention_mask.shape',attention_mask.shape)
print('token_type_ids.shape',token_type_ids.shape)
print('labels:',labels)

在该段代码中首先是模拟了一批数据,这批数据中包含4个句子,通过将该批数据输入到整理函数以后,运行结果如下:

input_ids.shape torch.Size([6, 500])
attention_mask.shape torch.Size([6, 500])
token_type_ids.shape torch.Size([6, 500])
labels: tensor([1, 0, 1, 1, 0, 0])

可见编码之后的结果都是确定的500个词的长度,并且每个结果都会被移动到可用的计算设备上,这样可以方便后续的计算。

定义数据加载器

上述代码中定义了数据集和数据整理函数以后,下面我们将定义一个数据加载器DataLoader,它可以使用数据整理函数来完成成批地处理数据集中的数据,通俗来讲每一批的数据我们可以称为batch

# 定义数据加载器并查看数据样例
loader = torch.utils.data.DataLoader(dataset=dataset, batch_size=16,
                                     collate_fn=collate_fn,
                                     shuffle=True,
                                     drop_last=True)

对于上述代码,我们使用了Pytorch提供的工具类定义数据集加载器,其参数说明可参考下图:
在这里插入图片描述

数据加载器的例子

为了更好地使用数据加载器,这里我们查看一批数据样例,将这批数据输入到数据加载器中,可以发现其结果会与数据整理函数的运行结果相似,只不过是句子的数量增多了。

上述代码依次打印了加载器中批次数目、加载器中输入数据的input_ids和掩蔽注意力的形状
attention_mask_shape、词元的ids类型形状token_type_ids_shape以及标签labels

for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(loader):
    break
print(len(loader))
print('input_ids', input_ids)
print('attention_mask_shape', attention_mask.shape)
print('token_type_ids_shape', token_type_ids.shape)
print('labels', labels)
  1. input_ids 就是编码后的词
  2. token_type_ids 第一个句子和特殊符号的位置是0,第二个句子的位置是1
  3. attention_mask pad的位置是0,其他位置都是1
  4. special_tokens_mask 特殊符号的位置是1,其他位置都是0

定义模型

因为我们是要利用Huggingface的预训练语言模型,所以需要做两件事情:加载预训练模型PLM以及定义下游任务模型。

加载预训练模型

这里使用的BERT预训练模型,模型名称为bert-base-chinese,这里的名称和编码器的名称是一致的,因为往往模型和其编码工具配套使用。另外,BERT模型不是必须的模型,进行中文情感分类也可以使用其他支持中文的模型,例如BART等。

from transformers import BertModel
# 加载预训练模型
pretrained = BertModel.from_pretrained('bert-base-chinese')
# 统计参数量
sum(i.numel() for i in pretrained.parameters()) / 10000
out:10226.7648

由上可知bert-base-chinese模型的参数量超过1亿个,这个模型的体量还是比较大的。由于它的体量比较大,所以如果要训练它,对计算资源的要求较高,而对于本次的二分类任务则可以选择不训练它,只是作为一个特征提取器。这样就可以避免训练这个笨重的模型,不需要计算它的梯度,进而不更新它的参数,所以需要冻结它的参数:

# 当不进行训练时不需要计算梯度
for param in pretrained.parameters():
    param.requires_grad_(False)

定义好PLM后,需要进行一次试算,观察模型的输入和输出结果:

# 设定计算设备
pretrained.to(device)
# 模型试算
out = pretrained(input_ids=input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids)
print(out.last_hidden_state.shape)

这里可能会报错:

RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu! (when checking argument for argument index in method wrapper_CUDA__index_select)

这是因为之前我们忘了将input_ids等参数放到cuda上,所以需要改一下代码:

for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(loader):
    break
input_ids = input_ids.to(device)
attention_mask = attention_mask.to(device)
token_type_ids = token_type_ids.to(device)
labels = labels.to(device)
print(len(loader))
print('input_ids', input_ids)
print('attention_mask_shape', attention_mask.shape)
print('token_type_ids_shape', token_type_ids.shape)
print('labels', labels)
print(input_ids.is_cuda)

这里如果有显卡的话会输出True,然后上面的程序报错也会消除,同时输出:

torch.Size([16, 500, 768])

上述代码中将我们的16个样例数据(在定义数据加载器部分)输入到预训练模型中,得到的计算结果和我们预想的是一致的。首先从第一个维度16可以看出是和我们的样例输入的句子数量有关的,随后的500是指每句话中包含了500个单词,因为max_length=500(在数据整理函数中定义),这就把之前所有的内容都串起来了。最后的768表示将每一个词抽成一个768维的向量。到此为止,我们已经通过预训练模型成功地把16句话转换成为了一个特征向量矩阵,这样就可以接入下面的下游任务模型做分类或者回归任务。

定义下游任务模型

下游任务模型的任务是对backbone抽取的特征进行进一步的计算,得到符合业务需求的计算结果,这里做的是一个二分类的结果,因为我们数据集中的labels只有两种。

# 定义下游任务模型
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.fc = torch.nn.Linear(768, 2).to(device)

    def forward(self, input_ids, attention_mask, token_type_ids):
        with torch.no_grad():
            out = pretrained(input_ids=input_ids,
                             attention_mask=attention_mask,
                             token_type_ids=token_type_ids)
        out = self.fc(out.last_hidden_state[:, 0])
        out = out.softmax(dim=1)
        return out


model = Model()
# 设置计算设备
model.to(device)

在这段代码中,定义了一个下游任务模型,该模型包括一个全连接的LinearModel,权重矩阵是768x2,所以它能够将一个768维度的向量转换成一个二维空间中。
上述的下游任务模型的计算流程为:

在这里插入图片描述
这里之所以丢弃后面466个词的特征,是因为BERT模型所致,具体的内容可以参考BERT模型的论文:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

下游任务模型试算

在最后我们使用刚才使用的batch=16的数据进行试算:

# 试算
print(model(input_ids=input_ids,
            attention_mask=attention_mask,
            token_type_ids=token_type_ids).shape)

其输出结果为:

torch.Size([16, 2])

由此可见这就是我们一开始所要求的16句话进行二分类的结果。

训练和测试

模型训练

模型定义完成之后,我们就可以对该模型进行训练了~代码如下:

from transformers import AdamW
from transformers.optimization import get_scheduler
def train():
  # 定义优化器
  optimizer = torch.optim.AdamW(model.parameters(), lr=5e-4)
  # 定义损失函数
  criterion = torch.nn.CrossEntropyLoss()
  # 定义学习率调节器
  scheduler = get_scheduler(name='linear',
                num_warmup_steps=0,
                num_training_steps=len(loader),
                optimizer=optimizer)
  # 将模型切换到训练模式
  model.train()
  # 按批次进行遍历训练数据集中的数据
  for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(loader):
    input_ids = input_ids.to(device)
    attention_mask = attention_mask.to(device)
    token_type_ids = token_type_ids.to(device)
    labels = labels.to(device)
    # 模型计算
    out = model(input_ids=input_ids, attention_mask=attention_mask, token_type_ids=token_type_ids).to(device)
    # 计算损失并使用梯度下降法优化模型参数
    loss = criterion(out, labels)
    loss.backward()
    optimizer.step()
    scheduler.step()
    optimizer.zero_grad()
    # 输出各项数据的情况,便于观察
    if i % 10 == 0:
        out = out.argmax(dim=1)
        accuracy = (out == labels).sum().item() / len(labels)
        lr = optimizer.state_dict()['param_groups'][0]['lr']
        print(i, loss.item(),lr, accuracy)
train()

在上述的代码中首先定义了优化器、损失函数、学习率调节器。其中优化器使用了HuggingFace提供的AdamW优化器,这是传统的Adam优化器的改进版本,在自然语言处理任务中,该优化器往往取得了比Adam优化器更加好的成绩,并且计算效率高。学习率调节器使用了HuggingFace提供的线性学习率调节器,它能够在训练过程中让学习率缓慢下降,而不是始终使用一致的学习率,因为在训练的后期阶段往往需要更小的学习率来微调参数有利于损失函数下降到最低点。这里的损失函数采用了分类任务中常用的CrossEntropyLoss交叉熵损失函数。
然后将下游任务模型切换到训练模式即可开始训练。最后每当优化10次模型参数时,就计算一次当前模型预测结果的正确率,并输出模型的损失函数、学习率,最终训练完毕的结果如下所示:
在这里插入图片描述
由上图可见在训练到大约200个steps时,模型已经能够达到85%左右的正确率,损失函数也如同预期一样随着训练过程不断下降,学习率亦如此。

模型测试

对于已经训练好的模型进行测试,以便验证训练的有效性,其测试代码如下:

def test():
  # 定义测试数据加载器
  loader_test = torch.utils.data.DataLoader(dataset = Dataset('test'),
                        batch_size = 32,
                        collate_fn = collate_fn,
                        shuffle = True,
                        drop_last = True)
  # 将下游任务模型切换到运行模式
  model.eval()
  correct = 0
  total = 0
  for i, (input_ids, attention_mask, token_type_ids, labels) in enumerate(loader_test):
      # 计算5个批次即可,不需要全部遍历
      input_ids = input_ids.to(device)
      attention_mask = attention_mask.to(device)
      token_type_ids = token_type_ids.to(device)  
      labels = labels.to(device)    
      if i == 5:
        break
      print(i)
      # 计算
      with torch.no_grad():
        out = model(input_ids=input_ids,attention_mask=attention_mask,token_type_ids=token_type_ids).to(device)
      # 统计正确率
      out = out.argmax(dim=1)
      correct += (out==labels).sum().item()
      total += len(labels)
  print(correct/total)

test()

在上述的代码中首先定义了测试数据集及其加载器,同时取出5个批次的数据让模型进行预测,最后将统计的正确率输出,运行结果为:

0
1
2
3
4
0.88125

最终模型取得了88.125%的正确率,这个正确率虽然不是很高,但是验证了下游任务模型即使在不训练basebone的情况下也可以达到一定的成绩。

省流版-全部代码

在这里插入图片描述

总结

本文通过一个情感分类的例子说明了使用BERT预训练模型抽取文本特征数据的方法,使用BERT作为backbone,相对于传统的RNN而言其计算量会稍稍大一些,但是BERT抽取的文本特征将更加完整,更容易被下游任务模型识别总结出数据之间的规律。所以在不对BERT预训练模型进行训练,而是简单应用于下游任务时也可以表现一个比较好的结果。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1240149.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

zookeeper单机版的搭建

一 zookeeper的搭建 1.1 上传zkjar包 1.2 搭建配置 1.解压压缩包 [rootlocalhost export]# tar -zxvf zookeeper-3.7.0-bin.tar.gz 2.创建data文件夹 [rootlocalhost export]# cd apache-zookeeper-3.7.0-bin/ [rootlocalhost apache-zookeeper-3.7.0-bin]# ls bin conf…

专业远程控制如何塑造安全体系?向日葵“全流程安全闭环”解析

安全是远程控制的重中之重,作为国民级远程控制品牌,向日葵远程控制就极为注重安全远控服务的塑造。近期向日葵发布了以安全和核心的新版“向日葵15”以及同步发布《贝锐向日葵远控安全标准白皮书》(下简称《白皮书》),…

2023年危险化学品生产单位安全生产管理人员证模拟考试题库及危险化学品生产单位安全生产管理人员理论考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2023年危险化学品生产单位安全生产管理人员证模拟考试题库及危险化学品生产单位安全生产管理人员理论考试试题是由安全生产模拟考试一点通提供,危险化学品生产单位安全生产管理人员证模拟考试题库是根据危…

DDD神药:去哪儿结合DDD,实现架构大调优

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中,最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题: 谈谈你的DDD落地经验? 谈谈你对DDD的理解&#x…

苹果 CEO 库克在找接班人;大英图书馆确认被勒索软件攻击丨 RTE 开发者日报 Vol.90

开发者朋友们大家好: 这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE (Real Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

Nginx配置Websocket

WebSocket 和HTTP虽然是不同协议,但是两者“握手”方式兼容。通过HTTP升级机制,使用HTTP的Upgrade和Connection协议头的方式可以将连接从HTTP升级为WebSocket。 Websocket 使用 ws 或 wss 的统一资源标志符,类似于 HTTPS,其中 wss…

【PyGIS】使用阿里AIEarth快速下载指定区域指定年份的土地利用数据

说明 中国逐年土地覆盖数据集(CLCD) 由武汉大学的杨杰和黄昕教授团队基于Landsat影像制作了中国逐年土地覆盖数据集(annual China Land Cover Dataset, CLCD),数据包含1985—2021年中国逐年土地覆盖信息。研究团队基于Landsat长时序卫星观测数据,构建时空特征,结合随机森…

JAVA毕业设计111—基于Java+Springboot+Vue的养老院管理系统(源码+数据库+12000字论文)

基于JavaSpringbootVue的养老院管理系统(源码数据库12000字论文)111 一、系统介绍 本系统前后端分离,本系统分为销售、人事、服务、餐饮、财务、超级管理员六种角色 系统主要功能如下: 首页统计:包括今日新增咨询、今日新增预定、今日新增…

java实现置顶功能

目录 一、需求描述 二、功能呈现 (一)需求分析 (二)关键设计披露 1、数据库字段 2、查询语句 一、需求描述 在查看公司列表数据时,我想最先看到我常用的公司。 也就是,我想把这个公司放在最前面&am…

攻防世界-web-Confusion1

1. 题目描述 打开链接,如图 点击Login和Rigister,都报错 但是有提示 指出了flag所在的位置,题目中直接能获取到的信息暂时就这么些了 2. 思路分析 既然告诉了我们flag文件的位置,那么要读取到这个文件,要么是任意文…

【EI会议征稿】第九届能源科学与化学工程国际学术研讨会 (ISESCE 2024)

第九届能源科学与化学工程国际学术研讨会 (ISESCE 2024) 2024 9th International Symposium on Energy Science and Chemical Engineering 第九届能源科学与化学工程国际学术研讨会(ISESCE 2024)定于2024年3月22-24日在中国南京…

时间序列预测建模的完整流程以及数据分析(新手科研必备)

一、本文介绍 本文给大家带来是时间序列建模的完整流程,大家在接触到这个领域的时候,往往都想将数据直接输入到模型中进行训练和预测,对于其中的一些参数都不太理解,这种情况是不可能得到一个好的结果的(本文的内容是…

基于 Flink CDC 打造企业级实时数据集成方案

本文整理自Flink数据通道的Flink负责人、Flink CDC开源社区的负责人、Apache Flink社区的PMC成员徐榜江在云栖大会开源大数据专场的分享。本篇内容主要分为四部分: CDC 数据实时集成的挑战Flink CDC 核心技术解读基于 Flink CDC 的企业级实时数据集成方案实时数据集…

实现centos7与windows共享文件夹

第一步 点击设置 第二步 第三步 第四步 让共享文件夹挂载到hgfs目录下 输入如下命令: sudo vmhgfs-fuse .host:/ /mnt/hgfs -o subtypevmhgfs-fuse,allow_other完成共享

电脑桌面便签工具选择哪一款?

随着互联网时代的不断发展,电脑成为日常工作及办公中必不可少的工具,通过电脑这款工具,大家可以更好的进行工作、学习等方面的交流;电脑桌面便签由于可以为大家整合一些工作及学习方面的备忘事项及笔记等,因而深受大家…

智慧社区建设管理方案,AI技术让小区更智能、更舒适

一、背景与需求分析 智慧社区是充分应用大数据、云计算、人工智能等信息技术手段,整合社区各类服务资源,打造基于信息化、智能化管理与服务的社区治理新形态。根据《关于深入推进智慧社区建设的意见》,到2025年,基本构建起网格化…

数据库数据恢复—MongoDB数据库文件拷贝出现错误的数据恢复案例

MongoDB数据库数据恢复环境: 一台Windows Server操作系统的虚拟机,虚拟机上部署有MongoDB数据库。 MongoDB数据库故障&检测: 在未关闭MongoDB服务的情况下,工作人员将MongoDB数据库文件拷贝到其他分区,然后将原数…

【idea】解决idea 执行maven build总下载 Downloading maven-metadata.xml文件

可以看到如下日志中打印了执行的命令行,其中包含 --update-snapshots,是强制更新的意思。 日志内容如下: D:\env\jdk1.8.0_261\bin\java.exe --update-snapshots -s D:\env\apache-maven-3.8.6\conf\settings.xml -Dmaven.repo.localD:\env\…

元素的点击操作

元素的点击操作 .click 语法 // 单击某个元素 .click()// 带参数的单击 .click(options)// 在某个位置点击 .click(position)// 在某个位置点击,且带参数 .click(position, options)// 根据页面坐标点击 .click(x, y)// 根据页面坐标点击,且带参数 .c…

三极管基础知识

三极管 基本概念应用电路 基本概念 三极管 NPN 和PNP 电流方向 PNP是从e 流向 b c NPN是从 b c流向e 应用电路 箭头出发方向的电极比箭头指向方向的电极,高0.7v才导通。 NPN控制下游是否接到地,PNP控制上游的电源能否接过来。