循环神经网络(RNN)入门指南:从原理到实践

目录

1. 循环神经网络的基本概念

2. 简单循环网络及其应用

3. 参数学习与优化

4. 基于门控的循环神经网络

4.1 长短期记忆网络(LSTM)

4.1.1 LSTM的核心组件:

4.2 门控循环单元(GRU)

5 实际应用中的优化技巧

5.1 变体和改进

5.2 注意力机制的结合

6 实现细节和最佳实践

6.1 初始化策略

6.1.1 梯度处理


1. 循环神经网络的基本概念

循环神经网络(Recurrent Neural Network,RNN)是一类具有短期记忆能 力的神经网络。在循环神经网络中,神经元不但可以接受其他神经元的信息,也 可以接受自身的信息,形成具有环路的网络结构。

循环神经网络是一类专门用于处理序列数据的神经网络。与传统的前馈神经网络不同,RNN引入了循环连接,使网络具备了处理时序信息的能力。在处理每个时间步的输入时,网络不仅考虑当前输入,还会利用之前的历史信息。

循环神经网络

从结构上看,RNN的核心是一个循环单元,它在每个时间步接收两个输入:当前时刻的输入数据和前一时刻的隐藏状态。这两个输入经过加权组合和非线性变换,生成当前时刻的新隐藏状态。具体来说,在每个时间步t,网络会执行以下计算:h_t = tanh(W_xh * x_t + W_hh * h_{t-1} + b_h),其中激活函数通常选择tanh或ReLU。

我们通过一个完整的Python实现来深入理解简单循环网络的工作机制:

import numpy as npclass SimpleRNN:def __init__(self, input_size, hidden_size, output_size):# 初始化网络参数self.hidden_size = hidden_sizeself.W_xh = np.random.randn(input_size, hidden_size) * 0.01self.W_hh = np.random.randn(hidden_size, hidden_size) * 0.01self.W_hy = np.random.randn(hidden_size, output_size) * 0.01self.b_h = np.zeros((1, hidden_size))self.b_y = np.zeros((1, output_size))# 用于存储反向传播所需的中间值self.hidden_states = []self.inputs = []def forward(self, input_sequence):# 初始化隐藏状态h = np.zeros((1, self.hidden_size))self.hidden_states = [h]self.inputs = input_sequenceoutputs = []# 前向传播for x in input_sequence:h = np.tanh(np.dot(x, self.W_xh) + np.dot(h, self.W_hh) + self.b_h)y = np.dot(h, self.W_hy) + self.b_yself.hidden_states.append(h)outputs.append(y)return outputsdef backward(self, d_outputs, learning_rate=0.01):# 初始化梯度dW_xh = np.zeros_like(self.W_xh)dW_hh = np.zeros_like(self.W_hh)dW_hy = np.zeros_like(self.W_hy)db_h = np.zeros_like(self.b_h)db_y = np.zeros_like(self.b_y)# 反向传播dh_next = np.zeros((1, self.hidden_size))for t in reversed(range(len(self.inputs))):# 输出层的梯度dy = d_outputs[t]dW_hy += np.dot(self.hidden_states[t+1].T, dy)db_y += dy# 隐藏层的梯度dh = np.dot(dy, self.W_hy.T) + dh_nextdh_raw = (1 - self.hidden_states[t+1] ** 2) * dhdW_xh += np.dot(self.inputs[t].T, dh_raw)dW_hh += np.dot(self.hidden_states[t].T, dh_raw)db_h += dh_rawdh_next = np.dot(dh_raw, self.W_hh.T)# 更新参数self.W_xh -= learning_rate * dW_xhself.W_hh -= learning_rate * dW_hhself.W_hy -= learning_rate * dW_hyself.b_h -= learning_rate * db_hself.b_y -= learning_rate * db_y

在自然语言处理中,它可以用于实现基础的语言模型我们可以训练网络预测句子中的下一个词:

