研究背景
马上就要进行智能优化作业大考核了,但是对于智能优化里面的什么粒子群算法、遗传算法之类的明白的太少,只对神经网络有所了解,再加上对于以后的个人规划,我觉得我还是pytorch写一个神经网络识别数字吧。
pytorch
PyTorch是一个开源的Python机器学习库,基于Torch,用于自然语言处理等应用程序。是facebook推出来的。
读取数据
读取数据一般需要三个类,分别是Dataset
、DataLoader
、DataloaderIter
;三者是依次封装的关系.
Dataset
dataset位于torch.utils.data.Dataset
,当我们自定义类的时候必须继承他并实现他的两个成员函数----__len__()
和__getitem__
,例如我下面代码里面的Mydata
函数。
import torch.utils.data
import numpy as np
import os, random, glob
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
from torch.utils.data import Dataset, DataLoader
class Mydata(torch.utils.data.Dataset):
def __init__(self, root, train=True, transform=None,
target_transform=None):
self.root = root
self.train = train
self.transform = transform
self.target_transform = target_transform
file_list_label = os.listdir(self.root)
print(file_list_label)
self.label = []
self.data = []
for index, i in enumerate(file_list_label):
print(index,i)
file_list_img = os.listdir(self.root + '/' + i)
for j in file_list_img:
imge = Image.open(root + '/' + i + '/' + j).convert('RGB')
self.label.append(int(i))
self.data.append(imge)
def __getitem__(self, index):
img, target = self.data[index], self.label[index]
if self.transform is not None:
imgee = self.transform(img)
# print(imgee.shape)
if self.target_transform is not None:
target = self.target_transform(target)
return imgee, target
def __len__(self):
return len(self.data)
# 读取数据
if __name__ == "__main__":
CLASSES = {0: "0", 1: "1", 2: "2", 3: "3", 4: "4", 5: "5"}
img_dir = "./data/train"
data_transform = transforms.Compose([
transforms.Resize(32), # resize到32
transforms.CenterCrop(24), # crop到24
transforms.ToTensor(),
# 把一个取值范围是[0,255]的PIL.Image或者shape为(H,W,C)的numpy.ndarray,转换成形状为[C,H,W],取值范围是[0,1.0]的torch.FloadTensor /255.操作
])
dataSet = Mydata('./TrainData', transform=transforms.Compose([transforms.Resize((32, 32)), transforms.ToTensor()]))
dataLoader = torch.utils.data.DataLoader(dataSet, batch_size=8, shuffle=True, num_workers=4)
image_batch, label_batch = iter(dataLoader).next() #迭代器获取数据
print(image_batch.data.shape[0])
print(label_batch)
for i in range(image_batch.data.shape[0]):
label = np.array(label_batch.data[i]) ## tensor ==> numpy
print(label_batch.data[i])
img = np.array(image_batch.data[i]*255, np.int32)
print(CLASSES[int(label)])
plt.imshow(np.transpose(img, [2, 1, 0]))
plt.show()
Datasetloader
dataLoader = torch.utils.data.DataLoader(dataSet, batch_size=8, shuffle=True, num_workers=4)
dataset : 上面所实现的自定义类Dataset;
batch_size : 默认为1,每次读取的batch的大小;
shuffle : 默认为False, 是否对数据进行shuffle操作(简单理解成将数据集打乱);
num_works : 默认为0,表示在加载数据的时候每次使用子进程的数量,即简单的多线程预读数据的方法;
DataLoader返回的是一个迭代器,我们通过这个迭代器来获取数据
Dataloder的目的是将给定的n个数据, 经过Dataloader操作后, 在每一次调用时调用一个小batch, 如:
给出的是: (5000,28,28), 表示有5000个样本,每个样本的size为(28,28)经过Dataloader处理后, 一次得到的是(100,28,28)(假设batch_size大小为100), 表示本次取出100个样本, 每个样本的size为(28,28).
卷积网络结构
在这里卷积神经采用的是2层卷积神经网络和一个全连接层,步长为1,填充为2(计算边缘特征),最大池化层为2×2,滤波器5×5。
from __future__ import print_function, division
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from torch.utils.data import Dataset
from torchvision import transforms, datasets, models
from Dataloader2 import Mydata
import matplotlib.pyplot as plt
EPOCH = 10 # 训练次数
batch_size = 32 # 批处理大小
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Sequential( #input shape (3,32,32)
nn.Conv2d(in_channels=3, #input height
out_channels=16, #n_filter
kernel_size=5, #filter size
stride=1, #filter step 步幅
padding=2
), #output shape (16,32,32)
nn.ReLU(),
nn.MaxPool2d(kernel_size=2) #2x2采样,output shape (16,16,16)
)
self.conv2 = nn.Sequential(nn.Conv2d(16, 32, 5, 1, 2), #output shape (32,8,8)
nn.ReLU(),
nn.MaxPool2d(2))
self.out = nn.Linear(32*8*8,6) #连接层
def forward(self, x): #定义自己的前向传播方式
x = self.conv1(x)
x = self.conv2(x)
x = x.view(x.size(0), -1) #flat (batch_size, 32*7*7)
output = self.out(x)
return output
train_dataset = Mydata('./TrainData', transform=transforms.Compose([transforms.Resize((32, 32)), transforms.ToTensor()]))
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=2)
test_dataset = Mydata('./TestData', transform=transforms.Compose([transforms.Resize((32, 32)), transforms.ToTensor()]))
test_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=2)
cnn = CNN()
print(cnn)
#optimizer
optimizer = torch.optim.Adam(cnn.parameters(), lr=0.001) #Adam的优点主要在于经过偏置校正后,每一次迭代学习率都有个确定范围,使得参数比较平稳
loss_func = nn.CrossEntropyLoss() #loss_fun 使用交叉熵损失
loss_count = []
test_loss_cout = []
for epoch in range(EPOCH):
running_loss = 0.0
train_total = 0
train_correct=0
for i, (x, y) in enumerate(train_loader):
batch_x = Variable(x)
batch_y = Variable(y)
output = cnn(batch_x) #输入训练数据
# _, train_predicted = torch.max(output.data, 1)
# train_correct += (train_predicted == batch_y.data).sum()
preds=output.data.max(dim=1,keepdim=True)[1]
train_correct+=preds.eq(batch_y.data.view_as(preds)).cpu().sum()
loss = loss_func(output, batch_y) #计算误差
optimizer.zero_grad() #清空上一次梯度
loss.backward() #误差反向传递
optimizer.step() #优化器参数更新
# if i % 20 == 0:
# loss_count.append(loss)
# torch.save(cnn, "my_model3.pth")
running_loss += loss.item()
# print("train epoch: ", epoch, " loss: ", loss.item())
train_total += batch_y.size(0)
acc = 100.0*train_correct / len(train_loader.dataset)
print('train %d epoch loss: %.3f Acc: %.3f' % (
epoch + 1, running_loss / len(train_loader.dataset), acc))
loss_count.append(running_loss / len(train_loader.dataset))
torch.save(cnn, "my_model3.pth")
# 模型测试
correct = 0
test_loss = 0.0
test_total = 0
test_total = 0
cnn.eval()
for data in test_loader:
images, labels = data
images, labels = Variable(images), Variable(labels)
outputs = cnn(images)
_, predicted = torch.max(outputs.data, 1)
loss2 = loss_func(outputs, labels)
test_loss += loss2.item()
test_total += labels.size(0)
correct += (predicted == labels.data).sum()
print('test %d epoch loss: %.3f acc: %.3f ' % (epoch + 1, test_loss / len(test_loader.dataset), 100.0 * correct / len(test_loader.dataset)))
test_loss_cout.append(test_loss / len(test_loader.dataset))
"""
if i % 20 == 0:
loss_count.append(loss)
#print('损失函数—{}:\t'.format(i), loss.item())
print("epoch: ", epoch+1, " loss: ", loss.item())
torch.save(cnn, "my_model_cnn.pth")
if i % 100 == 0:
for a,b in test_loader:
test_x = Variable(a)
test_y = Variable(b)
out = cnn(test_x)
# print('test_out:\t',torch.max(out,1)[1])
# print('test_y:\t',test_y)
accuracy = torch.max(out,1)[1].numpy() == test_y.numpy()
print('accuracy:\t',accuracy.mean())
break
#模型测试
test_output =cnn(test_x[:10])
pred_y = torch.max(test_output,1)[1].data.numpy().squeeze()
print(pred_y, 'prediction number')
print(test_y[:10])
"""
plt.figure('PyTorch_CNN_Loss')
plt.plot(loss_count,label='train_loss')
plt.plot(test_loss_cout,label='test_loss')
plt.legend()
plt.show()
推荐书籍----pytorch深度学习()毗湿奴.布拉马尼亚