美文网首页
pytorch学习记录-alexnet

pytorch学习记录-alexnet

作者: jyx2 | 来源:发表于2020-07-20 18:14 被阅读0次

    \color{red}{1.读取数据}
    https://blog.csdn.net/sinat_42239797/article/details/90641659

    #***************************一些必要的包的调用********************************
    import torch.nn.functional as F
    import torch
    import torch 
    import torch.nn as nn
    from torch.autograd import Variable
    import torchvision.models as models
    from torchvision import transforms, utils
    from torch.utils.data import Dataset, DataLoader
    from PIL import Image
    import numpy as np
    import torch.optim as optim
    import os
    #***************************初始化一些函数********************************
    #torch.cuda.set_device(gpu_id)#使用GPU
    learning_rate = 0.0001#学习率的设置
    
    #*************************************数据集的设置****************************************************************************
    root =os.getcwd()+"\\"#数据集的地址
    #定义读取文件的格式
    def default_loader(path):
        return Image.open(path).convert('RGB')
    
    class MyDataset(Dataset): 
                                     #创建自己的类: MyDataset,这个类是继承的torch.utils.data.Dataset
            #**********************************  #使用__init__()初始化一些需要传入的参数及数据集的调用**********************
        def __init__(self,txt, transform=None,target_transform=None, loader=default_loader):
    
            super(MyDataset,self).__init__()
            imgs = []
                               #对继承自父类的属性进行初始化
            fh = open(txt, 'r')
                        #按照传入的路径和txt文本参数,以只读的方式打开这个文本
            for line in fh: #迭代该列表#按行循环txt文本中的内
                line = line.strip('\n')
                line = line.rstrip('\n')
                    # 删除 本行string 字符串末尾的指定字符,这个方法的详细介绍自己查询python
                words = line.split()
                      #用split将该行分割成列表  split的默认参数是空格,所以不传递任何参数时分割空格
                imgs.append((words[0],int(words[1])))
                     #把txt里的内容读入imgs列表保存,具体是words几要看txt内容而定 
                            # 很显然,根据我刚才截图所示txt的内容,words[0]是图片信息,words[1]是lable       
            self.imgs = imgs
            self.transform = transform
            self.target_transform = target_transform
            self.loader = loader        
                    #*************************** #使用__getitem__()对数据进行预处理并返回想要的信息**********************
        def __getitem__(self, index):#这个方法是必须要有的,用于按照索引读取每个元素的具体内容
            fn, label = self.imgs[index]
                           #fn是图片path #fn和label分别获得imgs[index]也即是刚才每行中word[0]和word[1]的信息
            img = self.loader(fn) 
                          # 按照路径读取图片
            if self.transform is not None:
                img = self.transform(img) 
                            #数据标签转换为Tensor
            return img,label
                          #return回哪些内容,那么我们在训练时循环读取每个batch时,就能获得哪些内容
             #**********************************  #使用__len__()初始化一些需要传入的参数及数据集的调用**********************
        def __len__(self):
                #这个函数也必须要写,它返回的是数据集的长度,也就是多少张图片,要和loader的长度作区分
            return len(self.imgs)
    train_data=MyDataset(txt=root+'train.txt', transform=transforms.ToTensor())
    test_data = MyDataset(txt=root+'text.txt', transform=transforms.ToTensor())
    #然后就是调用DataLoader和刚刚创建的数据集,来创建dataloader,这里提一句,loader的长度是有多少个batch,所以和batch_size有关
    train_loader = DataLoader(dataset=train_data, batch_size=32, shuffle=True,num_workers=0)
    test_loader = DataLoader(dataset=test_data, batch_size=32, shuffle=False,num_workers=0)
    print('num_of_trainData:', len(train_loader))
    print('num_of_testData:', len(test_loader))
    

    要使用上面的代码,首先要制作供调用的txt文件,我的文件夹里面的内容是这样的


    我的文件夹.JPG

    train里面的数据如下,一共10类,10个数字,我预先resize成224x224


    train文件夹.JPG

    用的制作txt的代码如下

    import os
    
    dir = 'D:/cv/TEST/alexnet/test/'#图片文件的地址
    #os.listdir的结果就是一个list集,可以使用list的sort方法来排序。如果文件名中有数字,就用数字的排序
    files = os.listdir(dir)#列出dirname下的目录和文件
    files.sort()#排序
    text = open('./text.txt', 'a')
    for file in files:
        label = file.split('.')[0].split('_')[-1]
        name = str(dir) +file + ' ' + label +'\n'
        text.write(name)
    text.close()
    
    dir = 'D:/cv/TEST/alexnet/train/'#图片文件的地址
    #os.listdir的结果就是一个list集,可以使用list的sort方法来排序。如果文件名中有数字,就用数字的排序
    files = os.listdir(dir)#列出dirname下的目录和文件
    files.sort()#排序
    train = open('./train.txt','a')
    for file in files:
        label = file.split('.')[0].split('_')[-1]
        name = str(dir) +file + ' ' + label +'\n'
        train.write(name)
    train.close()
    
    dir = 'D:/cv/TEST/alexnet/vaild/'#图片文件的地址
    #os.listdir的结果就是一个list集,可以使用list的sort方法来排序。如果文件名中有数字,就用数字的排序
    files = os.listdir(dir)#列出dirname下的目录和文件
    files.sort()#排序
    vaild = open('./vaild.txt','a')
    for file in files:
        label = file.split('.')[0].split('_')[-1]
        name = str(dir) +file + ' ' + label +'\n'
        vaild.write(name)
    vaild.close()
    

    \color{red}{2.模型构建}
    用的是官网的模型,没有想到pytorch做模型怎么简单
    https://pytorch.org/docs/master/_modules/torchvision/models/alexnet.html#alexnet

    class AlexNet(nn.Module):
    
        def __init__(self, num_classes=1000):
            super(AlexNet, self).__init__()
            self.features = nn.Sequential(
                nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2),
                nn.Conv2d(64, 192, kernel_size=5, padding=2),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2),
                nn.Conv2d(192, 384, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),
                nn.Conv2d(384, 256, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),
                nn.Conv2d(256, 256, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2),
            )
            self.avgpool = nn.AdaptiveAvgPool2d((6, 6))
            self.classifier = nn.Sequential(
                nn.Dropout(),
                nn.Linear(256 * 6 * 6, 4096),
                nn.ReLU(inplace=True),
                nn.Dropout(),
                nn.Linear(4096, 4096),
                nn.ReLU(inplace=True),
                nn.Linear(4096, num_classes),
            )
    
        def forward(self, x):
            x = self.features(x)
            x = self.avgpool(x)
            x = torch.flatten(x, 1)
            x = self.classifier(x)
            return x
    

    \color{red}{3.训练}

    net = AlexNet()
    net.cuda()
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
    """
    ###画图
    import matplotlib.pyplot as plt
    import numpy as np
    import torchvision
    
    # functions to show an image
    
    
    def imshow(img):
        img = img / 2 + 0.5     # unnormalize
        npimg = img.numpy()
        plt.imshow(np.transpose(npimg, (1, 2, 0)))
        plt.show()
    
    
    # get some random training images
    dataiter = iter(train_loader)
    images, labels = dataiter.next()
    # show images
    print(images[0])
    imshow(torchvision.utils.make_grid(images[0]))
    # print labels
    print(' '.join('%5s' % labels[j] for j in range(32)))
    ###画图结束
    """
    # 训练网络
    # 迭代epoch
    for epoch in range(30):
        running_loss = 0.0
        for i, data in enumerate(train_loader, 0):
            # get the input
            inputs, labels = data
            # zeros the paramster gradients
            optimizer.zero_grad()       # 
            # print(inputs)
            # forward + backward + optimize
            outputs = net(inputs.cuda())
            loss = criterion(outputs, labels.cuda())  # 计算loss
            #print(outputs,labels)
            loss.backward()     # loss 求导
            optimizer.step()    # 更新参数
    
            # print statistics
            running_loss += loss.item()  # tensor.item()  获取tensor的数值
            if i % 50 == 49:
                print('[%d, %5d] loss: %.3f' %
                      (epoch + 1, i + 1, running_loss / 5))  # 每2000次迭代,输出loss的平均值
                running_loss = 0.0
    
    print('Finished Training')
    

    \color{red}{4.保存}

    # 保存
    torch.save(net, 'model.pth')
    

    \color{red}{5.提取和测试}

    def evaluteTop1(model, loader):
        model.eval()
        correct = 0
        total = len(loader.dataset)
        for x,y in loader:
            x,y = x.cuda(), y.cuda()
            with torch.no_grad():
                logits = model(x)
                pred = logits.argmax(dim=1)
                correct += torch.eq(pred, y).sum().float().item()
            #correct += torch.eq(pred, y).sum().item()
        return correct / total
    model = AlexNet()
    model = torch.load('model.pth')
    print(evaluteTop1(model,test_loader))
    """
    ###错误的图片,要上面的imshow代码
    #net.eval()
    eval_loss = 0.
    eval_acc = 0.
    errorimg = []
    for i, data in enumerate(test_loader, 0):
        inputs, labels = data
        outputs = model(inputs.cuda())
        pred = torch.max(outputs, 1)[1]
        for i in range(len(labels)):
            if labels[i] != pred[i]:
                errorimg.append(inputs[i])
    imshow(torchvision.utils.make_grid(errorimg))
    ###
    """
    

    \color{red}{6.用到的数据}
    图片及处理代码和很潦草的jupyter文件
    链接: https://pan.baidu.com/s/19sA7brPbKbv9tPByuY2Rkw 提取码: t2ih 复制这段内容后打开百度网盘手机App,操作更方便哦
    训练出的模型
    链接: https://pan.baidu.com/s/1WAevnAAJA8J5JHWaStJ_NQ 提取码: b9we

    相关文章

      网友评论

          本文标题:pytorch学习记录-alexnet

          本文链接:https://www.haomeiwen.com/subject/ifvykktx.html