Pytorch_加载自己的数据集并训练

如何制作数据集txt,并进行加载

1. 根据图片制作train.txt val.txt 和 test.txt

# MakeTxt.py
"""
原始图片保存路径
**************文件保存方式  一  *******************
--data
    --train
        --category_1
        --category_2
        ...
    --val
        --category_1
        --category_2
        ...
    --test
        --category_1
        --category_2
        ...

**************文件保存方式  二  *******************
--data
    --category_1
        --001.jpg
        --002.jpg
        ...
    --category_2
        --001.jpg
        --002.jpg
        ...
    ...

"""

import os
# 【1. 获取文件绝对路径】
def get_files_path(file_dir):
    dir_names = []
    for fn in os.listdir(file_dir): #fn 表示的是文件名
        dir_names.append(os.path.join(file_dir,fn))
    print(dir_names)
    return dir_names
def get_dir_img(file_dir):
    filenames = []
    for root, dirs, files in os.walk(file_dir):
        for name in files:
            # print(os.path.join(root, name))
            filenames.append(os.path.join(root, name))
    return filenames
def make_txt(img_root,txt_root,quantity_proportion):
    """
    img_root : 图像保存路径
    txt_root : txt路径
    quantity_proportion : [train,eval,test] 各数据集的比例 eg. [0.8, 0.1, 0.1]
    """
    # 创建 txt文件
    txt_name = [txt_root + '/train.txt', txt_root +'/val.txt', txt_root + '/test.txt']
    for file_path in txt_name:
        if os.path.isfile(file_path):
            os.remove(file_path)
    train = open(txt_name[0],'a')
    val = open(txt_name[1], 'a')
    test = open(txt_name[2], 'a')
    sort_files = get_files_path(img_root)
    for i,file in enumerate(sort_files):	# 进行枚举,i为索引
        tem_total_img = get_dir_img(file)
        num_img = len(tem_total_img)
        span_num = [int(x* num_img) for x in quantity_proportion] 
        print(span_num,num_img)
        for j in range(span_num[0]+1):
            train.write(tem_total_img[j] + ' ' + str(i) + '\n')
        for k in range(span_num[0]+1,span_num[0]+span_num[1]+1):
            val.write(tem_total_img[k] + ' ' + str(i) + '\n')
        for p in range(span_num[0]+span_num[1]+1,num_img):
            test.write(tem_total_img[p] + ' ' + str(i) + '\n')
        train.close()
        val.close()
        test.close()

def main():
    quantity_proportion = [0.8, 0.1, 0.1]
    make_txt('./pokeman','./dataTxt',quantity_proportion)
    pass
if __name__=='__main__':
    main()

2. torch.utils.data.Dataset用来制作数据集

Image.open(path).convert(‘RGB’) 图片转换成RGB通道,对应后面的网络输入channel改为3

#***************************一些必要的包的调用********************************
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
#***************************初始化一些函数********************************
gpu_id =0
torch.cuda.set_device(gpu_id)#使用GPU
learning_rate = 0.0001       #学习率的设置

#*************************************数据集的设置****************************************************************************
    #定义读取文件的格式
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__()
		#对继承自父类的属性进行初始化
		fh = open(txt, 'r') 
		imgs = []  
		# 按照传入的路径和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)


def my_data_set(txt_root = './dataTxt/',batchsize=32,resize=227):
	#图像的初始化操作

	_transforms = transforms.Compose([
		transforms.RandomResizedCrop((resize,resize)),
		transforms.ToTensor(),])
	train_data = MyDataset(txt=txt_root + 'train.txt', transform=_transforms)
	test_data  = MyDataset(txt=txt_root + 'test.txt', transform=_transforms)
	val_data   = MyDataset(txt=txt_root + 'val.txt', transform=_transforms)
	train_loader = DataLoader(dataset=train_data, batch_size=batchsize, shuffle=True,num_workers=1)
	test_loader  = DataLoader(dataset=test_data, batch_size=batchsize, shuffle=False,num_workers=1)
	val_loader   = DataLoader(dataset=val_data, batch_size=batchsize, shuffle=False,num_workers=1)
	print('num_of_trainData:', len(train_data))
	print('num_of_testData:', len(test_data))
	print('num_of_valData:', len(val_data))
	return train_loader,test_loader,val_loader
	# print(train_data)

