Pytorch NLP入门3:用嵌入表示单词

初次编辑时间:2024/3/17;最后编辑时间:2024/3/17

本栏目链接:https://blog.csdn.net/qq_33345365/category_12597850.html

本人的其他栏目:

pytorch 基础的栏目链接:https://blog.csdn.net/qq_33345365/category_12591348.html

pytorch CV的栏目链接:https://blog.csdn.net/qq_33345365/category_12578430.html

用嵌入表示单词

1 嵌入 Embeddings

在我们之前的示例中,我们对长度为vocab_size的高维词袋向量进行操作,并且明确地将低维位置表示向量转换为稀疏的独热(one-hot)表示。

通过找到单词近似于其他单词的意义来理解单词的含义。这是通过取两个单词向量并分析向量中的单词如何经常一起使用来完成的。频率越高,单词之间的相关性和关系就越大。 训练词嵌入以在给定维度中找到单词之间的近似是我们将单词表示减少到低维度的方法。 嵌入向量作为单词的数值表示,并被用作输入到其他机器学习网络层。 嵌入向量成为词汇表中单词的存储查找表。 在本单元中,我们将继续探索新闻AG数据集。首先,让我们加载数据并从上一单元中获取一些定义。此外,我们将分配我们的训练和测试数据集;词汇表大小;以及我们词类的类别:世界、体育、商业和科技。

准备文件

wget -q https://raw.githubusercontent.com/MicrosoftDocs/pytorchfundamentals/main/nlp-pytorch/torchnlp.py

加载库

import torch
import torchtext
from torchtext.data import get_tokenizer
import numpy as np
from torchnlp import *
from torchinfo import summary
train_dataset, test_dataset, classes, vocab = load_dataset()

2 处理可变的序列大小

在处理单词时,你会遇到长度不同的文本序列或句子。这可能在训练单词嵌入神经网络时造成问题。为了保持单词嵌入的一致性并提高训练性能,我们需要对标记化的数据集应用一些填充操作。这可以通过使用torch.nn.functional.pad来实现,在向量末尾的空索引处添加零值。

def padify(b):# b is the list of tuples of length batch_size#   - first element of a tuple = label, #   - second = feature (text sequence)# build vectorized sequencev = [encode(x[1]) for x in b]# 首先,计算这个小批量中序列的最大长度l = max(map(len,v))return ( # 张量的元组 - 标签和特征torch.LongTensor([t[0]-1 for t in b]),torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v]))

让我们以前两个句子为例来查看文本长度差异和填充效果。

first_sentence = train_dataset[0][1]
second_sentence = train_dataset[1][1]f_tokens = encode(first_sentence)
s_tokens = encode(second_sentence)print(f'First Sentence in dataset:\n{first_sentence}')
print("Length:", len(train_dataset[0][1]))
print(f'\nSecond Sentence in dataset:\n{second_sentence}')
print("Length: ", len(train_dataset[1][1]))

输出是:

First Sentence in dataset:
Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\band of ultra-cynics, are seeing green again.
Length: 144Second Sentence in dataset:
Carlyle Looks Toward Commercial Aerospace (Reuters) Reuters - Private investment firm Carlyle Group,\which has a reputation for making well-timed and occasionally\controversial plays in the defense industry, has quietly placed\its bets on another part of the market.
Length:  266

我们将使用数据集中新闻标题的文本序列,将其转换为分词向量。正如您将看到的那样,文本序列的长度不同。我们将应用填充(padding)的方法,以使所有文本序列具有固定的长度。这种方法在您的数据集中有大量文本序列时使用。

  • 第一句和第二句的长度不同。
  • 数据集张量的最大长度是整个数据集中最长句子的长度。
  • 在张量中的空白索引处添加零。
vocab_size = len(vocab)
labels, features = padify(train_dataset)  
print(f'features: {features}')print(f'\nlength of first sentence: {len(f_tokens)}')
print(f'length of second sentence: {len(s_tokens)}')
print(f'size of features: {features.size()}')

输出:

features: tensor([[  432,   426,     2,  ...,     0,     0,     0],[15875,  1073,   855,  ...,     0,     0,     0],[   59,     9,   348,  ...,     0,     0,     0],...,[ 7736,    63,   665,  ...,     0,     0,     0],[   97,    17,    10,  ...,     0,     0,     0],[ 2155,   223,  2405,  ...,     0,     0,     0]])length of first sentence: 29
length of second sentence: 42
size of features: torch.Size([120000, 207])

