赞
踩
AlexNet总共包含8层变换,分别为5层卷积层、2个全连接层和一个全连接输出层
import time
import torch
from torch import nn, optim
import torchvision
import sys
# 如果有gpu计算设备,选择gpu计算设备,否则选择在cpu上训练
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
device
class AlexNet(nn.Module): def __init__(self): super(AlexNet, self).__init__() # 卷积层 self.conv = nn.Sequential( # 第一层卷积 # 如果使用mnist类的数据集,输入通道为1,如果使用的cifar等彩色图像的数据集,输入通道为3 nn.Conv2d(3, 96, 11, 4), nn.ReLU(), nn.MaxPool2d(3, 2), # 第二层卷积,开始减小卷积窗口 nn.Conv2d(96, 256, 5, 1, 2), nn.ReLU(), nn.MaxPool2d(3, 2), # 第三层卷积 nn.Conv2d(256, 384, 3, 1, 1), nn.ReLU(), # 第四层卷积 nn.Conv2d(384, 384, 3, 1, 1), nn.ReLU(), # 第五层卷积 nn.Conv2d(384, 256, 3, 1, 1), nn.ReLU(), nn.MaxPool2d(3, 2) ) self.fc = nn.Sequential( # 第一层全连接层 nn.Linear(256*5*5, 4096), nn.ReLU(), nn.Dropout(0.5), # 第二层全连接层 nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(0.5), # 第三层全连接层(输出层) nn.Linear(4096, 10) ) def forward(self, x): x = self.conv(x) x = self.fc(x.view(x.shape[0], -1)) return x
alexnet = AlexNet()
alexnet
def load_data(batch_size, resize=None, root='./data/CIFAR10'): trans = [] if resize: trans.append(torchvision.transforms.Resize(size=resize)) trans.append(torchvision.transforms.ToTensor()) transform = torchvision.transforms.Compose(trans) # torchvision.datasets包内还有许多其他的数据集,只需要修改网络的输入通道数和输出类别数即可 data_train = torchvision.datasets.CIFAR10(root=root, train=True, download=True, transform=transform) data_test = torchvision.datasets.CIFAR10(root=root, train=False, download=True, transform=transform) if sys.platform.startswith('win'): num_workers = 0 # 0表示不用额外的进程来加速读取数据 else: num_workers = 4 train_iter = torch.utils.data.DataLoader(data_train, batch_size=batch_size, shuffle=True, num_workers=num_workers) test_iter = torch.utils.data.DataLoader(data_test, batch_size=batch_size, shuffle=False, num_workers=num_workers) return train_iter, test_iter
# batchsize可以根据电脑的实际情况进行修改
batchsize = 128
# 由于imagenet数据集图片的形状为224*224,所以需要将输入的图片resize为224*224
train_iter, test_iter = load_data(batch_size=batchsize, resize=224)
# lr, num_epochos可以根据实际情况进行修改 lr, num_epochos = 0.001, 5 # 优化算法采用Adam算法,也可以选择torch.optim包下其他的优化算法 optimizer = torch.optim.Adam(alexnet.parameters(), lr=lr) def train(train_iter, test_iter, net, optimizer, device, num_epochs): # 将网络部署在gpu设备上 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: # 输入的属性 X = X.to(device) # 标签 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 {}, loss {:.4f}, train acc {:.4f}, test acc{:.4f}, time {:.2f} sec' .format(epoch + 1, train_l_sum / batch_count, train_acc_sum / n, test_acc, time.time() - start)) # 评估模型在测试集的表现 def evaluate_accuracy(data_iter, net, device=None): if device is None and isinstance(net, torch.nn.Module): # 如果没指定device就使用net的device device = list(net.parameters())[0].device acc_sum, n = 0.0, 0 with torch.no_grad(): for X, y in data_iter: if isinstance(net, torch.nn.Module): # 评估模式, 关闭dropout net.eval() acc_sum += (net(X.to(device)).argmax(dim=1) == y.to(device)).float().sum().cpu().item() # 改回训练模式 net.train() else: if ('is_training' in net.__code__.co_varnames): # 如果有is_training这个参数 # 将is_training设置成False acc_sum += (net(X, is_training=False).argmax(dim=1) == y).float().sum().item() else: acc_sum += (net(X).argmax(dim=1) == y).float().sum().item() n += y.shape[0] return acc_sum / n train(train_iter=train_iter, test_iter=test_iter, net=alexnet, optimizer=optimizer, device=device,num_epochs=num_epochos)
%matplotlib inline import os import time import torch from torch import nn, optim import torch.nn.functional as F from torch.utils.data import Dataset, DataLoader import torchvision from IPython import display from matplotlib import pyplot as plt from PIL import Image os.environ["CUDA_VISIBLE_DEVICES"] = "0" import sys device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') device
# 读取图片
display.set_matplotlib_formats('svg')
plt.rcParams['figure.figsize'] = (3.5, 2.5)
img = Image.open('./dog.jpg')
plt.imshow(img)
def show_images(imgs, num_rows, num_cols, scale=2):
figsize = (num_cols * scale, num_rows * scale)
_, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)
for i in range(num_rows):
for j in range(num_cols):
axes[i][j].imshow(imgs[i * num_cols + j])
axes[i][j].axes.get_xaxis().set_visible(False)
axes[i][j].axes.get_yaxis().set_visible(False)
return axes
def apply(img, aug, num_rows=2, num_cols=4, scale=1.5):
Y = [aug(img) for _ in range(num_rows * num_cols)]
show_images(Y, num_rows, num_cols, scale)
# 一半概率的图像左右翻转
apply(img, torchvision.transforms.RandomHorizontalFlip())
# 一半概率的图像上下翻转
apply(img, torchvision.transforms.RandomVerticalFlip())
# 随机选取图像中10%-50%的区域,区域的宽和高之比为0.5-2,将该区域缩放到200像素
shape_aug = torchvision.transforms.RandomResizedCrop(200, scale=(0.1, 0.5), ratio=(0.5, 2))
apply(img, shape_aug)
# 将图像的亮度随机变化为源图像的50%
apply(img, torchvision.transforms.ColorJitter(brightness=0.5))
# 将图像的色调随机变化为源图像的50%
apply(img, torchvision.transforms.ColorJitter(hue=0.5))
# 将图像的对比度随机变化为源图像的50%
apply(img, torchvision.transforms.ColorJitter(contrast=0.5))
# 同时设置修改亮度,色调,对比度
# 将图像的亮度随机变化为源图像的50%
apply(img, torchvision.transforms.ColorJitter(
brightness=0.5, hue=0.5, contrast=0.5))
augs = torchvision.transforms.Compose([
torchvision.transforms.RandomHorizontalFlip(),
torchvision.transforms.ColorJitter(
brightness=0.5, hue=0.5, contrast=0.5),
torchvision.transforms.RandomResizedCrop(200, scale=(0.1, 0.5), ratio=(0.5, 2))
])
apply(img, augs)
在读取数据函数load_data里面添加图像增广的方法
def load_data(batch_size, resize=None, root='./data/CIFAR10'): trans = [] if resize: trans.append(torchvision.transforms.Resize(size=resize)) # 根据实际情况添加图像增广的方法 trans.append(torchvision.transforms.RandomHorizontalFlip()) trans.append(torchvision.transforms.ToTensor()) transform = torchvision.transforms.Compose(trans) data_train = torchvision.datasets.CIFAR10(root=root, train=True, download=True, transform=transform) data_test = torchvision.datasets.CIFAR10(root=root, train=False, download=True, transform=transform) if sys.platform.startswith('win'): num_workers = 0 # 0表示不用额外的进程来加速读取数据 else: num_workers = 4 train_iter = torch.utils.data.DataLoader(data_train, batch_size=batch_size, shuffle=True, num_workers=num_workers) test_iter = torch.utils.data.DataLoader(data_test, batch_size=batch_size, shuffle=False, num_workers=num_workers) return train_iter, test_iter
pytorch继承好了许多预训练的模型,这些的模型的参数已经十分优秀了,对于
使用热狗数据集进行测试点击下载
import os
data_dir = './data'
os.listdir(os.path.join(data_dir, 'hotdog'))
alexnet.classifier
选择其他预训练的模型基本操作都是相同的,把最后一层的输出改成实际需要的输出
alexnet.classifier = nn.Sequential(
# 第一层全连接层
nn.Linear(9216, 4096),
nn.ReLU(),
nn.Dropout(0.5),
# 第二层全连接层
nn.Linear(4096, 4096),
nn.ReLU(),
nn.Dropout(0.5),
# 第三层全连接层(输出层)
nn.Linear(4096, 10)
)
alexnet.classifier
output_params = list(map(id, alexnet.classifier.parameters()))
features_params = filter(lambda p: id(p) not in output_params, alexnet.parameters())
lr = 0.01
optimizer = optim.Adam([
{'params': features_params},
{'params': alexnet.classifier.parameters(), 'lr': lr * 100}
], lr=lr, weight_decay=0.001)
from torchvision import transforms
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
train_augs = transforms.Compose([
transforms.RandomResizedCrop(size=224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
normalize
])
test_augs = transforms.Compose([
transforms.Resize(size=256),
transforms.CenterCrop(size=224),
transforms.ToTensor(),
normalize
])
from torch.utils.data import Dataset, DataLoader
from torchvision.datasets import ImageFolder
def train_fine_tuning(net, optimizer, batch_size=5, num_epochs=5):
train_iter = DataLoader(ImageFolder(os.path.join(data_dir, 'hotdog/train'), transform=train_augs),
batch_size, shuffle=True)
test_iter = DataLoader(ImageFolder(os.path.join(data_dir, 'hotdog/test'), transform=test_augs),
batch_size)
train(train_iter, test_iter, net, optimizer, device, num_epochs)
train_fine_tuning(alexnet, optimizer)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。