太原网站建设最好,长春企业网站建设,烟台seo管理,电子商务网站的实施包括哪些步骤一、数据集下载
下载地址#xff1a;https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
下载解压后#xff0c;有如下5个目录#xff0c;每个目录中放的是对应花卉类别的图片二、导入需要的库
from torch.utils.data import Datase…一、数据集下载下载地址https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz下载解压后有如下5个目录每个目录中放的是对应花卉类别的图片二、导入需要的库fromtorch.utils.dataimportDataset,DataLoader,ConcatDatasetfromtorchvisionimporttransformsfromPILimportImageimporttorch,os,shutilimporttorch.nnasnnfromtorchinfoimportsummaryimportrandomfromtorch.optim.lr_schedulerimportExponentialLRimporttorch.optimasoptim三、拆分数据集拆分思路按8:1:1的比例将原始数据拆分为训练集、验证集、测试集。训练集用于模型的参数学习验证集用于监控训练过程、参数调优测试集用于评估模型的泛化能力。方法新建3个目录train、test、predict每个目录下的分类文件夹与原目录相同从原目录中复制或移动文件到新目录。为什么要保留原始的分类目录为了在构造数据集的时候能知道每个图片的分类–也就是标签。代码实现#随机将文件按比例分配到3个目录defsplit_files_randomly(source_dir,dir1,dir2,dir3,ratio0.8): source_dir: 源目录 dir1: 目录1存放80% dir2: 目录2存放10% dir3: 目录3存放10% ratio: 分配到目录1的比例 # 创建目标目录os.makedirs(dir1,exist_okTrue)os.makedirs(dir2,exist_okTrue)os.makedirs(dir3,exist_okTrue)# 获取所有文件files[fforfinos.listdir(source_dir)ifos.path.isfile(os.path.join(source_dir,f))]random.shuffle(files)#随机打乱文件列表# 计算分割点split_point1int(len(files)*ratio)split_point2split_point1int((1-ratio)/2*len(files))# 复制文件到目录1 (80%)fori,fileinenumerate(files[:split_point1]):srcos.path.join(source_dir,file)dstos.path.join(dir1,file)shutil.copy(src,dst)# 使用copy复制文件# 复制文件到目录2 (10%)fori,fileinenumerate(files[split_point1:split_point2]):srcos.path.join(source_dir,file)dstos.path.join(dir2,file)shutil.copy(src,dst)# 复制文件到目录3 (10%)fori,fileinenumerate(files[split_point2:]):srcos.path.join(source_dir,file)dstos.path.join(dir3,file)shutil.copy(src,dst)#使用copy复制文件print(f找到{len(files)}个文件,,end)print(f目录1:{split_point1}个文件目录2:{split_point2-split_point1}个文件,目录3{len(files)-split_point2}个文件)调用代码如下if__name____main__:#将原始文件按8:1:1统一放到train、test、predict的对应类别文件下#输出结果找到 633 个文件,目录1: 506 个文件目录2: 63 个文件,目录364个文件split_files_randomly(source_dir./flowers/daisy,dir1./flowers/train/daisy,dir2./flowers/test/daisy,dir3./flowers/predict/daisy)#输出结果找到 898 个文件,目录1: 718 个文件目录2: 89 个文件,目录391个文件split_files_randomly(source_dir./flowers/dandelion,dir1./flowers/train/dandelion,dir2./flowers/test/dandelion,dir3./flowers/predict/dandelion)#输出结果找到 641 个文件,目录1: 512 个文件目录2: 64 个文件,目录365个文件split_files_randomly(source_dir./flowers/roses,dir1./flowers/train/roses,dir2./flowers/test/roses,dir3./flowers/predict/roses)#输出结果找到 699 个文件,目录1: 559 个文件目录2: 69 个文件,目录371个文件split_files_randomly(source_dir./flowers/sunflowers,dir1./flowers/train/sunflowers,dir2./flowers/test/sunflowers,dir3./flowers/predict/sunflowers)#输出结果找到 799 个文件,目录1: 639 个文件目录2: 79 个文件,目录381个文件split_files_randomly(source_dir./flowers/tulips,dir1./flowers/train/tulips,dir2./flowers/test/tulips,dir3./flowers/predict/tulips)四、数据预处理查看原始图片发现数据集的质量差比如大小尺寸不一最重要的是部分图片提取不到花的特征比如所以使用一些数据增强的手段对训练数据进行处理提高模型的泛化能力。方法利用torchvision.transforms.Compose代码实现如下#训练集需要数据增强train_transformtransforms.Compose([transforms.Resize(300),# 先放大到300×300确保大于裁剪尺寸transforms.RandomHorizontalFlip(),#以50%默认的概率对图像进行水平翻转transforms.RandomRotation(degrees20),#在[-20°, 20°]范围内随机选择一个角度对图像进行旋转transforms.RandomCrop(256),# 随机选择一个左上角坐标裁剪出一个 256×256 的正方形区域transforms.RandomGrayscale(0.1),#以10%的概率将彩色图像转换为灰度图像并将灰度图扩展为 3 通道即 RGB保持通道数与原始 RGB 图像一致transforms.ToTensor(),#将PIL 图像转换为PyTorch 张量Tensor神经网络的输入格式要求transforms.Normalize(mean[0.485,0.456,0.406],std[0.229,0.224,0.225])#对张量进行标准化归一化处理])#测试集不用数据增强手段test_transformtransforms.Compose([transforms.Resize((256,256)),#将图像直接缩放到 256×256 的固定尺寸transforms.ToTensor(),transforms.Normalize(mean[0.485,0.456,0.406],std[0.229,0.224,0.225])#测试集的标准化参数需要与训练集相同])#构造数据集classFlowerDataset(Dataset):def__init__(self,dir_path,transformNone):super().__init__()self.transformtransform subdirsos.listdir(dir_path)#子目录名self.files[]#所有文件的路径forsubdirinsubdirs:#subdir子文件夹对应花卉类别file_path[f{dir_path}/{subdir}/{file}forfileinos.listdir(f{dir_path}/{subdir})]self.files.extend(file_path)def__getitem__(self,index):imageself.transform(Image.open(self.files[index]))file_nameself.files[index]#file_name是图片完整的路径比如./flowers/train/roses/xxx.png#如果文件路径中包含对应关键词原始分类目录给图片一个标签ifdaisyinfile_name:label0elifdandelioninfile_name:label1elifrosesinfile_name:label2elifsunflowersinfile_name:label3eliftulipsinfile_name:label4else:passreturnimage,label# image的形状是torch.Size([3, 256, 256])取决于transforms.Compose处理后的形状def__len__(self):returnlen(self.files)五、构造AlexNet模型AlexNet模型的结构本次实现代码如下classFlowerAlexNet(nn.Module):def__init__(self):super().__init__()self.featuresnn.Sequential(nn.Conv2d(in_channels3,out_channels96,kernel_size11,stride4,padding2),nn.BatchNorm2d(96),# 加的BatchNorm2d加速收敛不是AlexNet模型里的nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size3,stride2),nn.Conv2d(in_channels96,out_channels256,kernel_size5,padding2),nn.BatchNorm2d(256),nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size3,stride2),nn.Conv2d(in_channels256,out_channels384,kernel_size3,padding1),nn.BatchNorm2d(384),nn.ReLU(inplaceTrue),nn.Conv2d(in_channels384,out_channels384,kernel_size3,padding1),nn.BatchNorm2d(384),nn.ReLU(inplaceTrue),nn.Conv2d(in_channels384,out_channels256,kernel_size3,padding1),nn.BatchNorm2d(256),nn.ReLU(inplaceTrue),nn.MaxPool2d(kernel_size3,stride2),)# 全连接层self.classifiernn.Sequential(nn.Dropout(0.5),nn.Flatten(),nn.Linear(in_features7*7*256,out_features4096),# 全连接的第一层输入是卷积输出的拉平值即6*6*256nn.ReLU(inplaceTrue),nn.Dropout(p0.5),nn.Linear(4096,4096),nn.ReLU(inplaceTrue),nn.Dropout(0.5),nn.Linear(4096,5)#花卉只有5个类别改成5)# 前向算法defforward(self,x):xself.features(x)xself.classifier(x)returnx六、训练和测试采用的是同时对训练集进行训练、对验证集进行测试的方式deftrain_and_test(epochs):#构造数据集train_dsFlowerDataset(dir_path./flowers/train,transformtrain_transform)#训练集train_dlDataLoader(train_ds,batch_size32,shuffleTrue,drop_lastTrue)#分批test_dsFlowerDataset(dir_path./flowers/test,transformtest_transform)#验证集test_dlDataLoader(test_ds,batch_size20,shuffleFalse,drop_lastTrue)#分批modelFlowerAlexNet().to(device)#加载到gpu上运行device会在调用的时候定义为全局变量print(summary(model))#查看模型结构感兴趣可以打印出来看看criterionnn.CrossEntropyLoss()# 损失函数多分类交叉熵损失optimizeroptim.SGD(model.parameters(),lr0.01,momentum0.9)#SGD优化器随机梯度下降lr0.01学习率momentum0.9动量schedulerExponentialLR(optimizer,gamma0.9)#指数学习率衰减每个epoch后学习率乘以gamma0.9forepochinrange(epochs):train_loss,train_acc[],[]# 记录训练损失和准确率#训练model.train()#设置为训练模式fordata,labelintrain_dl:data,labeldata.to(device),label.to(device)# 数据移动到GPUoptimizer.zero_grad()# 梯度清零outputmodel(data)#前向传播losscriterion(output,label)# 计算损失loss.backward()# 反向传播optimizer.step()# 参数更新train_loss.append(loss.item())y_predoutput.argmax(dim1)# 取概率最大的类别作为预测correct_count(y_predlabel).sum().item()/len(label)#计算当前批次的准确率train_acc.append(correct_count)# 计算每一轮平均训练损失和准确率avg_losssum(train_loss)/len(train_loss)avg_accsum(train_acc)/len(train_acc)print(f第{epoch1}轮,训练集损失{avg_loss:.4f},准确率{avg_acc:.4f})scheduler.step()# 每个epoch结束时调用scheduler的step()方法更新学习率#print(f第 {epoch 1} 轮学习率为, optimizer.param_groups[0][lr])#优化器的学习率感兴趣可以打印出来看#测试model.eval()#设置为评估模式test_loss,test_acc[],[]#计算损失和准确率withtorch.no_grad():# 禁用梯度计算forxt,ytintest_dl:x_test,y_testxt.to(device),yt.to(device)y_test_predmodel(x_test)losscriterion(y_test_pred,y_test)test_loss.append(loss.item())correct_count(y_test_pred.argmax(dim1)y_test).sum().item()test_acc.append(correct_count)avg_test_losssum(test_loss)/len(test_dl)avg_test_accsum(test_acc)/len(test_dl.dataset)print(f第{epoch1}轮,测试集损失{avg_test_loss:.4f},准确率{avg_test_acc:.4f})returnmodel这段代码的逻辑开始训练↓for epoch in range(epochs):↓设置 model.train() 模式↓for batch in train_dataloader:↓数据移动到GPU → 梯度清零 → 前向传播 → 计算损失↓反向传播 → 参数更新 → 记录统计↓计算epoch平均训练损失和准确率↓设置 model.eval() 模式 torch.no_grad()↓for batch in test_dataloader:↓前向传播 → 计算损失 → 记录统计↓计算epoch平均测试损失和准确率↓更新学习率 scheduler.step()↓返回训练好的模型七、推理对测试集predict目录进行推理labels[daisy,dandelion,roses,sunflowers,tulips]#定义全局变量defpredict(model,files_path):model.eval()#评估模式count,sum0,0#count为预测准确的数量sum为总数量withtorch.no_grad():#禁用梯度计算forsubdirinos.listdir(files_path):#循环predict下的每个子目录file_listos.listdir(f{files_path}/{subdir})#获取每个子目录的文件sumlen(file_list)#计算图片总数forfileinfile_list:#处理单张图像file_pathf{files_path}/{subdir}/{file}#构建文件路径比如file_path ./flowers/predict/daisy/xx.jpgimagetest_transform(Image.open(file_path)).to(device)#加载并预处理图像,移动到GPUy_predmodel(image.unsqueeze(0))#添加批次维度:在维度0添加一个维度再给模型推理y_predy_pred.squeeze().view(1,5)#squeeze()去除维度为1的维度再变回[1,5]y_maxy_pred.argmax(dim1)#找到最大概率的类别也就是预测的分类predlabels[y_max.item()]#转换为类别名称print(f真实{subdir},预测结果{pred},{subdirpred})count(subdirpred)#统计预测正确的数量print(f准确率为{count/sum})returncount/sum八、调用代码if__name____main__:devicetorch.device(cudaiftorch.cuda.is_available()elsecpu)#设备选择train_modeltrain_and_test(100)#训练模型100轮torch.save(train_model.state_dict(),./flower_model-5.pth)#保存模型modelFlowerAlexNet().to(device)#创建新的模型实例并移动到GPU上model.load_state_dict(torch.load(./flower_model-5.pth))#模型加载predict(model,files_path./flowers/predict)模型推理九、结果训练结果推理结果