博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【问题记录】pytorch自定义数据集 No such file or directory, invalid index of a 0-dim
阅读量:3903 次
发布时间:2019-05-23

本文共 13320 字,大约阅读时间需要 44 分钟。

保存模型:

保存整个神经网络的结构和模型参数
torch.save(mymodel, ‘mymodel.pkl’)
只保存神经网络的模型参数
torch.save(mymodel.state_dict(), ‘mymodel_params.pkl’)
导入模型:
mymodel = torch.load(‘mymodel.pkl’)

x=x.view(1,1,4,5) 意思是将 x 矩阵转换成 (1,1,4,5) 的四维矩阵,第一个 1是样本数,第二个1是通道数,第三个 4 和第四个 5 是高度和宽度。

卷积层

卷积层是用一个固定大小的矩形区去席卷原始数据,将原始数据分成一个个和卷积核大小相同的小块,然后将这些小块和卷积核相乘输出一个卷积值(注意:这里是一个单独的值,不再是矩阵了)。

conv2d 是二维度卷积,对数据在宽度和高度两个维度上进行卷积。
函数:
torch.nn.functional.conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups)
weight:卷积核权重,也就是卷积核本身,是一个四维度数组,(out_channels, in_channels/groups, kH, kW
Out_channels)。
out_channels是卷积核输出层的神经元个数,也就是这层有多少个卷积核,;in_channels 输入通道数,kH kW是卷积核的高度和宽

第一个代码:

train_hd=pandas.read_csv('C:\\Users\\number.csv')train_path='C:\\Users\\pic'class Mydataset(Dataset):    def __init__(self,df_data,data_dir='./',transform=None):        super().__init__()        self.df=df_data.values        self.data_dir=data_dir        self.transform=transform    def __len__(self):        return len(self.df)    def __getiem__(self,idex):        c,img_name,label=self.df[idex]        img_path=os.path.join(self.data_dir,img_name)        image=cv2.imread(img_path)        if self.transform is not None:            image=self.transform(image)        return image,labeltransforms_train=transforms.Compose([    transforms.ToPILImage(),    transforms.RandomHorizontalFlip(),    transforms.RandomRotation(10),    transforms.ToTensor(),    transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])train_data=Mydataset(train_hd,train_path,transform=transforms_train)BATCH_SIZE=64train_loader=DataLoader(train_data,batch_size=BATCH_SIZE,shuffle=True)print(train_data.__len__())print(train_data.__getiem__(100))# --------------------------------------------------------hidden_layer = 3input_data = 3output_data = 2x = Variable(torch.randn(BATCH_SIZE, input_data), requires_grad= False)y = Variable(torch.randn(BATCH_SIZE, output_data), requires_grad =False)w1 = Variable(torch.randn(input_data, hidden_layer) , requires_grad= True)w2 = Variable(torch.randn(hidden_layer, output_data) , requires_grad =True)epochn = 100  # grad.data. zero() 全部置零,learning_rate = 1e-6for epoch in range(epochn): y_pred = x.mm(w1).clamp(min=0).mm(w2) loss = (y_pred - y).pow(2).sum() print("Epoch:{},Loss:{:.4f}".format(epoch,loss.item())) loss.backward() w1.data -= learning_rate * w1.grad.data w2.data -= learning_rate * w2.grad.data w1.grad.data.zero_() w2.grad.data.zero_()

之后的代码:

