本文共 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/