HBU深度学习作业9

1. 实现SRN

(1)使用Numpy实现SRN 

import numpy as np
 
inputs = np.array([[1., 1.],
                   [1., 1.],
                   [2., 2.]])  # 初始化输入序列
print('inputs is ', inputs)
 
state_t = np.zeros(2, )  # 初始化存储器
print('state_t is ', state_t)
 
w1, w2, w3, w4, w5, w6, w7, w8 = 1., 1., 1., 1., 1., 1., 1., 1.
U1, U2, U3, U4 = 1., 1., 1., 1.
for input_t in inputs:
    print('inputs is ', input_t)
    print('state_t is ', state_t)
    in_h1 = np.dot([w1, w3], input_t) + np.dot([U2, U4], state_t)
    in_h2 = np.dot([w2, w4], input_t) + np.dot([U1, U3], state_t)
    state_t = in_h1, in_h2
    output_y1 = np.dot([w5, w7], [in_h1, in_h2])
    output_y2 = np.dot([w6, w8], [in_h1, in_h2])
    print('output_y is ', output_y1, output_y2)
    print('---------------------')

(2)在1的基础上,增加激活函数tanh

import numpy as np
 
inputs = np.array([[1., 1.],
                   [1., 1.],
                   [2., 2.]])  # 初始化输入序列
print('inputs is ', inputs)
 
state_t = np.zeros(2, )  # 初始化存储器
print('state_t is ', state_t)
 
w1, w2, w3, w4, w5, w6, w7, w8 = 1., 1., 1., 1., 1., 1., 1., 1.
U1, U2, U3, U4 = 1., 1., 1., 1.
print('--------------------------------------')
for input_t in inputs:
    print('inputs is ', input_t)
    print('state_t is ', state_t)
    in_h1 = np.tanh(np.dot([w1, w3], input_t) + np.dot([U2, U4], state_t))
    in_h2 = np.tanh(np.dot([w2, w4], input_t) + np.dot([U1, U3], state_t))
    state_t = in_h1, in_h2
    output_y1 = np.dot([w5, w7], [in_h1, in_h2])
    output_y2 = np.dot([w6, w8], [in_h1, in_h2])
    print('output_y is ', output_y1, output_y2)
    print('---------------------------------------------')

(3)使用nn.RNNCell实现

import torch
 
batch_size = 1
seq_len = 3  # 序列长度
input_size = 2  # 输入序列维度
hidden_size = 2  # 隐藏层维度
output_size = 2  # 输出层维度
 
# RNNCell
cell = torch.nn.RNNCell(input_size=input_size, hidden_size=hidden_size)
# 初始化参数 https://zhuanlan.zhihu.com/p/342012463
for name, param in cell.named_parameters():
    if name.startswith("weight"):
        torch.nn.init.ones_(param)
    else:
        torch.nn.init.zeros_(param)
# 线性层
liner = torch.nn.Linear(hidden_size, output_size)
liner.weight.data = torch.Tensor([[1, 1], [1, 1]])
liner.bias.data = torch.Tensor([0.0])
 
seq = torch.Tensor([[[1, 1]],
                    [[1, 1]],
                    [[2, 2]]])
hidden = torch.zeros(batch_size, hidden_size)
output = torch.zeros(batch_size, output_size)
 
for idx, input in enumerate(seq):
    print('=' * 20, idx, '=' * 20)
 
    print('Input :', input)
    print('hidden :', hidden)
 
    hidden = cell(input, hidden)
    output = liner(hidden)
    print('output :', output)

(4)使用nn.RNN实现

import torch
 
batch_size = 1
seq_len = 3
input_size = 2
hidden_size = 2
num_layers = 1
output_size = 2
 
cell = torch.nn.RNN(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers)
for name, param in cell.named_parameters():  # 初始化参数
    if name.startswith("weight"):
        torch.nn.init.ones_(param)
    else:
        torch.nn.init.zeros_(param)
 