import torch.nn.functional as Fimport torchimport torch.nn as nnfrom torch.autograd import Variablefrom torchvision import transformsfrom torch.utils.data.dataset import Datasetfrom torch.utils.data.dataloader import DataLoaderfrom PIL import Imageimport torch.optim as optimimport os# ***************************初始化一些函数********************************# torch.cuda.set_device(gpu_id)#使用GPUlearning_rate = 0.0001  # 学习率的设置# *************************************数据集的设置****************************************************************************root = os.getcwd() + '/data/'  # 数据集的地址# 定义读取文件的格式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):        super(MyDataset, self).__init__()        # 对继承自父类的属性进行初始化        imgs = []        fh = open("./data/num.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        # *************************** #使用__getitem__()对数据进行预处理并返回想要的信息**********************    def __getitem__(self, index):  # 这个方法是必须要有的,用于按照索引读取每个元素的具体内容        fn, label = self.imgs[index]        print(fn+'mm')        # fn是图片path #fn和label分别获得imgs[index]也即是刚才每行中word[0]和word[1]的信息        img_path = os.path.join("C:/Users/pic/", fn)        img = Image.open(img_path).convert('RGB')        # 按照路径读取图片        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)class Net(nn.Module):  # 定义网络,继承torch.nn.Module    def __init__(self):        super(Net, self).__init__()        self.conv1 = nn.Conv2d(1, 6, 5)  # 卷积层        self.pool = nn.MaxPool2d(2, 2)  # 池化层        self.conv2 = nn.Conv2d(6, 16, 5)  # 卷积层        self.fc1 = nn.Linear(16 * 5 * 5, 120)  # 全连接层        self.fc2 = nn.Linear(120, 84)        self.fc3 = nn.Linear(84, 2)  # 2个输出    def forward(self, x):  # 前向传播        x = self.pool(F.relu(self.conv1(x)))  # F就是torch.nn.functional        x = self.pool(F.relu(self.conv2(x)))        x = x.view(-1, 16 * 5 * 5)  # .view( )是一个tensor的方法,使得tensor改变size但是元素的总数是不变的。        # 从卷基层到全连接层的维度转换        x = F.relu(self.fc1(x))        x = F.relu(self.fc2(x))        x = self.fc3(x)        returnnet = Net()  # 初始化一个卷积神经网络leNet-train_data = MyDataset(txt=root + 'num.txt', transform=transforms.Compose([    transforms.Resize((32, 32)),    # 将图片缩放到指定大小(h,w)或者保持长宽比并缩放最短的边到int大小    transforms.CenterCrop(32),    transforms.ToTensor()])                       )train_loader = DataLoader(dataset=train_data, batch_size=2, shuffle=True)# batch_size:从样本中取多少张,每一次epoch都会输入batch_size张print('num_of_trainData:', len(train_data))def trainandsave():    # 神经网络结构    print('h')    net = Net()    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)  # 学习率为0.001    criterion = nn.CrossEntropyLoss()  # 损失函数也可以自己定义,我们这里用的交叉熵损失函数    # 训练部分    i = 0    for epoch in range(5):  # 训练的数据量为5个epoch,每个epoch为一个循环        # 每个epoch要训练所有的图片,每训练完成200张便打印一下训练的效果(loss值)        running_loss = 0.0  # 定义一个变量方便我们对loss进行输出        for i, data in enumerate(train_loader, 0):  # 这里我们遇到了第一步中出现的trailoader,代码传入数据            # enumerate是python的内置函数,既获得索引也获得数据            # get the inputs            inputs, labels = data  # data是从enumerate返回的data,包含数据和标签信息,分别赋值给inputs和labels            # wrap them in Variable            inputs, labels = Variable(inputs), Variable(labels)  # # 转换数据格式用Variable            optimizer.zero_grad()  # 梯度置零,因为反向传播过程中梯度会累加上一次循环的梯度            # forward + backward + optimize            outputs = net(inputs)  # 把数据输进CNN网络net            loss = criterion(outputs, labels)  # 计算损失值            loss.backward()  # loss反向传播            optimizer.step()  # 反向传播后参数更新            running_loss += loss.data[0]  # loss累加            if i % 20 == 19:                print('[%d, %5d] loss: %.3f' %                      (epoch + 1, i + 1, running_loss / 20))  # 然后再除以200,就得到这两百次的平均损失值                running_loss = 0.0  # 这一个200次结束后,就把running_loss归零,下一个200次继续使用    print('Finished Training')    # 保存神经网络    torch.save(net, 'net.pkl')    # 保存整个神经网络的结构和模型参数    torch.save(net.state_dict(), 'net_params.pkl')if __name__ == '__main__':    for i, data in enumerate(train_loader, 0):        print(i)

