几种常见的优化函数比较:
- '''
- 基于 Adam 识别 MNIST 数据集
- '''
- import torch
- import torchvision
- import torchvision.transforms as transform
- import torch.nn
- from torch.autograd import Variable
- '''
- 神经网络层级结构:
- 卷积层 Conv1,Conv2()
- 最大池化层 MaxPool2d()
- 损失函数 ReLU()
- 参数:
- 卷积神经网络的卷积层参数:------ 输入通道数, 输出通道数, 卷积核大小, 卷积核移动步长和 Padding 的值
- Conv2d(input_channels,output_channels,kernel_size,stride,padding);
- 最大池化层参数:------ 池化窗口大小, 移动步长
- MaxPool2d(kernel_size,stride)
- 方法:
- 1.torch.nn.Sequential() 用作参数序列化, 神经网络模块会按照传入 Suquential 构造器顺序依次被添加到计算图中执行
- 2.torch.nn.Linear(x,y) 用作对矩阵线性变换, 对于一个 a*x 大小的矩阵, 变换后会变成 a*y 大小的矩阵, 即矩阵的乘法
- '''
- class LeNet(torch.nn.Module):
- def __init__(self):
- super(LeNet, self).__init__()
- # 卷积层 1
- self.conv1 = torch.nn.Sequential( # input_size=(1*28*28)
- torch.nn.Conv2d(1, 6, 5, 1, 2), # padding=2 保证输入输出尺寸相同
- # 输出尺寸计算公式: Height=(Height_input-kernel_size+2*padding)/stride+1
- # 输出尺寸 =(28 - 5 + 2*2)/1 + 1 = 28
- torch.nn.ReLU(), # input_size=(6*28*28)
- torch.nn.MaxPool2d(kernel_size=2, stride=2), # output_size=(6*14*14)
- # 池化层尺寸计算公式: Height=(Height_input-Height_filter)/stride+1
- # Height = (28 - 2)/2 +1 = 14
- )
- # 卷积层 2
- self.conv2 = torch.nn.Sequential(
- torch.nn.Conv2d(6, 16, 5), # 默认 stride=1,padding=0; 输入矩阵 6*14*14
- # Height = (14-5+0*2)/1 + 1 = 10
- torch.nn.ReLU(), # input_size=(16*10*10)
- torch.nn.MaxPool2d(2, 2) # output_size=(16*5*5)
- # Height = (10-2)/2 + 1 = 5
- )
- # 全连接层 1
- self.fullConnection1 = torch.nn.Sequential(
- torch.nn.Linear(16 * 5 * 5, 120),
- torch.nn.ReLU()
- )
- # 全连接层 2
- self.fullConnection2 = torch.nn.Sequential(
- torch.nn.Linear(120, 84),
- torch.nn.ReLU()
- )
- # 全连接层 3
- self.fullConnection3 = torch.nn.Linear(84, 10)
- def forward(self, x):
- x = self.conv1(x)
- x = self.conv2(x)
- x = x.view(x.size()[0], -1) # 对参数进行扁平化, 因为之后要进行全连接, 必须降低他的 channel
- x = self.fullConnection1(x)
- x = self.fullConnection2(x)
- x = self.fullConnection3(x)
- return x
- EPOCH = 8 # 遍历总次数
- BATCH_SIZE = 64 # 批处理尺寸
- LEARNINGRATE = 0.001
- '''
- ------------------------------ 定义数据预处理方式 ------------------------------
- 现在需要考虑的是, 计算机视觉的数据集很多是图片形式的, 而 PyTorch 中计算的则是 Tensor 数据类型的变量, 因此我们先要做的是数据类型的转换
- 即 图像类型 ---->Tensor 类型
- 需要注意的是, 有的时候我们的训练集是有限的, 这个时候需要进行数据增强
- 数据增强就是将图片进行各种变换, 例如放大, 缩小, 水平翻转, 垂直反转等
- torch.transforms() 中有很多数据增强的变换类
- '''
- transform = transform.ToTensor()
- # 定义训练数据集
- data_train = torchvision.datasets.MNIST(
- root='C://data/',
- train=True,
- download=False,
- transform=transform
- )
- # 定义训练批处理数据
- data_train_loader = torch.utils.data.DataLoader(
- data_train,
- batch_size=BATCH_SIZE,
- shuffle=True
- )
- # 定义测试数据集
- data_test = torchvision.datasets.MNIST(
- root='C://data/',
- train=True,
- download=False,
- transform=transform
- )
- # 定义测试批处理数据
- data_test_loader = torch.utils.data.DataLoader(
- data_test,
- batch_size=BATCH_SIZE,
- shuffle=False
- )
- # 定义损失函数 Loss function 和优化方式 (这里采用 Adam)
- net = LeNet()
- loss_n = torch.nn.CrossEntropyLoss() # 交叉熵损失函数
- optimizer = torch.optim.Adam.NET.parameters())
- # 训练
- for epoch in range(EPOCH):
- sum_loss = 0.0
- # 读取数据
- for i, data in enumerate(data_train_loader):
- inputs, labels = data
- inputs, labels = Variable(inputs), Variable(labels)
- # 梯度清理
- optimizer.zero_grad()
- # forward + backward
- outputs = net(inputs) # 预测数据
- loss = loss_n(outputs, labels) # 预测数据与实际数据做交叉熵
- loss.backward()
- optimizer.step() # 后向传播过后对模型进行更新
- # 每 100 个 batch 打印一次平均 loss
- sum_loss += loss.item() # ???????????
- if i % 100 == 99:
- print('[%d,%d] loss:%.03f' % (epoch + 1, i + 1, sum_loss / 100))
- sum_loss = 0.0 # 打印并且重置
- # 每次运行一次 epoch 打印一次正确率
- with torch.no_grad():
- correct = 0
- total = 0
- for data in data_test_loader:
- images, labels = data
- images, labels = Variable(images), Variable(labels)
- outputs = net(images)
- # 取得分最高的那个类
- _, predicted = torch.max(outputs.data, 1)
- total += labels.size(0)
- correct += (predicted == labels).sum()
- print('第 %d 个 epoch 的识别准确率为:%d%%' % (epoch + 1, (100 * correct / total)))
- # torch.save.NET.state_dict(), '%s/net_%03d.pth' % (opt.outf, epoch + 1))
- '''
- 基于 SGD 优化函数识别 MNIST 数据集
- '''
- import torch
- import torchvision as tv
- import torchvision.transforms as transforms
- import torch.nn as nn
- import torch.optim as optim
- import argparse
- # 定义是否使用 GPU
- device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
- # 定义网络结构
- '''
- 神经网络层级结构:
- 卷积层 Conv1,Conv2()
- 最大池化层 MaxPool2d()
- 损失函数 ReLU()
- 参数:
- 卷积神经网络的卷积层参数:------ 输入通道数, 输出通道数, 卷积核大小, 卷积核移动步长和 Padding 的值
- Conv2d(input_channels,output_channels,kernel_size,stride,padding);
- 最大池化层参数:------ 池化窗口大小, 移动步长
- MaxPool2d(kernel_size,stride)
- 方法:
- 1.torch.nn.Sequential() 用作参数序列化, 神经网络模块会按照传入 Suquential 构造器顺序依次被添加到计算图中执行
- 2.torch.nn.Linear(x,y) 用作对矩阵线性变换, 对于一个 a*x 大小的矩阵, 变换后会变成 a*y 大小的矩阵, 即矩阵的乘法
- '''
- class LeNet(nn.Module):
- def __init__(self):
- super(LeNet, self).__init__()
- # 卷积层 1
- self.conv1 = nn.Sequential( # input_size=(1*28*28)
- nn.Conv2d(1, 6, 5, 1, 2), # padding=2 保证输入输出尺寸相同
- nn.ReLU(), # input_size=(6*28*28)
- nn.MaxPool2d(kernel_size=2, stride=2), # output_size=(6*14*14)
- )
- # 卷积层 2
- self.conv2 = nn.Sequential(
- nn.Conv2d(6, 16, 5),
- nn.ReLU(), # input_size=(16*10*10)
- nn.MaxPool2d(2, 2) # output_size=(16*5*5)
- )
- # 全连接层 1
- self.fc1 = nn.Sequential(
- nn.Linear(16 * 5 * 5, 120),
- nn.ReLU()
- )
- # 全连接层 2
- self.fc2 = nn.Sequential(
- nn.Linear(120, 84),
- nn.ReLU()
- )
- # 全连接层 3
- self.fc3 = nn.Linear(84, 10)
- # 定义前向传播过程, 输入为 x
- def forward(self, x):
- x = self.conv1(x)
- x = self.conv2(x)
- # nn.Linear() 的输入输出都是维度为一的值, 所以要把多维度的 tensor 展平成一维
- x = x.view(x.size()[0], -1)
- x = self.fc1(x)
- x = self.fc2(x)
- x = self.fc3(x)
- return x
- # 使得我们能够手动输入命令行参数, 就是让风格变得和 Linux 命令行差不多
- parser = argparse.ArgumentParser()
- parser.add_argument('--outf', default='./model/', help='folder to output images and model checkpoints') # 模型保存路径
- parser.add_argument('--net', default='./model/net.pth', help="path to netG (to continue training)") # 模型加载路径
- opt = parser.parse_args()
- # 超参数设置
- EPOCH = 8 # 遍历数据集次数
- BATCH_SIZE = 64 # 批处理尺寸 (batch_size)
- LR = 0.001 # 学习率
- # 定义数据预处理方式
- transform = transforms.ToTensor()
- # 定义训练数据集
- trainset = tv.datasets.MNIST(
- root='./data/',
- train=True,
- download=True,
- transform=transform)
- # 定义训练批处理数据
- trainloader = torch.utils.data.DataLoader(
- trainset,
- batch_size=BATCH_SIZE,
- shuffle=True,
- )
- # 定义测试数据集
- testset = tv.datasets.MNIST(
- root='C://data//',
- train=False,
- download=True,
- transform=transform)
- # 定义测试批处理数据
- testloader = torch.utils.data.DataLoader(
- testset,
- batch_size=BATCH_SIZE,
- shuffle=False,
- )
- # 定义损失函数 loss function 和优化方式 (采用 SGD)
- net = LeNet().to(device)
- criterion = nn.CrossEntropyLoss() # 交叉熵损失函数, 通常用于多分类问题上
- optimizer = optim.SGD.NET.parameters(), lr=LR, momentum=0.9)
- # 训练
- if __name__ == "__main__":
- for epoch in range(EPOCH):
- sum_loss = 0.0
- # 数据读取
- for i, data in enumerate(trainloader):
- inputs, labels = data
- inputs, labels = inputs.to(device), labels.to(device)
- # 梯度清零
- optimizer.zero_grad()
- # forward + backward
- outputs = net(inputs)
- loss = criterion(outputs, labels)
- loss.backward()
- optimizer.step()
- # 每训练 100 个 batch 打印一次平均 loss
- sum_loss += loss.item()
- if i % 100 == 99:
- print('[%d, %d] loss: %.03f'
- % (epoch + 1, i + 1, sum_loss / 100))
- sum_loss = 0.0
- # 每跑完一次 epoch 测试一下准确率
- with torch.no_grad():
- correct = 0
- total = 0
- for data in testloader:
- images, labels = data
- images, labels = images.to(device), labels.to(device)
- outputs = net(images)
- # 取得分最高的那个类
- _, predicted = torch.max(outputs.data, 1)
- total += labels.size(0)
- correct += (predicted == labels).sum()
- print('第 %d 个 epoch 的识别准确率为:%d%%' % (epoch + 1, (100 * correct / total)))
- # torch.save.NET.state_dict(), '%s/net_%03d.pth' % (opt.outf, epoch + 1))
来源: http://www.bubuko.com/infodetail-3304122.html