# 线性层
liner = torch.nn.Linear(hidden_size, output_size)
liner.weight.data = torch.Tensor([[1, 1], [1, 1]])
liner.bias.data = torch.Tensor([0.0])
 
inputs = torch.Tensor([[[1, 1]],
                       [[1, 1]],
                       [[2, 2]]])
hidden = torch.zeros(num_layers, batch_size, hidden_size)
out, hidden = cell(inputs, hidden)
 
print('Input :', inputs[0])
print('hidden:', 0, 0)
print('Output:', liner(out[0]))
print('--------------------------------------')
print('Input :', inputs[1])
print('hidden:', out[0])
print('Output:', liner(out[1]))
print('--------------------------------------')
print('Input :', inputs[2])
print('hidden:', out[1])
print('Output:', liner(out[2]))

2. 实现“序列到序列”

import torch

input_size = 4
hidden_size = 4
batch_size = 1

idx2char = ['e', 'h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [3, 1, 2, 3, 2]

one_hot_lookup = [[1, 0, 0, 0],
                  [0, 1, 0, 0],
                  [0, 0, 1, 0],
                  [0, 0, 0, 1]]

x_one_hot = [one_hot_lookup[x] for x in x_data]

inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size)
labels = torch.LongTensor(y_data).view(-1, 1)


class Model(torch.nn.Module):
    def __init__(self, input_size, hidden_size, batch_size):
        super(Model, self).__init__()
        self.batch_size = batch_size
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.rnncell = torch.nn.RNNCell(input_size=self.input_size,
                                        hidden_size=self.hidden_size)

    def forward(self, input, hidden):
        hidden = self.rnncell(input, hidden)
        return hidden

    def init_hidden(self):
        return torch.zeros(self.batch_size, self.hidden_size)


net = Model(input_size, hidden_size, batch_size)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.1)

for epoch in range(15):  # 循环15轮
    loss = 0
    optimizer.zero_grad()  # 每一次计算前先把梯度归零
    hidden = net.init_hidden()  # 初始化 h_0
    print('Predicted string:', end='')
    for input, label in zip(inputs, labels):  # 输入seq_length, batch_size, input_size
        hidden = net(input, hidden)
        loss += criterion(hidden, label)  # 所有的损失要用累加,不能用item
        _, idx = hidden.max(dim=1)  # 找到hidden 里面最大的值,认为是最有可能的
        print(idx2char[idx.item()], end='')
    loss.backward()  # 反向传播
    optimizer.step()  # 更新参数
    print(', Epoch [%d/15] loss=%.4f' % (epoch + 1, loss.item()))

3. “编码器-解码器”的简单实现

import torch
import numpy as np
import torch.nn as nn
import torch.utils.data as Data

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# S: Symbol that shows starting of decoding input
# E: Symbol that shows starting of decoding output
# ?: Symbol that will fill in blank sequence if current batch data size is short than n_step

letter = [c for c in 'SE?abcdefghijklmnopqrstuvwxyz']
letter2idx = {n: i for i, n in enumerate(letter)}

seq_data = [['man', 'women'], ['black', 'white'], ['king', 'queen'], ['girl', 'boy'], ['up', 'down'], ['high', 'low']]

# Seq2Seq Parameter
n_step = max([max(len(i), len(j)) for i, j in seq_data])  # max_len(=5)
n_hidden = 128
n_class = len(letter2idx)  # classfication problem
batch_size = 3


def make_data(seq_data):
    enc_input_all, dec_input_all, dec_output_all = [], [], []

    for seq in seq_data:
        for i in range(2):
            seq[i] = seq[i] + '?' * (n_step - len(seq[i]))  # 'man??', 'women'

        enc_input = [letter2idx[n] for n in (seq[0] + 'E')]  # ['m', 'a', 'n', '?', '?', 'E']
        dec_input = [letter2idx[n] for n in ('S' + seq[1])]  # ['S', 'w', 'o', 'm', 'e', 'n']
        dec_output = [letter2idx[n] for n in (seq[1] + 'E')]  # ['w', 'o', 'm', 'e', 'n', 'E']

        enc_input_all.append(np.eye(n_class)[enc_input])
        dec_input_all.append(np.eye(n_class)[dec_input])
        dec_output_all.append(dec_output)  # not one-hot

    # make tensor
    return torch.Tensor(enc_input_all), torch.Tensor(dec_input_all), torch.LongTensor(dec_output_all)


