机器学习学习笔记-20241018

继续跟着小土堆去学习机器学习

文章目录

    • Flatten
      • 1. `Flatten` 的作用
      • 2. 何时使用 `Flatten`
      • 3. PyTorch 中的 `Flatten`
    • Sequentia
    • 优化器
    • 模型的保存与加载
    • 模型的完整训练

Flatten

在神经网络中,Flatten 操作是将高维的输入(如二维图像或三维特征图)转换为一维向量的过程。这个步骤通常出现在卷积神经网络(CNN)的中后部分,用于连接卷积层或池化层的输出与全连接层(Fully Connected Layer, FC)。

1. Flatten 的作用

在卷积神经网络中,输入通常是多维数据,比如图像会表示为三维张量(例如,RGB图片的格式为 [Height, Width, Channels])。卷积层或池化层处理之后,输出的仍然是高维的特征图。为了能够与全连接层相连,需要将这些高维特征图转换为一维向量,这就是 Flatten 的作用。

示例:
假设一个卷积层的输出形状是 (batch_size, channels, height, width),比如 (64, 6, 30, 30),在使用 Flatten 后,会将这个输出转换为 (batch_size, 6 * 30 * 30),即 (64, 5400),这样可以输入到全连接层中。

2. 何时使用 Flatten

Flatten 通常在以下场景中使用:

  • 卷积神经网络的最后阶段:在卷积层或池化层处理完特征图后,通常会在全连接层之前使用 Flatten,将特征图展开为一维向量。
  • 序列或分类问题:全连接层一般用于序列生成或分类任务,输入要求是向量形式,而不是多维的张量。

3. PyTorch 中的 Flatten

在 PyTorch 中,Flatten 操作可以使用 torch.flatten() 或者直接在模型中使用 nn.Flatten() 层。

代码示例:

import torch
import torch.nn as nn# 定义一个简单的卷积神经网络
class SimpleCNN(nn.Module):def __init__(self):super(SimpleCNN, self).__init__()# 定义一个卷积层self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=1)# 定义一个最大池化层self.pool = nn.MaxPool2d(kernel_size=2, stride=2)# 定义一个Flatten层self.flatten = nn.Flatten()# 定义一个全连接层self.fc = nn.Linear(6 * 16 * 16, 10)  # 假设输入图像是32x32,经过池化后尺寸为16x16def forward(self, x):x = self.conv1(x)  # 卷积层x = self.pool(x)    # 池化层x = self.flatten(x)  # 展平特征图x = self.fc(x)      # 全连接层return x# 创建网络实例
model = SimpleCNN()# 随机生成一个输入张量,模拟输入32x32的RGB图像
input_tensor = torch.randn(1, 3, 32, 32)# 前向传播
output = model(input_tensor)
print(output.shape)  # 输出的张量形状

在这个例子中,Flatten 将卷积层的输出从 (batch_size, channels, height, width) 转换为一维向量 (batch_size, flattened_size)。其中 flattened_size = channels * height * width,从而可以输入到全连接层中。

Sequentia

在这里插入图片描述