报错信息:

在这里插入图片描述

在这里插入图片描述

发现每次batch_size修改后对迭代有影响。只有batch_size为1时才进入了main 的循环,很奇怪。然后 fp = builtins.open(filename, “rb”)
FileNotFoundError: [Errno 2] No such file or directory: ‘C:/Users/pic/a_236.jpg’
一直以为自己文件夹下面有图片,但是仔细检查才知道自己那部分图片是png后缀结尾的,天哪,捣鼓了一下午居然就因为这个原因,我狂汗阿。。。。真的太不仔细了。。。。粗心害死人。。。。。
但是我也产生了疑问,难道pytorch的训练图片只能说jpg格式吗?在书上也没看到过这一点。
另一个报错:
TypeError: pic should be Tensor or ndarray. Got <class ‘PIL.Image.Image’>.
方法:删去transform的toPILIMAGE。

用程序将png后缀文件改成jpg之后仍然有错:

在这里插入图片描述
看来文件已经都能迭代成功了,但是参数有问题。
发现在net中的第一卷积层是这样的:
self.conv1 = nn.Conv2d(2, 6, 5) # 卷积层
这个函数第一个参数为输入的通道数,第二个参数为输出的通道数。而我图片是3通道
改为:
self.conv1 = nn.Conv2d(3, 6, 5) # 卷积层

之后的报错:

loss.data[0] # loss累加
IndexError: invalid index of a 0-dim
在这里插入图片描述
版本原因,应该把data[0]写成.item()
修改所有错误终于开始训练了:
在这里插入图片描述
上面结果的全部代码:

import cv2import torch.nn.functional as Fimport torchimport torch.nn as nnfrom torch.autograd import Variablefrom torchvision import transformsfrom torch.utils.data.dataset import Datasetfrom torch.utils.data.dataloader import DataLoaderfrom PIL import Imageimport torch.optim as optimimport os# ***************************初始化一些函数********************************# torch.cuda.set_device(gpu_id)#使用GPUlearning_rate = 0.0001  # 学习率的设置# *************************************数据集的设置****************************************************************************root = os.getcwd() + '\\data\\'  # 数据集的地址# 定义读取文件的格式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        # *************************** #使用__getitem__()对数据进行预处理并返回想要的信息**********************    def __getitem__(self, index):  # 这个方法是必须要有的,用于按照索引读取每个元素的具体内容        fn, label = self.imgs[index]        # fn是图片path #fn和label分别获得imgs[index]也即是刚才每行中word[0]和word[1]的信息        img_path = os.path.join("C:\\Users\\pic\\", fn)        img = Image.open(img_path).convert('RGB')        # 按照路径读取图片        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)class Net(nn.Module):  # 定义网络,继承torch.nn.Module    def __init__(self):        super(Net, self).__init__()        self.conv1 = nn.Conv2d(3, 6, 5)  # 卷积层        self.pool = nn.MaxPool2d(2, 2)  # 池化层        self.conv2 = nn.Conv2d(6, 16, 5)  # 卷积层        self.fc1 = nn.Linear(16 * 5 * 5, 120)  # 全连接层        self.fc2 = nn.Linear(120, 84)        self.fc3 = nn.Linear(84, 2)  # 2个输出    def forward(self, x):  # 前向传播        x = self.pool(F.relu(self.conv1(x)))  # F就是torch.nn.functional        x = self.pool(F.relu(self.conv2(x)))        x = x.view(-1, 16 * 5 * 5)  # .view( )是一个tensor的方法,使得tensor改变size但是元素的总数是不变的。        # 从卷基层到全连接层的维度转换        x = F.relu(self.fc1(x))        x = F.relu(self.fc2(x))        x = self.fc3(x)        return xIMG_MEAN = [0.485, 0.456, 0.406]IMG_STD = [0.229, 0.224, 0.225]net = Net()  # 初始化一个卷积神经网络leNet-train_data = MyDataset(txt=root + 'num.txt', transform=transforms.Compose([    transforms.Resize((32, 32)),    # 将图片缩放到指定大小(h,w)或者保持长宽比并缩放最短的边到int大小    transforms.CenterCrop(32),    transforms.ToTensor()])                       )train_loader = DataLoader(dataset=train_data, batch_size=227, shuffle=True,drop_last=True)# batch_size:从样本中取多少张,每一次epoch都会输入batch_size张print('num_of_trainData:', len(train_data))def trainandsave():    # 神经网络结构    print('h')    net = Net()    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)  # 学习率为0.001    criterion = nn.CrossEntropyLoss()  # 损失函数也可以自己定义,我们这里用的交叉熵损失函数    # 训练部分    for epoch in range(10):  # 训练的数据量为10个epoch,每个epoch为一个循环        # 每个epoch要训练所有的图片,每训练完成200张便打印一下训练的效果(loss值)        running_loss = 0.0  # 定义一个变量方便我们对loss进行输出        for i, data in enumerate(train_loader, 0):  # 这里我们遇到了第一步中出现的trailoader,代码传入数据            # enumerate是python的内置函数,既获得索引也获得数据            # get the inputs            inputs, labels = data  # data是从enumerate返回的data,包含数据和标签信息,分别赋值给inputs和labels            # wrap them in Variable            inputs, labels = Variable(inputs), Variable(labels)  # # 转换数据格式用Variable            optimizer.zero_grad()  # 梯度置零,因为反向传播过程中梯度会累加上一次循环的梯度            # forward + backward + optimize            outputs = net(inputs)  # 把数据输进CNN网络net            loss = criterion(outputs, labels)  # 计算损失值            loss.backward()  # loss反向传播            optimizer.step()  # 反向传播后参数更新            running_loss += loss.item()  # loss累加            if i % 9 == 1:                print('[%d, %5d] loss: %.3f' %                      (epoch + 1, i + 1, running_loss / 10))  # 平均损失值                running_loss = 0.0  # 这一个结束后,就把running_loss归零,    print('Finished Training')    # 保存神经网络    torch.save(net, 'net.pkl')    # 保存整个神经网络的结构和模型参数    torch.save(net.state_dict(), 'net_params.pkl')if __name__ == '__main__':    trainandsave()

记住net的前向传播函数要return x

转载地址:http://svten.baihongyu.com/

你可能感兴趣的文章
nginx依据http请求头中的accept-language转发到不同的页面
查看>>
matplotlib-绘制精美的图表
查看>>
离群点检测Outlier Detection
查看>>
最大似然估计(Maximum likelihood estimation)
查看>>
Python 爬虫的工具列表 附Github代码下载链接
查看>>
Configure Git to sync your fork with the original 同步 Github fork 出来的分支
查看>>
浅析时间序列用户生命周期的聚类方法
查看>>
Python Packeage Install
查看>>
Programatically understanding dynamic time warping
查看>>
轻松看懂机器学习十大常用算法
查看>>
数据挖掘十大经典算法(8) kNN: k-nearest neighbor classification
查看>>
基于Flume的美团日志收集系统(一)架构和设计
查看>>
稀疏索引
查看>>
Kafka文件存储机制那些事
查看>>
Kafka 高性能吞吐揭秘
查看>>
【Zookeeper系列一】Zookeeper应用介绍与安装部署
查看>>
zookeeper 安装 使用
查看>>
kafka 安装部署
查看>>
关于吞吐量和延迟的精彩比喻
查看>>
UPYUN基于ngx_lua的动态服务路由方案
查看>>