1-3.文本数据建模流程范例

文章最前: 我是Octopus,这个名字来源于我的中文名–章鱼;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github
;这博客是记录我学习的点点滴滴,如果您对 Python、Java、AI、算法有兴趣,可以关注我的动态,一起学习,共同进步。

import os#mac系统上pytorch和matplotlib在jupyter中同时跑需要更改环境变量
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" 
!pip install gensim 
!pip install torchkeras
import torch 
import gensim
import torchkeras 
print("torch.__version__ = ", torch.__version__)
print("gensim.__version__ = ", gensim.__version__) 
print("torchkeras.__version__ = ", torchkeras.__version__) 
torch.__version__ =  2.0.1
gensim.__version__ =  4.3.1
torchkeras.__version__ =  3.9.3

公众号 算法美食屋 回复关键词:pytorch, 获取本项目源码和所用数据集百度云盘下载链接。


一,准备数据

imdb数据集的目标是根据电影评论的文本内容预测评论的情感标签。

训练集有20000条电影评论文本,测试集有5000条电影评论文本,其中正面评论和负面评论都各占一半。

文本数据预处理较为繁琐,包括文本切词,构建词典,编码转换,序列填充,构建数据管道等等。

此处使用gensim中的词典工具并自定义Dataset。

下面进行演示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