搭建RestNet18进行测试

import torch
import time
from torch import nn,optim
import torch.nn.functional as F
from PIL import Image
from torchvision import transforms
import MyDataset as md
import sys
sys.path.append("..")
from Pytorch_learning import pytorch_deep as pyd
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 创建残差块 rest block
class Residual(nn.Module):
    def __init__(self, in_channels,out_channels,use_1x1conv = False,stride = 1):
        super(Residual,self).__init__()
        self.conv1 = nn.Conv2d(in_channels,out_channels,kernel_size=3,padding = 1, stride = stride)
        self.conv2 = nn.Conv2d(out_channels,out_channels,kernel_size=3,padding=1)
        if use_1x1conv:
            self.conv3 = nn.Conv2d(in_channels,out_channels,kernel_size=3,padding = 1, stride = stride)
        else:self.conv3 = None
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.bn2 = nn.BatchNorm2d(out_channels)
        
    def forward(self,X):
        Y = F.relu(self.bn1(self.conv1(X)))
        Y = self.bn2(self.conv2(Y))
        if self.conv3:
            X = self.conv3(X)
        return F.relu(X+Y)
def resnet_block(in_channels, out_channels, num_residuals,first_block=False):
    if first_block:
        assert in_channels == out_channels # 第⼀个模块的通道数同输⼊通道数⼀致
    blk = []
    for i in range(num_residuals):
        if i == 0 and not first_block:
            blk.append(Residual(in_channels, out_channels,use_1x1conv=True, stride=2))
        else:
            blk.append(Residual(out_channels, out_channels))
    return nn.Sequential(*blk)

def my_restnet_18(num_classes= 6):
    net = nn.Sequential(
                nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),
                nn.BatchNorm2d(64),
                nn.ReLU(),
                nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

    net.add_module("resnet_block1", resnet_block(64, 64, 2,first_block=True))
    net.add_module("resnet_block2", resnet_block(64, 128, 2))
    net.add_module("resnet_block3", resnet_block(128, 256, 2))
    net.add_module("resnet_block4", resnet_block(256, 512, 2))
    net.add_module("global_avg_pool", pyd.GlobalAvgPool2d()) #GlobalAvgPool2d的输出: (Batch, 512, 1, 1)
    net.add_module("fc", nn.Sequential(pyd.FlattenLayer(),nn.Linear(512, num_classes)))
    return net

def my_train(save_path = './weight/restNet18_3.pth',resize=96,batch_size = 32):
    ## Training
    net = my_restnet_18(num_classes= 6)
    # 如出现“out of memory”的报错信息,可减⼩batch_size或resize
    train_iter, test_iter,val_iter =md.my_data_set(batchsize=batch_size,resize=resize)
    # train_iter, test_iter = pyd.load_data_fashion_mnist(batch_size,resize)
    lr, num_epochs = 0.001, 10
    optimizer = torch.optim.Adam(net.parameters(), lr=lr)
    ###训练过程
    net = net.to(device)
    print("training on ", device)
    ## 损失函数 交叉熵损失
    loss = torch.nn.CrossEntropyLoss()  
    batch_count = 0
    for epoch in range(num_epochs):
        train_l_sum, train_acc_sum, n, start = 0.0, 0.0, 0,time.time()
        for X, y in train_iter:
            # print(X)
            # print(len(X.data))
            X = X.to(device)   # 数据放到GPU
            y = y.to(device)
            y_hat = net(X)     #得到网络输出结果
            l = loss(y_hat, y)
            optimizer.zero_grad()
            l.backward()
            optimizer.step()
            train_l_sum += l.cpu().item()
            train_acc_sum += (y_hat.argmax(dim=1) ==y).sum().cpu().item()
            n += y.shape[0]
            batch_count += 1
        test_acc = pyd.evaluate_accuracy(test_iter, net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f,time %.1f sec'% 
              (epoch + 1, train_l_sum / batch_count,train_acc_sum / n, test_acc, time.time() - start))
    # torch.save(net,save_path)
