3月30日毕设准备
今天取得重要进步,解决了之前训练需要长时间的问题,寻求新方法:迁移学习。从pytroch官网上学习到了许多,并且套用模板。
https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html#finetuning-the-convnet
# Data augmentation and normalization for training
# Just normalization for validation
data_transforms = {
'train': transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
}
data_dir = 'data/hymenoptera_data'
image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x),
data_transforms[x])
for x in ['train', 'val']}
dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4,
shuffle=True, num_workers=4)
for x in ['train', 'val']}
dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}
class_names = image_datasets['train'].classes
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
这里需要把数据结构配置好,才能正确套用模板。
import os
from shutil import copy
import random
def mkfile(file):
if not os.path.exists(file):
os.makedirs(file)
# 获取 flower_photos 文件夹下除 .txt 文件以外所有文件夹名(即5种类名)
file_path = 'flower_data/flower_photos'
flower_class = [cla for cla in os.listdir(file_path) if ".txt" not in cla]
# 创建 训练集train 文件夹,并由5种类名在其目录下创建5个子目录
mkfile('flower_data/train')
for cla in flower_class:
mkfile('flower_data/train/' + cla)
# 创建 验证集val 文件夹,并由5种类名在其目录下创建5个子目录
mkfile('flower_data/val')
for cla in flower_class:
mkfile('flower_data/val/' + cla)
# 划分比例,训练集 : 验证集 = 9 : 1
split_rate = 0.1
# 遍历5种类别的全部图像并按比例分成训练集和验证集
for cla in flower_class:
cla_path = file_path + '/' + cla + '/' # 某一类别的子目录
images = os.listdir(cla_path) # iamges 列表存储了该目录下所有图像的名称
num = len(images)
eval_index = random.sample(images, k=int(num * split_rate)) # 从images列表中随机抽取 k 个图像名称
for index, image in enumerate(images):
# eval_index 中保存验证集val的图像名称
if image in eval_index:
image_path = cla_path + image
new_path = 'flower_data/val/' + cla
copy(image_path, new_path) # 将选中的图像复制到新路径
# 其余的图像保存在训练集train中
else:
image_path = cla_path + image
new_path = 'flower_data/train/' + cla
copy(image_path, new_path)
print("\r[{}] processing [{}/{}]".format(cla, index + 1, num), end="") # processing bar
print()
print("processing done!")
成功分配好训练集和测试集。
这样我开始跑代码
已经实现vgg16,resnet18,densenet169,inception_v3的模型。
其中有的模型没法直接套用pytorch官网上的代码来修改类别,也就算最后输出的类别。
#提取最后一层层中的输入神经元数目
in_features = model.classifier.in_features
#修改类别为5
model.classifier = nn.Linear(in_features, 5)
print(model)
通过print(model)可以查看模型最后一层是什么类型,有的是classifier,这样就需要使用上面的代码。
还学习了怎样定义pytorch一般训练的函数,
def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
since = time.time()
best_model_wts = copy.deepcopy(model.state_dict())
best_acc = 0.0
for epoch in range(num_epochs):
print(f'Epoch {epoch}/{num_epochs - 1}')
print('-' * 10)
# Each epoch has a training and validation phase
for phase in ['train', 'val']:
if phase == 'train':
model.train() # Set model to training mode
else:
model.eval() # Set model to evaluate mode
running_loss = 0.0
running_corrects = 0
# Iterate over data.
for inputs, labels in dataloaders[phase]:
inputs = inputs.to(device)
labels = labels.to(device)
# zero the parameter gradients
optimizer.zero_grad()
# forward
# track history if only in train
with torch.set_grad_enabled(phase == 'train'):
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels)
# backward + optimize only if in training phase
if phase == 'train':
loss.backward()
optimizer.step()
# statistics
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds == labels.data)
if phase == 'train':
scheduler.step()
epoch_loss = running_loss / dataset_sizes[phase]
epoch_acc = running_corrects.double() / dataset_sizes[phase]
print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}')
# deep copy the model
if phase == 'val' and epoch_acc > best_acc:
best_acc = epoch_acc
best_model_wts = copy.deepcopy(model.state_dict())
print()
time_elapsed = time.time() - since
print(f'Training complete in {time_elapsed // 60:.0f}m {time_elapsed % 60:.0f}s')
print(f'Best val Acc: {best_acc:4f}')
# load best model weights
model.load_state_dict(best_model_wts)
return model
这里想用tensorboard进行可视化需要加代码
from torch.utils.tensorboard import SummaryWriter```
writer.add_scalar('training loss',
epoch_loss,
epoch)
命令行输入 tensorboard --logdir=resnet18 启动tensorboard
学习了
model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler,
num_epochs=25)
这个函数的参数,实现模型训练。问题是有些模型电脑运行不出来,GPU容量不够。日后研究下docker用网上主机。
需要解决问题:
1、制作数据集 解决:制作完成训练数据集,掌握方法
2、批量生存对抗样本
3、完善编写实现文件夹名字转换成label的函数
4、对抗训练(耗时可能很长,需要尽快实现) 解决:用迁移学习
5、编写对抗攻击的准确率统计函数。
还剩问题:
1、用网上的主机训练
2、批量生存对抗样本
3、完善编写实现文件夹名字转换成label的函数
4、编写对抗攻击的准确率统计函数。
5、完善数据可视化