新年伊始,想着pytorch的笔记也该写一个完结篇,以此来纪念前一段时间对pytorch的学习
神经网络的搭建大同小异,一层卷积一层池化一层非线性激活诸如此类。重点还是在于对数据集的把握
一个完整的项目离不开自建数据集这个环节,这就需要对Dataset进行重写
class MyData(Dataset):
def __init__(self, root_dir, mode_dir, label_dir, transform=None): # 初始化类,为class提供全局变量
self.transform = transform
self.root_dir = root_dir # 根文件位置
self.mode_dir = mode_dir # 次级文件
self.label_dir = label_dir # 子文件名
self.path = os.path.join(self.root_dir, self.mode_dir)
self.path = os.path.join(self.path, self.label_dir) # 合并,即具体位置
self.img_path = os.listdir(self.path) # 转换成列表的形式
def __getitem__(self, idx): # 获取列表中每一个图片
img_name = self.img_path[idx] # idx表示下标,即对应位置
img_item_path = os.path.join(self.root_dir, self.mode_dir, self.label_dir, img_name) # 每一个图片的位置
img = Image.open(img_item_path) # 调用方法,拿到该图像
img = img.convert("RGB")
img = self.transform(img)
if self.label_dir == "happy":
label = 1
elif self.label_dir == "sad":
label = 0 # 标签
return img, label # 返回img 图片 label 标签
def __len__(self): # 返回长度
return len(self.img_path)
在重写的时候要注意数据集的层级结构,根据数据集的排列来选择相应的测试集和训练集
下面就是搭建神经网络
这边主要是运用了VGG16来入门
看一下代码
class SJ(nn.Module):
def __init__(self):
super(SJ, self).__init__()
self.layer1 = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2, 0, 1, ceil_mode=False),
nn.Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False),
nn.Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False),
nn.Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2, 0, 1, ceil_mode=False),
nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False),
)
self.layer2 = nn.Sequential(
nn.AdaptiveAvgPool2d(output_size=(7, 7))
)
self.layer3 = nn.Sequential(
nn.Linear(in_features=512 * 7 * 7, out_features=4096, bias=True),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5, inplace=False),
nn.Linear(4096, 4096, bias=True),
nn.ReLU(inplace=True),
nn.Dropout(p=0.5, inplace=False),
nn.Linear(4096, 2, bias=True)
)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = x.view(x.size(0), -1)
x = self.layer3(x)
return x
其中kernel_size stride padding dilation ceil_mode等参数在前面的章节中也已经提及,这里就不多介绍
最后就是训练的过程
建议还是用gpu进行训练,cpu真的超级慢
for i in range(epoch):
running_loss = 0.0
print("第{}轮训练开始".format(i + 1))
# 训练步骤
for data in train_loader:
imgs, labels = data
imgs = imgs.to(device)
labels = labels.to(device)
outputs = sj(imgs)
result_loss = loss_cross(outputs, labels)
optimizer = torch.optim.Adam(sj.parameters(), lr=1e-4) # 优化器 lr为学习速率
optimizer.zero_grad() # 梯度清零
result_loss.backward() # 反向传播
optimizer.step() # 调优
total_train = total_train + 1
if total_train % 10 == 0:
print("----训练次数{}----".format(total_train) + "----Loss:{}----".format(result_loss.item()))
writer.add_scalar('train_loss', result_loss.item(), total_train)
# 测试步骤
total_test_loss = 0
total_accuracy = 0
with torch.no_grad():
step = 0
for data in test_loader:
imgs, labels = data
imgs = imgs.to(device)
labels = labels.to(device)
outputs = sj(imgs)
test_loss = loss_cross(outputs, labels)
total_test_loss = total_test_loss + test_loss
accuracy = (outputs.argmax(1) == labels).sum()
total_accuracy = total_accuracy + accuracy
print("整体测试集上的Loss:{}".format(total_test_loss))
print("整体测试集上的正确率:{}".format(total_accuracy/test_size))
writer.add_scalar('test_loss', total_test_loss, total_test)
writer.add_scalar('test_accuracy', total_accuracy/test_size, total_test)
total_test = total_test + 1
writer.close()
梯度清零,反向传播,优化器优化
这些都是根据自己实际的数据集来选择,最后的结果在tensorboard上也体现出来
最后还有不懂或不太理解的地方欢迎留言私信交流,必回
祝大家新年快乐哦~~