Python深度学习基础——卷积神经网络(CNN)(PyTorch)

CNN原理

从DNN到CNN

  1. 卷积层与汇聚
  • 深度神经网络DNN中,相邻层的所有神经元之间都有连接,这叫全连接;卷积神经网络 CNN 中,新增了卷积层(Convolution)与汇聚(Pooling)。
  • DNN 的全连接层对应 CNN 的卷积层,汇聚是与激活函数类似的附件;单个卷积层的结构是:卷积层-激活函数-(汇聚),其中汇聚可省略。

2.CNN:专攻多维数据
在深度神经网络 DNN 课程的最后一章,使用 DNN 进行了手写数字的识别。但是,图像至少就有二维,向全连接层输入时,需要多维数据拉平为 1 维数据,这样一来,图像的形状就被忽视了,很多特征是隐藏在空间属性里的,如下图所示。
在这里插入图片描述
而卷积层可以保持输入数据的维数不变,当输入数据是二维图像时,卷积层会以多维数据的形式接收输入数据,并同样以多维数据的形式输出至下一层,如下图所示。
在这里插入图片描述

卷积层

CNN 中的卷积层与 DNN 中的全连接层是平级关系,全连接层中的权重与偏置即y = ω1x1 + ω2x2 + ω3x3 + b中的 ω 与 b,卷积层中的权重与偏置变得稍微复杂。

  1. 内部参数:权重(卷积核)
    当输入数据进入卷积层后,输入数据会与卷积核进行卷积运算,如下图:
    在这里插入图片描述
    上图中的输入大小是(4,4),卷积核大小事(3,3),输出大小是(2,2)卷积运算的原理是逐元素乘积后再相加。
    在这里插入图片描述

  2. 内部参数:偏置
    在卷积运算的过程中也存在偏置,如下图所示:
    在这里插入图片描述

  3. 外部参数:补充
    为了防止经过多个卷积层后图像越卷越小,可以在进行卷积层的处理之前,向输入数据的周围填入固定的数据(比如 0),这称为填充(padding)。
    在这里插入图片描述
    对上图大小为(4, 4)的输入数据应用了幅度为 1 的填充,填充值为 0。

  4. 外部参数:步幅
    使用卷积核的位置间隔被称为步幅(stride),之前的例子中步幅都是 1,如果将步幅设为 2,此时使用卷积核的窗口的间隔变为 2。
    在这里插入图片描述
    综上,增大填充后,输出尺寸会变大;而增大步幅后,输出尺寸会变小

  5. 输入与输出尺寸的关系
    假设输入尺寸为(H, W),卷积核的尺寸为(FH, FW),填充为 P,步幅为 S。则输出尺寸(OH, OW)的计算公式为
    在这里插入图片描述

多通道

在上一小节讲的卷积层,仅仅针对二维的输入与输出数据(一般是灰度图像),可称之为单通道。
但是,彩色图像除了高、长两个维度之外,还有第三个维度:通道(channel)。例如,以 RGB 三原色为基础的彩色图像,其通道方向就有红、黄、蓝三部分,可视为 3 个单通道二维图像的混合叠加。一般的,当输入数据是二维时,权重被称为卷积核(Kernel);当输入数据是三维或更高时,权重被称为滤波器(Filter)。

1.多通道输入
对三维数据的卷积操作如图 1-8 所示,输入数据与滤波器的通道数必须要设为相同的值,可以发现,这种情况下的输出结果降级为了二维
在这里插入图片描述
将数据和滤波器看作长方体,如图 1-9 所示
在这里插入图片描述
C、H、W 是固定的顺序,通道数要写在高与宽的前面
图 1-9 可看出,仅通过一个卷积层,三维就被降成二维了。大多数时候我们想让三维的特征多经过几个卷积层,因此就需要多通道输出,如图 1-10 所示。
在这里插入图片描述
别忘了,卷积运算中存在偏置,如果进一步追加偏置的加法运算处理,则结果如图 1-11 所示,每个通道都有一个单独的偏置。
在这里插入图片描述

汇聚(很多教材也叫做池化)

