第五节上,图像分类实战,食物分类

随机种子固定随机结果,方便复现

def seed_everything(seed):
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    torch.backends.cudnn.benchmark = False
    torch.backends.cudnn.deterministic = True
    random.seed(seed)
    np.random.seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)

def read_file(self, path):
    if self.mode == "semi":
        file_list = os.listdir(path)
        xi = np.zeros((len(file_list), HW, HW, 3), dtype=np.uint8) #len(file_list)表示图像数量 dtype读成整型 RGB全为整数
        # 列出文件夹下所有文件名字
        for j, img_name in enumerate(file_list):
            img_path = os.path.join(path, img_name) #合并两个路径
            img = Image.open(img_path)
            img = img.resize((HW, HW))
            xi[j, ...] = img
        print("读到了%d个数据" % len(xi))
        return xi
    else:
        for i in tqdm(range(11)):
            file_dir = path + "/%02d" % i
            file_list = os.listdir(file_dir)

            xi = np.zeros((len(file_list), HW, HW, 3), dtype=np.uint8)#读成整型
            yi = np.zeros(len(file_list), dtype=np.uint8)

            # 列出文件夹下所有文件名字
            for j, img_name in enumerate(file_list): #enumerate读下标和下标工具
                img_path = os.path.join(file_dir, img_name)
                img = Image.open(img_path)
                img = img.resize((HW, HW))
                xi[j, ...] = img
                yi[j] = i

            if i == 0:
                X = xi
                Y = yi
            else:
                X = np.concatenate((X, xi), axis=0)#将数组 X 和数组 xi 沿着第 0 个轴(通常代表样本数量这个维度)进行拼接
                Y = np.concatenate((Y, yi), axis=0)
        print("读到了%d个数据" % len(Y))
        return X, Y

tqdm显示循环进度条

train_transform = transforms.Compose(
    [
        transforms.ToPILImage(),   #224, 224, 3模型  :3, 224, 224
        transforms.RandomResizedCrop(224), #随机放大然后裁切
        transforms.RandomRotation(50), #旋转
        transforms.ToTensor() #模型用张量运行
    ]
)
class food_Dataset(Dataset):
    def __init__(self, path, mode="train"):
        self.mode = mode
        if mode == "semi":
            self.X = self.read_file(path)
        else:
            self.X, self.Y = self.read_file(path)
            self.Y = torch.LongTensor(self.Y)  #标签转为长整形

        if mode == "train":#规定train和val不同的transform模式
            self.transform = train_transform
        else:
            self.transform = val_transform

    def __getitem__(self, item):
        if self.mode == "semi":
            return self.transform(self.X[item]), self.X[item]# 进行模型检测和加入数据集
        else:
            return self.transform(self.X[item]), self.Y[item]

    def __len__(self):
        return len(s

lr动态调整
W:权重衰减,让曲线更平滑

模型

class MyModel(nn.Module):                  #自己的模型
    def __init__(self,numclass = 2):
        super(MyModel, self).__init__()
        self.layer0 = nn.Sequential(
            nn.Conv2d(in_channels=3,out_channels=64,kernel_size=3,stride=1,padding=1,bias=True),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2)
        )  #112*112
        self.layer1 = nn.Sequential(
            nn.Conv2d(in_channels=64,out_channels=128,kernel_size=3,stride=1,padding=1,bias=True),
            nn.BatchNorm2d(128),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2)
        )  #56*56
        self.layer2 = nn.Sequential(
            nn.Conv2d(in_channels=128,out_channels=256,kernel_size=3,stride=1,padding=1,bias=True),
            nn.BatchNorm2d(256),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2)
        )  #28*28
        self.layer3 = nn.Sequential(
            nn.Conv2d(in_channels=256,out_channels=512,kernel_size=3,stride=1,padding=1,bias=True),
            nn.BatchNorm2d(512),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2)
        )  #14*14
        self.pool1 = nn.MaxPool2d(2)#7*7
        self.fc = nn.Linear(25088, 512)
        # self.drop = nn.Dropout(0.5)
        self.relu1 = nn.ReLU(inplace=True)
        self.fc2 = nn.Linear(512, numclass)
    def forward(self,x):
        x = self.layer0(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.pool1(x)
        x = x.view(x.size()[0],-1) #view 类似于reshape  这里指定了第一维度为batch大小,第二维度为适应的,即剩多少, 就是多少维。
                                   # 这里就是将特征展平。  展为 B*N  ,N为特征维度。4*512*512 ->4*25088
        x = self.fc(x)
        # x = self.drop(x)
        x = self.relu1(x)
        x = self.fc2(x)
        return x
model_name == "resnet18":
        """ Resnet18
        """
        model_ft = models.resnet18(pretrained=use_pretrained) # 从网络下载模型  pretrain true 使用参数和架构, false 仅使用架构。
        set_parameter_requires_grad(model_ft, linear_prob)  # 是否为线性探测,线性探测: 固定特征提取器不训练。
        num_ftrs = model_ft.fc.in_features  #分类头的输入维度
        model_ft.fc = nn.Linear(num_ftrs, num_classes) # 删掉原来分类头, 更改最后一层为想要的分类数的分类头。
        input_size = 224

posted @ 2025-02-01 09:51  JYP0222  阅读(39)  评论(0)    收藏  举报