def create_language_model():vocab_size = 5000  # 词汇表大小embedding_size = 128hidden_size = 256model = SimpleRNN(embedding_size, hidden_size, vocab_size)return modeldef train_language_model(model, sentences, word_to_idx):for sentence in sentences:# 将句子转换为词嵌入序列input_sequence = [word_to_embedding[word_to_idx[word]] for word in sentence[:-1]]target_sequence = [word_to_idx[word] for word in sentence[1:]]# 前向传播outputs = model.forward(input_sequence)# 计算损失和梯度d_outputs = []for t, output in enumerate(outputs):target = np.zeros((1, vocab_size))target[0, target_sequence[t]] = 1d_outputs.append(output - target)# 反向传播model.backward(d_outputs)

在时间序列预测领域,简单循环网络可以用于预测股票价格、天气等连续值:

def time_series_prediction(data, sequence_length):model = SimpleRNN(input_size=1, hidden_size=32, output_size=1)# 准备训练数据sequences = []targets = []for i in range(len(data) - sequence_length):sequences.append(data[i:i+sequence_length])targets.append(data[i+sequence_length])# 训练模型for epoch in range(num_epochs):for seq, target in zip(sequences, targets):outputs = model.forward(seq)d_outputs = [output - target for output in outputs]model.backward(d_outputs)

虽然简单循环网络在这些应用中表现出了一定的能力,但它也存在明显的局限性。主要问题包括:

  1. 梯度消失和爆炸:在反向传播过程中,梯度会随着时间步的增加而衰减或爆炸。
  2. 长程依赖问题:网络难以捕捉距离较远的依赖关系。
  3. 信息瓶颈:所有历史信息都需要压缩在固定大小的隐藏状态中。

为了克服这些限制,后来发展出了LSTM和GRU等更复杂的RNN变体。但是,理解简单循环网络的原理和实现对于掌握这些高级模型仍然是必要的。

2. 简单循环网络及其应用

简单循环神经网络(Simple RNN)是循环神经网络家族中最基础的架构。它通过在传统神经网络的基础上引入循环连接,使网络具备了处理序列数据的能力。这种设计理念源于对人类认知过程的模拟:当我们阅读文本或听音乐时,总是会结合之前的内容来理解当前信息。简单循环网络正是通过这种方式,在处理序列数据的每个时间步都保持并更新一个内部状态,从而捕捉序列中的时序依赖关系。

从结构上看,简单循环网络的核心是循环层,它在每个时间步都执行相同的运算。具体来说,网络在处理当前输入时,会同时考虑两个因素:当前时间步的输入数据和上一时间步的隐藏状态。这两部分信息通过权重矩阵进行加权组合,然后经过非线性激活函数(通常是tanh或ReLU)得到当前时间步的新隐藏状态。

这个过程可以用数学表达式表示为:h_t = tanh(W_xh * x_t + W_hh * h_{t-1} + b_h),其中W_xh是输入到隐藏层的权重矩阵,W_hh是隐藏层到隐藏层的权重矩阵,b_h是偏置项。

在训练过程中,简单循环网络采用随时间反向传播(BPTT)算法。这种算法将网络在时间维度上展开,转化为一个深度前馈网络,然后应用标准的反向传播算法进行训练。值得注意的是,由于所有时间步共享相同的权重,网络的参数更新需要累积所有时间步的梯度。这种训练方式虽然直观,但在处理长序列时容易出现梯度消失或梯度爆炸的问题。

然而,简单循环网络也存在一些固有的局限性。最显著的问题是长程依赖问题,即网络难以捕捉序列中相距较远的元素之间的关系。这个问题的根源在于,随着序列长度的增加,早期的信息会在多次非线性变换中逐渐减弱,最终可能完全丧失。此外,简单循环网络还面临着训练不稳定的问题,特别是在处理长序列时,梯度的传播容易出现消失或爆炸。

