深度学习:基于循环神经网络RNN实现自然语言生成

news2024/12/25 22:14:17

目录

1 循环神经网络介绍

1.1 什么是循环神经网络

1.2 RNN的网络结构

1.3 RNN的工作原理

​编辑

1.4 RNN的应用场景

2 基于RNN实现语句生成

2.1 句子生成介绍

2.2 基于pytorch实现语句生成

2.3 完整代码

2.4 该模型的局限

3 总结


1 循环神经网络介绍

1.1 什么是循环神经网络

循环神经网络(Recurrent Neural Network,简称RNN)是一种处理序列数据的神经网络结构,它具有记忆能力,能够捕捉序列中的时序信息。RNN在自然语言处理、时间序列预测、语音识别等领域有着广泛的应用。

RNN的目的使用来处理序列数据。在传统的神经网络模型中,是从输入层到隐含层再到输出层,层与层之间是全连接的,每层之间的节点是无连接的。

但是这种普通的神经网络对于很多问题却无能无力。例如,你要预测句子的下一个单词是什么,一般需要用到前面的单词,因为一个句子中前后单词并不是独立的。

1.2 RNN的网络结构

首先看一个简单的循环神经网络如,它由输入层、一个隐藏层和一个输出层组成:

  • x是一个向量,它表示输入层的值;
  • s是一个向量,它表示隐藏层的值;
  • U是输入层到隐藏层的权重矩阵,o也是一个向量,它表示输出层的值;
  • V是隐藏层到输出层的权重矩阵;

循环神经网络的隐藏层的值s不仅仅取决于当前这次的输入x,还取决于上一次隐藏层的值s。权重矩阵W就是隐藏层上一次的值作为这一次的输入的权重。

从抽象到具体的展示如下:

RNN之所以称为循环神经网路,即一个序列当前的输出与前面的输出也有关。具体的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐藏层之间的节点不再无连接而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。理论上,RNN能够对任何长度的序列数据进行处理。但是在实践中,为了降低复杂性往往假设当前的状态只与前面的几个状态相关,模型结构展开如下:

上图显示了一个RNN被展开成一个完整的网络。 例如,如果我们关心的序列是5个单词的句子,网络将被展开成5层神经网络,每个单词一层。RNN中发生的计算的公式如下:

1.3 RNN的工作原理

  • 输入层:RNN能够接受一个输入序列(例如文字、股票价格、语音信号等)并将其传递到隐藏层。

  • 隐藏层:隐藏层之间存在循环连接,使得网络能够维护一个“记忆”状态,这一状态包含了过去的信息。这使得RNN能够理解序列中的上下文信息。

  • 输出层:RNN可以有一个或多个输出,例如在序列生成任务中,每个时间步都会有一个输出。

梯度问题:梯度消失和爆炸

由于RNN的循环结构,在训练中可能会出现梯度消失或梯度爆炸的问题。长序列可能会导致训练过程中的梯度变得非常小(消失)或非常大(爆炸),从而影响模型的学习效率。

1.4 RNN的应用场景

循环神经网络(RNN)因其在捕获序列数据中的时序依赖性方面的优势,在许多应用场景中都得到了广泛的使用。

  • 自然语言处理(NLP)

    • 文本生成:RNN可以用于生成文本,如文本生成、散文创作和诗歌生成。
    • 语言建模:RNN可用于语言建模任务,如预测下一个单词或字符。
    • 机器翻译:RNN的变种,如长短时记忆网络(LSTM)和门控循环单元(GRU),已广泛用于机器翻译任务。
    • 情感分析:RNN可以用于分析文本情感,如判断一段文本的情感极性(正面、负面、中性)。
  • 语音识别

    • 语音转文本:RNN被用于将语音信号转换为文本,如语音助手和语音识别系统。
    • 声纹识别:RNN也可以用于声纹识别,用于验证个人的身份。
  • 时间序列分析

    • 股票价格预测:RNN可以用于分析股票价格和预测市场趋势。
    • 天气预测:RNN可用于天气预测,处理气象数据的时间序列。
    • 信用风险评估:RNN可用于分析客户的信用历史和行为,进行信用评估。

2 基于RNN实现语句生成

2.1 句子生成介绍

