赞
踩
目录
4、预测结果展示:
(1)首次使用GPU进行网络加速训练。
(2)使用了ReLU激活函数,而不是传统的Sigmoid激活函数以及Tanh激活函数。
(3)使用了LRN局部响应归一化。
(4)在全连接层的前两层中使用了Dropout随机失活神经元操作,以减少过拟合。
- import torch
- import torch.nn as nn
-
- '''
- AlexNet网络的亮点:
- ①首次利用GPU进行网络加速训练。(2012年)
- ②使用了RuLU激活函数,而不是传统的Sigmoid激活函数以及Tanh激活函数。
- ③使用了LRN局部响应归一化。
- ④在全连接层的前两层中使用了Dropout随机失活神经元操作,以减少过拟合!!!。
-
- '''
- class AlexNet(nn.Module):
- def __init__(self,num_classes=1000, init_weights=False): # init_weights=False 初始化权重
- super(AlexNet, self).__init__()
- self.features = nn.Sequential( # 将一系列打包nn.Sequential()精简代码
- nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2), # input[3,224,224] output[48,55,55]
- nn.ReLU(inplace=True), # inplace=True 增加计算量,减少内存使用
- nn.MaxPool2d(kernel_size=3, stride=2),
-
- nn.Conv2d(48, 128, kernel_size=5, padding=2),
- nn.ReLU(inplace=True),
- nn.MaxPool2d(kernel_size=3, stride=2),
-
- nn.Conv2d(128, 192, kernel_size=3, padding=1),
- nn.ReLU(inplace=True),
-
- nn.Conv2d(192,192,kernel_size=3,padding=1),
- nn.ReLU(inplace=True),
-
- nn.Conv2d(192,128,kernel_size=3,padding=1),
- nn.ReLU(inplace=True),
- nn.MaxPool2d(kernel_size=3, stride=2)
- )
- self.classifier = nn.Sequential(
- nn.Dropout(p=0.5), # p=0.5 随机失活的参数 ( 默认为0.5 )
- nn.Linear(128 * 6 * 6, 2048), # 全连接层
- nn.ReLU(inplace=True), # 激活函数
-
- nn.Dropout(p=0.5),
- nn.Linear(2048,2048),
- nn.ReLU(inplace=True),
-
- nn.Linear(2048, num_classes)
- )
- if init_weights: # 初始化权重函数
- self._initialize_weights()
-
- def forward(self,x):
- x = self.features(x)
- x = torch.flatten(x, start_dim=1) # 展平处理.
- x = self.classifier(x)
- return x
-
- def _initialize_weights(self): # 初始化权重的函数
- for m in self.modules(): # self.modules() 继承了nn.Module这个函数;会遍历每一个层结构
- if isinstance(m, nn.Conv2d): # 判断层结构是否是卷积层
- nn.init.kaiming_normal_(m.weight, mode='fan_in') # 使用kaiming_normal_()这个权重对w进行初始化
- if m.bias is not None: # 如果偏置不为空,就用0对其进行初始化
- nn.init.constant_(m.bias,0) # 对其偏置初始化为0
- elif isinstance(m, nn.Linear):
- nn.init.normal_(m.weight, 0, 0.01) # 通过正态分布,对其进行赋值;均值为0;方差为0.01
- nn.init.constant_(m.bias, 0) # 对其偏置,初始化为0
- import json
- import os.path
- import time
-
- import matplotlib.pyplot as plt
- import numpy as np
- import torch
- from torch import nn, optim
- from torchvision import datasets, utils
- from torchvision.transforms import transforms
-
- from model import AlexNet
-
- device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
- print(device)
-
- data_transform = {
- 'train': transforms.Compose([transforms.RandomResizedCrop(224), # 随机裁剪224x224大小
- transforms.RandomHorizontalFlip(), # 水平方向上进行随机反转
- transforms.ToTensor(), # 转化成tensor
- transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))]), # 标准化处理
- 'val': transforms.Compose([transforms.Resize((224,224)),
- transforms.ToTensor(),
- transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])
- }
-
- data_root = os.path.abspath(os.path.join(os.getcwd())) # 获取当前文件所在的目录
- image_path = data_root+'/flower_data/' # flower的路径地址
- print("image_path",image_path)
- # 获取训练集数据
- train_dataset = datasets.ImageFolder(root=image_path+'/train',
- transform=data_transform['train']) # transform数据预处理,上面定义的
- train_num = len(train_dataset) # 训练的数量个数
-
- flower_list = train_dataset.class_to_idx # {'daisy': 0, 'dandelion': 1, 'roses': 2, 'sunflowers': 3, 'tulips': 4}
- cla_dict = dict((val,key) for key,val in flower_list.items()) # 将其键值对反过来。 {0: 'daisy', 1: 'dandelion', 2: 'roses', 3: 'sunflowers', 4: 'tulips'}
- json_str = json.dumps(cla_dict, indent=4) # 转换成json的格式; indent=4 表示前面空4格
- with open('class_indices.json', 'w') as json_file: # 将上面生成的json_str 的格式,存入到class_indices.json文件中
- json_file.write(json_str)
-
-
- batch_size = 32
- # 加载训练集数据
- train_loader = torch.utils.data.DataLoader(train_dataset,
- batch_size=batch_size,
- shuffle=True,
- num_workers=0)
- # 获取测试集数据
- validate_dataset = datasets.ImageFolder(root=image_path+'/val',
- transform=data_transform['val'])
- val_num = len(validate_dataset) # 训练集的数量
-
- # 加载训练集数据
- validate_loader = torch.utils.data.DataLoader(validate_dataset,
- batch_size=batch_size,
- shuffle=False,
- num_workers=0)
-
- # # 测试查看下 数据集 → 把validate_loader里面的batch_size改为4
- # test_image,test_label = next(iter(validate_loader))
- #
- #
- # def imshow(img):
- # img = img / 2 + 0.5 # unnormalize
- # npimg = img.numpy()
- # plt.imshow(np.transpose(npimg,(1,2,0)))
- # plt.show()
- #
- # print(' '.join('%5s' % cla_dict[test_label[j].item()] for j in range(4)))
- # imshow(utils.make_grid(test_image))
-
-
- # 实例化
- net = AlexNet(num_classes=5, init_weights=True)
-
- net.to(device) # 将网络指定到,设置的device上面
- loss_function = nn.CrossEntropyLoss() # 定义损失函数(损失交叉熵函数)
- optimizer = optim.Adam(net.parameters(),lr=0.0002) # 定义优化器,使用Adam优化器,优化对象是网络中所有的可训练的参数
-
- save_path = './AlexNet.pth' # 保存地址
- best_acc = 0.0 # 保存学习率最高的那次训练的模型
- for epoch in range(10):
- # train
- net.train() # 使用net.train() 和net.eval()方法管理DropOut()方法; 调用net.train()会启动调用DropOut()方法; net.eval()关闭调用DropOut()方法
- running_loss = 0.0 # 计算训练过程中的损失
- t1 = time.perf_counter()
- for step, data in enumerate(train_loader, start=0):
- images, labels = data
- optimizer.zero_grad() # 清空梯度信息
- outputs = net(images.to(device)) # 将图片指定到device上
- loss = loss_function(outputs, labels.to(device))
- loss.backward() # 反向传播,到每个节点
- optimizer.step() # 更新参数
-
- running_loss += loss.item()
-
- # 打印训练过程的进度条
- rate = (step+1) / len(train_loader)
- a = '*'*int(rate*50)
- b = '.'*int((1-rate)*50)
- print("\rtrain loss:{:^3.0f}% [{}->{}]{:.3f}".format(int(rate*100), a, b, loss), end="")
- print()
- print(time.perf_counter()-t1)
-
- # validate 验证集
- net.eval() # 关闭调用DropOut()方法
- acc = 0.0
- with torch.no_grad():
- for data_test in validate_loader:
- test_images, test_labels = data_test
- outputs = net(test_images.to(device))
- predict_y = torch.max(outputs, dim=1)[1]
- acc += (predict_y == test_labels.to(device)).sum().item()
- accurate_test = acc / val_num
- if accurate_test > best_acc: # 获得最优准确率
- best_acc = accurate_test
- torch.save(net.state_dict(), save_path)
- print('[epoch %d] train_loss:%.3f test_accuracy:%.3f' % (epoch+1, running_loss/step, acc/val_num))
-
- print('Finished Training')
训练文件运行结果:
结果展示,训练的损失在下降,测试的准确率最高达到72%。
- import torch
- from model import AlexNet
- from PIL import Image
- from torchvision import transforms
- import matplotlib.pyplot as plt
- import json
-
- # 定义图片预处理函数
- data_transform = transforms.Compose(
- [transforms.Resize((224,224)), # 将图片缩放到224x224
- transforms.ToTensor(), # 转换成tensor格式
- transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))] # 标准化处理
- )
-
- # 加载图片
- img = Image.open('./tulip.jpg')
- plt.imshow(img)
- # [N,C,H,W]
- img = data_transform(img) # 对图片进行预处理(上面定义的)
-
- # 扩充一个维度
- img = torch.unsqueeze(img, dim=0)
-
-
- # 读取之前保存的.json文件
- try:
- json_file = open('./class_indices.json', 'r')
- class_indict = json.load(json_file)
- except Exception as e:
- print(e)
- exit(-1)
-
- # 创建model
- model = AlexNet(num_classes=5)
- # 加载模型权重
- model_weight_path = './AlexNet.pth'
-
- model.load_state_dict(torch.load(model_weight_path))
- model.eval()
- # 不跟踪变量的损失梯度
- with torch.no_grad():
- output = torch.squeeze(model(img)) # 维度压缩
- predict = torch.softmax(output, dim=0)
- predict_cla = torch.argmax(predict).numpy() # 概率最大数
- print(class_indict[str(predict_cla)], predict[predict_cla].item()) # 打印预测名称,预测概率
- plt.show()
①给定的图片:
预测结果:(预测结果正确,显示87%的概率是郁金香)
②给定图片:
预测结果:(预测结果正确,显示99.7%的概率为向日葵)
至此,我们使用AlexNet搭建的神经网络结构,预测flower分类,就暂时到这里啦。
代码,我是在服务器上面跑的,我的本地实在带动不起来,电脑配置不给力。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。