为了提升模型性能,我们可以采取一些实用的策略。合适的权重初始化,可以使用正交初始化或者Xavier/He初始化方法来减缓梯度问题。使用梯度裁剪技术,防止梯度爆炸导致的训练不稳定。在优化器的选择上,Adam或RMSprop等自适应优化算法通常能够取得较好的效果。此外,批归一化等技术也可以帮助稳定训练过程。

在数据预处理方面,需要特别注意序列长度的处理。由于实际应用中的序列往往长度不一,我们通常需要通过截断或填充的方式将它们处理成固定长度。对输入数据进行适当的标准化或归一化处理也是提升模型性能的重要步骤。

尽管简单循环网络存在这些局限性,但它的设计思想启发了后续更复杂的RNN变体,如长短期记忆网络(LSTM)和门控循环单元(GRU)的发展。这些高级模型通过引入门控机制等创新设计,在很大程度上克服了简单循环网络的缺点,但其基本原理仍然源于简单循环网络的核心思想。

简单循环网络(Simple RNN)是最基础的RNN结构。在每个时间步,网络会:

  1. 接收当前时间步的输入
  2. 结合上一时间步的隐藏状态
  3. 通过非线性激活函数计算当前时间步的隐藏状态
  4. 输出预测结果

这种结构可以应用于多种机器学习任务,比如序列预测、序列标注等。在情感分析任务中,我们可以这样实现:

class SimpleRNN:def __init__(self, input_size, hidden_size, output_size):self.hidden_size = hidden_size# 初始化权重self.W_xh = np.random.randn(input_size, hidden_size) / np.sqrt(input_size)self.W_hh = np.random.randn(hidden_size, hidden_size) / np.sqrt(hidden_size)self.W_hy = np.random.randn(hidden_size, output_size) / np.sqrt(hidden_size)def forward(self, inputs):h = np.zeros((1, self.hidden_size))for x in inputs:h = np.tanh(np.dot(x, self.W_xh) + np.dot(h, self.W_hh))return np.dot(h, self.W_hy)

3. 参数学习与优化

参数学习是循环神经网络中最核心的环节,它直接决定了模型的性能。与传统神经网络相比,RNN的参数学习具有其特殊性,这主要源于其处理序列数据的特性。让我们深入探讨RNN的参数学习机制和优化策略。

随时间反向传播(BPTT)是RNN参数学习的基础算法。在前向传播过程中,RNN会按时间顺序处理输入序列,并在每个时间步保存必要的中间状态。当到达序列末尾时,网络会计算损失函数,然后开始反向传播过程。这个过程可以通过下面的数学表达式来描述:

对于时间步t的前向传播:

通过代码来详细展示这个过程:

class RNNWithOptimization:def __init__(self, input_size, hidden_size, output_size):# 初始化网络参数self.params = {'W_xh': np.random.randn(input_size, hidden_size) / np.sqrt(input_size),'W_hh': np.random.randn(hidden_size, hidden_size) / np.sqrt(hidden_size),'W_hy': np.random.randn(hidden_size, output_size) / np.sqrt(hidden_size),'b_h': np.zeros((1, hidden_size)),'b_y': np.zeros((1, output_size))}# 初始化Adam优化器的动量参数self.m = {key: np.zeros_like(value) for key, value in self.params.items()}self.v = {key: np.zeros_like(value) for key, value in self.params.items()}self.t = 0def forward_pass(self, inputs, targets):"""前向传播并计算损失"""h = np.zeros((1, self.params['W_hh'].shape[0]))  # 初始化隐藏状态loss = 0cache = {'h': [h], 'y': [], 'inputs': inputs}# 前向传播through timefor t, x in enumerate(inputs):# 计算隐藏状态h = np.tanh(np.dot(x, self.params['W_xh']) + np.dot(h, self.params['W_hh']) + self.params['b_h'])# 计算输出y = np.dot(h, self.params['W_hy']) + self.params['b_y']# 保存中间状态用于反向传播cache['h'].append(h)cache['y'].append(y)# 计算损失loss += 0.5 * np.sum((y - targets[t]) ** 2)return loss, cachedef backward_pass(self, cache, targets, clip_threshold=5):"""实现BPTT算法"""grads = {key: np.zeros_like(value) for key, value in self.params.items()}H = len(cache['h']) - 1  # 序列长度dh_next = np.zeros_like(cache['h'][0])for t in reversed(range(H)):# 计算输出层的梯度dy = cache['y'][t] - targets[t]grads['W_hy'] += np.dot(cache['h'][t+1].T, dy)grads['b_y'] += dy# 反向传播到隐藏层dh = np.dot(dy, self.params['W_hy'].T) + dh_next# 计算tanh的梯度dtanh = (1 - cache['h'][t+1] ** 2) * dh# 计算各参数的梯度grads['b_h'] += dtanhgrads['W_xh'] += np.dot(cache['inputs'][t].T, dtanh)grads['W_hh'] += np.dot(cache['h'][t].T, dtanh)# 为下一个时间步准备梯度dh_next = np.dot(dtanh, self.params['W_hh'].T)# 梯度裁剪for key in grads:np.clip(grads[key], -clip_threshold, clip_threshold, out=grads[key])return gradsdef adam_optimize(self, grads, learning_rate=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8):"""实现Adam优化算法"""self.t += 1for key in self.params:# 更新动量self.m[key] = beta1 * self.m[key] + (1 - beta1) * grads[key]self.v[key] = beta2 * self.v[key] + (1 - beta2) * (grads[key] ** 2)# 偏差修正m_hat = self.m[key] / (1 - beta1 ** self.t)v_hat = self.v[key] / (1 - beta2 ** self.t)# 更新参数self.params[key] -= learning_rate * m_hat / (np.sqrt(v_hat) + epsilon)

在实际应用中,RNN的训练还需要考虑以下几个关键优化策略:

  • 梯度裁剪:防止梯度爆炸问题,通过设置梯度阈值来限制梯度的大小:
def clip_gradients(gradients, threshold=5.0):for grad in gradients.values():np.clip(grad, -threshold, threshold, out=grad)
  •  学习率调整:采用学习率衰减或自适应学习率策略:
def adjust_learning_rate(initial_lr, epoch, decay_rate=0.1):return initial_lr / (1 + decay_rate * epoch)
  • 正则化技术:包括权重衰减、dropout等:
def apply_dropout(h, dropout_rate=0.5):mask = (np.random.rand(*h.shape) > dropout_rate) / (1 - dropout_rate)return h * mask
  • 批量训练:使用小批量梯度下降来提高训练效率和稳定性:
def batch_generator(data, batch_size):n_batches = len(data) // batch_sizefor i in range(n_batches):yield data[i*batch_size:(i+1)*batch_size]
  • 初始化策略:采用适当的权重初始化方法:
def xavier_initialization(input_dim, output_dim):return np.random.randn(input_dim, output_dim) * np.sqrt(2.0/(input_dim + output_dim))

为了更好地监控训练过程,我们还需要实现验证和早停机制

class EarlyStopping:def __init__(self, patience=5, min_delta=0):self.patience = patienceself.min_delta = min_deltaself.counter = 0self.best_loss = Noneself.early_stop = Falsedef __call__(self, val_loss):if self.best_loss is None:self.best_loss = val_losselif val_loss > self.best_loss - self.min_delta:self.counter += 1if self.counter >= self.patience:self.early_stop = Trueelse:self.best_loss = val_lossself.counter = 0

在训练循环中,我们需要综合运用这些优化策略