绝大多数的NLP任务,文本数据都会先通过嵌入码(Embedding code),独热编码(One-hot encoding)等方式转为数字编码。在本篇文章中将使用one-hot编码标识我们的字符。首先,我们需要将把文本数据预处理为简单的表示形式——字符级别的One-hot encoding。

这种编码形式基本上是给文本中的每个字符一个唯一的向量。 例如,如果我们的文本只包含单词“GOOD”,那么只有 3 个唯一字符,G,O,D,三个,因此我们的词汇量只有 3。我们将为每个唯一字符分配一个唯一向量,其中除了索引中的一项之外,所有项都为零。 这就是我们向模型表示每个字符的方式。

对于只有三个单词的one-hot,那么维度即为3;按序编码G,O,D,那么
G为1,展开one-hot就是[1,0,0],
O为2, 就是[0,1,0],
D为3,就是[0,0,1]

输出也可能类似,我们可以取向量中的最高数字并将其作为预测字符。在这个实现中,我们将使用 PyTorch 库,这是一个易于使用并被顶级研究人员广泛使用的深度学习平台。 我们将构建一个模型,该模型将根据传入的一个单词或几个字符来完成一个句子。

该模型将输入一个单词,并预测句子中的下一个字符是什么。 这个过程会不断重复,直到我们生成所需长度的句子。为了保持简短和简单,我们不会使用任何大型或外部数据集。 我们将只定义几个句子来看看模型如何从这些句子中学习。

2.2 基于pytorch实现语句生成

首先,我们将定义我们希望模型在输入第一个单词或前几个字符时输出的句子。

然后我们将从句子中的所有字符创建一个字典,并将它们映射到一个整数。 这将允许我们将输入字符转换为它们各自的整数(char2int),反之亦然(int2char)。

text = ['hey how are you','good i am fine','have a nice day']

# Join all the sentences together and extract the unique characters from the combined sentences
chars = set(''.join(text))

# Creating a dictionary that maps integers to the characters
int2char = dict(enumerate(chars))

# Creating another dictionary that maps characters to integers
char2int = {char: ind for ind, char in int2char.items()}

char2int 字典看起来像这样:它包含我们句子中出现的所有字母/符号,并将它们中的每一个映射到一个唯一的整数。

[Out]: {'f': 0, 'a': 1, 'h': 2, 'i': 3, 'u': 4, 'e': 5, 'm': 6, 'w': 7, 'y': 8, 'd': 9, 'c': 10, ' ': 11, 'r': 12, 'o': 13, 'n': 14, 'g': 15, 'v': 16}

接下来,我们将填充(padding)输入句子以确保所有句子都是标准长度。 虽然 RNN 通常能够接收可变大小的输入,但我们通常希望分批输入训练数据以加快训练过程。 为了使用批次来训练我们的数据,我们需要确保输入数据中的每个序列大小相等。

因此,在大多数情况下,可以通过用 0 值填充太短的序列和修剪太长的序列来完成填充。 在我们的例子中,我们将找到最长序列的长度,并用空格填充其余句子以匹配该长度。

# Finding the length of the longest string in our data
maxlen = len(max(text, key=len))

# Padding

# A simple loop that loops through the list of sentences and adds a ' ' whitespace until the length of
# the sentence matches the length of the longest sentence
for i in range(len(text)):
  while len(text[i])<maxlen:
      text[i] += ' '

由于我们要在每个时间步预测序列中的下一个字符,我们必须将每个句子分为:

  • 输入数据
    最后一个字符需排除因为它不需要作为模型的输入
  • 目标/真实标签
    它为每一个时刻后的值,因为这才是下一个时刻的值。
# Creating lists that will hold our input and target sequences
input_seq = []
target_seq = []

for i in range(len(text)):
    # Remove last character for input sequence
  input_seq.append(text[i][:-1])
    
    # Remove first character for target sequence
  target_seq.append(text[i][1:])
  print("Input Sequence: {}\nTarget Sequence: {}".format(input_seq[i], target_seq[i]))

输入和输出样例如下:

  • 输入:hey how are yo
  • 对应的标签: ey how are you

现在我们可以通过使用上面创建的字典映射输入和目标序列到整数序列。 这将允许我们随后对输入序列进行一次one-hot encoding。

for i in range(len(text)):
    input_seq[i] = [char2int[character] for character in input_seq[i]]
    target_seq[i] = [char2int[character] for character in target_seq[i]]

