AlexNet网络构建与训练
???????? 2012年AlexNet橫空出世,正式將深度學習推向高潮。如今10年過去,整個深度學習生態已經發展到非常龐大。這里使用pytorch進行AlexNet網絡實現及在圖像分類任務上的訓練過程。
???????? AlexNet是在LeNet基礎上發展而來,模型結構更深。LeNet5由2層卷積層加3層全連接層構成,AlexNet則在此基礎上將卷積層增加到5層,網絡深度達到了8層,并且增加了Dropout,將池化層由平均池化換成最大池化,激活函數改為Relu,整體參數量達到千萬級。
???????? 以圖形分類任務開始講解AlexNet構建,首先需要將一張輸入圖像轉換為[3, 224, 224]的矩陣,一般的彩色圖像為RGB三通道構成,因此模型的輸入通道即為3。
???????? 第一個卷積層輸入通道為3,輸出通道96,卷積核大小為11,步長為4,填充為1,經過第一個卷積層后,特征圖由[3, 224,224]變為[96,54,54]。卷積計算后進行Relu激活函數和最大池化處理,池化層卷積核大小為3,步長為2,特征圖由[96,54,54]變為[96,26,26]。
???????? 第二個卷積層輸入通道96,輸出通道256,卷積核大小為5,填充為2,步長為1,經過第二個卷積層后特征圖寬高不變,僅通道數改變。第二個卷積層后同樣接一個Relu和池化層,經過池化層后特征圖由[256,26,26]變為[256,12,12]。
???????? 第三個卷積層和第四個卷積層沒有接池化層,卷積核大小為3,填充為1,因此經過第三四個卷積層后特征圖尺寸不變,第三個卷積層輸出通道為384,第四個卷積層輸出通道不變。
???????? 第五個卷積層輸入通道384,輸出通道256,卷積核3,填充1,經過池化層后特征圖由[256,12,12]變為[256,5,5]。
???????? 卷積之后通過三個全連接層將輸出通道逐步降維到分類數量。在全連接之前需要將特征圖打平,[256,5,5]打平以后變為6400。全連接層輸入輸出通道可根據任務分類數自行設計,如:[6400, 4096]-->[4096,4096]-->[4096,1000],最后的1000就是ImageNet數據集圖像分類數量。
整體結構:
模型構建:
def AlexNet(input_channel, class_num):model = nn.Sequential(nn.Conv2d(input_channel, 96, kernel_size=11, stride=4, padding=1), # [3,224,224]-->[96,54,54]nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2), # [96,54,54]-->[96,26,26]nn.Conv2d(96, 256, kernel_size=5, padding=2), # [96,26,26]-->[256,26,26]nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2), # [256,26,26]-->[256,12,12]nn.ReLU(),nn.Conv2d(256, 384, kernel_size=3, padding=1), # [256,12,12]-->[384,12,12]nn.ReLU(),nn.Conv2d(384, 384, kernel_size=3, padding=1), # [384,12,12]-->[384,12,12]nn.ReLU(),nn.Conv2d(384, 256, kernel_size=3, padding=1), # [384,12,12]-->[]256,12,12]nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2), # [256,12,12]-->[256,5,5]nn.Flatten(),nn.Linear(6400, 4096),nn.ReLU(),nn.Dropout(),nn.Linear(4096, 4096),nn.ReLU(),nn.Dropout(),nn.Linear(4096, class_num))return model???????? 完成模型構建后,這里使用自定義數據集進行訓練。
def train():# 如有GPU,默認使用第一塊GPUdevice = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')print('using device {}'.format(device))#數據預處理data_transform = {"train": transforms.Compose([transforms.RandomResizedCrop(224), #隨機縮放裁剪transforms.RandomHorizontalFlip(), #隨機水平翻轉transforms.ToTensor(), #轉換為Tensortransforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) #歸一化]),"val": transforms.Compose([transforms.RandomResizedCrop(224),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}#加載數據集batch_size = 32data_path = 'dataset/dogs'assert os.path.exists(data_path), "{} does not exist".format(data_path)train_dataset = datasets.ImageFolder(root=os.path.join(data_path, 'train'), transform=data_transform['train'])val_dataset = datasets.ImageFolder(root=os.path.join(data_path, 'val'), transform=data_transform['val'])train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=8)val_loader = torch.utils.data.DataLoader(val_dataset, batch_size=5, shuffle=False, num_workers=8) model = AlexNet(3, 2)model.to(device)loss_function = nn.CrossEntropyLoss()optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)epochs = 10save_path = 'alexnet.pt'best_acc = 0.0steps = len(train_loader)for epoch in range(epochs):model.train()running_loss = 0.0for step, data in enumerate(train_loader):images, labels = dataoptimizer.zero_grad()outputs = model(images.to(device))loss = loss_function(outputs, labels.to(device))loss.backward()optimizer.step()running_loss += loss.item()print('epoch:{},step:{}/{},loss:{}'.format(epoch + 1, step + 1, steps, loss))model.eval()acc = 0.0with torch.no_grad():for val_data in val_loader:images, labels = val_dataoutputs = model(images.to(device))predict = torch.max(outputs, dim=1)[1]acc += torch.eq(predict, labels.to(device)).sum().item()val_acc = acc / len(val_dataset)print('epoch:{}, acc:{}'.format(epoch + 1, val_acc))if val_acc > best_acc:best_acc = val_acctorch.save(model.state_dict(), save_path)print("finish train")if __name__ == '__main__':train()總結
以上是生活随笔為你收集整理的AlexNet网络构建与训练的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自定义LeNet5,开启你的炼丹之路
- 下一篇: VGG模型构建与实现