def train_rnn(model, train_data, val_data, epochs=100, batch_size=32):early_stopping = EarlyStopping(patience=5)for epoch in range(epochs):train_loss = 0for batch in batch_generator(train_data, batch_size):# 前向传播loss, cache = model.forward_pass(batch.inputs, batch.targets)# 反向传播grads = model.backward_pass(cache, batch.targets)# 应用优化策略clip_gradients(grads)model.adam_optimize(grads)train_loss += loss# 验证val_loss = evaluate(model, val_data)# 早停检查early_stopping(val_loss)if early_stopping.early_stop:print(f"Early stopping at epoch {epoch}")break

参数学习与优化是RNN成功应用的关键。通过合理的优化策略组合,我们可以显著提升模型的训练效果和泛化能力。在实践中,需要根据具体任务特点和数据特性,灵活调整这些优化策略的使用方式和参数设置。同时,良好的监控和调试机制也是确保训练过程顺利进行的重要保障。

4. 基于门控的循环神经网络

基于门控的循环神经网络是为了解决简单RNN在处理长序列时存在的梯度消失和长程依赖问题而提出的。通过引入门控机制,这些网络能够更好地控制信息的流动,从而在长序列处理任务中取得更好的效果。

4.1 长短期记忆网络(LSTM)

LSTM是最早提出且最为经典的门控RNN结构。它通过设计遗忘门、输入门和输出门三个门控单元,以及一个记忆单元,来控制信息的存储、更新和输出。

4.1.1 LSTM的核心组件:

class LSTM:def __init__(self, input_size, hidden_size):# 初始化权重矩阵# 输入门参数self.W_xi = np.random.randn(input_size, hidden_size) * 0.01self.W_hi = np.random.randn(hidden_size, hidden_size) * 0.01self.b_i = np.zeros((1, hidden_size))# 遗忘门参数self.W_xf = np.random.randn(input_size, hidden_size) * 0.01self.W_hf = np.random.randn(hidden_size, hidden_size) * 0.01self.b_f = np.zeros((1, hidden_size))# 输出门参数self.W_xo = np.random.randn(input_size, hidden_size) * 0.01self.W_ho = np.random.randn(hidden_size, hidden_size) * 0.01self.b_o = np.zeros((1, hidden_size))# 候选记忆单元参数self.W_xc = np.random.randn(input_size, hidden_size) * 0.01self.W_hc = np.random.randn(hidden_size, hidden_size) * 0.01self.b_c = np.zeros((1, hidden_size))def forward(self, x, prev_h, prev_c):# 输入门i = sigmoid(np.dot(x, self.W_xi) + np.dot(prev_h, self.W_hi) + self.b_i)# 遗忘门f = sigmoid(np.dot(x, self.W_xf) + np.dot(prev_h, self.W_hf) + self.b_f)# 输出门o = sigmoid(np.dot(x, self.W_xo) + np.dot(prev_h, self.W_ho) + self.b_o)# 候选记忆单元c_tilde = np.tanh(np.dot(x, self.W_xc) + np.dot(prev_h, self.W_hc) + self.b_c)# 更新记忆单元c = f * prev_c + i * c_tilde# 计算隐藏状态h = o * np.tanh(c)return h, c

LSTM的各个门控单元作用如下:

  1. 遗忘门(f):控制上一时刻记忆单元中的信息有多少需要保留
  2. 输入门(i):控制当前时刻新信息有多少需要写入记忆单元
  3. 输出门(o):控制记忆单元中的信息有多少需要输出到隐藏状态
  4. 记忆单元(c):存储长期记忆,通过门控机制进行更新

4.2 门控循环单元(GRU)

GRU是LSTM的简化版本,它将输入门和遗忘门合并为更新门,并引入重置门来控制历史信息的使用。