汇聚(Pooling)仅仅是从一定范围内提取一个特征值,所以不存在要学习的内部参数。一般有平均汇聚与最大值汇聚。

  1. 平均汇聚
    一个以步幅为2进行的2*2窗口的平均汇聚,如图1-12所示
    在这里插入图片描述

  2. 最大值汇聚
    一个以步幅为 2 进行 2*2 窗口的最大值汇聚,如图 1-13 所示
    在这里插入图片描述
    汇聚对图像的高 H 和宽 W 进行特征提取,不改变通道数 C。

尺寸变换总结

  1. 卷积层
    现假设卷积层的填充为P,步幅为S,由
  • 输入数据的尺寸是:( C,H,W) 。
  • 滤波器的尺寸是:(FN,C,FH,FW)。
  • 输出数据的尺寸是:(FN,OH,OW) 。

可得
在这里插入图片描述
2. 汇聚
现假设汇聚的步幅为 S,由

  • 输入数据的尺寸是:( C,H,W) 。
  • 输出数据的尺寸是:(C,OH,OW) 。

可得
在这里插入图片描述

LeNet-5

网络结构

LeNet-5 虽诞生于 1998 年,但基于它的手写数字识别系统则非常成功。
该网络共 7 层,输入图像尺寸为 28×28,输出则是 10 个神经元,分别表示某手写数字是 0 至 9 的概率。
在这里插入图片描述
PS:输出层由 10 个径向基函数 RBF 组成,用于归一化最终的结果,目前RBF 已被 Softmax 取代。
根据网络结构,在 PyTorch 的 nn.Sequential 中编写为

self.net = nn.Sequential(nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Tanh(), # C1:卷积层nn.AvgPool2d(kernel_size=2, stride=2),                # S2:平均汇聚nn.Conv2d(6, 16, kernel_size=5), nn.Tanh(),           # C3:卷积层nn.AvgPool2d(kernel_size=2, stride=2),                # S4:平均汇聚nn.Conv2d(16, 120, kernel_size=5), nn.Tanh(),         # C5:卷积层nn.Flatten(),                                         # 把图像铺平成一维nn.Linear(120, 84), nn.Tanh(),                        # F5:全连接层nn.Linear(84, 10)                                     # F6:全连接层
)

其中,nn.Conv2d( )需要四个参数,分别为

  • in_channel:此层输入图像的通道数;
  • out_channel:此层输出图像的通道数;
  • kernel_size:卷积核尺寸;
  • padding:填充;
  • stride:步幅。

制作数据集

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import matplotlib.pyplot as plt
%matplotlib inline
# 展示高清图
from matplotlib_inline import backend_inline
backend_inline.set_matplotlib_formats('svg')
# 制作数据集
# 数据集转换参数
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize(0.1307, 0.3081)
])
# 下载训练集与测试集
train_Data = datasets.MNIST(root = 'D:/Jupyter/dataset/mnist/', # 下载路径train = True, # 是 train 集download = True, # 如果该路径没有该数据集,就下载transform = transform # 数据集转换参数
)
test_Data = datasets.MNIST(root = 'D:/Jupyter/dataset/mnist/', # 下载路径train = False, # 是 test 集download = True, # 如果该路径没有该数据集,就下载transform = transform # 数据集转换参数
)
# 批次加载器
train_loader = DataLoader(train_Data, shuffle=True, batch_size=256)
test_loader = DataLoader(test_Data, shuffle=False, batch_size=256)

搭建神经网络

class CNN(nn.Module):def __init__(self):super(CNN,self).__init__()self.net = nn.Sequential(nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Tanh(),nn.AvgPool2d(kernel_size=2, stride=2),nn.Conv2d(6, 16, kernel_size=5), nn.Tanh(),nn.AvgPool2d(kernel_size=2, stride=2),nn.Conv2d(16, 120, kernel_size=5), nn.Tanh(),nn.Flatten(),nn.Linear(120, 84), nn.Tanh(),nn.Linear(84, 10))def forward(self, x):y = self.net(x)return y
# 查看网络结构
X = torch.rand(size= (1, 1, 28, 28))
for layer in CNN().net:X = layer(X)print( layer.__class__.__name__, 'output shape: \t', X.shape )