3 什么是嵌入 What is embedding

嵌入(Embedding)的概念是将单词映射到向量中,这反映了单词的语义含义。其向量的长度是嵌入维度的大小。我们稍后会讨论如何构建有意义的单词嵌入,但现在让我们将嵌入视为降低单词向量维度的一种方式。

因此,嵌入层会接受一个单词作为输入,并产生一个指定嵌入尺寸的输出向量。在某种意义上,它与线性层非常相似,但它不是接受独热编码向量作为输入,而是可以接受单词编号作为输入。

通过在网络中使用嵌入层作为第一层,我们可以从基于词袋(bag-of-words)的模型切换到嵌入包(embedding bag)模型,在这种模型中,我们首先将文本中的每个单词转换为相应的嵌入,然后计算所有这些嵌入的一些聚合函数,如sumaveragemax

神经网络分类器将从嵌入层开始,然后是聚合层,最后是线性分类器:

  • vocab_size 表示我们词汇表中单词的总数。
  • embed_dim 表示用于表示单词之间关系的词向量的长度。
  • num_class 表示我们尝试分类的新闻类别数量(例如世界新闻、体育新闻、商业新闻、科技新闻)。
class EmbedClassifier(torch.nn.Module):def __init__(self, vocab_size, embed_dim, num_class):super().__init__()self.embedding = torch.nn.Embedding(vocab_size, embed_dim)self.fc = torch.nn.Linear(embed_dim, num_class)def forward(self, x):x = self.embedding(x)x = torch.mean(x,dim=1)return self.fc(x)

4 训练嵌入分类器

现在我们将定义我们的训练数据加载器,并使用collate_fn将padify函数应用于每个批次加载的数据集。结果是,训练数据集将被填充。

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=padify, shuffle=True)

我们可以使用前一个单元中定义的训练函数来训练模型,以运行嵌入网络。训练输出作为基于词汇表中唯一索引标记的向量查找存储。

net = EmbedClassifier(vocab_size,32,len(classes)).to(device)
train_epoch(net,train_loader, lr=1, epoch_size=25000)

输出是:

3200: acc=0.64875
6400: acc=0.69234375
9600: acc=0.7110416666666667
12800: acc=0.72421875
16000: acc=0.73625
19200: acc=0.7476041666666666
22400: acc=0.7541964285714285(0.9072840441058861, 0.7583173384516955)

请注意:出于时间考虑,我们只对 25k 条记录进行训练(不到一个完整的周期),但您可以继续训练,编写一个函数来进行多个周期的训练,并尝试不同的学习率参数以达到更高的准确率。您应该能够将准确率提高到约 90%。

5 EmbeddingBag层和变长序列表示

在以前的架构中,我们需要将所有序列填充到相同的长度,以便将它们适应一个小批量。这并不是表示可变长度序列的最有效方式 - 另一种方法是使用偏移向量,该向量将存储在一个大向量中的所有序列的偏移量。

注意:在上面的图片中,我们展示了一个字符序列,但在我们的示例中,我们处理的是单词序列。然而,使用偏移向量表示序列的一般原则保持不变。

要使用偏移表示进行工作,我们使用PyTorch的EmbeddingBag层。它类似于Embedding,但它接受内容向量和偏移向量作为输入,并且还包括平均层,可以是meansummax

这里是修改后使用EmbeddingBag的网络:

class EmbedClassifier(torch.nn.Module):def __init__(self, vocab_size, embed_dim, num_class):super().__init__()self.embedding = torch.nn.EmbeddingBag(vocab_size, embed_dim)self.fc = torch.nn.Linear(embed_dim, num_class)def forward(self, text, off):x = self.embedding(text, off)return self.fc(x)

为了准备训练数据集,我们需要提供一个转换函数来准备偏移量向量:

def offsetify(b):# first, compute data tensor from all sequencesx = [torch.tensor(encode(t[1])) for t in b]# now, compute the offsets by accumulating the tensor of sequence lengthso = [0] + [len(t) for t in x]o = torch.tensor(o[:-1]).cumsum(dim=0)return ( torch.LongTensor([t[0]-1 for t in b]), # labelstorch.cat(x), # text o)train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=offsetify, shuffle=True)

偏移向量是通过首先将句子索引合并为一个张量序列,然后提取每个句子在序列中的起始索引位置来计算的。例如:

  • 我们训练数据集中第一句话的长度为29。这意味着偏移的第一个索引将是0
  • 数据集中第二句话的长度为42。这意味着偏移的第二个索引将是29,即第一句话结束的位置。
  • 偏移的第三个索引将是29 + 42 = 71,即第二句话结束的位置。