定义如下三个变量

  1. dict_size: 字典的长度,即唯一字符的个数。它将决定one-hot vector的长度
  2. seq_len:输入到模型中的sequence长度。这里是最长的句子的长度-1,因为不需要最后一个字符
  3. batch_size: mini batch的大小,用于批量训练
dict_size = len(char2int)
seq_len = maxlen - 1
batch_size = len(text)

def one_hot_encode(sequence, dict_size, seq_len, batch_size):
    # Creating a multi-dimensional array of zeros with the desired output shape
    features = np.zeros((batch_size, seq_len, dict_size), dtype=np.float32)
    
    # Replacing the 0 at the relevant character index with a 1 to represent that character
    for i in range(batch_size):
        for u in range(seq_len):
            features[i, u, sequence[i][u]] = 1
    return features

 同时定义一个helper function,用于初始化one-hot向量

# Input shape --> (Batch Size, Sequence Length, One-Hot Encoding Size)
input_seq = one_hot_encode(input_seq, dict_size, seq_len, batch_size)

到此我们完成了所有的数据预处理,可以将数据从NumPy数组转为PyTorch张量啦。

input_seq = torch.from_numpy(input_seq)
target_seq = torch.Tensor(target_seq)

接下来就是搭建模型的步骤,你可以在这一步使用全连接层,卷积层,RNN层,LSTM层等等。但是我在这里使用最最基础的nn.rnn来示例一个RNN是如何使用的。

在开始构建模型之前,让我们使用 PyTorch 中的内置功能来检查我们正在运行的设备(CPU 或 GPU)。 此实现不需要 GPU,因为训练非常简单。 但是,随着处理具有数百万个可训练参数的大型数据集和模型,使用 GPU 对加速训练非常重要。

# torch.cuda.is_available() checks and returns a Boolean True if a GPU is available, else it'll return False
is_cuda = torch.cuda.is_available()

# If we have a GPU available, we'll set our device to GPU. We'll use this device variable later in our code.
if is_cuda:
    device = torch.device("cuda")
    print("GPU is available")
else:
    device = torch.device("cpu")
    print("GPU not available, CPU used")

要开始构建我们自己的神经网络模型,我们可以为所有神经网络模块定义一个继承 PyTorch 的基类(nn.module)的类。 这样做之后,我们可以开始在构造函数下定义一些变量以及模型的层。 对于这个模型,我们将只使用一层 RNN,然后是一个全连接层。 全连接层将负责将 RNN 输出转换为我们想要的输出形状。

我们还必须将 forward() 下的前向传递函数定义为类方法。 前向函数是按顺序执行的,因此我们必须先将输入和零初始化隐藏状态通过 RNN 层,然后再将 RNN 输出传递到全连接层。 请注意,我们使用的是在构造函数中定义的层。

我们必须定义的最后一个方法是我们之前调用的用于初始化hidden state的方法 - init_hidden()。 这基本上会在我们的隐藏状态的形状中创建一个零张量。

class Model(nn.Module):
    def __init__(self, input_size, output_size, hidden_dim, n_layers):
        super(Model, self).__init__()

        # Defining some parameters
        self.hidden_dim = hidden_dim
        self.n_layers = n_layers

        #Defining the layers
        # RNN Layer
        self.rnn = nn.RNN(input_size, hidden_dim, n_layers, batch_first=True)   
        # Fully connected layer
        self.fc = nn.Linear(hidden_dim, output_size)
    
    def forward(self, x):
        
        batch_size = x.size(0)

        # Initializing hidden state for first input using method defined below
        hidden = self.init_hidden(batch_size)

        # Passing in the input and hidden state into the model and obtaining outputs
        out, hidden = self.rnn(x, hidden)
        
        # Reshaping the outputs such that it can be fit into the fully connected layer
        out = out.contiguous().view(-1, self.hidden_dim)
        out = self.fc(out)
        
        return out, hidden
    
    def init_hidden(self, batch_size):
        # This method generates the first hidden state of zeros which we'll use in the forward pass
        # We'll send the tensor holding the hidden state to the device we specified earlier as well
        hidden = torch.zeros(self.n_layers, batch_size, self.hidden_dim)
        return hidde

