深度学习笔记01
从零训练一个神经网络 2023-04-12
1.读取训练数据
# 读取数据
# 这一步类似预处理,将图片裁剪成64*64大小
data_dir = "./data"
# 字典语法 dict = {a:b}
# Scale已经被删除,用Resize代替
data_transform = {x: transforms.Compose([transforms.Resize([64,64]),
transforms.ToTensor()]) for x in ['train', 'valid']}
# 这一步相当于读取数据
# ImageFolder返回的对象是一个包含数据集所有图像及对应标签构成的二维元组容器,支持索引和迭代,可作为torch.utils.data.DataLoader的输入。
image_datasets = {x: datasets.ImageFolder(root=os.path.join(data_dir, x),
transform=data_transform[x]) for x in ['train', 'valid']}
# 读取完数据后,对数据进行装载
dataloader = {x: torch.utils.data.DataLoader(dataset = image_datasets[x],
batch_size=16,
shuffle=True) for x in ['train', 'valid']}
2.搭建模型
# 搭建模型
class MyModel(torch.nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.Conv = torch.nn.Sequential(
torch.nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),
torch.nn.ReLU(),
torch.nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2),
torch.nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),
torch.nn.ReLU(),
torch.nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2)
)
self.Classes = torch.nn.Sequential(
torch.nn.Linear(16*16*256, 512),
torch.nn.ReLU(),
torch.nn.Dropout(p=0.5),
torch.nn.Linear(512,7)
)
def forward(self, inputs):
# 经过卷积层
x = self.Conv(inputs)
# 展平成一维数组
x = x.view(-1, 16 * 16 * 256)
# 经过全连接层
x = self.Classes(x)
return x
# 将模型实例化
model = MyModel()
3.定义超参数
# 定义损失和优化:交叉熵损失(适合多分类)和自适应优化(首选的优化函数)函数
loss_f = torch.nn.CrossEntropyLoss()
# 定义学习率
lr = 0.0005
# 定义优化器
optimizer = torch.optim.Adam(model.parameters(), lr=lr)
# 使用GPU训练
Use_gpu = torch.cuda.is_available()
if Use_gpu:
# 將模型放在cuda上
model = model.cuda()
# 训练轮次
epoch_n = 10
4.训练
# 每执行一个epoch输出一次
for epoch in range(epoch_n):
print("epoch {}/{}".format(epoch+1,epoch_n))
print("-"*10)
# 判断是训练还是测试
for phase in ['train','valid']:
if phase=='train':
print("training...")
model.train(True)
else:
print("validating...")
model.train(False)
# running_loss && running_accuracy
running_loss = 0.0
running_accuracy = 0.0
# 输出标号 和对应图片,下标从1开始
# enumerate
for batch, data in enumerate(dataloader[phase], 1):
X,Y = data
# 将数据放在GPU训练
X, Y = Variable(X).cuda(), Variable(Y).cuda()
# predict
y_pred = model(X)
# pred,概率较大值对应的索引值,可看做预测结果,1表示行
_, pred = torch.max(y_pred.data, 1)
# -------反向传播---------------------------------------------------------------
# 梯度归零
optimizer.zero_grad()
# 计算损失
loss = loss_f(y_pred, Y)
# 训练 需要反向传播及梯度更新
if phase == 'train':
# 反向传播出现问题
loss.backward()
optimizer.step()
# 计算loss值
running_loss += loss.data.item()
# 计算accuracy
running_accuracy += torch.sum(pred == Y.data)
# 训练时,每500个batch输出一次,训练loss和acc
if batch % 500 == 0 and phase == 'train':
print('batch{},trainLoss:{:.4f},trainAcc:{:.4f}'.format(batch, running_loss / batch,
100 * running_accuracy / (4 * batch)))
# 输出每个epoch的loss和acc
epoch_loss = running_loss * 4 / len(image_datasets[phase])
epoch_acc = 100 * running_accuracy / len(image_datasets[phase])
print('{} Loss:{:.4f} Acc:{:.4f}%'.format(phase, epoch_loss, epoch_acc))
5.保存模型
# 保存模型和参数
torch.save(model, 'classificationModel02.pth')
dropout层的用法 2023-04-12
在PyTorch中,我们只需要在全连接层后添加 Dropout 层并指定丢弃概率。在训练模型时, Dropout
层将以指定的丢弃概率随机丢弃上⼀层的输出元素;在测试模型时(即 model.eval()
后), Dropout 层并不发挥作⽤。
如:
net = nn.Sequential(
d2l.FlattenLayer(),
nn.Linear(num_inputs, num_hiddens1),
nn.ReLU(),
nn.Dropout(drop_prob1),
nn.Linear(num_hiddens1, num_hiddens2),
nn.ReLU(),
nn.Dropout(drop_prob2),
nn.Linear(num_hiddens2, 10)
)
model.train() , model.eval() , torch.no_grad() 2023-04-12
model.train()的作用是启用 Batch Normalization 和 Dropout
model.eval()的作用是不启用 Batch Normalization 和 Dropout
而with torch.no_grad()则主要是用于停止autograd模块的工作,以起到加速和节省显存的作用。它的作用是将该with语句包裹起来的部分停止梯度的更新,从而节省了GPU算力和显存,但是并不会影响dropout和BN层的行为。
如果不在意显存大小和计算时间的话,仅仅使用model.eval()已足够得到正确的validation/test的结果;而with torch.no_grad()则是更进一步加速和节省gpu空间(因为不用计算和存储梯度),从而可以更快计算,也可以跑更大的batch来测试。
load model时遇到的一个问题 2023-04-12
load model时必须导入这个Model类,否者无法导入
import 文件时遇到的一个问题 2023-04-12
import一个文件,这个文件里面的代码会被执行
imageFolder下存放数据的格式
- data
- train
- class1
- class2
- ...
- valid
- class1
- class2
...
- test
- class1
- class2
...
pytorch正则化(还不会,待补)
python文件操作 2023-4-13
读取一个文件
with open('data.txt', 'r') as f:
data = f.read()
print('context: {}'.format(data))
拼接路径
os.path.join(path,name)
获取路径下的文件名或者目录名列表
file_name_list = os.listdir(path)
数据增强 2023-4-13
im_aug = transforms.Compose([
# 先设置大小为80
transforms.Resize([80,80]),
# 随记进行翻转
transforms.RandomHorizontalFlip(),
# 随机进行截取
transforms.RandomCrop(64),
# 亮度,对比度,色调随机变化
transforms.ColorJitter(brightness=0.5, contrast=0.5, hue=0.5),
# 转化成tensor
transforms.ToTensor(),
# 归一化使其更快地收敛
transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])
python项目中__init__.py的作用
当一个包被引用的时候,init.py里的代码会最先被执行
GT和IOU是什么
GT:gound truth代表真实值,即人工标注的值
IOU:intersection over union代表GT框和描框的交并比
模型的不同阶段
参考自:https://www.zhihu.com/question/399611596
1.backbone:代表主干网络。这个主干网络大多时候指的是提取特征的网络,其作用就是提取图片中的信息,共后面的网络使用。这些网络经常使用的是resnet VGG等,而不是我们自己设计的网络,因为这些网络已经证明了在分类等问题上的特征提取能力是很强的。在用这些网络作为backbone的时候,都是直接加载官方已经训练好的模型参数,后面接着我们自己的网络。让网络的这两个部分同时进行训练,因为加载的backbone模型已经具有提取特征的能力了,在我们的训练过程中,会对他进行微调,使得其更适合于我们自己的任务。
2.head:head是获取网络输出内容的网络,利用之前提取的特征,head利用这些特征,做出预测。
3.neck:是放在backbone和head之间的,是为了更好的利用backbone提取的特征
4.bottleneck:瓶颈的意思,通常指的是网网络输入的数据维度和输出的维度不同,输出的维度比输入的小了许多,就像脖子一样,变细了。经常设置的参数 bottle_num=256,指的是网络输出的数据的维度是256 ,可是输入进来的可能是1024维度的。
5.GAP:在设计的网络中经常能够看到gap这个层,我之前不知道是干啥的,后了解了,就是Global Average Pool全局平均池化,就是将某个通道的特征取平均值,经常使用AdaptativeAvgpoold(1),在pytorch中,这个代表自适应性全局平均池化,说人话就是将某个通道的特征取平均值
6.Embedding: 深度学习方法都是利用使用线性和非线性转换对复杂的数据进行自动特征抽取,并将特征表示为“向量”(vector),这一过程一般也称为“嵌入”(embedding)
7.用于预训练的任务被称为前置/代理任务(pretext task),用于微调的任务被称为下游任务(downstream task)
8.热身Warm up。Warm up指的是用一个小的学习率先训练几个epoch,这是因为网络的参数是随机初始化的,一开始就采用较大的学习率容易数值不稳定。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人