当前位置: 首页 > news >正文

详细介绍:传统神经网络实现-----手写数字识别(MNIST)项目

详细介绍:传统神经网络实现-----手写数字识别(MNIST)项目

完整代码:

# import torch
# print(torch.__version__)#1.X     1、验证安装的开发环境是否正确,
'''
MNIST包含70,000张手写数字图像: 60,000张用于训练,10,000张用于测试。
图像是灰度的,28x28像素的,并且居中的,以减少预处理和加快运行。
'''
import torch
from torch import nn    #导入神经网络模块,
from torch.utils.data import DataLoader #数据包管理工具,打包数据,
from torchvision import datasets #封装了很多与图像相关的模型,及数据集
from torchvision.transforms import ToTensor #数据转换,张量,将其他类型的数据转换为tensor张量,numpy array,dataframe
'''下载训练数据集(包含训练图片+标签)'''
training_data = datasets.MNIST( #跳转到函数的内部源代码,pycharm 按下ctrl +鼠标点击
root="data",#表示下载的手写数字 到哪个路径。60000
train=True,#读取下载后的数据 中的 训练集
download=True,#如果你之前已经下载过了,就不用再下载
transform=ToTensor(),   #张量,图片是不能直接传入神经网络模型
)   #对于pytorch库能够识别的数据一般是tensor张量.
print(len(training_data))
# datasets.MNIST的参数:
#   root(string): 表示数据集的根目录,
#   train(bool, optional): 如果为True,则从training.pt创建数据集,否则从test.pt创建数据集
#   download(bool, optional): 如果为True,则从internet下载数据集并将其放入根目录。如果数据集已下载,则不会再次下载
#   transform(callable, optional): 接收PIL图片并返回转换后版本图片的转换函数
'''下载测试数据集(包含训练图片+标签) '''
test_data = datasets.MNIST(
root="data",
train=False,
download=True,
transform=ToTensor(),#Tensor是在深度学习中提出并广泛应用的数据类型,它与深度学习框架(如 PyTorch、TensorFlow)紧密集成,方便进行神经网络的训练和推理。
)#NumPy 数组只能在CPU上运行。Tensor可以在GPU上运行,这在深度学习应用中可以显著提高计算速度。
print(len(test_data))
# '''展示手写字图片,把训练数据集中的前59000张图片展示一下'''
# from matplotlib import pyplot as plt
# figure = plt.figure()
# for i in range(9):#
#     img, label = training_data[i+59000]#提取第59000张图片
#
#     figure.add_subplot(3, 3, i+1)#图像窗口中创建多个小窗口,小窗口用于显示图片
#     plt.title(label)
#     plt.axis("off")  # plt.show(I)#显示矢量,
#     plt.imshow(img.squeeze(), cmap="gray")  #plt.imshow()将NumPy数组data中的数据显示为图像,并在图形窗口中显示该图像
#     a = img.squeeze() # img.squeeze()从张量img中去掉维度为1的。如果该维度的大小不为1则张量不会改变。#cmap="gray"表示使用灰度色彩映射来显示图像。这意味着图像将以灰度模式显示
# plt.show()
'''创建数据DataLoader(数据加载器)
batch_size:将数据集分成多份,每一份为batch_size个数据。
优点:可以减少内存的使用,提高训练速度。
'''
train_dataloader = DataLoader(training_data, batch_size=64)#64张图片为一个包,1、损失函数2、GPU一次性接受的图片个数
test_dataloader = DataLoader(test_data, batch_size=64)
for X, y in test_dataloader:#X是表示打包好的每一个数据包
print(f"Shape of X [N, C, H, W]: {X.shape}")#
print(f"Shape of y: {y.shape} {y.dtype}")
break
'''判断当前设备是否支持GPU,其中mps是苹果m系列芯片的GPU。'''#返回cuda,mps。CPU   m1 ,m2  集显CPU+GPU  RTX3060,
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
print(f"Using {device} device")#字符串的格式化。  CUDA驱动软件的功能:pytorch能够去执行cuda的命令,cuda通过GPU指令集去控制GPU
#神经网络的模型也需要传入到GPU,1个batchsize的数据集也需要传入到GPU,才可以进行训练。
''' 定义神经网络  类的继承这种方式'''
class NeuralNetwork(nn.Module):#通过调用类的形式来使用神经网络,神经网络的模型,nn.module
def __init__(self):#python基础关于类,self类自己本身
super().__init__()#继承的父类初始化
self.flatten = nn.Flatten()#展开,创建一个展开对象flatten
self.hidden1 = nn.Linear(28*28, 128)#第1个参数:有多少个神经元传入进来,第2个参数:有多少个数据传出去前一层神经元的个数,当前本层神经元个数
self.hidden2 = nn.Linear(128, 256)#为什么你要用128
self.out = nn.Linear(256, 10)#输出必需和标签的类别相同,输入必须是上一层的神经元个数
def forward(self, x):   #前向传播,你得告诉它  数据的流向。是神经网络层连接起来,函数名称不能改。当你调用forward函数的时候,传入进来的图像数据
x = self.flatten.forward(x)     #图像进行展开  self.flatten.forward
x = self.hidden1.forward(x)
x = torch.relu(x) #激活函数,torch使用的relu函数 relu,tanh
x = self.hidden2.forward(x)
x = torch.relu(x)
x = self.out.forward(x)
return x
model = NeuralNetwork().to(device)#把刚刚创建的模型传入到Gpu
print(model)
def train(dataloader, model, loss_fn, optimizer):
model.train()#告诉模型,我要开始训练,模型中w进行随机化操作,已经更新w。在训练过程中,w会被修改的
#pytorch提供2种方式来切换训练和测试的模式,分别是:model.train() 和 model.eval()。
# 一般用法是:在训练开始之前写上model.trian(),在测试时写上 model.eval() 。
batch_size_num = 1  #统计 训练的batch数量
for X, y in dataloader:                 #其中batch为每一个数据的编号
X, y = X.to(device), y.to(device)   #把训练数据集和标签传入cpu或GPU
pred = model(X)             #.forward可以被省略,父类中已经对此功能进行了设置。自动初始化 w权值
loss = loss_fn(pred, y)             #通过交叉熵损失函数计算损失值loss
# Backpropagation 进来一个batch的数据,计算一次梯度,更新一次网络
optimizer.zero_grad()               #梯度值清零
loss.backward()                     #反向传播计算得到每个参数的梯度值w
optimizer.step()                    #根据梯度更新网络w参数
loss_value = loss.item()                  #从tensor数据中提取数据出来,tensor获取损失值
if batch_size_num %100  ==0:
print(f"loss: {loss_value:>7f}  [number:{batch_size_num}]")
batch_size_num += 1
def test(dataloader, model, loss_fn):
size = len(dataloader.dataset)#10000
num_batches = len(dataloader)#打包的数量
model.eval()    #测试,w就不能再更新。
test_loss, correct = 0, 0   #
with torch.no_grad():   #一个上下文管理器,关闭梯度计算。当你确认不会调用Tensor.backward()的时候。这可以减少计算所用内存消耗。
for X, y in dataloader:
X, y = X.to(device), y.to(device)  #送到GPU
pred = model.forward(X)
test_loss += loss_fn(pred, y).item() #test_loss是会自动累加每一个批次的损失值
correct += (pred.argmax(1) == y).type(torch.float).sum().item()
a = (pred.argmax(1) == y)  #dim=1表示每一行中的最大值对应的索引号,dim=0表示每一列中的最大值对应的索引号
b = (pred.argmax(1) == y).type(torch.float)
test_loss /= num_batches  #能来衡量模型测试的好坏。
correct /= size  #平均的正确率
print(f"Test result: \n Accuracy: {(100*correct)}%, Avg loss: {test_loss}")
loss_fn = nn.CrossEntropyLoss() #创建交叉熵损失函数对象,因为手写字识别中一共有10个数字,输出会有10个结果
# L1Loss:L1损失,也称为平均绝对误差(Mean Absolute Error, MAE)。它计算预测值与真实值之间的绝对差值的平均值。
# NLLLoss:负对数似然损失(Negative Log Likelihood Loss)。它用于多分类问题,通常与LogSoftmax输出层配合使用。
# NLLLoss2d:这是NLLLoss的一个特殊版本,用于处理2D图像数据。在最新版本的PyTorch中,这个损失函数可能已经被整合到NLLLoss中,通过指定reduction参数来实现同样的功能。
# PoissonNLLLoss:泊松负对数似然损失,用于泊松回归问题。
# GaussianNLLLoss:高斯负对数似然损失,用于高斯分布(正态分布)的回归问题。
# KLDivLoss:Kullback-Leibler散度损失,用于度量两个概率分布之间的差异。
# MSELoss:均方误差损失(Mean Squared Error Loss),计算预测值与真实值之间差值的平方的平均值。
# BCELoss:二元交叉熵损失(Binary Cross Entropy Loss),用于二分类问题。
# BCEWithLogitsLoss:结合了Sigmoid激活函数和二元交叉熵损失的损失函数,用于提高数值稳定性。
# HingeEmbeddingLoss:铰链嵌入损失,用于学习非线性嵌入或半监督学习。
# MultiLabelMarginLoss:多标签边际损失,用于多标签分类问题。
# SmoothL1Loss:平滑L1损失,是L1损失和L2损失(MSE)的结合,旨在避免梯度爆炸问题。
# HuberLoss:Huber损失,与SmoothL1Loss类似,但有一个可调的参数来控制L1和L2损失之间的平衡。
# SoftMarginLoss:软边际损失,用于二分类问题,可以看作是Hinge损失的一种软化版本。
# CrossEntropyLoss:交叉熵损失,用于多分类问题。它结合了LogSoftmax和NLLLoss的功能。
# MultiLabelSoftMarginLoss:多标签软边际损失,用于多标签二分类问题。
# CosineEmbeddingLoss:余弦嵌入损失,用于学习非线性嵌入,通过余弦相似度来度量样本之间的相似性。
# MarginRankingLoss:边际排序损失,用于排序问题,如学习到排序的嵌入空间。
# MultiMarginLoss:多边际损失,用于多分类问题,旨在优化分类边界的边际。
# TripletMarginLoss:三元组边际损失,用于学习嵌入空间中的距离度量,通常用于人脸识别或图像检索等任务。
# TripletMarginWithDistanceLoss:这是TripletMarginLoss的一个变体,允许使用自定义的距离函数。
# CTCLoss:连接时序分类损失(Connectionist Temporal Classification Loss),用于序列到序列的学习问题,特别是当输出序列的长度不固定时(如语音识别)。
#一会改成adam优化器   梯度下降
optimizer = torch.optim.Adam(model.parameters(), lr=0.005)#创建一个优化器,SGD为随机梯度下降算法
# #params:要训练的参数,一般我们传入的都是model.parameters()。
# #lr:learning_rate学习率,也就是步长。
#loss表示模型训练后的输出结果与 样本标签的差距。如果差距越小,就表示模型训练越好,越逼近于真实的模型。
# train(train_dataloader, model, loss_fn, optimizer)#训练1次完整的数据,多轮训练,
# test(test_dataloader, model, loss_fn)
epochs = 10 #到底选择多少呢?
for t in range(epochs):
print(f"Epoch {t+1}\n-------------------------------")
train(train_dataloader, model, loss_fn, optimizer)#10次训练
print("Done!")
test(test_dataloader, model, loss_fn)
# # #分析sigmiod,relu
# # # sgd,Adam