import torch
from torch import nn  # 导入PyTorch中的神经网络模块
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential  # 导入必要的网络层
from torch.utils.tensorboard import SummaryWriter  # 导入用于TensorBoard可视化的工具# 定义神经网络模型类,继承自nn.Module
class Tudui(nn.Module):def __init__(self):# 调用父类的初始化方法super(Tudui, self).__init__()# 使用Sequential容器将多个层按顺序构建self.model1 = Sequential(# 第一个卷积层:输入通道3(对应RGB图像),输出通道32,卷积核大小5x5,填充为2(保持图像大小)Conv2d(3, 32, 5, padding=2),# 第一个池化层:使用2x2的最大池化层来缩小图像尺寸MaxPool2d(2),# 第二个卷积层:输入通道32,输出通道仍为32,卷积核大小5x5,填充为2Conv2d(32, 32, 5, padding=2),# 第二个池化层:继续使用2x2的最大池化MaxPool2d(2),# 第三个卷积层:输入通道32,输出通道64,卷积核大小5x5,填充为2Conv2d(32, 64, 5, padding=2),# 第三个池化层:再次使用2x2的最大池化MaxPool2d(2),# 展平层:将3D的特征图展开为1D的向量,便于传入全连接层Flatten(),# 全连接层:将展平后的特征图(大小为1024)映射到64维向量Linear(1024, 64),# 全连接层:将64维向量映射到最终的10类(假设是10分类任务)Linear(64, 10))# 定义前向传播的过程def forward(self, x):x = self.model1(x)  # 将输入x依次传入self.model1中的各层return x  # 返回最终的输出# 实例化网络模型
tudui = Tudui()# 打印模型结构,方便检查各层的参数与连接情况
print(tudui)# 创建一个大小为[64, 3, 32, 32]的输入张量,表示批量大小为64,3通道的32x32图像
input = torch.ones((64, 3, 32, 32))# 将输入张量传入模型,获取输出
output = tudui(input)# 打印输出的形状,通常是[64, 10],即64个样本,每个样本对应10类的输出
print(output.shape)# 创建TensorBoard的SummaryWriter实例,指定日志保存的路径
writer = SummaryWriter("../logs_seq")# 将模型图添加到TensorBoard中进行可视化
writer.add_graph(tudui, input)# 关闭writer,释放资源
writer.close()

优化器

优化器就是更新参数和学习率

import torch  # 导入PyTorch库
import torchvision  # 导入用于计算机视觉任务的工具包
from torch import nn  # 导入神经网络模块
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear  # 导入需要使用的网络层
from torch.optim.lr_scheduler import StepLR  # 导入学习率调度器
from torch.utils.data import DataLoader  # 导入数据加载器# 下载并加载CIFAR-10数据集,将图像转换为张量格式
dataset = torchvision.datasets.CIFAR10("../data", train=False, transform=torchvision.transforms.ToTensor(),download=True)# 使用DataLoader来按批次加载数据
dataloader = DataLoader(dataset, batch_size=1)  # 设置batch_size为1,意味着一次加载一张图片# 定义一个卷积神经网络模型类
class Tudui(nn.Module):def __init__(self):super(Tudui, self).__init__()# 使用Sequential容器将多个层按顺序连接self.model1 = Sequential(Conv2d(3, 32, 5, padding=2),  # 第一个卷积层:输入3通道(RGB),输出32通道,卷积核5x5,填充2MaxPool2d(2),  # 第一个最大池化层:2x2池化Conv2d(32, 32, 5, padding=2),  # 第二个卷积层:输入32通道,输出32通道,卷积核5x5,填充2MaxPool2d(2),  # 第二个最大池化层Conv2d(32, 64, 5, padding=2),  # 第三个卷积层:输入32通道,输出64通道MaxPool2d(2),  # 第三个最大池化层Flatten(),  # 展平:将多维特征图展开为一维向量Linear(1024, 64),  # 全连接层:将1024维的特征向量映射到64维Linear(64, 10)  # 全连接层:将64维向量映射到10类(CIFAR-10数据集的类别数))# 前向传播过程def forward(self, x):x = self.model1(x)  # 将输入x依次传入网络return x  # 返回输出# 定义损失函数为交叉熵损失,用于分类任务
loss = nn.CrossEntropyLoss()# 实例化神经网络模型
tudui = Tudui()# 定义优化器,使用随机梯度下降(SGD),学习率设为0.01
optim = torch.optim.SGD(tudui.parameters(), lr=0.005)#经常会出现nan 和loss变化为0的情况,这时候就得要调参了。感觉0.01,0.001,0.1,都不太好,神经网络经常发神经# 定义学习率调度器,优化器,使用StepLR,每5个epoch将学习率乘以0.1
scheduler = StepLR(optim, step_size=5, gamma=0.1)# 训练过程,设定20个epoch
for epoch in range(20):running_loss = 0.0  # 初始化每个epoch的累计损失,每次计算都要loss清零for data in dataloader:  # 遍历每一批数据imgs, targets = data  # imgs是输入图像,targets是对应的标签outputs = tudui(imgs)  # 将图像输入网络,得到预测输出result_loss = loss(outputs, targets)  # 计算损失optim.zero_grad()  # 优化器梯度清零,防止累加result_loss.backward()  # 反向传播,计算梯度optim.step()  # 小土堆源码没有,注意 更新权重running_loss += result_loss.item()  # 累加损失值scheduler.step()  # 那小土堆的改到epoch的代码,更新学习率print(running_loss)  # 打印每个epoch的累计损失