在这里插入图片描述

# 创建子类的实例,并搬到 GPU 上
model = CNN().to('cuda:0')

训练网络

# 损失函数的选择
loss_fn = nn.CrossEntropyLoss() # 自带 softmax 激活函数
# 优化算法的选择
learning_rate = 0.9 # 设置学习率
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate,
)
# 训练网络
epochs = 5
losses = [] # 记录损失函数变化的列表
for epoch in range(epochs):for (x, y) in train_loader: # 获取小批次的 x 与 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向传播(小批量)loss = loss_fn(Pred, y) # 计算损失函数losses.append(loss.item()) # 记录损失函数的变化optimizer.zero_grad() # 清理上一轮滞留的梯度loss.backward() # 一次反向传播optimizer.step() # 优化内部参数
Fig = plt.figure()
plt.plot(range(len(losses)), losses)
plt.show()

在这里插入图片描述

测试网络

# 测试网络
correct = 0
total = 0
with torch.no_grad(): # 该局部关闭梯度计算功能for (x, y) in test_loader: # 获取小批次的 x 与 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向传播(小批量)_, predicted = torch.max(Pred.data, dim=1)correct += torch.sum( (predicted == y) )total += y.size(0) print(f'测试集精准度: {100*correct/total} %')   #OUT:测试集精准度: 9.569999694824219 %

AlexNet

网络结构

AlexNet 是第一个现代深度卷积网络模型,其首次使用了很多现代网络的技术方法,作为 2012 年 ImageNet 图像分类竞赛冠军,输入为 3×224×224 的图像,输出为 1000 个类别的条件概率。
考虑到如果使用 ImageNet 训练集会导致训练时间过长,这里使用稍低亿档的 1×28×28 的 MNIST 数据集,并手动将其分辨率从 1×28×28 提到 1×224×224,同时输出从 1000 个类别降到 10 个,修改后的网络结构见下表。
在这里插入图片描述
根据网络结构,在 PyTorch 的 nn.Sequential 中编写为

self.net = nn.Sequential(nn.Conv2d(1, 96, kernel_size=11, stride=4, padding=1), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(),nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(),nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Flatten(),nn.Linear(6400, 4096), nn.ReLU(),nn.Dropout(p=0.5), # Dropout——随机丢弃权重nn.Linear(4096, 4096), nn.ReLU(),nn.Dropout(p=0.5), # 按概率 p 随机丢弃突触nn.Linear(4096, 10)
)

制作数据集

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import matplotlib.pyplot as plt
%matplotlib inline
# 展示高清图
from matplotlib_inline import backend_inline
backend_inline.set_matplotlib_formats('svg')
# 制作数据集
# 数据集转换参数
transform = transforms.Compose([transforms.ToTensor(),transforms.Resize(224),transforms.Normalize(0.1307, 0.3081)
])
# 下载训练集与测试集
train_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = True,download = True,transform = transform
)
test_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = False,download = True,transform = transform
)
# 批次加载器
train_loader = DataLoader(train_Data, shuffle=True, batch_size=128)
test_loader = DataLoader(test_Data, shuffle=False, batch_size=128)

搭建神经网络

