pytorch学习记录-alexnet

\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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351