运行结果也还行

Files already downloaded and verified
18864.705932210665
15439.860634332174
13744.55594523397
12428.718186999993
11342.776699185897
7056.810089337026
5552.8082057812735
4661.32626584378
3898.5063211931256
3208.6409183643354
2436.161548842425
2299.006631286251
2211.327144692005
2136.3464579411434
2067.7032547439658
1984.4474980983596
1975.8219145699131
1968.4251595352762
1961.4812723635232
1954.759079959732

感觉后面学习有点吃力,就把gamma值改成0.5,确实感觉效果更好。调参技能get点

Files already downloaded and verified
18972.406568901613
15460.233340543578
13756.254361514979
12417.585550802492
11310.643081888893
7457.094932298466
5994.618627047323
5507.483447367285
5794.649616663532
4877.494456583252
2490.7070572731336
955.5687210418287
371.26659479515604
169.87884318090371
72.07394882918663
42.53886234954232
33.56396412941994
28.734524085854517
25.233990153099555
22.519621285593622

好奇0.3会不会更好点,果然还是差点,前面速度还不错,后面效果有点拉跨。

Files already downloaded and verified
18824.60679809982
15556.305155576905
13735.934430592446
12342.659838442378
11285.891235672563
6900.019034815649
5026.226464926721
3598.409451258059
2544.912955761785
2417.9225108390256
1447.369545274334
549.7065285773949
312.4407196212337
210.27363093647688
156.48747144329707
126.68451174328214
117.18196939325574
109.68678552139573
103.18362671615421
97.42433589926554

模型的保存与加载

# 导入 PyTorch 和 torchvision 库
import torch
import torchvision
from torch import nn# 加载 VGG16 模型结构,设置 pretrained=False 表示不使用预训练权重
vgg16 = torchvision.models.vgg16(pretrained=False)# 保存方式1: 保存整个模型(包括结构和参数)这种方法简单,但在加载时需要使用相同的代码来重新定义模型结构。
torch.save(vgg16, "vgg16_method1.pth")# 保存方式2: 只保存模型的参数(推荐使用此方法),参数保存成字典形式,,空间更小这是官方推荐的方式,因为它更灵活且易于管理。
torch.save(vgg16.state_dict(), "vgg16_method2.pth")# 定义一个简单的自定义模型类 Tudui
class Tudui(nn.Module):def __init__(self):# 调用父类的构造函数super(Tudui, self).__init__()# 定义一个卷积层,输入通道数为 3,输出通道数为 64,卷积核大小为 3self.conv1 = nn.Conv2d(3, 64, kernel_size=3)def forward(self, x):# 在前向传播中应用卷积层x = self.conv1(x)return x# 实例化 Tudui 模型
tudui = Tudui()# 保存方式1: 保存整个自定义模型(包括结构和参数)
torch.save(tudui, "tudui_method1.pth")
model=torch.load('tudui_method1.pth')
print(model)

虽然保存整个模型方便,但在模型结构发生变化时会导致加载失败。使用 state_dict 保存参数是更为推荐的做法,因为它只保存模型的参数,不依赖于模型的代码结构。