labels, features, offset = offsetify(train_dataset)  
print(f'offset: {offset}')
print(f'\nlength of first sentence: {len(f_tokens)}')
print(f'length of second sentence: {len(s_tokens)}')
print(f'size of data vector: {features.size()}')
print(f'size of offset vector: {offset.size()}')

输出是:

offset: tensor([      0,      29,      71,  ..., 5193441, 5193488, 5193569])length of first sentence: 29
length of second sentence: 42
size of data vector: torch.Size([5193609])
size of offset vector: torch.Size([120000])

注意:与以往所有示例不同的是,我们的网络现在接受两个参数:数据向量和偏移向量,它们的大小不同。同样,我们的数据加载器也提供了3个值,而不是2个:文本和偏移向量都作为特征提供。因此,我们需要稍微调整我们的训练函数来处理这种情况。

net = EmbedClassifier(vocab_size,32,len(classes)).to(device)def train_epoch_emb(net,dataloader,lr=0.01,optimizer=None,loss_fn = torch.nn.CrossEntropyLoss(),epoch_size=None, report_freq=200):optimizer = optimizer or torch.optim.Adam(net.parameters(),lr=lr)loss_fn = loss_fn.to(device)net.train()total_loss,acc,count,i = 0,0,0,0for labels,text,off in dataloader:optimizer.zero_grad()labels,text,off = labels.to(device), text.to(device), off.to(device)out = net(text, off)loss = loss_fn(out,labels) #cross_entropy(out,labels)loss.backward()optimizer.step()total_loss+=loss_,predicted = torch.max(out,1)acc+=(predicted==labels).sum()count+=len(labels)i+=1if i%report_freq==0:print(f"{count}: acc={acc.item()/count}")if epoch_size and count>epoch_size:breakreturn total_loss.item()/count, acc.item()/counttrain_epoch_emb(net,train_loader, lr=4, epoch_size=25000)

输出是:

3200: acc=0.6496875
6400: acc=0.6853125
9600: acc=0.7097916666666667
12800: acc=0.725546875
16000: acc=0.737375
19200: acc=0.7446354166666667
22400: acc=0.7532589285714286
(22.52296015275112, 0.7591570697376839)

6 语义嵌入:Word2Vec

Word2Vec是一种用于训练语义嵌入模型的技术,它有两种主要的架构:Continuous Bag-of-Words(CBoW)和Continuous Skip-gram。在CBoW架构中,模型通过周围的上下文来预测当前词语,而在Skip-gram架构中,则是通过当前词语来预测周围的上下文。这些预测性的嵌入技术仅考虑局部上下文,而不考虑全局上下文。

除了Word2Vec外,还有其他的词嵌入技术,如GloVe和FastText。GloVe是通过词对出现的频率来推断词语之间的关系,而FastText则在Word2Vec的基础上学习每个词语和词中字符n-gram的向量表示,然后将这些表示的值平均为一个向量。

Gensim是一个开源的NLP Python库,提供了构建词向量、语料库、进行主题识别等NLP任务的统一接口。

在Word2Vec的例子中,我们将使用预训练的语义嵌入模型,但了解如何使用FastText、CBoW或Skip-gram架构来训练这些嵌入向量也是很有趣的。这些练习超出了本模块的范围,但有兴趣的人可以参考Pytorch网站上关于Word Embeddings的教程。

7 Genim

gensim框架可以与Pytorch一起使用,只需几行代码就可以训练最常用的嵌入。为了使用在Google News数据集上预训练的word2vec嵌入进行实验,我们可以使用gensim库。以下是找到与’neural’最相似的单词:

**注意:**第一次创建单词向量时,下载可能需要一些时间!

import gensim.downloader as api
w2v = api.load('word2vec-google-news-300')

让我们来看看和’dog’相似的单词。

for w,p in w2v.most_similar('dog'):print(f"{w} -> {p}")

输出是:

dogs -> 0.8680489659309387
puppy -> 0.8106428384780884
pit_bull -> 0.780396044254303
pooch -> 0.7627377510070801
cat -> 0.7609456777572632
golden_retriever -> 0.7500902414321899
German_shepherd -> 0.7465174198150635
Rottweiler -> 0.7437614798545837
beagle -> 0.7418621778488159
pup -> 0.740691065788269