class CNN(nn.Module):def __init__(self):super(CNN,self).__init__()self.net = nn.Sequential(nn.Conv2d(1, 96, kernel_size=11, stride=4, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Conv2d(96, 256, kernel_size=5, padding=2),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Conv2d(256, 384, kernel_size=3, padding=1),nn.ReLU(),nn.Conv2d(384, 384, kernel_size=3, padding=1),nn.ReLU(),nn.Conv2d(384, 256, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Flatten(),nn.Linear(6400, 4096), nn.ReLU(),nn.Dropout(p=0.5),nn.Linear(4096, 4096), nn.ReLU(),nn.Dropout(p=0.5),nn.Linear(4096, 10))def forward(self, x):y = self.net(x)return y
# 查看网络结构
X = torch.rand(size= (1, 1, 224, 224))
for layer in CNN().net:X = layer(X)print( layer.__class__.__name__, 'output shape: \t', X.shape )

在这里插入图片描述

# 创建子类的实例,并搬到 GPU 上
model = CNN().to('cuda:0')

训练网络

# 损失函数的选择
loss_fn = nn.CrossEntropyLoss() # 自带 softmax 激活函数
# 优化算法的选择
learning_rate = 0.1 # 设置学习率
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate,
)
# 训练网络
epochs = 10
losses = [] # 记录损失函数变化的列表
for epoch in range(epochs):for (x, y) in train_loader: # 获取小批次的 x 与 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向传播(小批量)loss = loss_fn(Pred, y) # 计算损失函数losses.append(loss.item()) # 记录损失函数的变化optimizer.zero_grad() # 清理上一轮滞留的梯度loss.backward() # 一次反向传播optimizer.step() # 优化内部参数
Fig = plt.figure()
plt.plot(range(len(losses)), losses)
plt.show()

测试网络

# 测试网络
correct = 0
total = 0
with torch.no_grad(): # 该局部关闭梯度计算功能for (x, y) in test_loader: # 获取小批次的 x 与 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向传播(小批量)_, predicted = torch.max(Pred.data, dim=1)correct += torch.sum( (predicted == y) )total += y.size(0)
print(f'测试集精准度: {100*correct/total} %')

GoogLeNet

网络结构

2014 年,获得 ImageNet 图像分类竞赛的冠军是 GoogLeNet,其解决了一个重要问题:滤波器超参数选择困难,如何能够自动找到最佳的情况。
其在网络中引入了一个小网络——Inception 块,由 4 条并行路径组成,4 条路径互不干扰。这样一来,超参数最好的分支的那条分支,其权重会在训练过程中不断增加,这就类似于帮我们挑选最佳的超参数,如示例所示。

# 一个 Inception 块
class Inception(nn.Module):def __init__(self, in_channels):super(Inception, self).__init__()self.branch1 = nn.Conv2d(in_channels, 16, kernel_size=1)self.branch2 = nn.Sequential(nn.Conv2d(in_channels, 16, kernel_size=1),nn.Conv2d(16, 24, kernel_size=3, padding=1),nn.Conv2d(24, 24, kernel_size=3, padding=1))self.branch3 = nn.Sequential(nn.Conv2d(in_channels, 16, kernel_size=1),nn.Conv2d(16, 24, kernel_size=5, padding=2))self.branch4 = nn.Conv2d(in_channels, 24, kernel_size=1)def forward(self, x):branch1 = self.branch1(x)branch2 = self.branch2(x)branch3 = self.branch3(x)branch4 = self.branch4(x)outputs = [branch1, branch2, branch3, branch4]return torch.cat(outputs, 1)

此外,分支 2 和分支 3 上增加了额外 1×1 的滤波器,这是为了减少通道数,降低模型复杂度。
GoogLeNet 之所以叫 GoogLeNet,是为了向 LeNet 致敬,其网络结构为

class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()self.net = nn.Sequential(nn.Conv2d(1, 10, kernel_size=5), nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),Inception(in_channels=10),nn.Conv2d(88, 20, kernel_size=5), nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),Inception(in_channels=20),nn.Flatten(),nn.Linear(1408, 10) )def forward(self, x):y = self.net(x)return y

制作数据集

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import matplotlib.pyplot as plt
%matplotlib inline
# 展示高清图
from matplotlib_inline import backend_inline
backend_inline.set_matplotlib_formats('svg')
# 制作数据集
# 数据集转换参数
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(0.1307, 0.3081)
])
# 下载训练集与测试集
train_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = True,download = True,transform = transform
)
test_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = False,download = True,transform = transform
)
# 批次加载器
train_loader = DataLoader(train_Data, shuffle=True, batch_size=128)
test_loader = DataLoader(test_Data, shuffle=False, batch_size=128)

搭建神经网络