按代码模块进行解析:

第一部分:环境验证与数据加载
# import torch
# print(torch.__version__)#1.X     1、验证安装的开发环境是否正确,
  • 注释掉了,用于检查 PyTorch 是否安装成功。


import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor

  • 导入 PyTorch 核心库及相关模块:

    • nn:构建神经网络。

    • DataLoader:批量加载数据。

    • datasets:内置数据集(如 MNIST)。

    • ToTensor:将图片转为 Tensor 格式。


training_data = datasets.MNIST(
root="data",
train=True,
download=True,
transform=ToTensor(),
)

  • 下载 训练集(60,000 张图):

    • root="data":保存到本地 data/ 文件夹。

    • transform=ToTensor():将图片转为 Tensor(灰度值归一化到 [0, 1])。


test_data = datasets.MNIST(
root="data",
train=False,
download=True,
transform=ToTensor(),
)

  • 下载 测试集(10,000 张图)。


train_dataloader = DataLoader(training_data, batch_size=64)
test_dataloader = DataLoader(test_data, batch_size=64)

  • 使用 DataLoader 将数据打包成 批次(每批 64 张图),方便训练。


第二部分:设备选择与模型定义

device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"

  • 自动选择设备:

    • 优先使用 NVIDIA GPU(cuda);

    • 其次 Apple 芯片(mps);

    • 最后回退到 CPU。