模型的完整训练

with 是 Python 中的一个关键字,用于简化资源管理和异常处理。
进入 with 块时,torch.no_grad() 会自动调用其 enter 方法,禁用梯度计算;当退出块时,会调用 exit 方法,恢复梯度计算状态。在模型推理阶段(例如,验证或测试模型时),通常不需要计算梯度,因为不需要进行反向传播。禁用梯度计算可以提高推理的效率,减少内存占用。
示例 1:文件操作
使用 with 语句打开文件,可以确保在处理完文件后自动关闭文件,而不需要显式调用 close() 方法。
不使用GPU,大概是10分钟,使用GPU,速度加快

import torchvision  # 用于数据集和图像处理
from torch.utils.tensorboard import SummaryWriter  # 用于可视化训练过程。*:这个符号表示导入该模块中的所有公开对象(例如类、函数、变量等)。这意味着,你可以直接使用 model.py 中定义的任何内容,而无需指定模块名。
from torch import nn  # 导入 PyTorch 的神经网络模块
import torchfrom torch.utils.data import DataLoader  # 导入数据加载器
import time
train_data = torchvision.datasets.CIFAR10(root="../data", train=True, transform=torchvision.transforms.ToTensor(),  # 将图像转换为 Tensordownload=True  # 如果数据集未下载,则自动下载
)
test_data = torchvision.datasets.CIFAR10(root="../data", train=False, transform=torchvision.transforms.ToTensor(),  # 将图像转换为 Tensordownload=True  # 如果数据集未下载,则自动下载
)# 获取数据集长度,图片张数
train_data_size = len(train_data)  # 训练数据集的大小
test_data_size = len(test_data)  # 测试数据集的大小# 打印数据集长度
print("训练数据集的长度为:{}".format(train_data_size))#将大括号内的内容替换为train_data_size
print("测试数据集的长度为:{}".format(test_data_size))
# 利用 DataLoader 加载数据集,设置批大小为 64
train_dataloader = DataLoader(train_data, batch_size=64, shuffle=True)  # 随机打乱训练数据
test_dataloader = DataLoader(test_data, batch_size=64, shuffle=False)  # 测试数据一般不打乱
# 定义一个名为 Tudui 的类,继承自 nn.Module
class Tudui(nn.Module):def __init__(self):# 初始化父类 nn.Modulesuper(Tudui, self).__init__()# 定义一个顺序模型,包含多个层self.model = nn.Sequential(# 第一个卷积层:接收 3 通道的输入(RGB图像),输出 32 通道,卷积核大小为 5,步长为 1,填充为 2nn.Conv2d(3, 32, 5, 1, 2),# 第一个最大池化层:池化窗口大小为 2,减小特征图的尺寸nn.MaxPool2d(2),# 第二个卷积层:接收 32 通道的输入,输出 32 通道,卷积核大小为 5,步长为 1,填充为 2nn.Conv2d(32, 32, 5, 1, 2),# 第二个最大池化层nn.MaxPool2d(2),# 第三个卷积层:接收 32 通道的输入,输出 64 通道,卷积核大小为 5,步长为 1,填充为 2nn.Conv2d(32, 64, 5, 1, 2),# 第三个最大池化层nn.MaxPool2d(2),# 将多维输入展平为一维,以便输入全连接层nn.Flatten(),# 第一个全连接层:输入为展平后的特征,输出 64 个特征nn.Linear(64 * 4 * 4, 64),# 第二个全连接层:输出 10 个特征(适用于10类分类任务,如CIFAR-10)nn.Linear(64, 10))# 定义前向传播的方法def forward(self, x):# 将输入 x 传递通过模型,得到输出x = self.model(x)# 返回输出return x# 主程序入口
if __name__ == '__main__':# 实例化自定义模型 Tuduitudui = Tudui()# 创建一个输入张量,大小为 (64, 3, 32, 32)# 这里表示 64 张 RGB 图像,每张图像的尺寸为 32x32 像素input = torch.ones((64, 3, 32, 32))# 将输入张量传递给模型,得到输出output = tudui(input)# 打印输出的形状,应该是 (64, 10),表示每张输入图像对应 10 个类的预测print(output.shape)  # 输出形状应为 torch.Size([64, 10])
# 创建网络模型
tudui = Tudui()  # 实例化自定义模型 Tudui
tudui=tudui.cuda()
# 定义损失函数,使用交叉熵损失
loss_fn = nn.CrossEntropyLoss()
loss_fn=loss_fn.cuda()# 定义优化器,使用 SGD 优化器,学习率设置为 0.01
learning_rate = 1e-2
optimizer = torch.optim.SGD(tudui.parameters(), lr=learning_rate)# 设置训练网络的一些参数
total_train_step = 0  # 记录训练的次数
total_test_step = 0  # 记录测试的次数
epoch = 20  # 训练的轮数
start_time=time.time()
# 添加 TensorBoard 记录器
writer = SummaryWriter("../logs_train")  # 指定日志目录# 训练过程
for i in range(epoch):  # 遍历每一个训练轮次print("-------第 {} 轮训练开始-------".format(i + 1))# 训练步骤开始tudui.train()  # 设置模型为训练模式,启用 Dropout 和 BatchNormfor data in train_dataloader:  # 遍历训练数据imgs, targets = data  # 拆分输入图像和目标标签imgs=imgs.cuda()targets=targets.cuda()outputs = tudui(imgs)  # 前向传播,获取模型输出loss = loss_fn(outputs, targets)  # 计算损失# 优化器优化模型optimizer.zero_grad()  # 清空梯度loss.backward()  # 反向传播,计算梯度optimizer.step()  # 更新模型参数total_train_step += 1  # 增加训练次数计数if total_train_step % 100 == 0:  # 每 100 次训练打印一次损失end_time=time.time()print(end_time-start_time)print("训练次数:{}, Loss: {}".format(total_train_step, loss.item()))  # 打印当前训练步数和损失值writer.add_scalar("train_loss", loss.item(), total_train_step)  # 记录训练损失到 TensorBoard# 测试步骤开始tudui.eval()  # 设置模型为评估模式,禁用 Dropout 和 BatchNormtotal_test_loss = 0  # 初始化测试损失total_accuracy = 0  # 初始化正确率计数with torch.no_grad():  # 禁用梯度计算,减少内存使用for data in test_dataloader:  # 遍历测试数据imgs, targets = data  # 拆分输入图像和目标标签imgs=imgs.cuda()targets=targets.cuda()outputs = tudui(imgs)  # 前向传播,获取模型输出loss = loss_fn(outputs, targets)  # 计算损失total_test_loss += loss.item()  # 累加测试损失accuracy = (outputs.argmax(1) == targets).sum()  # 计算正确预测的数量total_accuracy += accuracy.item()  # 累加正确预测数量# 打印测试结果print("整体测试集上的Loss: {}".format(total_test_loss))  # 打印测试损失print("整体测试集上的正确率: {}".format(total_accuracy / test_data_size))  # 计算并打印准确率writer.add_scalar("test_loss", total_test_loss, total_test_step)  # 记录测试损失writer.add_scalar("test_accuracy", total_accuracy / test_data_size, total_test_step)  # 记录测试准确率total_test_step += 1  # 增加测试次数计数# 保存模型torch.save(tudui, "tudui_{}.pth".format(i))  # 每个 epoch 保存一次模型print("模型已保存")writer.close()  # 关闭 TensorBoard 记录器