我们还可以从单词中提取向量嵌入,用于训练分类模型(为了清晰起见,我们只显示向量的前20个分量):

w2v.word_vec('play')[:20]

输出是:

array([ 0.01226807,  0.06225586,  0.10693359,  0.05810547,  0.23828125,0.03686523,  0.05151367, -0.20703125,  0.01989746,  0.10058594,-0.03759766, -0.1015625 , -0.15820312, -0.08105469, -0.0390625 ,-0.05053711,  0.16015625,  0.2578125 ,  0.10058594, -0.25976562],dtype=float32)

语义嵌入的伟大之处在于您可以操作向量编码以改变语义。例如,我们可以要求找到一个词,其向量表示与king和woman尽可能接近,但与man尽可能远。

w2v.most_similar(positive=['king','woman'],negative=['man'])[0]

输出:

('queen', 0.7118192911148071)

8 在PyTorch中使用预训练嵌入

我们可以修改上面的例子,将我们的嵌入层中的矩阵预先填充为语义嵌入,比如Word2Vec。我们需要考虑到预训练嵌入的词汇表是对我们已有的文本语料库的补充,因此它们可能不完全匹配。因此,我们将为缺失的单词初始化随机值的权重:

embed_size = len(w2v.get_vector('hello'))
print(f'Embedding size: {embed_size}')net = EmbedClassifier(vocab_size,embed_size,len(classes))print('Populating matrix, this will take some time...',end='')
found, not_found = 0,0
for i,w in enumerate(vocab.itos):try:net.embedding.weight[i].data = torch.tensor(w2v.get_vector(w))found+=1except:net.embedding.weight[i].data = torch.normal(0.0,1.0,(embed_size,))not_found+=1print(f"Done, found {found} words, {not_found} words missing")
net = net.to(device)

输出是:

Embedding size: 300
Populating matrix, this will take some time...Done, found 41080 words, 54732 words missing

现在让我们训练我们的模型。请注意,由于较大的嵌入层大小,模型训练所需的时间显着增加,因此参数数量也更多。因此,如果我们想要避免过拟合,可能需要在更多的示例上训练我们的模型。

train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)

输出是:

3200: acc=0.6409375
6400: acc=0.6875
9600: acc=0.7163541666666666
12800: acc=0.730859375
16000: acc=0.740875
19200: acc=0.7510416666666667
22400: acc=0.7584821428571429
(228.52019353806782, 0.7641154830454254)

在我们的情况下,我们没有看到准确率的显著增加,这可能是因为词汇表有很大的差异。

为了解决不同词汇表的问题,我们可以使用以下其中一种解决方案:

  • 在我们的词汇表上重新训练Word2Vec模型
  • 使用预训练的Word2Vec模型的词汇表加载我们的数据集。在加载数据集时可以指定用于加载数据集的词汇表。

后一种方法似乎更容易,特别是因为PyTorch的torchtext框架内置了对嵌入的支持。

9 GloVe嵌入

为了从预训练的word2vec模型中加载词汇表,我们使用Glove嵌入。我们将以以下方式实例化基于手套的词汇:

vocab = torchtext.vocab.GloVe(name='6B', dim=50)

加载的词汇表具有以下基本操作:

  • vocab.stoi 字典允许我们将单词转换为其字典索引
  • vocab.itos 则反之 - 将数字转换为单词
  • vocab.vectors 是嵌入向量的数组,因此要获取单词的嵌入,我们需要使用 vocab.vectors[vocab.stoi[s]]

这里是操纵嵌入向量的示例,以演示等式 kind-man+woman = queen(系数稍作调整以使其有效):

# get the vector corresponding to kind-man+woman
qvec = vocab.vectors[vocab.stoi['king']]-vocab.vectors[vocab.stoi['man']]+1.3*vocab.vectors[vocab.stoi['woman']]
# find the index of the closest embedding vector 
d = torch.sum((vocab.vectors-qvec)**2,dim=1)
min_idx = torch.argmin(d)
# find the corresponding word
vocab.itos[min_idx]

输出是:

'queen'

为了使用这些嵌入训练分类器,我们首先需要使用GloVe词汇对我们的数据集进行编码:

def offsetify(b):# first, compute data tensor from all sequencesx = [torch.tensor(encode(t[1],voc=vocab)) for t in b] # pass the instance of vocab to encode function!# now, compute the offsets by accumulating the tensor of sequence lengthso = [0] + [len(t) for t in x]o = torch.tensor(o[:-1]).cumsum(dim=0)return ( torch.LongTensor([t[0]-1 for t in b]), # labelstorch.cat(x), # text o)