class NeuralNetwork(nn.Module):
def __init__(self):
super().__init__()
self.flatten = nn.Flatten()
self.hidden1 = nn.Linear(28*28, 128)
self.hidden2 = nn.Linear(128, 256)
self.out = nn.Linear(256, 10)
def forward(self, x):
x = self.flatten(x)
x = torch.relu(self.hidden1(x))
x = torch.relu(self.hidden2(x))
x = self.out(x)
return x

  • 定义一个 三层全连接神经网络

    • 输入层:28×28 = 784 像素;

    • 隐藏层1:128 个神经元;

    • 隐藏层2:256 个神经元;

    • 输出层:10 个类别(0~9 数字);

    • 激活函数:ReLU。


model = NeuralNetwork().to(device)

  • 将模型迁移到 GPU(或 CPU)。


第三部分:训练与测试函数

def train(dataloader, model, loss_fn, optimizer):
model.train()
for batch, (X, y) in enumerate(dataloader):
X, y = X.to(device), y.to(device)
pred = model(X)
loss = loss_fn(pred, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if batch % 100 == 0:
print(f"loss: {loss.item():.7f} [batch {batch}]")

  • 训练函数

    • 每个批次前向传播 → 计算损失 → 反向传播 → 更新权重;

    • 每 100 个批次打印一次损失值。


def test(dataloader, model, loss_fn):
model.eval()
test_loss, correct = 0, 0
with torch.no_grad():
for X, y in dataloader:
X, y = X.to(device), y.to(device)
pred = model(X)
test_loss += loss_fn(pred, y).item()
correct += (pred.argmax(1) == y).type(torch.float).sum().item()
test_loss /= len(dataloader)
correct /= len(dataloader.dataset)
print(f"Test Accuracy: {100*correct:.2f}%, Avg loss: {test_loss:.4f}")

  • 测试函数

    • 不更新权重(model.eval());

    • 计算整体损失与准确率。


第四部分:损失函数与优化器

loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.005)

  • 使用 交叉熵损失(适合多分类);

  • 使用 Adam 优化器(比 SGD 更稳定)。


第五部分:训练循环