# 一个 Inception 块
class Inception(nn.Module):def __init__(self, in_channels):super(Inception, self).__init__()self.branch1 = nn.Conv2d(in_channels, 16, kernel_size=1)self.branch2 = nn.Sequential(nn.Conv2d(in_channels, 16, kernel_size=1),nn.Conv2d(16, 24, kernel_size=3, padding=1),nn.Conv2d(24, 24, kernel_size=3, padding=1))self.branch3 = nn.Sequential(nn.Conv2d(in_channels, 16, kernel_size=1),nn.Conv2d(16, 24, kernel_size=5, padding=2))self.branch4 = nn.Conv2d(in_channels, 24, kernel_size=1)def forward(self, x):branch1 = self.branch1(x)branch2 = self.branch2(x)branch3 = self.branch3(x)branch4 = self.branch4(x)outputs = [branch1, branch2, branch3, branch4]return torch.cat(outputs, 1)
class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()self.net = nn.Sequential(nn.Conv2d(1, 10, kernel_size=5), nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),Inception(in_channels=10),nn.Conv2d(88, 20, kernel_size=5), nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),Inception(in_channels=20),nn.Flatten(),nn.Linear(1408, 10))def forward(self, x):y = self.net(x) return y
# 查看网络结构
X = torch.rand(size= (1, 1, 28, 28))
for layer in CNN().net:X = layer(X)print( layer.__class__.__name__, 'output shape: \t', X.shape )
# 创建子类的实例,并搬到 GPU 上
model = CNN().to('cuda:0')

训练网络

# 损失函数的选择
loss_fn = nn.CrossEntropyLoss()
# 优化算法的选择
learning_rate = 0.1 # 设置学习率
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate,
)
# 训练网络
epochs = 10
losses = [] # 记录损失函数变化的列表
for epoch in range(epochs):for (x, y) in train_loader: # 获取小批次的 x 与 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向传播(小批量)loss = loss_fn(Pred, y) # 计算损失函数losses.append(loss.item()) # 记录损失函数的变化optimizer.zero_grad() # 清理上一轮滞留的梯度loss.backward() # 一次反向传播optimizer.step() # 优化内部参数
Fig = plt.figure()
plt.plot(range(len(losses)), losses)
plt.show()

测试网络

# 测试网络
correct = 0
total = 0
with torch.no_grad(): # 该局部关闭梯度计算功能for (x, y) in test_loader: # 获取小批次的 x 与 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向传播(小批量)_, predicted = torch.max(Pred.data, dim=1)correct += torch.sum( (predicted == y) )total += y.size(0)print(f'测试集精准度: {100*correct/total} %')

ResNet

网络结构

残差网络(Residual Network,ResNet)荣获 2015 年的 ImageNet 图像分类竞赛冠军,其可以缓解深度神经网络中增加深度带来的“梯度消失”问题。
在反向传播计算梯度时,梯度是不断相乘的,假如训练到后期,各层的梯度均小于 1,则其相乘起来就会不断趋于 0。因此,深度学习的隐藏层并非越多越好,隐藏层越深,梯度越趋于 0,此之谓“梯度消失”。
在这里插入图片描述

制作数据集

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import matplotlib.pyplot as plt
%matplotlib inline
# 展示高清图
from matplotlib_inline import backend_inline
backend_inline.set_matplotlib_formats('svg')
# 制作数据集
# 数据集转换参数
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(0.1307, 0.3081)
])
# 下载训练集与测试集
train_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = True,download = True,transform = transform
)
test_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = False,download = True,transform = transform
)
# 批次加载器
train_loader = DataLoader(train_Data, shuffle=True, batch_size=128)
test_loader = DataLoader(test_Data, shuffle=False, batch_size=128)

搭建神经网络

# 残差块
class ResidualBlock(nn.Module):def __init__(self, channels):super(ResidualBlock, self).__init__()self.net = nn.Sequential(nn.Conv2d(channels, channels, kernel_size=3, padding=1),nn.ReLU(),nn.Conv2d(channels, channels, kernel_size=3, padding=1),)def forward(self, x):y = self.net(x)return nn.functional.relu(x+y)
class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()self.net = nn.Sequential(nn.Conv2d(1, 16, kernel_size=5), nn.ReLU(),nn.MaxPool2d(2), ResidualBlock(16),nn.Conv2d(16, 32, kernel_size=5), nn.ReLU(),nn.MaxPool2d(2), ResidualBlock(32),nn.Flatten(),nn.Linear(512, 10))def forward(self, x):y = self.net(x) return y
# 查看网络结构
X = torch.rand(size= (1, 1, 28, 28))for layer in CNN().net:X = layer(X)print( layer.__class__.__name__, 'output shape: \t', X.shape )
# 创建子类的实例,并搬到 GPU 上
model = CNN().to('cuda:0')