正如我们之前所看到的,所有向量嵌入都存储在vocab.vectors矩阵中。这使得将这些权重加载到嵌入层的权重中变得非常容易,只需简单地进行复制即可。

net = EmbedClassifier(len(vocab),len(vocab.vectors[0]),len(classes))
net.embedding.weight.data = vocab.vectors
net = net.to(device)

现在来训练我们的模型,看看是否能得到更好的结果:

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=offsetify, shuffle=True)
train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)

输出:

3200: acc=0.6359375
6400: acc=0.68203125
9600: acc=0.706875
12800: acc=0.727734375
16000: acc=0.738625
19200: acc=0.7465104166666666
22400: acc=0.7526785714285714
(35.71297184900832, 0.7573576455534229)

我们没有看到准确率显著提高的一个原因是,我们数据集中的一些单词在预训练的GloVe词汇表中缺失,因此它们基本上被忽略了。为了克服这一问题,我们可以在我们的数据集上训练自己的嵌入模型。

10 Contextual Embeddings

传统的预训练嵌入表示(如Word2Vec)的一个关键局限性是词义问题和消除歧义的困难。虽然预训练嵌入可以捕捉词在上下文中的某些含义,但每个词的所有可能含义都被编码到同一个嵌入中。这会在下游模型中造成问题,因为像“play”这样的许多词根据使用的上下文不同而有不同的含义。

例如,这两个不同句子中的’play’有着不同的含义:

  • 我去剧院看了一场
  • 约翰想要和朋友

上述的预训练嵌入表示了’play’这个词的两种含义在同一个嵌入中。为了克服这个限制,我们需要基于语言模型构建嵌入,该模型经过大量文本语料的训练,知道如何将词在不同上下文中组合在一起。讨论上下文嵌入超出了本教程的范围,但在下一个单元中讨论语言模型时,我们将回到这个话题。

11 知识检测

假设文本语料库包含 80000 个不同的字词。 通常如何将输入向量的维数降低到神经分类器?

A. 随机选择 10% 的字词,并忽略其余字词

B. 使用卷积层,然后使用全连接分类器层

C. 使用嵌入层,然后使用全连接分类器层

D. 选择 10% 的最常用字词,并忽略其余字词

答案:C

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

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

相关文章

便利店小程序有哪些功能

​便利店小程序为附近的住户提供小程序在线购物的服务。用户只需要打开小程序,就可以购买需要的商品,可以选择自取或者配送。整个过程非常简单快速。下面具体介绍便利店小程序的功能。 1. **商品展示**:展示便利店的商品信息,包括…

快速幂算法详解

一、引言 快速幂算法是数学和计算机科学中用于大数幂运算的一种高效算法。它采用了二进制分治策略,将幂运算分解为更小的部分,从而显著降低运算的时间和空间复杂度。在处理大规模数幂运算、加密算法和某些数学问题时,快速幂算法显示出其卓越…

贪心算法题解

前言 大家好,我是jiantaoyab,这篇文章将给大家介绍贪心算法和贪心算法题目的练习和解析,贪心算法的本质就是每一个阶段都是局部最优,从而实现全局最优。我们在做题的同时,不仅要把题目做出来,还要有严格的证…

9 个顶级免费视频压缩软件精选

视频有多种格式、不同的大小和不同的压缩级别。但是,您可以使用最好的视频压缩器来: 减小文件大小提高压缩质量更好地服务您的观众 我们将列出九个领先的视频压缩软件精选,您今天可以免费使用它们来增强您的视频。 9 个顶级免费视频压缩器精…

PHP8编译安装

CentOS8编译安装PHP8 PHP,全称Hypertext Preprocessor(超文本预处理器),是一种通用开源脚本语言。它特别适合于web开发,并能嵌入HTML中。现在主要用于PHP网站中实现动态网站功能,常规我们使用nginx、apache…

【黑马程序员】Python综合案例

文章目录 数据分析案例目的需求数据准备实践数据记录类 文件解析解析csv格式解析json文件 进行数据计算读取文件数据按日期累加数据 图表展示图标绘制最终效果展示 数据分析案例 目的 文件操作实践json库使用三方库pyecharts使用面向对象实践数据容器使用 需求 给定一个csv…

