commit 6d7f5d5c232670a5d6562710198d37d03c4f8321 Author: ClF3 Date: Wed Oct 16 10:08:07 2024 +0800 first commit diff --git a/CIFAR10_playground.py b/CIFAR10_playground.py new file mode 100755 index 0000000..7df1dc8 --- /dev/null +++ b/CIFAR10_playground.py @@ -0,0 +1,296 @@ +import torch +import torchvision +import numpy as np +from tqdm import tqdm +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +import torchvision.transforms as transforms +import matplotlib.pyplot as plt + + +################### 数据集初始化与读入 ################### +train_transform = transforms.Compose([ + transforms.RandomHorizontalFlip(), + transforms.RandomCrop(32, padding=4), + transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2), + transforms.ToTensor() +]) +train_dset = torchvision.datasets.CIFAR10(root='./CIFAR10',train=True,download=False,transform=train_transform) +test_dset = torchvision.datasets.CIFAR10(root='./CIFAR10',train=False,download=False,transform=transforms.ToTensor()) +train_loader = torch.utils.data.DataLoader(train_dset, batch_size=128, shuffle=True, num_workers=0) +test_loader = torch.utils.data.DataLoader(test_dset, batch_size=128, shuffle=False, num_workers=0) +####################################################### + + +################### 构建模型 ################### +class Net(nn.Module): + def __init__(self,act): + super(Net, self).__init__() + # 卷积层 (32x32x3的图像) + self.conv1 = nn.Conv2d(3, 16, 3, padding=1) + # 卷积层(16x16x16) + self.conv2 = nn.Conv2d(16, 32, 3, padding=1) + # 卷积层(8x8x32) + self.conv3 = nn.Conv2d(32, 64, 3, padding=1) + # 最大池化层 + self.pool = nn.MaxPool2d(2, 2) + # linear layer (64 * 4 * 4 -> 500) + self.fc1 = nn.Linear(64 * 4 * 4, 500) + # linear layer (500 -> 10) + self.fc2 = nn.Linear(500, 10) + if act == 'relu': + self.act = F.relu + elif act == 'tanh': + self.act = torch.tanh + elif act == 'sigmoid': + self.act = F.sigmoid + + def forward(self, x): + # add sequence of convolutional and max pooling layers + x = self.pool(self.act(self.conv1(x))) + x = self.pool(self.act(self.conv2(x))) + x = self.pool(self.act(self.conv3(x))) + # flatten image input + x = x.view(-1, 64 * 4 * 4) + + x = self.act(self.fc1(x)) + + x = self.fc2(x) + return x +####################################################### + +################### 模型加入batchnorm ################### +class BnNet(nn.Module): + def __init__(self, act): + super(BnNet, self).__init__() + # 卷积层 (32x32x3的图像) + self.conv1 = nn.Conv2d(3, 16, 3, padding=1) + self.bn1 = nn.BatchNorm2d(16) + + # 卷积层(16x16x16) + self.conv2 = nn.Conv2d(16, 32, 3, padding=1) + self.bn2 = nn.BatchNorm2d(32) + + # 卷积层(8x8x32) + self.conv3 = nn.Conv2d(32, 64, 3, padding=1) + self.bn3 = nn.BatchNorm2d(64) + + # 最大池化层 + self.pool = nn.MaxPool2d(2, 2) + + # linear layer (64 * 4 * 4 -> 500) + self.fc1 = nn.Linear(64 * 4 * 4, 500) + self.bn4 = nn.BatchNorm1d(500) + + # linear layer (500 -> 10) + self.fc2 = nn.Linear(500, 10) + + if act == 'relu': + self.act = F.relu + elif act == 'tanh': + self.act = torch.tanh + elif act == 'sigmoid': + self.act = F.sigmoid + + def forward(self, x): + # add sequence of convolutional and max pooling layers + x = self.pool(self.act(self.bn1(self.conv1(x)))) + x = self.pool(self.act(self.bn2(self.conv2(x)))) + x = self.pool(self.act(self.bn3(self.conv3(x)))) + + # flatten image input + x = x.view(-1, 64 * 4 * 4) + + x = self.act(self.bn4(self.fc1(x))) + x = self.fc2(x) + return x + +################### 构建模型 ################### +class DeepNet(nn.Module): + def __init__(self,act): + super(DeepNet, self).__init__() + ################### 代码填空:请在此填补模型定义代码 ################### + # 卷积层 (32x32x3的图像) + self.conv1 = nn.Conv2d(3, 16, 3, padding=1) + # 卷积层(32x32x16) + self.conv2 = nn.Conv2d(16, 32, 3, padding=1) + # 卷积层(16x16x32) + self.conv3 = nn.Conv2d(32, 64, 3, padding=1) + # 卷积层(16x16x64) + self.conv4 = nn.Conv2d(64, 128, 3, padding=1) + # 卷积层(8x8x128) + self.conv5 = nn.Conv2d(128, 256, 3, padding=1) + # 卷积层(8x8x256) + self.conv6 = nn.Conv2d(256, 512, 3, padding=1) + # 最大池化层 + self.pool = nn.MaxPool2d(2, 2) + # 自适应平均池化层 + self.apool = nn.AdaptiveAvgPool2d((1, 1)) + # linear layer (512 -> 256) + self.fc1 = nn.Linear(512, 256) + # linear layer (256 -> 128) + self.fc2 = nn.Linear(256, 128) + # linear layer (128 -> 10) + self.fc3 = nn.Linear(128, 10) + if act == 'relu': + self.act = F.relu + elif act == 'tanh': + self.act = torch.tanh + elif act == 'sigmoid': + self.act = F.sigmoid + ################################################################## + + def forward(self, x): + # convolutional layers + ################### 代码填空:请在此填补前向计算代码 ################### + x = self.pool(self.act(self.conv2(self.act(self.conv1(x))))) + x = self.pool(self.act(self.conv4(self.act(self.conv3(x))))) + x = self.apool(self.act(self.conv6(self.act(self.conv5(x))))) + + # flatten image input + x = x.view(-1, 512) + + x = self.act(self.fc1(x)) + x = self.act(self.fc2(x)) + + x = self.fc3(x) + return x + ################################################################## + +class BnDeepNet(nn.Module): + def __init__(self,act): + super(BnDeepNet, self).__init__() + ################### 代码填空:请在此填补模型定义代码 ################### + # 卷积层 (32x32x3的图像) + self.conv1 = nn.Conv2d(3, 16, 3, padding=1) + self.bn1 = nn.BatchNorm2d(16) + # 卷积层(32x32x16) + self.conv2 = nn.Conv2d(16, 32, 3, padding=1) + self.bn2 = nn.BatchNorm2d(32) + # 卷积层(16x16x32) + self.conv3 = nn.Conv2d(32, 64, 3, padding=1) + self.bn3 = nn.BatchNorm2d(64) + # 卷积层(16x16x64) + self.conv4 = nn.Conv2d(64, 128, 3, padding=1) + self.bn4 = nn.BatchNorm2d(128) + # 卷积层(8x8x128) + self.conv5 = nn.Conv2d(128, 256, 3, padding=1) + self.bn5 = nn.BatchNorm2d(256) + # 卷积层(8x8x256) + self.conv6 = nn.Conv2d(256, 512, 3, padding=1) + self.bn6 = nn.BatchNorm2d(512) + # 最大池化层 + self.pool = nn.MaxPool2d(2, 2) + # 自适应平均池化层 + self.apool = nn.AdaptiveAvgPool2d((1, 1)) + # linear layer (512 -> 256) + self.fc1 = nn.Linear(512, 256) + self.bn7 = nn.BatchNorm1d(256) + # linear layer (256 -> 128) + self.fc2 = nn.Linear(256, 128) + self.bn8 = nn.BatchNorm1d(128) + # linear layer (128 -> 10) + self.fc3 = nn.Linear(128, 10) + if act == 'relu': + self.act = F.relu + elif act == 'tanh': + self.act = torch.tanh + elif act == 'sigmoid': + self.act = F.sigmoid + ################################################################### + + def forward(self, x): + # convolutional layers + ################### 代码填空:请在此填补前向计算代码 ################### + x = self.pool(self.act(self.bn2(self.conv2(self.act(self.bn1(self.conv1(x))))))) + x = self.pool(self.act(self.bn4(self.conv4(self.act(self.bn3(self.conv3(x))))))) + x = self.apool(self.act(self.bn6(self.conv6(self.act(self.bn5(self.conv5(x))))))) + + # flatten image input + x = x.view(-1, 512) + + x = self.act(self.bn7(self.fc1(x))) + x = self.act(self.bn8(self.fc2(x))) + + x = self.fc3(x) + return x + ################################################################## + +################### 训练前准备 ################### +# model = Net('tanh') +# model = BnNet('relu') +model = DeepNet('tanh') +# model = BnDeepNet('relu') + +device=torch.device("cuda") +model.to(device) +criterion = nn.CrossEntropyLoss() + +optimizer_type = "SGD" +# optimizer_type = "Adam" +if optimizer_type == "SGD": + optimizer = optim.SGD(model.parameters(), lr=0.001) +elif optimizer_type == "Adam": + ########## 代码填空:请在此填补Adam优化器计算代码, lr=0.0001 ########### + optimizer = optim.Adam(model.parameters(), lr = 0.0001) + ################################################################## + +n_epochs = 100 +train_losses = [] +valid_losses = [] +accuracies = [] +################################################ + +################### 训练+验证 ################### +for epoch in range(n_epochs): + train_loss = 0.0 + valid_loss = 0.0 + model.train() + for idx,(img,label) in tqdm(enumerate(train_loader)): + img, label=img.to(device), label.to(device) + optimizer.zero_grad() + output = model(img) + loss = criterion(output,label) + loss.backward() + optimizer.step() + train_loss += loss.item() * img.shape[0] + + model.eval() + correct = 0 + total = 0 + for idx,(img,label) in tqdm(enumerate(test_loader)): + output = model(img) + loss = criterion(output, label) + valid_loss += loss.item() * img.shape[0] + _, predicted = torch.max(output.data, 1) + total += label.size(0) + correct += (predicted == label).sum().item() + + train_loss = train_loss / len(train_dset) + valid_loss = valid_loss / len(test_dset) + + train_losses.append(train_loss) + valid_losses.append(valid_loss) + accuracy = correct / total + accuracies.append(accuracy) + + print(f"Epoch:{epoch}, Acc:{correct/total}, Train Loss:{train_loss}, Test Loss:{valid_loss}") +################################################ + +################### 曲线绘制 ################### +print("MAX ACC: ",np.max(accuracies)) +plt.plot(range(n_epochs), train_losses, label='Train Loss') +plt.plot(range(n_epochs), valid_losses, label='Valid Loss') +plt.xlabel('Epoch') +plt.ylabel('Loss') +plt.legend() +plt.savefig("Loss.png") +plt.clf() +# 绘制验证集准确率随epoch的变化曲线 +plt.plot(range(n_epochs), accuracies, label='Accuracy') +plt.xlabel('Epoch') +plt.ylabel('Accuracy') +plt.legend() +plt.savefig("Acc.png") +################################################