训练网络

# 损失函数的选择
loss_fn = nn.CrossEntropyLoss()
# 优化算法的选择
learning_rate = 0.1 # 设置学习率
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate,
)
# 训练网络
epochs = 10
losses = [] # 记录损失函数变化的列表
for epoch in range(epochs):for (x, y) in train_loader: # 获取小批次的 x 与 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向传播(小批量)loss = loss_fn(Pred, y) # 计算损失函数losses.append(loss.item()) # 记录损失函数的变化optimizer.zero_grad() # 清理上一轮滞留的梯度loss.backward() # 一次反向传播optimizer.step() # 优化内部参数
Fig = plt.figure()
plt.plot(range(len(losses)), losses)
plt.show()

测试网络

# 测试网络
correct = 0
total = 0
with torch.no_grad(): # 该局部关闭梯度计算功能for (x, y) in test_loader: # 获取小批次的 x 与 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向传播(小批量)_, predicted = torch.max(Pred.data, dim=1)correct += torch.sum( (predicted == y) )total += y.size(0)
print(f'测试集精准度: {100*correct/total} %')

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

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

相关文章

Linux 第三讲 --- 基础指令(三)

前言: 在前面我们已经讲了有十几个Linux的基础指令,今天我们再补充几个常用的基础指令,为后面的学习做准备 。 目录 前言: 一、两个与时间相关的指令 1.date指令 演示 : 时间戳 设置时间 2、cal指令 演示&#x…

基于SiamFC的红外目标跟踪

基于SiamFC的红外目标跟踪 1,背景与原理2,SiamFC跟踪方法概述2.1 核心思想2.2 算法优势3,基于SiamFC的红外跟踪代码详解3.1 网络定义与交叉相关模块3.2 SiamFC 跟踪器实现3.3 主程序:利用 OpenCV 实现视频跟踪4,总结与展望在红外监控、无人机防御以及低光照场景中,红外图…

Odoo 部署本地 把現時的excel計算表格部署上odoo 教程

要将现有的 Excel 计算表格部署到 Odoo 平台上,您可以按照以下步骤进行操作: 将 Excel 表格中的数据转移到 Odoo 模块中:首先,您需要将 Excel 表格中的数据导出为 CSV 格式,然后可以使用 Odoo 的数据导入功能将这些数据…

KWDB创作者计划—KWDB认知引擎:数据流动架构与时空感知计算的范式突破