class GRU:def __init__(self, input_size, hidden_size):# 更新门参数self.W_xz = np.random.randn(input_size, hidden_size) * 0.01self.W_hz = np.random.randn(hidden_size, hidden_size) * 0.01self.b_z = np.zeros((1, hidden_size))# 重置门参数self.W_xr = np.random.randn(input_size, hidden_size) * 0.01self.W_hr = np.random.randn(hidden_size, hidden_size) * 0.01self.b_r = np.zeros((1, hidden_size))# 候选隐藏状态参数self.W_xh = np.random.randn(input_size, hidden_size) * 0.01self.W_hh = np.random.randn(hidden_size, hidden_size) * 0.01self.b_h = np.zeros((1, hidden_size))def forward(self, x, prev_h):# 更新门z = sigmoid(np.dot(x, self.W_xz) + np.dot(prev_h, self.W_hz) + self.b_z)# 重置门r = sigmoid(np.dot(x, self.W_xr) + np.dot(prev_h, self.W_hr) + self.b_r)# 候选隐藏状态h_tilde = np.tanh(np.dot(x, self.W_xh) + np.dot(r * prev_h, self.W_hh) + self.b_h)# 更新隐藏状态h = (1 - z) * prev_h + z * h_tildereturn h

5 实际应用中的优化技巧

5.1 变体和改进

class PeepholeConnLSTM:def __init__(self, input_size, hidden_size):# 标准LSTM参数self.lstm = LSTM(input_size, hidden_size)# Peephole连接参数self.W_ci = np.random.randn(hidden_size, hidden_size) * 0.01self.W_cf = np.random.randn(hidden_size, hidden_size) * 0.01self.W_co = np.random.randn(hidden_size, hidden_size) * 0.01def forward(self, x, prev_h, prev_c):# 修改门控计算,加入记忆单元的直接连接i = sigmoid(np.dot(x, self.lstm.W_xi) + np.dot(prev_h, self.lstm.W_hi) + np.dot(prev_c, self.W_ci) + self.lstm.b_i)f = sigmoid(np.dot(x, self.lstm.W_xf) + np.dot(prev_h, self.lstm.W_hf) + np.dot(prev_c, self.W_cf) + self.lstm.b_f)# 其余计算与标准LSTM相同...

5.2 注意力机制的结合

class AttentionLSTM:def __init__(self, input_size, hidden_size, attention_size):self.lstm = LSTM(input_size, hidden_size)self.attention = Attention(hidden_size, attention_size)def forward(self, x_sequence, prev_h, prev_c):# 存储所有隐藏状态all_hidden_states = []current_h, current_c = prev_h, prev_c# LSTM前向传播for x in x_sequence:current_h, current_c = self.lstm.forward(x, current_h, current_c)all_hidden_states.append(current_h)# 计算注意力权重context = self.attention(all_hidden_states)return context, current_h, current_c

6 实现细节和最佳实践

6.1 初始化策略

def initialize_lstm_params(input_size, hidden_size):# 使用正交初始化def orthogonal(shape):rand = np.random.randn(*shape)u, _, v = np.linalg.svd(rand)return u if u.shape == shape else vparams = {}for gate in ['i', 'f', 'o', 'c']:params[f'W_x{gate}'] = orthogonal((input_size, hidden_size))params[f'W_h{gate}'] = orthogonal((hidden_size, hidden_size))params[f'b_{gate}'] = np.zeros((1, hidden_size))# 特殊处理遗忘门偏置if gate == 'f':params[f'b_{gate}'] += 1.0return params

6.1.1 梯度处理

def lstm_backward(dh_next, dc_next, cache):# 解包缓存的值x, prev_h, prev_c, i, f, o, c_tilde, c, h = cache# 计算各个门和状态的梯度do = dh_next * np.tanh(c)dc = dc_next + dh_next * o * (1 - np.tanh(c)**2)di = dc * c_tildedf = dc * prev_cdc_tilde = dc * i# 计算激活函数的梯度di_raw = di * i * (1 - i)df_raw = df * f * (1 - f)do_raw = do * o * (1 - o)dc_tilde_raw = dc_tilde * (1 - c_tilde**2)# 计算权重梯度dW_xi = np.dot(x.T, di_raw)dW_hi = np.dot(prev_h.T, di_raw)db_i = np.sum(di_raw, axis=0, keepdims=True)# ... 类似计算其他参数的梯度return dW_xi, dW_hi, db_i, ...