还是学到了很多,收获颇丰。建议学习机器学习,先学《深度学习入门》,再学小土堆。

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

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

相关文章

LabVIEW提高开发效率技巧----减少UI更新频率

在LabVIEW开发中,图形化用户界面(UI)的更新频率对程序的响应速度有着显著影响。频繁的UI更新会占用大量资源,导致系统性能下降。本文将详细介绍如何通过减少UI更新频率来提升LabVIEW程序的运行效率,从多个角度进行分析…

Jenkins入门(二):流水线方式部署多模块Springboot项目

目录 一、环境准备 1. 搭建配置Jenkins (在上一篇基础上进行) 2. 安装mysql 3. 安装redis 4. 配置docker-componse 5. 启动docker-componse 二、脚本准备 1. Jenkinsfile 2. deploy.sh 3. Dockerfile 三、Jenkins流水线配置 新增版本号参数 流水线选择代码里面的Je…

游戏逆向基础-找释放技能CALL

思路:通过send断点然后对send的data参数下写入断点找到游戏里面的技能或者攻击call 进入游戏先选好一个怪物(之所以要先选好是因为选怪也会断,如果直接左键打怪的话就会断几次) 断下来后对参数下硬件写入断点 硬件断点断下来后先…

Java | Leetcode Java题解之第475题供暖器