'''
enc_input_all: [6, n_step+1 (because of 'E'), n_class]
dec_input_all: [6, n_step+1 (because of 'S'), n_class]
dec_output_all: [6, n_step+1 (because of 'E')]
'''
enc_input_all, dec_input_all, dec_output_all = make_data(seq_data)


class TranslateDataSet(Data.Dataset):
    def __init__(self, enc_input_all, dec_input_all, dec_output_all):
        self.enc_input_all = enc_input_all
        self.dec_input_all = dec_input_all
        self.dec_output_all = dec_output_all

    def __len__(self):  # return dataset size
        return len(self.enc_input_all)

    def __getitem__(self, idx):
        return self.enc_input_all[idx], self.dec_input_all[idx], self.dec_output_all[idx]


loader = Data.DataLoader(TranslateDataSet(enc_input_all, dec_input_all, dec_output_all), batch_size, True)


# Model
class Seq2Seq(nn.Module):
    def __init__(self):
        super(Seq2Seq, self).__init__()
        self.encoder = nn.RNN(input_size=n_class, hidden_size=n_hidden, dropout=0.5)  # encoder
        self.decoder = nn.RNN(input_size=n_class, hidden_size=n_hidden, dropout=0.5)  # decoder
        self.fc = nn.Linear(n_hidden, n_class)

    def forward(self, enc_input, enc_hidden, dec_input):
        # enc_input(=input_batch): [batch_size, n_step+1, n_class]
        # dec_inpu(=output_batch): [batch_size, n_step+1, n_class]
        enc_input = enc_input.transpose(0, 1)  # enc_input: [n_step+1, batch_size, n_class]
        dec_input = dec_input.transpose(0, 1)  # dec_input: [n_step+1, batch_size, n_class]

        # h_t : [num_layers(=1) * num_directions(=1), batch_size, n_hidden]
        _, h_t = self.encoder(enc_input, enc_hidden)
        # outputs : [n_step+1, batch_size, num_directions(=1) * n_hidden(=128)]
        outputs, _ = self.decoder(dec_input, h_t)

        model = self.fc(outputs)  # model : [n_step+1, batch_size, n_class]
        return model


model = Seq2Seq().to(device)
criterion = nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

for epoch in range(5000):
    for enc_input_batch, dec_input_batch, dec_output_batch in loader:
        # make hidden shape [num_layers * num_directions, batch_size, n_hidden]
        h_0 = torch.zeros(1, batch_size, n_hidden).to(device)

        (enc_input_batch, dec_intput_batch, dec_output_batch) = (
            enc_input_batch.to(device), dec_input_batch.to(device), dec_output_batch.to(device))
        # enc_input_batch : [batch_size, n_step+1, n_class]
        # dec_intput_batch : [batch_size, n_step+1, n_class]
        # dec_output_batch : [batch_size, n_step+1], not one-hot
        pred = model(enc_input_batch, h_0, dec_intput_batch)
        # pred : [n_step+1, batch_size, n_class]
        pred = pred.transpose(0, 1)  # [batch_size, n_step+1(=6), n_class]
        loss = 0
        for i in range(len(dec_output_batch)):
            # pred[i] : [n_step+1, n_class]
            # dec_output_batch[i] : [n_step+1]
            loss += criterion(pred[i], dec_output_batch[i])
        if (epoch + 1) % 1000 == 0:
            print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.6f}'.format(loss))

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()