在定义了上面的模型之后,我们必须用相关参数实例化模型并定义我们的超参数。 我们在下面定义的超参数是:

  • n_epochs: 模型训练所有数据集的次数
  • lr: learning rate学习率

有关超参数,可以参考该文章作为进一步学习。

与其他神经网络类似,我们也必须定义优化器和损失函数。 我们将使用 CrossEntropyLoss,因为最终输出基本上是一个分类任务和常见的 Adam 优化器。

# Instantiate the model with hyperparameters
model = Model(input_size=dict_size, output_size=dict_size, hidden_dim=12, n_layers=1)
# We'll also set the model to the device that we defined earlier (default is CPU)
model.to(device)

# Define hyperparameters
n_epochs = 100
lr=0.01

# Define Loss, Optimizer
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr)

 现在我们可以开始训练了! 由于我们只有几句话,所以这个训练过程非常快。 然而,随着我们的进步,更大的数据集和更深的模型意味着输入数据要大得多,并且我们必须计算的模型中的参数数量要多得多。

# Training Run
for epoch in range(1, n_epochs + 1):
    optimizer.zero_grad() # Clears existing gradients from previous epoch
    input_seq.to(device)
    output, hidden = model(input_seq)
    loss = criterion(output, target_seq.view(-1).long())
    loss.backward() # Does backpropagation and calculates gradients
    optimizer.step() # Updates the weights accordingly
    
    if epoch%10 == 0:
        print('Epoch: {}/{}.............'.format(epoch, n_epochs), end=' ')
        print("Loss: {:.4f}".format(loss.item()))
Epoch: 10/100............. Loss: 2.4351
Epoch: 20/100............. Loss: 2.2388
Epoch: 30/100............. Loss: 1.8932
Epoch: 40/100............. Loss: 1.4660
Epoch: 50/100............. Loss: 1.0754
Epoch: 60/100............. Loss: 0.7707
Epoch: 70/100............. Loss: 0.5341
Epoch: 80/100............. Loss: 0.3661
Epoch: 90/100............. Loss: 0.2591
Epoch: 100/100............. Loss: 0.1939

现在让我们测试我们的模型,看看我们会得到什么样的输出。 作为第一步,我们将定义一些辅助函数来将我们的模型输出转换回文本。

# This function takes in the model and character as arguments and returns the next character prediction and hidden state
def predict(model, character):
    # One-hot encoding our input to fit into the model
    character = np.array([[char2int[c] for c in character]])
    character = one_hot_encode(character, dict_size, character.shape[1], 1)
    character = torch.from_numpy(character)
    character.to(device)
    
    out, hidden = model(character)

    prob = nn.functional.softmax(out[-1], dim=0).data
    # Taking the class with the highest probability score from the output
    char_ind = torch.max(prob, dim=0)[1].item()

    return int2char[char_ind], hidden
# This function takes the desired output length and input characters as arguments, returning the produced sentence
def sample(model, out_len, start='hey'):
    model.eval() # eval mode
    start = start.lower()
    # First off, run through the starting characters
    chars = [ch for ch in start]
    size = out_len - len(chars)
    # Now pass in the previous characters and get a new one
    for ii in range(size):
        char, h = predict(model, chars)
        chars.append(char)

    return ''.join(chars)

 让我们测试一下good

sample(model, 15, 'good')
[Out]: 'good i am fine '

 正如我们所看到的,如果我们用“good”这个词输入到模型,该模型能够提出“good i am fine”这个句子。

2.3 完整代码

import torch
import torch.nn as nn
import numpy as np


text = ['hey how are you', 'good i am fine', 'have a nice day']
chars = set(''.join(text))
int2char = dict(enumerate(chars))
char2int = {char: ind for ind, char in int2char.items()}
print(char2int)

maxlen = len(max(text, key=len))
for i in range(len(text)):
  while len(text[i]) < maxlen:
      text[i] += ' '

input_seq = []
target_seq = []

for i in range(len(text)):
    input_seq.append(text[i][:-1])
    target_seq.append(text[i][1:])
    print("Input Sequence: {}\nTarget Sequence: {}".format(input_seq[i], target_seq[i]))


for i in range(len(text)):
    input_seq[i] = [char2int[character] for character in input_seq[i]]
    target_seq[i] = [char2int[character] for character in target_seq[i]]

dict_size = len(char2int)
seq_len = maxlen - 1
batch_size = len(text)


