AlexNet花分类实践
AlexNet实现花分类(记录)
理论
AlexNetAlexNet由LeNet演变而来,使用了八层卷积网络:五个卷积层、三个全连接层,以ReLU激活函数代替sigmoid激活函数,并引入Dropout,每次训练中随机失活一定比例的神经元,防止过拟合的发生。
过拟合由于特征维度过多,模型假设过于复杂,参数过多,训练数据过少,噪声过多,导致拟合的函数完美的预测训练集,但对新数据的测试集预测结果差。过度地拟合了训练数据,而没有考虑到模型的泛化能力。
模型
AlexNet模型由数据集、model、train三个部分组成,在python3.11环境下运行,引入了pytorch。
model.pyimport torch.nn as nn import torch class AlexNet(nn.Module): def __init__(self, num_classes=1000, init_weights=False): super(AlexNet, self).__init__() # pack the net as one self.features = nn.Sequential( # extract features with convolution nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2), # input[3, 224, 224] output[48, 55, 55] nn.ReLU(inplace=True), # cover the origin key to reduce the usage of RAM nn.MaxPool2d(kernel_size=3, stride=2), # output[48, 27,27] nn.Conv2d(48, 128, kernel_size=5, padding=2), # output[128, 27, 27] nn.ReLU(inplace=True), # reduce usage of RAM nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 13, 13] nn.Conv2d(128, 192, kernel_size=3, padding=1), # output[192, 13, 13] nn.ReLU(inplace=True), # reduce usage of RAM nn.Conv2d(192, 192, kernel_size=3, padding=1), # output[192, 13, 13] nn.ReLU(inplace=True), nn.Conv2d(192, 128, kernel_size=3, padding=1), # output[128,13,13] nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=3, stride=2), # output[128, 6, 6] ) self.classifier = nn.Sequential( # FC nn.Dropout(p=0.5), # randomly inactive some neurons 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() # forward trans def forward(self, x): x = self.features(x) x = torch.flatten(x, start_dim=1) # flatten and dense x = self.classifier(x) return x # initialize weight of the Net def _initialize_weights(self): for m in self.modules(): if isinstance(m, nn.Conv2d): # if it is conv nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') # use kaiming_normal_method to initialize the weight if m.bias is not None: nn.init.constant_(m.bias, 0) # initialize bias as 0 elif isinstance(m, nn.Linear): # if it is fc nn.init.normal_(m.weight, 0, 0.01) # initialize with normal distribution nn.init.constant_(m.bias, 0)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 train.pyimport os import sys import json import torch import time import torch.nn as nn from torchvision import transforms, datasets, utils import matplotlib.pyplot as plt import numpy as np import torch.optim as optim from tqdm import tqdm from model import AlexNet def main(): device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") print("using {} device.".format(device)) data_transform = { "train": transforms.Compose([transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), 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(), "../..")) # get data root path image_path = os.path.join(data_root, "data_set", "flower_data") # flower data set path assert os.path.exists(image_path), "{} path does not exist.".format(image_path) train_dataset = datasets.ImageFolder(root=os.path.join(image_path, "train"), transform=data_transform["train"]) train_num = len(train_dataset) # { 0:'daisy', 1:'dandelion', 2:'roses', 3:'sunflower', 4:'tulips} flower_list = train_dataset.class_to_idx cla_dict = dict((val, key) for key, val in flower_list.items()) # write dict into json file json_str = json.dumps(cla_dict, indent=4) with open('class_indices.json', 'w') as json_file: json_file.write(json_str) batch_size = 64 nw = 0 # numbers of workers print('Using {} dataloader workers every process'.format(nw)) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=nw) validate_dataset = datasets.ImageFolder(root=os.path.join(image_path, "val"), transform=data_transform["val"]) val_num = len(validate_dataset) validate_loader = torch.utils.data.DataLoader(validate_dataset, batch_size=4, shuffle=False, num_workers=nw) print("using {} images for training, {} images for validation.".format(train_num, val_num)) # test_data_iter = iter(validate_loader) # test_image, test_label = test_data_iter.next() # 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) # initialize weights net.to(device) # use device to train this net loss_function = nn.CrossEntropyLoss() # 交叉熵损失 # pata = list(net.parameters()) optimizer = optim.Adam(net.parameters(), lr=0.0002) # 优化器 epochs = 10 save_path = './AlexNet.pth' best_acc = 0.0 train_steps = len(train_loader) # train for epoch in range(epochs): net.train() # activate Dropout during training process running_loss = 0.0 # running_loss will be reset as 0 when epoch time_start = time.perf_counter() # record time for every epoch train_bar = tqdm(train_loader, file=sys.stdout) for step, data in enumerate(train_bar): # 遍历训练集, start calculate step from 0 images, labels = data # get labels of images in train optimizer.zero_grad() # 清除历史梯度 outputs = net(images.to(device)) loss = loss_function(outputs, labels.to(device)) loss = loss.requires_grad_(True) loss.backward() optimizer.step() running_loss += loss.item() # print the process and make it visible 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('%f s' % (time.perf_counter() - time_start)) # validate net.eval() # shut Dropout when validate acc = 0.0 # accumulate accurate number / epoch with torch.no_grad(): val_bar = tqdm(validate_loader, file=sys.stdout) for val_data in val_bar: val_images, val_labels = val_data outputs = net(val_images.to(device)) predict_y = torch.max(outputs, dim=1)[1] acc += torch.eq(predict_y, val_labels.to(device)).sum().item() val_accurate = acc / val_num print('[epoch %d] train_loss: %.3f val_accuracy: %.3f' % (epoch + 1, running_loss / train_steps, val_accurate)) if val_accurate > best_acc: best_acc = val_accurate torch.save(net.state_dict(), save_path) print('Finished Training') if __name__ == '__main__': main()
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 数据集处理 split_data.pyimport os from shutil import copy, rmtree import random def mk_file(file_path: str): if os.path.exists(file_path): # 如果文件夹存在,则先删除原文件夹在重新创建 rmtree(file_path) os.makedirs(file_path) def main(): # 保证随机可复现 random.seed(0) # 将数据集中10%的数据划分到验证集中 split_rate = 0.1 # 指向你解压后的flower_photos文件夹 cwd = os.getcwd() data_root = os.path.join(cwd, "flower_data") origin_flower_path = os.path.join(data_root, "flower_photos") assert os.path.exists(origin_flower_path), "path '{}' does not exist.".format(origin_flower_path) flower_class = [cla for cla in os.listdir(origin_flower_path) if os.path.isdir(os.path.join(origin_flower_path, cla))] # 建立保存训练集的文件夹 train_root = os.path.join(data_root, "train") mk_file(train_root) for cla in flower_class: # 建立每个类别对应的文件夹 mk_file(os.path.join(train_root, cla)) # 建立保存验证集的文件夹 val_root = os.path.join(data_root, "val") mk_file(val_root) for cla in flower_class: # 建立每个类别对应的文件夹 mk_file(os.path.join(val_root, cla)) for cla in flower_class: cla_path = os.path.join(origin_flower_path, cla) images = os.listdir(cla_path) num = len(images) # 随机采样验证集的索引 eval_index = random.sample(images, k=int(num*split_rate)) for index, image in enumerate(images): if image in eval_index: # 将分配至验证集中的文件复制到相应目录 image_path = os.path.join(cla_path, image) new_path = os.path.join(val_root, cla) copy(image_path, new_path) else: # 将分配至训练集中的文件复制到相应目录 image_path = os.path.join(cla_path, image) new_path = os.path.join(train_root, cla) copy(image_path, new_path) print("r[{}] processing [{}/{}]".format(cla, index+1, num), end="") # processing bar print() print("processing done!") if __name__ == '__main__': main()
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667引用声明:
split_data.py 参考CSDN @AiCharm 深度学习实战(二):AlexNet实现花图像分类
train.py 和 model.py 参考CSDN @heart_6662 pytorch——AlexNet——训练花分类数据集
理论知识参考 bilibili @霹雳吧啦Wz 深度学习-图像分类篇章
代码均在文件结构上进行过修改
相关知识
深度学习实战:AlexNet实现花图像分类
Pytorch之AlexNet花朵分类
pytorch——AlexNet——训练花分类数据集
图像分类:AlexNet网络、五分类 flower 数据集、pytorch
深度学习实战(二):AlexNet实现花图像分类
pytorch图像分类篇: 花分类数据集下载和AlexNet网络搭建训练
AlexNet实现花卉识别
第一个深度学习入门项目——使用AlexNet网络实现花分类
AlexNet网络的搭建以及训练花分类
AlexNet网络详解(实现花的种类识别)
网址: AlexNet花分类实践 https://www.huajiangbk.com/newsview1388138.html
上一篇: 我的植物朋友——制作观察记录卡 |
下一篇: 支持向量机(SVM)代码实现学习 |
推荐分享

- 1君子兰什么品种最名贵 十大名 4012
- 2世界上最名贵的10种兰花图片 3364
- 3花圈挽联怎么写? 3286
- 4迷信说家里不能放假花 家里摆 1878
- 5香山红叶什么时候红 1493
- 6花的意思,花的解释,花的拼音 1210
- 7教师节送什么花最合适 1167
- 8勿忘我花图片 1103
- 9橄榄枝的象征意义 1093
- 10洛阳的市花 1039