def my_test(pth_path = './weight/restNet18.pth',resize = 96,batch_size = 32):
    model_net = torch.load(pth_path)
    train_iter, test_iter,val_iter =md.my_data_set(batchsize=batch_size,resize=resize)
    # 预测正确的数量和总数量
    correct = 0
    total = 0
    # 使用torch.no_grad的话在前向传播中不记录梯度,节省内存
    # cv2.namedWindow('predictPic', cv2.WINDOW_NORMAL)
    # to_pil_image  = transforms.ToPILImage()
    with torch.no_grad():
        for images,labels in val_iter:
            # images, labels = data
            # print(images)
            print(len(images.data))
            images, labels = images.to(device), labels.to(device)
            # 预测
            # outputs = self.net(images)
            outputs = model_net(images)
            # 我们的网络输出的实际上是个概率分布,去最大概率的哪一项作为预测分类
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
            # print(images.data[0])
            # print(len(images.data[0]))
            for i in range(len(images.data)):
                print('实际标签 {},预测标签 {}'.format(labels[i],predicted[i]))

def test_one_img(img_path, pth_path = './weight/restNet18_2.pth',resize = 96):
    img = Image.open(img_path).convert('RGBA')
    test_transforms = transforms.Compose([
            transforms.RandomResizedCrop((resize,resize)),
            transforms.ToTensor(),])
    img = test_transforms(img) 
    img = torch.unsqueeze(img, 0) 
    model_net = torch.load(pth_path)

    with torch.no_grad():
            img = img.to(device)
            # 预测
            # outputs = self.net(images)
            outputs = model_net(img)
            print(outputs)
            # # 我们的网络输出的实际上是个概率分布,去最大概率的哪一项作为预测分类
            _, predicted = torch.max(outputs.data, 1)
            print('predicted = {}'.format(predicted.item()))
            # total += labels.size(0)
            # correct += (predicted == labels).sum().item()

def main():
    save_path = './weight/restNet18_3.pth'
    pth_path = save_path
    resize = 227
    batch_size = 32
    #训练
    my_train(save_path,resize,batch_size)
    # 测试
    # my_test(pth_path,resize,batch_size)
    # 测试一张图片
    # img_path = './pokeman/mewtwo/00000036.jpg'
    # test_one_img(img_path,pth_path,resize)
    pass
if __name__=='__main__':
    main()

相关调用

# -*- coding: utf-8 -*-
import torch
from torch import nn
import matplotlib.pyplot as plt
from IPython import display
import torchvision
import torchvision.transforms as transforms
import time
import torch.nn.functional as F
def use_svg_display():
    # ⽤⽮量图显示
    display.set_matplotlib_formats('svg')
def set_figsize(figsize=(3.5, 2.5)):
    use_svg_display()
    # 设置图的尺⼨
    plt.rcParams['figure.figsize'] = figsize

#小批量数据读取
def data_iter(batch_size, features, labels):
    num_examples = len(features)
    indices = list(range(num_examples))
    random.shuffle(indices)
    for i in range(0,num_examples,batch_size):
#         print(i)
        j = torch.LongTensor(indices[i:min(i +batch_size,num_examples)])
        yield features.index_select(0,j),labels.index_select(0,j)
# 定义损失函数
def squared_loss(y_hat, y):
    return (y_hat - y.view(y_hat.size())) ** 2 /2
# 优化函数
def sgd(params, lr, batch_size):
    for param in params:
        param.data -= lr * param.grad / batch_size