def translate(word):
    enc_input, dec_input, _ = make_data([[word, '?' * n_step]])
    enc_input, dec_input = enc_input.to(device), dec_input.to(device)
    # make hidden shape [num_layers * num_directions, batch_size, n_hidden]
    hidden = torch.zeros(1, 1, n_hidden).to(device)
    output = model(enc_input, hidden, dec_input)
    # output : [n_step+1, batch_size, n_class]

    predict = output.data.max(2, keepdim=True)[1]  # select n_class dimension
    decoded = [letter[i] for i in predict]
    translated = ''.join(decoded[:decoded.index('E')])

    return translated.replace('?', '')


print('test')
print('man ->', translate('man'))
print('mans ->', translate('mans'))
print('king ->', translate('king'))
print('black ->', translate('black'))
print('up ->', translate('up'))

4.简单总结nn.RNNCell、nn.RNN

参考链接:

【PyTorch学习笔记】21:nn.RNN和nn.RNNCell的使用-CSDN博客

【学习笔记】RNN算法的pytorch实现 - Lugendary - 博客园 (cnblogs.com)

torch 循环神经网络torch.nn.RNN()和 torch.nn.RNNCell()-CSDN博客 

torch.nn.RNN()调用的是循环神经网络最原始的形态,这种没法处理比较长的时间序列,后面的变体Lstm和GRU解决了这个问题,这里只是用torch.nn.RNN()展示一下循环神经网络的一些基本参数等信息,当然有些大神也是直接调用这个去搭建一些自己需要的网络结构。

import torch
from torch.autograd import Variable
from torch import nn

input_size = 10
batch_size = 5

hidden_size = 20
num_layers = 2
#定义一个最简单的循环神经网络,网络输入的特征维度为10,隐层的节点数目为20个,有2层
model = nn.RNN(input_size=input_size, hidden_size=hidden_size, num_layers=num_layers)

x = torch.rand(3, batch_size, input_size) #这里理解为生成batch_size条数据,每条数据长度为3,特征维度为input_size
h0 = torch.zeros(num_layers, batch_size, hidden_size) #这里定义最初始输入的记忆状态,直接设置为0就行
y, h = model(x, h0)

print('y.shape=', y.shape)
print('h.shape=', h.shape)

 

上面搭建了一个最简单的示例,解释下y和h的输出都表示什么,这对后面的使用影响比较大,循环神经网络是这样的,一条时间序列的长度为3,那么就对应了3个时刻,前面一个时刻模型的神经元的输出会作为下一个时刻模型神经元的输入,假设模型的所有神经元表示为H,h表示所有神经元的输出,h也叫记忆单元。那么在最开始的时间t0,计算过程就是

h1 = H(h0 + x0) #h0为初始化输入,可以直接设置为0
#因为时间序列每个元素都需要对应一个输出,于是0时刻,第1个元素对应的输出为
out1 = h1[-1] #也就是所有神经元输出的最后一层
开始循环如下:
h2 = H(h1 +  x1)
out2 = h2[-1]
h3 = H(h2 +  x2)
out3 = h3[-1]

最后训练结束,输出的h就是最后一个时刻模型所有神经元的输出,也就是h3,我们上面定义的模型有2层,每层神经元数目为20,于是得到的输出尺寸应该为[2, 20],又因为上面我设置了5条神经元数据,每条都对应一个[2, 20]的输出矩阵,所以最终的输出矩阵尺寸为[2, 5, 20],记得中间的维度是针对第几条数据,希望读者能理解输出和输入都是表示什么。

那么很好理解了吧,模型最后输出的y,就是每个时刻元素的输出,也就是[out1, out2, out3],每个out都是模型最后一层神经元的输出,尺寸为[1, 20],这里我设置的数据每条时间序列有3个元素,每个元素对应一个时刻的输出,于是尺寸为[3, 20],又因为有5条数据,所以最终尺寸为[3, 5, 20]。

这里注意下,RNN的输入格式不同于CNN,CNN模型的输入尺寸是batch_size放前面,也就是[batch_size, input_size_1, input_size_2],而RNN是放中间,也就是
[input_size_1, batch_size, input_size_2],希望各位同学注意下。