epochs = 10
for t in range(epochs):
print(f"Epoch {t+1}\n-------------------------------")
train(train_dataloader, model, loss_fn, optimizer)
print("Done!")
test(test_dataloader, model, loss_fn)

  • 训练 10 轮

  • 每轮遍历一次完整训练集;

  • 最后测试模型性能。

代码模块具体逐行逐句解释:

class NeuralNetwork(nn.Module):
def __init__(self):
super().__init__()
self.flatten = nn.Flatten()
self.hidden1 = nn.Linear(28*28, 128)
self.hidden2 = nn.Linear(128, 256)
self.out = nn.Linear(256, 10)
def forward(self, x):
x = self.flatten(x)
x = torch.relu(self.hidden1(x))
x = torch.relu(self.hidden2(x))
x = self.out(x)
return x
第一部分:类定义与初始化 (__init__ 方法)

class NeuralNetwork(nn.Module):

作用:声明一个继承自 PyTorch 基类 nn.Module 的新类
含义:所有自定义神经网络必须继承此类才能享受 PyTorch 的训练/推理功能(如 model.train(), model.eval()

super().__init__()

作用:调用父类 nn.Module 的构造函数
重要性:初始化模块的必要内部结构(如参数注册器),不可省略

self.flatten = nn.Flatten()

作用:创建一个展平层对象
功能详解:将多维输入(如图像 [B, H, W])压缩为一维向量 [B, H×W]
典型场景:连接卷积层和非全连接层时的过渡操作

self.hidden1 = nn.Linear(28*28, 128)

作用:定义第一个全连接层(又称密集层)
参数解析

  • in_features=28*28=784:输入特征数(对应 28×28 图像的像素总数)

  • out_features=128:本层神经元数量
    内部机制:自动创建权重矩阵 W₁ (形状 784×128) 和偏置向量 b₁ (长度 128)

self.hidden2 = nn.Linear(128, 256)

作用:定义第二个全连接层
参数解析

  • in_features=128:前一层的输出特征数

  • out_features=256:本层神经元数量
    内部机制:自动创建权重矩阵 W₂ (形状 128×256) 和偏置向量 b₂ (长度 256)

self.out = nn.Linear(256, 10)

作用:定义输出层
特殊设计

  • out_features=10:对应分类任务的类别数(如 MNIST 手写数字识别)

  • 输出未经过激活函数(直接输出 logits),配合交叉熵损失函数使用


第二部分:前向传播 (forward 方法)

def forward(self, x):

作用:定义数据的前向传播路径
关键性质:每次调用 model(input) 时会自动执行此方法

x = self.flatten(x)

作用:展平输入张量
示例

  • 输入形状 [batch_size, 28, 28] → 输出形状 [batch_size, 784]
    必要性:全连接层只能接受一维特征向量

x = torch.relu(self.hidden1(x))

作用:通过第一隐藏层并进行 ReLU 激活
计算过程

  1. 线性变换:x = W₁·x + b₁

  2. ReLU 激活:x[x<0]=0(保留正值,引入非线性)
    设计理由:解决线性模型无法拟合复杂模式的问题

x = torch.relu(self.hidden2(x))

作用:通过第二隐藏层并进行 ReLU 激活
计算过程

  1. 线性变换:x = W₂·x + b₂

  2. ReLU 激活:同上
    效果:进一步提取高阶特征,增加模型表达能力

x = self.out(x)

作用:通过输出层生成最终结果
注意:此处不添加激活函数
原因:分类任务通常在损失函数中结合 LogSoftmax(如 CrossEntropyLoss),logits 更灵活可控

return x

作用:返回模型输出
输出形式:原始 logits(未归一化的概率分数)
后续处理:通常会接入软最大值函数(Softmax)进行概率转换,或直接用于计算损失

def train(dataloader, model, loss_fn, optimizer):
model.train()
for batch, (X, y) in enumerate(dataloader):
X, y = X.to(device), y.to(device)
pred = model(X)
loss = loss_fn(pred, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if batch % 100 == 0:
print(f"loss: {loss.item():.7f} [batch {batch}]")

第1行:model.train()

功能:将模型设置为 训练模式
底层逻辑

  • 激活模型中所有适用于训练的特殊组件。

    • 示例nn.Dropout(p=0.5) 在训练时会随机屏蔽50%的神经元,而在推理模式(model.eval())下无效。

  • 确保模型处于可学习状态(参数注册钩子启用)。
    关键性:若省略此步,模型可能因未启用必要层(如 Dropout)导致性能下降或错误。


第2行:for batch, (X, y) in enumerate(dataloader):

功能:遍历数据集的一个完整周期(Epoch)
参数解析

  • dataloader:PyTorch 的 DataLoader 对象,负责按批次加载数据。

  • enumerate():同时获取当前批次的索引 batch 和数据 (X, y)
    典型输出

    • X: 输入特征张量,形状为 [batch_size × input_dim](如图像数据为 [B, C, H, W])。

    • y: 目标标签张量,形状为 [batch_size × output_dim](分类任务通常为 one-hot 编码或类别索引)。
      设计目的:通过迭代实现 mini-batch SGD(随机梯度下降),逐步优化模型参数。


第3-4行:X, y = X.to(device), y.to(device)

功能:将数据迁移到指定计算设备(CPU/GPU)
底层逻辑

  • device 通常是预定义的变量(如 torch.device('cuda')),表示可用的硬件资源。

  • .to(device) 方法执行以下操作:

    • 数据搬运:将张量从 CPU 内存复制到 GPU 显存(若 device='cuda')。

    • 类型匹配:自动转换数据类型以匹配模型参数的类型(如 float32)。
      重要性:确保模型与数据在同一设备上运算,否则会抛出 RuntimeError: ... not on the same device
      注意:此操作仅影响张量的存储位置,不改变其数值内容。


第5行:pred = model(X)

功能:执行前向传播(Forward Propagation)
计算流程

  1. 输入 X 经模型各层依次变换(如线性层、激活函数、归一化层等)。

  2. 输出 pred 是模型对输入 X 的原始预测值(Logits),尚未应用任何激活函数。
    维度示例

  • 输入形状:[batch_size, input_dim] → 输出形状:[batch_size, num_classes](分类任务)。
    注意:此处保持线性输出,供损失函数后续处理。


第6行:loss = loss_fn(pred, y)

功能:计算当前批次的损失值
核心机制

  • loss_fn 是预定义的损失函数(如 nn.CrossEntropyLoss()nn.MSELoss())。

  • 对比模型输出 pred 与真实标签 y,量化预测误差。
    数学本质

    • 分类任务:交叉熵损失 L = -Σ(y * log(softmax(pred)))

    • 回归任务:均方误差 L = ||pred - y||²_2
      作用:为反向传播提供优化目标,指导参数更新方向。


第7行:optimizer.zero_grad()

功能:清空优化器的梯度缓存
底层逻辑

  • PyTorch 采用 累积梯度 策略,每次调用 loss.backward() 会将新梯度累加到现有梯度上。

  • 此操作将所有可训练参数的梯度置零,防止跨批次梯度混合。
    必要性:若不执行此步,梯度会指数级增长,导致参数更新异常剧烈(如爆炸性梯度)。
    内部实现:遍历模型的所有可训练参数,执行 param.grad = None


第8行:loss.backward()

功能:执行反向传播(Backward Propagation)
计算流程

  1. 根据链式法则自动计算损失对每个参数的梯度。

  2. 梯度存储在 param.grad 属性中(仅存在于 requires_grad=True 的参数)。
    技术核心:利用自动微分系统高效计算复杂计算图的梯度。
    注意:此操作 不会立即更新参数,仅计算梯度。


第9行:optimizer.step()

功能:根据梯度更新模型参数
执行过程

  1. 优化器(如 SGD、Adam)按照预设规则(学习率、动量等)更新参数。

    • SGD 示例param = param - lr * param.grad

  2. 完成一次参数更新后,梯度会被自动清零(部分优化器除外)。
    效果:使模型向损失降低的方向调整参数。
    注意:此操作是参数更新的唯一入口,必须在 zero_grad() 之后调用。


第10-11行:if batch % 100 == 0: print(f"loss: {loss.item():.7f} [batch {batch}]")

功能:定期打印训练进度
实现细节

  • batch % 100 == 0:每处理 100 个批次打印一次日志。

  • loss.item():将张量转换为 Python 标量(浮点数),用于格式化输出。
    输出示例loss: 0.1234567 [batch 100]
    用途:监控训练稳定性,辅助调试(如发现 NaN 或爆炸性损失)。

相关文章:

详细介绍:传统神经网络实现-----手写数字识别(MNIST)项目

详细介绍:传统神经网络实现-----手写数字识别(MNIST)项目pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New",…...

C#语言中使用using关键字

在 C# 语言中,“using”关键字被用于不同的上下文和目的,它的用法大体上可以被分为三类:导入命名空间、简化资源管理和提供别名。 首先,"using"关键字最常见的用途是导入命名空间。这在 C# 程序中非常普遍,因为它可以允许程序员引用命名空间中定义的类型,而不需…...

中育新版本OSS Token获取API分析

中育新版本OSS Token获取API分析 在8/28更新中(或更早),中育彻底停用了旧版本的GenerateTokenAsyncAPI,转而使用GenerateTokenV2AsyncAPI,新的API使用了签名和一些不明所以的参数,并可能限制了可以上传的路径。 为了尽快迁移旧的工具、程序,我对web端的OSS逻辑进行了分析。…...

25/9/12(补,上一篇是9/11的)

把昨天没改完的码积木改完了,最终解法先发现一个性质是往上堆一个就算和下一个高度重叠也对下一个没有影响,所升序排完后设变量m(m初始等于a[1]),如果m比当前遍历到的a[i]大代表这个a[i]有重叠,更新答案,如果比a[i]小就让m=a[i]保持同频。 改完这题后又去改暑假的T3,就是…...

动态编译 vs. 静态编译,容器时代那个更有优势?

动态编译 vs. 静态编译,容器时代那个更有优势?一、动态编译 vs. 静态编译:一场关于“依赖”的战争 要理解静态编译,我们首先要明白它的对立面——动态编译,这也是 C、C++ 以及 Java、Python、C#、Ruby 等大多数主流语言所采用的方式。 1. 动态编译:运行时“借”东西 想象…...

实用指南:操作系统类型全解析:从批处理到嵌入式

实用指南:操作系统类型全解析:从批处理到嵌入式pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace…...

【C++ 类和对象・高阶深化(下)】再探构造函数(含初始化列表),吃透 static 成员、友元、内部类及对象拷贝编译器优化 - 指南

【C++ 类和对象・高阶深化(下)】再探构造函数(含初始化列表),吃透 static 成员、友元、内部类及对象拷贝编译器优化 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &qu…...

2

C++ 数据结构数组 链表 队列 堆 树 map/set hashmysql 索引 索引就像是数据的目录。索引的好处就是可以提高查询速度,但是会占用物理空间,而且创建和维护索引要耗费时间,每次进行增删改操作都需要动态维护。索引的分类数据结构:B+ 树索引,hash,full-text物理存储:聚簇索…...

VSCode 运行 C/C++ 程序

VSCode 安装插件:重点参考: https://blog.csdn.net/icacxygh001/article/details/120981354 https://code.visualstudio.com/docs/cpp/config-linux#_running-the-build...

3 字节

进程与线程的区别 线程是轻量级进程,每个进程中都有唯一的主线程,主线程和进程是相互依存的关系。进程是资源分配和拥有的基本单位;线程是系统调度的基本单位进程拥有CPU 资源,内存资源,文件资源,句柄等;线程拥有程序计数器,寄存器,栈和状态字切换情况:进程由操作系统…...

Springcloud Alibaba(一)

一、什么是Springcloud Alibaba它是微服务概念的一种实现,解决了如下问题N个服务,如何管理?(服务治理 注册中心【服务的注册、发现、删除】)nacos N个服务,如何通信?feign N个服务,客户端如何访问?gateway N个服务,一旦出现问题了,怎么处理?(容错)sentinel N个服…...

111111111

1111111111...

202204_DASCTF_SimpleFlow

流量分析,DASCTF,WebShell,蚁剑AntSwordTags:流量分析,DASCTF,WebShell,蚁剑AntSword 0x00. 题目 附件路径:https://pan.baidu.com/s/1GyH7kitkMYywGC9YJeQLJA?pwd=Zmxh#list/path=/CTF附件 附件名称:202204_DASCTF_SimpleFlow.zip 0x01. WP 1. 分析http协议,找到附件数据 …...

使用 Winscope 跟踪窗口转换

Winscope 是一款 Web 工具,可以让用户在动画和转换期间和之后记录、重放和分析多个系统服务的状态。Winscope 将所有相关的系统服务状态记录在一个跟踪文件中。使用带有跟踪文件的 Winscope 界面,您可以通过重放、单步执行和调试过渡来针对每个动画帧检查这些服务的状态(无论…...

25/9/12(补)

做了下19csps初试,60多分,记不清了,反正能过,写完后改一道暑假没过的题,没改完就下课了...

深入解析:“纳米总管”——Arduino Nano 的趣味生活

深入解析:“纳米总管”——Arduino Nano 的趣味生活pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monosp…...

洛谷题目难度系统优化

以下为优化后的难度系统:优化后难度 对应KaTex数学公式\(\color{FE4C61}{{入门}}\) \color{FE4C61}{{入门}}\(\color{F39C11}{{普及-}}\) \color{F39C11}{{普及-}}\(\color{FFC116}{{普及}}\) \color{FFC116}{{普及}}\(\color{FFD700}{{普及+}}\) \color{FFD700}{{普及+}}\(\c…...

202112_摆烂杯_WhatAHack!

流量分析Tags:流量分析,CTFSHOW 0x00. 题目 这是你沐师傅的站的流量,最近你沐师傅去跟着某讯搭了一个WP平台后发了一篇文章再测试了一下自己的网站就再也没去管过平台了。结果被某位名字貌似大概可能叫g4_simon的大黑阔给hack掉了网站,并进行了一些操作拿到了沐师傅放在平台里…...

少儿 500 常用汉字 字帖

500 常用汉字 每个字加入拼音 每个字加入笔画笔顺 少儿楷书练习下载链接如下 1-4画 5画 6画 7画 8画 9画 10画 11-16画...

Ubuntu 安装 gcc

命令 gcc --version 或者 gcc -v 能查看 gcc 版本。 未安装:安装命令: sudo apt update # 更新软件包源 sudo apt-get install build-essential gdb这样,GCC 就安装完成了。...

Redis常见性能问题

常见性能问题和解决方案?Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化。 如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。 为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内。 尽量避…...

3 线性模型

目录P22 P22 复习一下: 假设同类别之间的数据是比较相似的,所以在空间里,同类别的数据是挨在一起的。那么假设现在有一个超平面去进行二分类,由于一个类别的数量多得多而且两个类别的权重是一样的,于是超平面就可以把很多少数类分为正数类而且损失函数的值要下降(看P12,…...

详细介绍:七彩喜智慧养老:用科技温暖晚年,让关爱永不掉线

详细介绍:七彩喜智慧养老:用科技温暖晚年,让关爱永不掉线pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New",…...

P3522 [POI 2011] TEM-Temperature

题目描述 给出 \(n\) 个数所在区间,求最长可能不降区间。 思路 首先,我们要解决不降的问题,如何才能保证两个相邻区间选数可能不降,不难发现,只要前一个数的最大值大于等于后一个数的最小值即可,即 \(r_{i-1} \ge l_i\)。 然后,因为我们要求的是一段一段连续的区间,所以…...

202105_风二西_SQL基于时间盲注

流量分析,SQL注入,基于时间盲注,蚁剑AntSwordTags:流量分析,SQL注入,基于时间盲注,蚁剑AntSword 0x00. 题目 附件路径:https://pan.baidu.com/s/1GyH7kitkMYywGC9YJeQLJA?pwd=Zmxh#list/path=/CTF附件 附件名称:202105_风二西_SQL基于时间盲注.zip 0x01. WP 1. 浏览流量包,…...

实用指南:【C++】list容器的模拟实现

实用指南:【C++】list容器的模拟实现pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important…...

windows系统缺失DLL库文件下载方法

https://cn.dll-files.com/ windows系统缺失DLL文件下载方法_dll文件下载官网-CSDN博客...

更为通用的决策单调性

学习自 在线决策单调性地皮还能单老哥分治做? - 洛谷专栏 决策单调性最为常用的为分治和二分队列,前者要求离线,后者必须快速处理两个位置的转移,都有一定的局限性,其他算法大部分码量较长,很难应用。 但我们还有一种好写且能维护复杂转移的写法, 简易版 LARSCH 算法,一…...

一文读懂 PHP PSR 接口 PSR-3、PSR-7、PSR-11、PSR-15 完整指南

一文读懂 PHP PSR 接口 PSR-3、PSR-7、PSR-11、PSR-15 完整指南 现代 PHP 的选择很多。这本来是好事,但一到升级框架、替换 Logger,或在团队间统一服务时,你会发现:看不见的耦合(类型、方法签名、约定)会把小改动变成大手术。 本文用通俗的话讲清四个关键标准——PSR-3(…...

2025模拟赛Round9

T1 T2 T3 T4 T5 T6\({\color{#F39C11} 普及− }\) \({\color{#FFC116} 普及/提高− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\)参赛网址:https://boyacoding.cn…...

NOIP2025模拟赛19

T1 T2 T3 T4\({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#9D3DCF} 省选/NOI− }\) \({\color{#3498DB} 提高+/省选− }\)参赛网址:https://oj.33dai.cn/d/TYOI/contest/68919c89c5d9c2f14c1a537f T2,T4搭建未完成 T1 人才计数【NOIP2…...

Qt/C++开发监控GB28181系统/公网对讲/代码实现28181语音对讲/采集本地麦克风数据/支持udp和tcp模式

一、前言说明 按照国标的文档,语音对讲这块,并没有强制要求支持公网对讲,所以当初设备厂家做的都是支持的udp对讲,而且按照国标协议要求,对讲是先发一个语音对讲广播到设备,设备收到后,主动发起对讲到服务端,和视频点播是反着来的,这样的话数据的传输模式只能设备控制…...

P3195 [HNOI2008] 玩具装箱 (斜率优化)

题目描述 一道不限段数的分段问题,要求给出 \(n\) 个元素,求出分任意组所产生的最小代价。 思路 我们可以分为两步来求解这个问题,暴力转移与优化。 The First Step 暴力转移 考虑暴力DP,根据题目描述,每个容器之中玩具的编号都是连续的,并且不限容器数量,状态就很好定义…...

DBeaver使用指南

概述 由于众所周知的原因,公司不容许使用非授权正版软件。datagrip本身挺不错的,但是要倒腾激活码之类的,比较麻烦。只能从开源社区寻找好用的DBMS GUI工具。 发现DBeaver挺不错,功能很全,但是默认的配置不够好用、字体、样式等都不友好,需要打磨一番才行。 下文重点关注…...

sh-2025模拟赛

CSP-J 模拟(九)题目解答 一、单项选择题(每题2分,共30分) 1. 进制转换计算 答案:C 解析:先将八进制数\((2025)_8\)转换为十进制: \(2\times8^3 + 0\times8^2 + 2\times8^1 + 5\times8^0 = 2\times512 + 0 + 16 + 5 = 1024 + 21 = 1045\)。 将十六进制数\((2025)_{16}\)…...

C++ day7 - 指南

C++ day7 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !i…...

读人形机器人11娱乐领域

读人形机器人11娱乐领域1. 机器人表演者与艺术家 1.1. 在人类历史的宏大画卷中,艺术与娱乐一直是我们内心欲望、恐惧和抱负的映照 1.2. 音乐、舞蹈和戏剧表演中的机器人不再是科幻的虚构,而是正在重塑艺术表现形式的崭新现实 1.3. 机器人表演者和艺术家正在通过引入新的表现形…...

Java 注解机制全解析:原理、用途与框架中的实战

注解(Annotation)作为 Java 语言自 JDK5 引入以来的一项重要元编程特性,已经成为现代 Java 开发不可或缺的一部分。无论是 Spring 框架中的依赖注入、事务控制,还是 Hibernate 的对象关系映射,抑或是 Lombok 对代码生成的辅助,注解几乎贯穿于 Java 的开发全过程。 本文将…...

模板集

考虑到作为一名 Oier 有很多需要掌握的模板,所以整合了一下以前的专栏,就变成现在这样了! 有问题请加 qq 3848603482。可以帮你讲解。 给萌新的代码建议 尽量不要写全局变量,容易弄混不方便调试,要用了再创建。没有必要手写栈之类的,STL要了解多一点。不要写#define int …...

暑假

P2569 https://www.luogu.com.cn/problem/P2569 参考这篇。 /*单调队列优化dp买入股票的转移方程j是顺序枚举的,因为是买入股票,手中的股票应该是越来越多的, 当前的决策有可能在后面(j更大)的时候用到,所以你需要先求出来, 同理,卖出股票时,你手中的股票是越来越少的…...

做题记录

P1248 加工生产调度 比较妙的一道题,这里我们可以直接把 A 与 B 的最小值碾一遍,注意 B 操作时间要与 A 操作时间取最大值。...

课程助教工作总结

在上学期,我有幸担任了《数字电路与逻辑设计》课程的助教。这是一次极其宝贵和充实的经历,不仅巩固和深化了我的专业知识,更锻炼了我的沟通、组织和解决问题的能力。现将本学期的工作情况总结如下: 一、 助教工作的具体职责和任务 我的工作核心是成为连接主讲教师与学生的桥…...

6G 驱动的智慧城市新格局

引言随着科技的不断进步,6G 驱动的智慧城市新格局 正逐渐走向应用前沿。它不仅推动了相关产业的发展,也在改变人类社会的运作方式。本文将从背景、核心技术、应用案例、挑战与趋势、总结几个方面对其进行系统分析。 背景 📊6G 驱动的智慧城市新格局 的出现,是社会需求、政…...

SHA-1 证书淘汰警告:网站管理员需紧急验证TLS安全性

微软宣布自2017年5月9日起,Edge和IE11浏览器将逐步阻止SHA-1签名的TLS服务器证书。本文详细解析三阶段淘汰计划、受影响证书类型验证方法及企业应对方案,涉及证书链验证和弱签名日志收集技术。こんにちは、村木ゆりかです。 以前よりマイクロソフト セキュリティ アドバイザリ…...

数字孪生在制造业中的应用

引言在当前快速发展的科技环境中,数字孪生在制造业中的应用 已经成为学术界与产业界广泛关注的主题。本文将通过背景、核心技术、应用案例、挑战与趋势、总结六个部分进行系统性分析。 背景 📊数字孪生在制造业中的应用 的兴起与社会发展需求密切相关。随着数字化转型的加速…...

device第一周个人作业

一. 自我介绍 回顾我的学习经历,虽然没有什么惊天动地的大成就,但也没有一些值得骄傲的小闪光点。兴趣爱好是科幻和军事读物,以前喜欢跟朋友一起打比赛,现在发现朋友在打假赛…… 二.现状、经验与计划 (1)当前技能树与技术偏好 当前技能树: 我可以使用基础的C语言和java…...

Java 在移动开发与跨平台应用中的应用

随着智能手机的普及,移动应用已经成为数字化转型的重要载体。移动端承载着用户的核心交互,而跨平台开发趋势也不断兴起, 旨在减少多端重复开发成本。在这一过程中,Java 一直是移动开发的核心语言, 尤其在 Android 生态中占据主导地位,并通过跨平台技术、移动后端服务、混…...

5G 技术与远程教育

引言在当前快速发展的科技环境中,5G 技术与远程教育 已经成为学术界与产业界广泛关注的主题。本文将通过背景、核心技术、应用案例、挑战与趋势、总结六个部分进行系统性分析。 背景 📊5G 技术与远程教育 的兴起与社会发展需求密切相关。随着数字化转型的加速,全球化的扩展…...

5G 技术在工业互联网的应用

引言在当前社会与科技的双重推动下,5G 技术在工业互联网的应用 已成为一个举世瞩目的议题。它不仅仅是技术层面的创新,更代表着社会运行模式的转型。本文将从背景、核心技术、应用案例、挑战与趋势、总结几个方面进行深入探讨。 背景 📊5G 技术在工业互联网的应用 的发展源…...

一键部署ftp脚本

在 Ubuntu(root) 上搭建标准 FTP(vsftpd)服务器,带被动模式端口、用户创建、目录与权限配置,可直接落地执行。一、部署脚本(保存为 setup_ftp.sh,root 执行) #!/usr/bin/env bash set -euo pipefail### ====== 可按需修改的变量 ====== FTP_USER="ftpuser" …...