#       MNIST_FASHION 标签
def get_fashion_mnist_labels(labels):
    text_labels = ['t-shirt', 'trouser', 'pullover', 'dress','coat','sandal', 'shirt', 'sneaker', 'bag', 'ankleboot']
    label_list = []
    for item in labels:
        label_list.append(text_labels[int(item)])
#     return [text_labels[int(i)] for i in labels]
    return label_list


def show_fashion_mnist(images, labels):
    use_svg_display()
    # 这⾥的_表示我们忽略(不使⽤)的变量
    _, figs = plt.subplots(1, len(images), figsize=(12, 12))
    for f, img, lbl in zip(figs, images, labels):
        f.imshow(img.view((28, 28)).numpy())
        f.set_title(lbl)
        f.axes.get_xaxis().set_visible(False)
        f.axes.get_yaxis().set_visible(False)
    plt.show()

def load_data_fashion_mnist(batch_size = 256,resize=None,num_workers = 0):
    trans = []
    if resize:
        trans.append(torchvision.transforms.Resize(size=resize))
    trans.append(torchvision.transforms.ToTensor())
    transform = torchvision.transforms.Compose(trans)
    pwd_MNIST = '/home/tjmt/tjmt_new/notebook/Wangjiale_DeepLab/Pytorch_learning'
    mnist_train = torchvision.datasets.FashionMNIST(root=pwd_MNIST + '/MNIST', train=True, download=True,
                                                    transform=transform)
    mnist_test = torchvision.datasets.FashionMNIST(root=pwd_MNIST + '/MNIST', train=False, download=True,
                                                   transform=transform)
    train_iter = torch.utils.data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=num_workers)
    test_iter = torch.utils.data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=num_workers)
    return train_iter,test_iter
def evaluate_accuracy(data_iter,net):
#     模型net 在数据集data_iter 上的分类准确率
    acc_sum,n = 0.0,0
    for X,y in data_iter:
#         print((net(X).argmax(dim=1)==y).float().sum().item())
        acc_sum += (net(X).argmax(dim=1)==y).float().sum().item()
        n+=y.shape[0]
    return acc_sum/n
def train_ch3(net, train_iter,test_iter,loss,num_epochs,batch_size,params=None,lr=None,optimizer = None):
    for epoch in range(num_epochs):
        #模型训练次数 5次
        train_l_num, train_acc_num,n = 0.0,0.0,0
        for X,y in train_iter:
            #X 为小批量256个图像 28*28 y为标签  
            # 计算X softmax下的值   与损失函数值
            y_hat = net(X) 
            l = loss(y_hat,y).sum()
            
            #梯度清零
            if optimizer is not None:
                optimizer.zero_grad()
            elif params is not None and params[0].grad is not None:
                for param in params:
                    param.grad.data.zero_()
            l.backward()
            if optimizer is None:
                sgd(params,lr,batch_size)
            else:
                optimizer.step()
            train_l_num += l.item()
            train_acc_num += (y_hat.argmax(dim=1)==y).sum().item()
            n+= y.shape[0]
        test_acc = evaluate_accuracy(test_iter,net)
        print('epoch %d, loss %.4f,train_acc %.3f,test_acc %.3f'%(epoch+1,train_l_num/n, train_acc_num/n, test_acc))
class FlattenLayer(nn.Module):
    def __init__(self):
        super(FlattenLayer, self).__init__()
    def forward(self, x): # x shape: (batch, *, *, ...)
        return x.view(x.shape[0], -1)
def fun1():
    print('sssss')
    
# 计算训练准确度 20200625
def evaluate_accuracy(data_iter, net, device= torch.device('cuda' if torch.cuda.is_available() else 'cpu')):
    acc_sum,n = 0.0,0.0       #acc_sum 计算训练过程中模型输出结果与标签相同的数量
    with torch.no_grad():     # torch.no_grad() 该作用域下 的计算不会被 track
        for X, y in data_iter:
            if isinstance(net, torch.nn.Module):
                net.eval() # 评估模式, 这会关闭dropout
                acc_sum += (net(X.to(device)).argmax(dim=1) ==y.to(device)).float().sum().cpu().item()
                net.train() # 改回训练模式
            else:print('error net')
            n += y.shape[0]
    return acc_sum / n