题目&#xff1a; 题解&#xff1a; class Solution {public int findRadius(int[] houses, int[] heaters) {Arrays.sort(houses);Arrays.sort(heaters);int ans 0;for (int i 0, j 0; i < houses.length; i) {int curDistance Math.abs(houses[i] - heaters[j]);whil…

【工具篇】MLU运行XInference部署手册

文章目录 前言一、平台环境准备二、代码下载三、安装部署1.正常pip 安装 四、运行结果展示1.如果界面404或没有东西请这样做2.运行效果 前言 Xorbits Inference&#xff08;Xinference&#xff09;是一个功能强大、用途广泛的库&#xff0c;旨在为语言、语音识别和多模态模型提…

Python | Leetcode Python题解之第478题在圆内随机生成点

题目&#xff1a; 题解&#xff1a; class Solution:def __init__(self, radius: float, x_center: float, y_center: float):self.xc x_centerself.yc y_centerself.r radiusdef randPoint(self) -> List[float]:u, theta random.random(), random.random() * 2 * mat…

js简单基础笔记

一 . js特点 1. Js是一门解释型语言&#xff0c;不用编译&#xff0c;而是直接执行 2. js是一门动态语言&#xff0c;其中的任何内容都是不确定的 3. 语法结构和Java&#xff0c;c都很像 4. ​ js是一门面向对象的语言 5.js严格区分大小写 二 . js使用 1…

【AI知识】距离度量和相似性度量的常见算法

本文介绍一些AI中常见的距离度量和相似性度量算法&#xff1a; 1. 欧几里得距离&#xff08;Euclidean Distance&#xff09; 欧几里得距离是最常见的距离度量方法&#xff0c;用来计算两个向量之间的“直线距离”&#xff0c;也被成为L2范数。 公式如下&#xff0c;其中 x…

6、ES6

文章目录 一.关于ES6二.关于变量声明let声明变量const 声明常量 三.变量的解构赋值四.字符串的扩展五.函数的扩展函数默认参数rest参数箭头函数(函数的新写法) 六.数组的扩展七.对象的扩展语法上的简化对象的解构赋值 八.Symbol&#xff1a;新的数据类型(类似于字符串)独一无二…

学习中,师傅b站泷羽sec——xss挖掘过程

某职业技术学院网站xss挖掘&#xff1a; 资产归纳 例如&#xff1a;先把功能点都看一遍&#xff0c;大部分都是文章 根据信息搜集第一课学习到一般主站的防御力是比较强的&#xff0c;出现漏洞的点不是对新手不友好。 在资产验证过程中还是把主站看了一遍 没有发现有攻击的机会…

未来人工智能的发展对就业市场的影响 人工智能在生活中的相关