def one_hot_encode(sequence, dict_size, seq_len, batch_size):
    features = np.zeros((batch_size, seq_len, dict_size), dtype=np.float32)

    for i in range(batch_size):
        for u in range(seq_len):
            features[i, u, sequence[i][u]] = 1
    return features


input_seq = one_hot_encode(input_seq, dict_size, seq_len, batch_size)
input_seq = torch.from_numpy(input_seq)
target_seq = torch.Tensor(target_seq)


is_cuda = torch.cuda.is_available()
if is_cuda:
    device = torch.device("cuda")
    print("GPU is available")
else:
    device = torch.device("cpu")
    print("GPU not available, CPU used")


class RnnModel(nn.Module):
    def __init__(self, input_size, output_size, hidden_dim, n_layers):
        super(RnnModel, self).__init__()

        self.hidden_dim = hidden_dim
        self.n_layers = n_layers

        self.rnn = nn.RNN(input_size, hidden_dim, n_layers, batch_first=True)
        self.fc = nn.Linear(hidden_dim, output_size)

    def forward(self, x):
        batch_size = x.size(0)
        hidden = self.init_hidden(batch_size)
        out, hidden = self.rnn(x, hidden)
        out = out.contiguous().view(-1, self.hidden_dim)
        out = self.fc(out)

        return out, hidden

    def init_hidden(self, batch_size):
        hidden = torch.zeros(self.n_layers, batch_size, self.hidden_dim)
        return hidden


model = RnnModel(input_size=dict_size, output_size=dict_size, hidden_dim=12, n_layers=1)
model.to(device)
n_epochs = 100
lr = 0.01

# Define Loss, Optimizer
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr)

for epoch in range(1, n_epochs + 1):
    optimizer.zero_grad()
    input_seq.to(device)
    output, hidden = model(input_seq)
    loss = criterion(output, target_seq.view(-1).long())
    loss.backward()
    optimizer.step()

    if epoch % 10 == 0:
        print('Epoch: {}/{}.............'.format(epoch, n_epochs), end=' ')
        print("Loss: {:.4f}".format(loss.item()))


def predict(model, character):
    # One-hot encoding our input to fit into the model
    character = np.array([[char2int[c] for c in character]])
    character = one_hot_encode(character, dict_size, character.shape[1], 1)
    character = torch.from_numpy(character)
    character.to(device)

    out, hidden = model(character)

    prob = nn.functional.softmax(out[-1], dim=0).data
    # Taking the class with the highest probability score from the output
    char_ind = torch.max(prob, dim=0)[1].item()

    return int2char[char_ind], hidden


def sample(model, out_len, start='hey'):
    model.eval()
    start = start.lower()
    chars = [ch for ch in start]
    size = out_len - len(chars)
    for ii in range(size):
        char, h = predict(model, chars)
        chars.append(char)

    return ''.join(chars)


result = sample(model, 15, 'good')
print(result)

2.4 该模型的局限

虽然这个模型绝对是一个过度简化的语言模型,但让我们回顾一下它的局限性以及为了训练更好的语言模型需要解决的问题。

  • 局限一、过拟合 over-fitting

我们只为模型提供了 3 个训练句子,因此它基本上“记住”了这些句子的字符序列,从而返回了我们训练它的确切句子。 但是,如果在更大的数据集上训练一个类似的模型,并添加一些随机性,该模型将挑选出一般的句子结构和语言规则,并且能够生成自己独特的句子。

尽管如此,使用单个样本或批次运行模型可以作为对工作流程的健全性检查,确保您的数据类型全部正确,模型学习良好等。

  • 局限二、处理未见过的字符

该模型目前只能处理它之前在训练数据集中看到的字符。 通常,如果训练数据集足够大,所有字母和符号等应该至少出现一次,从而出现在我们的词汇表中。 然而,有一种方法来处理从未见过的字符总是好的,例如将所有未知数分配给它自己的索引。

  • 局限三、文本标识的方式

在这个实现中,我们使用 one-hot 编码来表示我们的字符。 虽然由于它的简单性,它可能适合此任务,但大多数时候它不应该用作实际或更复杂问题的解决方案。 这是因为:

  • 对于大型数据集,计算成本太高
  • one-hot向量中没有嵌入上下文/语义信息

