这段代码首先导入了collections
模块中的Counter
类,用于统计数据。然后,再次调用之前定义的data_set
函数,获取数据集。接着,使用切片操作将数据集分为训练集、测试集和验证集。然后,使用之前定义的Get_Dataset
类构建三个数据集对象。接着,从训练集中获取两个数据,并打印出来。最后,使用Counter
类统计训练集中每个类别的数量,并打印出来。还有一些被注释掉的代码,它们演示了如何从数据集中获取单个数据。
##################################
FOLDS=5
EPOCH=100
BATCH_SIZE=30
##################################
这段代码定义了三个变量:FOLDS
、EPOCH
和BATCH_SIZE
。它们分别表示交叉验证的折数、训练的轮数和批量大小。这些变量通常用于控制模型训练过程中的参数。
##################################
import torch
import torch.nn as nn
import torch.nn.functional as F
import math
from torch.nn import init
from cbam import *
from inception import InceptionA
from bam import *
class VGG16_cml(nn.Module):
def __init__(self, num_classes=5):
super(VGG16_cml, self).__init__()
layers = []
in_dim = 3
out_dim = 64
for i in range(13):
if i==0 or i==2 or i==4 or i==7 or i==10 :
# pass
layers += [InceptionA(in_dim , out_dim), nn.ReLU(inplace=True)]
else:
layers += [nn.Conv2d(in_dim, out_dim, 3, 1, 1), nn.ReLU(inplace=True)]
in_dim = out_dim
if i==1 or i==3 or i==6 or i==9 or i==12:
layers += [CBAM(out_dim, 16 ), nn.ReLU(inplace=True)]
layers += [nn.MaxPool2d(2, 2)]
if i!=9:
out_dim*=2
self.features = nn.Sequential(*layers)
self.classifier = nn.Sequential(
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, num_classes),
)
def forward(self, x):
x = self.features(x)
x = x.view(x.size(0), -1)
x = self.classifier(x)
return x
model=VGG16_cml()
print(model)
##################################
这段代码定义了一个名为VGG16_cml
的类,它继承自torch.nn.Module
。这个类实现了一个卷积神经网络模型,用于图像分类。
类中定义了两个方法:__init__
和forward
。__init__
方法用于初始化对象,它接受一个可选参数num_classes
,表示分类的类别数,默认为5。方法首先定义了一个空列表layers
,用于存储网络层。然后,使用循环构建卷积层和激活层。在特定位置,使用自定义的InceptionA
类替换卷积层。在另一些特定位置,添加自定义的CBAM
类和池化层。最后,将所有层添加到一个顺序容器中,并赋值给实例变量self.features
。接着,定义了一个全连接层,用于分类,并赋值给实例变量self.classifier
。
forward
方法用于前向传播,它接受一个参数x
,表示输入数据。方法首先使用实例变量self.features
对输入数据进行卷积和池化操作,然后使用view
方法将四维张量转换为二维张量。最后,使用实例变量self.classifier
对数据进行分类,并返回结果。
最后,代码中创建了一个模型对象,并打印出来。
##################################
model_vgg16=VGG16_cml(5)
# model_vgg16=models.vgg16()
# model_vgg16.classifier._modules['6']=nn.Linear(4096, 5)
model_vgg16
##################################
这段代码使用之前定义的VGG16_cml
类创建了一个模型对象,传入的参数为5,表示分类的类别数。然后,有一些被注释掉的代码,它们演示了如何使用torchvision.models
模块中的vgg16
函数创建一个预训练的VGG16模型,并修改最后一层全连接层的输出维度。最后,打印出模型对象。
##################################
weights = list(model_vgg16.parameters()) # 获取模型的权重
print(weights) # 打印模型的权重
##################################
这段代码使用parameters
方法获取模型的权重,然后将其转换为列表并赋值给变量weights
。最后,打印出模型的权重。
##################################
torch.manual_seed(2023)
criterion =nn.CrossEntropyLoss()#交叉熵损失函数中自带
learn_rate=[0.5,0.1,0.001]
optimizer1=torch.optim.SGD(model_vgg16.parameters(),lr=learn_rate[0])
# optimizer2=torch.optim.SGD(model_vgg16.parameters(),lr=learn_rate[1])
# optimizer2=torch.optim.Adam(model_vgg16.parameters(),lr=learn_rate[1])
scheduler = lr_scheduler.StepLR(optimizer1, step_size=25, gamma=0.1)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model_vgg16=model_vgg16.to(device)
T1 = time.time()
loss_list=[0]
correct_list=[0]
c=[]
train_loader=DataLoader(train_dataset,batch_size=64,shuffle=True,num_workers=0)
test_loader=DataLoader(test_dataset,batch_size=64,shuffle=False,num_workers=0)
val_loader=DataLoader(val_dataset,batch_size=64,shuffle=False,num_workers=0)
for epoch in tqdm(range(EPOCH),ascii=True,desc='轮数'):
model_vgg16.train()
train_loss=0.0
for i,data in enumerate(train_loader):
image,label=data
image=image.to(device)
label=np.asarray(label, dtype = float)
label=torch.tensor(label,dtype=torch.int64)
label=label.to(device)
out=model_vgg16(image)
loss=criterion(out,label)
loss_list.append(loss)
if epoch<100:
optimizer1.zero_grad()
loss.backward()
optimizer1.step()
scheduler = lr_scheduler.StepLR(optimizer1, step_size=30, gamma=0.1)
else:
optimizer2.zero_grad()
loss.backward()
optimizer2.step()
# scheduler.step()
train_loss+=loss.item()
num_per_epoch=i+1
model_vgg16.eval()
with torch.no_grad():
total=0.0
correct=0.0
for j ,data in enumerate(test_loader):
image,label = data
image=image.to(device)
label=np.asarray(label, dtype = float)
label=torch.tensor(label,dtype=torch.int64)
label=label.to(device)
out = model_vgg16(image)
_,predict = torch.max(out.data, dim=1)
total+=label.size(0)
correct+=(predict==label).sum().item()
correct_val=correct/total
if correct_val > max(correct_list):
torch.save(model_vgg16.state_dict(), "best_new.pth")
print("save epoch {} model".format(epoch))
correct_list.append(correct_val)
print('第{}轮的loss为{},正确率为{}%,学习率为{}'.format(epoch,train_loss/num_per_epoch,correct_val*100,scheduler.get_lr))
torch.save(model_vgg16.state_dict(),'last_new.pth')
T2 = time.time()
print('程序一共运行了{}分钟'.format((T2-T1)/60))
loss_list=np.array(loss_list)
np.save('loss_list_new.npy',loss_list)
acc_list=np.array(correct_list)
np.save('correct_list_new.npy',correct_list)
##################################
这段代码实现了模型的训练过程。首先,使用torch.manual_seed
函数设置随机数种子,以确保每次运行结果相同。然后,定义了一个交叉熵损失函数,用于计算模型的损失。接着,定义了一个学习率列表,并使用torch.optim.SGD
函数创建一个随机梯度下降优化器。然后,使用lr_scheduler.StepLR
类创建一个学习率调度器,用于动态调整学习率。接着,使用torch.device
函数获取可用的计算设备,并将模型转移到该设备上。然后,记录当前时间,并定义一些变量和列表,用于存储训练过程中的信息。
接着,使用DataLoader
类创建三个数据加载器,分别用于加载训练集、测试集和验证集中的数据。然后,使用循环进行多轮训练。在每一轮训练中,首先将模型设置为训练模式,然后遍历训练集中的所有数据。对于每批数据,将其转移到计算设备上,并使用模型进行前向传播,计算损失。然后,根据当前轮数选择优化器,并使用该优化器更新模型的权重。
在每一轮训练结束后,将模型设置为评估模式,并使用测试集对模型进行评估。计算模型在测试集上的准确率,并将其添加到列表中。如果当前轮的准确率高于之前所有轮的准确率,则保存模型的权重。
最后,在所有轮训练结束后,保存模型的权重,并打印出程序运行时间。还将损失和准确率列表保存到文件中。
##################################
model_vgg16.load_state_dict(torch.load('./best_new.pth'))
##################################
这段代码使用torch.load
函数从文件中加载模型的权重,并使用load_state_dict
方法将权重加载到模型中。这样,就可以使用保存的最优模型进行预测或继续训练。
##################################
path='./corn weed datasets/corn/IMG_20160628_081200.jpg'
image=Image.open(path)
normalize = T.Normalize(mean=[0.5605, 0.5399, 0.4873], std=[0.1603, 0.1647, 0.1739])
transforms = T.Compose([
T.Resize(256),
T.CenterCrop(224),
T.ToTensor(),
normalize
])
img=torch.unsqueeze(transforms(image),0)
img=img.to(device)
out=model_vgg16(img)
print(out)
_,predic=torch.max(out.data,dim=1)
print(predic)
##################################
这段代码演示了如何使用训练好的模型对单张图像进行预测。首先,定义了一张图像的路径,并使用PIL库中的Image类打开图像文件。然后,定义了一个图像预处理流程,包括缩放、居中裁剪、转换为张量和归一化。接着,对图像进行预处理,并使用torch.unsqueeze
函数在第一个维度上添加一个维度,使其形状变为(1, C, H, W)
。然后,将图像转移到计算设备上,并使用模型进行前向传播,得到预测结果。最后,使用torch.max
函数获取预测结果中概率最大的类别,并打印出来。
##################################
path='./corn weed datasets/bluegrass/IMG_0001.jpg'
image=Image.open(path)
normalize = T.Normalize(mean=[0.5605, 0.5399, 0.4873], std=[0.1603, 0.1647, 0.1739])
transforms = T.Compose([
T.Resize(256),
T.CenterCrop(224),
T.ToTensor(),
normalize
])
img=torch.unsqueeze(transforms(image),0)
img=img.to(device)
out=model_vgg16(img)
print(out)
_,predic=torch.max(out.data,dim=1)
print(predic)
##################################
这段代码与上一段代码类似,不同之处在于它使用了另一张图像进行预测。首先,定义了一张图像的路径,并使用PIL库中的Image类打开图像文件。然后,定义了一个图像预处理流程,包括缩放、居中裁剪、转换为张量和归一化。接着,对图像进行预处理,并使用torch.unsqueeze
函数在第一个维度上添加一个维度,使其形状变为(1, C, H, W)
。然后,将图像转移到计算设备上,并使用模型进行前向传播,得到预测结果。最后,使用torch.max
函数获取预测结果中概率最大的类别,并打印出来。
##################################
path='./corn weed datasets/cirsium setosum/IMG_20160702_065655.jpg'
image=Image.open(path)
normalize = T.Normalize(mean=[0.5605, 0.5399, 0.4873], std=[0.1603, 0.1647, 0.1739])
transforms = T.Compose([
T.Resize(256),
T.CenterCrop(224),
T.ToTensor(),
normalize
])
img=torch.unsqueeze(transforms(image),0)
img=img.to(device)
out=model_vgg16(img)
print(out)
_,predic=torch.max(out.data,dim=1)
print(predic)
##################################
这段代码与上一段代码类似,不同之处在于它使用了另一张图像进行预测。首先,定义了一张图像的路径,并使用PIL库中的Image类打开图像文件。然后,定义了一个图像预处理流程,包括缩放、居中裁剪、转换为张量和归一化。接着,对图像进行预处理,并使用torch.unsqueeze
函数在第一个维度上添加一个维度,使其形状变为(1, C, H, W)
。然后,将图像转移到计算设备上,并使用模型进行前向传播,得到预测结果。最后,使用torch.max
函数获取预测结果中概率最大的类别,并打印出来。
##################################
'''验证集'''
total=0.0
correct=0.0
# optimizer=torch.optim.Adam(model_vgg16.parameters(),lr=0.0001)
val_loader=DataLoader(val_dataset,batch_size=16,shuffle=False,num_workers=0)
for j ,data in enumerate(val_loader):
image,label = data
image=image.cuda()
label=np.asarray(label, dtype = float)
label=torch.tensor(label)
label=label.cuda()
# optimizer.zero_grad()
model_vgg16=model_vgg16.cuda()
out = model_vgg16(image)
_,predict = torch.max(out.data, dim=1)
total+=label.size(0)
correct+=(predict==label).sum().item()
correct_val=correct/total
print('模型在验证集的正确率为{}%'.format(correct_val*100))
##################################
这段代码实现了模型在验证集上的评估过程。首先,定义了两个变量total
和correct
,用于统计模型在验证集上的准确率。然后,使用DataLoader
类创建一个数据加载器,用于加载验证集中的数据。接着,遍历验证集中的所有数据。对于每批数据,将其转移到计算设备上,并使用模型进行前向传播,得到预测结果。然后,使用torch.max
函数获取预测结果中概率最大的类别,并与标签进行比较,统计模型在验证集上的准确率。最后,在所有数据遍历完成后,打印出模型在验证集上的准确率。
##################################
这些代码实现了一个基于深度学习的田间杂草识别项目。首先,定义了一些函数和类,用于读取数据、构建数据集和定义模型。然后,使用这些函数和类读取数据、构建数据集、初始化模型并进行训练。在训练过程中,使用交叉熵损失函数计算模型的损失,并使用随机梯度下降优化器更新模型的权重。在每一轮训练结束后,使用测试集对模型进行评估,并保存最优模型的权重。最后,在所有轮训练结束后,使用验证集对模型进行最终评估,并打印出结果。
##################################