人工智能&#xff08;Artificial Intelligence&#xff09;&#xff0c;英文缩写为AI.是新一轮科技革命和产业变革的重要驱动力量&#xff0c; 是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学. 人工智能的发展对就业市场的影响主要…

论文笔记:RelationPrompt :Zero-Shot Relation Triplet Extraction

论文来源: ACL Findings 2022 论文链接:https://arxiv.org/pdf/2203.09101.pdf 论文代码:http://github.com/declare-lab/RelationPrompt 本篇论文是由阿里达摩院自然语言智能实验室于2022年发表的关于零样本关系抽取的顶会论文,本篇博客将记录我在阅读过程中的一些笔记…

修改pq_default.ini禁用降噪,解决S905X3电视盒硬解视频画质模糊、严重涂抹得像油画、水彩画的问题

笔者使用一台处理器芯片为 S905X3 的电视盒将近一年&#xff0c;性能比之前的 RK3328 的盒子有所提升&#xff0c;但我对它视频解码方面感到越来越不爽&#xff0c;该盒子的硬解视频总是开启美颜降噪和锐化&#xff0c;导致硬解视频的画质模糊&#xff0c;细节都被磨平&#xf…

使用Jenkins部署项目

部署中的痛点 为什么要用Jenkins&#xff1f;我说下我以前开发的痛点&#xff0c;在一些中小型企业&#xff0c;每次开发一个项目完成后&#xff0c;需要打包部署&#xff0c;可能没有专门的运维人员&#xff0c;只能开发人员去把项目打成一个exe包&#xff0c;可能这个项目已…

OPENSSL-2023/11/10学习记录-C/C++对称分组加密DES

对称分组加密常用算法&#xff1a; DES 3DES AES 国密SM4 对称分组加密应用场景&#xff1a; 文件或者视频加密 加密比特币私钥 消息或者配置项加密 SSL通信加密 对称分组加密 使用异或实现一个简易的对称加密算法 A明文 B秘钥 AB密文AB (AB)B A 密码补全和初始化 数…

第六节——从深层剖析qsort的使用(让你不再害怕指针)

文章目录 1.什么是回调函数2.qsort的使用qsort排序整形数据qsort排序结构体数据qsort排序字符串数据 3.qsort的模拟实现 1.什么是回调函数 回调函数就是⼀个通过函数指针调用的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另⼀个函数&#xff0c;当…

Python画笔案例-087 绘制 旋转的文字

1、绘制 旋转的文字 通过 python 的turtle 库绘制 旋转的文字,如下图: 2、实现代码 绘制 旋转的文字,以下为实现代码: """旋转的文字.py """ import time from turtle import * from write_patch import *screen = Screen

【JPCS独立出版 | 福州大学主办 | 有确定的ISSN号】第三届可再生能源与电气科技国际学术会议(ICREET 2024)

第三届可再生能源与电气科技国际学术会议&#xff08;ICREET 2024&#xff09; 2024 3rd International Conference on Renewable Energy and Electrical Technology ICREET 2024已成功申请JPCS - Journal of Physics: Conference Series (ISSN:1742-6596) 独立出版&#xf…

架构设计笔记-16-嵌入式系统架构设计理论与实践

目录 知识要点 嵌入式微处理器 存储器&#xff08;memory&#xff09; 内&#xff08;外&#xff09;总线逻辑 嵌入式操作系统&#xff08;Embedded Operating System&#xff0c;EOS&#xff09; 通用中间件 嵌入式中间件的一般架构 典型嵌入式中间件系统 案例分析 1…

搭建mongodb单机部署-认证使用

搭建mongodb单机部署-认证使用 实现思路 先将配置文件配置好&#xff0c;使用不用认证的启动命令启动docker&#xff0c;然后创建账号并制定角色。在使用开启认证的命令重新启动容器就好。 这里我并没有说先停止容器&#xff0c;删掉容器重新创建容器。是因为我的启动命令中…