以及许多其他使此解决方案不太可行的缺点。

相反,大多数现代 NLP 解决方案依赖于词嵌入(word2vec、GloVe)或最近在 BERT、ELMo 和 ULMFit 中的独特上下文词表示。 这些方法允许模型根据出现在它之前的文本来学习单词的含义,并且在 BERT 等的情况下,也可以从出现在它之后的文本中学习。

3 总结

循环神经网络是一种强大的模型,特别适合于处理具有时间依赖性的序列数据。然而,标准RNN通常难以学习长序列中的依赖关系,因此有了更多复杂的变体如LSTM和GRU,来解决这些问题。

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

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

相关文章

Anaconda - 操作系统安装程序 简要介绍

Anaconda 简要介绍 1. Anaconda 简介2. Anaconda 体系结构3. Anaconda 开发模型4. Anaconda 启动概述5. Anaconda 源码1. 接口2. 自定义组件3. 硬盘分区&#xff1a;使用python-blivet包4. Bootloader5. 各个步骤的配置&#xff1a;6. 安装软件包&#xff1a;7. 安装控制&#…

华为强势回归,苹果iPhone15ProMax独占潜望式镜头,预计销量受损

9月8日消息&#xff0c;据集邦咨询发布的产业洞察报告显示&#xff0c;苹果即将发布的iPhone 15 Pro Max将会独占潜望式镜头&#xff0c;该机型的占比预计将会达到40%左右。报告同时预估&#xff0c;今年iPhone 15系列手机的出货量将达到8000万&#xff0c;相比去年同期增长6%以…

无需公网IP教你如何外网远程访问管家婆ERP进销存

文章目录 前言 1.管家婆服务2. 内网穿透2.1 安装cpolar内网穿透2.2 设置远程访问 3. 固定访问地址4. 配置固定公网访问地址 前言 管家婆辉煌系列产品是中小企业进销存、财务管理一体化的典范软件&#xff0c;历经十余年市场的洗礼&#xff0c;深受广大中小企业的欢迎&#xff…

冠达管理:不要误读“房贷利率降低”

最近&#xff0c;人人都知道房贷利率降了&#xff0c;但如果细问“怎么降的、哪些城市降了、将产生何种影响”&#xff0c;恐怕不少人都是水中望月。正因此&#xff0c;部分房地产中介、营销机构利用购房者的信息不对称劣势&#xff0c;刻意夸张房贷利率下降关于楼市价格的影响…

16 除自身以外数组的乘积

除自身以外数组的乘积 题解1 前缀积*后缀积题解2 空间优化 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数…

YAPI的搭建和使用

https://www.cnblogs.com/yehuisir/p/12315137.html 1、#进入数据库 mongo 2、#进入admin库 use admin 3、#添加一个用户root&#xff08;此步骤可不执行&#xff09; db.createUser({user:"root",pwd:"123456abc.COM",roles:["root"]}) …

【合作 】联通、壳牌、联想、国金证券等众多企业签约 Eolink !

联通、壳牌、联想、华润置地、中国铁塔等多家知名企业签约 Eolink&#xff0c;携手落地 API 全生命周期管理&#xff0c;感谢广大企业对 Eolink 的信任和选择&#xff01; Eolink 致力于为企业提供最全面的 API 研发管理解决方案&#xff0c;提供高效、可靠的工具以及服务&…

深入了解 Axios 的 put 请求:使用技巧与最佳实践

在前端开发中&#xff0c;我们经常需要与后端服务器进行数据交互。其中&#xff0c;PUT 请求是一种常用的方法&#xff0c;用于向服务器发送更新或修改数据的请求。通过发送 PUT 请求&#xff0c;我们可以更新服务器上的资源状态。 Axios 是一个流行的 JavaScript 库&#xff0…

解析进程复制:父子进程内存地址的神秘之处

当涉及到进程复制时&#xff0c;有时会出现一个令人困惑的现象&#xff1a;在父进程和子进程中&#xff0c;某些变量的内存地址似乎是相同的&#xff0c;尽管它们实际上是独立的进程。下面我将简单解释这个现象以及背后的原因。 进程复制&#xff1a;父子进程的神秘关系 在多…

Vue3统一导出局部组件和全局组件