这里需要对比的是RNNCell,我们上面提到上述过程是一个循环的过程,唯一区别就是,RNN是读取了0时刻的隐层信息h0,剩下的过程是自动循环完成的,而RNNCell就需要自己写循环处理了,代码如下:

import torch
from torch.autograd import Variable
from torch import nn

input_size = 10
batch_size = 5

hidden_size = 20
num_layers = 2
#定义一个最简单的循环神经网络,网络输入的特征维度为10,隐层的节点数目为20个
model = nn.RNNCell(input_size=input_size, hidden_size=hidden_size)

x = torch.rand(3, batch_size, input_size) #这里理解为生成batch_size条数据,每条数据长度为3,特征维度为input_size
h0 = torch.zeros(batch_size, hidden_size) #这里定义最初始输入的记忆状态,直接设置为0就行

for i in range(3):
    h0 = model(x[i], h0)
    y = h0
    print(y.shape)

RNNCell是单层结构,所以每次的输出,就是对应时刻元素x的输出。 

5.谈一谈对“序列”、“序列到序列”的理解

参考链接:

序列到序列 | 机器之心 (jiqizhixin.com)

使用Python实现深度学习模型:序列到序列模型(Seq2Seq) - 华为云开发者联盟 - 博客园 (cnblogs.com)

什么是序列?

序列数据(Sequence Data) 是指按照一定顺序排列的数据集合,其中的每个元素被称为序列的一个项(item)。

序列数据的特点是按顺序排列,元素之间存在时间或空间上的依赖关系。

什么是序列到序列?

序列到序列学习(Seq2Seq)是指训练模型从而把一个域的序列(比如英语语句)转化为另一个域的序列(比如法语中的对应语句):

 这是一种通用的端到端序列学习方法,它基于编码-解码(Encoder - Decoder)的架构。一般情况下,输入序列和输出序列有不同的长度(比如机器翻译)。这就需要一个更高级的设置,尤其在没有进一步语境的「序列到序列模型」时。下面是其工作原理:

  • 一个 RNN 层(或其中的堆栈)作为「编码器」:它处理输入序列并反馈其内部状态。注意我们抛弃了编码器 RNN 的输出,只恢复其状态。该状态在下一步中充当解码器的「语境」。
  • 另一个 RNN 层作为「解码器」:在给定目标序列先前字母的情况下,它被训练以预测目标序列的下一个字符。具体讲,它被训练把目标序列转化为相同序列,但接下来被一个时间步抵消,这一训练过程在语境中被称为「teacher forcing」。更重要的是,编码器把其状态向量用作初始状态,如此编码器获得了其将要生成的信息。实际上,在给定 targets[...t] 的情况下,解码器学习生成 targets[t+1...],前提是在输入序列上。

什么是序列到序列模型?

Seq2Seq 模型通常由两个主要部分组成:编码器(Encoder)和解码器(Decoder)。编码器将输入序列编码成一个固定长度的上下文向量(context vector),然后解码器根据这个上下文向量生成目标序列。

编码器(Encoder)

编码器是一个循环神经网络(RNN),如 LSTM 或 GRU,用于处理输入序列,并生成一个上下文向量。这个向量总结了输入序列的全部信息。

解码器(Decoder)

解码器也是一个 RNN,使用编码器生成的上下文向量作为初始输入,并逐步生成目标序列的每一个元素。

训练过程

在训练过程中,解码器在每一步生成一个单词,并使用该单词作为下一步的输入。这种方法被称为教师强制(Teacher Forcing)。

6.总结本周理论课和作业,写心得体会

 参考链接:

RNN Layer - mathor (wmathor.com)

人工智能 - 循环神经网络RNN完全解析:从基础理论到PyTorch实战 - 个人文章 - SegmentFault 思否

 

 

 这次作业主要是熟悉RNN的基本原理、RNN与CNN和DNN的不同与联系

RNN 主要由输入层、隐藏层和输出层组成。其中,隐藏层之间的节点不再无连接,而是有连接的,并且隐藏层的输入不仅包括输入层的输出,还包括上一时刻隐藏层的输出。

 