引言:数据智能的第三范式 在数字化转型进入深水区的2025年,企业数据系统正面临三重悖论:数据规模指数级增长与实时决策需求之间的矛盾、多模态数据孤岛与业务连续性要求之间的冲突、静态存储范式与动态场景适配之间的鸿沟。KWDB(K…

C语言 数据结构 【栈】动态模拟实现

引言 动态模拟实现栈的各个接口 一、栈的概念与结构 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(LastInFirstOut…

Python itertools模块的groupby函数介绍

itertools.groupby 是 Python 标准库 itertools 模块中的一个函数,它的主要功能是对可迭代对象中相邻的相同元素进行分组。 itertools.groupby(iterable, keyNone) 函数 作用: 将连续的(相邻的)相同元素分组,返回 (…

Python实例题:使用Python生成分形图片

目录 Python实例题 题目 题目分析 需求理解 关键知识点 实现思路分析 代码实现 代码解释 mandelbrot 函数: 设置复平面区域和图像参数: 计算分形数据: 绘图展示: 运行思路 Python实例题 题目 使用Python生成分形图…

系统编程1(进程的概念与原理)

进程的概念与原理 计算机组成部分一般遵循冯诺依曼结构,也就是由控制器、运算器、存储器、输入设备、输出设备五个部分组成。 ⦁ 程序的编译 一般在编写出程序之后,并不能直接运行,而是需要把程序通过编译器进行编译,生成可执行…

《Vue Router实战教程》5.嵌套路由

欢迎观看《Vue Router 实战(第4版)》视频课程 嵌套路由 一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构,例如: 通过 Vue Router,你可以使用嵌套路由配置…

使用Python解决Logistic方程

引言 在数学和计算机科学中,Logistic 方程是描述人口增长、传播过程等现象的一种常见模型。它通常用于表示一种有限资源下的增长过程,比如动物种群、疾病传播等。本文将带领大家通过 Python 实现 Logistic 方程的求解,帮助你更好地理解这一经典数学模型。 1.什么是 Logist…

《从零搭建Vue3项目实战》(AI辅助搭建Vue3+ElemntPlus后台管理项目)零基础入门系列第十二篇(完结篇):数据统计功能实现

🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 《从零搭建Vue3项目实战》(AI辅助…

研究嵌入式软件架构时遇到的初始化堆栈溢出问题

文章目录 2025年4月10日新增分析PC寄存器指针值排查问题map文件设计到的知识点1. **.bss 段(Block Started by Symbol)**2. **.data 段**3. **.text 段**4. **.heap 段**5. **.stack 段**6. **.rodata 段(只读数据段)**7. **.init…

软件架构评估两大法:ATAM 和 SAAM 的对比与实践

架构权衡分析方法(ATAM)和软件架构分析方法(SAAM)是软件架构评估领域中非常重要的两种方法,以下为你详细介绍: 一、架构权衡分析方法(ATAM) 1.背景与起源:ATAM 是由卡耐…

Python爬虫-爬取全球股市涨跌幅和涨跌额数据

前言 本文是该专栏的第52篇,后面会持续分享python爬虫干货知识,记得关注。 本文中,笔者将基于Python爬虫,实现批量采集全球股市行情(亚洲,美洲,欧非,其他等)的各股市“涨跌幅”以及“涨跌额”数据。 具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。…

电流互感器的两相星形接线的建模与仿真

微♥“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink(版本MATLAB 2016Rb)软件。建议采用matlab2016 Rb及以上版本打开。(若需要其他版本可联系代为转换) 2.仿真模型 3.仿真结果 3.1一次…

详解 kotlin 相对 Java 特有的关键字及使用

文章目录 1. val 和 var2. fun3. when4. is 和 !is5. lateinit6. by7. reified8. companion 本文首发地址:https://h89.cn/archives/366.html 最新更新地址:https://gitee.com/chenjim/chenjimblog Kotlin 在兼容Java的基础上,引入了许多特有…

国标GB28181视频平台EasyCVR如何搭建汽车修理厂远程视频网络监控方案

一、背景分析 近年我国汽车保有量持续攀升,与之相伴的汽车保养维修需求也逐渐提高。随着社会经济的发展,消费者对汽车维修服务质量的要求越来越高,这使得汽车维修店的安全防范与人员管理问题面临着巨大挑战。 多数汽车维修店分布分散&#…

linux RCU技术

RCU(Read-Copy-Update)是Linux内核中的一种同步机制,用于在多核处理器环境中实现无锁读取和延迟更新。Linux RCU(Read-Copy-Update)技术通过一种高效的同步机制来处理并发冲突,确保在多核环境中读者和写者对…

【笔记ing】AI大模型-02开发环境搭建

按实验需求合理选用实例规格,一般:模型开发阶段:使用最低算力2U8GB CPU。训练或推理阶段:切换至GPU规格,用完及时关闭算力环境,且切回最低算力规格。 每次实验结束手动关闭实例。使用ModelArts公有云资源。…

Python——numpy测试题目

题目: 生成一个2行3列随机整数二维数组a使用Numpy方法对(1)中数组a进行整体求积使用Numpy方法对(1)中数组a进行求每列最大值索引定义一个NumPy一维数组 b,元素为 1 到 10 的整数获取(4&#x…