局部组件统一导出 components新增ComponentA.vue、ComponentB.vue两个组件 新增index.js进行组件统一导入 import ComponentA from ./ComponentA.vue import ComponentB from ./ComponentB.vueexport {ComponentA,ComponentB }使用 <template><ComponentA /><…

leetcode 150.逆波兰表达式求值

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;逆波兰表达式求值 思路&#xff1a; 假设这样一组表达式 { "2" , "1" , "" , "3" , "*" } 这是一种后缀表达式&#xff0c;首先我们准备一个栈&#xff0c;当如果不是…

电动汽车行业,这个技能绝了!

在当今不断演变的汽车工业中&#xff0c;电动汽车已经崭露头角&#xff0c;并迅速改变着我们的出行方式。这种创新的交通方式不仅减少了尾气排放&#xff0c;还为我们带来了更加环保和可持续的未来愿景。在电动汽车的核心&#xff0c;蓄电池技术正发挥着至关重要的作用。 然而&…

阿里巴巴推出D.Design文生图网站(免费10-20张图)

简介&#xff1a; d.design是阿里巴巴推出的一个基于人工智能的设计工具&#xff0c;可以帮助用户轻松创建3D模型和场景。该工具提供了丰富的素材库和功能&#xff0c;可以满足用户的各种需求。 ​堆友堆友是Alibaba Design打造的设计师全成长周期服务平台&#xff0c;围绕品质…

Python中处理异常和错误

作为一种强大且灵活的编程语言&#xff0c;Python 提供了许多机制来处理程序运行过程中可能出现的异常和错误。本文将详细介绍如何在 Python 中以“优雅、高效”的方式进行异常处理&#xff0c;并提供实用技巧帮助开发者更好地应对各种情况。无论您是初学者还是有经验的开发人员…

上行取消指示 DCI format 2_4

上篇介绍了DCI format 2_1的DL传输中断的内容&#xff0c;这篇就看下DCI format 2_4有关的UL 传输取消机制&#xff0c;值得注意的是这里的UL传输针对的是PUSCH和SRS传输。 UL cancellation DCI format 2_4相关机制引入的背景与DCI format 2_1一样&#xff0c;都是因为URLLC和e…

3ds max插件CG MAGIC中的室外功能可以高效出图吗?

使用3ds Max高效出图秘诀有没有什么秘诀呢&#xff1f;如何做到快速出图呢&#xff1f; 3ds max插件CG MAGIC中的室外功能可以高效出图吗&#xff1f; CG MAGIC 是一款基于3DS max深入开发的智能辅助设计插件。 自从CG Magic专业版上线之后&#xff0c;小伙伴们对新功能诀窍…

当浏览器切换到其他标签页或者最小化时,你的js定时器还准时吗?

最近一个项目遇到这个问题&#xff0c;获取北斗授时服务器时间校准本地时间&#xff0c;定时器是需要用到的&#xff0c;大致步骤分为以下几点&#xff1a; 1.定时请求服务器时间 2.根据获取到接口返回时间自动累加 参考&#xff1a; vue.js和原生js时间自动累加功能_js时间…

windows 下docker安装宝塔镜像 宝塔docker获取镜像

1. docker 安装宝塔 打开链接&#xff1a;https://www.docker.com/get-started&#xff0c;找对应的版本下载docker&#xff0c;安装docker打开百度云盘&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1DGIjpKkNDAmy4roaKGLA_w 提取码&#xff1a;u8bi 2. 设置镜像 点…

LeetCode刷题笔记【31】:动态规划专题-3(整数拆分、不同的二叉搜索树)

文章目录 前置知识343. 整数拆分题目描述解题思路代码进一步优化 96.不同的二叉搜索树题目描述解题思路代码优化改进 总结 前置知识 参考前文 参考文章&#xff1a; LeetCode刷题笔记【29】&#xff1a;动态规划专题-1&#xff08;斐波那契数、爬楼梯、使用最小花费爬楼梯&…

TikTok运营做不起来?IP是关键

作为跨境电商新蓝海&#xff0c;TikTok不断的加快自己推进电商业务的步伐&#xff0c;也吸引了越来越多的跨境商家入驻。但是很多人信心满满注册入驻后&#xff0c;却遇到了0播放&#xff0c;流量少&#xff0c;转化低的问题&#xff0c;Tiktok运营不起来&#xff0c;那你要注意…