对于初学者而言,搜资料的时候这个图会频繁出现,不好理解

真正的图长这样,这样看就舒服多了

还有就是RNN中的权值共享。

 无论是W、U、V在每个时间步上都是同一个

若说CNN是空间上的权值共享,那么RNN就是时间步上的共享

参数共享在一定程度上可以对文本处理中的每个单元实现“相对公平”,虽然这不一定是好事,后续LSTM以及attention的提出则打破了这种公平。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能堆叠,集群和IRF

堆叠和IRF其实可以近似看成同一种技术,只是华三叫IRF,华为叫智能堆叠 智能堆叠(iStack):支持堆叠特性的交换机通过堆叠线缆连接在一起,从逻辑上变成一台交换设备,作为一个整体参与数据转发&…

三维渲染中顺序无关的半透明混合(OIT)(二——Stencil Route)

1、A-Buffer算法。 在谈到Stencil Route之前,需要先讨论A-Buffer算法。A-Buffer是一种图形学(渲染方向)上的用于可见面分析(Visble Surface Detection)的技术,是Z-Buffer的衍生方法。 Z-Buffer是用于剔除 不透明 物体的算法。假…

transformers bert-base-uncased情感分析

一、使用huggingface中的预训练模型,先要安装transformers、torch和SentencePiece pip install transformers pip install torch pip install SentencePiece 手动下载:https://huggingface.co/google-bert/bert-base-uncased/tree/main 添加以目录&…

Android开发仿qq详情下拉头像变大

Android开发仿qq详情下拉头像变大 个人详情界面,很多都有下拉头像变大的效果,其实我觉得这效果还不如点击头像看大图呢 一、思路: 自定义ScrollView 二、效果图: 看视频更直观点: Android开发教程案例分享-仿qq详情…

洛谷 P1157 组合的输出 C语言

题目:https://www.luogu.com.cn/problem/P1157#submit 题目描述 排列与组合是常用的数学方法,其中组合就是从 n 个元素中抽出 rr 个元素(不分顺序且 r≤nr≤n),我们可以简单地将 n 个元素理解为自然数 1,2,…,n从中任…

数据结构3.链表

目录 1.链表的概念及结构 2.链表的分类 1.单向或者双向 2.带头或者不带头 3.循环或者非循环 3.链表的实现 1.无头单向非循环链表 2.双向带头循环链表 4.顺序表和链表的区别 1.链表的概念及结构 概念:链表是一种物理存储结构上非连续、非顺序的存储结构&…

A054-基于Spring Boot的青年公寓服务平台

🙊作者简介:在校研究生,拥有计算机专业的研究生开发团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹 赠送计算机毕业设计600…

paimon的四种changelog模式(2)-none模式

# 请先了解input模式 环境创建 CREATE CATALOG fs_catalog WITH (typepaimon,warehousefile:/data/soft/paimon/catalog );USE CATALOG fs_catalog;drop table if exists t_changelog_none ;CREATE TABLE t_changelog_none (age BIGINT,money BIGINT,hh STRING,PRIMARY KEY (h…

【CSS in Depth 2 精译_064】10.3 CSS 中的容器查询相对单位 + 10.4 CSS 容器样式查询 + 10.5 本章小结

当前内容所在位置(可进入专栏查看其他译好的章节内容) 【第十章 CSS 容器查询】 ✔️ 10.1 容器查询的一个简单示例 10.1.1 容器尺寸查询的用法 10.2 深入理解容器 10.2.1 容器的类型10.2.2 容器的名称10.2.3 容器与模块化 CSS 10.3 与容器相关的单位 ✔…

CSS笔记(二)类名复用

