<jupyter_start><jupyter_text>封装好的split工具<jupyter_code>import os
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
from PIL import Image
import random
from torchvision import models

import matplotlib.pyplot as plt
import numpy as np

learning_rate = 1e-4
keep_prob_rate = 0.7  #
max_epoch = 10
BATCH_SIZE = 32

DOWNLOAD_MNIST = False

from torch.autograd import Variable
import torchvision
import torch.nn.functional as F
import numpy as np

def load_dataset(folder_path, ratio=0.7):
    # folder_path 表示数据放的路径
    train_data = []
    test_data = []

    ##随机数种设定，为了每次运行程序，随机数都相同
    random.seed(1)

    ##将类别名统一以数字代替
    label_dict = {label: i for i, label in enumerate(os.listdir(folder_path))}
    print(label_dict)
    ##按radio:1-radio的比例划分出训练集和测试集
    for label in os.listdir(folder_path):
        img_paths = [img_path
                     for img_path in os.listdir(os.path.join(folder_path, label))]

        random.shuffle(img_paths)
        train_data += [(os.path.join(folder_path, label, img), label_dict[label])
                       for img in img_paths[:int(len(img_paths) * ratio)]]
        test_data += [(os.path.join(folder_path, label, img), label_dict[label])
                      for img in img_paths[int(len(img_paths) * ratio):]]

    # transforms.Compose 表示数据预处理
    train_dataset = dataset(
        data=train_data,
        transform=transforms.Compose([transforms.RandomResizedCrop(224),
                                      transforms.RandomHorizontalFlip(),
                                      transforms.ToTensor(),
                                      transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
    )
    test_dataset = dataset(
        data=test_data,
        transform=transforms.Compose([transforms.Resize((224, 224)),  # cannot 224, must (224, 224)
                                      transforms.ToTensor(),
                                      transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
    )

    # get_loader获取数据的迭代器
    # shuffle表示是否打乱顺序
    # drop_last表示是否丢掉batch_size不等于BATCH_SIZE的数据
    # num_workers表示计算核数

    # train_dataloader = train_dataset.get_loader(
    #     batch_size=BATCH_SIZE,
    #     shuffle=True,
    #     drop_last=True,
    #     num_workers=4
    # )

    #   使用for循环获取每次batch_size大小的数据
    # for imgs, labels in train_dataloader:
    #     print(imgs.shape, labels.shape)

    return train_dataset, test_dataset


class dataset(Dataset):
    def __init__(self, data, transform=None):
        super(dataset, self).__init__()
        self.data = data
        self.transform = transform

    def get_loader(self, batch_size=BATCH_SIZE, shuffle=True, drop_last=False, num_workers=0):
        return DataLoader(self,
                          batch_size=batch_size,
                          shuffle=shuffle,
                          num_workers=num_workers,
                          drop_last=drop_last)

    def __len__(self):
        ##数据总长度
        return len(self.data)

    def __getitem__(self, idx):
        # 每次获取数据中的一条，idx表示数据的下标

        img = Image.open(self.data[idx][0]).convert('RGB')
        if self.transform:
            img = self.transform(img)
        label = torch.LongTensor([self.data[idx][1]])
        
        return img, label<jupyter_output><empty_output><jupyter_text>分隔数据集<jupyter_code>import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
import numpy as np
import torch.optim as optim
import os
import json
import time
batch_size = 32
path = 'F:\\ECNU2020_2\\人工智能\\上机作业\\作业6\\CNN图像分类\\CNN图像分类\\animal\\animal'
save_path = 'F:\\ECNU2020_2\\人工智能\\上机作业\\作业6\\CNN图像分类\\CNN图像分类'
train_dataset, test_dataset=load_dataset(path, ratio=0.7)
train_loader = train_dataset.get_loader(batch_size=batch_size,
                                       shuffle = True,
                                       num_workers=0,
                                       drop_last=False)
test_loader = test_dataset.get_loader(batch_size=batch_size,
                                       shuffle = True,
                                       num_workers=0,
                                       drop_last=False)
test_num = len(test_dataset.data)<jupyter_output>{'butterfly': 0, 'cat': 1, 'chicken': 2, 'dog': 3, 'horse': 4}<jupyter_text>定义模型这里做了一个区分，把_2的forward进行更改从而实现输出图像操作 AlexNet(2012)<jupyter_code>class AlexNet(nn.Module):
    def __init__(self,num_classes=1000):
        super(AlexNet,self).__init__()
        self.features = nn.Sequential(
            #3-48
            nn.Conv2d(in_channels=      3,  
                      out_channels=     48,
                      kernel_size=      11,
                      stride=           4,
                      padding=          2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3,stride=2),
            nn.Conv2d(in_channels=      48,  
                      out_channels=     128,
                      kernel_size=      5,
                      padding=          2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3,stride=2),
            nn.Conv2d(in_channels=      128,  
                      out_channels=     192,
                      kernel_size=      3,
                      padding=          1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=      192,  
                      out_channels=     192,
                      kernel_size=      3,
                      padding=          1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=      192,  
                      out_channels=     128,
                      kernel_size=      3,
                      padding=          1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3,stride=2),
        )
        self.classifier = nn.Sequential(
            nn.Dropout(),
            nn.Linear(128*6*6,2048),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(2048,2048),
            nn.ReLU(inplace = True),
            nn.Linear(2048,num_classes)
        )
    def forward(self,x):
        x = self.features(x)
        x = torch.flatten(x,start_dim=1)
        x = self.classifier(x)
        return x
    
class AlexNet_2(nn.Module): #作图返回forward
    def __init__(self,num_classes=1000):
        super(AlexNet_2,self).__init__()
        self.features = nn.Sequential(
            #3-48
            nn.Conv2d(in_channels=      3,  
                      out_channels=     48,
                      kernel_size=      11,
                      stride=           4,
                      padding=          2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3,stride=2),
            nn.Conv2d(in_channels=      48,  
                      out_channels=     128,
                      kernel_size=      5,
                      padding=          2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3,stride=2),
            nn.Conv2d(in_channels=      128,  
                      out_channels=     192,
                      kernel_size=      3,
                      padding=          1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=      192,  
                      out_channels=     192,
                      kernel_size=      3,
                      padding=          1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=      192,  
                      out_channels=     128,
                      kernel_size=      3,
                      padding=          1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=3,stride=2),
        )
        self.classifier = nn.Sequential(
            nn.Dropout(),
            nn.Linear(128*6*6,2048),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(2048,2048),
            nn.ReLU(inplace = True),
            nn.Linear(2048,num_classes)
        )
        
    def forward(self,x):
        outputs=[]
        for name,module in self.features.named_children():
            x = module(x)
            if name in ["0","3","6","10"]:
                outputs.append(x)
        return outputs<jupyter_output><empty_output><jupyter_text>Resnet18<jupyter_code>def make_layer(in_channel, out_channel, block_num, stride=1):
    shortcut = nn.Sequential(
        nn.Conv2d(in_channel, out_channel, 1, stride),
        nn.BatchNorm2d(out_channel))
    layers = list()
    layers.append(ResBlock(in_channel, out_channel, stride, shortcut))

    for i in range(1, block_num):
        layers.append(ResBlock(out_channel, out_channel))
    return nn.Sequential(*layers)

class ResBlock(nn.Module):
    def __init__(self, in_channel, out_channel, stride=1, shortcut=None):
        super(ResBlock, self).__init__()
        self.left = nn.Sequential(
            nn.Conv2d(in_channel, out_channel, 3, stride, 1, bias=False),
            nn.BatchNorm2d(out_channel),
            nn.ReLU(True),
            nn.Conv2d(out_channel, out_channel, 3, 1, 1, bias=False),
            nn.BatchNorm2d(out_channel),
        )
        self.right = shortcut

    def forward(self, x):
        out = self.left(x)
        residual = x if self.right is None else self.right(x)
        out += residual
        return F.relu(out)

class myResNet(nn.Module):
    def __init__(self,num_classes = 1000):
        super(myResNet, self).__init__()
        self.pre = nn.Sequential(
            nn.Conv2d(in_channels=      3,  
                      out_channels=     64,
                      kernel_size=      7,
                      stride=           2,
                      padding=          3,
                      bias=False), 
            nn.BatchNorm2d(64),
            nn.ReLU(True), nn.MaxPool2d(3, 2, 1))
        self.layer1 = make_layer(64, 64, 2)
        self.layer2 = make_layer(64, 128, 2, stride=2)
        self.layer3 = make_layer(128, 256, 2, stride=2)
        self.layer4 = make_layer(256, 512, 2, stride=2)
        self.avg = nn.AvgPool2d(7)
        self.classifier = nn.Sequential(nn.Linear(512, num_classes))

    def forward(self, x):
        x = self.pre(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = self.avg(x)
        x = x.view(x.size(0), -1)
        out = self.classifier(x)
        return out
class myResNet_2(nn.Module):
    def __init__(self,num_classes = 1000):
        super(myResNet_2, self).__init__()
        self.pre = nn.Sequential(
            nn.Conv2d(in_channels=      3,  
                      out_channels=     64,
                      kernel_size=      7,
                      stride=           2,
                      padding=          3,
                      bias=False), 
            nn.BatchNorm2d(64),
            nn.ReLU(True), nn.MaxPool2d(3, 2, 1))
        self.layer1 = make_layer(64, 64, 2)
        self.layer2 = make_layer(64, 128, 2, stride=2)
        self.layer3 = make_layer(128, 256, 2, stride=2)
        self.layer4 = make_layer(256, 512, 2, stride=2)
        self.avg = nn.AvgPool2d(7)
        self.classifier = nn.Sequential(nn.Linear(512, num_classes))

    def forward(self,x):
        outputs=[]
        x = self.pre(x)
        x = self.layer1(x)
        outputs.append(x)
        x = self.layer2(x)
        outputs.append(x)
        x = self.layer3(x)
        outputs.append(x)
        x = self.layer4(x)
        outputs.append(x)
        x = self.avg(x)
        x = x.view(x.size(0), -1)
        out = self.classifier(x)
        return outputs<jupyter_output><empty_output><jupyter_text>训练与验证<jupyter_code>def train(cpu=0,epoch_round=10,prt=1,NET = 'AlexNet',res = 18): #默认使用GPU,默认打印输出,Alexnet,如果是myresnet就是用自己实现的resnet
    if NET == 'ResNet':        
        if res==18:
            net = models.resnet18(pretrained=False,num_classes=5)
        elif res==34:
            net = models.resnet34(pretrained=False,num_classes=5)
        elif res==50:
            net = models.resnet50(pretrained=False,num_classes=5)
        elif res==101:
            net = models.resnet101(pretrained=False,num_classes=5)
        elif res==152:
            net = models.resnet152(pretrained=False,num_classes=5)
        else:
            net = models.resnet18(pretrained=False,num_classes=5)
    elif NET == 'myResNet':
        net = myResNet(num_classes = 5)
        res = ''
    else:
        net = AlexNet(num_classes=5)
        res = ''
    all_t=0
    loss_function = nn.CrossEntropyLoss()
    optimizer = optim.Adam(net.parameters(),lr=0.0002)
    best_acc = 0.0
    ret = []#设立一个参数，是准确率的曲线
    device = torch.device("cuda:0")#if torch.cuda.is_available() else "cpu")
    if cpu == 1:
        device = "cpu"
    for epoch in range(epoch_round):
        net.to(device)
        net.train()
        running_loss = 0.0
        t1 = time.time()
        for step,data in enumerate(train_loader,start = 0):
            images,labels = data
            images = images.to(device)
            labels = labels.to(device)
            labels = labels.squeeze()
            optimizer.zero_grad()
            outputs= net(images)
            loss = loss_function(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss+=loss.item()
            rate = (step+1)/len(train_loader)
            if prt:
                print("\r",int(rate*100),"%          ",running_loss,end="")
        if (epoch_round<=20 or epoch%10 == 0) and prt:
            print()
            if cpu==1:
                print("CPU",end=" ")
            else:
                print("GPU",end=" ")     
            print("Time:",time.time()-t1)
        all_t+=time.time()-t1
        #验证集
        net.eval()
        acc = 0.0
        with torch.no_grad():
            for test_data in test_loader:
                test_images,test_labels = test_data
                test_images = test_images.to(device)
                test_labels = test_labels.to(device)
                test_labels = test_labels.squeeze()
                outputs = net(test_images)
                predict_y = torch.max(outputs,dim=1)[1]
                acc+=(predict_y == test_labels).sum().item()
            test_accurate = acc/test_num
            ret.append(test_accurate)
            if test_accurate>best_acc:
                best_acc = test_accurate
                if NET == 'AlexNet':
                    torch.save(net.state_dict(),save_path+'\\Alexnet.pth')
                if NET == 'myResNet':
                    torch.save(net.state_dict(),save_path+'\\ResNet18.pth')
            if (epoch_round<=20 or epoch%10 == 0) and prt:
                print('[epoch %d] train loss: %.3f test accuracy: %.3f'%
                     (epoch+1,running_loss/step,test_accurate))
    print(NET,res,"=> BEST ACC:",best_acc,"---time: ",all_t,"---FIN.")
    return ret
#round = 25,观察对比myResNet和AlexNet的精度以及运算过程的精度情况
rounds = 25
ret1 = train(0,rounds,1,"myResNet",1)
ret2 = train(0,rounds,1,"AlexNet",1)
plt.figure()
x=[i for i in range(rounds)]
plt.plot(x,ret1,ret2)
#在round = 25，batch_size=32时进行resnet各算法对比并关注层数的关系
rounds = 25
res = [18,34,50,101] #经测试，152过深，显存不足以支持。
for i in res:
    train(0,rounds,0,"ResNet",i)<jupyter_output>ResNet 18 => BEST ACC: 0.6866666666666666 ---time:  110.39004349708557 ---FIN.
ResNet 34 => BEST ACC: 0.6644444444444444 ---time:  150.573233127594 ---FIN.
ResNet 50 => BEST ACC: 0.6288888888888889 ---time:  239.49761319160461 ---FIN.
ResNet 101 => BEST ACC: 0.6 ---time:  379.16691851615906 ---FIN.<jupyter_text>特征输出<jupyter_code>data_transform = transforms.Compose(
    [transforms.Resize((224,224)),
     transforms.ToTensor(),
     transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])

ret = train(0,25,0,'AlexNet',1)
model = AlexNet_2(num_classes=5)
model2 = AlexNet(num_classes=5)
model.load_state_dict(torch.load(save_path+'\\Alexnet.pth'))
model2.load_state_dict(torch.load(save_path+'\\Alexnet.pth'))
print(model)

imgpath = 'F:\\ECNU2020_2\\人工智能\\上机作业\\作业6\\CNN图像分类\\CNN图像分类\\predict_2.jpeg'
img = Image.open(imgpath)
img = data_transform(img)
img = torch.unsqueeze(img,dim = 0)

out_put = model(img)
out_put2 = model2(img)
print(out_put2)
for feature_map in out_put:
    im = np.squeeze(feature_map.detach().numpy())
    im = np.transpose(im,[1,2,0])
    plt.figure()
    for i in range(12):
        ax = plt.subplot(4,3,i+1)
        plt.imshow(im[:,:,i],cmap='gray')
    plt.show()
data_transform = transforms.Compose(
    [transforms.Resize((224,224)),
     transforms.ToTensor(),
     transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))])

#ret = train(0,25,0,'myResNet',1)
model = myResNet_2(num_classes=5)
model2 = myResNet(num_classes=5)
model.load_state_dict(torch.load(save_path+'\\ResNet18.pth'))
model2.load_state_dict(torch.load(save_path+'\\ResNet18.pth'))
print(model)
imgpath = 'F:\\ECNU2020_2\\人工智能\\上机作业\\作业6\\CNN图像分类\\CNN图像分类\\predict_2.jpeg'
img = Image.open(imgpath)
img = data_transform(img)
img = torch.unsqueeze(img,dim = 0)

out_put = model(img)
out_put2 = model2(img)
print(out_put2)
for feature_map in out_put:
    im = np.squeeze(feature_map.detach().numpy())
    im = np.transpose(im,[1,2,0])
    plt.figure()
    for i in range(12):
        ax = plt.subplot(4,3,i+1)
        plt.imshow(im[:,:,i],cmap='gray')
    plt.show()
#batchsize=10
rounds = 10
ret1 = train(0,rounds,1,"AlexNet",1)
#batchsize=25
rounds = 10
ret1 = train(0,rounds,1,"AlexNet",1)
#batchsize=32
rounds = 10
ret1 = train(0,rounds,1,"AlexNet",1)
#batchsize=50
rounds = 10
ret1 = train(0,rounds,1,"AlexNet",1)
#batchsize=32
rounds = 100
ret1 = train(0,rounds,1,"AlexNet",1)
ret2 = train(0,rounds,1,"myResNet",1)
plt.figure()
x=[i for i in range(rounds)]
plt.plot(x,ret1,ret2)<jupyter_output>100 %           51.526464223861694
GPU Time: 2.504297971725464
[epoch 1] train loss: 1.610 test accuracy: 0.351
 100 %           40.299273431301126
GPU Time: 2.4753780364990234
[epoch 11] train loss: 1.259 test accuracy: 0.444
 100 %           37.656023383140564
GPU Time: 2.5342209339141846
[epoch 21] train loss: 1.177 test accuracy: 0.489
 100 %           32.107383668422734
GPU Time: 2.479367733001709
[epoch 31] train loss: 1.003 test accuracy: 0.618
 100 %           27.848536193370824
GPU Time: 2.461416482925415
[epoch 41] train loss: 0.870 test accuracy: 0.636
 100 %           24.622782796621323
GPU Time: 2.4773733615875244
[epoch 51] train loss: 0.769 test accuracy: 0.662
 100 %           18.839892536401756
GPU Time: 2.48036527633667
[epoch 61] train loss: 0.589 test accuracy: 0.693
 100 %           17.993737667798996
GPU Time: 2.4913361072540283
[epoch 71] train loss: 0.562 test accuracy: 0.736
 100 %           15.028421610593796
GPU Time: 2.479367733001709
[epoch 81] train loss:[...]
{'fraction_non_alphanumeric': 0.1218290343210403, 'fraction_numerical': 0.0634193135791942, 'mean_word_length': 1.9509356817109609, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 3, 'word_list_counts': {'cursed_substrings.json': 11, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '536871', 'license': 'MIT', 'n_tokens_mistral': 7175, 'n_tokens_neox': 6518, 'n_words': 1115, 'path': 'Lab6/lab6.ipynb', 'repo_name': 'Busdriver26/Artificial-Intelligence-Lab', 'size': '18764'}