保存带 numpy.ndarray 的 dataframe

# 创建 DataFrame texts ["hi", "hello", "you"] embeddings [np.random.randn(10,) for i in range(3)] df pd.DataFrame({"text":texts, "embedding":embeddings})type(df.embedding.values[0]) # numpy.ndarray# 保存…

设计模式之外观模式(Facade Pattern)【结构性模式】

为什么用结构性模式? 结构性模式关注点“怎样组合对象/类?”所以我们关注下类的组合关系类结构型模式关心类的组合,由多个类可以组合成一个更大的(继承)对象结构型模式关心类与对象的组合,通过关联关系在一…

Hadoop大数据应用:HDFS 集群节点缩容

目录 一、实验 1.环境 2.HDFS 集群节点缩容 二、问题 1.数据迁移有哪些状态 2.数据迁移失败 一、实验 1.环境 (1)主机 表1 主机 主机架构软件版本IP备注hadoop NameNode (已部署) SecondaryNameNode (已部署…

ChatGPT学术论文润色的方法与步骤教程

GPT学术论文润色方法 请查看视频详细润色步骤 把ChatGPT运用到论文写作翻译润色,绝对是仰首佩服,莫敢与争啊,分分钟碾压最顶级的传统翻译或润色模式。 因为,正正好是撞在ChatGPT最擅长的领域上了! 正如我们所知&…

异常随笔xx1

关于过滤器和拦截器 看一下过滤器,过滤器我们可以分两步: 1.配置自定义过滤器 2.过滤器注册 这样它才会生效,拦截器也如此 先配置: RequiredArgsConstructor public class UserTransmitFilter implements Filter {private f…

裁员潮下,打工人的自我修养

法律规定的 裁员补偿: 1、平等协商解除的,底线是N1,上限能谈多少法律都支持 2、有客观原因解除的,是N1 3、强制违法辞退的,是2N Tips:基数是每月的全额税前工资,包括奖金绩效等&#xff0c…

vue框架渲染原理

Vue.js,作为当前最受欢迎的前端框架之一,以其轻量级和灵活性受到众多开发者的喜爱。Vue的核心理念在于采用数据驱动和组件化的方式来构建用户界面。为了更好地使用Vue及其丰富的生态系统,理解其背后的核心原理是非常重要的。本文将深入探讨Vu…

Java 测试Thread StackOverflowError

测试堆栈溢出 Testpublic void testStackOverflow() {try {foo1();} catch (Throwable throwable) {// 栈满时,打印递归深度System.out.println(countRecursion);throw throwable;}}public void foo1() {countRecursion;foo1();}JVM option Xmx50mXss20m 线程栈大小…

strstr的模拟实现

一:strstr函数的定义: strstr函数功能的解释: 在一个字符串里面寻找另一个字符串的首次出现位置,返回值为该位置。 strstr函数要点: 1,如果 str2 是 str1 的一部分,它返回一个指向 str1 中 …

2024.3.15

1.单向循环链表 代码: #include"loop.h" //创建单向循环链表 loop_p create_loop_list() {loop_p H (loop_p)malloc(sizeof(loop));if(HNULL){printf("空间申请失败\n");return NULL;}H->len0;H->nextH;return H; } //创建节点 loop_p…

【C语言】打印用*组成的X形图案

代码如下&#xff1a; #include<stdio.h> int main() { int n 0; int i 0; int j 0; while (scanf("%d", &n) ! EOF) for (i 0; i < n; i) { for (j 0; j < n; j) { if (…

拼多多根据关键词取商品列表 API 返回值说明

一、应用场景 拼多多根据关键词取商品列表的API应用场景非常广泛&#xff0c;主要集中在电商领域&#xff0c;包括但不限于以下几个方面&#xff1a; 1、商品搜索与推荐&#xff1a;商家可以通过API接口&#xff0c;根据用户输入的关键词&#xff0c;实时获取拼多多平台上的相…

python 基础练习题3

目录 1、用户登录注册案例 2、求50~150之间的质数是那些&#xff1f; 3、打印输出标准水仙花数&#xff0c;输出这些水仙花数 4、验证:任意一个大于9的整数减去它的各位数字之和所得的差,一定能被9整除. 5、一个五位数,若在它的后面写上一个7,得到一个六位数A, 若在它前面…

什么是布隆过滤器?

1、什么是布隆过滤器 ​ 布隆过滤器&#xff08;Bloom Filter&#xff09;是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多&#xff0c;缺…