基于门控的循环神经网络通过其特殊的结构设计,很好地解决了简单RNN面临的问题。它们在各种序列处理任务中都展现出了优异的性能,成为了深度学习领域最重要的模型之一。理解这些模型的工作原理和实现细节,对于实际应用中选择合适的模型结构和优化策略具有重要的指导意义。

内容不全等,请各位理解支持!!

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

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

相关文章

U盘格式化工具合集:6个免费的U盘格式化工具

在日常使用中,U盘可能会因为文件系统不兼容、数据损坏或使用需求发生改变而需要进行格式化。一个合适的格式化工具不仅可以清理存储空间,还能解决部分存储问题。本文为大家精选了6款免费的U盘格式化工具,并详细介绍它们的功能、使用方法、优缺…

1 数据库(下):多表设计 、多表查询 + SQL中的with查询语法(MySQL8.0以后版本才支持这种新语法)+ 数据库优化(索引优化)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、多表设计1 多表设计-概述2 三种多表关系一对多(多对一)(1)无外键约束(逻辑外键)&…

python读写文件的三种做法

对于文件操作,python提供了3种做法:open(), os.open() 和with open()语句。 1. open()函数:一般用于更高级的文件读写操作,即人能读懂的用法,如果是写入数据,可用传入字符串。 用法:open(path…

RocketMQ(二)RocketMQ实战

文章目录 一、RocketMQ实战1.1 批量消息发送1.2 消息发送队列自选择1.3 事务消息1.4 SpringCloud集成RocketMQ 二、最佳实践2.1 生产者2.1.1 发送消息注意事项2.1.2 消息发送失败处理方式 2.2 消费者2.2.1 消费过程幂等2.2.2 消费打印日志 2.3 Broker 三、相关问题3.1 为什么要…

产品原型设计

🤣🤣目录🤣🤣 一、Axure原型设计(Axure RP 9 )1.1 软件下载安装1.2 产品原型展示1.3 产品原型下载1.4 视频课程推荐 二、磨刀原型设计2.1 软件下载安装2.2 产品原型展示2.3 产品原型下载2.4 视频课程推荐 什…

C++ 编译过程全解析:从源码到可执行文件的蜕变之旅

引言 C 作为一种广泛应用于系统开发、游戏编程、嵌入式系统等领域的高级编程语言,其代码需要经过编译才能转换为计算机可执行的机器语言。编译过程涵盖多个复杂阶段,每个阶段对最终生成的可执行文件的性能、稳定性及兼容性都有着深远影响。深入理解 C 编…

【漏洞复现】NetMizer 日志管理系统 hostdelay.php 前台RCE漏洞复现

免责声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。工具来自网络,安全性自测,如有侵权请联系删除。本次测试仅供学习使用,如若非法他用,与平台和本文作…

hive-sql 连续登录五天的用户

with tmp as (select 梁牧泽 as uid, 2023-03-03 as dt union allselect 梁牧泽 as uid, 2023-03-04 as dt union allselect 梁牧泽 as uid, 2023-03-05 as dt union allselect 梁牧泽 as uid, 2023-03-07 as dt union allselect 梁牧泽 as uid, 2023-03-08 as dt union allsel…

【运维】部署MKDocs

部署MKDocs obsidian 记录笔记,通过 mkdocs 私有化部署。 1 使用MKDocs创建笔记 创建仓库,安装 Material for MkDocs 和 mkdocs-minify-plugin mkdir tmp cd tmp git initpip install mkdocs-material pip install mkdocs-minify-pluginmkdocs new .2 …

Linux的进程替换以及基础IO

进程替换 上一篇草率的讲完了进程地址空间的组成结构和之间的关系,那么我们接下来了解一下程序的替换。 首先,在进程部分我们提过了,其实文件可以在运行时变成进程,而我们使用的Linux软件其实也是一个进程,所以进一步…

C#编写的金鱼趣味小应用 - 开源研究系列文章

今天逛网,在GitHub中文网上发现一个源码,里面有这个金鱼小应用,于是就下载下来,根据自己的C#架构模板进行了更改,最终形成了这个例子。 1、 项目目录; 2、 源码介绍; 1) 初始化; 将样…

cloudns二级免费域名python更新ipv6 dns记录

没找到api,托管到cloudflare也不行。就只能写代码了(只写了更新和添加单条ipv6记录) 需要修改的地方 请求头的cookies填自己的 data里的zone填自己的 import requests from lxml import etree host#子域名 cookies填自己的 zone自己域名的 …

机器学习作业 | 泰坦尼克号生存的预测任务

泰坦尼克号生存的预测任务 学校作业,我来水一水 环境:pycharmanaconda虚拟环境 文章目录 泰坦尼克号生存的预测任务0.环境搭建参考:1 目的与要求2 任务背景3 任务简介4 模型介绍1.决策树(Decision Tree)2.朴素贝叶斯…

【pytorch】conda安装pytorch

Step 1 打开官网: https://pytorch.org/get-started/locally/ 进行选择对应版本: 复制图中命令执行。 Step 2 验证是否安装成功。 执行: import torch print(torch.cuda.is_available()) print(torch.cuda.device_count()) print(torch.…

项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(四)

文章目录 一、管理员角色功能实现1、添加教师功能实现1.1 页面设计1.2 前端功能实现1.3 后端功能实现1.4 效果展示2、教师管理功能实现2.1 页面设计2.2 前端功能实现2.3 后端功能实现2.3.1 后端查询接口实现2.3.2 后端编辑接口实现2.3.3 后端删除接口实现2.4 效果展示二、代码下…

基于16QAM的载波同步和定时同步性能仿真,采用四倍采样,包括Costas环和gardner环

目录 1.算法仿真效果 2.算法涉及理论知识概要 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下(完整代码运行后无水印): 仿真操作步骤可参考程序配套的操作视频。 2.算法涉及理论知识概要 载波同步是…

新服务器ubuntu系统相关操作

1、查看驱动:驱动版本535.216.01能够支持cuda12.2,下面直接使用默认安装的cuda。 2、赋予用户管理员权限。 首先有超级用户(root)权限来编辑 /etc/sudoers 文件,visudo 是一个命令,用于安全地编辑 /etc/sudoers 文件。运行: sudo visudo 在 visudo 编辑器中,找到类似…

2、Bert论文笔记

Bert论文 1、解决的问题2、预训练微调2.1预训练微调概念2.2深度双向2.3基于特征和微调(预训练下游策略) 3、模型架构4、输入/输出1.输入:2.输出:3.Learned Embeddings(学习嵌入)1. **Token Embedding**2. **Position Embedding**3…

python 渗透开发工具之SQLMapApi Server不同IP服务启动方式处理 解决方案SqlMapApiServer外网不能访问的情况

目录 说在前面 什么是 SQLMapAPI 说明 sqlmapApi能干什么 sqlmapApi 服务安装相关 kali-sqlmap存放位置 正常启动sqlmap-api server SqlMapApi-Server 解决外网不能访问情况 说在前面 什么是sqlmap 这个在前面已经说过了,如果这个不知道,就可以…

操作系统论文导读(八):Schedulability analysis of sporadic tasks with multiple criticality specifications——具有多个

Schedulability analysis of sporadic tasks with multiple criticality specifications——具有多个关键性规范的零星任务的可调度性分析 目录 一、论文核心思想 二、基本定义 2.1 关键性指标 2.2 任务及相关参数定义 2.3 几个基础定义 三、可调度性分析 3.1 调度算法分…