IT评测·应用市场-qidao123.com
标题:
动手学深度学习V2每日笔记(深度卷积神经网络AlexNet)
[打印本页]
作者:
温锦文欧普厨电及净水器总代理
时间:
2024-8-6 23:10
标题:
动手学深度学习V2每日笔记(深度卷积神经网络AlexNet)
本文重要参考沐神的视频教程
https://www.bilibili.com/video/BV1h54y1L7oe/spm_id_from=333.788.recommend_more_video.0&vd_source=c7bfc6ce0ea0cbe43aa288ba2713e56d
文档教程 https://zh-v2.d2l.ai/
本文的重要内容对沐神提供的代码中个人不太明白的内容举行笔记记录,内容不会特殊严谨仅供参考。
1.函数目次
2. 深度卷积神经网络AlexNet
AlexNet赢了2012年lmageNet 比赛·
更深更大的 LeNet·
重要改进:
抛弃法
ReLu
MaxPooling
计算机视觉方法论的改变
LeNet利用输出形状AlexNet利用输出形状输入层\1x28x28输入层\3x224x224卷积层kernel=5、padding=2、stride=1、output_channel=66x28x28卷积层kernel=11、stride=4、output_channel=9696x54x54平均池化层kernel=2、padding=0、stride=26x14x14最大池化层kernel=3、stride=296x26x26卷积层kernel=5、padding=0、stride=1、output_channel=1616x10x10卷积层kernel=5、padding=2、output_channel=256256x26x26平均池化层kernel=2、padding=0、stride=216x5x5最大池化层kernel=3、stride=2256x12x12全连接层480->120120卷积层kernel=3、padding=1、output_channel=384384x12x12全连接层120->8484卷积层kernel=3、padding=1、output_channel=384384x12x12全连接层84->1010卷积层kernel=3、padding=1、output_channel=256256x12x12\\\最大池化层kernel=3、stride=2256x5x5\\\全连接层256x5x5->40964096\\\全连接层4096->40964096\\\全连接层4096->10001000
从LeNet(左)到AlexNet(右)
更多细节
激活函数从sigmoid酿成了Relu(减缓梯度消失)
隐藏全连接层后加入了抛弃层
数据增强
3 代码实现
3.1 模型
import torch
from torch import nn
class Reshape(torch.nn.Module):
def forward(self, x):
return x.view(-1, 1, 28, 28)
net = nn.Sequential(
nn.Conv2d(in_channels=1, out_channels=96, kernel_size=11, stride=4, padding=1),nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(in_channels=96, out_channels=256, kernel_size=5, padding=2),nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(in_channels=256, out_channels=384, kernel_size=3, padding=1),nn.ReLU(),
nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, padding=1),nn.ReLU(),
nn.Conv2d(in_channels=384, out_channels=256, kernel_size=3, padding=1),nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Flatten(),
nn.Linear(256*5*5, 4096), nn.ReLU(),nn.Dropout(p=0.5),
nn.Linear(4096, 4096), nn.ReLU(),nn.Dropout(p=0.5),
nn.Linear(4096,10)
)
# X = torch.rand((1,1,224,224), dtype=torch.float32)
# for layer in net:
# X = layer(X)
# print(layer.__class__.__name__, 'output shape:\t',X.shape)
复制代码
3.2 训练
import torch
from torch import nn
import model
import tools
from model import net
from d2l import torch as d2l
import pandas as pd
from tools import *
if __name__ == "__main__":
batch_size = 128
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size, resize=224)
AlexNet = model.net
train_process = train_ch6(AlexNet,train_iter,test_iter,10,0.01,tools.try_gpu())
tools.matplot_acc_loss(train_process)
复制代码
tools文件
import pandas as pd
import torch
import matplotlib.pyplot as plt
from torch import nn
import time
import numpy as np
class Timer: #@save
"""记录多次运行时间"""
def __init__(self):
self.times = []
self.start()
def start(self):
"""启动计时器"""
self.tik = time.time()
def stop(self):
"""停止计时器并将时间记录在列表中"""
self.times.append(time.time() - self.tik)
return self.times[-1]
def avg(self):
"""返回平均时间"""
return sum(self.times) / len(self.times)
def sum(self):
"""返回时间总和"""
return sum(self.times)
def cumsum(self):
"""返回累计时间"""
return np.array(self.times).cumsum().tolist()
argmax = lambda x, *args, **kwargs: x.argmax(*args, **kwargs) #返回最大值的索引下标
astype = lambda x, *args, **kwargs: x.type(*args, **kwargs) # 转换数据类型
reduce_sum = lambda x, *args, **kwargs: x.sum(*args, **kwargs) # 求和
# 对多个变量累加
class Accumulator:
"""For accumulating sums over `n` variables."""
def __init__(self, n):
"""Defined in :numref:`sec_utils`"""
self.data = [0.0] * n
def add(self, *args):
self.data = [a + float(b) for a, b in zip(self.data, args)]
def reset(self):
self.data = [0.0] * len(self.data)
def __getitem__(self, idx):
return self.data[idx]
# 计算正确预测的数量
def accuracy(y_hat, y):
"""Compute the number of correct predictions.
Defined in :numref:`sec_utils`"""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
y_hat = argmax(y_hat, axis=1)
cmp = astype(y_hat, y.dtype) == y
return float(reduce_sum(astype(cmp, y.dtype)))
# 单轮训练
def train_epoch(net, train_iter, loss, trainer):
if isinstance(net, nn.Module):
net.train()
metric_train = Accumulator(3)
for X, y in train_iter:
y_hat = net(X)
l = loss(y_hat, y)
if isinstance(trainer, torch.optim.Optimizer):
trainer.zero_grad()
l.mean().backward()
trainer.step()
else:
l.sum().backward()
trainer(X.shape[0])
metric_train.add(float(l.sum()), accuracy(y_hat, y), y.numel())
#返回训练损失和训练精度
return metric_train[0]/metric_train[2], metric_train[1]/metric_train[2]
# 单轮训练
def train_epoch_gpu(net, train_iter, loss, trainer,device):
if isinstance(net, nn.Module):
net.train()
metric_train = Accumulator(3)
for i, (X, y) in enumerate(train_iter):
X, y = X.to(device), y.to(device)
y_hat = net(X)
l = loss(y_hat, y)
if isinstance(trainer, torch.optim.Optimizer):
trainer.zero_grad()
l.backward()
trainer.step()
else:
l.sum().backward()
trainer(X.shape[0])
metric_train.add(l * X.shape[0], accuracy(y_hat, y), X.shape[0])
#返回训练损失和训练精度
return metric_train[0]/metric_train[2], metric_train[1]/metric_train[2]
# 用于计算验证集上的准确率
def evalution_loss_accuracy(net, data_iter, loss):
if isinstance(net, torch.nn.Module):
net.eval()
meteric = Accumulator(3)
with torch.no_grad():
for X, y in data_iter:
l = loss(net(X), y)
meteric.add(float(l.sum())*X.shape[0], accuracy(net(X), y), X.shape[0])
return meteric[0]/meteric[2], meteric[1]/meteric[2]
# 用于计算验证集上的准确率
def evalution_loss_accuracy_gpu(net, data_iter, loss, device='None'):
if isinstance(net, torch.nn.Module):
net.eval()
if not device:
#将net层的第一个元素拿出来看其在那个设备上
device = next(iter(net.parameters())).device
meteric = Accumulator(3)
with torch.no_grad():
for X, y in data_iter:
if isinstance(X, list):
X = [x.to(device) for x in X]
else:
X = X.to(device) # 赋值给 X,将数据移动到GPU中
y = y.to(device) # 赋值给 y,将数据移动到GPU中
l = loss(net(X), y)
meteric.add(l * X.shape[0], accuracy(net(X), y), X.shape[0])
# meteric.add(float(l.sum()), accuracy(net(X), y), y.numel()) # 转为浮点数
return meteric[0]/meteric[2], meteric[1]/meteric[2]
def matplot_acc_loss(train_process):
# 显示每一次迭代后的训练集和验证集的损失函数和准确率
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(train_process['epoch'], train_process.train_loss_all, "ro-", label="Train loss")
plt.plot(train_process['epoch'], train_process.val_loss_all, "bs-", label="Val loss")
plt.legend()
plt.xlabel("epoch")
plt.ylabel("Loss")
plt.subplot(1, 2, 2)
plt.plot(train_process['epoch'], train_process.train_acc_all, "ro-", label="Train acc")
plt.plot(train_process['epoch'], train_process.val_acc_all, "bs-", label="Val acc")
plt.xlabel("epoch")
plt.ylabel("acc")
plt.legend()
plt.show()
def gpu(i=0):
"""Get a GPU device.
Defined in :numref:`sec_use_gpu`"""
return torch.device(f'cuda:{i}')
def cpu():
"""Get the CPU device.
Defined in :numref:`sec_use_gpu`"""
return torch.device('cpu')
def num_gpus():
"""Get the number of available GPUs.
Defined in :numref:`sec_use_gpu`"""
return torch.cuda.device_count()
def try_gpu(i=0):
"""Return gpu(i) if exists, otherwise return cpu().
Defined in :numref:`sec_use_gpu`"""
if num_gpus() >= i + 1:
return gpu(i)
return cpu()
def train_ch6(net, train_iter, test_iter, num_epochs, lr, device):
"""用GPU训练模型(在第六章定义)"""
#模型参数初始化
def init_weights(m):
if type(m) == nn.Linear or type(m) == nn.Conv2d:
nn.init.xavier_uniform_(m.weight)
net.apply(init_weights)
print("training on", device)
net.to(device)
# 定义优化器
ptimizer = torch.optim.SGD(net.parameters(), lr=lr)
# 定义损失函数
loss = nn.CrossEntropyLoss()
# 训练集损失函数
# 训练集损失列表
train_loss_all = []
train_acc_all = []
# 验证集损失列表
val_loss_all = []
val_acc_all = []
timer = Timer()
timer.start()
for epoch in range(num_epochs):
train_loss, train_acc = train_epoch_gpu(net, train_iter, loss, ptimizer, device)
val_loss, val_acc = evalution_loss_accuracy_gpu(net, test_iter, loss, device)
train_loss_all.append(train_loss)
train_acc_all.append(train_acc)
val_loss_all.append(val_loss)
val_acc_all.append(val_acc)
print("{} train loss:{:.4f} train acc: {:.4f}".format(epoch, train_loss_all[-1], train_acc_all[-1]))
print("{} val loss:{:.4f} val acc: {:.4f}".format(epoch, val_loss_all[-1], val_acc_all[-1]))
print("训练和验证耗费的时间{:.0f}m{:.0f}s".format(timer.stop() // 60, timer.stop() % 60))
train_process = pd.DataFrame(data={"epoch": range(num_epochs),
"train_loss_all": train_loss_all,
"val_loss_all": val_loss_all,
"train_acc_all": train_acc_all,
"val_acc_all": val_acc_all, })
return train_process
复制代码
4 QA
题目1:老师,ImageNet数据集是怎么构建的,如今看是不是要成为历史了?
ImageNet数据集仍然还是一个很重要的数据集。在多数卷积神经网络中还是利用该数据集验证模型性能。
题目2:为什么2000年的时候,神经网络被核方法代替?是因为神经网络运算量太大,数据多,硬件跟不上吗?
重要是核方法有很好理论,同时在2000年的时候深度神经网络计算不动。
题目3:nlp范畴,cnn也代替了人工特征工程吗?如何对待nlp范畴transformer、bert、deepfm这些方法和cv范畴cnn方法的区别?
nlp与cnn在计划思路上是没有区别的。
题目4:alexNet让机器自己寻找特征,这些找到的特征都符合人类的逻辑吗?如果不复合的话,要怎么解释?
AlexNet寻找的特征通常是不符合人类的逻辑。其优化的目标是让机器模型可以更好的分类,再此过程中并没有思量人的因素。因此深度学习神经网络解释性较差。
题目7:从发展视角来看,CNN完爆MLP吗?未来MLP是否有大概由于某些技能成为主流?
CNN就是一个特殊的MLP,MLP可以做更多的结构化计划。Transformer你也可以以为是MLP加一起其他东西的计划。
题目11:我们在一个识别细胞的程序里做了颜色+多少变更的增强后结果反倒比只做多少变革的增强结果差。这个大概是因为什么?
这个征象属于正常征象。数据增强加多变差不是一个很奇怪的事情。
题目13:没太明白为什么leNet不属于深度卷积神经网络?
对于好的研究结果也要学会包装和营销。取一个好的名字很重要。突出自己工作内容的创新。
题目16:作为一个行外汉,感觉如今新的CV范畴模型也越来越少,大家都在搞demo。老师如何对待这件事呢?
这是技能发展的一定过程。这是一个好的征象。大家搞demo可以将技能落地,搞出产物。如今去做CNN的计划比较难。
题目17:网络要求输入的size是固定的,实际利用的时候图片不一定是要求的size,如果强行resize成网络要求的size,会不会最后的结果要差?
当图片过大的时候,通常会将短边压缩到要求的宽度然后再冲里面随机扣除符合要求的图片去做训练大概测试。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/)
Powered by Discuz! X3.4