这里我通过两张不同位置的卡片来实现效果 代码 <!DOCTYPE html> <html><head><style>/*设置画布*/body{/* 方便排列与对齐*/display: flex; /*画布布满整个窗口*/height: 100vh;/*水平居中*/justify-content: center;/*垂直居中*/align-items: cente…

常用函数的使用错题汇总

#include <iostream> #include <fstream> #include <string>int main() {std::ifstream fin("example.txt"); // 创建 ifstream 对象并打开文件// 检查文件是否成功打开if (!fin) {std::cerr << "Error opening file!" << s…

【树莓派5】移动热点获取树莓派IP并初次登录SSH

本篇文章包含的内容 1 打开系统热点2 烧录系统设置3 配置 MobaXterm4 初次启动树莓派配置选项4.1 换源4.2 更新软件包4.3 安装vim编辑器4.4 更改CPU FAN温度转速 Windows版本&#xff1a;Windows11 24H2树莓派&#xff1a;树莓派5&#xff0c;Raspberry Pi 5SSH软件&#xff1a…

分布式调用 - 服务间的远程调用RPC

文章目录 导图PreRPC 概述RPC 调用过程RPC 动态代理1. 接口定义 (SeverProvider)2. 实现类 (ServerProviderImpl)3. 动态代理类 (DynamicProxy)4. 客户端 (Client)5. 代码工作流程6. 总结和注意点7. 结果输出8. 小结 RPC 序列化1. JSON (JavaScript Object Notation)2. Hessian…

基于Matlab湍流对高斯光束传播影响的模拟与评估

随着光学通信与激光技术的不断发展&#xff0c;湍流对光束传播的影响已成为研究中的重要课题。特别是在大气湍流条件下&#xff0c;光束的传播会受到相位扰动的影响&#xff0c;从而导致光束质量的恶化、能量损失及光束中心的偏移等问题。本文基于高斯光束模型&#xff0c;提出…

19. C++STL 5(深入理解vector,vector的模拟实现,二维动态数组)

⭐本篇重点&#xff1a;vector深入理解和模拟实现 ⭐本篇代码&#xff1a;c学习/09.vector-2 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) 目录 一. 深入理解vector 二. 使用模板模拟实现vector &#xff08;包含迭代器&#xff09; 2.1 模拟vector类的成员…

PDF文件怎么加密?如何给pdf文档加密码保护?(2025全新科普)

PDF文件因其跨平台兼容性和格式稳定性&#xff0c;成为广泛使用的文档格式。 然而&#xff0c;随着信息泄露风险的增加&#xff0c;如何保护PDF文件的安全成为了一个重要问题。 本文将介绍几种2025年最新的PDF文件加密方法&#xff0c;帮助用户为PDF文档添加密码保护。 一、使…

服务器端使用国密证书

服务器端国密证书nignx代理配置 1.资料准备 从gmssl实验室下载已经编译完成的gmssl包 地址&#xff1a;https://www.gmssl.cn/gmssl/index.jsp 下载位置&#xff1a; 保证openssl支持国密算法&#xff0c;ssl 1.1.1 已支持&#xff0c;检查一下最佳 准备一个支持国密的ngin…

第04章_运算符(基础)

1. 算术运算符 算术运算符主要用于数学运算&#xff0c;其可以连接运算符前后的两个数值或表达式&#xff0c;对数值或表达式进行加&#xff08;&#xff09;、减&#xff08;-&#xff09;、乘&#xff08;*&#xff09;、除&#xff08;/&#xff09;和取模&#xff08;%&am…

如何寻找适合的HTTP代理IP资源?

一、怎么找代理IP资源&#xff1f; 在选择代理IP资源的时候&#xff0c;很多小伙伴往往将可用率作为首要的参考指标。事实上&#xff0c;市面上的住宅IP或拨号VPS代理IP资源&#xff0c;其可用率普遍在95%以上&#xff0c;因此IP可用率并不是唯一的评判标准 其实更应该关注的…

FinalShell工具数据备份升级、密码解密方法

前言 FinalShell 作为国产的服务器管理工具和远程终端软件。一个一体化的运维工具&#xff0c;在国内运维人员中还是比较受欢迎。它整合了多个常用功能&#xff0c;界面友好&#xff0c;使用方便。不过它是一个闭源的商业软件&#xff0c;虽然提供免费版本&#xff0c;但部分高…