import numpy as np 
import pandas as pd 
import torch MAX_LEN = 200           #每个样本保留200个词的长度
BATCH_SIZE = 20 dftrain = pd.read_csv("./eat_pytorch_datasets/imdb/train.tsv",sep="\t",header = None,names = ["label","text"])
dfval = pd.read_csv("./eat_pytorch_datasets/imdb/test.tsv",sep="\t",header = None,names = ["label","text"])
from gensim import corpora
import string#1,文本切词
def textsplit(text):translator = str.maketrans('', '', string.punctuation)words = text.translate(translator).split(' ')return words#2,构建词典
vocab = corpora.Dictionary((textsplit(text) for text in dftrain['text']))
vocab.filter_extremes(no_below=5,no_above=5000)
special_tokens = {'<pad>': 0, '<unk>': 1}
vocab.patch_with_special_tokens(special_tokens)
vocab_size = len(vocab.token2id) 
print('vocab_size = ',vocab_size)#3,序列填充
def pad(seq,max_length,pad_value=0):n = len(seq)result = seq+[pad_value]*max_lengthreturn result[:max_length]#4,编码转换
def text_pipeline(text):tokens = vocab.doc2idx(textsplit(text))tokens = [x if x>0 else special_tokens['<unk>']  for x in tokens ]result = pad(tokens,MAX_LEN,special_tokens['<pad>'])return result print(text_pipeline("this is an example!")) 
vocab_size =  29924
[145, 77, 569, 55, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

#5,构建管道
from torch.utils.data import Dataset,DataLoaderclass ImdbDataset(Dataset):def __init__(self,df):self.df = dfdef __len__(self):return len(self.df)def __getitem__(self,index):text = self.df["text"].iloc[index]label = torch.tensor([self.df["label"].iloc[index]]).float()tokens = torch.tensor(text_pipeline(text)).int() return tokens,labelds_train = ImdbDataset(dftrain)
ds_val = ImdbDataset(dfval)
dl_train = DataLoader(ds_train,batch_size = 50,shuffle = True)
dl_val = DataLoader(ds_val,batch_size = 50,shuffle = False)
for features,labels in dl_train:break 

二,定义模型

使用Pytorch通常有三种方式构建模型:使用nn.Sequential按层顺序构建模型,继承nn.Module基类构建自定义模型,继承nn.Module基类构建模型并辅助应用模型容器(nn.Sequential,nn.ModuleList,nn.ModuleDict)进行封装。

此处选择使用第三种方式进行构建。

import torch
from torch import nn 
torch.manual_seed(42)
<torch._C.Generator at 0x142700950>
class Net(nn.Module):def __init__(self):super(Net, self).__init__()#设置padding_idx参数后将在训练过程中将填充的token始终赋值为0向量self.embedding = nn.Embedding(num_embeddings = vocab_size,embedding_dim = 3,padding_idx = 0)self.conv = nn.Sequential()self.conv.add_module("conv_1",nn.Conv1d(in_channels = 3,out_channels = 16,kernel_size = 5))self.conv.add_module("pool_1",nn.MaxPool1d(kernel_size = 2))self.conv.add_module("relu_1",nn.ReLU())self.conv.add_module("conv_2",nn.Conv1d(in_channels = 16,out_channels = 128,kernel_size = 2))self.conv.add_module("pool_2",nn.MaxPool1d(kernel_size = 2))self.conv.add_module("relu_2",nn.ReLU())self.dense = nn.Sequential()self.dense.add_module("flatten",nn.Flatten())self.dense.add_module("linear",nn.Linear(6144,1))def forward(self,x):x = self.embedding(x).transpose(1,2)x = self.conv(x)y = self.dense(x)return ynet = Net() 
print(net)
Net((embedding): Embedding(29924, 3, padding_idx=0)(conv): Sequential((conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))(pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(relu_1): ReLU()(conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))(pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(relu_2): ReLU())(dense): Sequential((flatten): Flatten(start_dim=1, end_dim=-1)(linear): Linear(in_features=6144, out_features=1, bias=True))
)
Net((embedding): Embedding(8813, 3, padding_idx=0)(conv): Sequential((conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))(pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(relu_1): ReLU()(conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))(pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(relu_2): ReLU())(dense): Sequential((flatten): Flatten(start_dim=1, end_dim=-1)(linear): Linear(in_features=6144, out_features=1, bias=True))
)

from torchkeras import summary 
summary(net,input_data=features);
--------------------------------------------------------------------------
Layer (type)                            Output Shape              Param #
==========================================================================
Embedding-1                             [-1, 200, 3]               89,772
Conv1d-2                               [-1, 16, 196]                  256
MaxPool1d-3                             [-1, 16, 98]                    0
ReLU-4                                  [-1, 16, 98]                    0
Conv1d-5                               [-1, 128, 97]                4,224
MaxPool1d-6                            [-1, 128, 48]                    0
ReLU-7                                 [-1, 128, 48]                    0
Flatten-8                                 [-1, 6144]                    0
Linear-9                                     [-1, 1]                6,145
==========================================================================
Total params: 100,397
Trainable params: 100,397
Non-trainable params: 0
--------------------------------------------------------------------------
Input size (MB): 0.000069
Forward/backward pass size (MB): 0.287788
Params size (MB): 0.382984
Estimated Total Size (MB): 0.670841
--------------------------------------------------------------------------

三,训练模型

训练Pytorch通常需要用户编写自定义训练循环,训练循环的代码风格因人而异。

有3类典型的训练循环代码风格:脚本形式训练循环,函数形式训练循环,类形式训练循环。

此处介绍一种较通用的仿照Keras风格的类形式的训练循环。

该训练循环的代码也是torchkeras库的核心代码。

torchkeras详情: https://github.com/lyhue1991/torchkeras

import os,sys,time
import numpy as np
import pandas as pd
import datetime 
from tqdm import tqdm import torch
from torch import nn 
from copy import deepcopydef printlog(info):nowtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')print("\n"+"=========="*8 + "%s"%nowtime)print(str(info)+"\n")class StepRunner:def __init__(self, net, loss_fn,stage = "train", metrics_dict = None, optimizer = None, lr_scheduler = None):self.net,self.loss_fn,self.metrics_dict,self.stage = net,loss_fn,metrics_dict,stageself.optimizer,self.lr_scheduler = optimizer,lr_schedulerdef __call__(self, features, labels):#losspreds = self.net(features)loss = self.loss_fn(preds,labels)#backward()if self.optimizer is not None and self.stage=="train":loss.backward()self.optimizer.step()if self.lr_scheduler is not None:self.lr_scheduler.step()self.optimizer.zero_grad()#metricsstep_metrics = {self.stage+"_"+name:metric_fn(preds, labels).item() for name,metric_fn in self.metrics_dict.items()}return loss.item(),step_metricsclass EpochRunner:def __init__(self,steprunner):self.steprunner = steprunnerself.stage = steprunner.stageself.steprunner.net.train() if self.stage=="train" else self.steprunner.net.eval()def __call__(self,dataloader):total_loss,step = 0,0loop = tqdm(enumerate(dataloader), total =len(dataloader))for i, batch in loop: if self.stage=="train":loss, step_metrics = self.steprunner(*batch)else:with torch.no_grad():loss, step_metrics = self.steprunner(*batch)step_log = dict({self.stage+"_loss":loss},**step_metrics)total_loss += lossstep+=1if i!=len(dataloader)-1:loop.set_postfix(**step_log)else:epoch_loss = total_loss/stepepoch_metrics = {self.stage+"_"+name:metric_fn.compute().item() for name,metric_fn in self.steprunner.metrics_dict.items()}epoch_log = dict({self.stage+"_loss":epoch_loss},**epoch_metrics)loop.set_postfix(**epoch_log)for name,metric_fn in self.steprunner.metrics_dict.items():metric_fn.reset()return epoch_logclass KerasModel(torch.nn.Module):def __init__(self,net,loss_fn,metrics_dict=None,optimizer=None,lr_scheduler = None):super().__init__()self.history = {}self.net = netself.loss_fn = loss_fnself.metrics_dict = nn.ModuleDict(metrics_dict) self.optimizer = optimizer if optimizer is not None else torch.optim.Adam(self.parameters(), lr=1e-2)self.lr_scheduler = lr_schedulerdef forward(self, x):if self.net:return self.net.forward(x)else:raise NotImplementedErrordef fit(self, train_data, val_data=None, epochs=10, ckpt_path='checkpoint.pt', patience=5, monitor="val_loss", mode="min"):for epoch in range(1, epochs+1):printlog("Epoch {0} / {1}".format(epoch, epochs))# 1,train -------------------------------------------------  train_step_runner = StepRunner(net = self.net,stage="train",loss_fn = self.loss_fn,metrics_dict=deepcopy(self.metrics_dict),optimizer = self.optimizer, lr_scheduler = self.lr_scheduler)train_epoch_runner = EpochRunner(train_step_runner)train_metrics = train_epoch_runner(train_data)for name, metric in train_metrics.items():self.history[name] = self.history.get(name, []) + [metric]# 2,validate -------------------------------------------------if val_data:val_step_runner = StepRunner(net = self.net,stage="val",loss_fn = self.loss_fn,metrics_dict=deepcopy(self.metrics_dict))val_epoch_runner = EpochRunner(val_step_runner)with torch.no_grad():val_metrics = val_epoch_runner(val_data)val_metrics["epoch"] = epochfor name, metric in val_metrics.items():self.history[name] = self.history.get(name, []) + [metric]# 3,early-stopping -------------------------------------------------if not val_data:continuearr_scores = self.history[monitor]best_score_idx = np.argmax(arr_scores) if mode=="max" else np.argmin(arr_scores)if best_score_idx==len(arr_scores)-1:torch.save(self.net.state_dict(),ckpt_path)print("<<<<<< reach best {0} : {1} >>>>>>".format(monitor,arr_scores[best_score_idx]),file=sys.stderr)if len(arr_scores)-best_score_idx>patience:print("<<<<<< {} without improvement in {} epoch, early stopping >>>>>>".format(monitor,patience),file=sys.stderr)break self.net.load_state_dict(torch.load(ckpt_path))  return pd.DataFrame(self.history)@torch.no_grad()def evaluate(self, val_data):val_step_runner = StepRunner(net = self.net,stage="val",loss_fn = self.loss_fn,metrics_dict=deepcopy(self.metrics_dict))val_epoch_runner = EpochRunner(val_step_runner)val_metrics = val_epoch_runner(val_data)return val_metrics@torch.no_grad()def predict(self, dataloader):self.net.eval()result = torch.cat([self.forward(t[0]) for t in dataloader])return result.data
from torchmetrics import Accuracynet = Net() 
model = KerasModel(net,loss_fn = nn.BCEWithLogitsLoss(),optimizer= torch.optim.Adam(net.parameters(),lr = 0.01),  metrics_dict = {"acc":Accuracy(task='binary')})
model.fit(dl_train,val_data=dl_val,epochs=10,ckpt_path='checkpoint',patience=3,monitor='val_acc',mode='max')
================================================================================2023-08-02 14:20:21
Epoch 1 / 10100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 400/400 [00:10<00:00, 39.28it/s, train_acc=0.496, train_loss=0.701]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [00:01<00:00, 51.21it/s, val_acc=0.518, val_loss=0.693]
<<<<<< reach best val_acc : 0.5180000066757202 >>>>>>================================================================================2023-08-02 14:20:33
Epoch 2 / 10100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 400/400 [00:09<00:00, 40.14it/s, train_acc=0.503, train_loss=0.693]
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [00:01<00:00, 54.22it/s, val_acc=0.58, val_loss=0.689]
<<<<<< reach best val_acc : 0.5803999900817871 >>>>>>================================================================================2023-08-02 14:20:45
Epoch 3 / 10100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 400/400 [00:10<00:00, 39.46it/s, train_acc=0.69, train_loss=0.58]
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [00:01<00:00, 53.84it/s, val_acc=0.781, val_loss=0.47]
<<<<<< reach best val_acc : 0.7807999849319458 >>>>>>================================================================================2023-08-02 14:20:57
Epoch 4 / 10100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 400/400 [00:09<00:00, 40.33it/s, train_acc=0.83, train_loss=0.386]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [00:01<00:00, 54.18it/s, val_acc=0.819, val_loss=0.408]
<<<<<< reach best val_acc : 0.8194000124931335 >>>>>>================================================================================2023-08-02 14:21:09
Epoch 5 / 10100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 400/400 [00:09<00:00, 40.63it/s, train_acc=0.893, train_loss=0.262]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [00:01<00:00, 55.69it/s, val_acc=0.836, val_loss=0.395]
<<<<<< reach best val_acc : 0.8357999920845032 >>>>>>================================================================================2023-08-02 14:21:21
Epoch 6 / 10100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 400/400 [00:09<00:00, 40.58it/s, train_acc=0.932, train_loss=0.176]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [00:01<00:00, 50.93it/s, val_acc=0.828, val_loss=0.456]================================================================================2023-08-02 14:21:33
Epoch 7 / 10100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 400/400 [00:10<00:00, 39.62it/s, train_acc=0.956, train_loss=0.119]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [00:01<00:00, 55.26it/s, val_acc=0.829, val_loss=0.558]================================================================================2023-08-02 14:21:44
Epoch 8 / 10100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 400/400 [00:09<00:00, 40.58it/s, train_acc=0.973, train_loss=0.0754]
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [00:01<00:00, 52.91it/s, val_acc=0.823, val_loss=0.67]
<<<<<< val_acc without improvement in 3 epoch, early stopping >>>>>>
train_losstrain_accval_lossval_accepoch
00.7010640.495800.6930450.51801
10.6930600.503350.6886560.58042
20.5798670.690100.4695740.78083
30.3856250.829900.4076330.81944
40.2616530.892600.3949010.83585
50.1759210.932100.4556040.82846
60.1191780.956100.5584300.82867
70.0754090.973300.6701720.82328


四,评估模型

import pandas as pd history = model.history
dfhistory = pd.DataFrame(history) 
dfhistory 
train_losstrain_accval_lossval_accepoch
00.7010640.495800.6930450.51801
10.6930600.503350.6886560.58042
20.5798670.690100.4695740.78083
30.3856250.829900.4076330.81944
40.2616530.892600.3949010.83585
50.1759210.932100.4556040.82846
60.1191780.956100.5584300.82867
70.0754090.973300.6701720.82328
%matplotlib inline
%config InlineBackend.figure_format = 'svg'import matplotlib.pyplot as pltdef plot_metric(dfhistory, metric):train_metrics = dfhistory["train_"+metric]val_metrics = dfhistory['val_'+metric]epochs = range(1, len(train_metrics) + 1)plt.plot(epochs, train_metrics, 'bo--')plt.plot(epochs, val_metrics, 'ro-')plt.title('Training and validation '+ metric)plt.xlabel("Epochs")plt.ylabel(metric)plt.legend(["train_"+metric, 'val_'+metric])plt.show()
plot_metric(dfhistory,"loss")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

plot_metric(dfhistory,"acc")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

# 评估
model.evaluate(dl_val)
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 100/100 [00:01<00:00, 50.26it/s, val_acc=0.836, val_loss=0.395]{'val_loss': 0.39490113019943235, 'val_acc': 0.8357999920845032}

五,使用模型

def predict(net,dl):net.eval()with torch.no_grad():result = nn.Sigmoid()(torch.cat([net.forward(t[0]) for t in dl]))return(result.data)
y_pred_probs = predict(net,dl_val)
y_pred_probs
tensor([[0.9372],[1.0000],[0.8672],...,[0.5141],[0.4756],[0.9998]])

六,保存模型

#模型权重已经被保存在了ckpt_path='checkpoint.'
net_clone = Net()
net_clone.load_state_dict(torch.load('checkpoint'))
<All keys matched successfully>

如果本书对你有所帮助,想鼓励一下作者,记得给本项目加一颗星星star⭐️,并分享给你的朋友们喔😊!

如果对本书内容理解上有需要进一步和作者交流的地方,欢迎在公众号"算法美食屋"下留言。作者时间和精力有限,会酌情予以回复。

也可以在公众号后台回复关键字:加群,加入读者交流群和大家讨论。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

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

相关文章

基于隐马尔可夫模型的股票预测【HMM】

基于机器学习方法的股票预测系列文章目录 一、基于强化学习DQN的股票预测【股票交易】 二、基于CNN的股票预测方法【卷积神经网络】 三、基于隐马尔可夫模型的股票预测【HMM】 文章目录 基于机器学习方法的股票预测系列文章目录一、HMM模型简介&#xff08;1&#xff09;前向后…

复杂系统失效原理

原文How Complex System Fail原文作者Richard I. Cook 1. 复杂系统本质上是危险的 所有重要系统&#xff08;如交通、医疗、电力等&#xff09;&#xff0c;出于自身性质的原因&#xff0c;必然是危险的。虽然系统发生故障的频率不断变化&#xff0c;系统内部处理流程在本质上…

监控易监测对象及指标之:全面监测IBM Domino邮件服务器的关键指标

在现代企业通信中&#xff0c;IBM Domino邮件服务器以其稳定性和丰富的功能而备受青睐。为了确保邮件服务器的顺畅运行&#xff0c;对其各项性能指标进行全面监测至关重要。监控易作为一款高效的监控工具&#xff0c;为IBM Domino邮件服务器提供了一系列精细的监测指标。 首先&…

使用 BroadcastChannel 实现浏览器标签页之间的通信

在现代的 Web 应用程序中&#xff0c;有时需要在不同的浏览器标签页或窗口之间进行通信。为了实现这种通信&#xff0c;我们可以使用 BroadcastChannel 接口。BroadcastChannel 允许我们在同一浏览器上的不同上下文之间发送消息&#xff0c;包括不同的标签页、窗口或同一页面中…

华为:坚持实事求是的进行产品及技术创新

作为国内自主创新&#xff0c;尤其是产品和技术创新的标志性企业&#xff0c;华为值得国内企业借鉴的经验是多方面的&#xff0c;但如果一定要总结为一条的话&#xff0c;那就是——实事求是的自主创新。最近&#xff0c;华为任正非总裁的一个讲话以“实事求是的科研方向和二十…

全球首款搭载Google Gemini和GPT-4o的智能眼镜发布

智能眼镜仍然是一个尚未完全成熟的未来概念&#xff0c;但生成式人工智能的到来显著提升了这些设备的能力。Meta 的 Ray-Ban 智能眼镜被许多人视为当今最好的选择之一&#xff0c;而现在 Solos AirGo Vision 正在为其带来竞争&#xff0c;这款眼镜还集成了 Google Gemini 支持。…

生命在于学习——Python人工智能原理(3.1.1)

Python部分结束了&#xff0c;开始概率论部分 一、概率基本知识 1.1 事件与概率 1.1.1 事件的运算与关系 &#xff08;一&#xff09;基本概念 定义1 随机试验 如果一个试验满足如下条件&#xff1a; 在试验前不能断定其将发生什么结果&#xff0c;但可明确指出或说明试验…

浅聊JavaScript中的栈(stack)

前言 这篇文章结合leetcode题目讲解一下栈这种结构 第20题&#xff1a;20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 第LCR-147题LCR 147. 最小栈 - 力扣&#xff08;LeetCode&#xff09; 栈&#xff08;stack&#xff09; 在讲解题目之前&#xff0c;我们先来…

HTTPS是什么?原理是什么?用公钥加密为什么不能用公钥解密?

HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;是HTTP的安全版本&#xff0c;它通过在HTTP协议之上加入SSL/TLS协议来实现数据加密传输&#xff0c;确保数据在客户端和服务器之间的传输过程中不会被窃取或篡改。 HTTPS 的工作原理 客户端发起HTTPS请求&…

primetime中cell和net的OCV

文章目录 前言一、Cell OCV1. POCV coefficient file2. POCV Slew-Load Table in Liberty Variation Format&#xff08;LVF lib&#xff09; 二、Net OCV三、如何check OCV是否已加上&#xff1f;总结 前言 在生产中&#xff0c;外界环境的各种变化&#xff0c;比如PVT&#…

4、DDD、中台和微服务的关系

DDD、中台和微服务的关系 1 DDD和中台的本质 领域驱动设计&#xff08;DDD&#xff09;和中台在企业架构中有着密切的关系。DDD的本质在于通过对业务领域的深入分析和建模&#xff0c;构建高内聚、低耦合的系统。而中台则是对企业核心业务能力的抽象和封装&#xff0c;以实现…

中英双语介绍美国常春藤联盟( Ivy League):八所高校

中文版 常春藤联盟简介 常春藤联盟&#xff08;Ivy League&#xff09;是美国东北部八所私立大学组成的高校联盟。虽然最初是因体育联盟而得名&#xff0c;但这些学校以其学术卓越、历史悠久、校友杰出而闻名于世。以下是对常春藤联盟的详细介绍&#xff0c;包括其由来、成员…

统一 REST 接口规范:提升低代码平台研发效率

1.背景 在一个低代码研发团队的办公室里&#xff0c;大家正忙碌着。小张在调试组件&#xff0c;小李在优化性能&#xff0c;小王则在制定新项目的技术方案。 这时&#xff0c;团队负责人小刘走进来&#xff0c;对大家说&#xff1a;“我们需要聊聊 REST 接口规范的问题。”他指…

C语言之线程的学习

线程属于某一个进程 共同点&#xff1a;都能并发 线程共享变量&#xff0c;进程不共享。 多线程任务中&#xff0c;其中某一个线程调用了exit了&#xff0c;其他线程会跟着一起退出 如果是特定的线程就调用pthread_exit 失败返回的是错误号 下面也是

企业为何要进行互联网收口

互联网收口又被称为网络出口收敛或网络出口整合&#xff0c;顾名思义&#xff0c;是通过技术手段将多个网络出口合并为一个或少数几个出口的过程&#xff0c;以优化网络性能、提高安全性和降低运营成本。在本文中&#xff0c;我们将深入探讨企业互联网收口的重要性&#xff0c;…

代码随想录-Day44

322. 零钱兑换 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。 你可以认为每种硬币的数…

科普文:一文搞懂jvm原理(三)执行引擎

概叙 科普文&#xff1a;一文搞懂jvm(一)jvm概叙-CSDN博客 科普文&#xff1a;一文搞懂jvm原理(二)类加载器-CSDN博客 前面我们介绍了jvm&#xff0c;jvm主要包括两个子系统和两个组件&#xff1a; Class loader(类装载器) 子系统&#xff0c;Execution engine(执行引擎) 子系…

16_C语言编程基础

目录 C语言入门 程序段和代码段 C语言入门实例 英文分号(;) 注释 标识符 保留字 C中的空格 C数据类型 基本类型 sizeof获取存储字节 void类型 变量 C数组 C枚举 C中的左值(lvalue)和右值(rvalue) C常量 变量存储类型 C常用关键字(保留字) 宏定义#define co…

Codeforces Round955 (Div2)--(A~D)题解

Problem - A - Codeforces 思路&#xff1a;如果领先方互换&#xff0c;那么“NO”&#xff0c;否则“YES”。 void solve(){ Aint x1,y1; cin>>x1>>y1;int x2,y2; cin>>x2>>y2;if(x1>y1&&x2>y2||x1<y1&&…

生成式AI:未来商业的变革者

在2023年&#xff0c;生成式人工智能&#xff08;GenAI&#xff09;的浪潮席卷了全球&#xff0c;成为科技领域最炙手可热的话题之一。它不仅改变了我们与机器的互动方式&#xff0c;更在商业创新和生产力提升方面发挥了巨大的作用。本文将深入探讨2024年生成式AI的应用模式、趋…