def train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs):
    net = net.to(device)
    print("training on 111000", device)
    ## 损失函数 交叉熵损失
    loss = torch.nn.CrossEntropyLoss()  
    batch_count = 0
    for epoch in range(num_epochs):
        train_l_sum, train_acc_sum, n, start = 0.0, 0.0, 0,time.time()
        for X, y in train_iter:
            X = X.to(device)   # 数据放到GPU
            y = y.to(device)
            y_hat = net(X)     #得到网络输出结果
            l = loss(y_hat, y)
            optimizer.zero_grad()
            l.backward()
            optimizer.step()
            train_l_sum += l.cpu().item()
            train_acc_sum += (y_hat.argmax(dim=1) ==y).sum().cpu().item()
            n += y.shape[0]
            batch_count += 1
        test_acc = evaluate_accuracy(test_iter, net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f,time %.1f sec'% 
              (epoch + 1, train_l_sum / batch_count,train_acc_sum / n, test_acc, time.time() - start))
    torch.save(net,'./mnist_alexnet_model.pth')
    # torch.save(net.state_dict(),'./mnist_alexnet.pth')
class GlobalAvgPool2d(nn.Module):
    # 全局平均池化层可通过将池化窗⼝形状设置成输⼊的⾼和宽实现
    def __init__(self):
        super(GlobalAvgPool2d, self).__init__()
    def forward(self, x):
        return F.avg_pool2d(x, kernel_size=x.size()[2:])
if __name__ == '__main__':
    main()                                                  
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用PyTorch加载自己的数据集并进行训练的完整代码示例: ```python import torch from torchvision import datasets, transforms from torch.utils.data import DataLoader import torch.nn as nn import torch.optim as optim # 定义数据集的预处理转换 transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)) ]) # 定义自己的数据集类 class CustomDataset(torch.utils.data.Dataset): def __init__(self, ...): # 读取数据集并进行必要的预处理操作 def __len__(self): # 返回数据集的长度 def __getitem__(self, index): # 返回指定索引处的数据样本 # 创建数据集实例 train_dataset = CustomDataset(...) test_dataset = CustomDataset(...) # 创建数据加载器 batch_size = 64 train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False) # 定义模型 class MyModel(nn.Module): def __init__(self): super(MyModel, self).__init__() # 定义模型结构 def forward(self, x): # 定义前向传播过程 model = MyModel() # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 训练模型 num_epochs = 10 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model.to(device) for epoch in range(num_epochs): train_loss = 0.0 model.train() for images, labels in train_loader: images = images.to(device) labels = labels.to(device) optimizer.zero_grad() outputs = model(images) loss = criterion(outputs, labels) loss.backward() optimizer.step() train_loss += loss.item() * images.size(0) train_loss /= len(train_loader.dataset) print(f"Epoch {epoch+1}/{num_epochs}, Training Loss: {train_loss}") # 在测试集上评估模型 model.eval() test_loss = 0.0 correct = 0 with torch.no_grad(): for images, labels in test_loader: images = images.to(device) labels = labels.to(device) outputs = model(images) loss = criterion(outputs, labels) test_loss += loss.item() * images.size(0) _, predicted = torch.max(outputs.data, 1) correct += (predicted == labels).sum().item() test_loss /= len(test_loader.dataset) accuracy = correct / len(test_loader.dataset) print(f"Test Loss: {test_loss}, Accuracy: {accuracy}") ``` 请注意,上述代码中有一些需要替换为你自己数据集和模型的部分,如`CustomDataset`类的定义、数据集实例的创建、模型的定义和前向传播过程等。你需要根据你自己的数据集和模型来进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值